summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES7974
-rw-r--r--COPYRIGHT30
-rw-r--r--FAQ873
-rw-r--r--FAQ.xml1576
-rw-r--r--Makefile.in61
-rw-r--r--NSEC3-NOTES128
-rw-r--r--README590
-rw-r--r--README.idnkit112
-rw-r--r--README.pkcs1161
-rw-r--r--acconfig.h151
-rw-r--r--aclocal.m42
-rw-r--r--bin/Makefile.in25
-rw-r--r--bin/check/Makefile.in98
-rw-r--r--bin/check/check-tool.c663
-rw-r--r--bin/check/check-tool.h55
-rw-r--r--bin/check/named-checkconf.894
-rw-r--r--bin/check/named-checkconf.c504
-rw-r--r--bin/check/named-checkconf.docbook171
-rw-r--r--bin/check/named-checkconf.html96
-rw-r--r--bin/check/named-checkzone.8278
-rw-r--r--bin/check/named-checkzone.c457
-rw-r--r--bin/check/named-checkzone.docbook455
-rw-r--r--bin/check/named-checkzone.html262
-rw-r--r--bin/check/win32/checktool.dsp113
-rw-r--r--bin/check/win32/checktool.dsw29
-rw-r--r--bin/check/win32/namedcheckconf.dsp107
-rw-r--r--bin/check/win32/namedcheckconf.dsw29
-rw-r--r--bin/check/win32/namedcheckconf.mak404
-rw-r--r--bin/check/win32/namedcheckzone.dsp108
-rw-r--r--bin/check/win32/namedcheckzone.dsw29
-rw-r--r--bin/check/win32/namedcheckzone.mak404
-rw-r--r--bin/dig/Makefile.in101
-rw-r--r--bin/dig/dig.1568
-rw-r--r--bin/dig/dig.c1813
-rw-r--r--bin/dig/dig.docbook952
-rw-r--r--bin/dig/dig.html637
-rw-r--r--bin/dig/dighost.c5420
-rw-r--r--bin/dig/host.1219
-rw-r--r--bin/dig/host.c862
-rw-r--r--bin/dig/host.docbook278
-rw-r--r--bin/dig/host.html212
-rw-r--r--bin/dig/include/dig/dig.h406
-rw-r--r--bin/dig/nslookup.1252
-rw-r--r--bin/dig/nslookup.c891
-rw-r--r--bin/dig/nslookup.docbook496
-rw-r--r--bin/dig/nslookup.html307
-rw-r--r--bin/dig/win32/dig.dsp107
-rw-r--r--bin/dig/win32/dig.dsw29
-rw-r--r--bin/dig/win32/dig.mak425
-rw-r--r--bin/dig/win32/dighost.dsp113
-rw-r--r--bin/dig/win32/dighost.dsw29
-rw-r--r--bin/dig/win32/host.dsp103
-rw-r--r--bin/dig/win32/host.dsw29
-rw-r--r--bin/dig/win32/host.mak425
-rw-r--r--bin/dig/win32/nslookup.dsp107
-rw-r--r--bin/dig/win32/nslookup.dsw29
-rw-r--r--bin/dig/win32/nslookup.mak425
-rw-r--r--bin/dnssec/Makefile.in95
-rw-r--r--bin/dnssec/dnssec-dsfromkey.8124
-rw-r--r--bin/dnssec/dnssec-dsfromkey.c388
-rw-r--r--bin/dnssec/dnssec-dsfromkey.docbook214
-rw-r--r--bin/dnssec/dnssec-dsfromkey.html133
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.8149
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.c327
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.docbook265
-rw-r--r--bin/dnssec/dnssec-keyfromlabel.html171
-rw-r--r--bin/dnssec/dnssec-keygen.8200
-rw-r--r--bin/dnssec/dnssec-keygen.c540
-rw-r--r--bin/dnssec/dnssec-keygen.docbook360
-rw-r--r--bin/dnssec/dnssec-keygen.html232
-rw-r--r--bin/dnssec/dnssec-signzone.8287
-rw-r--r--bin/dnssec/dnssec-signzone.c3031
-rw-r--r--bin/dnssec/dnssec-signzone.docbook512
-rw-r--r--bin/dnssec/dnssec-signzone.html302
-rw-r--r--bin/dnssec/dnssectool.c313
-rw-r--r--bin/dnssec/dnssectool.h76
-rw-r--r--bin/dnssec/win32/dnssectool.dsp113
-rw-r--r--bin/dnssec/win32/dnssectool.dsw29
-rw-r--r--bin/dnssec/win32/keygen.dsp103
-rw-r--r--bin/dnssec/win32/keygen.dsw29
-rw-r--r--bin/dnssec/win32/keygen.mak324
-rw-r--r--bin/dnssec/win32/nsupdate.dsp103
-rw-r--r--bin/dnssec/win32/nsupdate.dsw29
-rw-r--r--bin/dnssec/win32/signzone.dsp103
-rw-r--r--bin/dnssec/win32/signzone.dsw29
-rw-r--r--bin/dnssec/win32/signzone.mak324
-rw-r--r--bin/named/Makefile.in154
-rw-r--r--bin/named/bind9.xsl481
-rw-r--r--bin/named/bind9.xsl.h486
-rw-r--r--bin/named/builtin.c307
-rw-r--r--bin/named/client.c2798
-rw-r--r--bin/named/config.c807
-rw-r--r--bin/named/control.c197
-rw-r--r--bin/named/controlconf.c1459
-rwxr-xr-xbin/named/convertxsl.pl57
-rw-r--r--bin/named/include/named/builtin.h31
-rw-r--r--bin/named/include/named/client.h375
-rw-r--r--bin/named/include/named/config.h79
-rw-r--r--bin/named/include/named/control.h95
-rw-r--r--bin/named/include/named/globals.h139
-rw-r--r--bin/named/include/named/interfacemgr.h176
-rw-r--r--bin/named/include/named/listenlist.h105
-rw-r--r--bin/named/include/named/log.h98
-rw-r--r--bin/named/include/named/logconf.h34
-rw-r--r--bin/named/include/named/lwaddr.h36
-rw-r--r--bin/named/include/named/lwdclient.h234
-rw-r--r--bin/named/include/named/lwresd.h121
-rw-r--r--bin/named/include/named/lwsearch.h112
-rw-r--r--bin/named/include/named/main.h34
-rw-r--r--bin/named/include/named/notify.h55
-rw-r--r--bin/named/include/named/ns_smf_globals.h44
-rw-r--r--bin/named/include/named/query.h87
-rw-r--r--bin/named/include/named/server.h298
-rw-r--r--bin/named/include/named/sortlist.h87
-rw-r--r--bin/named/include/named/statschannel.h61
-rw-r--r--bin/named/include/named/tkeyconf.h53
-rw-r--r--bin/named/include/named/tsigconf.h49
-rw-r--r--bin/named/include/named/types.h46
-rw-r--r--bin/named/include/named/update.h50
-rw-r--r--bin/named/include/named/xfrout.h39
-rw-r--r--bin/named/include/named/zoneconf.h63
-rw-r--r--bin/named/interfacemgr.c974
-rw-r--r--bin/named/listenlist.c138
-rw-r--r--bin/named/log.c235
-rw-r--r--bin/named/logconf.c299
-rw-r--r--bin/named/lwaddr.c94
-rw-r--r--bin/named/lwdclient.c468
-rw-r--r--bin/named/lwderror.c80
-rw-r--r--bin/named/lwdgabn.c657
-rw-r--r--bin/named/lwdgnba.c270
-rw-r--r--bin/named/lwdgrbn.c513
-rw-r--r--bin/named/lwdnoop.c87
-rw-r--r--bin/named/lwresd.8223
-rw-r--r--bin/named/lwresd.c870
-rw-r--r--bin/named/lwresd.docbook373
-rw-r--r--bin/named/lwresd.html225
-rw-r--r--bin/named/lwsearch.c206
-rw-r--r--bin/named/main.c991
-rw-r--r--bin/named/named.8256
-rw-r--r--bin/named/named.conf.5548
-rw-r--r--bin/named/named.conf.docbook629
-rw-r--r--bin/named/named.conf.html585
-rw-r--r--bin/named/named.docbook445
-rw-r--r--bin/named/named.html284
-rw-r--r--bin/named/notify.c174
-rw-r--r--bin/named/query.c5096
-rw-r--r--bin/named/server.c5462
-rw-r--r--bin/named/sortlist.c170
-rw-r--r--bin/named/statschannel.c1257
-rw-r--r--bin/named/tkeyconf.c128
-rw-r--r--bin/named/tsigconf.c181
-rw-r--r--bin/named/unix/Makefile.in36
-rw-r--r--bin/named/unix/include/named/os.h71
-rw-r--r--bin/named/unix/os.c816
-rw-r--r--bin/named/update.c4296
-rw-r--r--bin/named/win32/include/named/ntservice.h35
-rw-r--r--bin/named/win32/include/named/os.h70
-rw-r--r--bin/named/win32/named.dsp327
-rw-r--r--bin/named/win32/named.dsw29
-rw-r--r--bin/named/win32/named.mak1174
-rw-r--r--bin/named/win32/ntservice.c239
-rw-r--r--bin/named/win32/os.c304
-rw-r--r--bin/named/xfrout.c1842
-rw-r--r--bin/named/zoneconf.c1016
-rw-r--r--bin/nsupdate/Makefile.in83
-rw-r--r--bin/nsupdate/nsupdate.1377
-rw-r--r--bin/nsupdate/nsupdate.c2724
-rw-r--r--bin/nsupdate/nsupdate.docbook701
-rw-r--r--bin/nsupdate/nsupdate.html530
-rw-r--r--bin/nsupdate/win32/nsupdate.dsp103
-rw-r--r--bin/nsupdate/win32/nsupdate.dsw29
-rw-r--r--bin/nsupdate/win32/nsupdate.mak373
-rw-r--r--bin/rndc/Makefile.in104
-rw-r--r--bin/rndc/include/rndc/os.h46
-rw-r--r--bin/rndc/rndc-confgen.8211
-rw-r--r--bin/rndc/rndc-confgen.c342
-rw-r--r--bin/rndc/rndc-confgen.docbook286
-rw-r--r--bin/rndc/rndc-confgen.html188
-rw-r--r--bin/rndc/rndc.8148
-rw-r--r--bin/rndc/rndc.c859
-rw-r--r--bin/rndc/rndc.conf47
-rw-r--r--bin/rndc/rndc.conf.5214
-rw-r--r--bin/rndc/rndc.conf.docbook252
-rw-r--r--bin/rndc/rndc.conf.html217
-rw-r--r--bin/rndc/rndc.docbook253
-rw-r--r--bin/rndc/rndc.html165
-rw-r--r--bin/rndc/unix/Makefile.in36
-rw-r--r--bin/rndc/unix/os.c70
-rw-r--r--bin/rndc/util.c57
-rw-r--r--bin/rndc/util.h51
-rw-r--r--bin/rndc/win32/confgen.dsp111
-rw-r--r--bin/rndc/win32/confgen.dsw29
-rw-r--r--bin/rndc/win32/confgen.mak313
-rw-r--r--bin/rndc/win32/os.c65
-rw-r--r--bin/rndc/win32/rndc.dsp107
-rw-r--r--bin/rndc/win32/rndc.dsw29
-rw-r--r--bin/rndc/win32/rndc.mak425
-rw-r--r--bin/rndc/win32/rndcutil.dsp119
-rw-r--r--bin/rndc/win32/rndcutil.dsw29
-rw-r--r--bin/tests/Kchild.example.+003+04017.key1
-rw-r--r--bin/tests/Kchild.example.+003+04017.private7
-rw-r--r--bin/tests/Makefile.in306
-rw-r--r--bin/tests/adb_test.c436
-rw-r--r--bin/tests/b8t.mk63
-rw-r--r--bin/tests/b9t.mk68
-rw-r--r--bin/tests/byaddr_test.c267
-rw-r--r--bin/tests/byname_test.c376
-rw-r--r--bin/tests/cfg_test.c151
-rw-r--r--bin/tests/compress_test.c194
-rw-r--r--bin/tests/db/Makefile.in57
-rw-r--r--bin/tests/db/dns_db_class_1.data11
-rw-r--r--bin/tests/db/dns_db_class_data9
-rw-r--r--bin/tests/db/dns_db_closeversion_1.data11
-rw-r--r--bin/tests/db/dns_db_closeversion_1_data7
-rw-r--r--bin/tests/db/dns_db_closeversion_2.data11
-rw-r--r--bin/tests/db/dns_db_closeversion_2_data7
-rw-r--r--bin/tests/db/dns_db_currentversion.data11
-rw-r--r--bin/tests/db/dns_db_currentversion_data7
-rw-r--r--bin/tests/db/dns_db_expirenode.data11
-rw-r--r--bin/tests/db/dns_db_expirenode_data7
-rw-r--r--bin/tests/db/dns_db_find_1.data12
-rw-r--r--bin/tests/db/dns_db_find_10.data10
-rw-r--r--bin/tests/db/dns_db_find_10_data8
-rw-r--r--bin/tests/db/dns_db_find_1_data7
-rw-r--r--bin/tests/db/dns_db_find_2.data9
-rw-r--r--bin/tests/db/dns_db_find_2_data9
-rw-r--r--bin/tests/db/dns_db_find_3.data10
-rw-r--r--bin/tests/db/dns_db_find_3_data9
-rw-r--r--bin/tests/db/dns_db_find_4.data9
-rw-r--r--bin/tests/db/dns_db_find_4_data7
-rw-r--r--bin/tests/db/dns_db_find_5.data10
-rw-r--r--bin/tests/db/dns_db_find_5_data8
-rw-r--r--bin/tests/db/dns_db_find_6.data10
-rw-r--r--bin/tests/db/dns_db_find_6_data8
-rw-r--r--bin/tests/db/dns_db_find_7.data12
-rw-r--r--bin/tests/db/dns_db_find_7_data7
-rw-r--r--bin/tests/db/dns_db_find_8.data13
-rw-r--r--bin/tests/db/dns_db_find_8_data7
-rw-r--r--bin/tests/db/dns_db_find_9.data13
-rw-r--r--bin/tests/db/dns_db_find_9_data7
-rw-r--r--bin/tests/db/dns_db_findnode_1.data11
-rw-r--r--bin/tests/db/dns_db_findnode_1_data9
-rw-r--r--bin/tests/db/dns_db_findnode_2.data11
-rw-r--r--bin/tests/db/dns_db_findnode_2_data7
-rw-r--r--bin/tests/db/dns_db_iscache_1.data11
-rw-r--r--bin/tests/db/dns_db_iscache_1_data7
-rw-r--r--bin/tests/db/dns_db_iscache_2.data11
-rw-r--r--bin/tests/db/dns_db_iscache_2_data7
-rw-r--r--bin/tests/db/dns_db_iszone_1.data11
-rw-r--r--bin/tests/db/dns_db_iszone_1_data7
-rw-r--r--bin/tests/db/dns_db_iszone_2.data11
-rw-r--r--bin/tests/db/dns_db_iszone_2_data7
-rw-r--r--bin/tests/db/dns_db_load_1.data11
-rw-r--r--bin/tests/db/dns_db_load_25.data6
-rw-r--r--bin/tests/db/dns_db_load_data7
-rw-r--r--bin/tests/db/dns_db_load_soa_not_top7
-rw-r--r--bin/tests/db/dns_db_newversion.data11
-rw-r--r--bin/tests/db/dns_db_newversion_data7
-rw-r--r--bin/tests/db/dns_db_origin_1.data11
-rw-r--r--bin/tests/db/dns_db_origin_data8
-rw-r--r--bin/tests/db/t_db.c3146
-rw-r--r--bin/tests/db_test.c946
-rw-r--r--bin/tests/dst/Kdh.+002+18602.key1
-rw-r--r--bin/tests/dst/Kdh.+002+18602.private6
-rw-r--r--bin/tests/dst/Kdh.+002+48957.key1
-rw-r--r--bin/tests/dst/Kdh.+002+48957.private6
-rw-r--r--bin/tests/dst/Ktest.+001+00002.key1
-rw-r--r--bin/tests/dst/Ktest.+001+54622.key1
-rw-r--r--bin/tests/dst/Ktest.+001+54622.private10
-rw-r--r--bin/tests/dst/Ktest.+003+23616.key1
-rw-r--r--bin/tests/dst/Ktest.+003+23616.private7
-rw-r--r--bin/tests/dst/Ktest.+003+49667.key1
-rw-r--r--bin/tests/dst/Makefile.in65
-rw-r--r--bin/tests/dst/dst_2_data16
-rw-r--r--bin/tests/dst/dst_test.c294
-rwxr-xr-xbin/tests/dst/gsstest.c566
-rw-r--r--bin/tests/dst/t2_data_13077
-rw-r--r--bin/tests/dst/t2_data_23077
-rw-r--r--bin/tests/dst/t2_dsasig3
-rw-r--r--bin/tests/dst/t2_rsasig6
-rw-r--r--bin/tests/dst/t_dst.c933
-rw-r--r--bin/tests/entropy2_test.c175
-rw-r--r--bin/tests/entropy_test.c140
-rw-r--r--bin/tests/fsaccess_test.c60
-rw-r--r--bin/tests/genrandom.c76
-rw-r--r--bin/tests/gxba_test.c98
-rw-r--r--bin/tests/gxbn_test.c86
-rw-r--r--bin/tests/hash_test.c289
-rw-r--r--bin/tests/headerdep_test.sh.in57
-rw-r--r--bin/tests/inter_test.c137
-rw-r--r--bin/tests/journalprint.c86
-rw-r--r--bin/tests/keyboard_test.c75
-rw-r--r--bin/tests/lex_test.c160
-rw-r--r--bin/tests/lfsr_test.c95
-rw-r--r--bin/tests/log_test.c338
-rw-r--r--bin/tests/lwres_test.c304
-rw-r--r--bin/tests/lwresconf_test.c98
-rw-r--r--bin/tests/master/Makefile.in58
-rw-r--r--bin/tests/master/dns_master_load_10_data12
-rw-r--r--bin/tests/master/dns_master_load_11_data12
-rw-r--r--bin/tests/master/dns_master_load_1_data12
-rw-r--r--bin/tests/master/dns_master_load_2_data12
-rw-r--r--bin/tests/master/dns_master_load_3_data12
-rw-r--r--bin/tests/master/dns_master_load_4_data12
-rw-r--r--bin/tests/master/dns_master_load_5_data12
-rw-r--r--bin/tests/master/dns_master_load_6_data12
-rw-r--r--bin/tests/master/dns_master_load_7_data12
-rw-r--r--bin/tests/master/dns_master_load_8_data12
-rw-r--r--bin/tests/master/dns_master_load_9_data12
-rw-r--r--bin/tests/master/master1.data11
-rw-r--r--bin/tests/master/master10.data7
-rw-r--r--bin/tests/master/master11.data6
-rw-r--r--bin/tests/master/master2.data11
-rw-r--r--bin/tests/master/master3.data11
-rw-r--r--bin/tests/master/master4.data11
-rw-r--r--bin/tests/master/master5.data11
-rw-r--r--bin/tests/master/master6.data33
-rw-r--r--bin/tests/master/master7.data17
-rw-r--r--bin/tests/master/master8.data4
-rw-r--r--bin/tests/master/master9.data4
-rw-r--r--bin/tests/master/t_master.c336
-rw-r--r--bin/tests/master_test.c95
-rw-r--r--bin/tests/mem/Makefile.in55
-rw-r--r--bin/tests/mem/t_mem.c208
-rw-r--r--bin/tests/mempool_test.c128
-rw-r--r--bin/tests/name_test.c352
-rw-r--r--bin/tests/named.conf624
-rw-r--r--bin/tests/names/Makefile.in58
-rw-r--r--bin/tests/names/dns_name_compare_data11
-rw-r--r--bin/tests/names/dns_name_countlabels_data10
-rw-r--r--bin/tests/names/dns_name_fromregion_data12
-rw-r--r--bin/tests/names/dns_name_fromtext_data9
-rw-r--r--bin/tests/names/dns_name_fromwire_1_data30
-rw-r--r--bin/tests/names/dns_name_fromwire_2_data30
-rw-r--r--bin/tests/names/dns_name_fromwire_3_data31
-rw-r--r--bin/tests/names/dns_name_fromwire_4_data30
-rw-r--r--bin/tests/names/dns_name_fromwire_5_data30
-rw-r--r--bin/tests/names/dns_name_fromwire_6_data30
-rw-r--r--bin/tests/names/dns_name_fromwire_7_data30
-rw-r--r--bin/tests/names/dns_name_fromwire_8_data30
-rw-r--r--bin/tests/names/dns_name_fullcompare_data10
-rw-r--r--bin/tests/names/dns_name_getlabel_data10
-rw-r--r--bin/tests/names/dns_name_getlabelsequence_data9
-rw-r--r--bin/tests/names/dns_name_hash_data12
-rw-r--r--bin/tests/names/dns_name_isabsolute_data8
-rw-r--r--bin/tests/names/dns_name_issubdomain_data11
-rw-r--r--bin/tests/names/dns_name_rdatacompare_data11
-rw-r--r--bin/tests/names/dns_name_toregion_data8
-rw-r--r--bin/tests/names/dns_name_totext_data9
-rw-r--r--bin/tests/names/dns_name_towire_1_data17
-rw-r--r--bin/tests/names/dns_name_towire_2_data17
-rw-r--r--bin/tests/names/t_names.c2345
-rw-r--r--bin/tests/names/wire_test1.data13
-rw-r--r--bin/tests/names/wire_test2.data13
-rw-r--r--bin/tests/names/wire_test3_1.data11
-rw-r--r--bin/tests/names/wire_test3_2.data12
-rw-r--r--bin/tests/names/wire_test4.data45
-rw-r--r--bin/tests/names/wire_test5.data13
-rw-r--r--bin/tests/names/wire_test6.data13
-rw-r--r--bin/tests/names/wire_test7.data5
-rw-r--r--bin/tests/names/wire_test8.data28
-rw-r--r--bin/tests/ndc.conf36
-rw-r--r--bin/tests/ndc.conf-include25
-rw-r--r--bin/tests/net/Makefile.in53
-rw-r--r--bin/tests/net/driver.c107
-rw-r--r--bin/tests/net/driver.h48
-rw-r--r--bin/tests/net/netaddr_multicast.c112
-rw-r--r--bin/tests/net/sockaddr_multicast.c36
-rw-r--r--bin/tests/net/testsuite.h33
-rw-r--r--bin/tests/nsec3hash.c117
-rw-r--r--bin/tests/nsecify.c216
-rw-r--r--bin/tests/printmsg.c251
-rw-r--r--bin/tests/printmsg.h27
-rw-r--r--bin/tests/ratelimiter_test.c153
-rw-r--r--bin/tests/rbt/Makefile.in58
-rw-r--r--bin/tests/rbt/dns_rbt.data14
-rw-r--r--bin/tests/rbt/dns_rbt_addname_1_data6
-rw-r--r--bin/tests/rbt/dns_rbt_addname_2_data6
-rw-r--r--bin/tests/rbt/dns_rbt_bitstring.data10
-rw-r--r--bin/tests/rbt/dns_rbt_create_1_data7
-rw-r--r--bin/tests/rbt/dns_rbt_deletename_1_data6
-rw-r--r--bin/tests/rbt/dns_rbt_deletename_2_data6
-rw-r--r--bin/tests/rbt/dns_rbt_findname_1_data6
-rw-r--r--bin/tests/rbt/dns_rbt_findname_2_data6
-rw-r--r--bin/tests/rbt/dns_rbt_findname_3_data6
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_first_1.data13
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_first_2.data9
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_first_data7
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_init.data13
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_init_data6
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_last_1.data13
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_last_2.data7
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_last_data7
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_next.data13
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_next_data6
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_prev.data13
-rw-r--r--bin/tests/rbt/dns_rbtnodechain_prev_data6
-rw-r--r--bin/tests/rbt/t_rbt.c1857
-rw-r--r--bin/tests/rbt_test.c457
-rw-r--r--bin/tests/rbt_test.out395
-rw-r--r--bin/tests/rbt_test.txt93
-rw-r--r--bin/tests/rdata_test.c1182
-rw-r--r--bin/tests/resolv.conf.sample38
-rw-r--r--bin/tests/rwlock_test.c142
-rw-r--r--bin/tests/serial_test.c50
-rw-r--r--bin/tests/shutdown_test.c232
-rw-r--r--bin/tests/sig0_test.c305
-rw-r--r--bin/tests/sock_test.c382
-rw-r--r--bin/tests/sockaddr/Makefile.in55
-rw-r--r--bin/tests/sockaddr/t_sockaddr.c137
-rw-r--r--bin/tests/sym_test.c127
-rw-r--r--bin/tests/system/Makefile.in45
-rw-r--r--bin/tests/system/README54
-rw-r--r--bin/tests/system/acl/clean.sh25
-rw-r--r--bin/tests/system/acl/ns2/named1.conf61
-rw-r--r--bin/tests/system/acl/ns2/named2.conf65
-rw-r--r--bin/tests/system/acl/ns2/named3.conf74
-rw-r--r--bin/tests/system/acl/ns2/named4.conf73
-rw-r--r--bin/tests/system/acl/setup.sh21
-rw-r--r--bin/tests/system/acl/tests.sh144
-rw-r--r--bin/tests/system/cacheclean/clean.sh25
-rw-r--r--bin/tests/system/cacheclean/dig.batch924
-rw-r--r--bin/tests/system/cacheclean/knowngood.dig.out953
-rw-r--r--bin/tests/system/cacheclean/ns1/example.db2950
-rw-r--r--bin/tests/system/cacheclean/ns1/named.conf38
-rw-r--r--bin/tests/system/cacheclean/ns2/named.conf38
-rw-r--r--bin/tests/system/cacheclean/tests.sh32
-rw-r--r--bin/tests/system/checkconf/bad.conf52
-rw-r--r--bin/tests/system/checkconf/good.conf56
-rw-r--r--bin/tests/system/checkconf/tests.sh37
-rw-r--r--bin/tests/system/checknames/clean.sh24
-rw-r--r--bin/tests/system/checknames/ns1/fail.example.db.in22
-rw-r--r--bin/tests/system/checknames/ns1/fail.update.db.in21
-rw-r--r--bin/tests/system/checknames/ns1/ignore.example.db.in23
-rw-r--r--bin/tests/system/checknames/ns1/ignore.update.db.in21
-rw-r--r--bin/tests/system/checknames/ns1/named.conf76
-rw-r--r--bin/tests/system/checknames/ns1/root.db35
-rw-r--r--bin/tests/system/checknames/ns1/warn.example.db.in22
-rw-r--r--bin/tests/system/checknames/ns1/warn.update.db.in21
-rw-r--r--bin/tests/system/checknames/ns2/named.conf38
-rw-r--r--bin/tests/system/checknames/ns2/root.hints19
-rw-r--r--bin/tests/system/checknames/ns3/named.conf38
-rw-r--r--bin/tests/system/checknames/ns3/root.hints19
-rw-r--r--bin/tests/system/checknames/setup.sh23
-rw-r--r--bin/tests/system/checknames/tests.sh134
-rw-r--r--bin/tests/system/cleanall.sh38
-rw-r--r--bin/tests/system/common/controls.conf28
-rw-r--r--bin/tests/system/common/rndc.conf27
-rw-r--r--bin/tests/system/common/root.hint20
-rw-r--r--bin/tests/system/conf.sh.in54
-rw-r--r--bin/tests/system/dialup/ns1/example.db25
-rw-r--r--bin/tests/system/dialup/ns1/named.conf45
-rw-r--r--bin/tests/system/dialup/ns1/root.db26
-rw-r--r--bin/tests/system/dialup/ns2/hint.db19
-rw-r--r--bin/tests/system/dialup/ns2/named.conf45
-rw-r--r--bin/tests/system/dialup/ns3/hint.db19
-rw-r--r--bin/tests/system/dialup/ns3/named.conf45
-rw-r--r--bin/tests/system/dialup/setup.sh19
-rw-r--r--bin/tests/system/dialup/tests.sh71
-rw-r--r--bin/tests/system/digcomp.pl111
-rw-r--r--bin/tests/system/dlv/clean.sh28
-rw-r--r--bin/tests/system/dlv/ns1/named.conf35
-rw-r--r--bin/tests/system/dlv/ns1/root.db24
-rw-r--r--bin/tests/system/dlv/ns1/rootservers.utld.db20
-rw-r--r--bin/tests/system/dlv/ns2/hints18
-rw-r--r--bin/tests/system/dlv/ns2/named.conf35
-rw-r--r--bin/tests/system/dlv/ns2/utld.db56
-rw-r--r--bin/tests/system/dlv/ns3/child.db.in22
-rw-r--r--bin/tests/system/dlv/ns3/dlv.db.in20
-rw-r--r--bin/tests/system/dlv/ns3/hints18
-rw-r--r--bin/tests/system/dlv/ns3/named.conf43
-rwxr-xr-xbin/tests/system/dlv/ns3/sign.sh174
-rw-r--r--bin/tests/system/dlv/ns4/child.db41
-rw-r--r--bin/tests/system/dlv/ns4/hints18
-rw-r--r--bin/tests/system/dlv/ns4/named.conf36
-rw-r--r--bin/tests/system/dlv/ns5/hints18
-rw-r--r--bin/tests/system/dlv/ns5/named.conf66
-rw-r--r--bin/tests/system/dlv/ns5/rndc.conf27
-rw-r--r--bin/tests/system/dlv/setup.sh21
-rw-r--r--bin/tests/system/dlv/tests.sh19
-rw-r--r--bin/tests/system/dnssec/README17
-rw-r--r--bin/tests/system/dnssec/clean.sh38
-rw-r--r--bin/tests/system/dnssec/dnssec_update_test.pl105
-rw-r--r--bin/tests/system/dnssec/ns1/named.conf43
-rw-r--r--bin/tests/system/dnssec/ns1/root.db.in32
-rw-r--r--bin/tests/system/dnssec/ns1/sign.sh56
-rw-r--r--bin/tests/system/dnssec/ns2/child.nsec3.example.db25
-rw-r--r--bin/tests/system/dnssec/ns2/child.optout.example.db25
-rw-r--r--bin/tests/system/dnssec/ns2/dlv.db.in26
-rw-r--r--bin/tests/system/dnssec/ns2/dst.example.db.in26
-rw-r--r--bin/tests/system/dnssec/ns2/example.db.in97
-rw-r--r--bin/tests/system/dnssec/ns2/insecure.secure.example.db32
-rw-r--r--bin/tests/system/dnssec/ns2/named.conf83
-rw-r--r--bin/tests/system/dnssec/ns2/private.secure.example.db.in34
-rw-r--r--bin/tests/system/dnssec/ns2/rfc2335.example.db103
-rw-r--r--bin/tests/system/dnssec/ns2/sign.sh68
-rw-r--r--bin/tests/system/dnssec/ns3/bogus.example.db.in32
-rw-r--r--bin/tests/system/dnssec/ns3/dynamic.example.db.in31
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.example.db32
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.nsec3.example.db31
-rw-r--r--bin/tests/system/dnssec/ns3/insecure.optout.example.db31
-rw-r--r--bin/tests/system/dnssec/ns3/keyless.example.db.in29
-rw-r--r--bin/tests/system/dnssec/ns3/multiple.example.db.in34
-rw-r--r--bin/tests/system/dnssec/ns3/named.conf159
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in34
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3.example.db.in43
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/optout-unknown.example.db.in34
-rw-r--r--bin/tests/system/dnssec/ns3/optout.example.db.in45
-rw-r--r--bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/optout.optout.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/secure.example.db.in41
-rw-r--r--bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/secure.optout.example.db.in40
-rw-r--r--bin/tests/system/dnssec/ns3/sign.sh224
-rw-r--r--bin/tests/system/dnssec/ns4/named.conf44
-rw-r--r--bin/tests/system/dnssec/ns5/named.conf43
-rw-r--r--bin/tests/system/dnssec/ns5/trusted.conf.bad22
-rw-r--r--bin/tests/system/dnssec/ns6/named.conf45
-rw-r--r--bin/tests/system/dnssec/ns7/named.conf72
-rw-r--r--bin/tests/system/dnssec/prereq.sh28
-rw-r--r--bin/tests/system/dnssec/setup.sh26
-rw-r--r--bin/tests/system/dnssec/tests.sh834
-rw-r--r--bin/tests/system/forward/clean.sh22
-rw-r--r--bin/tests/system/forward/ns1/example.db12
-rw-r--r--bin/tests/system/forward/ns1/named.conf61
-rw-r--r--bin/tests/system/forward/ns1/root.db36
-rw-r--r--bin/tests/system/forward/ns2/example.db12
-rw-r--r--bin/tests/system/forward/ns2/named.conf56
-rw-r--r--bin/tests/system/forward/ns2/root.db36
-rw-r--r--bin/tests/system/forward/ns3/named.conf56
-rw-r--r--bin/tests/system/forward/ns3/root.db36
-rw-r--r--bin/tests/system/forward/ns4/named.conf52
-rw-r--r--bin/tests/system/forward/ns4/root.db36
-rw-r--r--bin/tests/system/forward/tests.sh92
-rw-r--r--bin/tests/system/genzone.sh267
-rw-r--r--bin/tests/system/glue/clean.sh25
-rw-r--r--bin/tests/system/glue/fi.good27
-rw-r--r--bin/tests/system/glue/noglue.good14
-rw-r--r--bin/tests/system/glue/ns1/cache.in23
-rw-r--r--bin/tests/system/glue/ns1/mil.db31
-rw-r--r--bin/tests/system/glue/ns1/named.conf53
-rw-r--r--bin/tests/system/glue/ns1/net.db40
-rw-r--r--bin/tests/system/glue/ns1/root-servers.nil.db31
-rw-r--r--bin/tests/system/glue/ns1/root.db76
-rw-r--r--bin/tests/system/glue/setup.sh20
-rw-r--r--bin/tests/system/glue/tests.sh46
-rw-r--r--bin/tests/system/glue/xx.good16
-rw-r--r--bin/tests/system/glue/yy.good17
-rwxr-xr-xbin/tests/system/ifconfig.sh189
-rw-r--r--bin/tests/system/ixfr/ans2/ans.pl157
-rw-r--r--bin/tests/system/ixfr/clean.sh21
-rw-r--r--bin/tests/system/ixfr/prereq.sh26
-rw-r--r--bin/tests/system/ixfr/setup.sh43
-rw-r--r--bin/tests/system/ixfr/tests.sh132
-rw-r--r--bin/tests/system/limits/clean.sh24
-rw-r--r--bin/tests/system/limits/knowngood.dig.out.10001023
-rw-r--r--bin/tests/system/limits/knowngood.dig.out.20002023
-rw-r--r--bin/tests/system/limits/knowngood.dig.out.30003023
-rw-r--r--bin/tests/system/limits/knowngood.dig.out.40004023
-rw-r--r--bin/tests/system/limits/knowngood.dig.out.a-maximum-rrset4114
-rw-r--r--bin/tests/system/limits/ns1/example.db19118
-rw-r--r--bin/tests/system/limits/ns1/named.conf42
-rw-r--r--bin/tests/system/limits/ns1/root.db30
-rw-r--r--bin/tests/system/limits/tests.sh60
-rw-r--r--bin/tests/system/lwresd/Makefile.in56
-rw-r--r--bin/tests/system/lwresd/clean.sh22
-rw-r--r--bin/tests/system/lwresd/lwresd1/lwresd.conf34
-rw-r--r--bin/tests/system/lwresd/lwresd1/resolv.conf21
-rw-r--r--bin/tests/system/lwresd/lwtest.c773
-rw-r--r--bin/tests/system/lwresd/ns1/10.10.10.in-addr.arpa.db29
-rw-r--r--bin/tests/system/lwresd/ns1/e.example1.db54
-rw-r--r--bin/tests/system/lwresd/ns1/example1.db35
-rw-r--r--bin/tests/system/lwresd/ns1/example2.db30
-rw-r--r--bin/tests/system/lwresd/ns1/ip6.arpa.db30
-rw-r--r--bin/tests/system/lwresd/ns1/ip6.int.db29
-rw-r--r--bin/tests/system/lwresd/ns1/named.conf69
-rw-r--r--bin/tests/system/lwresd/ns1/root.db33
-rw-r--r--bin/tests/system/lwresd/resolv.conf21
-rw-r--r--bin/tests/system/lwresd/tests.sh46
-rw-r--r--bin/tests/system/masterfile/clean.sh21
-rw-r--r--bin/tests/system/masterfile/knowngood.dig.out33
-rw-r--r--bin/tests/system/masterfile/ns1/include.db41
-rw-r--r--bin/tests/system/masterfile/ns1/named.conf47
-rw-r--r--bin/tests/system/masterfile/ns1/sub.db21
-rw-r--r--bin/tests/system/masterfile/ns1/ttl1.db33
-rw-r--r--bin/tests/system/masterfile/ns1/ttl2.db36
-rw-r--r--bin/tests/system/masterfile/tests.sh37
-rwxr-xr-xbin/tests/system/masterformat/clean.sh23
-rwxr-xr-xbin/tests/system/masterformat/ns1/compile.sh17
-rw-r--r--bin/tests/system/masterformat/ns1/example.db54
-rw-r--r--bin/tests/system/masterformat/ns1/named.conf36
-rw-r--r--bin/tests/system/masterformat/ns2/named.conf35
-rwxr-xr-xbin/tests/system/masterformat/setup.sh20
-rwxr-xr-xbin/tests/system/masterformat/tests.sh80
-rw-r--r--bin/tests/system/notify/clean.sh26
-rw-r--r--bin/tests/system/notify/ns1/named.conf37
-rw-r--r--bin/tests/system/notify/ns1/root.db30
-rw-r--r--bin/tests/system/notify/ns2/example1.db150
-rw-r--r--bin/tests/system/notify/ns2/example2.db150
-rw-r--r--bin/tests/system/notify/ns2/example3.db150
-rw-r--r--bin/tests/system/notify/ns2/example4.db150
-rw-r--r--bin/tests/system/notify/ns2/named.conf43
-rw-r--r--bin/tests/system/notify/ns3/named.conf46
-rw-r--r--bin/tests/system/notify/setup.sh20
-rw-r--r--bin/tests/system/notify/tests.sh92
-rw-r--r--bin/tests/system/nsupdate/clean.sh28
-rw-r--r--bin/tests/system/nsupdate/knowngood.ns1.after99
-rw-r--r--bin/tests/system/nsupdate/knowngood.ns1.afterstop3
-rw-r--r--bin/tests/system/nsupdate/knowngood.ns1.before98
-rw-r--r--bin/tests/system/nsupdate/ns1/example1.db152
-rw-r--r--bin/tests/system/nsupdate/ns1/named.conf58
-rw-r--r--bin/tests/system/nsupdate/ns2/named.conf49
-rw-r--r--bin/tests/system/nsupdate/setup.sh42
-rw-r--r--bin/tests/system/nsupdate/tests.sh161
-rw-r--r--bin/tests/system/nsupdate/update_test.pl426
-rw-r--r--bin/tests/system/resolver/ans2/ans.pl75
-rw-r--r--bin/tests/system/resolver/ans3/ans.pl60
-rw-r--r--bin/tests/system/resolver/clean.sh22
-rw-r--r--bin/tests/system/resolver/ns1/named.conf38
-rw-r--r--bin/tests/system/resolver/ns1/root.hint20
-rw-r--r--bin/tests/system/resolver/prereq.sh26
-rw-r--r--bin/tests/system/resolver/tests.sh39
-rw-r--r--bin/tests/system/rrsetorder/clean.sh23
-rw-r--r--bin/tests/system/rrsetorder/dig.out.fixed.good4
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good14
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good104
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good114
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good124
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good134
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good144
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good154
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good164
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good174
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good184
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good194
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good24
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good204
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good214
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good224
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good234
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good244
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good34
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good44
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good54
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good64
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good74
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good84
-rw-r--r--bin/tests/system/rrsetorder/dig.out.random.good94
-rw-r--r--bin/tests/system/rrsetorder/ns1/named.conf43
-rw-r--r--bin/tests/system/rrsetorder/ns1/root.db40
-rw-r--r--bin/tests/system/rrsetorder/ns2/named.conf45
-rw-r--r--bin/tests/system/rrsetorder/ns3/named.conf45
-rw-r--r--bin/tests/system/rrsetorder/tests.sh332
-rw-r--r--bin/tests/system/run.sh115
-rw-r--r--bin/tests/system/runall.sh46
-rw-r--r--bin/tests/system/send.pl39
-rw-r--r--bin/tests/system/setup.sh40
-rw-r--r--bin/tests/system/sortlist/clean.sh21
-rw-r--r--bin/tests/system/sortlist/ns1/example.db43
-rw-r--r--bin/tests/system/sortlist/ns1/named.conf53
-rw-r--r--bin/tests/system/sortlist/ns1/root.db30
-rw-r--r--bin/tests/system/sortlist/tests.sh60
-rw-r--r--bin/tests/system/start.pl209
-rw-r--r--bin/tests/system/start.sh21
-rw-r--r--bin/tests/system/stop.pl188
-rw-r--r--bin/tests/system/stop.sh22
-rw-r--r--bin/tests/system/stress/clean.sh29
-rw-r--r--bin/tests/system/stress/ns1/named.conf37
-rw-r--r--bin/tests/system/stress/ns2/named.conf39
-rw-r--r--bin/tests/system/stress/ns3/named.conf56
-rw-r--r--bin/tests/system/stress/ns4/named.conf41
-rw-r--r--bin/tests/system/stress/setup.pl91
-rw-r--r--bin/tests/system/stress/setup.sh24
-rw-r--r--bin/tests/system/stress/tests.sh53
-rw-r--r--bin/tests/system/stress/update.pl107
-rw-r--r--bin/tests/system/stub/clean.sh24
-rw-r--r--bin/tests/system/stub/knowngood.dig.out.norec21
-rw-r--r--bin/tests/system/stub/knowngood.dig.out.rec24
-rw-r--r--bin/tests/system/stub/ns1/named.conf37
-rw-r--r--bin/tests/system/stub/ns1/root.db30
-rw-r--r--bin/tests/system/stub/ns2/child.example.db28
-rw-r--r--bin/tests/system/stub/ns2/named.conf42
-rw-r--r--bin/tests/system/stub/ns3/example.db28
-rw-r--r--bin/tests/system/stub/ns3/named.conf49
-rw-r--r--bin/tests/system/stub/tests.sh39
-rw-r--r--bin/tests/system/testsock.pl51
-rw-r--r--bin/tests/system/tkey/Makefile.in60
-rw-r--r--bin/tests/system/tkey/clean.sh22
-rw-r--r--bin/tests/system/tkey/keycreate.c329
-rw-r--r--bin/tests/system/tkey/keydelete.c267
-rw-r--r--bin/tests/system/tkey/ns1/named.conf.in39
-rw-r--r--bin/tests/system/tkey/ns1/setup.sh25
-rw-r--r--bin/tests/system/tkey/prereq.sh28
-rw-r--r--bin/tests/system/tkey/setup.sh24
-rw-r--r--bin/tests/system/tkey/tests.sh83
-rw-r--r--bin/tests/system/tsig/clean.sh24
-rw-r--r--bin/tests/system/tsig/ns1/example.db151
-rw-r--r--bin/tests/system/tsig/ns1/named.conf96
-rw-r--r--bin/tests/system/tsig/tests.sh218
-rw-r--r--bin/tests/system/unknown/clean.sh21
-rw-r--r--bin/tests/system/unknown/ns1/broken1.db29
-rw-r--r--bin/tests/system/unknown/ns1/broken2.db29
-rw-r--r--bin/tests/system/unknown/ns1/broken3.db29
-rw-r--r--bin/tests/system/unknown/ns1/broken4.db29
-rw-r--r--bin/tests/system/unknown/ns1/broken5.db29
-rw-r--r--bin/tests/system/unknown/ns1/class10.hints19
-rw-r--r--bin/tests/system/unknown/ns1/example-class10.db37
-rw-r--r--bin/tests/system/unknown/ns1/example-in.db52
-rw-r--r--bin/tests/system/unknown/ns1/named.conf76
-rw-r--r--bin/tests/system/unknown/tests.sh119
-rw-r--r--bin/tests/system/upforwd/clean.sh26
-rw-r--r--bin/tests/system/upforwd/knowngood.after110
-rw-r--r--bin/tests/system/upforwd/knowngood.after211
-rw-r--r--bin/tests/system/upforwd/knowngood.before8
-rw-r--r--bin/tests/system/upforwd/knowngood.ns2.before6
-rw-r--r--bin/tests/system/upforwd/ns1/example1.db24
-rw-r--r--bin/tests/system/upforwd/ns1/named.conf44
-rw-r--r--bin/tests/system/upforwd/ns2/named.conf39
-rw-r--r--bin/tests/system/upforwd/ns3/named.conf40
-rw-r--r--bin/tests/system/upforwd/setup.sh21
-rw-r--r--bin/tests/system/upforwd/tests.sh103
-rw-r--r--bin/tests/system/v6synth/clean.sh21
-rw-r--r--bin/tests/system/v6synth/ns1/named.conf37
-rw-r--r--bin/tests/system/v6synth/ns1/root.db33
-rw-r--r--bin/tests/system/v6synth/ns2/example.db38
-rw-r--r--bin/tests/system/v6synth/ns2/ip6.arpa.db24
-rw-r--r--bin/tests/system/v6synth/ns2/ip6.int.db24
-rw-r--r--bin/tests/system/v6synth/ns2/named.conf49
-rw-r--r--bin/tests/system/v6synth/ns3/named.conf39
-rw-r--r--bin/tests/system/v6synth/tests.sh71
-rw-r--r--bin/tests/system/views/clean.sh26
-rw-r--r--bin/tests/system/views/ns1/named.conf37
-rw-r--r--bin/tests/system/views/ns1/root.db30
-rw-r--r--bin/tests/system/views/ns2/example1.db34
-rw-r--r--bin/tests/system/views/ns2/example2.db34
-rw-r--r--bin/tests/system/views/ns2/internal.db36
-rw-r--r--bin/tests/system/views/ns2/named1.conf45
-rw-r--r--bin/tests/system/views/ns2/named2.conf65
-rw-r--r--bin/tests/system/views/ns3/internal.db34
-rw-r--r--bin/tests/system/views/ns3/named1.conf55
-rw-r--r--bin/tests/system/views/ns3/named2.conf54
-rw-r--r--bin/tests/system/views/setup.sh23
-rw-r--r--bin/tests/system/views/tests.sh83
-rw-r--r--bin/tests/system/xfer/clean.sh27
-rw-r--r--bin/tests/system/xfer/dig1.good80
-rw-r--r--bin/tests/system/xfer/dig2.good80
-rw-r--r--bin/tests/system/xfer/ns1/named.conf37
-rw-r--r--bin/tests/system/xfer/ns1/root.db33
-rw-r--r--bin/tests/system/xfer/ns2/named.conf61
-rw-r--r--bin/tests/system/xfer/ns3/named.conf71
-rw-r--r--bin/tests/system/xfer/setup.sh21
-rw-r--r--bin/tests/system/xfer/tests.sh102
-rw-r--r--bin/tests/system/xferquota/clean.sh28
-rw-r--r--bin/tests/system/xferquota/ns1/changing1.db33
-rw-r--r--bin/tests/system/xferquota/ns1/changing2.db33
-rw-r--r--bin/tests/system/xferquota/ns1/named.conf44
-rw-r--r--bin/tests/system/xferquota/ns1/root.db35
-rw-r--r--bin/tests/system/xferquota/ns2/example.db152
-rw-r--r--bin/tests/system/xferquota/ns2/named.conf48
-rw-r--r--bin/tests/system/xferquota/setup.pl46
-rw-r--r--bin/tests/system/xferquota/setup.sh26
-rw-r--r--bin/tests/system/xferquota/tests.sh71
-rw-r--r--bin/tests/system/zonechecks/a.db19
-rw-r--r--bin/tests/system/zonechecks/aaaa.db19
-rw-r--r--bin/tests/system/zonechecks/clean.sh20
-rw-r--r--bin/tests/system/zonechecks/cname.db19
-rw-r--r--bin/tests/system/zonechecks/dname.db19
-rw-r--r--bin/tests/system/zonechecks/noaddress.db19
-rw-r--r--bin/tests/system/zonechecks/nxdomain.db19
-rw-r--r--bin/tests/system/zonechecks/tests.sh164
-rw-r--r--bin/tests/t_api.pl223
-rw-r--r--bin/tests/task_test.c191
-rw-r--r--bin/tests/tasks/Makefile.in55
-rw-r--r--bin/tests/tasks/t_tasks.c2293
-rw-r--r--bin/tests/timer_test.c172
-rw-r--r--bin/tests/timers/Makefile.in55
-rw-r--r--bin/tests/timers/t_timers.c1128
-rw-r--r--bin/tests/wire_test.c284
-rw-r--r--bin/tests/wire_test.data9
-rw-r--r--bin/tests/wire_test.data214
-rw-r--r--bin/tests/wire_test.data314
-rw-r--r--bin/tests/wire_test.data431
-rw-r--r--bin/tests/zone_test.c312
-rw-r--r--bin/win32/BINDInstall/AccountInfo.cpp438
-rw-r--r--bin/win32/BINDInstall/AccountInfo.h48
-rw-r--r--bin/win32/BINDInstall/BINDInstall.cpp106
-rw-r--r--bin/win32/BINDInstall/BINDInstall.dsp177
-rw-r--r--bin/win32/BINDInstall/BINDInstall.dsw29
-rw-r--r--bin/win32/BINDInstall/BINDInstall.h64
-rw-r--r--bin/win32/BINDInstall/BINDInstall.mak428
-rw-r--r--bin/win32/BINDInstall/BINDInstall.rc338
-rw-r--r--bin/win32/BINDInstall/BINDInstallDlg.cpp1288
-rw-r--r--bin/win32/BINDInstall/BINDInstallDlg.h127
-rw-r--r--bin/win32/BINDInstall/DirBrowse.cpp103
-rw-r--r--bin/win32/BINDInstall/DirBrowse.h71
-rw-r--r--bin/win32/BINDInstall/StdAfx.cpp8
-rw-r--r--bin/win32/BINDInstall/StdAfx.h30
-rw-r--r--bin/win32/BINDInstall/VersionInfo.cpp286
-rw-r--r--bin/win32/BINDInstall/VersionInfo.h62
-rw-r--r--bin/win32/BINDInstall/res/BINDInstall.icobin0 -> 1078 bytes
-rw-r--r--bin/win32/BINDInstall/res/BINDInstall.rc213
-rw-r--r--bin/win32/BINDInstall/resource.h103
-rw-r--r--config.guess1447
-rw-r--r--config.h.in340
-rw-r--r--config.h.win32236
-rw-r--r--config.sub1555
-rw-r--r--config.threads.in177
-rwxr-xr-xconfigure33235
-rw-r--r--configure.in2990
-rwxr-xr-xcontrib/dbus/GetForwarders31
-rw-r--r--contrib/dbus/INSTALL9
-rw-r--r--contrib/dbus/Makefile.9.3.2b120
-rw-r--r--contrib/dbus/Makefile.9.3.3rc220
-rw-r--r--contrib/dbus/README.DBUS259
-rwxr-xr-xcontrib/dbus/SetForwarders52
-rw-r--r--contrib/dbus/bind-9.3.2b1-dbus.patch713
-rw-r--r--contrib/dbus/bind-9.3.3rc2-dbus.patch778
-rw-r--r--contrib/dbus/dbus_mgr.c2458
-rw-r--r--contrib/dbus/dbus_mgr.h37
-rw-r--r--contrib/dbus/dbus_service.c1161
-rw-r--r--contrib/dbus/dbus_service.h287
-rw-r--r--contrib/dbus/named-dbus-system.conf20
-rw-r--r--contrib/dbus/named-dbus.service3
-rw-r--r--contrib/dlz/bin/dlzbdb/Makefile.in73
-rw-r--r--contrib/dlz/bin/dlzbdb/dlzbdb.c1273
-rw-r--r--contrib/dlz/config.dlz.in478
-rw-r--r--contrib/dlz/drivers/dlz_bdb_driver.c797
-rw-r--r--contrib/dlz/drivers/dlz_bdbhpt_driver.c860
-rw-r--r--contrib/dlz/drivers/dlz_drivers.c157
-rw-r--r--contrib/dlz/drivers/dlz_filesystem_driver.c1048
-rw-r--r--contrib/dlz/drivers/dlz_ldap_driver.c1339
-rw-r--r--contrib/dlz/drivers/dlz_mysql_driver.c1060
-rw-r--r--contrib/dlz/drivers/dlz_odbc_driver.c1568
-rw-r--r--contrib/dlz/drivers/dlz_postgres_driver.c1372
-rw-r--r--contrib/dlz/drivers/dlz_stub_driver.c331
-rw-r--r--contrib/dlz/drivers/include/dlz/dlz_bdb_driver.h45
-rw-r--r--contrib/dlz/drivers/include/dlz/dlz_bdbhpt_driver.h45
-rw-r--r--contrib/dlz/drivers/include/dlz/dlz_drivers.h30
-rw-r--r--contrib/dlz/drivers/include/dlz/dlz_filesystem_driver.h45
-rw-r--r--contrib/dlz/drivers/include/dlz/dlz_ldap_driver.h45
-rw-r--r--contrib/dlz/drivers/include/dlz/dlz_mysql_driver.h45
-rw-r--r--contrib/dlz/drivers/include/dlz/dlz_odbc_driver.h45
-rw-r--r--contrib/dlz/drivers/include/dlz/dlz_postgres_driver.h45
-rw-r--r--contrib/dlz/drivers/include/dlz/dlz_stub_driver.h45
-rw-r--r--contrib/dlz/drivers/include/dlz/sdlz_helper.h117
-rw-r--r--contrib/dlz/drivers/rules.in47
-rw-r--r--contrib/dlz/drivers/sdlz_helper.c531
-rw-r--r--contrib/idn/idnkit-1.0-src/ChangeLog856
-rw-r--r--contrib/idn/idnkit-1.0-src/DISTFILES191
-rw-r--r--contrib/idn/idnkit-1.0-src/INSTALL309
-rw-r--r--contrib/idn/idnkit-1.0-src/INSTALL.ja310
-rw-r--r--contrib/idn/idnkit-1.0-src/LICENSE.txt39
-rw-r--r--contrib/idn/idnkit-1.0-src/Makefile.in79
-rw-r--r--contrib/idn/idnkit-1.0-src/NEWS186
-rw-r--r--contrib/idn/idnkit-1.0-src/README159
-rw-r--r--contrib/idn/idnkit-1.0-src/README.ja151
-rw-r--r--contrib/idn/idnkit-1.0-src/acconfig.h53
-rw-r--r--contrib/idn/idnkit-1.0-src/aclocal.m4472
-rwxr-xr-xcontrib/idn/idnkit-1.0-src/config.guess1317
-rwxr-xr-xcontrib/idn/idnkit-1.0-src/config.sub1411
-rwxr-xr-xcontrib/idn/idnkit-1.0-src/configure3517
-rw-r--r--contrib/idn/idnkit-1.0-src/configure.in711
-rw-r--r--contrib/idn/idnkit-1.0-src/include/Makefile.in65
-rw-r--r--contrib/idn/idnkit-1.0-src/include/config.h.in181
-rw-r--r--contrib/idn/idnkit-1.0-src/include/config.h.win45
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/Makefile.in103
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/aliaslist.h114
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/api.h298
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/assert.h61
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/checker.h171
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/converter.h258
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/debug.h69
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/delimitermap.h123
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/export.h58
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/filechecker.h136
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/filemapper.h137
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/localencoding.h79
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/log.h107
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/logmacro.h72
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/mapper.h159
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/mapselector.h165
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/nameprep.h185
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/normalizer.h155
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/punycode.h70
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/race.h72
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/res.h309
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/resconf.h323
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/result.h86
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/strhash.h123
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/ucs4.h103
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/ucsmap.h131
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/ucsset.h145
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/unicode.h164
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/unormalize.h86
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/utf8.h137
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/util.h98
-rw-r--r--contrib/idn/idnkit-1.0-src/include/idn/version.h70
-rw-r--r--contrib/idn/idnkit-1.0-src/include/mdn/Makefile.in83
-rw-r--r--contrib/idn/idnkit-1.0-src/include/mdn/api.h91
-rw-r--r--contrib/idn/idnkit-1.0-src/include/mdn/localencoding.h49
-rw-r--r--contrib/idn/idnkit-1.0-src/include/mdn/log.h92
-rw-r--r--contrib/idn/idnkit-1.0-src/include/mdn/res.h121
-rw-r--r--contrib/idn/idnkit-1.0-src/include/mdn/resconf.h150
-rw-r--r--contrib/idn/idnkit-1.0-src/include/mdn/result.h97
-rw-r--r--contrib/idn/idnkit-1.0-src/include/mdn/utf8.h70
-rw-r--r--contrib/idn/idnkit-1.0-src/include/mdn/version.h66
-rwxr-xr-xcontrib/idn/idnkit-1.0-src/install-sh250
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/Makefile.in309
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/aliaslist.c355
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/aliaslist.sh35
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/api.c257
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/checker.c446
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/converter.c1244
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/debug.c267
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/delimitermap.c268
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/filechecker.c261
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/filemapper.c347
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/idn.conf.sample.in61
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/localencoding.c123
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/log.c215
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/make.wnt279
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/mapper.c482
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/mapselector.c375
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/nameprep.c357
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/nameprep_template.c137
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/nameprepdata.c2546
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/normalizer.c439
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/punycode.c434
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/race.c427
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/res.c1726
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/resconf.c1477
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/result.c76
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/strhash.c283
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/Makefile.in304
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/api-init1.tsy113
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/api-init2.tsy113
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/api-init3.tsy117
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/api-init4-1.tsy96
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/api-init4-2.tsy96
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/api-init4-3.tsy102
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/api-init5-1.tsy102
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/api-init5-2.tsy102
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/api-init5-3.tsy109
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/api.tsy1009
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/checker.tsy610
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/codeset.h71
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/converter.tsy822
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/delimitermap.tsy257
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/iconvchk.c132
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/mapper.tsy497
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/mapselector.tsy592
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/nameprep.tsy340
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/normalizer.tsy346
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/res.tsy1026
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/resconf.tsy1026
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/setenv.c134
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/setenv.h61
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/testsuite.c578
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/testsuite.h276
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/testutil.c83
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/testutil.h71
-rwxr-xr-xcontrib/idn/idnkit-1.0-src/lib/tests/testygen557
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/tests/ucs4.tsy257
-rwxr-xr-xcontrib/idn/idnkit-1.0-src/lib/tests/utffilter82
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/ucs4.c461
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/ucsmap.c380
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/ucsset.c368
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/unicode.c309
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/unicode_template.c101
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/unicodedata_320.c7916
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/unormalize.c413
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/utf8.c276
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/util.c162
-rw-r--r--contrib/idn/idnkit-1.0-src/lib/version.c54
-rwxr-xr-xcontrib/idn/idnkit-1.0-src/ltconfig3114
-rw-r--r--contrib/idn/idnkit-1.0-src/ltmain.sh4024
-rw-r--r--contrib/idn/idnkit-1.0-src/make.wnt76
-rw-r--r--contrib/idn/idnkit-1.0-src/man/Makefile.in116
-rw-r--r--contrib/idn/idnkit-1.0-src/man/idn.conf.5.in312
-rw-r--r--contrib/idn/idnkit-1.0-src/man/libidnkit.3.in480
-rw-r--r--contrib/idn/idnkit-1.0-src/map/Makefile.in75
-rw-r--r--contrib/idn/idnkit-1.0-src/map/jp.map50
-rwxr-xr-xcontrib/idn/idnkit-1.0-src/mkinstalldirs40
-rw-r--r--contrib/idn/idnkit-1.0-src/patch/bind9/bind-9.2.1-patch5900
-rw-r--r--contrib/idn/idnkit-1.0-src/patch/bind9/bind-9.2.2-patch1169
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/Makefile.in65
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/idnconv/Makefile.in116
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/idnconv/idnconv.1373
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/idnconv/idnconv.c803
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/idnconv/idnslookup.in116
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/idnconv/make.wnt72
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/idnconv/selectiveencode.c127
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/idnconv/selectiveencode.h70
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/idnconv/util.c554
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/idnconv/util.h96
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/make.wnt57
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/rpm/idnkit.spec142
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/runidn/Makefile.in167
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/runidn/resolver.c1056
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/runidn/resolver.h70
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/runidn/runidn.1151
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/runidn/runidn.in109
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/runidn/stub.c387
-rw-r--r--contrib/idn/idnkit-1.0-src/tools/runidn/stub.h94
-rw-r--r--contrib/idn/idnkit-1.0-src/util/Makefile43
-rw-r--r--contrib/idn/idnkit-1.0-src/util/SparseMap.pm575
-rw-r--r--contrib/idn/idnkit-1.0-src/util/UCD.pm194
-rwxr-xr-xcontrib/idn/idnkit-1.0-src/util/generate_nameprep_data.pl405
-rwxr-xr-xcontrib/idn/idnkit-1.0-src/util/generate_normalize_data.pl586
-rw-r--r--contrib/idn/idnkit-1.0-src/win/README.WIN17
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/README.txt665
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/README_j.txt717
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/common/checkdll.c242
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/common/convert.c180
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/common/dump.c118
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/common/encoding.c271
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/common/hook.c224
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/common/make.wnt102
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/common/printf.c138
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/common/wrapcommon.h109
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/config/idnconf.tcl1123
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/config/make.wnt58
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/make.wnt97
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock11/dlldef.h86
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock11/dllfunc.c212
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock11/dllload.c63
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock11/dllmain.c96
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock11/dllstub.c1541
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock11/make.wnt98
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock11/wsock32.def87
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock20/dlldef.h123
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock20/dllfunc.c592
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock20/dllload.c62
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock20/dllmain.c94
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock20/dllstub.c2168
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock20/make.wnt97
-rw-r--r--contrib/idn/idnkit-1.0-src/wsock/wsock20/ws2_32.def120
-rw-r--r--contrib/linux/coredump-patch12
-rw-r--r--contrib/named-bootconf/named-bootconf.sh314
-rw-r--r--contrib/nanny/nanny.pl55
-rw-r--r--contrib/nslint-2.1a3/CHANGES191
-rw-r--r--contrib/nslint-2.1a3/FILES24
-rw-r--r--contrib/nslint-2.1a3/INSTALL42
-rw-r--r--contrib/nslint-2.1a3/Makefile.in122
-rw-r--r--contrib/nslint-2.1a3/README14
-rw-r--r--contrib/nslint-2.1a3/VERSION1
-rw-r--r--contrib/nslint-2.1a3/aclocal.m4765
-rw-r--r--contrib/nslint-2.1a3/config.guess693
-rw-r--r--contrib/nslint-2.1a3/config.sub927
-rw-r--r--contrib/nslint-2.1a3/configure1905
-rw-r--r--contrib/nslint-2.1a3/configure.in47
-rw-r--r--contrib/nslint-2.1a3/install-sh250
-rw-r--r--contrib/nslint-2.1a3/lbl/gnuc.h43
-rw-r--r--contrib/nslint-2.1a3/lbl/os-irix5.h38
-rw-r--r--contrib/nslint-2.1a3/lbl/os-osf3.h32
-rw-r--r--contrib/nslint-2.1a3/lbl/os-solaris2.h50
-rw-r--r--contrib/nslint-2.1a3/lbl/os-sunos4.h215
-rw-r--r--contrib/nslint-2.1a3/lbl/os-ultrix4.h39
-rw-r--r--contrib/nslint-2.1a3/mkdep109
-rw-r--r--contrib/nslint-2.1a3/nslint.8451
-rw-r--r--contrib/nslint-2.1a3/nslint.c2382
-rw-r--r--contrib/nslint-2.1a3/savestr.c67
-rw-r--r--contrib/nslint-2.1a3/savestr.h24
-rw-r--r--contrib/nslint-2.1a3/strerror.c75
-rw-r--r--contrib/pkcs11-keygen/PEM_write_pubkey.c124
-rw-r--r--contrib/pkcs11-keygen/README18
-rw-r--r--contrib/pkcs11-keygen/destroyobj.c183
-rw-r--r--contrib/pkcs11-keygen/genkey.c206
-rwxr-xr-xcontrib/pkcs11-keygen/genkey.sh55
-rwxr-xr-xcontrib/pkcs11-keygen/keyconv.pl61
-rwxr-xr-xcontrib/pkcs11-keygen/keydump.pl26
-rw-r--r--contrib/pkcs11-keygen/listobjs.c197
-rw-r--r--contrib/pkcs11-keygen/openssl-0.9.8g-patch8715
-rw-r--r--contrib/pkcs11-keygen/readkey.c230
-rw-r--r--contrib/pkcs11-keygen/set_key_id.c159
-rw-r--r--contrib/pkcs11-keygen/writekey.c360
-rwxr-xr-xcontrib/pkcs11-keygen/writekey.sh73
-rw-r--r--contrib/query-loc-0.4.0/ADDRESSES16
-rw-r--r--contrib/query-loc-0.4.0/ALGO48
-rw-r--r--contrib/query-loc-0.4.0/INSTALL9
-rw-r--r--contrib/query-loc-0.4.0/Makefile.in42
-rw-r--r--contrib/query-loc-0.4.0/README21
-rw-r--r--contrib/query-loc-0.4.0/USAGE7
-rw-r--r--contrib/query-loc-0.4.0/config.h.in69
-rwxr-xr-xcontrib/query-loc-0.4.0/configure6436
-rw-r--r--contrib/query-loc-0.4.0/configure.in65
-rwxr-xr-xcontrib/query-loc-0.4.0/install-sh323
-rw-r--r--contrib/query-loc-0.4.0/loc.c590
-rw-r--r--contrib/query-loc-0.4.0/loc.h78
-rw-r--r--contrib/query-loc-0.4.0/loc_ntoa.c248
-rw-r--r--contrib/query-loc-0.4.0/query-loc.155
-rw-r--r--contrib/query-loc-0.4.0/query-loc.c98
-rwxr-xr-xcontrib/query-loc-0.4.0/reconf8
-rw-r--r--contrib/queryperf/Makefile.in28
-rw-r--r--contrib/queryperf/README82
-rw-r--r--contrib/queryperf/config.h.in37
-rwxr-xr-xcontrib/queryperf/configure4365
-rw-r--r--contrib/queryperf/configure.in70
-rw-r--r--contrib/queryperf/input/sample.06
-rw-r--r--contrib/queryperf/input/sample.113
-rw-r--r--contrib/queryperf/missing/addrinfo.h100
-rw-r--r--contrib/queryperf/missing/getaddrinfo.c632
-rw-r--r--contrib/queryperf/missing/getnameinfo.c226
-rw-r--r--contrib/queryperf/queryperf.c2113
-rw-r--r--contrib/queryperf/utils/gen-data-queryperf.py113
-rw-r--r--contrib/sdb/bdb/README37
-rw-r--r--contrib/sdb/bdb/bdb.c235
-rw-r--r--contrib/sdb/bdb/bdb.h31
-rw-r--r--contrib/sdb/bdb/zone2bdb.c187
-rw-r--r--contrib/sdb/dir/dirdb.c195
-rw-r--r--contrib/sdb/dir/dirdb.h25
-rw-r--r--contrib/sdb/ldap/INSTALL.ldap83
-rw-r--r--contrib/sdb/ldap/README.ldap48
-rw-r--r--contrib/sdb/ldap/README.zone2ldap17
-rw-r--r--contrib/sdb/ldap/ldapdb.c667
-rw-r--r--contrib/sdb/ldap/ldapdb.h6
-rw-r--r--contrib/sdb/ldap/zone2ldap.164
-rw-r--r--contrib/sdb/ldap/zone2ldap.c734
-rw-r--r--contrib/sdb/pgsql/pgsqldb.c348
-rw-r--r--contrib/sdb/pgsql/pgsqldb.h25
-rw-r--r--contrib/sdb/pgsql/zonetodb.c292
-rw-r--r--contrib/sdb/sqlite/README.sdb_sqlite67
-rw-r--r--contrib/sdb/sqlite/sqlitedb.c324
-rw-r--r--contrib/sdb/sqlite/sqlitedb.h25
-rw-r--r--contrib/sdb/sqlite/zone2sqlite.c301
-rw-r--r--contrib/sdb/tcl/lookup.tcl51
-rw-r--r--contrib/sdb/tcl/tcldb.c232
-rw-r--r--contrib/sdb/tcl/tcldb.h25
-rw-r--r--contrib/sdb/time/timedb.c143
-rw-r--r--contrib/sdb/time/timedb.h25
-rw-r--r--contrib/zkt/CHANGELOG446
-rw-r--r--contrib/zkt/LICENSE30
-rw-r--r--contrib/zkt/Makefile.in151
-rw-r--r--contrib/zkt/README44
-rw-r--r--contrib/zkt/README.logging99
-rw-r--r--contrib/zkt/TODO37
-rw-r--r--contrib/zkt/config.h.in217
-rw-r--r--contrib/zkt/config_zkt.h121
-rwxr-xr-xcontrib/zkt/configure6838
-rw-r--r--contrib/zkt/debug.h66
-rw-r--r--contrib/zkt/dki.c1185
-rw-r--r--contrib/zkt/dki.h185
-rw-r--r--contrib/zkt/dnssec-signer.8436
-rw-r--r--contrib/zkt/dnssec-signer.c1002
-rw-r--r--contrib/zkt/dnssec-zkt.8481
-rw-r--r--contrib/zkt/dnssec-zkt.c823
-rw-r--r--contrib/zkt/domaincmp.c190
-rw-r--r--contrib/zkt/domaincmp.h40
-rw-r--r--contrib/zkt/examples/dnskey.db24
-rwxr-xr-xcontrib/zkt/examples/dnssec-signer.sh12
-rwxr-xr-xcontrib/zkt/examples/dnssec-zkt.sh12
-rwxr-xr-xcontrib/zkt/examples/flat/dist.sh70
-rw-r--r--contrib/zkt/examples/flat/dnssec.conf41
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+003+42138.key3
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+003+42138.private7
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+005+01355.key3
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+005+01355.private10
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./dnskey.db29
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./dnssec.conf5
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./dsset-dyn.example.net.2
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./keyset-dyn.example.net.18
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./zone.db136
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./zone.db.dsigned136
-rw-r--r--contrib/zkt/examples/flat/dyn.example.net./zone.org30
-rw-r--r--contrib/zkt/examples/flat/example.net./Kexample.net.+005+01764.key3
-rw-r--r--contrib/zkt/examples/flat/example.net./Kexample.net.+005+01764.published10
-rw-r--r--contrib/zkt/examples/flat/example.net./Kexample.net.+005+41151.key3
-rw-r--r--contrib/zkt/examples/flat/example.net./Kexample.net.+005+41151.private10
-rw-r--r--contrib/zkt/examples/flat/example.net./Kexample.net.+005+41300.key3
-rw-r--r--contrib/zkt/examples/flat/example.net./Kexample.net.+005+41300.private10
-rw-r--r--contrib/zkt/examples/flat/example.net./dnskey.db33
-rw-r--r--contrib/zkt/examples/flat/example.net./dsset-example.net.4
-rw-r--r--contrib/zkt/examples/flat/example.net./kexample.net.+005+14829.key4
-rw-r--r--contrib/zkt/examples/flat/example.net./kexample.net.+005+14829.private10
-rw-r--r--contrib/zkt/examples/flat/example.net./keyset-example.net.19
-rw-r--r--contrib/zkt/examples/flat/example.net./zone.db43
-rw-r--r--contrib/zkt/examples/flat/example.net./zone.db.signed166
-rw-r--r--contrib/zkt/examples/flat/keysets/dlvset-sub.example.net.2
-rw-r--r--contrib/zkt/examples/flat/keysets/dsset-dyn.example.net.2
-rw-r--r--contrib/zkt/examples/flat/keysets/dsset-example.net.4
-rw-r--r--contrib/zkt/examples/flat/keysets/dsset-sub.example.net.2
-rw-r--r--contrib/zkt/examples/flat/keysets/keyset-dyn.example.net.18
-rw-r--r--contrib/zkt/examples/flat/keysets/keyset-example.net.19
-rw-r--r--contrib/zkt/examples/flat/keysets/keyset-sub.example.net.8
-rw-r--r--contrib/zkt/examples/flat/named.conf99
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+04254.key3
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+04254.private10
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+56744.key3
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+56744.published10
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+005+54876.key1
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+005+54876.private10
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./dlvset-sub.example.net.2
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./dnskey.db29
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./dnssec.conf14
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./zone.db25
-rw-r--r--contrib/zkt/examples/flat/sub.example.net./zone.db.signed103
-rw-r--r--contrib/zkt/examples/flat/zkt.log2501
-rw-r--r--contrib/zkt/examples/flat/zone.conf10
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+11867.key3
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+11867.published10
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+17439.key4
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+17439.private10
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+35672.key3
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+35672.private10
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+41145.key3
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+41145.private10
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+59244.key3
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+59244.published10
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./dnskey.db48
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./dsset-example.de.6
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./keyset-example.de.28
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./keyset-sub.example.de.8
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+19793.key3
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+19793.private10
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+51977.depreciated10
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+51977.key3
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+55699.key3
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+55699.published10
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+005+40998.key3
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+005+40998.private10
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dlvset-sub.example.de.2
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dnskey.db35
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dnssec.conf17
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dsset-sub.example.de.2
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./keyset-sub.example.de.8
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./zone.db25
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./zone.db.signed108
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./zone.db37
-rw-r--r--contrib/zkt/examples/hierarchical/de./example.de./zone.db.signed147
-rw-r--r--contrib/zkt/examples/hierarchical/de./keyset-example.de.28
-rw-r--r--contrib/zkt/examples/hierarchical/dnssec.conf40
-rw-r--r--contrib/zkt/examples/hierarchical/named.conf102
-rw-r--r--contrib/zkt/examples/hierarchical/zone.conf10
-rw-r--r--contrib/zkt/examples/views/dnssec-extern.conf39
-rw-r--r--contrib/zkt/examples/views/dnssec-intern.conf39
-rwxr-xr-xcontrib/zkt/examples/views/dnssec-signer-extern7
-rwxr-xr-xcontrib/zkt/examples/views/dnssec-signer-intern7
-rwxr-xr-xcontrib/zkt/examples/views/dnssec-zkt-extern7
-rwxr-xr-xcontrib/zkt/examples/views/dnssec-zkt-intern7
-rw-r--r--contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+10367.key3
-rw-r--r--contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+10367.published10
-rw-r--r--contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+23553.key1
-rw-r--r--contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+23553.private10
-rw-r--r--contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+35744.key4
-rw-r--r--contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+35744.private10
-rw-r--r--contrib/zkt/examples/views/extern/example.net./dnskey.db30
-rw-r--r--contrib/zkt/examples/views/extern/example.net./dsset-example.net.2
-rw-r--r--contrib/zkt/examples/views/extern/example.net./keyset-example.net.10
-rw-r--r--contrib/zkt/examples/views/extern/example.net./zone.db33
-rw-r--r--contrib/zkt/examples/views/extern/example.net./zone.db.signed109
-rw-r--r--contrib/zkt/examples/views/extern/zkt-ext.log28
-rw-r--r--contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+00126.key1
-rw-r--r--contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+00126.private10
-rw-r--r--contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+05972.key1
-rw-r--r--contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+05972.private10
-rw-r--r--contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+23375.key3
-rw-r--r--contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+23375.published10
-rw-r--r--contrib/zkt/examples/views/intern/example.net./dnskey.db30
-rw-r--r--contrib/zkt/examples/views/intern/example.net./dsset-example.net.2
-rw-r--r--contrib/zkt/examples/views/intern/example.net./keyset-example.net.10
-rw-r--r--contrib/zkt/examples/views/intern/example.net./zone.db33
-rw-r--r--contrib/zkt/examples/views/intern/example.net./zone.db.signed109
-rw-r--r--contrib/zkt/examples/views/intern/zkt-int.log169
-rw-r--r--contrib/zkt/examples/views/named.conf97
-rw-r--r--contrib/zkt/examples/views/named.log17
-rw-r--r--contrib/zkt/examples/views/root.hint45
-rwxr-xr-xcontrib/zkt/examples/views/viewtest.sh20
-rw-r--r--contrib/zkt/examples/zone.db45
-rw-r--r--contrib/zkt/examples/zone.db.signed146
-rw-r--r--contrib/zkt/log.c443
-rw-r--r--contrib/zkt/log.h66
-rw-r--r--contrib/zkt/misc.c1157
-rw-r--r--contrib/zkt/misc.h84
-rw-r--r--contrib/zkt/ncparse.c317
-rw-r--r--contrib/zkt/ncparse.h41
-rw-r--r--contrib/zkt/rollover.c615
-rw-r--r--contrib/zkt/rollover.h52
-rw-r--r--contrib/zkt/strlist.c166
-rw-r--r--contrib/zkt/strlist.h46
-rw-r--r--contrib/zkt/tags324
-rw-r--r--contrib/zkt/zconf.c775
-rw-r--r--contrib/zkt/zconf.h173
-rw-r--r--contrib/zkt/zkt-soaserial.c222
-rw-r--r--contrib/zkt/zkt.c354
-rw-r--r--contrib/zkt/zkt.h46
-rw-r--r--contrib/zkt/zone.c336
-rw-r--r--contrib/zkt/zone.h66
-rw-r--r--doc/Makefile.in29
-rw-r--r--doc/arm/Bv9ARM-book.xml14205
-rw-r--r--doc/arm/Bv9ARM.ch01.html562
-rw-r--r--doc/arm/Bv9ARM.ch02.html158
-rw-r--r--doc/arm/Bv9ARM.ch03.html818
-rw-r--r--doc/arm/Bv9ARM.ch04.html1036
-rw-r--r--doc/arm/Bv9ARM.ch05.html143
-rw-r--r--doc/arm/Bv9ARM.ch06.html8784
-rw-r--r--doc/arm/Bv9ARM.ch07.html254
-rw-r--r--doc/arm/Bv9ARM.ch08.html139
-rw-r--r--doc/arm/Bv9ARM.ch09.html630
-rw-r--r--doc/arm/Bv9ARM.ch10.html111
-rw-r--r--doc/arm/Bv9ARM.html276
-rwxr-xr-xdoc/arm/Bv9ARM.pdf14133
-rw-r--r--doc/arm/Makefile.in67
-rw-r--r--doc/arm/README-SGML329
-rw-r--r--doc/arm/isc-logo.eps12253
-rw-r--r--doc/arm/isc-logo.pdfbin0 -> 21981 bytes
-rw-r--r--doc/arm/latex-fixup.pl49
-rw-r--r--doc/arm/man.dig.html673
-rw-r--r--doc/arm/man.dnssec-dsfromkey.html170
-rw-r--r--doc/arm/man.dnssec-keyfromlabel.html210
-rw-r--r--doc/arm/man.dnssec-keygen.html270
-rw-r--r--doc/arm/man.dnssec-signzone.html340
-rw-r--r--doc/arm/man.host.html249
-rw-r--r--doc/arm/man.named-checkconf.html134
-rw-r--r--doc/arm/man.named-checkzone.html300
-rw-r--r--doc/arm/man.named.html322
-rw-r--r--doc/arm/man.nsupdate.html568
-rw-r--r--doc/arm/man.rndc-confgen.html222
-rw-r--r--doc/arm/man.rndc.conf.html255
-rw-r--r--doc/arm/man.rndc.html203
-rw-r--r--doc/doxygen/Doxyfile.in1269
-rw-r--r--doc/doxygen/Makefile.in38
-rw-r--r--doc/doxygen/doxygen-input-filter.in60
-rw-r--r--doc/doxygen/isc-footer.html28
-rw-r--r--doc/doxygen/isc-header.html26
-rw-r--r--doc/doxygen/mainpage85
-rw-r--r--doc/draft/draft-baba-dnsext-acl-reqts-01.txt336
-rw-r--r--doc/draft/draft-daigle-napstr-04.txt1232
-rw-r--r--doc/draft/draft-danisch-dns-rr-smtp-03.txt1960
-rw-r--r--doc/draft/draft-dnsext-opcode-discover-02.txt241
-rw-r--r--doc/draft/draft-durand-dnsop-dynreverse-00.txt240
-rw-r--r--doc/draft/draft-ietf-dnsext-2929bis-01.txt928
-rw-r--r--doc/draft/draft-ietf-dnsext-axfr-clarify-09.txt992
-rw-r--r--doc/draft/draft-ietf-dnsext-dns-name-p-s-00.txt1397
-rw-r--r--doc/draft/draft-ietf-dnsext-dnssec-2535typecode-change-06.txt442
-rw-r--r--doc/draft/draft-ietf-dnsext-dnssec-bis-updates-01.txt616
-rw-r--r--doc/draft/draft-ietf-dnsext-dnssec-experiments-03.txt840
-rw-r--r--doc/draft/draft-ietf-dnsext-dnssec-online-signing-02.txt616
-rw-r--r--doc/draft/draft-ietf-dnsext-dnssec-opt-in-07.txt896
-rw-r--r--doc/draft/draft-ietf-dnsext-dnssec-rsasha256-06.txt504
-rw-r--r--doc/draft/draft-ietf-dnsext-dnssec-trans-02.txt839
-rw-r--r--doc/draft/draft-ietf-dnsext-ds-sha256-05.txt504
-rw-r--r--doc/draft/draft-ietf-dnsext-ecc-key-07.txt928
-rw-r--r--doc/draft/draft-ietf-dnsext-forgery-resilience-02.txt17
-rw-r--r--doc/draft/draft-ietf-dnsext-interop3597-02.txt334
-rw-r--r--doc/draft/draft-ietf-dnsext-keyrr-key-signing-flag-12.txt560
-rw-r--r--doc/draft/draft-ietf-dnsext-mdns-46.txt1801
-rw-r--r--doc/draft/draft-ietf-dnsext-nsid-01.txt840
-rw-r--r--doc/draft/draft-ietf-dnsext-rfc2536bis-dsa-07.txt464
-rw-r--r--doc/draft/draft-ietf-dnsext-rfc2539bis-dhk-07.txt580
-rw-r--r--doc/draft/draft-ietf-dnsext-rfc2671bis-edns0-01.txt480
-rw-r--r--doc/draft/draft-ietf-dnsext-rfc2672bis-dname-13.txt952
-rw-r--r--doc/draft/draft-ietf-dnsext-signed-nonexistence-requirements-01.txt755
-rw-r--r--doc/draft/draft-ietf-dnsext-tkey-renewal-mode-05.txt1292
-rw-r--r--doc/draft/draft-ietf-dnsext-trustupdate-threshold-00.txt1501
-rw-r--r--doc/draft/draft-ietf-dnsext-trustupdate-timers-05.txt729
-rw-r--r--doc/draft/draft-ietf-dnsext-tsig-sha-06.txt522
-rw-r--r--doc/draft/draft-ietf-dnsext-wcard-clarify-10.txt1063
-rw-r--r--doc/draft/draft-ietf-dnsop-bad-dns-res-05.txt1232
-rw-r--r--doc/draft/draft-ietf-dnsop-default-local-zones-05.txt672
-rw-r--r--doc/draft/draft-ietf-dnsop-inaddr-required-07.txt396
-rw-r--r--doc/draft/draft-ietf-dnsop-ipv6-dns-configuration-06.txt1848
-rw-r--r--doc/draft/draft-ietf-dnsop-ipv6-dns-issues-11.txt1682
-rw-r--r--doc/draft/draft-ietf-dnsop-ipv6-transport-guidelines-01.txt300
-rw-r--r--doc/draft/draft-ietf-dnsop-key-rollover-requirements-02.txt389
-rw-r--r--doc/draft/draft-ietf-dnsop-name-server-management-reqs-01.txt1008
-rw-r--r--doc/draft/draft-ietf-dnsop-respsize-06.txt640
-rw-r--r--doc/draft/draft-ietf-dnsop-serverid-06.txt618
-rw-r--r--doc/draft/draft-ietf-enum-e164-gstn-np-05.txt1588
-rw-r--r--doc/draft/draft-ietf-ipv6-node-requirements-08.txt1200
-rw-r--r--doc/draft/draft-ietf-secsh-dns-05.txt614
-rw-r--r--doc/draft/draft-ihren-dnsext-threshold-validation-00.txt519
-rw-r--r--doc/draft/draft-kato-dnsop-local-zones-00.txt295
-rw-r--r--doc/draft/draft-park-ipv6-extensions-dns-pnp-00.txt1830
-rw-r--r--doc/draft/update46
-rw-r--r--doc/misc/Makefile.in48
-rw-r--r--doc/misc/dnssec84
-rw-r--r--doc/misc/format-options.pl49
-rw-r--r--doc/misc/ipv6113
-rw-r--r--doc/misc/migration267
-rw-r--r--doc/misc/migration-4to957
-rw-r--r--doc/misc/options537
-rw-r--r--doc/misc/rfc-compliance62
-rw-r--r--doc/misc/roadmap47
-rw-r--r--doc/misc/sdb169
-rw-r--r--doc/misc/sort-options.pl50
-rwxr-xr-xdoc/rfc/fetch6
-rw-r--r--doc/rfc/index119
-rw-r--r--doc/rfc/rfc1032.txt781
-rw-r--r--doc/rfc/rfc1033.txt1229
-rw-r--r--doc/rfc/rfc1034.txt3077
-rw-r--r--doc/rfc/rfc1035.txt3077
-rw-r--r--doc/rfc/rfc1101.txt787
-rw-r--r--doc/rfc/rfc1122.txt6844
-rw-r--r--doc/rfc/rfc1123.txt5782
-rw-r--r--doc/rfc/rfc1183.txt619
-rw-r--r--doc/rfc/rfc1348.txt227
-rw-r--r--doc/rfc/rfc1535.txt283
-rw-r--r--doc/rfc/rfc1536.txt675
-rw-r--r--doc/rfc/rfc1537.txt507
-rw-r--r--doc/rfc/rfc1591.txt395
-rw-r--r--doc/rfc/rfc1611.txt1683
-rw-r--r--doc/rfc/rfc1612.txt1795
-rw-r--r--doc/rfc/rfc1706.txt563
-rw-r--r--doc/rfc/rfc1712.txt395
-rw-r--r--doc/rfc/rfc1750.txt1683
-rw-r--r--doc/rfc/rfc1876.txt1011
-rw-r--r--doc/rfc/rfc1886.txt268
-rw-r--r--doc/rfc/rfc1982.txt394
-rw-r--r--doc/rfc/rfc1995.txt451
-rw-r--r--doc/rfc/rfc1996.txt395
-rw-r--r--doc/rfc/rfc2052.txt563
-rw-r--r--doc/rfc/rfc2104.txt620
-rw-r--r--doc/rfc/rfc2119.txt171
-rw-r--r--doc/rfc/rfc2133.txt1795
-rw-r--r--doc/rfc/rfc2136.txt1460
-rw-r--r--doc/rfc/rfc2137.txt619
-rw-r--r--doc/rfc/rfc2163.txt1459
-rw-r--r--doc/rfc/rfc2168.txt1123
-rw-r--r--doc/rfc/rfc2181.txt842
-rw-r--r--doc/rfc/rfc2230.txt619
-rw-r--r--doc/rfc/rfc2308.txt1067
-rw-r--r--doc/rfc/rfc2317.txt563
-rw-r--r--doc/rfc/rfc2373.txt1459
-rw-r--r--doc/rfc/rfc2374.txt675
-rw-r--r--doc/rfc/rfc2375.txt451
-rw-r--r--doc/rfc/rfc2418.txt1459
-rw-r--r--doc/rfc/rfc2535.txt2635
-rw-r--r--doc/rfc/rfc2536.txt339
-rw-r--r--doc/rfc/rfc2537.txt339
-rw-r--r--doc/rfc/rfc2538.txt563
-rw-r--r--doc/rfc/rfc2539.txt395
-rw-r--r--doc/rfc/rfc2540.txt339
-rw-r--r--doc/rfc/rfc2541.txt395
-rw-r--r--doc/rfc/rfc2553.txt2299
-rw-r--r--doc/rfc/rfc2671.txt395
-rw-r--r--doc/rfc/rfc2672.txt507
-rw-r--r--doc/rfc/rfc2673.txt395
-rw-r--r--doc/rfc/rfc2782.txt675
-rw-r--r--doc/rfc/rfc2825.txt395
-rw-r--r--doc/rfc/rfc2826.txt339
-rw-r--r--doc/rfc/rfc2845.txt843
-rw-r--r--doc/rfc/rfc2874.txt1123
-rw-r--r--doc/rfc/rfc2915.txt1011
-rw-r--r--doc/rfc/rfc2929.txt675
-rw-r--r--doc/rfc/rfc2930.txt899
-rw-r--r--doc/rfc/rfc2931.txt563
-rw-r--r--doc/rfc/rfc3007.txt507
-rw-r--r--doc/rfc/rfc3008.txt395
-rw-r--r--doc/rfc/rfc3071.txt563
-rw-r--r--doc/rfc/rfc3090.txt619
-rw-r--r--doc/rfc/rfc3110.txt395
-rw-r--r--doc/rfc/rfc3123.txt451
-rw-r--r--doc/rfc/rfc3152.txt227
-rw-r--r--doc/rfc/rfc3197.txt283
-rw-r--r--doc/rfc/rfc3225.txt339
-rw-r--r--doc/rfc/rfc3226.txt339
-rw-r--r--doc/rfc/rfc3258.txt619
-rw-r--r--doc/rfc/rfc3363.txt339
-rw-r--r--doc/rfc/rfc3364.txt619
-rw-r--r--doc/rfc/rfc3425.txt283
-rw-r--r--doc/rfc/rfc3445.txt563
-rw-r--r--doc/rfc/rfc3467.txt1739
-rw-r--r--doc/rfc/rfc3490.txt1235
-rw-r--r--doc/rfc/rfc3491.txt395
-rw-r--r--doc/rfc/rfc3492.txt1963
-rw-r--r--doc/rfc/rfc3493.txt2187
-rw-r--r--doc/rfc/rfc3513.txt1459
-rw-r--r--doc/rfc/rfc3596.txt451
-rw-r--r--doc/rfc/rfc3597.txt451
-rw-r--r--doc/rfc/rfc3645.txt1459
-rw-r--r--doc/rfc/rfc3655.txt451
-rw-r--r--doc/rfc/rfc3658.txt1067
-rw-r--r--doc/rfc/rfc3757.txt451
-rw-r--r--doc/rfc/rfc3833.txt899
-rw-r--r--doc/rfc/rfc3845.txt395
-rw-r--r--doc/rfc/rfc3901.txt283
-rw-r--r--doc/rfc/rfc4025.txt675
-rw-r--r--doc/rfc/rfc4033.txt1179
-rw-r--r--doc/rfc/rfc4034.txt1627
-rw-r--r--doc/rfc/rfc4035.txt2971
-rw-r--r--doc/rfc/rfc4074.txt339
-rw-r--r--doc/rfc/rfc4159.txt171
-rw-r--r--doc/rfc/rfc4193.txt899
-rw-r--r--doc/rfc/rfc4255.txt507
-rw-r--r--doc/rfc/rfc4343.txt563
-rw-r--r--doc/rfc/rfc4367.txt955
-rw-r--r--doc/rfc/rfc4398.txt955
-rw-r--r--doc/rfc/rfc4408.txt2691
-rw-r--r--doc/rfc/rfc4431.txt227
-rw-r--r--doc/rfc/rfc4470.txt451
-rw-r--r--doc/rfc/rfc4634.txt6051
-rw-r--r--doc/rfc/rfc4641.txt1963
-rw-r--r--doc/rfc/rfc4648.txt1011
-rw-r--r--doc/rfc/rfc4701.txt675
-rw-r--r--doc/rfc/rfc5155.txt2915
-rw-r--r--doc/rfc/rfc952.txt340
-rw-r--r--doc/xsl/Makefile.in28
-rw-r--r--doc/xsl/copyright.xsl75
-rw-r--r--doc/xsl/isc-docbook-chunk.xsl.in65
-rw-r--r--doc/xsl/isc-docbook-html.xsl.in58
-rw-r--r--doc/xsl/isc-docbook-latex-mappings.xml37
-rw-r--r--doc/xsl/isc-docbook-latex.xsl.in166
-rw-r--r--doc/xsl/isc-docbook-text.xsl50
-rw-r--r--doc/xsl/isc-manpage.xsl.in145
-rw-r--r--doc/xsl/pre-latex.xsl55
-rw-r--r--docutil/HTML_COPYRIGHT16
-rw-r--r--docutil/MAN_COPYRIGHT16
-rw-r--r--docutil/patch-db2latex-duplicate-template-bug77
-rw-r--r--docutil/patch-db2latex-nested-param-bug18
-rw-r--r--docutil/patch-db2latex-xsltproc-title-bug29
-rwxr-xr-xinstall-sh250
-rw-r--r--isc-config.sh.in149
-rw-r--r--lib/Makefile.in29
-rw-r--r--lib/bind9/Makefile.in84
-rw-r--r--lib/bind9/api3
-rw-r--r--lib/bind9/check.c2296
-rw-r--r--lib/bind9/getaddresses.c231
-rw-r--r--lib/bind9/include/Makefile.in25
-rw-r--r--lib/bind9/include/bind9/Makefile.in42
-rw-r--r--lib/bind9/include/bind9/check.h57
-rw-r--r--lib/bind9/include/bind9/getaddresses.h61
-rw-r--r--lib/bind9/include/bind9/version.h28
-rw-r--r--lib/bind9/version.c28
-rw-r--r--lib/bind9/win32/DLLMain.c57
-rw-r--r--lib/bind9/win32/libbind9.def8
-rw-r--r--lib/bind9/win32/libbind9.dsp133
-rw-r--r--lib/bind9/win32/libbind9.dsw29
-rw-r--r--lib/bind9/win32/libbind9.mak452
-rw-r--r--lib/bind9/win32/version.c28
-rw-r--r--lib/dns/Makefile.in179
-rw-r--r--lib/dns/acache.c1782
-rw-r--r--lib/dns/acl.c623
-rw-r--r--lib/dns/adb.c3621
-rw-r--r--lib/dns/api3
-rw-r--r--lib/dns/byaddr.c316
-rw-r--r--lib/dns/cache.c1089
-rw-r--r--lib/dns/callbacks.c113
-rw-r--r--lib/dns/compress.c341
-rw-r--r--lib/dns/db.c926
-rw-r--r--lib/dns/dbiterator.c143
-rw-r--r--lib/dns/dbtable.c291
-rw-r--r--lib/dns/diff.c638
-rw-r--r--lib/dns/dispatch.c3436
-rw-r--r--lib/dns/dlz.c510
-rw-r--r--lib/dns/dnssec.c892
-rw-r--r--lib/dns/ds.c104
-rw-r--r--lib/dns/dst_api.c1310
-rw-r--r--lib/dns/dst_internal.h217
-rw-r--r--lib/dns/dst_lib.c67
-rw-r--r--lib/dns/dst_openssl.h40
-rw-r--r--lib/dns/dst_parse.c532
-rw-r--r--lib/dns/dst_parse.h134
-rw-r--r--lib/dns/dst_result.c89
-rw-r--r--lib/dns/forward.c199
-rw-r--r--lib/dns/gen-unix.h97
-rw-r--r--lib/dns/gen-win32.h290
-rw-r--r--lib/dns/gen.c888
-rw-r--r--lib/dns/gssapi_link.c310
-rw-r--r--lib/dns/gssapictx.c738
-rw-r--r--lib/dns/hmac_link.c1687
-rw-r--r--lib/dns/include/Makefile.in25
-rw-r--r--lib/dns/include/dns/Makefile.in54
-rw-r--r--lib/dns/include/dns/acache.h445
-rw-r--r--lib/dns/include/dns/acl.h222
-rw-r--r--lib/dns/include/dns/adb.h634
-rw-r--r--lib/dns/include/dns/bit.h39
-rw-r--r--lib/dns/include/dns/byaddr.h171
-rw-r--r--lib/dns/include/dns/cache.h253
-rw-r--r--lib/dns/include/dns/callbacks.h87
-rw-r--r--lib/dns/include/dns/cert.h69
-rw-r--r--lib/dns/include/dns/compress.h269
-rw-r--r--lib/dns/include/dns/db.h1477
-rw-r--r--lib/dns/include/dns/dbiterator.h297
-rw-r--r--lib/dns/include/dns/dbtable.h165
-rw-r--r--lib/dns/include/dns/diff.h291
-rw-r--r--lib/dns/include/dns/dispatch.h501
-rw-r--r--lib/dns/include/dns/dlz.h290
-rw-r--r--lib/dns/include/dns/dnssec.h183
-rw-r--r--lib/dns/include/dns/ds.h63
-rw-r--r--lib/dns/include/dns/events.h75
-rw-r--r--lib/dns/include/dns/fixedname.h86
-rw-r--r--lib/dns/include/dns/forward.h118
-rw-r--r--lib/dns/include/dns/iptable.h70
-rw-r--r--lib/dns/include/dns/journal.h282
-rw-r--r--lib/dns/include/dns/keyflags.h54
-rw-r--r--lib/dns/include/dns/keytable.h255
-rw-r--r--lib/dns/include/dns/keyvalues.h100
-rw-r--r--lib/dns/include/dns/lib.h45
-rw-r--r--lib/dns/include/dns/log.h107
-rw-r--r--lib/dns/include/dns/lookup.h137
-rw-r--r--lib/dns/include/dns/master.h306
-rw-r--r--lib/dns/include/dns/masterdump.h340
-rw-r--r--lib/dns/include/dns/message.h1343
-rw-r--r--lib/dns/include/dns/name.h1297
-rw-r--r--lib/dns/include/dns/ncache.h179
-rw-r--r--lib/dns/include/dns/nsec.h80
-rw-r--r--lib/dns/include/dns/nsec3.h194
-rw-r--r--lib/dns/include/dns/opcode.h51
-rw-r--r--lib/dns/include/dns/order.h99
-rw-r--r--lib/dns/include/dns/peer.h219
-rw-r--r--lib/dns/include/dns/portlist.h101
-rw-r--r--lib/dns/include/dns/rbt.h939
-rw-r--r--lib/dns/include/dns/rcode.h113
-rw-r--r--lib/dns/include/dns/rdata.h702
-rw-r--r--lib/dns/include/dns/rdataclass.h81
-rw-r--r--lib/dns/include/dns/rdatalist.h124
-rw-r--r--lib/dns/include/dns/rdataset.h639
-rw-r--r--lib/dns/include/dns/rdatasetiter.h170
-rw-r--r--lib/dns/include/dns/rdataslab.h170
-rw-r--r--lib/dns/include/dns/rdatatype.h84
-rw-r--r--lib/dns/include/dns/request.h374
-rw-r--r--lib/dns/include/dns/resolver.h481
-rw-r--r--lib/dns/include/dns/result.h191
-rw-r--r--lib/dns/include/dns/rootns.h45
-rw-r--r--lib/dns/include/dns/sdb.h209
-rw-r--r--lib/dns/include/dns/sdlz.h266
-rw-r--r--lib/dns/include/dns/secalg.h71
-rw-r--r--lib/dns/include/dns/secproto.h71
-rw-r--r--lib/dns/include/dns/soa.h81
-rw-r--r--lib/dns/include/dns/ssu.h189
-rw-r--r--lib/dns/include/dns/stats.h345
-rw-r--r--lib/dns/include/dns/tcpmsg.h147
-rw-r--r--lib/dns/include/dns/time.h72
-rw-r--r--lib/dns/include/dns/timer.h52
-rw-r--r--lib/dns/include/dns/tkey.h250
-rw-r--r--lib/dns/include/dns/tsig.h257
-rw-r--r--lib/dns/include/dns/ttl.h78
-rw-r--r--lib/dns/include/dns/types.h346
-rw-r--r--lib/dns/include/dns/validator.h255
-rw-r--r--lib/dns/include/dns/version.h28
-rw-r--r--lib/dns/include/dns/view.h879
-rw-r--r--lib/dns/include/dns/xfrin.h111
-rw-r--r--lib/dns/include/dns/zone.h1736
-rw-r--r--lib/dns/include/dns/zonekey.h42
-rw-r--r--lib/dns/include/dns/zt.h183
-rw-r--r--lib/dns/include/dst/Makefile.in37
-rw-r--r--lib/dns/include/dst/dst.h642
-rw-r--r--lib/dns/include/dst/gssapi.h207
-rw-r--r--lib/dns/include/dst/lib.h41
-rw-r--r--lib/dns/include/dst/result.h71
-rw-r--r--lib/dns/iptable.c185
-rw-r--r--lib/dns/journal.c2217
-rw-r--r--lib/dns/key.c147
-rw-r--r--lib/dns/keytable.c395
-rw-r--r--lib/dns/lib.c65
-rw-r--r--lib/dns/log.c98
-rw-r--r--lib/dns/lookup.c497
-rw-r--r--lib/dns/master.c2892
-rw-r--r--lib/dns/masterdump.c1754
-rw-r--r--lib/dns/message.c3378
-rw-r--r--lib/dns/name.c2408
-rw-r--r--lib/dns/ncache.c658
-rw-r--r--lib/dns/nsec.c277
-rw-r--r--lib/dns/nsec3.c1377
-rw-r--r--lib/dns/openssl_link.c447
-rw-r--r--lib/dns/openssldh_link.c638
-rw-r--r--lib/dns/openssldsa_link.c607
-rw-r--r--lib/dns/opensslrsa_link.c986
-rw-r--r--lib/dns/order.c167
-rw-r--r--lib/dns/peer.c712
-rw-r--r--lib/dns/portlist.c266
-rw-r--r--lib/dns/rbt.c2657
-rw-r--r--lib/dns/rbtdb.c8435
-rw-r--r--lib/dns/rbtdb.h44
-rw-r--r--lib/dns/rbtdb64.c23
-rw-r--r--lib/dns/rbtdb64.h45
-rw-r--r--lib/dns/rcode.c489
-rw-r--r--lib/dns/rdata.c1769
-rw-r--r--lib/dns/rdata/any_255/tsig_250.c597
-rw-r--r--lib/dns/rdata/any_255/tsig_250.h38
-rw-r--r--lib/dns/rdata/ch_3/a_1.c316
-rw-r--r--lib/dns/rdata/ch_3/a_1.h34
-rw-r--r--lib/dns/rdata/generic/afsdb_18.c309
-rw-r--r--lib/dns/rdata/generic/afsdb_18.h34
-rw-r--r--lib/dns/rdata/generic/cert_37.c280
-rw-r--r--lib/dns/rdata/generic/cert_37.h34
-rw-r--r--lib/dns/rdata/generic/cname_5.c232
-rw-r--r--lib/dns/rdata/generic/cname_5.h29
-rw-r--r--lib/dns/rdata/generic/dlv_32769.c321
-rw-r--r--lib/dns/rdata/generic/dlv_32769.h33
-rw-r--r--lib/dns/rdata/generic/dname_39.c233
-rw-r--r--lib/dns/rdata/generic/dname_39.h32
-rw-r--r--lib/dns/rdata/generic/dnskey_48.c312
-rw-r--r--lib/dns/rdata/generic/dnskey_48.h37
-rw-r--r--lib/dns/rdata/generic/ds_43.c321
-rw-r--r--lib/dns/rdata/generic/ds_43.h35
-rw-r--r--lib/dns/rdata/generic/gpos_27.c252
-rw-r--r--lib/dns/rdata/generic/gpos_27.h37
-rw-r--r--lib/dns/rdata/generic/hinfo_13.c224
-rw-r--r--lib/dns/rdata/generic/hinfo_13.h32
-rw-r--r--lib/dns/rdata/generic/ipseckey_45.c462
-rw-r--r--lib/dns/rdata/generic/ipseckey_45.h35
-rw-r--r--lib/dns/rdata/generic/isdn_20.c234
-rw-r--r--lib/dns/rdata/generic/isdn_20.h35
-rw-r--r--lib/dns/rdata/generic/key_25.c312
-rw-r--r--lib/dns/rdata/generic/key_25.h37
-rw-r--r--lib/dns/rdata/generic/loc_29.c794
-rw-r--r--lib/dns/rdata/generic/loc_29.h43
-rw-r--r--lib/dns/rdata/generic/mb_7.c234
-rw-r--r--lib/dns/rdata/generic/mb_7.h30
-rw-r--r--lib/dns/rdata/generic/md_3.c236
-rw-r--r--lib/dns/rdata/generic/md_3.h31
-rw-r--r--lib/dns/rdata/generic/mf_4.c235
-rw-r--r--lib/dns/rdata/generic/mf_4.h30
-rw-r--r--lib/dns/rdata/generic/mg_8.c230
-rw-r--r--lib/dns/rdata/generic/mg_8.h30
-rw-r--r--lib/dns/rdata/generic/minfo_14.c324
-rw-r--r--lib/dns/rdata/generic/minfo_14.h31
-rw-r--r--lib/dns/rdata/generic/mr_9.c231
-rw-r--r--lib/dns/rdata/generic/mr_9.h30
-rw-r--r--lib/dns/rdata/generic/mx_15.c319
-rw-r--r--lib/dns/rdata/generic/mx_15.h31
-rw-r--r--lib/dns/rdata/generic/ns_2.c251
-rw-r--r--lib/dns/rdata/generic/ns_2.h31
-rw-r--r--lib/dns/rdata/generic/nsec3_50.c481
-rw-r--r--lib/dns/rdata/generic/nsec3_50.h93
-rw-r--r--lib/dns/rdata/generic/nsec3param_51.c314
-rw-r--r--lib/dns/rdata/generic/nsec3param_51.h38
-rw-r--r--lib/dns/rdata/generic/nsec_47.c366
-rw-r--r--lib/dns/rdata/generic/nsec_47.h34
-rw-r--r--lib/dns/rdata/generic/null_10.c192
-rw-r--r--lib/dns/rdata/generic/null_10.h32
-rw-r--r--lib/dns/rdata/generic/nxt_30.c329
-rw-r--r--lib/dns/rdata/generic/nxt_30.h34
-rw-r--r--lib/dns/rdata/generic/opt_41.c280
-rw-r--r--lib/dns/rdata/generic/opt_41.h55
-rw-r--r--lib/dns/rdata/generic/proforma.c173
-rw-r--r--lib/dns/rdata/generic/proforma.h30
-rw-r--r--lib/dns/rdata/generic/ptr_12.c291
-rw-r--r--lib/dns/rdata/generic/ptr_12.h30
-rw-r--r--lib/dns/rdata/generic/rp_17.c314
-rw-r--r--lib/dns/rdata/generic/rp_17.h34
-rw-r--r--lib/dns/rdata/generic/rrsig_46.c551
-rw-r--r--lib/dns/rdata/generic/rrsig_46.h41
-rw-r--r--lib/dns/rdata/generic/rt_21.c311
-rw-r--r--lib/dns/rdata/generic/rt_21.h33
-rw-r--r--lib/dns/rdata/generic/sig_24.c578
-rw-r--r--lib/dns/rdata/generic/sig_24.h42
-rw-r--r--lib/dns/rdata/generic/soa_6.c443
-rw-r--r--lib/dns/rdata/generic/soa_6.h37
-rw-r--r--lib/dns/rdata/generic/spf_99.c238
-rw-r--r--lib/dns/rdata/generic/spf_99.h51
-rw-r--r--lib/dns/rdata/generic/sshfp_44.c262
-rw-r--r--lib/dns/rdata/generic/sshfp_44.h35
-rw-r--r--lib/dns/rdata/generic/tkey_249.c555
-rw-r--r--lib/dns/rdata/generic/tkey_249.h41
-rw-r--r--lib/dns/rdata/generic/txt_16.c238
-rw-r--r--lib/dns/rdata/generic/txt_16.h52
-rw-r--r--lib/dns/rdata/generic/unspec_103.c189
-rw-r--r--lib/dns/rdata/generic/unspec_103.h31
-rw-r--r--lib/dns/rdata/generic/x25_19.c219
-rw-r--r--lib/dns/rdata/generic/x25_19.h33
-rw-r--r--lib/dns/rdata/hs_4/a_1.c232
-rw-r--r--lib/dns/rdata/hs_4/a_1.h29
-rw-r--r--lib/dns/rdata/in_1/a6_38.c461
-rw-r--r--lib/dns/rdata/in_1/a6_38.h34
-rw-r--r--lib/dns/rdata/in_1/a_1.c236
-rw-r--r--lib/dns/rdata/in_1/a_1.h29
-rw-r--r--lib/dns/rdata/in_1/aaaa_28.c233
-rw-r--r--lib/dns/rdata/in_1/aaaa_28.h31
-rw-r--r--lib/dns/rdata/in_1/apl_42.c453
-rw-r--r--lib/dns/rdata/in_1/apl_42.h56
-rw-r--r--lib/dns/rdata/in_1/dhcid_49.c229
-rw-r--r--lib/dns/rdata/in_1/dhcid_49.h30
-rw-r--r--lib/dns/rdata/in_1/kx_36.c288
-rw-r--r--lib/dns/rdata/in_1/kx_36.h33
-rw-r--r--lib/dns/rdata/in_1/naptr_35.c578
-rw-r--r--lib/dns/rdata/in_1/naptr_35.h40
-rw-r--r--lib/dns/rdata/in_1/nsap-ptr_23.c245
-rw-r--r--lib/dns/rdata/in_1/nsap-ptr_23.h32
-rw-r--r--lib/dns/rdata/in_1/nsap_22.c255
-rw-r--r--lib/dns/rdata/in_1/nsap_22.h33
-rw-r--r--lib/dns/rdata/in_1/px_26.c374
-rw-r--r--lib/dns/rdata/in_1/px_26.h34
-rw-r--r--lib/dns/rdata/in_1/srv_33.c373
-rw-r--r--lib/dns/rdata/in_1/srv_33.h37
-rw-r--r--lib/dns/rdata/in_1/wks_11.c349
-rw-r--r--lib/dns/rdata/in_1/wks_11.h32
-rw-r--r--lib/dns/rdata/rdatastructpre.h42
-rw-r--r--lib/dns/rdata/rdatastructsuf.h22
-rw-r--r--lib/dns/rdatalist.c347
-rw-r--r--lib/dns/rdatalist_p.h64
-rw-r--r--lib/dns/rdataset.c734
-rw-r--r--lib/dns/rdatasetiter.c80
-rw-r--r--lib/dns/rdataslab.c1092
-rw-r--r--lib/dns/request.c1497
-rw-r--r--lib/dns/resolver.c7602
-rw-r--r--lib/dns/result.c277
-rw-r--r--lib/dns/rootns.c525
-rw-r--r--lib/dns/sdb.c1551
-rw-r--r--lib/dns/sdlz.c1799
-rw-r--r--lib/dns/soa.c111
-rw-r--r--lib/dns/spnego.asn152
-rw-r--r--lib/dns/spnego.c1792
-rw-r--r--lib/dns/spnego.h71
-rw-r--r--lib/dns/spnego_asn1.c885
-rw-r--r--lib/dns/spnego_asn1.pl200
-rw-r--r--lib/dns/ssu.c552
-rw-r--r--lib/dns/stats.c564
-rw-r--r--lib/dns/tcpmsg.c243
-rw-r--r--lib/dns/time.c174
-rw-r--r--lib/dns/timer.c60
-rw-r--r--lib/dns/tkey.c1419
-rw-r--r--lib/dns/tsig.c1549
-rw-r--r--lib/dns/ttl.c216
-rw-r--r--lib/dns/validator.c3776
-rw-r--r--lib/dns/version.c28
-rw-r--r--lib/dns/view.c1467
-rw-r--r--lib/dns/win32/DLLMain.c57
-rw-r--r--lib/dns/win32/gen.dsp107
-rw-r--r--lib/dns/win32/gen.dsw29
-rw-r--r--lib/dns/win32/gen.mak267
-rw-r--r--lib/dns/win32/libdns.def860
-rw-r--r--lib/dns/win32/libdns.dsp737
-rw-r--r--lib/dns/win32/libdns.dsw29
-rw-r--r--lib/dns/win32/libdns.mak2182
-rw-r--r--lib/dns/win32/version.c28
-rw-r--r--lib/dns/xfrin.c1532
-rw-r--r--lib/dns/zone.c11502
-rw-r--r--lib/dns/zonekey.c55
-rw-r--r--lib/dns/zt.c411
-rw-r--r--lib/isc/Makefile.in116
-rw-r--r--lib/isc/alpha/Makefile.in24
-rw-r--r--lib/isc/alpha/include/Makefile.in24
-rw-r--r--lib/isc/alpha/include/isc/Makefile.in36
-rw-r--r--lib/isc/alpha/include/isc/atomic.h170
-rw-r--r--lib/isc/api3
-rw-r--r--lib/isc/assertions.c97
-rw-r--r--lib/isc/base32.c371
-rw-r--r--lib/isc/base64.c250
-rw-r--r--lib/isc/bitstring.c127
-rw-r--r--lib/isc/buffer.c489
-rw-r--r--lib/isc/bufferlist.c64
-rw-r--r--lib/isc/commandline.c225
-rw-r--r--lib/isc/entropy.c1274
-rw-r--r--lib/isc/error.c106
-rw-r--r--lib/isc/event.c88
-rw-r--r--lib/isc/fsaccess.c102
-rw-r--r--lib/isc/hash.c390
-rw-r--r--lib/isc/heap.c262
-rw-r--r--lib/isc/hex.c201
-rw-r--r--lib/isc/hmacmd5.c118
-rw-r--r--lib/isc/hmacsha.c438
-rw-r--r--lib/isc/httpd.c987
-rw-r--r--lib/isc/ia64/Makefile.in24
-rw-r--r--lib/isc/ia64/include/Makefile.in24
-rw-r--r--lib/isc/ia64/include/isc/Makefile.in36
-rw-r--r--lib/isc/ia64/include/isc/atomic.h88
-rw-r--r--lib/isc/include/Makefile.in25
-rw-r--r--lib/isc/include/isc/Makefile.in61
-rw-r--r--lib/isc/include/isc/app.h212
-rw-r--r--lib/isc/include/isc/assertions.h124
-rw-r--r--lib/isc/include/isc/base32.h128
-rw-r--r--lib/isc/include/isc/base64.h99
-rw-r--r--lib/isc/include/isc/bitstring.h157
-rw-r--r--lib/isc/include/isc/boolean.h31
-rw-r--r--lib/isc/include/isc/buffer.h904
-rw-r--r--lib/isc/include/isc/bufferlist.h86
-rw-r--r--lib/isc/include/isc/commandline.h50
-rw-r--r--lib/isc/include/isc/entropy.h314
-rw-r--r--lib/isc/include/isc/error.h62
-rw-r--r--lib/isc/include/isc/event.h121
-rw-r--r--lib/isc/include/isc/eventclass.h53
-rw-r--r--lib/isc/include/isc/file.h256
-rw-r--r--lib/isc/include/isc/formatcheck.h40
-rw-r--r--lib/isc/include/isc/fsaccess.h178
-rw-r--r--lib/isc/include/isc/hash.h185
-rw-r--r--lib/isc/include/isc/heap.h170
-rw-r--r--lib/isc/include/isc/hex.h98
-rw-r--r--lib/isc/include/isc/hmacmd5.h63
-rw-r--r--lib/isc/include/isc/hmacsha.h156
-rw-r--r--lib/isc/include/isc/httpd.h64
-rw-r--r--lib/isc/include/isc/interfaceiter.h133
-rw-r--r--lib/isc/include/isc/ipv6.h148
-rw-r--r--lib/isc/include/isc/iterated_hash.h47
-rw-r--r--lib/isc/include/isc/lang.h33
-rw-r--r--lib/isc/include/isc/lex.h431
-rw-r--r--lib/isc/include/isc/lfsr.h130
-rw-r--r--lib/isc/include/isc/lib.h41
-rw-r--r--lib/isc/include/isc/list.h184
-rw-r--r--lib/isc/include/isc/log.h913
-rw-r--r--lib/isc/include/isc/magic.h41
-rw-r--r--lib/isc/include/isc/md5.h73
-rw-r--r--lib/isc/include/isc/mem.h626
-rw-r--r--lib/isc/include/isc/msgcat.h131
-rw-r--r--lib/isc/include/isc/msgs.h194
-rw-r--r--lib/isc/include/isc/mutexblock.h71
-rw-r--r--lib/isc/include/isc/netaddr.h180
-rw-r--r--lib/isc/include/isc/netscope.h43
-rw-r--r--lib/isc/include/isc/ondestroy.h116
-rw-r--r--lib/isc/include/isc/os.h38
-rw-r--r--lib/isc/include/isc/parseint.h64
-rw-r--r--lib/isc/include/isc/platform.h.in344
-rw-r--r--lib/isc/include/isc/portset.h141
-rw-r--r--lib/isc/include/isc/print.h87
-rw-r--r--lib/isc/include/isc/quota.h119
-rw-r--r--lib/isc/include/isc/radix.h181
-rw-r--r--lib/isc/include/isc/random.h62
-rw-r--r--lib/isc/include/isc/ratelimiter.h134
-rw-r--r--lib/isc/include/isc/refcount.h233
-rw-r--r--lib/isc/include/isc/region.h99
-rw-r--r--lib/isc/include/isc/resource.h97
-rw-r--r--lib/isc/include/isc/result.h107
-rw-r--r--lib/isc/include/isc/resultclass.h50
-rw-r--r--lib/isc/include/isc/rwlock.h135
-rw-r--r--lib/isc/include/isc/serial.h75
-rw-r--r--lib/isc/include/isc/sha1.h59
-rw-r--r--lib/isc/include/isc/sha2.h132
-rw-r--r--lib/isc/include/isc/sockaddr.h241
-rw-r--r--lib/isc/include/isc/socket.h925
-rw-r--r--lib/isc/include/isc/stdio.h77
-rw-r--r--lib/isc/include/isc/stdlib.h40
-rw-r--r--lib/isc/include/isc/string.h231
-rw-r--r--lib/isc/include/isc/symtab.h131
-rw-r--r--lib/isc/include/isc/task.h624
-rw-r--r--lib/isc/include/isc/taskpool.h105
-rw-r--r--lib/isc/include/isc/timer.h344
-rw-r--r--lib/isc/include/isc/types.h122
-rw-r--r--lib/isc/include/isc/util.h233
-rw-r--r--lib/isc/include/isc/version.h28
-rw-r--r--lib/isc/include/isc/xml.h41
-rw-r--r--lib/isc/inet_aton.c196
-rw-r--r--lib/isc/inet_ntop.c198
-rw-r--r--lib/isc/inet_pton.c214
-rw-r--r--lib/isc/iterated_hash.c46
-rw-r--r--lib/isc/lex.c959
-rw-r--r--lib/isc/lfsr.c161
-rw-r--r--lib/isc/lib.c79
-rw-r--r--lib/isc/log.c1761
-rw-r--r--lib/isc/md5.c251
-rw-r--r--lib/isc/mem.c2171
-rw-r--r--lib/isc/mips/Makefile.in24
-rw-r--r--lib/isc/mips/include/Makefile.in24
-rw-r--r--lib/isc/mips/include/isc/Makefile.in36
-rw-r--r--lib/isc/mips/include/isc/atomic.h98
-rw-r--r--lib/isc/mutexblock.c59
-rw-r--r--lib/isc/netaddr.c436
-rw-r--r--lib/isc/netscope.c76
-rw-r--r--lib/isc/nls/Makefile.in37
-rw-r--r--lib/isc/nls/msgcat.c131
-rw-r--r--lib/isc/noatomic/Makefile.in24
-rw-r--r--lib/isc/noatomic/include/Makefile.in24
-rw-r--r--lib/isc/noatomic/include/isc/Makefile.in36
-rw-r--r--lib/isc/noatomic/include/isc/atomic.h24
-rw-r--r--lib/isc/nothreads/Makefile.in38
-rw-r--r--lib/isc/nothreads/condition.c24
-rw-r--r--lib/isc/nothreads/include/Makefile.in25
-rw-r--r--lib/isc/nothreads/include/isc/Makefile.in37
-rw-r--r--lib/isc/nothreads/include/isc/condition.h59
-rw-r--r--lib/isc/nothreads/include/isc/mutex.h39
-rw-r--r--lib/isc/nothreads/include/isc/once.h32
-rw-r--r--lib/isc/nothreads/include/isc/thread.h35
-rw-r--r--lib/isc/nothreads/mutex.c25
-rw-r--r--lib/isc/nothreads/thread.c28
-rw-r--r--lib/isc/ondestroy.c85
-rw-r--r--lib/isc/parseint.c72
-rw-r--r--lib/isc/portset.c143
-rw-r--r--lib/isc/powerpc/Makefile.in24
-rw-r--r--lib/isc/powerpc/include/Makefile.in24
-rw-r--r--lib/isc/powerpc/include/isc/Makefile.in36
-rw-r--r--lib/isc/powerpc/include/isc/atomic.h160
-rw-r--r--lib/isc/print.c624
-rw-r--r--lib/isc/pthreads/Makefile.in38
-rw-r--r--lib/isc/pthreads/condition.c74
-rw-r--r--lib/isc/pthreads/include/Makefile.in25
-rw-r--r--lib/isc/pthreads/include/isc/Makefile.in37
-rw-r--r--lib/isc/pthreads/include/isc/condition.h65
-rw-r--r--lib/isc/pthreads/include/isc/mutex.h145
-rw-r--r--lib/isc/pthreads/include/isc/once.h50
-rw-r--r--lib/isc/pthreads/include/isc/thread.h60
-rw-r--r--lib/isc/pthreads/mutex.c272
-rw-r--r--lib/isc/pthreads/thread.c76
-rw-r--r--lib/isc/quota.c101
-rw-r--r--lib/isc/radix.c702
-rw-r--r--lib/isc/random.c104
-rw-r--r--lib/isc/ratelimiter.c328
-rw-r--r--lib/isc/refcount.c37
-rw-r--r--lib/isc/region.c45
-rw-r--r--lib/isc/result.c213
-rw-r--r--lib/isc/rwlock.c808
-rw-r--r--lib/isc/serial.c59
-rw-r--r--lib/isc/sha1.c315
-rw-r--r--lib/isc/sha2.c1234
-rw-r--r--lib/isc/sockaddr.c503
-rw-r--r--lib/isc/sparc64/Makefile.in24
-rw-r--r--lib/isc/sparc64/include/Makefile.in24
-rw-r--r--lib/isc/sparc64/include/isc/Makefile.in36
-rw-r--r--lib/isc/sparc64/include/isc/atomic.h127
-rw-r--r--lib/isc/string.c270
-rw-r--r--lib/isc/strtoul.c129
-rw-r--r--lib/isc/symtab.c252
-rw-r--r--lib/isc/task.c1376
-rw-r--r--lib/isc/task_p.h31
-rw-r--r--lib/isc/taskpool.c96
-rw-r--r--lib/isc/timer.c932
-rw-r--r--lib/isc/timer_p.h31
-rw-r--r--lib/isc/unix/Makefile.in51
-rw-r--r--lib/isc/unix/app.c684
-rw-r--r--lib/isc/unix/dir.c247
-rw-r--r--lib/isc/unix/entropy.c594
-rw-r--r--lib/isc/unix/errno2result.c123
-rw-r--r--lib/isc/unix/errno2result.h39
-rw-r--r--lib/isc/unix/file.c437
-rw-r--r--lib/isc/unix/fsaccess.c93
-rw-r--r--lib/isc/unix/ifiter_getifaddrs.c234
-rw-r--r--lib/isc/unix/ifiter_ioctl.c931
-rw-r--r--lib/isc/unix/ifiter_sysctl.c302
-rw-r--r--lib/isc/unix/include/Makefile.in25
-rw-r--r--lib/isc/unix/include/isc/Makefile.in38
-rw-r--r--lib/isc/unix/include/isc/dir.h94
-rw-r--r--lib/isc/unix/include/isc/int.h55
-rw-r--r--lib/isc/unix/include/isc/keyboard.h52
-rw-r--r--lib/isc/unix/include/isc/net.h365
-rw-r--r--lib/isc/unix/include/isc/netdb.h57
-rw-r--r--lib/isc/unix/include/isc/offset.h45
-rw-r--r--lib/isc/unix/include/isc/stat.h52
-rw-r--r--lib/isc/unix/include/isc/stdtime.h60
-rw-r--r--lib/isc/unix/include/isc/strerror.h45
-rw-r--r--lib/isc/unix/include/isc/syslog.h47
-rw-r--r--lib/isc/unix/include/isc/time.h334
-rw-r--r--lib/isc/unix/interfaceiter.c312
-rw-r--r--lib/isc/unix/ipv6.c27
-rw-r--r--lib/isc/unix/keyboard.c126
-rw-r--r--lib/isc/unix/net.c524
-rw-r--r--lib/isc/unix/os.c94
-rw-r--r--lib/isc/unix/resource.c227
-rw-r--r--lib/isc/unix/socket.c5362
-rw-r--r--lib/isc/unix/socket_p.h32
-rw-r--r--lib/isc/unix/stdio.c117
-rw-r--r--lib/isc/unix/stdtime.c86
-rw-r--r--lib/isc/unix/strerror.c74
-rw-r--r--lib/isc/unix/syslog.c84
-rw-r--r--lib/isc/unix/time.c438
-rw-r--r--lib/isc/version.c28
-rw-r--r--lib/isc/win32/DLLMain.c58
-rw-r--r--lib/isc/win32/Makefile.in40
-rw-r--r--lib/isc/win32/app.c260
-rw-r--r--lib/isc/win32/condition.c258
-rw-r--r--lib/isc/win32/dir.c312
-rw-r--r--lib/isc/win32/entropy.c307
-rw-r--r--lib/isc/win32/errno2result.c113
-rw-r--r--lib/isc/win32/errno2result.h40
-rw-r--r--lib/isc/win32/file.c507
-rw-r--r--lib/isc/win32/fsaccess.c375
-rw-r--r--lib/isc/win32/include/Makefile.in25
-rw-r--r--lib/isc/win32/include/isc/Makefile.in38
-rw-r--r--lib/isc/win32/include/isc/bind_registry.h50
-rw-r--r--lib/isc/win32/include/isc/bindevt.h91
-rw-r--r--lib/isc/win32/include/isc/condition.h67
-rw-r--r--lib/isc/win32/include/isc/dir.h83
-rw-r--r--lib/isc/win32/include/isc/int.h56
-rw-r--r--lib/isc/win32/include/isc/ipv6.h124
-rw-r--r--lib/isc/win32/include/isc/keyboard.h47
-rw-r--r--lib/isc/win32/include/isc/mutex.h55
-rw-r--r--lib/isc/win32/include/isc/net.h346
-rw-r--r--lib/isc/win32/include/isc/netdb.h54
-rw-r--r--lib/isc/win32/include/isc/ntgroups.h35
-rw-r--r--lib/isc/win32/include/isc/ntpaths.h71
-rw-r--r--lib/isc/win32/include/isc/offset.h44
-rw-r--r--lib/isc/win32/include/isc/once.h43
-rw-r--r--lib/isc/win32/include/isc/platform.h101
-rw-r--r--lib/isc/win32/include/isc/stat.h46
-rw-r--r--lib/isc/win32/include/isc/stdtime.h58
-rw-r--r--lib/isc/win32/include/isc/strerror.h42
-rw-r--r--lib/isc/win32/include/isc/syslog.h45
-rw-r--r--lib/isc/win32/include/isc/thread.h100
-rw-r--r--lib/isc/win32/include/isc/time.h291
-rw-r--r--lib/isc/win32/include/isc/win32os.h71
-rw-r--r--lib/isc/win32/interfaceiter.c500
-rw-r--r--lib/isc/win32/ipv6.c27
-rw-r--r--lib/isc/win32/keyboard.c89
-rw-r--r--lib/isc/win32/libisc.def542
-rw-r--r--lib/isc/win32/libisc.dsp780
-rw-r--r--lib/isc/win32/libisc.dsw29
-rw-r--r--lib/isc/win32/libisc.mak1974
-rw-r--r--lib/isc/win32/net.c332
-rw-r--r--lib/isc/win32/netdb.h187
-rw-r--r--lib/isc/win32/ntgroups.c186
-rw-r--r--lib/isc/win32/ntpaths.c140
-rw-r--r--lib/isc/win32/once.c54
-rw-r--r--lib/isc/win32/os.c45
-rw-r--r--lib/isc/win32/resource.c72
-rw-r--r--lib/isc/win32/socket.c3658
-rw-r--r--lib/isc/win32/stdio.c117
-rw-r--r--lib/isc/win32/stdtime.c37
-rw-r--r--lib/isc/win32/strerror.c459
-rw-r--r--lib/isc/win32/syslog.c181
-rw-r--r--lib/isc/win32/syslog.h76
-rw-r--r--lib/isc/win32/thread.c90
-rw-r--r--lib/isc/win32/time.c295
-rw-r--r--lib/isc/win32/unistd.h53
-rw-r--r--lib/isc/win32/version.c28
-rw-r--r--lib/isc/win32/win32os.c101
-rw-r--r--lib/isc/x86_32/Makefile.in24
-rw-r--r--lib/isc/x86_32/include/Makefile.in24
-rw-r--r--lib/isc/x86_32/include/isc/Makefile.in36
-rw-r--r--lib/isc/x86_32/include/isc/atomic.h176
-rw-r--r--lib/isc/x86_64/Makefile.in24
-rw-r--r--lib/isc/x86_64/include/Makefile.in24
-rw-r--r--lib/isc/x86_64/include/isc/Makefile.in36
-rw-r--r--lib/isc/x86_64/include/isc/atomic.h123
-rw-r--r--lib/isccc/Makefile.in86
-rw-r--r--lib/isccc/alist.c312
-rw-r--r--lib/isccc/api3
-rw-r--r--lib/isccc/base64.c78
-rw-r--r--lib/isccc/cc.c831
-rw-r--r--lib/isccc/ccmsg.c235
-rw-r--r--lib/isccc/include/Makefile.in25
-rw-r--r--lib/isccc/include/isccc/Makefile.in42
-rw-r--r--lib/isccc/include/isccc/alist.h87
-rw-r--r--lib/isccc/include/isccc/base64.h85
-rw-r--r--lib/isccc/include/isccc/cc.h122
-rw-r--r--lib/isccc/include/isccc/ccmsg.h148
-rw-r--r--lib/isccc/include/isccc/events.h50
-rw-r--r--lib/isccc/include/isccc/lib.h55
-rw-r--r--lib/isccc/include/isccc/result.h73
-rw-r--r--lib/isccc/include/isccc/sexpr.h124
-rw-r--r--lib/isccc/include/isccc/symtab.h135
-rw-r--r--lib/isccc/include/isccc/symtype.h44
-rw-r--r--lib/isccc/include/isccc/types.h59
-rw-r--r--lib/isccc/include/isccc/util.h225
-rw-r--r--lib/isccc/include/isccc/version.h28
-rw-r--r--lib/isccc/lib.c78
-rw-r--r--lib/isccc/result.c85
-rw-r--r--lib/isccc/sexpr.c325
-rw-r--r--lib/isccc/symtab.c293
-rw-r--r--lib/isccc/version.c28
-rw-r--r--lib/isccc/win32/DLLMain.c57
-rw-r--r--lib/isccc/win32/libisccc.def66
-rw-r--r--lib/isccc/win32/libisccc.dsp197
-rw-r--r--lib/isccc/win32/libisccc.dsw29
-rw-r--r--lib/isccc/win32/libisccc.mak540
-rw-r--r--lib/isccc/win32/version.c28
-rw-r--r--lib/isccfg/Makefile.in83
-rw-r--r--lib/isccfg/aclconf.c437
-rw-r--r--lib/isccfg/api3
-rw-r--r--lib/isccfg/include/Makefile.in25
-rw-r--r--lib/isccfg/include/isccfg/Makefile.in42
-rw-r--r--lib/isccfg/include/isccfg/aclconf.h75
-rw-r--r--lib/isccfg/include/isccfg/cfg.h425
-rw-r--r--lib/isccfg/include/isccfg/grammar.h454
-rw-r--r--lib/isccfg/include/isccfg/log.h55
-rw-r--r--lib/isccfg/include/isccfg/namedconf.h45
-rw-r--r--lib/isccfg/include/isccfg/version.h28
-rw-r--r--lib/isccfg/log.c52
-rw-r--r--lib/isccfg/namedconf.c2223
-rw-r--r--lib/isccfg/parser.c2406
-rw-r--r--lib/isccfg/version.c29
-rw-r--r--lib/isccfg/win32/DLLMain.c60
-rw-r--r--lib/isccfg/win32/libisccfg.def45
-rw-r--r--lib/isccfg/win32/libisccfg.dsp157
-rw-r--r--lib/isccfg/win32/libisccfg.dsw29
-rw-r--r--lib/isccfg/win32/libisccfg.mak466
-rw-r--r--lib/isccfg/win32/version.c29
-rw-r--r--lib/lwres/Makefile.in84
-rw-r--r--lib/lwres/api3
-rw-r--r--lib/lwres/assert_p.h35
-rw-r--r--lib/lwres/context.c482
-rw-r--r--lib/lwres/context_p.h65
-rw-r--r--lib/lwres/gai_strerror.c83
-rw-r--r--lib/lwres/getaddrinfo.c808
-rw-r--r--lib/lwres/gethost.c362
-rw-r--r--lib/lwres/getipnode.c1148
-rw-r--r--lib/lwres/getnameinfo.c346
-rw-r--r--lib/lwres/getrrset.c288
-rw-r--r--lib/lwres/herror.c122
-rw-r--r--lib/lwres/include/Makefile.in25
-rw-r--r--lib/lwres/include/lwres/Makefile.in46
-rw-r--r--lib/lwres/include/lwres/context.h129
-rw-r--r--lib/lwres/include/lwres/int.h34
-rw-r--r--lib/lwres/include/lwres/ipv6.h124
-rw-r--r--lib/lwres/include/lwres/lang.h33
-rw-r--r--lib/lwres/include/lwres/list.h121
-rw-r--r--lib/lwres/include/lwres/lwbuffer.h406
-rw-r--r--lib/lwres/include/lwres/lwpacket.h159
-rw-r--r--lib/lwres/include/lwres/lwres.h579
-rw-r--r--lib/lwres/include/lwres/netdb.h.in520
-rw-r--r--lib/lwres/include/lwres/platform.h.in120
-rw-r--r--lib/lwres/include/lwres/result.h42
-rw-r--r--lib/lwres/include/lwres/stdlib.h40
-rw-r--r--lib/lwres/include/lwres/version.h28
-rw-r--r--lib/lwres/lwbuffer.c361
-rw-r--r--lib/lwres/lwconfig.c725
-rw-r--r--lib/lwres/lwinetaton.c205
-rw-r--r--lib/lwres/lwinetntop.c197
-rw-r--r--lib/lwres/lwinetpton.c209
-rw-r--r--lib/lwres/lwpacket.c129
-rw-r--r--lib/lwres/lwres_gabn.c505
-rw-r--r--lib/lwres/lwres_gnba.c415
-rw-r--r--lib/lwres/lwres_grbn.c426
-rw-r--r--lib/lwres/lwres_noop.c342
-rw-r--r--lib/lwres/lwresutil.c576
-rw-r--r--lib/lwres/man/Makefile.in232
-rw-r--r--lib/lwres/man/lwres.3165
-rw-r--r--lib/lwres/man/lwres.docbook266
-rw-r--r--lib/lwres/man/lwres.html218
-rw-r--r--lib/lwres/man/lwres_buffer.3233
-rw-r--r--lib/lwres/man/lwres_buffer.docbook394
-rw-r--r--lib/lwres/man/lwres_buffer.html455
-rw-r--r--lib/lwres/man/lwres_config.3106
-rw-r--r--lib/lwres/man/lwres_config.docbook173
-rw-r--r--lib/lwres/man/lwres_config.html156
-rw-r--r--lib/lwres/man/lwres_context.3170
-rw-r--r--lib/lwres/man/lwres_context.docbook262
-rw-r--r--lib/lwres/man/lwres_context.html295
-rw-r--r--lib/lwres/man/lwres_gabn.3195
-rw-r--r--lib/lwres/man/lwres_gabn.docbook260
-rw-r--r--lib/lwres/man/lwres_gabn.html324
-rw-r--r--lib/lwres/man/lwres_gai_strerror.3129
-rw-r--r--lib/lwres/man/lwres_gai_strerror.docbook200
-rw-r--r--lib/lwres/man/lwres_gai_strerror.html124
-rw-r--r--lib/lwres/man/lwres_getaddrinfo.3246
-rw-r--r--lib/lwres/man/lwres_getaddrinfo.docbook387
-rw-r--r--lib/lwres/man/lwres_getaddrinfo.html322
-rw-r--r--lib/lwres/man/lwres_gethostent.3315
-rw-r--r--lib/lwres/man/lwres_gethostent.docbook439
-rw-r--r--lib/lwres/man/lwres_gethostent.html466
-rw-r--r--lib/lwres/man/lwres_getipnode.3206
-rw-r--r--lib/lwres/man/lwres_getipnode.docbook331
-rw-r--r--lib/lwres/man/lwres_getipnode.html279
-rw-r--r--lib/lwres/man/lwres_getnameinfo.3117
-rw-r--r--lib/lwres/man/lwres_getnameinfo.docbook205
-rw-r--r--lib/lwres/man/lwres_getnameinfo.html176
-rw-r--r--lib/lwres/man/lwres_getrrsetbyname.3164
-rw-r--r--lib/lwres/man/lwres_getrrsetbyname.docbook223
-rw-r--r--lib/lwres/man/lwres_getrrsetbyname.html192
-rw-r--r--lib/lwres/man/lwres_gnba.3183
-rw-r--r--lib/lwres/man/lwres_gnba.docbook261
-rw-r--r--lib/lwres/man/lwres_gnba.html316
-rw-r--r--lib/lwres/man/lwres_hstrerror.399
-rw-r--r--lib/lwres/man/lwres_hstrerror.docbook152
-rw-r--r--lib/lwres/man/lwres_hstrerror.html104
-rw-r--r--lib/lwres/man/lwres_inetntop.377
-rw-r--r--lib/lwres/man/lwres_inetntop.docbook120
-rw-r--r--lib/lwres/man/lwres_inetntop.html103
-rw-r--r--lib/lwres/man/lwres_noop.3183
-rw-r--r--lib/lwres/man/lwres_noop.docbook255
-rw-r--r--lib/lwres/man/lwres_noop.html317
-rw-r--r--lib/lwres/man/lwres_packet.3170
-rw-r--r--lib/lwres/man/lwres_packet.docbook291
-rw-r--r--lib/lwres/man/lwres_packet.html235
-rw-r--r--lib/lwres/man/lwres_resutil.3170
-rw-r--r--lib/lwres/man/lwres_resutil.docbook238
-rw-r--r--lib/lwres/man/lwres_resutil.html258
-rw-r--r--lib/lwres/print.c560
-rw-r--r--lib/lwres/print_p.h86
-rw-r--r--lib/lwres/strtoul.c135
-rw-r--r--lib/lwres/unix/Makefile.in25
-rw-r--r--lib/lwres/unix/include/Makefile.in25
-rw-r--r--lib/lwres/unix/include/lwres/Makefile.in34
-rw-r--r--lib/lwres/unix/include/lwres/net.h135
-rw-r--r--lib/lwres/version.c28
-rw-r--r--lib/lwres/win32/DLLMain.c58
-rw-r--r--lib/lwres/win32/Makefile.in25
-rw-r--r--lib/lwres/win32/include/Makefile.in25
-rw-r--r--lib/lwres/win32/include/lwres/Makefile.in34
-rw-r--r--lib/lwres/win32/include/lwres/int.h32
-rw-r--r--lib/lwres/win32/include/lwres/net.h164
-rw-r--r--lib/lwres/win32/include/lwres/netdb.h516
-rw-r--r--lib/lwres/win32/include/lwres/platform.h102
-rw-r--r--lib/lwres/win32/liblwres.def78
-rw-r--r--lib/lwres/win32/liblwres.dsp245
-rw-r--r--lib/lwres/win32/liblwres.dsw29
-rw-r--r--lib/lwres/win32/liblwres.mak774
-rw-r--r--lib/lwres/win32/lwconfig.c151
-rw-r--r--lib/lwres/win32/socket.c41
-rw-r--r--lib/lwres/win32/version.c28
-rw-r--r--lib/tests/Makefile.in56
-rw-r--r--lib/tests/T_testlist.imp3
-rw-r--r--lib/tests/include/Makefile.in25
-rw-r--r--lib/tests/include/tests/Makefile.in27
-rw-r--r--lib/tests/include/tests/t_api.h103
-rw-r--r--lib/tests/t_api.c801
-rw-r--r--lib/win32/bindevt/bindevt.c31
-rw-r--r--lib/win32/bindevt/bindevt.dsp132
-rw-r--r--lib/win32/bindevt/bindevt.dsw29
-rw-r--r--lib/win32/bindevt/bindevt.mak310
-rw-r--r--lib/win32/bindevt/bindevt.mc47
-rw-r--r--libtool.m46000
-rw-r--r--ltmain.sh6416
-rw-r--r--make/Makefile.in28
-rw-r--r--make/includes.in48
-rw-r--r--make/mkdep.in175
-rw-r--r--make/rules.in250
-rwxr-xr-xmkinstalldirs40
-rw-r--r--version10
-rw-r--r--win32utils/BINDBuild.dsw440
-rw-r--r--win32utils/BuildAll.bat123
-rw-r--r--win32utils/BuildOpenSSL.bat26
-rw-r--r--win32utils/BuildPost.bat28
-rw-r--r--win32utils/BuildSetup.bat107
-rw-r--r--win32utils/dnsheadergen.bat26
-rw-r--r--win32utils/index.html52
-rw-r--r--win32utils/makedefs.pl149
-rw-r--r--win32utils/makeversion.pl125
-rw-r--r--win32utils/readme1st.txt158
-rw-r--r--win32utils/updateopenssl.pl106
-rw-r--r--win32utils/win32-build.txt144
2300 files changed, 863368 insertions, 0 deletions
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..c7555ab
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,7974 @@
+
+ --- 9.6.0rc1 released ---
+
+2498. [bug] Removed a bogus function argument used with
+ ISC_SOCKET_USE_POLLWATCH: it could cause compiler
+ warning or crash named with the debug 1 level
+ of logging. [RT #18917]
+
+2497. [bug] Don't add RRSIG bit to NSEC3 bit map for insecure
+ delegation.
+
+2496. [bug] Add sanity length checks to NSID option. [RT #18813]
+
+2495. [bug] Tighten RRSIG checks. [RT #18795]
+
+2494. [bug] isc/radix.h, dns/sdlz.h and dns/dlz.h were not being
+ installed. [RT #18826]
+
+2493. [bug] The linux capabilities code was not correctly cleaning
+ up after itself. [RT #18767]
+
+2492. [func] Rndc status now reports the number of cpus discovered
+ and the number of worker threads when running
+ multi-threaded. [RT #18273]
+
+2491. [func] Attempt to re-use a local port if we are already using
+ the port. [RT #18548]
+
+2490. [port] aix: work around a kernel bug where IPV6_RECVPKTINFO
+ is cleared when IPV6_V6ONLY is set. [RT #18785]
+
+2489. [port] solaris: Workaround Solaris's kernel bug about
+ /dev/poll:
+ http://bugs.opensolaris.org/view_bug.do?bug_id=6724237
+ Define ISC_SOCKET_USE_POLLWATCH at build time to enable
+ this workaround. [RT #18870]
+
+2488. [func] Added a tool, dnssec-dsfromkey, to generate DS records
+ from keyset and .key files. [RT #18694]
+
+2487. [bug] Give TCP connections longer to complete. [RT #18675]
+
+2486. [func] The default locations for named.pid and lwresd.pid
+ are now /var/run/named/named.pid and
+ /var/run/lwresd/lwresd.pid respectively.
+
+ This allows the owner of the containing directory
+ to be set, for "named -u" support, and allows there
+ to be a permanent symbolic link in the path, for
+ "named -t" support. [RT #18306]
+
+2485. [bug] Change update's the handling of obscured RRSIG
+ records. Not all orphaned DS records were being
+ removed. [RT #18828]
+
+2484. [bug] It was possible to trigger a REQUIRE failure when
+ adding NSEC3 proofs to the response in
+ query_addwildcardproof(). [RT #18828]
+
+2483. [port] win32: chroot() is not supported. [RT #18805]
+
+2482. [port] libxml2: support versions 2.7.* in addition
+ to 2.6.*. [RT #18806]
+
+ --- 9.6.0b1 released ---
+
+2481. [bug] rbtdb.c:matchparams() failed to handle NSEC3 chain
+ collisions. [RT #18812]
+
+2480. [bug] named could fail to emit all the required NSEC3
+ records. [RT #18812]
+
+2479. [bug] xfrout:covers was not properly initialized. [RT #18801]
+
+2478. [bug] 'addresses' could be used uninitialized in
+ configure_forward(). [RT #18800]
+
+2477. [bug] dig: the global option to print the command line is
+ +cmd not print_cmd. Update the output to reflect
+ this. [RT #17008]
+
+2476. [doc] ARM: improve documentation for max-journal-size and
+ ixfr-from-differences. [RT #15909] [RT #18541]
+
+2475. [bug] LRU cache cleanup under overmem condition could purge
+ particular entries more aggressively. [RT #17628]
+
+2474. [bug] ACL structures could be allocated with insufficient
+ space, causing an array overrun. [RT #18765]
+
+2473. [port] linux: raise the limit on open files to the possible
+ maximum value before spawning threads; 'files'
+ specified in named.conf doesn't seem to work with
+ threads as expected. [RT #18784]
+
+2472. [port] linux: check the number of available cpu's before
+ calling chroot as it depends on "/proc". [RT #16923]
+
+2471. [bug] named-checkzone was not reporting missing mandatory
+ glue when sibling checks were disabled. [RT #18768]
+
+2470. [bug] Elements of the isc_radix_node_t could be incorrectly
+ overwritten. [RT# 18719]
+
+2469. [port] solaris: Work around Solaris's select() limitations.
+ [RT #18769]
+
+2468. [bug] Resolver could try unreachable servers multiple times.
+ [RT #18739]
+
+2467. [bug] Failure of fcntl(F_DUPFD) wasn't logged. [RT #18740]
+
+2466. [doc] ARM: explain max-cache-ttl 0 SERVFAIL issue.
+ [RT #18302]
+
+2465. [bug] Adb's handling of lame addresses was different
+ for IPv4 and IPv6. [RT #18738]
+
+2464. [port] linux: check that a capability is present before
+ trying to set it. [RT #18135]
+
+2463. [port] linux: POSIX doesn't include the IPv6 Advanced Socket
+ API and glibc hides parts of the IPv6 Advanced Socket
+ API as a result. This is stupid as it breaks how the
+ two halves (Basic and Advanced) of the IPv6 Socket API
+ were designed to be used but we have to live with it.
+ Define _GNU_SOURCE to pull in the IPv6 Advanced Socket
+ API. [RT #18388]
+
+2462. [doc] Document -m (enable memory usage debugging)
+ option for dig. [RT #18757]
+
+2461. [port] sunos: Change #2363 was not complete. [RT #17513]
+
+ --- 9.6.0a1 released ---
+
+2460. [bug] Don't call dns_db_getnsec3parameters() on the cache.
+ [RT #18697]
+
+2459. [contrib] Import dnssec-zkt to contrib/zkt. [RT #18448]
+
+2458. [doc] ARM: update and correction for max-cache-size.
+ [RT #18294]
+
+2457. [tuning] max-cache-size is reverted to 0, the previous
+ default. It should be safe because expired cache
+ entries are also purged. [RT #18684]
+
+2456. [bug] In ACLs, ::/0 and 0.0.0.0/0 would both match any
+ address, regardless of family. They now correctly
+ distinguish IPv4 from IPv6. [RT #18559]
+
+2455. [bug] Stop metadata being transferred via axfr/ixfr.
+ [RT #18639]
+
+2454. [func] nsupdate: you can now set a default ttl. [RT #18317]
+
+2453. [bug] Remove NULL pointer dereference in dns_journal_print().
+ [RT #18316]
+
+2452. [func] Improve bin/test/journalprint. [RT #18316]
+
+2451. [port] solaris: handle runtime linking better. [RT #18356]
+
+2450. [doc] Fix lwresd docbook problem for manual page.
+ [RT #18672]
+
+2449. [placeholder]
+
+2448. [func] Add NSEC3 support. [RT #15452]
+
+2447. [cleanup] libbind has been split out as a separate product.
+
+2446. [func] Add a new log message about build options on startup.
+ A new command-line option '-V' for named is also
+ provided to show this information. [RT# 18645]
+
+2445. [doc] ARM out-of-date on empty reverse zones (list includes
+ RFC1918 address, but these are not yet compiled in).
+ [RT #18578]
+
+2444. [port] Linux, FreeBSD, AIX: Turn off path mtu discovery
+ (clear DF) for UDP responses and requests.
+
+2443. [bug] win32: UDP connect() would not generate an event,
+ and so connected UDP sockets would never clean up.
+ Fix this by doing an immediate WSAConnect() rather
+ than an io completion port type for UDP.
+
+2442. [bug] A lock could be destroyed twice. [RT# 18626]
+
+2441. [bug] isc_radix_insert() could copy radix tree nodes
+ incompletely. [RT #18573]
+
+2440. [bug] named-checkconf used an incorrect test to determine
+ if an ACL was set to none.
+
+2439. [bug] Potential NULL dereference in dns_acl_isanyornone().
+ [RT #18559]
+
+2438. [bug] Timeouts could be logged incorrectly under win32.
+
+2437. [bug] Sockets could be closed too early, leading to
+ inconsistent states in the socket module. [RT #18298]
+
+2436. [security] win32: UDP client handler can be shutdown. [RT #18576]
+
+2435. [bug] Fixed an ACL memory leak affecting win32.
+
+2434. [bug] Fixed a minor error-reporting bug in
+ lib/isc/win32/socket.c.
+
+2433. [tuning] Set initial timeout to 800ms.
+
+2432. [bug] More Windows socket handling improvements. Stop
+ using I/O events and use IO Completion Ports
+ throughout. Rewrite the receive path logic to make
+ it easier to support multiple simultaneous
+ requesters in the future. Add stricter consistency
+ checking as a compile-time option (define
+ ISC_SOCKET_CONSISTENCY_CHECKS; defaults to off).
+
+2431. [bug] Acl processing could leak memory. [RT #18323]
+
+2430. [bug] win32: isc_interval_set() could round down to
+ zero if the input was less than NS_INTERVAL
+ nanoseconds. Round up instead. [RT #18549]
+
+2429. [doc] nsupdate should be in section 1 of the man pages.
+ [RT #18283]
+
+2428. [bug] dns_iptable_merge() mishandled merges of negative
+ tables. [RT #18409]
+
+2427. [func] Treat DNSKEY queries as if "minimal-response yes;"
+ was set. [RT #18528]
+
+2426. [bug] libbind: inet_net_pton() can sometimes return the
+ wrong value if excessively large net masks are
+ supplied. [RT #18512]
+
+2425. [bug] named didn't detect unavailable query source addresses
+ at load time. [RT #18536]
+
+2424. [port] configure now probes for a working epoll
+ implementation. Allow the use of kqueue,
+ epoll and /dev/poll to be selected at compile
+ time. [RT #18277]
+
+2423. [security] Randomize server selection on queries, so as to
+ make forgery a little more difficult. Instead of
+ always preferring the server with the lowest RTT,
+ pick a server with RTT within the same 128
+ millisecond band. [RT #18441]
+
+2422. [bug] Handle the special return value of a empty node as
+ if it was a NXRRSET in the validator. [RT #18447]
+
+2421. [func] Add new command line option '-S' for named to specify
+ the max number of sockets. [RT #18493]
+ Use caution: this option may not work for some
+ operating systems without rebuilding named.
+
+2420. [bug] Windows socket handling cleanup. Let the io
+ completion event send out canceled read/write
+ done events, which keeps us from writing to memory
+ we no longer have ownership of. Add debugging
+ socket_log() function. Rework TCP socket handling
+ to not leak sockets.
+
+2419. [cleanup] Document that isc_socket_create() and isc_socket_open()
+ should not be used for isc_sockettype_fdwatch sockets.
+ [RT #18521]
+
+2418. [bug] AXFR request on a DLZ could trigger a REQUIRE failure
+ [RT #18430]
+
+2417. [bug] Connecting UDP sockets for outgoing queries could
+ unexpectedly fail with an 'address already in use'
+ error. [RT #18411]
+
+2416. [func] Log file descriptors that cause exceeding the
+ internal maximum. [RT #18460]
+
+2415. [bug] 'rndc dumpdb' could trigger various assertion failures
+ in rbtdb.c. [RT #18455]
+
+2414. [bug] A masterdump context held the database lock too long,
+ causing various troubles such as dead lock and
+ recursive lock acquisition. [RT #18311, #18456]
+
+2413. [bug] Fixed an unreachable code path in socket.c. [RT #18442]
+
+2412. [bug] win32: address a resource leak. [RT #18374]
+
+2411. [bug] Allow using a larger number of sockets than FD_SETSIZE
+ for select(). To enable this, set ISC_SOCKET_MAXSOCKETS
+ at compilation time. [RT #18433]
+
+2410. [bug] Correctly delete m_versionInfo. [RT #18432]
+
+2409. [bug] Only log that we disabled EDNS processing if we were
+ subsequently successful. [RT #18029]
+
+2408. [bug] A duplicate TCP dispatch event could be sent, which
+ could then trigger an assertion failure in
+ resquery_response(). [RT #18275]
+
+2407. [port] hpux: test for sys/dyntune.h. [RT #18421]
+
+2406. [placeholder]
+
+2405. [cleanup] The default value for dnssec-validation was changed to
+ "yes" in 9.5.0-P1 and all subsequent releases; this
+ was inadvertently omitted from CHANGES at the time.
+
+2404. [port] hpux: files unlimited support.
+
+2403. [bug] TSIG context leak. [RT #18341]
+
+2402. [port] Support Solaris 2.11 and over. [RT #18362]
+
+2401. [bug] Expect to get E[MN]FILE errno internal_accept()
+ (from accept() or fcntl() system calls). [RT #18358]
+
+2400. [bug] Log if kqueue()/epoll_create()/open(/dev/poll) fails.
+ [RT #18297]
+
+2399. [placeholder]
+
+2398. [bug] Improve file descriptor management. New,
+ temporary, named.conf option reserved-sockets,
+ default 512. [RT #18344]
+
+2397. [bug] gssapi_functions had too many elements. [RT #18355]
+
+2396. [bug] Don't set SO_REUSEADDR for randomized ports.
+ [RT #18336]
+
+2395. [port] Avoid warning and no effect from "files unlimited"
+ on Linux when running as root. [RT #18335]
+
+2394. [bug] Default configuration options set the limit for
+ open files to 'unlimited' as described in the
+ documentation. [RT #18331]
+
+2393. [bug] nested acls containing keys could trigger an
+ assertion in acl.c. [RT #18166]
+
+2392. [bug] remove 'grep -q' from acl test script, some platforms
+ don't support it. [RT #18253]
+
+2391. [port] hpux: cover additional recvmsg() error codes.
+ [RT #18301]
+
+2390. [bug] dispatch.c could make a false warning on 'odd socket'.
+ [RT #18301].
+
+2389. [bug] Move the "working directory writable" check to after
+ the ns_os_changeuser() call. [RT #18326]
+
+2388. [bug] Avoid using tables for layout purposes in
+ statistics XSL [RT #18159].
+
+2387. [bug] Silence compiler warnings in lib/isc/radix.c.
+ [RT #18147] [RT #18258]
+
+2386. [func] Add warning about too small 'open files' limit.
+ [RT #18269]
+
+2385. [bug] A condition variable in socket.c could leak in
+ rare error handling [RT #17968].
+
+2384. [security] Fully randomize UDP query ports to improve
+ forgery resilience. [RT #17949, #18098]
+
+2383. [bug] named could double queries when they resulted in
+ SERVFAIL due to overkilling EDNS0 failure detection.
+ [RT #18182]
+
+2382. [doc] Add descriptions of DHCID, IPSECKEY, SPF and SSHFP
+ to ARM.
+
+2381. [port] dlz/mysql: support multiple install layouts for
+ mysql. <prefix>/include/{,mysql/}mysql.h and
+ <prefix>/lib/{,mysql/}. [RT #18152]
+
+2380. [bug] dns_view_find() was not returning NXDOMAIN/NXRRSET
+ proofs which, in turn, caused validation failures
+ for insecure zones immediately below a secure zone
+ the server was authoritative for. [RT #18112]
+
+2379. [contrib] queryperf/gen-data-queryperf.py: removed redundant
+ TLDs and supported RRs with TTLs [RT #17972]
+
+2378. [bug] gssapi_functions{} had a redundant member in BIND 9.5.
+ [RT #18169]
+
+2377. [bug] Address race condition in dnssec-signzone. [RT #18142]
+
+2376. [bug] Change #2144 was not complete.
+
+2375. [placeholder]
+
+2374. [bug] "blackhole" ACLs could cause named to segfault due
+ to some uninitialized memory. [RT #18095]
+
+2373. [bug] Default values of zone ACLs were re-parsed each time a
+ new zone was configured, causing an overconsumption
+ of memory. [RT #18092]
+
+2372. [bug] Fixed incorrect TAG_HMACSHA256_BITS value [RT #18047]
+
+2371. [doc] Add +nsid option to dig man page. [RT #18039]
+
+2370. [bug] "rndc freeze" could trigger an assertion in named
+ when called on a nonexistent zone. [RT #18050]
+
+2369. [bug] libbind: Array bounds overrun on read in bitncmp().
+ [RT #18054]
+
+2368. [port] Linux: use libcap for capability management if
+ possible. [RT# 18026]
+
+2367. [bug] Improve counting of dns_resstatscounter_retry
+ [RT #18030]
+
+2366. [bug] Adb shutdown race. [RT #18021]
+
+2365. [bug] Fix a bug that caused dns_acl_isany() to return
+ spurious results. [RT #18000]
+
+2364. [bug] named could trigger a assertion when serving a
+ malformed signed zone. [RT #17828]
+
+2363. [port] sunos: pre-set "lt_cv_sys_max_cmd_len=4096;".
+ [RT #17513]
+
+2362. [cleanup] Make "rrset-order fixed" a compile-time option.
+ settable by "./configure --enable-fixed-rrset".
+ Disabled by default. [RT #17977]
+
+2361. [bug] "recursion" statistics counter could be counted
+ multiple times for a single query. [RT #17990]
+
+2360. [bug] Fix a condition where we release a database version
+ (which may acquire a lock) while holding the lock.
+
+2359. [bug] Fix NSID bug. [RT #17942]
+
+2358. [doc] Update host's default query description. [RT #17934]
+
+2357. [port] Don't use OpenSSL's engine support in versions before
+ OpenSSL 0.9.7f. [RT #17922]
+
+2356. [bug] Built in mutex profiler was not scalable enough.
+ [RT #17436]
+
+2355. [func] Extend the number statistics counters available.
+ [RT #17590]
+
+2354. [bug] Failed to initialize some rdatasetheader_t elements.
+ [RT #17927]
+
+2353. [func] Add support for Name Server ID (RFC 5001).
+ 'dig +nsid' requests NSID from server.
+ 'request-nsid yes;' causes recursive server to send
+ NSID requests to upstream servers. Server responds
+ to NSID requests with the string configured by
+ 'server-id' option. [RT #17091]
+
+2352. [bug] Various GSS_API fixups. [RT #17729]
+
+2351. [bug] convertxsl.pl generated very long lines. [RT #17906]
+
+2350. [port] win32: IPv6 support. [RT #17797]
+
+2349. [func] Provide incremental re-signing support for secure
+ dynamic zones. [RT #1091]
+
+2348. [func] Use the EVP interface to OpenSSL. Add PKCS#11 support.
+ Documentation is in the new README.pkcs11 file.
+ [RT #16844]
+
+2347. [bug] Delete now traverses the RB tree in the canonical
+ order. [RT #17451]
+
+2346. [func] Memory statistics now cover all active memory contexts
+ in increased detail. [RT #17580]
+
+2345. [bug] named-checkconf failed to detect when forwarders
+ were set at both the options/view level and in
+ a root zone. [RT #17671]
+
+2344. [bug] Improve "logging{ file ...; };" documentation.
+ [RT #17888]
+
+2343. [bug] (Seemingly) duplicate IPv6 entries could be
+ created in ADB. [RT #17837]
+
+2342. [func] Use getifaddrs() if available under Linux. [RT #17224]
+
+2341. [bug] libbind: add missing -I../include for off source
+ tree builds. [RT #17606]
+
+2340. [port] openbsd: interface configuration. [RT #17700]
+
+2339. [port] tru64: support for libbind. [RT #17589]
+
+2338. [bug] check_ds() could be called with a non DS rdataset.
+ [RT #17598]
+
+2337. [bug] BUILD_LDFLAGS was not being correctly set. [RT #17614]
+
+2336. [func] If "named -6" is specified then listen on all IPv6
+ interfaces if there are not listen-on-v6 clauses in
+ named.conf. [RT #17581]
+
+2335. [port] sunos: libbind and *printf() support for long long.
+ [RT #17513]
+
+2334. [bug] Bad REQUIRES in fromstruct_in_naptr(), off by one
+ bug in fromstruct_txt(). [RT #17609]
+
+2333. [bug] Fix off by one error in isc_time_nowplusinterval().
+ [RT #17608]
+
+2332. [contrib] query-loc-0.4.0. [RT #17602]
+
+2331. [bug] Failure to regenerate any signatures was not being
+ reported nor being past back to the UPDATE client.
+ [RT #17570]
+
+2330. [bug] Remove potential race condition when handling
+ over memory events. [RT #17572]
+
+ WARNING: API CHANGE: over memory callback
+ function now needs to call isc_mem_waterack().
+ See <isc/mem.h> for details.
+
+2329. [bug] Clearer help text for dig's '-x' and '-i' options.
+
+2328. [maint] Add AAAA addresses for A.ROOT-SERVERS.NET,
+ F.ROOT-SERVERS.NET, H.ROOT-SERVERS.NET,
+ J.ROOT-SERVERS.NET, K.ROOT-SERVERS.NET and
+ M.ROOT-SERVERS.NET.
+
+2327. [bug] It was possible to dereference a NULL pointer in
+ rbtdb.c. Implement dead node processing in zones as
+ we do for caches. [RT #17312]
+
+2326. [bug] It was possible to trigger a INSIST in the acache
+ processing.
+
+2325. [port] Linux: use capset() function if available. [RT #17557]
+
+2324. [bug] Fix IPv6 matching against "any;". [RT #17533]
+
+2323. [port] tru64: namespace clash. [RT #17547]
+
+2322. [port] MacOS: work around the limitation of setrlimit()
+ for RLIMIT_NOFILE. [RT #17526]
+
+2321. [placeholder]
+
+2320. [func] Make statistics counters thread-safe for platforms
+ that support certain atomic operations. [RT #17466]
+
+2319. [bug] Silence Coverity warnings in
+ lib/dns/rdata/in_1/apl_42.c. [RT #17469]
+
+2318. [port] sunos fixes for libbind. [RT #17514]
+
+2317. [bug] "make distclean" removed bind9.xsl.h. [RT #17518]
+
+2316. [port] Missing #include <isc/print.h> in lib/dns/gssapictx.c.
+ [RT #17513]
+
+2315. [bug] Used incorrect address family for mapped IPv4
+ addresses in acl.c. [RT #17519]
+
+2314. [bug] Uninitialized memory use on error path in
+ bin/named/lwdnoop.c. [RT #17476]
+
+2313. [cleanup] Silence Coverity warnings. Handle private stacks.
+ [RT #17447] [RT #17478]
+
+2312. [cleanup] Silence Coverity warning in lib/isc/unix/socket.c.
+ [RT #17458]
+
+2311. [bug] IPv6 addresses could match IPv4 ACL entries and
+ vice versa. [RT #17462]
+
+2310. [bug] dig, host, nslookup: flush stdout before emitting
+ debug/fatal messages. [RT #17501]
+
+2309. [cleanup] Fix Coverity warnings in lib/dns/acl.c and iptable.c.
+ [RT #17455]
+
+2308. [cleanup] Silence Coverity warning in bin/named/controlconf.c.
+ [RT #17495]
+
+2307. [bug] Remove infinite loop from lib/dns/sdb.c. [RT #17496]
+
+2306. [bug] Remove potential race from lib/dns/resolver.c.
+ [RT #17470]
+
+2305. [security] inet_network() buffer overflow. CVE-2008-0122.
+
+2304. [bug] Check returns from all dns_rdata_tostruct() calls.
+ [RT #17460]
+
+2303. [bug] Remove unnecessary code from bin/named/lwdgnba.c.
+ [RT #17471]
+
+2302. [bug] Fix memset() calls in lib/tests/t_api.c. [RT #17472]
+
+2301. [bug] Remove resource leak and fix error messages in
+ bin/tests/system/lwresd/lwtest.c. [RT #17474]
+
+2300. [bug] Fixed failure to close open file in
+ bin/tests/names/t_names.c. [RT #17473]
+
+2299. [bug] Remove unnecessary NULL check in
+ bin/nsupdate/nsupdate.c. [RT #17475]
+
+2298. [bug] isc_mutex_lock() failure not caught in
+ bin/tests/timers/t_timers.c. [RT #17468]
+
+2297. [bug] isc_entropy_createfilesource() failure not caught in
+ bin/tests/dst/t_dst.c. [RT #17467]
+
+2296. [port] Allow docbook stylesheet location to be specified to
+ configure. [RT #17457]
+
+2295. [bug] Silence static overrun error in bin/named/lwaddr.c.
+ [RT #17459]
+
+2294. [func] Allow the experimental statistics channels to have
+ multiple connections and ACL.
+ Note: the stats-server and stats-server-v6 options
+ available in the previous beta releases are replaced
+ with the generic statistics-channels statement.
+
+2293. [func] Add ACL regression test. [RT #17375]
+
+2292. [bug] Log if the working directory is not writable.
+ [RT #17312]
+
+2291. [bug] PR_SET_DUMPABLE may be set too late. Also report
+ failure to set PR_SET_DUMPABLE. [RT #17312]
+
+2290. [bug] Let AD in the query signal that the client wants AD
+ set in the response. [RT #17301]
+
+2289. [func] named-checkzone now reports the out-of-zone CNAME
+ found. [RT #17309]
+
+2288. [port] win32: mark service as running when we have finished
+ loading. [RT #17441]
+
+2287. [bug] Use 'volatile' if the compiler supports it. [RT #17413]
+
+2286. [func] Allow a TCP connection to be used as a weak
+ authentication method for reverse zones.
+ New update-policy methods tcp-self and 6to4-self.
+ [RT #17378]
+
+2285. [func] Test framework for client memory context management.
+ [RT #17377]
+
+2284. [bug] Memory leak in UPDATE prerequisite processing.
+ [RT #17377]
+
+2283. [bug] TSIG keys were not attaching to the memory
+ context. TSIG keys should use the rings
+ memory context rather than the clients memory
+ context. [RT #17377]
+
+2282. [bug] Acl code fixups. [RT #17346] [RT #17374]
+
+2281. [bug] Attempts to use undefined acls were not being logged.
+ [RT #17307]
+
+2280. [func] Allow the experimental http server to be reached
+ over IPv6 as well as IPv4. [RT #17332]
+
+2279. [bug] Use setsockopt(SO_NOSIGPIPE), when available,
+ to protect applications from receiving spurious
+ SIGPIPE signals when using the resolver.
+
+2278. [bug] win32: handle the case where Windows returns no
+ search list or DNS suffix. [RT #17354]
+
+2277. [bug] Empty zone names were not correctly being caught at
+ in the post parse checks. [RT #17357]
+
+2276. [bug] Install <dst/gssapi.h>. [RT# 17359]
+
+2275. [func] Add support to dig to perform IXFR queries over UDP.
+ [RT #17235]
+
+2274. [func] Log zone transfer statistics. [RT #17336]
+
+2273. [bug] Adjust log level to WARNING when saving inconsistent
+ stub/slave master and journal files. [RT# 17279]
+
+2272. [bug] Handle illegal dnssec-lookaside trust-anchor names.
+ [RT #17262]
+
+2271. [bug] Fix a memory leak in http server code [RT #17100]
+
+2270. [bug] dns_db_closeversion() version->writer could be reset
+ before it is tested. [RT #17290]
+
+2269. [contrib] dbus memory leaks and missing va_end calls. [RT #17232]
+
+2268. [bug] 0.IN-ADDR.ARPA was missing from the empty zones
+ list.
+
+ --- 9.5.0b1 released ---
+
+2267. [bug] Radix tree node_num value could be set incorrectly,
+ causing positive ACL matches to look like negative
+ ones. [RT #17311]
+
+2266. [bug] client.c:get_clientmctx() returned the same mctx
+ once the pool of mctx's was filled. [RT #17218]
+
+2265. [bug] Test that the memory context's basic_table is non NULL
+ before freeing. [RT #17265]
+
+2264. [bug] Server prefix length was being ignored. [RT #17308]
+
+2263. [bug] "named-checkconf -z" failed to set default value
+ for "check-integrity". [RT #17306]
+
+2262. [bug] Error status from all but the last view could be
+ lost. [RT #17292]
+
+2261. [bug] Fix memory leak with "any" and "none" ACLs [RT #17272]
+
+2260. [bug] Reported wrong clients-per-query when increasing the
+ value. [RT #17236]
+
+2259. [placeholder]
+
+ --- 9.5.0a7 released ---
+
+2258. [bug] Fallback from IXFR/TSIG to SOA/AXFR/TSIG broken.
+ [RT #17241]
+
+2257. [bug] win32: Use the full path to vcredist_x86.exe when
+ calling it. [RT #17222]
+
+2256. [bug] win32: Correctly register the installation location of
+ bindevt.dll. [RT #17159]
+
+2255. [maint] L.ROOT-SERVERS.NET is now 199.7.83.42.
+
+2254. [bug] timer.c:dispatch() failed to lock timer->lock
+ when reading timer->idle allowing it to see
+ intermediate values as timer->idle was reset by
+ isc_timer_touch(). [RT #17243]
+
+2253. [func] "max-cache-size" defaults to 32M.
+ "max-acache-size" defaults to 16M.
+
+2252. [bug] Fixed errors in sortlist code [RT #17216]
+
+2251. [placeholder]
+
+2250. [func] New flag 'memstatistics' to state whether the
+ memory statistics file should be written or not.
+ Additionally named's -m option will cause the
+ statistics file to be written. [RT #17113]
+
+2249. [bug] Only set Authentic Data bit if client requested
+ DNSSEC, per RFC 3655 [RT #17175]
+
+2248. [cleanup] Fix several errors reported by Coverity. [RT #17160]
+
+2247. [doc] Sort doc/misc/options. [RT #17067]
+
+2246. [bug] Make the startup of test servers (ans.pl) more
+ robust. [RT #17147]
+
+2245. [bug] Validating lack of DS records at trust anchors wasn't
+ working. [RT #17151]
+
+2244. [func] Allow the check of nameserver names against the
+ SOA MNAME field to be disabled by specifying
+ 'notify-to-soa yes;'. [RT #17073]
+
+2243. [func] Configuration files without a newline at the end now
+ parse without error. [RT #17120]
+
+2242. [bug] nsupdate: GSS-TSIG support using the Heimdal Kerberos
+ library could require a source of random data.
+ [RT #17127]
+
+2241. [func] nsupdate: add a interactive 'help' command. [RT #17099]
+
+2240. [bug] Cleanup nsupdates GSS-TSIG support. Convert
+ a number of INSIST()s into plain fatal() errors
+ which report the triggering result code.
+ The 'key' command wasn't disabling GSS-TSIG.
+ [RT #17099]
+
+2239. [func] Ship a pre built bin/named/bind9.xsl.h. [RT #17114]
+
+2238. [bug] It was possible to trigger a REQUIRE when a
+ validation was canceled. [RT #17106]
+
+2237. [bug] libbind: res_init() was not thread aware. [RT #17123]
+
+2236. [bug] dnssec-signzone failed to preserve the case of
+ of wildcard owner names. [RT #17085]
+
+2235. [bug] <isc/atomic.h> was not being installed. [RT #17135]
+
+2234. [port] Correct some compiler warnings on SCO OSr5 [RT #17134]
+
+2233. [func] Add support for O(1) ACL processing, based on
+ radix tree code originally written by Kevin
+ Brintnall. [RT #16288]
+
+2232. [bug] dns_adb_findaddrinfo() could fail and return
+ ISC_R_SUCCESS. [RT #17137]
+
+2231. [bug] Building dlzbdb (contrib/dlz/bin/dlzbdb) was broken.
+ [RT #17088]
+
+2230. [bug] We could INSIST reading a corrupted journal.
+ [RT #17132]
+
+2229. [bug] Null pointer dereference on query pool creation
+ failure. [RT #17133]
+
+2228. [contrib] contrib: Change 2188 was incomplete.
+
+2227. [cleanup] Tidied up the FAQ. [RT #17121]
+
+2226. [placeholder]
+
+2225. [bug] More support for systems with no IPv4 addresses.
+ [RT #17111]
+
+2224. [bug] Defer journal compaction if a xfrin is in progress.
+ [RT #17119]
+
+2223. [bug] Make a new journal when compacting. [RT #17119]
+
+2222. [func] named-checkconf now checks server key references.
+ [RT #17097]
+
+2221. [bug] Set the event result code to reflect the actual
+ record turned to caller when a cache update is
+ rejected due to a more credible answer existing.
+ [RT #17017]
+
+2220. [bug] win32: Address a race condition in final shutdown of
+ the Windows socket code. [RT #17028]
+
+2219. [bug] Apply zone consistency checks to additions, not
+ removals, when updating. [RT #17049]
+
+2218. [bug] Remove unnecessary REQUIRE from dns_validator_create().
+ [RT #16976]
+
+2217. [func] Adjust update log levels. [RT #17092]
+
+2216. [cleanup] Fix a number of errors reported by Coverity.
+ [RT #17094]
+
+2215. [bug] Bad REQUIRE check isc_hmacsha1_verify(). [RT #17094]
+
+2214. [bug] Deregister OpenSSL lock callback when cleaning
+ up. Reorder OpenSSL cleanup so that RAND_cleanup()
+ is called before the locks are destroyed. [RT #17098]
+
+2213. [bug] SIG0 diagnostic failure messages were looking at the
+ wrong status code. [RT #17101]
+
+2212. [func] 'host -m' now causes memory statistics and active
+ memory to be printed at exit. [RT 17028]
+
+2211. [func] Update "dynamic update temporarily disabled" message.
+ [RT #17065]
+
+2210. [bug] Deleting class specific records via UPDATE could
+ fail. [RT #17074]
+
+2209. [port] osx: linking against user supplied static OpenSSL
+ libraries failed as the system ones were still being
+ found. [RT #17078]
+
+2208. [port] win32: make sure both build methods produce the
+ same output. [RT #17058]
+
+2207. [port] Some implementations of getaddrinfo() fail to set
+ ai_canonname correctly. [RT #17061]
+
+ --- 9.5.0a6 released ---
+
+2206. [security] "allow-query-cache" and "allow-recursion" now
+ cross inherit from each other.
+
+ If allow-query-cache is not set in named.conf then
+ allow-recursion is used if set, otherwise allow-query
+ is used if set, otherwise the default (localnets;
+ localhost;) is used.
+
+ If allow-recursion is not set in named.conf then
+ allow-query-cache is used if set, otherwise allow-query
+ is used if set, otherwise the default (localnets;
+ localhost;) is used.
+
+ [RT #16987]
+
+2205. [bug] libbind: change #2119 broke thread support. [RT #16982]
+
+2204. [bug] "rndc flushanme name unknown-view" caused named
+ to crash. [RT #16984]
+
+2203. [security] Query id generation was cryptographically weak.
+ [RT # 16915]
+
+2202. [security] The default acls for allow-query-cache and
+ allow-recursion were not being applied. [RT #16960]
+
+2201. [bug] The build failed in a separate object directory.
+ [RT #16943]
+
+2200. [bug] The search for cached NSEC records was stopping to
+ early leading to excessive DLV queries. [RT #16930]
+
+2199. [bug] win32: don't call WSAStartup() while loading dlls.
+ [RT #16911]
+
+2198. [bug] win32: RegCloseKey() could be called when
+ RegOpenKeyEx() failed. [RT #16911]
+
+2197. [bug] Add INSIST to catch negative responses which are
+ not setting the event result code appropriately.
+ [RT #16909]
+
+2196. [port] win32: yield processor while waiting for once to
+ to complete. [RT #16958]
+
+2195. [func] dnssec-keygen now defaults to nametype "ZONE"
+ when generating DNSKEYs. [RT #16954]
+
+2194. [bug] Close journal before calling 'done' in xfrin.c.
+
+ --- 9.5.0a5 released ---
+
+2193. [port] win32: BINDInstall.exe is now linked statically.
+ [RT #16906]
+
+2192. [port] win32: use vcredist_x86.exe to install Visual
+ Studio's redistributable dlls if building with
+ Visual Stdio 2005 or later.
+
+2191. [func] named-checkzone now allows dumping to stdout (-).
+ named-checkconf now has -h for help.
+ named-checkzone now has -h for help.
+ rndc now has -h for help.
+ Better handling of '-?' for usage summaries.
+ [RT #16707]
+
+2190. [func] Make fallback to plain DNS from EDNS due to timeouts
+ more visible. New logging category "edns-disabled".
+ [RT #16871]
+
+2189. [bug] Handle socket() returning EINTR. [RT #15949]
+
+2188. [contrib] queryperf: autoconf changes to make the search for
+ libresolv or libbind more robust. [RT #16299]
+
+2187. [bug] query_addds(), query_addwildcardproof() and
+ query_addnxrrsetnsec() should take a version
+ argument. [RT #16368]
+
+2186. [port] cygwin: libbind: check for struct sockaddr_storage
+ independently of IPv6. [RT #16482]
+
+2185. [port] sunos: libbind: check for ssize_t, memmove() and
+ memchr(). [RT #16463]
+
+2184. [bug] bind9.xsl.h didn't build out of the source tree.
+ [RT #16830]
+
+2183. [bug] dnssec-signzone didn't handle offline private keys
+ well. [RT #16832]
+
+2182. [bug] dns_dispatch_createtcp() and dispatch_createudp()
+ could return ISC_R_SUCCESS when they ran out of
+ memory. [RT #16365]
+
+2181. [port] sunos: libbind: add paths.h from BIND 8. [RT #16462]
+
+2180. [cleanup] Remove bit test from 'compress_test' as they
+ are no longer needed. [RT #16497]
+
+2179. [func] 'rndc command zone' will now find 'zone' if it is
+ unique to all the views. [RT #16821]
+
+2178. [bug] 'rndc reload' of a slave or stub zone resulted in
+ a reference leak. [RT #16867]
+
+2177. [bug] Array bounds overrun on read (rcodetext) at
+ debug level 10+. [RT #16798]
+
+2176. [contrib] dbus update to handle race condition during
+ initialization (Bugzilla 235809). [RT #16842]
+
+2175. [bug] win32: windows broadcast condition variable support
+ was broken. [RT #16592]
+
+2174. [bug] I/O errors should always be fatal when reading
+ master files. [RT #16825]
+
+2173. [port] win32: When compiling with MSVS 2005 SP1 we also
+ need to ship Microsoft.VC80.MFCLOC.
+
+ --- 9.5.0a4 released ---
+
+2172. [bug] query_addsoa() was being called with a non zone db.
+ [RT #16834]
+
+2171. [bug] Handle breaks in DNSSEC trust chains where the parent
+ servers are not DS aware (DS queries to the parent
+ return a referral to the child).
+
+2170. [func] Add acache processing to test suite. [RT #16711]
+
+2169. [bug] host, nslookup: when reporting NXDOMAIN report the
+ given name and not the last name searched for.
+ [RT #16763]
+
+2168. [bug] nsupdate: in non-interactive mode treat syntax errors
+ as fatal errors. [RT #16785]
+
+2167. [bug] When re-using a automatic zone named failed to
+ attach it to the new view. [RT #16786]
+
+ --- 9.5.0a3 released ---
+
+2166. [bug] When running in batch mode, dig could misinterpret
+ a server address as a name to be looked up, causing
+ unexpected output. [RT #16743]
+
+2165. [func] Allow the destination address of a query to determine
+ if we will answer the query or recurse.
+ allow-query-on, allow-recursion-on and
+ allow-query-cache-on. [RT #16291]
+
+2164. [bug] The code to determine how named-checkzone /
+ named-compilezone was called failed under windows.
+ [RT #16764]
+
+2163. [bug] If only one of query-source and query-source-v6
+ specified a port the query pools code broke (change
+ 2129). [RT #16768]
+
+2162. [func] Allow "rrset-order fixed" to be disabled at compile
+ time. [RT #16665]
+
+2161. [bug] Fix which log messages are emitted for 'rndc flush'.
+ [RT #16698]
+
+2160. [bug] libisc wasn't handling NULL ifa_addr pointers returned
+ from getifaddrs(). [RT #16708]
+
+ --- 9.5.0a2 released ---
+
+2159. [bug] Array bounds overrun in acache processing. [RT #16710]
+
+2158. [bug] ns_client_isself() failed to initialize key
+ leading to a REQUIRE failure. [RT #16688]
+
+2157. [func] dns_db_transfernode() created. [RT #16685]
+
+2156. [bug] Fix node reference leaks in lookup.c:lookup_find(),
+ resolver.c:validated() and resolver.c:cache_name().
+ Fix a memory leak in rbtdb.c:free_noqname().
+ Make lookup.c:lookup_find() robust against
+ event leaks. [RT #16685]
+
+2155. [contrib] SQLite sdb module from jaboydjr@netwalk.com.
+ [RT #16694]
+
+2154. [func] Scoped (e.g. IPv6 link-local) addresses may now be
+ matched in acls by omitting the scope. [RT #16599]
+
+2153. [bug] nsupdate could leak memory. [RT #16691]
+
+2152. [cleanup] Use sizeof(buf) instead of fixed number in
+ dighost.c:get_trusted_key(). [RT #16678]
+
+2151. [bug] Missing newline in usage message for journalprint.
+ [RT #16679]
+
+2150. [bug] 'rrset-order cyclic' uniformly distribute the
+ starting point for the first response for a given
+ RRset. [RT #16655]
+
+2149. [bug] isc_mem_checkdestroyed() failed to abort on
+ if there were still active memory contexts.
+ [RT #16672]
+
+2148. [func] Add positive logging for rndc commands. [RT #14623]
+
+2147. [bug] libbind: remove potential buffer overflow from
+ hmac_link.c. [RT #16437]
+
+2146. [cleanup] Silence Linux's spurious "obsolete setsockopt
+ SO_BSDCOMPAT" message. [RT #16641]
+
+2145. [bug] Check DS/DLV digest lengths for known digests.
+ [RT #16622]
+
+2144. [cleanup] Suppress logging of SERVFAIL from forwarders.
+ [RT #16619]
+
+2143. [bug] We failed to restart the IPv6 client when the
+ kernel failed to return the destination the
+ packet was sent to. [RT #16613]
+
+2142. [bug] Handle master files with a modification time that
+ matches the epoch. [RT# 16612]
+
+2141. [bug] dig/host should not be setting IDN_ASCCHECK (IDN
+ equivalent of LDH checks). [RT #16609]
+
+2140. [bug] libbind: missing unlock on pthread_key_create()
+ failures. [RT #16654]
+
+2139. [bug] dns_view_find() was being called with wrong type
+ in adb.c. [RT #16670]
+
+2138. [bug] Lock order reversal in resolver.c. [RT #16653]
+
+2137. [port] Mips little endian and/or mips 64 bit are now
+ supported for atomic operations. [RT#16648]
+
+2136. [bug] nslookup/host looped if there was no search list
+ and the host didn't exist. [RT #16657]
+
+2135. [bug] Uninitialized rdataset in sdlz.c. [RT# 16656]
+
+2134. [func] Additional statistics support. [RT #16666]
+
+2133. [port] powerpc: Support both IBM and MacOS Power PC
+ assembler syntaxes. [RT #16647]
+
+2132. [bug] Missing unlock on out of memory in
+ dns_dispatchmgr_setudp().
+
+2131. [contrib] dlz/mysql: AXFR was broken. [RT #16630]
+
+2130. [func] Log if CD or DO were set. [RT #16640]
+
+2129. [func] Provide a pool of UDP sockets for queries to be
+ made over. See use-queryport-pool, queryport-pool-ports
+ and queryport-pool-updateinterval. [RT #16415]
+
+2128. [doc] xsltproc --nonet, update DTD versions. [RT #16635]
+
+2127. [port] Improved OpenSSL 0.9.8 support. [RT #16563]
+
+2126. [security] Serialize validation of type ANY responses. [RT #16555]
+
+2125. [bug] dns_zone_getzeronosoattl() REQUIRE failure if DLZ
+ was defined. [RT #16574]
+
+2124. [security] It was possible to dereference a freed fetch
+ context. [RT #16584]
+
+ --- 9.5.0a1 released ---
+
+2123. [func] Use Doxygen to generate internal documentation.
+ [RT #11398]
+
+2122. [func] Experimental http server and statistics support
+ for named via xml.
+
+2121. [func] Add a 10 slot dead masters cache (LRU) with a 600
+ second timeout. [RT #16553]
+
+2120. [doc] Fix markup on nsupdate man page. [RT #16556]
+
+2119. [compat] libbind: allow res_init() to succeed enough to
+ return the default domain even if it was unable
+ to allocate memory.
+
+2118. [bug] Handle response with long chains of domain name
+ compression pointers which point to other compression
+ pointers. [RT #16427]
+
+2117. [bug] DNSSEC fixes: named could fail to cache NSEC records
+ which could lead to validation failures. named didn't
+ handle negative DS responses that were in the process
+ of being validated. Check CNAME bit before accepting
+ NODATA proof. To be able to ignore a child NSEC there
+ must be SOA (and NS) set in the bitmap. [RT #16399]
+
+2116. [bug] 'rndc reload' could cause the cache to continually
+ be cleaned. [RT #16401]
+
+2115. [bug] 'rndc reconfig' could trigger a INSIST if the
+ number of masters for a zone was reduced. [RT #16444]
+
+2114. [bug] dig/host/nslookup: searches for names with multiple
+ labels were failing. [RT #16447]
+
+2113. [bug] nsupdate: if a zone is specified it should be used
+ for server discover. [RT# 16455]
+
+2112. [security] Warn if weak RSA exponent is used. [RT #16460]
+
+2111. [bug] Fix a number of errors reported by Coverity.
+ [RT #16507]
+
+2110. [bug] "minimal-responses yes;" interacted badly with BIND 8
+ priming queries. [RT #16491]
+
+2109. [port] libbind: silence aix 5.3 compiler warnings. [RT #16502]
+
+2108. [func] DHCID support. [RT #16456]
+
+2107. [bug] dighost.c: more cleanup of buffers. [RT #16499]
+
+2106. [func] 'rndc status' now reports named's version. [RT #16426]
+
+2105. [func] GSS-TSIG support (RFC 3645).
+
+2104. [port] Fix Solaris SMF error message.
+
+2103. [port] Add /usr/sfw to list of locations for OpenSSL
+ under Solaris.
+
+2102. [port] Silence Solaris 10 warnings.
+
+2101. [bug] OpenSSL version checks were not quite right.
+ [RT #16476]
+
+2100. [port] win32: copy libeay32.dll to Build\Debug.
+ Copy Debug\named-checkzone to Debug\named-compilezone.
+
+2099. [port] win32: more manifest issues.
+
+2098. [bug] Race in rbtdb.c:no_references(), which occasionally
+ triggered an INSIST failure about the node lock
+ reference. [RT #16411]
+
+2097. [bug] named could reference a destroyed memory context
+ after being reloaded / reconfigured. [RT #16428]
+
+2096. [bug] libbind: handle applications that fail to detect
+ res_init() failures better.
+
+2095. [port] libbind: alway prototype inet_cidr_ntop_ipv6() and
+ net_cidr_ntop_ipv6(). [RT #16388]
+
+2094. [contrib] Update named-bootconf. [RT# 16404]
+
+2093. [bug] named-checkzone -s was broken.
+
+2092. [bug] win32: dig, host, nslookup. Use registry config
+ if resolv.conf does not exist or no nameservers
+ listed. [RT #15877]
+
+2091. [port] dighost.c: race condition on cleanup. [RT #16417]
+
+2090. [port] win32: Visual C++ 2005 command line manifest support.
+ [RT #16417]
+
+2089. [security] Raise the minimum safe OpenSSL versions to
+ OpenSSL 0.9.7l and OpenSSL 0.9.8d. Versions
+ prior to these have known security flaws which
+ are (potentially) exploitable in named. [RT #16391]
+
+2088. [security] Change the default RSA exponent from 3 to 65537.
+ [RT #16391]
+
+2087. [port] libisc failed to compile on OS's w/o a vsnprintf.
+ [RT #16382]
+
+2086. [port] libbind: FreeBSD now has get*by*_r() functions.
+ [RT #16403]
+
+2085. [doc] win32: added index.html and README to zip. [RT #16201]
+
+2084. [contrib] dbus update for 9.3.3rc2.
+
+2083. [port] win32: Visual C++ 2005 support.
+
+2082. [doc] Document 'cache-file' as a test only option.
+
+2081. [port] libbind: minor 64-bit portability fix in memcluster.c.
+ [RT #16360]
+
+2080. [port] libbind: res_init.c did not compile on older versions
+ of Solaris. [RT #16363]
+
+2079. [bug] The lame cache was not handling multiple types
+ correctly. [RT #16361]
+
+2078. [bug] dnssec-checkzone output style "default" was badly
+ named. It is now called "relative". [RT #16326]
+
+2077. [bug] 'dnssec-signzone -O raw' wasn't outputting the
+ complete signed zone. [RT #16326]
+
+2076. [bug] Several files were missing #include <config.h>
+ causing build failures on OSF. [RT #16341]
+
+2075. [bug] The spillat timer event hander could leak memory.
+ [RT #16357]
+
+2074. [bug] dns_request_createvia2(), dns_request_createvia3(),
+ dns_request_createraw2() and dns_request_createraw3()
+ failed to send multiple UDP requests. [RT #16349]
+
+2073. [bug] Incorrect semantics check for update policy "wildcard".
+ [RT #16353]
+
+2072. [bug] We were not generating valid HMAC SHA digests.
+ [RT #16320]
+
+2071. [port] Test whether gcc accepts -fno-strict-aliasing.
+ [RT #16324]
+
+2070. [bug] The remote address was not always displayed when
+ reporting dispatch failures. [RT #16315]
+
+2069. [bug] Cross compiling was not working. [RT #16330]
+
+2068. [cleanup] Lower incremental tuning message to debug 1.
+ [RT #16319]
+
+2067. [bug] 'rndc' could close the socket too early triggering
+ a INSIST under Windows. [RT #16317]
+
+2066. [security] Handle SIG queries gracefully. [RT #16300]
+
+2065. [bug] libbind: probe for HPUX prototypes for
+ endprotoent_r() and endservent_r(). [RT 16313]
+
+2064. [bug] libbind: silence AIX compiler warnings. [RT #16218]
+
+2063. [bug] Change #1955 introduced a bug which caused the first
+ 'rndc flush' call to not free memory. [RT #16244]
+
+2062. [bug] 'dig +nssearch' was reusing a buffer before it had
+ been returned by the socket code. [RT #16307]
+
+2061. [bug] Accept expired wildcard message reversed. [RT #16296]
+
+2060. [bug] Enabling DLZ support could leave views partially
+ configured. [RT #16295]
+
+2059. [bug] Search into cache rbtdb could trigger an INSIST
+ failure while cleaning up a stale rdataset.
+ [RT #16292]
+
+2058. [bug] Adjust how we calculate rtt estimates in the presence
+ of authoritative servers that drop EDNS and/or CD
+ requests. Also fallback to EDNS/512 and plain DNS
+ faster for zones with less than 3 servers. [RT #16187]
+
+2057. [bug] Make setting "ra" dependent on both allow-query-cache
+ and allow-recursion. [RT #16290]
+
+2056. [bug] dig: ixfr= was not being treated case insensitively
+ at all times. [RT #15955]
+
+2055. [bug] Missing goto after dropping multicast query.
+ [RT #15944]
+
+2054. [port] freebsd: do not explicitly link against -lpthread.
+ [RT #16170]
+
+2053. [port] netbsd:libbind: silence compiler warnings. [RT #16220]
+
+2052. [bug] 'rndc' improve connect failed message to report
+ the failing address. [RT #15978]
+
+2051. [port] More strtol() fixes. [RT #16249]
+
+2050. [bug] Parsing of NSAP records was not case insensitive.
+ [RT #16287]
+
+2049. [bug] Restore SOA before AXFR when falling back from
+ a attempted IXFR when transferring in a zone.
+ Allow a initial SOA query before attempting
+ a AXFR to be requested. [RT #16156]
+
+2048. [bug] It was possible to loop forever when using
+ avoid-v4-udp-ports / avoid-v6-udp-ports when
+ the OS always returned the same local port.
+ [RT #16182]
+
+2047. [bug] Failed to initialize the interface flags to zero.
+ [RT #16245]
+
+2046. [bug] rbtdb.c:rdataset_setadditional() could cause duplicate
+ cleanup [RT #16247].
+
+2045. [func] Use lock buckets for acache entries to limit memory
+ consumption. [RT #16183]
+
+2044. [port] Add support for atomic operations for Itanium.
+ [RT #16179]
+
+2043. [port] nsupdate/nslookup: Force the flushing of the prompt
+ for interactive sessions. [RT#16148]
+
+2042. [bug] named-checkconf was incorrectly rejecting the
+ logging category "config". [RT #16117]
+
+2041. [bug] "configure --with-dlz-bdb=yes" produced a bad
+ set of libraries to be linked. [RT #16129]
+
+2040. [bug] rbtdb no_references() could trigger an INSIST
+ failure with --enable-atomic. [RT #16022]
+
+2039. [func] Check that all buffers passed to the socket code
+ have been retrieved when the socket event is freed.
+ [RT #16122]
+
+2038. [bug] dig/nslookup/host was unlinking from wrong list
+ when handling errors. [RT #16122]
+
+2037. [func] When unlinking the first or last element in a list
+ check that the list head points to the element to
+ be unlinked. [RT #15959]
+
+2036. [bug] 'rndc recursing' could cause trigger a REQUIRE.
+ [RT #16075]
+
+2035. [func] Make falling back to TCP on UDP refresh failure
+ optional. Default "try-tcp-refresh yes;" for BIND 8
+ compatibility. [RT #16123]
+
+2034. [bug] gcc: set -fno-strict-aliasing. [RT #16124]
+
+2033. [bug] We weren't creating multiple client memory contexts
+ on demand as expected. [RT #16095]
+
+2032. [bug] Remove a INSIST in query_addadditional2(). [RT #16074]
+
+2031. [bug] Emit a error message when "rndc refresh" is called on
+ a non slave/stub zone. [RT # 16073]
+
+2030. [bug] We were being overly conservative when disabling
+ openssl engine support. [RT #16030]
+
+2029. [bug] host printed out the server multiple times when
+ specified on the command line. [RT #15992]
+
+2028. [port] linux: socket.c compatibility for old systems.
+ [RT #16015]
+
+2027. [port] libbind: Solaris x86 support. [RT #16020]
+
+2026. [bug] Rate limit the two recursive client exceeded messages.
+ [RT #16044]
+
+2025. [func] Update "zone serial unchanged" message. [RT #16026]
+
+2024. [bug] named emitted spurious "zone serial unchanged"
+ messages on reload. [RT #16027]
+
+2023. [bug] "make install" should create ${localstatedir}/run and
+ ${sysconfdir} if they do not exist. [RT #16033]
+
+2022. [bug] If dnssec validation is disabled only assert CD if
+ CD was requested. [RT #16037]
+
+2021. [bug] dnssec-enable no; triggered a REQUIRE. [RT #16037]
+
+2020. [bug] rdataset_setadditional() could leak memory. [RT #16034]
+
+2019. [tuning] Reduce the amount of work performed per quantum
+ when cleaning the cache. [RT #15986]
+
+2018. [bug] Checking if the HMAC MD5 private file was broken.
+ [RT #15960]
+
+2017. [bug] allow-query default was not correct. [RT #15946]
+
+2016. [bug] Return a partial answer if recursion is not
+ allowed but requested and we had the answer
+ to the original qname. [RT #15945]
+
+2015. [cleanup] use-additional-cache is now acache-enable for
+ consistency. Default acache-enable off in BIND 9.4
+ as it requires memory usage to be configured.
+ It may be enabled by default in BIND 9.5 once we
+ have more experience with it.
+
+2014. [func] Statistics about acache now recorded and sent
+ to log. [RT #15976]
+
+2013. [bug] Handle unexpected TSIGs on unsigned AXFR/IXFR
+ responses more gracefully. [RT #15941]
+
+2012. [func] Don't insert new acache entries if acache is full.
+ [RT #15970]
+
+2011. [func] dnssec-signzone can now update the SOA record of
+ the signed zone, either as an increment or as the
+ system time(). [RT #15633]
+
+2010. [placeholder] rt15958
+
+2009. [bug] libbind: Coverity fixes. [RT #15808]
+
+2008. [func] It is now possible to enable/disable DNSSEC
+ validation from rndc. This is useful for the
+ mobile hosts where the current connection point
+ breaks DNSSEC (firewall/proxy). [RT #15592]
+
+ rndc validation newstate [view]
+
+2007. [func] It is now possible to explicitly enable DNSSEC
+ validation. default dnssec-validation no; to
+ be changed to yes in 9.5.0. [RT #15674]
+
+2006. [security] Allow-query-cache and allow-recursion now default
+ to the built in acls "localnets" and "localhost".
+
+ This is being done to make caching servers less
+ attractive as reflective amplifying targets for
+ spoofed traffic. This still leave authoritative
+ servers exposed.
+
+ The best fix is for full BCP 38 deployment to
+ remove spoofed traffic.
+
+2005. [bug] libbind: Retransmission timeouts should be
+ based on which attempt it is to the nameserver
+ and not the nameserver itself. [RT #13548]
+
+2004. [bug] dns_tsig_sign() could pass a NULL pointer to
+ dst_context_destroy() when cleaning up after a
+ error. [RT #15835]
+
+2003. [bug] libbind: The DNS name/address lookup functions could
+ occasionally follow a random pointer due to
+ structures not being completely zeroed. [RT #15806]
+
+2002. [bug] libbind: tighten the constraints on when
+ struct addrinfo._ai_pad exists. [RT #15783]
+
+2001. [func] Check the KSK flag when updating a secure dynamic zone.
+ New zone option "update-check-ksk yes;". [RT #15817]
+
+2000. [bug] memmove()/strtol() fix was incomplete. [RT #15812]
+
+1999. [func] Implement "rrset-order fixed". [RT #13662]
+
+1998. [bug] Restrict handling of fifos as sockets to just SunOS.
+ This allows named to connect to entropy gathering
+ daemons that use fifos instead of sockets. [RT #15840]
+
+1997. [bug] Named was failing to replace negative cache entries
+ when a positive one for the type was learnt.
+ [RT #15818]
+
+1996. [bug] nsupdate: if a zone has been specified it should
+ appear in the output of 'show'. [RT #15797]
+
+1995. [bug] 'host' was reporting multiple "is an alias" messages.
+ [RT #15702]
+
+1994. [port] OpenSSL 0.9.8 support. [RT #15694]
+
+1993. [bug] Log messages, via syslog, were missing the space
+ after the timestamp if "print-time yes" was specified.
+ [RT #15844]
+
+1992. [bug] Not all incoming zone transfer messages included the
+ view. [RT #15825]
+
+1991. [cleanup] The configuration data, once read, should be treated
+ as read only. Expand the use of const to enforce this
+ at compile time. [RT #15813]
+
+1990. [bug] libbind: isc's override of broken gettimeofday()
+ implementations was not always effective.
+ [RT #15709]
+
+1989. [bug] win32: don't check the service password when
+ re-installing. [RT #15882]
+
+1988. [bug] Remove a bus error from the SHA256/SHA512 support.
+ [RT #15878]
+
+1987. [func] DS/DLV SHA256 digest algorithm support. [RT #15608]
+
+1986. [func] Report when a zone is removed. [RT #15849]
+
+1985. [protocol] DLV has now been assigned a official type code of
+ 32769. [RT #15807]
+
+ Note: care should be taken to ensure you upgrade
+ both named and dnssec-signzone at the same time for
+ zones with DLV records where named is the master
+ server for the zone. Also any zones that contain
+ DLV records should be removed when upgrading a slave
+ zone. You do not however have to upgrade all
+ servers for a zone with DLV records simultaneously.
+
+1984. [func] dig, nslookup and host now advertise a 4096 byte
+ EDNS UDP buffer size by default. [RT #15855]
+
+1983. [func] Two new update policies. "selfsub" and "selfwild".
+ [RT #12895]
+
+1982. [bug] DNSKEY was being accepted on the parent side of
+ a delegation. KEY is still accepted there for
+ RFC 3007 validated updates. [RT #15620]
+
+1981. [bug] win32: condition.c:wait() could fail to reattain
+ the mutex lock.
+
+1980. [func] dnssec-signzone: output the SOA record as the
+ first record in the signed zone. [RT #15758]
+
+1979. [port] linux: allow named to drop core after changing
+ user ids. [RT #15753]
+
+1978. [port] Handle systems which have a broken recvmsg().
+ [RT #15742]
+
+1977. [bug] Silence noisy log message. [RT #15704]
+
+1976. [bug] Handle systems with no IPv4 addresses. [RT #15695]
+
+1975. [bug] libbind: isc_gethexstring() could misparse multi-line
+ hex strings with comments. [RT #15814]
+
+1974. [doc] List each of the zone types and associated zone
+ options separately in the ARM.
+
+1973. [func] TSIG HMACSHA1, HMACSHA224, HMACSHA256, HMACSHA384 and
+ HMACSHA512 support. [RT #13606]
+
+1972. [contrib] DBUS dynamic forwarders integration from
+ Jason Vas Dias <jvdias@redhat.com>.
+
+1971. [port] linux: make detection of missing IF_NAMESIZE more
+ robust. [RT #15443]
+
+1970. [bug] nsupdate: adjust UDP timeout when falling back to
+ unsigned SOA query. [RT #15775]
+
+1969. [bug] win32: the socket code was freeing the socket
+ structure too early. [RT #15776]
+
+1968. [bug] Missing lock in resolver.c:validated(). [RT #15739]
+
+1967. [func] dig/nslookup/host: warn about missing "QR". [RT #15779]
+
+1966. [bug] Don't set CD when we have fallen back to plain DNS.
+ [RT #15727]
+
+1965. [func] Suppress spurious "recursion requested but not
+ available" warning with 'dig +qr'. [RT #15780].
+
+1964. [func] Separate out MX and SRV to CNAME checks. [RT #15723]
+
+1963. [port] Tru64 4.0E doesn't support send() and recv().
+ [RT #15586]
+
+1962. [bug] Named failed to clear old update-policy when it
+ was removed. [RT #15491]
+
+1961. [bug] Check the port and address of responses forwarded
+ to dispatch. [RT #15474]
+
+1960. [bug] Update code should set NSEC ttls from SOA MINIMUM.
+ [RT #15465]
+
+1959. [func] Control the zeroing of the negative response TTL to
+ a soa query. Defaults "zero-no-soa-ttl yes;" and
+ "zero-no-soa-ttl-cache no;". [RT #15460]
+
+1958. [bug] Named failed to update the zone's secure state
+ until the zone was reloaded. [RT #15412]
+
+1957. [bug] Dig mishandled responses to class ANY queries.
+ [RT #15402]
+
+1956. [bug] Improve cross compile support, 'gen' is now built
+ by native compiler. See README for additional
+ cross compile support information. [RT #15148]
+
+1955. [bug] Pre-allocate the cache cleaning iterator. [RT #14998]
+
+1954. [func] Named now falls back to advertising EDNS with a
+ 512 byte receive buffer if the initial EDNS queries
+ fail. [RT #14852]
+
+1953. [func] The maximum EDNS UDP response named will send can
+ now be set in named.conf (max-udp-size). This is
+ independent of the advertised receive buffer
+ (edns-udp-size). [RT #14852]
+
+1952. [port] hpux: tell the linker to build a runtime link
+ path "-Wl,+b:". [RT #14816].
+
+1951. [security] Drop queries from particular well known ports.
+ Don't return FORMERR to queries from particular
+ well known ports. [RT #15636]
+
+1950. [port] Solaris 2.5.1 and earlier cannot bind() then connect()
+ a TCP socket. This prevents the source address being
+ set for TCP connections. [RT #15628]
+
+1949. [func] Addition memory leakage checks. [RT #15544]
+
+1948. [bug] If was possible to trigger a REQUIRE failure in
+ xfrin.c:maybe_free() if named ran out of memory.
+ [RT #15568]
+
+1947. [func] It is now possible to configure named to accept
+ expired RRSIGs. Default "dnssec-accept-expired no;".
+ Setting "dnssec-accept-expired yes;" leaves named
+ vulnerable to replay attacks. [RT #14685]
+
+1946. [bug] resume_dslookup() could trigger a REQUIRE failure
+ when using forwarders. [RT #15549]
+
+1945. [cleanup] dnssec-keygen: RSA (RSAMD5) is no longer recommended.
+ To generate a RSAMD5 key you must explicitly request
+ RSAMD5. [RT #13780]
+
+1944. [cleanup] isc_hash_create() does not need a read/write lock.
+ [RT #15522]
+
+1943. [bug] Set the loadtime after rolling forward the journal.
+ [RT #15647]
+
+1942. [bug] If the name of a DNSKEY match that of one in
+ trusted-keys do not attempt to validate the DNSKEY
+ using the parents DS RRset. [RT #15649]
+
+1941. [bug] ncache_adderesult() should set eresult even if no
+ rdataset is passed to it. [RT #15642]
+
+1940. [bug] Fixed a number of error conditions reported by
+ Coverity.
+
+1939. [bug] The resolver could dereference a null pointer after
+ validation if all the queries have timed out.
+ [RT #15528]
+
+1938. [bug] The validator was not correctly handling unsecure
+ negative responses at or below a SEP. [RT #15528]
+
+1937. [bug] sdlz doesn't handle RRSIG records. [RT #15564]
+
+1936. [bug] The validator could leak memory. [RT #15544]
+
+1935. [bug] 'acache' was DO sensitive. [RT #15430]
+
+1934. [func] Validate pending NS RRsets, in the authority section,
+ prior to returning them if it can be done without
+ requiring DNSKEYs to be fetched. [RT #15430]
+
+1933. [bug] dump_rdataset_raw() had a incorrect INSIST. [RT #15534]
+
+1932. [bug] hpux: LDFLAGS was getting corrupted. [RT #15530]
+
+1931. [bug] Per-client mctx could require a huge amount of memory,
+ particularly for a busy caching server. [RT #15519]
+
+1930. [port] HPUX: ia64 support. [RT #15473]
+
+1929. [port] FreeBSD: extend use of PTHREAD_SCOPE_SYSTEM.
+
+1928. [bug] Race in rbtdb.c:currentversion(). [RT #15517]
+
+1927. [bug] Access to soanode or nsnode in rbtdb violated the
+ lock order rule and could cause a dead lock.
+ [RT# 15518]
+
+1926. [bug] The Windows installer did not check for empty
+ passwords. BINDinstall was being installed in
+ the wrong place. [RT #15483]
+
+1925. [port] All outer level AC_TRY_RUNs need cross compiling
+ defaults. [RT #15469]
+
+1924. [port] libbind: hpux ia64 support. [RT #15473]
+
+1923. [bug] ns_client_detach() called too early. [RT #15499]
+
+1922. [bug] check-tool.c:setup_logging() missing call to
+ dns_log_setcontext().
+
+1921. [bug] Client memory contexts were not using internal
+ malloc. [RT# 15434]
+
+1920. [bug] The cache rbtdb lock array was too small to
+ have the desired performance characteristics.
+ [RT #15454]
+
+1919. [contrib] queryperf: a set of new features: collecting/printing
+ response delays, printing intermediate results, and
+ adjusting query rate for the "target" qps.
+
+1918. [bug] Memory leak when checking acls. [RT #15391]
+
+1917. [doc] funcsynopsisinfo wasn't being treated as verbatim
+ when generating man pages. [RT #15385]
+
+1916. [func] Integrate contributed IDN code from JPNIC. [RT #15383]
+
+1915. [bug] dig +ndots was broken. [RT #15215]
+
+1914. [protocol] DS is required to accept mnemonic algorithms
+ (RFC 4034). Still emit numeric algorithms for
+ compatibility with RFC 3658. [RT #15354]
+
+1913. [func] Integrate contributed DLZ code into named. [RT #11382]
+
+1912. [port] aix: atomic locking for powerpc. [RT #15020]
+
+1911. [bug] Update windows socket code. [RT #14965]
+
+1910. [bug] dig's +sigchase code overhauled. [RT #14933]
+
+1909. [bug] The DLV code has been re-worked to make no longer
+ query order sensitive. [RT #14933]
+
+1908. [func] 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. [RT #15005]
+
+1907. [func] host/nslookup now continue (default)/fail on SERVFAIL.
+ [RT #15006]
+
+1906. [func] dig now has a '-q queryname' and '+showsearch' options.
+ [RT #15034]
+
+1905. [bug] Strings returned from cfg_obj_asstring() should be
+ treated as read-only. The prototype for
+ cfg_obj_asstring() has been updated to reflect this.
+ [RT #15256]
+
+1904. [func] 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.
+
+1903. [func] ISC string copy API.
+
+1902. [func] 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.
+ [RT #14996]
+
+1901. [cleanup] Don't add DNSKEY records to the additional section.
+
+1900. [bug] ixfr-from-differences failed to ensure that the
+ serial number increased. [RT #15036]
+
+1899. [func] named-checkconf now validates update-policy entries.
+ [RT #14963]
+
+1898. [bug] Extend ISC_SOCKADDR_FORMATSIZE and
+ ISC_NETADDR_FORMATSIZE to allow for scope details.
+
+1897. [func] x86 and x86_64 now have separate atomic locking
+ implementations.
+
+1896. [bug] Recursive clients soft quota support wasn't working
+ as expected. [RT #15103]
+
+1895. [bug] A escaped character is, potentially, converted to
+ the output character set too early. [RT #14666]
+
+1894. [doc] Review ARM for BIND 9.4.
+
+1893. [port] Use uintptr_t if available. [RT #14606]
+
+1892. [func] Support for SPF rdata type. [RT #15033]
+
+1891. [port] freebsd: pthread_mutex_init can fail if it runs out
+ of memory. [RT #14995]
+
+1890. [func] Raise the UDP receive buffer size to 32k if it is
+ less than 32k. [RT #14953]
+
+1889. [port] sunos: non blocking i/o support. [RT #14951]
+
+1888. [func] Support for IPSECKEY rdata type. [RT #14967]
+
+1887. [bug] The cache could delete expired records too fast for
+ clients with a virtual time in the past. [RT #14991]
+
+1886. [bug] fctx_create() could return success even though it
+ failed. [RT #14993]
+
+1885. [func] dig: report the number of extra bytes still left in
+ the packet after processing all the records.
+
+1884. [cleanup] dighost.c: move external declarations into <dig/dig.h>.
+
+1883. [bug] dnssec-signzone, dnssec-keygen: handle negative debug
+ levels. [RT #14962]
+
+1882. [func] Limit the number of recursive clients that can be
+ waiting for a single query (<qname,qtype,qclass>) to
+ resolve. New options clients-per-query and
+ max-clients-per-query.
+
+1881. [func] Add a system test for named-checkconf. [RT #14931]
+
+1880. [func] The lame cache is now done on a <qname,qclass,qtype>
+ basis as some servers only appear to be lame for
+ certain query types. [RT #14916]
+
+1879. [func] "USE INTERNAL MALLOC" is now runtime selectable.
+ [RT #14892]
+
+1878. [func] Detect duplicates of UDP queries we are recursing on
+ and drop them. New stats category "duplicate".
+ [RT #2471]
+
+1877. [bug] Fix unreasonably low quantum on call to
+ dns_rbt_destroy2(). Remove unnecessary unhash_node()
+ call. [RT #14919]
+
+1876. [func] Additional memory debugging support to track size
+ and mctx arguments. [RT #14814]
+
+1875. [bug] process_dhtkey() was using the wrong memory context
+ to free some memory. [RT #14890]
+
+1874. [port] sunos: portability fixes. [RT #14814]
+
+1873. [port] win32: isc__errno2result() now reports its caller.
+ [RT #13753]
+
+1872. [port] win32: Handle ERROR_NETNAME_DELETED. [RT #13753]
+
+1871. [placeholder]
+
+1870. [func] Added framework for handling multiple EDNS versions.
+ [RT #14873]
+
+1869. [func] dig can now specify the EDNS version when making
+ a query. [RT #14873]
+
+1868. [func] edns-udp-size can now be overridden on a per
+ server basis. [RT #14851]
+
+1867. [bug] It was possible to trigger a INSIST in
+ dlv_validatezonekey(). [RT #14846]
+
+1866. [bug] resolv.conf parse errors were being ignored by
+ dig/host/nslookup. [RT #14841]
+
+1865. [bug] Silently ignore nameservers in /etc/resolv.conf with
+ bad addresses. [RT #14841]
+
+1864. [bug] Don't try the alternative transfer source if you
+ got a answer / transfer with the main source
+ address. [RT #14802]
+
+1863. [bug] rrset-order "fixed" error messages not complete.
+
+1862. [func] 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.
+ [RT #4940]
+
+1861. [bug] dig could trigger a INSIST on certain malformed
+ responses. [RT #14801]
+
+1860. [port] solaris 2.8: hack_shutup_pthreadmutexinit was
+ incorrectly set. [RT #14775]
+
+1859. [func] Add support for CH A record. [RT #14695]
+
+1858. [bug] The flush-zones-on-shutdown option wasn't being
+ parsed. [RT #14686]
+
+1857. [bug] named could trigger a INSIST() if reconfigured /
+ reloaded too fast. [RT #14673]
+
+1856. [doc] Switch Docbook toolchain from DSSSL to XSL.
+ [RT #11398]
+
+1855. [bug] ixfr-from-differences was failing to detect changes
+ of ttl due to dns_diff_subtract() was ignoring the ttl
+ of records. [RT #14616]
+
+1854. [bug] lwres also needs to know the print format for
+ (long long). [RT #13754]
+
+1853. [bug] Rework how DLV interacts with proveunsecure().
+ [RT #13605]
+
+1852. [cleanup] Remove last vestiges of dnssec-signkey and
+ dnssec-makekeyset (removed from Makefile years ago).
+
+1851. [doc] Doxygen comment markup. [RT #11398]
+
+1850. [bug] Memory leak in lwres_getipnodebyaddr(). [RT #14591]
+
+1849. [doc] All forms of the man pages (docbook, man, html) should
+ have consistent copyright dates.
+
+1848. [bug] Improve SMF integration. [RT #13238]
+
+1847. [bug] isc_ondestroy_init() is called too late in
+ dns_rbtdb_create()/dns_rbtdb64_create().
+ [RT #13661]
+
+1846. [contrib] query-loc-0.3.0 from Stephane Bortzmeyer
+ <bortzmeyer@nic.fr>.
+
+1845. [bug] Improve error reporting to distinguish between
+ accept()/fcntl() and socket()/fcntl() errors.
+ [RT #13745]
+
+1844. [bug] inet_pton() accepted more that 4 hexadecimal digits
+ for each 16 bit piece of the IPv6 address. The text
+ representation of a IPv6 address has been tightened
+ to disallow this (draft-ietf-ipv6-addr-arch-v4-02.txt).
+ [RT #5662]
+
+1843. [cleanup] CINCLUDES takes precedence over CFLAGS. This helps
+ when CFLAGS contains "-I /usr/local/include"
+ resulting in old header files being used.
+
+1842. [port] cmsg_len() could produce incorrect results on
+ some platform. [RT #13744]
+
+1841. [bug] "dig +nssearch" now makes a recursive query to
+ find the list of nameservers to query. [RT #13694]
+
+1840. [func] dnssec-signzone can now randomize signature end times
+ (dnssec-signzone -j jitter). [RT #13609]
+
+1839. [bug] <isc/hash.h> was not being installed.
+
+1838. [cleanup] Don't allow Linux capabilities to be inherited.
+ [RT #13707]
+
+1837. [bug] Compile time option ISC_FACILITY was not effective
+ for 'named -u <user>'. [RT #13714]
+
+1836. [cleanup] Silence compiler warnings in hash_test.c.
+
+1835. [bug] Update dnssec-signzone's usage message. [RT #13657]
+
+1834. [bug] Bad memset in rdata_test.c. [RT #13658]
+
+1833. [bug] Race condition in isc_mutex_lock_profile(). [RT #13660]
+
+1832. [bug] named fails to return BADKEY on unknown TSIG algorithm.
+ [RT #13620]
+
+1831. [doc] Update named-checkzone documentation. [RT#13604]
+
+1830. [bug] adb lame cache has sence of test reversed. [RT #13600]
+
+1829. [bug] win32: "pid-file none;" broken. [RT #13563]
+
+1828. [bug] isc_rwlock_init() failed to properly cleanup if it
+ encountered a error. [RT #13549]
+
+1827. [bug] host: update usage message for '-a'. [RT #37116]
+
+1826. [bug] Missing DESTROYLOCK() in isc_mem_createx() on out
+ of memory error. [RT #13537]
+
+1825. [bug] Missing UNLOCK() on out of memory error from in
+ rbtdb.c:subtractrdataset(). [RT #13519]
+
+1824. [bug] Memory leak on dns_zone_setdbtype() failure.
+ [RT #13510]
+
+1823. [bug] Wrong macro used to check for point to point interface.
+ [RT#13418]
+
+1822. [bug] check-names test for RT was reversed. [RT #13382]
+
+1821. [placeholder]
+
+1820. [bug] Gracefully handle acl loops. [RT #13659]
+
+1819. [bug] The validator needed to check both the algorithm and
+ digest types of the DS to determine if it could be
+ used to introduce a secure zone. [RT #13593]
+
+1818. [bug] 'named-checkconf -z' triggered an INSIST. [RT #13599]
+
+1817. [func] 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.
+
+1816. [port] UnixWare: failed to compile lib/isc/unix/net.c.
+ [RT #13597]
+
+1815. [bug] nsupdate triggered a REQUIRE if the server was set
+ without also setting the zone and it encountered
+ a CNAME and was using TSIG. [RT #13086]
+
+1814. [func] UNIX domain controls are now supported.
+
+1813. [func] 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.
+
+1812. [port] win32: IN6_IS_ADDR_UNSPECIFIED macro is incorrect.
+ [RT #13453]
+
+1811. [func] Preserve the case of domain names in rdata during
+ zone transfers. [RT #13547]
+
+1810. [bug] configure, lib/bind/configure make different default
+ decisions about whether to do a threaded build.
+ [RT #13212]
+
+1809. [bug] "make distclean" failed for libbind if the platform
+ is not supported.
+
+1808. [bug] zone.c:notify_zone() contained a race condition,
+ zone->db could change underneath it. [RT #13511]
+
+1807. [bug] When forwarding (forward only) set the active domain
+ from the forward zone name. [RT #13526]
+
+1806. [bug] The resolver returned the wrong result when a CNAME /
+ DNAME was encountered when fetching glue from a
+ secure namespace. [RT #13501]
+
+1805. [bug] Pending status was not being cleared when DLV was
+ active. [RT #13501]
+
+1804. [bug] Ensure that if we are queried for glue that it fits
+ in the additional section or TC is set to tell the
+ client to retry using TCP. [RT #10114]
+
+1803. [bug] dnssec-signzone sometimes failed to remove old
+ RRSIGs. [RT #13483]
+
+1802. [bug] Handle connection resets better. [RT #11280]
+
+1801. [func] Report differences between hints and real NS rrset
+ and associated address records.
+
+1800. [bug] Changes #1719 allowed a INSIST to be triggered.
+ [RT #13428]
+
+1799. [bug] 'rndc flushname' failed to flush negative cache
+ entries. [RT #13438]
+
+1798. [func] The server syntax has been extended to support a
+ range of servers. [RT #11132]
+
+1797. [func] named-checkconf now check acls to verify that they
+ only refer to existing acls. [RT #13101]
+
+1796. [func] "rndc freeze/thaw" now freezes/thaws all zones.
+
+1795. [bug] "rndc dumpdb" was not fully documented. Minor
+ formating issues with "rndc dumpdb -all". [RT #13396]
+
+1794. [func] Named and named-checkzone can now both check for
+ non-terminal wildcard records.
+
+1793. [func] Extend adjusting TTL warning messages. [RT #13378]
+
+1792. [func] New zone option "notify-delay". Specify a minimum
+ delay between sets of NOTIFY messages.
+
+1791. [bug] 'host -t a' still printed out AAAA and MX records.
+ [RT #13230]
+
+1790. [cleanup] Move lib/dns/sec/dst up into lib/dns. This should
+ allow parallel make to succeed.
+
+1789. [bug] Prerequisite test for tkey and dnssec could fail
+ with "configure --with-libtool".
+
+1788. [bug] libbind9.la/libbind9.so needs to link against
+ libisccfg.la/libisccfg.so.
+
+1787. [port] HPUX: both "cc" and "gcc" need -Wl,+vnocompatwarnings.
+
+1786. [port] AIX: libt_api needs to be taught to look for
+ T_testlist in the main executable (--with-libtool).
+ [RT #13239]
+
+1785. [bug] libbind9.la/libbind9.so needs to link against
+ libisc.la/libisc.so.
+
+1784. [cleanup] "libtool -allow-undefined" is the default.
+ Leave hooks in configure to allow it to be set
+ if needed in the future.
+
+1783. [cleanup] We only need one copy of libtool.m4, ltmain.sh in the
+ source tree.
+
+1782. [port] OSX: --with-libtool + --enable-libbind broke on
+ __evOptMonoTime. [RT #13219]
+
+1781. [port] FreeBSD 5.3: set PTHREAD_SCOPE_SYSTEM. [RT #12810]
+
+1780. [bug] Update libtool to 1.5.10.
+
+1779. [port] OSF 5.1: libtool didn't handle -pthread correctly.
+
+1778. [port] HUX 11.11: fix broken IN6ADDR_ANY_INIT and
+ IN6ADDR_LOOPBACK_INIT macros.
+
+1777. [port] OSF 5.1: fix broken IN6ADDR_ANY_INIT and
+ IN6ADDR_LOOPBACK_INIT macros.
+
+1776. [port] Solaris 2.9: fix broken IN6ADDR_ANY_INIT and
+ IN6ADDR_LOOPBACK_INIT macros.
+
+1775. [bug] Only compile getnetent_r.c when threaded. [RT #13205]
+
+1774. [port] Aix: Silence compiler warnings / build failures.
+ [RT #13154]
+
+1773. [bug] Fast retry on host / net unreachable. [RT #13153]
+
+1772. [placeholder]
+
+1771. [placeholder]
+
+1770. [bug] named-checkconf failed to report missing a missing
+ file clause for rbt{64} master/hint zones. [RT#13009]
+
+1769. [port] win32: change compiler flags /MTd ==> /MDd,
+ /MT ==> /MD.
+
+1768. [bug] nsecnoexistnodata() could be called with a non-NSEC
+ rdataset. [RT #12907]
+
+1767. [port] Builds on IPv6 platforms without IPv6 Advanced API
+ support for (struct in6_pktinfo) failed. [RT #13077]
+
+1766. [bug] Update the master file timestamp on successful refresh
+ as well as the journal's timestamp. [RT# 13062]
+
+1765. [bug] configure --with-openssl=auto failed. [RT #12937]
+
+1764. [bug] dns_zone_replacedb failed to emit a error message
+ if there was no SOA record in the replacement db.
+ [RT #13016]
+
+1763. [func] Perform sanity checks on NS records which refer to
+ 'in zone' names. [RT #13002]
+
+1762. [bug] isc_interfaceiter_create() could return ISC_R_SUCCESS
+ even when it failed. [RT #12995]
+
+1761. [bug] 'rndc dumpdb' didn't report unassociated entries.
+ [RT #12971]
+
+1760. [bug] Host / net unreachable was not penalising rtt
+ estimates. [RT #12970]
+
+1759. [bug] Named failed to startup if the OS supported IPv6
+ but had no IPv6 interfaces configured. [RT #12942]
+
+1758. [func] Don't send notify messages to self. [RT #12933]
+
+1757. [func] host now can turn on memory debugging flags with '-m'.
+
+1756. [func] named-checkconf now checks the logging configuration.
+ [RT #12352]
+
+1755. [func] allow-update is now settable at the options / view
+ level. [RT #6636]
+
+1754. [bug] We weren't always attempting to query the parent
+ server for the DS records at the zone cut.
+ [RT #12774]
+
+1753. [bug] Don't serve a slave zone which has no NS records.
+ [RT #12894]
+
+1752. [port] Move isc_app_start() to after ns_os_daemonise()
+ as some fork() implementations unblock the signals
+ that are blocked by isc_app_start(). [RT #12810]
+
+1751. [bug] --enable-getifaddrs failed under linux. [RT #12867]
+
+1750. [port] lib/bind/make/rules.in:subdirs was not bash friendly.
+ [RT #12864]
+
+1749. [bug] 'check-names response ignore;' failed to ignore.
+ [RT #12866]
+
+1748. [func] dig now returns the byte count for axfr/ixfr.
+
+1747. [bug] BIND 8 compatibility: named/named-checkconf failed
+ to parse "host-statistics-max" in named.conf.
+
+1746. [func] Make public the function to read a key file,
+ dst_key_read_public(). [RT #12450]
+
+1745. [bug] Dig/host/nslookup accept replies from link locals
+ regardless of scope if no scope was specified when
+ query was sent. [RT #12745]
+
+1744. [bug] If tuple2msgname() failed to convert a tuple to
+ a name a REQUIRE could be triggered. [RT #12796]
+
+1743. [bug] If isc_taskmgr_create() was not able to create the
+ requested number of worker threads then destruction
+ of the manager would trigger an INSIST() failure.
+ [RT #12790]
+
+1742. [bug] Deleting all records at a node then adding a
+ previously existing record, in a single UPDATE
+ transaction, failed to leave / regenerate the
+ associated RRSIG records. [RT #12788]
+
+1741. [bug] Deleting all records at a node in a secure zone
+ using a update-policy grant failed. [RT #12787]
+
+1740. [bug] Replace rbt's hash algorithm as it performed badly
+ with certain zones. [RT #12729]
+
+ NOTE: a hash context now needs to be established
+ via isc_hash_create() if the application was not
+ already doing this.
+
+1739. [bug] dns_rbt_deletetree() could incorrectly return
+ ISC_R_QUOTA. [RT #12695]
+
+1738. [bug] Enable overrun checking by default. [RT #12695]
+
+1737. [bug] named failed if more than 16 masters were specified.
+ [RT #12627]
+
+1736. [bug] dst_key_fromnamedfile() could fail to read a
+ public key. [RT #12687]
+
+1735. [bug] 'dig +sigtrace' could die with a REQUIRE failure.
+ [RE #12688]
+
+1734. [cleanup] 'rndc-confgen -a -t' remove extra '/' in path.
+ [RT #12588]
+
+1733. [bug] Return non-zero exit status on initial load failure.
+ [RT #12658]
+
+1732. [bug] 'rrset-order name "*"' wasn't being applied to ".".
+ [RT #12467]
+
+1731. [port] darwin: relax version test in ifconfig.sh.
+ [RT #12581]
+
+1730. [port] Determine the length type used by the socket API.
+ [RT #12581]
+
+1729. [func] Improve check-names error messages.
+
+1728. [doc] Update check-names documentation.
+
+1727. [bug] named-checkzone: check-names support didn't match
+ documentation.
+
+1726. [port] aix5: add support for aix5.
+
+1725. [port] linux: update error message on interaction of threads,
+ capabilities and setuid support (named -u). [RT #12541]
+
+1724. [bug] Look for DNSKEY records with "dig +sigtrace".
+ [RT #12557]
+
+1723. [cleanup] Silence compiler warnings from t_tasks.c. [RT #12493]
+
+1722. [bug] Don't commit the journal on malformed ixfr streams.
+ [RT #12519]
+
+1721. [bug] Error message from the journal processing were not
+ always identifying the relevant journal. [RT #12519]
+
+1720. [bug] 'dig +chase' did not terminate on a RFC 2308 Type 1
+ negative response. [RT #12506]
+
+1719. [bug] named was not correctly caching a RFC 2308 Type 1
+ negative response. [RT #12506]
+
+1718. [bug] nsupdate was not handling RFC 2308 Type 3 negative
+ responses when looking for the zone / master server.
+ [RT #12506]
+
+1717. [port] solaris: ifconfig.sh did not support Solaris 10.
+ "ifconfig.sh down" didn't work for Solaris 9.
+
+1716. [doc] named.conf(5) was being installed in the wrong
+ location. [RT# 12441]
+
+1715. [func] 'dig +trace' now randomly selects the next servers
+ to try. Report if there is a bad delegation.
+
+1714. [bug] dig/host/nslookup were only trying the first
+ address when a nameserver was specified by name.
+ [RT #12286]
+
+1713. [port] linux: extend capset failure message to say:
+ please ensure that the capset kernel module is
+ loaded. see insmod(8)
+
+1712. [bug] Missing FULLCHECK for "trusted-key" in dig.
+
+1711. [func] 'rndc unfreeze' has been deprecated by 'rndc thaw'.
+
+1710. [func] 'rndc notify zone [class [view]]' resend the NOTIFY
+ messages for the specified zone. [RT #9479]
+
+1709. [port] solaris: add SMF support from Sun.
+
+1708. [cleanup] Replaced dns_fullname_hash() with dns_name_fullhash()
+ for conformance to the name space convention. Binary
+ backward compatibility to the old function name is
+ provided. [RT #12376]
+
+1707. [contrib] sdb/ldap updated to version 1.0-beta.
+
+1706. [bug] 'rndc stop' failed to cause zones to be flushed
+ sometimes. [RT #12328]
+
+1705. [func] Allow the journal's name to be changed via named.conf.
+
+1704. [port] lwres needed a snprintf() implementation for
+ platforms without snprintf(). Add missing
+ "#include <isc/print.h>". [RT #12321]
+
+1703. [bug] named would loop sending NOTIFY messages when it
+ failed to receive a response. [RT #12322]
+
+1702. [bug] also-notify should not be applied to built in zones.
+ [RT #12323]
+
+1701. [doc] A minimal named.conf man page.
+
+1700. [func] nslookup is no longer to be treated as deprecated.
+ Remove "deprecated" warning message. Add man page.
+
+1699. [bug] dnssec-signzone can generate "not exact" errors
+ when resigning. [RT #12281]
+
+1698. [doc] Use reserved IPv6 documentation prefix.
+
+1697. [bug] xxx-source{,-v6} was not effective when it
+ specified one of listening addresses and a
+ different port than the listening port. [RT #12257]
+
+1696. [bug] dnssec-signzone failed to clean out nodes that
+ consisted of only NSEC and RRSIG records.
+ [RT #12154]
+
+1695. [bug] DS records when forwarding require special handling.
+ [RT #12133]
+
+1694. [bug] Report if the builtin views of "_default" / "_bind"
+ are defined in named.conf. [RT #12023]
+
+1693. [bug] max-journal-size was not effective for master zones
+ with ixfr-from-differences set. [RT# 12024]
+
+1692. [bug] Don't set -I, -L and -R flags when libcrypto is in
+ /usr/lib. [RT #11971]
+
+1691. [bug] sdb's attachversion was not complete. [RT #11990]
+
+1690. [bug] Delay detaching view from the client until UPDATE
+ processing completes when shutting down. [RT #11714]
+
+1689. [bug] DNS_NAME_TOREGION() and DNS_NAME_SPLIT() macros
+ contained gratuitous semicolons. [RT #11707]
+
+1688. [bug] LDFLAGS was not supported.
+
+1687. [bug] Race condition in dispatch. [RT #10272]
+
+1686. [bug] Named sent a extraneous NOTIFY when it received a
+ redundant UPDATE request. [RT #11943]
+
+1685. [bug] Change #1679 loop tests weren't quite right.
+
+1684. [func] ixfr-from-differences now takes master and slave in
+ addition to yes and no at the options and view levels.
+
+1683. [bug] dig +sigchase could leak memory. [RT #11445]
+
+1682. [port] Update configure test for (long long) printf format.
+ [RT #5066]
+
+1681. [bug] Only set SO_REUSEADDR when a port is specified in
+ isc_socket_bind(). [RT #11742]
+
+1680. [func] rndc: the source address can now be specified.
+
+1679. [bug] When there was a single nameserver with multiple
+ addresses for a zone not all addresses were tried.
+ [RT #11706]
+
+1678. [bug] RRSIG should use TYPEXXXXX for unknown types.
+
+1677. [bug] dig: +aaonly didn't work, +aaflag undocumented.
+
+1676. [func] 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 allow-query applies.
+
+1675. [bug] named would sometimes add extra NSEC records to
+ the authority section.
+
+1674. [port] linux: increase buffer size used to scan
+ /proc/net/if_inet6.
+
+1673. [port] linux: issue a error messages if IPv6 interface
+ scans fails.
+
+1672. [cleanup] Tests which only function in a threaded build
+ now return R:THREADONLY (rather than R:UNTESTED)
+ in a non-threaded build.
+
+1671. [contrib] queryperf: add NAPTR to the list of known types.
+
+1670. [func] Log UPDATE requests to slave zones without an acl as
+ "disabled" at debug level 3. [RT# 11657]
+
+1669. [placeholder]
+
+1668. [bug] DIG_SIGCHASE was making bin/dig/host dump core.
+
+1667. [port] linux: not all versions have IF_NAMESIZE.
+
+1666. [bug] The optional port on hostnames in dual-stack-servers
+ was being ignored.
+
+1665. [func] rndc now allows addresses to be set in the
+ server clauses.
+
+1664. [bug] nsupdate needed KEY for SIG(0), not DNSKEY.
+
+1663. [func] Look for OpenSSL by default.
+
+1662. [bug] Change #1658 failed to change one use of 'type'
+ to 'keytype'.
+
+1661. [bug] Restore dns_name_concatenate() call in
+ adb.c:set_target(). [RT #11582]
+
+1660. [bug] win32: connection_reset_fix() was being called
+ unconditionally. [RT #11595]
+
+1659. [cleanup] Cleanup some messages that were referring to KEY vs
+ DNSKEY, NXT vs NSEC and SIG vs RRSIG.
+
+1658. [func] Update dnssec-keygen to default to KEY for HMAC-MD5
+ and DH. Tighten which options apply to KEY and
+ DNSKEY records.
+
+1657. [doc] ARM: document query log output.
+
+1656. [doc] Update DNSSEC description in ARM to cover DS, NSEC
+ DNSKEY and RRSIG. [RT #11542]
+
+1655. [bug] Logging multiple versions w/o a size was broken.
+ [RT #11446]
+
+1654. [bug] isc_result_totext() contained array bounds read
+ error.
+
+1653. [func] Add key type checking to dst_key_fromfilename(),
+ DST_TYPE_KEY should be used to read TSIG, TKEY and
+ SIG(0) keys.
+
+1652. [bug] TKEY still uses KEY.
+
+1651. [bug] dig: process multiple dash options.
+
+1650. [bug] dig, nslookup: flush standard out after each command.
+
+1649. [bug] Silence "unexpected non-minimal diff" message.
+ [RT #11206]
+
+1648. [func] Update dnssec-lookaside named.conf syntax to support
+ multiple dnssec-lookaside namespaces (not yet
+ implemented).
+
+1647. [bug] It was possible trigger a INSIST when chasing a DS
+ record that required walking back over a empty node.
+ [RT #11445]
+
+1646. [bug] win32: logging file versions didn't work with
+ non-UNC filenames. [RT#11486]
+
+1645. [bug] named could trigger a REQUIRE failure if multiple
+ masters with keys are specified.
+
+1644. [bug] Update the journal modification time after a
+ successful refresh query. [RT #11436]
+
+1643. [bug] dns_db_closeversion() could leak memory / node
+ references. [RT #11163]
+
+1642. [port] Support OpenSSL implementations which don't have
+ DSA support. [RT #11360]
+
+1641. [bug] Update the check-names description in ARM. [RT #11389]
+
+1640. [bug] win32: isc_socket_cancel(ISC_SOCKCANCEL_ACCEPT) was
+ incorrectly closing the socket. [RT #11291]
+
+1639. [func] Initial dlv system test.
+
+1638. [bug] "ixfr-from-differences" could generate a REQUIRE
+ failure if the journal open failed. [RT #11347]
+
+1637. [bug] Node reference leak on error in addnoqname().
+
+1636. [bug] The dump done callback could get ISC_R_SUCCESS even if
+ a error had occurred. The database version no longer
+ matched the version of the database that was dumped.
+
+1635. [bug] Memory leak on error in query_addds().
+
+1634. [bug] named didn't supply a useful error message when it
+ detected duplicate views. [RT #11208]
+
+1633. [bug] named should return NOTIMP to update requests to a
+ slaves without a allow-update-forwarding acl specified.
+ [RT #11331]
+
+1632. [bug] nsupdate failed to send prerequisite only UPDATE
+ messages. [RT #11288]
+
+1631. [bug] dns_journal_compact() could sometimes corrupt the
+ journal. [RT #11124]
+
+1630. [contrib] queryperf: add support for IPv6 transport.
+
+1629. [func] dig now supports IPv6 scoped addresses with the
+ extended format in the local-server part. [RT #8753]
+
+1628. [bug] Typo in Compaq Trucluster support. [RT# 11264]
+
+1627. [bug] win32: sockets were not being closed when the
+ last external reference was removed. [RT# 11179]
+
+1626. [bug] --enable-getifaddrs was broken. [RT#11259]
+
+1625. [bug] named failed to load/transfer RFC2535 signed zones
+ which contained CNAMES. [RT# 11237]
+
+1624. [bug] zonemgr_putio() call should be locked. [RT# 11163]
+
+1623. [bug] A serial number of zero was being displayed in the
+ "sending notifies" log message when also-notify was
+ used. [RT #11177]
+
+1622. [func] probe the system to see if IPV6_(RECV)PKTINFO is
+ available, and suppress wildcard binding if not.
+
+1621. [bug] match-destinations did not work for IPv6 TCP queries.
+ [RT# 11156]
+
+1620. [func] When loading a zone report if it is signed. [RT #11149]
+
+1619. [bug] Missing ISC_LIST_UNLINK in end_reserved_dispatches().
+ [RT# 11118]
+
+1618. [bug] Fencepost errors in dns_name_ishostname() and
+ dns_name_ismailbox() could trigger a INSIST().
+
+1617. [port] win32: VC++ 6.0 support.
+
+1616. [compat] Ensure that named's version is visible in the core
+ dump. [RT #11127]
+
+1615. [port] Define ISC_SOCKADDR_LEN_T based on _BSD_SOCKLEN_T_ if
+ it is defined.
+
+1614. [port] win32: silence resource limit messages. [RT# 11101]
+
+1613. [bug] Builds would fail on machines w/o a if_nametoindex().
+ Missing #ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX/#endif.
+ [RT #11119]
+
+1612. [bug] check-names at the option/view level could trigger
+ an INSIST. [RT# 11116]
+
+1611. [bug] solaris: IPv6 interface scanning failed to cope with
+ no active IPv6 interfaces.
+
+1610. [bug] On dual stack machines "dig -b" failed to set the
+ address type to be looked up with "@server".
+ [RT #11069]
+
+1609. [func] dig now has support to chase DNSSEC signature chains.
+ Requires -DDIG_SIGCHASE=1 to be set in STD_CDEFINES.
+
+ DNSSEC validation code in dig coded by Olivier Courtay
+ (olivier.courtay@irisa.fr) for the IDsA project
+ (http://idsa.irisa.fr).
+
+1608. [func] dig and host now accept -4/-6 to select IP transport
+ to use when making queries.
+
+1607. [bug] dig, host and nslookup were still using random()
+ to generate query ids. [RT# 11013]
+
+1606. [bug] DLV insecurity proof was failing.
+
+1605. [func] New dns_db_find() option DNS_DBFIND_COVERINGNSEC.
+
+1604. [bug] A xfrout_ctx_create() failure would result in
+ xfrout_ctx_destroy() being called with a
+ partially initialized structure.
+
+1603. [bug] nsupdate: set interactive based on isatty().
+ [RT# 10929]
+
+1602. [bug] Logging to a file failed unless a size was specified.
+ [RT# 10925]
+
+1601. [bug] Silence spurious warning 'both "recursion no;" and
+ "allow-recursion" active' warning from view "_bind".
+ [RT# 10920]
+
+1600. [bug] Duplicate zone pre-load checks were not case
+ insensitive.
+
+1599. [bug] Fix memory leak on error path when checking named.conf.
+
+1598. [func] Specify that certain parts of the namespace must
+ be secure (dnssec-must-be-secure).
+
+1597. [func] Allow notify-source and query-source to be specified
+ on a per server basis similar to transfer-source.
+ [RT #6496]
+
+1596. [func] Accept 'notify-source' style syntax for query-source.
+
+1595. [func] New notify type 'master-only'. Enable notify for
+ master zones only.
+
+1594. [bug] 'rndc dumpdb' could prevent named from answering
+ queries while the dump was in progress. [RT #10565]
+
+1593. [bug] rndc should return "unknown command" to unknown
+ commands. [RT# 10642]
+
+1592. [bug] configure_view() could leak a dispatch. [RT# 10675]
+
+1591. [bug] libbind: updated to BIND 8.4.5.
+
+1590. [port] netbsd: update thread support.
+
+1589. [func] DNSSEC lookaside validation.
+
+1588. [bug] win32: TCP sockets could become blocked. [RT #10115]
+
+1587. [bug] dns_message_settsigkey() failed to clear existing key.
+ [RT #10590]
+
+1586. [func] "check-names" is now implemented.
+
+1585. [placeholder]
+
+1584. [bug] "make test" failed with a read only source tree.
+ [RT #10461]
+
+1583. [bug] Records add via UPDATE failed to get the correct trust
+ level. [RT #10452]
+
+1582. [bug] rrset-order failed to work on RRsets with more
+ than 32 elements. [RT #10381]
+
+1581. [func] Disable DNSSEC support by default. To enable
+ DNSSEC specify "dnssec-enable yes;" in named.conf.
+
+1580. [bug] Zone destruction on final detach takes a long time.
+ [RT #3746]
+
+1579. [bug] Multiple task managers could not be created.
+
+1578. [bug] Don't use CLASS E IPv4 addresses when resolving.
+ [RT #10346]
+
+1577. [bug] Use isc_uint32_t in ultrasparc optimizer bug
+ workaround code. [RT #10331]
+
+1576. [bug] Race condition in dns_dispatch_addresponse().
+ [RT# 10272]
+
+1575. [func] Log TSIG name on TSIG verify failure. [RT #4404]
+
+1574. [bug] Don't attempt to open the controls socket(s) when
+ running tests. [RT #9091]
+
+1573. [port] linux: update to libtool 1.5.2 so that
+ "make install DESTDIR=/xx" works with
+ "configure --with-libtool". [RT #9941]
+
+1572. [bug] nsupdate: sign the soa query to find the enclosing
+ zone if the server is specified. [RT #10148]
+
+1571. [bug] rbt:hash_node() could fail leaving the hash table
+ in an inconsistent state. [RT #10208]
+
+1570. [bug] nsupdate failed to handle classes other than IN.
+ New keyword 'class' which sets the default class.
+ [RT #10202]
+
+1569. [func] nsupdate new command 'answer' which displays the
+ complete answer message to the last update.
+
+1568. [bug] nsupdate now reports that the update failed in
+ interactive mode. [RT# 10236]
+
+1567. [maint] B.ROOT-SERVERS.NET is now 192.228.79.201.
+
+1566. [port] Support for the cmsg framework on Solaris and HP/UX.
+ This also solved the problem that match-destinations
+ for IPv6 addresses did not work on these systems.
+ [RT #10221]
+
+1565. [bug] CD flag should be copied to outgoing queries unless
+ the query is under a secure entry point in which case
+ CD should be set.
+
+1564. [func] Attempt to provide a fallback entropy source to be
+ used if named is running chrooted and named is unable
+ to open entropy source within the chroot area.
+ [RT #10133]
+
+1563. [bug] Gracefully fail when unable to obtain neither an IPv4
+ nor an IPv6 dispatch. [RT #10230]
+
+1562. [bug] isc_socket_create() and isc_socket_accept() could
+ leak memory under error conditions. [RT #10230]
+
+1561. [bug] It was possible to release the same name twice if
+ named ran out of memory. [RT #10197]
+
+1560. [port] FreeBSD: work around FreeBSD 5.2 mapping EAI_NODATA
+ and EAI_NONAME to the same value.
+
+1559. [port] named should ignore SIGFSZ.
+
+1558. [func] New DNSSEC 'disable-algorithms'. Support entry into
+ child zones for which we don't have a supported
+ algorithm. Such child zones are treated as unsigned.
+
+1557. [func] Implement missing DNSSEC tests for
+ * NOQNAME proof with wildcard answers.
+ * NOWILDARD proof with NXDOMAIN.
+ Cache and return NOQNAME with wildcard answers.
+
+1556. [bug] nsupdate now treats all names as fully qualified.
+ [RT #6427]
+
+1555. [func] 'rrset-order cyclic' no longer has a random starting
+ point per query. [RT #7572]
+
+1554. [bug] dig, host, nslookup failed when no nameservers
+ were specified in /etc/resolv.conf. [RT #8232]
+
+1553. [bug] The windows socket code could stop accepting
+ connections. [RT#10115]
+
+1552. [bug] Accept NOTIFY requests from mapped masters if
+ matched-mapped is set. [RT #10049]
+
+1551. [port] Open "/dev/null" before calling chroot().
+
+1550. [port] Call tzset(), if available, before calling chroot().
+
+1549. [func] named-checkzone can now write out the zone contents
+ in a easily parsable format (-D and -o).
+
+1548. [bug] When parsing APL records it was possible to silently
+ accept out of range ADDRESSFAMILY values. [RT# 9979]
+
+1547. [bug] Named wasted memory recording duplicate lame zone
+ entries. [RT #9341]
+
+1546. [bug] We were rejecting valid secure CNAME to negative
+ answers.
+
+1545. [bug] It was possible to leak memory if named was unable to
+ bind to the specified transfer source and TSIG was
+ being used. [RT #10120]
+
+1544. [bug] Named would logged a single entry to a file despite it
+ being over the specified size limit.
+
+1543. [bug] Logging using "versions unlimited" did not work.
+
+1542. [placeholder]
+
+1541. [func] NSEC now uses new bitmap format.
+
+1540. [bug] "rndc reload <dynamiczone>" was silently accepted.
+ [RT #8934]
+
+1539. [bug] Open UDP sockets for notify-source and transfer-source
+ that use reserved ports at startup. [RT #9475]
+
+1538. [placeholder] rt9997
+
+1537. [func] New option "querylog". If set specify whether query
+ logging is to be enabled or disabled at startup.
+
+1536. [bug] Windows socket code failed to log a error description
+ when returning ISC_R_UNEXPECTED. [RT #9998]
+
+1535. [placeholder]
+
+1534. [bug] Race condition when priming cache. [RT# 9940]
+
+1533. [func] Warn if both "recursion no;" and "allow-recursion"
+ are active. [RT# 4389]
+
+1532. [port] netbsd: the configure test for <sys/sysctl.h>
+ requires <sys/param.h>.
+
+1531. [port] AIX more libtool fixes.
+
+1530. [bug] It was possible to trigger a INSIST() failure if a
+ slave master file was removed at just the correct
+ moment. [RT #9462]
+
+1529. [bug] "notify explicit;" failed to log that NOTIFY messages
+ were being sent for the zone. [RT# 9442]
+
+1528. [cleanup] Simplify some dns_name_ functions based on the
+ deprecation of bitstring labels.
+
+1527. [cleanup] Reduce the number of gettimeofday() calls without
+ losing necessary timer granularity.
+
+1526. [func] 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.
+
+1525. [bug] dns_cache_create() could trigger a REQUIRE
+ failure in isc_mem_put() during error cleanup.
+ [RT# 9360]
+
+1524. [port] AIX needs to be able to resolve all symbols when
+ creating shared libraries (--with-libtool).
+
+1523. [bug] Fix race condition in rbtdb. [RT# 9189]
+
+1522. [bug] dns_db_findnode() relax the requirements on 'name'.
+ [RT# 9286]
+
+1521. [bug] dns_view_createresolver() failed to check the
+ result from isc_mem_create(). [RT# 9294]
+
+1520. [protocol] Add SSHFP (SSH Finger Print) type.
+
+1519. [bug] dnssec-signzone:nsec_setbit() computed the wrong
+ length of the new bitmap.
+
+1518. [bug] dns_nsec_buildrdata(), and hence dns_nsec_build(),
+ contained a off-by-one error when working out the
+ number of octets in the bitmap.
+
+1517. [port] Support for IPv6 interface scanning on HP/UX and
+ TrueUNIX 5.1.
+
+1516. [func] Roll the DNSSEC types to RRSIG, NSEC and DNSKEY.
+
+1515. [func] Allow transfer source to be set in a server statement.
+ [RT #6496]
+
+1514. [bug] named: isc_hash_destroy() was being called too early.
+ [RT #9160]
+
+1513. [doc] Add "US" to root-delegation-only exclude list.
+
+1512. [bug] Extend the delegation-only logging to return query
+ type, class and responding nameserver.
+
+1511. [bug] delegation-only was generating false positives
+ on negative answers from sub-zones.
+
+1510. [func] New view option "root-delegation-only". Apply
+ delegation-only check to all TLDs and root.
+ Note there are some TLDs that are NOT delegation
+ only (e.g. DE, LV, US and MUSEUM) these can be excluded
+ from the checks by using exclude.
+
+ root-delegation-only exclude {
+ "DE"; "LV"; "US"; "MUSEUM";
+ };
+
+1509. [bug] Hint zones should accept delegation-only. Forward
+ zone should not accept delegation-only.
+
+1508. [bug] Don't apply delegation-only checks to answers from
+ forwarders.
+
+1507. [bug] Handle BIND 8 style returns to NS queries to parents
+ when making delegation-only checks.
+
+1506. [bug] Wrong return type for dns_view_isdelegationonly().
+
+1505. [bug] Uninitialized rdataset in sdb. [RT #8750]
+
+1504. [func] New zone type "delegation-only".
+
+1503. [port] win32: install libeay32.dll outside of system32.
+
+1502. [bug] nsupdate: adjust timeouts for UPDATE requests over TCP.
+
+1501. [func] Allow TCP queue length to be specified via
+ named.conf, tcp-listen-queue.
+
+1500. [bug] host failed to lookup MX records. Also look up
+ AAAA records.
+
+1499. [bug] isc_random need to be seeded better if arc4random()
+ is not used.
+
+1498. [port] bsdos: 5.x support.
+
+1497. [placeholder]
+
+1496. [port] test for pthread_attr_setstacksize().
+
+1495. [cleanup] Replace hash functions with universal hash.
+
+1494. [security] Turn on RSA BLINDING as a precaution.
+
+1493. [placeholder]
+
+1492. [cleanup] Preserve rwlock quota context when upgrading /
+ downgrading. [RT #5599]
+
+1491. [bug] dns_master_dump*() would produce extraneous $ORIGIN
+ lines. [RT #6206]
+
+1490. [bug] Accept reading state as well as working state in
+ ns_client_next(). [RT #6813]
+
+1489. [compat] Treat 'allow-update' on slave zones as a warning.
+ [RT #3469]
+
+1488. [bug] Don't override trust levels for glue addresses.
+ [RT #5764]
+
+1487. [bug] A REQUIRE() failure could be triggered if a zone was
+ queued for transfer and the zone was then removed.
+ [RT #6189]
+
+1486. [bug] isc_print_snprintf() '%%' consumed one too many format
+ characters. [RT# 8230]
+
+1485. [bug] gen failed to handle high type values. [RT #6225]
+
+1484. [bug] The number of records reported after a AXFR was wrong.
+ [RT #6229]
+
+1483. [bug] dig axfr failed if the message id in the answer failed
+ to match that in the request. Only the id in the first
+ message is required to match. [RT #8138]
+
+1482. [bug] named could fail to start if the kernel supports
+ IPv6 but no interfaces are configured. Similarly
+ for IPv4. [RT #6229]
+
+1481. [bug] Refresh and stub queries failed to use masters keys
+ if specified. [RT #7391]
+
+1480. [bug] Provide replay protection for rndc commands. Full
+ replay protection requires both rndc and named to
+ be updated. Partial replay protection (limited
+ exposure after restart) is provided if just named
+ is updated.
+
+1479. [bug] cfg_create_tuple() failed to handle out of
+ memory cleanup. parse_list() would leak memory
+ on syntax errors.
+
+1478. [port] ifconfig.sh didn't account for other virtual
+ interfaces. It now takes a optional argument
+ to specify the first interface number. [RT #3907]
+
+1477. [bug] memory leak using stub zones and TSIG.
+
+1476. [placeholder]
+
+1475. [port] Probe for old sprintf().
+
+1474. [port] Provide strtoul() and memmove() for platforms
+ without them.
+
+1473. [bug] create_map() and create_string() failed to handle out
+ of memory cleanup. [RT #6813]
+
+1472. [contrib] idnkit-1.0 from JPNIC, replaces mdnkit.
+
+1471. [bug] libbind: updated to BIND 8.4.0.
+
+1470. [bug] Incorrect length passed to snprintf. [RT #5966]
+
+1469. [func] Log end of outgoing zone transfer at same level
+ as the start of transfer is logged. [RT #4441]
+
+1468. [func] Internal zones are no longer counted for
+ 'rndc status'. [RT #4706]
+
+1467. [func] $GENERATES now supports optional class and ttl.
+
+1466. [bug] lwresd configuration errors resulted in memory
+ and lock leaks. [RT #5228]
+
+1465. [bug] isc_base64_decodestring() and isc_base64_tobuffer()
+ failed to check that trailing bits were zero allowing
+ some invalid base64 strings to be accepted. [RT #5397]
+
+1464. [bug] Preserve "out of zone" data for outgoing zone
+ transfers. [RT #5192]
+
+1463. [bug] dns_rdata_from{wire,struct}() failed to catch bad
+ NXT bit maps. [RT #5577]
+
+1462. [bug] parse_sizeval() failed to check the token type.
+ [RT #5586]
+
+1461. [bug] Remove deadlock from rbtdb code. [RT #5599]
+
+1460. [bug] inet_pton() failed to reject certain malformed
+ IPv6 literals.
+
+1459. [placeholder]
+
+1458. [cleanup] sprintf() -> snprintf().
+
+1457. [port] Provide strlcat() and strlcpy() for platforms without
+ them.
+
+1456. [contrib] gen-data-queryperf.py from Stephane Bortzmeyer.
+
+1455. [bug] <netaddr> missing from server grammar in
+ doc/misc/options. [RT #5616]
+
+1454. [port] Use getifaddrs() if available for interface scanning.
+ --disable-getifaddrs to override. Glibc currently
+ has a getifaddrs() that does not support IPv6.
+ Use --enable-getifaddrs=glibc to force the use of
+ this version under linux machines.
+
+1453. [doc] ARM: $GENERATE example wasn't accurate. [RT #5298]
+
+1452. [placeholder]
+
+1451. [bug] rndc-confgen didn't exit with a error code for all
+ failures. [RT #5209]
+
+1450. [bug] Fetching expired glue failed under certain
+ circumstances. [RT #5124]
+
+1449. [bug] query_addbestns() didn't handle running out of memory
+ gracefully.
+
+1448. [bug] Handle empty wildcards labels.
+
+1447. [bug] We were casting (unsigned int) to and from (void *).
+ rdataset->private4 is now rdataset->privateuint4
+ to reflect a type change.
+
+1446. [func] Implemented undocumented alternate transfer sources
+ from BIND 8. See use-alt-transfer-source,
+ alt-transfer-source and alt-transfer-source-v6.
+
+ SECURITY: use-alt-transfer-source is ENABLED unless
+ you are using views. This may cause a security risk
+ resulting in accidental disclosure of wrong zone
+ content if the master supplying different source
+ content based on IP address. If you are not certain
+ ISC recommends setting use-alt-transfer-source no;
+
+1445. [bug] DNS_ADBFIND_STARTATROOT broke stub zones. This has
+ been replaced with DNS_ADBFIND_STARTATZONE which
+ causes the search to start using the closest zone.
+
+1444. [func] dns_view_findzonecut2() allows you to specify if the
+ cache should be searched for zone cuts.
+
+1443. [func] Masters lists can now be specified and referenced
+ in zone masters clauses and other masters lists.
+
+1442. [func] New functions for manipulating port lists:
+ dns_portlist_create(), dns_portlist_add(),
+ dns_portlist_remove(), dns_portlist_match(),
+ dns_portlist_attach() and dns_portlist_detach().
+
+1441. [func] It is now possible to tell dig to bind to a specific
+ source port.
+
+1440. [func] It is now possible to tell named to avoid using
+ certain source ports (avoid-v4-udp-ports,
+ avoid-v6-udp-ports).
+
+1439. [bug] Named could return NOERROR with certain NOTIFY
+ failures. Return NOTAUTH if the NOTIFY zone is
+ not being served.
+
+1438. [func] Log TSIG (if any) when logging NOTIFY requests.
+
+1437. [bug] Leave space for stdio to work in. [RT #5033]
+
+1436. [func] dns_zonemgr_resumexfrs() can be used to restart
+ stalled transfers.
+
+1435. [bug] zmgr_resume_xfrs() was being called read locked
+ rather than write locked. zmgr_resume_xfrs()
+ was not being called if the zone was being
+ shutdown.
+
+1434. [bug] "rndc reconfig" failed to initiate the initial
+ zone transfer of new slave zones.
+
+1433. [bug] named could trigger a REQUIRE failure if it could
+ not get a file descriptor when attempting to write
+ a master file. [RT #4347]
+
+1432. [func] The advertised EDNS UDP buffer size can now be set
+ via named.conf (edns-udp-size).
+
+1431. [bug] isc_print_snprintf() "%s" with precision could walk off
+ end of argument. [RT #5191]
+
+1430. [port] linux: IPv6 interface scanning support.
+
+1429. [bug] Prevent the cache getting locked to old servers.
+
+1428. [placeholder]
+
+1427. [bug] Race condition in adb with threaded build.
+
+1426. [placeholder]
+
+1425. [port] linux/libbind: define __USE_MISC when testing *_r()
+ function prototypes in netdb.h. [RT #4921]
+
+1424. [bug] EDNS version not being correctly printed.
+
+1423. [contrib] queryperf: added A6 and SRV.
+
+1422. [func] Log name/type/class when denying a query. [RT #4663]
+
+1421. [func] Differentiate updates that don't succeed due to
+ prerequisites (unsuccessful) vs other reasons
+ (failed).
+
+1420. [port] solaris: work around gcc optimizer bug.
+
+1419. [port] openbsd: use /dev/arandom. [RT #4950]
+
+1418. [bug] 'rndc reconfig' did not cause new slaves to load.
+
+1417. [func] ID.SERVER/CHAOS is now a built in zone.
+ See "server-id" for how to configure.
+
+1416. [bug] Empty node should return NOERROR NODATA, not NXDOMAIN.
+ [RT #4715]
+
+1415. [func] DS TTL now derived from NS ttl. NXT TTL now derived
+ from SOA MINIMUM.
+
+1414. [func] Support for KSK flag.
+
+1413. [func] Explicitly request the (re-)generation of DS records
+ from keysets (dnssec-signzone -g).
+
+1412. [func] You can now specify servers to be tried if a nameserver
+ has IPv6 address and you only support IPv4 or the
+ reverse. See dual-stack-servers.
+
+1411. [bug] empty nodes should stop wildcard matches. [RT #4802]
+
+1410. [func] Handle records that live in the parent zone, e.g. DS.
+
+1409. [bug] DS should have attribute DNS_RDATATYPEATTR_DNSSEC.
+
+1408. [bug] "make distclean" was not complete. [RT #4700]
+
+1407. [bug] lfsr incorrectly implements the shift register.
+ [RT #4617]
+
+1406. [bug] dispatch initializes one of the LFSR's with a incorrect
+ polynomial. [RT #4617]
+
+1405. [func] Use arc4random() if available.
+
+1404. [bug] libbind: ns_name_ntol() could overwrite a zero length
+ buffer.
+
+1403. [func] dnssec-signzone, dnssec-keygen, dnssec-makekeyset
+ dnssec-signkey now report their version in the
+ usage message.
+
+1402. [cleanup] A6 has been moved to experimental and is no longer
+ fully supported.
+
+1401. [bug] adb wasn't clearing state when the timer expired.
+
+1400. [bug] Block the addition of wildcard NS records by IXFR
+ or UPDATE. [RT #3502]
+
+1399. [bug] Use serial number arithmetic when testing SIG
+ timestamps. [RT #4268]
+
+1398. [doc] ARM: notify-also should have been also-notify.
+ [RT #4345]
+
+1397. [maint] J.ROOT-SERVERS.NET is now 192.58.128.30.
+
+1396. [func] dnssec-signzone: adjust the default signing time by
+ 1 hour to allow for clock skew.
+
+1395. [port] OpenSSL 0.9.7 defines CRYPTO_LOCK_ENGINE but doesn't
+ have a working implementation. [RT #4079]
+
+1394. [func] It is now possible to check if a particular element is
+ in a acl. Remove duplicate entries from the localnets
+ acl.
+
+1393. [port] Bind to individual IPv6 interfaces if IPV6_IPV6ONLY
+ is not available in the kernel to prevent accidently
+ listening on IPv4 interfaces.
+
+1392. [bug] named-checkzone: update usage.
+
+1391. [func] Add support for IPv6 scoped addresses in named.
+
+1390. [func] host now supports ixfr.
+
+1389. [bug] named could fail to rotate long log files. [RT #3666]
+
+1388. [port] irix: check for sys/sysctl.h and NET_RT_IFLIST before
+ defining HAVE_IFLIST_SYSCTL. [RT #3770]
+
+1387. [bug] named could crash due to an access to invalid memory
+ space (which caused an assertion failure) in
+ incremental cleaning. [RT #3588]
+
+1386. [bug] named-checkzone -z stopped on errors in a zone.
+ [RT #3653]
+
+1385. [bug] Setting serial-query-rate to 10 would trigger a
+ REQUIRE failure.
+
+1384. [bug] host was incompatible with BIND 8 in its exit code and
+ in the output with the -l option. [RT #3536]
+
+1383. [func] Track the serial number in a IXFR response and log if
+ a mismatch occurs. This is a more specific error than
+ "not exact". [RT #3445]
+
+1382. [bug] make install failed with --enable-libbind. [RT #3656]
+
+1381. [bug] named failed to correctly process answers that
+ contained DNAME records where the resulting CNAME
+ resulted in a negative answer.
+
+1380. [func] 'rndc recursing' dump recursing queries to
+ 'recursing-file = "named.recursing";'.
+
+1379. [func] 'rndc status' now reports tcp and recursion quota
+ states.
+
+1378. [func] Improved positive feedback for 'rndc {reload|refresh}.
+
+1377. [func] dns_zone_load{new}() now reports if the zone was
+ loaded, queued for loading to up to date.
+
+1376. [func] New function dns_zone_logc() to log to specified
+ category.
+
+1375. [func] 'rndc dumpdb' now dumps the adb cache along with the
+ data cache.
+
+1374. [func] dns_adb_dump() now logs the lame zones associated
+ with each server.
+
+1373. [bug] Recovery from expired glue failed under certain
+ circumstances.
+
+1372. [bug] named crashes with an assertion failure on exit when
+ sharing the same port for listening and querying, and
+ changing listening addresses several times. [RT# 3509]
+
+1371. [bug] notify-source-v6, transfer-source-v6 and
+ query-source-v6 with explicit addresses and using the
+ same ports as named was listening on could interfere
+ with named's ability to answer queries sent to those
+ addresses.
+
+1370. [bug] dig '+[no]recurse' was incorrectly documented.
+
+1369. [bug] Adding an NS record as the lexicographically last
+ record in a secure zone didn't work.
+
+1368. [func] remove support for bitstring labels.
+
+1367. [func] Use response times to select forwarders.
+
+1366. [contrib] queryperf usage was incomplete. Add '-h' for help.
+
+1365. [func] "localhost" and "localnets" acls now include IPv6
+ addresses / prefixes.
+
+1364. [func] Log file name when unable to open memory statistics
+ and dump database files. [RT# 3437]
+
+1363. [func] Listen-on-v6 now supports specific addresses.
+
+1362. [bug] remove IFF_RUNNING test when scanning interfaces.
+
+1361. [func] log the reason for rejecting a server when resolving
+ queries.
+
+1360. [bug] --enable-libbind would fail when not built in the
+ source tree for certain OS's.
+
+1359. [security] Support patches OpenSSL libraries.
+ http://www.cert.org/advisories/CA-2002-23.html
+
+1358. [bug] It was possible to trigger a INSIST when debugging
+ large dynamic updates. [RT #3390]
+
+1357. [bug] nsupdate was extremely wasteful of memory.
+
+1356. [tuning] Reduce the number of events / quantum for zone tasks.
+
+1355. [bug] Fix DNSSEC wildcard proof for CNAME/DNAME.
+
+1354. [doc] lwres man pages had illegal nroff.
+
+1353. [contrib] sdb/ldap to version 0.9.
+
+1352. [bug] dig, host, nslookup when falling back to TCP use the
+ current search entry (if any). [RT #3374]
+
+1351. [bug] lwres_getipnodebyname() returned the wrong name
+ when given a IPv4 literal, af=AF_INET6 and AI_MAPPED
+ was set.
+
+1350. [bug] dns_name_fromtext() failed to handle too many labels
+ gracefully.
+
+1349. [security] Minimum OpenSSL version now 0.9.6e (was 0.9.5a).
+ http://www.cert.org/advisories/CA-2002-23.html
+
+1348. [port] win32: Rewrote code to use I/O Completion Ports
+ in socket.c and eliminating a host of socket
+ errors. Performance is enhanced.
+
+1347. [placeholder]
+
+1346. [placeholder]
+
+1345. [port] Use a explicit -Wformat with gcc. Not all versions
+ include it in -Wall.
+
+1344. [func] Log if the serial number on the master has gone
+ backwards.
+ If you have multiple machines specified in the masters
+ clause you may want to set 'multi-master yes;' to
+ suppress this warning.
+
+1343. [func] Log successful notifies received (info). Adjust log
+ level for failed notifies to notice.
+
+1342. [func] Log remote address with TCP dispatch failures.
+
+1341. [func] Allow a rate limiter to be stalled.
+
+1340. [bug] Delay and spread out the startup refresh load.
+
+1339. [func] dig, host and nslookup now use IP6.ARPA for nibble
+ lookups. Bit string lookups are no longer attempted.
+
+1338. [placeholder]
+
+1337. [placeholder]
+
+1336. [func] Nibble lookups under IP6.ARPA are now supported by
+ dns_byaddr_create(). dns_byaddr_createptrname() is
+ deprecated, use dns_byaddr_createptrname2() instead.
+
+1335. [bug] When performing a nonexistence proof, the validator
+ should discard parent NXTs from higher in the DNS.
+
+1334. [bug] When signing/verifying rdatasets, duplicate rdatas
+ need to be suppressed.
+
+1333. [contrib] queryperf now reports a summary of returned
+ rcodes (-c), rcodes are printed in mnemonic form (-v).
+
+1332. [func] Report the current serial with periodic commits when
+ rolling forward the journal.
+
+1331. [func] Generate DNSSEC wildcard proofs.
+
+1330. [bug] When processing events (non-threaded) only allow
+ the task one chance to use to use its quantum.
+
+1329. [func] named-checkzone will now check if nameservers that
+ appear to be IP addresses. Available modes "fail",
+ "warn" (default) and "ignore" the results of the
+ check.
+
+1328. [bug] The validator could incorrectly verify an invalid
+ negative proof.
+
+1327. [bug] The validator would incorrectly mark data as insecure
+ when seeing a bogus signature before a correct
+ signature.
+
+1326. [bug] DNAME/CNAME signatures were not being cached when
+ validation was not being performed. [RT #3284]
+
+1325. [bug] If the tcpquota was exhausted it was possible to
+ to trigger a INSIST() failure.
+
+1324. [port] darwin: ifconfig.sh now supports darwin.
+
+1323. [port] linux: Slackware 4.0 needs <asm/unistd.h>. [RT #3205]
+
+1322. [bug] dnssec-signzone usage message was misleading.
+
+1321. [bug] If the last RRset in a zone is glue, dnssec-signzone
+ would incorrectly duplicate its output and sign it.
+
+1320. [doc] query-source-v6 was missing from options section.
+ [RT #3218]
+
+1319. [func] libbind: log attempts to exploit #1318.
+
+1318. [bug] libbind: Remote buffer overrun.
+
+1317. [port] libbind: TrueUNIX 5.1 does not like __align as a
+ element name.
+
+1316. [bug] libbind: gethostans() could get out of sync parsing
+ the response if there was a very long CNAME chain.
+
+1315. [bug] Options should apply to the internal _bind view.
+
+1314. [port] Handle ECONNRESET from sendmsg() [unix].
+
+1313. [func] Query log now says if the query was signed (S) or
+ if EDNS was used (E).
+
+1312. [func] Log TSIG key used w/ outgoing zone transfers.
+
+1311. [bug] lwres_getrrsetbyname leaked memory. [RT #3159]
+
+1310. [bug] 'rndc stop' failed to cause zones to be flushed
+ sometimes. [RT #3157]
+
+1309. [func] Log that a zone transfer was covered by a TSIG.
+
+1308. [func] DS (delegation signer) support.
+
+1307. [bug] nsupdate: allow white space base64 key data.
+
+1306. [bug] Badly encoded LOC record when the size, horizontal
+ precision or vertical precision was 0.1m.
+
+1305. [bug] Document that internal zones are included in the
+ rndc status results.
+
+1304. [func] New function: dns_zone_name().
+
+1303. [func] Option 'flush-zones-on-shutdown <boolean>;'.
+
+1302. [func] Extended rndc dumpdb to support dumping of zones and
+ view selection: 'dumpdb [-all|-zones|-cache] [view]'.
+
+1301. [func] New category 'update-security'.
+
+1300. [port] Compaq Trucluster support.
+
+1299. [bug] Set AI_ADDRCONFIG when looking up addresses
+ via getaddrinfo() (affects dig, host, nslookup, rndc
+ and nsupdate).
+
+1298. [bug] The CINCLUDES macro in lib/dns/sec/dst/Makefile
+ could be left with a trailing "\" after configure
+ has been run.
+
+1297. [port] linux: make handling EINVAL from socket() no longer
+ conditional on #ifdef LINUX.
+
+1296. [bug] isc_log_closefilelogs() needed to lock the log
+ context.
+
+1295. [bug] isc_log_setdebuglevel() needed to lock the log
+ context.
+
+1294. [func] libbind: no longer attempts bit string labels for
+ IPv6 reverse resolution. Try IP6.ARPA then IP6.INT
+ for nibble style resolution.
+
+1293. [func] Entropy can now be retrieved from EGDs. [RT #2438]
+
+1292. [func] Enable IPv6 support when using ioctl style interface
+ scanning and OS supports SIOCGLIFADDR using struct
+ if_laddrreq.
+
+1291. [func] Enable IPv6 support when using sysctl style interface
+ scanning.
+
+1290. [func] "dig axfr" now reports the number of messages
+ as well as the number of records.
+
+1289. [port] See if -ldl is required for OpenSSL? [RT #2672]
+
+1288. [bug] Adjusted REQUIRE's in lib/dns/name.c to better
+ reflect written requirements.
+
+1287. [bug] REQUIRE that DNS_DBADD_MERGE only be set when adding
+ a rdataset to a zone db in the rbtdb implementation of
+ addrdataset.
+
+1286. [bug] dns_name_downcase() enforce requirement that
+ target != NULL or name->buffer != NULL.
+
+1285. [func] lwres: probe the system to see what address families
+ are currently in use.
+
+1284. [bug] The RTT estimate on unused servers was not aged.
+ [RT #2569]
+
+1283. [func] Use "dataready" accept filter if available.
+
+1282. [port] libbind: hpux 11.11 interface scanning.
+
+1281. [func] Log zone when unable to get private keys to update
+ zone. Log zone when NXT records are missing from
+ secure zone.
+
+1280. [bug] libbind: escape '(' and ')' when converting to
+ presentation form.
+
+1279. [port] Darwin uses (unsigned long) for size_t. [RT #2590]
+
+1278. [func] dig: now supports +[no]cl +[no]ttlid.
+
+1277. [func] You can now create your own customized printing
+ styles: dns_master_stylecreate() and
+ dns_master_styledestroy().
+
+1276. [bug] libbind: const pointer conflicts in res_debug.c.
+
+1275. [port] libbind: hpux: treat all hpux systems as BIG_ENDIAN.
+
+1274. [bug] Memory leak in lwres_gnbarequest_parse().
+
+1273. [port] libbind: solaris: 64 bit binary compatibility.
+
+1272. [contrib] Berkeley DB 4.0 sdb implementation from
+ Nuno Miguel Rodrigues <nmr@co.sapo.pt>.
+
+1271. [bug] "recursion available: {denied,approved}" was too
+ confusing.
+
+1270. [bug] Check that system inet_pton() and inet_ntop() support
+ AF_INET6.
+
+1269. [port] Openserver: ifconfig.sh support.
+
+1268. [port] Openserver: the value FD_SETSIZE depends on whether
+ <sys/param.h> is included or not. Be consistent.
+
+1267. [func] isc_file_openunique() now creates file using mode
+ 0666 rather than 0600.
+
+1266. [bug] ISC_LINK_INIT, ISC_LINK_UNLINK, ISC_LIST_DEQUEUE,
+ __ISC_LINK_UNLINKUNSAFE and __ISC_LIST_DEQUEUEUNSAFE
+ are not C++ compatible, use *_TYPE versions instead.
+
+1265. [bug] libbind: LINK_INIT and UNLINK were not compatible with
+ C++, use LINK_INIT_TYPE and UNLINK_TYPE instead.
+
+1264. [placeholder]
+
+1263. [bug] Reference after free error if dns_dispatchmgr_create()
+ failed.
+
+1262. [bug] ns_server_destroy() failed to set *serverp to NULL.
+
+1261. [func] libbind: ns_sign2() and ns_sign_tcp() now provide
+ support for compressed TSIG owner names.
+
+1260. [func] libbind: res_update can now update IPv6 servers,
+ new function res_findzonecut2().
+
+1259. [bug] libbind: get_salen() IPv6 support was broken for OSs
+ w/o sa_len.
+
+1258. [bug] libbind: res_nametotype() and res_nametoclass() were
+ broken.
+
+1257. [bug] Failure to write pid-file should not be fatal on
+ reload. [RT #2861]
+
+1256. [contrib] 'queryperf' now has EDNS (-e) + DNSSEC DO (-D) support.
+
+1255. [bug] When verifying that an NXT proves nonexistence, check
+ the rcode of the message and only do the matching NXT
+ check. That is, for NXDOMAIN responses, check that
+ the name is in the range between the NXT owner and
+ next name, and for NOERROR NODATA responses, check
+ that the type is not present in the NXT bitmap.
+
+1254. [func] preferred-glue option from BIND 8.3.
+
+1253. [bug] The dnssec system test failed to remove the correct
+ files.
+
+1252. [bug] Dig, host and nslookup were not checking the address
+ the answer was coming from against the address it was
+ sent to. [RT# 2692]
+
+1251. [port] win32: a make file contained absolute version specific
+ references.
+
+1250. [func] Nsupdate will report the address the update was
+ sent to.
+
+1249. [bug] Missing masters clause was not handled gracefully.
+ [RT #2703]
+
+1248. [bug] DESTDIR was not being propagated between makes.
+
+1247. [bug] Don't reset the interface index for link/site local
+ addresses. [RT #2576]
+
+1246. [func] New functions isc_sockaddr_issitelocal(),
+ isc_sockaddr_islinklocal(), isc_netaddr_issitelocal()
+ and isc_netaddr_islinklocal().
+
+1245. [bug] Treat ENOBUFS, ENOMEM and ENFILE as soft errors for
+ accept().
+
+1244. [bug] Receiving a TCP message from a blackhole address would
+ prevent further messages being received over that
+ interface.
+
+1243. [bug] It was possible to trigger a REQUIRE() in
+ dns_message_findtype(). [RT #2659]
+
+1242. [bug] named-checkzone failed if a journal existed. [RT #2657]
+
+1241. [bug] Drop received UDP messages with a zero source port
+ as these are invariably forged. [RT #2621]
+
+1240. [bug] It was possible to leak zone references by
+ specifying an incorrect zone to rndc.
+
+1239. [bug] Under certain circumstances named could continue to
+ use a name after it had been freed triggering
+ INSIST() failures. [RT #2614]
+
+1238. [bug] It is possible to lockup the server when shutting down
+ if notifies were being processed. [RT #2591]
+
+1237. [bug] nslookup: "set q=type" failed.
+
+1236. [bug] dns_rdata{class,type}_fromtext() didn't handle non
+ NULL terminated text regions. [RT #2588]
+
+1235. [func] Report 'out of memory' errors from openssl.
+
+1234. [bug] contrib/sdb: 'zonetodb' failed to call
+ dns_result_register(). DNS_R_SEENINCLUDE should not
+ be fatal.
+
+1233. [bug] The flags field of a KEY record can be expressed in
+ hex as well as decimal.
+
+1232. [bug] unix/errno2result() didn't handle EADDRNOTAVAIL.
+
+1231. [port] HPUX 11.11 recvmsg() can return spurious EADDRNOTAVAIL.
+
+1230. [bug] isccc_cc_isreply() and isccc_cc_isack() were broken.
+
+1229. [bug] named would crash if it received a TSIG signed
+ query as part of an AXFR response. [RT #2570]
+
+1228. [bug] 'make install' did not depend on 'make all'. [RT #2559]
+
+1227. [bug] dns_lex_getmastertoken() now returns ISC_R_BADNUMBER
+ if a number was expected and some other token was
+ found. [RT#2532]
+
+1226. [func] Use EDNS for zone refresh queries. [RT #2551]
+
+1225. [func] dns_message_setopt() no longer requires that
+ dns_message_renderbegin() to have been called.
+
+1224. [bug] 'rrset-order' and 'sortlist' should be additive
+ not exclusive.
+
+1223. [func] 'rrset-order' partially works 'cyclic' and 'random'
+ are supported.
+
+1222. [bug] Specifying 'port *' did not always result in a system
+ selected (non-reserved) port being used. [RT #2537]
+
+1221. [bug] Zone types 'master', 'slave' and 'stub' were not being
+ compared case insensitively. [RT #2542]
+
+1220. [func] Support for APL rdata type.
+
+1219. [func] Named now reports the TSIG extended error code when
+ signature verification fails. [RT #1651]
+
+1218. [bug] Named incorrectly returned SERVFAIL rather than
+ NOTAUTH when there was a TSIG BADTIME error. [RT #2519]
+
+1217. [func] Report locations of previous key definition when a
+ duplicate is detected.
+
+1216. [bug] Multiple server clauses for the same server were not
+ reported. [RT #2514]
+
+1215. [port] solaris: add support to ifconfig.sh for x86 2.5.1
+
+1214. [bug] Win32: isc_file_renameunique() could leave zero length
+ files behind.
+
+1213. [func] Report view associated with client if it is not a
+ standard view (_default or _bind).
+
+1212. [port] libbind: 64k answer buffers were causing stack space
+ to be exceeded for certain OS. Use heap space instead.
+
+1211. [bug] dns_name_fromtext() incorrectly handled certain
+ valid octal bitlabels. [RT #2483]
+
+1210. [bug] libbind: getnameinfo() failed to lookup IPv4 mapped /
+ compatible addresses. [RT #2461]
+
+1209. [bug] Dig, host, nslookup were not checking the message ids
+ on the responses. [RT #2454]
+
+1208. [bug] dns_master_load*() failed to log a error message if
+ an error was detected when parsing the ownername of
+ a record. [RT #2448]
+
+1207. [bug] libbind: getaddrinfo() could call freeaddrinfo() with
+ an invalid pointer.
+
+1206. [bug] SERVFAIL and NOTIMP responses to an EDNS query should
+ trigger a non-EDNS retry.
+
+1205. [bug] OPT, TSIG and TKEY cannot be used to set the "class"
+ of the message. [RT #2449]
+
+1204. [bug] libbind: res_nupdate() failed to update the name
+ server addresses before sending the update.
+
+1203. [func] Report locations of previous acl and zone definitions
+ when a duplicate is detected.
+
+1202. [func] New functions: cfg_obj_line() and cfg_obj_file().
+
+1201. [bug] Require that if 'callbacks' is passed to
+ dns_rdata_fromtext(), callbacks->error and
+ callbacks->warn are initialized.
+
+1200. [bug] Log 'errno' that we are unable to convert to
+ isc_result_t. [RT #2404]
+
+1199. [doc] ARM reference to RFC 2157 should have been RFC 1918.
+ [RT #2436]
+
+1198. [bug] OPT printing style was not consistent with the way the
+ header fields are printed. The DO bit was not reported
+ if set. Report if any of the MBZ bits are set.
+
+1197. [bug] Attempts to define the same acl multiple times were not
+ detected.
+
+1196. [contrib] update mdnkit to 2.2.3.
+
+1195. [bug] Attempts to redefine builtin acls should be caught.
+ [RT #2403]
+
+1194. [bug] Not all duplicate zone definitions were being detected
+ at the named.conf checking stage. [RT #2431]
+
+1193. [bug] dig +besteffort parsing didn't handle packet
+ truncation. dns_message_parse() has new flag
+ DNS_MESSAGE_IGNORETRUNCATION.
+
+1192. [bug] The seconds fields in LOC records were restricted
+ to three decimal places. More decimal places should
+ be allowed but warned about.
+
+1191. [bug] A dynamic update removing the last non-apex name in
+ a secure zone would fail. [RT #2399]
+
+1190. [func] Add the "rndc freeze" and "rndc unfreeze" commands.
+ [RT #2394]
+
+1189. [bug] On some systems, malloc(0) returns NULL, which
+ could cause the caller to report an out of memory
+ error. [RT #2398]
+
+1188. [bug] Dynamic updates of a signed zone would fail if
+ some of the zone private keys were unavailable.
+
+1187. [bug] named was incorrectly returning DNSSEC records
+ in negative responses when the DO bit was not set.
+
+1186. [bug] isc_hex_tobuffer(,,length = 0) failed to unget the
+ EOL token when reading to end of line.
+
+1185. [bug] libbind: don't assume statp->_u._ext.ext is valid
+ unless RES_INIT is set when calling res_*init().
+
+1184. [bug] libbind: call res_ndestroy() if RES_INIT is set
+ when res_*init() is called.
+
+1183. [bug] Handle ENOSR error when writing to the internal
+ control pipe. [RT #2395]
+
+1182. [bug] The server could throw an assertion failure when
+ constructing a negative response packet.
+
+1181. [func] Add the "key-directory" configuration statement,
+ which allows the server to look for online signing
+ keys in alternate directories.
+
+1180. [func] dnssec-keygen should always generate keys with
+ protocol 3 (DNSSEC), since it's less confusing
+ that way.
+
+1179. [func] Add SIG(0) support to nsupdate.
+
+1178. [bug] Follow and cache (if appropriate) A6 and other
+ data chains to completion in the additional section.
+
+1177. [func] Report view when loading zones if it is not a
+ standard view (_default or _bind). [RT #2270]
+
+1176. [doc] Document that allow-v6-synthesis is only performed
+ for clients that are supplied recursive service.
+ [RT #2260]
+
+1175. [bug] named-checkzone and named-checkconf failed to call
+ dns_result_register() at startup which could
+ result in runtime exceptions when printing
+ "out of memory" errors. [RT #2335]
+
+1174. [bug] Win32: add WSAECONNRESET to the expected errors
+ from connect(). [RT #2308]
+
+1173. [bug] Potential memory leaks in isc_log_create() and
+ isc_log_settag(). [RT #2336]
+
+1172. [doc] Add CERT, GPOS, KX, NAPTR, NSAP, PX and TXT to
+ table of RR types in ARM.
+
+1171. [func] Added function isc_region_compare(), updated files in
+ lib/dns to use this function instead of local one.
+
+1170. [bug] Don't attempt to print the token when a I/O error
+ occurs when parsing named.conf. [RT #2275]
+
+1169. [func] Identify recursive queries in the query log.
+
+1168. [bug] Empty also-notify clauses were not handled. [RT #2309]
+
+1167. [contrib] nslint-2.1a3 (from author).
+
+1166. [bug] "Not Implemented" should be reported as NOTIMP,
+ not NOTIMPL. [RT #2281]
+
+1165. [bug] We were rejecting notify-source{-v6} in zone clauses.
+
+1164. [bug] Empty masters clauses in slave / stub zones were not
+ handled gracefully. [RT #2262]
+
+1163. [func] isc_time_formattimestamp() now includes the year.
+
+1162. [bug] The allow-notify option was not accepted in slave
+ zone statements.
+
+1161. [bug] named-checkzone looped on unbalanced brackets.
+ [RT #2248]
+
+1160. [bug] Generating Diffie-Hellman keys longer than 1024
+ bits could fail. [RT #2241]
+
+1159. [bug] MD and MF are not permitted to be loaded by RFC1123.
+
+1158. [func] Report the client's address when logging notify
+ messages.
+
+1157. [func] match-clients and match-destinations now accept
+ keys. [RT #2045]
+
+1156. [port] The configure test for strsep() incorrectly
+ succeeded on certain patched versions of
+ AIX 4.3.3. [RT #2190]
+
+1155. [func] Recover from master files being removed from under
+ us.
+
+1154. [bug] Don't attempt to obtain the netmask of a interface
+ if there is no address configured. [RT #2176]
+
+1153. [func] 'rndc {stop|halt} -p' now reports the process id
+ of the instance of named being shutdown.
+
+1152. [bug] libbind: read buffer overflows.
+
+1151. [bug] nslookup failed to check that the arguments to
+ the port, timeout, and retry options were
+ valid integers and in range. [RT #2099]
+
+1150. [bug] named incorrectly accepted TTL values
+ containing plus or minus signs, such as
+ 1d+1h-1s.
+
+1149. [func] New function isc_parse_uint32().
+
+1148. [func] 'rndc-confgen -a' now provides positive feedback.
+
+1147. [func] Set IPV6_V6ONLY on IPv6 sockets if supported by
+ the OS. listen-on-v6 { any; }; should no longer
+ result in IPv4 queries be accepted. Similarly
+ control { inet :: ... }; should no longer result
+ in IPv4 connections being accepted. This can be
+ overridden at compile time by defining
+ ISC_ALLOW_MAPPED=1.
+
+1146. [func] Allow IPV6_IPV6ONLY to be set/cleared on a socket if
+ supported by the OS by a new function
+ isc_socket_ipv6only().
+
+1145. [func] "host" no longer reports a NOERROR/NODATA response
+ by printing nothing. [RT #2065]
+
+1144. [bug] rndc-confgen would crash if both the -a and -t
+ options were specified. [RT #2159]
+
+1143. [bug] When a trusted-keys statement was present and named
+ was built without crypto support, it would leak memory.
+
+1142. [bug] dnssec-signzone would fail to delete temporary files
+ in some failure cases. [RT #2144]
+
+1141. [bug] When named rejected a control message, it would
+ leak a file descriptor and memory. It would also
+ fail to respond, causing rndc to hang.
+ [RT #2139, #2164]
+
+1140. [bug] rndc-confgen did not accept IPv6 addresses as arguments
+ to the -s option. [RT #2138]
+
+1139. [func] It is now possible to flush a given name from the
+ cache(s) via 'rndc flushname name [view]'. [RT #2051]
+
+1138. [func] It is now possible to flush a given name from the
+ cache by calling the new function
+ dns_cache_flushname().
+
+1137. [func] It is now possible to flush a given name from the
+ ADB by calling the new function dns_adb_flushname().
+
+1136. [bug] CNAME records synthesized from DNAMEs did not
+ have a TTL of zero as required by RFC2672.
+ [RT #2129]
+
+1135. [func] You can now override the default syslog() facility for
+ named/lwresd at compile time. [RT #1982]
+
+1134. [bug] Multi-threaded servers could deadlock in ferror()
+ when reloading zone files. [RT #1951, #1998]
+
+1133. [bug] IN6_IS_ADDR_LOOPBACK was not portably defined on
+ platforms without IN6_IS_ADDR_LOOPBACK. [RT #2106]
+
+1132. [func] Improve UPDATE prerequisite failure diagnostic messages.
+
+1131. [bug] The match-destinations view option did not work with
+ IPv6 destinations. [RT #2073, #2074]
+
+1130. [bug] Log messages reporting an out-of-range serial number
+ did not include the out-of-range number but the
+ following token. [RT #2076]
+
+1129. [bug] Multi-threaded servers could crash under heavy
+ resolution load due to a race condition. [RT #2018]
+
+1128. [func] sdb drivers can now provide RR data in either text
+ or wire format, the latter using the new functions
+ dns_sdb_putrdata() and dns_sdb_putnamedrdata().
+
+1127. [func] rndc: If the server to contact has multiple addresses,
+ try all of them.
+
+1126. [bug] The server could access a freed event if shut
+ down while a client start event was pending
+ delivery. [RT #2061]
+
+1125. [bug] rndc: -k option was missing from usage message.
+ [RT #2057]
+
+1124. [doc] dig: +[no]dnssec, +[no]besteffort and +[no]fail
+ are now documented. [RT #2052]
+
+1123. [bug] dig +[no]fail did not match description. [RT #2052]
+
+1122. [tuning] Resolution timeout reduced from 90 to 30 seconds.
+ [RT #2046]
+
+1121. [bug] The server could attempt to access a NULL zone
+ table if shut down while resolving.
+ [RT #1587, #2054]
+
+1120. [bug] Errors in options were not fatal. [RT #2002]
+
+1119. [func] Added support in Win32 for NTFS file/directory ACL's
+ for access control.
+
+1118. [bug] On multi-threaded servers, a race condition
+ could cause an assertion failure in resolver.c
+ during resolver shutdown. [RT #2029]
+
+1117. [port] The configure check for in6addr_loopback incorrectly
+ succeeded on AIX 4.3 when compiling with -O2
+ because the test code was optimized away.
+ [RT #2016]
+
+1116. [bug] Setting transfers in a server clause, transfers-in,
+ or transfers-per-ns to a value greater than
+ 2147483647 disabled transfers. [RT #2002]
+
+1115. [func] Set maximum values for cleaning-interval,
+ heartbeat-interval, interface-interval,
+ max-transfer-idle-in, max-transfer-idle-out,
+ max-transfer-time-in, max-transfer-time-out,
+ statistics-interval of 28 days and
+ sig-validity-interval of 3660 days. [RT #2002]
+
+1114. [port] Ignore more accept() errors. [RT #2021]
+
+1113. [bug] The allow-update-forwarding option was ignored
+ when specified in a view. [RT #2014]
+
+1112. [placeholder]
+
+1111. [bug] Multi-threaded servers could deadlock processing
+ recursive queries due to a locking hierarchy
+ violation in adb.c. [RT #2017]
+
+1110. [bug] dig should only accept valid abbreviations of +options.
+ [RT #2003]
+
+1109. [bug] nsupdate accepted illegal ttl values.
+
+1108. [bug] On Win32, rndc was hanging when named was not running
+ due to failure to select for exceptional conditions
+ in select(). [RT #1870]
+
+1107. [bug] nsupdate could catch an assertion failure if an
+ invalid domain name was given as the argument to
+ the "zone" command.
+
+1106. [bug] After seeing an out of range TTL, nsupdate would
+ treat all TTLs as out of range. [RT #2001]
+
+1105. [port] OpenUNIX 8 enable threads by default. [RT #1970]
+
+1104. [bug] Invalid arguments to the transfer-format option
+ could cause an assertion failure. [RT #1995]
+
+1103. [port] OpenUNIX 8 support (ifconfig.sh). [RT #1970]
+
+1102. [doc] Note that query logging is enabled by directing the
+ queries category to a channel.
+
+1101. [bug] Array bounds read error in lwres_gai_strerror.
+
+1100. [bug] libbind: DNSSEC key ids were computed incorrectly.
+
+1099. [cleanup] libbind: defining REPORT_ERRORS in lib/bind/dst caused
+ compile time errors.
+
+1098. [bug] libbind: HMAC-MD5 key files are now mode 0600.
+
+1097. [func] libbind: RES_PRF_TRUNC for dig.
+
+1096. [func] libbind: "DNSSEC OK" (DO) support.
+
+1095. [func] libbind: resolver option: no-tld-query. disables
+ trying unqualified as a tld. no_tld_query is also
+ supported for FreeBSD compatibility.
+
+1094. [func] libbind: add support gcc's format string checking.
+
+1093. [doc] libbind: miscellaneous nroff fixes.
+
+1092. [bug] libbind: get*by*() failed to check if res_init() had
+ been called.
+
+1091. [bug] libbind: misplaced va_end().
+
+1090. [bug] libbind: dns_ho.c:add_hostent() was not returning
+ the amount of memory consumed resulting in garbage
+ address being returned. Alignment calculations were
+ wasting space. We weren't suppressing duplicate
+ addresses.
+
+1089. [func] libbind: inet_{cidr,net}_{pton,ntop}() now have IPv6
+ support.
+
+1088. [port] libbind: MPE/iX C.70 (incomplete)
+
+1087. [bug] libbind: struct __res_state too large on 64 bit arch.
+
+1086. [port] libbind: sunos: old sprintf.
+
+1085. [port] libbind: solaris: sys_nerr and sys_errlist do not
+ exist when compiling in 64 bit mode.
+
+1084. [cleanup] libbind: gai_strerror() rewritten.
+
+1083. [bug] The default control channel listened on the
+ wildcard address, not the loopback as documented.
+ [RT #1975]
+
+1082. [bug] The -g option to named incorrectly caused logging
+ to be sent to syslog in addition to stderr.
+ [RT #1974]
+
+1081. [bug] Multicast queries were incorrectly identified
+ based on the source address, not the destination
+ address.
+
+1080. [bug] BIND 8 compatibility: accept bare IP prefixes
+ as the second element of a two-element top level
+ sort list statement. [RT #1964]
+
+1079. [bug] BIND 8 compatibility: accept bare elements at top
+ level of sort list treating them as if they were
+ a single element list. [RT #1963]
+
+1078. [bug] We failed to correct bad tv_usec values in one case.
+ [RT #1966]
+
+1077. [func] Do not accept further recursive clients when
+ the total number of recursive lookups being
+ processed exceeds max-recursive-clients, even
+ if some of the lookups are internally generated.
+ [RT #1915, #1938]
+
+1076. [bug] A badly defined global key could trigger an assertion
+ on load/reload if views were used. [RT #1947]
+
+1075. [bug] Out-of-range network prefix lengths were not
+ reported. [RT #1954]
+
+1074. [bug] Running out of memory in dump_rdataset() could
+ cause an assertion failure. [RT #1946]
+
+1073. [bug] The ADB cache cleaning should also be space driven.
+ [RT #1915, #1938]
+
+1072. [bug] The TCP client quota could be exceeded when
+ recursion occurred. [RT #1937]
+
+1071. [bug] Sockets listening for TCP DNS connections
+ specified an excessive listen backlog. [RT #1937]
+
+1070. [bug] Copy DNSSEC OK (DO) to response as specified by
+ draft-ietf-dnsext-dnssec-okbit-03.txt.
+
+1069. [placeholder]
+
+1068. [bug] errno could be overwritten by catgets(). [RT #1921]
+
+1067. [func] Allow quotas to be soft, isc_quota_soft().
+
+1066. [bug] Provide a thread safe wrapper for strerror().
+ [RT #1689]
+
+1065. [func] Runtime support to select new / old style interface
+ scanning using ioctls.
+
+1064. [bug] Do not shut down active network interfaces if we
+ are unable to scan the interface list. [RT #1921]
+
+1063. [bug] libbind: "make install" was failing on IRIX.
+ [RT #1919]
+
+1062. [bug] If the control channel listener socket was shut
+ down before server exit, the listener object could
+ be freed twice. [RT #1916]
+
+1061. [bug] If periodic cache cleaning happened to start
+ while cleaning due to reaching the configured
+ maximum cache size was in progress, the server
+ could catch an assertion failure. [RT #1912]
+
+1060. [func] Move refresh, stub and notify UDP retry processing
+ into dns_request.
+
+1059. [func] dns_request now support will now retry UDP queries,
+ dns_request_createvia2() and dns_request_createraw2().
+
+1058. [func] Limited lifetime ticker timers are now available,
+ isc_timertype_limited.
+
+1057. [bug] Reloading the server after adding a "file" clause
+ to a zone statement could cause the server to
+ crash due to a typo in change 1016.
+
+1056. [bug] Rndc could catch an assertion failure on SIGINT due
+ to an uninitialized variable. [RT #1908]
+
+1055. [func] Version and hostname queries can now be disabled
+ using "version none;" and "hostname none;",
+ respectively.
+
+1054. [bug] On Win32, cfg_categories and cfg_modules need to be
+ exported from the libisccfg DLL.
+
+1053. [bug] Dig did not increase its timeout when receiving
+ AXFRs unless the +time option was used. [RT #1904]
+
+1052. [bug] Journals were not being created in binary mode
+ resulting in "journal format not recognized" error
+ under Win32. [RT #1889]
+
+1051. [bug] Do not ignore a network interface completely just
+ because it has a noncontiguous netmask. Instead,
+ omit it from the localnets ACL and issue a warning.
+ [RT #1891]
+
+1050. [bug] Log messages reporting malformed IP addresses in
+ address lists such as that of the forwarders option
+ failed to include the correct error code, file
+ name, and line number. [RT #1890]
+
+1049. [func] "pid-file none;" will disable writing a pid file.
+ [RT #1848]
+
+1048. [bug] Servers built with -DISC_MEM_USE_INTERNAL_MALLOC=1
+ didn't work.
+
+1047. [bug] named was incorrectly refusing all requests signed
+ with a TSIG key derived from an unsigned TKEY
+ negotiation with a NOERROR response. [RT #1886]
+
+1046. [bug] The help message for the --with-openssl configure
+ option was inaccurate. [RT #1880]
+
+1045. [bug] It was possible to skip saving glue for a nameserver
+ for a stub zone.
+
+1044. [bug] Specifying allow-transfer, notify-source, or
+ notify-source-v6 in a stub zone was not treated
+ as an error.
+
+1043. [bug] Specifying a transfer-source or transfer-source-v6
+ option in the zone statement for a master zone was
+ not treated as an error. [RT #1876]
+
+1042. [bug] The "config" logging category did not work properly.
+ [RT #1873]
+
+1041. [bug] Dig/host/nslookup could catch an assertion failure
+ on SIGINT due to an uninitialized variable. [RT #1867]
+
+1040. [bug] Multiple listen-on-v6 options with different ports
+ were not accepted. [RT #1875]
+
+1039. [bug] Negative responses with CNAMEs in the answer section
+ were cached incorrectly. [RT #1862]
+
+1038. [bug] In servers configured with a tkey-domain option,
+ TKEY queries with an owner name other than the root
+ could cause an assertion failure. [RT #1866, #1869]
+
+1037. [bug] Negative responses whose authority section contain
+ SOA or NS records whose owner names are not equal
+ equal to or parents of the query name should be
+ rejected. [RT #1862]
+
+1036. [func] Silently drop requests received via multicast as
+ long as there is no final multicast DNS standard.
+
+1035. [bug] If we respond to multicast queries (which we
+ currently do not), respond from a unicast address
+ as specified in RFC 1123. [RT #137]
+
+1034. [bug] Ignore the RD bit on multicast queries as specified
+ in RFC 1123. [RT #137]
+
+1033. [bug] Always respond to requests with an unsupported opcode
+ with NOTIMP, even if we don't have a matching view
+ or cannot determine the class.
+
+1032. [func] hostname.bind/txt/chaos now returns the name of
+ the machine hosting the nameserver. This is useful
+ in diagnosing problems with anycast servers.
+
+1031. [bug] libbind.a: isc__gettimeofday() infinite recursion.
+ [RT #1858]
+
+1030. [bug] On systems with no resolv.conf file, nsupdate
+ exited with an error rather than defaulting
+ to using the loopback address. [RT #1836]
+
+1029. [bug] Some named.conf errors did not cause the loading
+ of the configuration file to return a failure
+ status even though they were logged. [RT #1847]
+
+1028. [bug] On Win32, dig/host/nslookup looked for resolv.conf
+ in the wrong directory. [RT #1833]
+
+1027. [bug] RRs having the reserved type 0 should be rejected.
+ [RT #1471]
+
+1026. [placeholder]
+
+1025. [bug] Don't use multicast addresses to resolve iterative
+ queries. [RT #101]
+
+1024. [port] Compilation failed on HP-UX 11.11 due to
+ incompatible use of the SIOCGLIFCONF macro
+ name. [RT #1831]
+
+1023. [func] Accept hints without TTLs.
+
+1022. [bug] Don't report empty root hints as "extra data".
+ [RT #1802]
+
+1021. [bug] On Win32, log message timestamps were one month
+ later than they should have been, and the server
+ would exhibit unspecified behavior in December.
+
+1020. [bug] IXFR log messages did not distinguish between
+ true IXFRs, AXFR-style IXFRs, and mere version
+ polls. [RT #1811]
+
+1019. [bug] The value of the lame-ttl option was limited to 18000
+ seconds, not 1800 seconds as documented. [RT #1803]
+
+1018. [bug] The default log channel was not always initialized
+ correctly. [RT #1813]
+
+1017. [bug] When specifying TSIG keys to dig and nsupdate using
+ the -k option, they must be HMAC-MD5 keys. [RT #1810]
+
+1016. [bug] Slave zones with no backup file were re-transferred
+ on every server reload.
+
+1015. [bug] Log channels that had a "versions" option but no
+ "size" option failed to create numbered log
+ files. [RT #1783]
+
+1014. [bug] Some queries would cause statistics counters to
+ increment more than once or not at all. [RT #1321]
+
+1013. [bug] It was possible to cancel a query twice when marking
+ a server as bogus or by having a blackhole acl.
+ [RT #1776]
+
+1012. [bug] The -p option to named did not behave as documented.
+
+1011. [cleanup] Removed isc_dir_current().
+
+1010. [bug] The server could attempt to execute a command channel
+ command after initiating server shutdown, causing
+ an assertion failure. [RT #1766]
+
+1009. [port] OpenUNIX 8 support. [RT #1728]
+
+1008. [port] libtool.m4, ltmain.sh from libtool-1.4.2.
+
+1007. [port] config.guess, config.sub from autoconf-2.52.
+
+1006. [bug] If a KEY RR was found missing during DNSSEC validation,
+ an assertion failure could subsequently be triggered
+ in the resolver. [RT #1763]
+
+1005. [bug] Don't copy nonzero RCODEs from request to response.
+ [RT #1765]
+
+1004. [port] Deal with recvfrom() returning EHOSTDOWN. [RT #1770]
+
+1003. [func] Add the +retry option to dig.
+
+1002. [bug] When reporting an unknown class name in named.conf,
+ including the file name and line number. [RT #1759]
+
+1001. [bug] win32 socket code doio_recv was not catching a
+ WSACONNRESET error when a client was timing out
+ the request and closing its socket. [RT #1745]
+
+1000. [bug] BIND 8 compatibility: accept "HESIOD" as an alias
+ for class "HS". [RT #1759]
+
+ 999. [func] "rndc retransfer zone [class [view]]" added.
+ [RT #1752]
+
+ 998. [func] named-checkzone now has arguments to specify the
+ chroot directory (-t) and working directory (-w).
+ [RT #1755]
+
+ 997. [func] Add support for RSA-SHA1 keys (RFC3110).
+
+ 996. [func] Issue warning if the configuration filename contains
+ the chroot path.
+
+ 995. [bug] dig, host, nslookup: using a raw IPv6 address as a
+ target address should be fatal on a IPv4 only system.
+
+ 994. [func] Treat non-authoritative responses to queries for type
+ NS as referrals even if the NS records are in the
+ answer section, because BIND 8 servers incorrectly
+ send them that way. This is necessary for DNSSEC
+ validation of the NS records of a secure zone to
+ succeed when the parent is a BIND 8 server. [RT #1706]
+
+ 993. [func] dig: -v now reports the version.
+
+ 992. [doc] dig: ~/.digrc is now documented.
+
+ 991. [func] Lower UDP refresh timeout messages to level
+ debug 1.
+
+ 990. [bug] The rndc-confgen man page was not installed.
+
+ 989. [bug] Report filename if $INCLUDE fails for file related
+ errors. [RT #1736]
+
+ 988. [bug] 'additional-from-auth no;' did not work reliably
+ in the case of queries answered from the cache.
+ [RT #1436]
+
+ 987. [bug] "dig -help" didn't show "+[no]stats".
+
+ 986. [bug] "dig +noall" failed to clear stats and command
+ printing.
+
+ 985. [func] Consider network interfaces to be up iff they have
+ a nonzero IP address rather than based on the
+ IFF_UP flag. [RT #1160]
+
+ 984. [bug] Multi-threading should be enabled by default on
+ Solaris 2.7 and newer, but it wasn't.
+
+ 983. [func] The server now supports generating IXFR difference
+ sequences for non-dynamic zones by comparing zone
+ versions, when enabled using the new config
+ option "ixfr-from-differences". [RT #1727]
+
+ 982. [func] If "memstatistics-file" is set in options the memory
+ statistics will be written to it.
+
+ 981. [func] The dnssec tools can now take multiple '-r randomfile'
+ arguments.
+
+ 980. [bug] Incoming zone transfers restarting after an error
+ could trigger an assertion failure. [RT #1692]
+
+ 979. [func] Incremental master file dumping. dns_master_dumpinc(),
+ dns_master_dumptostreaminc(), dns_dumpctx_attach(),
+ dns_dumpctx_detach(), dns_dumpctx_cancel(),
+ dns_dumpctx_db() and dns_dumpctx_version().
+
+ 978. [bug] dns_db_attachversion() had an invalid REQUIRE()
+ condition.
+
+ 977. [bug] Improve "not at top of zone" error message.
+
+ 976. [func] named-checkconf can now test load master zones
+ (named-checkconf -z). [RT #1468]
+
+ 975. [bug] "max-cache-size default;" as a view option
+ caused an assertion failure.
+
+ 974. [bug] "max-cache-size unlimited;" as a global option
+ was not accepted.
+
+ 973. [bug] Failed to log the question name when logging:
+ "bad zone transfer request: non-authoritative zone
+ (NOTAUTH)".
+
+ 972. [bug] The file modification time code in zone.c was using the
+ wrong epoch. [RT #1667]
+
+ 971. [placeholder]
+
+ 970. [func] 'max-journal-size' can now be used to set a target
+ size for a journal.
+
+ 969. [func] dig now supports the undocumented dig 8 feature
+ of allowing arbitrary labels, not just dotted
+ decimal quads, with the -x option. This can be
+ used to conveniently look up RFC2317 names as in
+ "dig -x 10.0.0.0-127". [RT #827, #1576, #1598]
+
+ 968. [bug] On win32, the isc_time_now() function was unnecessarily
+ calling strtime(). [RT #1671]
+
+ 967. [bug] On win32, the link for bindevt was not including the
+ required resource file to enable the event viewer
+ to interpret the error messages in the event log,
+ [RT #1668]
+
+ 966. [placeholder]
+
+ 965. [bug] Including data other than root server NS and A
+ records in the root hint file could cause a rbtdb
+ node reference leak. [RT #1581, #1618]
+
+ 964. [func] Warn if data other than root server NS and A records
+ are found in the root hint file. [RT #1581, #1618]
+
+ 963. [bug] Bad ISC_LANG_ENDDECLS. [RT #1645]
+
+ 962. [bug] libbind: bad "#undef", don't attempt to install
+ non-existent nlist.h. [RT #1640]
+
+ 961. [bug] Tried to use a IPV6 feature when ISC_PLATFORM_HAVEIPV6
+ was not defined. [RT #1482]
+
+ 960. [port] liblwres failed to build on systems with support for
+ getrrsetbyname() in the OS. [RT #1592]
+
+ 959. [port] On FreeBSD, determine the number of CPUs by calling
+ sysctlbyname(). [RT #1584]
+
+ 958. [port] ssize_t is not available on all platforms. [RT #1607]
+
+ 957. [bug] sys/select.h inclusion was broken on older platforms.
+ [RT #1607]
+
+ 956. [bug] ns_g_autorndcfile changed to ns_g_keyfile
+ in named/win32/os.c due to code changes in
+ change #953. win32 .make file for rndc-confgen
+ updated to add include path for os.h header.
+
+ --- 9.2.0rc1 released ---
+
+ 955. [bug] When using views, the zone's class was not being
+ inherited from the view's class. [RT #1583]
+
+ 954. [bug] When requesting AXFRs or IXFRs using dig, host, or
+ nslookup, the RD bit should not be set as zone
+ transfers are inherently non-recursive. [RT #1575]
+
+ 953. [func] The /var/run/named.key file from change #843
+ has been replaced by /etc/rndc.key. Both
+ named and rndc will look for this file and use
+ it to configure a default control channel key
+ if not already configured using a different
+ method (rndc.conf / controls). Unlike
+ named.key, rndc.key is not created automatically;
+ it must be created by manually running
+ "rndc-confgen -a".
+
+ 952. [bug] The server required manual intervention to serve the
+ affected zones if it died between creating a journal
+ and committing the first change to it.
+
+ 951. [bug] CFLAGS was not passed to the linker when
+ linking some of the test programs under
+ bin/tests. [RT #1555].
+
+ 950. [bug] Explicit TTLs did not properly override $TTL
+ due to a bug in change 834. [RT #1558]
+
+ 949. [bug] host was unable to print records larger than 512
+ bytes. [RT #1557]
+
+ --- 9.2.0b2 released ---
+
+ 948. [port] Integrated support for building on Windows NT /
+ Windows 2000.
+
+ 947. [bug] dns_rdata_soa_t had a badly named element "mname" which
+ was really the RNAME field from RFC1035. To avoid
+ confusion and silent errors that would occur it the
+ "origin" and "mname" elements were given their correct
+ names "mname" and "rname" respectively, the "mname"
+ element is renamed to "contact".
+
+ 946. [cleanup] doc/misc/options is now machine-generated from the
+ configuration parser syntax tables, and therefore
+ more likely to be correct.
+
+ 945. [func] Add the new view-specific options
+ "match-destinations" and "match-recursive-only".
+
+ 944. [func] Check for expired signatures on load.
+
+ 943. [bug] The server could crash when receiving a command
+ via rndc if the configuration file listed only
+ nonexistent keys in the controls statement. [RT #1530]
+
+ 942. [port] libbind: GETNETBYADDR_ADDR_T was not correctly
+ defined on some platforms.
+
+ 941. [bug] The configuration checker crashed if a slave
+ zone didn't contain a masters statement. [RT #1514]
+
+ 940. [bug] Double zone locking failure on error path. [RT #1510]
+
+ --- 9.2.0b1 released ---
+
+ 939. [port] Add the --disable-linux-caps option to configure for
+ systems that manage capabilities outside of named.
+ [RT #1503]
+
+ 938. [placeholder]
+
+ 937. [bug] A race when shutting down a zone could trigger a
+ INSIST() failure. [RT #1034]
+
+ 936. [func] Warn about IPv4 addresses that are not complete
+ dotted quads. [RT #1084]
+
+ 935. [bug] inet_pton failed to reject leading zeros.
+
+ 934. [port] Deal with systems where accept() spuriously returns
+ ECONNRESET.
+
+ 933. [bug] configure failed doing libbind on platforms not
+ supported by BIND 8. [RT #1496]
+
+ --- 9.2.0a3 released ---
+
+ 932. [bug] Use INSTALL_SCRIPT, not INSTALL_PROGRAM,
+ when installing isc-config.sh.
+ [RT #198, #1466]
+
+ 931. [bug] The controls statement only attempted to verify
+ messages using the first key in the key list.
+ (9.2.0a1/a2 only).
+
+ 930. [func] Query performance testing tool added as
+ contrib/queryperf.
+
+ 929. [placeholder]
+
+ 928. [bug] nsupdate would send empty update packets if the
+ send (or empty line) command was run after
+ another send but before any new updates or
+ prerequisites were specified. It should simply
+ ignore this command.
+
+ 927. [bug] Don't hold the zone lock for the entire dump to disk.
+ [RT #1423]
+
+ 926. [bug] The resolver could deadlock with the ADB when
+ shutting down (multi-threaded builds only).
+ [RT #1324]
+
+ 925. [cleanup] Remove openssl from the distribution; require that
+ --with-openssl be specified if DNSSEC is needed.
+
+ 924. [port] Extend support for pre-RFC2133 IPv6 implementation.
+ [RT #987]
+
+ 923. [bug] Multiline TSIG secrets (and other multiline strings)
+ were not accepted in named.conf. [RT #1469]
+
+ 922. [func] Added two new lwres_getrrsetbyname() result codes,
+ ERR_NONAME and ERR_NODATA.
+
+ 921. [bug] lwres returned an incorrect error code if it received
+ a truncated message.
+
+ 920. [func] Increase the lwres receive buffer size to 16K.
+ [RT #1451]
+
+ 919. [placeholder]
+
+ 918. [func] In nsupdate, TSIG errors are no longer treated as
+ fatal errors.
+
+ 917. [func] New nsupdate command 'key', allowing TSIG keys to
+ be specified in the nsupdate command stream rather
+ than the command line.
+
+ 916. [bug] Specifying type ixfr to dig without specifying
+ a serial number failed in unexpected ways.
+
+ 915. [func] The named-checkconf and named-checkzone programs
+ now have a '-v' option for printing their version.
+ [RT #1151]
+
+ 914. [bug] Global 'server' statements were rejected when
+ using views, even though they were accepted
+ in 9.1. [RT #1368]
+
+ 913. [bug] Cache cleaning was not sufficiently aggressive.
+ [RT #1441, #1444]
+
+ 912. [bug] Attempts to set the 'additional-from-cache' or
+ 'additional-from-auth' option to 'no' in a
+ server with recursion enabled will now
+ be ignored and cause a warning message.
+ [RT #1145]
+
+ 911. [placeholder]
+
+ 910. [port] Some pre-RFC2133 IPv6 implementations do not define
+ IN6ADDR_ANY_INIT. [RT #1416]
+
+ 909. [placeholder]
+
+ 908. [func] New program, rndc-confgen, to simplify setting up rndc.
+
+ 907. [func] The ability to get entropy from either the
+ random device, a user-provided file or from
+ the keyboard was migrated from the DNSSEC tools
+ to libisc as isc_entropy_usebestsource().
+
+ 906. [port] Separated the system independent portion of
+ lib/isc/unix/entropy.c into lib/isc/entropy.c
+ and added lib/isc/win32/entropy.c.
+
+ 905. [bug] Configuring a forward "zone" for the root domain
+ did not work. [RT #1418]
+
+ 904. [bug] The server would leak memory if attempting to use
+ an expired TSIG key. [RT #1406]
+
+ 903. [bug] dig should not crash when receiving a TCP packet
+ of length 0.
+
+ 902. [bug] The -d option was ignored if both -t and -g were also
+ specified.
+
+ 901. [placeholder]
+
+ 900. [bug] A config.guess update changed the system identification
+ string of FreeBSD systems; configure and
+ bin/tests/system/ifconfig.sh now recognize the new
+ string.
+
+ --- 9.2.0a2 released ---
+
+ 899. [bug] lib/dns/soa.c failed to compile on many platforms
+ due to inappropriate use of a void value.
+ [RT #1372, #1373, #1386, #1387, #1395]
+
+ 898. [bug] "dig" failed to set a nonzero exit status
+ on UDP query timeout. [RT #1323]
+
+ 897. [bug] A config.guess update changed the system identification
+ string of UnixWare systems; configure now recognizes
+ the new string.
+
+ 896. [bug] If a configuration file is set on named's command line
+ and it has a relative pathname, the current directory
+ (after any possible jailing resulting from named -t)
+ will be prepended to it so that reloading works
+ properly even when a directory option is present.
+
+ 895. [func] New function, isc_dir_current(), akin to POSIX's
+ getcwd().
+
+ 894. [bug] When using the DNSSEC tools, a message intended to warn
+ when the keyboard was being used because of the lack
+ of a suitable random device was not being printed.
+
+ 893. [func] Removed isc_file_test() and added isc_file_exists()
+ for the basic functionality that was being added
+ with isc_file_test().
+
+ 892. [placeholder]
+
+ 891. [bug] Return an error when a SIG(0) signed response to
+ an unsigned query is seen. This should actually
+ do the verification, but it's not currently
+ possible. [RT #1391]
+
+ 890. [cleanup] The man pages no longer require the mandoc macros
+ and should now format cleanly using most versions of
+ nroff, and HTML versions of the man pages have been
+ added. Both are generated from DocBook source.
+
+ 889. [port] Eliminated blank lines before .TH in nroff man
+ pages since they cause problems with some versions
+ of nroff. [RT #1390]
+
+ 888. [bug] Don't die when using TKEY to delete a nonexistent
+ TSIG key. [RT #1392]
+
+ 887. [port] Detect broken compilers that can't call static
+ functions from inline functions. [RT #1212]
+
+ 886. [placeholder]
+
+ 885. [placeholder]
+
+ 884. [placeholder]
+
+ 883. [placeholder]
+
+ 882. [placeholder]
+
+ 881. [placeholder]
+
+ 880. [placeholder]
+
+ 879. [placeholder]
+
+ 878. [placeholder]
+
+ 877. [placeholder]
+
+ 876. [placeholder]
+
+ 875. [placeholder]
+
+ 874. [placeholder]
+
+ 873. [placeholder]
+
+ 872. [placeholder]
+
+ 871. [placeholder]
+
+ 870. [placeholder]
+
+ 869. [placeholder]
+
+ 868. [placeholder]
+
+ 867. [placeholder]
+
+ 866. [func] Close debug only file channels when debug is set to
+ zero. [RT #1246]
+
+ 865. [bug] The new configuration parser did not allow
+ the optional debug level in a "severity debug"
+ clause of a logging channel to be omitted.
+ This is now allowed and treated as "severity
+ debug 1;" like it does in BIND 8.2.4, not as
+ "severity debug 0;" like it did in BIND 9.1.
+ [RT #1367]
+
+ 864. [cleanup] Multi-threading is now enabled by default on
+ OSF1, Solaris 2.7 and newer, AIX, IRIX, and HP-UX.
+
+ 863. [bug] If an error occurred while an outgoing zone transfer
+ was starting up, the server could access a domain
+ name that had already been freed when logging a
+ message saying that the transfer was starting.
+ [RT #1383]
+
+ 862. [bug] Use after realloc(), non portable pointer arithmetic in
+ grmerge().
+
+ 861. [port] Add support for Mac OS X, by making it equivalent
+ to Darwin. This was derived from the config.guess
+ file shipped with Mac OS X. [RT #1355]
+
+ 860. [func] Drop cross class glue in zone transfers.
+
+ 859. [bug] Cache cleaning now won't swamp the CPU if there
+ is a persistent over limit condition.
+
+ 858. [func] isc_mem_setwater() no longer requires that when the
+ callback function is non-NULL then its hi_water
+ argument must be greater than its lo_water argument
+ (they can now be equal) or that they be non-zero.
+
+ 857. [cleanup] Use ISC_MAGIC() to define all magic numbers for
+ structs, for our friends in EBCDIC-land.
+
+ 856. [func] Allow partial rdatasets to be returned in answer and
+ authority sections to help non-TCP capable clients
+ recover from truncation. [RT #1301]
+
+ 855. [bug] Stop spurious "using RFC 1035 TTL semantics" warnings.
+
+ 854. [bug] The config parser didn't properly handle config
+ options that were specified in units of time other
+ than seconds. [RT #1372]
+
+ 853. [bug] configure_view_acl() failed to detach existing acls.
+ [RT #1374]
+
+ 852. [bug] Handle responses from servers which do not know
+ about IXFR.
+
+ 851. [cleanup] The obsolete support-ixfr option was not properly
+ ignored.
+
+ --- 9.2.0a1 released ---
+
+ 850. [bug] dns_rbt_findnode() would not find nodes that were
+ split on a bitstring label somewhere other than in
+ the last label of the node. [RT #1351]
+
+ 849. [func] <isc/net.h> will ensure INADDR_LOOPBACK is defined.
+
+ 848. [func] A minimum max-cache-size of two megabytes is enforced
+ by the cache cleaner.
+
+ 847. [func] Added isc_file_test(), which currently only has
+ some very basic functionality to test for the
+ existence of a file, whether a pathname is absolute,
+ or whether a pathname is the fundamental representation
+ of the current directory. It is intended that this
+ function can be expanded to test other things a
+ programmer might want to know about a file.
+
+ 846. [func] A non-zero 'param' to dst_key_generate() when making an
+ hmac-md5 key means that good entropy is not required.
+
+ 845. [bug] The access rights on the public file of a symmetric
+ key are now restricted as soon as the file is opened,
+ rather than after it has been written and closed.
+
+ 844. [func] <isc/net.h> will ensure INADDR_LOOPBACK is defined,
+ just as <lwres/net.h> does.
+
+ 843. [func] If no controls statement is present in named.conf,
+ or if any inet phrase of a controls statement is
+ lacking a keys clause, then a key will be automatically
+ generated by named and an rndc.conf-style file
+ named named.key will be written that uses it. rndc
+ will use this file only if its normal configuration
+ file, or one provided on the command line, does not
+ exist.
+
+ 842. [func] 'rndc flush' now takes an optional view.
+
+ 841. [bug] When sdb modules were not declared threadsafe, their
+ create and destroy functions were not serialized.
+
+ 840. [bug] The config file parser could print the wrong file
+ name if an error was detected after an included file
+ was parsed. [RT #1353]
+
+ 839. [func] Dump packets for which there was no view or that the
+ class could not be determined to category "unmatched".
+
+ 838. [port] UnixWare 7.x.x is now suported by
+ bin/tests/system/ifconfig.sh.
+
+ 837. [cleanup] Multi-threading is now enabled by default only on
+ OSF1, Solaris 2.7 and newer, and AIX.
+
+ 836. [func] Upgraded libtool to 1.4.
+
+ 835. [bug] The dispatcher could enter a busy loop if
+ it got an I/O error receiving on a UDP socket.
+ [RT #1293]
+
+ 834. [func] Accept (but warn about) master files beginning with
+ an SOA record without an explicit TTL field and
+ lacking a $TTL directive, by using the SOA MINTTL
+ as a default TTL. This is for backwards compatibility
+ with old versions of BIND 8, which accepted such
+ files without warning although they are illegal
+ according to RFC1035.
+
+ 833. [cleanup] Moved dns_soa_*() from <dns/journal.h> to
+ <dns/soa.h>, and extended them to support
+ all the integer-valued fields of the SOA RR.
+
+ 832. [bug] The default location for named.conf in named-checkconf
+ should depend on --sysconfdir like it does in named.
+ [RT #1258]
+
+ 831. [placeholder]
+
+ 830. [func] Implement 'rndc status'.
+
+ 829. [bug] The DNS_R_ZONECUT result code should only be returned
+ when an ANY query is made with DNS_DBFIND_GLUEOK set.
+ In all other ANY query cases, returning the delegation
+ is better.
+
+ 828. [bug] The errno value from recvfrom() could be overwritten
+ by logging code. [RT #1293]
+
+ 827. [bug] When an IXFR protocol error occurs, the slave
+ should retry with AXFR.
+
+ 826. [bug] Some IXFR protocol errors were not detected.
+
+ 825. [bug] zone.c:ns_query() detached from the wrong zone
+ reference. [RT #1264]
+
+ 824. [bug] Correct line numbers reported by dns_master_load().
+ [RT #1263]
+
+ 823. [func] The output of "dig -h" now goes to stdout so that it
+ can easily be piped through "more". [RT #1254]
+
+ 822. [bug] Sending nxrrset prerequisites would crash nsupdate.
+ [RT #1248]
+
+ 821. [bug] The program name used when logging to syslog should
+ be stripped of leading path components.
+ [RT #1178, #1232]
+
+ 820. [bug] Name server address lookups failed to follow
+ A6 chains into the glue of local authoritative
+ zones.
+
+ 819. [bug] In certain cases, the resolver's attempts to
+ restart an address lookup at the root could cause
+ the fetch to deadlock (with itself) instead of
+ restarting. [RT #1225]
+
+ 818. [bug] Certain pathological responses to ANY queries could
+ cause an assertion failure. [RT #1218]
+
+ 817. [func] Adjust timeouts for dialup zone queries.
+
+ 816. [bug] Report potential problems with log file accessibility
+ at configuration time, since such problems can't
+ reliably be reported at the time they actually occur.
+
+ 815. [bug] If a log file was specified with a path separator
+ character (i.e. "/") in its name and the directory
+ did not exist, the log file's name was treated as
+ though it were the directory name. [RT #1189]
+
+ 814. [bug] Socket objects left over from accept() failures
+ were incorrectly destroyed, causing corruption
+ of socket manager data structures.
+
+ 813. [bug] File descriptors exceeding FD_SETSIZE were handled
+ badly. [RT #1192]
+
+ 812. [bug] dig sometimes printed incomplete IXFR responses
+ due to an uninitialized variable. [RT #1188]
+
+ 811. [bug] Parentheses were not quoted in zone dumps. [RT #1194]
+
+ 810. [bug] The signer name in SIG records was not properly
+ down-cased when signing/verifying records. [RT #1186]
+
+ 809. [bug] Configuring a non-local address as a transfer-source
+ could cause an assertion failure during load.
+
+ 808. [func] Add 'rndc flush' to flush the server's cache.
+
+ 807. [bug] When setting up TCP connections for incoming zone
+ transfers, the transfer-source port was not
+ ignored like it should be.
+
+ 806. [bug] DNS_R_SEENINCLUDE was failing to propagate back up
+ the calling stack to the zone maintenance level,
+ causing zones to not reload when an included file was
+ touched but the top-level zone file was not.
+
+ 805. [bug] When using "forward only", missing root hints should
+ not cause queries to fail. [RT #1143]
+
+ 804. [bug] Attempting to obtain entropy could fail in some
+ situations. This would be most common on systems
+ with user-space threads. [RT #1131]
+
+ 803. [bug] Treat all SIG queries as if they have the CD bit set,
+ otherwise no data will be returned [RT #749]
+
+ 802. [bug] DNSSEC key tags were computed incorrectly in almost
+ all cases. [RT #1146]
+
+ 801. [bug] nsupdate should treat lines beginning with ';' as
+ comments. [RT #1139]
+
+ 800. [bug] dnssec-signzone produced incorrect statistics for
+ large zones. [RT #1133]
+
+ 799. [bug] The ADB didn't find AAAA glue in a zone unless A6
+ glue was also present.
+
+ 798. [bug] nsupdate should be able to reject bad input lines
+ and continue. [RT #1130]
+
+ 797. [func] Issue a warning if the 'directory' option contains
+ a relative path. [RT #269]
+
+ 796. [func] When a size limit is associated with a log file,
+ only roll it when the size is reached, not every
+ time the log file is opened. [RT #1096]
+
+ 795. [func] Add the +multiline option to dig. [RT #1095]
+
+ 794. [func] Implement the "port" and "default-port" statements
+ in rndc.conf.
+
+ 793. [cleanup] The DNSSEC tools could create filenames that were
+ illegal or contained shell meta-characters. They
+ now use a different text encoding of names that
+ doesn't have these problems. [RT #1101]
+
+ 792. [cleanup] Replace the OMAPI command channel protocol with a
+ simpler one.
+
+ 791. [bug] The command channel now works over IPv6.
+
+ 790. [bug] Wildcards created using dynamic update or IXFR
+ could fail to match. [RT #1111]
+
+ 789. [bug] The "localhost" and "localnets" ACLs did not match
+ when used as the second element of a two-element
+ sortlist item.
+
+ 788. [func] Add the "match-mapped-addresses" option, which
+ causes IPv6 v4mapped addresses to be treated as
+ IPv4 addresses for the purpose of acl matching.
+
+ 787. [bug] The DNSSEC tools failed to downcase domain
+ names when mapping them into file names.
+
+ 786. [bug] When DNSSEC signing/verifying data, owner names were
+ not properly down-cased.
+
+ 785. [bug] A race condition in the resolver could cause
+ an assertion failure. [RT #673, #872, #1048]
+
+ 784. [bug] nsupdate and other programs would not quit properly
+ if some signals were blocked by the caller. [RT #1081]
+
+ 783. [bug] Following CNAMEs could cause an assertion failure
+ when either using an sdb database or under very
+ rare conditions.
+
+ 782. [func] Implement the "serial-query-rate" option.
+
+ 781. [func] Avoid error packet loops by dropping duplicate FORMERR
+ responses. [RT #1006]
+
+ 780. [bug] Error handling code dealing with out of memory or
+ other rare errors could lead to assertion failures
+ by calling functions on uninitialized names. [RT #1065]
+
+ 779. [func] Added the "minimal-responses" option.
+
+ 778. [bug] When starting cache cleaning, cleaning_timer_action()
+ returned without first pausing the iterator, which
+ could cause deadlock. [RT #998]
+
+ 777. [bug] An empty forwarders list in a zone failed to override
+ global forwarders. [RT #995]
+
+ 776. [func] Improved error reporting in denied messages. [RT #252]
+
+ 775. [placeholder]
+
+ 774. [func] max-cache-size is implemented.
+
+ 773. [func] Added isc_rwlock_trylock() to attempt to lock without
+ blocking.
+
+ 772. [bug] Owner names could be incorrectly omitted from cache
+ dumps in the presence of negative caching entries.
+ [RT #991]
+
+ 771. [cleanup] TSIG errors related to unsynchronized clocks
+ are logged better. [RT #919]
+
+ 770. [func] Add the "edns yes_or_no" statement to the server
+ clause. [RT #524]
+
+ 769. [func] Improved error reporting when parsing rdata. [RT #740]
+
+ 768. [bug] The server did not emit an SOA when a CNAME
+ or DNAME chain ended in NXDOMAIN in an
+ authoritative zone.
+
+ 767. [placeholder]
+
+ 766. [bug] A few cases in query_find() could leak fname.
+ This would trigger the mpctx->allocated == 0
+ assertion when the server exited.
+ [RT #739, #776, #798, #812, #818, #821, #845,
+ #892, #935, #966]
+
+ 765. [func] ACL names are once again case insensitive, like
+ in BIND 8. [RT #252]
+
+ 764. [func] Configuration files now allow "include" directives
+ in more places, such as inside the "view" statement.
+ [RT #377, #728, #860]
+
+ 763. [func] Configuration files no longer have reserved words.
+ [RT #731, #753]
+
+ 762. [cleanup] The named.conf and rndc.conf file parsers have
+ been completely rewritten.
+
+ 761. [bug] _REENTRANT was still defined when building with
+ --disable-threads.
+
+ 760. [contrib] Significant enhancements to the pgsql sdb driver.
+
+ 759. [bug] The resolver didn't turn off "avoid fetches" mode
+ when restarting, possibly causing resolution
+ to fail when it should not. This bug only affected
+ platforms which support both IPv4 and IPv6. [RT #927]
+
+ 758. [bug] The "avoid fetches" code did not treat negative
+ cache entries correctly, causing fetches that would
+ be useful to be avoided. This bug only affected
+ platforms which support both IPv4 and IPv6. [RT #927]
+
+ 757. [func] Log zone transfers.
+
+ 756. [bug] dns_zone_load() could "return" success when no master
+ file was configured.
+
+ 755. [bug] Fix incorrectly formatted log messages in zone.c.
+
+ 754. [bug] Certain failure conditions sending UDP packets
+ could cause the server to retry the transmission
+ indefinitely. [RT #902]
+
+ 753. [bug] dig, host, and nslookup would fail to contact a
+ remote server if getaddrinfo() returned an IPv6
+ address on a system that doesn't support IPv6.
+ [RT #917]
+
+ 752. [func] Correct bad tv_usec elements returned by
+ gettimeofday().
+
+ 751. [func] Log successful zone loads / transfers. [RT #898]
+
+ 750. [bug] A query should not match a DNAME whose trust level
+ is pending. [RT #916]
+
+ 749. [bug] When a query matched a DNAME in a secure zone, the
+ server did not return the signature of the DNAME.
+ [RT #915]
+
+ 748. [doc] List supported RFCs in doc/misc/rfc-compliance.
+ [RT #781]
+
+ 747. [bug] The code to determine whether an IXFR was possible
+ did not properly check for a database that could
+ not have a journal. [RT #865, #908]
+
+ 746. [bug] The sdb didn't clone rdatasets properly, causing
+ a crash when the server followed delegations. [RT #905]
+
+ 745. [func] Report the owner name of records that fail
+ semantic checks while loading.
+
+ 744. [bug] When returning DNS_R_CNAME or DNS_R_DNAME as the
+ result of an ANY or SIG query, the resolver failed
+ to setup the return event's rdatasets, causing an
+ assertion failure in the query code. [RT #881]
+
+ 743. [bug] Receiving a large number of certain malformed
+ answers could cause named to stop responding.
+ [RT #861]
+
+ 742. [placeholder]
+
+ 741. [port] Support openssl-engine. [RT #709]
+
+ 740. [port] Handle openssl library mismatches slightly better.
+
+ 739. [port] Look for /dev/random in configure, rather than
+ assuming it will be there for only a predefined
+ set of OSes.
+
+ 738. [bug] If a non-threadsafe sdb driver supported AXFR and
+ received an AXFR request, it would deadlock or die
+ with an assertion failure. [RT #852]
+
+ 737. [port] stdtime.c failed to compile on certain platforms.
+
+ 736. [func] New functions isc_task_{begin,end}exclusive().
+
+ 735. [doc] Add BIND 4 migration notes.
+
+ 734. [bug] An attempt to re-lock the zone lock could occur if
+ the server was shutdown during a zone transfer.
+ [RT #830]
+
+ 733. [bug] Reference counts of dns_acl_t objects need to be
+ locked but were not. [RT #801, #821]
+
+ 732. [bug] Glue with 0 TTL could also cause SERVFAIL. [RT #828]
+
+ 731. [bug] Certain zone errors could cause named-checkzone to
+ fail ungracefully. [RT #819]
+
+ 730. [bug] lwres_getaddrinfo() returns the correct result when
+ it fails to contact a server. [RT #768]
+
+ 729. [port] pthread_setconcurrency() needs to be called on Solaris.
+
+ 728. [bug] Fix comment processing on master file directives.
+ [RT# 757]
+
+ 727. [port] Work around OS bug where accept() succeeds but
+ fails to fill in the peer address of the accepted
+ connection, by treating it as an error rather than
+ an assertion failure. [RT #809]
+
+ 726. [func] Implement the "trace" and "notrace" commands in rndc.
+
+ 725. [bug] Installing man pages could fail.
+
+ 724. [func] New libisc functions isc_netaddr_any(),
+ isc_netaddr_any6().
+
+ 723. [bug] Referrals whose NS RRs had a 0 TTL caused the resolver
+ to return DNS_R_SERVFAIL. [RT #783]
+
+ 722. [func] Allow incremental loads to be canceled.
+
+ 721. [cleanup] Load manager and dns_master_loadfilequota() are no
+ more.
+
+ 720. [bug] Server could enter infinite loop in
+ dispatch.c:do_cancel(). [RT #733]
+
+ 719. [bug] Rapid reloads could trigger an assertion failure.
+ [RT #743, #763]
+
+ 718. [cleanup] "internal" is no longer a reserved word in named.conf.
+ [RT #753, #731]
+
+ 717. [bug] Certain TKEY processing failure modes could
+ reference an uninitialized variable, causing the
+ server to crash. [RT #750]
+
+ 716. [bug] The first line of a $INCLUDE master file was lost if
+ an origin was specified. [RT #744]
+
+ 715. [bug] Resolving some A6 chains could cause an assertion
+ failure in adb.c. [RT #738]
+
+ 714. [bug] Preserve interval timers across reloads unless changed.
+ [RT# 729]
+
+ 713. [func] named-checkconf takes '-t directory' similar to named.
+ [RT #726]
+
+ 712. [bug] Sending a large signed update message caused an
+ assertion failure. [RT #718]
+
+ 711. [bug] The libisc and liblwres implementations of
+ inet_ntop contained an off by one error.
+
+ 710. [func] The forwarders statement now takes an optional
+ port. [RT #418]
+
+ 709. [bug] ANY or SIG queries for data with a TTL of 0
+ would return SERVFAIL. [RT #620]
+
+ 708. [bug] When building with --with-openssl, the openssl headers
+ included with BIND 9 should not be used. [RT #702]
+
+ 707. [func] The "filename" argument to named-checkzone is no
+ longer optional, to reduce confusion. [RT #612]
+
+ 706. [bug] Zones with an explicit "allow-update { none; };"
+ were considered dynamic and therefore not reloaded
+ on SIGHUP or "rndc reload".
+
+ 705. [port] Work out resource limit type for use where rlim_t is
+ not available. [RT #695]
+
+ 704. [port] RLIMIT_NOFILE is not available on all platforms.
+ [RT #695]
+
+ 703. [port] sys/select.h is needed on older platforms. [RT #695]
+
+ 702. [func] If the address 0.0.0.0 is seen in resolv.conf,
+ use 127.0.0.1 instead. [RT #693]
+
+ 701. [func] Root hints are now fully optional. Class IN
+ views use compiled-in hints by default, as
+ before. Non-IN views with no root hints now
+ provide authoritative service but not recursion.
+ A warning is logged if a view has neither root
+ hints nor authoritative data for the root. [RT #696]
+
+ 700. [bug] $GENERATE range check was wrong. [RT #688]
+
+ 699. [bug] The lexer mishandled empty quoted strings. [RT #694]
+
+ 698. [bug] Aborting nsupdate with ^C would lead to several
+ race conditions.
+
+ 697. [bug] nsupdate was not compatible with the undocumented
+ BIND 8 behavior of ignoring TTLs in "update delete"
+ commands. [RT #693]
+
+ 696. [bug] lwresd would die with an assertion failure when passed
+ a zero-length name. [RT #692]
+
+ 695. [bug] If the resolver attempted to query a blackholed or
+ bogus server, the resolution would fail immediately.
+
+ 694. [bug] $GENERATE did not produce the last entry.
+ [RT #682, #683]
+
+ 693. [bug] An empty lwres statement in named.conf caused
+ the server to crash while loading.
+
+ 692. [bug] Deal with systems that have getaddrinfo() but not
+ gai_strerror(). [RT #679]
+
+ 691. [bug] Configuring per-view forwarders caused an assertion
+ failure. [RT #675, #734]
+
+ 690. [func] $GENERATE now supports DNAME. [RT #654]
+
+ 689. [doc] man pages are now installed. [RT #210]
+
+ 688. [func] "make tags" now works on systems with the
+ "Exuberant Ctags" etags.
+
+ 687. [bug] Only say we have IPv6, with sufficient functionality,
+ if it has actually been tested. [RT #586]
+
+ 686. [bug] dig and nslookup can now be properly aborted during
+ blocking operations. [RT #568]
+
+ 685. [bug] nslookup should use the search list/domain options
+ from resolv.conf by default. [RT #405, #630]
+
+ 684. [bug] Memory leak with view forwarders. [RT #656]
+
+ 683. [bug] File descriptor leak in isc_lex_openfile().
+
+ 682. [bug] nslookup displayed SOA records incorrectly. [RT #665]
+
+ 681. [bug] $GENERATE specifying output format was broken. [RT #653]
+
+ 680. [bug] dns_rdata_fromstruct() mishandled options bigger
+ than 255 octets.
+
+ 679. [bug] $INCLUDE could leak memory and file descriptors on
+ reload. [RT #639]
+
+ 678. [bug] "transfer-format one-answer;" could trigger an assertion
+ failure. [RT #646]
+
+ 677. [bug] dnssec-signzone would occasionally use the wrong ttl
+ for database operations and fail. [RT #643]
+
+ 676. [bug] Log messages about lame servers to category
+ 'lame-servers' rather than 'resolver', so as not
+ to be gratuitously incompatible with BIND 8.
+
+ 675. [bug] TKEY queries could cause the server to leak
+ memory.
+
+ 674. [func] Allow messages to be TSIG signed / verified using
+ a offset from the current time.
+
+ 673. [func] The server can now convert RFC1886-style recursive
+ lookup requests into RFC2874-style lookups, when
+ enabled using the new option "allow-v6-synthesis".
+
+ 672. [bug] The wrong time was in the "time signed" field when
+ replying with BADTIME error.
+
+ 671. [bug] The message code was failing to parse a message with
+ no question section and a TSIG record. [RT #628]
+
+ 670. [bug] The lwres replacements for getaddrinfo and
+ getipnodebyname didn't properly check for the
+ existence of the sockaddr sa_len field.
+
+ 669. [bug] dnssec-keygen now makes the public key file
+ non-world-readable for symmetric keys. [RT #403]
+
+ 668. [func] named-checkzone now reports multiple errors in master
+ files.
+
+ 667. [bug] On Linux, running named with the -u option and a
+ non-world-readable configuration file didn't work.
+ [RT #626]
+
+ 666. [bug] If a request sent by dig is longer than 512 bytes,
+ use TCP.
+
+ 665. [bug] Signed responses were not sent when the size of the
+ TSIG + question exceeded the maximum message size.
+ [RT #628]
+
+ 664. [bug] The t_tasks and t_timers module tests are now skipped
+ when building without threads, since they require
+ threads.
+
+ 663. [func] Accept a size_spec, not just an integer, in the
+ (unimplemented and ignored) max-ixfr-log-size option
+ for compatibility with recent versions of BIND 8.
+ [RT #613]
+
+ 662. [bug] dns_rdata_fromtext() failed to log certain errors.
+
+ 661. [bug] Certain UDP IXFR requests caused an assertion failure
+ (mpctx->allocated == 0). [RT #355, #394, #623]
+
+ 660. [port] Detect multiple CPUs on HP-UX and IRIX.
+
+ 659. [performance] Rewrite the name compression code to be much faster.
+
+ 658. [cleanup] Remove all vestiges of 16 bit global compression.
+
+ 657. [bug] When a listen-on statement in an lwres block does not
+ specify a port, use 921, not 53. Also update the
+ listen-on documentation. [RT #616]
+
+ 656. [func] Treat an unescaped newline in a quoted string as
+ an error. This means that TXT records with missing
+ close quotes should have meaningful errors printed.
+
+ 655. [bug] Improve error reporting on unexpected eof when loading
+ zones. [RT #611]
+
+ 654. [bug] Origin was being forgotten in TCP retries in dig.
+ [RT #574]
+
+ 653. [bug] +defname option in dig was reversed in sense.
+ [RT #549]
+
+ 652. [bug] zone_saveunique() did not report the new name.
+
+ 651. [func] The AD bit in responses now has the meaning
+ specified in <draft-ietf-dnsext-ad-is-secure>.
+
+ 650. [bug] SIG(0) records were being generated and verified
+ incorrectly. [RT #606]
+
+ 649. [bug] It was possible to join to an already running fctx
+ after it had "cloned" its events, but before it sent
+ them. In this case, the event of the newly joined
+ fetch would not contain the answer, and would
+ trigger the INSIST() in fctx_sendevents(). In
+ BIND 9.0, this bug did not trigger an INSIST(), but
+ caused the fetch to fail with a SERVFAIL result.
+ [RT #588, #597, #605, #607]
+
+ 648. [port] Add support for pre-RFC2133 IPv6 implementations.
+
+ 647. [bug] Resolver queries sent after following multiple
+ referrals had excessively long retransmission
+ timeouts due to incorrectly counting the referrals
+ as "restarts".
+
+ 646. [bug] The UnixWare ISC_PLATFORM_FIXIN6INADDR fix in isc/net.h
+ didn't _cleanly_ fix the problem it was trying to fix.
+
+ 645. [port] BSD/OS 3.0 needs pthread_init(). [RT #603]
+
+ 644. [bug] #622 needed more work. [RT #562]
+
+ 643. [bug] xfrin error messages made more verbose, added class
+ of the zone. [RT# 599]
+
+ 642. [bug] Break the exit_check() race in the zone module.
+ [RT #598]
+
+ --- 9.1.0b2 released ---
+
+ 641. [bug] $GENERATE caused a uninitialized link to be used.
+ [RT #595]
+
+ 640. [bug] Memory leak in error path could cause
+ "mpctx->allocated == 0" failure. [RT #584]
+
+ 639. [bug] Reading entropy from the keyboard would sometimes fail.
+ [RT #591]
+
+ 638. [port] lib/isc/random.c needed to explicitly include time.h
+ to get a prototype for time() when pthreads was not
+ being used. [RT #592]
+
+ 637. [port] Use isc_u?int64_t instead of (unsigned) long long in
+ lib/isc/print.c. Also allow lib/isc/print.c to
+ be compiled even if the platform does not need it.
+ [RT #592]
+
+ 636. [port] Shut up MSVC++ about a possible loss of precision
+ in the ISC__BUFFER_PUTUINT*() macros. [RT #592]
+
+ 635. [bug] Reloading a server with a configured blackhole list
+ would cause an assertion. [RT #590]
+
+ 634. [bug] A log file will completely stop being written when
+ it reaches the maximum size in all cases, not just
+ when versioning is also enabled. [RT #570]
+
+ 633. [port] Cope with rlim_t missing on BSD/OS systems. [RT #575]
+
+ 632. [bug] The index array of the journal file was
+ corrupted as it was written to disk.
+
+ 631. [port] Build without thread support on systems without
+ pthreads.
+
+ 630. [bug] Locking failure in zone code. [RT #582]
+
+ 629. [bug] 9.1.0b1 dereferenced a null pointer and crashed
+ when responding to a UDP IXFR request.
+
+ 628. [bug] If the root hints contained only AAAA addresses,
+ named would be unable to perform resolution.
+
+ 627. [bug] The EDNS0 blackhole detection code of change 324
+ waited for three retransmissions to each server,
+ which takes much too long when a domain has many
+ name servers and all of them drop EDNS0 queries.
+ Now we retry without EDNS0 after three consecutive
+ timeouts, even if they are all from different
+ servers. [RT #143]
+
+ 626. [bug] The lightweight resolver daemon no longer crashes
+ when asked for a SIG rrset. [RT #558]
+
+ 625. [func] Zones now inherit their class from the enclosing view.
+
+ 624. [bug] The zone object could get timer events after it had
+ been destroyed, causing a server crash. [RT #571]
+
+ 623. [func] Added "named-checkconf" and "named-checkzone" program
+ for syntax checking named.conf files and zone files,
+ respectively.
+
+ 622. [bug] A canceled request could be destroyed before
+ dns_request_destroy() was called. [RT #562]
+
+ 621. [port] Disable IPv6 at runtime if IPv6 sockets are unusable.
+ This mostly affects Red Hat Linux 7.0, which has
+ conflicts between libc and the kernel.
+
+ 620. [bug] dns_master_load*inc() now require 'task' and 'load'
+ to be non-null. Also 'done' will not be called if
+ dns_master_load*inc() fails immediately. [RT #565]
+
+ 619. [placeholder]
+
+ 618. [bug] Queries to a signed zone could sometimes cause
+ an assertion failure.
+
+ 617. [bug] When using dynamic update to add a new RR to an
+ existing RRset with a different TTL, the journal
+ entries generated from the update did not include
+ explicit deletions and re-additions of the existing
+ RRs to update their TTL to the new value.
+
+ 616. [func] dnssec-signzone -t output now includes performance
+ statistics.
+
+ 615. [bug] dnssec-signzone did not like child keysets signed
+ by multiple keys.
+
+ 614. [bug] Checks for uninitialized link fields were prone
+ to false positives, causing assertion failures.
+ The checks are now disabled by default and may
+ be re-enabled by defining ISC_LIST_CHECKINIT.
+
+ 613. [bug] "rndc reload zone" now reloads primary zones.
+ It previously only updated slave and stub zones,
+ if an SOA query indicated an out of date serial.
+
+ 612. [cleanup] Shutup a ridiculously noisy HP-UX compiler that
+ complains relentlessly about how its treatment
+ of 'const' has changed as well as how casting
+ sometimes tightens alignment constraints.
+
+ 611. [func] allow-notify can be used to permit processing of
+ notify messages from hosts other than a slave's
+ masters.
+
+ 610. [func] rndc dumpdb is now supported.
+
+ 609. [bug] getrrsetbyname() would crash lwresd if the server
+ found more SIGs than answers. [RT #554]
+
+ 608. [func] dnssec-signzone now adds a comment to the zone
+ with the time the file was signed.
+
+ 607. [bug] nsupdate would fail if it encountered a CNAME or
+ DNAME in a response to an SOA query. [RT #515]
+
+ 606. [bug] Compiling with --disable-threads failed due
+ to isc_thread_self() being incorrectly defined
+ as an integer rather than a function.
+
+ 605. [func] New function isc_lex_getlasttokentext().
+
+ 604. [bug] The named.conf parser could print incorrect line
+ numbers when long comments were present.
+
+ 603. [bug] Make dig handle multiple types or classes on the same
+ query more correctly.
+
+ 602. [func] Cope automatically with UnixWare's broken
+ IN6_IS_ADDR_* macros. [RT #539]
+
+ 601. [func] Return a non-zero exit code if an update fails
+ in nsupdate.
+
+ 600. [bug] Reverse lookups sometimes failed in dig, etc...
+
+ 599. [func] Added four new functions to the libisc log API to
+ support i18n messages. isc_log_iwrite(),
+ isc_log_ivwrite(), isc_log_iwrite1() and
+ isc_log_ivwrite1() were added.
+
+ 598. [bug] An update-policy statement would cause the server
+ to assert while loading. [RT #536]
+
+ 597. [func] dnssec-signzone is now multi-threaded.
+
+ 596. [bug] DNS_RDATASLAB_FORCE and DNS_RDATASLAB_EXACT are
+ not mutually exclusive.
+
+ 595. [port] On Linux 2.2, socket() returns EINVAL when it
+ should return EAFNOSUPPORT. Work around this.
+ [RT #531]
+
+ 594. [func] sdb drivers are now assumed to not be thread-safe
+ unless the DNS_SDBFLAG_THREADSAFE flag is supplied.
+
+ 593. [bug] If a secure zone was missing all its NXTs and
+ a dynamic update was attempted, the server entered
+ an infinite loop.
+
+ 592. [bug] The sig-validity-interval option now specifies a
+ number of days, not seconds. This matches the
+ documentation. [RT #529]
+
+ --- 9.1.0b1 released ---
+
+ 591. [bug] Work around non-reentrancy in openssl by disabling
+ pre-computation in keys.
+
+ 590. [doc] There are now man pages for the lwres library in
+ doc/man/lwres.
+
+ 589. [bug] The server could deadlock if a zone was updated
+ while being transferred out.
+
+ 588. [bug] ctx->in_use was not being correctly initialized when
+ when pushing a file for $INCLUDE. [RT #523]
+
+ 587. [func] A warning is now printed if the "allow-update"
+ option allows updates based on the source IP
+ address, to alert users to the fact that this
+ is insecure and becoming increasingly so as
+ servers capable of update forwarding are being
+ deployed.
+
+ 586. [bug] multiple views with the same name were fatal. [RT #516]
+
+ 585. [func] dns_db_addrdataset() and and dns_rdataslab_merge()
+ now support 'exact' additions in a similar manner to
+ dns_db_subtractrdataset() and dns_rdataslab_subtract().
+
+ 584. [func] You can now say 'notify explicit'; to suppress
+ notification of the servers listed in NS records
+ and notify only those servers listed in the
+ 'also-notify' option.
+
+ 583. [func] "rndc querylog" will now toggle logging of
+ queries, like "ndc querylog" in BIND 8.
+
+ 582. [bug] dns_zone_idetach() failed to lock the zone.
+ [RT #199, #463]
+
+ 581. [bug] log severity was not being correctly processed.
+ [RT #485]
+
+ 580. [func] Ignore trailing garbage on incoming DNS packets,
+ for interoperability with broken server
+ implementations. [RT #491]
+
+ 579. [bug] nsupdate did not take a filename to read update from.
+ [RT #492]
+
+ 578. [func] New config option "notify-source", to specify the
+ source address for notify messages.
+
+ 577. [func] Log illegal RDATA combinations. e.g. multiple
+ singleton types, cname and other data.
+
+ 576. [doc] isc_log_create() description did not match reality.
+
+ 575. [bug] isc_log_create() was not setting internal state
+ correctly to reflect the default channels created.
+
+ 574. [bug] TSIG signed queries sent by the resolver would fail to
+ have their responses validated and would leak memory.
+
+ 573. [bug] The journal files of IXFRed slave zones were
+ inadvertently discarded on server reload, causing
+ "journal out of sync with zone" errors on subsequent
+ reloads. [RT #482]
+
+ 572. [bug] Quoted strings were not accepted as key names in
+ address match lists.
+
+ 571. [bug] It was possible to create an rdataset of singleton
+ type which had more than one rdata. [RT #154]
+ [RT #279]
+
+ 570. [bug] rbtdb.c allowed zones containing nodes which had
+ both a CNAME and "other data". [RT #154]
+
+ 569. [func] The DNSSEC AD bit will not be set on queries which
+ have not requested a DNSSEC response.
+
+ 568. [func] Add sample simple database drivers in contrib/sdb.
+
+ 567. [bug] Setting the zone transfer timeout to zero caused an
+ assertion failure. [RT #302]
+
+ 566. [func] New public function dns_timer_setidle().
+
+ 565. [func] Log queries more like BIND 8: query logging is now
+ done to category "queries", level "info". [RT #169]
+
+ 564. [func] Add sortlist support to lwresd.
+
+ 563. [func] New public functions dns_rdatatype_format() and
+ dns_rdataclass_format(), for convenient formatting
+ of rdata type/class mnemonics in log messages.
+
+ 562. [cleanup] Moved lib/dns/*conf.c to bin/named where they belong.
+
+ 561. [func] The 'datasize', 'stacksize', 'coresize' and 'files'
+ clauses of the options{} statement are now implemented.
+
+ 560. [bug] dns_name_split did not properly the resulting prefix
+ when a maximal length bitstring label was split which
+ was preceded by another bitstring label. [RT #429]
+
+ 559. [bug] dns_name_split did not properly create the suffix
+ when splitting within a maximal length bitstring label.
+
+ 558. [func] New functions, isc_resource_getlimit and
+ isc_resource_setlimit.
+
+ 557. [func] Symbolic constants for libisc integral types.
+
+ 556. [func] The DNSSEC OK bit in the EDNS extended flags
+ is now implemented. Responses to queries without
+ this bit set will not contain any DNSSEC records.
+
+ 555. [bug] A slave server attempting a zone transfer could
+ crash with an assertion failure on certain
+ malformed responses from the master. [RT #457]
+
+ 554. [bug] In some cases, not all of the dnssec tools were
+ properly installed.
+
+ 553. [bug] Incoming zone transfers deferred due to quota
+ were not started when quota was increased but
+ only when a transfer in progress finished. [RT #456]
+
+ 552. [bug] We were not correctly detecting the end of all c-style
+ comments. [RT #455]
+
+ 551. [func] Implemented the 'sortlist' option.
+
+ 550. [func] Support unknown rdata types and classes.
+
+ 549. [bug] "make" did not immediately abort the build when a
+ subdirectory make failed [RT #450].
+
+ 548. [func] The lexer now ungets tokens more correctly.
+
+ 547. [placeholder]
+
+ 546. [func] Option 'lame-ttl' is now implemented.
+
+ 545. [func] Name limit and counting options removed from dig;
+ they didn't work properly, and cannot be correctly
+ implemented without significant changes.
+
+ 544. [func] Add statistics option, enable statistics-file option,
+ add RNDC option "dump-statistics" to write out a
+ query statistics file.
+
+ 543. [doc] The 'port' option is now documented.
+
+ 542. [func] Add support for update forwarding as required for
+ full compliance with RFC2136. It is turned off
+ by default and can be enabled using the
+ 'allow-update-forwarding' option.
+
+ 541. [func] Add bogus server support.
+
+ 540. [func] Add dialup support.
+
+ 539. [func] Support the blackhole option.
+
+ 538. [bug] fix buffer overruns by 1 in lwres_getnameinfo().
+
+ 537. [placeholder]
+
+ 536. [func] Use transfer-source{-v6} when sending refresh queries.
+ Transfer-source{-v6} now take a optional port
+ parameter for setting the UDP source port. The port
+ parameter is ignored for TCP.
+
+ 535. [func] Use transfer-source{-v6} when forwarding update
+ requests.
+
+ 534. [func] Ancestors have been removed from RBT chains. Ancestor
+ information can be discerned via node parent pointers.
+
+ 533. [func] Incorporated name hashing into the RBT database to
+ improve search speed.
+
+ 532. [func] Implement DNS UPDATE pseudo records using
+ DNS_RDATA_UPDATE flag.
+
+ 531. [func] Rdata really should be initialized before being assigned
+ to (dns_rdata_fromwire(), dns_rdata_fromtext(),
+ dns_rdata_clone(), dns_rdata_fromregion()),
+ check that it is.
+
+ 530. [func] New function dns_rdata_invalidate().
+
+ 529. [bug] 521 contained a bug which caused zones to always
+ reload. [RT #410]
+
+ 528. [func] The ISC_LIST_XXXX macros now perform sanity checks
+ on their arguments. ISC_LIST_XXXXUNSAFE can be use
+ to skip the checks however use with caution.
+
+ 527. [func] New function dns_rdata_clone().
+
+ 526. [bug] nsupdate incorrectly refused to add RRs with a TTL
+ of 0.
+
+ 525. [func] New arguments 'options' for dns_db_subtractrdataset(),
+ and 'flags' for dns_rdataslab_subtract() allowing you
+ to request that the RR's must exist prior to deletion.
+ DNS_R_NOTEXACT is returned if the condition is not met.
+
+ 524. [func] The 'forward' and 'forwarders' statement in
+ non-forward zones should work now.
+
+ 523. [doc] The source to the Administrator Reference Manual is
+ now an XML file using the DocBook DTD, and is included
+ in the distribution. The plain text version of the
+ ARM is temporarily unavailable while we figure out
+ how to generate readable plain text from the XML.
+
+ 522. [func] The lightweight resolver daemon can now use
+ a real configuration file, and its functionality
+ can be provided by a name server. Also, the -p and -P
+ options to lwresd have been reversed.
+
+ 521. [bug] Detect master files which contain $INCLUDE and always
+ reload. [RT #196]
+
+ 520. [bug] Upgraded libtool to 1.3.5, which makes shared
+ library builds almost work on AIX (and possibly
+ others).
+
+ 519. [bug] dns_name_split() would improperly split some bitstring
+ labels, zeroing a few of the least significant bits in
+ the prefix part. When such an improperly created
+ prefix was returned to the RBT database, the bogus
+ label was dutifully stored, corrupting the tree.
+ [RT #369]
+
+ 518. [bug] The resolver did not realize that a DNAME which was
+ "the answer" to the client's query was "the answer",
+ and such queries would fail. [RT #399]
+
+ 517. [bug] The resolver's DNAME code would trigger an assertion
+ if there was more than one DNAME in the chain.
+ [RT #399]
+
+ 516. [bug] Cache lookups which had a NULL node pointer, e.g.
+ those by dns_view_find(), and which would match a
+ DNAME, would trigger an INSIST(!search.need_cleanup)
+ assertion. [RT #399]
+
+ 515. [bug] The ssu table was not being attached / detached
+ by dns_zone_[sg]etssutable. [RT#397]
+
+ 514. [func] Retry refresh and notify queries if they timeout.
+ [RT #388]
+
+ 513. [func] New functionality added to rdnc and server to allow
+ individual zones to be refreshed or reloaded.
+
+ 512. [bug] The zone transfer code could throw an exception with
+ an invalid IXFR stream.
+
+ 511. [bug] The message code could throw an assertion on an
+ out of memory failure. [RT #392]
+
+ 510. [bug] Remove spurious view notify warning. [RT #376]
+
+ 509. [func] Add support for write of zone files on shutdown.
+
+ 508. [func] dns_message_parse() can now do a best-effort
+ attempt, which should allow dig to print more invalid
+ messages.
+
+ 507. [func] New functions dns_zone_flush(), dns_zt_flushanddetach()
+ and dns_view_flushanddetach().
+
+ 506. [func] Do not fail to start on errors in zone files.
+
+ 505. [bug] nsupdate was printing "unknown result code". [RT #373]
+
+ 504. [bug] The zone was not being marked as dirty when updated via
+ IXFR.
+
+ 503. [bug] dumptime was not being set along with
+ DNS_ZONEFLG_NEEDDUMP.
+
+ 502. [func] On a SERVFAIL reply, DiG will now try the next server
+ in the list, unless the +fail option is specified.
+
+ 501. [bug] Incorrect port numbers were being displayed by
+ nslookup. [RT #352]
+
+ 500. [func] Nearly useless +details option removed from DiG.
+
+ 499. [func] In DiG, specifying a class with -c or type with -t
+ changes command-line parsing so that classes and
+ types are only recognized if following -c or -t.
+ This allows hosts with the same name as a class or
+ type to be looked up.
+
+ 498. [doc] There is now a man page for "dig"
+ in doc/man/bin/dig.1.
+
+ 497. [bug] The error messages printed when an IP match list
+ contained a network address with a nonzero host
+ part where not sufficiently detailed. [RT #365]
+
+ 496. [bug] named didn't sanity check numeric parameters. [RT #361]
+
+ 495. [bug] nsupdate was unable to handle large records. [RT #368]
+
+ 494. [func] Do not cache NXDOMAIN responses for SOA queries.
+
+ 493. [func] Return non-cachable (ttl = 0) NXDOMAIN responses
+ for SOA queries. This makes it easier to locate
+ the containing zone without polluting intermediate
+ caches.
+
+ 492. [bug] attempting to reload a zone caused the server fail
+ to shutdown cleanly. [RT #360]
+
+ 491. [bug] nsupdate would segfault when sending certain
+ prerequisites with empty RDATA. [RT #356]
+
+ 490. [func] When a slave/stub zone has not yet successfully
+ obtained an SOA containing the zone's configured
+ retry time, perform the SOA query retries using
+ exponential backoff. [RT #337]
+
+ 489. [func] The zone manager now has a "i/o" queue.
+
+ 488. [bug] Locks weren't properly destroyed in some cases.
+
+ 487. [port] flockfile() is not defined on all systems.
+
+ 486. [bug] nslookup: "set all" and "server" commands showed
+ the incorrect port number if a port other than 53
+ was specified. [RT #352]
+
+ 485. [func] When dig had more than one server to query, it would
+ send all of the messages at the same time. Add
+ rate limiting of the transmitted messages.
+
+ 484. [bug] When the server was reloaded after removing addresses
+ from the named.conf "listen-on" statement, sockets
+ were still listening on the removed addresses due
+ to reference count loops. [RT #325]
+
+ 483. [bug] nslookup: "set all" showed a "search" option but it
+ was not settable.
+
+ 482. [bug] nslookup: a plain "server" or "lserver" should be
+ treated as a lookup.
+
+ 481. [bug] nslookup:get_next_command() stack size could exceed
+ per thread limit.
+
+ 480. [bug] strtok() is not thread safe. [RT #349]
+
+ 479. [func] The test suite can now be run by typing "make check"
+ or "make test" at the top level.
+
+ 478. [bug] "make install" failed if the directory specified with
+ --prefix did not already exist.
+
+ 477. [bug] The the isc-config.sh script could be installed before
+ its directory was created. [RT #324]
+
+ 476. [bug] A zone could expire while a zone transfer was in
+ progress triggering a INSIST failure. [RT #329]
+
+ 475. [bug] query_getzonedb() sometimes returned a non-null version
+ on failure. This caused assertion failures when
+ generating query responses where names subject to
+ additional section processing pointed to a zone
+ to which access had been denied by means of the
+ allow-query option. [RT #336]
+
+ 474. [bug] The mnemonic of the CHAOS class is CH according to
+ RFC1035, but it was printed and read only as CHAOS.
+ We now accept both forms as input, and print it
+ as CH. [RT #305]
+
+ 473. [bug] nsupdate overran the end of the list of name servers
+ when no servers could be reached, typically causing
+ it to print the error message "dns_request_create:
+ not implemented".
+
+ 472. [bug] Off-by-one error caused isc_time_add() to sometimes
+ produce invalid time values.
+
+ 471. [bug] nsupdate didn't compile on HP/UX 10.20
+
+ 470. [func] $GENERATE is now supported. See also
+ doc/misc/migration.
+
+ 469. [bug] "query-source address * port 53;" now works.
+
+ 468. [bug] dns_master_load*() failed to report file and line
+ number in certain error conditions.
+
+ 467. [bug] dns_master_load*() failed to log an error if
+ pushfile() failed.
+
+ 466. [bug] dns_master_load*() could return success when it failed.
+
+ 465. [cleanup] Allow 0 to be set as an omapi_value_t value by
+ omapi_value_storeint().
+
+ 464. [cleanup] Build with openssl's RSA code instead of dnssafe.
+
+ 463. [bug] nsupdate sent malformed SOA queries to the second
+ and subsequent name servers in resolv.conf if the
+ query sent to the first one failed.
+
+ 462. [bug] --disable-ipv6 should work now.
+
+ 461. [bug] Specifying an unknown key in the "keys" clause of the
+ "controls" statement caused a NULL pointer dereference.
+ [RT #316]
+
+ 460. [bug] Much of the DNSSEC code only worked with class IN.
+
+ 459. [bug] Nslookup processed the "set" command incorrectly.
+
+ 458. [bug] Nslookup didn't properly check class and type values.
+ [RT #305]
+
+ 457. [bug] Dig/host/hslookup didn't properly handle connect
+ timeouts in certain situations, causing an
+ unnecessary warning message to be printed.
+
+ 456. [bug] Stub zones were not resetting the refresh and expire
+ counters, loadtime or clearing the DNS_ZONE_REFRESH
+ (refresh in progress) flag upon successful update.
+ This disabled further refreshing of the stub zone,
+ causing it to eventually expire. [RT #300]
+
+ 455. [doc] Document IPv4 prefix notation does not require a
+ dotted decimal quad but may be just dotted decimal.
+
+ 454. [bug] Enforce dotted decimal and dotted decimal quad where
+ documented as such in named.conf. [RT #304, RT #311]
+
+ 453. [bug] Warn if the obsolete option "maintain-ixfr-base"
+ is specified in named.conf. [RT #306]
+
+ 452. [bug] Warn if the unimplemented option "statistics-file"
+ is specified in named.conf. [RT #301]
+
+ 451. [func] Update forwarding implemented.
+
+ 450. [func] New function ns_client_sendraw().
+
+ 449. [bug] isc_bitstring_copy() only works correctly if the
+ two bitstrings have the same lsb0 value, but this
+ requirement was not documented, nor was there a
+ REQUIRE for it.
+
+ 448. [bug] Host output formatting change, to match v8. [RT #255]
+
+ 447. [bug] Dig didn't properly retry in TCP mode after
+ a truncated reply. [RT #277]
+
+ 446. [bug] Confusing notify log message. [RT #298]
+
+ 445. [bug] Doing a 0 bit isc_bitstring_copy() of an lsb0
+ bitstring triggered a REQUIRE statement. The REQUIRE
+ statement was incorrect. [RT #297]
+
+ 444. [func] "recursion denied" messages are always logged at
+ debug level 1, now, rather than sometimes at ERROR.
+ This silences these warnings in the usual case, where
+ some clients set the RD bit in all queries.
+
+ 443. [bug] When loading a master file failed because of an
+ unrecognized RR type name, the error message
+ did not include the file name and line number.
+ [RT #285]
+
+ 442. [bug] TSIG signed messages that did not match any view
+ crashed the server. [RT #290]
+
+ 441. [bug] Nodes obscured by a DNAME were inaccessible even
+ when DNS_DBFIND_GLUEOK was set.
+
+ 440. [func] New function dns_zone_forwardupdate().
+
+ 439. [func] New function dns_request_createraw().
+
+ 438. [func] New function dns_message_getrawmessage().
+
+ 437. [func] Log NOTIFY activity to the notify channel.
+
+ 436. [bug] If recvmsg() returned EHOSTUNREACH or ENETUNREACH,
+ which sometimes happens on Linux, named would enter
+ a busy loop. Also, unexpected socket errors were
+ not logged at a high enough logging level to be
+ useful in diagnosing this situation. [RT #275]
+
+ 435. [bug] dns_zone_dump() overwrote existing zone files
+ rather than writing to a temporary file and
+ renaming. This could lead to empty or partial
+ zone files being left around in certain error
+ conditions involving the initial transfer of a
+ slave zone, interfering with subsequent server
+ startup. [RT #282]
+
+ 434. [func] New function isc_file_isabsolute().
+
+ 433. [func] isc_base64_decodestring() now accepts newlines
+ within the base64 data. This makes it possible
+ to break up the key data in a "trusted-keys"
+ statement into multiple lines. [RT #284]
+
+ 432. [func] Added refresh/retry jitter. The actual refresh/
+ retry time is now a random value between 75% and
+ 100% of the configured value.
+
+ 431. [func] Log at ISC_LOG_INFO when a zone is successfully
+ loaded.
+
+ 430. [bug] Rewrote the lightweight resolver client management
+ code to handle shutdown correctly and general
+ cleanup.
+
+ 429. [bug] The space reserved for a TSIG record in a response
+ was 2 bytes too short, leading to message
+ generation failures.
+
+ 428. [bug] rbtdb.c:find_closest_nxt() erroneously returned
+ DNS_R_BADDB for nodes which had neither NXT nor SIG NXT
+ (e.g. glue). This could cause SERVFAILs when
+ generating negative responses in a secure zone.
+
+ 427. [bug] Avoid going into an infinite loop when the validator
+ gets a negative response to a key query where the
+ records are signed by the missing key.
+
+ 426. [bug] Attempting to generate an oversized RSA key could
+ cause dnssec-keygen to dump core.
+
+ 425. [bug] Warn about the auth-nxdomain default value change
+ if there is no auth-nxdomain statement in the
+ config file. [RT #287]
+
+ 424. [bug] notify_createmessage() could trigger an assertion
+ failure when creating the notify message failed,
+ e.g. due to corrupt zones with multiple SOA records.
+ [RT #279]
+
+ 423. [bug] When responding to a recursive query, errors that occur
+ after following a CNAME should cause the query to fail.
+ [RT #274]
+
+ 422. [func] get rid of isc_random_t, and make isc_random_get()
+ and isc_random_jitter() use rand() internally
+ instead of local state. Note that isc_random_*()
+ functions are only for weak, non-critical "randomness"
+ such as timing jitter and such.
+
+ 421. [bug] nslookup would exit when given a blank line as input.
+
+ 420. [bug] nslookup failed to implement the "exit" command.
+
+ 419. [bug] The certificate type PKIX was misspelled as SKIX.
+
+ 418. [bug] At debug levels >= 10, getting an unexpected
+ socket receive error would crash the server
+ while trying to log the error message.
+
+ 417. [func] Add isc_app_block() and isc_app_unblock(), which
+ allow an application to handle signals while
+ blocking.
+
+ 416. [bug] Slave zones with no master file tried to use a
+ NULL pointer for a journal file name when they
+ received an IXFR. [RT #273]
+
+ 415. [bug] The logging code leaked file descriptors.
+
+ 414. [bug] Server did not shut down until all incoming zone
+ transfers were finished.
+
+ 413. [bug] Notify could attempt to use the zone database after
+ it had been unloaded. [RT#267]
+
+ 412. [bug] named -v didn't print the version.
+
+ 411. [bug] A typo in the HS A code caused an assertion failure.
+
+ 410. [bug] lwres_gethostbyname() and company set lwres_h_errno
+ to a random value on success.
+
+ 409. [bug] If named was shut down early in the startup
+ process, ns_omapi_shutdown() would attempt to lock
+ an uninitialized mutex. [RT #262]
+
+ 408. [bug] stub zones could leak memory and reference counts if
+ all the masters were unreachable.
+
+ 407. [bug] isc_rwlock_lock() would needlessly block
+ readers when it reached the read quota even
+ if no writers were waiting.
+
+ 406. [bug] Log messages were occasionally lost or corrupted
+ due to a race condition in isc_log_doit().
+
+ 405. [func] Add support for selective forwarding (forward zones)
+
+ 404. [bug] The request library didn't completely work with IPv6.
+
+ 403. [bug] "host" did not use the search list.
+
+ 402. [bug] Treat undefined acls as errors, rather than
+ warning and then later throwing an assertion.
+ [RT #252]
+
+ 401. [func] Added simple database API.
+
+ 400. [bug] SIG(0) signing and verifying was done incorrectly.
+ [RT #249]
+
+ 399. [bug] When reloading the server with a config file
+ containing a syntax error, it could catch an
+ assertion failure trying to perform zone
+ maintenance on, or sending notifies from,
+ tentatively created zones whose views were
+ never fully configured and lacked an address
+ database and request manager.
+
+ 398. [bug] "dig" sometimes caught an assertion failure when
+ using TSIG, depending on the key length.
+
+ 397. [func] Added utility functions dns_view_gettsig() and
+ dns_view_getpeertsig().
+
+ 396. [doc] There is now a man page for "nsupdate"
+ in doc/man/bin/nsupdate.8.
+
+ 395. [bug] nslookup printed incorrect RR type mnemonics
+ for RRs of type >= 21 [RT #237].
+
+ 394. [bug] Current name was not propagated via $INCLUDE.
+
+ 393. [func] Initial answer while loading (awl) support.
+ Entry points: dns_master_loadfileinc(),
+ dns_master_loadstreaminc(), dns_master_loadbufferinc().
+ Note: calls to dns_master_load*inc() should be rate
+ be rate limited so as to not use up all file
+ descriptors.
+
+ 392. [func] Add ISC_R_FAMILYNOSUPPORT. Returned when OS does
+ not support the given address family requested.
+
+ 391. [clarity] ISC_R_FAMILY -> ISC_R_FAMILYMISMATCH.
+
+ 390. [func] The function dns_zone_setdbtype() now takes
+ an argc/argv style vector of words and sets
+ both the zone database type and its arguments,
+ making the functions dns_zone_adddbarg()
+ and dns_zone_cleardbargs() unnecessary.
+
+ 389. [bug] Attempting to send a request over IPv6 using
+ dns_request_create() on a system without IPv6
+ support caused an assertion failure [RT #235].
+
+ 388. [func] dig and host can now do reverse ipv6 lookups.
+
+ 387. [func] Add dns_byaddr_createptrname(), which converts
+ an address into the name used by a PTR query.
+
+ 386. [bug] Missing strdup() of ACL name caused random
+ ACL matching failures [RT #228].
+
+ 385. [cleanup] Removed functions dns_zone_equal(), dns_zone_print(),
+ and dns_zt_print().
+
+ 384. [bug] nsupdate was incorrectly limiting TTLs to 65535 instead
+ of 2147483647.
+
+ 383. [func] When writing a master file, print the SOA and NS
+ records (and their SIGs) before other records.
+
+ 382. [bug] named -u failed on many Linux systems where the
+ libc provided kernel headers do not match
+ the current kernel.
+
+ 381. [bug] Check for IPV6_RECVPKTINFO and use it instead of
+ IPV6_PKTINFO if found. [RT #229]
+
+ 380. [bug] nsupdate didn't work with IPv6.
+
+ 379. [func] New library function isc_sockaddr_anyofpf().
+
+ 378. [func] named and lwresd will log the command line arguments
+ they were started with in the "starting ..." message.
+
+ 377. [bug] When additional data lookups were refused due to
+ "allow-query", the databases were still being
+ attached causing reference leaks.
+
+ 376. [bug] The server should always use good entropy when
+ performing cryptographic functions needing entropy.
+
+ 375. [bug] Per-zone "allow-query" did not properly override the
+ view/global one for CNAME targets and additional
+ data [RT #220].
+
+ 374. [bug] SOA in authoritative negative responses had wrong TTL.
+
+ 373. [func] nslookup is now installed by "make install".
+
+ 372. [bug] Deal with Microsoft DNS servers appending two bytes of
+ garbage to zone transfer requests.
+
+ 371. [bug] At high debug levels, doing an outgoing zone transfer
+ of a very large RRset could cause an assertion failure
+ during logging.
+
+ 370. [bug] The error messages for roll-forward failures were
+ overly terse.
+
+ 369. [func] Support new named.conf options, view and zone
+ statements:
+
+ max-retry-time, min-retry-time,
+ max-refresh-time, min-refresh-time.
+
+ 368. [func] Restructure the internal ".bind" view so that more
+ zones can be added to it.
+
+ 367. [bug] Allow proper selection of server on nslookup command
+ line.
+
+ 366. [func] Allow use of '-' batch file in dig for stdin.
+
+ 365. [bug] nsupdate -k leaked memory.
+
+ 364. [func] Added additional-from-{cache,auth}
+
+ 363. [placeholder]
+
+ 362. [bug] rndc no longer aborts if the configuration file is
+ missing an options statement. [RT #209]
+
+ 361. [func] When the RBT find or chain functions set the name and
+ origin for a node that stores the root label
+ the name is now set to an empty name, instead of ".",
+ to simplify later use of the name and origin by
+ dns_name_concatenate(), dns_name_totext() or
+ dns_name_format().
+
+ 360. [func] dns_name_totext() and dns_name_format() now allow
+ an empty name to be passed, which is formatted as "@".
+
+ 359. [bug] dnssec-signzone occasionally signed glue records.
+
+ 358. [cleanup] Rename the intermediate files used by the dnssec
+ programs.
+
+ 357. [bug] The zone file parser crashed if the argument
+ to $INCLUDE was a quoted string.
+
+ 356. [cleanup] isc_task_send no longer requires event->sender to
+ be non-null.
+
+ 355. [func] Added isc_dir_createunique(), similar to mkdtemp().
+
+ 354. [doc] Man pages for the dnssec tools are now included in
+ the distribution, in doc/man/dnssec.
+
+ 353. [bug] double increment in lwres/gethost.c:copytobuf().
+ [RT# 187]
+
+ 352. [bug] Race condition in dns_client_t startup could cause
+ an assertion failure.
+
+ 351. [bug] Constructing a response with rcode SERVFAIL to a TSIG
+ signed query could crash the server.
+
+ 350. [bug] Also-notify lists specified in the global options
+ block were not correctly reference counted, causing
+ a memory leak.
+
+ 349. [bug] Processing a query with the CD bit set now works
+ as expected.
+
+ 348. [func] New boolean named.conf options 'additional-from-auth'
+ and 'additional-from-cache' now supported in view and
+ global options statement.
+
+ 347. [bug] Don't crash if an argument is left off options in dig.
+
+ 346. [placeholder]
+
+ 345. [bug] Large-scale changes/cleanups to dig:
+ * Significantly improve structure handling
+ * Don't pre-load entire batch files
+ * Add name/rr counting/limiting
+ * Fix SIGINT handling
+ * Shorten timeouts to match v8's behavior
+
+ 344. [bug] When shutting down, lwresd sometimes tried
+ to shut down its client tasks twice,
+ triggering an assertion.
+
+ 343. [bug] Although zone maintenance SOA queries and
+ notify requests were signed with TSIG keys
+ when configured for the server in case,
+ the TSIG was not verified on the response.
+
+ 342. [bug] The wrong name was being passed to
+ dns_name_dup() when generating a TSIG
+ key using TKEY.
+
+ 341. [func] Support 'key' clause in named.conf zone masters
+ statement to allow authentication via TSIG keys:
+
+ masters {
+ 10.0.0.1 port 5353 key "foo";
+ 10.0.0.2 ;
+ };
+
+ 340. [bug] The top-level COPYRIGHT file was missing from
+ the distribution.
+
+ 339. [bug] DNSSEC validation of the response to an ANY
+ query at a name with a CNAME RR in a secure
+ zone triggered an assertion failure.
+
+ 338. [bug] lwresd logged to syslog as named, not lwresd.
+
+ 337. [bug] "dig" did not recognize "nsap-ptr" as an RR type
+ on the command line.
+
+ 336. [bug] "dig -f" used 64 k of memory for each line in
+ the file. It now uses much less, though still
+ proportionally to the file size.
+
+ 335. [bug] named would occasionally attempt recursion when
+ it was disallowed or undesired.
+
+ 334. [func] Added hmac-md5 to libisc.
+
+ 333. [bug] The resolver incorrectly accepted referrals to
+ domains that were not parents of the query name,
+ causing assertion failures.
+
+ 332. [func] New function dns_name_reset().
+
+ 331. [bug] Only log "recursion denied" if RD is set. [RT #178]
+
+ 330. [bug] Many debugging messages were partially formatted
+ even when debugging was turned off, causing a
+ significant decrease in query performance.
+
+ 329. [func] omapi_auth_register() now takes a size_t argument for
+ the length of a key's secret data. Previously
+ OMAPI only stored secrets up to the first NUL byte.
+
+ 328. [func] Added isc_base64_decodestring().
+
+ 327. [bug] rndc.conf parser wasn't correctly recognizing an IP
+ address where a host specification was required.
+
+ 326. [func] 'keys' in an 'inet' control statement is now
+ required and must have at least one item in it.
+ A "not supported" warning is now issued if a 'unix'
+ control channel is defined.
+
+ 325. [bug] isc_lex_gettoken was processing octal strings when
+ ISC_LEXOPT_CNUMBER was not set.
+
+ 324. [func] In the resolver, turn EDNS0 off if there is no
+ response after a number of retransmissions.
+ This is to allow queries some chance of succeeding
+ even if all the authoritative servers of a zone
+ silently discard EDNS0 requests instead of
+ sending an error response like they ought to.
+
+ 323. [bug] dns_rbt_findname() did not ignore empty rbt nodes.
+ Because of this, servers authoritative for a parent
+ and grandchild zone but not authoritative for the
+ intervening child zone did not correctly issue
+ referrals to the servers of the child zone.
+
+ 322. [bug] Queries for KEY RRs are now sent to the parent
+ server before the authoritative one, making
+ DNSSEC insecurity proofs work in many cases
+ where they previously didn't.
+
+ 321. [bug] When synthesizing a CNAME RR for a DNAME
+ response, query_addcname() failed to initialize
+ the type and class of the CNAME dns_rdata_t,
+ causing random failures.
+
+ 320. [func] Multiple rndc changes: parses an rndc.conf file,
+ uses authentication to talk to named, command
+ line syntax changed. This will all be described
+ in the ARM.
+
+ 319. [func] The named.conf "controls" statement is now used
+ to configure the OMAPI command channel.
+
+ 318. [func] dns_c_ndcctx_destroy() could never return anything
+ except ISC_R_SUCCESS; made it have void return instead.
+
+ 317. [func] Use callbacks from libomapi to determine if a
+ new connection is valid, and if a key requested
+ to be used with that connection is valid.
+
+ 316. [bug] Generate a warning if we detect an unexpected <eof>
+ but treat as <eol><eof>.
+
+ 315. [bug] Handle non-empty blanks lines. [RT #163]
+
+ 314. [func] The named.conf controls statement can now have
+ more than one key specified for the inet clause.
+
+ 313. [bug] When parsing resolv.conf, don't terminate on an
+ error. Instead, parse as much as possible, but
+ still return an error if one was found.
+
+ 312. [bug] Increase the number of allowed elements in the
+ resolv.conf search path from 6 to 8. If there
+ are more than this, ignore the remainder rather
+ than returning a failure in lwres_conf_parse.
+
+ 311. [bug] lwres_conf_parse failed when the first line of
+ resolv.conf was empty or a comment.
+
+ 310. [func] Changes to named.conf "controls" statement (inet
+ subtype only)
+
+ - support "keys" clause
+
+ controls {
+ inet * port 1024
+ allow { any; } keys { "foo"; }
+ }
+
+ - allow "port xxx" to be left out of statement,
+ in which case it defaults to omapi's default port
+ of 953.
+
+ 309. [bug] When sending a referral, the server did not look
+ for name server addresses as glue in the zone
+ holding the NS RRset in the case where this zone
+ was not the same as the one where it looked for
+ name server addresses as authoritative data.
+
+ 308. [bug] Treat a SOA record not at top of zone as an error
+ when loading a zone. [RT #154]
+
+ 307. [bug] When canceling a query, the resolver didn't check for
+ isc_socket_sendto() calls that did not yet have their
+ completion events posted, so it could (rarely) end up
+ destroying the query context and then want to use
+ it again when the send event posted, triggering an
+ assertion as it tried to cancel an already-canceled
+ query. [RT #77]
+
+ 306. [bug] Reading HMAC-MD5 private key files didn't work.
+
+ 305. [bug] When reloading the server with a config file
+ containing a syntax error, it could catch an
+ assertion failure trying to perform zone
+ maintenance on tentatively created zones whose
+ views were never fully configured and lacked
+ an address database.
+
+ 304. [bug] If more than LWRES_CONFMAXNAMESERVERS servers
+ are listed in resolv.conf, silently ignore them
+ instead of returning failure.
+
+ 303. [bug] Add additional sanity checks to differentiate a AXFR
+ response vs a IXFR response. [RT #157]
+
+ 302. [bug] In dig, host, and nslookup, MXNAME should be large
+ enough to hold any legal domain name in presentation
+ format + terminating NULL.
+
+ 301. [bug] Uninitialized pointer in host:printmessage(). [RT #159]
+
+ 300. [bug] Using both <isc/net.h> and <lwres/net.h> didn't work
+ on platforms lacking IPv6 because each included their
+ own ipv6 header file for the missing definitions. Now
+ each library's ipv6.h defines the wrapper symbol of
+ the other (ISC_IPV6_H and LWRES_IPV6_H).
+
+ 299. [cleanup] Get the user and group information before changing the
+ root directory, so the administrator does not need to
+ keep a copy of the user and group databases in the
+ chroot'ed environment. Suggested by Hakan Olsson.
+
+ 298. [bug] A mutex deadlock occurred during shutdown of the
+ interface manager under certain conditions.
+ Digital Unix systems were the most affected.
+
+ 297. [bug] Specifying a key name that wasn't fully qualified
+ in certain parts of the config file could cause
+ an assertion failure.
+
+ 296. [bug] "make install" from a separate build directory
+ failed unless configure had been run in the source
+ directory, too.
+
+ 295. [bug] When invoked with type==CNAME and a message
+ not constructed by dns_message_parse(),
+ dns_message_findname() failed to find anything
+ due to checking for attribute bits that are set
+ only in dns_message_parse(). This caused an
+ infinite loop when constructing the response to
+ an ANY query at a CNAME in a secure zone.
+
+ 294. [bug] If we run out of space in while processing glue
+ when reading a master file and commit "current name"
+ reverts to "name_current" instead of staying as
+ "name_glue".
+
+ 293. [port] Add support for FreeBSD 4.0 system tests.
+
+ 292. [bug] Due to problems with the way some operating systems
+ handle simultaneous listening on IPv4 and IPv6
+ addresses, the server no longer listens on IPv6
+ addresses by default. To revert to the previous
+ behavior, specify "listen-on-v6 { any; };" in
+ the config file.
+
+ 291. [func] Caching servers no longer send outgoing queries
+ over TCP just because the incoming recursive query
+ was a TCP one.
+
+ 290. [cleanup] +twiddle option to dig (for testing only) removed.
+
+ 289. [cleanup] dig is now installed in $bindir instead of $sbindir.
+ host is now installed in $bindir. (Be sure to remove
+ any $sbindir/dig from a previous release.)
+
+ 288. [func] rndc is now installed by "make install" into $sbindir.
+
+ 287. [bug] rndc now works again as "rndc 127.1 reload" (for
+ only that task). Parsing its configuration file and
+ using digital signatures for authentication has been
+ disabled until named supports the "controls" statement,
+ post-9.0.0.
+
+ 286. [bug] On Solaris 2, when named inherited a signal state
+ where SIGHUP had the SIG_IGN action, SIGHUP would
+ be ignored rather than causing the server to reload
+ its configuration.
+
+ 285. [bug] A change made to the dst API for beta4 inadvertently
+ broke OMAPI's creation of a dst key from an incoming
+ message, causing an assertion to be triggered. Fixed.
+
+ 284. [func] The DNSSEC key generation and signing tools now
+ generate randomness from keyboard input on systems
+ that lack /dev/random.
+
+ 283. [cleanup] The 'lwresd' program is now a link to 'named'.
+
+ 282. [bug] The lexer now returns ISC_R_RANGE if parsed integer is
+ too big for an unsigned long.
+
+ 281. [bug] Fixed list of recognized config file category names.
+
+ 280. [func] Add isc-config.sh, which can be used to more
+ easily build applications that link with
+ our libraries.
+
+ 279. [bug] Private omapi function symbols shared between
+ two or more files in libomapi.a were not namespace
+ protected using the ISC convention of starting with
+ the library name and two underscores ("omapi__"...)
+
+ 278. [bug] bin/named/logconf.c:category_fromconf() didn't take
+ note of when isc_log_categorybyname() wasn't able
+ to find the category name and would then apply the
+ channel list of the unknown category to all categories.
+
+ 277. [bug] isc_log_categorybyname() and isc_log_modulebyname()
+ would fail to find the first member of any category
+ or module array apart from the internal defaults.
+ Thus, for example, the "notify" category was improperly
+ configured by named.
+
+ 276. [bug] dig now supports maximum sized TCP messages.
+
+ 275. [bug] The definition of lwres_gai_strerror() was missing
+ the lwres_ prefix.
+
+ 274. [bug] TSIG AXFR verify failed when talking to a BIND 8
+ server.
+
+ 273. [func] The default for the 'transfer-format' option is
+ now 'many-answers'. This will break zone transfers
+ to BIND 4.9.5 and older unless there is an explicit
+ 'one-answer' configuration.
+
+ 272. [bug] The sending of large TCP responses was canceled
+ in mid-transmission due to a race condition
+ caused by the failure to set the client object's
+ "newstate" variable correctly when transitioning
+ to the "working" state.
+
+ 271. [func] Attempt to probe the number of cpus in named
+ if unspecified rather than defaulting to 1.
+
+ 270. [func] Allow maximum sized TCP answers.
+
+ 269. [bug] Failed DNSSEC validations could cause an assertion
+ failure by causing clone_results() to be called with
+ with hevent->node == NULL.
+
+ 268. [doc] A plain text version of the Administrator
+ Reference Manual is now included in the distribution,
+ as doc/arm/Bv9ARM.txt.
+
+ 267. [func] Nsupdate is now provided in the distribution.
+
+ 266. [bug] zone.c:save_nsrrset() node was not initialized.
+
+ 265. [bug] dns_request_create() now works for TCP.
+
+ 264. [func] Dispatch can not take TCP sockets in connecting
+ state. Set DNS_DISPATCHATTR_CONNECTED when calling
+ dns_dispatch_createtcp() for connected TCP sockets
+ or call dns_dispatch_starttcp() when the socket is
+ connected.
+
+ 263. [func] New logging channel type 'stderr'
+
+ channel some-name {
+ stderr;
+ severity error;
+ }
+
+ 262. [bug] 'master' was not initialized in zone.c:stub_callback().
+
+ 261. [func] Add dns_zone_markdirty().
+
+ 260. [bug] Running named as a non-root user failed on Linux
+ kernels new enough to support retaining capabilities
+ after setuid().
+
+ 259. [func] New random-device and random-seed-file statements
+ for global options block of named.conf. Both accept
+ a single string argument.
+
+ 258. [bug] Fixed printing of lwres_addr_t.address field.
+
+ 257. [bug] The server detached the last zone manager reference
+ too early, while it could still be in use by queries.
+ This manifested itself as assertion failures during the
+ shutdown process for busy name servers. [RT #133]
+
+ 256. [func] isc_ratelimiter_t now has attach/detach semantics, and
+ isc_ratelimiter_shutdown guarantees that the rate
+ limiter is detached from its task.
+
+ 255. [func] New function dns_zonemgr_attach().
+
+ 254. [bug] Suppress "query denied" messages on additional data
+ lookups.
+
+ --- 9.0.0b4 released ---
+
+ 253. [func] resolv.conf parser now recognizes ';' and '#' as
+ comments (anywhere in line, not just as the beginning).
+
+ 252. [bug] resolv.conf parser mishandled masks on sortlists.
+ It also aborted when an unrecognized keyword was seen,
+ now it silently ignores the entire line.
+
+ 251. [bug] lwresd caught an assertion failure on startup.
+
+ 250. [bug] fixed handling of size+unit when value would be too
+ large for internal representation.
+
+ 249. [cleanup] max-cache-size config option now takes a size-spec
+ like 'datasize', except 'default' is not allowed.
+
+ 248. [bug] global lame-ttl option was not being printed when
+ config structures were written out.
+
+ 247. [cleanup] Rename cache-size config option to max-cache-size.
+
+ 246. [func] Rename global option cachesize to cache-size and
+ add corresponding option to view statement.
+
+ 245. [bug] If an uncompressed name will take more than 255
+ bytes and the buffer is sufficiently long,
+ dns_name_fromwire should return DNS_R_FORMERR,
+ not ISC_R_NOSPACE. This bug caused cause the
+ server to catch an assertion failure when it
+ received a query for a name longer than 255
+ bytes.
+
+ 244. [bug] empty named.conf file and empty options statement are
+ now parsed properly.
+
+ 243. [func] new cachesize option for named.conf
+
+ 242. [cleanup] fixed incorrect warning about auth-nxdomain usage.
+
+ 241. [cleanup] nscount and soacount have been removed from the
+ dns_master_*() argument lists.
+
+ 240. [func] databases now come in three flavours: zone, cache
+ and stub.
+
+ 239. [func] If ISC_MEM_DEBUG is enabled, the variable
+ isc_mem_debugging controls whether messages
+ are printed or not.
+
+ 238. [cleanup] A few more compilation warnings have been quieted:
+ + missing sigwait prototype on BSD/OS 4.0/4.0.1.
+ + PTHREAD_ONCE_INIT unbraced initializer warnings on
+ Solaris 2.8.
+ + IN6ADDR_ANY_INIT unbraced initializer warnings on
+ BSD/OS 4.*, Linux and Solaris 2.8.
+
+ 237. [bug] If connect() returned ENOBUFS when the resolver was
+ initiating a TCP query, the socket didn't get
+ destroyed, and the server did not shut down cleanly.
+
+ 236. [func] Added new listen-on-v6 config file statement.
+
+ 235. [func] Consider it a config file error if a listen-on
+ statement has an IPv6 address in it, or a
+ listen-on-v6 statement has an IPv4 address in it.
+
+ 234. [bug] Allow a trusted-key's first field (domain-name) be
+ either a quoted or an unquoted string, instead of
+ requiring a quoted string.
+
+ 233. [cleanup] Convert all config structure integer values to unsigned
+ integer (isc_uint32_t) to match grammar.
+
+ 232. [bug] Allow slave zones to not have a file.
+
+ 231. [func] Support new 'port' clause in config file options
+ section. Causes 'listen-on', 'masters' and
+ 'also-notify' statements to use its value instead of
+ default (53).
+
+ 230. [func] Replace the dst sign/verify API with a cleaner one.
+
+ 229. [func] Support config file sig-validity-interval statement
+ in options, views and zone statements (master
+ zones only).
+
+ 228. [cleanup] Logging messages in config module stripped of
+ trailing period.
+
+ 227. [cleanup] The enumerated identifiers dns_rdataclass_*,
+ dns_rcode_*, dns_opcode_*, and dns_trust_* are
+ also now cast to their appropriate types, as with
+ dns_rdatatype_* in item number 225 below.
+
+ 226. [func] dns_name_totext() now always prints the root name as
+ '.', even when omit_final_dot is true.
+
+ 225. [cleanup] The enumerated dns_rdatatype_* identifiers are now
+ cast to dns_rdatatype_t via macros of their same name
+ so that they are of the proper integral type wherever
+ a dns_rdatatype_t is needed.
+
+ 224. [cleanup] The entire project builds cleanly with gcc's
+ -Wcast-qual and -Wwrite-strings warnings enabled,
+ which is now the default when using gcc. (Warnings
+ from confparser.c, because of yacc's code, are
+ unfortunately to be expected.)
+
+ 223. [func] Several functions were re-prototyped to qualify one
+ or more of their arguments with "const". Similarly,
+ several functions that return pointers now have
+ those pointers qualified with const.
+
+ 222. [bug] The global 'also-notify' option was ignored.
+
+ 221. [bug] An uninitialized variable was sometimes passed to
+ dns_rdata_freestruct() when loading a zone, causing
+ an assertion failure.
+
+ 220. [cleanup] Set the default outgoing port in the view, and
+ set it in sockaddrs returned from the ADB.
+ [31-May-2000 explorer]
+
+ 219. [bug] Signed truncated messages more correctly follow
+ the respective specs.
+
+ 218. [func] When an rdataset is signed, its ttl is normalized
+ based on the signature validity period.
+
+ 217. [func] Also-notify and trusted-keys can now be used in
+ the 'view' statement.
+
+ 216. [func] The 'max-cache-ttl' and 'max-ncache-ttl' options
+ now work.
+
+ 215. [bug] Failures at certain points in request processing
+ could cause the assertion INSIST(client->lockview
+ == NULL) to be triggered.
+
+ 214. [func] New public function isc_netaddr_format(), for
+ formatting network addresses in log messages.
+
+ 213. [bug] Don't leak memory when reloading the zone if
+ an update-policy clause was present in the old zone.
+
+ 212. [func] Added dns_message_get/settsigkey, to make TSIG
+ key management reasonable.
+
+ 211. [func] The 'key' and 'server' statements can now occur
+ inside 'view' statements.
+
+ 210. [bug] The 'allow-transfer' option was ignored for slave
+ zones, and the 'transfers-per-ns' option was
+ was ignored for all zones.
+
+ 209. [cleanup] Upgraded openssl files to new version 0.9.5a
+
+ 208. [func] Added ISC_OFFSET_MAXIMUM for the maximum value
+ of an isc_offset_t.
+
+ 207. [func] The dnssec tools properly use the logging subsystem.
+
+ 206. [cleanup] dst now stores the key name as a dns_name_t, not
+ a char *.
+
+ 205. [cleanup] On IRIX, turn off the mostly harmless warnings 1692
+ ("prototyped function redeclared without prototype")
+ and 1552 ("variable ... set but not used") when
+ compiling in the lib/dns/sec/{dnssafe,openssl}
+ directories, which contain code imported from outside
+ sources.
+
+ 204. [cleanup] On HP/UX, pass +vnocompatwarnings to the linker
+ to quiet the warnings that "The linked output may not
+ run on a PA 1.x system."
+
+ 203. [func] notify and zone soa queries are now tsig signed when
+ appropriate.
+
+ 202. [func] isc_lex_getsourceline() changed from returning int
+ to returning unsigned long, the type of its underlying
+ counter.
+
+ 201. [cleanup] Removed the test/sdig program, it has been
+ replaced by bin/dig/dig.
+
+ --- 9.0.0b3 released ---
+
+ 200. [bug] Failures in sending query responses to clients
+ (e.g., running out of network buffers) were
+ not logged.
+
+ 199. [bug] isc_heap_delete() sometimes violated the heap
+ invariant, causing timer events not to be posted
+ when due.
+
+ 198. [func] Dispatch managers hold memory pools which
+ any managed dispatcher may use. This allows
+ us to avoid dipping into the memory context for
+ most allocations. [19-May-2000 explorer]
+
+ 197. [bug] When an incoming AXFR or IXFR completes, the
+ zone's internal state is refreshed from the
+ SOA data. [19-May-2000 explorer]
+
+ 196. [func] Dispatchers can be shared easily between views
+ and/or interfaces. [19-May-2000 explorer]
+
+ 195. [bug] Including the NXT record of the root domain
+ in a negative response caused an assertion
+ failure.
+
+ 194. [doc] The PDF version of the Administrator's Reference
+ Manual is no longer included in the ISC BIND9
+ distribution.
+
+ 193. [func] changed dst_key_free() prototype.
+
+ 192. [bug] Zone configuration validation is now done at end
+ of config file parsing, and before loading
+ callbacks.
+
+ 191. [func] Patched to compile on UnixWare 7.x. This platform
+ is not directly supported by the ISC.
+
+ 190. [cleanup] The DNSSEC tools have been moved to a separate
+ directory dnssec/ and given the following new,
+ more descriptive names:
+
+ dnssec-keygen
+ dnssec-signzone
+ dnssec-signkey
+ dnssec-makekeyset
+
+ Their command line arguments have also been changed to
+ be more consistent. dnssec-keygen now prints the
+ name of the generated key files (sans extension)
+ on standard output to simplify its use in automated
+ scripts.
+
+ 189. [func] isc_time_secondsastimet(), a new function, will ensure
+ that the number of seconds in an isc_time_t does not
+ exceed the range of a time_t, or return ISC_R_RANGE.
+ Similarly, isc_time_now(), isc_time_nowplusinterval(),
+ isc_time_add() and isc_time_subtract() now check the
+ range for overflow/underflow. In the case of
+ isc_time_subtract, this changed a calling requirement
+ (ie, something that could generate an assertion)
+ into merely a condition that returns an error result.
+ isc_time_add() and isc_time_subtract() were void-
+ valued before but now return isc_result_t.
+
+ 188. [func] Log a warning message when an incoming zone transfer
+ contains out-of-zone data.
+
+ 187. [func] isc_ratelimiter_enqueue() has an additional argument
+ 'task'.
+
+ 186. [func] dns_request_getresponse() has an additional argument
+ 'preserve_order'.
+
+ 185. [bug] Fixed up handling of ISC_MEMCLUSTER_LEGACY. Several
+ public functions did not have an isc__ prefix, and
+ referred to functions that had previously been
+ renamed.
+
+ 184. [cleanup] Variables/functions which began with two leading
+ underscores were made to conform to the ANSI/ISO
+ standard, which says that such names are reserved.
+
+ 183. [func] ISC_LOG_PRINTTAG option for log channels. Useful
+ for logging the program name or other identifier.
+
+ 182. [cleanup] New command-line parameters for dnssec tools
+
+ 181. [func] Added dst_key_buildfilename and dst_key_parsefilename
+
+ 180. [func] New isc_result_t ISC_R_RANGE. Supersedes DNS_R_RANGE.
+
+ 179. [func] options named.conf statement *must* now come
+ before any zone or view statements.
+
+ 178. [func] Post-load of named.conf check verifies a slave zone
+ has non-empty list of masters defined.
+
+ 177. [func] New per-zone boolean:
+
+ enable-zone yes | no ;
+
+ intended to let a zone be disabled without having
+ to comment out the entire zone statement.
+
+ 176. [func] New global and per-view option:
+
+ max-cache-ttl number
+
+ 175. [func] New global and per-view option:
+
+ additional-data internal | minimal | maximal;
+
+ 174. [func] New public function isc_sockaddr_format(), for
+ formatting socket addresses in log messages.
+
+ 173. [func] Keep a queue of zones waiting for zone transfer
+ quota so that a new transfer can be dispatched
+ immediately whenever quota becomes available.
+
+ 172. [bug] $TTL directive was sometimes missing from dumped
+ master files because totext_ctx_init() failed to
+ initialize ctx->current_ttl_valid.
+
+ 171. [cleanup] On NetBSD systems, the mit-pthreads or
+ unproven-pthreads library is now always used
+ unless --with-ptl2 is explicitly specified on
+ the configure command line. The
+ --with-mit-pthreads option is no longer needed
+ and has been removed.
+
+ 170. [cleanup] Remove inter server consistency checks from zone,
+ these should return as a separate module in 9.1.
+ dns_zone_checkservers(), dns_zone_checkparents(),
+ dns_zone_checkchildren(), dns_zone_checkglue().
+
+ Remove dns_zone_setadb(), dns_zone_setresolver(),
+ dns_zone_setrequestmgr() these should now be found
+ via the view.
+
+ 169. [func] ratelimiter can now process N events per interval.
+
+ 168. [bug] include statements in named.conf caused syntax errors
+ due to not consuming the semicolon ending the include
+ statement before switching input streams.
+
+ 167. [bug] Make lack of masters for a slave zone a soft error.
+
+ 166. [bug] Keygen was overwriting existing keys if key_id
+ conflicted, now it will retry, and non-null keys
+ with key_id == 0 are not generated anymore. Key
+ was not able to generate NOAUTHCONF DSA key,
+ increased RSA key size to 2048 bits.
+
+ 165. [cleanup] Silence "end-of-loop condition not reached" warnings
+ from Solaris compiler.
+
+ 164. [func] Added functions isc_stdio_open(), isc_stdio_close(),
+ isc_stdio_seek(), isc_stdio_read(), isc_stdio_write(),
+ isc_stdio_flush(), isc_stdio_sync(), isc_file_remove()
+ to encapsulate nonportable usage of errno and sync.
+
+ 163. [func] Added result codes ISC_R_FILENOTFOUND and
+ ISC_R_FILEEXISTS.
+
+ 162. [bug] Ensure proper range for arguments to ctype.h functions.
+
+ 161. [cleanup] error in yyparse prototype that only HPUX caught.
+
+ 160. [cleanup] getnet*() are not going to be implemented at this
+ stage.
+
+ 159. [func] Redefinition of config file elements is now an
+ error (instead of a warning).
+
+ 158. [bug] Log channel and category list copy routines
+ weren't assigning properly to output parameter.
+
+ 157. [port] Fix missing prototype for getopt().
+
+ 156. [func] Support new 'database' statement in zone.
+
+ database "quoted-string";
+
+ 155. [bug] ns_notify_start() was not detaching the found zone.
+
+ 154. [func] The signer now logs libdns warnings to stderr even when
+ not verbose, and in a nicer format.
+
+ 153. [func] dns_rdata_tostruct() 'mctx' is now optional. If 'mctx'
+ is NULL then you need to preserve the 'rdata' until
+ you have finished using the structure as there may be
+ references to the associated memory. If 'mctx' is
+ non-NULL it is guaranteed that there are no references
+ to memory associated with 'rdata'.
+
+ dns_rdata_freestruct() must be called if 'mctx' was
+ non-NULL and may safely be called if 'mctx' was NULL.
+
+ 152. [bug] keygen dumped core if domain name argument was omitted
+ from command line.
+
+ 151. [func] Support 'disabled' statement in zone config (causes
+ zone to be parsed and then ignored). Currently must
+ come after the 'type' clause.
+
+ 150. [func] Support optional ports in masters and also-notify
+ statements:
+
+ masters [ port xxx ] { y.y.y.y [ port zzz ] ; }
+
+ 149. [cleanup] Removed unused argument 'olist' from
+ dns_c_view_unsetordering().
+
+ 148. [cleanup] Stop issuing some warnings about some configuration
+ file statements that were not implemented, but now are.
+
+ 147. [bug] Changed yacc union size to be smaller for yaccs that
+ put yacc-stack on the real stack.
+
+ 146. [cleanup] More general redundant header file cleanup. Rather
+ than continuing to itemize every header which changed,
+ this changelog entry just notes that if a header file
+ did not need another header file that it was including
+ in order to provide its advertised functionality, the
+ inclusion of the other header file was removed. See
+ util/check-includes for how this was tested.
+
+ 145. [cleanup] Added <isc/lang.h> and ISC_LANG_BEGINDECLS/
+ ISC_LANG_ENDDECLS to header files that had function
+ prototypes, and removed it from those that did not.
+
+ 144. [cleanup] libdns header files too numerous to name were made
+ to conform to the same style for multiple inclusion
+ protection.
+
+ 143. [func] Added function dns_rdatatype_isknown().
+
+ 142. [cleanup] <isc/stdtime.h> does not need <time.h> or
+ <isc/result.h>.
+
+ 141. [bug] Corrupt requests with multiple questions could
+ cause an assertion failure.
+
+ 140. [cleanup] <isc/time.h> does not need <time.h> or <isc/result.h>.
+
+ 139. [cleanup] <isc/net.h> now includes <isc/types.h> instead of
+ <isc/int.h> and <isc/result.h>.
+
+ 138. [cleanup] isc_strtouq moved from str.[ch] to string.[ch] and
+ renamed isc_string_touint64. isc_strsep moved from
+ strsep.c to string.c and renamed isc_string_separate.
+
+ 137. [cleanup] <isc/commandline.h>, <isc/mem.h>, <isc/print.h>
+ <isc/serial.h>, <isc/string.h> and <isc/offset.h>
+ made to conform to the same style for multiple
+ inclusion protection.
+
+ 136. [cleanup] <isc/commandline.h>, <isc/interfaceiter.h>,
+ <isc/net.h> and Win32's <isc/thread.h> needed
+ ISC_LANG_BEGINDECLS/ISC_LANG_ENDDECLS.
+
+ 135. [cleanup] Win32's <isc/condition.h> did not need <isc/result.h>
+ or <isc/boolean.h>, now uses <isc/types.h> in place
+ of <isc/time.h>, and needed ISC_LANG_BEGINDECLS
+ and ISC_LANG_ENDDECLS.
+
+ 134. [cleanup] <isc/dir.h> does not need <limits.h>.
+
+ 133. [cleanup] <isc/ipv6.h> needs <isc/platform.h>.
+
+ 132. [cleanup] <isc/app.h> does not need <isc/task.h>, but does
+ need <isc/eventclass.h>.
+
+ 131. [cleanup] <isc/mutex.h> and <isc/util.h> need <isc/result.h>
+ for ISC_R_* codes used in macros.
+
+ 130. [cleanup] <isc/condition.h> does not need <pthread.h> or
+ <isc/boolean.h>, and now includes <isc/types.h>
+ instead of <isc/time.h>.
+
+ 129. [bug] The 'default_debug' log channel was not set up when
+ 'category default' was present in the config file
+
+ 128. [cleanup] <isc/dir.h> had ISC_LANG_BEGINDECLS instead of
+ ISC_LANG_ENDDECLS at end of header.
+
+ 127. [cleanup] The contracts for the comparison routines
+ dns_name_fullcompare(), dns_name_compare(),
+ dns_name_rdatacompare(), and dns_rdata_compare() now
+ specify that the order value returned is < 0, 0, or > 0
+ instead of -1, 0, or 1.
+
+ 126. [cleanup] <isc/quota.h> and <isc/taskpool.h> need <isc/lang.h>.
+
+ 125. [cleanup] <isc/eventclass.h>, <isc/ipv6.h>, <isc/magic.h>,
+ <isc/mutex.h>, <isc/once.h>, <isc/region.h>, and
+ <isc/resultclass.h> do not need <isc/lang.h>.
+
+ 124. [func] signer now imports parent's zone key signature
+ and creates null keys/sets zone status bit for
+ children when necessary
+
+ 123. [cleanup] <isc/event.h> does not need <stddef.h>.
+
+ 122. [cleanup] <isc/task.h> does not need <isc/mem.h> or
+ <isc/result.h>.
+
+ 121. [cleanup] <isc/symtab.h> does not need <isc/mem.h> or
+ <isc/result.h>. Multiple inclusion protection
+ symbol fixed from ISC_SYMBOL_H to ISC_SYMTAB_H.
+ isc_symtab_t moved to <isc/types.h>.
+
+ 120. [cleanup] <isc/socket.h> does not need <isc/boolean.h>,
+ <isc/bufferlist.h>, <isc/task.h>, <isc/mem.h> or
+ <isc/net.h>.
+
+ 119. [cleanup] structure definitions for generic rdata structures do
+ not have _generic_ in their names.
+
+ 118. [cleanup] libdns.a is now namespace-clean, on NetBSD, excepting
+ YACC crust (yyparse, etc) [2000-apr-27 explorer]
+
+ 117. [cleanup] libdns.a changes:
+ dns_zone_clearnotify() and dns_zone_addnotify()
+ are replaced by dns_zone_setnotifyalso().
+ dns_zone_clearmasters() and dns_zone_addmaster()
+ are replaced by dns_zone_setmasters().
+
+ 116. [func] Added <isc/offset.h> for isc_offset_t (aka off_t
+ on Unix systems).
+
+ 115. [port] Shut up the -Wmissing-declarations warning about
+ <stdio.h>'s __sputaux on BSD/OS pre-4.1.
+
+ 114. [cleanup] <isc/sockaddr.h> does not need <isc/buffer.h> or
+ <isc/list.h>.
+
+ 113. [func] Utility programs dig and host added.
+
+ 112. [cleanup] <isc/serial.h> does not need <isc/boolean.h>.
+
+ 111. [cleanup] <isc/rwlock.h> does not need <isc/result.h> or
+ <isc/mutex.h>.
+
+ 110. [cleanup] <isc/result.h> does not need <isc/boolean.h> or
+ <isc/list.h>.
+
+ 109. [bug] "make depend" did nothing for
+ bin/tests/{db,mem,sockaddr,tasks,timers}/.
+
+ 108. [cleanup] DNS_SETBIT/DNS_GETBIT/DNS_CLEARBIT moved from
+ <dns/types.h> to <dns/bit.h> and renamed to
+ DNS_BIT_SET/DNS_BIT_GET/DNS_BIT_CLEAR.
+
+ 107. [func] Add keysigner and keysettool.
+
+ 106. [func] Allow dnssec verifications to ignore the validity
+ period. Used by several of the dnssec tools.
+
+ 105. [doc] doc/dev/coding.html expanded with other
+ implicit conventions the developers have used.
+
+ 104. [bug] Made compress_add and compress_find static to
+ lib/dns/compress.c.
+
+ 103. [func] libisc buffer API changes for <isc/buffer.h>:
+ Added:
+ isc_buffer_base(b) (pointer)
+ isc_buffer_current(b) (pointer)
+ isc_buffer_active(b) (pointer)
+ isc_buffer_used(b) (pointer)
+ isc_buffer_length(b) (int)
+ isc_buffer_usedlength(b) (int)
+ isc_buffer_consumedlength(b) (int)
+ isc_buffer_remaininglength(b) (int)
+ isc_buffer_activelength(b) (int)
+ isc_buffer_availablelength(b) (int)
+ Removed:
+ ISC_BUFFER_USEDCOUNT(b)
+ ISC_BUFFER_AVAILABLECOUNT(b)
+ isc_buffer_type(b)
+ Changed names:
+ isc_buffer_used(b, r) ->
+ isc_buffer_usedregion(b, r)
+ isc_buffer_available(b, r) ->
+ isc_buffer_available_region(b, r)
+ isc_buffer_consumed(b, r) ->
+ isc_buffer_consumedregion(b, r)
+ isc_buffer_active(b, r) ->
+ isc_buffer_activeregion(b, r)
+ isc_buffer_remaining(b, r) ->
+ isc_buffer_remainingregion(b, r)
+
+ Buffer types were removed, so the ISC_BUFFERTYPE_*
+ macros are no more, and the type argument to
+ isc_buffer_init and isc_buffer_allocate were removed.
+ isc_buffer_putstr is now void (instead of isc_result_t)
+ and requires that the caller ensure that there
+ is enough available buffer space for the string.
+
+ 102. [port] Correctly detect inet_aton, inet_pton and inet_ptop
+ on BSD/OS 4.1.
+
+ 101. [cleanup] Quieted EGCS warnings from lib/isc/print.c.
+
+ 100. [cleanup] <isc/random.h> does not need <isc/int.h> or
+ <isc/mutex.h>. isc_random_t moved to <isc/types.h>.
+
+ 99. [cleanup] Rate limiter now has separate shutdown() and
+ destroy() functions, and it guarantees that all
+ queued events are delivered even in the shutdown case.
+
+ 98. [cleanup] <isc/print.h> does not need <stdarg.h> or <stddef.h>
+ unless ISC_PLATFORM_NEEDVSNPRINTF is defined.
+
+ 97. [cleanup] <isc/ondestroy.h> does not need <stddef.h> or
+ <isc/event.h>.
+
+ 96. [cleanup] <isc/mutex.h> does not need <isc/result.h>.
+
+ 95. [cleanup] <isc/mutexblock.h> does not need <isc/result.h>.
+
+ 94. [cleanup] Some installed header files did not compile as C++.
+
+ 93. [cleanup] <isc/msgcat.h> does not need <isc/result.h>.
+
+ 92. [cleanup] <isc/mem.h> does not need <stddef.h>, <isc/boolean.h>,
+ or <isc/result.h>.
+
+ 91. [cleanup] <isc/log.h> does not need <sys/types.h> or
+ <isc/result.h>.
+
+ 90. [cleanup] Removed unneeded ISC_LANG_BEGINDECLS/ISC_LANG_ENDDECLS
+ from <named/listenlist.h>.
+
+ 89. [cleanup] <isc/lex.h> does not need <stddef.h>.
+
+ 88. [cleanup] <isc/interfaceiter.h> does not need <isc/result.h> or
+ <isc/mem.h>. isc_interface_t and isc_interfaceiter_t
+ moved to <isc/types.h>.
+
+ 87. [cleanup] <isc/heap.h> does not need <isc/boolean.h>,
+ <isc/mem.h> or <isc/result.h>.
+
+ 86. [cleanup] isc_bufferlist_t moved from <isc/bufferlist.h> to
+ <isc/types.h>.
+
+ 85. [cleanup] <isc/bufferlist.h> does not need <isc/buffer.h>,
+ <isc/list.h>, <isc/mem.h>, <isc/region.h> or
+ <isc/int.h>.
+
+ 84. [func] allow-query ACL checks now apply to all data
+ added to a response.
+
+ 83. [func] If the server is authoritative for both a
+ delegating zone and its (nonsecure) delegatee, and
+ a query is made for a KEY RR at the top of the
+ delegatee, then the server will look for a KEY
+ in the delegator if it is not found in the delegatee.
+
+ 82. [cleanup] <isc/buffer.h> does not need <isc/list.h>.
+
+ 81. [cleanup] <isc/int.h> and <isc/boolean.h> do not need
+ <isc/lang.h>.
+
+ 80. [cleanup] <isc/print.h> does not need <stdio.h> or <stdlib.h>.
+
+ 79. [cleanup] <dns/callbacks.h> does not need <stdio.h>.
+
+ 78. [cleanup] lwres_conftest renamed to lwresconf_test for
+ consistency with other *_test programs.
+
+ 77. [cleanup] typedef of isc_time_t and isc_interval_t moved from
+ <isc/time.h> to <isc/types.h>.
+
+ 76. [cleanup] Rewrote keygen.
+
+ 75. [func] Don't load a zone if its database file is older
+ than the last time the zone was loaded.
+
+ 74. [cleanup] Removed mktemplate.o and ufile.o from libisc.a,
+ subsumed by file.o.
+
+ 73. [func] New "file" API in libisc, including new function
+ isc_file_getmodtime, isc_mktemplate renamed to
+ isc_file_mktemplate and isc_ufile renamed to
+ isc_file_openunique. By no means an exhaustive API,
+ it is just what's needed for now.
+
+ 72. [func] DNS_RBTFIND_NOPREDECESSOR and DNS_RBTFIND_NOOPTIONS
+ added for dns_rbt_findnode, the former to disable the
+ setting of the chain to the predecessor, and the
+ latter to make clear when no options are set.
+
+ 71. [cleanup] Made explicit the implicit REQUIREs of
+ isc_time_seconds, isc_time_nanoseconds, and
+ isc_time_subtract.
+
+ 70. [func] isc_time_set() added.
+
+ 69. [bug] The zone object's master and also-notify lists grew
+ longer with each server reload.
+
+ 68. [func] Partial support for SIG(0) on incoming messages.
+
+ 67. [performance] Allow use of alternate (compile-time supplied)
+ OpenSSL libraries/headers.
+
+ 66. [func] Data in authoritative zones should have a trust level
+ beyond secure.
+
+ 65. [cleanup] Removed obsolete typedef of dns_zone_callbackarg_t
+ from <dns/types.h>.
+
+ 64. [func] The RBT, DB, and zone table APIs now allow the
+ caller find the most-enclosing superdomain of
+ a name.
+
+ 63. [func] Generate NOTIFY messages.
+
+ 62. [func] Add UDP refresh support.
+
+ 61. [cleanup] Use single quotes consistently in log messages.
+
+ 60. [func] Catch and disallow singleton types on message
+ parse.
+
+ 59. [bug] Cause net/host unreachable to be a hard error
+ when sending and receiving.
+
+ 58. [bug] bin/named/query.c could sometimes trigger the
+ (client->query.attributes & NS_QUERYATTR_NAMEBUFUSED)
+ == 0 assertion in query_newname().
+
+ 57. [func] Added dns_nxt_typepresent()
+
+ 56. [bug] SIG records were not properly returned in cached
+ negative answers.
+
+ 55. [bug] Responses containing multiple names in the authority
+ section were not negatively cached.
+
+ 54. [bug] If a fetch with sigrdataset==NULL joined one with
+ sigrdataset!=NULL or vice versa, the resolver
+ could catch an assertion or lose signature data,
+ respectively.
+
+ 53. [port] freebsd 4.0: lib/isc/unix/socket.c requires
+ <sys/param.h>.
+
+ 52. [bug] rndc: taskmgr and socketmgr were not initialized
+ to NULL.
+
+ 51. [cleanup] dns/compress.h and dns/zt.h did not need to include
+ dns/rbt.h; it was needed only by compress.c and zt.c.
+
+ 50. [func] RBT deletion no longer requires a valid chain to work,
+ and dns_rbt_deletenode was added.
+
+ 49. [func] Each cache now has its own mctx.
+
+ 48. [func] isc_task_create() no longer takes an mctx.
+ isc_task_mem() has been eliminated.
+
+ 47. [func] A number of modules now use memory context reference
+ counting.
+
+ 46. [func] Memory contexts are now reference counted.
+ Added isc_mem_inuse() and isc_mem_preallocate().
+ Renamed isc_mem_destroy_check() to
+ isc_mem_setdestroycheck().
+
+ 45. [bug] The trusted-key statement incorrectly loaded keys.
+
+ 44. [bug] Don't include authority data if it would force us
+ to unset the AD bit in the message.
+
+ 43. [bug] DNSSEC verification of cached rdatasets was failing.
+
+ 42. [cleanup] Simplified logging of messages with embedded domain
+ names by introducing a new convenience function
+ dns_name_format().
+
+ 41. [func] Use PR_SET_KEEPCAPS on Linux 2.3.99-pre3 and later
+ to allow 'named' to run as a non-root user while
+ retaining the ability to bind() to privileged
+ ports.
+
+ 40. [func] Introduced new logging category "dnssec" and
+ logging module "dns/validator".
+
+ 39. [cleanup] Moved the typedefs for isc_region_t, isc_textregion_t,
+ and isc_lex_t to <isc/types.h>.
+
+ 38. [bug] TSIG signed incoming zone transfers work now.
+
+ 37. [bug] If the first RR in an incoming zone transfer was
+ not an SOA, the server died with an assertion failure
+ instead of just reporting an error.
+
+ 36. [cleanup] Change DNS_R_SUCCESS (and others) to ISC_R_SUCCESS
+
+ 35. [performance] Log messages which are of a level too high to be
+ logged by any channel in the logging configuration
+ will not cause the log mutex to be locked.
+
+ 34. [bug] Recursion was allowed even with 'recursion no'.
+
+ 33. [func] The RBT now maintains a parent pointer at each node.
+
+ 32. [cleanup] bin/lwresd/client.c needs <string.h> for memset()
+ prototype.
+
+ 31. [bug] Use ${LIBTOOL} to compile bin/named/main.@O@.
+
+ 30. [func] config file grammar change to support optional
+ class type for a view.
+
+ 29. [func] support new config file view options:
+
+ auth-nxdomain recursion query-source
+ query-source-v6 transfer-source
+ transfer-source-v6 max-transfer-time-out
+ max-transfer-idle-out transfer-format
+ request-ixfr provide-ixfr cleaning-interval
+ fetch-glue notify rfc2308-type1 lame-ttl
+ max-ncache-ttl min-roots
+
+ 28. [func] support lame-ttl, min-roots and serial-queries
+ config global options.
+
+ 27. [bug] Only include <netinet6/in6.h> on BSD/OS 4.[01]*.
+ Including it on other platforms (eg, NetBSD) can
+ cause a forced #error from the C preprocessor.
+
+ 26. [func] new match-clients statement in config file view.
+
+ 25. [bug] make install failed to install <isc/log.h> and
+ <isc/ondestroy.h>.
+
+ 24. [cleanup] Eliminate some unnecessary #includes of header
+ files from header files.
+
+ 23. [cleanup] Provide more context in log messages about client
+ requests, using a new function ns_client_log().
+
+ 22. [bug] SIGs weren't returned in the answer section when
+ the query resulted in a fetch.
+
+ 21. [port] Look at STD_CINCLUDES after CINCLUDES during
+ compilation, so additional system include directories
+ can be searched but header files in the bind9 source
+ tree with conflicting names take precedence. This
+ avoids issues with installed versions of dnssafe and
+ openssl.
+
+ 20. [func] Configuration file post-load validation of zones
+ failed if there were no zones.
+
+ 19. [bug] dns_zone_notifyreceive() failed to unlock the zone
+ lock in certain error cases.
+
+ 18. [bug] Use AC_TRY_LINK rather than AC_TRY_COMPILE in
+ configure.in to check for presence of in6addr_any.
+
+ 17. [func] Do configuration file post-load validation of zones.
+
+ 16. [bug] put quotes around key names on config file
+ output to avoid possible keyword clashes.
+
+ 15. [func] Add dns_name_dupwithoffsets(). This function is
+ improves comparison performance for duped names.
+
+ 14. [bug] free_rbtdb() could have 'put' unallocated memory in
+ an unlikely error path.
+
+ 13. [bug] lib/dns/master.c and lib/dns/xfrin.c didn't ignore
+ out-of-zone data.
+
+ 12. [bug] Fixed possible uninitialized variable error.
+
+ 11. [bug] axfr_rrstream_first() didn't check the result code of
+ db_rr_iterator_first(), possibly causing an assertion
+ to be triggered later.
+
+ 10. [bug] A bug in the code which makes EDNS0 OPT records in
+ bin/named/client.c and lib/dns/resolver.c could
+ trigger an assertion.
+
+ 9. [cleanup] replaced bit-setting code in confctx.c and replaced
+ repeated code with macro calls.
+
+ 8. [bug] Shutdown of incoming zone transfer accessed
+ freed memory.
+
+ 7. [cleanup] removed 'listen-on' from view statement.
+
+ 6. [bug] quote RR names when generating config file to
+ prevent possible clash with config file keywords
+ (such as 'key').
+
+ 5. [func] syntax change to named.conf file: new ssu grant/deny
+ statements must now be enclosed by an 'update-policy'
+ block.
+
+ 4. [port] bin/named/unix/os.c didn't compile on systems with
+ linux 2.3 kernel includes due to conflicts between
+ C library includes and the kernel includes. We now
+ get only what we need from <linux/capability.h>, and
+ avoid pulling in other linux kernel .h files.
+
+ 3. [bug] TKEYs go in the answer section of responses, not
+ the additional section.
+
+ 2. [bug] Generating cryptographic randomness failed on
+ systems without /dev/random.
+
+ 1. [bug] The installdirs rule in
+ lib/isc/unix/include/isc/Makefile.in had a typo which
+ prevented the isc directory from being created if it
+ didn't exist.
+
+ --- 9.0.0b2 released ---
+
+# This tells Emacs to use hard tabs in this file.
+# Local Variables:
+# indent-tabs-mode: t
+# End:
diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644
index 0000000..065c64f
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,30 @@
+Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 1996-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: COPYRIGHT,v 1.14 2008/01/02 23:47:01 tbox Exp $
+
+Portions Copyright (C) 1996-2001 Nominum, Inc.
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM 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.
diff --git a/FAQ b/FAQ
new file mode 100644
index 0000000..2c333be
--- /dev/null
+++ b/FAQ
@@ -0,0 +1,873 @@
+Frequently Asked Questions about BIND 9
+
+Copyright © 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+
+Copyright © 2000-2003 Internet Software Consortium.
+
+-----------------------------------------------------------------------
+
+1. Compilation and Installation Questions
+
+Q: I'm trying to compile BIND 9, and "make" is failing due to files not
+ being found. Why?
+
+A: Using a parallel or distributed "make" to build BIND 9 is not
+ supported, and doesn't work. If you are using one of these, use normal
+ make or gmake instead.
+
+Q: Isn't "make install" supposed to generate a default named.conf?
+
+A: Short Answer: No.
+
+ Long Answer: There really isn't a default configuration which fits any
+ site perfectly. There are lots of decisions that need to be made and
+ there is no consensus on what the defaults should be. For example
+ FreeBSD uses /etc/namedb as the location where the configuration files
+ for named are stored. Others use /var/named.
+
+ What addresses to listen on? For a laptop on the move a lot you may
+ only want to listen on the loop back interfaces.
+
+ Who do you offer recursive service to? Is there are firewall to
+ consider? If so is it stateless or stateful. Are you directly on the
+ Internet? Are you on a private network? Are you on a NAT'd network? The
+ answers to all these questions change how you configure even a caching
+ name server.
+
+2. Configuration and Setup Questions
+
+Q: Why does named log the warning message "no TTL specified - using SOA
+ MINTTL instead"?
+
+A: Your zone file is illegal according to RFC1035. It must either have a
+ line like:
+
+ $TTL 86400
+
+ at the beginning, or the first record in it must have a TTL field, like
+ the "84600" in this example:
+
+ example.com. 86400 IN SOA ns hostmaster ( 1 3600 1800 1814400 3600 )
+
+Q: Why do I get errors like "dns_zone_load: zone foo/IN: loading master
+ file bar: ran out of space"?
+
+A: This is often caused by TXT records with missing close quotes. Check
+ that all TXT records containing quoted strings have both open and close
+ quotes.
+
+Q: How do I restrict people from looking up the server version?
+
+A: Put a "version" option containing something other than the real version
+ in the "options" section of named.conf. Note doing this will not
+ prevent attacks and may impede people trying to diagnose problems with
+ your server. Also it is possible to "fingerprint" nameservers to
+ determine their version.
+
+Q: How do I restrict only remote users from looking up the server version?
+
+A: The following view statement will intercept lookups as the internal
+ view that holds the version information will be matched last. The
+ caveats of the previous answer still apply, of course.
+
+ view "chaos" chaos {
+ match-clients { <those to be refused>; };
+ allow-query { none; };
+ zone "." {
+ type hint;
+ file "/dev/null"; // or any empty file
+ };
+ };
+
+Q: What do "no source of entropy found" or "could not open entropy source
+ foo" mean?
+
+A: The server requires a source of entropy to perform certain operations,
+ mostly DNSSEC related. These messages indicate that you have no source
+ of entropy. On systems with /dev/random or an equivalent, it is used by
+ default. A source of entropy can also be defined using the
+ random-device option in named.conf.
+
+Q: I'm trying to use TSIG to authenticate dynamic updates or zone
+ transfers. I'm sure I have the keys set up correctly, but the server is
+ rejecting the TSIG. Why?
+
+A: This may be a clock skew problem. Check that the the clocks on the
+ client and server are properly synchronised (e.g., using ntp).
+
+Q: I see a log message like the following. Why?
+
+ couldn't open pid file '/var/run/named.pid': Permission denied
+
+A: You are most likely running named as a non-root user, and that user
+ does not have permission to write in /var/run. The common ways of
+ fixing this are to create a /var/run/named directory owned by the named
+ user and set pid-file to "/var/run/named/named.pid", or set pid-file to
+ "named.pid", which will put the file in the directory specified by the
+ directory option (which, in this case, must be writable by the named
+ user).
+
+Q: I can query the nameserver from the nameserver but not from other
+ machines. Why?
+
+A: This is usually the result of the firewall configuration stopping the
+ queries and / or the replies.
+
+Q: How can I make a server a slave for both an internal and an external
+ view at the same time? When I tried, both views on the slave were
+ transferred from the same view on the master.
+
+A: You will need to give the master and slave multiple IP addresses and
+ use those to make sure you reach the correct view on the other machine.
+
+ Master: 10.0.1.1 (internal), 10.0.1.2 (external, IP alias)
+ internal:
+ match-clients { !10.0.1.2; !10.0.1.4; 10.0.1/24; };
+ notify-source 10.0.1.1;
+ transfer-source 10.0.1.1;
+ query-source address 10.0.1.1;
+ external:
+ match-clients { any; };
+ recursion no; // don't offer recursion to the world
+ notify-source 10.0.1.2;
+ transfer-source 10.0.1.2;
+ query-source address 10.0.1.2;
+
+ Slave: 10.0.1.3 (internal), 10.0.1.4 (external, IP alias)
+ internal:
+ match-clients { !10.0.1.2; !10.0.1.4; 10.0.1/24; };
+ notify-source 10.0.1.3;
+ transfer-source 10.0.1.3;
+ query-source address 10.0.1.3;
+ external:
+ match-clients { any; };
+ recursion no; // don't offer recursion to the world
+ notify-source 10.0.1.4;
+ transfer-source 10.0.1.4;
+ query-source address 10.0.1.4;
+
+ You put the external address on the alias so that all the other dns
+ clients on these boxes see the internal view by default.
+
+A: BIND 9.3 and later: Use TSIG to select the appropriate view.
+
+ Master 10.0.1.1:
+ key "external" {
+ algorithm hmac-md5;
+ secret "xxxxxxxx";
+ };
+ view "internal" {
+ match-clients { !key external; 10.0.1/24; };
+ ...
+ };
+ view "external" {
+ match-clients { key external; any; };
+ server 10.0.1.2 { keys external; };
+ recursion no;
+ ...
+ };
+
+ Slave 10.0.1.2:
+ key "external" {
+ algorithm hmac-md5;
+ secret "xxxxxxxx";
+ };
+ view "internal" {
+ match-clients { !key external; 10.0.1/24; };
+ ...
+ };
+ view "external" {
+ match-clients { key external; any; };
+ server 10.0.1.1 { keys external; };
+ recursion no;
+ ...
+ };
+
+Q: I get error messages like "multiple RRs of singleton type" and "CNAME
+ and other data" when transferring a zone. What does this mean?
+
+A: These indicate a malformed master zone. You can identify the exact
+ records involved by transferring the zone using dig then running
+ named-checkzone on it.
+
+ dig axfr example.com @master-server > tmp
+ named-checkzone example.com tmp
+
+ A CNAME record cannot exist with the same name as another record except
+ for the DNSSEC records which prove its existence (NSEC).
+
+ RFC 1034, Section 3.6.2: "If a CNAME RR is present at a node, no other
+ data should be present; this ensures that the data for a canonical name
+ and its aliases cannot be different. This rule also insures that a
+ cached CNAME can be used without checking with an authoritative server
+ for other RR types."
+
+Q: I get error messages like "named.conf:99: unexpected end of input"
+ where 99 is the last line of named.conf.
+
+A: There are unbalanced quotes in named.conf.
+
+A: Some text editors (notepad and wordpad) fail to put a line title
+ indication (e.g. CR/LF) on the last line of a text file. This can be
+ fixed by "adding" a blank line to the end of the file. Named expects to
+ see EOF immediately after EOL and treats text files where this is not
+ met as truncated.
+
+Q: How do I share a dynamic zone between multiple views?
+
+A: You choose one view to be master and the second a slave and transfer
+ the zone between views.
+
+ Master 10.0.1.1:
+ key "external" {
+ algorithm hmac-md5;
+ secret "xxxxxxxx";
+ };
+
+ key "mykey" {
+ algorithm hmac-md5;
+ secret "yyyyyyyy";
+ };
+
+ view "internal" {
+ match-clients { !key external; 10.0.1/24; };
+ server 10.0.1.1 {
+ /* Deliver notify messages to external view. */
+ keys { external; };
+ };
+ zone "example.com" {
+ type master;
+ file "internal/example.db";
+ allow-update { key mykey; };
+ notify-also { 10.0.1.1; };
+ };
+ };
+
+ view "external" {
+ match-clients { key external; any; };
+ zone "example.com" {
+ type slave;
+ file "external/example.db";
+ masters { 10.0.1.1; };
+ transfer-source { 10.0.1.1; };
+ // allow-update-forwarding { any; };
+ // allow-notify { ... };
+ };
+ };
+
+Q: I get a error message like "zone wireless.ietf56.ietf.org/IN: loading
+ master file primaries/wireless.ietf56.ietf.org: no owner".
+
+A: This error is produced when a line in the master file contains leading
+ white space (tab/space) but the is no current record owner name to
+ inherit the name from. Usually this is the result of putting white
+ space before a comment, forgetting the "@" for the SOA record, or
+ indenting the master file.
+
+Q: Why are my logs in GMT (UTC).
+
+A: You are running chrooted (-t) and have not supplied local timezone
+ information in the chroot area.
+
+ FreeBSD: /etc/localtime
+ Solaris: /etc/TIMEZONE and /usr/share/lib/zoneinfo
+ OSF: /etc/zoneinfo/localtime
+
+ See also tzset(3) and zic(8).
+
+Q: I get "rndc: connect failed: connection refused" when I try to run
+ rndc.
+
+A: This is usually a configuration error.
+
+ First ensure that named is running and no errors are being reported at
+ startup (/var/log/messages or equivalent). Running "named -g <usual
+ arguments>" from a title can help at this point.
+
+ Secondly ensure that named is configured to use rndc either by
+ "rndc-confgen -a", rndc-confgen or manually. The Administrators
+ Reference manual has details on how to do this.
+
+ Old versions of rndc-confgen used localhost rather than 127.0.0.1 in /
+ etc/rndc.conf for the default server. Update /etc/rndc.conf if
+ necessary so that the default server listed in /etc/rndc.conf matches
+ the addresses used in named.conf. "localhost" has two address
+ (127.0.0.1 and ::1).
+
+ If you use "rndc-confgen -a" and named is running with -t or -u ensure
+ that /etc/rndc.conf has the correct ownership and that a copy is in the
+ chroot area. You can do this by re-running "rndc-confgen -a" with
+ appropriate -t and -u arguments.
+
+Q: I get "transfer of 'example.net/IN' from 192.168.4.12#53: failed while
+ receiving responses: permission denied" error messages.
+
+A: These indicate a filesystem permission error preventing named creating
+ / renaming the temporary file. These will usually also have other
+ associated error messages like
+
+ "dumping master file: sl/tmp-XXXX5il3sQ: open: permission denied"
+
+ Named needs write permission on the directory containing the file.
+ Named writes the new cache file to a temporary file then renames it to
+ the name specified in named.conf to ensure that the contents are always
+ complete. This is to prevent named loading a partial zone in the event
+ of power failure or similar interrupting the write of the master file.
+
+ Note file names are relative to the directory specified in options and
+ any chroot directory ([<chroot dir>/][<options dir>]).
+
+ If named is invoked as "named -t /chroot/DNS" with the following
+ named.conf then "/chroot/DNS/var/named/sl" needs to be writable by the
+ user named is running as.
+
+ options {
+ directory "/var/named";
+ };
+
+ zone "example.net" {
+ type slave;
+ file "sl/example.net";
+ masters { 192.168.4.12; };
+ };
+
+Q: I want to forward all DNS queries from my caching nameserver to another
+ server. But there are some domains which have to be served locally, via
+ rbldnsd.
+
+ How do I achieve this ?
+
+A: options {
+ forward only;
+ forwarders { <ip.of.primary.nameserver>; };
+ };
+
+ zone "sbl-xbl.spamhaus.org" {
+ type forward; forward only;
+ forwarders { <ip.of.rbldns.server> port 530; };
+ };
+
+ zone "list.dsbl.org" {
+ type forward; forward only;
+ forwarders { <ip.of.rbldns.server> port 530; };
+ };
+
+
+Q: Can you help me understand how BIND 9 uses memory to store DNS zones?
+
+ Some times it seems to take several times the amount of memory it needs
+ to store the zone.
+
+A: When reloading a zone named my have multiple copies of the zone in
+ memory at one time. The zone it is serving and the one it is loading.
+ If reloads are ultra fast it can have more still.
+
+ e.g. Ones that are transferring out, the one that it is serving and the
+ one that is loading.
+
+ BIND 8 destroyed the zone before loading and also killed off outgoing
+ transfers of the zone.
+
+ The new strategy allows slaves to get copies of the new zone regardless
+ of how often the master is loaded compared to the transfer time. The
+ slave might skip some intermediate versions but the transfers will
+ complete and it will keep reasonably in sync with the master.
+
+ The new strategy also allows the master to recover from syntax and
+ other errors in the master file as it still has an in-core copy of the
+ old contents.
+
+Q: I want to use IPv6 locally but I don't have a external IPv6 connection.
+ External lookups are slow.
+
+A: You can use server clauses to stop named making external lookups over
+ IPv6.
+
+ server fd81:ec6c:bd62::/48 { bogus no; }; // site ULA prefix
+ server ::/0 { bogus yes; };
+
+3. Operations Questions
+
+Q: How to change the nameservers for a zone?
+
+A: Step 1: Ensure all nameservers, new and old, are serving the same zone
+ content.
+
+ Step 2: Work out the maximum TTL of the NS RRset in the parent and
+ child zones. This is the time it will take caches to be clear of a
+ particular version of the NS RRset. If you are just removing
+ nameservers you can skip to Step 6.
+
+ Step 3: Add new nameservers to the NS RRset for the zone and wait until
+ all the servers for the zone are answering with this new NS RRset.
+
+ Step 4: Inform the parent zone of the new NS RRset then wait for all
+ the parent servers to be answering with the new NS RRset.
+
+ Step 5: Wait for cache to be clear of the old NS RRset. See Step 2 for
+ how long. If you are just adding nameservers you are done.
+
+ Step 6: Remove any old nameservers from the zones NS RRset and wait for
+ all the servers for the zone to be serving the new NS RRset.
+
+ Step 7: Inform the parent zone of the new NS RRset then wait for all
+ the parent servers to be answering with the new NS RRset.
+
+ Step 8: Wait for cache to be clear of the old NS RRset. See Step 2 for
+ how long.
+
+ Step 9: Turn off the old nameservers or remove the zone entry from the
+ configuration of the old nameservers.
+
+ Step 10: Increment the serial number and wait for the change to be
+ visible in all nameservers for the zone. This ensures that zone
+ transfers are still working after the old servers are decommissioned.
+
+ Note: the above procedure is designed to be transparent to dns clients.
+ Decommissioning the old servers too early will result in some clients
+ not being able to look up answers in the zone.
+
+ Note: while it is possible to run the addition and removal stages
+ together it is not recommended.
+
+4. General Questions
+
+Q: I keep getting log messages like the following. Why?
+
+ Dec 4 23:47:59 client 10.0.0.1#1355: updating zone 'example.com/IN':
+ update failed: 'RRset exists (value dependent)' prerequisite not
+ satisfied (NXRRSET)
+
+A: DNS updates allow the update request to test to see if certain
+ conditions are met prior to proceeding with the update. The message
+ above is saying that conditions were not met and the update is not
+ proceeding. See doc/rfc/rfc2136.txt for more details on prerequisites.
+
+Q: I keep getting log messages like the following. Why?
+
+ Jun 21 12:00:00.000 client 10.0.0.1#1234: update denied
+
+A: Someone is trying to update your DNS data using the RFC2136 Dynamic
+ Update protocol. Windows 2000 machines have a habit of sending dynamic
+ update requests to DNS servers without being specifically configured to
+ do so. If the update requests are coming from a Windows 2000 machine,
+ see <http://support.microsoft.com/support/kb/articles/q246/8/04.asp>
+ for information about how to turn them off.
+
+Q: When I do a "dig . ns", many of the A records for the root servers are
+ missing. Why?
+
+A: This is normal and harmless. It is a somewhat confusing side effect of
+ the way BIND 9 does RFC2181 trust ranking and of the efforts BIND 9
+ makes to avoid promoting glue into answers.
+
+ When BIND 9 first starts up and primes its cache, it receives the root
+ server addresses as additional data in an authoritative response from a
+ root server, and these records are eligible for inclusion as additional
+ data in responses. Subsequently it receives a subset of the root server
+ addresses as additional data in a non-authoritative (referral) response
+ from a root server. This causes the addresses to now be considered
+ non-authoritative (glue) data, which is not eligible for inclusion in
+ responses.
+
+ The server does have a complete set of root server addresses cached at
+ all times, it just may not include all of them as additional data,
+ depending on whether they were last received as answers or as glue. You
+ can always look up the addresses with explicit queries like "dig
+ a.root-servers.net A".
+
+Q: Why don't my zones reload when I do an "rndc reload" or SIGHUP?
+
+A: A zone can be updated either by editing zone files and reloading the
+ server or by dynamic update, but not both. If you have enabled dynamic
+ update for a zone using the "allow-update" option, you are not supposed
+ to edit the zone file by hand, and the server will not attempt to
+ reload it.
+
+Q: Why is named listening on UDP port other than 53?
+
+A: Named uses a system selected port to make queries of other nameservers.
+ This behaviour can be overridden by using query-source to lock down the
+ port and/or address. See also notify-source and transfer-source.
+
+Q: I get warning messages like "zone example.com/IN: refresh: failure
+ trying master 1.2.3.4#53: timed out".
+
+A: Check that you can make UDP queries from the slave to the master
+
+ dig +norec example.com soa @1.2.3.4
+
+ You could be generating queries faster than the slave can cope with.
+ Lower the serial query rate.
+
+ serial-query-rate 5; // default 20
+
+Q: I don't get RRSIG's returned when I use "dig +dnssec".
+
+A: You need to ensure DNSSEC is enabled (dnssec-enable yes;).
+
+Q: Can a NS record refer to a CNAME.
+
+A: No. The rules for glue (copies of the *address* records in the parent
+ zones) and additional section processing do not allow it to work.
+
+ You would have to add both the CNAME and address records (A/AAAA) as
+ glue to the parent zone and have CNAMEs be followed when doing
+ additional section processing to make it work. No nameserver
+ implementation supports either of these requirements.
+
+Q: What does "RFC 1918 response from Internet for 0.0.0.10.IN-ADDR.ARPA"
+ mean?
+
+A: If the IN-ADDR.ARPA name covered refers to a internal address space you
+ are using then you have failed to follow RFC 1918 usage rules and are
+ leaking queries to the Internet. You should establish your own zones
+ for these addresses to prevent you querying the Internet's name servers
+ for these addresses. Please see <http://as112.net/> for details of the
+ problems you are causing and the counter measures that have had to be
+ deployed.
+
+ If you are not using these private addresses then a client has queried
+ for them. You can just ignore the messages, get the offending client to
+ stop sending you these messages as they are most probably leaking them
+ or setup your own zones empty zones to serve answers to these queries.
+
+ zone "10.IN-ADDR.ARPA" {
+ type master;
+ file "empty";
+ };
+
+ zone "16.172.IN-ADDR.ARPA" {
+ type master;
+ file "empty";
+ };
+
+ ...
+
+ zone "31.172.IN-ADDR.ARPA" {
+ type master;
+ file "empty";
+ };
+
+ zone "168.192.IN-ADDR.ARPA" {
+ type master;
+ file "empty";
+ };
+
+ empty:
+ @ 10800 IN SOA <name-of-server>. <contact-email>. (
+ 1 3600 1200 604800 10800 )
+ @ 10800 IN NS <name-of-server>.
+
+ Note
+
+ Future versions of named are likely to do this automatically.
+
+Q: Will named be affected by the 2007 changes to daylight savings rules in
+ the US.
+
+A: No, so long as the machines internal clock (as reported by "date -u")
+ remains at UTC. The only visible change if you fail to upgrade your OS,
+ if you are in a affected area, will be that log messages will be a hour
+ out during the period where the old rules do not match the new rules.
+
+ For most OS's this change just means that you need to update the
+ conversion rules from UTC to local time. Normally this involves
+ updating a file in /etc (which sets the default timezone for the
+ machine) and possibly a directory which has all the conversion rules
+ for the world (e.g. /usr/share/zoneinfo). When updating the OS do not
+ forget to update any chroot areas as well. See your OS's documentation
+ for more details.
+
+ The local timezone conversion rules can also be done on a individual
+ basis by setting the TZ environment variable appropriately. See your
+ OS's documentation for more details.
+
+Q: Is there a bugzilla (or other tool) database that mere mortals can have
+ (read-only) access to for bind?
+
+A: No. The BIND 9 bug database is kept closed for a number of reasons.
+ These include, but are not limited to, that the database contains
+ proprietory information from people reporting bugs. The database has in
+ the past and may in future contain unfixed bugs which are capable of
+ bringing down most of the Internet's DNS infrastructure.
+
+ The release pages for each version contain up to date lists of bugs
+ that have been fixed post release. That is as close as we can get to
+ providing a bug database.
+
+Q: Why do queries for NSEC3 records fail to return the NSEC3 record?
+
+A: NSEC3 records are strictly meta data and can only be returned in the
+ authority section. This is done so that signing the zone using NSEC3
+ records does not bring names into existance that do not exist in the
+ unsigned version of the zone.
+
+5. Operating-System Specific Questions
+
+5.1. HPUX
+
+Q: I get the following error trying to configure BIND:
+
+ checking if unistd.h or sys/types.h defines fd_set... no
+ configure: error: need either working unistd.h or sys/select.h
+
+A: You have attempted to configure BIND with the bundled C compiler. This
+ compiler does not meet the minimum compiler requirements to for
+ building BIND. You need to install a ANSI C compiler and / or teach
+ configure how to find the ANSI C compiler. The later can be done by
+ adjusting the PATH environment variable and / or specifying the
+ compiler via CC.
+
+ ./configure CC=<compiler> ...
+
+5.2. Linux
+
+Q: Why do I get the following errors:
+
+ general: errno2result.c:109: unexpected error:
+ general: unable to convert errno to isc_result: 14: Bad address
+ client: UDP client handler shutting down due to fatal receive error: unexpected error
+
+A: This is the result of a Linux kernel bug.
+
+ See: <http://marc.theaimsgroup.com/?l=linux-netdev&m=113081708031466&w=
+ 2>
+
+Q: Why does named lock up when it attempts to connect over IPSEC tunnels?
+
+A: This is due to a kernel bug where the fact that a socket is marked
+ non-blocking is ignored. It is reported that setting xfrm_larval_drop
+ to 1 helps but this may have negative side effects. See: <https://
+ bugzilla.redhat.com/show_bug.cgi?id=427629> and <http://lkml.org/lkml/
+ 2007/12/4/260>.
+
+ xfrm_larval_drop can be set to 1 by the following procedure:
+
+ echo "1" > proc/sys/net/core/xfrm_larval_drop
+
+Q: Why do I see 5 (or more) copies of named on Linux?
+
+A: Linux threads each show up as a process under ps. The approximate
+ number of threads running is n+4, where n is the number of CPUs. Note
+ that the amount of memory used is not cumulative; if each process is
+ using 10M of memory, only a total of 10M is used.
+
+ Newer versions of Linux's ps command hide the individual threads and
+ require -L to display them.
+
+Q: Why does BIND 9 log "permission denied" errors accessing its
+ configuration files or zones on my Linux system even though it is
+ running as root?
+
+A: On Linux, BIND 9 drops most of its root privileges on startup. This
+ including the privilege to open files owned by other users. Therefore,
+ if the server is running as root, the configuration files and zone
+ files should also be owned by root.
+
+Q: I get the error message "named: capset failed: Operation not permitted"
+ when starting named.
+
+A: The capability module, part of "Linux Security Modules/LSM", has not
+ been loaded into the kernel. See insmod(8), modprobe(8).
+
+ The relevant modules can be loaded by running:
+
+ modprobe commoncap
+ modprobe capability
+
+Q: I'm running BIND on Red Hat Enterprise Linux or Fedora Core -
+
+ Why can't named update slave zone database files?
+
+ Why can't named create DDNS journal files or update the master zones
+ from journals?
+
+ Why can't named create custom log files?
+
+A: Red Hat Security Enhanced Linux (SELinux) policy security protections :
+
+ Red Hat have adopted the National Security Agency's SELinux security
+ policy (see <http://www.nsa.gov/selinux>) and recommendations for BIND
+ security , which are more secure than running named in a chroot and
+ make use of the bind-chroot environment unnecessary .
+
+ By default, named is not allowed by the SELinux policy to write, create
+ or delete any files EXCEPT in these directories:
+
+ $ROOTDIR/var/named/slaves
+ $ROOTDIR/var/named/data
+ $ROOTDIR/var/tmp
+
+
+ where $ROOTDIR may be set in /etc/sysconfig/named if bind-chroot is
+ installed.
+
+ The SELinux policy particularly does NOT allow named to modify the
+ $ROOTDIR/var/named directory, the default location for master zone
+ database files.
+
+ SELinux policy overrules file access permissions - so even if all the
+ files under /var/named have ownership named:named and mode rw-rw-r--,
+ named will still not be able to write or create files except in the
+ directories above, with SELinux in Enforcing mode.
+
+ So, to allow named to update slave or DDNS zone files, it is best to
+ locate them in $ROOTDIR/var/named/slaves, with named.conf zone
+ statements such as:
+
+ zone "slave.zone." IN {
+ type slave;
+ file "slaves/slave.zone.db";
+ ...
+ };
+ zone "ddns.zone." IN {
+ type master;
+ allow-updates {...};
+ file "slaves/ddns.zone.db";
+ };
+
+
+ To allow named to create its cache dump and statistics files, for
+ example, you could use named.conf options statements such as:
+
+ options {
+ ...
+ dump-file "/var/named/data/cache_dump.db";
+ statistics-file "/var/named/data/named_stats.txt";
+ ...
+ };
+
+
+ You can also tell SELinux to allow named to update any zone database
+ files, by setting the SELinux tunable boolean parameter
+ 'named_write_master_zones=1', using the system-config-securitylevel
+ GUI, using the 'setsebool' command, or in /etc/selinux/targeted/
+ booleans.
+
+ You can disable SELinux protection for named entirely by setting the
+ 'named_disable_trans=1' SELinux tunable boolean parameter.
+
+ The SELinux named policy defines these SELinux contexts for named:
+
+ named_zone_t : for zone database files - $ROOTDIR/var/named/*
+ named_conf_t : for named configuration files - $ROOTDIR/etc/{named,rndc}.*
+ named_cache_t: for files modifiable by named - $ROOTDIR/var/{tmp,named/{slaves,data}}
+
+
+ If you want to retain use of the SELinux policy for named, and put
+ named files in different locations, you can do so by changing the
+ context of the custom file locations .
+
+ To create a custom configuration file location, e.g. '/root/
+ named.conf', to use with the 'named -c' option, do:
+
+ # chcon system_u:object_r:named_conf_t /root/named.conf
+
+
+ To create a custom modifiable named data location, e.g. '/var/log/
+ named' for a log file, do:
+
+ # chcon system_u:object_r:named_cache_t /var/log/named
+
+
+ To create a custom zone file location, e.g. /root/zones/, do:
+
+ # chcon system_u:object_r:named_zone_t /root/zones/{.,*}
+
+
+ See these man-pages for more information : selinux(8), named_selinux
+ (8), chcon(1), setsebool(8)
+
+Q: Listening on individual IPv6 interfaces does not work.
+
+A: This is usually due to "/proc/net/if_inet6" not being available in the
+ chroot file system. Mount another instance of "proc" in the chroot file
+ system.
+
+ This can be be made permanent by adding a second instance to /etc/
+ fstab.
+
+ proc /proc proc defaults 0 0
+ proc /var/named/proc proc defaults 0 0
+
+5.3. Windows
+
+Q: Zone transfers from my BIND 9 master to my Windows 2000 slave fail.
+ Why?
+
+A: This may be caused by a bug in the Windows 2000 DNS server where DNS
+ messages larger than 16K are not handled properly. This can be worked
+ around by setting the option "transfer-format one-answer;". Also check
+ whether your zone contains domain names with embedded spaces or other
+ special characters, like "John\032Doe\213s\032Computer", since such
+ names have been known to cause Windows 2000 slaves to incorrectly
+ reject the zone.
+
+Q: I get "Error 1067" when starting named under Windows.
+
+A: This is the service manager saying that named exited. You need to
+ examine the Application log in the EventViewer to find out why.
+
+ Common causes are that you failed to create "named.conf" (usually "C:\
+ windows\dns\etc\named.conf") or failed to specify the directory in
+ named.conf.
+
+ options {
+ Directory "C:\windows\dns\etc";
+ };
+
+5.4. FreeBSD
+
+Q: I have FreeBSD 4.x and "rndc-confgen -a" just sits there.
+
+A: /dev/random is not configured. Use rndcontrol(8) to tell the kernel to
+ use certain interrupts as a source of random events. You can make this
+ permanent by setting rand_irqs in /etc/rc.conf.
+
+ /etc/rc.conf
+ rand_irqs="3 14 15"
+
+ See also <http://people.freebsd.org/~dougb/randomness.html>.
+
+5.5. Solaris
+
+Q: How do I integrate BIND 9 and Solaris SMF
+
+A: Sun has a blog entry describing how to do this.
+
+ <http://blogs.sun.com/roller/page/anay/Weblog?catname=%2FSolaris>
+
+5.6. Apple Mac OS X
+
+Q: How do I run BIND 9 on Apple Mac OS X?
+
+A: If you run Tiger(Mac OS 10.4) or later then this is all you need to do:
+
+ % sudo rndc-confgen > /etc/rndc.conf
+
+ Copy the key statement from /etc/rndc.conf into /etc/rndc.key, e.g.:
+
+ key "rndc-key" {
+ algorithm hmac-md5;
+ secret "uvceheVuqf17ZwIcTydddw==";
+ };
+
+ Then start the relevant service:
+
+ % sudo service org.isc.named start
+
+ This is persistent upon a reboot, so you will have to do it only once.
+
+A: Alternatively you can just generate /etc/rndc.key by running:
+
+ % sudo rndc-confgen -a
+
+ Then start the relevant service:
+
+ % sudo service org.isc.named start
+
+ Named will look for /etc/rndc.key when it starts if it doesn't have a
+ controls section or the existing controls are missing keys sub-clauses.
+ This is persistent upon a reboot, so you will have to do it only once.
+
diff --git a/FAQ.xml b/FAQ.xml
new file mode 100644
index 0000000..44de005
--- /dev/null
+++ b/FAQ.xml
@@ -0,0 +1,1576 @@
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" []>
+<!--
+ - 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
+ - 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: FAQ.xml,v 1.46 2008/09/09 05:42:17 marka Exp $ -->
+
+<article class="faq">
+ <title>Frequently Asked Questions about BIND 9</title>
+ <articleinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </articleinfo>
+ <qandaset defaultlabel='qanda'>
+
+ <qandadiv><title>Compilation and Installation Questions</title>
+
+ <qandaentry>
+ <question>
+ <para>
+ I'm trying to compile BIND 9, and "make" is failing due to
+ files not being found. Why?
+ </para>
+ </question>
+ <answer>
+ <para>
+ Using a parallel or distributed "make" to build BIND 9 is
+ not supported, and doesn't work. If you are using one of
+ these, use normal make or gmake instead.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Isn't "make install" supposed to generate a default named.conf?
+ </para>
+ </question>
+ <answer>
+ <para>
+ Short Answer: No.
+ </para>
+ <para>
+ Long Answer: There really isn't a default configuration which fits
+ any site perfectly. There are lots of decisions that need to
+ be made and there is no consensus on what the defaults should be.
+ For example FreeBSD uses /etc/namedb as the location where the
+ configuration files for named are stored. Others use /var/named.
+ </para>
+ <para>
+ What addresses to listen on? For a laptop on the move a lot
+ you may only want to listen on the loop back interfaces.
+ </para>
+ <para>
+ Who do you offer recursive service to? Is there are firewall
+ to consider? If so is it stateless or stateful. Are you
+ directly on the Internet? Are you on a private network? Are
+ you on a NAT'd network? The answers
+ to all these questions change how you configure even a
+ caching name server.
+ </para>
+ </answer>
+ </qandaentry>
+
+ </qandadiv> <!-- Compilation and Installation Questions -->
+
+ <qandadiv><title>Configuration and Setup Questions</title>
+
+ <qandaentry>
+ <!-- configuration, log -->
+ <question>
+ <para>
+ Why does named log the warning message <quote>no TTL specified -
+ using SOA MINTTL instead</quote>?
+ </para>
+ </question>
+ <answer>
+ <para>
+ Your zone file is illegal according to RFC1035. It must either
+ have a line like:
+ </para>
+ <informalexample>
+ <programlisting>
+$TTL 86400</programlisting>
+ </informalexample>
+ <para>
+ at the beginning, or the first record in it must have a TTL field,
+ like the "84600" in this example:
+ </para>
+ <informalexample>
+ <programlisting>
+example.com. 86400 IN SOA ns hostmaster ( 1 3600 1800 1814400 3600 )</programlisting>
+ </informalexample>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <!-- configuration -->
+ <question>
+ <para>
+ Why do I get errors like <quote>dns_zone_load: zone foo/IN: loading
+ master file bar: ran out of space</quote>?
+ </para>
+ </question>
+ <answer>
+ <para>
+ This is often caused by TXT records with missing close
+ quotes. Check that all TXT records containing quoted strings
+ have both open and close quotes.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <!-- security -->
+ <question>
+ <para>
+ How do I restrict people from looking up the server version?
+ </para>
+ </question>
+ <answer>
+ <para>
+ Put a "version" option containing something other than the
+ real version in the "options" section of named.conf. Note
+ doing this will not prevent attacks and may impede people
+ trying to diagnose problems with your server. Also it is
+ possible to "fingerprint" nameservers to determine their
+ version.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <!-- security -->
+ <question>
+ <para>
+ How do I restrict only remote users from looking up the
+ server version?
+ </para>
+ </question>
+ <answer>
+ <para>
+ The following view statement will intercept lookups as the
+ internal view that holds the version information will be
+ matched last. The caveats of the previous answer still
+ apply, of course.
+ </para>
+ <informalexample>
+ <programlisting>
+view "chaos" chaos {
+ match-clients { &lt;those to be refused&gt;; };
+ allow-query { none; };
+ zone "." {
+ type hint;
+ file "/dev/null"; // or any empty file
+ };
+};</programlisting>
+ </informalexample>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <!-- configuration -->
+ <question>
+ <para>
+ What do <quote>no source of entropy found</quote> or <quote>could not
+ open entropy source foo</quote> mean?
+ </para>
+ </question>
+ <answer>
+ <para>
+ The server requires a source of entropy to perform certain
+ operations, mostly DNSSEC related. These messages indicate
+ that you have no source of entropy. On systems with
+ /dev/random or an equivalent, it is used by default. A
+ source of entropy can also be defined using the random-device
+ option in named.conf.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <!-- configuration -->
+ <question>
+ <para>
+ I'm trying to use TSIG to authenticate dynamic updates or
+ zone transfers. I'm sure I have the keys set up correctly,
+ but the server is rejecting the TSIG. Why?
+ </para>
+ </question>
+ <answer>
+ <para>
+ This may be a clock skew problem. Check that the the clocks
+ on the client and server are properly synchronised (e.g.,
+ using ntp).
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I see a log message like the following. Why?
+ </para>
+ <para>
+ couldn't open pid file '/var/run/named.pid': Permission denied
+ </para>
+ </question>
+ <answer>
+ <para>
+ You are most likely running named as a non-root user, and
+ that user does not have permission to write in /var/run.
+ The common ways of fixing this are to create a /var/run/named
+ directory owned by the named user and set pid-file to
+ "/var/run/named/named.pid", or set pid-file to "named.pid",
+ which will put the file in the directory specified by the
+ directory option (which, in this case, must be writable by
+ the named user).
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I can query the nameserver from the nameserver but not from other
+ machines. Why?
+ </para>
+ </question>
+ <answer>
+ <para>
+ This is usually the result of the firewall configuration stopping
+ the queries and / or the replies.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ How can I make a server a slave for both an internal and
+ an external view at the same time? When I tried, both views
+ on the slave were transferred from the same view on the master.
+ </para>
+ </question>
+ <answer>
+ <para>
+ You will need to give the master and slave multiple IP
+ addresses and use those to make sure you reach the correct
+ view on the other machine.
+ </para>
+ <informalexample>
+ <programlisting>
+Master: 10.0.1.1 (internal), 10.0.1.2 (external, IP alias)
+ internal:
+ match-clients { !10.0.1.2; !10.0.1.4; 10.0.1/24; };
+ notify-source 10.0.1.1;
+ transfer-source 10.0.1.1;
+ query-source address 10.0.1.1;
+ external:
+ match-clients { any; };
+ recursion no; // don't offer recursion to the world
+ notify-source 10.0.1.2;
+ transfer-source 10.0.1.2;
+ query-source address 10.0.1.2;
+
+Slave: 10.0.1.3 (internal), 10.0.1.4 (external, IP alias)
+ internal:
+ match-clients { !10.0.1.2; !10.0.1.4; 10.0.1/24; };
+ notify-source 10.0.1.3;
+ transfer-source 10.0.1.3;
+ query-source address 10.0.1.3;
+ external:
+ match-clients { any; };
+ recursion no; // don't offer recursion to the world
+ notify-source 10.0.1.4;
+ transfer-source 10.0.1.4;
+ query-source address 10.0.1.4;</programlisting>
+ </informalexample>
+ <para>
+ You put the external address on the alias so that all the other
+ dns clients on these boxes see the internal view by default.
+ </para>
+ </answer>
+ <answer>
+ <para>
+ BIND 9.3 and later: Use TSIG to select the appropriate view.
+ </para>
+ <informalexample>
+ <programlisting>
+Master 10.0.1.1:
+ key "external" {
+ algorithm hmac-md5;
+ secret "xxxxxxxx";
+ };
+ view "internal" {
+ match-clients { !key external; 10.0.1/24; };
+ ...
+ };
+ view "external" {
+ match-clients { key external; any; };
+ server 10.0.1.2 { keys external; };
+ recursion no;
+ ...
+ };
+
+Slave 10.0.1.2:
+ key "external" {
+ algorithm hmac-md5;
+ secret "xxxxxxxx";
+ };
+ view "internal" {
+ match-clients { !key external; 10.0.1/24; };
+ ...
+ };
+ view "external" {
+ match-clients { key external; any; };
+ server 10.0.1.1 { keys external; };
+ recursion no;
+ ...
+ };</programlisting>
+ </informalexample>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I get error messages like <quote>multiple RRs of singleton type</quote>
+ and <quote>CNAME and other data</quote> when transferring a zone. What
+ does this mean?
+ </para>
+ </question>
+ <answer>
+ <para>
+ These indicate a malformed master zone. You can identify
+ the exact records involved by transferring the zone using
+ dig then running named-checkzone on it.
+ </para>
+ <informalexample>
+ <programlisting>
+dig axfr example.com @master-server &gt; tmp
+named-checkzone example.com tmp</programlisting>
+ </informalexample>
+ <para>
+ A CNAME record cannot exist with the same name as another record
+ except for the DNSSEC records which prove its existence (NSEC).
+ </para>
+ <para>
+ RFC 1034, Section 3.6.2: <quote>If a CNAME RR is present at a node,
+ no other data should be present; this ensures that the data for a
+ canonical name and its aliases cannot be different. This rule also
+ insures that a cached CNAME can be used without checking with an
+ authoritative server for other RR types.</quote>
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I get error messages like <quote>named.conf:99: unexpected end
+ of input</quote> where 99 is the last line of named.conf.
+ </para>
+ </question>
+ <answer>
+ <para>
+ There are unbalanced quotes in named.conf.
+ </para>
+ </answer>
+ <answer>
+ <para>
+ Some text editors (notepad and wordpad) fail to put a line
+ title indication (e.g. CR/LF) on the last line of a
+ text file. This can be fixed by "adding" a blank line to
+ the end of the file. Named expects to see EOF immediately
+ after EOL and treats text files where this is not met as
+ truncated.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ How do I share a dynamic zone between multiple views?
+ </para>
+ </question>
+ <answer>
+ <para>
+ You choose one view to be master and the second a slave and
+ transfer the zone between views.
+ </para>
+ <informalexample>
+ <programlisting>
+Master 10.0.1.1:
+ key "external" {
+ algorithm hmac-md5;
+ secret "xxxxxxxx";
+ };
+
+ key "mykey" {
+ algorithm hmac-md5;
+ secret "yyyyyyyy";
+ };
+
+ view "internal" {
+ match-clients { !key external; 10.0.1/24; };
+ server 10.0.1.1 {
+ /* Deliver notify messages to external view. */
+ keys { external; };
+ };
+ zone "example.com" {
+ type master;
+ file "internal/example.db";
+ allow-update { key mykey; };
+ notify-also { 10.0.1.1; };
+ };
+ };
+
+ view "external" {
+ match-clients { key external; any; };
+ zone "example.com" {
+ type slave;
+ file "external/example.db";
+ masters { 10.0.1.1; };
+ transfer-source { 10.0.1.1; };
+ // allow-update-forwarding { any; };
+ // allow-notify { ... };
+ };
+ };</programlisting>
+ </informalexample>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I get a error message like <quote>zone wireless.ietf56.ietf.org/IN:
+ loading master file primaries/wireless.ietf56.ietf.org: no
+ owner</quote>.
+ </para>
+ </question>
+ <answer>
+ <para>
+ This error is produced when a line in the master file
+ contains leading white space (tab/space) but the is no
+ current record owner name to inherit the name from. Usually
+ this is the result of putting white space before a comment,
+ forgetting the "@" for the SOA record, or indenting the master
+ file.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Why are my logs in GMT (UTC).
+ </para>
+ </question>
+ <answer>
+ <para>
+ You are running chrooted (-t) and have not supplied local timezone
+ information in the chroot area.
+ </para>
+ <simplelist>
+ <member>FreeBSD: /etc/localtime</member>
+ <member>Solaris: /etc/TIMEZONE and /usr/share/lib/zoneinfo</member>
+ <member>OSF: /etc/zoneinfo/localtime</member>
+ </simplelist>
+ <para>
+ See also tzset(3) and zic(8).
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I get <quote>rndc: connect failed: connection refused</quote> when
+ I try to run rndc.
+ </para>
+ </question>
+ <answer>
+ <para>
+ This is usually a configuration error.
+ </para>
+ <para>
+ First ensure that named is running and no errors are being
+ reported at startup (/var/log/messages or equivalent).
+ Running "named -g &lt;usual arguments&gt;" from a title
+ can help at this point.
+ </para>
+ <para>
+ Secondly ensure that named is configured to use rndc either
+ by "rndc-confgen -a", rndc-confgen or manually. The
+ Administrators Reference manual has details on how to do
+ this.
+ </para>
+ <para>
+ Old versions of rndc-confgen used localhost rather than
+ 127.0.0.1 in /etc/rndc.conf for the default server. Update
+ /etc/rndc.conf if necessary so that the default server
+ listed in /etc/rndc.conf matches the addresses used in
+ named.conf. "localhost" has two address (127.0.0.1 and
+ ::1).
+ </para>
+ <para>
+ If you use "rndc-confgen -a" and named is running with -t or -u
+ ensure that /etc/rndc.conf has the correct ownership and that
+ a copy is in the chroot area. You can do this by re-running
+ "rndc-confgen -a" with appropriate -t and -u arguments.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I get <quote>transfer of 'example.net/IN' from 192.168.4.12#53:
+ failed while receiving responses: permission denied</quote> error
+ messages.
+ </para>
+ </question>
+ <answer>
+ <para>
+ These indicate a filesystem permission error preventing
+ named creating / renaming the temporary file. These will
+ usually also have other associated error messages like
+ </para>
+ <informalexample>
+ <programlisting>
+"dumping master file: sl/tmp-XXXX5il3sQ: open: permission denied"</programlisting>
+ </informalexample>
+ <para>
+ Named needs write permission on the directory containing
+ the file. Named writes the new cache file to a temporary
+ file then renames it to the name specified in named.conf
+ to ensure that the contents are always complete. This is
+ to prevent named loading a partial zone in the event of
+ power failure or similar interrupting the write of the
+ master file.
+ </para>
+ <para>
+ Note file names are relative to the directory specified in
+ options and any chroot directory ([&lt;chroot
+ dir&gt;/][&lt;options dir&gt;]).
+ </para>
+ <informalexample>
+ <para>
+ If named is invoked as "named -t /chroot/DNS" with
+ the following named.conf then "/chroot/DNS/var/named/sl"
+ needs to be writable by the user named is running as.
+ </para>
+ <programlisting>
+options {
+ directory "/var/named";
+};
+
+zone "example.net" {
+ type slave;
+ file "sl/example.net";
+ masters { 192.168.4.12; };
+};</programlisting>
+ </informalexample>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I want to forward all DNS queries from my caching nameserver to
+ another server. But there are some domains which have to be
+ served locally, via rbldnsd.
+ </para>
+ <para>
+ How do I achieve this ?
+ </para>
+ </question>
+ <answer>
+ <programlisting>
+options {
+ forward only;
+ forwarders { &lt;ip.of.primary.nameserver&gt;; };
+};
+
+zone "sbl-xbl.spamhaus.org" {
+ type forward; forward only;
+ forwarders { &lt;ip.of.rbldns.server&gt; port 530; };
+};
+
+zone "list.dsbl.org" {
+ type forward; forward only;
+ forwarders { &lt;ip.of.rbldns.server&gt; port 530; };
+};
+ </programlisting>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Can you help me understand how BIND 9 uses memory to store
+ DNS zones?
+ </para>
+ <para>
+ Some times it seems to take several times the amount of
+ memory it needs to store the zone.
+ </para>
+ </question>
+ <answer>
+ <para>
+ When reloading a zone named my have multiple copies of
+ the zone in memory at one time. The zone it is serving
+ and the one it is loading. If reloads are ultra fast it
+ can have more still.
+ </para>
+ <para>
+ e.g. Ones that are transferring out, the one that it is
+ serving and the one that is loading.
+ </para>
+ <para>
+ BIND 8 destroyed the zone before loading and also killed
+ off outgoing transfers of the zone.
+ </para>
+ <para>
+ The new strategy allows slaves to get copies of the new
+ zone regardless of how often the master is loaded compared
+ to the transfer time. The slave might skip some intermediate
+ versions but the transfers will complete and it will keep
+ reasonably in sync with the master.
+ </para>
+ <para>
+ The new strategy also allows the master to recover from
+ syntax and other errors in the master file as it still
+ has an in-core copy of the old contents.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I want to use IPv6 locally but I don't have a external IPv6
+ connection. External lookups are slow.
+ </para>
+ </question>
+ <answer>
+ <para>
+ You can use server clauses to stop named making external lookups
+ over IPv6.
+ </para>
+ <programlisting>
+server fd81:ec6c:bd62::/48 { bogus no; }; // site ULA prefix
+server ::/0 { bogus yes; };
+</programlisting>
+ </answer>
+ </qandaentry>
+
+ </qandadiv> <!-- Configuration and Setup Questions -->
+
+ <qandadiv><title>Operations Questions</title>
+
+ <qandaentry>
+ <question>
+ <para>
+ How to change the nameservers for a zone?
+ </para>
+ </question>
+ <answer>
+ <para>
+ Step 1: Ensure all nameservers, new and old, are serving the
+ same zone content.
+ </para>
+ <para>
+ Step 2: Work out the maximum TTL of the NS RRset in the parent and child
+ zones. This is the time it will take caches to be clear of a
+ particular version of the NS RRset.
+ If you are just removing nameservers you can skip to Step 6.
+ </para>
+ <para>
+ Step 3: Add new nameservers to the NS RRset for the zone and
+ wait until all the servers for the zone are answering with this
+ new NS RRset.
+ </para>
+ <para>
+ Step 4: Inform the parent zone of the new NS RRset then wait for all the
+ parent servers to be answering with the new NS RRset.
+ </para>
+ <para>
+ Step 5: Wait for cache to be clear of the old NS RRset.
+ See Step 2 for how long.
+ If you are just adding nameservers you are done.
+ </para>
+ <para>
+ Step 6: Remove any old nameservers from the zones NS RRset and
+ wait for all the servers for the zone to be serving the new NS RRset.
+ </para>
+ <para>
+ Step 7: Inform the parent zone of the new NS RRset then wait for all the
+ parent servers to be answering with the new NS RRset.
+ </para>
+ <para>
+ Step 8: Wait for cache to be clear of the old NS RRset.
+ See Step 2 for how long.
+ </para>
+ <para>
+ Step 9: Turn off the old nameservers or remove the zone entry from
+ the configuration of the old nameservers.
+ </para>
+ <para>
+ Step 10: Increment the serial number and wait for the change to
+ be visible in all nameservers for the zone. This ensures that
+ zone transfers are still working after the old servers are
+ decommissioned.
+ </para>
+ <para>
+ Note: the above procedure is designed to be transparent
+ to dns clients. Decommissioning the old servers too early
+ will result in some clients not being able to look up
+ answers in the zone.
+ </para>
+ <para>
+ Note: while it is possible to run the addition and removal
+ stages together it is not recommended.
+ </para>
+ </answer>
+ </qandaentry>
+
+ </qandadiv> <!-- Operations Questions -->
+
+ <qandadiv><title>General Questions</title>
+
+ <qandaentry>
+ <question>
+ <para>
+ I keep getting log messages like the following. Why?
+ </para>
+ <para>
+ Dec 4 23:47:59 client 10.0.0.1#1355: updating zone
+ 'example.com/IN': update failed: 'RRset exists (value
+ dependent)' prerequisite not satisfied (NXRRSET)
+ </para>
+ </question>
+ <answer>
+ <para>
+ DNS updates allow the update request to test to see if
+ certain conditions are met prior to proceeding with the
+ update. The message above is saying that conditions were
+ not met and the update is not proceeding. See doc/rfc/rfc2136.txt
+ for more details on prerequisites.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I keep getting log messages like the following. Why?
+ </para>
+ <para>
+ Jun 21 12:00:00.000 client 10.0.0.1#1234: update denied
+ </para>
+ </question>
+ <answer>
+ <para>
+ Someone is trying to update your DNS data using the RFC2136
+ Dynamic Update protocol. Windows 2000 machines have a habit
+ of sending dynamic update requests to DNS servers without
+ being specifically configured to do so. If the update
+ requests are coming from a Windows 2000 machine, see
+ <ulink
+ url="http://support.microsoft.com/support/kb/articles/q246/8/04.asp">
+ &lt;http://support.microsoft.com/support/kb/articles/q246/8/04.asp&gt;</ulink>
+ for information about how to turn them off.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ When I do a "dig . ns", many of the A records for the root
+ servers are missing. Why?
+ </para>
+ </question>
+ <answer>
+ <para>
+ This is normal and harmless. It is a somewhat confusing
+ side effect of the way BIND 9 does RFC2181 trust ranking
+ and of the efforts BIND 9 makes to avoid promoting glue
+ into answers.
+ </para>
+ <para>
+ When BIND 9 first starts up and primes its cache, it receives
+ the root server addresses as additional data in an authoritative
+ response from a root server, and these records are eligible
+ for inclusion as additional data in responses. Subsequently
+ it receives a subset of the root server addresses as
+ additional data in a non-authoritative (referral) response
+ from a root server. This causes the addresses to now be
+ considered non-authoritative (glue) data, which is not
+ eligible for inclusion in responses.
+ </para>
+ <para>
+ The server does have a complete set of root server addresses
+ cached at all times, it just may not include all of them
+ as additional data, depending on whether they were last
+ received as answers or as glue. You can always look up the
+ addresses with explicit queries like "dig a.root-servers.net A".
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Why don't my zones reload when I do an "rndc reload" or SIGHUP?
+ </para>
+ </question>
+ <answer>
+ <para>
+ A zone can be updated either by editing zone files and
+ reloading the server or by dynamic update, but not both.
+ If you have enabled dynamic update for a zone using the
+ "allow-update" option, you are not supposed to edit the
+ zone file by hand, and the server will not attempt to reload
+ it.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Why is named listening on UDP port other than 53?
+ </para>
+ </question>
+ <answer>
+ <para>
+ Named uses a system selected port to make queries of other
+ nameservers. This behaviour can be overridden by using
+ query-source to lock down the port and/or address. See
+ also notify-source and transfer-source.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I get warning messages like <quote>zone example.com/IN: refresh:
+ failure trying master 1.2.3.4#53: timed out</quote>.
+ </para>
+ </question>
+ <answer>
+ <para>
+ Check that you can make UDP queries from the slave to the master
+ </para>
+ <informalexample>
+ <programlisting>
+dig +norec example.com soa @1.2.3.4</programlisting>
+ </informalexample>
+ <para>
+ You could be generating queries faster than the slave can
+ cope with. Lower the serial query rate.
+ </para>
+ <informalexample>
+ <programlisting>
+serial-query-rate 5; // default 20</programlisting>
+ </informalexample>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I don't get RRSIG's returned when I use "dig +dnssec".
+ </para>
+ </question>
+ <answer>
+ <para>
+ You need to ensure DNSSEC is enabled (dnssec-enable yes;).
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Can a NS record refer to a CNAME.
+ </para>
+ </question>
+ <answer>
+ <para>
+ No. The rules for glue (copies of the *address* records
+ in the parent zones) and additional section processing do
+ not allow it to work.
+ </para>
+ <para>
+ You would have to add both the CNAME and address records
+ (A/AAAA) as glue to the parent zone and have CNAMEs be
+ followed when doing additional section processing to make
+ it work. No nameserver implementation supports either of
+ these requirements.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ What does <quote>RFC 1918 response from Internet for
+ 0.0.0.10.IN-ADDR.ARPA</quote> mean?
+ </para>
+ </question>
+ <answer>
+ <para>
+ If the IN-ADDR.ARPA name covered refers to a internal address
+ space you are using then you have failed to follow RFC 1918
+ usage rules and are leaking queries to the Internet. You
+ should establish your own zones for these addresses to prevent
+ you querying the Internet's name servers for these addresses.
+ Please see <ulink url="http://as112.net/">&lt;http://as112.net/&gt;</ulink>
+ for details of the problems you are causing and the counter
+ measures that have had to be deployed.
+ </para>
+ <para>
+ If you are not using these private addresses then a client
+ has queried for them. You can just ignore the messages,
+ get the offending client to stop sending you these messages
+ as they are most probably leaking them or setup your own zones
+ empty zones to serve answers to these queries.
+ </para>
+ <informalexample>
+ <programlisting>
+zone "10.IN-ADDR.ARPA" {
+ type master;
+ file "empty";
+};
+
+zone "16.172.IN-ADDR.ARPA" {
+ type master;
+ file "empty";
+};
+
+...
+
+zone "31.172.IN-ADDR.ARPA" {
+ type master;
+ file "empty";
+};
+
+zone "168.192.IN-ADDR.ARPA" {
+ type master;
+ file "empty";
+};
+
+empty:
+@ 10800 IN SOA &lt;name-of-server&gt;. &lt;contact-email&gt;. (
+ 1 3600 1200 604800 10800 )
+@ 10800 IN NS &lt;name-of-server&gt;.</programlisting>
+ </informalexample>
+ <para>
+ <note>
+ Future versions of named are likely to do this automatically.
+ </note>
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Will named be affected by the 2007 changes to daylight savings
+ rules in the US.
+ </para>
+ </question>
+ <answer>
+ <para>
+ No, so long as the machines internal clock (as reported
+ by "date -u") remains at UTC. The only visible change
+ if you fail to upgrade your OS, if you are in a affected
+ area, will be that log messages will be a hour out during
+ the period where the old rules do not match the new rules.
+ </para>
+ <para>
+ For most OS's this change just means that you need to
+ update the conversion rules from UTC to local time.
+ Normally this involves updating a file in /etc (which
+ sets the default timezone for the machine) and possibly
+ a directory which has all the conversion rules for the
+ world (e.g. /usr/share/zoneinfo). When updating the OS
+ do not forget to update any chroot areas as well.
+ See your OS's documentation for more details.
+ </para>
+ <para>
+ The local timezone conversion rules can also be done on
+ a individual basis by setting the TZ environment variable
+ appropriately. See your OS's documentation for more
+ details.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Is there a bugzilla (or other tool) database that mere
+ mortals can have (read-only) access to for bind?
+ </para>
+ </question>
+ <answer>
+ <para>
+ No. The BIND 9 bug database is kept closed for a number
+ of reasons. These include, but are not limited to, that
+ the database contains proprietory information from people
+ reporting bugs. The database has in the past and may in
+ future contain unfixed bugs which are capable of bringing
+ down most of the Internet's DNS infrastructure.
+ </para>
+ <para>
+ The release pages for each version contain up to date
+ lists of bugs that have been fixed post release. That
+ is as close as we can get to providing a bug database.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Why do queries for NSEC3 records fail to return the NSEC3 record?
+ </para>
+ </question>
+ <answer>
+ <para>
+ NSEC3 records are strictly meta data and can only be
+ returned in the authority section. This is done so that
+ signing the zone using NSEC3 records does not bring names
+ into existance that do not exist in the unsigned version
+ of the zone.
+ </para>
+ </answer>
+ </qandaentry>
+
+ </qandadiv> <!-- General Questions -->
+
+ <qandadiv><title>Operating-System Specific Questions</title>
+
+ <qandadiv><title>HPUX</title>
+
+ <qandaentry>
+ <question>
+ <para>I get the following error trying to configure BIND:
+<programlisting>checking if unistd.h or sys/types.h defines fd_set... no
+configure: error: need either working unistd.h or sys/select.h</programlisting>
+ </para>
+ </question>
+ <answer>
+ <para>
+ You have attempted to configure BIND with the bundled C compiler.
+ This compiler does not meet the minimum compiler requirements to
+ for building BIND. You need to install a ANSI C compiler and / or
+ teach configure how to find the ANSI C compiler. The later can
+ be done by adjusting the PATH environment variable and / or
+ specifying the compiler via CC.
+ </para>
+ <informalexample>
+ <programlisting>./configure CC=&lt;compiler&gt; ...</programlisting>
+ </informalexample>
+ </answer>
+ </qandaentry>
+
+ </qandadiv> <!-- HPUX -->
+
+ <qandadiv><title>Linux</title>
+
+ <qandaentry>
+ <question>
+ <para>
+ Why do I get the following errors:
+<programlisting>general: errno2result.c:109: unexpected error:
+general: unable to convert errno to isc_result: 14: Bad address
+client: UDP client handler shutting down due to fatal receive error: unexpected error</programlisting>
+ </para>
+ </question>
+ <answer>
+ <para>
+ This is the result of a Linux kernel bug.
+ </para>
+ <para>
+ See:
+ <ulink url="http://marc.theaimsgroup.com/?l=linux-netdev&amp;m=113081708031466&amp;w=2">&lt;http://marc.theaimsgroup.com/?l=linux-netdev&amp;m=113081708031466&amp;w=2&gt;</ulink>
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Why does named lock up when it attempts to connect over IPSEC tunnels?
+ </para>
+ </question>
+ <answer>
+ <para>
+ This is due to a kernel bug where the fact that a socket is marked
+ non-blocking is ignored. It is reported that setting
+ xfrm_larval_drop to 1 helps but this may have negative side effects.
+ See:
+<ulink url="https://bugzilla.redhat.com/show_bug.cgi?id=427629">&lt;https://bugzilla.redhat.com/show_bug.cgi?id=427629&gt;</ulink>
+ and
+<ulink url="http://lkml.org/lkml/2007/12/4/260">&lt;http://lkml.org/lkml/2007/12/4/260&gt;</ulink>.
+ </para>
+ <para>
+ xfrm_larval_drop can be set to 1 by the following procedure:
+<programlisting>
+echo "1" &gt; proc/sys/net/core/xfrm_larval_drop</programlisting>
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Why do I see 5 (or more) copies of named on Linux?
+ </para>
+ </question>
+ <answer>
+ <para>
+ Linux threads each show up as a process under ps. The
+ approximate number of threads running is n+4, where n is
+ the number of CPUs. Note that the amount of memory used
+ is not cumulative; if each process is using 10M of memory,
+ only a total of 10M is used.
+ </para>
+ <para>
+ Newer versions of Linux's ps command hide the individual threads
+ and require -L to display them.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Why does BIND 9 log <quote>permission denied</quote> errors accessing
+ its configuration files or zones on my Linux system even
+ though it is running as root?
+ </para>
+ </question>
+ <answer>
+ <para>
+ On Linux, BIND 9 drops most of its root privileges on
+ startup. This including the privilege to open files owned
+ by other users. Therefore, if the server is running as
+ root, the configuration files and zone files should also
+ be owned by root.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I get the error message <quote>named: capset failed: Operation
+ not permitted</quote> when starting named.
+ </para>
+ </question>
+ <answer>
+ <para>
+ The capability module, part of "Linux Security Modules/LSM",
+ has not been loaded into the kernel. See insmod(8), modprobe(8).
+ </para>
+ <para>
+ The relevant modules can be loaded by running:
+<programlisting>
+modprobe commoncap
+modprobe capability</programlisting>
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I'm running BIND on Red Hat Enterprise Linux or Fedora Core -
+ </para>
+ <para>
+ Why can't named update slave zone database files?
+ </para>
+ <para>
+ Why can't named create DDNS journal files or update
+ the master zones from journals?
+ </para>
+ <para>
+ Why can't named create custom log files?
+ </para>
+ </question>
+
+ <answer>
+ <para>
+ Red Hat Security Enhanced Linux (SELinux) policy security
+ protections :
+ </para>
+
+ <para>
+ Red Hat have adopted the National Security Agency's
+ SELinux security policy (see <ulink
+ url="http://www.nsa.gov/selinux">&lt;http://www.nsa.gov/selinux&gt;</ulink>)
+ and recommendations for BIND security , which are more
+ secure than running named in a chroot and make use of
+ the bind-chroot environment unnecessary .
+ </para>
+
+ <para>
+ By default, named is not allowed by the SELinux policy
+ to write, create or delete any files EXCEPT in these
+ directories:
+ <informalexample>
+ <programlisting>
+$ROOTDIR/var/named/slaves
+$ROOTDIR/var/named/data
+$ROOTDIR/var/tmp
+ </programlisting>
+ </informalexample>
+ where $ROOTDIR may be set in /etc/sysconfig/named if
+ bind-chroot is installed.
+ </para>
+
+ <para>
+ The SELinux policy particularly does NOT allow named to modify
+ the $ROOTDIR/var/named directory, the default location for master
+ zone database files.
+ </para>
+
+ <para>
+ SELinux policy overrules file access permissions - so
+ even if all the files under /var/named have ownership
+ named:named and mode rw-rw-r--, named will still not be
+ able to write or create files except in the directories
+ above, with SELinux in Enforcing mode.
+ </para>
+
+ <para>
+ So, to allow named to update slave or DDNS zone files,
+ it is best to locate them in $ROOTDIR/var/named/slaves,
+ with named.conf zone statements such as:
+ <informalexample>
+ <programlisting>
+zone "slave.zone." IN {
+ type slave;
+ file "slaves/slave.zone.db";
+ ...
+};
+zone "ddns.zone." IN {
+ type master;
+ allow-updates {...};
+ file "slaves/ddns.zone.db";
+};
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ To allow named to create its cache dump and statistics
+ files, for example, you could use named.conf options
+ statements such as:
+ <informalexample>
+ <programlisting>
+options {
+ ...
+ dump-file "/var/named/data/cache_dump.db";
+ statistics-file "/var/named/data/named_stats.txt";
+ ...
+};
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ You can also tell SELinux to allow named to update any
+ zone database files, by setting the SELinux tunable boolean
+ parameter 'named_write_master_zones=1', using the
+ system-config-securitylevel GUI, using the 'setsebool'
+ command, or in /etc/selinux/targeted/booleans.
+ </para>
+
+ <para>
+ You can disable SELinux protection for named entirely by
+ setting the 'named_disable_trans=1' SELinux tunable boolean
+ parameter.
+ </para>
+
+ <para>
+ The SELinux named policy defines these SELinux contexts for named:
+ <informalexample>
+ <programlisting>
+named_zone_t : for zone database files - $ROOTDIR/var/named/*
+named_conf_t : for named configuration files - $ROOTDIR/etc/{named,rndc}.*
+named_cache_t: for files modifiable by named - $ROOTDIR/var/{tmp,named/{slaves,data}}
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ If you want to retain use of the SELinux policy for named,
+ and put named files in different locations, you can do
+ so by changing the context of the custom file locations
+ .
+ </para>
+
+ <para>
+ To create a custom configuration file location, e.g.
+ '/root/named.conf', to use with the 'named -c' option,
+ do:
+ <informalexample>
+ <programlisting>
+# chcon system_u:object_r:named_conf_t /root/named.conf
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ To create a custom modifiable named data location, e.g.
+ '/var/log/named' for a log file, do:
+ <informalexample>
+ <programlisting>
+# chcon system_u:object_r:named_cache_t /var/log/named
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ To create a custom zone file location, e.g. /root/zones/, do:
+ <informalexample>
+ <programlisting>
+# chcon system_u:object_r:named_zone_t /root/zones/{.,*}
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ See these man-pages for more information : selinux(8),
+ named_selinux(8), chcon(1), setsebool(8)
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ Listening on individual IPv6 interfaces does not work.
+ </para>
+ </question>
+ <answer>
+ <para>
+ This is usually due to "/proc/net/if_inet6" not being available
+ in the chroot file system. Mount another instance of "proc"
+ in the chroot file system.
+ </para>
+ <para>
+ This can be be made permanent by adding a second instance to
+ /etc/fstab.
+ <informalexample>
+ <programlisting>
+proc /proc proc defaults 0 0
+proc /var/named/proc proc defaults 0 0</programlisting>
+ </informalexample>
+ </para>
+ </answer>
+ </qandaentry>
+
+ </qandadiv> <!-- Linux -->
+
+ <qandadiv><title>Windows</title>
+
+ <qandaentry>
+ <question>
+ <para>
+ Zone transfers from my BIND 9 master to my Windows 2000
+ slave fail. Why?
+ </para>
+ </question>
+ <answer>
+ <para>
+ This may be caused by a bug in the Windows 2000 DNS server
+ where DNS messages larger than 16K are not handled properly.
+ This can be worked around by setting the option "transfer-format
+ one-answer;". Also check whether your zone contains domain
+ names with embedded spaces or other special characters,
+ like "John\032Doe\213s\032Computer", since such names have
+ been known to cause Windows 2000 slaves to incorrectly
+ reject the zone.
+ </para>
+ </answer>
+ </qandaentry>
+
+ <qandaentry>
+ <question>
+ <para>
+ I get <quote>Error 1067</quote> when starting named under Windows.
+ </para>
+ </question>
+ <answer>
+ <para>
+ This is the service manager saying that named exited. You
+ need to examine the Application log in the EventViewer to
+ find out why.
+ </para>
+ <para>
+ Common causes are that you failed to create "named.conf"
+ (usually "C:\windows\dns\etc\named.conf") or failed to
+ specify the directory in named.conf.
+ </para>
+ <informalexample>
+ <programlisting>
+options {
+ Directory "C:\windows\dns\etc";
+};</programlisting>
+ </informalexample>
+ </answer>
+ </qandaentry>
+
+ </qandadiv> <!-- Windows -->
+
+ <qandadiv><title>FreeBSD</title>
+
+ <qandaentry>
+ <question>
+ <para>
+ I have FreeBSD 4.x and "rndc-confgen -a" just sits there.
+ </para>
+ </question>
+ <answer>
+ <para>
+ /dev/random is not configured. Use rndcontrol(8) to tell
+ the kernel to use certain interrupts as a source of random
+ events. You can make this permanent by setting rand_irqs
+ in /etc/rc.conf.
+ </para>
+ <informalexample>
+ <programlisting>
+/etc/rc.conf
+rand_irqs="3 14 15"</programlisting>
+ </informalexample>
+ <para>
+ See also
+ <ulink url="http://people.freebsd.org/~dougb/randomness.html">
+ &lt;http://people.freebsd.org/~dougb/randomness.html&gt;</ulink>.
+ </para>
+ </answer>
+ </qandaentry>
+
+ </qandadiv> <!-- FreeBSD -->
+
+ <qandadiv><title>Solaris</title>
+
+ <qandaentry>
+ <question>
+ <para>
+ How do I integrate BIND 9 and Solaris SMF
+ </para>
+ </question>
+ <answer>
+ <para>
+ Sun has a blog entry describing how to do this.
+ </para>
+ <para>
+ <ulink
+ url="http://blogs.sun.com/roller/page/anay/Weblog?catname=%2FSolaris">
+ &lt;http://blogs.sun.com/roller/page/anay/Weblog?catname=%2FSolaris&gt;
+ </ulink>
+ </para>
+ </answer>
+ </qandaentry>
+
+ </qandadiv>
+
+ <qandadiv><title>Apple Mac OS X</title>
+
+ <qandaentry>
+ <question>
+ <para>
+ How do I run BIND 9 on Apple Mac OS X?
+ </para>
+ </question>
+ <answer>
+ <para>
+ If you run Tiger(Mac OS 10.4) or later then this is all you need to do:
+ </para>
+ <informalexample>
+ <programlisting>
+% sudo rndc-confgen > /etc/rndc.conf</programlisting>
+ </informalexample>
+ <para>
+ Copy the key statement from /etc/rndc.conf into /etc/rndc.key, e.g.:
+ </para>
+ <informalexample>
+ <programlisting>
+key "rndc-key" {
+ algorithm hmac-md5;
+ secret "uvceheVuqf17ZwIcTydddw==";
+};</programlisting>
+ </informalexample>
+ <para>
+ Then start the relevant service:
+ </para>
+ <informalexample>
+ <programlisting>
+% sudo service org.isc.named start</programlisting>
+ </informalexample>
+ <para>
+ This is persistent upon a reboot, so you will have to do it only once.
+ </para>
+ </answer>
+
+ <answer>
+ <para>
+ Alternatively you can just generate /etc/rndc.key by running:
+ </para>
+ <informalexample>
+ <programlisting>
+% sudo rndc-confgen -a</programlisting>
+ </informalexample>
+ <para>
+ Then start the relevant service:
+ </para>
+ <informalexample>
+ <programlisting>
+% sudo service org.isc.named start</programlisting>
+ </informalexample>
+ <para>
+ Named will look for /etc/rndc.key when it starts if it
+ doesn't have a controls section or the existing controls are
+ missing keys sub-clauses. This is persistent upon a
+ reboot, so you will have to do it only once.
+ </para>
+ </answer>
+ </qandaentry>
+
+ </qandadiv>
+
+ </qandadiv> <!-- Operating-System Specific Questions -->
+
+ </qandaset>
+</article>
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..cfdfb00
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,61 @@
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-2002 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.52 2008/09/25 04:02:38 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+SUBDIRS = make lib bin doc
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+distclean::
+ rm -f config.cache config.h config.log config.status TAGS
+ rm -f libtool isc-config.sh configure.lineno
+ rm -f util/conf.sh docutil/docbook2man-wrapper.sh
+
+# XXX we should clean libtool stuff too. Only do this after we add rules
+# to make it.
+maintainer-clean::
+ rm -f configure
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir} \
+ ${DESTDIR}${localstatedir}/run ${DESTDIR}${sysconfdir}
+
+install:: isc-config.sh installdirs
+ ${INSTALL_SCRIPT} isc-config.sh ${DESTDIR}${bindir}
+
+tags:
+ rm -f TAGS
+ find lib bin -name "*.[ch]" -print | @ETAGS@ -
+
+check: test
+
+test:
+ (cd bin/tests && ${MAKE} ${MAKEDEFS} test)
+
+FAQ: FAQ.xml
+ ${XSLTPROC} doc/xsl/isc-docbook-text.xsl FAQ.xml | \
+ LC_ALL=C ${W3M} -T text/html -dump -cols 72 >$@.tmp
+ mv $@.tmp $@
+
+clean::
+ rm -f FAQ.tmp
diff --git a/NSEC3-NOTES b/NSEC3-NOTES
new file mode 100644
index 0000000..d23b20e
--- /dev/null
+++ b/NSEC3-NOTES
@@ -0,0 +1,128 @@
+
+ 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 TYPE65535) 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 NSECPARAM 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
new file mode 100644
index 0000000..cc60dc8
--- /dev/null
+++ b/README
@@ -0,0 +1,590 @@
+BIND 9
+
+ BIND version 9 is a major rewrite of nearly all aspects of the
+ underlying BIND architecture. Some of the important features of
+ BIND 9 are:
+
+ - DNS Security
+ DNSSEC (signed zones)
+ TSIG (signed DNS requests)
+
+ - IP version 6
+ Answers DNS queries on IPv6 sockets
+ IPv6 resource records (AAAA)
+ Experimental IPv6 Resolver Library
+
+ - DNS Protocol Enhancements
+ IXFR, DDNS, Notify, EDNS0
+ Improved standards conformance
+
+ - Views
+ One server process can provide multiple "views" of
+ the DNS namespace, e.g. an "inside" view to certain
+ clients, and an "outside" view to others.
+
+ - Multiprocessor Support
+
+ - Improved Portability Architecture
+
+
+ BIND version 9 development has been underwritten by the following
+ organizations:
+
+ Sun Microsystems, Inc.
+ Hewlett Packard
+ Compaq Computer Corporation
+ IBM
+ Process Software Corporation
+ Silicon Graphics, Inc.
+ Network Associates, Inc.
+ U.S. Defense Information Systems Agency
+ USENIX Association
+ Stichting NLnet - NLnet Foundation
+ Nominum, Inc.
+
+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, 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 <qname,qclass,qtype> 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 (<qname,qtype,qclass>) 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 detailed list of user-visible changes from
+ previous releases, see the CHANGES file.
+
+
+Building
+
+ BIND 9 currently requires a UNIX system with an ANSI C compiler,
+ basic POSIX support, and a 64 bit integer type.
+
+ We've had successful builds and tests on the following systems:
+
+ COMPAQ Tru64 UNIX 5.1B
+ Fedora Core 6
+ FreeBSD 4.10, 5.2.1, 6.2
+ HP-UX 11.11
+ Mac OS X 10.5
+ NetBSD 3.x and 4.0-beta
+ OpenBSD 3.3 and up
+ Solaris 8, 9, 9 (x86), 10
+ Ubuntu 7.04, 7.10
+ Windows XP/2003/2008
+
+ NOTE: As of BIND 9.5.1, 9.4.3, and 9.3.6, older versions of
+ Windows, including Windows NT and Windows 2000, are no longer
+ supported.
+
+ We have recent reports from the user community that a supported
+ version of BIND will build and run on the following systems:
+
+ AIX 4.3, 5L
+ CentOS 4, 4.5, 5
+ Darwin 9.0.0d1/ARM
+ Debian 4
+ Fedora Core 5, 7
+ FreeBSD 6.1
+ HP-UX 11.23 PA
+ MacOS X 10.4, 10.5
+ Red Hat Enterprise Linux 4, 5
+ SCO OpenServer 5.0.6
+ Slackware 9, 10
+ SuSE 9, 10
+
+ To build, just
+
+ ./configure
+ make
+
+ Do not use a parallel "make".
+
+ Several environment variables that can be set before running
+ configure will affect compilation:
+
+ CC
+ The C compiler to use. configure tries to figure
+ out the right one for supported systems.
+
+ CFLAGS
+ C compiler flags. Defaults to include -g and/or -O2
+ as supported by the compiler.
+
+ STD_CINCLUDES
+ System header file directories. Can be used to specify
+ where add-on thread or IPv6 support is, for example.
+ Defaults to empty string.
+
+ STD_CDEFINES
+ Any additional preprocessor symbols you want defined.
+ Defaults to empty string.
+
+ Possible settings:
+ Change the default syslog facility of named/lwresd.
+ -DISC_FACILITY=LOG_LOCAL0
+ Enable DNSSEC signature chasing support in dig.
+ -DDIG_SIGCHASE=1 (sets -DDIG_SIGCHASE_TD=1 and
+ -DDIG_SIGCHASE_BU=1)
+ Disable dropping queries from particular well known ports.
+ -DNS_CLIENT_DROPPORT=0
+ Sibling glue checking in named-checkzone is enabled by default.
+ To disable the default check set. -DCHECK_SIBLING=0
+ named-checkzone checks out-of-zone addresses by default.
+ To disable this default set. -DCHECK_LOCAL=0
+ To create the default pid files in ${localstatedir}/run rather
+ than ${localstatedir}/run/{named,lwresd}/ set.
+ -DNS_RUN_PID_DIR=0
+ Enable workaround for Solaris kernel bug about /dev/poll
+ -DISC_SOCKET_USE_POLLWATCH=1
+ The watch timeout is also configurable, e.g.,
+ -DISC_SOCKET_POLLWATCH_TIMEOUT=20
+
+ LDFLAGS
+ Linker flags. Defaults to empty string.
+
+ The following need to be set when cross compiling.
+
+ BUILD_CC
+ The native C compiler.
+ BUILD_CFLAGS (optional)
+ BUILD_CPPFLAGS (optional)
+ Possible Settings:
+ -DNEED_OPTARG=1 (optarg is not declared in <unistd.h>)
+ BUILD_LDFLAGS (optional)
+ BUILD_LIBS (optional)
+
+ To build shared libraries, specify "--with-libtool" on the
+ configure command line.
+
+ For the server to support DNSSEC, you need to build it
+ with crypto support. You must have OpenSSL 0.9.5a
+ or newer installed and specify "--with-openssl" on the
+ configure command line. If OpenSSL is installed under
+ a nonstandard prefix, you can tell configure where to
+ look for it using "--with-openssl=/prefix".
+
+ On some platforms it is necessary to explictly request large
+ file support to handle files bigger than 2GB. This can be
+ done by "--enable-largefile" on the configure command line.
+
+ On some platforms, BIND 9 can be built with multithreading
+ support, allowing it to take advantage of multiple CPUs.
+ You can specify whether to build a multithreaded BIND 9
+ by specifying "--enable-threads" or "--disable-threads"
+ on the configure command line. The default is operating
+ system dependent.
+
+ Support for the "fixed" rrset-order option can be enabled
+ or disabled by specifying "--enable-fixed-rrset" or
+ "--disable-fixed-rrset" on the configure command line.
+ The default is "disabled", to reduce memory footprint.
+
+ If your operating system has integrated support for IPv6, it
+ will be used automatically. If you have installed KAME IPv6
+ separately, use "--with-kame[=PATH]" to specify its location.
+
+ "make install" will install "named" and the various BIND 9 libraries.
+ By default, installation is into /usr/local, but this can be changed
+ with the "--prefix" option when running "configure".
+
+ You may specify the option "--sysconfdir" to set the directory
+ where configuration files like "named.conf" go by default,
+ and "--localstatedir" to set the default parent directory
+ of "run/named.pid". For backwards compatibility with BIND 8,
+ --sysconfdir defaults to "/etc" and --localstatedir defaults to
+ "/var" if no --prefix option is given. If there is a --prefix
+ option, sysconfdir defaults to "$prefix/etc" and localstatedir
+ defaults to "$prefix/var".
+
+ To see additional configure options, run "configure --help".
+ Note that the help message does not reflect the BIND 8
+ compatibility defaults for sysconfdir and localstatedir.
+
+ If you're planning on making changes to the BIND 9 source, you
+ should also "make depend". If you're using Emacs, you might find
+ "make tags" helpful.
+
+ If you need to re-run configure please run "make distclean" first.
+ This will ensure that all the option changes take.
+
+ Building with gcc is not supported, unless gcc is the vendor's usual
+ compiler (e.g. the various BSD systems, Linux).
+
+ Known compiler issues:
+ * gcc-3.2.1 and gcc-3.1.1 is known to cause problems with solaris-x86.
+ * gcc prior to gcc-3.2.3 ultrasparc generates incorrect code at -02.
+ * gcc-3.3.5 powerpc generates incorrect code at -02.
+ * Irix, MipsPRO 7.4.1m is known to cause problems.
+
+ A limited test suite can be run with "make test". Many of
+ the tests require you to configure a set of virtual IP addresses
+ on your system, and some require Perl; see bin/tests/system/README
+ for details.
+
+ SunOS 4 requires "printf" to be installed to make the shared
+ libraries. sh-utils-1.16 provides a "printf" which compiles
+ on SunOS 4.
+
+Documentation
+
+ The BIND 9 Administrator Reference Manual is included with the
+ source distribution in DocBook XML and HTML format, in the
+ doc/arm directory.
+
+ Some of the programs in the BIND 9 distribution have man pages
+ in their directories. In particular, the command line
+ options of "named" are documented in /bin/named/named.8.
+ There is now also a set of man pages for the lwres library.
+
+ If you are upgrading from BIND 8, please read the migration
+ notes in doc/misc/migration. If you are upgrading from
+ BIND 4, read doc/misc/migration-4to9.
+
+ Frequently asked questions and their answers can be found in
+ FAQ.
+
+
+Bug Reports and Mailing Lists
+
+ Bugs reports should be sent to
+
+ bind9-bugs@isc.org
+
+ To join the BIND Users mailing list, send mail to
+
+ bind-users-request@isc.org
+
+ archives of which can be found via
+
+ http://www.isc.org/ops/lists/
+
+ If you're planning on making changes to the BIND 9 source
+ code, you might want to join the BIND Workers mailing list.
+ Send mail to
+
+ bind-workers-request@isc.org
+
+
diff --git a/README.idnkit b/README.idnkit
new file mode 100644
index 0000000..bb20b68
--- /dev/null
+++ b/README.idnkit
@@ -0,0 +1,112 @@
+
+ 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 exacutable 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 doens'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 argments, 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 2005/09/09 06:13:57 marka Exp $
diff --git a/README.pkcs11 b/README.pkcs11
new file mode 100644
index 0000000..b58640d
--- /dev/null
+++ b/README.pkcs11
@@ -0,0 +1,61 @@
+
+ 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
new file mode 100644
index 0000000..a806e58
--- /dev/null
+++ b/acconfig.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: acconfig.h,v 1.51 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+/***
+ *** This file is not to be included by any public header files, because
+ *** it does not get installed.
+ ***/
+@TOP@
+
+/** define to `int' if <sys/types.h> doesn't define. */
+#undef ssize_t
+
+/** define on DEC OSF to enable 4.4BSD style sa_len support */
+#undef _SOCKADDR_LEN
+
+/** define if your system needs pthread_init() before using pthreads */
+#undef NEED_PTHREAD_INIT
+
+/** define if your system has sigwait() */
+#undef HAVE_SIGWAIT
+
+/** define if sigwait() is the UnixWare flavor */
+#undef HAVE_UNIXWARE_SIGWAIT
+
+/** define on Solaris to get sigwait() to work using pthreads semantics */
+#undef _POSIX_PTHREAD_SEMANTICS
+
+/** define if LinuxThreads is in use */
+#undef HAVE_LINUXTHREADS
+
+/** define if sysconf() is available */
+#undef HAVE_SYSCONF
+
+/** define if sysctlbyname() is available */
+#undef HAVE_SYSCTLBYNAME
+
+/** define if catgets() is available */
+#undef HAVE_CATGETS
+
+/** define if getifaddrs() exists */
+#undef HAVE_GETIFADDRS
+
+/** define if you have the NET_RT_IFLIST sysctl variable and sys/sysctl.h */
+#undef HAVE_IFLIST_SYSCTL
+
+/** define if chroot() is available */
+#undef HAVE_CHROOT
+
+/** define if tzset() is available */
+#undef HAVE_TZSET
+
+/** define if struct addrinfo exists */
+#undef HAVE_ADDRINFO
+
+/** define if getaddrinfo() exists */
+#undef HAVE_GETADDRINFO
+
+/** define if gai_strerror() exists */
+#undef HAVE_GAISTRERROR
+
+/** define if arc4random() exists */
+#undef HAVE_ARC4RANDOM
+
+/**
+ * define if pthread_setconcurrency() should be called to tell the
+ * OS how many threads we might want to run.
+ */
+#undef CALL_PTHREAD_SETCONCURRENCY
+
+/** define if IPv6 is not disabled */
+#undef WANT_IPV6
+
+/** define if flockfile() is available */
+#undef HAVE_FLOCKFILE
+
+/** define if getc_unlocked() is available */
+#undef HAVE_GETCUNLOCKED
+
+/** Shut up warnings about sputaux in stdio.h on BSD/OS pre-4.1 */
+#undef SHUTUP_SPUTAUX
+#ifdef SHUTUP_SPUTAUX
+struct __sFILE;
+extern __inline int __sputaux(int _c, struct __sFILE *_p);
+#endif
+
+/** Shut up warnings about missing sigwait prototype on BSD/OS 4.0* */
+#undef SHUTUP_SIGWAIT
+#ifdef SHUTUP_SIGWAIT
+int sigwait(const unsigned int *set, int *sig);
+#endif
+
+/** Shut up warnings from gcc -Wcast-qual on BSD/OS 4.1. */
+#undef SHUTUP_STDARG_CAST
+#if defined(SHUTUP_STDARG_CAST) && defined(__GNUC__)
+#include <stdarg.h> /** Grr. Must be included *every time*. */
+/**
+ * The silly continuation line is to keep configure from
+ * commenting out the #undef.
+ */
+
+#undef \
+ va_start
+#define va_start(ap, last) \
+ do { \
+ union { const void *konst; long *var; } _u; \
+ _u.konst = &(last); \
+ ap = (va_list)(_u.var + __va_words(__typeof(last))); \
+ } while (0)
+#endif /** SHUTUP_STDARG_CAST && __GNUC__ */
+
+/** define if the system has a random number generating device */
+#undef PATH_RANDOMDEV
+
+/** define if pthread_attr_getstacksize() is available */
+#undef HAVE_PTHREAD_ATTR_GETSTACKSIZE
+
+/** define if pthread_attr_setstacksize() is available */
+#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE
+
+/** define if you have strerror in the C library. */
+#undef HAVE_STRERROR
+
+/** Define if you are running under Compaq TruCluster. */
+#undef HAVE_TRUCLUSTER
+
+/* Define if OpenSSL includes DSA support */
+#undef HAVE_OPENSSL_DSA
+
+/* Define to the length type used by the socket API (socklen_t, size_t, int). */
+#undef ISC_SOCKADDR_LEN_T
+
+/* Define if threads need PTHREAD_SCOPE_SYSTEM */
+#undef NEED_PTHREAD_SCOPE_SYSTEM
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..c1a594c
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,2 @@
+sinclude(./libtool.m4)dnl
+
diff --git a/bin/Makefile.in b/bin/Makefile.in
new file mode 100644
index 0000000..ef28e0c
--- /dev/null
+++ b/bin/Makefile.in
@@ -0,0 +1,25 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.25 2007/06/19 23:46:59 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = named rndc dig dnssec tests nsupdate check
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/bin/check/Makefile.in b/bin/check/Makefile.in
new file mode 100644
index 0000000..06f5541
--- /dev/null
+++ b/bin/check/Makefile.in
@@ -0,0 +1,98 @@
+# Copyright (C) 2004-2007 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: Makefile.in,v 1.32 2007/06/19 23:46:59 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${BIND9_INCLUDES} ${DNS_INCLUDES} ${ISCCFG_INCLUDES} \
+ ${ISC_INCLUDES}
+
+CDEFINES = -DNAMED_CONFFILE=\"${sysconfdir}/named.conf\"
+CWARNINGS =
+
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+
+LIBS = @LIBS@
+
+SUBDIRS =
+
+# Alphabetically
+TARGETS = named-checkconf@EXEEXT@ named-checkzone@EXEEXT@
+
+# Alphabetically
+SRCS = named-checkconf.c named-checkzone.c check-tool.c
+
+MANPAGES = named-checkconf.8 named-checkzone.8
+
+HTMLPAGES = named-checkconf.html named-checkzone.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+named-checkconf.@O@: named-checkconf.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -c ${srcdir}/named-checkconf.c
+
+named-checkzone.@O@: named-checkzone.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -c ${srcdir}/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}
+
+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}
+
+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:: named-checkconf@EXEEXT@ named-checkzone@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-checkconf@EXEEXT@ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-checkzone@EXEEXT@ ${DESTDIR}${sbindir}
+ (cd ${DESTDIR}${sbindir}; rm -f named-compilezone@EXEEXT@; ${LINK_PROGRAM} named-checkzone@EXEEXT@ named-compilezone@EXEEXT@)
+ for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8; done
+ (cd ${DESTDIR}${mandir}/man8; rm -f named-compilezone.8; ${LINK_PROGRAM} named-checkzone.8 named-compilezone.8)
+
+clean distclean::
+ rm -f ${TARGETS} r1.htm
diff --git a/bin/check/check-tool.c b/bin/check/check-tool.c
new file mode 100644
index 0000000..98bc721
--- /dev/null
+++ b/bin/check/check-tool.c
@@ -0,0 +1,663 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: check-tool.c,v 1.35 2008/10/24 00:28:00 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include "check-tool.h"
+#include <isc/buffer.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/netdb.h>
+#include <isc/net.h>
+#include <isc/region.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/symtab.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/types.h>
+#include <dns/zone.h>
+
+#include <isccfg/log.h>
+
+#ifndef CHECK_SIBLING
+#define CHECK_SIBLING 1
+#endif
+
+#ifndef CHECK_LOCAL
+#define CHECK_LOCAL 1
+#endif
+
+#ifdef HAVE_ADDRINFO
+#ifdef HAVE_GETADDRINFO
+#ifdef HAVE_GAISTRERROR
+#define USE_GETADDRINFO
+#endif
+#endif
+#endif
+
+#define CHECK(r) \
+ do { \
+ result = (r); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+#define ERR_IS_CNAME 1
+#define ERR_NO_ADDRESSES 2
+#define ERR_LOOKUP_FAILURE 3
+#define ERR_EXTRA_A 4
+#define ERR_EXTRA_AAAA 5
+#define ERR_MISSING_GLUE 5
+#define ERR_IS_MXCNAME 6
+#define ERR_IS_SRVCNAME 7
+
+static const char *dbtype[] = { "rbt" };
+
+int debug = 0;
+isc_boolean_t nomerge = ISC_TRUE;
+#if CHECK_LOCAL
+isc_boolean_t docheckmx = ISC_TRUE;
+isc_boolean_t dochecksrv = ISC_TRUE;
+isc_boolean_t docheckns = ISC_TRUE;
+#else
+isc_boolean_t docheckmx = ISC_FALSE;
+isc_boolean_t dochecksrv = ISC_FALSE;
+isc_boolean_t docheckns = ISC_FALSE;
+#endif
+unsigned int zone_options = DNS_ZONEOPT_CHECKNS |
+ DNS_ZONEOPT_CHECKMX |
+ DNS_ZONEOPT_MANYERRORS |
+ DNS_ZONEOPT_CHECKNAMES |
+ DNS_ZONEOPT_CHECKINTEGRITY |
+#if CHECK_SIBLING
+ DNS_ZONEOPT_CHECKSIBLING |
+#endif
+ DNS_ZONEOPT_CHECKWILDCARD |
+ DNS_ZONEOPT_WARNMXCNAME |
+ DNS_ZONEOPT_WARNSRVCNAME;
+
+/*
+ * This needs to match the list in bin/named/log.c.
+ */
+static isc_logcategory_t categories[] = {
+ { "", 0 },
+ { "client", 0 },
+ { "network", 0 },
+ { "update", 0 },
+ { "queries", 0 },
+ { "unmatched", 0 },
+ { "update-security", 0 },
+ { NULL, 0 }
+};
+
+static isc_symtab_t *symtab = NULL;
+static isc_mem_t *sym_mctx;
+
+static void
+freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
+ UNUSED(type);
+ UNUSED(value);
+ isc_mem_free(userarg, key);
+}
+
+static void
+add(char *key, int value) {
+ isc_result_t result;
+ isc_symvalue_t symvalue;
+
+ if (sym_mctx == NULL) {
+ result = isc_mem_create(0, 0, &sym_mctx);
+ if (result != ISC_R_SUCCESS)
+ return;
+ }
+
+ if (symtab == NULL) {
+ result = isc_symtab_create(sym_mctx, 100, freekey, sym_mctx,
+ ISC_FALSE, &symtab);
+ if (result != ISC_R_SUCCESS)
+ return;
+ }
+
+ key = isc_mem_strdup(sym_mctx, key);
+ if (key == NULL)
+ return;
+
+ symvalue.as_pointer = NULL;
+ result = isc_symtab_define(symtab, key, value, symvalue,
+ isc_symexists_reject);
+ if (result != ISC_R_SUCCESS)
+ isc_mem_free(sym_mctx, key);
+}
+
+static isc_boolean_t
+logged(char *key, int value) {
+ isc_result_t result;
+
+ if (symtab == NULL)
+ return (ISC_FALSE);
+
+ result = isc_symtab_lookup(symtab, key, value, NULL);
+ if (result == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+static isc_boolean_t
+checkns(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner,
+ dns_rdataset_t *a, dns_rdataset_t *aaaa)
+{
+#ifdef USE_GETADDRINFO
+ dns_rdataset_t *rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ struct addrinfo hints, *ai, *cur;
+ char namebuf[DNS_NAME_FORMATSIZE + 1];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
+ isc_boolean_t answer = ISC_TRUE;
+ isc_boolean_t match;
+ const char *type;
+ void *ptr = NULL;
+ int result;
+
+ REQUIRE(a == NULL || !dns_rdataset_isassociated(a) ||
+ a->type == dns_rdatatype_a);
+ REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) ||
+ aaaa->type == dns_rdatatype_aaaa);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ /*
+ * Turn off search.
+ */
+ if (dns_name_countlabels(name) > 1U)
+ strcat(namebuf, ".");
+ dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
+
+ result = getaddrinfo(namebuf, NULL, &hints, &ai);
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ switch (result) {
+ case 0:
+ /*
+ * Work around broken getaddrinfo() implementations that
+ * fail to set ai_canonname on first entry.
+ */
+ cur = ai;
+ while (cur != NULL && cur->ai_canonname == NULL &&
+ cur->ai_next != NULL)
+ cur = cur->ai_next;
+ if (ai != NULL && cur->ai_canonname != NULL &&
+ strcasecmp(ai->ai_canonname, namebuf) != 0 &&
+ !logged(namebuf, ERR_IS_CNAME)) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/NS '%s' (out of zone) "
+ "is a CNAME '%s' (illegal)",
+ ownerbuf, namebuf,
+ cur->ai_canonname);
+ /* XXX950 make fatal for 9.5.0 */
+ /* answer = ISC_FALSE; */
+ add(namebuf, ERR_IS_CNAME);
+ }
+ break;
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ if (!logged(namebuf, ERR_NO_ADDRESSES)) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/NS '%s' (out of zone) "
+ "has no addresses records (A or AAAA)",
+ ownerbuf, namebuf);
+ add(namebuf, ERR_NO_ADDRESSES);
+ }
+ /* XXX950 make fatal for 9.5.0 */
+ return (ISC_TRUE);
+
+ default:
+ if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "getaddrinfo(%s) failed: %s",
+ namebuf, gai_strerror(result));
+ add(namebuf, ERR_LOOKUP_FAILURE);
+ }
+ return (ISC_TRUE);
+ }
+ if (a == NULL || aaaa == NULL)
+ return (answer);
+ /*
+ * Check that all glue records really exist.
+ */
+ if (!dns_rdataset_isassociated(a))
+ goto checkaaaa;
+ result = dns_rdataset_first(a);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(a, &rdata);
+ match = ISC_FALSE;
+ for (cur = ai; cur != NULL; cur = cur->ai_next) {
+ if (cur->ai_family != AF_INET)
+ continue;
+ ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
+ if (memcmp(ptr, rdata.data, rdata.length) == 0) {
+ match = ISC_TRUE;
+ break;
+ }
+ }
+ if (!match && !logged(namebuf, ERR_EXTRA_A)) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
+ "extra GLUE A record (%s)",
+ ownerbuf, namebuf,
+ inet_ntop(AF_INET, rdata.data,
+ addrbuf, sizeof(addrbuf)));
+ add(namebuf, ERR_EXTRA_A);
+ /* XXX950 make fatal for 9.5.0 */
+ /* answer = ISC_FALSE; */
+ }
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(a);
+ }
+
+ checkaaaa:
+ if (!dns_rdataset_isassociated(aaaa))
+ goto checkmissing;
+ result = dns_rdataset_first(aaaa);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(aaaa, &rdata);
+ match = ISC_FALSE;
+ for (cur = ai; cur != NULL; cur = cur->ai_next) {
+ if (cur->ai_family != AF_INET6)
+ continue;
+ ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
+ if (memcmp(ptr, rdata.data, rdata.length) == 0) {
+ match = ISC_TRUE;
+ break;
+ }
+ }
+ if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
+ "extra GLUE AAAA record (%s)",
+ ownerbuf, namebuf,
+ inet_ntop(AF_INET6, rdata.data,
+ addrbuf, sizeof(addrbuf)));
+ add(namebuf, ERR_EXTRA_AAAA);
+ /* XXX950 make fatal for 9.5.0. */
+ /* answer = ISC_FALSE; */
+ }
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(aaaa);
+ }
+
+ checkmissing:
+ /*
+ * Check that all addresses appear in the glue.
+ */
+ if (!logged(namebuf, ERR_MISSING_GLUE)) {
+ isc_boolean_t missing_glue = ISC_FALSE;
+ for (cur = ai; cur != NULL; cur = cur->ai_next) {
+ switch (cur->ai_family) {
+ case AF_INET:
+ rdataset = a;
+ ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
+ type = "A";
+ break;
+ case AF_INET6:
+ rdataset = aaaa;
+ ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
+ type = "AAAA";
+ break;
+ default:
+ continue;
+ }
+ match = ISC_FALSE;
+ if (dns_rdataset_isassociated(rdataset))
+ result = dns_rdataset_first(rdataset);
+ else
+ result = ISC_R_FAILURE;
+ while (result == ISC_R_SUCCESS && !match) {
+ dns_rdataset_current(rdataset, &rdata);
+ if (memcmp(ptr, rdata.data, rdata.length) == 0)
+ match = ISC_TRUE;
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(rdataset);
+ }
+ if (!match) {
+ dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
+ "missing GLUE %s record (%s)",
+ ownerbuf, namebuf, type,
+ inet_ntop(cur->ai_family, ptr,
+ addrbuf, sizeof(addrbuf)));
+ /* XXX950 make fatal for 9.5.0. */
+ /* answer = ISC_FALSE; */
+ missing_glue = ISC_TRUE;
+ }
+ }
+ if (missing_glue)
+ add(namebuf, ERR_MISSING_GLUE);
+ }
+ freeaddrinfo(ai);
+ return (answer);
+#else
+ return (ISC_TRUE);
+#endif
+}
+
+static isc_boolean_t
+checkmx(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
+#ifdef USE_GETADDRINFO
+ struct addrinfo hints, *ai, *cur;
+ char namebuf[DNS_NAME_FORMATSIZE + 1];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ int result;
+ int level = ISC_LOG_ERROR;
+ isc_boolean_t answer = ISC_TRUE;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ /*
+ * Turn off search.
+ */
+ if (dns_name_countlabels(name) > 1U)
+ strcat(namebuf, ".");
+ dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
+
+ result = getaddrinfo(namebuf, NULL, &hints, &ai);
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ switch (result) {
+ case 0:
+ /*
+ * Work around broken getaddrinfo() implementations that
+ * fail to set ai_canonname on first entry.
+ */
+ cur = ai;
+ while (cur != NULL && cur->ai_canonname == NULL &&
+ cur->ai_next != NULL)
+ cur = cur->ai_next;
+ if (cur != NULL && cur->ai_canonname != NULL &&
+ strcasecmp(cur->ai_canonname, namebuf) != 0) {
+ if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0)
+ level = ISC_LOG_WARNING;
+ if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) {
+ if (!logged(namebuf, ERR_IS_MXCNAME)) {
+ dns_zone_log(zone, level,
+ "%s/MX '%s' (out of zone)"
+ " is a CNAME '%s' "
+ "(illegal)",
+ ownerbuf, namebuf,
+ cur->ai_canonname);
+ add(namebuf, ERR_IS_MXCNAME);
+ }
+ if (level == ISC_LOG_ERROR)
+ answer = ISC_FALSE;
+ }
+ }
+ freeaddrinfo(ai);
+ return (answer);
+
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ if (!logged(namebuf, ERR_NO_ADDRESSES)) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/MX '%s' (out of zone) "
+ "has no addresses records (A or AAAA)",
+ ownerbuf, namebuf);
+ add(namebuf, ERR_NO_ADDRESSES);
+ }
+ /* XXX950 make fatal for 9.5.0. */
+ return (ISC_TRUE);
+
+ default:
+ if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "getaddrinfo(%s) failed: %s",
+ namebuf, gai_strerror(result));
+ add(namebuf, ERR_LOOKUP_FAILURE);
+ }
+ return (ISC_TRUE);
+ }
+#else
+ return (ISC_TRUE);
+#endif
+}
+
+static isc_boolean_t
+checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
+#ifdef USE_GETADDRINFO
+ struct addrinfo hints, *ai, *cur;
+ char namebuf[DNS_NAME_FORMATSIZE + 1];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ int result;
+ int level = ISC_LOG_ERROR;
+ isc_boolean_t answer = ISC_TRUE;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ /*
+ * Turn off search.
+ */
+ if (dns_name_countlabels(name) > 1U)
+ strcat(namebuf, ".");
+ dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
+
+ result = getaddrinfo(namebuf, NULL, &hints, &ai);
+ dns_name_format(name, namebuf, sizeof(namebuf) - 1);
+ switch (result) {
+ case 0:
+ /*
+ * Work around broken getaddrinfo() implementations that
+ * fail to set ai_canonname on first entry.
+ */
+ cur = ai;
+ while (cur != NULL && cur->ai_canonname == NULL &&
+ cur->ai_next != NULL)
+ cur = cur->ai_next;
+ if (cur != NULL && cur->ai_canonname != NULL &&
+ strcasecmp(cur->ai_canonname, namebuf) != 0) {
+ if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0)
+ level = ISC_LOG_WARNING;
+ if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) {
+ if (!logged(namebuf, ERR_IS_SRVCNAME)) {
+ dns_zone_log(zone, level, "%s/SRV '%s'"
+ " (out of zone) is a "
+ "CNAME '%s' (illegal)",
+ ownerbuf, namebuf,
+ cur->ai_canonname);
+ add(namebuf, ERR_IS_SRVCNAME);
+ }
+ if (level == ISC_LOG_ERROR)
+ answer = ISC_FALSE;
+ }
+ }
+ freeaddrinfo(ai);
+ return (answer);
+
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ if (!logged(namebuf, ERR_NO_ADDRESSES)) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "%s/SRV '%s' (out of zone) "
+ "has no addresses records (A or AAAA)",
+ ownerbuf, namebuf);
+ add(namebuf, ERR_NO_ADDRESSES);
+ }
+ /* XXX950 make fatal for 9.5.0. */
+ return (ISC_TRUE);
+
+ default:
+ if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "getaddrinfo(%s) failed: %s",
+ namebuf, gai_strerror(result));
+ add(namebuf, ERR_LOOKUP_FAILURE);
+ }
+ return (ISC_TRUE);
+ }
+#else
+ return (ISC_TRUE);
+#endif
+}
+
+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_registercategories(log, categories);
+ isc_log_setcontext(log);
+ dns_log_init(log);
+ dns_log_setcontext(log);
+ cfg_log_init(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);
+}
+
+/*% load the zone */
+isc_result_t
+load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
+ dns_masterformat_t fileformat, const char *classname,
+ dns_zone_t **zonep)
+{
+ isc_result_t result;
+ dns_rdataclass_t rdclass;
+ isc_textregion_t region;
+ isc_buffer_t buffer;
+ dns_fixedname_t fixorigin;
+ dns_name_t *origin;
+ dns_zone_t *zone = NULL;
+
+ REQUIRE(zonep == NULL || *zonep == NULL);
+
+ if (debug)
+ fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
+ zonename, filename, classname);
+
+ CHECK(dns_zone_create(&zone, mctx));
+
+ dns_zone_settype(zone, dns_zone_master);
+
+ isc_buffer_init(&buffer, zonename, strlen(zonename));
+ 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_zone_setorigin(zone, origin));
+ CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype));
+ CHECK(dns_zone_setfile2(zone, filename, fileformat));
+
+ DE_CONST(classname, region.base);
+ region.length = strlen(classname);
+ CHECK(dns_rdataclass_fromtext(&rdclass, &region));
+
+ dns_zone_setclass(zone, rdclass);
+ dns_zone_setoption(zone, zone_options, ISC_TRUE);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);
+ if (docheckmx)
+ dns_zone_setcheckmx(zone, checkmx);
+ if (docheckns)
+ dns_zone_setcheckns(zone, checkns);
+ if (dochecksrv)
+ dns_zone_setchecksrv(zone, checksrv);
+
+ CHECK(dns_zone_load(zone));
+ if (zonep != NULL) {
+ *zonep = zone;
+ zone = NULL;
+ }
+
+ cleanup:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ return (result);
+}
+
+/*% dump the zone */
+isc_result_t
+dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
+ dns_masterformat_t fileformat, const dns_master_style_t *style)
+{
+ isc_result_t result;
+ FILE *output = stdout;
+
+ if (debug) {
+ if (filename != NULL && strcmp(filename, "-") != 0)
+ fprintf(stderr, "dumping \"%s\" to \"%s\"\n",
+ zonename, filename);
+ else
+ fprintf(stderr, "dumping \"%s\"\n", zonename);
+ }
+
+ if (filename != NULL && strcmp(filename, "-") != 0) {
+ result = isc_stdio_open(filename, "w+", &output);
+
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not open output "
+ "file \"%s\" for writing\n", filename);
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ result = dns_zone_dumptostream2(zone, output, fileformat, style);
+
+ if (output != stdout)
+ (void)isc_stdio_close(output);
+
+ return (result);
+}
diff --git a/bin/check/check-tool.h b/bin/check/check-tool.h
new file mode 100644
index 0000000..b0ba7e0
--- /dev/null
+++ b/bin/check/check-tool.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: check-tool.h,v 1.14 2007/06/18 23:47:17 tbox Exp $ */
+
+#ifndef CHECK_TOOL_H
+#define CHECK_TOOL_H
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/stdio.h>
+#include <isc/types.h>
+
+#include <dns/masterdump.h>
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp);
+
+isc_result_t
+load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
+ dns_masterformat_t fileformat, const char *classname,
+ dns_zone_t **zonep);
+
+isc_result_t
+dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
+ dns_masterformat_t fileformat, const dns_master_style_t *style);
+
+extern int debug;
+extern isc_boolean_t nomerge;
+extern isc_boolean_t docheckmx;
+extern isc_boolean_t docheckns;
+extern isc_boolean_t dochecksrv;
+extern unsigned int zone_options;
+
+ISC_LANG_ENDDECLS
+
+#endif
diff --git a/bin/check/named-checkconf.8 b/bin/check/named-checkconf.8
new file mode 100644
index 0000000..852b133
--- /dev/null
+++ b/bin/check/named-checkconf.8
@@ -0,0 +1,94 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2002 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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-checkconf.8,v 1.30 2007/06/20 02:27:32 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: named\-checkconf
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: June 14, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "NAMED\-CHECKCONF" "8" "June 14, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+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]
+.SH "DESCRIPTION"
+.PP
+\fBnamed\-checkconf\fR
+checks the syntax, but not the semantics, of a named configuration file.
+.SH "OPTIONS"
+.PP
+\-h
+.RS 4
+Print the usage summary and exit.
+.RE
+.PP
+\-t \fIdirectory\fR
+.RS 4
+Chroot to
+\fIdirectory\fR
+so that include directives in the configuration file are processed as if run by a similarly chrooted named.
+.RE
+.PP
+\-v
+.RS 4
+Print the version of the
+\fBnamed\-checkconf\fR
+program and exit.
+.RE
+.PP
+\-z
+.RS 4
+Perform a test load of all master zones found in
+\fInamed.conf\fR.
+.RE
+.PP
+\-j
+.RS 4
+When loading a zonefile read the journal if it exists.
+.RE
+.PP
+filename
+.RS 4
+The name of the configuration file to be checked. If not specified, it defaults to
+\fI/etc/named.conf\fR.
+.RE
+.SH "RETURN VALUES"
+.PP
+\fBnamed\-checkconf\fR
+returns an exit status of 1 if errors were detected and 0 otherwise.
+.SH "SEE ALSO"
+.PP
+\fBnamed\fR(8),
+\fBnamed\-checkzone\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 2000\-2002 Internet Software Consortium.
+.br
diff --git a/bin/check/named-checkconf.c b/bin/check/named-checkconf.c
new file mode 100644
index 0000000..0c6e70f
--- /dev/null
+++ b/bin/check/named-checkconf.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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-checkconf.c,v 1.46 2007/11/26 02:12:45 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <isccfg/namedconf.h>
+
+#include <bind9/check.h>
+
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/result.h>
+#include <dns/zone.h>
+
+#include "check-tool.h"
+
+static const char *program = "named-checkconf";
+
+isc_log_t *logc = NULL;
+
+#define CHECK(r)\
+ do { \
+ result = (r); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+/*% usage */
+static void
+usage(void) {
+ fprintf(stderr, "usage: %s [-h] [-j] [-v] [-z] [-t directory] "
+ "[named.conf]\n", program);
+ exit(1);
+}
+
+/*% directory callback */
+static isc_result_t
+directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
+ isc_result_t result;
+ const char *directory;
+
+ REQUIRE(strcasecmp("directory", clausename) == 0);
+
+ UNUSED(arg);
+ UNUSED(clausename);
+
+ /*
+ * Change directory.
+ */
+ directory = cfg_obj_asstring(obj);
+ result = isc_dir_chdir(directory);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logc, ISC_LOG_ERROR,
+ "change directory to '%s' failed: %s\n",
+ directory, isc_result_totext(result));
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+get_maps(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) {
+ int i;
+ for (i = 0;; i++) {
+ if (maps[i] == NULL)
+ return (ISC_FALSE);
+ if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+ }
+}
+
+static isc_boolean_t
+get_checknames(const cfg_obj_t **maps, const cfg_obj_t **obj) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *checknames;
+ const cfg_obj_t *type;
+ const cfg_obj_t *value;
+ isc_result_t result;
+ int i;
+
+ for (i = 0;; i++) {
+ if (maps[i] == NULL)
+ return (ISC_FALSE);
+ checknames = NULL;
+ result = cfg_map_get(maps[i], "check-names", &checknames);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if (checknames != NULL && !cfg_obj_islist(checknames)) {
+ *obj = checknames;
+ return (ISC_TRUE);
+ }
+ for (element = cfg_list_first(checknames);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ value = cfg_listelt_value(element);
+ type = cfg_tuple_get(value, "type");
+ if (strcasecmp(cfg_obj_asstring(type), "master") != 0)
+ continue;
+ *obj = cfg_tuple_get(value, "mode");
+ return (ISC_TRUE);
+ }
+ }
+}
+
+static isc_result_t
+config_get(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) {
+ int i;
+
+ for (i = 0;; i++) {
+ if (maps[i] == NULL)
+ return (ISC_R_NOTFOUND);
+ if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+ }
+}
+
+/*% configure the zone */
+static isc_result_t
+configure_zone(const char *vclass, const char *view,
+ const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
+ const cfg_obj_t *config, isc_mem_t *mctx)
+{
+ int i = 0;
+ isc_result_t result;
+ const char *zclass;
+ const char *zname;
+ const char *zfile;
+ const cfg_obj_t *maps[4];
+ const cfg_obj_t *zoptions = NULL;
+ const cfg_obj_t *classobj = NULL;
+ const cfg_obj_t *typeobj = NULL;
+ const cfg_obj_t *fileobj = NULL;
+ const cfg_obj_t *dbobj = NULL;
+ const cfg_obj_t *obj = NULL;
+ const cfg_obj_t *fmtobj = NULL;
+ dns_masterformat_t masterformat;
+
+ zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_MANYERRORS;
+
+ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+ classobj = cfg_tuple_get(zconfig, "class");
+ if (!cfg_obj_isstring(classobj))
+ zclass = vclass;
+ else
+ zclass = cfg_obj_asstring(classobj);
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+ maps[i++] = zoptions;
+ if (vconfig != NULL)
+ maps[i++] = cfg_tuple_get(vconfig, "options");
+ if (config != NULL) {
+ cfg_map_get(config, "options", &obj);
+ if (obj != NULL)
+ maps[i++] = obj;
+ }
+ maps[i++] = NULL;
+
+ cfg_map_get(zoptions, "type", &typeobj);
+ if (typeobj == NULL)
+ return (ISC_R_FAILURE);
+ if (strcasecmp(cfg_obj_asstring(typeobj), "master") != 0)
+ return (ISC_R_SUCCESS);
+ cfg_map_get(zoptions, "database", &dbobj);
+ if (dbobj != NULL)
+ return (ISC_R_SUCCESS);
+ cfg_map_get(zoptions, "file", &fileobj);
+ if (fileobj == NULL)
+ return (ISC_R_FAILURE);
+ zfile = cfg_obj_asstring(fileobj);
+
+ obj = NULL;
+ if (get_maps(maps, "check-mx", &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKMX;
+ zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKMX;
+ zone_options |= DNS_ZONEOPT_CHECKMXFAIL;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options &= ~DNS_ZONEOPT_CHECKMX;
+ zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
+ } else
+ INSIST(0);
+ } else {
+ zone_options |= DNS_ZONEOPT_CHECKMX;
+ zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-integrity", &obj)) {
+ if (cfg_obj_asboolean(obj))
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
+ else
+ zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
+ } else
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
+
+ obj = NULL;
+ if (get_maps(maps, "check-mx-cname", &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_WARNMXCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options |= DNS_ZONEOPT_WARNMXCNAME;
+ zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
+ } else
+ INSIST(0);
+ } else {
+ zone_options |= DNS_ZONEOPT_WARNMXCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-srv-cname", &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
+ } else
+ INSIST(0);
+ } else {
+ zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
+ }
+
+ obj = NULL;
+ if (get_maps(maps, "check-sibling", &obj)) {
+ if (cfg_obj_asboolean(obj))
+ zone_options |= DNS_ZONEOPT_CHECKSIBLING;
+ else
+ zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
+ }
+
+ obj = NULL;
+ if (get_checknames(maps, &obj)) {
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKNAMES;
+ zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ zone_options |= DNS_ZONEOPT_CHECKNAMES;
+ zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ zone_options &= ~DNS_ZONEOPT_CHECKNAMES;
+ zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
+ } else
+ INSIST(0);
+ } else {
+ zone_options |= DNS_ZONEOPT_CHECKNAMES;
+ zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL;
+ }
+
+ masterformat = dns_masterformat_text;
+ fmtobj = NULL;
+ result = config_get(maps, "masterfile-format", &fmtobj);
+ if (result == ISC_R_SUCCESS) {
+ const char *masterformatstr = cfg_obj_asstring(fmtobj);
+ if (strcasecmp(masterformatstr, "text") == 0)
+ masterformat = dns_masterformat_text;
+ else if (strcasecmp(masterformatstr, "raw") == 0)
+ masterformat = dns_masterformat_raw;
+ else
+ INSIST(0);
+ }
+
+ result = load_zone(mctx, zname, zfile, masterformat, zclass, NULL);
+ if (result != ISC_R_SUCCESS)
+ fprintf(stderr, "%s/%s/%s: %s\n", view, zname, zclass,
+ dns_result_totext(result));
+ return(result);
+}
+
+/*% configure a view */
+static isc_result_t
+configure_view(const char *vclass, const char *view, const cfg_obj_t *config,
+ const cfg_obj_t *vconfig, isc_mem_t *mctx)
+{
+ const cfg_listelt_t *element;
+ const cfg_obj_t *voptions;
+ const cfg_obj_t *zonelist;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+
+ voptions = NULL;
+ if (vconfig != NULL)
+ voptions = cfg_tuple_get(vconfig, "options");
+
+ zonelist = NULL;
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "zone", &zonelist);
+ else
+ (void)cfg_map_get(config, "zone", &zonelist);
+
+ for (element = cfg_list_first(zonelist);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *zconfig = cfg_listelt_value(element);
+ tresult = configure_zone(vclass, view, zconfig, vconfig,
+ config, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ return (result);
+}
+
+
+/*% load zones from the configuration */
+static isc_result_t
+load_zones_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *classobj;
+ const cfg_obj_t *views;
+ const cfg_obj_t *vconfig;
+ const char *vclass;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+
+ views = NULL;
+
+ (void)cfg_map_get(config, "view", &views);
+ for (element = cfg_list_first(views);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const char *vname;
+
+ vclass = "IN";
+ vconfig = cfg_listelt_value(element);
+ if (vconfig != NULL) {
+ classobj = cfg_tuple_get(vconfig, "class");
+ if (cfg_obj_isstring(classobj))
+ vclass = cfg_obj_asstring(classobj);
+ }
+ vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
+ tresult = configure_view(vclass, vname, config, vconfig, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+
+ if (views == NULL) {
+ tresult = configure_view("IN", "_default", config, NULL, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ return (result);
+}
+
+/*% The main processing routine */
+int
+main(int argc, char **argv) {
+ int c;
+ cfg_parser_t *parser = NULL;
+ cfg_obj_t *config = NULL;
+ const char *conffile = NULL;
+ isc_mem_t *mctx = NULL;
+ isc_result_t result;
+ int exit_status = 0;
+ isc_entropy_t *ectx = NULL;
+ isc_boolean_t load_zones = ISC_FALSE;
+
+ isc_commandline_errprint = ISC_FALSE;
+
+ while ((c = isc_commandline_parse(argc, argv, "dhjt:vz")) != EOF) {
+ switch (c) {
+ case 'd':
+ debug++;
+ break;
+
+ case 'j':
+ nomerge = ISC_FALSE;
+ break;
+
+ case 't':
+ result = isc_dir_chroot(isc_commandline_argument);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "isc_dir_chroot: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+ result = isc_dir_chdir("/");
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "isc_dir_chdir: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+ break;
+
+ case 'v':
+ printf(VERSION "\n");
+ exit(0);
+
+ case 'z':
+ load_zones = ISC_TRUE;
+ docheckmx = ISC_FALSE;
+ docheckns = ISC_FALSE;
+ dochecksrv = ISC_FALSE;
+ 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 + 1 < argc)
+ usage();
+ if (argv[isc_commandline_index] != NULL)
+ conffile = argv[isc_commandline_index];
+ if (conffile == NULL || conffile[0] == '\0')
+ conffile = NAMED_CONFFILE;
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(setup_logging(mctx, stdout, &logc) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
+ == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ RUNTIME_CHECK(cfg_parser_create(mctx, logc, &parser) == ISC_R_SUCCESS);
+
+ cfg_parser_setcallback(parser, directory_callback, NULL);
+
+ if (cfg_parse_file(parser, conffile, &cfg_type_namedconf, &config) !=
+ ISC_R_SUCCESS)
+ exit(1);
+
+ result = bind9_check_namedconf(config, logc, mctx);
+ if (result != ISC_R_SUCCESS)
+ exit_status = 1;
+
+ if (result == ISC_R_SUCCESS && load_zones) {
+ result = load_zones_fromconfig(config, mctx);
+ if (result != ISC_R_SUCCESS)
+ exit_status = 1;
+ }
+
+ cfg_obj_destroy(parser, &config);
+
+ cfg_parser_destroy(&parser);
+
+ dns_name_destroy();
+
+ isc_log_destroy(&logc);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mem_destroy(&mctx);
+
+ return (exit_status);
+}
diff --git a/bin/check/named-checkconf.docbook b/bin/check/named-checkconf.docbook
new file mode 100644
index 0000000..5359239
--- /dev/null
+++ b/bin/check/named-checkconf.docbook
@@ -0,0 +1,171 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2002 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-checkconf.docbook,v 1.19 2007/06/19 06:58:03 marka Exp $ -->
+<refentry id="man.named-checkconf">
+ <refentryinfo>
+ <date>June 14, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>named-checkconf</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname><application>named-checkconf</application></refname>
+ <refpurpose>named configuration file syntax checking tool</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>named-checkconf</command>
+ <arg><option>-h</option></arg>
+ <arg><option>-v</option></arg>
+ <arg><option>-j</option></arg>
+ <arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg choice="req">filename</arg>
+ <arg><option>-z</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>named-checkconf</command>
+ checks the syntax, but not the semantics, of a named
+ configuration file.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Print the usage summary and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Chroot to <filename>directory</filename> so that
+ include
+ directives in the configuration file are processed as if
+ run by a similarly chrooted named.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Print the version of the <command>named-checkconf</command>
+ program and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-z</term>
+ <listitem>
+ <para>
+ Perform a test load of all master zones found in
+ <filename>named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-j</term>
+ <listitem>
+ <para>
+ When loading a zonefile read the journal if it exists.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>filename</term>
+ <listitem>
+ <para>
+ The name of the configuration file to be checked. If not
+ specified, it defaults to <filename>/etc/named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para><command>named-checkconf</command>
+ returns an exit status of 1 if
+ errors were detected and 0 otherwise.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named-checkzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/check/named-checkconf.html b/bin/check/named-checkconf.html
new file mode 100644
index 0000000..34bec80
--- /dev/null
+++ b/bin/check/named-checkconf.html
@@ -0,0 +1,96 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2002 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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-checkconf.html,v 1.30 2007/06/20 02:27:32 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named-checkconf</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.named-checkconf"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">named-checkconf</span> &#8212; named configuration file syntax checking tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">named-checkconf</code> [<code class="option">-h</code>] [<code class="option">-v</code>] [<code class="option">-j</code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] {filename} [<code class="option">-z</code>]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543387"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">named-checkconf</strong></span>
+ checks the syntax, but not the semantics, of a named
+ configuration file.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543399"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Print the usage summary and exit.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Chroot to <code class="filename">directory</code> so that
+ include
+ directives in the configuration file are processed as if
+ run by a similarly chrooted named.
+ </p></dd>
+<dt><span class="term">-v</span></dt>
+<dd><p>
+ Print the version of the <span><strong class="command">named-checkconf</strong></span>
+ program and exit.
+ </p></dd>
+<dt><span class="term">-z</span></dt>
+<dd><p>
+ Perform a test load of all master zones found in
+ <code class="filename">named.conf</code>.
+ </p></dd>
+<dt><span class="term">-j</span></dt>
+<dd><p>
+ When loading a zonefile read the journal if it exists.
+ </p></dd>
+<dt><span class="term">filename</span></dt>
+<dd><p>
+ The name of the configuration file to be checked. If not
+ specified, it defaults to <code class="filename">/etc/named.conf</code>.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543507"></a><h2>RETURN VALUES</h2>
+<p><span><strong class="command">named-checkconf</strong></span>
+ returns an exit status of 1 if
+ errors were detected and 0 otherwise.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543518"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named-checkzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543548"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/check/named-checkzone.8 b/bin/check/named-checkzone.8
new file mode 100644
index 0000000..3600755
--- /dev/null
+++ b/bin/check/named-checkzone.8
@@ -0,0 +1,278 @@
+.\" Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2002 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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-checkzone.8,v 1.42 2007/06/20 02:27:32 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: named\-checkzone
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: June 13, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "NAMED\-CHECKZONE" "8" "June 13, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+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\-o\ \fR\fB\fIfilename\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] {zonename} {filename}
+.SH "DESCRIPTION"
+.PP
+\fBnamed\-checkzone\fR
+checks the syntax and integrity of a zone file. It performs the same checks as
+\fBnamed\fR
+does when loading a zone. This makes
+\fBnamed\-checkzone\fR
+useful for checking zone files before configuring them into a name server.
+.PP
+\fBnamed\-compilezone\fR
+is similar to
+\fBnamed\-checkzone\fR, but it always dumps the zone contents to a specified file in a specified format. Additionally, it applies stricter check levels by default, since the dump output will be used as an actual zone file loaded by
+\fBnamed\fR. When manually specified otherwise, the check levels must at least be as strict as those specified in the
+\fBnamed\fR
+configuration file.
+.SH "OPTIONS"
+.PP
+\-d
+.RS 4
+Enable debugging.
+.RE
+.PP
+\-h
+.RS 4
+Print the usage summary and exit.
+.RE
+.PP
+\-q
+.RS 4
+Quiet mode \- exit code only.
+.RE
+.PP
+\-v
+.RS 4
+Print the version of the
+\fBnamed\-checkzone\fR
+program and exit.
+.RE
+.PP
+\-j
+.RS 4
+When loading the zone file read the journal if it exists.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Specify the class of the zone. If not specified "IN" is assumed.
+.RE
+.PP
+\-i \fImode\fR
+.RS 4
+Perform post\-load zone integrity checks. Possible modes are
+\fB"full"\fR
+(default),
+\fB"full\-sibling"\fR,
+\fB"local"\fR,
+\fB"local\-sibling"\fR
+and
+\fB"none"\fR.
+.sp
+Mode
+\fB"full"\fR
+checks that MX records refer to A or AAAA record (both in\-zone and out\-of\-zone hostnames). Mode
+\fB"local"\fR
+only checks MX records which refer to in\-zone hostnames.
+.sp
+Mode
+\fB"full"\fR
+checks that SRV records refer to A or AAAA record (both in\-zone and out\-of\-zone hostnames). Mode
+\fB"local"\fR
+only checks SRV records which refer to in\-zone hostnames.
+.sp
+Mode
+\fB"full"\fR
+checks that delegation NS records refer to A or AAAA record (both in\-zone and out\-of\-zone hostnames). It also checks that glue address records in the zone match those advertised by the child. Mode
+\fB"local"\fR
+only checks NS records which refer to in\-zone hostnames or that some required glue exists, that is when the nameserver is in a child zone.
+.sp
+Mode
+\fB"full\-sibling"\fR
+and
+\fB"local\-sibling"\fR
+disable sibling glue checks but are otherwise the same as
+\fB"full"\fR
+and
+\fB"local"\fR
+respectively.
+.sp
+Mode
+\fB"none"\fR
+disables the checks.
+.RE
+.PP
+\-f \fIformat\fR
+.RS 4
+Specify the format of the zone file. Possible formats are
+\fB"text"\fR
+(default) and
+\fB"raw"\fR.
+.RE
+.PP
+\-F \fIformat\fR
+.RS 4
+Specify the format of the output file specified. Possible formats are
+\fB"text"\fR
+(default) and
+\fB"raw"\fR. For
+\fBnamed\-checkzone\fR, this does not cause any effects unless it dumps the zone contents.
+.RE
+.PP
+\-k \fImode\fR
+.RS 4
+Perform
+\fB"check\-names"\fR
+checks with the specified failure mode. Possible modes are
+\fB"fail"\fR
+(default for
+\fBnamed\-compilezone\fR),
+\fB"warn"\fR
+(default for
+\fBnamed\-checkzone\fR) and
+\fB"ignore"\fR.
+.RE
+.PP
+\-m \fImode\fR
+.RS 4
+Specify whether MX records should be checked to see if they are addresses. Possible modes are
+\fB"fail"\fR,
+\fB"warn"\fR
+(default) and
+\fB"ignore"\fR.
+.RE
+.PP
+\-M \fImode\fR
+.RS 4
+Check if a MX record refers to a CNAME. Possible modes are
+\fB"fail"\fR,
+\fB"warn"\fR
+(default) and
+\fB"ignore"\fR.
+.RE
+.PP
+\-n \fImode\fR
+.RS 4
+Specify whether NS records should be checked to see if they are addresses. Possible modes are
+\fB"fail"\fR
+(default for
+\fBnamed\-compilezone\fR),
+\fB"warn"\fR
+(default for
+\fBnamed\-checkzone\fR) and
+\fB"ignore"\fR.
+.RE
+.PP
+\-o \fIfilename\fR
+.RS 4
+Write zone output to
+\fIfilename\fR. If
+\fIfilename\fR
+is
+\fI\-\fR
+then write to standard out. This is mandatory for
+\fBnamed\-compilezone\fR.
+.RE
+.PP
+\-s \fIstyle\fR
+.RS 4
+Specify the style of the dumped zone file. Possible styles are
+\fB"full"\fR
+(default) and
+\fB"relative"\fR. The full format is most suitable for processing automatically by a separate script. On the other hand, the relative format is more human\-readable and is thus suitable for editing by hand. For
+\fBnamed\-checkzone\fR
+this does not cause any effects unless it dumps the zone contents. It also does not have any meaning if the output format is not text.
+.RE
+.PP
+\-S \fImode\fR
+.RS 4
+Check if a SRV record refers to a CNAME. Possible modes are
+\fB"fail"\fR,
+\fB"warn"\fR
+(default) and
+\fB"ignore"\fR.
+.RE
+.PP
+\-t \fIdirectory\fR
+.RS 4
+Chroot to
+\fIdirectory\fR
+so that include directives in the configuration file are processed as if run by a similarly chrooted named.
+.RE
+.PP
+\-w \fIdirectory\fR
+.RS 4
+chdir to
+\fIdirectory\fR
+so that relative filenames in master file $INCLUDE directives work. This is similar to the directory clause in
+\fInamed.conf\fR.
+.RE
+.PP
+\-D
+.RS 4
+Dump zone file in canonical format. This is always enabled for
+\fBnamed\-compilezone\fR.
+.RE
+.PP
+\-W \fImode\fR
+.RS 4
+Specify whether to check for non\-terminal wildcards. Non\-terminal wildcards are almost always the result of a failure to understand the wildcard matching algorithm (RFC 1034). Possible modes are
+\fB"warn"\fR
+(default) and
+\fB"ignore"\fR.
+.RE
+.PP
+zonename
+.RS 4
+The domain name of the zone being checked.
+.RE
+.PP
+filename
+.RS 4
+The name of the zone file.
+.RE
+.SH "RETURN VALUES"
+.PP
+\fBnamed\-checkzone\fR
+returns an exit status of 1 if errors were detected and 0 otherwise.
+.SH "SEE ALSO"
+.PP
+\fBnamed\fR(8),
+\fBnamed\-checkconf\fR(8),
+RFC 1035,
+BIND 9 Administrator Reference Manual.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2004\-2007 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
new file mode 100644
index 0000000..60f1ee2
--- /dev/null
+++ b/bin/check/named-checkzone.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright (C) 2004-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
+ * 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-checkzone.c,v 1.51 2008/10/24 01:44:48 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/masterdump.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+#include <dns/types.h>
+#include <dns/zone.h>
+
+#include "check-tool.h"
+
+static int quiet = 0;
+static isc_mem_t *mctx = NULL;
+static isc_entropy_t *ectx = NULL;
+dns_zone_t *zone = NULL;
+dns_zonetype_t zonetype = dns_zone_master;
+static int dumpzone = 0;
+static const char *output_filename;
+static char *prog_name = NULL;
+static const dns_master_style_t *outputstyle = NULL;
+static enum { progmode_check, progmode_compile } progmode;
+
+#define ERRRET(result, function) \
+ do { \
+ if (result != ISC_R_SUCCESS) { \
+ if (!quiet) \
+ fprintf(stderr, "%s() returned %s\n", \
+ function, dns_result_totext(result)); \
+ return (result); \
+ } \
+ } while (0)
+
+static void
+usage(void) {
+ fprintf(stderr,
+ "usage: %s [-djqvD] [-c class] [-o output] "
+ "[-f inputformat] [-F outputformat] "
+ "[-t directory] [-w directory] [-k (ignore|warn|fail)] "
+ "[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
+ "[-i (full|full-sibling|local|local-sibling|none)] "
+ "[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
+ "[-W (ignore|warn)] "
+ "zonename filename\n", prog_name);
+ exit(1);
+}
+
+static void
+destroy(void) {
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ dns_name_destroy();
+}
+
+/*% main processing routine */
+int
+main(int argc, char **argv) {
+ int c;
+ char *origin = NULL;
+ char *filename = NULL;
+ isc_log_t *lctx = NULL;
+ isc_result_t result;
+ char classname_in[] = "IN";
+ char *classname = classname_in;
+ const char *workdir = NULL;
+ const char *inputformatstr = NULL;
+ const char *outputformatstr = NULL;
+ dns_masterformat_t inputformat = dns_masterformat_text;
+ dns_masterformat_t outputformat = dns_masterformat_text;
+ FILE *errout = stdout;
+
+ outputstyle = &dns_master_style_full;
+
+ prog_name = strrchr(argv[0], '/');
+ if (prog_name == NULL)
+ prog_name = strrchr(argv[0], '\\');
+ if (prog_name != NULL)
+ prog_name++;
+ else
+ prog_name = argv[0];
+ /*
+ * Libtool doesn't preserve the program name prior to final
+ * installation. Remove the libtool prefix ("lt-").
+ */
+ if (strncmp(prog_name, "lt-", 3) == 0)
+ prog_name += 3;
+ if (strcmp(prog_name, "named-checkzone") == 0)
+ progmode = progmode_check;
+ else if (strcmp(prog_name, "named-compilezone") == 0)
+ progmode = progmode_compile;
+ else
+ INSIST(0);
+
+ /* Compilation specific defaults */
+ if (progmode == progmode_compile) {
+ zone_options |= (DNS_ZONEOPT_CHECKNS |
+ DNS_ZONEOPT_FATALNS |
+ DNS_ZONEOPT_CHECKNAMES |
+ DNS_ZONEOPT_CHECKNAMESFAIL |
+ DNS_ZONEOPT_CHECKWILDCARD);
+ }
+
+#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:"))
+ != EOF) {
+ switch (c) {
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+
+ case 'd':
+ debug++;
+ break;
+
+ case 'i':
+ if (ARGCMP("full")) {
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
+ DNS_ZONEOPT_CHECKSIBLING;
+ docheckmx = ISC_TRUE;
+ docheckns = ISC_TRUE;
+ dochecksrv = ISC_TRUE;
+ } else if (ARGCMP("full-sibling")) {
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
+ zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
+ docheckmx = ISC_TRUE;
+ docheckns = ISC_TRUE;
+ dochecksrv = ISC_TRUE;
+ } else if (ARGCMP("local")) {
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
+ zone_options |= DNS_ZONEOPT_CHECKSIBLING;
+ docheckmx = ISC_FALSE;
+ docheckns = ISC_FALSE;
+ dochecksrv = ISC_FALSE;
+ } else if (ARGCMP("local-sibling")) {
+ zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
+ zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
+ docheckmx = ISC_FALSE;
+ docheckns = ISC_FALSE;
+ dochecksrv = ISC_FALSE;
+ } else if (ARGCMP("none")) {
+ zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
+ zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
+ docheckmx = ISC_FALSE;
+ docheckns = ISC_FALSE;
+ dochecksrv = ISC_FALSE;
+ } else {
+ fprintf(stderr, "invalid argument to -i: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'f':
+ inputformatstr = isc_commandline_argument;
+ break;
+
+ case 'F':
+ outputformatstr = isc_commandline_argument;
+ break;
+
+ case 'j':
+ nomerge = ISC_FALSE;
+ break;
+
+ case 'k':
+ if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_CHECKNAMES;
+ zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
+ } else if (ARGCMP("fail")) {
+ zone_options |= DNS_ZONEOPT_CHECKNAMES |
+ DNS_ZONEOPT_CHECKNAMESFAIL;
+ } else if (ARGCMP("ignore")) {
+ zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
+ DNS_ZONEOPT_CHECKNAMESFAIL);
+ } else {
+ fprintf(stderr, "invalid argument to -k: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'n':
+ if (ARGCMP("ignore")) {
+ zone_options &= ~(DNS_ZONEOPT_CHECKNS|
+ DNS_ZONEOPT_FATALNS);
+ } else if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_CHECKNS;
+ zone_options &= ~DNS_ZONEOPT_FATALNS;
+ } else if (ARGCMP("fail")) {
+ zone_options |= DNS_ZONEOPT_CHECKNS|
+ DNS_ZONEOPT_FATALNS;
+ } else {
+ fprintf(stderr, "invalid argument to -n: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'm':
+ if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_CHECKMX;
+ zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
+ } else if (ARGCMP("fail")) {
+ zone_options |= DNS_ZONEOPT_CHECKMX |
+ DNS_ZONEOPT_CHECKMXFAIL;
+ } else if (ARGCMP("ignore")) {
+ zone_options &= ~(DNS_ZONEOPT_CHECKMX |
+ DNS_ZONEOPT_CHECKMXFAIL);
+ } else {
+ fprintf(stderr, "invalid argument to -m: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ 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));
+ exit(1);
+ }
+ result = isc_dir_chdir("/");
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "isc_dir_chdir: %s\n",
+ isc_result_totext(result));
+ exit(1);
+ }
+ break;
+
+ case 's':
+ if (ARGCMP("full"))
+ outputstyle = &dns_master_style_full;
+ else if (ARGCMP("relative")) {
+ outputstyle = &dns_master_style_default;
+ } else {
+ fprintf(stderr,
+ "unknown or unsupported style: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'o':
+ output_filename = isc_commandline_argument;
+ break;
+
+ case 'v':
+ printf(VERSION "\n");
+ exit(0);
+
+ case 'w':
+ workdir = isc_commandline_argument;
+ break;
+
+ case 'D':
+ dumpzone++;
+ break;
+
+ case 'M':
+ if (ARGCMP("fail")) {
+ zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
+ } else if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_WARNMXCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
+ } else if (ARGCMP("ignore")) {
+ zone_options |= DNS_ZONEOPT_WARNMXCNAME;
+ zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
+ } else {
+ fprintf(stderr, "invalid argument to -M: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'S':
+ if (ARGCMP("fail")) {
+ zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
+ } else if (ARGCMP("warn")) {
+ zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
+ } else if (ARGCMP("ignore")) {
+ zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
+ zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
+ } else {
+ fprintf(stderr, "invalid argument to -S: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'W':
+ if (ARGCMP("warn"))
+ zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
+ else if (ARGCMP("ignore"))
+ zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
+ break;
+
+ case '?':
+ if (isc_commandline_option != '?')
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ prog_name, isc_commandline_option);
+ case 'h':
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n",
+ prog_name, isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (workdir != NULL) {
+ result = isc_dir_chdir(workdir);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "isc_dir_chdir: %s: %s\n",
+ workdir, isc_result_totext(result));
+ exit(1);
+ }
+ }
+
+ if (inputformatstr != NULL) {
+ if (strcasecmp(inputformatstr, "text") == 0)
+ inputformat = dns_masterformat_text;
+ else if (strcasecmp(inputformatstr, "raw") == 0)
+ inputformat = dns_masterformat_raw;
+ else {
+ fprintf(stderr, "unknown file format: %s\n",
+ inputformatstr);
+ exit(1);
+ }
+ }
+
+ if (outputformatstr != NULL) {
+ if (strcasecmp(outputformatstr, "text") == 0)
+ outputformat = dns_masterformat_text;
+ else if (strcasecmp(outputformatstr, "raw") == 0)
+ outputformat = dns_masterformat_raw;
+ else {
+ fprintf(stderr, "unknown file format: %s\n",
+ outputformatstr);
+ exit(1);
+ }
+ }
+
+ if (progmode == progmode_compile) {
+ dumpzone = 1; /* always dump */
+ if (output_filename == NULL) {
+ fprintf(stderr,
+ "output file required, but not specified\n");
+ usage();
+ }
+ }
+
+ if (output_filename != NULL)
+ dumpzone = 1;
+
+ /*
+ * If we are outputing to stdout then send the informational
+ * output to stderr.
+ */
+ if (dumpzone &&
+ (output_filename == NULL ||
+ strcmp(output_filename, "-") == 0 ||
+ strcmp(output_filename, "/dev/fd/1") == 0 ||
+ strcmp(output_filename, "/dev/stdout") == 0))
+ errout = stderr;
+
+ if (isc_commandline_index + 2 != argc)
+ usage();
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ if (!quiet)
+ RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
+ == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
+ == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ origin = argv[isc_commandline_index++];
+ filename = argv[isc_commandline_index++];
+ result = load_zone(mctx, origin, filename, inputformat, classname,
+ &zone);
+
+ if (result == ISC_R_SUCCESS && dumpzone) {
+ if (!quiet && progmode == progmode_compile) {
+ fprintf(errout, "dump zone to %s...", output_filename);
+ fflush(errout);
+ }
+ result = dump_zone(origin, zone, output_filename,
+ outputformat, outputstyle);
+ if (!quiet && progmode == progmode_compile)
+ fprintf(errout, "done\n");
+ }
+
+ if (!quiet && result == ISC_R_SUCCESS)
+ fprintf(errout, "OK\n");
+ destroy();
+ if (lctx != NULL)
+ isc_log_destroy(&lctx);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return ((result == ISC_R_SUCCESS) ? 0 : 1);
+}
diff --git a/bin/check/named-checkzone.docbook b/bin/check/named-checkzone.docbook
new file mode 100644
index 0000000..c5321e2
--- /dev/null
+++ b/bin/check/named-checkzone.docbook
@@ -0,0 +1,455 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2002 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-checkzone.docbook,v 1.34 2007/06/19 06:58:03 marka Exp $ -->
+<refentry id="man.named-checkzone">
+ <refentryinfo>
+ <date>June 13, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>named-checkzone</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname><application>named-checkzone</application></refname>
+ <refname><application>named-compilezone</application></refname>
+ <refpurpose>zone file validity checking or converting tool</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>named-checkzone</command>
+ <arg><option>-d</option></arg>
+ <arg><option>-h</option></arg>
+ <arg><option>-j</option></arg>
+ <arg><option>-q</option></arg>
+ <arg><option>-v</option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-f <replaceable class="parameter">format</replaceable></option></arg>
+ <arg><option>-F <replaceable class="parameter">format</replaceable></option></arg>
+ <arg><option>-i <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-k <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-m <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-M <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-n <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-o <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg><option>-s <replaceable class="parameter">style</replaceable></option></arg>
+ <arg><option>-S <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-w <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-D</option></arg>
+ <arg><option>-W <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="req">zonename</arg>
+ <arg choice="req">filename</arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>named-compilezone</command>
+ <arg><option>-d</option></arg>
+ <arg><option>-j</option></arg>
+ <arg><option>-q</option></arg>
+ <arg><option>-v</option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-C <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-f <replaceable class="parameter">format</replaceable></option></arg>
+ <arg><option>-F <replaceable class="parameter">format</replaceable></option></arg>
+ <arg><option>-i <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-k <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-m <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-n <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg><option>-o <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg><option>-s <replaceable class="parameter">style</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-w <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-D</option></arg>
+ <arg><option>-W <replaceable class="parameter">mode</replaceable></option></arg>
+ <arg choice="req">zonename</arg>
+ <arg choice="req">filename</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>named-checkzone</command>
+ checks the syntax and integrity of a zone file. It performs the
+ same checks as <command>named</command> does when loading a
+ zone. This makes <command>named-checkzone</command> useful for
+ checking zone files before configuring them into a name server.
+ </para>
+ <para>
+ <command>named-compilezone</command> is similar to
+ <command>named-checkzone</command>, but it always dumps the
+ zone contents to a specified file in a specified format.
+ Additionally, it applies stricter check levels by default,
+ since the dump output will be used as an actual zone file
+ loaded by <command>named</command>.
+ When manually specified otherwise, the check levels must at
+ least be as strict as those specified in the
+ <command>named</command> configuration file.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-d</term>
+ <listitem>
+ <para>
+ Enable debugging.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Print the usage summary and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q</term>
+ <listitem>
+ <para>
+ Quiet mode - exit code only.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Print the version of the <command>named-checkzone</command>
+ program and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-j</term>
+ <listitem>
+ <para>
+ When loading the zone file read the journal if it exists.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Specify the class of the zone. If not specified "IN" is assumed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Perform post-load zone integrity checks. Possible modes are
+ <command>"full"</command> (default),
+ <command>"full-sibling"</command>,
+ <command>"local"</command>,
+ <command>"local-sibling"</command> and
+ <command>"none"</command>.
+ </para>
+ <para>
+ Mode <command>"full"</command> checks that MX records
+ refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). Mode <command>"local"</command> only
+ checks MX records which refer to in-zone hostnames.
+ </para>
+ <para>
+ Mode <command>"full"</command> checks that SRV records
+ refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). Mode <command>"local"</command> only
+ checks SRV records which refer to in-zone hostnames.
+ </para>
+ <para>
+ Mode <command>"full"</command> checks that delegation NS
+ records refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). It also checks that glue address records
+ in the zone match those advertised by the child.
+ Mode <command>"local"</command> only checks NS records which
+ refer to in-zone hostnames or that some required glue exists,
+ that is when the nameserver is in a child zone.
+ </para>
+ <para>
+ Mode <command>"full-sibling"</command> and
+ <command>"local-sibling"</command> disable sibling glue
+ checks but are otherwise the same as <command>"full"</command>
+ and <command>"local"</command> respectively.
+ </para>
+ <para>
+ Mode <command>"none"</command> disables the checks.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">format</replaceable></term>
+ <listitem>
+ <para>
+ Specify the format of the zone file.
+ Possible formats are <command>"text"</command> (default)
+ and <command>"raw"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-F <replaceable class="parameter">format</replaceable></term>
+ <listitem>
+ <para>
+ Specify the format of the output file specified.
+ Possible formats are <command>"text"</command> (default)
+ and <command>"raw"</command>.
+ For <command>named-checkzone</command>,
+ this does not cause any effects unless it dumps the zone
+ contents.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Perform <command>"check-names"</command> checks with the
+ specified failure mode.
+ Possible modes are <command>"fail"</command>
+ (default for <command>named-compilezone</command>),
+ <command>"warn"</command>
+ (default for <command>named-checkzone</command>) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Specify whether MX records should be checked to see if they
+ are addresses. Possible modes are <command>"fail"</command>,
+ <command>"warn"</command> (default) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-M <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Check if a MX record refers to a CNAME.
+ Possible modes are <command>"fail"</command>,
+ <command>"warn"</command> (default) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Specify whether NS records should be checked to see if they
+ are addresses.
+ Possible modes are <command>"fail"</command>
+ (default for <command>named-compilezone</command>),
+ <command>"warn"</command>
+ (default for <command>named-checkzone</command>) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-o <replaceable class="parameter">filename</replaceable></term>
+ <listitem>
+ <para>
+ Write zone output to <filename>filename</filename>.
+ If <filename>filename</filename> is <filename>-</filename> then
+ write to standard out.
+ This is mandatory for <command>named-compilezone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">style</replaceable></term>
+ <listitem>
+ <para>
+ Specify the style of the dumped zone file.
+ Possible styles are <command>"full"</command> (default)
+ and <command>"relative"</command>.
+ The full format is most suitable for processing
+ automatically by a separate script.
+ On the other hand, the relative format is more
+ human-readable and is thus suitable for editing by hand.
+ For <command>named-checkzone</command>
+ this does not cause any effects unless it dumps the zone
+ contents.
+ It also does not have any meaning if the output format
+ is not text.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-S <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Check if a SRV record refers to a CNAME.
+ Possible modes are <command>"fail"</command>,
+ <command>"warn"</command> (default) and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Chroot to <filename>directory</filename> so that
+ include
+ directives in the configuration file are processed as if
+ run by a similarly chrooted named.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-w <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ chdir to <filename>directory</filename> so that
+ relative
+ filenames in master file $INCLUDE directives work. This
+ is similar to the directory clause in
+ <filename>named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-D</term>
+ <listitem>
+ <para>
+ Dump zone file in canonical format.
+ This is always enabled for <command>named-compilezone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-W <replaceable class="parameter">mode</replaceable></term>
+ <listitem>
+ <para>
+ Specify whether to check for non-terminal wildcards.
+ Non-terminal wildcards are almost always the result of a
+ failure to understand the wildcard matching algorithm (RFC 1034).
+ Possible modes are <command>"warn"</command> (default)
+ and
+ <command>"ignore"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>zonename</term>
+ <listitem>
+ <para>
+ The domain name of the zone being checked.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>filename</term>
+ <listitem>
+ <para>
+ The name of the zone file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para><command>named-checkzone</command>
+ returns an exit status of 1 if
+ errors were detected and 0 otherwise.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named-checkconf</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>RFC 1035</citetitle>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/check/named-checkzone.html b/bin/check/named-checkzone.html
new file mode 100644
index 0000000..4e0b5ea
--- /dev/null
+++ b/bin/check/named-checkzone.html
@@ -0,0 +1,262 @@
+<!--
+ - Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2002 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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-checkzone.html,v 1.42 2007/06/20 02:27:32 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named-checkzone</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.named-checkzone"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">named-checkzone</span>, <span class="application">named-compilezone</span> &#8212; zone file validity checking or converting tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">named-checkzone</code> [<code class="option">-d</code>] [<code class="option">-h</code>] [<code class="option">-j</code>] [<code class="option">-q</code>] [<code class="option">-v</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>format</code></em></code>] [<code class="option">-F <em class="replaceable"><code>format</code></em></code>] [<code class="option">-i <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-k <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-m <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-M <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-n <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-o <em class="replaceable"><code>filename</code></em></code>] [<code class="option">-s <em class="replaceable"><code>style</code></em></code>] [<code class="option">-S <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-w <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-D</code>] [<code class="option">-W <em class="replaceable"><code>mode</code></em></code>] {zonename} {filename}</p></div>
+<div class="cmdsynopsis"><p><code class="command">named-compilezone</code> [<code class="option">-d</code>] [<code class="option">-j</code>] [<code class="option">-q</code>] [<code class="option">-v</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-C <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-f <em class="replaceable"><code>format</code></em></code>] [<code class="option">-F <em class="replaceable"><code>format</code></em></code>] [<code class="option">-i <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-k <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-m <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-n <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-o <em class="replaceable"><code>filename</code></em></code>] [<code class="option">-s <em class="replaceable"><code>style</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-w <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-D</code>] [<code class="option">-W <em class="replaceable"><code>mode</code></em></code>] {zonename} {filename}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543669"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">named-checkzone</strong></span>
+ checks the syntax and integrity of a zone file. It performs the
+ same checks as <span><strong class="command">named</strong></span> does when loading a
+ zone. This makes <span><strong class="command">named-checkzone</strong></span> useful for
+ checking zone files before configuring them into a name server.
+ </p>
+<p>
+ <span><strong class="command">named-compilezone</strong></span> is similar to
+ <span><strong class="command">named-checkzone</strong></span>, but it always dumps the
+ zone contents to a specified file in a specified format.
+ Additionally, it applies stricter check levels by default,
+ since the dump output will be used as an actual zone file
+ loaded by <span><strong class="command">named</strong></span>.
+ When manually specified otherwise, the check levels must at
+ least be as strict as those specified in the
+ <span><strong class="command">named</strong></span> configuration file.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543704"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-d</span></dt>
+<dd><p>
+ Enable debugging.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Print the usage summary and exit.
+ </p></dd>
+<dt><span class="term">-q</span></dt>
+<dd><p>
+ Quiet mode - exit code only.
+ </p></dd>
+<dt><span class="term">-v</span></dt>
+<dd><p>
+ Print the version of the <span><strong class="command">named-checkzone</strong></span>
+ program and exit.
+ </p></dd>
+<dt><span class="term">-j</span></dt>
+<dd><p>
+ When loading the zone file read the journal if it exists.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Specify the class of the zone. If not specified "IN" is assumed.
+ </p></dd>
+<dt><span class="term">-i <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+<p>
+ Perform post-load zone integrity checks. Possible modes are
+ <span><strong class="command">"full"</strong></span> (default),
+ <span><strong class="command">"full-sibling"</strong></span>,
+ <span><strong class="command">"local"</strong></span>,
+ <span><strong class="command">"local-sibling"</strong></span> and
+ <span><strong class="command">"none"</strong></span>.
+ </p>
+<p>
+ Mode <span><strong class="command">"full"</strong></span> checks that MX records
+ refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). Mode <span><strong class="command">"local"</strong></span> only
+ checks MX records which refer to in-zone hostnames.
+ </p>
+<p>
+ Mode <span><strong class="command">"full"</strong></span> checks that SRV records
+ refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). Mode <span><strong class="command">"local"</strong></span> only
+ checks SRV records which refer to in-zone hostnames.
+ </p>
+<p>
+ Mode <span><strong class="command">"full"</strong></span> checks that delegation NS
+ records refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). It also checks that glue address records
+ in the zone match those advertised by the child.
+ Mode <span><strong class="command">"local"</strong></span> only checks NS records which
+ refer to in-zone hostnames or that some required glue exists,
+ that is when the nameserver is in a child zone.
+ </p>
+<p>
+ Mode <span><strong class="command">"full-sibling"</strong></span> and
+ <span><strong class="command">"local-sibling"</strong></span> disable sibling glue
+ checks but are otherwise the same as <span><strong class="command">"full"</strong></span>
+ and <span><strong class="command">"local"</strong></span> respectively.
+ </p>
+<p>
+ Mode <span><strong class="command">"none"</strong></span> disables the checks.
+ </p>
+</dd>
+<dt><span class="term">-f <em class="replaceable"><code>format</code></em></span></dt>
+<dd><p>
+ Specify the format of the zone file.
+ Possible formats are <span><strong class="command">"text"</strong></span> (default)
+ and <span><strong class="command">"raw"</strong></span>.
+ </p></dd>
+<dt><span class="term">-F <em class="replaceable"><code>format</code></em></span></dt>
+<dd><p>
+ Specify the format of the output file specified.
+ Possible formats are <span><strong class="command">"text"</strong></span> (default)
+ and <span><strong class="command">"raw"</strong></span>.
+ For <span><strong class="command">named-checkzone</strong></span>,
+ this does not cause any effects unless it dumps the zone
+ contents.
+ </p></dd>
+<dt><span class="term">-k <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Perform <span><strong class="command">"check-names"</strong></span> checks with the
+ specified failure mode.
+ Possible modes are <span><strong class="command">"fail"</strong></span>
+ (default for <span><strong class="command">named-compilezone</strong></span>),
+ <span><strong class="command">"warn"</strong></span>
+ (default for <span><strong class="command">named-checkzone</strong></span>) and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">-m <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Specify whether MX records should be checked to see if they
+ are addresses. Possible modes are <span><strong class="command">"fail"</strong></span>,
+ <span><strong class="command">"warn"</strong></span> (default) and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">-M <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Check if a MX record refers to a CNAME.
+ Possible modes are <span><strong class="command">"fail"</strong></span>,
+ <span><strong class="command">"warn"</strong></span> (default) and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Specify whether NS records should be checked to see if they
+ are addresses.
+ Possible modes are <span><strong class="command">"fail"</strong></span>
+ (default for <span><strong class="command">named-compilezone</strong></span>),
+ <span><strong class="command">"warn"</strong></span>
+ (default for <span><strong class="command">named-checkzone</strong></span>) and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">-o <em class="replaceable"><code>filename</code></em></span></dt>
+<dd><p>
+ Write zone output to <code class="filename">filename</code>.
+ If <code class="filename">filename</code> is <code class="filename">-</code> then
+ write to standard out.
+ This is mandatory for <span><strong class="command">named-compilezone</strong></span>.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>style</code></em></span></dt>
+<dd><p>
+ Specify the style of the dumped zone file.
+ Possible styles are <span><strong class="command">"full"</strong></span> (default)
+ and <span><strong class="command">"relative"</strong></span>.
+ The full format is most suitable for processing
+ automatically by a separate script.
+ On the other hand, the relative format is more
+ human-readable and is thus suitable for editing by hand.
+ For <span><strong class="command">named-checkzone</strong></span>
+ this does not cause any effects unless it dumps the zone
+ contents.
+ It also does not have any meaning if the output format
+ is not text.
+ </p></dd>
+<dt><span class="term">-S <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Check if a SRV record refers to a CNAME.
+ Possible modes are <span><strong class="command">"fail"</strong></span>,
+ <span><strong class="command">"warn"</strong></span> (default) and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Chroot to <code class="filename">directory</code> so that
+ include
+ directives in the configuration file are processed as if
+ run by a similarly chrooted named.
+ </p></dd>
+<dt><span class="term">-w <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ chdir to <code class="filename">directory</code> so that
+ relative
+ filenames in master file $INCLUDE directives work. This
+ is similar to the directory clause in
+ <code class="filename">named.conf</code>.
+ </p></dd>
+<dt><span class="term">-D</span></dt>
+<dd><p>
+ Dump zone file in canonical format.
+ This is always enabled for <span><strong class="command">named-compilezone</strong></span>.
+ </p></dd>
+<dt><span class="term">-W <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Specify whether to check for non-terminal wildcards.
+ Non-terminal wildcards are almost always the result of a
+ failure to understand the wildcard matching algorithm (RFC 1034).
+ Possible modes are <span><strong class="command">"warn"</strong></span> (default)
+ and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">zonename</span></dt>
+<dd><p>
+ The domain name of the zone being checked.
+ </p></dd>
+<dt><span class="term">filename</span></dt>
+<dd><p>
+ The name of the zone file.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544325"></a><h2>RETURN VALUES</h2>
+<p><span><strong class="command">named-checkzone</strong></span>
+ returns an exit status of 1 if
+ errors were detected and 0 otherwise.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544337"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named-checkconf</span>(8)</span>,
+ <em class="citetitle">RFC 1035</em>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544370"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/check/win32/checktool.dsp b/bin/check/win32/checktool.dsp
new file mode 100644
index 0000000..0d0afc5
--- /dev/null
+++ b/bin/check/win32/checktool.dsp
@@ -0,0 +1,113 @@
+# Microsoft Developer Studio Project File - Name="checktool" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static-Link Library" 0x0104
+
+CFG=checktool - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "checktool.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "checktool.mak" CFG="checktool - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "checktool - Win32 Release" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE "checktool - Win32 Debug" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "checktool - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /YX /FD /c /Fdchecktool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/checktool.lib"
+
+!ELSEIF "$(CFG)" == "checktool - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR /YX /FD /GZ /c /Fdchecktool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug out:"Debug/checktool.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "checktool - Win32 Release"
+# Name "checktool - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\check-tool.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/check/win32/checktool.dsw b/bin/check/win32/checktool.dsw
new file mode 100644
index 0000000..bb139e7
--- /dev/null
+++ b/bin/check/win32/checktool.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "checktool"=".\checktool.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/check/win32/namedcheckconf.dsp b/bin/check/win32/namedcheckconf.dsp
new file mode 100644
index 0000000..b0240d4
--- /dev/null
+++ b/bin/check/win32/namedcheckconf.dsp
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="namedcheckconf" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=namedcheckconf - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "namedcheckconf.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "namedcheckconf.mak" CFG="namedcheckconf - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "namedcheckconf - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "namedcheckconf - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "namedcheckconf - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/checktool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/named-checkconf.exe"
+
+!ELSEIF "$(CFG)" == "namedcheckconf - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/checktool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/named-checkconf.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "namedcheckconf - Win32 Release"
+# Name "namedcheckconf - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\named-checkconf.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\check-tool.h"
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/check/win32/namedcheckconf.dsw b/bin/check/win32/namedcheckconf.dsw
new file mode 100644
index 0000000..d7b794f
--- /dev/null
+++ b/bin/check/win32/namedcheckconf.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "namedcheckconf"=".\namedcheckconf.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/check/win32/namedcheckconf.mak b/bin/check/win32/namedcheckconf.mak
new file mode 100644
index 0000000..3d98e01
--- /dev/null
+++ b/bin/check/win32/namedcheckconf.mak
@@ -0,0 +1,404 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on namedcheckconf.dsp
+!IF "$(CFG)" == ""
+CFG=namedcheckconf - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to namedcheckconf - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "namedcheckconf - Win32 Release" && "$(CFG)" != "namedcheckconf - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "namedcheckconf.mak" CFG="namedcheckconf - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "namedcheckconf - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "namedcheckconf - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "namedcheckconf - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "namedcheckconf - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+# Begin Custom Macros
+OutDir=.\Release
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\named-checkconf.exe" "$(OUTDIR)\namedcheckconf.bsc"
+
+!ELSE
+
+ALL : "libdns - Win32 Release" "libisccfg - Win32 Release" "libisc - Win32 Release" "..\..\..\Build\Release\named-checkconf.exe" "$(OUTDIR)\namedcheckconf.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - Win32 ReleaseCLEAN" "libisccfg - Win32 ReleaseCLEAN" "libdns - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\check-tool.obj"
+ -@erase "$(INTDIR)\check-tool.sbr"
+ -@erase "$(INTDIR)\named-checkconf.obj"
+ -@erase "$(INTDIR)\named-checkconf.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(OUTDIR)\namedcheckconf.bsc"
+ -@erase "..\..\..\Build\Release\named-checkconf.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\namedcheckconf.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\namedcheckconf.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\check-tool.sbr" \
+ "$(INTDIR)\named-checkconf.sbr"
+
+"$(OUTDIR)\namedcheckconf.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named-checkconf.pdb" /machine:I386 /out:"../../../Build/Release/named-checkconf.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\check-tool.obj" \
+ "$(INTDIR)\named-checkconf.obj" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib"
+
+"..\..\..\Build\Release\named-checkconf.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "namedcheckconf - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\named-checkconf.exe" "$(OUTDIR)\namedcheckconf.bsc"
+
+!ELSE
+
+ALL : "libdns - Win32 Debug" "libisccfg - Win32 Debug" "libisc - Win32 Debug" "..\..\..\Build\Debug\named-checkconf.exe" "$(OUTDIR)\namedcheckconf.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - Win32 DebugCLEAN" "libisccfg - Win32 DebugCLEAN" "libdns - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\check-tool.obj"
+ -@erase "$(INTDIR)\check-tool.sbr"
+ -@erase "$(INTDIR)\named-checkconf.obj"
+ -@erase "$(INTDIR)\named-checkconf.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\named-checkconf.pdb"
+ -@erase "$(OUTDIR)\namedcheckconf.bsc"
+ -@erase "..\..\..\Build\Debug\named-checkconf.exe"
+ -@erase "..\..\..\Build\Debug\named-checkconf.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/isccfg/include" /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\namedcheckconf.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\check-tool.sbr" \
+ "$(INTDIR)\named-checkconf.sbr"
+
+"$(OUTDIR)\namedcheckconf.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named-checkconf.pdb" /debug /machine:I386 /out:"../../../Build/Debug/named-checkconf.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\check-tool.obj" \
+ "$(INTDIR)\named-checkconf.obj" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib"
+
+"..\..\..\Build\Debug\named-checkconf.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("namedcheckconf.dep")
+!INCLUDE "namedcheckconf.dep"
+!ELSE
+!MESSAGE Warning: cannot find "namedcheckconf.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "namedcheckconf - Win32 Release" || "$(CFG)" == "namedcheckconf - Win32 Debug"
+SOURCE="..\check-tool.c"
+
+"$(INTDIR)\check-tool.obj" "$(INTDIR)\check-tool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+SOURCE="..\named-checkconf.c"
+
+"$(INTDIR)\named-checkconf.obj" "$(INTDIR)\named-checkconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!IF "$(CFG)" == "namedcheckconf - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\check\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ELSEIF "$(CFG)" == "namedcheckconf - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\check\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "namedcheckconf - Win32 Release"
+
+"libisccfg - Win32 Release" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Release"
+ cd "..\..\..\bin\check\win32"
+
+"libisccfg - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ELSEIF "$(CFG)" == "namedcheckconf - Win32 Debug"
+
+"libisccfg - Win32 Debug" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Debug"
+ cd "..\..\..\bin\check\win32"
+
+"libisccfg - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "namedcheckconf - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\..\bin\check\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ELSEIF "$(CFG)" == "namedcheckconf - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\..\bin\check\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/check/win32/namedcheckzone.dsp b/bin/check/win32/namedcheckzone.dsp
new file mode 100644
index 0000000..2b64144
--- /dev/null
+++ b/bin/check/win32/namedcheckzone.dsp
@@ -0,0 +1,108 @@
+# Microsoft Developer Studio Project File - Name="namedcheckzone" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=namedcheckzone - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "namedcheckzone.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "namedcheckzone.mak" CFG="namedcheckzone - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "namedcheckzone - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "namedcheckzone - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "namedcheckzone - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /YX /FD /c
+# SUBTRACT CPP /Fr
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/checktool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/named-checkzone.exe"
+
+!ELSEIF "$(CFG)" == "namedcheckzone - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/checktool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/named-checkzone.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "namedcheckzone - Win32 Release"
+# Name "namedcheckzone - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\named-checkzone.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\check-tool.h"
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/check/win32/namedcheckzone.dsw b/bin/check/win32/namedcheckzone.dsw
new file mode 100644
index 0000000..d723eb5
--- /dev/null
+++ b/bin/check/win32/namedcheckzone.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "namedcheckzone"=".\namedcheckzone.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/check/win32/namedcheckzone.mak b/bin/check/win32/namedcheckzone.mak
new file mode 100644
index 0000000..810a60e
--- /dev/null
+++ b/bin/check/win32/namedcheckzone.mak
@@ -0,0 +1,404 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on namedcheckzone.dsp
+!IF "$(CFG)" == ""
+CFG=namedcheckzone - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to namedcheckzone - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "namedcheckzone - Win32 Release" && "$(CFG)" != "namedcheckzone - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "namedcheckzone.mak" CFG="namedcheckzone - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "namedcheckzone - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "namedcheckzone - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "namedcheckzone - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "namedcheckzone - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\named-checkzone.exe"
+
+!ELSE
+
+ALL : "libisc - Win32 Release" "libdns - Win32 Release" "..\..\..\Build\Release\named-checkzone.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\check-tool.obj"
+ -@erase "$(INTDIR)\named-checkzone.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\named-checkzone.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /Fp"$(INTDIR)\namedcheckzone.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\namedcheckzone.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named-checkzone.pdb" /machine:I386 /out:"../../../Build/Release/named-checkzone.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\check-tool.obj" \
+ "$(INTDIR)\named-checkzone.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib"
+
+"..\..\..\Build\Release\named-checkzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "namedcheckzone - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\named-checkzone.exe" "$(OUTDIR)\namedcheckzone.bsc"
+
+!ELSE
+
+ALL : "libisc - Win32 Debug" "libdns - Win32 Debug" "..\..\..\Build\Debug\named-checkzone.exe" "$(OUTDIR)\namedcheckzone.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 DebugCLEAN" "libisc - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\check-tool.obj"
+ -@erase "$(INTDIR)\check-tool.sbr"
+ -@erase "$(INTDIR)\named-checkzone.obj"
+ -@erase "$(INTDIR)\named-checkzone.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\named-checkzone.pdb"
+ -@erase "$(OUTDIR)\namedcheckzone.bsc"
+ -@erase "..\..\..\Build\Debug\named-checkzone.exe"
+ -@erase "..\..\..\Build\Debug\named-checkzone.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/isccfg/include" /D "_DEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\namedcheckzone.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\check-tool.sbr" \
+ "$(INTDIR)\named-checkzone.sbr"
+
+"$(OUTDIR)\namedcheckzone.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named-checkzone.pdb" /debug /machine:I386 /out:"../../../Build/Debug/named-checkzone.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\check-tool.obj" \
+ "$(INTDIR)\named-checkzone.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib"
+
+"..\..\..\Build\Debug\named-checkzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("namedcheckzone.dep")
+!INCLUDE "namedcheckzone.dep"
+!ELSE
+!MESSAGE Warning: cannot find "namedcheckzone.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "namedcheckzone - Win32 Release" || "$(CFG)" == "namedcheckzone - Win32 Debug"
+SOURCE="..\check-tool.c"
+
+!IF "$(CFG)" == "namedcheckzone - Win32 Release"
+
+
+"$(INTDIR)\check-tool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "namedcheckzone - Win32 Debug"
+
+
+"$(INTDIR)\check-tool.obj" "$(INTDIR)\check-tool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE="..\named-checkzone.c"
+
+!IF "$(CFG)" == "namedcheckzone - Win32 Release"
+
+
+"$(INTDIR)\named-checkzone.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "namedcheckzone - Win32 Debug"
+
+
+"$(INTDIR)\named-checkzone.obj" "$(INTDIR)\named-checkzone.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "namedcheckzone - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\..\bin\check\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ELSEIF "$(CFG)" == "namedcheckzone - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\..\bin\check\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "namedcheckzone - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\check\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ELSEIF "$(CFG)" == "namedcheckzone - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\check\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\check\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in
new file mode 100644
index 0000000..bc9d34f
--- /dev/null
+++ b/bin/dig/Makefile.in
@@ -0,0 +1,101 @@
+# Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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.41 2007/06/19 23:46:59 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} ${BIND9_INCLUDES} \
+ ${ISC_INCLUDES} ${LWRES_INCLUDES}
+
+CDEFINES = -DVERSION=\"${VERSION}\"
+CWARNINGS =
+
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+LWRESLIBS = ../../lib/lwres/liblwres.@A@
+
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS} \
+ ${LWRESDEPLIBS}
+
+LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCLIBS} \
+ ${ISCCFGLIBS} @IDNLIBS@ @LIBS@
+
+SUBDIRS =
+
+TARGETS = dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@
+
+OBJS = dig.@O@ dighost.@O@ host.@O@ nslookup.@O@
+
+UOBJS =
+
+SRCS = dig.c dighost.c host.c nslookup.c
+
+MANPAGES = dig.1 host.1 nslookup.1
+
+HTMLPAGES = dig.html host.html nslookup.html
+
+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}
+
+host@EXEEXT@: host.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ host.@O@ dighost.@O@ ${UOBJS} ${LIBS}
+
+nslookup@EXEEXT@: nslookup.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ nslookup.@O@ dighost.@O@ ${UOBJS} ${LIBS}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1
+
+install:: dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
+ dig@EXEEXT@ ${DESTDIR}${bindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
+ host@EXEEXT@ ${DESTDIR}${bindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
+ nslookup@EXEEXT@ ${DESTDIR}${bindir}
+ for m in ${MANPAGES}; do \
+ ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man1; \
+ done
diff --git a/bin/dig/dig.1 b/bin/dig/dig.1
new file mode 100644
index 0000000..436740b
--- /dev/null
+++ b/bin/dig/dig.1
@@ -0,0 +1,568 @@
+.\" Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: dig.1,v 1.50 2008/10/14 01:11:35 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: dig
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "DIG" "1" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+dig \- DNS lookup utility
+.SH "SYNOPSIS"
+.HP 4
+\fBdig\fR [@server] [\fB\-b\ \fR\fB\fIaddress\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIfilename\fR\fR] [\fB\-k\ \fR\fB\fIfilename\fR\fR] [\fB\-m\fR] [\fB\-p\ \fR\fB\fIport#\fR\fR] [\fB\-q\ \fR\fB\fIname\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-x\ \fR\fB\fIaddr\fR\fR] [\fB\-y\ \fR\fB\fI[hmac:]\fR\fIname:key\fR\fR] [\fB\-4\fR] [\fB\-6\fR] [name] [type] [class] [queryopt...]
+.HP 4
+\fBdig\fR [\fB\-h\fR]
+.HP 4
+\fBdig\fR [global\-queryopt...] [query...]
+.SH "DESCRIPTION"
+.PP
+\fBdig\fR
+(domain information groper) is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried. Most DNS administrators use
+\fBdig\fR
+to troubleshoot DNS problems because of its flexibility, ease of use and clarity of output. Other lookup tools tend to have less functionality than
+\fBdig\fR.
+.PP
+Although
+\fBdig\fR
+is normally used with command\-line arguments, it also has a batch mode of operation for reading lookup requests from a file. A brief summary of its command\-line arguments and options is printed when the
+\fB\-h\fR
+option is given. Unlike earlier versions, the BIND 9 implementation of
+\fBdig\fR
+allows multiple lookups to be issued from the command line.
+.PP
+Unless it is told to query a specific name server,
+\fBdig\fR
+will try each of the servers listed in
+\fI/etc/resolv.conf\fR.
+.PP
+When no command line arguments or options are given,
+\fBdig\fR
+will perform an NS query for "." (the root).
+.PP
+It is possible to set per\-user defaults for
+\fBdig\fR
+via
+\fI${HOME}/.digrc\fR. This file is read and any options in it are applied before the command line arguments.
+.PP
+The IN and CH class names overlap with the IN and CH top level domains names. Either use the
+\fB\-t\fR
+and
+\fB\-c\fR
+options to specify the type and class, use the
+\fB\-q\fR
+the specify the domain name, or use "IN." and "CH." when looking up these top level domains.
+.SH "SIMPLE USAGE"
+.PP
+A typical invocation of
+\fBdig\fR
+looks like:
+.sp
+.RS 4
+.nf
+ dig @server name type
+.fi
+.RE
+.sp
+where:
+.PP
+\fBserver\fR
+.RS 4
+is the name or IP address of the name server to query. This can be an IPv4 address in dotted\-decimal notation or an IPv6 address in colon\-delimited notation. When the supplied
+\fIserver\fR
+argument is a hostname,
+\fBdig\fR
+resolves that name before querying that name server. If no
+\fIserver\fR
+argument is provided,
+\fBdig\fR
+consults
+\fI/etc/resolv.conf\fR
+and queries the name servers listed there. The reply from the name server that responds is displayed.
+.RE
+.PP
+\fBname\fR
+.RS 4
+is the name of the resource record that is to be looked up.
+.RE
+.PP
+\fBtype\fR
+.RS 4
+indicates what type of query is required \(em ANY, A, MX, SIG, etc.
+\fItype\fR
+can be any valid query type. If no
+\fItype\fR
+argument is supplied,
+\fBdig\fR
+will perform a lookup for an A record.
+.RE
+.SH "OPTIONS"
+.PP
+The
+\fB\-b\fR
+option sets the source IP address of the query to
+\fIaddress\fR. This must be a valid address on one of the host's network interfaces or "0.0.0.0" or "::". An optional port may be specified by appending "#<port>"
+.PP
+The default query class (IN for internet) is overridden by the
+\fB\-c\fR
+option.
+\fIclass\fR
+is any valid class, such as HS for Hesiod records or CH for Chaosnet records.
+.PP
+The
+\fB\-f\fR
+option makes
+\fBdig \fR
+operate in batch mode by reading a list of lookup requests to process from the file
+\fIfilename\fR. The file contains a number of queries, one per line. Each entry in the file should be organized in the same way they would be presented as queries to
+\fBdig\fR
+using the command\-line interface.
+.PP
+The
+\fB\-m\fR
+option enables memory usage debugging.
+.PP
+If a non\-standard port number is to be queried, the
+\fB\-p\fR
+option is used.
+\fIport#\fR
+is the port number that
+\fBdig\fR
+will send its queries instead of the standard DNS port number 53. This option would be used to test a name server that has been configured to listen for queries on a non\-standard port number.
+.PP
+The
+\fB\-4\fR
+option forces
+\fBdig\fR
+to only use IPv4 query transport. The
+\fB\-6\fR
+option forces
+\fBdig\fR
+to only use IPv6 query transport.
+.PP
+The
+\fB\-t\fR
+option sets the query type to
+\fItype\fR. It can be any valid query type which is supported in BIND 9. The default query type is "A", unless the
+\fB\-x\fR
+option is supplied to indicate a reverse lookup. A zone transfer can be requested by specifying a type of AXFR. When an incremental zone transfer (IXFR) is required,
+\fItype\fR
+is set to
+ixfr=N. The incremental zone transfer will contain the changes made to the zone since the serial number in the zone's SOA record was
+\fIN\fR.
+.PP
+The
+\fB\-q\fR
+option sets the query name to
+\fIname\fR. This useful do distinguish the
+\fIname\fR
+from other arguments.
+.PP
+Reverse lookups \(em mapping addresses to names \(em are simplified by the
+\fB\-x\fR
+option.
+\fIaddr\fR
+is an IPv4 address in dotted\-decimal notation, or a colon\-delimited IPv6 address. When this option is used, there is no need to provide the
+\fIname\fR,
+\fIclass\fR
+and
+\fItype\fR
+arguments.
+\fBdig\fR
+automatically performs a lookup for a name like
+11.12.13.10.in\-addr.arpa
+and sets the query type and class to PTR and IN respectively. By default, IPv6 addresses are looked up using nibble format under the IP6.ARPA domain. To use the older RFC1886 method using the IP6.INT domain specify the
+\fB\-i\fR
+option. Bit string labels (RFC2874) are now experimental and are not attempted.
+.PP
+To sign the DNS queries sent by
+\fBdig\fR
+and their responses using transaction signatures (TSIG), specify a TSIG key file using the
+\fB\-k\fR
+option. You can also specify the TSIG key itself on the command line using the
+\fB\-y\fR
+option;
+\fIhmac\fR
+is the type of the TSIG, default HMAC\-MD5,
+\fIname\fR
+is the name of the TSIG key and
+\fIkey\fR
+is the actual key. The key is a base\-64 encoded string, typically generated by
+\fBdnssec\-keygen\fR(8). Caution should be taken when using the
+\fB\-y\fR
+option on multi\-user systems as the key can be visible in the output from
+\fBps\fR(1)
+or in the shell's history file. When using TSIG authentication with
+\fBdig\fR, the name server that is queried needs to know the key and algorithm that is being used. In BIND, this is done by providing appropriate
+\fBkey\fR
+and
+\fBserver\fR
+statements in
+\fInamed.conf\fR.
+.SH "QUERY OPTIONS"
+.PP
+\fBdig\fR
+provides a number of query options which affect the way in which lookups are made and the results displayed. Some of these set or reset flag bits in the query header, some determine which sections of the answer get printed, and others determine the timeout and retry strategies.
+.PP
+Each query option is identified by a keyword preceded by a plus sign (+). Some keywords set or reset an option. These may be preceded by the string
+no
+to negate the meaning of that keyword. Other keywords assign values to options like the timeout interval. They have the form
+\fB+keyword=value\fR. The query options are:
+.PP
+\fB+[no]tcp\fR
+.RS 4
+Use [do not use] TCP when querying name servers. The default behavior is to use UDP unless an AXFR or IXFR query is requested, in which case a TCP connection is used.
+.RE
+.PP
+\fB+[no]vc\fR
+.RS 4
+Use [do not use] TCP when querying name servers. This alternate syntax to
+\fI+[no]tcp\fR
+is provided for backwards compatibility. The "vc" stands for "virtual circuit".
+.RE
+.PP
+\fB+[no]ignore\fR
+.RS 4
+Ignore truncation in UDP responses instead of retrying with TCP. By default, TCP retries are performed.
+.RE
+.PP
+\fB+domain=somename\fR
+.RS 4
+Set the search list to contain the single domain
+\fIsomename\fR, as if specified in a
+\fBdomain\fR
+directive in
+\fI/etc/resolv.conf\fR, and enable search list processing as if the
+\fI+search\fR
+option were given.
+.RE
+.PP
+\fB+[no]search\fR
+.RS 4
+Use [do not use] the search list defined by the searchlist or domain directive in
+\fIresolv.conf\fR
+(if any). The search list is not used by default.
+.RE
+.PP
+\fB+[no]showsearch\fR
+.RS 4
+Perform [do not perform] a search showing intermediate results.
+.RE
+.PP
+\fB+[no]defname\fR
+.RS 4
+Deprecated, treated as a synonym for
+\fI+[no]search\fR
+.RE
+.PP
+\fB+[no]aaonly\fR
+.RS 4
+Sets the "aa" flag in the query.
+.RE
+.PP
+\fB+[no]aaflag\fR
+.RS 4
+A synonym for
+\fI+[no]aaonly\fR.
+.RE
+.PP
+\fB+[no]adflag\fR
+.RS 4
+Set [do not set] the AD (authentic data) bit in the query. The AD bit currently has a standard meaning only in responses, not in queries, but the ability to set the bit in the query is provided for completeness.
+.RE
+.PP
+\fB+[no]cdflag\fR
+.RS 4
+Set [do not set] the CD (checking disabled) bit in the query. This requests the server to not perform DNSSEC validation of responses.
+.RE
+.PP
+\fB+[no]cl\fR
+.RS 4
+Display [do not display] the CLASS when printing the record.
+.RE
+.PP
+\fB+[no]ttlid\fR
+.RS 4
+Display [do not display] the TTL when printing the record.
+.RE
+.PP
+\fB+[no]recurse\fR
+.RS 4
+Toggle the setting of the RD (recursion desired) bit in the query. This bit is set by default, which means
+\fBdig\fR
+normally sends recursive queries. Recursion is automatically disabled when the
+\fI+nssearch\fR
+or
+\fI+trace\fR
+query options are used.
+.RE
+.PP
+\fB+[no]nssearch\fR
+.RS 4
+When this option is set,
+\fBdig\fR
+attempts to find the authoritative name servers for the zone containing the name being looked up and display the SOA record that each name server has for the zone.
+.RE
+.PP
+\fB+[no]trace\fR
+.RS 4
+Toggle tracing of the delegation path from the root name servers for the name being looked up. Tracing is disabled by default. When tracing is enabled,
+\fBdig\fR
+makes iterative queries to resolve the name being looked up. It will follow referrals from the root servers, showing the answer from each server that was used to resolve the lookup.
+.RE
+.PP
+\fB+[no]cmd\fR
+.RS 4
+Toggles the printing of the initial comment in the output identifying the version of
+\fBdig\fR
+and the query options that have been applied. This comment is printed by default.
+.RE
+.PP
+\fB+[no]short\fR
+.RS 4
+Provide a terse answer. The default is to print the answer in a verbose form.
+.RE
+.PP
+\fB+[no]identify\fR
+.RS 4
+Show [or do not show] the IP address and port number that supplied the answer when the
+\fI+short\fR
+option is enabled. If short form answers are requested, the default is not to show the source address and port number of the server that provided the answer.
+.RE
+.PP
+\fB+[no]comments\fR
+.RS 4
+Toggle the display of comment lines in the output. The default is to print comments.
+.RE
+.PP
+\fB+[no]stats\fR
+.RS 4
+This query option toggles the printing of statistics: when the query was made, the size of the reply and so on. The default behavior is to print the query statistics.
+.RE
+.PP
+\fB+[no]qr\fR
+.RS 4
+Print [do not print] the query as it is sent. By default, the query is not printed.
+.RE
+.PP
+\fB+[no]question\fR
+.RS 4
+Print [do not print] the question section of a query when an answer is returned. The default is to print the question section as a comment.
+.RE
+.PP
+\fB+[no]answer\fR
+.RS 4
+Display [do not display] the answer section of a reply. The default is to display it.
+.RE
+.PP
+\fB+[no]authority\fR
+.RS 4
+Display [do not display] the authority section of a reply. The default is to display it.
+.RE
+.PP
+\fB+[no]additional\fR
+.RS 4
+Display [do not display] the additional section of a reply. The default is to display it.
+.RE
+.PP
+\fB+[no]all\fR
+.RS 4
+Set or clear all display flags.
+.RE
+.PP
+\fB+time=T\fR
+.RS 4
+Sets the timeout for a query to
+\fIT\fR
+seconds. The default timeout is 5 seconds. An attempt to set
+\fIT\fR
+to less than 1 will result in a query timeout of 1 second being applied.
+.RE
+.PP
+\fB+tries=T\fR
+.RS 4
+Sets the number of times to try UDP queries to server to
+\fIT\fR
+instead of the default, 3. If
+\fIT\fR
+is less than or equal to zero, the number of tries is silently rounded up to 1.
+.RE
+.PP
+\fB+retry=T\fR
+.RS 4
+Sets the number of times to retry UDP queries to server to
+\fIT\fR
+instead of the default, 2. Unlike
+\fI+tries\fR, this does not include the initial query.
+.RE
+.PP
+\fB+ndots=D\fR
+.RS 4
+Set the number of dots that have to appear in
+\fIname\fR
+to
+\fID\fR
+for it to be considered absolute. The default value is that defined using the ndots statement in
+\fI/etc/resolv.conf\fR, or 1 if no ndots statement is present. Names with fewer dots are interpreted as relative names and will be searched for in the domains listed in the
+\fBsearch\fR
+or
+\fBdomain\fR
+directive in
+\fI/etc/resolv.conf\fR.
+.RE
+.PP
+\fB+bufsize=B\fR
+.RS 4
+Set the UDP message buffer size advertised using EDNS0 to
+\fIB\fR
+bytes. The maximum and minimum sizes of this buffer are 65535 and 0 respectively. Values outside this range are rounded up or down appropriately. Values other than zero will cause a EDNS query to be sent.
+.RE
+.PP
+\fB+edns=#\fR
+.RS 4
+Specify the EDNS version to query with. Valid values are 0 to 255. Setting the EDNS version will cause a EDNS query to be sent.
+\fB+noedns\fR
+clears the remembered EDNS version.
+.RE
+.PP
+\fB+[no]multiline\fR
+.RS 4
+Print records like the SOA records in a verbose multi\-line format with human\-readable comments. The default is to print each record on a single line, to facilitate machine parsing of the
+\fBdig\fR
+output.
+.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.
+.RE
+.PP
+\fB+[no]besteffort\fR
+.RS 4
+Attempt to display the contents of messages which are malformed. The default is to not display malformed answers.
+.RE
+.PP
+\fB+[no]dnssec\fR
+.RS 4
+Requests DNSSEC records be sent by setting the DNSSEC OK bit (DO) in the OPT record in the additional section of the query.
+.RE
+.PP
+\fB+[no]sigchase\fR
+.RS 4
+Chase DNSSEC signature chains. Requires dig be compiled with \-DDIG_SIGCHASE.
+.RE
+.PP
+\fB+trusted\-key=####\fR
+.RS 4
+Specifies a file containing trusted keys to be used with
+\fB+sigchase\fR. Each DNSKEY record must be on its own line.
+.sp
+If not specified
+\fBdig\fR
+will look for
+\fI/etc/trusted\-key.key\fR
+then
+\fItrusted\-key.key\fR
+in the current directory.
+.sp
+Requires dig be compiled with \-DDIG_SIGCHASE.
+.RE
+.PP
+\fB+[no]topdown\fR
+.RS 4
+When chasing DNSSEC signature chains perform a top\-down validation. Requires dig be compiled with \-DDIG_SIGCHASE.
+.RE
+.PP
+\fB+[no]nsid\fR
+.RS 4
+Include an EDNS name server ID request when sending a query.
+.RE
+.SH "MULTIPLE QUERIES"
+.PP
+The BIND 9 implementation of
+\fBdig \fR
+supports specifying multiple queries on the command line (in addition to supporting the
+\fB\-f\fR
+batch file option). Each of those queries can be supplied with its own set of flags, options and query options.
+.PP
+In this case, each
+\fIquery\fR
+argument represent an individual query in the command\-line syntax described above. Each consists of any of the standard options and flags, the name to be looked up, an optional query type and class and any query options that should be applied to that query.
+.PP
+A global set of query options, which should be applied to all queries, can also be supplied. These global query options must precede the first tuple of name, class, type, options, flags, and query options supplied on the command line. Any global query options (except the
+\fB+[no]cmd\fR
+option) can be overridden by a query\-specific set of query options. For example:
+.sp
+.RS 4
+.nf
+dig +qr www.isc.org any \-x 127.0.0.1 isc.org ns +noqr
+.fi
+.RE
+.sp
+shows how
+\fBdig\fR
+could be used from the command line to make three lookups: an ANY query for
+www.isc.org, a reverse lookup of 127.0.0.1 and a query for the NS records of
+isc.org. A global query option of
+\fI+qr\fR
+is applied, so that
+\fBdig\fR
+shows the initial query it made for each lookup. The final query has a local query option of
+\fI+noqr\fR
+which means that
+\fBdig\fR
+will not print the initial query when it looks up the NS records for
+isc.org.
+.SH "IDN SUPPORT"
+.PP
+If
+\fBdig\fR
+has been built with IDN (internationalized domain name) support, it can accept and display non\-ASCII domain names.
+\fBdig\fR
+appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server. If you'd like to turn off the IDN support for some reason, defines the
+\fBIDN_DISABLE\fR
+environment variable. The IDN support is disabled if the variable is set when
+\fBdig\fR
+runs.
+.SH "FILES"
+.PP
+\fI/etc/resolv.conf\fR
+.PP
+\fI${HOME}/.digrc\fR
+.SH "SEE ALSO"
+.PP
+\fBhost\fR(1),
+\fBnamed\fR(8),
+\fBdnssec\-keygen\fR(8),
+RFC1035.
+.SH "BUGS"
+.PP
+There are probably too many query options.
+.SH "COPYRIGHT"
+Copyright \(co 2004\-2008 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
new file mode 100644
index 0000000..7f9377d
--- /dev/null
+++ b/bin/dig/dig.c
@@ -0,0 +1,1813 @@
+/*
+ * 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
+ * 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: dig.c,v 1.225 2008/10/28 23:47:06 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+
+#include <isc/app.h>
+#include <isc/netaddr.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+#include <isc/task.h>
+
+#include <dns/byaddr.h>
+#include <dns/fixedname.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/tsig.h>
+
+#include <bind9/getaddresses.h>
+
+#include <dig/dig.h>
+
+#define ADD_STRING(b, s) { \
+ if (strlen(s) >= isc_buffer_availablelength(b)) \
+ return (ISC_R_NOSPACE); \
+ else \
+ isc_buffer_putstr(b, s); \
+}
+
+#define DIG_MAX_ADDRESSES 20
+
+dig_lookup_t *default_lookup = NULL;
+
+static char *batchname = NULL;
+static FILE *batchfp = NULL;
+static char *argv0;
+static int addresscount = 0;
+
+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;
+
+/*% opcode text */
+static const char * const opcodetext[] = {
+ "QUERY",
+ "IQUERY",
+ "STATUS",
+ "RESERVED3",
+ "NOTIFY",
+ "UPDATE",
+ "RESERVED6",
+ "RESERVED7",
+ "RESERVED8",
+ "RESERVED9",
+ "RESERVED10",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15"
+};
+
+/*% return code text */
+static const char * const rcodetext[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15",
+ "BADVERS"
+};
+
+/*% print usage */
+static void
+print_usage(FILE *fp) {
+ fputs(
+"Usage: dig [@global-server] [domain] [q-type] [q-class] {q-opt}\n"
+" {global-d-opt} host [@local-server] {local-d-opt}\n"
+" [ host [@local-server] {local-d-opt} [...]]\n", fp);
+}
+
+static void
+usage(void) {
+ print_usage(stderr);
+ fputs("\nUse \"dig -h\" (or \"dig -h | more\") "
+ "for complete list of options\n", stderr);
+ exit(1);
+}
+
+/*% version */
+static void
+version(void) {
+ fputs("DiG " VERSION "\n", stderr);
+}
+
+/*% help */
+static void
+help(void) {
+ print_usage(stdout);
+ fputs(
+"Where: domain is in the Domain Name System\n"
+" q-class is one of (in,hs,ch,...) [default: in]\n"
+" q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n"
+" (Use ixfr=version for type ixfr)\n"
+" q-opt is one of:\n"
+" -x dot-notation (shortcut for reverse lookups)\n"
+" -i (use IP6.INT for IPv6 reverse lookups)\n"
+" -f filename (batch mode)\n"
+" -b address[#port] (bind to source address/port)\n"
+" -p port (specify port number)\n"
+" -q name (specify query name)\n"
+" -t type (specify query type)\n"
+" -c class (specify query class)\n"
+" -k keyfile (specify tsig key file)\n"
+" -y [hmac:]name:key (specify named base64 tsig key)\n"
+" -4 (use IPv4 query transport only)\n"
+" -6 (use IPv6 query transport only)\n"
+" -m (enable memory usage debugging)\n"
+" d-opt is of the form +keyword[=value], where keyword is:\n"
+" +[no]vc (TCP mode)\n"
+" +[no]tcp (TCP mode, alternate syntax)\n"
+" +time=### (Set query timeout) [5]\n"
+" +tries=### (Set number of UDP attempts) [3]\n"
+" +retry=### (Set number of UDP retries) [2]\n"
+" +domain=### (Set default domainname)\n"
+" +bufsize=### (Set EDNS0 Max UDP packet size)\n"
+" +ndots=### (Set NDOTS value)\n"
+" +edns=### (Set EDNS version)\n"
+" +[no]search (Set whether to use searchlist)\n"
+" +[no]showsearch (Search with intermediate results)\n"
+" +[no]defname (Ditto)\n"
+" +[no]recurse (Recursive mode)\n"
+" +[no]ignore (Don't revert to TCP for TC responses.)"
+"\n"
+" +[no]fail (Don't try next server on SERVFAIL)\n"
+" +[no]besteffort (Try to parse even illegal messages)\n"
+" +[no]aaonly (Set AA flag in query (+[no]aaflag))\n"
+" +[no]adflag (Set AD flag in query)\n"
+" +[no]cdflag (Set CD flag in query)\n"
+" +[no]cl (Control display of class in records)\n"
+" +[no]cmd (Control display of command line)\n"
+" +[no]comments (Control display of comment lines)\n"
+" +[no]question (Control display of question)\n"
+" +[no]answer (Control display of answer)\n"
+" +[no]authority (Control display of authority)\n"
+" +[no]additional (Control display of additional)\n"
+" +[no]stats (Control display of statistics)\n"
+" +[no]short (Disable everything except short\n"
+" form of answer)\n"
+" +[no]ttlid (Control display of ttls in records)\n"
+" +[no]all (Set or clear all display flags)\n"
+" +[no]qr (Print question before sending)\n"
+" +[no]nssearch (Search all authoritative nameservers)\n"
+" +[no]identify (ID responders in short answers)\n"
+" +[no]trace (Trace delegation down from root)\n"
+" +[no]dnssec (Request DNSSEC records)\n"
+" +[no]nsid (Request Name Server ID)\n"
+#ifdef DIG_SIGCHASE
+" +[no]sigchase (Chase DNSSEC signatures)\n"
+" +trusted-key=#### (Trusted Key when chasing DNSSEC sigs)\n"
+#if DIG_SIGCHASE_TD
+" +[no]topdown (Do DNSSEC validation top down mode)\n"
+#endif
+#endif
+" +[no]multiline (Print records in an expanded format)\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"
+" -v (print version and exit)\n",
+ stdout);
+}
+
+/*%
+ * Callback from dighost.c to print the received message.
+ */
+void
+received(int bytes, isc_sockaddr_t *from, dig_query_t *query) {
+ isc_uint64_t diff;
+ isc_time_t now;
+ time_t tnow;
+ char fromtext[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(from, fromtext, sizeof(fromtext));
+
+ TIME_NOW(&now);
+
+ if (query->lookup->stats && !short_form) {
+ diff = isc_time_microdiff(&now, &query->time_sent);
+ printf(";; Query time: %ld msec\n", (long int)diff/1000);
+ printf(";; SERVER: %s(%s)\n", fromtext, query->servname);
+ time(&tnow);
+ printf(";; WHEN: %s", ctime(&tnow));
+ if (query->lookup->doing_xfr) {
+ printf(";; XFR size: %u records (messages %u, "
+ "bytes %" ISC_PRINT_QUADFORMAT "u)\n",
+ query->rr_count, query->msg_count,
+ query->byte_count);
+ } else {
+ printf(";; MSG SIZE rcvd: %u\n", bytes);
+
+ }
+ if (key != NULL) {
+ if (!validated)
+ puts(";; WARNING -- Some TSIG could not "
+ "be validated");
+ }
+ if ((key == NULL) && (keysecret[0] != 0)) {
+ puts(";; WARNING -- TSIG key was not used.");
+ }
+ puts("");
+ } else if (query->lookup->identify && !short_form) {
+ diff = isc_time_microdiff(&now, &query->time_sent);
+ printf(";; Received %" ISC_PRINT_QUADFORMAT "u bytes "
+ "from %s(%s) in %d ms\n\n",
+ query->lookup->doing_xfr ?
+ query->byte_count : (isc_uint64_t)bytes,
+ fromtext, query->servname,
+ (int)diff/1000);
+ }
+}
+
+/*
+ * Callback from dighost.c to print that it is trying a server.
+ * Not used in dig.
+ * XXX print_trying
+ */
+void
+trying(char *frm, dig_lookup_t *lookup) {
+ UNUSED(frm);
+ UNUSED(lookup);
+}
+
+/*%
+ * Internal print routine used to print short form replies.
+ */
+static isc_result_t
+say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) {
+ isc_result_t result;
+ isc_uint64_t diff;
+ isc_time_t now;
+ char store[sizeof("12345678901234567890")];
+
+ if (query->lookup->trace || query->lookup->ns_search_only) {
+ result = dns_rdatatype_totext(rdata->type, buf);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ ADD_STRING(buf, " ");
+ }
+ result = dns_rdata_totext(rdata, NULL, buf);
+ check_result(result, "dns_rdata_totext");
+ if (query->lookup->identify) {
+ TIME_NOW(&now);
+ diff = isc_time_microdiff(&now, &query->time_sent);
+ ADD_STRING(buf, " from server ");
+ ADD_STRING(buf, query->servname);
+ snprintf(store, 19, " in %d ms.", (int)diff/1000);
+ ADD_STRING(buf, store);
+ }
+ ADD_STRING(buf, "\n");
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * short_form message print handler. Calls above say_message()
+ */
+static isc_result_t
+short_answer(dns_message_t *msg, dns_messagetextflag_t flags,
+ isc_buffer_t *buf, dig_query_t *query)
+{
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ isc_buffer_t target;
+ isc_result_t result, loopresult;
+ dns_name_t empty_name;
+ char t[4096];
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ UNUSED(flags);
+
+ dns_name_init(&empty_name, NULL);
+ result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+
+ isc_buffer_init(&target, t, sizeof(t));
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ result = say_message(&rdata, query,
+ buf);
+ check_result(result, "say_message");
+ loopresult = dns_rdataset_next(rdataset);
+ dns_rdata_reset(&rdata);
+ }
+ }
+ result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+#ifdef DIG_SIGCHASE
+isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target)
+{
+ isc_result_t result;
+ dns_master_style_t *style = NULL;
+ unsigned int styleflags = 0;
+
+ if (rdataset == NULL || owner_name == NULL || target == NULL)
+ return(ISC_FALSE);
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (nottl)
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ if (noclass)
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ if (multiline) {
+ styleflags |= DNS_STYLEFLAG_OMIT_OWNER;
+ styleflags |= DNS_STYLEFLAG_OMIT_CLASS;
+ styleflags |= DNS_STYLEFLAG_REL_DATA;
+ styleflags |= DNS_STYLEFLAG_OMIT_TTL;
+ styleflags |= DNS_STYLEFLAG_TTL;
+ styleflags |= DNS_STYLEFLAG_MULTILINE;
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ }
+ if (multiline || (nottl && noclass))
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 24, 24, 32, 80, 8, mctx);
+ else if (nottl || noclass)
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 24, 32, 40, 80, 8, mctx);
+ else
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 32, 40, 48, 80, 8, mctx);
+ check_result(result, "dns_master_stylecreate");
+
+ result = dns_master_rdatasettotext(owner_name, rdataset, style, target);
+
+ if (style != NULL)
+ dns_master_styledestroy(&style, mctx);
+
+ return(result);
+}
+#endif
+
+/*
+ * Callback from dighost.c to print the reply from a server
+ */
+isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
+ isc_result_t result;
+ dns_messagetextflag_t flags;
+ isc_buffer_t *buf = NULL;
+ unsigned int len = OUTPUTBUF;
+ dns_master_style_t *style = NULL;
+ unsigned int styleflags = 0;
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (nottl)
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ if (noclass)
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ if (multiline) {
+ styleflags |= DNS_STYLEFLAG_OMIT_OWNER;
+ styleflags |= DNS_STYLEFLAG_OMIT_CLASS;
+ styleflags |= DNS_STYLEFLAG_REL_DATA;
+ styleflags |= DNS_STYLEFLAG_OMIT_TTL;
+ styleflags |= DNS_STYLEFLAG_TTL;
+ styleflags |= DNS_STYLEFLAG_MULTILINE;
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ }
+ if (multiline || (nottl && noclass))
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 24, 24, 32, 80, 8, mctx);
+ else if (nottl || noclass)
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 24, 32, 40, 80, 8, mctx);
+ else
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 32, 40, 48, 80, 8, mctx);
+ check_result(result, "dns_master_stylecreate");
+
+ if (query->lookup->cmdline[0] != 0) {
+ if (!short_form)
+ fputs(query->lookup->cmdline, stdout);
+ query->lookup->cmdline[0]=0;
+ }
+ debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders",
+ query->lookup->comments ? "comments" : "nocomments",
+ short_form ? "short_form" : "long_form");
+
+ flags = 0;
+ if (!headers) {
+ flags |= DNS_MESSAGETEXTFLAG_NOHEADERS;
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+ }
+ if (!query->lookup->comments)
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+
+ result = ISC_R_SUCCESS;
+
+ result = isc_buffer_allocate(mctx, &buf, len);
+ check_result(result, "isc_buffer_allocate");
+
+ if (query->lookup->comments && !short_form) {
+ if (query->lookup->cmdline[0] != 0)
+ printf("; %s\n", query->lookup->cmdline);
+ if (msg == query->lookup->sendmsg)
+ printf(";; Sending:\n");
+ else
+ printf(";; Got answer:\n");
+
+ if (headers) {
+ printf(";; ->>HEADER<<- opcode: %s, status: %s, "
+ "id: %u\n",
+ opcodetext[msg->opcode], rcodetext[msg->rcode],
+ msg->id);
+ printf(";; flags:");
+ if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
+ printf(" qr");
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
+ printf(" aa");
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
+ printf(" tc");
+ if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
+ printf(" rd");
+ if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
+ printf(" ra");
+ if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
+ printf(" ad");
+ if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
+ printf(" cd");
+
+ printf("; QUERY: %u, ANSWER: %u, "
+ "AUTHORITY: %u, ADDITIONAL: %u\n",
+ msg->counts[DNS_SECTION_QUESTION],
+ msg->counts[DNS_SECTION_ANSWER],
+ msg->counts[DNS_SECTION_AUTHORITY],
+ msg->counts[DNS_SECTION_ADDITIONAL]);
+
+ if (msg != query->lookup->sendmsg &&
+ (msg->flags & DNS_MESSAGEFLAG_RD) != 0 &&
+ (msg->flags & DNS_MESSAGEFLAG_RA) == 0)
+ printf(";; WARNING: recursion requested "
+ "but not available\n");
+ }
+ if (msg != query->lookup->sendmsg && extrabytes != 0U)
+ printf(";; WARNING: Messages has %u extra byte%s at "
+ "end\n", extrabytes, extrabytes != 0 ? "s" : "");
+ }
+
+repopulate_buffer:
+
+ if (query->lookup->comments && headers && !short_form) {
+ result = dns_message_pseudosectiontotext(msg,
+ DNS_PSEUDOSECTION_OPT,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+buftoosmall:
+ len += OUTPUTBUF;
+ isc_buffer_free(&buf);
+ result = isc_buffer_allocate(mctx, &buf, len);
+ if (result == ISC_R_SUCCESS)
+ goto repopulate_buffer;
+ else
+ goto cleanup;
+ }
+ check_result(result,
+ "dns_message_pseudosectiontotext");
+ }
+
+ if (query->lookup->section_question && headers) {
+ if (!short_form) {
+ result = dns_message_sectiontotext(msg,
+ DNS_SECTION_QUESTION,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result, "dns_message_sectiontotext");
+ }
+ }
+ if (query->lookup->section_answer) {
+ if (!short_form) {
+ result = dns_message_sectiontotext(msg,
+ DNS_SECTION_ANSWER,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result, "dns_message_sectiontotext");
+ } else {
+ result = short_answer(msg, flags, buf, query);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result, "short_answer");
+ }
+ }
+ if (query->lookup->section_authority) {
+ if (!short_form) {
+ result = dns_message_sectiontotext(msg,
+ DNS_SECTION_AUTHORITY,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result, "dns_message_sectiontotext");
+ }
+ }
+ if (query->lookup->section_additional) {
+ if (!short_form) {
+ result = dns_message_sectiontotext(msg,
+ DNS_SECTION_ADDITIONAL,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result, "dns_message_sectiontotext");
+ /*
+ * Only print the signature on the first record.
+ */
+ if (headers) {
+ result = dns_message_pseudosectiontotext(
+ msg,
+ DNS_PSEUDOSECTION_TSIG,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result,
+ "dns_message_pseudosectiontotext");
+ result = dns_message_pseudosectiontotext(
+ msg,
+ DNS_PSEUDOSECTION_SIG0,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result,
+ "dns_message_pseudosectiontotext");
+ }
+ }
+ }
+
+ if (headers && query->lookup->comments && !short_form)
+ printf("\n");
+
+ printf("%.*s", (int)isc_buffer_usedlength(buf),
+ (char *)isc_buffer_base(buf));
+ isc_buffer_free(&buf);
+
+cleanup:
+ if (style != NULL)
+ dns_master_styledestroy(&style, mctx);
+ return (result);
+}
+
+/*%
+ * print the greeting message when the program first starts up.
+ */
+static void
+printgreeting(int argc, char **argv, dig_lookup_t *lookup) {
+ int i;
+ int remaining;
+ static isc_boolean_t first = ISC_TRUE;
+ char append[MXNAME];
+
+ if (printcmd) {
+ lookup->cmdline[sizeof(lookup->cmdline) - 1] = 0;
+ snprintf(lookup->cmdline, sizeof(lookup->cmdline),
+ "%s; <<>> DiG " VERSION " <<>>",
+ first?"\n":"");
+ i = 1;
+ while (i < argc) {
+ snprintf(append, sizeof(append), " %s", argv[i++]);
+ remaining = sizeof(lookup->cmdline) -
+ strlen(lookup->cmdline) - 1;
+ strncat(lookup->cmdline, append, remaining);
+ }
+ remaining = sizeof(lookup->cmdline) -
+ strlen(lookup->cmdline) - 1;
+ strncat(lookup->cmdline, "\n", remaining);
+ if (first && addresscount != 0) {
+ snprintf(append, sizeof(append),
+ "; (%d server%s found)\n",
+ addresscount,
+ addresscount > 1 ? "s" : "");
+ remaining = sizeof(lookup->cmdline) -
+ strlen(lookup->cmdline) - 1;
+ strncat(lookup->cmdline, append, remaining);
+ }
+ if (first) {
+ snprintf(append, sizeof(append),
+ ";; global options:%s%s\n",
+ short_form ? " +short" : "",
+ printcmd ? " +cmd" : "");
+ first = ISC_FALSE;
+ remaining = sizeof(lookup->cmdline) -
+ strlen(lookup->cmdline) - 1;
+ strncat(lookup->cmdline, append, remaining);
+ }
+ }
+}
+
+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
+ * by that routine.
+ * XXX doc options
+ */
+
+static void
+plus_option(char *option, isc_boolean_t is_batchfile,
+ dig_lookup_t *lookup)
+{
+ char option_store[256];
+ char *cmd, *value, *ptr;
+ isc_boolean_t state = ISC_TRUE;
+#ifdef DIG_SIGCHASE
+ size_t n;
+#endif
+
+ strncpy(option_store, option, sizeof(option_store));
+ option_store[sizeof(option_store)-1]=0;
+ ptr = option_store;
+ cmd = next_token(&ptr,"=");
+ if (cmd == NULL) {
+ printf(";; Invalid option %s\n", option_store);
+ return;
+ }
+ value = ptr;
+ if (strncasecmp(cmd, "no", 2)==0) {
+ cmd += 2;
+ state = ISC_FALSE;
+ }
+
+#define FULLCHECK(A) \
+ do { \
+ size_t _l = strlen(cmd); \
+ if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \
+ goto invalid_option; \
+ } while (0)
+#define FULLCHECK2(A, B) \
+ do { \
+ size_t _l = strlen(cmd); \
+ if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
+ (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \
+ goto invalid_option; \
+ } while (0)
+
+ switch (cmd[0]) {
+ case 'a':
+ switch (cmd[1]) {
+ case 'a': /* aaonly / aaflag */
+ FULLCHECK2("aaonly", "aaflag");
+ lookup->aaonly = state;
+ break;
+ case 'd':
+ switch (cmd[2]) {
+ case 'd': /* additional */
+ FULLCHECK("additional");
+ lookup->section_additional = state;
+ break;
+ case 'f': /* adflag */
+ FULLCHECK("adflag");
+ lookup->adflag = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'l': /* all */
+ FULLCHECK("all");
+ lookup->section_question = state;
+ lookup->section_authority = state;
+ lookup->section_answer = state;
+ lookup->section_additional = state;
+ lookup->comments = state;
+ lookup->stats = state;
+ printcmd = state;
+ break;
+ case 'n': /* answer */
+ FULLCHECK("answer");
+ lookup->section_answer = state;
+ break;
+ case 'u': /* authority */
+ FULLCHECK("authority");
+ lookup->section_authority = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'b':
+ switch (cmd[1]) {
+ case 'e':/* besteffort */
+ FULLCHECK("besteffort");
+ lookup->besteffort = state;
+ break;
+ case 'u':/* bufsize */
+ FULLCHECK("bufsize");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ lookup->udpsize = (isc_uint16_t) parse_uint(value,
+ "buffer size", COMMSIZE);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'c':
+ switch (cmd[1]) {
+ case 'd':/* cdflag */
+ FULLCHECK("cdflag");
+ lookup->cdflag = state;
+ break;
+ case 'l': /* cl */
+ FULLCHECK("cl");
+ noclass = ISC_TF(!state);
+ break;
+ case 'm': /* cmd */
+ FULLCHECK("cmd");
+ printcmd = state;
+ break;
+ case 'o': /* comments */
+ FULLCHECK("comments");
+ lookup->comments = state;
+ if (lookup == default_lookup)
+ pluscomm = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'd':
+ switch (cmd[1]) {
+ case 'e': /* defname */
+ FULLCHECK("defname");
+ usesearch = state;
+ break;
+ case 'n': /* dnssec */
+ FULLCHECK("dnssec");
+ if (state && lookup->edns == -1)
+ lookup->edns = 0;
+ lookup->dnssec = state;
+ break;
+ case 'o': /* domain */
+ FULLCHECK("domain");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ strncpy(domainopt, value, sizeof(domainopt));
+ domainopt[sizeof(domainopt)-1] = '\0';
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'e':
+ FULLCHECK("edns");
+ if (!state) {
+ lookup->edns = -1;
+ break;
+ }
+ if (value == NULL)
+ goto need_value;
+ lookup->edns = (isc_int16_t) parse_uint(value, "edns", 255);
+ break;
+ case 'f': /* fail */
+ FULLCHECK("fail");
+ lookup->servfail_stops = state;
+ break;
+ case 'i':
+ switch (cmd[1]) {
+ case 'd': /* identify */
+ FULLCHECK("identify");
+ lookup->identify = state;
+ break;
+ case 'g': /* ignore */
+ default: /* Inherets default for compatibility */
+ FULLCHECK("ignore");
+ lookup->ignore = ISC_TRUE;
+ }
+ break;
+ case 'm': /* multiline */
+ FULLCHECK("multiline");
+ multiline = state;
+ break;
+ case 'n':
+ switch (cmd[1]) {
+ case 'd': /* ndots */
+ FULLCHECK("ndots");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ ndots = parse_uint(value, "ndots", MAXNDOTS);
+ break;
+ case 's':
+ switch (cmd[2]) {
+ case 'i': /* nsid */
+ FULLCHECK("nsid");
+ if (state && lookup->edns == -1)
+ lookup->edns = 0;
+ lookup->nsid = state;
+ break;
+ case 's': /* nssearch */
+ FULLCHECK("nssearch");
+ lookup->ns_search_only = state;
+ if (state) {
+ lookup->trace_root = ISC_TRUE;
+ lookup->recurse = ISC_TRUE;
+ lookup->identify = ISC_TRUE;
+ lookup->stats = ISC_FALSE;
+ lookup->comments = ISC_FALSE;
+ lookup->section_additional = ISC_FALSE;
+ lookup->section_authority = ISC_FALSE;
+ lookup->section_question = ISC_FALSE;
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = ISC_TRUE;
+ short_form = ISC_TRUE;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'q':
+ switch (cmd[1]) {
+ case 'r': /* qr */
+ FULLCHECK("qr");
+ qr = state;
+ break;
+ case 'u': /* question */
+ FULLCHECK("question");
+ lookup->section_question = state;
+ if (lookup == default_lookup)
+ plusquest = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ switch (cmd[1]) {
+ case 'e':
+ switch (cmd[2]) {
+ case 'c': /* recurse */
+ FULLCHECK("recurse");
+ lookup->recurse = state;
+ break;
+ case 't': /* retry / retries */
+ FULLCHECK2("retry", "retries");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ lookup->retries = parse_uint(value, "retries",
+ MAXTRIES - 1);
+ lookup->retries++;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 's':
+ switch (cmd[1]) {
+ case 'e': /* search */
+ FULLCHECK("search");
+ usesearch = state;
+ break;
+ case 'h':
+ if (cmd[2] != 'o')
+ goto invalid_option;
+ switch (cmd[3]) {
+ case 'r': /* short */
+ FULLCHECK("short");
+ short_form = state;
+ if (state) {
+ printcmd = ISC_FALSE;
+ lookup->section_additional = ISC_FALSE;
+ lookup->section_answer = ISC_TRUE;
+ lookup->section_authority = ISC_FALSE;
+ lookup->section_question = ISC_FALSE;
+ lookup->comments = ISC_FALSE;
+ lookup->stats = ISC_FALSE;
+ }
+ break;
+ case 'w': /* showsearch */
+ FULLCHECK("showsearch");
+ showsearch = state;
+ usesearch = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+#ifdef DIG_SIGCHASE
+ case 'i': /* sigchase */
+ FULLCHECK("sigchase");
+ lookup->sigchase = state;
+ if (lookup->sigchase)
+ lookup->dnssec = ISC_TRUE;
+ break;
+#endif
+ case 't': /* stats */
+ FULLCHECK("stats");
+ lookup->stats = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't':
+ switch (cmd[1]) {
+ case 'c': /* tcp */
+ FULLCHECK("tcp");
+ if (!is_batchfile)
+ lookup->tcp_mode = state;
+ break;
+ case 'i': /* timeout */
+ FULLCHECK("timeout");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ timeout = parse_uint(value, "timeout", MAXTIMEOUT);
+ if (timeout == 0)
+ timeout = 1;
+ break;
+#if DIG_SIGCHASE_TD
+ case 'o': /* topdown */
+ FULLCHECK("topdown");
+ lookup->do_topdown = state;
+ break;
+#endif
+ case 'r':
+ switch (cmd[2]) {
+ case 'a': /* trace */
+ FULLCHECK("trace");
+ lookup->trace = state;
+ lookup->trace_root = state;
+ if (state) {
+ lookup->recurse = ISC_FALSE;
+ lookup->identify = ISC_TRUE;
+ lookup->comments = ISC_FALSE;
+ lookup->stats = ISC_FALSE;
+ lookup->section_additional = ISC_FALSE;
+ lookup->section_authority = ISC_TRUE;
+ lookup->section_question = ISC_FALSE;
+ }
+ break;
+ case 'i': /* tries */
+ FULLCHECK("tries");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ lookup->retries = parse_uint(value, "tries",
+ MAXTRIES);
+ if (lookup->retries == 0)
+ lookup->retries = 1;
+ break;
+#ifdef DIG_SIGCHASE
+ case 'u': /* trusted-key */
+ FULLCHECK("trusted-key");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ n = strlcpy(trustedkey, ptr,
+ sizeof(trustedkey));
+ if (n >= sizeof(trustedkey))
+ fatal("trusted key too large");
+ break;
+#endif
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't': /* ttlid */
+ FULLCHECK("ttlid");
+ nottl = ISC_TF(!state);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'v':
+ FULLCHECK("vc");
+ if (!is_batchfile)
+ lookup->tcp_mode = state;
+ break;
+ default:
+ invalid_option:
+ need_value:
+ fprintf(stderr, "Invalid option: +%s\n",
+ option);
+ usage();
+ }
+ return;
+}
+
+/*%
+ * #ISC_TRUE returned if value was used
+ */
+static const char *single_dash_opts = "46dhimnv";
+static const char *dash_opts = "46bcdfhikmnptvyx";
+static isc_boolean_t
+dash_option(char *option, char *next, dig_lookup_t **lookup,
+ isc_boolean_t *open_type_class, isc_boolean_t *need_clone,
+ isc_boolean_t config_only, int argc, char **argv,
+ isc_boolean_t *firstarg)
+{
+ char opt, *value, *ptr, *ptr2, *ptr3;
+ isc_result_t result;
+ isc_boolean_t value_from_next;
+ isc_textregion_t tr;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ char textname[MXNAME];
+ struct in_addr in4;
+ struct in6_addr in6;
+ in_port_t srcport;
+ char *hash, *cmd;
+
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ /*
+ * Since the -[46dhimnv] options do not take an argument,
+ * account for them (in any number and/or combination)
+ * if they appear as the first character(s) of a q-opt.
+ */
+ opt = option[0];
+ switch (opt) {
+ case '4':
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = ISC_FALSE;
+ } else {
+ fatal("can't find IPv4 networking");
+ return (ISC_FALSE);
+ }
+ break;
+ case '6':
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = ISC_FALSE;
+ } else {
+ fatal("can't find IPv6 networking");
+ return (ISC_FALSE);
+ }
+ break;
+ case 'd':
+ ptr = strpbrk(&option[1], dash_opts);
+ if (ptr != &option[1]) {
+ cmd = option;
+ FULLCHECK("debug");
+ debugging = ISC_TRUE;
+ return (ISC_FALSE);
+ } else
+ debugging = ISC_TRUE;
+ break;
+ case 'h':
+ help();
+ exit(0);
+ break;
+ case 'i':
+ ip6_int = ISC_TRUE;
+ break;
+ case 'm': /* memdebug */
+ /* memdebug is handled in preparse_args() */
+ break;
+ case 'n':
+ /* deprecated */
+ break;
+ case 'v':
+ version();
+ exit(0);
+ break;
+ }
+ if (strlen(option) > 1U)
+ option = &option[1];
+ else
+ return (ISC_FALSE);
+ }
+ opt = option[0];
+ if (strlen(option) > 1U) {
+ value_from_next = ISC_FALSE;
+ value = &option[1];
+ } else {
+ value_from_next = ISC_TRUE;
+ value = next;
+ }
+ if (value == NULL)
+ goto invalid_option;
+ switch (opt) {
+ case 'b':
+ hash = strchr(value, '#');
+ if (hash != NULL) {
+ srcport = (in_port_t)
+ parse_uint(hash + 1,
+ "port number", MAXPORT);
+ *hash = '\0';
+ } else
+ srcport = 0;
+ if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) {
+ isc_sockaddr_fromin6(&bind_address, &in6, srcport);
+ isc_net_disableipv4();
+ } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) {
+ isc_sockaddr_fromin(&bind_address, &in4, srcport);
+ isc_net_disableipv6();
+ } else {
+ if (hash != NULL)
+ *hash = '#';
+ fatal("invalid address %s", value);
+ }
+ if (hash != NULL)
+ *hash = '#';
+ specified_source = ISC_TRUE;
+ return (value_from_next);
+ case 'c':
+ if ((*lookup)->rdclassset) {
+ fprintf(stderr, ";; Warning, extra class option\n");
+ }
+ *open_type_class = ISC_FALSE;
+ tr.base = value;
+ tr.length = strlen(value);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ (*lookup)->rdclass = rdclass;
+ (*lookup)->rdclassset = ISC_TRUE;
+ } else
+ fprintf(stderr, ";; Warning, ignoring "
+ "invalid class %s\n",
+ value);
+ return (value_from_next);
+ case 'f':
+ batchname = value;
+ return (value_from_next);
+ case 'k':
+ strncpy(keyfile, value, sizeof(keyfile));
+ keyfile[sizeof(keyfile)-1]=0;
+ return (value_from_next);
+ case 'p':
+ port = (in_port_t) parse_uint(value, "port number", MAXPORT);
+ return (value_from_next);
+ case 'q':
+ if (!config_only) {
+ if (*need_clone)
+ (*lookup) = clone_lookup(default_lookup,
+ ISC_TRUE);
+ *need_clone = ISC_TRUE;
+ strncpy((*lookup)->textname, value,
+ sizeof((*lookup)->textname));
+ (*lookup)->textname[sizeof((*lookup)->textname)-1]=0;
+ (*lookup)->trace_root = ISC_TF((*lookup)->trace ||
+ (*lookup)->ns_search_only);
+ (*lookup)->new_search = ISC_TRUE;
+ if (*firstarg) {
+ printgreeting(argc, argv, *lookup);
+ *firstarg = ISC_FALSE;
+ }
+ ISC_LIST_APPEND(lookup_list, (*lookup), link);
+ debug("looking up %s", (*lookup)->textname);
+ }
+ return (value_from_next);
+ case 't':
+ *open_type_class = ISC_FALSE;
+ if (strncasecmp(value, "ixfr=", 5) == 0) {
+ rdtype = dns_rdatatype_ixfr;
+ result = ISC_R_SUCCESS;
+ } else {
+ tr.base = value;
+ tr.length = strlen(value);
+ result = dns_rdatatype_fromtext(&rdtype,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS &&
+ rdtype == dns_rdatatype_ixfr) {
+ result = DNS_R_UNKNOWN;
+ }
+ }
+ if (result == ISC_R_SUCCESS) {
+ if ((*lookup)->rdtypeset) {
+ fprintf(stderr, ";; Warning, "
+ "extra type option\n");
+ }
+ if (rdtype == dns_rdatatype_ixfr) {
+ (*lookup)->rdtype = dns_rdatatype_ixfr;
+ (*lookup)->rdtypeset = ISC_TRUE;
+ (*lookup)->ixfr_serial =
+ parse_uint(&value[5], "serial number",
+ MAXSERIAL);
+ (*lookup)->section_question = plusquest;
+ (*lookup)->comments = pluscomm;
+ (*lookup)->tcp_mode = ISC_TRUE;
+ } else {
+ (*lookup)->rdtype = rdtype;
+ (*lookup)->rdtypeset = ISC_TRUE;
+ if (rdtype == dns_rdatatype_axfr) {
+ (*lookup)->section_question = plusquest;
+ (*lookup)->comments = pluscomm;
+ }
+ (*lookup)->ixfr_serial = ISC_FALSE;
+ }
+ } else
+ fprintf(stderr, ";; Warning, ignoring "
+ "invalid type %s\n",
+ value);
+ return (value_from_next);
+ case 'y':
+ ptr = next_token(&value,":"); /* hmac type or name */
+ if (ptr == NULL) {
+ usage();
+ }
+ ptr2 = next_token(&value, ":"); /* name or secret */
+ if (ptr2 == NULL)
+ 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);
+ }
+ ptr = ptr2;
+ ptr2 = ptr3;
+ } else {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ digestbits = 0;
+ }
+ strncpy(keynametext, ptr, sizeof(keynametext));
+ keynametext[sizeof(keynametext)-1]=0;
+ strncpy(keysecret, ptr2, sizeof(keysecret));
+ keysecret[sizeof(keysecret)-1]=0;
+ return (value_from_next);
+ case 'x':
+ if (*need_clone)
+ *lookup = clone_lookup(default_lookup, ISC_TRUE);
+ *need_clone = ISC_TRUE;
+ if (get_reverse(textname, sizeof(textname), value,
+ ip6_int, ISC_FALSE) == ISC_R_SUCCESS) {
+ strncpy((*lookup)->textname, textname,
+ sizeof((*lookup)->textname));
+ debug("looking up %s", (*lookup)->textname);
+ (*lookup)->trace_root = ISC_TF((*lookup)->trace ||
+ (*lookup)->ns_search_only);
+ (*lookup)->ip6_int = ip6_int;
+ if (!(*lookup)->rdtypeset)
+ (*lookup)->rdtype = dns_rdatatype_ptr;
+ if (!(*lookup)->rdclassset)
+ (*lookup)->rdclass = dns_rdataclass_in;
+ (*lookup)->new_search = ISC_TRUE;
+ if (*firstarg) {
+ printgreeting(argc, argv, *lookup);
+ *firstarg = ISC_FALSE;
+ }
+ ISC_LIST_APPEND(lookup_list, *lookup, link);
+ } else {
+ fprintf(stderr, "Invalid IP address %s\n", value);
+ exit(1);
+ }
+ return (value_from_next);
+ invalid_option:
+ default:
+ fprintf(stderr, "Invalid option: -%s\n", option);
+ usage();
+ }
+ return (ISC_FALSE);
+}
+
+/*%
+ * Because we may be trying to do memory allocation recording, we're going
+ * to need to parse the arguments for the -m *before* we start the main
+ * argument parsing routine.
+ *
+ * I'd prefer not to have to do this, but I am not quite sure how else to
+ * fix the problem. Argument parsing in dig involves memory allocation
+ * by its nature, so it can't be done in the main argument parser.
+ */
+static void
+preparse_args(int argc, char **argv) {
+ int rc;
+ char **rv;
+ char *option;
+
+ rc = argc;
+ rv = argv;
+ for (rc--, rv++; rc > 0; rc--, rv++) {
+ if (rv[0][0] != '-')
+ continue;
+ option = &rv[0][1];
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ if (option[0] == 'm') {
+ memdebugging = ISC_TRUE;
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE |
+ ISC_MEM_DEBUGRECORD;
+ return;
+ }
+ option = &option[1];
+ }
+ }
+}
+
+static void
+getaddresses(dig_lookup_t *lookup, const char *host) {
+ isc_result_t result;
+ isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
+ isc_netaddr_t netaddr;
+ int count, i;
+ dig_server_t *srv;
+ char tmp[ISC_NETADDR_FORMATSIZE];
+
+ result = bind9_getaddresses(host, 0, sockaddrs,
+ DIG_MAX_ADDRESSES, &count);
+ if (result != ISC_R_SUCCESS)
+ fatal("couldn't get address for '%s': %s",
+ host, isc_result_totext(result));
+
+ for (i = 0; i < count; i++) {
+ isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
+ isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
+ srv = make_server(tmp, host);
+ ISC_LIST_APPEND(lookup->my_server_list, srv, link);
+ }
+ addresscount = count;
+}
+
+static void
+parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only,
+ int argc, char **argv) {
+ isc_result_t result;
+ isc_textregion_t tr;
+ isc_boolean_t firstarg = ISC_TRUE;
+ dig_lookup_t *lookup = NULL;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ isc_boolean_t open_type_class = ISC_TRUE;
+ char batchline[MXNAME];
+ int bargc;
+ char *bargv[64];
+ int rc;
+ char **rv;
+#ifndef NOPOSIX
+ char *homedir;
+ char rcfile[256];
+#endif
+ char *input;
+ int i;
+ isc_boolean_t need_clone = ISC_TRUE;
+
+ /*
+ * The semantics for parsing the args is a bit complex; if
+ * we don't have a host yet, make the arg apply globally,
+ * otherwise make it apply to the latest host. This is
+ * a bit different than the previous versions, but should
+ * form a consistent user interface.
+ *
+ * First, create a "default lookup" which won't actually be used
+ * anywhere, except for cloning into new lookups
+ */
+
+ debug("parse_args()");
+ if (!is_batchfile) {
+ debug("making new lookup");
+ default_lookup = make_empty_lookup();
+
+#ifndef NOPOSIX
+ /*
+ * Treat ${HOME}/.digrc as a special batchfile
+ */
+ INSIST(batchfp == NULL);
+ homedir = getenv("HOME");
+ if (homedir != NULL) {
+ unsigned int n;
+ n = snprintf(rcfile, sizeof(rcfile), "%s/.digrc",
+ homedir);
+ if (n < sizeof(rcfile))
+ batchfp = fopen(rcfile, "r");
+ }
+ if (batchfp != NULL) {
+ while (fgets(batchline, sizeof(batchline),
+ batchfp) != 0) {
+ debug("config line %s", batchline);
+ bargc = 1;
+ input = batchline;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ while ((bargv[bargc] != NULL) &&
+ (bargc < 62)) {
+ bargc++;
+ bargv[bargc] =
+ next_token(&input, " \t\r\n");
+ }
+
+ bargv[0] = argv[0];
+ argv0 = argv[0];
+
+ for(i = 0; i < bargc; i++)
+ debug(".digrc argv %d: %s",
+ i, bargv[i]);
+ parse_args(ISC_TRUE, ISC_TRUE, bargc,
+ (char **)bargv);
+ }
+ fclose(batchfp);
+ }
+#endif
+ }
+
+ if (is_batchfile && !config_only) {
+ /* Processing '-f batchfile'. */
+ lookup = clone_lookup(default_lookup, ISC_TRUE);
+ need_clone = ISC_FALSE;
+ } else
+ lookup = default_lookup;
+
+ rc = argc;
+ rv = argv;
+ for (rc--, rv++; rc > 0; rc--, rv++) {
+ debug("main parsing %s", rv[0]);
+ if (strncmp(rv[0], "%", 1) == 0)
+ break;
+ if (strncmp(rv[0], "@", 1) == 0) {
+ getaddresses(lookup, &rv[0][1]);
+ } else if (rv[0][0] == '+') {
+ plus_option(&rv[0][1], is_batchfile,
+ lookup);
+ } else if (rv[0][0] == '-') {
+ if (rc <= 1) {
+ if (dash_option(&rv[0][1], NULL,
+ &lookup, &open_type_class,
+ &need_clone, config_only,
+ argc, argv, &firstarg)) {
+ rc--;
+ rv++;
+ }
+ } else {
+ if (dash_option(&rv[0][1], rv[1],
+ &lookup, &open_type_class,
+ &need_clone, config_only,
+ argc, argv, &firstarg)) {
+ rc--;
+ rv++;
+ }
+ }
+ } else {
+ /*
+ * Anything which isn't an option
+ */
+ if (open_type_class) {
+ if (strncasecmp(rv[0], "ixfr=", 5) == 0) {
+ rdtype = dns_rdatatype_ixfr;
+ result = ISC_R_SUCCESS;
+ } else {
+ tr.base = rv[0];
+ tr.length = strlen(rv[0]);
+ result = dns_rdatatype_fromtext(&rdtype,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS &&
+ rdtype == dns_rdatatype_ixfr) {
+ result = DNS_R_UNKNOWN;
+ fprintf(stderr, ";; Warning, "
+ "ixfr requires a "
+ "serial number\n");
+ continue;
+ }
+ }
+ if (result == ISC_R_SUCCESS) {
+ if (lookup->rdtypeset) {
+ fprintf(stderr, ";; Warning, "
+ "extra type option\n");
+ }
+ if (rdtype == dns_rdatatype_ixfr) {
+ lookup->rdtype =
+ dns_rdatatype_ixfr;
+ lookup->rdtypeset = ISC_TRUE;
+ lookup->ixfr_serial =
+ parse_uint(&rv[0][5],
+ "serial number",
+ MAXSERIAL);
+ lookup->section_question =
+ plusquest;
+ lookup->comments = pluscomm;
+ lookup->tcp_mode = ISC_TRUE;
+ } else {
+ lookup->rdtype = rdtype;
+ lookup->rdtypeset = ISC_TRUE;
+ if (rdtype ==
+ dns_rdatatype_axfr) {
+ lookup->section_question =
+ plusquest;
+ lookup->comments = pluscomm;
+ }
+ lookup->ixfr_serial = ISC_FALSE;
+ }
+ continue;
+ }
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ if (lookup->rdclassset) {
+ fprintf(stderr, ";; Warning, "
+ "extra class option\n");
+ }
+ lookup->rdclass = rdclass;
+ lookup->rdclassset = ISC_TRUE;
+ continue;
+ }
+ }
+
+ if (!config_only) {
+ if (need_clone)
+ lookup = clone_lookup(default_lookup,
+ ISC_TRUE);
+ need_clone = ISC_TRUE;
+ strncpy(lookup->textname, rv[0],
+ sizeof(lookup->textname));
+ lookup->textname[sizeof(lookup->textname)-1]=0;
+ lookup->trace_root = ISC_TF(lookup->trace ||
+ lookup->ns_search_only);
+ lookup->new_search = ISC_TRUE;
+ if (firstarg) {
+ printgreeting(argc, argv, lookup);
+ firstarg = ISC_FALSE;
+ }
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ debug("looking up %s", lookup->textname);
+ }
+ /* XXX Error message */
+ }
+ }
+
+ /*
+ * If we have a batchfile, seed the lookup list with the
+ * first entry, then trust the callback in dighost_shutdown
+ * to get the rest
+ */
+ if ((batchname != NULL) && !(is_batchfile)) {
+ if (strcmp(batchname, "-") == 0)
+ batchfp = stdin;
+ else
+ batchfp = fopen(batchname, "r");
+ if (batchfp == NULL) {
+ perror(batchname);
+ if (exitcode < 8)
+ exitcode = 8;
+ fatal("couldn't open specified batch file");
+ }
+ /* XXX Remove code dup from shutdown code */
+ next_line:
+ if (fgets(batchline, sizeof(batchline), batchfp) != 0) {
+ bargc = 1;
+ debug("batch line %s", batchline);
+ if (batchline[0] == '\r' || batchline[0] == '\n'
+ || batchline[0] == '#' || batchline[0] == ';')
+ goto next_line;
+ input = batchline;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ while ((bargv[bargc] != NULL) && (bargc < 14)) {
+ bargc++;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ }
+
+ bargv[0] = argv[0];
+ argv0 = argv[0];
+
+ for(i = 0; i < bargc; i++)
+ debug("batch argv %d: %s", i, bargv[i]);
+ parse_args(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv);
+ return;
+ }
+ return;
+ }
+ /*
+ * If no lookup specified, search for root
+ */
+ if ((lookup_list.head == NULL) && !config_only) {
+ if (need_clone)
+ lookup = clone_lookup(default_lookup, ISC_TRUE);
+ need_clone = ISC_TRUE;
+ lookup->trace_root = ISC_TF(lookup->trace ||
+ lookup->ns_search_only);
+ lookup->new_search = ISC_TRUE;
+ strcpy(lookup->textname, ".");
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = ISC_TRUE;
+ if (firstarg) {
+ printgreeting(argc, argv, lookup);
+ firstarg = ISC_FALSE;
+ }
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ if (!need_clone)
+ destroy_lookup(lookup);
+}
+
+/*
+ * Callback from dighost.c to allow program-specific shutdown code.
+ * Here, we're possibly reading from a batch file, then shutting down
+ * for real if there's nothing in the batch file to read.
+ */
+void
+dighost_shutdown(void) {
+ char batchline[MXNAME];
+ int bargc;
+ char *bargv[16];
+ char *input;
+ int i;
+
+ if (batchname == NULL) {
+ isc_app_shutdown();
+ return;
+ }
+
+ fflush(stdout);
+ if (feof(batchfp)) {
+ batchname = NULL;
+ isc_app_shutdown();
+ if (batchfp != stdin)
+ fclose(batchfp);
+ return;
+ }
+
+ if (fgets(batchline, sizeof(batchline), batchfp) != 0) {
+ debug("batch line %s", batchline);
+ bargc = 1;
+ input = batchline;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ while ((bargv[bargc] != NULL) && (bargc < 14)) {
+ bargc++;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ }
+
+ bargv[0] = argv0;
+
+ for(i = 0; i < bargc; i++)
+ debug("batch argv %d: %s", i, bargv[i]);
+ parse_args(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv);
+ start_lookup();
+ } else {
+ batchname = NULL;
+ if (batchfp != stdin)
+ fclose(batchfp);
+ isc_app_shutdown();
+ return;
+ }
+}
+
+/*% Main processing routine for dig */
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ debug("main()");
+ preparse_args(argc, argv);
+ progname = argv[0];
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+ setup_libs();
+ parse_args(ISC_FALSE, ISC_FALSE, argc, argv);
+ setup_system();
+ if (domainopt[0] != '\0') {
+ set_search_domain(domainopt);
+ usesearch = ISC_TRUE;
+ }
+ result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
+ check_result(result, "isc_app_onrun");
+ isc_app_run();
+ destroy_lookup(default_lookup);
+ if (batchname != NULL) {
+ if (batchfp != stdin)
+ fclose(batchfp);
+ batchname = NULL;
+ }
+#ifdef DIG_SIGCHASE
+ clean_trustedkey();
+#endif
+ cancel_all();
+ destroy_libs();
+ isc_app_finish();
+ return (exitcode);
+}
diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook
new file mode 100644
index 0000000..af26d70
--- /dev/null
+++ b/bin/dig/dig.docbook
@@ -0,0 +1,952 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - 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
+ - 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: dig.docbook,v 1.42 2008/10/13 21:18:56 jreed Exp $ -->
+<refentry id="man.dig">
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>dig</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>dig</refname>
+ <refpurpose>DNS lookup utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dig</command>
+ <arg choice="opt">@server</arg>
+ <arg><option>-b <replaceable class="parameter">address</replaceable></option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-f <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg><option>-k <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg><option>-m</option></arg>
+ <arg><option>-p <replaceable class="parameter">port#</replaceable></option></arg>
+ <arg><option>-q <replaceable class="parameter">name</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg><option>-x <replaceable class="parameter">addr</replaceable></option></arg>
+ <arg><option>-y <replaceable class="parameter"><optional>hmac:</optional>name:key</replaceable></option></arg>
+ <arg><option>-4</option></arg>
+ <arg><option>-6</option></arg>
+ <arg choice="opt">name</arg>
+ <arg choice="opt">type</arg>
+ <arg choice="opt">class</arg>
+ <arg choice="opt" rep="repeat">queryopt</arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>dig</command>
+ <arg><option>-h</option></arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>dig</command>
+ <arg choice="opt" rep="repeat">global-queryopt</arg>
+ <arg choice="opt" rep="repeat">query</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dig</command>
+ (domain information groper) is a flexible tool
+ for interrogating DNS name servers. It performs DNS lookups and
+ displays the answers that are returned from the name server(s) that
+ were queried. Most DNS administrators use <command>dig</command> to
+ troubleshoot DNS problems because of its flexibility, ease of use and
+ clarity of output. Other lookup tools tend to have less functionality
+ than <command>dig</command>.
+ </para>
+
+ <para>
+ Although <command>dig</command> is normally used with
+ command-line
+ arguments, it also has a batch mode of operation for reading lookup
+ requests from a file. A brief summary of its command-line arguments
+ and options is printed when the <option>-h</option> option is given.
+ Unlike earlier versions, the BIND 9 implementation of
+ <command>dig</command> allows multiple lookups to be issued
+ from the
+ command line.
+ </para>
+
+ <para>
+ Unless it is told to query a specific name server,
+ <command>dig</command> will try each of the servers listed
+ in
+ <filename>/etc/resolv.conf</filename>.
+ </para>
+
+ <para>
+ When no command line arguments or options are given,
+ <command>dig</command> will perform an NS query for "." (the root).
+ </para>
+
+ <para>
+ It is possible to set per-user defaults for <command>dig</command> via
+ <filename>${HOME}/.digrc</filename>. This file is read and
+ any options in it
+ are applied before the command line arguments.
+ </para>
+
+ <para>
+ The IN and CH class names overlap with the IN and CH top level
+ domains names. Either use the <option>-t</option> and
+ <option>-c</option> options to specify the type and class,
+ use the <option>-q</option> the specify the domain name, or
+ use "IN." and "CH." when looking up these top level domains.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>SIMPLE USAGE</title>
+
+ <para>
+ A typical invocation of <command>dig</command> looks like:
+ <programlisting> dig @server name type </programlisting>
+ where:
+
+ <variablelist>
+
+ <varlistentry>
+ <term><constant>server</constant></term>
+ <listitem>
+ <para>
+ is the name or IP address of the name server to query. This can
+ be an IPv4
+ address in dotted-decimal notation or an IPv6
+ address in colon-delimited notation. When the supplied
+ <parameter>server</parameter> argument is a
+ hostname,
+ <command>dig</command> resolves that name before
+ querying that name
+ server. If no <parameter>server</parameter>
+ argument is provided,
+ <command>dig</command> consults <filename>/etc/resolv.conf</filename>
+ and queries the name servers listed there. The reply from the
+ name
+ server that responds is displayed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>name</constant></term>
+ <listitem>
+ <para>
+ is the name of the resource record that is to be looked up.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>type</constant></term>
+ <listitem>
+ <para>
+ indicates what type of query is required &mdash;
+ ANY, A, MX, SIG, etc.
+ <parameter>type</parameter> can be any valid query
+ type. If no
+ <parameter>type</parameter> argument is supplied,
+ <command>dig</command> will perform a lookup for an
+ A record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <para>
+ The <option>-b</option> option sets the source IP address of the query
+ to <parameter>address</parameter>. This must be a valid
+ address on
+ one of the host's network interfaces or "0.0.0.0" or "::". An optional
+ port
+ may be specified by appending "#&lt;port&gt;"
+ </para>
+
+ <para>
+ The default query class (IN for internet) is overridden by the
+ <option>-c</option> option. <parameter>class</parameter> is
+ any valid
+ class, such as HS for Hesiod records or CH for Chaosnet records.
+ </para>
+
+ <para>
+ The <option>-f</option> option makes <command>dig </command>
+ operate
+ in batch mode by reading a list of lookup requests to process from the
+ file <parameter>filename</parameter>. The file contains a
+ number of
+ queries, one per line. Each entry in the file should be organized in
+ the same way they would be presented as queries to
+ <command>dig</command> using the command-line interface.
+ </para>
+
+ <para>
+ The <option>-m</option> option enables memory usage debugging.
+ <!-- It enables ISC_MEM_DEBUGTRACE and ISC_MEM_DEBUGRECORD
+ documented in include/isc/mem.h -->
+ </para>
+
+ <para>
+ If a non-standard port number is to be queried, the
+ <option>-p</option> option is used. <parameter>port#</parameter> is
+ the port number that <command>dig</command> will send its
+ queries
+ instead of the standard DNS port number 53. This option would be used
+ to test a name server that has been configured to listen for queries
+ on a non-standard port number.
+ </para>
+
+ <para>
+ The <option>-4</option> option forces <command>dig</command>
+ to only
+ use IPv4 query transport. The <option>-6</option> option forces
+ <command>dig</command> to only use IPv6 query transport.
+ </para>
+
+ <para>
+ The <option>-t</option> option sets the query type to
+ <parameter>type</parameter>. It can be any valid query type
+ which is
+ supported in BIND 9. The default query type is "A", unless the
+ <option>-x</option> option is supplied to indicate a reverse lookup.
+ A zone transfer can be requested by specifying a type of AXFR. When
+ an incremental zone transfer (IXFR) is required,
+ <parameter>type</parameter> is set to <literal>ixfr=N</literal>.
+ The incremental zone transfer will contain the changes made to the zone
+ since the serial number in the zone's SOA record was
+ <parameter>N</parameter>.
+ </para>
+
+ <para>
+ The <option>-q</option> option sets the query name to
+ <parameter>name</parameter>. This useful do distinguish the
+ <parameter>name</parameter> from other arguments.
+ </para>
+
+ <para>
+ Reverse lookups &mdash; mapping addresses to names &mdash; are simplified by the
+ <option>-x</option> option. <parameter>addr</parameter> is
+ an IPv4
+ address in dotted-decimal notation, or a colon-delimited IPv6 address.
+ When this option is used, there is no need to provide the
+ <parameter>name</parameter>, <parameter>class</parameter> and
+ <parameter>type</parameter> arguments. <command>dig</command>
+ automatically performs a lookup for a name like
+ <literal>11.12.13.10.in-addr.arpa</literal> and sets the
+ query type and
+ class to PTR and IN respectively. By default, IPv6 addresses are
+ looked up using nibble format under the IP6.ARPA domain.
+ To use the older RFC1886 method using the IP6.INT domain
+ specify the <option>-i</option> option. Bit string labels (RFC2874)
+ are now experimental and are not attempted.
+ </para>
+
+ <para>
+ To sign the DNS queries sent by <command>dig</command> and
+ their
+ responses using transaction signatures (TSIG), specify a TSIG key file
+ using the <option>-k</option> option. You can also specify the TSIG
+ key itself on the command line using the <option>-y</option> option;
+ <parameter>hmac</parameter> is the type of the TSIG, default HMAC-MD5,
+ <parameter>name</parameter> is the name of the TSIG key and
+ <parameter>key</parameter> is the actual key. The key is a
+ base-64
+ encoded string, typically generated by
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+
+ Caution should be taken when using the <option>-y</option> option on
+ multi-user systems as the key can be visible in the output from
+ <citerefentry>
+ <refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>
+ or in the shell's history file. When
+ using TSIG authentication with <command>dig</command>, the name
+ server that is queried needs to know the key and algorithm that is
+ being used. In BIND, this is done by providing appropriate
+ <command>key</command> and <command>server</command> statements in
+ <filename>named.conf</filename>.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>QUERY OPTIONS</title>
+
+ <para><command>dig</command>
+ provides a number of query options which affect
+ the way in which lookups are made and the results displayed. Some of
+ these set or reset flag bits in the query header, some determine which
+ sections of the answer get printed, and others determine the timeout
+ and retry strategies.
+ </para>
+
+ <para>
+ Each query option is identified by a keyword preceded by a plus sign
+ (<literal>+</literal>). Some keywords set or reset an
+ option. These may be preceded
+ by the string <literal>no</literal> to negate the meaning of
+ that keyword. Other
+ keywords assign values to options like the timeout interval. They
+ have the form <option>+keyword=value</option>.
+ The query options are:
+
+ <variablelist>
+
+ <varlistentry>
+ <term><option>+[no]tcp</option></term>
+ <listitem>
+ <para>
+ Use [do not use] TCP when querying name servers. The default
+ behavior is to use UDP unless an AXFR or IXFR query is
+ requested, in
+ which case a TCP connection is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]vc</option></term>
+ <listitem>
+ <para>
+ Use [do not use] TCP when querying name servers. This alternate
+ syntax to <parameter>+[no]tcp</parameter> is
+ provided for backwards
+ compatibility. The "vc" stands for "virtual circuit".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ignore</option></term>
+ <listitem>
+ <para>
+ Ignore truncation in UDP responses instead of retrying with TCP.
+ By
+ default, TCP retries are performed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+domain=somename</option></term>
+ <listitem>
+ <para>
+ Set the search list to contain the single domain
+ <parameter>somename</parameter>, as if specified in
+ a
+ <command>domain</command> directive in
+ <filename>/etc/resolv.conf</filename>, and enable
+ search list
+ processing as if the <parameter>+search</parameter>
+ option were given.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]search</option></term>
+ <listitem>
+ <para>
+ Use [do not use] the search list defined by the searchlist or
+ domain
+ directive in <filename>resolv.conf</filename> (if
+ any).
+ The search list is not used by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]showsearch</option></term>
+ <listitem>
+ <para>
+ Perform [do not perform] a search showing intermediate
+ results.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]defname</option></term>
+ <listitem>
+ <para>
+ Deprecated, treated as a synonym for <parameter>+[no]search</parameter>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]aaonly</option></term>
+ <listitem>
+ <para>
+ Sets the "aa" flag in the query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]aaflag</option></term>
+ <listitem>
+ <para>
+ A synonym for <parameter>+[no]aaonly</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]adflag</option></term>
+ <listitem>
+ <para>
+ Set [do not set] the AD (authentic data) bit in the query. The
+ AD bit
+ currently has a standard meaning only in responses, not in
+ queries,
+ but the ability to set the bit in the query is provided for
+ completeness.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cdflag</option></term>
+ <listitem>
+ <para>
+ Set [do not set] the CD (checking disabled) bit in the query.
+ This
+ requests the server to not perform DNSSEC validation of
+ responses.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cl</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the CLASS when printing the record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ttlid</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the TTL when printing the record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]recurse</option></term>
+ <listitem>
+ <para>
+ Toggle the setting of the RD (recursion desired) bit in the
+ query.
+ This bit is set by default, which means <command>dig</command>
+ normally sends recursive queries. Recursion is automatically
+ disabled
+ when the <parameter>+nssearch</parameter> or
+ <parameter>+trace</parameter> query options are
+ used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]nssearch</option></term>
+ <listitem>
+ <para>
+ When this option is set, <command>dig</command>
+ attempts to find the
+ authoritative name servers for the zone containing the name
+ being
+ looked up and display the SOA record that each name server has
+ for the
+ zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]trace</option></term>
+ <listitem>
+ <para>
+ Toggle tracing of the delegation path from the root name servers
+ for
+ the name being looked up. Tracing is disabled by default. When
+ tracing is enabled, <command>dig</command> makes
+ iterative queries to
+ resolve the name being looked up. It will follow referrals from
+ the
+ root servers, showing the answer from each server that was used
+ to
+ resolve the lookup.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cmd</option></term>
+ <listitem>
+ <para>
+ Toggles the printing of the initial comment in the output
+ identifying
+ the version of <command>dig</command> and the query
+ options that have
+ been applied. This comment is printed by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]short</option></term>
+ <listitem>
+ <para>
+ Provide a terse answer. The default is to print the answer in a
+ verbose form.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]identify</option></term>
+ <listitem>
+ <para>
+ Show [or do not show] the IP address and port number that
+ supplied the
+ answer when the <parameter>+short</parameter> option
+ is enabled. If
+ short form answers are requested, the default is not to show the
+ source address and port number of the server that provided the
+ answer.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]comments</option></term>
+ <listitem>
+ <para>
+ Toggle the display of comment lines in the output. The default
+ is to
+ print comments.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]stats</option></term>
+ <listitem>
+ <para>
+ This query option toggles the printing of statistics: when the
+ query
+ was made, the size of the reply and so on. The default
+ behavior is
+ to print the query statistics.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]qr</option></term>
+ <listitem>
+ <para>
+ Print [do not print] the query as it is sent.
+ By default, the query is not printed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]question</option></term>
+ <listitem>
+ <para>
+ Print [do not print] the question section of a query when an
+ answer is
+ returned. The default is to print the question section as a
+ comment.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]answer</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the answer section of a reply. The
+ default
+ is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]authority</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the authority section of a reply. The
+ default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]additional</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the additional section of a reply.
+ The default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]all</option></term>
+ <listitem>
+ <para>
+ Set or clear all display flags.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+time=T</option></term>
+ <listitem>
+ <para>
+
+ Sets the timeout for a query to
+ <parameter>T</parameter> seconds. The default
+ timeout is 5 seconds.
+ An attempt to set <parameter>T</parameter> to less
+ than 1 will result
+ in a query timeout of 1 second being applied.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+tries=T</option></term>
+ <listitem>
+ <para>
+ Sets the number of times to try UDP queries to server to
+ <parameter>T</parameter> instead of the default, 3.
+ If
+ <parameter>T</parameter> is less than or equal to
+ zero, the number of
+ tries is silently rounded up to 1.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+retry=T</option></term>
+ <listitem>
+ <para>
+ Sets the number of times to retry UDP queries to server to
+ <parameter>T</parameter> instead of the default, 2.
+ Unlike
+ <parameter>+tries</parameter>, this does not include
+ the initial
+ query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+ndots=D</option></term>
+ <listitem>
+ <para>
+ Set the number of dots that have to appear in
+ <parameter>name</parameter> to <parameter>D</parameter> for it to be
+ considered absolute. The default value is that defined using
+ the
+ ndots statement in <filename>/etc/resolv.conf</filename>, or 1 if no
+ ndots statement is present. Names with fewer dots are
+ interpreted as
+ relative names and will be searched for in the domains listed in
+ the
+ <option>search</option> or <option>domain</option> directive in
+ <filename>/etc/resolv.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+bufsize=B</option></term>
+ <listitem>
+ <para>
+ Set the UDP message buffer size advertised using EDNS0 to
+ <parameter>B</parameter> bytes. The maximum and minimum sizes
+ of this buffer are 65535 and 0 respectively. Values outside
+ this range are rounded up or down appropriately.
+ Values other than zero will cause a EDNS query to be sent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+edns=#</option></term>
+ <listitem>
+ <para>
+ Specify the EDNS version to query with. Valid values
+ are 0 to 255. Setting the EDNS version will cause a
+ EDNS query to be sent. <option>+noedns</option> clears the
+ remembered EDNS version.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]multiline</option></term>
+ <listitem>
+ <para>
+ Print records like the SOA records in a verbose multi-line
+ format with human-readable comments. The default is to print
+ each record on a single line, to facilitate machine parsing
+ of the <command>dig</command> output.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]fail</option></term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]besteffort</option></term>
+ <listitem>
+ <para>
+ Attempt to display the contents of messages which are malformed.
+ The default is to not display malformed answers.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]dnssec</option></term>
+ <listitem>
+ <para>
+ Requests DNSSEC records be sent by setting the DNSSEC OK bit
+ (DO)
+ in the OPT record in the additional section of the query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]sigchase</option></term>
+ <listitem>
+ <para>
+ Chase DNSSEC signature chains. Requires dig be compiled with
+ -DDIG_SIGCHASE.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+trusted-key=####</option></term>
+ <listitem>
+ <para>
+ Specifies a file containing trusted keys to be used with
+ <option>+sigchase</option>. Each DNSKEY record must be
+ on its own line.
+ </para>
+ <para>
+ If not specified <command>dig</command> will look for
+ <filename>/etc/trusted-key.key</filename> then
+ <filename>trusted-key.key</filename> in the current directory.
+ </para>
+ <para>
+ Requires dig be compiled with -DDIG_SIGCHASE.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]topdown</option></term>
+ <listitem>
+ <para>
+ When chasing DNSSEC signature chains perform a top-down
+ validation.
+ Requires dig be compiled with -DDIG_SIGCHASE.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]nsid</option></term>
+ <listitem>
+ <para>
+ Include an EDNS name server ID request when sending a query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ </variablelist>
+
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>MULTIPLE QUERIES</title>
+
+ <para>
+ The BIND 9 implementation of <command>dig </command>
+ supports
+ specifying multiple queries on the command line (in addition to
+ supporting the <option>-f</option> batch file option). Each of those
+ queries can be supplied with its own set of flags, options and query
+ options.
+ </para>
+
+ <para>
+ In this case, each <parameter>query</parameter> argument
+ represent an
+ individual query in the command-line syntax described above. Each
+ consists of any of the standard options and flags, the name to be
+ looked up, an optional query type and class and any query options that
+ should be applied to that query.
+ </para>
+
+ <para>
+ A global set of query options, which should be applied to all queries,
+ can also be supplied. These global query options must precede the
+ first tuple of name, class, type, options, flags, and query options
+ supplied on the command line. Any global query options (except
+ the <option>+[no]cmd</option> option) can be
+ overridden by a query-specific set of query options. For example:
+ <programlisting>
+dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr
+</programlisting>
+ shows how <command>dig</command> could be used from the
+ command line
+ to make three lookups: an ANY query for <literal>www.isc.org</literal>, a
+ reverse lookup of 127.0.0.1 and a query for the NS records of
+ <literal>isc.org</literal>.
+
+ A global query option of <parameter>+qr</parameter> is
+ applied, so
+ that <command>dig</command> shows the initial query it made
+ for each
+ lookup. The final query has a local query option of
+ <parameter>+noqr</parameter> which means that <command>dig</command>
+ will not print the initial query when it looks up the NS records for
+ <literal>isc.org</literal>.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>IDN SUPPORT</title>
+ <para>
+ If <command>dig</command> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <command>dig</command> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, defines
+ the <envar>IDN_DISABLE</envar> environment variable.
+ The IDN support is disabled if the variable is set when
+ <command>dig</command> runs.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ <para><filename>${HOME}/.digrc</filename>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>host</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>RFC1035</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>BUGS</title>
+ <para>
+ There are probably too many query options.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dig/dig.html b/bin/dig/dig.html
new file mode 100644
index 0000000..7c79c6e
--- /dev/null
+++ b/bin/dig/dig.html
@@ -0,0 +1,637 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: dig.html,v 1.45 2008/10/14 01:11:35 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dig</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.dig"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>dig &#8212; DNS lookup utility</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dig</code> [@server] [<code class="option">-b <em class="replaceable"><code>address</code></em></code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>filename</code></em></code>] [<code class="option">-k <em class="replaceable"><code>filename</code></em></code>] [<code class="option">-m</code>] [<code class="option">-p <em class="replaceable"><code>port#</code></em></code>] [<code class="option">-q <em class="replaceable"><code>name</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-x <em class="replaceable"><code>addr</code></em></code>] [<code class="option">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]name:key</code></em></code>] [<code class="option">-4</code>] [<code class="option">-6</code>] [name] [type] [class] [queryopt...]</p></div>
+<div class="cmdsynopsis"><p><code class="command">dig</code> [<code class="option">-h</code>]</p></div>
+<div class="cmdsynopsis"><p><code class="command">dig</code> [global-queryopt...] [query...]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543515"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dig</strong></span>
+ (domain information groper) is a flexible tool
+ for interrogating DNS name servers. It performs DNS lookups and
+ displays the answers that are returned from the name server(s) that
+ were queried. Most DNS administrators use <span><strong class="command">dig</strong></span> to
+ troubleshoot DNS problems because of its flexibility, ease of use and
+ clarity of output. Other lookup tools tend to have less functionality
+ than <span><strong class="command">dig</strong></span>.
+ </p>
+<p>
+ Although <span><strong class="command">dig</strong></span> is normally used with
+ command-line
+ arguments, it also has a batch mode of operation for reading lookup
+ requests from a file. A brief summary of its command-line arguments
+ and options is printed when the <code class="option">-h</code> option is given.
+ Unlike earlier versions, the BIND 9 implementation of
+ <span><strong class="command">dig</strong></span> allows multiple lookups to be issued
+ from the
+ command line.
+ </p>
+<p>
+ Unless it is told to query a specific name server,
+ <span><strong class="command">dig</strong></span> will try each of the servers listed
+ in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+<p>
+ When no command line arguments or options are given,
+ <span><strong class="command">dig</strong></span> will perform an NS query for "." (the root).
+ </p>
+<p>
+ It is possible to set per-user defaults for <span><strong class="command">dig</strong></span> via
+ <code class="filename">${HOME}/.digrc</code>. This file is read and
+ any options in it
+ are applied before the command line arguments.
+ </p>
+<p>
+ The IN and CH class names overlap with the IN and CH top level
+ domains names. Either use the <code class="option">-t</code> and
+ <code class="option">-c</code> options to specify the type and class,
+ use the <code class="option">-q</code> the specify the domain name, or
+ use "IN." and "CH." when looking up these top level domains.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543589"></a><h2>SIMPLE USAGE</h2>
+<p>
+ A typical invocation of <span><strong class="command">dig</strong></span> looks like:
+ </p>
+<pre class="programlisting"> dig @server name type </pre>
+<p>
+ where:
+
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">server</code></span></dt>
+<dd><p>
+ is the name or IP address of the name server to query. This can
+ be an IPv4
+ address in dotted-decimal notation or an IPv6
+ address in colon-delimited notation. When the supplied
+ <em class="parameter"><code>server</code></em> argument is a
+ hostname,
+ <span><strong class="command">dig</strong></span> resolves that name before
+ querying that name
+ server. If no <em class="parameter"><code>server</code></em>
+ argument is provided,
+ <span><strong class="command">dig</strong></span> consults <code class="filename">/etc/resolv.conf</code>
+ and queries the name servers listed there. The reply from the
+ name
+ server that responds is displayed.
+ </p></dd>
+<dt><span class="term"><code class="constant">name</code></span></dt>
+<dd><p>
+ is the name of the resource record that is to be looked up.
+ </p></dd>
+<dt><span class="term"><code class="constant">type</code></span></dt>
+<dd><p>
+ indicates what type of query is required &#8212;
+ ANY, A, MX, SIG, etc.
+ <em class="parameter"><code>type</code></em> can be any valid query
+ type. If no
+ <em class="parameter"><code>type</code></em> argument is supplied,
+ <span><strong class="command">dig</strong></span> will perform a lookup for an
+ A record.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543680"></a><h2>OPTIONS</h2>
+<p>
+ The <code class="option">-b</code> option sets the source IP address of the query
+ to <em class="parameter"><code>address</code></em>. This must be a valid
+ address on
+ one of the host's network interfaces or "0.0.0.0" or "::". An optional
+ port
+ may be specified by appending "#&lt;port&gt;"
+ </p>
+<p>
+ The default query class (IN for internet) is overridden by the
+ <code class="option">-c</code> option. <em class="parameter"><code>class</code></em> is
+ any valid
+ class, such as HS for Hesiod records or CH for Chaosnet records.
+ </p>
+<p>
+ The <code class="option">-f</code> option makes <span><strong class="command">dig </strong></span>
+ operate
+ in batch mode by reading a list of lookup requests to process from the
+ file <em class="parameter"><code>filename</code></em>. The file contains a
+ number of
+ queries, one per line. Each entry in the file should be organized in
+ the same way they would be presented as queries to
+ <span><strong class="command">dig</strong></span> using the command-line interface.
+ </p>
+<p>
+ The <code class="option">-m</code> option enables memory usage debugging.
+
+ </p>
+<p>
+ If a non-standard port number is to be queried, the
+ <code class="option">-p</code> option is used. <em class="parameter"><code>port#</code></em> is
+ the port number that <span><strong class="command">dig</strong></span> will send its
+ queries
+ instead of the standard DNS port number 53. This option would be used
+ to test a name server that has been configured to listen for queries
+ on a non-standard port number.
+ </p>
+<p>
+ The <code class="option">-4</code> option forces <span><strong class="command">dig</strong></span>
+ to only
+ use IPv4 query transport. The <code class="option">-6</code> option forces
+ <span><strong class="command">dig</strong></span> to only use IPv6 query transport.
+ </p>
+<p>
+ The <code class="option">-t</code> option sets the query type to
+ <em class="parameter"><code>type</code></em>. It can be any valid query type
+ which is
+ supported in BIND 9. The default query type is "A", unless the
+ <code class="option">-x</code> option is supplied to indicate a reverse lookup.
+ A zone transfer can be requested by specifying a type of AXFR. When
+ an incremental zone transfer (IXFR) is required,
+ <em class="parameter"><code>type</code></em> is set to <code class="literal">ixfr=N</code>.
+ The incremental zone transfer will contain the changes made to the zone
+ since the serial number in the zone's SOA record was
+ <em class="parameter"><code>N</code></em>.
+ </p>
+<p>
+ The <code class="option">-q</code> option sets the query name to
+ <em class="parameter"><code>name</code></em>. This useful do distinguish the
+ <em class="parameter"><code>name</code></em> from other arguments.
+ </p>
+<p>
+ Reverse lookups &#8212; mapping addresses to names &#8212; are simplified by the
+ <code class="option">-x</code> option. <em class="parameter"><code>addr</code></em> is
+ an IPv4
+ address in dotted-decimal notation, or a colon-delimited IPv6 address.
+ When this option is used, there is no need to provide the
+ <em class="parameter"><code>name</code></em>, <em class="parameter"><code>class</code></em> and
+ <em class="parameter"><code>type</code></em> arguments. <span><strong class="command">dig</strong></span>
+ automatically performs a lookup for a name like
+ <code class="literal">11.12.13.10.in-addr.arpa</code> and sets the
+ query type and
+ class to PTR and IN respectively. By default, IPv6 addresses are
+ looked up using nibble format under the IP6.ARPA domain.
+ To use the older RFC1886 method using the IP6.INT domain
+ specify the <code class="option">-i</code> option. Bit string labels (RFC2874)
+ are now experimental and are not attempted.
+ </p>
+<p>
+ To sign the DNS queries sent by <span><strong class="command">dig</strong></span> and
+ their
+ responses using transaction signatures (TSIG), specify a TSIG key file
+ using the <code class="option">-k</code> option. You can also specify the TSIG
+ key itself on the command line using the <code class="option">-y</code> option;
+ <em class="parameter"><code>hmac</code></em> is the type of the TSIG, default HMAC-MD5,
+ <em class="parameter"><code>name</code></em> is the name of the TSIG key and
+ <em class="parameter"><code>key</code></em> is the actual key. The key is a
+ base-64
+ encoded string, typically generated by
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>.
+
+ Caution should be taken when using the <code class="option">-y</code> option on
+ multi-user systems as the key can be visible in the output from
+ <span class="citerefentry"><span class="refentrytitle">ps</span>(1)</span>
+ or in the shell's history file. When
+ using TSIG authentication with <span><strong class="command">dig</strong></span>, the name
+ server that is queried needs to know the key and algorithm that is
+ being used. In BIND, this is done by providing appropriate
+ <span><strong class="command">key</strong></span> and <span><strong class="command">server</strong></span> statements in
+ <code class="filename">named.conf</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544028"></a><h2>QUERY OPTIONS</h2>
+<p><span><strong class="command">dig</strong></span>
+ provides a number of query options which affect
+ the way in which lookups are made and the results displayed. Some of
+ these set or reset flag bits in the query header, some determine which
+ sections of the answer get printed, and others determine the timeout
+ and retry strategies.
+ </p>
+<p>
+ Each query option is identified by a keyword preceded by a plus sign
+ (<code class="literal">+</code>). Some keywords set or reset an
+ option. These may be preceded
+ by the string <code class="literal">no</code> to negate the meaning of
+ that keyword. Other
+ keywords assign values to options like the timeout interval. They
+ have the form <code class="option">+keyword=value</code>.
+ The query options are:
+
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="option">+[no]tcp</code></span></dt>
+<dd><p>
+ Use [do not use] TCP when querying name servers. The default
+ behavior is to use UDP unless an AXFR or IXFR query is
+ requested, in
+ which case a TCP connection is used.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]vc</code></span></dt>
+<dd><p>
+ Use [do not use] TCP when querying name servers. This alternate
+ syntax to <em class="parameter"><code>+[no]tcp</code></em> is
+ provided for backwards
+ compatibility. The "vc" stands for "virtual circuit".
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]ignore</code></span></dt>
+<dd><p>
+ Ignore truncation in UDP responses instead of retrying with TCP.
+ By
+ default, TCP retries are performed.
+ </p></dd>
+<dt><span class="term"><code class="option">+domain=somename</code></span></dt>
+<dd><p>
+ Set the search list to contain the single domain
+ <em class="parameter"><code>somename</code></em>, as if specified in
+ a
+ <span><strong class="command">domain</strong></span> directive in
+ <code class="filename">/etc/resolv.conf</code>, and enable
+ search list
+ processing as if the <em class="parameter"><code>+search</code></em>
+ option were given.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]search</code></span></dt>
+<dd><p>
+ Use [do not use] the search list defined by the searchlist or
+ domain
+ directive in <code class="filename">resolv.conf</code> (if
+ any).
+ The search list is not used by default.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]showsearch</code></span></dt>
+<dd><p>
+ Perform [do not perform] a search showing intermediate
+ results.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]defname</code></span></dt>
+<dd><p>
+ Deprecated, treated as a synonym for <em class="parameter"><code>+[no]search</code></em>
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]aaonly</code></span></dt>
+<dd><p>
+ Sets the "aa" flag in the query.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]aaflag</code></span></dt>
+<dd><p>
+ A synonym for <em class="parameter"><code>+[no]aaonly</code></em>.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]adflag</code></span></dt>
+<dd><p>
+ Set [do not set] the AD (authentic data) bit in the query. The
+ AD bit
+ currently has a standard meaning only in responses, not in
+ queries,
+ but the ability to set the bit in the query is provided for
+ completeness.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]cdflag</code></span></dt>
+<dd><p>
+ Set [do not set] the CD (checking disabled) bit in the query.
+ This
+ requests the server to not perform DNSSEC validation of
+ responses.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]cl</code></span></dt>
+<dd><p>
+ Display [do not display] the CLASS when printing the record.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]ttlid</code></span></dt>
+<dd><p>
+ Display [do not display] the TTL when printing the record.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]recurse</code></span></dt>
+<dd><p>
+ Toggle the setting of the RD (recursion desired) bit in the
+ query.
+ This bit is set by default, which means <span><strong class="command">dig</strong></span>
+ normally sends recursive queries. Recursion is automatically
+ disabled
+ when the <em class="parameter"><code>+nssearch</code></em> or
+ <em class="parameter"><code>+trace</code></em> query options are
+ used.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]nssearch</code></span></dt>
+<dd><p>
+ When this option is set, <span><strong class="command">dig</strong></span>
+ attempts to find the
+ authoritative name servers for the zone containing the name
+ being
+ looked up and display the SOA record that each name server has
+ for the
+ zone.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]trace</code></span></dt>
+<dd><p>
+ Toggle tracing of the delegation path from the root name servers
+ for
+ the name being looked up. Tracing is disabled by default. When
+ tracing is enabled, <span><strong class="command">dig</strong></span> makes
+ iterative queries to
+ resolve the name being looked up. It will follow referrals from
+ the
+ root servers, showing the answer from each server that was used
+ to
+ resolve the lookup.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]cmd</code></span></dt>
+<dd><p>
+ Toggles the printing of the initial comment in the output
+ identifying
+ the version of <span><strong class="command">dig</strong></span> and the query
+ options that have
+ been applied. This comment is printed by default.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]short</code></span></dt>
+<dd><p>
+ Provide a terse answer. The default is to print the answer in a
+ verbose form.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]identify</code></span></dt>
+<dd><p>
+ Show [or do not show] the IP address and port number that
+ supplied the
+ answer when the <em class="parameter"><code>+short</code></em> option
+ is enabled. If
+ short form answers are requested, the default is not to show the
+ source address and port number of the server that provided the
+ answer.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]comments</code></span></dt>
+<dd><p>
+ Toggle the display of comment lines in the output. The default
+ is to
+ print comments.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]stats</code></span></dt>
+<dd><p>
+ This query option toggles the printing of statistics: when the
+ query
+ was made, the size of the reply and so on. The default
+ behavior is
+ to print the query statistics.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]qr</code></span></dt>
+<dd><p>
+ Print [do not print] the query as it is sent.
+ By default, the query is not printed.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]question</code></span></dt>
+<dd><p>
+ Print [do not print] the question section of a query when an
+ answer is
+ returned. The default is to print the question section as a
+ comment.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]answer</code></span></dt>
+<dd><p>
+ Display [do not display] the answer section of a reply. The
+ default
+ is to display it.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]authority</code></span></dt>
+<dd><p>
+ Display [do not display] the authority section of a reply. The
+ default is to display it.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]additional</code></span></dt>
+<dd><p>
+ Display [do not display] the additional section of a reply.
+ The default is to display it.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]all</code></span></dt>
+<dd><p>
+ Set or clear all display flags.
+ </p></dd>
+<dt><span class="term"><code class="option">+time=T</code></span></dt>
+<dd><p>
+
+ Sets the timeout for a query to
+ <em class="parameter"><code>T</code></em> seconds. The default
+ timeout is 5 seconds.
+ An attempt to set <em class="parameter"><code>T</code></em> to less
+ than 1 will result
+ in a query timeout of 1 second being applied.
+ </p></dd>
+<dt><span class="term"><code class="option">+tries=T</code></span></dt>
+<dd><p>
+ Sets the number of times to try UDP queries to server to
+ <em class="parameter"><code>T</code></em> instead of the default, 3.
+ If
+ <em class="parameter"><code>T</code></em> is less than or equal to
+ zero, the number of
+ tries is silently rounded up to 1.
+ </p></dd>
+<dt><span class="term"><code class="option">+retry=T</code></span></dt>
+<dd><p>
+ Sets the number of times to retry UDP queries to server to
+ <em class="parameter"><code>T</code></em> instead of the default, 2.
+ Unlike
+ <em class="parameter"><code>+tries</code></em>, this does not include
+ the initial
+ query.
+ </p></dd>
+<dt><span class="term"><code class="option">+ndots=D</code></span></dt>
+<dd><p>
+ Set the number of dots that have to appear in
+ <em class="parameter"><code>name</code></em> to <em class="parameter"><code>D</code></em> for it to be
+ considered absolute. The default value is that defined using
+ the
+ ndots statement in <code class="filename">/etc/resolv.conf</code>, or 1 if no
+ ndots statement is present. Names with fewer dots are
+ interpreted as
+ relative names and will be searched for in the domains listed in
+ the
+ <code class="option">search</code> or <code class="option">domain</code> directive in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p></dd>
+<dt><span class="term"><code class="option">+bufsize=B</code></span></dt>
+<dd><p>
+ Set the UDP message buffer size advertised using EDNS0 to
+ <em class="parameter"><code>B</code></em> bytes. The maximum and minimum sizes
+ of this buffer are 65535 and 0 respectively. Values outside
+ this range are rounded up or down appropriately.
+ Values other than zero will cause a EDNS query to be sent.
+ </p></dd>
+<dt><span class="term"><code class="option">+edns=#</code></span></dt>
+<dd><p>
+ Specify the EDNS version to query with. Valid values
+ are 0 to 255. Setting the EDNS version will cause a
+ EDNS query to be sent. <code class="option">+noedns</code> clears the
+ remembered EDNS version.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]multiline</code></span></dt>
+<dd><p>
+ Print records like the SOA records in a verbose multi-line
+ format with human-readable comments. The default is to print
+ each record on a single line, to facilitate machine parsing
+ of the <span><strong class="command">dig</strong></span> output.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]fail</code></span></dt>
+<dd><p>
+ 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.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]besteffort</code></span></dt>
+<dd><p>
+ Attempt to display the contents of messages which are malformed.
+ The default is to not display malformed answers.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]dnssec</code></span></dt>
+<dd><p>
+ Requests DNSSEC records be sent by setting the DNSSEC OK bit
+ (DO)
+ in the OPT record in the additional section of the query.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]sigchase</code></span></dt>
+<dd><p>
+ Chase DNSSEC signature chains. Requires dig be compiled with
+ -DDIG_SIGCHASE.
+ </p></dd>
+<dt><span class="term"><code class="option">+trusted-key=####</code></span></dt>
+<dd>
+<p>
+ Specifies a file containing trusted keys to be used with
+ <code class="option">+sigchase</code>. Each DNSKEY record must be
+ on its own line.
+ </p>
+<p>
+ If not specified <span><strong class="command">dig</strong></span> will look for
+ <code class="filename">/etc/trusted-key.key</code> then
+ <code class="filename">trusted-key.key</code> in the current directory.
+ </p>
+<p>
+ Requires dig be compiled with -DDIG_SIGCHASE.
+ </p>
+</dd>
+<dt><span class="term"><code class="option">+[no]topdown</code></span></dt>
+<dd><p>
+ When chasing DNSSEC signature chains perform a top-down
+ validation.
+ Requires dig be compiled with -DDIG_SIGCHASE.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]nsid</code></span></dt>
+<dd><p>
+ Include an EDNS name server ID request when sending a query.
+ </p></dd>
+</dl></div>
+<p>
+
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545163"></a><h2>MULTIPLE QUERIES</h2>
+<p>
+ The BIND 9 implementation of <span><strong class="command">dig </strong></span>
+ supports
+ specifying multiple queries on the command line (in addition to
+ supporting the <code class="option">-f</code> batch file option). Each of those
+ queries can be supplied with its own set of flags, options and query
+ options.
+ </p>
+<p>
+ In this case, each <em class="parameter"><code>query</code></em> argument
+ represent an
+ individual query in the command-line syntax described above. Each
+ consists of any of the standard options and flags, the name to be
+ looked up, an optional query type and class and any query options that
+ should be applied to that query.
+ </p>
+<p>
+ A global set of query options, which should be applied to all queries,
+ can also be supplied. These global query options must precede the
+ first tuple of name, class, type, options, flags, and query options
+ supplied on the command line. Any global query options (except
+ the <code class="option">+[no]cmd</code> option) can be
+ overridden by a query-specific set of query options. For example:
+ </p>
+<pre class="programlisting">
+dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr
+</pre>
+<p>
+ shows how <span><strong class="command">dig</strong></span> could be used from the
+ command line
+ to make three lookups: an ANY query for <code class="literal">www.isc.org</code>, a
+ reverse lookup of 127.0.0.1 and a query for the NS records of
+ <code class="literal">isc.org</code>.
+
+ A global query option of <em class="parameter"><code>+qr</code></em> is
+ applied, so
+ that <span><strong class="command">dig</strong></span> shows the initial query it made
+ for each
+ lookup. The final query has a local query option of
+ <em class="parameter"><code>+noqr</code></em> which means that <span><strong class="command">dig</strong></span>
+ will not print the initial query when it looks up the NS records for
+ <code class="literal">isc.org</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545225"></a><h2>IDN SUPPORT</h2>
+<p>
+ If <span><strong class="command">dig</strong></span> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <span><strong class="command">dig</strong></span> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, defines
+ the <code class="envar">IDN_DISABLE</code> environment variable.
+ The IDN support is disabled if the variable is set when
+ <span><strong class="command">dig</strong></span> runs.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545248"></a><h2>FILES</h2>
+<p><code class="filename">/etc/resolv.conf</code>
+ </p>
+<p><code class="filename">${HOME}/.digrc</code>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545333"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">host</span>(1)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <em class="citetitle">RFC1035</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545370"></a><h2>BUGS</h2>
+<p>
+ There are probably too many query options.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
new file mode 100644
index 0000000..8665944
--- /dev/null
+++ b/bin/dig/dighost.c
@@ -0,0 +1,5420 @@
+/*
+ * 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
+ * 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: dighost.c,v 1.311 2008/07/23 23:27:54 marka Exp $ */
+
+/*! \file
+ * \note
+ * Notice to programmers: Do not use this code as an example of how to
+ * use the ISC library to perform DNS lookups. Dig and Host both operate
+ * on the request level, since they allow fine-tuning of output and are
+ * intended as debugging tools. As a result, they perform many of the
+ * functions which could be better handled using the dns_resolver
+ * functions in most applications.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#ifdef WITH_IDN
+#include <idn/result.h>
+#include <idn/log.h>
+#include <idn/resconf.h>
+#include <idn/api.h>
+#endif
+
+#include <dns/byaddr.h>
+#ifdef DIG_SIGCHASE
+#include <dns/dnssec.h>
+#include <dns/ds.h>
+#include <dns/nsec.h>
+#include <isc/random.h>
+#include <ctype.h>
+#endif
+#include <dns/fixedname.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/tsig.h>
+
+#include <dst/dst.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/lang.h>
+#include <isc/netaddr.h>
+#ifdef DIG_SIGCHASE
+#include <isc/netdb.h>
+#endif
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+
+#include <bind9/getaddresses.h>
+
+#include <dig/dig.h>
+
+#if ! defined(NS_INADDRSZ)
+#define NS_INADDRSZ 4
+#endif
+
+#if ! defined(NS_IN6ADDRSZ)
+#define NS_IN6ADDRSZ 16
+#endif
+
+static lwres_context_t *lwctx = NULL;
+static lwres_conf_t *lwconf;
+
+dig_lookuplist_t lookup_list;
+dig_serverlist_t server_list;
+dig_searchlistlist_t search_list;
+
+isc_boolean_t
+ check_ra = ISC_FALSE,
+ have_ipv4 = ISC_FALSE,
+ have_ipv6 = ISC_FALSE,
+ specified_source = ISC_FALSE,
+ free_now = ISC_FALSE,
+ cancel_now = ISC_FALSE,
+ usesearch = ISC_FALSE,
+ showsearch = ISC_FALSE,
+ qr = ISC_FALSE,
+ is_dst_up = ISC_FALSE;
+in_port_t port = 53;
+unsigned int timeout = 0;
+unsigned int extrabytes;
+isc_mem_t *mctx = NULL;
+isc_taskmgr_t *taskmgr = NULL;
+isc_task_t *global_task = NULL;
+isc_timermgr_t *timermgr = NULL;
+isc_socketmgr_t *socketmgr = NULL;
+isc_sockaddr_t bind_address;
+isc_sockaddr_t bind_any;
+int sendcount = 0;
+int recvcount = 0;
+int sockcount = 0;
+int ndots = -1;
+int tries = 3;
+int lookup_counter = 0;
+
+#ifdef WITH_IDN
+static void initialize_idn(void);
+static isc_result_t output_filter(isc_buffer_t *buffer,
+ unsigned int used_org,
+ isc_boolean_t absolute);
+static idn_result_t append_textname(char *name, const char *origin,
+ size_t namesize);
+static void idn_check_result(idn_result_t r, const char *msg);
+
+#define MAXDLEN 256
+int idnoptions = 0;
+#endif
+
+/*%
+ * Exit Codes:
+ *
+ *\li 0 Everything went well, including things like NXDOMAIN
+ *\li 1 Usage error
+ *\li 7 Got too many RR's or Names
+ *\li 8 Couldn't open batch file
+ *\li 9 No reply from server
+ *\li 10 Internal error
+ */
+int exitcode = 0;
+int fatalexit = 0;
+char keynametext[MXNAME];
+char keyfile[MXNAME] = "";
+char keysecret[MXNAME] = "";
+dns_name_t *hmacname = NULL;
+unsigned int digestbits = 0;
+isc_buffer_t *namebuf = NULL;
+dns_tsigkey_t *key = NULL;
+isc_boolean_t validated = ISC_TRUE;
+isc_entropy_t *entp = NULL;
+isc_mempool_t *commctx = NULL;
+isc_boolean_t debugging = ISC_FALSE;
+isc_boolean_t memdebugging = ISC_FALSE;
+char *progname = NULL;
+isc_mutex_t lookup_lock;
+dig_lookup_t *current_lookup = NULL;
+
+#ifdef DIG_SIGCHASE
+
+isc_result_t get_trusted_key(isc_mem_t *mctx);
+dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ isc_boolean_t *lookedup,
+ dns_name_t *rdata_name);
+dns_rdataset_t * chase_scanname_section(dns_message_t *msg,
+ dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ int section);
+isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset,
+ dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ isc_boolean_t *lookedup);
+isc_result_t sigchase_verify_sig_key(dns_name_t *name,
+ dns_rdataset_t *rdataset,
+ dst_key_t* dnsseckey,
+ dns_rdataset_t *sigrdataset,
+ isc_mem_t *mctx);
+isc_result_t sigchase_verify_sig(dns_name_t *name,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *sigrdataset,
+ isc_mem_t *mctx);
+isc_result_t sigchase_verify_ds(dns_name_t *name,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *dsrdataset,
+ isc_mem_t *mctx);
+void sigchase(dns_message_t *msg);
+void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
+void print_rdataset(dns_name_t *name,
+ dns_rdataset_t *rdataset, isc_mem_t *mctx);
+void dup_name(dns_name_t *source, dns_name_t* target,
+ isc_mem_t *mctx);
+void free_name(dns_name_t *name, isc_mem_t *mctx);
+void dump_database(void);
+void dump_database_section(dns_message_t *msg, int section);
+dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type,
+ dns_rdatatype_t covers);
+isc_result_t contains_trusted_key(dns_name_t *name,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset,
+ isc_mem_t *mctx);
+void print_type(dns_rdatatype_t type);
+isc_result_t prove_nx_domain(dns_message_t * msg,
+ dns_name_t * name,
+ dns_name_t * rdata_name,
+ dns_rdataset_t ** rdataset,
+ dns_rdataset_t ** sigrdataset);
+isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name,
+ dns_rdataset_t *nsec,
+ dns_rdataclass_t class,
+ dns_rdatatype_t type,
+ dns_name_t * rdata_name,
+ dns_rdataset_t ** rdataset,
+ dns_rdataset_t ** sigrdataset);
+isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name,
+ dns_rdataclass_t class,
+ dns_rdatatype_t type,
+ dns_name_t * rdata_name,
+ dns_rdataset_t ** rdataset,
+ dns_rdataset_t ** sigrdataset);
+static void nameFromString(const char *str, dns_name_t *p_ret);
+int inf_name(dns_name_t * name1, dns_name_t * name2);
+isc_result_t opentmpkey(isc_mem_t *mctx, const char *file,
+ char **tempp, FILE **fp);
+isc_result_t removetmpkey(isc_mem_t *mctx, const char *file);
+void clean_trustedkey(void);
+void insert_trustedkey(dst_key_t * key);
+#if DIG_SIGCHASE_BU
+isc_result_t getneededrr(dns_message_t *msg);
+void sigchase_bottom_up(dns_message_t *msg);
+void sigchase_bu(dns_message_t *msg);
+#endif
+#if DIG_SIGCHASE_TD
+isc_result_t initialization(dns_name_t *name);
+isc_result_t prepare_lookup(dns_name_t *name);
+isc_result_t grandfather_pb_test(dns_name_t * zone_name,
+ dns_rdataset_t *sigrdataset);
+isc_result_t child_of_zone(dns_name_t *name,
+ dns_name_t *zone_name,
+ dns_name_t *child_name);
+void sigchase_td(dns_message_t *msg);
+#endif
+char trustedkey[MXNAME] = "";
+
+dns_rdataset_t *chase_rdataset = NULL;
+dns_rdataset_t *chase_sigrdataset = NULL;
+dns_rdataset_t *chase_dsrdataset = NULL;
+dns_rdataset_t *chase_sigdsrdataset = NULL;
+dns_rdataset_t *chase_keyrdataset = NULL;
+dns_rdataset_t *chase_sigkeyrdataset = NULL;
+dns_rdataset_t *chase_nsrdataset = NULL;
+
+dns_name_t chase_name; /* the query name */
+#if DIG_SIGCHASE_TD
+/*
+ * the current name is the parent name when we follow delegation
+ */
+dns_name_t chase_current_name;
+/*
+ * the child name is used for delegation (NS DS responses in AUTHORITY section)
+ */
+dns_name_t chase_authority_name;
+#endif
+#if DIG_SIGCHASE_BU
+dns_name_t chase_signame;
+#endif
+
+
+isc_boolean_t chase_siglookedup = ISC_FALSE;
+isc_boolean_t chase_keylookedup = ISC_FALSE;
+isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
+isc_boolean_t chase_dslookedup = ISC_FALSE;
+isc_boolean_t chase_sigdslookedup = ISC_FALSE;
+#if DIG_SIGCHASE_TD
+isc_boolean_t chase_nslookedup = ISC_FALSE;
+isc_boolean_t chase_lookedup = ISC_FALSE;
+
+
+isc_boolean_t delegation_follow = ISC_FALSE;
+isc_boolean_t grandfather_pb = ISC_FALSE;
+isc_boolean_t have_response = ISC_FALSE;
+isc_boolean_t have_delegation_ns = ISC_FALSE;
+dns_message_t * error_message = NULL;
+#endif
+
+isc_boolean_t dsvalidating = ISC_FALSE;
+isc_boolean_t chase_name_dup = ISC_FALSE;
+
+ISC_LIST(dig_message_t) chase_message_list;
+ISC_LIST(dig_message_t) chase_message_list2;
+
+
+#define MAX_TRUSTED_KEY 5
+typedef struct struct_trusted_key_list {
+ dst_key_t * key[MAX_TRUSTED_KEY];
+ int nb_tk;
+} struct_tk_list;
+
+struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
+
+#endif
+
+#define DIG_MAX_ADDRESSES 20
+
+/*%
+ * Apply and clear locks at the event level in global task.
+ * Can I get rid of these using shutdown events? XXX
+ */
+#define LOCK_LOOKUP {\
+ debug("lock_lookup %s:%d", __FILE__, __LINE__);\
+ check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
+ debug("success");\
+}
+#define UNLOCK_LOOKUP {\
+ debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
+ check_result(isc_mutex_unlock((&lookup_lock)),\
+ "isc_mutex_unlock");\
+}
+
+static void
+cancel_lookup(dig_lookup_t *lookup);
+
+static void
+recv_done(isc_task_t *task, isc_event_t *event);
+
+static void
+send_udp(dig_query_t *query);
+
+static void
+connect_timeout(isc_task_t *task, isc_event_t *event);
+
+static void
+launch_next_query(dig_query_t *query, isc_boolean_t include_question);
+
+
+static void *
+mem_alloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+static void
+mem_free(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+
+char *
+next_token(char **stringp, const char *delim) {
+ char *res;
+
+ do {
+ res = strsep(stringp, delim);
+ if (res == NULL)
+ break;
+ } while (*res == '\0');
+ return (res);
+}
+
+static int
+count_dots(char *string) {
+ char *s;
+ int i = 0;
+
+ s = string;
+ while (*s != '\0') {
+ if (*s == '.')
+ i++;
+ s++;
+ }
+ return (i);
+}
+
+static void
+hex_dump(isc_buffer_t *b) {
+ unsigned int len;
+ isc_region_t r;
+
+ isc_buffer_usedregion(b, &r);
+
+ printf("%d bytes\n", r.length);
+ for (len = 0; len < r.length; len++) {
+ printf("%02x ", r.base[len]);
+ if (len % 16 == 15)
+ printf("\n");
+ }
+ if (len % 16 != 0)
+ printf("\n");
+}
+
+/*%
+ * Append 'len' bytes of 'text' at '*p', failing with
+ * ISC_R_NOSPACE if that would advance p past 'end'.
+ */
+static isc_result_t
+append(const char *text, int len, char **p, char *end) {
+ if (len > end - *p)
+ return (ISC_R_NOSPACE);
+ memcpy(*p, text, len);
+ *p += len;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+reverse_octets(const char *in, char **p, char *end) {
+ char *dot = strchr(in, '.');
+ int len;
+ if (dot != NULL) {
+ isc_result_t result;
+ result = reverse_octets(dot + 1, p, end);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = append(".", 1, p, end);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ len = dot - in;
+ } else {
+ len = strlen(in);
+ }
+ return (append(in, len, p, end));
+}
+
+isc_result_t
+get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
+ isc_boolean_t strict)
+{
+ int r;
+ isc_result_t result;
+ isc_netaddr_t addr;
+
+ addr.family = AF_INET6;
+ r = inet_pton(AF_INET6, value, &addr.type.in6);
+ if (r > 0) {
+ /* This is a valid IPv6 address. */
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ unsigned int options = 0;
+
+ if (ip6_int)
+ options |= DNS_BYADDROPT_IPV6INT;
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ result = dns_byaddr_createptrname2(&addr, options, name);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_name_format(name, reverse, len);
+ return (ISC_R_SUCCESS);
+ } else {
+ /*
+ * Not a valid IPv6 address. Assume IPv4.
+ * If 'strict' is not set, construct the
+ * in-addr.arpa name by blindly reversing
+ * octets whether or not they look like integers,
+ * so that this can be used for RFC2317 names
+ * and such.
+ */
+ char *p = reverse;
+ char *end = reverse + len;
+ if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
+ return (DNS_R_BADDOTTEDQUAD);
+ result = reverse_octets(value, &p, end);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ /* Append .in-addr.arpa. and a terminating NUL. */
+ result = append(".in-addr.arpa.", 15, &p, end);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (ISC_R_SUCCESS);
+ }
+}
+
+void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, "%s: ", progname);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ if (exitcode < 10)
+ exitcode = 10;
+ if (fatalexit != 0)
+ exitcode = fatalexit;
+ exit(exitcode);
+}
+
+void
+debug(const char *format, ...) {
+ va_list args;
+
+ if (debugging) {
+ fflush(stdout);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+void
+check_result(isc_result_t result, const char *msg) {
+ if (result != ISC_R_SUCCESS) {
+ fatal("%s: %s", msg, isc_result_totext(result));
+ }
+}
+
+/*%
+ * Create a server structure, which is part of the lookup structure.
+ * This is little more than a linked list of servers to query in hopes
+ * of finding the answer the user is looking for
+ */
+dig_server_t *
+make_server(const char *servname, const char *userarg) {
+ dig_server_t *srv;
+
+ REQUIRE(servname != NULL);
+
+ debug("make_server(%s)", servname);
+ srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
+ if (srv == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ strncpy(srv->servername, servname, MXNAME);
+ strncpy(srv->userarg, userarg, MXNAME);
+ srv->servername[MXNAME-1] = 0;
+ srv->userarg[MXNAME-1] = 0;
+ ISC_LINK_INIT(srv, link);
+ return (srv);
+}
+
+static int
+addr2af(int lwresaddrtype)
+{
+ int af = 0;
+
+ switch (lwresaddrtype) {
+ case LWRES_ADDRTYPE_V4:
+ af = AF_INET;
+ break;
+
+ case LWRES_ADDRTYPE_V6:
+ af = AF_INET6;
+ break;
+ }
+
+ return (af);
+}
+
+/*%
+ * Create a copy of the server list from the lwres configuration structure.
+ * The dest list must have already had ISC_LIST_INIT applied.
+ */
+static void
+copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
+ dig_server_t *newsrv;
+ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+ int af;
+ int i;
+
+ debug("copy_server_list()");
+ for (i = 0; i < confdata->nsnext; i++) {
+ af = addr2af(confdata->nameservers[i].family);
+
+ lwres_net_ntop(af, confdata->nameservers[i].address,
+ tmp, sizeof(tmp));
+ newsrv = make_server(tmp, tmp);
+ ISC_LINK_INIT(newsrv, link);
+ ISC_LIST_ENQUEUE(*dest, newsrv, link);
+ }
+}
+
+void
+flush_server_list(void) {
+ dig_server_t *s, *ps;
+
+ debug("flush_server_list()");
+ s = ISC_LIST_HEAD(server_list);
+ while (s != NULL) {
+ ps = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(server_list, ps, link);
+ isc_mem_free(mctx, ps);
+ }
+}
+
+void
+set_nameserver(char *opt) {
+ isc_result_t result;
+ isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
+ isc_netaddr_t netaddr;
+ int count, i;
+ dig_server_t *srv;
+ char tmp[ISC_NETADDR_FORMATSIZE];
+
+ if (opt == NULL)
+ return;
+
+ result = bind9_getaddresses(opt, 0, sockaddrs,
+ DIG_MAX_ADDRESSES, &count);
+ if (result != ISC_R_SUCCESS)
+ fatal("couldn't get address for '%s': %s",
+ opt, isc_result_totext(result));
+
+ flush_server_list();
+
+ for (i = 0; i < count; i++) {
+ isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
+ isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
+ srv = make_server(tmp, opt);
+ if (srv == NULL)
+ fatal("memory allocation failure");
+ ISC_LIST_APPEND(server_list, srv, link);
+ }
+}
+
+static isc_result_t
+add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
+
+ int i = confdata->nsnext;
+
+ if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
+ return (ISC_R_FAILURE);
+
+ switch (af) {
+ case AF_INET:
+ confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
+ confdata->nameservers[i].length = NS_INADDRSZ;
+ break;
+ case AF_INET6:
+ confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
+ confdata->nameservers[i].length = NS_IN6ADDRSZ;
+ break;
+ default:
+ return (ISC_R_FAILURE);
+ }
+
+ if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
+ confdata->nsnext++;
+ return (ISC_R_SUCCESS);
+ }
+ return (ISC_R_FAILURE);
+}
+
+/*%
+ * Produce a cloned server list. The dest list must have already had
+ * ISC_LIST_INIT applied.
+ */
+void
+clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
+ dig_server_t *srv, *newsrv;
+
+ debug("clone_server_list()");
+ srv = ISC_LIST_HEAD(src);
+ while (srv != NULL) {
+ newsrv = make_server(srv->servername, srv->userarg);
+ ISC_LINK_INIT(newsrv, link);
+ ISC_LIST_ENQUEUE(*dest, newsrv, link);
+ srv = ISC_LIST_NEXT(srv, link);
+ }
+}
+
+/*%
+ * Create an empty lookup structure, which holds all the information needed
+ * to get an answer to a user's question. This structure contains two
+ * linked lists: the server list (servers to query) and the query list
+ * (outstanding queries which have been made to the listed servers).
+ */
+dig_lookup_t *
+make_empty_lookup(void) {
+ dig_lookup_t *looknew;
+
+ debug("make_empty_lookup()");
+
+ INSIST(!free_now);
+
+ looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
+ if (looknew == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ looknew->pending = ISC_TRUE;
+ looknew->textname[0] = 0;
+ looknew->cmdline[0] = 0;
+ looknew->rdtype = dns_rdatatype_a;
+ looknew->qrdtype = dns_rdatatype_a;
+ looknew->rdclass = dns_rdataclass_in;
+ looknew->rdtypeset = ISC_FALSE;
+ looknew->rdclassset = ISC_FALSE;
+ looknew->sendspace = NULL;
+ looknew->sendmsg = NULL;
+ looknew->name = NULL;
+ looknew->oname = NULL;
+ looknew->timer = NULL;
+ looknew->xfr_q = NULL;
+ looknew->current_query = NULL;
+ looknew->doing_xfr = ISC_FALSE;
+ looknew->ixfr_serial = ISC_FALSE;
+ looknew->trace = ISC_FALSE;
+ looknew->trace_root = ISC_FALSE;
+ looknew->identify = ISC_FALSE;
+ looknew->identify_previous_line = ISC_FALSE;
+ looknew->ignore = ISC_FALSE;
+ looknew->servfail_stops = ISC_TRUE;
+ looknew->besteffort = ISC_TRUE;
+ looknew->dnssec = ISC_FALSE;
+ looknew->nsid = ISC_FALSE;
+#ifdef DIG_SIGCHASE
+ looknew->sigchase = ISC_FALSE;
+#if DIG_SIGCHASE_TD
+ looknew->do_topdown = ISC_FALSE;
+ looknew->trace_root_sigchase = ISC_FALSE;
+ looknew->rdtype_sigchaseset = ISC_FALSE;
+ looknew->rdtype_sigchase = dns_rdatatype_any;
+ looknew->qrdtype_sigchase = dns_rdatatype_any;
+ looknew->rdclass_sigchase = dns_rdataclass_in;
+ looknew->rdclass_sigchaseset = ISC_FALSE;
+#endif
+#endif
+ looknew->udpsize = 0;
+ looknew->edns = -1;
+ looknew->recurse = ISC_TRUE;
+ looknew->aaonly = ISC_FALSE;
+ looknew->adflag = ISC_FALSE;
+ looknew->cdflag = ISC_FALSE;
+ looknew->ns_search_only = ISC_FALSE;
+ looknew->origin = NULL;
+ looknew->tsigctx = NULL;
+ looknew->querysig = NULL;
+ looknew->retries = tries;
+ looknew->nsfound = 0;
+ looknew->tcp_mode = ISC_FALSE;
+ looknew->ip6_int = ISC_FALSE;
+ looknew->comments = ISC_TRUE;
+ looknew->stats = ISC_TRUE;
+ looknew->section_question = ISC_TRUE;
+ looknew->section_answer = ISC_TRUE;
+ looknew->section_authority = ISC_TRUE;
+ looknew->section_additional = ISC_TRUE;
+ looknew->new_search = ISC_FALSE;
+ looknew->done_as_is = ISC_FALSE;
+ looknew->need_search = ISC_FALSE;
+ ISC_LINK_INIT(looknew, link);
+ ISC_LIST_INIT(looknew->q);
+ ISC_LIST_INIT(looknew->my_server_list);
+ return (looknew);
+}
+
+/*%
+ * Clone a lookup, perhaps copying the server list. This does not clone
+ * the query list, since it will be regenerated by the setup_lookup()
+ * function, nor does it queue up the new lookup for processing.
+ * Caution: If you don't clone the servers, you MUST clone the server
+ * list seperately from somewhere else, or construct it by hand.
+ */
+dig_lookup_t *
+clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
+ dig_lookup_t *looknew;
+
+ debug("clone_lookup()");
+
+ INSIST(!free_now);
+
+ looknew = make_empty_lookup();
+ INSIST(looknew != NULL);
+ strncpy(looknew->textname, lookold->textname, MXNAME);
+#if DIG_SIGCHASE_TD
+ strncpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
+#endif
+ strncpy(looknew->cmdline, lookold->cmdline, MXNAME);
+ looknew->textname[MXNAME-1] = 0;
+ looknew->rdtype = lookold->rdtype;
+ looknew->qrdtype = lookold->qrdtype;
+ looknew->rdclass = lookold->rdclass;
+ looknew->rdtypeset = lookold->rdtypeset;
+ looknew->rdclassset = lookold->rdclassset;
+ looknew->doing_xfr = lookold->doing_xfr;
+ looknew->ixfr_serial = lookold->ixfr_serial;
+ looknew->trace = lookold->trace;
+ looknew->trace_root = lookold->trace_root;
+ looknew->identify = lookold->identify;
+ looknew->identify_previous_line = lookold->identify_previous_line;
+ looknew->ignore = lookold->ignore;
+ looknew->servfail_stops = lookold->servfail_stops;
+ looknew->besteffort = lookold->besteffort;
+ looknew->dnssec = lookold->dnssec;
+ looknew->nsid = lookold->nsid;
+#ifdef DIG_SIGCHASE
+ looknew->sigchase = lookold->sigchase;
+#if DIG_SIGCHASE_TD
+ looknew->do_topdown = lookold->do_topdown;
+ looknew->trace_root_sigchase = lookold->trace_root_sigchase;
+ looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
+ looknew->rdtype_sigchase = lookold->rdtype_sigchase;
+ looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
+ looknew->rdclass_sigchase = lookold->rdclass_sigchase;
+ looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
+#endif
+#endif
+ looknew->udpsize = lookold->udpsize;
+ looknew->edns = lookold->edns;
+ looknew->recurse = lookold->recurse;
+ looknew->aaonly = lookold->aaonly;
+ looknew->adflag = lookold->adflag;
+ looknew->cdflag = lookold->cdflag;
+ looknew->ns_search_only = lookold->ns_search_only;
+ looknew->tcp_mode = lookold->tcp_mode;
+ looknew->comments = lookold->comments;
+ looknew->stats = lookold->stats;
+ looknew->section_question = lookold->section_question;
+ looknew->section_answer = lookold->section_answer;
+ looknew->section_authority = lookold->section_authority;
+ looknew->section_additional = lookold->section_additional;
+ looknew->retries = lookold->retries;
+ looknew->tsigctx = NULL;
+ looknew->need_search = lookold->need_search;
+ looknew->done_as_is = lookold->done_as_is;
+
+ if (servers)
+ clone_server_list(lookold->my_server_list,
+ &looknew->my_server_list);
+ return (looknew);
+}
+
+/*%
+ * Requeue a lookup for further processing, perhaps copying the server
+ * list. The new lookup structure is returned to the caller, and is
+ * queued for processing. If servers are not cloned in the requeue, they
+ * must be added before allowing the current event to complete, since the
+ * completion of the event may result in the next entry on the lookup
+ * queue getting run.
+ */
+dig_lookup_t *
+requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
+ dig_lookup_t *looknew;
+
+ debug("requeue_lookup()");
+
+ lookup_counter++;
+ if (lookup_counter > LOOKUP_LIMIT)
+ fatal("too many lookups");
+
+ looknew = clone_lookup(lookold, servers);
+ INSIST(looknew != NULL);
+
+ debug("before insertion, init@%p -> %p, new@%p -> %p",
+ lookold, lookold->link.next, looknew, looknew->link.next);
+ ISC_LIST_PREPEND(lookup_list, looknew, link);
+ debug("after insertion, init -> %p, new = %p, new -> %p",
+ lookold, looknew, looknew->link.next);
+ return (looknew);
+}
+
+
+static void
+setup_text_key(void) {
+ isc_result_t result;
+ dns_name_t keyname;
+ isc_buffer_t secretbuf;
+ int secretsize;
+ unsigned char *secretstore;
+
+ debug("setup_text_key()");
+ result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
+ check_result(result, "isc_buffer_allocate");
+ dns_name_init(&keyname, NULL);
+ check_result(result, "dns_name_init");
+ isc_buffer_putstr(namebuf, keynametext);
+ secretsize = strlen(keysecret) * 3 / 4;
+ secretstore = isc_mem_allocate(mctx, secretsize);
+ if (secretstore == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ isc_buffer_init(&secretbuf, secretstore, secretsize);
+ result = isc_base64_decodestring(keysecret, &secretbuf);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ secretsize = isc_buffer_usedlength(&secretbuf);
+
+ result = dns_name_fromtext(&keyname, namebuf,
+ dns_rootname, ISC_FALSE,
+ namebuf);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ result = dns_tsigkey_create(&keyname, hmacname, secretstore,
+ secretsize, ISC_FALSE, NULL, 0, 0, mctx,
+ NULL, &key);
+ failure:
+ if (result != ISC_R_SUCCESS)
+ printf(";; Couldn't create key %s: %s\n",
+ keynametext, isc_result_totext(result));
+ else
+ dst_key_setbits(key->key, digestbits);
+
+ isc_mem_free(mctx, secretstore);
+ dns_name_invalidate(&keyname);
+ isc_buffer_free(&namebuf);
+}
+
+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);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "Couldn't read key from %s: %s\n",
+ keyfile, isc_result_totext(result));
+ goto failure;
+ }
+
+ switch (dst_key_alg(dstkey)) {
+ case DST_ALG_HMACMD5:
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ break;
+ case DST_ALG_HMACSHA1:
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ break;
+ case DST_ALG_HMACSHA224:
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ break;
+ case DST_ALG_HMACSHA256:
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ break;
+ case DST_ALG_HMACSHA384:
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ break;
+ case DST_ALG_HMACSHA512:
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ break;
+ default:
+ printf(";; Couldn't create key %s: bad algorithm\n",
+ keynametext);
+ goto failure;
+ }
+ result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
+ dstkey, ISC_FALSE, NULL, 0, 0,
+ mctx, NULL, &key);
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Couldn't create key %s: %s\n",
+ keynametext, isc_result_totext(result));
+ goto failure;
+ }
+ dstkey = NULL;
+ failure:
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+}
+
+static dig_searchlist_t *
+make_searchlist_entry(char *domain) {
+ dig_searchlist_t *search;
+ search = isc_mem_allocate(mctx, sizeof(*search));
+ if (search == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ strncpy(search->origin, domain, MXNAME);
+ search->origin[MXNAME-1] = 0;
+ ISC_LINK_INIT(search, link);
+ return (search);
+}
+
+static void
+create_search_list(lwres_conf_t *confdata) {
+ int i;
+ dig_searchlist_t *search;
+
+ debug("create_search_list()");
+ ISC_LIST_INIT(search_list);
+
+ for (i = 0; i < confdata->searchnxt; i++) {
+ search = make_searchlist_entry(confdata->search[i]);
+ ISC_LIST_APPEND(search_list, search, link);
+ }
+}
+
+/*%
+ * Setup the system as a whole, reading key information and resolv.conf
+ * settings.
+ */
+void
+setup_system(void) {
+ dig_searchlist_t *domain = NULL;
+ lwres_result_t lwresult;
+
+ debug("setup_system()");
+
+ lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
+ if (lwresult != LWRES_R_SUCCESS)
+ fatal("lwres_context_create failed");
+
+ lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
+ if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
+ fatal("parse of %s failed", RESOLV_CONF);
+
+ lwconf = lwres_conf_get(lwctx);
+
+ /* Make the search list */
+ if (lwconf->searchnxt > 0)
+ create_search_list(lwconf);
+ else { /* No search list. Use the domain name if any */
+ if (lwconf->domainname != NULL) {
+ domain = make_searchlist_entry(lwconf->domainname);
+ ISC_LIST_INITANDAPPEND(search_list, domain, link);
+ domain = NULL;
+ }
+ }
+
+ if (ndots == -1) {
+ ndots = lwconf->ndots;
+ debug("ndots is %d.", ndots);
+ }
+
+ /* If we don't find a nameserver fall back to localhost */
+ if (lwconf->nsnext == 0) {
+ if (have_ipv4) {
+ lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
+ if (lwresult != ISC_R_SUCCESS)
+ fatal("add_nameserver failed");
+ }
+ if (have_ipv6) {
+ lwresult = add_nameserver(lwconf, "::1", AF_INET6);
+ if (lwresult != ISC_R_SUCCESS)
+ fatal("add_nameserver failed");
+ }
+ }
+
+ if (ISC_LIST_EMPTY(server_list))
+ copy_server_list(lwconf, &server_list);
+
+#ifdef WITH_IDN
+ initialize_idn();
+#endif
+
+ if (keyfile[0] != 0)
+ setup_file_key();
+ else if (keysecret[0] != 0)
+ setup_text_key();
+#ifdef DIG_SIGCHASE
+ /* Setup the list of messages for +sigchase */
+ ISC_LIST_INIT(chase_message_list);
+ ISC_LIST_INIT(chase_message_list2);
+ dns_name_init(&chase_name, NULL);
+#if DIG_SIGCHASE_TD
+ dns_name_init(&chase_current_name, NULL);
+ dns_name_init(&chase_authority_name, NULL);
+#endif
+#if DIG_SIGCHASE_BU
+ dns_name_init(&chase_signame, NULL);
+#endif
+
+#endif
+
+}
+
+static void
+clear_searchlist(void) {
+ dig_searchlist_t *search;
+ while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
+ ISC_LIST_UNLINK(search_list, search, link);
+ isc_mem_free(mctx, search);
+ }
+}
+
+/*%
+ * Override the search list derived from resolv.conf by 'domain'.
+ */
+void
+set_search_domain(char *domain) {
+ dig_searchlist_t *search;
+
+ clear_searchlist();
+ search = make_searchlist_entry(domain);
+ ISC_LIST_APPEND(search_list, search, link);
+}
+
+/*%
+ * Setup the ISC and DNS libraries for use by the system.
+ */
+void
+setup_libs(void) {
+ isc_result_t result;
+
+ debug("setup_libs()");
+
+ result = isc_net_probeipv4();
+ if (result == ISC_R_SUCCESS)
+ have_ipv4 = ISC_TRUE;
+
+ result = isc_net_probeipv6();
+ if (result == ISC_R_SUCCESS)
+ have_ipv6 = ISC_TRUE;
+ if (!have_ipv6 && !have_ipv4)
+ fatal("can't find either v4 or v6 networking");
+
+ result = isc_mem_create(0, 0, &mctx);
+ check_result(result, "isc_mem_create");
+
+ result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
+ check_result(result, "isc_taskmgr_create");
+
+ result = isc_task_create(taskmgr, 0, &global_task);
+ check_result(result, "isc_task_create");
+
+ result = isc_timermgr_create(mctx, &timermgr);
+ check_result(result, "isc_timermgr_create");
+
+ result = isc_socketmgr_create(mctx, &socketmgr);
+ check_result(result, "isc_socketmgr_create");
+
+ result = isc_entropy_create(mctx, &entp);
+ check_result(result, "isc_entropy_create");
+
+ result = dst_lib_init(mctx, entp, 0);
+ check_result(result, "dst_lib_init");
+ is_dst_up = ISC_TRUE;
+
+ result = isc_mempool_create(mctx, COMMSIZE, &commctx);
+ check_result(result, "isc_mempool_create");
+ isc_mempool_setname(commctx, "COMMPOOL");
+ /*
+ * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
+ * systems.
+ */
+ isc_mempool_setfreemax(commctx, 6);
+ isc_mempool_setfillcount(commctx, 2);
+
+ result = isc_mutex_init(&lookup_lock);
+ check_result(result, "isc_mutex_init");
+
+ dns_result_register();
+}
+
+/*%
+ * Add EDNS0 option record to a message. Currently, the only supported
+ * options are UDP buffer size, the DO bit, and NSID request.
+ */
+static void
+add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
+ isc_boolean_t dnssec, isc_boolean_t nsid)
+{
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdatalist_t *rdatalist = NULL;
+ dns_rdata_t *rdata = NULL;
+ isc_result_t result;
+
+ debug("add_opt()");
+ result = dns_message_gettemprdataset(msg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+ dns_rdataset_init(rdataset);
+ result = dns_message_gettemprdatalist(msg, &rdatalist);
+ check_result(result, "dns_message_gettemprdatalist");
+ result = dns_message_gettemprdata(msg, &rdata);
+ check_result(result, "dns_message_gettemprdata");
+
+ debug("setting udp size of %d", udpsize);
+ rdatalist->type = dns_rdatatype_opt;
+ rdatalist->covers = 0;
+ rdatalist->rdclass = udpsize;
+ rdatalist->ttl = edns << 16;
+ if (dnssec)
+ rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
+ if (nsid) {
+ unsigned char data[4];
+ isc_buffer_t buf;
+
+ 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;
+ }
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+ result = dns_message_setopt(msg, rdataset);
+ check_result(result, "dns_message_setopt");
+}
+
+/*%
+ * Add a question section to a message, asking for the specified name,
+ * type, and class.
+ */
+static void
+add_question(dns_message_t *message, dns_name_t *name,
+ dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
+{
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+
+ debug("add_question()");
+ rdataset = NULL;
+ result = dns_message_gettemprdataset(message, &rdataset);
+ check_result(result, "dns_message_gettemprdataset()");
+ dns_rdataset_init(rdataset);
+ dns_rdataset_makequestion(rdataset, rdclass, rdtype);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+}
+
+/*%
+ * Check if we're done with all the queued lookups, which is true iff
+ * all sockets, sends, and recvs are accounted for (counters == 0),
+ * and the lookup list is empty.
+ * If we are done, pass control back out to dighost_shutdown() (which is
+ * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
+ * a whole or reseed the lookup list.
+ */
+static void
+check_if_done(void) {
+ debug("check_if_done()");
+ debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
+ if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
+ sendcount == 0) {
+ INSIST(sockcount == 0);
+ INSIST(recvcount == 0);
+ debug("shutting down");
+ dighost_shutdown();
+ }
+}
+
+/*%
+ * Clear out a query when we're done with it. WARNING: This routine
+ * WILL invalidate the query pointer.
+ */
+static void
+clear_query(dig_query_t *query) {
+ dig_lookup_t *lookup;
+
+ REQUIRE(query != NULL);
+
+ debug("clear_query(%p)", query);
+
+ lookup = query->lookup;
+
+ if (lookup->current_query == query)
+ lookup->current_query = NULL;
+
+ ISC_LIST_UNLINK(lookup->q, query, link);
+ if (ISC_LINK_LINKED(&query->recvbuf, link))
+ ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
+ link);
+ if (ISC_LINK_LINKED(&query->lengthbuf, link))
+ ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
+ link);
+ INSIST(query->recvspace != NULL);
+ if (query->sock != NULL) {
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ }
+ isc_mempool_put(commctx, query->recvspace);
+ isc_buffer_invalidate(&query->recvbuf);
+ isc_buffer_invalidate(&query->lengthbuf);
+ if (query->waiting_senddone)
+ query->pending_free = ISC_TRUE;
+ else
+ isc_mem_free(mctx, query);
+}
+
+/*%
+ * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
+ * the lookup was successfully cleared. If ISC_TRUE is returned, the
+ * lookup pointer has been invalidated.
+ */
+static isc_boolean_t
+try_clear_lookup(dig_lookup_t *lookup) {
+ dig_query_t *q;
+
+ REQUIRE(lookup != NULL);
+
+ debug("try_clear_lookup(%p)", lookup);
+
+ if (ISC_LIST_HEAD(lookup->q) != NULL) {
+ if (debugging) {
+ q = ISC_LIST_HEAD(lookup->q);
+ while (q != NULL) {
+ debug("query to %s still pending", q->servname);
+ q = ISC_LIST_NEXT(q, link);
+ }
+ }
+ return (ISC_FALSE);
+ }
+
+ /*
+ * At this point, we know there are no queries on the lookup,
+ * so can make it go away also.
+ */
+ destroy_lookup(lookup);
+ return (ISC_TRUE);
+}
+
+void
+destroy_lookup(dig_lookup_t *lookup) {
+ dig_server_t *s;
+ void *ptr;
+
+ debug("destroy");
+ s = ISC_LIST_HEAD(lookup->my_server_list);
+ while (s != NULL) {
+ debug("freeing server %p belonging to %p", s, lookup);
+ ptr = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(lookup->my_server_list,
+ (dig_server_t *)ptr, link);
+ isc_mem_free(mctx, ptr);
+ }
+ if (lookup->sendmsg != NULL)
+ dns_message_destroy(&lookup->sendmsg);
+ if (lookup->querysig != NULL) {
+ debug("freeing buffer %p", lookup->querysig);
+ isc_buffer_free(&lookup->querysig);
+ }
+ if (lookup->timer != NULL)
+ isc_timer_detach(&lookup->timer);
+ if (lookup->sendspace != NULL)
+ isc_mempool_put(commctx, lookup->sendspace);
+
+ if (lookup->tsigctx != NULL)
+ dst_context_destroy(&lookup->tsigctx);
+
+ isc_mem_free(mctx, lookup);
+}
+
+/*%
+ * If we can, start the next lookup in the queue running.
+ * This assumes that the lookup on the head of the queue hasn't been
+ * started yet. It also removes the lookup from the head of the queue,
+ * setting the current_lookup pointer pointing to it.
+ */
+void
+start_lookup(void) {
+ debug("start_lookup()");
+ if (cancel_now)
+ return;
+
+ /*
+ * If there's a current lookup running, we really shouldn't get
+ * here.
+ */
+ INSIST(current_lookup == NULL);
+
+ current_lookup = ISC_LIST_HEAD(lookup_list);
+ /*
+ * Put the current lookup somewhere so cancel_all can find it
+ */
+ if (current_lookup != NULL) {
+ ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
+#if DIG_SIGCHASE_TD
+ if (current_lookup->do_topdown &&
+ !current_lookup->rdtype_sigchaseset) {
+ dst_key_t *trustedkey = NULL;
+ isc_buffer_t *b = NULL;
+ isc_region_t r;
+ isc_result_t result;
+ dns_name_t query_name;
+ dns_name_t *key_name;
+ int i;
+
+ result = get_trusted_key(mctx);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; No trusted key, "
+ "+sigchase option is disabled\n");
+ current_lookup->sigchase = ISC_FALSE;
+ goto novalidation;
+ }
+ dns_name_init(&query_name, NULL);
+ nameFromString(current_lookup->textname, &query_name);
+
+ for (i = 0; i < tk_list.nb_tk; i++) {
+ key_name = dst_key_name(tk_list.key[i]);
+
+ if (dns_name_issubdomain(&query_name,
+ key_name) == ISC_TRUE)
+ trustedkey = tk_list.key[i];
+ /*
+ * Verifier que la temp est bien la plus basse
+ * WARNING
+ */
+ }
+ if (trustedkey == NULL) {
+ printf("\n;; The queried zone: ");
+ dns_name_print(&query_name, stdout);
+ printf(" isn't a subdomain of any Trusted Keys"
+ ": +sigchase option is disable\n");
+ current_lookup->sigchase = ISC_FALSE;
+ free_name(&query_name, mctx);
+ goto novalidation;
+ }
+ free_name(&query_name, mctx);
+
+ current_lookup->rdtype_sigchase
+ = current_lookup->rdtype;
+ current_lookup->rdtype_sigchaseset
+ = current_lookup->rdtypeset;
+ current_lookup->rdtype = dns_rdatatype_ns;
+
+ current_lookup->qrdtype_sigchase
+ = current_lookup->qrdtype;
+ current_lookup->qrdtype = dns_rdatatype_ns;
+
+ current_lookup->rdclass_sigchase
+ = current_lookup->rdclass;
+ current_lookup->rdclass_sigchaseset
+ = current_lookup->rdclassset;
+ current_lookup->rdclass = dns_rdataclass_in;
+
+ strncpy(current_lookup->textnamesigchase,
+ current_lookup->textname, MXNAME);
+
+ current_lookup->trace_root_sigchase = ISC_TRUE;
+
+ result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_name_totext(dst_key_name(trustedkey),
+ ISC_FALSE, b);
+ check_result(result, "dns_name_totext");
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strncpy(current_lookup->textname, (char*)r.base,
+ MXNAME);
+ isc_buffer_free(&b);
+
+ nameFromString(current_lookup->textnamesigchase,
+ &chase_name);
+
+ dns_name_init(&chase_authority_name, NULL);
+ }
+ novalidation:
+#endif
+ setup_lookup(current_lookup);
+ do_lookup(current_lookup);
+ } else {
+ check_if_done();
+ }
+}
+
+/*%
+ * If we can, clear the current lookup and start the next one running.
+ * This calls try_clear_lookup, so may invalidate the lookup pointer.
+ */
+static void
+check_next_lookup(dig_lookup_t *lookup) {
+
+ INSIST(!free_now);
+
+ debug("check_next_lookup(%p)", lookup);
+
+ if (ISC_LIST_HEAD(lookup->q) != NULL) {
+ debug("still have a worker");
+ return;
+ }
+ if (try_clear_lookup(lookup)) {
+ current_lookup = NULL;
+ start_lookup();
+ }
+}
+
+/*%
+ * Create and queue a new lookup as a followup to the current lookup,
+ * based on the supplied message and section. This is used in trace and
+ * name server search modes to start a new lookup using servers from
+ * NS records in a reply. Returns the number of followup lookups made.
+ */
+static int
+followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
+{
+ dig_lookup_t *lookup = NULL;
+ dig_server_t *srv = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_name_t *name = NULL;
+ isc_result_t result;
+ isc_boolean_t success = ISC_FALSE;
+ int numLookups = 0;
+ dns_name_t *domain;
+ isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE;
+
+ INSIST(!free_now);
+
+ debug("following up %s", query->lookup->textname);
+
+ for (result = dns_message_firstname(msg, section);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(msg, section)) {
+ name = NULL;
+ dns_message_currentname(msg, section, &name);
+
+ if (section == DNS_SECTION_AUTHORITY) {
+ rdataset = NULL;
+ result = dns_message_findtype(name, dns_rdatatype_soa,
+ 0, &rdataset);
+ if (result == ISC_R_SUCCESS)
+ return (0);
+ }
+ rdataset = NULL;
+ result = dns_message_findtype(name, dns_rdatatype_ns, 0,
+ &rdataset);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ debug("found NS set");
+
+ if (query->lookup->trace && !query->lookup->trace_root) {
+ dns_namereln_t namereln;
+ unsigned int nlabels;
+ int order;
+
+ domain = dns_fixedname_name(&query->lookup->fdomain);
+ namereln = dns_name_fullcompare(name, domain,
+ &order, &nlabels);
+ if (namereln == dns_namereln_equal) {
+ if (!horizontal)
+ printf(";; BAD (HORIZONTAL) REFERRAL\n");
+ horizontal = ISC_TRUE;
+ } else if (namereln != dns_namereln_subdomain) {
+ if (!bad)
+ printf(";; BAD REFERRAL\n");
+ bad = ISC_TRUE;
+ continue;
+ }
+ }
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_rdata_ns_t ns;
+
+ if (query->lookup->trace_root &&
+ query->lookup->nsfound >= MXSERV)
+ break;
+
+ dns_rdataset_current(rdataset, &rdata);
+
+ query->lookup->nsfound++;
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ dns_name_format(&ns.name, namestr, sizeof(namestr));
+ dns_rdata_freestruct(&ns);
+
+ /* Initialize lookup if we've not yet */
+ debug("found NS %d %s", numLookups, namestr);
+ numLookups++;
+ if (!success) {
+ success = ISC_TRUE;
+ lookup_counter++;
+ lookup = requeue_lookup(query->lookup,
+ ISC_FALSE);
+ cancel_lookup(query->lookup);
+ lookup->doing_xfr = ISC_FALSE;
+ if (!lookup->trace_root &&
+ section == DNS_SECTION_ANSWER)
+ lookup->trace = ISC_FALSE;
+ else
+ lookup->trace = query->lookup->trace;
+ lookup->ns_search_only =
+ query->lookup->ns_search_only;
+ lookup->trace_root = ISC_FALSE;
+ if (lookup->ns_search_only)
+ lookup->recurse = ISC_FALSE;
+ dns_fixedname_init(&lookup->fdomain);
+ domain = dns_fixedname_name(&lookup->fdomain);
+ dns_name_copy(name, domain, NULL);
+ }
+ srv = make_server(namestr, namestr);
+ debug("adding server %s", srv->servername);
+ ISC_LIST_APPEND(lookup->my_server_list, srv, link);
+ dns_rdata_reset(&rdata);
+ }
+ }
+
+ if (lookup == NULL &&
+ section == DNS_SECTION_ANSWER &&
+ (query->lookup->trace || query->lookup->ns_search_only))
+ return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
+
+ /*
+ * Randomize the order the nameserver will be tried.
+ */
+ if (numLookups > 1) {
+ isc_uint32_t i, j;
+ dig_serverlist_t my_server_list;
+
+ ISC_LIST_INIT(my_server_list);
+
+ for (i = numLookups; i > 0; i--) {
+ isc_random_get(&j);
+ j %= i;
+ srv = ISC_LIST_HEAD(lookup->my_server_list);
+ while (j-- > 0)
+ srv = ISC_LIST_NEXT(srv, link);
+ ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
+ ISC_LIST_APPEND(my_server_list, srv, link);
+ }
+ ISC_LIST_APPENDLIST(lookup->my_server_list,
+ my_server_list, link);
+ }
+
+ return (numLookups);
+}
+
+/*%
+ * Create and queue a new lookup using the next origin from the search
+ * list, read in setup_system().
+ *
+ * Return ISC_TRUE iff there was another searchlist entry.
+ */
+static isc_boolean_t
+next_origin(dns_message_t *msg, dig_query_t *query) {
+ dig_lookup_t *lookup;
+ dig_searchlist_t *search;
+
+ UNUSED(msg);
+
+ INSIST(!free_now);
+
+ debug("next_origin()");
+ debug("following up %s", query->lookup->textname);
+
+ if (!usesearch)
+ /*
+ * We're not using a search list, so don't even think
+ * about finding the next entry.
+ */
+ return (ISC_FALSE);
+ if (query->lookup->origin == NULL && !query->lookup->need_search)
+ /*
+ * Then we just did rootorg; there's nothing left.
+ */
+ return (ISC_FALSE);
+ if (query->lookup->origin == NULL && query->lookup->need_search) {
+ lookup = requeue_lookup(query->lookup, ISC_TRUE);
+ lookup->origin = ISC_LIST_HEAD(search_list);
+ lookup->need_search = ISC_FALSE;
+ } else {
+ search = ISC_LIST_NEXT(query->lookup->origin, link);
+ if (search == NULL && query->lookup->done_as_is)
+ return (ISC_FALSE);
+ lookup = requeue_lookup(query->lookup, ISC_TRUE);
+ lookup->origin = search;
+ }
+ cancel_lookup(query->lookup);
+ return (ISC_TRUE);
+}
+
+/*%
+ * Insert an SOA record into the sendmessage in a lookup. Used for
+ * creating IXFR queries.
+ */
+static void
+insert_soa(dig_lookup_t *lookup) {
+ isc_result_t result;
+ dns_rdata_soa_t soa;
+ dns_rdata_t *rdata = NULL;
+ dns_rdatalist_t *rdatalist = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ dns_name_t *soaname = NULL;
+
+ debug("insert_soa()");
+ soa.mctx = mctx;
+ soa.serial = lookup->ixfr_serial;
+ soa.refresh = 0;
+ soa.retry = 0;
+ soa.expire = 0;
+ soa.minimum = 0;
+ soa.common.rdclass = lookup->rdclass;
+ soa.common.rdtype = dns_rdatatype_soa;
+
+ dns_name_init(&soa.origin, NULL);
+ dns_name_init(&soa.contact, NULL);
+
+ dns_name_clone(dns_rootname, &soa.origin);
+ dns_name_clone(dns_rootname, &soa.contact);
+
+ isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
+ sizeof(lookup->rdatastore));
+
+ result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
+ check_result(result, "dns_message_gettemprdata");
+
+ result = dns_rdata_fromstruct(rdata, lookup->rdclass,
+ dns_rdatatype_soa, &soa,
+ &lookup->rdatabuf);
+ check_result(result, "isc_rdata_fromstruct");
+
+ result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
+ check_result(result, "dns_message_gettemprdatalist");
+
+ result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+
+ dns_rdatalist_init(rdatalist);
+ rdatalist->type = dns_rdatatype_soa;
+ rdatalist->rdclass = lookup->rdclass;
+ rdatalist->covers = 0;
+ rdatalist->ttl = 0;
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+
+ dns_rdataset_init(rdataset);
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+
+ result = dns_message_gettempname(lookup->sendmsg, &soaname);
+ check_result(result, "dns_message_gettempname");
+ dns_name_init(soaname, NULL);
+ dns_name_clone(lookup->name, soaname);
+ ISC_LIST_INIT(soaname->list);
+ ISC_LIST_APPEND(soaname->list, rdataset, link);
+ dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
+}
+
+/*%
+ * Setup the supplied lookup structure, making it ready to start sending
+ * queries to servers. Create and initialize the message to be sent as
+ * well as the query structures and buffer space for the replies. If the
+ * server list is empty, clone it from the system default list.
+ */
+void
+setup_lookup(dig_lookup_t *lookup) {
+ isc_result_t result;
+ isc_uint32_t id;
+ int len;
+ dig_server_t *serv;
+ dig_query_t *query;
+ isc_buffer_t b;
+ dns_compress_t cctx;
+ char store[MXNAME];
+#ifdef WITH_IDN
+ idn_result_t mr;
+ char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
+#endif
+
+#ifdef WITH_IDN
+ result = dns_name_settotextfilter(output_filter);
+ check_result(result, "dns_name_settotextfilter");
+#endif
+
+ REQUIRE(lookup != NULL);
+ INSIST(!free_now);
+
+ debug("setup_lookup(%p)", lookup);
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
+ &lookup->sendmsg);
+ check_result(result, "dns_message_create");
+
+ if (lookup->new_search) {
+ debug("resetting lookup counter.");
+ lookup_counter = 0;
+ }
+
+ if (ISC_LIST_EMPTY(lookup->my_server_list)) {
+ debug("cloning server list");
+ clone_server_list(server_list, &lookup->my_server_list);
+ }
+ result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
+ check_result(result, "dns_message_gettempname");
+ dns_name_init(lookup->name, NULL);
+
+ isc_buffer_init(&lookup->namebuf, lookup->namespace,
+ sizeof(lookup->namespace));
+ isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
+ sizeof(lookup->onamespace));
+
+#ifdef WITH_IDN
+ /*
+ * We cannot convert `textname' and `origin' separately.
+ * `textname' doesn't contain TLD, but local mapping needs
+ * TLD.
+ */
+ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
+ utf8_textname, sizeof(utf8_textname));
+ idn_check_result(mr, "convert textname to UTF-8");
+#endif
+
+ /*
+ * If the name has too many dots, force the origin to be NULL
+ * (which produces an absolute lookup). Otherwise, take the origin
+ * we have if there's one in the struct already. If it's NULL,
+ * take the first entry in the searchlist iff either usesearch
+ * is TRUE or we got a domain line in the resolv.conf file.
+ */
+ if (lookup->new_search) {
+#ifdef WITH_IDN
+ if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
+ lookup->origin = NULL; /* Force abs lookup */
+ lookup->done_as_is = ISC_TRUE;
+ lookup->need_search = usesearch;
+ } else if (lookup->origin == NULL && usesearch) {
+ lookup->origin = ISC_LIST_HEAD(search_list);
+ lookup->need_search = ISC_FALSE;
+ }
+#else
+ if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
+ lookup->origin = NULL; /* Force abs lookup */
+ lookup->done_as_is = ISC_TRUE;
+ lookup->need_search = usesearch;
+ } else if (lookup->origin == NULL && usesearch) {
+ lookup->origin = ISC_LIST_HEAD(search_list);
+ lookup->need_search = ISC_FALSE;
+ }
+#endif
+ }
+
+#ifdef WITH_IDN
+ if (lookup->origin != NULL) {
+ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
+ lookup->origin->origin, utf8_origin,
+ sizeof(utf8_origin));
+ idn_check_result(mr, "convert origin to UTF-8");
+ mr = append_textname(utf8_textname, utf8_origin,
+ sizeof(utf8_textname));
+ idn_check_result(mr, "append origin to textname");
+ }
+ mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
+ IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
+ idn_textname, sizeof(idn_textname));
+ idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
+#else
+ if (lookup->origin != NULL) {
+ debug("trying origin %s", lookup->origin->origin);
+ result = dns_message_gettempname(lookup->sendmsg,
+ &lookup->oname);
+ check_result(result, "dns_message_gettempname");
+ dns_name_init(lookup->oname, NULL);
+ /* XXX Helper funct to conv char* to name? */
+ len = strlen(lookup->origin->origin);
+ 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);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->name);
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->oname);
+ fatal("'%s' is not in legal name syntax (%s)",
+ lookup->origin->origin,
+ isc_result_totext(result));
+ }
+ if (lookup->trace && lookup->trace_root) {
+ dns_name_clone(dns_rootname, lookup->name);
+ } else {
+ len = strlen(lookup->textname);
+ isc_buffer_init(&b, lookup->textname, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->name, &b,
+ lookup->oname, ISC_FALSE,
+ &lookup->namebuf);
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->name);
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->oname);
+ fatal("'%s' is not in legal name syntax (%s)",
+ lookup->textname, isc_result_totext(result));
+ }
+ dns_message_puttempname(lookup->sendmsg, &lookup->oname);
+ } else
+#endif
+ {
+ debug("using root origin");
+ if (lookup->trace && lookup->trace_root)
+ dns_name_clone(dns_rootname, lookup->name);
+ else {
+#ifdef WITH_IDN
+ len = strlen(idn_textname);
+ isc_buffer_init(&b, idn_textname, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->name, &b,
+ dns_rootname,
+ ISC_FALSE,
+ &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,
+ &lookup->namebuf);
+#endif
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->name);
+ isc_buffer_init(&b, store, MXNAME);
+ fatal("'%s' is not a legal name "
+ "(%s)", lookup->textname,
+ isc_result_totext(result));
+ }
+ }
+ dns_name_format(lookup->name, store, sizeof(store));
+ trying(store, lookup);
+ INSIST(dns_name_isabsolute(lookup->name));
+
+ isc_random_get(&id);
+ lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
+ lookup->sendmsg->opcode = dns_opcode_query;
+ lookup->msgcounter = 0;
+ /*
+ * If this is a trace request, completely disallow recursion, since
+ * it's meaningless for traces.
+ */
+ if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
+ lookup->recurse = ISC_FALSE;
+
+ if (lookup->recurse &&
+ lookup->rdtype != dns_rdatatype_axfr &&
+ lookup->rdtype != dns_rdatatype_ixfr) {
+ debug("recursive query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
+ }
+
+ /* XXX aaflag */
+ if (lookup->aaonly) {
+ debug("AA query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
+ }
+
+ if (lookup->adflag) {
+ debug("AD query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
+ }
+
+ if (lookup->cdflag) {
+ debug("CD query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
+ }
+
+ dns_message_addname(lookup->sendmsg, lookup->name,
+ DNS_SECTION_QUESTION);
+
+ if (lookup->trace && lookup->trace_root) {
+ lookup->qrdtype = lookup->rdtype;
+ lookup->rdtype = dns_rdatatype_ns;
+ }
+
+ if ((lookup->rdtype == dns_rdatatype_axfr) ||
+ (lookup->rdtype == dns_rdatatype_ixfr)) {
+ /*
+ * Force TCP mode if we're doing an axfr.
+ */
+ if (lookup->rdtype == dns_rdatatype_axfr) {
+ lookup->doing_xfr = ISC_TRUE;
+ lookup->tcp_mode = ISC_TRUE;
+ } else if (lookup->tcp_mode) {
+ lookup->doing_xfr = ISC_TRUE;
+ }
+ }
+
+ add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
+ lookup->rdtype);
+
+ /* add_soa */
+ if (lookup->rdtype == dns_rdatatype_ixfr)
+ insert_soa(lookup);
+
+ /* XXX Insist this? */
+ lookup->tsigctx = NULL;
+ lookup->querysig = NULL;
+ if (key != NULL) {
+ debug("initializing keys");
+ result = dns_message_settsigkey(lookup->sendmsg, key);
+ check_result(result, "dns_message_settsigkey");
+ }
+
+ lookup->sendspace = isc_mempool_get(commctx);
+ if (lookup->sendspace == NULL)
+ fatal("memory allocation failure");
+
+ result = dns_compress_init(&cctx, -1, mctx);
+ check_result(result, "dns_compress_init");
+
+ debug("starting to render the message");
+ isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
+ result = dns_message_renderbegin(lookup->sendmsg, &cctx,
+ &lookup->renderbuf);
+ check_result(result, "dns_message_renderbegin");
+ if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1) {
+ if (lookup->udpsize == 0)
+ lookup->udpsize = 4096;
+ if (lookup->edns < 0)
+ lookup->edns = 0;
+ add_opt(lookup->sendmsg, lookup->udpsize,
+ lookup->edns, lookup->dnssec, lookup->nsid);
+ }
+
+ result = dns_message_rendersection(lookup->sendmsg,
+ DNS_SECTION_QUESTION, 0);
+ check_result(result, "dns_message_rendersection");
+ result = dns_message_rendersection(lookup->sendmsg,
+ DNS_SECTION_AUTHORITY, 0);
+ check_result(result, "dns_message_rendersection");
+ result = dns_message_renderend(lookup->sendmsg);
+ check_result(result, "dns_message_renderend");
+ debug("done rendering");
+
+ dns_compress_invalidate(&cctx);
+
+ /*
+ * Force TCP mode if the request is larger than 512 bytes.
+ */
+ if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
+ lookup->tcp_mode = ISC_TRUE;
+
+ lookup->pending = ISC_FALSE;
+
+ for (serv = ISC_LIST_HEAD(lookup->my_server_list);
+ serv != NULL;
+ serv = ISC_LIST_NEXT(serv, link)) {
+ query = isc_mem_allocate(mctx, sizeof(dig_query_t));
+ if (query == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ debug("create query %p linked to lookup %p",
+ query, lookup);
+ query->lookup = lookup;
+ query->waiting_connect = ISC_FALSE;
+ query->waiting_senddone = ISC_FALSE;
+ query->pending_free = ISC_FALSE;
+ query->recv_made = ISC_FALSE;
+ query->first_pass = ISC_TRUE;
+ query->first_soa_rcvd = ISC_FALSE;
+ query->second_rr_rcvd = ISC_FALSE;
+ query->first_repeat_rcvd = ISC_FALSE;
+ query->warn_id = ISC_TRUE;
+ query->first_rr_serial = 0;
+ query->second_rr_serial = 0;
+ query->servname = serv->servername;
+ query->userarg = serv->userarg;
+ query->rr_count = 0;
+ query->msg_count = 0;
+ query->byte_count = 0;
+ ISC_LINK_INIT(query, link);
+ ISC_LIST_INIT(query->recvlist);
+ ISC_LIST_INIT(query->lengthlist);
+ query->sock = NULL;
+ query->recvspace = isc_mempool_get(commctx);
+ if (query->recvspace == NULL)
+ fatal("memory allocation failure");
+
+ isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
+ isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
+ isc_buffer_init(&query->slbuf, query->slspace, 2);
+ query->sendbuf = lookup->renderbuf;
+
+ ISC_LINK_INIT(query, link);
+ ISC_LIST_ENQUEUE(lookup->q, query, link);
+ }
+ /* XXX qrflag, print_query, etc... */
+ if (!ISC_LIST_EMPTY(lookup->q) && qr) {
+ extrabytes = 0;
+ printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
+ ISC_TRUE);
+ }
+}
+
+/*%
+ * Event handler for send completion. Track send counter, and clear out
+ * the query if the send was canceled.
+ */
+static void
+send_done(isc_task_t *_task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ isc_buffer_t *b = NULL;
+ dig_query_t *query, *next;
+ dig_lookup_t *l;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+
+ UNUSED(_task);
+
+ LOCK_LOOKUP;
+
+ debug("send_done()");
+ sendcount--;
+ debug("sendcount=%d", sendcount);
+ INSIST(sendcount >= 0);
+
+ for (b = ISC_LIST_HEAD(sevent->bufferlist);
+ b != NULL;
+ b = ISC_LIST_HEAD(sevent->bufferlist))
+ ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
+
+ query = event->ev_arg;
+ query->waiting_senddone = ISC_FALSE;
+ l = query->lookup;
+
+ if (l->ns_search_only && !l->trace_root) {
+ debug("sending next, since searching");
+ next = ISC_LIST_NEXT(query, link);
+ if (next != NULL)
+ send_udp(next);
+ }
+
+ isc_event_free(&event);
+
+ if (query->pending_free)
+ isc_mem_free(mctx, query);
+
+ check_if_done();
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
+ * IO sockets. The cancel handlers should take care of cleaning up the
+ * query and lookup structures
+ */
+static void
+cancel_lookup(dig_lookup_t *lookup) {
+ dig_query_t *query, *next;
+
+ debug("cancel_lookup()");
+ query = ISC_LIST_HEAD(lookup->q);
+ while (query != NULL) {
+ next = ISC_LIST_NEXT(query, link);
+ if (query->sock != NULL) {
+ isc_socket_cancel(query->sock, global_task,
+ ISC_SOCKCANCEL_ALL);
+ check_if_done();
+ } else {
+ clear_query(query);
+ }
+ query = next;
+ }
+ if (lookup->timer != NULL)
+ isc_timer_detach(&lookup->timer);
+ lookup->pending = ISC_FALSE;
+ lookup->retries = 0;
+}
+
+static void
+bringup_timer(dig_query_t *query, unsigned int default_timeout) {
+ dig_lookup_t *l;
+ unsigned int local_timeout;
+ isc_result_t result;
+
+ debug("bringup_timer()");
+ /*
+ * If the timer already exists, that means we're calling this
+ * a second time (for a retry). Don't need to recreate it,
+ * just reset it.
+ */
+ l = query->lookup;
+ if (ISC_LIST_NEXT(query, link) != NULL)
+ local_timeout = SERVER_TIMEOUT;
+ else {
+ if (timeout == 0)
+ local_timeout = default_timeout;
+ else
+ local_timeout = timeout;
+ }
+ debug("have local timeout of %d", local_timeout);
+ isc_interval_set(&l->interval, local_timeout, 0);
+ if (l->timer != NULL)
+ isc_timer_detach(&l->timer);
+ result = isc_timer_create(timermgr, isc_timertype_once, NULL,
+ &l->interval, global_task, connect_timeout,
+ l, &l->timer);
+ check_result(result, "isc_timer_create");
+}
+
+static void
+connect_done(isc_task_t *task, isc_event_t *event);
+
+/*%
+ * Unlike send_udp, this can't be called multiple times with the same
+ * query. When we retry TCP, we requeue the whole lookup, which should
+ * start anew.
+ */
+static void
+send_tcp_connect(dig_query_t *query) {
+ isc_result_t result;
+ dig_query_t *next;
+ dig_lookup_t *l;
+
+ debug("send_tcp_connect(%p)", query);
+
+ l = query->lookup;
+ query->waiting_connect = ISC_TRUE;
+ query->lookup->current_query = query;
+ get_address(query->servname, port, &query->sockaddr);
+
+ if (specified_source &&
+ (isc_sockaddr_pf(&query->sockaddr) !=
+ isc_sockaddr_pf(&bind_address))) {
+ printf(";; Skipping server %s, incompatible "
+ "address family\n", query->servname);
+ query->waiting_connect = ISC_FALSE;
+ next = ISC_LIST_NEXT(query, link);
+ l = query->lookup;
+ clear_query(query);
+ if (next == NULL) {
+ printf(";; No acceptable nameservers\n");
+ check_next_lookup(l);
+ return;
+ }
+ send_tcp_connect(next);
+ return;
+ }
+ INSIST(query->sock == NULL);
+ result = isc_socket_create(socketmgr,
+ isc_sockaddr_pf(&query->sockaddr),
+ isc_sockettype_tcp, &query->sock);
+ check_result(result, "isc_socket_create");
+ sockcount++;
+ debug("sockcount=%d", sockcount);
+ if (specified_source)
+ result = isc_socket_bind(query->sock, &bind_address,
+ ISC_SOCKET_REUSEADDRESS);
+ else {
+ if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
+ have_ipv4)
+ isc_sockaddr_any(&bind_any);
+ else
+ isc_sockaddr_any6(&bind_any);
+ result = isc_socket_bind(query->sock, &bind_any, 0);
+ }
+ check_result(result, "isc_socket_bind");
+ bringup_timer(query, TCP_TIMEOUT);
+ result = isc_socket_connect(query->sock, &query->sockaddr,
+ global_task, connect_done, query);
+ check_result(result, "isc_socket_connect");
+ /*
+ * If we're at the endgame of a nameserver search, we need to
+ * immediately bring up all the queries. Do it here.
+ */
+ if (l->ns_search_only && !l->trace_root) {
+ debug("sending next, since searching");
+ next = ISC_LIST_NEXT(query, link);
+ if (next != NULL)
+ send_tcp_connect(next);
+ }
+}
+
+/*%
+ * Send a UDP packet to the remote nameserver, possible starting the
+ * recv action as well. Also make sure that the timer is running and
+ * is properly reset.
+ */
+static void
+send_udp(dig_query_t *query) {
+ dig_lookup_t *l = NULL;
+ isc_result_t result;
+
+ debug("send_udp(%p)", query);
+
+ l = query->lookup;
+ bringup_timer(query, UDP_TIMEOUT);
+ l->current_query = query;
+ debug("working on lookup %p, query %p", query->lookup, query);
+ if (!query->recv_made) {
+ /* XXX Check the sense of this, need assertion? */
+ query->waiting_connect = ISC_FALSE;
+ get_address(query->servname, port, &query->sockaddr);
+
+ result = isc_socket_create(socketmgr,
+ isc_sockaddr_pf(&query->sockaddr),
+ isc_sockettype_udp, &query->sock);
+ check_result(result, "isc_socket_create");
+ sockcount++;
+ debug("sockcount=%d", sockcount);
+ if (specified_source) {
+ result = isc_socket_bind(query->sock, &bind_address,
+ ISC_SOCKET_REUSEADDRESS);
+ } else {
+ isc_sockaddr_anyofpf(&bind_any,
+ isc_sockaddr_pf(&query->sockaddr));
+ result = isc_socket_bind(query->sock, &bind_any, 0);
+ }
+ check_result(result, "isc_socket_bind");
+
+ query->recv_made = ISC_TRUE;
+ ISC_LINK_INIT(&query->recvbuf, link);
+ ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
+ link);
+ debug("recving with lookup=%p, query=%p, sock=%p",
+ query->lookup, query, query->sock);
+ result = isc_socket_recvv(query->sock, &query->recvlist, 1,
+ global_task, recv_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ debug("recvcount=%d", recvcount);
+ }
+ ISC_LIST_INIT(query->sendlist);
+ ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
+ debug("sending a request");
+ TIME_NOW(&query->time_sent);
+ INSIST(query->sock != NULL);
+ query->waiting_senddone = ISC_TRUE;
+ result = isc_socket_sendtov(query->sock, &query->sendlist,
+ global_task, send_done, query,
+ &query->sockaddr, NULL);
+ check_result(result, "isc_socket_sendtov");
+ sendcount++;
+}
+
+/*%
+ * IO timeout handler, used for both connect and recv timeouts. If
+ * retries are still allowed, either resend the UDP packet or queue a
+ * new TCP lookup. Otherwise, cancel the lookup.
+ */
+static void
+connect_timeout(isc_task_t *task, isc_event_t *event) {
+ dig_lookup_t *l = NULL;
+ dig_query_t *query = NULL, *cq;
+
+ UNUSED(task);
+ REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
+
+ debug("connect_timeout()");
+
+ LOCK_LOOKUP;
+ l = event->ev_arg;
+ query = l->current_query;
+ isc_event_free(&event);
+
+ INSIST(!free_now);
+
+ if ((query != NULL) && (query->lookup->current_query != NULL) &&
+ (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
+ debug("trying next server...");
+ cq = query->lookup->current_query;
+ if (!l->tcp_mode)
+ send_udp(ISC_LIST_NEXT(cq, link));
+ else
+ send_tcp_connect(ISC_LIST_NEXT(cq, link));
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (l->retries > 1) {
+ if (!l->tcp_mode) {
+ l->retries--;
+ debug("resending UDP request to first server");
+ send_udp(ISC_LIST_HEAD(l->q));
+ } else {
+ debug("making new TCP request, %d tries left",
+ l->retries);
+ l->retries--;
+ requeue_lookup(l, ISC_TRUE);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ }
+ } else {
+ fputs(l->cmdline, stdout);
+ printf(";; connection timed out; no servers could be "
+ "reached\n");
+ cancel_lookup(l);
+ check_next_lookup(l);
+ if (exitcode < 9)
+ exitcode = 9;
+ }
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Event handler for the TCP recv which gets the length header of TCP
+ * packets. Start the next recv of length bytes.
+ */
+static void
+tcp_length_done(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent;
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+ dig_query_t *query = NULL;
+ dig_lookup_t *l;
+ isc_uint16_t length;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
+ INSIST(!free_now);
+
+ UNUSED(task);
+
+ debug("tcp_length_done()");
+
+ LOCK_LOOKUP;
+ sevent = (isc_socketevent_t *)event;
+ query = event->ev_arg;
+
+ recvcount--;
+ INSIST(recvcount >= 0);
+
+ b = ISC_LIST_HEAD(sevent->bufferlist);
+ INSIST(b == &query->lengthbuf);
+ ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
+
+ if (sevent->result == ISC_R_CANCELED) {
+ isc_event_free(&event);
+ l = query->lookup;
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (sevent->result != ISC_R_SUCCESS) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&query->sockaddr, sockstr,
+ sizeof(sockstr));
+ printf(";; communications error to %s: %s\n",
+ sockstr, isc_result_totext(sevent->result));
+ l = query->lookup;
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ isc_event_free(&event);
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ length = isc_buffer_getuint16(b);
+ if (length == 0) {
+ isc_event_free(&event);
+ launch_next_query(query, ISC_FALSE);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ /*
+ * Even though the buffer was already init'ed, we need
+ * to redo it now, to force the length we want.
+ */
+ isc_buffer_invalidate(&query->recvbuf);
+ isc_buffer_init(&query->recvbuf, query->recvspace, length);
+ ENSURE(ISC_LIST_EMPTY(query->recvlist));
+ ISC_LINK_INIT(&query->recvbuf, link);
+ ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
+ debug("recving with lookup=%p, query=%p", query->lookup, query);
+ result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
+ recv_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ debug("resubmitted recv request with length %d, recvcount=%d",
+ length, recvcount);
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * For transfers that involve multiple recvs (XFR's in particular),
+ * launch the next recv.
+ */
+static void
+launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
+ isc_result_t result;
+ dig_lookup_t *l;
+
+ INSIST(!free_now);
+
+ debug("launch_next_query()");
+
+ if (!query->lookup->pending) {
+ debug("ignoring launch_next_query because !pending");
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ query->waiting_connect = ISC_FALSE;
+ l = query->lookup;
+ clear_query(query);
+ check_next_lookup(l);
+ return;
+ }
+
+ isc_buffer_clear(&query->slbuf);
+ isc_buffer_clear(&query->lengthbuf);
+ isc_buffer_putuint16(&query->slbuf, (isc_uint16_t) query->sendbuf.used);
+ ISC_LIST_INIT(query->sendlist);
+ ISC_LINK_INIT(&query->slbuf, link);
+ ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
+ if (include_question)
+ ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
+ ISC_LINK_INIT(&query->lengthbuf, link);
+ ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
+
+ result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
+ global_task, tcp_length_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ debug("recvcount=%d", recvcount);
+ if (!query->first_soa_rcvd) {
+ debug("sending a request in launch_next_query");
+ TIME_NOW(&query->time_sent);
+ query->waiting_senddone = ISC_TRUE;
+ result = isc_socket_sendv(query->sock, &query->sendlist,
+ global_task, send_done, query);
+ check_result(result, "isc_socket_sendv");
+ sendcount++;
+ debug("sendcount=%d", sendcount);
+ }
+ query->waiting_connect = ISC_FALSE;
+#if 0
+ check_next_lookup(query->lookup);
+#endif
+ return;
+}
+
+/*%
+ * Event handler for TCP connect complete. Make sure the connection was
+ * successful, then pass into launch_next_query to actually send the
+ * question.
+ */
+static void
+connect_done(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = NULL;
+ dig_query_t *query = NULL, *next;
+ dig_lookup_t *l;
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
+ INSIST(!free_now);
+
+ debug("connect_done()");
+
+ LOCK_LOOKUP;
+ sevent = (isc_socketevent_t *)event;
+ query = sevent->ev_arg;
+
+ INSIST(query->waiting_connect);
+
+ query->waiting_connect = ISC_FALSE;
+
+ if (sevent->result == ISC_R_CANCELED) {
+ debug("in cancel handler");
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ INSIST(sockcount >= 0);
+ debug("sockcount=%d", sockcount);
+ query->waiting_connect = ISC_FALSE;
+ isc_event_free(&event);
+ l = query->lookup;
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (sevent->result != ISC_R_SUCCESS) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+
+ debug("unsuccessful connection: %s",
+ isc_result_totext(sevent->result));
+ isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
+ if (sevent->result != ISC_R_CANCELED)
+ printf(";; Connection to %s(%s) for %s failed: "
+ "%s.\n", sockstr,
+ query->servname, query->lookup->textname,
+ isc_result_totext(sevent->result));
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ INSIST(sockcount >= 0);
+ /* XXX Clean up exitcodes */
+ if (exitcode < 9)
+ exitcode = 9;
+ debug("sockcount=%d", sockcount);
+ query->waiting_connect = ISC_FALSE;
+ isc_event_free(&event);
+ l = query->lookup;
+ if (l->current_query != NULL)
+ next = ISC_LIST_NEXT(l->current_query, link);
+ else
+ next = NULL;
+ clear_query(query);
+ if (next != NULL) {
+ bringup_timer(next, TCP_TIMEOUT);
+ send_tcp_connect(next);
+ } else {
+ check_next_lookup(l);
+ }
+ UNLOCK_LOOKUP;
+ return;
+ }
+ launch_next_query(query, ISC_TRUE);
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Check if the ongoing XFR needs more data before it's complete, using
+ * the semantics of IXFR and AXFR protocols. Much of the complexity of
+ * this routine comes from determining when an IXFR is complete.
+ * ISC_FALSE means more data is on the way, and the recv has been issued.
+ */
+static isc_boolean_t
+check_for_more_data(dig_query_t *query, dns_message_t *msg,
+ isc_socketevent_t *sevent)
+{
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_soa_t soa;
+ isc_uint32_t serial;
+ isc_result_t result;
+
+ debug("check_for_more_data()");
+
+ /*
+ * By the time we're in this routine, we know we're doing
+ * either an AXFR or IXFR. If there's no second_rr_type,
+ * then we don't yet know which kind of answer we got back
+ * from the server. Here, we're going to walk through the
+ * rr's in the message, acting as necessary whenever we hit
+ * an SOA rr.
+ */
+
+ query->msg_count++;
+ query->byte_count += sevent->n;
+ result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
+ if (result != ISC_R_SUCCESS) {
+ puts("; Transfer failed.");
+ return (ISC_TRUE);
+ }
+ do {
+ dns_name_t *name;
+ name = NULL;
+ dns_message_currentname(msg, DNS_SECTION_ANSWER,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ do {
+ query->rr_count++;
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ /*
+ * If this is the first rr, make sure
+ * it's an SOA
+ */
+ if ((!query->first_soa_rcvd) &&
+ (rdata.type != dns_rdatatype_soa)) {
+ puts("; Transfer failed. "
+ "Didn't start with SOA answer.");
+ return (ISC_TRUE);
+ }
+ if ((!query->second_rr_rcvd) &&
+ (rdata.type != dns_rdatatype_soa)) {
+ query->second_rr_rcvd = ISC_TRUE;
+ query->second_rr_serial = 0;
+ debug("got the second rr as nonsoa");
+ goto next_rdata;
+ }
+
+ /*
+ * If the record is anything except an SOA
+ * now, just continue on...
+ */
+ if (rdata.type != dns_rdatatype_soa)
+ goto next_rdata;
+ /* Now we have an SOA. Work with it. */
+ debug("got an SOA");
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ serial = soa.serial;
+ dns_rdata_freestruct(&soa);
+ if (!query->first_soa_rcvd) {
+ query->first_soa_rcvd = ISC_TRUE;
+ query->first_rr_serial = serial;
+ debug("this is the first %d",
+ query->lookup->ixfr_serial);
+ if (query->lookup->ixfr_serial >=
+ serial)
+ goto doexit;
+ goto next_rdata;
+ }
+ if (query->lookup->rdtype ==
+ dns_rdatatype_axfr) {
+ debug("doing axfr, got second SOA");
+ goto doexit;
+ }
+ if (!query->second_rr_rcvd) {
+ if (query->first_rr_serial == serial) {
+ debug("doing ixfr, got "
+ "empty zone");
+ goto doexit;
+ }
+ debug("this is the second %d",
+ query->lookup->ixfr_serial);
+ query->second_rr_rcvd = ISC_TRUE;
+ query->second_rr_serial = serial;
+ goto next_rdata;
+ }
+ if (query->second_rr_serial == 0) {
+ /*
+ * If the second RR was a non-SOA
+ * record, and we're getting any
+ * other SOA, then this is an
+ * AXFR, and we're done.
+ */
+ debug("done, since axfr");
+ goto doexit;
+ }
+ /*
+ * If we get to this point, we're doing an
+ * IXFR and have to start really looking
+ * at serial numbers.
+ */
+ if (query->first_rr_serial == serial) {
+ debug("got a match for ixfr");
+ if (!query->first_repeat_rcvd) {
+ query->first_repeat_rcvd =
+ ISC_TRUE;
+ goto next_rdata;
+ }
+ debug("done with ixfr");
+ goto doexit;
+ }
+ debug("meaningless soa %d", serial);
+ next_rdata:
+ result = dns_rdataset_next(rdataset);
+ } while (result == ISC_R_SUCCESS);
+ }
+ result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
+ } while (result == ISC_R_SUCCESS);
+ launch_next_query(query, ISC_FALSE);
+ return (ISC_FALSE);
+ doexit:
+ received(sevent->n, &sevent->address, query);
+ return (ISC_TRUE);
+}
+
+/*%
+ * Event handler for recv complete. Perform whatever actions are necessary,
+ * based on the specifics of the user's request.
+ */
+static void
+recv_done(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = NULL;
+ dig_query_t *query = NULL;
+ isc_buffer_t *b = NULL;
+ dns_message_t *msg = NULL;
+#ifdef DIG_SIGCHASE
+ dig_message_t *chase_msg = NULL;
+ dig_message_t *chase_msg2 = NULL;
+#endif
+ isc_result_t result;
+ dig_lookup_t *n, *l;
+ isc_boolean_t docancel = ISC_FALSE;
+ isc_boolean_t match = ISC_TRUE;
+ unsigned int parseflags;
+ dns_messageid_t id;
+ unsigned int msgflags;
+#ifdef DIG_SIGCHASE
+ isc_result_t do_sigchase = ISC_FALSE;
+
+ dns_message_t *msg_temp = NULL;
+ isc_region_t r;
+ isc_buffer_t *buf = NULL;
+#endif
+
+ UNUSED(task);
+ INSIST(!free_now);
+
+ debug("recv_done()");
+
+ LOCK_LOOKUP;
+ recvcount--;
+ debug("recvcount=%d", recvcount);
+ INSIST(recvcount >= 0);
+
+ query = event->ev_arg;
+ debug("lookup=%p, query=%p", query->lookup, query);
+
+ l = query->lookup;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
+ sevent = (isc_socketevent_t *)event;
+
+ b = ISC_LIST_HEAD(sevent->bufferlist);
+ INSIST(b == &query->recvbuf);
+ ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
+
+ if ((l->tcp_mode) && (l->timer != NULL))
+ isc_timer_touch(l->timer);
+ if ((!l->pending && !l->ns_search_only) || cancel_now) {
+ debug("no longer pending. Got %s",
+ isc_result_totext(sevent->result));
+ query->waiting_connect = ISC_FALSE;
+
+ isc_event_free(&event);
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (sevent->result != ISC_R_SUCCESS) {
+ if (sevent->result == ISC_R_CANCELED) {
+ debug("in recv cancel handler");
+ query->waiting_connect = ISC_FALSE;
+ } else {
+ printf(";; communications error: %s\n",
+ isc_result_totext(sevent->result));
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ }
+ isc_event_free(&event);
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (!l->tcp_mode &&
+ !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
+ ISC_SOCKADDR_CMPADDR|
+ ISC_SOCKADDR_CMPPORT|
+ ISC_SOCKADDR_CMPSCOPE|
+ ISC_SOCKADDR_CMPSCOPEZERO)) {
+ char buf1[ISC_SOCKADDR_FORMATSIZE];
+ char buf2[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t any;
+
+ if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
+ isc_sockaddr_any(&any);
+ else
+ isc_sockaddr_any6(&any);
+
+ /*
+ * We don't expect a match when the packet is
+ * sent to 0.0.0.0, :: or to a multicast addresses.
+ * XXXMPA broadcast needs to be handled here as well.
+ */
+ if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
+ !isc_sockaddr_ismulticast(&query->sockaddr)) ||
+ isc_sockaddr_getport(&query->sockaddr) !=
+ isc_sockaddr_getport(&sevent->address)) {
+ isc_sockaddr_format(&sevent->address, buf1,
+ sizeof(buf1));
+ isc_sockaddr_format(&query->sockaddr, buf2,
+ sizeof(buf2));
+ printf(";; reply from unexpected source: %s,"
+ " expected %s\n", buf1, buf2);
+ match = ISC_FALSE;
+ }
+ }
+
+ result = dns_message_peekheader(b, &id, &msgflags);
+ if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
+ match = ISC_FALSE;
+ if (l->tcp_mode) {
+ isc_boolean_t fail = ISC_TRUE;
+ if (result == ISC_R_SUCCESS) {
+ if (!query->first_soa_rcvd ||
+ query->warn_id)
+ printf(";; %s: ID mismatch: "
+ "expected ID %u, got %u\n",
+ query->first_soa_rcvd ?
+ "WARNING" : "ERROR",
+ l->sendmsg->id, id);
+ if (query->first_soa_rcvd)
+ fail = ISC_FALSE;
+ query->warn_id = ISC_FALSE;
+ } else
+ printf(";; ERROR: short "
+ "(< header size) message\n");
+ if (fail) {
+ isc_event_free(&event);
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ match = ISC_TRUE;
+ } else if (result == ISC_R_SUCCESS)
+ printf(";; Warning: ID mismatch: "
+ "expected ID %u, got %u\n", l->sendmsg->id, id);
+ else
+ printf(";; Warning: short "
+ "(< header size) message received\n");
+ }
+
+ if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
+ printf(";; Warning: query response not set\n");
+
+ if (!match) {
+ isc_buffer_invalidate(&query->recvbuf);
+ isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
+ ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
+ result = isc_socket_recvv(query->sock, &query->recvlist, 1,
+ global_task, recv_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
+ check_result(result, "dns_message_create");
+
+ if (key != NULL) {
+ if (l->querysig == NULL) {
+ debug("getting initial querysig");
+ result = dns_message_getquerytsig(l->sendmsg, mctx,
+ &l->querysig);
+ check_result(result, "dns_message_getquerytsig");
+ }
+ result = dns_message_setquerytsig(msg, l->querysig);
+ check_result(result, "dns_message_setquerytsig");
+ result = dns_message_settsigkey(msg, key);
+ check_result(result, "dns_message_settsigkey");
+ msg->tsigctx = l->tsigctx;
+ l->tsigctx = NULL;
+ if (l->msgcounter != 0)
+ msg->tcp_continuation = 1;
+ l->msgcounter++;
+ }
+
+ debug("before parse starts");
+ parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
+#ifdef DIG_SIGCHASE
+ if (!l->sigchase) {
+ do_sigchase = ISC_FALSE;
+ } else {
+ parseflags = 0;
+ do_sigchase = ISC_TRUE;
+ }
+#endif
+ if (l->besteffort) {
+ parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
+ parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
+ }
+ result = dns_message_parse(msg, b, parseflags);
+ if (result == DNS_R_RECOVERABLE) {
+ printf(";; Warning: Message parser reports malformed "
+ "message packet.\n");
+ result = ISC_R_SUCCESS;
+ }
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Got bad packet: %s\n", isc_result_totext(result));
+ hex_dump(b);
+ query->waiting_connect = ISC_FALSE;
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
+ !l->ignore && !l->tcp_mode) {
+ printf(";; Truncated, retrying in TCP mode.\n");
+ n = requeue_lookup(l, ISC_TRUE);
+ n->tcp_mode = ISC_TRUE;
+ n->origin = query->lookup->origin;
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
+ (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
+ {
+ dig_query_t *next = ISC_LIST_NEXT(query, link);
+ if (l->current_query == query)
+ l->current_query = NULL;
+ if (next != NULL) {
+ debug("sending query %p\n", next);
+ if (l->tcp_mode)
+ send_tcp_connect(next);
+ else
+ send_udp(next);
+ }
+ /*
+ * If our query is at the head of the list and there
+ * is no next, we're the only one left, so fall
+ * through to print the message.
+ */
+ if ((ISC_LIST_HEAD(l->q) != query) ||
+ (ISC_LIST_NEXT(query, link) != NULL)) {
+ if( l->comments == ISC_TRUE )
+ printf(";; Got %s from %s, "
+ "trying next server\n",
+ msg->rcode == dns_rcode_servfail ?
+ "SERVFAIL reply" :
+ "recursion not available",
+ query->servname);
+ clear_query(query);
+ check_next_lookup(l);
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ }
+
+ if (key != NULL) {
+ result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Couldn't verify signature: %s\n",
+ isc_result_totext(result));
+ validated = ISC_FALSE;
+ }
+ l->tsigctx = msg->tsigctx;
+ msg->tsigctx = NULL;
+ if (l->querysig != NULL) {
+ debug("freeing querysig buffer %p", l->querysig);
+ isc_buffer_free(&l->querysig);
+ }
+ result = dns_message_getquerytsig(msg, mctx, &l->querysig);
+ check_result(result,"dns_message_getquerytsig");
+ }
+
+ extrabytes = isc_buffer_remaininglength(b);
+
+ debug("after parse");
+ if (l->doing_xfr && l->xfr_q == NULL) {
+ l->xfr_q = query;
+ /*
+ * Once we are in the XFR message, increase
+ * the timeout to much longer, so brief network
+ * outages won't cause the XFR to abort
+ */
+ if (timeout != INT_MAX && l->timer != NULL) {
+ unsigned int local_timeout;
+
+ if (timeout == 0) {
+ if (l->tcp_mode)
+ local_timeout = TCP_TIMEOUT * 4;
+ else
+ local_timeout = UDP_TIMEOUT * 4;
+ } else {
+ if (timeout < (INT_MAX / 4))
+ local_timeout = timeout * 4;
+ else
+ local_timeout = INT_MAX;
+ }
+ debug("have local timeout of %d", local_timeout);
+ isc_interval_set(&l->interval, local_timeout, 0);
+ result = isc_timer_reset(l->timer,
+ isc_timertype_once,
+ NULL,
+ &l->interval,
+ ISC_FALSE);
+ check_result(result, "isc_timer_reset");
+ }
+ }
+
+ if (!l->doing_xfr || l->xfr_q == query) {
+ if (msg->rcode != dns_rcode_noerror &&
+ (l->origin != NULL || l->need_search)) {
+ if (!next_origin(msg, query) || showsearch) {
+ printmessage(query, msg, ISC_TRUE);
+ received(b->used, &sevent->address, query);
+ }
+ } else if (!l->trace && !l->ns_search_only) {
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ printmessage(query, msg, ISC_TRUE);
+ } else if (l->trace) {
+ int n = 0;
+ int count = msg->counts[DNS_SECTION_ANSWER];
+
+ debug("in TRACE code");
+ if (!l->ns_search_only)
+ printmessage(query, msg, ISC_TRUE);
+
+ l->rdtype = l->qrdtype;
+ if (l->trace_root || (l->ns_search_only && count > 0)) {
+ if (!l->trace_root)
+ l->rdtype = dns_rdatatype_soa;
+ n = followup_lookup(msg, query,
+ DNS_SECTION_ANSWER);
+ l->trace_root = ISC_FALSE;
+ } else if (count == 0)
+ n = followup_lookup(msg, query,
+ DNS_SECTION_AUTHORITY);
+ if (n == 0)
+ docancel = ISC_TRUE;
+ } else {
+ debug("in NSSEARCH code");
+
+ if (l->trace_root) {
+ /*
+ * This is the initial NS query.
+ */
+ int n;
+
+ l->rdtype = dns_rdatatype_soa;
+ n = followup_lookup(msg, query,
+ DNS_SECTION_ANSWER);
+ if (n == 0)
+ docancel = ISC_TRUE;
+ l->trace_root = ISC_FALSE;
+ } else
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ printmessage(query, msg, ISC_TRUE);
+ }
+#ifdef DIG_SIGCHASE
+ if (do_sigchase) {
+ chase_msg = isc_mem_allocate(mctx,
+ sizeof(dig_message_t));
+ if (chase_msg == NULL) {
+ fatal("Memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ }
+ ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
+ link);
+ if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
+ &msg_temp) != ISC_R_SUCCESS) {
+ fatal("dns_message_create in %s:%d",
+ __FILE__, __LINE__);
+ }
+
+ isc_buffer_usedregion(b, &r);
+ result = isc_buffer_allocate(mctx, &buf, r.length);
+
+ check_result(result, "isc_buffer_allocate");
+ result = isc_buffer_copyregion(buf, &r);
+ check_result(result, "isc_buffer_copyregion");
+
+ result = dns_message_parse(msg_temp, buf, 0);
+
+ isc_buffer_free(&buf);
+ chase_msg->msg = msg_temp;
+
+ chase_msg2 = isc_mem_allocate(mctx,
+ sizeof(dig_message_t));
+ if (chase_msg2 == NULL) {
+ fatal("Memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ }
+ ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
+ link);
+ chase_msg2->msg = msg;
+ }
+#endif
+ }
+
+#ifdef DIG_SIGCHASE
+ if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
+ sigchase(msg_temp);
+ }
+#endif
+
+ if (l->pending)
+ debug("still pending.");
+ if (l->doing_xfr) {
+ if (query != l->xfr_q) {
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ query->waiting_connect = ISC_FALSE;
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (!docancel)
+ docancel = check_for_more_data(query, msg, sevent);
+ if (docancel) {
+ dns_message_destroy(&msg);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ }
+ } else {
+
+ if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
+
+#ifdef DIG_SIGCHASE
+ if (!l->sigchase)
+#endif
+ received(b->used, &sevent->address, query);
+ }
+
+ if (!query->lookup->ns_search_only)
+ query->lookup->pending = ISC_FALSE;
+ if (!query->lookup->ns_search_only ||
+ query->lookup->trace_root || docancel) {
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ dns_message_destroy(&msg);
+
+ cancel_lookup(l);
+ }
+ clear_query(query);
+ check_next_lookup(l);
+ }
+ if (msg != NULL) {
+#ifdef DIG_SIGCHASE
+ if (do_sigchase)
+ msg = NULL;
+ else
+#endif
+ dns_message_destroy(&msg);
+ }
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Turn a name into an address, using system-supplied routines. This is
+ * used in looking up server names, etc... and needs to use system-supplied
+ * routines, since they may be using a non-DNS system for these lookups.
+ */
+void
+get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
+ int count;
+ isc_result_t result;
+
+ isc_app_block();
+ result = bind9_getaddresses(host, port, sockaddr, 1, &count);
+ isc_app_unblock();
+ if (result != ISC_R_SUCCESS)
+ fatal("couldn't get address for '%s': %s",
+ host, isc_result_totext(result));
+ INSIST(count == 1);
+}
+
+/*%
+ * Initiate either a TCP or UDP lookup
+ */
+void
+do_lookup(dig_lookup_t *lookup) {
+
+ REQUIRE(lookup != NULL);
+
+ debug("do_lookup()");
+ lookup->pending = ISC_TRUE;
+ if (lookup->tcp_mode)
+ send_tcp_connect(ISC_LIST_HEAD(lookup->q));
+ else
+ send_udp(ISC_LIST_HEAD(lookup->q));
+}
+
+/*%
+ * Start everything in action upon task startup.
+ */
+void
+onrun_callback(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ isc_event_free(&event);
+ LOCK_LOOKUP;
+ start_lookup();
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Make everything on the lookup queue go away. Mainly used by the
+ * SIGINT handler.
+ */
+void
+cancel_all(void) {
+ dig_lookup_t *l, *n;
+ dig_query_t *q, *nq;
+
+ debug("cancel_all()");
+
+ LOCK_LOOKUP;
+ if (free_now) {
+ UNLOCK_LOOKUP;
+ return;
+ }
+ cancel_now = ISC_TRUE;
+ if (current_lookup != NULL) {
+ if (current_lookup->timer != NULL)
+ isc_timer_detach(&current_lookup->timer);
+ q = ISC_LIST_HEAD(current_lookup->q);
+ while (q != NULL) {
+ debug("cancelling query %p, belonging to %p",
+ q, current_lookup);
+ nq = ISC_LIST_NEXT(q, link);
+ if (q->sock != NULL) {
+ isc_socket_cancel(q->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ } else {
+ clear_query(q);
+ }
+ q = nq;
+ }
+ }
+ l = ISC_LIST_HEAD(lookup_list);
+ while (l != NULL) {
+ n = ISC_LIST_NEXT(l, link);
+ ISC_LIST_DEQUEUE(lookup_list, l, link);
+ try_clear_lookup(l);
+ l = n;
+ }
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Destroy all of the libs we are using, and get everything ready for a
+ * clean shutdown.
+ */
+void
+destroy_libs(void) {
+#ifdef DIG_SIGCHASE
+ void * ptr;
+ dig_message_t *chase_msg;
+#endif
+#ifdef WITH_IDN
+ isc_result_t result;
+#endif
+
+ debug("destroy_libs()");
+ if (global_task != NULL) {
+ debug("freeing task");
+ isc_task_detach(&global_task);
+ }
+ /*
+ * The taskmgr_destroy() call blocks until all events are cleared
+ * from the task.
+ */
+ if (taskmgr != NULL) {
+ debug("freeing taskmgr");
+ isc_taskmgr_destroy(&taskmgr);
+ }
+ LOCK_LOOKUP;
+ REQUIRE(sockcount == 0);
+ REQUIRE(recvcount == 0);
+ REQUIRE(sendcount == 0);
+
+ INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
+ INSIST(current_lookup == NULL);
+ INSIST(!free_now);
+
+ free_now = ISC_TRUE;
+
+ lwres_conf_clear(lwctx);
+ lwres_context_destroy(&lwctx);
+
+ flush_server_list();
+
+ clear_searchlist();
+
+#ifdef WITH_IDN
+ result = dns_name_settotextfilter(NULL);
+ check_result(result, "dns_name_settotextfilter");
+#endif
+ dns_name_destroy();
+
+ if (commctx != NULL) {
+ debug("freeing commctx");
+ isc_mempool_destroy(&commctx);
+ }
+ if (socketmgr != NULL) {
+ debug("freeing socketmgr");
+ isc_socketmgr_destroy(&socketmgr);
+ }
+ if (timermgr != NULL) {
+ debug("freeing timermgr");
+ isc_timermgr_destroy(&timermgr);
+ }
+ if (key != NULL) {
+ debug("freeing key %p", key);
+ dns_tsigkey_detach(&key);
+ }
+ if (namebuf != NULL)
+ isc_buffer_free(&namebuf);
+
+ if (is_dst_up) {
+ debug("destroy DST lib");
+ dst_lib_destroy();
+ is_dst_up = ISC_FALSE;
+ }
+ if (entp != NULL) {
+ debug("detach from entropy");
+ isc_entropy_detach(&entp);
+ }
+
+ UNLOCK_LOOKUP;
+ DESTROYLOCK(&lookup_lock);
+#ifdef DIG_SIGCHASE
+
+ debug("Destroy the messages kept for sigchase");
+ /* Destroy the messages kept for sigchase */
+ chase_msg = ISC_LIST_HEAD(chase_message_list);
+
+ while (chase_msg != NULL) {
+ INSIST(chase_msg->msg != NULL);
+ dns_message_destroy(&(chase_msg->msg));
+ ptr = chase_msg;
+ chase_msg = ISC_LIST_NEXT(chase_msg, link);
+ isc_mem_free(mctx, ptr);
+ }
+
+ chase_msg = ISC_LIST_HEAD(chase_message_list2);
+
+ while (chase_msg != NULL) {
+ INSIST(chase_msg->msg != NULL);
+ dns_message_destroy(&(chase_msg->msg));
+ ptr = chase_msg;
+ chase_msg = ISC_LIST_NEXT(chase_msg, link);
+ isc_mem_free(mctx, ptr);
+ }
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name, mctx);
+#if DIG_SIGCHASE_TD
+ if (dns_name_dynamic(&chase_current_name))
+ free_name(&chase_current_name, mctx);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name, mctx);
+#endif
+#if DIG_SIGCHASE_BU
+ if (dns_name_dynamic(&chase_signame))
+ free_name(&chase_signame, mctx);
+#endif
+
+ debug("Destroy memory");
+
+#endif
+ if (memdebugging != 0)
+ isc_mem_stats(mctx, stderr);
+ if (mctx != NULL)
+ isc_mem_destroy(&mctx);
+}
+
+#ifdef WITH_IDN
+static void
+initialize_idn(void) {
+ idn_result_t r;
+ isc_result_t result;
+
+#ifdef HAVE_SETLOCALE
+ /* Set locale */
+ (void)setlocale(LC_ALL, "");
+#endif
+ /* Create configuration context. */
+ r = idn_nameinit(1);
+ if (r != idn_success)
+ fatal("idn api initialization failed: %s",
+ idn_result_tostring(r));
+
+ /* Set domain name -> text post-conversion filter. */
+ result = dns_name_settotextfilter(output_filter);
+ check_result(result, "dns_name_settotextfilter");
+}
+
+static isc_result_t
+output_filter(isc_buffer_t *buffer, unsigned int used_org,
+ isc_boolean_t absolute)
+{
+ char tmp1[MAXDLEN], tmp2[MAXDLEN];
+ size_t fromlen, tolen;
+ isc_boolean_t end_with_dot;
+
+ /*
+ * Copy contents of 'buffer' to 'tmp1', supply trailing dot
+ * if 'absolute' is true, and terminate with NUL.
+ */
+ fromlen = isc_buffer_usedlength(buffer) - used_org;
+ if (fromlen >= MAXDLEN)
+ return (ISC_R_SUCCESS);
+ memcpy(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
+ end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
+ if (absolute && !end_with_dot) {
+ fromlen++;
+ if (fromlen >= MAXDLEN)
+ return (ISC_R_SUCCESS);
+ tmp1[fromlen - 1] = '.';
+ }
+ tmp1[fromlen] = '\0';
+
+ /*
+ * Convert contents of 'tmp1' to local encoding.
+ */
+ if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
+ return (ISC_R_SUCCESS);
+ strcpy(tmp1, tmp2);
+
+ /*
+ * Copy the converted contents in 'tmp1' back to 'buffer'.
+ * If we have appended trailing dot, remove it.
+ */
+ tolen = strlen(tmp1);
+ if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
+ tolen--;
+
+ if (isc_buffer_length(buffer) < used_org + tolen)
+ return (ISC_R_NOSPACE);
+
+ isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
+ memcpy(isc_buffer_used(buffer), tmp1, tolen);
+ isc_buffer_add(buffer, tolen);
+
+ return (ISC_R_SUCCESS);
+}
+
+static idn_result_t
+append_textname(char *name, const char *origin, size_t namesize) {
+ size_t namelen = strlen(name);
+ size_t originlen = strlen(origin);
+
+ /* Already absolute? */
+ if (namelen > 0 && name[namelen - 1] == '.')
+ return idn_success;
+
+ /* Append dot and origin */
+
+ if (namelen + 1 + originlen >= namesize)
+ return idn_buffer_overflow;
+
+ name[namelen++] = '.';
+ (void)strcpy(name + namelen, origin);
+ return idn_success;
+}
+
+static void
+idn_check_result(idn_result_t r, const char *msg) {
+ if (r != idn_success) {
+ exitcode = 1;
+ fatal("%s: %s", msg, idn_result_tostring(r));
+ }
+}
+#endif /* WITH_IDN */
+
+#ifdef DIG_SIGCHASE
+void
+print_type(dns_rdatatype_t type)
+{
+ isc_buffer_t * b = NULL;
+ isc_result_t result;
+ isc_region_t r;
+
+ result = isc_buffer_allocate(mctx, &b, 4000);
+ check_result(result, "isc_buffer_allocate");
+
+ result = dns_rdatatype_totext(type, b);
+ check_result(result, "print_type");
+
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+
+ printf("%s", r.base);
+
+ isc_buffer_free(&b);
+}
+
+void
+dump_database_section(dns_message_t *msg, int section)
+{
+ dns_name_t *msg_name=NULL;
+
+ dns_rdataset_t *rdataset;
+
+ do {
+ dns_message_currentname(msg, section, &msg_name);
+
+ for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ dns_name_print(msg_name, stdout);
+ printf("\n");
+ print_rdataset(msg_name, rdataset, mctx);
+ printf("end\n");
+ }
+ msg_name = NULL;
+ } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
+}
+
+void
+dump_database(void) {
+ dig_message_t * msg;
+
+ for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL;
+ msg = ISC_LIST_NEXT(msg, link)) {
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
+ == ISC_R_SUCCESS)
+ dump_database_section(msg->msg, DNS_SECTION_ANSWER);
+
+ if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
+ == ISC_R_SUCCESS)
+ dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
+
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
+ == ISC_R_SUCCESS)
+ dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
+ }
+}
+
+
+dns_rdataset_t *
+search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
+ dns_rdataset_t *rdataset;
+ dns_rdata_sig_t siginfo;
+ dns_rdata_t sigrdata;
+ isc_result_t result;
+
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (type == dns_rdatatype_any) {
+ if (rdataset->type != dns_rdatatype_rrsig)
+ return (rdataset);
+ } else if ((type == dns_rdatatype_rrsig) &&
+ (rdataset->type == dns_rdatatype_rrsig)) {
+ dns_rdata_init(&sigrdata);
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "empty rdataset");
+ dns_rdataset_current(rdataset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+
+ if ((siginfo.covered == covers) ||
+ (covers == dns_rdatatype_any)) {
+ dns_rdata_reset(&sigrdata);
+ dns_rdata_freestruct(&siginfo);
+ return (rdataset);
+ }
+ dns_rdata_reset(&sigrdata);
+ dns_rdata_freestruct(&siginfo);
+ } else if (rdataset->type == type)
+ return (rdataset);
+ }
+ return (NULL);
+}
+
+dns_rdataset_t *
+chase_scanname_section(dns_message_t *msg, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ int section)
+{
+ dns_rdataset_t *rdataset;
+ dns_name_t *msg_name = NULL;
+
+ do {
+ dns_message_currentname(msg, section, &msg_name);
+ if (dns_name_compare(msg_name, name) == 0) {
+ rdataset = search_type(msg_name, type, covers);
+ if (rdataset != NULL)
+ return (rdataset);
+ }
+ msg_name = NULL;
+ } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
+
+ return (NULL);
+}
+
+
+dns_rdataset_t *
+chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
+{
+ dns_rdataset_t *rdataset = NULL;
+ dig_message_t * msg;
+
+ for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL;
+ msg = ISC_LIST_NEXT(msg, link)) {
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
+ == ISC_R_SUCCESS)
+ rdataset = chase_scanname_section(msg->msg, name,
+ type, covers,
+ DNS_SECTION_ANSWER);
+ if (rdataset != NULL)
+ return (rdataset);
+ if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
+ == ISC_R_SUCCESS)
+ rdataset =
+ chase_scanname_section(msg->msg, name,
+ type, covers,
+ DNS_SECTION_AUTHORITY);
+ if (rdataset != NULL)
+ return (rdataset);
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
+ == ISC_R_SUCCESS)
+ rdataset =
+ chase_scanname_section(msg->msg, name, type,
+ covers,
+ DNS_SECTION_ADDITIONAL);
+ if (rdataset != NULL)
+ return (rdataset);
+ }
+
+ return (NULL);
+}
+
+dns_rdataset_t *
+sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
+ isc_boolean_t * lookedup, dns_name_t *rdata_name)
+{
+ dig_lookup_t *lookup;
+ isc_buffer_t *b = NULL;
+ isc_region_t r;
+ isc_result_t result;
+ dns_rdataset_t * temp;
+ dns_rdatatype_t querytype;
+
+ temp = chase_scanname(rdata_name, type, covers);
+ if (temp != NULL)
+ return (temp);
+
+ if (*lookedup == ISC_TRUE)
+ return (NULL);
+
+ lookup = clone_lookup(current_lookup, ISC_TRUE);
+ lookup->trace_root = ISC_FALSE;
+ lookup->new_search = ISC_TRUE;
+
+ result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_name_totext(rdata_name, ISC_FALSE, b);
+ check_result(result, "dns_name_totext");
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strcpy(lookup->textname, (char*)r.base);
+ isc_buffer_free(&b);
+
+ if (type == dns_rdatatype_rrsig)
+ querytype = covers;
+ else
+ querytype = type;
+
+ if (querytype == 0 || querytype == 255) {
+ printf("Error in the queried type: %d\n", querytype);
+ return (NULL);
+ }
+
+ lookup->rdtype = querytype;
+ lookup->rdtypeset = ISC_TRUE;
+ lookup->qrdtype = querytype;
+ *lookedup = ISC_TRUE;
+
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ printf("\n\nLaunch a query to find a RRset of type ");
+ print_type(type);
+ printf(" for zone: %s\n", lookup->textname);
+ return (NULL);
+}
+
+void
+insert_trustedkey(dst_key_t * key)
+{
+ if (key == NULL)
+ return;
+ if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
+ return;
+
+ tk_list.key[tk_list.nb_tk++] = key;
+ return;
+}
+
+void
+clean_trustedkey()
+{
+ int i = 0;
+
+ for (i= 0; i < MAX_TRUSTED_KEY; i++) {
+ if (tk_list.key[i] != NULL) {
+ dst_key_free(&tk_list.key[i]);
+ tk_list.key[i] = NULL;
+ } else
+ break;
+ }
+ tk_list.nb_tk = 0;
+ return;
+}
+
+char alphnum[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+isc_result_t
+removetmpkey(isc_mem_t *mctx, const char *file)
+{
+ char *tempnamekey = NULL;
+ int tempnamekeylen;
+ isc_result_t result;
+
+ tempnamekeylen = strlen(file)+10;
+
+ tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
+ if (tempnamekey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(tempnamekey, 0, tempnamekeylen);
+
+ strcat(tempnamekey, file);
+ strcat(tempnamekey,".key");
+ isc_file_remove(tempnamekey);
+
+ result = isc_file_remove(tempnamekey);
+ isc_mem_free(mctx, tempnamekey);
+ return (result);
+}
+
+isc_result_t
+opentmpkey(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) {
+ FILE *f = NULL;
+ isc_result_t result;
+ char *tempname = NULL;
+ char *tempnamekey = NULL;
+ int tempnamelen;
+ int tempnamekeylen;
+ char *x;
+ char *cp;
+ isc_uint32_t which;
+
+ while (1) {
+ tempnamelen = strlen(file) + 20;
+ tempname = isc_mem_allocate(mctx, tempnamelen);
+ if (tempname == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(tempname, 0, tempnamelen);
+
+ result = isc_file_mktemplate(file, tempname, tempnamelen);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ cp = tempname;
+ while (*cp != '\0')
+ cp++;
+ if (cp == tempname) {
+ isc_mem_free(mctx, tempname);
+ return (ISC_R_FAILURE);
+ }
+
+ x = cp--;
+ while (cp >= tempname && *cp == 'X') {
+ isc_random_get(&which);
+ *cp = alphnum[which % (sizeof(alphnum) - 1)];
+ x = cp--;
+ }
+
+ tempnamekeylen = tempnamelen+5;
+ tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
+ if (tempnamekey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(tempnamekey, 0, tempnamekeylen);
+ strncpy(tempnamekey, tempname, tempnamelen);
+ strcat(tempnamekey ,".key");
+
+
+ if (isc_file_exists(tempnamekey)) {
+ isc_mem_free(mctx, tempnamekey);
+ isc_mem_free(mctx, tempname);
+ continue;
+ }
+
+ if ((f = fopen(tempnamekey, "w")) == NULL) {
+ printf("get_trusted_key(): trusted key not found %s\n",
+ tempnamekey);
+ return (ISC_R_FAILURE);
+ }
+ break;
+ }
+ isc_mem_free(mctx, tempnamekey);
+ *tempp = tempname;
+ *fp = f;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_mem_free(mctx, tempname);
+
+ return (result);
+}
+
+
+isc_result_t
+get_trusted_key(isc_mem_t *mctx)
+{
+ isc_result_t result;
+ const char *filename = NULL;
+ char *filetemp = NULL;
+ char buf[1500];
+ FILE *fp, *fptemp;
+ dst_key_t *key = NULL;
+
+ result = isc_file_exists(trustedkey);
+ if (result != ISC_TRUE) {
+ result = isc_file_exists("/etc/trusted-key.key");
+ if (result != ISC_TRUE) {
+ result = isc_file_exists("./trusted-key.key");
+ if (result != ISC_TRUE)
+ return (ISC_R_FAILURE);
+ else
+ filename = "./trusted-key.key";
+ } else
+ filename = "/etc/trusted-key.key";
+ } else
+ filename = trustedkey;
+
+ if (filename == NULL) {
+ printf("No trusted key\n");
+ return (ISC_R_FAILURE);
+ }
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ printf("get_trusted_key(): trusted key not found %s\n",
+ filename);
+ return (ISC_R_FAILURE);
+ }
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ result = opentmpkey(mctx,"tmp_file", &filetemp, &fptemp);
+ if (result != ISC_R_SUCCESS) {
+ fclose(fp);
+ return (ISC_R_FAILURE);
+ }
+ if (fputs(buf, fptemp) < 0) {
+ fclose(fp);
+ fclose(fptemp);
+ return (ISC_R_FAILURE);
+ }
+ fclose(fptemp);
+ result = dst_key_fromnamedfile(filetemp, DST_TYPE_PUBLIC,
+ mctx, &key);
+ removetmpkey(mctx, filetemp);
+ isc_mem_free(mctx, filetemp);
+ if (result != ISC_R_SUCCESS) {
+ fclose(fp);
+ return (ISC_R_FAILURE);
+ }
+ insert_trustedkey(key);
+#if 0
+ dst_key_tofile(key, DST_TYPE_PUBLIC,"/tmp");
+#endif
+ key = NULL;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+
+static void
+nameFromString(const char *str, dns_name_t *p_ret) {
+ size_t len = strlen(str);
+ isc_result_t result;
+ isc_buffer_t buffer;
+ dns_fixedname_t fixedname;
+
+ REQUIRE(p_ret != NULL);
+ REQUIRE(str != NULL);
+
+ isc_buffer_init(&buffer, str, len);
+ isc_buffer_add(&buffer, len);
+
+ dns_fixedname_init(&fixedname);
+ result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
+ dns_rootname, ISC_TRUE, NULL);
+ check_result(result, "nameFromString");
+
+ if (dns_name_dynamic(p_ret))
+ free_name(p_ret, mctx);
+
+ result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
+ check_result(result, "nameFromString");
+}
+
+
+#if DIG_SIGCHASE_TD
+isc_result_t
+prepare_lookup(dns_name_t *name)
+{
+ isc_result_t result;
+ dig_lookup_t *lookup = NULL;
+ dig_server_t *s;
+ void *ptr;
+
+ lookup = clone_lookup(current_lookup, ISC_TRUE);
+ lookup->trace_root = ISC_FALSE;
+ lookup->new_search = ISC_TRUE;
+ lookup->trace_root_sigchase = ISC_FALSE;
+
+ strncpy(lookup->textname, lookup->textnamesigchase, MXNAME);
+
+ lookup->rdtype = lookup->rdtype_sigchase;
+ lookup->rdtypeset = ISC_TRUE;
+ lookup->qrdtype = lookup->qrdtype_sigchase;
+
+ s = ISC_LIST_HEAD(lookup->my_server_list);
+ while (s != NULL) {
+ debug("freeing server %p belonging to %p",
+ s, lookup);
+ ptr = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(lookup->my_server_list,
+ (dig_server_t *)ptr, link);
+ isc_mem_free(mctx, ptr);
+ }
+
+
+ for (result = dns_rdataset_first(chase_nsrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(chase_nsrdataset)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_rdata_ns_t ns;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dig_server_t * srv = NULL;
+#define __FOLLOW_GLUE__
+#ifdef __FOLLOW_GLUE__
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+ isc_region_t r;
+ dns_rdataset_t *rdataset = NULL;
+ isc_boolean_t true = ISC_TRUE;
+#endif
+
+ memset(namestr, 0, DNS_NAME_FORMATSIZE);
+
+ dns_rdataset_current(chase_nsrdataset, &rdata);
+
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+#ifdef __FOLLOW_GLUE__
+
+ result = advanced_rrsearch(&rdataset, &ns.name,
+ dns_rdatatype_aaaa,
+ dns_rdatatype_any, &true);
+ if (result == ISC_R_SUCCESS) {
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t aaaa = DNS_RDATA_INIT;
+ dns_rdataset_current(rdataset, &aaaa);
+
+ result = isc_buffer_allocate(mctx, &b, 80);
+ check_result(result, "isc_buffer_allocate");
+
+ dns_rdata_totext(&aaaa, &ns.name, b);
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strncpy(namestr, (char*)r.base,
+ DNS_NAME_FORMATSIZE);
+ isc_buffer_free(&b);
+ dns_rdata_reset(&aaaa);
+
+
+ srv = make_server(namestr, namestr);
+
+ ISC_LIST_APPEND(lookup->my_server_list,
+ srv, link);
+ }
+ }
+
+ rdataset = NULL;
+ result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
+ dns_rdatatype_any, &true);
+ if (result == ISC_R_SUCCESS) {
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t a = DNS_RDATA_INIT;
+ dns_rdataset_current(rdataset, &a);
+
+ result = isc_buffer_allocate(mctx, &b, 80);
+ check_result(result, "isc_buffer_allocate");
+
+ dns_rdata_totext(&a, &ns.name, b);
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strncpy(namestr, (char*)r.base,
+ DNS_NAME_FORMATSIZE);
+ isc_buffer_free(&b);
+ dns_rdata_reset(&a);
+ printf("ns name: %s\n", namestr);
+
+
+ srv = make_server(namestr, namestr);
+
+ ISC_LIST_APPEND(lookup->my_server_list,
+ srv, link);
+ }
+ }
+#else
+
+ dns_name_format(&ns.name, namestr, sizeof(namestr));
+ printf("ns name: ");
+ dns_name_print(&ns.name, stdout);
+ printf("\n");
+ srv = make_server(namestr, namestr);
+
+ ISC_LIST_APPEND(lookup->my_server_list, srv, link);
+
+#endif
+ dns_rdata_freestruct(&ns);
+ dns_rdata_reset(&rdata);
+
+ }
+
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ printf("\nLaunch a query to find a RRset of type ");
+ print_type(lookup->rdtype);
+ printf(" for zone: %s", lookup->textname);
+ printf(" with nameservers:");
+ printf("\n");
+ print_rdataset(name, chase_nsrdataset, mctx);
+ return (ISC_R_SUCCESS);
+}
+
+
+isc_result_t
+child_of_zone(dns_name_t * name, dns_name_t * zone_name,
+ dns_name_t * child_name)
+{
+ dns_namereln_t name_reln;
+ int orderp;
+ unsigned int nlabelsp;
+
+ name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
+ if (name_reln != dns_namereln_subdomain ||
+ dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
+ printf("\n;; ERROR : ");
+ dns_name_print(name, stdout);
+ printf(" is not a subdomain of: ");
+ dns_name_print(zone_name, stdout);
+ printf(" FAILED\n\n");
+ return (ISC_R_FAILURE);
+ }
+
+ dns_name_getlabelsequence(name,
+ dns_name_countlabels(name) -
+ dns_name_countlabels(zone_name) -1,
+ dns_name_countlabels(zone_name) +1,
+ child_name);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset)
+{
+ isc_result_t result;
+ dns_rdata_t sigrdata;
+ dns_rdata_sig_t siginfo;
+
+ result = dns_rdataset_first(sigrdataset);
+ check_result(result, "empty RRSIG dataset");
+ dns_rdata_init(&sigrdata);
+
+ do {
+ dns_rdataset_current(sigrdataset, &sigrdata);
+
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+
+ if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
+ dns_rdata_freestruct(&siginfo);
+ dns_rdata_reset(&sigrdata);
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_rdata_freestruct(&siginfo);
+
+ } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
+
+ dns_rdata_reset(&sigrdata);
+
+ return (ISC_R_FAILURE);
+}
+
+
+isc_result_t
+initialization(dns_name_t *name)
+{
+ isc_result_t result;
+ isc_boolean_t true = ISC_TRUE;
+
+ chase_nsrdataset = NULL;
+ result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
+ dns_rdatatype_any, &true);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; NS RRset is missing to continue validation:"
+ " FAILED\n\n");
+ return (ISC_R_FAILURE);
+ }
+ INSIST(chase_nsrdataset != NULL);
+ prepare_lookup(name);
+
+ dup_name(name, &chase_current_name, mctx);
+
+ return (ISC_R_SUCCESS);
+}
+#endif
+
+void
+print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset, isc_mem_t *mctx)
+{
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+ isc_region_t r;
+
+ result = isc_buffer_allocate(mctx, &b, 9000);
+ check_result(result, "isc_buffer_allocate");
+
+ printrdataset(name, rdataset, b);
+
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+
+
+ printf("%s\n", r.base);
+
+ isc_buffer_free(&b);
+}
+
+
+void
+dup_name(dns_name_t *source, dns_name_t *target, isc_mem_t *mctx) {
+ isc_result_t result;
+
+ if (dns_name_dynamic(target))
+ free_name(target, mctx);
+ result = dns_name_dup(source, mctx, target);
+ check_result(result, "dns_name_dup");
+}
+
+void
+free_name(dns_name_t *name, isc_mem_t *mctx) {
+ dns_name_free(name, mctx);
+ dns_name_init(name, NULL);
+}
+
+/*
+ *
+ * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
+ * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
+ * and the RRset is valid
+ * return ISC_R_NOTFOUND if not contains trusted key
+ or if the RRset isn't valid
+ * return ISC_R_FAILURE if problem
+ *
+ */
+isc_result_t
+contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset,
+ isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_rdata_t rdata;
+ dst_key_t *trustedKey = NULL;
+ dst_key_t *dnsseckey = NULL;
+ int i;
+
+ if (name == NULL || rdataset == NULL)
+ return (ISC_R_FAILURE);
+
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "empty rdataset");
+ dns_rdata_init(&rdata);
+
+ do {
+ dns_rdataset_current(rdataset, &rdata);
+ INSIST(rdata.type == dns_rdatatype_dnskey);
+
+ result = dns_dnssec_keyfromrdata(name, &rdata,
+ mctx, &dnsseckey);
+ check_result(result, "dns_dnssec_keyfromrdata");
+
+
+ for (i = 0; i < tk_list.nb_tk; i++) {
+ if (dst_key_compare(tk_list.key[i], dnsseckey)
+ == ISC_TRUE) {
+ dns_rdata_reset(&rdata);
+
+ printf(";; Ok, find a Trusted Key in the "
+ "DNSKEY RRset: %d\n",
+ dst_key_id(dnsseckey));
+ if (sigchase_verify_sig_key(name, rdataset,
+ dnsseckey,
+ sigrdataset,
+ mctx)
+ == ISC_R_SUCCESS) {
+ dst_key_free(&dnsseckey);
+ dnsseckey = NULL;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ }
+
+ dns_rdata_reset(&rdata);
+ if (dnsseckey != NULL)
+ dst_key_free(&dnsseckey);
+ } while (dns_rdataset_next(rdataset) == ISC_R_SUCCESS);
+
+ if (trustedKey != NULL)
+ dst_key_free(&trustedKey);
+ trustedKey = NULL;
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *sigrdataset,
+ isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_rdata_t keyrdata;
+ dst_key_t *dnsseckey = NULL;
+
+ result = dns_rdataset_first(keyrdataset);
+ check_result(result, "empty DNSKEY dataset");
+ dns_rdata_init(&keyrdata);
+
+ do {
+ dns_rdataset_current(keyrdataset, &keyrdata);
+ INSIST(keyrdata.type == dns_rdatatype_dnskey);
+
+ result = dns_dnssec_keyfromrdata(name, &keyrdata,
+ mctx, &dnsseckey);
+ check_result(result, "dns_dnssec_keyfromrdata");
+
+ result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
+ sigrdataset, mctx);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&keyrdata);
+ dst_key_free(&dnsseckey);
+ return (ISC_R_SUCCESS);
+ }
+ dst_key_free(&dnsseckey);
+ } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
+
+ dns_rdata_reset(&keyrdata);
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
+ dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset,
+ isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_rdata_t sigrdata;
+ dns_rdata_sig_t siginfo;
+
+ result = dns_rdataset_first(sigrdataset);
+ check_result(result, "empty RRSIG dataset");
+ dns_rdata_init(&sigrdata);
+
+ do {
+ dns_rdataset_current(sigrdataset, &sigrdata);
+
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+
+ /*
+ * Test if the id of the DNSKEY is
+ * the id of the DNSKEY signer's
+ */
+ if (siginfo.keyid == dst_key_id(dnsseckey)) {
+
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "empty DS dataset");
+
+ result = dns_dnssec_verify(name, rdataset, dnsseckey,
+ ISC_FALSE, mctx, &sigrdata);
+
+ printf(";; VERIFYING ");
+ print_type(rdataset->type);
+ printf(" RRset for ");
+ dns_name_print(name, stdout);
+ printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
+ isc_result_totext(result));
+
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&sigrdata);
+ return (result);
+ }
+ }
+ dns_rdata_freestruct(&siginfo);
+
+ } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
+
+ dns_rdata_reset(&sigrdata);
+
+ return (ISC_R_NOTFOUND);
+}
+
+
+isc_result_t
+sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_rdata_t keyrdata;
+ dns_rdata_t newdsrdata;
+ dns_rdata_t dsrdata;
+ dns_rdata_ds_t dsinfo;
+ dst_key_t *dnsseckey = NULL;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+
+ result = dns_rdataset_first(dsrdataset);
+ check_result(result, "empty DSset dataset");
+ dns_rdata_init(&dsrdata);
+ do {
+ dns_rdataset_current(dsrdataset, &dsrdata);
+
+ result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
+ check_result(result, "dns_rdata_tostruct for DS");
+
+ result = dns_rdataset_first(keyrdataset);
+ check_result(result, "empty KEY dataset");
+ dns_rdata_init(&keyrdata);
+
+ do {
+ dns_rdataset_current(keyrdataset, &keyrdata);
+ INSIST(keyrdata.type == dns_rdatatype_dnskey);
+
+ result = dns_dnssec_keyfromrdata(name, &keyrdata,
+ mctx, &dnsseckey);
+ check_result(result, "dns_dnssec_keyfromrdata");
+
+ /*
+ * Test if the id of the DNSKEY is the
+ * id of DNSKEY referenced by the DS
+ */
+ if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
+ dns_rdata_init(&newdsrdata);
+
+ result = dns_ds_buildrdata(name, &keyrdata,
+ dsinfo.digest_type,
+ dsbuf, &newdsrdata);
+ dns_rdata_freestruct(&dsinfo);
+
+ if (result != ISC_R_SUCCESS) {
+ dns_rdata_reset(&keyrdata);
+ dns_rdata_reset(&newdsrdata);
+ dns_rdata_reset(&dsrdata);
+ dst_key_free(&dnsseckey);
+ dns_rdata_freestruct(&dsinfo);
+ printf("Oops: impossible to build"
+ " new DS rdata\n");
+ return (result);
+ }
+
+
+ if (dns_rdata_compare(&dsrdata,
+ &newdsrdata) == 0) {
+ printf(";; OK a DS valids a DNSKEY"
+ " in the RRset\n");
+ printf(";; Now verify that this"
+ " DNSKEY validates the "
+ "DNSKEY RRset\n");
+
+ result = sigchase_verify_sig_key(name,
+ keyrdataset,
+ dnsseckey,
+ chase_sigkeyrdataset,
+ mctx);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&keyrdata);
+ dns_rdata_reset(&newdsrdata);
+ dns_rdata_reset(&dsrdata);
+ dst_key_free(&dnsseckey);
+
+ return (result);
+ }
+ } else {
+ printf(";; This DS is NOT the DS for"
+ " the chasing KEY: FAILED\n");
+ }
+
+ dns_rdata_reset(&newdsrdata);
+ }
+ dst_key_free(&dnsseckey);
+ dnsseckey = NULL;
+ } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
+ dns_rdata_reset(&keyrdata);
+
+ } while (dns_rdataset_next(chase_dsrdataset) == ISC_R_SUCCESS);
+#if 0
+ dns_rdata_reset(&dsrdata); WARNING
+#endif
+
+ return (ISC_R_NOTFOUND);
+}
+
+/*
+ *
+ * take a pointer on a rdataset in parameter and try to resolv it.
+ * the searched rrset is a rrset on 'name' with type 'type'
+ * (and if the type is a rrsig the signature cover 'covers').
+ * the lookedup is to known if you have already done the query on the net.
+ * ISC_R_SUCCESS: if we found the rrset
+ * ISC_R_NOTFOUND: we do not found the rrset in cache
+ * and we do a query on the net
+ * ISC_R_FAILURE: rrset not found
+ */
+isc_result_t
+advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ isc_boolean_t *lookedup)
+{
+ isc_boolean_t tmplookedup;
+
+ INSIST(rdataset != NULL);
+
+ if (*rdataset != NULL)
+ return (ISC_R_SUCCESS);
+
+ tmplookedup = *lookedup;
+ if ((*rdataset = sigchase_scanname(type, covers,
+ lookedup, name)) == NULL) {
+ if (tmplookedup)
+ return (ISC_R_FAILURE);
+ return (ISC_R_NOTFOUND);
+ }
+ *lookedup = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+}
+
+
+
+#if DIG_SIGCHASE_TD
+void
+sigchase_td(dns_message_t *msg)
+{
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ isc_boolean_t have_answer = ISC_FALSE;
+ isc_boolean_t true = ISC_TRUE;
+
+ if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
+ == ISC_R_SUCCESS) {
+ dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+ if (current_lookup->trace_root_sigchase) {
+ initialization(name);
+ return;
+ }
+ have_answer = true;
+ } else {
+ if (!current_lookup->trace_root_sigchase) {
+ result = dns_message_firstname(msg,
+ DNS_SECTION_AUTHORITY);
+ if (result == ISC_R_SUCCESS)
+ dns_message_currentname(msg,
+ DNS_SECTION_AUTHORITY,
+ &name);
+ chase_nsrdataset
+ = chase_scanname_section(msg, name,
+ dns_rdatatype_ns,
+ dns_rdatatype_any,
+ DNS_SECTION_AUTHORITY);
+ dup_name(name, &chase_authority_name, mctx);
+ if (chase_nsrdataset != NULL) {
+ have_delegation_ns = ISC_TRUE;
+ printf("no response but there is a delegation"
+ " in authority section:");
+ dns_name_print(name, stdout);
+ printf("\n");
+ } else {
+ printf("no response and no delegation in "
+ "authority section but a reference"
+ " to: ");
+ dns_name_print(name, stdout);
+ printf("\n");
+ error_message = msg;
+ }
+ } else {
+ printf(";; NO ANSWERS: %s\n",
+ isc_result_totext(result));
+ free_name(&chase_name, mctx);
+ clean_trustedkey();
+ return;
+ }
+ }
+
+
+ if (have_answer) {
+ chase_rdataset
+ = chase_scanname_section(msg, &chase_name,
+ current_lookup
+ ->rdtype_sigchase,
+ dns_rdatatype_any,
+ DNS_SECTION_ANSWER);
+ if (chase_rdataset != NULL)
+ have_response = ISC_TRUE;
+ }
+
+ result = advanced_rrsearch(&chase_keyrdataset,
+ &chase_current_name,
+ dns_rdatatype_dnskey,
+ dns_rdatatype_any,
+ &chase_keylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; DNSKEY is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND)
+ return;
+ INSIST(chase_keyrdataset != NULL);
+ printf("\n;; DNSKEYset:\n");
+ print_rdataset(&chase_current_name , chase_keyrdataset, mctx);
+
+
+ result = advanced_rrsearch(&chase_sigkeyrdataset,
+ &chase_current_name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_dnskey,
+ &chase_sigkeylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND)
+ return;
+ INSIST(chase_sigkeyrdataset != NULL);
+ printf("\n;; RRSIG of the DNSKEYset:\n");
+ print_rdataset(&chase_current_name , chase_sigkeyrdataset, mctx);
+
+
+ if (!chase_dslookedup && !chase_nslookedup) {
+ if (!delegation_follow) {
+ result = contains_trusted_key(&chase_current_name,
+ chase_keyrdataset,
+ chase_sigkeyrdataset,
+ mctx);
+ } else {
+ INSIST(chase_dsrdataset != NULL);
+ INSIST(chase_sigdsrdataset != NULL);
+ result = sigchase_verify_ds(&chase_current_name,
+ chase_keyrdataset,
+ chase_dsrdataset,
+ mctx);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; chain of trust can't be validated:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ } else {
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ }
+ }
+
+ if (have_response || (!have_delegation_ns && !have_response)) {
+ /* test if it's a grand father case */
+
+ if (have_response) {
+ result = advanced_rrsearch(&chase_sigrdataset,
+ &chase_name,
+ dns_rdatatype_rrsig,
+ current_lookup
+ ->rdtype_sigchase,
+ &true);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRset is missing to continue"
+ " validation SHOULD NOT APPEND:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+
+ } else {
+ result = advanced_rrsearch(&chase_sigrdataset,
+ &chase_authority_name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_any,
+ &true);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG is missing to continue"
+ " validation SHOULD NOT APPEND:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ }
+ result = grandfather_pb_test(&chase_current_name,
+ chase_sigrdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_name_t tmp_name;
+
+ printf("\n;; We are in a Grand Father Problem:"
+ " See 2.2.1 in RFC 3568\n");
+ chase_rdataset = NULL;
+ chase_sigrdataset = NULL;
+ have_response = ISC_FALSE;
+ have_delegation_ns = ISC_FALSE;
+
+ dns_name_init(&tmp_name, NULL);
+ result = child_of_zone(&chase_name, &chase_current_name,
+ &tmp_name);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name, mctx);
+ dup_name(&tmp_name, &chase_authority_name, mctx);
+ printf(";; and we try to continue chain of trust"
+ " validation of the zone: ");
+ dns_name_print(&chase_authority_name, stdout);
+ printf("\n");
+ have_delegation_ns = ISC_TRUE;
+ } else {
+ if (have_response)
+ goto finalstep;
+ else
+ chase_sigrdataset = NULL;
+ }
+ }
+
+ if (have_delegation_ns) {
+ chase_nsrdataset = NULL;
+ result = advanced_rrsearch(&chase_nsrdataset,
+ &chase_authority_name,
+ dns_rdatatype_ns,
+ dns_rdatatype_any,
+ &chase_nslookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;;NSset is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND) {
+ return;
+ }
+ INSIST(chase_nsrdataset != NULL);
+
+ result = advanced_rrsearch(&chase_dsrdataset,
+ &chase_authority_name,
+ dns_rdatatype_ds,
+ dns_rdatatype_any,
+ &chase_dslookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; DSset is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND)
+ return;
+ INSIST(chase_dsrdataset != NULL);
+ printf("\n;; DSset:\n");
+ print_rdataset(&chase_authority_name , chase_dsrdataset, mctx);
+
+ result = advanced_rrsearch(&chase_sigdsrdataset,
+ &chase_authority_name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_ds,
+ &true);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; DSset is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ printf("\n;; RRSIGset of DSset\n");
+ print_rdataset(&chase_authority_name,
+ chase_sigdsrdataset, mctx);
+ INSIST(chase_sigdsrdataset != NULL);
+
+ result = sigchase_verify_sig(&chase_authority_name,
+ chase_dsrdataset,
+ chase_keyrdataset,
+ chase_sigdsrdataset, mctx);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; Impossible to verify the DSset:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+
+
+ prepare_lookup(&chase_authority_name);
+
+ have_response = ISC_FALSE;
+ have_delegation_ns = ISC_FALSE;
+ delegation_follow = ISC_TRUE;
+ error_message = NULL;
+ dup_name(&chase_authority_name, &chase_current_name, mctx);
+ free_name(&chase_authority_name, mctx);
+ return;
+ }
+
+
+ if (error_message != NULL) {
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ dns_name_t rdata_name;
+ isc_result_t ret = ISC_R_FAILURE;
+
+ dns_name_init(&rdata_name, NULL);
+ result = prove_nx(error_message, &chase_name,
+ current_lookup->rdclass_sigchase,
+ current_lookup->rdtype_sigchase, &rdata_name,
+ &rdataset, &sigrdataset);
+ if (rdataset == NULL || sigrdataset == NULL ||
+ dns_name_countlabels(&rdata_name) == 0) {
+ printf("\n;; Impossible to verify the non-existence,"
+ " the NSEC RRset can't be validated:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ ret = sigchase_verify_sig(&rdata_name, rdataset,
+ chase_keyrdataset,
+ sigrdataset, mctx);
+ if (ret != ISC_R_SUCCESS) {
+ free_name(&rdata_name, mctx);
+ printf("\n;; Impossible to verify the NSEC RR to prove"
+ " the non-existence : FAILED\n\n");
+ goto cleanandgo;
+ }
+ free_name(&rdata_name, mctx);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; Impossible to verify the non-existence:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ } else {
+ printf("\n;; OK the query doesn't have response but"
+ " we have validate this fact : SUCCESS\n\n");
+ goto cleanandgo;
+ }
+ }
+
+ cleanandgo:
+ printf(";; cleanandgo \n");
+ if (dns_name_dynamic(&chase_current_name))
+ free_name(&chase_current_name, mctx);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name, mctx);
+ clean_trustedkey();
+ return;
+
+ finalstep :
+ result = advanced_rrsearch(&chase_rdataset, &chase_name,
+ current_lookup->rdtype_sigchase,
+ dns_rdatatype_any ,
+ &true);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRsig of RRset is missing to continue validation"
+ " SHOULD NOT APPEND: FAILED\n\n");
+ goto cleanandgo;
+ }
+ result = sigchase_verify_sig(&chase_name, chase_rdataset,
+ chase_keyrdataset,
+ chase_sigrdataset, mctx);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; Impossible to verify the RRset : FAILED\n\n");
+ /*
+ printf("RRset:\n");
+ print_rdataset(&chase_name , chase_rdataset, mctx);
+ printf("DNSKEYset:\n");
+ print_rdataset(&chase_name , chase_keyrdataset, mctx);
+ printf("RRSIG of RRset:\n");
+ print_rdataset(&chase_name , chase_sigrdataset, mctx);
+ printf("\n");
+ */
+ goto cleanandgo;
+ } else {
+ printf("\n;; The Answer:\n");
+ print_rdataset(&chase_name , chase_rdataset, mctx);
+
+ printf("\n;; FINISH : we have validate the DNSSEC chain"
+ " of trust: SUCCESS\n\n");
+ goto cleanandgo;
+ }
+}
+
+#endif
+
+
+#if DIG_SIGCHASE_BU
+
+isc_result_t
+getneededrr(dns_message_t *msg)
+{
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ dns_rdata_t sigrdata;
+ dns_rdata_sig_t siginfo;
+ isc_boolean_t true = ISC_TRUE;
+
+ if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
+ != ISC_R_SUCCESS) {
+ printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
+
+ if (chase_name.ndata == NULL)
+ return (ISC_R_ADDRNOTAVAIL);
+ } else {
+ dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+ }
+
+ /* What do we chase? */
+ if (chase_rdataset == NULL) {
+ result = advanced_rrsearch(&chase_rdataset, name,
+ dns_rdatatype_any,
+ dns_rdatatype_any, &true);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; No Answers: Validation FAILED\n\n");
+ return (ISC_R_NOTFOUND);
+ }
+ dup_name(name, &chase_name, mctx);
+ printf(";; RRset to chase:\n");
+ print_rdataset(&chase_name, chase_rdataset, mctx);
+ }
+ INSIST(chase_rdataset != NULL);
+
+
+ if (chase_sigrdataset == NULL) {
+ result = advanced_rrsearch(&chase_sigrdataset, name,
+ dns_rdatatype_rrsig,
+ chase_rdataset->type,
+ &chase_siglookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG is missing for continue validation:"
+ " FAILED\n\n");
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; RRSIG of the RRset to chase:\n");
+ print_rdataset(&chase_name, chase_sigrdataset, mctx);
+ }
+ INSIST(chase_sigrdataset != NULL);
+
+
+ /* first find the DNSKEY name */
+ result = dns_rdataset_first(chase_sigrdataset);
+ check_result(result, "empty RRSIG dataset");
+ dns_rdata_init(&sigrdata);
+ dns_rdataset_current(chase_sigrdataset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+ dup_name(&siginfo.signer, &chase_signame, mctx);
+ dns_rdata_freestruct(&siginfo);
+ dns_rdata_reset(&sigrdata);
+
+ /* Do we have a key? */
+ if (chase_keyrdataset == NULL) {
+ result = advanced_rrsearch(&chase_keyrdataset,
+ &chase_signame,
+ dns_rdatatype_dnskey,
+ dns_rdatatype_any,
+ &chase_keylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; DNSKEY is missing to continue validation:"
+ " FAILED\n\n");
+ free_name(&chase_signame, mctx);
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; DNSKEYset that signs the RRset to chase:\n");
+ print_rdataset(&chase_signame, chase_keyrdataset, mctx);
+ }
+ INSIST(chase_keyrdataset != NULL);
+
+ if (chase_sigkeyrdataset == NULL) {
+ result = advanced_rrsearch(&chase_sigkeyrdataset,
+ &chase_signame,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_dnskey,
+ &chase_sigkeylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG for DNSKEY is missing to continue"
+ " validation : FAILED\n\n");
+ free_name(&chase_signame, mctx);
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; RRSIG of the DNSKEYset that signs the "
+ "RRset to chase:\n");
+ print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx);
+ }
+ INSIST(chase_sigkeyrdataset != NULL);
+
+
+ if (chase_dsrdataset == NULL) {
+ result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
+ dns_rdatatype_ds,
+ dns_rdatatype_any,
+ &chase_dslookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; WARNING There is no DS for the zone: ");
+ dns_name_print(&chase_signame, stdout);
+ printf("\n");
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ if (chase_dsrdataset != NULL) {
+ printf("\n;; DSset of the DNSKEYset\n");
+ print_rdataset(&chase_signame, chase_dsrdataset, mctx);
+ }
+ }
+
+ if (chase_dsrdataset != NULL) {
+ /*
+ * if there is no RRSIG of DS,
+ * we don't want to search on the network
+ */
+ result = advanced_rrsearch(&chase_sigdsrdataset,
+ &chase_signame,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_ds, &true);
+ if (result == ISC_R_FAILURE) {
+ printf(";; WARNING : NO RRSIG DS : RRSIG DS"
+ " should come with DS\n");
+ /*
+ * We continue even the DS couldn't be validated,
+ * because the DNSKEY could be a Trusted Key.
+ */
+ chase_dsrdataset = NULL;
+ } else {
+ printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
+ print_rdataset(&chase_signame, chase_sigdsrdataset,
+ mctx);
+ }
+ }
+ return (1);
+}
+
+
+
+void
+sigchase_bu(dns_message_t *msg)
+{
+ isc_result_t result;
+ int ret;
+
+ if (tk_list.nb_tk == 0) {
+ result = get_trusted_key(mctx);
+ if (result != ISC_R_SUCCESS) {
+ printf("No trusted keys present\n");
+ return;
+ }
+ }
+
+
+ ret = getneededrr(msg);
+ if (ret == ISC_R_NOTFOUND)
+ return;
+
+ if (ret == ISC_R_ADDRNOTAVAIL) {
+ /* We have no response */
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ dns_name_t rdata_name;
+ dns_name_t query_name;
+
+
+ dns_name_init(&query_name, NULL);
+ dns_name_init(&rdata_name, NULL);
+ nameFromString(current_lookup->textname, &query_name);
+
+ result = prove_nx(msg, &query_name, current_lookup->rdclass,
+ current_lookup->rdtype, &rdata_name,
+ &rdataset, &sigrdataset);
+ free_name(&query_name, mctx);
+ if (rdataset == NULL || sigrdataset == NULL ||
+ dns_name_countlabels(&rdata_name) == 0) {
+ printf("\n;; Impossible to verify the Non-existence,"
+ " the NSEC RRset can't be validated: "
+ "FAILED\n\n");
+ clean_trustedkey();
+ return;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ printf("\n No Answers and impossible to prove the"
+ " unsecurity : Validation FAILED\n\n");
+ clean_trustedkey();
+ return;
+ }
+ printf(";; An NSEC prove the non-existence of a answers,"
+ " Now we want validate this NSEC\n");
+
+ dup_name(&rdata_name, &chase_name, mctx);
+ free_name(&rdata_name, mctx);
+ chase_rdataset = rdataset;
+ chase_sigrdataset = sigrdataset;
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ chase_siglookedup = ISC_FALSE;
+ chase_keylookedup = ISC_FALSE;
+ chase_dslookedup = ISC_FALSE;
+ chase_sigdslookedup = ISC_FALSE;
+ sigchase(msg);
+ clean_trustedkey();
+ return;
+ }
+
+
+ printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
+
+ result = sigchase_verify_sig(&chase_name, chase_rdataset,
+ chase_keyrdataset,
+ chase_sigrdataset, mctx);
+ if (result != ISC_R_SUCCESS) {
+ free_name(&chase_name, mctx);
+ free_name(&chase_signame, mctx);
+ printf(";; No DNSKEY is valid to check the RRSIG"
+ " of the RRset: FAILED\n");
+ clean_trustedkey();
+ return;
+ }
+ printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
+
+ result = contains_trusted_key(&chase_signame, chase_keyrdataset,
+ chase_sigkeyrdataset, mctx);
+ if (result == ISC_R_SUCCESS) {
+ free_name(&chase_name, mctx);
+ free_name(&chase_signame, mctx);
+ printf("\n;; Ok this DNSKEY is a Trusted Key,"
+ " DNSSEC validation is ok: SUCCESS\n\n");
+ clean_trustedkey();
+ return;
+ }
+
+ printf(";; Now, we are going to validate this DNSKEY by the DS\n");
+
+ if (chase_dsrdataset == NULL) {
+ free_name(&chase_name, mctx);
+ free_name(&chase_signame, mctx);
+ printf(";; the DNSKEY isn't trusted-key and there isn't"
+ " DS to validate the DNSKEY: FAILED\n");
+ clean_trustedkey();
+ return;
+ }
+
+ result = sigchase_verify_ds(&chase_signame, chase_keyrdataset,
+ chase_dsrdataset, mctx);
+ if (result != ISC_R_SUCCESS) {
+ free_name(&chase_signame, mctx);
+ free_name(&chase_name, mctx);
+ printf(";; ERROR no DS validates a DNSKEY in the"
+ " DNSKEY RRset: FAILED\n");
+ clean_trustedkey();
+ return;
+ } else
+ printf(";; OK this DNSKEY (validated by the DS) validates"
+ " the RRset of the DNSKEYs, thus the DNSKEY validates"
+ " the RRset\n");
+ INSIST(chase_sigdsrdataset != NULL);
+
+ dup_name(&chase_signame, &chase_name, mctx);
+ free_name(&chase_signame, mctx);
+ chase_rdataset = chase_dsrdataset;
+ chase_sigrdataset = chase_sigdsrdataset;
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ chase_siglookedup = chase_keylookedup = ISC_FALSE;
+ chase_dslookedup = chase_sigdslookedup = ISC_FALSE;
+
+ printf(";; Now, we want to validate the DS : recursive call\n");
+ sigchase(msg);
+ return;
+}
+#endif
+
+void
+sigchase(dns_message_t *msg) {
+#if DIG_SIGCHASE_TD
+ if (current_lookup->do_topdown) {
+ sigchase_td(msg);
+ return;
+ }
+#endif
+#if DIG_SIGCHASE_BU
+ sigchase_bu(msg);
+ return;
+#endif
+}
+
+
+/*
+ * return 1 if name1 < name2
+ * 0 if name1 == name2
+ * -1 if name1 > name2
+ * and -2 if problem
+ */
+int
+inf_name(dns_name_t *name1, dns_name_t *name2)
+{
+ dns_label_t label1;
+ dns_label_t label2;
+ unsigned int nblabel1;
+ unsigned int nblabel2;
+ int min_lum_label;
+ int i;
+ int ret = -2;
+
+ nblabel1 = dns_name_countlabels(name1);
+ nblabel2 = dns_name_countlabels(name2);
+
+ if (nblabel1 >= nblabel2)
+ min_lum_label = nblabel2;
+ else
+ min_lum_label = nblabel1;
+
+
+ for (i=1 ; i < min_lum_label; i++) {
+ dns_name_getlabel(name1, nblabel1 -1 - i, &label1);
+ dns_name_getlabel(name2, nblabel2 -1 - i, &label2);
+ if ((ret = isc_region_compare(&label1, &label2)) != 0) {
+ if (ret < 0)
+ return (-1);
+ else if (ret > 0)
+ return (1);
+ }
+ }
+ if (nblabel1 == nblabel2)
+ return (0);
+
+ if (nblabel1 < nblabel2)
+ return (-1);
+ else
+ return (1);
+}
+
+/**
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx_domain(dns_message_t *msg,
+ dns_name_t *name,
+ dns_name_t *rdata_name,
+ dns_rdataset_t **rdataset,
+ dns_rdataset_t **sigrdataset)
+{
+ isc_result_t ret = ISC_R_FAILURE;
+ isc_result_t result = ISC_R_NOTFOUND;
+ dns_rdataset_t *nsecset = NULL;
+ dns_rdataset_t *signsecset = NULL ;
+ dns_rdata_t nsec = DNS_RDATA_INIT;
+ dns_name_t *nsecname;
+ dns_rdata_nsec_t nsecstruct;
+
+ if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
+ != ISC_R_SUCCESS) {
+ printf(";; nothing in authority section : impossible to"
+ " validate the non-existence : FAILED\n");
+ return (ISC_R_FAILURE);
+ }
+
+ do {
+ nsecname = NULL;
+ dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
+ nsecset = search_type(nsecname, dns_rdatatype_nsec,
+ dns_rdatatype_any);
+ if (nsecset == NULL)
+ continue;
+
+ printf("There is a NSEC for this zone in the"
+ " AUTHORITY section:\n");
+ print_rdataset(nsecname, nsecset, mctx);
+
+ for (result = dns_rdataset_first(nsecset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(nsecset)) {
+ dns_rdataset_current(nsecset, &nsec);
+
+
+ signsecset
+ = chase_scanname_section(msg, nsecname,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_nsec,
+ DNS_SECTION_AUTHORITY);
+ if (signsecset == NULL) {
+ printf(";; no RRSIG NSEC in authority section:"
+ " impossible to validate the "
+ "non-existence: FAILED\n");
+ return (ISC_R_FAILURE);
+ }
+
+ ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
+ check_result(ret,"dns_rdata_tostruct");
+
+ if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
+ inf_name(name, &nsecstruct.next) == 1) ||
+ (inf_name(name, nsecname) == 1 &&
+ inf_name(&nsecstruct.next, name) == 1)) {
+ dns_rdata_freestruct(&nsecstruct);
+ *rdataset = nsecset;
+ *sigrdataset = signsecset;
+ dup_name(nsecname, rdata_name, mctx);
+
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_rdata_freestruct(&nsecstruct);
+ }
+ } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
+ == ISC_R_SUCCESS);
+
+ *rdataset = NULL;
+ *sigrdataset = NULL;
+ rdata_name = NULL;
+ return (ISC_R_FAILURE);
+}
+
+/**
+ *
+ *
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
+ dns_rdataclass_t class, dns_rdatatype_t type,
+ dns_name_t *rdata_name, dns_rdataset_t **rdataset,
+ dns_rdataset_t **sigrdataset)
+{
+ isc_result_t ret;
+ dns_rdataset_t *signsecset;
+ dns_rdata_t nsec = DNS_RDATA_INIT;
+
+ UNUSED(class);
+
+ ret = dns_rdataset_first(nsecset);
+ check_result(ret,"dns_rdataset_first");
+
+ dns_rdataset_current(nsecset, &nsec);
+
+ ret = dns_nsec_typepresent(&nsec, type);
+ if (ret == ISC_R_SUCCESS)
+ printf("OK the NSEC said that the type doesn't exist \n");
+
+ signsecset = chase_scanname_section(msg, name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_nsec,
+ DNS_SECTION_AUTHORITY);
+ if (signsecset == NULL) {
+ printf("There isn't RRSIG NSEC for the zone \n");
+ return (ISC_R_FAILURE);
+ }
+ dup_name(name, rdata_name, mctx);
+ *rdataset = nsecset;
+ *sigrdataset = signsecset;
+
+ return (ret);
+}
+
+/**
+ *
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
+ dns_rdatatype_t type, dns_name_t *rdata_name,
+ dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
+{
+ isc_result_t ret;
+ dns_rdataset_t *nsecset = NULL;
+
+ printf("We want to prove the non-existance of a type of rdata %d"
+ " or of the zone: \n", type);
+
+ if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
+ != ISC_R_SUCCESS) {
+ printf(";; nothing in authority section : impossible to"
+ " validate the non-existence : FAILED\n");
+ return (ISC_R_FAILURE);
+ }
+
+ nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
+ dns_rdatatype_any,
+ DNS_SECTION_AUTHORITY);
+ if (nsecset != NULL) {
+ printf("We have a NSEC for this zone :OK\n");
+ ret = prove_nx_type(msg, name, nsecset, class,
+ type, rdata_name, rdataset,
+ sigrdataset);
+ if (ret != ISC_R_SUCCESS) {
+ printf("prove_nx: ERROR type exist\n");
+ return (ret);
+ } else {
+ printf("prove_nx: OK type does not exist\n");
+ return (ISC_R_SUCCESS);
+ }
+ } else {
+ printf("there is no NSEC for this zone: validating "
+ "that the zone doesn't exist\n");
+ ret = prove_nx_domain(msg, name, rdata_name,
+ rdataset, sigrdataset);
+ return (ret);
+ }
+ /* Never get here */
+}
+#endif
diff --git a/bin/dig/host.1 b/bin/dig/host.1
new file mode 100644
index 0000000..2ec7d17
--- /dev/null
+++ b/bin/dig/host.1
@@ -0,0 +1,219 @@
+.\" Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2002 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: host.1,v 1.29 2008/04/05 01:09:34 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: host
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "HOST" "1" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+host \- DNS lookup utility
+.SH "SYNOPSIS"
+.HP 5
+\fBhost\fR [\fB\-aCdlnrsTwv\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-N\ \fR\fB\fIndots\fR\fR] [\fB\-R\ \fR\fB\fInumber\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-W\ \fR\fB\fIwait\fR\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-4\fR] [\fB\-6\fR] {name} [server]
+.SH "DESCRIPTION"
+.PP
+\fBhost\fR
+is a simple utility for performing DNS lookups. It is normally used to convert names to IP addresses and vice versa. When no arguments or options are given,
+\fBhost\fR
+prints a short summary of its command line arguments and options.
+.PP
+\fIname\fR
+is the domain name that is to be looked up. It can also be a dotted\-decimal IPv4 address or a colon\-delimited IPv6 address, in which case
+\fBhost\fR
+will by default perform a reverse lookup for that address.
+\fIserver\fR
+is an optional argument which is either the name or IP address of the name server that
+\fBhost\fR
+should query instead of the server or servers listed in
+\fI/etc/resolv.conf\fR.
+.PP
+The
+\fB\-a\fR
+(all) option is equivalent to setting the
+\fB\-v\fR
+option and asking
+\fBhost\fR
+to make a query of type ANY.
+.PP
+When the
+\fB\-C\fR
+option is used,
+\fBhost\fR
+will attempt to display the SOA records for zone
+\fIname\fR
+from all the listed authoritative name servers for that zone. The list of name servers is defined by the NS records that are found for the zone.
+.PP
+The
+\fB\-c\fR
+option instructs to make a DNS query of class
+\fIclass\fR. This can be used to lookup Hesiod or Chaosnet class resource records. The default class is IN (Internet).
+.PP
+Verbose output is generated by
+\fBhost\fR
+when the
+\fB\-d\fR
+or
+\fB\-v\fR
+option is used. The two options are equivalent. They have been provided for backwards compatibility. In previous versions, the
+\fB\-d\fR
+option switched on debugging traces and
+\fB\-v\fR
+enabled verbose output.
+.PP
+List mode is selected by the
+\fB\-l\fR
+option. This makes
+\fBhost\fR
+perform a zone transfer for zone
+\fIname\fR. Transfer the zone printing out the NS, PTR and address records (A/AAAA). If combined with
+\fB\-a\fR
+all records will be printed.
+.PP
+The
+\fB\-i\fR
+option specifies that reverse lookups of IPv6 addresses should use the IP6.INT domain as defined in RFC1886. The default is to use IP6.ARPA.
+.PP
+The
+\fB\-N\fR
+option sets the number of dots that have to be in
+\fIname\fR
+for it to be considered absolute. The default value is that defined using the ndots statement in
+\fI/etc/resolv.conf\fR, or 1 if no ndots statement is present. Names with fewer dots are interpreted as relative names and will be searched for in the domains listed in the
+\fBsearch\fR
+or
+\fBdomain\fR
+directive in
+\fI/etc/resolv.conf\fR.
+.PP
+The number of UDP retries for a lookup can be changed with the
+\fB\-R\fR
+option.
+\fInumber\fR
+indicates how many times
+\fBhost\fR
+will repeat a query that does not get answered. The default number of retries is 1. If
+\fInumber\fR
+is negative or zero, the number of retries will default to 1.
+.PP
+Non\-recursive queries can be made via the
+\fB\-r\fR
+option. Setting this option clears the
+\fBRD\fR
+\(em recursion desired \(em bit in the query which
+\fBhost\fR
+makes. This should mean that the name server receiving the query will not attempt to resolve
+\fIname\fR. The
+\fB\-r\fR
+option enables
+\fBhost\fR
+to mimic the behavior of a name server by making non\-recursive queries and expecting to receive answers to those queries that are usually referrals to other name servers.
+.PP
+By default
+\fBhost\fR
+uses UDP when making queries. The
+\fB\-T\fR
+option makes it use a TCP connection when querying the name server. TCP will be automatically selected for queries that require it, such as zone transfer (AXFR) requests.
+.PP
+The
+\fB\-4\fR
+option forces
+\fBhost\fR
+to only use IPv4 query transport. The
+\fB\-6\fR
+option forces
+\fBhost\fR
+to only use IPv6 query transport.
+.PP
+The
+\fB\-t\fR
+option is used to select the query type.
+\fItype\fR
+can be any recognized query type: CNAME, NS, SOA, SIG, KEY, AXFR, etc. When no query type is specified,
+\fBhost\fR
+automatically selects an appropriate query type. By default it looks for A, AAAA, and MX records, but if the
+\fB\-C\fR
+option was given, queries will be made for SOA records, and if
+\fIname\fR
+is a dotted\-decimal IPv4 address or colon\-delimited IPv6 address,
+\fBhost\fR
+will query for PTR records. If a query type of IXFR is chosen the starting serial number can be specified by appending an equal followed by the starting serial number (e.g. \-t IXFR=12345678).
+.PP
+The time to wait for a reply can be controlled through the
+\fB\-W\fR
+and
+\fB\-w\fR
+options. The
+\fB\-W\fR
+option makes
+\fBhost\fR
+wait for
+\fIwait\fR
+seconds. If
+\fIwait\fR
+is less than one, the wait interval is set to one second. When the
+\fB\-w\fR
+option is used,
+\fBhost\fR
+will effectively wait forever for a reply. The time to wait for a response will be set to the number of seconds given by the hardware's maximum value for an integer quantity.
+.PP
+The
+\fB\-s\fR
+option tells
+\fBhost\fR
+\fInot\fR
+to send the query to the next nameserver if any server responds with a SERVFAIL response, which is the reverse of normal stub resolver behavior.
+.PP
+The
+\fB\-m\fR
+can be used to set the memory usage debugging flags
+\fIrecord\fR,
+\fIusage\fR
+and
+\fItrace\fR.
+.SH "IDN SUPPORT"
+.PP
+If
+\fBhost\fR
+has been built with IDN (internationalized domain name) support, it can accept and display non\-ASCII domain names.
+\fBhost\fR
+appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server. If you'd like to turn off the IDN support for some reason, defines the
+\fBIDN_DISABLE\fR
+environment variable. The IDN support is disabled if the variable is set when
+\fBhost\fR
+runs.
+.SH "FILES"
+.PP
+\fI/etc/resolv.conf\fR
+.SH "SEE ALSO"
+.PP
+\fBdig\fR(1),
+\fBnamed\fR(8).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000\-2002 Internet Software Consortium.
+.br
diff --git a/bin/dig/host.c b/bin/dig/host.c
new file mode 100644
index 0000000..ac29ae6
--- /dev/null
+++ b/bin/dig/host.c
@@ -0,0 +1,862 @@
+/*
+ * Copyright (C) 2004-2007 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: host.c,v 1.116 2007/12/03 00:21:48 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#ifdef WITH_IDN
+#include <idn/result.h>
+#include <idn/log.h>
+#include <idn/resconf.h>
+#include <idn/api.h>
+#endif
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+#include <isc/task.h>
+#include <isc/stdlib.h>
+
+#include <dns/byaddr.h>
+#include <dns/fixedname.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/rdatastruct.h>
+
+#include <dig/dig.h>
+
+static isc_boolean_t short_form = ISC_TRUE, listed_server = ISC_FALSE;
+static isc_boolean_t default_lookups = ISC_TRUE;
+static int seen_error = -1;
+static isc_boolean_t list_addresses = ISC_TRUE;
+static dns_rdatatype_t list_type = dns_rdatatype_a;
+static isc_boolean_t printed_server = ISC_FALSE;
+
+static const char *opcodetext[] = {
+ "QUERY",
+ "IQUERY",
+ "STATUS",
+ "RESERVED3",
+ "NOTIFY",
+ "UPDATE",
+ "RESERVED6",
+ "RESERVED7",
+ "RESERVED8",
+ "RESERVED9",
+ "RESERVED10",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15"
+};
+
+static const char *rcodetext[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15",
+ "BADVERS"
+};
+
+struct rtype {
+ unsigned int type;
+ const char *text;
+};
+
+struct rtype rtypes[] = {
+ { 1, "has address" },
+ { 2, "name server" },
+ { 5, "is an alias for" },
+ { 11, "has well known services" },
+ { 12, "domain name pointer" },
+ { 13, "host information" },
+ { 15, "mail is handled by" },
+ { 16, "descriptive text" },
+ { 19, "x25 address" },
+ { 20, "ISDN address" },
+ { 24, "has signature" },
+ { 25, "has key" },
+ { 28, "has IPv6 address" },
+ { 29, "location" },
+ { 0, NULL }
+};
+
+static void
+show_usage(void) {
+ fputs(
+"Usage: host [-aCdlriTwv] [-c class] [-N ndots] [-t type] [-W time]\n"
+" [-R number] [-m flag] hostname [server]\n"
+" -a is equivalent to -v -t ANY\n"
+" -c specifies query class for non-IN data\n"
+" -C compares SOA records on authoritative nameservers\n"
+" -d is equivalent to -v\n"
+" -l lists all hosts in a domain, using AXFR\n"
+" -i IP6.INT reverse lookups\n"
+" -N changes the number of dots allowed before root lookup is done\n"
+" -r disables recursive processing\n"
+" -R specifies number of retries for UDP packets\n"
+" -s a SERVFAIL response should stop query\n"
+" -t specifies the query type\n"
+" -T enables TCP/IP mode\n"
+" -v enables verbose output\n"
+" -w specifies to wait forever for a reply\n"
+" -W specifies how long to wait for a reply\n"
+" -4 use IPv4 query transport only\n"
+" -6 use IPv6 query transport only\n"
+" -m set memory debugging flag (trace|record|usage)\n", stderr);
+ exit(1);
+}
+
+void
+dighost_shutdown(void) {
+ isc_app_shutdown();
+}
+
+void
+received(int bytes, isc_sockaddr_t *from, dig_query_t *query) {
+ isc_time_t now;
+ int diff;
+
+ if (!short_form) {
+ char fromtext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(from, fromtext, sizeof(fromtext));
+ TIME_NOW(&now);
+ diff = (int) isc_time_microdiff(&now, &query->time_sent);
+ printf("Received %u bytes from %s in %d ms\n",
+ bytes, fromtext, diff/1000);
+ }
+}
+
+void
+trying(char *frm, dig_lookup_t *lookup) {
+ UNUSED(lookup);
+
+ if (!short_form)
+ printf("Trying \"%s\"\n", frm);
+}
+
+static void
+say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata,
+ dig_query_t *query)
+{
+ isc_buffer_t *b = NULL;
+ char namestr[DNS_NAME_FORMATSIZE];
+ isc_region_t r;
+ isc_result_t result;
+ unsigned int bufsize = BUFSIZ;
+
+ dns_name_format(name, namestr, sizeof(namestr));
+ retry:
+ result = isc_buffer_allocate(mctx, &b, bufsize);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_rdata_totext(rdata, NULL, b);
+ if (result == ISC_R_NOSPACE) {
+ isc_buffer_free(&b);
+ bufsize *= 2;
+ goto retry;
+ }
+ check_result(result, "dns_rdata_totext");
+ isc_buffer_usedregion(b, &r);
+ if (query->lookup->identify_previous_line) {
+ printf("Nameserver %s:\n\t",
+ query->servname);
+ }
+ printf("%s %s %.*s", namestr,
+ msg, (int)r.length, (char *)r.base);
+ if (query->lookup->identify) {
+ printf(" on server %s", query->servname);
+ }
+ printf("\n");
+ isc_buffer_free(&b);
+}
+#ifdef DIG_SIGCHASE
+/* Just for compatibility : not use in host program */
+isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target)
+{
+ UNUSED(owner_name);
+ UNUSED(rdataset);
+ UNUSED(target);
+ return(ISC_FALSE);
+}
+#endif
+static isc_result_t
+printsection(dns_message_t *msg, dns_section_t sectionid,
+ const char *section_name, isc_boolean_t headers,
+ dig_query_t *query)
+{
+ dns_name_t *name, *print_name;
+ dns_rdataset_t *rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t target;
+ isc_result_t result, loopresult;
+ isc_region_t r;
+ dns_name_t empty_name;
+ char t[4096];
+ isc_boolean_t first;
+ isc_boolean_t no_rdata;
+
+ if (sectionid == DNS_SECTION_QUESTION)
+ no_rdata = ISC_TRUE;
+ else
+ no_rdata = ISC_FALSE;
+
+ if (headers)
+ printf(";; %s SECTION:\n", section_name);
+
+ dns_name_init(&empty_name, NULL);
+
+ result = dns_message_firstname(msg, sectionid);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, sectionid, &name);
+
+ isc_buffer_init(&target, t, sizeof(t));
+ first = ISC_TRUE;
+ print_name = name;
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (query->lookup->rdtype == dns_rdatatype_axfr &&
+ !((!list_addresses &&
+ (list_type == dns_rdatatype_any ||
+ rdataset->type == list_type)) ||
+ (list_addresses &&
+ (rdataset->type == dns_rdatatype_a ||
+ rdataset->type == dns_rdatatype_aaaa ||
+ rdataset->type == dns_rdatatype_ns ||
+ rdataset->type == dns_rdatatype_ptr))))
+ continue;
+ if (!short_form) {
+ result = dns_rdataset_totext(rdataset,
+ print_name,
+ ISC_FALSE,
+ no_rdata,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#ifdef USEINITALWS
+ if (first) {
+ print_name = &empty_name;
+ first = ISC_FALSE;
+ }
+#else
+ UNUSED(first); /* Shut up compiler. */
+#endif
+ } else {
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ struct rtype *t;
+ const char *rtt;
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char typebuf2[DNS_RDATATYPE_FORMATSIZE
+ + 20];
+ dns_rdataset_current(rdataset, &rdata);
+
+ for (t = rtypes; t->text != NULL; t++) {
+ if (t->type == rdata.type) {
+ rtt = t->text;
+ goto found;
+ }
+ }
+
+ dns_rdatatype_format(rdata.type,
+ typebuf,
+ sizeof(typebuf));
+ snprintf(typebuf2, sizeof(typebuf2),
+ "has %s record", typebuf);
+ rtt = typebuf2;
+ found:
+ say_message(print_name, rtt,
+ &rdata, query);
+ dns_rdata_reset(&rdata);
+ loopresult =
+ dns_rdataset_next(rdataset);
+ }
+ }
+ }
+ if (!short_form) {
+ isc_buffer_usedregion(&target, &r);
+ if (no_rdata)
+ printf(";%.*s", (int)r.length,
+ (char *)r.base);
+ else
+ printf("%.*s", (int)r.length, (char *)r.base);
+ }
+
+ result = dns_message_nextname(msg, sectionid);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner,
+ const char *set_name, isc_boolean_t headers)
+{
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ char t[4096];
+
+ UNUSED(msg);
+ if (headers)
+ printf(";; %s SECTION:\n", set_name);
+
+ 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);
+}
+
+static void
+chase_cnamechain(dns_message_t *msg, dns_name_t *qname) {
+ isc_result_t result;
+ dns_rdataset_t *rdataset;
+ dns_rdata_cname_t cname;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int i = msg->counts[DNS_SECTION_ANSWER];
+
+ while (i-- > 0) {
+ rdataset = NULL;
+ result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
+ dns_rdatatype_cname, 0, NULL,
+ &rdataset);
+ if (result != ISC_R_SUCCESS)
+ return;
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "dns_rdataset_first");
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ dns_name_copy(&cname.cname, qname, NULL);
+ dns_rdata_freestruct(&cname);
+ }
+}
+
+isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
+ isc_boolean_t did_flag = ISC_FALSE;
+ dns_rdataset_t *opt, *tsig = NULL;
+ dns_name_t *tsigname;
+ isc_result_t result = ISC_R_SUCCESS;
+ int force_error;
+
+ UNUSED(headers);
+
+ /*
+ * We get called multiple times.
+ * Preserve any existing error status.
+ */
+ force_error = (seen_error == 1) ? 1 : 0;
+ seen_error = 1;
+ if (listed_server && !printed_server) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+
+ printf("Using domain server:\n");
+ printf("Name: %s\n", query->userarg);
+ isc_sockaddr_format(&query->sockaddr, sockstr,
+ sizeof(sockstr));
+ printf("Address: %s\n", sockstr);
+ printf("Aliases: \n\n");
+ printed_server = ISC_TRUE;
+ }
+
+ if (msg->rcode != 0) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(query->lookup->name, namestr, sizeof(namestr));
+ printf("Host %s not found: %d(%s)\n",
+ (msg->rcode != dns_rcode_nxdomain) ? namestr :
+ query->lookup->textname, msg->rcode,
+ rcodetext[msg->rcode]);
+ return (ISC_R_SUCCESS);
+ }
+
+ if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dig_lookup_t *lookup;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ /* Add AAAA and MX lookups. */
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ dns_name_copy(query->lookup->name, name, NULL);
+ chase_cnamechain(msg, name);
+ dns_name_format(name, namestr, sizeof(namestr));
+ lookup = clone_lookup(query->lookup, ISC_FALSE);
+ if (lookup != NULL) {
+ strncpy(lookup->textname, namestr,
+ sizeof(lookup->textname));
+ lookup->textname[sizeof(lookup->textname)-1] = 0;
+ lookup->rdtype = dns_rdatatype_aaaa;
+ lookup->rdtypeset = ISC_TRUE;
+ lookup->origin = NULL;
+ lookup->retries = tries;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ lookup = clone_lookup(query->lookup, ISC_FALSE);
+ if (lookup != NULL) {
+ strncpy(lookup->textname, namestr,
+ sizeof(lookup->textname));
+ lookup->textname[sizeof(lookup->textname)-1] = 0;
+ lookup->rdtype = dns_rdatatype_mx;
+ lookup->rdtypeset = ISC_TRUE;
+ lookup->origin = NULL;
+ lookup->retries = tries;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ }
+
+ if (!short_form) {
+ printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n",
+ opcodetext[msg->opcode], rcodetext[msg->rcode],
+ msg->id);
+ printf(";; flags: ");
+ if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
+ printf("qr");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
+ printf("%saa", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
+ printf("%stc", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
+ printf("%srd", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
+ printf("%sra", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
+ printf("%sad", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
+ printf("%scd", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ printf("; QUERY: %u, ANSWER: %u, "
+ "AUTHORITY: %u, ADDITIONAL: %u\n",
+ msg->counts[DNS_SECTION_QUESTION],
+ msg->counts[DNS_SECTION_ANSWER],
+ msg->counts[DNS_SECTION_AUTHORITY],
+ msg->counts[DNS_SECTION_ADDITIONAL]);
+ opt = dns_message_getopt(msg);
+ if (opt != NULL)
+ printf(";; EDNS: version: %u, udp=%u\n",
+ (unsigned int)((opt->ttl & 0x00ff0000) >> 16),
+ (unsigned int)opt->rdclass);
+ tsigname = NULL;
+ tsig = dns_message_gettsig(msg, &tsigname);
+ if (tsig != NULL)
+ printf(";; PSEUDOSECTIONS: TSIG\n");
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) &&
+ !short_form) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION",
+ ISC_TRUE, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
+ if (!short_form)
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER",
+ ISC_TF(!short_form), query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) &&
+ !short_form) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY",
+ ISC_TRUE, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) &&
+ !short_form) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_ADDITIONAL,
+ "ADDITIONAL", ISC_TRUE, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if ((tsig != NULL) && !short_form) {
+ printf("\n");
+ result = printrdata(msg, tsig, tsigname,
+ "PSEUDOSECTION TSIG", ISC_TRUE);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (!short_form)
+ printf("\n");
+
+ if (short_form && !default_lookups &&
+ ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+ dns_name_format(query->lookup->name, namestr, sizeof(namestr));
+ dns_rdatatype_format(query->lookup->rdtype, typestr,
+ sizeof(typestr));
+ printf("%s has no %s record\n", namestr, typestr);
+ }
+ seen_error = force_error;
+ return (result);
+}
+
+static const char * optstring = "46ac:dilnm:rst:vwCDN:R:TW:";
+
+static void
+pre_parse_args(int argc, char **argv) {
+ int c;
+
+ while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) {
+ switch (c) {
+ case 'm':
+ memdebugging = ISC_TRUE;
+ if (strcasecmp("trace", isc_commandline_argument) == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+ else if (!strcasecmp("record",
+ isc_commandline_argument) == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ else if (strcasecmp("usage",
+ isc_commandline_argument) == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+ break;
+
+ case '4': break;
+ case '6': break;
+ case 'a': break;
+ case 'c': break;
+ case 'd': break;
+ case 'i': break;
+ case 'l': break;
+ case 'n': break;
+ case 'r': break;
+ case 's': break;
+ case 't': break;
+ case 'v': break;
+ case 'w': break;
+ case 'C': break;
+ case 'D': break;
+ case 'N': break;
+ case 'R': break;
+ case 'T': break;
+ case 'W': break;
+ default:
+ show_usage();
+ }
+ }
+ isc_commandline_reset = ISC_TRUE;
+ isc_commandline_index = 1;
+}
+
+static void
+parse_args(isc_boolean_t is_batchfile, int argc, char **argv) {
+ char hostname[MXNAME];
+ dig_lookup_t *lookup;
+ int c;
+ char store[MXNAME];
+ isc_textregion_t tr;
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ isc_uint32_t serial = 0;
+
+ UNUSED(is_batchfile);
+
+ lookup = make_empty_lookup();
+
+ lookup->servfail_stops = ISC_FALSE;
+ lookup->comments = ISC_FALSE;
+
+ while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) {
+ switch (c) {
+ case 'l':
+ lookup->tcp_mode = ISC_TRUE;
+ lookup->rdtype = dns_rdatatype_axfr;
+ lookup->rdtypeset = ISC_TRUE;
+ fatalexit = 3;
+ break;
+ case 'v':
+ case 'd':
+ short_form = ISC_FALSE;
+ break;
+ case 'r':
+ lookup->recurse = ISC_FALSE;
+ break;
+ case 't':
+ if (strncasecmp(isc_commandline_argument,
+ "ixfr=", 5) == 0) {
+ rdtype = dns_rdatatype_ixfr;
+ /* XXXMPA add error checking */
+ serial = strtoul(isc_commandline_argument + 5,
+ NULL, 10);
+ result = ISC_R_SUCCESS;
+ } else {
+ tr.base = isc_commandline_argument;
+ tr.length = strlen(isc_commandline_argument);
+ result = dns_rdatatype_fromtext(&rdtype,
+ (isc_textregion_t *)&tr);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ fatalexit = 2;
+ fatal("invalid type: %s\n",
+ isc_commandline_argument);
+ }
+ if (!lookup->rdtypeset ||
+ lookup->rdtype != dns_rdatatype_axfr)
+ lookup->rdtype = rdtype;
+ lookup->rdtypeset = ISC_TRUE;
+#ifdef WITH_IDN
+ idnoptions = 0;
+#endif
+ if (rdtype == dns_rdatatype_axfr) {
+ /* -l -t any -v */
+ list_type = dns_rdatatype_any;
+ short_form = ISC_FALSE;
+ lookup->tcp_mode = ISC_TRUE;
+ } else if (rdtype == dns_rdatatype_ixfr) {
+ lookup->ixfr_serial = serial;
+ lookup->tcp_mode = ISC_TRUE;
+ list_type = rdtype;
+#ifdef WITH_IDN
+ } else if (rdtype == dns_rdatatype_a ||
+ rdtype == dns_rdatatype_aaaa ||
+ rdtype == dns_rdatatype_mx) {
+ idnoptions = IDN_ASCCHECK;
+ list_type = rdtype;
+#endif
+ } else
+ list_type = rdtype;
+ list_addresses = ISC_FALSE;
+ default_lookups = ISC_FALSE;
+ break;
+ case 'c':
+ tr.base = isc_commandline_argument;
+ tr.length = strlen(isc_commandline_argument);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+
+ if (result != ISC_R_SUCCESS) {
+ fatalexit = 2;
+ fatal("invalid class: %s\n",
+ isc_commandline_argument);
+ } else {
+ lookup->rdclass = rdclass;
+ lookup->rdclassset = ISC_TRUE;
+ }
+ default_lookups = ISC_FALSE;
+ break;
+ case 'a':
+ if (!lookup->rdtypeset ||
+ lookup->rdtype != dns_rdatatype_axfr)
+ lookup->rdtype = dns_rdatatype_any;
+ list_type = dns_rdatatype_any;
+ list_addresses = ISC_FALSE;
+ lookup->rdtypeset = ISC_TRUE;
+ short_form = ISC_FALSE;
+ default_lookups = ISC_FALSE;
+ break;
+ case 'i':
+ lookup->ip6_int = ISC_TRUE;
+ break;
+ case 'n':
+ /* deprecated */
+ break;
+ case 'm':
+ /* Handled by pre_parse_args(). */
+ break;
+ case 'w':
+ /*
+ * The timer routines are coded such that
+ * timeout==MAXINT doesn't enable the timer
+ */
+ timeout = INT_MAX;
+ break;
+ case 'W':
+ timeout = atoi(isc_commandline_argument);
+ if (timeout < 1)
+ timeout = 1;
+ break;
+ case 'R':
+ tries = atoi(isc_commandline_argument) + 1;
+ if (tries < 2)
+ tries = 2;
+ break;
+ case 'T':
+ lookup->tcp_mode = ISC_TRUE;
+ break;
+ case 'C':
+ debug("showing all SOAs");
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = ISC_TRUE;
+ lookup->rdclass = dns_rdataclass_in;
+ lookup->rdclassset = ISC_TRUE;
+ lookup->ns_search_only = ISC_TRUE;
+ lookup->trace_root = ISC_TRUE;
+ lookup->identify_previous_line = ISC_TRUE;
+ default_lookups = ISC_FALSE;
+ break;
+ case 'N':
+ debug("setting NDOTS to %s",
+ isc_commandline_argument);
+ ndots = atoi(isc_commandline_argument);
+ break;
+ case 'D':
+ debugging = ISC_TRUE;
+ break;
+ case '4':
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = ISC_FALSE;
+ } else
+ fatal("can't find IPv4 networking");
+ break;
+ case '6':
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = ISC_FALSE;
+ } else
+ fatal("can't find IPv6 networking");
+ break;
+ case 's':
+ lookup->servfail_stops = ISC_TRUE;
+ break;
+ }
+ }
+
+ lookup->retries = tries;
+
+ if (isc_commandline_index >= argc)
+ show_usage();
+
+ strncpy(hostname, argv[isc_commandline_index], sizeof(hostname));
+ hostname[sizeof(hostname)-1]=0;
+ if (argc > isc_commandline_index + 1) {
+ set_nameserver(argv[isc_commandline_index+1]);
+ debug("server is %s", argv[isc_commandline_index+1]);
+ listed_server = ISC_TRUE;
+ } else
+ check_ra = ISC_TRUE;
+
+ lookup->pending = ISC_FALSE;
+ if (get_reverse(store, sizeof(store), hostname,
+ lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) {
+ strncpy(lookup->textname, store, sizeof(lookup->textname));
+ lookup->textname[sizeof(lookup->textname)-1] = 0;
+ lookup->rdtype = dns_rdatatype_ptr;
+ lookup->rdtypeset = ISC_TRUE;
+ default_lookups = ISC_FALSE;
+ } else {
+ strncpy(lookup->textname, hostname, sizeof(lookup->textname));
+ lookup->textname[sizeof(lookup->textname)-1]=0;
+ }
+ lookup->new_search = ISC_TRUE;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+
+ usesearch = ISC_TRUE;
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+
+ tries = 2;
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ fatalexit = 1;
+#ifdef WITH_IDN
+ idnoptions = IDN_ASCCHECK;
+#endif
+
+ debug("main()");
+ progname = argv[0];
+ pre_parse_args(argc, argv);
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+ setup_libs();
+ parse_args(ISC_FALSE, argc, argv);
+ setup_system();
+ result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
+ check_result(result, "isc_app_onrun");
+ isc_app_run();
+ cancel_all();
+ destroy_libs();
+ isc_app_finish();
+ return ((seen_error == 0) ? 0 : 1);
+}
diff --git a/bin/dig/host.docbook b/bin/dig/host.docbook
new file mode 100644
index 0000000..bbd8d72
--- /dev/null
+++ b/bin/dig/host.docbook
@@ -0,0 +1,278 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2002 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: host.docbook,v 1.18 2008/04/04 23:47:01 tbox Exp $ -->
+<refentry id="man.host">
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>host</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>host</refname>
+ <refpurpose>DNS lookup utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>host</command>
+ <arg><option>-aCdlnrsTwv</option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-N <replaceable class="parameter">ndots</replaceable></option></arg>
+ <arg><option>-R <replaceable class="parameter">number</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg><option>-W <replaceable class="parameter">wait</replaceable></option></arg>
+ <arg><option>-m <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg><option>-4</option></arg>
+ <arg><option>-6</option></arg>
+ <arg choice="req">name</arg>
+ <arg choice="opt">server</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para><command>host</command>
+ is a simple utility for performing DNS lookups.
+ It is normally used to convert names to IP addresses and vice versa.
+ When no arguments or options are given,
+ <command>host</command>
+ prints a short summary of its command line arguments and options.
+ </para>
+
+ <para><parameter>name</parameter> is the domain name that is to be
+ looked
+ up. It can also be a dotted-decimal IPv4 address or a colon-delimited
+ IPv6 address, in which case <command>host</command> will by
+ default
+ perform a reverse lookup for that address.
+ <parameter>server</parameter> is an optional argument which
+ is either
+ the name or IP address of the name server that <command>host</command>
+ should query instead of the server or servers listed in
+ <filename>/etc/resolv.conf</filename>.
+ </para>
+
+ <para>
+ The <option>-a</option> (all) option is equivalent to setting the
+ <option>-v</option> option and asking <command>host</command> to make
+ a query of type ANY.
+ </para>
+
+ <para>
+ When the <option>-C</option> option is used, <command>host</command>
+ will attempt to display the SOA records for zone
+ <parameter>name</parameter> from all the listed
+ authoritative name
+ servers for that zone. The list of name servers is defined by the NS
+ records that are found for the zone.
+ </para>
+
+ <para>
+ The <option>-c</option> option instructs to make a DNS query of class
+ <parameter>class</parameter>. This can be used to lookup
+ Hesiod or
+ Chaosnet class resource records. The default class is IN (Internet).
+ </para>
+
+ <para>
+ Verbose output is generated by <command>host</command> when
+ the
+ <option>-d</option> or <option>-v</option> option is used. The two
+ options are equivalent. They have been provided for backwards
+ compatibility. In previous versions, the <option>-d</option> option
+ switched on debugging traces and <option>-v</option> enabled verbose
+ output.
+ </para>
+
+ <para>
+ List mode is selected by the <option>-l</option> option. This makes
+ <command>host</command> perform a zone transfer for zone
+ <parameter>name</parameter>. Transfer the zone printing out
+ the NS, PTR
+ and address records (A/AAAA). If combined with <option>-a</option>
+ all records will be printed.
+ </para>
+
+ <para>
+ The <option>-i</option>
+ option specifies that reverse lookups of IPv6 addresses should
+ use the IP6.INT domain as defined in RFC1886.
+ The default is to use IP6.ARPA.
+ </para>
+
+ <para>
+ The <option>-N</option> option sets the number of dots that have to be
+ in <parameter>name</parameter> for it to be considered
+ absolute. The
+ default value is that defined using the ndots statement in
+ <filename>/etc/resolv.conf</filename>, or 1 if no ndots
+ statement is
+ present. Names with fewer dots are interpreted as relative names and
+ will be searched for in the domains listed in the <type>search</type>
+ or <type>domain</type> directive in
+ <filename>/etc/resolv.conf</filename>.
+ </para>
+
+ <para>
+ The number of UDP retries for a lookup can be changed with the
+ <option>-R</option> option. <parameter>number</parameter>
+ indicates
+ how many times <command>host</command> will repeat a query
+ that does
+ not get answered. The default number of retries is 1. If
+ <parameter>number</parameter> is negative or zero, the
+ number of
+ retries will default to 1.
+ </para>
+
+ <para>
+ Non-recursive queries can be made via the <option>-r</option> option.
+ Setting this option clears the <type>RD</type> &mdash; recursion
+ desired &mdash; bit in the query which <command>host</command> makes.
+ This should mean that the name server receiving the query will not
+ attempt to resolve <parameter>name</parameter>. The
+ <option>-r</option> option enables <command>host</command>
+ to mimic
+ the behavior of a name server by making non-recursive queries and
+ expecting to receive answers to those queries that are usually
+ referrals to other name servers.
+ </para>
+
+ <para>
+ By default <command>host</command> uses UDP when making
+ queries. The
+ <option>-T</option> option makes it use a TCP connection when querying
+ the name server. TCP will be automatically selected for queries that
+ require it, such as zone transfer (AXFR) requests.
+ </para>
+
+ <para>
+ The <option>-4</option> option forces <command>host</command> to only
+ use IPv4 query transport. The <option>-6</option> option forces
+ <command>host</command> to only use IPv6 query transport.
+ </para>
+
+ <para>
+ The <option>-t</option> option is used to select the query type.
+ <parameter>type</parameter> can be any recognized query
+ type: CNAME,
+ NS, SOA, SIG, KEY, AXFR, etc. When no query type is specified,
+ <command>host</command> automatically selects an appropriate
+ query
+ type. By default it looks for A, AAAA, and MX records, but if the
+ <option>-C</option> option was given, queries will be made for SOA
+ records, and if <parameter>name</parameter> is a
+ dotted-decimal IPv4
+ address or colon-delimited IPv6 address, <command>host</command> will
+ query for PTR records. If a query type of IXFR is chosen the starting
+ serial number can be specified by appending an equal followed by the
+ starting serial number (e.g. -t IXFR=12345678).
+ </para>
+
+ <para>
+ The time to wait for a reply can be controlled through the
+ <option>-W</option> and <option>-w</option> options. The
+ <option>-W</option> option makes <command>host</command>
+ wait for
+ <parameter>wait</parameter> seconds. If <parameter>wait</parameter>
+ is less than one, the wait interval is set to one second. When the
+ <option>-w</option> option is used, <command>host</command>
+ will
+ effectively wait forever for a reply. The time to wait for a response
+ will be set to the number of seconds given by the hardware's maximum
+ value for an integer quantity.
+ </para>
+
+ <para>
+ The <option>-s</option> option tells <command>host</command>
+ <emphasis>not</emphasis> to send the query to the next nameserver
+ if any server responds with a SERVFAIL response, which is the
+ reverse of normal stub resolver behavior.
+ </para>
+
+ <para>
+ The <option>-m</option> can be used to set the memory usage debugging
+ flags
+ <parameter>record</parameter>, <parameter>usage</parameter> and
+ <parameter>trace</parameter>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>IDN SUPPORT</title>
+ <para>
+ If <command>host</command> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <command>host</command> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, defines
+ the <envar>IDN_DISABLE</envar> environment variable.
+ The IDN support is disabled if the variable is set when
+ <command>host</command> runs.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dig</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dig/host.html b/bin/dig/host.html
new file mode 100644
index 0000000..6d14ef5
--- /dev/null
+++ b/bin/dig/host.html
@@ -0,0 +1,212 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2002 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: host.html,v 1.28 2008/04/05 01:09:34 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>host</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.host"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>host &#8212; DNS lookup utility</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">host</code> [<code class="option">-aCdlnrsTwv</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-N <em class="replaceable"><code>ndots</code></em></code>] [<code class="option">-R <em class="replaceable"><code>number</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-W <em class="replaceable"><code>wait</code></em></code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-4</code>] [<code class="option">-6</code>] {name} [server]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543431"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">host</strong></span>
+ is a simple utility for performing DNS lookups.
+ It is normally used to convert names to IP addresses and vice versa.
+ When no arguments or options are given,
+ <span><strong class="command">host</strong></span>
+ prints a short summary of its command line arguments and options.
+ </p>
+<p><em class="parameter"><code>name</code></em> is the domain name that is to be
+ looked
+ up. It can also be a dotted-decimal IPv4 address or a colon-delimited
+ IPv6 address, in which case <span><strong class="command">host</strong></span> will by
+ default
+ perform a reverse lookup for that address.
+ <em class="parameter"><code>server</code></em> is an optional argument which
+ is either
+ the name or IP address of the name server that <span><strong class="command">host</strong></span>
+ should query instead of the server or servers listed in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+<p>
+ The <code class="option">-a</code> (all) option is equivalent to setting the
+ <code class="option">-v</code> option and asking <span><strong class="command">host</strong></span> to make
+ a query of type ANY.
+ </p>
+<p>
+ When the <code class="option">-C</code> option is used, <span><strong class="command">host</strong></span>
+ will attempt to display the SOA records for zone
+ <em class="parameter"><code>name</code></em> from all the listed
+ authoritative name
+ servers for that zone. The list of name servers is defined by the NS
+ records that are found for the zone.
+ </p>
+<p>
+ The <code class="option">-c</code> option instructs to make a DNS query of class
+ <em class="parameter"><code>class</code></em>. This can be used to lookup
+ Hesiod or
+ Chaosnet class resource records. The default class is IN (Internet).
+ </p>
+<p>
+ Verbose output is generated by <span><strong class="command">host</strong></span> when
+ the
+ <code class="option">-d</code> or <code class="option">-v</code> option is used. The two
+ options are equivalent. They have been provided for backwards
+ compatibility. In previous versions, the <code class="option">-d</code> option
+ switched on debugging traces and <code class="option">-v</code> enabled verbose
+ output.
+ </p>
+<p>
+ List mode is selected by the <code class="option">-l</code> option. This makes
+ <span><strong class="command">host</strong></span> perform a zone transfer for zone
+ <em class="parameter"><code>name</code></em>. Transfer the zone printing out
+ the NS, PTR
+ and address records (A/AAAA). If combined with <code class="option">-a</code>
+ all records will be printed.
+ </p>
+<p>
+ The <code class="option">-i</code>
+ option specifies that reverse lookups of IPv6 addresses should
+ use the IP6.INT domain as defined in RFC1886.
+ The default is to use IP6.ARPA.
+ </p>
+<p>
+ The <code class="option">-N</code> option sets the number of dots that have to be
+ in <em class="parameter"><code>name</code></em> for it to be considered
+ absolute. The
+ default value is that defined using the ndots statement in
+ <code class="filename">/etc/resolv.conf</code>, or 1 if no ndots
+ statement is
+ present. Names with fewer dots are interpreted as relative names and
+ will be searched for in the domains listed in the <span class="type">search</span>
+ or <span class="type">domain</span> directive in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+<p>
+ The number of UDP retries for a lookup can be changed with the
+ <code class="option">-R</code> option. <em class="parameter"><code>number</code></em>
+ indicates
+ how many times <span><strong class="command">host</strong></span> will repeat a query
+ that does
+ not get answered. The default number of retries is 1. If
+ <em class="parameter"><code>number</code></em> is negative or zero, the
+ number of
+ retries will default to 1.
+ </p>
+<p>
+ Non-recursive queries can be made via the <code class="option">-r</code> option.
+ Setting this option clears the <span class="type">RD</span> &#8212; recursion
+ desired &#8212; bit in the query which <span><strong class="command">host</strong></span> makes.
+ This should mean that the name server receiving the query will not
+ attempt to resolve <em class="parameter"><code>name</code></em>. The
+ <code class="option">-r</code> option enables <span><strong class="command">host</strong></span>
+ to mimic
+ the behavior of a name server by making non-recursive queries and
+ expecting to receive answers to those queries that are usually
+ referrals to other name servers.
+ </p>
+<p>
+ By default <span><strong class="command">host</strong></span> uses UDP when making
+ queries. The
+ <code class="option">-T</code> option makes it use a TCP connection when querying
+ the name server. TCP will be automatically selected for queries that
+ require it, such as zone transfer (AXFR) requests.
+ </p>
+<p>
+ The <code class="option">-4</code> option forces <span><strong class="command">host</strong></span> to only
+ use IPv4 query transport. The <code class="option">-6</code> option forces
+ <span><strong class="command">host</strong></span> to only use IPv6 query transport.
+ </p>
+<p>
+ The <code class="option">-t</code> option is used to select the query type.
+ <em class="parameter"><code>type</code></em> can be any recognized query
+ type: CNAME,
+ NS, SOA, SIG, KEY, AXFR, etc. When no query type is specified,
+ <span><strong class="command">host</strong></span> automatically selects an appropriate
+ query
+ type. By default it looks for A, AAAA, and MX records, but if the
+ <code class="option">-C</code> option was given, queries will be made for SOA
+ records, and if <em class="parameter"><code>name</code></em> is a
+ dotted-decimal IPv4
+ address or colon-delimited IPv6 address, <span><strong class="command">host</strong></span> will
+ query for PTR records. If a query type of IXFR is chosen the starting
+ serial number can be specified by appending an equal followed by the
+ starting serial number (e.g. -t IXFR=12345678).
+ </p>
+<p>
+ The time to wait for a reply can be controlled through the
+ <code class="option">-W</code> and <code class="option">-w</code> options. The
+ <code class="option">-W</code> option makes <span><strong class="command">host</strong></span>
+ wait for
+ <em class="parameter"><code>wait</code></em> seconds. If <em class="parameter"><code>wait</code></em>
+ is less than one, the wait interval is set to one second. When the
+ <code class="option">-w</code> option is used, <span><strong class="command">host</strong></span>
+ will
+ effectively wait forever for a reply. The time to wait for a response
+ will be set to the number of seconds given by the hardware's maximum
+ value for an integer quantity.
+ </p>
+<p>
+ The <code class="option">-s</code> option tells <span><strong class="command">host</strong></span>
+ <span class="emphasis"><em>not</em></span> to send the query to the next nameserver
+ if any server responds with a SERVFAIL response, which is the
+ reverse of normal stub resolver behavior.
+ </p>
+<p>
+ The <code class="option">-m</code> can be used to set the memory usage debugging
+ flags
+ <em class="parameter"><code>record</code></em>, <em class="parameter"><code>usage</code></em> and
+ <em class="parameter"><code>trace</code></em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543797"></a><h2>IDN SUPPORT</h2>
+<p>
+ If <span><strong class="command">host</strong></span> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <span><strong class="command">host</strong></span> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, defines
+ the <code class="envar">IDN_DISABLE</code> environment variable.
+ The IDN support is disabled if the variable is set when
+ <span><strong class="command">host</strong></span> runs.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543819"></a><h2>FILES</h2>
+<p><code class="filename">/etc/resolv.conf</code>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543831"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dig</span>(1)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h
new file mode 100644
index 0000000..ccf9bf1
--- /dev/null
+++ b/bin/dig/include/dig/dig.h
@@ -0,0 +1,406 @@
+/*
+ * 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
+ * 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: dig.h,v 1.107 2008/04/03 06:09:04 tbox Exp $ */
+
+#ifndef DIG_H
+#define DIG_H
+
+/*! \file */
+
+#include <dns/rdatalist.h>
+
+#include <dst/dst.h>
+
+#include <isc/boolean.h>
+#include <isc/buffer.h>
+#include <isc/bufferlist.h>
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/list.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+
+#define MXSERV 20
+#define MXNAME (DNS_NAME_MAXTEXT+1)
+#define MXRD 32
+/*% Buffer Size */
+#define BUFSIZE 512
+#define COMMSIZE 0xffff
+#ifndef RESOLV_CONF
+/*% location of resolve.conf */
+#define RESOLV_CONF "/etc/resolv.conf"
+#endif
+/*% output buffer */
+#define OUTPUTBUF 32767
+/*% Max RR Limit */
+#define MAXRRLIMIT 0xffffffff
+#define MAXTIMEOUT 0xffff
+/*% Max number of tries */
+#define MAXTRIES 0xffffffff
+/*% Max number of dots */
+#define MAXNDOTS 0xffff
+/*% Max number of ports */
+#define MAXPORT 0xffff
+/*% Max serial number */
+#define MAXSERIAL 0xffffffff
+
+/*% Default TCP Timeout */
+#define TCP_TIMEOUT 10
+/*% Default UDP Timeout */
+#define UDP_TIMEOUT 5
+
+#define SERVER_TIMEOUT 1
+
+#define LOOKUP_LIMIT 64
+/*%
+ * Lookup_limit is just a limiter, keeping too many lookups from being
+ * created. It's job is mainly to prevent the program from running away
+ * in a tight loop of constant lookups. It's value is arbitrary.
+ */
+
+/*
+ * Defaults for the sigchase suboptions. Consolidated here because
+ * these control the layout of dig_lookup_t (among other things).
+ */
+#ifdef DIG_SIGCHASE
+#ifndef DIG_SIGCHASE_BU
+#define DIG_SIGCHASE_BU 1
+#endif
+#ifndef DIG_SIGCHASE_TD
+#define DIG_SIGCHASE_TD 1
+#endif
+#endif
+
+ISC_LANG_BEGINDECLS
+
+typedef struct dig_lookup dig_lookup_t;
+typedef struct dig_query dig_query_t;
+typedef struct dig_server dig_server_t;
+#ifdef DIG_SIGCHASE
+typedef struct dig_message dig_message_t;
+#endif
+typedef ISC_LIST(dig_server_t) dig_serverlist_t;
+typedef struct dig_searchlist dig_searchlist_t;
+
+/*% The dig_lookup structure */
+struct dig_lookup {
+ isc_boolean_t
+ pending, /*%< Pending a successful answer */
+ waiting_connect,
+ doing_xfr,
+ ns_search_only, /*%< dig +nssearch, host -C */
+ identify, /*%< Append an "on server <foo>" message */
+ identify_previous_line, /*% Prepend a "Nameserver <foo>:"
+ message, with newline and tab */
+ ignore,
+ recurse,
+ aaonly,
+ adflag,
+ cdflag,
+ trace, /*% dig +trace */
+ trace_root, /*% initial query for either +trace or +nssearch */
+ tcp_mode,
+ ip6_int,
+ comments,
+ stats,
+ section_question,
+ section_answer,
+ section_authority,
+ section_additional,
+ servfail_stops,
+ new_search,
+ need_search,
+ done_as_is,
+ besteffort,
+ dnssec,
+ nsid; /*% Name Server ID (RFC 5001) */
+#ifdef DIG_SIGCHASE
+isc_boolean_t sigchase;
+#if DIG_SIGCHASE_TD
+ isc_boolean_t do_topdown,
+ trace_root_sigchase,
+ rdtype_sigchaseset,
+ rdclass_sigchaseset;
+ /* Name we are going to validate RRset */
+ char textnamesigchase[MXNAME];
+#endif
+#endif
+
+ char textname[MXNAME]; /*% Name we're going to be looking up */
+ char cmdline[MXNAME];
+ dns_rdatatype_t rdtype;
+ dns_rdatatype_t qrdtype;
+#if DIG_SIGCHASE_TD
+ dns_rdatatype_t rdtype_sigchase;
+ dns_rdatatype_t qrdtype_sigchase;
+ dns_rdataclass_t rdclass_sigchase;
+#endif
+ dns_rdataclass_t rdclass;
+ isc_boolean_t rdtypeset;
+ isc_boolean_t rdclassset;
+ char namespace[BUFSIZE];
+ char onamespace[BUFSIZE];
+ isc_buffer_t namebuf;
+ isc_buffer_t onamebuf;
+ isc_buffer_t renderbuf;
+ char *sendspace;
+ dns_name_t *name;
+ isc_timer_t *timer;
+ isc_interval_t interval;
+ dns_message_t *sendmsg;
+ dns_name_t *oname;
+ ISC_LINK(dig_lookup_t) link;
+ ISC_LIST(dig_query_t) q;
+ dig_query_t *current_query;
+ dig_serverlist_t my_server_list;
+ dig_searchlist_t *origin;
+ dig_query_t *xfr_q;
+ isc_uint32_t retries;
+ int nsfound;
+ isc_uint16_t udpsize;
+ isc_int16_t edns;
+ isc_uint32_t ixfr_serial;
+ isc_buffer_t rdatabuf;
+ char rdatastore[MXNAME];
+ dst_context_t *tsigctx;
+ isc_buffer_t *querysig;
+ isc_uint32_t msgcounter;
+ dns_fixedname_t fdomain;
+};
+
+/*% The dig_query structure */
+struct dig_query {
+ dig_lookup_t *lookup;
+ isc_boolean_t waiting_connect,
+ pending_free,
+ waiting_senddone,
+ first_pass,
+ first_soa_rcvd,
+ second_rr_rcvd,
+ first_repeat_rcvd,
+ recv_made,
+ warn_id;
+ isc_uint32_t first_rr_serial;
+ isc_uint32_t second_rr_serial;
+ isc_uint32_t msg_count;
+ isc_uint32_t rr_count;
+ char *servname;
+ char *userarg;
+ isc_bufferlist_t sendlist,
+ recvlist,
+ lengthlist;
+ isc_buffer_t recvbuf,
+ lengthbuf,
+ slbuf;
+ char *recvspace,
+ lengthspace[4],
+ slspace[4];
+ isc_socket_t *sock;
+ ISC_LINK(dig_query_t) link;
+ isc_sockaddr_t sockaddr;
+ isc_time_t time_sent;
+ isc_uint64_t byte_count;
+ isc_buffer_t sendbuf;
+};
+
+struct dig_server {
+ char servername[MXNAME];
+ char userarg[MXNAME];
+ ISC_LINK(dig_server_t) link;
+};
+
+struct dig_searchlist {
+ char origin[MXNAME];
+ ISC_LINK(dig_searchlist_t) link;
+};
+#ifdef DIG_SIGCHASE
+struct dig_message {
+ dns_message_t *msg;
+ ISC_LINK(dig_message_t) link;
+};
+#endif
+
+typedef ISC_LIST(dig_searchlist_t) dig_searchlistlist_t;
+typedef ISC_LIST(dig_lookup_t) dig_lookuplist_t;
+
+/*
+ * Externals from dighost.c
+ */
+
+extern dig_lookuplist_t lookup_list;
+extern dig_serverlist_t server_list;
+extern dig_searchlistlist_t search_list;
+extern unsigned int extrabytes;
+
+extern isc_boolean_t check_ra, have_ipv4, have_ipv6, specified_source,
+ usesearch, showsearch, qr;
+extern in_port_t port;
+extern unsigned int timeout;
+extern isc_mem_t *mctx;
+extern dns_messageid_t id;
+extern int sendcount;
+extern int ndots;
+extern int lookup_counter;
+extern int exitcode;
+extern isc_sockaddr_t bind_address;
+extern char keynametext[MXNAME];
+extern char keyfile[MXNAME];
+extern char keysecret[MXNAME];
+extern dns_name_t *hmacname;
+extern unsigned int digestbits;
+#ifdef DIG_SIGCHASE
+extern char trustedkey[MXNAME];
+#endif
+extern dns_tsigkey_t *key;
+extern isc_boolean_t validated;
+extern isc_taskmgr_t *taskmgr;
+extern isc_task_t *global_task;
+extern isc_boolean_t free_now;
+extern isc_boolean_t debugging, memdebugging;
+
+extern char *progname;
+extern int tries;
+extern int fatalexit;
+#ifdef WITH_IDN
+extern int idnoptions;
+#endif
+
+/*
+ * Routines in dighost.c.
+ */
+void
+get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr);
+
+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);
+
+void
+debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+check_result(isc_result_t result, const char *msg);
+
+void
+setup_lookup(dig_lookup_t *lookup);
+
+void
+destroy_lookup(dig_lookup_t *lookup);
+
+void
+do_lookup(dig_lookup_t *lookup);
+
+void
+start_lookup(void);
+
+void
+onrun_callback(isc_task_t *task, isc_event_t *event);
+
+int
+dhmain(int argc, char **argv);
+
+void
+setup_libs(void);
+
+void
+setup_system(void);
+
+dig_lookup_t *
+requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers);
+
+dig_lookup_t *
+make_empty_lookup(void);
+
+dig_lookup_t *
+clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers);
+
+dig_server_t *
+make_server(const char *servname, const char *userarg);
+
+void
+flush_server_list(void);
+
+void
+set_nameserver(char *opt);
+
+void
+clone_server_list(dig_serverlist_t src,
+ dig_serverlist_t *dest);
+
+void
+cancel_all(void);
+
+void
+destroy_libs(void);
+
+void
+set_search_domain(char *domain);
+
+#ifdef DIG_SIGCHASE
+void
+clean_trustedkey(void);
+#endif
+
+/*
+ * Routines to be defined in dig.c, host.c, and nslookup.c.
+ */
+#ifdef DIG_SIGCHASE
+isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target);
+#endif
+
+isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers);
+/*%<
+ * Print the final result of the lookup.
+ */
+
+void
+received(int bytes, isc_sockaddr_t *from, dig_query_t *query);
+/*%<
+ * Print a message about where and when the response
+ * was received from, like the final comment in the
+ * output of "dig".
+ */
+
+void
+trying(char *frm, dig_lookup_t *lookup);
+
+void
+dighost_shutdown(void);
+
+char *
+next_token(char **stringp, const char *delim);
+
+#ifdef DIG_SIGCHASE
+/* Chasing functions */
+dns_rdataset_t *
+chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers);
+void
+chase_sig(dns_message_t *msg);
+#endif
+
+ISC_LANG_ENDDECLS
+
+#endif
diff --git a/bin/dig/nslookup.1 b/bin/dig/nslookup.1
new file mode 100644
index 0000000..2d19534
--- /dev/null
+++ b/bin/dig/nslookup.1
@@ -0,0 +1,252 @@
+.\" Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: nslookup.1,v 1.14 2007/05/16 06:12:01 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: nslookup
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "NSLOOKUP" "1" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+nslookup \- query Internet name servers interactively
+.SH "SYNOPSIS"
+.HP 9
+\fBnslookup\fR [\fB\-option\fR] [name\ |\ \-] [server]
+.SH "DESCRIPTION"
+.PP
+\fBNslookup\fR
+is a program to query Internet domain name servers.
+\fBNslookup\fR
+has two modes: interactive and non\-interactive. Interactive mode allows the user to query name servers for information about various hosts and domains or to print a list of hosts in a domain. Non\-interactive mode is used to print just the name and requested information for a host or domain.
+.SH "ARGUMENTS"
+.PP
+Interactive mode is entered in the following cases:
+.TP 4
+1.
+when no arguments are given (the default name server will be used)
+.TP 4
+2.
+when the first argument is a hyphen (\-) and the second argument is the host name or Internet address of a name server.
+.sp
+.RE
+.PP
+Non\-interactive mode is used when the name or Internet address of the host to be looked up is given as the first argument. The optional second argument specifies the host name or address of a name server.
+.PP
+Options can also be specified on the command line if they precede the arguments and are prefixed with a hyphen. For example, to change the default query type to host information, and the initial timeout to 10 seconds, type:
+.sp .RS 4 .nf nslookup \-query=hinfo \-timeout=10 .fi .RE
+.SH "INTERACTIVE COMMANDS"
+.PP
+\fBhost\fR [server]
+.RS 4
+Look up information for host using the current default server or using server, if specified. If host is an Internet address and the query type is A or PTR, the name of the host is returned. If host is a name and does not have a trailing period, the search list is used to qualify the name.
+.sp
+To look up a host not in the current domain, append a period to the name.
+.RE
+.PP
+\fBserver\fR \fIdomain\fR
+.RS 4
+.RE
+.PP
+\fBlserver\fR \fIdomain\fR
+.RS 4
+Change the default server to
+\fIdomain\fR;
+\fBlserver\fR
+uses the initial server to look up information about
+\fIdomain\fR, while
+\fBserver\fR
+uses the current default server. If an authoritative answer can't be found, the names of servers that might have the answer are returned.
+.RE
+.PP
+\fBroot\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBfinger\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBls\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBview\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBhelp\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fB?\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBexit\fR
+.RS 4
+Exits the program.
+.RE
+.PP
+\fBset\fR \fIkeyword\fR\fI[=value]\fR
+.RS 4
+This command is used to change state information that affects the lookups. Valid keywords are:
+.RS 4
+.PP
+\fBall\fR
+.RS 4
+Prints the current values of the frequently used options to
+\fBset\fR. Information about the current default server and host is also printed.
+.RE
+.PP
+\fBclass=\fR\fIvalue\fR
+.RS 4
+Change the query class to one of:
+.RS 4
+.PP
+\fBIN\fR
+.RS 4
+the Internet class
+.RE
+.PP
+\fBCH\fR
+.RS 4
+the Chaos class
+.RE
+.PP
+\fBHS\fR
+.RS 4
+the Hesiod class
+.RE
+.PP
+\fBANY\fR
+.RS 4
+wildcard
+.RE
+.RE
+.IP "" 4
+The class specifies the protocol group of the information.
+.sp
+(Default = IN; abbreviation = cl)
+.RE
+.PP
+\fB \fR\fB\fI[no]\fR\fR\fBdebug\fR
+.RS 4
+Turn on or off the display of the full response packet and any intermediate response packets when searching.
+.sp
+(Default = nodebug; abbreviation =
+[no]deb)
+.RE
+.PP
+\fB \fR\fB\fI[no]\fR\fR\fBd2\fR
+.RS 4
+Turn debugging mode on or off. This displays more about what nslookup is doing.
+.sp
+(Default = nod2)
+.RE
+.PP
+\fBdomain=\fR\fIname\fR
+.RS 4
+Sets the search list to
+\fIname\fR.
+.RE
+.PP
+\fB \fR\fB\fI[no]\fR\fR\fBsearch\fR
+.RS 4
+If the lookup request contains at least one period but doesn't end with a trailing period, append the domain names in the domain search list to the request until an answer is received.
+.sp
+(Default = search)
+.RE
+.PP
+\fBport=\fR\fIvalue\fR
+.RS 4
+Change the default TCP/UDP name server port to
+\fIvalue\fR.
+.sp
+(Default = 53; abbreviation = po)
+.RE
+.PP
+\fBquerytype=\fR\fIvalue\fR
+.RS 4
+.RE
+.PP
+\fBtype=\fR\fIvalue\fR
+.RS 4
+Change the type of the information query.
+.sp
+(Default = A; abbreviations = q, ty)
+.RE
+.PP
+\fB \fR\fB\fI[no]\fR\fR\fBrecurse\fR
+.RS 4
+Tell the name server to query other servers if it does not have the information.
+.sp
+(Default = recurse; abbreviation = [no]rec)
+.RE
+.PP
+\fBretry=\fR\fInumber\fR
+.RS 4
+Set the number of retries to number.
+.RE
+.PP
+\fBtimeout=\fR\fInumber\fR
+.RS 4
+Change the initial timeout interval for waiting for a reply to number seconds.
+.RE
+.PP
+\fB \fR\fB\fI[no]\fR\fR\fBvc\fR
+.RS 4
+Always use a virtual circuit when sending requests to the server.
+.sp
+(Default = novc)
+.RE
+.PP
+\fB \fR\fB\fI[no]\fR\fR\fBfail\fR
+.RS 4
+Try the next nameserver if a nameserver responds with SERVFAIL or a referral (nofail) or terminate query (fail) on such a response.
+.sp
+(Default = nofail)
+.RE
+.RE
+.IP "" 4
+.RE
+.SH "FILES"
+.PP
+\fI/etc/resolv.conf\fR
+.SH "SEE ALSO"
+.PP
+\fBdig\fR(1),
+\fBhost\fR(1),
+\fBnamed\fR(8).
+.SH "AUTHOR"
+.PP
+Andrew Cherenson
+.SH "COPYRIGHT"
+Copyright \(co 2004\-2007 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c
new file mode 100644
index 0000000..31be018
--- /dev/null
+++ b/bin/dig/nslookup.c
@@ -0,0 +1,891 @@
+/*
+ * Copyright (C) 2004-2007 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: nslookup.c,v 1.117 2007/06/18 23:47:17 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/event.h>
+#include <isc/parseint.h>
+#include <isc/string.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+#include <isc/task.h>
+#include <isc/netaddr.h>
+
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/fixedname.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/byaddr.h>
+
+#include <dig/dig.h>
+
+static isc_boolean_t short_form = ISC_TRUE,
+ tcpmode = ISC_FALSE,
+ identify = ISC_FALSE, stats = ISC_TRUE,
+ comments = ISC_TRUE, section_question = ISC_TRUE,
+ section_answer = ISC_TRUE, section_authority = ISC_TRUE,
+ section_additional = ISC_TRUE, recurse = ISC_TRUE,
+ aaonly = ISC_FALSE, nofail = ISC_TRUE;
+
+static isc_boolean_t in_use = ISC_FALSE;
+static char defclass[MXRD] = "IN";
+static char deftype[MXRD] = "A";
+static isc_event_t *global_event = NULL;
+
+static char domainopt[DNS_NAME_MAXTEXT];
+
+static const char *rcodetext[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15",
+ "BADVERS"
+};
+
+static const char *rtypetext[] = {
+ "rtype_0 = ", /* 0 */
+ "internet address = ", /* 1 */
+ "nameserver = ", /* 2 */
+ "md = ", /* 3 */
+ "mf = ", /* 4 */
+ "canonical name = ", /* 5 */
+ "soa = ", /* 6 */
+ "mb = ", /* 7 */
+ "mg = ", /* 8 */
+ "mr = ", /* 9 */
+ "rtype_10 = ", /* 10 */
+ "protocol = ", /* 11 */
+ "name = ", /* 12 */
+ "hinfo = ", /* 13 */
+ "minfo = ", /* 14 */
+ "mail exchanger = ", /* 15 */
+ "text = ", /* 16 */
+ "rp = ", /* 17 */
+ "afsdb = ", /* 18 */
+ "x25 address = ", /* 19 */
+ "isdn address = ", /* 20 */
+ "rt = ", /* 21 */
+ "nsap = ", /* 22 */
+ "nsap_ptr = ", /* 23 */
+ "signature = ", /* 24 */
+ "key = ", /* 25 */
+ "px = ", /* 26 */
+ "gpos = ", /* 27 */
+ "has AAAA address ", /* 28 */
+ "loc = ", /* 29 */
+ "next = ", /* 30 */
+ "rtype_31 = ", /* 31 */
+ "rtype_32 = ", /* 32 */
+ "service = ", /* 33 */
+ "rtype_34 = ", /* 34 */
+ "naptr = ", /* 35 */
+ "kx = ", /* 36 */
+ "cert = ", /* 37 */
+ "v6 address = ", /* 38 */
+ "dname = ", /* 39 */
+ "rtype_40 = ", /* 40 */
+ "optional = " /* 41 */
+};
+
+#define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
+
+static void flush_lookup_list(void);
+static void getinput(isc_task_t *task, isc_event_t *event);
+
+void
+dighost_shutdown(void) {
+ isc_event_t *event = global_event;
+
+ flush_lookup_list();
+ debug("dighost_shutdown()");
+
+ if (!in_use) {
+ isc_app_shutdown();
+ return;
+ }
+
+ isc_task_send(global_task, &event);
+}
+
+static void
+printsoa(dns_rdata_t *rdata) {
+ dns_rdata_soa_t soa;
+ isc_result_t result;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ result = dns_rdata_tostruct(rdata, &soa, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ dns_name_format(&soa.origin, namebuf, sizeof(namebuf));
+ printf("\torigin = %s\n", namebuf);
+ dns_name_format(&soa.contact, namebuf, sizeof(namebuf));
+ printf("\tmail addr = %s\n", namebuf);
+ printf("\tserial = %u\n", soa.serial);
+ printf("\trefresh = %u\n", soa.refresh);
+ printf("\tretry = %u\n", soa.retry);
+ printf("\texpire = %u\n", soa.expire);
+ printf("\tminimum = %u\n", soa.minimum);
+ dns_rdata_freestruct(&soa);
+}
+
+static void
+printa(dns_rdata_t *rdata) {
+ isc_result_t result;
+ char text[sizeof("255.255.255.255")];
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, text, sizeof(text));
+ result = dns_rdata_totext(rdata, NULL, &b);
+ check_result(result, "dns_rdata_totext");
+ printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
+ (char *)isc_buffer_base(&b));
+}
+#ifdef DIG_SIGCHASE
+/* Just for compatibility : not use in host program */
+isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target)
+{
+ UNUSED(owner_name);
+ UNUSED(rdataset);
+ UNUSED(target);
+ return(ISC_FALSE);
+}
+#endif
+static void
+printrdata(dns_rdata_t *rdata) {
+ isc_result_t result;
+ isc_buffer_t *b = NULL;
+ unsigned int size = 1024;
+ isc_boolean_t done = ISC_FALSE;
+
+ if (rdata->type < N_KNOWN_RRTYPES)
+ printf("%s", rtypetext[rdata->type]);
+ else
+ printf("rdata_%d = ", rdata->type);
+
+ while (!done) {
+ result = isc_buffer_allocate(mctx, &b, size);
+ if (result != ISC_R_SUCCESS)
+ check_result(result, "isc_buffer_allocate");
+ result = dns_rdata_totext(rdata, NULL, b);
+ if (result == ISC_R_SUCCESS) {
+ printf("%.*s\n", (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+ done = ISC_TRUE;
+ } else if (result != ISC_R_NOSPACE)
+ check_result(result, "dns_rdata_totext");
+ isc_buffer_free(&b);
+ size *= 2;
+ }
+}
+
+static isc_result_t
+printsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
+ dns_section_t section) {
+ isc_result_t result, loopresult;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ UNUSED(query);
+ UNUSED(headers);
+
+ debug("printsection()");
+
+ result = dns_message_firstname(msg, section);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, section,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ switch (rdata.type) {
+ case dns_rdatatype_a:
+ if (section != DNS_SECTION_ANSWER)
+ goto def_short_section;
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("Name:\t%s\n", namebuf);
+ printa(&rdata);
+ break;
+ case dns_rdatatype_soa:
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("%s\n", namebuf);
+ printsoa(&rdata);
+ break;
+ default:
+ def_short_section:
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("%s\t", namebuf);
+ printrdata(&rdata);
+ break;
+ }
+ dns_rdata_reset(&rdata);
+ loopresult = dns_rdataset_next(rdataset);
+ }
+ }
+ result = dns_message_nextname(msg, section);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+detailsection(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers,
+ dns_section_t section) {
+ isc_result_t result, loopresult;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ UNUSED(query);
+
+ debug("detailsection()");
+
+ if (headers) {
+ switch (section) {
+ case DNS_SECTION_QUESTION:
+ puts(" QUESTIONS:");
+ break;
+ case DNS_SECTION_ANSWER:
+ puts(" ANSWERS:");
+ break;
+ case DNS_SECTION_AUTHORITY:
+ puts(" AUTHORITY RECORDS:");
+ break;
+ case DNS_SECTION_ADDITIONAL:
+ puts(" ADDITIONAL RECORDS:");
+ break;
+ }
+ }
+
+ result = dns_message_firstname(msg, section);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, section,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (section == DNS_SECTION_QUESTION) {
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("\t%s, ", namebuf);
+ dns_rdatatype_format(rdataset->type,
+ namebuf,
+ sizeof(namebuf));
+ printf("type = %s, ", namebuf);
+ dns_rdataclass_format(rdataset->rdclass,
+ namebuf,
+ sizeof(namebuf));
+ printf("class = %s\n", namebuf);
+ }
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf(" -> %s\n", namebuf);
+
+ switch (rdata.type) {
+ case dns_rdatatype_soa:
+ printsoa(&rdata);
+ break;
+ default:
+ printf("\t");
+ printrdata(&rdata);
+ }
+ dns_rdata_reset(&rdata);
+ loopresult = dns_rdataset_next(rdataset);
+ }
+ }
+ result = dns_message_nextname(msg, section);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+void
+received(int bytes, isc_sockaddr_t *from, dig_query_t *query)
+{
+ UNUSED(bytes);
+ UNUSED(from);
+ UNUSED(query);
+}
+
+void
+trying(char *frm, dig_lookup_t *lookup) {
+ UNUSED(frm);
+ UNUSED(lookup);
+
+}
+
+isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
+ char servtext[ISC_SOCKADDR_FORMATSIZE];
+
+ debug("printmessage()");
+
+ isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
+ printf("Server:\t\t%s\n", query->userarg);
+ printf("Address:\t%s\n", servtext);
+
+ puts("");
+
+ if (!short_form) {
+ isc_boolean_t headers = ISC_TRUE;
+ puts("------------");
+ /* detailheader(query, msg);*/
+ detailsection(query, msg, headers, DNS_SECTION_QUESTION);
+ detailsection(query, msg, headers, DNS_SECTION_ANSWER);
+ detailsection(query, msg, headers, DNS_SECTION_AUTHORITY);
+ detailsection(query, msg, headers, DNS_SECTION_ADDITIONAL);
+ puts("------------");
+ }
+
+ if (msg->rcode != 0) {
+ char nametext[DNS_NAME_FORMATSIZE];
+ dns_name_format(query->lookup->name,
+ nametext, sizeof(nametext));
+ printf("** server can't find %s: %s\n",
+ (msg->rcode != dns_rcode_nxdomain) ? nametext :
+ query->lookup->textname, rcodetext[msg->rcode]);
+ debug("returning with rcode == 0");
+ return (ISC_R_SUCCESS);
+ }
+
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
+ puts("Non-authoritative answer:");
+ if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
+ printsection(query, msg, headers, DNS_SECTION_ANSWER);
+ else
+ printf("*** Can't find %s: No answer\n",
+ query->lookup->textname);
+
+ if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
+ (query->lookup->rdtype != dns_rdatatype_a)) {
+ puts("\nAuthoritative answers can be found from:");
+ printsection(query, msg, headers,
+ DNS_SECTION_AUTHORITY);
+ printsection(query, msg, headers,
+ DNS_SECTION_ADDITIONAL);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static void
+show_settings(isc_boolean_t full, isc_boolean_t serv_only) {
+ dig_server_t *srv;
+ isc_sockaddr_t sockaddr;
+ dig_searchlist_t *listent;
+
+ srv = ISC_LIST_HEAD(server_list);
+
+ while (srv != NULL) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+
+ get_address(srv->servername, port, &sockaddr);
+ isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr));
+ printf("Default server: %s\nAddress: %s\n",
+ srv->userarg, sockstr);
+ if (!full)
+ return;
+ srv = ISC_LIST_NEXT(srv, link);
+ }
+ if (serv_only)
+ return;
+ printf("\nSet options:\n");
+ printf(" %s\t\t\t%s\t\t%s\n",
+ tcpmode ? "vc" : "novc",
+ short_form ? "nodebug" : "debug",
+ debugging ? "d2" : "nod2");
+ printf(" %s\t\t%s\n",
+ usesearch ? "search" : "nosearch",
+ recurse ? "recurse" : "norecurse");
+ printf(" timeout = %d\t\tretry = %d\tport = %d\n",
+ timeout, tries, port);
+ printf(" querytype = %-8s\tclass = %s\n", deftype, defclass);
+ printf(" srchlist = ");
+ for (listent = ISC_LIST_HEAD(search_list);
+ listent != NULL;
+ listent = ISC_LIST_NEXT(listent, link)) {
+ printf("%s", listent->origin);
+ if (ISC_LIST_NEXT(listent, link) != NULL)
+ printf("/");
+ }
+ printf("\n");
+}
+
+static isc_boolean_t
+testtype(char *typetext) {
+ isc_result_t result;
+ isc_textregion_t tr;
+ dns_rdatatype_t rdtype;
+
+ tr.base = typetext;
+ tr.length = strlen(typetext);
+ result = dns_rdatatype_fromtext(&rdtype, &tr);
+ if (result == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+ else {
+ printf("unknown query type: %s\n", typetext);
+ return (ISC_FALSE);
+ }
+}
+
+static isc_boolean_t
+testclass(char *typetext) {
+ isc_result_t result;
+ isc_textregion_t tr;
+ dns_rdataclass_t rdclass;
+
+ tr.base = typetext;
+ tr.length = strlen(typetext);
+ result = dns_rdataclass_fromtext(&rdclass, &tr);
+ if (result == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+ else {
+ printf("unknown query class: %s\n", typetext);
+ return (ISC_FALSE);
+ }
+}
+
+static void
+safecpy(char *dest, char *src, int size) {
+ strncpy(dest, src, 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;
+ isc_result_t result = parse_uint(&n, value, 65535, "port");
+ if (result == ISC_R_SUCCESS)
+ port = (isc_uint16_t) n;
+}
+
+static void
+set_timeout(const char *value) {
+ isc_uint32_t n;
+ isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout");
+ if (result == ISC_R_SUCCESS)
+ timeout = n;
+}
+
+static void
+set_tries(const char *value) {
+ isc_uint32_t n;
+ isc_result_t result = parse_uint(&n, value, INT_MAX, "tries");
+ if (result == ISC_R_SUCCESS)
+ tries = n;
+}
+
+static void
+setoption(char *opt) {
+ if (strncasecmp(opt, "all", 4) == 0) {
+ show_settings(ISC_TRUE, ISC_FALSE);
+ } else if (strncasecmp(opt, "class=", 6) == 0) {
+ if (testclass(&opt[6]))
+ safecpy(defclass, &opt[6], sizeof(defclass));
+ } else if (strncasecmp(opt, "cl=", 3) == 0) {
+ if (testclass(&opt[3]))
+ safecpy(defclass, &opt[3], sizeof(defclass));
+ } else if (strncasecmp(opt, "type=", 5) == 0) {
+ if (testtype(&opt[5]))
+ safecpy(deftype, &opt[5], sizeof(deftype));
+ } else if (strncasecmp(opt, "ty=", 3) == 0) {
+ if (testtype(&opt[3]))
+ safecpy(deftype, &opt[3], sizeof(deftype));
+ } else if (strncasecmp(opt, "querytype=", 10) == 0) {
+ if (testtype(&opt[10]))
+ safecpy(deftype, &opt[10], sizeof(deftype));
+ } else if (strncasecmp(opt, "query=", 6) == 0) {
+ if (testtype(&opt[6]))
+ safecpy(deftype, &opt[6], sizeof(deftype));
+ } else if (strncasecmp(opt, "qu=", 3) == 0) {
+ if (testtype(&opt[3]))
+ safecpy(deftype, &opt[3], sizeof(deftype));
+ } else if (strncasecmp(opt, "q=", 2) == 0) {
+ if (testtype(&opt[2]))
+ safecpy(deftype, &opt[2], sizeof(deftype));
+ } else if (strncasecmp(opt, "domain=", 7) == 0) {
+ safecpy(domainopt, &opt[7], sizeof(domainopt));
+ set_search_domain(domainopt);
+ usesearch = ISC_TRUE;
+ } else if (strncasecmp(opt, "do=", 3) == 0) {
+ safecpy(domainopt, &opt[3], sizeof(domainopt));
+ set_search_domain(domainopt);
+ usesearch = ISC_TRUE;
+ } else if (strncasecmp(opt, "port=", 5) == 0) {
+ set_port(&opt[5]);
+ } else if (strncasecmp(opt, "po=", 3) == 0) {
+ set_port(&opt[3]);
+ } else if (strncasecmp(opt, "timeout=", 8) == 0) {
+ set_timeout(&opt[8]);
+ } else if (strncasecmp(opt, "t=", 2) == 0) {
+ set_timeout(&opt[2]);
+ } else if (strncasecmp(opt, "rec", 3) == 0) {
+ recurse = ISC_TRUE;
+ } else if (strncasecmp(opt, "norec", 5) == 0) {
+ recurse = ISC_FALSE;
+ } else if (strncasecmp(opt, "retry=", 6) == 0) {
+ set_tries(&opt[6]);
+ } else if (strncasecmp(opt, "ret=", 4) == 0) {
+ set_tries(&opt[4]);
+ } else if (strncasecmp(opt, "def", 3) == 0) {
+ usesearch = ISC_TRUE;
+ } else if (strncasecmp(opt, "nodef", 5) == 0) {
+ usesearch = ISC_FALSE;
+ } else if (strncasecmp(opt, "vc", 3) == 0) {
+ tcpmode = ISC_TRUE;
+ } else if (strncasecmp(opt, "novc", 5) == 0) {
+ tcpmode = ISC_FALSE;
+ } else if (strncasecmp(opt, "deb", 3) == 0) {
+ short_form = ISC_FALSE;
+ showsearch = ISC_TRUE;
+ } else if (strncasecmp(opt, "nodeb", 5) == 0) {
+ short_form = ISC_TRUE;
+ showsearch = ISC_FALSE;
+ } else if (strncasecmp(opt, "d2", 2) == 0) {
+ debugging = ISC_TRUE;
+ } else if (strncasecmp(opt, "nod2", 4) == 0) {
+ debugging = ISC_FALSE;
+ } else if (strncasecmp(opt, "search", 3) == 0) {
+ usesearch = ISC_TRUE;
+ } else if (strncasecmp(opt, "nosearch", 5) == 0) {
+ usesearch = ISC_FALSE;
+ } else if (strncasecmp(opt, "sil", 3) == 0) {
+ /* deprecation_msg = ISC_FALSE; */
+ } else if (strncasecmp(opt, "fail", 3) == 0) {
+ nofail=ISC_FALSE;
+ } else if (strncasecmp(opt, "nofail", 3) == 0) {
+ nofail=ISC_TRUE;
+ } else {
+ printf("*** Invalid option: %s\n", opt);
+ }
+}
+
+static void
+addlookup(char *opt) {
+ dig_lookup_t *lookup;
+ isc_result_t result;
+ isc_textregion_t tr;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ char store[MXNAME];
+
+ debug("addlookup()");
+ tr.base = deftype;
+ tr.length = strlen(deftype);
+ result = dns_rdatatype_fromtext(&rdtype, &tr);
+ if (result != ISC_R_SUCCESS) {
+ printf("unknown query type: %s\n", deftype);
+ rdclass = dns_rdatatype_a;
+ }
+ tr.base = defclass;
+ tr.length = strlen(defclass);
+ result = dns_rdataclass_fromtext(&rdclass, &tr);
+ if (result != ISC_R_SUCCESS) {
+ printf("unknown query class: %s\n", defclass);
+ rdclass = dns_rdataclass_in;
+ }
+ lookup = make_empty_lookup();
+ if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE)
+ == ISC_R_SUCCESS) {
+ safecpy(lookup->textname, store, sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_ptr;
+ lookup->rdtypeset = ISC_TRUE;
+ } else {
+ safecpy(lookup->textname, opt, sizeof(lookup->textname));
+ lookup->rdtype = rdtype;
+ lookup->rdtypeset = ISC_TRUE;
+ }
+ lookup->rdclass = rdclass;
+ lookup->rdclassset = ISC_TRUE;
+ lookup->trace = ISC_FALSE;
+ lookup->trace_root = lookup->trace;
+ lookup->ns_search_only = ISC_FALSE;
+ lookup->identify = identify;
+ lookup->recurse = recurse;
+ lookup->aaonly = aaonly;
+ lookup->retries = tries;
+ lookup->udpsize = 0;
+ lookup->comments = comments;
+ lookup->tcp_mode = tcpmode;
+ lookup->stats = stats;
+ lookup->section_question = section_question;
+ lookup->section_answer = section_answer;
+ lookup->section_authority = section_authority;
+ lookup->section_additional = section_additional;
+ lookup->new_search = ISC_TRUE;
+ if (nofail)
+ lookup->servfail_stops = ISC_FALSE;
+ ISC_LIST_INIT(lookup->q);
+ ISC_LINK_INIT(lookup, link);
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ lookup->origin = NULL;
+ ISC_LIST_INIT(lookup->my_server_list);
+ debug("looking up %s", lookup->textname);
+}
+
+static void
+get_next_command(void) {
+ char *buf;
+ char *ptr, *arg;
+ char *input;
+
+ fflush(stdout);
+ buf = isc_mem_allocate(mctx, COMMSIZE);
+ if (buf == NULL)
+ fatal("memory allocation failure");
+ fputs("> ", stderr);
+ fflush(stderr);
+ isc_app_block();
+ ptr = fgets(buf, COMMSIZE, stdin);
+ isc_app_unblock();
+ if (ptr == NULL) {
+ in_use = ISC_FALSE;
+ goto cleanup;
+ }
+ input = buf;
+ ptr = next_token(&input, " \t\r\n");
+ if (ptr == NULL)
+ goto cleanup;
+ arg = next_token(&input, " \t\r\n");
+ if ((strcasecmp(ptr, "set") == 0) &&
+ (arg != NULL))
+ setoption(arg);
+ else if ((strcasecmp(ptr, "server") == 0) ||
+ (strcasecmp(ptr, "lserver") == 0)) {
+ isc_app_block();
+ set_nameserver(arg);
+ check_ra = ISC_FALSE;
+ isc_app_unblock();
+ show_settings(ISC_TRUE, ISC_TRUE);
+ } else if (strcasecmp(ptr, "exit") == 0) {
+ in_use = ISC_FALSE;
+ goto cleanup;
+ } else if (strcasecmp(ptr, "help") == 0 ||
+ strcasecmp(ptr, "?") == 0) {
+ printf("The '%s' command is not yet implemented.\n", ptr);
+ goto cleanup;
+ } else if (strcasecmp(ptr, "finger") == 0 ||
+ strcasecmp(ptr, "root") == 0 ||
+ strcasecmp(ptr, "ls") == 0 ||
+ strcasecmp(ptr, "view") == 0) {
+ printf("The '%s' command is not implemented.\n", ptr);
+ goto cleanup;
+ } else
+ addlookup(ptr);
+ cleanup:
+ isc_mem_free(mctx, buf);
+}
+
+static void
+parse_args(int argc, char **argv) {
+ isc_boolean_t have_lookup = ISC_FALSE;
+
+ usesearch = ISC_TRUE;
+ for (argc--, argv++; argc > 0; argc--, argv++) {
+ debug("main parsing %s", argv[0]);
+ if (argv[0][0] == '-') {
+ if (argv[0][1] != 0)
+ setoption(&argv[0][1]);
+ else
+ have_lookup = ISC_TRUE;
+ } else {
+ if (!have_lookup) {
+ have_lookup = ISC_TRUE;
+ in_use = ISC_TRUE;
+ addlookup(argv[0]);
+ } else {
+ set_nameserver(argv[0]);
+ check_ra = ISC_FALSE;
+ }
+ }
+ }
+}
+
+static void
+flush_lookup_list(void) {
+ dig_lookup_t *l, *lp;
+ dig_query_t *q, *qp;
+ dig_server_t *s, *sp;
+
+ lookup_counter = 0;
+ l = ISC_LIST_HEAD(lookup_list);
+ while (l != NULL) {
+ q = ISC_LIST_HEAD(l->q);
+ while (q != NULL) {
+ if (q->sock != NULL) {
+ isc_socket_cancel(q->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ isc_socket_detach(&q->sock);
+ }
+ if (ISC_LINK_LINKED(&q->recvbuf, link))
+ ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
+ link);
+ if (ISC_LINK_LINKED(&q->lengthbuf, link))
+ ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
+ link);
+ isc_buffer_invalidate(&q->recvbuf);
+ isc_buffer_invalidate(&q->lengthbuf);
+ qp = q;
+ q = ISC_LIST_NEXT(q, link);
+ ISC_LIST_DEQUEUE(l->q, qp, link);
+ isc_mem_free(mctx, qp);
+ }
+ s = ISC_LIST_HEAD(l->my_server_list);
+ while (s != NULL) {
+ sp = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
+ isc_mem_free(mctx, sp);
+
+ }
+ if (l->sendmsg != NULL)
+ dns_message_destroy(&l->sendmsg);
+ if (l->timer != NULL)
+ isc_timer_detach(&l->timer);
+ lp = l;
+ l = ISC_LIST_NEXT(l, link);
+ ISC_LIST_DEQUEUE(lookup_list, lp, link);
+ isc_mem_free(mctx, lp);
+ }
+}
+
+static void
+getinput(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+ if (global_event == NULL)
+ global_event = event;
+ while (in_use) {
+ get_next_command();
+ if (ISC_LIST_HEAD(lookup_list) != NULL) {
+ start_lookup();
+ return;
+ }
+ }
+ isc_app_shutdown();
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ check_ra = ISC_TRUE;
+
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+
+ setup_libs();
+ progname = argv[0];
+
+ parse_args(argc, argv);
+
+ setup_system();
+ if (domainopt[0] != '\0')
+ set_search_domain(domainopt);
+ if (in_use)
+ result = isc_app_onrun(mctx, global_task, onrun_callback,
+ NULL);
+ else
+ result = isc_app_onrun(mctx, global_task, getinput, NULL);
+ check_result(result, "isc_app_onrun");
+ in_use = ISC_TF(!in_use);
+
+ (void)isc_app_run();
+
+ puts("");
+ debug("done, and starting to shut down");
+ if (global_event != NULL)
+ isc_event_free(&global_event);
+ cancel_all();
+ destroy_libs();
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/dig/nslookup.docbook b/bin/dig/nslookup.docbook
new file mode 100644
index 0000000..6c94809
--- /dev/null
+++ b/bin/dig/nslookup.docbook
@@ -0,0 +1,496 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004-2007 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: nslookup.docbook,v 1.16 2007/06/18 23:47:17 tbox Exp $ -->
+<!--
+ - Copyright (c) 1985, 1989
+ - The Regents of the University of California. All rights reserved.
+ -
+ - Redistribution and use in source and binary forms, with or without
+ - modification, are permitted provided that the following conditions
+ - are met:
+ - 1. Redistributions of source code must retain the above copyright
+ - notice, this list of conditions and the following disclaimer.
+ - 2. Redistributions in binary form must reproduce the above copyright
+ - notice, this list of conditions and the following disclaimer in the
+ - documentation and/or other materials provided with the distribution.
+ - 3. All advertising materials mentioning features or use of this software
+ - must display the following acknowledgement:
+ - This product includes software developed by the University of
+ - California, Berkeley and its contributors.
+ - 4. Neither the name of the University nor the names of its contributors
+ - may be used to endorse or promote products derived from this software
+ - without specific prior written permission.
+ -
+ - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ - SUCH DAMAGE.
+-->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>nslookup</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>nslookup</refname>
+ <refpurpose>query Internet name servers interactively</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>nslookup</command>
+ <arg><option>-option</option></arg>
+ <arg choice="opt">name | -</arg>
+ <arg choice="opt">server</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>Nslookup</command>
+ is a program to query Internet domain name servers. <command>Nslookup</command>
+ has two modes: interactive and non-interactive. Interactive mode allows
+ the user to query name servers for information about various hosts and
+ domains or to print a list of hosts in a domain. Non-interactive mode
+ is
+ used to print just the name and requested information for a host or
+ domain.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>ARGUMENTS</title>
+ <para>
+ Interactive mode is entered in the following cases:
+ <orderedlist numeration="loweralpha">
+ <listitem>
+ <para>
+ when no arguments are given (the default name server will be used)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ when the first argument is a hyphen (-) and the second argument is
+ the host name or Internet address of a name server.
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+
+ <para>
+ Non-interactive mode is used when the name or Internet address of the
+ host to be looked up is given as the first argument. The optional second
+ argument specifies the host name or address of a name server.
+ </para>
+
+ <para>
+ Options can also be specified on the command line if they precede the
+ arguments and are prefixed with a hyphen. For example, to
+ change the default query type to host information, and the initial
+ timeout to 10 seconds, type:
+ <informalexample>
+ <programlisting>
+nslookup -query=hinfo -timeout=10
+</programlisting>
+ </informalexample>
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>INTERACTIVE COMMANDS</title>
+ <variablelist>
+ <varlistentry>
+ <term><constant>host</constant> <optional>server</optional></term>
+ <listitem>
+ <para>
+ Look up information for host using the current default server or
+ using server, if specified. If host is an Internet address and
+ the query type is A or PTR, the name of the host is returned.
+ If host is a name and does not have a trailing period, the
+ search list is used to qualify the name.
+ </para>
+
+ <para>
+ To look up a host not in the current domain, append a period to
+ the name.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>server</constant> <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para/>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>lserver</constant> <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para>
+ Change the default server to <replaceable>domain</replaceable>; <constant>lserver</constant> uses the initial
+ server to look up information about <replaceable>domain</replaceable>, while <constant>server</constant> uses
+ the current default server. If an authoritative answer can't be
+ found, the names of servers that might have the answer are
+ returned.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>root</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>finger</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>ls</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>view</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>help</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>?</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>exit</constant></term>
+ <listitem>
+ <para>
+ Exits the program.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>set</constant>
+ <replaceable>keyword<optional>=value</optional></replaceable></term>
+ <listitem>
+ <para>
+ This command is used to change state information that affects
+ the lookups. Valid keywords are:
+ <variablelist>
+ <varlistentry>
+ <term><constant>all</constant></term>
+ <listitem>
+ <para>
+ Prints the current values of the frequently used
+ options to <command>set</command>.
+ Information about the current default
+ server and host is also printed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>class=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para>
+ Change the query class to one of:
+ <variablelist>
+ <varlistentry>
+ <term><constant>IN</constant></term>
+ <listitem>
+ <para>
+ the Internet class
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>CH</constant></term>
+ <listitem>
+ <para>
+ the Chaos class
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>HS</constant></term>
+ <listitem>
+ <para>
+ the Hesiod class
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>ANY</constant></term>
+ <listitem>
+ <para>
+ wildcard
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ The class specifies the protocol group of the information.
+
+ </para>
+ <para>
+ (Default = IN; abbreviation = cl)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>
+ <replaceable><optional>no</optional></replaceable>debug</constant></term>
+ <listitem>
+ <para>
+ Turn on or off the display of the full response packet and
+ any intermediate response packets when searching.
+ </para>
+ <para>
+ (Default = nodebug; abbreviation = <optional>no</optional>deb)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>
+ <replaceable><optional>no</optional></replaceable>d2</constant></term>
+ <listitem>
+ <para>
+ Turn debugging mode on or off. This displays more about
+ what nslookup is doing.
+ </para>
+ <para>
+ (Default = nod2)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>domain=</constant><replaceable>name</replaceable></term>
+ <listitem>
+ <para>
+ Sets the search list to <replaceable>name</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>
+ <replaceable><optional>no</optional></replaceable>search</constant></term>
+ <listitem>
+ <para>
+ If the lookup request contains at least one period but
+ doesn't end with a trailing period, append the domain
+ names in the domain search list to the request until an
+ answer is received.
+ </para>
+ <para>
+ (Default = search)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>port=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para>
+ Change the default TCP/UDP name server port to <replaceable>value</replaceable>.
+ </para>
+ <para>
+ (Default = 53; abbreviation = po)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>querytype=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para/>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>type=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para>
+ Change the type of the information query.
+ </para>
+ <para>
+ (Default = A; abbreviations = q, ty)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>
+ <replaceable><optional>no</optional></replaceable>recurse</constant></term>
+ <listitem>
+ <para>
+ Tell the name server to query other servers if it does not
+ have the
+ information.
+ </para>
+ <para>
+ (Default = recurse; abbreviation = [no]rec)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>retry=</constant><replaceable>number</replaceable></term>
+ <listitem>
+ <para>
+ Set the number of retries to number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>timeout=</constant><replaceable>number</replaceable></term>
+ <listitem>
+ <para>
+ Change the initial timeout interval for waiting for a
+ reply to number seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>
+ <replaceable><optional>no</optional></replaceable>vc</constant></term>
+ <listitem>
+ <para>
+ Always use a virtual circuit when sending requests to the
+ server.
+ </para>
+ <para>
+ (Default = novc)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>
+ <replaceable><optional>no</optional></replaceable>fail</constant></term>
+ <listitem>
+ <para>
+ Try the next nameserver if a nameserver responds with
+ SERVFAIL or a referral (nofail) or terminate query
+ (fail) on such a response.
+ </para>
+ <para>
+ (Default = nofail)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dig</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>host</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Author</title>
+ <para>
+ Andrew Cherenson
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dig/nslookup.html b/bin/dig/nslookup.html
new file mode 100644
index 0000000..0f38176
--- /dev/null
+++ b/bin/dig/nslookup.html
@@ -0,0 +1,307 @@
+<!--
+ - Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: nslookup.html,v 1.21 2007/05/16 06:12:01 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>nslookup</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476276"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>nslookup &#8212; query Internet name servers interactively</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">nslookup</code> [<code class="option">-option</code>] [name | -] [server]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543355"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">Nslookup</strong></span>
+ is a program to query Internet domain name servers. <span><strong class="command">Nslookup</strong></span>
+ has two modes: interactive and non-interactive. Interactive mode allows
+ the user to query name servers for information about various hosts and
+ domains or to print a list of hosts in a domain. Non-interactive mode
+ is
+ used to print just the name and requested information for a host or
+ domain.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543371"></a><h2>ARGUMENTS</h2>
+<p>
+ Interactive mode is entered in the following cases:
+ </p>
+<div class="orderedlist"><ol type="a">
+<li><p>
+ when no arguments are given (the default name server will be used)
+ </p></li>
+<li><p>
+ when the first argument is a hyphen (-) and the second argument is
+ the host name or Internet address of a name server.
+ </p></li>
+</ol></div>
+<p>
+ </p>
+<p>
+ Non-interactive mode is used when the name or Internet address of the
+ host to be looked up is given as the first argument. The optional second
+ argument specifies the host name or address of a name server.
+ </p>
+<p>
+ Options can also be specified on the command line if they precede the
+ arguments and are prefixed with a hyphen. For example, to
+ change the default query type to host information, and the initial
+ timeout to 10 seconds, type:
+ </p>
+<div class="informalexample"><pre class="programlisting">
+nslookup -query=hinfo -timeout=10
+</pre></div>
+<p>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543413"></a><h2>INTERACTIVE COMMANDS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">host</code> [<span class="optional">server</span>]</span></dt>
+<dd>
+<p>
+ Look up information for host using the current default server or
+ using server, if specified. If host is an Internet address and
+ the query type is A or PTR, the name of the host is returned.
+ If host is a name and does not have a trailing period, the
+ search list is used to qualify the name.
+ </p>
+<p>
+ To look up a host not in the current domain, append a period to
+ the name.
+ </p>
+</dd>
+<dt><span class="term"><code class="constant">server</code> <em class="replaceable"><code>domain</code></em></span></dt>
+<dd><p></p></dd>
+<dt><span class="term"><code class="constant">lserver</code> <em class="replaceable"><code>domain</code></em></span></dt>
+<dd><p>
+ Change the default server to <em class="replaceable"><code>domain</code></em>; <code class="constant">lserver</code> uses the initial
+ server to look up information about <em class="replaceable"><code>domain</code></em>, while <code class="constant">server</code> uses
+ the current default server. If an authoritative answer can't be
+ found, the names of servers that might have the answer are
+ returned.
+ </p></dd>
+<dt><span class="term"><code class="constant">root</code></span></dt>
+<dd><p>
+ not implemented
+ </p></dd>
+<dt><span class="term"><code class="constant">finger</code></span></dt>
+<dd><p>
+ not implemented
+ </p></dd>
+<dt><span class="term"><code class="constant">ls</code></span></dt>
+<dd><p>
+ not implemented
+ </p></dd>
+<dt><span class="term"><code class="constant">view</code></span></dt>
+<dd><p>
+ not implemented
+ </p></dd>
+<dt><span class="term"><code class="constant">help</code></span></dt>
+<dd><p>
+ not implemented
+ </p></dd>
+<dt><span class="term"><code class="constant">?</code></span></dt>
+<dd><p>
+ not implemented
+ </p></dd>
+<dt><span class="term"><code class="constant">exit</code></span></dt>
+<dd><p>
+ Exits the program.
+ </p></dd>
+<dt><span class="term"><code class="constant">set</code>
+ <em class="replaceable"><code>keyword[<span class="optional">=value</span>]</code></em></span></dt>
+<dd>
+<p>
+ This command is used to change state information that affects
+ the lookups. Valid keywords are:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">all</code></span></dt>
+<dd><p>
+ Prints the current values of the frequently used
+ options to <span><strong class="command">set</strong></span>.
+ Information about the current default
+ server and host is also printed.
+ </p></dd>
+<dt><span class="term"><code class="constant">class=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+<p>
+ Change the query class to one of:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">IN</code></span></dt>
+<dd><p>
+ the Internet class
+ </p></dd>
+<dt><span class="term"><code class="constant">CH</code></span></dt>
+<dd><p>
+ the Chaos class
+ </p></dd>
+<dt><span class="term"><code class="constant">HS</code></span></dt>
+<dd><p>
+ the Hesiod class
+ </p></dd>
+<dt><span class="term"><code class="constant">ANY</code></span></dt>
+<dd><p>
+ wildcard
+ </p></dd>
+</dl></div>
+<p>
+ The class specifies the protocol group of the information.
+
+ </p>
+<p>
+ (Default = IN; abbreviation = cl)
+ </p>
+</dd>
+<dt><span class="term"><code class="constant">
+ <em class="replaceable"><code>[<span class="optional">no</span>]</code></em>debug</code></span></dt>
+<dd>
+<p>
+ Turn on or off the display of the full response packet and
+ any intermediate response packets when searching.
+ </p>
+<p>
+ (Default = nodebug; abbreviation = [<span class="optional">no</span>]deb)
+ </p>
+</dd>
+<dt><span class="term"><code class="constant">
+ <em class="replaceable"><code>[<span class="optional">no</span>]</code></em>d2</code></span></dt>
+<dd>
+<p>
+ Turn debugging mode on or off. This displays more about
+ what nslookup is doing.
+ </p>
+<p>
+ (Default = nod2)
+ </p>
+</dd>
+<dt><span class="term"><code class="constant">domain=</code><em class="replaceable"><code>name</code></em></span></dt>
+<dd><p>
+ Sets the search list to <em class="replaceable"><code>name</code></em>.
+ </p></dd>
+<dt><span class="term"><code class="constant">
+ <em class="replaceable"><code>[<span class="optional">no</span>]</code></em>search</code></span></dt>
+<dd>
+<p>
+ If the lookup request contains at least one period but
+ doesn't end with a trailing period, append the domain
+ names in the domain search list to the request until an
+ answer is received.
+ </p>
+<p>
+ (Default = search)
+ </p>
+</dd>
+<dt><span class="term"><code class="constant">port=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+<p>
+ Change the default TCP/UDP name server port to <em class="replaceable"><code>value</code></em>.
+ </p>
+<p>
+ (Default = 53; abbreviation = po)
+ </p>
+</dd>
+<dt><span class="term"><code class="constant">querytype=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd><p></p></dd>
+<dt><span class="term"><code class="constant">type=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+<p>
+ Change the type of the information query.
+ </p>
+<p>
+ (Default = A; abbreviations = q, ty)
+ </p>
+</dd>
+<dt><span class="term"><code class="constant">
+ <em class="replaceable"><code>[<span class="optional">no</span>]</code></em>recurse</code></span></dt>
+<dd>
+<p>
+ Tell the name server to query other servers if it does not
+ have the
+ information.
+ </p>
+<p>
+ (Default = recurse; abbreviation = [no]rec)
+ </p>
+</dd>
+<dt><span class="term"><code class="constant">retry=</code><em class="replaceable"><code>number</code></em></span></dt>
+<dd><p>
+ Set the number of retries to number.
+ </p></dd>
+<dt><span class="term"><code class="constant">timeout=</code><em class="replaceable"><code>number</code></em></span></dt>
+<dd><p>
+ Change the initial timeout interval for waiting for a
+ reply to number seconds.
+ </p></dd>
+<dt><span class="term"><code class="constant">
+ <em class="replaceable"><code>[<span class="optional">no</span>]</code></em>vc</code></span></dt>
+<dd>
+<p>
+ Always use a virtual circuit when sending requests to the
+ server.
+ </p>
+<p>
+ (Default = novc)
+ </p>
+</dd>
+<dt><span class="term"><code class="constant">
+ <em class="replaceable"><code>[<span class="optional">no</span>]</code></em>fail</code></span></dt>
+<dd>
+<p>
+ Try the next nameserver if a nameserver responds with
+ SERVFAIL or a referral (nofail) or terminate query
+ (fail) on such a response.
+ </p>
+<p>
+ (Default = nofail)
+ </p>
+</dd>
+</dl></div>
+<p>
+ </p>
+</dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2546279"></a><h2>FILES</h2>
+<p><code class="filename">/etc/resolv.conf</code>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2546291"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dig</span>(1)</span>,
+ <span class="citerefentry"><span class="refentrytitle">host</span>(1)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2546325"></a><h2>Author</h2>
+<p>
+ Andrew Cherenson
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dig/win32/dig.dsp b/bin/dig/win32/dig.dsp
new file mode 100644
index 0000000..4051643
--- /dev/null
+++ b/bin/dig/win32/dig.dsp
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="dig" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=dig - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dig.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dig.mak" CFG="dig - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dig - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "dig - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/dighost.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/dig.exe"
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/dighost.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/dig.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "dig - Win32 Release"
+# Name "dig - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\dig.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\dig\dig.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/dig.dsw b/bin/dig/win32/dig.dsw
new file mode 100644
index 0000000..ae9c548
--- /dev/null
+++ b/bin/dig/win32/dig.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dig"=".\dig.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/dig.mak b/bin/dig/win32/dig.mak
new file mode 100644
index 0000000..e6eb21c
--- /dev/null
+++ b/bin/dig/win32/dig.mak
@@ -0,0 +1,425 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on dig.dsp
+!IF "$(CFG)" == ""
+CFG=dig - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to dig - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "dig - Win32 Release" && "$(CFG)" != "dig - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dig.mak" CFG="dig - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dig - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "dig - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dig - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\dig.exe"
+
+!ELSE
+
+ALL : "liblwres - Win32 Release" "libbind9 - Win32 Release" "libisc - Win32 Release" "libdns - Win32 Release" "..\..\..\Build\Release\dig.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN" "libbind9 - Win32 ReleaseCLEAN" "liblwres - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dig.obj"
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dig.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\dig.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\dig.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dig.pdb" /machine:I386 /out:"../../../Build/Release/dig.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dig.obj" \
+ "$(INTDIR)\dighost.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib"
+
+"..\..\..\Build\Release\dig.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\dig.exe" "$(OUTDIR)\dig.bsc"
+
+!ELSE
+
+ALL : "liblwres - Win32 Debug" "libbind9 - Win32 Debug" "libisc - Win32 Debug" "libdns - Win32 Debug" "..\..\..\Build\Debug\dig.exe" "$(OUTDIR)\dig.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 DebugCLEAN" "libisc - Win32 DebugCLEAN" "libbind9 - Win32 DebugCLEAN" "liblwres - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dig.obj"
+ -@erase "$(INTDIR)\dig.sbr"
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\dighost.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dig.bsc"
+ -@erase "$(OUTDIR)\dig.pdb"
+ -@erase "..\..\..\Build\Debug\dig.exe"
+ -@erase "..\..\..\Build\Debug\dig.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\dig.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dig.sbr" \
+ "$(INTDIR)\dighost.sbr"
+
+"$(OUTDIR)\dig.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dig.pdb" /debug /machine:I386 /out:"../../../Build/Debug/dig.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dig.obj" \
+ "$(INTDIR)\dighost.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib"
+
+"..\..\..\Build\Debug\dig.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("dig.dep")
+!INCLUDE "dig.dep"
+!ELSE
+!MESSAGE Warning: cannot find "dig.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "dig - Win32 Release" || "$(CFG)" == "dig - Win32 Debug"
+SOURCE=..\dig.c
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+
+"$(INTDIR)\dig.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+
+"$(INTDIR)\dig.obj" "$(INTDIR)\dig.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+"libbind9 - Win32 Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+"libbind9 - Win32 Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+"liblwres - Win32 Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+"liblwres - Win32 Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dig/win32/dighost.dsp b/bin/dig/win32/dighost.dsp
new file mode 100644
index 0000000..e37031b
--- /dev/null
+++ b/bin/dig/win32/dighost.dsp
@@ -0,0 +1,113 @@
+# Microsoft Developer Studio Project File - Name="dighost" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static-Link Library" 0x0104
+
+CFG=dighost - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dighost.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dighost.mak" CFG="dighost - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dighost - Win32 Release" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE "dighost - Win32 Debug" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dighost - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /YX /FD /c /Fddighost
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/dighost.lib"
+
+!ELSEIF "$(CFG)" == "dighost - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR /YX /FD /GZ /c /Fddighost
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug out:"Debug/dighost.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "dighost - Win32 Release"
+# Name "dighost - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\dighost.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/dighost.dsw b/bin/dig/win32/dighost.dsw
new file mode 100644
index 0000000..fdae6d4
--- /dev/null
+++ b/bin/dig/win32/dighost.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dighost"=".\dighost.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/host.dsp b/bin/dig/win32/host.dsp
new file mode 100644
index 0000000..4dc4312
--- /dev/null
+++ b/bin/dig/win32/host.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="host" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=host - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "host.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "host.mak" CFG="host - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "host - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "host - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/dighost.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/host.exe"
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/dighost.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/host.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "host - Win32 Release"
+# Name "host - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\host.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/host.dsw b/bin/dig/win32/host.dsw
new file mode 100644
index 0000000..e566e78
--- /dev/null
+++ b/bin/dig/win32/host.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "host"=".\host.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/host.mak b/bin/dig/win32/host.mak
new file mode 100644
index 0000000..4a72609
--- /dev/null
+++ b/bin/dig/win32/host.mak
@@ -0,0 +1,425 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on host.dsp
+!IF "$(CFG)" == ""
+CFG=host - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to host - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "host - Win32 Release" && "$(CFG)" != "host - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "host.mak" CFG="host - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "host - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "host - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "host - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\host.exe"
+
+!ELSE
+
+ALL : "liblwres - Win32 Release" "libbind9 - Win32 Release" "libisc - Win32 Release" "libdns - Win32 Release" "..\..\..\Build\Release\host.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN" "libbind9 - Win32 ReleaseCLEAN" "liblwres - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\host.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\host.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\host.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\host.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\host.pdb" /machine:I386 /out:"../../../Build/Release/host.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\host.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib"
+
+"..\..\..\Build\Release\host.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\host.exe" "$(OUTDIR)\host.bsc"
+
+!ELSE
+
+ALL : "liblwres - Win32 Debug" "libbind9 - Win32 Debug" "libisc - Win32 Debug" "libdns - Win32 Debug" "..\..\..\Build\Debug\host.exe" "$(OUTDIR)\host.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 DebugCLEAN" "libisc - Win32 DebugCLEAN" "libbind9 - Win32 DebugCLEAN" "liblwres - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\dighost.sbr"
+ -@erase "$(INTDIR)\host.obj"
+ -@erase "$(INTDIR)\host.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\host.bsc"
+ -@erase "$(OUTDIR)\host.pdb"
+ -@erase "..\..\..\Build\Debug\host.exe"
+ -@erase "..\..\..\Build\Debug\host.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\host.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dighost.sbr" \
+ "$(INTDIR)\host.sbr"
+
+"$(OUTDIR)\host.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\host.pdb" /debug /machine:I386 /out:"../../../Build/Debug/host.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\host.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib"
+
+"..\..\..\Build\Debug\host.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("host.dep")
+!INCLUDE "host.dep"
+!ELSE
+!MESSAGE Warning: cannot find "host.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "host - Win32 Release" || "$(CFG)" == "host - Win32 Debug"
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\host.c
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+
+"$(INTDIR)\host.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+
+"$(INTDIR)\host.obj" "$(INTDIR)\host.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+"libbind9 - Win32 Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+"libbind9 - Win32 Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+"liblwres - Win32 Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+"liblwres - Win32 Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dig/win32/nslookup.dsp b/bin/dig/win32/nslookup.dsp
new file mode 100644
index 0000000..cc0f4ab
--- /dev/null
+++ b/bin/dig/win32/nslookup.dsp
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="nslookup" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=nslookup - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "nslookup.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nslookup.mak" CFG="nslookup - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nslookup - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "nslookup - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/nslookup.exe"
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/nslookup.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "nslookup - Win32 Release"
+# Name "nslookup - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\dighost.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nslookup.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/nslookup.dsw b/bin/dig/win32/nslookup.dsw
new file mode 100644
index 0000000..0ff8c66
--- /dev/null
+++ b/bin/dig/win32/nslookup.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "nslookup"=".\nslookup.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/nslookup.mak b/bin/dig/win32/nslookup.mak
new file mode 100644
index 0000000..6fcbf13
--- /dev/null
+++ b/bin/dig/win32/nslookup.mak
@@ -0,0 +1,425 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on nslookup.dsp
+!IF "$(CFG)" == ""
+CFG=nslookup - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to nslookup - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "nslookup - Win32 Release" && "$(CFG)" != "nslookup - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nslookup.mak" CFG="nslookup - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nslookup - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "nslookup - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\nslookup.exe"
+
+!ELSE
+
+ALL : "liblwres - Win32 Release" "libbind9 - Win32 Release" "libisc - Win32 Release" "libdns - Win32 Release" "..\..\..\Build\Release\nslookup.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN" "libbind9 - Win32 ReleaseCLEAN" "liblwres - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\nslookup.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\nslookup.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\nslookup.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nslookup.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\nslookup.pdb" /machine:I386 /out:"../../../Build/Release/nslookup.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\nslookup.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib"
+
+"..\..\..\Build\Release\nslookup.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\nslookup.exe" "$(OUTDIR)\nslookup.bsc"
+
+!ELSE
+
+ALL : "liblwres - Win32 Debug" "libbind9 - Win32 Debug" "libisc - Win32 Debug" "libdns - Win32 Debug" "..\..\..\Build\Debug\nslookup.exe" "$(OUTDIR)\nslookup.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 DebugCLEAN" "libisc - Win32 DebugCLEAN" "libbind9 - Win32 DebugCLEAN" "liblwres - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\dighost.sbr"
+ -@erase "$(INTDIR)\nslookup.obj"
+ -@erase "$(INTDIR)\nslookup.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\nslookup.bsc"
+ -@erase "$(OUTDIR)\nslookup.pdb"
+ -@erase "..\..\..\Build\Debug\nslookup.exe"
+ -@erase "..\..\..\Build\Debug\nslookup.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nslookup.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dighost.sbr" \
+ "$(INTDIR)\nslookup.sbr"
+
+"$(OUTDIR)\nslookup.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\nslookup.pdb" /debug /machine:I386 /out:"../../../Build/Debug/nslookup.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\nslookup.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib"
+
+"..\..\..\Build\Debug\nslookup.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("nslookup.dep")
+!INCLUDE "nslookup.dep"
+!ELSE
+!MESSAGE Warning: cannot find "nslookup.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "nslookup - Win32 Release" || "$(CFG)" == "nslookup - Win32 Debug"
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\nslookup.c
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+
+"$(INTDIR)\nslookup.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+
+"$(INTDIR)\nslookup.obj" "$(INTDIR)\nslookup.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+"libbind9 - Win32 Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+"libbind9 - Win32 Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+"liblwres - Win32 Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+"liblwres - Win32 Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/Makefile.in b/bin/dnssec/Makefile.in
new file mode 100644
index 0000000..d59a38f
--- /dev/null
+++ b/bin/dnssec/Makefile.in
@@ -0,0 +1,95 @@
+# Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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.35 2008/11/07 02:28:49 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES = -DVERSION=\"${VERSION}\"
+CWARNINGS =
+
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../lib/isc/libisc.@A@
+
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+# Alphabetically
+TARGETS = dnssec-keygen@EXEEXT@ dnssec-signzone@EXEEXT@ \
+ dnssec-keyfromlabel@EXEEXT@ dnssec-dsfromkey@EXEEXT@
+
+OBJS = dnssectool.@O@
+
+SRCS = dnssec-dsfromkey.c dnssec-keyfromlabel.c dnssec-keygen.c \
+ dnssec-signzone.c dnssectool.c
+
+MANPAGES = dnssec-dsfromkey.8 dnssec-keyfromlabel.8 dnssec-keygen.8 \
+ dnssec-signzone.8
+
+HTMLPAGES = dnssec-dsfromkey.html dnssec-keyfromlabel.html \
+ dnssec-keygen.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}
+
+dnssec-keyfromlabel@EXEEXT@: dnssec-keyfromlabel.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-keyfromlabel.@O@ ${OBJS} ${LIBS}
+
+dnssec-keygen@EXEEXT@: dnssec-keygen.@O@ ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-keygen.@O@ ${OBJS} ${LIBS}
+
+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}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dnssec-signzone.@O@ ${OBJS} ${LIBS}
+
+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:: ${TARGETS} installdirs
+ for t in ${TARGETS}; do ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} $$t ${DESTDIR}${sbindir}; done
+ for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man8; done
+
+clean distclean::
+ rm -f ${TARGETS}
+
diff --git a/bin/dnssec/dnssec-dsfromkey.8 b/bin/dnssec/dnssec-dsfromkey.8
new file mode 100644
index 0000000..4d4cbc9
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.8
@@ -0,0 +1,124 @@
+.\" Copyright (C) 2008 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-dsfromkey.8,v 1.5 2008/11/08 01:11:47 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: dnssec\-dsfromkey
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: November 29, 2008
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "DNSSEC\-DSFROMKEY" "8" "November 29, 2008" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+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}
+.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}
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-dsfromkey\fR
+outputs the Delegation Signer (DS) resource record (RR), as defined in RFC 3658 and RFC 4509, for the given key(s).
+.SH "OPTIONS"
+.PP
+\-1
+.RS 4
+Use SHA\-1 as the digest algorithm (the default is to use both SHA\-1 and SHA\-256).
+.RE
+.PP
+\-2
+.RS 4
+Use SHA\-256 as the digest algorithm.
+.RE
+.PP
+\-a \fIalgorithm\fR
+.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.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level.
+.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.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Specifies the DNS class (default is IN), useful only in the keyset mode.
+.RE
+.PP
+\-d \fIdirectory\fR
+.RS 4
+Look for
+\fIkeyset\fR
+files in
+\fBdirectory\fR
+as the directory, ignored when not in the keyset mode.
+.RE
+.SH "EXAMPLE"
+.PP
+To build the SHA\-256 DS RR from the
+\fBKexample.com.+003+26160\fR
+keyfile name, the following command would be issued:
+.PP
+\fBdnssec\-dsfromkey \-2 Kexample.com.+003+26160\fR
+.PP
+The command would print something like:
+.PP
+\fBexample.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94\fR
+.SH "FILES"
+.PP
+The keyfile can be designed by the key identification
+\fIKnnnn.+aaa+iiiii\fR
+or the full file name
+\fIKnnnn.+aaa+iiiii.key\fR
+as generated by
+dnssec\-keygen(8).
+.PP
+The keyset file name is built from the
+\fBdirectory\fR, the string
+\fIkeyset\-\fR
+and the
+\fBdnsname\fR.
+.SH "CAVEAT"
+.PP
+A keyfile error can give a "file not found" even if the file exists.
+.SH "SEE ALSO"
+.PP
+\fBdnssec\-keygen\fR(8),
+\fBdnssec\-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 3658,
+RFC 4509.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2008 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-dsfromkey.c b/bin/dnssec/dnssec-dsfromkey.c
new file mode 100644
index 0000000..d3d1d06
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2008 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-dsfromkey.c,v 1.2 2008/11/07 02:28:49 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/ds.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+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 void
+loadkeys(char *dirname, char *setname)
+{
+ isc_result_t result;
+ char filename[1024];
+ 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);
+
+ isc_buffer_init(&buf, filename, sizeof(filename));
+ if (dirname != NULL) {
+ isc_buffer_putstr(&buf, dirname);
+ if (dirname[strlen(dirname) - 1] != '/')
+ isc_buffer_putstr(&buf, "/");
+ }
+ 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);
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
+ rdclass, 0, NULL, &db);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't create database");
+
+ result = dns_db_load(db, filename);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
+ fatal("can't load %s: %s", filename, isc_result_totext(result));
+
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't find %s node in %s", setname, filename);
+
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey,
+ 0, 0, &keyset, 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");
+}
+
+static void
+loadkey(char *filename, dns_rdata_t *rdata)
+{
+ isc_result_t result;
+ dst_key_t *key = NULL;
+ unsigned char key_buf[DST_KEY_MAXSIZE];
+ isc_buffer_t keyb;
+ isc_region_t r;
+
+ dns_rdataset_init(&keyset);
+ dns_rdata_init(rdata);
+
+ isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
+
+ result = dst_key_fromnamedfile(filename, 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];
+
+ key_format(key, keystr, sizeof(keystr));
+ fprintf(stderr, "%s: %s\n", program, keystr);
+ }
+
+ result = dst_key_todns(key, &keyb);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't decode key");
+
+ isc_buffer_usedregion(&keyb, &r);
+ dns_rdata_fromregion(rdata, dst_key_class(key),
+ dns_rdatatype_dnskey, &r);
+
+ rdclass = dst_key_class(key);
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ result = dns_name_copy(dst_key_name(key), name, NULL);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't copy name");
+
+ dst_key_free(&key);
+}
+
+static void
+logkey(dns_rdata_t *rdata)
+{
+ isc_result_t result;
+ dst_key_t *key = NULL;
+ isc_buffer_t buf;
+ char keystr[KEY_FORMATSIZE];
+
+ isc_buffer_init(&buf, rdata->data, rdata->length);
+ isc_buffer_add(&buf, rdata->length);
+ result = dst_key_fromdns(name, rdclass, &buf, mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ 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)
+{
+ 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_buffer_init(&textb, text_buf, sizeof(text_buf));
+ isc_buffer_init(&classb, class_buf, sizeof(class_buf));
+
+ dns_rdata_init(&ds);
+
+ result = dns_ds_buildrdata(name, rdata, dtype, buf, &ds);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't build DS");
+
+ result = dns_rdata_totext(&ds, (dns_name_t *) NULL, &textb);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't print DS rdata");
+
+ result = dns_rdataclass_totext(rdclass, &classb);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't print DS class");
+
+ result = dns_name_print(name, stdout);
+ if (result != ISC_R_SUCCESS)
+ fatal("can't print DS name");
+
+ putchar(' ');
+
+ isc_buffer_usedregion(&classb, &r);
+ fwrite(r.base, 1, r.length, stdout);
+
+ printf(" DS ");
+
+ isc_buffer_usedregion(&textb, &r);
+ fwrite(r.base, 1, r.length, stdout);
+ putchar('\n');
+}
+
+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",
+ program);
+ fprintf(stderr, "Version: %s\n", VERSION);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -v <verbose level>\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");
+
+ 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;
+
+ dns_rdata_init(&rdata);
+
+ 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,
+ "12a:c:d:sv:h")) != -1) {
+ switch (ch) {
+ case '1':
+ dtype = DNS_DSDIGEST_SHA1;
+ both = ISC_FALSE;
+ break;
+ case '2':
+ dtype = DNS_DSDIGEST_SHA256;
+ both = ISC_FALSE;
+ break;
+ case 'a':
+ algname = isc_commandline_argument;
+ both = ISC_FALSE;
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'd':
+ dirname = isc_commandline_argument;
+ break;
+ case 's':
+ usekeyset = 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 (algname != NULL) {
+ if (strcasecmp(algname, "SHA1") == 0 ||
+ strcasecmp(algname, "SHA-1") == 0)
+ dtype = DNS_DSDIGEST_SHA1;
+ else if (strcasecmp(algname, "SHA256") == 0 ||
+ strcasecmp(algname, "SHA-256") == 0)
+ dtype = DNS_DSDIGEST_SHA256;
+ else
+ fatal("unknown algorithm %s", algname);
+ }
+
+ rdclass = strtoclass(classname);
+
+ if (argc < isc_commandline_index + 1)
+ 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_init(mctx, ectx,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize dst");
+ isc_entropy_stopcallbacksources(ectx);
+
+ setup_logging(verbose, mctx, &log);
+
+ if (usekeyset) {
+ loadkeys(dirname, argv[isc_commandline_index]);
+
+ for (result = dns_rdataset_first(&keyset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&keyset)) {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(&keyset, &rdata);
+
+ if (verbose > 2)
+ logkey(&rdata);
+
+ if (both) {
+ emitds(DNS_DSDIGEST_SHA1, &rdata);
+ emitds(DNS_DSDIGEST_SHA256, &rdata);
+ } else
+ emitds(dtype, &rdata);
+ }
+ } else {
+ loadkey(argv[isc_commandline_index], &rdata);
+
+ if (both) {
+ emitds(DNS_DSDIGEST_SHA1, &rdata);
+ emitds(DNS_DSDIGEST_SHA256, &rdata);
+ } else
+ emitds(dtype, &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);
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ dns_name_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-dsfromkey.docbook b/bin/dnssec/dnssec-dsfromkey.docbook
new file mode 100644
index 0000000..c2c6b85
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.docbook
@@ -0,0 +1,214 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2008 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-dsfromkey.docbook,v 1.6 2008/11/07 13:54:11 jreed Exp $ -->
+<refentry id="man.dnssec-dsfromkey">
+ <refentryinfo>
+ <date>November 29, 2008</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-dsfromkey</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-dsfromkey</application></refname>
+ <refpurpose>DNSSEC DS RR generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-dsfromkey</command>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg><option>-1</option></arg>
+ <arg><option>-2</option></arg>
+ <arg><option>-a <replaceable class="parameter">alg</replaceable></option></arg>
+ <arg choice="req">keyfile</arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>dnssec-dsfromkey</command>
+ <arg choice="req">-s</arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg><option>-1</option></arg>
+ <arg><option>-2</option></arg>
+ <arg><option>-a <replaceable class="parameter">alg</replaceable></option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-d <replaceable class="parameter">dir</replaceable></option></arg>
+ <arg choice="req">dnsname</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dnssec-dsfromkey</command>
+ outputs the Delegation Signer (DS) resource record (RR), as defined in
+ RFC 3658 and RFC 4509, for the given key(s).
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-1</term>
+ <listitem>
+ <para>
+ Use SHA-1 as the digest algorithm (the default is to use
+ both SHA-1 and SHA-256).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-2</term>
+ <listitem>
+ <para>
+ Use SHA-256 as the digest algorithm.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ Select the digest algorithm. The value of
+ <option>algorithm</option> must be one of SHA-1 (SHA1) or
+ SHA-256 (SHA256). These values are case insensitive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s</term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the DNS class (default is IN), useful only
+ in the keyset mode.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Look for <filename>keyset</filename> files in
+ <option>directory</option> as the directory, ignored when
+ not in the keyset mode.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLE</title>
+ <para>
+ To build the SHA-256 DS RR from the
+ <userinput>Kexample.com.+003+26160</userinput>
+ keyfile name, the following command would be issued:
+ </para>
+ <para><userinput>dnssec-dsfromkey -2 Kexample.com.+003+26160</userinput>
+ </para>
+ <para>
+ The command would print something like:
+ </para>
+ <para><userinput>example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94</userinput>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+ <para>
+ The keyfile can be designed by the key identification
+ <filename>Knnnn.+aaa+iiiii</filename> or the full file name
+ <filename>Knnnn.+aaa+iiiii.key</filename> as generated by
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>.
+ </para>
+ <para>
+ The keyset file name is built from the <option>directory</option>,
+ the string <filename>keyset-</filename> and the
+ <option>dnsname</option>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>CAVEAT</title>
+ <para>
+ A keyfile error can give a "file not found" even if the file exists.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 3658</citetitle>,
+ <citetitle>RFC 4509</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dnssec/dnssec-dsfromkey.html b/bin/dnssec/dnssec-dsfromkey.html
new file mode 100644
index 0000000..72dfd3a
--- /dev/null
+++ b/bin/dnssec/dnssec-dsfromkey.html
@@ -0,0 +1,133 @@
+<!--
+ - Copyright (C) 2008 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-dsfromkey.html,v 1.5 2008/11/08 01:11:47 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-dsfromkey</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.dnssec-dsfromkey"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-dsfromkey</span> &#8212; DNSSEC DS RR generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-dsfromkey</code> [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-1</code>] [<code class="option">-2</code>] [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] {keyfile}</p></div>
+<div class="cmdsynopsis"><p><code class="command">dnssec-dsfromkey</code> {-s} [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-1</code>] [<code class="option">-2</code>] [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-d <em class="replaceable"><code>dir</code></em></code>] {dnsname}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543424"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-dsfromkey</strong></span>
+ outputs the Delegation Signer (DS) resource record (RR), as defined in
+ RFC 3658 and RFC 4509, for the given key(s).
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543435"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-1</span></dt>
+<dd><p>
+ Use SHA-1 as the digest algorithm (the default is to use
+ both SHA-1 and SHA-256).
+ </p></dd>
+<dt><span class="term">-2</span></dt>
+<dd><p>
+ Use SHA-256 as the digest algorithm.
+ </p></dd>
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd><p>
+ Select the digest algorithm. The value of
+ <code class="option">algorithm</code> must be one of SHA-1 (SHA1) or
+ SHA-256 (SHA256). These values are case insensitive.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+<dt><span class="term">-s</span></dt>
+<dd><p>
+ 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.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Specifies the DNS class (default is IN), useful only
+ in the keyset mode.
+ </p></dd>
+<dt><span class="term">-d <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Look for <code class="filename">keyset</code> files in
+ <code class="option">directory</code> as the directory, ignored when
+ not in the keyset mode.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543563"></a><h2>EXAMPLE</h2>
+<p>
+ To build the SHA-256 DS RR from the
+ <strong class="userinput"><code>Kexample.com.+003+26160</code></strong>
+ keyfile name, the following command would be issued:
+ </p>
+<p><strong class="userinput"><code>dnssec-dsfromkey -2 Kexample.com.+003+26160</code></strong>
+ </p>
+<p>
+ The command would print something like:
+ </p>
+<p><strong class="userinput"><code>example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94</code></strong>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543593"></a><h2>FILES</h2>
+<p>
+ The keyfile can be designed by the key identification
+ <code class="filename">Knnnn.+aaa+iiiii</code> or the full file name
+ <code class="filename">Knnnn.+aaa+iiiii.key</code> as generated by
+ <span class="refentrytitle">dnssec-keygen</span>(8).
+ </p>
+<p>
+ The keyset file name is built from the <code class="option">directory</code>,
+ the string <code class="filename">keyset-</code> and the
+ <code class="option">dnsname</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543628"></a><h2>CAVEAT</h2>
+<p>
+ A keyfile error can give a "file not found" even if the file exists.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543638"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 3658</em>,
+ <em class="citetitle">RFC 4509</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543674"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-keyfromlabel.8 b/bin/dnssec/dnssec-keyfromlabel.8
new file mode 100644
index 0000000..6222058
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.8
@@ -0,0 +1,149 @@
+.\" Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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-keyfromlabel.8,v 1.6 2008/11/08 01:11:47 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: dnssec\-keyfromlabel
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: February 8, 2008
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "DNSSEC\-KEYFROMLABEL" "8" "February 8, 2008" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+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}
+.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.
+.SH "OPTIONS"
+.PP
+\-a \fIalgorithm\fR
+.RS 4
+Selects the cryptographic algorithm. The value of
+\fBalgorithm\fR
+must be one of RSAMD5 (RSA) or RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA or DH (Diffie Hellman). These values are case insensitive.
+.sp
+Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement algorithm, and DSA is recommended.
+.sp
+Note 2: DH automatically sets the \-k flag.
+.RE
+.PP
+\-l \fIlabel\fR
+.RS 4
+Specifies the label of keys in the crypto hardware (PKCS#11 device).
+.RE
+.PP
+\-n \fInametype\fR
+.RS 4
+Specifies the owner type of the key. The value of
+\fBnametype\fR
+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 \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
+\-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.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of the options and arguments to
+\fBdnssec\-keygen\fR.
+.RE
+.PP
+\-k
+.RS 4
+Generate KEY records rather than DNSKEY records.
+.RE
+.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.
+.RE
+.PP
+\-t \fItype\fR
+.RS 4
+Indicates the use of the key.
+\fBtype\fR
+must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level.
+.RE
+.SH "GENERATED KEY FILES"
+.PP
+When
+\fBdnssec\-keyfromlabel\fR
+completes successfully, it prints a string of the form
+\fIKnnnn.+aaa+iiiii\fR
+to the standard output. This is an identification string for the key files it has generated.
+.TP 4
+\(bu
+\fInnnn\fR
+is the key name.
+.TP 4
+\(bu
+\fIaaa\fR
+is the numeric representation of the algorithm.
+.TP 4
+\(bu
+\fIiiiii\fR
+is the key identifier (or footprint).
+.PP
+\fBdnssec\-keyfromlabel\fR
+creates two files, with names based on the printed string.
+\fIKnnnn.+aaa+iiiii.key\fR
+contains the public key, and
+\fIKnnnn.+aaa+iiiii.private\fR
+contains the private key.
+.PP
+The
+\fI.key\fR
+file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement).
+.PP
+The
+\fI.private\fR
+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),
+\fBdnssec\-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 2539,
+RFC 2845,
+RFC 4033.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2008 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dnssec/dnssec-keyfromlabel.c b/bin/dnssec/dnssec-keyfromlabel.c
new file mode 100644
index 0000000..e7587c3
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2007, 2008 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-keyfromlabel.c,v 1.4 2008/09/24 02:46:21 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+#define MAX_RSA 4096 /* should be long enough... */
+
+const char *program = "dnssec-keyfromlabel";
+int verbose;
+
+static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 |"
+ " NSEC3DSA | NSEC3RSASHA1";
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s -a alg -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, " name: owner of the key\n");
+ fprintf(stderr, "Other options:\n");
+ fprintf(stderr, " -n nametype: ZONE | HOST | ENTITY | USER | OTHER\n");
+ fprintf(stderr, " (DNSKEY generation defaults to ZONE\n");
+ fprintf(stderr, " -c <class> (default: IN)\n");
+ fprintf(stderr, " -f keyflag: KSK\n");
+ fprintf(stderr, " -t <type>: "
+ "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
+ "(default: AUTHCONF)\n");
+ fprintf(stderr, " -p <protocol>: "
+ "default: 3 [dnssec]\n");
+ fprintf(stderr, " -v <verbose level>\n");
+ fprintf(stderr, " -k : generate a TYPE=KEY key\n");
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, " K<name>+<alg>+<id>.key, "
+ "K<name>+<alg>+<id>.private\n");
+
+ exit (-1);
+}
+
+int
+main(int argc, char **argv) {
+ char *algname = NULL, *nametype = NULL, *type = NULL;
+ char *classname = NULL;
+ char *endp;
+ dst_key_t *key = NULL, *oldkey;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_uint16_t flags = 0, ksk = 0;
+ dns_secalg_t alg;
+ isc_boolean_t null_key = ISC_FALSE;
+ isc_mem_t *mctx = NULL;
+ int ch;
+ int protocol = -1, signatory = 0;
+ isc_result_t ret;
+ isc_textregion_t r;
+ char filename[255];
+ isc_buffer_t buf;
+ isc_log_t *log = NULL;
+ isc_entropy_t *ectx = NULL;
+ dns_rdataclass_t rdclass;
+ int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
+ char *label = NULL;
+
+ 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:c:f:kl:n:p:t:v:h")) != -1)
+ {
+ switch (ch) {
+ case 'a':
+ algname = isc_commandline_argument;
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'f':
+ if (strcasecmp(isc_commandline_argument, "KSK") == 0)
+ ksk = DNS_KEYFLAG_KSK;
+ else
+ fatal("unknown flag '%s'",
+ isc_commandline_argument);
+ break;
+ case 'k':
+ options |= DST_TYPE_KEY;
+ break;
+ case 'l':
+ label = isc_commandline_argument;
+ break;
+ case 'n':
+ nametype = isc_commandline_argument;
+ break;
+ case 'p':
+ protocol = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || protocol < 0 || protocol > 255)
+ fatal("-p must be followed by a number "
+ "[0..255]");
+ break;
+ case 't':
+ type = isc_commandline_argument;
+ 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);
+ case 'h':
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n",
+ program, isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ ret = dst_lib_init(mctx, ectx,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (ret != ISC_R_SUCCESS)
+ fatal("could not initialize dst");
+
+ setup_logging(verbose, mctx, &log);
+
+ if (label == NULL)
+ fatal("the key label was not specified");
+ 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 {
+ 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;
+ }
+
+ 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);
+ }
+ else if (strcasecmp(type, "AUTHCONF") == 0)
+ /* nothing */;
+ else
+ fatal("invalid type %s", type);
+ }
+
+ if (nametype == NULL) {
+ if ((options & DST_TYPE_KEY) != 0) /* KEY */
+ fatal("no nametype specified");
+ flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */
+ } else if (strcasecmp(nametype, "zone") == 0)
+ flags |= DNS_KEYOWNER_ZONE;
+ else if ((options & DST_TYPE_KEY) != 0) { /* KEY */
+ if (strcasecmp(nametype, "host") == 0 ||
+ strcasecmp(nametype, "entity") == 0)
+ flags |= DNS_KEYOWNER_ENTITY;
+ else if (strcasecmp(nametype, "user") == 0)
+ flags |= DNS_KEYOWNER_USER;
+ else
+ fatal("invalid KEY nametype %s", nametype);
+ } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */
+ fatal("invalid DNSKEY nametype %s", nametype);
+
+ rdclass = strtoclass(classname);
+
+ if ((options & DST_TYPE_KEY) != 0) /* KEY */
+ flags |= signatory;
+ else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
+ flags |= ksk;
+
+ if (protocol == -1)
+ protocol = DNS_KEYPROTO_DNSSEC;
+ else if ((options & DST_TYPE_KEY) == 0 &&
+ protocol != DNS_KEYPROTO_DNSSEC)
+ fatal("invalid DNSKEY protocol: %d", protocol);
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
+ if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0)
+ fatal("specified null key with signing authority");
+ }
+
+ if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
+ alg == DNS_KEYALG_DH)
+ 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));
+
+ 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);
+ isc_entropy_stopcallbacksources(ectx);
+
+ if (ret != ISC_R_SUCCESS) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char algstr[ALG_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ alg_format(alg, algstr, sizeof(algstr));
+ fatal("failed to generate key %s/%s: %s\n",
+ namestr, algstr, isc_result_totext(ret));
+ 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.
+ */
+ 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) {
+ 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_tofile(key, options, NULL);
+ if (ret != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(key, keystr, sizeof(keystr));
+ fatal("failed to write key %s: %s\n", keystr,
+ isc_result_totext(ret));
+ }
+
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ printf("%s\n", filename);
+ dst_key_free(&key);
+
+ cleanup_logging(&log);
+ cleanup_entropy(&ectx);
+ dst_lib_destroy();
+ dns_name_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-keyfromlabel.docbook b/bin/dnssec/dnssec-keyfromlabel.docbook
new file mode 100644
index 0000000..2bcf0a4
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.docbook
@@ -0,0 +1,265 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2008 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-keyfromlabel.docbook,v 1.6 2008/11/07 13:54:11 jreed Exp $ -->
+<refentry id="man.dnssec-keyfromlabel">
+ <refentryinfo>
+ <date>February 8, 2008</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-keyfromlabel</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-keyfromlabel</application></refname>
+ <refpurpose>DNSSEC key generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-keyfromlabel</command>
+ <arg choice="req">-a <replaceable class="parameter">algorithm</replaceable></arg>
+ <arg choice="req">-l <replaceable class="parameter">label</replaceable></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-f <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg><option>-k</option></arg>
+ <arg><option>-n <replaceable class="parameter">nametype</replaceable></option></arg>
+ <arg><option>-p <replaceable class="parameter">protocol</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="req">name</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dnssec-keyfromlabel</command>
+ 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.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ Selects the cryptographic algorithm. The value of
+ <option>algorithm</option> must be one of RSAMD5 (RSA)
+ or RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA or DH (Diffie Hellman).
+ These values are case insensitive.
+ </para>
+ <para>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended.
+ </para>
+ <para>
+ Note 2: DH automatically sets the -k flag.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">label</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the label of keys in the crypto hardware
+ (PKCS#11 device).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">nametype</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the owner type of the key. The value of
+ <option>nametype</option> 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-keygen</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k</term>
+ <listitem>
+ <para>
+ Generate KEY records rather than DNSKEY records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">protocol</replaceable></term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ Indicates the use of the key. <option>type</option> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>GENERATED KEY FILES</title>
+ <para>
+ When <command>dnssec-keyfromlabel</command> completes
+ successfully,
+ it prints a string of the form <filename>Knnnn.+aaa+iiiii</filename>
+ to the standard output. This is an identification string for
+ the key files it has generated.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><filename>nnnn</filename> is the key name.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>aaa</filename> is the numeric representation
+ of the
+ algorithm.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>iiiii</filename> is the key identifier (or
+ footprint).
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para><command>dnssec-keyfromlabel</command>
+ creates two files, with names based
+ on the printed string. <filename>Knnnn.+aaa+iiiii.key</filename>
+ contains the public key, and
+ <filename>Knnnn.+aaa+iiiii.private</filename> contains the
+ private
+ key.
+ </para>
+ <para>
+ The <filename>.key</filename> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </para>
+ <para>
+ The <filename>.private</filename> file contains algorithm
+ specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 2539</citetitle>,
+ <citetitle>RFC 2845</citetitle>,
+ <citetitle>RFC 4033</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dnssec/dnssec-keyfromlabel.html b/bin/dnssec/dnssec-keyfromlabel.html
new file mode 100644
index 0000000..cbea64b
--- /dev/null
+++ b/bin/dnssec/dnssec-keyfromlabel.html
@@ -0,0 +1,171 @@
+<!--
+ - Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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-keyfromlabel.html,v 1.5 2008/10/15 01:11:35 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-keyfromlabel</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.dnssec-keyfromlabel"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-keyfromlabel</span> &#8212; DNSSEC key generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-keyfromlabel</code> {-a <em class="replaceable"><code>algorithm</code></em>} {-l <em class="replaceable"><code>label</code></em>} [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-k</code>] [<code class="option">-n <em class="replaceable"><code>nametype</code></em></code>] [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] {name}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543413"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-keyfromlabel</strong></span>
+ 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.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543425"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+<p>
+ Selects the cryptographic algorithm. The value of
+ <code class="option">algorithm</code> must be one of RSAMD5 (RSA)
+ or RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA or DH (Diffie Hellman).
+ These values are case insensitive.
+ </p>
+<p>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended.
+ </p>
+<p>
+ Note 2: DH automatically sets the -k flag.
+ </p>
+</dd>
+<dt><span class="term">-l <em class="replaceable"><code>label</code></em></span></dt>
+<dd><p>
+ Specifies the label of keys in the crypto hardware
+ (PKCS#11 device).
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>nametype</code></em></span></dt>
+<dd><p>
+ Specifies the owner type of the key. The value of
+ <code class="option">nametype</code> 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.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </p></dd>
+<dt><span class="term">-f <em class="replaceable"><code>flag</code></em></span></dt>
+<dd><p>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">dnssec-keygen</strong></span>.
+ </p></dd>
+<dt><span class="term">-k</span></dt>
+<dd><p>
+ Generate KEY records rather than DNSKEY records.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>protocol</code></em></span></dt>
+<dd><p>
+ 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.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd><p>
+ Indicates the use of the key. <code class="option">type</code> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543619"></a><h2>GENERATED KEY FILES</h2>
+<p>
+ When <span><strong class="command">dnssec-keyfromlabel</strong></span> completes
+ successfully,
+ it prints a string of the form <code class="filename">Knnnn.+aaa+iiiii</code>
+ to the standard output. This is an identification string for
+ the key files it has generated.
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p><code class="filename">nnnn</code> is the key name.
+ </p></li>
+<li><p><code class="filename">aaa</code> is the numeric representation
+ of the
+ algorithm.
+ </p></li>
+<li><p><code class="filename">iiiii</code> is the key identifier (or
+ footprint).
+ </p></li>
+</ul></div>
+<p><span><strong class="command">dnssec-keyfromlabel</strong></span>
+ creates two files, with names based
+ on the printed string. <code class="filename">Knnnn.+aaa+iiiii.key</code>
+ contains the public key, and
+ <code class="filename">Knnnn.+aaa+iiiii.private</code> contains the
+ private
+ key.
+ </p>
+<p>
+ The <code class="filename">.key</code> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </p>
+<p>
+ The <code class="filename">.private</code> file contains algorithm
+ specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543691"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 2539</em>,
+ <em class="citetitle">RFC 2845</em>,
+ <em class="citetitle">RFC 4033</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543731"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-keygen.8 b/bin/dnssec/dnssec-keygen.8
new file mode 100644
index 0000000..13db3d9
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.8
@@ -0,0 +1,200 @@
+.\" Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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-keygen.8,v 1.40 2008/10/15 01:11:35 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: dnssec\-keygen
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: June 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "DNSSEC\-KEYGEN" "8" "June 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+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}
+.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.
+.SH "OPTIONS"
+.PP
+\-a \fIalgorithm\fR
+.RS 4
+Selects the cryptographic algorithm. The value of
+\fBalgorithm\fR
+must be one of RSAMD5 (RSA) or RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA, DH (Diffie Hellman), or HMAC\-MD5. These values are case insensitive.
+.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.
+.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. RSAMD5 / RSASHA1 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\-MD5 keys must be between 1 and 512 bits.
+.RE
+.PP
+\-n \fInametype\fR
+.RS 4
+Specifies the owner type of the key. The value of
+\fBnametype\fR
+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
+\-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
+.RS 4
+If generating an RSAMD5/RSASHA1 key, use a large exponent.
+.RE
+.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.
+.RE
+.PP
+\-g \fIgenerator\fR
+.RS 4
+If generating a Diffie Hellman key, use this generator. Allowed values are 2 and 5. If no generator is specified, a known prime from RFC 2539 will be used if possible; otherwise the default is 2.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of the options and arguments to
+\fBdnssec\-keygen\fR.
+.RE
+.PP
+\-k
+.RS 4
+Generate KEY records rather than DNSKEY records.
+.RE
+.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.
+.RE
+.PP
+\-r \fIrandomdev\fR
+.RS 4
+Specifies the source of randomness. 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 \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 \fItype\fR
+.RS 4
+Indicates the use of the key.
+\fBtype\fR
+must be one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default is AUTHCONF. AUTH refers to the ability to authenticate data, and CONF the ability to encrypt data.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level.
+.RE
+.SH "GENERATED KEYS"
+.PP
+When
+\fBdnssec\-keygen\fR
+completes successfully, it prints a string of the form
+\fIKnnnn.+aaa+iiiii\fR
+to the standard output. This is an identification string for the key it has generated.
+.TP 4
+\(bu
+\fInnnn\fR
+is the key name.
+.TP 4
+\(bu
+\fIaaa\fR
+is the numeric representation of the algorithm.
+.TP 4
+\(bu
+\fIiiiii\fR
+is the key identifier (or footprint).
+.PP
+\fBdnssec\-keygen\fR
+creates two files, with names based on the printed string.
+\fIKnnnn.+aaa+iiiii.key\fR
+contains the public key, and
+\fIKnnnn.+aaa+iiiii.private\fR
+contains the private key.
+.PP
+The
+\fI.key\fR
+file contains a DNS KEY record that can be inserted into a zone file (directly or with a $INCLUDE statement).
+.PP
+The
+\fI.private\fR
+file contains algorithm\-specific fields. For obvious security reasons, this file does not have general read permission.
+.PP
+Both
+\fI.key\fR
+and
+\fI.private\fR
+files are generated for symmetric encryption algorithms such as HMAC\-MD5, even though the public and private key are equivalent.
+.SH "EXAMPLE"
+.PP
+To generate a 768\-bit DSA key for the domain
+\fBexample.com\fR, the following command would be issued:
+.PP
+\fBdnssec\-keygen \-a DSA \-b 768 \-n ZONE example.com\fR
+.PP
+The command would print a string of the form:
+.PP
+\fBKexample.com.+003+26160\fR
+.PP
+In this example,
+\fBdnssec\-keygen\fR
+creates the files
+\fIKexample.com.+003+26160.key\fR
+and
+\fIKexample.com.+003+26160.private\fR.
+.SH "SEE ALSO"
+.PP
+\fBdnssec\-signzone\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 2539,
+RFC 2845,
+RFC 4033.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000\-2003 Internet Software Consortium.
+.br
diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c
new file mode 100644
index 0000000..614d388
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.c
@@ -0,0 +1,540 @@
+/*
+ * Portions Copyright (C) 2004-2008 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
+ * 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 AND NETWORK ASSOCIATES 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.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 AND NETWORK ASSOCIATES 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-keygen.c,v 1.81 2008/09/25 04:02:38 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+#define MAX_RSA 4096 /* should be long enough... */
+
+const char *program = "dnssec-keygen";
+int verbose;
+
+static const char *algs = "RSA | RSAMD5 | DH | DSA | RSASHA1 | NSEC3DSA |"
+ " NSEC3RSASHA1 | HMAC-MD5 |"
+ " HMAC-SHA1 | HMAC-SHA224 | HMAC-SHA256 |"
+ " HMAC-SHA384 | HMAC-SHA512";
+
+static isc_boolean_t
+dsa_size_ok(int size) {
+ return (ISC_TF(size >= 512 && size <= 1024 && size % 64 == 0));
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, " %s -a alg -b bits [-n type] [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, " 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, " 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 <class> (default: IN)\n");
+ fprintf(stderr, " -d <digest bits> (0 => max, default)\n");
+ fprintf(stderr, " -e use large exponent (RSAMD5/RSASHA1 only)\n");
+ fprintf(stderr, " -f keyflag: KSK\n");
+ fprintf(stderr, " -g <generator> use specified generator "
+ "(DH only)\n");
+ fprintf(stderr, " -t <type>: "
+ "AUTHCONF | NOAUTHCONF | NOAUTH | NOCONF "
+ "(default: AUTHCONF)\n");
+ fprintf(stderr, " -p <protocol>: "
+ "default: 3 [dnssec]\n");
+ fprintf(stderr, " -s <strength> strength value this key signs DNS "
+ "records with (default: 0)\n");
+ fprintf(stderr, " -r <randomdev>: a file containing random data\n");
+ fprintf(stderr, " -v <verbose level>\n");
+ fprintf(stderr, " -k : generate a TYPE=KEY key\n");
+ fprintf(stderr, "Output:\n");
+ fprintf(stderr, " K<name>+<alg>+<id>.key, "
+ "K<name>+<alg>+<id>.private\n");
+
+ exit (-1);
+}
+
+int
+main(int argc, char **argv) {
+ char *algname = NULL, *nametype = NULL, *type = NULL;
+ char *classname = NULL;
+ char *endp;
+ dst_key_t *key = NULL, *oldkey;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_uint16_t flags = 0, ksk = 0;
+ dns_secalg_t alg;
+ isc_boolean_t conflict = ISC_FALSE, null_key = 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];
+ isc_buffer_t buf;
+ isc_log_t *log = NULL;
+ isc_entropy_t *ectx = NULL;
+ dns_rdataclass_t rdclass;
+ int options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC;
+ int dbits = 0;
+
+ 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)
+ {
+ switch (ch) {
+ case 'a':
+ algname = isc_commandline_argument;
+ break;
+ case 'b':
+ size = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || size < 0)
+ fatal("-b requires a non-negative number");
+ break;
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'd':
+ dbits = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || dbits < 0)
+ fatal("-d requires a non-negative number");
+ break;
+ case 'e':
+ rsa_exp = 1;
+ break;
+ case 'f':
+ if (strcasecmp(isc_commandline_argument, "KSK") == 0)
+ ksk = DNS_KEYFLAG_KSK;
+ else
+ fatal("unknown flag '%s'",
+ isc_commandline_argument);
+ break;
+ case 'g':
+ generator = strtol(isc_commandline_argument,
+ &endp, 10);
+ if (*endp != '\0' || generator <= 0)
+ fatal("-g requires a positive number");
+ break;
+ case 'k':
+ options |= DST_TYPE_KEY;
+ break;
+ case 'n':
+ nametype = isc_commandline_argument;
+ break;
+ case 't':
+ type = isc_commandline_argument;
+ break;
+ case 'p':
+ protocol = strtol(isc_commandline_argument, &endp, 10);
+ if (*endp != '\0' || protocol < 0 || protocol > 255)
+ fatal("-p must be followed by a number "
+ "[0..255]");
+ break;
+ case 's':
+ signatory = strtol(isc_commandline_argument,
+ &endp, 10);
+ if (*endp != '\0' || signatory < 0 || signatory > 15)
+ fatal("-s must be followed by a number "
+ "[0..15]");
+ break;
+ case 'r':
+ setup_entropy(mctx, isc_commandline_argument, &ectx);
+ break;
+ case 'v':
+ endp = NULL;
+ 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);
+ case 'h':
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n",
+ program, isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ ret = dst_lib_init(mctx, ectx,
+ ISC_ENTROPY_BLOCKING | ISC_ENTROPY_GOODONLY);
+ if (ret != ISC_R_SUCCESS)
+ fatal("could not initialize dst");
+
+ 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 (ret != ISC_R_SUCCESS)
+ fatal("unknown algorithm %s", algname);
+ if (alg == DST_ALG_DH)
+ options |= DST_TYPE_KEY;
+ }
+
+ 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)
+ fatal("key size not specified (-b option)");
+
+ switch (alg) {
+ case DNS_KEYALG_RSAMD5:
+ case DNS_KEYALG_RSASHA1:
+ case DNS_KEYALG_NSEC3RSASHA1:
+ if (size != 0 && (size < 512 || size > MAX_RSA))
+ fatal("RSA key size %d out of range", size);
+ break;
+ case DNS_KEYALG_DH:
+ if (size != 0 && (size < 128 || size > 4096))
+ fatal("DH key size %d out of range", size);
+ break;
+ case DNS_KEYALG_DSA:
+ case DNS_KEYALG_NSEC3DSA:
+ if (size != 0 && !dsa_size_ok(size))
+ fatal("invalid DSS key size: %d", size);
+ break;
+ case DST_ALG_HMACMD5:
+ if (size < 1 || size > 512)
+ fatal("HMAC-MD5 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 80 || dbits > 128))
+ fatal("HMAC-MD5 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-MD5 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA1:
+ if (size < 1 || size > 160)
+ fatal("HMAC-SHA1 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 80 || dbits > 160))
+ fatal("HMAC-SHA1 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA1 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA224:
+ if (size < 1 || size > 224)
+ fatal("HMAC-SHA224 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 112 || dbits > 224))
+ fatal("HMAC-SHA224 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA224 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA256:
+ if (size < 1 || size > 256)
+ fatal("HMAC-SHA256 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 128 || dbits > 256))
+ fatal("HMAC-SHA256 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA256 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA384:
+ if (size < 1 || size > 384)
+ fatal("HMAC-384 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 192 || dbits > 384))
+ fatal("HMAC-SHA384 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA384 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ case DST_ALG_HMACSHA512:
+ if (size < 1 || size > 512)
+ fatal("HMAC-SHA512 key size %d out of range", size);
+ if (dbits != 0 && (dbits < 256 || dbits > 512))
+ fatal("HMAC-SHA512 digest bits %d out of range", dbits);
+ if ((dbits % 8) != 0)
+ fatal("HMAC-SHA512 digest bits %d not divisible by 8",
+ dbits);
+ break;
+ }
+
+ if (!(alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_RSASHA1 ||
+ alg == DNS_KEYALG_NSEC3RSASHA1) && rsa_exp != 0)
+ fatal("specified RSA exponent for a non-RSA key");
+
+ if (alg != DNS_KEYALG_DH && generator != 0)
+ fatal("specified DH generator for a non-DH key");
+
+ if (nametype == NULL) {
+ if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */
+ fatal("no nametype specified");
+ flags |= DNS_KEYOWNER_ZONE; /* DNSKEY */
+ } else if (strcasecmp(nametype, "zone") == 0)
+ flags |= DNS_KEYOWNER_ZONE;
+ else if ((options & DST_TYPE_KEY) != 0) { /* KEY / HMAC */
+ if (strcasecmp(nametype, "host") == 0 ||
+ strcasecmp(nametype, "entity") == 0)
+ flags |= DNS_KEYOWNER_ENTITY;
+ else if (strcasecmp(nametype, "user") == 0)
+ flags |= DNS_KEYOWNER_USER;
+ else
+ fatal("invalid KEY nametype %s", nametype);
+ } else if (strcasecmp(nametype, "other") != 0) /* DNSKEY */
+ fatal("invalid DNSKEY nametype %s", nametype);
+
+ rdclass = strtoclass(classname);
+
+ if ((options & DST_TYPE_KEY) != 0) /* KEY / HMAC */
+ flags |= signatory;
+ else if ((flags & DNS_KEYOWNER_ZONE) != 0) /* DNSKEY */
+ flags |= ksk;
+
+ if (protocol == -1)
+ protocol = DNS_KEYPROTO_DNSSEC;
+ else if ((options & DST_TYPE_KEY) == 0 &&
+ protocol != DNS_KEYPROTO_DNSSEC)
+ fatal("invalid DNSKEY protocol: %d", protocol);
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
+ if (size > 0)
+ fatal("specified null key with non-zero size");
+ if ((flags & DNS_KEYFLAG_SIGNATORYMASK) != 0)
+ fatal("specified null key with signing authority");
+ }
+
+ if ((flags & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE &&
+ (alg == DNS_KEYALG_DH || alg == DST_ALG_HMACMD5 ||
+ alg == DST_ALG_HMACSHA1 || alg == DST_ALG_HMACSHA224 ||
+ alg == DST_ALG_HMACSHA256 || alg == DST_ALG_HMACSHA384 ||
+ alg == DST_ALG_HMACSHA512))
+ 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:
+ param = rsa_exp;
+ break;
+ case DNS_KEYALG_DH:
+ param = generator;
+ break;
+ case DNS_KEYALG_DSA:
+ case DST_ALG_HMACMD5:
+ case DST_ALG_HMACSHA1:
+ case DST_ALG_HMACSHA224:
+ case DST_ALG_HMACSHA256:
+ case DST_ALG_HMACSHA384:
+ case DST_ALG_HMACSHA512:
+ param = 0;
+ break;
+ }
+
+ if ((flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY)
+ null_key = ISC_TRUE;
+
+ isc_buffer_init(&buf, filename, sizeof(filename) - 1);
+
+ do {
+ conflict = ISC_FALSE;
+ oldkey = NULL;
+
+ /* generate the key */
+ ret = dst_key_generate(name, alg, size, param, flags, protocol,
+ rdclass, mctx, &key);
+ isc_entropy_stopcallbacksources(ectx);
+
+ if (ret != ISC_R_SUCCESS) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char algstr[ALG_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ alg_format(alg, algstr, sizeof(algstr));
+ fatal("failed to generate key %s/%s: %s\n",
+ namestr, algstr, isc_result_totext(ret));
+ 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.
+ */
+ 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);
+ conflict = ISC_TRUE;
+ if (null_key)
+ break;
+ }
+ if (conflict == ISC_TRUE) {
+ if (verbose > 0) {
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ fprintf(stderr,
+ "%s: %s already exists, "
+ "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");
+
+ ret = dst_key_tofile(key, options, NULL);
+ if (ret != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(key, keystr, sizeof(keystr));
+ fatal("failed to write key %s: %s\n", keystr,
+ isc_result_totext(ret));
+ }
+
+ isc_buffer_clear(&buf);
+ ret = dst_key_buildfilename(key, 0, NULL, &buf);
+ printf("%s\n", filename);
+ dst_key_free(&key);
+
+ cleanup_logging(&log);
+ cleanup_entropy(&ectx);
+ dst_lib_destroy();
+ dns_name_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-keygen.docbook b/bin/dnssec/dnssec-keygen.docbook
new file mode 100644
index 0000000..c267a1b
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.docbook
@@ -0,0 +1,360 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007, 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
+ - 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-keygen.docbook,v 1.22 2008/10/14 14:32:50 jreed Exp $ -->
+<refentry id="man.dnssec-keygen">
+ <refentryinfo>
+ <date>June 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-keygen</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-keygen</application></refname>
+ <refpurpose>DNSSEC key generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-keygen</command>
+ <arg choice="req">-a <replaceable class="parameter">algorithm</replaceable></arg>
+ <arg choice="req">-b <replaceable class="parameter">keysize</replaceable></arg>
+ <arg choice="req">-n <replaceable class="parameter">nametype</replaceable></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-e</option></arg>
+ <arg><option>-f <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg><option>-g <replaceable class="parameter">generator</replaceable></option></arg>
+ <arg><option>-h</option></arg>
+ <arg><option>-k</option></arg>
+ <arg><option>-p <replaceable class="parameter">protocol</replaceable></option></arg>
+ <arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg><option>-s <replaceable class="parameter">strength</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg choice="req">name</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dnssec-keygen</command>
+ 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.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-a <replaceable class="parameter">algorithm</replaceable></term>
+ <listitem>
+ <para>
+ Selects the cryptographic algorithm. The value of
+ <option>algorithm</option> must be one of RSAMD5 (RSA) or RSASHA1,
+ DSA, NSEC3RSASHA1, NSEC3DSA, DH (Diffie Hellman), or HMAC-MD5.
+ These values are case insensitive.
+ </para>
+ <para>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is
+ mandatory.
+ </para>
+ <para>
+ Note 2: HMAC-MD5 and DH automatically set the -k flag.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-b <replaceable class="parameter">keysize</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the number of bits in the key. The choice of key
+ size depends on the algorithm used. RSAMD5 / RSASHA1 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-MD5 keys must be
+ between 1 and 512 bits.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">nametype</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the owner type of the key. The value of
+ <option>nametype</option> 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-e</term>
+ <listitem>
+ <para>
+ If generating an RSAMD5/RSASHA1 key, use a large exponent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g <replaceable class="parameter">generator</replaceable></term>
+ <listitem>
+ <para>
+ If generating a Diffie Hellman key, use this generator.
+ Allowed values are 2 and 5. If no generator
+ is specified, a known prime from RFC 2539 will be used
+ if possible; otherwise the default is 2.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-keygen</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k</term>
+ <listitem>
+ <para>
+ Generate KEY records rather than DNSKEY records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">protocol</replaceable></term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">randomdev</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the source of randomness. If the operating
+ system does not provide a <filename>/dev/random</filename>
+ or equivalent device, the default source of randomness
+ is keyboard input. <filename>randomdev</filename>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard
+ input should be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">strength</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the strength value of the key. The strength is
+ a number between 0 and 15, and currently has no defined
+ purpose in DNSSEC.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ Indicates the use of the key. <option>type</option> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>GENERATED KEYS</title>
+ <para>
+ When <command>dnssec-keygen</command> completes
+ successfully,
+ it prints a string of the form <filename>Knnnn.+aaa+iiiii</filename>
+ to the standard output. This is an identification string for
+ the key it has generated.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para><filename>nnnn</filename> is the key name.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>aaa</filename> is the numeric representation
+ of the
+ algorithm.
+ </para>
+ </listitem>
+ <listitem>
+ <para><filename>iiiii</filename> is the key identifier (or
+ footprint).
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para><command>dnssec-keygen</command>
+ creates two files, with names based
+ on the printed string. <filename>Knnnn.+aaa+iiiii.key</filename>
+ contains the public key, and
+ <filename>Knnnn.+aaa+iiiii.private</filename> contains the
+ private
+ key.
+ </para>
+ <para>
+ The <filename>.key</filename> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </para>
+ <para>
+ The <filename>.private</filename> file contains
+ algorithm-specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </para>
+ <para>
+ Both <filename>.key</filename> and <filename>.private</filename>
+ files are generated for symmetric encryption algorithms such as
+ HMAC-MD5, even though the public and private key are equivalent.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLE</title>
+ <para>
+ To generate a 768-bit DSA key for the domain
+ <userinput>example.com</userinput>, the following command would be
+ issued:
+ </para>
+ <para><userinput>dnssec-keygen -a DSA -b 768 -n ZONE example.com</userinput>
+ </para>
+ <para>
+ The command would print a string of the form:
+ </para>
+ <para><userinput>Kexample.com.+003+26160</userinput>
+ </para>
+ <para>
+ In this example, <command>dnssec-keygen</command> creates
+ the files <filename>Kexample.com.+003+26160.key</filename>
+ and
+ <filename>Kexample.com.+003+26160.private</filename>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dnssec-signzone</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 2539</citetitle>,
+ <citetitle>RFC 2845</citetitle>,
+ <citetitle>RFC 4033</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dnssec/dnssec-keygen.html b/bin/dnssec/dnssec-keygen.html
new file mode 100644
index 0000000..696ef88
--- /dev/null
+++ b/bin/dnssec/dnssec-keygen.html
@@ -0,0 +1,232 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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-keygen.html,v 1.32 2008/10/15 01:11:35 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-keygen</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.dnssec-keygen"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-keygen</span> &#8212; DNSSEC key generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-keygen</code> {-a <em class="replaceable"><code>algorithm</code></em>} {-b <em class="replaceable"><code>keysize</code></em>} {-n <em class="replaceable"><code>nametype</code></em>} [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-e</code>] [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-g <em class="replaceable"><code>generator</code></em></code>] [<code class="option">-h</code>] [<code class="option">-k</code>] [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>] [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-s <em class="replaceable"><code>strength</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] {name}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543477"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-keygen</strong></span>
+ 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.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543489"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+<p>
+ Selects the cryptographic algorithm. The value of
+ <code class="option">algorithm</code> must be one of RSAMD5 (RSA) or RSASHA1,
+ DSA, NSEC3RSASHA1, NSEC3DSA, DH (Diffie Hellman), or HMAC-MD5.
+ These values are case insensitive.
+ </p>
+<p>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is
+ mandatory.
+ </p>
+<p>
+ Note 2: HMAC-MD5 and DH automatically set the -k flag.
+ </p>
+</dd>
+<dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt>
+<dd><p>
+ Specifies the number of bits in the key. The choice of key
+ size depends on the algorithm used. RSAMD5 / RSASHA1 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-MD5 keys must be
+ between 1 and 512 bits.
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>nametype</code></em></span></dt>
+<dd><p>
+ Specifies the owner type of the key. The value of
+ <code class="option">nametype</code> 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.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </p></dd>
+<dt><span class="term">-e</span></dt>
+<dd><p>
+ If generating an RSAMD5/RSASHA1 key, use a large exponent.
+ </p></dd>
+<dt><span class="term">-f <em class="replaceable"><code>flag</code></em></span></dt>
+<dd><p>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ </p></dd>
+<dt><span class="term">-g <em class="replaceable"><code>generator</code></em></span></dt>
+<dd><p>
+ If generating a Diffie Hellman key, use this generator.
+ Allowed values are 2 and 5. If no generator
+ is specified, a known prime from RFC 2539 will be used
+ if possible; otherwise the default is 2.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">dnssec-keygen</strong></span>.
+ </p></dd>
+<dt><span class="term">-k</span></dt>
+<dd><p>
+ Generate KEY records rather than DNSKEY records.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>protocol</code></em></span></dt>
+<dd><p>
+ 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.
+ </p></dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomdev</code></em></span></dt>
+<dd><p>
+ Specifies the source of randomness. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>strength</code></em></span></dt>
+<dd><p>
+ Specifies the strength value of the key. The strength is
+ a number between 0 and 15, and currently has no defined
+ purpose in DNSSEC.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd><p>
+ Indicates the use of the key. <code class="option">type</code> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543824"></a><h2>GENERATED KEYS</h2>
+<p>
+ When <span><strong class="command">dnssec-keygen</strong></span> completes
+ successfully,
+ it prints a string of the form <code class="filename">Knnnn.+aaa+iiiii</code>
+ to the standard output. This is an identification string for
+ the key it has generated.
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p><code class="filename">nnnn</code> is the key name.
+ </p></li>
+<li><p><code class="filename">aaa</code> is the numeric representation
+ of the
+ algorithm.
+ </p></li>
+<li><p><code class="filename">iiiii</code> is the key identifier (or
+ footprint).
+ </p></li>
+</ul></div>
+<p><span><strong class="command">dnssec-keygen</strong></span>
+ creates two files, with names based
+ on the printed string. <code class="filename">Knnnn.+aaa+iiiii.key</code>
+ contains the public key, and
+ <code class="filename">Knnnn.+aaa+iiiii.private</code> contains the
+ private
+ key.
+ </p>
+<p>
+ The <code class="filename">.key</code> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </p>
+<p>
+ The <code class="filename">.private</code> file contains
+ algorithm-specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </p>
+<p>
+ Both <code class="filename">.key</code> and <code class="filename">.private</code>
+ files are generated for symmetric encryption algorithms such as
+ HMAC-MD5, even though the public and private key are equivalent.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543906"></a><h2>EXAMPLE</h2>
+<p>
+ To generate a 768-bit DSA key for the domain
+ <strong class="userinput"><code>example.com</code></strong>, the following command would be
+ issued:
+ </p>
+<p><strong class="userinput"><code>dnssec-keygen -a DSA -b 768 -n ZONE example.com</code></strong>
+ </p>
+<p>
+ The command would print a string of the form:
+ </p>
+<p><strong class="userinput"><code>Kexample.com.+003+26160</code></strong>
+ </p>
+<p>
+ In this example, <span><strong class="command">dnssec-keygen</strong></span> creates
+ the files <code class="filename">Kexample.com.+003+26160.key</code>
+ and
+ <code class="filename">Kexample.com.+003+26160.private</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543949"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 2539</em>,
+ <em class="citetitle">RFC 2845</em>,
+ <em class="citetitle">RFC 4033</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544049"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssec-signzone.8 b/bin/dnssec/dnssec-signzone.8
new file mode 100644
index 0000000..ca0ed36
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.8
@@ -0,0 +1,287 @@
+.\" Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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-signzone.8,v 1.47 2008/10/15 01:11:35 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: dnssec\-signzone
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: June 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "DNSSEC\-SIGNZONE" "8" "June 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+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\-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...]
+.SH "DESCRIPTION"
+.PP
+\fBdnssec\-signzone\fR
+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
+.RS 4
+Verify all generated signatures.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+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
+.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
+\-d \fIdirectory\fR
+.RS 4
+Look for
+\fIkeyset\fR
+files in
+\fBdirectory\fR
+as the directory
+.RE
+.PP
+\-g
+.RS 4
+Generate DS records for child zones from keyset files. Existing DS records will be removed.
+.RE
+.PP
+\-s \fIstart\-time\fR
+.RS 4
+Specify the date and time when the generated RRSIG records become valid. This can be either an absolute or relative time. An absolute start time is indicated by a number in YYYYMMDDHHMMSS notation; 20000530144500 denotes 14:45:00 UTC on May 30th, 2000. A relative start time is indicated by +N, which is N seconds from the current time. If no
+\fBstart\-time\fR
+is specified, the current time minus 1 hour (to allow for clock skew) is used.
+.RE
+.PP
+\-e \fIend\-time\fR
+.RS 4
+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.
+.RE
+.PP
+\-f \fIoutput\-file\fR
+.RS 4
+The name of the output file containing the signed zone. The default is to append
+\fI.signed\fR
+to the input filename.
+.RE
+.PP
+\-h
+.RS 4
+Prints a short summary of the options and arguments to
+\fBdnssec\-signzone\fR.
+.RE
+.PP
+\-i \fIinterval\fR
+.RS 4
+When a previously\-signed zone is passed as input, records may be resigned. The
+\fBinterval\fR
+option specifies the cycle interval as an offset from the current time (in seconds). If a RRSIG record expires after the cycle interval, it is retained. Otherwise, it is considered to be expiring soon, and it will be replaced.
+.sp
+The default cycle interval is one quarter of the difference between the signature end and start times. So if neither
+\fBend\-time\fR
+or
+\fBstart\-time\fR
+are specified,
+\fBdnssec\-signzone\fR
+generates signatures that are valid for 30 days, with a cycle interval of 7.5 days. Therefore, if any existing RRSIG records are due to expire in less than 7.5 days, they would be replaced.
+.RE
+.PP
+\-I \fIinput\-format\fR
+.RS 4
+The format of the input zone file. Possible formats are
+\fB"text"\fR
+(default) and
+\fB"raw"\fR. This option is primarily intended to be used for dynamic signed zones so that the dumped zone file in a non\-text format containing updates can be signed directly. The use of this option does not make much sense for non\-dynamic zones.
+.RE
+.PP
+\-j \fIjitter\fR
+.RS 4
+When signing a zone with a fixed signature lifetime, all RRSIG records issued at the time of signing expires simultaneously. If the zone is incrementally signed, i.e. a previously\-signed zone is passed as input to the signer, all expired signatures have to be regenerated at about the same time. The
+\fBjitter\fR
+option specifies a jitter window that will be used to randomize the signature expire time, thus spreading incremental signature regeneration over time.
+.sp
+Signature lifetime jitter also to some extent benefits validators and servers by spreading out cache expiration, i.e. if large numbers of RRSIGs don't expire at the same time from all caches there will be less congestion than if all validators need to refetch at mostly the same time.
+.RE
+.PP
+\-n \fIncpus\fR
+.RS 4
+Specifies the number of threads to use. By default, one thread is started for each detected CPU.
+.RE
+.PP
+\-N \fIsoa\-serial\-format\fR
+.RS 4
+The SOA serial number format of the signed zone. Possible formats are
+\fB"keep"\fR
+(default),
+\fB"increment"\fR
+and
+\fB"unixtime"\fR.
+.RS 4
+.PP
+\fB"keep"\fR
+.RS 4
+Do not modify the SOA serial number.
+.RE
+.PP
+\fB"increment"\fR
+.RS 4
+Increment the SOA serial number using RFC 1982 arithmetics.
+.RE
+.PP
+\fB"unixtime"\fR
+.RS 4
+Set the SOA serial number to the number of seconds since epoch.
+.RE
+.RE
+.RE
+.PP
+\-o \fIorigin\fR
+.RS 4
+The zone origin. If not specified, the name of the zone file is assumed to be the origin.
+.RE
+.PP
+\-O \fIoutput\-format\fR
+.RS 4
+The format of the output file containing the signed zone. Possible formats are
+\fB"text"\fR
+(default) and
+\fB"raw"\fR.
+.RE
+.PP
+\-p
+.RS 4
+Use pseudo\-random data when signing the zone. This is faster, but less secure, than using real random data. This option may be useful when signing large zones or when the entropy source is limited.
+.RE
+.PP
+\-r \fIrandomdev\fR
+.RS 4
+Specifies the source of randomness. 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
+\-t
+.RS 4
+Print statistics at completion.
+.RE
+.PP
+\-v \fIlevel\fR
+.RS 4
+Sets the debugging level.
+.RE
+.PP
+\-z
+.RS 4
+Ignore KSK flag on key when determining what to sign.
+.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.
+.RE
+.PP
+\-H \fIiterations\fR
+.RS 4
+When generating a NSEC3 chain use this many interations. The default is 100.
+.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.
+.RE
+.PP
+zonefile
+.RS 4
+The file containing the zone to be signed.
+.RE
+.PP
+key
+.RS 4
+Specify which keys should be used to sign the zone. If no keys are specified, then the zone will be examined for DNSKEY records at the zone apex. If these are found and there are matching private keys, in the current directory, then these will be used for signing.
+.RE
+.SH "EXAMPLE"
+.PP
+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).
+.sp
+.RS 4
+.nf
+% dnssec\-signzone \-g \-o example.com db.example.com \\
+Kexample.com.+003+17247
+db.example.com.signed
+%
+.fi
+.RE
+.PP
+In the above example,
+\fBdnssec\-signzone\fR
+creates the file
+\fIdb.example.com.signed\fR. This file should be referenced in a zone statement in a
+\fInamed.conf\fR
+file.
+.PP
+This example re\-signs a previously signed zone with default parameters. The private keys are assumed to be in the current directory.
+.sp
+.RS 4
+.nf
+% cp db.example.com.signed db.example.com
+% dnssec\-signzone \-o example.com db.example.com
+db.example.com.signed
+%
+.fi
+.RE
+.SH "SEE ALSO"
+.PP
+\fBdnssec\-keygen\fR(8),
+BIND 9 Administrator Reference Manual,
+RFC 4033.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2004\-2008 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000\-2003 Internet Software Consortium.
+.br
diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c
new file mode 100644
index 0000000..f446ef3
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.c
@@ -0,0 +1,3031 @@
+/*
+ * Portions Copyright (C) 2004-2008 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
+ * 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 AND NETWORK ASSOCIATES 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.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 AND NETWORK ASSOCIATES 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-signzone.c,v 1.209 2008/11/14 22:53:46 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <time.h>
+
+#include <isc/app.h>
+#include <isc/base32.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/event.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/hex.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/os.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/serial.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/diff.h>
+#include <dns/dnssec.h>
+#include <dns/ds.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/soa.h>
+#include <dns/time.h>
+
+#include <dst/dst.h>
+
+#include "dnssectool.h"
+
+const char *program = "dnssec-signzone";
+int verbose;
+
+typedef struct hashlist hashlist_t;
+
+static int nsec_datatype = dns_rdatatype_nsec;
+
+#define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
+#define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 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;
+ 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)
+
+#define SOA_SERIAL_KEEP 0
+#define SOA_SERIAL_INCREMENT 1
+#define SOA_SERIAL_UNIXTIME 2
+
+typedef struct signer_event sevent_t;
+struct signer_event {
+ ISC_EVENT_COMMON(sevent_t);
+ dns_fixedname_t *fname;
+ dns_dbnode_t *node;
+};
+
+static ISC_LIST(signer_key_t) keylist;
+static unsigned int keycount = 0;
+static isc_stdtime_t starttime = 0, endtime = 0, now;
+static int cycle = -1;
+static int jitter = 0;
+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 FILE *fp;
+static char *tempfile = NULL;
+static const dns_master_style_t *masterstyle;
+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 isc_mutex_t namelock, statslock;
+static isc_taskmgr_t *taskmgr = NULL;
+static dns_db_t *gdb; /* The database */
+static dns_dbversion_t *gversion; /* The database version */
+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 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 dns_name_t *dlv = NULL;
+static dns_fixedname_t dlv_fixed;
+static dns_master_style_t *dsstyle = NULL;
+static unsigned int serialformat = SOA_SERIAL_KEEP;
+static unsigned int hash_length = 0;
+static isc_boolean_t unknownalg = ISC_FALSE;
+
+#define INCSTAT(counter) \
+ if (printstats) { \
+ LOCK(&statslock); \
+ counter++; \
+ UNLOCK(&statslock); \
+ }
+
+static void
+sign(isc_task_t *task, isc_event_t *event);
+
+static isc_boolean_t
+nsec3only(dns_dbnode_t *node);
+
+static void
+dumpnode(dns_name_t *name, dns_dbnode_t *node) {
+ isc_result_t result;
+
+ if (outputformat != dns_masterformat_text)
+ return;
+ result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
+ masterstyle, fp);
+ 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->position = keycount++;
+ ISC_LINK_INIT(key, link);
+ return (key);
+}
+
+static void
+signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdata_t *rdata,
+ dst_key_t *key, isc_buffer_t *b)
+{
+ isc_result_t result;
+ isc_stdtime_t jendtime;
+
+ jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
+ result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
+ mctx, b, rdata);
+ isc_entropy_stopcallbacksources(ectx);
+ if (result != ISC_R_SUCCESS) {
+ char keystr[KEY_FORMATSIZE];
+ key_format(key, keystr, sizeof(keystr));
+ fatal("dnskey '%s' failed to sign data: %s",
+ keystr, isc_result_totext(result));
+ }
+ INCSTAT(nsigned);
+
+ if (tryverify) {
+ result = dns_dnssec_verify(name, rdataset, key,
+ ISC_TRUE, mctx, rdata);
+ if (result == ISC_R_SUCCESS) {
+ vbprintf(3, "\tsignature verified\n");
+ INCSTAT(nverified);
+ } else {
+ vbprintf(3, "\tsignature failed to verify\n");
+ INCSTAT(nverifyfailed);
+ }
+ }
+}
+
+static inline isc_boolean_t
+issigningkey(signer_key_t *key) {
+ return (key->issigningkey);
+}
+
+static inline isc_boolean_t
+iszonekey(signer_key_t *key) {
+ return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
+ dst_key_iszonekey(key->key)));
+}
+
+/*%
+ * 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 *
+keythatsigned(dns_rdata_rrsig_t *rrsig) {
+ isc_result_t result;
+ dst_key_t *pubkey = NULL, *privkey = NULL;
+ signer_key_t *key;
+
+ key = ISC_LIST_HEAD(keylist);
+ while (key != NULL) {
+ 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);
+ }
+
+ result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
+ rrsig->algorithm, DST_TYPE_PUBLIC,
+ NULL, mctx, &pubkey);
+ if (result != ISC_R_SUCCESS)
+ return (NULL);
+
+ result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
+ rrsig->algorithm,
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ NULL, mctx, &privkey);
+ if (result == ISC_R_SUCCESS) {
+ dst_key_free(&pubkey);
+ key = newkeystruct(privkey, ISC_FALSE);
+ } else
+ key = newkeystruct(pubkey, ISC_FALSE);
+ ISC_LIST_APPEND(keylist, key, link);
+ return (key);
+}
+
+/*%
+ * Check to see if we expect to find a key at this name. If we see a RRSIG
+ * and can't find the signing key that we expect to find, we drop the rrsig.
+ * I'm not sure if this is completely correct, but it seems to work.
+ */
+static isc_boolean_t
+expecttofindkey(dns_name_t *name) {
+ unsigned int options = DNS_DBFIND_NOWILD;
+ dns_fixedname_t fname;
+ isc_result_t result;
+ char namestr[DNS_NAME_FORMATSIZE];
+
+ dns_fixedname_init(&fname);
+ result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
+ 0, NULL, dns_fixedname_name(&fname), NULL, NULL);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_NXDOMAIN:
+ case DNS_R_NXRRSET:
+ return (ISC_TRUE);
+ case DNS_R_DELEGATION:
+ case DNS_R_CNAME:
+ case DNS_R_DNAME:
+ return (ISC_FALSE);
+ }
+ dns_name_format(name, namestr, sizeof(namestr));
+ fatal("failure looking for '%s DNSKEY' in database: %s",
+ namestr, isc_result_totext(result));
+ return (ISC_FALSE); /* removes a warning */
+}
+
+static inline isc_boolean_t
+setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
+ dns_rdata_t *rrsig)
+{
+ isc_result_t result;
+ result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, rrsig);
+ if (result == ISC_R_SUCCESS) {
+ INCSTAT(nverified);
+ return (ISC_TRUE);
+ } else {
+ INCSTAT(nverifyfailed);
+ return (ISC_FALSE);
+ }
+}
+
+/*%
+ * Signs a set. Goes through contortions to decide if each RRSIG should
+ * be dropped or retained, and then determines if any new SIGs need to
+ * be generated.
+ */
+static void
+signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
+ dns_rdataset_t *set)
+{
+ dns_rdataset_t sigset;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t rrsig;
+ signer_key_t *key;
+ isc_result_t result;
+ isc_boolean_t nosigs = ISC_FALSE;
+ isc_boolean_t *wassignedby, *nowsignedby;
+ int arraysize;
+ dns_difftuple_t *tuple;
+ dns_ttl_t ttl;
+ int i;
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[TYPE_FORMATSIZE];
+ char sigstr[SIG_FORMATSIZE];
+
+ dns_name_format(name, namestr, sizeof(namestr));
+ type_format(set->type, typestr, sizeof(typestr));
+
+ ttl = ISC_MIN(set->ttl, endtime - starttime);
+
+ dns_rdataset_init(&sigset);
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
+ set->type, 0, &sigset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ nosigs = ISC_TRUE;
+ }
+ if (result != ISC_R_SUCCESS)
+ fatal("failed while looking for '%s RRSIG %s': %s",
+ namestr, typestr, isc_result_totext(result));
+
+ vbprintf(1, "%s/%s:\n", namestr, typestr);
+
+ arraysize = keycount;
+ if (!nosigs)
+ arraysize += dns_rdataset_count(&sigset);
+ wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
+ nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
+ if (wassignedby == NULL || nowsignedby == NULL)
+ fatal("out of memory");
+
+ for (i = 0; i < arraysize; i++)
+ wassignedby[i] = nowsignedby[i] = ISC_FALSE;
+
+ if (nosigs)
+ result = ISC_R_NOMORE;
+ else
+ result = dns_rdataset_first(&sigset);
+
+ while (result == ISC_R_SUCCESS) {
+ isc_boolean_t expired, future;
+ isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
+
+ dns_rdataset_current(&sigset, &sigrdata);
+
+ result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ future = isc_serial_lt(now, rrsig.timesigned);
+
+ key = keythatsigned(&rrsig);
+ sig_format(&rrsig, sigstr, sizeof(sigstr));
+ if (key != NULL && issigningkey(key))
+ expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
+ else
+ expired = isc_serial_gt(now, rrsig.timeexpire);
+
+ if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
+ /* rrsig is dropped and not replaced */
+ vbprintf(2, "\trrsig by %s dropped - "
+ "invalid validity period\n",
+ sigstr);
+ } else if (key == NULL && !future &&
+ expecttofindkey(&rrsig.signer))
+ {
+ /* rrsig is dropped and not replaced */
+ vbprintf(2, "\trrsig by %s dropped - "
+ "private dnskey not found\n",
+ sigstr);
+ } else if (key == NULL || future) {
+ vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
+ expired ? "retained" : "dropped", sigstr);
+ if (!expired)
+ keep = ISC_TRUE;
+ } else if (issigningkey(key)) {
+ if (!expired && setverifies(name, set, key, &sigrdata))
+ {
+ vbprintf(2, "\trrsig by %s retained\n", sigstr);
+ keep = ISC_TRUE;
+ wassignedby[key->position] = ISC_TRUE;
+ nowsignedby[key->position] = ISC_TRUE;
+ } else {
+ vbprintf(2, "\trrsig by %s dropped - %s\n",
+ sigstr,
+ expired ? "expired" :
+ "failed to verify");
+ wassignedby[key->position] = ISC_TRUE;
+ resign = ISC_TRUE;
+ }
+ } else if (iszonekey(key)) {
+ if (!expired && setverifies(name, set, key, &sigrdata))
+ {
+ vbprintf(2, "\trrsig by %s retained\n", sigstr);
+ keep = ISC_TRUE;
+ wassignedby[key->position] = ISC_TRUE;
+ nowsignedby[key->position] = ISC_TRUE;
+ } else {
+ vbprintf(2, "\trrsig by %s dropped - %s\n",
+ sigstr,
+ expired ? "expired" :
+ "failed to verify");
+ wassignedby[key->position] = ISC_TRUE;
+ }
+ } else if (!expired) {
+ vbprintf(2, "\trrsig by %s retained\n", sigstr);
+ keep = ISC_TRUE;
+ } else {
+ vbprintf(2, "\trrsig by %s expired\n", sigstr);
+ }
+
+ if (keep) {
+ nowsignedby[key->position] = ISC_TRUE;
+ INCSTAT(nretained);
+ if (sigset.ttl != ttl) {
+ vbprintf(2, "\tfixing ttl %s\n", sigstr);
+ tuple = NULL;
+ result = dns_difftuple_create(mctx,
+ DNS_DIFFOP_DEL,
+ name, sigset.ttl,
+ &sigrdata,
+ &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(del, &tuple);
+ result = dns_difftuple_create(mctx,
+ DNS_DIFFOP_ADD,
+ name, ttl,
+ &sigrdata,
+ &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(add, &tuple);
+ }
+ } else {
+ tuple = NULL;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
+ name, sigset.ttl,
+ &sigrdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(del, &tuple);
+ INCSTAT(ndropped);
+ }
+
+ if (resign) {
+ isc_buffer_t b;
+ dns_rdata_t trdata = DNS_RDATA_INIT;
+ unsigned char array[BUFSIZE];
+ char keystr[KEY_FORMATSIZE];
+
+ INSIST(!keep);
+
+ key_format(key->key, keystr, sizeof(keystr));
+ vbprintf(1, "\tresigning with dnskey %s\n", keystr);
+ isc_buffer_init(&b, array, sizeof(array));
+ signwithkey(name, set, &trdata, key->key, &b);
+ nowsignedby[key->position] = ISC_TRUE;
+ tuple = NULL;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ name, ttl, &trdata,
+ &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(add, &tuple);
+ }
+
+ dns_rdata_reset(&sigrdata);
+ dns_rdata_freestruct(&rrsig);
+ result = dns_rdataset_next(&sigset);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ check_result(result, "dns_rdataset_first/next");
+ if (dns_rdataset_isassociated(&sigset))
+ dns_rdataset_disassociate(&sigset);
+
+ for (key = ISC_LIST_HEAD(keylist);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ isc_buffer_t b;
+ dns_rdata_t trdata;
+ unsigned char array[BUFSIZE];
+ char keystr[KEY_FORMATSIZE];
+
+ if (nowsignedby[key->position])
+ continue;
+
+ if (!key->issigningkey)
+ continue;
+ if (!(ignoreksk || key->isdsk ||
+ (key->isksk &&
+ set->type == dns_rdatatype_dnskey &&
+ dns_name_equal(name, gorigin))))
+ continue;
+
+ key_format(key->key, keystr, sizeof(keystr));
+ vbprintf(1, "\tsigning with dnskey %s\n", keystr);
+ dns_rdata_init(&trdata);
+ isc_buffer_init(&b, array, sizeof(array));
+ signwithkey(name, set, &trdata, key->key, &b);
+ tuple = NULL;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
+ ttl, &trdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(add, &tuple);
+ }
+
+ isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
+ isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
+}
+
+struct hashlist {
+ unsigned char *hashbuf;
+ size_t entries;
+ size_t size;
+ size_t length;
+};
+
+static void
+hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
+
+ l->entries = 0;
+ l->length = length + 1;
+
+ if (nodes != 0) {
+ l->size = nodes;
+ l->hashbuf = malloc(l->size * l->length);
+ if (l->hashbuf == NULL)
+ l->size = 0;
+ } else {
+ l->size = 0;
+ l->hashbuf = NULL;
+ }
+}
+
+static void
+hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
+{
+
+ REQUIRE(len <= l->length);
+
+ if (l->entries == l->size) {
+ l->size = l->size * 2 + 100;
+ l->hashbuf = realloc(l->hashbuf, l->size * l->length);
+ }
+ memset(l->hashbuf + l->entries * l->length, 0, l->length);
+ memcpy(l->hashbuf + l->entries * l->length, hash, len);
+ l->entries++;
+}
+
+static void
+hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
+ unsigned int hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length,
+ isc_boolean_t speculative)
+{
+ char nametext[DNS_NAME_FORMATSIZE];
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
+ unsigned int len;
+ size_t i;
+
+ len = isc_iterated_hash(hash, hashalg, iterations, salt, salt_length,
+ name->ndata, name->length);
+ if (verbose) {
+ dns_name_format(name, nametext, sizeof nametext);
+ for (i = 0 ; i < len; i++)
+ fprintf(stderr, "%02x", hash[i]);
+ fprintf(stderr, " %s\n", nametext);
+ }
+ hash[len++] = speculative ? 1 : 0;
+ hashlist_add(l, hash, len);
+}
+
+static int
+hashlist_comp(const void *a, const void *b) {
+ return (memcmp(a, b, hash_length + 1));
+}
+
+static void
+hashlist_sort(hashlist_t *l) {
+ qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
+}
+
+static isc_boolean_t
+hashlist_hasdup(hashlist_t *l) {
+ unsigned char *current;
+ unsigned char *next = l->hashbuf;
+ size_t entries = l->entries;
+
+ /*
+ * Skip initial speculative wild card hashs.
+ */
+ while (entries > 0U && next[l->length-1] != 0U) {
+ next += l->length;
+ entries--;
+ }
+
+ current = next;
+ while (entries-- > 1U) {
+ next += l->length;
+ if (next[l->length-1] != 0)
+ continue;
+ if (memcmp(current, next, l->length - 1) == 0)
+ return (ISC_TRUE);
+ current = next;
+ }
+ return (ISC_FALSE);
+}
+
+static const unsigned char *
+hashlist_findnext(const hashlist_t *l,
+ const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
+{
+ unsigned int entries = l->entries;
+ const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
+ l->length, hashlist_comp);
+ INSIST(next != NULL);
+
+ do {
+ if (next < l->hashbuf + (l->entries - 1) * l->length)
+ next += l->length;
+ else
+ next = l->hashbuf;
+ if (next[l->length - 1] == 0)
+ break;
+ } while (entries-- > 1);
+ INSIST(entries != 0);
+ return (next);
+}
+
+static isc_boolean_t
+hashlist_exists(const hashlist_t *l,
+ const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
+{
+ if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+static void
+addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
+ unsigned int hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length)
+{
+ dns_fixedname_t fixed;
+ dns_name_t *wild;
+ dns_dbnode_t *node = NULL;
+ isc_result_t result;
+ char namestr[DNS_NAME_FORMATSIZE];
+
+ dns_fixedname_init(&fixed);
+ wild = dns_fixedname_name(&fixed);
+
+ result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
+ if (result == ISC_R_NOSPACE)
+ return;
+ check_result(result,"addnowildcardhash: dns_name_concatenate()");
+
+ result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
+ if (result == ISC_R_SUCCESS) {
+ dns_db_detachnode(gdb, &node);
+ return;
+ }
+
+ if (verbose) {
+ dns_name_format(wild, namestr, sizeof(namestr));
+ fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
+ }
+
+ hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_length,
+ ISC_TRUE);
+}
+
+static void
+opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
+ dns_db_t **dbp)
+{
+ char filename[256];
+ 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] != '/')
+ isc_buffer_putstr(&b, "/");
+ }
+ isc_buffer_putstr(&b, prefix);
+ result = dns_name_tofilenametext(name, ISC_FALSE, &b);
+ check_result(result, "dns_name_tofilenametext()");
+ if (isc_buffer_availablelength(&b) == 0) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ fatal("name '%s' is too long", namestr);
+ }
+ isc_buffer_putuint8(&b, 0);
+
+ result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
+ rdclass, 0, NULL, dbp);
+ check_result(result, "dns_db_create()");
+
+ result = dns_db_load(*dbp, filename);
+ 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.
+ */
+static isc_result_t
+loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
+ dns_db_t *db = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_dbnode_t *node = NULL;
+ isc_result_t result;
+ dns_rdataset_t keyset;
+ dns_rdata_t key, ds;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+ dns_diff_t diff;
+ dns_difftuple_t *tuple = NULL;
+
+ opendb("keyset-", name, gclass, &db);
+ 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);
+ }
+ dns_rdataset_init(&keyset);
+ 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);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&keyset))
+ {
+ dns_rdata_init(&key);
+ dns_rdata_init(&ds);
+ dns_rdataset_current(&keyset, &key);
+ result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
+ ttl, &ds, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+
+ dns_rdata_reset(&ds);
+ result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
+ ttl, &ds, &tuple);
+ 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);
+
+ dns_db_closeversion(db, &ver, ISC_TRUE);
+
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
+ dsset, NULL);
+ check_result(result, "dns_db_findrdataset");
+
+ dns_rdataset_disassociate(&keyset);
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ return (result);
+}
+
+static isc_boolean_t
+delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
+ dns_rdataset_t nsset;
+ isc_result_t result;
+
+ if (dns_name_equal(name, gorigin))
+ return (ISC_FALSE);
+
+ dns_rdataset_init(&nsset);
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
+ 0, 0, &nsset, NULL);
+ if (dns_rdataset_isassociated(&nsset)) {
+ if (ttlp != NULL)
+ *ttlp = nsset.ttl;
+ dns_rdataset_disassociate(&nsset);
+ }
+
+ return (ISC_TF(result == ISC_R_SUCCESS));
+}
+
+static isc_boolean_t
+secure(dns_name_t *name, dns_dbnode_t *node) {
+ dns_rdataset_t dsset;
+ isc_result_t result;
+
+ if (dns_name_equal(name, gorigin))
+ return (ISC_FALSE);
+
+ dns_rdataset_init(&dsset);
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
+ 0, 0, &dsset, NULL);
+ if (dns_rdataset_isassociated(&dsset))
+ dns_rdataset_disassociate(&dsset);
+
+ return (ISC_TF(result == ISC_R_SUCCESS));
+}
+
+/*%
+ * Signs all records at a name.
+ */
+static void
+signname(dns_dbnode_t *node, dns_name_t *name) {
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdatasetiter_t *rdsiter;
+ isc_boolean_t isdelegation = ISC_FALSE;
+ dns_diff_t del, add;
+ char namestr[DNS_NAME_FORMATSIZE];
+
+ dns_rdataset_init(&rdataset);
+ dns_name_format(name, namestr, sizeof(namestr));
+
+ /*
+ * Determine if this is a delegation point.
+ */
+ if (delegation(name, node, NULL))
+ isdelegation = ISC_TRUE;
+
+ /*
+ * Now iterate through the rdatasets.
+ */
+ dns_diff_init(mctx, &del);
+ dns_diff_init(mctx, &add);
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+
+ /* If this is a RRSIG set, skip it. */
+ if (rdataset.type == dns_rdatatype_rrsig)
+ goto skip;
+
+ /*
+ * If this name is a delegation point, skip all records
+ * except NSEC and DS sets. Otherwise check that there
+ * isn't a DS record.
+ */
+ if (isdelegation) {
+ if (rdataset.type != nsec_datatype &&
+ rdataset.type != dns_rdatatype_ds)
+ goto skip;
+ } else if (rdataset.type == dns_rdatatype_ds) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ fatal("'%s': found DS RRset without NS RRset\n",
+ namebuf);
+ }
+
+ signset(&del, &add, node, name, &rdataset);
+
+ skip:
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration for name '%s' failed: %s",
+ namestr, isc_result_totext(result));
+
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ result = dns_diff_applysilently(&del, gdb, gversion);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to delete SIGs at node '%s': %s",
+ namestr, isc_result_totext(result));
+
+ result = dns_diff_applysilently(&add, gdb, gversion);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to add SIGs at node '%s': %s",
+ namestr, isc_result_totext(result));
+
+ dns_diff_clear(&del);
+ dns_diff_clear(&add);
+}
+
+static inline isc_boolean_t
+active_node(dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_rdatasetiter_t *rdsiter2 = NULL;
+ isc_boolean_t active = ISC_FALSE;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdatatype_t type;
+ dns_rdatatype_t covers;
+ isc_boolean_t found;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ if (rdataset.type != dns_rdatatype_nsec &&
+ rdataset.type != dns_rdatatype_nsec3 &&
+ rdataset.type != dns_rdatatype_rrsig)
+ active = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ if (!active)
+ result = dns_rdatasetiter_next(rdsiter);
+ else
+ result = ISC_R_NOMORE;
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+
+ if (!active && nsec_datatype == dns_rdatatype_nsec) {
+ /*%
+ * The node is empty of everything but NSEC / RRSIG records.
+ */
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter)) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ rdataset.type,
+ rdataset.covers);
+ check_result(result, "dns_db_deleterdataset()");
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ } else {
+ /*
+ * Delete RRSIGs for types that no longer exist.
+ */
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
+ 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);
+ type = rdataset.type;
+ covers = rdataset.covers;
+ dns_rdataset_disassociate(&rdataset);
+ if (type != dns_rdatatype_rrsig)
+ continue;
+ found = ISC_FALSE;
+ for (result = dns_rdatasetiter_first(rdsiter2);
+ !found && result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter2)) {
+ dns_rdatasetiter_current(rdsiter2, &rdataset);
+ if (rdataset.type == covers)
+ found = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (!found) {
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ result = dns_db_deleterdataset(gdb, node,
+ gversion, type,
+ covers);
+ check_result(result,
+ "dns_db_deleterdataset(rrsig)");
+ } else if (result != ISC_R_NOMORE &&
+ result != ISC_R_SUCCESS)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ dns_rdatasetiter_destroy(&rdsiter2);
+
+#if 0
+ /*
+ * Delete all NSEC records and RRSIG(NSEC) if we are in
+ * NSEC3 mode and vica versa.
+ */
+ for (result = dns_rdatasetiter_first(rdsiter2);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter2)) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ type = rdataset.type;
+ covers = rdataset.covers;
+ if (type == dns_rdatatype_rrsig)
+ type = covers;
+ dns_rdataset_disassociate(&rdataset);
+ if (type == nsec_datatype ||
+ (type != dns_rdatatype_nsec &&
+ type != dns_rdatatype_nsec3))
+ continue;
+ if (covers != 0)
+ type = dns_rdatatype_rrsig;
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ type, covers);
+ check_result(result, "dns_db_deleterdataset()");
+ }
+#endif
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ return (active);
+}
+
+/*%
+ * Extracts the TTL from the SOA.
+ */
+static dns_ttl_t
+soattl(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);
+ dns_rdataset_init(&soaset);
+ result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
+ 0, 0, NULL, name, &soaset, NULL);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to find an SOA at the zone apex: %s",
+ isc_result_totext(result));
+
+ 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;
+ dns_rdataset_disassociate(&soaset);
+ return (ttl);
+}
+
+/*%
+ * Increment (or set if nonzero) the SOA serial
+ */
+static isc_result_t
+setsoaserial(isc_uint32_t serial) {
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_uint32_t old_serial, new_serial;
+
+ result = dns_db_getoriginnode(gdb, &node);
+ if (result != ISC_R_SUCCESS)
+ return result;
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_findrdataset(gdb, node, gversion,
+ dns_rdatatype_soa, 0,
+ 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_rdataset_first(&rdataset);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ dns_rdataset_current(&rdataset, &rdata);
+
+ old_serial = dns_soa_getserial(&rdata);
+
+ if (serial) {
+ /* Set SOA serial to the value provided. */
+ new_serial = serial;
+ } else {
+ /* Increment SOA serial using RFC 1982 arithmetics */
+ new_serial = (old_serial + 1) & 0xFFFFFFFF;
+ if (new_serial == 0)
+ new_serial = 1;
+ }
+
+ /* If the new serial is not likely to cause a zone transfer
+ * (a/ixfr) from servers having the old serial, warn the user.
+ *
+ * RFC1982 section 7 defines the maximum increment to be
+ * (2^(32-1))-1. Using u_int32_t arithmetic, we can do a single
+ * comparison. (5 - 6 == (2^32)-1, not negative-one)
+ */
+ if (new_serial == old_serial ||
+ (new_serial - old_serial) > 0x7fffffffU)
+ fprintf(stderr, "%s: warning: Serial number not advanced, "
+ "zone may not transfer\n", program);
+
+ dns_soa_setserial(new_serial, &rdata);
+
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_soa, 0);
+ check_result(result, "dns_db_deleterdataset");
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_db_addrdataset(gdb, node, gversion,
+ 0, &rdataset, 0, NULL);
+ check_result(result, "dns_db_addrdataset");
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+cleanup:
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(gdb, &node);
+ dns_rdata_reset(&rdata);
+
+ return (result);
+}
+
+/*%
+ * Delete any RRSIG records at a node.
+ */
+static void
+cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_rdataset_t set;
+ isc_result_t result, dresult;
+
+ if (outputformat != dns_masterformat_text)
+ return;
+
+ dns_rdataset_init(&set);
+ result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ isc_boolean_t destroy = ISC_FALSE;
+ dns_rdatatype_t covers = 0;
+ dns_rdatasetiter_current(rdsiter, &set);
+ if (set.type == dns_rdatatype_rrsig) {
+ covers = set.covers;
+ destroy = ISC_TRUE;
+ }
+ dns_rdataset_disassociate(&set);
+ result = dns_rdatasetiter_next(rdsiter);
+ if (destroy) {
+ dresult = dns_db_deleterdataset(db, node, version,
+ dns_rdatatype_rrsig,
+ covers);
+ check_result(dresult, "dns_db_deleterdataset");
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ dns_rdatasetiter_destroy(&rdsiter);
+}
+
+/*%
+ * Set up the iterator and global state before starting the tasks.
+ */
+static void
+presign(void) {
+ isc_result_t result;
+
+ gdbiter = NULL;
+ result = dns_db_createiterator(gdb, 0, &gdbiter);
+ check_result(result, "dns_db_createiterator()");
+}
+
+/*%
+ * Clean up the iterator and global state after the tasks complete.
+ */
+static void
+postsign(void) {
+ dns_dbiterator_destroy(&gdbiter);
+}
+
+/*%
+ * Sign the apex of the zone.
+ * Note the origin may not be the first node if there are out of zone
+ * records.
+ */
+static void
+signapex(void) {
+ dns_dbnode_t *node = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_result_t result;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ result = dns_dbiterator_seek(gdbiter, gorigin);
+ check_result(result, "dns_dbiterator_seek()");
+ result = dns_dbiterator_current(gdbiter, &node, name);
+ check_result(result, "dns_dbiterator_current()");
+ signname(node, name);
+ dumpnode(name, node);
+ cleannode(gdb, gversion, node);
+ dns_db_detachnode(gdb, &node);
+ result = dns_dbiterator_first(gdbiter);
+ if (result == ISC_R_NOMORE)
+ finished = ISC_TRUE;
+ else if (result != ISC_R_SUCCESS)
+ fatal("failure iterating database: %s",
+ isc_result_totext(result));
+}
+
+/*%
+ * Assigns a node to a worker thread. This is protected by the master task's
+ * lock.
+ */
+static void
+assignwork(isc_task_t *task, isc_task_t *worker) {
+ dns_fixedname_t *fname;
+ dns_name_t *name;
+ dns_dbnode_t *node;
+ sevent_t *sevent;
+ dns_rdataset_t nsec;
+ isc_boolean_t found;
+ isc_result_t result;
+ static dns_name_t *zonecut = NULL; /* Protected by namelock. */
+ static dns_fixedname_t fzonecut; /* Protected by namelock. */
+ static unsigned int ended = 0; /* Protected by namelock. */
+
+ if (shuttingdown)
+ return;
+
+ LOCK(&namelock);
+ if (finished) {
+ ended++;
+ if (ended == ntasks) {
+ isc_task_detach(&task);
+ isc_app_shutdown();
+ }
+ goto unlock;
+ }
+
+ fname = isc_mem_get(mctx, sizeof(dns_fixedname_t));
+ if (fname == NULL)
+ fatal("out of memory");
+ dns_fixedname_init(fname);
+ name = dns_fixedname_name(fname);
+ node = NULL;
+ found = ISC_FALSE;
+ while (!found) {
+ result = dns_dbiterator_current(gdbiter, &node, name);
+ if (result != ISC_R_SUCCESS)
+ fatal("failure iterating database: %s",
+ isc_result_totext(result));
+ /*
+ * The origin was handled by signapex().
+ */
+ if (dns_name_equal(name, gorigin)) {
+ dns_db_detachnode(gdb, &node);
+ goto next;
+ }
+ /*
+ * Sort the zone data from the glue and out-of-zone data.
+ * For NSEC zones nodes with zone data have NSEC records.
+ * For NSEC3 zones the NSEC3 nodes are zone data but
+ * outside of the zone name space. For the rest we need
+ * to track the bottom of zone cuts.
+ * Nodes which don't need to be signed are dumped here.
+ */
+ dns_rdataset_init(&nsec);
+ result = dns_db_findrdataset(gdb, node, gversion,
+ nsec_datatype, 0, 0,
+ &nsec, NULL);
+ if (dns_rdataset_isassociated(&nsec))
+ dns_rdataset_disassociate(&nsec);
+ if (result == ISC_R_SUCCESS) {
+ found = ISC_TRUE;
+ } else if (nsec_datatype == dns_rdatatype_nsec3) {
+ if (dns_name_issubdomain(name, gorigin) &&
+ (zonecut == NULL ||
+ !dns_name_issubdomain(name, zonecut))) {
+ if (delegation(name, node, NULL)) {
+ dns_fixedname_init(&fzonecut);
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(name, zonecut, NULL);
+ if (!OPTOUT(nsec3flags) ||
+ secure(name, node))
+ found = ISC_TRUE;
+ } else
+ found = ISC_TRUE;
+ }
+ }
+
+ if (!found) {
+ dumpnode(name, node);
+ dns_db_detachnode(gdb, &node);
+ }
+
+ next:
+ result = dns_dbiterator_next(gdbiter);
+ if (result == ISC_R_NOMORE) {
+ finished = ISC_TRUE;
+ break;
+ } else if (result != ISC_R_SUCCESS)
+ fatal("failure iterating database: %s",
+ isc_result_totext(result));
+ }
+ if (!found) {
+ ended++;
+ if (ended == ntasks) {
+ isc_task_detach(&task);
+ isc_app_shutdown();
+ }
+ isc_mem_put(mctx, fname, sizeof(dns_fixedname_t));
+ goto unlock;
+ }
+ sevent = (sevent_t *)
+ isc_event_allocate(mctx, task, SIGNER_EVENT_WORK,
+ sign, NULL, sizeof(sevent_t));
+ if (sevent == NULL)
+ fatal("failed to allocate event\n");
+
+ sevent->node = node;
+ sevent->fname = fname;
+ isc_task_send(worker, ISC_EVENT_PTR(&sevent));
+ unlock:
+ UNLOCK(&namelock);
+}
+
+/*%
+ * Start a worker task
+ */
+static void
+startworker(isc_task_t *task, isc_event_t *event) {
+ isc_task_t *worker;
+
+ worker = (isc_task_t *)event->ev_arg;
+ assignwork(task, worker);
+ isc_event_free(&event);
+}
+
+/*%
+ * Write a node to the output file, and restart the worker task.
+ */
+static void
+writenode(isc_task_t *task, isc_event_t *event) {
+ isc_task_t *worker;
+ sevent_t *sevent = (sevent_t *)event;
+
+ worker = (isc_task_t *)event->ev_sender;
+ dumpnode(dns_fixedname_name(sevent->fname), sevent->node);
+ cleannode(gdb, gversion, sevent->node);
+ dns_db_detachnode(gdb, &sevent->node);
+ isc_mem_put(mctx, sevent->fname, sizeof(dns_fixedname_t));
+ assignwork(task, worker);
+ isc_event_free(&event);
+}
+
+/*%
+ * Sign a database node.
+ */
+static void
+sign(isc_task_t *task, isc_event_t *event) {
+ dns_fixedname_t *fname;
+ dns_dbnode_t *node;
+ sevent_t *sevent, *wevent;
+
+ sevent = (sevent_t *)event;
+ node = sevent->node;
+ fname = sevent->fname;
+ isc_event_free(&event);
+
+ signname(node, dns_fixedname_name(fname));
+ wevent = (sevent_t *)
+ isc_event_allocate(mctx, task, SIGNER_EVENT_WRITE,
+ writenode, NULL, sizeof(sevent_t));
+ if (wevent == NULL)
+ fatal("failed to allocate event\n");
+ wevent->node = node;
+ wevent->fname = fname;
+ isc_task_send(master, ISC_EVENT_PTR(&wevent));
+}
+
+/*%
+ * Update / remove the DS RRset. Preserve RRSIG(DS) if possible.
+ */
+static void
+add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
+ dns_rdataset_t dsset;
+ dns_rdataset_t sigdsset;
+ isc_result_t result;
+
+ dns_rdataset_init(&dsset);
+ dns_rdataset_init(&sigdsset);
+ result = dns_db_findrdataset(gdb, node, gversion,
+ dns_rdatatype_ds,
+ 0, 0, &dsset, &sigdsset);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&dsset);
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ 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,
+ &dsset, 0, NULL);
+ check_result(result, "dns_db_addrdataset");
+ dns_rdataset_disassociate(&dsset);
+ if (dns_rdataset_isassociated(&sigdsset))
+ dns_rdataset_disassociate(&sigdsset);
+ } else if (dns_rdataset_isassociated(&sigdsset)) {
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_ds);
+ check_result(result, "dns_db_deleterdataset");
+ dns_rdataset_disassociate(&sigdsset);
+ }
+}
+
+/*%
+ * Generate NSEC records for the zone.
+ */
+static void
+nsecify(void) {
+ dns_dbiterator_t *dbiter = NULL;
+ dns_dbnode_t *node = NULL, *nextnode = NULL;
+ dns_fixedname_t fname, fnextname, fzonecut;
+ dns_name_t *name, *nextname, *zonecut;
+ isc_boolean_t done = ISC_FALSE;
+ isc_result_t result;
+ isc_uint32_t nsttl = 0;
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_fixedname_init(&fnextname);
+ nextname = dns_fixedname_name(&fnextname);
+ dns_fixedname_init(&fzonecut);
+ zonecut = NULL;
+
+ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+
+ while (!done) {
+ dns_dbiterator_current(dbiter, &node, name);
+ if (delegation(name, node, &nsttl)) {
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(name, zonecut, NULL);
+ if (generateds)
+ add_ds(name, node, nsttl);
+ }
+ result = dns_dbiterator_next(dbiter);
+ nextnode = NULL;
+ while (result == ISC_R_SUCCESS) {
+ isc_boolean_t active = ISC_FALSE;
+ result = dns_dbiterator_current(dbiter, &nextnode,
+ nextname);
+ if (result != ISC_R_SUCCESS)
+ break;
+ active = active_node(nextnode);
+ if (!active) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (!dns_name_issubdomain(nextname, gorigin) ||
+ (zonecut != NULL &&
+ dns_name_issubdomain(nextname, zonecut)))
+ {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ dns_db_detachnode(gdb, &nextnode);
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_name_clone(gorigin, nextname);
+ done = ISC_TRUE;
+ } else if (result != ISC_R_SUCCESS)
+ fatal("iterating through the database failed: %s",
+ isc_result_totext(result));
+ result = dns_nsec_build(gdb, gversion, node, nextname,
+ zonettl);
+ check_result(result, "dns_nsec_build()");
+ dns_db_detachnode(gdb, &node);
+ }
+
+ dns_dbiterator_destroy(&dbiter);
+}
+
+/*%
+ * Does this node only contain NSEC3 records or RRSIG records or is empty.
+ */
+static isc_boolean_t
+nsec3only(dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter = NULL;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ isc_boolean_t answer = ISC_TRUE;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ if (rdataset.type != dns_rdatatype_nsec3 &&
+ rdataset.type != dns_rdatatype_rrsig) {
+ answer = ISC_FALSE;
+ result = ISC_R_NOMORE;
+ } else
+ result = dns_rdatasetiter_next(rdsiter);
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed: %s",
+ isc_result_totext(result));
+ dns_rdatasetiter_destroy(&rdsiter);
+ return (answer);
+}
+
+static void
+addnsec3param(const unsigned char *salt, size_t salt_length,
+ unsigned int iterations)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ unsigned char nsec3parambuf[5 + 255];
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+
+ nsec3param.common.rdclass = gclass;
+ nsec3param.common.rdtype = dns_rdatatype_nsec3param;
+ ISC_LINK_INIT(&nsec3param.common, link);
+ nsec3param.mctx = NULL;
+ nsec3param.flags = 0;
+ nsec3param.hash = unknownalg ? DNS_NSEC3_UNKNOWNALG : dns_hash_sha1;
+ nsec3param.iterations = iterations;
+ nsec3param.salt_length = salt_length;
+ DE_CONST(salt, nsec3param.salt);
+
+ isc_buffer_init(&b, nsec3parambuf, sizeof(nsec3parambuf));
+ result = dns_rdata_fromstruct(&rdata, gclass,
+ dns_rdatatype_nsec3param,
+ &nsec3param, &b);
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.type = rdata.type;
+ rdatalist.covers = 0;
+ rdatalist.ttl = 0;
+ ISC_LIST_INIT(rdatalist.rdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
+ check_result(result, "dns_rdatalist_tordataset()");
+
+ result = dns_db_findnode(gdb, gorigin, ISC_TRUE, &node);
+ check_result(result, "dns_db_find(gorigin)");
+ result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
+ DNS_DBADD_MERGE, NULL);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ check_result(result, "addnsec3param: dns_db_addrdataset()");
+ dns_db_detachnode(gdb, &node);
+}
+
+static void
+addnsec3(dns_name_t *name, dns_dbnode_t *node,
+ const unsigned char *salt, size_t salt_length,
+ unsigned int iterations, hashlist_t *hashlist,
+ dns_ttl_t ttl)
+{
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ const unsigned char *nexthash;
+ unsigned char nsec3buffer[DNS_NSEC3_BUFFERSIZE];
+ dns_fixedname_t hashname;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ dns_dbnode_t *nsec3node = NULL;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ size_t hash_length;
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+
+ dns_fixedname_init(&hashname);
+ dns_rdataset_init(&rdataset);
+
+ dns_name_downcase(name, name, NULL);
+ result = dns_nsec3_hashname(&hashname, hash, &hash_length,
+ name, gorigin, dns_hash_sha1, iterations,
+ salt, salt_length);
+ check_result(result, "addnsec3: dns_nsec3_hashname()");
+ nexthash = hashlist_findnext(hashlist, hash);
+ result = dns_nsec3_buildrdata(gdb, gversion, node,
+ unknownalg ?
+ DNS_NSEC3_UNKNOWNALG : dns_hash_sha1,
+ nsec3flags, iterations,
+ salt, salt_length,
+ nexthash, ISC_SHA1_DIGESTLENGTH,
+ nsec3buffer, &rdata);
+ check_result(result, "addnsec3: dns_nsec3_buildrdata()");
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.type = rdata.type;
+ rdatalist.covers = 0;
+ rdatalist.ttl = ttl;
+ ISC_LIST_INIT(rdatalist.rdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ result = dns_rdatalist_tordataset(&rdatalist, &rdataset);
+ check_result(result, "dns_rdatalist_tordataset()");
+ result = dns_db_findnsec3node(gdb, dns_fixedname_name(&hashname),
+ ISC_TRUE, &nsec3node);
+ check_result(result, "addnsec3: dns_db_findnode()");
+ result = dns_db_addrdataset(gdb, nsec3node, gversion, 0, &rdataset,
+ 0, NULL);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ check_result(result, "addnsec3: dns_db_addrdataset()");
+ dns_db_detachnode(gdb, &nsec3node);
+}
+
+/*%
+ * Clean out NSEC3 record and RRSIG(NSEC3) that are not in the hash list.
+ *
+ * Extract the hash from the first label of 'name' then see if it
+ * is in hashlist. If 'name' is not in the hashlist then delete the
+ * any NSEC3 records which have the same parameters as the chain we
+ * are building.
+ *
+ * XXXMPA Should we also check that it of the form <hash>.<origin>?
+ */
+static void
+nsec3clean(dns_name_t *name, dns_dbnode_t *node,
+ unsigned int hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
+{
+ dns_label_t label;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata, delrdata;
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset, delrdataset;
+ isc_boolean_t delete_rrsigs = ISC_FALSE;
+ isc_buffer_t target;
+ isc_result_t result;
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
+
+ /*
+ * Get the first label.
+ */
+ dns_name_getlabel(name, 0, &label);
+
+ /*
+ * We want just the label contents.
+ */
+ isc_region_consume(&label, 1);
+
+ /*
+ * Decode base32hex string.
+ */
+ isc_buffer_init(&target, hash, sizeof(hash) - 1);
+ result = isc_base32hex_decoderegion(&label, &target);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ hash[isc_buffer_usedlength(&target)] = 0;
+
+ if (hashlist_exists(hashlist, hash))
+ return;
+
+ /*
+ * Verify that the NSEC3 parameters match the current ones
+ * otherwise we are dealing with a different NSEC3 chain.
+ */
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&delrdataset);
+
+ result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_nsec3,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ /*
+ * Delete any matching NSEC3 records which have parameters that
+ * match the NSEC3 chain we are building.
+ */
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(&rdataset, &rdata);
+ dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ if (nsec3.hash == hashalg &&
+ nsec3.iterations == iterations &&
+ nsec3.salt_length == salt_length &&
+ !memcmp(nsec3.salt, salt, salt_length))
+ break;
+ rdatalist.rdclass = rdata.rdclass;
+ rdatalist.type = rdata.type;
+ rdatalist.covers = 0;
+ rdatalist.ttl = rdataset.ttl;
+ ISC_LIST_INIT(rdatalist.rdata);
+ dns_rdata_init(&delrdata);
+ dns_rdata_clone(&rdata, &delrdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &delrdata, link);
+ result = dns_rdatalist_tordataset(&rdatalist, &delrdataset);
+ check_result(result, "dns_rdatalist_tordataset()");
+ result = dns_db_subtractrdataset(gdb, node, gversion,
+ &delrdataset, 0, NULL);
+ dns_rdataset_disassociate(&delrdataset);
+ if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
+ check_result(result, "dns_db_subtractrdataset(NSEC3)");
+ delete_rrsigs = ISC_TRUE;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_NOMORE)
+ check_result(result, "dns_rdataset_first/next");
+
+ if (!delete_rrsigs)
+ return;
+ /*
+ * Delete the NSEC3 RRSIGs
+ */
+ result = dns_db_deleterdataset(gdb, node, gversion,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_nsec3);
+ if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
+ check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
+}
+
+/*
+ * Generate NSEC3 records for the zone.
+ */
+static void
+nsec3ify(unsigned int hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length, hashlist_t *hashlist)
+{
+ dns_dbiterator_t *dbiter = NULL;
+ dns_dbnode_t *node = NULL, *nextnode = NULL;
+ dns_fixedname_t fname, fnextname, fzonecut;
+ dns_name_t *name, *nextname, *zonecut;
+ isc_boolean_t done = ISC_FALSE;
+ isc_result_t result;
+ isc_boolean_t active;
+ isc_uint32_t nsttl = 0;
+ unsigned int count, nlabels;
+ int order;
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_fixedname_init(&fnextname);
+ nextname = dns_fixedname_name(&fnextname);
+ dns_fixedname_init(&fzonecut);
+ zonecut = NULL;
+
+ /*
+ * Walk the zone generating the hash names.
+ */
+ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+
+ while (!done) {
+ dns_dbiterator_current(dbiter, &node, name);
+ result = dns_dbiterator_next(dbiter);
+ nextnode = NULL;
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbiter, &nextnode,
+ nextname);
+ if (result != ISC_R_SUCCESS)
+ break;
+ active = active_node(nextnode);
+ if (!active) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (!dns_name_issubdomain(nextname, gorigin) ||
+ (zonecut != NULL &&
+ dns_name_issubdomain(nextname, zonecut))) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (delegation(nextname, nextnode, &nsttl)) {
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(nextname, zonecut, NULL);
+ if (generateds)
+ add_ds(nextname, nextnode, nsttl);
+ if (OPTOUT(nsec3flags) &&
+ !secure(nextname, nextnode)) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ }
+ dns_db_detachnode(gdb, &nextnode);
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_name_copy(gorigin, nextname, NULL);
+ done = ISC_TRUE;
+ } else if (result != ISC_R_SUCCESS)
+ fatal("iterating through the database failed: %s",
+ isc_result_totext(result));
+ dns_name_downcase(name, name, NULL);
+ hashlist_add_dns_name(hashlist, name, hashalg, iterations,
+ salt, salt_length, ISC_FALSE);
+ dns_db_detachnode(gdb, &node);
+ /*
+ * Add hashs for empty nodes. Use closest encloser logic.
+ * The closest encloser either has data or is a empty
+ * node for another <name,nextname> span so we don't add
+ * it here. Empty labels on nextname are within the span.
+ */
+ dns_name_downcase(nextname, nextname, NULL);
+ dns_name_fullcompare(name, nextname, &order, &nlabels);
+ addnowildcardhash(hashlist, name, hashalg, iterations,
+ salt, salt_length);
+ count = dns_name_countlabels(nextname);
+ while (count > nlabels + 1) {
+ count--;
+ dns_name_split(nextname, count, NULL, nextname);
+ hashlist_add_dns_name(hashlist, nextname, hashalg,
+ iterations, salt, salt_length,
+ ISC_FALSE);
+ addnowildcardhash(hashlist, nextname, hashalg,
+ iterations, salt, salt_length);
+ }
+ }
+ dns_dbiterator_destroy(&dbiter);
+
+ /*
+ * We have all the hashes now so we can sort them.
+ */
+ hashlist_sort(hashlist);
+
+ /*
+ * Check for duplicate hashes. If found the salt needs to
+ * be changed.
+ */
+ if (hashlist_hasdup(hashlist))
+ fatal("Duplicate hash detected. Pick a different salt.");
+
+ /*
+ * Generate the nsec3 records.
+ */
+ zonecut = NULL;
+ done = ISC_FALSE;
+
+ addnsec3param(salt, salt_length, iterations);
+
+ result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first()");
+
+ while (!done) {
+ dns_dbiterator_current(dbiter, &node, name);
+ result = dns_dbiterator_next(dbiter);
+ nextnode = NULL;
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbiter, &nextnode,
+ nextname);
+ if (result != ISC_R_SUCCESS)
+ break;
+ /*
+ * Cleanout NSEC3 RRsets which don't exist in the
+ * hash table.
+ */
+ nsec3clean(nextname, nextnode, hashalg, iterations,
+ salt, salt_length, hashlist);
+ /*
+ * Skip NSEC3 only nodes when looking for the next
+ * node in the zone. Also skips now empty nodes.
+ */
+ if (nsec3only(nextnode)) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (!dns_name_issubdomain(nextname, gorigin) ||
+ (zonecut != NULL &&
+ dns_name_issubdomain(nextname, zonecut))) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ if (delegation(nextname, nextnode, NULL)) {
+ zonecut = dns_fixedname_name(&fzonecut);
+ dns_name_copy(nextname, zonecut, NULL);
+ if (OPTOUT(nsec3flags) &&
+ !secure(nextname, nextnode)) {
+ dns_db_detachnode(gdb, &nextnode);
+ result = dns_dbiterator_next(dbiter);
+ continue;
+ }
+ }
+ dns_db_detachnode(gdb, &nextnode);
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_name_copy(gorigin, nextname, NULL);
+ done = ISC_TRUE;
+ } else if (result != ISC_R_SUCCESS)
+ fatal("iterating through the database failed: %s",
+ isc_result_totext(result));
+ /*
+ * We need to pause here to release the lock on the database.
+ */
+ dns_dbiterator_pause(dbiter);
+ addnsec3(name, node, salt, salt_length, iterations,
+ hashlist, zonettl);
+ dns_db_detachnode(gdb, &node);
+ /*
+ * Add NSEC3's for empty nodes. Use closest encloser logic.
+ */
+ dns_name_fullcompare(name, nextname, &order, &nlabels);
+ count = dns_name_countlabels(nextname);
+ while (count > nlabels + 1) {
+ count--;
+ dns_name_split(nextname, count, NULL, nextname);
+ addnsec3(nextname, NULL, salt, salt_length,
+ iterations, hashlist, zonettl);
+ }
+ }
+ dns_dbiterator_destroy(&dbiter);
+}
+
+/*%
+ * Load the zone file from disk
+ */
+static void
+loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
+ isc_buffer_t b;
+ int len;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result;
+
+ len = strlen(origin);
+ isc_buffer_init(&b, origin, len);
+ isc_buffer_add(&b, len);
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed converting name '%s' to dns format: %s",
+ origin, isc_result_totext(result));
+
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
+ rdclass, 0, NULL, db);
+ check_result(result, "dns_db_create()");
+
+ result = dns_db_load2(*db, file, inputformat);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
+ fatal("failed loading zone from '%s': %s",
+ file, isc_result_totext(result));
+}
+
+/*%
+ * Finds all public zone keys in the zone, and attempts to load the
+ * private keys from disk.
+ */
+static void
+loadzonekeys(dns_db_t *db) {
+ dns_dbnode_t *node;
+ dns_dbversion_t *currentversion;
+ isc_result_t result;
+ dst_key_t *keys[20];
+ unsigned int nkeys, i;
+
+ currentversion = NULL;
+ dns_db_currentversion(db, &currentversion);
+
+ node = NULL;
+ 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_dnssec_findzonekeys(db, currentversion, node, gorigin,
+ mctx, 20, keys, &nkeys);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_SUCCESS;
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to find the zone keys: %s",
+ isc_result_totext(result));
+
+ for (i = 0; i < nkeys; i++) {
+ signer_key_t *key;
+
+ key = newkeystruct(keys[i], dst_key_isprivate(keys[i]));
+ ISC_LIST_APPEND(keylist, key, link);
+ }
+ dns_db_detachnode(db, &node);
+ dns_db_closeversion(db, &currentversion, 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;
+ isc_result_t result;
+
+ dns_db_currentversion(db, &currentversion);
+
+ 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));
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, currentversion,
+ dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
+ 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;
+ }
+
+ 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, &currentversion, ISC_FALSE);
+}
+
+static void
+warnifallksk(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;
+ isc_result_t result;
+ dns_rdata_key_t key;
+ isc_boolean_t have_non_ksk = ISC_FALSE;
+
+ dns_db_currentversion(db, &currentversion);
+
+ 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));
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, currentversion,
+ dns_rdatatype_dnskey, 0, 0, &rdataset, NULL);
+ 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) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &key, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ if ((key.flags & DNS_KEYFLAG_KSK) == 0) {
+ have_non_ksk = ISC_TRUE;
+ result = ISC_R_NOMORE;
+ } else
+ result = dns_rdataset_next(&rdataset);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+ dns_db_closeversion(db, &currentversion, ISC_FALSE);
+ if (!have_non_ksk && !ignoreksk)
+ fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
+ "Supply non-KSK dnskey or use '-z'.\n",
+ program);
+}
+
+static void
+writeset(const char *prefix, dns_rdatatype_t type) {
+ char *filename;
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_db_t *db = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_diff_t diff;
+ dns_difftuple_t *tuple = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ dns_rdata_t rdata, ds;
+ isc_boolean_t have_ksk = ISC_FALSE;
+ isc_boolean_t have_non_ksk = ISC_FALSE;
+ isc_buffer_t b;
+ isc_buffer_t namebuf;
+ isc_region_t r;
+ isc_result_t result;
+ signer_key_t *key;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+ unsigned char keybuf[DST_KEY_MAXSIZE];
+ unsigned int filenamelen;
+ const dns_master_style_t *style =
+ (type == dns_rdatatype_dnskey) ? masterstyle : dsstyle;
+
+ isc_buffer_init(&namebuf, namestr, sizeof(namestr));
+ result = dns_name_tofilenametext(gorigin, ISC_FALSE, &namebuf);
+ check_result(result, "dns_name_tofilenametext");
+ isc_buffer_putuint8(&namebuf, 0);
+ filenamelen = strlen(prefix) + strlen(namestr);
+ if (directory != NULL)
+ filenamelen += strlen(directory) + 1;
+ filename = isc_mem_get(mctx, filenamelen + 1);
+ if (filename == NULL)
+ fatal("out of memory");
+ if (directory != NULL)
+ sprintf(filename, "%s/", directory);
+ else
+ filename[0] = 0;
+ strcat(filename, prefix);
+ strcat(filename, namestr);
+
+ 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;
+
+ dns_name_init(&tname, NULL);
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ labels = dns_name_countlabels(gorigin);
+ dns_name_getlabelsequence(gorigin, 0, labels - 1, &tname);
+ result = dns_name_concatenate(&tname, dlv, name, NULL);
+ check_result(result, "dns_name_concatenate");
+ } else
+ name = gorigin;
+
+ for (key = ISC_LIST_HEAD(keylist);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ if (have_ksk && have_non_ksk && !key->isksk)
+ continue;
+ dns_rdata_init(&rdata);
+ dns_rdata_init(&ds);
+ isc_buffer_init(&b, keybuf, sizeof(keybuf));
+ result = dst_key_todns(key->key, &b);
+ check_result(result, "dst_key_todns");
+ isc_buffer_usedregion(&b, &r);
+ dns_rdata_fromregion(&rdata, gclass, dns_rdatatype_dnskey, &r);
+ if (type != dns_rdatatype_dnskey) {
+ result = dns_ds_buildrdata(gorigin, &rdata,
+ DNS_DSDIGEST_SHA1,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+ if (type == dns_rdatatype_dlv)
+ ds.type = dns_rdatatype_dlv;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ name, 0, &ds, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+
+ dns_rdata_reset(&ds);
+ result = dns_ds_buildrdata(gorigin, &rdata,
+ DNS_DSDIGEST_SHA256,
+ dsbuf, &ds);
+ check_result(result, "dns_ds_buildrdata");
+ if (type == dns_rdatatype_dlv)
+ ds.type = dns_rdatatype_dlv;
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ name, 0, &ds, &tuple);
+
+ } else
+ result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
+ gorigin, zonettl,
+ &rdata, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(&diff, &tuple);
+ }
+
+ result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
+ gclass, 0, NULL, &db);
+ check_result(result, "dns_db_create");
+
+ result = dns_db_newversion(db, &version);
+ check_result(result, "dns_db_newversion");
+
+ result = dns_diff_apply(&diff, db, version);
+ check_result(result, "dns_diff_apply");
+ dns_diff_clear(&diff);
+
+ result = dns_master_dump(mctx, db, version, style, filename);
+ check_result(result, "dns_master_dump");
+
+ isc_mem_put(mctx, filename, filenamelen + 1);
+
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ dns_db_detach(&db);
+}
+
+static void
+print_time(FILE *fp) {
+ time_t currenttime;
+
+ if (outputformat != dns_masterformat_text)
+ return;
+
+ currenttime = time(NULL);
+ fprintf(fp, "; File written on %s", ctime(&currenttime));
+}
+
+static void
+print_version(FILE *fp) {
+ if (outputformat != dns_masterformat_text)
+ return;
+
+ fprintf(fp, "; dnssec_signzone version " VERSION "\n");
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\t%s [options] zonefile [keys]\n", program);
+
+ fprintf(stderr, "\n");
+
+ 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-g:\t");
+ fprintf(stderr, "generate DS records from keyset files\n");
+ fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\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");
+ fprintf(stderr, "\t-i interval:\n");
+ 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-v debuglevel (0)\n");
+ fprintf(stderr, "\t-o origin:\n");
+ fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
+ fprintf(stderr, "\t-f outfile:\n");
+ fprintf(stderr, "\t\tfile the signed zone is written in "
+ "(zonefile + .signed)\n");
+ fprintf(stderr, "\t-I format:\n");
+ fprintf(stderr, "\t\tfile format of input zonefile (text)\n");
+ fprintf(stderr, "\t-O format:\n");
+ fprintf(stderr, "\t\tfile format of signed zone file (text)\n");
+ fprintf(stderr, "\t-N format:\n");
+ fprintf(stderr, "\t\tsoa serial format of signed zone file (keep)\n");
+ fprintf(stderr, "\t-r randomdev:\n");
+ fprintf(stderr, "\t\ta file containing random data\n");
+ fprintf(stderr, "\t-a:\t");
+ fprintf(stderr, "verify generated signatures\n");
+ fprintf(stderr, "\t-p:\t");
+ fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
+ fprintf(stderr, "\t-t:\t");
+ fprintf(stderr, "print statistics\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 interations (NSEC3 interations)\n");
+ fprintf(stderr, "\t-A (NSEC3 optout)\n");
+ fprintf(stderr, "\t-z:\t");
+ fprintf(stderr, "ignore KSK flag in DNSKEYs");
+
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, "Signing Keys: ");
+ fprintf(stderr, "(default: all zone keys that have private keys)\n");
+ fprintf(stderr, "\tkeyfile (Kname+alg+tag)\n");
+ exit(0);
+}
+
+static void
+removetempfile(void) {
+ if (removefile)
+ isc_file_remove(tempfile);
+}
+
+static void
+print_stats(isc_time_t *timer_start, isc_time_t *timer_finish) {
+ isc_uint64_t runtime_us; /* Runtime in microseconds */
+ isc_uint64_t runtime_ms; /* Runtime in milliseconds */
+ isc_uint64_t sig_ms; /* Signatures per millisecond */
+
+ runtime_us = isc_time_microdiff(timer_finish, timer_start);
+
+ printf("Signatures generated: %10d\n", nsigned);
+ printf("Signatures retained: %10d\n", nretained);
+ printf("Signatures dropped: %10d\n", ndropped);
+ printf("Signatures successfully verified: %10d\n", nverified);
+ printf("Signatures unsuccessfully verified: %10d\n", nverifyfailed);
+ runtime_ms = runtime_us / 1000;
+ printf("Runtime in seconds: %7u.%03u\n",
+ (unsigned int) (runtime_ms / 1000),
+ (unsigned int) (runtime_ms % 1000));
+ if (runtime_us > 0) {
+ sig_ms = ((isc_uint64_t)nsigned * 1000000000) / runtime_us;
+ printf("Signatures per second: %7u.%03u\n",
+ (unsigned int) sig_ms / 1000,
+ (unsigned int) sig_ms % 1000);
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ int i, ch;
+ char *startstr = NULL, *endstr = NULL, *classname = NULL;
+ char *origin = NULL, *file = NULL, *output = NULL;
+ char *inputformatstr = NULL, *outputformatstr = NULL;
+ char *serialformatstr = NULL;
+ char *dskeyfile[MAXDSKEYS];
+ int ndskeys = 0;
+ char *endp;
+ isc_time_t timer_start, timer_finish;
+ signer_key_t *key;
+ isc_result_t result;
+ isc_log_t *log = NULL;
+ isc_boolean_t pseudorandom = ISC_FALSE;
+ unsigned int eflags;
+ isc_boolean_t free_output = ISC_FALSE;
+ int tempfilelen;
+ dns_rdataclass_t rdclass;
+ 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;
+
+#define CMDLINE_FLAGS "3:aAc:d:e:f:ghH:i:I:j:k:l:m:n:N:o:O:pr:s:StUv:z"
+
+ /*
+ * Process memory debugging arguement first.
+ */
+ 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;
+
+ masterstyle = &dns_master_style_explicitttl;
+
+ check_result(isc_app_start(), "isc_app_start");
+
+ 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, CMDLINE_FLAGS)) != -1) {
+ switch (ch) {
+ case '3':
+ if (strcmp(isc_commandline_argument, "-")) {
+ isc_buffer_t target;
+ char *sarg;
+
+ sarg = isc_commandline_argument;
+ isc_buffer_init(&target, saltbuf,
+ sizeof(saltbuf));
+ 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;
+ break;
+
+ case 'a':
+ tryverify = ISC_TRUE;
+ break;
+
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+
+ case 'd':
+ directory = isc_commandline_argument;
+ break;
+
+ case 'e':
+ endstr = isc_commandline_argument;
+ break;
+
+ case 'f':
+ output = isc_commandline_argument;
+ break;
+
+ case 'g':
+ generateds = ISC_TRUE;
+ break;
+
+ case '?':
+ if (isc_commandline_option != '?')
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ case 'h':
+ usage();
+ break;
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n",
+ program, isc_commandline_option);
+ exit(1);
+
+ case 'i':
+ endp = NULL;
+ cycle = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0' || cycle < 0)
+ fatal("cycle period must be numeric and "
+ "positive");
+ break;
+
+ case 'I':
+ inputformatstr = isc_commandline_argument;
+ break;
+
+ case 'j':
+ endp = NULL;
+ jitter = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0' || jitter < 0)
+ fatal("jitter must be numeric and positive");
+ break;
+
+ case 'l':
+ dns_fixedname_init(&dlv_fixed);
+ len = strlen(isc_commandline_argument);
+ isc_buffer_init(&b, isc_commandline_argument, len);
+ isc_buffer_add(&b, len);
+
+ dns_fixedname_init(&dlv_fixed);
+ dlv = dns_fixedname_name(&dlv_fixed);
+ result = dns_name_fromtext(dlv, &b, dns_rootname,
+ ISC_FALSE, NULL);
+ check_result(result, "dns_name_fromtext(dlv)");
+ break;
+
+ case 'k':
+ if (ndskeys == MAXDSKEYS)
+ fatal("too many key-signing keys specified");
+ dskeyfile[ndskeys++] = isc_commandline_argument;
+ break;
+
+ case 'm':
+ break;
+
+ case 'n':
+ endp = NULL;
+ ntasks = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0' || ntasks > ISC_INT32_MAX)
+ fatal("number of cpus must be numeric");
+ break;
+
+ case 'N':
+ serialformatstr = isc_commandline_argument;
+ break;
+
+ case 'H':
+ iterations = strtoul(isc_commandline_argument,
+ &endp, 0);
+ if (*endp != '\0')
+ fatal("iterations must be numeric");
+ if (iterations > 0xffffU)
+ fatal("iterations too big");
+ break;
+
+ case 'o':
+ origin = isc_commandline_argument;
+ break;
+
+ case 'O':
+ outputformatstr = isc_commandline_argument;
+ break;
+
+ case 'p':
+ pseudorandom = ISC_TRUE;
+ break;
+
+ case 'r':
+ setup_entropy(mctx, isc_commandline_argument, &ectx);
+ break;
+
+ case 's':
+ startstr = isc_commandline_argument;
+ break;
+
+ case 'S':
+ /* This is intentionally undocumented */
+ /* -S: simple output style */
+ masterstyle = &dns_master_style_simple;
+ break;
+
+ case 't':
+ printstats = ISC_TRUE;
+ break;
+
+ case 'U': /* Undocumented for testing only. */
+ unknownalg = ISC_TRUE;
+ break;
+
+ case 'v':
+ endp = NULL;
+ verbose = strtol(isc_commandline_argument, &endp, 0);
+ if (*endp != '\0')
+ fatal("verbose level must be numeric");
+ break;
+
+ case 'z':
+ ignoreksk = ISC_TRUE;
+ break;
+ }
+ }
+
+ if (ectx == NULL)
+ setup_entropy(mctx, NULL, &ectx);
+ eflags = ISC_ENTROPY_BLOCKING;
+ if (!pseudorandom)
+ eflags |= ISC_ENTROPY_GOODONLY;
+
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not create hash context");
+
+ result = dst_lib_init(mctx, ectx, eflags);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize dst");
+
+ isc_stdtime_get(&now);
+
+ if (startstr != NULL)
+ starttime = strtotime(startstr, now, now);
+ else
+ starttime = now - 3600; /* Allow for some clock skew. */
+
+ if (endstr != NULL)
+ endtime = strtotime(endstr, now, starttime);
+ else
+ endtime = starttime + (30 * 24 * 60 * 60);
+
+ if (cycle == -1)
+ cycle = (endtime - starttime) / 4;
+
+ if (ntasks == 0)
+ ntasks = isc_os_ncpus() * 2;
+ vbprintf(4, "using %d cpus\n", ntasks);
+
+ rdclass = strtoclass(classname);
+
+ setup_logging(verbose, mctx, &log);
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc < 1)
+ usage();
+
+ file = argv[0];
+
+ argc -= 1;
+ argv += 1;
+
+ if (origin == NULL)
+ origin = file;
+
+ if (output == NULL) {
+ free_output = ISC_TRUE;
+ output = isc_mem_allocate(mctx,
+ strlen(file) + strlen(".signed") + 1);
+ if (output == NULL)
+ fatal("out of memory");
+ sprintf(output, "%s.signed", file);
+ }
+
+ if (inputformatstr != NULL) {
+ if (strcasecmp(inputformatstr, "text") == 0)
+ inputformat = dns_masterformat_text;
+ else if (strcasecmp(inputformatstr, "raw") == 0)
+ inputformat = dns_masterformat_raw;
+ else
+ fatal("unknown file format: %s\n", inputformatstr);
+ }
+
+ if (outputformatstr != NULL) {
+ if (strcasecmp(outputformatstr, "text") == 0)
+ outputformat = dns_masterformat_text;
+ else if (strcasecmp(outputformatstr, "raw") == 0)
+ outputformat = dns_masterformat_raw;
+ else
+ fatal("unknown file format: %s\n", outputformatstr);
+ }
+
+ if (serialformatstr != NULL) {
+ if (strcasecmp(serialformatstr, "keep") == 0)
+ serialformat = SOA_SERIAL_KEEP;
+ else if (strcasecmp(serialformatstr, "increment") == 0 ||
+ strcasecmp(serialformatstr, "incr") == 0)
+ serialformat = SOA_SERIAL_INCREMENT;
+ else if (strcasecmp(serialformatstr, "unixtime") == 0)
+ serialformat = SOA_SERIAL_UNIXTIME;
+ else
+ fatal("unknown soa serial format: %s\n", serialformatstr);
+ }
+
+ result = dns_master_stylecreate(&dsstyle, DNS_STYLEFLAG_NO_TTL,
+ 0, 24, 0, 0, 0, 8, mctx);
+ check_result(result, "dns_master_stylecreate");
+
+ gdb = NULL;
+ TIME_NOW(&timer_start);
+ loadzone(file, origin, rdclass, &gdb);
+ gorigin = dns_db_origin(gdb);
+ gclass = dns_db_class(gdb);
+ zonettl = soattl();
+
+ if (IS_NSEC3) {
+ isc_boolean_t answer;
+ hash_length = dns_nsec3_hashlength(dns_hash_sha1);
+ hashlist_init(&hashlist, dns_db_nodecount(gdb) * 2,
+ hash_length);
+ result = dns_nsec_nseconly(gdb, gversion, &answer);
+ check_result(result, "dns_nsec_nseconly");
+ if (answer)
+ fatal("NSEC3 generation requested with "
+ "NSEC only DNSKEY");
+ }
+
+ ISC_LIST_INIT(keylist);
+
+ 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);
+ 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));
+
+ if (!dns_name_equal(gorigin, dst_key_name(newkey)))
+ fatal("key %s not at origin\n", dskeyfile[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)))
+ {
+ /* 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);
+ }
+ }
+
+ if (ISC_LIST_EMPTY(keylist)) {
+ fprintf(stderr, "%s: warning: No keys specified or found\n",
+ program);
+ nokeys = ISC_TRUE;
+ }
+
+ if (IS_NSEC3) {
+ unsigned int max;
+ result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
+ check_result(result, "dns_nsec3_maxiterations()");
+ if (iterations > max)
+ fatal("NSEC3 interations too big for weakest DNSKEY "
+ "strength. Maximum iterations allowed %u.", max);
+ }
+
+ warnifallksk(gdb);
+
+ gversion = NULL;
+ result = dns_db_newversion(gdb, &gversion);
+ check_result(result, "dns_db_newversion()");
+
+ switch (serialformat) {
+ case SOA_SERIAL_INCREMENT:
+ setsoaserial(0);
+ break;
+ case SOA_SERIAL_UNIXTIME:
+ setsoaserial(now);
+ break;
+ case SOA_SERIAL_KEEP:
+ default:
+ /* do nothing */
+ break;
+ }
+
+ if (IS_NSEC3)
+ nsec3ify(dns_hash_sha1, iterations, salt, salt_length,
+ &hashlist);
+ else
+ nsecify();
+
+ if (!nokeys) {
+ writeset("keyset-", dns_rdatatype_dnskey);
+ writeset("dsset-", dns_rdatatype_ds);
+ if (dlv != NULL) {
+ writeset("dlvset-", dns_rdatatype_dlv);
+ }
+ }
+
+ tempfilelen = strlen(output) + 20;
+ tempfile = isc_mem_get(mctx, tempfilelen);
+ if (tempfile == NULL)
+ fatal("out of memory");
+
+ result = isc_file_mktemplate(output, tempfile, tempfilelen);
+ check_result(result, "isc_file_mktemplate");
+
+ fp = NULL;
+ result = isc_file_openunique(tempfile, &fp);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to open temporary output file: %s",
+ isc_result_totext(result));
+ removefile = ISC_TRUE;
+ setfatalcallback(&removetempfile);
+
+ print_time(fp);
+ print_version(fp);
+
+ result = isc_taskmgr_create(mctx, ntasks, 0, &taskmgr);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to create task manager: %s",
+ isc_result_totext(result));
+
+ master = NULL;
+ result = isc_task_create(taskmgr, 0, &master);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to create task: %s", isc_result_totext(result));
+
+ tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
+ if (tasks == NULL)
+ fatal("out of memory");
+ for (i = 0; i < (int)ntasks; i++) {
+ tasks[i] = NULL;
+ result = isc_task_create(taskmgr, 0, &tasks[i]);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to create task: %s",
+ isc_result_totext(result));
+ }
+
+ RUNTIME_CHECK(isc_mutex_init(&namelock) == ISC_R_SUCCESS);
+ if (printstats)
+ RUNTIME_CHECK(isc_mutex_init(&statslock) == ISC_R_SUCCESS);
+
+ presign();
+ signapex();
+ if (!finished) {
+ /*
+ * There is more work to do. Spread it out over multiple
+ * processors if possible.
+ */
+ for (i = 0; i < (int)ntasks; i++) {
+ result = isc_app_onrun(mctx, master, startworker,
+ tasks[i]);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to start task: %s",
+ isc_result_totext(result));
+ }
+ (void)isc_app_run();
+ if (!finished)
+ fatal("process aborted by user");
+ } else
+ isc_task_detach(&master);
+ shuttingdown = ISC_TRUE;
+ for (i = 0; i < (int)ntasks; i++)
+ isc_task_detach(&tasks[i]);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_mem_put(mctx, tasks, ntasks * sizeof(isc_task_t *));
+ postsign();
+
+ if (outputformat != dns_masterformat_text) {
+ result = dns_master_dumptostream2(mctx, gdb, gversion,
+ masterstyle, outputformat,
+ fp);
+ check_result(result, "dns_master_dumptostream2");
+ }
+
+ result = isc_stdio_close(fp);
+ check_result(result, "isc_stdio_close");
+ removefile = ISC_FALSE;
+
+ result = isc_file_rename(tempfile, output);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to rename temp file to %s: %s\n",
+ output, isc_result_totext(result));
+
+ DESTROYLOCK(&namelock);
+ if (printstats)
+ DESTROYLOCK(&statslock);
+
+ printf("%s\n", output);
+
+ dns_db_closeversion(gdb, &gversion, ISC_FALSE);
+ dns_db_detach(&gdb);
+
+ 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));
+ }
+
+ isc_mem_put(mctx, tempfile, tempfilelen);
+
+ if (free_output)
+ isc_mem_free(mctx, output);
+
+ dns_master_styledestroy(&dsstyle, mctx);
+
+ cleanup_logging(&log);
+ dst_lib_destroy();
+ isc_hash_destroy();
+ cleanup_entropy(&ectx);
+ dns_name_destroy();
+ if (verbose > 10)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ (void) isc_app_finish();
+
+ if (printstats) {
+ TIME_NOW(&timer_finish);
+ print_stats(&timer_start, &timer_finish);
+ }
+
+ return (0);
+}
diff --git a/bin/dnssec/dnssec-signzone.docbook b/bin/dnssec/dnssec-signzone.docbook
new file mode 100644
index 0000000..2f26ba4
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.docbook
@@ -0,0 +1,512 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - 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
+ - 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-signzone.docbook,v 1.31 2008/10/14 14:28:25 jreed Exp $ -->
+<refentry id="man.dnssec-signzone">
+ <refentryinfo>
+ <date>June 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>dnssec-signzone</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>dnssec-signzone</application></refname>
+ <refpurpose>DNSSEC zone signing tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dnssec-signzone</command>
+ <arg><option>-a</option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-d <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-e <replaceable class="parameter">end-time</replaceable></option></arg>
+ <arg><option>-f <replaceable class="parameter">output-file</replaceable></option></arg>
+ <arg><option>-g</option></arg>
+ <arg><option>-h</option></arg>
+ <arg><option>-k <replaceable class="parameter">key</replaceable></option></arg>
+ <arg><option>-l <replaceable class="parameter">domain</replaceable></option></arg>
+ <arg><option>-i <replaceable class="parameter">interval</replaceable></option></arg>
+ <arg><option>-I <replaceable class="parameter">input-format</replaceable></option></arg>
+ <arg><option>-j <replaceable class="parameter">jitter</replaceable></option></arg>
+ <arg><option>-N <replaceable class="parameter">soa-serial-format</replaceable></option></arg>
+ <arg><option>-o <replaceable class="parameter">origin</replaceable></option></arg>
+ <arg><option>-O <replaceable class="parameter">output-format</replaceable></option></arg>
+ <arg><option>-p</option></arg>
+ <arg><option>-r <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg><option>-s <replaceable class="parameter">start-time</replaceable></option></arg>
+ <arg><option>-t</option></arg>
+ <arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg><option>-z</option></arg>
+ <arg><option>-3 <replaceable class="parameter">salt</replaceable></option></arg>
+ <arg><option>-H <replaceable class="parameter">iterations</replaceable></option></arg>
+ <arg><option>-A</option></arg>
+ <arg choice="req">zonefile</arg>
+ <arg rep="repeat">key</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dnssec-signzone</command>
+ 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
+ <filename>keyset</filename> file for each child zone.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-a</term>
+ <listitem>
+ <para>
+ Verify all generated signatures.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the DNS class of the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">key</replaceable></term>
+ <listitem>
+ <para>
+ Treat specified key as a key signing key ignoring any
+ key flags. This option may be specified multiple times.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para>
+ Generate a DLV set in addition to the key (DNSKEY) and DS sets.
+ The domain is appended to the name of the records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>
+ Look for <filename>keyset</filename> files in
+ <option>directory</option> as the directory
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g</term>
+ <listitem>
+ <para>
+ Generate DS records for child zones from keyset files.
+ Existing DS records will be removed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">start-time</replaceable></term>
+ <listitem>
+ <para>
+ Specify the date and time when the generated RRSIG records
+ become valid. This can be either an absolute or relative
+ time. An absolute start time is indicated by a number
+ in YYYYMMDDHHMMSS notation; 20000530144500 denotes
+ 14:45:00 UTC on May 30th, 2000. A relative start time is
+ indicated by +N, which is N seconds from the current time.
+ If no <option>start-time</option> is specified, the current
+ time minus 1 hour (to allow for clock skew) is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-e <replaceable class="parameter">end-time</replaceable></term>
+ <listitem>
+ <para>
+ Specify the date and time when the generated RRSIG records
+ expire. As with <option>start-time</option>, 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 <option>end-time</option> is
+ specified, 30 days from the start time is used as a default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">output-file</replaceable></term>
+ <listitem>
+ <para>
+ The name of the output file containing the signed zone. The
+ default is to append <filename>.signed</filename> to
+ the
+ input filename.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>dnssec-signzone</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">interval</replaceable></term>
+ <listitem>
+ <para>
+ When a previously-signed zone is passed as input, records
+ may be resigned. The <option>interval</option> option
+ specifies the cycle interval as an offset from the current
+ time (in seconds). If a RRSIG record expires after the
+ cycle interval, it is retained. Otherwise, it is considered
+ to be expiring soon, and it will be replaced.
+ </para>
+ <para>
+ The default cycle interval is one quarter of the difference
+ between the signature end and start times. So if neither
+ <option>end-time</option> or <option>start-time</option>
+ are specified, <command>dnssec-signzone</command>
+ generates
+ signatures that are valid for 30 days, with a cycle
+ interval of 7.5 days. Therefore, if any existing RRSIG records
+ are due to expire in less than 7.5 days, they would be
+ replaced.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-I <replaceable class="parameter">input-format</replaceable></term>
+ <listitem>
+ <para>
+ The format of the input zone file.
+ Possible formats are <command>"text"</command> (default)
+ and <command>"raw"</command>.
+ This option is primarily intended to be used for dynamic
+ signed zones so that the dumped zone file in a non-text
+ format containing updates can be signed directly.
+ The use of this option does not make much sense for
+ non-dynamic zones.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-j <replaceable class="parameter">jitter</replaceable></term>
+ <listitem>
+ <para>
+ When signing a zone with a fixed signature lifetime, all
+ RRSIG records issued at the time of signing expires
+ simultaneously. If the zone is incrementally signed, i.e.
+ a previously-signed zone is passed as input to the signer,
+ all expired signatures have to be regenerated at about the
+ same time. The <option>jitter</option> option specifies a
+ jitter window that will be used to randomize the signature
+ expire time, thus spreading incremental signature
+ regeneration over time.
+ </para>
+ <para>
+ Signature lifetime jitter also to some extent benefits
+ validators and servers by spreading out cache expiration,
+ i.e. if large numbers of RRSIGs don't expire at the same time
+ from all caches there will be less congestion than if all
+ validators need to refetch at mostly the same time.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">ncpus</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the number of threads to use. By default, one
+ thread is started for each detected CPU.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-N <replaceable class="parameter">soa-serial-format</replaceable></term>
+ <listitem>
+ <para>
+ The SOA serial number format of the signed zone.
+ Possible formats are <command>"keep"</command> (default),
+ <command>"increment"</command> and
+ <command>"unixtime"</command>.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>"keep"</command></term>
+ <listitem>
+ <para>Do not modify the SOA serial number.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>"increment"</command></term>
+ <listitem>
+ <para>Increment the SOA serial number using RFC 1982
+ arithmetics.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>"unixtime"</command></term>
+ <listitem>
+ <para>Set the SOA serial number to the number of seconds
+ since epoch.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-o <replaceable class="parameter">origin</replaceable></term>
+ <listitem>
+ <para>
+ The zone origin. If not specified, the name of the zone file
+ is assumed to be the origin.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-O <replaceable class="parameter">output-format</replaceable></term>
+ <listitem>
+ <para>
+ The format of the output file containing the signed zone.
+ Possible formats are <command>"text"</command> (default)
+ and <command>"raw"</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p</term>
+ <listitem>
+ <para>
+ Use pseudo-random data when signing the zone. This is faster,
+ but less secure, than using real random data. This option
+ may be useful when signing large zones or when the entropy
+ source is limited.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">randomdev</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the source of randomness. If the operating
+ system does not provide a <filename>/dev/random</filename>
+ or equivalent device, the default source of randomness
+ is keyboard input. <filename>randomdev</filename>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard
+ input should be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t</term>
+ <listitem>
+ <para>
+ Print statistics at completion.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v <replaceable class="parameter">level</replaceable></term>
+ <listitem>
+ <para>
+ Sets the debugging level.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-z</term>
+ <listitem>
+ <para>
+ Ignore KSK flag on key when determining what to sign.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-3 <replaceable class="parameter">salt</replaceable></term>
+ <listitem>
+ <para>
+ Generate a NSEC3 chain with the given hex encoded salt.
+ A dash (<replaceable class="parameter">salt</replaceable>) can
+ be used to indicate that no salt is to be used when generating the NSEC3 chain.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-H <replaceable class="parameter">iterations</replaceable></term>
+ <listitem>
+ <para>
+ When generating a NSEC3 chain use this many interations. The
+ default is 100.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-A</term>
+ <listitem>
+ <para>
+ When generating a NSEC3 chain set the OPTOUT flag on all
+ NSEC3 records and do not generate NSEC3 records for insecure
+ delegations.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>zonefile</term>
+ <listitem>
+ <para>
+ The file containing the zone to be signed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>key</term>
+ <listitem>
+ <para>
+ Specify which keys should be used to sign the zone. If
+ no keys are specified, then the zone will be examined
+ for DNSKEY records at the zone apex. If these are found and
+ there are matching private keys, in the current directory,
+ then these will be used for signing.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLE</title>
+ <para>
+ The following command signs the <userinput>example.com</userinput>
+ zone with the DSA key generated by <command>dnssec-keygen</command>
+ (Kexample.com.+003+17247). The zone's keys must be in the master
+ file (<filename>db.example.com</filename>). This invocation looks
+ for <filename>keyset</filename> files, in the current directory,
+ so that DS records can be generated from them (<command>-g</command>).
+ </para>
+<programlisting>% dnssec-signzone -g -o example.com db.example.com \
+Kexample.com.+003+17247
+db.example.com.signed
+%</programlisting>
+ <para>
+ In the above example, <command>dnssec-signzone</command> creates
+ the file <filename>db.example.com.signed</filename>. This
+ file should be referenced in a zone statement in a
+ <filename>named.conf</filename> file.
+ </para>
+ <para>
+ This example re-signs a previously signed zone with default parameters.
+ The private keys are assumed to be in the current directory.
+ </para>
+<programlisting>% cp db.example.com.signed db.example.com
+% dnssec-signzone -o example.com db.example.com
+db.example.com.signed
+%</programlisting>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>,
+ <citetitle>RFC 4033</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dnssec/dnssec-signzone.html b/bin/dnssec/dnssec-signzone.html
new file mode 100644
index 0000000..6548d84
--- /dev/null
+++ b/bin/dnssec/dnssec-signzone.html
@@ -0,0 +1,302 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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-signzone.html,v 1.33 2008/10/15 01:11:35 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-signzone</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.dnssec-signzone"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-signzone</span> &#8212; DNSSEC zone signing tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-signzone</code> [<code class="option">-a</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-d <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-e <em class="replaceable"><code>end-time</code></em></code>] [<code class="option">-f <em class="replaceable"><code>output-file</code></em></code>] [<code class="option">-g</code>] [<code class="option">-h</code>] [<code class="option">-k <em class="replaceable"><code>key</code></em></code>] [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>] [<code class="option">-i <em class="replaceable"><code>interval</code></em></code>] [<code class="option">-I <em class="replaceable"><code>input-format</code></em></code>] [<code class="option">-j <em class="replaceable"><code>jitter</code></em></code>] [<code class="option">-N <em class="replaceable"><code>soa-serial-format</code></em></code>] [<code class="option">-o <em class="replaceable"><code>origin</code></em></code>] [<code class="option">-O <em class="replaceable"><code>output-format</code></em></code>] [<code class="option">-p</code>] [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-s <em class="replaceable"><code>start-time</code></em></code>] [<code class="option">-t</code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-z</code>] [<code class="option">-3 <em class="replaceable"><code>salt</code></em></code>] [<code class="option">-H <em class="replaceable"><code>iterations</code></em></code>] [<code class="option">-A</code>] {zonefile} [key...]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543550"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-signzone</strong></span>
+ 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
+ <code class="filename">keyset</code> file for each child zone.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543565"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a</span></dt>
+<dd><p>
+ Verify all generated signatures.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Specifies the DNS class of the zone.
+ </p></dd>
+<dt><span class="term">-k <em class="replaceable"><code>key</code></em></span></dt>
+<dd><p>
+ Treat specified key as a key signing key ignoring any
+ key flags. This option may be specified multiple times.
+ </p></dd>
+<dt><span class="term">-l <em class="replaceable"><code>domain</code></em></span></dt>
+<dd><p>
+ Generate a DLV set in addition to the key (DNSKEY) and DS sets.
+ The domain is appended to the name of the records.
+ </p></dd>
+<dt><span class="term">-d <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Look for <code class="filename">keyset</code> files in
+ <code class="option">directory</code> as the directory
+ </p></dd>
+<dt><span class="term">-g</span></dt>
+<dd><p>
+ Generate DS records for child zones from keyset files.
+ Existing DS records will be removed.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>start-time</code></em></span></dt>
+<dd><p>
+ Specify the date and time when the generated RRSIG records
+ become valid. This can be either an absolute or relative
+ time. An absolute start time is indicated by a number
+ in YYYYMMDDHHMMSS notation; 20000530144500 denotes
+ 14:45:00 UTC on May 30th, 2000. A relative start time is
+ indicated by +N, which is N seconds from the current time.
+ If no <code class="option">start-time</code> is specified, the current
+ time minus 1 hour (to allow for clock skew) is used.
+ </p></dd>
+<dt><span class="term">-e <em class="replaceable"><code>end-time</code></em></span></dt>
+<dd><p>
+ Specify the date and time when the generated RRSIG records
+ expire. As with <code class="option">start-time</code>, 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 <code class="option">end-time</code> is
+ specified, 30 days from the start time is used as a default.
+ </p></dd>
+<dt><span class="term">-f <em class="replaceable"><code>output-file</code></em></span></dt>
+<dd><p>
+ The name of the output file containing the signed zone. The
+ default is to append <code class="filename">.signed</code> to
+ the
+ input filename.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">dnssec-signzone</strong></span>.
+ </p></dd>
+<dt><span class="term">-i <em class="replaceable"><code>interval</code></em></span></dt>
+<dd>
+<p>
+ When a previously-signed zone is passed as input, records
+ may be resigned. The <code class="option">interval</code> option
+ specifies the cycle interval as an offset from the current
+ time (in seconds). If a RRSIG record expires after the
+ cycle interval, it is retained. Otherwise, it is considered
+ to be expiring soon, and it will be replaced.
+ </p>
+<p>
+ The default cycle interval is one quarter of the difference
+ between the signature end and start times. So if neither
+ <code class="option">end-time</code> or <code class="option">start-time</code>
+ are specified, <span><strong class="command">dnssec-signzone</strong></span>
+ generates
+ signatures that are valid for 30 days, with a cycle
+ interval of 7.5 days. Therefore, if any existing RRSIG records
+ are due to expire in less than 7.5 days, they would be
+ replaced.
+ </p>
+</dd>
+<dt><span class="term">-I <em class="replaceable"><code>input-format</code></em></span></dt>
+<dd><p>
+ The format of the input zone file.
+ Possible formats are <span><strong class="command">"text"</strong></span> (default)
+ and <span><strong class="command">"raw"</strong></span>.
+ This option is primarily intended to be used for dynamic
+ signed zones so that the dumped zone file in a non-text
+ format containing updates can be signed directly.
+ The use of this option does not make much sense for
+ non-dynamic zones.
+ </p></dd>
+<dt><span class="term">-j <em class="replaceable"><code>jitter</code></em></span></dt>
+<dd>
+<p>
+ When signing a zone with a fixed signature lifetime, all
+ RRSIG records issued at the time of signing expires
+ simultaneously. If the zone is incrementally signed, i.e.
+ a previously-signed zone is passed as input to the signer,
+ all expired signatures have to be regenerated at about the
+ same time. The <code class="option">jitter</code> option specifies a
+ jitter window that will be used to randomize the signature
+ expire time, thus spreading incremental signature
+ regeneration over time.
+ </p>
+<p>
+ Signature lifetime jitter also to some extent benefits
+ validators and servers by spreading out cache expiration,
+ i.e. if large numbers of RRSIGs don't expire at the same time
+ from all caches there will be less congestion than if all
+ validators need to refetch at mostly the same time.
+ </p>
+</dd>
+<dt><span class="term">-n <em class="replaceable"><code>ncpus</code></em></span></dt>
+<dd><p>
+ Specifies the number of threads to use. By default, one
+ thread is started for each detected CPU.
+ </p></dd>
+<dt><span class="term">-N <em class="replaceable"><code>soa-serial-format</code></em></span></dt>
+<dd>
+<p>
+ The SOA serial number format of the signed zone.
+ Possible formats are <span><strong class="command">"keep"</strong></span> (default),
+ <span><strong class="command">"increment"</strong></span> and
+ <span><strong class="command">"unixtime"</strong></span>.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">"keep"</strong></span></span></dt>
+<dd><p>Do not modify the SOA serial number.</p></dd>
+<dt><span class="term"><span><strong class="command">"increment"</strong></span></span></dt>
+<dd><p>Increment the SOA serial number using RFC 1982
+ arithmetics.</p></dd>
+<dt><span class="term"><span><strong class="command">"unixtime"</strong></span></span></dt>
+<dd><p>Set the SOA serial number to the number of seconds
+ since epoch.</p></dd>
+</dl></div>
+</dd>
+<dt><span class="term">-o <em class="replaceable"><code>origin</code></em></span></dt>
+<dd><p>
+ The zone origin. If not specified, the name of the zone file
+ is assumed to be the origin.
+ </p></dd>
+<dt><span class="term">-O <em class="replaceable"><code>output-format</code></em></span></dt>
+<dd><p>
+ The format of the output file containing the signed zone.
+ Possible formats are <span><strong class="command">"text"</strong></span> (default)
+ and <span><strong class="command">"raw"</strong></span>.
+ </p></dd>
+<dt><span class="term">-p</span></dt>
+<dd><p>
+ Use pseudo-random data when signing the zone. This is faster,
+ but less secure, than using real random data. This option
+ may be useful when signing large zones or when the entropy
+ source is limited.
+ </p></dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomdev</code></em></span></dt>
+<dd><p>
+ Specifies the source of randomness. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p></dd>
+<dt><span class="term">-t</span></dt>
+<dd><p>
+ Print statistics at completion.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+<dt><span class="term">-z</span></dt>
+<dd><p>
+ Ignore KSK flag on key when determining what to sign.
+ </p></dd>
+<dt><span class="term">-3 <em class="replaceable"><code>salt</code></em></span></dt>
+<dd><p>
+ Generate a NSEC3 chain with the given hex encoded salt.
+ A dash (<em class="replaceable"><code>salt</code></em>) can
+ be used to indicate that no salt is to be used when generating the NSEC3 chain.
+ </p></dd>
+<dt><span class="term">-H <em class="replaceable"><code>iterations</code></em></span></dt>
+<dd><p>
+ When generating a NSEC3 chain use this many interations. The
+ default is 100.
+ </p></dd>
+<dt><span class="term">-A</span></dt>
+<dd><p>
+ When generating a NSEC3 chain set the OPTOUT flag on all
+ NSEC3 records and do not generate NSEC3 records for insecure
+ delegations.
+ </p></dd>
+<dt><span class="term">zonefile</span></dt>
+<dd><p>
+ The file containing the zone to be signed.
+ </p></dd>
+<dt><span class="term">key</span></dt>
+<dd><p>
+ Specify which keys should be used to sign the zone. If
+ no keys are specified, then the zone will be examined
+ for DNSKEY records at the zone apex. If these are found and
+ there are matching private keys, in the current directory,
+ then these will be used for signing.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544404"></a><h2>EXAMPLE</h2>
+<p>
+ The following command signs the <strong class="userinput"><code>example.com</code></strong>
+ zone with the DSA key generated by <span><strong class="command">dnssec-keygen</strong></span>
+ (Kexample.com.+003+17247). The zone's keys must be in the master
+ file (<code class="filename">db.example.com</code>). This invocation looks
+ for <code class="filename">keyset</code> files, in the current directory,
+ so that DS records can be generated from them (<span><strong class="command">-g</strong></span>).
+ </p>
+<pre class="programlisting">% dnssec-signzone -g -o example.com db.example.com \
+Kexample.com.+003+17247
+db.example.com.signed
+%</pre>
+<p>
+ In the above example, <span><strong class="command">dnssec-signzone</strong></span> creates
+ the file <code class="filename">db.example.com.signed</code>. This
+ file should be referenced in a zone statement in a
+ <code class="filename">named.conf</code> file.
+ </p>
+<p>
+ This example re-signs a previously signed zone with default parameters.
+ The private keys are assumed to be in the current directory.
+ </p>
+<pre class="programlisting">% cp db.example.com.signed db.example.com
+% dnssec-signzone -o example.com db.example.com
+db.example.com.signed
+%</pre>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544523"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 4033</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544548"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dnssec/dnssectool.c b/bin/dnssec/dnssectool.c
new file mode 100644
index 0000000..e933a06
--- /dev/null
+++ b/bin/dnssec/dnssectool.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: dnssectool.c,v 1.45 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+/*%
+ * DNSSEC Support Routines.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/list.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+#include <isc/print.h>
+
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+#include <dns/time.h>
+
+#include "dnssectool.h"
+
+extern int verbose;
+extern const char *program;
+
+typedef struct entropysource entropysource_t;
+
+struct entropysource {
+ isc_entropysource_t *source;
+ isc_mem_t *mctx;
+ ISC_LINK(entropysource_t) link;
+};
+
+static ISC_LIST(entropysource_t) sources;
+static fatalcallback_t *fatalcallback = NULL;
+
+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");
+ if (fatalcallback != NULL)
+ (*fatalcallback)();
+ exit(1);
+}
+
+void
+setfatalcallback(fatalcallback_t *callback) {
+ fatalcallback = callback;
+}
+
+void
+check_result(isc_result_t result, const char *message) {
+ if (result != ISC_R_SUCCESS)
+ fatal("%s: %s", message, isc_result_totext(result));
+}
+
+void
+vbprintf(int level, const char *fmt, ...) {
+ va_list ap;
+ if (level > verbose)
+ return;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s: ", program);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+void
+type_format(const dns_rdatatype_t type, 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_rdatatype_totext(type, &b);
+ check_result(result, "dns_rdatatype_totext()");
+ isc_buffer_usedregion(&b, &r);
+ r.base[r.length] = 0;
+}
+
+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));
+ 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;
+ isc_logconfig_t *logconfig = NULL;
+ isc_log_t *log = NULL;
+ int level;
+
+ if (verbose < 0)
+ verbose = 0;
+ switch (verbose) {
+ case 0:
+ /*
+ * We want to see warnings about things like out-of-zone
+ * data in the master file even when not verbose.
+ */
+ level = ISC_LOG_WARNING;
+ break;
+ case 1:
+ level = ISC_LOG_INFO;
+ break;
+ default:
+ level = ISC_LOG_DEBUG(verbose - 2 + 1);
+ break;
+ }
+
+ RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
+ isc_log_setcontext(log);
+ dns_log_init(log);
+ dns_log_setcontext(log);
+
+ RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
+
+ /*
+ * Set up a channel similar to default_stderr except:
+ * - the logging level is passed in
+ * - the program name and logging level are printed
+ * - no time stamp is printed
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(logconfig, "stderr",
+ ISC_LOG_TOFILEDESC,
+ level,
+ &destination,
+ ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
+ check_result(result, "isc_log_createchannel()");
+
+ RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
+ NULL, NULL) == ISC_R_SUCCESS);
+
+ *logp = log;
+}
+
+void
+cleanup_logging(isc_log_t **logp) {
+ isc_log_t *log;
+
+ REQUIRE(logp != NULL);
+
+ log = *logp;
+ if (log == NULL)
+ return;
+ isc_log_destroy(&log);
+ isc_log_setcontext(NULL);
+ dns_log_setcontext(NULL);
+ logp = NULL;
+}
+
+void
+setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
+ isc_result_t result;
+ isc_entropysource_t *source = NULL;
+ entropysource_t *elt;
+ int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
+
+ REQUIRE(ectx != NULL);
+
+ if (*ectx == NULL) {
+ result = isc_entropy_create(mctx, ectx);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not create entropy object");
+ ISC_LIST_INIT(sources);
+ }
+
+ if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
+ usekeyboard = ISC_ENTROPY_KEYBOARDYES;
+ randomfile = NULL;
+ }
+
+ result = isc_entropy_usebestsource(*ectx, &source, randomfile,
+ usekeyboard);
+
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize entropy source: %s",
+ isc_result_totext(result));
+
+ if (source != NULL) {
+ elt = isc_mem_get(mctx, sizeof(*elt));
+ if (elt == NULL)
+ fatal("out of memory");
+ elt->source = source;
+ elt->mctx = mctx;
+ ISC_LINK_INIT(elt, link);
+ ISC_LIST_APPEND(sources, elt, link);
+ }
+}
+
+void
+cleanup_entropy(isc_entropy_t **ectx) {
+ entropysource_t *source;
+ while (!ISC_LIST_EMPTY(sources)) {
+ source = ISC_LIST_HEAD(sources);
+ ISC_LIST_UNLINK(sources, source, link);
+ isc_entropy_destroysource(&source->source);
+ isc_mem_put(source->mctx, source, sizeof(*source));
+ }
+ isc_entropy_detach(ectx);
+}
+
+isc_stdtime_t
+strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
+ isc_int64_t val, offset;
+ isc_result_t result;
+ char *endp;
+
+ if (str[0] == '+') {
+ offset = strtol(str + 1, &endp, 0);
+ if (*endp != '\0')
+ fatal("time value %s is invalid", str);
+ 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 (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);
+ } else {
+ result = dns_time64_fromtext(str, &val);
+ if (result != ISC_R_SUCCESS)
+ fatal("time value %s is invalid", str);
+ }
+
+ return ((isc_stdtime_t) val);
+}
+
+dns_rdataclass_t
+strtoclass(const char *str) {
+ isc_textregion_t r;
+ dns_rdataclass_t rdclass;
+ isc_result_t ret;
+
+ if (str == NULL)
+ return dns_rdataclass_in;
+ DE_CONST(str, r.base);
+ r.length = strlen(str);
+ ret = dns_rdataclass_fromtext(&rdclass, &r);
+ if (ret != ISC_R_SUCCESS)
+ fatal("unknown class %s", str);
+ return (rdclass);
+}
diff --git a/bin/dnssec/dnssectool.h b/bin/dnssec/dnssectool.h
new file mode 100644
index 0000000..ee476f4
--- /dev/null
+++ b/bin/dnssec/dnssectool.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 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
+ * 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: dnssectool.h,v 1.22 2008/09/25 04:02:38 tbox Exp $ */
+
+#ifndef DNSSECTOOL_H
+#define DNSSECTOOL_H 1
+
+#include <isc/log.h>
+#include <isc/stdtime.h>
+#include <dns/rdatastruct.h>
+#include <dst/dst.h>
+
+typedef void (fatalcallback_t)(void);
+
+void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+setfatalcallback(fatalcallback_t *callback);
+
+void
+check_result(isc_result_t result, const char *message);
+
+void
+vbprintf(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
+
+void
+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 10
+
+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"))
+
+void
+setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp);
+
+void
+cleanup_logging(isc_log_t **logp);
+
+void
+setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx);
+
+void
+cleanup_entropy(isc_entropy_t **ectx);
+
+isc_stdtime_t
+strtotime(const char *str, isc_int64_t now, isc_int64_t base);
+
+dns_rdataclass_t
+strtoclass(const char *str);
+
+#endif /* DNSSEC_DNSSECTOOL_H */
diff --git a/bin/dnssec/win32/dnssectool.dsp b/bin/dnssec/win32/dnssectool.dsp
new file mode 100644
index 0000000..ebc4b11
--- /dev/null
+++ b/bin/dnssec/win32/dnssectool.dsp
@@ -0,0 +1,113 @@
+# Microsoft Developer Studio Project File - Name="dnssectool" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static-Link Library" 0x0104
+
+CFG=dnssectool - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dnssectool.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dnssectool.mak" CFG="dnssectool - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dnssectool - Win32 Release" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE "dnssectool - Win32 Debug" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dnssectool - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /YX /FD /c /Fddnssectool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/dnssectool.lib"
+
+!ELSEIF "$(CFG)" == "dnssectool - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR /YX /FD /GZ /c /Fddnssectool
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug out:"Debug/dnssectool.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "dnssectool - Win32 Release"
+# Name "dnssectool - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\dnssectool.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/dnssectool.dsw b/bin/dnssec/win32/dnssectool.dsw
new file mode 100644
index 0000000..1049441
--- /dev/null
+++ b/bin/dnssec/win32/dnssectool.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dighost"=".\dnssectool.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/keygen.dsp b/bin/dnssec/win32/keygen.dsp
new file mode 100644
index 0000000..5eb70f0
--- /dev/null
+++ b/bin/dnssec/win32/keygen.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="keygen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=keygen - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "keygen.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keygen.mak" CFG="keygen - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keygen - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "keygen - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "keygen - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/dnssec-keygen.exe"
+
+!ELSEIF "$(CFG)" == "keygen - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/dnssec-keygen.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "keygen - Win32 Release"
+# Name "keygen - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-keygen.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/keygen.dsw b/bin/dnssec/win32/keygen.dsw
new file mode 100644
index 0000000..f988651
--- /dev/null
+++ b/bin/dnssec/win32/keygen.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "keygen"=".\keygen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/keygen.mak b/bin/dnssec/win32/keygen.mak
new file mode 100644
index 0000000..faf134a
--- /dev/null
+++ b/bin/dnssec/win32/keygen.mak
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on keygen.dsp
+!IF "$(CFG)" == ""
+CFG=keygen - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to keygen - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "keygen - Win32 Release" && "$(CFG)" != "keygen - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "keygen.mak" CFG="keygen - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "keygen - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "keygen - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "keygen - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "keygen - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-keygen.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-keygen.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-keygen.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\keygen.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keygen.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-keygen.pdb" /machine:I386 /out:"../../../Build/Release/dnssec-keygen.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-keygen.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "keygen - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-keygen.exe" "$(OUTDIR)\keygen.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-keygen.obj"
+ -@erase "$(INTDIR)\dnssec-keygen.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-keygen.pdb"
+ -@erase "$(OUTDIR)\keygen.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-keygen.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-keygen.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\keygen.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-keygen.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\keygen.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-keygen.pdb" /debug /machine:I386 /out:"../../../Build/Debug/dnssec-keygen.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-keygen.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-keygen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("keygen.dep")
+!INCLUDE "keygen.dep"
+!ELSE
+!MESSAGE Warning: cannot find "keygen.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "keygen - Win32 Release" || "$(CFG)" == "keygen - Win32 Debug"
+SOURCE="..\dnssec-keygen.c"
+
+!IF "$(CFG)" == "keygen - Win32 Release"
+
+
+"$(INTDIR)\dnssec-keygen.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keygen - Win32 Debug"
+
+
+"$(INTDIR)\dnssec-keygen.obj" "$(INTDIR)\dnssec-keygen.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "keygen - Win32 Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "keygen - Win32 Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dnssec/win32/nsupdate.dsp b/bin/dnssec/win32/nsupdate.dsp
new file mode 100644
index 0000000..a818f42
--- /dev/null
+++ b/bin/dnssec/win32/nsupdate.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="nsupdate" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=nsupdate - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "nsupdate.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nsupdate.mak" CFG="nsupdate - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nsupdate - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "nsupdate - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nsupdate - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/lwres/win32/Release/liblwres.lib user32.lib advapi32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/nsupdate.exe"
+
+!ELSEIF "$(CFG)" == "nsupdate - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/lwres/win32/Debug/liblwres.lib user32.lib advapi32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/nsupdate.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "nsupdate - Win32 Release"
+# Name "nsupdate - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\nsupdate.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/nsupdate.dsw b/bin/dnssec/win32/nsupdate.dsw
new file mode 100644
index 0000000..5f0ac36
--- /dev/null
+++ b/bin/dnssec/win32/nsupdate.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "nsupdate"=".\nsupdate.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/signzone.dsp b/bin/dnssec/win32/signzone.dsp
new file mode 100644
index 0000000..6fd45d8
--- /dev/null
+++ b/bin/dnssec/win32/signzone.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="signzone" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=signzone - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "signzone.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "signzone.mak" CFG="signzone - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "signzone - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "signzone - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "signzone - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib Release/dnssectool.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/dnssec-signzone.exe"
+
+!ELSEIF "$(CFG)" == "signzone - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib Debug/dnssectool.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/dnssec-signzone.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "signzone - Win32 Release"
+# Name "signzone - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE="..\dnssec-signzone.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dnssec/win32/signzone.dsw b/bin/dnssec/win32/signzone.dsw
new file mode 100644
index 0000000..f3314b9
--- /dev/null
+++ b/bin/dnssec/win32/signzone.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "signzone"=".\signzone.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dnssec/win32/signzone.mak b/bin/dnssec/win32/signzone.mak
new file mode 100644
index 0000000..ff4887c
--- /dev/null
+++ b/bin/dnssec/win32/signzone.mak
@@ -0,0 +1,324 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on signzone.dsp
+!IF "$(CFG)" == ""
+CFG=signzone - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to signzone - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "signzone - Win32 Release" && "$(CFG)" != "signzone - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "signzone.mak" CFG="signzone - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "signzone - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "signzone - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "signzone - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "signzone - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\dnssec-signzone.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-signzone.obj"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dnssec-signzone.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "__STDC__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\signzone.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\signzone.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dnssec-signzone.pdb" /machine:I386 /out:"../../../Build/Release/dnssec-signzone.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-signzone.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Release\dnssec-signzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "signzone - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\dnssec-signzone.exe" "$(OUTDIR)\signzone.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\dnssec-signzone.obj"
+ -@erase "$(INTDIR)\dnssec-signzone.sbr"
+ -@erase "$(INTDIR)\dnssectool.obj"
+ -@erase "$(INTDIR)\dnssectool.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dnssec-signzone.pdb"
+ -@erase "$(OUTDIR)\signzone.bsc"
+ -@erase "..\..\..\Build\Debug\dnssec-signzone.exe"
+ -@erase "..\..\..\Build\Debug\dnssec-signzone.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\signzone.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dnssec-signzone.sbr" \
+ "$(INTDIR)\dnssectool.sbr"
+
+"$(OUTDIR)\signzone.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dnssec-signzone.pdb" /debug /machine:I386 /out:"../../../Build/Debug/dnssec-signzone.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dnssec-signzone.obj" \
+ "$(INTDIR)\dnssectool.obj"
+
+"..\..\..\Build\Debug\dnssec-signzone.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("signzone.dep")
+!INCLUDE "signzone.dep"
+!ELSE
+!MESSAGE Warning: cannot find "signzone.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "signzone - Win32 Release" || "$(CFG)" == "signzone - Win32 Debug"
+SOURCE="..\dnssec-signzone.c"
+
+!IF "$(CFG)" == "signzone - Win32 Release"
+
+
+"$(INTDIR)\dnssec-signzone.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "signzone - Win32 Debug"
+
+
+"$(INTDIR)\dnssec-signzone.obj" "$(INTDIR)\dnssec-signzone.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dnssectool.c
+
+!IF "$(CFG)" == "signzone - Win32 Release"
+
+
+"$(INTDIR)\dnssectool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "signzone - Win32 Debug"
+
+
+"$(INTDIR)\dnssectool.obj" "$(INTDIR)\dnssectool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/named/Makefile.in b/bin/named/Makefile.in
new file mode 100644
index 0000000..4d800a6
--- /dev/null
+++ b/bin/named/Makefile.in
@@ -0,0 +1,154 @@
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-2002 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.101 2008/09/23 17:25:47 jinmei Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_CONFIGARGS@
+
+@BIND9_MAKE_INCLUDES@
+
+#
+# Add database drivers here.
+#
+DBDRIVER_OBJS =
+DBDRIVER_SRCS =
+DBDRIVER_INCLUDES =
+DBDRIVER_LIBS =
+
+DLZ_DRIVER_DIR = ${top_srcdir}/contrib/dlz/drivers
+
+DLZDRIVER_OBJS = @DLZ_DRIVER_OBJS@
+DLZDRIVER_SRCS = @DLZ_DRIVER_SRCS@
+DLZDRIVER_INCLUDES = @DLZ_DRIVER_INCLUDES@
+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}
+
+CDEFINES = @USE_DLZ@
+
+CWARNINGS =
+
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCCCLIBS = ../../lib/isccc/libisccc.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+LWRESLIBS = ../../lib/lwres/liblwres.@A@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+ISCCCDEPLIBS = ../../lib/isccc/libisccc.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+
+DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \
+ ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} \
+ ${ISCCFGLIBS} ${ISCCCLIBS} ${ISCLIBS} \
+ ${DLZDRIVER_LIBS} ${DBDRIVER_LIBS} @LIBS@
+
+SUBDIRS = unix
+
+TARGETS = named@EXEEXT@ lwresd@EXEEXT@
+
+OBJS = builtin.@O@ client.@O@ config.@O@ control.@O@ \
+ controlconf.@O@ interfacemgr.@O@ \
+ listenlist.@O@ log.@O@ logconf.@O@ main.@O@ notify.@O@ \
+ query.@O@ server.@O@ sortlist.@O@ statschannel.@O@ \
+ tkeyconf.@O@ tsigconf.@O@ update.@O@ xfrout.@O@ \
+ zoneconf.@O@ \
+ lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \
+ lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ \
+ ${DLZDRIVER_OBJS} ${DBDRIVER_OBJS}
+
+UOBJS = unix/os.@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 \
+ tkeyconf.c tsigconf.c update.c xfrout.c \
+ zoneconf.c \
+ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \
+ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \
+ ${DLZDRIVER_SRCS} ${DBDRIVER_SRCS}
+
+MANPAGES = named.8 lwresd.8 named.conf.5
+
+HTMLPAGES = named.html lwresd.html named.conf.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+main.@O@: main.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DCONFIGARGS="\"${CONFIGARGS}\"" \
+ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \
+ -DNS_SYSCONFDIR=\"${sysconfdir}\" -c ${srcdir}/main.c
+
+config.@O@: config.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \
+ -c ${srcdir}/config.c
+
+named@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ ${OBJS} ${UOBJS} ${LIBS}
+
+lwresd@EXEEXT@: named@EXEEXT@
+ rm -f lwresd@EXEEXT@
+ @LN@ named@EXEEXT@ lwresd@EXEEXT@
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS} ${OBJS}
+
+bind9.xsl.h: bind9.xsl convertxsl.pl
+ ${PERL} ${srcdir}/convertxsl.pl < ${srcdir}/bind9.xsl > bind9.xsl.h
+
+depend: bind9.xsl.h
+statschannel.@O@: bind9.xsl.h
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+install:: named@EXEEXT@ lwresd@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named@EXEEXT@ ${DESTDIR}${sbindir}
+ (cd ${DESTDIR}${sbindir}; rm -f lwresd@EXEEXT@; @LN@ named@EXEEXT@ lwresd@EXEEXT@)
+ ${INSTALL_DATA} ${srcdir}/named.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/lwresd.8 ${DESTDIR}${mandir}/man8
+ ${INSTALL_DATA} ${srcdir}/named.conf.5 ${DESTDIR}${mandir}/man5
+
+@DLZ_DRIVER_RULES@
diff --git a/bin/named/bind9.xsl b/bin/named/bind9.xsl
new file mode 100644
index 0000000..b6562b8
--- /dev/null
+++ b/bin/named/bind9.xsl
@@ -0,0 +1,481 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ - Copyright (C) 2006-2008 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.xsl,v 1.19 2008/07/17 23:43:26 jinmei Exp $ -->
+
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:template match="isc/bind/statistics">
+ <html>
+ <head>
+ <style type="text/css">
+body {
+ font-family: sans-serif;
+ background-color: #ffffff;
+ color: #000000;
+}
+
+table {
+ border-collapse: collapse;
+}
+
+tr.rowh {
+ text-align: center;
+ border: 1px solid #000000;
+ background-color: #8080ff;
+ color: #ffffff;
+}
+
+tr.row {
+ text-align: right;
+ border: 1px solid #000000;
+ background-color: teal;
+ color: #ffffff;
+}
+
+tr.lrow {
+ text-align: left;
+ border: 1px solid #000000;
+ background-color: teal;
+ color: #ffffff;
+}
+
+td, th {
+ padding-right: 5px;
+ padding-left: 5px;
+}
+
+.header h1 {
+ background-color: teal;
+ color: #ffffff;
+ padding: 4px;
+}
+
+.content {
+ background-color: #ffffff;
+ color: #000000;
+ padding: 4px;
+}
+
+.item {
+ padding: 4px;
+ align: right;
+}
+
+.value {
+ padding: 4px;
+ font-weight: bold;
+}
+
+div.statcounter h2 {
+ text-align: center;
+ font-size: large;
+ border: 1px solid #000000;
+ background-color: #8080ff;
+ color: #ffffff;
+}
+
+div.statcounter dl {
+ float: left;
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+div.statcounter dt {
+ width: 200px;
+ text-align: center;
+ font-weight: bold;
+ border: 0.5px solid #000000;
+ background-color: #8080ff;
+ color: #ffffff;
+}
+
+div.statcounter dd {
+ width: 200px;
+ text-align: right;
+ border: 0.5px solid #000000;
+ background-color: teal;
+ color: #ffffff;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+div.statcounter br {
+ clear: left;
+}
+ </style>
+ <title>BIND 9 Statistics</title>
+ </head>
+ <body>
+ <div class="header">
+ <h1>Bind 9 Configuration and Statistics</h1>
+ </div>
+
+ <br/>
+
+ <table>
+ <tr class="rowh"><th colspan="2">Times</th></tr>
+ <tr class="lrow">
+ <td>boot-time</td>
+ <td><xsl:value-of select="server/boot-time"/></td>
+ </tr>
+ <tr class="lrow">
+ <td>current-time</td>
+ <td><xsl:value-of select="server/current-time"/></td>
+ </tr>
+ </table>
+
+ <br/>
+
+ <table>
+ <tr class="rowh"><th colspan="2">Incoming Requests</th></tr>
+ <xsl:for-each select="server/requests/opcode">
+ <tr class="lrow">
+ <td><xsl:value-of select="name"/></td>
+ <td><xsl:value-of select="counter"/></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+
+ <br/>
+
+ <table>
+ <tr class="rowh"><th colspan="2">Incoming Queries</th></tr>
+ <xsl:for-each select="server/queries-in/rdtype">
+ <tr class="lrow">
+ <td><xsl:value-of select="name"/></td>
+ <td><xsl:value-of select="counter"/></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+
+ <br/>
+
+ <xsl:for-each select="views/view">
+ <table>
+ <tr class="rowh">
+ <th colspan="2">Outgoing Queries from View <xsl:value-of select="name"/></th>
+ </tr>
+ <xsl:for-each select="rdtype">
+ <tr class="lrow">
+ <td><xsl:value-of select="name"/></td>
+ <td><xsl:value-of select="counter"/></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:for-each>
+
+ <br/>
+
+ <div class="statcounter">
+ <h2>Server Statistics</h2>
+ <xsl:for-each select="server/nsstat">
+ <dl>
+ <dt><xsl:value-of select="name"/></dt>
+ <dd><xsl:value-of select="counter"/></dd>
+ </dl>
+ </xsl:for-each>
+ <br/>
+ </div>
+
+ <div class="statcounter">
+ <h2>Zone Maintenance Statistics</h2>
+ <xsl:for-each select="server/zonestat">
+ <dl>
+ <dt><xsl:value-of select="name"/></dt>
+ <dd><xsl:value-of select="counter"/></dd>
+ </dl>
+ </xsl:for-each>
+ <br />
+ </div>
+
+ <div class="statcounter">
+ <h2>Resolver Statistics (Common)</h2>
+ <xsl:for-each select="server/resstat">
+ <dl>
+ <dt><xsl:value-of select="name"/></dt>
+ <dd><xsl:value-of select="counter"/></dd>
+ </dl>
+ </xsl:for-each>
+ <br />
+ </div>
+
+ <xsl:for-each select="views/view">
+ <div class="statcounter">
+ <h2>Resolver Statistics for View <xsl:value-of select="name"/></h2>
+ <xsl:for-each select="resstat">
+ <dl>
+ <dt><xsl:value-of select="name"/></dt>
+ <dd><xsl:value-of select="counter"/></dd>
+ </dl>
+ </xsl:for-each>
+ <br />
+ </div>
+ </xsl:for-each>
+
+ <br />
+
+ <xsl:for-each select="views/view">
+ <table>
+ <tr class="rowh">
+ <th colspan="2">Cache DB RRsets for View <xsl:value-of select="name"/></th>
+ </tr>
+ <xsl:for-each select="cache/rrset">
+ <tr class="lrow">
+ <td><xsl:value-of select="name"/></td>
+ <td><xsl:value-of select="counter"/></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:for-each>
+
+ <br/>
+
+ <xsl:for-each select="views/view">
+ <table>
+ <tr class="rowh">
+ <th colspan="10">Zones for View <xsl:value-of select="name"/></th>
+ </tr>
+ <tr class="rowh">
+ <th>Name</th>
+ <th>Class</th>
+ <th>Serial</th>
+ <th>Success</th>
+ <th>Referral</th>
+ <th>NXRRSET</th>
+ <th>NXDOMAIN</th>
+ <th>Failure</th>
+ <th>XfrReqDone</th>
+ <th>XfrRej</th>
+ </tr>
+ <xsl:for-each select="zones/zone">
+ <tr class="lrow">
+ <td>
+ <xsl:value-of select="name"/>
+ </td>
+ <td>
+ <xsl:value-of select="rdataclass"/>
+ </td>
+ <td>
+ <xsl:value-of select="serial"/>
+ </td>
+ <td>
+ <xsl:value-of select="counters/QrySuccess"/>
+ </td>
+ <td>
+ <xsl:value-of select="counters/QryReferral"/>
+ </td>
+ <td>
+ <xsl:value-of select="counters/QryNxrrset"/>
+ </td>
+ <td>
+ <xsl:value-of select="counters/QryNXDOMAIN"/>
+ </td>
+ <td>
+ <xsl:value-of select="counters/QryFailure"/>
+ </td>
+ <td>
+ <xsl:value-of select="counters/XfrReqDone"/>
+ </td>
+ <td>
+ <xsl:value-of select="counters/XfrRej"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ </xsl:for-each>
+
+ <br/>
+
+ <table>
+ <tr class="rowh">
+ <th colspan="7">Network Status</th>
+ </tr>
+ <tr class="rowh">
+ <th>ID</th>
+ <th>Name</th>
+ <th>Type</th>
+ <th>References</th>
+ <th>LocalAddress</th>
+ <th>PeerAddress</th>
+ <th>State</th>
+ </tr>
+ <xsl:for-each select="socketmgr/sockets/socket">
+ <tr class="lrow">
+ <td>
+ <xsl:value-of select="id"/>
+ </td>
+ <td>
+ <xsl:value-of select="name"/>
+ </td>
+ <td>
+ <xsl:value-of select="type"/>
+ </td>
+ <td>
+ <xsl:value-of select="references"/>
+ </td>
+ <td>
+ <xsl:value-of select="local-address"/>
+ </td>
+ <td>
+ <xsl:value-of select="peer-address"/>
+ </td>
+ <td>
+ <xsl:for-each select="states">
+ <xsl:value-of select="."/>
+ </xsl:for-each>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br/>
+ <table>
+ <tr class="rowh">
+ <th colspan="2">Task Manager Configuration</th>
+ </tr>
+ <tr class="lrow">
+ <td>Thread-Model</td>
+ <td>
+ <xsl:value-of select="taskmgr/thread-model/type"/>
+ </td>
+ </tr>
+ <tr class="lrow">
+ <td>Worker Threads</td>
+ <td>
+ <xsl:value-of select="taskmgr/thread-model/worker-threads"/>
+ </td>
+ </tr>
+ <tr class="lrow">
+ <td>Default Quantum</td>
+ <td>
+ <xsl:value-of select="taskmgr/thread-model/default-quantum"/>
+ </td>
+ </tr>
+ <tr class="lrow">
+ <td>Tasks Running</td>
+ <td>
+ <xsl:value-of select="taskmgr/thread-model/tasks-running"/>
+ </td>
+ </tr>
+ </table>
+ <br/>
+ <table>
+ <tr class="rowh">
+ <th colspan="5">Tasks</th>
+ </tr>
+ <tr class="rowh">
+ <th>ID</th>
+ <th>Name</th>
+ <th>References</th>
+ <th>State</th>
+ <th>Quantum</th>
+ </tr>
+ <xsl:for-each select="taskmgr/tasks/task">
+ <tr class="lrow">
+ <td>
+ <xsl:value-of select="id"/>
+ </td>
+ <td>
+ <xsl:value-of select="name"/>
+ </td>
+ <td>
+ <xsl:value-of select="references"/>
+ </td>
+ <td>
+ <xsl:value-of select="state"/>
+ </td>
+ <td>
+ <xsl:value-of select="quantum"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br />
+ <table>
+ <tr class="rowh">
+ <th colspan="4">Memory Usage Summary</th>
+ </tr>
+ <xsl:for-each select="memory/summary/*">
+ <tr class="lrow">
+ <td><xsl:value-of select="name()"/></td>
+ <td><xsl:value-of select="."/></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ <br />
+ <table>
+ <tr class="rowh">
+ <th colspan="10">Memory Contexts</th>
+ </tr>
+ <tr class="rowh">
+ <th>ID</th>
+ <th>Name</th>
+ <th>References</th>
+ <th>TotalUse</th>
+ <th>InUse</th>
+ <th>MaxUse</th>
+ <th>BlockSize</th>
+ <th>Pools</th>
+ <th>HiWater</th>
+ <th>LoWater</th>
+ </tr>
+ <xsl:for-each select="memory/contexts/context">
+ <tr class="lrow">
+ <td>
+ <xsl:value-of select="id"/>
+ </td>
+ <td>
+ <xsl:value-of select="name"/>
+ </td>
+ <td>
+ <xsl:value-of select="references"/>
+ </td>
+ <td>
+ <xsl:value-of select="total"/>
+ </td>
+ <td>
+ <xsl:value-of select="inuse"/>
+ </td>
+ <td>
+ <xsl:value-of select="maxinuse"/>
+ </td>
+ <td>
+ <xsl:value-of select="blocksize"/>
+ </td>
+ <td>
+ <xsl:value-of select="pools"/>
+ </td>
+ <td>
+ <xsl:value-of select="hiwater"/>
+ </td>
+ <td>
+ <xsl:value-of select="lowater"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+
+ </body>
+ </html>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/bin/named/bind9.xsl.h b/bin/named/bind9.xsl.h
new file mode 100644
index 0000000..d9dc624
--- /dev/null
+++ b/bin/named/bind9.xsl.h
@@ -0,0 +1,486 @@
+/*
+ * Generated by convertxsl.pl 1.14 2008/07/17 23:43:26 jinmei Exp
+ * From bind9.xsl 1.19 2008/07/17 23:43:26 jinmei Exp
+ */
+static char xslmsg[] =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!--\n"
+ " - Copyright (C) 2006-2008 Internet Systems Consortium, Inc. (\"ISC\")\n"
+ " -\n"
+ " - Permission to use, copy, modify, and/or distribute this software for any\n"
+ " - purpose with or without fee is hereby granted, provided that the above\n"
+ " - copyright notice and this permission notice appear in all copies.\n"
+ " -\n"
+ " - THE SOFTWARE IS PROVIDED \"AS IS\" AND ISC DISCLAIMS ALL WARRANTIES WITH\n"
+ " - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\n"
+ " - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,\n"
+ " - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n"
+ " - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE\n"
+ " - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n"
+ " - PERFORMANCE OF THIS SOFTWARE.\n"
+ "-->\n"
+ "\n"
+ "<!-- \045Id: bind9.xsl,v 1.19 2008/07/17 23:43:26 jinmei Exp \045 -->\n"
+ "\n"
+ "<xsl:stylesheet version=\"1.0\"\n"
+ " xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n"
+ " xmlns=\"http://www.w3.org/1999/xhtml\">\n"
+ " <xsl:template match=\"isc/bind/statistics\">\n"
+ " <html>\n"
+ " <head>\n"
+ " <style type=\"text/css\">\n"
+ "body {\n"
+ " font-family: sans-serif;\n"
+ " background-color: #ffffff;\n"
+ " color: #000000;\n"
+ "}\n"
+ "\n"
+ "table {\n"
+ " border-collapse: collapse;\n"
+ "}\n"
+ "\n"
+ "tr.rowh {\n"
+ " text-align: center;\n"
+ " border: 1px solid #000000;\n"
+ " background-color: #8080ff;\n"
+ " color: #ffffff;\n"
+ "}\n"
+ "\n"
+ "tr.row {\n"
+ " text-align: right;\n"
+ " border: 1px solid #000000;\n"
+ " background-color: teal;\n"
+ " color: #ffffff;\n"
+ "}\n"
+ "\n"
+ "tr.lrow {\n"
+ " text-align: left;\n"
+ " border: 1px solid #000000;\n"
+ " background-color: teal;\n"
+ " color: #ffffff;\n"
+ "}\n"
+ "\n"
+ "td, th {\n"
+ " padding-right: 5px;\n"
+ " padding-left: 5px;\n"
+ "}\n"
+ "\n"
+ ".header h1 {\n"
+ " background-color: teal;\n"
+ " color: #ffffff;\n"
+ " padding: 4px;\n"
+ "}\n"
+ "\n"
+ ".content {\n"
+ " background-color: #ffffff;\n"
+ " color: #000000;\n"
+ " padding: 4px;\n"
+ "}\n"
+ "\n"
+ ".item {\n"
+ " padding: 4px;\n"
+ " align: right;\n"
+ "}\n"
+ "\n"
+ ".value {\n"
+ " padding: 4px;\n"
+ " font-weight: bold;\n"
+ "}\n"
+ "\n"
+ "div.statcounter h2 {\n"
+ " text-align: center;\n"
+ " font-size: large;\n"
+ " border: 1px solid #000000;\n"
+ " background-color: #8080ff;\n"
+ " color: #ffffff;\n"
+ "}\n"
+ "\n"
+ "div.statcounter dl {\n"
+ " float: left;\n"
+ " margin-top: 0;\n"
+ " margin-bottom: 0;\n"
+ " margin-left: 0;\n"
+ " margin-right: 0;\n"
+ "}\n"
+ "\n"
+ "div.statcounter dt {\n"
+ " width: 200px;\n"
+ " text-align: center;\n"
+ " font-weight: bold;\n"
+ " border: 0.5px solid #000000;\n"
+ " background-color: #8080ff;\n"
+ " color: #ffffff;\n"
+ "}\n"
+ "\n"
+ "div.statcounter dd {\n"
+ " width: 200px;\n"
+ " text-align: right;\n"
+ " border: 0.5px solid #000000;\n"
+ " background-color: teal;\n"
+ " color: #ffffff;\n"
+ " margin-left: 0;\n"
+ " margin-right: 0;\n"
+ "}\n"
+ "\n"
+ "div.statcounter br {\n"
+ " clear: left;\n"
+ "}\n"
+ " </style>\n"
+ " <title>BIND 9 Statistics</title>\n"
+ " </head>\n"
+ " <body>\n"
+ " <div class=\"header\">\n"
+ " <h1>Bind 9 Configuration and Statistics</h1>\n"
+ " </div>\n"
+ "\n"
+ " <br/>\n"
+ "\n"
+ " <table>\n"
+ " <tr class=\"rowh\"><th colspan=\"2\">Times</th></tr>\n"
+ " <tr class=\"lrow\">\n"
+ " <td>boot-time</td>\n"
+ " <td><xsl:value-of select=\"server/boot-time\"/></td>\n"
+ " </tr>\n"
+ " <tr class=\"lrow\">\n"
+ " <td>current-time</td>\n"
+ " <td><xsl:value-of select=\"server/current-time\"/></td>\n"
+ " </tr>\n"
+ " </table>\n"
+ "\n"
+ " <br/>\n"
+ "\n"
+ " <table>\n"
+ " <tr class=\"rowh\"><th colspan=\"2\">Incoming Requests</th></tr>\n"
+ " <xsl:for-each select=\"server/requests/opcode\">\n"
+ " <tr class=\"lrow\">\n"
+ " <td><xsl:value-of select=\"name\"/></td>\n"
+ " <td><xsl:value-of select=\"counter\"/></td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ "\n"
+ " <br/>\n"
+ "\n"
+ " <table>\n"
+ " <tr class=\"rowh\"><th colspan=\"2\">Incoming Queries</th></tr>\n"
+ " <xsl:for-each select=\"server/queries-in/rdtype\">\n"
+ " <tr class=\"lrow\">\n"
+ " <td><xsl:value-of select=\"name\"/></td>\n"
+ " <td><xsl:value-of select=\"counter\"/></td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ "\n"
+ " <br/>\n"
+ "\n"
+ " <xsl:for-each select=\"views/view\">\n"
+ " <table>\n"
+ " <tr class=\"rowh\">\n"
+ " <th colspan=\"2\">Outgoing Queries from View <xsl:value-of select=\"name\"/></th>\n"
+ " </tr>\n"
+ " <xsl:for-each select=\"rdtype\">\n"
+ " <tr class=\"lrow\">\n"
+ " <td><xsl:value-of select=\"name\"/></td>\n"
+ " <td><xsl:value-of select=\"counter\"/></td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:for-each>\n"
+ "\n"
+ " <br/>\n"
+ "\n"
+ " <div class=\"statcounter\">\n"
+ " <h2>Server Statistics</h2>\n"
+ " <xsl:for-each select=\"server/nsstat\">\n"
+ " <dl>\n"
+ " <dt><xsl:value-of select=\"name\"/></dt>\n"
+ " <dd><xsl:value-of select=\"counter\"/></dd>\n"
+ " </dl>\n"
+ " </xsl:for-each>\n"
+ " <br/>\n"
+ " </div>\n"
+ "\n"
+ " <div class=\"statcounter\">\n"
+ " <h2>Zone Maintenance Statistics</h2>\n"
+ " <xsl:for-each select=\"server/zonestat\">\n"
+ " <dl>\n"
+ " <dt><xsl:value-of select=\"name\"/></dt>\n"
+ " <dd><xsl:value-of select=\"counter\"/></dd>\n"
+ " </dl>\n"
+ " </xsl:for-each>\n"
+ " <br />\n"
+ " </div>\n"
+ "\n"
+ " <div class=\"statcounter\">\n"
+ " <h2>Resolver Statistics (Common)</h2>\n"
+ " <xsl:for-each select=\"server/resstat\">\n"
+ " <dl>\n"
+ " <dt><xsl:value-of select=\"name\"/></dt>\n"
+ " <dd><xsl:value-of select=\"counter\"/></dd>\n"
+ " </dl>\n"
+ " </xsl:for-each>\n"
+ " <br />\n"
+ " </div>\n"
+ "\n"
+ " <xsl:for-each select=\"views/view\">\n"
+ " <div class=\"statcounter\">\n"
+ " <h2>Resolver Statistics for View <xsl:value-of select=\"name\"/></h2>\n"
+ " <xsl:for-each select=\"resstat\">\n"
+ " <dl>\n"
+ " <dt><xsl:value-of select=\"name\"/></dt>\n"
+ " <dd><xsl:value-of select=\"counter\"/></dd>\n"
+ " </dl>\n"
+ " </xsl:for-each>\n"
+ " <br />\n"
+ " </div>\n"
+ " </xsl:for-each>\n"
+ "\n"
+ " <br />\n"
+ "\n"
+ " <xsl:for-each select=\"views/view\">\n"
+ " <table>\n"
+ " <tr class=\"rowh\">\n"
+ " <th colspan=\"2\">Cache DB RRsets for View <xsl:value-of select=\"name\"/></th>\n"
+ " </tr>\n"
+ " <xsl:for-each select=\"cache/rrset\">\n"
+ " <tr class=\"lrow\">\n"
+ " <td><xsl:value-of select=\"name\"/></td>\n"
+ " <td><xsl:value-of select=\"counter\"/></td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:for-each>\n"
+ "\n"
+ " <br/>\n"
+ "\n"
+ " <xsl:for-each select=\"views/view\">\n"
+ " <table>\n"
+ " <tr class=\"rowh\">\n"
+ " <th colspan=\"10\">Zones for View <xsl:value-of select=\"name\"/></th>\n"
+ " </tr>\n"
+ " <tr class=\"rowh\">\n"
+ " <th>Name</th>\n"
+ " <th>Class</th>\n"
+ " <th>Serial</th>\n"
+ " <th>Success</th>\n"
+ " <th>Referral</th>\n"
+ " <th>NXRRSET</th>\n"
+ " <th>NXDOMAIN</th>\n"
+ " <th>Failure</th>\n"
+ " <th>XfrReqDone</th>\n"
+ " <th>XfrRej</th>\n"
+ " </tr>\n"
+ " <xsl:for-each select=\"zones/zone\">\n"
+ " <tr class=\"lrow\">\n"
+ " <td>\n"
+ " <xsl:value-of select=\"name\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"rdataclass\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"serial\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"counters/QrySuccess\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"counters/QryReferral\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"counters/QryNxrrset\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"counters/QryNXDOMAIN\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"counters/QryFailure\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"counters/XfrReqDone\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"counters/XfrRej\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " </xsl:for-each>\n"
+ "\n"
+ " <br/>\n"
+ "\n"
+ " <table>\n"
+ " <tr class=\"rowh\">\n"
+ " <th colspan=\"7\">Network Status</th>\n"
+ " </tr>\n"
+ " <tr class=\"rowh\">\n"
+ " <th>ID</th>\n"
+ " <th>Name</th>\n"
+ " <th>Type</th>\n"
+ " <th>References</th>\n"
+ " <th>LocalAddress</th>\n"
+ " <th>PeerAddress</th>\n"
+ " <th>State</th>\n"
+ " </tr>\n"
+ " <xsl:for-each select=\"socketmgr/sockets/socket\">\n"
+ " <tr class=\"lrow\">\n"
+ " <td>\n"
+ " <xsl:value-of select=\"id\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"name\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"type\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"references\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"local-address\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"peer-address\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:for-each select=\"states\">\n"
+ " <xsl:value-of select=\".\"/>\n"
+ " </xsl:for-each>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br/>\n"
+ " <table>\n"
+ " <tr class=\"rowh\">\n"
+ " <th colspan=\"2\">Task Manager Configuration</th>\n"
+ " </tr>\n"
+ " <tr class=\"lrow\">\n"
+ " <td>Thread-Model</td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"taskmgr/thread-model/type\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr class=\"lrow\">\n"
+ " <td>Worker Threads</td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"taskmgr/thread-model/worker-threads\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr class=\"lrow\">\n"
+ " <td>Default Quantum</td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"taskmgr/thread-model/default-quantum\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr class=\"lrow\">\n"
+ " <td>Tasks Running</td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"taskmgr/thread-model/tasks-running\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </table>\n"
+ " <br/>\n"
+ " <table>\n"
+ " <tr class=\"rowh\">\n"
+ " <th colspan=\"5\">Tasks</th>\n"
+ " </tr>\n"
+ " <tr class=\"rowh\">\n"
+ " <th>ID</th>\n"
+ " <th>Name</th>\n"
+ " <th>References</th>\n"
+ " <th>State</th>\n"
+ " <th>Quantum</th>\n"
+ " </tr>\n"
+ " <xsl:for-each select=\"taskmgr/tasks/task\">\n"
+ " <tr class=\"lrow\">\n"
+ " <td>\n"
+ " <xsl:value-of select=\"id\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"name\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"references\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"state\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"quantum\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br />\n"
+ " <table>\n"
+ " <tr class=\"rowh\">\n"
+ " <th colspan=\"4\">Memory Usage Summary</th>\n"
+ " </tr>\n"
+ " <xsl:for-each select=\"memory/summary/*\">\n"
+ " <tr class=\"lrow\">\n"
+ " <td><xsl:value-of select=\"name()\"/></td>\n"
+ " <td><xsl:value-of select=\".\"/></td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ " <br />\n"
+ " <table>\n"
+ " <tr class=\"rowh\">\n"
+ " <th colspan=\"10\">Memory Contexts</th>\n"
+ " </tr>\n"
+ " <tr class=\"rowh\">\n"
+ " <th>ID</th>\n"
+ " <th>Name</th>\n"
+ " <th>References</th>\n"
+ " <th>TotalUse</th>\n"
+ " <th>InUse</th>\n"
+ " <th>MaxUse</th>\n"
+ " <th>BlockSize</th>\n"
+ " <th>Pools</th>\n"
+ " <th>HiWater</th>\n"
+ " <th>LoWater</th>\n"
+ " </tr>\n"
+ " <xsl:for-each select=\"memory/contexts/context\">\n"
+ " <tr class=\"lrow\">\n"
+ " <td>\n"
+ " <xsl:value-of select=\"id\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"name\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"references\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"total\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"inuse\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"maxinuse\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"blocksize\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"pools\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"hiwater\"/>\n"
+ " </td>\n"
+ " <td>\n"
+ " <xsl:value-of select=\"lowater\"/>\n"
+ " </td>\n"
+ " </tr>\n"
+ " </xsl:for-each>\n"
+ " </table>\n"
+ "\n"
+ " </body>\n"
+ " </html>\n"
+ " </xsl:template>\n"
+ "</xsl:stylesheet>\n";
diff --git a/bin/named/builtin.c b/bin/named/builtin.c
new file mode 100644
index 0000000..7927737
--- /dev/null
+++ b/bin/named/builtin.c
@@ -0,0 +1,307 @@
+/*
+ * 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: builtin.c,v 1.12 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * The built-in "version", "hostname", "id", "authors" and "empty" databases.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/result.h>
+#include <dns/sdb.h>
+
+#include <named/builtin.h>
+#include <named/globals.h>
+#include <named/server.h>
+#include <named/os.h>
+
+typedef struct builtin builtin_t;
+
+static isc_result_t do_version_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_hostname_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_authors_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_id_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup);
+
+/*
+ * We can't use function pointers as the db_data directly
+ * because ANSI C does not guarantee that function pointers
+ * can safely be cast to void pointers and back.
+ */
+
+struct builtin {
+ isc_result_t (*do_lookup)(dns_sdblookup_t *lookup);
+ char *server;
+ char *contact;
+};
+
+static builtin_t version_builtin = { do_version_lookup, NULL, NULL };
+static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL };
+static builtin_t authors_builtin = { do_authors_lookup, NULL, NULL };
+static builtin_t id_builtin = { do_id_lookup, NULL, NULL };
+static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL };
+
+static dns_sdbimplementation_t *builtin_impl;
+
+static isc_result_t
+builtin_lookup(const char *zone, const char *name, void *dbdata,
+ dns_sdblookup_t *lookup)
+{
+ builtin_t *b = (builtin_t *) dbdata;
+
+ UNUSED(zone);
+
+ if (strcmp(name, "@") == 0)
+ return (b->do_lookup(lookup));
+ else
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+put_txt(dns_sdblookup_t *lookup, const char *text) {
+ unsigned char buf[256];
+ unsigned int len = strlen(text);
+ if (len > 255)
+ len = 255; /* Silently truncate */
+ buf[0] = len;
+ memcpy(&buf[1], text, len);
+ return (dns_sdb_putrdata(lookup, dns_rdatatype_txt, 0, buf, len + 1));
+}
+
+static isc_result_t
+do_version_lookup(dns_sdblookup_t *lookup) {
+ if (ns_g_server->version_set) {
+ if (ns_g_server->version == NULL)
+ return (ISC_R_SUCCESS);
+ else
+ return (put_txt(lookup, ns_g_server->version));
+ } else {
+ return (put_txt(lookup, ns_g_version));
+ }
+}
+
+static isc_result_t
+do_hostname_lookup(dns_sdblookup_t *lookup) {
+ if (ns_g_server->hostname_set) {
+ if (ns_g_server->hostname == NULL)
+ return (ISC_R_SUCCESS);
+ else
+ return (put_txt(lookup, ns_g_server->hostname));
+ } else {
+ char buf[256];
+ isc_result_t result = ns_os_gethostname(buf, sizeof(buf));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (put_txt(lookup, buf));
+ }
+}
+
+static isc_result_t
+do_authors_lookup(dns_sdblookup_t *lookup) {
+ isc_result_t result;
+ const char **p;
+ static const char *authors[] = {
+ "Mark Andrews",
+ "James Brister",
+ "Ben Cottrell",
+ "Michael Graff",
+ "Andreas Gustafsson",
+ "Bob Halley",
+ "David Lawrence",
+ "Danny Mayer",
+ "Damien Neil",
+ "Matt Nelson",
+ "Michael Sawyer",
+ "Brian Wellington",
+ NULL
+ };
+
+ /*
+ * If a version string is specified, disable the authors.bind zone.
+ */
+ if (ns_g_server->version_set)
+ return (ISC_R_SUCCESS);
+
+ for (p = authors; *p != NULL; p++) {
+ result = put_txt(lookup, *p);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+do_id_lookup(dns_sdblookup_t *lookup) {
+
+ if (ns_g_server->server_usehostname) {
+ char buf[256];
+ isc_result_t result = ns_os_gethostname(buf, sizeof(buf));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (put_txt(lookup, buf));
+ }
+
+ if (ns_g_server->server_id == NULL)
+ return (ISC_R_SUCCESS);
+ else
+ return (put_txt(lookup, ns_g_server->server_id));
+}
+
+static isc_result_t
+do_empty_lookup(dns_sdblookup_t *lookup) {
+
+ UNUSED(lookup);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+builtin_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
+ isc_result_t result;
+ const char *contact = "hostmaster";
+ const char *server = "@";
+ builtin_t *b = (builtin_t *) dbdata;
+
+ UNUSED(zone);
+ UNUSED(dbdata);
+
+ if (b == &empty_builtin) {
+ server = ".";
+ contact = ".";
+ } else {
+ if (b->server != NULL)
+ server = b->server;
+ if (b->contact != NULL)
+ contact = b->contact;
+ }
+
+ result = dns_sdb_putsoa(lookup, server, contact, 0);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+
+ result = dns_sdb_putrr(lookup, "ns", 0, server);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+builtin_create(const char *zone, int argc, char **argv,
+ void *driverdata, void **dbdata)
+{
+ REQUIRE(argc >= 1);
+
+ UNUSED(zone);
+ UNUSED(driverdata);
+
+ if (strcmp(argv[0], "empty") == 0) {
+ if (argc != 3)
+ return (DNS_R_SYNTAX);
+ } else if (argc != 1)
+ return (DNS_R_SYNTAX);
+
+ if (strcmp(argv[0], "version") == 0)
+ *dbdata = &version_builtin;
+ else if (strcmp(argv[0], "hostname") == 0)
+ *dbdata = &hostname_builtin;
+ else if (strcmp(argv[0], "authors") == 0)
+ *dbdata = &authors_builtin;
+ else if (strcmp(argv[0], "id") == 0)
+ *dbdata = &id_builtin;
+ else if (strcmp(argv[0], "empty") == 0) {
+ builtin_t *empty;
+ char *server;
+ char *contact;
+ /*
+ * We don't want built-in zones to fail. Fallback to
+ * the static configuration if memory allocation fails.
+ */
+ empty = isc_mem_get(ns_g_mctx, sizeof(*empty));
+ 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 (server != NULL)
+ isc_mem_free(ns_g_mctx, server);
+ if (contact != NULL)
+ isc_mem_free(ns_g_mctx, contact);
+ if (empty != NULL)
+ isc_mem_put(ns_g_mctx, empty, sizeof (*empty));
+ } else {
+ memcpy(empty, &empty_builtin, sizeof (empty_builtin));
+ empty->server = server;
+ empty->contact = contact;
+ *dbdata = empty;
+ }
+ } else
+ return (ISC_R_NOTIMPLEMENTED);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+builtin_destroy(const char *zone, void *driverdata, void **dbdata) {
+ builtin_t *b = (builtin_t *) *dbdata;
+
+ UNUSED(zone);
+ UNUSED(driverdata);
+
+ /*
+ * Don't free the static versions.
+ */
+ if (*dbdata == &version_builtin || *dbdata == &hostname_builtin ||
+ *dbdata == &authors_builtin || *dbdata == &id_builtin ||
+ *dbdata == &empty_builtin)
+ return;
+
+ isc_mem_free(ns_g_mctx, b->server);
+ isc_mem_free(ns_g_mctx, b->contact);
+ isc_mem_put(ns_g_mctx, b, sizeof (*b));
+}
+
+static dns_sdbmethods_t builtin_methods = {
+ builtin_lookup,
+ builtin_authority,
+ NULL, /* allnodes */
+ builtin_create,
+ builtin_destroy
+};
+
+isc_result_t
+ns_builtin_init(void) {
+ RUNTIME_CHECK(dns_sdb_register("_builtin", &builtin_methods, NULL,
+ DNS_SDBFLAG_RELATIVEOWNER |
+ DNS_SDBFLAG_RELATIVERDATA,
+ ns_g_mctx, &builtin_impl)
+ == ISC_R_SUCCESS);
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_builtin_deinit(void) {
+ dns_sdb_unregister(&builtin_impl);
+}
diff --git a/bin/named/client.c b/bin/named/client.c
new file mode 100644
index 0000000..164af7c
--- /dev/null
+++ b/bin/named/client.c
@@ -0,0 +1,2798 @@
+/*
+ * Copyright (C) 2004-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
+ * 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.259 2008/11/16 20:57:54 marka Exp $ */
+
+#include <config.h>
+
+#include <isc/formatcheck.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/message.h>
+#include <dns/peer.h>
+#include <dns/rcode.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/resolver.h>
+#include <dns/stats.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+
+#include <named/interfacemgr.h>
+#include <named/log.h>
+#include <named/notify.h>
+#include <named/os.h>
+#include <named/server.h>
+#include <named/update.h>
+
+/***
+ *** Client
+ ***/
+
+/*! \file
+ * Client Routines
+ *
+ * Important note!
+ *
+ * All client state changes, other than that from idle to listening, occur
+ * as a result of events. This guarantees serialization and avoids the
+ * need for locking.
+ *
+ * If a routine is ever created that allows someone other than the client's
+ * task to change the client, then the client will have to be locked.
+ */
+
+#define NS_CLIENT_TRACE
+#ifdef NS_CLIENT_TRACE
+#define CTRACE(m) ns_client_log(client, \
+ NS_LOGCATEGORY_CLIENT, \
+ NS_LOGMODULE_CLIENT, \
+ ISC_LOG_DEBUG(3), \
+ "%s", (m))
+#define MTRACE(m) isc_log_write(ns_g_lctx, \
+ NS_LOGCATEGORY_GENERAL, \
+ NS_LOGMODULE_CLIENT, \
+ ISC_LOG_DEBUG(3), \
+ "clientmgr @%p: %s", manager, (m))
+#else
+#define CTRACE(m) ((void)(m))
+#define MTRACE(m) ((void)(m))
+#endif
+
+#define TCP_CLIENT(c) (((c)->attributes & NS_CLIENTATTR_TCP) != 0)
+
+#define TCP_BUFFER_SIZE (65535 + 2)
+#define SEND_BUFFER_SIZE 4096
+#define RECV_BUFFER_SIZE 4096
+
+#ifdef ISC_PLATFORM_USETHREADS
+#define NMCTXS 100
+/*%<
+ * Number of 'mctx pools' for clients. (Should this be configurable?)
+ * When enabling threads, we use a pool of memory contexts shared by
+ * client objects, since concurrent access to a shared context would cause
+ * heavy contentions. The above constant is expected to be enough for
+ * completely avoiding contentions among threads for an authoritative-only
+ * server.
+ */
+#else
+#define NMCTXS 0
+/*%<
+ * If named with built without thread, simply share manager's context. Using
+ * a separate context in this case would simply waste memory.
+ */
+#endif
+
+/*% nameserver client manager structure */
+struct ns_clientmgr {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ isc_taskmgr_t * taskmgr;
+ isc_timermgr_t * timermgr;
+ isc_mutex_t lock;
+ /* Locked by lock. */
+ isc_boolean_t exiting;
+ client_list_t active; /*%< Active clients */
+ client_list_t recursing; /*%< Recursing clients */
+ client_list_t inactive; /*%< To be recycled */
+#if NMCTXS > 0
+ /*%< mctx pool for clients. */
+ unsigned int nextmctx;
+ isc_mem_t * mctxpool[NMCTXS];
+#endif
+};
+
+#define MANAGER_MAGIC ISC_MAGIC('N', 'S', 'C', 'm')
+#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, MANAGER_MAGIC)
+
+/*!
+ * Client object states. Ordering is significant: higher-numbered
+ * states are generally "more active", meaning that the client can
+ * have more dynamically allocated data, outstanding events, etc.
+ * In the list below, any such properties listed for state N
+ * also apply to any state > N.
+ *
+ * To force the client into a less active state, set client->newstate
+ * to that state and call exit_check(). This will cause any
+ * activities defined for higher-numbered states to be aborted.
+ */
+
+#define NS_CLIENTSTATE_FREED 0
+/*%<
+ * The client object no longer exists.
+ */
+
+#define NS_CLIENTSTATE_INACTIVE 1
+/*%<
+ * The client object exists and has a task and timer.
+ * Its "query" struct and sendbuf are initialized.
+ * It is on the client manager's list of inactive clients.
+ * It has a message and OPT, both in the reset state.
+ */
+
+#define NS_CLIENTSTATE_READY 2
+/*%<
+ * The client object is either a TCP or a UDP one, and
+ * it is associated with a network interface. It is on the
+ * client manager's list of active clients.
+ *
+ * If it is a TCP client object, it has a TCP listener socket
+ * and an outstanding TCP listen request.
+ *
+ * If it is a UDP client object, it has a UDP listener socket
+ * and an outstanding UDP receive request.
+ */
+
+#define NS_CLIENTSTATE_READING 3
+/*%<
+ * The client object is a TCP client object that has received
+ * a connection. It has a tcpsocket, tcpmsg, TCP quota, and an
+ * outstanding TCP read request. This state is not used for
+ * UDP client objects.
+ */
+
+#define NS_CLIENTSTATE_WORKING 4
+/*%<
+ * The client object has received a request and is working
+ * on it. It has a view, and it may have any of a non-reset OPT,
+ * recursion quota, and an outstanding write request.
+ */
+
+#define NS_CLIENTSTATE_MAX 9
+/*%<
+ * Sentinel value used to indicate "no state". When client->newstate
+ * has this value, we are not attempting to exit the current state.
+ * Must be greater than any valid state.
+ */
+
+/*
+ * Enable ns_client_dropport() by default.
+ */
+#ifndef NS_CLIENT_DROPPORT
+#define NS_CLIENT_DROPPORT 1
+#endif
+
+unsigned int ns_client_requests;
+
+static void client_read(ns_client_t *client);
+static void client_accept(ns_client_t *client);
+static void client_udprecv(ns_client_t *client);
+static void clientmgr_destroy(ns_clientmgr_t *manager);
+static isc_boolean_t exit_check(ns_client_t *client);
+static void ns_client_endrequest(ns_client_t *client);
+static void ns_client_checkactive(ns_client_t *client);
+static void client_start(isc_task_t *task, isc_event_t *event);
+static void client_request(isc_task_t *task, isc_event_t *event);
+static void ns_client_dumpmessage(ns_client_t *client, const char *reason);
+
+void
+ns_client_recursing(ns_client_t *client) {
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ LOCK(&client->manager->lock);
+ ISC_LIST_UNLINK(*client->list, client, link);
+ ISC_LIST_APPEND(client->manager->recursing, client, link);
+ client->list = &client->manager->recursing;
+ UNLOCK(&client->manager->lock);
+}
+
+void
+ns_client_killoldestquery(ns_client_t *client) {
+ ns_client_t *oldest;
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ LOCK(&client->manager->lock);
+ oldest = ISC_LIST_HEAD(client->manager->recursing);
+ if (oldest != NULL) {
+ ns_query_cancel(oldest);
+ ISC_LIST_UNLINK(*oldest->list, oldest, link);
+ ISC_LIST_APPEND(client->manager->active, oldest, link);
+ oldest->list = &client->manager->active;
+ }
+ UNLOCK(&client->manager->lock);
+}
+
+void
+ns_client_settimeout(ns_client_t *client, unsigned int seconds) {
+ isc_result_t result;
+ isc_interval_t interval;
+
+ isc_interval_set(&interval, seconds, 0);
+ result = isc_timer_reset(client->timer, isc_timertype_once, NULL,
+ &interval, ISC_FALSE);
+ client->timerset = ISC_TRUE;
+ if (result != ISC_R_SUCCESS) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
+ "setting timeout: %s",
+ isc_result_totext(result));
+ /* Continue anyway. */
+ }
+}
+
+/*%
+ * Check for a deactivation or shutdown request and take appropriate
+ * action. Returns ISC_TRUE if either is in progress; in this case
+ * the caller must no longer use the client object as it may have been
+ * freed.
+ */
+static isc_boolean_t
+exit_check(ns_client_t *client) {
+ ns_clientmgr_t *locked_manager = NULL;
+ ns_clientmgr_t *destroy_manager = NULL;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ if (client->state <= client->newstate)
+ return (ISC_FALSE); /* Business as usual. */
+
+ INSIST(client->newstate < NS_CLIENTSTATE_WORKING);
+
+ /*
+ * We need to detach from the view early when shutting down
+ * the server to break the following vicious circle:
+ *
+ * - The resolver will not shut down until the view refcount is zero
+ * - The view refcount does not go to zero until all clients detach
+ * - The client does not detach from the view until references is zero
+ * - references does not go to zero until the resolver has shut down
+ *
+ * Keep the view attached until any outstanding updates complete.
+ */
+ if (client->nupdates == 0 &&
+ client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
+ dns_view_detach(&client->view);
+
+ if (client->state == NS_CLIENTSTATE_WORKING) {
+ INSIST(client->newstate <= NS_CLIENTSTATE_READING);
+ /*
+ * Let the update processing complete.
+ */
+ if (client->nupdates > 0)
+ return (ISC_TRUE);
+ /*
+ * We are trying to abort request processing.
+ */
+ if (client->nsends > 0) {
+ isc_socket_t *socket;
+ if (TCP_CLIENT(client))
+ socket = client->tcpsocket;
+ else
+ socket = client->udpsocket;
+ isc_socket_cancel(socket, client->task,
+ ISC_SOCKCANCEL_SEND);
+ }
+
+ if (! (client->nsends == 0 && client->nrecvs == 0 &&
+ client->references == 0))
+ {
+ /*
+ * Still waiting for I/O cancel completion.
+ * or lingering references.
+ */
+ return (ISC_TRUE);
+ }
+ /*
+ * I/O cancel is complete. Burn down all state
+ * related to the current request. Ensure that
+ * the client is on the active list and not the
+ * recursing list.
+ */
+ LOCK(&client->manager->lock);
+ if (client->list == &client->manager->recursing) {
+ ISC_LIST_UNLINK(*client->list, client, link);
+ ISC_LIST_APPEND(client->manager->active, client, link);
+ client->list = &client->manager->active;
+ }
+ UNLOCK(&client->manager->lock);
+ ns_client_endrequest(client);
+
+ client->state = NS_CLIENTSTATE_READING;
+ INSIST(client->recursionquota == NULL);
+ if (NS_CLIENTSTATE_READING == client->newstate) {
+ client_read(client);
+ client->newstate = NS_CLIENTSTATE_MAX;
+ return (ISC_TRUE); /* We're done. */
+ }
+ }
+
+ if (client->state == NS_CLIENTSTATE_READING) {
+ /*
+ * We are trying to abort the current TCP connection,
+ * if any.
+ */
+ INSIST(client->recursionquota == NULL);
+ INSIST(client->newstate <= NS_CLIENTSTATE_READY);
+ if (client->nreads > 0)
+ dns_tcpmsg_cancelread(&client->tcpmsg);
+ if (! client->nreads == 0) {
+ /* Still waiting for read cancel completion. */
+ return (ISC_TRUE);
+ }
+
+ if (client->tcpmsg_valid) {
+ dns_tcpmsg_invalidate(&client->tcpmsg);
+ client->tcpmsg_valid = ISC_FALSE;
+ }
+ if (client->tcpsocket != NULL) {
+ CTRACE("closetcp");
+ isc_socket_detach(&client->tcpsocket);
+ }
+
+ if (client->tcpquota != NULL)
+ isc_quota_detach(&client->tcpquota);
+
+ if (client->timerset) {
+ (void)isc_timer_reset(client->timer,
+ isc_timertype_inactive,
+ NULL, NULL, ISC_TRUE);
+ client->timerset = ISC_FALSE;
+ }
+
+ client->peeraddr_valid = ISC_FALSE;
+
+ client->state = NS_CLIENTSTATE_READY;
+ INSIST(client->recursionquota == NULL);
+
+ /*
+ * Now the client is ready to accept a new TCP connection
+ * or UDP request, but we may have enough clients doing
+ * that already. Check whether this client needs to remain
+ * active and force it to go inactive if not.
+ */
+ ns_client_checkactive(client);
+
+ if (NS_CLIENTSTATE_READY == client->newstate) {
+ if (TCP_CLIENT(client)) {
+ client_accept(client);
+ } else
+ client_udprecv(client);
+ client->newstate = NS_CLIENTSTATE_MAX;
+ return (ISC_TRUE);
+ }
+ }
+
+ if (client->state == NS_CLIENTSTATE_READY) {
+ INSIST(client->newstate <= NS_CLIENTSTATE_INACTIVE);
+ /*
+ * We are trying to enter the inactive state.
+ */
+ if (client->naccepts > 0)
+ isc_socket_cancel(client->tcplistener, client->task,
+ ISC_SOCKCANCEL_ACCEPT);
+
+ if (! (client->naccepts == 0)) {
+ /* Still waiting for accept cancel completion. */
+ return (ISC_TRUE);
+ }
+ /* Accept cancel is complete. */
+
+ if (client->nrecvs > 0)
+ isc_socket_cancel(client->udpsocket, client->task,
+ ISC_SOCKCANCEL_RECV);
+ if (! (client->nrecvs == 0)) {
+ /* Still waiting for recv cancel completion. */
+ return (ISC_TRUE);
+ }
+ /* Recv cancel is complete. */
+
+ if (client->nctls > 0) {
+ /* Still waiting for control event to be delivered */
+ return (ISC_TRUE);
+ }
+
+ /* Deactivate the client. */
+ if (client->interface)
+ ns_interface_detach(&client->interface);
+
+ INSIST(client->naccepts == 0);
+ INSIST(client->recursionquota == NULL);
+ if (client->tcplistener != NULL)
+ isc_socket_detach(&client->tcplistener);
+
+ if (client->udpsocket != NULL)
+ isc_socket_detach(&client->udpsocket);
+
+ if (client->dispatch != NULL)
+ dns_dispatch_detach(&client->dispatch);
+
+ client->attributes = 0;
+ client->mortal = ISC_FALSE;
+
+ LOCK(&client->manager->lock);
+ /*
+ * Put the client on the inactive list. If we are aiming for
+ * the "freed" state, it will be removed from the inactive
+ * list shortly, and we need to keep the manager locked until
+ * that has been done, lest the manager decide to reactivate
+ * the dying client inbetween.
+ */
+ locked_manager = client->manager;
+ ISC_LIST_UNLINK(*client->list, client, link);
+ ISC_LIST_APPEND(client->manager->inactive, client, link);
+ client->list = &client->manager->inactive;
+ client->state = NS_CLIENTSTATE_INACTIVE;
+ INSIST(client->recursionquota == NULL);
+
+ if (client->state == client->newstate) {
+ client->newstate = NS_CLIENTSTATE_MAX;
+ if (client->needshutdown)
+ isc_task_shutdown(client->task);
+ goto unlock;
+ }
+ }
+
+ if (client->state == NS_CLIENTSTATE_INACTIVE) {
+ INSIST(client->newstate == NS_CLIENTSTATE_FREED);
+ /*
+ * We are trying to free the client.
+ *
+ * When "shuttingdown" is true, either the task has received
+ * its shutdown event or no shutdown event has ever been
+ * set up. Thus, we have no outstanding shutdown
+ * event at this point.
+ */
+ REQUIRE(client->state == NS_CLIENTSTATE_INACTIVE);
+
+ INSIST(client->recursionquota == NULL);
+
+ ns_query_free(client);
+ isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
+ isc_event_free((isc_event_t **)&client->sendevent);
+ isc_event_free((isc_event_t **)&client->recvevent);
+ isc_timer_detach(&client->timer);
+
+ if (client->tcpbuf != NULL)
+ isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
+ if (client->opt != NULL) {
+ INSIST(dns_rdataset_isassociated(client->opt));
+ dns_rdataset_disassociate(client->opt);
+ dns_message_puttemprdataset(client->message, &client->opt);
+ }
+ dns_message_destroy(&client->message);
+ if (client->manager != NULL) {
+ ns_clientmgr_t *manager = client->manager;
+ if (locked_manager == NULL) {
+ LOCK(&manager->lock);
+ locked_manager = manager;
+ }
+ ISC_LIST_UNLINK(*client->list, client, link);
+ client->list = NULL;
+ if (manager->exiting &&
+ ISC_LIST_EMPTY(manager->active) &&
+ ISC_LIST_EMPTY(manager->inactive) &&
+ ISC_LIST_EMPTY(manager->recursing))
+ destroy_manager = manager;
+ }
+ /*
+ * Detaching the task must be done after unlinking from
+ * the manager's lists because the manager accesses
+ * client->task.
+ */
+ if (client->task != NULL)
+ isc_task_detach(&client->task);
+
+ CTRACE("free");
+ client->magic = 0;
+ /*
+ * Check that there are no other external references to
+ * the memory context.
+ */
+ if (ns_g_clienttest && isc_mem_references(client->mctx) != 1) {
+ isc_mem_stats(client->mctx, stderr);
+ INSIST(0);
+ }
+ isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
+
+ goto unlock;
+ }
+
+ unlock:
+ if (locked_manager != NULL) {
+ UNLOCK(&locked_manager->lock);
+ locked_manager = NULL;
+ }
+
+ /*
+ * Only now is it safe to destroy the client manager (if needed),
+ * because we have accessed its lock for the last time.
+ */
+ if (destroy_manager != NULL)
+ clientmgr_destroy(destroy_manager);
+
+ return (ISC_TRUE);
+}
+
+/*%
+ * The client's task has received the client's control event
+ * as part of the startup process.
+ */
+static void
+client_start(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client = (ns_client_t *) event->ev_arg;
+
+ INSIST(task == client->task);
+
+ UNUSED(task);
+
+ INSIST(client->nctls == 1);
+ client->nctls--;
+
+ if (exit_check(client))
+ return;
+
+ if (TCP_CLIENT(client)) {
+ client_accept(client);
+ } else {
+ client_udprecv(client);
+ }
+}
+
+
+/*%
+ * The client's task has received a shutdown event.
+ */
+static void
+client_shutdown(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client;
+
+ REQUIRE(event != NULL);
+ REQUIRE(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
+ client = event->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+
+ UNUSED(task);
+
+ CTRACE("shutdown");
+
+ isc_event_free(&event);
+
+ if (client->shutdown != NULL) {
+ (client->shutdown)(client->shutdown_arg, ISC_R_SHUTTINGDOWN);
+ client->shutdown = NULL;
+ client->shutdown_arg = NULL;
+ }
+
+ client->newstate = NS_CLIENTSTATE_FREED;
+ client->needshutdown = ISC_FALSE;
+ (void)exit_check(client);
+}
+
+static void
+ns_client_endrequest(ns_client_t *client) {
+ INSIST(client->naccepts == 0);
+ INSIST(client->nreads == 0);
+ INSIST(client->nsends == 0);
+ INSIST(client->nrecvs == 0);
+ INSIST(client->nupdates == 0);
+ INSIST(client->state == NS_CLIENTSTATE_WORKING);
+
+ CTRACE("endrequest");
+
+ if (client->next != NULL) {
+ (client->next)(client);
+ client->next = NULL;
+ }
+
+ if (client->view != NULL)
+ dns_view_detach(&client->view);
+ if (client->opt != NULL) {
+ INSIST(dns_rdataset_isassociated(client->opt));
+ dns_rdataset_disassociate(client->opt);
+ dns_message_puttemprdataset(client->message, &client->opt);
+ }
+
+ client->udpsize = 512;
+ client->extflags = 0;
+ client->ednsversion = -1;
+ dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
+
+ if (client->recursionquota != NULL)
+ isc_quota_detach(&client->recursionquota);
+
+ /*
+ * Clear all client attributes that are specific to
+ * the request; that's all except the TCP flag.
+ */
+ client->attributes &= NS_CLIENTATTR_TCP;
+}
+
+static void
+ns_client_checkactive(ns_client_t *client) {
+ if (client->mortal) {
+ /*
+ * This client object should normally go inactive
+ * at this point, but if we have fewer active client
+ * objects than desired due to earlier quota exhaustion,
+ * keep it active to make up for the shortage.
+ */
+ isc_boolean_t need_another_client = ISC_FALSE;
+ if (TCP_CLIENT(client) && !ns_g_clienttest) {
+ LOCK(&client->interface->lock);
+ if (client->interface->ntcpcurrent <
+ client->interface->ntcptarget)
+ need_another_client = ISC_TRUE;
+ UNLOCK(&client->interface->lock);
+ } else {
+ /*
+ * The UDP client quota is enforced by making
+ * requests fail rather than by not listening
+ * for new ones. Therefore, there is always a
+ * full set of UDP clients listening.
+ */
+ }
+ if (! need_another_client) {
+ /*
+ * We don't need this client object. Recycle it.
+ */
+ if (client->newstate >= NS_CLIENTSTATE_INACTIVE)
+ client->newstate = NS_CLIENTSTATE_INACTIVE;
+ }
+ }
+}
+
+void
+ns_client_next(ns_client_t *client, isc_result_t result) {
+ int newstate;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||
+ client->state == NS_CLIENTSTATE_READING);
+
+ CTRACE("next");
+
+ if (result != ISC_R_SUCCESS)
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "request failed: %s", isc_result_totext(result));
+
+ /*
+ * An error processing a TCP request may have left
+ * the connection out of sync. To be safe, we always
+ * sever the connection when result != ISC_R_SUCCESS.
+ */
+ if (result == ISC_R_SUCCESS && TCP_CLIENT(client))
+ newstate = NS_CLIENTSTATE_READING;
+ else
+ newstate = NS_CLIENTSTATE_READY;
+
+ if (client->newstate > newstate)
+ client->newstate = newstate;
+ (void)exit_check(client);
+}
+
+
+static void
+client_senddone(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client;
+ isc_socketevent_t *sevent = (isc_socketevent_t *) event;
+
+ REQUIRE(sevent != NULL);
+ REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
+ client = sevent->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+ REQUIRE(sevent == client->sendevent);
+
+ UNUSED(task);
+
+ CTRACE("senddone");
+
+ if (sevent->result != ISC_R_SUCCESS)
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
+ "error sending response: %s",
+ isc_result_totext(sevent->result));
+
+ INSIST(client->nsends > 0);
+ client->nsends--;
+
+ if (client->tcpbuf != NULL) {
+ INSIST(TCP_CLIENT(client));
+ isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
+ client->tcpbuf = NULL;
+ }
+
+ if (exit_check(client))
+ return;
+
+ ns_client_next(client, ISC_R_SUCCESS);
+}
+
+/*%
+ * We only want to fail with ISC_R_NOSPACE when called from
+ * ns_client_sendraw() and not when called from ns_client_send(),
+ * tcpbuffer is NULL when called from ns_client_sendraw() and
+ * length != 0. tcpbuffer != NULL when called from ns_client_send()
+ * and length == 0.
+ */
+
+static isc_result_t
+client_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,
+ isc_buffer_t *tcpbuffer, isc_uint32_t length,
+ unsigned char *sendbuf, unsigned char **datap)
+{
+ unsigned char *data;
+ isc_uint32_t bufsize;
+ isc_result_t result;
+
+ INSIST(datap != NULL);
+ INSIST((tcpbuffer == NULL && length != 0) ||
+ (tcpbuffer != NULL && length == 0));
+
+ if (TCP_CLIENT(client)) {
+ INSIST(client->tcpbuf == NULL);
+ if (length + 2 > TCP_BUFFER_SIZE) {
+ result = ISC_R_NOSPACE;
+ goto done;
+ }
+ client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);
+ if (client->tcpbuf == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto done;
+ }
+ data = client->tcpbuf;
+ if (tcpbuffer != NULL) {
+ isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);
+ isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);
+ } else {
+ isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);
+ INSIST(length <= 0xffff);
+ isc_buffer_putuint16(buffer, (isc_uint16_t)length);
+ }
+ } else {
+ data = sendbuf;
+ if (client->udpsize < SEND_BUFFER_SIZE)
+ bufsize = client->udpsize;
+ else
+ bufsize = SEND_BUFFER_SIZE;
+ if (length > bufsize) {
+ result = ISC_R_NOSPACE;
+ goto done;
+ }
+ isc_buffer_init(buffer, data, bufsize);
+ }
+ *datap = data;
+ result = ISC_R_SUCCESS;
+
+ done:
+ return (result);
+}
+
+static isc_result_t
+client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
+ struct in6_pktinfo *pktinfo;
+ isc_result_t result;
+ isc_region_t r;
+ isc_sockaddr_t *address;
+ isc_socket_t *socket;
+ isc_netaddr_t netaddr;
+ int match;
+ unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;
+
+ if (TCP_CLIENT(client)) {
+ socket = client->tcpsocket;
+ address = NULL;
+ } else {
+ socket = client->udpsocket;
+ address = &client->peeraddr;
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ if (ns_g_server->blackholeacl != NULL &&
+ dns_acl_match(&netaddr, NULL,
+ ns_g_server->blackholeacl,
+ &ns_g_server->aclenv,
+ &match, NULL) == ISC_R_SUCCESS &&
+ match > 0)
+ return (DNS_R_BLACKHOLED);
+ sockflags |= ISC_SOCKFLAG_NORETRY;
+ }
+
+ if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0 &&
+ (client->attributes & NS_CLIENTATTR_MULTICAST) == 0)
+ pktinfo = &client->pktinfo;
+ else
+ pktinfo = NULL;
+
+ isc_buffer_usedregion(buffer, &r);
+
+ CTRACE("sendto");
+
+ result = isc_socket_sendto2(socket, &r, client->task,
+ address, pktinfo,
+ client->sendevent, sockflags);
+ if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {
+ client->nsends++;
+ if (result == ISC_R_SUCCESS)
+ client_senddone(client->task,
+ (isc_event_t *)client->sendevent);
+ result = ISC_R_SUCCESS;
+ }
+ return (result);
+}
+
+void
+ns_client_sendraw(ns_client_t *client, dns_message_t *message) {
+ isc_result_t result;
+ unsigned char *data;
+ isc_buffer_t buffer;
+ isc_region_t r;
+ isc_region_t *mr;
+ unsigned char sendbuf[SEND_BUFFER_SIZE];
+
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ CTRACE("sendraw");
+
+ mr = dns_message_getrawmessage(message);
+ if (mr == NULL) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto done;
+ }
+
+ result = client_allocsendbuf(client, &buffer, NULL, mr->length,
+ sendbuf, &data);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+ /*
+ * Copy message to buffer and fixup id.
+ */
+ isc_buffer_availableregion(&buffer, &r);
+ result = isc_buffer_copyregion(&buffer, mr);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ r.base[0] = (client->message->id >> 8) & 0xff;
+ r.base[1] = client->message->id & 0xff;
+
+ result = client_sendpkg(client, &buffer);
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ done:
+ if (client->tcpbuf != NULL) {
+ isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
+ client->tcpbuf = NULL;
+ }
+ ns_client_next(client, result);
+}
+
+void
+ns_client_send(ns_client_t *client) {
+ isc_result_t result;
+ unsigned char *data;
+ isc_buffer_t buffer;
+ isc_buffer_t tcpbuffer;
+ isc_region_t r;
+ dns_compress_t cctx;
+ isc_boolean_t cleanup_cctx = ISC_FALSE;
+ unsigned char sendbuf[SEND_BUFFER_SIZE];
+ unsigned int dnssec_opts;
+ unsigned int preferred_glue;
+ isc_boolean_t opt_included = ISC_FALSE;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ CTRACE("send");
+
+ if ((client->attributes & NS_CLIENTATTR_RA) != 0)
+ client->message->flags |= DNS_MESSAGEFLAG_RA;
+
+ if ((client->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
+ dnssec_opts = 0;
+ else
+ dnssec_opts = DNS_MESSAGERENDER_OMITDNSSEC;
+
+ preferred_glue = 0;
+ if (client->view != NULL) {
+ if (client->view->preferred_glue == dns_rdatatype_a)
+ preferred_glue = DNS_MESSAGERENDER_PREFER_A;
+ else if (client->view->preferred_glue == dns_rdatatype_aaaa)
+ preferred_glue = DNS_MESSAGERENDER_PREFER_AAAA;
+ }
+
+ /*
+ * XXXRTH The following doesn't deal with TCP buffer resizing.
+ */
+ result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,
+ sendbuf, &data);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+ result = dns_compress_init(&cctx, -1, client->mctx);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ cleanup_cctx = ISC_TRUE;
+
+ result = dns_message_renderbegin(client->message, &cctx, &buffer);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+ if (client->opt != NULL) {
+ result = dns_message_setopt(client->message, client->opt);
+ opt_included = ISC_TRUE;
+ client->opt = NULL;
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ }
+ result = dns_message_rendersection(client->message,
+ DNS_SECTION_QUESTION, 0);
+ if (result == ISC_R_NOSPACE) {
+ client->message->flags |= DNS_MESSAGEFLAG_TC;
+ goto renderend;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ result = dns_message_rendersection(client->message,
+ DNS_SECTION_ANSWER,
+ DNS_MESSAGERENDER_PARTIAL |
+ dnssec_opts);
+ if (result == ISC_R_NOSPACE) {
+ client->message->flags |= DNS_MESSAGEFLAG_TC;
+ goto renderend;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ result = dns_message_rendersection(client->message,
+ DNS_SECTION_AUTHORITY,
+ DNS_MESSAGERENDER_PARTIAL |
+ dnssec_opts);
+ if (result == ISC_R_NOSPACE) {
+ client->message->flags |= DNS_MESSAGEFLAG_TC;
+ goto renderend;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ result = dns_message_rendersection(client->message,
+ DNS_SECTION_ADDITIONAL,
+ preferred_glue | dnssec_opts);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
+ goto done;
+ renderend:
+ result = dns_message_renderend(client->message);
+
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+ if (cleanup_cctx) {
+ dns_compress_invalidate(&cctx);
+ cleanup_cctx = ISC_FALSE;
+ }
+
+ if (TCP_CLIENT(client)) {
+ isc_buffer_usedregion(&buffer, &r);
+ isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);
+ isc_buffer_add(&tcpbuffer, r.length);
+ result = client_sendpkg(client, &tcpbuffer);
+ } else
+ result = client_sendpkg(client, &buffer);
+
+ /* update statistics (XXXJT: is it okay to access message->xxxkey?) */
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_response);
+ if (opt_included) {
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_edns0out);
+ }
+ if (client->message->tsigkey != NULL) {
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_tsigout);
+ }
+ if (client->message->sig0key != NULL) {
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_sig0out);
+ }
+ if ((client->message->flags & DNS_MESSAGEFLAG_TC) != 0)
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_truncatedresp);
+
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ done:
+ if (client->tcpbuf != NULL) {
+ isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);
+ client->tcpbuf = NULL;
+ }
+
+ if (cleanup_cctx)
+ dns_compress_invalidate(&cctx);
+
+ ns_client_next(client, result);
+}
+
+#if NS_CLIENT_DROPPORT
+#define DROPPORT_NO 0
+#define DROPPORT_REQUEST 1
+#define DROPPORT_RESPONSE 2
+/*%
+ * ns_client_dropport determines if certain requests / responses
+ * should be dropped based on the port number.
+ *
+ * Returns:
+ * \li 0: Don't drop.
+ * \li 1: Drop request.
+ * \li 2: Drop (error) response.
+ */
+static int
+ns_client_dropport(in_port_t port) {
+ switch (port) {
+ case 7: /* echo */
+ case 13: /* daytime */
+ case 19: /* chargen */
+ case 37: /* time */
+ return (DROPPORT_REQUEST);
+ case 464: /* kpasswd */
+ return (DROPPORT_RESPONSE);
+ }
+ return (DROPPORT_NO);
+}
+#endif
+
+void
+ns_client_error(ns_client_t *client, isc_result_t result) {
+ dns_rcode_t rcode;
+ dns_message_t *message;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+
+ CTRACE("error");
+
+ message = client->message;
+ rcode = dns_result_torcode(result);
+
+#if NS_CLIENT_DROPPORT
+ /*
+ * Don't send FORMERR to ports on the drop port list.
+ */
+ if (rcode == dns_rcode_formerr &&
+ ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) !=
+ DROPPORT_NO) {
+ char buf[64];
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, buf, sizeof(buf) - 1);
+ if (dns_rcode_totext(rcode, &b) != ISC_R_SUCCESS)
+ isc_buffer_putstr(&b, "UNKNOWN RCODE");
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "dropped error (%.*s) response: suspicious port",
+ (int)isc_buffer_usedlength(&b), buf);
+ ns_client_next(client, ISC_R_SUCCESS);
+ return;
+ }
+#endif
+
+ /*
+ * Message may be an in-progress reply that we had trouble
+ * with, in which case QR will be set. We need to clear QR before
+ * calling dns_message_reply() to avoid triggering an assertion.
+ */
+ message->flags &= ~DNS_MESSAGEFLAG_QR;
+ /*
+ * AA and AD shouldn't be set.
+ */
+ message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);
+ result = dns_message_reply(message, ISC_TRUE);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * It could be that we've got a query with a good header,
+ * but a bad question section, so we try again with
+ * want_question_section set to ISC_FALSE.
+ */
+ result = dns_message_reply(message, ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_next(client, result);
+ return;
+ }
+ }
+ message->rcode = rcode;
+
+ /*
+ * FORMERR loop avoidance: If we sent a FORMERR message
+ * with the same ID to the same client less than two
+ * seconds ago, assume that we are in an infinite error
+ * packet dialog with a server for some protocol whose
+ * error responses look enough like DNS queries to
+ * elicit a FORMERR response. Drop a packet to break
+ * the loop.
+ */
+ if (rcode == dns_rcode_formerr) {
+ if (isc_sockaddr_equal(&client->peeraddr,
+ &client->formerrcache.addr) &&
+ message->id == client->formerrcache.id &&
+ client->requesttime - client->formerrcache.time < 2) {
+ /* Drop packet. */
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
+ "possible error packet loop, "
+ "FORMERR dropped");
+ ns_client_next(client, result);
+ return;
+ }
+ client->formerrcache.addr = client->peeraddr;
+ client->formerrcache.time = client->requesttime;
+ client->formerrcache.id = message->id;
+ }
+ ns_client_send(client);
+}
+
+static inline isc_result_t
+client_addopt(ns_client_t *client) {
+ dns_rdataset_t *rdataset;
+ dns_rdatalist_t *rdatalist;
+ dns_rdata_t *rdata;
+ isc_result_t result;
+ dns_view_t *view;
+ dns_resolver_t *resolver;
+ isc_uint16_t udpsize;
+
+ REQUIRE(client->opt == NULL); /* XXXRTH free old. */
+
+ rdatalist = NULL;
+ result = dns_message_gettemprdatalist(client->message, &rdatalist);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ rdata = NULL;
+ result = dns_message_gettemprdata(client->message, &rdata);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ rdataset = NULL;
+ result = dns_message_gettemprdataset(client->message, &rdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_init(rdataset);
+
+ rdatalist->type = dns_rdatatype_opt;
+ rdatalist->covers = 0;
+
+ /*
+ * Set the maximum UDP buffer size.
+ */
+ view = client->view;
+ resolver = (view != NULL) ? view->resolver : NULL;
+ if (resolver != NULL)
+ udpsize = dns_resolver_getudpsize(resolver);
+ else
+ udpsize = ns_g_udpsize;
+ rdatalist->rdclass = udpsize;
+
+ /*
+ * Set EXTENDED-RCODE, VERSION and Z to 0.
+ */
+ rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);
+
+ /* Set EDNS options if applicable */
+ if (client->attributes & NS_CLIENTATTR_WANTNSID &&
+ (ns_g_server->server_id != NULL ||
+ ns_g_server->server_usehostname)) {
+ /*
+ * Space required for NSID data:
+ * 2 bytes for opt code
+ * + 2 bytes for NSID length
+ * + NSID itself
+ */
+ char nsid[BUFSIZ], *nsidp;
+ isc_buffer_t *buffer = NULL;
+
+ if (ns_g_server->server_usehostname) {
+ isc_result_t result;
+ result = ns_os_gethostname(nsid, sizeof(nsid));
+ if (result != ISC_R_SUCCESS) {
+ goto no_nsid;
+ }
+ nsidp = nsid;
+ } else
+ nsidp = ns_g_server->server_id;
+
+ rdata->length = strlen(nsidp) + 4;
+ result = isc_buffer_allocate(client->mctx, &buffer,
+ rdata->length);
+ if (result != ISC_R_SUCCESS)
+ goto no_nsid;
+
+ isc_buffer_putuint16(buffer, DNS_OPT_NSID);
+ isc_buffer_putuint16(buffer, strlen(nsidp));
+ isc_buffer_putstr(buffer, nsidp);
+ rdata->data = buffer->base;
+ dns_message_takebuffer(client->message, &buffer);
+ } else {
+no_nsid:
+ rdata->data = NULL;
+ rdata->length = 0;
+ }
+
+ rdata->rdclass = rdatalist->rdclass;
+ rdata->type = rdatalist->type;
+ rdata->flags = 0;
+
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
+ == ISC_R_SUCCESS);
+
+ client->opt = rdataset;
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_boolean_t
+allowed(isc_netaddr_t *addr, dns_name_t *signer, dns_acl_t *acl) {
+ int match;
+ isc_result_t result;
+
+ if (acl == NULL)
+ return (ISC_TRUE);
+ result = dns_acl_match(addr, signer, acl, &ns_g_server->aclenv,
+ &match, NULL);
+ if (result == ISC_R_SUCCESS && match > 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+/*
+ * Callback to see if a non-recursive query coming from 'srcaddr' to
+ * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
+ * delivered to 'myview'.
+ *
+ * We run this unlocked as both the view list and the interface list
+ * are updated when the approprite task has exclusivity.
+ */
+isc_boolean_t
+ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *dstaddr,
+ dns_rdataclass_t rdclass, void *arg)
+{
+ dns_view_t *view;
+ dns_tsigkey_t *key = NULL;
+ dns_name_t *tsig = NULL;
+ isc_netaddr_t netsrc;
+ isc_netaddr_t netdst;
+
+ UNUSED(arg);
+
+ if (!ns_interfacemgr_listeningon(ns_g_server->interfacemgr, dstaddr))
+ return (ISC_FALSE);
+
+ isc_netaddr_fromsockaddr(&netsrc, srcaddr);
+ isc_netaddr_fromsockaddr(&netdst, dstaddr);
+
+ for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+
+ if (view->matchrecursiveonly)
+ continue;
+
+ if (rdclass != view->rdclass)
+ continue;
+
+ if (mykey != NULL) {
+ isc_boolean_t match;
+ isc_result_t result;
+
+ result = dns_view_gettsig(view, &mykey->name, &key);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ match = dst_key_compare(mykey->key, key->key);
+ dns_tsigkey_detach(&key);
+ if (!match)
+ continue;
+ tsig = dns_tsigkey_identity(mykey);
+ }
+
+ if (allowed(&netsrc, tsig, view->matchclients) &&
+ allowed(&netdst, tsig, view->matchdestinations))
+ break;
+ }
+ return (ISC_TF(view == myview));
+}
+
+/*
+ * Handle an incoming request event from the socket (UDP case)
+ * or tcpmsg (TCP case).
+ */
+static void
+client_request(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client;
+ isc_socketevent_t *sevent;
+ isc_result_t result;
+ isc_result_t sigresult = ISC_R_SUCCESS;
+ isc_buffer_t *buffer;
+ isc_buffer_t tbuffer;
+ dns_view_t *view;
+ dns_rdataset_t *opt;
+ 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;
+ isc_boolean_t notimp;
+ dns_rdata_t rdata;
+ isc_uint16_t optcode;
+
+ REQUIRE(event != NULL);
+ client = event->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+
+ INSIST(client->recursionquota == NULL);
+
+ INSIST(client->state ==
+ TCP_CLIENT(client) ?
+ NS_CLIENTSTATE_READING :
+ NS_CLIENTSTATE_READY);
+
+ ns_client_requests++;
+
+ if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {
+ INSIST(!TCP_CLIENT(client));
+ sevent = (isc_socketevent_t *)event;
+ REQUIRE(sevent == client->recvevent);
+ isc_buffer_init(&tbuffer, sevent->region.base, sevent->n);
+ isc_buffer_add(&tbuffer, sevent->n);
+ buffer = &tbuffer;
+ result = sevent->result;
+ if (result == ISC_R_SUCCESS) {
+ client->peeraddr = sevent->address;
+ client->peeraddr_valid = ISC_TRUE;
+ }
+ if ((sevent->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
+ client->attributes |= NS_CLIENTATTR_PKTINFO;
+ client->pktinfo = sevent->pktinfo;
+ }
+ if ((sevent->attributes & ISC_SOCKEVENTATTR_MULTICAST) != 0)
+ client->attributes |= NS_CLIENTATTR_MULTICAST;
+ client->nrecvs--;
+ } else {
+ INSIST(TCP_CLIENT(client));
+ REQUIRE(event->ev_type == DNS_EVENT_TCPMSG);
+ REQUIRE(event->ev_sender == &client->tcpmsg);
+ buffer = &client->tcpmsg.buffer;
+ result = client->tcpmsg.result;
+ INSIST(client->nreads == 1);
+ /*
+ * client->peeraddr was set when the connection was accepted.
+ */
+ client->nreads--;
+ }
+
+ if (exit_check(client))
+ goto cleanup;
+ client->state = client->newstate = NS_CLIENTSTATE_WORKING;
+
+ isc_task_getcurrenttime(task, &client->requesttime);
+ client->now = client->requesttime;
+
+ if (result != ISC_R_SUCCESS) {
+ if (TCP_CLIENT(client)) {
+ ns_client_next(client, result);
+ } else {
+ if (result != ISC_R_CANCELED)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT,
+ ISC_LOG_ERROR,
+ "UDP client handler shutting "
+ "down due to fatal receive "
+ "error: %s",
+ isc_result_totext(result));
+ isc_task_shutdown(client->task);
+ }
+ goto cleanup;
+ }
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+
+#if NS_CLIENT_DROPPORT
+ if (ns_client_dropport(isc_sockaddr_getport(&client->peeraddr)) ==
+ DROPPORT_REQUEST) {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "dropped request: suspicious port");
+ ns_client_next(client, ISC_R_SUCCESS);
+ goto cleanup;
+ }
+#endif
+
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "%s request",
+ TCP_CLIENT(client) ? "TCP" : "UDP");
+
+ /*
+ * Check the blackhole ACL for UDP only, since TCP is done in
+ * client_newconn.
+ */
+ if (!TCP_CLIENT(client)) {
+
+ if (ns_g_server->blackholeacl != NULL &&
+ dns_acl_match(&netaddr, NULL, ns_g_server->blackholeacl,
+ &ns_g_server->aclenv,
+ &match, NULL) == ISC_R_SUCCESS &&
+ match > 0)
+ {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "blackholed UDP datagram");
+ ns_client_next(client, ISC_R_SUCCESS);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Silently drop multicast requests for the present.
+ * XXXMPA look at when/if mDNS spec stabilizes.
+ */
+ if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(2),
+ "dropping multicast request");
+ ns_client_next(client, DNS_R_REFUSED);
+ goto cleanup;
+ }
+
+ result = dns_message_peekheader(buffer, &id, &flags);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * There isn't enough header to determine whether
+ * this was a request or a response. Drop it.
+ */
+ ns_client_next(client, result);
+ goto cleanup;
+ }
+
+ /*
+ * The client object handles requests, not responses.
+ * If this is a UDP response, forward it to the dispatcher.
+ * If it's a TCP response, discard it here.
+ */
+ if ((flags & DNS_MESSAGEFLAG_QR) != 0) {
+ if (TCP_CLIENT(client)) {
+ CTRACE("unexpected response");
+ ns_client_next(client, DNS_R_FORMERR);
+ goto cleanup;
+ } else {
+ dns_dispatch_importrecv(client->dispatch, event);
+ ns_client_next(client, ISC_R_SUCCESS);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Update some statistics counters. Don't count responses.
+ */
+ if (isc_sockaddr_pf(&client->peeraddr) == PF_INET) {
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_requestv4);
+ } else {
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_requestv6);
+ }
+ if (TCP_CLIENT(client))
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_tcp);
+
+ /*
+ * It's a request. Parse it.
+ */
+ result = dns_message_parse(client->message, buffer, 0);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * Parsing the request failed. Send a response
+ * (typically FORMERR or SERVFAIL).
+ */
+ ns_client_error(client, result);
+ goto cleanup;
+ }
+
+ dns_opcodestats_increment(ns_g_server->opcodestats,
+ client->message->opcode);
+ switch (client->message->opcode) {
+ case dns_opcode_query:
+ case dns_opcode_update:
+ case dns_opcode_notify:
+ notimp = ISC_FALSE;
+ break;
+ case dns_opcode_iquery:
+ default:
+ notimp = ISC_TRUE;
+ break;
+ }
+
+ client->message->rcode = dns_rcode_noerror;
+
+ /* RFC1123 section 6.1.3.2 */
+ if ((client->attributes & NS_CLIENTATTR_MULTICAST) != 0)
+ client->message->flags &= ~DNS_MESSAGEFLAG_RD;
+
+ /*
+ * Deal with EDNS.
+ */
+ opt = dns_message_getopt(client->message);
+ if (opt != NULL) {
+ /*
+ * Set the client's UDP buffer size.
+ */
+ client->udpsize = opt->rdclass;
+
+ /*
+ * If the requested UDP buffer size is less than 512,
+ * ignore it and use 512.
+ */
+ if (client->udpsize < 512)
+ client->udpsize = 512;
+
+ /*
+ * Get the flags out of the OPT record.
+ */
+ client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF);
+
+ /*
+ * Do we understand this version of EDNS?
+ *
+ * XXXRTH need library support for this!
+ */
+ client->ednsversion = (opt->ttl & 0x00FF0000) >> 16;
+ if (client->ednsversion > 0) {
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_badednsver);
+ result = client_addopt(client);
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_BADVERS;
+ ns_client_error(client, result);
+ goto cleanup;
+ }
+
+ /* Check for NSID request */
+ result = dns_rdataset_first(opt);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(opt, &rdata);
+ if (rdata.length >= 2) {
+ isc_buffer_t nsidbuf;
+ isc_buffer_init(&nsidbuf,
+ rdata.data, rdata.length);
+ isc_buffer_add(&nsidbuf, rdata.length);
+ optcode = isc_buffer_getuint16(&nsidbuf);
+ if (optcode == DNS_OPT_NSID)
+ client->attributes |=
+ NS_CLIENTATTR_WANTNSID;
+ }
+ }
+
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_edns0in);
+
+ /*
+ * Create an OPT for our reply.
+ */
+ result = client_addopt(client);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_error(client, result);
+ goto cleanup;
+ }
+ }
+
+ if (client->message->rdclass == 0) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
+ "message class could not be determined");
+ ns_client_dumpmessage(client,
+ "message class could not be determined");
+ ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_FORMERR);
+ goto cleanup;
+ }
+
+ /*
+ * Determine the destination address. If the receiving interface is
+ * bound to a specific address, we simply use it regardless of the
+ * address family. All IPv4 queries should fall into this case.
+ * Otherwise, if this is a TCP query, get the address from the
+ * receiving socket (this needs a system call and can be heavy).
+ * For IPv6 UDP queries, we get this from the pktinfo structure (if
+ * supported).
+ * If all the attempts fail (this can happen due to memory shortage,
+ * etc), we regard this as an error for safety.
+ */
+ if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
+ isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr);
+ else {
+ result = ISC_R_FAILURE;
+
+ if (TCP_CLIENT(client)) {
+ isc_sockaddr_t destsockaddr;
+
+ result = isc_socket_getsockname(client->tcpsocket,
+ &destsockaddr);
+ if (result == ISC_R_SUCCESS)
+ isc_netaddr_fromsockaddr(&destaddr,
+ &destsockaddr);
+ }
+ 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,
+ * due to the fact there is no standard API for this,
+ * we only handle link-local addresses and use the
+ * 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,
+ &client->pktinfo.ipi6_addr);
+ isc_netaddr_setzone(&destaddr, zone);
+ result = ISC_R_SUCCESS;
+ }
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "failed to get request's "
+ "destination: %s",
+ isc_result_totext(result));
+ ns_client_next(client, ISC_R_SUCCESS);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Find a view that matches the client's source address.
+ */
+ for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ if (client->message->rdclass == view->rdclass ||
+ client->message->rdclass == dns_rdataclass_any)
+ {
+ dns_name_t *tsig = NULL;
+
+ sigresult = dns_message_rechecksig(client->message,
+ view);
+ if (sigresult == ISC_R_SUCCESS)
+ tsig = dns_tsigkey_identity(client->message->tsigkey);
+
+ if (allowed(&netaddr, tsig, view->matchclients) &&
+ allowed(&destaddr, tsig, view->matchdestinations) &&
+ !((client->message->flags & DNS_MESSAGEFLAG_RD)
+ == 0 && view->matchrecursiveonly))
+ {
+ dns_view_attach(view, &client->view);
+ break;
+ }
+ }
+ }
+
+ if (view == NULL) {
+ char classname[DNS_RDATACLASS_FORMATSIZE];
+
+ /*
+ * Do a dummy TSIG verification attempt so that the
+ * response will have a TSIG if the query did, as
+ * required by RFC2845.
+ */
+ isc_buffer_t b;
+ isc_region_t *r;
+
+ dns_message_resetsig(client->message);
+
+ r = dns_message_getrawmessage(client->message);
+ isc_buffer_init(&b, r->base, r->length);
+ isc_buffer_add(&b, r->length);
+ (void)dns_tsig_verify(&b, client->message, NULL, NULL);
+
+ dns_rdataclass_format(client->message->rdclass, classname,
+ sizeof(classname));
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
+ "no matching view in class '%s'", classname);
+ ns_client_dumpmessage(client, "no matching view in class");
+ ns_client_error(client, notimp ? DNS_R_NOTIMP : DNS_R_REFUSED);
+ goto cleanup;
+ }
+
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(5),
+ "using view '%s'", view->name);
+
+ /*
+ * Check for a signature. We log bad signatures regardless of
+ * whether they ultimately cause the request to be rejected or
+ * not. We do not log the lack of a signature unless we are
+ * debugging.
+ */
+ client->signer = NULL;
+ dns_name_init(&client->signername, NULL);
+ result = dns_message_signer(client->message, &client->signername);
+ if (result != ISC_R_NOTFOUND) {
+ signame = NULL;
+ if (dns_message_gettsig(client->message, &signame) != NULL) {
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_tsigin);
+ } else {
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_sig0in);
+ }
+
+ }
+ if (result == ISC_R_SUCCESS) {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "request has valid signature");
+ client->signer = &client->signername;
+ } else if (result == ISC_R_NOTFOUND) {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "request is not signed");
+ } else if (result == DNS_R_NOIDENTITY) {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "request is signed by a nonauthoritative key");
+ } else {
+ char tsigrcode[64];
+ isc_buffer_t b;
+ dns_rcode_t status;
+ isc_result_t tresult;
+
+ /* There is a signature, but it is bad. */
+ dns_generalstats_increment(ns_g_server->nsstats,
+ dns_nsstatscounter_invalidsig);
+ signame = NULL;
+ if (dns_message_gettsig(client->message, &signame) != NULL) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char cnamebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(signame, namebuf, sizeof(namebuf));
+ status = client->message->tsigstatus;
+ isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
+ tresult = dns_tsigrcode_totext(status, &b);
+ INSIST(tresult == ISC_R_SUCCESS);
+ tsigrcode[isc_buffer_usedlength(&b)] = '\0';
+ if (client->message->tsigkey->generated) {
+ dns_name_format(client->message->tsigkey->creator,
+ cnamebuf, sizeof(cnamebuf));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT,
+ ISC_LOG_ERROR,
+ "request has invalid signature: "
+ "TSIG %s (%s): %s (%s)", namebuf,
+ cnamebuf,
+ isc_result_totext(result),
+ tsigrcode);
+ } else {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT,
+ ISC_LOG_ERROR,
+ "request has invalid signature: "
+ "TSIG %s: %s (%s)", namebuf,
+ isc_result_totext(result),
+ tsigrcode);
+ }
+ } else {
+ status = client->message->sig0status;
+ isc_buffer_init(&b, tsigrcode, sizeof(tsigrcode) - 1);
+ tresult = dns_tsigrcode_totext(status, &b);
+ INSIST(tresult == ISC_R_SUCCESS);
+ tsigrcode[isc_buffer_usedlength(&b)] = '\0';
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_ERROR,
+ "request has invalid signature: %s (%s)",
+ isc_result_totext(result), tsigrcode);
+ }
+ /*
+ * Accept update messages signed by unknown keys so that
+ * update forwarding works transparently through slaves
+ * that don't have all the same keys as the master.
+ */
+ if (!(client->message->tsigstatus == dns_tsigerror_badkey &&
+ client->message->opcode == dns_opcode_update)) {
+ ns_client_error(client, sigresult);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Decide whether recursive service is available to this client.
+ * We do this here rather than in the query code so that we can
+ * set the RA bit correctly on all kinds of responses, not just
+ * responses to ordinary queries. Note if you can't query the
+ * cache there is no point in setting RA.
+ */
+ ra = ISC_FALSE;
+ if (client->view->resolver != NULL &&
+ client->view->recursion == ISC_TRUE &&
+ ns_client_checkaclsilent(client, NULL,
+ client->view->recursionacl,
+ ISC_TRUE) == ISC_R_SUCCESS &&
+ ns_client_checkaclsilent(client, NULL,
+ client->view->queryacl,
+ ISC_TRUE) == ISC_R_SUCCESS &&
+ ns_client_checkaclsilent(client, &client->interface->addr,
+ client->view->recursiononacl,
+ ISC_TRUE) == ISC_R_SUCCESS &&
+ ns_client_checkaclsilent(client, &client->interface->addr,
+ client->view->queryonacl,
+ ISC_TRUE) == ISC_R_SUCCESS)
+ ra = ISC_TRUE;
+
+ if (ra == ISC_TRUE)
+ client->attributes |= NS_CLIENTATTR_RA;
+
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
+ ISC_LOG_DEBUG(3), ra ? "recursion available" :
+ "recursion not available");
+
+ /*
+ * Adjust maximum UDP response size for this client.
+ */
+ if (client->udpsize > 512) {
+ dns_peer_t *peer = NULL;
+ isc_uint16_t udpsize = view->maxudp;
+ (void) dns_peerlist_peerbyaddr(view->peers, &netaddr, &peer);
+ if (peer != NULL)
+ dns_peer_getmaxudp(peer, &udpsize);
+ if (client->udpsize > udpsize)
+ client->udpsize = udpsize;
+ }
+
+ /*
+ * Dispatch the request.
+ */
+ switch (client->message->opcode) {
+ case dns_opcode_query:
+ CTRACE("query");
+ ns_query_start(client);
+ break;
+ case dns_opcode_update:
+ CTRACE("update");
+ ns_client_settimeout(client, 60);
+ ns_update_start(client, sigresult);
+ break;
+ case dns_opcode_notify:
+ CTRACE("notify");
+ ns_client_settimeout(client, 60);
+ ns_notify_start(client);
+ break;
+ case dns_opcode_iquery:
+ CTRACE("iquery");
+ ns_client_error(client, DNS_R_NOTIMP);
+ break;
+ default:
+ CTRACE("unknown opcode");
+ ns_client_error(client, DNS_R_NOTIMP);
+ }
+
+ cleanup:
+ return;
+}
+
+static void
+client_timeout(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client;
+
+ REQUIRE(event != NULL);
+ REQUIRE(event->ev_type == ISC_TIMEREVENT_LIFE ||
+ event->ev_type == ISC_TIMEREVENT_IDLE);
+ client = event->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+ REQUIRE(client->timer != NULL);
+
+ UNUSED(task);
+
+ CTRACE("timeout");
+
+ isc_event_free(&event);
+
+ if (client->shutdown != NULL) {
+ (client->shutdown)(client->shutdown_arg, ISC_R_TIMEDOUT);
+ client->shutdown = NULL;
+ client->shutdown_arg = NULL;
+ }
+
+ if (client->newstate > NS_CLIENTSTATE_READY)
+ client->newstate = NS_CLIENTSTATE_READY;
+ (void)exit_check(client);
+}
+
+static isc_result_t
+get_clientmctx(ns_clientmgr_t *manager, isc_mem_t **mctxp) {
+ isc_mem_t *clientmctx;
+ isc_result_t result;
+
+ /*
+ * Caller must be holding the manager lock.
+ */
+ if (ns_g_clienttest) {
+ result = isc_mem_create(0, 0, mctxp);
+ if (result == ISC_R_SUCCESS)
+ isc_mem_setname(*mctxp, "client", NULL);
+ return (result);
+ }
+#if NMCTXS > 0
+ INSIST(manager->nextmctx < NMCTXS);
+ clientmctx = manager->mctxpool[manager->nextmctx];
+ if (clientmctx == NULL) {
+ result = isc_mem_create(0, 0, &clientmctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_mem_setname(clientmctx, "client", NULL);
+
+ manager->mctxpool[manager->nextmctx] = clientmctx;
+ }
+ manager->nextmctx++;
+ if (manager->nextmctx == NMCTXS)
+ manager->nextmctx = 0;
+#else
+ clientmctx = manager->mctx;
+#endif
+
+ isc_mem_attach(clientmctx, mctxp);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
+ ns_client_t *client;
+ isc_result_t result;
+ isc_mem_t *mctx = NULL;
+
+ /*
+ * Caller must be holding the manager lock.
+ *
+ * Note: creating a client does not add the client to the
+ * manager's client list or set the client's manager pointer.
+ * The caller is responsible for that.
+ */
+
+ REQUIRE(clientp != NULL && *clientp == NULL);
+
+ result = get_clientmctx(manager, &mctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ client = isc_mem_get(mctx, sizeof(*client));
+ if (client == NULL) {
+ isc_mem_detach(&mctx);
+ return (ISC_R_NOMEMORY);
+ }
+ client->mctx = mctx;
+
+ client->task = NULL;
+ result = isc_task_create(manager->taskmgr, 0, &client->task);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_client;
+ isc_task_setname(client->task, "client", client);
+
+ client->timer = NULL;
+ result = isc_timer_create(manager->timermgr, isc_timertype_inactive,
+ NULL, NULL, client->task, client_timeout,
+ client, &client->timer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_task;
+ client->timerset = ISC_FALSE;
+
+ client->message = NULL;
+ result = dns_message_create(client->mctx, DNS_MESSAGE_INTENTPARSE,
+ &client->message);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_timer;
+
+ /* XXXRTH Hardwired constants */
+
+ client->sendevent = (isc_socketevent_t *)
+ isc_event_allocate(client->mctx, client,
+ ISC_SOCKEVENT_SENDDONE,
+ client_senddone, client,
+ sizeof(isc_socketevent_t));
+ if (client->sendevent == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_message;
+ }
+
+ client->recvbuf = isc_mem_get(client->mctx, RECV_BUFFER_SIZE);
+ if (client->recvbuf == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_sendevent;
+ }
+
+ client->recvevent = (isc_socketevent_t *)
+ isc_event_allocate(client->mctx, client,
+ ISC_SOCKEVENT_RECVDONE,
+ client_request, client,
+ sizeof(isc_socketevent_t));
+ if (client->recvevent == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_recvbuf;
+ }
+
+ client->magic = NS_CLIENT_MAGIC;
+ client->manager = NULL;
+ client->state = NS_CLIENTSTATE_INACTIVE;
+ client->newstate = NS_CLIENTSTATE_MAX;
+ client->naccepts = 0;
+ client->nreads = 0;
+ client->nsends = 0;
+ client->nrecvs = 0;
+ client->nupdates = 0;
+ client->nctls = 0;
+ client->references = 0;
+ client->attributes = 0;
+ client->view = NULL;
+ client->dispatch = NULL;
+ client->udpsocket = NULL;
+ client->tcplistener = NULL;
+ client->tcpsocket = NULL;
+ client->tcpmsg_valid = ISC_FALSE;
+ client->tcpbuf = NULL;
+ client->opt = NULL;
+ client->udpsize = 512;
+ client->extflags = 0;
+ client->ednsversion = -1;
+ client->next = NULL;
+ client->shutdown = NULL;
+ client->shutdown_arg = NULL;
+ dns_name_init(&client->signername, NULL);
+ client->mortal = ISC_FALSE;
+ client->tcpquota = NULL;
+ client->recursionquota = NULL;
+ client->interface = NULL;
+ client->peeraddr_valid = ISC_FALSE;
+ ISC_EVENT_INIT(&client->ctlevent, sizeof(client->ctlevent), 0, NULL,
+ NS_EVENT_CLIENTCONTROL, client_start, client, client,
+ NULL, NULL);
+ /*
+ * Initialize FORMERR cache to sentinel value that will not match
+ * any actual FORMERR response.
+ */
+ isc_sockaddr_any(&client->formerrcache.addr);
+ client->formerrcache.time = 0;
+ client->formerrcache.id = 0;
+ ISC_LINK_INIT(client, link);
+ client->list = NULL;
+
+ /*
+ * We call the init routines for the various kinds of client here,
+ * after we have created an otherwise valid client, because some
+ * of them call routines that REQUIRE(NS_CLIENT_VALID(client)).
+ */
+ result = ns_query_init(client);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_recvevent;
+
+ result = isc_task_onshutdown(client->task, client_shutdown, client);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_query;
+
+ client->needshutdown = ns_g_clienttest;
+
+ CTRACE("create");
+
+ *clientp = client;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_query:
+ ns_query_free(client);
+
+ cleanup_recvevent:
+ isc_event_free((isc_event_t **)&client->recvevent);
+
+ cleanup_recvbuf:
+ isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE);
+
+ cleanup_sendevent:
+ isc_event_free((isc_event_t **)&client->sendevent);
+
+ client->magic = 0;
+
+ cleanup_message:
+ dns_message_destroy(&client->message);
+
+ cleanup_timer:
+ isc_timer_detach(&client->timer);
+
+ cleanup_task:
+ isc_task_detach(&client->task);
+
+ cleanup_client:
+ isc_mem_putanddetach(&client->mctx, client, sizeof(*client));
+
+ return (result);
+}
+
+static void
+client_read(ns_client_t *client) {
+ isc_result_t result;
+
+ CTRACE("read");
+
+ result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,
+ client_request, client);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ /*
+ * Set a timeout to limit the amount of time we will wait
+ * for a request on this TCP connection.
+ */
+ ns_client_settimeout(client, 30);
+
+ client->state = client->newstate = NS_CLIENTSTATE_READING;
+ INSIST(client->nreads == 0);
+ INSIST(client->recursionquota == NULL);
+ client->nreads++;
+
+ return;
+ fail:
+ ns_client_next(client, result);
+}
+
+static void
+client_newconn(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client = event->ev_arg;
+ isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
+ isc_result_t result;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(client->task == task);
+
+ UNUSED(task);
+
+ INSIST(client->state == NS_CLIENTSTATE_READY);
+
+ INSIST(client->naccepts == 1);
+ client->naccepts--;
+
+ LOCK(&client->interface->lock);
+ INSIST(client->interface->ntcpcurrent > 0);
+ client->interface->ntcpcurrent--;
+ UNLOCK(&client->interface->lock);
+
+ /*
+ * We must take ownership of the new socket before the exit
+ * check to make sure it gets destroyed if we decide to exit.
+ */
+ if (nevent->result == ISC_R_SUCCESS) {
+ client->tcpsocket = nevent->newsocket;
+ isc_socket_setname(client->tcpsocket, "client-tcp", NULL);
+ client->state = NS_CLIENTSTATE_READING;
+ INSIST(client->recursionquota == NULL);
+
+ (void)isc_socket_getpeername(client->tcpsocket,
+ &client->peeraddr);
+ client->peeraddr_valid = ISC_TRUE;
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "new TCP connection");
+ } else {
+ /*
+ * XXXRTH What should we do? We're trying to accept but
+ * it didn't work. If we just give up, then TCP
+ * service may eventually stop.
+ *
+ * For now, we just go idle.
+ *
+ * Going idle is probably the right thing if the
+ * I/O was canceled.
+ */
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "accept failed: %s",
+ isc_result_totext(nevent->result));
+ }
+
+ if (exit_check(client))
+ goto freeevent;
+
+ if (nevent->result == ISC_R_SUCCESS) {
+ int match;
+ isc_netaddr_t netaddr;
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+
+ if (ns_g_server->blackholeacl != NULL &&
+ dns_acl_match(&netaddr, NULL,
+ ns_g_server->blackholeacl,
+ &ns_g_server->aclenv,
+ &match, NULL) == ISC_R_SUCCESS &&
+ match > 0)
+ {
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "blackholed connection attempt");
+ client->newstate = NS_CLIENTSTATE_READY;
+ (void)exit_check(client);
+ goto freeevent;
+ }
+
+ INSIST(client->tcpmsg_valid == ISC_FALSE);
+ dns_tcpmsg_init(client->mctx, client->tcpsocket,
+ &client->tcpmsg);
+ client->tcpmsg_valid = ISC_TRUE;
+
+ /*
+ * Let a new client take our place immediately, before
+ * we wait for a request packet. If we don't,
+ * telnetting to port 53 (once per CPU) will
+ * deny service to legititmate TCP clients.
+ */
+ result = isc_quota_attach(&ns_g_server->tcpquota,
+ &client->tcpquota);
+ if (result == ISC_R_SUCCESS)
+ result = ns_client_replace(client);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,
+ "no more TCP clients: %s",
+ isc_result_totext(result));
+ }
+
+ client_read(client);
+ }
+
+ freeevent:
+ isc_event_free(&event);
+}
+
+static void
+client_accept(ns_client_t *client) {
+ isc_result_t result;
+
+ CTRACE("accept");
+
+ result = isc_socket_accept(client->tcplistener, client->task,
+ client_newconn, client);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socket_accept() failed: %s",
+ isc_result_totext(result));
+ /*
+ * XXXRTH What should we do? We're trying to accept but
+ * it didn't work. If we just give up, then TCP
+ * service may eventually stop.
+ *
+ * For now, we just go idle.
+ */
+ return;
+ }
+ INSIST(client->naccepts == 0);
+ client->naccepts++;
+ LOCK(&client->interface->lock);
+ client->interface->ntcpcurrent++;
+ UNLOCK(&client->interface->lock);
+}
+
+static void
+client_udprecv(ns_client_t *client) {
+ isc_result_t result;
+ isc_region_t r;
+
+ CTRACE("udprecv");
+
+ r.base = client->recvbuf;
+ r.length = RECV_BUFFER_SIZE;
+ result = isc_socket_recv2(client->udpsocket, &r, 1,
+ client->task, client->recvevent, 0);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socket_recv2() failed: %s",
+ isc_result_totext(result));
+ /*
+ * This cannot happen in the current implementation, since
+ * isc_socket_recv2() cannot fail if flags == 0.
+ *
+ * If this does fail, we just go idle.
+ */
+ return;
+ }
+ INSIST(client->nrecvs == 0);
+ client->nrecvs++;
+}
+
+void
+ns_client_attach(ns_client_t *source, ns_client_t **targetp) {
+ REQUIRE(NS_CLIENT_VALID(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ source->references++;
+ ns_client_log(source, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "ns_client_attach: ref = %d", source->references);
+ *targetp = source;
+}
+
+void
+ns_client_detach(ns_client_t **clientp) {
+ ns_client_t *client = *clientp;
+
+ client->references--;
+ INSIST(client->references >= 0);
+ *clientp = NULL;
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),
+ "ns_client_detach: ref = %d", client->references);
+ (void)exit_check(client);
+}
+
+isc_boolean_t
+ns_client_shuttingdown(ns_client_t *client) {
+ return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));
+}
+
+isc_result_t
+ns_client_replace(ns_client_t *client) {
+ isc_result_t result;
+
+ CTRACE("replace");
+
+ result = ns_clientmgr_createclients(client->manager,
+ 1, client->interface,
+ (TCP_CLIENT(client) ?
+ ISC_TRUE : ISC_FALSE));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * The responsibility for listening for new requests is hereby
+ * transferred to the new client. Therefore, the old client
+ * should refrain from listening for any more requests.
+ */
+ client->mortal = ISC_TRUE;
+
+ return (ISC_R_SUCCESS);
+}
+
+/***
+ *** Client Manager
+ ***/
+
+static void
+clientmgr_destroy(ns_clientmgr_t *manager) {
+#if NMCTXS > 0
+ int i;
+#endif
+
+ REQUIRE(ISC_LIST_EMPTY(manager->active));
+ REQUIRE(ISC_LIST_EMPTY(manager->inactive));
+ REQUIRE(ISC_LIST_EMPTY(manager->recursing));
+
+ MTRACE("clientmgr_destroy");
+
+#if NMCTXS > 0
+ for (i = 0; i < NMCTXS; i++) {
+ if (manager->mctxpool[i] != NULL)
+ isc_mem_detach(&manager->mctxpool[i]);
+ }
+#endif
+
+ DESTROYLOCK(&manager->lock);
+ manager->magic = 0;
+ isc_mem_put(manager->mctx, manager, sizeof(*manager));
+}
+
+isc_result_t
+ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
+ isc_timermgr_t *timermgr, ns_clientmgr_t **managerp)
+{
+ ns_clientmgr_t *manager;
+ isc_result_t result;
+#if NMCTXS > 0
+ int i;
+#endif
+
+ manager = isc_mem_get(mctx, sizeof(*manager));
+ if (manager == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&manager->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_manager;
+
+ manager->mctx = mctx;
+ manager->taskmgr = taskmgr;
+ manager->timermgr = timermgr;
+ manager->exiting = ISC_FALSE;
+ ISC_LIST_INIT(manager->active);
+ ISC_LIST_INIT(manager->inactive);
+ ISC_LIST_INIT(manager->recursing);
+#if NMCTXS > 0
+ manager->nextmctx = 0;
+ for (i = 0; i < NMCTXS; i++)
+ manager->mctxpool[i] = NULL; /* will be created on-demand */
+#endif
+ manager->magic = MANAGER_MAGIC;
+
+ MTRACE("create");
+
+ *managerp = manager;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_manager:
+ isc_mem_put(manager->mctx, manager, sizeof(*manager));
+
+ return (result);
+}
+
+void
+ns_clientmgr_destroy(ns_clientmgr_t **managerp) {
+ ns_clientmgr_t *manager;
+ ns_client_t *client;
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(managerp != NULL);
+ manager = *managerp;
+ REQUIRE(VALID_MANAGER(manager));
+
+ MTRACE("destroy");
+
+ LOCK(&manager->lock);
+
+ manager->exiting = ISC_TRUE;
+
+ for (client = ISC_LIST_HEAD(manager->recursing);
+ client != NULL;
+ client = ISC_LIST_NEXT(client, link))
+ isc_task_shutdown(client->task);
+
+ for (client = ISC_LIST_HEAD(manager->active);
+ client != NULL;
+ client = ISC_LIST_NEXT(client, link))
+ isc_task_shutdown(client->task);
+
+ for (client = ISC_LIST_HEAD(manager->inactive);
+ client != NULL;
+ client = ISC_LIST_NEXT(client, link))
+ isc_task_shutdown(client->task);
+
+ if (ISC_LIST_EMPTY(manager->active) &&
+ ISC_LIST_EMPTY(manager->inactive) &&
+ ISC_LIST_EMPTY(manager->recursing))
+ need_destroy = ISC_TRUE;
+
+ UNLOCK(&manager->lock);
+
+ if (need_destroy)
+ clientmgr_destroy(manager);
+
+ *managerp = NULL;
+}
+
+isc_result_t
+ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
+ ns_interface_t *ifp, isc_boolean_t tcp)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ unsigned int i;
+ ns_client_t *client;
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(n > 0);
+
+ MTRACE("createclients");
+
+ /*
+ * We MUST lock the manager lock for the entire client creation
+ * process. If we didn't do this, then a client could get a
+ * shutdown event and disappear out from under us.
+ */
+
+ LOCK(&manager->lock);
+
+ for (i = 0; i < n; i++) {
+ isc_event_t *ev;
+ /*
+ * Allocate a client. First try to get a recycled one;
+ * if that fails, make a new one.
+ */
+ client = NULL;
+ if (!ns_g_clienttest)
+ client = ISC_LIST_HEAD(manager->inactive);
+ if (client != NULL) {
+ MTRACE("recycle");
+ ISC_LIST_UNLINK(manager->inactive, client, link);
+ client->list = NULL;
+ } else {
+ MTRACE("create new");
+ result = client_create(manager, &client);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+
+ ns_interface_attach(ifp, &client->interface);
+ client->state = NS_CLIENTSTATE_READY;
+ INSIST(client->recursionquota == NULL);
+
+ if (tcp) {
+ client->attributes |= NS_CLIENTATTR_TCP;
+ isc_socket_attach(ifp->tcpsocket,
+ &client->tcplistener);
+ } else {
+ isc_socket_t *sock;
+
+ dns_dispatch_attach(ifp->udpdispatch,
+ &client->dispatch);
+ sock = dns_dispatch_getsocket(client->dispatch);
+ isc_socket_attach(sock, &client->udpsocket);
+ }
+ client->manager = manager;
+ ISC_LIST_APPEND(manager->active, client, link);
+ client->list = &manager->active;
+
+ INSIST(client->nctls == 0);
+ client->nctls++;
+ ev = &client->ctlevent;
+ isc_task_send(client->task, &ev);
+ }
+ if (i != 0) {
+ /*
+ * We managed to create at least one client, so we
+ * declare victory.
+ */
+ result = ISC_R_SUCCESS;
+ }
+
+ UNLOCK(&manager->lock);
+
+ return (result);
+}
+
+isc_sockaddr_t *
+ns_client_getsockaddr(ns_client_t *client) {
+ return (&client->peeraddr);
+}
+
+isc_result_t
+ns_client_checkaclsilent(ns_client_t *client, isc_sockaddr_t *sockaddr,
+ dns_acl_t *acl, isc_boolean_t default_allow)
+{
+ isc_result_t result;
+ int match;
+ isc_netaddr_t netaddr;
+
+ if (acl == NULL) {
+ if (default_allow)
+ goto allow;
+ else
+ goto deny;
+ }
+
+
+ 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);
+
+ if (result != ISC_R_SUCCESS)
+ goto deny; /* Internal error, already logged. */
+ if (match > 0)
+ goto allow;
+ goto deny; /* Negative match or no match. */
+
+ allow:
+ return (ISC_R_SUCCESS);
+
+ deny:
+ return (DNS_R_REFUSED);
+}
+
+isc_result_t
+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);
+
+ if (result == ISC_R_SUCCESS)
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
+ "%s approved", opname);
+ else
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_CLIENT,
+ log_level, "%s denied", opname);
+ return (result);
+}
+
+static void
+ns_client_name(ns_client_t *client, char *peerbuf, size_t len) {
+ if (client->peeraddr_valid)
+ isc_sockaddr_format(&client->peeraddr, peerbuf, len);
+ else
+ snprintf(peerbuf, len, "@%p", client);
+}
+
+void
+ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *fmt, va_list ap)
+{
+ char msgbuf[2048];
+ char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+ const char *name = "";
+ const char *sep = "";
+
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ ns_client_name(client, peerbuf, sizeof(peerbuf));
+ if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 &&
+ strcmp(client->view->name, "_default") != 0) {
+ name = client->view->name;
+ sep = ": view ";
+ }
+
+ isc_log_write(ns_g_lctx, category, module, level,
+ "client %s%s%s: %s", peerbuf, sep, name, msgbuf);
+}
+
+void
+ns_client_log(ns_client_t *client, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (! isc_log_wouldlog(ns_g_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ ns_client_logv(client, category, module, level, fmt, ap);
+ va_end(ap);
+}
+
+void
+ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
+ dns_rdataclass_t rdclass, char *buf, size_t len)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+ dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
+ (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
+ classbuf);
+}
+
+static void
+ns_client_dumpmessage(ns_client_t *client, const char *reason) {
+ isc_buffer_t buffer;
+ char *buf = NULL;
+ int len = 1024;
+ isc_result_t result;
+
+ /*
+ * Note that these are multiline debug messages. We want a newline
+ * to appear in the log after each message.
+ */
+
+ do {
+ buf = isc_mem_get(client->mctx, len);
+ if (buf == NULL)
+ break;
+ isc_buffer_init(&buffer, buf, len);
+ result = dns_message_totext(client->message,
+ &dns_master_style_debug,
+ 0, &buffer);
+ if (result == ISC_R_NOSPACE) {
+ isc_mem_put(client->mctx, buf, len);
+ len += 1024;
+ } else if (result == ISC_R_SUCCESS)
+ ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
+ NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
+ "%s\n%.*s", reason,
+ (int)isc_buffer_usedlength(&buffer),
+ buf);
+ } while (result == ISC_R_NOSPACE);
+
+ if (buf != NULL)
+ isc_mem_put(client->mctx, buf, len);
+}
+
+void
+ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) {
+ ns_client_t *client;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+ const char *name;
+ const char *sep;
+
+ REQUIRE(VALID_MANAGER(manager));
+
+ LOCK(&manager->lock);
+ client = ISC_LIST_HEAD(manager->recursing);
+ while (client != NULL) {
+ ns_client_name(client, peerbuf, sizeof(peerbuf));
+ if (client->view != NULL &&
+ strcmp(client->view->name, "_bind") != 0 &&
+ strcmp(client->view->name, "_default") != 0) {
+ name = client->view->name;
+ sep = ": view ";
+ } else {
+ name = "";
+ 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);
+ client = ISC_LIST_NEXT(client, link);
+ }
+ UNLOCK(&manager->lock);
+}
+
+void
+ns_client_qnamereplace(ns_client_t *client, dns_name_t *name) {
+
+ if (client->manager != NULL)
+ LOCK(&client->manager->lock);
+ if (client->query.restarts > 0) {
+ /*
+ * client->query.qname was dynamically allocated.
+ */
+ dns_message_puttempname(client->message,
+ &client->query.qname);
+ }
+ client->query.qname = name;
+ if (client->manager != NULL)
+ UNLOCK(&client->manager->lock);
+}
diff --git a/bin/named/config.c b/bin/named/config.c
new file mode 100644
index 0000000..96b071d
--- /dev/null
+++ b/bin/named/config.c
@@ -0,0 +1,807 @@
+/*
+ * Copyright (C) 2004-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: config.c,v 1.93 2008/11/06 05:30:24 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/parseint.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <isccfg/namedconf.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/tsig.h>
+#include <dns/zone.h>
+
+#include <named/config.h>
+#include <named/globals.h>
+
+/*% default configuration */
+static char defaultconf[] = "\
+options {\n\
+# blackhole {none;};\n"
+#ifndef WIN32
+" coresize default;\n\
+ datasize default;\n\
+ files unlimited;\n\
+ stacksize default;\n"
+#endif
+" deallocate-on-exit true;\n\
+# directory <none>\n\
+ dump-file \"named_dump.db\";\n\
+ fake-iquery no;\n\
+ has-old-clients false;\n\
+ heartbeat-interval 60;\n\
+ host-statistics no;\n\
+ interface-interval 60;\n\
+ listen-on {any;};\n\
+ listen-on-v6 {none;};\n\
+ match-mapped-addresses no;\n\
+ memstatistics-file \"named.memstats\";\n\
+ multiple-cnames no;\n\
+# named-xfer <obsolete>;\n\
+# pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\
+ port 53;\n\
+ recursing-file \"named.recursing\";\n\
+"
+#ifdef PATH_RANDOMDEV
+"\
+ random-device \"" PATH_RANDOMDEV "\";\n\
+"
+#endif
+"\
+ recursive-clients 1000;\n\
+ rrset-order {type NS order random; order cyclic; };\n\
+ serial-queries 20;\n\
+ serial-query-rate 20;\n\
+ server-id none;\n\
+ statistics-file \"named.stats\";\n\
+ statistics-interval 60;\n\
+ tcp-clients 100;\n\
+ tcp-listen-queue 3;\n\
+# tkey-dhkey <none>\n\
+# tkey-gssapi-credential <none>\n\
+# tkey-domain <none>\n\
+ transfers-per-ns 2;\n\
+ transfers-in 10;\n\
+ transfers-out 10;\n\
+ treat-cr-as-space true;\n\
+ use-id-pool true;\n\
+ use-ixfr true;\n\
+ edns-udp-size 4096;\n\
+ max-udp-size 4096;\n\
+ request-nsid false;\n\
+ reserved-sockets 512;\n\
+\n\
+ /* view */\n\
+ allow-notify {none;};\n\
+ allow-update-forwarding {none;};\n\
+ allow-query-cache { localnets; localhost; };\n\
+ allow-query-cache-on { any; };\n\
+ allow-recursion { localnets; localhost; };\n\
+ allow-recursion-on { any; };\n\
+# allow-v6-synthesis <obsolete>;\n\
+# sortlist <none>\n\
+# topology <none>\n\
+ auth-nxdomain false;\n\
+ minimal-responses false;\n\
+ recursion true;\n\
+ provide-ixfr true;\n\
+ request-ixfr true;\n\
+ fetch-glue no;\n\
+ rfc2308-type1 no;\n\
+ additional-from-auth true;\n\
+ additional-from-cache true;\n\
+ query-source address *;\n\
+ query-source-v6 address *;\n\
+ notify-source *;\n\
+ notify-source-v6 *;\n\
+ cleaning-interval 0; /* now meaningless */\n\
+ min-roots 2;\n\
+ lame-ttl 600;\n\
+ max-ncache-ttl 10800; /* 3 hours */\n\
+ max-cache-ttl 604800; /* 1 week */\n\
+ transfer-format many-answers;\n\
+ max-cache-size 0;\n\
+ check-names master fail;\n\
+ check-names slave warn;\n\
+ check-names response ignore;\n\
+ check-mx warn;\n\
+ acache-enable no;\n\
+ acache-cleaning-interval 60;\n\
+ max-acache-size 16M;\n\
+ dnssec-enable yes;\n\
+ dnssec-validation yes; \n\
+ dnssec-accept-expired no;\n\
+ clients-per-query 10;\n\
+ max-clients-per-query 100;\n\
+ zero-no-soa-ttl-cache no;\n\
+ nsec3-test-zone no;\n\
+"
+
+" /* zone */\n\
+ allow-query {any;};\n\
+ allow-query-on {any;};\n\
+ allow-transfer {any;};\n\
+ notify yes;\n\
+# also-notify <none>\n\
+ notify-delay 5;\n\
+ notify-to-soa no;\n\
+ dialup no;\n\
+# forward <none>\n\
+# forwarders <none>\n\
+ maintain-ixfr-base no;\n\
+# max-ixfr-log-size <obsolete>\n\
+ transfer-source *;\n\
+ transfer-source-v6 *;\n\
+ alt-transfer-source *;\n\
+ alt-transfer-source-v6 *;\n\
+ max-transfer-time-in 120;\n\
+ max-transfer-time-out 120;\n\
+ max-transfer-idle-in 60;\n\
+ max-transfer-idle-out 60;\n\
+ max-retry-time 1209600; /* 2 weeks */\n\
+ min-retry-time 500;\n\
+ max-refresh-time 2419200; /* 4 weeks */\n\
+ min-refresh-time 300;\n\
+ multi-master no;\n\
+ sig-validity-interval 30; /* days */\n\
+ sig-signing-nodes 100;\n\
+ sig-signing-signatures 10;\n\
+ sig-signing-type 65535;\n\
+ zone-statistics false;\n\
+ max-journal-size unlimited;\n\
+ ixfr-from-differences false;\n\
+ check-wildcard yes;\n\
+ check-sibling yes;\n\
+ check-integrity yes;\n\
+ check-mx-cname warn;\n\
+ check-srv-cname warn;\n\
+ zero-no-soa-ttl yes;\n\
+ update-check-ksk yes;\n\
+ try-tcp-refresh yes; /* BIND 8 compat */\n\
+};\n\
+"
+
+"#\n\
+# Zones in the \"_bind\" view are NOT counted in the count of zones.\n\
+#\n\
+view \"_bind\" chaos {\n\
+ recursion no;\n\
+ notify no;\n\
+\n\
+ zone \"version.bind\" chaos {\n\
+ type master;\n\
+ database \"_builtin version\";\n\
+ };\n\
+\n\
+ zone \"hostname.bind\" chaos {\n\
+ type master;\n\
+ database \"_builtin hostname\";\n\
+ };\n\
+\n\
+ zone \"authors.bind\" chaos {\n\
+ type master;\n\
+ database \"_builtin authors\";\n\
+ };\n\
+ zone \"id.server\" chaos {\n\
+ type master;\n\
+ database \"_builtin id\";\n\
+ };\n\
+};\n\
+";
+
+isc_result_t
+ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1);
+ isc_buffer_add(&b, sizeof(defaultconf) - 1);
+ return (cfg_parse_buffer(parser, &b, &cfg_type_namedconf, conf));
+}
+
+isc_result_t
+ns_config_get(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) {
+ int i;
+
+ for (i = 0;; i++) {
+ if (maps[i] == NULL)
+ return (ISC_R_NOTFOUND);
+ if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+ }
+}
+
+isc_result_t
+ns_checknames_get(const cfg_obj_t **maps, const char *which,
+ const cfg_obj_t **obj)
+{
+ const cfg_listelt_t *element;
+ const cfg_obj_t *checknames;
+ const cfg_obj_t *type;
+ const cfg_obj_t *value;
+ int i;
+
+ for (i = 0;; i++) {
+ if (maps[i] == NULL)
+ return (ISC_R_NOTFOUND);
+ checknames = NULL;
+ if (cfg_map_get(maps[i], "check-names", &checknames) == ISC_R_SUCCESS) {
+ /*
+ * Zone map entry is not a list.
+ */
+ if (checknames != NULL && !cfg_obj_islist(checknames)) {
+ *obj = checknames;
+ return (ISC_R_SUCCESS);
+ }
+ for (element = cfg_list_first(checknames);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ value = cfg_listelt_value(element);
+ type = cfg_tuple_get(value, "type");
+ if (strcasecmp(cfg_obj_asstring(type), which) == 0) {
+ *obj = cfg_tuple_get(value, "mode");
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ }
+ }
+}
+
+int
+ns_config_listcount(const cfg_obj_t *list) {
+ const cfg_listelt_t *e;
+ int i = 0;
+
+ for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e))
+ i++;
+
+ return (i);
+}
+
+isc_result_t
+ns_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
+ dns_rdataclass_t *classp) {
+ isc_textregion_t r;
+ isc_result_t result;
+
+ if (!cfg_obj_isstring(classobj)) {
+ *classp = defclass;
+ return (ISC_R_SUCCESS);
+ }
+ DE_CONST(cfg_obj_asstring(classobj), r.base);
+ r.length = strlen(r.base);
+ result = dns_rdataclass_fromtext(classp, &r);
+ if (result != ISC_R_SUCCESS)
+ cfg_obj_log(classobj, ns_g_lctx, ISC_LOG_ERROR,
+ "unknown class '%s'", r.base);
+ return (result);
+}
+
+isc_result_t
+ns_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype,
+ dns_rdatatype_t *typep) {
+ isc_textregion_t r;
+ isc_result_t result;
+
+ if (!cfg_obj_isstring(typeobj)) {
+ *typep = deftype;
+ return (ISC_R_SUCCESS);
+ }
+ DE_CONST(cfg_obj_asstring(typeobj), r.base);
+ r.length = strlen(r.base);
+ result = dns_rdatatype_fromtext(typep, &r);
+ if (result != ISC_R_SUCCESS)
+ cfg_obj_log(typeobj, ns_g_lctx, ISC_LOG_ERROR,
+ "unknown type '%s'", r.base);
+ return (result);
+}
+
+dns_zonetype_t
+ns_config_getzonetype(const cfg_obj_t *zonetypeobj) {
+ dns_zonetype_t ztype = dns_zone_none;
+ const char *str;
+
+ str = cfg_obj_asstring(zonetypeobj);
+ if (strcasecmp(str, "master") == 0)
+ ztype = dns_zone_master;
+ else if (strcasecmp(str, "slave") == 0)
+ ztype = dns_zone_slave;
+ else if (strcasecmp(str, "stub") == 0)
+ ztype = dns_zone_stub;
+ else
+ INSIST(0);
+ return (ztype);
+}
+
+isc_result_t
+ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
+ in_port_t defport, isc_mem_t *mctx,
+ isc_sockaddr_t **addrsp, isc_uint32_t *countp)
+{
+ int count, i = 0;
+ const cfg_obj_t *addrlist;
+ const cfg_obj_t *portobj;
+ const cfg_listelt_t *element;
+ isc_sockaddr_t *addrs;
+ in_port_t port;
+ isc_result_t result;
+
+ INSIST(addrsp != NULL && *addrsp == NULL);
+ INSIST(countp != NULL);
+
+ addrlist = cfg_tuple_get(list, "addresses");
+ count = ns_config_listcount(addrlist);
+
+ portobj = cfg_tuple_get(list, "port");
+ if (cfg_obj_isuint32(portobj)) {
+ isc_uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > ISC_UINT16_MAX) {
+ cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ return (ISC_R_RANGE);
+ }
+ port = (in_port_t) val;
+ } else if (defport != 0)
+ port = defport;
+ else {
+ result = ns_config_getport(config, &port);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
+ if (addrs == NULL)
+ return (ISC_R_NOMEMORY);
+
+ for (element = cfg_list_first(addrlist);
+ element != NULL;
+ element = cfg_list_next(element), i++)
+ {
+ INSIST(i < count);
+ addrs[i] = *cfg_obj_assockaddr(cfg_listelt_value(element));
+ if (isc_sockaddr_getport(&addrs[i]) == 0)
+ isc_sockaddr_setport(&addrs[i], port);
+ }
+ INSIST(i == count);
+
+ *addrsp = addrs;
+ *countp = count;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
+ isc_uint32_t count)
+{
+ INSIST(addrsp != NULL && *addrsp != NULL);
+
+ isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
+ *addrsp = NULL;
+}
+
+static isc_result_t
+get_masters_def(const cfg_obj_t *cctx, const char *name,
+ const cfg_obj_t **ret)
+{
+ isc_result_t result;
+ const cfg_obj_t *masters = NULL;
+ const cfg_listelt_t *elt;
+
+ result = cfg_map_get(cctx, "masters", &masters);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ for (elt = cfg_list_first(masters);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ const cfg_obj_t *list;
+ const char *listname;
+
+ list = cfg_listelt_value(elt);
+ listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
+
+ if (strcasecmp(listname, name) == 0) {
+ *ret = list;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
+ isc_mem_t *mctx, isc_sockaddr_t **addrsp,
+ dns_name_t ***keysp, isc_uint32_t *countp)
+{
+ isc_uint32_t addrcount = 0, keycount = 0, i = 0;
+ isc_uint32_t listcount = 0, l = 0, j;
+ isc_uint32_t stackcount = 0, pushed = 0;
+ isc_result_t result;
+ const cfg_listelt_t *element;
+ const cfg_obj_t *addrlist;
+ const cfg_obj_t *portobj;
+ in_port_t port;
+ dns_fixedname_t fname;
+ isc_sockaddr_t *addrs = NULL;
+ dns_name_t **keys = NULL;
+ struct { const char *name; } *lists = NULL;
+ struct {
+ const cfg_listelt_t *element;
+ in_port_t port;
+ } *stack = NULL;
+
+ REQUIRE(addrsp != NULL && *addrsp == NULL);
+ REQUIRE(keysp != NULL && *keysp == NULL);
+ REQUIRE(countp != NULL);
+
+ newlist:
+ addrlist = cfg_tuple_get(list, "addresses");
+ portobj = cfg_tuple_get(list, "port");
+ if (cfg_obj_isuint32(portobj)) {
+ isc_uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > ISC_UINT16_MAX) {
+ cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ port = (in_port_t) val;
+ } else {
+ result = ns_config_getport(config, &port);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ result = ISC_R_NOMEMORY;
+
+ element = cfg_list_first(addrlist);
+ resume:
+ for ( ;
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *addr;
+ const cfg_obj_t *key;
+ const char *keystr;
+ isc_buffer_t b;
+
+ addr = cfg_tuple_get(cfg_listelt_value(element),
+ "masterselement");
+ key = cfg_tuple_get(cfg_listelt_value(element), "key");
+
+ if (!cfg_obj_issockaddr(addr)) {
+ const char *listname = cfg_obj_asstring(addr);
+ isc_result_t tresult;
+
+ /* Grow lists? */
+ if (listcount == l) {
+ void * new;
+ isc_uint32_t newlen = listcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(*lists);
+ oldsize = listcount * sizeof(*lists);
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ if (listcount != 0) {
+ memcpy(new, lists, oldsize);
+ isc_mem_put(mctx, lists, oldsize);
+ }
+ lists = new;
+ listcount = newlen;
+ }
+ /* Seen? */
+ for (j = 0; j < l; j++)
+ if (strcasecmp(lists[j].name, listname) == 0)
+ break;
+ if (j < l)
+ continue;
+ tresult = get_masters_def(config, listname, &list);
+ if (tresult == ISC_R_NOTFOUND) {
+ cfg_obj_log(addr, ns_g_lctx, ISC_LOG_ERROR,
+ "masters \"%s\" not found", listname);
+
+ result = tresult;
+ goto cleanup;
+ }
+ if (tresult != ISC_R_SUCCESS)
+ goto cleanup;
+ lists[l++].name = listname;
+ /* Grow stack? */
+ if (stackcount == pushed) {
+ void * new;
+ isc_uint32_t newlen = stackcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(*stack);
+ oldsize = stackcount * sizeof(*stack);
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ if (stackcount != 0) {
+ memcpy(new, stack, oldsize);
+ isc_mem_put(mctx, stack, oldsize);
+ }
+ stack = new;
+ stackcount = newlen;
+ }
+ /*
+ * We want to resume processing this list on the
+ * next element.
+ */
+ stack[pushed].element = cfg_list_next(element);
+ stack[pushed].port = port;
+ pushed++;
+ goto newlist;
+ }
+
+ if (i == addrcount) {
+ void * new;
+ isc_uint32_t newlen = addrcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(isc_sockaddr_t);
+ oldsize = addrcount * sizeof(isc_sockaddr_t);
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ if (addrcount != 0) {
+ memcpy(new, addrs, oldsize);
+ isc_mem_put(mctx, addrs, oldsize);
+ }
+ addrs = new;
+ addrcount = newlen;
+
+ newsize = newlen * sizeof(dns_name_t *);
+ oldsize = keycount * sizeof(dns_name_t *);
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ if (keycount != 0) {
+ memcpy(new, keys, oldsize);
+ isc_mem_put(mctx, keys, oldsize);
+ }
+ keys = new;
+ keycount = newlen;
+ }
+
+ addrs[i] = *cfg_obj_assockaddr(addr);
+ if (isc_sockaddr_getport(&addrs[i]) == 0)
+ isc_sockaddr_setport(&addrs[i], port);
+ keys[i] = NULL;
+ if (!cfg_obj_isstring(key)) {
+ i++;
+ continue;
+ }
+ keys[i] = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (keys[i] == NULL)
+ goto cleanup;
+ dns_name_init(keys[i], NULL);
+
+ keystr = cfg_obj_asstring(key);
+ isc_buffer_init(&b, keystr, strlen(keystr));
+ isc_buffer_add(&b, strlen(keystr));
+ dns_fixedname_init(&fname);
+ result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
+ dns_rootname, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_name_dup(dns_fixedname_name(&fname), mctx,
+ keys[i]);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ i++;
+ }
+ if (pushed != 0) {
+ pushed--;
+ element = stack[pushed].element;
+ port = stack[pushed].port;
+ goto resume;
+ }
+ if (i < addrcount) {
+ void * new;
+ size_t newsize, oldsize;
+
+ newsize = i * sizeof(isc_sockaddr_t);
+ oldsize = addrcount * sizeof(isc_sockaddr_t);
+ if (i != 0) {
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ memcpy(new, addrs, newsize);
+ } else
+ new = NULL;
+ isc_mem_put(mctx, addrs, oldsize);
+ addrs = new;
+ addrcount = i;
+
+ newsize = i * sizeof(dns_name_t *);
+ oldsize = keycount * sizeof(dns_name_t *);
+ if (i != 0) {
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ memcpy(new, keys, newsize);
+ } else
+ new = NULL;
+ isc_mem_put(mctx, keys, oldsize);
+ keys = new;
+ keycount = i;
+ }
+
+ if (lists != NULL)
+ isc_mem_put(mctx, lists, listcount * sizeof(*lists));
+ if (stack != NULL)
+ isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
+
+ INSIST(keycount == addrcount);
+
+ *addrsp = addrs;
+ *keysp = keys;
+ *countp = addrcount;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (addrs != NULL)
+ isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t));
+ if (keys != NULL) {
+ for (j = 0; j <= i; j++) {
+ if (keys[j] == NULL)
+ continue;
+ if (dns_name_dynamic(keys[j]))
+ dns_name_free(keys[j], mctx);
+ isc_mem_put(mctx, keys[j], sizeof(dns_name_t));
+ }
+ isc_mem_put(mctx, keys, keycount * sizeof(dns_name_t *));
+ }
+ if (lists != NULL)
+ isc_mem_put(mctx, lists, listcount * sizeof(*lists));
+ if (stack != NULL)
+ isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
+ return (result);
+}
+
+void
+ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
+ dns_name_t ***keysp, isc_uint32_t count)
+{
+ unsigned int i;
+ dns_name_t **keys = *keysp;
+
+ INSIST(addrsp != NULL && *addrsp != NULL);
+
+ isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
+ for (i = 0; i < count; i++) {
+ if (keys[i] == NULL)
+ continue;
+ if (dns_name_dynamic(keys[i]))
+ dns_name_free(keys[i], mctx);
+ isc_mem_put(mctx, keys[i], sizeof(dns_name_t));
+ }
+ isc_mem_put(mctx, *keysp, count * sizeof(dns_name_t *));
+ *addrsp = NULL;
+ *keysp = NULL;
+}
+
+isc_result_t
+ns_config_getport(const cfg_obj_t *config, in_port_t *portp) {
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *portobj = NULL;
+ isc_result_t result;
+ int i;
+
+ (void)cfg_map_get(config, "options", &options);
+ i = 0;
+ if (options != NULL)
+ maps[i++] = options;
+ maps[i++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ result = ns_config_get(maps, "port", &portobj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
+ cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
+ "port '%u' out of range",
+ cfg_obj_asuint32(portobj));
+ return (ISC_R_RANGE);
+ }
+ *portp = (in_port_t)cfg_obj_asuint32(portobj);
+ return (ISC_R_SUCCESS);
+}
+
+struct keyalgorithms {
+ const char *str;
+ enum { hmacnone, hmacmd5, hmacsha1, hmacsha224,
+ hmacsha256, hmacsha384, hmacsha512 } hmac;
+ 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 }
+};
+
+isc_result_t
+ns_config_getkeyalgorithm(const char *str, dns_name_t **name,
+ isc_uint16_t *digestbits)
+{
+ int i;
+ size_t len = 0;
+ isc_uint16_t bits;
+ isc_result_t result;
+
+ for (i = 0; algorithms[i].str != NULL; i++) {
+ len = strlen(algorithms[i].str);
+ if (strncasecmp(algorithms[i].str, str, len) == 0 &&
+ (str[len] == '\0' ||
+ (algorithms[i].size != 0 && str[len] == '-')))
+ break;
+ }
+ if (algorithms[i].str == NULL)
+ return (ISC_R_NOTFOUND);
+ if (str[len] == '-') {
+ result = isc_parse_uint16(&bits, str + len + 1, 10);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (bits > algorithms[i].size)
+ return (ISC_R_RANGE);
+ } else if (algorithms[i].size == 0)
+ bits = 128;
+ else
+ bits = algorithms[i].size;
+
+ if (name != NULL) {
+ switch (algorithms[i].hmac) {
+ case hmacmd5: *name = dns_tsig_hmacmd5_name; break;
+ case hmacsha1: *name = dns_tsig_hmacsha1_name; break;
+ case hmacsha224: *name = dns_tsig_hmacsha224_name; break;
+ case hmacsha256: *name = dns_tsig_hmacsha256_name; break;
+ case hmacsha384: *name = dns_tsig_hmacsha384_name; break;
+ case hmacsha512: *name = dns_tsig_hmacsha512_name; break;
+ default:
+ INSIST(0);
+ }
+ }
+ if (digestbits != NULL)
+ *digestbits = bits;
+ return (ISC_R_SUCCESS);
+}
diff --git a/bin/named/control.c b/bin/named/control.c
new file mode 100644
index 0000000..8bd8f6c
--- /dev/null
+++ b/bin/named/control.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2004-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: control.c,v 1.33 2007/09/13 04:45:18 each Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+
+#include <isc/app.h>
+#include <isc/event.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/result.h>
+
+#include <isccc/alist.h>
+#include <isccc/cc.h>
+#include <isccc/result.h>
+
+#include <named/control.h>
+#include <named/log.h>
+#include <named/os.h>
+#include <named/server.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#endif
+
+static isc_boolean_t
+command_compare(const char *text, const char *command) {
+ unsigned int commandlen = strlen(command);
+ if (strncasecmp(text, command, commandlen) == 0 &&
+ (text[commandlen] == '\0' ||
+ text[commandlen] == ' ' ||
+ text[commandlen] == '\t'))
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+/*%
+ * This function is called to process the incoming command
+ * when a control channel message is received.
+ */
+isc_result_t
+ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
+ isccc_sexpr_t *data;
+ char *command;
+ isc_result_t result;
+ int log_level;
+#ifdef HAVE_LIBSCF
+ ns_smf_want_disable = 0;
+#endif
+
+ data = isccc_alist_lookup(message, "_data");
+ if (data == NULL) {
+ /*
+ * No data section.
+ */
+ return (ISC_R_FAILURE);
+ }
+
+ result = isccc_cc_lookupstring(data, "type", &command);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * We have no idea what this is.
+ */
+ return (result);
+ }
+
+ /*
+ * Compare the 'command' parameter against all known control commands.
+ */
+ if (command_compare(command, NS_COMMAND_NULL) ||
+ command_compare(command, NS_COMMAND_STATUS)) {
+ log_level = ISC_LOG_DEBUG(1);
+ } else {
+ log_level = ISC_LOG_INFO;
+ }
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, log_level,
+ "received control channel command '%s'",
+ command);
+
+ if (command_compare(command, NS_COMMAND_RELOAD)) {
+ result = ns_server_reloadcommand(ns_g_server, command, text);
+ } else if (command_compare(command, NS_COMMAND_RECONFIG)) {
+ result = ns_server_reconfigcommand(ns_g_server, command);
+ } else if (command_compare(command, NS_COMMAND_REFRESH)) {
+ result = ns_server_refreshcommand(ns_g_server, command, text);
+ } else if (command_compare(command, NS_COMMAND_RETRANSFER)) {
+ result = ns_server_retransfercommand(ns_g_server, command);
+ } else if (command_compare(command, NS_COMMAND_HALT)) {
+#ifdef HAVE_LIBSCF
+ /*
+ * If we are managed by smf(5), AND in chroot, then
+ * we cannot connect to the smf repository, so just
+ * return with an appropriate message back to rndc.
+ */
+ if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
+ result = ns_smf_add_message(text);
+ return (result);
+ }
+ /*
+ * If we are managed by smf(5) but not in chroot,
+ * try to disable ourselves the smf way.
+ */
+ if (ns_smf_got_instance == 1 && ns_smf_chroot == 0)
+ ns_smf_want_disable = 1;
+ /*
+ * If ns_smf_got_instance = 0, ns_smf_chroot
+ * is not relevant and we fall through to
+ * isc_app_shutdown below.
+ */
+#endif
+ ns_server_flushonshutdown(ns_g_server, ISC_FALSE);
+ ns_os_shutdownmsg(command, text);
+ isc_app_shutdown();
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NS_COMMAND_STOP)) {
+#ifdef HAVE_LIBSCF
+ if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
+ result = ns_smf_add_message(text);
+ return (result);
+ }
+ if (ns_smf_got_instance == 1 && ns_smf_chroot == 0)
+ ns_smf_want_disable = 1;
+#endif
+ ns_server_flushonshutdown(ns_g_server, ISC_TRUE);
+ ns_os_shutdownmsg(command, text);
+ isc_app_shutdown();
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NS_COMMAND_DUMPSTATS)) {
+ result = ns_server_dumpstats(ns_g_server);
+ } else if (command_compare(command, NS_COMMAND_QUERYLOG)) {
+ result = ns_server_togglequerylog(ns_g_server);
+ } 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_TRACE)) {
+ result = ns_server_setdebuglevel(ns_g_server, command);
+ } else if (command_compare(command, NS_COMMAND_NOTRACE)) {
+ ns_g_debuglevel = 0;
+ isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NS_COMMAND_FLUSH)) {
+ result = ns_server_flushcache(ns_g_server, command);
+ } else if (command_compare(command, NS_COMMAND_FLUSHNAME)) {
+ result = ns_server_flushname(ns_g_server, command);
+ } else if (command_compare(command, NS_COMMAND_STATUS)) {
+ result = ns_server_status(ns_g_server, text);
+ } else if (command_compare(command, NS_COMMAND_TSIGLIST)) {
+ result = ns_server_tsiglist(ns_g_server, text);
+ } else if (command_compare(command, NS_COMMAND_TSIGDELETE)) {
+ result = ns_server_tsigdelete(ns_g_server, command, text);
+ } else if (command_compare(command, NS_COMMAND_FREEZE)) {
+ result = ns_server_freeze(ns_g_server, ISC_TRUE, command);
+ } else if (command_compare(command, NS_COMMAND_UNFREEZE) ||
+ command_compare(command, NS_COMMAND_THAW)) {
+ result = ns_server_freeze(ns_g_server, ISC_FALSE, command);
+ } else if (command_compare(command, NS_COMMAND_RECURSING)) {
+ result = ns_server_dumprecursing(ns_g_server);
+ } else if (command_compare(command, NS_COMMAND_TIMERPOKE)) {
+ result = ISC_R_SUCCESS;
+ isc_timermgr_poke(ns_g_timermgr);
+ } else if (command_compare(command, NS_COMMAND_NULL)) {
+ result = ISC_R_SUCCESS;
+ } else if (command_compare(command, NS_COMMAND_NOTIFY)) {
+ 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 {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "unknown control channel command '%s'",
+ command);
+ result = DNS_R_UNKNOWNCOMMAND;
+ }
+
+ return (result);
+}
diff --git a/bin/named/controlconf.c b/bin/named/controlconf.c
new file mode 100644
index 0000000..766f013
--- /dev/null
+++ b/bin/named/controlconf.c
@@ -0,0 +1,1459 @@
+/*
+ * Copyright (C) 2004-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: controlconf.c,v 1.60 2008/07/23 23:27:54 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/event.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/stdtime.h>
+#include <isc/string.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <isccfg/namedconf.h>
+
+#include <bind9/check.h>
+
+#include <isccc/alist.h>
+#include <isccc/cc.h>
+#include <isccc/ccmsg.h>
+#include <isccc/events.h>
+#include <isccc/result.h>
+#include <isccc/sexpr.h>
+#include <isccc/symtab.h>
+#include <isccc/util.h>
+
+#include <dns/result.h>
+
+#include <named/config.h>
+#include <named/control.h>
+#include <named/log.h>
+#include <named/server.h>
+
+/*
+ * Note: Listeners and connections are not locked. All event handlers are
+ * executed by the server task, and all callers of exported routines must
+ * be running under the server task.
+ */
+
+typedef struct controlkey controlkey_t;
+typedef ISC_LIST(controlkey_t) controlkeylist_t;
+
+typedef struct controlconnection controlconnection_t;
+typedef ISC_LIST(controlconnection_t) controlconnectionlist_t;
+
+typedef struct controllistener controllistener_t;
+typedef ISC_LIST(controllistener_t) controllistenerlist_t;
+
+struct controlkey {
+ char * keyname;
+ isc_region_t secret;
+ ISC_LINK(controlkey_t) link;
+};
+
+struct controlconnection {
+ isc_socket_t * sock;
+ isccc_ccmsg_t ccmsg;
+ isc_boolean_t ccmsg_valid;
+ isc_boolean_t sending;
+ isc_timer_t * timer;
+ unsigned char buffer[2048];
+ controllistener_t * listener;
+ isc_uint32_t nonce;
+ ISC_LINK(controlconnection_t) link;
+};
+
+struct controllistener {
+ ns_controls_t * controls;
+ isc_mem_t * mctx;
+ isc_task_t * task;
+ isc_sockaddr_t address;
+ isc_socket_t * sock;
+ dns_acl_t * acl;
+ isc_boolean_t listening;
+ isc_boolean_t exiting;
+ controlkeylist_t keys;
+ controlconnectionlist_t connections;
+ isc_sockettype_t type;
+ isc_uint32_t perm;
+ isc_uint32_t owner;
+ isc_uint32_t group;
+ ISC_LINK(controllistener_t) link;
+};
+
+struct ns_controls {
+ ns_server_t *server;
+ controllistenerlist_t listeners;
+ isc_boolean_t shuttingdown;
+ isccc_symtab_t *symtab;
+};
+
+static void control_newconn(isc_task_t *task, isc_event_t *event);
+static void control_recvmessage(isc_task_t *task, isc_event_t *event);
+
+#define CLOCKSKEW 300
+
+static void
+free_controlkey(controlkey_t *key, isc_mem_t *mctx) {
+ if (key->keyname != NULL)
+ isc_mem_free(mctx, key->keyname);
+ if (key->secret.base != NULL)
+ isc_mem_put(mctx, key->secret.base, key->secret.length);
+ isc_mem_put(mctx, key, sizeof(*key));
+}
+
+static void
+free_controlkeylist(controlkeylist_t *keylist, isc_mem_t *mctx) {
+ while (!ISC_LIST_EMPTY(*keylist)) {
+ controlkey_t *key = ISC_LIST_HEAD(*keylist);
+ ISC_LIST_UNLINK(*keylist, key, link);
+ free_controlkey(key, mctx);
+ }
+}
+
+static void
+free_listener(controllistener_t *listener) {
+ INSIST(listener->exiting);
+ INSIST(!listener->listening);
+ INSIST(ISC_LIST_EMPTY(listener->connections));
+
+ if (listener->sock != NULL)
+ isc_socket_detach(&listener->sock);
+
+ free_controlkeylist(&listener->keys, listener->mctx);
+
+ if (listener->acl != NULL)
+ dns_acl_detach(&listener->acl);
+
+ isc_mem_put(listener->mctx, listener, sizeof(*listener));
+}
+
+static void
+maybe_free_listener(controllistener_t *listener) {
+ if (listener->exiting &&
+ !listener->listening &&
+ ISC_LIST_EMPTY(listener->connections))
+ free_listener(listener);
+}
+
+static void
+maybe_free_connection(controlconnection_t *conn) {
+ controllistener_t *listener = conn->listener;
+
+ if (conn->timer != NULL)
+ isc_timer_detach(&conn->timer);
+
+ if (conn->ccmsg_valid) {
+ isccc_ccmsg_cancelread(&conn->ccmsg);
+ return;
+ }
+
+ if (conn->sending) {
+ isc_socket_cancel(conn->sock, listener->task,
+ ISC_SOCKCANCEL_SEND);
+ return;
+ }
+
+ ISC_LIST_UNLINK(listener->connections, conn, link);
+ isc_mem_put(listener->mctx, conn, sizeof(*conn));
+}
+
+static void
+shutdown_listener(controllistener_t *listener) {
+ controlconnection_t *conn;
+ controlconnection_t *next;
+
+ if (!listener->exiting) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ ISC_LIST_UNLINK(listener->controls->listeners, listener, link);
+
+ isc_sockaddr_format(&listener->address, socktext,
+ sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
+ "stopping command channel on %s", socktext);
+ if (listener->type == isc_sockettype_unix)
+ isc_socket_cleanunix(&listener->address, ISC_TRUE);
+ listener->exiting = ISC_TRUE;
+ }
+
+ for (conn = ISC_LIST_HEAD(listener->connections);
+ conn != NULL;
+ conn = next)
+ {
+ next = ISC_LIST_NEXT(conn, link);
+ maybe_free_connection(conn);
+ }
+
+ if (listener->listening)
+ isc_socket_cancel(listener->sock, listener->task,
+ ISC_SOCKCANCEL_ACCEPT);
+
+ maybe_free_listener(listener);
+}
+
+static isc_boolean_t
+address_ok(isc_sockaddr_t *sockaddr, dns_acl_t *acl) {
+ isc_netaddr_t netaddr;
+ isc_result_t result;
+ int match;
+
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+
+ result = dns_acl_match(&netaddr, NULL, acl,
+ &ns_g_server->aclenv, &match, NULL);
+
+ if (result != ISC_R_SUCCESS || match <= 0)
+ return (ISC_FALSE);
+ else
+ return (ISC_TRUE);
+}
+
+static isc_result_t
+control_accept(controllistener_t *listener) {
+ isc_result_t result;
+ result = isc_socket_accept(listener->sock,
+ listener->task,
+ control_newconn, listener);
+ if (result != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socket_accept() failed: %s",
+ isc_result_totext(result));
+ else
+ listener->listening = ISC_TRUE;
+ return (result);
+}
+
+static isc_result_t
+control_listen(controllistener_t *listener) {
+ isc_result_t result;
+
+ result = isc_socket_listen(listener->sock, 0);
+ if (result != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socket_listen() failed: %s",
+ isc_result_totext(result));
+ return (result);
+}
+
+static void
+control_next(controllistener_t *listener) {
+ (void)control_accept(listener);
+}
+
+static void
+control_senddone(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *) event;
+ controlconnection_t *conn = event->ev_arg;
+ controllistener_t *listener = conn->listener;
+ isc_socket_t *sock = (isc_socket_t *)sevent->ev_sender;
+ isc_result_t result;
+
+ REQUIRE(conn->sending);
+
+ UNUSED(task);
+
+ conn->sending = ISC_FALSE;
+
+ if (sevent->result != ISC_R_SUCCESS &&
+ sevent->result != ISC_R_CANCELED)
+ {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t peeraddr;
+
+ (void)isc_socket_getpeername(sock, &peeraddr);
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "error sending command response to %s: %s",
+ socktext, isc_result_totext(sevent->result));
+ }
+ isc_event_free(&event);
+
+ result = isccc_ccmsg_readmessage(&conn->ccmsg, listener->task,
+ control_recvmessage, conn);
+ if (result != ISC_R_SUCCESS) {
+ isc_socket_detach(&conn->sock);
+ maybe_free_connection(conn);
+ maybe_free_listener(listener);
+ }
+}
+
+static inline void
+log_invalid(isccc_ccmsg_t *ccmsg, isc_result_t result) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t peeraddr;
+
+ (void)isc_socket_getpeername(ccmsg->sock, &peeraddr);
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_ERROR,
+ "invalid command from %s: %s",
+ socktext, isc_result_totext(result));
+}
+
+static void
+control_recvmessage(isc_task_t *task, isc_event_t *event) {
+ controlconnection_t *conn;
+ controllistener_t *listener;
+ controlkey_t *key;
+ isccc_sexpr_t *request = NULL;
+ isccc_sexpr_t *response = NULL;
+ isccc_region_t ccregion;
+ isccc_region_t secret;
+ isc_stdtime_t now;
+ isc_buffer_t b;
+ isc_region_t r;
+ isc_uint32_t len;
+ isc_buffer_t text;
+ char textarray[1024];
+ isc_result_t result;
+ isc_result_t eresult;
+ isccc_sexpr_t *_ctrl;
+ isccc_time_t sent;
+ isccc_time_t exp;
+ isc_uint32_t nonce;
+
+ REQUIRE(event->ev_type == ISCCC_EVENT_CCMSG);
+
+ conn = event->ev_arg;
+ listener = conn->listener;
+ secret.rstart = NULL;
+
+ /* Is the server shutting down? */
+ if (listener->controls->shuttingdown)
+ goto cleanup;
+
+ if (conn->ccmsg.result != ISC_R_SUCCESS) {
+ if (conn->ccmsg.result != ISC_R_CANCELED &&
+ conn->ccmsg.result != ISC_R_EOF)
+ log_invalid(&conn->ccmsg, conn->ccmsg.result);
+ goto cleanup;
+ }
+
+ request = NULL;
+
+ for (key = ISC_LIST_HEAD(listener->keys);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link))
+ {
+ ccregion.rstart = isc_buffer_base(&conn->ccmsg.buffer);
+ ccregion.rend = isc_buffer_used(&conn->ccmsg.buffer);
+ secret.rstart = isc_mem_get(listener->mctx, key->secret.length);
+ if (secret.rstart == NULL)
+ goto cleanup;
+ memcpy(secret.rstart, key->secret.base, key->secret.length);
+ secret.rend = secret.rstart + key->secret.length;
+ result = isccc_cc_fromwire(&ccregion, &request, &secret);
+ if (result == ISC_R_SUCCESS)
+ break;
+ isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
+ if (result == ISCCC_R_BADAUTH) {
+ /*
+ * For some reason, request is non-NULL when
+ * isccc_cc_fromwire returns ISCCC_R_BADAUTH.
+ */
+ if (request != NULL)
+ isccc_sexpr_free(&request);
+ } else {
+ log_invalid(&conn->ccmsg, result);
+ goto cleanup;
+ }
+ }
+
+ if (key == NULL) {
+ log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
+ goto cleanup;
+ }
+
+ /* We shouldn't be getting a reply. */
+ if (isccc_cc_isreply(request)) {
+ log_invalid(&conn->ccmsg, ISC_R_FAILURE);
+ goto cleanup_request;
+ }
+
+ isc_stdtime_get(&now);
+
+ /*
+ * Limit exposure to replay attacks.
+ */
+ _ctrl = isccc_alist_lookup(request, "_ctrl");
+ if (_ctrl == NULL) {
+ log_invalid(&conn->ccmsg, ISC_R_FAILURE);
+ goto cleanup_request;
+ }
+
+ if (isccc_cc_lookupuint32(_ctrl, "_tim", &sent) == ISC_R_SUCCESS) {
+ if ((sent + CLOCKSKEW) < now || (sent - CLOCKSKEW) > now) {
+ log_invalid(&conn->ccmsg, ISCCC_R_CLOCKSKEW);
+ goto cleanup_request;
+ }
+ } else {
+ log_invalid(&conn->ccmsg, ISC_R_FAILURE);
+ goto cleanup_request;
+ }
+
+ /*
+ * Expire messages that are too old.
+ */
+ if (isccc_cc_lookupuint32(_ctrl, "_exp", &exp) == ISC_R_SUCCESS &&
+ now > exp) {
+ log_invalid(&conn->ccmsg, ISCCC_R_EXPIRED);
+ goto cleanup_request;
+ }
+
+ /*
+ * Duplicate suppression (required for UDP).
+ */
+ isccc_cc_cleansymtab(listener->controls->symtab, now);
+ result = isccc_cc_checkdup(listener->controls->symtab, request, now);
+ if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_EXISTS)
+ result = ISCCC_R_DUPLICATE;
+ log_invalid(&conn->ccmsg, result);
+ goto cleanup_request;
+ }
+
+ if (conn->nonce != 0 &&
+ (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS ||
+ conn->nonce != nonce)) {
+ log_invalid(&conn->ccmsg, ISCCC_R_BADAUTH);
+ goto cleanup_request;
+ }
+
+ /*
+ * Establish nonce.
+ */
+ while (conn->nonce == 0)
+ isc_random_get(&conn->nonce);
+
+ isc_buffer_init(&text, textarray, sizeof(textarray));
+ eresult = ns_control_docommand(request, &text);
+
+ result = isccc_cc_createresponse(request, now, now + 60, &response);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_request;
+ if (eresult != ISC_R_SUCCESS) {
+ isccc_sexpr_t *data;
+
+ data = isccc_alist_lookup(response, "_data");
+ if (data != NULL) {
+ const char *estr = isc_result_totext(eresult);
+ if (isccc_cc_definestring(data, "err", estr) == NULL)
+ goto cleanup_response;
+ }
+ }
+
+ if (isc_buffer_usedlength(&text) > 0) {
+ isccc_sexpr_t *data;
+
+ data = isccc_alist_lookup(response, "_data");
+ if (data != NULL) {
+ char *str = (char *)isc_buffer_base(&text);
+ if (isccc_cc_definestring(data, "text", str) == NULL)
+ goto cleanup_response;
+ }
+ }
+
+ _ctrl = isccc_alist_lookup(response, "_ctrl");
+ if (_ctrl == NULL ||
+ isccc_cc_defineuint32(_ctrl, "_nonce", conn->nonce) == NULL)
+ goto cleanup_response;
+
+ ccregion.rstart = conn->buffer + 4;
+ ccregion.rend = conn->buffer + sizeof(conn->buffer);
+ result = isccc_cc_towire(response, &ccregion, &secret);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_response;
+ isc_buffer_init(&b, conn->buffer, 4);
+ len = sizeof(conn->buffer) - REGION_SIZE(ccregion);
+ isc_buffer_putuint32(&b, len - 4);
+ r.base = conn->buffer;
+ r.length = len;
+
+ result = isc_socket_send(conn->sock, &r, task, control_senddone, conn);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_response;
+ conn->sending = ISC_TRUE;
+
+ isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
+ isccc_sexpr_free(&request);
+ isccc_sexpr_free(&response);
+ return;
+
+ cleanup_response:
+ isccc_sexpr_free(&response);
+
+ cleanup_request:
+ isccc_sexpr_free(&request);
+ isc_mem_put(listener->mctx, secret.rstart, REGION_SIZE(secret));
+
+ cleanup:
+ isc_socket_detach(&conn->sock);
+ isccc_ccmsg_invalidate(&conn->ccmsg);
+ conn->ccmsg_valid = ISC_FALSE;
+ maybe_free_connection(conn);
+ maybe_free_listener(listener);
+}
+
+static void
+control_timeout(isc_task_t *task, isc_event_t *event) {
+ controlconnection_t *conn = event->ev_arg;
+
+ UNUSED(task);
+
+ isc_timer_detach(&conn->timer);
+ maybe_free_connection(conn);
+
+ isc_event_free(&event);
+}
+
+static isc_result_t
+newconnection(controllistener_t *listener, isc_socket_t *sock) {
+ controlconnection_t *conn;
+ isc_interval_t interval;
+ isc_result_t result;
+
+ conn = isc_mem_get(listener->mctx, sizeof(*conn));
+ if (conn == NULL)
+ return (ISC_R_NOMEMORY);
+
+ conn->sock = sock;
+ isccc_ccmsg_init(listener->mctx, sock, &conn->ccmsg);
+ conn->ccmsg_valid = ISC_TRUE;
+ conn->sending = ISC_FALSE;
+ conn->timer = NULL;
+ isc_interval_set(&interval, 60, 0);
+ result = isc_timer_create(ns_g_timermgr, isc_timertype_once,
+ NULL, &interval, listener->task,
+ control_timeout, conn, &conn->timer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ conn->listener = listener;
+ conn->nonce = 0;
+ ISC_LINK_INIT(conn, link);
+
+ result = isccc_ccmsg_readmessage(&conn->ccmsg, listener->task,
+ control_recvmessage, conn);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isccc_ccmsg_setmaxsize(&conn->ccmsg, 2048);
+
+ ISC_LIST_APPEND(listener->connections, conn, link);
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isccc_ccmsg_invalidate(&conn->ccmsg);
+ if (conn->timer != NULL)
+ isc_timer_detach(&conn->timer);
+ isc_mem_put(listener->mctx, conn, sizeof(*conn));
+ return (result);
+}
+
+static void
+control_newconn(isc_task_t *task, isc_event_t *event) {
+ isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;
+ controllistener_t *listener = event->ev_arg;
+ isc_socket_t *sock;
+ isc_sockaddr_t peeraddr;
+ isc_result_t result;
+
+ UNUSED(task);
+
+ listener->listening = ISC_FALSE;
+
+ if (nevent->result != ISC_R_SUCCESS) {
+ if (nevent->result == ISC_R_CANCELED) {
+ shutdown_listener(listener);
+ goto cleanup;
+ }
+ goto restart;
+ }
+
+ sock = nevent->newsocket;
+ isc_socket_setname(sock, "control", NULL);
+ (void)isc_socket_getpeername(sock, &peeraddr);
+ if (listener->type == isc_sockettype_tcp &&
+ !address_ok(&peeraddr, listener->acl)) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "rejected command channel message from %s",
+ socktext);
+ isc_socket_detach(&sock);
+ goto restart;
+ }
+
+ result = newconnection(listener, sock);
+ if (result != ISC_R_SUCCESS) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&peeraddr, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "dropped command channel from %s: %s",
+ socktext, isc_result_totext(result));
+ isc_socket_detach(&sock);
+ goto restart;
+ }
+
+ restart:
+ control_next(listener);
+ cleanup:
+ isc_event_free(&event);
+}
+
+static void
+controls_shutdown(ns_controls_t *controls) {
+ controllistener_t *listener;
+ controllistener_t *next;
+
+ for (listener = ISC_LIST_HEAD(controls->listeners);
+ listener != NULL;
+ listener = next)
+ {
+ /*
+ * This is asynchronous. As listeners shut down, they will
+ * call their callbacks.
+ */
+ next = ISC_LIST_NEXT(listener, link);
+ shutdown_listener(listener);
+ }
+}
+
+void
+ns_controls_shutdown(ns_controls_t *controls) {
+ controls_shutdown(controls);
+ controls->shuttingdown = ISC_TRUE;
+}
+
+static isc_result_t
+cfgkeylist_find(const cfg_obj_t *keylist, const char *keyname,
+ const cfg_obj_t **objp)
+{
+ const cfg_listelt_t *element;
+ const char *str;
+ const cfg_obj_t *obj;
+
+ for (element = cfg_list_first(keylist);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(cfg_map_getname(obj));
+ if (strcasecmp(str, keyname) == 0)
+ break;
+ }
+ if (element == NULL)
+ return (ISC_R_NOTFOUND);
+ obj = cfg_listelt_value(element);
+ *objp = obj;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+controlkeylist_fromcfg(const cfg_obj_t *keylist, isc_mem_t *mctx,
+ controlkeylist_t *keyids)
+{
+ const cfg_listelt_t *element;
+ char *newstr = NULL;
+ const char *str;
+ const cfg_obj_t *obj;
+ controlkey_t *key;
+
+ for (element = cfg_list_first(keylist);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(obj);
+ newstr = isc_mem_strdup(mctx, str);
+ if (newstr == NULL)
+ goto cleanup;
+ key = isc_mem_get(mctx, sizeof(*key));
+ if (key == NULL)
+ goto cleanup;
+ key->keyname = newstr;
+ key->secret.base = NULL;
+ key->secret.length = 0;
+ ISC_LINK_INIT(key, link);
+ ISC_LIST_APPEND(*keyids, key, link);
+ newstr = NULL;
+ }
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (newstr != NULL)
+ isc_mem_free(mctx, newstr);
+ free_controlkeylist(keyids, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist,
+ controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext)
+{
+ controlkey_t *keyid, *next;
+ const cfg_obj_t *keydef;
+ char secret[1024];
+ isc_buffer_t b;
+ isc_result_t result;
+
+ /*
+ * Find the keys corresponding to the keyids used by this listener.
+ */
+ for (keyid = ISC_LIST_HEAD(*keyids); keyid != NULL; keyid = next) {
+ next = ISC_LIST_NEXT(keyid, link);
+
+ result = cfgkeylist_find(keylist, keyid->keyname, &keydef);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't find key '%s' for use with "
+ "command channel %s",
+ keyid->keyname, socktext);
+ ISC_LIST_UNLINK(*keyids, keyid, link);
+ free_controlkey(keyid, mctx);
+ } else {
+ const cfg_obj_t *algobj = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ const char *algstr = NULL;
+ const char *secretstr = NULL;
+
+ (void)cfg_map_get(keydef, "algorithm", &algobj);
+ (void)cfg_map_get(keydef, "secret", &secretobj);
+ INSIST(algobj != NULL && secretobj != NULL);
+
+ algstr = cfg_obj_asstring(algobj);
+ secretstr = cfg_obj_asstring(secretobj);
+
+ if (ns_config_getkeyalgorithm(algstr, NULL, NULL) !=
+ ISC_R_SUCCESS)
+ {
+ cfg_obj_log(control, ns_g_lctx,
+ ISC_LOG_WARNING,
+ "unsupported algorithm '%s' in "
+ "key '%s' for use with command "
+ "channel %s",
+ algstr, keyid->keyname, socktext);
+ ISC_LIST_UNLINK(*keyids, keyid, link);
+ free_controlkey(keyid, mctx);
+ continue;
+ }
+
+ isc_buffer_init(&b, secret, sizeof(secret));
+ result = isc_base64_decodestring(secretstr, &b);
+
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
+ "secret for key '%s' on "
+ "command channel %s: %s",
+ keyid->keyname, socktext,
+ isc_result_totext(result));
+ ISC_LIST_UNLINK(*keyids, keyid, link);
+ free_controlkey(keyid, mctx);
+ continue;
+ }
+
+ keyid->secret.length = isc_buffer_usedlength(&b);
+ keyid->secret.base = isc_mem_get(mctx,
+ keyid->secret.length);
+ if (keyid->secret.base == NULL) {
+ cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't register key '%s': "
+ "out of memory", keyid->keyname);
+ ISC_LIST_UNLINK(*keyids, keyid, link);
+ free_controlkey(keyid, mctx);
+ break;
+ }
+ memcpy(keyid->secret.base, isc_buffer_base(&b),
+ keyid->secret.length);
+ }
+ }
+}
+
+#define CHECK(x) \
+ do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto cleanup; \
+ } while (0)
+
+static isc_result_t
+get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) {
+ isc_result_t result;
+ cfg_parser_t *pctx = NULL;
+ cfg_obj_t *config = NULL;
+ const cfg_obj_t *key = NULL;
+ const cfg_obj_t *algobj = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ const char *algstr = NULL;
+ const char *secretstr = NULL;
+ controlkey_t *keyid = NULL;
+ char secret[1024];
+ isc_buffer_t b;
+
+ CHECK(cfg_parser_create(mctx, ns_g_lctx, &pctx));
+ CHECK(cfg_parse_file(pctx, ns_g_keyfile, &cfg_type_rndckey, &config));
+ CHECK(cfg_map_get(config, "key", &key));
+
+ keyid = isc_mem_get(mctx, sizeof(*keyid));
+ if (keyid == NULL)
+ CHECK(ISC_R_NOMEMORY);
+ keyid->keyname = isc_mem_strdup(mctx,
+ cfg_obj_asstring(cfg_map_getname(key)));
+ keyid->secret.base = NULL;
+ keyid->secret.length = 0;
+ ISC_LINK_INIT(keyid, link);
+ if (keyid->keyname == NULL)
+ CHECK(ISC_R_NOMEMORY);
+
+ CHECK(bind9_check_key(key, ns_g_lctx));
+
+ (void)cfg_map_get(key, "algorithm", &algobj);
+ (void)cfg_map_get(key, "secret", &secretobj);
+ INSIST(algobj != NULL && secretobj != NULL);
+
+ algstr = cfg_obj_asstring(algobj);
+ secretstr = cfg_obj_asstring(secretobj);
+
+ if (ns_config_getkeyalgorithm(algstr, NULL, NULL) != ISC_R_SUCCESS) {
+ cfg_obj_log(key, ns_g_lctx,
+ ISC_LOG_WARNING,
+ "unsupported algorithm '%s' in "
+ "key '%s' for use with command "
+ "channel",
+ algstr, keyid->keyname);
+ goto cleanup;
+ }
+
+ isc_buffer_init(&b, secret, sizeof(secret));
+ result = isc_base64_decodestring(secretstr, &b);
+
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
+ "secret for key '%s' on command channel: %s",
+ keyid->keyname, isc_result_totext(result));
+ CHECK(result);
+ }
+
+ keyid->secret.length = isc_buffer_usedlength(&b);
+ keyid->secret.base = isc_mem_get(mctx,
+ keyid->secret.length);
+ if (keyid->secret.base == NULL) {
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't register key '%s': "
+ "out of memory", keyid->keyname);
+ CHECK(ISC_R_NOMEMORY);
+ }
+ memcpy(keyid->secret.base, isc_buffer_base(&b),
+ keyid->secret.length);
+ ISC_LIST_APPEND(*keyids, keyid, link);
+ keyid = NULL;
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (keyid != NULL)
+ free_controlkey(keyid, mctx);
+ if (config != NULL)
+ cfg_obj_destroy(pctx, &config);
+ if (pctx != NULL)
+ cfg_parser_destroy(&pctx);
+ return (result);
+}
+
+/*
+ * Ensures that both '*global_keylistp' and '*control_keylistp' are
+ * valid or both are NULL.
+ */
+static void
+get_key_info(const cfg_obj_t *config, const cfg_obj_t *control,
+ const cfg_obj_t **global_keylistp,
+ const cfg_obj_t **control_keylistp)
+{
+ isc_result_t result;
+ const cfg_obj_t *control_keylist = NULL;
+ const cfg_obj_t *global_keylist = NULL;
+
+ REQUIRE(global_keylistp != NULL && *global_keylistp == NULL);
+ REQUIRE(control_keylistp != NULL && *control_keylistp == NULL);
+
+ control_keylist = cfg_tuple_get(control, "keys");
+
+ if (!cfg_obj_isvoid(control_keylist) &&
+ cfg_list_first(control_keylist) != NULL) {
+ result = cfg_map_get(config, "key", &global_keylist);
+
+ if (result == ISC_R_SUCCESS) {
+ *global_keylistp = global_keylist;
+ *control_keylistp = control_keylist;
+ }
+ }
+}
+
+static void
+update_listener(ns_controls_t *cp, controllistener_t **listenerp,
+ const cfg_obj_t *control, const cfg_obj_t *config,
+ isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
+ const char *socktext, isc_sockettype_t type)
+{
+ controllistener_t *listener;
+ const cfg_obj_t *allow;
+ const cfg_obj_t *global_keylist = NULL;
+ const cfg_obj_t *control_keylist = NULL;
+ dns_acl_t *new_acl = NULL;
+ controlkeylist_t keys;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ for (listener = ISC_LIST_HEAD(cp->listeners);
+ listener != NULL;
+ listener = ISC_LIST_NEXT(listener, link))
+ if (isc_sockaddr_equal(addr, &listener->address))
+ break;
+
+ if (listener == NULL) {
+ *listenerp = NULL;
+ return;
+ }
+
+ /*
+ * There is already a listener for this sockaddr.
+ * Update the access list and key information.
+ *
+ * First try to deal with the key situation. There are a few
+ * possibilities:
+ * (a) It had an explicit keylist and still has an explicit keylist.
+ * (b) It had an automagic key and now has an explicit keylist.
+ * (c) It had an explicit keylist and now needs an automagic key.
+ * (d) It has an automagic key and still needs the automagic key.
+ *
+ * (c) and (d) are the annoying ones. The caller needs to know
+ * that it should use the automagic configuration for key information
+ * in place of the named.conf configuration.
+ *
+ * XXXDCL There is one other hazard that has not been dealt with,
+ * the problem that if a key change is being caused by a control
+ * channel reload, then the response will be with the new key
+ * and not able to be decrypted by the client.
+ */
+ if (control != NULL)
+ get_key_info(config, control, &global_keylist,
+ &control_keylist);
+
+ if (control_keylist != NULL) {
+ INSIST(global_keylist != NULL);
+
+ ISC_LIST_INIT(keys);
+ result = controlkeylist_fromcfg(control_keylist,
+ listener->mctx, &keys);
+ if (result == ISC_R_SUCCESS) {
+ free_controlkeylist(&listener->keys, listener->mctx);
+ listener->keys = keys;
+ register_keys(control, global_keylist, &listener->keys,
+ listener->mctx, socktext);
+ }
+ } else {
+ free_controlkeylist(&listener->keys, listener->mctx);
+ result = get_rndckey(listener->mctx, &listener->keys);
+ }
+
+ if (result != ISC_R_SUCCESS && global_keylist != NULL) {
+ /*
+ * This message might be a little misleading since the
+ * "new keys" might in fact be identical to the old ones,
+ * but tracking whether they are identical just for the
+ * sake of avoiding this message would be too much trouble.
+ */
+ if (control != NULL)
+ cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't install new keys for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "couldn't install new keys for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ }
+
+ /*
+ * Now, keep the old access list unless a new one can be made.
+ */
+ if (control != NULL && type == isc_sockettype_tcp) {
+ allow = cfg_tuple_get(control, "allow");
+ result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
+ aclconfctx, listener->mctx, 0,
+ &new_acl);
+ } else {
+ result = dns_acl_any(listener->mctx, &new_acl);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ dns_acl_detach(&listener->acl);
+ dns_acl_attach(new_acl, &listener->acl);
+ dns_acl_detach(&new_acl);
+ /* XXXDCL say the old acl is still used? */
+ } else if (control != NULL)
+ cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't install new acl for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
+ "couldn't install new acl for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+
+ if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) {
+ isc_uint32_t perm, owner, group;
+ perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm"));
+ owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner"));
+ group = cfg_obj_asuint32(cfg_tuple_get(control, "group"));
+ result = ISC_R_SUCCESS;
+ if (listener->perm != perm || listener->owner != owner ||
+ listener->group != group)
+ result = isc_socket_permunix(&listener->address, perm,
+ owner, group);
+ if (result == ISC_R_SUCCESS) {
+ listener->perm = perm;
+ listener->owner = owner;
+ listener->group = group;
+ } else if (control != NULL)
+ cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't update ownership/permission for "
+ "command channel %s", socktext);
+ }
+
+ *listenerp = listener;
+}
+
+static void
+add_listener(ns_controls_t *cp, controllistener_t **listenerp,
+ const cfg_obj_t *control, const cfg_obj_t *config,
+ isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
+ const char *socktext, isc_sockettype_t type)
+{
+ isc_mem_t *mctx = cp->server->mctx;
+ controllistener_t *listener;
+ const cfg_obj_t *allow;
+ const cfg_obj_t *global_keylist = NULL;
+ const cfg_obj_t *control_keylist = NULL;
+ dns_acl_t *new_acl = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ listener = isc_mem_get(mctx, sizeof(*listener));
+ if (listener == NULL)
+ result = ISC_R_NOMEMORY;
+
+ if (result == ISC_R_SUCCESS) {
+ listener->controls = cp;
+ listener->mctx = mctx;
+ listener->task = cp->server->task;
+ listener->address = *addr;
+ listener->sock = NULL;
+ listener->listening = ISC_FALSE;
+ listener->exiting = ISC_FALSE;
+ listener->acl = NULL;
+ listener->type = type;
+ listener->perm = 0;
+ listener->owner = 0;
+ listener->group = 0;
+ ISC_LINK_INIT(listener, link);
+ ISC_LIST_INIT(listener->keys);
+ ISC_LIST_INIT(listener->connections);
+
+ /*
+ * Make the acl.
+ */
+ if (control != NULL && type == isc_sockettype_tcp) {
+ allow = cfg_tuple_get(control, "allow");
+ result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
+ aclconfctx, mctx, 0,
+ &new_acl);
+ } else {
+ result = dns_acl_any(mctx, &new_acl);
+ }
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ dns_acl_attach(new_acl, &listener->acl);
+ dns_acl_detach(&new_acl);
+
+ if (config != NULL)
+ get_key_info(config, control, &global_keylist,
+ &control_keylist);
+
+ if (control_keylist != NULL) {
+ result = controlkeylist_fromcfg(control_keylist,
+ listener->mctx,
+ &listener->keys);
+ if (result == ISC_R_SUCCESS)
+ register_keys(control, global_keylist,
+ &listener->keys,
+ listener->mctx, socktext);
+ } else
+ result = get_rndckey(mctx, &listener->keys);
+
+ if (result != ISC_R_SUCCESS && control != NULL)
+ cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't install keys for "
+ "command channel %s: %s",
+ socktext, isc_result_totext(result));
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ int pf = isc_sockaddr_pf(&listener->address);
+ if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ (pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) ||
+#endif
+ (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
+ result = ISC_R_FAMILYNOSUPPORT;
+ }
+
+ if (result == ISC_R_SUCCESS && type == isc_sockettype_unix)
+ isc_socket_cleanunix(&listener->address, ISC_FALSE);
+
+ if (result == ISC_R_SUCCESS)
+ result = isc_socket_create(ns_g_socketmgr,
+ isc_sockaddr_pf(&listener->address),
+ type, &listener->sock);
+ if (result == ISC_R_SUCCESS)
+ isc_socket_setname(listener->sock, "control", NULL);
+
+ if (result == ISC_R_SUCCESS)
+ result = isc_socket_bind(listener->sock, &listener->address,
+ ISC_SOCKET_REUSEADDRESS);
+
+ if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) {
+ listener->perm = cfg_obj_asuint32(cfg_tuple_get(control,
+ "perm"));
+ listener->owner = cfg_obj_asuint32(cfg_tuple_get(control,
+ "owner"));
+ listener->group = cfg_obj_asuint32(cfg_tuple_get(control,
+ "group"));
+ result = isc_socket_permunix(&listener->address, listener->perm,
+ listener->owner, listener->group);
+ }
+ if (result == ISC_R_SUCCESS)
+ result = control_listen(listener);
+
+ if (result == ISC_R_SUCCESS)
+ result = control_accept(listener);
+
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
+ "command channel listening on %s", socktext);
+ *listenerp = listener;
+
+ } else {
+ if (listener != NULL) {
+ listener->exiting = ISC_TRUE;
+ free_listener(listener);
+ }
+
+ if (control != NULL)
+ cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't add command channel %s: %s",
+ socktext, isc_result_totext(result));
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE,
+ "couldn't add command channel %s: %s",
+ socktext, isc_result_totext(result));
+
+ *listenerp = NULL;
+ }
+
+ /* XXXDCL return error results? fail hard? */
+}
+
+isc_result_t
+ns_controls_configure(ns_controls_t *cp, const cfg_obj_t *config,
+ cfg_aclconfctx_t *aclconfctx)
+{
+ controllistener_t *listener;
+ controllistenerlist_t new_listeners;
+ const cfg_obj_t *controlslist = NULL;
+ const cfg_listelt_t *element, *element2;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ ISC_LIST_INIT(new_listeners);
+
+ /*
+ * Get the list of named.conf 'controls' statements.
+ */
+ (void)cfg_map_get(config, "controls", &controlslist);
+
+ /*
+ * Run through the new control channel list, noting sockets that
+ * are already being listened on and moving them to the new list.
+ *
+ * Identifying duplicate addr/port combinations is left to either
+ * the underlying config code, or to the bind attempt getting an
+ * address-in-use error.
+ */
+ if (controlslist != NULL) {
+ for (element = cfg_list_first(controlslist);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ const cfg_obj_t *controls;
+ const cfg_obj_t *inetcontrols = NULL;
+
+ controls = cfg_listelt_value(element);
+ (void)cfg_map_get(controls, "inet", &inetcontrols);
+ if (inetcontrols == NULL)
+ continue;
+
+ for (element2 = cfg_list_first(inetcontrols);
+ element2 != NULL;
+ element2 = cfg_list_next(element2)) {
+ const cfg_obj_t *control;
+ const cfg_obj_t *obj;
+ isc_sockaddr_t addr;
+
+ /*
+ * The parser handles BIND 8 configuration file
+ * syntax, so it allows unix phrases as well
+ * inet phrases with no keys{} clause.
+ */
+ control = cfg_listelt_value(element2);
+
+ obj = cfg_tuple_get(control, "address");
+ addr = *cfg_obj_assockaddr(obj);
+ if (isc_sockaddr_getport(&addr) == 0)
+ isc_sockaddr_setport(&addr,
+ NS_CONTROL_PORT);
+
+ isc_sockaddr_format(&addr, socktext,
+ sizeof(socktext));
+
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL,
+ ISC_LOG_DEBUG(9),
+ "processing control channel %s",
+ socktext);
+
+ update_listener(cp, &listener, control, config,
+ &addr, aclconfctx, socktext,
+ isc_sockettype_tcp);
+
+ if (listener != NULL)
+ /*
+ * Remove the listener from the old
+ * list, so it won't be shut down.
+ */
+ ISC_LIST_UNLINK(cp->listeners,
+ listener, link);
+ else
+ /*
+ * This is a new listener.
+ */
+ add_listener(cp, &listener, control,
+ config, &addr, aclconfctx,
+ socktext,
+ isc_sockettype_tcp);
+
+ if (listener != NULL)
+ ISC_LIST_APPEND(new_listeners,
+ listener, link);
+ }
+ }
+ for (element = cfg_list_first(controlslist);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ const cfg_obj_t *controls;
+ const cfg_obj_t *unixcontrols = NULL;
+
+ controls = cfg_listelt_value(element);
+ (void)cfg_map_get(controls, "unix", &unixcontrols);
+ if (unixcontrols == NULL)
+ continue;
+
+ for (element2 = cfg_list_first(unixcontrols);
+ element2 != NULL;
+ element2 = cfg_list_next(element2)) {
+ const cfg_obj_t *control;
+ const cfg_obj_t *path;
+ isc_sockaddr_t addr;
+ isc_result_t result;
+
+ /*
+ * The parser handles BIND 8 configuration file
+ * syntax, so it allows unix phrases as well
+ * inet phrases with no keys{} clause.
+ */
+ control = cfg_listelt_value(element2);
+
+ path = cfg_tuple_get(control, "path");
+ result = isc_sockaddr_frompath(&addr,
+ cfg_obj_asstring(path));
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL,
+ ISC_LOG_DEBUG(9),
+ "control channel '%s': %s",
+ cfg_obj_asstring(path),
+ isc_result_totext(result));
+ continue;
+ }
+
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_CONTROL,
+ ISC_LOG_DEBUG(9),
+ "processing control channel '%s'",
+ cfg_obj_asstring(path));
+
+ update_listener(cp, &listener, control, config,
+ &addr, aclconfctx,
+ cfg_obj_asstring(path),
+ isc_sockettype_unix);
+
+ if (listener != NULL)
+ /*
+ * Remove the listener from the old
+ * list, so it won't be shut down.
+ */
+ ISC_LIST_UNLINK(cp->listeners,
+ listener, link);
+ else
+ /*
+ * This is a new listener.
+ */
+ add_listener(cp, &listener, control,
+ config, &addr, aclconfctx,
+ cfg_obj_asstring(path),
+ isc_sockettype_unix);
+
+ if (listener != NULL)
+ ISC_LIST_APPEND(new_listeners,
+ listener, link);
+ }
+ }
+ } else {
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ isc_sockaddr_t addr;
+
+ if (i == 0) {
+ struct in_addr localhost;
+
+ if (isc_net_probeipv4() != ISC_R_SUCCESS)
+ continue;
+ localhost.s_addr = htonl(INADDR_LOOPBACK);
+ isc_sockaddr_fromin(&addr, &localhost, 0);
+ } else {
+ if (isc_net_probeipv6() != ISC_R_SUCCESS)
+ continue;
+ isc_sockaddr_fromin6(&addr,
+ &in6addr_loopback, 0);
+ }
+ isc_sockaddr_setport(&addr, NS_CONTROL_PORT);
+
+ isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+
+ update_listener(cp, &listener, NULL, NULL,
+ &addr, NULL, socktext,
+ isc_sockettype_tcp);
+
+ if (listener != NULL)
+ /*
+ * Remove the listener from the old
+ * list, so it won't be shut down.
+ */
+ ISC_LIST_UNLINK(cp->listeners,
+ listener, link);
+ else
+ /*
+ * This is a new listener.
+ */
+ add_listener(cp, &listener, NULL, NULL,
+ &addr, NULL, socktext,
+ isc_sockettype_tcp);
+
+ if (listener != NULL)
+ ISC_LIST_APPEND(new_listeners,
+ listener, link);
+ }
+ }
+
+ /*
+ * ns_control_shutdown() will stop whatever is on the global
+ * listeners list, which currently only has whatever sockaddrs
+ * were in the previous configuration (if any) that do not
+ * remain in the current configuration.
+ */
+ controls_shutdown(cp);
+
+ /*
+ * Put all of the valid listeners on the listeners list.
+ * Anything already on listeners in the process of shutting
+ * down will be taken care of by listen_done().
+ */
+ ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp) {
+ isc_mem_t *mctx = server->mctx;
+ isc_result_t result;
+ ns_controls_t *controls = isc_mem_get(mctx, sizeof(*controls));
+
+ if (controls == NULL)
+ return (ISC_R_NOMEMORY);
+ controls->server = server;
+ ISC_LIST_INIT(controls->listeners);
+ controls->shuttingdown = ISC_FALSE;
+ controls->symtab = NULL;
+ result = isccc_cc_createsymtab(&controls->symtab);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(server->mctx, controls, sizeof(*controls));
+ return (result);
+ }
+ *ctrlsp = controls;
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_controls_destroy(ns_controls_t **ctrlsp) {
+ ns_controls_t *controls = *ctrlsp;
+
+ REQUIRE(ISC_LIST_EMPTY(controls->listeners));
+
+ isccc_symtab_destroy(&controls->symtab);
+ isc_mem_put(controls->server->mctx, controls, sizeof(*controls));
+ *ctrlsp = NULL;
+}
diff --git a/bin/named/convertxsl.pl b/bin/named/convertxsl.pl
new file mode 100755
index 0000000..87550b3
--- /dev/null
+++ b/bin/named/convertxsl.pl
@@ -0,0 +1,57 @@
+#!/usr/bin/env perl
+#
+# Copyright (C) 2006-2008 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: convertxsl.pl,v 1.14 2008/07/17 23:43:26 jinmei Exp $
+
+use strict;
+use warnings;
+
+my $rev = '$Id: convertxsl.pl,v 1.14 2008/07/17 23:43:26 jinmei Exp $';
+$rev =~ s/\$//g;
+$rev =~ s/,v//g;
+$rev =~ s/Id: //;
+
+my $xsl = "unknown";
+my $lines = '';
+
+while (<>) {
+ chomp;
+ # pickout the id for comment.
+ $xsl = $_ if (/<!-- .Id:.* -->/);
+ # convert Id string to a form not recognisable by cvs.
+ $_ =~ s/<!-- .Id:(.*). -->/<!-- \\045Id: $1\\045 -->/;
+ s/[\ \t]+/ /g;
+ s/\>\ \</\>\</g;
+ s/\"/\\\"/g;
+ s/^/\t\"/;
+ s/$/\\n\"/;
+ if ($lines eq "") {
+ $lines .= $_;
+ } else {
+ $lines .= "\n" . $_;
+ }
+}
+
+$xsl =~ s/\$//g;
+$xsl =~ s/<!-- Id: //;
+$xsl =~ s/ -->.*//;
+$xsl =~ s/,v//;
+
+print "/*\n * Generated by $rev \n * From $xsl\n */\n";
+print 'static char xslmsg[] =',"\n";
+print $lines;
+
+print ';', "\n";
diff --git a/bin/named/include/named/builtin.h b/bin/named/include/named/builtin.h
new file mode 100644
index 0000000..a5185ba
--- /dev/null
+++ b/bin/named/include/named/builtin.h
@@ -0,0 +1,31 @@
+/*
+ * 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: builtin.h,v 1.6 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_BUILTIN_H
+#define NAMED_BUILTIN_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+
+isc_result_t ns_builtin_init(void);
+
+void ns_builtin_deinit(void);
+
+#endif /* NAMED_BUILTIN_H */
diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h
new file mode 100644
index 0000000..b4be639
--- /dev/null
+++ b/bin/named/include/named/client.h
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2004-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
+ * 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.86 2008/04/03 02:01:08 marka Exp $ */
+
+#ifndef NAMED_CLIENT_H
+#define NAMED_CLIENT_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * This module defines two objects, ns_client_t and ns_clientmgr_t.
+ *
+ * An ns_client_t object handles incoming DNS requests from clients
+ * on a given network interface.
+ *
+ * Each ns_client_t object can handle only one TCP connection or UDP
+ * request at a time. Therefore, several ns_client_t objects are
+ * typically created to serve each network interface, e.g., one
+ * for handling TCP requests and a few (one per CPU) for handling
+ * UDP requests.
+ *
+ * Incoming requests are classified as queries, zone transfer
+ * requests, update requests, notify requests, etc, and handed off
+ * to the appropriate request handler. When the request has been
+ * fully handled (which can be much later), the ns_client_t must be
+ * notified of this by calling one of the following functions
+ * exactly once in the context of its task:
+ * \code
+ * ns_client_send() (sending a non-error response)
+ * ns_client_sendraw() (sending a raw response)
+ * ns_client_error() (sending an error response)
+ * ns_client_next() (sending no response)
+ *\endcode
+ * This will release any resources used by the request and
+ * and allow the ns_client_t to listen for the next request.
+ *
+ * A ns_clientmgr_t manages a number of ns_client_t objects.
+ * New ns_client_t objects are created by calling
+ * ns_clientmgr_createclients(). They are destroyed by
+ * destroying their manager.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/buffer.h>
+#include <isc/magic.h>
+#include <isc/stdtime.h>
+#include <isc/quota.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/tcpmsg.h>
+#include <dns/types.h>
+
+#include <named/types.h>
+#include <named/query.h>
+
+/***
+ *** Types
+ ***/
+
+typedef ISC_LIST(ns_client_t) client_list_t;
+
+/*% nameserver client structure */
+struct ns_client {
+ unsigned int magic;
+ isc_mem_t * mctx;
+ ns_clientmgr_t * manager;
+ int state;
+ int newstate;
+ int naccepts;
+ int nreads;
+ int nsends;
+ int nrecvs;
+ int nupdates;
+ int nctls;
+ int references;
+ isc_boolean_t needshutdown; /*
+ * Used by clienttest to get
+ * the client to go from
+ * inactive to free state
+ * by shutting down the
+ * client's task.
+ */
+ unsigned int attributes;
+ isc_task_t * task;
+ dns_view_t * view;
+ dns_dispatch_t * dispatch;
+ isc_socket_t * udpsocket;
+ isc_socket_t * tcplistener;
+ isc_socket_t * tcpsocket;
+ unsigned char * tcpbuf;
+ dns_tcpmsg_t tcpmsg;
+ isc_boolean_t tcpmsg_valid;
+ isc_timer_t * timer;
+ isc_boolean_t timerset;
+ dns_message_t * message;
+ isc_socketevent_t * sendevent;
+ isc_socketevent_t * recvevent;
+ unsigned char * recvbuf;
+ dns_rdataset_t * opt;
+ isc_uint16_t udpsize;
+ isc_uint16_t extflags;
+ isc_int16_t ednsversion; /* -1 noedns */
+ void (*next)(ns_client_t *);
+ void (*shutdown)(void *arg, isc_result_t result);
+ void *shutdown_arg;
+ ns_query_t query;
+ isc_stdtime_t requesttime;
+ isc_stdtime_t now;
+ dns_name_t signername; /*%< [T]SIG key name */
+ dns_name_t * signer; /*%< NULL if not valid sig */
+ isc_boolean_t mortal; /*%< Die after handling request */
+ isc_quota_t *tcpquota;
+ isc_quota_t *recursionquota;
+ ns_interface_t *interface;
+ isc_sockaddr_t peeraddr;
+ isc_boolean_t peeraddr_valid;
+ struct in6_pktinfo pktinfo;
+ isc_event_t ctlevent;
+ /*%
+ * Information about recent FORMERR response(s), for
+ * FORMERR loop avoidance. This is separate for each
+ * client object rather than global only to avoid
+ * the need for locking.
+ */
+ struct {
+ isc_sockaddr_t addr;
+ isc_stdtime_t time;
+ dns_messageid_t id;
+ } formerrcache;
+ ISC_LINK(ns_client_t) link;
+ /*%
+ * The list 'link' is part of, or NULL if not on any list.
+ */
+ client_list_t *list;
+};
+
+#define NS_CLIENT_MAGIC ISC_MAGIC('N','S','C','c')
+#define NS_CLIENT_VALID(c) ISC_MAGIC_VALID(c, NS_CLIENT_MAGIC)
+
+#define NS_CLIENTATTR_TCP 0x01
+#define NS_CLIENTATTR_RA 0x02 /*%< Client gets recusive service */
+#define NS_CLIENTATTR_PKTINFO 0x04 /*%< pktinfo is valid */
+#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 */
+
+extern unsigned int ns_client_requests;
+
+/***
+ *** Functions
+ ***/
+
+/*%
+ * Note! These ns_client_ routines MUST be called ONLY from the client's
+ * task in order to ensure synchronization.
+ */
+
+void
+ns_client_send(ns_client_t *client);
+/*%
+ * Finish processing the current client request and
+ * send client->message as a response.
+ * \brief
+ * Note! These ns_client_ routines MUST be called ONLY from the client's
+ * task in order to ensure synchronization.
+ */
+
+void
+ns_client_sendraw(ns_client_t *client, dns_message_t *msg);
+/*%
+ * Finish processing the current client request and
+ * send msg as a response using client->message->id for the id.
+ */
+
+void
+ns_client_error(ns_client_t *client, isc_result_t result);
+/*%
+ * Finish processing the current client request and return
+ * an error response to the client. The error response
+ * will have an RCODE determined by 'result'.
+ */
+
+void
+ns_client_next(ns_client_t *client, isc_result_t result);
+/*%
+ * Finish processing the current client request,
+ * return no response to the client.
+ */
+
+isc_boolean_t
+ns_client_shuttingdown(ns_client_t *client);
+/*%
+ * Return ISC_TRUE iff the client is currently shutting down.
+ */
+
+void
+ns_client_attach(ns_client_t *source, ns_client_t **target);
+/*%
+ * Attach '*targetp' to 'source'.
+ */
+
+void
+ns_client_detach(ns_client_t **clientp);
+/*%
+ * Detach '*clientp' from its client.
+ */
+
+isc_result_t
+ns_client_replace(ns_client_t *client);
+/*%
+ * Try to replace the current client with a new one, so that the
+ * current one can go off and do some lengthy work without
+ * leaving the dispatch/socket without service.
+ */
+
+void
+ns_client_settimeout(ns_client_t *client, unsigned int seconds);
+/*%
+ * Set a timer in the client to go off in the specified amount of time.
+ */
+
+isc_result_t
+ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
+ isc_timermgr_t *timermgr, ns_clientmgr_t **managerp);
+/*%
+ * Create a client manager.
+ */
+
+void
+ns_clientmgr_destroy(ns_clientmgr_t **managerp);
+/*%
+ * Destroy a client manager and all ns_client_t objects
+ * managed by it.
+ */
+
+isc_result_t
+ns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,
+ ns_interface_t *ifp, isc_boolean_t tcp);
+/*%
+ * Create up to 'n' clients listening on interface 'ifp'.
+ * If 'tcp' is ISC_TRUE, the clients will listen for TCP connections,
+ * otherwise for UDP requests.
+ */
+
+isc_sockaddr_t *
+ns_client_getsockaddr(ns_client_t *client);
+/*%
+ * Get the socket address of the client whose request is
+ * currently being processed.
+ */
+
+isc_result_t
+ns_client_checkaclsilent(ns_client_t *client,
+ isc_sockaddr_t *sockaddr,
+ dns_acl_t *acl,
+ isc_boolean_t default_allow);
+
+/*%
+ * Convenience function for client request ACL checking.
+ *
+ * Check the current client request against 'acl'. If 'acl'
+ * is NULL, allow the request iff 'default_allow' is ISC_TRUE.
+ * If netaddr is NULL, check the ACL against client->peeraddr;
+ * otherwise check it against netaddr.
+ *
+ * Notes:
+ *\li This is appropriate for checking allow-update,
+ * allow-query, allow-transfer, etc. It is not appropriate
+ * for checking the blackhole list because we treat positive
+ * matches as "allow" and negative matches as "deny"; in
+ * the case of the blackhole list this would be backwards.
+ *
+ * Requires:
+ *\li 'client' points to a valid client.
+ *\li 'sockaddr' 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 No other return values are possible.
+ */
+
+isc_result_t
+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);
+/*%
+ * Like ns_client_checkaclsilent, except the outcome of the check is
+ * logged at log level 'log_level' if denied, and at debug 3 if approved.
+ * Log messages will refer to the request as an 'opname' request.
+ *
+ * Requires:
+ *\li 'client' points to a valid client.
+ *\li 'sockaddr' points to a valid address, or is NULL.
+ *\li 'acl' points to a valid ACL, or is NULL.
+ *\li 'opname' points to a null-terminated string.
+ */
+
+void
+ns_client_log(ns_client_t *client, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
+
+void
+ns_client_logv(ns_client_t *client, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *fmt, va_list ap) ISC_FORMAT_PRINTF(5, 0);
+
+void
+ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
+ dns_rdataclass_t rdclass, char *buf, size_t len);
+
+#define NS_CLIENT_ACLMSGSIZE(x) \
+ (DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE + \
+ DNS_RDATACLASS_FORMATSIZE + sizeof(x) + sizeof("'/'"))
+
+void
+ns_client_recursing(ns_client_t *client);
+/*%
+ * Add client to end of th recursing list.
+ */
+
+void
+ns_client_killoldestquery(ns_client_t *client);
+/*%
+ * Kill the oldest recursive query (recursing list head).
+ */
+
+void
+ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager);
+/*%
+ * Dump the outstanding recursive queries to 'f'.
+ */
+
+void
+ns_client_qnamereplace(ns_client_t *client, dns_name_t *name);
+/*%
+ * Replace the qname.
+ */
+
+isc_boolean_t
+ns_client_isself(dns_view_t *myview, dns_tsigkey_t *mykey,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ dns_rdataclass_t rdclass, void *arg);
+/*%
+ * Isself callback.
+ */
+
+#endif /* NAMED_CLIENT_H */
diff --git a/bin/named/include/named/config.h b/bin/named/include/named/config.h
new file mode 100644
index 0000000..f7ceed8
--- /dev/null
+++ b/bin/named/include/named/config.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002 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: config.h,v 1.14 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_CONFIG_H
+#define NAMED_CONFIG_H 1
+
+/*! \file */
+
+#include <isccfg/cfg.h>
+
+#include <dns/types.h>
+#include <dns/zone.h>
+
+isc_result_t
+ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf);
+
+isc_result_t
+ns_config_get(const cfg_obj_t **maps, const char* name, const cfg_obj_t **obj);
+
+isc_result_t
+ns_checknames_get(const cfg_obj_t **maps, const char* name,
+ const cfg_obj_t **obj);
+
+int
+ns_config_listcount(const cfg_obj_t *list);
+
+isc_result_t
+ns_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
+ dns_rdataclass_t *classp);
+
+isc_result_t
+ns_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype,
+ dns_rdatatype_t *typep);
+
+dns_zonetype_t
+ns_config_getzonetype(const cfg_obj_t *zonetypeobj);
+
+isc_result_t
+ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
+ in_port_t defport, isc_mem_t *mctx,
+ isc_sockaddr_t **addrsp, isc_uint32_t *countp);
+
+void
+ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
+ isc_uint32_t count);
+
+isc_result_t
+ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
+ isc_mem_t *mctx, isc_sockaddr_t **addrsp,
+ dns_name_t ***keys, isc_uint32_t *countp);
+
+void
+ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
+ dns_name_t ***keys, isc_uint32_t count);
+
+isc_result_t
+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);
+
+#endif /* NAMED_CONFIG_H */
diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h
new file mode 100644
index 0000000..d382ffe
--- /dev/null
+++ b/bin/named/include/named/control.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2004-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: control.h,v 1.25 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_CONTROL_H
+#define NAMED_CONTROL_H 1
+
+/*! \file
+ * \brief
+ * The name server command channel.
+ */
+
+#include <isccc/types.h>
+
+#include <isccfg/aclconf.h>
+
+#include <named/types.h>
+
+#define NS_CONTROL_PORT 953
+
+#define NS_COMMAND_STOP "stop"
+#define NS_COMMAND_HALT "halt"
+#define NS_COMMAND_RELOAD "reload"
+#define NS_COMMAND_RECONFIG "reconfig"
+#define NS_COMMAND_REFRESH "refresh"
+#define NS_COMMAND_RETRANSFER "retransfer"
+#define NS_COMMAND_DUMPSTATS "stats"
+#define NS_COMMAND_QUERYLOG "querylog"
+#define NS_COMMAND_DUMPDB "dumpdb"
+#define NS_COMMAND_TRACE "trace"
+#define NS_COMMAND_NOTRACE "notrace"
+#define NS_COMMAND_FLUSH "flush"
+#define NS_COMMAND_FLUSHNAME "flushname"
+#define NS_COMMAND_STATUS "status"
+#define NS_COMMAND_TSIGLIST "tsig-list"
+#define NS_COMMAND_TSIGDELETE "tsig-delete"
+#define NS_COMMAND_FREEZE "freeze"
+#define NS_COMMAND_UNFREEZE "unfreeze"
+#define NS_COMMAND_THAW "thaw"
+#define NS_COMMAND_TIMERPOKE "timerpoke"
+#define NS_COMMAND_RECURSING "recursing"
+#define NS_COMMAND_NULL "null"
+#define NS_COMMAND_NOTIFY "notify"
+#define NS_COMMAND_VALIDATION "validation"
+
+isc_result_t
+ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp);
+/*%<
+ * Create an initial, empty set of command channels for 'server'.
+ */
+
+void
+ns_controls_destroy(ns_controls_t **ctrlsp);
+/*%<
+ * Destroy a set of command channels.
+ *
+ * Requires:
+ * Shutdown of the channels has completed.
+ */
+
+isc_result_t
+ns_controls_configure(ns_controls_t *controls, const cfg_obj_t *config,
+ cfg_aclconfctx_t *aclconfctx);
+/*%<
+ * Configure zero or more command channels into 'controls'
+ * as defined in the configuration parse tree 'config'.
+ * The channels will evaluate ACLs in the context of
+ * 'aclconfctx'.
+ */
+
+void
+ns_controls_shutdown(ns_controls_t *controls);
+/*%<
+ * Initiate shutdown of all the command channels in 'controls'.
+ */
+
+isc_result_t
+ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text);
+
+#endif /* NAMED_CONTROL_H */
diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h
new file mode 100644
index 0000000..6040dc3
--- /dev/null
+++ b/bin/named/include/named/globals.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: globals.h,v 1.80 2008/11/16 22:49:18 marka Exp $ */
+
+#ifndef NAMED_GLOBALS_H
+#define NAMED_GLOBALS_H 1
+
+/*! \file */
+
+#include <isc/rwlock.h>
+#include <isc/log.h>
+#include <isc/net.h>
+
+#include <isccfg/cfg.h>
+
+#include <dns/zone.h>
+
+#include <named/types.h>
+
+#undef EXTERN
+#undef INIT
+#ifdef NS_MAIN
+#define EXTERN
+#define INIT(v) = (v)
+#else
+#define EXTERN extern
+#define INIT(v)
+#endif
+
+#ifndef NS_RUN_PID_DIR
+#define NS_RUN_PID_DIR 1
+#endif
+
+EXTERN isc_mem_t * ns_g_mctx INIT(NULL);
+EXTERN unsigned int ns_g_cpus INIT(0);
+EXTERN isc_taskmgr_t * ns_g_taskmgr INIT(NULL);
+EXTERN dns_dispatchmgr_t * ns_g_dispatchmgr INIT(NULL);
+EXTERN isc_entropy_t * ns_g_entropy INIT(NULL);
+EXTERN isc_entropy_t * ns_g_fallbackentropy INIT(NULL);
+EXTERN unsigned int ns_g_cpus_detected INIT(1);
+
+/*
+ * XXXRTH We're going to want multiple timer managers eventually. One
+ * for really short timers, another for client timers, and one
+ * for zone timers.
+ */
+EXTERN isc_timermgr_t * ns_g_timermgr INIT(NULL);
+EXTERN isc_socketmgr_t * ns_g_socketmgr INIT(NULL);
+EXTERN cfg_parser_t * ns_g_parser INIT(NULL);
+EXTERN const char * ns_g_version INIT(VERSION);
+EXTERN const char * ns_g_configargs INIT(CONFIGARGS);
+EXTERN in_port_t ns_g_port INIT(0);
+EXTERN in_port_t lwresd_g_listenport INIT(0);
+
+EXTERN ns_server_t * ns_g_server INIT(NULL);
+
+EXTERN isc_boolean_t ns_g_lwresdonly INIT(ISC_FALSE);
+
+/*
+ * Logging.
+ */
+EXTERN isc_log_t * ns_g_lctx INIT(NULL);
+EXTERN isc_logcategory_t * ns_g_categories INIT(NULL);
+EXTERN isc_logmodule_t * ns_g_modules INIT(NULL);
+EXTERN unsigned int ns_g_debuglevel INIT(0);
+
+/*
+ * Current configuration information.
+ */
+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 const char * ns_g_keyfile INIT(NS_SYSCONFDIR
+ "/rndc.key");
+EXTERN const char * lwresd_g_conffile INIT(NS_SYSCONFDIR
+ "/lwresd.conf");
+EXTERN const char * lwresd_g_resolvconffile INIT("/etc"
+ "/resolv.conf");
+EXTERN isc_boolean_t ns_g_conffileset INIT(ISC_FALSE);
+EXTERN isc_boolean_t lwresd_g_useresolvconf INIT(ISC_FALSE);
+EXTERN isc_uint16_t ns_g_udpsize INIT(4096);
+
+/*
+ * Initial resource limits.
+ */
+EXTERN isc_resourcevalue_t ns_g_initstacksize INIT(0);
+EXTERN isc_resourcevalue_t ns_g_initdatasize INIT(0);
+EXTERN isc_resourcevalue_t ns_g_initcoresize INIT(0);
+EXTERN isc_resourcevalue_t ns_g_initopenfiles INIT(0);
+
+/*
+ * Misc.
+ */
+EXTERN isc_boolean_t ns_g_coreok INIT(ISC_TRUE);
+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);
+
+#if NS_RUN_PID_DIR
+EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR
+ "/run/named/"
+ "named.pid");
+EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR
+ "/run/lwresd/"
+ "lwresd.pid");
+#else
+EXTERN const char * ns_g_defaultpidfile INIT(NS_LOCALSTATEDIR
+ "/run/named.pid");
+EXTERN const char * lwresd_g_defaultpidfile INIT(NS_LOCALSTATEDIR
+ "/run/lwresd.pid");
+#endif
+
+EXTERN const char * ns_g_username INIT(NULL);
+
+EXTERN int ns_g_listen INIT(3);
+EXTERN isc_time_t ns_g_boottime;
+EXTERN isc_boolean_t ns_g_memstatistics INIT(ISC_FALSE);
+EXTERN isc_boolean_t ns_g_clienttest INIT(ISC_FALSE);
+
+#undef EXTERN
+#undef INIT
+
+#endif /* NAMED_GLOBALS_H */
diff --git a/bin/named/include/named/interfacemgr.h b/bin/named/include/named/interfacemgr.h
new file mode 100644
index 0000000..2724c39
--- /dev/null
+++ b/bin/named/include/named/interfacemgr.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: interfacemgr.h,v 1.33 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_INTERFACEMGR_H
+#define NAMED_INTERFACEMGR_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * The interface manager monitors the operating system's list
+ * of network interfaces, creating and destroying listeners
+ * as needed.
+ *
+ * Reliability:
+ *\li No impact expected.
+ *
+ * Resources:
+ *
+ * Security:
+ * \li The server will only be able to bind to the DNS port on
+ * newly discovered interfaces if it is running as root.
+ *
+ * Standards:
+ *\li The API for scanning varies greatly among operating systems.
+ * This module attempts to hide the differences.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/socket.h>
+
+#include <dns/result.h>
+
+#include <named/listenlist.h>
+#include <named/types.h>
+
+/***
+ *** Types
+ ***/
+
+#define IFACE_MAGIC ISC_MAGIC('I',':','-',')')
+#define NS_INTERFACE_VALID(t) ISC_MAGIC_VALID(t, IFACE_MAGIC)
+
+#define NS_INTERFACEFLAG_ANYADDR 0x01U /*%< bound to "any" address */
+
+/*% The nameserver interface structure */
+struct ns_interface {
+ unsigned int magic; /*%< Magic number. */
+ ns_interfacemgr_t * mgr; /*%< Interface manager. */
+ isc_mutex_t lock;
+ int references; /*%< Locked */
+ unsigned int generation; /*%< Generation number. */
+ isc_sockaddr_t addr; /*%< Address and port. */
+ unsigned int flags; /*%< Interface characteristics */
+ char name[32]; /*%< Null terminated. */
+ dns_dispatch_t * udpdispatch; /*%< UDP dispatcher. */
+ isc_socket_t * tcpsocket; /*%< TCP socket. */
+ int ntcptarget; /*%< Desired number of concurrent
+ TCP accepts */
+ int ntcpcurrent; /*%< Current ditto, locked */
+ ns_clientmgr_t * clientmgr; /*%< Client manager. */
+ ISC_LINK(ns_interface_t) link;
+};
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
+ isc_socketmgr_t *socketmgr,
+ dns_dispatchmgr_t *dispatchmgr,
+ ns_interfacemgr_t **mgrp);
+/*%
+ * Create a new interface manager.
+ *
+ * Initially, the new manager will not listen on any interfaces.
+ * Call ns_interfacemgr_setlistenon() and/or ns_interfacemgr_setlistenon6()
+ * to set nonempty listen-on lists.
+ */
+
+void
+ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target);
+
+void
+ns_interfacemgr_detach(ns_interfacemgr_t **targetp);
+
+void
+ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr);
+
+void
+ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose);
+/*%
+ * Scan the operatings system's list of network interfaces
+ * and create listeners when new interfaces are discovered.
+ * Shut down the sockets for interfaces that go away.
+ *
+ * This should be called once on server startup and then
+ * periodically according to the 'interface-interval' option
+ * in named.conf.
+ */
+
+void
+ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
+ isc_boolean_t verbose);
+/*%
+ * Similar to ns_interfacemgr_scan(), but this function also tries to see the
+ * need for an explicit listen-on when a list element in 'list' is going to
+ * override an already-listening a wildcard interface.
+ *
+ * This function does not update localhost and localnets ACLs.
+ *
+ * This should be called once on server startup, after configuring views and
+ * zones.
+ */
+
+void
+ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value);
+/*%
+ * Set the IPv4 "listen-on" list of 'mgr' to 'value'.
+ * The previous IPv4 listen-on list is freed.
+ */
+
+void
+ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value);
+/*%
+ * Set the IPv6 "listen-on" list of 'mgr' to 'value'.
+ * The previous IPv6 listen-on list is freed.
+ */
+
+dns_aclenv_t *
+ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr);
+
+void
+ns_interface_attach(ns_interface_t *source, ns_interface_t **target);
+
+void
+ns_interface_detach(ns_interface_t **targetp);
+
+void
+ns_interface_shutdown(ns_interface_t *ifp);
+/*%
+ * Stop listening for queries on interface 'ifp'.
+ * May safely be called multiple times.
+ */
+
+void
+ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr);
+
+isc_boolean_t
+ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr);
+
+#endif /* NAMED_INTERFACEMGR_H */
diff --git a/bin/named/include/named/listenlist.h b/bin/named/include/named/listenlist.h
new file mode 100644
index 0000000..9e65d5d
--- /dev/null
+++ b/bin/named/include/named/listenlist.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: listenlist.h,v 1.15 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_LISTENLIST_H
+#define NAMED_LISTENLIST_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * "Listen lists", as in the "listen-on" configuration statement.
+ */
+
+/***
+ *** Imports
+ ***/
+#include <isc/net.h>
+
+#include <dns/types.h>
+
+/***
+ *** Types
+ ***/
+
+typedef struct ns_listenelt ns_listenelt_t;
+typedef struct ns_listenlist ns_listenlist_t;
+
+struct ns_listenelt {
+ isc_mem_t * mctx;
+ in_port_t port;
+ dns_acl_t * acl;
+ ISC_LINK(ns_listenelt_t) link;
+};
+
+struct ns_listenlist {
+ isc_mem_t * mctx;
+ int refcount;
+ ISC_LIST(ns_listenelt_t) elts;
+};
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+ns_listenelt_create(isc_mem_t *mctx, in_port_t port,
+ dns_acl_t *acl, ns_listenelt_t **target);
+/*%
+ * Create a listen-on list element.
+ */
+
+void
+ns_listenelt_destroy(ns_listenelt_t *elt);
+/*%
+ * Destroy a listen-on list element.
+ */
+
+isc_result_t
+ns_listenlist_create(isc_mem_t *mctx, ns_listenlist_t **target);
+/*%
+ * Create a new, empty listen-on list.
+ */
+
+void
+ns_listenlist_attach(ns_listenlist_t *source, ns_listenlist_t **target);
+/*%
+ * Attach '*target' to '*source'.
+ */
+
+void
+ns_listenlist_detach(ns_listenlist_t **listp);
+/*%
+ * Detach 'listp'.
+ */
+
+isc_result_t
+ns_listenlist_default(isc_mem_t *mctx, in_port_t port,
+ isc_boolean_t enabled, ns_listenlist_t **target);
+/*%
+ * Create a listen-on list with default contents, matching
+ * all addresses with port 'port' (if 'enabled' is ISC_TRUE),
+ * or no addresses (if 'enabled' is ISC_FALSE).
+ */
+
+#endif /* NAMED_LISTENLIST_H */
+
+
diff --git a/bin/named/include/named/log.h b/bin/named/include/named/log.h
new file mode 100644
index 0000000..e8a4f32
--- /dev/null
+++ b/bin/named/include/named/log.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: log.h,v 1.25 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_LOG_H
+#define NAMED_LOG_H 1
+
+/*! \file */
+
+#include <isc/log.h>
+#include <isc/types.h>
+
+#include <dns/log.h>
+
+#include <named/globals.h> /* Required for ns_g_(categories|modules). */
+
+/* Unused slot 0. */
+#define NS_LOGCATEGORY_CLIENT (&ns_g_categories[1])
+#define NS_LOGCATEGORY_NETWORK (&ns_g_categories[2])
+#define NS_LOGCATEGORY_UPDATE (&ns_g_categories[3])
+#define NS_LOGCATEGORY_QUERIES (&ns_g_categories[4])
+#define NS_LOGCATEGORY_UNMATCHED (&ns_g_categories[5])
+#define NS_LOGCATEGORY_UPDATE_SECURITY (&ns_g_categories[6])
+
+/*
+ * Backwards compatibility.
+ */
+#define NS_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL
+
+#define NS_LOGMODULE_MAIN (&ns_g_modules[0])
+#define NS_LOGMODULE_CLIENT (&ns_g_modules[1])
+#define NS_LOGMODULE_SERVER (&ns_g_modules[2])
+#define NS_LOGMODULE_QUERY (&ns_g_modules[3])
+#define NS_LOGMODULE_INTERFACEMGR (&ns_g_modules[4])
+#define NS_LOGMODULE_UPDATE (&ns_g_modules[5])
+#define NS_LOGMODULE_XFER_IN (&ns_g_modules[6])
+#define NS_LOGMODULE_XFER_OUT (&ns_g_modules[7])
+#define NS_LOGMODULE_NOTIFY (&ns_g_modules[8])
+#define NS_LOGMODULE_CONTROL (&ns_g_modules[9])
+#define NS_LOGMODULE_LWRESD (&ns_g_modules[10])
+
+isc_result_t
+ns_log_init(isc_boolean_t safe);
+/*%
+ * Initialize the logging system and set up an initial default
+ * logging default configuration that will be used until the
+ * config file has been read.
+ *
+ * If 'safe' is true, use a default configuration that refrains
+ * from opening files. This is to avoid creating log files
+ * as root.
+ */
+
+isc_result_t
+ns_log_setdefaultchannels(isc_logconfig_t *lcfg);
+/*%
+ * Set up logging channels according to the named defaults, which
+ * may differ from the logging library defaults. Currently,
+ * this just means setting up default_debug.
+ */
+
+isc_result_t
+ns_log_setsafechannels(isc_logconfig_t *lcfg);
+/*%
+ * Like ns_log_setdefaultchannels(), but omits any logging to files.
+ */
+
+isc_result_t
+ns_log_setdefaultcategory(isc_logconfig_t *lcfg);
+/*%
+ * Set up "category default" to go to the right places.
+ */
+
+isc_result_t
+ns_log_setunmatchedcategory(isc_logconfig_t *lcfg);
+/*%
+ * Set up "category unmatched" to go to the right places.
+ */
+
+void
+ns_log_shutdown(void);
+
+#endif /* NAMED_LOG_H */
diff --git a/bin/named/include/named/logconf.h b/bin/named/include/named/logconf.h
new file mode 100644
index 0000000..0354345
--- /dev/null
+++ b/bin/named/include/named/logconf.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: logconf.h,v 1.17 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_LOGCONF_H
+#define NAMED_LOGCONF_H 1
+
+/*! \file */
+
+#include <isc/log.h>
+
+isc_result_t
+ns_log_configure(isc_logconfig_t *logconf, const cfg_obj_t *logstmt);
+/*%<
+ * Set up the logging configuration in '*logconf' according to
+ * the named.conf data in 'logstmt'.
+ */
+
+#endif /* NAMED_LOGCONF_H */
diff --git a/bin/named/include/named/lwaddr.h b/bin/named/include/named/lwaddr.h
new file mode 100644
index 0000000..962aa91
--- /dev/null
+++ b/bin/named/include/named/lwaddr.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwaddr.h,v 1.8 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+
+isc_result_t
+lwaddr_netaddr_fromlwresaddr(isc_netaddr_t *na, lwres_addr_t *la);
+
+isc_result_t
+lwaddr_sockaddr_fromlwresaddr(isc_sockaddr_t *sa, lwres_addr_t *la,
+ in_port_t port);
+
+isc_result_t
+lwaddr_lwresaddr_fromnetaddr(lwres_addr_t *la, isc_netaddr_t *na);
+
+isc_result_t
+lwaddr_lwresaddr_fromsockaddr(lwres_addr_t *la, isc_sockaddr_t *sa);
diff --git a/bin/named/include/named/lwdclient.h b/bin/named/include/named/lwdclient.h
new file mode 100644
index 0000000..176134a
--- /dev/null
+++ b/bin/named/include/named/lwdclient.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwdclient.h,v 1.18 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_LWDCLIENT_H
+#define NAMED_LWDCLIENT_H 1
+
+/*! \file */
+
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/netaddr.h>
+#include <isc/sockaddr.h>
+#include <isc/types.h>
+
+#include <dns/fixedname.h>
+#include <dns/types.h>
+
+#include <lwres/lwres.h>
+
+#include <named/lwsearch.h>
+
+#define LWRD_EVENTCLASS ISC_EVENTCLASS(4242)
+
+#define LWRD_SHUTDOWN (LWRD_EVENTCLASS + 0x0001)
+
+/*% Lighweight Resolver Daemon Client */
+struct ns_lwdclient {
+ isc_sockaddr_t address; /*%< where to reply */
+ struct in6_pktinfo pktinfo;
+ isc_boolean_t pktinfo_valid;
+ ns_lwdclientmgr_t *clientmgr; /*%< our parent */
+ ISC_LINK(ns_lwdclient_t) link;
+ unsigned int state;
+ void *arg; /*%< packet processing state */
+
+ /*
+ * Received data info.
+ */
+ unsigned char buffer[LWRES_RECVLENGTH]; /*%< receive buffer */
+ isc_uint32_t recvlength; /*%< length recv'd */
+ lwres_lwpacket_t pkt;
+
+ /*%
+ * Send data state. If sendbuf != buffer (that is, the send buffer
+ * isn't our receive buffer) it will be freed to the lwres_context_t.
+ */
+ unsigned char *sendbuf;
+ isc_uint32_t sendlength;
+ isc_buffer_t recv_buffer;
+
+ /*%
+ * gabn (get address by name) state info.
+ */
+ dns_adbfind_t *find;
+ dns_adbfind_t *v4find;
+ dns_adbfind_t *v6find;
+ unsigned int find_wanted; /*%< Addresses we want */
+ dns_fixedname_t query_name;
+ dns_fixedname_t target_name;
+ ns_lwsearchctx_t searchctx;
+ lwres_gabnresponse_t gabn;
+
+ /*%
+ * gnba (get name by address) state info.
+ */
+ lwres_gnbaresponse_t gnba;
+ dns_byaddr_t *byaddr;
+ unsigned int options;
+ isc_netaddr_t na;
+
+ /*%
+ * grbn (get rrset by name) state info.
+ *
+ * Note: this also uses target_name and searchctx.
+ */
+ lwres_grbnresponse_t grbn;
+ dns_lookup_t *lookup;
+ dns_rdatatype_t rdtype;
+
+ /*%
+ * Alias and address info. This is copied up to the gabn/gnba
+ * structures eventually.
+ *
+ * XXXMLG We can keep all of this in a client since we only service
+ * three packet types right now. If we started handling more,
+ * we'd need to use "arg" above and allocate/destroy things.
+ */
+ char *aliases[LWRES_MAX_ALIASES];
+ isc_uint16_t aliaslen[LWRES_MAX_ALIASES];
+ lwres_addr_t addrs[LWRES_MAX_ADDRS];
+};
+
+/*%
+ * Client states.
+ *
+ * _IDLE The client is not doing anything at all.
+ *
+ * _RECV The client is waiting for data after issuing a socket recv().
+ *
+ * _RECVDONE Data has been received, and is being processed.
+ *
+ * _FINDWAIT An adb (or other) request was made that cannot be satisfied
+ * immediately. An event will wake the client up.
+ *
+ * _SEND All data for a response has completed, and a reply was
+ * sent via a socket send() call.
+ *
+ * Badly formatted state table:
+ *
+ * IDLE -> RECV when client has a recv() queued.
+ *
+ * RECV -> RECVDONE when recvdone event received.
+ *
+ * RECVDONE -> SEND if the data for a reply is at hand.
+ * RECVDONE -> FINDWAIT if more searching is needed, and events will
+ * eventually wake us up again.
+ *
+ * FINDWAIT -> SEND when enough data was received to reply.
+ *
+ * SEND -> IDLE when a senddone event was received.
+ *
+ * At any time -> IDLE on error. Sometimes this will be -> SEND
+ * instead, if enough data is on hand to reply with a meaningful
+ * error.
+ *
+ * Packets which are badly formatted may or may not get error returns.
+ */
+#define NS_LWDCLIENT_STATEIDLE 1
+#define NS_LWDCLIENT_STATERECV 2
+#define NS_LWDCLIENT_STATERECVDONE 3
+#define NS_LWDCLIENT_STATEFINDWAIT 4
+#define NS_LWDCLIENT_STATESEND 5
+#define NS_LWDCLIENT_STATESENDDONE 6
+
+#define NS_LWDCLIENT_ISIDLE(c) \
+ ((c)->state == NS_LWDCLIENT_STATEIDLE)
+#define NS_LWDCLIENT_ISRECV(c) \
+ ((c)->state == NS_LWDCLIENT_STATERECV)
+#define NS_LWDCLIENT_ISRECVDONE(c) \
+ ((c)->state == NS_LWDCLIENT_STATERECVDONE)
+#define NS_LWDCLIENT_ISFINDWAIT(c) \
+ ((c)->state == NS_LWDCLIENT_STATEFINDWAIT)
+#define NS_LWDCLIENT_ISSEND(c) \
+ ((c)->state == NS_LWDCLIENT_STATESEND)
+
+/*%
+ * Overall magic test that means we're not idle.
+ */
+#define NS_LWDCLIENT_ISRUNNING(c) (!NS_LWDCLIENT_ISIDLE(c))
+
+#define NS_LWDCLIENT_SETIDLE(c) \
+ ((c)->state = NS_LWDCLIENT_STATEIDLE)
+#define NS_LWDCLIENT_SETRECV(c) \
+ ((c)->state = NS_LWDCLIENT_STATERECV)
+#define NS_LWDCLIENT_SETRECVDONE(c) \
+ ((c)->state = NS_LWDCLIENT_STATERECVDONE)
+#define NS_LWDCLIENT_SETFINDWAIT(c) \
+ ((c)->state = NS_LWDCLIENT_STATEFINDWAIT)
+#define NS_LWDCLIENT_SETSEND(c) \
+ ((c)->state = NS_LWDCLIENT_STATESEND)
+#define NS_LWDCLIENT_SETSENDDONE(c) \
+ ((c)->state = NS_LWDCLIENT_STATESENDDONE)
+
+/*% lightweight daemon client manager */
+struct ns_lwdclientmgr {
+ ns_lwreslistener_t *listener;
+ isc_mem_t *mctx;
+ isc_socket_t *sock; /*%< socket to use */
+ dns_view_t *view;
+ lwres_context_t *lwctx; /*%< lightweight proto context */
+ isc_task_t *task; /*%< owning task */
+ unsigned int flags;
+ ISC_LINK(ns_lwdclientmgr_t) link;
+ ISC_LIST(ns_lwdclient_t) idle; /*%< idle client slots */
+ ISC_LIST(ns_lwdclient_t) running; /*%< running clients */
+};
+
+#define NS_LWDCLIENTMGR_FLAGRECVPENDING 0x00000001
+#define NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN 0x00000002
+
+isc_result_t
+ns_lwdclientmgr_create(ns_lwreslistener_t *, unsigned int, isc_taskmgr_t *);
+
+void
+ns_lwdclient_initialize(ns_lwdclient_t *, ns_lwdclientmgr_t *);
+
+isc_result_t
+ns_lwdclient_startrecv(ns_lwdclientmgr_t *);
+
+void
+ns_lwdclient_stateidle(ns_lwdclient_t *);
+
+void
+ns_lwdclient_recv(isc_task_t *, isc_event_t *);
+
+void
+ns_lwdclient_shutdown(isc_task_t *, isc_event_t *);
+
+void
+ns_lwdclient_send(isc_task_t *, isc_event_t *);
+
+isc_result_t
+ns_lwdclient_sendreply(ns_lwdclient_t *client, isc_region_t *r);
+
+/*
+ * Processing functions of various types.
+ */
+void ns_lwdclient_processgabn(ns_lwdclient_t *, lwres_buffer_t *);
+void ns_lwdclient_processgnba(ns_lwdclient_t *, lwres_buffer_t *);
+void ns_lwdclient_processgrbn(ns_lwdclient_t *, lwres_buffer_t *);
+void ns_lwdclient_processnoop(ns_lwdclient_t *, lwres_buffer_t *);
+
+void ns_lwdclient_errorpktsend(ns_lwdclient_t *, isc_uint32_t);
+
+void ns_lwdclient_log(int level, const char *format, ...)
+ ISC_FORMAT_PRINTF(2, 3);
+
+#endif /* NAMED_LWDCLIENT_H */
diff --git a/bin/named/include/named/lwresd.h b/bin/named/include/named/lwresd.h
new file mode 100644
index 0000000..565e58d
--- /dev/null
+++ b/bin/named/include/named/lwresd.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2004-2007 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: lwresd.h,v 1.19 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_LWRESD_H
+#define NAMED_LWRESD_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+#include <isc/sockaddr.h>
+
+#include <isccfg/cfg.h>
+
+#include <dns/types.h>
+
+struct ns_lwresd {
+ unsigned int magic;
+
+ isc_mutex_t lock;
+ dns_view_t *view;
+ ns_lwsearchlist_t *search;
+ unsigned int ndots;
+ isc_mem_t *mctx;
+ isc_boolean_t shutting_down;
+ unsigned int refs;
+};
+
+struct ns_lwreslistener {
+ unsigned int magic;
+
+ isc_mutex_t lock;
+ isc_mem_t *mctx;
+ isc_sockaddr_t address;
+ ns_lwresd_t *manager;
+ isc_socket_t *sock;
+ unsigned int refs;
+ ISC_LIST(ns_lwdclientmgr_t) cmgrs;
+ ISC_LINK(ns_lwreslistener_t) link;
+};
+
+/*%
+ * Configure lwresd.
+ */
+isc_result_t
+ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config);
+
+isc_result_t
+ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx,
+ cfg_obj_t **configp);
+
+/*%
+ * Trigger shutdown.
+ */
+void
+ns_lwresd_shutdown(void);
+
+/*
+ * Manager functions
+ */
+/*% create manager */
+isc_result_t
+ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres,
+ ns_lwresd_t **lwresdp);
+
+/*% attach to manager */
+void
+ns_lwdmanager_attach(ns_lwresd_t *source, ns_lwresd_t **targetp);
+
+/*% detach from manager */
+void
+ns_lwdmanager_detach(ns_lwresd_t **lwresdp);
+
+/*
+ * Listener functions
+ */
+/*% attach to listener */
+void
+ns_lwreslistener_attach(ns_lwreslistener_t *source,
+ ns_lwreslistener_t **targetp);
+
+/*% detach from lister */
+void
+ns_lwreslistener_detach(ns_lwreslistener_t **listenerp);
+
+/*% link client manager */
+void
+ns_lwreslistener_unlinkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm);
+
+/*% unlink client manager */
+void
+ns_lwreslistener_linkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm);
+
+
+
+
+/*
+ * INTERNAL FUNCTIONS.
+ */
+void *
+ns__lwresd_memalloc(void *arg, size_t size);
+
+void
+ns__lwresd_memfree(void *arg, void *mem, size_t size);
+
+#endif /* NAMED_LWRESD_H */
diff --git a/bin/named/include/named/lwsearch.h b/bin/named/include/named/lwsearch.h
new file mode 100644
index 0000000..c1b4f48
--- /dev/null
+++ b/bin/named/include/named/lwsearch.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwsearch.h,v 1.9 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_LWSEARCH_H
+#define NAMED_LWSEARCH_H 1
+
+#include <isc/mutex.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+#include <dns/types.h>
+
+#include <named/types.h>
+
+/*! \file
+ * \brief
+ * Lightweight resolver search list types and routines.
+ *
+ * An ns_lwsearchlist_t holds a list of search path elements.
+ *
+ * An ns_lwsearchctx stores the state of search list during a lookup
+ * operation.
+ */
+
+/*% An ns_lwsearchlist_t holds a list of search path elements. */
+struct ns_lwsearchlist {
+ unsigned int magic;
+
+ isc_mutex_t lock;
+ isc_mem_t *mctx;
+ unsigned int refs;
+ dns_namelist_t names;
+};
+/*% An ns_lwsearchctx stores the state of search list during a lookup operation. */
+struct ns_lwsearchctx {
+ dns_name_t *relname;
+ dns_name_t *searchname;
+ unsigned int ndots;
+ ns_lwsearchlist_t *list;
+ isc_boolean_t doneexact;
+ isc_boolean_t exactfirst;
+};
+
+isc_result_t
+ns_lwsearchlist_create(isc_mem_t *mctx, ns_lwsearchlist_t **listp);
+/*%<
+ * Create an empty search list object.
+ */
+
+void
+ns_lwsearchlist_attach(ns_lwsearchlist_t *source, ns_lwsearchlist_t **target);
+/*%<
+ * Attach to a search list object.
+ */
+
+void
+ns_lwsearchlist_detach(ns_lwsearchlist_t **listp);
+/*%<
+ * Detach from a search list object.
+ */
+
+isc_result_t
+ns_lwsearchlist_append(ns_lwsearchlist_t *list, dns_name_t *name);
+/*%<
+ * Append an element to a search list. This creates a copy of the name.
+ */
+
+void
+ns_lwsearchctx_init(ns_lwsearchctx_t *sctx, ns_lwsearchlist_t *list,
+ dns_name_t *name, unsigned int ndots);
+/*%<
+ * Creates a search list context structure.
+ */
+
+void
+ns_lwsearchctx_first(ns_lwsearchctx_t *sctx);
+/*%<
+ * Moves the search list context iterator to the first element, which
+ * is usually the exact name.
+ */
+
+isc_result_t
+ns_lwsearchctx_next(ns_lwsearchctx_t *sctx);
+/*%<
+ * Moves the search list context iterator to the next element.
+ */
+
+isc_result_t
+ns_lwsearchctx_current(ns_lwsearchctx_t *sctx, dns_name_t *absname);
+/*%<
+ * Obtains the current name to be looked up. This involves either
+ * concatenating the name with a search path element, making an
+ * exact name absolute, or doing nothing.
+ */
+
+#endif /* NAMED_LWSEARCH_H */
diff --git a/bin/named/include/named/main.h b/bin/named/include/named/main.h
new file mode 100644
index 0000000..e834539
--- /dev/null
+++ b/bin/named/include/named/main.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: main.h,v 1.15 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_MAIN_H
+#define NAMED_MAIN_H 1
+
+/*! \file */
+
+void
+ns_main_earlyfatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+ns_main_earlywarning(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+ns_main_setmemstats(const char *);
+
+#endif /* NAMED_MAIN_H */
diff --git a/bin/named/include/named/notify.h b/bin/named/include/named/notify.h
new file mode 100644
index 0000000..6205d7d
--- /dev/null
+++ b/bin/named/include/named/notify.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: notify.h,v 1.14 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_NOTIFY_H
+#define NAMED_NOTIFY_H 1
+
+#include <named/types.h>
+#include <named/client.h>
+
+/***
+ *** Module Info
+ ***/
+
+/*! \file
+ * \brief
+ * RFC1996
+ * A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY)
+ */
+
+/***
+ *** Functions.
+ ***/
+
+void
+ns_notify_start(ns_client_t *client);
+
+/*%<
+ * Examines the incoming message to determine apporiate zone.
+ * Returns FORMERR if there is not exactly one question.
+ * Returns REFUSED if we do not serve the listed zone.
+ * Pass the message to the zone module for processing
+ * and returns the return status.
+ *
+ * Requires
+ *\li client to be valid.
+ */
+
+#endif /* NAMED_NOTIFY_H */
+
diff --git a/bin/named/include/named/ns_smf_globals.h b/bin/named/include/named/ns_smf_globals.h
new file mode 100644
index 0000000..3a35743
--- /dev/null
+++ b/bin/named/include/named/ns_smf_globals.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2005, 2007 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: ns_smf_globals.h,v 1.7 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NS_SMF_GLOBALS_H
+#define NS_SMF_GLOBALS_H 1
+
+#include <libscf.h>
+
+#undef EXTERN
+#undef INIT
+#ifdef NS_MAIN
+#define EXTERN
+#define INIT(v) = (v)
+#else
+#define EXTERN extern
+#define INIT(v)
+#endif
+
+EXTERN unsigned int ns_smf_got_instance INIT(0);
+EXTERN unsigned int ns_smf_chroot INIT(0);
+EXTERN unsigned int ns_smf_want_disable INIT(0);
+
+isc_result_t ns_smf_add_message(isc_buffer_t *text);
+isc_result_t ns_smf_get_instance(char **name, int debug, isc_mem_t *mctx);
+
+#undef EXTERN
+#undef INIT
+
+#endif /* NS_SMF_GLOBALS_H */
diff --git a/bin/named/include/named/query.h b/bin/named/include/named/query.h
new file mode 100644
index 0000000..500b577
--- /dev/null
+++ b/bin/named/include/named/query.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: query.h,v 1.40 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_QUERY_H
+#define NAMED_QUERY_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+#include <isc/buffer.h>
+#include <isc/netaddr.h>
+
+#include <dns/types.h>
+
+#include <named/types.h>
+
+/*% nameserver database version structure */
+typedef struct ns_dbversion {
+ dns_db_t *db;
+ dns_dbversion_t *version;
+ isc_boolean_t queryok;
+ ISC_LINK(struct ns_dbversion) link;
+} ns_dbversion_t;
+
+/*% nameserver query structure */
+struct ns_query {
+ unsigned int attributes;
+ unsigned int restarts;
+ isc_boolean_t timerset;
+ dns_name_t * qname;
+ dns_name_t * origqname;
+ unsigned int dboptions;
+ unsigned int fetchoptions;
+ dns_db_t * gluedb;
+ dns_db_t * authdb;
+ dns_zone_t * authzone;
+ isc_boolean_t authdbset;
+ isc_boolean_t isreferral;
+ isc_mutex_t fetchlock;
+ dns_fetch_t * fetch;
+ isc_bufferlist_t namebufs;
+ ISC_LIST(ns_dbversion_t) activeversions;
+ ISC_LIST(ns_dbversion_t) freeversions;
+};
+
+#define NS_QUERYATTR_RECURSIONOK 0x0001
+#define NS_QUERYATTR_CACHEOK 0x0002
+#define NS_QUERYATTR_PARTIALANSWER 0x0004
+#define NS_QUERYATTR_NAMEBUFUSED 0x0008
+#define NS_QUERYATTR_RECURSING 0x0010
+#define NS_QUERYATTR_CACHEGLUEOK 0x0020
+#define NS_QUERYATTR_QUERYOKVALID 0x0040
+#define NS_QUERYATTR_QUERYOK 0x0080
+#define NS_QUERYATTR_WANTRECURSION 0x0100
+#define NS_QUERYATTR_SECURE 0x0200
+#define NS_QUERYATTR_NOAUTHORITY 0x0400
+#define NS_QUERYATTR_NOADDITIONAL 0x0800
+
+isc_result_t
+ns_query_init(ns_client_t *client);
+
+void
+ns_query_free(ns_client_t *client);
+
+void
+ns_query_start(ns_client_t *client);
+
+void
+ns_query_cancel(ns_client_t *client);
+
+#endif /* NAMED_QUERY_H */
diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h
new file mode 100644
index 0000000..d3a75fd
--- /dev/null
+++ b/bin/named/include/named/server.h
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: server.h,v 1.93 2008/04/03 05:55:51 marka Exp $ */
+
+#ifndef NAMED_SERVER_H
+#define NAMED_SERVER_H 1
+
+/*! \file */
+
+#include <isc/log.h>
+#include <isc/magic.h>
+#include <isc/quota.h>
+#include <isc/sockaddr.h>
+#include <isc/types.h>
+#include <isc/xml.h>
+
+#include <dns/acl.h>
+#include <dns/types.h>
+
+#include <named/types.h>
+
+#define NS_EVENTCLASS ISC_EVENTCLASS(0x4E43)
+#define NS_EVENT_RELOAD (NS_EVENTCLASS + 0)
+#define NS_EVENT_CLIENTCONTROL (NS_EVENTCLASS + 1)
+
+/*%
+ * Name server state. Better here than in lots of separate global variables.
+ */
+struct ns_server {
+ unsigned int magic;
+ isc_mem_t * mctx;
+
+ isc_task_t * task;
+
+ /* Configurable data. */
+ isc_quota_t xfroutquota;
+ isc_quota_t tcpquota;
+ isc_quota_t recursionquota;
+ dns_acl_t *blackholeacl;
+ char * statsfile; /*%< Statistics file name */
+ char * dumpfile; /*%< Dump file name */
+ char * recfile; /*%< Recursive file name */
+ isc_boolean_t version_set; /*%< User has set version */
+ char * version; /*%< User-specified version */
+ isc_boolean_t hostname_set; /*%< User has set hostname */
+ char * hostname; /*%< User-specified hostname */
+ /*% Use hostname for server id */
+ isc_boolean_t server_usehostname;
+ char * server_id; /*%< User-specified server id */
+
+ /*%
+ * Current ACL environment. This defines the
+ * current values of the localhost and localnets
+ * ACLs.
+ */
+ dns_aclenv_t aclenv;
+
+ /* Server data structures. */
+ dns_loadmgr_t * loadmgr;
+ dns_zonemgr_t * zonemgr;
+ dns_viewlist_t viewlist;
+ ns_interfacemgr_t * interfacemgr;
+ dns_db_t * in_roothints;
+ dns_tkeyctx_t * tkeyctx;
+
+ isc_timer_t * interface_timer;
+ isc_timer_t * heartbeat_timer;
+ isc_timer_t * pps_timer;
+
+ isc_uint32_t interface_interval;
+ isc_uint32_t heartbeat_interval;
+
+ isc_mutex_t reload_event_lock;
+ isc_event_t * reload_event;
+
+ isc_boolean_t flushonshutdown;
+ isc_boolean_t log_queries; /*%< For BIND 8 compatibility */
+
+ dns_stats_t * nsstats; /*%< Server statistics */
+ dns_stats_t * rcvquerystats; /*% Incoming query statistics */
+ dns_stats_t * opcodestats; /*%< Incoming message statistics */
+ dns_stats_t * zonestats; /*% Zone management statistics */
+ dns_stats_t * resolverstats; /*% Resolver statistics */
+
+ ns_controls_t * controls; /*%< Control channels */
+ unsigned int dispatchgen;
+ ns_dispatchlist_t dispatches;
+
+ dns_acache_t *acache;
+
+ ns_statschannellist_t statschannels;
+};
+
+#define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R')
+#define NS_SERVER_VALID(s) ISC_MAGIC_VALID(s, NS_SERVER_MAGIC)
+
+/*%
+ * Server statistics counters. Used as dns_statscounter_t values.
+ */
+enum {
+ dns_nsstatscounter_requestv4 = 0,
+ dns_nsstatscounter_requestv6 = 1,
+ dns_nsstatscounter_edns0in = 2,
+ dns_nsstatscounter_badednsver = 3,
+ dns_nsstatscounter_tsigin = 4,
+ dns_nsstatscounter_sig0in = 5,
+ dns_nsstatscounter_invalidsig = 6,
+ dns_nsstatscounter_tcp = 7,
+
+ dns_nsstatscounter_authrej = 8,
+ dns_nsstatscounter_recurserej = 9,
+ dns_nsstatscounter_xfrrej = 10,
+ dns_nsstatscounter_updaterej = 11,
+
+ dns_nsstatscounter_response = 12,
+ dns_nsstatscounter_truncatedresp = 13,
+ dns_nsstatscounter_edns0out = 14,
+ dns_nsstatscounter_tsigout = 15,
+ dns_nsstatscounter_sig0out = 16,
+
+ dns_nsstatscounter_success = 17,
+ dns_nsstatscounter_authans = 18,
+ dns_nsstatscounter_nonauthans = 19,
+ dns_nsstatscounter_referral = 20,
+ dns_nsstatscounter_nxrrset = 21,
+ dns_nsstatscounter_servfail = 22,
+ dns_nsstatscounter_formerr = 23,
+ dns_nsstatscounter_nxdomain = 24,
+ dns_nsstatscounter_recursion = 25,
+ dns_nsstatscounter_duplicate = 26,
+ dns_nsstatscounter_dropped = 27,
+ dns_nsstatscounter_failure = 28,
+
+ dns_nsstatscounter_xfrdone = 29,
+
+ dns_nsstatscounter_updatereqfwd = 30,
+ dns_nsstatscounter_updaterespfwd = 31,
+ dns_nsstatscounter_updatefwdfail = 32,
+ dns_nsstatscounter_updatedone = 33,
+ dns_nsstatscounter_updatefail = 34,
+ dns_nsstatscounter_updatebadprereq = 35,
+
+ dns_nsstatscounter_max = 36
+};
+
+void
+ns_server_create(isc_mem_t *mctx, ns_server_t **serverp);
+/*%<
+ * Create a server object with default settings.
+ * This function either succeeds or causes the program to exit
+ * with a fatal error.
+ */
+
+void
+ns_server_destroy(ns_server_t **serverp);
+/*%<
+ * Destroy a server object, freeing its memory.
+ */
+
+void
+ns_server_reloadwanted(ns_server_t *server);
+/*%<
+ * Inform a server that a reload is wanted. This function
+ * may be called asynchronously, from outside the server's task.
+ * If a reload is already scheduled or in progress, the call
+ * is ignored.
+ */
+
+void
+ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush);
+/*%<
+ * Inform the server that the zones should be flushed to disk on shutdown.
+ */
+
+isc_result_t
+ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text);
+/*%<
+ * Act on a "reload" command from the command channel.
+ */
+
+isc_result_t
+ns_server_reconfigcommand(ns_server_t *server, char *args);
+/*%<
+ * Act on a "reconfig" command from the command channel.
+ */
+
+isc_result_t
+ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text);
+/*%<
+ * Act on a "notify" command from the command channel.
+ */
+
+isc_result_t
+ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text);
+/*%<
+ * Act on a "refresh" command from the command channel.
+ */
+
+isc_result_t
+ns_server_retransfercommand(ns_server_t *server, char *args);
+/*%<
+ * Act on a "retransfer" command from the command channel.
+ */
+
+isc_result_t
+ns_server_togglequerylog(ns_server_t *server);
+/*%<
+ * Toggle logging of queries, as in BIND 8.
+ */
+
+/*%
+ * Dump the current statistics to the statistics file.
+ */
+isc_result_t
+ns_server_dumpstats(ns_server_t *server);
+
+/*%
+ * Dump the current cache to the dump file.
+ */
+isc_result_t
+ns_server_dumpdb(ns_server_t *server, char *args);
+
+/*%
+ * Change or increment the server debug level.
+ */
+isc_result_t
+ns_server_setdebuglevel(ns_server_t *server, char *args);
+
+/*%
+ * Flush the server's cache(s)
+ */
+isc_result_t
+ns_server_flushcache(ns_server_t *server, char *args);
+
+/*%
+ * Flush a particular name from the server's cache(s)
+ */
+isc_result_t
+ns_server_flushname(ns_server_t *server, char *args);
+
+/*%
+ * Report the server's status.
+ */
+isc_result_t
+ns_server_status(ns_server_t *server, isc_buffer_t *text);
+
+/*%
+ * Report a list of dynamic and static tsig keys, per view.
+ */
+isc_result_t
+ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text);
+
+/*%
+ * Delete a specific key (with optional view).
+ */
+isc_result_t
+ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text);
+
+/*%
+ * Enable or disable updates for a zone.
+ */
+isc_result_t
+ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args);
+
+/*%
+ * Dump the current recursive queries.
+ */
+isc_result_t
+ns_server_dumprecursing(ns_server_t *server);
+
+/*%
+ * Maintain a list of dispatches that require reserved ports.
+ */
+void
+ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr);
+
+/*%
+ * Enable or disable dnssec validation.
+ */
+isc_result_t
+ns_server_validation(ns_server_t *server, char *args);
+
+#endif /* NAMED_SERVER_H */
diff --git a/bin/named/include/named/sortlist.h b/bin/named/include/named/sortlist.h
new file mode 100644
index 0000000..b9f6076
--- /dev/null
+++ b/bin/named/include/named/sortlist.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2004-2007 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: sortlist.h,v 1.11 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_SORTLIST_H
+#define NAMED_SORTLIST_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+
+#include <dns/types.h>
+
+/*%
+ * Type for callback functions that rank addresses.
+ */
+typedef int
+(*dns_addressorderfunc_t)(const isc_netaddr_t *address, const void *arg);
+
+/*%
+ * Return value type for setup_sortlist.
+ */
+typedef enum {
+ NS_SORTLISTTYPE_NONE,
+ NS_SORTLISTTYPE_1ELEMENT,
+ NS_SORTLISTTYPE_2ELEMENT
+} ns_sortlisttype_t;
+
+ns_sortlisttype_t
+ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr,
+ const void **argp);
+/*%<
+ * Find the sortlist statement in 'acl' that applies to 'clientaddr', if any.
+ *
+ * If a 1-element sortlist item applies, return NS_SORTLISTTYPE_1ELEMENT and
+ * make '*argp' point to the matching subelement.
+ *
+ * If a 2-element sortlist item applies, return NS_SORTLISTTYPE_2ELEMENT and
+ * make '*argp' point to ACL that forms the second element.
+ *
+ * If no sortlist item applies, return NS_SORTLISTTYPE_NONE and set '*argp'
+ * to NULL.
+ */
+
+int
+ns_sortlist_addrorder1(const isc_netaddr_t *addr, const void *arg);
+/*%<
+ * Find the sort order of 'addr' in 'arg', the matching element
+ * of a 1-element top-level sortlist statement.
+ */
+
+int
+ns_sortlist_addrorder2(const isc_netaddr_t *addr, const void *arg);
+/*%<
+ * Find the sort order of 'addr' in 'arg', a topology-like
+ * ACL forming the second element in a 2-element top-level
+ * sortlist statement.
+ */
+
+void
+ns_sortlist_byaddrsetup(dns_acl_t *sortlist_acl, isc_netaddr_t *client_addr,
+ dns_addressorderfunc_t *orderp,
+ const void **argp);
+/*%<
+ * Find the sortlist statement in 'acl' that applies to 'clientaddr', if any.
+ * If a sortlist statement applies, return in '*orderp' a pointer to a function
+ * for ranking network addresses based on that sortlist statement, and in
+ * '*argp' an argument to pass to said function. If no sortlist statement
+ * applies, set '*orderp' and '*argp' to NULL.
+ */
+
+#endif /* NAMED_SORTLIST_H */
diff --git a/bin/named/include/named/statschannel.h b/bin/named/include/named/statschannel.h
new file mode 100644
index 0000000..0c36d8c
--- /dev/null
+++ b/bin/named/include/named/statschannel.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 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: statschannel.h,v 1.3 2008/04/03 05:55:51 marka Exp $ */
+
+#ifndef NAMED_STATSCHANNEL_H
+#define NAMED_STATSCHANNEL_H 1
+
+/*! \file
+ * \brief
+ * The statistics channels built-in the name server.
+ */
+
+#include <isccc/types.h>
+
+#include <isccfg/aclconf.h>
+
+#include <named/types.h>
+
+#define NS_STATSCHANNEL_HTTPPORT 80
+
+isc_result_t
+ns_statschannels_configure(ns_server_t *server, const cfg_obj_t *config,
+ cfg_aclconfctx_t *aclconfctx);
+/*%<
+ * [Re]configure the statistics channels.
+ *
+ * If it is no longer there but was previously configured, destroy
+ * it here.
+ *
+ * If the IP address or port has changed, destroy the old server
+ * and create a new one.
+ */
+
+
+void
+ns_statschannels_shutdown(ns_server_t *server);
+/*%<
+ * Initiate shutdown of all the statistics channel listeners.
+ */
+
+isc_result_t
+ns_stats_dump(ns_server_t *server, FILE *fp);
+/*%<
+ * Dump statistics counters managed by the server to the file fp.
+ */
+
+#endif /* NAMED_STATSCHANNEL_H */
diff --git a/bin/named/include/named/tkeyconf.h b/bin/named/include/named/tkeyconf.h
new file mode 100644
index 0000000..02bd718
--- /dev/null
+++ b/bin/named/include/named/tkeyconf.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: tkeyconf.h,v 1.16 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NS_TKEYCONF_H
+#define NS_TKEYCONF_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+#include <isc/lang.h>
+
+#include <isccfg/cfg.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
+ isc_entropy_t *ectx, dns_tkeyctx_t **tctxp);
+/*%<
+ * Create a TKEY context and configure it, including the default DH key
+ * and default domain, according to 'options'.
+ *
+ * Requires:
+ *\li 'cfg' is a valid configuration options object.
+ *\li 'mctx' is not NULL
+ *\li 'ectx' is not NULL
+ *\li 'tctx' is not NULL
+ *\li '*tctx' is NULL
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOMEMORY
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* NS_TKEYCONF_H */
diff --git a/bin/named/include/named/tsigconf.h b/bin/named/include/named/tsigconf.h
new file mode 100644
index 0000000..49ad82a
--- /dev/null
+++ b/bin/named/include/named/tsigconf.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: tsigconf.h,v 1.16 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NS_TSIGCONF_H
+#define NS_TSIGCONF_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ isc_mem_t *mctx, dns_tsig_keyring_t **ringp);
+/*%<
+ * Create a TSIG key ring and configure it according to the 'key'
+ * statements in the global and view configuration objects.
+ *
+ * Requires:
+ * \li 'config' is not NULL.
+ * \li 'mctx' is not NULL
+ * \li 'ring' is not NULL, and '*ring' is NULL
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOMEMORY
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* NS_TSIGCONF_H */
diff --git a/bin/named/include/named/types.h b/bin/named/include/named/types.h
new file mode 100644
index 0000000..eb25520
--- /dev/null
+++ b/bin/named/include/named/types.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: types.h,v 1.29 2008/01/17 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_TYPES_H
+#define NAMED_TYPES_H 1
+
+/*! \file */
+
+#include <dns/types.h>
+
+typedef struct ns_client ns_client_t;
+typedef struct ns_clientmgr ns_clientmgr_t;
+typedef struct ns_query ns_query_t;
+typedef struct ns_server ns_server_t;
+typedef struct ns_xmld ns_xmld_t;
+typedef struct ns_xmldmgr ns_xmldmgr_t;
+typedef struct ns_interface ns_interface_t;
+typedef struct ns_interfacemgr ns_interfacemgr_t;
+typedef struct ns_lwresd ns_lwresd_t;
+typedef struct ns_lwreslistener ns_lwreslistener_t;
+typedef struct ns_lwdclient ns_lwdclient_t;
+typedef struct ns_lwdclientmgr ns_lwdclientmgr_t;
+typedef struct ns_lwsearchlist ns_lwsearchlist_t;
+typedef struct ns_lwsearchctx ns_lwsearchctx_t;
+typedef struct ns_controls ns_controls_t;
+typedef struct ns_dispatch ns_dispatch_t;
+typedef ISC_LIST(ns_dispatch_t) ns_dispatchlist_t;
+typedef struct ns_statschannel ns_statschannel_t;
+typedef ISC_LIST(ns_statschannel_t) ns_statschannellist_t;
+#endif /* NAMED_TYPES_H */
diff --git a/bin/named/include/named/update.h b/bin/named/include/named/update.h
new file mode 100644
index 0000000..a34570c
--- /dev/null
+++ b/bin/named/include/named/update.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: update.h,v 1.13 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_UPDATE_H
+#define NAMED_UPDATE_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * RFC2136 Dynamic Update
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <dns/types.h>
+#include <dns/result.h>
+
+/***
+ *** Types.
+ ***/
+
+/***
+ *** Functions
+ ***/
+
+void
+ns_update_start(ns_client_t *client, isc_result_t sigresult);
+
+#endif /* NAMED_UPDATE_H */
diff --git a/bin/named/include/named/xfrout.h b/bin/named/include/named/xfrout.h
new file mode 100644
index 0000000..4bb79a3
--- /dev/null
+++ b/bin/named/include/named/xfrout.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: xfrout.h,v 1.12 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NAMED_XFROUT_H
+#define NAMED_XFROUT_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * Outgoing zone transfers (AXFR + IXFR).
+ */
+
+/***
+ *** Functions
+ ***/
+
+void
+ns_xfr_start(ns_client_t *client, dns_rdatatype_t xfrtype);
+
+#endif /* NAMED_XFROUT_H */
diff --git a/bin/named/include/named/zoneconf.h b/bin/named/include/named/zoneconf.h
new file mode 100644
index 0000000..b973013
--- /dev/null
+++ b/bin/named/include/named/zoneconf.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: zoneconf.h,v 1.26 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NS_ZONECONF_H
+#define NS_ZONECONF_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <isccfg/aclconf.h>
+#include <isccfg/cfg.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
+ dns_zone_t *zone);
+/*%<
+ * Configure or reconfigure a zone according to the named.conf
+ * data in 'cctx' and 'czone'.
+ *
+ * The zone origin is not configured, it is assumed to have been set
+ * at zone creation time.
+ *
+ * Require:
+ * \li 'lctx' to be initialized or NULL.
+ * \li 'cctx' to be initialized or NULL.
+ * \li 'ac' to point to an initialized ns_aclconfctx_t.
+ * \li 'czone' to be initialized.
+ * \li 'zone' to be initialized.
+ */
+
+isc_boolean_t
+ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig);
+/*%<
+ * If 'zone' can be safely reconfigured according to the configuration
+ * data in 'zconfig', return ISC_TRUE. If the configuration data is so
+ * different from the current zone state that the zone needs to be destroyed
+ * and recreated, return ISC_FALSE.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* NS_ZONECONF_H */
diff --git a/bin/named/interfacemgr.c b/bin/named/interfacemgr.c
new file mode 100644
index 0000000..897de28
--- /dev/null
+++ b/bin/named/interfacemgr.c
@@ -0,0 +1,974 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: interfacemgr.c,v 1.93 2008/07/23 23:27:54 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/interfaceiter.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/dispatch.h>
+
+#include <named/client.h>
+#include <named/log.h>
+#include <named/interfacemgr.h>
+
+#define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G')
+#define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC)
+
+#define IFMGR_COMMON_LOGARGS \
+ ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR
+
+/*% nameserver interface manager structure */
+struct ns_interfacemgr {
+ unsigned int magic; /*%< Magic number. */
+ int references;
+ isc_mutex_t lock;
+ isc_mem_t * mctx; /*%< Memory context. */
+ isc_taskmgr_t * taskmgr; /*%< Task manager. */
+ isc_socketmgr_t * socketmgr; /*%< Socket manager. */
+ dns_dispatchmgr_t * dispatchmgr;
+ unsigned int generation; /*%< Current generation no. */
+ ns_listenlist_t * listenon4;
+ ns_listenlist_t * listenon6;
+ dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */
+ ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */
+ ISC_LIST(isc_sockaddr_t) listenon;
+};
+
+static void
+purge_old_interfaces(ns_interfacemgr_t *mgr);
+
+static void
+clearlistenon(ns_interfacemgr_t *mgr);
+
+isc_result_t
+ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
+ isc_socketmgr_t *socketmgr,
+ dns_dispatchmgr_t *dispatchmgr,
+ ns_interfacemgr_t **mgrp)
+{
+ isc_result_t result;
+ ns_interfacemgr_t *mgr;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(mgrp != NULL);
+ REQUIRE(*mgrp == NULL);
+
+ mgr = isc_mem_get(mctx, sizeof(*mgr));
+ if (mgr == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&mgr->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mem;
+
+ mgr->mctx = mctx;
+ mgr->taskmgr = taskmgr;
+ mgr->socketmgr = socketmgr;
+ mgr->dispatchmgr = dispatchmgr;
+ mgr->generation = 1;
+ mgr->listenon4 = NULL;
+ mgr->listenon6 = NULL;
+
+ ISC_LIST_INIT(mgr->interfaces);
+ ISC_LIST_INIT(mgr->listenon);
+
+ /*
+ * The listen-on lists are initially empty.
+ */
+ result = ns_listenlist_create(mctx, &mgr->listenon4);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mem;
+ ns_listenlist_attach(mgr->listenon4, &mgr->listenon6);
+
+ result = dns_aclenv_init(mctx, &mgr->aclenv);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_listenon;
+
+ mgr->references = 1;
+ mgr->magic = IFMGR_MAGIC;
+ *mgrp = mgr;
+ return (ISC_R_SUCCESS);
+
+ cleanup_listenon:
+ ns_listenlist_detach(&mgr->listenon4);
+ ns_listenlist_detach(&mgr->listenon6);
+ cleanup_mem:
+ isc_mem_put(mctx, mgr, sizeof(*mgr));
+ return (result);
+}
+
+static void
+ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) {
+ REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+ dns_aclenv_destroy(&mgr->aclenv);
+ ns_listenlist_detach(&mgr->listenon4);
+ ns_listenlist_detach(&mgr->listenon6);
+ clearlistenon(mgr);
+ DESTROYLOCK(&mgr->lock);
+ mgr->magic = 0;
+ isc_mem_put(mgr->mctx, mgr, sizeof(*mgr));
+}
+
+dns_aclenv_t *
+ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) {
+ return (&mgr->aclenv);
+}
+
+void
+ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) {
+ REQUIRE(NS_INTERFACEMGR_VALID(source));
+ LOCK(&source->lock);
+ INSIST(source->references > 0);
+ source->references++;
+ UNLOCK(&source->lock);
+ *target = source;
+}
+
+void
+ns_interfacemgr_detach(ns_interfacemgr_t **targetp) {
+ isc_result_t need_destroy = ISC_FALSE;
+ ns_interfacemgr_t *target = *targetp;
+ REQUIRE(target != NULL);
+ REQUIRE(NS_INTERFACEMGR_VALID(target));
+ LOCK(&target->lock);
+ REQUIRE(target->references > 0);
+ target->references--;
+ if (target->references == 0)
+ need_destroy = ISC_TRUE;
+ UNLOCK(&target->lock);
+ if (need_destroy)
+ ns_interfacemgr_destroy(target);
+ *targetp = NULL;
+}
+
+void
+ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) {
+ REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+
+ /*%
+ * Shut down and detach all interfaces.
+ * By incrementing the generation count, we make purge_old_interfaces()
+ * consider all interfaces "old".
+ */
+ mgr->generation++;
+ purge_old_interfaces(mgr);
+}
+
+
+static isc_result_t
+ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
+ const char *name, ns_interface_t **ifpret)
+{
+ ns_interface_t *ifp;
+ isc_result_t result;
+
+ REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+ ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
+ if (ifp == NULL)
+ return (ISC_R_NOMEMORY);
+ ifp->mgr = NULL;
+ ifp->generation = mgr->generation;
+ ifp->addr = *addr;
+ ifp->flags = 0;
+ strncpy(ifp->name, name, sizeof(ifp->name));
+ ifp->name[sizeof(ifp->name)-1] = '\0';
+ ifp->clientmgr = NULL;
+
+ result = isc_mutex_init(&ifp->lock);
+ if (result != ISC_R_SUCCESS)
+ goto lock_create_failure;
+
+ result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr,
+ ns_g_timermgr,
+ &ifp->clientmgr);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "ns_clientmgr_create() failed: %s",
+ isc_result_totext(result));
+ goto clientmgr_create_failure;
+ }
+
+ ifp->udpdispatch = NULL;
+
+ ifp->tcpsocket = NULL;
+ /*
+ * Create a single TCP client object. It will replace itself
+ * with a new one as soon as it gets a connection, so the actual
+ * connections will be handled in parallel even though there is
+ * only one client initially.
+ */
+ ifp->ntcptarget = 1;
+ ifp->ntcpcurrent = 0;
+
+ ISC_LINK_INIT(ifp, link);
+
+ ns_interfacemgr_attach(mgr, &ifp->mgr);
+ ISC_LIST_APPEND(mgr->interfaces, ifp, link);
+
+ ifp->references = 1;
+ ifp->magic = IFACE_MAGIC;
+ *ifpret = ifp;
+
+ return (ISC_R_SUCCESS);
+
+ clientmgr_create_failure:
+ DESTROYLOCK(&ifp->lock);
+ lock_create_failure:
+ ifp->magic = 0;
+ isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));
+
+ return (ISC_R_UNEXPECTED);
+}
+
+static isc_result_t
+ns_interface_listenudp(ns_interface_t *ifp) {
+ isc_result_t result;
+ unsigned int attrs;
+ unsigned int attrmask;
+
+ attrs = 0;
+ attrs |= DNS_DISPATCHATTR_UDP;
+ if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ else
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ attrs |= DNS_DISPATCHATTR_NOLISTEN;
+ attrmask = 0;
+ attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
+ result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr,
+ ns_g_taskmgr, &ifp->addr,
+ 4096, 1000, 32768, 8219, 8237,
+ attrs, attrmask, &ifp->udpdispatch);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "could not listen on UDP socket: %s",
+ isc_result_totext(result));
+ goto udp_dispatch_failure;
+ }
+
+ result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus,
+ ifp, ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "UDP ns_clientmgr_createclients(): %s",
+ isc_result_totext(result));
+ goto addtodispatch_failure;
+ }
+ return (ISC_R_SUCCESS);
+
+ addtodispatch_failure:
+ dns_dispatch_changeattributes(ifp->udpdispatch, 0,
+ DNS_DISPATCHATTR_NOLISTEN);
+ dns_dispatch_detach(&ifp->udpdispatch);
+ udp_dispatch_failure:
+ return (result);
+}
+
+static isc_result_t
+ns_interface_accepttcp(ns_interface_t *ifp) {
+ isc_result_t result;
+
+ /*
+ * Open a TCP socket.
+ */
+ result = isc_socket_create(ifp->mgr->socketmgr,
+ isc_sockaddr_pf(&ifp->addr),
+ isc_sockettype_tcp,
+ &ifp->tcpsocket);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "creating TCP socket: %s",
+ isc_result_totext(result));
+ goto tcp_socket_failure;
+ }
+ isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL);
+#ifndef ISC_ALLOW_MAPPED
+ isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE);
+#endif
+ result = isc_socket_bind(ifp->tcpsocket, &ifp->addr,
+ ISC_SOCKET_REUSEADDRESS);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "binding TCP socket: %s",
+ isc_result_totext(result));
+ goto tcp_bind_failure;
+ }
+ result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "listening on TCP socket: %s",
+ isc_result_totext(result));
+ goto tcp_listen_failure;
+ }
+
+ /*
+ * If/when there a multiple filters listen to the
+ * result.
+ */
+ (void)isc_socket_filter(ifp->tcpsocket, "dataready");
+
+ result = ns_clientmgr_createclients(ifp->clientmgr,
+ ifp->ntcptarget, ifp,
+ ISC_TRUE);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "TCP ns_clientmgr_createclients(): %s",
+ isc_result_totext(result));
+ goto accepttcp_failure;
+ }
+ return (ISC_R_SUCCESS);
+
+ accepttcp_failure:
+ tcp_listen_failure:
+ tcp_bind_failure:
+ isc_socket_detach(&ifp->tcpsocket);
+ tcp_socket_failure:
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
+ const char *name, ns_interface_t **ifpret,
+ isc_boolean_t accept_tcp)
+{
+ isc_result_t result;
+ ns_interface_t *ifp = NULL;
+ REQUIRE(ifpret != NULL && *ifpret == NULL);
+
+ result = ns_interface_create(mgr, addr, name, &ifp);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = ns_interface_listenudp(ifp);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_interface;
+
+ if (accept_tcp == ISC_TRUE) {
+ result = ns_interface_accepttcp(ifp);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * XXXRTH We don't currently have a way to easily stop
+ * dispatch service, so we currently return
+ * ISC_R_SUCCESS (the UDP stuff will work even if TCP
+ * creation failed). This will be fixed later.
+ */
+ result = ISC_R_SUCCESS;
+ }
+ }
+ *ifpret = ifp;
+ return (ISC_R_SUCCESS);
+
+ cleanup_interface:
+ ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
+ ns_interface_detach(&ifp);
+ return (result);
+}
+
+void
+ns_interface_shutdown(ns_interface_t *ifp) {
+ if (ifp->clientmgr != NULL)
+ ns_clientmgr_destroy(&ifp->clientmgr);
+}
+
+static void
+ns_interface_destroy(ns_interface_t *ifp) {
+ isc_mem_t *mctx = ifp->mgr->mctx;
+ REQUIRE(NS_INTERFACE_VALID(ifp));
+
+ ns_interface_shutdown(ifp);
+
+ if (ifp->udpdispatch != NULL) {
+ dns_dispatch_changeattributes(ifp->udpdispatch, 0,
+ DNS_DISPATCHATTR_NOLISTEN);
+ dns_dispatch_detach(&ifp->udpdispatch);
+ }
+ if (ifp->tcpsocket != NULL)
+ isc_socket_detach(&ifp->tcpsocket);
+
+ DESTROYLOCK(&ifp->lock);
+
+ ns_interfacemgr_detach(&ifp->mgr);
+
+ ifp->magic = 0;
+ isc_mem_put(mctx, ifp, sizeof(*ifp));
+}
+
+void
+ns_interface_attach(ns_interface_t *source, ns_interface_t **target) {
+ REQUIRE(NS_INTERFACE_VALID(source));
+ LOCK(&source->lock);
+ INSIST(source->references > 0);
+ source->references++;
+ UNLOCK(&source->lock);
+ *target = source;
+}
+
+void
+ns_interface_detach(ns_interface_t **targetp) {
+ isc_result_t need_destroy = ISC_FALSE;
+ ns_interface_t *target = *targetp;
+ REQUIRE(target != NULL);
+ REQUIRE(NS_INTERFACE_VALID(target));
+ LOCK(&target->lock);
+ REQUIRE(target->references > 0);
+ target->references--;
+ if (target->references == 0)
+ need_destroy = ISC_TRUE;
+ UNLOCK(&target->lock);
+ if (need_destroy)
+ ns_interface_destroy(target);
+ *targetp = NULL;
+}
+
+/*%
+ * Search the interface list for an interface whose address and port
+ * both match those of 'addr'. Return a pointer to it, or NULL if not found.
+ */
+static ns_interface_t *
+find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
+ ns_interface_t *ifp;
+ for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL;
+ ifp = ISC_LIST_NEXT(ifp, link)) {
+ if (isc_sockaddr_equal(&ifp->addr, addr))
+ break;
+ }
+ return (ifp);
+}
+
+/*%
+ * Remove any interfaces whose generation number is not the current one.
+ */
+static void
+purge_old_interfaces(ns_interfacemgr_t *mgr) {
+ ns_interface_t *ifp, *next;
+ for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) {
+ INSIST(NS_INTERFACE_VALID(ifp));
+ next = ISC_LIST_NEXT(ifp, link);
+ if (ifp->generation != mgr->generation) {
+ char sabuf[256];
+ ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link);
+ isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf));
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_INFO,
+ "no longer listening on %s", sabuf);
+ ns_interface_shutdown(ifp);
+ ns_interface_detach(&ifp);
+ }
+ }
+}
+
+static isc_result_t
+clearacl(isc_mem_t *mctx, dns_acl_t **aclp) {
+ dns_acl_t *newacl = NULL;
+ isc_result_t result;
+ result = dns_acl_create(mctx, 0, &newacl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_acl_detach(aclp);
+ dns_acl_attach(newacl, aclp);
+ dns_acl_detach(&newacl);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+listenon_is_ip6_any(ns_listenelt_t *elt) {
+ REQUIRE(elt && elt->acl);
+ return dns_acl_isany(elt->acl);
+}
+
+static isc_result_t
+setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
+ isc_result_t result;
+ unsigned int prefixlen;
+ isc_netaddr_t *netaddr;
+
+ netaddr = &interface->address;
+
+ /* First add localhost address */
+ prefixlen = (netaddr->family == AF_INET) ? 32 : 128;
+ result = dns_iptable_addprefix(mgr->aclenv.localhost->iptable,
+ netaddr, prefixlen, ISC_TRUE);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /* Then add localnets prefix */
+ result = isc_netaddr_masktoprefixlen(&interface->netmask,
+ &prefixlen);
+
+ /* Non contigious netmasks not allowed by IPv6 arch. */
+ if (result != ISC_R_SUCCESS && netaddr->family == AF_INET6)
+ return (result);
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_WARNING,
+ "omitting IPv4 interface %s from "
+ "localnets ACL: %s",
+ interface->name,
+ isc_result_totext(result));
+ return (ISC_R_SUCCESS);
+ }
+
+ result = dns_iptable_addprefix(mgr->aclenv.localnets->iptable,
+ netaddr, prefixlen, ISC_TRUE);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+setup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface,
+ in_port_t port)
+{
+ isc_sockaddr_t *addr;
+ isc_sockaddr_t *old;
+
+ addr = isc_mem_get(mgr->mctx, sizeof(*addr));
+ if (addr == NULL)
+ return;
+
+ isc_sockaddr_fromnetaddr(addr, &interface->address, port);
+
+ for (old = ISC_LIST_HEAD(mgr->listenon);
+ old != NULL;
+ old = ISC_LIST_NEXT(old, link))
+ if (isc_sockaddr_equal(addr, old))
+ break;
+
+ if (old != NULL)
+ isc_mem_put(mgr->mctx, addr, sizeof(*addr));
+ else
+ ISC_LIST_APPEND(mgr->listenon, addr, link);
+}
+
+static void
+clearlistenon(ns_interfacemgr_t *mgr) {
+ isc_sockaddr_t *old;
+
+ old = ISC_LIST_HEAD(mgr->listenon);
+ while (old != NULL) {
+ ISC_LIST_UNLINK(mgr->listenon, old, link);
+ isc_mem_put(mgr->mctx, old, sizeof(*old));
+ old = ISC_LIST_HEAD(mgr->listenon);
+ }
+}
+
+static isc_result_t
+do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
+ isc_boolean_t verbose)
+{
+ isc_interfaceiter_t *iter = NULL;
+ isc_boolean_t scan_ipv4 = ISC_FALSE;
+ isc_boolean_t scan_ipv6 = ISC_FALSE;
+ isc_boolean_t adjusting = ISC_FALSE;
+ isc_boolean_t ipv6only = ISC_TRUE;
+ isc_boolean_t ipv6pktinfo = ISC_TRUE;
+ isc_result_t result;
+ isc_netaddr_t zero_address, zero_address6;
+ ns_listenelt_t *le;
+ isc_sockaddr_t listen_addr;
+ ns_interface_t *ifp;
+ isc_boolean_t log_explicit = ISC_FALSE;
+ isc_boolean_t dolistenon;
+
+ if (ext_listen != NULL)
+ adjusting = ISC_TRUE;
+
+ if (isc_net_probeipv6() == ISC_R_SUCCESS)
+ scan_ipv6 = ISC_TRUE;
+#ifdef WANT_IPV6
+ else
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
+ "no IPv6 interfaces found");
+#endif
+
+ if (isc_net_probeipv4() == ISC_R_SUCCESS)
+ scan_ipv4 = ISC_TRUE;
+ else
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
+ "no IPv4 interfaces found");
+
+ /*
+ * A special, but typical case; listen-on-v6 { any; }.
+ * When we can make the socket IPv6-only, open a single wildcard
+ * socket for IPv6 communication. Otherwise, make separate socket
+ * for each IPv6 address in order to avoid accepting IPv4 packets
+ * as the form of mapped addresses unintentionally unless explicitly
+ * allowed.
+ */
+#ifndef ISC_ALLOW_MAPPED
+ if (scan_ipv6 == ISC_TRUE &&
+ isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
+ ipv6only = ISC_FALSE;
+ log_explicit = ISC_TRUE;
+ }
+#endif
+ if (scan_ipv6 == ISC_TRUE &&
+ isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
+ ipv6pktinfo = ISC_FALSE;
+ log_explicit = ISC_TRUE;
+ }
+ if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
+ for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
+ le != NULL;
+ le = ISC_LIST_NEXT(le, link)) {
+ struct in6_addr in6a;
+
+ if (!listenon_is_ip6_any(le))
+ continue;
+
+ in6a = in6addr_any;
+ isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);
+
+ ifp = find_matching_interface(mgr, &listen_addr);
+ if (ifp != NULL) {
+ ifp->generation = mgr->generation;
+ } else {
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_INFO,
+ "listening on IPv6 "
+ "interfaces, port %u",
+ le->port);
+ result = ns_interface_setup(mgr, &listen_addr,
+ "<any>", &ifp,
+ ISC_TRUE);
+ if (result == ISC_R_SUCCESS)
+ ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
+ else
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_ERROR,
+ "listening on all IPv6 "
+ "interfaces failed");
+ /* Continue. */
+ }
+ }
+ }
+
+ isc_netaddr_any(&zero_address);
+ isc_netaddr_any6(&zero_address6);
+
+ result = isc_interfaceiter_create(mgr->mctx, &iter);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (adjusting == ISC_FALSE) {
+ result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_iter;
+ result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_iter;
+ clearlistenon(mgr);
+ }
+
+ for (result = isc_interfaceiter_first(iter);
+ result == ISC_R_SUCCESS;
+ result = isc_interfaceiter_next(iter))
+ {
+ isc_interface_t interface;
+ ns_listenlist_t *ll;
+ unsigned int family;
+
+ result = isc_interfaceiter_current(iter, &interface);
+ if (result != ISC_R_SUCCESS)
+ break;
+
+ family = interface.address.family;
+ if (family != AF_INET && family != AF_INET6)
+ continue;
+ if (scan_ipv4 == ISC_FALSE && family == AF_INET)
+ continue;
+ if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
+ continue;
+
+ /*
+ * Test for the address being nonzero rather than testing
+ * INTERFACE_F_UP, because on some systems the latter
+ * follows the media state and we could end up ignoring
+ * the interface for an entire rescan interval due to
+ * a temporary media glitch at rescan time.
+ */
+ if (family == AF_INET &&
+ isc_netaddr_equal(&interface.address, &zero_address)) {
+ continue;
+ }
+ if (family == AF_INET6 &&
+ isc_netaddr_equal(&interface.address, &zero_address6)) {
+ continue;
+ }
+
+ if (adjusting == ISC_FALSE) {
+ result = setup_locals(mgr, &interface);
+ if (result != ISC_R_SUCCESS)
+ goto ignore_interface;
+ }
+
+ ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
+ dolistenon = ISC_TRUE;
+ for (le = ISC_LIST_HEAD(ll->elts);
+ le != NULL;
+ le = ISC_LIST_NEXT(le, link))
+ {
+ int match;
+ isc_boolean_t ipv6_wildcard = ISC_FALSE;
+ isc_netaddr_t listen_netaddr;
+ isc_sockaddr_t listen_sockaddr;
+
+ /*
+ * Construct a socket address for this IP/port
+ * combination.
+ */
+ if (family == AF_INET) {
+ isc_netaddr_fromin(&listen_netaddr,
+ &interface.address.type.in);
+ } else {
+ isc_netaddr_fromin6(&listen_netaddr,
+ &interface.address.type.in6);
+ isc_netaddr_setzone(&listen_netaddr,
+ interface.address.zone);
+ }
+ isc_sockaddr_fromnetaddr(&listen_sockaddr,
+ &listen_netaddr,
+ le->port);
+
+ /*
+ * See if the address matches the listen-on statement;
+ * if not, ignore the interface.
+ */
+ (void)dns_acl_match(&listen_netaddr, NULL, le->acl,
+ &mgr->aclenv, &match, NULL);
+ if (match <= 0)
+ continue;
+
+ if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) {
+ setup_listenon(mgr, &interface, le->port);
+ dolistenon = ISC_FALSE;
+ }
+
+ /*
+ * The case of "any" IPv6 address will require
+ * special considerations later, so remember it.
+ */
+ if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
+ listenon_is_ip6_any(le))
+ ipv6_wildcard = ISC_TRUE;
+
+ /*
+ * When adjusting interfaces with extra a listening
+ * list, see if the address matches the extra list.
+ * If it does, and is also covered by a wildcard
+ * interface, we need to listen on the address
+ * explicitly.
+ */
+ if (adjusting == ISC_TRUE) {
+ ns_listenelt_t *ele;
+
+ match = 0;
+ for (ele = ISC_LIST_HEAD(ext_listen->elts);
+ ele != NULL;
+ ele = ISC_LIST_NEXT(ele, link)) {
+ (void)dns_acl_match(&listen_netaddr,
+ NULL, ele->acl,
+ NULL, &match, NULL);
+ if (match > 0 &&
+ (ele->port == le->port ||
+ ele->port == 0))
+ break;
+ else
+ match = 0;
+ }
+ if (ipv6_wildcard == ISC_TRUE && match == 0)
+ continue;
+ }
+
+ ifp = find_matching_interface(mgr, &listen_sockaddr);
+ if (ifp != NULL) {
+ ifp->generation = mgr->generation;
+ } else {
+ char sabuf[ISC_SOCKADDR_FORMATSIZE];
+
+ if (adjusting == ISC_FALSE &&
+ ipv6_wildcard == ISC_TRUE)
+ continue;
+
+ if (log_explicit && family == AF_INET6 &&
+ !adjusting && listenon_is_ip6_any(le)) {
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ verbose ? ISC_LOG_INFO :
+ ISC_LOG_DEBUG(1),
+ "IPv6 socket API is "
+ "incomplete; explicitly "
+ "binding to each IPv6 "
+ "address separately");
+ log_explicit = ISC_FALSE;
+ }
+ isc_sockaddr_format(&listen_sockaddr,
+ sabuf, sizeof(sabuf));
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_INFO,
+ "%s"
+ "listening on %s interface "
+ "%s, %s",
+ (adjusting == ISC_TRUE) ?
+ "additionally " : "",
+ (family == AF_INET) ?
+ "IPv4" : "IPv6",
+ interface.name, sabuf);
+
+ result = ns_interface_setup(mgr,
+ &listen_sockaddr,
+ interface.name,
+ &ifp,
+ (adjusting == ISC_TRUE) ?
+ ISC_FALSE :
+ ISC_TRUE);
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_ERROR,
+ "creating %s interface "
+ "%s failed; interface "
+ "ignored",
+ (family == AF_INET) ?
+ "IPv4" : "IPv6",
+ interface.name);
+ }
+ /* Continue. */
+ }
+
+ }
+ continue;
+
+ ignore_interface:
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ ISC_LOG_ERROR,
+ "ignoring %s interface %s: %s",
+ (family == AF_INET) ? "IPv4" : "IPv6",
+ interface.name, isc_result_totext(result));
+ continue;
+ }
+ if (result != ISC_R_NOMORE)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "interface iteration failed: %s",
+ isc_result_totext(result));
+ else
+ result = ISC_R_SUCCESS;
+ cleanup_iter:
+ isc_interfaceiter_destroy(&iter);
+ return (result);
+}
+
+static void
+ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
+ isc_boolean_t verbose)
+{
+ isc_boolean_t purge = ISC_TRUE;
+
+ REQUIRE(NS_INTERFACEMGR_VALID(mgr));
+
+ mgr->generation++; /* Increment the generation count. */
+
+ if (do_scan(mgr, ext_listen, verbose) != ISC_R_SUCCESS)
+ purge = ISC_FALSE;
+
+ /*
+ * Now go through the interface list and delete anything that
+ * does not have the current generation number. This is
+ * how we catch interfaces that go away or change their
+ * addresses.
+ */
+ if (purge)
+ purge_old_interfaces(mgr);
+
+ /*
+ * Warn if we are not listening on any interface, unless
+ * we're in lwresd-only mode, in which case that is to
+ * be expected.
+ */
+ if (ext_listen == NULL &&
+ ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) {
+ isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING,
+ "not listening on any interfaces");
+ }
+}
+
+void
+ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) {
+ ns_interfacemgr_scan0(mgr, NULL, verbose);
+}
+
+void
+ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list,
+ isc_boolean_t verbose)
+{
+ ns_interfacemgr_scan0(mgr, list, verbose);
+}
+
+void
+ns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
+ LOCK(&mgr->lock);
+ ns_listenlist_detach(&mgr->listenon4);
+ ns_listenlist_attach(value, &mgr->listenon4);
+ UNLOCK(&mgr->lock);
+}
+
+void
+ns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) {
+ LOCK(&mgr->lock);
+ ns_listenlist_detach(&mgr->listenon6);
+ ns_listenlist_attach(value, &mgr->listenon6);
+ UNLOCK(&mgr->lock);
+}
+
+void
+ns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) {
+ ns_interface_t *interface;
+
+ LOCK(&mgr->lock);
+ interface = ISC_LIST_HEAD(mgr->interfaces);
+ while (interface != NULL) {
+ if (interface->clientmgr != NULL)
+ ns_client_dumprecursing(f, interface->clientmgr);
+ interface = ISC_LIST_NEXT(interface, link);
+ }
+ UNLOCK(&mgr->lock);
+}
+
+isc_boolean_t
+ns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) {
+ isc_sockaddr_t *old;
+
+ old = ISC_LIST_HEAD(mgr->listenon);
+ for (old = ISC_LIST_HEAD(mgr->listenon);
+ old != NULL;
+ old = ISC_LIST_NEXT(old, link))
+ if (isc_sockaddr_equal(old, addr))
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
diff --git a/bin/named/listenlist.c b/bin/named/listenlist.c
new file mode 100644
index 0000000..513fe9c
--- /dev/null
+++ b/bin/named/listenlist.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: listenlist.c,v 1.14 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+
+#include <named/listenlist.h>
+
+static void
+destroy(ns_listenlist_t *list);
+
+isc_result_t
+ns_listenelt_create(isc_mem_t *mctx, in_port_t port,
+ dns_acl_t *acl, ns_listenelt_t **target)
+{
+ ns_listenelt_t *elt = NULL;
+ REQUIRE(target != NULL && *target == NULL);
+ elt = isc_mem_get(mctx, sizeof(*elt));
+ if (elt == NULL)
+ return (ISC_R_NOMEMORY);
+ elt->mctx = mctx;
+ ISC_LINK_INIT(elt, link);
+ elt->port = port;
+ elt->acl = acl;
+ *target = elt;
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_listenelt_destroy(ns_listenelt_t *elt) {
+ if (elt->acl != NULL)
+ dns_acl_detach(&elt->acl);
+ isc_mem_put(elt->mctx, elt, sizeof(*elt));
+}
+
+isc_result_t
+ns_listenlist_create(isc_mem_t *mctx, ns_listenlist_t **target) {
+ ns_listenlist_t *list = NULL;
+ REQUIRE(target != NULL && *target == NULL);
+ list = isc_mem_get(mctx, sizeof(*list));
+ if (list == NULL)
+ return (ISC_R_NOMEMORY);
+ list->mctx = mctx;
+ list->refcount = 1;
+ ISC_LIST_INIT(list->elts);
+ *target = list;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+destroy(ns_listenlist_t *list) {
+ ns_listenelt_t *elt, *next;
+ for (elt = ISC_LIST_HEAD(list->elts);
+ elt != NULL;
+ elt = next)
+ {
+ next = ISC_LIST_NEXT(elt, link);
+ ns_listenelt_destroy(elt);
+ }
+ isc_mem_put(list->mctx, list, sizeof(*list));
+}
+
+void
+ns_listenlist_attach(ns_listenlist_t *source, ns_listenlist_t **target) {
+ INSIST(source->refcount > 0);
+ source->refcount++;
+ *target = source;
+}
+
+void
+ns_listenlist_detach(ns_listenlist_t **listp) {
+ ns_listenlist_t *list = *listp;
+ INSIST(list->refcount > 0);
+ list->refcount--;
+ if (list->refcount == 0)
+ destroy(list);
+ *listp = NULL;
+}
+
+isc_result_t
+ns_listenlist_default(isc_mem_t *mctx, in_port_t port,
+ isc_boolean_t enabled, ns_listenlist_t **target)
+{
+ isc_result_t result;
+ dns_acl_t *acl = NULL;
+ ns_listenelt_t *elt = NULL;
+ ns_listenlist_t *list = NULL;
+
+ REQUIRE(target != NULL && *target == NULL);
+ if (enabled)
+ result = dns_acl_any(mctx, &acl);
+ else
+ result = dns_acl_none(mctx, &acl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = ns_listenelt_create(mctx, port, acl, &elt);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_acl;
+
+ result = ns_listenlist_create(mctx, &list);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_listenelt;
+
+ ISC_LIST_APPEND(list->elts, elt, link);
+
+ *target = list;
+ return (ISC_R_SUCCESS);
+
+ cleanup_listenelt:
+ ns_listenelt_destroy(elt);
+ cleanup_acl:
+ dns_acl_detach(&acl);
+ cleanup:
+ return (result);
+}
diff --git a/bin/named/log.c b/bin/named/log.c
new file mode 100644
index 0000000..fdb4e0c
--- /dev/null
+++ b/bin/named/log.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: log.c,v 1.46 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/result.h>
+
+#include <isccfg/log.h>
+
+#include <named/log.h>
+
+#ifndef ISC_FACILITY
+#define ISC_FACILITY LOG_DAEMON
+#endif
+
+/*%
+ * When adding a new category, be sure to add the appropriate
+ * \#define to <named/log.h> and to update the list in
+ * bin/check/check-tool.c.
+ */
+static isc_logcategory_t categories[] = {
+ { "", 0 },
+ { "client", 0 },
+ { "network", 0 },
+ { "update", 0 },
+ { "queries", 0 },
+ { "unmatched", 0 },
+ { "update-security", 0 },
+ { NULL, 0 }
+};
+
+/*%
+ * When adding a new module, be sure to add the appropriate
+ * \#define to <dns/log.h>.
+ */
+static isc_logmodule_t modules[] = {
+ { "main", 0 },
+ { "client", 0 },
+ { "server", 0 },
+ { "query", 0 },
+ { "interfacemgr", 0 },
+ { "update", 0 },
+ { "xfer-in", 0 },
+ { "xfer-out", 0 },
+ { "notify", 0 },
+ { "control", 0 },
+ { "lwresd", 0 },
+ { NULL, 0 }
+};
+
+isc_result_t
+ns_log_init(isc_boolean_t safe) {
+ isc_result_t result;
+ isc_logconfig_t *lcfg = NULL;
+
+ ns_g_categories = categories;
+ ns_g_modules = modules;
+
+ /*
+ * Setup a logging context.
+ */
+ result = isc_log_create(ns_g_mctx, &ns_g_lctx, &lcfg);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * named-checktool.c:setup_logging() needs to be kept in sync.
+ */
+ isc_log_registercategories(ns_g_lctx, ns_g_categories);
+ isc_log_registermodules(ns_g_lctx, ns_g_modules);
+ isc_log_setcontext(ns_g_lctx);
+ dns_log_init(ns_g_lctx);
+ dns_log_setcontext(ns_g_lctx);
+ cfg_log_init(ns_g_lctx);
+
+ if (safe)
+ result = ns_log_setsafechannels(lcfg);
+ else
+ result = ns_log_setdefaultchannels(lcfg);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = ns_log_setdefaultcategory(lcfg);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_log_destroy(&ns_g_lctx);
+ isc_log_setcontext(NULL);
+ dns_log_setcontext(NULL);
+
+ return (result);
+}
+
+isc_result_t
+ns_log_setdefaultchannels(isc_logconfig_t *lcfg) {
+ isc_result_t result;
+ isc_logdestination_t destination;
+
+ /*
+ * By default, the logging library makes "default_debug" log to
+ * stderr. In BIND, we want to override this and log to named.run
+ * instead, unless the the -g option was given.
+ */
+ if (! ns_g_logstderr) {
+ destination.file.stream = NULL;
+ destination.file.name = "named.run";
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(lcfg, "default_debug",
+ ISC_LOG_TOFILE,
+ ISC_LOG_DYNAMIC,
+ &destination,
+ ISC_LOG_PRINTTIME|
+ ISC_LOG_DEBUGONLY);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+#if ISC_FACILITY != LOG_DAEMON
+ destination.facility = ISC_FACILITY;
+ result = isc_log_createchannel(lcfg, "default_syslog",
+ ISC_LOG_TOSYSLOG, ISC_LOG_INFO,
+ &destination, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+#endif
+
+ /*
+ * Set the initial debug level.
+ */
+ isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ return (result);
+}
+
+isc_result_t
+ns_log_setsafechannels(isc_logconfig_t *lcfg) {
+ isc_result_t result;
+#if ISC_FACILITY != LOG_DAEMON
+ isc_logdestination_t destination;
+#endif
+
+ if (! ns_g_logstderr) {
+ result = isc_log_createchannel(lcfg, "default_debug",
+ ISC_LOG_TONULL,
+ ISC_LOG_DYNAMIC,
+ NULL, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * Setting the debug level to zero should get the output
+ * discarded a bit faster.
+ */
+ isc_log_setdebuglevel(ns_g_lctx, 0);
+ } else {
+ isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
+ }
+
+#if ISC_FACILITY != LOG_DAEMON
+ destination.facility = ISC_FACILITY;
+ result = isc_log_createchannel(lcfg, "default_syslog",
+ ISC_LOG_TOSYSLOG, ISC_LOG_INFO,
+ &destination, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+#endif
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ return (result);
+}
+
+isc_result_t
+ns_log_setdefaultcategory(isc_logconfig_t *lcfg) {
+ isc_result_t result;
+
+ if (! ns_g_logstderr) {
+ result = isc_log_usechannel(lcfg, "default_syslog",
+ ISC_LOGCATEGORY_DEFAULT, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ result = isc_log_usechannel(lcfg, "default_debug",
+ ISC_LOGCATEGORY_DEFAULT, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ return (result);
+}
+
+isc_result_t
+ns_log_setunmatchedcategory(isc_logconfig_t *lcfg) {
+ isc_result_t result;
+
+ result = isc_log_usechannel(lcfg, "null",
+ NS_LOGCATEGORY_UNMATCHED, NULL);
+ return (result);
+}
+
+void
+ns_log_shutdown(void) {
+ isc_log_destroy(&ns_g_lctx);
+ isc_log_setcontext(NULL);
+ dns_log_setcontext(NULL);
+}
diff --git a/bin/named/logconf.c b/bin/named/logconf.c
new file mode 100644
index 0000000..e324965
--- /dev/null
+++ b/bin/named/logconf.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: logconf.c,v 1.42 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/offset.h>
+#include <isc/result.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/syslog.h>
+
+#include <isccfg/cfg.h>
+#include <isccfg/log.h>
+
+#include <named/log.h>
+#include <named/logconf.h>
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto cleanup; \
+ } while (0)
+
+/*%
+ * Set up a logging category according to the named.conf data
+ * in 'ccat' and add it to 'lctx'.
+ */
+static isc_result_t
+category_fromconf(const cfg_obj_t *ccat, isc_logconfig_t *lctx) {
+ isc_result_t result;
+ const char *catname;
+ isc_logcategory_t *category;
+ isc_logmodule_t *module;
+ const cfg_obj_t *destinations = NULL;
+ const cfg_listelt_t *element = NULL;
+
+ catname = cfg_obj_asstring(cfg_tuple_get(ccat, "name"));
+ category = isc_log_categorybyname(ns_g_lctx, catname);
+ if (category == NULL) {
+ cfg_obj_log(ccat, ns_g_lctx, ISC_LOG_ERROR,
+ "unknown logging category '%s' ignored",
+ catname);
+ /*
+ * Allow further processing by returning success.
+ */
+ return (ISC_R_SUCCESS);
+ }
+
+ module = NULL;
+
+ destinations = cfg_tuple_get(ccat, "destinations");
+ for (element = cfg_list_first(destinations);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *channel = cfg_listelt_value(element);
+ const char *channelname = cfg_obj_asstring(channel);
+
+ result = isc_log_usechannel(lctx, channelname, category,
+ module);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, CFG_LOGCATEGORY_CONFIG,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "logging channel '%s': %s", channelname,
+ isc_result_totext(result));
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Set up a logging channel according to the named.conf data
+ * in 'cchan' and add it to 'lctx'.
+ */
+static isc_result_t
+channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *lctx) {
+ isc_result_t result;
+ isc_logdestination_t dest;
+ unsigned int type;
+ unsigned int flags = 0;
+ int level;
+ const char *channelname;
+ const cfg_obj_t *fileobj = NULL;
+ const cfg_obj_t *syslogobj = NULL;
+ const cfg_obj_t *nullobj = NULL;
+ const cfg_obj_t *stderrobj = NULL;
+ const cfg_obj_t *severity = NULL;
+ int i;
+
+ channelname = cfg_obj_asstring(cfg_map_getname(channel));
+
+ (void)cfg_map_get(channel, "file", &fileobj);
+ (void)cfg_map_get(channel, "syslog", &syslogobj);
+ (void)cfg_map_get(channel, "null", &nullobj);
+ (void)cfg_map_get(channel, "stderr", &stderrobj);
+
+ i = 0;
+ if (fileobj != NULL)
+ i++;
+ if (syslogobj != NULL)
+ i++;
+ if (nullobj != NULL)
+ i++;
+ if (stderrobj != NULL)
+ i++;
+
+ if (i != 1) {
+ cfg_obj_log(channel, ns_g_lctx, ISC_LOG_ERROR,
+ "channel '%s': exactly one of file, syslog, "
+ "null, and stderr must be present", channelname);
+ return (ISC_R_FAILURE);
+ }
+
+ type = ISC_LOG_TONULL;
+
+ if (fileobj != NULL) {
+ const cfg_obj_t *pathobj = cfg_tuple_get(fileobj, "file");
+ const cfg_obj_t *sizeobj = cfg_tuple_get(fileobj, "size");
+ const cfg_obj_t *versionsobj =
+ cfg_tuple_get(fileobj, "versions");
+ isc_int32_t versions = ISC_LOG_ROLLNEVER;
+ isc_offset_t size = 0;
+
+ type = ISC_LOG_TOFILE;
+
+ if (versionsobj != NULL && cfg_obj_isuint32(versionsobj))
+ versions = cfg_obj_asuint32(versionsobj);
+ if (versionsobj != NULL && cfg_obj_isstring(versionsobj) &&
+ strcasecmp(cfg_obj_asstring(versionsobj), "unlimited") == 0)
+ versions = ISC_LOG_ROLLINFINITE;
+ if (sizeobj != NULL &&
+ cfg_obj_isuint64(sizeobj) &&
+ cfg_obj_asuint64(sizeobj) < ISC_OFFSET_MAXIMUM)
+ size = (isc_offset_t)cfg_obj_asuint64(sizeobj);
+ dest.file.stream = NULL;
+ dest.file.name = cfg_obj_asstring(pathobj);
+ dest.file.versions = versions;
+ dest.file.maximum_size = size;
+ } else if (syslogobj != NULL) {
+ int facility = LOG_DAEMON;
+
+ type = ISC_LOG_TOSYSLOG;
+
+ if (cfg_obj_isstring(syslogobj)) {
+ const char *facilitystr = cfg_obj_asstring(syslogobj);
+ (void)isc_syslog_facilityfromstring(facilitystr,
+ &facility);
+ }
+ dest.facility = facility;
+ } else if (stderrobj != NULL) {
+ type = ISC_LOG_TOFILEDESC;
+ dest.file.stream = stderr;
+ dest.file.name = NULL;
+ dest.file.versions = ISC_LOG_ROLLNEVER;
+ dest.file.maximum_size = 0;
+ }
+
+ /*
+ * Munge flags.
+ */
+ {
+ const cfg_obj_t *printcat = NULL;
+ const cfg_obj_t *printsev = NULL;
+ const cfg_obj_t *printtime = NULL;
+
+ (void)cfg_map_get(channel, "print-category", &printcat);
+ (void)cfg_map_get(channel, "print-severity", &printsev);
+ (void)cfg_map_get(channel, "print-time", &printtime);
+
+ if (printcat != NULL && cfg_obj_asboolean(printcat))
+ flags |= ISC_LOG_PRINTCATEGORY;
+ if (printtime != NULL && cfg_obj_asboolean(printtime))
+ flags |= ISC_LOG_PRINTTIME;
+ if (printsev != NULL && cfg_obj_asboolean(printsev))
+ flags |= ISC_LOG_PRINTLEVEL;
+ }
+
+ level = ISC_LOG_INFO;
+ if (cfg_map_get(channel, "severity", &severity) == ISC_R_SUCCESS) {
+ if (cfg_obj_isstring(severity)) {
+ const char *str = cfg_obj_asstring(severity);
+ if (strcasecmp(str, "critical") == 0)
+ level = ISC_LOG_CRITICAL;
+ else if (strcasecmp(str, "error") == 0)
+ level = ISC_LOG_ERROR;
+ else if (strcasecmp(str, "warning") == 0)
+ level = ISC_LOG_WARNING;
+ else if (strcasecmp(str, "notice") == 0)
+ level = ISC_LOG_NOTICE;
+ else if (strcasecmp(str, "info") == 0)
+ level = ISC_LOG_INFO;
+ else if (strcasecmp(str, "dynamic") == 0)
+ level = ISC_LOG_DYNAMIC;
+ } else
+ /* debug */
+ level = cfg_obj_asuint32(severity);
+ }
+
+ result = isc_log_createchannel(lctx, channelname,
+ type, level, &dest, flags);
+
+ if (result == ISC_R_SUCCESS && type == ISC_LOG_TOFILE) {
+ FILE *fp;
+
+ /*
+ * Test that the file can be opened, since isc_log_open()
+ * can't effectively report failures when called in
+ * isc_log_doit().
+ */
+ result = isc_stdio_open(dest.file.name, "a", &fp);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, CFG_LOGCATEGORY_CONFIG,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "logging channel '%s' file '%s': %s",
+ channelname, dest.file.name,
+ isc_result_totext(result));
+ else
+ (void)isc_stdio_close(fp);
+
+ /*
+ * Allow named to continue by returning success.
+ */
+ result = ISC_R_SUCCESS;
+ }
+
+ return (result);
+}
+
+isc_result_t
+ns_log_configure(isc_logconfig_t *logconf, const cfg_obj_t *logstmt) {
+ isc_result_t result;
+ const cfg_obj_t *channels = NULL;
+ const cfg_obj_t *categories = NULL;
+ const cfg_listelt_t *element;
+ isc_boolean_t default_set = ISC_FALSE;
+ isc_boolean_t unmatched_set = ISC_FALSE;
+ const cfg_obj_t *catname;
+
+ CHECK(ns_log_setdefaultchannels(logconf));
+
+ (void)cfg_map_get(logstmt, "channel", &channels);
+ for (element = cfg_list_first(channels);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *channel = cfg_listelt_value(element);
+ CHECK(channel_fromconf(channel, logconf));
+ }
+
+ (void)cfg_map_get(logstmt, "category", &categories);
+ for (element = cfg_list_first(categories);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *category = cfg_listelt_value(element);
+ CHECK(category_fromconf(category, logconf));
+ if (!default_set) {
+ catname = cfg_tuple_get(category, "name");
+ if (strcmp(cfg_obj_asstring(catname), "default") == 0)
+ default_set = ISC_TRUE;
+ }
+ if (!unmatched_set) {
+ catname = cfg_tuple_get(category, "name");
+ if (strcmp(cfg_obj_asstring(catname), "unmatched") == 0)
+ unmatched_set = ISC_TRUE;
+ }
+ }
+
+ if (!default_set)
+ CHECK(ns_log_setdefaultcategory(logconf));
+
+ if (!unmatched_set)
+ CHECK(ns_log_setunmatchedcategory(logconf));
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (logconf != NULL)
+ isc_logconfig_destroy(&logconf);
+ return (result);
+}
diff --git a/bin/named/lwaddr.c b/bin/named/lwaddr.c
new file mode 100644
index 0000000..ed7880a
--- /dev/null
+++ b/bin/named/lwaddr.c
@@ -0,0 +1,94 @@
+/*
+ * 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
+ * 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: lwaddr.c,v 1.10 2008/01/11 23:46:56 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/result.h>
+#include <isc/netaddr.h>
+#include <isc/sockaddr.h>
+
+#include <lwres/lwres.h>
+
+#include <named/lwaddr.h>
+
+/*%
+ * Convert addresses from lwres to isc format.
+ */
+isc_result_t
+lwaddr_netaddr_fromlwresaddr(isc_netaddr_t *na, lwres_addr_t *la) {
+ if (la->family != LWRES_ADDRTYPE_V4 && la->family != LWRES_ADDRTYPE_V6)
+ return (ISC_R_FAMILYNOSUPPORT);
+
+ if (la->family == LWRES_ADDRTYPE_V4) {
+ struct in_addr ina;
+ memcpy(&ina.s_addr, la->address, 4);
+ isc_netaddr_fromin(na, &ina);
+ } else {
+ struct in6_addr ina6;
+ memcpy(&ina6.s6_addr, la->address, 16);
+ isc_netaddr_fromin6(na, &ina6);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+lwaddr_sockaddr_fromlwresaddr(isc_sockaddr_t *sa, lwres_addr_t *la,
+ in_port_t port)
+{
+ isc_netaddr_t na;
+ isc_result_t result;
+
+ result = lwaddr_netaddr_fromlwresaddr(&na, la);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_sockaddr_fromnetaddr(sa, &na, port);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Convert addresses from isc to lwres format.
+ */
+
+isc_result_t
+lwaddr_lwresaddr_fromnetaddr(lwres_addr_t *la, isc_netaddr_t *na) {
+ if (na->family != AF_INET && na->family != AF_INET6)
+ return (ISC_R_FAMILYNOSUPPORT);
+
+ if (na->family == AF_INET) {
+ la->family = LWRES_ADDRTYPE_V4;
+ la->length = 4;
+ memcpy(la->address, &na->type.in, 4);
+ } else {
+ la->family = LWRES_ADDRTYPE_V6;
+ la->length = 16;
+ memcpy(la->address, &na->type.in6, 16);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+lwaddr_lwresaddr_fromsockaddr(lwres_addr_t *la, isc_sockaddr_t *sa) {
+ isc_netaddr_t na;
+ isc_netaddr_fromsockaddr(&na, sa);
+ return (lwaddr_lwresaddr_fromnetaddr(la, &na));
+}
diff --git a/bin/named/lwdclient.c b/bin/named/lwdclient.c
new file mode 100644
index 0000000..a843134
--- /dev/null
+++ b/bin/named/lwdclient.c
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwdclient.c,v 1.22 2007/06/18 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/view.h>
+#include <dns/log.h>
+
+#include <named/types.h>
+#include <named/log.h>
+#include <named/lwresd.h>
+#include <named/lwdclient.h>
+
+#define SHUTTINGDOWN(cm) ((cm->flags & NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN) != 0)
+
+static void
+lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev);
+
+void
+ns_lwdclient_log(int level, const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ isc_log_vwrite(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
+ ISC_LOG_DEBUG(level), format, args);
+ va_end(args);
+}
+
+isc_result_t
+ns_lwdclientmgr_create(ns_lwreslistener_t *listener, unsigned int nclients,
+ isc_taskmgr_t *taskmgr)
+{
+ ns_lwresd_t *lwresd = listener->manager;
+ ns_lwdclientmgr_t *cm;
+ ns_lwdclient_t *client;
+ unsigned int i;
+ isc_result_t result = ISC_R_FAILURE;
+
+ cm = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclientmgr_t));
+ if (cm == NULL)
+ return (ISC_R_NOMEMORY);
+
+ cm->listener = NULL;
+ ns_lwreslistener_attach(listener, &cm->listener);
+ cm->mctx = lwresd->mctx;
+ cm->sock = NULL;
+ isc_socket_attach(listener->sock, &cm->sock);
+ cm->view = lwresd->view;
+ cm->lwctx = NULL;
+ cm->task = NULL;
+ cm->flags = 0;
+ ISC_LINK_INIT(cm, link);
+ ISC_LIST_INIT(cm->idle);
+ ISC_LIST_INIT(cm->running);
+
+ if (lwres_context_create(&cm->lwctx, cm->mctx,
+ ns__lwresd_memalloc, ns__lwresd_memfree,
+ LWRES_CONTEXT_SERVERMODE)
+ != ISC_R_SUCCESS)
+ goto errout;
+
+ for (i = 0; i < nclients; i++) {
+ client = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclient_t));
+ if (client != NULL) {
+ ns_lwdclient_log(50, "created client %p, manager %p",
+ client, cm);
+ ns_lwdclient_initialize(client, cm);
+ }
+ }
+
+ /*
+ * If we could create no clients, clean up and return.
+ */
+ if (ISC_LIST_EMPTY(cm->idle))
+ goto errout;
+
+ result = isc_task_create(taskmgr, 0, &cm->task);
+ if (result != ISC_R_SUCCESS)
+ goto errout;
+ isc_task_setname(cm->task, "lwdclient", NULL);
+
+ /*
+ * This MUST be last, since there is no way to cancel an onshutdown...
+ */
+ result = isc_task_onshutdown(cm->task, lwdclientmgr_shutdown_callback,
+ cm);
+ if (result != ISC_R_SUCCESS)
+ goto errout;
+
+ ns_lwreslistener_linkcm(listener, cm);
+
+ return (ISC_R_SUCCESS);
+
+ errout:
+ client = ISC_LIST_HEAD(cm->idle);
+ while (client != NULL) {
+ ISC_LIST_UNLINK(cm->idle, client, link);
+ isc_mem_put(lwresd->mctx, client, sizeof(*client));
+ client = ISC_LIST_HEAD(cm->idle);
+ }
+
+ if (cm->task != NULL)
+ isc_task_detach(&cm->task);
+
+ if (cm->lwctx != NULL)
+ lwres_context_destroy(&cm->lwctx);
+
+ isc_mem_put(lwresd->mctx, cm, sizeof(*cm));
+ return (result);
+}
+
+static void
+lwdclientmgr_destroy(ns_lwdclientmgr_t *cm) {
+ ns_lwdclient_t *client;
+ ns_lwreslistener_t *listener;
+
+ if (!SHUTTINGDOWN(cm))
+ return;
+
+ /*
+ * run through the idle list and free the clients there. Idle
+ * clients do not have a recv running nor do they have any finds
+ * or similar running.
+ */
+ client = ISC_LIST_HEAD(cm->idle);
+ while (client != NULL) {
+ ns_lwdclient_log(50, "destroying client %p, manager %p",
+ client, cm);
+ ISC_LIST_UNLINK(cm->idle, client, link);
+ isc_mem_put(cm->mctx, client, sizeof(*client));
+ client = ISC_LIST_HEAD(cm->idle);
+ }
+
+ if (!ISC_LIST_EMPTY(cm->running))
+ return;
+
+ lwres_context_destroy(&cm->lwctx);
+ cm->view = NULL;
+ isc_socket_detach(&cm->sock);
+ isc_task_detach(&cm->task);
+
+ listener = cm->listener;
+ ns_lwreslistener_unlinkcm(listener, cm);
+ ns_lwdclient_log(50, "destroying manager %p", cm);
+ isc_mem_put(cm->mctx, cm, sizeof(*cm));
+ ns_lwreslistener_detach(&listener);
+}
+
+static void
+process_request(ns_lwdclient_t *client) {
+ lwres_buffer_t b;
+ isc_result_t result;
+
+ lwres_buffer_init(&b, client->buffer, client->recvlength);
+ lwres_buffer_add(&b, client->recvlength);
+
+ result = lwres_lwpacket_parseheader(&b, &client->pkt);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwdclient_log(50, "invalid packet header received");
+ goto restart;
+ }
+
+ ns_lwdclient_log(50, "opcode %08x", client->pkt.opcode);
+
+ switch (client->pkt.opcode) {
+ case LWRES_OPCODE_GETADDRSBYNAME:
+ ns_lwdclient_processgabn(client, &b);
+ return;
+ case LWRES_OPCODE_GETNAMEBYADDR:
+ ns_lwdclient_processgnba(client, &b);
+ return;
+ case LWRES_OPCODE_GETRDATABYNAME:
+ ns_lwdclient_processgrbn(client, &b);
+ return;
+ case LWRES_OPCODE_NOOP:
+ ns_lwdclient_processnoop(client, &b);
+ return;
+ default:
+ ns_lwdclient_log(50, "unknown opcode %08x", client->pkt.opcode);
+ goto restart;
+ }
+
+ /*
+ * Drop the packet.
+ */
+ restart:
+ ns_lwdclient_log(50, "restarting client %p...", client);
+ ns_lwdclient_stateidle(client);
+}
+
+void
+ns_lwdclient_recv(isc_task_t *task, isc_event_t *ev) {
+ isc_result_t result;
+ ns_lwdclient_t *client = ev->ev_arg;
+ ns_lwdclientmgr_t *cm = client->clientmgr;
+ isc_socketevent_t *dev = (isc_socketevent_t *)ev;
+
+ INSIST(dev->region.base == client->buffer);
+ INSIST(NS_LWDCLIENT_ISRECV(client));
+
+ NS_LWDCLIENT_SETRECVDONE(client);
+
+ INSIST((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0);
+ cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING;
+
+ ns_lwdclient_log(50,
+ "event received: task %p, length %u, result %u (%s)",
+ task, dev->n, dev->result,
+ isc_result_totext(dev->result));
+
+ if (dev->result != ISC_R_SUCCESS) {
+ isc_event_free(&ev);
+ dev = NULL;
+
+ /*
+ * Go idle.
+ */
+ ns_lwdclient_stateidle(client);
+
+ return;
+ }
+
+ client->recvlength = dev->n;
+ client->address = dev->address;
+ if ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
+ client->pktinfo = dev->pktinfo;
+ client->pktinfo_valid = ISC_TRUE;
+ } else
+ client->pktinfo_valid = ISC_FALSE;
+ isc_event_free(&ev);
+ dev = NULL;
+
+ result = ns_lwdclient_startrecv(cm);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
+ "could not start lwres "
+ "client handler: %s",
+ isc_result_totext(result));
+
+ process_request(client);
+}
+
+/*
+ * This function will start a new recv() on a socket for this client manager.
+ */
+isc_result_t
+ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) {
+ ns_lwdclient_t *client;
+ isc_result_t result;
+ isc_region_t r;
+
+ if (SHUTTINGDOWN(cm)) {
+ lwdclientmgr_destroy(cm);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * If a recv is already running, don't bother.
+ */
+ if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0)
+ return (ISC_R_SUCCESS);
+
+ /*
+ * If we have no idle slots, just return success.
+ */
+ client = ISC_LIST_HEAD(cm->idle);
+ if (client == NULL)
+ return (ISC_R_SUCCESS);
+ INSIST(NS_LWDCLIENT_ISIDLE(client));
+
+ /*
+ * Issue the recv. If it fails, return that it did.
+ */
+ r.base = client->buffer;
+ r.length = LWRES_RECVLENGTH;
+ result = isc_socket_recv(cm->sock, &r, 0, cm->task, ns_lwdclient_recv,
+ client);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Set the flag to say we've issued a recv() call.
+ */
+ cm->flags |= NS_LWDCLIENTMGR_FLAGRECVPENDING;
+
+ /*
+ * Remove the client from the idle list, and put it on the running
+ * list.
+ */
+ NS_LWDCLIENT_SETRECV(client);
+ ISC_LIST_UNLINK(cm->idle, client, link);
+ ISC_LIST_APPEND(cm->running, client, link);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev) {
+ ns_lwdclientmgr_t *cm = ev->ev_arg;
+ ns_lwdclient_t *client;
+
+ REQUIRE(!SHUTTINGDOWN(cm));
+
+ ns_lwdclient_log(50, "got shutdown event, task %p, lwdclientmgr %p",
+ task, cm);
+
+ /*
+ * run through the idle list and free the clients there. Idle
+ * clients do not have a recv running nor do they have any finds
+ * or similar running.
+ */
+ client = ISC_LIST_HEAD(cm->idle);
+ while (client != NULL) {
+ ns_lwdclient_log(50, "destroying client %p, manager %p",
+ client, cm);
+ ISC_LIST_UNLINK(cm->idle, client, link);
+ isc_mem_put(cm->mctx, client, sizeof(*client));
+ client = ISC_LIST_HEAD(cm->idle);
+ }
+
+ /*
+ * Cancel any pending I/O.
+ */
+ isc_socket_cancel(cm->sock, task, ISC_SOCKCANCEL_ALL);
+
+ /*
+ * Run through the running client list and kill off any finds
+ * in progress.
+ */
+ client = ISC_LIST_HEAD(cm->running);
+ while (client != NULL) {
+ if (client->find != client->v4find
+ && client->find != client->v6find)
+ dns_adb_cancelfind(client->find);
+ if (client->v4find != NULL)
+ dns_adb_cancelfind(client->v4find);
+ if (client->v6find != NULL)
+ dns_adb_cancelfind(client->v6find);
+ client = ISC_LIST_NEXT(client, link);
+ }
+
+ cm->flags |= NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN;
+
+ isc_event_free(&ev);
+}
+
+/*
+ * Do all the crap needed to move a client from the run queue to the idle
+ * queue.
+ */
+void
+ns_lwdclient_stateidle(ns_lwdclient_t *client) {
+ ns_lwdclientmgr_t *cm;
+ isc_result_t result;
+
+ cm = client->clientmgr;
+
+ INSIST(client->sendbuf == NULL);
+ INSIST(client->sendlength == 0);
+ INSIST(client->arg == NULL);
+ INSIST(client->v4find == NULL);
+ INSIST(client->v6find == NULL);
+
+ ISC_LIST_UNLINK(cm->running, client, link);
+ ISC_LIST_PREPEND(cm->idle, client, link);
+
+ NS_LWDCLIENT_SETIDLE(client);
+
+ result = ns_lwdclient_startrecv(cm);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
+ "could not start lwres "
+ "client handler: %s",
+ isc_result_totext(result));
+}
+
+void
+ns_lwdclient_send(isc_task_t *task, isc_event_t *ev) {
+ ns_lwdclient_t *client = ev->ev_arg;
+ ns_lwdclientmgr_t *cm = client->clientmgr;
+ isc_socketevent_t *dev = (isc_socketevent_t *)ev;
+
+ UNUSED(task);
+ UNUSED(dev);
+
+ INSIST(NS_LWDCLIENT_ISSEND(client));
+ INSIST(client->sendbuf == dev->region.base);
+
+ ns_lwdclient_log(50, "task %p for client %p got send-done event",
+ task, client);
+
+ if (client->sendbuf != client->buffer)
+ lwres_context_freemem(cm->lwctx, client->sendbuf,
+ client->sendlength);
+ client->sendbuf = NULL;
+ client->sendlength = 0;
+
+ ns_lwdclient_stateidle(client);
+
+ isc_event_free(&ev);
+}
+
+isc_result_t
+ns_lwdclient_sendreply(ns_lwdclient_t *client, isc_region_t *r) {
+ struct in6_pktinfo *pktinfo;
+ ns_lwdclientmgr_t *cm = client->clientmgr;
+
+ if (client->pktinfo_valid)
+ pktinfo = &client->pktinfo;
+ else
+ pktinfo = NULL;
+ return (isc_socket_sendto(cm->sock, r, cm->task, ns_lwdclient_send,
+ client, &client->address, pktinfo));
+}
+
+void
+ns_lwdclient_initialize(ns_lwdclient_t *client, ns_lwdclientmgr_t *cmgr) {
+ client->clientmgr = cmgr;
+ ISC_LINK_INIT(client, link);
+ NS_LWDCLIENT_SETIDLE(client);
+ client->arg = NULL;
+
+ client->recvlength = 0;
+
+ client->sendbuf = NULL;
+ client->sendlength = 0;
+
+ client->find = NULL;
+ client->v4find = NULL;
+ client->v6find = NULL;
+ client->find_wanted = 0;
+
+ client->options = 0;
+ client->byaddr = NULL;
+
+ client->lookup = NULL;
+
+ client->pktinfo_valid = ISC_FALSE;
+
+ ISC_LIST_APPEND(cmgr->idle, client, link);
+}
diff --git a/bin/named/lwderror.c b/bin/named/lwderror.c
new file mode 100644
index 0000000..33f247a
--- /dev/null
+++ b/bin/named/lwderror.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwderror.c,v 1.12 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/socket.h>
+#include <isc/util.h>
+
+#include <named/types.h>
+#include <named/lwdclient.h>
+
+/*%
+ * Generate an error packet for the client, schedule a send, and put us in
+ * the SEND state.
+ *
+ * The client->pkt structure will be modified to form an error return.
+ * The receiver needs to verify that it is in fact an error, and do the
+ * right thing with it. The opcode will be unchanged. The result needs
+ * to be set before calling this function.
+ *
+ * The only change this code makes is to set the receive buffer size to the
+ * size we use, set the reply bit, and recompute any security information.
+ */
+void
+ns_lwdclient_errorpktsend(ns_lwdclient_t *client, isc_uint32_t _result) {
+ isc_result_t result;
+ int lwres;
+ isc_region_t r;
+ lwres_buffer_t b;
+
+ REQUIRE(NS_LWDCLIENT_ISRUNNING(client));
+
+ /*
+ * Since we are only sending the packet header, we can safely toss
+ * the receive buffer. This means we won't need to allocate space
+ * for sending an error reply. This is a Good Thing.
+ */
+ client->pkt.length = LWRES_LWPACKET_LENGTH;
+ client->pkt.pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
+ client->pkt.recvlength = LWRES_RECVLENGTH;
+ client->pkt.authtype = 0; /* XXXMLG */
+ client->pkt.authlength = 0;
+ client->pkt.result = _result;
+
+ lwres_buffer_init(&b, client->buffer, LWRES_RECVLENGTH);
+ lwres = lwres_lwpacket_renderheader(&b, &client->pkt);
+ if (lwres != LWRES_R_SUCCESS) {
+ ns_lwdclient_stateidle(client);
+ return;
+ }
+
+ r.base = client->buffer;
+ r.length = b.used;
+ client->sendbuf = client->buffer;
+ result = ns_lwdclient_sendreply(client, &r);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwdclient_stateidle(client);
+ return;
+ }
+
+ NS_LWDCLIENT_SETSEND(client);
+}
diff --git a/bin/named/lwdgabn.c b/bin/named/lwdgabn.c
new file mode 100644
index 0000000..dec1e1a
--- /dev/null
+++ b/bin/named/lwdgabn.c
@@ -0,0 +1,657 @@
+/*
+ * Copyright (C) 2004-2007 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: lwdgabn.c,v 1.22 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/netaddr.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/events.h>
+#include <dns/result.h>
+
+#include <named/types.h>
+#include <named/lwaddr.h>
+#include <named/lwdclient.h>
+#include <named/lwresd.h>
+#include <named/lwsearch.h>
+#include <named/sortlist.h>
+
+#define NEED_V4(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V4) != 0) \
+ && ((c)->v4find == NULL))
+#define NEED_V6(c) ((((c)->find_wanted & LWRES_ADDRTYPE_V6) != 0) \
+ && ((c)->v6find == NULL))
+
+static isc_result_t start_find(ns_lwdclient_t *);
+static void restart_find(ns_lwdclient_t *);
+static void init_gabn(ns_lwdclient_t *);
+
+/*%
+ * Destroy any finds. This can be used to "start over from scratch" and
+ * should only be called when events are _not_ being generated by the finds.
+ */
+static void
+cleanup_gabn(ns_lwdclient_t *client) {
+ ns_lwdclient_log(50, "cleaning up client %p", client);
+
+ if (client->v6find != NULL) {
+ if (client->v6find == client->v4find)
+ client->v6find = NULL;
+ else
+ dns_adb_destroyfind(&client->v6find);
+ }
+ if (client->v4find != NULL)
+ dns_adb_destroyfind(&client->v4find);
+}
+
+static void
+setup_addresses(ns_lwdclient_t *client, dns_adbfind_t *find, unsigned int at) {
+ dns_adbaddrinfo_t *ai;
+ lwres_addr_t *addr;
+ int af;
+ const struct sockaddr *sa;
+ isc_result_t result;
+
+ if (at == DNS_ADBFIND_INET)
+ af = AF_INET;
+ else
+ af = AF_INET6;
+
+ ai = ISC_LIST_HEAD(find->list);
+ while (ai != NULL && client->gabn.naddrs < LWRES_MAX_ADDRS) {
+ sa = &ai->sockaddr.type.sa;
+ if (sa->sa_family != af)
+ goto next;
+
+ addr = &client->addrs[client->gabn.naddrs];
+
+ result = lwaddr_lwresaddr_fromsockaddr(addr, &ai->sockaddr);
+ if (result != ISC_R_SUCCESS)
+ goto next;
+
+ ns_lwdclient_log(50, "adding address %p, family %d, length %d",
+ addr->address, addr->family, addr->length);
+
+ client->gabn.naddrs++;
+ REQUIRE(!LWRES_LINK_LINKED(addr, link));
+ LWRES_LIST_APPEND(client->gabn.addrs, addr, link);
+
+ next:
+ ai = ISC_LIST_NEXT(ai, publink);
+ }
+}
+
+typedef struct {
+ isc_netaddr_t address;
+ int rank;
+} rankedaddress;
+
+static int
+addr_compare(const void *av, const void *bv) {
+ const rankedaddress *a = (const rankedaddress *) av;
+ const rankedaddress *b = (const rankedaddress *) bv;
+ return (a->rank - b->rank);
+}
+
+static void
+sort_addresses(ns_lwdclient_t *client) {
+ unsigned int naddrs;
+ rankedaddress *addrs;
+ isc_netaddr_t remote;
+ dns_addressorderfunc_t order;
+ const void *arg;
+ ns_lwresd_t *lwresd = client->clientmgr->listener->manager;
+ unsigned int i;
+ isc_result_t result;
+
+ naddrs = client->gabn.naddrs;
+
+ if (naddrs <= 1 || lwresd->view->sortlist == NULL)
+ return;
+
+ addrs = isc_mem_get(lwresd->mctx, sizeof(rankedaddress) * naddrs);
+ if (addrs == NULL)
+ return;
+
+ isc_netaddr_fromsockaddr(&remote, &client->address);
+ ns_sortlist_byaddrsetup(lwresd->view->sortlist,
+ &remote, &order, &arg);
+ if (order == NULL) {
+ isc_mem_put(lwresd->mctx, addrs,
+ sizeof(rankedaddress) * naddrs);
+ return;
+ }
+ for (i = 0; i < naddrs; i++) {
+ result = lwaddr_netaddr_fromlwresaddr(&addrs[i].address,
+ &client->addrs[i]);
+ INSIST(result == ISC_R_SUCCESS);
+ addrs[i].rank = (*order)(&addrs[i].address, arg);
+ }
+ qsort(addrs, naddrs, sizeof(rankedaddress), addr_compare);
+ for (i = 0; i < naddrs; i++) {
+ result = lwaddr_lwresaddr_fromnetaddr(&client->addrs[i],
+ &addrs[i].address);
+ INSIST(result == ISC_R_SUCCESS);
+ }
+
+ isc_mem_put(lwresd->mctx, addrs, sizeof(rankedaddress) * naddrs);
+}
+
+static void
+generate_reply(ns_lwdclient_t *client) {
+ isc_result_t result;
+ int lwres;
+ isc_region_t r;
+ lwres_buffer_t lwb;
+ ns_lwdclientmgr_t *cm;
+
+ cm = client->clientmgr;
+ lwb.base = NULL;
+
+ ns_lwdclient_log(50, "generating gabn reply for client %p", client);
+
+ /*
+ * We must make certain the client->find is not still active.
+ * If it is either the v4 or v6 answer, just set it to NULL and
+ * let the cleanup code destroy it. Otherwise, destroy it now.
+ */
+ if (client->find == client->v4find || client->find == client->v6find)
+ client->find = NULL;
+ else
+ if (client->find != NULL)
+ dns_adb_destroyfind(&client->find);
+
+ /*
+ * perhaps there are some here?
+ */
+ if (NEED_V6(client) && client->v4find != NULL)
+ client->v6find = client->v4find;
+
+ /*
+ * Run through the finds we have and wire them up to the gabn
+ * structure.
+ */
+ LWRES_LIST_INIT(client->gabn.addrs);
+ if (client->v4find != NULL)
+ setup_addresses(client, client->v4find, DNS_ADBFIND_INET);
+ if (client->v6find != NULL)
+ setup_addresses(client, client->v6find, DNS_ADBFIND_INET6);
+
+ /*
+ * If there are no addresses, try the next element in the search
+ * path, if there are any more. Otherwise, fall through into
+ * the error handling code below.
+ */
+ if (client->gabn.naddrs == 0) {
+ do {
+ result = ns_lwsearchctx_next(&client->searchctx);
+ if (result == ISC_R_SUCCESS) {
+ cleanup_gabn(client);
+ result = start_find(client);
+ if (result == ISC_R_SUCCESS)
+ return;
+ }
+ } while (result == ISC_R_SUCCESS);
+ }
+
+ /*
+ * Render the packet.
+ */
+ client->pkt.recvlength = LWRES_RECVLENGTH;
+ client->pkt.authtype = 0; /* XXXMLG */
+ client->pkt.authlength = 0;
+
+ /*
+ * If there are no addresses, return failure.
+ */
+ if (client->gabn.naddrs != 0)
+ client->pkt.result = LWRES_R_SUCCESS;
+ else
+ client->pkt.result = LWRES_R_NOTFOUND;
+
+ sort_addresses(client);
+
+ lwres = lwres_gabnresponse_render(cm->lwctx, &client->gabn,
+ &client->pkt, &lwb);
+ if (lwres != LWRES_R_SUCCESS)
+ goto out;
+
+ r.base = lwb.base;
+ r.length = lwb.used;
+ client->sendbuf = r.base;
+ client->sendlength = r.length;
+ result = ns_lwdclient_sendreply(client, &r);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+
+ NS_LWDCLIENT_SETSEND(client);
+
+ /*
+ * All done!
+ */
+ cleanup_gabn(client);
+
+ return;
+
+ out:
+ cleanup_gabn(client);
+
+ if (lwb.base != NULL)
+ lwres_context_freemem(client->clientmgr->lwctx,
+ lwb.base, lwb.length);
+
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
+
+/*
+ * Take the current real name, move it to an alias slot (if any are
+ * open) then put this new name in as the real name for the target.
+ *
+ * Return success if it can be rendered, otherwise failure. Note that
+ * not having enough alias slots open is NOT a failure.
+ */
+static isc_result_t
+add_alias(ns_lwdclient_t *client) {
+ isc_buffer_t b;
+ isc_result_t result;
+ isc_uint16_t naliases;
+
+ b = client->recv_buffer;
+
+ /*
+ * Render the new name to the buffer.
+ */
+ result = dns_name_totext(dns_fixedname_name(&client->target_name),
+ ISC_TRUE, &client->recv_buffer);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Are there any open slots?
+ */
+ naliases = client->gabn.naliases;
+ if (naliases < LWRES_MAX_ALIASES) {
+ client->gabn.aliases[naliases] = client->gabn.realname;
+ client->gabn.aliaslen[naliases] = client->gabn.realnamelen;
+ client->gabn.naliases++;
+ }
+
+ /*
+ * Save this name away as the current real name.
+ */
+ client->gabn.realname = (char *)(b.base) + b.used;
+ client->gabn.realnamelen = client->recv_buffer.used - b.used;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+store_realname(ns_lwdclient_t *client) {
+ isc_buffer_t b;
+ isc_result_t result;
+ dns_name_t *tname;
+
+ b = client->recv_buffer;
+
+ tname = dns_fixedname_name(&client->target_name);
+ result = ns_lwsearchctx_current(&client->searchctx, tname);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Render the new name to the buffer.
+ */
+ result = dns_name_totext(tname, ISC_TRUE, &client->recv_buffer);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Save this name away as the current real name.
+ */
+ client->gabn.realname = (char *) b.base + b.used;
+ client->gabn.realnamelen = client->recv_buffer.used - b.used;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+process_gabn_finddone(isc_task_t *task, isc_event_t *ev) {
+ ns_lwdclient_t *client = ev->ev_arg;
+ isc_eventtype_t evtype;
+ isc_boolean_t claimed;
+
+ ns_lwdclient_log(50, "find done for task %p, client %p", task, client);
+
+ evtype = ev->ev_type;
+ isc_event_free(&ev);
+
+ /*
+ * No more info to be had? If so, we have all the good stuff
+ * right now, so we can render things.
+ */
+ claimed = ISC_FALSE;
+ if (evtype == DNS_EVENT_ADBNOMOREADDRESSES) {
+ if (NEED_V4(client)) {
+ client->v4find = client->find;
+ claimed = ISC_TRUE;
+ }
+ if (NEED_V6(client)) {
+ client->v6find = client->find;
+ claimed = ISC_TRUE;
+ }
+ if (client->find != NULL) {
+ if (claimed)
+ client->find = NULL;
+ else
+ dns_adb_destroyfind(&client->find);
+
+ }
+ generate_reply(client);
+ return;
+ }
+
+ /*
+ * We probably don't need this find anymore. We're either going to
+ * reissue it, or an error occurred. Either way, we're done with
+ * it.
+ */
+ if ((client->find != client->v4find)
+ && (client->find != client->v6find)) {
+ dns_adb_destroyfind(&client->find);
+ } else {
+ client->find = NULL;
+ }
+
+ /*
+ * We have some new information we can gather. Run off and fetch
+ * it.
+ */
+ if (evtype == DNS_EVENT_ADBMOREADDRESSES) {
+ restart_find(client);
+ return;
+ }
+
+ /*
+ * An error or other strangeness happened. Drop this query.
+ */
+ cleanup_gabn(client);
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
+
+static void
+restart_find(ns_lwdclient_t *client) {
+ unsigned int options;
+ isc_result_t result;
+ isc_boolean_t claimed;
+
+ ns_lwdclient_log(50, "starting find for client %p", client);
+
+ /*
+ * Issue a find for the name contained in the request. We won't
+ * set the bit that says "anything is good enough" -- we want it
+ * all.
+ */
+ options = 0;
+ options |= DNS_ADBFIND_WANTEVENT;
+ options |= DNS_ADBFIND_RETURNLAME;
+
+ /*
+ * Set the bits up here to mark that we want this address family
+ * and that we do not currently have a find pending. We will
+ * set that bit again below if it turns out we will get an event.
+ */
+ if (NEED_V4(client))
+ options |= DNS_ADBFIND_INET;
+ if (NEED_V6(client))
+ options |= DNS_ADBFIND_INET6;
+
+ find_again:
+ INSIST(client->find == NULL);
+ result = dns_adb_createfind(client->clientmgr->view->adb,
+ client->clientmgr->task,
+ process_gabn_finddone, client,
+ dns_fixedname_name(&client->target_name),
+ dns_rootname, 0, options, 0,
+ dns_fixedname_name(&client->target_name),
+ client->clientmgr->view->dstport,
+ &client->find);
+
+ /*
+ * Did we get an alias? If so, save it and re-issue the query.
+ */
+ if (result == DNS_R_ALIAS) {
+ ns_lwdclient_log(50, "found alias, restarting query");
+ dns_adb_destroyfind(&client->find);
+ cleanup_gabn(client);
+ result = add_alias(client);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwdclient_log(50,
+ "out of buffer space adding alias");
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+ return;
+ }
+ goto find_again;
+ }
+
+ ns_lwdclient_log(50, "find returned %d (%s)", result,
+ isc_result_totext(result));
+
+ /*
+ * Did we get an error?
+ */
+ if (result != ISC_R_SUCCESS) {
+ if (client->find != NULL)
+ dns_adb_destroyfind(&client->find);
+ cleanup_gabn(client);
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+ return;
+ }
+
+ claimed = ISC_FALSE;
+
+ /*
+ * Did we get our answer to V4 addresses?
+ */
+ if (NEED_V4(client)
+ && ((client->find->query_pending & DNS_ADBFIND_INET) == 0)) {
+ ns_lwdclient_log(50, "client %p ipv4 satisfied by find %p",
+ client, client->find);
+ claimed = ISC_TRUE;
+ client->v4find = client->find;
+ }
+
+ /*
+ * Did we get our answer to V6 addresses?
+ */
+ if (NEED_V6(client)
+ && ((client->find->query_pending & DNS_ADBFIND_INET6) == 0)) {
+ ns_lwdclient_log(50, "client %p ipv6 satisfied by find %p",
+ client, client->find);
+ claimed = ISC_TRUE;
+ client->v6find = client->find;
+ }
+
+ /*
+ * If we're going to get an event, set our internal pending flag
+ * and return. When we get an event back we'll do the right
+ * thing, basically by calling this function again, perhaps with a
+ * new target name.
+ *
+ * If we have both v4 and v6, and we are still getting an event,
+ * we have a programming error, so die hard.
+ */
+ if ((client->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
+ ns_lwdclient_log(50, "event will be sent");
+ INSIST(client->v4find == NULL || client->v6find == NULL);
+ return;
+ }
+ ns_lwdclient_log(50, "no event will be sent");
+ if (claimed)
+ client->find = NULL;
+ else
+ dns_adb_destroyfind(&client->find);
+
+ /*
+ * We seem to have everything we asked for, or at least we are
+ * able to respond with things we've learned.
+ */
+
+ generate_reply(client);
+}
+
+static isc_result_t
+start_find(ns_lwdclient_t *client) {
+ isc_result_t result;
+
+ /*
+ * Initialize the real name and alias arrays in the reply we're
+ * going to build up.
+ */
+ init_gabn(client);
+
+ result = store_realname(client);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ restart_find(client);
+ return (ISC_R_SUCCESS);
+
+}
+
+static void
+init_gabn(ns_lwdclient_t *client) {
+ int i;
+
+ /*
+ * Initialize the real name and alias arrays in the reply we're
+ * going to build up.
+ */
+ for (i = 0; i < LWRES_MAX_ALIASES; i++) {
+ client->aliases[i] = NULL;
+ client->aliaslen[i] = 0;
+ }
+ for (i = 0; i < LWRES_MAX_ADDRS; i++) {
+ client->addrs[i].family = 0;
+ client->addrs[i].length = 0;
+ memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN);
+ LWRES_LINK_INIT(&client->addrs[i], link);
+ }
+
+ client->gabn.naliases = 0;
+ client->gabn.naddrs = 0;
+ client->gabn.realname = NULL;
+ client->gabn.aliases = client->aliases;
+ client->gabn.realnamelen = 0;
+ client->gabn.aliaslen = client->aliaslen;
+ LWRES_LIST_INIT(client->gabn.addrs);
+ client->gabn.base = NULL;
+ client->gabn.baselen = 0;
+
+ /*
+ * Set up the internal buffer to point to the receive region.
+ */
+ isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
+}
+
+/*
+ * When we are called, we can be assured that:
+ *
+ * client->sockaddr contains the address we need to reply to,
+ *
+ * client->pkt contains the packet header data,
+ *
+ * the packet "checks out" overall -- any MD5 hashes or crypto
+ * bits have been verified,
+ *
+ * "b" points to the remaining data after the packet header
+ * was parsed off.
+ *
+ * We are in a the RECVDONE state.
+ *
+ * From this state we will enter the SEND state if we happen to have
+ * everything we need or we need to return an error packet, or to the
+ * FINDWAIT state if we need to look things up.
+ */
+void
+ns_lwdclient_processgabn(ns_lwdclient_t *client, lwres_buffer_t *b) {
+ isc_result_t result;
+ lwres_gabnrequest_t *req;
+ ns_lwdclientmgr_t *cm;
+ isc_buffer_t namebuf;
+
+ REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
+
+ cm = client->clientmgr;
+ req = NULL;
+
+ result = lwres_gabnrequest_parse(client->clientmgr->lwctx,
+ b, &client->pkt, &req);
+ if (result != LWRES_R_SUCCESS)
+ goto out;
+ if (req->name == NULL)
+ goto out;
+
+ isc_buffer_init(&namebuf, req->name, req->namelen);
+ isc_buffer_add(&namebuf, req->namelen);
+
+ 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);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ ns_lwsearchctx_init(&client->searchctx,
+ cm->listener->manager->search,
+ dns_fixedname_name(&client->query_name),
+ cm->listener->manager->ndots);
+ ns_lwsearchctx_first(&client->searchctx);
+
+ client->find_wanted = req->addrtypes;
+ ns_lwdclient_log(50, "client %p looking for addrtypes %08x",
+ client, client->find_wanted);
+
+ /*
+ * We no longer need to keep this around.
+ */
+ lwres_gabnrequest_free(client->clientmgr->lwctx, &req);
+
+ /*
+ * Start the find.
+ */
+ result = start_find(client);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+
+ return;
+
+ /*
+ * We're screwed. Return an error packet to our caller.
+ */
+ out:
+ if (req != NULL)
+ lwres_gabnrequest_free(client->clientmgr->lwctx, &req);
+
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
diff --git a/bin/named/lwdgnba.c b/bin/named/lwdgnba.c
new file mode 100644
index 0000000..dfc2ad6
--- /dev/null
+++ b/bin/named/lwdgnba.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: lwdgnba.c,v 1.22 2008/01/14 23:46:56 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/socket.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/byaddr.h>
+#include <dns/result.h>
+
+#include <named/types.h>
+#include <named/lwdclient.h>
+
+static void start_byaddr(ns_lwdclient_t *);
+
+static void
+byaddr_done(isc_task_t *task, isc_event_t *event) {
+ ns_lwdclient_t *client;
+ ns_lwdclientmgr_t *cm;
+ dns_byaddrevent_t *bevent;
+ int lwres;
+ lwres_buffer_t lwb;
+ dns_name_t *name;
+ isc_result_t result;
+ lwres_result_t lwresult;
+ isc_region_t r;
+ isc_buffer_t b;
+ lwres_gnbaresponse_t *gnba;
+ isc_uint16_t naliases;
+
+ UNUSED(task);
+
+ lwb.base = NULL;
+ client = event->ev_arg;
+ cm = client->clientmgr;
+ INSIST(client->byaddr == (dns_byaddr_t *)event->ev_sender);
+
+ bevent = (dns_byaddrevent_t *)event;
+ gnba = &client->gnba;
+
+ ns_lwdclient_log(50, "byaddr event result = %s",
+ isc_result_totext(bevent->result));
+
+ result = bevent->result;
+ if (result != ISC_R_SUCCESS) {
+ dns_byaddr_destroy(&client->byaddr);
+ isc_event_free(&event);
+ bevent = NULL;
+
+ if (client->na.family != AF_INET6 ||
+ (client->options & DNS_BYADDROPT_IPV6INT) != 0) {
+ if (result == DNS_R_NCACHENXDOMAIN ||
+ result == DNS_R_NCACHENXRRSET ||
+ result == DNS_R_NXDOMAIN ||
+ result == DNS_R_NXRRSET)
+ lwresult = LWRES_R_NOTFOUND;
+ else
+ lwresult = LWRES_R_FAILURE;
+ ns_lwdclient_errorpktsend(client, lwresult);
+ return;
+ }
+
+ /*
+ * Fall back to ip6.int reverse if the default ip6.arpa
+ * fails.
+ */
+ client->options |= DNS_BYADDROPT_IPV6INT;
+
+ start_byaddr(client);
+ return;
+ }
+
+ for (name = ISC_LIST_HEAD(bevent->names);
+ name != NULL;
+ name = ISC_LIST_NEXT(name, link))
+ {
+ b = client->recv_buffer;
+
+ result = dns_name_totext(name, ISC_TRUE, &client->recv_buffer);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ ns_lwdclient_log(50, "found name '%.*s'",
+ (int)(client->recv_buffer.used - b.used),
+ (char *)(b.base) + b.used);
+ if (gnba->realname == NULL) {
+ gnba->realname = (char *)(b.base) + b.used;
+ gnba->realnamelen = client->recv_buffer.used - b.used;
+ } else {
+ naliases = gnba->naliases;
+ if (naliases >= LWRES_MAX_ALIASES)
+ break;
+ gnba->aliases[naliases] = (char *)(b.base) + b.used;
+ gnba->aliaslen[naliases] =
+ client->recv_buffer.used - b.used;
+ gnba->naliases++;
+ }
+ }
+
+ dns_byaddr_destroy(&client->byaddr);
+ isc_event_free(&event);
+
+ /*
+ * Render the packet.
+ */
+ client->pkt.recvlength = LWRES_RECVLENGTH;
+ client->pkt.authtype = 0; /* XXXMLG */
+ client->pkt.authlength = 0;
+ client->pkt.result = LWRES_R_SUCCESS;
+
+ lwres = lwres_gnbaresponse_render(cm->lwctx,
+ gnba, &client->pkt, &lwb);
+ if (lwres != LWRES_R_SUCCESS)
+ goto out;
+
+ r.base = lwb.base;
+ r.length = lwb.used;
+ client->sendbuf = r.base;
+ client->sendlength = r.length;
+ result = ns_lwdclient_sendreply(client, &r);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+
+ NS_LWDCLIENT_SETSEND(client);
+
+ return;
+
+ out:
+ if (client->byaddr != NULL)
+ dns_byaddr_destroy(&client->byaddr);
+ if (lwb.base != NULL)
+ lwres_context_freemem(cm->lwctx,
+ lwb.base, lwb.length);
+
+ if (event != NULL)
+ isc_event_free(&event);
+}
+
+static void
+start_byaddr(ns_lwdclient_t *client) {
+ isc_result_t result;
+ ns_lwdclientmgr_t *cm;
+
+ cm = client->clientmgr;
+
+ INSIST(client->byaddr == NULL);
+
+ result = dns_byaddr_create(cm->mctx, &client->na, cm->view,
+ client->options, cm->task, byaddr_done,
+ client, &client->byaddr);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+ return;
+ }
+}
+
+static void
+init_gnba(ns_lwdclient_t *client) {
+ int i;
+
+ /*
+ * Initialize the real name and alias arrays in the reply we're
+ * going to build up.
+ */
+ for (i = 0; i < LWRES_MAX_ALIASES; i++) {
+ client->aliases[i] = NULL;
+ client->aliaslen[i] = 0;
+ }
+ for (i = 0; i < LWRES_MAX_ADDRS; i++) {
+ client->addrs[i].family = 0;
+ client->addrs[i].length = 0;
+ memset(client->addrs[i].address, 0, LWRES_ADDR_MAXLEN);
+ LWRES_LINK_INIT(&client->addrs[i], link);
+ }
+
+ client->gnba.naliases = 0;
+ client->gnba.realname = NULL;
+ client->gnba.aliases = client->aliases;
+ client->gnba.realnamelen = 0;
+ client->gnba.aliaslen = client->aliaslen;
+ client->gnba.base = NULL;
+ client->gnba.baselen = 0;
+ isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
+}
+
+void
+ns_lwdclient_processgnba(ns_lwdclient_t *client, lwres_buffer_t *b) {
+ lwres_gnbarequest_t *req;
+ isc_result_t result;
+ isc_sockaddr_t sa;
+ ns_lwdclientmgr_t *cm;
+
+ REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
+ INSIST(client->byaddr == NULL);
+
+ cm = client->clientmgr;
+ req = NULL;
+
+ result = lwres_gnbarequest_parse(cm->lwctx,
+ b, &client->pkt, &req);
+ if (result != LWRES_R_SUCCESS)
+ goto out;
+
+ client->options = 0;
+ if (req->addr.family == LWRES_ADDRTYPE_V4) {
+ client->na.family = AF_INET;
+ if (req->addr.length != 4)
+ goto out;
+ memcpy(&client->na.type.in, req->addr.address, 4);
+ } else if (req->addr.family == LWRES_ADDRTYPE_V6) {
+ client->na.family = AF_INET6;
+ if (req->addr.length != 16)
+ goto out;
+ memcpy(&client->na.type.in6, req->addr.address, 16);
+ } else {
+ goto out;
+ }
+ isc_sockaddr_fromnetaddr(&sa, &client->na, 53);
+
+ ns_lwdclient_log(50, "client %p looking for addrtype %08x",
+ client, req->addr.family);
+
+ /*
+ * We no longer need to keep this around.
+ */
+ lwres_gnbarequest_free(cm->lwctx, &req);
+
+ /*
+ * Initialize the real name and alias arrays in the reply we're
+ * going to build up.
+ */
+ init_gnba(client);
+ client->options = 0;
+
+ /*
+ * Start the find.
+ */
+ start_byaddr(client);
+
+ return;
+
+ /*
+ * We're screwed. Return an error packet to our caller.
+ */
+ out:
+ if (req != NULL)
+ lwres_gnbarequest_free(cm->lwctx, &req);
+
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
diff --git a/bin/named/lwdgrbn.c b/bin/named/lwdgrbn.c
new file mode 100644
index 0000000..b54e83d
--- /dev/null
+++ b/bin/named/lwdgrbn.c
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2004-2007 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
+ * 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: lwdgrbn.c,v 1.20 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/socket.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/lookup.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+#include <named/types.h>
+#include <named/lwdclient.h>
+#include <named/lwresd.h>
+#include <named/lwsearch.h>
+
+static void start_lookup(ns_lwdclient_t *);
+
+static isc_result_t
+fill_array(int *pos, dns_rdataset_t *rdataset,
+ int size, unsigned char **rdatas, lwres_uint16_t *rdatalen)
+{
+ dns_rdata_t rdata;
+ isc_result_t result;
+ isc_region_t r;
+
+ UNUSED(size);
+
+ dns_rdata_init(&rdata);
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ INSIST(*pos < size);
+ dns_rdataset_current(rdataset, &rdata);
+ dns_rdata_toregion(&rdata, &r);
+ rdatas[*pos] = r.base;
+ rdatalen[*pos] = r.length;
+ dns_rdata_reset(&rdata);
+ (*pos)++;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
+static isc_result_t
+iterate_node(lwres_grbnresponse_t *grbn, dns_db_t *db, dns_dbnode_t *node,
+ isc_mem_t *mctx)
+{
+ int used = 0, count;
+ int size = 8, oldsize = 0;
+ unsigned char **rdatas = NULL, **oldrdatas = NULL, **newrdatas = NULL;
+ lwres_uint16_t *lens = NULL, *oldlens = NULL, *newlens = NULL;
+ dns_rdatasetiter_t *iter = NULL;
+ dns_rdataset_t set;
+ dns_ttl_t ttl = ISC_INT32_MAX;
+ lwres_uint32_t flags = LWRDATA_VALIDATED;
+ isc_result_t result = ISC_R_NOMEMORY;
+
+ result = dns_db_allrdatasets(db, node, NULL, 0, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+
+ rdatas = isc_mem_get(mctx, size * sizeof(*rdatas));
+ if (rdatas == NULL)
+ goto out;
+ lens = isc_mem_get(mctx, size * sizeof(*lens));
+ if (lens == NULL)
+ goto out;
+
+ for (result = dns_rdatasetiter_first(iter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iter))
+ {
+ result = ISC_R_NOMEMORY;
+ dns_rdataset_init(&set);
+ dns_rdatasetiter_current(iter, &set);
+
+ if (set.type != dns_rdatatype_rrsig) {
+ dns_rdataset_disassociate(&set);
+ continue;
+ }
+
+ count = dns_rdataset_count(&set);
+ if (used + count > size) {
+ /* copy & reallocate */
+ oldsize = size;
+ oldrdatas = rdatas;
+ oldlens = lens;
+ rdatas = NULL;
+ lens = NULL;
+
+ size *= 2;
+
+ rdatas = isc_mem_get(mctx, size * sizeof(*rdatas));
+ if (rdatas == NULL)
+ goto out;
+ lens = isc_mem_get(mctx, size * sizeof(*lens));
+ if (lens == NULL)
+ goto out;
+ memcpy(rdatas, oldrdatas, used * sizeof(*rdatas));
+ memcpy(lens, oldlens, used * sizeof(*lens));
+ isc_mem_put(mctx, oldrdatas,
+ oldsize * sizeof(*oldrdatas));
+ isc_mem_put(mctx, oldlens, oldsize * sizeof(*oldlens));
+ oldrdatas = NULL;
+ oldlens = NULL;
+ }
+ if (set.ttl < ttl)
+ ttl = set.ttl;
+ if (set.trust != dns_trust_secure)
+ flags &= (~LWRDATA_VALIDATED);
+ result = fill_array(&used, &set, size, rdatas, lens);
+ dns_rdataset_disassociate(&set);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ dns_rdatasetiter_destroy(&iter);
+
+ /*
+ * If necessary, shrink and copy the arrays.
+ */
+ if (size != used) {
+ result = ISC_R_NOMEMORY;
+ newrdatas = isc_mem_get(mctx, used * sizeof(*rdatas));
+ if (newrdatas == NULL)
+ goto out;
+ newlens = isc_mem_get(mctx, used * sizeof(*lens));
+ if (newlens == NULL)
+ goto out;
+ memcpy(newrdatas, rdatas, used * sizeof(*rdatas));
+ memcpy(newlens, lens, used * sizeof(*lens));
+ isc_mem_put(mctx, rdatas, size * sizeof(*rdatas));
+ isc_mem_put(mctx, lens, size * sizeof(*lens));
+ grbn->rdatas = newrdatas;
+ grbn->rdatalen = newlens;
+ } else {
+ grbn->rdatas = rdatas;
+ grbn->rdatalen = lens;
+ }
+ grbn->nrdatas = used;
+ grbn->ttl = ttl;
+ grbn->flags = flags;
+ return (ISC_R_SUCCESS);
+
+ out:
+ dns_rdatasetiter_destroy(&iter);
+ if (rdatas != NULL)
+ isc_mem_put(mctx, rdatas, size * sizeof(*rdatas));
+ if (lens != NULL)
+ isc_mem_put(mctx, lens, size * sizeof(*lens));
+ if (oldrdatas != NULL)
+ isc_mem_put(mctx, oldrdatas, oldsize * sizeof(*oldrdatas));
+ if (oldlens != NULL)
+ isc_mem_put(mctx, oldlens, oldsize * sizeof(*oldlens));
+ if (newrdatas != NULL)
+ isc_mem_put(mctx, newrdatas, used * sizeof(*oldrdatas));
+ return (result);
+}
+
+static void
+lookup_done(isc_task_t *task, isc_event_t *event) {
+ ns_lwdclient_t *client;
+ ns_lwdclientmgr_t *cm;
+ dns_lookupevent_t *levent;
+ lwres_buffer_t lwb;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ isc_result_t result;
+ lwres_result_t lwresult;
+ isc_region_t r;
+ isc_buffer_t b;
+ lwres_grbnresponse_t *grbn;
+ int i;
+
+ UNUSED(task);
+
+ lwb.base = NULL;
+ client = event->ev_arg;
+ cm = client->clientmgr;
+ INSIST(client->lookup == (dns_lookup_t *)event->ev_sender);
+
+ levent = (dns_lookupevent_t *)event;
+ grbn = &client->grbn;
+
+ ns_lwdclient_log(50, "lookup event result = %s",
+ isc_result_totext(levent->result));
+
+ result = levent->result;
+ if (result != ISC_R_SUCCESS) {
+ dns_lookup_destroy(&client->lookup);
+ isc_event_free(&event);
+ levent = NULL;
+
+ switch (result) {
+ case DNS_R_NXDOMAIN:
+ case DNS_R_NCACHENXDOMAIN:
+ result = ns_lwsearchctx_next(&client->searchctx);
+ if (result != ISC_R_SUCCESS)
+ lwresult = LWRES_R_NOTFOUND;
+ else {
+ start_lookup(client);
+ return;
+ }
+ break;
+ case DNS_R_NXRRSET:
+ case DNS_R_NCACHENXRRSET:
+ lwresult = LWRES_R_TYPENOTFOUND;
+ break;
+ default:
+ lwresult = LWRES_R_FAILURE;
+ }
+ ns_lwdclient_errorpktsend(client, lwresult);
+ return;
+ }
+
+ name = levent->name;
+ b = client->recv_buffer;
+
+ grbn->flags = 0;
+
+ grbn->nrdatas = 0;
+ grbn->rdatas = NULL;
+ grbn->rdatalen = NULL;
+
+ grbn->nsigs = 0;
+ grbn->sigs = NULL;
+ grbn->siglen = NULL;
+
+ result = dns_name_totext(name, ISC_TRUE, &client->recv_buffer);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ grbn->realname = (char *)isc_buffer_used(&b);
+ grbn->realnamelen = isc_buffer_usedlength(&client->recv_buffer) -
+ isc_buffer_usedlength(&b);
+ ns_lwdclient_log(50, "found name '%.*s'", grbn->realnamelen,
+ grbn->realname);
+
+ grbn->rdclass = cm->view->rdclass;
+ grbn->rdtype = client->rdtype;
+
+ rdataset = levent->rdataset;
+ if (rdataset != NULL) {
+ /* The normal case */
+ grbn->nrdatas = dns_rdataset_count(rdataset);
+ grbn->rdatas = isc_mem_get(cm->mctx, grbn->nrdatas *
+ sizeof(unsigned char *));
+ if (grbn->rdatas == NULL)
+ goto out;
+ grbn->rdatalen = isc_mem_get(cm->mctx, grbn->nrdatas *
+ sizeof(lwres_uint16_t));
+ if (grbn->rdatalen == NULL)
+ goto out;
+
+ i = 0;
+ result = fill_array(&i, rdataset, grbn->nrdatas, grbn->rdatas,
+ grbn->rdatalen);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ INSIST(i == grbn->nrdatas);
+ grbn->ttl = rdataset->ttl;
+ if (rdataset->trust == dns_trust_secure)
+ grbn->flags |= LWRDATA_VALIDATED;
+ } else {
+ /* The SIG query case */
+ result = iterate_node(grbn, levent->db, levent->node,
+ cm->mctx);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ }
+ ns_lwdclient_log(50, "filled in %d rdata%s", grbn->nrdatas,
+ (grbn->nrdatas == 1) ? "" : "s");
+
+ sigrdataset = levent->sigrdataset;
+ if (sigrdataset != NULL) {
+ grbn->nsigs = dns_rdataset_count(sigrdataset);
+ grbn->sigs = isc_mem_get(cm->mctx, grbn->nsigs *
+ sizeof(unsigned char *));
+ if (grbn->sigs == NULL)
+ goto out;
+ grbn->siglen = isc_mem_get(cm->mctx, grbn->nsigs *
+ sizeof(lwres_uint16_t));
+ if (grbn->siglen == NULL)
+ goto out;
+
+ i = 0;
+ result = fill_array(&i, sigrdataset, grbn->nsigs, grbn->sigs,
+ grbn->siglen);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ INSIST(i == grbn->nsigs);
+ ns_lwdclient_log(50, "filled in %d signature%s", grbn->nsigs,
+ (grbn->nsigs == 1) ? "" : "s");
+ }
+
+ dns_lookup_destroy(&client->lookup);
+ isc_event_free(&event);
+
+ /*
+ * Render the packet.
+ */
+ client->pkt.recvlength = LWRES_RECVLENGTH;
+ client->pkt.authtype = 0; /* XXXMLG */
+ client->pkt.authlength = 0;
+ client->pkt.result = LWRES_R_SUCCESS;
+
+ lwresult = lwres_grbnresponse_render(cm->lwctx,
+ grbn, &client->pkt, &lwb);
+ if (lwresult != LWRES_R_SUCCESS)
+ goto out;
+
+ isc_mem_put(cm->mctx, grbn->rdatas,
+ grbn->nrdatas * sizeof(unsigned char *));
+ isc_mem_put(cm->mctx, grbn->rdatalen,
+ grbn->nrdatas * sizeof(lwres_uint16_t));
+
+ if (grbn->sigs != NULL)
+ isc_mem_put(cm->mctx, grbn->sigs,
+ grbn->nsigs * sizeof(unsigned char *));
+ if (grbn->siglen != NULL)
+ isc_mem_put(cm->mctx, grbn->siglen,
+ grbn->nsigs * sizeof(lwres_uint16_t));
+
+ r.base = lwb.base;
+ r.length = lwb.used;
+ client->sendbuf = r.base;
+ client->sendlength = r.length;
+ result = ns_lwdclient_sendreply(client, &r);
+ if (result != ISC_R_SUCCESS)
+ goto out2;
+
+ NS_LWDCLIENT_SETSEND(client);
+
+ return;
+
+ out:
+ if (grbn->rdatas != NULL)
+ isc_mem_put(cm->mctx, grbn->rdatas,
+ grbn->nrdatas * sizeof(unsigned char *));
+ if (grbn->rdatalen != NULL)
+ isc_mem_put(cm->mctx, grbn->rdatalen,
+ grbn->nrdatas * sizeof(lwres_uint16_t));
+
+ if (grbn->sigs != NULL)
+ isc_mem_put(cm->mctx, grbn->sigs,
+ grbn->nsigs * sizeof(unsigned char *));
+ if (grbn->siglen != NULL)
+ isc_mem_put(cm->mctx, grbn->siglen,
+ grbn->nsigs * sizeof(lwres_uint16_t));
+ out2:
+ if (client->lookup != NULL)
+ dns_lookup_destroy(&client->lookup);
+ if (lwb.base != NULL)
+ lwres_context_freemem(cm->lwctx, lwb.base, lwb.length);
+
+ if (event != NULL)
+ isc_event_free(&event);
+
+ ns_lwdclient_log(50, "error constructing getrrsetbyname response");
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
+
+static void
+start_lookup(ns_lwdclient_t *client) {
+ isc_result_t result;
+ ns_lwdclientmgr_t *cm;
+ dns_fixedname_t absname;
+
+ cm = client->clientmgr;
+
+ INSIST(client->lookup == NULL);
+
+ dns_fixedname_init(&absname);
+ result = ns_lwsearchctx_current(&client->searchctx,
+ dns_fixedname_name(&absname));
+ /*
+ * This will return failure if relative name + suffix is too long.
+ * In this case, just go on to the next entry in the search path.
+ */
+ if (result != ISC_R_SUCCESS)
+ start_lookup(client);
+
+ result = dns_lookup_create(cm->mctx,
+ dns_fixedname_name(&absname),
+ client->rdtype, cm->view,
+ client->options, cm->task, lookup_done,
+ client, &client->lookup);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+ return;
+ }
+}
+
+static void
+init_grbn(ns_lwdclient_t *client) {
+ client->grbn.rdclass = 0;
+ client->grbn.rdtype = 0;
+ client->grbn.ttl = 0;
+ client->grbn.nrdatas = 0;
+ client->grbn.realname = NULL;
+ client->grbn.realnamelen = 0;
+ client->grbn.rdatas = 0;
+ client->grbn.rdatalen = 0;
+ client->grbn.base = NULL;
+ client->grbn.baselen = 0;
+ isc_buffer_init(&client->recv_buffer, client->buffer, LWRES_RECVLENGTH);
+}
+
+void
+ns_lwdclient_processgrbn(ns_lwdclient_t *client, lwres_buffer_t *b) {
+ lwres_grbnrequest_t *req;
+ isc_result_t result;
+ ns_lwdclientmgr_t *cm;
+ isc_buffer_t namebuf;
+
+ REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
+ INSIST(client->byaddr == NULL);
+
+ cm = client->clientmgr;
+ req = NULL;
+
+ result = lwres_grbnrequest_parse(cm->lwctx,
+ b, &client->pkt, &req);
+ if (result != LWRES_R_SUCCESS)
+ goto out;
+ if (req->name == NULL)
+ goto out;
+
+ client->options = 0;
+ if (req->rdclass != cm->view->rdclass)
+ goto out;
+
+ if (req->rdclass == dns_rdataclass_any ||
+ req->rdtype == dns_rdatatype_any)
+ goto out;
+
+ client->rdtype = req->rdtype;
+
+ isc_buffer_init(&namebuf, req->name, req->namelen);
+ isc_buffer_add(&namebuf, req->namelen);
+
+ dns_fixedname_init(&client->query_name);
+ result = dns_name_fromtext(dns_fixedname_name(&client->query_name),
+ &namebuf, NULL, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ ns_lwsearchctx_init(&client->searchctx,
+ cm->listener->manager->search,
+ dns_fixedname_name(&client->query_name),
+ cm->listener->manager->ndots);
+ ns_lwsearchctx_first(&client->searchctx);
+
+ ns_lwdclient_log(50, "client %p looking for type %d",
+ client, client->rdtype);
+
+ /*
+ * We no longer need to keep this around.
+ */
+ lwres_grbnrequest_free(cm->lwctx, &req);
+
+ /*
+ * Initialize the real name and alias arrays in the reply we're
+ * going to build up.
+ */
+ init_grbn(client);
+
+ /*
+ * Start the find.
+ */
+ start_lookup(client);
+
+ return;
+
+ /*
+ * We're screwed. Return an error packet to our caller.
+ */
+ out:
+ if (req != NULL)
+ lwres_grbnrequest_free(cm->lwctx, &req);
+
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
diff --git a/bin/named/lwdnoop.c b/bin/named/lwdnoop.c
new file mode 100644
index 0000000..14d8e0c
--- /dev/null
+++ b/bin/named/lwdnoop.c
@@ -0,0 +1,87 @@
+/*
+ * 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
+ * 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: lwdnoop.c,v 1.13 2008/01/22 23:28:04 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/socket.h>
+#include <isc/util.h>
+
+#include <named/types.h>
+#include <named/lwdclient.h>
+
+void
+ns_lwdclient_processnoop(ns_lwdclient_t *client, lwres_buffer_t *b) {
+ lwres_nooprequest_t *req;
+ lwres_noopresponse_t resp;
+ isc_result_t result;
+ lwres_result_t lwres;
+ isc_region_t r;
+ lwres_buffer_t lwb;
+
+ REQUIRE(NS_LWDCLIENT_ISRECVDONE(client));
+ INSIST(client->byaddr == NULL);
+
+ req = NULL;
+
+ result = lwres_nooprequest_parse(client->clientmgr->lwctx,
+ b, &client->pkt, &req);
+ if (result != LWRES_R_SUCCESS)
+ goto send_error;
+
+ client->pkt.recvlength = LWRES_RECVLENGTH;
+ client->pkt.authtype = 0; /* XXXMLG */
+ client->pkt.authlength = 0;
+ client->pkt.result = LWRES_R_SUCCESS;
+
+ resp.datalength = req->datalength;
+ resp.data = req->data;
+
+ lwres = lwres_noopresponse_render(client->clientmgr->lwctx, &resp,
+ &client->pkt, &lwb);
+ if (lwres != LWRES_R_SUCCESS)
+ goto cleanup_req;
+
+ r.base = lwb.base;
+ r.length = lwb.used;
+ client->sendbuf = r.base;
+ client->sendlength = r.length;
+ result = ns_lwdclient_sendreply(client, &r);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lwb;
+
+ /*
+ * We can now destroy request.
+ */
+ lwres_nooprequest_free(client->clientmgr->lwctx, &req);
+
+ NS_LWDCLIENT_SETSEND(client);
+
+ return;
+
+ cleanup_lwb:
+ lwres_context_freemem(client->clientmgr->lwctx, lwb.base, lwb.length);
+
+ cleanup_req:
+ lwres_nooprequest_free(client->clientmgr->lwctx, &req);
+
+ send_error:
+ ns_lwdclient_errorpktsend(client, LWRES_R_FAILURE);
+}
diff --git a/bin/named/lwresd.8 b/bin/named/lwresd.8
new file mode 100644
index 0000000..2c4e3bc
--- /dev/null
+++ b/bin/named/lwresd.8
@@ -0,0 +1,223 @@
+.\" Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwresd.8,v 1.29 2008/11/07 01:11:19 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwresd
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: June 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRESD" "8" "June 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwresd \- lightweight resolver daemon
+.SH "SYNOPSIS"
+.HP 7
+\fBlwresd\fR [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-C\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-d\ \fR\fB\fIdebug\-level\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-i\ \fR\fB\fIpid\-file\fR\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-P\ \fR\fB\fIport\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-4\fR] [\fB\-6\fR]
+.SH "DESCRIPTION"
+.PP
+\fBlwresd\fR
+is the daemon providing name lookup services to clients that use the BIND 9 lightweight resolver library. It is essentially a stripped\-down, caching\-only name server that answers queries using the BIND 9 lightweight resolver protocol rather than the DNS protocol.
+.PP
+\fBlwresd\fR
+listens for resolver queries on a UDP port on the IPv4 loopback interface, 127.0.0.1. This means that
+\fBlwresd\fR
+can only be used by processes running on the local machine. By default UDP port number 921 is used for lightweight resolver requests and responses.
+.PP
+Incoming lightweight resolver requests are decoded by the server which then resolves them using the DNS protocol. When the DNS lookup completes,
+\fBlwresd\fR
+encodes the answers in the lightweight resolver format and returns them to the client that made the request.
+.PP
+If
+\fI/etc/resolv.conf\fR
+contains any
+\fBnameserver\fR
+entries,
+\fBlwresd\fR
+sends recursive DNS queries to those servers. This is similar to the use of forwarders in a caching name server. If no
+\fBnameserver\fR
+entries are present, or if forwarding fails,
+\fBlwresd\fR
+resolves the queries autonomously starting at the root name servers, using a built\-in list of root server hints.
+.SH "OPTIONS"
+.PP
+\-4
+.RS 4
+Use IPv4 only even if the host machine is capable of IPv6.
+\fB\-4\fR
+and
+\fB\-6\fR
+are mutually exclusive.
+.RE
+.PP
+\-6
+.RS 4
+Use IPv6 only even if the host machine is capable of IPv4.
+\fB\-4\fR
+and
+\fB\-6\fR
+are mutually exclusive.
+.RE
+.PP
+\-c \fIconfig\-file\fR
+.RS 4
+Use
+\fIconfig\-file\fR
+as the configuration file instead of the default,
+\fI/etc/lwresd.conf\fR.
+\fB\-c\fR
+can not be used with
+\fB\-C\fR.
+.RE
+.PP
+\-C \fIconfig\-file\fR
+.RS 4
+Use
+\fIconfig\-file\fR
+as the configuration file instead of the default,
+\fI/etc/resolv.conf\fR.
+\fB\-C\fR
+can not be used with
+\fB\-c\fR.
+.RE
+.PP
+\-d \fIdebug\-level\fR
+.RS 4
+Set the daemon's debug level to
+\fIdebug\-level\fR. Debugging traces from
+\fBlwresd\fR
+become more verbose as the debug level increases.
+.RE
+.PP
+\-f
+.RS 4
+Run the server in the foreground (i.e. do not daemonize).
+.RE
+.PP
+\-g
+.RS 4
+Run the server in the foreground and force all logging to
+\fIstderr\fR.
+.RE
+.PP
+\-i \fIpid\-file\fR
+.RS 4
+Use
+\fIpid\-file\fR
+as the PID file instead of the default,
+\fI/var/run/lwresd/lwresd.pid\fR.
+.RE
+.PP
+\-m \fIflag\fR
+.RS 4
+Turn on memory usage debugging flags. Possible flags are
+\fIusage\fR,
+\fItrace\fR,
+\fIrecord\fR,
+\fIsize\fR, and
+\fImctx\fR. These correspond to the ISC_MEM_DEBUGXXXX flags described in
+\fI<isc/mem.h>\fR.
+.RE
+.PP
+\-n \fI#cpus\fR
+.RS 4
+Create
+\fI#cpus\fR
+worker threads to take advantage of multiple CPUs. If not specified,
+\fBlwresd\fR
+will try to determine the number of CPUs present and create one thread per CPU. If it is unable to determine the number of CPUs, a single worker thread will be created.
+.RE
+.PP
+\-P \fIport\fR
+.RS 4
+Listen for lightweight resolver queries on port
+\fIport\fR. If not specified, the default is port 921.
+.RE
+.PP
+\-p \fIport\fR
+.RS 4
+Send DNS lookups to port
+\fIport\fR. If not specified, the default is port 53. This provides a way of testing the lightweight resolver daemon with a name server that listens for queries on a non\-standard port number.
+.RE
+.PP
+\-s
+.RS 4
+Write memory usage statistics to
+\fIstdout\fR
+on exit.
+.RS
+.B "Note:"
+This option is mainly of interest to BIND 9 developers and may be removed or changed in a future release.
+.RE
+.RE
+.PP
+\-t \fIdirectory\fR
+.RS 4
+Chroot to
+\fIdirectory\fR
+after processing the command line arguments, but before reading the configuration file.
+.RS
+.B "Warning:"
+This option should be used in conjunction with the
+\fB\-u\fR
+option, as chrooting a process running as root doesn't enhance security on most systems; the way
+\fBchroot(2)\fR
+is defined allows a process with root privileges to escape a chroot jail.
+.RE
+.RE
+.PP
+\-u \fIuser\fR
+.RS 4
+Setuid to
+\fIuser\fR
+after completing privileged operations, such as creating sockets that listen on privileged ports.
+.RE
+.PP
+\-v
+.RS 4
+Report the version number and exit.
+.RE
+.SH "FILES"
+.PP
+\fI/etc/resolv.conf\fR
+.RS 4
+The default configuration file.
+.RE
+.PP
+\fI/var/run/lwresd.pid\fR
+.RS 4
+The default process\-id file.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBnamed\fR(8),
+\fBlwres\fR(3),
+\fBresolver\fR(5).
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/bin/named/lwresd.c b/bin/named/lwresd.c
new file mode 100644
index 0000000..4e245fd
--- /dev/null
+++ b/bin/named/lwresd.c
@@ -0,0 +1,870 @@
+/*
+ * 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
+ * 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: lwresd.c,v 1.58 2008/07/23 23:27:54 marka Exp $ */
+
+/*! \file
+ * \brief
+ * Main program for the Lightweight Resolver Daemon.
+ *
+ * To paraphrase the old saying about X11, "It's not a lightweight deamon
+ * for resolvers, it's a deamon for lightweight resolvers".
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/list.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <isccfg/namedconf.h>
+
+#include <dns/log.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+#include <named/config.h>
+#include <named/globals.h>
+#include <named/log.h>
+#include <named/lwaddr.h>
+#include <named/lwresd.h>
+#include <named/lwdclient.h>
+#include <named/lwsearch.h>
+#include <named/server.h>
+
+#define LWRESD_MAGIC ISC_MAGIC('L', 'W', 'R', 'D')
+#define VALID_LWRESD(l) ISC_MAGIC_VALID(l, LWRESD_MAGIC)
+
+#define LWRESLISTENER_MAGIC ISC_MAGIC('L', 'W', 'R', 'L')
+#define VALID_LWRESLISTENER(l) ISC_MAGIC_VALID(l, LWRESLISTENER_MAGIC)
+
+/*!
+ * The total number of clients we can handle will be NTASKS * NRECVS.
+ */
+#define NTASKS 2 /*%< tasks to create to handle lwres queries */
+#define NRECVS 2 /*%< max clients per task */
+
+typedef ISC_LIST(ns_lwreslistener_t) ns_lwreslistenerlist_t;
+
+static ns_lwreslistenerlist_t listeners;
+static isc_mutex_t listeners_lock;
+static isc_once_t once = ISC_ONCE_INIT;
+
+
+static void
+initialize_mutex(void) {
+ RUNTIME_CHECK(isc_mutex_init(&listeners_lock) == ISC_R_SUCCESS);
+}
+
+
+/*%
+ * Wrappers around our memory management stuff, for the lwres functions.
+ */
+void *
+ns__lwresd_memalloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+void
+ns__lwresd_memfree(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto cleanup; \
+ } while (0)
+
+static isc_result_t
+buffer_putstr(isc_buffer_t *b, const char *s) {
+ unsigned int len = strlen(s);
+ if (isc_buffer_availablelength(b) <= len)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putmem(b, (const unsigned char *)s, len);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Convert a resolv.conf file into a config structure.
+ */
+isc_result_t
+ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx,
+ cfg_obj_t **configp)
+{
+ char text[4096];
+ char str[16];
+ isc_buffer_t b;
+ lwres_context_t *lwctx = NULL;
+ lwres_conf_t *lwc = NULL;
+ isc_sockaddr_t sa;
+ isc_netaddr_t na;
+ int i;
+ isc_result_t result;
+ lwres_result_t lwresult;
+
+ lwctx = NULL;
+ lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc,
+ ns__lwresd_memfree,
+ LWRES_CONTEXT_SERVERMODE);
+ if (lwresult != LWRES_R_SUCCESS) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ lwresult = lwres_conf_parse(lwctx, lwresd_g_resolvconffile);
+ if (lwresult != LWRES_R_SUCCESS) {
+ result = DNS_R_SYNTAX;
+ goto cleanup;
+ }
+
+ lwc = lwres_conf_get(lwctx);
+ INSIST(lwc != NULL);
+
+ isc_buffer_init(&b, text, sizeof(text));
+
+ CHECK(buffer_putstr(&b, "options {\n"));
+
+ /*
+ * Build the list of forwarders.
+ */
+ if (lwc->nsnext > 0) {
+ CHECK(buffer_putstr(&b, "\tforwarders {\n"));
+
+ for (i = 0; i < lwc->nsnext; i++) {
+ CHECK(lwaddr_sockaddr_fromlwresaddr(
+ &sa,
+ &lwc->nameservers[i],
+ ns_g_port));
+ isc_netaddr_fromsockaddr(&na, &sa);
+ CHECK(buffer_putstr(&b, "\t\t"));
+ CHECK(isc_netaddr_totext(&na, &b));
+ CHECK(buffer_putstr(&b, ";\n"));
+ }
+ CHECK(buffer_putstr(&b, "\t};\n"));
+ }
+
+ /*
+ * Build the sortlist
+ */
+ if (lwc->sortlistnxt > 0) {
+ CHECK(buffer_putstr(&b, "\tsortlist {\n"));
+ CHECK(buffer_putstr(&b, "\t\t{\n"));
+ CHECK(buffer_putstr(&b, "\t\t\tany;\n"));
+ CHECK(buffer_putstr(&b, "\t\t\t{\n"));
+ for (i = 0; i < lwc->sortlistnxt; i++) {
+ lwres_addr_t *lwaddr = &lwc->sortlist[i].addr;
+ lwres_addr_t *lwmask = &lwc->sortlist[i].mask;
+ unsigned int mask;
+
+ CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwmask, 0));
+ isc_netaddr_fromsockaddr(&na, &sa);
+ result = isc_netaddr_masktoprefixlen(&na, &mask);
+ if (result != ISC_R_SUCCESS) {
+ char addrtext[ISC_NETADDR_FORMATSIZE];
+ isc_netaddr_format(&na, addrtext,
+ sizeof(addrtext));
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD,
+ ISC_LOG_ERROR,
+ "processing sortlist: '%s' is "
+ "not a valid netmask",
+ addrtext);
+ goto cleanup;
+ }
+
+ CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwaddr, 0));
+ isc_netaddr_fromsockaddr(&na, &sa);
+
+ CHECK(buffer_putstr(&b, "\t\t\t\t"));
+ CHECK(isc_netaddr_totext(&na, &b));
+ snprintf(str, sizeof(str), "%u", mask);
+ CHECK(buffer_putstr(&b, "/"));
+ CHECK(buffer_putstr(&b, str));
+ CHECK(buffer_putstr(&b, ";\n"));
+ }
+ CHECK(buffer_putstr(&b, "\t\t\t};\n"));
+ CHECK(buffer_putstr(&b, "\t\t};\n"));
+ CHECK(buffer_putstr(&b, "\t};\n"));
+ }
+
+ CHECK(buffer_putstr(&b, "};\n\n"));
+
+ CHECK(buffer_putstr(&b, "lwres {\n"));
+
+ /*
+ * Build the search path
+ */
+ if (lwc->searchnxt > 0) {
+ if (lwc->searchnxt > 0) {
+ CHECK(buffer_putstr(&b, "\tsearch {\n"));
+ for (i = 0; i < lwc->searchnxt; i++) {
+ CHECK(buffer_putstr(&b, "\t\t\""));
+ CHECK(buffer_putstr(&b, lwc->search[i]));
+ CHECK(buffer_putstr(&b, "\";\n"));
+ }
+ CHECK(buffer_putstr(&b, "\t};\n"));
+ }
+ }
+
+ /*
+ * Build the ndots line
+ */
+ if (lwc->ndots != 1) {
+ CHECK(buffer_putstr(&b, "\tndots "));
+ snprintf(str, sizeof(str), "%u", lwc->ndots);
+ CHECK(buffer_putstr(&b, str));
+ CHECK(buffer_putstr(&b, ";\n"));
+ }
+
+ /*
+ * Build the listen-on line
+ */
+ if (lwc->lwnext > 0) {
+ CHECK(buffer_putstr(&b, "\tlisten-on {\n"));
+
+ for (i = 0; i < lwc->lwnext; i++) {
+ CHECK(lwaddr_sockaddr_fromlwresaddr(&sa,
+ &lwc->lwservers[i],
+ 0));
+ isc_netaddr_fromsockaddr(&na, &sa);
+ CHECK(buffer_putstr(&b, "\t\t"));
+ CHECK(isc_netaddr_totext(&na, &b));
+ CHECK(buffer_putstr(&b, ";\n"));
+ }
+ CHECK(buffer_putstr(&b, "\t};\n"));
+ }
+
+ CHECK(buffer_putstr(&b, "};\n"));
+
+#if 0
+ printf("%.*s\n",
+ (int)isc_buffer_usedlength(&b),
+ (char *)isc_buffer_base(&b));
+#endif
+
+ lwres_conf_clear(lwctx);
+ lwres_context_destroy(&lwctx);
+
+ return (cfg_parse_buffer(pctx, &b, &cfg_type_namedconf, configp));
+
+ cleanup:
+
+ if (lwctx != NULL) {
+ lwres_conf_clear(lwctx);
+ lwres_context_destroy(&lwctx);
+ }
+
+ return (result);
+}
+
+
+/*
+ * Handle lwresd manager objects
+ */
+isc_result_t
+ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres,
+ ns_lwresd_t **lwresdp)
+{
+ ns_lwresd_t *lwresd;
+ const char *vname;
+ dns_rdataclass_t vclass;
+ const cfg_obj_t *obj, *viewobj, *searchobj;
+ const cfg_listelt_t *element;
+ isc_result_t result;
+
+ INSIST(lwresdp != NULL && *lwresdp == NULL);
+
+ lwresd = isc_mem_get(mctx, sizeof(ns_lwresd_t));
+ if (lwresd == NULL)
+ return (ISC_R_NOMEMORY);
+
+ lwresd->mctx = NULL;
+ isc_mem_attach(mctx, &lwresd->mctx);
+ lwresd->view = NULL;
+ lwresd->search = NULL;
+ lwresd->refs = 1;
+
+ obj = NULL;
+ (void)cfg_map_get(lwres, "ndots", &obj);
+ if (obj != NULL)
+ lwresd->ndots = cfg_obj_asuint32(obj);
+ else
+ lwresd->ndots = 1;
+
+ RUNTIME_CHECK(isc_mutex_init(&lwresd->lock) == ISC_R_SUCCESS);
+
+ lwresd->shutting_down = ISC_FALSE;
+
+ viewobj = NULL;
+ (void)cfg_map_get(lwres, "view", &viewobj);
+ if (viewobj != NULL) {
+ vname = cfg_obj_asstring(cfg_tuple_get(viewobj, "name"));
+ obj = cfg_tuple_get(viewobj, "class");
+ result = ns_config_getclass(obj, dns_rdataclass_in, &vclass);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ } else {
+ vname = "_default";
+ vclass = dns_rdataclass_in;
+ }
+
+ result = dns_viewlist_find(&ns_g_server->viewlist, vname, vclass,
+ &lwresd->view);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "couldn't find view %s", vname);
+ goto fail;
+ }
+
+ searchobj = NULL;
+ (void)cfg_map_get(lwres, "search", &searchobj);
+ if (searchobj != NULL) {
+ lwresd->search = NULL;
+ result = ns_lwsearchlist_create(lwresd->mctx,
+ &lwresd->search);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "couldn't create searchlist");
+ goto fail;
+ }
+ for (element = cfg_list_first(searchobj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *search;
+ const char *searchstr;
+ isc_buffer_t namebuf;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+
+ search = cfg_listelt_value(element);
+ searchstr = cfg_obj_asstring(search);
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ isc_buffer_init(&namebuf, searchstr,
+ strlen(searchstr));
+ isc_buffer_add(&namebuf, strlen(searchstr));
+ result = dns_name_fromtext(name, &namebuf,
+ dns_rootname, ISC_FALSE,
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD,
+ ISC_LOG_WARNING,
+ "invalid name %s in searchlist",
+ searchstr);
+ continue;
+ }
+
+ result = ns_lwsearchlist_append(lwresd->search, name);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD,
+ ISC_LOG_WARNING,
+ "couldn't update searchlist");
+ goto fail;
+ }
+ }
+ }
+
+ lwresd->magic = LWRESD_MAGIC;
+
+ *lwresdp = lwresd;
+ return (ISC_R_SUCCESS);
+
+ fail:
+ if (lwresd->view != NULL)
+ dns_view_detach(&lwresd->view);
+ if (lwresd->search != NULL)
+ ns_lwsearchlist_detach(&lwresd->search);
+ if (lwresd->mctx != NULL)
+ isc_mem_detach(&lwresd->mctx);
+ isc_mem_put(mctx, lwresd, sizeof(ns_lwresd_t));
+ return (result);
+}
+
+void
+ns_lwdmanager_attach(ns_lwresd_t *source, ns_lwresd_t **targetp) {
+ INSIST(VALID_LWRESD(source));
+ INSIST(targetp != NULL && *targetp == NULL);
+
+ LOCK(&source->lock);
+ source->refs++;
+ UNLOCK(&source->lock);
+
+ *targetp = source;
+}
+
+void
+ns_lwdmanager_detach(ns_lwresd_t **lwresdp) {
+ ns_lwresd_t *lwresd;
+ isc_mem_t *mctx;
+ isc_boolean_t done = ISC_FALSE;
+
+ INSIST(lwresdp != NULL && *lwresdp != NULL);
+ INSIST(VALID_LWRESD(*lwresdp));
+
+ lwresd = *lwresdp;
+ *lwresdp = NULL;
+
+ LOCK(&lwresd->lock);
+ INSIST(lwresd->refs > 0);
+ lwresd->refs--;
+ if (lwresd->refs == 0)
+ done = ISC_TRUE;
+ UNLOCK(&lwresd->lock);
+
+ if (!done)
+ return;
+
+ dns_view_detach(&lwresd->view);
+ if (lwresd->search != NULL)
+ ns_lwsearchlist_detach(&lwresd->search);
+ mctx = lwresd->mctx;
+ lwresd->magic = 0;
+ isc_mem_put(mctx, lwresd, sizeof(*lwresd));
+ isc_mem_detach(&mctx);
+}
+
+
+/*
+ * Handle listener objects
+ */
+void
+ns_lwreslistener_attach(ns_lwreslistener_t *source,
+ ns_lwreslistener_t **targetp)
+{
+ INSIST(VALID_LWRESLISTENER(source));
+ INSIST(targetp != NULL && *targetp == NULL);
+
+ LOCK(&source->lock);
+ source->refs++;
+ UNLOCK(&source->lock);
+
+ *targetp = source;
+}
+
+void
+ns_lwreslistener_detach(ns_lwreslistener_t **listenerp) {
+ ns_lwreslistener_t *listener;
+ isc_mem_t *mctx;
+ isc_boolean_t done = ISC_FALSE;
+
+ INSIST(listenerp != NULL && *listenerp != NULL);
+ INSIST(VALID_LWRESLISTENER(*listenerp));
+
+ listener = *listenerp;
+
+ LOCK(&listener->lock);
+ INSIST(listener->refs > 0);
+ listener->refs--;
+ if (listener->refs == 0)
+ done = ISC_TRUE;
+ UNLOCK(&listener->lock);
+
+ if (!done)
+ return;
+
+ if (listener->manager != NULL)
+ ns_lwdmanager_detach(&listener->manager);
+
+ if (listener->sock != NULL)
+ isc_socket_detach(&listener->sock);
+
+ listener->magic = 0;
+ mctx = listener->mctx;
+ isc_mem_put(mctx, listener, sizeof(*listener));
+ isc_mem_detach(&mctx);
+ listenerp = NULL;
+}
+
+static isc_result_t
+listener_create(isc_mem_t *mctx, ns_lwresd_t *lwresd,
+ ns_lwreslistener_t **listenerp)
+{
+ ns_lwreslistener_t *listener;
+ isc_result_t result;
+
+ REQUIRE(listenerp != NULL && *listenerp == NULL);
+
+ listener = isc_mem_get(mctx, sizeof(ns_lwreslistener_t));
+ if (listener == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&listener->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, listener, sizeof(ns_lwreslistener_t));
+ return (result);
+ }
+
+ listener->magic = LWRESLISTENER_MAGIC;
+ listener->refs = 1;
+
+ listener->sock = NULL;
+
+ listener->manager = NULL;
+ ns_lwdmanager_attach(lwresd, &listener->manager);
+
+ listener->mctx = NULL;
+ isc_mem_attach(mctx, &listener->mctx);
+
+ ISC_LINK_INIT(listener, link);
+ ISC_LIST_INIT(listener->cmgrs);
+
+ *listenerp = listener;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+listener_bind(ns_lwreslistener_t *listener, isc_sockaddr_t *address) {
+ isc_socket_t *sock = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ int pf;
+
+ pf = isc_sockaddr_pf(address);
+ if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) ||
+ (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS))
+ return (ISC_R_FAMILYNOSUPPORT);
+
+ listener->address = *address;
+
+ if (isc_sockaddr_getport(&listener->address) == 0) {
+ in_port_t port;
+ port = lwresd_g_listenport;
+ if (port == 0)
+ port = LWRES_UDP_PORT;
+ isc_sockaddr_setport(&listener->address, port);
+ }
+
+ sock = NULL;
+ result = isc_socket_create(ns_g_socketmgr, pf,
+ isc_sockettype_udp, &sock);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "failed to create lwres socket: %s",
+ isc_result_totext(result));
+ return (result);
+ }
+
+ result = isc_socket_bind(sock, &listener->address,
+ ISC_SOCKET_REUSEADDRESS);
+ if (result != ISC_R_SUCCESS) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&listener->address, socktext,
+ sizeof(socktext));
+ isc_socket_detach(&sock);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "failed to add lwres socket: %s: %s",
+ socktext, isc_result_totext(result));
+ return (result);
+ }
+ listener->sock = sock;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+listener_copysock(ns_lwreslistener_t *oldlistener,
+ ns_lwreslistener_t *newlistener)
+{
+ newlistener->address = oldlistener->address;
+ isc_socket_attach(oldlistener->sock, &newlistener->sock);
+}
+
+static isc_result_t
+listener_startclients(ns_lwreslistener_t *listener) {
+ ns_lwdclientmgr_t *cm;
+ unsigned int i;
+ isc_result_t result;
+
+ /*
+ * Create the client managers.
+ */
+ result = ISC_R_SUCCESS;
+ for (i = 0; i < NTASKS && result == ISC_R_SUCCESS; i++)
+ result = ns_lwdclientmgr_create(listener, NRECVS,
+ ns_g_taskmgr);
+
+ /*
+ * Ensure that we have created at least one.
+ */
+ if (ISC_LIST_EMPTY(listener->cmgrs))
+ return (result);
+
+ /*
+ * Walk the list of clients and start each one up.
+ */
+ LOCK(&listener->lock);
+ cm = ISC_LIST_HEAD(listener->cmgrs);
+ while (cm != NULL) {
+ result = ns_lwdclient_startrecv(cm);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_ERROR,
+ "could not start lwres "
+ "client handler: %s",
+ isc_result_totext(result));
+ cm = ISC_LIST_NEXT(cm, link);
+ }
+ UNLOCK(&listener->lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+listener_shutdown(ns_lwreslistener_t *listener) {
+ ns_lwdclientmgr_t *cm;
+
+ cm = ISC_LIST_HEAD(listener->cmgrs);
+ while (cm != NULL) {
+ isc_task_shutdown(cm->task);
+ cm = ISC_LIST_NEXT(cm, link);
+ }
+}
+
+static isc_result_t
+find_listener(isc_sockaddr_t *address, ns_lwreslistener_t **listenerp) {
+ ns_lwreslistener_t *listener;
+
+ INSIST(listenerp != NULL && *listenerp == NULL);
+
+ for (listener = ISC_LIST_HEAD(listeners);
+ listener != NULL;
+ listener = ISC_LIST_NEXT(listener, link))
+ {
+ if (!isc_sockaddr_equal(address, &listener->address))
+ continue;
+ *listenerp = listener;
+ return (ISC_R_SUCCESS);
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+void
+ns_lwreslistener_unlinkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm)
+{
+ REQUIRE(VALID_LWRESLISTENER(listener));
+
+ LOCK(&listener->lock);
+ ISC_LIST_UNLINK(listener->cmgrs, cm, link);
+ UNLOCK(&listener->lock);
+}
+
+void
+ns_lwreslistener_linkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm) {
+ REQUIRE(VALID_LWRESLISTENER(listener));
+
+ /*
+ * This does no locking, since it's called early enough that locking
+ * isn't needed.
+ */
+ ISC_LIST_APPEND(listener->cmgrs, cm, link);
+}
+
+static isc_result_t
+configure_listener(isc_sockaddr_t *address, ns_lwresd_t *lwresd,
+ isc_mem_t *mctx, ns_lwreslistenerlist_t *newlisteners)
+{
+ ns_lwreslistener_t *listener, *oldlistener = NULL;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_result_t result;
+
+ (void)find_listener(address, &oldlistener);
+ listener = NULL;
+ result = listener_create(mctx, lwresd, &listener);
+ if (result != ISC_R_SUCCESS) {
+ isc_sockaddr_format(address, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "lwres failed to configure %s: %s",
+ socktext, isc_result_totext(result));
+ return (result);
+ }
+
+ /*
+ * If there's already a listener, don't rebind the socket.
+ */
+ if (oldlistener == NULL) {
+ result = listener_bind(listener, address);
+ if (result != ISC_R_SUCCESS) {
+ ns_lwreslistener_detach(&listener);
+ return (ISC_R_SUCCESS);
+ }
+ } else
+ listener_copysock(oldlistener, listener);
+
+ result = listener_startclients(listener);
+ if (result != ISC_R_SUCCESS) {
+ isc_sockaddr_format(address, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_WARNING,
+ "lwres: failed to start %s: %s", socktext,
+ isc_result_totext(result));
+ ns_lwreslistener_detach(&listener);
+ return (ISC_R_SUCCESS);
+ }
+
+ if (oldlistener != NULL) {
+ /*
+ * Remove the old listener from the old list and shut it down.
+ */
+ ISC_LIST_UNLINK(listeners, oldlistener, link);
+ listener_shutdown(oldlistener);
+ ns_lwreslistener_detach(&oldlistener);
+ } else {
+ isc_sockaddr_format(address, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
+ "lwres listening on %s", socktext);
+ }
+
+ ISC_LIST_APPEND(*newlisteners, listener, link);
+ return (result);
+}
+
+isc_result_t
+ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) {
+ const cfg_obj_t *lwreslist = NULL;
+ const cfg_obj_t *lwres = NULL;
+ const cfg_obj_t *listenerslist = NULL;
+ const cfg_listelt_t *element = NULL;
+ ns_lwreslistener_t *listener;
+ ns_lwreslistenerlist_t newlisteners;
+ isc_result_t result;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t *addrs = NULL;
+ ns_lwresd_t *lwresd = NULL;
+ isc_uint32_t count = 0;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(config != NULL);
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
+
+ ISC_LIST_INIT(newlisteners);
+
+ result = cfg_map_get(config, "lwres", &lwreslist);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+
+ LOCK(&listeners_lock);
+ /*
+ * Run through the new lwres address list, noting sockets that
+ * are already being listened on and moving them to the new list.
+ *
+ * Identifying duplicates addr/port combinations is left to either
+ * the underlying config code, or to the bind attempt getting an
+ * address-in-use error.
+ */
+ for (element = cfg_list_first(lwreslist);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ in_port_t port;
+
+ lwres = cfg_listelt_value(element);
+ CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd));
+
+ port = lwresd_g_listenport;
+ if (port == 0)
+ port = LWRES_UDP_PORT;
+
+ listenerslist = NULL;
+ (void)cfg_map_get(lwres, "listen-on", &listenerslist);
+ if (listenerslist == NULL) {
+ struct in_addr localhost;
+ isc_sockaddr_t address;
+
+ localhost.s_addr = htonl(INADDR_LOOPBACK);
+ isc_sockaddr_fromin(&address, &localhost, port);
+ CHECK(configure_listener(&address, lwresd, mctx,
+ &newlisteners));
+ } else {
+ isc_uint32_t i;
+
+ CHECK(ns_config_getiplist(config, listenerslist,
+ port, mctx, &addrs, &count));
+ for (i = 0; i < count; i++)
+ CHECK(configure_listener(&addrs[i], lwresd,
+ mctx, &newlisteners));
+ ns_config_putiplist(mctx, &addrs, count);
+ }
+ ns_lwdmanager_detach(&lwresd);
+ }
+
+ /*
+ * Shutdown everything on the listeners list, and remove them from
+ * the list. Then put all of the new listeners on it.
+ */
+
+ while (!ISC_LIST_EMPTY(listeners)) {
+ listener = ISC_LIST_HEAD(listeners);
+ ISC_LIST_UNLINK(listeners, listener, link);
+
+ isc_sockaddr_format(&listener->address,
+ socktext, sizeof(socktext));
+
+ listener_shutdown(listener);
+ ns_lwreslistener_detach(&listener);
+
+ isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
+ "lwres no longer listening on %s", socktext);
+ }
+
+ cleanup:
+ ISC_LIST_APPENDLIST(listeners, newlisteners, link);
+
+ if (addrs != NULL)
+ ns_config_putiplist(mctx, &addrs, count);
+
+ if (lwresd != NULL)
+ ns_lwdmanager_detach(&lwresd);
+
+ UNLOCK(&listeners_lock);
+
+ return (result);
+}
+
+void
+ns_lwresd_shutdown(void) {
+ ns_lwreslistener_t *listener;
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
+
+ while (!ISC_LIST_EMPTY(listeners)) {
+ listener = ISC_LIST_HEAD(listeners);
+ ISC_LIST_UNLINK(listeners, listener, link);
+ ns_lwreslistener_detach(&listener);
+ }
+}
diff --git a/bin/named/lwresd.docbook b/bin/named/lwresd.docbook
new file mode 100644
index 0000000..3e72fd3
--- /dev/null
+++ b/bin/named/lwresd.docbook
@@ -0,0 +1,373 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - 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
+ - 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: lwresd.docbook,v 1.18 2008/11/06 05:30:24 marka Exp $ -->
+<refentry>
+ <refentryinfo>
+ <date>June 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>lwresd</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>lwresd</application></refname>
+ <refpurpose>lightweight resolver daemon</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>lwresd</command>
+ <arg><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
+ <arg><option>-C <replaceable class="parameter">config-file</replaceable></option></arg>
+ <arg><option>-d <replaceable class="parameter">debug-level</replaceable></option></arg>
+ <arg><option>-f</option></arg>
+ <arg><option>-g</option></arg>
+ <arg><option>-i <replaceable class="parameter">pid-file</replaceable></option></arg>
+ <arg><option>-m <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg><option>-n <replaceable class="parameter">#cpus</replaceable></option></arg>
+ <arg><option>-P <replaceable class="parameter">port</replaceable></option></arg>
+ <arg><option>-p <replaceable class="parameter">port</replaceable></option></arg>
+ <arg><option>-s</option></arg>
+ <arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-u <replaceable class="parameter">user</replaceable></option></arg>
+ <arg><option>-v</option></arg>
+ <arg><option>-4</option></arg>
+ <arg><option>-6</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para><command>lwresd</command>
+ is the daemon providing name lookup
+ services to clients that use the BIND 9 lightweight resolver
+ library. It is essentially a stripped-down, caching-only name
+ server that answers queries using the BIND 9 lightweight
+ resolver protocol rather than the DNS protocol.
+ </para>
+
+ <para><command>lwresd</command>
+ listens for resolver queries on a
+ UDP port on the IPv4 loopback interface, 127.0.0.1. This
+ means that <command>lwresd</command> can only be used by
+ processes running on the local machine. By default UDP port
+ number 921 is used for lightweight resolver requests and
+ responses.
+ </para>
+ <para>
+ Incoming lightweight resolver requests are decoded by the
+ server which then resolves them using the DNS protocol. When
+ the DNS lookup completes, <command>lwresd</command> encodes
+ the answers in the lightweight resolver format and returns
+ them to the client that made the request.
+ </para>
+ <para>
+ If <filename>/etc/resolv.conf</filename> contains any
+ <option>nameserver</option> entries, <command>lwresd</command>
+ sends recursive DNS queries to those servers. This is similar
+ to the use of forwarders in a caching name server. If no
+ <option>nameserver</option> entries are present, or if
+ forwarding fails, <command>lwresd</command> resolves the
+ queries autonomously starting at the root name servers, using
+ a built-in list of root server hints.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>-4</term>
+ <listitem>
+ <para>
+ Use IPv4 only even if the host machine is capable of IPv6.
+ <option>-4</option> and <option>-6</option> are mutually
+ exclusive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-6</term>
+ <listitem>
+ <para>
+ Use IPv6 only even if the host machine is capable of IPv4.
+ <option>-4</option> and <option>-6</option> are mutually
+ exclusive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <!-- this is in source but not mentioned? does this matter? -->
+ <varlistentry>
+ <term>-c <replaceable class="parameter">config-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">config-file</replaceable> as the
+ configuration file instead of the default,
+ <filename>/etc/lwresd.conf</filename>.
+ <!-- Should this be an absolute path name? -->
+ <option>-c</option> can not be used with <option>-C</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-C <replaceable class="parameter">config-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">config-file</replaceable> as the
+ configuration file instead of the default,
+ <filename>/etc/resolv.conf</filename>.
+ <option>-C</option> can not be used with <option>-c</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">debug-level</replaceable></term>
+ <listitem>
+ <para>
+ Set the daemon's debug level to <replaceable class="parameter">debug-level</replaceable>.
+ Debugging traces from <command>lwresd</command> become
+ more verbose as the debug level increases.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f</term>
+ <listitem>
+ <para>
+ Run the server in the foreground (i.e. do not daemonize).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g</term>
+ <listitem>
+ <para>
+ Run the server in the foreground and force all logging
+ to <filename>stderr</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i <replaceable class="parameter">pid-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">pid-file</replaceable> as the
+ PID file instead of the default,
+ <filename>/var/run/lwresd/lwresd.pid</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Turn on memory usage debugging flags. Possible flags are
+ <replaceable class="parameter">usage</replaceable>,
+ <replaceable class="parameter">trace</replaceable>,
+ <replaceable class="parameter">record</replaceable>,
+ <replaceable class="parameter">size</replaceable>, and
+ <replaceable class="parameter">mctx</replaceable>.
+ These correspond to the ISC_MEM_DEBUGXXXX flags described in
+ <filename>&lt;isc/mem.h&gt;</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">#cpus</replaceable></term>
+ <listitem>
+ <para>
+ Create <replaceable class="parameter">#cpus</replaceable> worker threads
+ to take advantage of multiple CPUs. If not specified,
+ <command>lwresd</command> will try to determine the
+ number of CPUs present and create one thread per CPU.
+ If it is unable to determine the number of CPUs, a
+ single worker thread will be created.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-P <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Listen for lightweight resolver queries on port
+ <replaceable class="parameter">port</replaceable>. If
+ not specified, the default is port 921.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Send DNS lookups to port <replaceable class="parameter">port</replaceable>. If not
+ specified, the default is port 53. This provides a
+ way of testing the lightweight resolver daemon with a
+ name server that listens for queries on a non-standard
+ port number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s</term>
+ <listitem>
+ <para>
+ Write memory usage statistics to <filename>stdout</filename>
+ on exit.
+ </para>
+ <note>
+ <para>
+ This option is mainly of interest to BIND 9 developers
+ and may be removed or changed in a future release.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>Chroot
+ to <replaceable class="parameter">directory</replaceable> after
+ processing the command line arguments, but before
+ reading the configuration file.
+ </para>
+ <warning>
+ <para>
+ This option should be used in conjunction with the
+ <option>-u</option> option, as chrooting a process
+ running as root doesn't enhance security on most
+ systems; the way <function>chroot(2)</function> is
+ defined allows a process with root privileges to
+ escape a chroot jail.
+ </para>
+ </warning>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-u <replaceable class="parameter">user</replaceable></term>
+ <listitem>
+ <para>Setuid
+ to <replaceable class="parameter">user</replaceable> after completing
+ privileged operations, such as creating sockets that
+ listen on privileged ports.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Report the version number and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><filename>/etc/resolv.conf</filename></term>
+ <listitem>
+ <para>
+ The default configuration file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>/var/run/lwresd.pid</filename></term>
+ <listitem>
+ <para>
+ The default process-id file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>lwres</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>resolver</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/named/lwresd.html b/bin/named/lwresd.html
new file mode 100644
index 0000000..65f65e3
--- /dev/null
+++ b/bin/named/lwresd.html
@@ -0,0 +1,225 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwresd.html,v 1.25 2008/11/07 01:11:19 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwresd</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">lwresd</span> &#8212; lightweight resolver daemon</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">lwresd</code> [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-C <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>] [<code class="option">-f</code>] [<code class="option">-g</code>] [<code class="option">-i <em class="replaceable"><code>pid-file</code></em></code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>] [<code class="option">-P <em class="replaceable"><code>port</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-s</code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>] [<code class="option">-v</code>] [<code class="option">-4</code>] [<code class="option">-6</code>]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543464"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">lwresd</strong></span>
+ is the daemon providing name lookup
+ services to clients that use the BIND 9 lightweight resolver
+ library. It is essentially a stripped-down, caching-only name
+ server that answers queries using the BIND 9 lightweight
+ resolver protocol rather than the DNS protocol.
+ </p>
+<p><span><strong class="command">lwresd</strong></span>
+ listens for resolver queries on a
+ UDP port on the IPv4 loopback interface, 127.0.0.1. This
+ means that <span><strong class="command">lwresd</strong></span> can only be used by
+ processes running on the local machine. By default UDP port
+ number 921 is used for lightweight resolver requests and
+ responses.
+ </p>
+<p>
+ Incoming lightweight resolver requests are decoded by the
+ server which then resolves them using the DNS protocol. When
+ the DNS lookup completes, <span><strong class="command">lwresd</strong></span> encodes
+ the answers in the lightweight resolver format and returns
+ them to the client that made the request.
+ </p>
+<p>
+ If <code class="filename">/etc/resolv.conf</code> contains any
+ <code class="option">nameserver</code> entries, <span><strong class="command">lwresd</strong></span>
+ sends recursive DNS queries to those servers. This is similar
+ to the use of forwarders in a caching name server. If no
+ <code class="option">nameserver</code> entries are present, or if
+ forwarding fails, <span><strong class="command">lwresd</strong></span> resolves the
+ queries autonomously starting at the root name servers, using
+ a built-in list of root server hints.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543511"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-4</span></dt>
+<dd><p>
+ Use IPv4 only even if the host machine is capable of IPv6.
+ <code class="option">-4</code> and <code class="option">-6</code> are mutually
+ exclusive.
+ </p></dd>
+<dt><span class="term">-6</span></dt>
+<dd><p>
+ Use IPv6 only even if the host machine is capable of IPv4.
+ <code class="option">-4</code> and <code class="option">-6</code> are mutually
+ exclusive.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>config-file</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>config-file</code></em> as the
+ configuration file instead of the default,
+ <code class="filename">/etc/lwresd.conf</code>.
+
+ <code class="option">-c</code> can not be used with <code class="option">-C</code>.
+ </p></dd>
+<dt><span class="term">-C <em class="replaceable"><code>config-file</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>config-file</code></em> as the
+ configuration file instead of the default,
+ <code class="filename">/etc/resolv.conf</code>.
+ <code class="option">-C</code> can not be used with <code class="option">-c</code>.
+ </p></dd>
+<dt><span class="term">-d <em class="replaceable"><code>debug-level</code></em></span></dt>
+<dd><p>
+ Set the daemon's debug level to <em class="replaceable"><code>debug-level</code></em>.
+ Debugging traces from <span><strong class="command">lwresd</strong></span> become
+ more verbose as the debug level increases.
+ </p></dd>
+<dt><span class="term">-f</span></dt>
+<dd><p>
+ Run the server in the foreground (i.e. do not daemonize).
+ </p></dd>
+<dt><span class="term">-g</span></dt>
+<dd><p>
+ Run the server in the foreground and force all logging
+ to <code class="filename">stderr</code>.
+ </p></dd>
+<dt><span class="term">-i <em class="replaceable"><code>pid-file</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>pid-file</code></em> as the
+ PID file instead of the default,
+ <code class="filename">/var/run/lwresd/lwresd.pid</code>.
+ </p></dd>
+<dt><span class="term">-m <em class="replaceable"><code>flag</code></em></span></dt>
+<dd><p>
+ Turn on memory usage debugging flags. Possible flags are
+ <em class="replaceable"><code>usage</code></em>,
+ <em class="replaceable"><code>trace</code></em>,
+ <em class="replaceable"><code>record</code></em>,
+ <em class="replaceable"><code>size</code></em>, and
+ <em class="replaceable"><code>mctx</code></em>.
+ These correspond to the ISC_MEM_DEBUGXXXX flags described in
+ <code class="filename">&lt;isc/mem.h&gt;</code>.
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>#cpus</code></em></span></dt>
+<dd><p>
+ Create <em class="replaceable"><code>#cpus</code></em> worker threads
+ to take advantage of multiple CPUs. If not specified,
+ <span><strong class="command">lwresd</strong></span> will try to determine the
+ number of CPUs present and create one thread per CPU.
+ If it is unable to determine the number of CPUs, a
+ single worker thread will be created.
+ </p></dd>
+<dt><span class="term">-P <em class="replaceable"><code>port</code></em></span></dt>
+<dd><p>
+ Listen for lightweight resolver queries on port
+ <em class="replaceable"><code>port</code></em>. If
+ not specified, the default is port 921.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd><p>
+ Send DNS lookups to port <em class="replaceable"><code>port</code></em>. If not
+ specified, the default is port 53. This provides a
+ way of testing the lightweight resolver daemon with a
+ name server that listens for queries on a non-standard
+ port number.
+ </p></dd>
+<dt><span class="term">-s</span></dt>
+<dd>
+<p>
+ Write memory usage statistics to <code class="filename">stdout</code>
+ on exit.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ This option is mainly of interest to BIND 9 developers
+ and may be removed or changed in a future release.
+ </p>
+</div>
+</dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+<p>Chroot
+ to <em class="replaceable"><code>directory</code></em> after
+ processing the command line arguments, but before
+ reading the configuration file.
+ </p>
+<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+<p>
+ This option should be used in conjunction with the
+ <code class="option">-u</code> option, as chrooting a process
+ running as root doesn't enhance security on most
+ systems; the way <code class="function">chroot(2)</code> is
+ defined allows a process with root privileges to
+ escape a chroot jail.
+ </p>
+</div>
+</dd>
+<dt><span class="term">-u <em class="replaceable"><code>user</code></em></span></dt>
+<dd><p>Setuid
+ to <em class="replaceable"><code>user</code></em> after completing
+ privileged operations, such as creating sockets that
+ listen on privileged ports.
+ </p></dd>
+<dt><span class="term">-v</span></dt>
+<dd><p>
+ Report the version number and exit.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543928"></a><h2>FILES</h2>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="filename">/etc/resolv.conf</code></span></dt>
+<dd><p>
+ The default configuration file.
+ </p></dd>
+<dt><span class="term"><code class="filename">/var/run/lwresd.pid</code></span></dt>
+<dd><p>
+ The default process-id file.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543968"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">lwres</span>(3)</span>,
+ <span class="citerefentry"><span class="refentrytitle">resolver</span>(5)</span>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544002"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/named/lwsearch.c b/bin/named/lwsearch.c
new file mode 100644
index 0000000..6754c98
--- /dev/null
+++ b/bin/named/lwsearch.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwsearch.c,v 1.13 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/name.h>
+#include <dns/types.h>
+
+#include <named/lwsearch.h>
+#include <named/types.h>
+
+#define LWSEARCHLIST_MAGIC ISC_MAGIC('L', 'W', 'S', 'L')
+#define VALID_LWSEARCHLIST(l) ISC_MAGIC_VALID(l, LWSEARCHLIST_MAGIC)
+
+isc_result_t
+ns_lwsearchlist_create(isc_mem_t *mctx, ns_lwsearchlist_t **listp) {
+ ns_lwsearchlist_t *list;
+ isc_result_t result;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(listp != NULL && *listp == NULL);
+
+ list = isc_mem_get(mctx, sizeof(ns_lwsearchlist_t));
+ if (list == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&list->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, list, sizeof(ns_lwsearchlist_t));
+ return (result);
+ }
+ list->mctx = NULL;
+ isc_mem_attach(mctx, &list->mctx);
+ list->refs = 1;
+ ISC_LIST_INIT(list->names);
+ list->magic = LWSEARCHLIST_MAGIC;
+
+ *listp = list;
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_lwsearchlist_attach(ns_lwsearchlist_t *source, ns_lwsearchlist_t **target) {
+ REQUIRE(VALID_LWSEARCHLIST(source));
+ REQUIRE(target != NULL && *target == NULL);
+
+ LOCK(&source->lock);
+ INSIST(source->refs > 0);
+ source->refs++;
+ INSIST(source->refs != 0);
+ UNLOCK(&source->lock);
+
+ *target = source;
+}
+
+void
+ns_lwsearchlist_detach(ns_lwsearchlist_t **listp) {
+ ns_lwsearchlist_t *list;
+ isc_mem_t *mctx;
+
+ REQUIRE(listp != NULL);
+ list = *listp;
+ REQUIRE(VALID_LWSEARCHLIST(list));
+
+ LOCK(&list->lock);
+ INSIST(list->refs > 0);
+ list->refs--;
+ UNLOCK(&list->lock);
+
+ *listp = NULL;
+ if (list->refs != 0)
+ return;
+
+ mctx = list->mctx;
+ while (!ISC_LIST_EMPTY(list->names)) {
+ dns_name_t *name = ISC_LIST_HEAD(list->names);
+ ISC_LIST_UNLINK(list->names, name, link);
+ dns_name_free(name, list->mctx);
+ isc_mem_put(list->mctx, name, sizeof(dns_name_t));
+ }
+ list->magic = 0;
+ isc_mem_put(mctx, list, sizeof(ns_lwsearchlist_t));
+ isc_mem_detach(&mctx);
+}
+
+isc_result_t
+ns_lwsearchlist_append(ns_lwsearchlist_t *list, dns_name_t *name) {
+ dns_name_t *newname;
+ isc_result_t result;
+
+ REQUIRE(VALID_LWSEARCHLIST(list));
+ REQUIRE(name != NULL);
+
+ newname = isc_mem_get(list->mctx, sizeof(dns_name_t));
+ if (newname == NULL)
+ return (ISC_R_NOMEMORY);
+ dns_name_init(newname, NULL);
+ result = dns_name_dup(name, list->mctx, newname);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(list->mctx, newname, sizeof(dns_name_t));
+ return (result);
+ }
+ ISC_LINK_INIT(newname, link);
+ ISC_LIST_APPEND(list->names, newname, link);
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_lwsearchctx_init(ns_lwsearchctx_t *sctx, ns_lwsearchlist_t *list,
+ dns_name_t *name, unsigned int ndots)
+{
+ INSIST(sctx != NULL);
+ sctx->relname = name;
+ sctx->searchname = NULL;
+ sctx->doneexact = ISC_FALSE;
+ sctx->exactfirst = ISC_FALSE;
+ sctx->ndots = ndots;
+ if (dns_name_isabsolute(name) || list == NULL) {
+ sctx->list = NULL;
+ return;
+ }
+ sctx->list = list;
+ sctx->searchname = ISC_LIST_HEAD(sctx->list->names);
+ if (dns_name_countlabels(name) > ndots)
+ sctx->exactfirst = ISC_TRUE;
+}
+
+void
+ns_lwsearchctx_first(ns_lwsearchctx_t *sctx) {
+ REQUIRE(sctx != NULL);
+ UNUSED(sctx);
+}
+
+isc_result_t
+ns_lwsearchctx_next(ns_lwsearchctx_t *sctx) {
+ REQUIRE(sctx != NULL);
+
+ if (sctx->list == NULL)
+ return (ISC_R_NOMORE);
+
+ if (sctx->searchname == NULL) {
+ INSIST (!sctx->exactfirst || sctx->doneexact);
+ if (sctx->exactfirst || sctx->doneexact)
+ return (ISC_R_NOMORE);
+ sctx->doneexact = ISC_TRUE;
+ } else {
+ if (sctx->exactfirst && !sctx->doneexact)
+ sctx->doneexact = ISC_TRUE;
+ else {
+ sctx->searchname = ISC_LIST_NEXT(sctx->searchname,
+ link);
+ if (sctx->searchname == NULL && sctx->doneexact)
+ return (ISC_R_NOMORE);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_lwsearchctx_current(ns_lwsearchctx_t *sctx, dns_name_t *absname) {
+ dns_name_t *tname;
+ isc_boolean_t useexact = ISC_FALSE;
+
+ REQUIRE(sctx != NULL);
+
+ if (sctx->list == NULL ||
+ sctx->searchname == NULL ||
+ (sctx->exactfirst && !sctx->doneexact))
+ useexact = ISC_TRUE;
+
+ if (useexact) {
+ if (dns_name_isabsolute(sctx->relname))
+ tname = NULL;
+ else
+ tname = dns_rootname;
+ } else
+ tname = sctx->searchname;
+
+ return (dns_name_concatenate(sctx->relname, tname, absname, NULL));
+}
diff --git a/bin/named/main.c b/bin/named/main.c
new file mode 100644
index 0000000..aa6575a
--- /dev/null
+++ b/bin/named/main.c
@@ -0,0 +1,991 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: main.c,v 1.166 2008/10/24 01:24:54 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/os.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/resource.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <isccc/result.h>
+
+#include <dns/dispatch.h>
+#include <dns/name.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+#include <dst/result.h>
+
+/*
+ * Defining NS_MAIN provides storage declarations (rather than extern)
+ * for variables in named/globals.h.
+ */
+#define NS_MAIN 1
+
+#include <named/builtin.h>
+#include <named/control.h>
+#include <named/globals.h> /* Explicit, though named/log.h includes it. */
+#include <named/interfacemgr.h>
+#include <named/log.h>
+#include <named/os.h>
+#include <named/server.h>
+#include <named/lwresd.h>
+#include <named/main.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#endif
+
+/*
+ * Include header files for database drivers here.
+ */
+/* #include "xxdb.h" */
+
+/*
+ * Include DLZ drivers if appropriate.
+ */
+#ifdef DLZ
+#include <dlz/dlz_drivers.h>
+#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;
+
+void
+ns_main_earlywarning(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ if (ns_g_lctx != NULL) {
+ isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
+ format, args);
+ } else {
+ fprintf(stderr, "%s: ", program_name);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ va_end(args);
+}
+
+void
+ns_main_earlyfatal(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ if (ns_g_lctx != NULL) {
+ isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ format, args);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "exiting (due to early fatal error)");
+ } else {
+ fprintf(stderr, "%s: ", program_name);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+ va_end(args);
+
+ exit(1);
+}
+
+static void
+assertion_failed(const char *file, int line, isc_assertiontype_t type,
+ const char *cond)
+{
+ /*
+ * Handle assertion failures.
+ */
+
+ if (ns_g_lctx != NULL) {
+ /*
+ * Reset the assetion callback in case it is the log
+ * routines causing the assertion.
+ */
+ isc_assertion_setcallback(NULL);
+
+ 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);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "exiting (due to assertion failure)");
+ } else {
+ fprintf(stderr, "%s:%d: %s(%s) failed\n",
+ file, line, isc_assertion_typetotext(type), cond);
+ fflush(stderr);
+ }
+
+ if (ns_g_coreok)
+ abort();
+ exit(1);
+}
+
+static void
+library_fatal_error(const char *file, int line, const char *format,
+ va_list args) ISC_FORMAT_PRINTF(3, 0);
+
+static void
+library_fatal_error(const char *file, int line, const char *format,
+ va_list args)
+{
+ /*
+ * Handle isc_error_fatal() calls from our libraries.
+ */
+
+ if (ns_g_lctx != NULL) {
+ /*
+ * Reset the error callback in case it is the log
+ * routines causing the assertion.
+ */
+ isc_error_setfatal(NULL);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "%s:%d: fatal error:", file, line);
+ isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ format, args);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
+ "exiting (due to fatal error in library)");
+ } else {
+ fprintf(stderr, "%s:%d: fatal error: ", file, line);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+
+ if (ns_g_coreok)
+ abort();
+ exit(1);
+}
+
+static void
+library_unexpected_error(const char *file, int line, const char *format,
+ va_list args) ISC_FORMAT_PRINTF(3, 0);
+
+static void
+library_unexpected_error(const char *file, int line, const char *format,
+ va_list args)
+{
+ /*
+ * Handle isc_error_unexpected() calls from our libraries.
+ */
+
+ if (ns_g_lctx != NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_ERROR,
+ "%s:%d: unexpected error:", file, line);
+ isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_ERROR,
+ format, args);
+ } else {
+ fprintf(stderr, "%s:%d: fatal error: ", file, line);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+}
+
+static void
+lwresd_usage(void) {
+ fprintf(stderr,
+ "usage: lwresd [-4|-6] [-c conffile | -C resolvconffile] "
+ "[-d debuglevel]\n"
+ " [-f|-g] [-n number_of_cpus] [-p port] "
+ "[-P listen-port] [-s]\n"
+ " [-t chrootdir] [-u username] [-i pidfile]\n"
+ " [-m {usage|trace|record|size|mctx}]\n");
+}
+
+static void
+usage(void) {
+ if (ns_g_lwresdonly) {
+ lwresd_usage();
+ return;
+ }
+ 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"
+ " [-m {usage|trace|record|size|mctx}]\n");
+}
+
+static void
+save_command_line(int argc, char *argv[]) {
+ int i;
+ char *src;
+ char *dst;
+ char *eob;
+ const char truncated[] = "...";
+ isc_boolean_t quoted = ISC_FALSE;
+
+ dst = saved_command_line;
+ eob = saved_command_line + sizeof(saved_command_line);
+
+ for (i = 1; i < argc && dst < eob; i++) {
+ *dst++ = ' ';
+
+ src = argv[i];
+ while (*src != '\0' && dst < eob) {
+ /*
+ * This won't perfectly produce a shell-independent
+ * pastable command line in all circumstances, but
+ * comes close, and for practical purposes will
+ * nearly always be fine.
+ */
+ if (quoted || isalnum(*src & 0xff) ||
+ *src == '-' || *src == '_' ||
+ *src == '.' || *src == '/') {
+ *dst++ = *src++;
+ quoted = ISC_FALSE;
+ } else {
+ *dst++ = '\\';
+ quoted = ISC_TRUE;
+ }
+ }
+ }
+
+ INSIST(sizeof(saved_command_line) >= sizeof(truncated));
+
+ if (dst == eob)
+ strcpy(eob - sizeof(truncated), truncated);
+ else
+ *dst = '\0';
+}
+
+static int
+parse_int(char *arg, const char *desc) {
+ char *endp;
+ int tmp;
+ long int ltmp;
+
+ ltmp = strtol(arg, &endp, 10);
+ tmp = (int) ltmp;
+ if (*endp != '\0')
+ ns_main_earlyfatal("%s '%s' must be numeric", desc, arg);
+ if (tmp < 0 || tmp != ltmp)
+ ns_main_earlyfatal("%s '%s' out of range", desc, arg);
+ return (tmp);
+}
+
+static struct flag_def {
+ const char *name;
+ unsigned int value;
+} mem_debug_flags[] = {
+ { "trace", ISC_MEM_DEBUGTRACE },
+ { "record", ISC_MEM_DEBUGRECORD },
+ { "usage", ISC_MEM_DEBUGUSAGE },
+ { "size", ISC_MEM_DEBUGSIZE },
+ { "mctx", ISC_MEM_DEBUGCTX },
+ { NULL, 0 }
+};
+
+static void
+set_flags(const char *arg, struct flag_def *defs, unsigned int *ret) {
+ for (;;) {
+ const struct flag_def *def;
+ const char *end = strchr(arg, ',');
+ int arglen;
+ if (end == NULL)
+ end = arg + strlen(arg);
+ arglen = end - arg;
+ for (def = defs; def->name != NULL; def++) {
+ if (arglen == (int)strlen(def->name) &&
+ memcmp(arg, def->name, arglen) == 0) {
+ *ret |= def->value;
+ goto found;
+ }
+ }
+ ns_main_earlyfatal("unrecognized flag '%.*s'", arglen, arg);
+ found:
+ if (*end == '\0')
+ break;
+ arg = end + 1;
+ }
+}
+
+static void
+parse_command_line(int argc, char *argv[]) {
+ int ch;
+ int port;
+ isc_boolean_t disable6 = ISC_FALSE;
+ isc_boolean_t disable4 = ISC_FALSE;
+
+ save_command_line(argc, argv);
+
+ isc_commandline_errprint = ISC_FALSE;
+ while ((ch = isc_commandline_parse(argc, argv,
+ "46c:C:d:fgi:lm:n:N:p:P:"
+ "sS:t:T:u:vVx:")) != -1) {
+ switch (ch) {
+ case '4':
+ if (disable4)
+ ns_main_earlyfatal("cannot specify -4 and -6");
+ if (isc_net_probeipv4() != ISC_R_SUCCESS)
+ ns_main_earlyfatal("IPv4 not supported by OS");
+ isc_net_disableipv6();
+ disable6 = ISC_TRUE;
+ break;
+ case '6':
+ if (disable6)
+ ns_main_earlyfatal("cannot specify -4 and -6");
+ if (isc_net_probeipv6() != ISC_R_SUCCESS)
+ ns_main_earlyfatal("IPv6 not supported by OS");
+ isc_net_disableipv4();
+ disable4 = ISC_TRUE;
+ break;
+ case 'c':
+ ns_g_conffile = isc_commandline_argument;
+ lwresd_g_conffile = isc_commandline_argument;
+ if (lwresd_g_useresolvconf)
+ ns_main_earlyfatal("cannot specify -c and -C");
+ ns_g_conffileset = ISC_TRUE;
+ break;
+ case 'C':
+ lwresd_g_resolvconffile = isc_commandline_argument;
+ if (ns_g_conffileset)
+ ns_main_earlyfatal("cannot specify -c and -C");
+ lwresd_g_useresolvconf = ISC_TRUE;
+ break;
+ case 'd':
+ ns_g_debuglevel = parse_int(isc_commandline_argument,
+ "debug level");
+ break;
+ case 'f':
+ ns_g_foreground = ISC_TRUE;
+ break;
+ case 'g':
+ ns_g_foreground = ISC_TRUE;
+ ns_g_logstderr = ISC_TRUE;
+ break;
+ /* XXXBEW -i should be removed */
+ case 'i':
+ lwresd_g_defaultpidfile = isc_commandline_argument;
+ break;
+ case 'l':
+ ns_g_lwresdonly = ISC_TRUE;
+ break;
+ case 'm':
+ set_flags(isc_commandline_argument, mem_debug_flags,
+ &isc_mem_debugging);
+ break;
+ case 'N': /* Deprecated. */
+ case 'n':
+ ns_g_cpus = parse_int(isc_commandline_argument,
+ "number of cpus");
+ if (ns_g_cpus == 0)
+ ns_g_cpus = 1;
+ break;
+ case 'p':
+ port = parse_int(isc_commandline_argument, "port");
+ if (port < 1 || port > 65535)
+ ns_main_earlyfatal("port '%s' out of range",
+ isc_commandline_argument);
+ ns_g_port = port;
+ break;
+ /* XXXBEW Should -P be removed? */
+ case 'P':
+ port = parse_int(isc_commandline_argument, "port");
+ if (port < 1 || port > 65535)
+ ns_main_earlyfatal("port '%s' out of range",
+ isc_commandline_argument);
+ lwresd_g_listenport = port;
+ break;
+ case 's':
+ /* XXXRTH temporary syntax */
+ want_stats = ISC_TRUE;
+ break;
+ case 'S':
+ maxsocks = parse_int(isc_commandline_argument,
+ "max number of sockets");
+ break;
+ case 't':
+ /* XXXJAB should we make a copy? */
+ ns_g_chrootdir = isc_commandline_argument;
+ break;
+ case 'T':
+ /*
+ * clienttest: make clients single shot with their
+ * own memory context.
+ */
+ if (strcmp(isc_commandline_argument, "clienttest") == 0)
+ ns_g_clienttest = ISC_TRUE;
+ else
+ fprintf(stderr, "unknown -T flag '%s\n",
+ isc_commandline_argument);
+ break;
+ case 'u':
+ ns_g_username = isc_commandline_argument;
+ break;
+ case 'v':
+ printf("BIND %s\n", ns_g_version);
+ exit(0);
+ case 'V':
+ printf("BIND %s built with %s\n", ns_g_version,
+ ns_g_configargs);
+ exit(0);
+ case '?':
+ usage();
+ if (isc_commandline_option == '?')
+ exit(0);
+ ns_main_earlyfatal("unknown option '-%c'",
+ isc_commandline_option);
+ default:
+ ns_main_earlyfatal("parsing options returned %d", ch);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc > 0) {
+ usage();
+ ns_main_earlyfatal("extra command line arguments");
+ }
+}
+
+static isc_result_t
+create_managers(void) {
+ isc_result_t result;
+ unsigned int socks;
+
+#ifdef ISC_PLATFORM_USETHREADS
+ if (ns_g_cpus == 0)
+ ns_g_cpus = ns_g_cpus_detected;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "found %u CPU%s, using %u worker thread%s",
+ ns_g_cpus_detected, ns_g_cpus_detected == 1 ? "" : "s",
+ ns_g_cpus, ns_g_cpus == 1 ? "" : "s");
+#else
+ ns_g_cpus = 1;
+#endif
+ result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_taskmgr_create() failed: %s",
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ result = isc_timermgr_create(ns_g_mctx, &ns_g_timermgr);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_timermgr_create() failed: %s",
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ result = isc_socketmgr_create2(ns_g_mctx, &ns_g_socketmgr, maxsocks);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socketmgr_create() failed: %s",
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+ result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &socks);
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "using up to %u sockets", socks);
+ }
+
+ result = isc_entropy_create(ns_g_mctx, &ns_g_entropy);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_entropy_create() failed: %s",
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ result = isc_hash_create(ns_g_mctx, ns_g_entropy, DNS_NAME_MAXWIRE);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_hash_create() failed: %s",
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+destroy_managers(void) {
+ ns_lwresd_shutdown();
+
+ isc_entropy_detach(&ns_g_entropy);
+ if (ns_g_fallbackentropy != NULL)
+ isc_entropy_detach(&ns_g_fallbackentropy);
+
+ /*
+ * isc_taskmgr_destroy() will block until all tasks have exited,
+ */
+ isc_taskmgr_destroy(&ns_g_taskmgr);
+ isc_timermgr_destroy(&ns_g_timermgr);
+ isc_socketmgr_destroy(&ns_g_socketmgr);
+
+ /*
+ * isc_hash_destroy() cannot be called as long as a resolver may be
+ * running. Calling this after isc_taskmgr_destroy() ensures the
+ * call is safe.
+ */
+ isc_hash_destroy();
+}
+
+static void
+setup(void) {
+ isc_result_t result;
+ isc_resourcevalue_t old_openfiles;
+#ifdef HAVE_LIBSCF
+ char *instance = NULL;
+#endif
+
+ /*
+ * Get the user and group information before changing the root
+ * directory, so the administrator does not need to keep a copy
+ * of the user and group databases in the chroot'ed environment.
+ */
+ ns_os_inituserinfo(ns_g_username);
+
+ /*
+ * Initialize time conversion information
+ */
+ ns_os_tzset();
+
+ ns_os_opendevnull();
+
+#ifdef HAVE_LIBSCF
+ /* Check if named is under smf control, before chroot. */
+ result = ns_smf_get_instance(&instance, 0, ns_g_mctx);
+ /* We don't care about instance, just check if we got one. */
+ if (result == ISC_R_SUCCESS)
+ ns_smf_got_instance = 1;
+ else
+ ns_smf_got_instance = 0;
+ if (instance != NULL)
+ isc_mem_free(ns_g_mctx, instance);
+#endif /* HAVE_LIBSCF */
+
+#ifdef PATH_RANDOMDEV
+ /*
+ * Initialize system's random device as fallback entropy source
+ * if running chroot'ed.
+ */
+ if (ns_g_chrootdir != NULL) {
+ result = isc_entropy_create(ns_g_mctx, &ns_g_fallbackentropy);
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("isc_entropy_create() failed: %s",
+ isc_result_totext(result));
+
+ result = isc_entropy_createfilesource(ns_g_fallbackentropy,
+ PATH_RANDOMDEV);
+ if (result != ISC_R_SUCCESS) {
+ ns_main_earlywarning("could not open pre-chroot "
+ "entropy source %s: %s",
+ PATH_RANDOMDEV,
+ isc_result_totext(result));
+ isc_entropy_detach(&ns_g_fallbackentropy);
+ }
+ }
+#endif
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * Check for the number of cpu's before ns_os_chroot().
+ */
+ ns_g_cpus_detected = isc_os_ncpus();
+#endif
+
+ ns_os_chroot(ns_g_chrootdir);
+
+ /*
+ * For operating systems which have a capability mechanism, now
+ * is the time to switch to minimal privs and change our user id.
+ * On traditional UNIX systems, this call will be a no-op, and we
+ * will change the user ID after reading the config file the first
+ * time. (We need to read the config file to know which possibly
+ * privileged ports to bind() to.)
+ */
+ ns_os_minprivs();
+
+ result = ns_log_init(ISC_TF(ns_g_username != NULL));
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("ns_log_init() failed: %s",
+ isc_result_totext(result));
+
+ /*
+ * Now is the time to daemonize (if we're not running in the
+ * foreground). We waited until now because we wanted to get
+ * a valid logging context setup. We cannot daemonize any later,
+ * because calling create_managers() will create threads, which
+ * would be lost after fork().
+ */
+ if (!ns_g_foreground)
+ ns_os_daemonize();
+
+ /*
+ * We call isc_app_start() here as some versions of FreeBSD's fork()
+ * destroys all the signal handling it sets up.
+ */
+ result = isc_app_start();
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("isc_app_start() failed: %s",
+ isc_result_totext(result));
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE, "starting BIND %s%s", ns_g_version,
+ saved_command_line);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE, "built with %s", ns_g_configargs);
+
+ /*
+ * Get the initial resource limits.
+ */
+ (void)isc_resource_getlimit(isc_resource_stacksize,
+ &ns_g_initstacksize);
+ (void)isc_resource_getlimit(isc_resource_datasize,
+ &ns_g_initdatasize);
+ (void)isc_resource_getlimit(isc_resource_coresize,
+ &ns_g_initcoresize);
+ (void)isc_resource_getlimit(isc_resource_openfiles,
+ &ns_g_initopenfiles);
+
+ /*
+ * System resources cannot effectively be tuned on some systems.
+ * Raise the limit in such cases for safety.
+ */
+ old_openfiles = ns_g_initopenfiles;
+ ns_os_adjustnofile();
+ (void)isc_resource_getlimit(isc_resource_openfiles,
+ &ns_g_initopenfiles);
+ if (old_openfiles != ns_g_initopenfiles) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
+ "adjusted limit on open files from "
+ "%" ISC_PRINT_QUADFORMAT "u to "
+ "%" ISC_PRINT_QUADFORMAT "u",
+ old_openfiles, ns_g_initopenfiles);
+ }
+
+ /*
+ * If the named configuration filename is relative, prepend the current
+ * directory's name before possibly changing to another directory.
+ */
+ if (! isc_file_isabsolute(ns_g_conffile)) {
+ result = isc_file_absolutepath(ns_g_conffile,
+ absolute_conffile,
+ sizeof(absolute_conffile));
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("could not construct absolute path of "
+ "configuration file: %s",
+ isc_result_totext(result));
+ ns_g_conffile = absolute_conffile;
+ }
+
+ /*
+ * Record the server's startup time.
+ */
+ result = isc_time_now(&ns_g_boottime);
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("isc_time_now() failed: %s",
+ isc_result_totext(result));
+
+ result = create_managers();
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("create_managers() failed: %s",
+ isc_result_totext(result));
+
+ ns_builtin_init();
+
+ /*
+ * Add calls to register sdb drivers here.
+ */
+ /* xxdb_init(); */
+
+#ifdef DLZ
+ /*
+ * Registyer any DLZ drivers.
+ */
+ result = dlz_drivers_init();
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("dlz_drivers_init() failed: %s",
+ isc_result_totext(result));
+#endif
+
+ ns_server_create(ns_g_mctx, &ns_g_server);
+}
+
+static void
+cleanup(void) {
+ destroy_managers();
+
+ ns_server_destroy(&ns_g_server);
+
+ ns_builtin_deinit();
+
+ /*
+ * Add calls to unregister sdb drivers here.
+ */
+ /* xxdb_clear(); */
+
+#ifdef DLZ
+ /*
+ * Unregister any DLZ drivers.
+ */
+ dlz_drivers_clear();
+#endif
+
+ dns_name_destroy();
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
+ ISC_LOG_NOTICE, "exiting");
+ ns_log_shutdown();
+}
+
+static char *memstats = NULL;
+
+void
+ns_main_setmemstats(const char *filename) {
+ /*
+ * Caller has to ensure locking.
+ */
+
+ if (memstats != NULL) {
+ free(memstats);
+ memstats = NULL;
+ }
+ if (filename == NULL)
+ return;
+ memstats = malloc(strlen(filename) + 1);
+ if (memstats)
+ strcpy(memstats, filename);
+}
+
+#ifdef HAVE_LIBSCF
+/*
+ * Get FMRI for the named process.
+ */
+isc_result_t
+ns_smf_get_instance(char **ins_name, int debug, isc_mem_t *mctx) {
+ scf_handle_t *h = NULL;
+ int namelen;
+ char *instance;
+
+ REQUIRE(ins_name != NULL && *ins_name == NULL);
+
+ if ((h = scf_handle_create(SCF_VERSION)) == NULL) {
+ if (debug)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "scf_handle_create() failed: %s",
+ scf_strerror(scf_error()));
+ return (ISC_R_FAILURE);
+ }
+
+ if (scf_handle_bind(h) == -1) {
+ if (debug)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "scf_handle_bind() failed: %s",
+ scf_strerror(scf_error()));
+ scf_handle_destroy(h);
+ return (ISC_R_FAILURE);
+ }
+
+ if ((namelen = scf_myname(h, NULL, 0)) == -1) {
+ if (debug)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "scf_myname() failed: %s",
+ scf_strerror(scf_error()));
+ scf_handle_destroy(h);
+ return (ISC_R_FAILURE);
+ }
+
+ if ((instance = isc_mem_allocate(mctx, namelen + 1)) == NULL) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "ns_smf_get_instance memory "
+ "allocation failed: %s",
+ isc_result_totext(ISC_R_NOMEMORY));
+ scf_handle_destroy(h);
+ return (ISC_R_FAILURE);
+ }
+
+ if (scf_myname(h, instance, namelen + 1) == -1) {
+ if (debug)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "scf_myname() failed: %s",
+ scf_strerror(scf_error()));
+ scf_handle_destroy(h);
+ isc_mem_free(mctx, instance);
+ return (ISC_R_FAILURE);
+ }
+
+ scf_handle_destroy(h);
+ *ins_name = instance;
+ return (ISC_R_SUCCESS);
+}
+#endif /* HAVE_LIBSCF */
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+#ifdef HAVE_LIBSCF
+ char *instance = NULL;
+#endif
+
+ /*
+ * Record version in core image.
+ * strings named.core | grep "named version:"
+ */
+ strlcat(version,
+#ifdef __DATE__
+ "named version: BIND " VERSION " (" __DATE__ ")",
+#else
+ "named version: BIND " VERSION,
+#endif
+ sizeof(version));
+ result = isc_file_progname(*argv, program_name, sizeof(program_name));
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("program name too long");
+
+ if (strcmp(program_name, "lwresd") == 0)
+ ns_g_lwresdonly = ISC_TRUE;
+
+ isc_assertion_setcallback(assertion_failed);
+ isc_error_setfatal(library_fatal_error);
+ isc_error_setunexpected(library_unexpected_error);
+
+ ns_os_init(program_name);
+
+ dns_result_register();
+ dst_result_register();
+ isccc_result_register();
+
+ parse_command_line(argc, argv);
+
+ /*
+ * Warn about common configuration error.
+ */
+ if (ns_g_chrootdir != NULL) {
+ int len = strlen(ns_g_chrootdir);
+ if (strncmp(ns_g_chrootdir, ns_g_conffile, len) == 0 &&
+ (ns_g_conffile[len] == '/' || ns_g_conffile[len] == '\\'))
+ ns_main_earlywarning("config filename (-c %s) contains "
+ "chroot path (-t %s)",
+ ns_g_conffile, ns_g_chrootdir);
+ }
+
+ result = isc_mem_create(0, 0, &ns_g_mctx);
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlyfatal("isc_mem_create() failed: %s",
+ isc_result_totext(result));
+ isc_mem_setname(ns_g_mctx, "main", NULL);
+
+ setup();
+
+ /*
+ * Start things running and then wait for a shutdown request
+ * or reload.
+ */
+ do {
+ result = isc_app_run();
+
+ if (result == ISC_R_RELOAD) {
+ ns_server_reloadwanted(ns_g_server);
+ } else if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_run(): %s",
+ isc_result_totext(result));
+ /*
+ * Force exit.
+ */
+ result = ISC_R_SUCCESS;
+ }
+ } while (result != ISC_R_SUCCESS);
+
+#ifdef HAVE_LIBSCF
+ if (ns_smf_want_disable == 1) {
+ result = ns_smf_get_instance(&instance, 1, ns_g_mctx);
+ if (result == ISC_R_SUCCESS && instance != NULL) {
+ if (smf_disable_instance(instance, 0) != 0)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "smf_disable_instance() "
+ "failed for %s : %s",
+ instance,
+ scf_strerror(scf_error()));
+ }
+ if (instance != NULL)
+ isc_mem_free(ns_g_mctx, instance);
+ }
+#endif /* HAVE_LIBSCF */
+
+ cleanup();
+
+ if (want_stats) {
+ isc_mem_stats(ns_g_mctx, stdout);
+ isc_mutex_stats(stdout);
+ }
+
+ if (ns_g_memstatistics && memstats != NULL) {
+ FILE *fp = NULL;
+ result = isc_stdio_open(memstats, "w", &fp);
+ if (result == ISC_R_SUCCESS) {
+ isc_mem_stats(ns_g_mctx, fp);
+ isc_mutex_stats(fp);
+ isc_stdio_close(fp);
+ }
+ }
+ isc_mem_destroy(&ns_g_mctx);
+ isc_mem_checkdestroyed(stderr);
+
+ ns_main_setmemstats(NULL);
+
+ isc_app_finish();
+
+ ns_os_closedevnull();
+
+ ns_os_shutdown();
+
+ return (0);
+}
diff --git a/bin/named/named.8 b/bin/named/named.8
new file mode 100644
index 0000000..3408403
--- /dev/null
+++ b/bin/named/named.8
@@ -0,0 +1,256 @@
+.\" Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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.8,v 1.38 2008/11/07 01:11:19 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: named
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: June 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "NAMED" "8" "June 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+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]
+.SH "DESCRIPTION"
+.PP
+\fBnamed\fR
+is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC. For more information on the DNS, see RFCs 1033, 1034, and 1035.
+.PP
+When invoked without arguments,
+\fBnamed\fR
+will read the default configuration file
+\fI/etc/named.conf\fR, read any initial data, and listen for queries.
+.SH "OPTIONS"
+.PP
+\-4
+.RS 4
+Use IPv4 only even if the host machine is capable of IPv6.
+\fB\-4\fR
+and
+\fB\-6\fR
+are mutually exclusive.
+.RE
+.PP
+\-6
+.RS 4
+Use IPv6 only even if the host machine is capable of IPv4.
+\fB\-4\fR
+and
+\fB\-6\fR
+are mutually exclusive.
+.RE
+.PP
+\-c \fIconfig\-file\fR
+.RS 4
+Use
+\fIconfig\-file\fR
+as the configuration file instead of the default,
+\fI/etc/named.conf\fR. To ensure that reloading the configuration file continues to work after the server has changed its working directory due to to a possible
+\fBdirectory\fR
+option in the configuration file,
+\fIconfig\-file\fR
+should be an absolute pathname.
+.RE
+.PP
+\-d \fIdebug\-level\fR
+.RS 4
+Set the daemon's debug level to
+\fIdebug\-level\fR. Debugging traces from
+\fBnamed\fR
+become more verbose as the debug level increases.
+.RE
+.PP
+\-f
+.RS 4
+Run the server in the foreground (i.e. do not daemonize).
+.RE
+.PP
+\-g
+.RS 4
+Run the server in the foreground and force all logging to
+\fIstderr\fR.
+.RE
+.PP
+\-m \fIflag\fR
+.RS 4
+Turn on memory usage debugging flags. Possible flags are
+\fIusage\fR,
+\fItrace\fR,
+\fIrecord\fR,
+\fIsize\fR, and
+\fImctx\fR. These correspond to the ISC_MEM_DEBUGXXXX flags described in
+\fI<isc/mem.h>\fR.
+.RE
+.PP
+\-n \fI#cpus\fR
+.RS 4
+Create
+\fI#cpus\fR
+worker threads to take advantage of multiple CPUs. If not specified,
+\fBnamed\fR
+will try to determine the number of CPUs present and create one thread per CPU. If it is unable to determine the number of CPUs, a single worker thread will be created.
+.RE
+.PP
+\-p \fIport\fR
+.RS 4
+Listen for queries on port
+\fIport\fR. If not specified, the default is port 53.
+.RE
+.PP
+\-s
+.RS 4
+Write memory usage statistics to
+\fIstdout\fR
+on exit.
+.RS
+.B "Note:"
+This option is mainly of interest to BIND 9 developers and may be removed or changed in a future release.
+.RE
+.RE
+.PP
+\-S \fI#max\-socks\fR
+.RS 4
+Allow
+\fBnamed\fR
+to use up to
+\fI#max\-socks\fR
+sockets.
+.RS
+.B "Warning:"
+This option should be unnecessary for the vast majority of users. The use of this option could even be harmful because the specified value may exceed the limitation of the underlying system API. It is therefore set only when the default configuration causes exhaustion of file descriptors and the operational environment is known to support the specified number of sockets. Note also that the actual maximum number is normally a little fewer than the specified value because
+\fBnamed\fR
+reserves some file descriptors for its internal use.
+.RE
+.RE
+.PP
+\-t \fIdirectory\fR
+.RS 4
+Chroot to
+\fIdirectory\fR
+after processing the command line arguments, but before reading the configuration file.
+.RS
+.B "Warning:"
+This option should be used in conjunction with the
+\fB\-u\fR
+option, as chrooting a process running as root doesn't enhance security on most systems; the way
+\fBchroot(2)\fR
+is defined allows a process with root privileges to escape a chroot jail.
+.RE
+.RE
+.PP
+\-u \fIuser\fR
+.RS 4
+Setuid to
+\fIuser\fR
+after completing privileged operations, such as creating sockets that listen on privileged ports.
+.RS
+.B "Note:"
+On Linux,
+\fBnamed\fR
+uses the kernel's capability mechanism to drop all root privileges except the ability to
+\fBbind(2)\fR
+to a privileged port and set process resource limits. Unfortunately, this means that the
+\fB\-u\fR
+option only works when
+\fBnamed\fR
+is run on kernel 2.2.18 or later, or kernel 2.3.99\-pre3 or later, since previous kernels did not allow privileges to be retained after
+\fBsetuid(2)\fR.
+.RE
+.RE
+.PP
+\-v
+.RS 4
+Report the version number and exit.
+.RE
+.PP
+\-V
+.RS 4
+Report the version number and build options, and exit.
+.RE
+.PP
+\-x \fIcache\-file\fR
+.RS 4
+Load data from
+\fIcache\-file\fR
+into the cache of the default view.
+.RS
+.B "Warning:"
+This option must not be used. It is only of interest to BIND 9 developers and may be removed or changed in a future release.
+.RE
+.RE
+.SH "SIGNALS"
+.PP
+In routine operation, signals should not be used to control the nameserver;
+\fBrndc\fR
+should be used instead.
+.PP
+SIGHUP
+.RS 4
+Force a reload of the server.
+.RE
+.PP
+SIGINT, SIGTERM
+.RS 4
+Shut down the server.
+.RE
+.PP
+The result of sending any other signals to the server is undefined.
+.SH "CONFIGURATION"
+.PP
+The
+\fBnamed\fR
+configuration file is too complex to describe in detail here. A complete description is provided in the
+BIND 9 Administrator Reference Manual.
+.SH "FILES"
+.PP
+\fI/etc/named.conf\fR
+.RS 4
+The default configuration file.
+.RE
+.PP
+\fI/var/run/named/named.pid\fR
+.RS 4
+The default process\-id file.
+.RE
+.SH "SEE ALSO"
+.PP
+RFC 1033,
+RFC 1034,
+RFC 1035,
+\fBnamed\-checkconf\fR(8),
+\fBnamed\-checkzone\fR(8),
+\fBrndc\fR(8),
+\fBlwresd\fR(8),
+\fBnamed.conf\fR(5),
+BIND 9 Administrator Reference Manual.
+.SH "AUTHOR"
+.PP
+Internet Systems Consortium
+.SH "COPYRIGHT"
+Copyright \(co 2004\-2008 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001, 2003 Internet Software Consortium.
+.br
diff --git a/bin/named/named.conf.5 b/bin/named/named.conf.5
new file mode 100644
index 0000000..039c795
--- /dev/null
+++ b/bin/named/named.conf.5
@@ -0,0 +1,548 @@
+.\" Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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.conf.5,v 1.36 2008/09/25 04:45:04 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: \fInamed.conf\fR
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Aug 13, 2004
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "\fINAMED.CONF\fR" "5" "Aug 13, 2004" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+named.conf \- configuration file for named
+.SH "SYNOPSIS"
+.HP 11
+\fBnamed.conf\fR
+.SH "DESCRIPTION"
+.PP
+\fInamed.conf\fR
+is the configuration file for
+\fBnamed\fR. Statements are enclosed in braces and terminated with a semi\-colon. Clauses in the statements are also semi\-colon terminated. The usual comment styles are supported:
+.PP
+C style: /* */
+.PP
+C++ style: // to end of line
+.PP
+Unix style: # to end of line
+.SH "ACL"
+.sp
+.RS 4
+.nf
+acl \fIstring\fR { \fIaddress_match_element\fR; ... };
+.fi
+.RE
+.SH "KEY"
+.sp
+.RS 4
+.nf
+key \fIdomain_name\fR {
+ algorithm \fIstring\fR;
+ secret \fIstring\fR;
+};
+.fi
+.RE
+.SH "MASTERS"
+.sp
+.RS 4
+.nf
+masters \fIstring\fR [ port \fIinteger\fR ] {
+ ( \fImasters\fR | \fIipv4_address\fR [port \fIinteger\fR] |
+ \fIipv6_address\fR [port \fIinteger\fR] ) [ key \fIstring\fR ]; ...
+};
+.fi
+.RE
+.SH "SERVER"
+.sp
+.RS 4
+.nf
+server ( \fIipv4_address\fR\fI[/prefixlen]\fR | \fIipv6_address\fR\fI[/prefixlen]\fR ) {
+ bogus \fIboolean\fR;
+ edns \fIboolean\fR;
+ edns\-udp\-size \fIinteger\fR;
+ max\-udp\-size \fIinteger\fR;
+ provide\-ixfr \fIboolean\fR;
+ request\-ixfr \fIboolean\fR;
+ keys \fIserver_key\fR;
+ transfers \fIinteger\fR;
+ transfer\-format ( many\-answers | one\-answer );
+ transfer\-source ( \fIipv4_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ transfer\-source\-v6 ( \fIipv6_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ support\-ixfr \fIboolean\fR; // obsolete
+};
+.fi
+.RE
+.SH "TRUSTED\-KEYS"
+.sp
+.RS 4
+.nf
+trusted\-keys {
+ \fIdomain_name\fR \fIflags\fR \fIprotocol\fR \fIalgorithm\fR \fIkey\fR; ...
+};
+.fi
+.RE
+.SH "CONTROLS"
+.sp
+.RS 4
+.nf
+controls {
+ inet ( \fIipv4_address\fR | \fIipv6_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ]
+ allow { \fIaddress_match_element\fR; ... }
+ [ keys { \fIstring\fR; ... } ];
+ unix \fIunsupported\fR; // not implemented
+};
+.fi
+.RE
+.SH "LOGGING"
+.sp
+.RS 4
+.nf
+logging {
+ channel \fIstring\fR {
+ file \fIlog_file\fR;
+ syslog \fIoptional_facility\fR;
+ null;
+ stderr;
+ severity \fIlog_severity\fR;
+ print\-time \fIboolean\fR;
+ print\-severity \fIboolean\fR;
+ print\-category \fIboolean\fR;
+ };
+ category \fIstring\fR { \fIstring\fR; ... };
+};
+.fi
+.RE
+.SH "LWRES"
+.sp
+.RS 4
+.nf
+lwres {
+ listen\-on [ port \fIinteger\fR ] {
+ ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ]; ...
+ };
+ view \fIstring\fR \fIoptional_class\fR;
+ search { \fIstring\fR; ... };
+ ndots \fIinteger\fR;
+};
+.fi
+.RE
+.SH "OPTIONS"
+.sp
+.RS 4
+.nf
+options {
+ avoid\-v4\-udp\-ports { \fIport\fR; ... };
+ avoid\-v6\-udp\-ports { \fIport\fR; ... };
+ blackhole { \fIaddress_match_element\fR; ... };
+ coresize \fIsize\fR;
+ datasize \fIsize\fR;
+ directory \fIquoted_string\fR;
+ dump\-file \fIquoted_string\fR;
+ files \fIsize\fR;
+ heartbeat\-interval \fIinteger\fR;
+ host\-statistics \fIboolean\fR; // not implemented
+ host\-statistics\-max \fInumber\fR; // not implemented
+ hostname ( \fIquoted_string\fR | none );
+ interface\-interval \fIinteger\fR;
+ listen\-on [ port \fIinteger\fR ] { \fIaddress_match_element\fR; ... };
+ listen\-on\-v6 [ port \fIinteger\fR ] { \fIaddress_match_element\fR; ... };
+ match\-mapped\-addresses \fIboolean\fR;
+ memstatistics\-file \fIquoted_string\fR;
+ pid\-file ( \fIquoted_string\fR | none );
+ port \fIinteger\fR;
+ querylog \fIboolean\fR;
+ recursing\-file \fIquoted_string\fR;
+ reserved\-sockets \fIinteger\fR;
+ random\-device \fIquoted_string\fR;
+ recursive\-clients \fIinteger\fR;
+ serial\-query\-rate \fIinteger\fR;
+ server\-id ( \fIquoted_string\fR | none |;
+ stacksize \fIsize\fR;
+ statistics\-file \fIquoted_string\fR;
+ statistics\-interval \fIinteger\fR; // not yet implemented
+ tcp\-clients \fIinteger\fR;
+ tcp\-listen\-queue \fIinteger\fR;
+ tkey\-dhkey \fIquoted_string\fR \fIinteger\fR;
+ tkey\-gssapi\-credential \fIquoted_string\fR;
+ tkey\-domain \fIquoted_string\fR;
+ transfers\-per\-ns \fIinteger\fR;
+ transfers\-in \fIinteger\fR;
+ transfers\-out \fIinteger\fR;
+ use\-ixfr \fIboolean\fR;
+ version ( \fIquoted_string\fR | none );
+ allow\-recursion { \fIaddress_match_element\fR; ... };
+ allow\-recursion\-on { \fIaddress_match_element\fR; ... };
+ sortlist { \fIaddress_match_element\fR; ... };
+ topology { \fIaddress_match_element\fR; ... }; // not implemented
+ auth\-nxdomain \fIboolean\fR; // default changed
+ minimal\-responses \fIboolean\fR;
+ recursion \fIboolean\fR;
+ rrset\-order {
+ [ class \fIstring\fR ] [ type \fIstring\fR ]
+ [ name \fIquoted_string\fR ] \fIstring\fR \fIstring\fR; ...
+ };
+ provide\-ixfr \fIboolean\fR;
+ request\-ixfr \fIboolean\fR;
+ rfc2308\-type1 \fIboolean\fR; // not yet implemented
+ additional\-from\-auth \fIboolean\fR;
+ additional\-from\-cache \fIboolean\fR;
+ query\-source ( ( \fIipv4_address\fR | * ) | [ address ( \fIipv4_address\fR | * ) ] ) [ port ( \fIinteger\fR | * ) ];
+ query\-source\-v6 ( ( \fIipv6_address\fR | * ) | [ address ( \fIipv6_address\fR | * ) ] ) [ port ( \fIinteger\fR | * ) ];
+ use\-queryport\-pool \fIboolean\fR;
+ queryport\-pool\-ports \fIinteger\fR;
+ queryport\-pool\-updateinterval \fIinteger\fR;
+ cleaning\-interval \fIinteger\fR;
+ min\-roots \fIinteger\fR; // not implemented
+ lame\-ttl \fIinteger\fR;
+ max\-ncache\-ttl \fIinteger\fR;
+ max\-cache\-ttl \fIinteger\fR;
+ transfer\-format ( many\-answers | one\-answer );
+ max\-cache\-size \fIsize\fR;
+ max\-acache\-size \fIsize\fR;
+ clients\-per\-query \fInumber\fR;
+ max\-clients\-per\-query \fInumber\fR;
+ check\-names ( master | slave | response )
+ ( fail | warn | ignore );
+ check\-mx ( fail | warn | ignore );
+ check\-integrity \fIboolean\fR;
+ check\-mx\-cname ( fail | warn | ignore );
+ check\-srv\-cname ( fail | warn | ignore );
+ cache\-file \fIquoted_string\fR; // test option
+ suppress\-initial\-notify \fIboolean\fR; // not yet implemented
+ preferred\-glue \fIstring\fR;
+ dual\-stack\-servers [ port \fIinteger\fR ] {
+ ( \fIquoted_string\fR [port \fIinteger\fR] |
+ \fIipv4_address\fR [port \fIinteger\fR] |
+ \fIipv6_address\fR [port \fIinteger\fR] ); ...
+ };
+ edns\-udp\-size \fIinteger\fR;
+ max\-udp\-size \fIinteger\fR;
+ root\-delegation\-only [ exclude { \fIquoted_string\fR; ... } ];
+ disable\-algorithms \fIstring\fR { \fIstring\fR; ... };
+ dnssec\-enable \fIboolean\fR;
+ dnssec\-validation \fIboolean\fR;
+ dnssec\-lookaside \fIstring\fR trust\-anchor \fIstring\fR;
+ dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR;
+ dnssec\-accept\-expired \fIboolean\fR;
+ empty\-server \fIstring\fR;
+ empty\-contact \fIstring\fR;
+ empty\-zones\-enable \fIboolean\fR;
+ disable\-empty\-zone \fIstring\fR;
+ dialup \fIdialuptype\fR;
+ ixfr\-from\-differences \fIixfrdiff\fR;
+ allow\-query { \fIaddress_match_element\fR; ... };
+ allow\-query\-on { \fIaddress_match_element\fR; ... };
+ allow\-query\-cache { \fIaddress_match_element\fR; ... };
+ allow\-query\-cache\-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\-check\-ksk \fIboolean\fR;
+ masterfile\-format ( text | raw );
+ notify \fInotifytype\fR;
+ notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ];
+ notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ];
+ notify\-delay \fIseconds\fR;
+ notify\-to\-soa \fIboolean\fR;
+ also\-notify [ port \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR )
+ [ port \fIinteger\fR ]; ... };
+ allow\-notify { \fIaddress_match_element\fR; ... };
+ forward ( first | only );
+ forwarders [ port \fIinteger\fR ] {
+ ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ]; ...
+ };
+ max\-journal\-size \fIsize_no_default\fR;
+ max\-transfer\-time\-in \fIinteger\fR;
+ max\-transfer\-time\-out \fIinteger\fR;
+ max\-transfer\-idle\-in \fIinteger\fR;
+ max\-transfer\-idle\-out \fIinteger\fR;
+ max\-retry\-time \fIinteger\fR;
+ min\-retry\-time \fIinteger\fR;
+ max\-refresh\-time \fIinteger\fR;
+ min\-refresh\-time \fIinteger\fR;
+ multi\-master \fIboolean\fR;
+ sig\-validity\-interval \fIinteger\fR;
+ sig\-re\-signing\-interval \fIinteger\fR;
+ sig\-signing\-nodes \fIinteger\fR;
+ sig\-signing\-signatures \fIinteger\fR;
+ sig\-signing\-type \fIinteger\fR;
+ transfer\-source ( \fIipv4_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ transfer\-source\-v6 ( \fIipv6_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ alt\-transfer\-source ( \fIipv4_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ use\-alt\-transfer\-source \fIboolean\fR;
+ zone\-statistics \fIboolean\fR;
+ key\-directory \fIquoted_string\fR;
+ try\-tcp\-refresh \fIboolean\fR;
+ zero\-no\-soa\-ttl \fIboolean\fR;
+ zero\-no\-soa\-ttl\-cache \fIboolean\fR;
+ nsec3\-test\-zone \fIboolean\fR; // testing only
+ allow\-v6\-synthesis { \fIaddress_match_element\fR; ... }; // obsolete
+ deallocate\-on\-exit \fIboolean\fR; // obsolete
+ fake\-iquery \fIboolean\fR; // obsolete
+ fetch\-glue \fIboolean\fR; // obsolete
+ has\-old\-clients \fIboolean\fR; // obsolete
+ maintain\-ixfr\-base \fIboolean\fR; // obsolete
+ max\-ixfr\-log\-size \fIsize\fR; // obsolete
+ multiple\-cnames \fIboolean\fR; // obsolete
+ named\-xfer \fIquoted_string\fR; // obsolete
+ serial\-queries \fIinteger\fR; // obsolete
+ treat\-cr\-as\-space \fIboolean\fR; // obsolete
+ use\-id\-pool \fIboolean\fR; // obsolete
+};
+.fi
+.RE
+.SH "VIEW"
+.sp
+.RS 4
+.nf
+view \fIstring\fR \fIoptional_class\fR {
+ match\-clients { \fIaddress_match_element\fR; ... };
+ match\-destinations { \fIaddress_match_element\fR; ... };
+ match\-recursive\-only \fIboolean\fR;
+ key \fIstring\fR {
+ algorithm \fIstring\fR;
+ secret \fIstring\fR;
+ };
+ zone \fIstring\fR \fIoptional_class\fR {
+ ...
+ };
+ server ( \fIipv4_address\fR\fI[/prefixlen]\fR | \fIipv6_address\fR\fI[/prefixlen]\fR ) {
+ ...
+ };
+ trusted\-keys {
+ \fIstring\fR \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; ...
+ };
+ allow\-recursion { \fIaddress_match_element\fR; ... };
+ allow\-recursion\-on { \fIaddress_match_element\fR; ... };
+ sortlist { \fIaddress_match_element\fR; ... };
+ topology { \fIaddress_match_element\fR; ... }; // not implemented
+ auth\-nxdomain \fIboolean\fR; // default changed
+ minimal\-responses \fIboolean\fR;
+ recursion \fIboolean\fR;
+ rrset\-order {
+ [ class \fIstring\fR ] [ type \fIstring\fR ]
+ [ name \fIquoted_string\fR ] \fIstring\fR \fIstring\fR; ...
+ };
+ provide\-ixfr \fIboolean\fR;
+ request\-ixfr \fIboolean\fR;
+ rfc2308\-type1 \fIboolean\fR; // not yet implemented
+ additional\-from\-auth \fIboolean\fR;
+ additional\-from\-cache \fIboolean\fR;
+ query\-source ( ( \fIipv4_address\fR | * ) | [ address ( \fIipv4_address\fR | * ) ] ) [ port ( \fIinteger\fR | * ) ];
+ query\-source\-v6 ( ( \fIipv6_address\fR | * ) | [ address ( \fIipv6_address\fR | * ) ] ) [ port ( \fIinteger\fR | * ) ];
+ use\-queryport\-pool \fIboolean\fR;
+ queryport\-pool\-ports \fIinteger\fR;
+ queryport\-pool\-updateinterval \fIinteger\fR;
+ cleaning\-interval \fIinteger\fR;
+ min\-roots \fIinteger\fR; // not implemented
+ lame\-ttl \fIinteger\fR;
+ max\-ncache\-ttl \fIinteger\fR;
+ max\-cache\-ttl \fIinteger\fR;
+ transfer\-format ( many\-answers | one\-answer );
+ max\-cache\-size \fIsize\fR;
+ max\-acache\-size \fIsize\fR;
+ clients\-per\-query \fInumber\fR;
+ max\-clients\-per\-query \fInumber\fR;
+ check\-names ( master | slave | response )
+ ( fail | warn | ignore );
+ check\-mx ( fail | warn | ignore );
+ check\-integrity \fIboolean\fR;
+ check\-mx\-cname ( fail | warn | ignore );
+ check\-srv\-cname ( fail | warn | ignore );
+ cache\-file \fIquoted_string\fR; // test option
+ suppress\-initial\-notify \fIboolean\fR; // not yet implemented
+ preferred\-glue \fIstring\fR;
+ dual\-stack\-servers [ port \fIinteger\fR ] {
+ ( \fIquoted_string\fR [port \fIinteger\fR] |
+ \fIipv4_address\fR [port \fIinteger\fR] |
+ \fIipv6_address\fR [port \fIinteger\fR] ); ...
+ };
+ edns\-udp\-size \fIinteger\fR;
+ max\-udp\-size \fIinteger\fR;
+ root\-delegation\-only [ exclude { \fIquoted_string\fR; ... } ];
+ disable\-algorithms \fIstring\fR { \fIstring\fR; ... };
+ dnssec\-enable \fIboolean\fR;
+ dnssec\-validation \fIboolean\fR;
+ dnssec\-lookaside \fIstring\fR trust\-anchor \fIstring\fR;
+ dnssec\-must\-be\-secure \fIstring\fR \fIboolean\fR;
+ dnssec\-accept\-expired \fIboolean\fR;
+ empty\-server \fIstring\fR;
+ empty\-contact \fIstring\fR;
+ empty\-zones\-enable \fIboolean\fR;
+ disable\-empty\-zone \fIstring\fR;
+ dialup \fIdialuptype\fR;
+ ixfr\-from\-differences \fIixfrdiff\fR;
+ allow\-query { \fIaddress_match_element\fR; ... };
+ allow\-query\-on { \fIaddress_match_element\fR; ... };
+ allow\-query\-cache { \fIaddress_match_element\fR; ... };
+ allow\-query\-cache\-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\-check\-ksk \fIboolean\fR;
+ masterfile\-format ( text | raw );
+ notify \fInotifytype\fR;
+ notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ];
+ notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ];
+ notify\-delay \fIseconds\fR;
+ notify\-to\-soa \fIboolean\fR;
+ also\-notify [ port \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR )
+ [ port \fIinteger\fR ]; ... };
+ allow\-notify { \fIaddress_match_element\fR; ... };
+ forward ( first | only );
+ forwarders [ port \fIinteger\fR ] {
+ ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ]; ...
+ };
+ max\-journal\-size \fIsize_no_default\fR;
+ max\-transfer\-time\-in \fIinteger\fR;
+ max\-transfer\-time\-out \fIinteger\fR;
+ max\-transfer\-idle\-in \fIinteger\fR;
+ max\-transfer\-idle\-out \fIinteger\fR;
+ max\-retry\-time \fIinteger\fR;
+ min\-retry\-time \fIinteger\fR;
+ max\-refresh\-time \fIinteger\fR;
+ min\-refresh\-time \fIinteger\fR;
+ multi\-master \fIboolean\fR;
+ sig\-validity\-interval \fIinteger\fR;
+ transfer\-source ( \fIipv4_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ transfer\-source\-v6 ( \fIipv6_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ alt\-transfer\-source ( \fIipv4_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ use\-alt\-transfer\-source \fIboolean\fR;
+ zone\-statistics \fIboolean\fR;
+ try\-tcp\-refresh \fIboolean\fR;
+ key\-directory \fIquoted_string\fR;
+ zero\-no\-soa\-ttl \fIboolean\fR;
+ zero\-no\-soa\-ttl\-cache \fIboolean\fR;
+ allow\-v6\-synthesis { \fIaddress_match_element\fR; ... }; // obsolete
+ fetch\-glue \fIboolean\fR; // obsolete
+ maintain\-ixfr\-base \fIboolean\fR; // obsolete
+ max\-ixfr\-log\-size \fIsize\fR; // obsolete
+};
+.fi
+.RE
+.SH "ZONE"
+.sp
+.RS 4
+.nf
+zone \fIstring\fR \fIoptional_class\fR {
+ type ( master | slave | stub | hint |
+ forward | delegation\-only );
+ file \fIquoted_string\fR;
+ masters [ port \fIinteger\fR ] {
+ ( \fImasters\fR |
+ \fIipv4_address\fR [port \fIinteger\fR] |
+ \fIipv6_address\fR [ port \fIinteger\fR ] ) [ key \fIstring\fR ]; ...
+ };
+ database \fIstring\fR;
+ delegation\-only \fIboolean\fR;
+ check\-names ( fail | warn | ignore );
+ check\-mx ( fail | warn | ignore );
+ check\-integrity \fIboolean\fR;
+ check\-mx\-cname ( fail | warn | ignore );
+ check\-srv\-cname ( fail | warn | ignore );
+ dialup \fIdialuptype\fR;
+ ixfr\-from\-differences \fIboolean\fR;
+ journal \fIquoted_string\fR;
+ zero\-no\-soa\-ttl \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
+ ( name | subdomain | wildcard | self | selfsub | selfwild |
+ krb5\-self | ms\-self | krb5\-subdomain | ms\-subdomain |
+ tcp\-self | 6to4\-self ) \fIstring\fR
+ \fIrrtypelist\fR; ...
+ };
+ update\-check\-ksk \fIboolean\fR;
+ masterfile\-format ( text | raw );
+ notify \fInotifytype\fR;
+ notify\-source ( \fIipv4_address\fR | * ) [ port ( \fIinteger\fR | * ) ];
+ notify\-source\-v6 ( \fIipv6_address\fR | * ) [ port ( \fIinteger\fR | * ) ];
+ notify\-delay \fIseconds\fR;
+ notify\-to\-soa \fIboolean\fR;
+ also\-notify [ port \fIinteger\fR ] { ( \fIipv4_address\fR | \fIipv6_address\fR )
+ [ port \fIinteger\fR ]; ... };
+ allow\-notify { \fIaddress_match_element\fR; ... };
+ forward ( first | only );
+ forwarders [ port \fIinteger\fR ] {
+ ( \fIipv4_address\fR | \fIipv6_address\fR ) [ port \fIinteger\fR ]; ...
+ };
+ max\-journal\-size \fIsize_no_default\fR;
+ max\-transfer\-time\-in \fIinteger\fR;
+ max\-transfer\-time\-out \fIinteger\fR;
+ max\-transfer\-idle\-in \fIinteger\fR;
+ max\-transfer\-idle\-out \fIinteger\fR;
+ max\-retry\-time \fIinteger\fR;
+ min\-retry\-time \fIinteger\fR;
+ max\-refresh\-time \fIinteger\fR;
+ min\-refresh\-time \fIinteger\fR;
+ multi\-master \fIboolean\fR;
+ sig\-validity\-interval \fIinteger\fR;
+ transfer\-source ( \fIipv4_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ transfer\-source\-v6 ( \fIipv6_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ alt\-transfer\-source ( \fIipv4_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ alt\-transfer\-source\-v6 ( \fIipv6_address\fR | * )
+ [ port ( \fIinteger\fR | * ) ];
+ use\-alt\-transfer\-source \fIboolean\fR;
+ zone\-statistics \fIboolean\fR;
+ try\-tcp\-refresh \fIboolean\fR;
+ key\-directory \fIquoted_string\fR;
+ nsec3\-test\-zone \fIboolean\fR; // testing only
+ ixfr\-base \fIquoted_string\fR; // obsolete
+ ixfr\-tmp\-file \fIquoted_string\fR; // obsolete
+ maintain\-ixfr\-base \fIboolean\fR; // obsolete
+ max\-ixfr\-log\-size \fIsize\fR; // obsolete
+ pubkey \fIinteger\fR \fIinteger\fR \fIinteger\fR \fIquoted_string\fR; // obsolete
+};
+.fi
+.RE
+.SH "FILES"
+.PP
+\fI/etc/named.conf\fR
+.SH "SEE ALSO"
+.PP
+\fBnamed\fR(8),
+\fBnamed\-checkconf\fR(8),
+\fBrndc\fR(8),
+BIND 9 Administrator Reference Manual.
+.SH "COPYRIGHT"
+Copyright \(co 2004\-2008 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook
new file mode 100644
index 0000000..a4a8044
--- /dev/null
+++ b/bin/named/named.conf.docbook
@@ -0,0 +1,629 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004-2008 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.conf.docbook,v 1.39 2008/09/24 02:46:21 marka Exp $ -->
+<refentry>
+ <refentryinfo>
+ <date>Aug 13, 2004</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><filename>named.conf</filename></refentrytitle>
+ <manvolnum>5</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><filename>named.conf</filename></refname>
+ <refpurpose>configuration file for named</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>named.conf</command>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><filename>named.conf</filename> is the configuration file
+ for
+ <command>named</command>. Statements are enclosed
+ in braces and terminated with a semi-colon. Clauses in
+ the statements are also semi-colon terminated. The usual
+ comment styles are supported:
+ </para>
+ <para>
+ C style: /* */
+ </para>
+ <para>
+ C++ style: // to end of line
+ </para>
+ <para>
+ Unix style: # to end of line
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>ACL</title>
+ <literallayout>
+acl <replaceable>string</replaceable> { <replaceable>address_match_element</replaceable>; ... };
+
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>KEY</title>
+ <literallayout>
+key <replaceable>domain_name</replaceable> {
+ algorithm <replaceable>string</replaceable>;
+ secret <replaceable>string</replaceable>;
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>MASTERS</title>
+ <literallayout>
+masters <replaceable>string</replaceable> <optional> port <replaceable>integer</replaceable> </optional> {
+ ( <replaceable>masters</replaceable> | <replaceable>ipv4_address</replaceable> <optional>port <replaceable>integer</replaceable></optional> |
+ <replaceable>ipv6_address</replaceable> <optional>port <replaceable>integer</replaceable></optional> ) <optional> key <replaceable>string</replaceable> </optional>; ...
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>SERVER</title>
+ <literallayout>
+server ( <replaceable>ipv4_address<optional>/prefixlen</optional></replaceable> | <replaceable>ipv6_address<optional>/prefixlen</optional></replaceable> ) {
+ bogus <replaceable>boolean</replaceable>;
+ edns <replaceable>boolean</replaceable>;
+ edns-udp-size <replaceable>integer</replaceable>;
+ max-udp-size <replaceable>integer</replaceable>;
+ provide-ixfr <replaceable>boolean</replaceable>;
+ request-ixfr <replaceable>boolean</replaceable>;
+ keys <replaceable>server_key</replaceable>;
+ transfers <replaceable>integer</replaceable>;
+ transfer-format ( many-answers | one-answer );
+ transfer-source ( <replaceable>ipv4_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+
+ support-ixfr <replaceable>boolean</replaceable>; // obsolete
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>TRUSTED-KEYS</title>
+ <literallayout>
+trusted-keys {
+ <replaceable>domain_name</replaceable> <replaceable>flags</replaceable> <replaceable>protocol</replaceable> <replaceable>algorithm</replaceable> <replaceable>key</replaceable>; ...
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>CONTROLS</title>
+ <literallayout>
+controls {
+ inet ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>
+ allow { <replaceable>address_match_element</replaceable>; ... }
+ <optional> keys { <replaceable>string</replaceable>; ... } </optional>;
+ unix <replaceable>unsupported</replaceable>; // not implemented
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>LOGGING</title>
+ <literallayout>
+logging {
+ channel <replaceable>string</replaceable> {
+ file <replaceable>log_file</replaceable>;
+ syslog <replaceable>optional_facility</replaceable>;
+ null;
+ stderr;
+ severity <replaceable>log_severity</replaceable>;
+ print-time <replaceable>boolean</replaceable>;
+ print-severity <replaceable>boolean</replaceable>;
+ print-category <replaceable>boolean</replaceable>;
+ };
+ category <replaceable>string</replaceable> { <replaceable>string</replaceable>; ... };
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>LWRES</title>
+ <literallayout>
+lwres {
+ listen-on <optional> port <replaceable>integer</replaceable> </optional> {
+ ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> ) <optional> port <replaceable>integer</replaceable> </optional>; ...
+ };
+ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>;
+ search { <replaceable>string</replaceable>; ... };
+ ndots <replaceable>integer</replaceable>;
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+ <literallayout>
+options {
+ avoid-v4-udp-ports { <replaceable>port</replaceable>; ... };
+ avoid-v6-udp-ports { <replaceable>port</replaceable>; ... };
+ blackhole { <replaceable>address_match_element</replaceable>; ... };
+ coresize <replaceable>size</replaceable>;
+ datasize <replaceable>size</replaceable>;
+ directory <replaceable>quoted_string</replaceable>;
+ dump-file <replaceable>quoted_string</replaceable>;
+ files <replaceable>size</replaceable>;
+ heartbeat-interval <replaceable>integer</replaceable>;
+ host-statistics <replaceable>boolean</replaceable>; // not implemented
+ host-statistics-max <replaceable>number</replaceable>; // not implemented
+ hostname ( <replaceable>quoted_string</replaceable> | none );
+ interface-interval <replaceable>integer</replaceable>;
+ listen-on <optional> port <replaceable>integer</replaceable> </optional> { <replaceable>address_match_element</replaceable>; ... };
+ listen-on-v6 <optional> port <replaceable>integer</replaceable> </optional> { <replaceable>address_match_element</replaceable>; ... };
+ match-mapped-addresses <replaceable>boolean</replaceable>;
+ memstatistics-file <replaceable>quoted_string</replaceable>;
+ pid-file ( <replaceable>quoted_string</replaceable> | none );
+ port <replaceable>integer</replaceable>;
+ querylog <replaceable>boolean</replaceable>;
+ recursing-file <replaceable>quoted_string</replaceable>;
+ reserved-sockets <replaceable>integer</replaceable>;
+ random-device <replaceable>quoted_string</replaceable>;
+ recursive-clients <replaceable>integer</replaceable>;
+ serial-query-rate <replaceable>integer</replaceable>;
+ server-id ( <replaceable>quoted_string</replaceable> | none |;
+ stacksize <replaceable>size</replaceable>;
+ statistics-file <replaceable>quoted_string</replaceable>;
+ statistics-interval <replaceable>integer</replaceable>; // not yet implemented
+ tcp-clients <replaceable>integer</replaceable>;
+ tcp-listen-queue <replaceable>integer</replaceable>;
+ tkey-dhkey <replaceable>quoted_string</replaceable> <replaceable>integer</replaceable>;
+ tkey-gssapi-credential <replaceable>quoted_string</replaceable>;
+ tkey-domain <replaceable>quoted_string</replaceable>;
+ transfers-per-ns <replaceable>integer</replaceable>;
+ transfers-in <replaceable>integer</replaceable>;
+ transfers-out <replaceable>integer</replaceable>;
+ use-ixfr <replaceable>boolean</replaceable>;
+ version ( <replaceable>quoted_string</replaceable> | none );
+ allow-recursion { <replaceable>address_match_element</replaceable>; ... };
+ allow-recursion-on { <replaceable>address_match_element</replaceable>; ... };
+ sortlist { <replaceable>address_match_element</replaceable>; ... };
+ topology { <replaceable>address_match_element</replaceable>; ... }; // not implemented
+ auth-nxdomain <replaceable>boolean</replaceable>; // default changed
+ minimal-responses <replaceable>boolean</replaceable>;
+ recursion <replaceable>boolean</replaceable>;
+ rrset-order {
+ <optional> class <replaceable>string</replaceable> </optional> <optional> type <replaceable>string</replaceable> </optional>
+ <optional> name <replaceable>quoted_string</replaceable> </optional> <replaceable>string</replaceable> <replaceable>string</replaceable>; ...
+ };
+ provide-ixfr <replaceable>boolean</replaceable>;
+ request-ixfr <replaceable>boolean</replaceable>;
+ rfc2308-type1 <replaceable>boolean</replaceable>; // not yet implemented
+ additional-from-auth <replaceable>boolean</replaceable>;
+ additional-from-cache <replaceable>boolean</replaceable>;
+ query-source ( ( <replaceable>ipv4_address</replaceable> | * ) | <optional> address ( <replaceable>ipv4_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ query-source-v6 ( ( <replaceable>ipv6_address</replaceable> | * ) | <optional> address ( <replaceable>ipv6_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ use-queryport-pool <replaceable>boolean</replaceable>;
+ queryport-pool-ports <replaceable>integer</replaceable>;
+ queryport-pool-updateinterval <replaceable>integer</replaceable>;
+ cleaning-interval <replaceable>integer</replaceable>;
+ min-roots <replaceable>integer</replaceable>; // not implemented
+ lame-ttl <replaceable>integer</replaceable>;
+ max-ncache-ttl <replaceable>integer</replaceable>;
+ max-cache-ttl <replaceable>integer</replaceable>;
+ transfer-format ( many-answers | one-answer );
+ max-cache-size <replaceable>size</replaceable>;
+ max-acache-size <replaceable>size</replaceable>;
+ clients-per-query <replaceable>number</replaceable>;
+ max-clients-per-query <replaceable>number</replaceable>;
+ check-names ( master | slave | response )
+ ( fail | warn | ignore );
+ check-mx ( fail | warn | ignore );
+ check-integrity <replaceable>boolean</replaceable>;
+ check-mx-cname ( fail | warn | ignore );
+ check-srv-cname ( fail | warn | ignore );
+ cache-file <replaceable>quoted_string</replaceable>; // test option
+ suppress-initial-notify <replaceable>boolean</replaceable>; // not yet implemented
+ preferred-glue <replaceable>string</replaceable>;
+ dual-stack-servers <optional> port <replaceable>integer</replaceable> </optional> {
+ ( <replaceable>quoted_string</replaceable> <optional>port <replaceable>integer</replaceable></optional> |
+ <replaceable>ipv4_address</replaceable> <optional>port <replaceable>integer</replaceable></optional> |
+ <replaceable>ipv6_address</replaceable> <optional>port <replaceable>integer</replaceable></optional> ); ...
+ };
+ edns-udp-size <replaceable>integer</replaceable>;
+ max-udp-size <replaceable>integer</replaceable>;
+ root-delegation-only <optional> exclude { <replaceable>quoted_string</replaceable>; ... } </optional>;
+ disable-algorithms <replaceable>string</replaceable> { <replaceable>string</replaceable>; ... };
+ dnssec-enable <replaceable>boolean</replaceable>;
+ dnssec-validation <replaceable>boolean</replaceable>;
+ dnssec-lookaside <replaceable>string</replaceable> trust-anchor <replaceable>string</replaceable>;
+ dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>;
+ dnssec-accept-expired <replaceable>boolean</replaceable>;
+
+ empty-server <replaceable>string</replaceable>;
+ empty-contact <replaceable>string</replaceable>;
+ empty-zones-enable <replaceable>boolean</replaceable>;
+ disable-empty-zone <replaceable>string</replaceable>;
+
+ dialup <replaceable>dialuptype</replaceable>;
+ ixfr-from-differences <replaceable>ixfrdiff</replaceable>;
+
+ allow-query { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-cache { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-cache-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-transfer { <replaceable>address_match_element</replaceable>; ... };
+ allow-update { <replaceable>address_match_element</replaceable>; ... };
+ allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
+ update-check-ksk <replaceable>boolean</replaceable>;
+
+ masterfile-format ( text | raw );
+ notify <replaceable>notifytype</replaceable>;
+ notify-source ( <replaceable>ipv4_address</replaceable> | * ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ notify-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ notify-delay <replaceable>seconds</replaceable>;
+ notify-to-soa <replaceable>boolean</replaceable>;
+ also-notify <optional> port <replaceable>integer</replaceable> </optional> { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> )
+ <optional> port <replaceable>integer</replaceable> </optional>; ... };
+ allow-notify { <replaceable>address_match_element</replaceable>; ... };
+
+ forward ( first | only );
+ forwarders <optional> port <replaceable>integer</replaceable> </optional> {
+ ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> ) <optional> port <replaceable>integer</replaceable> </optional>; ...
+ };
+
+ max-journal-size <replaceable>size_no_default</replaceable>;
+ max-transfer-time-in <replaceable>integer</replaceable>;
+ max-transfer-time-out <replaceable>integer</replaceable>;
+ max-transfer-idle-in <replaceable>integer</replaceable>;
+ max-transfer-idle-out <replaceable>integer</replaceable>;
+ max-retry-time <replaceable>integer</replaceable>;
+ min-retry-time <replaceable>integer</replaceable>;
+ max-refresh-time <replaceable>integer</replaceable>;
+ min-refresh-time <replaceable>integer</replaceable>;
+ multi-master <replaceable>boolean</replaceable>;
+
+ sig-validity-interval <replaceable>integer</replaceable>;
+ sig-re-signing-interval <replaceable>integer</replaceable>;
+ sig-signing-nodes <replaceable>integer</replaceable>;
+ sig-signing-signatures <replaceable>integer</replaceable>;
+ sig-signing-type <replaceable>integer</replaceable>;
+
+ transfer-source ( <replaceable>ipv4_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+
+ alt-transfer-source ( <replaceable>ipv4_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ alt-transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ use-alt-transfer-source <replaceable>boolean</replaceable>;
+
+ zone-statistics <replaceable>boolean</replaceable>;
+ key-directory <replaceable>quoted_string</replaceable>;
+ try-tcp-refresh <replaceable>boolean</replaceable>;
+ zero-no-soa-ttl <replaceable>boolean</replaceable>;
+ zero-no-soa-ttl-cache <replaceable>boolean</replaceable>;
+
+ nsec3-test-zone <replaceable>boolean</replaceable>; // testing only
+
+ allow-v6-synthesis { <replaceable>address_match_element</replaceable>; ... }; // obsolete
+ deallocate-on-exit <replaceable>boolean</replaceable>; // obsolete
+ fake-iquery <replaceable>boolean</replaceable>; // obsolete
+ fetch-glue <replaceable>boolean</replaceable>; // obsolete
+ has-old-clients <replaceable>boolean</replaceable>; // obsolete
+ maintain-ixfr-base <replaceable>boolean</replaceable>; // obsolete
+ max-ixfr-log-size <replaceable>size</replaceable>; // obsolete
+ multiple-cnames <replaceable>boolean</replaceable>; // obsolete
+ named-xfer <replaceable>quoted_string</replaceable>; // obsolete
+ serial-queries <replaceable>integer</replaceable>; // obsolete
+ treat-cr-as-space <replaceable>boolean</replaceable>; // obsolete
+ use-id-pool <replaceable>boolean</replaceable>; // obsolete
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>VIEW</title>
+ <literallayout>
+view <replaceable>string</replaceable> <replaceable>optional_class</replaceable> {
+ match-clients { <replaceable>address_match_element</replaceable>; ... };
+ match-destinations { <replaceable>address_match_element</replaceable>; ... };
+ match-recursive-only <replaceable>boolean</replaceable>;
+
+ key <replaceable>string</replaceable> {
+ algorithm <replaceable>string</replaceable>;
+ secret <replaceable>string</replaceable>;
+ };
+
+ zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable> {
+ ...
+ };
+
+ server ( <replaceable>ipv4_address<optional>/prefixlen</optional></replaceable> | <replaceable>ipv6_address<optional>/prefixlen</optional></replaceable> ) {
+ ...
+ };
+
+ trusted-keys {
+ <replaceable>string</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>; ...
+ };
+
+ allow-recursion { <replaceable>address_match_element</replaceable>; ... };
+ allow-recursion-on { <replaceable>address_match_element</replaceable>; ... };
+ sortlist { <replaceable>address_match_element</replaceable>; ... };
+ topology { <replaceable>address_match_element</replaceable>; ... }; // not implemented
+ auth-nxdomain <replaceable>boolean</replaceable>; // default changed
+ minimal-responses <replaceable>boolean</replaceable>;
+ recursion <replaceable>boolean</replaceable>;
+ rrset-order {
+ <optional> class <replaceable>string</replaceable> </optional> <optional> type <replaceable>string</replaceable> </optional>
+ <optional> name <replaceable>quoted_string</replaceable> </optional> <replaceable>string</replaceable> <replaceable>string</replaceable>; ...
+ };
+ provide-ixfr <replaceable>boolean</replaceable>;
+ request-ixfr <replaceable>boolean</replaceable>;
+ rfc2308-type1 <replaceable>boolean</replaceable>; // not yet implemented
+ additional-from-auth <replaceable>boolean</replaceable>;
+ additional-from-cache <replaceable>boolean</replaceable>;
+ query-source ( ( <replaceable>ipv4_address</replaceable> | * ) | <optional> address ( <replaceable>ipv4_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ query-source-v6 ( ( <replaceable>ipv6_address</replaceable> | * ) | <optional> address ( <replaceable>ipv6_address</replaceable> | * ) </optional> ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ use-queryport-pool <replaceable>boolean</replaceable>;
+ queryport-pool-ports <replaceable>integer</replaceable>;
+ queryport-pool-updateinterval <replaceable>integer</replaceable>;
+ cleaning-interval <replaceable>integer</replaceable>;
+ min-roots <replaceable>integer</replaceable>; // not implemented
+ lame-ttl <replaceable>integer</replaceable>;
+ max-ncache-ttl <replaceable>integer</replaceable>;
+ max-cache-ttl <replaceable>integer</replaceable>;
+ transfer-format ( many-answers | one-answer );
+ max-cache-size <replaceable>size</replaceable>;
+ max-acache-size <replaceable>size</replaceable>;
+ clients-per-query <replaceable>number</replaceable>;
+ max-clients-per-query <replaceable>number</replaceable>;
+ check-names ( master | slave | response )
+ ( fail | warn | ignore );
+ check-mx ( fail | warn | ignore );
+ check-integrity <replaceable>boolean</replaceable>;
+ check-mx-cname ( fail | warn | ignore );
+ check-srv-cname ( fail | warn | ignore );
+ cache-file <replaceable>quoted_string</replaceable>; // test option
+ suppress-initial-notify <replaceable>boolean</replaceable>; // not yet implemented
+ preferred-glue <replaceable>string</replaceable>;
+ dual-stack-servers <optional> port <replaceable>integer</replaceable> </optional> {
+ ( <replaceable>quoted_string</replaceable> <optional>port <replaceable>integer</replaceable></optional> |
+ <replaceable>ipv4_address</replaceable> <optional>port <replaceable>integer</replaceable></optional> |
+ <replaceable>ipv6_address</replaceable> <optional>port <replaceable>integer</replaceable></optional> ); ...
+ };
+ edns-udp-size <replaceable>integer</replaceable>;
+ max-udp-size <replaceable>integer</replaceable>;
+ root-delegation-only <optional> exclude { <replaceable>quoted_string</replaceable>; ... } </optional>;
+ disable-algorithms <replaceable>string</replaceable> { <replaceable>string</replaceable>; ... };
+ dnssec-enable <replaceable>boolean</replaceable>;
+ dnssec-validation <replaceable>boolean</replaceable>;
+ dnssec-lookaside <replaceable>string</replaceable> trust-anchor <replaceable>string</replaceable>;
+ dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>;
+ dnssec-accept-expired <replaceable>boolean</replaceable>;
+
+ empty-server <replaceable>string</replaceable>;
+ empty-contact <replaceable>string</replaceable>;
+ empty-zones-enable <replaceable>boolean</replaceable>;
+ disable-empty-zone <replaceable>string</replaceable>;
+
+ dialup <replaceable>dialuptype</replaceable>;
+ ixfr-from-differences <replaceable>ixfrdiff</replaceable>;
+
+ allow-query { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-cache { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-cache-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-transfer { <replaceable>address_match_element</replaceable>; ... };
+ allow-update { <replaceable>address_match_element</replaceable>; ... };
+ allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
+ update-check-ksk <replaceable>boolean</replaceable>;
+
+ masterfile-format ( text | raw );
+ notify <replaceable>notifytype</replaceable>;
+ notify-source ( <replaceable>ipv4_address</replaceable> | * ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ notify-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ notify-delay <replaceable>seconds</replaceable>;
+ notify-to-soa <replaceable>boolean</replaceable>;
+ also-notify <optional> port <replaceable>integer</replaceable> </optional> { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> )
+ <optional> port <replaceable>integer</replaceable> </optional>; ... };
+ allow-notify { <replaceable>address_match_element</replaceable>; ... };
+
+ forward ( first | only );
+ forwarders <optional> port <replaceable>integer</replaceable> </optional> {
+ ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> ) <optional> port <replaceable>integer</replaceable> </optional>; ...
+ };
+
+ max-journal-size <replaceable>size_no_default</replaceable>;
+ max-transfer-time-in <replaceable>integer</replaceable>;
+ max-transfer-time-out <replaceable>integer</replaceable>;
+ max-transfer-idle-in <replaceable>integer</replaceable>;
+ max-transfer-idle-out <replaceable>integer</replaceable>;
+ max-retry-time <replaceable>integer</replaceable>;
+ min-retry-time <replaceable>integer</replaceable>;
+ max-refresh-time <replaceable>integer</replaceable>;
+ min-refresh-time <replaceable>integer</replaceable>;
+ multi-master <replaceable>boolean</replaceable>;
+ sig-validity-interval <replaceable>integer</replaceable>;
+
+ transfer-source ( <replaceable>ipv4_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+
+ alt-transfer-source ( <replaceable>ipv4_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ alt-transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ use-alt-transfer-source <replaceable>boolean</replaceable>;
+
+ zone-statistics <replaceable>boolean</replaceable>;
+ try-tcp-refresh <replaceable>boolean</replaceable>;
+ key-directory <replaceable>quoted_string</replaceable>;
+ zero-no-soa-ttl <replaceable>boolean</replaceable>;
+ zero-no-soa-ttl-cache <replaceable>boolean</replaceable>;
+
+ allow-v6-synthesis { <replaceable>address_match_element</replaceable>; ... }; // obsolete
+ fetch-glue <replaceable>boolean</replaceable>; // obsolete
+ maintain-ixfr-base <replaceable>boolean</replaceable>; // obsolete
+ max-ixfr-log-size <replaceable>size</replaceable>; // obsolete
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>ZONE</title>
+ <literallayout>
+zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable> {
+ type ( master | slave | stub | hint |
+ forward | delegation-only );
+ file <replaceable>quoted_string</replaceable>;
+
+ masters <optional> port <replaceable>integer</replaceable> </optional> {
+ ( <replaceable>masters</replaceable> |
+ <replaceable>ipv4_address</replaceable> <optional>port <replaceable>integer</replaceable></optional> |
+ <replaceable>ipv6_address</replaceable> <optional> port <replaceable>integer</replaceable> </optional> ) <optional> key <replaceable>string</replaceable> </optional>; ...
+ };
+
+ database <replaceable>string</replaceable>;
+ delegation-only <replaceable>boolean</replaceable>;
+ check-names ( fail | warn | ignore );
+ check-mx ( fail | warn | ignore );
+ check-integrity <replaceable>boolean</replaceable>;
+ check-mx-cname ( fail | warn | ignore );
+ check-srv-cname ( fail | warn | ignore );
+ dialup <replaceable>dialuptype</replaceable>;
+ ixfr-from-differences <replaceable>boolean</replaceable>;
+ journal <replaceable>quoted_string</replaceable>;
+ zero-no-soa-ttl <replaceable>boolean</replaceable>;
+
+ allow-query { <replaceable>address_match_element</replaceable>; ... };
+ allow-query-on { <replaceable>address_match_element</replaceable>; ... };
+ allow-transfer { <replaceable>address_match_element</replaceable>; ... };
+ allow-update { <replaceable>address_match_element</replaceable>; ... };
+ allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
+ update-policy {
+ ( grant | deny ) <replaceable>string</replaceable>
+ ( name | subdomain | wildcard | self | selfsub | selfwild |
+ krb5-self | ms-self | krb5-subdomain | ms-subdomain |
+ tcp-self | 6to4-self ) <replaceable>string</replaceable>
+ <replaceable>rrtypelist</replaceable>; ...
+ };
+ update-check-ksk <replaceable>boolean</replaceable>;
+
+ masterfile-format ( text | raw );
+ notify <replaceable>notifytype</replaceable>;
+ notify-source ( <replaceable>ipv4_address</replaceable> | * ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ notify-source-v6 ( <replaceable>ipv6_address</replaceable> | * ) <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ notify-delay <replaceable>seconds</replaceable>;
+ notify-to-soa <replaceable>boolean</replaceable>;
+ also-notify <optional> port <replaceable>integer</replaceable> </optional> { ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> )
+ <optional> port <replaceable>integer</replaceable> </optional>; ... };
+ allow-notify { <replaceable>address_match_element</replaceable>; ... };
+
+ forward ( first | only );
+ forwarders <optional> port <replaceable>integer</replaceable> </optional> {
+ ( <replaceable>ipv4_address</replaceable> | <replaceable>ipv6_address</replaceable> ) <optional> port <replaceable>integer</replaceable> </optional>; ...
+ };
+
+ max-journal-size <replaceable>size_no_default</replaceable>;
+ max-transfer-time-in <replaceable>integer</replaceable>;
+ max-transfer-time-out <replaceable>integer</replaceable>;
+ max-transfer-idle-in <replaceable>integer</replaceable>;
+ max-transfer-idle-out <replaceable>integer</replaceable>;
+ max-retry-time <replaceable>integer</replaceable>;
+ min-retry-time <replaceable>integer</replaceable>;
+ max-refresh-time <replaceable>integer</replaceable>;
+ min-refresh-time <replaceable>integer</replaceable>;
+ multi-master <replaceable>boolean</replaceable>;
+ sig-validity-interval <replaceable>integer</replaceable>;
+
+ transfer-source ( <replaceable>ipv4_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+
+ alt-transfer-source ( <replaceable>ipv4_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ alt-transfer-source-v6 ( <replaceable>ipv6_address</replaceable> | * )
+ <optional> port ( <replaceable>integer</replaceable> | * ) </optional>;
+ use-alt-transfer-source <replaceable>boolean</replaceable>;
+
+ zone-statistics <replaceable>boolean</replaceable>;
+ try-tcp-refresh <replaceable>boolean</replaceable>;
+ key-directory <replaceable>quoted_string</replaceable>;
+
+ nsec3-test-zone <replaceable>boolean</replaceable>; // testing only
+
+ ixfr-base <replaceable>quoted_string</replaceable>; // obsolete
+ ixfr-tmp-file <replaceable>quoted_string</replaceable>; // obsolete
+ maintain-ixfr-base <replaceable>boolean</replaceable>; // obsolete
+ max-ixfr-log-size <replaceable>size</replaceable>; // obsolete
+ pubkey <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>; // obsolete
+};
+</literallayout>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+ <para><filename>/etc/named.conf</filename>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named-checkconf</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/named/named.conf.html b/bin/named/named.conf.html
new file mode 100644
index 0000000..7bbbd0a
--- /dev/null
+++ b/bin/named/named.conf.html
@@ -0,0 +1,585 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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.conf.html,v 1.45 2008/09/25 04:45:04 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named.conf</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><code class="filename">named.conf</code> &#8212; configuration file for named</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">named.conf</code> </p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543342"></a><h2>DESCRIPTION</h2>
+<p><code class="filename">named.conf</code> is the configuration file
+ for
+ <span><strong class="command">named</strong></span>. Statements are enclosed
+ in braces and terminated with a semi-colon. Clauses in
+ the statements are also semi-colon terminated. The usual
+ comment styles are supported:
+ </p>
+<p>
+ C style: /* */
+ </p>
+<p>
+ C++ style: // to end of line
+ </p>
+<p>
+ Unix style: # to end of line
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543370"></a><h2>ACL</h2>
+<div class="literallayout"><p><br>
+acl <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543386"></a><h2>KEY</h2>
+<div class="literallayout"><p><br>
+key <em class="replaceable"><code>domain_name</code></em> {<br>
+ algorithm <em class="replaceable"><code>string</code></em>;<br>
+ secret <em class="replaceable"><code>string</code></em>;<br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543405"></a><h2>MASTERS</h2>
+<div class="literallayout"><p><br>
+masters <em class="replaceable"><code>string</code></em> [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br>
+ ( <em class="replaceable"><code>masters</code></em> | <em class="replaceable"><code>ipv4_address</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] |<br>
+ <em class="replaceable"><code>ipv6_address</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] ) [<span class="optional"> key <em class="replaceable"><code>string</code></em> </span>]; ...<br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543451"></a><h2>SERVER</h2>
+<div class="literallayout"><p><br>
+server ( <em class="replaceable"><code>ipv4_address[<span class="optional">/prefixlen</span>]</code></em> | <em class="replaceable"><code>ipv6_address[<span class="optional">/prefixlen</span>]</code></em> ) {<br>
+ bogus <em class="replaceable"><code>boolean</code></em>;<br>
+ edns <em class="replaceable"><code>boolean</code></em>;<br>
+ edns-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ max-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ provide-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ request-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ keys <em class="replaceable"><code>server_key</code></em>;<br>
+ transfers <em class="replaceable"><code>integer</code></em>;<br>
+ transfer-format ( many-answers | one-answer );<br>
+ transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+<br>
+ support-ixfr <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543520"></a><h2>TRUSTED-KEYS</h2>
+<div class="literallayout"><p><br>
+trusted-keys {<br>
+ <em class="replaceable"><code>domain_name</code></em> <em class="replaceable"><code>flags</code></em> <em class="replaceable"><code>protocol</code></em> <em class="replaceable"><code>algorithm</code></em> <em class="replaceable"><code>key</code></em>; ... <br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543545"></a><h2>CONTROLS</h2>
+<div class="literallayout"><p><br>
+controls {<br>
+ inet ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>]<br>
+ allow { <em class="replaceable"><code>address_match_element</code></em>; ... }<br>
+ [<span class="optional"> keys { <em class="replaceable"><code>string</code></em>; ... } </span>];<br>
+ unix <em class="replaceable"><code>unsupported</code></em>; // not implemented<br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543580"></a><h2>LOGGING</h2>
+<div class="literallayout"><p><br>
+logging {<br>
+ channel <em class="replaceable"><code>string</code></em> {<br>
+ file <em class="replaceable"><code>log_file</code></em>;<br>
+ syslog <em class="replaceable"><code>optional_facility</code></em>;<br>
+ null;<br>
+ stderr;<br>
+ severity <em class="replaceable"><code>log_severity</code></em>;<br>
+ print-time <em class="replaceable"><code>boolean</code></em>;<br>
+ print-severity <em class="replaceable"><code>boolean</code></em>;<br>
+ print-category <em class="replaceable"><code>boolean</code></em>;<br>
+ };<br>
+ category <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>string</code></em>; ... };<br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543619"></a><h2>LWRES</h2>
+<div class="literallayout"><p><br>
+lwres {<br>
+ listen-on [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br>
+ ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> ) [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ...<br>
+ };<br>
+ view <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>optional_class</code></em>;<br>
+ search { <em class="replaceable"><code>string</code></em>; ... };<br>
+ ndots <em class="replaceable"><code>integer</code></em>;<br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543660"></a><h2>OPTIONS</h2>
+<div class="literallayout"><p><br>
+options {<br>
+ avoid-v4-udp-ports { <em class="replaceable"><code>port</code></em>; ... };<br>
+ avoid-v6-udp-ports { <em class="replaceable"><code>port</code></em>; ... };<br>
+ blackhole { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ coresize <em class="replaceable"><code>size</code></em>;<br>
+ datasize <em class="replaceable"><code>size</code></em>;<br>
+ directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ dump-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ files <em class="replaceable"><code>size</code></em>;<br>
+ heartbeat-interval <em class="replaceable"><code>integer</code></em>;<br>
+ host-statistics <em class="replaceable"><code>boolean</code></em>; // not implemented<br>
+ host-statistics-max <em class="replaceable"><code>number</code></em>; // not implemented<br>
+ hostname ( <em class="replaceable"><code>quoted_string</code></em> | none );<br>
+ interface-interval <em class="replaceable"><code>integer</code></em>;<br>
+ listen-on [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ listen-on-v6 [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ match-mapped-addresses <em class="replaceable"><code>boolean</code></em>;<br>
+ memstatistics-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ pid-file ( <em class="replaceable"><code>quoted_string</code></em> | none );<br>
+ port <em class="replaceable"><code>integer</code></em>;<br>
+ querylog <em class="replaceable"><code>boolean</code></em>;<br>
+ recursing-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ reserved-sockets <em class="replaceable"><code>integer</code></em>;<br>
+ random-device <em class="replaceable"><code>quoted_string</code></em>;<br>
+ recursive-clients <em class="replaceable"><code>integer</code></em>;<br>
+ serial-query-rate <em class="replaceable"><code>integer</code></em>;<br>
+ server-id ( <em class="replaceable"><code>quoted_string</code></em> | none |;<br>
+ stacksize <em class="replaceable"><code>size</code></em>;<br>
+ statistics-file <em class="replaceable"><code>quoted_string</code></em>;<br>
+ statistics-interval <em class="replaceable"><code>integer</code></em>; // not yet implemented<br>
+ tcp-clients <em class="replaceable"><code>integer</code></em>;<br>
+ tcp-listen-queue <em class="replaceable"><code>integer</code></em>;<br>
+ tkey-dhkey <em class="replaceable"><code>quoted_string</code></em> <em class="replaceable"><code>integer</code></em>;<br>
+ tkey-gssapi-credential <em class="replaceable"><code>quoted_string</code></em>;<br>
+ tkey-domain <em class="replaceable"><code>quoted_string</code></em>;<br>
+ transfers-per-ns <em class="replaceable"><code>integer</code></em>;<br>
+ transfers-in <em class="replaceable"><code>integer</code></em>;<br>
+ transfers-out <em class="replaceable"><code>integer</code></em>;<br>
+ use-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ version ( <em class="replaceable"><code>quoted_string</code></em> | none );<br>
+ allow-recursion { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-recursion-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ sortlist { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ topology { <em class="replaceable"><code>address_match_element</code></em>; ... }; // not implemented<br>
+ auth-nxdomain <em class="replaceable"><code>boolean</code></em>; // default changed<br>
+ minimal-responses <em class="replaceable"><code>boolean</code></em>;<br>
+ recursion <em class="replaceable"><code>boolean</code></em>;<br>
+ rrset-order {<br>
+ [<span class="optional"> class <em class="replaceable"><code>string</code></em> </span>] [<span class="optional"> type <em class="replaceable"><code>string</code></em> </span>]<br>
+ [<span class="optional"> name <em class="replaceable"><code>quoted_string</code></em> </span>] <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>string</code></em>; ...<br>
+ };<br>
+ provide-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ request-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ rfc2308-type1 <em class="replaceable"><code>boolean</code></em>; // not yet implemented<br>
+ additional-from-auth <em class="replaceable"><code>boolean</code></em>;<br>
+ additional-from-cache <em class="replaceable"><code>boolean</code></em>;<br>
+ query-source ( ( <em class="replaceable"><code>ipv4_address</code></em> | * ) | [<span class="optional"> address ( <em class="replaceable"><code>ipv4_address</code></em> | * ) </span>] ) [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ query-source-v6 ( ( <em class="replaceable"><code>ipv6_address</code></em> | * ) | [<span class="optional"> address ( <em class="replaceable"><code>ipv6_address</code></em> | * ) </span>] ) [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ use-queryport-pool <em class="replaceable"><code>boolean</code></em>;<br>
+ queryport-pool-ports <em class="replaceable"><code>integer</code></em>;<br>
+ queryport-pool-updateinterval <em class="replaceable"><code>integer</code></em>;<br>
+ cleaning-interval <em class="replaceable"><code>integer</code></em>;<br>
+ min-roots <em class="replaceable"><code>integer</code></em>; // not implemented<br>
+ lame-ttl <em class="replaceable"><code>integer</code></em>;<br>
+ max-ncache-ttl <em class="replaceable"><code>integer</code></em>;<br>
+ max-cache-ttl <em class="replaceable"><code>integer</code></em>;<br>
+ transfer-format ( many-answers | one-answer );<br>
+ max-cache-size <em class="replaceable"><code>size</code></em>;<br>
+ max-acache-size <em class="replaceable"><code>size</code></em>;<br>
+ clients-per-query <em class="replaceable"><code>number</code></em>;<br>
+ max-clients-per-query <em class="replaceable"><code>number</code></em>;<br>
+ check-names ( master | slave | response )<br>
+ ( fail | warn | ignore );<br>
+ check-mx ( fail | warn | ignore );<br>
+ check-integrity <em class="replaceable"><code>boolean</code></em>;<br>
+ check-mx-cname ( fail | warn | ignore );<br>
+ check-srv-cname ( fail | warn | ignore );<br>
+ cache-file <em class="replaceable"><code>quoted_string</code></em>; // test option<br>
+ suppress-initial-notify <em class="replaceable"><code>boolean</code></em>; // not yet implemented<br>
+ preferred-glue <em class="replaceable"><code>string</code></em>;<br>
+ dual-stack-servers [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br>
+ ( <em class="replaceable"><code>quoted_string</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] |<br>
+ <em class="replaceable"><code>ipv4_address</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] |<br>
+ <em class="replaceable"><code>ipv6_address</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] ); ...<br>
+ };<br>
+ edns-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ max-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ root-delegation-only [<span class="optional"> exclude { <em class="replaceable"><code>quoted_string</code></em>; ... } </span>];<br>
+ disable-algorithms <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>string</code></em>; ... };<br>
+ dnssec-enable <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-validation <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-lookaside <em class="replaceable"><code>string</code></em> trust-anchor <em class="replaceable"><code>string</code></em>;<br>
+ dnssec-must-be-secure <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-accept-expired <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ empty-server <em class="replaceable"><code>string</code></em>;<br>
+ empty-contact <em class="replaceable"><code>string</code></em>;<br>
+ empty-zones-enable <em class="replaceable"><code>boolean</code></em>;<br>
+ disable-empty-zone <em class="replaceable"><code>string</code></em>;<br>
+<br>
+ dialup <em class="replaceable"><code>dialuptype</code></em>;<br>
+ ixfr-from-differences <em class="replaceable"><code>ixfrdiff</code></em>;<br>
+<br>
+ allow-query { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-cache { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-cache-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-transfer { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ masterfile-format ( text | raw );<br>
+ notify <em class="replaceable"><code>notifytype</code></em>;<br>
+ notify-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ notify-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ notify-delay <em class="replaceable"><code>seconds</code></em>;<br>
+ notify-to-soa <em class="replaceable"><code>boolean</code></em>;<br>
+ also-notify [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] { ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> )<br>
+ [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ... };<br>
+ allow-notify { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+<br>
+ forward ( first | only );<br>
+ forwarders [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br>
+ ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> ) [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ...<br>
+ };<br>
+<br>
+ max-journal-size <em class="replaceable"><code>size_no_default</code></em>;<br>
+ max-transfer-time-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ min-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ min-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ multi-master <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ sig-validity-interval <em class="replaceable"><code>integer</code></em>;<br>
+ sig-re-signing-interval <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-nodes <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-signatures <em class="replaceable"><code>integer</code></em>;<br>
+ sig-signing-type <em class="replaceable"><code>integer</code></em>;<br>
+<br>
+ transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+<br>
+ alt-transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ alt-transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ use-alt-transfer-source <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ zone-statistics <em class="replaceable"><code>boolean</code></em>;<br>
+ key-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ try-tcp-refresh <em class="replaceable"><code>boolean</code></em>;<br>
+ zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br>
+ zero-no-soa-ttl-cache <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ nsec3-test-zone <em class="replaceable"><code>boolean</code></em>;  // testing only<br>
+<br>
+ allow-v6-synthesis { <em class="replaceable"><code>address_match_element</code></em>; ... }; // obsolete<br>
+ deallocate-on-exit <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+ fake-iquery <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+ fetch-glue <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+ has-old-clients <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+ maintain-ixfr-base <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+ max-ixfr-log-size <em class="replaceable"><code>size</code></em>; // obsolete<br>
+ multiple-cnames <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+ named-xfer <em class="replaceable"><code>quoted_string</code></em>; // obsolete<br>
+ serial-queries <em class="replaceable"><code>integer</code></em>; // obsolete<br>
+ treat-cr-as-space <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+ use-id-pool <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544452"></a><h2>VIEW</h2>
+<div class="literallayout"><p><br>
+view <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>optional_class</code></em> {<br>
+ match-clients { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ match-destinations { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ match-recursive-only <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ key <em class="replaceable"><code>string</code></em> {<br>
+ algorithm <em class="replaceable"><code>string</code></em>;<br>
+ secret <em class="replaceable"><code>string</code></em>;<br>
+ };<br>
+<br>
+ zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>optional_class</code></em> {<br>
+ ...<br>
+ };<br>
+<br>
+ server ( <em class="replaceable"><code>ipv4_address[<span class="optional">/prefixlen</span>]</code></em> | <em class="replaceable"><code>ipv6_address[<span class="optional">/prefixlen</span>]</code></em> ) {<br>
+ ...<br>
+ };<br>
+<br>
+ trusted-keys {<br>
+ <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>quoted_string</code></em>; ...<br>
+ };<br>
+<br>
+ allow-recursion { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-recursion-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ sortlist { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ topology { <em class="replaceable"><code>address_match_element</code></em>; ... }; // not implemented<br>
+ auth-nxdomain <em class="replaceable"><code>boolean</code></em>; // default changed<br>
+ minimal-responses <em class="replaceable"><code>boolean</code></em>;<br>
+ recursion <em class="replaceable"><code>boolean</code></em>;<br>
+ rrset-order {<br>
+ [<span class="optional"> class <em class="replaceable"><code>string</code></em> </span>] [<span class="optional"> type <em class="replaceable"><code>string</code></em> </span>]<br>
+ [<span class="optional"> name <em class="replaceable"><code>quoted_string</code></em> </span>] <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>string</code></em>; ...<br>
+ };<br>
+ provide-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ request-ixfr <em class="replaceable"><code>boolean</code></em>;<br>
+ rfc2308-type1 <em class="replaceable"><code>boolean</code></em>; // not yet implemented<br>
+ additional-from-auth <em class="replaceable"><code>boolean</code></em>;<br>
+ additional-from-cache <em class="replaceable"><code>boolean</code></em>;<br>
+ query-source ( ( <em class="replaceable"><code>ipv4_address</code></em> | * ) | [<span class="optional"> address ( <em class="replaceable"><code>ipv4_address</code></em> | * ) </span>] ) [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ query-source-v6 ( ( <em class="replaceable"><code>ipv6_address</code></em> | * ) | [<span class="optional"> address ( <em class="replaceable"><code>ipv6_address</code></em> | * ) </span>] ) [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ use-queryport-pool <em class="replaceable"><code>boolean</code></em>;<br>
+ queryport-pool-ports <em class="replaceable"><code>integer</code></em>;<br>
+ queryport-pool-updateinterval <em class="replaceable"><code>integer</code></em>;<br>
+ cleaning-interval <em class="replaceable"><code>integer</code></em>;<br>
+ min-roots <em class="replaceable"><code>integer</code></em>; // not implemented<br>
+ lame-ttl <em class="replaceable"><code>integer</code></em>;<br>
+ max-ncache-ttl <em class="replaceable"><code>integer</code></em>;<br>
+ max-cache-ttl <em class="replaceable"><code>integer</code></em>;<br>
+ transfer-format ( many-answers | one-answer );<br>
+ max-cache-size <em class="replaceable"><code>size</code></em>;<br>
+ max-acache-size <em class="replaceable"><code>size</code></em>;<br>
+ clients-per-query <em class="replaceable"><code>number</code></em>;<br>
+ max-clients-per-query <em class="replaceable"><code>number</code></em>;<br>
+ check-names ( master | slave | response )<br>
+ ( fail | warn | ignore );<br>
+ check-mx ( fail | warn | ignore );<br>
+ check-integrity <em class="replaceable"><code>boolean</code></em>;<br>
+ check-mx-cname ( fail | warn | ignore );<br>
+ check-srv-cname ( fail | warn | ignore );<br>
+ cache-file <em class="replaceable"><code>quoted_string</code></em>; // test option<br>
+ suppress-initial-notify <em class="replaceable"><code>boolean</code></em>; // not yet implemented<br>
+ preferred-glue <em class="replaceable"><code>string</code></em>;<br>
+ dual-stack-servers [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br>
+ ( <em class="replaceable"><code>quoted_string</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] |<br>
+ <em class="replaceable"><code>ipv4_address</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] |<br>
+ <em class="replaceable"><code>ipv6_address</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] ); ...<br>
+ };<br>
+ edns-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ max-udp-size <em class="replaceable"><code>integer</code></em>;<br>
+ root-delegation-only [<span class="optional"> exclude { <em class="replaceable"><code>quoted_string</code></em>; ... } </span>];<br>
+ disable-algorithms <em class="replaceable"><code>string</code></em> { <em class="replaceable"><code>string</code></em>; ... };<br>
+ dnssec-enable <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-validation <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-lookaside <em class="replaceable"><code>string</code></em> trust-anchor <em class="replaceable"><code>string</code></em>;<br>
+ dnssec-must-be-secure <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>boolean</code></em>;<br>
+ dnssec-accept-expired <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ empty-server <em class="replaceable"><code>string</code></em>;<br>
+ empty-contact <em class="replaceable"><code>string</code></em>;<br>
+ empty-zones-enable <em class="replaceable"><code>boolean</code></em>;<br>
+ disable-empty-zone <em class="replaceable"><code>string</code></em>;<br>
+<br>
+ dialup <em class="replaceable"><code>dialuptype</code></em>;<br>
+ ixfr-from-differences <em class="replaceable"><code>ixfrdiff</code></em>;<br>
+<br>
+ allow-query { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-cache { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-cache-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-transfer { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ masterfile-format ( text | raw );<br>
+ notify <em class="replaceable"><code>notifytype</code></em>;<br>
+ notify-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ notify-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ notify-delay <em class="replaceable"><code>seconds</code></em>;<br>
+ notify-to-soa <em class="replaceable"><code>boolean</code></em>;<br>
+ also-notify [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] { ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> )<br>
+ [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ... };<br>
+ allow-notify { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+<br>
+ forward ( first | only );<br>
+ forwarders [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br>
+ ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> ) [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ...<br>
+ };<br>
+<br>
+ max-journal-size <em class="replaceable"><code>size_no_default</code></em>;<br>
+ max-transfer-time-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ min-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ min-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ multi-master <em class="replaceable"><code>boolean</code></em>;<br>
+ sig-validity-interval <em class="replaceable"><code>integer</code></em>;<br>
+<br>
+ transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+<br>
+ alt-transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ alt-transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ use-alt-transfer-source <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ zone-statistics <em class="replaceable"><code>boolean</code></em>;<br>
+ try-tcp-refresh <em class="replaceable"><code>boolean</code></em>;<br>
+ key-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+ zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br>
+ zero-no-soa-ttl-cache <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ allow-v6-synthesis { <em class="replaceable"><code>address_match_element</code></em>; ... }; // obsolete<br>
+ fetch-glue <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+ maintain-ixfr-base <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+ max-ixfr-log-size <em class="replaceable"><code>size</code></em>; // obsolete<br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545113"></a><h2>ZONE</h2>
+<div class="literallayout"><p><br>
+zone <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>optional_class</code></em> {<br>
+ type ( master | slave | stub | hint |<br>
+ forward | delegation-only );<br>
+ file <em class="replaceable"><code>quoted_string</code></em>;<br>
+<br>
+ masters [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br>
+ ( <em class="replaceable"><code>masters</code></em> |<br>
+ <em class="replaceable"><code>ipv4_address</code></em> [<span class="optional">port <em class="replaceable"><code>integer</code></em></span>] |<br>
+ <em class="replaceable"><code>ipv6_address</code></em> [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] ) [<span class="optional"> key <em class="replaceable"><code>string</code></em> </span>]; ...<br>
+ };<br>
+<br>
+ database <em class="replaceable"><code>string</code></em>;<br>
+ delegation-only <em class="replaceable"><code>boolean</code></em>;<br>
+ check-names ( fail | warn | ignore );<br>
+ check-mx ( fail | warn | ignore );<br>
+ check-integrity <em class="replaceable"><code>boolean</code></em>;<br>
+ check-mx-cname ( fail | warn | ignore );<br>
+ check-srv-cname ( fail | warn | ignore );<br>
+ dialup <em class="replaceable"><code>dialuptype</code></em>;<br>
+ ixfr-from-differences <em class="replaceable"><code>boolean</code></em>;<br>
+ journal <em class="replaceable"><code>quoted_string</code></em>;<br>
+ zero-no-soa-ttl <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ allow-query { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-query-on { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-transfer { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ allow-update-forwarding { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+ update-policy {<br>
+ ( grant | deny ) <em class="replaceable"><code>string</code></em><br>
+ ( name | subdomain | wildcard | self | selfsub | selfwild |<br>
+                  krb5-self | ms-self | krb5-subdomain | ms-subdomain |<br>
+   tcp-self | 6to4-self ) <em class="replaceable"><code>string</code></em><br>
+ <em class="replaceable"><code>rrtypelist</code></em>; ...<br>
+ };<br>
+ update-check-ksk <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ masterfile-format ( text | raw );<br>
+ notify <em class="replaceable"><code>notifytype</code></em>;<br>
+ notify-source ( <em class="replaceable"><code>ipv4_address</code></em> | * ) [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ notify-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * ) [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ notify-delay <em class="replaceable"><code>seconds</code></em>;<br>
+ notify-to-soa <em class="replaceable"><code>boolean</code></em>;<br>
+ also-notify [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] { ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> )<br>
+ [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ... };<br>
+ allow-notify { <em class="replaceable"><code>address_match_element</code></em>; ... };<br>
+<br>
+ forward ( first | only );<br>
+ forwarders [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>] {<br>
+ ( <em class="replaceable"><code>ipv4_address</code></em> | <em class="replaceable"><code>ipv6_address</code></em> ) [<span class="optional"> port <em class="replaceable"><code>integer</code></em> </span>]; ...<br>
+ };<br>
+<br>
+ max-journal-size <em class="replaceable"><code>size_no_default</code></em>;<br>
+ max-transfer-time-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-time-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-in <em class="replaceable"><code>integer</code></em>;<br>
+ max-transfer-idle-out <em class="replaceable"><code>integer</code></em>;<br>
+ max-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ min-retry-time <em class="replaceable"><code>integer</code></em>;<br>
+ max-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ min-refresh-time <em class="replaceable"><code>integer</code></em>;<br>
+ multi-master <em class="replaceable"><code>boolean</code></em>;<br>
+ sig-validity-interval <em class="replaceable"><code>integer</code></em>;<br>
+<br>
+ transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+<br>
+ alt-transfer-source ( <em class="replaceable"><code>ipv4_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ alt-transfer-source-v6 ( <em class="replaceable"><code>ipv6_address</code></em> | * )<br>
+ [<span class="optional"> port ( <em class="replaceable"><code>integer</code></em> | * ) </span>];<br>
+ use-alt-transfer-source <em class="replaceable"><code>boolean</code></em>;<br>
+<br>
+ zone-statistics <em class="replaceable"><code>boolean</code></em>;<br>
+ try-tcp-refresh <em class="replaceable"><code>boolean</code></em>;<br>
+ key-directory <em class="replaceable"><code>quoted_string</code></em>;<br>
+<br>
+ nsec3-test-zone <em class="replaceable"><code>boolean</code></em>;  // testing only<br>
+<br>
+ ixfr-base <em class="replaceable"><code>quoted_string</code></em>; // obsolete<br>
+ ixfr-tmp-file <em class="replaceable"><code>quoted_string</code></em>; // obsolete<br>
+ maintain-ixfr-base <em class="replaceable"><code>boolean</code></em>; // obsolete<br>
+ max-ixfr-log-size <em class="replaceable"><code>size</code></em>; // obsolete<br>
+ pubkey <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>integer</code></em> <em class="replaceable"><code>quoted_string</code></em>; // obsolete<br>
+};<br>
+</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545410"></a><h2>FILES</h2>
+<p><code class="filename">/etc/named.conf</code>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545421"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named-checkconf</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/named/named.docbook b/bin/named/named.docbook
new file mode 100644
index 0000000..f47eae1
--- /dev/null
+++ b/bin/named/named.docbook
@@ -0,0 +1,445 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004-2008 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
+ - 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.docbook,v 1.23 2008/11/06 05:30:24 marka Exp $ -->
+<refentry id="man.named">
+ <refentryinfo>
+ <date>June 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>named</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>named</application></refname>
+ <refpurpose>Internet domain name server</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>named</command>
+ <arg><option>-4</option></arg>
+ <arg><option>-6</option></arg>
+ <arg><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
+ <arg><option>-d <replaceable class="parameter">debug-level</replaceable></option></arg>
+ <arg><option>-f</option></arg>
+ <arg><option>-g</option></arg>
+ <arg><option>-m <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg><option>-n <replaceable class="parameter">#cpus</replaceable></option></arg>
+ <arg><option>-p <replaceable class="parameter">port</replaceable></option></arg>
+ <arg><option>-s</option></arg>
+ <arg><option>-S <replaceable class="parameter">#max-socks</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">directory</replaceable></option></arg>
+ <arg><option>-u <replaceable class="parameter">user</replaceable></option></arg>
+ <arg><option>-v</option></arg>
+ <arg><option>-V</option></arg>
+ <arg><option>-x <replaceable class="parameter">cache-file</replaceable></option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>named</command>
+ is a Domain Name System (DNS) server,
+ part of the BIND 9 distribution from ISC. For more
+ information on the DNS, see RFCs 1033, 1034, and 1035.
+ </para>
+ <para>
+ When invoked without arguments, <command>named</command>
+ will
+ read the default configuration file
+ <filename>/etc/named.conf</filename>, read any initial
+ data, and listen for queries.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-4</term>
+ <listitem>
+ <para>
+ Use IPv4 only even if the host machine is capable of IPv6.
+ <option>-4</option> and <option>-6</option> are mutually
+ exclusive.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-6</term>
+ <listitem>
+ <para>
+ Use IPv6 only even if the host machine is capable of IPv4.
+ <option>-4</option> and <option>-6</option> are mutually
+ exclusive.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>-c <replaceable class="parameter">config-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">config-file</replaceable> as the
+ configuration file instead of the default,
+ <filename>/etc/named.conf</filename>. To
+ ensure that reloading the configuration file continues
+ to work after the server has changed its working
+ directory due to to a possible
+ <option>directory</option> option in the configuration
+ file, <replaceable class="parameter">config-file</replaceable> should be
+ an absolute pathname.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d <replaceable class="parameter">debug-level</replaceable></term>
+ <listitem>
+ <para>
+ Set the daemon's debug level to <replaceable class="parameter">debug-level</replaceable>.
+ Debugging traces from <command>named</command> become
+ more verbose as the debug level increases.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f</term>
+ <listitem>
+ <para>
+ Run the server in the foreground (i.e. do not daemonize).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-g</term>
+ <listitem>
+ <para>
+ Run the server in the foreground and force all logging
+ to <filename>stderr</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Turn on memory usage debugging flags. Possible flags are
+ <replaceable class="parameter">usage</replaceable>,
+ <replaceable class="parameter">trace</replaceable>,
+ <replaceable class="parameter">record</replaceable>,
+ <replaceable class="parameter">size</replaceable>, and
+ <replaceable class="parameter">mctx</replaceable>.
+ These correspond to the ISC_MEM_DEBUGXXXX flags described in
+ <filename>&lt;isc/mem.h&gt;</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-n <replaceable class="parameter">#cpus</replaceable></term>
+ <listitem>
+ <para>
+ Create <replaceable class="parameter">#cpus</replaceable> worker threads
+ to take advantage of multiple CPUs. If not specified,
+ <command>named</command> will try to determine the
+ number of CPUs present and create one thread per CPU.
+ If it is unable to determine the number of CPUs, a
+ single worker thread will be created.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Listen for queries on port <replaceable class="parameter">port</replaceable>. If not
+ specified, the default is port 53.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s</term>
+ <listitem>
+ <para>
+ Write memory usage statistics to <filename>stdout</filename> on exit.
+ </para>
+ <note>
+ <para>
+ This option is mainly of interest to BIND 9 developers
+ and may be removed or changed in a future release.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-S <replaceable class="parameter">#max-socks</replaceable></term>
+ <listitem>
+ <para>
+ Allow <command>named</command> to use up to
+ <replaceable class="parameter">#max-socks</replaceable> sockets.
+ </para>
+ <warning>
+ <para>
+ This option should be unnecessary for the vast majority
+ of users.
+ The use of this option could even be harmful because the
+ specified value may exceed the limitation of the
+ underlying system API.
+ It is therefore set only when the default configuration
+ causes exhaustion of file descriptors and the
+ operational environment is known to support the
+ specified number of sockets.
+ Note also that the actual maximum number is normally a little
+ fewer than the specified value because
+ <command>named</command> reserves some file descriptors
+ for its internal use.
+ </para>
+ </warning>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">directory</replaceable></term>
+ <listitem>
+ <para>Chroot
+ to <replaceable class="parameter">directory</replaceable> after
+ processing the command line arguments, but before
+ reading the configuration file.
+ </para>
+ <warning>
+ <para>
+ This option should be used in conjunction with the
+ <option>-u</option> option, as chrooting a process
+ running as root doesn't enhance security on most
+ systems; the way <function>chroot(2)</function> is
+ defined allows a process with root privileges to
+ escape a chroot jail.
+ </para>
+ </warning>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-u <replaceable class="parameter">user</replaceable></term>
+ <listitem>
+ <para>Setuid
+ to <replaceable class="parameter">user</replaceable> after completing
+ privileged operations, such as creating sockets that
+ listen on privileged ports.
+ </para>
+ <note>
+ <para>
+ On Linux, <command>named</command> uses the kernel's
+ capability mechanism to drop all root privileges
+ except the ability to <function>bind(2)</function> to
+ a
+ privileged port and set process resource limits.
+ Unfortunately, this means that the <option>-u</option>
+ option only works when <command>named</command> is
+ run
+ on kernel 2.2.18 or later, or kernel 2.3.99-pre3 or
+ later, since previous kernels did not allow privileges
+ to be retained after <function>setuid(2)</function>.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Report the version number and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Report the version number and build options, and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-x <replaceable class="parameter">cache-file</replaceable></term>
+ <listitem>
+ <para>
+ Load data from <replaceable class="parameter">cache-file</replaceable> into the
+ cache of the default view.
+ </para>
+ <warning>
+ <para>
+ This option must not be used. It is only of interest
+ to BIND 9 developers and may be removed or changed in a
+ future release.
+ </para>
+ </warning>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>SIGNALS</title>
+ <para>
+ In routine operation, signals should not be used to control
+ the nameserver; <command>rndc</command> should be used
+ instead.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>SIGHUP</term>
+ <listitem>
+ <para>
+ Force a reload of the server.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>SIGINT, SIGTERM</term>
+ <listitem>
+ <para>
+ Shut down the server.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+ The result of sending any other signals to the server is undefined.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>CONFIGURATION</title>
+ <para>
+ The <command>named</command> configuration file is too complex
+ to describe in detail here. A complete description is provided
+ in the
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><filename>/etc/named.conf</filename></term>
+ <listitem>
+ <para>
+ The default configuration file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><filename>/var/run/named/named.pid</filename></term>
+ <listitem>
+ <para>
+ The default process-id file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citetitle>RFC 1033</citetitle>,
+ <citetitle>RFC 1034</citetitle>,
+ <citetitle>RFC 1035</citetitle>,
+ <citerefentry>
+ <refentrytitle>named-checkconf</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named-checkzone</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>lwresd</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named.conf</refentrytitle>
+ <manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/named/named.html b/bin/named/named.html
new file mode 100644
index 0000000..23c9a7c
--- /dev/null
+++ b/bin/named/named.html
@@ -0,0 +1,284 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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.html,v 1.30 2008/11/07 01:11:19 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.named"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">named</span> &#8212; Internet domain name server</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">named</code> [<code class="option">-4</code>] [<code class="option">-6</code>] [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>] [<code class="option">-f</code>] [<code class="option">-g</code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-s</code>] [<code class="option">-S <em class="replaceable"><code>#max-socks</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>] [<code class="option">-v</code>] [<code class="option">-V</code>] [<code class="option">-x <em class="replaceable"><code>cache-file</code></em></code>]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543468"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">named</strong></span>
+ is a Domain Name System (DNS) server,
+ part of the BIND 9 distribution from ISC. For more
+ information on the DNS, see RFCs 1033, 1034, and 1035.
+ </p>
+<p>
+ When invoked without arguments, <span><strong class="command">named</strong></span>
+ will
+ read the default configuration file
+ <code class="filename">/etc/named.conf</code>, read any initial
+ data, and listen for queries.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543493"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-4</span></dt>
+<dd><p>
+ Use IPv4 only even if the host machine is capable of IPv6.
+ <code class="option">-4</code> and <code class="option">-6</code> are mutually
+ exclusive.
+ </p></dd>
+<dt><span class="term">-6</span></dt>
+<dd><p>
+ Use IPv6 only even if the host machine is capable of IPv4.
+ <code class="option">-4</code> and <code class="option">-6</code> are mutually
+ exclusive.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>config-file</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>config-file</code></em> as the
+ configuration file instead of the default,
+ <code class="filename">/etc/named.conf</code>. To
+ ensure that reloading the configuration file continues
+ to work after the server has changed its working
+ directory due to to a possible
+ <code class="option">directory</code> option in the configuration
+ file, <em class="replaceable"><code>config-file</code></em> should be
+ an absolute pathname.
+ </p></dd>
+<dt><span class="term">-d <em class="replaceable"><code>debug-level</code></em></span></dt>
+<dd><p>
+ Set the daemon's debug level to <em class="replaceable"><code>debug-level</code></em>.
+ Debugging traces from <span><strong class="command">named</strong></span> become
+ more verbose as the debug level increases.
+ </p></dd>
+<dt><span class="term">-f</span></dt>
+<dd><p>
+ Run the server in the foreground (i.e. do not daemonize).
+ </p></dd>
+<dt><span class="term">-g</span></dt>
+<dd><p>
+ Run the server in the foreground and force all logging
+ to <code class="filename">stderr</code>.
+ </p></dd>
+<dt><span class="term">-m <em class="replaceable"><code>flag</code></em></span></dt>
+<dd><p>
+ Turn on memory usage debugging flags. Possible flags are
+ <em class="replaceable"><code>usage</code></em>,
+ <em class="replaceable"><code>trace</code></em>,
+ <em class="replaceable"><code>record</code></em>,
+ <em class="replaceable"><code>size</code></em>, and
+ <em class="replaceable"><code>mctx</code></em>.
+ These correspond to the ISC_MEM_DEBUGXXXX flags described in
+ <code class="filename">&lt;isc/mem.h&gt;</code>.
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>#cpus</code></em></span></dt>
+<dd><p>
+ Create <em class="replaceable"><code>#cpus</code></em> worker threads
+ to take advantage of multiple CPUs. If not specified,
+ <span><strong class="command">named</strong></span> will try to determine the
+ number of CPUs present and create one thread per CPU.
+ If it is unable to determine the number of CPUs, a
+ single worker thread will be created.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd><p>
+ Listen for queries on port <em class="replaceable"><code>port</code></em>. If not
+ specified, the default is port 53.
+ </p></dd>
+<dt><span class="term">-s</span></dt>
+<dd>
+<p>
+ Write memory usage statistics to <code class="filename">stdout</code> on exit.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ This option is mainly of interest to BIND 9 developers
+ and may be removed or changed in a future release.
+ </p>
+</div>
+</dd>
+<dt><span class="term">-S <em class="replaceable"><code>#max-socks</code></em></span></dt>
+<dd>
+<p>
+ Allow <span><strong class="command">named</strong></span> to use up to
+ <em class="replaceable"><code>#max-socks</code></em> sockets.
+ </p>
+<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+<p>
+ This option should be unnecessary for the vast majority
+ of users.
+ The use of this option could even be harmful because the
+ specified value may exceed the limitation of the
+ underlying system API.
+ It is therefore set only when the default configuration
+ causes exhaustion of file descriptors and the
+ operational environment is known to support the
+ specified number of sockets.
+ Note also that the actual maximum number is normally a little
+ fewer than the specified value because
+ <span><strong class="command">named</strong></span> reserves some file descriptors
+ for its internal use.
+ </p>
+</div>
+</dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+<p>Chroot
+ to <em class="replaceable"><code>directory</code></em> after
+ processing the command line arguments, but before
+ reading the configuration file.
+ </p>
+<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+<p>
+ This option should be used in conjunction with the
+ <code class="option">-u</code> option, as chrooting a process
+ running as root doesn't enhance security on most
+ systems; the way <code class="function">chroot(2)</code> is
+ defined allows a process with root privileges to
+ escape a chroot jail.
+ </p>
+</div>
+</dd>
+<dt><span class="term">-u <em class="replaceable"><code>user</code></em></span></dt>
+<dd>
+<p>Setuid
+ to <em class="replaceable"><code>user</code></em> after completing
+ privileged operations, such as creating sockets that
+ listen on privileged ports.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ On Linux, <span><strong class="command">named</strong></span> uses the kernel's
+ capability mechanism to drop all root privileges
+ except the ability to <code class="function">bind(2)</code> to
+ a
+ privileged port and set process resource limits.
+ Unfortunately, this means that the <code class="option">-u</code>
+ option only works when <span><strong class="command">named</strong></span> is
+ run
+ on kernel 2.2.18 or later, or kernel 2.3.99-pre3 or
+ later, since previous kernels did not allow privileges
+ to be retained after <code class="function">setuid(2)</code>.
+ </p>
+</div>
+</dd>
+<dt><span class="term">-v</span></dt>
+<dd><p>
+ Report the version number and exit.
+ </p></dd>
+<dt><span class="term">-V</span></dt>
+<dd><p>
+ Report the version number and build options, and exit.
+ </p></dd>
+<dt><span class="term">-x <em class="replaceable"><code>cache-file</code></em></span></dt>
+<dd>
+<p>
+ Load data from <em class="replaceable"><code>cache-file</code></em> into the
+ cache of the default view.
+ </p>
+<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+<p>
+ This option must not be used. It is only of interest
+ to BIND 9 developers and may be removed or changed in a
+ future release.
+ </p>
+</div>
+</dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543928"></a><h2>SIGNALS</h2>
+<p>
+ In routine operation, signals should not be used to control
+ the nameserver; <span><strong class="command">rndc</strong></span> should be used
+ instead.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term">SIGHUP</span></dt>
+<dd><p>
+ Force a reload of the server.
+ </p></dd>
+<dt><span class="term">SIGINT, SIGTERM</span></dt>
+<dd><p>
+ Shut down the server.
+ </p></dd>
+</dl></div>
+<p>
+ The result of sending any other signals to the server is undefined.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543976"></a><h2>CONFIGURATION</h2>
+<p>
+ The <span><strong class="command">named</strong></span> configuration file is too complex
+ to describe in detail here. A complete description is provided
+ in the
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543993"></a><h2>FILES</h2>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="filename">/etc/named.conf</code></span></dt>
+<dd><p>
+ The default configuration file.
+ </p></dd>
+<dt><span class="term"><code class="filename">/var/run/named/named.pid</code></span></dt>
+<dd><p>
+ The default process-id file.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544033"></a><h2>SEE ALSO</h2>
+<p><em class="citetitle">RFC 1033</em>,
+ <em class="citetitle">RFC 1034</em>,
+ <em class="citetitle">RFC 1035</em>,
+ <span class="citerefentry"><span class="refentrytitle">named-checkconf</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named-checkzone</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">lwresd</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named.conf</span>(5)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544171"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/named/notify.c b/bin/named/notify.c
new file mode 100644
index 0000000..de52b8c
--- /dev/null
+++ b/bin/named/notify.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: notify.c,v 1.37 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/log.h>
+#include <isc/print.h>
+
+#include <dns/message.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#include <named/log.h>
+#include <named/notify.h>
+
+/*! \file
+ * \brief
+ * This module implements notify as in RFC1996.
+ */
+
+static void
+notify_log(ns_client_t *client, int level, const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ ns_client_logv(client, DNS_LOGCATEGORY_NOTIFY, NS_LOGMODULE_NOTIFY,
+ level, fmt, ap);
+ va_end(ap);
+}
+
+static void
+respond(ns_client_t *client, isc_result_t result) {
+ dns_rcode_t rcode;
+ dns_message_t *message;
+ isc_result_t msg_result;
+
+ message = client->message;
+ rcode = dns_result_torcode(result);
+
+ msg_result = dns_message_reply(message, ISC_TRUE);
+ if (msg_result != ISC_R_SUCCESS)
+ msg_result = dns_message_reply(message, ISC_FALSE);
+ if (msg_result != ISC_R_SUCCESS) {
+ ns_client_next(client, msg_result);
+ return;
+ }
+ message->rcode = rcode;
+ if (rcode == dns_rcode_noerror)
+ message->flags |= DNS_MESSAGEFLAG_AA;
+ else
+ message->flags &= ~DNS_MESSAGEFLAG_AA;
+ ns_client_send(client);
+}
+
+void
+ns_notify_start(ns_client_t *client) {
+ dns_message_t *request = client->message;
+ isc_result_t result;
+ dns_name_t *zonename;
+ dns_rdataset_t *zone_rdataset;
+ dns_zone_t *zone = NULL;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char tsigbuf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
+ dns_tsigkey_t *tsigkey;
+
+ /*
+ * Interpret the question section.
+ */
+ result = dns_message_firstname(request, DNS_SECTION_QUESTION);
+ if (result != ISC_R_SUCCESS) {
+ notify_log(client, ISC_LOG_NOTICE,
+ "notify question section empty");
+ goto formerr;
+ }
+
+ /*
+ * The question section must contain exactly one question.
+ */
+ zonename = NULL;
+ dns_message_currentname(request, DNS_SECTION_QUESTION, &zonename);
+ zone_rdataset = ISC_LIST_HEAD(zonename->list);
+ if (ISC_LIST_NEXT(zone_rdataset, link) != NULL) {
+ notify_log(client, ISC_LOG_NOTICE,
+ "notify question section contains multiple RRs");
+ goto formerr;
+ }
+
+ /* The zone section must have exactly one name. */
+ result = dns_message_nextname(request, DNS_SECTION_ZONE);
+ if (result != ISC_R_NOMORE) {
+ notify_log(client, ISC_LOG_NOTICE,
+ "notify question section contains multiple RRs");
+ goto formerr;
+ }
+
+ /* The one rdataset must be an SOA. */
+ if (zone_rdataset->type != dns_rdatatype_soa) {
+ notify_log(client, ISC_LOG_NOTICE,
+ "notify question section contains no SOA");
+ goto formerr;
+ }
+
+ tsigkey = dns_message_gettsigkey(request);
+ if (tsigkey != NULL) {
+ dns_name_format(&tsigkey->name, namebuf, sizeof(namebuf));
+
+ if (tsigkey->generated) {
+ char cnamebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(tsigkey->creator, cnamebuf,
+ sizeof(cnamebuf));
+ snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s' (%s)",
+ namebuf, cnamebuf);
+ } else {
+ snprintf(tsigbuf, sizeof(tsigbuf), ": TSIG '%s'",
+ namebuf);
+ }
+ } else
+ tsigbuf[0] = '\0';
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ result = dns_zt_find(client->view->zonetable, zonename, 0, NULL,
+ &zone);
+ if (result != ISC_R_SUCCESS)
+ goto notauth;
+
+ switch (dns_zone_gettype(zone)) {
+ case dns_zone_master:
+ case dns_zone_slave:
+ case dns_zone_stub: /* Allow dialup passive to work. */
+ notify_log(client, ISC_LOG_INFO,
+ "received notify for zone '%s'%s", namebuf, tsigbuf);
+ respond(client, dns_zone_notifyreceive(zone,
+ ns_client_getsockaddr(client), request));
+ break;
+ default:
+ goto notauth;
+ }
+ dns_zone_detach(&zone);
+ return;
+
+ notauth:
+ notify_log(client, ISC_LOG_NOTICE,
+ "received notify for zone '%s'%s: not authoritative",
+ namebuf, tsigbuf);
+ result = DNS_R_NOTAUTH;
+ goto failure;
+
+ formerr:
+ result = DNS_R_FORMERR;
+
+ failure:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ respond(client, result);
+}
diff --git a/bin/named/query.c b/bin/named/query.c
new file mode 100644
index 0000000..cacd70a
--- /dev/null
+++ b/bin/named/query.c
@@ -0,0 +1,5096 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: query.c,v 1.313 2008/11/03 23:57:22 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/mem.h>
+#include <isc/util.h>
+#include <isc/hex.h>
+
+#include <dns/adb.h>
+#include <dns/byaddr.h>
+#include <dns/db.h>
+#ifdef DLZ
+#include <dns/dlz.h>
+#endif
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/message.h>
+#include <dns/ncache.h>
+#include <dns/nsec3.h>
+#include <dns/order.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/stats.h>
+#include <dns/tkey.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#include <named/client.h>
+#include <named/log.h>
+#include <named/server.h>
+#include <named/sortlist.h>
+#include <named/xfrout.h>
+
+/*% Partial answer? */
+#define PARTIALANSWER(c) (((c)->query.attributes & \
+ NS_QUERYATTR_PARTIALANSWER) != 0)
+/*% Use Cache? */
+#define USECACHE(c) (((c)->query.attributes & \
+ NS_QUERYATTR_CACHEOK) != 0)
+/*% Recursion OK? */
+#define RECURSIONOK(c) (((c)->query.attributes & \
+ NS_QUERYATTR_RECURSIONOK) != 0)
+/*% Recursing? */
+#define RECURSING(c) (((c)->query.attributes & \
+ NS_QUERYATTR_RECURSING) != 0)
+/*% Cache glue ok? */
+#define CACHEGLUEOK(c) (((c)->query.attributes & \
+ NS_QUERYATTR_CACHEGLUEOK) != 0)
+/*% Want Recursion? */
+#define WANTRECURSION(c) (((c)->query.attributes & \
+ NS_QUERYATTR_WANTRECURSION) != 0)
+/*% Want DNSSEC? */
+#define WANTDNSSEC(c) (((c)->attributes & \
+ NS_CLIENTATTR_WANTDNSSEC) != 0)
+/*% No authority? */
+#define NOAUTHORITY(c) (((c)->query.attributes & \
+ NS_QUERYATTR_NOAUTHORITY) != 0)
+/*% No additional? */
+#define NOADDITIONAL(c) (((c)->query.attributes & \
+ NS_QUERYATTR_NOADDITIONAL) != 0)
+/*% Secure? */
+#define SECURE(c) (((c)->query.attributes & \
+ NS_QUERYATTR_SECURE) != 0)
+
+/*% No QNAME Proof? */
+#define NOQNAME(r) (((r)->attributes & \
+ DNS_RDATASETATTR_NOQNAME) != 0)
+
+#if 0
+#define CTRACE(m) isc_log_write(ns_g_lctx, \
+ NS_LOGCATEGORY_CLIENT, \
+ NS_LOGMODULE_QUERY, \
+ ISC_LOG_DEBUG(3), \
+ "client %p: %s", client, (m))
+#define QTRACE(m) isc_log_write(ns_g_lctx, \
+ NS_LOGCATEGORY_GENERAL, \
+ NS_LOGMODULE_QUERY, \
+ ISC_LOG_DEBUG(3), \
+ "query %p: %s", query, (m))
+#else
+#define CTRACE(m) ((void)m)
+#define QTRACE(m) ((void)m)
+#endif
+
+#define DNS_GETDB_NOEXACT 0x01U
+#define DNS_GETDB_NOLOG 0x02U
+#define DNS_GETDB_PARTIAL 0x04U
+
+typedef struct client_additionalctx {
+ ns_client_t *client;
+ dns_rdataset_t *rdataset;
+} client_additionalctx_t;
+
+static void
+query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype);
+
+static isc_boolean_t
+validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
+
+static void
+query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
+ dns_dbversion_t *version, ns_client_t *client,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_name_t *fname, isc_boolean_t exact,
+ dns_name_t *found);
+
+/*%
+ * Increment query statistics counters.
+ */
+static inline void
+inc_stats(ns_client_t *client, dns_statscounter_t counter) {
+ dns_zone_t *zone = client->query.authzone;
+
+ dns_generalstats_increment(ns_g_server->nsstats, counter);
+
+ if (zone != NULL) {
+ dns_stats_t *zonestats = dns_zone_getrequeststats(zone);
+ if (zonestats != NULL)
+ dns_generalstats_increment(zonestats, counter);
+ }
+}
+
+static void
+query_send(ns_client_t *client) {
+ dns_statscounter_t counter;
+ if ((client->message->flags & DNS_MESSAGEFLAG_AA) == 0)
+ inc_stats(client, dns_nsstatscounter_nonauthans);
+ else
+ inc_stats(client, dns_nsstatscounter_authans);
+ if (client->message->rcode == dns_rcode_noerror) {
+ if (ISC_LIST_EMPTY(client->message->sections[DNS_SECTION_ANSWER])) {
+ if (client->query.isreferral) {
+ counter = dns_nsstatscounter_referral;
+ } else {
+ counter = dns_nsstatscounter_nxrrset;
+ }
+ } else {
+ counter = dns_nsstatscounter_success;
+ }
+ } else if (client->message->rcode == dns_rcode_nxdomain) {
+ counter = dns_nsstatscounter_nxdomain;
+ } else {
+ /* We end up here in case of YXDOMAIN, and maybe others */
+ counter = dns_nsstatscounter_failure;
+ }
+ inc_stats(client, counter);
+ ns_client_send(client);
+}
+
+static void
+query_error(ns_client_t *client, isc_result_t result) {
+ switch (result) {
+ case DNS_R_SERVFAIL:
+ inc_stats(client, dns_nsstatscounter_servfail);
+ break;
+ case DNS_R_FORMERR:
+ inc_stats(client, dns_nsstatscounter_formerr);
+ break;
+ default:
+ inc_stats(client, dns_nsstatscounter_failure);
+ break;
+ }
+ ns_client_error(client, result);
+}
+
+static void
+query_next(ns_client_t *client, isc_result_t result) {
+ if (result == DNS_R_DUPLICATE)
+ inc_stats(client, dns_nsstatscounter_duplicate);
+ else if (result == DNS_R_DROP)
+ inc_stats(client, dns_nsstatscounter_dropped);
+ else
+ inc_stats(client, dns_nsstatscounter_failure);
+ ns_client_next(client, result);
+}
+
+static inline void
+query_freefreeversions(ns_client_t *client, isc_boolean_t everything) {
+ ns_dbversion_t *dbversion, *dbversion_next;
+ unsigned int i;
+
+ for (dbversion = ISC_LIST_HEAD(client->query.freeversions), i = 0;
+ dbversion != NULL;
+ dbversion = dbversion_next, i++)
+ {
+ dbversion_next = ISC_LIST_NEXT(dbversion, link);
+ /*
+ * If we're not freeing everything, we keep the first three
+ * dbversions structures around.
+ */
+ if (i > 3 || everything) {
+ ISC_LIST_UNLINK(client->query.freeversions, dbversion,
+ link);
+ isc_mem_put(client->mctx, dbversion,
+ sizeof(*dbversion));
+ }
+ }
+}
+
+void
+ns_query_cancel(ns_client_t *client) {
+ LOCK(&client->query.fetchlock);
+ if (client->query.fetch != NULL) {
+ dns_resolver_cancelfetch(client->query.fetch);
+
+ client->query.fetch = NULL;
+ }
+ UNLOCK(&client->query.fetchlock);
+}
+
+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;
+
+ /*%
+ * Reset the query state of a client to its default state.
+ */
+
+ /*
+ * Cancel the fetch if it's running.
+ */
+ ns_query_cancel(client);
+
+ /*
+ * Cleanup any active versions.
+ */
+ for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
+ dbversion != NULL;
+ dbversion = dbversion_next) {
+ dbversion_next = ISC_LIST_NEXT(dbversion, link);
+ dns_db_closeversion(dbversion->db, &dbversion->version,
+ ISC_FALSE);
+ dns_db_detach(&dbversion->db);
+ ISC_LIST_INITANDAPPEND(client->query.freeversions,
+ dbversion, link);
+ }
+ ISC_LIST_INIT(client->query.activeversions);
+
+ if (client->query.authdb != NULL)
+ dns_db_detach(&client->query.authdb);
+ if (client->query.authzone != NULL)
+ dns_zone_detach(&client->query.authzone);
+
+ query_freefreeversions(client, everything);
+
+ for (dbuf = ISC_LIST_HEAD(client->query.namebufs);
+ dbuf != NULL;
+ dbuf = dbuf_next) {
+ dbuf_next = ISC_LIST_NEXT(dbuf, link);
+ if (dbuf_next != NULL || everything) {
+ ISC_LIST_UNLINK(client->query.namebufs, dbuf, link);
+ isc_buffer_free(&dbuf);
+ }
+ }
+
+ if (client->query.restarts > 0) {
+ /*
+ * client->query.qname was dynamically allocated.
+ */
+ dns_message_puttempname(client->message,
+ &client->query.qname);
+ }
+ client->query.qname = NULL;
+ client->query.attributes = (NS_QUERYATTR_RECURSIONOK |
+ NS_QUERYATTR_CACHEOK |
+ NS_QUERYATTR_SECURE);
+ client->query.restarts = 0;
+ client->query.timerset = ISC_FALSE;
+ 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;
+}
+
+static void
+query_next_callback(ns_client_t *client) {
+ query_reset(client, ISC_FALSE);
+}
+
+void
+ns_query_free(ns_client_t *client) {
+ query_reset(client, ISC_TRUE);
+}
+
+static inline isc_result_t
+query_newnamebuf(ns_client_t *client) {
+ isc_buffer_t *dbuf;
+ isc_result_t result;
+
+ CTRACE("query_newnamebuf");
+ /*%
+ * Allocate a name buffer.
+ */
+
+ dbuf = NULL;
+ result = isc_buffer_allocate(client->mctx, &dbuf, 1024);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE("query_newnamebuf: isc_buffer_allocate failed: done");
+ return (result);
+ }
+ ISC_LIST_APPEND(client->query.namebufs, dbuf, link);
+
+ CTRACE("query_newnamebuf: done");
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_buffer_t *
+query_getnamebuf(ns_client_t *client) {
+ isc_buffer_t *dbuf;
+ isc_result_t result;
+ isc_region_t r;
+
+ CTRACE("query_getnamebuf");
+ /*%
+ * Return a name buffer with space for a maximal name, allocating
+ * a new one if necessary.
+ */
+
+ if (ISC_LIST_EMPTY(client->query.namebufs)) {
+ result = query_newnamebuf(client);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE("query_getnamebuf: query_newnamebuf failed: done");
+ return (NULL);
+ }
+ }
+
+ dbuf = ISC_LIST_TAIL(client->query.namebufs);
+ INSIST(dbuf != NULL);
+ isc_buffer_availableregion(dbuf, &r);
+ if (r.length < 255) {
+ result = query_newnamebuf(client);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE("query_getnamebuf: query_newnamebuf failed: done");
+ return (NULL);
+
+ }
+ dbuf = ISC_LIST_TAIL(client->query.namebufs);
+ isc_buffer_availableregion(dbuf, &r);
+ INSIST(r.length >= 255);
+ }
+ CTRACE("query_getnamebuf: done");
+ return (dbuf);
+}
+
+static inline void
+query_keepname(ns_client_t *client, dns_name_t *name, isc_buffer_t *dbuf) {
+ isc_region_t r;
+
+ CTRACE("query_keepname");
+ /*%
+ * 'name' is using space in 'dbuf', but 'dbuf' has not yet been
+ * adjusted to take account of that. We do the adjustment.
+ */
+
+ REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) != 0);
+
+ dns_name_toregion(name, &r);
+ isc_buffer_add(dbuf, r.length);
+ dns_name_setbuffer(name, NULL);
+ client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
+}
+
+static inline void
+query_releasename(ns_client_t *client, dns_name_t **namep) {
+ dns_name_t *name = *namep;
+
+ /*%
+ * 'name' is no longer needed. Return it to our pool of temporary
+ * names. If it is using a name buffer, relinquish its exclusive
+ * rights on the buffer.
+ */
+
+ CTRACE("query_releasename");
+ if (dns_name_hasbuffer(name)) {
+ INSIST((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED)
+ != 0);
+ client->query.attributes &= ~NS_QUERYATTR_NAMEBUFUSED;
+ }
+ dns_message_puttempname(client->message, namep);
+ CTRACE("query_releasename: done");
+}
+
+static inline dns_name_t *
+query_newname(ns_client_t *client, isc_buffer_t *dbuf,
+ isc_buffer_t *nbuf)
+{
+ dns_name_t *name;
+ isc_region_t r;
+ isc_result_t result;
+
+ REQUIRE((client->query.attributes & NS_QUERYATTR_NAMEBUFUSED) == 0);
+
+ CTRACE("query_newname");
+ name = NULL;
+ result = dns_message_gettempname(client->message, &name);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE("query_newname: dns_message_gettempname failed: done");
+ return (NULL);
+ }
+ isc_buffer_availableregion(dbuf, &r);
+ isc_buffer_init(nbuf, r.base, r.length);
+ dns_name_init(name, NULL);
+ dns_name_setbuffer(name, nbuf);
+ client->query.attributes |= NS_QUERYATTR_NAMEBUFUSED;
+
+ CTRACE("query_newname: done");
+ return (name);
+}
+
+static inline dns_rdataset_t *
+query_newrdataset(ns_client_t *client) {
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+
+ CTRACE("query_newrdataset");
+ rdataset = NULL;
+ result = dns_message_gettemprdataset(client->message, &rdataset);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE("query_newrdataset: "
+ "dns_message_gettemprdataset failed: done");
+ return (NULL);
+ }
+ dns_rdataset_init(rdataset);
+
+ CTRACE("query_newrdataset: done");
+ 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;
+ ns_dbversion_t *dbversion;
+
+ for (i = 0; i < n; i++) {
+ dbversion = isc_mem_get(client->mctx, sizeof(*dbversion));
+ if (dbversion != NULL) {
+ dbversion->db = NULL;
+ dbversion->version = NULL;
+ ISC_LIST_INITANDAPPEND(client->query.freeversions,
+ dbversion, link);
+ } else {
+ /*
+ * We only return ISC_R_NOMEMORY if we couldn't
+ * allocate anything.
+ */
+ if (i == 0)
+ return (ISC_R_NOMEMORY);
+ else
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline ns_dbversion_t *
+query_getdbversion(ns_client_t *client) {
+ isc_result_t result;
+ ns_dbversion_t *dbversion;
+
+ if (ISC_LIST_EMPTY(client->query.freeversions)) {
+ result = query_newdbversion(client, 1);
+ if (result != ISC_R_SUCCESS)
+ return (NULL);
+ }
+ dbversion = ISC_LIST_HEAD(client->query.freeversions);
+ INSIST(dbversion != NULL);
+ ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);
+
+ return (dbversion);
+}
+
+isc_result_t
+ns_query_init(ns_client_t *client) {
+ isc_result_t result;
+
+ ISC_LIST_INIT(client->query.namebufs);
+ ISC_LIST_INIT(client->query.activeversions);
+ ISC_LIST_INIT(client->query.freeversions);
+ client->query.restarts = 0;
+ client->query.timerset = ISC_FALSE;
+ client->query.qname = NULL;
+ result = isc_mutex_init(&client->query.fetchlock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ client->query.fetch = NULL;
+ client->query.authdb = NULL;
+ client->query.authzone = NULL;
+ client->query.authdbset = ISC_FALSE;
+ client->query.isreferral = ISC_FALSE;
+ query_reset(client, ISC_FALSE);
+ result = query_newdbversion(client, 3);
+ if (result != ISC_R_SUCCESS) {
+ DESTROYLOCK(&client->query.fetchlock);
+ return (result);
+ }
+ result = query_newnamebuf(client);
+ if (result != ISC_R_SUCCESS)
+ query_freefreeversions(client, ISC_TRUE);
+
+ return (result);
+}
+
+static inline ns_dbversion_t *
+query_findversion(ns_client_t *client, dns_db_t *db,
+ isc_boolean_t *newzonep)
+{
+ ns_dbversion_t *dbversion;
+
+ /*%
+ * We may already have done a query related to this
+ * database. If so, we must be sure to make subsequent
+ * queries from the same version.
+ */
+ for (dbversion = ISC_LIST_HEAD(client->query.activeversions);
+ dbversion != NULL;
+ dbversion = ISC_LIST_NEXT(dbversion, link)) {
+ if (dbversion->db == db)
+ break;
+ }
+
+ if (dbversion == NULL) {
+ /*
+ * This is a new zone for this query. Add it to
+ * the active list.
+ */
+ dbversion = query_getdbversion(client);
+ if (dbversion == NULL)
+ return (NULL);
+ dns_db_attach(db, &dbversion->db);
+ dns_db_currentversion(db, &dbversion->version);
+ dbversion->queryok = ISC_FALSE;
+ ISC_LIST_APPEND(client->query.activeversions,
+ dbversion, link);
+ *newzonep = ISC_TRUE;
+ } else
+ *newzonep = ISC_FALSE;
+
+ return (dbversion);
+}
+
+static inline isc_result_t
+query_validatezonedb(ns_client_t *client, dns_name_t *name,
+ dns_rdatatype_t qtype, unsigned int options,
+ dns_zone_t *zone, dns_db_t *db,
+ dns_dbversion_t **versionp)
+{
+ isc_result_t result;
+ isc_boolean_t check_acl, new_zone;
+ dns_acl_t *queryacl;
+ ns_dbversion_t *dbversion;
+
+ REQUIRE(zone != NULL);
+ REQUIRE(db != NULL);
+
+ /*
+ * This limits our searching to the zone where the first name
+ * (the query target) was looked for. This prevents following
+ * CNAMES or DNAMES into other zones and prevents returning
+ * additional data from other zones.
+ */
+ if (!client->view->additionalfromauth &&
+ client->query.authdbset &&
+ db != client->query.authdb)
+ goto refuse;
+
+ /*
+ * If the zone has an ACL, we'll check it, otherwise
+ * we use the view's "allow-query" ACL. Each ACL is only checked
+ * once per query.
+ *
+ * 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;
+ }
+
+ queryacl = dns_zone_getqueryacl(zone);
+ if (queryacl == NULL) {
+ queryacl = client->view->queryacl;
+ if ((client->query.attributes &
+ NS_QUERYATTR_QUERYOKVALID) != 0) {
+ /*
+ * We've evaluated the view's queryacl already. If
+ * NS_QUERYATTR_QUERYOK is set, then the client is
+ * allowed to make queries, otherwise the query should
+ * be refused.
+ */
+ check_acl = ISC_FALSE;
+ if ((client->query.attributes &
+ NS_QUERYATTR_QUERYOK) == 0)
+ goto refuse;
+ } else {
+ /*
+ * We haven't evaluated the view's queryacl yet.
+ */
+ check_acl = ISC_TRUE;
+ }
+ }
+
+ 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 {
+ 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;
+ }
+ /*
+ * We've now evaluated the view's query ACL, and
+ * the NS_QUERYATTR_QUERYOK attribute is now valid.
+ */
+ client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
+ }
+
+ if (result != ISC_R_SUCCESS)
+ goto refuse;
+ }
+
+ /* Approved. */
+
+ /*
+ * Remember the result of the ACL check so we
+ * don't have to check again.
+ */
+ dbversion->queryok = ISC_TRUE;
+
+ /* 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
+query_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
+ unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
+ dns_dbversion_t **versionp)
+{
+ isc_result_t result;
+ unsigned int ztoptions;
+ dns_zone_t *zone = NULL;
+ dns_db_t *db = NULL;
+ isc_boolean_t partial = ISC_FALSE;
+
+ REQUIRE(zonep != NULL && *zonep == NULL);
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ /*%
+ * Find a zone database to answer the query.
+ */
+ ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ?
+ DNS_ZTFIND_NOEXACT : 0;
+
+ result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,
+ &zone);
+ if (result == DNS_R_PARTIALMATCH)
+ partial = ISC_TRUE;
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+ result = dns_zone_getdb(zone, &db);
+
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ result = query_validatezonedb(client, name, qtype, options, zone, db,
+ versionp);
+
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ /* Transfer ownership. */
+ *zonep = zone;
+ *dbp = db;
+
+ if (partial && (options & DNS_GETDB_PARTIAL) != 0)
+ return (DNS_R_PARTIALMATCH);
+ return (ISC_R_SUCCESS);
+
+ fail:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ if (db != NULL)
+ dns_db_detach(&db);
+
+ 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)
+{
+ isc_result_t result;
+ isc_boolean_t check_acl;
+ dns_db_t *db = NULL;
+
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ /*%
+ * Find a cache database to answer the query.
+ * This may fail with DNS_R_REFUSED if the client
+ * is not allowed to use the cache.
+ */
+
+ if (!USECACHE(client))
+ return (DNS_R_REFUSED);
+ dns_db_attach(client->view->cachedb, &db);
+
+ if ((client->query.attributes &
+ NS_QUERYATTR_QUERYOKVALID) != 0) {
+ /*
+ * We've evaluated the view's queryacl already. If
+ * NS_QUERYATTR_QUERYOK is set, then the client is
+ * allowed to make queries, otherwise the query should
+ * be refused.
+ */
+ check_acl = ISC_FALSE;
+ if ((client->query.attributes &
+ NS_QUERYATTR_QUERYOK) == 0)
+ goto refuse;
+ } else {
+ /*
+ * We haven't evaluated the view's queryacl yet.
+ */
+ check_acl = ISC_TRUE;
+ }
+
+ if (check_acl) {
+ isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);
+ char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];
+
+ result = ns_client_checkaclsilent(client, NULL,
+ client->view->queryacl,
+ ISC_TRUE);
+ 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 (log && isc_log_wouldlog(ns_g_lctx,
+ ISC_LOG_DEBUG(3)))
+ {
+ ns_client_aclmsg("query (cache)", 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 if (log) {
+ ns_client_aclmsg("query (cache)", name, qtype,
+ client->view->rdclass, msg,
+ sizeof(msg));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY, ISC_LOG_INFO,
+ "%s denied", msg);
+ }
+ /*
+ * We've now evaluated the view's query ACL, and
+ * the NS_QUERYATTR_QUERYOK attribute is now valid.
+ */
+ client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;
+
+ if (result != ISC_R_SUCCESS)
+ goto refuse;
+ }
+
+ /* Approved. */
+
+ /* Transfer ownership. */
+ *dbp = db;
+
+ return (ISC_R_SUCCESS);
+
+ refuse:
+ result = DNS_R_REFUSED;
+
+ if (db != NULL)
+ dns_db_detach(&db);
+
+ return (result);
+}
+
+
+static inline isc_result_t
+query_getdb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,
+ unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,
+ dns_dbversion_t **versionp, isc_boolean_t *is_zonep)
+{
+ isc_result_t result;
+
+#ifdef DLZ
+ isc_result_t tresult;
+ unsigned int namelabels;
+ unsigned int zonelabels;
+ dns_zone_t *zone = NULL;
+ dns_db_t *tdbp;
+
+ REQUIRE(zonep != NULL && *zonep == NULL);
+
+ tdbp = NULL;
+
+ /* Calculate how many labels are in name. */
+ namelabels = dns_name_countlabels(name);
+ zonelabels = 0;
+
+ /* Try to find name in bind's standard database. */
+ result = query_getzonedb(client, name, qtype, options, &zone,
+ dbp, versionp);
+
+ /* See how many labels are in the zone's name. */
+ if (result == ISC_R_SUCCESS && zone != NULL)
+ zonelabels = dns_name_countlabels(dns_zone_getorigin(zone));
+ /*
+ * If # zone labels < # name labels, try to find an even better match
+ * Only try if a DLZ driver is loaded for this view
+ */
+ if (zonelabels < namelabels && client->view->dlzdatabase != NULL) {
+ tresult = dns_dlzfindzone(client->view, name,
+ zonelabels, &tdbp);
+ /* If we successful, we found a better match. */
+ if (tresult == ISC_R_SUCCESS) {
+ /*
+ * If the previous search returned a zone, detach it.
+ */
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ /*
+ * If the previous search returned a database,
+ * detach it.
+ */
+ if (*dbp != NULL)
+ dns_db_detach(dbp);
+
+ /*
+ * If the previous search returned a version, clear it.
+ */
+ *versionp = NULL;
+
+ /*
+ * Get our database version.
+ */
+ dns_db_currentversion(tdbp, versionp);
+
+ /*
+ * Be sure to return our database.
+ */
+ *dbp = tdbp;
+
+ /*
+ * We return a null zone, No stats for DLZ zones.
+ */
+ zone = NULL;
+ result = tresult;
+ }
+ }
+#else
+ result = query_getzonedb(client, name, qtype, options,
+ zonep, dbp, versionp);
+#endif
+
+ /* If successfull, Transfer ownership of zone. */
+ if (result == ISC_R_SUCCESS) {
+#ifdef DLZ
+ *zonep = zone;
+#endif
+ /*
+ * If neither attempt above succeeded, return the cache instead
+ */
+ *is_zonep = ISC_TRUE;
+ } else if (result == ISC_R_NOTFOUND) {
+ result = query_getcachedb(client, name, qtype, dbp, options);
+ *is_zonep = ISC_FALSE;
+ }
+ return (result);
+}
+
+static inline isc_boolean_t
+query_isduplicate(ns_client_t *client, dns_name_t *name,
+ dns_rdatatype_t type, dns_name_t **mnamep)
+{
+ dns_section_t section;
+ dns_name_t *mname = NULL;
+ isc_result_t result;
+
+ CTRACE("query_isduplicate");
+
+ for (section = DNS_SECTION_ANSWER;
+ section <= DNS_SECTION_ADDITIONAL;
+ section++) {
+ result = dns_message_findname(client->message, section,
+ name, type, 0, &mname, NULL);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We've already got this RRset in the response.
+ */
+ CTRACE("query_isduplicate: true: done");
+ return (ISC_TRUE);
+ } else if (result == DNS_R_NXRRSET) {
+ /*
+ * The name exists, but the rdataset does not.
+ */
+ if (section == DNS_SECTION_ADDITIONAL)
+ break;
+ } else
+ RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
+ mname = NULL;
+ }
+
+ /*
+ * If the dns_name_t we're looking up is already in the message,
+ * we don't want to trigger the caller's name replacement logic.
+ */
+ if (name == mname)
+ mname = NULL;
+
+ *mnamep = mname;
+
+ CTRACE("query_isduplicate: false: done");
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
+ ns_client_t *client = arg;
+ isc_result_t result, eresult;
+ dns_dbnode_t *node;
+ dns_db_t *db;
+ dns_name_t *fname, *mname;
+ dns_rdataset_t *rdataset, *sigrdataset, *trdataset;
+ isc_buffer_t *dbuf;
+ isc_buffer_t b;
+ dns_dbversion_t *version;
+ isc_boolean_t added_something, need_addname;
+ dns_zone_t *zone;
+ dns_rdatatype_t type;
+
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(qtype != dns_rdatatype_any);
+
+ if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype))
+ return (ISC_R_SUCCESS);
+
+ CTRACE("query_addadditional");
+
+ /*
+ * Initialization.
+ */
+ eresult = ISC_R_SUCCESS;
+ fname = NULL;
+ rdataset = NULL;
+ sigrdataset = NULL;
+ trdataset = NULL;
+ db = NULL;
+ version = NULL;
+ node = NULL;
+ added_something = ISC_FALSE;
+ need_addname = ISC_FALSE;
+ zone = NULL;
+
+ /*
+ * We treat type A additional section processing as if it
+ * were "any address type" additional section processing.
+ * To avoid multiple lookups, we do an 'any' database
+ * lookup and iterate over the node.
+ */
+ if (qtype == dns_rdatatype_a)
+ type = dns_rdatatype_any;
+ else
+ type = qtype;
+
+ /*
+ * Get some resources.
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ rdataset = query_newrdataset(client);
+ if (fname == NULL || rdataset == NULL)
+ goto cleanup;
+ if (WANTDNSSEC(client)) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL)
+ goto cleanup;
+ }
+
+ /*
+ * Look for a zone database that might contain authoritative
+ * additional data.
+ */
+ result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
+ &zone, &db, &version);
+ if (result != ISC_R_SUCCESS)
+ goto try_cache;
+
+ CTRACE("query_addadditional: db_find");
+
+ /*
+ * Since we are looking for authoritative data, we do not set
+ * the GLUEOK flag. Glue will be looked for later, but not
+ * necessarily in the same database.
+ */
+ node = NULL;
+ result = dns_db_find(db, name, version, type, client->query.dboptions,
+ client->now, &node, fname, rdataset,
+ sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ if (sigrdataset != NULL && !dns_db_issecure(db) &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ goto found;
+ }
+
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ version = NULL;
+ dns_db_detach(&db);
+
+ /*
+ * No authoritative data was found. The cache is our next best bet.
+ */
+
+ try_cache:
+ result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
+ if (result != ISC_R_SUCCESS)
+ /*
+ * Most likely the client isn't allowed to query the cache.
+ */
+ goto try_glue;
+ /*
+ * Attempt to validate glue.
+ */
+ if (sigrdataset == NULL) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL)
+ goto cleanup;
+ }
+ result = dns_db_find(db, name, version, type,
+ client->query.dboptions | DNS_DBFIND_GLUEOK,
+ client->now, &node, fname, rdataset,
+ sigrdataset);
+ if (result == DNS_R_GLUE &&
+ validate(client, db, fname, rdataset, sigrdataset))
+ result = ISC_R_SUCCESS;
+ if (!WANTDNSSEC(client))
+ query_putrdataset(client, &sigrdataset);
+ if (result == ISC_R_SUCCESS)
+ goto found;
+
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+
+ try_glue:
+ /*
+ * No cached data was found. Glue is our last chance.
+ * RFC1035 sayeth:
+ *
+ * NS records cause both the usual additional section
+ * processing to locate a type A record, and, when used
+ * in a referral, a special search of the zone in which
+ * they reside for glue information.
+ *
+ * This is the "special search". Note that we must search
+ * the zone where the NS record resides, not the zone it
+ * points to, and that we only do the search in the delegation
+ * case (identified by client->query.gluedb being set).
+ */
+
+ if (client->query.gluedb == NULL)
+ goto cleanup;
+
+ /*
+ * Don't poision caches using the bailiwick protection model.
+ */
+ if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
+ goto cleanup;
+
+ dns_db_attach(client->query.gluedb, &db);
+ result = dns_db_find(db, name, version, type,
+ client->query.dboptions | DNS_DBFIND_GLUEOK,
+ client->now, &node, fname, rdataset,
+ sigrdataset);
+ if (!(result == ISC_R_SUCCESS ||
+ result == DNS_R_ZONECUT ||
+ result == DNS_R_GLUE))
+ goto cleanup;
+
+ found:
+ /*
+ * We have found a potential additional data rdataset, or
+ * at least a node to iterate over.
+ */
+ query_keepname(client, fname, dbuf);
+
+ /*
+ * If we have an rdataset, add it to the additional data
+ * section.
+ */
+ mname = NULL;
+ if (dns_rdataset_isassociated(rdataset) &&
+ !query_isduplicate(client, fname, type, &mname)) {
+ if (mname != NULL) {
+ query_releasename(client, &fname);
+ fname = mname;
+ } else
+ need_addname = ISC_TRUE;
+ ISC_LIST_APPEND(fname->list, rdataset, link);
+ trdataset = rdataset;
+ rdataset = NULL;
+ added_something = ISC_TRUE;
+ /*
+ * 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.
+ */
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ {
+ ISC_LIST_APPEND(fname->list, sigrdataset, link);
+ sigrdataset = NULL;
+ }
+ }
+
+ if (qtype == dns_rdatatype_a) {
+ /*
+ * We now go looking for A and AAAA records, along with
+ * their signatures.
+ *
+ * XXXRTH This code could be more efficient.
+ */
+ if (rdataset != NULL) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ } else {
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL)
+ goto addname;
+ }
+ if (sigrdataset != NULL) {
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ } else if (WANTDNSSEC(client)) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL)
+ goto addname;
+ }
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_a, 0,
+ client->now, rdataset,
+ sigrdataset);
+ if (result == DNS_R_NCACHENXDOMAIN)
+ goto addname;
+ if (result == DNS_R_NCACHENXRRSET) {
+ dns_rdataset_disassociate(rdataset);
+ /*
+ * Negative cache entries don't have sigrdatasets.
+ */
+ INSIST(sigrdataset == NULL ||
+ ! dns_rdataset_isassociated(sigrdataset));
+ }
+ if (result == ISC_R_SUCCESS) {
+ mname = NULL;
+ if (!query_isduplicate(client, fname,
+ dns_rdatatype_a, &mname)) {
+ if (mname != NULL) {
+ query_releasename(client, &fname);
+ fname = mname;
+ } else
+ need_addname = ISC_TRUE;
+ ISC_LIST_APPEND(fname->list, rdataset, link);
+ added_something = ISC_TRUE;
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ {
+ ISC_LIST_APPEND(fname->list,
+ sigrdataset, link);
+ sigrdataset =
+ query_newrdataset(client);
+ }
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL)
+ goto addname;
+ if (WANTDNSSEC(client) && sigrdataset == NULL)
+ goto addname;
+ } else {
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ }
+ }
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_aaaa, 0,
+ client->now, rdataset,
+ sigrdataset);
+ if (result == DNS_R_NCACHENXDOMAIN)
+ goto addname;
+ if (result == DNS_R_NCACHENXRRSET) {
+ dns_rdataset_disassociate(rdataset);
+ INSIST(sigrdataset == NULL ||
+ ! dns_rdataset_isassociated(sigrdataset));
+ }
+ if (result == ISC_R_SUCCESS) {
+ mname = NULL;
+ if (!query_isduplicate(client, fname,
+ dns_rdatatype_aaaa, &mname)) {
+ if (mname != NULL) {
+ query_releasename(client, &fname);
+ fname = mname;
+ } else
+ need_addname = ISC_TRUE;
+ ISC_LIST_APPEND(fname->list, rdataset, link);
+ added_something = ISC_TRUE;
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ {
+ ISC_LIST_APPEND(fname->list,
+ sigrdataset, link);
+ sigrdataset = NULL;
+ }
+ rdataset = NULL;
+ }
+ }
+ }
+
+ addname:
+ CTRACE("query_addadditional: addname");
+ /*
+ * If we haven't added anything, then we're done.
+ */
+ if (!added_something)
+ goto cleanup;
+
+ /*
+ * We may have added our rdatasets to an existing name, if so, then
+ * need_addname will be ISC_FALSE. Whether we used an existing name
+ * or a new one, we must set fname to NULL to prevent cleanup.
+ */
+ if (need_addname)
+ dns_message_addname(client->message, fname,
+ DNS_SECTION_ADDITIONAL);
+ fname = NULL;
+
+ /*
+ * In a few cases, we want to add additional data for additional
+ * data. It's simpler to just deal with special cases here than
+ * to try to create a general purpose mechanism and allow the
+ * rdata implementations to do it themselves.
+ *
+ * This involves recursion, but the depth is limited. The
+ * most complex case is adding a SRV rdataset, which involves
+ * recursing to add address records, which in turn can cause
+ * recursion to add KEYs.
+ */
+ if (type == dns_rdatatype_srv && trdataset != NULL) {
+ /*
+ * If we're adding SRV records to the additional data
+ * section, it's helpful if we add the SRV additional data
+ * as well.
+ */
+ eresult = dns_rdataset_additionaldata(trdataset,
+ query_addadditional,
+ client);
+ }
+
+ cleanup:
+ CTRACE("query_addadditional: cleanup");
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ CTRACE("query_addadditional: done");
+ return (eresult);
+}
+
+static inline void
+query_discardcache(ns_client_t *client, dns_rdataset_t *rdataset_base,
+ dns_rdatasetadditional_t additionaltype,
+ dns_rdatatype_t type, dns_zone_t **zonep, dns_db_t **dbp,
+ dns_dbversion_t **versionp, dns_dbnode_t **nodep,
+ dns_name_t *fname)
+{
+ dns_rdataset_t *rdataset;
+
+ while ((rdataset = ISC_LIST_HEAD(fname->list)) != NULL) {
+ ISC_LIST_UNLINK(fname->list, rdataset, link);
+ query_putrdataset(client, &rdataset);
+ }
+ if (*versionp != NULL)
+ dns_db_closeversion(*dbp, versionp, ISC_FALSE);
+ if (*nodep != NULL)
+ dns_db_detachnode(*dbp, nodep);
+ if (*dbp != NULL)
+ dns_db_detach(dbp);
+ if (*zonep != NULL)
+ dns_zone_detach(zonep);
+ (void)dns_rdataset_putadditional(client->view->acache, rdataset_base,
+ additionaltype, type);
+}
+
+static inline isc_result_t
+query_iscachevalid(dns_zone_t *zone, dns_db_t *db, dns_db_t *db0,
+ dns_dbversion_t *version)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_dbversion_t *version_current = NULL;
+ dns_db_t *db_current = db0;
+
+ if (db_current == NULL) {
+ result = dns_zone_getdb(zone, &db_current);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ dns_db_currentversion(db_current, &version_current);
+ if (db_current != db || version_current != version) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ cleanup:
+ dns_db_closeversion(db_current, &version_current, ISC_FALSE);
+ if (db0 == NULL && db_current != NULL)
+ dns_db_detach(&db_current);
+
+ return (result);
+}
+
+static isc_result_t
+query_addadditional2(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {
+ client_additionalctx_t *additionalctx = arg;
+ dns_rdataset_t *rdataset_base;
+ ns_client_t *client;
+ isc_result_t result, eresult;
+ dns_dbnode_t *node, *cnode;
+ dns_db_t *db, *cdb;
+ dns_name_t *fname, *mname0, cfname;
+ dns_rdataset_t *rdataset, *sigrdataset;
+ dns_rdataset_t *crdataset, *crdataset_next;
+ isc_buffer_t *dbuf;
+ isc_buffer_t b;
+ dns_dbversion_t *version, *cversion;
+ isc_boolean_t added_something, need_addname, needadditionalcache;
+ isc_boolean_t need_sigrrset;
+ dns_zone_t *zone;
+ dns_rdatatype_t type;
+ dns_rdatasetadditional_t additionaltype;
+
+ if (qtype != dns_rdatatype_a) {
+ /*
+ * This function is optimized for "address" types. For other
+ * types, use a generic routine.
+ * XXX: ideally, this function should be generic enough.
+ */
+ return (query_addadditional(additionalctx->client,
+ name, qtype));
+ }
+
+ /*
+ * Initialization.
+ */
+ rdataset_base = additionalctx->rdataset;
+ client = additionalctx->client;
+ REQUIRE(NS_CLIENT_VALID(client));
+ eresult = ISC_R_SUCCESS;
+ fname = NULL;
+ rdataset = NULL;
+ sigrdataset = NULL;
+ db = NULL;
+ cdb = NULL;
+ version = NULL;
+ cversion = NULL;
+ node = NULL;
+ cnode = NULL;
+ added_something = ISC_FALSE;
+ need_addname = ISC_FALSE;
+ zone = NULL;
+ needadditionalcache = ISC_FALSE;
+ additionaltype = dns_rdatasetadditional_fromauth;
+ dns_name_init(&cfname, NULL);
+
+ CTRACE("query_addadditional2");
+
+ /*
+ * We treat type A additional section processing as if it
+ * were "any address type" additional section processing.
+ * To avoid multiple lookups, we do an 'any' database
+ * lookup and iterate over the node.
+ * XXXJT: this approach can cause a suboptimal result when the cache
+ * DB only has partial address types and the glue DB has remaining
+ * ones.
+ */
+ type = dns_rdatatype_any;
+
+ /*
+ * Get some resources.
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL)
+ goto cleanup;
+ dns_name_setbuffer(&cfname, &b); /* share the buffer */
+
+ /* Check additional cache */
+ result = dns_rdataset_getadditional(rdataset_base, additionaltype,
+ type, client->view->acache, &zone,
+ &cdb, &cversion, &cnode, &cfname,
+ client->message, client->now);
+ if (result != ISC_R_SUCCESS)
+ goto findauthdb;
+ if (zone == NULL) {
+ CTRACE("query_addadditional2: auth zone not found");
+ goto try_cache;
+ }
+
+ /* Is the cached DB up-to-date? */
+ result = query_iscachevalid(zone, cdb, NULL, cversion);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE("query_addadditional2: old auth additional cache");
+ query_discardcache(client, rdataset_base, additionaltype,
+ type, &zone, &cdb, &cversion, &cnode,
+ &cfname);
+ goto findauthdb;
+ }
+
+ if (cnode == NULL) {
+ /*
+ * We have a negative cache. We don't have to check the zone
+ * ACL, since the result (not using this zone) would be same
+ * regardless of the result.
+ */
+ CTRACE("query_addadditional2: negative auth additional cache");
+ dns_db_closeversion(cdb, &cversion, ISC_FALSE);
+ dns_db_detach(&cdb);
+ dns_zone_detach(&zone);
+ goto try_cache;
+ }
+
+ result = query_validatezonedb(client, name, qtype, DNS_GETDB_NOLOG,
+ zone, cdb, NULL);
+ if (result != ISC_R_SUCCESS) {
+ query_discardcache(client, rdataset_base, additionaltype,
+ type, &zone, &cdb, &cversion, &cnode,
+ &cfname);
+ goto try_cache;
+ }
+
+ /* We've got an active cache. */
+ CTRACE("query_addadditional2: auth additional cache");
+ dns_db_closeversion(cdb, &cversion, ISC_FALSE);
+ db = cdb;
+ node = cnode;
+ dns_name_clone(&cfname, fname);
+ query_keepname(client, fname, dbuf);
+ goto foundcache;
+
+ /*
+ * Look for a zone database that might contain authoritative
+ * additional data.
+ */
+ findauthdb:
+ result = query_getzonedb(client, name, qtype, DNS_GETDB_NOLOG,
+ &zone, &db, &version);
+ if (result != ISC_R_SUCCESS) {
+ /* Cache the negative result */
+ (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
+ type, client->view->acache,
+ NULL, NULL, NULL, NULL,
+ NULL);
+ goto try_cache;
+ }
+
+ CTRACE("query_addadditional2: db_find");
+
+ /*
+ * Since we are looking for authoritative data, we do not set
+ * the GLUEOK flag. Glue will be looked for later, but not
+ * necessarily in the same database.
+ */
+ node = NULL;
+ result = dns_db_find(db, name, version, type, client->query.dboptions,
+ client->now, &node, fname, NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ goto found;
+
+ /* Cache the negative result */
+ (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
+ type, client->view->acache, zone, db,
+ version, NULL, fname);
+
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ version = NULL;
+ dns_db_detach(&db);
+
+ /*
+ * No authoritative data was found. The cache is our next best bet.
+ */
+
+ try_cache:
+ additionaltype = dns_rdatasetadditional_fromcache;
+ result = query_getcachedb(client, name, qtype, &db, DNS_GETDB_NOLOG);
+ if (result != ISC_R_SUCCESS)
+ /*
+ * Most likely the client isn't allowed to query the cache.
+ */
+ goto try_glue;
+
+ result = dns_db_find(db, name, version, type,
+ client->query.dboptions | DNS_DBFIND_GLUEOK,
+ client->now, &node, fname, NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ goto found;
+
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+
+ try_glue:
+ /*
+ * No cached data was found. Glue is our last chance.
+ * RFC1035 sayeth:
+ *
+ * NS records cause both the usual additional section
+ * processing to locate a type A record, and, when used
+ * in a referral, a special search of the zone in which
+ * they reside for glue information.
+ *
+ * This is the "special search". Note that we must search
+ * the zone where the NS record resides, not the zone it
+ * points to, and that we only do the search in the delegation
+ * case (identified by client->query.gluedb being set).
+ */
+ if (client->query.gluedb == NULL)
+ goto cleanup;
+
+ /*
+ * Don't poision caches using the bailiwick protection model.
+ */
+ if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))
+ goto cleanup;
+
+ /* Check additional cache */
+ additionaltype = dns_rdatasetadditional_fromglue;
+ result = dns_rdataset_getadditional(rdataset_base, additionaltype,
+ type, client->view->acache, NULL,
+ &cdb, &cversion, &cnode, &cfname,
+ client->message, client->now);
+ if (result != ISC_R_SUCCESS)
+ goto findglue;
+
+ result = query_iscachevalid(zone, cdb, client->query.gluedb, cversion);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE("query_addadditional2: old glue additional cache");
+ query_discardcache(client, rdataset_base, additionaltype,
+ type, &zone, &cdb, &cversion, &cnode,
+ &cfname);
+ goto findglue;
+ }
+
+ if (cnode == NULL) {
+ /* We have a negative cache. */
+ CTRACE("query_addadditional2: negative glue additional cache");
+ dns_db_closeversion(cdb, &cversion, ISC_FALSE);
+ dns_db_detach(&cdb);
+ goto cleanup;
+ }
+
+ /* Cache hit. */
+ CTRACE("query_addadditional2: glue additional cache");
+ dns_db_closeversion(cdb, &cversion, ISC_FALSE);
+ db = cdb;
+ node = cnode;
+ dns_name_clone(&cfname, fname);
+ query_keepname(client, fname, dbuf);
+ goto foundcache;
+
+ findglue:
+ dns_db_attach(client->query.gluedb, &db);
+ result = dns_db_find(db, name, version, type,
+ client->query.dboptions | DNS_DBFIND_GLUEOK,
+ client->now, &node, fname, NULL, NULL);
+ if (!(result == ISC_R_SUCCESS ||
+ result == DNS_R_ZONECUT ||
+ result == DNS_R_GLUE)) {
+ /* cache the negative result */
+ (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
+ type, client->view->acache,
+ NULL, db, version, NULL,
+ fname);
+ goto cleanup;
+ }
+
+ found:
+ /*
+ * We have found a DB node to iterate over from a DB.
+ * We are going to look for address RRsets (i.e., A and AAAA) in the DB
+ * node we've just found. We'll then store the complete information
+ * in the additional data cache.
+ */
+ dns_name_clone(fname, &cfname);
+ query_keepname(client, fname, dbuf);
+ needadditionalcache = ISC_TRUE;
+
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL)
+ goto cleanup;
+
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL)
+ goto cleanup;
+
+ /*
+ * Find A RRset with sig RRset. Even if we don't find a sig RRset
+ * for a client using DNSSEC, we'll continue the process to make a
+ * complete list to be cached. However, we need to cancel the
+ * caching when something unexpected happens, in order to avoid
+ * caching incomplete information.
+ */
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_a, 0,
+ client->now, rdataset, sigrdataset);
+ /*
+ * If we can't promote glue/pending from the cache to secure
+ * then drop it.
+ */
+ if (result == ISC_R_SUCCESS &&
+ additionaltype == dns_rdatasetadditional_fromcache &&
+ (rdataset->trust == dns_trust_pending ||
+ rdataset->trust == dns_trust_glue) &&
+ !validate(client, db, fname, rdataset, sigrdataset)) {
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ result = ISC_R_NOTFOUND;
+ }
+ if (result == DNS_R_NCACHENXDOMAIN)
+ goto setcache;
+ if (result == DNS_R_NCACHENXRRSET) {
+ dns_rdataset_disassociate(rdataset);
+ /*
+ * Negative cache entries don't have sigrdatasets.
+ */
+ INSIST(! dns_rdataset_isassociated(sigrdataset));
+ }
+ if (result == ISC_R_SUCCESS) {
+ /* Remember the result as a cache */
+ ISC_LIST_APPEND(cfname.list, rdataset, link);
+ if (dns_rdataset_isassociated(sigrdataset)) {
+ ISC_LIST_APPEND(cfname.list, sigrdataset, link);
+ sigrdataset = query_newrdataset(client);
+ }
+ rdataset = query_newrdataset(client);
+ if (sigrdataset == NULL || rdataset == NULL) {
+ /* do not cache incomplete information */
+ goto foundcache;
+ }
+ }
+
+ /* Find AAAA RRset with sig RRset */
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_aaaa,
+ 0, client->now, rdataset, sigrdataset);
+ /*
+ * If we can't promote glue/pending from the cache to secure
+ * then drop it.
+ */
+ if (result == ISC_R_SUCCESS &&
+ additionaltype == dns_rdatasetadditional_fromcache &&
+ (rdataset->trust == dns_trust_pending ||
+ rdataset->trust == dns_trust_glue) &&
+ !validate(client, db, fname, rdataset, sigrdataset)) {
+ dns_rdataset_disassociate(rdataset);
+ if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ result = ISC_R_NOTFOUND;
+ }
+ if (result == ISC_R_SUCCESS) {
+ ISC_LIST_APPEND(cfname.list, rdataset, link);
+ rdataset = NULL;
+ if (dns_rdataset_isassociated(sigrdataset)) {
+ ISC_LIST_APPEND(cfname.list, sigrdataset, link);
+ sigrdataset = NULL;
+ }
+ }
+
+ setcache:
+ /*
+ * Set the new result in the cache if required. We do not support
+ * caching additional data from a cache DB.
+ */
+ if (needadditionalcache == ISC_TRUE &&
+ (additionaltype == dns_rdatasetadditional_fromauth ||
+ additionaltype == dns_rdatasetadditional_fromglue)) {
+ (void)dns_rdataset_setadditional(rdataset_base, additionaltype,
+ type, client->view->acache,
+ zone, db, version, node,
+ &cfname);
+ }
+
+ foundcache:
+ need_sigrrset = ISC_FALSE;
+ mname0 = NULL;
+ for (crdataset = ISC_LIST_HEAD(cfname.list);
+ crdataset != NULL;
+ crdataset = crdataset_next) {
+ dns_name_t *mname;
+
+ crdataset_next = ISC_LIST_NEXT(crdataset, link);
+
+ mname = NULL;
+ if (crdataset->type == dns_rdatatype_a ||
+ crdataset->type == dns_rdatatype_aaaa) {
+ if (!query_isduplicate(client, fname, crdataset->type,
+ &mname)) {
+ if (mname != NULL) {
+ /*
+ * A different type of this name is
+ * already stored in the additional
+ * section. We'll reuse the name.
+ * Note that this should happen at most
+ * once. Otherwise, fname->link could
+ * leak below.
+ */
+ INSIST(mname0 == NULL);
+
+ query_releasename(client, &fname);
+ fname = mname;
+ mname0 = mname;
+ } else
+ need_addname = ISC_TRUE;
+ ISC_LIST_UNLINK(cfname.list, crdataset, link);
+ ISC_LIST_APPEND(fname->list, crdataset, link);
+ added_something = ISC_TRUE;
+ need_sigrrset = ISC_TRUE;
+ } else
+ need_sigrrset = ISC_FALSE;
+ } else if (crdataset->type == dns_rdatatype_rrsig &&
+ need_sigrrset && WANTDNSSEC(client)) {
+ ISC_LIST_UNLINK(cfname.list, crdataset, link);
+ ISC_LIST_APPEND(fname->list, crdataset, link);
+ added_something = ISC_TRUE; /* just in case */
+ need_sigrrset = ISC_FALSE;
+ }
+ }
+
+ CTRACE("query_addadditional2: addname");
+
+ /*
+ * If we haven't added anything, then we're done.
+ */
+ if (!added_something)
+ goto cleanup;
+
+ /*
+ * We may have added our rdatasets to an existing name, if so, then
+ * need_addname will be ISC_FALSE. Whether we used an existing name
+ * or a new one, we must set fname to NULL to prevent cleanup.
+ */
+ if (need_addname)
+ dns_message_addname(client->message, fname,
+ DNS_SECTION_ADDITIONAL);
+ fname = NULL;
+
+ cleanup:
+ CTRACE("query_addadditional2: cleanup");
+
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ while ((crdataset = ISC_LIST_HEAD(cfname.list)) != NULL) {
+ ISC_LIST_UNLINK(cfname.list, crdataset, link);
+ query_putrdataset(client, &crdataset);
+ }
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ CTRACE("query_addadditional2: done");
+ return (eresult);
+}
+
+static inline void
+query_addrdataset(ns_client_t *client, dns_name_t *fname,
+ dns_rdataset_t *rdataset)
+{
+ client_additionalctx_t additionalctx;
+
+ /*
+ * Add 'rdataset' and any pertinent additional data to
+ * 'fname', a name in the response message for 'client'.
+ */
+
+ CTRACE("query_addrdataset");
+
+ ISC_LIST_APPEND(fname->list, rdataset, link);
+
+ if (client->view->order != NULL)
+ rdataset->attributes |= dns_order_find(client->view->order,
+ fname, rdataset->type,
+ rdataset->rdclass);
+ rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
+
+ if (NOADDITIONAL(client))
+ return;
+
+ /*
+ * Add additional data.
+ *
+ * We don't care if dns_rdataset_additionaldata() fails.
+ */
+ additionalctx.client = client;
+ additionalctx.rdataset = rdataset;
+ (void)dns_rdataset_additionaldata(rdataset, query_addadditional2,
+ &additionalctx);
+ 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)
+{
+ 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,
+ isc_boolean_t zero_ttl)
+{
+ 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;
+
+ /*
+ * 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,
+ client->query.dboptions, 0, &node,
+ fname, rdataset, sigrdataset);
+ }
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * This is bad. We tried to get the SOA RR at the zone top
+ * and it didn't work!
+ */
+ eresult = DNS_R_SERVFAIL;
+ } else {
+ /*
+ * Extract the SOA MINIMUM.
+ */
+ dns_rdata_soa_t soa;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ result = dns_rdataset_first(rdataset);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ if (zero_ttl) {
+ rdataset->ttl = 0;
+ if (sigrdataset != NULL)
+ sigrdataset->ttl = 0;
+ }
+
+ /*
+ * Add the SOA and its SIG to the response, with the
+ * TTLs adjusted per RFC2308 section 3.
+ */
+ if (rdataset->ttl > soa.minimum)
+ rdataset->ttl = soa.minimum;
+ if (sigrdataset != NULL && sigrdataset->ttl > soa.minimum)
+ sigrdataset->ttl = soa.minimum;
+
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
+ DNS_SECTION_AUTHORITY);
+ }
+
+ cleanup:
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (name != NULL)
+ query_releasename(client, &name);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ return (eresult);
+}
+
+static inline isc_result_t
+query_addns(ns_client_t *client, dns_db_t *db, dns_dbversion_t *version) {
+ dns_name_t *name, *fname;
+ dns_dbnode_t *node;
+ isc_result_t result, eresult;
+ dns_fixedname_t foundname;
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+ dns_rdataset_t **sigrdatasetp = NULL;
+
+ CTRACE("query_addns");
+ /*
+ * Initialization.
+ */
+ eresult = ISC_R_SUCCESS;
+ name = NULL;
+ rdataset = NULL;
+ node = NULL;
+ dns_fixedname_init(&foundname);
+ fname = dns_fixedname_name(&foundname);
+
+ /*
+ * Get resources and make 'name' be the database origin.
+ */
+ result = dns_message_gettempname(client->message, &name);
+ if (result != ISC_R_SUCCESS) {
+ CTRACE("query_addns: dns_message_gettempname failed: done");
+ return (result);
+ }
+ dns_name_init(name, NULL);
+ dns_name_clone(dns_db_origin(db), name);
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL) {
+ CTRACE("query_addns: query_newrdataset failed");
+ eresult = DNS_R_SERVFAIL;
+ goto cleanup;
+ }
+ if (WANTDNSSEC(client) && dns_db_issecure(db)) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL) {
+ CTRACE("query_addns: query_newrdataset failed");
+ eresult = DNS_R_SERVFAIL;
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Find the NS rdataset.
+ */
+ result = dns_db_getoriginnode(db, &node);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_ns,
+ 0, client->now, rdataset,
+ sigrdataset);
+ } else {
+ CTRACE("query_addns: calling dns_db_find");
+ result = dns_db_find(db, name, NULL, dns_rdatatype_ns,
+ client->query.dboptions, 0, &node,
+ fname, rdataset, sigrdataset);
+ CTRACE("query_addns: dns_db_find complete");
+ }
+ if (result != ISC_R_SUCCESS) {
+ CTRACE("query_addns: "
+ "dns_db_findrdataset or dns_db_find failed");
+ /*
+ * This is bad. We tried to get the NS rdataset at the zone
+ * top and it didn't work!
+ */
+ eresult = DNS_R_SERVFAIL;
+ } else {
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ query_addrrset(client, &name, &rdataset, sigrdatasetp, NULL,
+ DNS_SECTION_AUTHORITY);
+ }
+
+ cleanup:
+ CTRACE("query_addns: cleanup");
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (name != NULL)
+ query_releasename(client, &name);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ CTRACE("query_addns: done");
+ return (eresult);
+}
+
+static inline isc_result_t
+query_addcnamelike(ns_client_t *client, dns_name_t *qname, dns_name_t *tname,
+ dns_trust_t trust, dns_name_t **anamep, dns_rdatatype_t type)
+{
+ dns_rdataset_t *rdataset;
+ dns_rdatalist_t *rdatalist;
+ dns_rdata_t *rdata;
+ isc_result_t result;
+ isc_region_t r;
+
+ /*
+ * We assume the name data referred to by tname won't go away.
+ */
+
+ REQUIRE(anamep != NULL);
+
+ rdatalist = NULL;
+ result = dns_message_gettemprdatalist(client->message, &rdatalist);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ rdata = NULL;
+ result = dns_message_gettemprdata(client->message, &rdata);
+ if (result != ISC_R_SUCCESS)
+ 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);
+ return (result);
+ }
+
+ rdatalist->type = type;
+ rdatalist->covers = 0;
+ rdatalist->rdclass = client->message->rdclass;
+ rdatalist->ttl = 0;
+
+ dns_name_toregion(tname, &r);
+ rdata->data = r.base;
+ rdata->length = r.length;
+ rdata->rdclass = client->message->rdclass;
+ rdata->type = type;
+
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
+ == ISC_R_SUCCESS);
+ rdataset->trust = trust;
+
+ query_addrrset(client, anamep, &rdataset, NULL, NULL,
+ DNS_SECTION_ANSWER);
+
+ if (rdataset != NULL) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ dns_message_puttemprdataset(client->message, &rdataset);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Mark the RRsets as secure. Update the cache (db) to reflect the
+ * change in trust level.
+ */
+static void
+mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
+ isc_uint32_t ttl, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+
+ rdataset->trust = dns_trust_secure;
+ sigrdataset->trust = dns_trust_secure;
+
+ /*
+ * Save the updated secure state. Ignore failures.
+ */
+ result = dns_db_findnode(db, name, ISC_TRUE, &node);
+ if (result != ISC_R_SUCCESS)
+ return;
+ /*
+ * Bound the validated ttls then minimise.
+ */
+ if (sigrdataset->ttl > ttl)
+ sigrdataset->ttl = ttl;
+ if (rdataset->ttl > ttl)
+ rdataset->ttl = ttl;
+ if (rdataset->ttl > sigrdataset->ttl)
+ rdataset->ttl = sigrdataset->ttl;
+ else
+ sigrdataset->ttl = rdataset->ttl;
+
+ (void)dns_db_addrdataset(db, node, NULL, client->now, rdataset,
+ 0, NULL);
+ (void)dns_db_addrdataset(db, node, NULL, client->now, sigrdataset,
+ 0, NULL);
+ dns_db_detachnode(db, &node);
+}
+
+/*
+ * Find the secure key that corresponds to rrsig.
+ * Note: 'keyrdataset' maintains state between sucessive calls,
+ * there may be multiple keys with the same keyid.
+ * Return ISC_FALSE if we have exhausted all the possible keys.
+ */
+static isc_boolean_t
+get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
+ dns_rdataset_t *keyrdataset, dst_key_t **keyp)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ isc_boolean_t secure = ISC_FALSE;
+
+ if (!dns_rdataset_isassociated(keyrdataset)) {
+ result = dns_db_findnode(db, &rrsig->signer, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+
+ result = dns_db_findrdataset(db, node, NULL,
+ dns_rdatatype_dnskey, 0,
+ client->now, keyrdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+
+ if (keyrdataset->trust != dns_trust_secure)
+ return (ISC_FALSE);
+
+ result = dns_rdataset_first(keyrdataset);
+ } else
+ result = dns_rdataset_next(keyrdataset);
+
+ for ( ; result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(keyrdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t b;
+
+ dns_rdataset_current(keyrdataset, &rdata);
+ isc_buffer_init(&b, rdata.data, rdata.length);
+ isc_buffer_add(&b, rdata.length);
+ result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
+ client->mctx, keyp);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
+ rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
+ dst_key_iszonekey(*keyp)) {
+ secure = ISC_TRUE;
+ break;
+ }
+ dst_key_free(keyp);
+ }
+ return (secure);
+}
+
+static isc_boolean_t
+verify(dst_key_t *key, dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_rdata_t *rdata, isc_mem_t *mctx, isc_boolean_t acceptexpired)
+{
+ isc_result_t result;
+ dns_fixedname_t fixed;
+ isc_boolean_t ignore = ISC_FALSE;
+
+ dns_fixedname_init(&fixed);
+
+again:
+ result = dns_dnssec_verify2(name, rdataset, key, ignore, mctx,
+ rdata, NULL);
+ if (result == DNS_R_SIGEXPIRED && acceptexpired) {
+ ignore = ISC_TRUE;
+ goto again;
+ }
+ if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+/*
+ * Validate the rdataset if possible with available records.
+ */
+static isc_boolean_t
+validate(ns_client_t *client, dns_db_t *db, dns_name_t *name,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t rrsig;
+ dst_key_t *key = NULL;
+ dns_rdataset_t keyrdataset;
+
+ if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
+ return (ISC_FALSE);
+
+ for (result = dns_rdataset_first(sigrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(sigrdataset)) {
+
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(sigrdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+ if (!dns_resolver_algorithm_supported(client->view->resolver,
+ name, rrsig.algorithm))
+ continue;
+ if (!dns_name_issubdomain(name, &rrsig.signer))
+ continue;
+ dns_rdataset_init(&keyrdataset);
+ do {
+ if (!get_key(client, db, &rrsig, &keyrdataset, &key))
+ break;
+ if (verify(key, name, rdataset, &rdata, client->mctx,
+ client->view->acceptexpired)) {
+ dst_key_free(&key);
+ dns_rdataset_disassociate(&keyrdataset);
+ mark_secure(client, db, name,
+ rrsig.originalttl,
+ rdataset, sigrdataset);
+ return (ISC_TRUE);
+ }
+ dst_key_free(&key);
+ } while (1);
+ if (dns_rdataset_isassociated(&keyrdataset))
+ dns_rdataset_disassociate(&keyrdataset);
+ }
+ return (ISC_FALSE);
+}
+
+static void
+query_addbestns(ns_client_t *client) {
+ dns_db_t *db, *zdb;
+ dns_dbnode_t *node;
+ dns_name_t *fname, *zfname;
+ dns_rdataset_t *rdataset, *sigrdataset, *zrdataset, *zsigrdataset;
+ isc_boolean_t is_zone, use_zone;
+ isc_buffer_t *dbuf;
+ isc_result_t result;
+ dns_dbversion_t *version;
+ dns_zone_t *zone;
+ isc_buffer_t b;
+
+ CTRACE("query_addbestns");
+ fname = NULL;
+ zfname = NULL;
+ rdataset = NULL;
+ zrdataset = NULL;
+ sigrdataset = NULL;
+ zsigrdataset = NULL;
+ node = NULL;
+ db = NULL;
+ zdb = NULL;
+ version = NULL;
+ zone = NULL;
+ is_zone = ISC_FALSE;
+ use_zone = ISC_FALSE;
+
+ /*
+ * Find the right database.
+ */
+ result = query_getdb(client, client->query.qname, dns_rdatatype_ns, 0,
+ &zone, &db, &version, &is_zone);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ db_find:
+ /*
+ * We'll need some resources...
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ rdataset = query_newrdataset(client);
+ if (fname == NULL || rdataset == NULL)
+ goto cleanup;
+ /*
+ * Get the RRSIGs if the client requested them or if we may
+ * need to validate answers from the cache.
+ */
+ if (WANTDNSSEC(client) || !is_zone) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL)
+ goto cleanup;
+ }
+
+ /*
+ * Now look for the zonecut.
+ */
+ if (is_zone) {
+ result = dns_db_find(db, client->query.qname, version,
+ dns_rdatatype_ns, client->query.dboptions,
+ client->now, &node, fname,
+ rdataset, sigrdataset);
+ if (result != DNS_R_DELEGATION)
+ goto cleanup;
+ if (USECACHE(client)) {
+ query_keepname(client, fname, dbuf);
+ zdb = db;
+ zfname = fname;
+ fname = NULL;
+ zrdataset = rdataset;
+ rdataset = NULL;
+ zsigrdataset = sigrdataset;
+ sigrdataset = NULL;
+ dns_db_detachnode(db, &node);
+ version = NULL;
+ db = NULL;
+ dns_db_attach(client->view->cachedb, &db);
+ is_zone = ISC_FALSE;
+ goto db_find;
+ }
+ } else {
+ result = dns_db_findzonecut(db, client->query.qname,
+ client->query.dboptions,
+ client->now, &node, fname,
+ rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ if (zfname != NULL &&
+ !dns_name_issubdomain(fname, zfname)) {
+ /*
+ * We found a zonecut in the cache, but our
+ * zone delegation is better.
+ */
+ use_zone = ISC_TRUE;
+ }
+ } else if (result == ISC_R_NOTFOUND && zfname != NULL) {
+ /*
+ * We didn't find anything in the cache, but we
+ * have a zone delegation, so use it.
+ */
+ use_zone = ISC_TRUE;
+ } else
+ goto cleanup;
+ }
+
+ if (use_zone) {
+ query_releasename(client, &fname);
+ fname = zfname;
+ zfname = NULL;
+ /*
+ * We've already done query_keepname() on
+ * zfname, so we must set dbuf to NULL to
+ * prevent query_addrrset() from trying to
+ * call query_keepname() again.
+ */
+ dbuf = NULL;
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ rdataset = zrdataset;
+ zrdataset = NULL;
+ sigrdataset = zsigrdataset;
+ zsigrdataset = NULL;
+ }
+
+ /*
+ * Attempt to validate RRsets that are pending or that are glue.
+ */
+ if ((rdataset->trust == dns_trust_pending ||
+ (sigrdataset != NULL && sigrdataset->trust == dns_trust_pending))
+ && !validate(client, db, fname, rdataset, sigrdataset) &&
+ (client->query.dboptions & DNS_DBFIND_PENDINGOK) == 0)
+ goto cleanup;
+
+ if ((rdataset->trust == dns_trust_glue ||
+ (sigrdataset != NULL && sigrdataset->trust == dns_trust_glue)) &&
+ !validate(client, db, fname, rdataset, sigrdataset) &&
+ SECURE(client) && WANTDNSSEC(client))
+ goto cleanup;
+
+ /*
+ * If the client doesn't want DNSSEC we can discard the sigrdataset
+ * now.
+ */
+ if (!WANTDNSSEC(client))
+ query_putrdataset(client, &sigrdataset);
+ query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
+ DNS_SECTION_AUTHORITY);
+
+ cleanup:
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ if (zdb != NULL) {
+ query_putrdataset(client, &zrdataset);
+ if (zsigrdataset != NULL)
+ query_putrdataset(client, &zsigrdataset);
+ if (zfname != NULL)
+ query_releasename(client, &zfname);
+ dns_db_detach(&zdb);
+ }
+}
+
+static void
+fixrdataset(ns_client_t *client, dns_rdataset_t **rdataset) {
+ if (*rdataset == NULL)
+ *rdataset = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(*rdataset))
+ dns_rdataset_disassociate(*rdataset);
+}
+
+static void
+fixfname(ns_client_t *client, dns_name_t **fname, isc_buffer_t **dbuf,
+ isc_buffer_t *nbuf)
+{
+ if (*fname == NULL) {
+ *dbuf = query_getnamebuf(client);
+ if (*dbuf == NULL)
+ return;
+ *fname = query_newname(client, *dbuf, nbuf);
+ }
+}
+
+static void
+query_addds(ns_client_t *client, dns_db_t *db, dns_dbnode_t *node,
+ dns_dbversion_t *version, dns_name_t *name)
+{
+ dns_fixedname_t fixed;
+ dns_name_t *fname = NULL;
+ dns_name_t *rname;
+ dns_rdataset_t *rdataset, *sigrdataset;
+ isc_buffer_t *dbuf, b;
+ isc_result_t result;
+ unsigned int count;
+
+ CTRACE("query_addds");
+ rname = NULL;
+ rdataset = NULL;
+ sigrdataset = NULL;
+
+ /*
+ * We'll need some resources...
+ */
+ rdataset = query_newrdataset(client);
+ sigrdataset = query_newrdataset(client);
+ if (rdataset == NULL || sigrdataset == NULL)
+ goto cleanup;
+
+ /*
+ * Look for the DS record, which may or may not be present.
+ */
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_ds, 0,
+ client->now, rdataset, sigrdataset);
+ /*
+ * If we didn't find it, look for an NSEC.
+ */
+ if (result == ISC_R_NOTFOUND)
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec, 0, client->now,
+ rdataset, sigrdataset);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+ goto addnsec3;
+ if (!dns_rdataset_isassociated(rdataset) ||
+ !dns_rdataset_isassociated(sigrdataset))
+ goto addnsec3;
+
+ /*
+ * We've already added the NS record, so if the name's not there,
+ * we have other problems. Use this name rather than calling
+ * query_addrrset().
+ */
+ result = dns_message_firstname(client->message, DNS_SECTION_AUTHORITY);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ rname = NULL;
+ dns_message_currentname(client->message, DNS_SECTION_AUTHORITY,
+ &rname);
+ result = dns_message_findtype(rname, dns_rdatatype_ns, 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ ISC_LIST_APPEND(rname->list, rdataset, link);
+ ISC_LIST_APPEND(rname->list, sigrdataset, link);
+ rdataset = NULL;
+ sigrdataset = NULL;
+ return;
+
+ addnsec3:
+ if (dns_db_iscache(db))
+ goto cleanup;
+ /*
+ * Add the NSEC3 which proves the DS does not exist.
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ dns_fixedname_init(&fixed);
+ query_findclosestnsec3(name, db, version, client, rdataset,
+ sigrdataset, fname, ISC_TRUE,
+ dns_fixedname_name(&fixed));
+ if (!dns_rdataset_isassociated(rdataset))
+ goto cleanup;
+ query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
+ DNS_SECTION_AUTHORITY);
+ /*
+ * Did we find the closest provable encloser instead?
+ * If so add the nearest to the closest provable encloser.
+ */
+ if (!dns_name_equal(name, dns_fixedname_name(&fixed))) {
+ count = dns_name_countlabels(dns_fixedname_name(&fixed)) + 1;
+ dns_name_getlabelsequence(name,
+ dns_name_countlabels(name) - count,
+ count, dns_fixedname_name(&fixed));
+ fixfname(client, &fname, &dbuf, &b);
+ fixrdataset(client, &rdataset);
+ fixrdataset(client, &sigrdataset);
+ if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
+ goto cleanup;
+ query_findclosestnsec3(dns_fixedname_name(&fixed), db, version,
+ client, rdataset, sigrdataset, fname,
+ ISC_FALSE, NULL);
+ if (!dns_rdataset_isassociated(rdataset))
+ goto cleanup;
+ query_addrrset(client, &fname, &rdataset, &sigrdataset, dbuf,
+ DNS_SECTION_AUTHORITY);
+ }
+
+ cleanup:
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+}
+
+static void
+query_addwildcardproof(ns_client_t *client, dns_db_t *db,
+ dns_dbversion_t *version, dns_name_t *name,
+ isc_boolean_t ispositive)
+{
+ isc_buffer_t *dbuf, b;
+ dns_name_t *fname;
+ dns_rdataset_t *rdataset, *sigrdataset;
+ dns_fixedname_t wfixed;
+ dns_name_t *wname;
+ dns_dbnode_t *node;
+ unsigned int options;
+ unsigned int olabels, nlabels, labels;
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec_t nsec;
+ isc_boolean_t have_wname;
+ int order;
+ dns_fixedname_t cfixed;
+ dns_name_t *cname;
+
+ CTRACE("query_addwildcardproof");
+ fname = NULL;
+ rdataset = NULL;
+ sigrdataset = NULL;
+ node = NULL;
+
+ /*
+ * Get the NOQNAME proof then if !ispositve
+ * get the NOWILDCARD proof.
+ *
+ * DNS_DBFIND_NOWILD finds the NSEC records that covers the
+ * name ignoring any wildcard. From the owner and next names
+ * of this record you can compute which wildcard (if it exists)
+ * will match by finding the longest common suffix of the
+ * owner name and next names with the qname and prefixing that
+ * with the wildcard label.
+ *
+ * e.g.
+ * Given:
+ * example SOA
+ * example NSEC b.example
+ * b.example A
+ * b.example NSEC a.d.example
+ * a.d.example A
+ * a.d.example NSEC g.f.example
+ * g.f.example A
+ * g.f.example NSEC z.i.example
+ * z.i.example A
+ * z.i.example NSEC example
+ *
+ * QNAME:
+ * a.example -> example NSEC b.example
+ * owner common example
+ * next common example
+ * wild *.example
+ * d.b.example -> b.example NSEC a.d.example
+ * owner common b.example
+ * next common example
+ * wild *.b.example
+ * a.f.example -> a.d.example NSEC g.f.example
+ * owner common example
+ * next common f.example
+ * wild *.f.example
+ * j.example -> z.i.example NSEC example
+ * owner common example
+ * next common example
+ * wild *.f.example
+ */
+ options = client->query.dboptions | DNS_DBFIND_NOWILD;
+ dns_fixedname_init(&wfixed);
+ wname = dns_fixedname_name(&wfixed);
+ again:
+ have_wname = ISC_FALSE;
+ /*
+ * We'll need some resources...
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ rdataset = query_newrdataset(client);
+ sigrdataset = query_newrdataset(client);
+ if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
+ goto cleanup;
+
+ result = dns_db_find(db, name, version, dns_rdatatype_nsec, options,
+ 0, &node, fname, rdataset, sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ if (!dns_rdataset_isassociated(rdataset)) {
+ /*
+ * No NSEC proof available, return NSEC3 proofs instead.
+ */
+ dns_fixedname_init(&cfixed);
+ cname = dns_fixedname_name(&cfixed);
+ /*
+ * Find the closest encloser.
+ */
+ dns_name_copy(name, cname, NULL);
+ while (result == DNS_R_NXDOMAIN) {
+ labels = dns_name_countlabels(cname) - 1;
+ dns_name_split(cname, labels, NULL, cname);
+ result = dns_db_find(db, cname, version,
+ dns_rdatatype_nsec,
+ options, 0, NULL, fname,
+ NULL, NULL);
+ }
+ /*
+ * Add closest (provable) encloser NSEC3.
+ */
+ query_findclosestnsec3(cname, db, NULL, client, rdataset,
+ sigrdataset, fname, ISC_TRUE, cname);
+ if (!dns_rdataset_isassociated(rdataset))
+ goto cleanup;
+ query_addrrset(client, &fname, &rdataset, &sigrdataset,
+ dbuf, DNS_SECTION_AUTHORITY);
+
+ /*
+ * Replace resources which were consumed by query_addrrset.
+ */
+ if (fname == NULL) {
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ }
+
+ if (rdataset == NULL)
+ rdataset = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+
+ if (sigrdataset == NULL)
+ sigrdataset = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+
+ if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
+ goto cleanup;
+ /*
+ * Add no qname proof.
+ */
+ labels = dns_name_countlabels(cname) + 1;
+ if (dns_name_countlabels(name) == labels)
+ dns_name_copy(name, wname, NULL);
+ else
+ dns_name_split(name, labels, NULL, wname);
+
+ query_findclosestnsec3(wname, db, NULL, client, rdataset,
+ sigrdataset, fname, ISC_FALSE, NULL);
+ if (!dns_rdataset_isassociated(rdataset))
+ goto cleanup;
+ query_addrrset(client, &fname, &rdataset, &sigrdataset,
+ dbuf, DNS_SECTION_AUTHORITY);
+
+ if (ispositive)
+ goto cleanup;
+
+ /*
+ * Replace resources which were consumed by query_addrrset.
+ */
+ if (fname == NULL) {
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ }
+
+ if (rdataset == NULL)
+ rdataset = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+
+ if (sigrdataset == NULL)
+ sigrdataset = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+
+ if (fname == NULL || rdataset == NULL || sigrdataset == NULL)
+ goto cleanup;
+ /*
+ * Add the no wildcard proof.
+ */
+ result = dns_name_concatenate(dns_wildcardname,
+ cname, wname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ query_findclosestnsec3(wname, db, NULL, client, rdataset,
+ sigrdataset, fname, ISC_FALSE, NULL);
+ if (!dns_rdataset_isassociated(rdataset))
+ goto cleanup;
+ query_addrrset(client, &fname, &rdataset, &sigrdataset,
+ dbuf, DNS_SECTION_AUTHORITY);
+
+ goto cleanup;
+ } else if (result == DNS_R_NXDOMAIN) {
+ if (!ispositive)
+ result = dns_rdataset_first(rdataset);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec, NULL);
+ }
+ if (result == ISC_R_SUCCESS) {
+ (void)dns_name_fullcompare(name, fname, &order,
+ &olabels);
+ (void)dns_name_fullcompare(name, &nsec.next, &order,
+ &nlabels);
+ /*
+ * Check for a pathological condition created when
+ * serving some malformed signed zones and bail out.
+ */
+ if (dns_name_countlabels(name) == nlabels)
+ goto cleanup;
+
+ if (olabels > nlabels)
+ dns_name_split(name, olabels, NULL, wname);
+ else
+ dns_name_split(name, nlabels, NULL, wname);
+ result = dns_name_concatenate(dns_wildcardname,
+ wname, wname, NULL);
+ if (result == ISC_R_SUCCESS)
+ have_wname = ISC_TRUE;
+ dns_rdata_freestruct(&nsec);
+ }
+ query_addrrset(client, &fname, &rdataset, &sigrdataset,
+ dbuf, DNS_SECTION_AUTHORITY);
+ }
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ if (have_wname) {
+ ispositive = ISC_TRUE; /* prevent loop */
+ if (!dns_name_equal(name, wname)) {
+ name = wname;
+ goto again;
+ }
+ }
+ cleanup:
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+}
+
+static void
+query_addnxrrsetnsec(ns_client_t *client, dns_db_t *db,
+ dns_dbversion_t *version, dns_name_t **namep,
+ dns_rdataset_t **rdatasetp, dns_rdataset_t **sigrdatasetp)
+{
+ dns_name_t *name;
+ dns_rdataset_t *sigrdataset;
+ dns_rdata_t sigrdata;
+ dns_rdata_rrsig_t sig;
+ unsigned int labels;
+ isc_buffer_t *dbuf, b;
+ dns_name_t *fname;
+ isc_result_t result;
+
+ name = *namep;
+ if ((name->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
+ query_addrrset(client, namep, rdatasetp, sigrdatasetp,
+ NULL, DNS_SECTION_AUTHORITY);
+ return;
+ }
+
+ if (sigrdatasetp == NULL)
+ return;
+
+ sigrdataset = *sigrdatasetp;
+ if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
+ return;
+ result = dns_rdataset_first(sigrdataset);
+ if (result != ISC_R_SUCCESS)
+ return;
+ dns_rdata_init(&sigrdata);
+ dns_rdataset_current(sigrdataset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ labels = dns_name_countlabels(name);
+ if ((unsigned int)sig.labels + 1 >= labels)
+ return;
+
+ /* XXX */
+ query_addwildcardproof(client, db, version, client->query.qname,
+ ISC_TRUE);
+
+ /*
+ * We'll need some resources...
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ return;
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL)
+ return;
+ dns_name_split(name, sig.labels + 1, NULL, fname);
+ /* This will succeed, since we've stripped labels. */
+ RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname,
+ NULL) == ISC_R_SUCCESS);
+ query_addrrset(client, &fname, rdatasetp, sigrdatasetp,
+ dbuf, DNS_SECTION_AUTHORITY);
+}
+
+static void
+query_resume(isc_task_t *task, isc_event_t *event) {
+ dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
+ ns_client_t *client;
+ isc_boolean_t fetch_cancelled, client_shuttingdown;
+
+ /*
+ * Resume a query after recursion.
+ */
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
+ client = devent->ev_arg;
+ REQUIRE(NS_CLIENT_VALID(client));
+ REQUIRE(task == client->task);
+ REQUIRE(RECURSING(client));
+
+ LOCK(&client->query.fetchlock);
+ if (client->query.fetch != NULL) {
+ /*
+ * This is the fetch we've been waiting for.
+ */
+ INSIST(devent->fetch == client->query.fetch);
+ client->query.fetch = NULL;
+ fetch_cancelled = ISC_FALSE;
+ /*
+ * Update client->now.
+ */
+ isc_stdtime_get(&client->now);
+ } else {
+ /*
+ * This is a fetch completion event for a cancelled fetch.
+ * Clean up and don't resume the find.
+ */
+ fetch_cancelled = ISC_TRUE;
+ }
+ UNLOCK(&client->query.fetchlock);
+ INSIST(client->query.fetch == NULL);
+
+ client->query.attributes &= ~NS_QUERYATTR_RECURSING;
+ dns_resolver_destroyfetch(&devent->fetch);
+
+ /*
+ * If this client is shutting down, or this transaction
+ * has timed out, do not resume the find.
+ */
+ client_shuttingdown = ns_client_shuttingdown(client);
+ if (fetch_cancelled || client_shuttingdown) {
+ if (devent->node != NULL)
+ dns_db_detachnode(devent->db, &devent->node);
+ if (devent->db != NULL)
+ dns_db_detach(&devent->db);
+ query_putrdataset(client, &devent->rdataset);
+ if (devent->sigrdataset != NULL)
+ query_putrdataset(client, &devent->sigrdataset);
+ isc_event_free(&event);
+ if (fetch_cancelled)
+ query_error(client, DNS_R_SERVFAIL);
+ else
+ query_next(client, ISC_R_CANCELED);
+ /*
+ * This may destroy the client.
+ */
+ ns_client_detach(&client);
+ } else {
+ query_find(client, devent, 0);
+ }
+}
+
+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)
+{
+ isc_result_t result;
+ dns_rdataset_t *rdataset, *sigrdataset;
+ isc_sockaddr_t *peeraddr;
+
+ if (!resuming)
+ inc_stats(client, dns_nsstatscounter_recursion);
+
+ /*
+ * We are about to recurse, which means that this client will
+ * be unavailable for serving new requests for an indeterminate
+ * amount of time. If this client is currently responsible
+ * for handling incoming queries, set up a new client
+ * object to handle them while we are waiting for a
+ * response. There is no need to replace TCP clients
+ * because those have already been replaced when the
+ * connection was accepted (if allowed by the TCP quota).
+ */
+ if (client->recursionquota == NULL) {
+ result = isc_quota_attach(&ns_g_server->recursionquota,
+ &client->recursionquota);
+ if (result == ISC_R_SOFTQUOTA) {
+ static isc_stdtime_t last = 0;
+ isc_stdtime_t now;
+ isc_stdtime_get(&now);
+ if (now != last) {
+ last = now;
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_WARNING,
+ "recursive-clients soft limit "
+ "exceeded, aborting oldest query");
+ }
+ ns_client_killoldestquery(client);
+ result = ISC_R_SUCCESS;
+ } else if (result == ISC_R_QUOTA) {
+ static isc_stdtime_t last = 0;
+ isc_stdtime_t now;
+ isc_stdtime_get(&now);
+ if (now != last) {
+ last = now;
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_WARNING,
+ "no more recursive clients: %s",
+ isc_result_totext(result));
+ }
+ ns_client_killoldestquery(client);
+ }
+ if (result == ISC_R_SUCCESS && !client->mortal &&
+ (client->attributes & NS_CLIENTATTR_TCP) == 0) {
+ result = ns_client_replace(client);
+ if (result != ISC_R_SUCCESS) {
+ ns_client_log(client, NS_LOGCATEGORY_CLIENT,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_WARNING,
+ "ns_client_replace() failed: %s",
+ isc_result_totext(result));
+ isc_quota_detach(&client->recursionquota);
+ }
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ ns_client_recursing(client);
+ }
+
+ /*
+ * Invoke the resolver.
+ */
+ REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);
+ REQUIRE(client->query.fetch == NULL);
+
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL)
+ return (ISC_R_NOMEMORY);
+ if (WANTDNSSEC(client)) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL) {
+ query_putrdataset(client, &rdataset);
+ return (ISC_R_NOMEMORY);
+ }
+ } else
+ sigrdataset = NULL;
+
+ if (client->query.timerset == ISC_FALSE)
+ ns_client_settimeout(client, 60);
+ if ((client->attributes & NS_CLIENTATTR_TCP) == 0)
+ peeraddr = &client->peeraddr;
+ else
+ peeraddr = NULL;
+ result = dns_resolver_createfetch2(client->view->resolver,
+ client->query.qname,
+ qtype, qdomain, nameservers,
+ NULL, peeraddr, client->message->id,
+ client->query.fetchoptions,
+ client->task,
+ query_resume, client,
+ rdataset, sigrdataset,
+ &client->query.fetch);
+
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Record that we're waiting for an event. A client which
+ * is shutting down will not be destroyed until all the
+ * events have been received.
+ */
+ } else {
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ }
+
+ return (result);
+}
+
+#define MAX_RESTARTS 16
+
+#define QUERY_ERROR(r) \
+do { \
+ eresult = r; \
+ want_restart = ISC_FALSE; \
+} while (0)
+
+/*
+ * Extract a network address from the RDATA of an A or AAAA
+ * record.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOTIMPLEMENTED The rdata is not a known address type.
+ */
+static isc_result_t
+rdata_tonetaddr(const dns_rdata_t *rdata, isc_netaddr_t *netaddr) {
+ struct in_addr ina;
+ struct in6_addr in6a;
+
+ switch (rdata->type) {
+ case dns_rdatatype_a:
+ INSIST(rdata->length == 4);
+ memcpy(&ina.s_addr, rdata->data, 4);
+ isc_netaddr_fromin(netaddr, &ina);
+ return (ISC_R_SUCCESS);
+ case dns_rdatatype_aaaa:
+ INSIST(rdata->length == 16);
+ memcpy(in6a.s6_addr, rdata->data, 16);
+ isc_netaddr_fromin6(netaddr, &in6a);
+ return (ISC_R_SUCCESS);
+ default:
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+}
+
+/*
+ * Find the sort order of 'rdata' in the topology-like
+ * ACL forming the second element in a 2-element top-level
+ * sortlist statement.
+ */
+static int
+query_sortlist_order_2element(const dns_rdata_t *rdata, const void *arg) {
+ isc_netaddr_t netaddr;
+
+ if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
+ return (INT_MAX);
+ return (ns_sortlist_addrorder2(&netaddr, arg));
+}
+
+/*
+ * Find the sort order of 'rdata' in the matching element
+ * of a 1-element top-level sortlist statement.
+ */
+static int
+query_sortlist_order_1element(const dns_rdata_t *rdata, const void *arg) {
+ isc_netaddr_t netaddr;
+
+ if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)
+ return (INT_MAX);
+ return (ns_sortlist_addrorder1(&netaddr, arg));
+}
+
+/*
+ * Find the sortlist statement that applies to 'client' and set up
+ * the sortlist info in in client->message appropriately.
+ */
+static void
+setup_query_sortlist(ns_client_t *client) {
+ isc_netaddr_t netaddr;
+ dns_rdatasetorderfunc_t order = NULL;
+ const void *order_arg = NULL;
+
+ isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
+ switch (ns_sortlist_setup(client->view->sortlist,
+ &netaddr, &order_arg)) {
+ case NS_SORTLISTTYPE_1ELEMENT:
+ order = query_sortlist_order_1element;
+ break;
+ case NS_SORTLISTTYPE_2ELEMENT:
+ order = query_sortlist_order_2element;
+ break;
+ case NS_SORTLISTTYPE_NONE:
+ order = NULL;
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+ dns_message_setsortorder(client->message, order, order_arg);
+}
+
+static void
+query_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {
+ isc_buffer_t *dbuf, b;
+ dns_name_t *fname;
+ dns_rdataset_t *neg, *negsig;
+ isc_result_t result = ISC_R_NOMEMORY;
+
+ CTRACE("query_addnoqnameproof");
+
+ fname = NULL;
+ neg = NULL;
+ negsig = NULL;
+
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ neg = query_newrdataset(client);
+ negsig = query_newrdataset(client);
+ if (fname == NULL || neg == NULL || negsig == NULL)
+ goto cleanup;
+
+ result = dns_rdataset_getnoqname(rdataset, fname, neg, negsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ query_addrrset(client, &fname, &neg, &negsig, dbuf,
+ DNS_SECTION_AUTHORITY);
+
+ if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) == 0)
+ goto cleanup;
+
+ if (fname == NULL) {
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL)
+ goto cleanup;
+ fname = query_newname(client, dbuf, &b);
+ }
+ if (neg == NULL)
+ neg = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(neg))
+ dns_rdataset_disassociate(neg);
+ if (negsig == NULL)
+ negsig = query_newrdataset(client);
+ else if (dns_rdataset_isassociated(negsig))
+ dns_rdataset_disassociate(negsig);
+ if (fname == NULL || neg == NULL || negsig == NULL)
+ goto cleanup;
+ result = dns_rdataset_getclosest(rdataset, fname, neg, negsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ query_addrrset(client, &fname, &neg, &negsig, dbuf,
+ DNS_SECTION_AUTHORITY);
+
+ cleanup:
+ if (neg != NULL)
+ query_putrdataset(client, &neg);
+ if (negsig != NULL)
+ query_putrdataset(client, &negsig);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+}
+
+static inline void
+answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {
+ dns_name_t *name;
+ dns_message_t *msg;
+ dns_section_t section = DNS_SECTION_ADDITIONAL;
+ dns_rdataset_t *rdataset = NULL;
+
+ msg = client->message;
+ for (name = ISC_LIST_HEAD(msg->sections[section]);
+ name != NULL;
+ name = ISC_LIST_NEXT(name, link))
+ if (dns_name_equal(name, client->query.qname)) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ if (rdataset->type == qtype)
+ break;
+ break;
+ }
+ if (rdataset != NULL) {
+ ISC_LIST_UNLINK(msg->sections[section], name, link);
+ ISC_LIST_PREPEND(msg->sections[section], name, link);
+ ISC_LIST_UNLINK(name->list, rdataset, link);
+ ISC_LIST_PREPEND(name->list, rdataset, link);
+ rdataset->attributes |= DNS_RDATASETATTR_REQUIREDGLUE;
+ }
+}
+
+#define NS_NAME_INIT(A,B) \
+ { \
+ DNS_NAME_MAGIC, \
+ A, sizeof(A), sizeof(B), \
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \
+ B, NULL, { (void *)-1, (void *)-1}, \
+ {NULL, NULL} \
+ }
+
+static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
+static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
+static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
+
+static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
+
+static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
+
+static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
+
+static dns_name_t rfc1918names[] = {
+ NS_NAME_INIT(inaddr10, inaddr10_offsets),
+ NS_NAME_INIT(inaddr16172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr17172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr18172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr19172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr20172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr21172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr22172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr23172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr24172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr25172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr26172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr27172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr28172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr29172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr30172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr31172, inaddr172_offsets),
+ NS_NAME_INIT(inaddr168192, inaddr192_offsets)
+};
+
+
+static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
+static unsigned char hostmaster_data[] = "\012hostmaster\014root-servers\003org";
+
+static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
+static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
+
+static dns_name_t prisoner = NS_NAME_INIT(prisoner_data, prisoner_offsets);
+static dns_name_t hostmaster = NS_NAME_INIT(hostmaster_data, hostmaster_offsets);
+
+static void
+warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
+ unsigned int i;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_soa_t soa;
+ dns_rdataset_t found;
+ isc_result_t result;
+
+ for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) {
+ if (dns_name_issubdomain(fname, &rfc1918names[i])) {
+ dns_rdataset_init(&found);
+ result = dns_ncache_getrdataset(rdataset,
+ &rfc1918names[i],
+ dns_rdatatype_soa,
+ &found);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ result = dns_rdataset_first(&found);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(&found, &rdata);
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ if (result != ISC_R_SUCCESS)
+ return;
+ if (dns_name_equal(&soa.origin, &prisoner) &&
+ dns_name_equal(&soa.contact, &hostmaster)) {
+ char buf[DNS_NAME_FORMATSIZE];
+ dns_name_format(fname, buf, sizeof(buf));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY,
+ ISC_LOG_WARNING,
+ "RFC 1918 response from "
+ "Internet for %s", buf);
+ }
+ dns_rdataset_disassociate(&found);
+ return;
+ }
+ }
+}
+
+static void
+query_findclosestnsec3(dns_name_t *qname, dns_db_t *db,
+ dns_dbversion_t *version, ns_client_t *client,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_name_t *fname, isc_boolean_t exact,
+ dns_name_t *found)
+{
+ unsigned char salt[256];
+ size_t salt_length = sizeof(salt);
+ isc_uint16_t iterations;
+ isc_result_t result;
+ unsigned int dboptions;
+ dns_fixedname_t fixed;
+ dns_hash_t hash;
+ dns_name_t name;
+ int order;
+ unsigned int count;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_boolean_t optout;
+
+ salt_length = sizeof(salt);
+ result = dns_db_getnsec3parameters(db, version, &hash, NULL,
+ &iterations, salt, &salt_length);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ dns_name_init(&name, NULL);
+ dns_name_clone(qname, &name);
+
+ /*
+ * Map unknown algorithm to known value.
+ */
+ if (hash == DNS_NSEC3_UNKNOWNALG)
+ hash = 1;
+
+ again:
+ dns_fixedname_init(&fixed);
+ result = dns_nsec3_hashname(&fixed, NULL, NULL, &name,
+ dns_db_origin(db), hash,
+ iterations, salt, salt_length);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ dboptions = client->query.dboptions | DNS_DBFIND_FORCENSEC3;
+ result = dns_db_find(db, dns_fixedname_name(&fixed), version,
+ 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 (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;
+}
+
+/*
+ * Do the bulk of query processing for the current query of 'client'.
+ * If 'event' is non-NULL, we are returning from recursion and 'qtype'
+ * is ignored. Otherwise, 'qtype' is the query type.
+ */
+static void
+query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
+{
+ dns_db_t *db, *zdb;
+ dns_dbnode_t *node;
+ dns_rdatatype_t type;
+ dns_name_t *fname, *zfname, *tname, *prefix;
+ dns_rdataset_t *rdataset, *trdataset;
+ dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset;
+ dns_rdataset_t **sigrdatasetp;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatasetiter_t *rdsiter;
+ isc_boolean_t want_restart, authoritative, is_zone, need_wildcardproof;
+ unsigned int n, nlabels;
+ dns_namereln_t namereln;
+ int order;
+ isc_buffer_t *dbuf;
+ isc_buffer_t b;
+ isc_result_t result, eresult;
+ dns_fixedname_t fixed;
+ dns_fixedname_t wildcardname;
+ dns_dbversion_t *version, *zversion;
+ dns_zone_t *zone;
+ dns_rdata_cname_t cname;
+ dns_rdata_dname_t dname;
+ unsigned int options;
+ isc_boolean_t empty_wild;
+ dns_rdataset_t *noqname;
+ isc_boolean_t resuming;
+
+ CTRACE("query_find");
+
+ /*
+ * One-time initialization.
+ *
+ * It's especially important to initialize anything that the cleanup
+ * code might cleanup.
+ */
+
+ eresult = ISC_R_SUCCESS;
+ fname = NULL;
+ zfname = NULL;
+ rdataset = NULL;
+ zrdataset = NULL;
+ sigrdataset = NULL;
+ zsigrdataset = NULL;
+ zversion = NULL;
+ node = NULL;
+ db = NULL;
+ zdb = NULL;
+ version = NULL;
+ zone = NULL;
+ need_wildcardproof = ISC_FALSE;
+ empty_wild = ISC_FALSE;
+ options = 0;
+ resuming = ISC_FALSE;
+ is_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;
+ 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;
+
+ /*
+ * We'll need some resources...
+ */
+ 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;
+ }
+ 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;
+ resuming = ISC_TRUE;
+
+ goto resume;
+ }
+
+ /*
+ * Not returning from recursion.
+ */
+
+ /*
+ * If it's a SIG query, we'll iterate the node.
+ */
+ if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
+ type = dns_rdatatype_any;
+ else
+ type = qtype;
+
+ restart:
+ CTRACE("query_find: restart");
+ want_restart = ISC_FALSE;
+ authoritative = ISC_FALSE;
+ version = NULL;
+ need_wildcardproof = ISC_FALSE;
+
+ if (client->view->checknames &&
+ !dns_rdata_checkowner(client->query.qname,
+ client->message->rdclass,
+ qtype, ISC_FALSE)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typename[DNS_RDATATYPE_FORMATSIZE];
+ char classname[DNS_RDATACLASS_FORMATSIZE];
+
+ dns_name_format(client->query.qname, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(qtype, typename, sizeof(typename));
+ dns_rdataclass_format(client->message->rdclass, classname,
+ sizeof(classname));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_QUERY, ISC_LOG_ERROR,
+ "check-names failure %s/%s/%s", namebuf,
+ typename, classname);
+ QUERY_ERROR(DNS_R_REFUSED);
+ goto cleanup;
+ }
+
+ /*
+ * First we must find the right database.
+ */
+ options &= DNS_GETDB_NOLOG; /* Preserve DNS_GETDB_NOLOG. */
+ if (dns_rdatatype_atparent(qtype) &&
+ !dns_name_equal(client->query.qname, dns_rootname))
+ options |= DNS_GETDB_NOEXACT;
+ result = query_getdb(client, client->query.qname, qtype, options,
+ &zone, &db, &version, &is_zone);
+ if ((result != ISC_R_SUCCESS || !is_zone) && !RECURSIONOK(client) &&
+ (options & DNS_GETDB_NOEXACT) != 0 && qtype == dns_rdatatype_ds) {
+ /*
+ * Look to see if we are authoritative for the
+ * child zone if the query type is DS.
+ */
+ dns_db_t *tdb = NULL;
+ dns_zone_t *tzone = NULL;
+ dns_dbversion_t *tversion = NULL;
+ isc_result_t tresult;
+
+ tresult = query_getzonedb(client, client->query.qname, qtype,
+ DNS_GETDB_PARTIAL, &tzone, &tdb,
+ &tversion);
+ if (tresult == ISC_R_SUCCESS) {
+ options &= ~DNS_GETDB_NOEXACT;
+ query_putrdataset(client, &rdataset);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ version = tversion;
+ db = tdb;
+ zone = tzone;
+ is_zone = ISC_TRUE;
+ result = ISC_R_SUCCESS;
+ } else {
+ if (tdb != NULL)
+ dns_db_detach(&tdb);
+ if (tzone != NULL)
+ dns_zone_detach(&tzone);
+ }
+ }
+ if (result != ISC_R_SUCCESS) {
+ if (result == DNS_R_REFUSED) {
+ if (WANTRECURSION(client)) {
+ inc_stats(client,
+ dns_nsstatscounter_recurserej);
+ } else
+ inc_stats(client, dns_nsstatscounter_authrej);
+ if (!PARTIALANSWER(client))
+ QUERY_ERROR(DNS_R_REFUSED);
+ } else
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+
+ if (is_zone)
+ authoritative = ISC_TRUE;
+
+ if (event == NULL && client->query.restarts == 0) {
+ if (is_zone) {
+#ifdef DLZ
+ if (zone != NULL) {
+ /*
+ * if is_zone = true, zone = NULL then this is
+ * a DLZ zone. Don't attempt to attach zone.
+ */
+#endif
+ dns_zone_attach(zone, &client->query.authzone);
+#ifdef DLZ
+ }
+#endif
+ dns_db_attach(db, &client->query.authdb);
+ }
+ client->query.authdbset = ISC_TRUE;
+ }
+
+ db_find:
+ CTRACE("query_find: db_find");
+ /*
+ * We'll need some resources...
+ */
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ fname = query_newname(client, dbuf, &b);
+ rdataset = query_newrdataset(client);
+ if (fname == NULL || rdataset == NULL) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ if (WANTDNSSEC(client) && (!is_zone || dns_db_issecure(db))) {
+ sigrdataset = query_newrdataset(client);
+ if (sigrdataset == NULL) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Now look for an answer in the database.
+ */
+ result = dns_db_find(db, client->query.qname, version, type,
+ client->query.dboptions, client->now,
+ &node, fname, rdataset, sigrdataset);
+
+ resume:
+ CTRACE("query_find: resume");
+ switch (result) {
+ case ISC_R_SUCCESS:
+ /*
+ * This case is handled in the main line below.
+ */
+ break;
+ case DNS_R_GLUE:
+ case DNS_R_ZONECUT:
+ /*
+ * These cases are handled in the main line below.
+ */
+ INSIST(is_zone);
+ authoritative = ISC_FALSE;
+ break;
+ case ISC_R_NOTFOUND:
+ /*
+ * The cache doesn't even have the root NS. Get them from
+ * the hints DB.
+ */
+ INSIST(!is_zone);
+ if (db != NULL)
+ dns_db_detach(&db);
+
+ if (client->view->hints == NULL) {
+ /* We have no hints. */
+ result = ISC_R_FAILURE;
+ } else {
+ dns_db_attach(client->view->hints, &db);
+ result = dns_db_find(db, dns_rootname,
+ NULL, dns_rdatatype_ns,
+ 0, client->now, &node, fname,
+ rdataset, sigrdataset);
+ }
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * Nonsensical root hints may require cleanup.
+ */
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+
+ /*
+ * We don't have any root server hints, but
+ * we may have working forwarders, so try to
+ * recurse anyway.
+ */
+ if (RECURSIONOK(client)) {
+ result = query_recurse(client, qtype,
+ NULL, NULL, resuming);
+ if (result == ISC_R_SUCCESS)
+ client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ else if (result == DNS_R_DUPLICATE ||
+ result == DNS_R_DROP) {
+ /* Duplicate query. */
+ QUERY_ERROR(result);
+ } else {
+ /* Unable to recurse. */
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ }
+ goto cleanup;
+ } else {
+ /* Unable to give root server referral. */
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ }
+ /*
+ * XXXRTH We should trigger root server priming here.
+ */
+ /* FALLTHROUGH */
+ case DNS_R_DELEGATION:
+ authoritative = ISC_FALSE;
+ if (is_zone) {
+ /*
+ * Look to see if we are authoritative for the
+ * child zone if the query type is DS.
+ */
+ if (!RECURSIONOK(client) &&
+ (options & DNS_GETDB_NOEXACT) != 0 &&
+ qtype == dns_rdatatype_ds) {
+ dns_db_t *tdb = NULL;
+ dns_zone_t *tzone = NULL;
+ dns_dbversion_t *tversion = NULL;
+ result = query_getzonedb(client,
+ client->query.qname,
+ qtype,
+ DNS_GETDB_PARTIAL,
+ &tzone, &tdb,
+ &tversion);
+ if (result == ISC_R_SUCCESS) {
+ options &= ~DNS_GETDB_NOEXACT;
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client,
+ &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client,
+ &fname);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ version = tversion;
+ db = tdb;
+ zone = tzone;
+ authoritative = ISC_TRUE;
+ goto db_find;
+ }
+ if (tdb != NULL)
+ dns_db_detach(&tdb);
+ if (tzone != NULL)
+ dns_zone_detach(&tzone);
+ }
+ /*
+ * We're authoritative for an ancestor of QNAME.
+ */
+ if (!USECACHE(client) || !RECURSIONOK(client)) {
+ dns_fixedname_t fixed;
+
+ dns_fixedname_init(&fixed);
+ dns_name_copy(fname,
+ dns_fixedname_name(&fixed), NULL);
+
+ /*
+ * If we don't have a cache, this is the best
+ * answer.
+ *
+ * If the client is making a nonrecursive
+ * query we always give out the authoritative
+ * delegation. This way even if we get
+ * junk in our cache, we won't fail in our
+ * role as the delegating authority if another
+ * nameserver asks us about a delegated
+ * subzone.
+ *
+ * We enable the retrieval of glue for this
+ * database by setting client->query.gluedb.
+ */
+ client->query.gluedb = db;
+ client->query.isreferral = ISC_TRUE;
+ /*
+ * We must ensure NOADDITIONAL is off,
+ * because the generation of
+ * additional data is required in
+ * delegations.
+ */
+ client->query.attributes &=
+ ~NS_QUERYATTR_NOADDITIONAL;
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ query_addrrset(client, &fname,
+ &rdataset, sigrdatasetp,
+ dbuf, DNS_SECTION_AUTHORITY);
+ client->query.gluedb = NULL;
+ if (WANTDNSSEC(client))
+ query_addds(client, db, node, version,
+ dns_fixedname_name(&fixed));
+ } else {
+ /*
+ * We might have a better answer or delegation
+ * in the cache. We'll remember the current
+ * values of fname, rdataset, and sigrdataset.
+ * We'll then go looking for QNAME in the
+ * cache. If we find something better, we'll
+ * use it instead.
+ */
+ query_keepname(client, fname, dbuf);
+ zdb = db;
+ zfname = fname;
+ fname = NULL;
+ zrdataset = rdataset;
+ rdataset = NULL;
+ zsigrdataset = sigrdataset;
+ sigrdataset = NULL;
+ dns_db_detachnode(db, &node);
+ zversion = version;
+ version = NULL;
+ db = NULL;
+ dns_db_attach(client->view->cachedb, &db);
+ is_zone = ISC_FALSE;
+ goto db_find;
+ }
+ } else {
+ if (zfname != NULL &&
+ !dns_name_issubdomain(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.
+ */
+ query_releasename(client, &fname);
+ fname = zfname;
+ zfname = NULL;
+ /*
+ * We've already done query_keepname() on
+ * zfname, so we must set dbuf to NULL to
+ * prevent query_addrrset() from trying to
+ * call query_keepname() again.
+ */
+ dbuf = NULL;
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client,
+ &sigrdataset);
+ rdataset = zrdataset;
+ zrdataset = NULL;
+ sigrdataset = zsigrdataset;
+ zsigrdataset = NULL;
+ version = zversion;
+ zversion = NULL;
+ /*
+ * We don't clean up zdb here because we
+ * may still need it. It will get cleaned
+ * up by the main cleanup code.
+ */
+ }
+
+ if (RECURSIONOK(client)) {
+ /*
+ * Recurse!
+ */
+ if (dns_rdatatype_atparent(type))
+ result = query_recurse(client, qtype,
+ NULL, NULL,
+ resuming);
+ else
+ result = query_recurse(client, qtype,
+ fname, rdataset,
+ resuming);
+ if (result == ISC_R_SUCCESS)
+ client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ else if (result == DNS_R_DUPLICATE ||
+ result == DNS_R_DROP)
+ QUERY_ERROR(result);
+ else
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ } else {
+ dns_fixedname_t fixed;
+
+ dns_fixedname_init(&fixed);
+ dns_name_copy(fname,
+ dns_fixedname_name(&fixed), NULL);
+ /*
+ * This is the best answer.
+ */
+ client->query.attributes |=
+ NS_QUERYATTR_CACHEGLUEOK;
+ client->query.gluedb = zdb;
+ client->query.isreferral = ISC_TRUE;
+ /*
+ * We must ensure NOADDITIONAL is off,
+ * because the generation of
+ * additional data is required in
+ * delegations.
+ */
+ client->query.attributes &=
+ ~NS_QUERYATTR_NOADDITIONAL;
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ query_addrrset(client, &fname,
+ &rdataset, sigrdatasetp,
+ dbuf, DNS_SECTION_AUTHORITY);
+ client->query.gluedb = NULL;
+ client->query.attributes &=
+ ~NS_QUERYATTR_CACHEGLUEOK;
+ if (WANTDNSSEC(client))
+ query_addds(client, db, node, version,
+ dns_fixedname_name(&fixed));
+ }
+ }
+ goto cleanup;
+ case DNS_R_EMPTYNAME:
+ result = DNS_R_NXRRSET;
+ /* FALLTHROUGH */
+ case DNS_R_NXRRSET:
+ INSIST(is_zone);
+ /*
+ * Look for a NSEC3 record if we don't have a NSEC record.
+ */
+ if (!dns_rdataset_isassociated(rdataset) &&
+ WANTDNSSEC(client)) {
+ if ((fname->attributes & DNS_NAMEATTR_WILDCARD) == 0) {
+ dns_name_t *found;
+ dns_name_t *qname;
+
+ dns_fixedname_init(&fixed);
+ found = dns_fixedname_name(&fixed);
+ qname = client->query.qname;
+
+ query_findclosestnsec3(qname, db, version,
+ client, rdataset,
+ sigrdataset, fname,
+ ISC_TRUE, found);
+ /*
+ * Did we find the closest provable encloser
+ * instead? If so add the nearest to the
+ * closest provable encloser.
+ */
+ if (found &&
+ dns_rdataset_isassociated(rdataset) &&
+ !dns_name_equal(qname, found))
+ {
+ unsigned int count;
+ unsigned int skip;
+
+ /*
+ * Add the closest provable encloser.
+ */
+ query_addrrset(client, &fname,
+ &rdataset, &sigrdataset,
+ dbuf,
+ DNS_SECTION_AUTHORITY);
+
+ count = dns_name_countlabels(found)
+ + 1;
+ skip = dns_name_countlabels(qname) -
+ count;
+ dns_name_getlabelsequence(qname, skip,
+ count,
+ found);
+
+ fixfname(client, &fname, &dbuf, &b);
+ fixrdataset(client, &rdataset);
+ fixrdataset(client, &sigrdataset);
+ if (fname == NULL ||
+ rdataset == NULL ||
+ sigrdataset == NULL) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ /*
+ * 'nearest' doesn't exist so
+ * 'exist' is set to ISC_FALSE.
+ */
+ query_findclosestnsec3(found, db,
+ version,
+ client,
+ rdataset,
+ sigrdataset,
+ fname,
+ ISC_FALSE,
+ NULL);
+ }
+ } else {
+ query_releasename(client, &fname);
+ query_addwildcardproof(client, db, version,
+ client->query.qname,
+ ISC_FALSE);
+ }
+ }
+ if (dns_rdataset_isassociated(rdataset)) {
+ /*
+ * If we've got a NSEC record, we need to save the
+ * name now because we're going call query_addsoa()
+ * below, and it needs to use the name buffer.
+ */
+ query_keepname(client, fname, dbuf);
+ } else if (fname != NULL) {
+ /*
+ * We're not going to use fname, and need to release
+ * our hold on the name buffer so query_addsoa()
+ * may use it.
+ */
+ query_releasename(client, &fname);
+ }
+ /*
+ * Add SOA.
+ */
+ result = query_addsoa(client, db, version, ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ QUERY_ERROR(result);
+ goto cleanup;
+ }
+ /*
+ * Add NSEC record if we found one.
+ */
+ if (WANTDNSSEC(client)) {
+ if (dns_rdataset_isassociated(rdataset))
+ query_addnxrrsetnsec(client, db, version,
+ &fname, &rdataset,
+ &sigrdataset);
+ }
+ goto cleanup;
+
+ case DNS_R_EMPTYWILD:
+ empty_wild = ISC_TRUE;
+ /* FALLTHROUGH */
+
+ case DNS_R_NXDOMAIN:
+ INSIST(is_zone);
+ if (dns_rdataset_isassociated(rdataset)) {
+ /*
+ * If we've got a NSEC record, we need to save the
+ * name now because we're going call query_addsoa()
+ * below, and it needs to use the name buffer.
+ */
+ query_keepname(client, fname, dbuf);
+ } else if (fname != NULL) {
+ /*
+ * We're not going to use fname, and need to release
+ * our hold on the name buffer so query_addsoa()
+ * may use it.
+ */
+ query_releasename(client, &fname);
+ }
+ /*
+ * Add SOA. If the query was for a SOA record force the
+ * ttl to zero so that it is possible for clients to find
+ * the containing zone of an arbitrary name with a stub
+ * resolver and not have it cached.
+ */
+ if (qtype == dns_rdatatype_soa &&
+#ifdef DLZ
+ zone != NULL &&
+#endif
+ dns_zone_getzeronosoattl(zone))
+ result = query_addsoa(client, db, version, ISC_TRUE);
+ else
+ result = query_addsoa(client, db, version, ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ QUERY_ERROR(result);
+ goto cleanup;
+ }
+
+ if (WANTDNSSEC(client)) {
+ /*
+ * Add NSEC record if we found one.
+ */
+ if (dns_rdataset_isassociated(rdataset))
+ query_addrrset(client, &fname, &rdataset,
+ &sigrdataset,
+ NULL, DNS_SECTION_AUTHORITY);
+ query_addwildcardproof(client, db, version,
+ client->query.qname, ISC_FALSE);
+ }
+
+ /*
+ * Set message rcode.
+ */
+ if (empty_wild)
+ client->message->rcode = dns_rcode_noerror;
+ else
+ client->message->rcode = dns_rcode_nxdomain;
+ goto cleanup;
+
+ case DNS_R_NCACHENXDOMAIN:
+ case DNS_R_NCACHENXRRSET:
+ INSIST(!is_zone);
+ authoritative = ISC_FALSE;
+ /*
+ * Set message rcode, if required.
+ */
+ if (result == DNS_R_NCACHENXDOMAIN)
+ client->message->rcode = dns_rcode_nxdomain;
+ /*
+ * Look for RFC 1918 leakage from Internet.
+ */
+ if (result == DNS_R_NCACHENXDOMAIN &&
+ qtype == dns_rdatatype_ptr &&
+ client->message->rdclass == dns_rdataclass_in &&
+ dns_name_countlabels(fname) == 7)
+ warn_rfc1918(client, fname, rdataset);
+ /*
+ * We don't call query_addrrset() because we don't need any
+ * of its extra features (and things would probably break!).
+ */
+ query_keepname(client, fname, dbuf);
+ dns_message_addname(client->message, fname,
+ DNS_SECTION_AUTHORITY);
+ ISC_LIST_APPEND(fname->list, rdataset, link);
+ fname = NULL;
+ rdataset = NULL;
+ goto cleanup;
+
+ case DNS_R_CNAME:
+ /*
+ * Keep a copy of the rdataset. We have to do this because
+ * query_addrrset may clear 'rdataset' (to prevent the
+ * cleanup code from cleaning it up).
+ */
+ trdataset = rdataset;
+ /*
+ * Add the CNAME to the answer section.
+ */
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ if (WANTDNSSEC(client) &&
+ (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
+ {
+ dns_fixedname_init(&wildcardname);
+ dns_name_copy(fname, dns_fixedname_name(&wildcardname),
+ NULL);
+ need_wildcardproof = ISC_TRUE;
+ }
+ if (NOQNAME(rdataset) && WANTDNSSEC(client))
+ noqname = rdataset;
+ else
+ noqname = NULL;
+ query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
+ DNS_SECTION_ANSWER);
+ if (noqname != NULL)
+ query_addnoqnameproof(client, noqname);
+ /*
+ * We set the PARTIALANSWER attribute so that if anything goes
+ * wrong later on, we'll return what we've got so far.
+ */
+ client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
+ /*
+ * Reset qname to be the target name of the CNAME and restart
+ * the query.
+ */
+ tname = NULL;
+ result = dns_message_gettempname(client->message, &tname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_rdataset_first(trdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ dns_rdataset_current(trdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ dns_name_init(tname, NULL);
+ result = dns_name_dup(&cname.cname, client->mctx, tname);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &tname);
+ dns_rdata_freestruct(&cname);
+ goto cleanup;
+ }
+ dns_rdata_freestruct(&cname);
+ ns_client_qnamereplace(client, tname);
+ want_restart = ISC_TRUE;
+ if (!WANTRECURSION(client))
+ options |= DNS_GETDB_NOLOG;
+ goto addauth;
+ case DNS_R_DNAME:
+ /*
+ * Compare the current qname to the found name. We need
+ * to know how many labels and bits are in common because
+ * we're going to have to split qname later on.
+ */
+ namereln = dns_name_fullcompare(client->query.qname, fname,
+ &order, &nlabels);
+ INSIST(namereln == dns_namereln_subdomain);
+ /*
+ * Keep a copy of the rdataset. We have to do this because
+ * query_addrrset may clear 'rdataset' (to prevent the
+ * cleanup code from cleaning it up).
+ */
+ trdataset = rdataset;
+ /*
+ * Add the DNAME to the answer section.
+ */
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ if (WANTDNSSEC(client) &&
+ (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
+ {
+ dns_fixedname_init(&wildcardname);
+ dns_name_copy(fname, dns_fixedname_name(&wildcardname),
+ NULL);
+ need_wildcardproof = ISC_TRUE;
+ }
+ query_addrrset(client, &fname, &rdataset, sigrdatasetp, dbuf,
+ DNS_SECTION_ANSWER);
+ /*
+ * We set the PARTIALANSWER attribute so that if anything goes
+ * wrong later on, we'll return what we've got so far.
+ */
+ client->query.attributes |= NS_QUERYATTR_PARTIALANSWER;
+ /*
+ * Get the target name of the DNAME.
+ */
+ tname = NULL;
+ result = dns_message_gettempname(client->message, &tname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_rdataset_first(trdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ dns_rdataset_current(trdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &dname, NULL);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS) {
+ 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.
+ */
+ dns_fixedname_init(&fixed);
+ prefix = dns_fixedname_name(&fixed);
+ dns_name_split(client->query.qname, nlabels, prefix, NULL);
+ INSIST(fname == NULL);
+ dbuf = query_getnamebuf(client);
+ if (dbuf == NULL) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ fname = query_newname(client, dbuf, &b);
+ if (fname == NULL) {
+ dns_message_puttempname(client->message, &tname);
+ goto cleanup;
+ }
+ result = dns_name_concatenate(prefix, tname, fname, NULL);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(client->message, &tname);
+ if (result == ISC_R_NOSPACE) {
+ /*
+ * RFC2672, section 4.1, subsection 3c says
+ * we should return YXDOMAIN if the constructed
+ * name would be too long.
+ */
+ client->message->rcode = dns_rcode_yxdomain;
+ }
+ goto cleanup;
+ }
+ query_keepname(client, fname, dbuf);
+ /*
+ * Synthesize a CNAME for this DNAME.
+ *
+ * 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.
+ *
+ * We do not try to synthesize a signature because we hope
+ * that security aware servers will understand DNAME. Also,
+ * even if we had an online key, making a signature
+ * 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->trust, &tname,
+ dns_rdatatype_cname);
+ if (tname != NULL)
+ dns_message_puttempname(client->message, &tname);
+ /*
+ * Switch to the new qname and restart.
+ */
+ ns_client_qnamereplace(client, fname);
+ fname = NULL;
+ want_restart = ISC_TRUE;
+ if (!WANTRECURSION(client))
+ options |= DNS_GETDB_NOLOG;
+ goto addauth;
+ default:
+ /*
+ * Something has gone wrong.
+ */
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+
+ if (WANTDNSSEC(client) &&
+ (fname->attributes & DNS_NAMEATTR_WILDCARD) != 0)
+ {
+ dns_fixedname_init(&wildcardname);
+ dns_name_copy(fname, dns_fixedname_name(&wildcardname), NULL);
+ need_wildcardproof = ISC_TRUE;
+ }
+
+ if (type == dns_rdatatype_any) {
+ /*
+ * XXXRTH Need to handle zonecuts with special case
+ * code.
+ */
+ n = 0;
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ /*
+ * Calling query_addrrset() with a non-NULL dbuf is going
+ * to either keep or release the name. We don't want it to
+ * release fname, since we may have to call query_addrrset()
+ * more than once. That means we have to call query_keepname()
+ * now, and pass a NULL dbuf to query_addrrset().
+ *
+ * If we do a query_addrrset() below, we must set fname to
+ * NULL before leaving this block, otherwise we might try to
+ * cleanup fname even though we're using it!
+ */
+ query_keepname(client, fname, dbuf);
+ tname = fname;
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, rdataset);
+ if (is_zone && qtype == dns_rdatatype_any &&
+ !dns_db_issecure(db) &&
+ dns_rdatatype_isdnssec(rdataset->type)) {
+ /*
+ * The zone is transitioning from insecure
+ * to secure. Hide the dnssec records from
+ * ANY queries.
+ */
+ dns_rdataset_disassociate(rdataset);
+ } else if ((qtype == dns_rdatatype_any ||
+ rdataset->type == qtype) && rdataset->type != 0) {
+ if (NOQNAME(rdataset) && WANTDNSSEC(client))
+ noqname = rdataset;
+ else
+ noqname = NULL;
+ query_addrrset(client,
+ fname != NULL ? &fname : &tname,
+ &rdataset, NULL,
+ NULL, DNS_SECTION_ANSWER);
+ if (noqname != NULL)
+ query_addnoqnameproof(client, noqname);
+ n++;
+ INSIST(tname != NULL);
+ /*
+ * rdataset is non-NULL only in certain
+ * pathological cases involving DNAMEs.
+ */
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ rdataset = query_newrdataset(client);
+ if (rdataset == NULL)
+ break;
+ } else {
+ /*
+ * We're not interested in this rdataset.
+ */
+ dns_rdataset_disassociate(rdataset);
+ }
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+
+ if (fname != NULL)
+ dns_message_puttempname(client->message, &fname);
+
+ if (n == 0 && is_zone) {
+ /*
+ * We didn't match any rdatasets.
+ */
+ if (qtype == dns_rdatatype_rrsig &&
+ result == ISC_R_NOMORE) {
+ /*
+ * XXXRTH If this is a secure zone and we
+ * didn't find any SIGs, we should generate
+ * an error unless we were searching for
+ * glue. Ugh.
+ */
+ if (!is_zone) {
+ authoritative = ISC_FALSE;
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (RECURSIONOK(client)) {
+ result = query_recurse(client,
+ qtype,
+ NULL,
+ NULL,
+ resuming);
+ if (result == ISC_R_SUCCESS)
+ client->query.attributes |=
+ NS_QUERYATTR_RECURSING;
+ else
+ QUERY_ERROR(DNS_R_SERVFAIL); }
+ goto addauth;
+ }
+ /*
+ * We were searching for SIG records in
+ * a nonsecure zone. Send a "no error,
+ * no data" response.
+ */
+ /*
+ * Add SOA.
+ */
+ result = query_addsoa(client, db, version,
+ ISC_FALSE);
+ if (result == ISC_R_SUCCESS)
+ result = ISC_R_NOMORE;
+ } else {
+ /*
+ * Something went wrong.
+ */
+ result = DNS_R_SERVFAIL;
+ }
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result != ISC_R_NOMORE) {
+ QUERY_ERROR(DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ } else {
+ /*
+ * This is the "normal" case -- an ordinary question to which
+ * we know the answer.
+ */
+ if (sigrdataset != NULL)
+ sigrdatasetp = &sigrdataset;
+ else
+ sigrdatasetp = NULL;
+ if (NOQNAME(rdataset) && WANTDNSSEC(client))
+ noqname = rdataset;
+ else
+ noqname = NULL;
+ /*
+ * BIND 8 priming queries need the additional section.
+ */
+ if (is_zone && qtype == dns_rdatatype_ns &&
+ 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 (noqname != NULL)
+ query_addnoqnameproof(client, noqname);
+ /*
+ * We shouldn't ever fail to add 'rdataset'
+ * because it's already in the answer.
+ */
+ INSIST(rdataset == NULL);
+ }
+
+ addauth:
+ CTRACE("query_find: addauth");
+ /*
+ * Add NS records to the authority section (if we haven't already
+ * added them to the answer section).
+ */
+ if (!want_restart && !NOAUTHORITY(client)) {
+ if (is_zone) {
+ if (!((qtype == dns_rdatatype_ns ||
+ qtype == dns_rdatatype_any) &&
+ dns_name_equal(client->query.qname,
+ dns_db_origin(db))))
+ (void)query_addns(client, db, version);
+ } else if (qtype != dns_rdatatype_ns) {
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ query_addbestns(client);
+ }
+ }
+
+ /*
+ * Add NSEC records to the authority section if they're needed for
+ * DNSSEC wildcard proofs.
+ */
+ if (need_wildcardproof && dns_db_issecure(db))
+ query_addwildcardproof(client, db, version,
+ dns_fixedname_name(&wildcardname),
+ ISC_TRUE);
+ cleanup:
+ CTRACE("query_find: cleanup");
+ /*
+ * General cleanup.
+ */
+ if (rdataset != NULL)
+ query_putrdataset(client, &rdataset);
+ if (sigrdataset != NULL)
+ query_putrdataset(client, &sigrdataset);
+ if (fname != NULL)
+ query_releasename(client, &fname);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ if (zdb != NULL) {
+ query_putrdataset(client, &zrdataset);
+ if (zsigrdataset != NULL)
+ query_putrdataset(client, &zsigrdataset);
+ if (zfname != NULL)
+ query_releasename(client, &zfname);
+ dns_db_detach(&zdb);
+ }
+ if (event != NULL)
+ isc_event_free(ISC_EVENT_PTR(&event));
+
+ /*
+ * AA bit.
+ */
+ if (client->query.restarts == 0 && !authoritative) {
+ /*
+ * We're not authoritative, so we must ensure the AA bit
+ * isn't set.
+ */
+ client->message->flags &= ~DNS_MESSAGEFLAG_AA;
+ }
+
+ /*
+ * Restart the query?
+ */
+ if (want_restart && client->query.restarts < MAX_RESTARTS) {
+ client->query.restarts++;
+ goto restart;
+ }
+
+ if (eresult != ISC_R_SUCCESS &&
+ (!PARTIALANSWER(client) || WANTRECURSION(client))) {
+ if (eresult == DNS_R_DUPLICATE || eresult == DNS_R_DROP) {
+ /*
+ * This was a duplicate query that we are
+ * recursing on. Don't send a response now.
+ * The original query will still cause a response.
+ */
+ query_next(client, eresult);
+ } else {
+ /*
+ * If we don't have any answer to give the client,
+ * or if the client requested recursion and thus wanted
+ * the complete answer, send an error response.
+ */
+ query_error(client, eresult);
+ }
+ ns_client_detach(&client);
+ } else if (!RECURSING(client)) {
+ /*
+ * We are done. Set up sortlist data for the message
+ * rendering code, make a final tweak to the AA bit if the
+ * auth-nxdomain config option says so, then render and
+ * send the response.
+ */
+ setup_query_sortlist(client);
+
+ /*
+ * If this is a referral and the answer to the question
+ * is in the glue sort it to the start of the additional
+ * section.
+ */
+ if (client->message->counts[DNS_SECTION_ANSWER] == 0 &&
+ client->message->rcode == dns_rcode_noerror &&
+ (qtype == dns_rdatatype_a || qtype == dns_rdatatype_aaaa))
+ answer_in_glue(client, qtype);
+
+ if (client->message->rcode == dns_rcode_nxdomain &&
+ client->view->auth_nxdomain == ISC_TRUE)
+ client->message->flags |= DNS_MESSAGEFLAG_AA;
+
+ query_send(client);
+ ns_client_detach(&client);
+ }
+ CTRACE("query_find: done");
+}
+
+static inline void
+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];
+ dns_rdataset_t *rdataset;
+ int level = ISC_LOG_INFO;
+
+ if (! isc_log_wouldlog(ns_g_lctx, level))
+ return;
+
+ rdataset = ISC_LIST_HEAD(client->query.qname->list);
+ INSIST(rdataset != NULL);
+ 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));
+
+ 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) ? "+" : "-",
+ (client->signer != NULL) ? "S": "",
+ (client->opt != NULL) ? "E" : "",
+ ((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "",
+ ((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "");
+}
+
+void
+ns_query_start(ns_client_t *client) {
+ isc_result_t result;
+ dns_message_t *message = client->message;
+ dns_rdataset_t *rdataset;
+ ns_client_t *qclient;
+ dns_rdatatype_t qtype;
+ unsigned int saved_extflags = client->extflags;
+ unsigned int saved_flags = client->message->flags;
+ isc_boolean_t want_ad;
+
+ CTRACE("ns_query_start");
+
+ /*
+ * Test only.
+ */
+ if (ns_g_clienttest && (client->attributes & NS_CLIENTATTR_TCP) == 0)
+ RUNTIME_CHECK(ns_client_replace(client) == ISC_R_SUCCESS);
+
+ /*
+ * Ensure that appropriate cleanups occur.
+ */
+ client->next = query_next_callback;
+
+ /*
+ * Behave as if we don't support DNSSEC if not enabled.
+ */
+ if (!client->view->enablednssec) {
+ message->flags &= ~DNS_MESSAGEFLAG_CD;
+ client->extflags &= ~DNS_MESSAGEEXTFLAG_DO;
+ if (client->opt != NULL)
+ client->opt->ttl &= ~DNS_MESSAGEEXTFLAG_DO;
+ }
+
+ if ((message->flags & DNS_MESSAGEFLAG_RD) != 0)
+ client->query.attributes |= NS_QUERYATTR_WANTRECURSION;
+
+ if ((client->extflags & DNS_MESSAGEEXTFLAG_DO) != 0)
+ client->attributes |= NS_CLIENTATTR_WANTDNSSEC;
+
+ if (client->view->minimalresponses)
+ client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
+ NS_QUERYATTR_NOADDITIONAL);
+
+ if ((client->view->cachedb == NULL)
+ || (!client->view->additionalfromcache)) {
+ /*
+ * We don't have a cache. Turn off cache support and
+ * recursion.
+ */
+ client->query.attributes &=
+ ~(NS_QUERYATTR_RECURSIONOK|NS_QUERYATTR_CACHEOK);
+ } else if ((client->attributes & NS_CLIENTATTR_RA) == 0 ||
+ (message->flags & DNS_MESSAGEFLAG_RD) == 0) {
+ /*
+ * If the client isn't allowed to recurse (due to
+ * "recursion no", the allow-recursion ACL, or the
+ * lack of a resolver in this view), or if it
+ * doesn't want recursion, turn recursion off.
+ */
+ client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
+ }
+
+ /*
+ * Get the question name.
+ */
+ result = dns_message_firstname(message, DNS_SECTION_QUESTION);
+ if (result != ISC_R_SUCCESS) {
+ query_error(client, result);
+ return;
+ }
+ dns_message_currentname(message, DNS_SECTION_QUESTION,
+ &client->query.qname);
+ client->query.origqname = client->query.qname;
+ result = dns_message_nextname(message, DNS_SECTION_QUESTION);
+ if (result != ISC_R_NOMORE) {
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * There's more than one QNAME in the question
+ * section.
+ */
+ query_error(client, DNS_R_FORMERR);
+ } else
+ query_error(client, result);
+ return;
+ }
+
+ if (ns_g_server->log_queries)
+ log_query(client, saved_flags, saved_extflags);
+
+ /*
+ * Check for multiple question queries, since edns1 is dead.
+ */
+ if (message->counts[DNS_SECTION_QUESTION] > 1) {
+ query_error(client, DNS_R_FORMERR);
+ return;
+ }
+
+ /*
+ * Check for meta-queries like IXFR and AXFR.
+ */
+ rdataset = ISC_LIST_HEAD(client->query.qname->list);
+ INSIST(rdataset != NULL);
+ qtype = rdataset->type;
+ dns_rdatatypestats_increment(ns_g_server->rcvquerystats, qtype);
+ if (dns_rdatatype_ismeta(qtype)) {
+ switch (qtype) {
+ case dns_rdatatype_any:
+ break; /* Let query_find handle it. */
+ case dns_rdatatype_ixfr:
+ case dns_rdatatype_axfr:
+ ns_xfr_start(client, rdataset->type);
+ return;
+ case dns_rdatatype_maila:
+ case dns_rdatatype_mailb:
+ query_error(client, DNS_R_NOTIMP);
+ return;
+ case dns_rdatatype_tkey:
+ result = dns_tkey_processquery(client->message,
+ ns_g_server->tkeyctx,
+ client->view->dynamickeys);
+ if (result == ISC_R_SUCCESS)
+ query_send(client);
+ else
+ query_error(client, result);
+ return;
+ default: /* TSIG, etc. */
+ query_error(client, DNS_R_FORMERR);
+ return;
+ }
+ }
+
+ /*
+ * Turn on minimal response for DNSKEY queries.
+ */
+ if (qtype == dns_rdatatype_dnskey)
+ client->query.attributes |= (NS_QUERYATTR_NOAUTHORITY |
+ NS_QUERYATTR_NOADDITIONAL);
+
+ /*
+ * If the client has requested that DNSSEC checking be disabled,
+ * allow lookups to return pending data and instruct the resolver
+ * to return data before validation has completed.
+ *
+ * We don't need to set DNS_DBFIND_PENDINGOK when validation is
+ * disabled as there will be no pending data.
+ */
+ if (message->flags & DNS_MESSAGEFLAG_CD ||
+ qtype == dns_rdatatype_rrsig)
+ {
+ client->query.dboptions |= DNS_DBFIND_PENDINGOK;
+ client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
+ } else if (!client->view->enablevalidation)
+ client->query.fetchoptions |= DNS_FETCHOPT_NOVALIDATE;
+
+ /*
+ * Allow glue NS records to be added to the authority section
+ * if the answer is secure.
+ */
+ if (message->flags & DNS_MESSAGEFLAG_CD)
+ client->query.attributes &= ~NS_QUERYATTR_SECURE;
+
+ /*
+ * Set 'want_ad' if the client has set AD in the query.
+ * This allows AD to be returned on queries without DO set.
+ */
+ if ((message->flags & DNS_MESSAGEFLAG_AD) != 0)
+ want_ad = ISC_TRUE;
+ else
+ want_ad = ISC_FALSE;
+
+ /*
+ * This is an ordinary query.
+ */
+ result = dns_message_reply(message, ISC_TRUE);
+ if (result != ISC_R_SUCCESS) {
+ query_next(client, result);
+ return;
+ }
+
+ /*
+ * Assume authoritative response until it is known to be
+ * otherwise.
+ */
+ message->flags |= DNS_MESSAGEFLAG_AA;
+
+ /*
+ * Set AD. We must clear it if we add non-validated data to a
+ * response.
+ */
+ if (WANTDNSSEC(client) || want_ad)
+ message->flags |= DNS_MESSAGEFLAG_AD;
+
+ qclient = NULL;
+ ns_client_attach(client, &qclient);
+ query_find(qclient, NULL, qtype);
+}
diff --git a/bin/named/server.c b/bin/named/server.c
new file mode 100644
index 0000000..31b2761
--- /dev/null
+++ b/bin/named/server.c
@@ -0,0 +1,5462 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: server.c,v 1.520 2008/11/14 23:47:32 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/hash.h>
+#include <isc/httpd.h>
+#include <isc/lex.h>
+#include <isc/parseint.h>
+#include <isc/portset.h>
+#include <isc/print.h>
+#include <isc/resource.h>
+#include <isc/socket.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+#include <isc/xml.h>
+
+#include <isccfg/namedconf.h>
+
+#include <bind9/check.h>
+
+#include <dns/acache.h>
+#include <dns/adb.h>
+#include <dns/cache.h>
+#include <dns/db.h>
+#include <dns/dispatch.h>
+#ifdef DLZ
+#include <dns/dlz.h>
+#endif
+#include <dns/forward.h>
+#include <dns/journal.h>
+#include <dns/keytable.h>
+#include <dns/lib.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/order.h>
+#include <dns/peer.h>
+#include <dns/portlist.h>
+#include <dns/rbt.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/resolver.h>
+#include <dns/rootns.h>
+#include <dns/secalg.h>
+#include <dns/stats.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#include <dst/dst.h>
+#include <dst/result.h>
+
+#include <named/client.h>
+#include <named/config.h>
+#include <named/control.h>
+#include <named/interfacemgr.h>
+#include <named/log.h>
+#include <named/logconf.h>
+#include <named/lwresd.h>
+#include <named/main.h>
+#include <named/os.h>
+#include <named/server.h>
+#include <named/statschannel.h>
+#include <named/tkeyconf.h>
+#include <named/tsigconf.h>
+#include <named/zoneconf.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#include <stdlib.h>
+#endif
+
+/*%
+ * Check an operation for failure. Assumes that the function
+ * using it has a 'result' variable and a 'cleanup' label.
+ */
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto cleanup; \
+ } while (0)
+
+#define CHECKM(op, msg) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ isc_log_write(ns_g_lctx, \
+ NS_LOGCATEGORY_GENERAL, \
+ NS_LOGMODULE_SERVER, \
+ ISC_LOG_ERROR, \
+ "%s: %s", msg, \
+ isc_result_totext(result)); \
+ goto cleanup; \
+ } \
+ } while (0) \
+
+#define CHECKMF(op, msg, file) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ isc_log_write(ns_g_lctx, \
+ NS_LOGCATEGORY_GENERAL, \
+ NS_LOGMODULE_SERVER, \
+ ISC_LOG_ERROR, \
+ "%s '%s': %s", msg, file, \
+ isc_result_totext(result)); \
+ goto cleanup; \
+ } \
+ } while (0) \
+
+#define CHECKFATAL(op, msg) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) \
+ fatal(msg, result); \
+ } while (0) \
+
+struct ns_dispatch {
+ isc_sockaddr_t addr;
+ unsigned int dispatchgen;
+ dns_dispatch_t *dispatch;
+ ISC_LINK(struct ns_dispatch) link;
+};
+
+struct dumpcontext {
+ isc_mem_t *mctx;
+ isc_boolean_t dumpcache;
+ isc_boolean_t dumpzones;
+ FILE *fp;
+ ISC_LIST(struct viewlistentry) viewlist;
+ struct viewlistentry *view;
+ struct zonelistentry *zone;
+ dns_dumpctx_t *mdctx;
+ dns_db_t *db;
+ dns_db_t *cache;
+ isc_task_t *task;
+ dns_dbversion_t *version;
+};
+
+struct viewlistentry {
+ dns_view_t *view;
+ ISC_LINK(struct viewlistentry) link;
+ ISC_LIST(struct zonelistentry) zonelist;
+};
+
+struct zonelistentry {
+ dns_zone_t *zone;
+ ISC_LINK(struct zonelistentry) link;
+};
+
+/*
+ * These zones should not leak onto the Internet.
+ */
+static const struct {
+ const char *zone;
+ isc_boolean_t rfc1918;
+} empty_zones[] = {
+#ifdef notyet
+ /* RFC 1918 */
+ { "10.IN-ADDR.ARPA", ISC_TRUE },
+ { "16.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "17.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "18.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "19.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "20.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "21.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "22.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "23.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "24.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "25.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "26.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "27.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "28.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "29.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "30.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "31.172.IN-ADDR.ARPA", ISC_TRUE },
+ { "168.192.IN-ADDR.ARPA", ISC_TRUE },
+#endif
+
+ /* RFC 3330 */
+ { "0.IN-ADDR.ARPA", ISC_FALSE }, /* THIS NETWORK */
+ { "127.IN-ADDR.ARPA", ISC_FALSE }, /* LOOPBACK */
+ { "254.169.IN-ADDR.ARPA", ISC_FALSE }, /* LINK LOCAL */
+ { "2.0.192.IN-ADDR.ARPA", ISC_FALSE }, /* TEST NET */
+ { "255.255.255.255.IN-ADDR.ARPA", ISC_FALSE }, /* BROADCAST */
+
+ /* Local IPv6 Unicast Addresses */
+ { "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
+ { "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
+ /* LOCALLY ASSIGNED LOCAL ADDRES S SCOPE */
+ { "D.F.IP6.ARPA", ISC_FALSE },
+ { "8.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
+ { "9.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
+ { "A.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
+ { "B.E.F.IP6.ARPA", ISC_FALSE }, /* LINK LOCAL */
+
+ { NULL, ISC_FALSE }
+};
+
+static void
+fatal(const char *msg, isc_result_t result);
+
+static void
+ns_server_reload(isc_task_t *task, isc_event_t *event);
+
+static isc_result_t
+ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx,
+ isc_mem_t *mctx, ns_listenelt_t **target);
+static isc_result_t
+ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx,
+ isc_mem_t *mctx, ns_listenlist_t **target);
+
+static isc_result_t
+configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
+ const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype);
+
+static isc_result_t
+configure_alternates(const cfg_obj_t *config, dns_view_t *view,
+ const cfg_obj_t *alternates);
+
+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);
+
+static void
+end_reserved_dispatches(ns_server_t *server, isc_boolean_t all);
+
+/*%
+ * Configure a single view ACL at '*aclp'. Get its configuration by
+ * calling 'getvcacl' (for per-view configuration) and maybe 'getscacl'
+ * (for a global default).
+ */
+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)
+{
+ isc_result_t result;
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *aclobj = NULL;
+ int i = 0;
+
+ if (*aclp != NULL)
+ dns_acl_detach(aclp);
+ 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, aclname, &aclobj);
+ if (aclobj == NULL)
+ /*
+ * No value available. *aclp == NULL.
+ */
+ return (ISC_R_SUCCESS);
+
+ 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
+ * nest_level value of 2.
+ */
+static isc_result_t
+configure_view_sortlist(const cfg_obj_t *vconfig, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx, isc_mem_t *mctx,
+ dns_acl_t **aclp)
+{
+ isc_result_t result;
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *aclobj = NULL;
+ int i = 0;
+
+ if (*aclp != NULL)
+ dns_acl_detach(aclp);
+ 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, "sortlist", &aclobj);
+ if (aclobj == NULL)
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Use a nest level of 3 for the "top level" of the sortlist;
+ * this means each entry in the top three levels will be stored
+ * as lists of separate, nested ACLs, rather than merged together
+ * into IP tables as is usually done with ACLs.
+ */
+ result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx,
+ actx, mctx, 3, aclp);
+
+ return (result);
+}
+
+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)
+{
+ dns_rdataclass_t viewclass;
+ dns_rdata_dnskey_t keystruct;
+ isc_uint32_t flags, proto, alg;
+ const char *keystr, *keynamestr;
+ unsigned char keydata[4096];
+ isc_buffer_t keydatabuf;
+ unsigned char rrdata[4096];
+ isc_buffer_t rrdatabuf;
+ isc_region_t r;
+ dns_fixedname_t fkeyname;
+ dns_name_t *keyname;
+ isc_buffer_t namebuf;
+ isc_result_t result;
+ dst_key_t *dstkey = 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 (vconfig == NULL)
+ viewclass = dns_rdataclass_in;
+ else {
+ const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class");
+ CHECK(ns_config_getclass(classobj, dns_rdataclass_in,
+ &viewclass));
+ }
+ keystruct.common.rdclass = viewclass;
+ keystruct.common.rdtype = dns_rdatatype_dnskey;
+ /*
+ * The key data in keystruct is not dynamically allocated.
+ */
+ keystruct.mctx = NULL;
+
+ ISC_LINK_INIT(&keystruct.common, link);
+
+ if (flags > 0xffff)
+ CHECKM(ISC_R_RANGE, "key flags");
+ if (proto > 0xff)
+ CHECKM(ISC_R_RANGE, "key protocol");
+ if (alg > 0xff)
+ CHECKM(ISC_R_RANGE, "key algorithm");
+ keystruct.flags = (isc_uint16_t)flags;
+ keystruct.protocol = (isc_uint8_t)proto;
+ keystruct.algorithm = (isc_uint8_t)alg;
+
+ isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
+ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
+
+ keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
+ CHECK(isc_base64_decodestring(keystr, &keydatabuf));
+ isc_buffer_usedregion(&keydatabuf, &r);
+ keystruct.datalen = r.length;
+ keystruct.data = r.base;
+
+ if ((keystruct.algorithm == DST_ALG_RSASHA1 ||
+ 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",
+ keynamestr);
+
+ CHECK(dns_rdata_fromstruct(NULL,
+ keystruct.common.rdclass,
+ keystruct.common.rdtype,
+ &keystruct, &rrdatabuf));
+ 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(dst_key_fromdns(keyname, viewclass, &rrdatabuf,
+ mctx, &dstkey));
+
+ CHECK(dns_keytable_add(keytable, &dstkey));
+ INSIST(dstkey == NULL);
+ 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",
+ keynamestr);
+ result = ISC_R_SUCCESS;
+ } else {
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
+ "configuring trusted key for '%s': %s",
+ keynamestr, isc_result_totext(result));
+ result = ISC_R_FAILURE;
+ }
+
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+
+ return (result);
+}
+
+/*%
+ * Configure DNSSEC keys for a view. Currently used only for
+ * the security roots.
+ *
+ * The per-view configuration values and the server-global defaults are read
+ * from 'vconfig' and 'config'. The variable to be configured is '*target'.
+ */
+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)
+{
+ isc_result_t result;
+ const cfg_obj_t *keys = NULL;
+ 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;
+
+ CHECK(dns_keytable_create(mctx, &keytable));
+
+ if (vconfig != NULL)
+ voptions = cfg_tuple_get(vconfig, "options");
+
+ keys = NULL;
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "trusted-keys", &keys);
+ if (keys == NULL)
+ (void)cfg_map_get(config, "trusted-keys", &keys);
+
+ 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));
+ }
+ }
+
+ dns_keytable_detach(target);
+ *target = keytable; /* Transfer ownership. */
+ keytable = NULL;
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ return (result);
+}
+
+static isc_result_t
+mustbesecure(const cfg_obj_t *mbs, dns_resolver_t *resolver)
+{
+ const cfg_listelt_t *element;
+ const cfg_obj_t *obj;
+ const char *str;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_boolean_t value;
+ isc_result_t result;
+ isc_buffer_t b;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ for (element = cfg_list_first(mbs);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ 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));
+ value = cfg_obj_asboolean(cfg_tuple_get(obj, "value"));
+ CHECK(dns_resolver_setmustbesecure(resolver, name, value));
+ }
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ return (result);
+}
+
+/*%
+ * Get a dispatch appropriate for the resolver of a given view.
+ */
+static isc_result_t
+get_view_querysource_dispatch(const cfg_obj_t **maps,
+ int af, dns_dispatch_t **dispatchp,
+ isc_boolean_t is_firstview)
+{
+ isc_result_t result;
+ dns_dispatch_t *disp;
+ isc_sockaddr_t sa;
+ unsigned int attrs, attrmask;
+ const cfg_obj_t *obj = NULL;
+ unsigned int maxdispatchbuffers;
+
+ /*
+ * Make compiler happy.
+ */
+ result = ISC_R_FAILURE;
+
+ switch (af) {
+ case AF_INET:
+ result = ns_config_get(maps, "query-source", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ break;
+ case AF_INET6:
+ result = ns_config_get(maps, "query-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ break;
+ default:
+ INSIST(0);
+ }
+
+ sa = *(cfg_obj_assockaddr(obj));
+ INSIST(isc_sockaddr_pf(&sa) == af);
+
+ /*
+ * If we don't support this address family, we're done!
+ */
+ switch (af) {
+ case AF_INET:
+ result = isc_net_probeipv4();
+ break;
+ case AF_INET6:
+ result = isc_net_probeipv6();
+ break;
+ default:
+ INSIST(0);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Try to find a dispatcher that we can share.
+ */
+ attrs = 0;
+ attrs |= DNS_DISPATCHATTR_UDP;
+ switch (af) {
+ case AF_INET:
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ break;
+ case AF_INET6:
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ break;
+ }
+ if (isc_sockaddr_getport(&sa) == 0) {
+ attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
+ maxdispatchbuffers = 4096;
+ } else {
+ INSIST(obj != NULL);
+ if (is_firstview) {
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO,
+ "using specific query-source port "
+ "suppresses port randomization and can be "
+ "insecure.");
+ }
+ maxdispatchbuffers = 1000;
+ }
+
+ attrmask = 0;
+ attrmask |= DNS_DISPATCHATTR_UDP;
+ attrmask |= DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4;
+ attrmask |= DNS_DISPATCHATTR_IPV6;
+
+ disp = NULL;
+ result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
+ ns_g_taskmgr, &sa, 4096,
+ maxdispatchbuffers, 32768, 16411, 16433,
+ attrs, attrmask, &disp);
+ if (result != ISC_R_SUCCESS) {
+ isc_sockaddr_t any;
+ char buf[ISC_SOCKADDR_FORMATSIZE];
+
+ switch (af) {
+ case AF_INET:
+ isc_sockaddr_any(&any);
+ break;
+ case AF_INET6:
+ isc_sockaddr_any6(&any);
+ break;
+ }
+ if (isc_sockaddr_equal(&sa, &any))
+ return (ISC_R_SUCCESS);
+ isc_sockaddr_format(&sa, buf, sizeof(buf));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "could not get query source dispatcher (%s)",
+ buf);
+ return (result);
+ }
+
+ *dispatchp = disp;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+configure_order(dns_order_t *order, const cfg_obj_t *ent) {
+ dns_rdataclass_t rdclass;
+ dns_rdatatype_t rdtype;
+ const cfg_obj_t *obj;
+ dns_fixedname_t fixed;
+ unsigned int mode = 0;
+ const char *str;
+ isc_buffer_t b;
+ isc_result_t result;
+ isc_boolean_t addroot;
+
+ result = ns_config_getclass(cfg_tuple_get(ent, "class"),
+ dns_rdataclass_any, &rdclass);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = ns_config_gettype(cfg_tuple_get(ent, "type"),
+ dns_rdatatype_any, &rdtype);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ obj = cfg_tuple_get(ent, "name");
+ if (cfg_obj_isstring(obj))
+ str = cfg_obj_asstring(obj);
+ else
+ str = "*";
+ addroot = ISC_TF(strcmp(str, "*") == 0);
+ isc_buffer_init(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ dns_fixedname_init(&fixed);
+ result = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
+ dns_rootname, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ obj = cfg_tuple_get(ent, "ordering");
+ INSIST(cfg_obj_isstring(obj));
+ str = cfg_obj_asstring(obj);
+ if (!strcasecmp(str, "fixed"))
+ mode = DNS_RDATASETATTR_FIXEDORDER;
+ else if (!strcasecmp(str, "random"))
+ mode = DNS_RDATASETATTR_RANDOMIZE;
+ else if (!strcasecmp(str, "cyclic"))
+ mode = 0;
+ else
+ INSIST(0);
+
+ /*
+ * "*" should match everything including the root (BIND 8 compat).
+ * As dns_name_matcheswildcard(".", "*.") returns FALSE add a
+ * explicit entry for "." when the name is "*".
+ */
+ if (addroot) {
+ result = dns_order_add(order, dns_rootname,
+ rdtype, rdclass, mode);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (dns_order_add(order, dns_fixedname_name(&fixed),
+ rdtype, rdclass, mode));
+}
+
+static isc_result_t
+configure_peer(const cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) {
+ isc_netaddr_t na;
+ dns_peer_t *peer;
+ const cfg_obj_t *obj;
+ const char *str;
+ isc_result_t result;
+ unsigned int prefixlen;
+
+ cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen);
+
+ peer = NULL;
+ result = dns_peer_newprefix(mctx, &na, prefixlen, &peer);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "bogus", &obj);
+ if (obj != NULL)
+ CHECK(dns_peer_setbogus(peer, cfg_obj_asboolean(obj)));
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "provide-ixfr", &obj);
+ if (obj != NULL)
+ CHECK(dns_peer_setprovideixfr(peer, cfg_obj_asboolean(obj)));
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "request-ixfr", &obj);
+ if (obj != NULL)
+ CHECK(dns_peer_setrequestixfr(peer, cfg_obj_asboolean(obj)));
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "request-nsid", &obj);
+ if (obj != NULL)
+ CHECK(dns_peer_setrequestnsid(peer, cfg_obj_asboolean(obj)));
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "edns", &obj);
+ if (obj != NULL)
+ CHECK(dns_peer_setsupportedns(peer, cfg_obj_asboolean(obj)));
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "edns-udp-size", &obj);
+ if (obj != NULL) {
+ isc_uint32_t udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 512)
+ udpsize = 512;
+ if (udpsize > 4096)
+ udpsize = 4096;
+ CHECK(dns_peer_setudpsize(peer, (isc_uint16_t)udpsize));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "max-udp-size", &obj);
+ if (obj != NULL) {
+ isc_uint32_t udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 512)
+ udpsize = 512;
+ if (udpsize > 4096)
+ udpsize = 4096;
+ CHECK(dns_peer_setmaxudp(peer, (isc_uint16_t)udpsize));
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "transfers", &obj);
+ if (obj != NULL)
+ CHECK(dns_peer_settransfers(peer, cfg_obj_asuint32(obj)));
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "transfer-format", &obj);
+ if (obj != NULL) {
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "many-answers") == 0)
+ CHECK(dns_peer_settransferformat(peer,
+ dns_many_answers));
+ else if (strcasecmp(str, "one-answer") == 0)
+ CHECK(dns_peer_settransferformat(peer,
+ dns_one_answer));
+ else
+ INSIST(0);
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(cpeer, "keys", &obj);
+ if (obj != NULL) {
+ result = dns_peer_setkeybycharp(peer, cfg_obj_asstring(obj));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ obj = NULL;
+ if (na.family == AF_INET)
+ (void)cfg_map_get(cpeer, "transfer-source", &obj);
+ else
+ (void)cfg_map_get(cpeer, "transfer-source-v6", &obj);
+ if (obj != NULL) {
+ result = dns_peer_settransfersource(peer,
+ cfg_obj_assockaddr(obj));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+ }
+
+ obj = NULL;
+ if (na.family == AF_INET)
+ (void)cfg_map_get(cpeer, "notify-source", &obj);
+ else
+ (void)cfg_map_get(cpeer, "notify-source-v6", &obj);
+ if (obj != NULL) {
+ result = dns_peer_setnotifysource(peer,
+ cfg_obj_assockaddr(obj));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+ }
+
+ obj = NULL;
+ if (na.family == AF_INET)
+ (void)cfg_map_get(cpeer, "query-source", &obj);
+ else
+ (void)cfg_map_get(cpeer, "query-source-v6", &obj);
+ if (obj != NULL) {
+ result = dns_peer_setquerysource(peer,
+ cfg_obj_assockaddr(obj));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+ }
+
+ *peerp = peer;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_peer_detach(&peer);
+ return (result);
+}
+
+static isc_result_t
+disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
+ isc_result_t result;
+ const cfg_obj_t *algorithms;
+ const cfg_listelt_t *element;
+ const char *str;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t b;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ 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));
+
+ algorithms = cfg_tuple_get(disabled, "algorithms");
+ for (element = cfg_list_first(algorithms);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ isc_textregion_t r;
+ dns_secalg_t alg;
+
+ DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
+ r.length = strlen(r.base);
+
+ result = dns_secalg_fromtext(&alg, &r);
+ if (result != ISC_R_SUCCESS) {
+ isc_uint8_t ui;
+ result = isc_parse_uint8(&ui, r.base, 10);
+ alg = ui;
+ }
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(cfg_listelt_value(element),
+ ns_g_lctx, ISC_LOG_ERROR,
+ "invalid algorithm");
+ CHECK(result);
+ }
+ CHECK(dns_resolver_disable_algorithm(resolver, name, alg));
+ }
+ cleanup:
+ return (result);
+}
+
+static isc_boolean_t
+on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) {
+ const cfg_listelt_t *element;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_result_t result;
+ const cfg_obj_t *value;
+ const char *str;
+ isc_buffer_t b;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+
+ for (element = cfg_list_first(disablelist);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ value = cfg_listelt_value(element);
+ str = cfg_obj_asstring(value);
+ isc_buffer_init(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ result = dns_name_fromtext(name, &b, dns_rootname,
+ ISC_TRUE, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (dns_name_equal(name, zonename))
+ return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
+static void
+check_dbtype(dns_zone_t **zonep, unsigned int dbtypec, const char **dbargv,
+ isc_mem_t *mctx)
+{
+ char **argv = NULL;
+ unsigned int i;
+ isc_result_t result;
+
+ result = dns_zone_getdbtype(*zonep, &argv, mctx);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_detach(zonep);
+ return;
+ }
+
+ /*
+ * Check that all the arguments match.
+ */
+ for (i = 0; i < dbtypec; i++)
+ if (argv[i] == NULL || strcmp(argv[i], dbargv[i]) != 0) {
+ dns_zone_detach(zonep);
+ break;
+ }
+
+ /*
+ * Check that there are not extra arguments.
+ */
+ if (i == dbtypec && argv[i] != NULL)
+ dns_zone_detach(zonep);
+ isc_mem_free(mctx, argv);
+}
+
+static isc_result_t
+setquerystats(dns_zone_t *zone, isc_mem_t *mctx, isc_boolean_t on) {
+ isc_result_t result;
+ dns_stats_t *zoneqrystats;
+
+ zoneqrystats = NULL;
+ if (on) {
+ result = dns_generalstats_create(mctx, &zoneqrystats,
+ dns_nsstatscounter_max);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ dns_zone_setrequeststats(zone, zoneqrystats);
+ if (zoneqrystats != NULL)
+ dns_stats_detach(&zoneqrystats);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Configure 'view' according to 'vconfig', taking defaults from 'config'
+ * where values are missing in 'vconfig'.
+ *
+ * When configuring the default view, 'vconfig' will be NULL and the
+ * 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)
+{
+ const cfg_obj_t *maps[4];
+ const cfg_obj_t *cfgmaps[3];
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *voptions = NULL;
+ const cfg_obj_t *forwardtype;
+ const cfg_obj_t *forwarders;
+ const cfg_obj_t *alternates;
+ const cfg_obj_t *zonelist;
+#ifdef DLZ
+ const cfg_obj_t *dlz;
+ unsigned int dlzargc;
+ char **dlzargv;
+#endif
+ const cfg_obj_t *disabled;
+ const cfg_obj_t *obj;
+ const cfg_listelt_t *element;
+ in_port_t port;
+ dns_cache_t *cache = NULL;
+ isc_result_t result;
+ isc_uint32_t max_adb_size;
+ isc_uint32_t max_cache_size;
+ isc_uint32_t max_acache_size;
+ isc_uint32_t lame_ttl;
+ dns_tsig_keyring_t *ring;
+ 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;
+ const char *str;
+ dns_order_t *order = NULL;
+ isc_uint32_t udpsize;
+ unsigned int resopts = 0;
+ dns_zone_t *zone = NULL;
+ isc_uint32_t max_clients_per_query;
+ const char *sep = ": view ";
+ const char *viewname = view->name;
+ const char *forview = " for view ";
+ isc_boolean_t rfc1918;
+ isc_boolean_t empty_zones_enable;
+ const cfg_obj_t *disablelist = NULL;
+ dns_stats_t *resstats = NULL;
+ dns_stats_t *resquerystats = NULL;
+
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ cmctx = NULL;
+
+ if (config != NULL)
+ (void)cfg_map_get(config, "options", &options);
+
+ i = 0;
+ if (vconfig != NULL) {
+ voptions = cfg_tuple_get(vconfig, "options");
+ maps[i++] = voptions;
+ }
+ if (options != NULL)
+ maps[i++] = options;
+ maps[i++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ i = 0;
+ if (voptions != NULL)
+ cfgmaps[i++] = voptions;
+ if (config != NULL)
+ cfgmaps[i++] = config;
+ cfgmaps[i] = NULL;
+
+ if (!strcmp(viewname, "_default")) {
+ sep = "";
+ viewname = "";
+ forview = "";
+ }
+
+ /*
+ * Set the view's port number for outgoing queries.
+ */
+ CHECKM(ns_config_getport(config, &port), "port");
+ dns_view_setdstport(view, port);
+
+ /*
+ * Create additional cache for this view and zones under the view
+ * if explicitly enabled.
+ * XXX950 default to on.
+ */
+ obj = NULL;
+ (void)ns_config_get(maps, "acache-enable", &obj);
+ if (obj != NULL && cfg_obj_asboolean(obj)) {
+ cmctx = NULL;
+ CHECK(isc_mem_create(0, 0, &cmctx));
+ CHECK(dns_acache_create(&view->acache, cmctx, ns_g_taskmgr,
+ ns_g_timermgr));
+ isc_mem_setname(cmctx, "acache", NULL);
+ isc_mem_detach(&cmctx);
+ }
+ if (view->acache != NULL) {
+ obj = NULL;
+ result = ns_config_get(maps, "acache-cleaning-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_acache_setcleaninginterval(view->acache,
+ cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-acache-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isstring(obj)) {
+ str = cfg_obj_asstring(obj);
+ INSIST(strcasecmp(str, "unlimited") == 0);
+ max_acache_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-acache-size "
+ "%" ISC_PRINT_QUADFORMAT
+ "d' is too large",
+ value);
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ max_acache_size = (isc_uint32_t)value;
+ }
+ dns_acache_setcachesize(view->acache, max_acache_size);
+ }
+
+ /*
+ * Configure the zones.
+ */
+ zonelist = NULL;
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "zone", &zonelist);
+ else
+ (void)cfg_map_get(config, "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));
+ }
+
+#ifdef DLZ
+ /*
+ * Create Dynamically Loadable Zone driver.
+ */
+ dlz = NULL;
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "dlz", &dlz);
+ else
+ (void)cfg_map_get(config, "dlz", &dlz);
+
+ obj = NULL;
+ if (dlz != NULL) {
+ (void)cfg_map_get(cfg_tuple_get(dlz, "options"),
+ "database", &obj);
+ if (obj != NULL) {
+ char *s = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
+ if (s == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_free(mctx, s);
+ goto cleanup;
+ }
+
+ obj = cfg_tuple_get(dlz, "name");
+ result = dns_dlzcreate(mctx, cfg_obj_asstring(obj),
+ dlzargv[0], dlzargc, dlzargv,
+ &view->dlzdatabase);
+ isc_mem_free(mctx, s);
+ isc_mem_put(mctx, dlzargv, dlzargc * sizeof(*dlzargv));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ }
+#endif
+
+ /*
+ * 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.
+ *
+ * XXX Determining when it is safe to reuse 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. As more view attributes become
+ * configurable, we will have to add code here to check
+ * whether they have changed in ways that could
+ * invalidate the cache.
+ */
+ 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) {
+ 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);
+ } else {
+ 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_view_setcache(view, cache);
+
+ /*
+ * cache-file cannot be inherited if views are present, but this
+ * should be caught by the configuration checking stage.
+ */
+ obj = NULL;
+ 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)
+ 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_setcachesize(cache, max_cache_size);
+
+ dns_cache_detach(&cache);
+
+ /*
+ * Check-names.
+ */
+ obj = NULL;
+ result = ns_checknames_get(maps, "response", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "fail") == 0) {
+ resopts |= DNS_RESOLVER_CHECKNAMES |
+ DNS_RESOLVER_CHECKNAMESFAIL;
+ view->checknames = ISC_TRUE;
+ } else if (strcasecmp(str, "warn") == 0) {
+ resopts |= DNS_RESOLVER_CHECKNAMES;
+ view->checknames = ISC_FALSE;
+ } else if (strcasecmp(str, "ignore") == 0) {
+ view->checknames = ISC_FALSE;
+ } else
+ INSIST(0);
+
+ /*
+ * Resolver.
+ *
+ * XXXRTH Hardwired number of tasks.
+ */
+ CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4,
+ ISC_TF(ISC_LIST_PREV(view, link)
+ == NULL)));
+ CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6,
+ ISC_TF(ISC_LIST_PREV(view, link)
+ == NULL)));
+ if (dispatch4 == NULL && dispatch6 == NULL) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "unable to obtain neither an IPv4 nor"
+ " an IPv6 dispatch");
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+ CHECK(dns_view_createresolver(view, ns_g_taskmgr, 31,
+ ns_g_socketmgr, ns_g_timermgr,
+ resopts, ns_g_dispatchmgr,
+ dispatch4, dispatch6));
+
+ if (resstats == NULL) {
+ CHECK(dns_generalstats_create(mctx, &resstats,
+ dns_resstatscounter_max));
+ }
+ dns_view_setresstats(view, resstats);
+ if (resquerystats == NULL)
+ CHECK(dns_rdatatypestats_create(mctx, &resquerystats));
+ dns_view_setresquerystats(view, resquerystats);
+
+ /*
+ * Set the ADB cache size to 1/8th of the max-cache-size.
+ */
+ 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. */
+ }
+ dns_adb_setadbsize(view->adb, max_adb_size);
+
+ /*
+ * Set resolver's lame-ttl.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "lame-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ lame_ttl = cfg_obj_asuint32(obj);
+ if (lame_ttl > 1800)
+ lame_ttl = 1800;
+ dns_resolver_setlamettl(view->resolver, lame_ttl);
+
+ obj = NULL;
+ result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_resolver_setzeronosoattl(view->resolver, cfg_obj_asboolean(obj));
+
+ /*
+ * Set the resolver's EDNS UDP size.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "edns-udp-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 512)
+ udpsize = 512;
+ if (udpsize > 4096)
+ udpsize = 4096;
+ dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize);
+
+ /*
+ * Set the maximum UDP response size.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "max-udp-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 512)
+ udpsize = 512;
+ if (udpsize > 4096)
+ udpsize = 4096;
+ view->maxudp = udpsize;
+
+ /*
+ * Set supported DNSSEC algorithms.
+ */
+ dns_resolver_reset_algorithms(view->resolver);
+ disabled = NULL;
+ (void)ns_config_get(maps, "disable-algorithms", &disabled);
+ if (disabled != NULL) {
+ for (element = cfg_list_first(disabled);
+ element != NULL;
+ element = cfg_list_next(element))
+ CHECK(disable_algorithms(cfg_listelt_value(element),
+ view->resolver));
+ }
+
+ /*
+ * A global or view "forwarders" option, if present,
+ * creates an entry for "." in the forwarding table.
+ */
+ forwardtype = NULL;
+ forwarders = NULL;
+ (void)ns_config_get(maps, "forward", &forwardtype);
+ (void)ns_config_get(maps, "forwarders", &forwarders);
+ if (forwarders != NULL)
+ CHECK(configure_forward(config, view, dns_rootname,
+ forwarders, forwardtype));
+
+ /*
+ * Dual Stack Servers.
+ */
+ alternates = NULL;
+ (void)ns_config_get(maps, "dual-stack-servers", &alternates);
+ if (alternates != NULL)
+ CHECK(configure_alternates(config, view, alternates));
+
+ /*
+ * We have default hints for class IN if we need them.
+ */
+ if (view->rdclass == dns_rdataclass_in && view->hints == NULL)
+ dns_view_sethints(view, ns_g_server->in_roothints);
+
+ /*
+ * If we still have no hints, this is a non-IN view with no
+ * "hints zone" configured. Issue a warning, except if this
+ * is a root server. Root servers never need to consult
+ * their hints, so it's no point requiring users to configure
+ * them.
+ */
+ if (view->hints == NULL) {
+ dns_zone_t *rootzone = NULL;
+ (void)dns_view_findzone(view, dns_rootname, &rootzone);
+ if (rootzone != NULL) {
+ dns_zone_detach(&rootzone);
+ need_hints = ISC_FALSE;
+ }
+ if (need_hints)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "no root hints for view '%s'",
+ view->name);
+ }
+
+ /*
+ * Configure the view's TSIG keys.
+ */
+ ring = NULL;
+ CHECK(ns_tsigkeyring_fromconfig(config, vconfig, view->mctx, &ring));
+ dns_view_setkeyring(view, ring);
+
+ /*
+ * Configure the view's peer list.
+ */
+ {
+ const cfg_obj_t *peers = NULL;
+ const cfg_listelt_t *element;
+ dns_peerlist_t *newpeers = NULL;
+
+ (void)ns_config_get(cfgmaps, "server", &peers);
+ CHECK(dns_peerlist_new(mctx, &newpeers));
+ for (element = cfg_list_first(peers);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *cpeer = cfg_listelt_value(element);
+ dns_peer_t *peer;
+
+ CHECK(configure_peer(cpeer, mctx, &peer));
+ dns_peerlist_addpeer(newpeers, peer);
+ dns_peer_detach(&peer);
+ }
+ dns_peerlist_detach(&view->peers);
+ view->peers = newpeers; /* Transfer ownership. */
+ }
+
+ /*
+ * Configure the views rrset-order.
+ */
+ {
+ const cfg_obj_t *rrsetorder = NULL;
+ const cfg_listelt_t *element;
+
+ (void)ns_config_get(maps, "rrset-order", &rrsetorder);
+ CHECK(dns_order_create(mctx, &order));
+ for (element = cfg_list_first(rrsetorder);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *ent = cfg_listelt_value(element);
+
+ CHECK(configure_order(order, ent));
+ }
+ if (view->order != NULL)
+ dns_order_detach(&view->order);
+ dns_order_attach(order, &view->order);
+ dns_order_detach(&order);
+ }
+ /*
+ * Copy the aclenv object.
+ */
+ dns_aclenv_copy(&view->aclenv, &ns_g_server->aclenv);
+
+ /*
+ * Configure the "match-clients" and "match-destinations" ACL.
+ */
+ CHECK(configure_view_acl(vconfig, config, "match-clients", actx,
+ ns_g_mctx, &view->matchclients));
+ CHECK(configure_view_acl(vconfig, config, "match-destinations", actx,
+ ns_g_mctx, &view->matchdestinations));
+
+ /*
+ * Configure the "match-recursive-only" option.
+ */
+ obj = NULL;
+ (void)ns_config_get(maps, "match-recursive-only", &obj);
+ if (obj != NULL && cfg_obj_asboolean(obj))
+ view->matchrecursiveonly = ISC_TRUE;
+ else
+ view->matchrecursiveonly = ISC_FALSE;
+
+ /*
+ * Configure other configurable data.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "recursion", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->recursion = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "auth-nxdomain", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->auth_nxdomain = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "minimal-responses", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->minimalresponses = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "transfer-format", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "many-answers") == 0)
+ view->transfer_format = dns_many_answers;
+ else if (strcasecmp(str, "one-answer") == 0)
+ view->transfer_format = dns_one_answer;
+ else
+ INSIST(0);
+
+ /*
+ * Set sources where additional data and CNAME/DNAME
+ * targets for authoritative answers may be found.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "additional-from-auth", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->additionalfromauth = cfg_obj_asboolean(obj);
+ if (view->recursion && ! view->additionalfromauth) {
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
+ "'additional-from-auth no' is only supported "
+ "with 'recursion no'");
+ view->additionalfromauth = ISC_TRUE;
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "additional-from-cache", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->additionalfromcache = cfg_obj_asboolean(obj);
+ if (view->recursion && ! view->additionalfromcache) {
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
+ "'additional-from-cache no' is only supported "
+ "with 'recursion no'");
+ view->additionalfromcache = ISC_TRUE;
+ }
+
+ /*
+ * Set "allow-query-cache", "allow-query-cache-on",
+ * "allow-recursion", and "allow-recursion-on" acls if
+ * configured in named.conf.
+ */
+ CHECK(configure_view_acl(vconfig, config, "allow-query-cache",
+ actx, ns_g_mctx, &view->queryacl));
+ CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on",
+ actx, ns_g_mctx, &view->queryonacl));
+ if (view->queryonacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-query-cache-on", actx,
+ ns_g_mctx, &view->queryonacl));
+ if (strcmp(view->name, "_bind") != 0) {
+ CHECK(configure_view_acl(vconfig, config, "allow-recursion",
+ actx, ns_g_mctx,
+ &view->recursionacl));
+ CHECK(configure_view_acl(vconfig, config, "allow-recursion-on",
+ actx, ns_g_mctx,
+ &view->recursiononacl));
+ }
+
+ /*
+ * "allow-query-cache" inherits from "allow-recursion" if set,
+ * otherwise from "allow-query" if set.
+ * "allow-recursion" inherits from "allow-query-cache" if set,
+ * otherwise from "allow-query" if set.
+ */
+ if (view->queryacl == NULL && view->recursionacl != NULL)
+ dns_acl_attach(view->recursionacl, &view->queryacl);
+ if (view->queryacl == NULL)
+ CHECK(configure_view_acl(vconfig, config, "allow-query",
+ actx, ns_g_mctx, &view->queryacl));
+ if (view->recursionacl == NULL && view->queryacl != NULL)
+ dns_acl_attach(view->queryacl, &view->recursionacl);
+
+ /*
+ * Set default "allow-recursion", "allow-recursion-on" and
+ * "allow-query-cache" acls.
+ */
+ if (view->recursionacl == NULL && view->recursion)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-recursion",
+ actx, ns_g_mctx,
+ &view->recursionacl));
+ if (view->recursiononacl == NULL && view->recursion)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-recursion-on",
+ actx, ns_g_mctx,
+ &view->recursiononacl));
+ if (view->queryacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-query-cache", actx,
+ ns_g_mctx, &view->queryacl));
+
+ /*
+ * Configure sortlist, if set
+ */
+ CHECK(configure_view_sortlist(vconfig, config, actx, ns_g_mctx,
+ &view->sortlist));
+
+ /*
+ * Configure default allow-transfer, allow-notify, allow-update
+ * and allow-update-forwarding ACLs, if set, so they can be
+ * inherited by zones.
+ */
+ if (view->notifyacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-notify", actx,
+ ns_g_mctx, &view->notifyacl));
+ if (view->transferacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-transfer", actx,
+ ns_g_mctx, &view->transferacl));
+ if (view->updateacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-update", actx,
+ ns_g_mctx, &view->updateacl));
+ if (view->upfwdacl == NULL)
+ CHECK(configure_view_acl(NULL, ns_g_config,
+ "allow-update-forwarding", actx,
+ ns_g_mctx, &view->upfwdacl));
+
+ obj = NULL;
+ result = ns_config_get(maps, "request-ixfr", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->requestixfr = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "provide-ixfr", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->provideixfr = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "request-nsid", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->requestnsid = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-clients-per-query", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ max_clients_per_query = cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "clients-per-query", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_resolver_setclientsperquery(view->resolver,
+ cfg_obj_asuint32(obj),
+ max_clients_per_query);
+
+ 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-accept-expired", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->acceptexpired = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "dnssec-validation", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->enablevalidation = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "dnssec-lookaside", &obj);
+ if (result == ISC_R_SUCCESS) {
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const char *str;
+ isc_buffer_t b;
+ 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));
+ view->dlv = dns_fixedname_name(&view->dlv_fixed);
+ }
+ } else
+ view->dlv = NULL;
+
+ /*
+ * For now, there is only one kind of trusted keys, the
+ * "security roots".
+ */
+ CHECK(configure_view_dnsseckeys(vconfig, config, mctx,
+ &view->secroots));
+ dns_resolver_resetmustbesecure(view->resolver);
+ obj = NULL;
+ result = ns_config_get(maps, "dnssec-must-be-secure", &obj);
+ if (result == ISC_R_SUCCESS)
+ CHECK(mustbesecure(obj, view->resolver));
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-cache-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->maxcachettl = cfg_obj_asuint32(obj);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-ncache-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ view->maxncachettl = cfg_obj_asuint32(obj);
+ if (view->maxncachettl > 7 * 24 * 3600)
+ view->maxncachettl = 7 * 24 * 3600;
+
+ obj = NULL;
+ result = ns_config_get(maps, "preferred-glue", &obj);
+ if (result == ISC_R_SUCCESS) {
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "a") == 0)
+ view->preferred_glue = dns_rdatatype_a;
+ else if (strcasecmp(str, "aaaa") == 0)
+ view->preferred_glue = dns_rdatatype_aaaa;
+ else
+ view->preferred_glue = 0;
+ } else
+ view->preferred_glue = 0;
+
+ obj = NULL;
+ result = ns_config_get(maps, "root-delegation-only", &obj);
+ if (result == ISC_R_SUCCESS) {
+ dns_view_setrootdelonly(view, ISC_TRUE);
+ if (!cfg_obj_isvoid(obj)) {
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t b;
+ const char *str;
+ const cfg_obj_t *exclude;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ exclude = cfg_listelt_value(element);
+ str = cfg_obj_asstring(exclude);
+ 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_view_excludedelegationonly(view,
+ name));
+ }
+ }
+ } else
+ dns_view_setrootdelonly(view, ISC_FALSE);
+
+ /*
+ * Setup automatic empty zones. If recursion is off then
+ * they are disabled by default.
+ */
+ obj = NULL;
+ (void)ns_config_get(maps, "empty-zones-enable", &obj);
+ (void)ns_config_get(maps, "disable-empty-zone", &disablelist);
+ if (obj == NULL && disablelist == NULL &&
+ view->rdclass == dns_rdataclass_in) {
+ rfc1918 = ISC_FALSE;
+ empty_zones_enable = view->recursion;
+ } else if (view->rdclass == dns_rdataclass_in) {
+ rfc1918 = ISC_TRUE;
+ if (obj != NULL)
+ empty_zones_enable = cfg_obj_asboolean(obj);
+ else
+ empty_zones_enable = view->recursion;
+ } else {
+ rfc1918 = ISC_FALSE;
+ empty_zones_enable = ISC_FALSE;
+ }
+ if (empty_zones_enable) {
+ const char *empty;
+ int empty_zone = 0;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t buffer;
+ const char *str;
+ char server[DNS_NAME_FORMATSIZE + 1];
+ char contact[DNS_NAME_FORMATSIZE + 1];
+ isc_boolean_t logit;
+ const char *empty_dbtype[4] =
+ { "_builtin", "empty", NULL, NULL };
+ int empty_dbtypec = 4;
+ isc_boolean_t zonestats_on;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+
+ obj = NULL;
+ result = ns_config_get(maps, "empty-server", &obj);
+ if (result == ISC_R_SUCCESS) {
+ 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));
+ isc_buffer_init(&buffer, server, sizeof(server) - 1);
+ CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
+ server[isc_buffer_usedlength(&buffer)] = 0;
+ empty_dbtype[2] = server;
+ } else
+ empty_dbtype[2] = "@";
+
+ obj = NULL;
+ result = ns_config_get(maps, "empty-contact", &obj);
+ if (result == ISC_R_SUCCESS) {
+ 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));
+ isc_buffer_init(&buffer, contact, sizeof(contact) - 1);
+ CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
+ contact[isc_buffer_usedlength(&buffer)] = 0;
+ empty_dbtype[3] = contact;
+ } else
+ empty_dbtype[3] = ".";
+
+ obj = NULL;
+ result = ns_config_get(maps, "zone-statistics", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ zonestats_on = cfg_obj_asboolean(obj);
+
+ logit = ISC_TRUE;
+ for (empty = empty_zones[empty_zone].zone;
+ empty != NULL;
+ empty = empty_zones[++empty_zone].zone)
+ {
+ dns_forwarders_t *forwarders = NULL;
+ dns_view_t *pview = NULL;
+
+ isc_buffer_init(&buffer, empty, strlen(empty));
+ isc_buffer_add(&buffer, strlen(empty));
+ /*
+ * Look for zone on drop list.
+ */
+ CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
+ ISC_FALSE, NULL));
+ if (disablelist != NULL &&
+ on_disable_list(disablelist, name))
+ continue;
+
+ /*
+ * This zone already exists.
+ */
+ (void)dns_view_findzone(view, name, &zone);
+ if (zone != NULL) {
+ CHECK(setquerystats(zone, mctx, zonestats_on));
+ dns_zone_detach(&zone);
+ continue;
+ }
+
+ /*
+ * If we would forward this name don't add a
+ * empty zone for it.
+ */
+ result = dns_fwdtable_find(view->fwdtable, name,
+ &forwarders);
+ if (result == ISC_R_SUCCESS &&
+ forwarders->fwdpolicy == dns_fwdpolicy_only)
+ continue;
+
+ if (!rfc1918 && empty_zones[empty_zone].rfc1918) {
+ if (logit) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_WARNING,
+ "Warning%s%s: "
+ "'empty-zones-enable/"
+ "disable-empty-zone' "
+ "not set: disabling "
+ "RFC 1918 empty zones",
+ sep, viewname);
+ logit = ISC_FALSE;
+ }
+ continue;
+ }
+
+ /*
+ * See if we can re-use a existing zone.
+ */
+ 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) {
+ (void)dns_view_findzone(pview, name, &zone);
+ dns_view_detach(&pview);
+ if (zone != NULL)
+ check_dbtype(&zone, empty_dbtypec,
+ empty_dbtype, mctx);
+ if (zone != NULL) {
+ dns_zone_setview(zone, view);
+ CHECK(dns_view_addzone(view, zone));
+ CHECK(setquerystats(zone, mctx,
+ zonestats_on));
+ dns_zone_detach(&zone);
+ continue;
+ }
+ }
+
+ 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, empty_dbtypec,
+ empty_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, zonestats_on));
+ CHECK(dns_view_addzone(view, zone));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "automatic empty zone%s%s: %s",
+ sep, viewname, empty);
+ dns_zone_detach(&zone);
+ }
+ }
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ if (dispatch4 != NULL)
+ dns_dispatch_detach(&dispatch4);
+ if (dispatch6 != NULL)
+ dns_dispatch_detach(&dispatch6);
+ if (resstats != NULL)
+ dns_stats_detach(&resstats);
+ if (resquerystats != NULL)
+ dns_stats_detach(&resquerystats);
+ if (order != NULL)
+ dns_order_detach(&order);
+ if (cmctx != NULL)
+ isc_mem_detach(&cmctx);
+
+ if (cache != NULL)
+ dns_cache_detach(&cache);
+
+ return (result);
+}
+
+static isc_result_t
+configure_hints(dns_view_t *view, const char *filename) {
+ isc_result_t result;
+ dns_db_t *db;
+
+ db = NULL;
+ result = dns_rootns_create(view->mctx, view->rdclass, filename, &db);
+ if (result == ISC_R_SUCCESS) {
+ dns_view_sethints(view, db);
+ dns_db_detach(&db);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+configure_alternates(const cfg_obj_t *config, dns_view_t *view,
+ const cfg_obj_t *alternates)
+{
+ const cfg_obj_t *portobj;
+ const cfg_obj_t *addresses;
+ const cfg_listelt_t *element;
+ isc_result_t result = ISC_R_SUCCESS;
+ in_port_t port;
+
+ /*
+ * Determine which port to send requests to.
+ */
+ if (ns_g_lwresdonly && ns_g_port != 0)
+ port = ns_g_port;
+ else
+ CHECKM(ns_config_getport(config, &port), "port");
+
+ if (alternates != NULL) {
+ portobj = cfg_tuple_get(alternates, "port");
+ if (cfg_obj_isuint32(portobj)) {
+ isc_uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > ISC_UINT16_MAX) {
+ cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ return (ISC_R_RANGE);
+ }
+ port = (in_port_t) val;
+ }
+ }
+
+ addresses = NULL;
+ if (alternates != NULL)
+ addresses = cfg_tuple_get(alternates, "addresses");
+
+ for (element = cfg_list_first(addresses);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *alternate = cfg_listelt_value(element);
+ isc_sockaddr_t sa;
+
+ if (!cfg_obj_issockaddr(alternate)) {
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ const char *str = cfg_obj_asstring(cfg_tuple_get(
+ alternate, "name"));
+ isc_buffer_t buffer;
+ in_port_t myport = port;
+
+ isc_buffer_init(&buffer, str, strlen(str));
+ 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));
+
+ portobj = cfg_tuple_get(alternate, "port");
+ if (cfg_obj_isuint32(portobj)) {
+ isc_uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > ISC_UINT16_MAX) {
+ cfg_obj_log(portobj, ns_g_lctx,
+ ISC_LOG_ERROR,
+ "port '%u' out of range",
+ val);
+ return (ISC_R_RANGE);
+ }
+ myport = (in_port_t) val;
+ }
+ CHECK(dns_resolver_addalternate(view->resolver, NULL,
+ name, myport));
+ continue;
+ }
+
+ sa = *cfg_obj_assockaddr(alternate);
+ if (isc_sockaddr_getport(&sa) == 0)
+ isc_sockaddr_setport(&sa, port);
+ CHECK(dns_resolver_addalternate(view->resolver, &sa,
+ NULL, 0));
+ }
+
+ cleanup:
+ return (result);
+}
+
+static isc_result_t
+configure_forward(const cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
+ const cfg_obj_t *forwarders, const cfg_obj_t *forwardtype)
+{
+ const cfg_obj_t *portobj;
+ const cfg_obj_t *faddresses;
+ const cfg_listelt_t *element;
+ dns_fwdpolicy_t fwdpolicy = dns_fwdpolicy_none;
+ isc_sockaddrlist_t addresses;
+ isc_sockaddr_t *sa;
+ isc_result_t result;
+ in_port_t port;
+
+ ISC_LIST_INIT(addresses);
+
+ /*
+ * Determine which port to send forwarded requests to.
+ */
+ if (ns_g_lwresdonly && ns_g_port != 0)
+ port = ns_g_port;
+ else
+ CHECKM(ns_config_getport(config, &port), "port");
+
+ if (forwarders != NULL) {
+ portobj = cfg_tuple_get(forwarders, "port");
+ if (cfg_obj_isuint32(portobj)) {
+ isc_uint32_t val = cfg_obj_asuint32(portobj);
+ if (val > ISC_UINT16_MAX) {
+ cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ return (ISC_R_RANGE);
+ }
+ port = (in_port_t) val;
+ }
+ }
+
+ faddresses = NULL;
+ if (forwarders != NULL)
+ faddresses = cfg_tuple_get(forwarders, "addresses");
+
+ for (element = cfg_list_first(faddresses);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *forwarder = cfg_listelt_value(element);
+ sa = isc_mem_get(view->mctx, sizeof(isc_sockaddr_t));
+ if (sa == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ *sa = *cfg_obj_assockaddr(forwarder);
+ if (isc_sockaddr_getport(sa) == 0)
+ isc_sockaddr_setport(sa, port);
+ ISC_LINK_INIT(sa, link);
+ ISC_LIST_APPEND(addresses, sa, link);
+ }
+
+ if (ISC_LIST_EMPTY(addresses)) {
+ if (forwardtype != NULL)
+ cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
+ "no forwarders seen; disabling "
+ "forwarding");
+ fwdpolicy = dns_fwdpolicy_none;
+ } else {
+ if (forwardtype == NULL)
+ fwdpolicy = dns_fwdpolicy_first;
+ else {
+ const char *forwardstr = cfg_obj_asstring(forwardtype);
+ if (strcasecmp(forwardstr, "first") == 0)
+ fwdpolicy = dns_fwdpolicy_first;
+ else if (strcasecmp(forwardstr, "only") == 0)
+ fwdpolicy = dns_fwdpolicy_only;
+ else
+ INSIST(0);
+ }
+ }
+
+ result = dns_fwdtable_add(view->fwdtable, origin, &addresses,
+ fwdpolicy);
+ if (result != ISC_R_SUCCESS) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(origin, namebuf, sizeof(namebuf));
+ cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
+ "could not set up forwarding for domain '%s': %s",
+ namebuf, isc_result_totext(result));
+ goto cleanup;
+ }
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+
+ while (!ISC_LIST_EMPTY(addresses)) {
+ sa = ISC_LIST_HEAD(addresses);
+ ISC_LIST_UNLINK(addresses, sa, link);
+ isc_mem_put(view->mctx, sa, sizeof(isc_sockaddr_t));
+ }
+
+ return (result);
+}
+
+/*
+ * Create a new view and add it to the list.
+ *
+ * If 'vconfig' is NULL, create the default view.
+ *
+ * The view created is attached to '*viewp'.
+ */
+static isc_result_t
+create_view(const cfg_obj_t *vconfig, dns_viewlist_t *viewlist,
+ dns_view_t **viewp)
+{
+ isc_result_t result;
+ const char *viewname;
+ dns_rdataclass_t viewclass;
+ dns_view_t *view = NULL;
+
+ if (vconfig != NULL) {
+ const cfg_obj_t *classobj = NULL;
+
+ viewname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
+ classobj = cfg_tuple_get(vconfig, "class");
+ result = ns_config_getclass(classobj, dns_rdataclass_in,
+ &viewclass);
+ } else {
+ viewname = "_default";
+ viewclass = dns_rdataclass_in;
+ }
+ result = dns_viewlist_find(viewlist, viewname, viewclass, &view);
+ if (result == ISC_R_SUCCESS)
+ return (ISC_R_EXISTS);
+ if (result != ISC_R_NOTFOUND)
+ return (result);
+ INSIST(view == NULL);
+
+ result = dns_view_create(ns_g_mctx, viewclass, viewname, &view);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ ISC_LIST_APPEND(*viewlist, view, link);
+ dns_view_attach(view, viewp);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Configure or reconfigure a zone.
+ */
+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)
+{
+ dns_view_t *pview = NULL; /* Production view */
+ dns_zone_t *zone = NULL; /* New or reused zone */
+ dns_zone_t *dupzone = NULL;
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *zoptions = NULL;
+ const cfg_obj_t *typeobj = NULL;
+ const cfg_obj_t *forwarders = NULL;
+ const cfg_obj_t *forwardtype = NULL;
+ const cfg_obj_t *only = NULL;
+ isc_result_t result;
+ isc_result_t tresult;
+ isc_buffer_t buffer;
+ dns_fixedname_t fixorigin;
+ dns_name_t *origin;
+ const char *zname;
+ dns_rdataclass_t zclass;
+ const char *ztypestr;
+
+ options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+
+ /*
+ * Get the zone origin as a dns_name_t.
+ */
+ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+ isc_buffer_init(&buffer, zname, strlen(zname));
+ isc_buffer_add(&buffer, strlen(zname));
+ dns_fixedname_init(&fixorigin);
+ CHECK(dns_name_fromtext(dns_fixedname_name(&fixorigin),
+ &buffer, dns_rootname, ISC_FALSE, NULL));
+ origin = dns_fixedname_name(&fixorigin);
+
+ CHECK(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
+ view->rdclass, &zclass));
+ if (zclass != view->rdclass) {
+ const char *vname = NULL;
+ if (vconfig != NULL)
+ vname = cfg_obj_asstring(cfg_tuple_get(vconfig,
+ "name"));
+ else
+ vname = "<default view>";
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': wrong class for view '%s'",
+ zname, vname);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ (void)cfg_map_get(zoptions, "type", &typeobj);
+ if (typeobj == NULL) {
+ cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
+ "zone '%s' 'type' not specified", zname);
+ return (ISC_R_FAILURE);
+ }
+ ztypestr = cfg_obj_asstring(typeobj);
+
+ /*
+ * "hints zones" aren't zones. If we've got one,
+ * configure it and return.
+ */
+ if (strcasecmp(ztypestr, "hint") == 0) {
+ const cfg_obj_t *fileobj = NULL;
+ if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "zone '%s': 'file' not specified",
+ zname);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ if (dns_name_equal(origin, dns_rootname)) {
+ const char *hintsfile = cfg_obj_asstring(fileobj);
+
+ result = configure_hints(view, hintsfile);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_ERROR,
+ "could not configure root hints "
+ "from '%s': %s", hintsfile,
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ /*
+ * Hint zones may also refer to delegation only points.
+ */
+ only = NULL;
+ tresult = cfg_map_get(zoptions, "delegation-only",
+ &only);
+ if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(only))
+ CHECK(dns_view_adddelegationonly(view, origin));
+ } else {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "ignoring non-root hint zone '%s'",
+ zname);
+ result = ISC_R_SUCCESS;
+ }
+ /* Skip ordinary zone processing. */
+ goto cleanup;
+ }
+
+ /*
+ * "forward zones" aren't zones either. Translate this syntax into
+ * the appropriate selective forwarding configuration and return.
+ */
+ if (strcasecmp(ztypestr, "forward") == 0) {
+ forwardtype = NULL;
+ forwarders = NULL;
+
+ (void)cfg_map_get(zoptions, "forward", &forwardtype);
+ (void)cfg_map_get(zoptions, "forwarders", &forwarders);
+ result = configure_forward(config, view, origin, forwarders,
+ forwardtype);
+ goto cleanup;
+ }
+
+ /*
+ * "delegation-only zones" aren't zones either.
+ */
+ if (strcasecmp(ztypestr, "delegation-only") == 0) {
+ result = dns_view_adddelegationonly(view, origin);
+ goto cleanup;
+ }
+
+ /*
+ * Check for duplicates in the new zone table.
+ */
+ result = dns_view_findzone(view, origin, &dupzone);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We already have this zone!
+ */
+ cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
+ "zone '%s' already exists", zname);
+ dns_zone_detach(&dupzone);
+ result = ISC_R_EXISTS;
+ goto cleanup;
+ }
+ INSIST(dupzone == NULL);
+
+ /*
+ * See if we can reuse an existing zone. This is
+ * only possible if all of these are true:
+ * - The zone's view exists
+ * - A zone with the right name exists in the view
+ * - The zone is compatible with the config
+ * options (e.g., an existing master zone cannot
+ * be reused if the options specify a slave zone)
+ */
+ 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)
+ result = dns_view_findzone(pview, origin, &zone);
+ if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
+ goto cleanup;
+ if (zone != NULL && !ns_zone_reusable(zone, zconfig))
+ dns_zone_detach(&zone);
+
+ if (zone != NULL) {
+ /*
+ * We found a reusable zone. Make it use the
+ * new view.
+ */
+ dns_zone_setview(zone, view);
+ if (view->acache != NULL)
+ dns_zone_setacache(zone, view->acache);
+ } else {
+ /*
+ * We cannot reuse an existing zone, we have
+ * to create a new one.
+ */
+ CHECK(dns_zone_create(&zone, mctx));
+ CHECK(dns_zone_setorigin(zone, origin));
+ dns_zone_setview(zone, view);
+ if (view->acache != NULL)
+ dns_zone_setacache(zone, view->acache);
+ CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
+ dns_zone_setstats(zone, ns_g_server->zonestats);
+ }
+
+ /*
+ * If the zone contains a 'forwarders' statement, configure
+ * selective forwarding.
+ */
+ forwarders = NULL;
+ if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS)
+ {
+ forwardtype = NULL;
+ (void)cfg_map_get(zoptions, "forward", &forwardtype);
+ CHECK(configure_forward(config, view, origin, forwarders,
+ forwardtype));
+ }
+
+ /*
+ * Stub and forward zones may also refer to delegation only points.
+ */
+ only = NULL;
+ if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS)
+ {
+ if (cfg_obj_asboolean(only))
+ CHECK(dns_view_adddelegationonly(view, origin));
+ }
+
+ /*
+ * Configure the zone.
+ */
+ CHECK(ns_zone_configure(config, vconfig, zconfig, aclconf, zone));
+
+ /*
+ * Add the zone to its view in the new view list.
+ */
+ CHECK(dns_view_addzone(view, zone));
+
+ cleanup:
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ if (pview != NULL)
+ dns_view_detach(&pview);
+
+ return (result);
+}
+
+/*
+ * Configure a single server quota.
+ */
+static void
+configure_server_quota(const cfg_obj_t **maps, const char *name,
+ isc_quota_t *quota)
+{
+ const cfg_obj_t *obj = NULL;
+ isc_result_t result;
+
+ result = ns_config_get(maps, name, &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ isc_quota_max(quota, cfg_obj_asuint32(obj));
+}
+
+/*
+ * This function is called as soon as the 'directory' statement has been
+ * parsed. This can be extended to support other options if necessary.
+ */
+static isc_result_t
+directory_callback(const char *clausename, const cfg_obj_t *obj, void *arg) {
+ isc_result_t result;
+ const char *directory;
+
+ REQUIRE(strcasecmp("directory", clausename) == 0);
+
+ UNUSED(arg);
+ UNUSED(clausename);
+
+ /*
+ * Change directory.
+ */
+ directory = cfg_obj_asstring(obj);
+
+ if (! isc_file_ischdiridempotent(directory))
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_WARNING,
+ "option 'directory' contains relative path '%s'",
+ directory);
+
+ result = isc_dir_chdir(directory);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR,
+ "change directory to '%s' failed: %s",
+ directory, isc_result_totext(result));
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+scan_interfaces(ns_server_t *server, isc_boolean_t verbose) {
+ isc_boolean_t match_mapped = server->aclenv.match_mapped;
+
+ ns_interfacemgr_scan(server->interfacemgr, verbose);
+ /*
+ * Update the "localhost" and "localnets" ACLs to match the
+ * current set of network interfaces.
+ */
+ dns_aclenv_copy(&server->aclenv,
+ ns_interfacemgr_getaclenv(server->interfacemgr));
+
+ server->aclenv.match_mapped = match_mapped;
+}
+
+static isc_result_t
+add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr,
+ isc_boolean_t wcardport_ok)
+{
+ ns_listenelt_t *lelt = NULL;
+ dns_acl_t *src_acl = NULL;
+ isc_result_t result;
+ isc_sockaddr_t any_sa6;
+ isc_netaddr_t netaddr;
+
+ REQUIRE(isc_sockaddr_pf(addr) == AF_INET6);
+
+ isc_sockaddr_any6(&any_sa6);
+ if (!isc_sockaddr_equal(&any_sa6, addr) &&
+ (wcardport_ok || isc_sockaddr_getport(addr) != 0)) {
+ isc_netaddr_fromin6(&netaddr, &addr->type.sin6.sin6_addr);
+
+ result = dns_acl_create(mctx, 0, &src_acl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_iptable_addprefix(src_acl->iptable,
+ &netaddr, 128, ISC_TRUE);
+ if (result != ISC_R_SUCCESS)
+ goto clean;
+
+ result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr),
+ src_acl, &lelt);
+ if (result != ISC_R_SUCCESS)
+ goto clean;
+ ISC_LIST_APPEND(list->elts, lelt, link);
+ }
+
+ return (ISC_R_SUCCESS);
+
+ clean:
+ INSIST(lelt == NULL);
+ dns_acl_detach(&src_acl);
+
+ return (result);
+}
+
+/*
+ * Make a list of xxx-source addresses and call ns_interfacemgr_adjust()
+ * to update the listening interfaces accordingly.
+ * We currently only consider IPv6, because this only affects IPv6 wildcard
+ * sockets.
+ */
+static void
+adjust_interfaces(ns_server_t *server, isc_mem_t *mctx) {
+ isc_result_t result;
+ ns_listenlist_t *list = NULL;
+ dns_view_t *view;
+ dns_zone_t *zone, *next;
+ isc_sockaddr_t addr, *addrp;
+
+ result = ns_listenlist_create(mctx, &list);
+ if (result != ISC_R_SUCCESS)
+ return;
+
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ dns_dispatch_t *dispatch6;
+
+ dispatch6 = dns_resolver_dispatchv6(view->resolver);
+ if (dispatch6 == NULL)
+ continue;
+ result = dns_dispatch_getlocaladdress(dispatch6, &addr);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ /*
+ * We always add non-wildcard address regardless of whether
+ * the port is 'any' (the fourth arg is TRUE): if the port is
+ * specific, we need to add it since it may conflict with a
+ * listening interface; if it's zero, we'll dynamically open
+ * query ports, and some of them may override an existing
+ * wildcard IPv6 port.
+ */
+ result = add_listenelt(mctx, list, &addr, ISC_TRUE);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ }
+
+ zone = NULL;
+ for (result = dns_zone_first(server->zonemgr, &zone);
+ result == ISC_R_SUCCESS;
+ next = NULL, result = dns_zone_next(zone, &next), zone = next) {
+ dns_view_t *zoneview;
+
+ /*
+ * At this point the zone list may contain a stale zone
+ * just removed from the configuration. To see the validity,
+ * check if the corresponding view is in our current view list.
+ * There may also be old zones that are still in the process
+ * of shutting down and have detached from their old view
+ * (zoneview == NULL).
+ */
+ zoneview = dns_zone_getview(zone);
+ if (zoneview == NULL)
+ continue;
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL && view != zoneview;
+ view = ISC_LIST_NEXT(view, link))
+ ;
+ if (view == NULL)
+ continue;
+
+ addrp = dns_zone_getnotifysrc6(zone);
+ result = add_listenelt(mctx, list, addrp, ISC_FALSE);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ addrp = dns_zone_getxfrsource6(zone);
+ result = add_listenelt(mctx, list, addrp, ISC_FALSE);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ }
+
+ ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE);
+
+ clean:
+ ns_listenlist_detach(&list);
+ return;
+
+ fail:
+ /*
+ * Even when we failed the procedure, most of other interfaces
+ * should work correctly. We therefore just warn it.
+ */
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "could not adjust the listen-on list; "
+ "some interfaces may not work");
+ goto clean;
+}
+
+/*
+ * This event callback is invoked to do periodic network
+ * interface scanning.
+ */
+static void
+interface_timer_tick(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ ns_server_t *server = (ns_server_t *) event->ev_arg;
+ INSIST(task == server->task);
+ UNUSED(task);
+ isc_event_free(&event);
+ /*
+ * XXX should scan interfaces unlocked and get exclusive access
+ * only to replace ACLs.
+ */
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ scan_interfaces(server, ISC_FALSE);
+ isc_task_endexclusive(server->task);
+}
+
+static void
+heartbeat_timer_tick(isc_task_t *task, isc_event_t *event) {
+ ns_server_t *server = (ns_server_t *) event->ev_arg;
+ dns_view_t *view;
+
+ UNUSED(task);
+ isc_event_free(&event);
+ view = ISC_LIST_HEAD(server->viewlist);
+ while (view != NULL) {
+ dns_view_dialup(view);
+ view = ISC_LIST_NEXT(view, link);
+ }
+}
+
+static void
+pps_timer_tick(isc_task_t *task, isc_event_t *event) {
+ static unsigned int oldrequests = 0;
+ unsigned int requests = ns_client_requests;
+
+ UNUSED(task);
+ isc_event_free(&event);
+
+ /*
+ * Don't worry about wrapping as the overflow result will be right.
+ */
+ dns_pps = (requests - oldrequests) / 1200;
+ oldrequests = requests;
+}
+
+/*
+ * Replace the current value of '*field', a dynamically allocated
+ * string or NULL, with a dynamically allocated copy of the
+ * null-terminated string pointed to by 'value', or NULL.
+ */
+static isc_result_t
+setstring(ns_server_t *server, char **field, const char *value) {
+ char *copy;
+
+ if (value != NULL) {
+ copy = isc_mem_strdup(server->mctx, value);
+ if (copy == NULL)
+ return (ISC_R_NOMEMORY);
+ } else {
+ copy = NULL;
+ }
+
+ if (*field != NULL)
+ isc_mem_free(server->mctx, *field);
+
+ *field = copy;
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Replace the current value of '*field', a dynamically allocated
+ * string or NULL, with another dynamically allocated string
+ * or NULL if whether 'obj' is a string or void value, respectively.
+ */
+static isc_result_t
+setoptstring(ns_server_t *server, char **field, const cfg_obj_t *obj) {
+ if (cfg_obj_isvoid(obj))
+ return (setstring(server, field, NULL));
+ else
+ return (setstring(server, field, cfg_obj_asstring(obj)));
+}
+
+static void
+set_limit(const cfg_obj_t **maps, const char *configname,
+ const char *description, isc_resource_t resourceid,
+ isc_resourcevalue_t defaultvalue)
+{
+ const cfg_obj_t *obj = NULL;
+ const char *resource;
+ isc_resourcevalue_t value;
+ isc_result_t result;
+
+ if (ns_config_get(maps, configname, &obj) != ISC_R_SUCCESS)
+ return;
+
+ if (cfg_obj_isstring(obj)) {
+ resource = cfg_obj_asstring(obj);
+ if (strcasecmp(resource, "unlimited") == 0)
+ value = ISC_RESOURCE_UNLIMITED;
+ else {
+ INSIST(strcasecmp(resource, "default") == 0);
+ value = defaultvalue;
+ }
+ } else
+ value = cfg_obj_asuint64(obj);
+
+ result = isc_resource_setlimit(resourceid, value);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ result == ISC_R_SUCCESS ?
+ ISC_LOG_DEBUG(3) : ISC_LOG_WARNING,
+ "set maximum %s to %" ISC_PRINT_QUADFORMAT "d: %s",
+ description, value, isc_result_totext(result));
+}
+
+#define SETLIMIT(cfgvar, resource, description) \
+ set_limit(maps, cfgvar, description, isc_resource_ ## resource, \
+ ns_g_init ## resource)
+
+static void
+set_limits(const cfg_obj_t **maps) {
+ SETLIMIT("stacksize", stacksize, "stack size");
+ SETLIMIT("datasize", datasize, "data size");
+ SETLIMIT("coresize", coresize, "core size");
+ SETLIMIT("files", openfiles, "open files");
+}
+
+static void
+portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports,
+ isc_boolean_t positive)
+{
+ const cfg_listelt_t *element;
+
+ for (element = cfg_list_first(ports);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ const cfg_obj_t *obj = cfg_listelt_value(element);
+
+ if (cfg_obj_isuint32(obj)) {
+ in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
+
+ if (positive)
+ isc_portset_add(portset, port);
+ else
+ isc_portset_remove(portset, port);
+ } else {
+ const cfg_obj_t *obj_loport, *obj_hiport;
+ in_port_t loport, hiport;
+
+ obj_loport = cfg_tuple_get(obj, "loport");
+ loport = (in_port_t)cfg_obj_asuint32(obj_loport);
+ obj_hiport = cfg_tuple_get(obj, "hiport");
+ hiport = (in_port_t)cfg_obj_asuint32(obj_hiport);
+
+ if (positive)
+ isc_portset_addrange(portset, loport, hiport);
+ else {
+ isc_portset_removerange(portset, loport,
+ hiport);
+ }
+ }
+ }
+}
+
+static isc_result_t
+removed(dns_zone_t *zone, void *uap) {
+ const char *type;
+
+ if (dns_zone_getview(zone) != uap)
+ return (ISC_R_SUCCESS);
+
+ switch (dns_zone_gettype(zone)) {
+ case dns_zone_master:
+ type = "master";
+ break;
+ case dns_zone_slave:
+ type = "slave";
+ break;
+ case dns_zone_stub:
+ type = "stub";
+ break;
+ default:
+ type = "other";
+ break;
+ }
+ dns_zone_log(zone, ISC_LOG_INFO, "(%s) removed", type);
+ return (ISC_R_SUCCESS);
+}
+
+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;
+ const cfg_listelt_t *element;
+ const cfg_obj_t *builtin_views;
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *obj;
+ const cfg_obj_t *options;
+ const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports;
+ const cfg_obj_t *views;
+ dns_view_t *view = NULL;
+ dns_view_t *view_next;
+ dns_viewlist_t tmpviewlist;
+ dns_viewlist_t viewlist;
+ in_port_t listen_port, udpport_low, udpport_high;
+ int i;
+ isc_interval_t interval;
+ isc_portset_t *v4portset = NULL;
+ isc_portset_t *v6portset = NULL;
+ isc_resourcevalue_t nfiles;
+ isc_result_t result;
+ isc_uint32_t heartbeat_interval;
+ isc_uint32_t interface_interval;
+ isc_uint32_t reserved;
+ isc_uint32_t udpsize;
+ unsigned int maxsocks;
+
+ cfg_aclconfctx_init(&aclconfctx);
+ ISC_LIST_INIT(viewlist);
+
+ /* Ensure exclusive access to configuration data. */
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ /*
+ * Parse the global default pseudo-config file.
+ */
+ 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);
+ }
+
+ /*
+ * Parse the configuration file using the new config code.
+ */
+ result = ISC_R_FAILURE;
+ config = NULL;
+
+ /*
+ * Unless this is lwresd with the -C option, parse the config file.
+ */
+ if (!(ns_g_lwresdonly && lwresd_g_useresolvconf)) {
+ isc_log_write(ns_g_lctx,
+ 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);
+ }
+
+ /*
+ * If this is lwresd with the -C option, or lwresd with no -C or -c
+ * option where the above parsing failed, parse resolv.conf.
+ */
+ if (ns_g_lwresdonly &&
+ (lwresd_g_useresolvconf ||
+ (!ns_g_conffileset && result == ISC_R_FILENOTFOUND)))
+ {
+ isc_log_write(ns_g_lctx,
+ 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,
+ &config);
+ }
+ CHECK(result);
+
+ /*
+ * Check the validity of the configuration.
+ */
+ CHECK(bind9_check_namedconf(config, ns_g_lctx, ns_g_mctx));
+
+ /*
+ * Fill in the maps array, used for resolving defaults.
+ */
+ i = 0;
+ options = NULL;
+ result = cfg_map_get(config, "options", &options);
+ if (result == ISC_R_SUCCESS)
+ maps[i++] = options;
+ maps[i++] = ns_g_defaults;
+ maps[i++] = NULL;
+
+ /*
+ * 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,
+ * but may cause subsequent runtime failures for a busy recursive
+ * server.
+ */
+ result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &maxsocks);
+ if (result != ISC_R_SUCCESS)
+ maxsocks = 0;
+ result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles);
+ if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "max open files (%" ISC_PRINT_QUADFORMAT "u)"
+ " is smaller than max sockets (%u)",
+ nfiles, maxsocks);
+ }
+
+ /*
+ * Set the number of socket reserved for TCP, stdio etc.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "reserved-sockets", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ reserved = cfg_obj_asuint32(obj);
+ if (maxsocks != 0) {
+ if (maxsocks < 128U) /* Prevent underflow. */
+ reserved = 0;
+ else if (reserved > maxsocks - 128U) /* Minimum UDP space. */
+ reserved = maxsocks - 128;
+ }
+ /* Minimum TCP/stdio space. */
+ if (reserved < 128U)
+ reserved = 128;
+ if (reserved + 128U > maxsocks && maxsocks != 0) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "less than 128 UDP sockets available after "
+ "applying 'reserved-sockets' and 'maxsockets'");
+ }
+ isc__socketmgr_setreserved(ns_g_socketmgr, reserved);
+
+ /*
+ * Configure various server options.
+ */
+ configure_server_quota(maps, "transfers-out", &server->xfroutquota);
+ configure_server_quota(maps, "tcp-clients", &server->tcpquota);
+ configure_server_quota(maps, "recursive-clients",
+ &server->recursionquota);
+ if (server->recursionquota.max > 1000)
+ isc_quota_soft(&server->recursionquota,
+ server->recursionquota.max - 100);
+ else
+ isc_quota_soft(&server->recursionquota, 0);
+
+ CHECK(configure_view_acl(NULL, config, "blackhole", &aclconfctx,
+ ns_g_mctx, &server->blackholeacl));
+ if (server->blackholeacl != NULL)
+ dns_dispatchmgr_setblackhole(ns_g_dispatchmgr,
+ server->blackholeacl);
+
+ obj = NULL;
+ result = ns_config_get(maps, "match-mapped-addresses", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ server->aclenv.match_mapped = cfg_obj_asboolean(obj);
+
+ CHECKM(ns_statschannels_configure(ns_g_server, config, &aclconfctx),
+ "configuring statistics server(s)");
+
+ /*
+ * Configure sets of UDP query source ports.
+ */
+ CHECKM(isc_portset_create(ns_g_mctx, &v4portset),
+ "creating UDP port set");
+ CHECKM(isc_portset_create(ns_g_mctx, &v6portset),
+ "creating UDP port set");
+
+ usev4ports = NULL;
+ usev6ports = NULL;
+ avoidv4ports = NULL;
+ avoidv6ports = NULL;
+
+ (void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports);
+ if (usev4ports != NULL)
+ portset_fromconf(v4portset, usev4ports, ISC_TRUE);
+ else {
+ CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low,
+ &udpport_high),
+ "get the default UDP/IPv4 port range");
+ if (udpport_low == udpport_high)
+ isc_portset_add(v4portset, udpport_low);
+ else {
+ isc_portset_addrange(v4portset, udpport_low,
+ udpport_high);
+ }
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "using default UDP/IPv4 port range: [%d, %d]",
+ udpport_low, udpport_high);
+ }
+ (void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);
+ if (avoidv4ports != NULL)
+ portset_fromconf(v4portset, avoidv4ports, ISC_FALSE);
+
+ (void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports);
+ if (usev6ports != NULL)
+ portset_fromconf(v6portset, usev6ports, ISC_TRUE);
+ else {
+ CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low,
+ &udpport_high),
+ "get the default UDP/IPv6 port range");
+ if (udpport_low == udpport_high)
+ isc_portset_add(v6portset, udpport_low);
+ else {
+ isc_portset_addrange(v6portset, udpport_low,
+ udpport_high);
+ }
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "using default UDP/IPv6 port range: [%d, %d]",
+ udpport_low, udpport_high);
+ }
+ (void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);
+ if (avoidv6ports != NULL)
+ portset_fromconf(v6portset, avoidv6ports, ISC_FALSE);
+
+ dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset);
+
+ /*
+ * Set the EDNS UDP size when we don't match a view.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "edns-udp-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ udpsize = cfg_obj_asuint32(obj);
+ if (udpsize < 512)
+ udpsize = 512;
+ if (udpsize > 4096)
+ udpsize = 4096;
+ ns_g_udpsize = (isc_uint16_t)udpsize;
+
+ /*
+ * Configure the zone manager.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "transfers-in", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_settransfersin(server->zonemgr, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "transfers-per-ns", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_settransfersperns(server->zonemgr, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "serial-query-rate", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zonemgr_setserialqueryrate(server->zonemgr, cfg_obj_asuint32(obj));
+
+ /*
+ * Determine which port to use for listening for incoming connections.
+ */
+ if (ns_g_port != 0)
+ listen_port = ns_g_port;
+ else
+ CHECKM(ns_config_getport(config, &listen_port), "port");
+
+ /*
+ * Find the listen queue depth.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "tcp-listen-queue", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ ns_g_listen = cfg_obj_asuint32(obj);
+ if (ns_g_listen < 3)
+ ns_g_listen = 3;
+
+ /*
+ * Configure the interface manager according to the "listen-on"
+ * statement.
+ */
+ {
+ const cfg_obj_t *clistenon = NULL;
+ ns_listenlist_t *listenon = NULL;
+
+ clistenon = NULL;
+ /*
+ * Even though listen-on is present in the default
+ * configuration, we can't use it here, since it isn't
+ * used if we're in lwresd mode. This way is easier.
+ */
+ if (options != NULL)
+ (void)cfg_map_get(options, "listen-on", &clistenon);
+ if (clistenon != NULL) {
+ result = ns_listenlist_fromconfig(clistenon,
+ config,
+ &aclconfctx,
+ ns_g_mctx,
+ &listenon);
+ } else if (!ns_g_lwresdonly) {
+ /*
+ * Not specified, use default.
+ */
+ CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
+ ISC_TRUE, &listenon));
+ }
+ if (listenon != NULL) {
+ ns_interfacemgr_setlistenon4(server->interfacemgr,
+ listenon);
+ ns_listenlist_detach(&listenon);
+ }
+ }
+ /*
+ * Ditto for IPv6.
+ */
+ {
+ const cfg_obj_t *clistenon = NULL;
+ ns_listenlist_t *listenon = NULL;
+
+ if (options != NULL)
+ (void)cfg_map_get(options, "listen-on-v6", &clistenon);
+ if (clistenon != NULL) {
+ result = ns_listenlist_fromconfig(clistenon,
+ config,
+ &aclconfctx,
+ ns_g_mctx,
+ &listenon);
+ } else if (!ns_g_lwresdonly) {
+ isc_boolean_t enable;
+ /*
+ * Not specified, use default.
+ */
+ enable = ISC_TF(isc_net_probeipv4() != ISC_R_SUCCESS);
+ CHECK(ns_listenlist_default(ns_g_mctx, listen_port,
+ enable, &listenon));
+ }
+ if (listenon != NULL) {
+ ns_interfacemgr_setlistenon6(server->interfacemgr,
+ listenon);
+ ns_listenlist_detach(&listenon);
+ }
+ }
+
+ /*
+ * Rescan the interface list to pick up changes in the
+ * listen-on option. It's important that we do this before we try
+ * to configure the query source, since the dispatcher we use might
+ * be shared with an interface.
+ */
+ scan_interfaces(server, ISC_TRUE);
+
+ /*
+ * Arrange for further interface scanning to occur periodically
+ * as specified by the "interface-interval" option.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "interface-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ interface_interval = cfg_obj_asuint32(obj) * 60;
+ if (interface_interval == 0) {
+ CHECK(isc_timer_reset(server->interface_timer,
+ isc_timertype_inactive,
+ NULL, NULL, ISC_TRUE));
+ } else if (server->interface_interval != interface_interval) {
+ isc_interval_set(&interval, interface_interval, 0);
+ CHECK(isc_timer_reset(server->interface_timer,
+ isc_timertype_ticker,
+ NULL, &interval, ISC_FALSE));
+ }
+ server->interface_interval = interface_interval;
+
+ /*
+ * Configure the dialup heartbeat timer.
+ */
+ obj = NULL;
+ result = ns_config_get(maps, "heartbeat-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ heartbeat_interval = cfg_obj_asuint32(obj) * 60;
+ if (heartbeat_interval == 0) {
+ CHECK(isc_timer_reset(server->heartbeat_timer,
+ isc_timertype_inactive,
+ NULL, NULL, ISC_TRUE));
+ } else if (server->heartbeat_interval != heartbeat_interval) {
+ isc_interval_set(&interval, heartbeat_interval, 0);
+ CHECK(isc_timer_reset(server->heartbeat_timer,
+ isc_timertype_ticker,
+ NULL, &interval, ISC_FALSE));
+ }
+ server->heartbeat_interval = heartbeat_interval;
+
+ isc_interval_set(&interval, 1200, 0);
+ CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL,
+ &interval, ISC_FALSE));
+
+ /*
+ * 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.
+ */
+ views = NULL;
+ (void)cfg_map_get(config, "view", &views);
+ for (element = cfg_list_first(views);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const 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,
+ ns_g_mctx, &aclconfctx, ISC_TRUE));
+ dns_view_freeze(view);
+ dns_view_detach(&view);
+ }
+
+ /*
+ * Make sure we have a default view if and only if there
+ * were no explicit views.
+ */
+ if (views == NULL) {
+ /*
+ * No explicit views; there ought to be a default view.
+ * There may already be one created as a side effect
+ * of zone statements, or we may have to create one.
+ * 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));
+ dns_view_freeze(view);
+ dns_view_detach(&view);
+ }
+
+ /*
+ * Create (or recreate) the built-in views. Currently
+ * there is only one, the _bind view.
+ */
+ builtin_views = NULL;
+ RUNTIME_CHECK(cfg_map_get(ns_g_config, "view",
+ &builtin_views) == ISC_R_SUCCESS);
+ for (element = cfg_list_first(builtin_views);
+ 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));
+ dns_view_freeze(view);
+ dns_view_detach(&view);
+ view = NULL;
+ }
+
+ /*
+ * Swap our new view list with the production one.
+ */
+ tmpviewlist = server->viewlist;
+ server->viewlist = viewlist;
+ viewlist = tmpviewlist;
+
+ /*
+ * 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,
+ &t),
+ "configuring TKEY");
+ if (server->tkeyctx != NULL)
+ dns_tkeyctx_destroy(&server->tkeyctx);
+ server->tkeyctx = t;
+ }
+
+ /*
+ * Bind the control port(s).
+ */
+ CHECKM(ns_controls_configure(ns_g_server->controls, config,
+ &aclconfctx),
+ "binding control channel(s)");
+
+ /*
+ * Bind the lwresd port(s).
+ */
+ CHECKM(ns_lwresd_configure(ns_g_mctx, config),
+ "binding lightweight resolver ports");
+
+ /*
+ * Open the source of entropy.
+ */
+ if (first_time) {
+ obj = NULL;
+ result = ns_config_get(maps, "random-device", &obj);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "no source of entropy found");
+ } else {
+ const char *randomdev = cfg_obj_asstring(obj);
+ result = isc_entropy_createfilesource(ns_g_entropy,
+ randomdev);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO,
+ "could not open entropy source "
+ "%s: %s",
+ randomdev,
+ isc_result_totext(result));
+#ifdef PATH_RANDOMDEV
+ if (ns_g_fallbackentropy != NULL) {
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO,
+ "using pre-chroot entropy source "
+ "%s",
+ PATH_RANDOMDEV);
+ isc_entropy_detach(&ns_g_entropy);
+ isc_entropy_attach(ns_g_fallbackentropy,
+ &ns_g_entropy);
+ }
+ isc_entropy_detach(&ns_g_fallbackentropy);
+ }
+#endif
+ }
+ }
+
+ /*
+ * Relinquish root privileges.
+ */
+ if (first_time)
+ ns_os_changeuser();
+
+ /*
+ * Check that the working directory is writable.
+ */
+ if (access(".", W_OK) != 0) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "the working directory is not writable");
+ }
+
+ /*
+ * Configure the logging system.
+ *
+ * Do this after changing UID to make sure that any log
+ * files specified in named.conf get created by the
+ * unprivileged user, not root.
+ */
+ if (ns_g_logstderr) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "ignoring config file logging "
+ "statement due to -g option");
+ } else {
+ const cfg_obj_t *logobj = NULL;
+ isc_logconfig_t *logc = NULL;
+
+ CHECKM(isc_logconfig_create(ns_g_lctx, &logc),
+ "creating new logging configuration");
+
+ logobj = NULL;
+ (void)cfg_map_get(config, "logging", &logobj);
+ if (logobj != NULL) {
+ CHECKM(ns_log_configure(logc, logobj),
+ "configuring logging");
+ } else {
+ CHECKM(ns_log_setdefaultchannels(logc),
+ "setting up default logging channels");
+ CHECKM(ns_log_setunmatchedcategory(logc),
+ "setting up default 'category unmatched'");
+ CHECKM(ns_log_setdefaultcategory(logc),
+ "setting up default 'category default'");
+ }
+
+ result = isc_logconfig_use(ns_g_lctx, logc);
+ if (result != ISC_R_SUCCESS) {
+ isc_logconfig_destroy(&logc);
+ CHECKM(result, "installing logging configuration");
+ }
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(1),
+ "now using logging configuration from "
+ "config file");
+ }
+
+ /*
+ * Set the default value of the query logging flag depending
+ * whether a "queries" category has been defined. This is
+ * a disgusting hack, but we need to do this for BIND 8
+ * compatibility.
+ */
+ if (first_time) {
+ const cfg_obj_t *logobj = NULL;
+ const cfg_obj_t *categories = NULL;
+
+ obj = NULL;
+ if (ns_config_get(maps, "querylog", &obj) == ISC_R_SUCCESS) {
+ server->log_queries = cfg_obj_asboolean(obj);
+ } else {
+
+ (void)cfg_map_get(config, "logging", &logobj);
+ if (logobj != NULL)
+ (void)cfg_map_get(logobj, "category",
+ &categories);
+ if (categories != NULL) {
+ const cfg_listelt_t *element;
+ for (element = cfg_list_first(categories);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *catobj;
+ const char *str;
+
+ obj = cfg_listelt_value(element);
+ catobj = cfg_tuple_get(obj, "name");
+ str = cfg_obj_asstring(catobj);
+ if (strcasecmp(str, "queries") == 0)
+ server->log_queries = ISC_TRUE;
+ }
+ }
+ }
+ }
+
+ 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 &&
+ cfg_map_get(options, "memstatistics", &obj) == ISC_R_SUCCESS)
+ ns_g_memstatistics = cfg_obj_asboolean(obj);
+ else
+ ns_g_memstatistics =
+ ISC_TF((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0);
+
+ obj = NULL;
+ if (ns_config_get(maps, "memstatistics-file", &obj) == ISC_R_SUCCESS)
+ ns_main_setmemstats(cfg_obj_asstring(obj));
+ else if (ns_g_memstatistics)
+ ns_main_setmemstats("named.memstats");
+ else
+ ns_main_setmemstats(NULL);
+
+ obj = NULL;
+ result = ns_config_get(maps, "statistics-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->statsfile, cfg_obj_asstring(obj)),
+ "strdup");
+
+ obj = NULL;
+ result = ns_config_get(maps, "dump-file", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ CHECKM(setstring(server, &server->dumpfile, 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)),
+ "strdup");
+
+ obj = NULL;
+ result = ns_config_get(maps, "version", &obj);
+ if (result == ISC_R_SUCCESS) {
+ CHECKM(setoptstring(server, &server->version, obj), "strdup");
+ server->version_set = ISC_TRUE;
+ } else {
+ server->version_set = ISC_FALSE;
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "hostname", &obj);
+ if (result == ISC_R_SUCCESS) {
+ CHECKM(setoptstring(server, &server->hostname, obj), "strdup");
+ server->hostname_set = ISC_TRUE;
+ } else {
+ server->hostname_set = ISC_FALSE;
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "server-id", &obj);
+ server->server_usehostname = ISC_FALSE;
+ if (result == ISC_R_SUCCESS && cfg_obj_isboolean(obj)) {
+ /* The parser translates "hostname" to ISC_TRUE */
+ server->server_usehostname = cfg_obj_asboolean(obj);
+ result = setstring(server, &server->server_id, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ } else if (result == ISC_R_SUCCESS) {
+ /* Found a quoted string */
+ CHECKM(setoptstring(server, &server->server_id, obj), "strdup");
+ } else {
+ result = setstring(server, &server->server_id, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "flush-zones-on-shutdown", &obj);
+ if (result == ISC_R_SUCCESS) {
+ server->flushonshutdown = cfg_obj_asboolean(obj);
+ } else {
+ server->flushonshutdown = ISC_FALSE;
+ }
+
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (v4portset != NULL)
+ isc_portset_destroy(ns_g_mctx, &v4portset);
+
+ if (v6portset != NULL)
+ isc_portset_destroy(ns_g_mctx, &v6portset);
+
+ cfg_aclconfctx_destroy(&aclconfctx);
+
+ if (parser != NULL) {
+ if (config != NULL)
+ cfg_obj_destroy(parser, &config);
+ cfg_parser_destroy(&parser);
+ }
+
+ if (view != NULL)
+ dns_view_detach(&view);
+
+ /*
+ * This cleans up either the old production view list
+ * or our temporary list depending on whether they
+ * were swapped above or not.
+ */
+ for (view = ISC_LIST_HEAD(viewlist);
+ view != NULL;
+ view = view_next) {
+ view_next = ISC_LIST_NEXT(view, link);
+ ISC_LIST_UNLINK(viewlist, view, link);
+ if (result == ISC_R_SUCCESS &&
+ strcmp(view->name, "_bind") != 0)
+ (void)dns_zt_apply(view->zonetable, ISC_FALSE,
+ removed, view);
+ dns_view_detach(&view);
+ }
+
+ /*
+ * Adjust the listening interfaces in accordance with the source
+ * addresses specified in views and zones.
+ */
+ if (isc_net_probeipv6() == ISC_R_SUCCESS)
+ adjust_interfaces(server, ns_g_mctx);
+
+ /* Relinquish exclusive access to configuration data. */
+ isc_task_endexclusive(server->task);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_DEBUG(1), "load_configuration: %s",
+ isc_result_totext(result));
+
+ return (result);
+}
+
+static isc_result_t
+load_zones(ns_server_t *server, isc_boolean_t stop) {
+ isc_result_t result;
+ dns_view_t *view;
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ /*
+ * Load zone data from disk.
+ */
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ CHECK(dns_view_load(view, stop));
+ }
+
+ /*
+ * 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.
+ */
+ CHECK(dns_zonemgr_forcemaint(server->zonemgr));
+ cleanup:
+ isc_task_endexclusive(server->task);
+ return (result);
+}
+
+static isc_result_t
+load_new_zones(ns_server_t *server, isc_boolean_t stop) {
+ isc_result_t result;
+ dns_view_t *view;
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ /*
+ * Load zone data from disk.
+ */
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ CHECK(dns_view_loadnew(view, stop));
+ }
+ /*
+ * 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.
+ */
+ dns_zonemgr_resumexfrs(server->zonemgr);
+ cleanup:
+ isc_task_endexclusive(server->task);
+ return (result);
+}
+
+static void
+run_server(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ ns_server_t *server = (ns_server_t *)event->ev_arg;
+
+ INSIST(task == server->task);
+
+ isc_event_free(&event);
+
+ CHECKFATAL(dns_dispatchmgr_create(ns_g_mctx, ns_g_entropy,
+ &ns_g_dispatchmgr),
+ "creating dispatch manager");
+
+ dns_dispatchmgr_setstats(ns_g_dispatchmgr, server->resolverstats);
+
+ CHECKFATAL(ns_interfacemgr_create(ns_g_mctx, ns_g_taskmgr,
+ ns_g_socketmgr, ns_g_dispatchmgr,
+ &server->interfacemgr),
+ "creating interface manager");
+
+ CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
+ NULL, NULL, server->task,
+ interface_timer_tick,
+ server, &server->interface_timer),
+ "creating interface timer");
+
+ CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
+ NULL, NULL, server->task,
+ heartbeat_timer_tick,
+ server, &server->heartbeat_timer),
+ "creating heartbeat timer");
+
+ CHECKFATAL(isc_timer_create(ns_g_timermgr, isc_timertype_inactive,
+ NULL, NULL, server->task, pps_timer_tick,
+ server, &server->pps_timer),
+ "creating pps timer");
+
+ CHECKFATAL(cfg_parser_create(ns_g_mctx, NULL, &ns_g_parser),
+ "creating default configuration parser");
+
+ if (ns_g_lwresdonly)
+ CHECKFATAL(load_configuration(lwresd_g_conffile, server,
+ ISC_TRUE),
+ "loading configuration");
+ else
+ CHECKFATAL(load_configuration(ns_g_conffile, server, ISC_TRUE),
+ "loading configuration");
+
+ isc_hash_init();
+
+ CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones");
+
+ ns_os_started();
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_NOTICE, "running");
+}
+
+void
+ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) {
+
+ REQUIRE(NS_SERVER_VALID(server));
+
+ server->flushonshutdown = flush;
+}
+
+static void
+shutdown_server(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ dns_view_t *view, *view_next;
+ ns_server_t *server = (ns_server_t *)event->ev_arg;
+ isc_boolean_t flush = server->flushonshutdown;
+
+ UNUSED(task);
+ INSIST(task == server->task);
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_INFO, "shutting down%s",
+ flush ? ": flushing changes" : "");
+
+ ns_statschannels_shutdown(server);
+ ns_controls_shutdown(server->controls);
+ end_reserved_dispatches(server, ISC_TRUE);
+
+ cfg_obj_destroy(ns_g_parser, &ns_g_config);
+ cfg_parser_destroy(&ns_g_parser);
+
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = view_next) {
+ view_next = ISC_LIST_NEXT(view, link);
+ ISC_LIST_UNLINK(server->viewlist, view, link);
+ if (flush)
+ dns_view_flushanddetach(&view);
+ else
+ dns_view_detach(&view);
+ }
+
+ isc_timer_detach(&server->interface_timer);
+ isc_timer_detach(&server->heartbeat_timer);
+ isc_timer_detach(&server->pps_timer);
+
+ ns_interfacemgr_shutdown(server->interfacemgr);
+ ns_interfacemgr_detach(&server->interfacemgr);
+
+ dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
+
+ dns_zonemgr_shutdown(server->zonemgr);
+
+ if (server->blackholeacl != NULL)
+ dns_acl_detach(&server->blackholeacl);
+
+ dns_db_detach(&server->in_roothints);
+
+ isc_task_endexclusive(server->task);
+
+ isc_task_detach(&server->task);
+
+ isc_event_free(&event);
+}
+
+void
+ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
+ isc_result_t result;
+
+ ns_server_t *server = isc_mem_get(mctx, sizeof(*server));
+ if (server == NULL)
+ fatal("allocating server object", ISC_R_NOMEMORY);
+
+ server->mctx = mctx;
+ server->task = NULL;
+
+ /* Initialize configuration data with default values. */
+
+ result = isc_quota_init(&server->xfroutquota, 10);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = isc_quota_init(&server->tcpquota, 10);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = isc_quota_init(&server->recursionquota, 100);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ result = dns_aclenv_init(mctx, &server->aclenv);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ /* Initialize server data structures. */
+ server->zonemgr = NULL;
+ server->interfacemgr = NULL;
+ ISC_LIST_INIT(server->viewlist);
+ server->in_roothints = NULL;
+ server->blackholeacl = NULL;
+
+ CHECKFATAL(dns_rootns_create(mctx, dns_rdataclass_in, NULL,
+ &server->in_roothints),
+ "setting up root hints");
+
+ CHECKFATAL(isc_mutex_init(&server->reload_event_lock),
+ "initializing reload event lock");
+ server->reload_event =
+ isc_event_allocate(ns_g_mctx, server,
+ NS_EVENT_RELOAD,
+ ns_server_reload,
+ server,
+ sizeof(isc_event_t));
+ CHECKFATAL(server->reload_event == NULL ?
+ ISC_R_NOMEMORY : ISC_R_SUCCESS,
+ "allocating reload event");
+
+ CHECKFATAL(dst_lib_init(ns_g_mctx, ns_g_entropy, ISC_ENTROPY_GOODONLY),
+ "initializing DST");
+
+ server->tkeyctx = NULL;
+ CHECKFATAL(dns_tkeyctx_create(ns_g_mctx, ns_g_entropy,
+ &server->tkeyctx),
+ "creating TKEY context");
+
+ /*
+ * Setup the server task, which is responsible for coordinating
+ * startup and shutdown of the server.
+ */
+ CHECKFATAL(isc_task_create(ns_g_taskmgr, 0, &server->task),
+ "creating server task");
+ isc_task_setname(server->task, "server", server);
+ CHECKFATAL(isc_task_onshutdown(server->task, shutdown_server, server),
+ "isc_task_onshutdown");
+ CHECKFATAL(isc_app_onrun(ns_g_mctx, server->task, run_server, server),
+ "isc_app_onrun");
+
+ server->interface_timer = NULL;
+ server->heartbeat_timer = NULL;
+ server->pps_timer = NULL;
+
+ server->interface_interval = 0;
+ server->heartbeat_interval = 0;
+
+ CHECKFATAL(dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr,
+ ns_g_socketmgr, &server->zonemgr),
+ "dns_zonemgr_create");
+
+ server->statsfile = isc_mem_strdup(server->mctx, "named.stats");
+ CHECKFATAL(server->statsfile == NULL ? ISC_R_NOMEMORY : ISC_R_SUCCESS,
+ "isc_mem_strdup");
+ server->nsstats = NULL;
+ server->rcvquerystats = NULL;
+ server->opcodestats = NULL;
+ server->zonestats = NULL;
+ server->resolverstats = NULL;
+
+ server->dumpfile = isc_mem_strdup(server->mctx, "named_dump.db");
+ CHECKFATAL(server->dumpfile == 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");
+
+ server->hostname_set = ISC_FALSE;
+ server->hostname = NULL;
+ server->version_set = ISC_FALSE;
+ server->version = NULL;
+ server->server_usehostname = ISC_FALSE;
+ server->server_id = NULL;
+
+ CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->nsstats,
+ dns_nsstatscounter_max),
+ "dns_stats_create (server)");
+
+ CHECKFATAL(dns_rdatatypestats_create(ns_g_mctx,
+ &server->rcvquerystats),
+ "dns_stats_create (rcvquery)");
+
+ CHECKFATAL(dns_opcodestats_create(ns_g_mctx, &server->opcodestats),
+ "dns_stats_create (opcode)");
+
+ CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->zonestats,
+ dns_zonestatscounter_max),
+ "dns_stats_create (zone)");
+
+ CHECKFATAL(dns_generalstats_create(ns_g_mctx, &server->resolverstats,
+ dns_resstatscounter_max),
+ "dns_stats_create (resolver)");
+
+ server->flushonshutdown = ISC_FALSE;
+ server->log_queries = ISC_FALSE;
+
+ server->controls = NULL;
+ CHECKFATAL(ns_controls_create(server, &server->controls),
+ "ns_controls_create");
+ server->dispatchgen = 0;
+ ISC_LIST_INIT(server->dispatches);
+
+ ISC_LIST_INIT(server->statschannels);
+
+ server->magic = NS_SERVER_MAGIC;
+ *serverp = server;
+}
+
+void
+ns_server_destroy(ns_server_t **serverp) {
+ ns_server_t *server = *serverp;
+ REQUIRE(NS_SERVER_VALID(server));
+
+ ns_controls_destroy(&server->controls);
+
+ dns_stats_detach(&server->nsstats);
+ dns_stats_detach(&server->rcvquerystats);
+ dns_stats_detach(&server->opcodestats);
+ dns_stats_detach(&server->zonestats);
+ dns_stats_detach(&server->resolverstats);
+
+ isc_mem_free(server->mctx, server->statsfile);
+ isc_mem_free(server->mctx, server->dumpfile);
+ isc_mem_free(server->mctx, server->recfile);
+
+ if (server->version != NULL)
+ isc_mem_free(server->mctx, server->version);
+ if (server->hostname != NULL)
+ isc_mem_free(server->mctx, server->hostname);
+ if (server->server_id != NULL)
+ isc_mem_free(server->mctx, server->server_id);
+
+ dns_zonemgr_detach(&server->zonemgr);
+
+ if (server->tkeyctx != NULL)
+ dns_tkeyctx_destroy(&server->tkeyctx);
+
+ dst_lib_destroy();
+
+ isc_event_free(&server->reload_event);
+
+ INSIST(ISC_LIST_EMPTY(server->viewlist));
+
+ dns_aclenv_destroy(&server->aclenv);
+
+ isc_quota_destroy(&server->recursionquota);
+ isc_quota_destroy(&server->tcpquota);
+ isc_quota_destroy(&server->xfroutquota);
+
+ server->magic = 0;
+ isc_mem_put(server->mctx, server, sizeof(*server));
+ *serverp = NULL;
+}
+
+static void
+fatal(const char *msg, isc_result_t result) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_CRITICAL, "%s: %s", msg,
+ isc_result_totext(result));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_CRITICAL, "exiting (due to fatal error)");
+ exit(1);
+}
+
+static void
+start_reserved_dispatches(ns_server_t *server) {
+
+ REQUIRE(NS_SERVER_VALID(server));
+
+ server->dispatchgen++;
+}
+
+static void
+end_reserved_dispatches(ns_server_t *server, isc_boolean_t all) {
+ ns_dispatch_t *dispatch, *nextdispatch;
+
+ REQUIRE(NS_SERVER_VALID(server));
+
+ for (dispatch = ISC_LIST_HEAD(server->dispatches);
+ dispatch != NULL;
+ dispatch = nextdispatch) {
+ nextdispatch = ISC_LIST_NEXT(dispatch, link);
+ if (!all && server->dispatchgen == dispatch-> dispatchgen)
+ continue;
+ ISC_LIST_UNLINK(server->dispatches, dispatch, link);
+ dns_dispatch_detach(&dispatch->dispatch);
+ isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
+ }
+}
+
+void
+ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr) {
+ ns_dispatch_t *dispatch;
+ in_port_t port;
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ isc_result_t result;
+ unsigned int attrs, attrmask;
+
+ REQUIRE(NS_SERVER_VALID(server));
+
+ port = isc_sockaddr_getport(addr);
+ if (port == 0 || port >= 1024)
+ return;
+
+ for (dispatch = ISC_LIST_HEAD(server->dispatches);
+ dispatch != NULL;
+ dispatch = ISC_LIST_NEXT(dispatch, link)) {
+ if (isc_sockaddr_equal(&dispatch->addr, addr))
+ break;
+ }
+ if (dispatch != NULL) {
+ dispatch->dispatchgen = server->dispatchgen;
+ return;
+ }
+
+ dispatch = isc_mem_get(server->mctx, sizeof(*dispatch));
+ if (dispatch == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ dispatch->addr = *addr;
+ dispatch->dispatchgen = server->dispatchgen;
+ dispatch->dispatch = NULL;
+
+ attrs = 0;
+ attrs |= DNS_DISPATCHATTR_UDP;
+ switch (isc_sockaddr_pf(addr)) {
+ case AF_INET:
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ break;
+ case AF_INET6:
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ break;
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ attrmask = 0;
+ attrmask |= DNS_DISPATCHATTR_UDP;
+ attrmask |= DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4;
+ attrmask |= DNS_DISPATCHATTR_IPV6;
+
+ result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
+ ns_g_taskmgr, &dispatch->addr, 4096,
+ 1000, 32768, 16411, 16433,
+ attrs, attrmask, &dispatch->dispatch);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ ISC_LIST_INITANDPREPEND(server->dispatches, dispatch, link);
+
+ return;
+
+ cleanup:
+ if (dispatch != NULL)
+ isc_mem_put(server->mctx, dispatch, sizeof(*dispatch));
+ isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "unable to create dispatch for reserved port %s: %s",
+ addrbuf, isc_result_totext(result));
+}
+
+
+static isc_result_t
+loadconfig(ns_server_t *server) {
+ isc_result_t result;
+ start_reserved_dispatches(server);
+ result = load_configuration(ns_g_lwresdonly ?
+ lwresd_g_conffile : ns_g_conffile,
+ server, ISC_FALSE);
+ if (result == ISC_R_SUCCESS) {
+ end_reserved_dispatches(server, ISC_FALSE);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reloading configuration succeeded");
+ } else {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "reloading configuration failed: %s",
+ isc_result_totext(result));
+ }
+ return (result);
+}
+
+static isc_result_t
+reload(ns_server_t *server) {
+ isc_result_t result;
+ CHECK(loadconfig(server));
+
+ result = load_zones(server, ISC_FALSE);
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "reloading zones succeeded");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "reloading zones failed: %s",
+ isc_result_totext(result));
+
+ cleanup:
+ return (result);
+}
+
+static void
+reconfig(ns_server_t *server) {
+ isc_result_t result;
+ CHECK(loadconfig(server));
+
+ result = load_new_zones(server, ISC_FALSE);
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "any newly configured zones are now loaded");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "loading new zones failed: %s",
+ isc_result_totext(result));
+
+ cleanup: ;
+}
+
+/*
+ * Handle a reload event (from SIGHUP).
+ */
+static void
+ns_server_reload(isc_task_t *task, isc_event_t *event) {
+ ns_server_t *server = (ns_server_t *)event->ev_arg;
+
+ INSIST(task = server->task);
+ UNUSED(task);
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "received SIGHUP signal to reload zones");
+ (void)reload(server);
+
+ LOCK(&server->reload_event_lock);
+ INSIST(server->reload_event == NULL);
+ server->reload_event = event;
+ UNLOCK(&server->reload_event_lock);
+}
+
+void
+ns_server_reloadwanted(ns_server_t *server) {
+ LOCK(&server->reload_event_lock);
+ if (server->reload_event != NULL)
+ isc_task_send(server->task, &server->reload_event);
+ UNLOCK(&server->reload_event_lock);
+}
+
+static char *
+next_token(char **stringp, const char *delim) {
+ char *res;
+
+ do {
+ res = strsep(stringp, delim);
+ if (res == NULL)
+ break;
+ } while (*res == '\0');
+ return (res);
+}
+
+/*
+ * Find the zone specified in the control channel command 'args',
+ * if any. If a zone is specified, point '*zonep' at it, otherwise
+ * set '*zonep' to NULL.
+ */
+static isc_result_t
+zone_from_args(ns_server_t *server, char *args, dns_zone_t **zonep) {
+ char *input, *ptr;
+ const char *zonetxt;
+ char *classtxt;
+ const char *viewtxt = NULL;
+ dns_fixedname_t name;
+ isc_result_t result;
+ isc_buffer_t buf;
+ dns_view_t *view = NULL;
+ dns_rdataclass_t rdclass;
+
+ REQUIRE(zonep != NULL && *zonep == NULL);
+
+ input = args;
+
+ /* Skip the command name. */
+ ptr = next_token(&input, " \t");
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ /* Look for the zone name. */
+ zonetxt = next_token(&input, " \t");
+ if (zonetxt == NULL)
+ return (ISC_R_SUCCESS);
+
+ /* Look for the optional class name. */
+ classtxt = next_token(&input, " \t");
+ if (classtxt != NULL) {
+ /* Look for the optional view name. */
+ viewtxt = next_token(&input, " \t");
+ }
+
+ isc_buffer_init(&buf, zonetxt, strlen(zonetxt));
+ isc_buffer_add(&buf, strlen(zonetxt));
+ dns_fixedname_init(&name);
+ result = dns_name_fromtext(dns_fixedname_name(&name),
+ &buf, dns_rootname, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto fail1;
+
+ if (classtxt != NULL) {
+ isc_textregion_t r;
+ r.base = classtxt;
+ r.length = strlen(classtxt);
+ result = dns_rdataclass_fromtext(&rdclass, &r);
+ if (result != ISC_R_SUCCESS)
+ goto fail1;
+ } else
+ rdclass = dns_rdataclass_in;
+
+ if (viewtxt == NULL) {
+ result = dns_viewlist_findzone(&server->viewlist,
+ dns_fixedname_name(&name),
+ ISC_TF(classtxt == NULL),
+ rdclass, zonep);
+ } else {
+ result = dns_viewlist_find(&server->viewlist, viewtxt,
+ rdclass, &view);
+ if (result != ISC_R_SUCCESS)
+ goto fail1;
+
+ result = dns_zt_find(view->zonetable, dns_fixedname_name(&name),
+ 0, NULL, zonep);
+ dns_view_detach(&view);
+ }
+
+ /* Partial match? */
+ if (result != ISC_R_SUCCESS && *zonep != NULL)
+ dns_zone_detach(zonep);
+ fail1:
+ return (result);
+}
+
+/*
+ * Act on a "retransfer" command from the command channel.
+ */
+isc_result_t
+ns_server_retransfercommand(ns_server_t *server, char *args) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ dns_zonetype_t type;
+
+ result = zone_from_args(server, args, &zone);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (zone == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+ type = dns_zone_gettype(zone);
+ if (type == dns_zone_slave || type == dns_zone_stub)
+ dns_zone_forcereload(zone);
+ else
+ result = ISC_R_NOTFOUND;
+ dns_zone_detach(&zone);
+ return (result);
+}
+
+/*
+ * Act on a "reload" command from the command channel.
+ */
+isc_result_t
+ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ dns_zonetype_t type;
+ const char *msg = NULL;
+
+ result = zone_from_args(server, args, &zone);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (zone == NULL) {
+ result = reload(server);
+ if (result == ISC_R_SUCCESS)
+ msg = "server reload successful";
+ } else {
+ type = dns_zone_gettype(zone);
+ if (type == dns_zone_slave || type == dns_zone_stub) {
+ dns_zone_refresh(zone);
+ dns_zone_detach(&zone);
+ msg = "zone refresh queued";
+ } else {
+ result = dns_zone_load(zone);
+ dns_zone_detach(&zone);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ msg = "zone reload successful";
+ break;
+ case DNS_R_CONTINUE:
+ msg = "zone reload queued";
+ result = ISC_R_SUCCESS;
+ break;
+ case DNS_R_UPTODATE:
+ msg = "zone reload up-to-date";
+ result = ISC_R_SUCCESS;
+ break;
+ default:
+ /* failure message will be generated by rndc */
+ break;
+ }
+ }
+ }
+ if (msg != NULL && strlen(msg) < isc_buffer_availablelength(text))
+ isc_buffer_putmem(text, (const unsigned char *)msg,
+ strlen(msg) + 1);
+ return (result);
+}
+
+/*
+ * Act on a "reconfig" command from the command channel.
+ */
+isc_result_t
+ns_server_reconfigcommand(ns_server_t *server, char *args) {
+ UNUSED(args);
+
+ reconfig(server);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Act on a "notify" command from the command channel.
+ */
+isc_result_t
+ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t *text) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ const unsigned char msg[] = "zone notify queued";
+
+ result = zone_from_args(server, args, &zone);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (zone == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ dns_zone_notify(zone);
+ dns_zone_detach(&zone);
+ if (sizeof(msg) <= isc_buffer_availablelength(text))
+ isc_buffer_putmem(text, msg, sizeof(msg));
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Act on a "refresh" command from the command channel.
+ */
+isc_result_t
+ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t *text) {
+ isc_result_t result;
+ dns_zone_t *zone = NULL;
+ const unsigned char msg1[] = "zone refresh queued";
+ const unsigned char msg2[] = "not a slave or stub zone";
+ dns_zonetype_t type;
+
+ result = zone_from_args(server, args, &zone);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (zone == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ type = dns_zone_gettype(zone);
+ if (type == dns_zone_slave || type == dns_zone_stub) {
+ dns_zone_refresh(zone);
+ dns_zone_detach(&zone);
+ if (sizeof(msg1) <= isc_buffer_availablelength(text))
+ isc_buffer_putmem(text, msg1, sizeof(msg1));
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_zone_detach(&zone);
+ if (sizeof(msg2) <= isc_buffer_availablelength(text))
+ isc_buffer_putmem(text, msg2, sizeof(msg2));
+ return (ISC_R_FAILURE);
+}
+
+isc_result_t
+ns_server_togglequerylog(ns_server_t *server) {
+ server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE;
+
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "query logging is now %s",
+ server->log_queries ? "on" : "off");
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+ns_listenlist_fromconfig(const cfg_obj_t *listenlist, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx,
+ isc_mem_t *mctx, ns_listenlist_t **target)
+{
+ isc_result_t result;
+ const cfg_listelt_t *element;
+ ns_listenlist_t *dlist = NULL;
+
+ REQUIRE(target != NULL && *target == NULL);
+
+ result = ns_listenlist_create(mctx, &dlist);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (element = cfg_list_first(listenlist);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ ns_listenelt_t *delt = NULL;
+ const cfg_obj_t *listener = cfg_listelt_value(element);
+ result = ns_listenelt_fromconfig(listener, config, actx,
+ mctx, &delt);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ ISC_LIST_APPEND(dlist->elts, delt, link);
+ }
+ *target = dlist;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ ns_listenlist_detach(&dlist);
+ return (result);
+}
+
+/*
+ * Create a listen list from the corresponding configuration
+ * data structure.
+ */
+static isc_result_t
+ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config,
+ cfg_aclconfctx_t *actx,
+ isc_mem_t *mctx, ns_listenelt_t **target)
+{
+ isc_result_t result;
+ const cfg_obj_t *portobj;
+ in_port_t port;
+ ns_listenelt_t *delt = NULL;
+ REQUIRE(target != NULL && *target == NULL);
+
+ portobj = cfg_tuple_get(listener, "port");
+ if (!cfg_obj_isuint32(portobj)) {
+ if (ns_g_port != 0) {
+ port = ns_g_port;
+ } else {
+ result = ns_config_getport(config, &port);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else {
+ if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
+ cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
+ "port value '%u' is out of range",
+ cfg_obj_asuint32(portobj));
+ return (ISC_R_RANGE);
+ }
+ port = (in_port_t)cfg_obj_asuint32(portobj);
+ }
+
+ result = ns_listenelt_create(mctx, port, NULL, &delt);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = cfg_acl_fromconfig(cfg_tuple_get(listener, "acl"),
+ config, ns_g_lctx, actx, mctx, 0,
+ &delt->acl);
+ if (result != ISC_R_SUCCESS) {
+ ns_listenelt_destroy(delt);
+ return (result);
+ }
+ *target = delt;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_server_dumpstats(ns_server_t *server) {
+ isc_result_t result;
+ FILE *fp = NULL;
+
+ CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
+ "could not open statistics dump file", server->statsfile);
+
+ result = ns_stats_dump(server, fp);
+ CHECK(result);
+
+ cleanup:
+ 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,
+ "dumpstats complete");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumpstats failed: %s",
+ dns_result_totext(result));
+ return (result);
+}
+
+static isc_result_t
+add_zone_tolist(dns_zone_t *zone, void *uap) {
+ struct dumpcontext *dctx = uap;
+ struct zonelistentry *zle;
+
+ zle = isc_mem_get(dctx->mctx, sizeof *zle);
+ if (zle == NULL)
+ return (ISC_R_NOMEMORY);
+ zle->zone = NULL;
+ dns_zone_attach(zone, &zle->zone);
+ ISC_LINK_INIT(zle, link);
+ ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
+ struct viewlistentry *vle;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ /*
+ * Prevent duplicate views.
+ */
+ for (vle = ISC_LIST_HEAD(dctx->viewlist);
+ vle != NULL;
+ vle = ISC_LIST_NEXT(vle, link))
+ if (vle->view == view)
+ return (ISC_R_SUCCESS);
+
+ vle = isc_mem_get(dctx->mctx, sizeof *vle);
+ if (vle == NULL)
+ return (ISC_R_NOMEMORY);
+ vle->view = NULL;
+ dns_view_attach(view, &vle->view);
+ ISC_LINK_INIT(vle, link);
+ ISC_LIST_INIT(vle->zonelist);
+ ISC_LIST_APPEND(dctx->viewlist, vle, link);
+ if (dctx->dumpzones)
+ result = dns_zt_apply(view->zonetable, ISC_TRUE,
+ add_zone_tolist, dctx);
+ return (result);
+}
+
+static void
+dumpcontext_destroy(struct dumpcontext *dctx) {
+ struct viewlistentry *vle;
+ struct zonelistentry *zle;
+
+ vle = ISC_LIST_HEAD(dctx->viewlist);
+ while (vle != NULL) {
+ ISC_LIST_UNLINK(dctx->viewlist, vle, link);
+ zle = ISC_LIST_HEAD(vle->zonelist);
+ while (zle != NULL) {
+ ISC_LIST_UNLINK(vle->zonelist, zle, link);
+ dns_zone_detach(&zle->zone);
+ isc_mem_put(dctx->mctx, zle, sizeof *zle);
+ zle = ISC_LIST_HEAD(vle->zonelist);
+ }
+ dns_view_detach(&vle->view);
+ isc_mem_put(dctx->mctx, vle, sizeof *vle);
+ vle = ISC_LIST_HEAD(dctx->viewlist);
+ }
+ if (dctx->version != NULL)
+ dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
+ if (dctx->db != NULL)
+ dns_db_detach(&dctx->db);
+ if (dctx->cache != NULL)
+ dns_db_detach(&dctx->cache);
+ if (dctx->task != NULL)
+ isc_task_detach(&dctx->task);
+ if (dctx->fp != NULL)
+ (void)isc_stdio_close(dctx->fp);
+ if (dctx->mdctx != NULL)
+ dns_dumpctx_detach(&dctx->mdctx);
+ isc_mem_put(dctx->mctx, dctx, sizeof *dctx);
+}
+
+static void
+dumpdone(void *arg, isc_result_t result) {
+ struct dumpcontext *dctx = arg;
+ char buf[1024+32];
+ const dns_master_style_t *style;
+
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ if (dctx->mdctx != NULL)
+ dns_dumpctx_detach(&dctx->mdctx);
+ if (dctx->view == NULL) {
+ dctx->view = ISC_LIST_HEAD(dctx->viewlist);
+ if (dctx->view == NULL)
+ goto done;
+ INSIST(dctx->zone == NULL);
+ } else
+ goto resume;
+ nextview:
+ fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
+ resume:
+ 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);
+ result = dns_master_dumptostreaminc(dctx->mctx,
+ dctx->cache, NULL,
+ style, dctx->fp,
+ dctx->task,
+ dumpdone, dctx,
+ &dctx->mdctx);
+ if (result == DNS_R_CONTINUE)
+ return;
+ if (result == ISC_R_NOTIMPLEMENTED)
+ fprintf(dctx->fp, "; %s\n",
+ dns_result_totext(result));
+ else if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ }
+ if (dctx->cache != NULL) {
+ dns_adb_dump(dctx->view->view->adb, dctx->fp);
+ dns_db_detach(&dctx->cache);
+ }
+ if (dctx->dumpzones) {
+ style = &dns_master_style_full;
+ nextzone:
+ if (dctx->version != NULL)
+ dns_db_closeversion(dctx->db, &dctx->version,
+ ISC_FALSE);
+ if (dctx->db != NULL)
+ dns_db_detach(&dctx->db);
+ if (dctx->zone == NULL)
+ dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist);
+ else
+ dctx->zone = ISC_LIST_NEXT(dctx->zone, link);
+ if (dctx->zone != NULL) {
+ /* start zone dump */
+ dns_zone_name(dctx->zone->zone, buf, sizeof(buf));
+ fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf);
+ result = dns_zone_getdb(dctx->zone->zone, &dctx->db);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(dctx->fp, "; %s\n",
+ dns_result_totext(result));
+ goto nextzone;
+ }
+ dns_db_currentversion(dctx->db, &dctx->version);
+ result = dns_master_dumptostreaminc(dctx->mctx,
+ dctx->db,
+ dctx->version,
+ style, dctx->fp,
+ dctx->task,
+ dumpdone, dctx,
+ &dctx->mdctx);
+ if (result == DNS_R_CONTINUE)
+ return;
+ if (result == ISC_R_NOTIMPLEMENTED) {
+ fprintf(dctx->fp, "; %s\n",
+ dns_result_totext(result));
+ result = ISC_R_SUCCESS;
+ goto nextzone;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ }
+ if (dctx->view != NULL)
+ dctx->view = ISC_LIST_NEXT(dctx->view, link);
+ if (dctx->view != NULL)
+ goto nextview;
+ done:
+ fprintf(dctx->fp, "; Dump complete\n");
+ result = isc_stdio_flush(dctx->fp);
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpdb complete");
+ cleanup:
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumpdb failed: %s", dns_result_totext(result));
+ dumpcontext_destroy(dctx);
+}
+
+isc_result_t
+ns_server_dumpdb(ns_server_t *server, char *args) {
+ struct dumpcontext *dctx = NULL;
+ dns_view_t *view;
+ isc_result_t result;
+ char *ptr;
+ const char *sep;
+
+ /* Skip the command name. */
+ ptr = next_token(&args, " \t");
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ dctx = isc_mem_get(server->mctx, sizeof(*dctx));
+ if (dctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dctx->mctx = server->mctx;
+ dctx->dumpcache = ISC_TRUE;
+ dctx->dumpzones = ISC_FALSE;
+ dctx->fp = NULL;
+ ISC_LIST_INIT(dctx->viewlist);
+ dctx->view = NULL;
+ dctx->zone = NULL;
+ dctx->cache = NULL;
+ dctx->mdctx = NULL;
+ dctx->db = NULL;
+ dctx->cache = NULL;
+ dctx->task = NULL;
+ dctx->version = NULL;
+ isc_task_attach(server->task, &dctx->task);
+
+ CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp),
+ "could not open dump file", server->dumpfile);
+
+ sep = (args == NULL) ? "" : ": ";
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumpdb started%s%s", sep, (args != NULL) ? args : "");
+
+ ptr = next_token(&args, " \t");
+ if (ptr != NULL && strcmp(ptr, "-all") == 0) {
+ dctx->dumpzones = ISC_TRUE;
+ dctx->dumpcache = ISC_TRUE;
+ ptr = next_token(&args, " \t");
+ } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
+ dctx->dumpzones = ISC_FALSE;
+ dctx->dumpcache = ISC_TRUE;
+ ptr = next_token(&args, " \t");
+ } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
+ dctx->dumpzones = ISC_TRUE;
+ dctx->dumpcache = ISC_FALSE;
+ ptr = next_token(&args, " \t");
+ }
+
+ 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;
+ CHECK(add_view_tolist(dctx, view));
+ }
+ if (ptr != NULL) {
+ ptr = next_token(&args, " \t");
+ if (ptr != NULL)
+ goto nextview;
+ }
+ dumpdone(dctx, ISC_R_SUCCESS);
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (dctx != NULL)
+ dumpcontext_destroy(dctx);
+ return (result);
+}
+
+isc_result_t
+ns_server_dumprecursing(ns_server_t *server) {
+ FILE *fp = NULL;
+ isc_result_t result;
+
+ CHECKMF(isc_stdio_open(server->recfile, "w", &fp),
+ "could not open dump file", server->recfile);
+ fprintf(fp,";\n; Recursing Queries\n;\n");
+ ns_interfacemgr_dumprecursing(fp, server->interfacemgr);
+ fprintf(fp, "; Dump complete\n");
+
+ cleanup:
+ if (fp != NULL)
+ result = isc_stdio_close(fp);
+ if (result == ISC_R_SUCCESS)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "dumprecursing complete");
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "dumprecursing failed: %s",
+ dns_result_totext(result));
+ return (result);
+}
+
+isc_result_t
+ns_server_setdebuglevel(ns_server_t *server, char *args) {
+ char *ptr;
+ char *levelstr;
+ char *endp;
+ long newlevel;
+
+ UNUSED(server);
+
+ /* Skip the command name. */
+ ptr = next_token(&args, " \t");
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ /* Look for the new level name. */
+ levelstr = next_token(&args, " \t");
+ if (levelstr == NULL) {
+ if (ns_g_debuglevel < 99)
+ ns_g_debuglevel++;
+ } else {
+ newlevel = strtol(levelstr, &endp, 10);
+ if (*endp != '\0' || newlevel < 0 || newlevel > 99)
+ return (ISC_R_RANGE);
+ ns_g_debuglevel = (unsigned int)newlevel;
+ }
+ isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "debug level is now %d", ns_g_debuglevel);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_server_validation(ns_server_t *server, char *args) {
+ char *ptr, *viewname;
+ dns_view_t *view;
+ isc_boolean_t changed = ISC_FALSE;
+ isc_result_t result;
+ isc_boolean_t enable;
+
+ /* Skip the command name. */
+ ptr = next_token(&args, " \t");
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ /* Find out what we are to do. */
+ ptr = next_token(&args, " \t");
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") ||
+ !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true"))
+ enable = ISC_TRUE;
+ else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") ||
+ !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false"))
+ enable = ISC_FALSE;
+ else
+ return (DNS_R_SYNTAX);
+
+ /* Look for the view name. */
+ viewname = next_token(&args, " \t");
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link))
+ {
+ if (viewname != NULL && strcasecmp(viewname, view->name) != 0)
+ continue;
+ result = dns_view_flushcache(view);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ view->enablevalidation = enable;
+ changed = ISC_TRUE;
+ }
+ if (changed)
+ result = ISC_R_SUCCESS;
+ else
+ result = ISC_R_FAILURE;
+ out:
+ isc_task_endexclusive(server->task);
+ return (result);
+}
+
+isc_result_t
+ns_server_flushcache(ns_server_t *server, char *args) {
+ char *ptr, *viewname;
+ dns_view_t *view;
+ isc_boolean_t flushed;
+ isc_boolean_t found;
+ isc_result_t result;
+
+ /* Skip the command name. */
+ ptr = next_token(&args, " \t");
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ /* Look for the view name. */
+ viewname = next_token(&args, " \t");
+
+ result = isc_task_beginexclusive(server->task);
+ 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;
+ found = ISC_TRUE;
+ result = dns_view_flushcache(view);
+ 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));
+ }
+ }
+ if (flushed && found) {
+ if (viewname != NULL)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing cache in view '%s' succeeded",
+ viewname);
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing caches in all views succeeded");
+ result = ISC_R_SUCCESS;
+ } else {
+ if (!found) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing cache in view '%s' failed: "
+ "view not found", viewname);
+ result = ISC_R_NOTFOUND;
+ } else
+ result = ISC_R_FAILURE;
+ }
+ isc_task_endexclusive(server->task);
+ return (result);
+}
+
+isc_result_t
+ns_server_flushname(ns_server_t *server, char *args) {
+ char *ptr, *target, *viewname;
+ dns_view_t *view;
+ isc_boolean_t flushed;
+ isc_boolean_t found;
+ isc_result_t result;
+ isc_buffer_t b;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ /* Skip the command name. */
+ ptr = next_token(&args, " \t");
+ if (ptr == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ /* Find the domain name to flush. */
+ target = next_token(&args, " \t");
+ if (target == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+
+ isc_buffer_init(&b, target, strlen(target));
+ 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);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /* Look for the view name. */
+ viewname = next_token(&args, " \t");
+
+ result = isc_task_beginexclusive(server->task);
+ 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;
+ found = ISC_TRUE;
+ result = dns_view_flushname(view, name);
+ if (result != ISC_R_SUCCESS) {
+ flushed = ISC_FALSE;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing name '%s' in cache view '%s' "
+ "failed: %s", target, view->name,
+ isc_result_totext(result));
+ }
+ }
+ if (flushed && found) {
+ if (viewname != NULL)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing name '%s' in cache view '%s' "
+ "succeeded", target, viewname);
+ else
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "flushing name '%s' in all cache views "
+ "succeeded", target);
+ result = ISC_R_SUCCESS;
+ } else {
+ if (!found)
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "flushing name '%s' in cache view '%s' "
+ "failed: view not found", target,
+ viewname);
+ result = ISC_R_FAILURE;
+ }
+ isc_task_endexclusive(server->task);
+ return (result);
+}
+
+isc_result_t
+ns_server_status(ns_server_t *server, isc_buffer_t *text) {
+ int zonecount, xferrunning, xferdeferred, soaqueries;
+ unsigned int n;
+ const char *ob = "", *cb = "", *alt = "";
+
+ if (ns_g_server->version_set) {
+ ob = " (";
+ cb = ")";
+ if (ns_g_server->version == NULL)
+ alt = "version.bind/txt/ch disabled";
+ else
+ alt = ns_g_server->version;
+ }
+ zonecount = dns_zonemgr_getcount(server->zonemgr, DNS_ZONESTATE_ANY);
+ xferrunning = dns_zonemgr_getcount(server->zonemgr,
+ DNS_ZONESTATE_XFERRUNNING);
+ xferdeferred = dns_zonemgr_getcount(server->zonemgr,
+ DNS_ZONESTATE_XFERDEFERRED);
+ soaqueries = dns_zonemgr_getcount(server->zonemgr,
+ DNS_ZONESTATE_SOAQUERY);
+
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "version: %s%s%s%s\n"
+#ifdef ISC_PLATFORM_USETHREADS
+ "CPUs found: %u\n"
+ "worker threads: %u\n"
+#endif
+ "number of zones: %u\n"
+ "debug level: %d\n"
+ "xfers running: %u\n"
+ "xfers deferred: %u\n"
+ "soa queries in progress: %u\n"
+ "query logging is %s\n"
+ "recursive clients: %d/%d/%d\n"
+ "tcp clients: %d/%d\n"
+ "server is up and running",
+ ns_g_version, ob, alt, cb,
+#ifdef ISC_PLATFORM_USETHREADS
+ ns_g_cpus_detected, ns_g_cpus,
+#endif
+ zonecount, ns_g_debuglevel, xferrunning, xferdeferred,
+ soaqueries, server->log_queries ? "ON" : "OFF",
+ server->recursionquota.used, server->recursionquota.soft,
+ server->recursionquota.max,
+ server->tcpquota.used, server->tcpquota.max);
+ if (n >= isc_buffer_availablelength(text))
+ return (ISC_R_NOSPACE);
+ isc_buffer_add(text, n);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+delete_keynames(dns_tsig_keyring_t *ring, char *target,
+ unsigned int *foundkeys)
+{
+ char namestr[DNS_NAME_FORMATSIZE];
+ isc_result_t result;
+ dns_rbtnodechain_t chain;
+ dns_name_t foundname;
+ dns_fixedname_t fixedorigin;
+ dns_name_t *origin;
+ dns_rbtnode_t *node;
+ dns_tsigkey_t *tkey;
+
+ dns_name_init(&foundname, NULL);
+ dns_fixedname_init(&fixedorigin);
+ origin = dns_fixedname_name(&fixedorigin);
+
+ again:
+ dns_rbtnodechain_init(&chain, ring->mctx);
+ result = dns_rbtnodechain_first(&chain, ring->keys, &foundname,
+ origin);
+ if (result == ISC_R_NOTFOUND) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+
+ for (;;) {
+ node = NULL;
+ dns_rbtnodechain_current(&chain, &foundname, origin, &node);
+ tkey = node->data;
+
+ if (tkey != NULL) {
+ if (!tkey->generated)
+ goto nextkey;
+
+ dns_name_format(&tkey->name, namestr, sizeof(namestr));
+ if (strcmp(namestr, target) == 0) {
+ (*foundkeys)++;
+ dns_rbtnodechain_invalidate(&chain);
+ (void)dns_rbt_deletename(ring->keys,
+ &tkey->name,
+ ISC_FALSE);
+ goto again;
+ }
+ }
+
+ nextkey:
+ result = dns_rbtnodechain_next(&chain, &foundname, origin);
+ if (result == ISC_R_NOMORE)
+ break;
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t *text) {
+ isc_result_t result;
+ unsigned int n;
+ dns_view_t *view;
+ unsigned int foundkeys = 0;
+ char *target;
+ char *viewname;
+
+ (void)next_token(&command, " \t"); /* skip command name */
+ target = next_token(&command, " \t");
+ if (target == NULL)
+ return (ISC_R_UNEXPECTEDEND);
+ viewname = next_token(&command, " \t");
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ if (viewname == NULL || strcmp(view->name, viewname) == 0) {
+ RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_write);
+ result = delete_keynames(view->dynamickeys, target,
+ &foundkeys);
+ RWUNLOCK(&view->dynamickeys->lock,
+ isc_rwlocktype_write);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_endexclusive(server->task);
+ return (result);
+ }
+ }
+ }
+ isc_task_endexclusive(server->task);
+
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "%d tsig keys deleted.\n", foundkeys);
+ if (n >= isc_buffer_availablelength(text)) {
+ isc_task_endexclusive(server->task);
+ return (ISC_R_NOSPACE);
+ }
+ isc_buffer_add(text, n);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+list_keynames(dns_view_t *view, dns_tsig_keyring_t *ring, isc_buffer_t *text,
+ unsigned int *foundkeys)
+{
+ char namestr[DNS_NAME_FORMATSIZE];
+ char creatorstr[DNS_NAME_FORMATSIZE];
+ isc_result_t result;
+ dns_rbtnodechain_t chain;
+ dns_name_t foundname;
+ dns_fixedname_t fixedorigin;
+ dns_name_t *origin;
+ dns_rbtnode_t *node;
+ dns_tsigkey_t *tkey;
+ unsigned int n;
+ const char *viewname;
+
+ if (view != NULL)
+ viewname = view->name;
+ else
+ viewname = "(global)";
+
+ 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_NOTFOUND) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+
+ for (;;) {
+ node = NULL;
+ dns_rbtnodechain_current(&chain, &foundname, origin, &node);
+ tkey = node->data;
+
+ if (tkey != NULL) {
+ (*foundkeys)++;
+ dns_name_format(&tkey->name, namestr, sizeof(namestr));
+ if (tkey->generated) {
+ dns_name_format(tkey->creator, creatorstr,
+ sizeof(creatorstr));
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "view \"%s\"; type \"dynamic\"; key \"%s\"; creator \"%s\";\n",
+ viewname, namestr, creatorstr);
+ } else {
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "view \"%s\"; type \"static\"; key \"%s\";\n",
+ viewname, namestr);
+ }
+ if (n >= isc_buffer_availablelength(text)) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (ISC_R_NOSPACE);
+ }
+ isc_buffer_add(text, n);
+ }
+ result = dns_rbtnodechain_next(&chain, &foundname, origin);
+ if (result == ISC_R_NOMORE)
+ break;
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return (result);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_server_tsiglist(ns_server_t *server, isc_buffer_t *text) {
+ isc_result_t result;
+ unsigned int n;
+ dns_view_t *view;
+ unsigned int foundkeys = 0;
+
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ RWLOCK(&view->statickeys->lock, isc_rwlocktype_read);
+ result = list_keynames(view, view->statickeys, text,
+ &foundkeys);
+ RWUNLOCK(&view->statickeys->lock, isc_rwlocktype_read);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_endexclusive(server->task);
+ return (result);
+ }
+ RWLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
+ result = list_keynames(view, view->dynamickeys, text,
+ &foundkeys);
+ RWUNLOCK(&view->dynamickeys->lock, isc_rwlocktype_read);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_endexclusive(server->task);
+ return (result);
+ }
+ }
+ isc_task_endexclusive(server->task);
+
+ if (foundkeys == 0) {
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "no tsig keys found.\n");
+ if (n >= isc_buffer_availablelength(text)) {
+ isc_task_endexclusive(server->task);
+ return (ISC_R_NOSPACE);
+ }
+ isc_buffer_add(text, n);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Act on a "freeze" or "thaw" command from the command channel.
+ */
+isc_result_t
+ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args) {
+ isc_result_t result, tresult;
+ dns_zone_t *zone = NULL;
+ dns_zonetype_t type;
+ char classstr[DNS_RDATACLASS_FORMATSIZE];
+ char zonename[DNS_NAME_FORMATSIZE];
+ dns_view_t *view;
+ char *journal;
+ const char *vname, *sep;
+ isc_boolean_t frozen;
+
+ result = zone_from_args(server, args, &zone);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (zone == NULL) {
+ result = isc_task_beginexclusive(server->task);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ tresult = ISC_R_SUCCESS;
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ result = dns_view_freezezones(view, freeze);
+ if (result != ISC_R_SUCCESS &&
+ tresult == ISC_R_SUCCESS)
+ tresult = result;
+ }
+ isc_task_endexclusive(server->task);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "%s all zones: %s",
+ freeze ? "freezing" : "thawing",
+ isc_result_totext(tresult));
+ return (tresult);
+ }
+ type = dns_zone_gettype(zone);
+ if (type != dns_zone_master) {
+ dns_zone_detach(&zone);
+ return (ISC_R_NOTFOUND);
+ }
+
+ frozen = dns_zone_getupdatedisabled(zone);
+ if (freeze) {
+ if (frozen)
+ result = DNS_R_FROZEN;
+ if (result == ISC_R_SUCCESS)
+ result = dns_zone_flush(zone);
+ if (result == ISC_R_SUCCESS) {
+ journal = dns_zone_getjournal(zone);
+ if (journal != NULL)
+ (void)isc_file_remove(journal);
+ }
+ } else {
+ if (frozen) {
+ result = dns_zone_load(zone);
+ if (result == DNS_R_CONTINUE ||
+ result == DNS_R_UPTODATE)
+ result = ISC_R_SUCCESS;
+ }
+ }
+ if (result == ISC_R_SUCCESS)
+ dns_zone_setupdatedisabled(zone, freeze);
+
+ view = dns_zone_getview(zone);
+ if (strcmp(view->name, "_bind") == 0 ||
+ strcmp(view->name, "_default") == 0)
+ {
+ vname = "";
+ sep = "";
+ } else {
+ vname = view->name;
+ sep = " ";
+ }
+ dns_rdataclass_format(dns_zone_getclass(zone), classstr,
+ sizeof(classstr));
+ dns_name_format(dns_zone_getorigin(zone),
+ zonename, sizeof(zonename));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+ "%s zone '%s/%s'%s%s: %s",
+ freeze ? "freezing" : "thawing",
+ zonename, classstr, sep, vname,
+ isc_result_totext(result));
+ dns_zone_detach(&zone);
+ return (result);
+}
+
+#ifdef HAVE_LIBSCF
+/*
+ * This function adds a message for rndc to echo if named
+ * is managed by smf and is also running chroot.
+ */
+isc_result_t
+ns_smf_add_message(isc_buffer_t *text) {
+ unsigned int n;
+
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "use svcadm(1M) to manage named");
+ if (n >= isc_buffer_availablelength(text))
+ return (ISC_R_NOSPACE);
+ isc_buffer_add(text, n);
+ return (ISC_R_SUCCESS);
+}
+#endif /* HAVE_LIBSCF */
diff --git a/bin/named/sortlist.c b/bin/named/sortlist.c
new file mode 100644
index 0000000..daefa07
--- /dev/null
+++ b/bin/named/sortlist.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2004-2007 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: sortlist.c,v 1.17 2007/09/14 01:46:05 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/result.h>
+
+#include <named/globals.h>
+#include <named/server.h>
+#include <named/sortlist.h>
+
+ns_sortlisttype_t
+ns_sortlist_setup(dns_acl_t *acl, isc_netaddr_t *clientaddr,
+ const void **argp)
+{
+ unsigned int i;
+
+ if (acl == NULL)
+ goto dont_sort;
+
+ for (i = 0; i < acl->length; i++) {
+ /*
+ * 'e' refers to the current 'top level statement'
+ * in the sortlist (see ARM).
+ */
+ dns_aclelement_t *e = &acl->elements[i];
+ dns_aclelement_t *try_elt;
+ dns_aclelement_t *order_elt = NULL;
+ const dns_aclelement_t *matched_elt = NULL;
+
+ if (e->type == dns_aclelementtype_nestedacl) {
+ dns_acl_t *inner = e->nestedacl;
+
+ if (inner->length == 0)
+ try_elt = e;
+ else if (inner->length > 2)
+ goto dont_sort;
+ else if (inner->elements[0].negative)
+ goto dont_sort;
+ else {
+ try_elt = &inner->elements[0];
+ if (inner->length == 2)
+ order_elt = &inner->elements[1];
+ }
+ } else {
+ /*
+ * BIND 8 allows bare elements at the top level
+ * as an undocumented feature.
+ */
+ try_elt = e;
+ }
+
+ if (dns_aclelement_match(clientaddr, NULL, try_elt,
+ &ns_g_server->aclenv,
+ &matched_elt)) {
+ if (order_elt != NULL) {
+ if (order_elt->type ==
+ dns_aclelementtype_nestedacl) {
+ *argp = order_elt->nestedacl;
+ return (NS_SORTLISTTYPE_2ELEMENT);
+ } else if (order_elt->type ==
+ dns_aclelementtype_localhost &&
+ ns_g_server->aclenv.localhost != NULL) {
+ *argp = ns_g_server->aclenv.localhost;
+ return (NS_SORTLISTTYPE_2ELEMENT);
+ } else if (order_elt->type ==
+ dns_aclelementtype_localnets &&
+ ns_g_server->aclenv.localnets != NULL) {
+ *argp = ns_g_server->aclenv.localnets;
+ return (NS_SORTLISTTYPE_2ELEMENT);
+ } else {
+ /*
+ * BIND 8 allows a bare IP prefix as
+ * the 2nd element of a 2-element
+ * sortlist statement.
+ */
+ *argp = order_elt;
+ return (NS_SORTLISTTYPE_1ELEMENT);
+ }
+ } else {
+ INSIST(matched_elt != NULL);
+ *argp = matched_elt;
+ return (NS_SORTLISTTYPE_1ELEMENT);
+ }
+ }
+ }
+
+ /* No match; don't sort. */
+ dont_sort:
+ *argp = NULL;
+ return (NS_SORTLISTTYPE_NONE);
+}
+
+int
+ns_sortlist_addrorder2(const isc_netaddr_t *addr, const void *arg) {
+ const dns_acl_t *sortacl = (const dns_acl_t *) arg;
+ int match;
+
+ (void)dns_acl_match(addr, NULL, sortacl,
+ &ns_g_server->aclenv,
+ &match, NULL);
+ if (match > 0)
+ return (match);
+ else if (match < 0)
+ return (INT_MAX - (-match));
+ else
+ return (INT_MAX / 2);
+}
+
+int
+ns_sortlist_addrorder1(const isc_netaddr_t *addr, const void *arg) {
+ const dns_aclelement_t *matchelt = (const dns_aclelement_t *) arg;
+ if (dns_aclelement_match(addr, NULL, matchelt,
+ &ns_g_server->aclenv,
+ NULL)) {
+ return (0);
+ } else {
+ return (INT_MAX);
+ }
+}
+
+void
+ns_sortlist_byaddrsetup(dns_acl_t *sortlist_acl, isc_netaddr_t *client_addr,
+ dns_addressorderfunc_t *orderp,
+ const void **argp)
+{
+ ns_sortlisttype_t sortlisttype;
+
+ sortlisttype = ns_sortlist_setup(sortlist_acl, client_addr, argp);
+
+ switch (sortlisttype) {
+ case NS_SORTLISTTYPE_1ELEMENT:
+ *orderp = ns_sortlist_addrorder1;
+ break;
+ case NS_SORTLISTTYPE_2ELEMENT:
+ *orderp = ns_sortlist_addrorder2;
+ break;
+ case NS_SORTLISTTYPE_NONE:
+ *orderp = NULL;
+ break;
+ default:
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "unexpected return from ns_sortlist_setup(): "
+ "%d", sortlisttype);
+ break;
+ }
+}
+
diff --git a/bin/named/statschannel.c b/bin/named/statschannel.c
new file mode 100644
index 0000000..6dc4fc6
--- /dev/null
+++ b/bin/named/statschannel.c
@@ -0,0 +1,1257 @@
+/*
+ * Copyright (C) 2008 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: statschannel.c,v 1.14 2008/08/08 05:06:49 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/httpd.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+
+#include <dns/db.h>
+#include <dns/opcode.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/stats.h>
+#include <dns/view.h>
+#include <dns/zt.h>
+
+#include <named/log.h>
+#include <named/server.h>
+#include <named/statschannel.h>
+
+#include "bind9.xsl.h"
+
+struct ns_statschannel {
+ /* Unlocked */
+ isc_httpdmgr_t *httpdmgr;
+ isc_sockaddr_t address;
+ isc_mem_t *mctx;
+
+ /*
+ * Locked by channel lock: can be refererenced and modified by both
+ * the server task and the channel task.
+ */
+ isc_mutex_t lock;
+ dns_acl_t *acl;
+
+ /* Locked by server task */
+ ISC_LINK(struct ns_statschannel) link;
+};
+
+typedef enum { statsformat_file, statsformat_xml } statsformat_t;
+
+typedef struct
+stats_dumparg {
+ statsformat_t type;
+ void *arg; /* type dependent argument */
+ const char *category; /* used for general statistics */
+ const char **desc; /* used for general statistics */
+ int ncounters; /* used for general statistics */
+} stats_dumparg_t;
+
+static isc_once_t once = ISC_ONCE_INIT;
+
+/*%
+ * Statistics descriptions. These could be statistically initialized at
+ * compile time, but we configure them run time in the init_desc() function
+ * below so that they'll be less susceptible to counter name changes.
+ */
+static const char *nsstats_desc[dns_nsstatscounter_max];
+static const char *resstats_desc[dns_resstatscounter_max];
+static const char *zonestats_desc[dns_zonestatscounter_max];
+#ifdef HAVE_LIBXML2
+static const char *nsstats_xmldesc[dns_nsstatscounter_max];
+static const char *resstats_xmldesc[dns_resstatscounter_max];
+static const char *zonestats_xmldesc[dns_zonestatscounter_max];
+#else
+#define nsstats_xmldesc NULL
+#define resstats_xmldesc NULL
+#define zonestats_xmldesc NULL
+#endif /* HAVE_LIBXML2 */
+
+static inline void
+set_desc(int counter, int maxcounter, const char *fdesc, const char **fdescs,
+ const char *xdesc, const char **xdescs)
+{
+ REQUIRE(counter < maxcounter);
+ REQUIRE(fdescs[counter] == NULL);
+#ifdef HAVE_LIBXML2
+ REQUIRE(xdescs[counter] == NULL);
+#endif
+
+ fdescs[counter] = fdesc;
+#ifdef HAVE_LIBXML2
+ xdescs[counter] = xdesc;
+#else
+ UNUSED(xdesc);
+ UNUSED(xdescs);
+#endif
+}
+
+static void
+init_desc(void) {
+ int i;
+
+ /* Initialize name server statistics */
+ memset(nsstats_desc, 0,
+ dns_nsstatscounter_max * sizeof(nsstats_desc[0]));
+#ifdef HAVE_LIBXML2
+ memset(nsstats_xmldesc, 0,
+ dns_nsstatscounter_max * sizeof(nsstats_xmldesc[0]));
+#endif
+ set_desc(dns_nsstatscounter_requestv4, dns_nsstatscounter_max,
+ "IPv4 requests received", nsstats_desc,
+ "Requestv4", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_requestv6, dns_nsstatscounter_max,
+ "IPv6 requests received", nsstats_desc,
+ "Requestv6", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_edns0in, dns_nsstatscounter_max,
+ "requests with EDNS(0) received", nsstats_desc,
+ "ReqEdns0", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_badednsver, dns_nsstatscounter_max,
+ "requests with unsupported EDNS version received",
+ nsstats_desc,
+ "ReqBadEDNSVer", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_tsigin, dns_nsstatscounter_max,
+ "requests with TSIG received", nsstats_desc,
+ "ReqTSIG", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_sig0in, dns_nsstatscounter_max,
+ "requests with SIG(0) received", nsstats_desc,
+ "ReqSIG0", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_invalidsig, dns_nsstatscounter_max,
+ "requests with invalid signature", nsstats_desc,
+ "ReqBadSIG", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_tcp, dns_nsstatscounter_max,
+ "TCP requests received", nsstats_desc,
+ "ReqTCP", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_authrej, dns_nsstatscounter_max,
+ "auth queries rejected", nsstats_desc,
+ "AuthQryRej", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_recurserej, dns_nsstatscounter_max,
+ "recursive queries rejected", nsstats_desc,
+ "RecQryRej", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_xfrrej, dns_nsstatscounter_max,
+ "transfer requests rejected", nsstats_desc,
+ "XfrRej", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_updaterej, dns_nsstatscounter_max,
+ "update requests rejected", nsstats_desc,
+ "UpdateRej", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_response, dns_nsstatscounter_max,
+ "responses sent", nsstats_desc,
+ "Response", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_truncatedresp, dns_nsstatscounter_max,
+ "truncated responses sent", nsstats_desc,
+ "TruncatedResp", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_edns0out, dns_nsstatscounter_max,
+ "responses with EDNS(0) sent", nsstats_desc,
+ "RespEDNS0", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_tsigout, dns_nsstatscounter_max,
+ "responses with TSIG sent", nsstats_desc,
+ "RespTSIG", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_sig0out, dns_nsstatscounter_max,
+ "responses with SIG(0) sent", nsstats_desc,
+ "RespSIG0", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_success, dns_nsstatscounter_max,
+ "queries resulted in successful answer", nsstats_desc,
+ "QrySuccess", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_authans, dns_nsstatscounter_max,
+ "queries resulted in authoritative answer", nsstats_desc,
+ "QryAuthAns", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_nonauthans, dns_nsstatscounter_max,
+ "queries resulted in non authoritative answer", nsstats_desc,
+ "QryNoauthAns", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_referral, dns_nsstatscounter_max,
+ "queries resulted in referral answer", nsstats_desc,
+ "QryReferral", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_nxrrset, dns_nsstatscounter_max,
+ "queries resulted in nxrrset", nsstats_desc,
+ "QryNxrrset", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_servfail, dns_nsstatscounter_max,
+ "queries resulted in SERVFAIL", nsstats_desc,
+ "QrySERVFAIL", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_formerr, dns_nsstatscounter_max,
+ "queries resulted in FORMERR", nsstats_desc,
+ "QryFORMERR", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_nxdomain, dns_nsstatscounter_max,
+ "queries resulted in NXDOMAIN", nsstats_desc,
+ "QryNXDOMAIN", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_recursion, dns_nsstatscounter_max,
+ "queries caused recursion", nsstats_desc,
+ "QryRecursion", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_duplicate, dns_nsstatscounter_max,
+ "duplicate queries received", nsstats_desc,
+ "QryDuplicate", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_dropped, dns_nsstatscounter_max,
+ "queries dropped", nsstats_desc,
+ "QryDropped", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_failure, dns_nsstatscounter_max,
+ "other query failures", nsstats_desc,
+ "QryFailure", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_xfrdone, dns_nsstatscounter_max,
+ "requested transfers completed", nsstats_desc,
+ "XfrReqDone", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_updatereqfwd, dns_nsstatscounter_max,
+ "update requests forwarded", nsstats_desc,
+ "UpdateReqFwd", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_updaterespfwd, dns_nsstatscounter_max,
+ "update responses forwarded", nsstats_desc,
+ "UpdateRespFwd", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_updatefwdfail, dns_nsstatscounter_max,
+ "update forward failed", nsstats_desc,
+ "UpdateFwdFail", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_updatedone, dns_nsstatscounter_max,
+ "updates completed", nsstats_desc,
+ "UpdateDone", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_updatefail, dns_nsstatscounter_max,
+ "updates failed", nsstats_desc,
+ "UpdateFail", nsstats_xmldesc);
+ set_desc(dns_nsstatscounter_updatebadprereq, dns_nsstatscounter_max,
+ "updates rejected due to prerequisite failure", nsstats_desc,
+ "UpdateBadPrereq", nsstats_xmldesc);
+
+ /* Initialize resolver statistics */
+ memset(resstats_desc, 0,
+ dns_resstatscounter_max * sizeof(resstats_desc[0]));
+#ifdef HAVE_LIBXML2
+ memset(resstats_xmldesc, 0,
+ dns_resstatscounter_max * sizeof(resstats_xmldesc[0]));
+#endif
+ set_desc(dns_resstatscounter_queryv4, dns_resstatscounter_max,
+ "IPv4 queries sent", resstats_desc,
+ "Queryv4", resstats_xmldesc);
+ set_desc(dns_resstatscounter_queryv6, dns_resstatscounter_max,
+ "IPv6 queries sent", resstats_desc,
+ "Queryv6", resstats_xmldesc);
+ set_desc(dns_resstatscounter_responsev4, dns_resstatscounter_max,
+ "IPv4 responses received", resstats_desc,
+ "Responsev4", resstats_xmldesc);
+ set_desc(dns_resstatscounter_responsev6, dns_resstatscounter_max,
+ "IPv6 responses received", resstats_desc,
+ "Responsev6", resstats_xmldesc);
+ set_desc(dns_resstatscounter_nxdomain, dns_resstatscounter_max,
+ "NXDOMAIN received", resstats_desc,
+ "NXDOMAIN", resstats_xmldesc);
+ set_desc(dns_resstatscounter_servfail, dns_resstatscounter_max,
+ "SERVFAIL received", resstats_desc,
+ "SERVFAIL", resstats_xmldesc);
+ set_desc(dns_resstatscounter_formerr, dns_resstatscounter_max,
+ "FORMERR received", resstats_desc,
+ "FORMERR", resstats_xmldesc);
+ set_desc(dns_resstatscounter_othererror, dns_resstatscounter_max,
+ "other errors received", resstats_desc,
+ "OtherError", resstats_xmldesc);
+ set_desc(dns_resstatscounter_edns0fail, dns_resstatscounter_max,
+ "EDNS(0) query failures", resstats_desc,
+ "EDNS0Fail", resstats_xmldesc);
+ set_desc(dns_resstatscounter_mismatch, dns_resstatscounter_max,
+ "mismatch responses received", resstats_desc,
+ "Mismatch", resstats_xmldesc);
+ set_desc(dns_resstatscounter_truncated, dns_resstatscounter_max,
+ "truncated responses received", resstats_desc,
+ "Truncated", resstats_xmldesc);
+ set_desc(dns_resstatscounter_lame, dns_resstatscounter_max,
+ "lame delegations received", resstats_desc,
+ "Lame", resstats_xmldesc);
+ set_desc(dns_resstatscounter_retry, dns_resstatscounter_max,
+ "query retries", resstats_desc,
+ "Retry", resstats_xmldesc);
+ set_desc(dns_resstatscounter_gluefetchv4, dns_resstatscounter_max,
+ "IPv4 NS address fetches", resstats_desc,
+ "GlueFetchv4", resstats_xmldesc);
+ set_desc(dns_resstatscounter_gluefetchv6, dns_resstatscounter_max,
+ "IPv6 NS address fetches", resstats_desc,
+ "GlueFetchv6", resstats_xmldesc);
+ set_desc(dns_resstatscounter_gluefetchv4fail, dns_resstatscounter_max,
+ "IPv4 NS address fetch failed", resstats_desc,
+ "GlueFetchv4Fail", resstats_xmldesc);
+ set_desc(dns_resstatscounter_gluefetchv6fail, dns_resstatscounter_max,
+ "IPv6 NS address fetch failed", resstats_desc,
+ "GlueFetchv6Fail", resstats_xmldesc);
+ set_desc(dns_resstatscounter_val, dns_resstatscounter_max,
+ "DNSSEC validation attempted", resstats_desc,
+ "ValAttempt", resstats_xmldesc);
+ set_desc(dns_resstatscounter_valsuccess, dns_resstatscounter_max,
+ "DNSSEC validation succeeded", resstats_desc,
+ "ValOk", resstats_xmldesc);
+ set_desc(dns_resstatscounter_valnegsuccess, dns_resstatscounter_max,
+ "DNSSEC NX validation succeeded", resstats_desc,
+ "ValNegOk", resstats_xmldesc);
+ set_desc(dns_resstatscounter_valfail, dns_resstatscounter_max,
+ "DNSSEC validation failed", resstats_desc,
+ "ValFail", resstats_xmldesc);
+
+ /* Initialize zone statistics */
+ memset(zonestats_desc, 0,
+ dns_zonestatscounter_max * sizeof(zonestats_desc[0]));
+#ifdef HAVE_LIBXML2
+ memset(zonestats_xmldesc, 0,
+ dns_zonestatscounter_max * sizeof(zonestats_xmldesc[0]));
+#endif
+ set_desc(dns_zonestatscounter_notifyoutv4, dns_zonestatscounter_max,
+ "IPv4 notifies sent", zonestats_desc,
+ "NotifyOutv4", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_notifyoutv6, dns_zonestatscounter_max,
+ "IPv6 notifies sent", zonestats_desc,
+ "NotifyOutv6", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_notifyinv4, dns_zonestatscounter_max,
+ "IPv4 notifies received", zonestats_desc,
+ "NotifyInv4", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_notifyinv6, dns_zonestatscounter_max,
+ "IPv6 notifies received", zonestats_desc,
+ "NotifyInv6", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_notifyrej, dns_zonestatscounter_max,
+ "notifies rejected", zonestats_desc,
+ "NotifyRej", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_soaoutv4, dns_zonestatscounter_max,
+ "IPv4 SOA queries sent", zonestats_desc,
+ "SOAOutv4", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_soaoutv6, dns_zonestatscounter_max,
+ "IPv6 SOA queries sent", zonestats_desc,
+ "SOAOutv6", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_axfrreqv4, dns_zonestatscounter_max,
+ "IPv4 AXFR requested", zonestats_desc,
+ "AXFRReqv4", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_axfrreqv6, dns_zonestatscounter_max,
+ "IPv6 AXFR requested", zonestats_desc,
+ "AXFRReqv6", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_ixfrreqv4, dns_zonestatscounter_max,
+ "IPv4 IXFR requested", zonestats_desc,
+ "IXFRReqv4", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_ixfrreqv6, dns_zonestatscounter_max,
+ "IPv6 IXFR requested", zonestats_desc,
+ "IXFRReqv6", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_xfrsuccess, dns_zonestatscounter_max,
+ "transfer requests succeeded", zonestats_desc,
+ "XfrSuccess", zonestats_xmldesc);
+ set_desc(dns_zonestatscounter_xfrfail, dns_zonestatscounter_max,
+ "transfer requests failed", zonestats_desc,
+ "XfrFail", zonestats_xmldesc);
+
+ /* Sanity check */
+ for (i = 0; i < dns_nsstatscounter_max; i++)
+ INSIST(nsstats_desc[i] != NULL);
+ for (i = 0; i < dns_resstatscounter_max; i++)
+ INSIST(resstats_desc[i] != NULL);
+ for (i = 0; i < dns_zonestatscounter_max; i++)
+ INSIST(zonestats_desc[i] != NULL);
+#ifdef HAVE_LIBXML2
+ for (i = 0; i < dns_nsstatscounter_max; i++)
+ INSIST(nsstats_xmldesc[i] != NULL);
+ for (i = 0; i < dns_resstatscounter_max; i++)
+ INSIST(resstats_xmldesc[i] != NULL);
+ for (i = 0; i < dns_zonestatscounter_max; i++)
+ INSIST(zonestats_xmldesc[i] != NULL);
+#endif
+}
+
+/*%
+ * Dump callback functions.
+ */
+static void
+generalstat_dump(dns_statscounter_t counter, isc_uint64_t val, void *arg) {
+ stats_dumparg_t *dumparg = arg;
+ FILE *fp;
+#ifdef HAVE_LIBXML2
+ xmlTextWriterPtr writer;
+#endif
+
+ REQUIRE(counter < dumparg->ncounters);
+
+ switch (dumparg->type) {
+ case statsformat_file:
+ fp = dumparg->arg;
+ fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val,
+ dumparg->desc[counter]);
+ break;
+ case statsformat_xml:
+#ifdef HAVE_LIBXML2
+ writer = dumparg->arg;
+
+ if (dumparg->category != NULL) {
+ xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR
+ dumparg->category);
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+ xmlTextWriterWriteString(writer, ISC_XMLCHAR
+ dumparg->desc[counter]);
+ xmlTextWriterEndElement(writer); /* name */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR
+ "counter");
+ } else {
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR
+ dumparg->desc[counter]);
+ }
+ xmlTextWriterWriteFormatString(writer,
+ "%" ISC_PRINT_QUADFORMAT "u",
+ val);
+ xmlTextWriterEndElement(writer); /* counter */
+ if (dumparg->category != NULL)
+ xmlTextWriterEndElement(writer); /* category */
+#endif
+ break;
+ }
+}
+
+static void
+rdtypestat_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) {
+ char typebuf[64];
+ const char *typestr;
+ stats_dumparg_t *dumparg = arg;
+ FILE *fp;
+#ifdef HAVE_LIBXML2
+ xmlTextWriterPtr writer;
+#endif
+
+ if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_OTHERTYPE)
+ == 0) {
+ dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf,
+ sizeof(typebuf));
+ typestr = typebuf;
+ } else
+ typestr = "Others";
+
+ switch (dumparg->type) {
+ case statsformat_file:
+ fp = dumparg->arg;
+ fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val, typestr);
+ break;
+ case statsformat_xml:
+#ifdef HAVE_LIBXML2
+ writer = dumparg->arg;
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "rdtype");
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+ xmlTextWriterWriteString(writer, ISC_XMLCHAR typestr);
+ xmlTextWriterEndElement(writer); /* name */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter");
+ xmlTextWriterWriteFormatString(writer,
+ "%" ISC_PRINT_QUADFORMAT "u",
+ val);
+ xmlTextWriterEndElement(writer); /* counter */
+
+ xmlTextWriterEndElement(writer); /* rdtype */
+#endif
+ break;
+ }
+}
+
+static void
+rdatasetstats_dump(dns_rdatastatstype_t type, isc_uint64_t val, void *arg) {
+ stats_dumparg_t *dumparg = arg;
+ FILE *fp;
+ char typebuf[64];
+ const char *typestr;
+ isc_boolean_t nxrrset = ISC_FALSE;
+#ifdef HAVE_LIBXML2
+ xmlTextWriterPtr writer;
+#endif
+
+ if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_NXDOMAIN)
+ != 0) {
+ typestr = "NXDOMAIN";
+ } else if ((DNS_RDATASTATSTYPE_ATTR(type) &
+ DNS_RDATASTATSTYPE_ATTR_OTHERTYPE) != 0) {
+ typestr = "Others";
+ } else {
+ dns_rdatatype_format(DNS_RDATASTATSTYPE_BASE(type), typebuf,
+ sizeof(typebuf));
+ typestr = typebuf;
+ }
+
+ if ((DNS_RDATASTATSTYPE_ATTR(type) & DNS_RDATASTATSTYPE_ATTR_NXRRSET)
+ != 0)
+ nxrrset = ISC_TRUE;
+
+ switch (dumparg->type) {
+ case statsformat_file:
+ fp = dumparg->arg;
+ fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s%s\n", val,
+ nxrrset ? "!" : "", typestr);
+ break;
+ case statsformat_xml:
+#ifdef HAVE_LIBXML2
+ writer = dumparg->arg;
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "rrset");
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+ xmlTextWriterWriteFormatString(writer, "%s%s",
+ nxrrset ? "!" : "", typestr);
+ xmlTextWriterEndElement(writer); /* name */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter");
+ xmlTextWriterWriteFormatString(writer,
+ "%" ISC_PRINT_QUADFORMAT "u",
+ val);
+ xmlTextWriterEndElement(writer); /* counter */
+
+ xmlTextWriterEndElement(writer); /* rrset */
+#endif
+ break;
+ }
+}
+
+static void
+opcodestat_dump(dns_opcode_t code, isc_uint64_t val, void *arg) {
+ FILE *fp = arg;
+ isc_buffer_t b;
+ char codebuf[64];
+ stats_dumparg_t *dumparg = arg;
+#ifdef HAVE_LIBXML2
+ xmlTextWriterPtr writer;
+#endif
+
+ isc_buffer_init(&b, codebuf, sizeof(codebuf) - 1);
+ dns_opcode_totext(code, &b);
+ codebuf[isc_buffer_usedlength(&b)] = '\0';
+
+ switch (dumparg->type) {
+ case statsformat_file:
+ fp = dumparg->arg;
+ fprintf(fp, "%20" ISC_PRINT_QUADFORMAT "u %s\n", val, codebuf);
+ break;
+ case statsformat_xml:
+#ifdef HAVE_LIBXML2
+ writer = dumparg->arg;
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "opcode");
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+ xmlTextWriterWriteString(writer, ISC_XMLCHAR codebuf);
+ xmlTextWriterEndElement(writer); /* name */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "counter");
+ xmlTextWriterWriteFormatString(writer,
+ "%" ISC_PRINT_QUADFORMAT "u",
+ val);
+ xmlTextWriterEndElement(writer); /* counter */
+
+ xmlTextWriterEndElement(writer); /* opcode */
+#endif
+ break;
+ }
+}
+
+#ifdef HAVE_LIBXML2
+
+/* XXXMLG below here sucks. */
+
+#define TRY(a) do { result = (a); INSIST(result == ISC_R_SUCCESS); } while(0);
+#define TRY0(a) do { xmlrc = (a); INSIST(xmlrc >= 0); } while(0);
+
+static isc_result_t
+zone_xmlrender(dns_zone_t *zone, void *arg) {
+ char buf[1024 + 32]; /* sufficiently large for zone name and class */
+ dns_rdataclass_t rdclass;
+ isc_uint32_t serial;
+ xmlTextWriterPtr writer = arg;
+ stats_dumparg_t dumparg;
+ dns_stats_t *zonestats;
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "zone");
+
+ dns_zone_name(zone, buf, sizeof(buf));
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+ xmlTextWriterWriteString(writer, ISC_XMLCHAR buf);
+ xmlTextWriterEndElement(writer);
+
+ rdclass = dns_zone_getclass(zone);
+ dns_rdataclass_format(rdclass, buf, sizeof(buf));
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "rdataclass");
+ xmlTextWriterWriteString(writer, ISC_XMLCHAR buf);
+ xmlTextWriterEndElement(writer);
+
+ serial = dns_zone_getserial(zone);
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial");
+ xmlTextWriterWriteFormatString(writer, "%u", serial);
+ xmlTextWriterEndElement(writer);
+
+ dumparg.type = statsformat_xml;
+ dumparg.arg = writer;
+ dumparg.category = NULL;
+ dumparg.desc = nsstats_xmldesc;
+ dumparg.ncounters = dns_nsstatscounter_max;
+
+ zonestats = dns_zone_getrequeststats(zone);
+ if (zonestats != NULL) {
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "counters");
+ dns_generalstats_dump(zonestats, generalstat_dump,
+ &dumparg, DNS_STATSDUMP_VERBOSE);
+ xmlTextWriterEndElement(writer); /* counters */
+ }
+
+ xmlTextWriterEndElement(writer); /* zone */
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+generatexml(ns_server_t *server, int *buflen, xmlChar **buf) {
+ char boottime[sizeof "yyyy-mm-ddThh:mm:ssZ"];
+ char nowstr[sizeof "yyyy-mm-ddThh:mm:ssZ"];
+ isc_time_t now;
+ xmlTextWriterPtr writer;
+ xmlDocPtr doc;
+ int xmlrc;
+ dns_view_t *view;
+ stats_dumparg_t dumparg;
+ dns_stats_t *cachestats;
+
+ isc_time_now(&now);
+ isc_time_formatISO8601(&ns_g_boottime, boottime, sizeof boottime);
+ isc_time_formatISO8601(&now, nowstr, sizeof nowstr);
+
+ writer = xmlNewTextWriterDoc(&doc, 0);
+ TRY0(xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL));
+ TRY0(xmlTextWriterWritePI(writer, ISC_XMLCHAR "xml-stylesheet",
+ ISC_XMLCHAR "type=\"text/xsl\" href=\"/bind9.xsl\""));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "isc"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
+ ISC_XMLCHAR "1.0"));
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "bind"));
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "statistics"));
+ TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "version",
+ ISC_XMLCHAR "1.0"));
+
+ /* Set common fields for statistics dump */
+ dumparg.type = statsformat_xml;
+ dumparg.arg = writer;
+
+ /*
+ * Start by rendering the views we know of here. For each view we
+ * know of, call its rendering function.
+ */
+ view = ISC_LIST_HEAD(server->viewlist);
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "views"));
+ while (view != NULL) {
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "view");
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+ xmlTextWriterWriteString(writer, ISC_XMLCHAR view->name);
+ xmlTextWriterEndElement(writer);
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "zones");
+ dns_zt_apply(view->zonetable, ISC_FALSE, zone_xmlrender,
+ writer);
+ xmlTextWriterEndElement(writer);
+
+ if (view->resquerystats != NULL) {
+ dns_rdatatypestats_dump(view->resquerystats,
+ rdtypestat_dump, &dumparg, 0);
+ }
+
+ if (view->resstats != NULL) {
+ dumparg.ncounters = dns_resstatscounter_max;
+ dumparg.category = "resstat";
+ dumparg.desc = resstats_xmldesc;
+ dns_generalstats_dump(view->resstats, generalstat_dump,
+ &dumparg, DNS_STATSDUMP_VERBOSE);
+ }
+
+ cachestats = dns_db_getrrsetstats(view->cachedb);
+ if (cachestats != NULL) {
+ xmlTextWriterStartElement(writer,
+ ISC_XMLCHAR "cache");
+ dns_rdatasetstats_dump(cachestats, rdatasetstats_dump,
+ &dumparg, 0);
+ xmlTextWriterEndElement(writer); /* cache */
+ }
+
+ xmlTextWriterEndElement(writer); /* view */
+
+ view = ISC_LIST_NEXT(view, link);
+ }
+ TRY0(xmlTextWriterEndElement(writer)); /* views */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "socketmgr"));
+ isc_socketmgr_renderxml(ns_g_socketmgr, writer);
+ TRY0(xmlTextWriterEndElement(writer)); /* socketmgr */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "taskmgr"));
+ isc_taskmgr_renderxml(ns_g_taskmgr, writer);
+ TRY0(xmlTextWriterEndElement(writer)); /* taskmgr */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "server"));
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "boot-time");
+ xmlTextWriterWriteString(writer, ISC_XMLCHAR boottime);
+ xmlTextWriterEndElement(writer);
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "current-time");
+ xmlTextWriterWriteString(writer, ISC_XMLCHAR nowstr);
+ xmlTextWriterEndElement(writer);
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "requests"));
+ dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg,
+ 0);
+ xmlTextWriterEndElement(writer); /* requests */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "queries-in"));
+ dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump,
+ &dumparg, 0);
+ xmlTextWriterEndElement(writer); /* queries-in */
+
+ dumparg.category = "nsstat";
+ dumparg.desc = nsstats_xmldesc;
+ dumparg.ncounters = dns_nsstatscounter_max;
+ dns_generalstats_dump(server->nsstats, generalstat_dump, &dumparg,
+ DNS_STATSDUMP_VERBOSE);
+
+ dumparg.category = "zonestat";
+ dumparg.desc = zonestats_xmldesc;
+ dumparg.ncounters = dns_zonestatscounter_max;
+ dns_generalstats_dump(server->zonestats, generalstat_dump, &dumparg,
+ DNS_STATSDUMP_VERBOSE);
+
+ /*
+ * Most of the common resolver statistics entries are 0, so we don't
+ * use the verbose dump here.
+ */
+ dumparg.category = "resstat";
+ dumparg.ncounters = dns_resstatscounter_max;
+ dumparg.desc = resstats_xmldesc;
+ dns_generalstats_dump(server->resolverstats, generalstat_dump,
+ &dumparg, 0);
+
+ xmlTextWriterEndElement(writer); /* server */
+
+ TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "memory"));
+ isc_mem_renderxml(writer);
+ TRY0(xmlTextWriterEndElement(writer)); /* memory */
+
+ TRY0(xmlTextWriterEndElement(writer)); /* statistics */
+ TRY0(xmlTextWriterEndElement(writer)); /* bind */
+ TRY0(xmlTextWriterEndElement(writer)); /* isc */
+
+ TRY0(xmlTextWriterEndDocument(writer));
+
+ xmlFreeTextWriter(writer);
+
+ xmlDocDumpFormatMemoryEnc(doc, buf, buflen, "UTF-8", 1);
+ xmlFreeDoc(doc);
+}
+
+static void
+wrap_xmlfree(isc_buffer_t *buffer, void *arg) {
+ UNUSED(arg);
+
+ xmlFree(isc_buffer_base(buffer));
+}
+
+static isc_result_t
+render_index(const char *url, const char *querystring, void *arg,
+ unsigned int *retcode, const char **retmsg, const char **mimetype,
+ isc_buffer_t *b, isc_httpdfree_t **freecb,
+ void **freecb_args)
+{
+ unsigned char *msg;
+ int msglen;
+ ns_server_t *server = arg;
+
+ UNUSED(url);
+ UNUSED(querystring);
+
+ generatexml(server, &msglen, &msg);
+
+ *retcode = 200;
+ *retmsg = "OK";
+ *mimetype = "text/xml";
+ isc_buffer_reinit(b, msg, msglen);
+ isc_buffer_add(b, msglen);
+ *freecb = wrap_xmlfree;
+ *freecb_args = NULL;
+
+ return (ISC_R_SUCCESS);
+}
+
+#endif /* HAVE_LIBXML2 */
+
+static isc_result_t
+render_xsl(const char *url, const char *querystring, void *args,
+ unsigned int *retcode, const char **retmsg, const char **mimetype,
+ isc_buffer_t *b, isc_httpdfree_t **freecb,
+ void **freecb_args)
+{
+ UNUSED(url);
+ UNUSED(querystring);
+ UNUSED(args);
+
+ *retcode = 200;
+ *retmsg = "OK";
+ *mimetype = "text/xslt+xml";
+ isc_buffer_reinit(b, xslmsg, strlen(xslmsg));
+ isc_buffer_add(b, strlen(xslmsg));
+ *freecb = NULL;
+ *freecb_args = NULL;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+shutdown_listener(ns_statschannel_t *listener) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&listener->address, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,NS_LOGMODULE_SERVER,
+ ISC_LOG_NOTICE, "stopping statistics channel on %s",
+ socktext);
+
+ isc_httpdmgr_shutdown(&listener->httpdmgr);
+}
+
+static isc_boolean_t
+client_ok(const isc_sockaddr_t *fromaddr, void *arg) {
+ ns_statschannel_t *listener = arg;
+ isc_netaddr_t netaddr;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ int match;
+
+ REQUIRE(listener != NULL);
+
+ isc_netaddr_fromsockaddr(&netaddr, fromaddr);
+
+ LOCK(&listener->lock);
+ if (dns_acl_match(&netaddr, NULL, listener->acl, &ns_g_server->aclenv,
+ &match, NULL) == ISC_R_SUCCESS && match > 0) {
+ UNLOCK(&listener->lock);
+ return (ISC_TRUE);
+ }
+ UNLOCK(&listener->lock);
+
+ isc_sockaddr_format(fromaddr, socktext, sizeof(socktext));
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "rejected statistics connection from %s", socktext);
+
+ return (ISC_FALSE);
+}
+
+static void
+destroy_listener(void *arg) {
+ ns_statschannel_t *listener = arg;
+
+ REQUIRE(listener != NULL);
+ REQUIRE(!ISC_LINK_LINKED(listener, link));
+
+ /* We don't have to acquire the lock here since it's already unlinked */
+ dns_acl_detach(&listener->acl);
+
+ DESTROYLOCK(&listener->lock);
+ isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener));
+}
+
+static isc_result_t
+add_listener(ns_server_t *server, ns_statschannel_t **listenerp,
+ const cfg_obj_t *listen_params, const cfg_obj_t *config,
+ isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
+ const char *socktext)
+{
+ isc_result_t result;
+ ns_statschannel_t *listener;
+ isc_task_t *task = NULL;
+ isc_socket_t *sock = NULL;
+ const cfg_obj_t *allow;
+ dns_acl_t *new_acl = NULL;
+
+ listener = isc_mem_get(server->mctx, sizeof(*listener));
+ if (listener == NULL)
+ return (ISC_R_NOMEMORY);
+
+ listener->httpdmgr = NULL;
+ listener->address = *addr;
+ listener->acl = NULL;
+ listener->mctx = NULL;
+ ISC_LINK_INIT(listener, link);
+
+ result = isc_mutex_init(&listener->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(server->mctx, listener, sizeof(*listener));
+ return (ISC_R_FAILURE);
+ }
+
+ isc_mem_attach(server->mctx, &listener->mctx);
+
+ allow = cfg_tuple_get(listen_params, "allow");
+ if (allow != NULL && cfg_obj_islist(allow)) {
+ result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
+ aclconfctx, listener->mctx, 0,
+ &new_acl);
+ } else
+ result = dns_acl_any(listener->mctx, &new_acl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_acl_attach(new_acl, &listener->acl);
+ dns_acl_detach(&new_acl);
+
+ result = isc_task_create(ns_g_taskmgr, 0, &task);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_task_setname(task, "statchannel", NULL);
+
+ result = isc_socket_create(ns_g_socketmgr, isc_sockaddr_pf(addr),
+ isc_sockettype_tcp, &sock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_socket_setname(sock, "statchannel", NULL);
+
+#ifndef ISC_ALLOW_MAPPED
+ isc_socket_ipv6only(sock, ISC_TRUE);
+#endif
+
+ result = isc_socket_bind(sock, addr, ISC_SOCKET_REUSEADDRESS);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = isc_httpdmgr_create(server->mctx, sock, task, client_ok,
+ destroy_listener, listener, ns_g_timermgr,
+ &listener->httpdmgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+#ifdef HAVE_LIBXML2
+ isc_httpdmgr_addurl(listener->httpdmgr, "/", render_index, server);
+#endif
+ isc_httpdmgr_addurl(listener->httpdmgr, "/bind9.xsl", render_xsl,
+ server);
+
+ *listenerp = listener;
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_NOTICE,
+ "statistics channel listening on %s", socktext);
+
+cleanup:
+ if (result != ISC_R_SUCCESS) {
+ if (listener->acl != NULL)
+ dns_acl_detach(&listener->acl);
+ DESTROYLOCK(&listener->lock);
+ isc_mem_putanddetach(&listener->mctx, listener,
+ sizeof(*listener));
+ }
+ if (task != NULL)
+ isc_task_detach(&task);
+ if (sock != NULL)
+ isc_socket_detach(&sock);
+
+ return (result);
+}
+
+static void
+update_listener(ns_server_t *server, ns_statschannel_t **listenerp,
+ const cfg_obj_t *listen_params, const cfg_obj_t *config,
+ isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
+ const char *socktext)
+{
+ ns_statschannel_t *listener;
+ const cfg_obj_t *allow = NULL;
+ dns_acl_t *new_acl = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ for (listener = ISC_LIST_HEAD(server->statschannels);
+ listener != NULL;
+ listener = ISC_LIST_NEXT(listener, link))
+ if (isc_sockaddr_equal(addr, &listener->address))
+ break;
+
+ if (listener == NULL) {
+ *listenerp = NULL;
+ return;
+ }
+
+ /*
+ * Now, keep the old access list unless a new one can be made.
+ */
+ allow = cfg_tuple_get(listen_params, "allow");
+ if (allow != NULL && cfg_obj_islist(allow)) {
+ result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
+ aclconfctx, listener->mctx, 0,
+ &new_acl);
+ } else
+ result = dns_acl_any(listener->mctx, &new_acl);
+
+ if (result == ISC_R_SUCCESS) {
+ LOCK(&listener->lock);
+
+ dns_acl_detach(&listener->acl);
+ dns_acl_attach(new_acl, &listener->acl);
+ dns_acl_detach(&new_acl);
+
+ UNLOCK(&listener->lock);
+ } else {
+ cfg_obj_log(listen_params, ns_g_lctx, ISC_LOG_WARNING,
+ "couldn't install new acl for "
+ "statistics channel %s: %s",
+ socktext, isc_result_totext(result));
+ }
+
+ *listenerp = listener;
+}
+
+isc_result_t
+ns_statschannels_configure(ns_server_t *server, const cfg_obj_t *config,
+ cfg_aclconfctx_t *aclconfctx)
+{
+ ns_statschannel_t *listener, *listener_next;
+ ns_statschannellist_t new_listeners;
+ const cfg_obj_t *statschannellist = NULL;
+ const cfg_listelt_t *element, *element2;
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS);
+
+ ISC_LIST_INIT(new_listeners);
+
+ /*
+ * Get the list of named.conf 'statistics-channels' statements.
+ */
+ (void)cfg_map_get(config, "statistics-channels", &statschannellist);
+
+ /*
+ * Run through the new address/port list, noting sockets that are
+ * already being listened on and moving them to the new list.
+ *
+ * Identifying duplicate addr/port combinations is left to either
+ * the underlying config code, or to the bind attempt getting an
+ * address-in-use error.
+ */
+ if (statschannellist != NULL) {
+#ifndef HAVE_LIBXML2
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "statistics-channels specified but not effective "
+ "due to missing XML library");
+#endif
+
+ for (element = cfg_list_first(statschannellist);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ const cfg_obj_t *statschannel;
+ const cfg_obj_t *listenercfg = NULL;
+
+ statschannel = cfg_listelt_value(element);
+ (void)cfg_map_get(statschannel, "inet",
+ &listenercfg);
+ if (listenercfg == NULL)
+ continue;
+
+ for (element2 = cfg_list_first(listenercfg);
+ element2 != NULL;
+ element2 = cfg_list_next(element2)) {
+ const cfg_obj_t *listen_params;
+ const cfg_obj_t *obj;
+ isc_sockaddr_t addr;
+
+ listen_params = cfg_listelt_value(element2);
+
+ obj = cfg_tuple_get(listen_params, "address");
+ addr = *cfg_obj_assockaddr(obj);
+ if (isc_sockaddr_getport(&addr) == 0)
+ isc_sockaddr_setport(&addr, NS_STATSCHANNEL_HTTPPORT);
+
+ isc_sockaddr_format(&addr, socktext,
+ sizeof(socktext));
+
+ isc_log_write(ns_g_lctx,
+ NS_LOGCATEGORY_GENERAL,
+ NS_LOGMODULE_SERVER,
+ ISC_LOG_DEBUG(9),
+ "processing statistics "
+ "channel %s",
+ socktext);
+
+ update_listener(server, &listener,
+ listen_params, config, &addr,
+ aclconfctx, socktext);
+
+ if (listener != NULL) {
+ /*
+ * Remove the listener from the old
+ * list, so it won't be shut down.
+ */
+ ISC_LIST_UNLINK(server->statschannels,
+ listener, link);
+ } else {
+ /*
+ * This is a new listener.
+ */
+ isc_result_t r;
+
+ r = add_listener(server, &listener,
+ listen_params, config,
+ &addr, aclconfctx,
+ socktext);
+ if (r != ISC_R_SUCCESS) {
+ cfg_obj_log(listen_params,
+ ns_g_lctx,
+ ISC_LOG_WARNING,
+ "couldn't allocate "
+ "statistics channel"
+ " %s: %s",
+ socktext,
+ isc_result_totext(r));
+ }
+ }
+
+ if (listener != NULL)
+ ISC_LIST_APPEND(new_listeners, listener,
+ link);
+ }
+ }
+ }
+
+ for (listener = ISC_LIST_HEAD(server->statschannels);
+ listener != NULL;
+ listener = listener_next) {
+ listener_next = ISC_LIST_NEXT(listener, link);
+ ISC_LIST_UNLINK(server->statschannels, listener, link);
+ shutdown_listener(listener);
+ }
+
+ ISC_LIST_APPENDLIST(server->statschannels, new_listeners, link);
+ return (ISC_R_SUCCESS);
+}
+
+void
+ns_statschannels_shutdown(ns_server_t *server) {
+ ns_statschannel_t *listener;
+
+ while ((listener = ISC_LIST_HEAD(server->statschannels)) != NULL) {
+ ISC_LIST_UNLINK(server->statschannels, listener, link);
+ shutdown_listener(listener);
+ }
+}
+
+isc_result_t
+ns_stats_dump(ns_server_t *server, FILE *fp) {
+ isc_stdtime_t now;
+ isc_result_t result;
+ dns_view_t *view;
+ dns_zone_t *zone, *next;
+ stats_dumparg_t dumparg;
+
+ RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS);
+
+ /* Set common fields */
+ dumparg.type = statsformat_file;
+ dumparg.arg = fp;
+ dumparg.category = NULL; /* unused */
+
+ isc_stdtime_get(&now);
+ fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);
+
+ fprintf(fp, "++ Incoming Requests ++\n");
+ dns_opcodestats_dump(server->opcodestats, opcodestat_dump, &dumparg, 0);
+
+ fprintf(fp, "++ Incoming Queries ++\n");
+ dns_rdatatypestats_dump(server->rcvquerystats, rdtypestat_dump,
+ &dumparg, 0);
+
+ fprintf(fp, "++ Outgoing Queries ++\n");
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ if (view->resquerystats == NULL)
+ continue;
+ if (strcmp(view->name, "_default") == 0)
+ fprintf(fp, "[View: default]\n");
+ else
+ fprintf(fp, "[View: %s]\n", view->name);
+ dns_rdatatypestats_dump(view->resquerystats, rdtypestat_dump,
+ &dumparg, 0);
+ }
+
+ fprintf(fp, "++ Name Server Statistics ++\n");
+ dumparg.desc = nsstats_desc;
+ dumparg.ncounters = dns_nsstatscounter_max;
+ dns_generalstats_dump(server->nsstats, generalstat_dump, &dumparg, 0);
+ fprintf(fp, "++ Zone Maintenance Statistics ++\n");
+ dumparg.desc = zonestats_desc;
+ dumparg.ncounters = dns_zonestatscounter_max;
+ dns_generalstats_dump(server->zonestats, generalstat_dump, &dumparg, 0);
+
+ fprintf(fp, "++ Resolver Statistics ++\n");
+ fprintf(fp, "[Common]\n");
+ dumparg.desc = resstats_desc;
+ dumparg.ncounters = dns_resstatscounter_max;
+ dns_generalstats_dump(server->resolverstats, generalstat_dump, &dumparg,
+ 0);
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ if (view->resstats == NULL)
+ continue;
+ if (strcmp(view->name, "_default") == 0)
+ fprintf(fp, "[View: default]\n");
+ else
+ fprintf(fp, "[View: %s]\n", view->name);
+ dns_generalstats_dump(view->resstats, generalstat_dump,
+ &dumparg, 0);
+ }
+
+ fprintf(fp, "++ Cache DB RRsets ++\n");
+ for (view = ISC_LIST_HEAD(server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ dns_stats_t *cachestats;
+
+ cachestats = dns_db_getrrsetstats(view->cachedb);
+ if (cachestats == NULL)
+ continue;
+ if (strcmp(view->name, "_default") == 0)
+ fprintf(fp, "[View: default]\n");
+ else
+ fprintf(fp, "[View: %s]\n", view->name);
+ dns_rdatasetstats_dump(cachestats, rdatasetstats_dump, &dumparg,
+ 0);
+ }
+
+ fprintf(fp, "++ Per Zone Query Statistics ++\n");
+ zone = NULL;
+ for (result = dns_zone_first(server->zonemgr, &zone);
+ result == ISC_R_SUCCESS;
+ next = NULL, result = dns_zone_next(zone, &next), zone = next)
+ {
+ dns_stats_t *zonestats = dns_zone_getrequeststats(zone);
+ if (zonestats != NULL) {
+ char zonename[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(dns_zone_getorigin(zone),
+ zonename, sizeof(zonename));
+ view = dns_zone_getview(zone);
+
+ fprintf(fp, "[%s", zonename);
+ if (strcmp(view->name, "_default") != 0)
+ fprintf(fp, " (view: %s)", view->name);
+ fprintf(fp, "]\n");
+
+ dumparg.desc = nsstats_desc;
+ dumparg.ncounters = dns_nsstatscounter_max;
+ dns_generalstats_dump(zonestats, generalstat_dump,
+ &dumparg, 0);
+ }
+ }
+
+ fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
+
+ return (ISC_R_SUCCESS); /* this function currently always succeeds */
+}
diff --git a/bin/named/tkeyconf.c b/bin/named/tkeyconf.c
new file mode 100644
index 0000000..82cf573
--- /dev/null
+++ b/bin/named/tkeyconf.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: tkeyconf.c,v 1.29 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/mem.h>
+
+#include <isccfg/cfg.h>
+
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+#include <dns/tkey.h>
+
+#include <dst/gssapi.h>
+
+#include <named/tkeyconf.h>
+
+#define RETERR(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
+#include<named/log.h>
+#define LOG(msg) \
+ isc_log_write(ns_g_lctx, \
+ NS_LOGCATEGORY_GENERAL, \
+ NS_LOGMODULE_SERVER, \
+ ISC_LOG_ERROR, \
+ "%s", msg)
+
+isc_result_t
+ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx,
+ isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
+{
+ isc_result_t result;
+ dns_tkeyctx_t *tctx = NULL;
+ const char *s;
+ isc_uint32_t n;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_buffer_t b;
+ const cfg_obj_t *obj;
+ int type;
+
+ result = dns_tkeyctx_create(mctx, ectx, &tctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ obj = NULL;
+ result = cfg_map_get(options, "tkey-dhkey", &obj);
+ if (result == ISC_R_SUCCESS) {
+ s = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
+ n = cfg_obj_asuint32(cfg_tuple_get(obj, "keyid"));
+ isc_buffer_init(&b, s, strlen(s));
+ 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));
+ 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));
+ }
+
+ obj = NULL;
+ result = cfg_map_get(options, "tkey-domain", &obj);
+ if (result == ISC_R_SUCCESS) {
+ s = cfg_obj_asstring(obj);
+ isc_buffer_init(&b, s, strlen(s));
+ 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));
+ tctx->domain = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (tctx->domain == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ dns_name_init(tctx->domain, NULL);
+ RETERR(dns_name_dup(name, mctx, tctx->domain));
+ }
+
+ obj = NULL;
+ result = cfg_map_get(options, "tkey-gssapi-credential", &obj);
+ if (result == ISC_R_SUCCESS) {
+ s = cfg_obj_asstring(obj);
+
+ isc_buffer_init(&b, s, strlen(s));
+ 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));
+ }
+
+ *tctxp = tctx;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ dns_tkeyctx_destroy(&tctx);
+ return (result);
+}
+
diff --git a/bin/named/tsigconf.c b/bin/named/tsigconf.c
new file mode 100644
index 0000000..b3c6e02
--- /dev/null
+++ b/bin/named/tsigconf.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: tsigconf.c,v 1.30 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+
+#include <isccfg/cfg.h>
+
+#include <dns/tsig.h>
+#include <dns/result.h>
+
+#include <named/log.h>
+
+#include <named/config.h>
+#include <named/tsigconf.h>
+
+static isc_result_t
+add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring,
+ isc_mem_t *mctx)
+{
+ dns_tsigkey_t *tsigkey = NULL;
+ const cfg_listelt_t *element;
+ const cfg_obj_t *key = NULL;
+ const char *keyid = NULL;
+ unsigned char *secret = NULL;
+ int secretalloc = 0;
+ int secretlen = 0;
+ isc_result_t ret;
+ isc_stdtime_t now;
+ isc_uint16_t bits;
+
+ for (element = cfg_list_first(list);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *algobj = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ dns_name_t keyname;
+ dns_name_t *alg;
+ const char *algstr;
+ char keynamedata[1024];
+ isc_buffer_t keynamesrc, keynamebuf;
+ const char *secretstr;
+ isc_buffer_t secretbuf;
+
+ key = cfg_listelt_value(element);
+ keyid = cfg_obj_asstring(cfg_map_getname(key));
+
+ algobj = NULL;
+ secretobj = NULL;
+ (void)cfg_map_get(key, "algorithm", &algobj);
+ (void)cfg_map_get(key, "secret", &secretobj);
+ INSIST(algobj != NULL && secretobj != NULL);
+
+ /*
+ * Create the key name.
+ */
+ dns_name_init(&keyname, NULL);
+ isc_buffer_init(&keynamesrc, keyid, strlen(keyid));
+ isc_buffer_add(&keynamesrc, strlen(keyid));
+ isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata));
+ ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname,
+ ISC_TRUE, &keynamebuf);
+ if (ret != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Create the algorithm.
+ */
+ algstr = cfg_obj_asstring(algobj);
+ if (ns_config_getkeyalgorithm(algstr, &alg, &bits)
+ != ISC_R_SUCCESS) {
+ cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR,
+ "key '%s': has a unsupported algorithm '%s'",
+ keyid, algstr);
+ ret = DNS_R_BADALG;
+ goto failure;
+ }
+
+ secretstr = cfg_obj_asstring(secretobj);
+ secretalloc = secretlen = strlen(secretstr) * 3 / 4;
+ secret = isc_mem_get(mctx, secretlen);
+ if (secret == NULL) {
+ ret = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ isc_buffer_init(&secretbuf, secret, secretlen);
+ ret = isc_base64_decodestring(secretstr, &secretbuf);
+ if (ret != ISC_R_SUCCESS)
+ goto failure;
+ secretlen = isc_buffer_usedlength(&secretbuf);
+
+ isc_stdtime_get(&now);
+ ret = dns_tsigkey_create(&keyname, alg, secret, secretlen,
+ ISC_FALSE, NULL, now, now,
+ mctx, ring, &tsigkey);
+ isc_mem_put(mctx, secret, secretalloc);
+ secret = NULL;
+ if (ret != ISC_R_SUCCESS)
+ goto failure;
+ /*
+ * Set digest bits.
+ */
+ dst_key_setbits(tsigkey->key, bits);
+ dns_tsigkey_detach(&tsigkey);
+ }
+
+ return (ISC_R_SUCCESS);
+
+ failure:
+ cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
+ "configuring key '%s': %s", keyid,
+ isc_result_totext(ret));
+
+ if (secret != NULL)
+ isc_mem_put(mctx, secret, secretalloc);
+ return (ret);
+}
+
+isc_result_t
+ns_tsigkeyring_fromconfig(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ isc_mem_t *mctx, dns_tsig_keyring_t **ringp)
+{
+ const cfg_obj_t *maps[3];
+ const cfg_obj_t *keylist;
+ dns_tsig_keyring_t *ring = NULL;
+ isc_result_t result;
+ int i;
+
+ i = 0;
+ if (config != NULL)
+ maps[i++] = config;
+ if (vconfig != NULL)
+ maps[i++] = cfg_tuple_get(vconfig, "options");
+ maps[i] = NULL;
+
+ result = dns_tsigkeyring_create(mctx, &ring);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (i = 0; ; i++) {
+ if (maps[i] == NULL)
+ break;
+ keylist = NULL;
+ result = cfg_map_get(maps[i], "key", &keylist);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ result = add_initial_keys(keylist, ring, mctx);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
+
+ *ringp = ring;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ dns_tsigkeyring_destroy(&ring);
+ return (result);
+}
diff --git a/bin/named/unix/Makefile.in b/bin/named/unix/Makefile.in
new file mode 100644
index 0000000..5092834
--- /dev/null
+++ b/bin/named/unix/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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.10 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/named/unix/include/named/os.h b/bin/named/unix/include/named/os.h
new file mode 100644
index 0000000..d03bf75
--- /dev/null
+++ b/bin/named/unix/include/named/os.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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.h,v 1.29 2008/10/24 01:44:48 tbox Exp $ */
+
+#ifndef NS_OS_H
+#define NS_OS_H 1
+
+/*! \file */
+
+#include <isc/types.h>
+
+void
+ns_os_init(const char *progname);
+
+void
+ns_os_daemonize(void);
+
+void
+ns_os_opendevnull(void);
+
+void
+ns_os_closedevnull(void);
+
+void
+ns_os_chroot(const char *root);
+
+void
+ns_os_inituserinfo(const char *username);
+
+void
+ns_os_changeuser(void);
+
+void
+ns_os_adjustnofile(void);
+
+void
+ns_os_minprivs(void);
+
+void
+ns_os_writepidfile(const char *filename, isc_boolean_t first_time);
+void
+ns_os_shutdown(void);
+
+isc_result_t
+ns_os_gethostname(char *buf, size_t len);
+
+void
+ns_os_shutdownmsg(char *command, isc_buffer_t *text);
+
+void
+ns_os_tzset(void);
+
+void
+ns_os_started(void);
+
+#endif /* NS_OS_H */
diff --git a/bin/named/unix/os.c b/bin/named/unix/os.c
new file mode 100644
index 0000000..d3b2ff3
--- /dev/null
+++ b/bin/named/unix/os.c
@@ -0,0 +1,816 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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.89 2008/11/14 05:08:48 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+#include <stdarg.h>
+
+#include <sys/types.h> /* dev_t FreeBSD 2.1 */
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h> /* Required for initgroups() on IRIX. */
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <syslog.h>
+#ifdef HAVE_TZSET
+#include <time.h>
+#endif
+#include <unistd.h>
+
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/print.h>
+#include <isc/resource.h>
+#include <isc/result.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+
+#include <named/main.h>
+#include <named/os.h>
+#ifdef HAVE_LIBSCF
+#include <named/ns_smf_globals.h>
+#endif
+
+static char *pidfile = NULL;
+static int devnullfd = -1;
+
+#ifndef ISC_FACILITY
+#define ISC_FACILITY LOG_DAEMON
+#endif
+
+/*
+ * If there's no <linux/capability.h>, we don't care about <sys/prctl.h>
+ */
+#ifndef HAVE_LINUX_CAPABILITY_H
+#undef HAVE_SYS_PRCTL_H
+#endif
+
+/*
+ * Linux defines:
+ * (T) HAVE_LINUXTHREADS
+ * (C) HAVE_SYS_CAPABILITY_H (or HAVE_LINUX_CAPABILITY_H)
+ * (P) HAVE_SYS_PRCTL_H
+ * The possible cases are:
+ * none: setuid() normally
+ * T: no setuid()
+ * C: setuid() normally, drop caps (keep CAP_SETUID)
+ * T+C: no setuid(), drop caps (don't keep CAP_SETUID)
+ * T+C+P: setuid() early, drop caps (keep CAP_SETUID)
+ * C+P: setuid() normally, drop caps (keep CAP_SETUID)
+ * P: not possible
+ * T+P: not possible
+ *
+ * if (C)
+ * caps = BIND_SERVICE + CHROOT + SETGID
+ * if ((T && C && P) || !T)
+ * caps += SETUID
+ * endif
+ * capset(caps)
+ * endif
+ * if (T && C && P && -u)
+ * setuid()
+ * else if (T && -u)
+ * fail
+ * --> start threads
+ * if (!T && -u)
+ * setuid()
+ * if (C && (P || !-u))
+ * caps = BIND_SERVICE
+ * capset(caps)
+ * endif
+ *
+ * It will be nice when Linux threads work properly with setuid().
+ */
+
+#ifdef HAVE_LINUXTHREADS
+static pid_t mainpid = 0;
+#endif
+
+static struct passwd *runas_pw = NULL;
+static isc_boolean_t done_setuid = ISC_FALSE;
+static int dfd[2] = { -1, -1 };
+
+#ifdef HAVE_LINUX_CAPABILITY_H
+
+static isc_boolean_t non_root = ISC_FALSE;
+static isc_boolean_t non_root_caps = ISC_FALSE;
+
+#ifdef HAVE_SYS_CAPABILITY_H
+#include <sys/capability.h>
+#else
+/*%
+ * We define _LINUX_FS_H to prevent it from being included. We don't need
+ * anything from it, and the files it includes cause warnings with 2.2
+ * kernels, and compilation failures (due to conflicts between <linux/string.h>
+ * and <string.h>) on 2.3 kernels.
+ */
+#define _LINUX_FS_H
+#include <linux/capability.h>
+#include <syscall.h>
+#ifndef SYS_capset
+#ifndef __NR_capset
+#include <asm/unistd.h> /* Slackware 4.0 needs this. */
+#endif /* __NR_capset */
+#define SYS_capset __NR_capset
+#endif /* SYS_capset */
+#endif /* HAVE_SYS_CAPABILITY_H */
+
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h> /* Required for prctl(). */
+
+/*
+ * If the value of PR_SET_KEEPCAPS is not in <sys/prctl.h>, define it
+ * here. This allows setuid() to work on systems running a new enough
+ * kernel but with /usr/include/linux pointing to "standard" kernel
+ * headers.
+ */
+#ifndef PR_SET_KEEPCAPS
+#define PR_SET_KEEPCAPS 8
+#endif
+
+#endif /* HAVE_SYS_PRCTL_H */
+
+#ifdef HAVE_LIBCAP
+#define SETCAPS_FUNC "cap_set_proc "
+#else
+typedef unsigned int cap_t;
+#define SETCAPS_FUNC "syscall(capset) "
+#endif /* HAVE_LIBCAP */
+
+static void
+linux_setcaps(cap_t caps) {
+#ifndef HAVE_LIBCAP
+ struct __user_cap_header_struct caphead;
+ struct __user_cap_data_struct cap;
+#endif
+ char strbuf[ISC_STRERRORSIZE];
+
+ if ((getuid() != 0 && !non_root_caps) || non_root)
+ return;
+#ifndef HAVE_LIBCAP
+ memset(&caphead, 0, sizeof(caphead));
+ caphead.version = _LINUX_CAPABILITY_VERSION;
+ caphead.pid = 0;
+ memset(&cap, 0, sizeof(cap));
+ cap.effective = caps;
+ cap.permitted = caps;
+ cap.inheritable = 0;
+#endif
+#ifdef HAVE_LIBCAP
+ if (cap_set_proc(caps) < 0) {
+#else
+ if (syscall(SYS_capset, &caphead, &cap) < 0) {
+#endif
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal(SETCAPS_FUNC "failed: %s:"
+ " please ensure that the capset kernel"
+ " module is loaded. see insmod(8)",
+ strbuf);
+ }
+}
+
+#ifdef HAVE_LIBCAP
+#define SET_CAP(flag) \
+ do { \
+ capval = (flag); \
+ cap_flag_value_t curval; \
+ err = cap_get_flag(curcaps, capval, CAP_PERMITTED, &curval); \
+ if (err != -1 && curval) { \
+ err = cap_set_flag(caps, CAP_EFFECTIVE, 1, &capval, CAP_SET); \
+ if (err == -1) { \
+ isc__strerror(errno, strbuf, sizeof(strbuf)); \
+ ns_main_earlyfatal("cap_set_proc failed: %s", strbuf); \
+ } \
+ \
+ err = cap_set_flag(caps, CAP_PERMITTED, 1, &capval, CAP_SET); \
+ if (err == -1) { \
+ isc__strerror(errno, strbuf, sizeof(strbuf)); \
+ ns_main_earlyfatal("cap_set_proc failed: %s", strbuf); \
+ } \
+ } \
+ } while (0)
+#define INIT_CAP \
+ do { \
+ caps = cap_init(); \
+ if (caps == NULL) { \
+ isc__strerror(errno, strbuf, sizeof(strbuf)); \
+ ns_main_earlyfatal("cap_init failed: %s", strbuf); \
+ } \
+ curcaps = cap_get_proc(); \
+ if (curcaps == NULL) { \
+ isc__strerror(errno, strbuf, sizeof(strbuf)); \
+ ns_main_earlyfatal("cap_get_proc failed: %s", strbuf); \
+ } \
+ } while (0)
+#define FREE_CAP \
+ { \
+ cap_free(caps); \
+ cap_free(curcaps); \
+ } while (0)
+#else
+#define SET_CAP(flag) do { caps |= (1 << (flag)); } while (0)
+#define INIT_CAP do { caps = 0; } while (0)
+#endif /* HAVE_LIBCAP */
+
+static void
+linux_initialprivs(void) {
+ cap_t caps;
+#ifdef HAVE_LIBCAP
+ cap_t curcaps;
+ cap_value_t capval;
+ char strbuf[ISC_STRERRORSIZE];
+ int err;
+#endif
+
+ /*%
+ * We don't need most privileges, so we drop them right away.
+ * Later on linux_minprivs() will be called, which will drop our
+ * capabilities to the minimum needed to run the server.
+ */
+ INIT_CAP;
+
+ /*
+ * We need to be able to bind() to privileged ports, notably port 53!
+ */
+ SET_CAP(CAP_NET_BIND_SERVICE);
+
+ /*
+ * We need chroot() initially too.
+ */
+ SET_CAP(CAP_SYS_CHROOT);
+
+#if defined(HAVE_SYS_PRCTL_H) || !defined(HAVE_LINUXTHREADS)
+ /*
+ * We can setuid() only if either the kernel supports keeping
+ * capabilities after setuid() (which we don't know until we've
+ * tried) or we're not using threads. If either of these is
+ * true, we want the setuid capability.
+ */
+ SET_CAP(CAP_SETUID);
+#endif
+
+ /*
+ * Since we call initgroups, we need this.
+ */
+ SET_CAP(CAP_SETGID);
+
+ /*
+ * Without this, we run into problems reading a configuration file
+ * owned by a non-root user and non-world-readable on startup.
+ */
+ SET_CAP(CAP_DAC_READ_SEARCH);
+
+ /*
+ * XXX We might want to add CAP_SYS_RESOURCE, though it's not
+ * clear it would work right given the way linuxthreads work.
+ * XXXDCL But since we need to be able to set the maximum number
+ * of files, the stack size, data size, and core dump size to
+ * support named.conf options, this is now being added to test.
+ */
+ SET_CAP(CAP_SYS_RESOURCE);
+
+ linux_setcaps(caps);
+
+#ifdef HAVE_LIBCAP
+ FREE_CAP;
+#endif
+}
+
+static void
+linux_minprivs(void) {
+ cap_t caps;
+#ifdef HAVE_LIBCAP
+ cap_t curcaps;
+ cap_value_t capval;
+ char strbuf[ISC_STRERRORSIZE];
+ int err;
+#endif
+
+ INIT_CAP;
+ /*%
+ * Drop all privileges except the ability to bind() to privileged
+ * ports.
+ *
+ * It's important that we drop CAP_SYS_CHROOT. If we didn't, it
+ * chroot() could be used to escape from the chrooted area.
+ */
+
+ SET_CAP(CAP_NET_BIND_SERVICE);
+
+ /*
+ * XXX We might want to add CAP_SYS_RESOURCE, though it's not
+ * clear it would work right given the way linuxthreads work.
+ * XXXDCL But since we need to be able to set the maximum number
+ * of files, the stack size, data size, and core dump size to
+ * support named.conf options, this is now being added to test.
+ */
+ SET_CAP(CAP_SYS_RESOURCE);
+
+ linux_setcaps(caps);
+
+#ifdef HAVE_LIBCAP
+ FREE_CAP;
+#endif
+}
+
+#ifdef HAVE_SYS_PRCTL_H
+static void
+linux_keepcaps(void) {
+ char strbuf[ISC_STRERRORSIZE];
+ /*%
+ * Ask the kernel to allow us to keep our capabilities after we
+ * setuid().
+ */
+
+ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
+ if (errno != EINVAL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("prctl() failed: %s", strbuf);
+ }
+ } else {
+ non_root_caps = ISC_TRUE;
+ if (getuid() != 0)
+ non_root = ISC_TRUE;
+ }
+}
+#endif
+
+#endif /* HAVE_LINUX_CAPABILITY_H */
+
+
+static void
+setup_syslog(const char *progname) {
+ int options;
+
+ options = LOG_PID;
+#ifdef LOG_NDELAY
+ options |= LOG_NDELAY;
+#endif
+ openlog(isc_file_basename(progname), options, ISC_FACILITY);
+}
+
+void
+ns_os_init(const char *progname) {
+ setup_syslog(progname);
+#ifdef HAVE_LINUX_CAPABILITY_H
+ linux_initialprivs();
+#endif
+#ifdef HAVE_LINUXTHREADS
+ mainpid = getpid();
+#endif
+#ifdef SIGXFSZ
+ signal(SIGXFSZ, SIG_IGN);
+#endif
+}
+
+void
+ns_os_daemonize(void) {
+ pid_t pid;
+ char strbuf[ISC_STRERRORSIZE];
+
+ if (pipe(dfd) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("pipe(): %s", strbuf);
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("fork(): %s", strbuf);
+ }
+ if (pid != 0) {
+ int n;
+ /*
+ * Wait for the child to finish loading for the first time.
+ * This would be so much simpler if fork() worked once we
+ * were multi-threaded.
+ */
+ (void)close(dfd[1]);
+ do {
+ char buf;
+ n = read(dfd[0], &buf, 1);
+ if (n == 1)
+ _exit(0);
+ } while (n == -1 && errno == EINTR);
+ _exit(1);
+ }
+ (void)close(dfd[0]);
+
+ /*
+ * We're the child.
+ */
+
+#ifdef HAVE_LINUXTHREADS
+ mainpid = getpid();
+#endif
+
+ if (setsid() == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("setsid(): %s", strbuf);
+ }
+
+ /*
+ * Try to set stdin, stdout, and stderr to /dev/null, but press
+ * on even if it fails.
+ *
+ * XXXMLG The close() calls here are unneeded on all but NetBSD, but
+ * are harmless to include everywhere. dup2() is supposed to close
+ * the FD if it is in use, but unproven-pthreads-0.16 is broken
+ * and will end up closing the wrong FD. This will be fixed eventually,
+ * and these calls will be removed.
+ */
+ if (devnullfd != -1) {
+ if (devnullfd != STDIN_FILENO) {
+ (void)close(STDIN_FILENO);
+ (void)dup2(devnullfd, STDIN_FILENO);
+ }
+ if (devnullfd != STDOUT_FILENO) {
+ (void)close(STDOUT_FILENO);
+ (void)dup2(devnullfd, STDOUT_FILENO);
+ }
+ if (devnullfd != STDERR_FILENO) {
+ (void)close(STDERR_FILENO);
+ (void)dup2(devnullfd, STDERR_FILENO);
+ }
+ }
+}
+
+void
+ns_os_started(void) {
+ char buf = 0;
+
+ /*
+ * Signal to the parent that we stated successfully.
+ */
+ if (dfd[0] != -1 && dfd[1] != -1) {
+ write(dfd[1], &buf, 1);
+ close(dfd[1]);
+ dfd[0] = dfd[1] = -1;
+ }
+}
+
+void
+ns_os_opendevnull(void) {
+ devnullfd = open("/dev/null", O_RDWR, 0);
+}
+
+void
+ns_os_closedevnull(void) {
+ if (devnullfd != STDIN_FILENO &&
+ devnullfd != STDOUT_FILENO &&
+ devnullfd != STDERR_FILENO) {
+ close(devnullfd);
+ devnullfd = -1;
+ }
+}
+
+static isc_boolean_t
+all_digits(const char *s) {
+ if (*s == '\0')
+ return (ISC_FALSE);
+ while (*s != '\0') {
+ if (!isdigit((*s)&0xff))
+ return (ISC_FALSE);
+ s++;
+ }
+ return (ISC_TRUE);
+}
+
+void
+ns_os_chroot(const char *root) {
+ char strbuf[ISC_STRERRORSIZE];
+#ifdef HAVE_LIBSCF
+ ns_smf_chroot = 0;
+#endif
+ if (root != NULL) {
+ if (chroot(root) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("chroot(): %s", strbuf);
+ }
+ if (chdir("/") < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("chdir(/): %s", strbuf);
+ }
+#ifdef HAVE_LIBSCF
+ /* Set ns_smf_chroot flag on successful chroot. */
+ ns_smf_chroot = 1;
+#endif
+ }
+}
+
+void
+ns_os_inituserinfo(const char *username) {
+ char strbuf[ISC_STRERRORSIZE];
+ if (username == NULL)
+ return;
+
+ if (all_digits(username))
+ runas_pw = getpwuid((uid_t)atoi(username));
+ else
+ runas_pw = getpwnam(username);
+ endpwent();
+
+ if (runas_pw == NULL)
+ ns_main_earlyfatal("user '%s' unknown", username);
+
+ if (getuid() == 0) {
+ if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("initgroups(): %s", strbuf);
+ }
+ }
+
+}
+
+void
+ns_os_changeuser(void) {
+ char strbuf[ISC_STRERRORSIZE];
+ if (runas_pw == NULL || done_setuid)
+ return;
+
+ done_setuid = ISC_TRUE;
+
+#ifdef HAVE_LINUXTHREADS
+#ifdef HAVE_LINUX_CAPABILITY_H
+ if (!non_root_caps)
+ ns_main_earlyfatal("-u with Linux threads not supported: "
+ "requires kernel support for "
+ "prctl(PR_SET_KEEPCAPS)");
+#else
+ ns_main_earlyfatal("-u with Linux threads not supported: "
+ "no capabilities support or capabilities "
+ "disabled at build time");
+#endif
+#endif
+
+ if (setgid(runas_pw->pw_gid) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("setgid(): %s", strbuf);
+ }
+
+ if (setuid(runas_pw->pw_uid) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlyfatal("setuid(): %s", strbuf);
+ }
+
+#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_DUMPABLE)
+ /*
+ * Restore the ability of named to drop core after the setuid()
+ * call has disabled it.
+ */
+ if (prctl(PR_SET_DUMPABLE,1,0,0,0) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ ns_main_earlywarning("prctl(PR_SET_DUMPABLE) failed: %s",
+ strbuf);
+ }
+#endif
+#if defined(HAVE_LINUX_CAPABILITY_H) && !defined(HAVE_LINUXTHREADS)
+ linux_minprivs();
+#endif
+}
+
+void
+ns_os_adjustnofile() {
+#ifdef HAVE_LINUXTHREADS
+ isc_result_t result;
+ isc_resourcevalue_t newvalue;
+
+ /*
+ * Linux: max number of open files specified by one thread doesn't seem
+ * to apply to other threads on Linux.
+ */
+ newvalue = ISC_RESOURCE_UNLIMITED;
+
+ result = isc_resource_setlimit(isc_resource_openfiles, newvalue);
+ if (result != ISC_R_SUCCESS)
+ ns_main_earlywarning("couldn't adjust limit on open files");
+#endif
+}
+
+void
+ns_os_minprivs(void) {
+#ifdef HAVE_SYS_PRCTL_H
+ linux_keepcaps();
+#endif
+
+#ifdef HAVE_LINUXTHREADS
+ ns_os_changeuser(); /* Call setuid() before threads are started */
+#endif
+
+#if defined(HAVE_LINUX_CAPABILITY_H) && defined(HAVE_LINUXTHREADS)
+ linux_minprivs();
+#endif
+}
+
+static int
+safe_open(const char *filename, isc_boolean_t append) {
+ int fd;
+ struct stat sb;
+
+ if (stat(filename, &sb) == -1) {
+ if (errno != ENOENT)
+ return (-1);
+ } else if ((sb.st_mode & S_IFREG) == 0) {
+ errno = EOPNOTSUPP;
+ return (-1);
+ }
+
+ if (append)
+ fd = open(filename, O_WRONLY|O_CREAT|O_APPEND,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ else {
+ (void)unlink(filename);
+ fd = open(filename, O_WRONLY|O_CREAT|O_EXCL,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ }
+ return (fd);
+}
+
+static void
+cleanup_pidfile(void) {
+ if (pidfile != NULL) {
+ (void)unlink(pidfile);
+ free(pidfile);
+ }
+ pidfile = NULL;
+}
+
+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 *, ...);
+ unsigned int mode;
+ char *slash;
+ int n;
+
+ /*
+ * The caller must ensure any required synchronization.
+ */
+
+ report = first_time ? ns_main_earlyfatal : ns_main_earlywarning;
+
+ cleanup_pidfile();
+
+ if (filename == NULL)
+ return;
+
+ len = strlen(filename);
+ pidfile = malloc(len + 1);
+ if (pidfile == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't malloc '%s': %s", filename, strbuf);
+ return;
+ }
+ /* This is safe. */
+ strcpy(pidfile, filename);
+
+ /*
+ * Make the containing directory if it doesn't exist.
+ */
+ slash = strrchr(pidfile, '/');
+ if (slash != NULL && slash != pidfile) {
+ *slash = '\0';
+ mode = S_IRUSR | S_IWUSR | S_IXUSR; /* u=rwx */
+ mode |= S_IRGRP | S_IXGRP; /* g=rx */
+ mode |= S_IROTH | S_IXOTH; /* o=rx */
+ n = mkdir(pidfile, mode);
+ if (n == -1 && errno != EEXIST) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't mkdir %s': %s", filename,
+ strbuf);
+ free(pidfile);
+ pidfile = NULL;
+ return;
+ }
+ *slash = '/';
+ }
+
+ 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");
+ 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;
+ }
+#ifdef HAVE_LINUXTHREADS
+ pid = mainpid;
+#else
+ pid = getpid();
+#endif
+ if (fprintf(lockfile, "%ld\n", (long)pid) < 0) {
+ (*report)("fprintf() to pid file '%s' failed", filename);
+ (void)fclose(lockfile);
+ cleanup_pidfile();
+ return;
+ }
+ if (fflush(lockfile) == EOF) {
+ (*report)("fflush() to pid file '%s' failed", filename);
+ (void)fclose(lockfile);
+ cleanup_pidfile();
+ return;
+ }
+ (void)fclose(lockfile);
+}
+
+void
+ns_os_shutdown(void) {
+ closelog();
+ cleanup_pidfile();
+}
+
+isc_result_t
+ns_os_gethostname(char *buf, size_t len) {
+ int n;
+
+ n = gethostname(buf, len);
+ return ((n == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE);
+}
+
+static char *
+next_token(char **stringp, const char *delim) {
+ char *res;
+
+ do {
+ res = strsep(stringp, delim);
+ if (res == NULL)
+ break;
+ } while (*res == '\0');
+ return (res);
+}
+
+void
+ns_os_shutdownmsg(char *command, isc_buffer_t *text) {
+ char *input, *ptr;
+ unsigned int n;
+ pid_t pid;
+
+ input = command;
+
+ /* Skip the command name. */
+ ptr = next_token(&input, " \t");
+ if (ptr == NULL)
+ return;
+
+ ptr = next_token(&input, " \t");
+ if (ptr == NULL)
+ return;
+
+ if (strcmp(ptr, "-p") != 0)
+ return;
+
+#ifdef HAVE_LINUXTHREADS
+ pid = mainpid;
+#else
+ pid = getpid();
+#endif
+
+ n = snprintf((char *)isc_buffer_used(text),
+ isc_buffer_availablelength(text),
+ "pid: %ld", (long)pid);
+ /* Only send a message if it is complete. */
+ if (n < isc_buffer_availablelength(text))
+ isc_buffer_add(text, n);
+}
+
+void
+ns_os_tzset(void) {
+#ifdef HAVE_TZSET
+ tzset();
+#endif
+}
diff --git a/bin/named/update.c b/bin/named/update.c
new file mode 100644
index 0000000..4285e2c
--- /dev/null
+++ b/bin/named/update.c
@@ -0,0 +1,4296 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: update.c,v 1.151 2008/11/19 06:21:45 marka Exp $ */
+
+#include <config.h>
+
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/serial.h>
+#include <isc/string.h>
+#include <isc/taskpool.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/diff.h>
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/journal.h>
+#include <dns/keyvalues.h>
+#include <dns/message.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/soa.h>
+#include <dns/ssu.h>
+#include <dns/stats.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#include <named/client.h>
+#include <named/log.h>
+#include <named/server.h>
+#include <named/update.h>
+
+/*! \file
+ * \brief
+ * This module implements dynamic update as in RFC2136.
+ */
+
+/*
+ * XXX TODO:
+ * - document strict minimality
+ */
+
+/**************************************************************************/
+
+/*%
+ * Log level for tracing dynamic update protocol requests.
+ */
+#define LOGLEVEL_PROTOCOL ISC_LOG_INFO
+
+/*%
+ * Log level for low-level debug tracing.
+ */
+#define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
+
+/*%
+ * Check an operation for failure. These macros all assume that
+ * the function using them has a 'result' variable and a 'failure'
+ * label.
+ */
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+/*%
+ * Fail unconditionally with result 'code', which must not
+ * be ISC_R_SUCCESS. The reason for failure presumably has
+ * been logged already.
+ *
+ * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+
+#define FAIL(code) \
+ do { \
+ result = (code); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+/*%
+ * Fail unconditionally and log as a client error.
+ * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+#define FAILC(code, msg) \
+ do { \
+ const char *_what = "failed"; \
+ result = (code); \
+ switch (result) { \
+ case DNS_R_NXDOMAIN: \
+ case DNS_R_YXDOMAIN: \
+ case DNS_R_YXRRSET: \
+ case DNS_R_NXRRSET: \
+ _what = "unsuccessful"; \
+ } \
+ update_log(client, zone, LOGLEVEL_PROTOCOL, \
+ "update %s: %s (%s)", _what, \
+ msg, isc_result_totext(result)); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+#define PREREQFAILC(code, msg) \
+ do { \
+ inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
+ FAILC(code, msg); \
+ } while (0)
+
+#define FAILN(code, name, msg) \
+ do { \
+ const char *_what = "failed"; \
+ result = (code); \
+ switch (result) { \
+ case DNS_R_NXDOMAIN: \
+ case DNS_R_YXDOMAIN: \
+ case DNS_R_YXRRSET: \
+ case DNS_R_NXRRSET: \
+ _what = "unsuccessful"; \
+ } \
+ if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \
+ char _nbuf[DNS_NAME_FORMATSIZE]; \
+ dns_name_format(name, _nbuf, sizeof(_nbuf)); \
+ update_log(client, zone, LOGLEVEL_PROTOCOL, \
+ "update %s: %s: %s (%s)", _what, _nbuf, \
+ msg, isc_result_totext(result)); \
+ } \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+#define PREREQFAILN(code, name, msg) \
+ do { \
+ inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
+ FAILN(code, name, msg); \
+ } while (0)
+
+#define FAILNT(code, name, type, msg) \
+ do { \
+ const char *_what = "failed"; \
+ result = (code); \
+ switch (result) { \
+ case DNS_R_NXDOMAIN: \
+ case DNS_R_YXDOMAIN: \
+ case DNS_R_YXRRSET: \
+ case DNS_R_NXRRSET: \
+ _what = "unsuccessful"; \
+ } \
+ if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \
+ char _nbuf[DNS_NAME_FORMATSIZE]; \
+ char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \
+ dns_name_format(name, _nbuf, sizeof(_nbuf)); \
+ dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \
+ update_log(client, zone, LOGLEVEL_PROTOCOL, \
+ "update %s: %s/%s: %s (%s)", \
+ _what, _nbuf, _tbuf, msg, \
+ isc_result_totext(result)); \
+ } \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+#define PREREQFAILNT(code, name, type, msg) \
+ do { \
+ inc_stats(zone, dns_nsstatscounter_updatebadprereq); \
+ FAILNT(code, name, type, msg); \
+ } while (0)
+
+/*%
+ * Fail unconditionally and log as a server error.
+ * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+#define FAILS(code, msg) \
+ do { \
+ result = (code); \
+ update_log(client, zone, LOGLEVEL_PROTOCOL, \
+ "error: %s: %s", \
+ msg, isc_result_totext(result)); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+/*
+ * Return TRUE if NS_CLIENTATTR_TCP is set in the attibutes other FALSE.
+ */
+#define TCPCLIENT(client) (((client)->attributes & NS_CLIENTATTR_TCP) != 0)
+
+/**************************************************************************/
+
+typedef struct rr rr_t;
+
+struct rr {
+ /* dns_name_t name; */
+ isc_uint32_t ttl;
+ dns_rdata_t rdata;
+};
+
+typedef struct update_event update_event_t;
+
+struct update_event {
+ ISC_EVENT_COMMON(update_event_t);
+ dns_zone_t *zone;
+ isc_result_t result;
+ dns_message_t *answer;
+};
+
+/**************************************************************************/
+/*
+ * Forward declarations.
+ */
+
+static void update_action(isc_task_t *task, isc_event_t *event);
+static void updatedone_action(isc_task_t *task, isc_event_t *event);
+static isc_result_t send_forward_event(ns_client_t *client, dns_zone_t *zone);
+static void forward_done(isc_task_t *task, isc_event_t *event);
+
+/**************************************************************************/
+
+static void
+update_log(ns_client_t *client, dns_zone_t *zone,
+ int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
+
+static void
+update_log(ns_client_t *client, dns_zone_t *zone,
+ int level, const char *fmt, ...)
+{
+ va_list ap;
+ char message[4096];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+
+ if (client == NULL || zone == NULL)
+ return;
+
+ if (isc_log_wouldlog(ns_g_lctx, level) == ISC_FALSE)
+ return;
+
+ dns_name_format(dns_zone_getorigin(zone), namebuf,
+ sizeof(namebuf));
+ dns_rdataclass_format(dns_zone_getclass(zone), classbuf,
+ sizeof(classbuf));
+
+ va_start(ap, fmt);
+ vsnprintf(message, sizeof(message), fmt, ap);
+ va_end(ap);
+
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE,
+ level, "updating zone '%s/%s': %s",
+ namebuf, classbuf, message);
+}
+
+/*%
+ * Increment updated-related statistics counters.
+ */
+static inline void
+inc_stats(dns_zone_t *zone, dns_statscounter_t counter) {
+ dns_generalstats_increment(ns_g_server->nsstats, counter);
+
+ if (zone != NULL) {
+ dns_stats_t *zonestats = dns_zone_getrequeststats(zone);
+ if (zonestats != NULL)
+ dns_generalstats_increment(zonestats, counter);
+ }
+}
+
+/*%
+ * 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.
+ *
+ * 'message' contains the type of operation that is being attempted.
+ * 'slave' indicates if this is a slave zone. If 'acl' is NULL then
+ * log at debug=3.
+ * If the zone has no access controls configured ('acl' == NULL &&
+ * 'has_ssutable == ISC_FALS) log the attempt at info, otherwise
+ * at error.
+ *
+ * If the request was signed log that we received it.
+ */
+static isc_result_t
+checkupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message,
+ dns_name_t *zonename, isc_boolean_t slave,
+ isc_boolean_t has_ssutable)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ int level = ISC_LOG_ERROR;
+ const char *msg = "denied";
+ isc_result_t result;
+
+ if (slave && acl == NULL) {
+ result = DNS_R_NOTIMP;
+ level = ISC_LOG_DEBUG(3);
+ msg = "disabled";
+ } else {
+ result = ns_client_checkaclsilent(client, NULL, acl, ISC_FALSE);
+ if (result == ISC_R_SUCCESS) {
+ level = ISC_LOG_DEBUG(3);
+ msg = "approved";
+ } else if (acl == NULL && !has_ssutable) {
+ level = ISC_LOG_INFO;
+ }
+ }
+
+ if (client->signer != NULL) {
+ dns_name_format(client->signer, namebuf, sizeof(namebuf));
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
+ NS_LOGMODULE_UPDATE, ISC_LOG_INFO,
+ "signer \"%s\" %s", namebuf, msg);
+ }
+
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(client->view->rdclass, classbuf,
+ sizeof(classbuf));
+
+ ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
+ NS_LOGMODULE_UPDATE, level, "%s '%s/%s' %s",
+ message, namebuf, classbuf, msg);
+ return (result);
+}
+
+/*%
+ * Update a single RR in version 'ver' of 'db' and log the
+ * update in 'diff'.
+ *
+ * Ensures:
+ * \li '*tuple' == NULL. Either the tuple is freed, or its
+ * ownership has been transferred to the diff.
+ */
+static isc_result_t
+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;
+
+ /*
+ * 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);
+ if (result != ISC_R_SUCCESS) {
+ dns_difftuple_free(tuple);
+ return (result);
+ }
+
+ /*
+ * Merge it into the current pending journal entry.
+ */
+ dns_diff_appendminimal(diff, tuple);
+
+ /*
+ * Do not clear temp_diff.
+ */
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Perform the updates in 'updates' in version 'ver' of 'db' and log the
+ * update in 'diff'.
+ *
+ * Ensures:
+ * \li 'updates' is empty.
+ */
+static isc_result_t
+do_diff(dns_diff_t *updates, dns_db_t *db, dns_dbversion_t *ver,
+ dns_diff_t *diff)
+{
+ isc_result_t result;
+ while (! ISC_LIST_EMPTY(updates->tuples)) {
+ dns_difftuple_t *t = ISC_LIST_HEAD(updates->tuples);
+ ISC_LIST_UNLINK(updates->tuples, t, link);
+ CHECK(do_one_tuple(&t, db, ver, diff));
+ }
+ return (ISC_R_SUCCESS);
+
+ failure:
+ dns_diff_clear(diff);
+ return (result);
+}
+
+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)
+{
+ 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));
+}
+
+/**************************************************************************/
+/*
+ * Callback-style iteration over rdatasets and rdatas.
+ *
+ * foreach_rrset() can be used to iterate over the RRsets
+ * of a name and call a callback function with each
+ * one. Similarly, foreach_rr() can be used to iterate
+ * over the individual RRs at name, optionally restricted
+ * to RRs of a given type.
+ *
+ * The callback functions are called "actions" and take
+ * two arguments: a void pointer for passing arbitrary
+ * context information, and a pointer to the current RRset
+ * or RR. By convention, their names end in "_action".
+ */
+
+/*
+ * XXXRTH We might want to make this public somewhere in libdns.
+ */
+
+/*%
+ * Function type for foreach_rrset() iterator actions.
+ */
+typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset);
+
+/*%
+ * Function type for foreach_rr() iterator actions.
+ */
+typedef isc_result_t rr_func(void *data, rr_t *rr);
+
+/*%
+ * Internal context struct for foreach_node_rr().
+ */
+typedef struct {
+ rr_func * rr_action;
+ void * rr_action_data;
+} foreach_node_rr_ctx_t;
+
+/*%
+ * Internal helper function for foreach_node_rr().
+ */
+static isc_result_t
+foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ foreach_node_rr_ctx_t *ctx = data;
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ rr_t rr = { 0, DNS_RDATA_INIT };
+
+ dns_rdataset_current(rdataset, &rr.rdata);
+ rr.ttl = rdataset->ttl;
+ result = (*ctx->rr_action)(ctx->rr_action_data, &rr);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (result != ISC_R_NOMORE)
+ return (result);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * For each rdataset of 'name' in 'ver' of 'db', call 'action'
+ * with the rdataset and 'action_data' as arguments. If the name
+ * does not exist, do nothing.
+ *
+ * If 'action' returns an error, abort iteration and return the error.
+ */
+static isc_result_t
+foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ rrset_func *action, void *action_data)
+{
+ isc_result_t result;
+ dns_dbnode_t *node;
+ dns_rdatasetiter_t *iter;
+
+ node = NULL;
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ iter = NULL;
+ result = dns_db_allrdatasets(db, node, ver,
+ (isc_stdtime_t) 0, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ for (result = dns_rdatasetiter_first(iter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iter))
+ {
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ dns_rdatasetiter_current(iter, &rdataset);
+
+ result = (*action)(action_data, &rdataset);
+
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_iterator;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ cleanup_iterator:
+ dns_rdatasetiter_destroy(&iter);
+
+ cleanup_node:
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+/*%
+ * For each RR of 'name' in 'ver' of 'db', call 'action'
+ * with the RR and 'action_data' as arguments. If the name
+ * does not exist, do nothing.
+ *
+ * If 'action' returns an error, abort iteration
+ * and return the error.
+ */
+static isc_result_t
+foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ rr_func *rr_action, void *rr_action_data)
+{
+ foreach_node_rr_ctx_t ctx;
+ ctx.rr_action = rr_action;
+ ctx.rr_action_data = rr_action_data;
+ return (foreach_rrset(db, ver, name,
+ foreach_node_rr_action, &ctx));
+}
+
+
+/*%
+ * For each of the RRs specified by 'db', 'ver', 'name', 'type',
+ * (which can be dns_rdatatype_any to match any type), and 'covers', call
+ * 'action' with the RR and 'action_data' as arguments. If the name
+ * does not exist, or if no RRset of the given type exists at the name,
+ * do nothing.
+ *
+ * If 'action' returns an error, abort iteration and return the error.
+ */
+static isc_result_t
+foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
+ void *rr_action_data)
+{
+
+ isc_result_t result;
+ dns_dbnode_t *node;
+ dns_rdataset_t rdataset;
+
+ if (type == dns_rdatatype_any)
+ return (foreach_node_rr(db, ver, name,
+ rr_action, rr_action_data));
+
+ node = NULL;
+ if (type == dns_rdatatype_nsec3 ||
+ (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3))
+ result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
+ else
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, type, covers,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ goto cleanup_node;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset))
+ {
+ rr_t rr = { 0, DNS_RDATA_INIT };
+ dns_rdataset_current(&rdataset, &rr.rdata);
+ rr.ttl = rdataset.ttl;
+ result = (*rr_action)(rr_action_data, &rr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_rdataset;
+ }
+ if (result != ISC_R_NOMORE)
+ goto cleanup_rdataset;
+ result = ISC_R_SUCCESS;
+
+ cleanup_rdataset:
+ dns_rdataset_disassociate(&rdataset);
+ cleanup_node:
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+/**************************************************************************/
+/*
+ * Various tests on the database contents (for prerequisites, etc).
+ */
+
+/*%
+ * Function type for predicate functions that compare a database RR 'db_rr'
+ * against an update RR 'update_rr'.
+ */
+typedef isc_boolean_t rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
+
+/*%
+ * Helper function for rrset_exists().
+ */
+static isc_result_t
+rrset_exists_action(void *data, rr_t *rr) {
+ UNUSED(data);
+ UNUSED(rr);
+ return (ISC_R_EXISTS);
+}
+
+/*%
+ * Utility macro for RR existence checking functions.
+ *
+ * If the variable 'result' has the value ISC_R_EXISTS or
+ * ISC_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE,
+ * respectively, and return success.
+ *
+ * If 'result' has any other value, there was a failure.
+ * Return the failure result code and do not set *exists.
+ *
+ * This would be more readable as "do { if ... } while(0)",
+ * but that form generates tons of warnings on Solaris 2.6.
+ */
+#define RETURN_EXISTENCE_FLAG \
+ return ((result == ISC_R_EXISTS) ? \
+ (*exists = ISC_TRUE, ISC_R_SUCCESS) : \
+ ((result == ISC_R_SUCCESS) ? \
+ (*exists = ISC_FALSE, ISC_R_SUCCESS) : \
+ result))
+
+/*%
+ * Set '*exists' to true iff an rrset of the given type exists,
+ * to false otherwise.
+ */
+static isc_result_t
+rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ isc_boolean_t *exists)
+{
+ isc_result_t result;
+ result = foreach_rr(db, ver, name, type, covers,
+ rrset_exists_action, NULL);
+ RETURN_EXISTENCE_FLAG;
+}
+
+/*%
+ * Set '*visible' to true if the RRset exists and is part of the
+ * visible zone. Otherwise '*visible' is set to false unless a
+ * error occurs.
+ */
+static isc_result_t
+rrset_visible(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, isc_boolean_t *visible)
+{
+ isc_result_t result;
+ dns_fixedname_t fixed;
+
+ dns_fixedname_init(&fixed);
+ result = dns_db_find(db, name, ver, type, DNS_DBFIND_NOWILD,
+ (isc_stdtime_t) 0, NULL,
+ dns_fixedname_name(&fixed), NULL, NULL);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ *visible = ISC_TRUE;
+ break;
+ /*
+ * Glue, obsured, deleted or replaced records.
+ */
+ case DNS_R_DELEGATION:
+ case DNS_R_DNAME:
+ case DNS_R_CNAME:
+ case DNS_R_NXDOMAIN:
+ case DNS_R_NXRRSET:
+ case DNS_R_EMPTYNAME:
+ case DNS_R_COVERINGNSEC:
+ *visible = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ break;
+ default:
+ break;
+ }
+ return (result);
+}
+
+/*%
+ * Helper function for cname_incompatible_rrset_exists.
+ */
+static isc_result_t
+cname_compatibility_action(void *data, dns_rdataset_t *rrset) {
+ UNUSED(data);
+ if (rrset->type != dns_rdatatype_cname &&
+ ! dns_rdatatype_isdnssec(rrset->type))
+ return (ISC_R_EXISTS);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Check whether there is an rrset incompatible with adding a CNAME RR,
+ * i.e., anything but another CNAME (which can be replaced) or a
+ * DNSSEC RR (which can coexist).
+ *
+ * If such an incompatible rrset exists, set '*exists' to ISC_TRUE.
+ * Otherwise, set it to ISC_FALSE.
+ */
+static isc_result_t
+cname_incompatible_rrset_exists(dns_db_t *db, dns_dbversion_t *ver,
+ dns_name_t *name, isc_boolean_t *exists) {
+ isc_result_t result;
+ result = foreach_rrset(db, ver, name,
+ cname_compatibility_action, NULL);
+ RETURN_EXISTENCE_FLAG;
+}
+
+/*%
+ * Helper function for rr_count().
+ */
+static isc_result_t
+count_rr_action(void *data, rr_t *rr) {
+ int *countp = data;
+ UNUSED(rr);
+ (*countp)++;
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Count the number of RRs of 'type' belonging to 'name' in 'ver' of 'db'.
+ */
+static isc_result_t
+rr_count(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers, int *countp)
+{
+ *countp = 0;
+ return (foreach_rr(db, ver, name, type, covers,
+ count_rr_action, countp));
+}
+
+/*%
+ * Context struct and helper function for name_exists().
+ */
+
+static isc_result_t
+name_exists_action(void *data, dns_rdataset_t *rrset) {
+ UNUSED(data);
+ UNUSED(rrset);
+ return (ISC_R_EXISTS);
+}
+
+/*%
+ * Set '*exists' to true iff the given name exists, to false otherwise.
+ */
+static isc_result_t
+name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ isc_boolean_t *exists)
+{
+ isc_result_t result;
+ result = foreach_rrset(db, ver, name,
+ name_exists_action, NULL);
+ RETURN_EXISTENCE_FLAG;
+}
+
+/*
+ * 'ssu_check_t' is used to pass the arguements to
+ * dns_ssutable_checkrules() to the callback function
+ * ssu_checkrule().
+ */
+typedef struct {
+ /* The ownername of the record to be updated. */
+ dns_name_t *name;
+
+ /* The signature's name if the request was signed. */
+ dns_name_t *signer;
+
+ /* The address of the client if the request was received via TCP. */
+ isc_netaddr_t *tcpaddr;
+
+ /* The ssu table to check against. */
+ dns_ssutable_t *table;
+} ssu_check_t;
+
+static isc_result_t
+ssu_checkrule(void *data, dns_rdataset_t *rrset) {
+ ssu_check_t *ssuinfo = data;
+ isc_boolean_t result;
+
+ /*
+ * If we're deleting all records, it's ok to delete RRSIG and NSEC even
+ * if we're normally not allowed to.
+ */
+ if (rrset->type == dns_rdatatype_rrsig ||
+ rrset->type == dns_rdatatype_nsec)
+ return (ISC_R_SUCCESS);
+ result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer,
+ ssuinfo->name, ssuinfo->tcpaddr,
+ rrset->type);
+ 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_result_t result;
+ ssu_check_t ssuinfo;
+
+ ssuinfo.name = name;
+ ssuinfo.table = ssutable;
+ ssuinfo.signer = signer;
+ ssuinfo.tcpaddr = tcpaddr;
+ result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo);
+ return (ISC_TF(result == ISC_R_SUCCESS));
+}
+
+/**************************************************************************/
+/*
+ * Checking of "RRset exists (value dependent)" prerequisites.
+ *
+ * In the RFC2136 section 3.2.5, this is the pseudocode involving
+ * a variable called "temp", a mapping of <name, type> tuples to rrsets.
+ *
+ * Here, we represent the "temp" data structure as (non-minimial) "dns_diff_t"
+ * where each typle has op==DNS_DIFFOP_EXISTS.
+ */
+
+
+/*%
+ * Append a tuple asserting the existence of the RR with
+ * 'name' and 'rdata' to 'diff'.
+ */
+static isc_result_t
+temp_append(dns_diff_t *diff, dns_name_t *name, dns_rdata_t *rdata) {
+ isc_result_t result;
+ dns_difftuple_t *tuple = NULL;
+
+ REQUIRE(DNS_DIFF_VALID(diff));
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_EXISTS,
+ name, 0, rdata, &tuple));
+ ISC_LIST_APPEND(diff->tuples, tuple, link);
+ failure:
+ return (result);
+}
+
+/*%
+ * Compare two rdatasets represented as sorted lists of tuples.
+ * All list elements must have the same owner name and type.
+ * Return ISC_R_SUCCESS if the rdatasets are equal, rcode(dns_rcode_nxrrset)
+ * if not.
+ */
+static isc_result_t
+temp_check_rrset(dns_difftuple_t *a, dns_difftuple_t *b) {
+ for (;;) {
+ if (a == NULL || b == NULL)
+ break;
+ INSIST(a->op == DNS_DIFFOP_EXISTS &&
+ 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)
+ return (DNS_R_NXRRSET);
+ a = ISC_LIST_NEXT(a, link);
+ b = ISC_LIST_NEXT(b, link);
+ }
+ if (a != NULL || b != NULL)
+ return (DNS_R_NXRRSET);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * A comparison function defining the sorting order for the entries
+ * in the "temp" data structure. The major sort key is the owner name,
+ * followed by the type and rdata.
+ */
+static int
+temp_order(const void *av, const void *bv) {
+ dns_difftuple_t const * const *ap = av;
+ dns_difftuple_t const * const *bp = bv;
+ dns_difftuple_t const *a = *ap;
+ dns_difftuple_t const *b = *bp;
+ int r;
+ r = dns_name_compare(&a->name, &b->name);
+ if (r != 0)
+ return (r);
+ r = (b->rdata.type - a->rdata.type);
+ if (r != 0)
+ return (r);
+ r = dns_rdata_compare(&a->rdata, &b->rdata);
+ return (r);
+}
+
+/*%
+ * Check the "RRset exists (value dependent)" prerequisite information
+ * in 'temp' against the contents of the database 'db'.
+ *
+ * Return ISC_R_SUCCESS if the prerequisites are satisfied,
+ * rcode(dns_rcode_nxrrset) if not.
+ *
+ * 'temp' must be pre-sorted.
+ */
+
+static isc_result_t
+temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db,
+ dns_dbversion_t *ver, dns_name_t *tmpname, dns_rdatatype_t *typep)
+{
+ isc_result_t result;
+ dns_name_t *name;
+ dns_dbnode_t *node;
+ dns_difftuple_t *t;
+ dns_diff_t trash;
+
+ dns_diff_init(mctx, &trash);
+
+ /*
+ * For each name and type in the prerequisites,
+ * construct a sorted rdata list of the corresponding
+ * database contents, and compare the lists.
+ */
+ t = ISC_LIST_HEAD(temp->tuples);
+ while (t != NULL) {
+ name = &t->name;
+ (void)dns_name_copy(name, tmpname, NULL);
+ *typep = t->rdata.type;
+
+ /* A new unique name begins here. */
+ node = NULL;
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND) {
+ dns_diff_clear(&trash);
+ return (DNS_R_NXRRSET);
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_diff_clear(&trash);
+ return (result);
+ }
+
+ /* A new unique type begins here. */
+ while (t != NULL && dns_name_equal(&t->name, name)) {
+ dns_rdatatype_t type, covers;
+ dns_rdataset_t rdataset;
+ dns_diff_t d_rrs; /* Database RRs with
+ this name and type */
+ dns_diff_t u_rrs; /* Update RRs with
+ this name and type */
+
+ *typep = type = t->rdata.type;
+ if (type == dns_rdatatype_rrsig ||
+ type == dns_rdatatype_sig)
+ covers = dns_rdata_covers(&t->rdata);
+ else
+ covers = 0;
+
+ /*
+ * Collect all database RRs for this name and type
+ * onto d_rrs and sort them.
+ */
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, type,
+ covers, (isc_stdtime_t) 0,
+ &rdataset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(db, &node);
+ dns_diff_clear(&trash);
+ return (DNS_R_NXRRSET);
+ }
+
+ dns_diff_init(mctx, &d_rrs);
+ dns_diff_init(mctx, &u_rrs);
+
+ 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 = temp_append(&d_rrs, name, &rdata);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ result = dns_diff_sort(&d_rrs, temp_order);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Collect all update RRs for this name and type
+ * onto u_rrs. No need to sort them here -
+ * they are already sorted.
+ */
+ while (t != NULL &&
+ dns_name_equal(&t->name, name) &&
+ t->rdata.type == type)
+ {
+ dns_difftuple_t *next =
+ ISC_LIST_NEXT(t, link);
+ ISC_LIST_UNLINK(temp->tuples, t, link);
+ ISC_LIST_APPEND(u_rrs.tuples, t, link);
+ t = next;
+ }
+
+ /* Compare the two sorted lists. */
+ result = temp_check_rrset(ISC_LIST_HEAD(u_rrs.tuples),
+ ISC_LIST_HEAD(d_rrs.tuples));
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * We are done with the tuples, but we can't free
+ * them yet because "name" still points into one
+ * of them. Move them on a temporary list.
+ */
+ ISC_LIST_APPENDLIST(trash.tuples, u_rrs.tuples, link);
+ ISC_LIST_APPENDLIST(trash.tuples, d_rrs.tuples, link);
+ dns_rdataset_disassociate(&rdataset);
+
+ continue;
+
+ failure:
+ dns_diff_clear(&d_rrs);
+ dns_diff_clear(&u_rrs);
+ dns_diff_clear(&trash);
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+ return (result);
+ }
+
+ dns_db_detachnode(db, &node);
+ }
+
+ dns_diff_clear(&trash);
+ return (ISC_R_SUCCESS);
+}
+
+/**************************************************************************/
+/*
+ * Conditional deletion of RRs.
+ */
+
+/*%
+ * Context structure for delete_if().
+ */
+
+typedef struct {
+ rr_predicate *predicate;
+ dns_db_t *db;
+ dns_dbversion_t *ver;
+ dns_diff_t *diff;
+ dns_name_t *name;
+ dns_rdata_t *update_rr;
+} conditional_delete_ctx_t;
+
+/*%
+ * Predicate functions for delete_if().
+ */
+
+/*%
+ * Return true iff 'db_rr' is neither a SOA nor an NS RR nor
+ * an RRSIG nor an NSEC3PARAM nor a NSEC.
+ */
+static isc_boolean_t
+type_not_soa_nor_ns_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ UNUSED(update_rr);
+ return ((db_rr->type != dns_rdatatype_soa &&
+ db_rr->type != dns_rdatatype_ns &&
+ db_rr->type != dns_rdatatype_nsec3param &&
+ db_rr->type != dns_rdatatype_rrsig &&
+ db_rr->type != dns_rdatatype_nsec) ?
+ ISC_TRUE : ISC_FALSE);
+}
+
+/*%
+ * Return true iff 'db_rr' is neither a RRSIG nor a NSEC.
+ */
+static isc_boolean_t
+type_not_dnssec(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ UNUSED(update_rr);
+ return ((db_rr->type != dns_rdatatype_rrsig &&
+ db_rr->type != dns_rdatatype_nsec) ?
+ ISC_TRUE : ISC_FALSE);
+}
+
+/*%
+ * Return true always.
+ */
+static isc_boolean_t
+true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ UNUSED(update_rr);
+ UNUSED(db_rr);
+ return (ISC_TRUE);
+}
+
+/*%
+ * Return true if the record is a RRSIG.
+ */
+static isc_boolean_t
+rrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ UNUSED(update_rr);
+ return ((db_rr->type == dns_rdatatype_rrsig) ?
+ ISC_TRUE : ISC_FALSE);
+}
+
+/*%
+ * Return true iff the two RRs have identical rdata.
+ */
+static isc_boolean_t
+rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ /*
+ * XXXRTH This is not a problem, but we should consider creating
+ * 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 ?
+ ISC_TRUE : ISC_FALSE);
+}
+
+/*%
+ * Return true iff 'update_rr' should replace 'db_rr' according
+ * to the special RFC2136 rules for CNAME, SOA, and WKS records.
+ *
+ * RFC2136 does not mention NSEC or DNAME, but multiple NSECs or DNAMEs
+ * make little sense, so we replace those, too.
+ *
+ * Additionally replace RRSIG that have been generated by the same key
+ * for the same type. This simplifies refreshing a offline KSK by not
+ * requiring that the old RRSIG be deleted. It also simpifies key
+ * rollover by only requiring that the new RRSIG be added.
+ */
+static isc_boolean_t
+replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
+ dns_rdata_rrsig_t updatesig, dbsig;
+ isc_result_t result;
+
+ if (db_rr->type != update_rr->type)
+ return (ISC_FALSE);
+ if (db_rr->type == dns_rdatatype_cname)
+ return (ISC_TRUE);
+ if (db_rr->type == dns_rdatatype_dname)
+ return (ISC_TRUE);
+ if (db_rr->type == dns_rdatatype_soa)
+ return (ISC_TRUE);
+ if (db_rr->type == dns_rdatatype_nsec)
+ return (ISC_TRUE);
+ if (db_rr->type == dns_rdatatype_rrsig) {
+ /*
+ * Replace existing RRSIG with the same keyid,
+ * covered and algorithm.
+ */
+ result = dns_rdata_tostruct(db_rr, &dbsig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = dns_rdata_tostruct(update_rr, &updatesig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (dbsig.keyid == updatesig.keyid &&
+ dbsig.covered == updatesig.covered &&
+ dbsig.algorithm == updatesig.algorithm)
+ return (ISC_TRUE);
+ }
+ if (db_rr->type == dns_rdatatype_wks) {
+ /*
+ * Compare the address and protocol fields only. These
+ * form the first five bytes of the RR data. Do a
+ * raw binary comparison; unpacking the WKS RRs using
+ * dns_rdata_tostruct() might be cleaner in some ways.
+ */
+ INSIST(db_rr->length >= 5 && update_rr->length >= 5);
+ return (memcmp(db_rr->data, update_rr->data, 5) == 0 ?
+ ISC_TRUE : ISC_FALSE);
+ }
+
+ if (db_rr->type == dns_rdatatype_nsec3param) {
+ if (db_rr->length != update_rr->length)
+ return (ISC_FALSE);
+ INSIST(db_rr->length >= 4 && update_rr->length >= 4);
+ /*
+ * Replace records added in this UPDATE request.
+ */
+ 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);
+ }
+ return (ISC_FALSE);
+}
+
+/*%
+ * Internal helper function for delete_if().
+ */
+static isc_result_t
+delete_if_action(void *data, rr_t *rr) {
+ conditional_delete_ctx_t *ctx = data;
+ if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) {
+ isc_result_t result;
+ result = update_one_rr(ctx->db, ctx->ver, ctx->diff,
+ DNS_DIFFOP_DEL, ctx->name,
+ rr->ttl, &rr->rdata);
+ return (result);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+}
+
+/*%
+ * Conditionally delete RRs. Apply 'predicate' to the RRs
+ * specified by 'db', 'ver', 'name', and 'type' (which can
+ * be dns_rdatatype_any to match any type). Delete those
+ * RRs for which the predicate returns true, and log the
+ * deletions in 'diff'.
+ */
+static isc_result_t
+delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver,
+ dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
+ dns_rdata_t *update_rr, dns_diff_t *diff)
+{
+ conditional_delete_ctx_t ctx;
+ ctx.predicate = predicate;
+ ctx.db = db;
+ ctx.ver = ver;
+ ctx.diff = diff;
+ ctx.name = name;
+ ctx.update_rr = update_rr;
+ return (foreach_rr(db, ver, name, type, covers,
+ delete_if_action, &ctx));
+}
+
+/**************************************************************************/
+/*%
+ * Prepare an RR for the addition of the new RR 'ctx->update_rr',
+ * with TTL 'ctx->update_rr_ttl', to its rdataset, by deleting
+ * the RRs if it is replaced by the new RR or has a conflicting TTL.
+ * The necessary changes are appended to ctx->del_diff and ctx->add_diff;
+ * we need to do all deletions before any additions so that we don't run
+ * into transient states with conflicting TTLs.
+ */
+
+typedef struct {
+ dns_db_t *db;
+ dns_dbversion_t *ver;
+ dns_diff_t *diff;
+ dns_name_t *name;
+ dns_rdata_t *update_rr;
+ dns_ttl_t update_rr_ttl;
+ isc_boolean_t ignore_add;
+ dns_diff_t del_diff;
+ dns_diff_t add_diff;
+} add_rr_prepare_ctx_t;
+
+static isc_result_t
+add_rr_prepare_action(void *data, rr_t *rr) {
+ isc_result_t result = ISC_R_SUCCESS;
+ add_rr_prepare_ctx_t *ctx = data;
+ dns_difftuple_t *tuple = NULL;
+ isc_boolean_t equal;
+
+ /*
+ * 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);
+ if (equal && rr->ttl == ctx->update_rr_ttl) {
+ ctx->ignore_add = ISC_TRUE;
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * If this RR is "equal" to the update RR, it should
+ * be deleted before the update RR is added.
+ */
+ if (replaces_p(ctx->update_rr, &rr->rdata)) {
+ CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL,
+ ctx->name, rr->ttl, &rr->rdata,
+ &tuple));
+ dns_diff_append(&ctx->del_diff, &tuple);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * If this RR differs in TTL from the update RR,
+ * its TTL must be adjusted.
+ */
+ if (rr->ttl != ctx->update_rr_ttl) {
+ CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL,
+ ctx->name, rr->ttl, &rr->rdata,
+ &tuple));
+ dns_diff_append(&ctx->del_diff, &tuple);
+ if (!equal) {
+ CHECK(dns_difftuple_create(ctx->add_diff.mctx,
+ DNS_DIFFOP_ADD, ctx->name,
+ ctx->update_rr_ttl,
+ &rr->rdata, &tuple));
+ dns_diff_append(&ctx->add_diff, &tuple);
+ }
+ }
+ failure:
+ return (result);
+}
+
+/**************************************************************************/
+/*
+ * Miscellaneous subroutines.
+ */
+
+/*%
+ * Extract a single update RR from 'section' of dynamic update message
+ * 'msg', with consistency checking.
+ *
+ * Stores the owner name, rdata, and TTL of the update RR at 'name',
+ * 'rdata', and 'ttl', respectively.
+ */
+static void
+get_current_rr(dns_message_t *msg, dns_section_t section,
+ dns_rdataclass_t zoneclass, dns_name_t **name,
+ dns_rdata_t *rdata, dns_rdatatype_t *covers,
+ dns_ttl_t *ttl, dns_rdataclass_t *update_class)
+{
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+ dns_message_currentname(msg, section, name);
+ rdataset = ISC_LIST_HEAD((*name)->list);
+ INSIST(rdataset != NULL);
+ INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);
+ *covers = rdataset->covers;
+ *ttl = rdataset->ttl;
+ result = dns_rdataset_first(rdataset);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdataset_current(rdataset, rdata);
+ INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE);
+ *update_class = rdata->rdclass;
+ rdata->rdclass = zoneclass;
+}
+
+/*%
+ * Increment the SOA serial number of database 'db', version 'ver'.
+ * Replace the SOA record in the database, and log the
+ * change in 'diff'.
+ */
+
+ /*
+ * XXXRTH Failures in this routine will be worth logging, when
+ * we have a logging system. Failure to find the zonename
+ * or the SOA rdataset warrant at least an UNEXPECTED_ERROR().
+ */
+
+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;
+
+ CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
+ CHECK(dns_difftuple_copy(deltuple, &addtuple));
+ addtuple->op = DNS_DIFFOP_ADD;
+
+ serial = dns_soa_getserial(&addtuple->rdata);
+
+ /* 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;
+
+ failure:
+ if (addtuple != NULL)
+ dns_difftuple_free(&addtuple);
+ if (deltuple != NULL)
+ dns_difftuple_free(&deltuple);
+ return (result);
+}
+
+/*%
+ * Check that the new SOA record at 'update_rdata' does not
+ * illegally cause the SOA serial number to decrease or stay
+ * unchanged relative to the existing SOA in 'db'.
+ *
+ * Sets '*ok' to ISC_TRUE if the update is legal, ISC_FALSE if not.
+ *
+ * William King points out that RFC2136 is inconsistent about
+ * the case where the serial number stays unchanged:
+ *
+ * section 3.4.2.2 requires a server to ignore a SOA update request
+ * if the serial number on the update SOA is less_than_or_equal to
+ * the zone SOA serial.
+ *
+ * section 3.6 requires a server to ignore a SOA update request if
+ * the serial is less_than the zone SOA serial.
+ *
+ * Paul says 3.4.2.2 is correct.
+ *
+ */
+static isc_result_t
+check_soa_increment(dns_db_t *db, dns_dbversion_t *ver,
+ dns_rdata_t *update_rdata, isc_boolean_t *ok)
+{
+ isc_uint32_t db_serial;
+ isc_uint32_t update_serial;
+ isc_result_t result;
+
+ update_serial = dns_soa_getserial(update_rdata);
+
+ result = dns_db_getsoaserial(db, ver, &db_serial);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (DNS_SERIAL_GE(db_serial, update_serial)) {
+ *ok = ISC_FALSE;
+ } else {
+ *ok = ISC_TRUE;
+ }
+
+ return (ISC_R_SUCCESS);
+
+}
+
+/**************************************************************************/
+/*
+ * Incremental updating of NSECs and RRSIGs.
+ */
+
+#define MAXZONEKEYS 32 /*%< Maximum number of zone keys supported. */
+
+/*%
+ * We abuse the dns_diff_t type to represent a set of domain names
+ * affected by the update.
+ */
+static isc_result_t
+namelist_append_name(dns_diff_t *list, dns_name_t *name) {
+ isc_result_t result;
+ dns_difftuple_t *tuple = NULL;
+ static dns_rdata_t dummy_rdata = DNS_RDATA_INIT;
+
+ CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0,
+ &dummy_rdata, &tuple));
+ dns_diff_append(list, &tuple);
+ failure:
+ return (result);
+}
+
+static isc_result_t
+namelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected)
+{
+ isc_result_t result;
+ dns_fixedname_t fixedname;
+ dns_name_t *child;
+ dns_dbiterator_t *dbit = NULL;
+
+ dns_fixedname_init(&fixedname);
+ child = dns_fixedname_name(&fixedname);
+
+ CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
+
+ for (result = dns_dbiterator_seek(dbit, name);
+ result == ISC_R_SUCCESS;
+ result = dns_dbiterator_next(dbit))
+ {
+ dns_dbnode_t *node = NULL;
+ CHECK(dns_dbiterator_current(dbit, &node, child));
+ dns_db_detachnode(db, &node);
+ if (! dns_name_issubdomain(child, name))
+ break;
+ CHECK(namelist_append_name(affected, child));
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ failure:
+ if (dbit != NULL)
+ dns_dbiterator_destroy(&dbit);
+ return (result);
+}
+
+
+
+/*%
+ * Helper function for non_nsec_rrset_exists().
+ */
+static isc_result_t
+is_non_nsec_action(void *data, dns_rdataset_t *rrset) {
+ UNUSED(data);
+ if (!(rrset->type == dns_rdatatype_nsec ||
+ rrset->type == dns_rdatatype_nsec3 ||
+ (rrset->type == dns_rdatatype_rrsig &&
+ (rrset->covers == dns_rdatatype_nsec ||
+ rrset->covers == dns_rdatatype_nsec3))))
+ return (ISC_R_EXISTS);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Check whether there is an rrset other than a NSEC or RRSIG NSEC,
+ * i.e., anything that justifies the continued existence of a name
+ * after a secure update.
+ *
+ * If such an rrset exists, set '*exists' to ISC_TRUE.
+ * Otherwise, set it to ISC_FALSE.
+ */
+static isc_result_t
+non_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver,
+ dns_name_t *name, isc_boolean_t *exists)
+{
+ isc_result_t result;
+ result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL);
+ RETURN_EXISTENCE_FLAG;
+}
+
+/*%
+ * A comparison function for sorting dns_diff_t:s by name.
+ */
+static int
+name_order(const void *av, const void *bv) {
+ dns_difftuple_t const * const *ap = av;
+ dns_difftuple_t const * const *bp = bv;
+ dns_difftuple_t const *a = *ap;
+ dns_difftuple_t const *b = *bp;
+ return (dns_name_compare(&a->name, &b->name));
+}
+
+static isc_result_t
+uniqify_name_list(dns_diff_t *list) {
+ isc_result_t result;
+ dns_difftuple_t *p, *q;
+
+ CHECK(dns_diff_sort(list, name_order));
+
+ p = ISC_LIST_HEAD(list->tuples);
+ while (p != NULL) {
+ do {
+ q = ISC_LIST_NEXT(p, link);
+ if (q == NULL || ! dns_name_equal(&p->name, &q->name))
+ break;
+ ISC_LIST_UNLINK(list->tuples, q, link);
+ dns_difftuple_free(&q);
+ } while (1);
+ p = ISC_LIST_NEXT(p, link);
+ }
+ failure:
+ return (result);
+}
+
+static isc_result_t
+is_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ isc_boolean_t *flag, isc_boolean_t *cut, isc_boolean_t *unsecure)
+{
+ isc_result_t result;
+ dns_fixedname_t foundname;
+ dns_fixedname_init(&foundname);
+ result = dns_db_find(db, name, ver, dns_rdatatype_any,
+ DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
+ (isc_stdtime_t) 0, NULL,
+ dns_fixedname_name(&foundname),
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) {
+ *flag = ISC_TRUE;
+ *cut = ISC_FALSE;
+ if (unsecure != NULL)
+ *unsecure = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+ } else if (result == DNS_R_ZONECUT) {
+ *flag = ISC_TRUE;
+ *cut = ISC_TRUE;
+ if (unsecure != NULL) {
+ /*
+ * We are at the zonecut. Check to see if there
+ * is a DS RRset.
+ */
+ if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0,
+ (isc_stdtime_t) 0, NULL,
+ dns_fixedname_name(&foundname),
+ NULL, NULL) == DNS_R_NXRRSET)
+ *unsecure = ISC_TRUE;
+ else
+ *unsecure = ISC_FALSE;
+ }
+ return (ISC_R_SUCCESS);
+ } else if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
+ result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
+ *flag = ISC_FALSE;
+ *cut = ISC_FALSE;
+ if (unsecure != NULL)
+ *unsecure = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+ } else {
+ /*
+ * Silence compiler.
+ */
+ *flag = ISC_FALSE;
+ *cut = ISC_FALSE;
+ if (unsecure != NULL)
+ *unsecure = ISC_FALSE;
+ return (result);
+ }
+}
+
+/*%
+ * Find the next/previous name that has a NSEC record.
+ * In other words, skip empty database nodes and names that
+ * have had their NSECs removed because they are obscured by
+ * a zone cut.
+ */
+static isc_result_t
+next_active(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
+ dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname,
+ isc_boolean_t forward)
+{
+ isc_result_t result;
+ dns_dbiterator_t *dbit = NULL;
+ isc_boolean_t has_nsec;
+ unsigned int wraps = 0;
+ isc_boolean_t secure = dns_db_issecure(db);
+
+ CHECK(dns_db_createiterator(db, 0, &dbit));
+
+ CHECK(dns_dbiterator_seek(dbit, oldname));
+ do {
+ dns_dbnode_t *node = NULL;
+
+ if (forward)
+ result = dns_dbiterator_next(dbit);
+ else
+ result = dns_dbiterator_prev(dbit);
+ if (result == ISC_R_NOMORE) {
+ /*
+ * Wrap around.
+ */
+ if (forward)
+ CHECK(dns_dbiterator_first(dbit));
+ else
+ CHECK(dns_dbiterator_last(dbit));
+ wraps++;
+ if (wraps == 2) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "secure zone with no NSECs");
+ result = DNS_R_BADZONE;
+ goto failure;
+ }
+ }
+ CHECK(dns_dbiterator_current(dbit, &node, newname));
+ dns_db_detachnode(db, &node);
+
+ /*
+ * The iterator may hold the tree lock, and
+ * rrset_exists() calls dns_db_findnode() which
+ * may try to reacquire it. To avoid deadlock
+ * we must pause the iterator first.
+ */
+ CHECK(dns_dbiterator_pause(dbit));
+ if (secure) {
+ CHECK(rrset_exists(db, ver, newname,
+ dns_rdatatype_nsec, 0, &has_nsec));
+ } else {
+ dns_fixedname_t ffound;
+ dns_name_t *found;
+ dns_fixedname_init(&ffound);
+ found = dns_fixedname_name(&ffound);
+ result = dns_db_find(db, newname, ver,
+ dns_rdatatype_soa,
+ DNS_DBFIND_NOWILD, 0, NULL, found,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS ||
+ result == DNS_R_EMPTYNAME ||
+ result == DNS_R_NXRRSET ||
+ result == DNS_R_CNAME ||
+ (result == DNS_R_DELEGATION &&
+ dns_name_equal(newname, found))) {
+ has_nsec = ISC_TRUE;
+ result = ISC_R_SUCCESS;
+ } else if (result != DNS_R_NXDOMAIN)
+ break;
+ }
+ } while (! has_nsec);
+ failure:
+ if (dbit != NULL)
+ dns_dbiterator_destroy(&dbit);
+
+ 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.
+ */
+static isc_result_t
+add_nsec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
+ dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl,
+ dns_diff_t *diff)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ unsigned char buffer[DNS_NSEC_BUFFERSIZE];
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_difftuple_t *tuple = NULL;
+ dns_fixedname_t fixedname;
+ dns_name_t *target;
+
+ dns_fixedname_init(&fixedname);
+ target = dns_fixedname_name(&fixedname);
+
+ /*
+ * Find the successor name, aka NSEC target.
+ */
+ CHECK(next_active(client, zone, db, ver, name, target, ISC_TRUE));
+
+ /*
+ * Create the NSEC RDATA.
+ */
+ 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, &region);
+ dns_name_fromregion(&next, &region);
+ isc_region_consume(&region, 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);
+
+ /*
+ * Delete the old NSEC and record the change.
+ */
+ CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0,
+ NULL, diff));
+ /*
+ * Add the new NSEC and record the change.
+ */
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
+ nsecttl, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, ver, diff));
+ INSIST(tuple == NULL);
+
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+/*%
+ * Add a placeholder NSEC record for "name", recording the change in "diff".
+ */
+static isc_result_t
+add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_diff_t *diff)
+{
+ isc_result_t result;
+ dns_difftuple_t *tuple = NULL;
+ isc_region_t r;
+ unsigned char data[1] = { 0 }; /* The root domain, no bits. */
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ r.base = data;
+ r.length = sizeof(data);
+ dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r);
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0,
+ &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, ver, diff));
+ failure:
+ return (result);
+}
+
+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));
+ CHECK(dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
+ directory, mctx, maxkeys, keys, nkeys));
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ 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".
+ */
+static isc_result_t
+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_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t sig_rdata = DNS_RDATA_INIT;
+ isc_buffer_t buffer;
+ unsigned char data[1024]; /* XXX */
+ unsigned int i;
+ isc_boolean_t added_sig = ISC_FALSE;
+ isc_mem_t *mctx = client->mctx;
+
+ dns_rdataset_init(&rdataset);
+ isc_buffer_init(&buffer, data, sizeof(data));
+
+ /* Get the rdataset to sign. */
+ if (type == dns_rdatatype_nsec3)
+ CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
+ else
+ CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
+ CHECK(dns_db_findrdataset(db, node, ver, type, 0,
+ (isc_stdtime_t) 0, &rdataset, NULL));
+ dns_db_detachnode(db, &node);
+
+ for (i = 0; i < nkeys; i++) {
+
+ if (check_ksk && type != dns_rdatatype_dnskey &&
+ (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0)
+ continue;
+
+ if (!dst_key_isprivate(keys[i]))
+ continue;
+
+ /* Calculate the signature, creating a RRSIG RDATA. */
+ CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
+ &inception, &expire,
+ mctx, &buffer, &sig_rdata));
+
+ /* Update the database and journal with the RRSIG. */
+ /* XXX inefficient - will cause dataset merging */
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
+ rdataset.ttl, &sig_rdata));
+ dns_rdata_reset(&sig_rdata);
+ added_sig = ISC_TRUE;
+ }
+ if (!added_sig) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "found no private keys, "
+ "unable to generate any signatures");
+ result = ISC_R_NOTFOUND;
+ }
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+/*
+ * Delete expired RRsigs and any RRsigs we are about to re-sign.
+ * See also zone.c:del_sigs().
+ */
+static isc_result_t
+del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
+ dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int i;
+ dns_rdata_rrsig_t rrsig;
+ isc_boolean_t found;
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig,
+ dns_rdatatype_dnskey, (isc_stdtime_t) 0,
+ &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_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);
+ result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ found = ISC_FALSE;
+ for (i = 0; i < nkeys; i++) {
+ if (rrsig.keyid == dst_key_id(keys[i])) {
+ found = ISC_TRUE;
+ if (!dst_key_isprivate(keys[i])) {
+ /*
+ * The re-signing code in zone.c
+ * will mark this as offline.
+ * Just skip the record for now.
+ */
+ break;
+ }
+ result = update_one_rr(db, ver, diff,
+ DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata);
+ break;
+ }
+ }
+ /*
+ * If there is not a matching DNSKEY then delete the RRSIG.
+ */
+ if (!found)
+ result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
+ name, rdataset.ttl, &rdata);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+static isc_result_t
+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_result_t result;
+ dns_dbnode_t *node;
+ dns_rdatasetiter_t *iter;
+
+ node = NULL;
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ iter = NULL;
+ result = dns_db_allrdatasets(db, node, ver,
+ (isc_stdtime_t) 0, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ for (result = dns_rdatasetiter_first(iter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iter))
+ {
+ dns_rdataset_t rdataset;
+ dns_rdatatype_t type;
+ isc_boolean_t flag;
+
+ dns_rdataset_init(&rdataset);
+ dns_rdatasetiter_current(iter, &rdataset);
+ type = rdataset.type;
+ dns_rdataset_disassociate(&rdataset);
+
+ /*
+ * We don't need to sign unsigned NSEC records at the cut
+ * as they are handled elsewhere.
+ */
+ if ((type == dns_rdatatype_rrsig) ||
+ (cut && type != dns_rdatatype_ds))
+ continue;
+ result = rrset_exists(db, ver, name, dns_rdatatype_rrsig,
+ type, &flag);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_iterator;
+ if (flag)
+ continue;;
+ result = add_sigs(client, zone, db, ver, name, type, diff,
+ keys, nkeys, inception, expire, check_ksk);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_iterator;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ cleanup_iterator:
+ dns_rdatasetiter_destroy(&iter);
+
+ cleanup_node:
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+/*%
+ * Update RRSIG, NSEC and NSEC3 records affected by an update. The original
+ * update, including the SOA serial update but exluding the RRSIG & NSEC
+ * changes, is in "diff" and has already been applied to "newver" of "db".
+ * The database version prior to the update is "oldver".
+ *
+ * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver"
+ * and added (as a minimal diff) to "diff".
+ *
+ * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds.
+ */
+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)
+{
+ isc_result_t result;
+ dns_difftuple_t *t;
+ dns_diff_t diffnames;
+ dns_diff_t affected;
+ dns_diff_t sig_diff;
+ dns_diff_t nsec_diff;
+ dns_diff_t nsec_mindiff;
+ isc_boolean_t flag;
+ dst_key_t *zone_keys[MAXZONEKEYS];
+ unsigned int nkeys = 0;
+ unsigned int i;
+ isc_stdtime_t now, inception, expire;
+ dns_ttl_t nsecttl;
+ dns_rdata_soa_t soa;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ dns_dbnode_t *node = NULL;
+ isc_boolean_t check_ksk;
+ isc_boolean_t unsecure;
+ isc_boolean_t cut;
+
+ dns_diff_init(client->mctx, &diffnames);
+ dns_diff_init(client->mctx, &affected);
+
+ dns_diff_init(client->mctx, &sig_diff);
+ sig_diff.resign = dns_zone_getsigresigninginterval(zone);
+ dns_diff_init(client->mctx, &nsec_diff);
+ dns_diff_init(client->mctx, &nsec_mindiff);
+
+ result = find_zone_keys(zone, db, newver, client->mctx,
+ MAXZONEKEYS, zone_keys, &nkeys);
+ if (result != ISC_R_SUCCESS) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "could not get zone keys for secure dynamic update");
+ goto failure;
+ }
+
+ isc_stdtime_get(&now);
+ inception = now - 3600; /* Allow for some clock skew. */
+ expire = now + sigvalidityinterval;
+
+ /*
+ * Do we look at the KSK flag on the DNSKEY to determining which
+ * keys sign which RRsets? First check the zone option then
+ * check the keys flags to make sure atleast one has a ksk set
+ * and one doesn't.
+ */
+ 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;
+
+ /*
+ * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field.
+ */
+ CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
+ dns_rdataset_init(&rdataset);
+ CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa, 0,
+ (isc_stdtime_t) 0, &rdataset, NULL));
+ CHECK(dns_rdataset_first(&rdataset));
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
+ nsecttl = soa.minimum;
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+
+ /*
+ * Find all RRsets directly affected by the update, and
+ * update their RRSIGs. Also build a list of names affected
+ * by the update in "diffnames".
+ */
+ CHECK(dns_diff_sort(diff, temp_order));
+
+ t = ISC_LIST_HEAD(diff->tuples);
+ while (t != NULL) {
+ dns_name_t *name = &t->name;
+ /* Now "name" is a new, unique name affected by the update. */
+
+ CHECK(namelist_append_name(&diffnames, name));
+
+ while (t != NULL && dns_name_equal(&t->name, name)) {
+ dns_rdatatype_t type;
+ type = t->rdata.type;
+
+ /*
+ * Now "name" and "type" denote a new unique RRset
+ * affected by the update.
+ */
+
+ /* Don't sign RRSIGs. */
+ if (type == dns_rdatatype_rrsig)
+ goto skip;
+
+ /*
+ * Delete all old RRSIGs covering this type, since they
+ * are all invalid when the signed RRset has changed.
+ * We may not be able to recreate all of them - tough.
+ * Special case changes to the zone's DNSKEY records
+ * to support offline KSKs.
+ */
+ if (type == dns_rdatatype_dnskey)
+ del_keysigs(db, newver, name, &sig_diff,
+ zone_keys, nkeys);
+ else
+ CHECK(delete_if(true_p, db, newver, name,
+ dns_rdatatype_rrsig, type,
+ NULL, &sig_diff));
+
+ /*
+ * If this RRset is still visible after the update,
+ * add a new signature for it.
+ */
+ CHECK(rrset_visible(db, newver, name, type, &flag));
+ if (flag) {
+ CHECK(add_sigs(client, zone, db, newver, name,
+ type, &sig_diff, zone_keys,
+ nkeys, inception, expire,
+ check_ksk));
+ }
+ skip:
+ /* Skip any other updates to the same RRset. */
+ while (t != NULL &&
+ dns_name_equal(&t->name, name) &&
+ t->rdata.type == type)
+ {
+ t = ISC_LIST_NEXT(t, link);
+ }
+ }
+ }
+ update_log(client, zone, ISC_LOG_DEBUG(3), "updated data signatures");
+
+ /* Remove orphaned NSECs and RRSIG NSECs. */
+ for (t = ISC_LIST_HEAD(diffnames.tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link))
+ {
+ CHECK(non_nsec_rrset_exists(db, newver, &t->name, &flag));
+ if (! flag) {
+ CHECK(delete_if(true_p, db, newver, &t->name,
+ dns_rdatatype_any, 0,
+ NULL, &sig_diff));
+ }
+ }
+ update_log(client, zone, ISC_LOG_DEBUG(3),
+ "removed any orphaned NSEC records");
+
+ /*
+ * If we don't have a NSEC record at the origin then we need to
+ * update the NSEC3 records.
+ */
+ CHECK(rrset_exists(db, newver, dns_db_origin(db), dns_rdatatype_nsec,
+ 0, &flag));
+ if (!flag)
+ goto update_nsec3;
+
+ update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC chain");
+
+ /*
+ * When a name is created or deleted, its predecessor needs to
+ * have its NSEC updated.
+ */
+ for (t = ISC_LIST_HEAD(diffnames.tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link))
+ {
+ isc_boolean_t existed, exists;
+ dns_fixedname_t fixedname;
+ dns_name_t *prevname;
+
+ dns_fixedname_init(&fixedname);
+ prevname = dns_fixedname_name(&fixedname);
+
+ CHECK(name_exists(db, oldver, &t->name, &existed));
+ CHECK(name_exists(db, newver, &t->name, &exists));
+ if (exists == existed)
+ continue;
+
+ /*
+ * Find the predecessor.
+ * When names become obscured or unobscured in this update
+ * transaction, we may find the wrong predecessor because
+ * the NSECs have not yet been updated to reflect the delegation
+ * change. This should not matter because in this case,
+ * the correct predecessor is either the delegation node or
+ * a newly unobscured node, and those nodes are on the
+ * "affected" list in any case.
+ */
+ CHECK(next_active(client, zone, db, newver,
+ &t->name, prevname, ISC_FALSE));
+ CHECK(namelist_append_name(&affected, prevname));
+ }
+
+ /*
+ * Find names potentially affected by delegation changes
+ * (obscured by adding an NS or DNAME, or unobscured by
+ * removing one).
+ */
+ for (t = ISC_LIST_HEAD(diffnames.tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link))
+ {
+ isc_boolean_t ns_existed, dname_existed;
+ isc_boolean_t ns_exists, dname_exists;
+
+ CHECK(rrset_exists(db, oldver, &t->name, dns_rdatatype_ns, 0,
+ &ns_existed));
+ CHECK(rrset_exists(db, oldver, &t->name, dns_rdatatype_dname, 0,
+ &dname_existed));
+ CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_ns, 0,
+ &ns_exists));
+ CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_dname, 0,
+ &dname_exists));
+ if ((ns_exists || dname_exists) == (ns_existed || dname_existed))
+ continue;
+ /*
+ * There was a delegation change. Mark all subdomains
+ * of t->name as potentially needing a NSEC update.
+ */
+ CHECK(namelist_append_subdomain(db, &t->name, &affected));
+ }
+
+ ISC_LIST_APPENDLIST(affected.tuples, diffnames.tuples, link);
+ INSIST(ISC_LIST_EMPTY(diffnames.tuples));
+
+ CHECK(uniqify_name_list(&affected));
+
+ /*
+ * Determine which names should have NSECs, and delete/create
+ * NSECs to make it so. We don't know the final NSEC targets yet,
+ * so we just create placeholder NSECs with arbitrary contents
+ * to indicate that their respective owner names should be part of
+ * the NSEC chain.
+ */
+ for (t = ISC_LIST_HEAD(affected.tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link))
+ {
+ isc_boolean_t exists;
+ dns_name_t *name = &t->name;
+
+ CHECK(name_exists(db, newver, name, &exists));
+ if (! exists)
+ continue;
+ CHECK(is_active(db, newver, name, &flag, &cut, NULL));
+ if (!flag) {
+ /*
+ * This name is obscured. Delete any
+ * existing NSEC record.
+ */
+ CHECK(delete_if(true_p, db, newver, name,
+ dns_rdatatype_nsec, 0,
+ NULL, &nsec_diff));
+ CHECK(delete_if(rrsig_p, db, newver, name,
+ dns_rdatatype_any, 0, NULL, diff));
+ } else {
+ /*
+ * This name is not obscured. It should have a NSEC.
+ */
+ 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));
+ }
+ }
+
+ /*
+ * Now we know which names are part of the NSEC chain.
+ * Make them all point at their correct targets.
+ */
+ for (t = ISC_LIST_HEAD(affected.tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link))
+ {
+ CHECK(rrset_exists(db, newver, &t->name,
+ dns_rdatatype_nsec, 0, &flag));
+ if (flag) {
+ /*
+ * There is a NSEC, but we don't know if it is correct.
+ * Delete it and create a correct one to be sure.
+ * If the update was unnecessary, the diff minimization
+ * will take care of eliminating it from the journal,
+ * IXFRs, etc.
+ *
+ * The RRSIG bit should always be set in the NSECs
+ * we generate, because they will all get RRSIG NSECs.
+ * (XXX what if the zone keys are missing?).
+ * Because the RRSIG NSECs have not necessarily been
+ * created yet, the correctness of the bit mask relies
+ * on the assumption that NSECs are only created if
+ * there is other data, and if there is other data,
+ * there are other RRSIGs.
+ */
+ CHECK(add_nsec(client, zone, db, newver, &t->name,
+ nsecttl, &nsec_diff));
+ }
+ }
+
+ /*
+ * Minimize the set of NSEC updates so that we don't
+ * have to regenerate the RRSIG NSECs for NSECs that were
+ * replaced with identical ones.
+ */
+ while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) {
+ ISC_LIST_UNLINK(nsec_diff.tuples, t, link);
+ dns_diff_appendminimal(&nsec_mindiff, &t);
+ }
+
+ update_log(client, zone, ISC_LOG_DEBUG(3),
+ "signing rebuilt NSEC chain");
+
+ /* Update RRSIG NSECs. */
+ for (t = ISC_LIST_HEAD(nsec_mindiff.tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link))
+ {
+ if (t->op == DNS_DIFFOP_DEL) {
+ CHECK(delete_if(true_p, db, newver, &t->name,
+ dns_rdatatype_rrsig, dns_rdatatype_nsec,
+ NULL, &sig_diff));
+ } else if (t->op == DNS_DIFFOP_ADD) {
+ CHECK(add_sigs(client, zone, db, newver, &t->name,
+ dns_rdatatype_nsec, &sig_diff,
+ zone_keys, nkeys, inception, expire,
+ check_ksk));
+ } else {
+ INSIST(0);
+ }
+ }
+
+ update_nsec3:
+
+ /* Record our changes for the journal. */
+ while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) {
+ ISC_LIST_UNLINK(sig_diff.tuples, t, link);
+ dns_diff_appendminimal(diff, &t);
+ }
+ while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) {
+ ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link);
+ dns_diff_appendminimal(diff, &t);
+ }
+
+ INSIST(ISC_LIST_EMPTY(sig_diff.tuples));
+ 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) {
+ update_log(client, zone, ISC_LOG_DEBUG(3),
+ "no NSEC3 chains to rebuild");
+ goto failure;
+ }
+
+ update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC3 chains");
+
+ dns_diff_clear(&diffnames);
+ dns_diff_clear(&affected);
+
+ CHECK(dns_diff_sort(diff, temp_order));
+
+ /*
+ * Find names potentially affected by delegation changes
+ * (obscured by adding an NS or DNAME, or unobscured by
+ * removing one).
+ */
+ t = ISC_LIST_HEAD(diff->tuples);
+ while (t != NULL) {
+ dns_name_t *name = &t->name;
+
+ isc_boolean_t ns_existed, dname_existed;
+ isc_boolean_t ns_exists, dname_exists;
+
+ if (t->rdata.type == dns_rdatatype_nsec ||
+ t->rdata.type == dns_rdatatype_rrsig) {
+ t = ISC_LIST_NEXT(t, link);
+ continue;
+ }
+
+ CHECK(namelist_append_name(&affected, name));
+
+ CHECK(rrset_exists(db, oldver, name, dns_rdatatype_ns, 0,
+ &ns_existed));
+ CHECK(rrset_exists(db, oldver, name, dns_rdatatype_dname, 0,
+ &dname_existed));
+ CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns, 0,
+ &ns_exists));
+ CHECK(rrset_exists(db, newver, name, dns_rdatatype_dname, 0,
+ &dname_exists));
+
+ if ((ns_exists || dname_exists) == (ns_existed || dname_existed))
+ goto nextname;
+ /*
+ * There was a delegation change. Mark all subdomains
+ * of t->name as potentially needing a NSEC3 update.
+ */
+ CHECK(namelist_append_subdomain(db, name, &affected));
+
+ nextname:
+ while (t != NULL && dns_name_equal(&t->name, name))
+ t = ISC_LIST_NEXT(t, link);
+ }
+
+ for (t = ISC_LIST_HEAD(affected.tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link)) {
+ dns_name_t *name = &t->name;
+
+ unsecure = ISC_FALSE; /* Silence compiler warning. */
+ CHECK(is_active(db, newver, name, &flag, &cut, &unsecure));
+
+ 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));
+ } 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));
+ }
+ }
+
+ /*
+ * Minimize the set of NSEC3 updates so that we don't
+ * have to regenerate the RRSIG NSEC3s for NSEC3s that were
+ * replaced with identical ones.
+ */
+ while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) {
+ ISC_LIST_UNLINK(nsec_diff.tuples, t, link);
+ dns_diff_appendminimal(&nsec_mindiff, &t);
+ }
+
+ update_log(client, zone, ISC_LOG_DEBUG(3),
+ "signing rebuilt NSEC3 chain");
+
+ /* Update RRSIG NSEC3s. */
+ for (t = ISC_LIST_HEAD(nsec_mindiff.tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link))
+ {
+ if (t->op == DNS_DIFFOP_DEL) {
+ CHECK(delete_if(true_p, db, newver, &t->name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_nsec3,
+ NULL, &sig_diff));
+ } else if (t->op == DNS_DIFFOP_ADD) {
+ CHECK(add_sigs(client, zone, db, newver, &t->name,
+ dns_rdatatype_nsec3,
+ &sig_diff, zone_keys, nkeys,
+ inception, expire, check_ksk));
+ } else {
+ INSIST(0);
+ }
+ }
+
+ /* Record our changes for the journal. */
+ while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) {
+ ISC_LIST_UNLINK(sig_diff.tuples, t, link);
+ dns_diff_appendminimal(diff, &t);
+ }
+ while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) {
+ ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link);
+ dns_diff_appendminimal(diff, &t);
+ }
+
+ INSIST(ISC_LIST_EMPTY(sig_diff.tuples));
+ INSIST(ISC_LIST_EMPTY(nsec_diff.tuples));
+ INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples));
+
+ failure:
+ dns_diff_clear(&sig_diff);
+ dns_diff_clear(&nsec_diff);
+ dns_diff_clear(&nsec_mindiff);
+
+ dns_diff_clear(&affected);
+ dns_diff_clear(&diffnames);
+
+ for (i = 0; i < nkeys; i++)
+ dst_key_free(&zone_keys[i]);
+
+ return (result);
+}
+
+
+/**************************************************************************/
+/*%
+ * The actual update code in all its glory. We try to follow
+ * the RFC2136 pseudocode as closely as possible.
+ */
+
+static isc_result_t
+send_update_event(ns_client_t *client, dns_zone_t *zone) {
+ isc_result_t result = ISC_R_SUCCESS;
+ update_event_t *event = NULL;
+ isc_task_t *zonetask = NULL;
+ ns_client_t *evclient;
+
+ event = (update_event_t *)
+ isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE,
+ update_action, NULL, sizeof(*event));
+ if (event == NULL)
+ FAIL(ISC_R_NOMEMORY);
+ event->zone = zone;
+ event->result = ISC_R_SUCCESS;
+
+ evclient = NULL;
+ ns_client_attach(client, &evclient);
+ INSIST(client->nupdates == 0);
+ client->nupdates++;
+ event->ev_arg = evclient;
+
+ dns_zone_gettask(zone, &zonetask);
+ isc_task_send(zonetask, ISC_EVENT_PTR(&event));
+
+ failure:
+ if (event != NULL)
+ isc_event_free(ISC_EVENT_PTR(&event));
+ return (result);
+}
+
+static void
+respond(ns_client_t *client, isc_result_t result) {
+ isc_result_t msg_result;
+
+ msg_result = dns_message_reply(client->message, ISC_TRUE);
+ if (msg_result != ISC_R_SUCCESS)
+ goto msg_failure;
+ client->message->rcode = dns_result_torcode(result);
+
+ ns_client_send(client);
+ return;
+
+ msg_failure:
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE,
+ ISC_LOG_ERROR,
+ "could not create update response message: %s",
+ isc_result_totext(msg_result));
+ ns_client_next(client, msg_result);
+}
+
+void
+ns_update_start(ns_client_t *client, isc_result_t sigresult) {
+ dns_message_t *request = client->message;
+ isc_result_t result;
+ dns_name_t *zonename;
+ dns_rdataset_t *zone_rdataset;
+ dns_zone_t *zone = NULL;
+
+ /*
+ * Interpret the zone section.
+ */
+ result = dns_message_firstname(request, DNS_SECTION_ZONE);
+ if (result != ISC_R_SUCCESS)
+ FAILC(DNS_R_FORMERR, "update zone section empty");
+
+ /*
+ * The zone section must contain exactly one "question", and
+ * it must be of type SOA.
+ */
+ zonename = NULL;
+ dns_message_currentname(request, DNS_SECTION_ZONE, &zonename);
+ zone_rdataset = ISC_LIST_HEAD(zonename->list);
+ if (zone_rdataset->type != dns_rdatatype_soa)
+ FAILC(DNS_R_FORMERR,
+ "update zone section contains non-SOA");
+ if (ISC_LIST_NEXT(zone_rdataset, link) != NULL)
+ FAILC(DNS_R_FORMERR,
+ "update zone section contains multiple RRs");
+
+ /* The zone section must have exactly one name. */
+ result = dns_message_nextname(request, DNS_SECTION_ZONE);
+ if (result != ISC_R_NOMORE)
+ FAILC(DNS_R_FORMERR,
+ "update zone section contains multiple RRs");
+
+ result = dns_zt_find(client->view->zonetable, zonename, 0, NULL,
+ &zone);
+ if (result != ISC_R_SUCCESS)
+ FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
+
+ switch(dns_zone_gettype(zone)) {
+ case dns_zone_master:
+ /*
+ * We can now fail due to a bad signature as we now know
+ * that we are the master.
+ */
+ if (sigresult != ISC_R_SUCCESS)
+ FAIL(sigresult);
+ CHECK(send_update_event(client, zone));
+ break;
+ case dns_zone_slave:
+ CHECK(checkupdateacl(client, dns_zone_getforwardacl(zone),
+ "update forwarding", zonename, ISC_TRUE,
+ ISC_FALSE));
+ CHECK(send_forward_event(client, zone));
+ break;
+ default:
+ FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
+ }
+ return;
+
+ failure:
+ if (result == DNS_R_REFUSED) {
+ INSIST(dns_zone_gettype(zone) == dns_zone_slave);
+ inc_stats(zone, dns_nsstatscounter_updaterej);
+ }
+ /*
+ * We failed without having sent an update event to the zone.
+ * We are still in the client task context, so we can
+ * simply give an error response without switching tasks.
+ */
+ respond(client, result);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+}
+
+/*%
+ * DS records are not allowed to exist without corresponding NS records,
+ * RFC 3658, 2.2 Protocol Change,
+ * "DS RRsets MUST NOT appear at non-delegation points or at a zone's apex".
+ */
+
+static isc_result_t
+remove_orphaned_ds(dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) {
+ isc_result_t result;
+ isc_boolean_t ns_exists;
+ dns_difftuple_t *t;
+
+ for (t = ISC_LIST_HEAD(diff->tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link)) {
+ if (!((t->op == DNS_DIFFOP_DEL &&
+ t->rdata.type == dns_rdatatype_ns) ||
+ (t->op == DNS_DIFFOP_ADD &&
+ t->rdata.type == dns_rdatatype_ds)))
+ continue;
+ CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_ns, 0,
+ &ns_exists));
+ if (ns_exists && !dns_name_equal(&t->name, dns_db_origin(db)))
+ continue;
+ CHECK(delete_if(true_p, db, newver, &t->name,
+ dns_rdatatype_ds, 0, NULL, diff));
+ }
+ return (ISC_R_SUCCESS);
+
+ failure:
+ return (result);
+}
+
+/*
+ * This implements the post load integrity checks for mx records.
+ */
+static isc_result_t
+check_mx(ns_client_t *client, dns_zone_t *zone,
+ dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff)
+{
+ char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123.")];
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char altbuf[DNS_NAME_FORMATSIZE];
+ dns_difftuple_t *t;
+ dns_fixedname_t fixed;
+ dns_name_t *foundname;
+ dns_rdata_mx_t mx;
+ dns_rdata_t rdata;
+ isc_boolean_t ok = ISC_TRUE;
+ isc_boolean_t isaddress;
+ isc_result_t result;
+ struct in6_addr addr6;
+ struct in_addr addr;
+ unsigned int options;
+
+ dns_fixedname_init(&fixed);
+ foundname = dns_fixedname_name(&fixed);
+ dns_rdata_init(&rdata);
+ options = dns_zone_getoptions(zone);
+
+ for (t = ISC_LIST_HEAD(diff->tuples);
+ t != NULL;
+ t = ISC_LIST_NEXT(t, link)) {
+ if (t->op != DNS_DIFFOP_ADD ||
+ t->rdata.type != dns_rdatatype_mx)
+ continue;
+
+ result = dns_rdata_tostruct(&t->rdata, &mx, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ /*
+ * Check if we will error out if we attempt to reload the
+ * zone.
+ */
+ dns_name_format(&mx.mx, namebuf, sizeof(namebuf));
+ dns_name_format(&t->name, ownerbuf, sizeof(ownerbuf));
+ isaddress = ISC_FALSE;
+ if ((options & DNS_RDATA_CHECKMX) != 0 &&
+ strlcpy(tmp, namebuf, sizeof(tmp)) < sizeof(tmp)) {
+ if (tmp[strlen(tmp) - 1] == '.')
+ tmp[strlen(tmp) - 1] = '\0';
+ if (inet_aton(tmp, &addr) == 1 ||
+ inet_pton(AF_INET6, tmp, &addr6) == 1)
+ isaddress = ISC_TRUE;
+ }
+
+ if (isaddress && (options & DNS_RDATA_CHECKMXFAIL) != 0) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "%s/MX: '%s': %s",
+ ownerbuf, namebuf,
+ dns_result_totext(DNS_R_MXISADDRESS));
+ ok = ISC_FALSE;
+ } else if (isaddress) {
+ update_log(client, zone, ISC_LOG_WARNING,
+ "%s/MX: warning: '%s': %s",
+ ownerbuf, namebuf,
+ dns_result_totext(DNS_R_MXISADDRESS));
+ }
+
+ /*
+ * Check zone integrity checks.
+ */
+ if ((options & DNS_ZONEOPT_CHECKINTEGRITY) == 0)
+ continue;
+ result = dns_db_find(db, &mx.mx, newver, dns_rdatatype_a,
+ 0, 0, NULL, foundname, NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ continue;
+
+ if (result == DNS_R_NXRRSET) {
+ result = dns_db_find(db, &mx.mx, newver,
+ dns_rdatatype_aaaa,
+ 0, 0, NULL, foundname,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ continue;
+ }
+
+ if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "%s/MX '%s' has no address records "
+ "(A or AAAA)", ownerbuf, namebuf);
+ ok = ISC_FALSE;
+ } else if (result == DNS_R_CNAME) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "%s/MX '%s' is a CNAME (illegal)",
+ ownerbuf, namebuf);
+ ok = ISC_FALSE;
+ } else if (result == DNS_R_DNAME) {
+ dns_name_format(foundname, altbuf, sizeof altbuf);
+ update_log(client, zone, ISC_LOG_ERROR,
+ "%s/MX '%s' is below a DNAME '%s' (illegal)",
+ ownerbuf, namebuf, altbuf);
+ ok = ISC_FALSE;
+ }
+ }
+ return (ok ? ISC_R_SUCCESS : DNS_R_REFUSED);
+}
+
+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_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;
+ }
+
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+static isc_result_t
+get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) {
+ dns_dbnode_t *node = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ unsigned int iterations = 0;
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ 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 success;
+ 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;
+
+ success:
+ *iterationsp = iterations;
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+/*
+ * Prevent the zone entering a inconsistant state where
+ * NSEC only DNSKEYs are present with NSEC3 chains.
+ */
+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;
+ isc_result_t result;
+ unsigned int iterations = 0, max;
+
+ dns_diff_init(diff->mctx, &temp_diff);
+
+ CHECK(dns_nsec_nseconly(db, ver, &flag));
+
+ 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 (iterations > max) {
+ flag = ISC_TRUE;
+ update_log(client, zone, ISC_LOG_WARNING,
+ "too many NSEC3 iterations (%u) for "
+ "weakest DNSKEY (%u)", iterations, max);
+ }
+ }
+ 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);
+ }
+ }
+
+
+ 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)
+{
+ 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];
+ dns_diff_t temp_diff;
+ dns_diffop_t op;
+ isc_boolean_t flag;
+
+ update_log(client, zone, ISC_LOG_DEBUG(3),
+ "checking for NSEC3PARAM changes");
+
+ dns_diff_init(diff->mctx, &temp_diff);
+
+ /*
+ * Extract NSEC3PARAM tuples from list.
+ */
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL;
+ tuple = next) {
+
+ next = ISC_LIST_NEXT(tuple, link);
+
+ if (tuple->rdata.type != dns_rdatatype_nsec3param ||
+ !dns_name_equal(name, &tuple->name))
+ continue;
+ ISC_LIST_UNLINK(diff->tuples, tuple, link);
+ ISC_LIST_APPEND(temp_diff.tuples, tuple, link);
+ }
+
+ for (tuple = ISC_LIST_HEAD(temp_diff.tuples);
+ tuple != NULL; tuple = next) {
+
+ if (tuple->op == DNS_DIFFOP_ADD) {
+ next = ISC_LIST_NEXT(tuple, link);
+ 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. */
+ 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])) {
+ 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);
+ }
+
+ 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;
+
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+
+ if (!flag) {
+ CHECK(dns_difftuple_create(diff->mctx,
+ DNS_DIFFOP_ADD,
+ name, tuple->ttl,
+ &rdata,
+ &newtuple));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ }
+ /*
+ * Remove the temporary add record.
+ */
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
+ name, tuple->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);
+ } else
+ 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) {
+ 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;
+
+ CHECK(rr_exists(db, ver, name, &rdata, &flag));
+
+ if (!flag) {
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ name, tuple->ttl, &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));
+ CHECK(do_one_tuple(&newtuple, db, ver, diff));
+ ISC_LIST_UNLINK(temp_diff.tuples, tuple, link);
+ dns_diff_appendminimal(diff, &tuple);
+ dns_rdata_reset(&rdata);
+ }
+
+ result = ISC_R_SUCCESS;
+ failure:
+ dns_diff_clear(&temp_diff);
+ return (result);
+}
+#endif
+
+/*
+ * 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)
+{
+ 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];
+
+ for (tuple = ISC_LIST_HEAD(diff->tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ if (tuple->rdata.type != dns_rdatatype_dnskey)
+ continue;
+
+ dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
+ if ((dnskey.flags &
+ (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
+ != DNS_KEYOWNER_ZONE)
+ continue;
+
+ dns_rdata_toregion(&tuple->rdata, &r);
+ keyid = dst_region_computeid(&r, dnskey.algorithm);
+
+ 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;
+
+ 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);
+}
+
+#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));
+
+ 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
+
+static void
+update_action(isc_task_t *task, isc_event_t *event) {
+ update_event_t *uev = (update_event_t *) event;
+ dns_zone_t *zone = uev->zone;
+ ns_client_t *client = (ns_client_t *)event->ev_arg;
+
+ isc_result_t result;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *oldver = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_diff_t diff; /* Pending updates. */
+ dns_diff_t temp; /* Pending RR existence assertions. */
+ isc_boolean_t soa_serial_changed = ISC_FALSE;
+ isc_mem_t *mctx = client->mctx;
+ dns_rdatatype_t covers;
+ dns_message_t *request = client->message;
+ dns_rdataclass_t zoneclass;
+ dns_name_t *zonename;
+ dns_ssutable_t *ssutable = NULL;
+ 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
+
+ INSIST(event->ev_type == DNS_EVENT_UPDATE);
+
+ dns_diff_init(mctx, &diff);
+ dns_diff_init(mctx, &temp);
+
+ CHECK(dns_zone_getdb(zone, &db));
+ zonename = dns_db_origin(db);
+ zoneclass = dns_db_class(db);
+ dns_zone_getssutable(zone, &ssutable);
+ dns_db_currentversion(db, &oldver);
+ CHECK(dns_db_newversion(db, &ver));
+
+ /*
+ * Check prerequisites.
+ */
+
+ for (result = dns_message_firstname(request, DNS_SECTION_PREREQUISITE);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(request, DNS_SECTION_PREREQUISITE))
+ {
+ dns_name_t *name = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_ttl_t ttl;
+ dns_rdataclass_t update_class;
+ isc_boolean_t flag;
+
+ get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass,
+ &name, &rdata, &covers, &ttl, &update_class);
+
+ if (ttl != 0)
+ PREREQFAILC(DNS_R_FORMERR,
+ "prerequisite TTL is not zero");
+
+ if (! dns_name_issubdomain(name, zonename))
+ PREREQFAILN(DNS_R_NOTZONE, name,
+ "prerequisite name is out of zone");
+
+ if (update_class == dns_rdataclass_any) {
+ if (rdata.length != 0)
+ PREREQFAILC(DNS_R_FORMERR,
+ "class ANY prerequisite "
+ "RDATA is not empty");
+ if (rdata.type == dns_rdatatype_any) {
+ CHECK(name_exists(db, ver, name, &flag));
+ if (! flag) {
+ PREREQFAILN(DNS_R_NXDOMAIN, name,
+ "'name in use' "
+ "prerequisite not "
+ "satisfied");
+ }
+ } else {
+ CHECK(rrset_exists(db, ver, name,
+ rdata.type, covers, &flag));
+ if (! flag) {
+ /* RRset does not exist. */
+ PREREQFAILNT(DNS_R_NXRRSET, name, rdata.type,
+ "'rrset exists (value independent)' "
+ "prerequisite not satisfied");
+ }
+ }
+ } else if (update_class == dns_rdataclass_none) {
+ if (rdata.length != 0)
+ PREREQFAILC(DNS_R_FORMERR,
+ "class NONE prerequisite "
+ "RDATA is not empty");
+ if (rdata.type == dns_rdatatype_any) {
+ CHECK(name_exists(db, ver, name, &flag));
+ if (flag) {
+ PREREQFAILN(DNS_R_YXDOMAIN, name,
+ "'name not in use' "
+ "prerequisite not "
+ "satisfied");
+ }
+ } else {
+ CHECK(rrset_exists(db, ver, name,
+ rdata.type, covers, &flag));
+ if (flag) {
+ /* RRset exists. */
+ PREREQFAILNT(DNS_R_YXRRSET, name,
+ rdata.type,
+ "'rrset does not exist' "
+ "prerequisite not "
+ "satisfied");
+ }
+ }
+ } else if (update_class == zoneclass) {
+ /* "temp<rr.name, rr.type> += rr;" */
+ result = temp_append(&temp, name, &rdata);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "temp entry creation failed: %s",
+ dns_result_totext(result));
+ FAIL(ISC_R_UNEXPECTED);
+ }
+ } else {
+ PREREQFAILC(DNS_R_FORMERR, "malformed prerequisite");
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ FAIL(result);
+
+
+ /*
+ * Perform the final check of the "rrset exists (value dependent)"
+ * prerequisites.
+ */
+ if (ISC_LIST_HEAD(temp.tuples) != NULL) {
+ dns_rdatatype_t type;
+
+ /*
+ * Sort the prerequisite records by owner name,
+ * type, and rdata.
+ */
+ result = dns_diff_sort(&temp, temp_order);
+ if (result != ISC_R_SUCCESS)
+ FAILC(result, "'RRset exists (value dependent)' "
+ "prerequisite not satisfied");
+
+ dns_fixedname_init(&tmpnamefixed);
+ tmpname = dns_fixedname_name(&tmpnamefixed);
+ result = temp_check(mctx, &temp, db, ver, tmpname, &type);
+ if (result != ISC_R_SUCCESS)
+ FAILNT(result, tmpname, type,
+ "'RRset exists (value dependent)' "
+ "prerequisite not satisfied");
+ }
+
+ update_log(client, zone, LOGLEVEL_DEBUG,
+ "prerequisites are OK");
+
+ /*
+ * Check Requestor's Permissions. It seems a bit silly to do this
+ * only after prerequisite testing, but that is what RFC2136 says.
+ */
+ result = ISC_R_SUCCESS;
+ if (ssutable == NULL)
+ CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone),
+ "update", zonename, ISC_FALSE, ISC_FALSE));
+ else if (client->signer == NULL && !TCPCLIENT(client))
+ CHECK(checkupdateacl(client, NULL, "update", zonename,
+ ISC_FALSE, ISC_TRUE));
+
+ if (dns_zone_getupdatedisabled(zone))
+ FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled "
+ "because the zone is frozen. Use "
+ "'rndc thaw' to re-enable updates.");
+
+ /*
+ * Perform the Update Section Prescan.
+ */
+
+ for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(request, DNS_SECTION_UPDATE))
+ {
+ dns_name_t *name = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_ttl_t ttl;
+ dns_rdataclass_t update_class;
+ get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,
+ &name, &rdata, &covers, &ttl, &update_class);
+
+ if (! dns_name_issubdomain(name, zonename))
+ FAILC(DNS_R_NOTZONE,
+ "update RR is outside zone");
+ if (update_class == zoneclass) {
+ /*
+ * Check for meta-RRs. The RFC2136 pseudocode says
+ * check for ANY|AXFR|MAILA|MAILB, but the text adds
+ * "or any other QUERY metatype"
+ */
+ if (dns_rdatatype_ismeta(rdata.type)) {
+ FAILC(DNS_R_FORMERR,
+ "meta-RR in update");
+ }
+ result = dns_zone_checknames(zone, name, &rdata);
+ if (result != ISC_R_SUCCESS)
+ FAIL(DNS_R_REFUSED);
+ } else if (update_class == dns_rdataclass_any) {
+ if (ttl != 0 || rdata.length != 0 ||
+ (dns_rdatatype_ismeta(rdata.type) &&
+ rdata.type != dns_rdatatype_any))
+ FAILC(DNS_R_FORMERR,
+ "meta-RR in update");
+ } else if (update_class == dns_rdataclass_none) {
+ if (ttl != 0 ||
+ dns_rdatatype_ismeta(rdata.type))
+ FAILC(DNS_R_FORMERR,
+ "meta-RR in update");
+ } else {
+ update_log(client, zone, ISC_LOG_WARNING,
+ "update RR has incorrect class %d",
+ 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 (ssutable != NULL) {
+ isc_netaddr_t *tcpaddr, netaddr;
+ /*
+ * If this is a TCP connection then pass the
+ * address of the client through for tcp-self
+ * and 6to4-self otherwise pass NULL. This
+ * provides weak address based authentication.
+ */
+ if (TCPCLIENT(client)) {
+ isc_netaddr_fromsockaddr(&netaddr,
+ &client->peeraddr);
+ tcpaddr = &netaddr;
+ } else
+ tcpaddr = NULL;
+ if (rdata.type != dns_rdatatype_any) {
+ if (!dns_ssutable_checkrules(ssutable,
+ client->signer,
+ name, tcpaddr,
+ rdata.type))
+ FAILC(DNS_R_REFUSED,
+ "rejected by secure update");
+ } else {
+ if (!ssu_checkall(db, ver, name, ssutable,
+ client->signer, tcpaddr))
+ FAILC(DNS_R_REFUSED,
+ "rejected by secure update");
+ }
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ FAIL(result);
+
+ update_log(client, zone, LOGLEVEL_DEBUG,
+ "update section prescan OK");
+
+ /*
+ * Process the Update Section.
+ */
+
+ options = dns_zone_getoptions(zone);
+ for (result = dns_message_firstname(request, DNS_SECTION_UPDATE);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(request, DNS_SECTION_UPDATE))
+ {
+ dns_name_t *name = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_ttl_t ttl;
+ dns_rdataclass_t update_class;
+ isc_boolean_t flag;
+
+ get_current_rr(request, DNS_SECTION_UPDATE, zoneclass,
+ &name, &rdata, &covers, &ttl, &update_class);
+
+ if (update_class == zoneclass) {
+
+ /*
+ * RFC1123 doesn't allow MF and MD in master zones. */
+ if (rdata.type == dns_rdatatype_md ||
+ rdata.type == dns_rdatatype_mf) {
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_rdatatype_format(rdata.type, typebuf,
+ sizeof(typebuf));
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "attempt to add %s ignored",
+ typebuf);
+ continue;
+ }
+ if ((rdata.type == dns_rdatatype_ns ||
+ rdata.type == dns_rdatatype_dname) &&
+ dns_name_iswildcard(name)) {
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_rdatatype_format(rdata.type, typebuf,
+ sizeof(typebuf));
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to add wildcard %s record "
+ "ignored", typebuf);
+ continue;
+ }
+ if (rdata.type == dns_rdatatype_cname) {
+ CHECK(cname_incompatible_rrset_exists(db, ver,
+ name,
+ &flag));
+ if (flag) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to add CNAME "
+ "alongside non-CNAME "
+ "ignored");
+ continue;
+ }
+ } else {
+ CHECK(rrset_exists(db, ver, name,
+ dns_rdatatype_cname, 0,
+ &flag));
+ if (flag &&
+ ! dns_rdatatype_isdnssec(rdata.type))
+ {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to add non-CNAME "
+ "alongside CNAME ignored");
+ continue;
+ }
+ }
+ if (rdata.type == dns_rdatatype_soa) {
+ isc_boolean_t ok;
+ CHECK(rrset_exists(db, ver, name,
+ dns_rdatatype_soa, 0,
+ &flag));
+ if (! flag) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to create 2nd "
+ "SOA ignored");
+ continue;
+ }
+ CHECK(check_soa_increment(db, ver, &rdata,
+ &ok));
+ if (! ok) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "SOA update failed to "
+ "increment serial, "
+ "ignoring it");
+ continue;
+ }
+ soa_serial_changed = ISC_TRUE;
+ }
+
+#ifdef ALLOW_NSEC3PARAM_UPDATE
+ if (rdata.type == dns_rdatatype_nsec3param) {
+ /*
+ * Ignore attempts to add NSEC3PARAM records
+ * with any flags other than OPTOUT.
+ */
+ if ((rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to add NSEC3PARAM "
+ "record with non OPTOUT "
+ "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)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr,
+ sizeof(namestr));
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "warning: ownername '%s' contains "
+ "a non-terminal wildcard", namestr);
+ }
+
+ if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+ dns_name_format(name, namestr,
+ sizeof(namestr));
+ dns_rdatatype_format(rdata.type, typestr,
+ sizeof(typestr));
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "adding an RR at '%s' %s",
+ namestr, typestr);
+ }
+
+ /* Prepare the affected RRset for the addition. */
+ {
+ add_rr_prepare_ctx_t ctx;
+ ctx.db = db;
+ ctx.ver = ver;
+ ctx.diff = &diff;
+ ctx.name = name;
+ ctx.update_rr = &rdata;
+ ctx.update_rr_ttl = ttl;
+ ctx.ignore_add = ISC_FALSE;
+ dns_diff_init(mctx, &ctx.del_diff);
+ dns_diff_init(mctx, &ctx.add_diff);
+ CHECK(foreach_rr(db, ver, name, rdata.type,
+ covers, add_rr_prepare_action,
+ &ctx));
+
+ if (ctx.ignore_add) {
+ dns_diff_clear(&ctx.del_diff);
+ dns_diff_clear(&ctx.add_diff);
+ } else {
+ CHECK(do_diff(&ctx.del_diff, db, ver,
+ &diff));
+ CHECK(do_diff(&ctx.add_diff, db, ver,
+ &diff));
+ CHECK(update_one_rr(db, ver, &diff,
+ DNS_DIFFOP_ADD,
+ name, ttl, &rdata));
+ }
+ }
+ } else if (update_class == dns_rdataclass_any) {
+ if (rdata.type == dns_rdatatype_any) {
+ if (isc_log_wouldlog(ns_g_lctx,
+ LOGLEVEL_PROTOCOL))
+ {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr,
+ sizeof(namestr));
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "delete all rrsets from "
+ "name '%s'", namestr);
+ }
+ if (dns_name_equal(name, zonename)) {
+ CHECK(delete_if(type_not_soa_nor_ns_p,
+ db, ver, name,
+ dns_rdatatype_any, 0,
+ &rdata, &diff));
+ } else {
+ CHECK(delete_if(type_not_dnssec,
+ db, ver, name,
+ 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)) {
+ update_log(client, zone, LOGLEVEL_PROTOCOL,
+ "attempt to delete all SOA "
+ "or NS records ignored");
+ continue;
+ } else {
+ if (isc_log_wouldlog(ns_g_lctx,
+ LOGLEVEL_PROTOCOL))
+ {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+ dns_name_format(name, namestr,
+ sizeof(namestr));
+ dns_rdatatype_format(rdata.type,
+ typestr,
+ sizeof(typestr));
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "deleting rrset at '%s' %s",
+ namestr, typestr);
+ }
+ CHECK(delete_if(true_p, db, ver, name,
+ rdata.type, covers, &rdata,
+ &diff));
+ }
+ } else if (update_class == dns_rdataclass_none) {
+ /*
+ * The (name == zonename) condition appears in
+ * RFC2136 3.4.2.4 but is missing from the pseudocode.
+ */
+ if (dns_name_equal(name, zonename)) {
+ if (rdata.type == dns_rdatatype_soa) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to delete SOA "
+ "ignored");
+ continue;
+ }
+ if (rdata.type == dns_rdatatype_ns) {
+ int count;
+ CHECK(rr_count(db, ver, name,
+ dns_rdatatype_ns,
+ 0, &count));
+ if (count == 1) {
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "attempt to "
+ "delete last "
+ "NS ignored");
+ continue;
+ }
+ }
+ }
+ update_log(client, zone,
+ LOGLEVEL_PROTOCOL,
+ "deleting an RR");
+ CHECK(delete_if(rr_equal_p, db, ver, name,
+ rdata.type, covers, &rdata, &diff));
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ FAIL(result);
+
+ /*
+ * Check that any changes to DNSKEY/NSEC3PARAM records make sense.
+ * If they don't then back out all changes to DNSKEY/NSEC3PARAM
+ * records.
+ */
+ if (! ISC_LIST_EMPTY(diff.tuples))
+ CHECK(check_dnssec(client, zone, db, ver, &diff));
+
+ /*
+ * If any changes were made, increment the SOA serial number,
+ * update RRSIGs and NSECs (if zone is secure), and write the update
+ * to the journal.
+ */
+ if (! ISC_LIST_EMPTY(diff.tuples)) {
+ char *journalfile;
+ dns_journal_t *journal;
+ isc_boolean_t has_dnskey;
+
+ /*
+ * Increment the SOA serial, but only if it was not
+ * changed as a result of an update operation.
+ */
+ if (! soa_serial_changed) {
+ CHECK(increment_soa_serial(db, ver, &diff, mctx));
+ }
+
+ CHECK(check_mx(client, zone, db, ver, &diff));
+
+ CHECK(remove_orphaned_ds(db, ver, &diff));
+
+ 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));
+
+#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;
+ }
+#endif
+#endif
+
+ CHECK(add_signing_records(db, zonename, ver,
+ dns_zone_getprivatetype(zone),
+ &diff));
+
+#ifdef ALLOW_NSEC3PARAM_UPDATE
+ CHECK(add_nsec3param_records(client, zone, db, zonename,
+ ver, &diff));
+#endif
+
+ if (!has_dnskey) {
+ /*
+ * We are transitioning from secure to insecure.
+ * Cause all NSEC3 chains to be deleted. When the
+ * 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)) {
+ isc_uint32_t interval;
+ interval = dns_zone_getsigvalidityinterval(zone);
+ result = update_signatures(client, zone, db, oldver,
+ ver, &diff, interval,
+ &deleted_zsk);
+ if (result != ISC_R_SUCCESS) {
+ update_log(client, zone,
+ ISC_LOG_ERROR,
+ "RRSIG/NSEC/NSEC3 update failed: %s",
+ isc_result_totext(result));
+ goto failure;
+ }
+ }
+
+ journalfile = dns_zone_getjournal(zone);
+ if (journalfile != NULL) {
+ update_log(client, zone, LOGLEVEL_DEBUG,
+ "writing journal %s", journalfile);
+
+ journal = NULL;
+ result = dns_journal_open(mctx, journalfile,
+ ISC_TRUE, &journal);
+ if (result != ISC_R_SUCCESS)
+ FAILS(result, "journal open failed");
+
+ result = dns_journal_write_transaction(journal, &diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_journal_destroy(&journal);
+ FAILS(result, "journal write failed");
+ }
+
+ dns_journal_destroy(&journal);
+ }
+
+ /*
+ * XXXRTH Just a note that this committing code will have
+ * to change to handle databases that need two-phase
+ * commit, but this isn't a priority.
+ */
+ update_log(client, zone, LOGLEVEL_DEBUG,
+ "committing update transaction");
+
+ dns_db_closeversion(db, &ver, ISC_TRUE);
+
+ /*
+ * Mark the zone as dirty so that it will be written to disk.
+ */
+ dns_zone_markdirty(zone);
+
+ /*
+ * Notify slaves of the change we just made.
+ */
+ dns_zone_notify(zone);
+
+ /*
+ * Cause the zone to be signed with the key that we
+ * have just added or have the corresponding signatures
+ * deleted.
+ *
+ * Note: we are already committed to this course of action.
+ */
+ for (tuple = ISC_LIST_HEAD(diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ isc_region_t r;
+ dns_secalg_t algorithm;
+ isc_uint16_t keyid;
+
+ if (tuple->rdata.type != dns_rdatatype_dnskey)
+ continue;
+
+ dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
+ if ((dnskey.flags &
+ (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
+ != DNS_KEYOWNER_ZONE)
+ continue;
+
+ dns_rdata_toregion(&tuple->rdata, &r);
+ algorithm = dnskey.algorithm;
+ keyid = dst_region_computeid(&r, algorithm);
+
+ result = dns_zone_signwithkey(zone, algorithm, keyid,
+ ISC_TF(tuple->op == DNS_DIFFOP_DEL));
+ if (result != ISC_R_SUCCESS) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "dns_zone_signwithkey failed: %s",
+ dns_result_totext(result));
+ }
+ }
+
+#ifdef ALLOW_NSEC3PARAM_UPDATE
+ /*
+ * Cause the zone to add/delete NSEC3 chains for the
+ * defered NSEC3PARAM changes.
+ *
+ * Note: we are already committed to this course of action.
+ */
+ for (tuple = ISC_LIST_HEAD(diff.tuples);
+ tuple != NULL;
+ tuple = ISC_LIST_NEXT(tuple, link)) {
+ dns_rdata_nsec3param_t nsec3param;
+
+ if (tuple->rdata.type != dns_rdatatype_nsec3param ||
+ tuple->op != DNS_DIFFOP_ADD)
+ continue;
+
+ dns_rdata_tostruct(&tuple->rdata, &nsec3param, NULL);
+ if (nsec3param.flags == 0)
+ continue;
+
+ result = dns_zone_addnsec3chain(zone, &nsec3param);
+ if (result != ISC_R_SUCCESS) {
+ update_log(client, zone, ISC_LOG_ERROR,
+ "dns_zone_addnsec3chain failed: %s",
+ dns_result_totext(result));
+ }
+ }
+#endif
+ } else {
+ update_log(client, zone, LOGLEVEL_DEBUG, "redundant request");
+ dns_db_closeversion(db, &ver, ISC_TRUE);
+ }
+ result = ISC_R_SUCCESS;
+ goto common;
+
+ failure:
+ if (result == DNS_R_REFUSED)
+ inc_stats(zone, dns_nsstatscounter_updaterej);
+
+ /*
+ * The reason for failure should have been logged at this point.
+ */
+ if (ver != NULL) {
+ update_log(client, zone, LOGLEVEL_DEBUG,
+ "rolling back");
+ dns_db_closeversion(db, &ver, ISC_FALSE);
+ }
+
+ common:
+ dns_diff_clear(&temp);
+ dns_diff_clear(&diff);
+
+ if (oldver != NULL)
+ dns_db_closeversion(db, &oldver, ISC_FALSE);
+
+ if (db != NULL)
+ dns_db_detach(&db);
+
+ if (ssutable != NULL)
+ dns_ssutable_detach(&ssutable);
+
+ isc_task_detach(&task);
+ uev->result = result;
+ if (zone != NULL)
+ INSIST(uev->zone == zone); /* we use this later */
+ uev->ev_type = DNS_EVENT_UPDATEDONE;
+ uev->ev_action = updatedone_action;
+ isc_task_send(client->task, &event);
+ INSIST(event == NULL);
+}
+
+static void
+updatedone_action(isc_task_t *task, isc_event_t *event) {
+ update_event_t *uev = (update_event_t *) event;
+ ns_client_t *client = (ns_client_t *) event->ev_arg;
+
+ UNUSED(task);
+
+ INSIST(event->ev_type == DNS_EVENT_UPDATEDONE);
+ INSIST(task == client->task);
+
+ INSIST(client->nupdates > 0);
+ switch (uev->result) {
+ case ISC_R_SUCCESS:
+ inc_stats(uev->zone, dns_nsstatscounter_updatedone);
+ break;
+ case DNS_R_REFUSED:
+ inc_stats(uev->zone, dns_nsstatscounter_updaterej);
+ break;
+ default:
+ inc_stats(uev->zone, dns_nsstatscounter_updatefail);
+ break;
+ }
+ if (uev->zone != NULL)
+ dns_zone_detach(&uev->zone);
+ client->nupdates--;
+ respond(client, uev->result);
+ isc_event_free(&event);
+ ns_client_detach(&client);
+}
+
+/*%
+ * Update forwarding support.
+ */
+
+static void
+forward_fail(isc_task_t *task, isc_event_t *event) {
+ ns_client_t *client = (ns_client_t *)event->ev_arg;
+
+ UNUSED(task);
+
+ INSIST(client->nupdates > 0);
+ client->nupdates--;
+ respond(client, DNS_R_SERVFAIL);
+ isc_event_free(&event);
+ ns_client_detach(&client);
+}
+
+
+static void
+forward_callback(void *arg, isc_result_t result, dns_message_t *answer) {
+ update_event_t *uev = arg;
+ ns_client_t *client = uev->ev_arg;
+ dns_zone_t *zone = uev->zone;
+
+ if (result != ISC_R_SUCCESS) {
+ INSIST(answer == NULL);
+ uev->ev_type = DNS_EVENT_UPDATEDONE;
+ uev->ev_action = forward_fail;
+ inc_stats(zone, dns_nsstatscounter_updatefwdfail);
+ } else {
+ uev->ev_type = DNS_EVENT_UPDATEDONE;
+ uev->ev_action = forward_done;
+ uev->answer = answer;
+ inc_stats(zone, dns_nsstatscounter_updaterespfwd);
+ }
+ isc_task_send(client->task, ISC_EVENT_PTR(&uev));
+ dns_zone_detach(&zone);
+}
+
+static void
+forward_done(isc_task_t *task, isc_event_t *event) {
+ update_event_t *uev = (update_event_t *) event;
+ ns_client_t *client = (ns_client_t *)event->ev_arg;
+
+ UNUSED(task);
+
+ INSIST(client->nupdates > 0);
+ client->nupdates--;
+ ns_client_sendraw(client, uev->answer);
+ dns_message_destroy(&uev->answer);
+ isc_event_free(&event);
+ ns_client_detach(&client);
+}
+
+static void
+forward_action(isc_task_t *task, isc_event_t *event) {
+ update_event_t *uev = (update_event_t *) event;
+ dns_zone_t *zone = uev->zone;
+ ns_client_t *client = (ns_client_t *)event->ev_arg;
+ isc_result_t result;
+
+ result = dns_zone_forwardupdate(zone, client->message,
+ forward_callback, event);
+ if (result != ISC_R_SUCCESS) {
+ uev->ev_type = DNS_EVENT_UPDATEDONE;
+ uev->ev_action = forward_fail;
+ isc_task_send(client->task, &event);
+ inc_stats(zone, dns_nsstatscounter_updatefwdfail);
+ dns_zone_detach(&zone);
+ } else
+ inc_stats(zone, dns_nsstatscounter_updatereqfwd);
+ isc_task_detach(&task);
+}
+
+static isc_result_t
+send_forward_event(ns_client_t *client, dns_zone_t *zone) {
+ isc_result_t result = ISC_R_SUCCESS;
+ update_event_t *event = NULL;
+ isc_task_t *zonetask = NULL;
+ ns_client_t *evclient;
+
+ event = (update_event_t *)
+ isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE,
+ forward_action, NULL, sizeof(*event));
+ if (event == NULL)
+ FAIL(ISC_R_NOMEMORY);
+ event->zone = zone;
+ event->result = ISC_R_SUCCESS;
+
+ evclient = NULL;
+ ns_client_attach(client, &evclient);
+ INSIST(client->nupdates == 0);
+ client->nupdates++;
+ event->ev_arg = evclient;
+
+ dns_zone_gettask(zone, &zonetask);
+ isc_task_send(zonetask, ISC_EVENT_PTR(&event));
+
+ failure:
+ if (event != NULL)
+ isc_event_free(ISC_EVENT_PTR(&event));
+ return (result);
+}
diff --git a/bin/named/win32/include/named/ntservice.h b/bin/named/win32/include/named/ntservice.h
new file mode 100644
index 0000000..0298388
--- /dev/null
+++ b/bin/named/win32/include/named/ntservice.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: ntservice.h,v 1.6 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef NTSERVICE_H
+#define NTSERVICE_H
+
+#include <winsvc.h>
+
+#define BIND_DISPLAY_NAME "ISC BIND"
+#define BIND_SERVICE_NAME "named"
+
+void
+ntservice_init();
+void UpdateSCM(DWORD);
+void ServiceControl(DWORD dwCtrlCode);
+void
+ntservice_shutdown();
+BOOL ntservice_isservice();
+#endif
diff --git a/bin/named/win32/include/named/os.h b/bin/named/win32/include/named/os.h
new file mode 100644
index 0000000..c00e973
--- /dev/null
+++ b/bin/named/win32/include/named/os.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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.h,v 1.14 2008/10/24 01:44:48 tbox Exp $ */
+
+#ifndef NS_OS_H
+#define NS_OS_H 1
+
+#include <isc/types.h>
+
+void
+ns_os_init(const char *progname);
+
+void
+ns_os_daemonize(void);
+
+void
+ns_os_opendevnull(void);
+
+void
+ns_os_closedevnull(void);
+
+void
+ns_os_chroot(const char *root);
+
+void
+ns_os_inituserinfo(const char *username);
+
+void
+ns_os_changeuser(void);
+
+void
+ns_os_adjustnofile(void);
+
+void
+ns_os_minprivs(void);
+
+void
+ns_os_writepidfile(const char *filename, isc_boolean_t first_time);
+
+void
+ns_os_shutdown(void);
+
+isc_result_t
+ns_os_gethostname(char *buf, size_t len);
+
+void
+ns_os_shutdownmsg(char *command, isc_buffer_t *text);
+
+void
+ns_os_tzset(void);
+
+void
+ns_os_started(void);
+
+#endif /* NS_OS_H */
diff --git a/bin/named/win32/named.dsp b/bin/named/win32/named.dsp
new file mode 100644
index 0000000..c7dec7d
--- /dev/null
+++ b/bin/named/win32/named.dsp
@@ -0,0 +1,327 @@
+# Microsoft Developer Studio Project File - Name="named" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=named - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "named.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "named.mak" CFG="named - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "named - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "named - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/lwres/win32/Release/liblwres.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/named.exe"
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/lwres/win32/Debug/liblwres.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /map /debug /machine:I386 /out:"../../../Build/Debug/named.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "named - Win32 Release"
+# Name "named - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\builtin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\client.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\config.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\control.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\controlconf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\interfacemgr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\listenlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\logconf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwdclient.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwderror.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwdgabn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwdgnba.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwdgrbn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwdnoop.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwresd.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwsearch.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\main.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\notify.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ntservice.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\query.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\server.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sortlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\statschannel.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\tkeyconf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\tsigconf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\update.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\xfrout.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zoneconf.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\named\client.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\globals.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\interfacemgr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\listenlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\logconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\lwaddr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\lwdclient.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\lwresd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\lwsearch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\main.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\notify.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\named\ntservice.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\omapi.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\named\os.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\query.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\server.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\sortlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\statschannel.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\tkeyconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\tsigconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\update.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\xfrout.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\named\zoneconf.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/named/win32/named.dsw b/bin/named/win32/named.dsw
new file mode 100644
index 0000000..c2913ef
--- /dev/null
+++ b/bin/named/win32/named.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "named"=".\named.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/named/win32/named.mak b/bin/named/win32/named.mak
new file mode 100644
index 0000000..8f006c3
--- /dev/null
+++ b/bin/named/win32/named.mak
@@ -0,0 +1,1174 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on named.dsp
+!IF "$(CFG)" == ""
+CFG=named - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to named - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "named - Win32 Release" && "$(CFG)" != "named - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "named.mak" CFG="named - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "named - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "named - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "named - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\named.exe"
+
+!ELSE
+
+ALL : "libisccfg - Win32 Release" "libisccc - Win32 Release" "liblwres - Win32 Release" "libbind9 - Win32 Release" "libisc - Win32 Release" "libdns - Win32 Release" "..\..\..\Build\Release\named.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN" "libbind9 - Win32 ReleaseCLEAN" "liblwres - Win32 ReleaseCLEAN" "libisccc - Win32 ReleaseCLEAN" "libisccfg - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\builtin.obj"
+ -@erase "$(INTDIR)\client.obj"
+ -@erase "$(INTDIR)\config.obj"
+ -@erase "$(INTDIR)\control.obj"
+ -@erase "$(INTDIR)\controlconf.obj"
+ -@erase "$(INTDIR)\interfacemgr.obj"
+ -@erase "$(INTDIR)\listenlist.obj"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\logconf.obj"
+ -@erase "$(INTDIR)\lwaddr.obj"
+ -@erase "$(INTDIR)\lwdclient.obj"
+ -@erase "$(INTDIR)\lwderror.obj"
+ -@erase "$(INTDIR)\lwdgabn.obj"
+ -@erase "$(INTDIR)\lwdgnba.obj"
+ -@erase "$(INTDIR)\lwdgrbn.obj"
+ -@erase "$(INTDIR)\lwdnoop.obj"
+ -@erase "$(INTDIR)\lwresd.obj"
+ -@erase "$(INTDIR)\lwsearch.obj"
+ -@erase "$(INTDIR)\main.obj"
+ -@erase "$(INTDIR)\notify.obj"
+ -@erase "$(INTDIR)\ntservice.obj"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\query.obj"
+ -@erase "$(INTDIR)\server.obj"
+ -@erase "$(INTDIR)\sortlist.obj"
+ -@erase "$(INTDIR)\statschannel.obj"
+ -@erase "$(INTDIR)\tkeyconf.obj"
+ -@erase "$(INTDIR)\tsigconf.obj"
+ -@erase "$(INTDIR)\update.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\xfrout.obj"
+ -@erase "$(INTDIR)\zoneconf.obj"
+ -@erase "..\..\..\Build\Release\named.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\named.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\named.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/lwres/win32/Release/liblwres.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\named.pdb" /machine:I386 /out:"../../../Build/Release/named.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\client.obj" \
+ "$(INTDIR)\config.obj" \
+ "$(INTDIR)\control.obj" \
+ "$(INTDIR)\controlconf.obj" \
+ "$(INTDIR)\interfacemgr.obj" \
+ "$(INTDIR)\listenlist.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\logconf.obj" \
+ "$(INTDIR)\lwaddr.obj" \
+ "$(INTDIR)\lwdclient.obj" \
+ "$(INTDIR)\lwderror.obj" \
+ "$(INTDIR)\lwdgabn.obj" \
+ "$(INTDIR)\lwdgnba.obj" \
+ "$(INTDIR)\lwdgrbn.obj" \
+ "$(INTDIR)\lwdnoop.obj" \
+ "$(INTDIR)\lwresd.obj" \
+ "$(INTDIR)\lwsearch.obj" \
+ "$(INTDIR)\main.obj" \
+ "$(INTDIR)\notify.obj" \
+ "$(INTDIR)\ntservice.obj" \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\query.obj" \
+ "$(INTDIR)\server.obj" \
+ "$(INTDIR)\sortlist.obj" \
+ "$(INTDIR)\statschannel.obj" \
+ "$(INTDIR)\tkeyconf.obj" \
+ "$(INTDIR)\tsigconf.obj" \
+ "$(INTDIR)\update.obj" \
+ "$(INTDIR)\xfrout.obj" \
+ "$(INTDIR)\zoneconf.obj" \
+ "$(INTDIR)\builtin.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib" \
+ "..\..\..\lib\isccc\win32\Release\libisccc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib"
+
+"..\..\..\Build\Release\named.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\named.exe" "$(OUTDIR)\named.bsc"
+
+!ELSE
+
+ALL : "libisccfg - Win32 Debug" "libisccc - Win32 Debug" "liblwres - Win32 Debug" "libbind9 - Win32 Debug" "libisc - Win32 Debug" "libdns - Win32 Debug" "..\..\..\Build\Debug\named.exe" "$(OUTDIR)\named.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 DebugCLEAN" "libisc - Win32 DebugCLEAN" "libbind9 - Win32 DebugCLEAN" "liblwres - Win32 DebugCLEAN" "libisccc - Win32 DebugCLEAN" "libisccfg - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\builtin.obj"
+ -@erase "$(INTDIR)\builtin.sbr"
+ -@erase "$(INTDIR)\client.obj"
+ -@erase "$(INTDIR)\client.sbr"
+ -@erase "$(INTDIR)\config.obj"
+ -@erase "$(INTDIR)\config.sbr"
+ -@erase "$(INTDIR)\control.obj"
+ -@erase "$(INTDIR)\control.sbr"
+ -@erase "$(INTDIR)\controlconf.obj"
+ -@erase "$(INTDIR)\controlconf.sbr"
+ -@erase "$(INTDIR)\interfacemgr.obj"
+ -@erase "$(INTDIR)\interfacemgr.sbr"
+ -@erase "$(INTDIR)\listenlist.obj"
+ -@erase "$(INTDIR)\listenlist.sbr"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\log.sbr"
+ -@erase "$(INTDIR)\logconf.obj"
+ -@erase "$(INTDIR)\logconf.sbr"
+ -@erase "$(INTDIR)\lwaddr.obj"
+ -@erase "$(INTDIR)\lwaddr.sbr"
+ -@erase "$(INTDIR)\lwdclient.obj"
+ -@erase "$(INTDIR)\lwdclient.sbr"
+ -@erase "$(INTDIR)\lwderror.obj"
+ -@erase "$(INTDIR)\lwderror.sbr"
+ -@erase "$(INTDIR)\lwdgabn.obj"
+ -@erase "$(INTDIR)\lwdgabn.sbr"
+ -@erase "$(INTDIR)\lwdgnba.obj"
+ -@erase "$(INTDIR)\lwdgnba.sbr"
+ -@erase "$(INTDIR)\lwdgrbn.obj"
+ -@erase "$(INTDIR)\lwdgrbn.sbr"
+ -@erase "$(INTDIR)\lwdnoop.obj"
+ -@erase "$(INTDIR)\lwdnoop.sbr"
+ -@erase "$(INTDIR)\lwresd.obj"
+ -@erase "$(INTDIR)\lwresd.sbr"
+ -@erase "$(INTDIR)\lwsearch.obj"
+ -@erase "$(INTDIR)\lwsearch.sbr"
+ -@erase "$(INTDIR)\main.obj"
+ -@erase "$(INTDIR)\main.sbr"
+ -@erase "$(INTDIR)\notify.obj"
+ -@erase "$(INTDIR)\notify.sbr"
+ -@erase "$(INTDIR)\ntservice.obj"
+ -@erase "$(INTDIR)\ntservice.sbr"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\os.sbr"
+ -@erase "$(INTDIR)\query.obj"
+ -@erase "$(INTDIR)\query.sbr"
+ -@erase "$(INTDIR)\server.obj"
+ -@erase "$(INTDIR)\server.sbr"
+ -@erase "$(INTDIR)\sortlist.obj"
+ -@erase "$(INTDIR)\sortlist.sbr"
+ -@erase "$(INTDIR)\statschannel.obj"
+ -@erase "$(INTDIR)\statschannel.sbr"
+ -@erase "$(INTDIR)\tkeyconf.obj"
+ -@erase "$(INTDIR)\tkeyconf.sbr"
+ -@erase "$(INTDIR)\tsigconf.obj"
+ -@erase "$(INTDIR)\tsigconf.sbr"
+ -@erase "$(INTDIR)\update.obj"
+ -@erase "$(INTDIR)\update.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\xfrout.obj"
+ -@erase "$(INTDIR)\xfrout.sbr"
+ -@erase "$(INTDIR)\zoneconf.obj"
+ -@erase "$(INTDIR)\zoneconf.sbr"
+ -@erase "$(OUTDIR)\named.bsc"
+ -@erase "$(OUTDIR)\named.map"
+ -@erase "$(OUTDIR)\named.pdb"
+ -@erase "..\..\..\Build\Debug\named.exe"
+ -@erase "..\..\..\Build\Debug\named.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../win32/include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "i386" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\named.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\client.sbr" \
+ "$(INTDIR)\config.sbr" \
+ "$(INTDIR)\control.sbr" \
+ "$(INTDIR)\controlconf.sbr" \
+ "$(INTDIR)\interfacemgr.sbr" \
+ "$(INTDIR)\listenlist.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\logconf.sbr" \
+ "$(INTDIR)\lwaddr.sbr" \
+ "$(INTDIR)\lwdclient.sbr" \
+ "$(INTDIR)\lwderror.sbr" \
+ "$(INTDIR)\lwdgabn.sbr" \
+ "$(INTDIR)\lwdgnba.sbr" \
+ "$(INTDIR)\lwdgrbn.sbr" \
+ "$(INTDIR)\lwdnoop.sbr" \
+ "$(INTDIR)\lwresd.sbr" \
+ "$(INTDIR)\lwsearch.sbr" \
+ "$(INTDIR)\main.sbr" \
+ "$(INTDIR)\notify.sbr" \
+ "$(INTDIR)\ntservice.sbr" \
+ "$(INTDIR)\os.sbr" \
+ "$(INTDIR)\query.sbr" \
+ "$(INTDIR)\server.sbr" \
+ "$(INTDIR)\sortlist.sbr" \
+ "$(INTDIR)\statschannel.sbr" \
+ "$(INTDIR)\tkeyconf.sbr" \
+ "$(INTDIR)\tsigconf.sbr" \
+ "$(INTDIR)\update.sbr" \
+ "$(INTDIR)\xfrout.sbr" \
+ "$(INTDIR)\zoneconf.sbr" \
+ "$(INTDIR)\builtin.sbr"
+
+"$(OUTDIR)\named.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib kernel32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/lwres/win32/Debug/liblwres.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\named.pdb" /map:"$(INTDIR)\named.map" /debug /machine:I386 /out:"../../../Build/Debug/named.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\client.obj" \
+ "$(INTDIR)\config.obj" \
+ "$(INTDIR)\control.obj" \
+ "$(INTDIR)\controlconf.obj" \
+ "$(INTDIR)\interfacemgr.obj" \
+ "$(INTDIR)\listenlist.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\logconf.obj" \
+ "$(INTDIR)\lwaddr.obj" \
+ "$(INTDIR)\lwdclient.obj" \
+ "$(INTDIR)\lwderror.obj" \
+ "$(INTDIR)\lwdgabn.obj" \
+ "$(INTDIR)\lwdgnba.obj" \
+ "$(INTDIR)\lwdgrbn.obj" \
+ "$(INTDIR)\lwdnoop.obj" \
+ "$(INTDIR)\lwresd.obj" \
+ "$(INTDIR)\lwsearch.obj" \
+ "$(INTDIR)\main.obj" \
+ "$(INTDIR)\notify.obj" \
+ "$(INTDIR)\ntservice.obj" \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\query.obj" \
+ "$(INTDIR)\server.obj" \
+ "$(INTDIR)\sortlist.obj" \
+ "$(INTDIR)\statschannel.obj" \
+ "$(INTDIR)\tkeyconf.obj" \
+ "$(INTDIR)\tsigconf.obj" \
+ "$(INTDIR)\update.obj" \
+ "$(INTDIR)\xfrout.obj" \
+ "$(INTDIR)\zoneconf.obj" \
+ "$(INTDIR)\builtin.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib" \
+ "..\..\..\lib\isccc\win32\Debug\libisccc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib"
+
+"..\..\..\Build\Debug\named.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("named.dep")
+!INCLUDE "named.dep"
+!ELSE
+!MESSAGE Warning: cannot find "named.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "named - Win32 Release" || "$(CFG)" == "named - Win32 Debug"
+SOURCE=..\builtin.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\builtin.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\builtin.obj" "$(INTDIR)\builtin.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\client.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\client.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\client.obj" "$(INTDIR)\client.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\config.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\config.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\config.obj" "$(INTDIR)\config.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\control.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\control.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\control.obj" "$(INTDIR)\control.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\controlconf.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\controlconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\controlconf.obj" "$(INTDIR)\controlconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\interfacemgr.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\interfacemgr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\interfacemgr.obj" "$(INTDIR)\interfacemgr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\listenlist.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\listenlist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\listenlist.obj" "$(INTDIR)\listenlist.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\log.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\log.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\logconf.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\logconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\logconf.obj" "$(INTDIR)\logconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwaddr.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\lwaddr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\lwaddr.obj" "$(INTDIR)\lwaddr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwdclient.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\lwdclient.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\lwdclient.obj" "$(INTDIR)\lwdclient.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwderror.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\lwderror.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\lwderror.obj" "$(INTDIR)\lwderror.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwdgabn.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\lwdgabn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\lwdgabn.obj" "$(INTDIR)\lwdgabn.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwdgnba.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\lwdgnba.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\lwdgnba.obj" "$(INTDIR)\lwdgnba.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwdgrbn.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\lwdgrbn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\lwdgrbn.obj" "$(INTDIR)\lwdgrbn.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwdnoop.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\lwdnoop.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\lwdnoop.obj" "$(INTDIR)\lwdnoop.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwresd.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\lwresd.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\lwresd.obj" "$(INTDIR)\lwresd.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwsearch.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\lwsearch.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\lwsearch.obj" "$(INTDIR)\lwsearch.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\main.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\main.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\main.obj" "$(INTDIR)\main.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\notify.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\notify.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\notify.obj" "$(INTDIR)\notify.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\ntservice.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\ntservice.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\ntservice.obj" "$(INTDIR)\ntservice.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\os.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\query.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\query.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\query.obj" "$(INTDIR)\query.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\server.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\server.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\server.obj" "$(INTDIR)\server.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sortlist.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\sortlist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\sortlist.obj" "$(INTDIR)\sortlist.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\statschannel.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\statschannel.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\statschannel.obj" "$(INTDIR)\statschannel.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\tkeyconf.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\tkeyconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\tkeyconf.obj" "$(INTDIR)\tkeyconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\tsigconf.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\tsigconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\tsigconf.obj" "$(INTDIR)\tsigconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\update.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\update.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\update.obj" "$(INTDIR)\update.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\xfrout.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\xfrout.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\xfrout.obj" "$(INTDIR)\xfrout.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\zoneconf.c
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+
+"$(INTDIR)\zoneconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+
+"$(INTDIR)\zoneconf.obj" "$(INTDIR)\zoneconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\..\bin\named\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\..\bin\named\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\named\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\named\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+"libbind9 - Win32 Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release"
+ cd "..\..\..\bin\named\win32"
+
+"libbind9 - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+"libbind9 - Win32 Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug"
+ cd "..\..\..\bin\named\win32"
+
+"libbind9 - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+"liblwres - Win32 Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release"
+ cd "..\..\..\bin\named\win32"
+
+"liblwres - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+"liblwres - Win32 Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug"
+ cd "..\..\..\bin\named\win32"
+
+"liblwres - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+"libisccc - Win32 Release" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - Win32 Release"
+ cd "..\..\..\bin\named\win32"
+
+"libisccc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+"libisccc - Win32 Debug" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - Win32 Debug"
+ cd "..\..\..\bin\named\win32"
+
+"libisccc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "named - Win32 Release"
+
+"libisccfg - Win32 Release" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Release"
+ cd "..\..\..\bin\named\win32"
+
+"libisccfg - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ELSEIF "$(CFG)" == "named - Win32 Debug"
+
+"libisccfg - Win32 Debug" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Debug"
+ cd "..\..\..\bin\named\win32"
+
+"libisccfg - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\named\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/named/win32/ntservice.c b/bin/named/win32/ntservice.c
new file mode 100644
index 0000000..74570cf
--- /dev/null
+++ b/bin/named/win32/ntservice.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: ntservice.c,v 1.12 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+#include <stdio.h>
+
+#include <isc/app.h>
+#include <isc/log.h>
+
+#include <named/globals.h>
+#include <named/ntservice.h>
+#include <named/main.h>
+#include <named/server.h>
+
+/* Handle to SCM for updating service status */
+static SERVICE_STATUS_HANDLE hServiceStatus = 0;
+static BOOL foreground = FALSE;
+static char ConsoleTitle[128];
+
+/*
+ * Forward declarations
+ */
+void ServiceControl(DWORD dwCtrlCode);
+void GetArgs(int *, char ***, char ***);
+int main(int, char *[], char *[]); /* From ns_main.c */
+
+/*
+ * Here we change the entry point for the executable to bindmain() from main()
+ * This allows us to invoke as a service or from the command line easily.
+ */
+#pragma comment(linker, "/entry:bindmain")
+
+/*
+ * This is the entry point for the executable
+ * We can now call main() explicitly or via StartServiceCtrlDispatcher()
+ * as we need to.
+ */
+int bindmain()
+{
+ int rc,
+ i = 1;
+
+ int argc;
+ char **envp, **argv;
+
+ /*
+ * We changed the entry point function, so we must initialize argv,
+ * etc. ourselves. Ick.
+ */
+ GetArgs(&argc, &argv, &envp);
+
+ /* Command line users should put -f in the options */
+ while (argv[i]) {
+ if (!strcmp(argv[i], "-f") || !strcmp(argv[i], "-g")) {
+ foreground = TRUE;
+ break;
+ }
+ i++;
+ }
+
+ if (foreground) {
+ /* run in console window */
+ exit(main(argc, argv, envp));
+ } else {
+ /* Start up as service */
+ char *SERVICE_NAME = BIND_SERVICE_NAME;
+
+ SERVICE_TABLE_ENTRY dispatchTable[] = {
+ { TEXT(SERVICE_NAME), (LPSERVICE_MAIN_FUNCTION)main },
+ { NULL, NULL }
+ };
+
+ rc = StartServiceCtrlDispatcher(dispatchTable);
+ if (!rc) {
+ fprintf(stderr, "Use -f to run from the command line.\n");
+ exit(GetLastError());
+ }
+ }
+ exit(0);
+}
+
+/*
+ * Initialize the Service by registering it.
+ */
+void
+ntservice_init() {
+ if (!foreground) {
+ /* Register handler with the SCM */
+ hServiceStatus = RegisterServiceCtrlHandler(BIND_SERVICE_NAME,
+ (LPHANDLER_FUNCTION)ServiceControl);
+ if (!hServiceStatus) {
+ ns_main_earlyfatal(
+ "could not register service control handler");
+ UpdateSCM(SERVICE_STOPPED);
+ exit(1);
+ }
+ UpdateSCM(SERVICE_RUNNING);
+ } else {
+ strcpy(ConsoleTitle, "BIND Version ");
+ strcat(ConsoleTitle, VERSION);
+ SetConsoleTitle(ConsoleTitle);
+ }
+}
+
+void
+ntservice_shutdown() {
+ UpdateSCM(SERVICE_STOPPED);
+}
+/*
+ * Routine to check if this is a service or a foreground program
+ */
+BOOL
+ntservice_isservice() {
+ return(!foreground);
+}
+/*
+ * ServiceControl(): Handles requests from the SCM and passes them on
+ * to named.
+ */
+void
+ServiceControl(DWORD dwCtrlCode) {
+ /* Handle the requested control code */
+ switch(dwCtrlCode) {
+ case SERVICE_CONTROL_INTERROGATE:
+ UpdateSCM(0);
+ break;
+
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ ns_server_flushonshutdown(ns_g_server, ISC_TRUE);
+ isc_app_shutdown();
+ UpdateSCM(SERVICE_STOPPED);
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Tell the Service Control Manager the state of the service.
+ */
+void UpdateSCM(DWORD state) {
+ SERVICE_STATUS ss;
+ static DWORD dwState = SERVICE_STOPPED;
+
+ if (hServiceStatus) {
+ if (state)
+ dwState = state;
+
+ memset(&ss, 0, sizeof(SERVICE_STATUS));
+ ss.dwServiceType |= SERVICE_WIN32_OWN_PROCESS;
+ ss.dwCurrentState = dwState;
+ ss.dwControlsAccepted = SERVICE_ACCEPT_STOP |
+ SERVICE_ACCEPT_SHUTDOWN;
+ ss.dwCheckPoint = 0;
+ ss.dwServiceSpecificExitCode = 0;
+ ss.dwWin32ExitCode = NO_ERROR;
+ ss.dwWaitHint = dwState == SERVICE_STOP_PENDING ? 10000 : 1000;
+
+ if (!SetServiceStatus(hServiceStatus, &ss)) {
+ ss.dwCurrentState = SERVICE_STOPPED;
+ SetServiceStatus(hServiceStatus, &ss);
+ }
+ }
+}
+
+/*
+ * C-runtime stuff used to initialize the app and
+ * get argv, argc, envp.
+ */
+
+typedef struct
+{
+ int newmode;
+} _startupinfo;
+
+_CRTIMP void __cdecl __set_app_type(int);
+_CRTIMP void __cdecl __getmainargs(int *, char ***, char ***, int,
+ _startupinfo *);
+void __cdecl _setargv(void);
+
+#ifdef _M_IX86
+/* Pentium FDIV adjustment */
+extern int _adjust_fdiv;
+extern int * _imp___adjust_fdiv;
+/* Floating point precision */
+extern void _setdefaultprecision();
+#endif
+
+extern int _newmode; /* malloc new() handler mode */
+extern int _dowildcard; /* passed to __getmainargs() */
+
+typedef void (__cdecl *_PVFV)(void);
+extern void __cdecl _initterm(_PVFV *, _PVFV *);
+extern _PVFV *__onexitbegin;
+extern _PVFV *__onexitend;
+extern _CRTIMP char **__initenv;
+
+/*
+ * Do the work that mainCRTStartup() would normally do
+ */
+void GetArgs(int *argc, char ***argv, char ***envp)
+{
+ _startupinfo startinfo;
+
+ /*
+ * Set the app type to Console (check CRT/SRC/INTERNAL.H:
+ * \#define _CONSOLE_APP 1)
+ */
+ __set_app_type(1);
+
+ /* Mark this module as an EXE file */
+ __onexitbegin = __onexitend = (_PVFV *)(-1);
+
+ startinfo.newmode = _newmode;
+ __getmainargs(argc, argv, envp, _dowildcard, &startinfo);
+ __initenv = *envp;
+
+#ifdef _M_IX86
+ _adjust_fdiv = * _imp___adjust_fdiv;
+ _setdefaultprecision();
+#endif
+}
diff --git a/bin/named/win32/os.c b/bin/named/win32/os.c
new file mode 100644
index 0000000..4df4443
--- /dev/null
+++ b/bin/named/win32/os.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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.31 2008/11/17 05:41:10 marka Exp $ */
+
+#include <config.h>
+#include <stdarg.h>
+
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <io.h>
+#include <process.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/ntpaths.h>
+#include <isc/util.h>
+#include <isc/win32os.h>
+
+#include <named/main.h>
+#include <named/log.h>
+#include <named/os.h>
+#include <named/globals.h>
+#include <named/ntservice.h>
+
+
+static char *pidfile = NULL;
+static int devnullfd = -1;
+
+static BOOL Initialized = FALSE;
+
+static char *version_error =
+ "named requires Windows 2000 Service Pack 2 or later to run correctly";
+
+void
+ns_paths_init() {
+ if (!Initialized)
+ isc_ntpaths_init();
+
+ ns_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH);
+ lwresd_g_conffile = isc_ntpaths_get(LWRES_CONF_PATH);
+ lwresd_g_resolvconffile = isc_ntpaths_get(RESOLV_CONF_PATH);
+ ns_g_conffile = isc_ntpaths_get(NAMED_CONF_PATH);
+ ns_g_defaultpidfile = isc_ntpaths_get(NAMED_PID_PATH);
+ lwresd_g_defaultpidfile = isc_ntpaths_get(LWRESD_PID_PATH);
+ ns_g_keyfile = isc_ntpaths_get(RNDC_KEY_PATH);
+
+ Initialized = TRUE;
+}
+
+/*
+ * Due to Knowledge base article Q263823 we need to make sure that
+ * Windows 2000 systems have Service Pack 2 or later installed and
+ * warn when it isn't.
+ */
+static void
+version_check(const char *progname) {
+
+ if(isc_win32os_majorversion() < 5)
+ return; /* No problem with Version 4.0 */
+ if(isc_win32os_versioncheck(5, 0, 2, 0) < 0)
+ if (ntservice_isservice())
+ NTReportError(progname, version_error);
+ else
+ fprintf(stderr, "%s\n", version_error);
+}
+
+static void
+setup_syslog(const char *progname) {
+ int options;
+
+ options = LOG_PID;
+#ifdef LOG_NDELAY
+ options |= LOG_NDELAY;
+#endif
+
+ openlog(progname, options, LOG_DAEMON);
+}
+
+void
+ns_os_init(const char *progname) {
+ ns_paths_init();
+ setup_syslog(progname);
+ /*
+ * XXXMPA. We may need to split ntservice_init() in two and
+ * just mark as running in ns_os_started(). If we do that
+ * this is where the first part of ntservice_init() should be
+ * called from.
+ *
+ * XXX970 Remove comment if no problems by 9.7.0.
+ *
+ * ntservice_init();
+ */
+ version_check(progname);
+}
+
+void
+ns_os_daemonize(void) {
+ /*
+ * Try to set stdin, stdout, and stderr to /dev/null, but press
+ * on even if it fails.
+ */
+ if (devnullfd != -1) {
+ if (devnullfd != _fileno(stdin)) {
+ close(_fileno(stdin));
+ (void)_dup2(devnullfd, _fileno(stdin));
+ }
+ if (devnullfd != _fileno(stdout)) {
+ close(_fileno(stdout));
+ (void)_dup2(devnullfd, _fileno(stdout));
+ }
+ if (devnullfd != _fileno(stderr)) {
+ close(_fileno(stderr));
+ (void)_dup2(devnullfd, _fileno(stderr));
+ }
+ }
+}
+
+void
+ns_os_opendevnull(void) {
+ devnullfd = open("NUL", O_RDWR, 0);
+}
+
+void
+ns_os_closedevnull(void) {
+ if (devnullfd != _fileno(stdin) &&
+ devnullfd != _fileno(stdout) &&
+ devnullfd != _fileno(stderr)) {
+ close(devnullfd);
+ devnullfd = -1;
+ }
+}
+
+void
+ns_os_chroot(const char *root) {
+ if (root != NULL)
+ ns_main_earlyfatal("chroot(): isn't supported by Win32 API");
+}
+
+void
+ns_os_inituserinfo(const char *username) {
+}
+
+void
+ns_os_changeuser(void) {
+}
+
+void
+ns_os_adjustnofile(void) {
+}
+
+void
+ns_os_minprivs(void) {
+}
+
+static int
+safe_open(const char *filename, isc_boolean_t append) {
+ int fd;
+ struct stat sb;
+
+ if (stat(filename, &sb) == -1) {
+ if (errno != ENOENT)
+ return (-1);
+ } else if ((sb.st_mode & S_IFREG) == 0)
+ return (-1);
+
+ if (append)
+ fd = open(filename, O_WRONLY|O_CREAT|O_APPEND,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ else {
+ (void)unlink(filename);
+ fd = open(filename, O_WRONLY|O_CREAT|O_EXCL,
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ }
+ return (fd);
+}
+
+static void
+cleanup_pidfile(void) {
+ if (pidfile != NULL) {
+ (void)unlink(pidfile);
+ free(pidfile);
+ }
+ pidfile = NULL;
+}
+
+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 *, ...);
+
+ /*
+ * The caller must ensure any required synchronization.
+ */
+
+ report = first_time ? ns_main_earlyfatal : ns_main_earlywarning;
+
+ cleanup_pidfile();
+
+ if (filename == NULL)
+ return;
+ len = strlen(filename);
+ pidfile = malloc(len + 1);
+ if (pidfile == NULL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ (*report)("couldn't malloc '%s': %s", filename, strbuf);
+ return;
+ }
+ /* This is safe. */
+ strcpy(pidfile, filename);
+
+ 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");
+ 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;
+ }
+
+ pid = getpid();
+
+ if (fprintf(lockfile, "%ld\n", (long)pid) < 0) {
+ (*report)("fprintf() to pid file '%s' failed", filename);
+ (void)fclose(lockfile);
+ cleanup_pidfile();
+ return;
+ }
+ if (fflush(lockfile) == EOF) {
+ (*report)("fflush() to pid file '%s' failed", filename);
+ (void)fclose(lockfile);
+ cleanup_pidfile();
+ return;
+ }
+ (void)fclose(lockfile);
+}
+
+void
+ns_os_shutdown(void) {
+ closelog();
+ cleanup_pidfile();
+ ntservice_shutdown(); /* This MUST be the last thing done */
+}
+
+isc_result_t
+ns_os_gethostname(char *buf, size_t len) {
+ int n;
+
+ n = gethostname(buf, len);
+ return ((n == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE);
+}
+
+void
+ns_os_shutdownmsg(char *command, isc_buffer_t *text) {
+ UNUSED(command);
+ UNUSED(text);
+}
+
+void
+ns_os_tzset(void) {
+#ifdef HAVE_TZSET
+ tzset();
+#endif
+}
+
+void
+ns_os_started(void) {
+ ntservice_init();
+}
diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c
new file mode 100644
index 0000000..55b19f0
--- /dev/null
+++ b/bin/named/xfrout.c
@@ -0,0 +1,1842 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: xfrout.c,v 1.131 2008/10/29 02:54:20 marka Exp $ */
+
+#include <config.h>
+
+#include <isc/formatcheck.h>
+#include <isc/mem.h>
+#include <isc/timer.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#ifdef DLZ
+#include <dns/dlz.h>
+#endif
+#include <dns/fixedname.h>
+#include <dns/journal.h>
+#include <dns/message.h>
+#include <dns/peer.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+#include <dns/soa.h>
+#include <dns/stats.h>
+#include <dns/timer.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#include <named/client.h>
+#include <named/log.h>
+#include <named/server.h>
+#include <named/xfrout.h>
+
+/*! \file
+ * \brief
+ * Outgoing AXFR and IXFR.
+ */
+
+/*
+ * TODO:
+ * - IXFR over UDP
+ */
+
+#define XFROUT_COMMON_LOGARGS \
+ ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
+
+#define XFROUT_PROTOCOL_LOGARGS \
+ XFROUT_COMMON_LOGARGS, ISC_LOG_INFO
+
+#define XFROUT_DEBUG_LOGARGS(n) \
+ XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
+
+#define XFROUT_RR_LOGARGS \
+ XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL
+
+#define XFROUT_RR_LOGLEVEL ISC_LOG_DEBUG(8)
+
+/*%
+ * Fail unconditionally and log as a client error.
+ * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+#define FAILC(code, msg) \
+ do { \
+ result = (code); \
+ ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
+ NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
+ "bad zone transfer request: %s (%s)", \
+ msg, isc_result_totext(code)); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+#define FAILQ(code, msg, question, rdclass) \
+ do { \
+ char _buf1[DNS_NAME_FORMATSIZE]; \
+ char _buf2[DNS_RDATACLASS_FORMATSIZE]; \
+ result = (code); \
+ dns_name_format(question, _buf1, sizeof(_buf1)); \
+ dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \
+ ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
+ NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
+ "bad zone transfer request: '%s/%s': %s (%s)", \
+ _buf1, _buf2, msg, isc_result_totext(code)); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } 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, dns_statscounter_t counter) {
+ dns_generalstats_increment(ns_g_server->nsstats, counter);
+ if (zone != NULL) {
+ dns_stats_t *zonestats = dns_zone_getrequeststats(zone);
+ if (zonestats != NULL)
+ dns_generalstats_increment(zonestats, 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) */
+
+static void
+log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) {
+ isc_result_t result;
+ isc_buffer_t buf;
+ char mem[2000];
+ dns_rdatalist_t rdl;
+ dns_rdataset_t rds;
+ dns_rdata_t rd = DNS_RDATA_INIT;
+
+ rdl.type = rdata->type;
+ rdl.rdclass = rdata->rdclass;
+ rdl.ttl = ttl;
+ if (rdata->type == dns_rdatatype_sig ||
+ rdata->type == dns_rdatatype_rrsig)
+ rdl.covers = dns_rdata_covers(rdata);
+ else
+ rdl.covers = dns_rdatatype_none;
+ ISC_LIST_INIT(rdl.rdata);
+ ISC_LINK_INIT(&rdl, link);
+ dns_rdataset_init(&rds);
+ dns_rdata_init(&rd);
+ dns_rdata_clone(rdata, &rd);
+ ISC_LIST_APPEND(rdl.rdata, &rd, link);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
+
+ isc_buffer_init(&buf, mem, sizeof(mem));
+ result = dns_rdataset_totext(&rds, name,
+ ISC_FALSE, ISC_FALSE, &buf);
+
+ /*
+ * We could use xfrout_log(), but that would produce
+ * very long lines with a repetitive prefix.
+ */
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Get rid of final newline.
+ */
+ INSIST(buf.used >= 1 &&
+ ((char *) buf.base)[buf.used - 1] == '\n');
+ buf.used--;
+
+ isc_log_write(XFROUT_RR_LOGARGS, "%.*s",
+ (int)isc_buffer_usedlength(&buf),
+ (char *)isc_buffer_base(&buf));
+ } else {
+ isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
+ }
+}
+
+/**************************************************************************/
+/*
+ * An 'rrstream_t' is a polymorphic iterator that returns
+ * a stream of resource records. There are multiple implementations,
+ * e.g. for generating AXFR and IXFR records streams.
+ */
+
+typedef struct rrstream_methods rrstream_methods_t;
+
+typedef struct rrstream {
+ isc_mem_t *mctx;
+ rrstream_methods_t *methods;
+} rrstream_t;
+
+struct rrstream_methods {
+ isc_result_t (*first)(rrstream_t *);
+ isc_result_t (*next)(rrstream_t *);
+ void (*current)(rrstream_t *,
+ dns_name_t **,
+ isc_uint32_t *,
+ dns_rdata_t **);
+ void (*pause)(rrstream_t *);
+ void (*destroy)(rrstream_t **);
+};
+
+static void
+rrstream_noop_pause(rrstream_t *rs) {
+ UNUSED(rs);
+}
+
+/**************************************************************************/
+/*
+ * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
+ * an IXFR-like RR stream from a journal file.
+ *
+ * The SOA at the beginning of each sequence of additions
+ * or deletions are included in the stream, but the extra
+ * SOAs at the beginning and end of the entire transfer are
+ * not included.
+ */
+
+typedef struct ixfr_rrstream {
+ rrstream_t common;
+ dns_journal_t *journal;
+} ixfr_rrstream_t;
+
+/* Forward declarations. */
+static void
+ixfr_rrstream_destroy(rrstream_t **sp);
+
+static rrstream_methods_t ixfr_rrstream_methods;
+
+/*
+ * Returns: anything dns_journal_open() or dns_journal_iter_init()
+ * may return.
+ */
+
+static isc_result_t
+ixfr_rrstream_create(isc_mem_t *mctx,
+ const char *journal_filename,
+ isc_uint32_t begin_serial,
+ isc_uint32_t end_serial,
+ rrstream_t **sp)
+{
+ ixfr_rrstream_t *s;
+ isc_result_t result;
+
+ INSIST(sp != NULL && *sp == NULL);
+
+ s = isc_mem_get(mctx, sizeof(*s));
+ if (s == NULL)
+ return (ISC_R_NOMEMORY);
+ s->common.mctx = mctx;
+ s->common.methods = &ixfr_rrstream_methods;
+ s->journal = NULL;
+
+ CHECK(dns_journal_open(mctx, journal_filename,
+ ISC_FALSE, &s->journal));
+ CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
+
+ *sp = (rrstream_t *) s;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ ixfr_rrstream_destroy((rrstream_t **) (void *)&s);
+ return (result);
+}
+
+static isc_result_t
+ixfr_rrstream_first(rrstream_t *rs) {
+ ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
+ return (dns_journal_first_rr(s->journal));
+}
+
+static isc_result_t
+ixfr_rrstream_next(rrstream_t *rs) {
+ ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
+ return (dns_journal_next_rr(s->journal));
+}
+
+static void
+ixfr_rrstream_current(rrstream_t *rs,
+ dns_name_t **name, isc_uint32_t *ttl,
+ dns_rdata_t **rdata)
+{
+ ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
+ dns_journal_current_rr(s->journal, name, ttl, rdata);
+}
+
+static void
+ixfr_rrstream_destroy(rrstream_t **rsp) {
+ ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp;
+ if (s->journal != 0)
+ dns_journal_destroy(&s->journal);
+ isc_mem_put(s->common.mctx, s, sizeof(*s));
+}
+
+static rrstream_methods_t ixfr_rrstream_methods = {
+ ixfr_rrstream_first,
+ ixfr_rrstream_next,
+ ixfr_rrstream_current,
+ rrstream_noop_pause,
+ ixfr_rrstream_destroy
+};
+
+/**************************************************************************/
+/*
+ * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
+ * an AXFR-like RR stream from a database.
+ *
+ * The SOAs at the beginning and end of the transfer are
+ * not included in the stream.
+ */
+
+typedef struct axfr_rrstream {
+ rrstream_t common;
+ db_rr_iterator_t it;
+ isc_boolean_t it_valid;
+} axfr_rrstream_t;
+
+/*
+ * Forward declarations.
+ */
+static void
+axfr_rrstream_destroy(rrstream_t **rsp);
+
+static rrstream_methods_t axfr_rrstream_methods;
+
+static isc_result_t
+axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
+ rrstream_t **sp)
+{
+ axfr_rrstream_t *s;
+ isc_result_t result;
+
+ INSIST(sp != NULL && *sp == NULL);
+
+ s = isc_mem_get(mctx, sizeof(*s));
+ if (s == NULL)
+ return (ISC_R_NOMEMORY);
+ s->common.mctx = mctx;
+ s->common.methods = &axfr_rrstream_methods;
+ s->it_valid = ISC_FALSE;
+
+ CHECK(db_rr_iterator_init(&s->it, db, ver, 0));
+ s->it_valid = ISC_TRUE;
+
+ *sp = (rrstream_t *) s;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ axfr_rrstream_destroy((rrstream_t **) (void *)&s);
+ return (result);
+}
+
+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);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ /* Skip SOA records. */
+ for (;;) {
+ 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);
+ if (rdata->type != dns_rdatatype_soa)
+ break;
+ result = db_rr_iterator_next(&s->it);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ return (result);
+}
+
+static isc_result_t
+axfr_rrstream_next(rrstream_t *rs) {
+ axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
+ isc_result_t result;
+
+ /* Skip SOA records. */
+ for (;;) {
+ dns_name_t *name_dummy = NULL;
+ isc_uint32_t ttl_dummy;
+ dns_rdata_t *rdata = NULL;
+ result = db_rr_iterator_next(&s->it);
+ if (result != ISC_R_SUCCESS)
+ break;
+ db_rr_iterator_current(&s->it, &name_dummy,
+ &ttl_dummy, &rdata);
+ if (rdata->type != dns_rdatatype_soa)
+ break;
+ }
+ return (result);
+}
+
+static void
+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);
+}
+
+static void
+axfr_rrstream_pause(rrstream_t *rs) {
+ axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
+ db_rr_iterator_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);
+ isc_mem_put(s->common.mctx, s, sizeof(*s));
+}
+
+static rrstream_methods_t axfr_rrstream_methods = {
+ axfr_rrstream_first,
+ axfr_rrstream_next,
+ axfr_rrstream_current,
+ axfr_rrstream_pause,
+ axfr_rrstream_destroy
+};
+
+/**************************************************************************/
+/*
+ * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
+ * a single SOA record.
+ */
+
+typedef struct soa_rrstream {
+ rrstream_t common;
+ dns_difftuple_t *soa_tuple;
+} soa_rrstream_t;
+
+/*
+ * Forward declarations.
+ */
+static void
+soa_rrstream_destroy(rrstream_t **rsp);
+
+static rrstream_methods_t soa_rrstream_methods;
+
+static isc_result_t
+soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
+ rrstream_t **sp)
+{
+ soa_rrstream_t *s;
+ isc_result_t result;
+
+ INSIST(sp != NULL && *sp == NULL);
+
+ s = isc_mem_get(mctx, sizeof(*s));
+ if (s == NULL)
+ return (ISC_R_NOMEMORY);
+ s->common.mctx = mctx;
+ s->common.methods = &soa_rrstream_methods;
+ s->soa_tuple = NULL;
+
+ CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
+ &s->soa_tuple));
+
+ *sp = (rrstream_t *) s;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ soa_rrstream_destroy((rrstream_t **) (void *)&s);
+ return (result);
+}
+
+static isc_result_t
+soa_rrstream_first(rrstream_t *rs) {
+ UNUSED(rs);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+soa_rrstream_next(rrstream_t *rs) {
+ UNUSED(rs);
+ return (ISC_R_NOMORE);
+}
+
+static void
+soa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
+ dns_rdata_t **rdata)
+{
+ soa_rrstream_t *s = (soa_rrstream_t *) rs;
+ *name = &s->soa_tuple->name;
+ *ttl = s->soa_tuple->ttl;
+ *rdata = &s->soa_tuple->rdata;
+}
+
+static void
+soa_rrstream_destroy(rrstream_t **rsp) {
+ soa_rrstream_t *s = (soa_rrstream_t *) *rsp;
+ if (s->soa_tuple != NULL)
+ dns_difftuple_free(&s->soa_tuple);
+ isc_mem_put(s->common.mctx, s, sizeof(*s));
+}
+
+static rrstream_methods_t soa_rrstream_methods = {
+ soa_rrstream_first,
+ soa_rrstream_next,
+ soa_rrstream_current,
+ rrstream_noop_pause,
+ soa_rrstream_destroy
+};
+
+/**************************************************************************/
+/*
+ * A 'compound_rrstream_t' objects owns a soa_rrstream
+ * and another rrstream, the "data stream". It returns
+ * a concatenated stream consisting of the soa_rrstream, then
+ * the data stream, then the soa_rrstream again.
+ *
+ * The component streams are owned by the compound_rrstream_t
+ * and are destroyed with it.
+ */
+
+typedef struct compound_rrstream {
+ rrstream_t common;
+ rrstream_t *components[3];
+ int state;
+ isc_result_t result;
+} compound_rrstream_t;
+
+/*
+ * Forward declarations.
+ */
+static void
+compound_rrstream_destroy(rrstream_t **rsp);
+
+static isc_result_t
+compound_rrstream_next(rrstream_t *rs);
+
+static rrstream_methods_t compound_rrstream_methods;
+
+/*
+ * Requires:
+ * soa_stream != NULL && *soa_stream != NULL
+ * data_stream != NULL && *data_stream != NULL
+ * sp != NULL && *sp == NULL
+ *
+ * Ensures:
+ * *soa_stream == NULL
+ * *data_stream == NULL
+ * *sp points to a valid compound_rrstream_t
+ * The soa and data streams will be destroyed
+ * when the compound_rrstream_t is destroyed.
+ */
+static isc_result_t
+compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
+ rrstream_t **data_stream, rrstream_t **sp)
+{
+ compound_rrstream_t *s;
+
+ INSIST(sp != NULL && *sp == NULL);
+
+ s = isc_mem_get(mctx, sizeof(*s));
+ if (s == NULL)
+ return (ISC_R_NOMEMORY);
+ s->common.mctx = mctx;
+ s->common.methods = &compound_rrstream_methods;
+ s->components[0] = *soa_stream;
+ s->components[1] = *data_stream;
+ s->components[2] = *soa_stream;
+ s->state = -1;
+ s->result = ISC_R_FAILURE;
+
+ *soa_stream = NULL;
+ *data_stream = NULL;
+ *sp = (rrstream_t *) s;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+compound_rrstream_first(rrstream_t *rs) {
+ compound_rrstream_t *s = (compound_rrstream_t *) rs;
+ s->state = 0;
+ do {
+ rrstream_t *curstream = s->components[s->state];
+ s->result = curstream->methods->first(curstream);
+ } while (s->result == ISC_R_NOMORE && s->state < 2);
+ return (s->result);
+}
+
+static isc_result_t
+compound_rrstream_next(rrstream_t *rs) {
+ compound_rrstream_t *s = (compound_rrstream_t *) rs;
+ rrstream_t *curstream = s->components[s->state];
+ s->result = curstream->methods->next(curstream);
+ while (s->result == ISC_R_NOMORE) {
+ /*
+ * Make sure locks held by the current stream
+ * are released before we switch streams.
+ */
+ curstream->methods->pause(curstream);
+ if (s->state == 2)
+ return (ISC_R_NOMORE);
+ s->state++;
+ curstream = s->components[s->state];
+ s->result = curstream->methods->first(curstream);
+ }
+ return (s->result);
+}
+
+static void
+compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
+ dns_rdata_t **rdata)
+{
+ compound_rrstream_t *s = (compound_rrstream_t *) rs;
+ rrstream_t *curstream;
+ INSIST(0 <= s->state && s->state < 3);
+ INSIST(s->result == ISC_R_SUCCESS);
+ curstream = s->components[s->state];
+ curstream->methods->current(curstream, name, ttl, rdata);
+}
+
+static void
+compound_rrstream_pause(rrstream_t *rs)
+{
+ compound_rrstream_t *s = (compound_rrstream_t *) rs;
+ rrstream_t *curstream;
+ INSIST(0 <= s->state && s->state < 3);
+ curstream = s->components[s->state];
+ curstream->methods->pause(curstream);
+}
+
+static void
+compound_rrstream_destroy(rrstream_t **rsp) {
+ compound_rrstream_t *s = (compound_rrstream_t *) *rsp;
+ s->components[0]->methods->destroy(&s->components[0]);
+ s->components[1]->methods->destroy(&s->components[1]);
+ s->components[2] = NULL; /* Copy of components[0]. */
+ isc_mem_put(s->common.mctx, s, sizeof(*s));
+}
+
+static rrstream_methods_t compound_rrstream_methods = {
+ compound_rrstream_first,
+ compound_rrstream_next,
+ compound_rrstream_current,
+ compound_rrstream_pause,
+ compound_rrstream_destroy
+};
+
+/**************************************************************************/
+/*
+ * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR
+ * in progress.
+ */
+
+typedef struct {
+ isc_mem_t *mctx;
+ ns_client_t *client;
+ unsigned int id; /* ID of request */
+ dns_name_t *qname; /* Question name of request */
+ dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */
+ dns_rdataclass_t qclass;
+ dns_zone_t *zone; /* (necessary for stats) */
+ dns_db_t *db;
+ dns_dbversion_t *ver;
+ isc_quota_t *quota;
+ rrstream_t *stream; /* The XFR RR stream */
+ isc_boolean_t end_of_stream; /* EOS has been reached */
+ isc_buffer_t buf; /* Buffer for message owner
+ names and rdatas */
+ isc_buffer_t txlenbuf; /* Transmit length buffer */
+ isc_buffer_t txbuf; /* Transmit message buffer */
+ void *txmem;
+ unsigned int txmemlen;
+ unsigned int nmsg; /* Number of messages sent */
+ dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
+ isc_buffer_t *lasttsig; /* the last TSIG */
+ isc_boolean_t many_answers;
+ int sends; /* Send in progress */
+ isc_boolean_t shuttingdown;
+ const char *mnemonic; /* Style of transfer */
+} xfrout_ctx_t;
+
+static isc_result_t
+xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
+ unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
+ dns_rdataclass_t qclass, dns_zone_t *zone,
+ dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
+ rrstream_t *stream, dns_tsigkey_t *tsigkey,
+ isc_buffer_t *lasttsig,
+ unsigned int maxtime,
+ unsigned int idletime,
+ isc_boolean_t many_answers,
+ xfrout_ctx_t **xfrp);
+
+static void
+sendstream(xfrout_ctx_t *xfr);
+
+static void
+xfrout_senddone(isc_task_t *task, isc_event_t *event);
+
+static void
+xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
+
+static void
+xfrout_maybe_destroy(xfrout_ctx_t *xfr);
+
+static void
+xfrout_ctx_destroy(xfrout_ctx_t **xfrp);
+
+static void
+xfrout_client_shutdown(void *arg, isc_result_t result);
+
+static void
+xfrout_log1(ns_client_t *client, dns_name_t *zonename,
+ dns_rdataclass_t rdclass, int level,
+ const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
+
+static void
+xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+/**************************************************************************/
+
+void
+ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
+ isc_result_t result;
+ dns_name_t *question_name;
+ dns_rdataset_t *question_rdataset;
+ dns_zone_t *zone = NULL;
+ dns_db_t *db = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_rdataclass_t question_class;
+ rrstream_t *soa_stream = NULL;
+ rrstream_t *data_stream = NULL;
+ rrstream_t *stream = NULL;
+ dns_difftuple_t *current_soa_tuple = NULL;
+ dns_name_t *soa_name;
+ dns_rdataset_t *soa_rdataset;
+ dns_rdata_t soa_rdata = DNS_RDATA_INIT;
+ isc_boolean_t have_soa = ISC_FALSE;
+ const char *mnemonic = NULL;
+ isc_mem_t *mctx = client->mctx;
+ dns_message_t *request = client->message;
+ xfrout_ctx_t *xfr = NULL;
+ isc_quota_t *quota = NULL;
+ dns_transfer_format_t format = client->view->transfer_format;
+ isc_netaddr_t na;
+ dns_peer_t *peer = NULL;
+ isc_buffer_t *tsigbuf = NULL;
+ char *journalfile;
+ char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
+ char keyname[DNS_NAME_FORMATSIZE];
+ isc_boolean_t is_poll = ISC_FALSE;
+#ifdef DLZ
+ isc_boolean_t is_dlz = ISC_FALSE;
+#endif
+
+ switch (reqtype) {
+ case dns_rdatatype_axfr:
+ mnemonic = "AXFR";
+ break;
+ case dns_rdatatype_ixfr:
+ mnemonic = "IXFR";
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+
+ ns_client_log(client,
+ DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
+ ISC_LOG_DEBUG(6), "%s request", mnemonic);
+ /*
+ * Apply quota.
+ */
+ result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
+ "%s request denied: %s", mnemonic,
+ isc_result_totext(result));
+ goto failure;
+ }
+
+ /*
+ * Interpret the question section.
+ */
+ result = dns_message_firstname(request, DNS_SECTION_QUESTION);
+ INSIST(result == ISC_R_SUCCESS);
+
+ /*
+ * The question section must contain exactly one question, and
+ * it must be for AXFR/IXFR as appropriate.
+ */
+ question_name = NULL;
+ dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
+ question_rdataset = ISC_LIST_HEAD(question_name->list);
+ question_class = question_rdataset->rdclass;
+ INSIST(question_rdataset->type == reqtype);
+ if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
+ FAILC(DNS_R_FORMERR, "multiple questions");
+ result = dns_message_nextname(request, DNS_SECTION_QUESTION);
+ if (result != ISC_R_NOMORE)
+ FAILC(DNS_R_FORMERR, "multiple questions");
+
+ result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
+ &zone);
+
+ if (result != ISC_R_SUCCESS)
+#ifdef DLZ
+ {
+ /*
+ * Normal zone table does not have a match. Try the DLZ database
+ */
+ if (client->view->dlzdatabase != NULL) {
+ result = dns_dlzallowzonexfr(client->view,
+ question_name, &client->peeraddr,
+ &db);
+
+ if (result == ISC_R_NOPERM) {
+ char _buf1[DNS_NAME_FORMATSIZE];
+ char _buf2[DNS_RDATACLASS_FORMATSIZE];
+
+ result = DNS_R_REFUSED;
+ dns_name_format(question_name, _buf1,
+ sizeof(_buf1));
+ dns_rdataclass_format(question_class,
+ _buf2, sizeof(_buf2));
+ ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_XFER_OUT,
+ ISC_LOG_ERROR,
+ "zone transfer '%s/%s' denied",
+ _buf1, _buf2);
+ goto failure;
+ }
+ if (result != ISC_R_SUCCESS)
+#endif
+ FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
+ question_name, question_class);
+#ifdef DLZ
+ is_dlz = ISC_TRUE;
+ /*
+ * DLZ only support full zone transfer, not incremental
+ */
+ if (reqtype != dns_rdatatype_axfr) {
+ mnemonic = "AXFR-style IXFR";
+ reqtype = dns_rdatatype_axfr;
+ }
+
+ } else {
+ /*
+ * not DLZ and not in normal zone table, we are
+ * not authoritative
+ */
+ FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
+ question_name, question_class);
+ }
+ } else {
+ /* zone table has a match */
+#endif
+ switch(dns_zone_gettype(zone)) {
+ case dns_zone_master:
+ case dns_zone_slave:
+ break; /* Master and slave zones are OK for transfer. */
+ default:
+ FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class);
+ }
+ CHECK(dns_zone_getdb(zone, &db));
+ dns_db_currentversion(db, &ver);
+#ifdef DLZ
+ }
+#endif
+
+ xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
+ "%s question section OK", mnemonic);
+
+ /*
+ * Check the authority section. Look for a SOA record with
+ * the same name and class as the question.
+ */
+ for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
+ {
+ soa_name = NULL;
+ dns_message_currentname(request, DNS_SECTION_AUTHORITY,
+ &soa_name);
+
+ /*
+ * Ignore data whose owner name is not the zone apex.
+ */
+ if (! dns_name_equal(soa_name, question_name))
+ continue;
+
+ for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
+ soa_rdataset != NULL;
+ soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
+ {
+ /*
+ * Ignore non-SOA data.
+ */
+ if (soa_rdataset->type != dns_rdatatype_soa)
+ continue;
+ if (soa_rdataset->rdclass != question_class)
+ continue;
+
+ CHECK(dns_rdataset_first(soa_rdataset));
+ dns_rdataset_current(soa_rdataset, &soa_rdata);
+ result = dns_rdataset_next(soa_rdataset);
+ if (result == ISC_R_SUCCESS)
+ FAILC(DNS_R_FORMERR,
+ "IXFR authority section "
+ "has multiple SOAs");
+ have_soa = ISC_TRUE;
+ goto got_soa;
+ }
+ }
+ got_soa:
+ if (result != ISC_R_NOMORE)
+ CHECK(result);
+
+ xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
+ "%s authority section OK", mnemonic);
+
+ /*
+ * Decide whether to allow this transfer.
+ */
+#ifdef DLZ
+ /*
+ * if not a DLZ zone decide whether to allow this transfer.
+ */
+ if (!is_dlz) {
+#endif
+ ns_client_aclmsg("zone transfer", question_name, reqtype,
+ client->view->rdclass, msg, sizeof(msg));
+ CHECK(ns_client_checkacl(client, NULL, msg,
+ dns_zone_getxfracl(zone),
+ ISC_TRUE, ISC_LOG_ERROR));
+#ifdef DLZ
+ }
+#endif
+
+ /*
+ * AXFR over UDP is not possible.
+ */
+ if (reqtype == dns_rdatatype_axfr &&
+ (client->attributes & NS_CLIENTATTR_TCP) == 0)
+ FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
+
+ /*
+ * Look up the requesting server in the peer table.
+ */
+ isc_netaddr_fromsockaddr(&na, &client->peeraddr);
+ (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
+
+ /*
+ * Decide on the transfer format (one-answer or many-answers).
+ */
+ if (peer != NULL)
+ (void)dns_peer_gettransferformat(peer, &format);
+
+ /*
+ * Get a dynamically allocated copy of the current SOA.
+ */
+#ifdef DLZ
+ if (is_dlz)
+ dns_db_currentversion(db, &ver);
+#endif
+ CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
+ &current_soa_tuple));
+
+ if (reqtype == dns_rdatatype_ixfr) {
+ isc_uint32_t begin_serial, current_serial;
+ isc_boolean_t provide_ixfr;
+
+ /*
+ * Outgoing IXFR may have been disabled for this peer
+ * or globally.
+ */
+ provide_ixfr = client->view->provideixfr;
+ if (peer != NULL)
+ (void) dns_peer_getprovideixfr(peer, &provide_ixfr);
+ if (provide_ixfr == ISC_FALSE)
+ goto axfr_fallback;
+
+ if (! have_soa)
+ FAILC(DNS_R_FORMERR,
+ "IXFR request missing SOA");
+
+ begin_serial = dns_soa_getserial(&soa_rdata);
+ current_serial = dns_soa_getserial(&current_soa_tuple->rdata);
+
+ /*
+ * RFC1995 says "If an IXFR query with the same or
+ * newer version number than that of the server
+ * is received, it is replied to with a single SOA
+ * record of the server's current version, just as
+ * in AXFR". The claim about AXFR is incorrect,
+ * but other than that, we do as the RFC says.
+ *
+ * Sending a single SOA record is also how we refuse
+ * IXFR over UDP (currently, we always do).
+ */
+ if (DNS_SERIAL_GE(begin_serial, current_serial) ||
+ (client->attributes & NS_CLIENTATTR_TCP) == 0)
+ {
+ CHECK(soa_rrstream_create(mctx, db, ver, &stream));
+ is_poll = ISC_TRUE;
+ goto have_stream;
+ }
+ journalfile = dns_zone_getjournal(zone);
+ if (journalfile != NULL)
+ result = ixfr_rrstream_create(mctx,
+ journalfile,
+ begin_serial,
+ current_serial,
+ &data_stream);
+ else
+ result = ISC_R_NOTFOUND;
+ if (result == ISC_R_NOTFOUND ||
+ result == ISC_R_RANGE) {
+ xfrout_log1(client, question_name, question_class,
+ ISC_LOG_DEBUG(4),
+ "IXFR version not in journal, "
+ "falling back to AXFR");
+ mnemonic = "AXFR-style IXFR";
+ goto axfr_fallback;
+ }
+ CHECK(result);
+ } else {
+ axfr_fallback:
+ CHECK(axfr_rrstream_create(mctx, db, ver,
+ &data_stream));
+ }
+
+ /*
+ * Bracket the the data stream with SOAs.
+ */
+ CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
+ CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
+ &stream));
+ soa_stream = NULL;
+ data_stream = NULL;
+
+ have_stream:
+ CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
+ /*
+ * Create the xfrout context object. This transfers the ownership
+ * of "stream", "db", "ver", and "quota" to the xfrout context object.
+ */
+
+
+
+#ifdef DLZ
+ if (is_dlz)
+ CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
+ reqtype, question_class, zone, db, ver,
+ quota, stream,
+ dns_message_gettsigkey(request),
+ tsigbuf,
+ 3600,
+ 3600,
+ (format == dns_many_answers) ?
+ ISC_TRUE : ISC_FALSE,
+ &xfr));
+ else
+#endif
+ CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
+ reqtype, question_class, zone, db, ver,
+ quota, stream,
+ dns_message_gettsigkey(request),
+ tsigbuf,
+ dns_zone_getmaxxfrout(zone),
+ dns_zone_getidleout(zone),
+ (format == dns_many_answers) ?
+ ISC_TRUE : ISC_FALSE,
+ &xfr));
+
+ xfr->mnemonic = mnemonic;
+ stream = NULL;
+ quota = NULL;
+
+ CHECK(xfr->stream->methods->first(xfr->stream));
+
+ if (xfr->tsigkey != NULL) {
+ dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
+ } else
+ keyname[0] = '\0';
+ if (is_poll)
+ xfrout_log1(client, question_name, question_class,
+ ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
+ (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
+ else
+ xfrout_log1(client, question_name, question_class,
+ ISC_LOG_INFO, "%s started%s%s", mnemonic,
+ (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
+
+ /*
+ * Hand the context over to sendstream(). Set xfr to NULL;
+ * sendstream() is responsible for either passing the
+ * context on to a later event handler or destroying it.
+ */
+ sendstream(xfr);
+ xfr = NULL;
+
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (result == DNS_R_REFUSED)
+ inc_stats(zone, dns_nsstatscounter_xfrrej);
+ if (quota != NULL)
+ isc_quota_detach(&quota);
+ if (current_soa_tuple != NULL)
+ dns_difftuple_free(&current_soa_tuple);
+ if (stream != NULL)
+ stream->methods->destroy(&stream);
+ if (soa_stream != NULL)
+ soa_stream->methods->destroy(&soa_stream);
+ if (data_stream != NULL)
+ data_stream->methods->destroy(&data_stream);
+ if (ver != NULL)
+ dns_db_closeversion(db, &ver, ISC_FALSE);
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ /* XXX kludge */
+ if (xfr != NULL) {
+ xfrout_fail(xfr, result, "setting up zone transfer");
+ } else if (result != ISC_R_SUCCESS) {
+ ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
+ NS_LOGMODULE_XFER_OUT,
+ ISC_LOG_DEBUG(3), "zone transfer setup failed");
+ ns_client_error(client, result);
+ }
+}
+
+static isc_result_t
+xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
+ dns_name_t *qname, dns_rdatatype_t qtype,
+ dns_rdataclass_t qclass, dns_zone_t *zone,
+ dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
+ rrstream_t *stream, dns_tsigkey_t *tsigkey,
+ isc_buffer_t *lasttsig, unsigned int maxtime,
+ unsigned int idletime, isc_boolean_t many_answers,
+ xfrout_ctx_t **xfrp)
+{
+ xfrout_ctx_t *xfr;
+ isc_result_t result;
+ unsigned int len;
+ void *mem;
+
+ INSIST(xfrp != NULL && *xfrp == NULL);
+ xfr = isc_mem_get(mctx, sizeof(*xfr));
+ if (xfr == NULL)
+ return (ISC_R_NOMEMORY);
+ xfr->mctx = mctx;
+ xfr->client = NULL;
+ ns_client_attach(client, &xfr->client);
+ xfr->id = id;
+ xfr->qname = qname;
+ xfr->qtype = qtype;
+ xfr->qclass = qclass;
+ xfr->zone = NULL;
+ xfr->db = NULL;
+ xfr->ver = NULL;
+ if (zone != NULL) /* zone will be NULL if it's DLZ */
+ dns_zone_attach(zone, &xfr->zone);
+ dns_db_attach(db, &xfr->db);
+ dns_db_attachversion(db, ver, &xfr->ver);
+ xfr->end_of_stream = ISC_FALSE;
+ xfr->tsigkey = tsigkey;
+ xfr->lasttsig = lasttsig;
+ xfr->txmem = NULL;
+ xfr->txmemlen = 0;
+ xfr->nmsg = 0;
+ xfr->many_answers = many_answers,
+ xfr->sends = 0;
+ xfr->shuttingdown = ISC_FALSE;
+ xfr->mnemonic = NULL;
+ xfr->buf.base = NULL;
+ xfr->buf.length = 0;
+ xfr->txmem = NULL;
+ xfr->txmemlen = 0;
+ xfr->stream = NULL;
+ xfr->quota = NULL;
+
+ /*
+ * Allocate a temporary buffer for the uncompressed response
+ * message data. The size should be no more than 65535 bytes
+ * so that the compressed data will fit in a TCP message,
+ * and no less than 65535 bytes so that an almost maximum-sized
+ * RR will fit. Note that although 65535-byte RRs are allowed
+ * in principle, they cannot be zone-transferred (at least not
+ * if uncompressible), because the message and RR headers would
+ * push the size of the TCP message over the 65536 byte limit.
+ */
+ len = 65535;
+ mem = isc_mem_get(mctx, len);
+ if (mem == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ isc_buffer_init(&xfr->buf, mem, len);
+
+ /*
+ * Allocate another temporary buffer for the compressed
+ * response message and its TCP length prefix.
+ */
+ len = 2 + 65535;
+ mem = isc_mem_get(mctx, len);
+ if (mem == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ isc_buffer_init(&xfr->txlenbuf, mem, 2);
+ isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
+ xfr->txmem = mem;
+ xfr->txmemlen = len;
+
+ CHECK(dns_timer_setidle(xfr->client->timer,
+ maxtime, idletime, ISC_FALSE));
+
+ /*
+ * Register a shutdown callback with the client, so that we
+ * can stop the transfer immediately when the client task
+ * gets a shutdown event.
+ */
+ xfr->client->shutdown = xfrout_client_shutdown;
+ xfr->client->shutdown_arg = xfr;
+ /*
+ * These MUST be after the last "goto failure;" / CHECK to
+ * prevent a double free by the caller.
+ */
+ xfr->quota = quota;
+ xfr->stream = stream;
+
+ *xfrp = xfr;
+ return (ISC_R_SUCCESS);
+
+failure:
+ xfrout_ctx_destroy(&xfr);
+ return (result);
+}
+
+
+/*
+ * Arrange to send as much as we can of "stream" without blocking.
+ *
+ * Requires:
+ * The stream iterator is initialized and points at an RR,
+ * or possiby at the end of the stream (that is, the
+ * _first method of the iterator has been called).
+ */
+static void
+sendstream(xfrout_ctx_t *xfr) {
+ dns_message_t *tcpmsg = NULL;
+ dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
+ isc_result_t result;
+ isc_region_t used;
+ isc_region_t region;
+ dns_rdataset_t *qrdataset;
+ dns_name_t *msgname = NULL;
+ dns_rdata_t *msgrdata = NULL;
+ dns_rdatalist_t *msgrdl = NULL;
+ dns_rdataset_t *msgrds = NULL;
+ dns_compress_t cctx;
+ isc_boolean_t cleanup_cctx = ISC_FALSE;
+
+ int n_rrs;
+
+ isc_buffer_clear(&xfr->buf);
+ isc_buffer_clear(&xfr->txlenbuf);
+ isc_buffer_clear(&xfr->txbuf);
+
+ if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {
+ /*
+ * In the UDP case, we put the response data directly into
+ * the client message.
+ */
+ msg = xfr->client->message;
+ CHECK(dns_message_reply(msg, ISC_TRUE));
+ } else {
+ /*
+ * TCP. Build a response dns_message_t, temporarily storing
+ * the raw, uncompressed owner names and RR data contiguously
+ * in xfr->buf. We know that if the uncompressed data fits
+ * in xfr->buf, the compressed data will surely fit in a TCP
+ * message.
+ */
+
+ CHECK(dns_message_create(xfr->mctx,
+ DNS_MESSAGE_INTENTRENDER, &tcpmsg));
+ msg = tcpmsg;
+
+ msg->id = xfr->id;
+ msg->rcode = dns_rcode_noerror;
+ msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
+ if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
+ msg->flags |= DNS_MESSAGEFLAG_RA;
+ CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
+ CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
+ if (xfr->lasttsig != NULL)
+ isc_buffer_free(&xfr->lasttsig);
+
+ /*
+ * Include a question section in the first message only.
+ * BIND 8.2.1 will not recognize an IXFR if it does not
+ * have a question section.
+ */
+ if (xfr->nmsg == 0) {
+ dns_name_t *qname = NULL;
+ isc_region_t r;
+
+ /*
+ * Reserve space for the 12-byte message header
+ * and 4 bytes of question.
+ */
+ isc_buffer_add(&xfr->buf, 12 + 4);
+
+ qrdataset = NULL;
+ result = dns_message_gettemprdataset(msg, &qrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ dns_rdataset_init(qrdataset);
+ dns_rdataset_makequestion(qrdataset,
+ xfr->client->message->rdclass,
+ xfr->qtype);
+
+ result = dns_message_gettempname(msg, &qname);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ dns_name_init(qname, NULL);
+ isc_buffer_availableregion(&xfr->buf, &r);
+ INSIST(r.length >= xfr->qname->length);
+ r.length = xfr->qname->length;
+ isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
+ xfr->qname->length);
+ dns_name_fromregion(qname, &r);
+ ISC_LIST_INIT(qname->list);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+
+ dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
+ }
+ else
+ msg->tcp_continuation = 1;
+ }
+
+ /*
+ * Try to fit in as many RRs as possible, unless "one-answer"
+ * format has been requested.
+ */
+ for (n_rrs = 0; ; n_rrs++) {
+ dns_name_t *name = NULL;
+ isc_uint32_t ttl;
+ dns_rdata_t *rdata = NULL;
+
+ unsigned int size;
+ isc_region_t r;
+
+ msgname = NULL;
+ msgrdata = NULL;
+ msgrdl = NULL;
+ msgrds = NULL;
+
+ xfr->stream->methods->current(xfr->stream,
+ &name, &ttl, &rdata);
+ size = name->length + 10 + rdata->length;
+ isc_buffer_availableregion(&xfr->buf, &r);
+ if (size >= r.length) {
+ /*
+ * RR would not fit. If there are other RRs in the
+ * buffer, send them now and leave this RR to the
+ * next message. If this RR overflows the buffer
+ * all by itself, fail.
+ *
+ * In theory some RRs might fit in a TCP message
+ * when compressed even if they do not fit when
+ * uncompressed, but surely we don't want
+ * to send such monstrosities to an unsuspecting
+ * slave.
+ */
+ if (n_rrs == 0) {
+ xfrout_log(xfr, ISC_LOG_WARNING,
+ "RR too large for zone transfer "
+ "(%d bytes)", size);
+ /* XXX DNS_R_RRTOOLARGE? */
+ result = ISC_R_NOSPACE;
+ goto failure;
+ }
+ break;
+ }
+
+ if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
+ log_rr(name, rdata, ttl); /* XXX */
+
+ result = dns_message_gettempname(msg, &msgname);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ dns_name_init(msgname, NULL);
+ isc_buffer_availableregion(&xfr->buf, &r);
+ INSIST(r.length >= name->length);
+ r.length = name->length;
+ isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
+ dns_name_fromregion(msgname, &r);
+
+ /* Reserve space for RR header. */
+ isc_buffer_add(&xfr->buf, 10);
+
+ result = dns_message_gettemprdata(msg, &msgrdata);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ isc_buffer_availableregion(&xfr->buf, &r);
+ r.length = rdata->length;
+ isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
+ dns_rdata_init(msgrdata);
+ dns_rdata_fromregion(msgrdata,
+ rdata->rdclass, rdata->type, &r);
+
+ result = dns_message_gettemprdatalist(msg, &msgrdl);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ msgrdl->type = rdata->type;
+ msgrdl->rdclass = rdata->rdclass;
+ msgrdl->ttl = ttl;
+ if (rdata->type == dns_rdatatype_sig ||
+ rdata->type == dns_rdatatype_rrsig)
+ msgrdl->covers = dns_rdata_covers(rdata);
+ else
+ msgrdl->covers = dns_rdatatype_none;
+ ISC_LINK_INIT(msgrdl, link);
+ ISC_LIST_INIT(msgrdl->rdata);
+ ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
+
+ result = dns_message_gettemprdataset(msg, &msgrds);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ dns_rdataset_init(msgrds);
+ result = dns_rdatalist_tordataset(msgrdl, msgrds);
+ INSIST(result == ISC_R_SUCCESS);
+
+ ISC_LIST_APPEND(msgname->list, msgrds, link);
+
+ dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
+ msgname = NULL;
+
+ result = xfr->stream->methods->next(xfr->stream);
+ if (result == ISC_R_NOMORE) {
+ xfr->end_of_stream = ISC_TRUE;
+ break;
+ }
+ CHECK(result);
+
+ if (! xfr->many_answers)
+ break;
+ }
+
+ if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {
+ CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
+ dns_compress_setsensitive(&cctx, ISC_TRUE);
+ cleanup_cctx = ISC_TRUE;
+ CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
+ CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
+ CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
+ CHECK(dns_message_renderend(msg));
+ dns_compress_invalidate(&cctx);
+ cleanup_cctx = ISC_FALSE;
+
+ isc_buffer_usedregion(&xfr->txbuf, &used);
+ isc_buffer_putuint16(&xfr->txlenbuf,
+ (isc_uint16_t)used.length);
+ region.base = xfr->txlenbuf.base;
+ region.length = 2 + used.length;
+ xfrout_log(xfr, ISC_LOG_DEBUG(8),
+ "sending TCP message of %d bytes",
+ used.length);
+ CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
+ &region, xfr->client->task,
+ xfrout_senddone,
+ xfr));
+ xfr->sends++;
+ } else {
+ xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
+ ns_client_send(xfr->client);
+ xfr->stream->methods->pause(xfr->stream);
+ xfrout_ctx_destroy(&xfr);
+ return;
+ }
+
+ /* Advance lasttsig to be the last TSIG generated */
+ CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
+
+ xfr->nmsg++;
+
+ failure:
+ if (msgname != NULL) {
+ if (msgrds != NULL) {
+ if (dns_rdataset_isassociated(msgrds))
+ dns_rdataset_disassociate(msgrds);
+ dns_message_puttemprdataset(msg, &msgrds);
+ }
+ if (msgrdl != NULL) {
+ ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
+ dns_message_puttemprdatalist(msg, &msgrdl);
+ }
+ if (msgrdata != NULL)
+ dns_message_puttemprdata(msg, &msgrdata);
+ dns_message_puttempname(msg, &msgname);
+ }
+
+ if (tcpmsg != NULL)
+ dns_message_destroy(&tcpmsg);
+
+ if (cleanup_cctx)
+ dns_compress_invalidate(&cctx);
+ /*
+ * Make sure to release any locks held by database
+ * iterators before returning from the event handler.
+ */
+ xfr->stream->methods->pause(xfr->stream);
+
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ xfrout_fail(xfr, result, "sending zone data");
+}
+
+static void
+xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
+ xfrout_ctx_t *xfr = *xfrp;
+
+ INSIST(xfr->sends == 0);
+
+ xfr->client->shutdown = NULL;
+ xfr->client->shutdown_arg = NULL;
+
+ if (xfr->stream != NULL)
+ xfr->stream->methods->destroy(&xfr->stream);
+ if (xfr->buf.base != NULL)
+ isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
+ if (xfr->txmem != NULL)
+ isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
+ if (xfr->lasttsig != NULL)
+ isc_buffer_free(&xfr->lasttsig);
+ if (xfr->quota != NULL)
+ isc_quota_detach(&xfr->quota);
+ if (xfr->ver != NULL)
+ dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
+ if (xfr->zone != NULL)
+ dns_zone_detach(&xfr->zone);
+ if (xfr->db != NULL)
+ dns_db_detach(&xfr->db);
+
+ ns_client_detach(&xfr->client);
+
+ isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
+
+ *xfrp = NULL;
+}
+
+static void
+xfrout_senddone(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sev = (isc_socketevent_t *)event;
+ xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg;
+ isc_result_t evresult = sev->result;
+
+ UNUSED(task);
+
+ INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+
+ isc_event_free(&event);
+ xfr->sends--;
+ INSIST(xfr->sends == 0);
+
+ (void)isc_timer_touch(xfr->client->timer);
+ if (xfr->shuttingdown == ISC_TRUE) {
+ xfrout_maybe_destroy(xfr);
+ } else if (evresult != ISC_R_SUCCESS) {
+ xfrout_fail(xfr, evresult, "send");
+ } else if (xfr->end_of_stream == ISC_FALSE) {
+ sendstream(xfr);
+ } else {
+ /* End of zone transfer stream. */
+ inc_stats(xfr->zone, dns_nsstatscounter_xfrdone);
+ xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic);
+ ns_client_next(xfr->client, ISC_R_SUCCESS);
+ xfrout_ctx_destroy(&xfr);
+ }
+}
+
+static void
+xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
+ xfr->shuttingdown = ISC_TRUE;
+ xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s",
+ msg, isc_result_totext(result));
+ xfrout_maybe_destroy(xfr);
+}
+
+static void
+xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
+ INSIST(xfr->shuttingdown == ISC_TRUE);
+ if (xfr->sends > 0) {
+ /*
+ * If we are currently sending, cancel it and wait for
+ * cancel event before destroying the context.
+ */
+ isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
+ ISC_SOCKCANCEL_SEND);
+ } else {
+ ns_client_next(xfr->client, ISC_R_CANCELED);
+ xfrout_ctx_destroy(&xfr);
+ }
+}
+
+static void
+xfrout_client_shutdown(void *arg, isc_result_t result) {
+ xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg;
+ xfrout_fail(xfr, result, "aborted");
+}
+
+/*
+ * Log outgoing zone transfer messages in a format like
+ * <client>: transfer of <zone>: <message>
+ */
+
+static void
+xfrout_logv(ns_client_t *client, dns_name_t *zonename,
+ dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
+ ISC_FORMAT_PRINTF(5, 0);
+
+static void
+xfrout_logv(ns_client_t *client, dns_name_t *zonename,
+ dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
+{
+ char msgbuf[2048];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+
+ dns_name_format(zonename, namebuf, sizeof(namebuf));
+ dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
+ NS_LOGMODULE_XFER_OUT, level,
+ "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);
+}
+
+/*
+ * Logging function for use when a xfrout_ctx_t has not yet been created.
+ */
+static void
+xfrout_log1(ns_client_t *client, dns_name_t *zonename,
+ dns_rdataclass_t rdclass, int level, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ xfrout_logv(client, zonename, rdclass, level, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Logging function for use when there is a xfrout_ctx_t.
+ */
+static void
+xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);
+ va_end(ap);
+}
diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c
new file mode 100644
index 0000000..7a420b5
--- /dev/null
+++ b/bin/named/zoneconf.c
@@ -0,0 +1,1016 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: zoneconf.c,v 1.147 2008/09/24 02:46:21 marka Exp $ */
+
+/*% */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rdatatype.h>
+#include <dns/ssu.h>
+#include <dns/stats.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+
+#include <named/client.h>
+#include <named/config.h>
+#include <named/globals.h>
+#include <named/log.h>
+#include <named/server.h>
+#include <named/zoneconf.h>
+
+/* ACLs associated with zone */
+typedef enum {
+ allow_notify,
+ allow_query,
+ allow_transfer,
+ allow_update,
+ 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)
+
+/*%
+ * Convenience function for configuring a single zone ACL.
+ */
+static isc_result_t
+configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
+ const cfg_obj_t *config, acl_type_t acltype,
+ cfg_aclconfctx_t *actx, dns_zone_t *zone,
+ void (*setzacl)(dns_zone_t *, dns_acl_t *),
+ void (*clearzacl)(dns_zone_t *))
+{
+ isc_result_t result;
+ const cfg_obj_t *maps[5] = {NULL, NULL, NULL, NULL, NULL};
+ const cfg_obj_t *aclobj = NULL;
+ int i = 0;
+ dns_acl_t **aclp = NULL, *acl = NULL;
+ const char *aclname;
+ dns_view_t *view;
+
+ view = dns_zone_getview(zone);
+
+ switch (acltype) {
+ case allow_notify:
+ if (view != NULL)
+ aclp = &view->notifyacl;
+ aclname = "allow-notify";
+ break;
+ case allow_query:
+ if (view != NULL)
+ aclp = &view->queryacl;
+ aclname = "allow-query";
+ break;
+ case allow_transfer:
+ if (view != NULL)
+ aclp = &view->transferacl;
+ aclname = "allow-transfer";
+ break;
+ case allow_update:
+ if (view != NULL)
+ aclp = &view->updateacl;
+ aclname = "allow-update";
+ break;
+ case allow_update_forwarding:
+ if (view != NULL)
+ aclp = &view->upfwdacl;
+ aclname = "allow-update-forwarding";
+ break;
+ default:
+ INSIST(0);
+ return (ISC_R_FAILURE);
+ }
+
+ /* First check to see if ACL is defined within the zone */
+ if (zconfig != NULL) {
+ maps[0] = cfg_tuple_get(zconfig, "options");
+ ns_config_get(maps, aclname, &aclobj);
+ if (aclobj != NULL) {
+ aclp = NULL;
+ goto parse_acl;
+ }
+ }
+
+ /* Failing that, see if there's a default ACL already in the view */
+ if (aclp != NULL && *aclp != NULL) {
+ (*setzacl)(zone, *aclp);
+ return (ISC_R_SUCCESS);
+ }
+
+ /* Check for default ACLs that haven't been parsed yet */
+ 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++] = ns_g_defaults;
+ maps[i] = NULL;
+
+ result = ns_config_get(maps, aclname, &aclobj);
+ if (aclobj == NULL) {
+ (*clearzacl)(zone);
+ return (ISC_R_SUCCESS);
+ }
+
+parse_acl:
+ result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx,
+ dns_zone_getmctx(zone), 0, &acl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ (*setzacl)(zone, acl);
+
+ /* Set the view default now */
+ if (aclp != NULL)
+ dns_acl_attach(acl, aclp);
+
+ dns_acl_detach(&acl);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Parse the zone update-policy statement.
+ */
+static isc_result_t
+configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone) {
+ 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_result_t result;
+
+ (void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
+ if (updatepolicy == NULL) {
+ dns_zone_setssutable(zone, NULL);
+ return (ISC_R_SUCCESS);
+ }
+
+ result = dns_ssutable_create(mctx, &table);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (element = cfg_list_first(updatepolicy);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *stmt = cfg_listelt_value(element);
+ const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode");
+ const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
+ const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
+ const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
+ const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
+ const char *str;
+ isc_boolean_t grant = ISC_FALSE;
+ unsigned int mtype = DNS_SSUMATCHTYPE_NAME;
+ dns_fixedname_t fname, fident;
+ isc_buffer_t b;
+ dns_rdatatype_t *types;
+ unsigned int i, n;
+
+ str = cfg_obj_asstring(mode);
+ if (strcasecmp(str, "grant") == 0)
+ grant = ISC_TRUE;
+ else if (strcasecmp(str, "deny") == 0)
+ grant = ISC_FALSE;
+ else
+ INSIST(0);
+
+ str = cfg_obj_asstring(matchtype);
+ if (strcasecmp(str, "name") == 0)
+ mtype = DNS_SSUMATCHTYPE_NAME;
+ else if (strcasecmp(str, "subdomain") == 0)
+ mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
+ else if (strcasecmp(str, "wildcard") == 0)
+ mtype = DNS_SSUMATCHTYPE_WILDCARD;
+ else if (strcasecmp(str, "self") == 0)
+ mtype = DNS_SSUMATCHTYPE_SELF;
+ else if (strcasecmp(str, "selfsub") == 0)
+ mtype = DNS_SSUMATCHTYPE_SELFSUB;
+ else if (strcasecmp(str, "selfwild") == 0)
+ mtype = DNS_SSUMATCHTYPE_SELFWILD;
+ else if (strcasecmp(str, "ms-self") == 0)
+ mtype = DNS_SSUMATCHTYPE_SELFMS;
+ else if (strcasecmp(str, "krb5-self") == 0)
+ mtype = DNS_SSUMATCHTYPE_SELFKRB5;
+ else if (strcasecmp(str, "ms-subdomain") == 0)
+ mtype = DNS_SSUMATCHTYPE_SUBDOMAINMS;
+ else if (strcasecmp(str, "krb5-subdomain") == 0)
+ mtype = DNS_SSUMATCHTYPE_SUBDOMAINKRB5;
+ else if (strcasecmp(str, "tcp-self") == 0)
+ mtype = DNS_SSUMATCHTYPE_TCPSELF;
+ else if (strcasecmp(str, "6to4-self") == 0)
+ mtype = DNS_SSUMATCHTYPE_6TO4SELF;
+ else
+ INSIST(0);
+
+ dns_fixedname_init(&fident);
+ str = cfg_obj_asstring(identity);
+ 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);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
+ "'%s' is not a valid name", str);
+ goto cleanup;
+ }
+
+ 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;
+ }
+
+ n = ns_config_listcount(typelist);
+ if (n == 0)
+ types = NULL;
+ else {
+ types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t));
+ if (types == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ }
+
+ i = 0;
+ for (element2 = cfg_list_first(typelist);
+ element2 != NULL;
+ element2 = cfg_list_next(element2))
+ {
+ const cfg_obj_t *typeobj;
+ isc_textregion_t r;
+
+ INSIST(i < n);
+
+ typeobj = cfg_listelt_value(element2);
+ str = cfg_obj_asstring(typeobj);
+ DE_CONST(str, r.base);
+ r.length = strlen(str);
+
+ result = dns_rdatatype_fromtext(&types[i++], &r);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
+ "'%s' is not a valid type", str);
+ isc_mem_put(mctx, types,
+ n * sizeof(dns_rdatatype_t));
+ goto cleanup;
+ }
+ }
+ INSIST(i == n);
+
+ result = dns_ssutable_addrule(table, grant,
+ dns_fixedname_name(&fident),
+ mtype,
+ dns_fixedname_name(&fname),
+ n, types);
+ if (types != NULL)
+ isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t));
+ if (result != ISC_R_SUCCESS) {
+ goto cleanup;
+ }
+
+ }
+
+ result = ISC_R_SUCCESS;
+ dns_zone_setssutable(zone, table);
+
+ cleanup:
+ dns_ssutable_detach(&table);
+ return (result);
+}
+
+/*%
+ * Convert a config file zone type into a server zone type.
+ */
+static inline dns_zonetype_t
+zonetype_fromconfig(const cfg_obj_t *map) {
+ const cfg_obj_t *obj = NULL;
+ isc_result_t result;
+
+ result = cfg_map_get(map, "type", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ return (ns_config_getzonetype(obj));
+}
+
+/*%
+ * Helper function for strtoargv(). Pardon the gratuitous recursion.
+ */
+static isc_result_t
+strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp,
+ char ***argvp, unsigned int n)
+{
+ isc_result_t result;
+
+ /* Discard leading whitespace. */
+ while (*s == ' ' || *s == '\t')
+ s++;
+
+ if (*s == '\0') {
+ /* We have reached the end of the string. */
+ *argcp = n;
+ *argvp = isc_mem_get(mctx, n * sizeof(char *));
+ if (*argvp == NULL)
+ return (ISC_R_NOMEMORY);
+ } else {
+ char *p = s;
+ while (*p != ' ' && *p != '\t' && *p != '\0')
+ p++;
+ if (*p != '\0')
+ *p++ = '\0';
+
+ result = strtoargvsub(mctx, p, argcp, argvp, n + 1);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ (*argvp)[n] = s;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Tokenize the string "s" into whitespace-separated words,
+ * return the number of words in '*argcp' and an array
+ * of pointers to the words in '*argvp'. The caller
+ * must free the array using isc_mem_put(). The string
+ * is modified in-place.
+ */
+static isc_result_t
+strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) {
+ return (strtoargvsub(mctx, s, argcp, argvp, 0));
+}
+
+static void
+checknames(dns_zonetype_t ztype, const cfg_obj_t **maps,
+ const cfg_obj_t **objp)
+{
+ const char *zone = NULL;
+ isc_result_t result;
+
+ switch (ztype) {
+ case dns_zone_slave: zone = "slave"; break;
+ case dns_zone_master: zone = "master"; break;
+ default:
+ INSIST(0);
+ }
+ result = ns_checknames_get(maps, zone, objp);
+ INSIST(result == ISC_R_SUCCESS);
+}
+
+isc_result_t
+ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
+ const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
+ dns_zone_t *zone)
+{
+ isc_result_t result;
+ const char *zname;
+ dns_rdataclass_t zclass;
+ dns_rdataclass_t vclass;
+ const cfg_obj_t *maps[5];
+ const cfg_obj_t *zoptions = NULL;
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *obj;
+ const char *filename = NULL;
+ dns_notifytype_t notifytype = dns_notifytype_yes;
+ isc_sockaddr_t *addrs;
+ dns_name_t **keynames;
+ isc_uint32_t count;
+ char *cpval;
+ unsigned int dbargc;
+ char **dbargv;
+ static char default_dbtype[] = "rbt";
+ isc_mem_t *mctx = dns_zone_getmctx(zone);
+ dns_dialuptype_t dialup = dns_dialuptype_no;
+ dns_zonetype_t ztype;
+ int i;
+ isc_int32_t journal_size;
+ isc_boolean_t multi;
+ isc_boolean_t alt;
+ dns_view_t *view;
+ isc_boolean_t check = ISC_FALSE, fail = ISC_FALSE;
+ isc_boolean_t warn = ISC_FALSE, ignore = ISC_FALSE;
+ isc_boolean_t ixfrdiff;
+ dns_masterformat_t masterformat;
+ dns_stats_t *zoneqrystats;
+ isc_boolean_t zonestats_on;
+ int seconds;
+
+ i = 0;
+ if (zconfig != NULL) {
+ zoptions = cfg_tuple_get(zconfig, "options");
+ maps[i++] = zoptions;
+ }
+ if (vconfig != NULL)
+ maps[i++] = cfg_tuple_get(vconfig, "options");
+ if (config != NULL) {
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ maps[i++] = options;
+ }
+ maps[i++] = ns_g_defaults;
+ maps[i++] = NULL;
+
+ if (vconfig != NULL)
+ RETERR(ns_config_getclass(cfg_tuple_get(vconfig, "class"),
+ dns_rdataclass_in, &vclass));
+ else
+ vclass = dns_rdataclass_in;
+
+ /*
+ * Configure values common to all zone types.
+ */
+
+ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+
+ RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
+ vclass, &zclass));
+ dns_zone_setclass(zone, zclass);
+
+ ztype = zonetype_fromconfig(zoptions);
+ dns_zone_settype(zone, ztype);
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "database", &obj);
+ if (result == ISC_R_SUCCESS)
+ cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
+ else
+ cpval = default_dbtype;
+
+ if (cpval == NULL)
+ return(ISC_R_NOMEMORY);
+
+ result = strtoargv(mctx, cpval, &dbargc, &dbargv);
+ if (result != ISC_R_SUCCESS && cpval != default_dbtype) {
+ isc_mem_free(mctx, cpval);
+ return (result);
+ }
+
+ /*
+ * ANSI C is strange here. There is no logical reason why (char **)
+ * cannot be promoted automatically to (const char * const *) by the
+ * compiler w/o generating a warning.
+ */
+ result = dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv);
+ isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv));
+ if (cpval != default_dbtype)
+ isc_mem_free(mctx, cpval);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "file", &obj);
+ if (result == ISC_R_SUCCESS)
+ filename = cfg_obj_asstring(obj);
+
+ masterformat = dns_masterformat_text;
+ obj = NULL;
+ result= ns_config_get(maps, "masterfile-format", &obj);
+ if (result == ISC_R_SUCCESS) {
+ const char *masterformatstr = cfg_obj_asstring(obj);
+
+ if (strcasecmp(masterformatstr, "text") == 0)
+ masterformat = dns_masterformat_text;
+ else if (strcasecmp(masterformatstr, "raw") == 0)
+ masterformat = dns_masterformat_raw;
+ else
+ INSIST(0);
+ }
+ RETERR(dns_zone_setfile2(zone, filename, masterformat));
+
+ obj = NULL;
+ result = cfg_map_get(zoptions, "journal", &obj);
+ if (result == ISC_R_SUCCESS)
+ RETERR(dns_zone_setjournal(zone, cfg_obj_asstring(obj)));
+
+ if (ztype == dns_zone_slave)
+ RETERR(configure_zone_acl(zconfig, vconfig, config,
+ allow_notify, ac, zone,
+ dns_zone_setnotifyacl,
+ dns_zone_clearnotifyacl));
+ /*
+ * XXXAG This probably does not make sense for stubs.
+ */
+ RETERR(configure_zone_acl(zconfig, vconfig, config,
+ allow_query, ac, zone,
+ dns_zone_setqueryacl,
+ dns_zone_clearqueryacl));
+
+ obj = NULL;
+ result = ns_config_get(maps, "dialup", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj))
+ dialup = dns_dialuptype_yes;
+ else
+ dialup = dns_dialuptype_no;
+ } else {
+ const char *dialupstr = cfg_obj_asstring(obj);
+ if (strcasecmp(dialupstr, "notify") == 0)
+ dialup = dns_dialuptype_notify;
+ else if (strcasecmp(dialupstr, "notify-passive") == 0)
+ dialup = dns_dialuptype_notifypassive;
+ else if (strcasecmp(dialupstr, "refresh") == 0)
+ dialup = dns_dialuptype_refresh;
+ else if (strcasecmp(dialupstr, "passive") == 0)
+ dialup = dns_dialuptype_passive;
+ else
+ INSIST(0);
+ }
+ dns_zone_setdialup(zone, dialup);
+
+ obj = NULL;
+ result = ns_config_get(maps, "zone-statistics", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ zonestats_on = cfg_obj_asboolean(obj);
+ zoneqrystats = NULL;
+ if (zonestats_on) {
+ RETERR(dns_generalstats_create(mctx, &zoneqrystats,
+ dns_nsstatscounter_max));
+ }
+ dns_zone_setrequeststats(zone, zoneqrystats);
+ if (zoneqrystats != NULL)
+ dns_stats_detach(&zoneqrystats);
+
+ /*
+ * Configure master functionality. This applies
+ * to primary masters (type "master") and slaves
+ * acting as masters (type "slave"), but not to stubs.
+ */
+ if (ztype != dns_zone_stub) {
+ obj = NULL;
+ result = ns_config_get(maps, "notify", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isboolean(obj)) {
+ if (cfg_obj_asboolean(obj))
+ notifytype = dns_notifytype_yes;
+ else
+ notifytype = dns_notifytype_no;
+ } else {
+ const char *notifystr = cfg_obj_asstring(obj);
+ if (strcasecmp(notifystr, "explicit") == 0)
+ notifytype = dns_notifytype_explicit;
+ else if (strcasecmp(notifystr, "master-only") == 0)
+ notifytype = dns_notifytype_masteronly;
+ else
+ INSIST(0);
+ }
+ dns_zone_setnotifytype(zone, notifytype);
+
+ obj = NULL;
+ result = ns_config_get(maps, "also-notify", &obj);
+ if (result == ISC_R_SUCCESS) {
+ isc_sockaddr_t *addrs = NULL;
+ isc_uint32_t addrcount;
+ result = ns_config_getiplist(config, obj, 0, mctx,
+ &addrs, &addrcount);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_zone_setalsonotify(zone, addrs,
+ addrcount);
+ ns_config_putiplist(mctx, &addrs, addrcount);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else
+ RETERR(dns_zone_setalsonotify(zone, NULL, 0));
+
+ obj = NULL;
+ result = ns_config_get(maps, "notify-source", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "notify-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "notify-to-soa", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA,
+ cfg_obj_asboolean(obj));
+
+ dns_zone_setisself(zone, ns_client_isself, NULL);
+
+ RETERR(configure_zone_acl(zconfig, vconfig, config,
+ allow_transfer, ac, zone,
+ dns_zone_setxfracl,
+ dns_zone_clearxfracl));
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-transfer-time-out", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-transfer-idle-out", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-journal-size", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setjournalsize(zone, -1);
+ if (cfg_obj_isstring(obj)) {
+ const char *str = cfg_obj_asstring(obj);
+ INSIST(strcasecmp(str, "unlimited") == 0);
+ journal_size = ISC_UINT32_MAX / 2;
+ } else {
+ isc_resourcevalue_t value;
+ value = cfg_obj_asuint64(obj);
+ if (value > ISC_UINT32_MAX / 2) {
+ cfg_obj_log(obj, ns_g_lctx,
+ ISC_LOG_ERROR,
+ "'max-journal-size "
+ "%" ISC_PRINT_QUADFORMAT "d' "
+ "is too large",
+ value);
+ RETERR(ISC_R_RANGE);
+ }
+ journal_size = (isc_uint32_t)value;
+ }
+ dns_zone_setjournalsize(zone, journal_size);
+
+ obj = NULL;
+ result = ns_config_get(maps, "ixfr-from-differences", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ if (cfg_obj_isboolean(obj))
+ ixfrdiff = cfg_obj_asboolean(obj);
+ else if (strcasecmp(cfg_obj_asstring(obj), "master") &&
+ ztype == dns_zone_master)
+ ixfrdiff = ISC_TRUE;
+ else if (strcasecmp(cfg_obj_asstring(obj), "slave") &&
+ ztype == dns_zone_slave)
+ ixfrdiff = ISC_TRUE;
+ else
+ ixfrdiff = ISC_FALSE;
+ dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, ixfrdiff);
+
+ checknames(ztype, maps, &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_CHECKNAMES, check);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, fail);
+
+ obj = NULL;
+ result = ns_config_get(maps, "notify-delay", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "check-sibling", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
+ cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "zero-no-soa-ttl", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "nsec3-test-zone", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE,
+ cfg_obj_asboolean(obj));
+ }
+
+ /*
+ * Configure update-related options. These apply to
+ * primary masters only.
+ */
+ if (ztype == dns_zone_master) {
+ dns_acl_t *updateacl;
+ RETERR(configure_zone_acl(zconfig, vconfig, config,
+ allow_update, ac, zone,
+ dns_zone_setupdateacl,
+ dns_zone_clearupdateacl));
+
+ updateacl = dns_zone_getupdateacl(zone);
+ if (updateacl != NULL && dns_acl_isinsecure(updateacl))
+ isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
+ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+ "zone '%s' allows updates by IP "
+ "address, which is insecure",
+ zname);
+
+ RETERR(configure_zone_ssutable(zoptions, zone));
+
+ obj = NULL;
+ result = ns_config_get(maps, "sig-validity-interval", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ {
+ const cfg_obj_t *validity, *resign;
+
+ validity = cfg_tuple_get(obj, "validity");
+ seconds = cfg_obj_asuint32(validity) * 86400;
+ dns_zone_setsigvalidityinterval(zone, seconds);
+
+ resign = cfg_tuple_get(obj, "re-sign");
+ if (cfg_obj_isvoid(resign)) {
+ seconds /= 4;
+ } else {
+ if (seconds > 7 * 86400)
+ seconds = cfg_obj_asuint32(resign) *
+ 86400;
+ else
+ seconds = cfg_obj_asuint32(resign) *
+ 3600;
+ }
+ dns_zone_setsigresigninginterval(zone, seconds);
+ }
+
+ obj = NULL;
+ 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));
+ }
+
+ obj = NULL;
+ result = ns_config_get(maps, "sig-signing-signatures", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setsignatures(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "sig-signing-nodes", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setnodes(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "sig-signing-type", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "update-check-ksk", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
+ cfg_obj_asboolean(obj));
+
+ } else if (ztype == dns_zone_slave) {
+ RETERR(configure_zone_acl(zconfig, vconfig, config,
+ allow_update_forwarding, ac, zone,
+ dns_zone_setforwardacl,
+ dns_zone_clearforwardacl));
+ }
+
+
+ /*%
+ * Primary master functionality.
+ */
+ if (ztype == dns_zone_master) {
+ obj = NULL;
+ result = ns_config_get(maps, "check-wildcard", &obj);
+ if (result == ISC_R_SUCCESS)
+ check = cfg_obj_asboolean(obj);
+ else
+ check = ISC_FALSE;
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKWILDCARD, check);
+
+ obj = NULL;
+ result = ns_config_get(maps, "check-mx", &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_CHECKMX, check);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMXFAIL, fail);
+
+ obj = NULL;
+ result = ns_config_get(maps, "check-integrity", &obj);
+ INSIST(obj != NULL);
+ dns_zone_setoption(zone, DNS_ZONEOPT_CHECKINTEGRITY,
+ cfg_obj_asboolean(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "check-mx-cname", &obj);
+ INSIST(obj != NULL);
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ warn = ISC_TRUE;
+ ignore = ISC_FALSE;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ warn = ignore = ISC_FALSE;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ warn = ignore = ISC_TRUE;
+ } else
+ INSIST(0);
+ dns_zone_setoption(zone, DNS_ZONEOPT_WARNMXCNAME, warn);
+ dns_zone_setoption(zone, DNS_ZONEOPT_IGNOREMXCNAME, ignore);
+
+ obj = NULL;
+ result = ns_config_get(maps, "check-srv-cname", &obj);
+ INSIST(obj != NULL);
+ if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
+ warn = ISC_TRUE;
+ ignore = ISC_FALSE;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
+ warn = ignore = ISC_FALSE;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
+ warn = ignore = ISC_TRUE;
+ } else
+ INSIST(0);
+ dns_zone_setoption(zone, DNS_ZONEOPT_WARNSRVCNAME, warn);
+ dns_zone_setoption(zone, DNS_ZONEOPT_IGNORESRVCNAME, ignore);
+ }
+
+ /*
+ * Configure slave functionality.
+ */
+ switch (ztype) {
+ case dns_zone_slave:
+ case dns_zone_stub:
+ count = 0;
+ obj = NULL;
+ result = cfg_map_get(zoptions, "masters", &obj);
+ if (obj != NULL) {
+ addrs = NULL;
+ keynames = NULL;
+ RETERR(ns_config_getipandkeylist(config, obj, mctx,
+ &addrs, &keynames,
+ &count));
+ result = dns_zone_setmasterswithkeys(zone, addrs,
+ keynames, count);
+ ns_config_putipandkeylist(mctx, &addrs, &keynames,
+ count);
+ } else
+ result = dns_zone_setmasters(zone, NULL, 0);
+ RETERR(result);
+
+ multi = ISC_FALSE;
+ if (count > 1) {
+ obj = NULL;
+ result = ns_config_get(maps, "multi-master", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ multi = cfg_obj_asboolean(obj);
+ }
+ dns_zone_setoption(zone, DNS_ZONEOPT_MULTIMASTER, multi);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-transfer-time-in", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setmaxxfrin(zone, cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-transfer-idle-in", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setidlein(zone, cfg_obj_asuint32(obj) * 60);
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-refresh-time", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setmaxrefreshtime(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "min-refresh-time", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setminrefreshtime(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "max-retry-time", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setmaxretrytime(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "min-retry-time", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setminretrytime(zone, cfg_obj_asuint32(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "transfer-source", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ RETERR(dns_zone_setxfrsource4(zone, cfg_obj_assockaddr(obj)));
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "transfer-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ RETERR(dns_zone_setxfrsource6(zone, cfg_obj_assockaddr(obj)));
+ ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
+
+ obj = NULL;
+ result = ns_config_get(maps, "alt-transfer-source", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ RETERR(dns_zone_setaltxfrsource4(zone, cfg_obj_assockaddr(obj)));
+
+ obj = NULL;
+ result = ns_config_get(maps, "alt-transfer-source-v6", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ RETERR(dns_zone_setaltxfrsource6(zone, cfg_obj_assockaddr(obj)));
+
+ obj = NULL;
+ (void)ns_config_get(maps, "use-alt-transfer-source", &obj);
+ if (obj == NULL) {
+ /*
+ * Default off when views are in use otherwise
+ * on for BIND 8 compatibility.
+ */
+ view = dns_zone_getview(zone);
+ if (view != NULL && strcmp(view->name, "_default") == 0)
+ alt = ISC_TRUE;
+ else
+ alt = ISC_FALSE;
+ } else
+ alt = cfg_obj_asboolean(obj);
+ dns_zone_setoption(zone, DNS_ZONEOPT_USEALTXFRSRC, alt);
+
+ obj = NULL;
+ (void)ns_config_get(maps, "try-tcp-refresh", &obj);
+ dns_zone_setoption(zone, DNS_ZONEOPT_TRYTCPREFRESH,
+ cfg_obj_asboolean(obj));
+ break;
+
+ default:
+ break;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) {
+ const cfg_obj_t *zoptions = NULL;
+ const cfg_obj_t *obj = NULL;
+ const char *cfilename;
+ const char *zfilename;
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+
+ if (zonetype_fromconfig(zoptions) != dns_zone_gettype(zone))
+ return (ISC_FALSE);
+
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "file", &obj);
+ if (obj != NULL)
+ cfilename = cfg_obj_asstring(obj);
+ else
+ cfilename = NULL;
+ zfilename = dns_zone_getfile(zone);
+ if (!((cfilename == NULL && zfilename == NULL) ||
+ (cfilename != NULL && zfilename != NULL &&
+ strcmp(cfilename, zfilename) == 0)))
+ return (ISC_FALSE);
+
+ return (ISC_TRUE);
+}
diff --git a/bin/nsupdate/Makefile.in b/bin/nsupdate/Makefile.in
new file mode 100644
index 0000000..6d65697
--- /dev/null
+++ b/bin/nsupdate/Makefile.in
@@ -0,0 +1,83 @@
+# Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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.29 2008/08/29 23:47:22 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \
+ ${ISC_INCLUDES} @DST_GSSAPI_INC@
+
+CDEFINES = @USE_GSSAPI@
+CWARNINGS =
+
+LWRESLIBS = ../../lib/lwres/liblwres.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+
+LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} ${ISCCFGDEPLIBS}
+
+LIBS = ${LWRESLIBS} ${DNSLIBS} ${BIND9LIBS} ${ISCLIBS} ${ISCCFGLIBS} @LIBS@
+
+SUBDIRS =
+
+TARGETS = nsupdate@EXEEXT@
+
+OBJS = nsupdate.@O@
+
+UOBJS =
+
+SRCS = nsupdate.c
+
+MANPAGES = nsupdate.1
+
+HTMLPAGES = nsupdate.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+nsupdate@EXEEXT@: nsupdate.@O@ ${UOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ nsupdate.@O@ ${UOBJS} ${LIBS}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+clean distclean::
+ rm -f ${TARGETS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1
+
+install:: nsupdate@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} nsupdate@EXEEXT@ ${DESTDIR}${bindir}
+ ${INSTALL_DATA} ${srcdir}/nsupdate.1 ${DESTDIR}${mandir}/man1
diff --git a/bin/nsupdate/nsupdate.1 b/bin/nsupdate/nsupdate.1
new file mode 100644
index 0000000..19f2889
--- /dev/null
+++ b/bin/nsupdate/nsupdate.1
@@ -0,0 +1,377 @@
+.\" Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: nsupdate.1,v 1.3 2008/09/25 04:45:04 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: nsupdate
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "NSUPDATE" "1" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+nsupdate \- Dynamic DNS update utility
+.SH "SYNOPSIS"
+.HP 9
+\fBnsupdate\fR [\fB\-d\fR] [\fB\-D\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.
+.PP
+Zones that are under dynamic control via
+\fBnsupdate\fR
+or a DHCP server should not be edited by hand. Manual edits could conflict with dynamic updates and cause data to be lost.
+.PP
+The resource records that are dynamically added or removed with
+\fBnsupdate\fR
+have to be in the same zone. Requests are sent to the zone's master server. This is identified by the MNAME field of the zone's SOA record.
+.PP
+The
+\fB\-d\fR
+option makes
+\fBnsupdate\fR
+operate in debug mode. This provides tracing information about the update requests that are made and the replies received from the name server.
+.PP
+The
+\fB\-D\fR
+option makes
+\fBnsupdate\fR
+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. 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
+and
+\fBserver\fR
+statements would be added to
+\fI/etc/named.conf\fR
+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.
+.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
+\fB\-y\fR
+option is used, a signature is generated from
+[\fIhmac:\fR]\fIkeyname:secret.\fR
+\fIkeyname\fR
+is the name of the key, and
+\fIsecret\fR
+is the base64 encoded shared secret. Use of the
+\fB\-y\fR
+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
+\fBps\fR(1)
+or in a history file maintained by the user's shell.
+.PP
+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
+By default
+\fBnsupdate\fR
+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
+\fB\-v\fR
+option makes
+\fBnsupdate\fR
+use a TCP connection. This may be preferable when a batch of update requests is made.
+.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
+The
+\fB\-u\fR
+option sets the UDP retry interval. The default is 3 seconds. If zero, the interval will be computed from the timeout interval and number of UDP retries.
+.PP
+The
+\fB\-r\fR
+option sets the number of UDP retries. The default is 3. If zero, only one update request will be made.
+.PP
+The
+\fB\-R \fR\fB\fIrandomdev\fR\fR
+option specifies a source of randomness. 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. This option may be specified multiple times.
+.SH "INPUT FORMAT"
+.PP
+\fBnsupdate\fR
+reads input from
+\fIfilename\fR
+or standard input. Each command is supplied on exactly one line of input. Some commands are for administrative purposes. The others are either update instructions or prerequisite checks on the contents of the zone. These checks set conditions that some name or set of resource records (RRset) either exists or is absent from the zone. These conditions must be met if the entire update request is to succeed. Updates will be rejected if the tests for the prerequisite conditions fail.
+.PP
+Every update request consists of zero or more prerequisites and zero or more updates. This allows a suitably authenticated update request to proceed if some specified resource records are present or missing from the zone. A blank input line (or the
+\fBsend\fR
+command) causes the accumulated commands to be sent as one Dynamic DNS update request to the name server.
+.PP
+The command formats and their meaning are as follows:
+.PP
+\fBserver\fR {servername} [port]
+.RS 4
+Sends all dynamic update requests to the name server
+\fIservername\fR. When no server statement is provided,
+\fBnsupdate\fR
+will send updates to the master server of the correct zone. The MNAME field of that zone's SOA record will identify the master server for that zone.
+\fIport\fR
+is the port number on
+\fIservername\fR
+where the dynamic update requests get sent. If no port number is specified, the default DNS port number of 53 is used.
+.RE
+.PP
+\fBlocal\fR {address} [port]
+.RS 4
+Sends all dynamic update requests using the local
+\fIaddress\fR. When no local statement is provided,
+\fBnsupdate\fR
+will send updates using an address and port chosen by the system.
+\fIport\fR
+can additionally be used to make requests come from a specific port. If no port number is specified, the system will assign one.
+.RE
+.PP
+\fBzone\fR {zonename}
+.RS 4
+Specifies that all updates are to be made to the zone
+\fIzonename\fR. If no
+\fIzone\fR
+statement is provided,
+\fBnsupdate\fR
+will attempt determine the correct zone to update based on the rest of the input.
+.RE
+.PP
+\fBclass\fR {classname}
+.RS 4
+Specify the default class. If no
+\fIclass\fR
+is specified, the default class is
+\fIIN\fR.
+.RE
+.PP
+\fBttl\fR {seconds}
+.RS 4
+Specify the default time to live for records to be added. The value
+\fInone\fR
+will clear the default ttl.
+.RE
+.PP
+\fBkey\fR {name} {secret}
+.RS 4
+Specifies that all updates are to be TSIG\-signed using the
+\fIkeyname\fR
+\fIkeysecret\fR
+pair. The
+\fBkey\fR
+command overrides any key specified on the command line via
+\fB\-y\fR
+or
+\fB\-k\fR.
+.RE
+.PP
+\fBprereq nxdomain\fR {domain\-name}
+.RS 4
+Requires that no resource record of any type exists with name
+\fIdomain\-name\fR.
+.RE
+.PP
+\fBprereq yxdomain\fR {domain\-name}
+.RS 4
+Requires that
+\fIdomain\-name\fR
+exists (has as at least one resource record, of any type).
+.RE
+.PP
+\fBprereq nxrrset\fR {domain\-name} [class] {type}
+.RS 4
+Requires that no resource record exists of the specified
+\fItype\fR,
+\fIclass\fR
+and
+\fIdomain\-name\fR. If
+\fIclass\fR
+is omitted, IN (internet) is assumed.
+.RE
+.PP
+\fBprereq yxrrset\fR {domain\-name} [class] {type}
+.RS 4
+This requires that a resource record of the specified
+\fItype\fR,
+\fIclass\fR
+and
+\fIdomain\-name\fR
+must exist. If
+\fIclass\fR
+is omitted, IN (internet) is assumed.
+.RE
+.PP
+\fBprereq yxrrset\fR {domain\-name} [class] {type} {data...}
+.RS 4
+The
+\fIdata\fR
+from each set of prerequisites of this form sharing a common
+\fItype\fR,
+\fIclass\fR, and
+\fIdomain\-name\fR
+are combined to form a set of RRs. This set of RRs must exactly match the set of RRs existing in the zone at the given
+\fItype\fR,
+\fIclass\fR, and
+\fIdomain\-name\fR. The
+\fIdata\fR
+are written in the standard text representation of the resource record's RDATA.
+.RE
+.PP
+\fBupdate delete\fR {domain\-name} [ttl] [class] [type\ [data...]]
+.RS 4
+Deletes any resource records named
+\fIdomain\-name\fR. If
+\fItype\fR
+and
+\fIdata\fR
+is provided, only matching resource records will be removed. The internet class is assumed if
+\fIclass\fR
+is not supplied. The
+\fIttl\fR
+is ignored, and is only allowed for compatibility.
+.RE
+.PP
+\fBupdate add\fR {domain\-name} {ttl} [class] {type} {data...}
+.RS 4
+Adds a new resource record with the specified
+\fIttl\fR,
+\fIclass\fR
+and
+\fIdata\fR.
+.RE
+.PP
+\fBshow\fR
+.RS 4
+Displays the current message, containing all of the prerequisites and updates specified since the last send.
+.RE
+.PP
+\fBsend\fR
+.RS 4
+Sends the current message. This is equivalent to entering a blank line.
+.RE
+.PP
+\fBanswer\fR
+.RS 4
+Displays the answer.
+.RE
+.PP
+\fBdebug\fR
+.RS 4
+Turn on debugging.
+.RE
+.PP
+Lines beginning with a semicolon are comments and are ignored.
+.SH "EXAMPLES"
+.PP
+The examples below show how
+\fBnsupdate\fR
+could be used to insert and delete resource records from the
+\fBexample.com\fR
+zone. Notice that the input in each example contains a trailing blank line so that a group of commands are sent as one dynamic update request to the master name server for
+\fBexample.com\fR.
+.sp
+.RS 4
+.nf
+# nsupdate
+> update delete oldhost.example.com A
+> update add newhost.example.com 86400 A 172.16.1.1
+> send
+.fi
+.RE
+.sp
+.PP
+Any A records for
+\fBoldhost.example.com\fR
+are deleted. And an A record for
+\fBnewhost.example.com\fR
+with IP address 172.16.1.1 is added. The newly\-added record has a 1 day TTL (86400 seconds).
+.sp
+.RS 4
+.nf
+# nsupdate
+> prereq nxdomain nickname.example.com
+> update add nickname.example.com 86400 CNAME somehost.example.com
+> send
+.fi
+.RE
+.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.)
+.SH "FILES"
+.PP
+\fB/etc/resolv.conf\fR
+.RS 4
+used to identify default name server
+.RE
+.PP
+\fBK{name}.+157.+{random}.key\fR
+.RS 4
+base\-64 encoding of HMAC\-MD5 key created by
+\fBdnssec\-keygen\fR(8).
+.RE
+.PP
+\fBK{name}.+157.+{random}.private\fR
+.RS 4
+base\-64 encoding of HMAC\-MD5 key created by
+\fBdnssec\-keygen\fR(8).
+.RE
+.SH "SEE ALSO"
+.PP
+\fBRFC2136\fR(),
+\fBRFC3007\fR(),
+\fBRFC2104\fR(),
+\fBRFC2845\fR(),
+\fBRFC1034\fR(),
+\fBRFC2535\fR(),
+\fBRFC2931\fR(),
+\fBnamed\fR(8),
+\fBdnssec\-keygen\fR(8).
+.SH "BUGS"
+.PP
+The TSIG key is redundantly stored in two separate files. This is a consequence of nsupdate using the DST library for its cryptographic operations, and may change in future releases.
+.SH "COPYRIGHT"
+Copyright \(co 2004\-2008 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000\-2003 Internet Software Consortium.
+.br
diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c
new file mode 100644
index 0000000..0987638
--- /dev/null
+++ b/bin/nsupdate/nsupdate.c
@@ -0,0 +1,2724 @@
+/*
+ * 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
+ * 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: nsupdate.c,v 1.163 2008/09/25 04:02:38 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/event.h>
+#include <isc/hash.h>
+#include <isc/lex.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/parseint.h>
+#include <isc/random.h>
+#include <isc/region.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/dispatch.h>
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rcode.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/request.h>
+#include <dns/result.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+
+#include <dst/dst.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+
+#ifdef GSSAPI
+#include <dst/gssapi.h>
+#endif
+#include <bind9/getaddresses.h>
+
+
+#ifdef HAVE_ADDRINFO
+#ifdef HAVE_GETADDRINFO
+#ifdef HAVE_GAISTRERROR
+#define USE_GETADDRINFO
+#endif
+#endif
+#endif
+
+#ifndef USE_GETADDRINFO
+#ifndef ISC_PLATFORM_NONSTDHERRNO
+extern int h_errno;
+#endif
+#endif
+
+#define MAXCMD (4 * 1024)
+#define MAXWIRE (64 * 1024)
+#define PACKETSIZE ((64 * 1024) - 1)
+#define INITTEXT (2 * 1024)
+#define MAXTEXT (128 * 1024)
+#define FIND_TIMEOUT 5
+#define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */
+
+#define DNSDEFAULTPORT 53
+
+#ifndef RESOLV_CONF
+#define RESOLV_CONF "/etc/resolv.conf"
+#endif
+
+static isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;
+static isc_boolean_t memdebugging = ISC_FALSE;
+static isc_boolean_t have_ipv4 = ISC_FALSE;
+static isc_boolean_t have_ipv6 = ISC_FALSE;
+static isc_boolean_t is_dst_up = ISC_FALSE;
+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_taskmgr_t *taskmgr = NULL;
+static isc_task_t *global_task = NULL;
+static isc_event_t *global_event = NULL;
+static isc_log_t *lctx = NULL;
+static isc_mem_t *mctx = NULL;
+static dns_dispatchmgr_t *dispatchmgr = NULL;
+static dns_requestmgr_t *requestmgr = NULL;
+static isc_socketmgr_t *socketmgr = NULL;
+static isc_timermgr_t *timermgr = NULL;
+static dns_dispatch_t *dispatchv4 = NULL;
+static dns_dispatch_t *dispatchv6 = NULL;
+static dns_message_t *updatemsg = NULL;
+static dns_fixedname_t fuserzone;
+static dns_name_t *userzone = NULL;
+static dns_name_t *zonename = NULL;
+static dns_name_t tmpzonename;
+static dns_name_t restart_master;
+static dns_tsig_keyring_t *gssring = NULL;
+static dns_tsigkey_t *tsigkey = NULL;
+static dst_key_t *sig0key;
+static lwres_context_t *lwctx = NULL;
+static lwres_conf_t *lwconf;
+static isc_sockaddr_t *servers;
+static int ns_inuse = 0;
+static int ns_total = 0;
+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 isc_entropy_t *entropy = NULL;
+static isc_boolean_t shuttingdown = ISC_FALSE;
+static FILE *input;
+static isc_boolean_t interactive = ISC_TRUE;
+static isc_boolean_t seenerror = ISC_FALSE;
+static const dns_master_style_t *style;
+static int requests = 0;
+static unsigned int logdebuglevel = 0;
+static unsigned int timeout = 300;
+static unsigned int udp_timeout = 3;
+static unsigned int udp_retries = 3;
+static dns_rdataclass_t defaultclass = dns_rdataclass_in;
+static dns_rdataclass_t zoneclass = dns_rdataclass_none;
+static dns_message_t *answer = NULL;
+static isc_uint32_t default_ttl = 0;
+static isc_boolean_t default_ttl_set = ISC_FALSE;
+
+typedef struct nsu_requestinfo {
+ dns_message_t *msg;
+ isc_sockaddr_t *addr;
+} nsu_requestinfo_t;
+
+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);
+
+static void
+debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+static void
+ddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+#ifdef GSSAPI
+static dns_fixedname_t fkname;
+static isc_sockaddr_t *kserver = NULL;
+static char servicename[DNS_NAME_FORMATSIZE];
+static dns_name_t *keyname;
+typedef struct nsu_gssinfo {
+ dns_message_t *msg;
+ isc_sockaddr_t *addr;
+ gss_ctx_id_t context;
+} nsu_gssinfo_t;
+
+static void
+start_gssrequest(dns_name_t *master);
+static void
+send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ dns_message_t *msg, dns_request_t **request,
+ gss_ctx_id_t context);
+static void
+recvgss(isc_task_t *task, isc_event_t *event);
+#endif /* GSSAPI */
+
+static void
+error(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+#define STATUS_MORE (isc_uint16_t)0
+#define STATUS_SEND (isc_uint16_t)1
+#define STATUS_QUIT (isc_uint16_t)2
+#define STATUS_SYNTAX (isc_uint16_t)3
+
+typedef struct entropysource entropysource_t;
+
+struct entropysource {
+ isc_entropysource_t *source;
+ isc_mem_t *mctx;
+ ISC_LINK(entropysource_t) link;
+};
+
+static ISC_LIST(entropysource_t) sources;
+
+static void
+setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx)
+{
+ isc_result_t result;
+ isc_entropysource_t *source = NULL;
+ entropysource_t *elt;
+ int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
+
+ REQUIRE(ectx != NULL);
+
+ if (*ectx == NULL) {
+ result = isc_entropy_create(mctx, ectx);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not create entropy object");
+ ISC_LIST_INIT(sources);
+ }
+
+ if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
+ usekeyboard = ISC_ENTROPY_KEYBOARDYES;
+ randomfile = NULL;
+ }
+
+ result = isc_entropy_usebestsource(*ectx, &source, randomfile,
+ usekeyboard);
+
+ if (result != ISC_R_SUCCESS)
+ fatal("could not initialize entropy source: %s",
+ isc_result_totext(result));
+
+ if (source != NULL) {
+ elt = isc_mem_get(mctx, sizeof(*elt));
+ if (elt == NULL)
+ fatal("out of memory");
+ elt->source = source;
+ elt->mctx = mctx;
+ ISC_LINK_INIT(elt, link);
+ ISC_LIST_APPEND(sources, elt, link);
+ }
+}
+
+static void
+cleanup_entropy(isc_entropy_t **ectx) {
+ entropysource_t *source;
+ while (!ISC_LIST_EMPTY(sources)) {
+ source = ISC_LIST_HEAD(sources);
+ ISC_LIST_UNLINK(sources, source, link);
+ isc_entropy_destroysource(&source->source);
+ isc_mem_put(source->mctx, source, sizeof(*source));
+ }
+ isc_entropy_detach(ectx);
+}
+
+
+static dns_rdataclass_t
+getzoneclass(void) {
+ if (zoneclass == dns_rdataclass_none)
+ zoneclass = defaultclass;
+ return (zoneclass);
+}
+
+static isc_boolean_t
+setzoneclass(dns_rdataclass_t rdclass) {
+ if (zoneclass == dns_rdataclass_none ||
+ rdclass == dns_rdataclass_none)
+ zoneclass = rdclass;
+ if (zoneclass != rdclass)
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+}
+
+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 void
+error(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+}
+
+static void
+debug(const char *format, ...) {
+ va_list args;
+
+ if (debugging) {
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+static void
+ddebug(const char *format, ...) {
+ va_list args;
+
+ if (ddebugging) {
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+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 *
+mem_alloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+static void
+mem_free(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+
+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
+reset_system(void) {
+ isc_result_t result;
+
+ ddebug("reset_system()");
+ /* If the update message is still around, destroy it */
+ if (updatemsg != NULL)
+ dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER);
+ else {
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
+ &updatemsg);
+ check_result(result, "dns_message_create");
+ }
+ updatemsg->opcode = dns_opcode_update;
+ if (usegsstsig) {
+ if (tsigkey != NULL)
+ dns_tsigkey_detach(&tsigkey);
+ if (gssring != NULL)
+ dns_tsigkeyring_destroy(&gssring);
+ tried_other_gsstsig = ISC_FALSE;
+ }
+}
+
+static isc_uint16_t
+parse_hmac(dns_name_t **hmac, const char *hmacstr, size_t len) {
+ isc_uint16_t digestbits = 0;
+ isc_result_t result;
+ char buf[20];
+
+ REQUIRE(hmac != NULL && *hmac == NULL);
+ REQUIRE(hmacstr != NULL);
+
+ if (len >= sizeof(buf))
+ fatal("unknown key type '%.*s'", (int)(len), hmacstr);
+
+ strncpy(buf, hmacstr, len);
+ buf[len] = 0;
+
+ if (strcasecmp(buf, "hmac-md5") == 0) {
+ *hmac = DNS_TSIG_HMACMD5_NAME;
+ } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
+ *hmac = DNS_TSIG_HMACMD5_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[9], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 128)
+ fatal("digest-bits out of range [0..128]");
+ digestbits = (digestbits +7) & ~0x7U;
+ } else if (strcasecmp(buf, "hmac-sha1") == 0) {
+ *hmac = DNS_TSIG_HMACSHA1_NAME;
+ } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
+ *hmac = DNS_TSIG_HMACSHA1_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[10], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 160)
+ fatal("digest-bits out of range [0..160]");
+ digestbits = (digestbits +7) & ~0x7U;
+ } else if (strcasecmp(buf, "hmac-sha224") == 0) {
+ *hmac = DNS_TSIG_HMACSHA224_NAME;
+ } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
+ *hmac = DNS_TSIG_HMACSHA224_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[12], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 224)
+ fatal("digest-bits out of range [0..224]");
+ digestbits = (digestbits +7) & ~0x7U;
+ } else if (strcasecmp(buf, "hmac-sha256") == 0) {
+ *hmac = DNS_TSIG_HMACSHA256_NAME;
+ } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
+ *hmac = DNS_TSIG_HMACSHA256_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[12], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 256)
+ fatal("digest-bits out of range [0..256]");
+ digestbits = (digestbits +7) & ~0x7U;
+ } else if (strcasecmp(buf, "hmac-sha384") == 0) {
+ *hmac = DNS_TSIG_HMACSHA384_NAME;
+ } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
+ *hmac = DNS_TSIG_HMACSHA384_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[12], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 384)
+ fatal("digest-bits out of range [0..384]");
+ digestbits = (digestbits +7) & ~0x7U;
+ } else if (strcasecmp(buf, "hmac-sha512") == 0) {
+ *hmac = DNS_TSIG_HMACSHA512_NAME;
+ } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
+ *hmac = DNS_TSIG_HMACSHA512_NAME;
+ result = isc_parse_uint16(&digestbits, &buf[12], 10);
+ if (result != ISC_R_SUCCESS || digestbits > 512)
+ fatal("digest-bits out of range [0..512]");
+ digestbits = (digestbits +7) & ~0x7U;
+ } else
+ fatal("unknown key type '%s'", buf);
+ return (digestbits);
+}
+
+static void
+setup_keystr(void) {
+ unsigned char *secret = NULL;
+ int secretlen;
+ isc_buffer_t secretbuf;
+ isc_result_t result;
+ isc_buffer_t keynamesrc;
+ char *secretstr;
+ char *s, *n;
+ dns_fixedname_t fkeyname;
+ dns_name_t *keyname;
+ char *name;
+ dns_name_t *hmacname = NULL;
+ isc_uint16_t digestbits = 0;
+
+ dns_fixedname_init(&fkeyname);
+ keyname = dns_fixedname_name(&fkeyname);
+
+ debug("Creating key...");
+
+ s = strchr(keystr, ':');
+ if (s == NULL || s == keystr || s[1] == 0)
+ fatal("key option must specify [hmac:]keyname:secret");
+ secretstr = s + 1;
+ n = strchr(secretstr, ':');
+ if (n != NULL) {
+ if (n == secretstr || n[1] == 0)
+ fatal("key option must specify [hmac:]keyname:secret");
+ name = secretstr;
+ secretstr = n + 1;
+ digestbits = parse_hmac(&hmacname, keystr, s - keystr);
+ } else {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ name = keystr;
+ n = s;
+ }
+
+ isc_buffer_init(&keynamesrc, name, n - name);
+ isc_buffer_add(&keynamesrc, n - name);
+
+ debug("namefromtext");
+ result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname,
+ ISC_FALSE, NULL);
+ check_result(result, "dns_name_fromtext");
+
+ secretlen = strlen(secretstr) * 3 / 4;
+ secret = isc_mem_allocate(mctx, secretlen);
+ if (secret == NULL)
+ fatal("out of memory");
+
+ isc_buffer_init(&secretbuf, secret, secretlen);
+ result = isc_base64_decodestring(secretstr, &secretbuf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not create key from %s: %s\n",
+ keystr, isc_result_totext(result));
+ goto failure;
+ }
+
+ secretlen = isc_buffer_usedlength(&secretbuf);
+
+ debug("keycreate");
+ result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
+ ISC_TRUE, NULL, 0, 0, mctx, NULL, &tsigkey);
+ if (result != ISC_R_SUCCESS)
+ fprintf(stderr, "could not create key from %s: %s\n",
+ keystr, dns_result_totext(result));
+ else
+ dst_key_setbits(tsigkey->key, digestbits);
+ failure:
+ if (secret != NULL)
+ isc_mem_free(mctx, secret);
+}
+
+static void
+setup_keyfile(void) {
+ dst_key_t *dstkey = NULL;
+ isc_result_t result;
+ dns_name_t *hmacname = NULL;
+
+ debug("Creating key...");
+
+ result = dst_key_fromnamedfile(keyfile,
+ 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));
+ return;
+ }
+ switch (dst_key_alg(dstkey)) {
+ case DST_ALG_HMACMD5:
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ break;
+ case DST_ALG_HMACSHA1:
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ break;
+ case DST_ALG_HMACSHA224:
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ break;
+ case DST_ALG_HMACSHA256:
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ break;
+ case DST_ALG_HMACSHA384:
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ break;
+ case DST_ALG_HMACSHA512:
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ break;
+ }
+ if (hmacname != NULL) {
+ result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
+ hmacname, dstkey, ISC_FALSE,
+ NULL, 0, 0, mctx, NULL,
+ &tsigkey);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not create key from %s: %s\n",
+ keyfile, isc_result_totext(result));
+ dst_key_free(&dstkey);
+ return;
+ }
+ } else
+ sig0key = dstkey;
+}
+
+static void
+doshutdown(void) {
+ isc_task_detach(&global_task);
+
+ if (userserver != NULL)
+ isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t));
+
+ if (localaddr != NULL)
+ isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t));
+
+ if (tsigkey != NULL) {
+ ddebug("Freeing TSIG key");
+ dns_tsigkey_detach(&tsigkey);
+ }
+
+ if (sig0key != NULL) {
+ ddebug("Freeing SIG(0) key");
+ dst_key_free(&sig0key);
+ }
+
+ if (updatemsg != NULL)
+ dns_message_destroy(&updatemsg);
+
+ if (is_dst_up) {
+ ddebug("Destroy DST lib");
+ dst_lib_destroy();
+ is_dst_up = ISC_FALSE;
+ }
+
+ cleanup_entropy(&entropy);
+
+ lwres_conf_clear(lwctx);
+ lwres_context_destroy(&lwctx);
+
+ isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t));
+
+ ddebug("Destroying request manager");
+ dns_requestmgr_detach(&requestmgr);
+
+ ddebug("Freeing the dispatchers");
+ if (have_ipv4)
+ dns_dispatch_detach(&dispatchv4);
+ if (have_ipv6)
+ dns_dispatch_detach(&dispatchv6);
+
+ ddebug("Shutting down dispatch manager");
+ dns_dispatchmgr_destroy(&dispatchmgr);
+
+}
+
+static void
+maybeshutdown(void) {
+ ddebug("Shutting down request manager");
+ dns_requestmgr_shutdown(requestmgr);
+
+ if (requests != 0)
+ return;
+
+ doshutdown();
+}
+
+static void
+shutdown_program(isc_task_t *task, isc_event_t *event) {
+ REQUIRE(task == global_task);
+ UNUSED(task);
+
+ ddebug("shutdown_program()");
+ isc_event_free(&event);
+
+ shuttingdown = ISC_TRUE;
+ maybeshutdown();
+}
+
+static void
+setup_system(void) {
+ isc_result_t result;
+ isc_sockaddr_t bind_any, bind_any6;
+ lwres_result_t lwresult;
+ unsigned int attrs, attrmask;
+ int i;
+ isc_logconfig_t *logconfig = NULL;
+
+ ddebug("setup_system()");
+
+ dns_result_register();
+
+ result = isc_net_probeipv4();
+ if (result == ISC_R_SUCCESS)
+ have_ipv4 = ISC_TRUE;
+
+ result = isc_net_probeipv6();
+ if (result == ISC_R_SUCCESS)
+ have_ipv6 = ISC_TRUE;
+
+ if (!have_ipv4 && !have_ipv6)
+ fatal("could not find either IPv4 or IPv6");
+
+ 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, logdebuglevel);
+
+ lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
+ if (lwresult != LWRES_R_SUCCESS)
+ fatal("lwres_context_create failed");
+
+ (void)lwres_conf_parse(lwctx, RESOLV_CONF);
+ lwconf = lwres_conf_get(lwctx);
+
+ ns_total = lwconf->nsnext;
+ if (ns_total <= 0) {
+ /* No name servers in resolv.conf; default to loopback. */
+ struct in_addr localhost;
+ ns_total = 1;
+ servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
+ if (servers == NULL)
+ fatal("out of memory");
+ localhost.s_addr = htonl(INADDR_LOOPBACK);
+ isc_sockaddr_fromin(&servers[0], &localhost, DNSDEFAULTPORT);
+ } else {
+ servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t));
+ if (servers == NULL)
+ fatal("out of memory");
+ for (i = 0; i < ns_total; i++) {
+ 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);
+ } else {
+ struct in6_addr in6;
+ memcpy(&in6, lwconf->nameservers[i].address, 16);
+ isc_sockaddr_fromin6(&servers[i], &in6,
+ DNSDEFAULTPORT);
+ }
+ }
+ }
+
+ setup_entropy(mctx, NULL, &entropy);
+
+ result = isc_hash_create(mctx, entropy, DNS_NAME_MAXWIRE);
+ check_result(result, "isc_hash_create");
+ isc_hash_init();
+
+ result = dns_dispatchmgr_create(mctx, entropy, &dispatchmgr);
+ check_result(result, "dns_dispatchmgr_create");
+
+ result = isc_socketmgr_create(mctx, &socketmgr);
+ check_result(result, "dns_socketmgr_create");
+
+ result = isc_timermgr_create(mctx, &timermgr);
+ check_result(result, "dns_timermgr_create");
+
+ result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
+ check_result(result, "isc_taskmgr_create");
+
+ result = isc_task_create(taskmgr, 0, &global_task);
+ check_result(result, "isc_task_create");
+
+ result = isc_task_onshutdown(global_task, shutdown_program, NULL);
+ check_result(result, "isc_task_onshutdown");
+
+ result = dst_lib_init(mctx, entropy, 0);
+ check_result(result, "dst_lib_init");
+ is_dst_up = ISC_TRUE;
+
+ attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
+
+ if (have_ipv6) {
+ attrs = DNS_DISPATCHATTR_UDP;
+ attrs |= DNS_DISPATCHATTR_MAKEQUERY;
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ isc_sockaddr_any6(&bind_any6);
+ result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any6, PACKETSIZE,
+ 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv6);
+ check_result(result, "dns_dispatch_getudp (v6)");
+ }
+
+ if (have_ipv4) {
+ attrs = DNS_DISPATCHATTR_UDP;
+ attrs |= DNS_DISPATCHATTR_MAKEQUERY;
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ isc_sockaddr_any(&bind_any);
+ result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any, PACKETSIZE,
+ 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv4);
+ check_result(result, "dns_dispatch_getudp (v4)");
+ }
+
+ result = dns_requestmgr_create(mctx, timermgr,
+ socketmgr, taskmgr, dispatchmgr,
+ dispatchv4, dispatchv6, &requestmgr);
+ check_result(result, "dns_requestmgr_create");
+
+ if (keystr != NULL)
+ setup_keystr();
+ else if (keyfile != NULL)
+ setup_keyfile();
+}
+
+static void
+get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
+ int count;
+ isc_result_t result;
+
+ isc_app_block();
+ result = bind9_getaddresses(host, port, sockaddr, 1, &count);
+ isc_app_unblock();
+ if (result != ISC_R_SUCCESS)
+ fatal("couldn't get address for '%s': %s",
+ host, isc_result_totext(result));
+ INSIST(count == 1);
+}
+
+#define PARSE_ARGS_FMT "dDMl:y:govk:rR::t:u:"
+
+static void
+pre_parse_args(int argc, char **argv) {
+ int ch;
+
+ while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
+ switch (ch) {
+ case 'M': /* was -dm */
+ debugging = ISC_TRUE;
+ ddebugging = ISC_TRUE;
+ memdebugging = ISC_TRUE;
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE |
+ ISC_MEM_DEBUGRECORD;
+ break;
+
+ case '?':
+ if (isc_commandline_option != '?')
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ argv[0], isc_commandline_option);
+ fprintf(stderr, "usage: nsupdate [-d] "
+ "[-g | -o | -y keyname:secret | -k keyfile] "
+ "[-v] [filename]\n");
+ exit(1);
+
+ default:
+ break;
+ }
+ }
+ isc_commandline_reset = ISC_TRUE;
+ isc_commandline_index = 1;
+}
+
+static void
+parse_args(int argc, char **argv, isc_mem_t *mctx, isc_entropy_t **ectx) {
+ int ch;
+ isc_uint32_t i;
+ isc_result_t result;
+
+ debug("parse_args");
+ while ((ch = isc_commandline_parse(argc, argv, PARSE_ARGS_FMT)) != -1) {
+ switch (ch) {
+ case 'd':
+ debugging = ISC_TRUE;
+ break;
+ case 'D': /* was -dd */
+ debugging = ISC_TRUE;
+ ddebugging = ISC_TRUE;
+ break;
+ case 'M':
+ break;
+ case 'l':
+ result = isc_parse_uint32(&i, isc_commandline_argument,
+ 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "bad library debug value "
+ "'%s'\n", isc_commandline_argument);
+ exit(1);
+ }
+ logdebuglevel = i;
+ break;
+ case 'y':
+ keystr = isc_commandline_argument;
+ break;
+ case 'v':
+ usevc = ISC_TRUE;
+ break;
+ case 'k':
+ keyfile = isc_commandline_argument;
+ break;
+ case 'g':
+ usegsstsig = ISC_TRUE;
+ use_win2k_gsstsig = ISC_FALSE;
+ break;
+ case 'o':
+ usegsstsig = ISC_TRUE;
+ use_win2k_gsstsig = ISC_TRUE;
+ break;
+ case 't':
+ result = isc_parse_uint32(&timeout,
+ isc_commandline_argument, 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "bad timeout '%s'\n", isc_commandline_argument);
+ exit(1);
+ }
+ if (timeout == 0)
+ timeout = UINT_MAX;
+ break;
+ case 'u':
+ result = isc_parse_uint32(&udp_timeout,
+ isc_commandline_argument, 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "bad udp timeout '%s'\n", isc_commandline_argument);
+ exit(1);
+ }
+ if (udp_timeout == 0)
+ udp_timeout = UINT_MAX;
+ break;
+ case 'r':
+ result = isc_parse_uint32(&udp_retries,
+ isc_commandline_argument, 10);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "bad udp retries '%s'\n", isc_commandline_argument);
+ exit(1);
+ }
+ break;
+
+ case 'R':
+ setup_entropy(mctx, isc_commandline_argument, ectx);
+ break;
+
+ default:
+ fprintf(stderr, "%s: unhandled option: %c\n",
+ argv[0], isc_commandline_option);
+ exit(1);
+ }
+ }
+ if (keyfile != NULL && keystr != NULL) {
+ fprintf(stderr, "%s: cannot specify both -k and -y\n",
+ argv[0]);
+ exit(1);
+ }
+
+#ifdef GSSAPI
+ if (usegsstsig && (keyfile != NULL || keystr != NULL)) {
+ fprintf(stderr, "%s: cannot specify -g with -k or -y\n",
+ argv[0]);
+ exit(1);
+ }
+#else
+ if (usegsstsig) {
+ fprintf(stderr, "%s: cannot specify -g or -o, " \
+ "program not linked with GSS API Library\n",
+ argv[0]);
+ exit(1);
+ }
+#endif
+
+ if (argv[isc_commandline_index] != NULL) {
+ if (strcmp(argv[isc_commandline_index], "-") == 0) {
+ input = stdin;
+ } else {
+ result = isc_stdio_open(argv[isc_commandline_index],
+ "r", &input);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not open '%s': %s\n",
+ argv[isc_commandline_index],
+ isc_result_totext(result));
+ exit(1);
+ }
+ }
+ interactive = ISC_FALSE;
+ }
+}
+
+static isc_uint16_t
+parse_name(char **cmdlinep, dns_message_t *msg, dns_name_t **namep) {
+ isc_result_t result;
+ char *word;
+ isc_buffer_t *namebuf = NULL;
+ isc_buffer_t source;
+
+ word = nsu_strsep(cmdlinep, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not read owner name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ result = dns_message_gettempname(msg, namep);
+ check_result(result, "dns_message_gettempname");
+ result = isc_buffer_allocate(mctx, &namebuf, DNS_NAME_MAXWIRE);
+ check_result(result, "isc_buffer_allocate");
+ dns_name_init(*namep, NULL);
+ dns_name_setbuffer(*namep, namebuf);
+ 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);
+ check_result(result, "dns_name_fromtext");
+ isc_buffer_invalidate(&source);
+ return (STATUS_MORE);
+}
+
+static isc_uint16_t
+parse_rdata(char **cmdlinep, dns_rdataclass_t rdataclass,
+ dns_rdatatype_t rdatatype, dns_message_t *msg,
+ 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 != 0 && isspace((unsigned char)*cmdline))
+ cmdline++;
+
+ if (*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(NULL, 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_fromregion(rdata, rdataclass, rdatatype, &r);
+ isc_buffer_free(&buf);
+ dns_message_takebuffer(msg, &newbuf);
+ } else {
+ fprintf(stderr, "invalid rdata format: %s\n",
+ isc_result_totext(result));
+ isc_buffer_free(&buf);
+ return (STATUS_SYNTAX);
+ }
+ } else {
+ rdata->flags = DNS_RDATA_UPDATE;
+ }
+ *cmdlinep = cmdline;
+ return (STATUS_MORE);
+}
+
+static isc_uint16_t
+make_prereq(char *cmdline, isc_boolean_t ispositive, isc_boolean_t isrrset) {
+ isc_result_t result;
+ char *word;
+ dns_name_t *name = NULL;
+ 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;
+ isc_uint16_t retval;
+
+ ddebug("make_prereq()");
+
+ /*
+ * Read the owner name
+ */
+ retval = parse_name(&cmdline, updatemsg, &name);
+ if (retval != STATUS_MORE)
+ return (retval);
+
+ /*
+ * If this is an rrset prereq, read the class or type.
+ */
+ if (isrrset) {
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not read class or type\n");
+ goto failure;
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdataclass_fromtext(&rdataclass, &region);
+ if (result == ISC_R_SUCCESS) {
+ if (!setzoneclass(rdataclass)) {
+ fprintf(stderr, "class mismatch: %s\n", word);
+ goto failure;
+ }
+ /*
+ * Now read the type.
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not read type\n");
+ goto failure;
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "invalid type: %s\n", word);
+ goto failure;
+ }
+ } else {
+ rdataclass = getzoneclass();
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "invalid type: %s\n", word);
+ goto failure;
+ }
+ }
+ } else
+ rdatatype = dns_rdatatype_any;
+
+ result = dns_message_gettemprdata(updatemsg, &rdata);
+ check_result(result, "dns_message_gettemprdata");
+
+ dns_rdata_init(rdata);
+
+ if (isrrset && ispositive) {
+ retval = parse_rdata(&cmdline, rdataclass, rdatatype,
+ updatemsg, rdata);
+ if (retval != STATUS_MORE)
+ goto failure;
+ } else
+ rdata->flags = DNS_RDATA_UPDATE;
+
+ result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
+ check_result(result, "dns_message_gettemprdatalist");
+ result = dns_message_gettemprdataset(updatemsg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+ 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);
+ dns_rdataset_init(rdataset);
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ dns_message_addname(updatemsg, name, DNS_SECTION_PREREQUISITE);
+ return (STATUS_MORE);
+
+ failure:
+ if (name != NULL)
+ dns_message_puttempname(updatemsg, &name);
+ return (STATUS_SYNTAX);
+}
+
+static isc_uint16_t
+evaluate_prereq(char *cmdline) {
+ char *word;
+ isc_boolean_t ispositive, isrrset;
+
+ ddebug("evaluate_prereq()");
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not read operation code\n");
+ return (STATUS_SYNTAX);
+ }
+ 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);
+ return (STATUS_SYNTAX);
+ }
+ return (make_prereq(cmdline, ispositive, isrrset));
+}
+
+static isc_uint16_t
+evaluate_server(char *cmdline) {
+ char *word, *server;
+ long port;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not read server name\n");
+ return (STATUS_SYNTAX);
+ }
+ server = word;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0)
+ port = DNSDEFAULTPORT;
+ else {
+ char *endp;
+ port = strtol(word, &endp, 10);
+ if (*endp != 0) {
+ fprintf(stderr, "port '%s' is not numeric\n", word);
+ return (STATUS_SYNTAX);
+ } else if (port < 1 || port > 65535) {
+ fprintf(stderr, "port '%s' is out of range "
+ "(1 to 65535)\n", word);
+ return (STATUS_SYNTAX);
+ }
+ }
+
+ if (userserver == NULL) {
+ userserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
+ if (userserver == NULL)
+ fatal("out of memory");
+ }
+
+ get_address(server, (in_port_t)port, userserver);
+
+ return (STATUS_MORE);
+}
+
+static isc_uint16_t
+evaluate_local(char *cmdline) {
+ char *word, *local;
+ long port;
+ struct in_addr in4;
+ struct in6_addr in6;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not read server name\n");
+ return (STATUS_SYNTAX);
+ }
+ local = word;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0)
+ port = 0;
+ else {
+ char *endp;
+ port = strtol(word, &endp, 10);
+ if (*endp != 0) {
+ fprintf(stderr, "port '%s' is not numeric\n", word);
+ return (STATUS_SYNTAX);
+ } else if (port < 1 || port > 65535) {
+ fprintf(stderr, "port '%s' is out of range "
+ "(1 to 65535)\n", word);
+ return (STATUS_SYNTAX);
+ }
+ }
+
+ if (localaddr == NULL) {
+ localaddr = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
+ if (localaddr == NULL)
+ fatal("out of memory");
+ }
+
+ if (have_ipv6 && inet_pton(AF_INET6, local, &in6) == 1)
+ isc_sockaddr_fromin6(localaddr, &in6, (in_port_t)port);
+ else if (have_ipv4 && inet_pton(AF_INET, local, &in4) == 1)
+ isc_sockaddr_fromin(localaddr, &in4, (in_port_t)port);
+ else {
+ fprintf(stderr, "invalid address %s", local);
+ return (STATUS_SYNTAX);
+ }
+
+ return (STATUS_MORE);
+}
+
+static isc_uint16_t
+evaluate_key(char *cmdline) {
+ char *namestr;
+ char *secretstr;
+ isc_buffer_t b;
+ isc_result_t result;
+ dns_fixedname_t fkeyname;
+ dns_name_t *keyname;
+ int secretlen;
+ unsigned char *secret = NULL;
+ isc_buffer_t secretbuf;
+ dns_name_t *hmacname = NULL;
+ isc_uint16_t digestbits = 0;
+ char *n;
+
+ namestr = nsu_strsep(&cmdline, " \t\r\n");
+ if (*namestr == 0) {
+ fprintf(stderr, "could not read key name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ dns_fixedname_init(&fkeyname);
+ keyname = dns_fixedname_name(&fkeyname);
+
+ n = strchr(namestr, ':');
+ if (n != NULL) {
+ digestbits = parse_hmac(&hmacname, namestr, n - namestr);
+ namestr = n + 1;
+ } else
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+
+ isc_buffer_init(&b, namestr, strlen(namestr));
+ isc_buffer_add(&b, strlen(namestr));
+ result = dns_name_fromtext(keyname, &b, dns_rootname, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not parse key name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ secretstr = nsu_strsep(&cmdline, "\r\n");
+ if (*secretstr == 0) {
+ fprintf(stderr, "could not read key secret\n");
+ return (STATUS_SYNTAX);
+ }
+ secretlen = strlen(secretstr) * 3 / 4;
+ secret = isc_mem_allocate(mctx, secretlen);
+ if (secret == NULL)
+ fatal("out of memory");
+
+ isc_buffer_init(&secretbuf, secret, secretlen);
+ result = isc_base64_decodestring(secretstr, &secretbuf);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not create key from %s: %s\n",
+ secretstr, isc_result_totext(result));
+ isc_mem_free(mctx, secret);
+ return (STATUS_SYNTAX);
+ }
+ secretlen = isc_buffer_usedlength(&secretbuf);
+
+ if (tsigkey != NULL)
+ dns_tsigkey_detach(&tsigkey);
+ result = dns_tsigkey_create(keyname, hmacname, secret, secretlen,
+ ISC_TRUE, NULL, 0, 0, mctx, NULL,
+ &tsigkey);
+ isc_mem_free(mctx, secret);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not create key from %s %s: %s\n",
+ namestr, secretstr, dns_result_totext(result));
+ return (STATUS_SYNTAX);
+ }
+ dst_key_setbits(tsigkey->key, digestbits);
+ return (STATUS_MORE);
+}
+
+static isc_uint16_t
+evaluate_zone(char *cmdline) {
+ char *word;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not read zone name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ dns_fixedname_init(&fuserzone);
+ 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);
+ if (result != ISC_R_SUCCESS) {
+ userzone = NULL; /* Lest it point to an invalid name */
+ fprintf(stderr, "could not parse zone name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ return (STATUS_MORE);
+}
+
+static isc_uint16_t
+evaluate_ttl(char *cmdline) {
+ char *word;
+ isc_result_t result;
+ isc_uint32_t ttl;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not ttl\n");
+ return (STATUS_SYNTAX);
+ }
+
+ if (!strcasecmp(word, "none")) {
+ default_ttl = 0;
+ default_ttl_set = ISC_FALSE;
+ return (STATUS_MORE);
+ }
+
+ result = isc_parse_uint32(&ttl, word, 10);
+ if (result != ISC_R_SUCCESS)
+ return (STATUS_SYNTAX);
+
+ if (ttl > TTL_MAX) {
+ fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
+ word, TTL_MAX);
+ return (STATUS_SYNTAX);
+ }
+ default_ttl = ttl;
+ default_ttl_set = ISC_TRUE;
+
+ return (STATUS_MORE);
+}
+
+static isc_uint16_t
+evaluate_class(char *cmdline) {
+ char *word;
+ isc_textregion_t r;
+ isc_result_t result;
+ dns_rdataclass_t rdclass;
+
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not read class name\n");
+ return (STATUS_SYNTAX);
+ }
+
+ r.base = word;
+ r.length = strlen(word);
+ result = dns_rdataclass_fromtext(&rdclass, &r);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not parse class name: %s\n", word);
+ return (STATUS_SYNTAX);
+ }
+ switch (rdclass) {
+ case dns_rdataclass_none:
+ case dns_rdataclass_any:
+ case dns_rdataclass_reserved0:
+ fprintf(stderr, "bad default class: %s\n", word);
+ return (STATUS_SYNTAX);
+ default:
+ defaultclass = rdclass;
+ }
+
+ return (STATUS_MORE);
+}
+
+static isc_uint16_t
+update_addordelete(char *cmdline, isc_boolean_t isdelete) {
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ 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;
+ isc_uint16_t retval;
+
+ ddebug("update_addordelete()");
+
+ /*
+ * Read the owner name.
+ */
+ retval = parse_name(&cmdline, updatemsg, &name);
+ if (retval != STATUS_MORE)
+ return (retval);
+
+ result = dns_message_gettemprdata(updatemsg, &rdata);
+ check_result(result, "dns_message_gettemprdata");
+
+ 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 == 0) {
+ if (!isdelete) {
+ fprintf(stderr, "could not read owner ttl\n");
+ goto failure;
+ }
+ 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 if (default_ttl_set) {
+ ttl = default_ttl;
+ goto parseclass;
+ } else {
+ fprintf(stderr, "ttl '%s': %s\n", word,
+ isc_result_totext(result));
+ goto failure;
+ }
+ }
+
+ if (isdelete)
+ ttl = 0;
+ else if (ttl > TTL_MAX) {
+ fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
+ word, TTL_MAX);
+ goto failure;
+ }
+
+ /*
+ * Read the class or type.
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ parseclass:
+ if (*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");
+ goto failure;
+ }
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdataclass_fromtext(&rdataclass, &region);
+ if (result == ISC_R_SUCCESS) {
+ if (!setzoneclass(rdataclass)) {
+ fprintf(stderr, "class mismatch: %s\n", word);
+ goto failure;
+ }
+ /*
+ * Now read the type.
+ */
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*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");
+ goto failure;
+ }
+ }
+ region.base = word;
+ region.length = strlen(word);
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "'%s' is not a valid type: %s\n",
+ word, isc_result_totext(result));
+ goto failure;
+ }
+ } else {
+ rdataclass = getzoneclass();
+ result = dns_rdatatype_fromtext(&rdatatype, &region);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "'%s' is not a valid class or type: "
+ "%s\n", word, isc_result_totext(result));
+ goto failure;
+ }
+ }
+
+ retval = parse_rdata(&cmdline, rdataclass, rdatatype, updatemsg,
+ rdata);
+ if (retval != STATUS_MORE)
+ goto failure;
+
+ 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");
+ goto failure;
+ }
+ }
+
+ doneparsing:
+
+ result = dns_message_gettemprdatalist(updatemsg, &rdatalist);
+ check_result(result, "dns_message_gettemprdatalist");
+ result = dns_message_gettemprdataset(updatemsg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+ 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);
+ dns_rdataset_init(rdataset);
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ dns_message_addname(updatemsg, name, DNS_SECTION_UPDATE);
+ return (STATUS_MORE);
+
+ failure:
+ if (name != NULL)
+ dns_message_puttempname(updatemsg, &name);
+ dns_message_puttemprdata(updatemsg, &rdata);
+ return (STATUS_SYNTAX);
+}
+
+static isc_uint16_t
+evaluate_update(char *cmdline) {
+ char *word;
+ isc_boolean_t isdelete;
+
+ ddebug("evaluate_update()");
+ word = nsu_strsep(&cmdline, " \t\r\n");
+ if (*word == 0) {
+ fprintf(stderr, "could not read operation code\n");
+ return (STATUS_SYNTAX);
+ }
+ if (strcasecmp(word, "delete") == 0)
+ isdelete = ISC_TRUE;
+ else if (strcasecmp(word, "add") == 0)
+ isdelete = ISC_FALSE;
+ else {
+ fprintf(stderr, "incorrect operation code: %s\n", word);
+ return (STATUS_SYNTAX);
+ }
+ return (update_addordelete(cmdline, isdelete));
+}
+
+static void
+setzone(dns_name_t *zonename) {
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ dns_rdataset_t *rdataset = NULL;
+
+ result = dns_message_firstname(updatemsg, DNS_SECTION_ZONE);
+ if (result == ISC_R_SUCCESS) {
+ dns_message_currentname(updatemsg, DNS_SECTION_ZONE, &name);
+ dns_message_removename(updatemsg, name, DNS_SECTION_ZONE);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_HEAD(name->list)) {
+ ISC_LIST_UNLINK(name->list, rdataset, link);
+ dns_rdataset_disassociate(rdataset);
+ dns_message_puttemprdataset(updatemsg, &rdataset);
+ }
+ dns_message_puttempname(updatemsg, &name);
+ }
+
+ if (zonename != NULL) {
+ result = dns_message_gettempname(updatemsg, &name);
+ check_result(result, "dns_message_gettempname");
+ dns_name_init(name, NULL);
+ dns_name_clone(zonename, name);
+ result = dns_message_gettemprdataset(updatemsg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+ dns_rdataset_makequestion(rdataset, getzoneclass(),
+ dns_rdatatype_soa);
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ dns_message_addname(updatemsg, name, DNS_SECTION_ZONE);
+ }
+}
+
+static void
+show_message(FILE *stream, dns_message_t *msg, const char *description) {
+ isc_result_t result;
+ isc_buffer_t *buf = NULL;
+ int bufsz;
+
+ ddebug("show_message()");
+
+ setzone(userzone);
+
+ bufsz = INITTEXT;
+ do {
+ if (bufsz > MAXTEXT) {
+ fprintf(stderr, "could not allocate large enough "
+ "buffer to display message\n");
+ exit(1);
+ }
+ if (buf != NULL)
+ isc_buffer_free(&buf);
+ result = isc_buffer_allocate(mctx, &buf, bufsz);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_message_totext(msg, style, 0, buf);
+ bufsz *= 2;
+ } while (result == ISC_R_NOSPACE);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "could not convert message to text format.\n");
+ isc_buffer_free(&buf);
+ return;
+ }
+ fprintf(stream, "%s\n%.*s", description,
+ (int)isc_buffer_usedlength(buf), (char*)isc_buffer_base(buf));
+ isc_buffer_free(&buf);
+}
+
+
+static isc_uint16_t
+get_next_command(void) {
+ char cmdlinebuf[MAXCMD];
+ char *cmdline;
+ char *word;
+
+ ddebug("get_next_command()");
+ if (interactive) {
+ fprintf(stdout, "> ");
+ fflush(stdout);
+ }
+ isc_app_block();
+ cmdline = fgets(cmdlinebuf, MAXCMD, input);
+ isc_app_unblock();
+ if (cmdline == NULL)
+ return (STATUS_QUIT);
+ word = nsu_strsep(&cmdline, " \t\r\n");
+
+ if (feof(input))
+ return (STATUS_QUIT);
+ if (*word == 0)
+ return (STATUS_SEND);
+ if (word[0] == ';')
+ return (STATUS_MORE);
+ if (strcasecmp(word, "quit") == 0)
+ return (STATUS_QUIT);
+ if (strcasecmp(word, "prereq") == 0)
+ return (evaluate_prereq(cmdline));
+ if (strcasecmp(word, "update") == 0)
+ return (evaluate_update(cmdline));
+ if (strcasecmp(word, "server") == 0)
+ return (evaluate_server(cmdline));
+ if (strcasecmp(word, "local") == 0)
+ return (evaluate_local(cmdline));
+ if (strcasecmp(word, "zone") == 0)
+ return (evaluate_zone(cmdline));
+ if (strcasecmp(word, "class") == 0)
+ return (evaluate_class(cmdline));
+ if (strcasecmp(word, "send") == 0)
+ return (STATUS_SEND);
+ if (strcasecmp(word, "debug") == 0) {
+ if (debugging)
+ ddebugging = ISC_TRUE;
+ else
+ debugging = ISC_TRUE;
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "ttl") == 0)
+ return (evaluate_ttl(cmdline));
+ if (strcasecmp(word, "show") == 0) {
+ show_message(stdout, updatemsg, "Outgoing update query:");
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "answer") == 0) {
+ if (answer != NULL)
+ show_message(stdout, answer, "Answer:");
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "key") == 0) {
+ usegsstsig = ISC_FALSE;
+ return (evaluate_key(cmdline));
+ }
+ if (strcasecmp(word, "gsstsig") == 0) {
+#ifdef GSSAPI
+ usegsstsig = ISC_TRUE;
+ use_win2k_gsstsig = ISC_FALSE;
+#else
+ fprintf(stderr, "gsstsig not supported\n");
+#endif
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "oldgsstsig") == 0) {
+#ifdef GSSAPI
+ usegsstsig = ISC_TRUE;
+ use_win2k_gsstsig = ISC_TRUE;
+#else
+ fprintf(stderr, "gsstsig not supported\n");
+#endif
+ return (STATUS_MORE);
+ }
+ if (strcasecmp(word, "help") == 0) {
+ fprintf(stdout,
+"local address [port] (set local resolver)\n"
+"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"
+"quit (quit, any pending update is not sent\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"
+"zone name (set the zone to be updated)\n"
+"class CLASS (set the zone's DNS class, e.g. IN (default), CH)\n"
+"prereq nxdomain name (does this name not exist)\n"
+"prereq yxdomain name (does this name exist)\n"
+"prereq nxrrset .... (does this RRset exist)\n"
+"prereq yxrrset .... (does this RRset not exist)\n"
+"update add .... (add the given record to the zone)\n"
+"update delete .... (remove the given record(s) from the zone)\n");
+ return (STATUS_MORE);
+ }
+ fprintf(stderr, "incorrect section name: %s\n", word);
+ return (STATUS_SYNTAX);
+}
+
+static isc_boolean_t
+user_interaction(void) {
+ isc_uint16_t result = STATUS_MORE;
+
+ ddebug("user_interaction()");
+ while ((result == STATUS_MORE) || (result == STATUS_SYNTAX)) {
+ result = get_next_command();
+ if (!interactive && result == STATUS_SYNTAX)
+ fatal("syntax error");
+ }
+ if (result == STATUS_SEND)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+
+}
+
+static void
+done_update(void) {
+ isc_event_t *event = global_event;
+ ddebug("done_update()");
+ isc_task_send(global_task, &event);
+}
+
+static void
+check_tsig_error(dns_rdataset_t *rdataset, isc_buffer_t *b) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_any_tsig_t tsig;
+
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "dns_rdataset_first");
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &tsig, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ if (tsig.error != 0) {
+ if (isc_buffer_remaininglength(b) < 1)
+ check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
+ isc__buffer_putstr(b, "(" /*)*/);
+ result = dns_tsigrcode_totext(tsig.error, b);
+ check_result(result, "dns_tsigrcode_totext");
+ if (isc_buffer_remaininglength(b) < 1)
+ check_result(ISC_R_NOSPACE, "isc_buffer_remaininglength");
+ isc__buffer_putstr(b, /*(*/ ")");
+ }
+}
+
+static void
+update_completed(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = NULL;
+ isc_result_t result;
+ dns_request_t *request;
+
+ UNUSED(task);
+
+ ddebug("update_completed()");
+
+ requests--;
+
+ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
+ reqev = (dns_requestevent_t *)event;
+ request = reqev->request;
+
+ if (shuttingdown) {
+ dns_request_destroy(&request);
+ isc_event_free(&event);
+ maybeshutdown();
+ return;
+ }
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "; Communication with server failed: %s\n",
+ isc_result_totext(reqev->result));
+ seenerror = ISC_TRUE;
+ goto done;
+ }
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &answer);
+ check_result(result, "dns_message_create");
+ result = dns_request_getresponse(request, answer,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ if (answer->verify_attempted)
+ ddebug("tsig verification successful");
+ break;
+ case DNS_R_CLOCKSKEW:
+ case DNS_R_EXPECTEDTSIG:
+ case DNS_R_TSIGERRORSET:
+ case DNS_R_TSIGVERIFYFAILURE:
+ case DNS_R_UNEXPECTEDTSIG:
+ case ISC_R_FAILURE:
+#if 0
+ if (usegsstsig && answer->rcode == dns_rcode_noerror) {
+ /*
+ * For MS DNS that violates RFC 2845, section 4.2
+ */
+ break;
+ }
+#endif
+ fprintf(stderr, "; TSIG error with server: %s\n",
+ isc_result_totext(result));
+ seenerror = ISC_TRUE;
+ break;
+ default:
+ check_result(result, "dns_request_getresponse");
+ }
+
+ if (answer->rcode != dns_rcode_noerror) {
+ seenerror = ISC_TRUE;
+ if (!debugging) {
+ char buf[64];
+ isc_buffer_t b;
+ dns_rdataset_t *rds;
+
+ isc_buffer_init(&b, buf, sizeof(buf) - 1);
+ result = dns_rcode_totext(answer->rcode, &b);
+ check_result(result, "dns_rcode_totext");
+ rds = dns_message_gettsig(answer, NULL);
+ if (rds != NULL)
+ check_tsig_error(rds, &b);
+ fprintf(stderr, "update failed: %.*s\n",
+ (int)isc_buffer_usedlength(&b), buf);
+ }
+ }
+ if (debugging)
+ show_message(stderr, answer, "\nReply from update query:");
+
+ done:
+ dns_request_destroy(&request);
+ if (usegsstsig) {
+ dns_name_free(&tmpzonename, mctx);
+ dns_name_free(&restart_master, mctx);
+ }
+ isc_event_free(&event);
+ done_update();
+}
+
+static void
+send_update(dns_name_t *zonename, isc_sockaddr_t *master,
+ isc_sockaddr_t *srcaddr)
+{
+ isc_result_t result;
+ dns_request_t *request = NULL;
+ unsigned int options = 0;
+
+ ddebug("send_update()");
+
+ setzone(zonename);
+
+ if (usevc)
+ options |= DNS_REQUESTOPT_TCP;
+ if (tsigkey == NULL && sig0key != NULL) {
+ result = dns_message_setsig0key(updatemsg, sig0key);
+ check_result(result, "dns_message_setsig0key");
+ }
+ if (debugging) {
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(master, addrbuf, sizeof(addrbuf));
+ fprintf(stderr, "Sending update to %s\n", addrbuf);
+ }
+
+ result = dns_request_createvia3(requestmgr, updatemsg, srcaddr,
+ master, options, tsigkey, timeout,
+ udp_timeout, udp_retries, global_task,
+ update_completed, NULL, &request);
+ check_result(result, "dns_request_createvia3");
+
+ if (debugging)
+ show_message(stdout, updatemsg, "Outgoing update query:");
+
+ requests++;
+}
+
+static void
+recvsoa(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = NULL;
+ dns_request_t *request = NULL;
+ isc_result_t result, eresult;
+ dns_message_t *rcvmsg = NULL;
+ dns_section_t section;
+ dns_name_t *name = NULL;
+ dns_rdataset_t *soaset = NULL;
+ dns_rdata_soa_t soa;
+ dns_rdata_t soarr = DNS_RDATA_INIT;
+ int pass = 0;
+ dns_name_t master;
+ nsu_requestinfo_t *reqinfo;
+ dns_message_t *soaquery = NULL;
+ isc_sockaddr_t *addr;
+ isc_boolean_t seencname = ISC_FALSE;
+ dns_name_t tname;
+ unsigned int nlabels;
+
+ UNUSED(task);
+
+ ddebug("recvsoa()");
+
+ requests--;
+
+ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
+ reqev = (dns_requestevent_t *)event;
+ request = reqev->request;
+ eresult = reqev->result;
+ reqinfo = reqev->ev_arg;
+ soaquery = reqinfo->msg;
+ addr = reqinfo->addr;
+
+ if (shuttingdown) {
+ dns_request_destroy(&request);
+ dns_message_destroy(&soaquery);
+ isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
+ isc_event_free(&event);
+ maybeshutdown();
+ return;
+ }
+
+ if (eresult != ISC_R_SUCCESS) {
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
+ fprintf(stderr, "; Communication with %s failed: %s\n",
+ addrbuf, isc_result_totext(eresult));
+ if (userserver != NULL)
+ fatal("could not talk to specified name server");
+ else if (++ns_inuse >= lwconf->nsnext)
+ fatal("could not talk to any default name server");
+ ddebug("Destroying request [%p]", request);
+ dns_request_destroy(&request);
+ dns_message_renderreset(soaquery);
+ dns_message_settsigkey(soaquery, NULL);
+ sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
+ isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
+ isc_event_free(&event);
+ setzoneclass(dns_rdataclass_none);
+ return;
+ }
+
+ isc_mem_put(mctx, reqinfo, sizeof(nsu_requestinfo_t));
+ reqinfo = NULL;
+ isc_event_free(&event);
+ reqev = NULL;
+
+ ddebug("About to create rcvmsg");
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
+ check_result(result, "dns_message_create");
+ result = dns_request_getresponse(request, rcvmsg,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ if (result == DNS_R_TSIGERRORSET && userserver != NULL) {
+ dns_message_destroy(&rcvmsg);
+ ddebug("Destroying request [%p]", request);
+ dns_request_destroy(&request);
+ reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
+ if (reqinfo == NULL)
+ fatal("out of memory");
+ reqinfo->msg = soaquery;
+ reqinfo->addr = addr;
+ dns_message_renderreset(soaquery);
+ ddebug("retrying soa request without TSIG");
+ result = dns_request_createvia3(requestmgr, soaquery,
+ localaddr, addr, 0, NULL,
+ FIND_TIMEOUT * 20,
+ FIND_TIMEOUT, 3,
+ global_task, recvsoa, reqinfo,
+ &request);
+ check_result(result, "dns_request_createvia");
+ requests++;
+ return;
+ }
+ check_result(result, "dns_request_getresponse");
+ section = DNS_SECTION_ANSWER;
+ if (debugging)
+ show_message(stderr, rcvmsg, "Reply from SOA query:");
+
+ if (rcvmsg->rcode != dns_rcode_noerror &&
+ rcvmsg->rcode != dns_rcode_nxdomain)
+ fatal("response to SOA query was unsuccessful");
+
+ if (userzone != NULL && rcvmsg->rcode == dns_rcode_nxdomain) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(userzone, namebuf, sizeof(namebuf));
+ error("specified zone '%s' does not exist (NXDOMAIN)",
+ namebuf);
+ dns_message_destroy(&rcvmsg);
+ dns_request_destroy(&request);
+ dns_message_destroy(&soaquery);
+ ddebug("Out of recvsoa");
+ done_update();
+ return;
+ }
+
+ lookforsoa:
+ if (pass == 0)
+ section = DNS_SECTION_ANSWER;
+ else if (pass == 1)
+ section = DNS_SECTION_AUTHORITY;
+ else
+ goto droplabel;
+
+ 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)
+ goto droplabel;
+
+ if (debugging) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ fprintf(stderr, "Found zone name: %s\n", namestr);
+ }
+
+ result = dns_rdataset_first(soaset);
+ check_result(result, "dns_rdataset_first");
+
+ dns_rdata_init(&soarr);
+ dns_rdataset_current(soaset, &soarr);
+ result = dns_rdata_tostruct(&soarr, &soa, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ dns_name_init(&master, NULL);
+ dns_name_clone(&soa.origin, &master);
+
+ if (userzone != NULL)
+ zonename = userzone;
+ else
+ zonename = name;
+
+ if (debugging) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(&master, namestr, sizeof(namestr));
+ fprintf(stderr, "The master is: %s\n", namestr);
+ }
+
+ if (userserver != NULL)
+ serveraddr = userserver;
+ else {
+ char serverstr[DNS_NAME_MAXTEXT+1];
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, serverstr, sizeof(serverstr));
+ 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);
+ serveraddr = &tempaddr;
+ }
+ dns_rdata_freestruct(&soa);
+
+#ifdef GSSAPI
+ if (usegsstsig) {
+ dns_name_init(&tmpzonename, NULL);
+ dns_name_dup(zonename, mctx, &tmpzonename);
+ dns_name_init(&restart_master, NULL);
+ dns_name_dup(&master, mctx, &restart_master);
+ start_gssrequest(&master);
+ } else {
+ send_update(zonename, serveraddr, localaddr);
+ setzoneclass(dns_rdataclass_none);
+ }
+#else
+ send_update(zonename, serveraddr, localaddr);
+ setzoneclass(dns_rdataclass_none);
+#endif
+
+ dns_message_destroy(&soaquery);
+ dns_request_destroy(&request);
+
+ out:
+ dns_message_destroy(&rcvmsg);
+ ddebug("Out of recvsoa");
+ return;
+
+ 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)
+ fatal("could not find enclosing zone");
+ dns_name_init(&tname, NULL);
+ dns_name_getlabelsequence(name, 1, nlabels - 1, &tname);
+ dns_name_clone(&tname, name);
+ dns_request_destroy(&request);
+ dns_message_renderreset(soaquery);
+ dns_message_settsigkey(soaquery, NULL);
+ if (userserver != NULL)
+ sendrequest(localaddr, userserver, soaquery, &request);
+ else
+ sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
+ goto out;
+}
+
+static void
+sendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ dns_message_t *msg, dns_request_t **request)
+{
+ isc_result_t result;
+ nsu_requestinfo_t *reqinfo;
+
+ reqinfo = isc_mem_get(mctx, sizeof(nsu_requestinfo_t));
+ if (reqinfo == NULL)
+ fatal("out of memory");
+ reqinfo->msg = msg;
+ reqinfo->addr = destaddr;
+ result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr, 0,
+ (userserver != NULL) ? tsigkey : NULL,
+ FIND_TIMEOUT * 20, FIND_TIMEOUT, 3,
+ global_task, recvsoa, reqinfo, request);
+ check_result(result, "dns_request_createvia");
+ requests++;
+}
+
+#ifdef GSSAPI
+static void
+start_gssrequest(dns_name_t *master)
+{
+ gss_ctx_id_t context;
+ isc_buffer_t buf;
+ isc_result_t result;
+ isc_uint32_t val = 0;
+ dns_message_t *rmsg;
+ dns_request_t *request = NULL;
+ dns_name_t *servname;
+ dns_fixedname_t fname;
+ char namestr[DNS_NAME_FORMATSIZE];
+ char keystr[DNS_NAME_FORMATSIZE];
+
+ debug("start_gssrequest");
+ usevc = ISC_TRUE;
+
+ if (gssring != NULL)
+ dns_tsigkeyring_destroy(&gssring);
+ gssring = NULL;
+ result = dns_tsigkeyring_create(mctx, &gssring);
+
+ if (result != ISC_R_SUCCESS)
+ fatal("dns_tsigkeyring_create failed: %s",
+ isc_result_totext(result));
+
+ dns_name_format(master, namestr, sizeof(namestr));
+ if (kserver == NULL) {
+ kserver = isc_mem_get(mctx, sizeof(isc_sockaddr_t));
+ if (kserver == NULL)
+ fatal("out of memory");
+ }
+ if (userserver == NULL)
+ get_address(namestr, DNSDEFAULTPORT, kserver);
+ else
+ (void)memcpy(kserver, userserver, sizeof(isc_sockaddr_t));
+
+ dns_fixedname_init(&fname);
+ servname = dns_fixedname_name(&fname);
+
+ result = isc_string_printf(servicename, sizeof(servicename),
+ "DNS/%s", namestr);
+ if (result != ISC_R_SUCCESS)
+ fatal("isc_string_printf(servicename) failed: %s",
+ 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);
+ if (result != ISC_R_SUCCESS)
+ fatal("dns_name_fromtext(servname) failed: %s",
+ isc_result_totext(result));
+
+ dns_fixedname_init(&fkname);
+ keyname = dns_fixedname_name(&fkname);
+
+ isc_random_get(&val);
+ result = isc_string_printf(keystr, sizeof(keystr), "%u.sig-%s",
+ val, namestr);
+ if (result != ISC_R_SUCCESS)
+ fatal("isc_string_printf(keystr) failed: %s",
+ isc_result_totext(result));
+ isc_buffer_init(&buf, keystr, strlen(keystr));
+ isc_buffer_add(&buf, strlen(keystr));
+
+ result = dns_name_fromtext(keyname, &buf, dns_rootname,
+ ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ fatal("dns_name_fromtext(keyname) failed: %s",
+ isc_result_totext(result));
+
+ /* Windows doesn't recognize name compression in the key name. */
+ keyname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
+
+ rmsg = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &rmsg);
+ if (result != ISC_R_SUCCESS)
+ fatal("dns_message_create failed: %s",
+ isc_result_totext(result));
+
+ /* Build first request. */
+
+ context = GSS_C_NO_CONTEXT;
+ result = dns_tkey_buildgssquery(rmsg, keyname, servname, NULL, 0,
+ &context, use_win2k_gsstsig);
+ if (result == ISC_R_FAILURE)
+ fatal("Check your Kerberos ticket, it may have expired.");
+ if (result != ISC_R_SUCCESS)
+ fatal("dns_tkey_buildgssquery failed: %s",
+ isc_result_totext(result));
+
+ send_gssrequest(localaddr, kserver, rmsg, &request, context);
+}
+
+static void
+send_gssrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ dns_message_t *msg, dns_request_t **request,
+ gss_ctx_id_t context)
+{
+ isc_result_t result;
+ nsu_gssinfo_t *reqinfo;
+ unsigned int options = 0;
+
+ debug("send_gssrequest");
+ reqinfo = isc_mem_get(mctx, sizeof(nsu_gssinfo_t));
+ if (reqinfo == NULL)
+ fatal("out of memory");
+ reqinfo->msg = msg;
+ reqinfo->addr = destaddr;
+ reqinfo->context = context;
+
+ options |= DNS_REQUESTOPT_TCP;
+ result = dns_request_createvia3(requestmgr, msg, srcaddr, destaddr,
+ options, tsigkey, FIND_TIMEOUT * 20,
+ FIND_TIMEOUT, 3, global_task, recvgss,
+ reqinfo, request);
+ check_result(result, "dns_request_createvia3");
+ if (debugging)
+ show_message(stdout, msg, "Outgoing update query:");
+ requests++;
+}
+
+static void
+recvgss(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = NULL;
+ dns_request_t *request = NULL;
+ isc_result_t result, eresult;
+ dns_message_t *rcvmsg = NULL;
+ nsu_gssinfo_t *reqinfo;
+ dns_message_t *tsigquery = NULL;
+ isc_sockaddr_t *addr;
+ gss_ctx_id_t context;
+ isc_buffer_t buf;
+ dns_name_t *servname;
+ dns_fixedname_t fname;
+
+ UNUSED(task);
+
+ ddebug("recvgss()");
+
+ requests--;
+
+ REQUIRE(event->ev_type == DNS_EVENT_REQUESTDONE);
+ reqev = (dns_requestevent_t *)event;
+ request = reqev->request;
+ eresult = reqev->result;
+ reqinfo = reqev->ev_arg;
+ tsigquery = reqinfo->msg;
+ context = reqinfo->context;
+ addr = reqinfo->addr;
+
+ if (shuttingdown) {
+ dns_request_destroy(&request);
+ dns_message_destroy(&tsigquery);
+ isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
+ isc_event_free(&event);
+ maybeshutdown();
+ return;
+ }
+
+ if (eresult != ISC_R_SUCCESS) {
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(addr, addrbuf, sizeof(addrbuf));
+ fprintf(stderr, "; Communication with %s failed: %s\n",
+ addrbuf, isc_result_totext(eresult));
+ if (userserver != NULL)
+ fatal("could not talk to specified name server");
+ else if (++ns_inuse >= lwconf->nsnext)
+ fatal("could not talk to any default name server");
+ ddebug("Destroying request [%p]", request);
+ dns_request_destroy(&request);
+ dns_message_renderreset(tsigquery);
+ sendrequest(localaddr, &servers[ns_inuse], tsigquery,
+ &request);
+ isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
+ isc_event_free(&event);
+ return;
+ }
+ isc_mem_put(mctx, reqinfo, sizeof(nsu_gssinfo_t));
+
+ isc_event_free(&event);
+ reqev = NULL;
+
+ ddebug("recvgss creating rcvmsg");
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rcvmsg);
+ check_result(result, "dns_message_create");
+
+ result = dns_request_getresponse(request, rcvmsg,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ check_result(result, "dns_request_getresponse");
+
+ if (debugging)
+ show_message(stderr, rcvmsg,
+ "recvmsg reply from GSS-TSIG query");
+
+ if (rcvmsg->rcode == dns_rcode_formerr && !tried_other_gsstsig) {
+ ddebug("recvgss trying %s GSS-TSIG",
+ use_win2k_gsstsig ? "Standard" : "Win2k");
+ if (use_win2k_gsstsig)
+ use_win2k_gsstsig = ISC_FALSE;
+ else
+ use_win2k_gsstsig = ISC_TRUE;
+ tried_other_gsstsig = ISC_TRUE;
+ start_gssrequest(&restart_master);
+ goto done;
+ }
+
+ if (rcvmsg->rcode != dns_rcode_noerror &&
+ rcvmsg->rcode != dns_rcode_nxdomain)
+ fatal("response to GSS-TSIG query was unsuccessful");
+
+
+ dns_fixedname_init(&fname);
+ 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);
+ check_result(result, "dns_name_fromtext");
+
+ tsigkey = NULL;
+ result = dns_tkey_gssnegotiate(tsigquery, rcvmsg, servname,
+ &context, &tsigkey, gssring,
+ use_win2k_gsstsig);
+ switch (result) {
+
+ case DNS_R_CONTINUE:
+ send_gssrequest(localaddr, kserver, tsigquery, &request,
+ context);
+ break;
+
+ case ISC_R_SUCCESS:
+ /*
+ * XXXSRA Waaay too much fun here. There's no good
+ * reason why we need a TSIG here (the people who put
+ * it into the spec admitted at the time that it was
+ * not a security issue), and Windows clients don't
+ * seem to work if named complies with the spec and
+ * includes the gratuitous TSIG. So we're in the
+ * bizzare situation of having to choose between
+ * complying with a useless requirement in the spec
+ * and interoperating. This is nuts. If we can
+ * confirm this behavior, we should ask the WG to
+ * consider removing the requirement for the
+ * gratuitous TSIG here. For the moment, we ignore
+ * the TSIG -- this too is a spec violation, but it's
+ * the least insane thing to do.
+ */
+#if 0
+ /*
+ * Verify the signature.
+ */
+ rcvmsg->state = DNS_SECTION_ANY;
+ dns_message_setquerytsig(rcvmsg, NULL);
+ result = dns_message_settsigkey(rcvmsg, tsigkey);
+ check_result(result, "dns_message_settsigkey");
+ result = dns_message_checksig(rcvmsg, NULL);
+ ddebug("tsig verification: %s", dns_result_totext(result));
+ check_result(result, "dns_message_checksig");
+#endif /* 0 */
+
+ send_update(&tmpzonename, serveraddr, localaddr);
+ setzoneclass(dns_rdataclass_none);
+ break;
+
+ default:
+ fatal("dns_tkey_negotiategss: %s", isc_result_totext(result));
+ }
+
+ done:
+ dns_request_destroy(&request);
+ dns_message_destroy(&tsigquery);
+
+ dns_message_destroy(&rcvmsg);
+ ddebug("Out of recvgss");
+}
+#endif
+
+static void
+start_update(void) {
+ isc_result_t result;
+ dns_rdataset_t *rdataset = NULL;
+ dns_name_t *name = NULL;
+ dns_request_t *request = NULL;
+ dns_message_t *soaquery = NULL;
+ dns_name_t *firstname;
+ dns_section_t section = DNS_SECTION_UPDATE;
+
+ ddebug("start_update()");
+
+ if (answer != NULL)
+ dns_message_destroy(&answer);
+
+ if (userzone != NULL && userserver != NULL && ! usegsstsig) {
+ send_update(userzone, userserver, localaddr);
+ setzoneclass(dns_rdataclass_none);
+ return;
+ }
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
+ &soaquery);
+ check_result(result, "dns_message_create");
+
+ if (userserver == NULL)
+ soaquery->flags |= DNS_MESSAGEFLAG_RD;
+
+ result = dns_message_gettempname(soaquery, &name);
+ check_result(result, "dns_message_gettempname");
+
+ result = dns_message_gettemprdataset(soaquery, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+
+ dns_rdataset_makequestion(rdataset, getzoneclass(), dns_rdatatype_soa);
+
+ if (userzone != NULL) {
+ dns_name_init(name, NULL);
+ dns_name_clone(userzone, name);
+ } else {
+ result = dns_message_firstname(updatemsg, section);
+ if (result == ISC_R_NOMORE) {
+ section = DNS_SECTION_PREREQUISITE;
+ result = dns_message_firstname(updatemsg, section);
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(soaquery, &name);
+ dns_rdataset_disassociate(rdataset);
+ dns_message_puttemprdataset(soaquery, &rdataset);
+ dns_message_destroy(&soaquery);
+ done_update();
+ return;
+ }
+ firstname = NULL;
+ dns_message_currentname(updatemsg, section, &firstname);
+ dns_name_init(name, NULL);
+ dns_name_clone(firstname, name);
+ }
+
+ ISC_LIST_INIT(name->list);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
+
+ if (userserver != NULL)
+ sendrequest(localaddr, userserver, soaquery, &request);
+ else {
+ ns_inuse = 0;
+ sendrequest(localaddr, &servers[ns_inuse], soaquery, &request);
+ }
+}
+
+static void
+cleanup(void) {
+ ddebug("cleanup()");
+
+ if (answer != NULL)
+ dns_message_destroy(&answer);
+
+#ifdef GSSAPI
+ if (tsigkey != NULL) {
+ ddebug("detach tsigkey x%p", tsigkey);
+ dns_tsigkey_detach(&tsigkey);
+ }
+ if (gssring != NULL) {
+ ddebug("Destroying GSS-TSIG keyring");
+ dns_tsigkeyring_destroy(&gssring);
+ }
+ if (kserver != NULL) {
+ isc_mem_put(mctx, kserver, sizeof(isc_sockaddr_t));
+ kserver = NULL;
+ }
+#endif
+
+ ddebug("Shutting down task manager");
+ isc_taskmgr_destroy(&taskmgr);
+
+ ddebug("Destroying event");
+ isc_event_free(&global_event);
+
+ ddebug("Shutting down socket manager");
+ isc_socketmgr_destroy(&socketmgr);
+
+ ddebug("Shutting down timer manager");
+ isc_timermgr_destroy(&timermgr);
+
+ ddebug("Destroying hash context");
+ isc_hash_destroy();
+
+ ddebug("Destroying name state");
+ dns_name_destroy();
+
+ ddebug("Removing log context");
+ isc_log_destroy(&lctx);
+
+ ddebug("Destroying memory context");
+ if (memdebugging)
+ isc_mem_stats(mctx, stderr);
+ isc_mem_destroy(&mctx);
+}
+
+static void
+getinput(isc_task_t *task, isc_event_t *event) {
+ isc_boolean_t more;
+
+ UNUSED(task);
+
+ if (shuttingdown) {
+ maybeshutdown();
+ return;
+ }
+
+ if (global_event == NULL)
+ global_event = event;
+
+ reset_system();
+ more = user_interaction();
+ if (!more) {
+ isc_app_shutdown();
+ return;
+ }
+ start_update();
+ return;
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+ style = &dns_master_style_debug;
+
+ input = stdin;
+
+ interactive = ISC_TF(isatty(0));
+
+ isc_app_start();
+
+ pre_parse_args(argc, argv);
+
+ result = isc_mem_create(0, 0, &mctx);
+ check_result(result, "isc_mem_create");
+
+ parse_args(argc, argv, mctx, &entropy);
+
+ setup_system();
+
+ result = isc_app_onrun(mctx, global_task, getinput, NULL);
+ check_result(result, "isc_app_onrun");
+
+ (void)isc_app_run();
+
+ cleanup();
+
+ isc_app_finish();
+
+ if (seenerror)
+ return (2);
+ else
+ return (0);
+}
diff --git a/bin/nsupdate/nsupdate.docbook b/bin/nsupdate/nsupdate.docbook
new file mode 100644
index 0000000..9787758
--- /dev/null
+++ b/bin/nsupdate/nsupdate.docbook
@@ -0,0 +1,701 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - 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
+ - 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: nsupdate.docbook,v 1.34 2008/09/25 02:20:27 marka Exp $ -->
+<refentry id="man.nsupdate">
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+ <refmeta>
+ <refentrytitle><application>nsupdate</application></refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+ <refnamediv>
+ <refname><application>nsupdate</application></refname>
+ <refpurpose>Dynamic DNS update utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>nsupdate</command>
+ <arg><option>-d</option></arg>
+ <arg><option>-D</option></arg>
+ <group>
+ <arg><option>-y <replaceable class="parameter"><optional>hmac:</optional>keyname:secret</replaceable></option></arg>
+ <arg><option>-k <replaceable class="parameter">keyfile</replaceable></option></arg>
+ </group>
+ <arg><option>-t <replaceable class="parameter">timeout</replaceable></option></arg>
+ <arg><option>-u <replaceable class="parameter">udptimeout</replaceable></option></arg>
+ <arg><option>-r <replaceable class="parameter">udpretries</replaceable></option></arg>
+ <arg><option>-R <replaceable class="parameter">randomdev</replaceable></option></arg>
+ <arg><option>-v</option></arg>
+ <arg>filename</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>nsupdate</command>
+ 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.
+ </para>
+ <para>
+ Zones that are under dynamic control via
+ <command>nsupdate</command>
+ or a DHCP server should not be edited by hand.
+ Manual edits could
+ conflict with dynamic updates and cause data to be lost.
+ </para>
+ <para>
+ The resource records that are dynamically added or removed with
+ <command>nsupdate</command>
+ have to be in the same zone.
+ Requests are sent to the zone's master server.
+ This is identified by the MNAME field of the zone's SOA record.
+ </para>
+ <para>
+ The
+ <option>-d</option>
+ option makes
+ <command>nsupdate</command>
+ operate in debug mode.
+ This provides tracing information about the update requests that are
+ made and the replies received from the name server.
+ </para>
+ <para>
+ The <option>-D</option> option makes <command>nsupdate</command>
+ report additional debugging information to <option>-d</option>.
+ </para>
+ <para>
+ 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.
+ TSIG relies on a shared secret that should only be known to
+ <command>nsupdate</command> 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
+ <type>key</type>
+ and
+ <type>server</type>
+ statements would be added to
+ <filename>/etc/named.conf</filename>
+ 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.
+ <command>nsupdate</command>
+ does not read
+ <filename>/etc/named.conf</filename>.
+ </para>
+ <para><command>nsupdate</command>
+ uses the <option>-y</option> or <option>-k</option> 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>-k</option> option, <command>nsupdate</command> reads
+ the shared secret from the file <parameter>keyfile</parameter>,
+ whose name is of the form
+ <filename>K{name}.+157.+{random}.private</filename>. For
+ historical reasons, the file
+ <filename>K{name}.+157.+{random}.key</filename> must also be
+ present. When the <option>-y</option> option is used, a
+ signature is generated from
+ <optional><parameter>hmac:</parameter></optional><parameter>keyname:secret.</parameter>
+ <parameter>keyname</parameter> is the name of the key, and
+ <parameter>secret</parameter> is the base64 encoded shared
+ secret. Use of the <option>-y</option> 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
+ <citerefentry>
+ <refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry> or in a history file maintained by the user's
+ shell.
+ </para>
+ <para>
+ The <option>-k</option> 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.
+ </para>
+ <para>
+ By default
+ <command>nsupdate</command>
+ 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
+ <option>-v</option>
+ option makes
+ <command>nsupdate</command>
+ use a TCP connection.
+ This may be preferable when a batch of update requests is made.
+ </para>
+ <para>
+ The <option>-t</option> 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.
+ </para>
+ <para>
+ The <option>-u</option> option sets the UDP retry interval. The default
+ is
+ 3 seconds. If zero, the interval will be computed from the timeout
+ interval
+ and number of UDP retries.
+ </para>
+ <para>
+ The <option>-r</option> option sets the number of UDP retries. The
+ default is
+ 3. If zero, only one update request will be made.
+ </para>
+ <para>
+ The <option>-R <replaceable
+ class="parameter">randomdev</replaceable></option> option
+ specifies a source of randomness. If the operating system
+ does not provide a <filename>/dev/random</filename> or
+ equivalent device, the default source of randomness is keyboard
+ input. <filename>randomdev</filename> specifies the name of
+ a character device or file containing random data to be used
+ instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard input
+ should be used. This option may be specified multiple times.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>INPUT FORMAT</title>
+ <para><command>nsupdate</command>
+ reads input from
+ <parameter>filename</parameter>
+ or standard input.
+ Each command is supplied on exactly one line of input.
+ Some commands are for administrative purposes.
+ The others are either update instructions or prerequisite checks on the
+ contents of the zone.
+ These checks set conditions that some name or set of
+ resource records (RRset) either exists or is absent from the zone.
+ These conditions must be met if the entire update request is to succeed.
+ Updates will be rejected if the tests for the prerequisite conditions
+ fail.
+ </para>
+ <para>
+ Every update request consists of zero or more prerequisites
+ and zero or more updates.
+ This allows a suitably authenticated update request to proceed if some
+ specified resource records are present or missing from the zone.
+ A blank input line (or the <command>send</command> command)
+ causes the
+ accumulated commands to be sent as one Dynamic DNS update request to the
+ name server.
+ </para>
+ <para>
+ The command formats and their meaning are as follows:
+ <variablelist>
+
+ <varlistentry>
+ <term>
+ <command>server</command>
+ <arg choice="req">servername</arg>
+ <arg choice="opt">port</arg>
+ </term>
+ <listitem>
+ <para>
+ Sends all dynamic update requests to the name server
+ <parameter>servername</parameter>.
+ When no server statement is provided,
+ <command>nsupdate</command>
+ will send updates to the master server of the correct zone.
+ The MNAME field of that zone's SOA record will identify the
+ master
+ server for that zone.
+ <parameter>port</parameter>
+ is the port number on
+ <parameter>servername</parameter>
+ where the dynamic update requests get sent.
+ If no port number is specified, the default DNS port number of
+ 53 is
+ used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>local</command>
+ <arg choice="req">address</arg>
+ <arg choice="opt">port</arg>
+ </term>
+ <listitem>
+ <para>
+ Sends all dynamic update requests using the local
+ <parameter>address</parameter>.
+
+ When no local statement is provided,
+ <command>nsupdate</command>
+ will send updates using an address and port chosen by the
+ system.
+ <parameter>port</parameter>
+ can additionally be used to make requests come from a specific
+ port.
+ If no port number is specified, the system will assign one.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>zone</command>
+ <arg choice="req">zonename</arg>
+ </term>
+ <listitem>
+ <para>
+ Specifies that all updates are to be made to the zone
+ <parameter>zonename</parameter>.
+ If no
+ <parameter>zone</parameter>
+ statement is provided,
+ <command>nsupdate</command>
+ will attempt determine the correct zone to update based on the
+ rest of the input.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>class</command>
+ <arg choice="req">classname</arg>
+ </term>
+ <listitem>
+ <para>
+ Specify the default class.
+ If no <parameter>class</parameter> is specified, the
+ default class is
+ <parameter>IN</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>ttl</command>
+ <arg choice="req">seconds</arg>
+ </term>
+ <listitem>
+ <para>
+ Specify the default time to live for records to be added.
+ The value <parameter>none</parameter> will clear the default
+ ttl.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>key</command>
+ <arg choice="req">name</arg>
+ <arg choice="req">secret</arg>
+ </term>
+ <listitem>
+ <para>
+ Specifies that all updates are to be TSIG-signed using the
+ <parameter>keyname</parameter> <parameter>keysecret</parameter> pair.
+ The <command>key</command> command
+ overrides any key specified on the command line via
+ <option>-y</option> or <option>-k</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>prereq nxdomain</command>
+ <arg choice="req">domain-name</arg>
+ </term>
+ <listitem>
+ <para>
+ Requires that no resource record of any type exists with name
+ <parameter>domain-name</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <command>prereq yxdomain</command>
+ <arg choice="req">domain-name</arg>
+ </term>
+ <listitem>
+ <para>
+ Requires that
+ <parameter>domain-name</parameter>
+ exists (has as at least one resource record, of any type).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>prereq nxrrset</command>
+ <arg choice="req">domain-name</arg>
+ <arg choice="opt">class</arg>
+ <arg choice="req">type</arg>
+ </term>
+ <listitem>
+ <para>
+ Requires that no resource record exists of the specified
+ <parameter>type</parameter>,
+ <parameter>class</parameter>
+ and
+ <parameter>domain-name</parameter>.
+ If
+ <parameter>class</parameter>
+ is omitted, IN (internet) is assumed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term>
+ <command>prereq yxrrset</command>
+ <arg choice="req">domain-name</arg>
+ <arg choice="opt">class</arg>
+ <arg choice="req">type</arg>
+ </term>
+ <listitem>
+ <para>
+ This requires that a resource record of the specified
+ <parameter>type</parameter>,
+ <parameter>class</parameter>
+ and
+ <parameter>domain-name</parameter>
+ must exist.
+ If
+ <parameter>class</parameter>
+ is omitted, IN (internet) is assumed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>prereq yxrrset</command>
+ <arg choice="req">domain-name</arg>
+ <arg choice="opt">class</arg>
+ <arg choice="req">type</arg>
+ <arg choice="req" rep="repeat">data</arg>
+ </term>
+ <listitem>
+ <para>
+ The
+ <parameter>data</parameter>
+ from each set of prerequisites of this form
+ sharing a common
+ <parameter>type</parameter>,
+ <parameter>class</parameter>,
+ and
+ <parameter>domain-name</parameter>
+ are combined to form a set of RRs. This set of RRs must
+ exactly match the set of RRs existing in the zone at the
+ given
+ <parameter>type</parameter>,
+ <parameter>class</parameter>,
+ and
+ <parameter>domain-name</parameter>.
+ The
+ <parameter>data</parameter>
+ are written in the standard text representation of the resource
+ record's
+ RDATA.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>update delete</command>
+ <arg choice="req">domain-name</arg>
+ <arg choice="opt">ttl</arg>
+ <arg choice="opt">class</arg>
+ <arg choice="opt">type <arg choice="opt" rep="repeat">data</arg></arg>
+ </term>
+ <listitem>
+ <para>
+ Deletes any resource records named
+ <parameter>domain-name</parameter>.
+ If
+ <parameter>type</parameter>
+ and
+ <parameter>data</parameter>
+ is provided, only matching resource records will be removed.
+ The internet class is assumed if
+ <parameter>class</parameter>
+ is not supplied. The
+ <parameter>ttl</parameter>
+ is ignored, and is only allowed for compatibility.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>update add</command>
+ <arg choice="req">domain-name</arg>
+ <arg choice="req">ttl</arg>
+ <arg choice="opt">class</arg>
+ <arg choice="req">type</arg>
+ <arg choice="req" rep="repeat">data</arg>
+ </term>
+ <listitem>
+ <para>
+ Adds a new resource record with the specified
+ <parameter>ttl</parameter>,
+ <parameter>class</parameter>
+ and
+ <parameter>data</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>show</command>
+ </term>
+ <listitem>
+ <para>
+ Displays the current message, containing all of the
+ prerequisites and
+ updates specified since the last send.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>send</command>
+ </term>
+ <listitem>
+ <para>
+ Sends the current message. This is equivalent to entering a
+ blank line.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>answer</command>
+ </term>
+ <listitem>
+ <para>
+ Displays the answer.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <command>debug</command>
+ </term>
+ <listitem>
+ <para>
+ Turn on debugging.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+
+ <para>
+ Lines beginning with a semicolon are comments and are ignored.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLES</title>
+ <para>
+ The examples below show how
+ <command>nsupdate</command>
+ could be used to insert and delete resource records from the
+ <type>example.com</type>
+ zone.
+ Notice that the input in each example contains a trailing blank line so
+ that
+ a group of commands are sent as one dynamic update request to the
+ master name server for
+ <type>example.com</type>.
+
+ <programlisting>
+# nsupdate
+&gt; update delete oldhost.example.com A
+&gt; update add newhost.example.com 86400 A 172.16.1.1
+&gt; send
+</programlisting>
+ </para>
+ <para>
+ Any A records for
+ <type>oldhost.example.com</type>
+ are deleted.
+ And an A record for
+ <type>newhost.example.com</type>
+ with IP address 172.16.1.1 is added.
+ The newly-added record has a 1 day TTL (86400 seconds).
+ <programlisting>
+# nsupdate
+&gt; prereq nxdomain nickname.example.com
+&gt; update add nickname.example.com 86400 CNAME somehost.example.com
+&gt; send
+</programlisting>
+ </para>
+ <para>
+ The prerequisite condition gets the name server to check that there
+ are no resource records of any type for
+ <type>nickname.example.com</type>.
+
+ 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.)
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>/etc/resolv.conf</constant></term>
+ <listitem>
+ <para>
+ used to identify default name server
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>K{name}.+157.+{random}.key</constant></term>
+ <listitem>
+ <para>
+ base-64 encoding of HMAC-MD5 key created by
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>K{name}.+157.+{random}.private</constant></term>
+ <listitem>
+ <para>
+ base-64 encoding of HMAC-MD5 key created by
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>RFC2136</refentrytitle>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>RFC3007</refentrytitle>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>RFC2104</refentrytitle>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>RFC2845</refentrytitle>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>RFC1034</refentrytitle>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>RFC2535</refentrytitle>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>RFC2931</refentrytitle>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+
+ </refsect1>
+ <refsect1>
+ <title>BUGS</title>
+ <para>
+ The TSIG key is redundantly stored in two separate files.
+ This is a consequence of nsupdate using the DST library
+ for its cryptographic operations, and may change in future
+ releases.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/nsupdate/nsupdate.html b/bin/nsupdate/nsupdate.html
new file mode 100644
index 0000000..9d29806
--- /dev/null
+++ b/bin/nsupdate/nsupdate.html
@@ -0,0 +1,530 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: nsupdate.html,v 1.40 2008/09/25 04:45:04 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>nsupdate</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.nsupdate"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">nsupdate</span> &#8212; Dynamic DNS update utility</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">nsupdate</code> [<code class="option">-d</code>] [<code class="option">-D</code>] [[<code class="option">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]keyname:secret</code></em></code>] | [<code class="option">-k <em class="replaceable"><code>keyfile</code></em></code>]] [<code class="option">-t <em class="replaceable"><code>timeout</code></em></code>] [<code class="option">-u <em class="replaceable"><code>udptimeout</code></em></code>] [<code class="option">-r <em class="replaceable"><code>udpretries</code></em></code>] [<code class="option">-R <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-v</code>] [filename]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543437"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">nsupdate</strong></span>
+ 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.
+ </p>
+<p>
+ Zones that are under dynamic control via
+ <span><strong class="command">nsupdate</strong></span>
+ or a DHCP server should not be edited by hand.
+ Manual edits could
+ conflict with dynamic updates and cause data to be lost.
+ </p>
+<p>
+ The resource records that are dynamically added or removed with
+ <span><strong class="command">nsupdate</strong></span>
+ have to be in the same zone.
+ Requests are sent to the zone's master server.
+ This is identified by the MNAME field of the zone's SOA record.
+ </p>
+<p>
+ The
+ <code class="option">-d</code>
+ option makes
+ <span><strong class="command">nsupdate</strong></span>
+ operate in debug mode.
+ This provides tracing information about the update requests that are
+ made and the replies received from the name server.
+ </p>
+<p>
+ The <code class="option">-D</code> option makes <span><strong class="command">nsupdate</strong></span>
+ report additional debugging information to <code class="option">-d</code>.
+ </p>
+<p>
+ 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.
+ TSIG relies on a shared secret that should only be known to
+ <span><strong class="command">nsupdate</strong></span> 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
+ <span class="type">key</span>
+ and
+ <span class="type">server</span>
+ statements would be added to
+ <code class="filename">/etc/named.conf</code>
+ 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.
+ <span><strong class="command">nsupdate</strong></span>
+ does not read
+ <code class="filename">/etc/named.conf</code>.
+ </p>
+<p><span><strong class="command">nsupdate</strong></span>
+ uses the <code class="option">-y</code> or <code class="option">-k</code> 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
+ <code class="option">-k</code> option, <span><strong class="command">nsupdate</strong></span> reads
+ the shared secret from the file <em class="parameter"><code>keyfile</code></em>,
+ whose name is of the form
+ <code class="filename">K{name}.+157.+{random}.private</code>. For
+ historical reasons, the file
+ <code class="filename">K{name}.+157.+{random}.key</code> must also be
+ present. When the <code class="option">-y</code> option is used, a
+ signature is generated from
+ [<span class="optional"><em class="parameter"><code>hmac:</code></em></span>]<em class="parameter"><code>keyname:secret.</code></em>
+ <em class="parameter"><code>keyname</code></em> is the name of the key, and
+ <em class="parameter"><code>secret</code></em> is the base64 encoded shared
+ secret. Use of the <code class="option">-y</code> 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
+ <span class="citerefentry"><span class="refentrytitle">ps</span>(1)</span> or in a history file maintained by the user's
+ shell.
+ </p>
+<p>
+ The <code class="option">-k</code> 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.
+ </p>
+<p>
+ By default
+ <span><strong class="command">nsupdate</strong></span>
+ 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
+ <code class="option">-v</code>
+ option makes
+ <span><strong class="command">nsupdate</strong></span>
+ use a TCP connection.
+ This may be preferable when a batch of update requests is made.
+ </p>
+<p>
+ The <code class="option">-t</code> 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.
+ </p>
+<p>
+ The <code class="option">-u</code> option sets the UDP retry interval. The default
+ is
+ 3 seconds. If zero, the interval will be computed from the timeout
+ interval
+ and number of UDP retries.
+ </p>
+<p>
+ The <code class="option">-r</code> option sets the number of UDP retries. The
+ default is
+ 3. If zero, only one update request will be made.
+ </p>
+<p>
+ The <code class="option">-R <em class="replaceable"><code>randomdev</code></em></code> option
+ specifies a source of randomness. If the operating system
+ does not provide a <code class="filename">/dev/random</code> or
+ equivalent device, the default source of randomness is keyboard
+ input. <code class="filename">randomdev</code> specifies the name of
+ a character device or file containing random data to be used
+ instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard input
+ should be used. This option may be specified multiple times.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543700"></a><h2>INPUT FORMAT</h2>
+<p><span><strong class="command">nsupdate</strong></span>
+ reads input from
+ <em class="parameter"><code>filename</code></em>
+ or standard input.
+ Each command is supplied on exactly one line of input.
+ Some commands are for administrative purposes.
+ The others are either update instructions or prerequisite checks on the
+ contents of the zone.
+ These checks set conditions that some name or set of
+ resource records (RRset) either exists or is absent from the zone.
+ These conditions must be met if the entire update request is to succeed.
+ Updates will be rejected if the tests for the prerequisite conditions
+ fail.
+ </p>
+<p>
+ Every update request consists of zero or more prerequisites
+ and zero or more updates.
+ This allows a suitably authenticated update request to proceed if some
+ specified resource records are present or missing from the zone.
+ A blank input line (or the <span><strong class="command">send</strong></span> command)
+ causes the
+ accumulated commands to be sent as one Dynamic DNS update request to the
+ name server.
+ </p>
+<p>
+ The command formats and their meaning are as follows:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term">
+ <span><strong class="command">server</strong></span>
+ {servername}
+ [port]
+ </span></dt>
+<dd><p>
+ Sends all dynamic update requests to the name server
+ <em class="parameter"><code>servername</code></em>.
+ When no server statement is provided,
+ <span><strong class="command">nsupdate</strong></span>
+ will send updates to the master server of the correct zone.
+ The MNAME field of that zone's SOA record will identify the
+ master
+ server for that zone.
+ <em class="parameter"><code>port</code></em>
+ is the port number on
+ <em class="parameter"><code>servername</code></em>
+ where the dynamic update requests get sent.
+ If no port number is specified, the default DNS port number of
+ 53 is
+ used.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">local</strong></span>
+ {address}
+ [port]
+ </span></dt>
+<dd><p>
+ Sends all dynamic update requests using the local
+ <em class="parameter"><code>address</code></em>.
+
+ When no local statement is provided,
+ <span><strong class="command">nsupdate</strong></span>
+ will send updates using an address and port chosen by the
+ system.
+ <em class="parameter"><code>port</code></em>
+ can additionally be used to make requests come from a specific
+ port.
+ If no port number is specified, the system will assign one.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">zone</strong></span>
+ {zonename}
+ </span></dt>
+<dd><p>
+ Specifies that all updates are to be made to the zone
+ <em class="parameter"><code>zonename</code></em>.
+ If no
+ <em class="parameter"><code>zone</code></em>
+ statement is provided,
+ <span><strong class="command">nsupdate</strong></span>
+ will attempt determine the correct zone to update based on the
+ rest of the input.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">class</strong></span>
+ {classname}
+ </span></dt>
+<dd><p>
+ Specify the default class.
+ If no <em class="parameter"><code>class</code></em> is specified, the
+ default class is
+ <em class="parameter"><code>IN</code></em>.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">ttl</strong></span>
+ {seconds}
+ </span></dt>
+<dd><p>
+ Specify the default time to live for records to be added.
+ The value <em class="parameter"><code>none</code></em> will clear the default
+ ttl.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">key</strong></span>
+ {name}
+ {secret}
+ </span></dt>
+<dd><p>
+ Specifies that all updates are to be TSIG-signed using the
+ <em class="parameter"><code>keyname</code></em> <em class="parameter"><code>keysecret</code></em> pair.
+ The <span><strong class="command">key</strong></span> command
+ overrides any key specified on the command line via
+ <code class="option">-y</code> or <code class="option">-k</code>.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">prereq nxdomain</strong></span>
+ {domain-name}
+ </span></dt>
+<dd><p>
+ Requires that no resource record of any type exists with name
+ <em class="parameter"><code>domain-name</code></em>.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">prereq yxdomain</strong></span>
+ {domain-name}
+ </span></dt>
+<dd><p>
+ Requires that
+ <em class="parameter"><code>domain-name</code></em>
+ exists (has as at least one resource record, of any type).
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">prereq nxrrset</strong></span>
+ {domain-name}
+ [class]
+ {type}
+ </span></dt>
+<dd><p>
+ Requires that no resource record exists of the specified
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>
+ and
+ <em class="parameter"><code>domain-name</code></em>.
+ If
+ <em class="parameter"><code>class</code></em>
+ is omitted, IN (internet) is assumed.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">prereq yxrrset</strong></span>
+ {domain-name}
+ [class]
+ {type}
+ </span></dt>
+<dd><p>
+ This requires that a resource record of the specified
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>
+ and
+ <em class="parameter"><code>domain-name</code></em>
+ must exist.
+ If
+ <em class="parameter"><code>class</code></em>
+ is omitted, IN (internet) is assumed.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">prereq yxrrset</strong></span>
+ {domain-name}
+ [class]
+ {type}
+ {data...}
+ </span></dt>
+<dd><p>
+ The
+ <em class="parameter"><code>data</code></em>
+ from each set of prerequisites of this form
+ sharing a common
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>,
+ and
+ <em class="parameter"><code>domain-name</code></em>
+ are combined to form a set of RRs. This set of RRs must
+ exactly match the set of RRs existing in the zone at the
+ given
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>,
+ and
+ <em class="parameter"><code>domain-name</code></em>.
+ The
+ <em class="parameter"><code>data</code></em>
+ are written in the standard text representation of the resource
+ record's
+ RDATA.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">update delete</strong></span>
+ {domain-name}
+ [ttl]
+ [class]
+ [type [data...]]
+ </span></dt>
+<dd><p>
+ Deletes any resource records named
+ <em class="parameter"><code>domain-name</code></em>.
+ If
+ <em class="parameter"><code>type</code></em>
+ and
+ <em class="parameter"><code>data</code></em>
+ is provided, only matching resource records will be removed.
+ The internet class is assumed if
+ <em class="parameter"><code>class</code></em>
+ is not supplied. The
+ <em class="parameter"><code>ttl</code></em>
+ is ignored, and is only allowed for compatibility.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">update add</strong></span>
+ {domain-name}
+ {ttl}
+ [class]
+ {type}
+ {data...}
+ </span></dt>
+<dd><p>
+ Adds a new resource record with the specified
+ <em class="parameter"><code>ttl</code></em>,
+ <em class="parameter"><code>class</code></em>
+ and
+ <em class="parameter"><code>data</code></em>.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">show</strong></span>
+ </span></dt>
+<dd><p>
+ Displays the current message, containing all of the
+ prerequisites and
+ updates specified since the last send.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">send</strong></span>
+ </span></dt>
+<dd><p>
+ Sends the current message. This is equivalent to entering a
+ blank line.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">answer</strong></span>
+ </span></dt>
+<dd><p>
+ Displays the answer.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">debug</strong></span>
+ </span></dt>
+<dd><p>
+ Turn on debugging.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+<p>
+ Lines beginning with a semicolon are comments and are ignored.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544540"></a><h2>EXAMPLES</h2>
+<p>
+ The examples below show how
+ <span><strong class="command">nsupdate</strong></span>
+ could be used to insert and delete resource records from the
+ <span class="type">example.com</span>
+ zone.
+ Notice that the input in each example contains a trailing blank line so
+ that
+ a group of commands are sent as one dynamic update request to the
+ master name server for
+ <span class="type">example.com</span>.
+
+ </p>
+<pre class="programlisting">
+# nsupdate
+&gt; update delete oldhost.example.com A
+&gt; update add newhost.example.com 86400 A 172.16.1.1
+&gt; send
+</pre>
+<p>
+ </p>
+<p>
+ Any A records for
+ <span class="type">oldhost.example.com</span>
+ are deleted.
+ And an A record for
+ <span class="type">newhost.example.com</span>
+ with IP address 172.16.1.1 is added.
+ The newly-added record has a 1 day TTL (86400 seconds).
+ </p>
+<pre class="programlisting">
+# nsupdate
+&gt; prereq nxdomain nickname.example.com
+&gt; update add nickname.example.com 86400 CNAME somehost.example.com
+&gt; send
+</pre>
+<p>
+ </p>
+<p>
+ The prerequisite condition gets the name server to check that there
+ are no resource records of any type for
+ <span class="type">nickname.example.com</span>.
+
+ 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.)
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544584"></a><h2>FILES</h2>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">/etc/resolv.conf</code></span></dt>
+<dd><p>
+ used to identify default name server
+ </p></dd>
+<dt><span class="term"><code class="constant">K{name}.+157.+{random}.key</code></span></dt>
+<dd><p>
+ base-64 encoding of HMAC-MD5 key created by
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>.
+ </p></dd>
+<dt><span class="term"><code class="constant">K{name}.+157.+{random}.private</code></span></dt>
+<dd><p>
+ base-64 encoding of HMAC-MD5 key created by
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2542128"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">RFC2136</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC3007</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC2104</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC2845</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC1034</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC2535</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC2931</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544929"></a><h2>BUGS</h2>
+<p>
+ The TSIG key is redundantly stored in two separate files.
+ This is a consequence of nsupdate using the DST library
+ for its cryptographic operations, and may change in future
+ releases.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/nsupdate/win32/nsupdate.dsp b/bin/nsupdate/win32/nsupdate.dsp
new file mode 100644
index 0000000..028ed55
--- /dev/null
+++ b/bin/nsupdate/win32/nsupdate.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="nsupdate" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=nsupdate - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "nsupdate.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nsupdate.mak" CFG="nsupdate - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nsupdate - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "nsupdate - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nsupdate - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/lwres/win32/Release/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/nsupdate.exe"
+
+!ELSEIF "$(CFG)" == "nsupdate - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/lwres/win32/Debug/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/nsupdate.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "nsupdate - Win32 Release"
+# Name "nsupdate - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\nsupdate.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/nsupdate/win32/nsupdate.dsw b/bin/nsupdate/win32/nsupdate.dsw
new file mode 100644
index 0000000..5f0ac36
--- /dev/null
+++ b/bin/nsupdate/win32/nsupdate.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "nsupdate"=".\nsupdate.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/nsupdate/win32/nsupdate.mak b/bin/nsupdate/win32/nsupdate.mak
new file mode 100644
index 0000000..1e41c29
--- /dev/null
+++ b/bin/nsupdate/win32/nsupdate.mak
@@ -0,0 +1,373 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on nsupdate.dsp
+!IF "$(CFG)" == ""
+CFG=nsupdate - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to nsupdate - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "nsupdate - Win32 Release" && "$(CFG)" != "nsupdate - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nsupdate.mak" CFG="nsupdate - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nsupdate - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "nsupdate - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nsupdate - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "nsupdate - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\nsupdate.exe"
+
+!ELSE
+
+ALL : "libbind9 - Win32 Release" "libisc - Win32 Release" "libdns - Win32 Release" "..\..\..\Build\Release\nsupdate.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN" "libbind9 - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\nsupdate.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\nsupdate.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\nsupdate.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nsupdate.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/lwres/win32/Release/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\nsupdate.pdb" /machine:I386 /out:"../../../Build/Release/nsupdate.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\nsupdate.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib"
+
+"..\..\..\Build\Release\nsupdate.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "nsupdate - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\nsupdate.exe" "$(OUTDIR)\nsupdate.bsc"
+
+!ELSE
+
+ALL : "libbind9 - Win32 Debug" "libisc - Win32 Debug" "libdns - Win32 Debug" "..\..\..\Build\Debug\nsupdate.exe" "$(OUTDIR)\nsupdate.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 DebugCLEAN" "libisc - Win32 DebugCLEAN" "libbind9 - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\nsupdate.obj"
+ -@erase "$(INTDIR)\nsupdate.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\nsupdate.bsc"
+ -@erase "$(OUTDIR)\nsupdate.pdb"
+ -@erase "..\..\..\Build\Debug\nsupdate.exe"
+ -@erase "..\..\..\Build\Debug\nsupdate.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/lwres/win32/include/lwres" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nsupdate.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\nsupdate.sbr"
+
+"$(OUTDIR)\nsupdate.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/lwres/win32/Debug/liblwres.lib user32.lib advapi32.lib ws2_32.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\nsupdate.pdb" /debug /machine:I386 /out:"../../../Build/Debug/nsupdate.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\nsupdate.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib"
+
+"..\..\..\Build\Debug\nsupdate.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("nsupdate.dep")
+!INCLUDE "nsupdate.dep"
+!ELSE
+!MESSAGE Warning: cannot find "nsupdate.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "nsupdate - Win32 Release" || "$(CFG)" == "nsupdate - Win32 Debug"
+SOURCE=..\nsupdate.c
+
+!IF "$(CFG)" == "nsupdate - Win32 Release"
+
+
+"$(INTDIR)\nsupdate.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nsupdate - Win32 Debug"
+
+
+"$(INTDIR)\nsupdate.obj" "$(INTDIR)\nsupdate.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "nsupdate - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ELSEIF "$(CFG)" == "nsupdate - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nsupdate - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ELSEIF "$(CFG)" == "nsupdate - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nsupdate - Win32 Release"
+
+"libbind9 - Win32 Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libbind9 - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ELSEIF "$(CFG)" == "nsupdate - Win32 Debug"
+
+"libbind9 - Win32 Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug"
+ cd "..\..\..\bin\nsupdate\win32"
+
+"libbind9 - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\nsupdate\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/rndc/Makefile.in b/bin/rndc/Makefile.in
new file mode 100644
index 0000000..9b0e20d
--- /dev/null
+++ b/bin/rndc/Makefile.in
@@ -0,0 +1,104 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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.44 2007/06/18 23:47:22 tbox 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@
+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}
+
+CONFLIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+CONFDEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+SRCS= rndc.c rndc-confgen.c
+
+SUBDIRS = unix
+
+TARGETS = rndc@EXEEXT@ rndc-confgen@EXEEXT@
+
+MANPAGES = rndc.8 rndc-confgen.8 rndc.conf.5
+
+HTMLPAGES = rndc.html rndc-confgen.html rndc.conf.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+UOBJS = unix/os.@O@
+
+@BIND9_MAKE_RULES@
+
+rndc.@O@: rndc.c
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
+ -DVERSION=\"${VERSION}\" \
+ -DRNDC_CONFFILE=\"${sysconfdir}/rndc.conf\" \
+ -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}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man5
+
+install:: rndc@EXEEXT@ rndc-confgen@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::
+ rm -f ${TARGETS}
diff --git a/bin/rndc/include/rndc/os.h b/bin/rndc/include/rndc/os.h
new file mode 100644
index 0000000..6e3007c
--- /dev/null
+++ b/bin/rndc/include/rndc/os.h
@@ -0,0 +1,46 @@
+/*
+ * 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.h,v 1.9 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#ifndef RNDC_OS_H
+#define RNDC_OS_H 1
+
+#include <isc/lang.h>
+#include <stdio.h>
+
+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 refernced by 'fd' to 'user'.
+ * Returns:
+ * 0 success
+ * -1 insufficient permissions, or 'user' does not exist.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif
diff --git a/bin/rndc/rndc-confgen.8 b/bin/rndc/rndc-confgen.8
new file mode 100644
index 0000000..440870a
--- /dev/null
+++ b/bin/rndc/rndc-confgen.8
@@ -0,0 +1,211 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2001, 2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: rndc\-confgen
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" 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
new file mode 100644
index 0000000..221135e
--- /dev/null
+++ b/bin/rndc/rndc-confgen.c
@@ -0,0 +1,342 @@
+/*
+ * 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 <config.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <isc/assertions.h>
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/keyboard.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+
+#include <dst/dst.h>
+#include <rndc/os.h>
+
+#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
new file mode 100644
index 0000000..4c51da5
--- /dev/null
+++ b/bin/rndc/rndc-confgen.docbook
@@ -0,0 +1,286 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - 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.docbook,v 1.13 2007/06/18 23:47:25 tbox Exp $ -->
+<refentry id="man.rndc-confgen">
+ <refentryinfo>
+ <date>Aug 27, 2001</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>rndc-confgen</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>rndc-confgen</application></refname>
+ <refpurpose>rndc key generation tool</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2001</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>rndc-confgen</command>
+ <arg><option>-a</option></arg>
+ <arg><option>-b <replaceable class="parameter">keysize</replaceable></option></arg>
+ <arg><option>-c <replaceable class="parameter">keyfile</replaceable></option></arg>
+ <arg><option>-h</option></arg>
+ <arg><option>-k <replaceable class="parameter">keyname</replaceable></option></arg>
+ <arg><option>-p <replaceable class="parameter">port</replaceable></option></arg>
+ <arg><option>-r <replaceable class="parameter">randomfile</replaceable></option></arg>
+ <arg><option>-s <replaceable class="parameter">address</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">chrootdir</replaceable></option></arg>
+ <arg><option>-u <replaceable class="parameter">user</replaceable></option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>rndc-confgen</command>
+ generates configuration files
+ for <command>rndc</command>. It can be used as a
+ convenient alternative to writing the
+ <filename>rndc.conf</filename> file
+ and the corresponding <command>controls</command>
+ and <command>key</command>
+ statements in <filename>named.conf</filename> by hand.
+ Alternatively, it can be run with the <command>-a</command>
+ option to set up a <filename>rndc.key</filename> file and
+ avoid the need for a <filename>rndc.conf</filename> file
+ and a <command>controls</command> statement altogether.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-a</term>
+ <listitem>
+ <para>
+ Do automatic <command>rndc</command> configuration.
+ This creates a file <filename>rndc.key</filename>
+ in <filename>/etc</filename> (or whatever
+ <varname>sysconfdir</varname>
+ was specified as when <acronym>BIND</acronym> was
+ built)
+ that is read by both <command>rndc</command>
+ and <command>named</command> on startup. The
+ <filename>rndc.key</filename> file defines a default
+ command channel and authentication key allowing
+ <command>rndc</command> to communicate with
+ <command>named</command> on the local host
+ with no further configuration.
+ </para>
+ <para>
+ Running <command>rndc-confgen -a</command> allows
+ BIND 9 and <command>rndc</command> to be used as
+ drop-in
+ replacements for BIND 8 and <command>ndc</command>,
+ with no changes to the existing BIND 8
+ <filename>named.conf</filename> file.
+ </para>
+ <para>
+ If a more elaborate configuration than that
+ generated by <command>rndc-confgen -a</command>
+ is required, for example if rndc is to be used remotely,
+ you should run <command>rndc-confgen</command> without
+ the
+ <command>-a</command> option and set up a
+ <filename>rndc.conf</filename> and
+ <filename>named.conf</filename>
+ as directed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-b <replaceable class="parameter">keysize</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the size of the authentication key in bits.
+ Must be between 1 and 512 bits; the default is 128.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">keyfile</replaceable></term>
+ <listitem>
+ <para>
+ Used with the <command>-a</command> option to specify
+ an alternate location for <filename>rndc.key</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-h</term>
+ <listitem>
+ <para>
+ Prints a short summary of the options and arguments to
+ <command>rndc-confgen</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">keyname</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the key name of the rndc authentication key.
+ This must be a valid domain name.
+ The default is <constant>rndc-key</constant>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the command channel port where <command>named</command>
+ listens for connections from <command>rndc</command>.
+ The default is 953.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r <replaceable class="parameter">randomfile</replaceable></term>
+ <listitem>
+ <para>
+ Specifies a source of random data for generating the
+ authorization. If the operating
+ system does not provide a <filename>/dev/random</filename>
+ or equivalent device, the default source of randomness
+ is keyboard input. <filename>randomdev</filename>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <filename>keyboard</filename> indicates that keyboard
+ input should be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">address</replaceable></term>
+ <listitem>
+ <para>
+ Specifies the IP address where <command>named</command>
+ listens for command channel connections from
+ <command>rndc</command>. The default is the loopback
+ address 127.0.0.1.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">chrootdir</replaceable></term>
+ <listitem>
+ <para>
+ Used with the <command>-a</command> option to specify
+ a directory where <command>named</command> will run
+ chrooted. An additional copy of the <filename>rndc.key</filename>
+ will be written relative to this directory so that
+ it will be found by the chrooted <command>named</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-u <replaceable class="parameter">user</replaceable></term>
+ <listitem>
+ <para>
+ Used with the <command>-a</command> option to set the
+ owner
+ of the <filename>rndc.key</filename> file generated.
+ If
+ <command>-t</command> is also specified only the file
+ in
+ the chroot area has its owner changed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLES</title>
+ <para>
+ To allow <command>rndc</command> to be used with
+ no manual configuration, run
+ </para>
+ <para><userinput>rndc-confgen -a</userinput>
+ </para>
+ <para>
+ To print a sample <filename>rndc.conf</filename> file and
+ corresponding <command>controls</command> and <command>key</command>
+ statements to be manually inserted into <filename>named.conf</filename>,
+ run
+ </para>
+ <para><userinput>rndc-confgen</userinput>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>rndc</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/rndc/rndc-confgen.html b/bin/rndc/rndc-confgen.html
new file mode 100644
index 0000000..4be87af
--- /dev/null
+++ b/bin/rndc/rndc-confgen.html
@@ -0,0 +1,188 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2001, 2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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.html,v 1.25 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>rndc-confgen</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.rndc-confgen"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">rndc-confgen</span> &#8212; rndc key generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">rndc-confgen</code> [<code class="option">-a</code>] [<code class="option">-b <em class="replaceable"><code>keysize</code></em></code>] [<code class="option">-c <em class="replaceable"><code>keyfile</code></em></code>] [<code class="option">-h</code>] [<code class="option">-k <em class="replaceable"><code>keyname</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-r <em class="replaceable"><code>randomfile</code></em></code>] [<code class="option">-s <em class="replaceable"><code>address</code></em></code>] [<code class="option">-t <em class="replaceable"><code>chrootdir</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543429"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">rndc-confgen</strong></span>
+ generates configuration files
+ for <span><strong class="command">rndc</strong></span>. It can be used as a
+ convenient alternative to writing the
+ <code class="filename">rndc.conf</code> file
+ and the corresponding <span><strong class="command">controls</strong></span>
+ and <span><strong class="command">key</strong></span>
+ statements in <code class="filename">named.conf</code> by hand.
+ Alternatively, it can be run with the <span><strong class="command">-a</strong></span>
+ option to set up a <code class="filename">rndc.key</code> file and
+ avoid the need for a <code class="filename">rndc.conf</code> file
+ and a <span><strong class="command">controls</strong></span> statement altogether.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543474"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a</span></dt>
+<dd>
+<p>
+ Do automatic <span><strong class="command">rndc</strong></span> configuration.
+ This creates a file <code class="filename">rndc.key</code>
+ in <code class="filename">/etc</code> (or whatever
+ <code class="varname">sysconfdir</code>
+ was specified as when <acronym class="acronym">BIND</acronym> was
+ built)
+ that is read by both <span><strong class="command">rndc</strong></span>
+ and <span><strong class="command">named</strong></span> on startup. The
+ <code class="filename">rndc.key</code> file defines a default
+ command channel and authentication key allowing
+ <span><strong class="command">rndc</strong></span> to communicate with
+ <span><strong class="command">named</strong></span> on the local host
+ with no further configuration.
+ </p>
+<p>
+ Running <span><strong class="command">rndc-confgen -a</strong></span> allows
+ BIND 9 and <span><strong class="command">rndc</strong></span> to be used as
+ drop-in
+ replacements for BIND 8 and <span><strong class="command">ndc</strong></span>,
+ with no changes to the existing BIND 8
+ <code class="filename">named.conf</code> file.
+ </p>
+<p>
+ If a more elaborate configuration than that
+ generated by <span><strong class="command">rndc-confgen -a</strong></span>
+ is required, for example if rndc is to be used remotely,
+ you should run <span><strong class="command">rndc-confgen</strong></span> without
+ the
+ <span><strong class="command">-a</strong></span> option and set up a
+ <code class="filename">rndc.conf</code> and
+ <code class="filename">named.conf</code>
+ as directed.
+ </p>
+</dd>
+<dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt>
+<dd><p>
+ Specifies the size of the authentication key in bits.
+ Must be between 1 and 512 bits; the default is 128.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>keyfile</code></em></span></dt>
+<dd><p>
+ Used with the <span><strong class="command">-a</strong></span> option to specify
+ an alternate location for <code class="filename">rndc.key</code>.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">rndc-confgen</strong></span>.
+ </p></dd>
+<dt><span class="term">-k <em class="replaceable"><code>keyname</code></em></span></dt>
+<dd><p>
+ Specifies the key name of the rndc authentication key.
+ This must be a valid domain name.
+ The default is <code class="constant">rndc-key</code>.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd><p>
+ Specifies the command channel port where <span><strong class="command">named</strong></span>
+ listens for connections from <span><strong class="command">rndc</strong></span>.
+ The default is 953.
+ </p></dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomfile</code></em></span></dt>
+<dd><p>
+ Specifies a source of random data for generating the
+ authorization. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>address</code></em></span></dt>
+<dd><p>
+ Specifies the IP address where <span><strong class="command">named</strong></span>
+ listens for command channel connections from
+ <span><strong class="command">rndc</strong></span>. The default is the loopback
+ address 127.0.0.1.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>chrootdir</code></em></span></dt>
+<dd><p>
+ Used with the <span><strong class="command">-a</strong></span> option to specify
+ a directory where <span><strong class="command">named</strong></span> will run
+ chrooted. An additional copy of the <code class="filename">rndc.key</code>
+ will be written relative to this directory so that
+ it will be found by the chrooted <span><strong class="command">named</strong></span>.
+ </p></dd>
+<dt><span class="term">-u <em class="replaceable"><code>user</code></em></span></dt>
+<dd><p>
+ Used with the <span><strong class="command">-a</strong></span> option to set the
+ owner
+ of the <code class="filename">rndc.key</code> file generated.
+ If
+ <span><strong class="command">-t</strong></span> is also specified only the file
+ in
+ the chroot area has its owner changed.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543787"></a><h2>EXAMPLES</h2>
+<p>
+ To allow <span><strong class="command">rndc</strong></span> to be used with
+ no manual configuration, run
+ </p>
+<p><strong class="userinput"><code>rndc-confgen -a</code></strong>
+ </p>
+<p>
+ To print a sample <code class="filename">rndc.conf</code> file and
+ corresponding <span><strong class="command">controls</strong></span> and <span><strong class="command">key</strong></span>
+ statements to be manually inserted into <code class="filename">named.conf</code>,
+ run
+ </p>
+<p><strong class="userinput"><code>rndc-confgen</code></strong>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543829"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">rndc.conf</span>(5)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543867"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/rndc/rndc.8 b/bin/rndc/rndc.8
new file mode 100644
index 0000000..7f0dea1
--- /dev/null
+++ b/bin/rndc/rndc.8
@@ -0,0 +1,148 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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.8,v 1.42 2007/12/14 22:37:22 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: rndc
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: June 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "RNDC" "8" "June 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+rndc \- name server control utility
+.SH "SYNOPSIS"
+.HP 5
+\fBrndc\fR [\fB\-b\ \fR\fB\fIsource\-address\fR\fR] [\fB\-c\ \fR\fB\fIconfig\-file\fR\fR] [\fB\-k\ \fR\fB\fIkey\-file\fR\fR] [\fB\-s\ \fR\fB\fIserver\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-V\fR] [\fB\-y\ \fR\fB\fIkey_id\fR\fR] {command}
+.SH "DESCRIPTION"
+.PP
+\fBrndc\fR
+controls the operation of a name server. It supersedes the
+\fBndc\fR
+utility that was provided in old BIND releases. If
+\fBrndc\fR
+is invoked with no command line options or arguments, it prints a short summary of the supported commands and the available options and their arguments.
+.PP
+\fBrndc\fR
+communicates with the name server over a TCP connection, sending commands authenticated with digital signatures. In the current versions of
+\fBrndc\fR
+and
+\fBnamed\fR, the only supported authentication algorithm is HMAC\-MD5, which uses a shared secret on each end of the connection. This provides TSIG\-style authentication for the command request and the name server's response. All commands sent over the channel must be signed by a key_id known to the server.
+.PP
+\fBrndc\fR
+reads a configuration file to determine how to contact the name server and decide what algorithm and key it should use.
+.SH "OPTIONS"
+.PP
+\-b \fIsource\-address\fR
+.RS 4
+Use
+\fIsource\-address\fR
+as the source address for the connection to the server. Multiple instances are permitted to allow setting of both the IPv4 and IPv6 source addresses.
+.RE
+.PP
+\-c \fIconfig\-file\fR
+.RS 4
+Use
+\fIconfig\-file\fR
+as the configuration file instead of the default,
+\fI/etc/rndc.conf\fR.
+.RE
+.PP
+\-k \fIkey\-file\fR
+.RS 4
+Use
+\fIkey\-file\fR
+as the key file instead of the default,
+\fI/etc/rndc.key\fR. The key in
+\fI/etc/rndc.key\fR
+will be used to authenticate commands sent to the server if the
+\fIconfig\-file\fR
+does not exist.
+.RE
+.PP
+\-s \fIserver\fR
+.RS 4
+\fIserver\fR
+is the name or address of the server which matches a server statement in the configuration file for
+\fBrndc\fR. If no server is supplied on the command line, the host named by the default\-server clause in the options statement of the
+\fBrndc\fR
+configuration file will be used.
+.RE
+.PP
+\-p \fIport\fR
+.RS 4
+Send commands to TCP port
+\fIport\fR
+instead of BIND 9's default control channel port, 953.
+.RE
+.PP
+\-V
+.RS 4
+Enable verbose logging.
+.RE
+.PP
+\-y \fIkey_id\fR
+.RS 4
+Use the key
+\fIkey_id\fR
+from the configuration file.
+\fIkey_id\fR
+must be known by named with the same algorithm and secret string in order for control message validation to succeed. If no
+\fIkey_id\fR
+is specified,
+\fBrndc\fR
+will first look for a key clause in the server statement of the server being used, or if no server statement is present for that host, then the default\-key clause of the options statement. Note that the configuration file contains shared secrets which are used to send authenticated control commands to name servers. It should therefore not have general read or write access.
+.RE
+.PP
+For the complete set of commands supported by
+\fBrndc\fR, see the BIND 9 Administrator Reference Manual or run
+\fBrndc\fR
+without arguments to see its help message.
+.SH "LIMITATIONS"
+.PP
+\fBrndc\fR
+does not yet support all the commands of the BIND 8
+\fBndc\fR
+utility.
+.PP
+There is currently no way to provide the shared secret for a
+\fBkey_id\fR
+without using the configuration file.
+.PP
+Several error messages could be clearer.
+.SH "SEE ALSO"
+.PP
+\fBrndc.conf\fR(5),
+\fBrndc\-confgen\fR(8),
+\fBnamed\fR(8),
+\fBnamed.conf\fR(5),
+\fBndc\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 2000, 2001 Internet Software Consortium.
+.br
diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c
new file mode 100644
index 0000000..cdebf3d
--- /dev/null
+++ b/bin/rndc/rndc.c
@@ -0,0 +1,859 @@
+/*
+ * 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
+ * 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.c,v 1.122 2008/10/15 03:01:59 marka Exp $ */
+
+/*! \file */
+
+/*
+ * Principal Author: DCL
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
+#include <isc/log.h>
+#include <isc/net.h>
+#include <isc/mem.h>
+#include <isc/random.h>
+#include <isc/socket.h>
+#include <isc/stdtime.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+
+#include <isccfg/namedconf.h>
+
+#include <isccc/alist.h>
+#include <isccc/base64.h>
+#include <isccc/cc.h>
+#include <isccc/ccmsg.h>
+#include <isccc/result.h>
+#include <isccc/sexpr.h>
+#include <isccc/types.h>
+#include <isccc/util.h>
+
+#include <dns/name.h>
+
+#include <bind9/getaddresses.h>
+
+#include "util.h"
+
+#define SERVERADDRS 10
+
+const char *progname;
+isc_boolean_t verbose;
+
+static const char *admin_conffile;
+static const char *admin_keyfile;
+static const char *version = VERSION;
+static const char *servername = NULL;
+static isc_sockaddr_t serveraddrs[SERVERADDRS];
+static isc_sockaddr_t local4, local6;
+static isc_boolean_t local4set = ISC_FALSE, local6set = ISC_FALSE;
+static int nserveraddrs;
+static int currentaddr = 0;
+static unsigned int remoteport = 0;
+static isc_socketmgr_t *socketmgr = NULL;
+static unsigned char databuf[2048];
+static isccc_ccmsg_t ccmsg;
+static isccc_region_t secret;
+static isc_boolean_t failed = ISC_FALSE;
+static isc_mem_t *mctx;
+static int sends, recvs, connects;
+static char *command;
+static char *args;
+static char program[256];
+static isc_socket_t *sock = NULL;
+static isc_uint32_t serial;
+
+static void rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task);
+
+static void
+usage(int status) {
+ fprintf(stderr, "\
+Usage: %s [-c config] [-s server] [-p port]\n\
+ [-k key-file ] [-y key] [-V] command\n\
+\n\
+command is one of the following:\n\
+\n\
+ reload Reload configuration file and zones.\n\
+ reload zone [class [view]]\n\
+ Reload a single zone.\n\
+ refresh zone [class [view]]\n\
+ Schedule immediate maintenance for a zone.\n\
+ retransfer zone [class [view]]\n\
+ Retransfer a single zone without checking serial number.\n\
+ freeze Suspend updates to all dynamic zones.\n\
+ freeze zone [class [view]]\n\
+ Suspend updates to a dynamic zone.\n\
+ thaw Enable updates to all dynamic zones and reload them.\n\
+ thaw zone [class [view]]\n\
+ Enable updates to a frozen dynamic zone and reload it.\n\
+ notify zone [class [view]]\n\
+ Resend NOTIFY messages for the zone.\n\
+ reconfig Reload configuration file and new zones only.\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\
+ 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\
+ halt Stop the server without saving pending updates.\n\
+ halt -p Stop the server without saving pending updates reporting\n\
+ process id.\n\
+ trace Increment debugging level by one.\n\
+ trace level Change the debugging level.\n\
+ notrace Set debugging level to 0.\n\
+ flush Flushes all of the server's caches.\n\
+ flush [view] Flushes the server's cache for a view.\n\
+ flushname name [view]\n\
+ Flush the given name from the server's cache(s)\n\
+ status Display status of the server.\n\
+ recursing Dump the queries that are currently recursing (named.recursing)\n\
+ validation newstate [view]\n\
+ Enable / disable DNSSEC validation.\n\
+ *restart Restart the server.\n\
+\n\
+* == not yet implemented\n\
+Version: %s\n",
+ progname, version);
+
+ exit(status);
+}
+
+static void
+get_addresses(const char *host, in_port_t port) {
+ isc_result_t result;
+ int found = 0, count;
+
+ if (*host == '/') {
+ result = isc_sockaddr_frompath(&serveraddrs[nserveraddrs],
+ host);
+ if (result == ISC_R_SUCCESS)
+ nserveraddrs++;
+ } else {
+ count = SERVERADDRS - nserveraddrs;
+ result = bind9_getaddresses(host, port,
+ &serveraddrs[nserveraddrs],
+ count, &found);
+ nserveraddrs += found;
+ }
+ if (result != ISC_R_SUCCESS)
+ fatal("couldn't get address for '%s': %s",
+ host, isc_result_totext(result));
+ INSIST(nserveraddrs > 0);
+}
+
+static void
+rndc_senddone(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+
+ UNUSED(task);
+
+ sends--;
+ if (sevent->result != ISC_R_SUCCESS)
+ fatal("send failed: %s", isc_result_totext(sevent->result));
+ isc_event_free(&event);
+ if (sends == 0 && recvs == 0) {
+ isc_socket_detach(&sock);
+ isc_task_shutdown(task);
+ RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
+ }
+}
+
+static void
+rndc_recvdone(isc_task_t *task, isc_event_t *event) {
+ isccc_sexpr_t *response = NULL;
+ isccc_sexpr_t *data;
+ isccc_region_t source;
+ char *errormsg = NULL;
+ char *textmsg = NULL;
+ isc_result_t result;
+
+ recvs--;
+
+ if (ccmsg.result == ISC_R_EOF)
+ fatal("connection to remote host closed\n"
+ "This may indicate that\n"
+ "* the remote server is using an older version of"
+ " the command protocol,\n"
+ "* this host is not authorized to connect,\n"
+ "* the clocks are not syncronized, or\n"
+ "* the key is invalid.");
+
+ if (ccmsg.result != ISC_R_SUCCESS)
+ fatal("recv failed: %s", isc_result_totext(ccmsg.result));
+
+ source.rstart = isc_buffer_base(&ccmsg.buffer);
+ source.rend = isc_buffer_used(&ccmsg.buffer);
+
+ DO("parse message", isccc_cc_fromwire(&source, &response, &secret));
+
+ data = isccc_alist_lookup(response, "_data");
+ if (data == NULL)
+ fatal("no data section in response");
+ result = isccc_cc_lookupstring(data, "err", &errormsg);
+ if (result == ISC_R_SUCCESS) {
+ failed = ISC_TRUE;
+ fprintf(stderr, "%s: '%s' failed: %s\n",
+ progname, command, errormsg);
+ }
+ else if (result != ISC_R_NOTFOUND)
+ fprintf(stderr, "%s: parsing response failed: %s\n",
+ progname, isc_result_totext(result));
+
+ result = isccc_cc_lookupstring(data, "text", &textmsg);
+ if (result == ISC_R_SUCCESS)
+ printf("%s\n", textmsg);
+ else if (result != ISC_R_NOTFOUND)
+ fprintf(stderr, "%s: parsing response failed: %s\n",
+ progname, isc_result_totext(result));
+
+ isc_event_free(&event);
+ isccc_sexpr_free(&response);
+ if (sends == 0 && recvs == 0) {
+ isc_socket_detach(&sock);
+ isc_task_shutdown(task);
+ RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
+ }
+}
+
+static void
+rndc_recvnonce(isc_task_t *task, isc_event_t *event) {
+ isccc_sexpr_t *response = NULL;
+ isccc_sexpr_t *_ctrl;
+ isccc_region_t source;
+ isc_result_t result;
+ isc_uint32_t nonce;
+ isccc_sexpr_t *request = NULL;
+ isccc_time_t now;
+ isc_region_t r;
+ isccc_sexpr_t *data;
+ isccc_region_t message;
+ isc_uint32_t len;
+ isc_buffer_t b;
+
+ recvs--;
+
+ if (ccmsg.result == ISC_R_EOF)
+ fatal("connection to remote host closed\n"
+ "This may indicate that\n"
+ "* the remote server is using an older version of"
+ " the command protocol,\n"
+ "* this host is not authorized to connect,\n"
+ "* the clocks are not syncronized, or\n"
+ "* the key is invalid.");
+
+ if (ccmsg.result != ISC_R_SUCCESS)
+ fatal("recv failed: %s", isc_result_totext(ccmsg.result));
+
+ source.rstart = isc_buffer_base(&ccmsg.buffer);
+ source.rend = isc_buffer_used(&ccmsg.buffer);
+
+ DO("parse message", isccc_cc_fromwire(&source, &response, &secret));
+
+ _ctrl = isccc_alist_lookup(response, "_ctrl");
+ if (_ctrl == NULL)
+ fatal("_ctrl section missing");
+ nonce = 0;
+ if (isccc_cc_lookupuint32(_ctrl, "_nonce", &nonce) != ISC_R_SUCCESS)
+ nonce = 0;
+
+ isc_stdtime_get(&now);
+
+ DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
+ now, now + 60, &request));
+ data = isccc_alist_lookup(request, "_data");
+ if (data == NULL)
+ fatal("_data section missing");
+ if (isccc_cc_definestring(data, "type", args) == NULL)
+ fatal("out of memory");
+ if (nonce != 0) {
+ _ctrl = isccc_alist_lookup(request, "_ctrl");
+ if (_ctrl == NULL)
+ fatal("_ctrl section missing");
+ if (isccc_cc_defineuint32(_ctrl, "_nonce", nonce) == NULL)
+ fatal("out of memory");
+ }
+ message.rstart = databuf + 4;
+ message.rend = databuf + sizeof(databuf);
+ DO("render message", isccc_cc_towire(request, &message, &secret));
+ len = sizeof(databuf) - REGION_SIZE(message);
+ isc_buffer_init(&b, databuf, 4);
+ isc_buffer_putuint32(&b, len - 4);
+ r.length = len;
+ r.base = databuf;
+
+ isccc_ccmsg_cancelread(&ccmsg);
+ DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
+ rndc_recvdone, NULL));
+ recvs++;
+ DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
+ NULL));
+ sends++;
+
+ isc_event_free(&event);
+ isccc_sexpr_free(&response);
+ return;
+}
+
+static void
+rndc_connected(isc_task_t *task, isc_event_t *event) {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ isccc_sexpr_t *request = NULL;
+ isccc_sexpr_t *data;
+ isccc_time_t now;
+ isccc_region_t message;
+ isc_region_t r;
+ isc_uint32_t len;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ connects--;
+
+ if (sevent->result != ISC_R_SUCCESS) {
+ isc_sockaddr_format(&serveraddrs[currentaddr], socktext,
+ sizeof(socktext));
+ if (sevent->result != ISC_R_CANCELED &&
+ ++currentaddr < nserveraddrs)
+ {
+ notify("connection failed: %s: %s", socktext,
+ isc_result_totext(sevent->result));
+ isc_socket_detach(&sock);
+ isc_event_free(&event);
+ rndc_startconnect(&serveraddrs[currentaddr], task);
+ return;
+ } else
+ fatal("connect failed: %s: %s", socktext,
+ isc_result_totext(sevent->result));
+ }
+
+ isc_stdtime_get(&now);
+ DO("create message", isccc_cc_createmessage(1, NULL, NULL, ++serial,
+ now, now + 60, &request));
+ data = isccc_alist_lookup(request, "_data");
+ if (data == NULL)
+ fatal("_data section missing");
+ if (isccc_cc_definestring(data, "type", "null") == NULL)
+ fatal("out of memory");
+ message.rstart = databuf + 4;
+ message.rend = databuf + sizeof(databuf);
+ DO("render message", isccc_cc_towire(request, &message, &secret));
+ len = sizeof(databuf) - REGION_SIZE(message);
+ isc_buffer_init(&b, databuf, 4);
+ isc_buffer_putuint32(&b, len - 4);
+ r.length = len;
+ r.base = databuf;
+
+ isccc_ccmsg_init(mctx, sock, &ccmsg);
+ isccc_ccmsg_setmaxsize(&ccmsg, 1024 * 1024);
+
+ DO("schedule recv", isccc_ccmsg_readmessage(&ccmsg, task,
+ rndc_recvnonce, NULL));
+ recvs++;
+ DO("send message", isc_socket_send(sock, &r, task, rndc_senddone,
+ NULL));
+ sends++;
+ isc_event_free(&event);
+}
+
+static void
+rndc_startconnect(isc_sockaddr_t *addr, isc_task_t *task) {
+ isc_result_t result;
+ int pf;
+ isc_sockettype_t type;
+
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(addr, socktext, sizeof(socktext));
+
+ notify("using server %s (%s)", servername, socktext);
+
+ pf = isc_sockaddr_pf(addr);
+ if (pf == AF_INET || pf == AF_INET6)
+ type = isc_sockettype_tcp;
+ else
+ type = isc_sockettype_unix;
+ DO("create socket", isc_socket_create(socketmgr, pf, type, &sock));
+ switch (isc_sockaddr_pf(addr)) {
+ case AF_INET:
+ DO("bind socket", isc_socket_bind(sock, &local4, 0));
+ break;
+ case AF_INET6:
+ DO("bind socket", isc_socket_bind(sock, &local6, 0));
+ break;
+ default:
+ break;
+ }
+ DO("connect", isc_socket_connect(sock, addr, task, rndc_connected,
+ NULL));
+ connects++;
+}
+
+static void
+rndc_start(isc_task_t *task, isc_event_t *event) {
+ isc_event_free(&event);
+
+ currentaddr = 0;
+ rndc_startconnect(&serveraddrs[currentaddr], task);
+}
+
+static void
+parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname,
+ cfg_parser_t **pctxp, cfg_obj_t **configp)
+{
+ isc_result_t result;
+ const char *conffile = admin_conffile;
+ const cfg_obj_t *addresses = NULL;
+ const cfg_obj_t *defkey = NULL;
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *servers = NULL;
+ const cfg_obj_t *server = NULL;
+ const cfg_obj_t *keys = NULL;
+ const cfg_obj_t *key = NULL;
+ const cfg_obj_t *defport = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ const cfg_obj_t *algorithmobj = NULL;
+ cfg_obj_t *config = NULL;
+ const cfg_obj_t *address = NULL;
+ const cfg_listelt_t *elt;
+ const char *secretstr;
+ const char *algorithm;
+ static char secretarray[1024];
+ const cfg_type_t *conftype = &cfg_type_rndcconf;
+ isc_boolean_t key_only = ISC_FALSE;
+ const cfg_listelt_t *element;
+
+ if (! isc_file_exists(conffile)) {
+ conffile = admin_keyfile;
+ conftype = &cfg_type_rndckey;
+
+ if (! isc_file_exists(conffile))
+ fatal("neither %s nor %s was found",
+ admin_conffile, admin_keyfile);
+ key_only = ISC_TRUE;
+ }
+
+ DO("create parser", cfg_parser_create(mctx, log, pctxp));
+
+ /*
+ * The parser will output its own errors, so DO() is not used.
+ */
+ result = cfg_parse_file(*pctxp, conffile, conftype, &config);
+ if (result != ISC_R_SUCCESS)
+ fatal("could not load rndc configuration");
+
+ if (!key_only)
+ (void)cfg_map_get(config, "options", &options);
+
+ if (key_only && servername == NULL)
+ servername = "127.0.0.1";
+ else if (servername == NULL && options != NULL) {
+ const cfg_obj_t *defserverobj = NULL;
+ (void)cfg_map_get(options, "default-server", &defserverobj);
+ if (defserverobj != NULL)
+ servername = cfg_obj_asstring(defserverobj);
+ }
+
+ if (servername == NULL)
+ fatal("no server specified and no default");
+
+ if (!key_only) {
+ (void)cfg_map_get(config, "server", &servers);
+ if (servers != NULL) {
+ for (elt = cfg_list_first(servers);
+ elt != NULL;
+ elt = cfg_list_next(elt))
+ {
+ const char *name;
+ server = cfg_listelt_value(elt);
+ name = cfg_obj_asstring(cfg_map_getname(server));
+ if (strcasecmp(name, servername) == 0)
+ break;
+ server = NULL;
+ }
+ }
+ }
+
+ /*
+ * Look for the name of the key to use.
+ */
+ if (keyname != NULL)
+ ; /* Was set on command line, do nothing. */
+ else if (server != NULL) {
+ DO("get key for server", cfg_map_get(server, "key", &defkey));
+ keyname = cfg_obj_asstring(defkey);
+ } else if (options != NULL) {
+ DO("get default key", cfg_map_get(options, "default-key",
+ &defkey));
+ keyname = cfg_obj_asstring(defkey);
+ } else if (!key_only)
+ fatal("no key for server and no default");
+
+ /*
+ * Get the key's definition.
+ */
+ if (key_only)
+ DO("get key", cfg_map_get(config, "key", &key));
+ else {
+ DO("get config key list", cfg_map_get(config, "key", &keys));
+ for (elt = cfg_list_first(keys);
+ elt != NULL;
+ elt = cfg_list_next(elt))
+ {
+ key = cfg_listelt_value(elt);
+ if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)),
+ keyname) == 0)
+ break;
+ }
+ if (elt == NULL)
+ fatal("no key definition for name %s", keyname);
+ }
+ (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");
+
+ secretstr = cfg_obj_asstring(secretobj);
+ algorithm = cfg_obj_asstring(algorithmobj);
+
+ if (strcasecmp(algorithm, "hmac-md5") != 0)
+ fatal("unsupported algorithm: %s", algorithm);
+
+ secret.rstart = (unsigned char *)secretarray;
+ secret.rend = (unsigned char *)secretarray + sizeof(secretarray);
+ DO("decode base64 secret", isccc_base64_decode(secretstr, &secret));
+ secret.rend = secret.rstart;
+ secret.rstart = (unsigned char *)secretarray;
+
+ /*
+ * Find the port to connect to.
+ */
+ if (remoteport != 0)
+ ; /* Was set on command line, do nothing. */
+ else {
+ if (server != NULL)
+ (void)cfg_map_get(server, "port", &defport);
+ if (defport == NULL && options != NULL)
+ (void)cfg_map_get(options, "default-port", &defport);
+ }
+ if (defport != NULL) {
+ remoteport = cfg_obj_asuint32(defport);
+ if (remoteport > 65535 || remoteport == 0)
+ fatal("port %u out of range", remoteport);
+ } else if (remoteport == 0)
+ remoteport = NS_CONTROL_PORT;
+
+ if (server != NULL)
+ result = cfg_map_get(server, "addresses", &addresses);
+ else
+ result = ISC_R_NOTFOUND;
+ if (result == ISC_R_SUCCESS) {
+ for (element = cfg_list_first(addresses);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ isc_sockaddr_t sa;
+
+ address = cfg_listelt_value(element);
+ if (!cfg_obj_issockaddr(address)) {
+ unsigned int myport;
+ const char *name;
+ const cfg_obj_t *obj;
+
+ obj = cfg_tuple_get(address, "name");
+ name = cfg_obj_asstring(obj);
+ obj = cfg_tuple_get(address, "port");
+ if (cfg_obj_isuint32(obj)) {
+ myport = cfg_obj_asuint32(obj);
+ if (myport > ISC_UINT16_MAX ||
+ myport == 0)
+ fatal("port %u out of range",
+ myport);
+ } else
+ myport = remoteport;
+ if (nserveraddrs < SERVERADDRS)
+ get_addresses(name, (in_port_t) myport);
+ else
+ fprintf(stderr, "too many address: "
+ "%s: dropped\n", name);
+ continue;
+ }
+ sa = *cfg_obj_assockaddr(address);
+ if (isc_sockaddr_getport(&sa) == 0)
+ isc_sockaddr_setport(&sa, remoteport);
+ if (nserveraddrs < SERVERADDRS)
+ serveraddrs[nserveraddrs++] = sa;
+ else {
+ char socktext[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(&sa, socktext,
+ sizeof(socktext));
+ fprintf(stderr,
+ "too many address: %s: dropped\n",
+ socktext);
+ }
+ }
+ }
+
+ if (!local4set && server != NULL) {
+ address = NULL;
+ cfg_map_get(server, "source-address", &address);
+ if (address != NULL) {
+ local4 = *cfg_obj_assockaddr(address);
+ local4set = ISC_TRUE;
+ }
+ }
+ if (!local4set && options != NULL) {
+ address = NULL;
+ cfg_map_get(options, "default-source-address", &address);
+ if (address != NULL) {
+ local4 = *cfg_obj_assockaddr(address);
+ local4set = ISC_TRUE;
+ }
+ }
+
+ if (!local6set && server != NULL) {
+ address = NULL;
+ cfg_map_get(server, "source-address-v6", &address);
+ if (address != NULL) {
+ local6 = *cfg_obj_assockaddr(address);
+ local6set = ISC_TRUE;
+ }
+ }
+ if (!local6set && options != NULL) {
+ address = NULL;
+ cfg_map_get(options, "default-source-address-v6", &address);
+ if (address != NULL) {
+ local6 = *cfg_obj_assockaddr(address);
+ local6set = ISC_TRUE;
+ }
+ }
+
+ *configp = config;
+}
+
+int
+main(int argc, char **argv) {
+ isc_boolean_t show_final_mem = ISC_FALSE;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_task_t *task = NULL;
+ isc_log_t *log = NULL;
+ isc_logconfig_t *logconfig = NULL;
+ isc_logdestination_t logdest;
+ cfg_parser_t *pctx = NULL;
+ cfg_obj_t *config = NULL;
+ const char *keyname = NULL;
+ struct in_addr in;
+ struct in6_addr in6;
+ char *p;
+ size_t argslen;
+ int ch;
+ int i;
+
+ result = isc_file_progname(*argv, program, sizeof(program));
+ if (result != ISC_R_SUCCESS)
+ memcpy(program, "rndc", 5);
+ progname = program;
+
+ admin_conffile = RNDC_CONFFILE;
+ admin_keyfile = RNDC_KEYFILE;
+
+ isc_sockaddr_any(&local4);
+ isc_sockaddr_any6(&local6);
+
+ result = isc_app_start();
+ if (result != ISC_R_SUCCESS)
+ fatal("isc_app_start() failed: %s", isc_result_totext(result));
+
+ isc_commandline_errprint = ISC_FALSE;
+
+ while ((ch = isc_commandline_parse(argc, argv, "b:c:hk:Mmp:s:Vy:"))
+ != -1) {
+ switch (ch) {
+ case 'b':
+ if (inet_pton(AF_INET, isc_commandline_argument,
+ &in) == 1) {
+ isc_sockaddr_fromin(&local4, &in, 0);
+ local4set = ISC_TRUE;
+ } else if (inet_pton(AF_INET6, isc_commandline_argument,
+ &in6) == 1) {
+ isc_sockaddr_fromin6(&local6, &in6, 0);
+ local6set = ISC_TRUE;
+ }
+ break;
+
+ case 'c':
+ admin_conffile = isc_commandline_argument;
+ break;
+
+ case 'k':
+ admin_keyfile = isc_commandline_argument;
+ break;
+
+ case 'M':
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE;
+ break;
+
+ case 'm':
+ show_final_mem = ISC_TRUE;
+ break;
+
+ case 'p':
+ remoteport = atoi(isc_commandline_argument);
+ if (remoteport > 65535 || remoteport == 0)
+ fatal("port '%s' out of range",
+ isc_commandline_argument);
+ break;
+
+ case 's':
+ servername = isc_commandline_argument;
+ break;
+
+ case 'V':
+ verbose = ISC_TRUE;
+ break;
+
+ case 'y':
+ keyname = isc_commandline_argument;
+ break;
+
+ case '?':
+ if (isc_commandline_option != '?') {
+ fprintf(stderr, "%s: invalid argument -%c\n",
+ program, isc_commandline_option);
+ usage(1);
+ }
+ case 'h':
+ 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 < 1)
+ usage(1);
+
+ isc_random_get(&serial);
+
+ DO("create memory context", isc_mem_create(0, 0, &mctx));
+ DO("create socket manager", isc_socketmgr_create(mctx, &socketmgr));
+ DO("create task manager", isc_taskmgr_create(mctx, 1, 0, &taskmgr));
+ DO("create task", isc_task_create(taskmgr, 0, &task));
+
+ DO("create logging context", isc_log_create(mctx, &log, &logconfig));
+ isc_log_setcontext(log);
+ DO("setting log tag", isc_log_settag(logconfig, progname));
+ logdest.file.stream = stderr;
+ logdest.file.name = NULL;
+ logdest.file.versions = ISC_LOG_ROLLNEVER;
+ logdest.file.maximum_size = 0;
+ DO("creating log channel",
+ isc_log_createchannel(logconfig, "stderr",
+ ISC_LOG_TOFILEDESC, ISC_LOG_INFO, &logdest,
+ ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL));
+ DO("enabling log channel", isc_log_usechannel(logconfig, "stderr",
+ NULL, NULL));
+
+ parse_config(mctx, log, keyname, &pctx, &config);
+
+ isccc_result_register();
+
+ command = *argv;
+
+ /*
+ * Convert argc/argv into a space-delimited command string
+ * similar to what the user might enter in interactive mode
+ * (if that were implemented).
+ */
+ argslen = 0;
+ for (i = 0; i < argc; i++)
+ argslen += strlen(argv[i]) + 1;
+
+ args = isc_mem_get(mctx, argslen);
+ if (args == NULL)
+ DO("isc_mem_get", ISC_R_NOMEMORY);
+
+ p = args;
+ for (i = 0; i < argc; i++) {
+ size_t len = strlen(argv[i]);
+ memcpy(p, argv[i], len);
+ p += len;
+ *p++ = ' ';
+ }
+
+ p--;
+ *p++ = '\0';
+ INSIST(p == args + argslen);
+
+ notify("%s", command);
+
+ if (strcmp(command, "restart") == 0)
+ fatal("'%s' is not implemented", command);
+
+ if (nserveraddrs == 0)
+ get_addresses(servername, (in_port_t) remoteport);
+
+ DO("post event", isc_app_onrun(mctx, task, rndc_start, NULL));
+
+ result = isc_app_run();
+ if (result != ISC_R_SUCCESS)
+ fatal("isc_app_run() failed: %s", isc_result_totext(result));
+
+ if (connects > 0 || sends > 0 || recvs > 0)
+ isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL);
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_socketmgr_destroy(&socketmgr);
+ isc_log_destroy(&log);
+ isc_log_setcontext(NULL);
+
+ cfg_obj_destroy(pctx, &config);
+ cfg_parser_destroy(&pctx);
+
+ isc_mem_put(mctx, args, argslen);
+ isccc_ccmsg_invalidate(&ccmsg);
+
+ dns_name_destroy();
+
+ if (show_final_mem)
+ isc_mem_stats(mctx, stderr);
+
+ isc_mem_destroy(&mctx);
+
+ if (failed)
+ return (1);
+
+ return (0);
+}
diff --git a/bin/rndc/rndc.conf b/bin/rndc/rndc.conf
new file mode 100644
index 0000000..67542b9
--- /dev/null
+++ b/bin/rndc/rndc.conf
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004, 2007 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: rndc.conf,v 1.11 2007/06/19 23:46:59 tbox Exp $ */
+
+/*
+ * Sample rndc configuration file.
+ */
+
+options {
+ default-server localhost;
+ default-key "key";
+};
+
+server localhost {
+ key "key";
+};
+
+key "cc64b3d1db63fc88d7cb5d2f9f57d258" {
+ algorithm hmac-md5;
+ secret "34f88008d07deabbe65bd01f1d233d47";
+};
+
+server "test1" {
+ key "cc64b3d1db63fc88d7cb5d2f9f57d258";
+ port 5353;
+ addresses { 10.53.0.1; };
+};
+
+key "key" {
+ algorithm hmac-md5;
+ secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
+};
diff --git a/bin/rndc/rndc.conf.5 b/bin/rndc/rndc.conf.5
new file mode 100644
index 0000000..9e9bad4
--- /dev/null
+++ b/bin/rndc/rndc.conf.5
@@ -0,0 +1,214 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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.conf.5,v 1.38 2007/05/09 13:35:57 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: \fIrndc.conf\fR
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: June 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "\fIRNDC.CONF\fR" "5" "June 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+rndc.conf \- rndc configuration file
+.SH "SYNOPSIS"
+.HP 10
+\fBrndc.conf\fR
+.SH "DESCRIPTION"
+.PP
+\fIrndc.conf\fR
+is the configuration file for
+\fBrndc\fR, the BIND 9 name server control utility. This file has a similar structure and syntax to
+\fInamed.conf\fR. Statements are enclosed in braces and terminated with a semi\-colon. Clauses in the statements are also semi\-colon terminated. The usual comment styles are supported:
+.PP
+C style: /* */
+.PP
+C++ style: // to end of line
+.PP
+Unix style: # to end of line
+.PP
+\fIrndc.conf\fR
+is much simpler than
+\fInamed.conf\fR. The file uses three statements: an options statement, a server statement and a key statement.
+.PP
+The
+\fBoptions\fR
+statement contains five clauses. The
+\fBdefault\-server\fR
+clause is followed by the name or address of a name server. This host will be used when no name server is given as an argument to
+\fBrndc\fR. The
+\fBdefault\-key\fR
+clause is followed by the name of a key which is identified by a
+\fBkey\fR
+statement. If no
+\fBkeyid\fR
+is provided on the rndc command line, and no
+\fBkey\fR
+clause is found in a matching
+\fBserver\fR
+statement, this default key will be used to authenticate the server's commands and responses. The
+\fBdefault\-port\fR
+clause is followed by the port to connect to on the remote name server. If no
+\fBport\fR
+option is provided on the rndc command line, and no
+\fBport\fR
+clause is found in a matching
+\fBserver\fR
+statement, this default port will be used to connect. The
+\fBdefault\-source\-address\fR
+and
+\fBdefault\-source\-address\-v6\fR
+clauses which can be used to set the IPv4 and IPv6 source addresses respectively.
+.PP
+After the
+\fBserver\fR
+keyword, the server statement includes a string which is the hostname or address for a name server. The statement has three possible clauses:
+\fBkey\fR,
+\fBport\fR
+and
+\fBaddresses\fR. The key name must match the name of a key statement in the file. The port number specifies the port to connect to. If an
+\fBaddresses\fR
+clause is supplied these addresses will be used instead of the server name. Each address can take an optional port. If an
+\fBsource\-address\fR
+or
+\fBsource\-address\-v6\fR
+of supplied then these will be used to specify the IPv4 and IPv6 source addresses respectively.
+.PP
+The
+\fBkey\fR
+statement begins with an identifying string, the name of the key. The statement has two clauses.
+\fBalgorithm\fR
+identifies the encryption algorithm for
+\fBrndc\fR
+to use; currently only HMAC\-MD5 is supported. This is followed by a secret clause which contains the base\-64 encoding of the algorithm's encryption key. The base\-64 string is enclosed in double quotes.
+.PP
+There are two common ways to generate the base\-64 string for the secret. The BIND 9 program
+\fBrndc\-confgen\fR
+can be used to generate a random key, or the
+\fBmmencode\fR
+program, also known as
+\fBmimencode\fR, can be used to generate a base\-64 string from known input.
+\fBmmencode\fR
+does not ship with BIND 9 but is available on many systems. See the EXAMPLE section for sample command lines for each.
+.SH "EXAMPLE"
+.PP
+.RS 4
+.nf
+ options {
+ default\-server localhost;
+ default\-key samplekey;
+ };
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+ server localhost {
+ key samplekey;
+ };
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+ server testserver {
+ key testkey;
+ addresses { localhost port 5353; };
+ };
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+ key samplekey {
+ algorithm hmac\-md5;
+ secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz";
+ };
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+ key testkey {
+ algorithm hmac\-md5;
+ secret "R3HI8P6BKw9ZwXwN3VZKuQ==";
+ };
+.fi
+.RE
+.sp
+.PP
+In the above example,
+\fBrndc\fR
+will by default use the server at localhost (127.0.0.1) and the key called samplekey. Commands to the localhost server will use the samplekey key, which must also be defined in the server's configuration file with the same name and secret. The key statement indicates that samplekey uses the HMAC\-MD5 algorithm and its secret clause contains the base\-64 encoding of the HMAC\-MD5 secret enclosed in double quotes.
+.PP
+If
+\fBrndc \-s testserver\fR
+is used then
+\fBrndc\fR
+will connect to server on localhost port 5353 using the key testkey.
+.PP
+To generate a random secret with
+\fBrndc\-confgen\fR:
+.PP
+\fBrndc\-confgen\fR
+.PP
+A complete
+\fIrndc.conf\fR
+file, including the randomly generated key, will be written to the standard output. Commented\-out
+\fBkey\fR
+and
+\fBcontrols\fR
+statements for
+\fInamed.conf\fR
+are also printed.
+.PP
+To generate a base\-64 secret with
+\fBmmencode\fR:
+.PP
+\fBecho "known plaintext for a secret" | mmencode\fR
+.SH "NAME SERVER CONFIGURATION"
+.PP
+The name server must be configured to accept rndc connections and to recognize the key specified in the
+\fIrndc.conf\fR
+file, using the controls statement in
+\fInamed.conf\fR. See the sections on the
+\fBcontrols\fR
+statement in the BIND 9 Administrator Reference Manual for details.
+.SH "SEE ALSO"
+.PP
+\fBrndc\fR(8),
+\fBrndc\-confgen\fR(8),
+\fBmmencode\fR(1),
+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 2000, 2001 Internet Software Consortium.
+.br
diff --git a/bin/rndc/rndc.conf.docbook b/bin/rndc/rndc.conf.docbook
new file mode 100644
index 0000000..9de1995
--- /dev/null
+++ b/bin/rndc/rndc.conf.docbook
@@ -0,0 +1,252 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: rndc.conf.docbook,v 1.17 2007/06/18 23:47:25 tbox Exp $ -->
+<refentry id="man.rndc.conf">
+ <refentryinfo>
+ <date>June 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><filename>rndc.conf</filename></refentrytitle>
+ <manvolnum>5</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><filename>rndc.conf</filename></refname>
+ <refpurpose>rndc configuration file</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>rndc.conf</command>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><filename>rndc.conf</filename> is the configuration file
+ for <command>rndc</command>, the BIND 9 name server control
+ utility. This file has a similar structure and syntax to
+ <filename>named.conf</filename>. Statements are enclosed
+ in braces and terminated with a semi-colon. Clauses in
+ the statements are also semi-colon terminated. The usual
+ comment styles are supported:
+ </para>
+ <para>
+ C style: /* */
+ </para>
+ <para>
+ C++ style: // to end of line
+ </para>
+ <para>
+ Unix style: # to end of line
+ </para>
+ <para><filename>rndc.conf</filename> is much simpler than
+ <filename>named.conf</filename>. The file uses three
+ statements: an options statement, a server statement
+ and a key statement.
+ </para>
+ <para>
+ The <option>options</option> statement contains five clauses.
+ The <option>default-server</option> clause is followed by the
+ name or address of a name server. This host will be used when
+ no name server is given as an argument to
+ <command>rndc</command>. The <option>default-key</option>
+ clause is followed by the name of a key which is identified by
+ a <option>key</option> statement. If no
+ <option>keyid</option> is provided on the rndc command line,
+ and no <option>key</option> clause is found in a matching
+ <option>server</option> statement, this default key will be
+ used to authenticate the server's commands and responses. The
+ <option>default-port</option> clause is followed by the port
+ to connect to on the remote name server. If no
+ <option>port</option> option is provided on the rndc command
+ line, and no <option>port</option> clause is found in a
+ matching <option>server</option> statement, this default port
+ will be used to connect.
+ The <option>default-source-address</option> and
+ <option>default-source-address-v6</option> clauses which
+ can be used to set the IPv4 and IPv6 source addresses
+ respectively.
+ </para>
+ <para>
+ After the <option>server</option> keyword, the server
+ statement includes a string which is the hostname or address
+ for a name server. The statement has three possible clauses:
+ <option>key</option>, <option>port</option> and
+ <option>addresses</option>. The key name must match the
+ name of a key statement in the file. The port number
+ specifies the port to connect to. If an <option>addresses</option>
+ clause is supplied these addresses will be used instead of
+ the server name. Each address can take an optional port.
+ If an <option>source-address</option> or <option>source-address-v6</option>
+ of supplied then these will be used to specify the IPv4 and IPv6
+ source addresses respectively.
+ </para>
+ <para>
+ The <option>key</option> statement begins with an identifying
+ string, the name of the key. The statement has two clauses.
+ <option>algorithm</option> identifies the encryption algorithm
+ for <command>rndc</command> to use; currently only HMAC-MD5
+ is
+ supported. This is followed by a secret clause which contains
+ the base-64 encoding of the algorithm's encryption key. The
+ base-64 string is enclosed in double quotes.
+ </para>
+ <para>
+ There are two common ways to generate the base-64 string for the
+ secret. The BIND 9 program <command>rndc-confgen</command>
+ can
+ be used to generate a random key, or the
+ <command>mmencode</command> program, also known as
+ <command>mimencode</command>, can be used to generate a
+ base-64
+ string from known input. <command>mmencode</command> does
+ not
+ ship with BIND 9 but is available on many systems. See the
+ EXAMPLE section for sample command lines for each.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>EXAMPLE</title>
+
+ <para><programlisting>
+ options {
+ default-server localhost;
+ default-key samplekey;
+ };
+</programlisting>
+ </para>
+ <para><programlisting>
+ server localhost {
+ key samplekey;
+ };
+</programlisting>
+ </para>
+ <para><programlisting>
+ server testserver {
+ key testkey;
+ addresses { localhost port 5353; };
+ };
+</programlisting>
+ </para>
+ <para><programlisting>
+ key samplekey {
+ algorithm hmac-md5;
+ secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz";
+ };
+</programlisting>
+ </para>
+ <para><programlisting>
+ key testkey {
+ algorithm hmac-md5;
+ secret "R3HI8P6BKw9ZwXwN3VZKuQ==";
+ };
+ </programlisting>
+ </para>
+
+ <para>
+ In the above example, <command>rndc</command> will by
+ default use
+ the server at localhost (127.0.0.1) and the key called samplekey.
+ Commands to the localhost server will use the samplekey key, which
+ must also be defined in the server's configuration file with the
+ same name and secret. The key statement indicates that samplekey
+ uses the HMAC-MD5 algorithm and its secret clause contains the
+ base-64 encoding of the HMAC-MD5 secret enclosed in double quotes.
+ </para>
+ <para>
+ If <command>rndc -s testserver</command> is used then <command>rndc</command> will
+ connect to server on localhost port 5353 using the key testkey.
+ </para>
+ <para>
+ To generate a random secret with <command>rndc-confgen</command>:
+ </para>
+ <para><userinput>rndc-confgen</userinput>
+ </para>
+ <para>
+ A complete <filename>rndc.conf</filename> file, including
+ the
+ randomly generated key, will be written to the standard
+ output. Commented-out <option>key</option> and
+ <option>controls</option> statements for
+ <filename>named.conf</filename> are also printed.
+ </para>
+ <para>
+ To generate a base-64 secret with <command>mmencode</command>:
+ </para>
+ <para><userinput>echo "known plaintext for a secret" | mmencode</userinput>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>NAME SERVER CONFIGURATION</title>
+ <para>
+ The name server must be configured to accept rndc connections and
+ to recognize the key specified in the <filename>rndc.conf</filename>
+ file, using the controls statement in <filename>named.conf</filename>.
+ See the sections on the <option>controls</option> statement in the
+ BIND 9 Administrator Reference Manual for details.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>rndc</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc-confgen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>mmencode</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/rndc/rndc.conf.html b/bin/rndc/rndc.conf.html
new file mode 100644
index 0000000..144cd1c
--- /dev/null
+++ b/bin/rndc/rndc.conf.html
@@ -0,0 +1,217 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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.conf.html,v 1.29 2007/05/09 13:35:57 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>rndc.conf</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.rndc.conf"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><code class="filename">rndc.conf</code> &#8212; rndc configuration file</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">rndc.conf</code> </p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543352"></a><h2>DESCRIPTION</h2>
+<p><code class="filename">rndc.conf</code> is the configuration file
+ for <span><strong class="command">rndc</strong></span>, the BIND 9 name server control
+ utility. This file has a similar structure and syntax to
+ <code class="filename">named.conf</code>. Statements are enclosed
+ in braces and terminated with a semi-colon. Clauses in
+ the statements are also semi-colon terminated. The usual
+ comment styles are supported:
+ </p>
+<p>
+ C style: /* */
+ </p>
+<p>
+ C++ style: // to end of line
+ </p>
+<p>
+ Unix style: # to end of line
+ </p>
+<p><code class="filename">rndc.conf</code> is much simpler than
+ <code class="filename">named.conf</code>. The file uses three
+ statements: an options statement, a server statement
+ and a key statement.
+ </p>
+<p>
+ The <code class="option">options</code> statement contains five clauses.
+ The <code class="option">default-server</code> clause is followed by the
+ name or address of a name server. This host will be used when
+ no name server is given as an argument to
+ <span><strong class="command">rndc</strong></span>. The <code class="option">default-key</code>
+ clause is followed by the name of a key which is identified by
+ a <code class="option">key</code> statement. If no
+ <code class="option">keyid</code> is provided on the rndc command line,
+ and no <code class="option">key</code> clause is found in a matching
+ <code class="option">server</code> statement, this default key will be
+ used to authenticate the server's commands and responses. The
+ <code class="option">default-port</code> clause is followed by the port
+ to connect to on the remote name server. If no
+ <code class="option">port</code> option is provided on the rndc command
+ line, and no <code class="option">port</code> clause is found in a
+ matching <code class="option">server</code> statement, this default port
+ will be used to connect.
+ The <code class="option">default-source-address</code> and
+ <code class="option">default-source-address-v6</code> clauses which
+ can be used to set the IPv4 and IPv6 source addresses
+ respectively.
+ </p>
+<p>
+ After the <code class="option">server</code> keyword, the server
+ statement includes a string which is the hostname or address
+ for a name server. The statement has three possible clauses:
+ <code class="option">key</code>, <code class="option">port</code> and
+ <code class="option">addresses</code>. The key name must match the
+ name of a key statement in the file. The port number
+ specifies the port to connect to. If an <code class="option">addresses</code>
+ clause is supplied these addresses will be used instead of
+ the server name. Each address can take an optional port.
+ If an <code class="option">source-address</code> or <code class="option">source-address-v6</code>
+ of supplied then these will be used to specify the IPv4 and IPv6
+ source addresses respectively.
+ </p>
+<p>
+ The <code class="option">key</code> statement begins with an identifying
+ string, the name of the key. The statement has two clauses.
+ <code class="option">algorithm</code> identifies the encryption algorithm
+ for <span><strong class="command">rndc</strong></span> to use; currently only HMAC-MD5
+ is
+ supported. This is followed by a secret clause which contains
+ the base-64 encoding of the algorithm's encryption key. The
+ base-64 string is enclosed in double quotes.
+ </p>
+<p>
+ There are two common ways to generate the base-64 string for the
+ secret. The BIND 9 program <span><strong class="command">rndc-confgen</strong></span>
+ can
+ be used to generate a random key, or the
+ <span><strong class="command">mmencode</strong></span> program, also known as
+ <span><strong class="command">mimencode</strong></span>, can be used to generate a
+ base-64
+ string from known input. <span><strong class="command">mmencode</strong></span> does
+ not
+ ship with BIND 9 but is available on many systems. See the
+ EXAMPLE section for sample command lines for each.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543500"></a><h2>EXAMPLE</h2>
+<pre class="programlisting">
+ options {
+ default-server localhost;
+ default-key samplekey;
+ };
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+ server localhost {
+ key samplekey;
+ };
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+ server testserver {
+ key testkey;
+ addresses { localhost port 5353; };
+ };
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+ key samplekey {
+ algorithm hmac-md5;
+ secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz";
+ };
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+ key testkey {
+ algorithm hmac-md5;
+ secret "R3HI8P6BKw9ZwXwN3VZKuQ==";
+ };
+ </pre>
+<p>
+ </p>
+<p>
+ In the above example, <span><strong class="command">rndc</strong></span> will by
+ default use
+ the server at localhost (127.0.0.1) and the key called samplekey.
+ Commands to the localhost server will use the samplekey key, which
+ must also be defined in the server's configuration file with the
+ same name and secret. The key statement indicates that samplekey
+ uses the HMAC-MD5 algorithm and its secret clause contains the
+ base-64 encoding of the HMAC-MD5 secret enclosed in double quotes.
+ </p>
+<p>
+ If <span><strong class="command">rndc -s testserver</strong></span> is used then <span><strong class="command">rndc</strong></span> will
+ connect to server on localhost port 5353 using the key testkey.
+ </p>
+<p>
+ To generate a random secret with <span><strong class="command">rndc-confgen</strong></span>:
+ </p>
+<p><strong class="userinput"><code>rndc-confgen</code></strong>
+ </p>
+<p>
+ A complete <code class="filename">rndc.conf</code> file, including
+ the
+ randomly generated key, will be written to the standard
+ output. Commented-out <code class="option">key</code> and
+ <code class="option">controls</code> statements for
+ <code class="filename">named.conf</code> are also printed.
+ </p>
+<p>
+ To generate a base-64 secret with <span><strong class="command">mmencode</strong></span>:
+ </p>
+<p><strong class="userinput"><code>echo "known plaintext for a secret" | mmencode</code></strong>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543592"></a><h2>NAME SERVER CONFIGURATION</h2>
+<p>
+ The name server must be configured to accept rndc connections and
+ to recognize the key specified in the <code class="filename">rndc.conf</code>
+ file, using the controls statement in <code class="filename">named.conf</code>.
+ See the sections on the <code class="option">controls</code> statement in the
+ BIND 9 Administrator Reference Manual for details.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543613"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">rndc-confgen</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">mmencode</span>(1)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543652"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/rndc/rndc.docbook b/bin/rndc/rndc.docbook
new file mode 100644
index 0000000..d407f2b
--- /dev/null
+++ b/bin/rndc/rndc.docbook
@@ -0,0 +1,253 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: rndc.docbook,v 1.21 2007/12/14 20:39:14 marka Exp $ -->
+<refentry id="man.rndc">
+ <refentryinfo>
+ <date>June 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle><application>rndc</application></refentrytitle>
+ <manvolnum>8</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname><application>rndc</application></refname>
+ <refpurpose>name server control utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>rndc</command>
+ <arg><option>-b <replaceable class="parameter">source-address</replaceable></option></arg>
+ <arg><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
+ <arg><option>-k <replaceable class="parameter">key-file</replaceable></option></arg>
+ <arg><option>-s <replaceable class="parameter">server</replaceable></option></arg>
+ <arg><option>-p <replaceable class="parameter">port</replaceable></option></arg>
+ <arg><option>-V</option></arg>
+ <arg><option>-y <replaceable class="parameter">key_id</replaceable></option></arg>
+ <arg choice="req">command</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>rndc</command>
+ controls the operation of a name
+ server. It supersedes the <command>ndc</command> utility
+ that was provided in old BIND releases. If
+ <command>rndc</command> is invoked with no command line
+ options or arguments, it prints a short summary of the
+ supported commands and the available options and their
+ arguments.
+ </para>
+ <para><command>rndc</command>
+ communicates with the name server
+ over a TCP connection, sending commands authenticated with
+ digital signatures. In the current versions of
+ <command>rndc</command> and <command>named</command>,
+ the only supported authentication algorithm is HMAC-MD5,
+ which uses a shared secret on each end of the connection.
+ This provides TSIG-style authentication for the command
+ request and the name server's response. All commands sent
+ over the channel must be signed by a key_id known to the
+ server.
+ </para>
+ <para><command>rndc</command>
+ reads a configuration file to
+ determine how to contact the name server and decide what
+ algorithm and key it should use.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <variablelist>
+ <varlistentry>
+ <term>-b <replaceable class="parameter">source-address</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">source-address</replaceable>
+ as the source address for the connection to the server.
+ Multiple instances are permitted to allow setting of both
+ the IPv4 and IPv6 source addresses.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">config-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">config-file</replaceable>
+ as the configuration file instead of the default,
+ <filename>/etc/rndc.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">key-file</replaceable></term>
+ <listitem>
+ <para>
+ Use <replaceable class="parameter">key-file</replaceable>
+ as the key file instead of the default,
+ <filename>/etc/rndc.key</filename>. The key in
+ <filename>/etc/rndc.key</filename> will be used to
+ authenticate
+ commands sent to the server if the <replaceable class="parameter">config-file</replaceable>
+ does not exist.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s <replaceable class="parameter">server</replaceable></term>
+ <listitem>
+ <para><replaceable class="parameter">server</replaceable> is
+ the name or address of the server which matches a
+ server statement in the configuration file for
+ <command>rndc</command>. If no server is supplied on the
+ command line, the host named by the default-server clause
+ in the options statement of the <command>rndc</command>
+ configuration file will be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Send commands to TCP port
+ <replaceable class="parameter">port</replaceable>
+ instead
+ of BIND 9's default control channel port, 953.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Enable verbose logging.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-y <replaceable class="parameter">key_id</replaceable></term>
+ <listitem>
+ <para>
+ Use the key <replaceable class="parameter">key_id</replaceable>
+ from the configuration file.
+ <replaceable class="parameter">key_id</replaceable>
+ must be
+ known by named with the same algorithm and secret string
+ in order for control message validation to succeed.
+ If no <replaceable class="parameter">key_id</replaceable>
+ is specified, <command>rndc</command> will first look
+ for a key clause in the server statement of the server
+ being used, or if no server statement is present for that
+ host, then the default-key clause of the options statement.
+ Note that the configuration file contains shared secrets
+ which are used to send authenticated control commands
+ to name servers. It should therefore not have general read
+ or write access.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+ For the complete set of commands supported by <command>rndc</command>,
+ see the BIND 9 Administrator Reference Manual or run
+ <command>rndc</command> without arguments to see its help
+ message.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>LIMITATIONS</title>
+ <para><command>rndc</command>
+ does not yet support all the commands of
+ the BIND 8 <command>ndc</command> utility.
+ </para>
+ <para>
+ There is currently no way to provide the shared secret for a
+ <option>key_id</option> without using the configuration file.
+ </para>
+ <para>
+ Several error messages could be clearer.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>rndc.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>rndc-confgen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named.conf</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>ndc</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>BIND 9 Administrator Reference Manual</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>AUTHOR</title>
+ <para><corpauthor>Internet Systems Consortium</corpauthor>
+ </para>
+ </refsect1>
+
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/rndc/rndc.html b/bin/rndc/rndc.html
new file mode 100644
index 0000000..a8d11c4
--- /dev/null
+++ b/bin/rndc/rndc.html
@@ -0,0 +1,165 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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.html,v 1.31 2007/12/14 22:37:22 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>rndc</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="man.rndc"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">rndc</span> &#8212; name server control utility</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">rndc</code> [<code class="option">-b <em class="replaceable"><code>source-address</code></em></code>] [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-k <em class="replaceable"><code>key-file</code></em></code>] [<code class="option">-s <em class="replaceable"><code>server</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-V</code>] [<code class="option">-y <em class="replaceable"><code>key_id</code></em></code>] {command}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543413"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">rndc</strong></span>
+ controls the operation of a name
+ server. It supersedes the <span><strong class="command">ndc</strong></span> utility
+ that was provided in old BIND releases. If
+ <span><strong class="command">rndc</strong></span> is invoked with no command line
+ options or arguments, it prints a short summary of the
+ supported commands and the available options and their
+ arguments.
+ </p>
+<p><span><strong class="command">rndc</strong></span>
+ communicates with the name server
+ over a TCP connection, sending commands authenticated with
+ digital signatures. In the current versions of
+ <span><strong class="command">rndc</strong></span> and <span><strong class="command">named</strong></span>,
+ the only supported authentication algorithm is HMAC-MD5,
+ which uses a shared secret on each end of the connection.
+ This provides TSIG-style authentication for the command
+ request and the name server's response. All commands sent
+ over the channel must be signed by a key_id known to the
+ server.
+ </p>
+<p><span><strong class="command">rndc</strong></span>
+ reads a configuration file to
+ determine how to contact the name server and decide what
+ algorithm and key it should use.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543448"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-b <em class="replaceable"><code>source-address</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>source-address</code></em>
+ as the source address for the connection to the server.
+ Multiple instances are permitted to allow setting of both
+ the IPv4 and IPv6 source addresses.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>config-file</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>config-file</code></em>
+ as the configuration file instead of the default,
+ <code class="filename">/etc/rndc.conf</code>.
+ </p></dd>
+<dt><span class="term">-k <em class="replaceable"><code>key-file</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>key-file</code></em>
+ as the key file instead of the default,
+ <code class="filename">/etc/rndc.key</code>. The key in
+ <code class="filename">/etc/rndc.key</code> will be used to
+ authenticate
+ commands sent to the server if the <em class="replaceable"><code>config-file</code></em>
+ does not exist.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>server</code></em></span></dt>
+<dd><p><em class="replaceable"><code>server</code></em> is
+ the name or address of the server which matches a
+ server statement in the configuration file for
+ <span><strong class="command">rndc</strong></span>. If no server is supplied on the
+ command line, the host named by the default-server clause
+ in the options statement of the <span><strong class="command">rndc</strong></span>
+ configuration file will be used.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd><p>
+ Send commands to TCP port
+ <em class="replaceable"><code>port</code></em>
+ instead
+ of BIND 9's default control channel port, 953.
+ </p></dd>
+<dt><span class="term">-V</span></dt>
+<dd><p>
+ Enable verbose logging.
+ </p></dd>
+<dt><span class="term">-y <em class="replaceable"><code>key_id</code></em></span></dt>
+<dd><p>
+ Use the key <em class="replaceable"><code>key_id</code></em>
+ from the configuration file.
+ <em class="replaceable"><code>key_id</code></em>
+ must be
+ known by named with the same algorithm and secret string
+ in order for control message validation to succeed.
+ If no <em class="replaceable"><code>key_id</code></em>
+ is specified, <span><strong class="command">rndc</strong></span> will first look
+ for a key clause in the server statement of the server
+ being used, or if no server statement is present for that
+ host, then the default-key clause of the options statement.
+ Note that the configuration file contains shared secrets
+ which are used to send authenticated control commands
+ to name servers. It should therefore not have general read
+ or write access.
+ </p></dd>
+</dl></div>
+<p>
+ For the complete set of commands supported by <span><strong class="command">rndc</strong></span>,
+ see the BIND 9 Administrator Reference Manual or run
+ <span><strong class="command">rndc</strong></span> without arguments to see its help
+ message.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543656"></a><h2>LIMITATIONS</h2>
+<p><span><strong class="command">rndc</strong></span>
+ does not yet support all the commands of
+ the BIND 8 <span><strong class="command">ndc</strong></span> utility.
+ </p>
+<p>
+ There is currently no way to provide the shared secret for a
+ <code class="option">key_id</code> without using the configuration file.
+ </p>
+<p>
+ Several error messages could be clearer.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543683"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">rndc.conf</span>(5)</span>,
+ <span class="citerefentry"><span class="refentrytitle">rndc-confgen</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named.conf</span>(5)</span>,
+ <span class="citerefentry"><span class="refentrytitle">ndc</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543738"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/rndc/unix/Makefile.in b/bin/rndc/unix/Makefile.in
new file mode 100644
index 0000000..31a0532
--- /dev/null
+++ b/bin/rndc/unix/Makefile.in
@@ -0,0 +1,36 @@
+# 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
new file mode 100644
index 0000000..ddf8259
--- /dev/null
+++ b/bin/rndc/unix/os.c
@@ -0,0 +1,70 @@
+/*
+ * 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 <config.h>
+
+#include <rndc/os.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+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.c b/bin/rndc/util.c
new file mode 100644
index 0000000..c654462
--- /dev/null
+++ b/bin/rndc/util.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: util.c,v 1.7 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <isc/boolean.h>
+
+#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/rndc/util.h b/bin/rndc/util.h
new file mode 100644
index 0000000..7adcaa5
--- /dev/null
+++ b/bin/rndc/util.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: util.h,v 1.10 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef RNDC_UTIL_H
+#define RNDC_UTIL_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+
+#include <isc/formatcheck.h>
+
+#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);
+
+void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+ISC_LANG_ENDDECLS
+
+#endif /* RNDC_UTIL_H */
diff --git a/bin/rndc/win32/confgen.dsp b/bin/rndc/win32/confgen.dsp
new file mode 100644
index 0000000..3cdd722
--- /dev/null
+++ b/bin/rndc/win32/confgen.dsp
@@ -0,0 +1,111 @@
+# Microsoft Developer Studio Project File - Name="rndcconfgen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=rndcconfgen - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "confgen.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "confgen.mak" CFG="rndcconfgen - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rndcconfgen - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "rndcconfgen - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rndcconfgen - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/util.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/rndc-confgen.exe"
+
+!ELSEIF "$(CFG)" == "rndcconfgen - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/util.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/rndc-confgen.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "rndcconfgen - Win32 Release"
+# Name "rndcconfgen - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\os.c
+# End Source File
+# Begin Source File
+
+SOURCE="..\rndc-confgen.c"
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\util.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/rndc/win32/confgen.dsw b/bin/rndc/win32/confgen.dsw
new file mode 100644
index 0000000..1b1f888
--- /dev/null
+++ b/bin/rndc/win32/confgen.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "confgen"=".\confgen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/rndc/win32/confgen.mak b/bin/rndc/win32/confgen.mak
new file mode 100644
index 0000000..02299e2
--- /dev/null
+++ b/bin/rndc/win32/confgen.mak
@@ -0,0 +1,313 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on confgen.dsp
+!IF "$(CFG)" == ""
+CFG=rndcconfgen - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to rndcconfgen - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "rndcconfgen - Win32 Release" && "$(CFG)" != "rndcconfgen - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "confgen.mak" CFG="rndcconfgen - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rndcconfgen - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "rndcconfgen - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rndcconfgen - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "rndcconfgen - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\rndc-confgen.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\rndc-confgen.obj"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\rndc-confgen.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\confgen.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\confgen.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\rndc-confgen.pdb" /machine:I386 /out:"../../../Build/Release/rndc-confgen.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\rndc-confgen.obj" \
+ "$(INTDIR)\util.obj"
+
+"..\..\..\Build\Release\rndc-confgen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "rndcconfgen - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\rndc-confgen.exe" "$(OUTDIR)\confgen.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\os.sbr"
+ -@erase "$(INTDIR)\rndc-confgen.obj"
+ -@erase "$(INTDIR)\rndc-confgen.sbr"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\util.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\confgen.bsc"
+ -@erase "$(OUTDIR)\rndc-confgen.pdb"
+ -@erase "..\..\..\Build\Debug\rndc-confgen.exe"
+ -@erase "..\..\..\Build\Debug\rndc-confgen.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\confgen.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\os.sbr" \
+ "$(INTDIR)\rndc-confgen.sbr" \
+ "$(INTDIR)\util.sbr"
+
+"$(OUTDIR)\confgen.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\rndc-confgen.pdb" /debug /machine:I386 /out:"../../../Build/Debug/rndc-confgen.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\rndc-confgen.obj" \
+ "$(INTDIR)\util.obj"
+
+"..\..\..\Build\Debug\rndc-confgen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("confgen.dep")
+!INCLUDE "confgen.dep"
+!ELSE
+!MESSAGE Warning: cannot find "confgen.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "rndcconfgen - Win32 Release" || "$(CFG)" == "rndcconfgen - Win32 Debug"
+SOURCE=.\os.c
+
+!IF "$(CFG)" == "rndcconfgen - Win32 Release"
+
+
+"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "rndcconfgen - Win32 Debug"
+
+
+"$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE="..\rndc-confgen.c"
+
+!IF "$(CFG)" == "rndcconfgen - Win32 Release"
+
+
+"$(INTDIR)\rndc-confgen.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rndcconfgen - Win32 Debug"
+
+
+"$(INTDIR)\rndc-confgen.obj" "$(INTDIR)\rndc-confgen.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\util.c
+
+!IF "$(CFG)" == "rndcconfgen - Win32 Release"
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rndcconfgen - Win32 Debug"
+
+
+"$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/rndc/win32/os.c b/bin/rndc/win32/os.c
new file mode 100644
index 0000000..cf9d311
--- /dev/null
+++ b/bin/rndc/win32/os.c
@@ -0,0 +1,65 @@
+/*
+ * 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: os.c,v 1.6 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <rndc/os.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <io.h>
+#include <sys/stat.h>
+
+int
+set_user(FILE *fd, const char *user) {
+ return (0);
+}
+
+/*
+ * Note that the error code EOPNOTSUPP does not exist
+ * on win32 so we are forced to fall back to using
+ * ENOENT for now. WSAEOPNOTSUPP does exist but it
+ * should only be used for sockets.
+ */
+
+FILE *
+safe_create(const char *filename) {
+ int fd;
+ FILE *f;
+ struct stat sb;
+
+ if (stat(filename, &sb) == -1) {
+ if (errno != ENOENT)
+ return (NULL);
+ } else if ((sb.st_mode & S_IFREG) == 0) {
+ errno = ENOENT;
+ return (NULL);
+ }
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 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/win32/rndc.dsp b/bin/rndc/win32/rndc.dsp
new file mode 100644
index 0000000..ba153e4
--- /dev/null
+++ b/bin/rndc/win32/rndc.dsp
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="rndc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=rndc - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rndc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rndc.mak" CFG="rndc - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rndc - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "rndc - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rndc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/util.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /profile /machine:I386 /out:"../../../Build/Release/rndc.exe"
+
+!ELSEIF "$(CFG)" == "rndc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/util.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/rndc.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "rndc - Win32 Release"
+# Name "rndc - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\rndc.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\util.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/rndc/win32/rndc.dsw b/bin/rndc/win32/rndc.dsw
new file mode 100644
index 0000000..97d3e43
--- /dev/null
+++ b/bin/rndc/win32/rndc.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "rndc"=".\rndc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/rndc/win32/rndc.mak b/bin/rndc/win32/rndc.mak
new file mode 100644
index 0000000..8220048
--- /dev/null
+++ b/bin/rndc/win32/rndc.mak
@@ -0,0 +1,425 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on rndc.dsp
+!IF "$(CFG)" == ""
+CFG=rndc - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to rndc - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "rndc - Win32 Release" && "$(CFG)" != "rndc - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rndc.mak" CFG="rndc - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rndc - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "rndc - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rndc - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "rndc - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\rndc.exe"
+
+!ELSE
+
+ALL : "libbind9 - Win32 Release" "libisccfg - Win32 Release" "libisccc - Win32 Release" "libisc - Win32 Release" "..\..\..\Build\Release\rndc.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - Win32 ReleaseCLEAN" "libisccc - Win32 ReleaseCLEAN" "libisccfg - Win32 ReleaseCLEAN" "libbind9 - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\rndc.obj"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\rndc.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\rndc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\rndc.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/isccc/win32/Release/libisccc.lib ../../../lib/bind9/win32/Release/libbind9.lib /nologo /subsystem:console /profile /machine:I386 /out:"../../../Build/Release/rndc.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\rndc.obj" \
+ "$(INTDIR)\util.obj" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\isccc\win32\Release\libisccc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib"
+
+"..\..\..\Build\Release\rndc.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "rndc - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\rndc.exe" "$(OUTDIR)\rndc.bsc"
+
+!ELSE
+
+ALL : "libbind9 - Win32 Debug" "libisccfg - Win32 Debug" "libisccc - Win32 Debug" "libisc - Win32 Debug" "..\..\..\Build\Debug\rndc.exe" "$(OUTDIR)\rndc.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - Win32 DebugCLEAN" "libisccc - Win32 DebugCLEAN" "libisccfg - Win32 DebugCLEAN" "libbind9 - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\rndc.obj"
+ -@erase "$(INTDIR)\rndc.sbr"
+ -@erase "$(INTDIR)\util.obj"
+ -@erase "$(INTDIR)\util.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\rndc.bsc"
+ -@erase "$(OUTDIR)\rndc.pdb"
+ -@erase "..\..\..\Build\Debug\rndc.exe"
+ -@erase "..\..\..\Build\Debug\rndc.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/isccc/include" /I "../../../lib/isccfg/include" /I "../../../lib/bind9/include" /I "../../../lib/dns/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\rndc.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\rndc.sbr" \
+ "$(INTDIR)\util.sbr"
+
+"$(OUTDIR)\rndc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/isccc/win32/Debug/libisccc.lib ../../../lib/bind9/win32/Debug/libbind9.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\rndc.pdb" /debug /machine:I386 /out:"../../../Build/Debug/rndc.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\rndc.obj" \
+ "$(INTDIR)\util.obj" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\isccc\win32\Debug\libisccc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib"
+
+"..\..\..\Build\Debug\rndc.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("rndc.dep")
+!INCLUDE "rndc.dep"
+!ELSE
+!MESSAGE Warning: cannot find "rndc.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "rndc - Win32 Release" || "$(CFG)" == "rndc - Win32 Debug"
+SOURCE=..\rndc.c
+
+!IF "$(CFG)" == "rndc - Win32 Release"
+
+
+"$(INTDIR)\rndc.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rndc - Win32 Debug"
+
+
+"$(INTDIR)\rndc.obj" "$(INTDIR)\rndc.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\util.c
+
+!IF "$(CFG)" == "rndc - Win32 Release"
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "rndc - Win32 Debug"
+
+
+"$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "rndc - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ELSEIF "$(CFG)" == "rndc - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "rndc - Win32 Release"
+
+"libisccc - Win32 Release" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - Win32 Release"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisccc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ELSEIF "$(CFG)" == "rndc - Win32 Debug"
+
+"libisccc - Win32 Debug" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - Win32 Debug"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisccc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isccc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccc.mak" CFG="libisccc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "rndc - Win32 Release"
+
+"libisccfg - Win32 Release" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Release"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisccfg - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ELSEIF "$(CFG)" == "rndc - Win32 Debug"
+
+"libisccfg - Win32 Debug" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Debug"
+ cd "..\..\..\bin\rndc\win32"
+
+"libisccfg - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "rndc - Win32 Release"
+
+"libbind9 - Win32 Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release"
+ cd "..\..\..\bin\rndc\win32"
+
+"libbind9 - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ELSEIF "$(CFG)" == "rndc - Win32 Debug"
+
+"libbind9 - Win32 Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug"
+ cd "..\..\..\bin\rndc\win32"
+
+"libbind9 - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\rndc\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/rndc/win32/rndcutil.dsp b/bin/rndc/win32/rndcutil.dsp
new file mode 100644
index 0000000..8827e09
--- /dev/null
+++ b/bin/rndc/win32/rndcutil.dsp
@@ -0,0 +1,119 @@
+# Microsoft Developer Studio Project File - Name="rndcutil" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static-Link Library" 0x0104
+
+CFG=rndcutil - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "rndcutil.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "rndcutil.mak" CFG="rndcutil - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "rndcutil - Win32 Release" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE "rndcutil - Win32 Debug" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "rndcutil - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /YX /FD /c /Fdutil
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/util.lib"
+LIB32=lib.exe
+# ADD BASE LIB32
+# ADD LIB32 /out:"Release/util.lib"
+
+!ELSEIF "$(CFG)" == "rndcutil - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/dns/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR /YX /FD /GZ /c /Fdutil
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug /out:"Debug/util.lib"
+LIB32=lib.exe
+# ADD BASE LIB32
+# ADD LIB32 /out:"Debug/util.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "rndcutil - Win32 Release"
+# Name "rndcutil - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\util.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/rndc/win32/rndcutil.dsw b/bin/rndc/win32/rndcutil.dsw
new file mode 100644
index 0000000..c6d981a
--- /dev/null
+++ b/bin/rndc/win32/rndcutil.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "rndcutil"=".\rndcutil.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/tests/Kchild.example.+003+04017.key b/bin/tests/Kchild.example.+003+04017.key
new file mode 100644
index 0000000..9f5cbac
--- /dev/null
+++ b/bin/tests/Kchild.example.+003+04017.key
@@ -0,0 +1 @@
+child.example. IN KEY 256 3 3 ALeiYGFXbil6PgHnkm5ZE67ygEVDvGT/gqZmLH7tGboofcPSfyhh1hpw dxZgJ26d/gynWMGVSYzaXfzsxpPoNeYn+qeevQoJOaxXXlfcy8Ik52Rm eW0J9mWlf9hsD7ShIhh1+0kRYGCOCaU25wIe3SLVkN3HgqiCBDYnBY0u nMkqRadiUnoEa3Tcvc9kJx9r9gDstR2A9A5sBhFLI/XQ0gViHHLVpQ4x hz+rTLb/xrBoAb5sQJT3xUjhhdNo9HuL6kwdLdSu//PCl1QnY9NpYPVV SKUo
diff --git a/bin/tests/Kchild.example.+003+04017.private b/bin/tests/Kchild.example.+003+04017.private
new file mode 100644
index 0000000..176ff98
--- /dev/null
+++ b/bin/tests/Kchild.example.+003+04017.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.2
+Algorithm: 3 (DSA)
+Prime(p): vGT/gqZmLH7tGboofcPSfyhh1hpwdxZgJ26d/gynWMGVSYzaXfzsxpPoNeYn+qeevQoJOaxXXlfcy8Ik52RmeQ==
+Subprime(q): t6JgYVduKXo+AeeSblkTrvKARUM=
+Base(g): bQn2ZaV/2GwPtKEiGHX7SRFgYI4JpTbnAh7dItWQ3ceCqIIENicFjS6cySpFp2JSegRrdNy9z2QnH2v2AOy1HQ==
+Private_value(x): J1Ctez8+w1PTR56Hze3pGoe0Wag=
+Public_value(y): gPQObAYRSyP10NIFYhxy1aUOMYc/q0y2/8awaAG+bECU98VI4YXTaPR7i+pMHS3Urv/zwpdUJ2PTaWD1VUilKA==
diff --git a/bin/tests/Makefile.in b/bin/tests/Makefile.in
new file mode 100644
index 0000000..93b63f1
--- /dev/null
+++ b/bin/tests/Makefile.in
@@ -0,0 +1,306 @@
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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: Makefile.in,v 1.131 2008/09/25 04:02:38 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@
+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 = @LIBS@
+
+SUBDIRS = db dst master mem names net rbt sockaddr tasks timers system
+
+# A few of the test programs are built by default:
+# cfg_test is needed for regenerating doc/misc/options;
+# genrandom is needed by the system tests
+
+# Alphabetically
+TARGETS = cfg_test@EXEEXT@ \
+ genrandom@EXEEXT@
+
+# All the other tests are optional and not built by default.
+
+# Alphabetically
+XTARGETS = adb_test@EXEEXT@ \
+ byaddr_test@EXEEXT@ \
+ byname_test@EXEEXT@ \
+ compress_test@EXEEXT@ \
+ db_test@EXEEXT@ \
+ entropy_test@EXEEXT@ \
+ entropy2_test@EXEEXT@ \
+ gxba_test@EXEEXT@ \
+ gxbn_test@EXEEXT@ \
+ hash_test@EXEEXT@ \
+ nsec3hash@EXEEXT@ \
+ fsaccess_test@EXEEXT@ \
+ inter_test@EXEEXT@ \
+ journalprint@EXEEXT@ \
+ keyboard_test@EXEEXT@ \
+ lex_test@EXEEXT@ \
+ lfsr_test@EXEEXT@ \
+ log_test@EXEEXT@ \
+ lwres_test@EXEEXT@ \
+ lwresconf_test@EXEEXT@ \
+ master_test@EXEEXT@ \
+ mempool_test@EXEEXT@ \
+ name_test@EXEEXT@ \
+ nsecify@EXEEXT@ \
+ ratelimiter_test@EXEEXT@ \
+ rbt_test@EXEEXT@ \
+ rdata_test@EXEEXT@ \
+ rwlock_test@EXEEXT@ \
+ serial_test@EXEEXT@ \
+ shutdown_test@EXEEXT@ \
+ sig0_test@EXEEXT@ \
+ sock_test@EXEEXT@ \
+ sym_test@EXEEXT@ \
+ task_test@EXEEXT@ \
+ timer_test@EXEEXT@ \
+ wire_test@EXEEXT@ \
+ zone_test@EXEEXT@
+
+# Alphabetically
+SRCS = cfg_test.c genrandom.c ${XSRCS}
+
+XSRCS = adb_test.c \
+ byaddr_test.c \
+ byname_test.c \
+ compress_test.c \
+ db_test.c \
+ entropy_test.c \
+ entropy2_test.c \
+ gxba_test.c \
+ gxbn_test.c \
+ hash_test.c \
+ fsaccess_test.c \
+ inter_test.c \
+ journalprint.c \
+ keyboard_test.c \
+ lex_test.c \
+ lfsr_test.c \
+ log_test.c \
+ lwres_test.c \
+ lwresconf_test.c \
+ master_test.c \
+ mempool_test.c \
+ name_test.c \
+ nsecify.c \
+ printmsg.c \
+ ratelimiter_test.c \
+ rbt_test.c \
+ rdata_test.c \
+ rwlock_test.c \
+ serial_test.c \
+ shutdown_test.c \
+ sig0_test.c \
+ sock_test.c \
+ sym_test.c \
+ task_test.c \
+ timer_test.c \
+ wire_test.c \
+ zone_test.c
+
+@BIND9_MAKE_RULES@
+
+all_tests: ${XTARGETS}
+
+genrandom@EXEEXT@: genrandom.@O@
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ genrandom.@O@ @GENRANDOMLIB@ ${LIBS}
+
+adb_test@EXEEXT@: adb_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ adb_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+nsecify@EXEEXT@: nsecify.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ nsecify.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+byaddr_test@EXEEXT@: byaddr_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byaddr_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+byname_test@EXEEXT@: byname_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ byname_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+lex_test@EXEEXT@: lex_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lex_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+lfsr_test@EXEEXT@: lfsr_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lfsr_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+log_test@EXEEXT@: log_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ log_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+name_test@EXEEXT@: name_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ name_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+hash_test@EXEEXT@: hash_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ hash_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+entropy_test@EXEEXT@: entropy_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+entropy2_test@EXEEXT@: entropy2_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ entropy2_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+sock_test@EXEEXT@: sock_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sock_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+sym_test@EXEEXT@: sym_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sym_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+task_test@EXEEXT@: task_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ task_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+shutdown_test@EXEEXT@: shutdown_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ shutdown_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+timer_test@EXEEXT@: timer_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ timer_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+ratelimiter_test@EXEEXT@: ratelimiter_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ratelimiter_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+rbt_test@EXEEXT@: rbt_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rbt_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+rdata_test@EXEEXT@: rdata_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rdata_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+rwlock_test@EXEEXT@: rwlock_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ rwlock_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+wire_test@EXEEXT@: wire_test.@O@ printmsg.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ wire_test.@O@ printmsg.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+master_test@EXEEXT@: master_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ master_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+db_test@EXEEXT@: db_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ db_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+compress_test@EXEEXT@: compress_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ compress_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+mempool_test@EXEEXT@: mempool_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ mempool_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+serial_test@EXEEXT@: serial_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ serial_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+zone_test@EXEEXT@: zone_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ zone_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+fsaccess_test@EXEEXT@: fsaccess_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ fsaccess_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+inter_test@EXEEXT@: inter_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ inter_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+keyboard_test@EXEEXT@: keyboard_test.@O@ ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ keyboard_test.@O@ \
+ ${ISCLIBS} ${LIBS}
+
+lwresconf_test@EXEEXT@: lwresconf_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwresconf_test.@O@ \
+ ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+
+lwres_test@EXEEXT@: lwres_test.@O@ ${ISCDEPLIBS} ${LWRESDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ lwres_test.@O@ \
+ ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+
+gxbn_test@EXEEXT@: gxbn_test.@O@ ${LWRESDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxbn_test.@O@ \
+ ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+
+gxba_test@EXEEXT@: gxba_test.@O@ ${LWRESDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ gxba_test.@O@ \
+ ${LWRESLIBS} ${ISCLIBS} ${LIBS}
+
+sig0_test@EXEEXT@: sig0_test.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ sig0_test.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+journalprint@EXEEXT@: journalprint.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ journalprint.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+cfg_test@EXEEXT@: cfg_test.@O@ ${ISCCFGDEPLIBS} ${ISCDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ cfg_test.@O@ \
+ ${ISCCFGLIBS} ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+nsec3hash@EXEEXT@: nsec3hash.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ nsec3hash.@O@ \
+ ${DNSLIBS} ${ISCLIBS} ${LIBS}
+
+distclean::
+ rm -f headerdep_test.sh
+
+clean distclean::
+ rm -f ${TARGETS} ${XTARGETS}
+ rm -f t_journal
+
+check: test
+
+test:
+ @for dir in $(SUBDIRS) ;\
+ do \
+ ( cd $$dir; $(MAKE) test ) ;\
+ done
diff --git a/bin/tests/adb_test.c b/bin/tests/adb_test.c
new file mode 100644
index 0000000..2ef812d
--- /dev/null
+++ b/bin/tests/adb_test.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: adb_test.c,v 1.68 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/cache.h>
+#include <dns/dispatch.h>
+#include <dns/db.h>
+#include <dns/log.h>
+#include <dns/rootns.h>
+#include <dns/result.h>
+
+typedef struct client client_t;
+struct client {
+ dns_name_t name;
+ const char *target;
+ ISC_LINK(client_t) link;
+ dns_adbfind_t *find;
+};
+
+static isc_mem_t *mctx = NULL;
+static isc_entropy_t *ectx = NULL;
+static isc_mempool_t *cmp;
+static isc_log_t *lctx;
+static isc_logconfig_t *lcfg;
+static isc_taskmgr_t *taskmgr;
+static isc_socketmgr_t *socketmgr;
+static isc_timermgr_t *timermgr;
+static dns_dispatchmgr_t *dispatchmgr;
+static isc_task_t *t1, *t2;
+static dns_view_t *view;
+static dns_db_t *rootdb;
+static ISC_LIST(client_t) clients;
+static isc_mutex_t client_lock;
+static isc_stdtime_t now;
+static dns_adb_t *adb;
+
+static void
+check_result(isc_result_t result, const char *format, ...)
+ ISC_FORMAT_PRINTF(2, 3);
+
+static void
+check_result(isc_result_t result, const char *format, ...) {
+ va_list args;
+
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, ": %s\n", isc_result_totext(result));
+ exit(1);
+}
+
+static client_t *
+new_client(void) {
+ client_t *client;
+
+ client = isc_mempool_get(cmp);
+ INSIST(client != NULL);
+ dns_name_init(&client->name, NULL);
+ ISC_LINK_INIT(client, link);
+ client->find = NULL;
+
+ return (client);
+}
+
+static void
+free_client(client_t **c) {
+ client_t *client;
+
+ INSIST(c != NULL);
+ client = *c;
+ *c = NULL;
+ INSIST(client != NULL);
+ dns_name_free(&client->name, mctx);
+ INSIST(!ISC_LINK_LINKED(client, link));
+ INSIST(client->find == NULL);
+
+ isc_mempool_put(cmp, client);
+}
+
+static inline void
+CLOCK(void) {
+ RUNTIME_CHECK(isc_mutex_lock(&client_lock) == ISC_R_SUCCESS);
+}
+
+static inline void
+CUNLOCK(void) {
+ RUNTIME_CHECK(isc_mutex_unlock(&client_lock) == ISC_R_SUCCESS);
+}
+
+static void
+lookup_callback(isc_task_t *task, isc_event_t *ev) {
+ client_t *client;
+
+ client = ev->ev_arg;
+ INSIST(client->find == ev->ev_sender);
+
+ printf("NAME %s:\n\tTask %p got event %p type %08x from %p, client %p\n\terr4: %s err6: %s\n",
+ client->target,
+ task, ev, ev->ev_type, client->find, client,
+ isc_result_totext(client->find->result_v4),
+ isc_result_totext(client->find->result_v6));
+
+ isc_event_free(&ev);
+ ev = NULL;
+
+ CLOCK();
+
+ dns_adb_dumpfind(client->find, stderr);
+ dns_adb_destroyfind(&client->find);
+
+ ISC_LIST_UNLINK(clients, client, link);
+ free_client(&client);
+
+ CUNLOCK();
+}
+
+static void
+create_managers(void) {
+ isc_result_t result;
+
+ taskmgr = NULL;
+ result = isc_taskmgr_create(mctx, 5, 0, &taskmgr);
+ check_result(result, "isc_taskmgr_create");
+
+ timermgr = NULL;
+ result = isc_timermgr_create(mctx, &timermgr);
+ check_result(result, "isc_timermgr_create");
+
+ socketmgr = NULL;
+ result = isc_socketmgr_create(mctx, &socketmgr);
+ check_result(result, "isc_socketmgr_create");
+
+ dispatchmgr = NULL;
+ result = dns_dispatchmgr_create(mctx, NULL, &dispatchmgr);
+ check_result(result, "dns_dispatchmgr_create");
+}
+
+static void
+create_view(void) {
+ dns_cache_t *cache;
+ isc_result_t result;
+
+ /*
+ * View.
+ */
+ view = NULL;
+ result = dns_view_create(mctx, dns_rdataclass_in, "_default", &view);
+ check_result(result, "dns_view_create");
+
+ /*
+ * Cache.
+ */
+ cache = NULL;
+ result = dns_cache_create(mctx, taskmgr, timermgr, dns_rdataclass_in,
+ "rbt", 0, NULL, &cache);
+ check_result(result, "dns_cache_create");
+ dns_view_setcache(view, cache);
+ dns_cache_detach(&cache);
+
+ {
+ unsigned int attrs;
+ isc_sockaddr_t any4, any6;
+ dns_dispatch_t *disp4 = NULL;
+ dns_dispatch_t *disp6 = NULL;
+
+ isc_sockaddr_any(&any4);
+ isc_sockaddr_any6(&any6);
+
+ attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr,
+ taskmgr, &any4, 512, 6, 1024,
+ 17, 19, attrs, attrs, &disp4)
+ == ISC_R_SUCCESS);
+ INSIST(disp4 != NULL);
+
+ attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr, socketmgr,
+ taskmgr, &any6, 512, 6, 1024,
+ 17, 19, attrs, attrs, &disp6)
+ == ISC_R_SUCCESS);
+ INSIST(disp6 != NULL);
+
+ RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10,
+ socketmgr,
+ timermgr, 0,
+ dispatchmgr,
+ disp4, disp6) ==
+ ISC_R_SUCCESS);
+ }
+
+ rootdb = NULL;
+ result = dns_rootns_create(mctx, dns_rdataclass_in, NULL, &rootdb);
+ check_result(result, "dns_rootns_create()");
+ dns_view_sethints(view, rootdb);
+ dns_db_detach(&rootdb);
+
+ dns_view_freeze(view);
+}
+
+static void
+lookup(const char *target) {
+ dns_name_t name;
+ unsigned char namedata[256];
+ client_t *client;
+ isc_buffer_t t, namebuf;
+ isc_result_t result;
+ unsigned int options;
+
+ INSIST(target != NULL);
+
+ client = new_client();
+ isc_buffer_init(&t, target, strlen(target));
+ isc_buffer_add(&t, strlen(target));
+ isc_buffer_init(&namebuf, namedata, sizeof(namedata));
+ dns_name_init(&name, NULL);
+ result = dns_name_fromtext(&name, &t, dns_rootname, ISC_FALSE,
+ &namebuf);
+ check_result(result, "dns_name_fromtext %s", target);
+
+ result = dns_name_dup(&name, mctx, &client->name);
+ check_result(result, "dns_name_dup %s", target);
+
+ options = 0;
+ options |= DNS_ADBFIND_INET;
+ options |= DNS_ADBFIND_INET6;
+ options |= DNS_ADBFIND_WANTEVENT;
+ options |= DNS_ADBFIND_HINTOK;
+ options |= DNS_ADBFIND_GLUEOK;
+ result = dns_adb_createfind(adb, t2, lookup_callback, client,
+ &client->name, dns_rootname, 0, options,
+ now, NULL, view->dstport, &client->find);
+#if 0
+ check_result(result, "dns_adb_createfind()");
+#endif
+ dns_adb_dumpfind(client->find, stderr);
+
+ if ((client->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
+ client->target = target;
+ ISC_LIST_APPEND(clients, client, link);
+ } else {
+ printf("NAME %s: err4 %s, err6 %s\n",
+ target, isc_result_totext(client->find->result_v4),
+ isc_result_totext(client->find->result_v6));
+
+ dns_adb_destroyfind(&client->find);
+ free_client(&client);
+ }
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+ isc_logdestination_t destination;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ dns_result_register();
+ result = isc_app_start();
+ check_result(result, "isc_app_start()");
+
+ isc_stdtime_get(&now);
+
+ result = isc_mutex_init(&client_lock);
+ check_result(result, "isc_mutex_init(&client_lock)");
+ ISC_LIST_INIT(clients);
+
+ /*
+ * EVERYTHING needs a memory context.
+ */
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ cmp = NULL;
+ RUNTIME_CHECK(isc_mempool_create(mctx, sizeof(client_t), &cmp)
+ == ISC_R_SUCCESS);
+ isc_mempool_setname(cmp, "adb test clients");
+
+ result = isc_entropy_create(mctx, &ectx);
+ check_result(result, "isc_entropy_create()");
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ check_result(result, "isc_hash_create()");
+
+ result = isc_log_create(mctx, &lctx, &lcfg);
+ check_result(result, "isc_log_create()");
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ /*
+ * Create and install the default channel.
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(lcfg, "_default",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, ISC_LOG_PRINTTIME);
+ check_result(result, "isc_log_createchannel()");
+ result = isc_log_usechannel(lcfg, "_default", NULL, NULL);
+ check_result(result, "isc_log_usechannel()");
+
+ /*
+ * Set the initial debug level.
+ */
+ isc_log_setdebuglevel(lctx, 2);
+
+ create_managers();
+
+ t1 = NULL;
+ result = isc_task_create(taskmgr, 0, &t1);
+ check_result(result, "isc_task_create t1");
+ t2 = NULL;
+ result = isc_task_create(taskmgr, 0, &t2);
+ check_result(result, "isc_task_create t2");
+
+ printf("task 1 = %p\n", t1);
+ printf("task 2 = %p\n", t2);
+
+ create_view();
+
+ adb = view->adb;
+
+ /*
+ * Lock the entire client list here. This will cause all events
+ * for found names to block as well.
+ */
+ CLOCK();
+ lookup("f.root-servers.net."); /* Should be in hints */
+ lookup("www.iengines.com"); /* should fetch */
+ lookup("www.isc.org"); /* should fetch */
+ lookup("www.flame.org"); /* should fetch */
+ lookup("kechara.flame.org."); /* should fetch */
+ lookup("moghedien.flame.org."); /* should fetch */
+ lookup("mailrelay.flame.org."); /* should fetch */
+ lookup("ipv4v6.flame.org."); /* should fetch */
+ lookup("nonexistant.flame.org."); /* should fail to be found */
+ lookup("foobar.badns.flame.org."); /* should fail utterly (NS) */
+ lookup("i.root-servers.net."); /* Should be in hints */
+ lookup("www.firstcard.com.");
+ lookup("dns04.flame.org.");
+ CUNLOCK();
+
+ sleep(10);
+
+ dns_adb_dump(adb, stderr);
+
+ sleep(10);
+
+ CLOCK();
+ lookup("f.root-servers.net."); /* Should be in hints */
+ lookup("www.iengines.com"); /* should fetch */
+ lookup("www.isc.org"); /* should fetch */
+ lookup("www.flame.org"); /* should fetch */
+ lookup("kechara.flame.org."); /* should fetch */
+ lookup("moghedien.flame.org."); /* should fetch */
+ lookup("mailrelay.flame.org."); /* should fetch */
+ lookup("ipv4v6.flame.org."); /* should fetch */
+ lookup("nonexistant.flame.org."); /* should fail to be found */
+ lookup("foobar.badns.flame.org."); /* should fail utterly (NS) */
+ lookup("i.root-servers.net."); /* Should be in hints */
+ CUNLOCK();
+
+ sleep(20);
+
+ dns_adb_dump(adb, stderr);
+
+ isc_task_detach(&t1);
+ isc_task_detach(&t2);
+
+ isc_mem_stats(mctx, stdout);
+ dns_adb_dump(adb, stderr);
+
+ isc_app_run();
+
+ dns_adb_dump(adb, stderr);
+
+ dns_view_detach(&view);
+ adb = NULL;
+
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ fprintf(stderr, "Destroying task manager\n");
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_log_destroy(&lctx);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mempool_destroy(&cmp);
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/b8t.mk b/bin/tests/b8t.mk
new file mode 100644
index 0000000..55923dc
--- /dev/null
+++ b/bin/tests/b8t.mk
@@ -0,0 +1,63 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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: b8t.mk,v 1.11 2007/06/19 23:46:59 tbox Exp $
+
+#
+# bind 8 multi-host make
+# PLATFORM set in the environment by cron
+#
+
+MODULE = bind
+BASE = /build
+BDIR = $(BASE)/$(MODULE)
+RDIR = /proj/build-reports/bind8/hosts/$(PLATFORM)
+SDIR = $(HOME)/b8t/src
+CVSROOT = /proj/cvs/isc
+
+all: clobber populate config build
+
+clobber:
+ @echo "CLOBBBER `date`"
+ @if test ! -d $(BASE) ; then mkdir -p $(BASE) ; fi
+ @rm -fr $(BDIR)
+ @echo "DONE `date`"
+
+populate:
+ @echo "POPULATE `date`"
+ @( cd $(BASE) && tar -xvf $(SDIR)/$(MODULE).tar ) > $(RDIR)/.populate 2>&1
+ @echo "DONE `date`"
+
+tarsrc:
+ @echo "TARSRC `date`"
+ @rm -fr $(SDIR)/$(MODULE)
+ @( cd $(SDIR) && cvs -d $(CVSROOT) checkout $(MODULE) )
+ @( cd $(SDIR) && tar -cvf $(MODULE).tar $(MODULE) )
+ @echo "DONE `date`"
+
+config:
+ @echo "CONFIG `date`"
+ @( cd $(BDIR)/src && make SRC=$(BDIR)/src DST=$(BDIR)/dst links ) > $(RDIR)/.config 2>&1
+ @echo "DONE `date`"
+
+build:
+ @echo "BUILD `date`"
+ @( cd $(BDIR)/dst && make -k clean depend all ) > $(RDIR)/.build 2>&1
+ @echo "DONE `date`"
+
+test:
+ @echo "TEST `date`"
+ @touch $(RDIR)/.test
+ @echo "DONE `date`"
diff --git a/bin/tests/b9t.mk b/bin/tests/b9t.mk
new file mode 100644
index 0000000..96f04fb
--- /dev/null
+++ b/bin/tests/b9t.mk
@@ -0,0 +1,68 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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: b9t.mk,v 1.13 2007/06/19 23:46:59 tbox Exp $
+
+#
+# makefile to configure, build and test bind9
+# this is run by cron (user wpk) on aa, sol, irix, hp and aix
+# $PLATFORM is set in the environment by cron
+#
+
+BASE = /build
+BDIR = $(BASE)
+MODULE = bind9
+SDIR = $(HOME)/b9t/src
+
+# as it says
+CVSROOT = /proj/cvs/isc
+
+# where the config, build and test output goes
+RDIR = /proj/build-reports/$(MODULE)/hosts/$(PLATFORM)
+
+all: clobber populate config build test
+
+clobber:
+ @echo "CLOBBBER `date`"
+ @if test ! -d $(BDIR) ; then mkdir -p $(BDIR) > /dev/null 2>&1 ; fi
+ @( cd $(BDIR) && rm -fr $(MODULE) )
+ @echo "DONE `date`"
+
+populate:
+ @echo "POPULATE `date`"
+ @( cd $(BDIR) && tar -xvf $(SDIR)/$(MODULE).tar ) > $(RDIR)/.populate 2>&1
+ @echo "DONE `date`"
+
+config:
+ @echo "CONFIG `date`"
+ @( cd $(BDIR)/$(MODULE) && ./configure ) > $(RDIR)/.config 2>&1
+ @echo "DONE `date`"
+
+build:
+ @echo "BUILD `date`"
+ @( cd $(BDIR)/$(MODULE) && $(MAKE) -k all ) > $(RDIR)/.build 2>&1
+ @echo "DONE `date`"
+
+test:
+ @echo "TEST `date`"
+ -@( cd $(BDIR)/$(MODULE)/bin/tests && $(MAKE) test ) > $(RDIR)/.test 2>&1
+ @echo "DONE `date`"
+
+tarsrc:
+ @echo "TARSRC `date`"
+ @rm -fr $(SDIR)/$(MODULE)
+ @( cd $(SDIR) && cvs -d $(CVSROOT) checkout $(MODULE) && tar -cvf $(MODULE).tar $(MODULE) )
+ @echo "DONE `date`"
+
diff --git a/bin/tests/byaddr_test.c b/bin/tests/byaddr_test.c
new file mode 100644
index 0000000..773b528
--- /dev/null
+++ b/bin/tests/byaddr_test.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: byaddr_test.c,v 1.28 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file
+ * \author
+ * Principal Author: Bob Halley
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/cache.h>
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/forward.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+static void
+done(isc_task_t *task, isc_event_t *event) {
+ dns_byaddrevent_t *bevent;
+ dns_byaddr_t *byaddr;
+ dns_name_t *name;
+
+ REQUIRE(event->ev_type == DNS_EVENT_BYADDRDONE);
+ bevent = (dns_byaddrevent_t *)event;
+
+ UNUSED(task);
+
+ printf("byaddr event result = %s\n",
+ isc_result_totext(bevent->result));
+
+ if (bevent->result == ISC_R_SUCCESS) {
+ for (name = ISC_LIST_HEAD(bevent->names);
+ name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ char text[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, text, sizeof(text));
+ printf("%s\n", text);
+ }
+ }
+
+ byaddr = event->ev_sender;
+ dns_byaddr_destroy(&byaddr);
+ isc_event_free(&event);
+
+ isc_app_shutdown();
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_mem_t *mctx;
+ isc_boolean_t verbose = ISC_FALSE;
+ unsigned int workers = 2;
+ isc_taskmgr_t *taskmgr;
+ isc_task_t *task;
+ isc_timermgr_t *timermgr;
+ dns_view_t *view;
+ int ch;
+ isc_socketmgr_t *socketmgr;
+ dns_dispatchmgr_t *dispatchmgr;
+ isc_netaddr_t na;
+ dns_byaddr_t *byaddr;
+ isc_result_t result;
+ unsigned int options = 0;
+ dns_cache_t *cache;
+
+ RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ while ((ch = isc_commandline_parse(argc, argv, "nvw:")) != -1) {
+ switch (ch) {
+ case 'n':
+ /*
+ * We only try nibbles, so do nothing for this option.
+ */
+ break;
+ case 'v':
+ verbose = ISC_TRUE;
+ break;
+ case 'w':
+ workers = (unsigned int)atoi(isc_commandline_argument);
+ break;
+ }
+ }
+
+ if (verbose) {
+ printf("%u workers\n", workers);
+ printf("IPv4: %s\n", isc_result_totext(isc_net_probeipv4()));
+ printf("IPv6: %s\n", isc_result_totext(isc_net_probeipv6()));
+ }
+
+ taskmgr = NULL;
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &taskmgr)
+ == ISC_R_SUCCESS);
+ task = NULL;
+ RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task)
+ == ISC_R_SUCCESS);
+ isc_task_setname(task, "byaddr", NULL);
+
+ dispatchmgr = NULL;
+ RUNTIME_CHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr)
+ == ISC_R_SUCCESS);
+
+ timermgr = NULL;
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
+ socketmgr = NULL;
+ RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
+
+ cache = NULL;
+ RUNTIME_CHECK(dns_cache_create(mctx, taskmgr, timermgr,
+ dns_rdataclass_in, "rbt", 0, NULL,
+ &cache) == ISC_R_SUCCESS);
+
+ view = NULL;
+ RUNTIME_CHECK(dns_view_create(mctx, dns_rdataclass_in, "default",
+ &view) == ISC_R_SUCCESS);
+
+ {
+ unsigned int attrs;
+ dns_dispatch_t *disp4 = NULL;
+ dns_dispatch_t *disp6 = NULL;
+
+ if (isc_net_probeipv4() == ISC_R_SUCCESS) {
+ isc_sockaddr_t any4;
+
+ isc_sockaddr_any(&any4);
+
+ attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
+ socketmgr,
+ taskmgr, &any4,
+ 512, 6, 1024,
+ 17, 19, attrs,
+ attrs, &disp4)
+ == ISC_R_SUCCESS);
+ INSIST(disp4 != NULL);
+ }
+
+ if (isc_net_probeipv6() == ISC_R_SUCCESS) {
+ isc_sockaddr_t any6;
+
+ isc_sockaddr_any6(&any6);
+
+ attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
+ socketmgr,
+ taskmgr, &any6,
+ 512, 6, 1024,
+ 17, 19, attrs,
+ attrs, &disp6)
+ == ISC_R_SUCCESS);
+ INSIST(disp6 != NULL);
+ }
+
+ RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10,
+ socketmgr,
+ timermgr, 0,
+ dispatchmgr,
+ disp4, disp6) ==
+ ISC_R_SUCCESS);
+
+ if (disp4 != NULL)
+ dns_dispatch_detach(&disp4);
+ if (disp6 != NULL)
+ dns_dispatch_detach(&disp6);
+ }
+
+ {
+ struct in_addr ina;
+ isc_sockaddr_t sa;
+ isc_sockaddrlist_t sal;
+
+ ISC_LIST_INIT(sal);
+ ina.s_addr = inet_addr("127.0.0.1");
+ isc_sockaddr_fromin(&sa, &ina, 53);
+ ISC_LIST_APPEND(sal, &sa, link);
+
+ RUNTIME_CHECK(dns_fwdtable_add(view->fwdtable, dns_rootname,
+ &sal, dns_fwdpolicy_only)
+ == ISC_R_SUCCESS);
+ }
+
+ dns_view_setcache(view, cache);
+ dns_view_freeze(view);
+
+ dns_cache_detach(&cache);
+
+ printf("address = %s\n", argv[isc_commandline_index]);
+ na.family = AF_INET;
+ if (inet_pton(AF_INET, argv[isc_commandline_index],
+ (char *)&na.type.in) != 1) {
+ na.family = AF_INET6;
+ if (inet_pton(AF_INET6, argv[isc_commandline_index],
+ (char *)&na.type.in6) != 1) {
+ printf("unknown address format\n");
+ exit(1);
+ }
+ }
+
+ result = dns_byaddr_create(mctx, &na, view, options, task,
+ done, NULL, &byaddr);
+ if (result != ISC_R_SUCCESS) {
+ printf("dns_byaddr_create() returned %s\n",
+ isc_result_totext(result));
+ RUNTIME_CHECK(0);
+ }
+
+ (void)isc_app_run();
+
+ /*
+ * XXXRTH if we get a control-C before we get to isc_app_run(),
+ * we're in trouble (because we might try to destroy things before
+ * they've been created.
+ */
+
+ dns_view_detach(&view);
+
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+
+ dns_dispatchmgr_destroy(&dispatchmgr);
+
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ if (verbose)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/byname_test.c b/bin/tests/byname_test.c
new file mode 100644
index 0000000..fdf45a9
--- /dev/null
+++ b/bin/tests/byname_test.c
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: byname_test.c,v 1.31 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file
+ * \author
+ * Principal Author: Bob Halley
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/netaddr.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/cache.h>
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/forward.h>
+#include <dns/log.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+
+static isc_mem_t *mctx = NULL;
+static isc_entropy_t *ectx = NULL;
+static isc_taskmgr_t *taskmgr;
+static dns_view_t *view = NULL;
+static dns_adbfind_t *find = NULL;
+static isc_task_t *task = NULL;
+static dns_fixedname_t name;
+static dns_fixedname_t target;
+static isc_log_t *lctx;
+static isc_logconfig_t *lcfg;
+static unsigned int level = 0;
+
+static void adb_callback(isc_task_t *task, isc_event_t *event);
+
+static void
+log_init(void) {
+ isc_logdestination_t destination;
+ unsigned int flags;
+
+ /*
+ * Setup a logging context.
+ */
+ RUNTIME_CHECK(isc_log_create(mctx, &lctx, &lcfg) == ISC_R_SUCCESS);
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ /*
+ * Create and install the default channel.
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ flags = ISC_LOG_PRINTTIME;
+ RUNTIME_CHECK(isc_log_createchannel(lcfg, "_default",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, flags) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_log_usechannel(lcfg, "_default", NULL, NULL) ==
+ ISC_R_SUCCESS);
+ isc_log_setdebuglevel(lctx, level);
+}
+
+static void
+print_addresses(dns_adbfind_t *find) {
+ dns_adbaddrinfo_t *address;
+
+ for (address = ISC_LIST_HEAD(find->list);
+ address != NULL;
+ address = ISC_LIST_NEXT(address, publink)) {
+ isc_netaddr_t netaddr;
+ char text[ISC_NETADDR_FORMATSIZE];
+ isc_netaddr_fromsockaddr(&netaddr, &address->sockaddr);
+ isc_netaddr_format(&netaddr, text, sizeof(text));
+ printf("%s\n", text);
+ }
+}
+
+static void
+print_name(dns_name_t *name) {
+ char text[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(name, text, sizeof(text));
+ printf("%s\n", text);
+}
+
+static void
+do_find(isc_boolean_t want_event) {
+ isc_result_t result;
+ isc_boolean_t done = ISC_FALSE;
+ unsigned int options;
+
+ options = DNS_ADBFIND_INET | DNS_ADBFIND_INET6;
+ if (want_event)
+ options |= DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
+ dns_fixedname_init(&target);
+ result = dns_adb_createfind(view->adb, task, adb_callback, NULL,
+ dns_fixedname_name(&name),
+ dns_rootname, 0, options, 0,
+ dns_fixedname_name(&target), 0,
+ &find);
+ if (result == ISC_R_SUCCESS) {
+ if (!ISC_LIST_EMPTY(find->list)) {
+ /*
+ * We have at least some of the addresses for the
+ * name.
+ */
+ INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
+ print_addresses(find);
+ done = ISC_TRUE;
+ } else {
+ /*
+ * We don't know any of the addresses for this
+ * name.
+ */
+ if ((find->options & DNS_ADBFIND_WANTEVENT) == 0) {
+ /*
+ * And ADB isn't going to send us any events
+ * either. This query loses.
+ */
+ done = ISC_TRUE;
+ }
+ /*
+ * If the DNS_ADBFIND_WANTEVENT flag was set, we'll
+ * get an event when something happens.
+ */
+ }
+ } else if (result == DNS_R_ALIAS) {
+ print_name(dns_fixedname_name(&target));
+ done = ISC_TRUE;
+ } else {
+ printf("dns_adb_createfind() returned %s\n",
+ isc_result_totext(result));
+ done = ISC_TRUE;
+ }
+
+ if (done) {
+ if (find != NULL)
+ dns_adb_destroyfind(&find);
+ isc_app_shutdown();
+ }
+}
+
+static void
+adb_callback(isc_task_t *etask, isc_event_t *event) {
+ unsigned int type = event->ev_type;
+
+ REQUIRE(etask == task);
+
+ isc_event_free(&event);
+ dns_adb_destroyfind(&find);
+
+ if (type == DNS_EVENT_ADBMOREADDRESSES)
+ do_find(ISC_FALSE);
+ else if (type == DNS_EVENT_ADBNOMOREADDRESSES) {
+ printf("no more addresses\n");
+ isc_app_shutdown();
+ } else {
+ printf("unexpected ADB event type %u\n", type);
+ isc_app_shutdown();
+ }
+}
+
+static void
+run(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+ do_find(ISC_TRUE);
+ isc_event_free(&event);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_boolean_t verbose = ISC_FALSE;
+ unsigned int workers = 2;
+ isc_timermgr_t *timermgr;
+ int ch;
+ isc_socketmgr_t *socketmgr;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_cache_t *cache;
+ isc_buffer_t b;
+
+ RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
+
+ dns_result_register();
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
+ == ISC_R_SUCCESS);
+
+ while ((ch = isc_commandline_parse(argc, argv, "d:vw:")) != -1) {
+ switch (ch) {
+ case 'd':
+ level = (unsigned int)atoi(isc_commandline_argument);
+ break;
+ case 'v':
+ verbose = ISC_TRUE;
+ break;
+ case 'w':
+ workers = (unsigned int)atoi(isc_commandline_argument);
+ break;
+ }
+ }
+
+ log_init();
+
+ if (verbose) {
+ printf("%u workers\n", workers);
+ printf("IPv4: %s\n", isc_result_totext(isc_net_probeipv4()));
+ printf("IPv6: %s\n", isc_result_totext(isc_net_probeipv6()));
+ }
+
+ taskmgr = NULL;
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &taskmgr) ==
+ ISC_R_SUCCESS);
+ task = NULL;
+ RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task) ==
+ ISC_R_SUCCESS);
+ isc_task_setname(task, "byname", NULL);
+
+ dispatchmgr = NULL;
+ RUNTIME_CHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr)
+ == ISC_R_SUCCESS);
+
+ timermgr = NULL;
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
+ socketmgr = NULL;
+ RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
+
+ cache = NULL;
+ RUNTIME_CHECK(dns_cache_create(mctx, taskmgr, timermgr,
+ dns_rdataclass_in, "rbt", 0, NULL,
+ &cache) == ISC_R_SUCCESS);
+
+ view = NULL;
+ RUNTIME_CHECK(dns_view_create(mctx, dns_rdataclass_in, "default",
+ &view) == ISC_R_SUCCESS);
+
+ {
+ unsigned int attrs;
+ dns_dispatch_t *disp4 = NULL;
+ dns_dispatch_t *disp6 = NULL;
+
+ if (isc_net_probeipv4() == ISC_R_SUCCESS) {
+ isc_sockaddr_t any4;
+ isc_sockaddr_any(&any4);
+
+ attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
+ socketmgr,
+ taskmgr, &any4,
+ 512, 6, 1024,
+ 17, 19, attrs,
+ attrs, &disp4)
+ == ISC_R_SUCCESS);
+ INSIST(disp4 != NULL);
+ }
+
+ if (isc_net_probeipv6() == ISC_R_SUCCESS) {
+ isc_sockaddr_t any6;
+
+ isc_sockaddr_any6(&any6);
+
+ attrs = DNS_DISPATCHATTR_IPV6 | DNS_DISPATCHATTR_UDP;
+ RUNTIME_CHECK(dns_dispatch_getudp(dispatchmgr,
+ socketmgr,
+ taskmgr, &any6,
+ 512, 6, 1024,
+ 17, 19, attrs,
+ attrs, &disp6)
+ == ISC_R_SUCCESS);
+ INSIST(disp6 != NULL);
+ }
+
+ RUNTIME_CHECK(dns_view_createresolver(view, taskmgr, 10,
+ socketmgr,
+ timermgr, 0,
+ dispatchmgr,
+ disp4, disp6) ==
+ ISC_R_SUCCESS);
+
+ if (disp4 != NULL)
+ dns_dispatch_detach(&disp4);
+ if (disp6 != NULL)
+ dns_dispatch_detach(&disp6);
+ }
+
+ {
+ struct in_addr ina;
+ isc_sockaddr_t sa;
+ isc_sockaddrlist_t sal;
+
+ ISC_LIST_INIT(sal);
+ ina.s_addr = inet_addr("127.0.0.1");
+ isc_sockaddr_fromin(&sa, &ina, 53);
+ ISC_LIST_APPEND(sal, &sa, link);
+
+ RUNTIME_CHECK(dns_fwdtable_add(view->fwdtable, dns_rootname,
+ &sal, dns_fwdpolicy_only)
+ == ISC_R_SUCCESS);
+ }
+
+ dns_view_setcache(view, cache);
+ dns_view_freeze(view);
+
+ dns_cache_detach(&cache);
+
+ printf("name = %s\n", argv[isc_commandline_index]);
+ isc_buffer_init(&b, argv[isc_commandline_index],
+ strlen(argv[isc_commandline_index]));
+ isc_buffer_add(&b, strlen(argv[isc_commandline_index]));
+ dns_fixedname_init(&name);
+ dns_fixedname_init(&target);
+ RUNTIME_CHECK(dns_name_fromtext(dns_fixedname_name(&name), &b,
+ dns_rootname, ISC_FALSE, NULL) ==
+ ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_app_onrun(mctx, task, run, NULL) == ISC_R_SUCCESS);
+
+ (void)isc_app_run();
+
+ dns_view_detach(&view);
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+
+ dns_dispatchmgr_destroy(&dispatchmgr);
+
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ isc_log_destroy(&lctx);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ if (verbose)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/cfg_test.c b/bin/tests/cfg_test.c
new file mode 100644
index 0000000..77c9712
--- /dev/null
+++ b/bin/tests/cfg_test.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002 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: cfg_test.c,v 1.19 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <isccfg/namedconf.h>
+
+#include <dns/log.h>
+
+static void
+check_result(isc_result_t result, const char *format, ...) {
+ va_list args;
+
+ if (result == ISC_R_SUCCESS)
+ return;
+
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, ": %s\n", isc_result_totext(result));
+ exit(1);
+}
+
+static void
+output(void *closure, const char *text, int textlen) {
+ UNUSED(closure);
+ (void) fwrite(text, 1, textlen, stdout);
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "usage: cfg_test --rndc|--named "
+ "[--grammar] [--memstats] conffile\n");
+ exit(1);
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+ isc_mem_t *mctx = NULL;
+ isc_log_t *lctx = NULL;
+ isc_logconfig_t *lcfg = NULL;
+ isc_logdestination_t destination;
+ cfg_parser_t *pctx = NULL;
+ cfg_obj_t *cfg = NULL;
+ cfg_type_t *type = NULL;
+ isc_boolean_t grammar = ISC_FALSE;
+ isc_boolean_t memstats = ISC_FALSE;
+ char *filename = NULL;
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ result = isc_log_create(mctx, &lctx, &lcfg);
+ check_result(result, "isc_log_create()");
+ isc_log_setcontext(lctx);
+
+ /*
+ * Create and install the default channel.
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(lcfg, "_default",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, ISC_LOG_PRINTTIME);
+ check_result(result, "isc_log_createchannel()");
+ result = isc_log_usechannel(lcfg, "_default", NULL, NULL);
+ check_result(result, "isc_log_usechannel()");
+
+ /*
+ * Set the initial debug level.
+ */
+ isc_log_setdebuglevel(lctx, 2);
+
+ if (argc < 3)
+ usage();
+
+ while (argc > 1) {
+ if (strcmp(argv[1], "--grammar") == 0) {
+ grammar = ISC_TRUE;
+ } else if (strcmp(argv[1], "--memstats") == 0) {
+ memstats = ISC_TRUE;
+ } else if (strcmp(argv[1], "--named") == 0) {
+ type = &cfg_type_namedconf;
+ } else if (strcmp(argv[1], "--rndc") == 0) {
+ type = &cfg_type_rndcconf;
+ } else if (argv[1][0] == '-') {
+ usage();
+ } else {
+ filename = argv[1];
+ }
+ argv++, argc--;
+ }
+
+ if (grammar) {
+ if (type == NULL)
+ usage();
+ cfg_print_grammar(type, output, NULL);
+ } else {
+ if (type == NULL || filename == NULL)
+ usage();
+ RUNTIME_CHECK(cfg_parser_create(mctx, lctx, &pctx) == ISC_R_SUCCESS);
+
+ result = cfg_parse_file(pctx, filename, type, &cfg);
+
+ fprintf(stderr, "read config: %s\n", isc_result_totext(result));
+
+ if (result != ISC_R_SUCCESS)
+ exit(1);
+
+ cfg_print(cfg, output, NULL);
+
+ cfg_obj_destroy(pctx, &cfg);
+
+ cfg_parser_destroy(&pctx);
+ }
+
+ isc_log_destroy(&lctx);
+ if (memstats)
+ isc_mem_stats(mctx, stderr);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/compress_test.c b/bin/tests/compress_test.c
new file mode 100644
index 0000000..8284dc1
--- /dev/null
+++ b/bin/tests/compress_test.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: compress_test.c,v 1.34 2007/06/18 23:47:26 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/compress.h>
+#include <dns/name.h>
+
+unsigned char plain1[] = "\003yyy\003foo";
+unsigned char plain2[] = "\003bar\003yyy\003foo";
+unsigned char plain3[] = "\003xxx\003bar\003foo";
+unsigned char plain[] = "\003yyy\003foo\0\003bar\003yyy\003foo\0\003"
+ "bar\003yyy\003foo\0\003xxx\003bar\003foo";
+
+/*
+ * Result concatenate (plain1, plain2, plain2, plain3).
+ */
+int raw = 0;
+int verbose = 0;
+
+void
+test(unsigned int, dns_name_t *, dns_name_t *, dns_name_t *,
+ unsigned char *, unsigned int);
+
+int
+main(int argc, char *argv[]) {
+ dns_name_t name1;
+ dns_name_t name2;
+ dns_name_t name3;
+ isc_region_t region;
+ int c;
+
+ while ((c = isc_commandline_parse(argc, argv, "rv")) != -1) {
+ switch (c) {
+ case 'r':
+ raw++;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ }
+ }
+
+ dns_name_init(&name1, NULL);
+ region.base = plain1;
+ region.length = sizeof(plain1);
+ dns_name_fromregion(&name1, &region);
+
+ dns_name_init(&name2, NULL);
+ region.base = plain2;
+ region.length = sizeof(plain2);
+ dns_name_fromregion(&name2, &region);
+
+ dns_name_init(&name3, NULL);
+ region.base = plain3;
+ region.length = sizeof(plain3);
+ dns_name_fromregion(&name3, &region);
+
+ test(DNS_COMPRESS_NONE, &name1, &name2, &name3, plain, sizeof(plain));
+ test(DNS_COMPRESS_GLOBAL14, &name1, &name2, &name3, plain,
+ sizeof(plain));
+ test(DNS_COMPRESS_ALL, &name1, &name2, &name3, plain, sizeof(plain));
+
+ return (0);
+}
+
+void
+test(unsigned int allowed, dns_name_t *name1, dns_name_t *name2,
+ dns_name_t *name3, unsigned char *result, unsigned int length)
+{
+ isc_mem_t *mctx = NULL;
+ dns_compress_t cctx;
+ dns_decompress_t dctx;
+ isc_buffer_t source;
+ isc_buffer_t target;
+ dns_name_t name;
+ unsigned char buf1[1024];
+ unsigned char buf2[1024];
+
+ if (verbose) {
+ const char *s;
+ switch (allowed) {
+ case DNS_COMPRESS_NONE: s = "DNS_COMPRESS_NONE"; break;
+ case DNS_COMPRESS_GLOBAL14: s = "DNS_COMPRESS_GLOBAL14"; break;
+ /* case DNS_COMPRESS_ALL: s = "DNS_COMPRESS_ALL"; break; */
+ default: s = "UNKNOWN"; break;
+ }
+ fprintf(stdout, "Allowed = %s\n", s);
+ }
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ isc_buffer_init(&source, buf1, sizeof(buf1));
+ RUNTIME_CHECK(dns_compress_init(&cctx, -1, mctx) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(dns_name_towire(name1, &cctx, &source) == ISC_R_SUCCESS);
+
+ /*
+ RUNTIME_CHECK(dns_compress_localinit(&cctx, name1, &source) ==
+ ISC_R_SUCCESS);
+ */
+ dns_compress_setmethods(&cctx, allowed);
+ RUNTIME_CHECK(dns_name_towire(name2, &cctx, &source) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_name_towire(name2, &cctx, &source) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_name_towire(name3, &cctx, &source) == ISC_R_SUCCESS);
+
+ /*
+ dns_compress_localinvalidate(&cctx);
+ */
+ dns_compress_rollback(&cctx, 0); /* testing only */
+ dns_compress_invalidate(&cctx);
+
+ if (raw) {
+ unsigned int i;
+ for (i = 0; i < source.used; /* */ ) {
+ fprintf(stdout, "%02x",
+ ((unsigned char *)source.base)[i]);
+ if ((++i % 20) == 0)
+ fputs("\n", stdout);
+ else
+ if (i == source.used)
+ fputs("\n", stdout);
+ else
+ fputs(" ", stdout);
+ }
+ }
+
+ isc_buffer_setactive(&source, source.used);
+ isc_buffer_init(&target, buf2, sizeof(buf2));
+ dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT);
+
+ dns_name_init(&name, NULL);
+ RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
+ &target) == ISC_R_SUCCESS);
+ dns_decompress_setmethods(&dctx, allowed);
+ /*
+ dns_decompress_localinit(&dctx, &name, &source);
+ */
+ RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
+ &target) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
+ &target) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
+ &target) == ISC_R_SUCCESS);
+ /*
+ dns_decompress_localinvalidate(&dctx);
+ */
+ dns_decompress_invalidate(&dctx);
+
+ if (raw) {
+ unsigned int i;
+ for (i = 0; i < target.used; /* */ ) {
+ fprintf(stdout, "%02x",
+ ((unsigned char *)target.base)[i]);
+ if ((++i % 20) == 0)
+ fputs("\n", stdout);
+ else
+ if (i == target.used)
+ fputs("\n", stdout);
+ else
+ fputs(" ", stdout);
+ }
+ fputs("\n", stdout);
+ fflush(stdout);
+ }
+
+ RUNTIME_CHECK(target.used == length);
+ RUNTIME_CHECK(memcmp(target.base, result, target.used) == 0);
+ isc_mem_destroy(&mctx);
+}
diff --git a/bin/tests/db/Makefile.in b/bin/tests/db/Makefile.in
new file mode 100644
index 0000000..13ebad2
--- /dev/null
+++ b/bin/tests/db/Makefile.in
@@ -0,0 +1,57 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-2002 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.29 2007/06/19 23:46:59 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../../lib/isc/libisc.@A@
+
+DNSDEPLIBS = ../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+TLIB = ../../../lib/tests/libt_api.@A@
+
+SRCS = t_db.c
+
+TARGETS = t_db@EXEEXT@
+
+@BIND9_MAKE_RULES@
+
+t_db@EXEEXT@: t_db.@O@ ${DEPLIBS} ${TLIB}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_db.@O@ ${TLIB} ${LIBS}
+
+test: t_db@EXEEXT@
+ -@./t_db@EXEEXT@ -c @top_srcdir@/t_config -b @srcdir@ -a
+
+testhelp:
+ @./t_db -h
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/db/dns_db_class_1.data b/bin/tests/db/dns_db_class_1.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_class_1.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_class_data b/bin/tests/db/dns_db_class_data
new file mode 100644
index 0000000..55a0cf8
--- /dev/null
+++ b/bin/tests/db/dns_db_class_data
@@ -0,0 +1,9 @@
+#
+# test data for dns_db_class
+#
+# format:
+# filename class
+#
+#
+dns_db_class_1.data in
+# dns_db_class_1.data any
diff --git a/bin/tests/db/dns_db_closeversion_1.data b/bin/tests/db/dns_db_closeversion_1.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_closeversion_1.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_closeversion_1_data b/bin/tests/db/dns_db_closeversion_1_data
new file mode 100644
index 0000000..7bfd5b0
--- /dev/null
+++ b/bin/tests/db/dns_db_closeversion_1_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_closeversion test 1
+#
+# format:
+# filename type origin class cache new_name new_type existing_name existing_type
+#
+dns_db_closeversion_1.data rbt vix.com. in zone a.b.c.vix.com. A a.vix.com. NS
diff --git a/bin/tests/db/dns_db_closeversion_2.data b/bin/tests/db/dns_db_closeversion_2.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_closeversion_2.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_closeversion_2_data b/bin/tests/db/dns_db_closeversion_2_data
new file mode 100644
index 0000000..e5bcf4d
--- /dev/null
+++ b/bin/tests/db/dns_db_closeversion_2_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_closeversion test 2
+#
+# format:
+# filename type origin class cache new_name new_type existing_name existing_type
+#
+dns_db_closeversion_1.data rbt vix.com. in zone a.b.c.vix.com. A a.vix.com. NS
diff --git a/bin/tests/db/dns_db_currentversion.data b/bin/tests/db/dns_db_currentversion.data
new file mode 100644
index 0000000..b7cb868
--- /dev/null
+++ b/bin/tests/db/dns_db_currentversion.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a.b.c.vix.com. a 1.2.3.4
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_currentversion_data b/bin/tests/db/dns_db_currentversion_data
new file mode 100644
index 0000000..e4a095e
--- /dev/null
+++ b/bin/tests/db/dns_db_currentversion_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_currentversion
+#
+# format:
+# filename findname findtype
+#
+dns_db_currentversion.data rbt vix.com. IN zone a.b.c.vix.com. A
diff --git a/bin/tests/db/dns_db_expirenode.data b/bin/tests/db/dns_db_expirenode.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_expirenode.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_expirenode_data b/bin/tests/db/dns_db_expirenode_data
new file mode 100644
index 0000000..f51858a
--- /dev/null
+++ b/bin/tests/db/dns_db_expirenode_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_expirenode
+#
+# format:
+# filename type origin class existing_name existing_type
+#
+dns_db_expirenode.data rbt vix.com. in a.vix.com. 10000 0 ISC_R_NOTFOUND
diff --git a/bin/tests/db/dns_db_find_1.data b/bin/tests/db/dns_db_find_1.data
new file mode 100644
index 0000000..8cfc69c
--- /dev/null
+++ b/bin/tests/db/dns_db_find_1.data
@@ -0,0 +1,12 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
+a.b.c in ns b
diff --git a/bin/tests/db/dns_db_find_10.data b/bin/tests/db/dns_db_find_10.data
new file mode 100644
index 0000000..ca1fc5e
--- /dev/null
+++ b/bin/tests/db/dns_db_find_10.data
@@ -0,0 +1,10 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+
+a.b.c in NS ns1.vix.com.
+a.b.c in A 1.2.3.4
diff --git a/bin/tests/db/dns_db_find_10_data b/bin/tests/db/dns_db_find_10_data
new file mode 100644
index 0000000..d1ab1d3
--- /dev/null
+++ b/bin/tests/db/dns_db_find_10_data
@@ -0,0 +1,8 @@
+#
+# test data for dns_db_find expiration time handling
+#
+# format:
+# dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results
+#
+dns_db_find_10.data rbt vix.com. in cache a.b.c.vix.com. NS 0 1010 ISC_R_NOTFOUND
+dns_db_find_10.data rbt vix.com. in cache a.b.c.vix.com. NS 0 0 ISC_R_SUCCESS
diff --git a/bin/tests/db/dns_db_find_1_data b/bin/tests/db/dns_db_find_1_data
new file mode 100644
index 0000000..e1664cf
--- /dev/null
+++ b/bin/tests/db/dns_db_find_1_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_find best match
+#
+# format:
+# dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results
+#
+dns_db_find_1.data rbt vix.com. in zone a.b.c.vix.com. NS DNS_DB_GLUEOK 0 DNS_R_DELEGATION
diff --git a/bin/tests/db/dns_db_find_2.data b/bin/tests/db/dns_db_find_2.data
new file mode 100644
index 0000000..ab4b435
--- /dev/null
+++ b/bin/tests/db/dns_db_find_2.data
@@ -0,0 +1,9 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+fx in ns a.fx.vix.com.
+a.fx in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_find_2_data b/bin/tests/db/dns_db_find_2_data
new file mode 100644
index 0000000..0e3ffca
--- /dev/null
+++ b/bin/tests/db/dns_db_find_2_data
@@ -0,0 +1,9 @@
+#
+# test data for dns_db_find DNS_R_GLUE
+#
+# format:
+# dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results
+#
+dns_db_find_2.data rbt vix.com. in zone a.fx.vix.com. A DNS_DBFIND_GLUEOK 0 DNS_R_GLUE
+dns_db_find_2.data rbt vix.com. in zone fx.vix.com. NS DNS_DBFIND_GLUEOK 0 DNS_R_GLUE
+dns_db_find_2.data rbt vix.com. in zone a.fx.vix.com. NS DNS_DBFIND_GLUEOK 0 DNS_R_DELEGATION
diff --git a/bin/tests/db/dns_db_find_3.data b/bin/tests/db/dns_db_find_3.data
new file mode 100644
index 0000000..d126e91
--- /dev/null
+++ b/bin/tests/db/dns_db_find_3.data
@@ -0,0 +1,10 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a.b.c in ns b
+a.a.b.c in a 10.0.0.1
+b in a 10.0.0.2
diff --git a/bin/tests/db/dns_db_find_3_data b/bin/tests/db/dns_db_find_3_data
new file mode 100644
index 0000000..a8e1223
--- /dev/null
+++ b/bin/tests/db/dns_db_find_3_data
@@ -0,0 +1,9 @@
+#
+# test data for dns_db_find DNS_R_DELAGATION
+#
+# format:
+# dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results
+#
+dns_db_find_3.data rbt vix.com. in zone a.b.c.vix.com. NS DNS_DB_GLUEOK 0 DNS_R_DELEGATION
+dns_db_find_3.data rbt vix.com. in zone a.a.b.c.vix.com. NS DNS_DB_GLUEOK 0 DNS_R_DELEGATION
+dns_db_find_3.data rbt vix.com. in zone a.a.b.c.vix.com. A DNS_DB_GLUEOK 0 DNS_R_DELEGATION
diff --git a/bin/tests/db/dns_db_find_4.data b/bin/tests/db/dns_db_find_4.data
new file mode 100644
index 0000000..4c3b5e9
--- /dev/null
+++ b/bin/tests/db/dns_db_find_4.data
@@ -0,0 +1,9 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a.b.c in ns b
+b.a.b.c in a 10.0.0.2
diff --git a/bin/tests/db/dns_db_find_4_data b/bin/tests/db/dns_db_find_4_data
new file mode 100644
index 0000000..b0326a6
--- /dev/null
+++ b/bin/tests/db/dns_db_find_4_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_find DNS_R_DELEGATION
+#
+# format:
+# dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results
+#
+dns_db_find_4.data rbt vix.com. in zone a.b.c.vix.com. ANY 0 0 DNS_R_DELEGATION
diff --git a/bin/tests/db/dns_db_find_5.data b/bin/tests/db/dns_db_find_5.data
new file mode 100644
index 0000000..e33f631
--- /dev/null
+++ b/bin/tests/db/dns_db_find_5.data
@@ -0,0 +1,10 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a.b.c in DNAME x.y.z
+a.x.y.z in A 1.2.3.4
+
diff --git a/bin/tests/db/dns_db_find_5_data b/bin/tests/db/dns_db_find_5_data
new file mode 100644
index 0000000..dab47c8
--- /dev/null
+++ b/bin/tests/db/dns_db_find_5_data
@@ -0,0 +1,8 @@
+#
+# test data for dns_db_find DNS_R_DNAME
+#
+# format:
+# dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results
+#
+dns_db_find_5.data rbt vix.com. in zone x.a.b.c.vix.com. ANY 0 0 DNS_R_DNAME
+dns_db_find_5.data rbt vix.com. in zone a.a.b.c.vix.com. ANY 0 0 DNS_R_DNAME
diff --git a/bin/tests/db/dns_db_find_6.data b/bin/tests/db/dns_db_find_6.data
new file mode 100644
index 0000000..108f043
--- /dev/null
+++ b/bin/tests/db/dns_db_find_6.data
@@ -0,0 +1,10 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+exploder in CNAME mx
+mx in A 1.2.3.4
+
diff --git a/bin/tests/db/dns_db_find_6_data b/bin/tests/db/dns_db_find_6_data
new file mode 100644
index 0000000..47de0e6
--- /dev/null
+++ b/bin/tests/db/dns_db_find_6_data
@@ -0,0 +1,8 @@
+#
+# test data for dns_db_find DNS_R_CNAME
+#
+# format:
+# dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results
+#
+dns_db_find_6.data rbt vix.com. in zone exploder.vix.com. A 0 0 DNS_R_CNAME
+dns_db_find_6.data rbt vix.com. in zone exploder.vix.com. ANY 0 0 ISC_R_SUCCESS
diff --git a/bin/tests/db/dns_db_find_7.data b/bin/tests/db/dns_db_find_7.data
new file mode 100644
index 0000000..f0ec22b
--- /dev/null
+++ b/bin/tests/db/dns_db_find_7.data
@@ -0,0 +1,12 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+
+a.b.c.d in A 1.2.3.4
+a.b in A 1.2.3.4
+a in NS ns1.vix.com.
+
diff --git a/bin/tests/db/dns_db_find_7_data b/bin/tests/db/dns_db_find_7_data
new file mode 100644
index 0000000..6592758
--- /dev/null
+++ b/bin/tests/db/dns_db_find_7_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_find DNS_R_NXDOMAIN
+#
+# format:
+# dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results
+#
+dns_db_find_7.data rbt vix.com. in zone a.b.c.vix.com. ANY 0 0 DNS_R_NXDOMAIN
diff --git a/bin/tests/db/dns_db_find_8.data b/bin/tests/db/dns_db_find_8.data
new file mode 100644
index 0000000..66e61ff
--- /dev/null
+++ b/bin/tests/db/dns_db_find_8.data
@@ -0,0 +1,13 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+
+a.b.c.d in A 1.2.3.4
+a.b.c in A 1.2.3.4
+a.b in A 1.2.3.4
+a in NS ns1.vix.com.
+
diff --git a/bin/tests/db/dns_db_find_8_data b/bin/tests/db/dns_db_find_8_data
new file mode 100644
index 0000000..4ad0c83
--- /dev/null
+++ b/bin/tests/db/dns_db_find_8_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_find DNS_R_NXRRSET
+#
+# format:
+# dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results
+#
+dns_db_find_8.data rbt vix.com. in zone a.b.c.vix.com. NS 0 0 DNS_R_NXRRSET
diff --git a/bin/tests/db/dns_db_find_9.data b/bin/tests/db/dns_db_find_9.data
new file mode 100644
index 0000000..54a6d5f
--- /dev/null
+++ b/bin/tests/db/dns_db_find_9.data
@@ -0,0 +1,13 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+
+a.b.c.d in NS ns1.vix.com.
+a.b.c in A 1.2.3.4
+a.b in NS ns1.vix.com.
+a in NS ns1.vix.com.
+
diff --git a/bin/tests/db/dns_db_find_9_data b/bin/tests/db/dns_db_find_9_data
new file mode 100644
index 0000000..d80795c
--- /dev/null
+++ b/bin/tests/db/dns_db_find_9_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_find ISC_R_NOTFOUND
+#
+# format:
+# dbfile dbtype dborigin dbclass dbcache findname findtype findopts findtime expected_results
+#
+dns_db_find_9.data rbt vix.com. in cache a.b.c.vix.com. NS 0 0 ISC_R_NOTFOUND
diff --git a/bin/tests/db/dns_db_findnode_1.data b/bin/tests/db/dns_db_findnode_1.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_findnode_1.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_findnode_1_data b/bin/tests/db/dns_db_findnode_1_data
new file mode 100644
index 0000000..a73c425
--- /dev/null
+++ b/bin/tests/db/dns_db_findnode_1_data
@@ -0,0 +1,9 @@
+#
+# test data for dns_db_findnode, case ISC_R_SUCCESS
+#
+# format:
+# filename type origin class cache existingname rdatatype
+#
+dns_db_findnode_1.data rbt vix.com. in zone a.vix.com. NS ISC_R_SUCCESS
+dns_db_findnode_1.data rbt vix.com. in zone b.vix.com. A ISC_R_SUCCESS
+dns_db_findnode_1.data rbt vix.com. in zone c.vix.com. A ISC_R_NOTFOUND
diff --git a/bin/tests/db/dns_db_findnode_2.data b/bin/tests/db/dns_db_findnode_2.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_findnode_2.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_findnode_2_data b/bin/tests/db/dns_db_findnode_2_data
new file mode 100644
index 0000000..db69d20
--- /dev/null
+++ b/bin/tests/db/dns_db_findnode_2_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_findnode 2
+#
+# format:
+# filename type origin class cache newname
+#
+dns_db_findnode_2.data rbt vix.com. in zone a.b.c.vix.com.
diff --git a/bin/tests/db/dns_db_iscache_1.data b/bin/tests/db/dns_db_iscache_1.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_iscache_1.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_iscache_1_data b/bin/tests/db/dns_db_iscache_1_data
new file mode 100644
index 0000000..af591f9
--- /dev/null
+++ b/bin/tests/db/dns_db_iscache_1_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_iscache test 1
+#
+# format:
+# filename db_type origin class
+#
+dns_db_iscache_1.data rbt . in
diff --git a/bin/tests/db/dns_db_iscache_2.data b/bin/tests/db/dns_db_iscache_2.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_iscache_2.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_iscache_2_data b/bin/tests/db/dns_db_iscache_2_data
new file mode 100644
index 0000000..e859ef7
--- /dev/null
+++ b/bin/tests/db/dns_db_iscache_2_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_iscache test 1
+#
+# format:
+# filename db_type origin class
+#
+dns_db_iscache_2.data rbt . in
diff --git a/bin/tests/db/dns_db_iszone_1.data b/bin/tests/db/dns_db_iszone_1.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_iszone_1.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_iszone_1_data b/bin/tests/db/dns_db_iszone_1_data
new file mode 100644
index 0000000..02862d7
--- /dev/null
+++ b/bin/tests/db/dns_db_iszone_1_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_iszone test 1
+#
+# format:
+# filename db_type origin class
+#
+dns_db_iszone_1.data rbt . in
diff --git a/bin/tests/db/dns_db_iszone_2.data b/bin/tests/db/dns_db_iszone_2.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_iszone_2.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_iszone_2_data b/bin/tests/db/dns_db_iszone_2_data
new file mode 100644
index 0000000..02d3dc2
--- /dev/null
+++ b/bin/tests/db/dns_db_iszone_2_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_iszone test 2
+#
+# format:
+# filename db_type origin class
+#
+dns_db_iszone_2.data rbt . in
diff --git a/bin/tests/db/dns_db_load_1.data b/bin/tests/db/dns_db_load_1.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_load_1.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_load_25.data b/bin/tests/db/dns_db_load_25.data
new file mode 100644
index 0000000..6e21bda
--- /dev/null
+++ b/bin/tests/db/dns_db_load_25.data
@@ -0,0 +1,6 @@
+$TTL 5
+@ IN SOA ns1 hostmaster 1 3600 1200 3600000 3600
+@ IN NS ns1
+ns1 IN A 10.0.0.1
+sub IN SOA ns2 hostmaster 1 3600 1200 3600000 3600
+ns2 IN A 10.0.0.2
diff --git a/bin/tests/db/dns_db_load_data b/bin/tests/db/dns_db_load_data
new file mode 100644
index 0000000..0684c62
--- /dev/null
+++ b/bin/tests/db/dns_db_load_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_load
+#
+# format:
+# filename type origin cache class findname expected_result
+#
+dns_db_load_1.data rbt . zone in ISC_R_SUCCESS a. A DNS_R_DELEGATION
diff --git a/bin/tests/db/dns_db_load_soa_not_top b/bin/tests/db/dns_db_load_soa_not_top
new file mode 100644
index 0000000..fbb8dcc
--- /dev/null
+++ b/bin/tests/db/dns_db_load_soa_not_top
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_load_soa_not_top
+#
+# format:
+# filename type origin cache class findname expected_result
+#
+dns_db_load_25.data rbt . zone in DNS_R_NOTZONETOP a. A DNS_R_DELEGATION
diff --git a/bin/tests/db/dns_db_newversion.data b/bin/tests/db/dns_db_newversion.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_newversion.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_newversion_data b/bin/tests/db/dns_db_newversion_data
new file mode 100644
index 0000000..be0c042
--- /dev/null
+++ b/bin/tests/db/dns_db_newversion_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_db_newversion
+#
+# format:
+# filename type origin class cache newname newtype
+#
+dns_db_newversion.data rbt vix.com. in zone a.b.c.vix.com. A
diff --git a/bin/tests/db/dns_db_origin_1.data b/bin/tests/db/dns_db_origin_1.data
new file mode 100644
index 0000000..ab61c95
--- /dev/null
+++ b/bin/tests/db/dns_db_origin_1.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2.vix.com.
+a in ns ns3.vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/db/dns_db_origin_data b/bin/tests/db/dns_db_origin_data
new file mode 100644
index 0000000..9c3b458
--- /dev/null
+++ b/bin/tests/db/dns_db_origin_data
@@ -0,0 +1,8 @@
+#
+# test data for dns_db_origin
+#
+# format:
+# filename origin
+#
+dns_db_origin_1.data .
+dns_db_origin_1.data vix.com.
diff --git a/bin/tests/db/t_db.c b/bin/tests/db/t_db.c
new file mode 100644
index 0000000..727c49e
--- /dev/null
+++ b/bin/tests/db/t_db.c
@@ -0,0 +1,3146 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: t_db.c,v 1.36 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/fixedname.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+
+#include <tests/t_api.h>
+
+static isc_result_t
+t_create(const char *db_type, const char *origin, const char *class,
+ const char *model, isc_mem_t *mctx, dns_db_t **db)
+{
+ int len;
+ isc_result_t dns_result;
+ dns_dbtype_t dbtype;
+ isc_textregion_t region;
+ isc_buffer_t origin_buffer;
+ dns_fixedname_t dns_origin;
+ dns_rdataclass_t rdataclass;
+
+
+ dbtype = dns_dbtype_zone;
+ if (strcasecmp(model, "cache") == 0)
+ dbtype = dns_dbtype_cache;
+
+ dns_fixedname_init(&dns_origin);
+ len = strlen(origin);
+ isc_buffer_init(&origin_buffer, origin, len);
+ isc_buffer_add(&origin_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_origin),
+ &origin_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(dns_result);
+ }
+
+ DE_CONST(class, region.base);
+ region.length = strlen(class);
+ dns_result = dns_rdataclass_fromtext(&rdataclass, &region);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdataclass_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(dns_result);
+ }
+
+ dns_result = dns_db_create(mctx, db_type,
+ dns_fixedname_name(&dns_origin),
+ dbtype, rdataclass, 0, NULL, db);
+ if (dns_result != ISC_R_SUCCESS)
+ t_info("dns_db_create failed %s\n",
+ dns_result_totext(dns_result));
+
+ return(dns_result);
+
+}
+
+static int
+t_dns_db_load(char **av) {
+ char *filename;
+ char *db_type;
+ char *origin;
+ char *model;
+ char *class;
+ char *expected_load_result;
+ char *findname;
+ char *find_type;
+ char *expected_find_result;
+
+ int result;
+ int len;
+ dns_db_t *db;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_dbnode_t *nodep;
+ isc_textregion_t textregion;
+ isc_buffer_t findname_buffer;
+ dns_fixedname_t dns_findname;
+ dns_fixedname_t dns_foundname;
+ dns_rdataset_t rdataset;
+ dns_rdatatype_t rdatatype;
+ dns_dbversion_t *versionp;
+ isc_result_t exp_load_result;
+ isc_result_t exp_find_result;
+
+ result = T_UNRESOLVED;
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+ filename = T_ARG(0);
+ db_type = T_ARG(1);
+ origin = T_ARG(2);
+ model = T_ARG(3);
+ class = T_ARG(4);
+ expected_load_result = T_ARG(5);
+ findname = T_ARG(6);
+ find_type = T_ARG(7);
+ expected_find_result = T_ARG(8);
+
+ t_info("testing using file %s and name %s\n", filename, findname);
+
+ exp_load_result = t_dns_result_fromtext(expected_load_result);
+ exp_find_result = t_dns_result_fromtext(expected_find_result);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = t_create(db_type, origin, class, model, mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result != exp_load_result) {
+ t_info("dns_db_load returned %s, expected %s\n",
+ dns_result_totext(dns_result),
+ dns_result_totext(exp_load_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+ if (dns_result != ISC_R_SUCCESS) {
+ result = T_PASS;
+ goto cleanup_db;
+ }
+
+ dns_fixedname_init(&dns_findname);
+ len = strlen(findname);
+ isc_buffer_init(&findname_buffer, findname, len);
+ isc_buffer_add(&findname_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname),
+ &findname_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ textregion.base = find_type;
+ textregion.length = strlen(find_type);
+ dns_result = dns_rdatatype_fromtext(&rdatatype, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatatype_fromtext %s failed %s\n",
+ find_type,
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ versionp = NULL;
+ dns_fixedname_init(&dns_foundname);
+ dns_rdataset_init(&rdataset);
+ if (dns_db_iszone(db))
+ dns_db_currentversion(db, &versionp);
+ nodep = NULL;
+
+ dns_result = dns_db_find(db,
+ dns_fixedname_name(&dns_findname),
+ versionp,
+ rdatatype,
+ DNS_DBFIND_GLUEOK,
+ 0,
+ &nodep,
+ dns_fixedname_name(&dns_foundname),
+ &rdataset, NULL);
+
+ if (dns_result != exp_find_result) {
+ t_info("dns_db_find returned %s, expected %s\n",
+ dns_result_totext(dns_result),
+ dns_result_totext(exp_find_result));
+ result = T_FAIL;
+ } else {
+ result = T_PASS;
+ }
+
+ if (dns_result != ISC_R_NOTFOUND) {
+ dns_db_detachnode(db, &nodep);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ }
+
+ if (dns_db_iszone(db))
+ dns_db_closeversion(db, &versionp, ISC_FALSE);
+ cleanup_db:
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+}
+
+static const char *a1 =
+ "A call to dns_db_load(db, filename) loads the contents of "
+ "the database in filename into db.";
+
+static void
+t1(void) {
+ int result;
+
+ t_assert("dns_db_load", 1, T_REQUIRED, a1);
+ result = t_eval("dns_db_load_data", t_dns_db_load, 9);
+ t_result(result);
+}
+
+
+static const char *a2 =
+ "When the database db has cache semantics, a call to "
+ "dns_db_iscache(db) returns ISC_TRUE.";
+
+static int
+t_dns_db_zc_x(char *filename, char *db_type, char *origin, char *class,
+ dns_dbtype_t dbtype, isc_boolean_t(*cf)(dns_db_t *),
+ isc_boolean_t exp_result)
+{
+ int result;
+ int len;
+ dns_db_t *db;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_rdataclass_t rdataclass;
+ isc_textregion_t textregion;
+ isc_buffer_t origin_buffer;
+ dns_fixedname_t dns_origin;
+
+ result = T_UNRESOLVED;
+
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+
+ t_info("testing using file %s\n", filename);
+
+ dns_fixedname_init(&dns_origin);
+ len = strlen(origin);
+ isc_buffer_init(&origin_buffer, origin, len);
+ isc_buffer_add(&origin_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_origin),
+ &origin_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(T_UNRESOLVED);
+ }
+
+ textregion.base = class;
+ textregion.length = strlen(class);
+ dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdataclass_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_create(mctx, db_type,
+ dns_fixedname_name(&dns_origin),
+ dbtype, rdataclass, 0, NULL, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_create failed %s\n",
+ dns_result_totext(dns_result));
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result == ISC_R_SUCCESS) {
+ if ((*cf)(db) == exp_result)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+ } else {
+ t_info("dns_db_load failed %s\n",
+ dns_result_totext(dns_result));
+ result = T_FAIL;
+ }
+
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+}
+
+static int
+test_dns_db_zc_x(const char *filename, dns_dbtype_t dbtype,
+ isc_boolean_t(*cf)(dns_db_t *), isc_boolean_t exp_result)
+{
+
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+ char *tokens[T_MAXTOKS];
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, tokens);
+ if (cnt == 4) {
+ result = t_dns_db_zc_x(tokens[0], /* file */
+ tokens[1], /* type */
+ tokens[2], /* origin */
+ tokens[3], /* class */
+ dbtype, /* cache */
+ cf, /* check func */
+ exp_result);/* expect */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if (nfails == 0 && nprobs == 0)
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static void
+t2(void) {
+ int result;
+
+ t_assert("dns_db_iscache", 2, T_REQUIRED, a2);
+ result = test_dns_db_zc_x("dns_db_iscache_1_data",
+ dns_dbtype_cache, dns_db_iscache, ISC_TRUE);
+ t_result(result);
+}
+
+
+static const char *a3 =
+ "When the database db has zone semantics, a call to "
+ "dns_db_iscache(db) returns ISC_FALSE.";
+
+
+static void
+t3(void) {
+ int result;
+
+ t_assert("dns_db_iscache", 3, T_REQUIRED, a3);
+ result = test_dns_db_zc_x("dns_db_iscache_2_data",
+ dns_dbtype_zone, dns_db_iscache, ISC_FALSE);
+ t_result(result);
+}
+
+
+static const char *a4 =
+ "When the database db has zone semantics, a call to "
+ "dns_db_iszone(db) returns ISC_TRUE.";
+
+
+static void
+t4(void) {
+ int result;
+
+ t_assert("dns_db_iszone", 4, T_REQUIRED, a4);
+ result = test_dns_db_zc_x("dns_db_iszone_1_data",
+ dns_dbtype_zone, dns_db_iszone, ISC_TRUE);
+ t_result(result);
+}
+
+
+static const char *a5 =
+ "When the database db has cache semantics, a call to "
+ "dns_db_iszone(db) returns ISC_FALSE.";
+
+static void
+t5(void) {
+ int result;
+
+ t_assert("dns_db_iszone", 5, T_REQUIRED, a5);
+ result = test_dns_db_zc_x("dns_db_iszone_2_data",
+ dns_dbtype_cache, dns_db_iszone, ISC_FALSE);
+ t_result(result);
+}
+
+static int
+t_dns_db_origin(char **av) {
+
+ char *filename;
+ char *origin;
+
+ int result;
+ int len;
+ int order;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_db_t *db;
+ dns_fixedname_t dns_origin;
+ dns_fixedname_t dns_dborigin;
+ isc_buffer_t origin_buffer;
+
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+
+ filename = T_ARG(0);
+ origin = T_ARG(1);
+
+ t_info("testing with database %s and origin %s\n",
+ filename, origin);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = t_create("rbt", origin, "in", "isc_true", mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("t_create failed %s\n",
+ dns_result_totext(dns_result));
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+ dns_fixedname_init(&dns_origin);
+ dns_fixedname_init(&dns_dborigin);
+
+ len = strlen(origin);
+ isc_buffer_init(&origin_buffer, origin, len);
+ isc_buffer_add(&origin_buffer, len);
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_load failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_origin),
+ &origin_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+ order = dns_name_compare(dns_fixedname_name(&dns_origin),
+ dns_db_origin(db));
+ if (order == 0) {
+ result = T_PASS;
+ } else {
+ t_info("dns_name_compare returned %d\n", order);
+ result = T_FAIL;
+ }
+
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+
+}
+
+static const char *a6 =
+ "A call to dns_db_origin(db) returns the origin of the database.";
+
+static void
+t6(void) {
+ int result;
+
+ t_assert("dns_db_origin", 6, T_REQUIRED, a6);
+ result = t_eval("dns_db_origin_data", t_dns_db_origin, 2);
+ t_result(result);
+}
+
+
+static const char *a7 =
+ "A call to dns_db_class(db) returns the class of the database.";
+
+
+#define CLASSBUFLEN 256
+
+static int
+t_dns_db_class(char **av) {
+
+ char *filename;
+ char *class;
+
+ int result;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_db_t *db;
+ dns_rdataclass_t rdataclass;
+ dns_rdataclass_t db_rdataclass;
+ isc_textregion_t textregion;
+
+ filename = T_ARG(0);
+ class = T_ARG(1);
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+
+ t_info("testing with database %s and class %s\n",
+ filename, class);
+
+ textregion.base = class;
+ textregion.length = strlen(class);
+ dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdataclass_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = t_create("rbt", ".", class, "isc_true", mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("t_create failed %s\n",
+ dns_result_totext(dns_result));
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_load failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ db_rdataclass = dns_db_class(db);
+ if (db_rdataclass == rdataclass)
+ result = T_PASS;
+ else {
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ dns_rdataclass_format(db_rdataclass,
+ classbuf, sizeof(classbuf));
+ t_info("dns_db_class returned %s, expected %s\n",
+ classbuf, class);
+ result = T_FAIL;
+ }
+
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+
+}
+static void
+t7(void) {
+ int result;
+
+ t_assert("dns_db_class", 7, T_REQUIRED, a7);
+ result = t_eval("dns_db_class_data", t_dns_db_class, 2);
+ t_result(result);
+}
+
+
+static const char *a8 =
+ "A call to dns_db_currentversion() opens the current "
+ "version for reading.";
+
+static int
+t_dns_db_currentversion(char **av) {
+ char *filename;
+ char *db_type;
+ char *origin;
+ char *class;
+ char *model;
+ char *findname;
+ char *findtype;
+
+ int result;
+ int len;
+ dns_db_t *db;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_dbnode_t *nodep;
+ isc_textregion_t textregion;
+ isc_buffer_t findname_buffer;
+ dns_fixedname_t dns_findname;
+ dns_fixedname_t dns_foundname;
+ dns_rdataset_t rdataset;
+ dns_rdatatype_t rdatatype;
+ dns_dbversion_t *cversionp;
+ dns_dbversion_t *nversionp;
+
+ result = T_UNRESOLVED;
+
+ filename = T_ARG(0);
+ db_type = T_ARG(1);
+ origin = T_ARG(2);
+ class = T_ARG(3);
+ model = T_ARG(4);
+ findname = T_ARG(5);
+ findtype = T_ARG(6);
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+
+ t_info("testing using file %s and name %s\n", filename, findname);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = t_create(db_type, origin, class, model, mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_load returned %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_fixedname_init(&dns_findname);
+ len = strlen(findname);
+ isc_buffer_init(&findname_buffer, findname, len);
+ isc_buffer_add(&findname_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname),
+ &findname_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ textregion.base = findtype;
+ textregion.length = strlen(findtype);
+ dns_result = dns_rdatatype_fromtext(&rdatatype, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatatype_fromtext %s failed %s\n",
+ findtype,
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * find a name we know is there
+ */
+
+ cversionp = NULL;
+ dns_fixedname_init(&dns_foundname);
+ dns_rdataset_init(&rdataset);
+ dns_db_currentversion(db, &cversionp);
+ nodep = NULL;
+
+ dns_result = dns_db_find(db,
+ dns_fixedname_name(&dns_findname),
+ cversionp,
+ rdatatype,
+ 0,
+ 0,
+ &nodep,
+ dns_fixedname_name(&dns_foundname),
+ &rdataset, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("unable to find %s using current version\n", findname);
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * create a new version
+ * delete the found rdataset in the new version
+ * attempt to find the rdataset again and expect the find to fail
+ * close/commit the new version
+ * attempt to find the rdataset in the current version and
+ * expect the find to succeed
+ */
+
+ nversionp = NULL;
+ dns_result = dns_db_newversion(db, &nversionp);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_newversion failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Delete the found rdataset in the new version.
+ */
+ dns_result = dns_db_deleterdataset(db, nodep, nversionp, rdatatype, 0);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_deleterdataset failed %s\n",
+ dns_result_totext(dns_result));
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &nodep);
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Don't need these now.
+ */
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &nodep);
+ nodep = NULL;
+
+ /*
+ * Find the deleted rdataset and expect it to fail.
+ */
+ dns_result = dns_db_find(db,
+ dns_fixedname_name(&dns_findname),
+ nversionp,
+ rdatatype,
+ 0,
+ 0,
+ &nodep,
+ dns_fixedname_name(&dns_foundname),
+ &rdataset, NULL);
+
+ if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) {
+ t_info("unexpectedly found %s using current version\n",
+ findname);
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ /*
+ * Close/commit the new version.
+ */
+ dns_db_closeversion(db, &nversionp, ISC_TRUE);
+
+ /*
+ * Find the deleted rdata in the current version.
+ */
+ dns_result = dns_db_find(db, dns_fixedname_name(&dns_findname),
+ cversionp, rdatatype, DNS_DBFIND_GLUEOK,
+ 0, &nodep, dns_fixedname_name(&dns_foundname),
+ &rdataset, NULL);
+
+ /*
+ * And expect it to succeed.
+ */
+ if (dns_result == ISC_R_SUCCESS) {
+ result = T_PASS;
+ } else {
+ t_info("cound not find %s using current version\n", findname);
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ result = T_FAIL;
+ }
+
+ dns_db_detachnode(db, &nodep);
+ dns_rdataset_disassociate(&rdataset);
+
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static void
+t8(void) {
+ int result;
+
+ t_assert("dns_db_currentversion", 8, T_REQUIRED, a8);
+ result = t_eval("dns_db_currentversion_data",
+ t_dns_db_currentversion, 7);
+ t_result(result);
+}
+
+static const char *a9 =
+ "A call to dns_db_newversion() opens a new version for "
+ "reading and writing.";
+
+static int
+t_dns_db_newversion(char **av) {
+
+ char *filename;
+ char *db_type;
+ char *origin;
+ char *class;
+ char *model;
+ char *newname;
+ char *newtype;
+
+ int result;
+ int len;
+ int rval;
+ dns_db_t *db;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_dbnode_t *nodep;
+ dns_dbnode_t *found_nodep;
+ isc_textregion_t textregion;
+ isc_buffer_t newname_buffer;
+ dns_fixedname_t dns_newname;
+ dns_fixedname_t dns_foundname;
+ dns_rdata_t added_rdata = DNS_RDATA_INIT;
+ const char * added_rdata_data;
+ dns_rdataset_t added_rdataset;
+ dns_rdata_t found_rdata = DNS_RDATA_INIT;
+ dns_rdataset_t found_rdataset;
+ dns_rdatatype_t rdatatype;
+ dns_rdataclass_t rdataclass;
+ dns_dbversion_t *nversionp;
+ dns_rdatalist_t rdatalist;
+
+ result = T_UNRESOLVED;
+
+ filename = T_ARG(0);
+ db_type = T_ARG(1);
+ origin = T_ARG(2);
+ class = T_ARG(3);
+ model = T_ARG(4);
+ newname = T_ARG(5);
+ newtype = T_ARG(6);
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+
+ /*
+ * Open a new version, add some data, commit it,
+ * close it, open a new version, and check that changes
+ * are present.
+ */
+
+ t_info("testing using file %s and name %s\n", filename, newname);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = t_create(db_type, origin, class, model, mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_load returned %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Add a new name.
+ */
+
+ dns_fixedname_init(&dns_newname);
+ len = strlen(newname);
+ isc_buffer_init(&newname_buffer, newname, len);
+ isc_buffer_add(&newname_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_newname),
+ &newname_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ nodep = NULL;
+ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_newname),
+ ISC_TRUE, &nodep);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Open a new version and associate some rdata with the new name.
+ */
+
+ textregion.base = newtype;
+ textregion.length = strlen(newtype);
+ dns_result = dns_rdatatype_fromtext(&rdatatype, &textregion);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatatype_fromtext %s failed %s\n",
+ newtype,
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ textregion.base = class;
+ textregion.length = strlen(class);
+ dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdataclass_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rdata_init(&added_rdata);
+ added_rdata_data = "\x10\x00\x00\x01";
+ DE_CONST(added_rdata_data, added_rdata.data);
+ added_rdata.length = 4;
+ added_rdata.rdclass = rdataclass;
+ added_rdata.type = rdatatype;
+
+ dns_rdataset_init(&added_rdataset);
+ rdatalist.type = rdatatype;
+ rdatalist.covers = 0;
+ rdatalist.rdclass = rdataclass;
+ rdatalist.ttl = 0;
+ ISC_LIST_INIT(rdatalist.rdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &added_rdata, link);
+
+ dns_result = dns_rdatalist_tordataset(&rdatalist, &added_rdataset);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatalist_tordataset failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ nversionp = NULL;
+ dns_result = dns_db_newversion(db, &nversionp);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_newversion failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_addrdataset(db, nodep, nversionp, 0,
+ &added_rdataset, 0, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_addrdataset failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Close and commit the version.
+ */
+ dns_db_closeversion(db, &nversionp, ISC_TRUE);
+ dns_db_detachnode(db, &nodep);
+ if (dns_rdataset_isassociated(&added_rdataset))
+ dns_rdataset_disassociate(&added_rdataset);
+ nodep = NULL;
+
+ /*
+ * Open a new version and find the data we added.
+ */
+ dns_fixedname_init(&dns_foundname);
+ dns_rdataset_init(&found_rdataset);
+ nversionp = NULL;
+ found_nodep = NULL;
+ dns_db_newversion(db, &nversionp);
+
+ /*
+ * Find the recently added name and rdata.
+ */
+ dns_result = dns_db_find(db, dns_fixedname_name(&dns_newname),
+ nversionp, rdatatype, 0, 0, &found_nodep,
+ dns_fixedname_name(&dns_foundname),
+ &found_rdataset, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ /* XXXWPK - NXRRSET ??? reference counts ??? */
+ t_info("dns_db_find failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detachnode(db, &found_nodep);
+ if (dns_rdataset_isassociated(&found_rdataset))
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ dns_result = dns_rdataset_first(&found_rdataset);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdataset_first failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ if (dns_rdataset_isassociated(&found_rdataset))
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ /*
+ * Now make sure its what we expect.
+ */
+ dns_rdata_init(&found_rdata);
+ dns_rdataset_current(&found_rdataset, &found_rdata);
+ rval = dns_rdata_compare(&added_rdata, &found_rdata);
+ if (rval == 0) {
+ result = T_PASS;
+ } else {
+ t_info("dns_rdata_compare returned %d\n", rval);
+ result = T_FAIL;
+ }
+
+ /*
+ * Don't need these now.
+ */
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ if (dns_rdataset_isassociated(&found_rdataset))
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_detachnode(db, &found_nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static void
+t9(void) {
+ int result;
+
+ t_assert("dns_db_newversion", 9, T_REQUIRED, a9);
+ result = t_eval("dns_db_newversion_data", t_dns_db_newversion, 7);
+ t_result(result);
+}
+
+static const char *a10 =
+ "When versionp points to a read-write version and commit is "
+ "ISC_TRUE, a call to dns_db_closeversion(db, versionp, commit) "
+ "causes all changes made in the version to take effect, "
+ "and returns ISC_R_SUCCESS.";
+
+static int
+t_dns_db_closeversion_1(char **av) {
+ char *filename;
+ char *db_type;
+ char *origin;
+ char *class;
+ char *model;
+ char *new_name;
+ char *new_type;
+ char *existing_name;
+ char *existing_type;
+
+ int result;
+ int len;
+ int rval;
+ int nfails;
+ dns_db_t *db;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_dbnode_t *nodep;
+ isc_textregion_t textregion;
+ isc_buffer_t name_buffer;
+ dns_fixedname_t dns_newname;
+ dns_fixedname_t dns_foundname;
+ dns_fixedname_t dns_existingname;
+ dns_rdata_t added_rdata = DNS_RDATA_INIT;
+ const char * added_rdata_data;
+ dns_rdataset_t added_rdataset;
+ dns_rdata_t found_rdata = DNS_RDATA_INIT;
+ dns_rdataset_t found_rdataset;
+ dns_rdatatype_t new_rdatatype;
+ dns_rdatatype_t existing_rdatatype;
+ dns_rdataclass_t rdataclass;
+ dns_dbversion_t *nversionp;
+ dns_dbversion_t *cversionp;
+ dns_rdatalist_t rdatalist;
+
+ filename = T_ARG(0);
+ db_type = T_ARG(1);
+ origin = T_ARG(2);
+ class = T_ARG(3);
+ model = T_ARG(4);
+ new_name = T_ARG(5);
+ new_type = T_ARG(6);
+ existing_name = T_ARG(7);
+ existing_type = T_ARG(8);
+
+ nfails = 0;
+ result = T_UNRESOLVED;
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+
+ /*
+ * Open a new version, add some data,
+ * remove some data, close with commit, open the current
+ * version and check that changes are present.
+ */
+
+ t_info("testing using file %s and name %s\n", filename, new_name);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = t_create(db_type, origin, class, model, mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_load returned %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Remove all rdata for an existing name.
+ */
+
+ dns_fixedname_init(&dns_existingname);
+ len = strlen(existing_name);
+ isc_buffer_init(&name_buffer, existing_name, len);
+ isc_buffer_add(&name_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_existingname),
+ &name_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ textregion.base = existing_type;
+ textregion.length = strlen(existing_type);
+ dns_result = dns_rdatatype_fromtext(&existing_rdatatype, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatatype_fromtext %s failed %s\n",
+ existing_type,
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ nodep = NULL;
+ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_existingname),
+ ISC_FALSE, &nodep);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_findnode %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /* open a new version */
+ nversionp = NULL;
+ dns_result = dns_db_newversion(db, &nversionp);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_newversion failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_deleterdataset(db, nodep, nversionp,
+ existing_rdatatype, 0);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_deleterdataset failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * add a new name and associate some rdata with it
+ */
+
+ dns_db_detachnode(db, &nodep);
+ nodep = NULL;
+
+ dns_fixedname_init(&dns_newname);
+ len = strlen(new_name);
+ isc_buffer_init(&name_buffer, new_name, len);
+ isc_buffer_add(&name_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_newname),
+ &name_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_newname),
+ ISC_TRUE, &nodep);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * associate some rdata with the new name
+ */
+
+ textregion.base = new_type;
+ textregion.length = strlen(new_type);
+ dns_result = dns_rdatatype_fromtext(&new_rdatatype, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatatype_fromtext %s failed %s\n",
+ new_type,
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ textregion.base = class;
+ textregion.length = strlen(class);
+ dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdataclass_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rdata_init(&added_rdata);
+ added_rdata_data = "\x10\x00\x00\x01";
+ DE_CONST(added_rdata_data, added_rdata.data);
+ added_rdata.length = 4;
+ added_rdata.rdclass = rdataclass;
+ added_rdata.type = new_rdatatype;
+
+ dns_rdataset_init(&added_rdataset);
+ rdatalist.type = new_rdatatype;
+ rdatalist.covers = 0;
+ rdatalist.rdclass = rdataclass;
+ rdatalist.ttl = 0;
+ ISC_LIST_INIT(rdatalist.rdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &added_rdata, link);
+
+ dns_result = dns_rdatalist_tordataset(&rdatalist, &added_rdataset);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatalist_tordataset failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_addrdataset(db, nodep, nversionp, 0,
+ &added_rdataset, 0, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_addrdataset failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /* close and commit the version */
+ dns_db_closeversion(db, &nversionp, ISC_TRUE);
+ dns_db_detachnode(db, &nodep);
+ nodep = NULL;
+
+ /* open the current version and check changes */
+ dns_fixedname_init(&dns_foundname);
+ dns_rdataset_init(&found_rdataset);
+ cversionp = NULL;
+ dns_db_currentversion(db, &cversionp);
+
+ /* find the recently added name and rdata */
+ dns_result = dns_db_find(db,
+ dns_fixedname_name(&dns_newname),
+ cversionp,
+ new_rdatatype,
+ 0,
+ 0,
+ &nodep,
+ dns_fixedname_name(&dns_foundname),
+ &found_rdataset, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ /* XXXWPK NXRRSET ??? reference counting ??? */
+ t_info("dns_db_find failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detachnode(db, &nodep);
+ if (dns_rdataset_isassociated(&found_rdataset))
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ dns_result = dns_rdataset_first(&found_rdataset);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdataset_first failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ if (dns_rdataset_isassociated(&found_rdataset))
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ /*
+ * Now make sure its what we expect.
+ */
+ dns_rdata_init(&found_rdata);
+ dns_rdataset_current(&found_rdataset, &found_rdata);
+ rval = dns_rdata_compare(&added_rdata, &found_rdata);
+ if (rval != 0) {
+ t_info("dns_rdata_compare returned %d\n", rval);
+ ++nfails;
+ }
+
+ /*
+ * Now check the rdata deletion.
+ */
+
+ if (dns_rdataset_isassociated(&found_rdataset))
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_rdataset_init(&found_rdataset);
+ dns_db_detachnode(db, &nodep);
+ nodep = NULL;
+ dns_fixedname_init(&dns_foundname);
+
+ dns_result = dns_db_find(db, dns_fixedname_name(&dns_existingname),
+ cversionp, existing_rdatatype,
+ 0, 0, &nodep,
+ dns_fixedname_name(&dns_foundname),
+ &found_rdataset, NULL);
+
+
+ if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) {
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_detachnode(db, &nodep);
+ t_info("dns_db_find %s returned %s\n", existing_name,
+ dns_result_totext(dns_result));
+ ++nfails;
+ }
+
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ if (nfails == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+
+ return(result);
+}
+
+static void
+t10(void) {
+ int result;
+
+ t_assert("dns_db_closeversion", 10, T_REQUIRED, a10);
+ result = t_eval("dns_db_closeversion_1_data",
+ t_dns_db_closeversion_1, 9);
+ t_result(result);
+}
+
+static const char *a11 =
+ "When versionp points to a read-write version and commit is "
+ "ISC_FALSE, a call to dns_db_closeversion(db, versionp, commit) "
+ "causes all changes made in the version to to be rolled back, "
+ "and returns ISC_R_SUCCESS.";
+
+static int
+t_dns_db_closeversion_2(char **av) {
+ char *filename;
+ char *db_type;
+ char *origin;
+ char *class;
+ char *model;
+ char *new_name;
+ char *new_type;
+ char *existing_name;
+ char *existing_type;
+
+ int result;
+ int len;
+ int rval;
+ int nfails;
+ dns_db_t *db;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_dbnode_t *nodep;
+ isc_textregion_t textregion;
+ isc_buffer_t name_buffer;
+ dns_fixedname_t dns_newname;
+ dns_fixedname_t dns_foundname;
+ dns_fixedname_t dns_existingname;
+ dns_rdata_t added_rdata = DNS_RDATA_INIT;
+ const char * added_rdata_data;
+ dns_rdataset_t added_rdataset;
+ dns_rdata_t found_rdata = DNS_RDATA_INIT;
+ dns_rdataset_t found_rdataset;
+ dns_rdatatype_t new_rdatatype;
+ dns_rdatatype_t existing_rdatatype;
+ dns_rdataclass_t rdataclass;
+ dns_dbversion_t *nversionp;
+ dns_dbversion_t *cversionp;
+ dns_rdatalist_t rdatalist;
+
+ filename = T_ARG(0);
+ db_type = T_ARG(1);
+ origin = T_ARG(2);
+ class = T_ARG(3);
+ model = T_ARG(4);
+ new_name = T_ARG(5);
+ new_type = T_ARG(6);
+ existing_name = T_ARG(7);
+ existing_type = T_ARG(8);
+
+ nfails = 0;
+ result = T_UNRESOLVED;
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+
+ /*
+ * Open a new version, add some data,
+ * remove some data, close with commit, open the current
+ * version and check that changes are present.
+ */
+
+ t_info("testing using file %s and name %s\n", filename, new_name);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = t_create(db_type, origin, class, model, mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_load returned %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Remove all rdata for an existing name.
+ */
+
+ dns_fixedname_init(&dns_existingname);
+ len = strlen(existing_name);
+ isc_buffer_init(&name_buffer, existing_name, len);
+ isc_buffer_add(&name_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_existingname),
+ &name_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ textregion.base = existing_type;
+ textregion.length = strlen(existing_type);
+ dns_result = dns_rdatatype_fromtext(&existing_rdatatype, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatatype_fromtext %s failed %s\n",
+ existing_type,
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ nodep = NULL;
+ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_existingname),
+ ISC_FALSE, &nodep);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_findnode %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Open a new version.
+ */
+ nversionp = NULL;
+ dns_result = dns_db_newversion(db, &nversionp);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_newversion failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_deleterdataset(db, nodep, nversionp,
+ existing_rdatatype, 0);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_deleterdataset failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * add a new name and associate some rdata with it
+ */
+
+ dns_db_detachnode(db, &nodep);
+ nodep = NULL;
+
+ dns_fixedname_init(&dns_newname);
+ len = strlen(new_name);
+ isc_buffer_init(&name_buffer, new_name, len);
+ isc_buffer_add(&name_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_newname),
+ &name_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_newname),
+ ISC_TRUE, &nodep);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ textregion.base = new_type;
+ textregion.length = strlen(new_type);
+ dns_result = dns_rdatatype_fromtext(&new_rdatatype, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatatype_fromtext %s failed %s\n",
+ new_type, dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ textregion.base = class;
+ textregion.length = strlen(class);
+ dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdataclass_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rdata_init(&added_rdata);
+ added_rdata_data = "\x10\x00\x00\x01";
+ DE_CONST(added_rdata_data, added_rdata.data);
+ added_rdata.length = 4;
+ added_rdata.rdclass = rdataclass;
+ added_rdata.type = new_rdatatype;
+
+ dns_rdataset_init(&added_rdataset);
+ rdatalist.type = new_rdatatype;
+ rdatalist.covers = 0;
+ rdatalist.rdclass = rdataclass;
+ rdatalist.ttl = 0;
+ ISC_LIST_INIT(rdatalist.rdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &added_rdata, link);
+
+ dns_result = dns_rdatalist_tordataset(&rdatalist, &added_rdataset);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatalist_tordataset failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_addrdataset(db, nodep, nversionp, 0,
+ &added_rdataset, 0, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_addrdataset failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Check that our changes took.
+ */
+ dns_db_detachnode(db, &nodep);
+ nodep = NULL;
+ dns_fixedname_init(&dns_foundname);
+ dns_rdataset_init(&found_rdataset);
+
+ /*
+ * Find the recently added name and rdata.
+ */
+ dns_result = dns_db_find(db, dns_fixedname_name(&dns_newname),
+ nversionp, new_rdatatype, 0, 0, &nodep,
+ dns_fixedname_name(&dns_foundname),
+ &found_rdataset, NULL);
+
+ if ((dns_result == ISC_R_NOTFOUND) ||
+ (dns_result == DNS_R_NXDOMAIN) ||
+ (dns_result == DNS_R_NXRRSET)) {
+
+ t_info("dns_db_find failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detachnode(db, &nodep);
+ if (dns_rdataset_isassociated(&found_rdataset))
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ dns_result = dns_rdataset_first(&found_rdataset);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdataset_first failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ if (dns_rdataset_isassociated(&found_rdataset))
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ /*
+ * Now make sure its what we expect.
+ */
+ dns_rdata_init(&found_rdata);
+ dns_rdataset_current(&found_rdataset, &found_rdata);
+ rval = dns_rdata_compare(&added_rdata, &found_rdata);
+ if (rval != 0) {
+ t_info("dns_rdata_compare returned %d\n", rval);
+ ++nfails;
+ }
+
+ /*
+ * Now check the rdata deletion.
+ */
+ if (dns_rdataset_isassociated(&found_rdataset))
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_rdataset_init(&found_rdataset);
+ dns_db_detachnode(db, &nodep);
+ nodep = NULL;
+ dns_fixedname_init(&dns_foundname);
+
+ dns_result = dns_db_find(db,
+ dns_fixedname_name(&dns_existingname),
+ nversionp,
+ existing_rdatatype,
+ 0,
+ 0,
+ &nodep,
+ dns_fixedname_name(&dns_foundname),
+ &found_rdataset, NULL);
+
+
+ if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) {
+ t_info("dns_db_find %s returned %s\n", existing_name,
+ dns_result_totext(dns_result));
+ if (dns_rdataset_isassociated(&found_rdataset))
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_detachnode(db, &nodep);
+ ++nfails;
+ }
+
+
+ /*
+ * Close the version without a commit.
+ */
+ dns_db_closeversion(db, &nversionp, ISC_FALSE);
+
+ /*
+ * Open the current version and check changes.
+ */
+ dns_fixedname_init(&dns_foundname);
+ dns_rdataset_init(&found_rdataset);
+ cversionp = NULL;
+ dns_db_currentversion(db, &cversionp);
+
+ /*
+ * Find the recently added name and rdata.
+ */
+ dns_result = dns_db_find(db,
+ dns_fixedname_name(&dns_newname),
+ cversionp,
+ new_rdatatype,
+ 0,
+ 0,
+ &nodep,
+ dns_fixedname_name(&dns_foundname),
+ &found_rdataset, NULL);
+
+ if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) {
+ t_info("dns_db_find %s returned %s\n", new_name,
+ dns_result_totext(dns_result));
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_detachnode(db, &nodep);
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ /*
+ * Now check the rdata deletion.
+ */
+ nodep = NULL;
+ dns_rdataset_init(&found_rdataset);
+ dns_fixedname_init(&dns_foundname);
+
+ dns_result = dns_db_find(db, dns_fixedname_name(&dns_existingname),
+ cversionp, existing_rdatatype, 0, 0,
+ &nodep, dns_fixedname_name(&dns_foundname),
+ &found_rdataset, NULL);
+
+
+ if ((dns_result == ISC_R_NOTFOUND) ||
+ (dns_result == DNS_R_NXDOMAIN) ||
+ (dns_result == DNS_R_NXRRSET)) {
+
+ t_info("dns_db_find %s returned %s\n", existing_name,
+ dns_result_totext(dns_result));
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_detachnode(db, &nodep);
+ ++nfails;
+ }
+
+ dns_db_detachnode(db, &nodep);
+ dns_rdataset_disassociate(&found_rdataset);
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ if (nfails == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+
+ return(result);
+}
+
+static void
+t11(void) {
+ int result;
+
+ t_assert("dns_db_closeversion", 11, T_REQUIRED, a11);
+ result = t_eval("dns_db_closeversion_2_data",
+ t_dns_db_closeversion_2, 9);
+ t_result(result);
+}
+
+static const char *a12 =
+ "A call to dns_db_expirenode() marks as stale all records at node "
+ "which expire at or before 'now'. If 'now' is zero, then the current "
+ "time will be used.";
+
+static int
+t_dns_db_expirenode(char **av) {
+ char *filename;
+ char *db_type;
+ char *origin;
+ char *class;
+ char *existing_name;
+ char *node_xtime;
+ char *find_xtime;
+ char *exp_find_result;
+
+ int result;
+ int len;
+ dns_db_t *db;
+ isc_result_t dns_result;
+ isc_result_t exp_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_dbnode_t *nodep;
+ isc_buffer_t name_buffer;
+ dns_fixedname_t dns_foundname;
+ dns_fixedname_t dns_existingname;
+ isc_stdtime_t node_expire_time;
+ isc_stdtime_t find_expire_time;
+ isc_stdtime_t now;
+ dns_rdataset_t rdataset;
+
+ filename = T_ARG(0);
+ db_type = T_ARG(1);
+ origin = T_ARG(2);
+ class = T_ARG(3);
+ existing_name = T_ARG(4);
+ node_xtime = T_ARG(5);
+ find_xtime = T_ARG(6);
+ exp_find_result = T_ARG(7);
+ mctx = NULL;
+ ectx = NULL;
+
+ result = T_UNRESOLVED;
+
+ /*
+ * Find a node, mark it as stale, do a dns_db_find on the name and
+ * expect it to fail.
+ */
+
+ t_info("testing using file %s and name %s\n", filename, existing_name);
+
+ node_expire_time = (isc_stdtime_t) strtol(node_xtime, NULL, 10);
+ find_expire_time = (isc_stdtime_t) strtol(find_xtime, NULL, 10);
+ exp_result = t_dns_result_fromtext(exp_find_result);
+
+ isc_stdtime_get(&now);
+
+ dns_fixedname_init(&dns_existingname);
+ len = strlen(existing_name);
+ isc_buffer_init(&name_buffer, existing_name, len);
+ isc_buffer_add(&name_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_existingname),
+ &name_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ db = NULL;
+ dns_result = t_create(db_type, origin, class, "cache", mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_load returned %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ nodep = NULL;
+
+ /*
+ * Check that the node is there.
+ */
+ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_existingname),
+ ISC_FALSE, &nodep);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("unable to find %s\n", existing_name);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Expire it.
+ */
+ if (node_expire_time != 0)
+ node_expire_time += now;
+
+ dns_result = dns_db_expirenode(db, nodep, node_expire_time);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_expirenode failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ dns_fixedname_init(&dns_foundname);
+ dns_rdataset_init(&rdataset);
+ dns_db_detachnode(db, &nodep);
+ nodep = NULL;
+
+ if (find_expire_time != 0)
+ find_expire_time += now;
+
+ dns_result = dns_db_find(db,
+ dns_fixedname_name(&dns_existingname),
+ NULL,
+ dns_rdatatype_any,
+ 0,
+ find_expire_time,
+ &nodep,
+ dns_fixedname_name(&dns_foundname),
+ &rdataset, NULL);
+
+ if (dns_result == exp_result) {
+ result = T_PASS;
+ } else {
+ t_info("dns_db_find %s returned %s\n", existing_name,
+ dns_result_totext(dns_result));
+ result = T_FAIL;
+ }
+
+ if ((dns_result != ISC_R_NOTFOUND) &&
+ (dns_result != DNS_R_NXDOMAIN) &&
+ (dns_result != DNS_R_NXRRSET)) {
+
+ /*
+ * Don't need to disassociate the rdataset because
+ * we're searching with dns_rdatatype_any.
+ */
+ dns_db_detachnode(db, &nodep);
+ }
+
+
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static void
+t12(void) {
+ int result;
+
+ t_assert("dns_db_expirenode", 12, T_REQUIRED, a12);
+ result = t_eval("dns_db_expirenode_data", t_dns_db_expirenode, 8);
+ t_result(result);
+}
+
+static const char *a13 =
+ "If the node name exists, then a call to "
+ "dns_db_findnode(db, name, ISC_FALSE, nodep) initializes nodep "
+ "to point to the node and returns ISC_R_SUCCESS, otherwise "
+ "it returns ISC_R_NOTFOUND.";
+
+static int
+t_dns_db_findnode_1(char **av) {
+ char *filename;
+ char *db_type;
+ char *origin;
+ char *class;
+ char *model;
+ char *find_name;
+ char *find_type;
+ char *expected_result;
+
+ int result;
+ int len;
+ dns_db_t *db;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_dbnode_t *nodep;
+ isc_buffer_t name_buffer;
+ dns_rdataset_t rdataset;
+ dns_rdatatype_t rdatatype;
+ isc_textregion_t textregion;
+ dns_fixedname_t dns_name;
+ dns_dbversion_t *cversionp;
+ isc_result_t exp_result;
+
+ filename = T_ARG(0);
+ db_type = T_ARG(1);
+ origin = T_ARG(2);
+ class = T_ARG(3);
+ model = T_ARG(4);
+ find_name = T_ARG(5);
+ find_type = T_ARG(6);
+ expected_result = T_ARG(7);
+
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+ result = T_UNRESOLVED;
+
+ t_info("testing using file %s and name %s\n", filename, find_name);
+
+ exp_result = t_dns_result_fromtext(expected_result);
+
+ textregion.base = find_type;
+ textregion.length = strlen(find_type);
+ dns_result = dns_rdatatype_fromtext(&rdatatype, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatatype_fromtext %s failed %s\n",
+ find_type,
+ dns_result_totext(dns_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = t_create(db_type, origin, class, model, mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_load returned %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ nodep = NULL;
+ dns_fixedname_init(&dns_name);
+
+ len = strlen(find_name);
+ isc_buffer_init(&name_buffer, find_name, len);
+ isc_buffer_add(&name_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_name),
+ &name_buffer, NULL, ISC_FALSE, NULL);
+
+ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_name),
+ ISC_FALSE, &nodep);
+ if (dns_result != exp_result) {
+ t_info("dns_db_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ if (dns_result == ISC_R_SUCCESS)
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ /*
+ * if we're expecting the find to succeed and it did,
+ * check that the node has been initialized
+ * by checking for the specified type of rdata
+ * and expecting the search to succeed
+ */
+
+ if (dns_result == ISC_R_SUCCESS) {
+ cversionp = NULL;
+ dns_db_currentversion(db, &cversionp);
+ dns_rdataset_init(&rdataset);
+
+ dns_result = dns_db_findrdataset(db, nodep, cversionp,
+ rdatatype, 0,
+ 0, &rdataset, NULL);
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&rdataset);
+ result = T_PASS;
+ } else {
+ t_info("dns_db_findrdataset failed %s\n",
+ dns_result_totext(dns_result));
+ result = T_FAIL;
+ }
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detachnode(db, &nodep);
+ } else {
+ result = T_PASS;
+ }
+
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static void
+t13(void) {
+ int result;
+
+ t_assert("dns_db_findnode", 13, T_REQUIRED, a13);
+ result = t_eval("dns_db_findnode_1_data", t_dns_db_findnode_1, 8);
+ t_result(result);
+}
+
+static const char *a14 =
+ "If the node name does not exist and create is ISC_TRUE, "
+ "then a call to dns_db_findnode(db, name, create, nodep) "
+ "creates the node, initializes nodep to point to the node, "
+ "and returns ISC_R_SUCCESS.";
+
+static int
+t_dns_db_findnode_2(char **av) {
+ char *filename;
+ char *db_type;
+ char *origin;
+ char *class;
+ char *model;
+ char *newname;
+
+ int nfails;
+ int result;
+ int len;
+ dns_db_t *db;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_dbnode_t *nodep;
+ dns_dbnode_t *newnodep;
+ isc_buffer_t name_buffer;
+ dns_rdataset_t rdataset;
+ dns_fixedname_t dns_name;
+ dns_fixedname_t dns_foundname;
+ dns_dbversion_t *cversionp;
+
+ filename = T_ARG(0);
+ db_type = T_ARG(1);
+ origin = T_ARG(2);
+ class = T_ARG(3);
+ model = T_ARG(4);
+ newname = T_ARG(5);
+
+ result = T_UNRESOLVED;
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+ nfails = 0;
+
+ t_info("testing using file %s and name %s\n", filename, newname);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = t_create(db_type, origin, class, model, mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, filename);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_load returned %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ nodep = NULL;
+ dns_fixedname_init(&dns_name);
+
+ /*
+ * Make sure the name isn't there
+ */
+ len = strlen(newname);
+ isc_buffer_init(&name_buffer, newname, len);
+ isc_buffer_add(&name_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_name),
+ &name_buffer, NULL, ISC_FALSE, NULL);
+
+ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_name),
+ ISC_FALSE, &nodep);
+ if ((dns_result != ISC_R_NOTFOUND) &&
+ (dns_result != DNS_R_NXDOMAIN) &&
+ (dns_result != DNS_R_NXRRSET)) {
+ t_info("dns_db_findnode %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detachnode(db, &nodep);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Add it.
+ */
+ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_name),
+ ISC_TRUE, &nodep);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_findnode %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ /*
+ * Check it.
+ */
+ newnodep = NULL;
+ dns_rdataset_init(&rdataset);
+ dns_fixedname_init(&dns_foundname);
+ cversionp = NULL;
+ dns_db_currentversion(db, &cversionp);
+
+ /*
+ * First try dns_db_find DNS_R_NXDOMAIN.
+ */
+ dns_result = dns_db_find(db,
+ dns_fixedname_name(&dns_name),
+ cversionp,
+ dns_rdatatype_any,
+ 0,
+ 0,
+ &newnodep,
+ dns_fixedname_name(&dns_foundname),
+ &rdataset, NULL);
+ if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) {
+ dns_db_detachnode(db, &newnodep);
+ }
+
+ if (dns_result != DNS_R_NXDOMAIN) {
+ t_info("dns_db_find %s\n",
+ dns_result_totext(dns_result));
+ ++nfails;
+ }
+
+ /*
+ * Then try dns_db_findnode ISC_R_SUCCESS.
+ */
+ dns_result = dns_db_findnode(db, dns_fixedname_name(&dns_name),
+ ISC_FALSE, &newnodep);
+ t_info("dns_db_findnode %s\n", dns_result_totext(dns_result));
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_db_detachnode(db, &newnodep);
+ } else {
+ t_info("dns_db_findnode %s failed %s\n", newname,
+ dns_result_totext(dns_result));
+ ++nfails;
+ }
+
+
+ dns_db_detachnode(db, &nodep);
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ if (nfails == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+
+ return(result);
+}
+
+static void
+t14(void) {
+ int result;
+
+ t_assert("dns_db_findnode", 14, T_REQUIRED, a14);
+ result = t_eval("dns_db_findnode_2_data", t_dns_db_findnode_2, 6);
+ t_result(result);
+}
+
+static int
+t_dns_db_find_x(char **av) {
+ char *dbfile;
+ char *dbtype;
+ char *dborigin;
+ char *dbclass;
+ char *dbmodel;
+ char *findname;
+ char *findtype;
+ char *findopts;
+ char *findtime;
+ char *expected_result;
+
+ int result;
+ int len;
+ int opts;
+ dns_db_t *db;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ isc_stdtime_t ftime;
+ isc_stdtime_t now;
+ isc_result_t exp_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_dbnode_t *nodep;
+ isc_textregion_t textregion;
+ isc_buffer_t findname_buffer;
+ dns_fixedname_t dns_findname;
+ dns_fixedname_t dns_foundname;
+ dns_rdataset_t rdataset;
+ dns_rdatatype_t rdatatype;
+ dns_dbversion_t *cversionp;
+
+ result = T_UNRESOLVED;
+
+ dbfile = T_ARG(0);
+ dbtype = T_ARG(1);
+ dborigin = T_ARG(2);
+ dbclass = T_ARG(3);
+ dbmodel = T_ARG(4);
+ findname = T_ARG(5);
+ findtype = T_ARG(6);
+ findopts = T_ARG(7);
+ findtime = T_ARG(8);
+ expected_result = T_ARG(9);
+ db = NULL;
+ mctx = NULL;
+ ectx = NULL;
+ opts = 0;
+
+ t_info("testing using %s, name %s, type %s\n", dbfile, findname,
+ findtype);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = t_create(dbtype, dborigin, dbclass, dbmodel, mctx, &db);
+ if (dns_result != ISC_R_SUCCESS) {
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_db_load(db, dbfile);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_db_load returned %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ exp_result = t_dns_result_fromtext(expected_result);
+
+ dns_fixedname_init(&dns_findname);
+ len = strlen(findname);
+ isc_buffer_init(&findname_buffer, findname, len);
+ isc_buffer_add(&findname_buffer, len);
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname),
+ &findname_buffer, NULL, ISC_FALSE, NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ textregion.base = findtype;
+ textregion.length = strlen(findtype);
+ dns_result = dns_rdatatype_fromtext(&rdatatype, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdatatype_fromtext %s failed %s\n",
+ findtype,
+ dns_result_totext(dns_result));
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ if (strstr(findopts, "DNS_DBFIND_GLUEOK"))
+ opts |= DNS_DBFIND_GLUEOK;
+ if (strstr(findopts, "DNS_DBFIND_VALIDATEGLUE"))
+ opts |= DNS_DBFIND_VALIDATEGLUE;
+
+ isc_stdtime_get(&now);
+
+ ftime = strtol(findtime, NULL, 10);
+ if (ftime != 0)
+ ftime += now;
+
+ cversionp = NULL;
+ dns_fixedname_init(&dns_foundname);
+ dns_rdataset_init(&rdataset);
+ if (dns_db_iszone(db))
+ dns_db_currentversion(db, &cversionp);
+ nodep = NULL;
+
+ dns_result = dns_db_find(db,
+ dns_fixedname_name(&dns_findname),
+ cversionp,
+ rdatatype,
+ opts,
+ ftime,
+ &nodep,
+ dns_fixedname_name(&dns_foundname),
+ &rdataset, NULL);
+
+ if (dns_result != exp_result) {
+ t_info("dns_db_find %s %s unexpectedly returned %s, "
+ "expected %s\n",
+ findname, findtype, dns_result_totext(dns_result),
+ dns_result_totext(exp_result));
+ result = T_FAIL;
+ } else {
+ result = T_PASS;
+ }
+
+ if ((dns_result != ISC_R_NOTFOUND) && (dns_result != DNS_R_NXDOMAIN)) {
+
+ if ((dns_result != DNS_R_NXRRSET) &&
+ (dns_result != DNS_R_ZONECUT))
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &nodep);
+ }
+
+ if (dns_db_iszone(db))
+ dns_db_closeversion(db, &cversionp, ISC_FALSE);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static const char *a15 =
+ "A call to dns_db_find(db, name, version, type, options, now, ...) "
+ "finds the best match for 'name' and 'type' in version 'version' "
+ "of 'db'.";
+
+static void
+t15(void) {
+ int result;
+
+ t_assert("dns_db_find", 15, T_REQUIRED, a15);
+ result = t_eval("dns_db_find_1_data", t_dns_db_find_x, 10);
+ t_result(result);
+}
+
+
+static const char *a16 =
+ "When the desired node and type were found, but are glue, "
+ "and the DNS_DBFIND_GLUEOK option is set, a call to "
+ "dns_db_find(db, name, version, type, options, now, ...) "
+ "returns DNS_R_GLUE.";
+
+static void
+t16(void) {
+ int result;
+
+ t_assert("dns_db_find", 16, T_REQUIRED, a16);
+ result = t_eval("dns_db_find_2_data", t_dns_db_find_x, 10);
+ t_result(result);
+}
+
+static const char *a17 =
+ "A call to dns_db_find() returns DNS_R_DELEGATION when the data "
+ "requested is beneath a zone cut.";
+
+static void
+t17(void) {
+ int result;
+
+ t_assert("dns_db_find", 17, T_REQUIRED, a17);
+ result = t_eval("dns_db_find_3_data", t_dns_db_find_x, 10);
+ t_result(result);
+}
+
+static const char *a18 =
+ "A call to dns_db_find() returns DNS_R_DELEGATION when type is "
+ "dns_rdatatype_any and the desired node is a zone cut.";
+
+static void
+t18(void) {
+ int result;
+
+ t_assert("dns_db_find", 18, T_REQUIRED, a18);
+ result = t_eval("dns_db_find_4_data", t_dns_db_find_x, 10);
+ t_result(result);
+}
+
+static const char *a19 =
+ "A call to dns_db_find() returns DNS_R_DNAME when the data "
+ "requested is beneath a DNAME.";
+
+static void
+t19(void) {
+ int result;
+
+ t_assert("dns_db_find", 19, T_REQUIRED, a19);
+ result = t_eval("dns_db_find_5_data", t_dns_db_find_x, 10);
+ t_result(result);
+}
+
+static const char *a20 =
+ "A call to dns_db_find() returns DNS_R_CNAME when the requested "
+ "rdataset was not found but there is a CNAME at the desired name.";
+
+static void
+t20(void) {
+ int result;
+
+ t_assert("dns_db_find", 20, T_REQUIRED, a20);
+ result = t_eval("dns_db_find_6_data", t_dns_db_find_x, 10);
+ t_result(result);
+}
+
+static const char *a21 =
+ "A call to dns_db_find() returns DNS_R_NXDOMAIN when name "
+ "does not exist.";
+
+static void
+t21(void) {
+ int result;
+
+ t_assert("dns_db_find", 21, T_REQUIRED, a21);
+ result = t_eval("dns_db_find_7_data", t_dns_db_find_x, 10);
+ t_result(result);
+}
+
+static const char *a22 =
+ "A call to dns_db_find() returns DNS_R_NXRRSET when "
+ "the desired name exists, but the desired type does not.";
+
+static void
+t22(void) {
+ int result;
+
+ t_assert("dns_db_find", 22, T_REQUIRED, a22);
+ result = t_eval("dns_db_find_8_data", t_dns_db_find_x, 10);
+ t_result(result);
+}
+
+static const char *a23 =
+ "When db is a cache database, a call to dns_db_find() "
+ "returns ISC_R_NOTFOUND when the desired name does not exist, "
+ "and no delegation could be found.";
+
+static void
+t23(void) {
+ int result;
+
+ t_assert("dns_db_find", 23, T_REQUIRED, a23);
+ result = t_eval("dns_db_find_9_data", t_dns_db_find_x, 10);
+ t_result(result);
+}
+
+static const char *a24 =
+ "When db is a cache database, an rdataset will be found only "
+ "if at least one rdataset at the found node expires after 'now'.";
+
+static void
+t24(void) {
+ int result;
+
+ t_assert("dns_db_find", 24, T_REQUIRED, a24);
+ result = t_eval("dns_db_find_10_data", t_dns_db_find_x, 10);
+ t_result(result);
+}
+
+static const char *a25 =
+ "A call to dns_db_load(db, filename) returns DNS_R_NOTZONETOP "
+ "when the zone data contains a SOA not at the zone apex.";
+
+static void
+t25(void) {
+ int result;
+
+ t_assert("dns_db_load", 25, T_REQUIRED, a25);
+ result = t_eval("dns_db_load_soa_not_top", t_dns_db_load, 9);
+ t_result(result);
+}
+
+testspec_t T_testlist[] = {
+ { t1, "dns_db_load" },
+ { t2, "dns_db_iscache" },
+ { t3, "dns_db_iscache" },
+ { t4, "dns_db_iszone" },
+ { t5, "dns_db_iszone" },
+ { t6, "dns_db_origin" },
+ { t7, "dns_db_class" },
+ { t8, "dns_db_currentversion" },
+ { t9, "dns_db_newversion" },
+ { t10, "dns_db_closeversion" },
+ { t11, "dns_db_closeversion" },
+ { t12, "dns_db_expirenode" },
+ { t13, "dns_db_findnode" },
+ { t14, "dns_db_findnode" },
+ { t15, "dns_db_find" },
+ { t16, "dns_db_find" },
+ { t17, "dns_db_find" },
+ { t18, "dns_db_find" },
+ { t19, "dns_db_find" },
+ { t20, "dns_db_find" },
+ { t21, "dns_db_find" },
+ { t22, "dns_db_find" },
+ { t23, "dns_db_find" },
+ { t24, "dns_db_find" },
+ { t25, "dns_db_load" },
+ { NULL, NULL }
+};
diff --git a/bin/tests/db_test.c b/bin/tests/db_test.c
new file mode 100644
index 0000000..9b0d90d
--- /dev/null
+++ b/bin/tests/db_test.c
@@ -0,0 +1,946 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: db_test.c,v 1.66 2008/09/25 04:02:38 tbox Exp $ */
+
+/*! \file
+ * \author
+ * Principal Author: Bob Halley
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/commandline.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/time.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/dbtable.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+
+#define MAXHOLD 100
+#define MAXVERSIONS 100
+
+typedef struct dbinfo {
+ dns_db_t * db;
+ dns_dbversion_t * version;
+ dns_dbversion_t * wversion;
+ dns_dbversion_t * rversions[MAXVERSIONS];
+ int rcount;
+ dns_dbnode_t * hold_nodes[MAXHOLD];
+ int hold_count;
+ dns_dbiterator_t * dbiterator;
+ dns_dbversion_t * iversion;
+ int pause_every;
+ isc_boolean_t ascending;
+ ISC_LINK(struct dbinfo) link;
+} dbinfo;
+
+static isc_mem_t * mctx = NULL;
+static char dbtype[128];
+static dns_dbtable_t * dbtable;
+static ISC_LIST(dbinfo) dbs;
+static dbinfo * cache_dbi = NULL;
+static int pause_every = 0;
+static isc_boolean_t ascending = ISC_TRUE;
+
+static void
+print_result(const char *message, isc_result_t result) {
+ size_t len;
+
+ if (message == NULL) {
+ len = 0;
+ message = "";
+ }
+ len = strlen(message);
+ printf("%s%sresult %08x: %s\n", message, (len == 0U) ? "" : " ",
+ result, isc_result_totext(result));
+}
+
+static void
+print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset) {
+ isc_buffer_t text;
+ char t[1000];
+ isc_result_t result;
+ isc_region_t r;
+
+ isc_buffer_init(&text, t, sizeof(t));
+ result = dns_rdataset_totext(rdataset, name, ISC_FALSE, ISC_FALSE,
+ &text);
+ isc_buffer_usedregion(&text, &r);
+ if (result == ISC_R_SUCCESS)
+ printf("%.*s", (int)r.length, (char *)r.base);
+ else
+ print_result("", result);
+}
+
+static void
+print_rdatasets(dns_name_t *name, dns_rdatasetiter_t *rdsiter) {
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ print_rdataset(name, &rdataset);
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+ if (result != ISC_R_NOMORE)
+ print_result("", result);
+}
+
+static dbinfo *
+select_db(char *origintext) {
+ dns_fixedname_t forigin;
+ dns_name_t *origin;
+ isc_buffer_t source;
+ size_t len;
+ dbinfo *dbi;
+ isc_result_t result;
+
+ if (strcasecmp(origintext, "cache") == 0) {
+ if (cache_dbi == NULL)
+ printf("the cache does not exist\n");
+ return (cache_dbi);
+ }
+ len = strlen(origintext);
+ isc_buffer_init(&source, origintext, len);
+ isc_buffer_add(&source, len);
+ dns_fixedname_init(&forigin);
+ origin = dns_fixedname_name(&forigin);
+ result = dns_name_fromtext(origin, &source, dns_rootname, ISC_FALSE,
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ print_result("bad name", result);
+ return (NULL);
+ }
+
+ for (dbi = ISC_LIST_HEAD(dbs);
+ dbi != NULL;
+ dbi = ISC_LIST_NEXT(dbi, link)) {
+ if (dns_name_compare(dns_db_origin(dbi->db), origin) == 0)
+ break;
+ }
+
+ return (dbi);
+}
+
+static void
+list(dbinfo *dbi, char *seektext) {
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ dns_dbnode_t *node;
+ dns_rdatasetiter_t *rdsiter;
+ isc_result_t result;
+ int i;
+ size_t len;
+ dns_fixedname_t fseekname;
+ dns_name_t *seekname;
+ isc_buffer_t source;
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+
+ if (dbi->dbiterator == NULL) {
+ INSIST(dbi->iversion == NULL);
+ if (dns_db_iszone(dbi->db)) {
+ if (dbi->version != NULL)
+ dns_db_attachversion(dbi->db, dbi->version,
+ &dbi->iversion);
+ else
+ dns_db_currentversion(dbi->db, &dbi->iversion);
+ }
+
+ result = dns_db_createiterator(dbi->db, 0, &dbi->dbiterator);
+ if (result == ISC_R_SUCCESS) {
+ if (seektext != NULL) {
+ len = strlen(seektext);
+ isc_buffer_init(&source, seektext, len);
+ isc_buffer_add(&source, len);
+ dns_fixedname_init(&fseekname);
+ seekname = dns_fixedname_name(&fseekname);
+ result = dns_name_fromtext(seekname, &source,
+ dns_db_origin(
+ dbi->db),
+ ISC_FALSE,
+ NULL);
+ if (result == ISC_R_SUCCESS)
+ result = dns_dbiterator_seek(
+ dbi->dbiterator,
+ seekname);
+ } else if (dbi->ascending)
+ result = dns_dbiterator_first(dbi->dbiterator);
+ else
+ result = dns_dbiterator_last(dbi->dbiterator);
+ }
+ } else
+ result = ISC_R_SUCCESS;
+
+ node = NULL;
+ rdsiter = NULL;
+ i = 0;
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbi->dbiterator, &node, name);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+ break;
+ result = dns_db_allrdatasets(dbi->db, node, dbi->iversion, 0,
+ &rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(dbi->db, &node);
+ break;
+ }
+ print_rdatasets(name, rdsiter);
+ dns_rdatasetiter_destroy(&rdsiter);
+ dns_db_detachnode(dbi->db, &node);
+ if (dbi->ascending)
+ result = dns_dbiterator_next(dbi->dbiterator);
+ else
+ result = dns_dbiterator_prev(dbi->dbiterator);
+ i++;
+ if (result == ISC_R_SUCCESS && i == dbi->pause_every) {
+ printf("[more...]\n");
+ result = dns_dbiterator_pause(dbi->dbiterator);
+ if (result == ISC_R_SUCCESS)
+ return;
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ print_result("", result);
+
+ dns_dbiterator_destroy(&dbi->dbiterator);
+ if (dbi->iversion != NULL)
+ dns_db_closeversion(dbi->db, &dbi->iversion, ISC_FALSE);
+}
+
+static isc_result_t
+load(const char *filename, const char *origintext, isc_boolean_t cache) {
+ dns_fixedname_t forigin;
+ dns_name_t *origin;
+ isc_result_t result;
+ isc_buffer_t source;
+ size_t len;
+ dbinfo *dbi;
+ unsigned int i;
+
+ dbi = isc_mem_get(mctx, sizeof(*dbi));
+ if (dbi == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dbi->db = NULL;
+ dbi->version = NULL;
+ dbi->wversion = NULL;
+ for (i = 0; i < MAXVERSIONS; i++)
+ dbi->rversions[i] = NULL;
+ dbi->hold_count = 0;
+ for (i = 0; i < MAXHOLD; i++)
+ dbi->hold_nodes[i] = NULL;
+ dbi->dbiterator = NULL;
+ dbi->iversion = NULL;
+ dbi->pause_every = pause_every;
+ dbi->ascending = ascending;
+ ISC_LINK_INIT(dbi, link);
+
+ len = strlen(origintext);
+ isc_buffer_init(&source, origintext, len);
+ isc_buffer_add(&source, len);
+ dns_fixedname_init(&forigin);
+ origin = dns_fixedname_name(&forigin);
+ result = dns_name_fromtext(origin, &source, dns_rootname, ISC_FALSE,
+ NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_create(mctx, dbtype, origin,
+ cache ? dns_dbtype_cache : dns_dbtype_zone,
+ dns_rdataclass_in,
+ 0, NULL, &dbi->db);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+
+ printf("loading %s (%s)\n", filename, origintext);
+ result = dns_db_load(dbi->db, filename);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
+ dns_db_detach(&dbi->db);
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+ printf("loaded\n");
+
+ if (cache) {
+ INSIST(cache_dbi == NULL);
+ dns_dbtable_adddefault(dbtable, dbi->db);
+ cache_dbi = dbi;
+ } else {
+ if (dns_dbtable_add(dbtable, dbi->db) != ISC_R_SUCCESS) {
+ dns_db_detach(&dbi->db);
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+ }
+ ISC_LIST_APPEND(dbs, dbi, link);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+unload_all(void) {
+ dbinfo *dbi, *dbi_next;
+
+ for (dbi = ISC_LIST_HEAD(dbs); dbi != NULL; dbi = dbi_next) {
+ dbi_next = ISC_LIST_NEXT(dbi, link);
+ if (dns_db_iszone(dbi->db))
+ dns_dbtable_remove(dbtable, dbi->db);
+ else {
+ INSIST(dbi == cache_dbi);
+ dns_dbtable_removedefault(dbtable);
+ cache_dbi = NULL;
+ }
+ dns_db_detach(&dbi->db);
+ ISC_LIST_UNLINK(dbs, dbi, link);
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ }
+}
+
+#define DBI_CHECK(dbi) \
+if ((dbi) == NULL) { \
+ printf("You must first select a database with !DB\n"); \
+ continue; \
+}
+
+int
+main(int argc, char *argv[]) {
+ dns_db_t *db;
+ dns_dbnode_t *node;
+ isc_result_t result;
+ dns_name_t name;
+ dns_offsets_t offsets;
+ size_t len;
+ isc_buffer_t source, target;
+ char s[1000];
+ char b[255];
+ dns_rdataset_t rdataset, sigrdataset;
+ int ch;
+ dns_rdatatype_t type = 1;
+ isc_boolean_t printnode = ISC_FALSE;
+ isc_boolean_t addmode = ISC_FALSE;
+ isc_boolean_t delmode = ISC_FALSE;
+ isc_boolean_t holdmode = ISC_FALSE;
+ isc_boolean_t verbose = ISC_FALSE;
+ isc_boolean_t done = ISC_FALSE;
+ isc_boolean_t quiet = ISC_FALSE;
+ isc_boolean_t time_lookups = ISC_FALSE;
+ isc_boolean_t found_as;
+ isc_boolean_t find_zonecut = ISC_FALSE;
+ isc_boolean_t noexact_zonecut = ISC_FALSE;
+ int i, v;
+ dns_rdatasetiter_t *rdsiter;
+ char t1[256];
+ char t2[256];
+ isc_buffer_t tb1, tb2;
+ isc_region_t r1, r2;
+ dns_fixedname_t foundname;
+ dns_name_t *fname;
+ unsigned int options = 0, zcoptions;
+ isc_time_t start, finish;
+ char *origintext;
+ dbinfo *dbi;
+ dns_dbversion_t *version;
+ dns_name_t *origin;
+ size_t memory_quota = 0;
+ dns_trust_t trust = 0;
+ unsigned int addopts;
+ isc_log_t *lctx = NULL;
+
+ dns_result_register();
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_dbtable_create(mctx, dns_rdataclass_in, &dbtable) ==
+ ISC_R_SUCCESS);
+
+
+
+ strcpy(dbtype, "rbt");
+ while ((ch = isc_commandline_parse(argc, argv, "c:d:t:z:P:Q:glpqvT"))
+ != -1) {
+ switch (ch) {
+ case 'c':
+ result = load(isc_commandline_argument, ".", ISC_TRUE);
+ if (result != ISC_R_SUCCESS)
+ printf("cache load(%s) %08x: %s\n",
+ isc_commandline_argument, result,
+ isc_result_totext(result));
+ break;
+ case 'd':
+ strcpy(dbtype, isc_commandline_argument);
+ break;
+ case 'g':
+ options |= (DNS_DBFIND_GLUEOK|DNS_DBFIND_VALIDATEGLUE);
+ break;
+ case 'l':
+ RUNTIME_CHECK(isc_log_create(mctx, &lctx,
+ NULL) == ISC_R_SUCCESS);
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+ break;
+ case 'q':
+ quiet = ISC_TRUE;
+ verbose = ISC_FALSE;
+ break;
+ case 'p':
+ printnode = ISC_TRUE;
+ break;
+ case 'P':
+ pause_every = atoi(isc_commandline_argument);
+ break;
+ case 'Q':
+ memory_quota = atoi(isc_commandline_argument);
+ isc_mem_setquota(mctx, memory_quota);
+ break;
+ case 't':
+ type = atoi(isc_commandline_argument);
+ break;
+ case 'T':
+ time_lookups = ISC_TRUE;
+ break;
+ case 'v':
+ verbose = ISC_TRUE;
+ break;
+ case 'z':
+ origintext = strrchr(isc_commandline_argument, '/');
+ if (origintext == NULL)
+ origintext = isc_commandline_argument;
+ else
+ origintext++; /* Skip '/'. */
+ result = load(isc_commandline_argument, origintext,
+ ISC_FALSE);
+ if (result != ISC_R_SUCCESS)
+ printf("zone load(%s) %08x: %s\n",
+ isc_commandline_argument, result,
+ isc_result_totext(result));
+ break;
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc != 0)
+ printf("ignoring trailing arguments\n");
+
+ /*
+ * Some final initialization...
+ */
+ dns_fixedname_init(&foundname);
+ fname = dns_fixedname_name(&foundname);
+ dbi = NULL;
+ origin = dns_rootname;
+ version = NULL;
+
+ if (time_lookups) {
+ TIME_NOW(&start);
+ }
+
+ while (!done) {
+ if (!quiet)
+ printf("\n");
+ if (fgets(s, sizeof(s), stdin) == NULL) {
+ done = ISC_TRUE;
+ continue;
+ }
+ len = strlen(s);
+ if (len > 0U && s[len - 1] == '\n') {
+ s[len - 1] = '\0';
+ len--;
+ }
+ if (verbose && dbi != NULL) {
+ if (dbi->wversion != NULL)
+ printf("future version (%p)\n", dbi->wversion);
+ for (i = 0; i < dbi->rcount; i++)
+ if (dbi->rversions[i] != NULL)
+ printf("open version %d (%p)\n", i,
+ dbi->rversions[i]);
+ }
+ dns_name_init(&name, offsets);
+ if (strcmp(s, "!R") == 0) {
+ DBI_CHECK(dbi);
+ if (dbi->rcount == MAXVERSIONS) {
+ printf("too many open versions\n");
+ continue;
+ }
+ dns_db_currentversion(dbi->db,
+ &dbi->rversions[dbi->rcount]);
+ printf("opened version %d\n", dbi->rcount);
+ dbi->version = dbi->rversions[dbi->rcount];
+ version = dbi->version;
+ dbi->rcount++;
+ continue;
+ } else if (strcmp(s, "!W") == 0) {
+ DBI_CHECK(dbi);
+ if (dbi->wversion != NULL) {
+ printf("using existing future version\n");
+ dbi->version = dbi->wversion;
+ version = dbi->version;
+ continue;
+ }
+ result = dns_db_newversion(dbi->db, &dbi->wversion);
+ if (result != ISC_R_SUCCESS)
+ print_result("", result);
+ else
+ printf("newversion\n");
+ dbi->version = dbi->wversion;
+ version = dbi->version;
+ continue;
+ } else if (strcmp(s, "!C") == 0) {
+ DBI_CHECK(dbi);
+ addmode = ISC_FALSE;
+ delmode = ISC_FALSE;
+ if (dbi->version == NULL)
+ continue;
+ if (dbi->version == dbi->wversion) {
+ printf("closing future version\n");
+ dbi->wversion = NULL;
+ } else {
+ for (i = 0; i < dbi->rcount; i++) {
+ if (dbi->version ==
+ dbi->rversions[i]) {
+ dbi->rversions[i] = NULL;
+ printf("closing open version %d\n",
+ i);
+ break;
+ }
+ }
+ }
+ dns_db_closeversion(dbi->db, &dbi->version, ISC_TRUE);
+ version = NULL;
+ continue;
+ } else if (strcmp(s, "!X") == 0) {
+ DBI_CHECK(dbi);
+ addmode = ISC_FALSE;
+ delmode = ISC_FALSE;
+ if (dbi->version == NULL)
+ continue;
+ if (dbi->version == dbi->wversion) {
+ printf("aborting future version\n");
+ dbi->wversion = NULL;
+ } else {
+ for (i = 0; i < dbi->rcount; i++) {
+ if (dbi->version ==
+ dbi->rversions[i]) {
+ dbi->rversions[i] = NULL;
+ printf("closing open version %d\n",
+ i);
+ break;
+ }
+ }
+ }
+ dns_db_closeversion(dbi->db, &dbi->version, ISC_FALSE);
+ version = NULL;
+ continue;
+ } else if (strcmp(s, "!A") == 0) {
+ DBI_CHECK(dbi);
+ delmode = ISC_FALSE;
+ if (addmode)
+ addmode = ISC_FALSE;
+ else
+ addmode = ISC_TRUE;
+ printf("addmode = %s\n", addmode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!D") == 0) {
+ DBI_CHECK(dbi);
+ addmode = ISC_FALSE;
+ if (delmode)
+ delmode = ISC_FALSE;
+ else
+ delmode = ISC_TRUE;
+ printf("delmode = %s\n", delmode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!H") == 0) {
+ DBI_CHECK(dbi);
+ if (holdmode)
+ holdmode = ISC_FALSE;
+ else
+ holdmode = ISC_TRUE;
+ printf("holdmode = %s\n", holdmode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!HR") == 0) {
+ DBI_CHECK(dbi);
+ for (i = 0; i < dbi->hold_count; i++)
+ dns_db_detachnode(dbi->db,
+ &dbi->hold_nodes[i]);
+ dbi->hold_count = 0;
+ holdmode = ISC_FALSE;
+ printf("held nodes have been detached\n");
+ continue;
+ } else if (strcmp(s, "!VC") == 0) {
+ DBI_CHECK(dbi);
+ printf("switching to current version\n");
+ dbi->version = NULL;
+ version = NULL;
+ continue;
+ } else if (strstr(s, "!V") == s) {
+ DBI_CHECK(dbi);
+ v = atoi(&s[2]);
+ if (v >= dbi->rcount) {
+ printf("unknown open version %d\n", v);
+ continue;
+ } else if (dbi->rversions[v] == NULL) {
+ printf("version %d is not open\n", v);
+ continue;
+ }
+ printf("switching to open version %d\n", v);
+ dbi->version = dbi->rversions[v];
+ version = dbi->version;
+ continue;
+ } else if (strstr(s, "!TR") == s) {
+ trust = (unsigned int)atoi(&s[3]);
+ printf("trust level is now %u\n", (unsigned int)trust);
+ continue;
+ } else if (strstr(s, "!T") == s) {
+ type = (unsigned int)atoi(&s[2]);
+ printf("now searching for type %u\n", type);
+ continue;
+ } else if (strcmp(s, "!G") == 0) {
+ if ((options & DNS_DBFIND_GLUEOK) != 0)
+ options &= ~DNS_DBFIND_GLUEOK;
+ else
+ options |= DNS_DBFIND_GLUEOK;
+ printf("glue ok = %s\n",
+ ((options & DNS_DBFIND_GLUEOK) != 0) ?
+ "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!GV") == 0) {
+ if ((options & DNS_DBFIND_VALIDATEGLUE) != 0)
+ options &= ~DNS_DBFIND_VALIDATEGLUE;
+ else
+ options |= DNS_DBFIND_VALIDATEGLUE;
+ printf("validate glue = %s\n",
+ ((options & DNS_DBFIND_VALIDATEGLUE) != 0) ?
+ "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!WC") == 0) {
+ if ((options & DNS_DBFIND_NOWILD) != 0)
+ options &= ~DNS_DBFIND_NOWILD;
+ else
+ options |= DNS_DBFIND_NOWILD;
+ printf("wildcard matching = %s\n",
+ ((options & DNS_DBFIND_NOWILD) == 0) ?
+ "TRUE" : "FALSE");
+ continue;
+ } else if (strstr(s, "!LS ") == s) {
+ DBI_CHECK(dbi);
+ list(dbi, &s[4]);
+ continue;
+ } else if (strcmp(s, "!LS") == 0) {
+ DBI_CHECK(dbi);
+ list(dbi, NULL);
+ continue;
+ } else if (strstr(s, "!DU ") == s) {
+ DBI_CHECK(dbi);
+ result = dns_db_dump(dbi->db, dbi->version, s+4);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n");
+ print_result("", result);
+ }
+ continue;
+ } else if (strcmp(s, "!PN") == 0) {
+ if (printnode)
+ printnode = ISC_FALSE;
+ else
+ printnode = ISC_TRUE;
+ printf("printnode = %s\n",
+ printnode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strstr(s, "!P") == s) {
+ DBI_CHECK(dbi);
+ v = atoi(&s[2]);
+ dbi->pause_every = v;
+ continue;
+ } else if (strcmp(s, "!+") == 0) {
+ DBI_CHECK(dbi);
+ dbi->ascending = ISC_TRUE;
+ continue;
+ } else if (strcmp(s, "!-") == 0) {
+ DBI_CHECK(dbi);
+ dbi->ascending = ISC_FALSE;
+ continue;
+ } else if (strcmp(s, "!DB") == 0) {
+ dbi = NULL;
+ origin = dns_rootname;
+ version = NULL;
+ printf("now searching all databases\n");
+ continue;
+ } else if (strncmp(s, "!DB ", 4) == 0) {
+ dbi = select_db(s+4);
+ if (dbi != NULL) {
+ db = dbi->db;
+ origin = dns_db_origin(dbi->db);
+ version = dbi->version;
+ addmode = ISC_FALSE;
+ delmode = ISC_FALSE;
+ holdmode = ISC_FALSE;
+ } else {
+ db = NULL;
+ version = NULL;
+ origin = dns_rootname;
+ printf("database not found; "
+ "now searching all databases\n");
+ }
+ continue;
+ } else if (strcmp(s, "!ZC") == 0) {
+ if (find_zonecut)
+ find_zonecut = ISC_FALSE;
+ else
+ find_zonecut = ISC_TRUE;
+ printf("find_zonecut = %s\n",
+ find_zonecut ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!NZ") == 0) {
+ if (noexact_zonecut)
+ noexact_zonecut = ISC_FALSE;
+ else
+ noexact_zonecut = ISC_TRUE;
+ printf("noexact_zonecut = %s\n",
+ noexact_zonecut ? "TRUE" : "FALSE");
+ continue;
+ }
+
+ isc_buffer_init(&source, s, len);
+ isc_buffer_add(&source, len);
+ isc_buffer_init(&target, b, sizeof(b));
+ result = dns_name_fromtext(&name, &source, origin,
+ ISC_FALSE, &target);
+ if (result != ISC_R_SUCCESS) {
+ print_result("bad name: ", result);
+ continue;
+ }
+
+ if (dbi == NULL) {
+ zcoptions = 0;
+ if (noexact_zonecut)
+ zcoptions |= DNS_DBTABLEFIND_NOEXACT;
+ db = NULL;
+ result = dns_dbtable_find(dbtable, &name, zcoptions,
+ &db);
+ if (result != ISC_R_SUCCESS &&
+ result != DNS_R_PARTIALMATCH) {
+ if (!quiet) {
+ printf("\n");
+ print_result("", result);
+ }
+ continue;
+ }
+ isc_buffer_init(&tb1, t1, sizeof(t1));
+ result = dns_name_totext(dns_db_origin(db), ISC_FALSE,
+ &tb1);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n");
+ print_result("", result);
+ dns_db_detach(&db);
+ continue;
+ }
+ isc_buffer_usedregion(&tb1, &r1);
+ printf("\ndatabase = %.*s (%s)\n",
+ (int)r1.length, r1.base,
+ (dns_db_iszone(db)) ? "zone" : "cache");
+ }
+ node = NULL;
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&sigrdataset);
+
+ if (find_zonecut && dns_db_iscache(db)) {
+ zcoptions = options;
+ if (noexact_zonecut)
+ zcoptions |= DNS_DBFIND_NOEXACT;
+ result = dns_db_findzonecut(db, &name, zcoptions,
+ 0, &node, fname,
+ &rdataset, &sigrdataset);
+ } else {
+ result = dns_db_find(db, &name, version, type,
+ options, 0, &node, fname,
+ &rdataset, &sigrdataset);
+ }
+
+ if (!quiet) {
+ if (dbi != NULL)
+ printf("\n");
+ print_result("", result);
+ }
+
+ found_as = ISC_FALSE;
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_GLUE:
+ case DNS_R_CNAME:
+ case DNS_R_ZONECUT:
+ break;
+ case DNS_R_DNAME:
+ case DNS_R_DELEGATION:
+ found_as = ISC_TRUE;
+ break;
+ case DNS_R_NXRRSET:
+ if (dns_rdataset_isassociated(&rdataset))
+ break;
+ if (dbi != NULL) {
+ if (holdmode) {
+ RUNTIME_CHECK(dbi->hold_count <
+ MAXHOLD);
+ dbi->hold_nodes[dbi->hold_count++] =
+ node;
+ node = NULL;
+ } else
+ dns_db_detachnode(db, &node);
+ } else {
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ }
+ continue;
+ case DNS_R_NXDOMAIN:
+ if (dns_rdataset_isassociated(&rdataset))
+ break;
+ /* FALLTHROUGH */
+ default:
+ if (dbi == NULL)
+ dns_db_detach(&db);
+ if (quiet)
+ print_result("", result);
+ continue;
+ }
+ if (found_as && !quiet) {
+ isc_buffer_init(&tb1, t1, sizeof(t1));
+ isc_buffer_init(&tb2, t2, sizeof(t2));
+ result = dns_name_totext(&name, ISC_FALSE, &tb1);
+ if (result != ISC_R_SUCCESS) {
+ print_result("", result);
+ dns_db_detachnode(db, &node);
+ if (dbi == NULL)
+ dns_db_detach(&db);
+ continue;
+ }
+ result = dns_name_totext(fname, ISC_FALSE, &tb2);
+ if (result != ISC_R_SUCCESS) {
+ print_result("", result);
+ dns_db_detachnode(db, &node);
+ if (dbi == NULL)
+ dns_db_detach(&db);
+ continue;
+ }
+ isc_buffer_usedregion(&tb1, &r1);
+ isc_buffer_usedregion(&tb2, &r2);
+ printf("found %.*s as %.*s\n",
+ (int)r1.length, r1.base,
+ (int)r2.length, r2.base);
+ }
+
+ if (printnode)
+ dns_db_printnode(db, node, stdout);
+
+ if (!found_as && type == dns_rdatatype_any) {
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, version, 0,
+ &rdsiter);
+ if (result == ISC_R_SUCCESS) {
+ if (!quiet)
+ print_rdatasets(fname, rdsiter);
+ dns_rdatasetiter_destroy(&rdsiter);
+ } else
+ print_result("", result);
+ } else {
+ if (!quiet)
+ print_rdataset(fname, &rdataset);
+ if (dns_rdataset_isassociated(&sigrdataset)) {
+ if (!quiet)
+ print_rdataset(fname, &sigrdataset);
+ dns_rdataset_disassociate(&sigrdataset);
+ }
+ if (dbi != NULL && addmode && !found_as) {
+ rdataset.ttl++;
+ rdataset.trust = trust;
+ if (dns_db_iszone(db))
+ addopts = DNS_DBADD_MERGE;
+ else
+ addopts = 0;
+ result = dns_db_addrdataset(db, node, version,
+ 0, &rdataset,
+ addopts, NULL);
+ if (result != ISC_R_SUCCESS)
+ print_result("", result);
+ if (printnode)
+ dns_db_printnode(db, node, stdout);
+ } else if (dbi != NULL && delmode && !found_as) {
+ result = dns_db_deleterdataset(db, node,
+ version, type,
+ 0);
+ if (result != ISC_R_SUCCESS)
+ print_result("", result);
+ if (printnode)
+ dns_db_printnode(db, node, stdout);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ }
+
+ if (dbi != NULL) {
+ if (holdmode) {
+ RUNTIME_CHECK(dbi->hold_count < MAXHOLD);
+ dbi->hold_nodes[dbi->hold_count++] = node;
+ node = NULL;
+ } else
+ dns_db_detachnode(db, &node);
+ } else {
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ }
+ }
+
+ if (time_lookups) {
+ isc_uint64_t usec;
+
+ TIME_NOW(&finish);
+
+ usec = isc_time_microdiff(&finish, &start);
+
+ printf("elapsed time: %lu.%06lu seconds\n",
+ (unsigned long)(usec / 1000000),
+ (unsigned long)(usec % 1000000));
+ }
+
+ unload_all();
+
+ dns_dbtable_detach(&dbtable);
+
+ if (lctx != NULL)
+ isc_log_destroy(&lctx);
+
+ if (!quiet)
+ isc_mem_stats(mctx, stdout);
+
+ return (0);
+}
diff --git a/bin/tests/dst/Kdh.+002+18602.key b/bin/tests/dst/Kdh.+002+18602.key
new file mode 100644
index 0000000..09b4cf5
--- /dev/null
+++ b/bin/tests/dst/Kdh.+002+18602.key
@@ -0,0 +1 @@
+dh. IN KEY 0 2 2 AAEBAAAAYIHI/wjtOagNga9GILSoS02IVelgLilPE/TfhtvShsiDAXqb IfxQcj2JkuOnNLs5ttb2WZXWl5/jsSjIxHMwMF2XY4gwt/lwHBf/vgYH r7aIxnKXov1jk9rymTLHGKIOtg==
diff --git a/bin/tests/dst/Kdh.+002+18602.private b/bin/tests/dst/Kdh.+002+18602.private
new file mode 100644
index 0000000..a2245bf
--- /dev/null
+++ b/bin/tests/dst/Kdh.+002+18602.private
@@ -0,0 +1,6 @@
+Private-key-format: v1.2
+Algorithm: 2 (DH)
+Prime(p): ///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjo2IP//////////
+Generator(g): Ag==
+Private_value(x): bpdsGQ1jbV3f2CGN/0Pk5KM1MlkFmMryPO1J1zoGn585fRmc9Ygw6l/HKmi2ViiDNorvd9/eV9uyYO6lYZC82R3D7rST1mAqCwbg/8gNE5dXBRbRIIq3qIl6GUYYs8mK
+Public_value(y): gcj/CO05qA2Br0YgtKhLTYhV6WAuKU8T9N+G29KGyIMBepsh/FByPYmS46c0uzm21vZZldaXn+OxKMjEczAwXZdjiDC3+XAcF/++BgevtojGcpei/WOT2vKZMscYog62
diff --git a/bin/tests/dst/Kdh.+002+48957.key b/bin/tests/dst/Kdh.+002+48957.key
new file mode 100644
index 0000000..9838829
--- /dev/null
+++ b/bin/tests/dst/Kdh.+002+48957.key
@@ -0,0 +1 @@
+dh. IN KEY 0 2 2 AAEBAAAAYOuaKjyMXYame2F6/ZFdEmXv0a2edB+69PEZgrExA6SJlivn 4KqAsfBHr/+0BCb+7nfWeMDSh2BXnSzWkXF1wMaCHMuz9EleG1gKFKeV Q9gKli88Cb8/jbovWChrGBNp2w==
diff --git a/bin/tests/dst/Kdh.+002+48957.private b/bin/tests/dst/Kdh.+002+48957.private
new file mode 100644
index 0000000..e191235
--- /dev/null
+++ b/bin/tests/dst/Kdh.+002+48957.private
@@ -0,0 +1,6 @@
+Private-key-format: v1.2
+Algorithm: 2 (DH)
+Prime(p): ///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjo2IP//////////
+Generator(g): Ag==
+Private_value(x): WJG0moh+QoZV+DYhqW7Z6O6TYpYGtSlN0Ym6JV6VRnzeH69OqMUFivqZorj3a3ofR/4zogNVyy5KLLj2NFTaLGP4Hcvt7uETJik6HrjLMhGf40QPXYgVK57Im0rv88Ca
+Public_value(y): 65oqPIxdhqZ7YXr9kV0SZe/RrZ50H7r08RmCsTEDpImWK+fgqoCx8Eev/7QEJv7ud9Z4wNKHYFedLNaRcXXAxoIcy7P0SV4bWAoUp5VD2AqWLzwJvz+Nui9YKGsYE2nb
diff --git a/bin/tests/dst/Ktest.+001+00002.key b/bin/tests/dst/Ktest.+001+00002.key
new file mode 100644
index 0000000..a8b4b4d
--- /dev/null
+++ b/bin/tests/dst/Ktest.+001+00002.key
@@ -0,0 +1 @@
+test. IN DNSKEY 49152 2 1
diff --git a/bin/tests/dst/Ktest.+001+54622.key b/bin/tests/dst/Ktest.+001+54622.key
new file mode 100644
index 0000000..b0277e3
--- /dev/null
+++ b/bin/tests/dst/Ktest.+001+54622.key
@@ -0,0 +1 @@
+test. IN DNSKEY 257 3 1 AQPQjwSpaVzxIgRCpiUoozUQKGh2oX8NIFKDOvtxK+tn536OZg2cROKTlgGEHXJK9YHfW/6nzQULTVpb63P+SQMmjCCidb8IYyhItixRztVeJQ==
diff --git a/bin/tests/dst/Ktest.+001+54622.private b/bin/tests/dst/Ktest.+001+54622.private
new file mode 100644
index 0000000..c97ac30
--- /dev/null
+++ b/bin/tests/dst/Ktest.+001+54622.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 1 (RSA)
+Modulus: 0I8EqWlc8SIEQqYlKKM1EChodqF/DSBSgzr7cSvrZ+d+jmYNnETik5YBhB1ySvWB31v+p80FC01aW+tz/kkDJowgonW/CGMoSLYsUc7VXiU=
+PublicExponent: Aw==
+PrivateExponent: iwoDG5uTS2wC1xluGxd4tXBFpGuqCMA3AidSS3Kc7++ptEQJEtiXC9kfCJMvZhGfQLaujft2OgrmkcuDVtPIbQWEENhyJhb4Lk82kFXbfus=
+Prime1: /rSKuzcZY7R5cY2YWD4CiBNyj9WJMq1wWmBnb9+5M08nTl5E9NW5qQ==
+Prime2: 0Z5shXQYd16E2Gs6e5WxtO0Oqlly2KkSqXohwTQWDWTb8Pw0WTZmHQ==
+Exponent1: qc2x0iS7l82mS7O65X6sWrehtTkGIcj1kZWaSpUmIjTE3umDTePRGw==
+Exponent2: i77zA6K6+j8DOvIm/Q52eJ4JxuZMkHC3G6bBK3gOs5iSoKgi5iREEw==
+Coefficient: 3+wYZB0SJad7z2EsjzgbSlg6CawoaOvrROGSbwSiW5DCsMFROudOTw==
diff --git a/bin/tests/dst/Ktest.+003+23616.key b/bin/tests/dst/Ktest.+003+23616.key
new file mode 100644
index 0000000..958d585
--- /dev/null
+++ b/bin/tests/dst/Ktest.+003+23616.key
@@ -0,0 +1 @@
+test. IN DNSKEY 16641 3 3 ANp1//lqDlEfTavcFI+cyudNfgEz73V/K7fSDvkA0eDYcGg/kSvEjAEO/oLWCERltkuC55ZcM/mSv17WF1d/wR6kww/pLI9eXwkjftAYqs5sNxk+mbEGl6zwve9wq5z7IoTY5/J4l7XLCKftg/wGvrzXQhggIkRvEh3myhxd+ouILcpfvTIthWlTKiH59tSJpmgmiSMTE7nDYaf10iVRWN6DMSprgejiH05/fpmyZAt44tyAh4m1wXS5u4tam1PXDJYJozn7EfQ8e2weIv1yC+t6PHSx
diff --git a/bin/tests/dst/Ktest.+003+23616.private b/bin/tests/dst/Ktest.+003+23616.private
new file mode 100644
index 0000000..5781c9d
--- /dev/null
+++ b/bin/tests/dst/Ktest.+003+23616.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.2
+Algorithm: 3 (DSA)
+Prime(p): 73V/K7fSDvkA0eDYcGg/kSvEjAEO/oLWCERltkuC55ZcM/mSv17WF1d/wR6kww/pLI9eXwkjftAYqs5sNxk+mQ==
+Subprime(q): 2nX/+WoOUR9Nq9wUj5zK501+ATM=
+Base(g): sQaXrPC973CrnPsihNjn8niXtcsIp+2D/Aa+vNdCGCAiRG8SHebKHF36i4gtyl+9Mi2FaVMqIfn21ImmaCaJIw==
+Private_value(x): Nky4tvIwg6xlcyeHXr4k2DEZg0E=
+Public_value(y): ExO5w2Gn9dIlUVjegzEqa4Ho4h9Of36ZsmQLeOLcgIeJtcF0ubuLWptT1wyWCaM5+xH0PHtsHiL9cgvrejx0sQ==
diff --git a/bin/tests/dst/Ktest.+003+49667.key b/bin/tests/dst/Ktest.+003+49667.key
new file mode 100644
index 0000000..fb73f57
--- /dev/null
+++ b/bin/tests/dst/Ktest.+003+49667.key
@@ -0,0 +1 @@
+test. IN DNSKEY 49152 2 3
diff --git a/bin/tests/dst/Makefile.in b/bin/tests/dst/Makefile.in
new file mode 100644
index 0000000..9b317fc
--- /dev/null
+++ b/bin/tests/dst/Makefile.in
@@ -0,0 +1,65 @@
+# Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-2002 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.46 2008/05/19 23:47:03 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} \
+ ${ISC_INCLUDES} @DST_GSSAPI_INC@
+
+CDEFINES =
+CWARNINGS =
+
+DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../../lib/isc/libisc.@A@
+
+DNSDEPLIBS = ../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+TLIB = ../../../lib/tests/libt_api.@A@
+
+TARGETS = dst_test@EXEEXT@ t_dst@EXEEXT@ gsstest@EXEEXT@
+
+SRCS = dst_test.c t_dst.c gsstest.c
+
+@BIND9_MAKE_RULES@
+
+dst_test@EXEEXT@: dst_test.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dst_test.@O@ ${LIBS}
+
+t_dst@EXEEXT@: t_dst.@O@ ${DEPLIBS} ${TLIB}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ t_dst.@O@ ${TLIB} ${LIBS}
+
+gsstest@EXEEXT@: gsstest.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ gsstest.@O@ ${LIBS}
+
+test: t_dst@EXEEXT@
+ ../genrandom@EXEEXT@ 100 randomfile
+ -@ ./t_dst@EXEEXT@ -b @srcdir@ -q 1800 -a
+
+clean distclean::
+ rm -f ${TARGETS} randomfile
diff --git a/bin/tests/dst/dst_2_data b/bin/tests/dst/dst_2_data
new file mode 100644
index 0000000..a303065
--- /dev/null
+++ b/bin/tests/dst/dst_2_data
@@ -0,0 +1,16 @@
+#
+# data for signature verification test
+#
+# format:
+# datafile, sigpath, keyname, keyid, alg, exp_result
+#
+t2_data_1 t2_dsasig test. 23616 DST_ALG_DSA ISC_R_SUCCESS
+t2_data_1 t2_rsasig test. 54622 DST_ALG_RSAMD5 ISC_R_SUCCESS
+# wrong sig
+t2_data_1 t2_dsasig test. 54622 DST_ALG_RSAMD5 !ISC_R_SUCCESS
+# wrong key
+#t2_data_1 t2_dsasig test. 54622 DST_ALG_DSA !ISC_R_SUCCESS
+# wrong alg
+#t2_data_1 t2_dsasig test. 23616 DST_ALG_RSAMD5 !ISC_R_SUCCESS
+# wrong data
+t2_data_2 t2_dsasig test. 23616 DST_ALG_DSA !ISC_R_SUCCESS
diff --git a/bin/tests/dst/dst_test.c b/bin/tests/dst/dst_test.c
new file mode 100644
index 0000000..8347a7d
--- /dev/null
+++ b/bin/tests/dst/dst_test.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: dst_test.c,v 1.43 2007/06/19 23:47:00 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <unistd.h> /* XXX */
+
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+#include <dst/result.h>
+
+char *current;
+const char *tmp = "/tmp";
+
+static void
+use(dst_key_t *key, isc_mem_t *mctx) {
+ isc_result_t ret;
+ const char *data = "This is some data";
+ unsigned char sig[512];
+ isc_buffer_t databuf, sigbuf;
+ isc_region_t datareg, sigreg;
+ dst_context_t *ctx = NULL;
+
+ isc_buffer_init(&sigbuf, sig, sizeof(sig));
+ /*
+ * Advance 1 byte for fun.
+ */
+ isc_buffer_add(&sigbuf, 1);
+
+ isc_buffer_init(&databuf, data, strlen(data));
+ isc_buffer_add(&databuf, strlen(data));
+ isc_buffer_usedregion(&databuf, &datareg);
+
+ ret = dst_context_create(key, mctx, &ctx);
+ if (ret != ISC_R_SUCCESS) {
+ printf("contextcreate(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ return;
+ }
+ ret = dst_context_adddata(ctx, &datareg);
+ if (ret != ISC_R_SUCCESS) {
+ printf("adddata(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ dst_context_destroy(&ctx);
+ return;
+ }
+ ret = dst_context_sign(ctx, &sigbuf);
+ printf("sign(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ dst_context_destroy(&ctx);
+
+ isc_buffer_forward(&sigbuf, 1);
+ isc_buffer_remainingregion(&sigbuf, &sigreg);
+ ret = dst_context_create(key, mctx, &ctx);
+ if (ret != ISC_R_SUCCESS) {
+ printf("contextcreate(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ return;
+ }
+ ret = dst_context_adddata(ctx, &datareg);
+ if (ret != ISC_R_SUCCESS) {
+ printf("adddata(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ dst_context_destroy(&ctx);
+ return;
+ }
+ ret = dst_context_verify(ctx, &sigreg);
+ printf("verify(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ dst_context_destroy(&ctx);
+}
+
+static void
+dns(dst_key_t *key, isc_mem_t *mctx) {
+ unsigned char buffer1[2048];
+ unsigned char buffer2[2048];
+ isc_buffer_t buf1, buf2;
+ isc_region_t r1, r2;
+ dst_key_t *newkey = NULL;
+ isc_result_t ret;
+ isc_boolean_t match;
+
+ isc_buffer_init(&buf1, buffer1, sizeof(buffer1));
+ ret = dst_key_todns(key, &buf1);
+ printf("todns(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ if (ret != ISC_R_SUCCESS)
+ return;
+ ret = dst_key_fromdns(dst_key_name(key), dns_rdataclass_in,
+ &buf1, mctx, &newkey);
+ printf("fromdns(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ if (ret != ISC_R_SUCCESS)
+ return;
+ isc_buffer_init(&buf2, buffer2, sizeof(buffer2));
+ ret = dst_key_todns(newkey, &buf2);
+ printf("todns2(%d) returned: %s\n", dst_key_alg(key),
+ isc_result_totext(ret));
+ if (ret != ISC_R_SUCCESS)
+ return;
+ isc_buffer_usedregion(&buf1, &r1);
+ isc_buffer_usedregion(&buf2, &r2);
+ match = ISC_TF(r1.length == r2.length &&
+ memcmp(r1.base, r2.base, r1.length) == 0);
+ printf("compare(%d): %s\n", dst_key_alg(key),
+ match ? "true" : "false");
+ dst_key_free(&newkey);
+}
+
+static void
+io(dns_name_t *name, int id, int alg, int type, isc_mem_t *mctx) {
+ dst_key_t *key = NULL;
+ isc_result_t ret;
+
+ ret = dst_key_fromfile(name, id, alg, type, current, mctx, &key);
+ printf("read(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+ ret = dst_key_tofile(key, type, tmp);
+ printf("write(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+ use(key, mctx);
+ dns(key, mctx);
+ dst_key_free(&key);
+}
+
+static void
+dh(dns_name_t *name1, int id1, dns_name_t *name2, int id2, isc_mem_t *mctx) {
+ dst_key_t *key1 = NULL, *key2 = NULL;
+ isc_result_t ret;
+ isc_buffer_t b1, b2;
+ isc_region_t r1, r2;
+ unsigned char array1[1024], array2[1024];
+ int alg = DST_ALG_DH;
+ int type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY;
+
+ ret = dst_key_fromfile(name1, id1, alg, type, current, mctx, &key1);
+ printf("read(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+ ret = dst_key_fromfile(name2, id2, alg, type, current, mctx, &key2);
+ printf("read(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+
+ ret = dst_key_tofile(key1, type, tmp);
+ printf("write(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+ ret = dst_key_tofile(key2, type, tmp);
+ printf("write(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != 0)
+ return;
+
+ isc_buffer_init(&b1, array1, sizeof(array1));
+ ret = dst_key_computesecret(key1, key2, &b1);
+ printf("computesecret() returned: %s\n", isc_result_totext(ret));
+ if (ret != 0)
+ return;
+
+ isc_buffer_init(&b2, array2, sizeof(array2));
+ ret = dst_key_computesecret(key2, key1, &b2);
+ printf("computesecret() returned: %s\n", isc_result_totext(ret));
+ if (ret != 0)
+ return;
+
+ isc_buffer_usedregion(&b1, &r1);
+ isc_buffer_usedregion(&b2, &r2);
+
+ if (r1.length != r2.length || memcmp(r1.base, r2.base, r1.length) != 0)
+ {
+ int i;
+ printf("secrets don't match\n");
+ printf("secret 1: %d bytes\n", r1.length);
+ for (i = 0; i < (int) r1.length; i++)
+ printf("%02x ", r1.base[i]);
+ printf("\n");
+ printf("secret 2: %d bytes\n", r2.length);
+ for (i = 0; i < (int) r2.length; i++)
+ printf("%02x ", r2.base[i]);
+ printf("\n");
+ }
+ dst_key_free(&key1);
+ dst_key_free(&key2);
+}
+
+static void
+generate(int alg, isc_mem_t *mctx) {
+ isc_result_t ret;
+ dst_key_t *key = NULL;
+
+ ret = dst_key_generate(dns_rootname, alg, 512, 0, 0, 0,
+ dns_rdataclass_in, mctx, &key);
+ printf("generate(%d) returned: %s\n", alg, isc_result_totext(ret));
+ if (ret != ISC_R_SUCCESS)
+ return;
+
+ if (alg != DST_ALG_DH)
+ use(key, mctx);
+
+ dst_key_free(&key);
+}
+
+int
+main(void) {
+ isc_mem_t *mctx = NULL;
+ isc_entropy_t *ectx = NULL;
+ isc_buffer_t b;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result;
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS)
+ return (1);
+
+ current = isc_mem_get(mctx, 256);
+ if (current == NULL)
+ return (1);
+ getcwd(current, 256);
+
+ dns_result_register();
+
+ result = isc_entropy_create(mctx, &ectx);
+ if (result != ISC_R_SUCCESS)
+ return (1);
+ result = isc_entropy_createfilesource(ectx, "randomfile");
+ if (result != ISC_R_SUCCESS)
+ return (1);
+ dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING|ISC_ENTROPY_GOODONLY);
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ isc_buffer_init(&b, "test.", 5);
+ isc_buffer_add(&b, 5);
+ result = dns_name_fromtext(name, &b, NULL, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (1);
+ io(name, 23616, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx);
+ io(name, 54622, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC,
+ mctx);
+
+ io(name, 49667, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx);
+ io(name, 2, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC, mctx);
+
+ isc_buffer_init(&b, "dh.", 3);
+ isc_buffer_add(&b, 3);
+ result = dns_name_fromtext(name, &b, NULL, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (1);
+ dh(name, 18602, name, 48957, mctx);
+
+ generate(DST_ALG_RSAMD5, mctx);
+ generate(DST_ALG_DH, mctx);
+ generate(DST_ALG_DSA, mctx);
+ generate(DST_ALG_HMACMD5, mctx);
+
+ dst_lib_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mem_put(mctx, current, 256);
+/* isc_mem_stats(mctx, stdout);*/
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/dst/gsstest.c b/bin/tests/dst/gsstest.c
new file mode 100755
index 0000000..98e16d2
--- /dev/null
+++ b/bin/tests/dst/gsstest.c
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2006, 2007 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: gsstest.c,v 1.6 2007/06/19 23:47:00 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/dispatch.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/request.h>
+#include <dns/result.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/masterdump.h>
+#include <dns/rdataset.h>
+#include <dns/resolver.h>
+#include <dns/types.h>
+
+#include <dst/result.h>
+
+#ifdef GSSAPI
+#include ISC_PLATFORM_GSSAPIHEADER
+
+struct dst_context {
+ unsigned int magic;
+ dst_key_t *key;
+ isc_mem_t *mctx;
+ void *opaque;
+};
+
+#define CHECK(str, x) { \
+ if ((x) != ISC_R_SUCCESS) { \
+ fprintf(stderr, "I:%d:%s: %s\n", __LINE__, (str), isc_result_totext(x)); \
+ goto end; \
+ } \
+}
+
+static char contextname[512];
+static char gssid[512];
+static char serveraddress[512];
+static dns_fixedname_t servername, gssname;
+
+static isc_mem_t *mctx;
+static dns_requestmgr_t *requestmgr;
+static isc_sockaddr_t address;
+
+static dns_tsig_keyring_t *ring;
+static dns_tsigkey_t *tsigkey = NULL;
+static gss_ctx_id_t gssctx;
+static gss_ctx_id_t *gssctxp = &gssctx;
+
+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+
+#define PORT 53
+#define TIMEOUT 30
+
+static void initctx1(isc_task_t *task, isc_event_t *event);
+static void sendquery(isc_task_t *task, isc_event_t *event);
+static void setup();
+
+static void
+console(isc_task_t *task, isc_event_t *event)
+{
+ char buf[32];
+ isc_event_t *ev = NULL;
+
+ isc_event_free(&event);
+
+ while(1) {
+ printf("\nCommand => ");
+ scanf("%s", buf);
+
+ if(strcmp(buf, "quit") == 0) {
+ isc_app_shutdown();
+ return;
+ }
+
+ if(strcmp(buf, "initctx") == 0) {
+ ev = isc_event_allocate(mctx, (void *)1, 1, initctx1,
+ NULL, sizeof(*event));
+ isc_task_send(task, &ev);
+ return;
+ }
+
+ if(strcmp(buf, "query") == 0) {
+ ev = isc_event_allocate(mctx, (void *)1, 1, sendquery,
+ NULL, sizeof(*event));
+ isc_task_send(task, &ev);
+ return;
+ }
+
+ printf("Unknown command\n");
+ }
+}
+
+static void
+recvresponse(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result, result2;
+ dns_message_t *query, *response = NULL;
+ isc_buffer_t outtoken;
+ isc_buffer_t outbuf;
+ char output[10 * 1024];
+
+ unsigned char array[DNS_NAME_MAXTEXT + 1];
+ isc_buffer_init(&outtoken, array, sizeof(array));
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ goto end;
+ }
+
+ query = reqev->ev_arg;
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ printf("\nReceived Response:\n");
+
+ result2 = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(response, &dns_master_style_debug, 0,
+ &outbuf);
+ CHECK("dns_message_totext", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+
+ CHECK("dns_request_getresponse", result2);
+
+ if (response)
+ dns_message_destroy(&response);
+
+end:
+ if (query)
+ dns_message_destroy(&query);
+
+ if (reqev->request)
+ dns_request_destroy(&reqev->request);
+
+ isc_event_free(&event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
+ sizeof(*event));
+ isc_task_send(task, &event);
+ return;
+}
+
+
+static void
+sendquery(isc_task_t *task, isc_event_t *event)
+{
+ dns_request_t *request = NULL;
+ dns_message_t *message = NULL;
+ dns_name_t *qname = NULL;
+ dns_rdataset_t *qrdataset = NULL;
+ isc_result_t result;
+ dns_fixedname_t queryname;
+ isc_buffer_t buf;
+ isc_buffer_t outbuf;
+ char output[10 * 1024];
+
+ static char host[256];
+
+ isc_event_free(&event);
+
+ printf("Query => ");
+ scanf("%s", host);
+
+ dns_fixedname_init(&queryname);
+ isc_buffer_init(&buf, host, strlen(host));
+ isc_buffer_add(&buf, strlen(host));
+ result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf,
+ dns_rootname, ISC_FALSE, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
+
+ message->opcode = dns_opcode_query;
+ message->rdclass = dns_rdataclass_in;
+ message->id = (unsigned short)(random() & 0xFFFF);
+
+ result = dns_message_gettempname(message, &qname);
+ if (result != ISC_R_SUCCESS)
+ goto end;
+
+ result = dns_message_gettemprdataset(message, &qrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto end;
+
+ dns_name_init(qname, NULL);
+ dns_name_clone(dns_fixedname_name(&queryname), qname);
+ dns_rdataset_init(qrdataset);
+ dns_rdataset_makequestion(qrdataset, dns_rdataclass_in,
+ dns_rdatatype_a);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+ dns_message_addname(message, qname, DNS_SECTION_QUESTION);
+
+ result = dns_request_create(requestmgr, message, &address, 0, tsigkey,
+ TIMEOUT, task, recvresponse,
+ message, &request);
+ CHECK("dns_request_create", result);
+
+ printf("Submitting query:\n");
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(message, &dns_master_style_debug, 0,
+ &outbuf);
+ CHECK("dns_message_totext", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+
+ return;
+
+ end:
+ if (qname != NULL)
+ dns_message_puttempname(message, &qname);
+ if (qrdataset != NULL)
+ dns_message_puttemprdataset(message, &qrdataset);
+ if (message != NULL)
+ dns_message_destroy(&message);
+}
+
+static void
+initctx2(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result;
+ dns_message_t *query, *response = NULL;
+ isc_buffer_t outtoken;
+ unsigned char array[DNS_NAME_MAXTEXT + 1];
+ dns_rdataset_t *rdataset;
+ dns_rdatatype_t qtype;
+ dns_name_t *question_name;
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ goto end;
+ }
+
+ query = reqev->ev_arg;
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = ISC_RESULTCLASS_DNSRCODE + response->rcode;
+ fprintf(stderr, "I:response rcode: %s\n",
+ isc_result_totext(result));
+ goto end;
+ }
+
+ printf("Received token from server, calling gss_init_sec_context()\n");
+ isc_buffer_init(&outtoken, array, DNS_NAME_MAXTEXT + 1);
+ result = dns_tkey_processgssresponse(query, response,
+ dns_fixedname_name(&gssname),
+ &gssctx, &outtoken,
+ &tsigkey, ring);
+ gssctx = *gssctxp;
+ CHECK("dns_tkey_processgssresponse", result);
+ printf("Context accepted\n");
+
+ question_name = NULL;
+ dns_message_currentname(response, DNS_SECTION_ANSWER, &question_name);
+ rdataset = ISC_LIST_HEAD(question_name->list);
+ INSIST(rdataset != NULL);
+ qtype = rdataset->type;
+ if(qtype == dns_rdatatype_tkey) {
+ printf("Received TKEY response from server\n");
+ printf("Context completed\n");
+ } else {
+ printf("Did not receive TKEY response from server\n");
+ printf("Context not completed\n");
+ dns_tsigkey_detach(&tsigkey);
+ tsigkey = NULL;
+ }
+
+ if(response)
+ dns_message_destroy(&response);
+
+end:
+ if(query)
+ dns_message_destroy(&query);
+
+ if(reqev->request)
+ dns_request_destroy(&reqev->request);
+
+ isc_event_free(&event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
+ sizeof(*event));
+ isc_task_send(task, &event);
+ return;
+}
+
+static void
+initctx1(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ isc_buffer_t buf;
+ dns_message_t *query;
+ dns_request_t *request;
+
+ isc_event_free(&event);
+
+ printf("Initctx - GSS name => ");
+ scanf("%s", gssid);
+
+ sprintf(contextname, "gsstest.context.%d.", (int)time(NULL));
+
+ printf("Initctx - context name we're using: %s\n", contextname);
+
+ printf("Negotiating GSSAPI context: ");
+ printf(gssid);
+ printf("\n");
+
+ /*
+ * Setup a GSSAPI context with the server
+ */
+ dns_fixedname_init(&servername);
+ isc_buffer_init(&buf, contextname, strlen(contextname));
+ isc_buffer_add(&buf, strlen(contextname));
+ result = dns_name_fromtext(dns_fixedname_name(&servername), &buf,
+ dns_rootname, ISC_FALSE, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ /* Make name happen */
+ dns_fixedname_init(&gssname);
+ isc_buffer_init(&buf, gssid, strlen(gssid));
+ isc_buffer_add(&buf, strlen(gssid));
+ result = dns_name_fromtext(dns_fixedname_name(&gssname), &buf,
+ dns_rootname, ISC_FALSE, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ query = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+ CHECK("dns_message_create", result);
+
+ printf("Calling gss_init_sec_context()\n");
+ gssctx = GSS_C_NO_CONTEXT;
+ result = dns_tkey_buildgssquery(query, dns_fixedname_name(&servername),
+ dns_fixedname_name(&gssname),
+ NULL, 36000, &gssctx, ISC_TRUE);
+ CHECK("dns_tkey_buildgssquery", result);
+
+ printf("Sending context token to server\n");
+ request = NULL;
+ result = dns_request_create(requestmgr, query, &address, 0, NULL,
+ TIMEOUT, task, initctx2, query, &request);
+ CHECK("dns_request_create", result);
+
+ return;
+end:
+ event = isc_event_allocate(mctx, (void *)1, 1, console, NULL,
+ sizeof(*event));
+ isc_task_send(task, &event);return;
+}
+
+static void
+setup(void)
+{
+ struct in_addr inaddr;
+ int c;
+
+ while (1) {
+ printf("Server IP => ");
+ c = scanf("%s", serveraddress);
+
+ if(c == EOF || strcmp(serveraddress, "quit") == 0) {
+ isc_app_shutdown();
+ return;
+ }
+
+ if (inet_pton(AF_INET, serveraddress, &inaddr) == 1) {
+ isc_sockaddr_fromin(&address, &inaddr, PORT);
+ return;
+ }
+
+ };
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_taskmgr_t *taskmgr;
+ isc_timermgr_t *timermgr;
+ isc_socketmgr_t *socketmgr;
+ isc_socket_t *sock;
+ unsigned int attrs, attrmask;
+ isc_sockaddr_t bind_any;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_dispatch_t *dispatchv4;
+ dns_view_t *view;
+ isc_entropy_t *ectx;
+ isc_task_t *task;
+ isc_log_t *lctx = NULL;
+ isc_logconfig_t *lcfg = NULL;
+ isc_logdestination_t destination;
+
+ UNUSED(argv);
+ UNUSED(argc);
+
+ RUNCHECK(isc_app_start());
+
+ dns_result_register();
+
+ mctx = NULL;
+ RUNCHECK(isc_mem_create(0, 0, &mctx));
+
+ RUNCHECK(isc_log_create(mctx, &lctx, &lcfg));
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ /*
+ * Create and install the default channel.
+ */
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ RUNCHECK(isc_log_createchannel(lcfg, "_default",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination, ISC_LOG_PRINTTIME));
+ RUNCHECK(isc_log_usechannel(lcfg, "_default", NULL, NULL));
+
+ isc_log_setdebuglevel(lctx, 9);
+
+ ectx = NULL;
+ RUNCHECK(isc_entropy_create(mctx, &ectx));
+ RUNCHECK(isc_entropy_createfilesource(ectx, "/dev/urandom"));
+
+ RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
+
+ taskmgr = NULL;
+ RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
+ task = NULL;
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ timermgr = NULL;
+ RUNCHECK(isc_timermgr_create(mctx, &timermgr));
+ socketmgr = NULL;
+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
+ dispatchmgr = NULL;
+ RUNCHECK(dns_dispatchmgr_create(mctx, ectx, &dispatchmgr));
+ isc_sockaddr_any(&bind_any);
+ attrs = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_MAKEQUERY |
+ DNS_DISPATCHATTR_IPV4;
+ attrmask = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_TCP |
+ DNS_DISPATCHATTR_IPV4 |
+ DNS_DISPATCHATTR_IPV6;
+ dispatchv4 = NULL;
+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any, 4096, 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv4));
+ requestmgr = NULL;
+ RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
+ dispatchmgr, dispatchv4, NULL,
+ &requestmgr));
+
+ ring = NULL;
+ RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
+
+ view = NULL;
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+ dns_view_setkeyring(view, ring);
+
+ sock = NULL;
+ RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
+ &sock));
+
+ setup();
+
+ RUNCHECK(isc_app_onrun(mctx, task, console, NULL));
+
+ (void)isc_app_run();
+
+ if (tsigkey)
+ dns_tsigkey_detach(&tsigkey);
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+
+ dns_dispatch_detach(&dispatchv4);
+ dns_dispatchmgr_destroy(&dispatchmgr);
+
+ isc_timermgr_destroy(&timermgr);
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_socket_detach(&sock);
+ isc_socketmgr_destroy(&socketmgr);
+
+ isc_mem_stats(mctx, stdout);
+
+ dns_view_detach(&view);
+
+ dst_lib_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
+#else
+int
+main(int argc, char *argv[]) {
+ UNUSED(argc);
+ UNUSED(argv);
+ fprintf(stderr, "R:GSSAPIONLY\n");
+ return (0);
+}
+#endif
diff --git a/bin/tests/dst/t2_data_1 b/bin/tests/dst/t2_data_1
new file mode 100644
index 0000000..b1a9bf5
--- /dev/null
+++ b/bin/tests/dst/t2_data_1
@@ -0,0 +1,3077 @@
+Network Working Group P. Mockapetris
+Request for Comments: 1035 ISI
+ November 1987
+Obsoletes: RFCs 882, 883, 973
+
+ DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION
+
+
+1. STATUS OF THIS MEMO
+
+This RFC describes the details of the domain system and protocol, and
+assumes that the reader is familiar with the concepts discussed in a
+companion RFC, "Domain Names - Concepts and Facilities" [RFC-1034].
+
+The domain system is a mixture of functions and data types which are an
+official protocol and functions and data types which are still
+experimental. Since the domain system is intentionally extensible, new
+data types and experimental behavior should always be expected in parts
+of the system beyond the official protocol. The official protocol parts
+include standard queries, responses and the Internet class RR data
+formats (e.g., host addresses). Since the previous RFC set, several
+definitions have changed, so some previous definitions are obsolete.
+
+Experimental or obsolete features are clearly marked in these RFCs, and
+such information should be used with caution.
+
+The reader is especially cautioned not to depend on the values which
+appear in examples to be current or complete, since their purpose is
+primarily pedagogical. Distribution of this memo is unlimited.
+
+ Table of Contents
+
+ 1. STATUS OF THIS MEMO 1
+ 2. INTRODUCTION 3
+ 2.1. Overview 3
+ 2.2. Common configurations 4
+ 2.3. Conventions 7
+ 2.3.1. Preferred name syntax 7
+ 2.3.2. Data Transmission Order 8
+ 2.3.3. Character Case 9
+ 2.3.4. Size limits 10
+ 3. DOMAIN NAME SPACE AND RR DEFINITIONS 10
+ 3.1. Name space definitions 10
+ 3.2. RR definitions 11
+ 3.2.1. Format 11
+ 3.2.2. TYPE values 12
+ 3.2.3. QTYPE values 12
+ 3.2.4. CLASS values 13
+
+
+
+Mockapetris [Page 1]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 3.2.5. QCLASS values 13
+ 3.3. Standard RRs 13
+ 3.3.1. CNAME RDATA format 14
+ 3.3.2. HINFO RDATA format 14
+ 3.3.3. MB RDATA format (EXPERIMENTAL) 14
+ 3.3.4. MD RDATA format (Obsolete) 15
+ 3.3.5. MF RDATA format (Obsolete) 15
+ 3.3.6. MG RDATA format (EXPERIMENTAL) 16
+ 3.3.7. MINFO RDATA format (EXPERIMENTAL) 16
+ 3.3.8. MR RDATA format (EXPERIMENTAL) 17
+ 3.3.9. MX RDATA format 17
+ 3.3.10. NULL RDATA format (EXPERIMENTAL) 17
+ 3.3.11. NS RDATA format 18
+ 3.3.12. PTR RDATA format 18
+ 3.3.13. SOA RDATA format 19
+ 3.3.14. TXT RDATA format 20
+ 3.4. ARPA Internet specific RRs 20
+ 3.4.1. A RDATA format 20
+ 3.4.2. WKS RDATA format 21
+ 3.5. IN-ADDR.ARPA domain 22
+ 3.6. Defining new types, classes, and special namespaces 24
+ 4. MESSAGES 25
+ 4.1. Format 25
+ 4.1.1. Header section format 26
+ 4.1.2. Question section format 28
+ 4.1.3. Resource record format 29
+ 4.1.4. Message compression 30
+ 4.2. Transport 32
+ 4.2.1. UDP usage 32
+ 4.2.2. TCP usage 32
+ 5. MASTER FILES 33
+ 5.1. Format 33
+ 5.2. Use of master files to define zones 35
+ 5.3. Master file example 36
+ 6. NAME SERVER IMPLEMENTATION 37
+ 6.1. Architecture 37
+ 6.1.1. Control 37
+ 6.1.2. Database 37
+ 6.1.3. Time 39
+ 6.2. Standard query processing 39
+ 6.3. Zone refresh and reload processing 39
+ 6.4. Inverse queries (Optional) 40
+ 6.4.1. The contents of inverse queries and responses 40
+ 6.4.2. Inverse query and response example 41
+ 6.4.3. Inverse query processing 42
+
+
+
+
+
+
+Mockapetris [Page 2]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 6.5. Completion queries and responses 42
+ 7. RESOLVER IMPLEMENTATION 43
+ 7.1. Transforming a user request into a query 43
+ 7.2. Sending the queries 44
+ 7.3. Processing responses 46
+ 7.4. Using the cache 47
+ 8. MAIL SUPPORT 47
+ 8.1. Mail exchange binding 48
+ 8.2. Mailbox binding (Experimental) 48
+ 9. REFERENCES and BIBLIOGRAPHY 50
+ Index 54
+
+2. INTRODUCTION
+
+2.1. Overview
+
+The goal of domain names is to provide a mechanism for naming resources
+in such a way that the names are usable in different hosts, networks,
+protocol families, internets, and administrative organizations.
+
+From the user's point of view, domain names are useful as arguments to a
+local agent, called a resolver, which retrieves information associated
+with the domain name. Thus a user might ask for the host address or
+mail information associated with a particular domain name. To enable
+the user to request a particular type of information, an appropriate
+query type is passed to the resolver with the domain name. To the user,
+the domain tree is a single information space; the resolver is
+responsible for hiding the distribution of data among name servers from
+the user.
+
+From the resolver's point of view, the database that makes up the domain
+space is distributed among various name servers. Different parts of the
+domain space are stored in different name servers, although a particular
+data item will be stored redundantly in two or more name servers. The
+resolver starts with knowledge of at least one name server. When the
+resolver processes a user query it asks a known name server for the
+information; in return, the resolver either receives the desired
+information or a referral to another name server. Using these
+referrals, resolvers learn the identities and contents of other name
+servers. Resolvers are responsible for dealing with the distribution of
+the domain space and dealing with the effects of name server failure by
+consulting redundant databases in other servers.
+
+Name servers manage two kinds of data. The first kind of data held in
+sets called zones; each zone is the complete database for a particular
+"pruned" subtree of the domain space. This data is called
+authoritative. A name server periodically checks to make sure that its
+zones are up to date, and if not, obtains a new copy of updated zones
+
+
+
+Mockapetris [Page 3]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+from master files stored locally or in another name server. The second
+kind of data is cached data which was acquired by a local resolver.
+This data may be incomplete, but improves the performance of the
+retrieval process when non-local data is repeatedly accessed. Cached
+data is eventually discarded by a timeout mechanism.
+
+This functional structure isolates the problems of user interface,
+failure recovery, and distribution in the resolvers and isolates the
+database update and refresh problems in the name servers.
+
+2.2. Common configurations
+
+A host can participate in the domain name system in a number of ways,
+depending on whether the host runs programs that retrieve information
+from the domain system, name servers that answer queries from other
+hosts, or various combinations of both functions. The simplest, and
+perhaps most typical, configuration is shown below:
+
+ Local Host | Foreign
+ |
+ +---------+ +----------+ | +--------+
+ | | user queries | |queries | | |
+ | User |-------------->| |---------|->|Foreign |
+ | Program | | Resolver | | | Name |
+ | |<--------------| |<--------|--| Server |
+ | | user responses| |responses| | |
+ +---------+ +----------+ | +--------+
+ | A |
+ cache additions | | references |
+ V | |
+ +----------+ |
+ | cache | |
+ +----------+ |
+
+User programs interact with the domain name space through resolvers; the
+format of user queries and user responses is specific to the host and
+its operating system. User queries will typically be operating system
+calls, and the resolver and its cache will be part of the host operating
+system. Less capable hosts may choose to implement the resolver as a
+subroutine to be linked in with every program that needs its services.
+Resolvers answer user queries with information they acquire via queries
+to foreign name servers and the local cache.
+
+Note that the resolver may have to make several queries to several
+different foreign name servers to answer a particular user query, and
+hence the resolution of a user query may involve several network
+accesses and an arbitrary amount of time. The queries to foreign name
+servers and the corresponding responses have a standard format described
+
+
+
+Mockapetris [Page 4]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+in this memo, and may be datagrams.
+
+Depending on its capabilities, a name server could be a stand alone
+program on a dedicated machine or a process or processes on a large
+timeshared host. A simple configuration might be:
+
+ Local Host | Foreign
+ |
+ +---------+ |
+ / /| |
+ +---------+ | +----------+ | +--------+
+ | | | | |responses| | |
+ | | | | Name |---------|->|Foreign |
+ | Master |-------------->| Server | | |Resolver|
+ | files | | | |<--------|--| |
+ | |/ | | queries | +--------+
+ +---------+ +----------+ |
+
+Here a primary name server acquires information about one or more zones
+by reading master files from its local file system, and answers queries
+about those zones that arrive from foreign resolvers.
+
+The DNS requires that all zones be redundantly supported by more than
+one name server. Designated secondary servers can acquire zones and
+check for updates from the primary server using the zone transfer
+protocol of the DNS. This configuration is shown below:
+
+ Local Host | Foreign
+ |
+ +---------+ |
+ / /| |
+ +---------+ | +----------+ | +--------+
+ | | | | |responses| | |
+ | | | | Name |---------|->|Foreign |
+ | Master |-------------->| Server | | |Resolver|
+ | files | | | |<--------|--| |
+ | |/ | | queries | +--------+
+ +---------+ +----------+ |
+ A |maintenance | +--------+
+ | +------------|->| |
+ | queries | |Foreign |
+ | | | Name |
+ +------------------|--| Server |
+ maintenance responses | +--------+
+
+In this configuration, the name server periodically establishes a
+virtual circuit to a foreign name server to acquire a copy of a zone or
+to check that an existing copy has not changed. The messages sent for
+
+
+
+Mockapetris [Page 5]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+these maintenance activities follow the same form as queries and
+responses, but the message sequences are somewhat different.
+
+The information flow in a host that supports all aspects of the domain
+name system is shown below:
+
+ Local Host | Foreign
+ |
+ +---------+ +----------+ | +--------+
+ | | user queries | |queries | | |
+ | User |-------------->| |---------|->|Foreign |
+ | Program | | Resolver | | | Name |
+ | |<--------------| |<--------|--| Server |
+ | | user responses| |responses| | |
+ +---------+ +----------+ | +--------+
+ | A |
+ cache additions | | references |
+ V | |
+ +----------+ |
+ | Shared | |
+ | database | |
+ +----------+ |
+ A | |
+ +---------+ refreshes | | references |
+ / /| | V |
+ +---------+ | +----------+ | +--------+
+ | | | | |responses| | |
+ | | | | Name |---------|->|Foreign |
+ | Master |-------------->| Server | | |Resolver|
+ | files | | | |<--------|--| |
+ | |/ | | queries | +--------+
+ +---------+ +----------+ |
+ A |maintenance | +--------+
+ | +------------|->| |
+ | queries | |Foreign |
+ | | | Name |
+ +------------------|--| Server |
+ maintenance responses | +--------+
+
+The shared database holds domain space data for the local name server
+and resolver. The contents of the shared database will typically be a
+mixture of authoritative data maintained by the periodic refresh
+operations of the name server and cached data from previous resolver
+requests. The structure of the domain data and the necessity for
+synchronization between name servers and resolvers imply the general
+characteristics of this database, but the actual format is up to the
+local implementor.
+
+
+
+
+Mockapetris [Page 6]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+Information flow can also be tailored so that a group of hosts act
+together to optimize activities. Sometimes this is done to offload less
+capable hosts so that they do not have to implement a full resolver.
+This can be appropriate for PCs or hosts which want to minimize the
+amount of new network code which is required. This scheme can also
+allow a group of hosts can share a small number of caches rather than
+maintaining a large number of separate caches, on the premise that the
+centralized caches will have a higher hit ratio. In either case,
+resolvers are replaced with stub resolvers which act as front ends to
+resolvers located in a recursive server in one or more name servers
+known to perform that service:
+
+ Local Hosts | Foreign
+ |
+ +---------+ |
+ | | responses |
+ | Stub |<--------------------+ |
+ | Resolver| | |
+ | |----------------+ | |
+ +---------+ recursive | | |
+ queries | | |
+ V | |
+ +---------+ recursive +----------+ | +--------+
+ | | queries | |queries | | |
+ | Stub |-------------->| Recursive|---------|->|Foreign |
+ | Resolver| | Server | | | Name |
+ | |<--------------| |<--------|--| Server |
+ +---------+ responses | |responses| | |
+ +----------+ | +--------+
+ | Central | |
+ | cache | |
+ +----------+ |
+
+In any case, note that domain components are always replicated for
+reliability whenever possible.
+
+2.3. Conventions
+
+The domain system has several conventions dealing with low-level, but
+fundamental, issues. While the implementor is free to violate these
+conventions WITHIN HIS OWN SYSTEM, he must observe these conventions in
+ALL behavior observed from other hosts.
+
+2.3.1. Preferred name syntax
+
+The DNS specifications attempt to be as general as possible in the rules
+for constructing domain names. The idea is that the name of any
+existing object can be expressed as a domain name with minimal changes.
+
+
+
+Mockapetris [Page 7]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+However, when assigning a domain name for an object, the prudent user
+will select a name which satisfies both the rules of the domain system
+and any existing rules for the object, whether these rules are published
+or implied by existing programs.
+
+For example, when naming a mail domain, the user should satisfy both the
+rules of this memo and those in RFC-822. When creating a new host name,
+the old rules for HOSTS.TXT should be followed. This avoids problems
+when old software is converted to use domain names.
+
+The following syntax will result in fewer problems with many
+
+applications that use domain names (e.g., mail, TELNET).
+
+<domain> ::= <subdomain> | " "
+
+<subdomain> ::= <label> | <subdomain> "." <label>
+
+<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
+
+<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+
+<let-dig-hyp> ::= <let-dig> | "-"
+
+<let-dig> ::= <letter> | <digit>
+
+<letter> ::= any one of the 52 alphabetic characters A through Z in
+upper case and a through z in lower case
+
+<digit> ::= any one of the ten digits 0 through 9
+
+Note that while upper and lower case letters are allowed in domain
+names, no significance is attached to the case. That is, two names with
+the same spelling but different case are to be treated as if identical.
+
+The labels must follow the rules for ARPANET host names. They must
+start with a letter, end with a letter or digit, and have as interior
+characters only letters, digits, and hyphen. There are also some
+restrictions on the length. Labels must be 63 characters or less.
+
+For example, the following strings identify hosts in the Internet:
+
+A.ISI.EDU XX.LCS.MIT.EDU SRI-NIC.ARPA
+
+2.3.2. Data Transmission Order
+
+The order of transmission of the header and data described in this
+document is resolved to the octet level. Whenever a diagram shows a
+
+
+
+Mockapetris [Page 8]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+group of octets, the order of transmission of those octets is the normal
+order in which they are read in English. For example, in the following
+diagram, the octets are transmitted in the order they are numbered.
+
+ 0 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 1 | 2 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 3 | 4 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 5 | 6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+Whenever an octet represents a numeric quantity, the left most bit in
+the diagram is the high order or most significant bit. That is, the bit
+labeled 0 is the most significant bit. For example, the following
+diagram represents the value 170 (decimal).
+
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |1 0 1 0 1 0 1 0|
+ +-+-+-+-+-+-+-+-+
+
+Similarly, whenever a multi-octet field represents a numeric quantity
+the left most bit of the whole field is the most significant bit. When
+a multi-octet quantity is transmitted the most significant octet is
+transmitted first.
+
+2.3.3. Character Case
+
+For all parts of the DNS that are part of the official protocol, all
+comparisons between character strings (e.g., labels, domain names, etc.)
+are done in a case-insensitive manner. At present, this rule is in
+force throughout the domain system without exception. However, future
+additions beyond current usage may need to use the full binary octet
+capabilities in names, so attempts to store domain names in 7-bit ASCII
+or use of special bytes to terminate labels, etc., should be avoided.
+
+When data enters the domain system, its original case should be
+preserved whenever possible. In certain circumstances this cannot be
+done. For example, if two RRs are stored in a database, one at x.y and
+one at X.Y, they are actually stored at the same place in the database,
+and hence only one casing would be preserved. The basic rule is that
+case can be discarded only when data is used to define structure in a
+database, and two names are identical when compared in a case
+insensitive manner.
+
+
+
+
+Mockapetris [Page 9]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+Loss of case sensitive data must be minimized. Thus while data for x.y
+and X.Y may both be stored under a single location x.y or X.Y, data for
+a.x and B.X would never be stored under A.x, A.X, b.x, or b.X. In
+general, this preserves the case of the first label of a domain name,
+but forces standardization of interior node labels.
+
+Systems administrators who enter data into the domain database should
+take care to represent the data they supply to the domain system in a
+case-consistent manner if their system is case-sensitive. The data
+distribution system in the domain system will ensure that consistent
+representations are preserved.
+
+2.3.4. Size limits
+
+Various objects and parameters in the DNS have size limits. They are
+listed below. Some could be easily changed, others are more
+fundamental.
+
+labels 63 octets or less
+
+names 255 octets or less
+
+TTL positive values of a signed 32 bit number.
+
+UDP messages 512 octets or less
+
+3. DOMAIN NAME SPACE AND RR DEFINITIONS
+
+3.1. Name space definitions
+
+Domain names in messages are expressed in terms of a sequence of labels.
+Each label is represented as a one octet length field followed by that
+number of octets. Since every domain name ends with the null label of
+the root, a domain name is terminated by a length byte of zero. The
+high order two bits of every length octet must be zero, and the
+remaining six bits of the length field limit the label to 63 octets or
+less.
+
+To simplify implementations, the total length of a domain name (i.e.,
+label octets and label length octets) is restricted to 255 octets or
+less.
+
+Although labels can contain any 8 bit values in octets that make up a
+label, it is strongly recommended that labels follow the preferred
+syntax described elsewhere in this memo, which is compatible with
+existing host naming conventions. Name servers and resolvers must
+compare labels in a case-insensitive manner (i.e., A=a), assuming ASCII
+with zero parity. Non-alphabetic codes must match exactly.
+
+
+
+Mockapetris [Page 10]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.2. RR definitions
+
+3.2.1. Format
+
+All RRs have the same top level format shown below:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / /
+ / NAME /
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | CLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TTL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RDLENGTH |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+ / RDATA /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+
+where:
+
+NAME an owner name, i.e., the name of the node to which this
+ resource record pertains.
+
+TYPE two octets containing one of the RR TYPE codes.
+
+CLASS two octets containing one of the RR CLASS codes.
+
+TTL a 32 bit signed integer that specifies the time interval
+ that the resource record may be cached before the source
+ of the information should again be consulted. Zero
+ values are interpreted to mean that the RR can only be
+ used for the transaction in progress, and should not be
+ cached. For example, SOA records are always distributed
+ with a zero TTL to prohibit caching. Zero values can
+ also be used for extremely volatile data.
+
+RDLENGTH an unsigned 16 bit integer that specifies the length in
+ octets of the RDATA field.
+
+
+
+Mockapetris [Page 11]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+RDATA a variable length string of octets that describes the
+ resource. The format of this information varies
+ according to the TYPE and CLASS of the resource record.
+
+3.2.2. TYPE values
+
+TYPE fields are used in resource records. Note that these types are a
+subset of QTYPEs.
+
+TYPE value and meaning
+
+A 1 a host address
+
+NS 2 an authoritative name server
+
+MD 3 a mail destination (Obsolete - use MX)
+
+MF 4 a mail forwarder (Obsolete - use MX)
+
+CNAME 5 the canonical name for an alias
+
+SOA 6 marks the start of a zone of authority
+
+MB 7 a mailbox domain name (EXPERIMENTAL)
+
+MG 8 a mail group member (EXPERIMENTAL)
+
+MR 9 a mail rename domain name (EXPERIMENTAL)
+
+NULL 10 a null RR (EXPERIMENTAL)
+
+WKS 11 a well known service description
+
+PTR 12 a domain name pointer
+
+HINFO 13 host information
+
+MINFO 14 mailbox or mail list information
+
+MX 15 mail exchange
+
+TXT 16 text strings
+
+3.2.3. QTYPE values
+
+QTYPE fields appear in the question part of a query. QTYPES are a
+superset of TYPEs, hence all TYPEs are valid QTYPEs. In addition, the
+following QTYPEs are defined:
+
+
+
+Mockapetris [Page 12]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+AXFR 252 A request for a transfer of an entire zone
+
+MAILB 253 A request for mailbox-related records (MB, MG or MR)
+
+MAILA 254 A request for mail agent RRs (Obsolete - see MX)
+
+* 255 A request for all records
+
+3.2.4. CLASS values
+
+CLASS fields appear in resource records. The following CLASS mnemonics
+and values are defined:
+
+IN 1 the Internet
+
+CS 2 the CSNET class (Obsolete - used only for examples in
+ some obsolete RFCs)
+
+CH 3 the CHAOS class
+
+HS 4 Hesiod [Dyer 87]
+
+3.2.5. QCLASS values
+
+QCLASS fields appear in the question section of a query. QCLASS values
+are a superset of CLASS values; every CLASS is a valid QCLASS. In
+addition to CLASS values, the following QCLASSes are defined:
+
+* 255 any class
+
+3.3. Standard RRs
+
+The following RR definitions are expected to occur, at least
+potentially, in all classes. In particular, NS, SOA, CNAME, and PTR
+will be used in all classes, and have the same format in all classes.
+Because their RDATA format is known, all domain names in the RDATA
+section of these RRs may be compressed.
+
+<domain-name> is a domain name represented as a series of labels, and
+terminated by a label with zero length. <character-string> is a single
+length octet followed by that number of characters. <character-string>
+is treated as binary information, and can be up to 256 characters in
+length (including the length octet).
+
+
+
+
+
+
+
+
+Mockapetris [Page 13]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.1. CNAME RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / CNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+CNAME A <domain-name> which specifies the canonical or primary
+ name for the owner. The owner name is an alias.
+
+CNAME RRs cause no additional section processing, but name servers may
+choose to restart the query at the canonical name in certain cases. See
+the description of name server logic in [RFC-1034] for details.
+
+3.3.2. HINFO RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / CPU /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / OS /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+CPU A <character-string> which specifies the CPU type.
+
+OS A <character-string> which specifies the operating
+ system type.
+
+Standard values for CPU and OS can be found in [RFC-1010].
+
+HINFO records are used to acquire general information about a host. The
+main use is for protocols such as FTP that can use special procedures
+when talking between machines or operating systems of the same type.
+
+3.3.3. MB RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MADNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MADNAME A <domain-name> which specifies a host which has the
+ specified mailbox.
+
+
+
+Mockapetris [Page 14]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+MB records cause additional section processing which looks up an A type
+RRs corresponding to MADNAME.
+
+3.3.4. MD RDATA format (Obsolete)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MADNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MADNAME A <domain-name> which specifies a host which has a mail
+ agent for the domain which should be able to deliver
+ mail for the domain.
+
+MD records cause additional section processing which looks up an A type
+record corresponding to MADNAME.
+
+MD is obsolete. See the definition of MX and [RFC-974] for details of
+the new scheme. The recommended policy for dealing with MD RRs found in
+a master file is to reject them, or to convert them to MX RRs with a
+preference of 0.
+
+3.3.5. MF RDATA format (Obsolete)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MADNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MADNAME A <domain-name> which specifies a host which has a mail
+ agent for the domain which will accept mail for
+ forwarding to the domain.
+
+MF records cause additional section processing which looks up an A type
+record corresponding to MADNAME.
+
+MF is obsolete. See the definition of MX and [RFC-974] for details ofw
+the new scheme. The recommended policy for dealing with MD RRs found in
+a master file is to reject them, or to convert them to MX RRs with a
+preference of 10.
+
+
+
+
+
+
+
+Mockapetris [Page 15]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.6. MG RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MGMNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MGMNAME A <domain-name> which specifies a mailbox which is a
+ member of the mail group specified by the domain name.
+
+MG records cause no additional section processing.
+
+3.3.7. MINFO RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / RMAILBX /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / EMAILBX /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+RMAILBX A <domain-name> which specifies a mailbox which is
+ responsible for the mailing list or mailbox. If this
+ domain name names the root, the owner of the MINFO RR is
+ responsible for itself. Note that many existing mailing
+ lists use a mailbox X-request for the RMAILBX field of
+ mailing list X, e.g., Msgroup-request for Msgroup. This
+ field provides a more general mechanism.
+
+
+EMAILBX A <domain-name> which specifies a mailbox which is to
+ receive error messages related to the mailing list or
+ mailbox specified by the owner of the MINFO RR (similar
+ to the ERRORS-TO: field which has been proposed). If
+ this domain name names the root, errors should be
+ returned to the sender of the message.
+
+MINFO records cause no additional section processing. Although these
+records can be associated with a simple mailbox, they are usually used
+with a mailing list.
+
+
+
+
+
+
+
+
+Mockapetris [Page 16]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.8. MR RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / NEWNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+NEWNAME A <domain-name> which specifies a mailbox which is the
+ proper rename of the specified mailbox.
+
+MR records cause no additional section processing. The main use for MR
+is as a forwarding entry for a user who has moved to a different
+mailbox.
+
+3.3.9. MX RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PREFERENCE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / EXCHANGE /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+PREFERENCE A 16 bit integer which specifies the preference given to
+ this RR among others at the same owner. Lower values
+ are preferred.
+
+EXCHANGE A <domain-name> which specifies a host willing to act as
+ a mail exchange for the owner name.
+
+MX records cause type A additional section processing for the host
+specified by EXCHANGE. The use of MX RRs is explained in detail in
+[RFC-974].
+
+3.3.10. NULL RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / <anything> /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+Anything at all may be in the RDATA field so long as it is 65535 octets
+or less.
+
+
+
+
+Mockapetris [Page 17]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+NULL records cause no additional section processing. NULL RRs are not
+allowed in master files. NULLs are used as placeholders in some
+experimental extensions of the DNS.
+
+3.3.11. NS RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / NSDNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+NSDNAME A <domain-name> which specifies a host which should be
+ authoritative for the specified class and domain.
+
+NS records cause both the usual additional section processing to locate
+a type A record, and, when used in a referral, a special search of the
+zone in which they reside for glue information.
+
+The NS RR states that the named host should be expected to have a zone
+starting at owner name of the specified class. Note that the class may
+not indicate the protocol family which should be used to communicate
+with the host, although it is typically a strong hint. For example,
+hosts which are name servers for either Internet (IN) or Hesiod (HS)
+class information are normally queried using IN class protocols.
+
+3.3.12. PTR RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / PTRDNAME /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+PTRDNAME A <domain-name> which points to some location in the
+ domain name space.
+
+PTR records cause no additional section processing. These RRs are used
+in special domains to point to some other location in the domain space.
+These records are simple data, and don't imply any special processing
+similar to that performed by CNAME, which identifies aliases. See the
+description of the IN-ADDR.ARPA domain for an example.
+
+
+
+
+
+
+
+
+Mockapetris [Page 18]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.13. SOA RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / RNAME /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | SERIAL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | REFRESH |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RETRY |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | EXPIRE |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | MINIMUM |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MNAME The <domain-name> of the name server that was the
+ original or primary source of data for this zone.
+
+RNAME A <domain-name> which specifies the mailbox of the
+ person responsible for this zone.
+
+SERIAL The unsigned 32 bit version number of the original copy
+ of the zone. Zone transfers preserve this value. This
+ value wraps and should be compared using sequence space
+ arithmetic.
+
+REFRESH A 32 bit time interval before the zone should be
+ refreshed.
+
+RETRY A 32 bit time interval that should elapse before a
+ failed refresh should be retried.
+
+EXPIRE A 32 bit time value that specifies the upper limit on
+ the time interval that can elapse before the zone is no
+ longer authoritative.
+
+
+
+
+
+Mockapetris [Page 19]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+MINIMUM The unsigned 32 bit minimum TTL field that should be
+ exported with any RR from this zone.
+
+SOA records cause no additional section processing.
+
+All times are in units of seconds.
+
+Most of these fields are pertinent only for name server maintenance
+operations. However, MINIMUM is used in all query operations that
+retrieve RRs from a zone. Whenever a RR is sent in a response to a
+query, the TTL field is set to the maximum of the TTL field from the RR
+and the MINIMUM field in the appropriate SOA. Thus MINIMUM is a lower
+bound on the TTL field for all RRs in a zone. Note that this use of
+MINIMUM should occur when the RRs are copied into the response and not
+when the zone is loaded from a master file or via a zone transfer. The
+reason for this provison is to allow future dynamic update facilities to
+change the SOA RR with known semantics.
+
+
+3.3.14. TXT RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / TXT-DATA /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+TXT-DATA One or more <character-string>s.
+
+TXT RRs are used to hold descriptive text. The semantics of the text
+depends on the domain where it is found.
+
+3.4. Internet specific RRs
+
+3.4.1. A RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ADDRESS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+ADDRESS A 32 bit Internet address.
+
+Hosts that have multiple Internet addresses will have multiple A
+records.
+
+
+
+
+
+Mockapetris [Page 20]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+A records cause no additional section processing. The RDATA section of
+an A line in a master file is an Internet address expressed as four
+decimal numbers separated by dots without any imbedded spaces (e.g.,
+"10.2.0.52" or "192.0.5.6").
+
+3.4.2. WKS RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ADDRESS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PROTOCOL | |
+ +--+--+--+--+--+--+--+--+ |
+ | |
+ / <BIT MAP> /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+ADDRESS An 32 bit Internet address
+
+PROTOCOL An 8 bit IP protocol number
+
+<BIT MAP> A variable length bit map. The bit map must be a
+ multiple of 8 bits long.
+
+The WKS record is used to describe the well known services supported by
+a particular protocol on a particular internet address. The PROTOCOL
+field specifies an IP protocol number, and the bit map has one bit per
+port of the specified protocol. The first bit corresponds to port 0,
+the second to port 1, etc. If the bit map does not include a bit for a
+protocol of interest, that bit is assumed zero. The appropriate values
+and mnemonics for ports and protocols are specified in [RFC-1010].
+
+For example, if PROTOCOL=TCP (6), the 26th bit corresponds to TCP port
+25 (SMTP). If this bit is set, a SMTP server should be listening on TCP
+port 25; if zero, SMTP service is not supported on the specified
+address.
+
+The purpose of WKS RRs is to provide availability information for
+servers for TCP and UDP. If a server supports both TCP and UDP, or has
+multiple Internet addresses, then multiple WKS RRs are used.
+
+WKS RRs cause no additional section processing.
+
+In master files, both ports and protocols are expressed using mnemonics
+or decimal numbers.
+
+
+
+
+Mockapetris [Page 21]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.5. IN-ADDR.ARPA domain
+
+The Internet uses a special domain to support gateway location and
+Internet address to host mapping. Other classes may employ a similar
+strategy in other domains. The intent of this domain is to provide a
+guaranteed method to perform host address to host name mapping, and to
+facilitate queries to locate all gateways on a particular network in the
+Internet.
+
+Note that both of these services are similar to functions that could be
+performed by inverse queries; the difference is that this part of the
+domain name space is structured according to address, and hence can
+guarantee that the appropriate data can be located without an exhaustive
+search of the domain space.
+
+The domain begins at IN-ADDR.ARPA and has a substructure which follows
+the Internet addressing structure.
+
+Domain names in the IN-ADDR.ARPA domain are defined to have up to four
+labels in addition to the IN-ADDR.ARPA suffix. Each label represents
+one octet of an Internet address, and is expressed as a character string
+for a decimal value in the range 0-255 (with leading zeros omitted
+except in the case of a zero octet which is represented by a single
+zero).
+
+Host addresses are represented by domain names that have all four labels
+specified. Thus data for Internet address 10.2.0.52 is located at
+domain name 52.0.2.10.IN-ADDR.ARPA. The reversal, though awkward to
+read, allows zones to be delegated which are exactly one network of
+address space. For example, 10.IN-ADDR.ARPA can be a zone containing
+data for the ARPANET, while 26.IN-ADDR.ARPA can be a separate zone for
+MILNET. Address nodes are used to hold pointers to primary host names
+in the normal domain space.
+
+Network numbers correspond to some non-terminal nodes at various depths
+in the IN-ADDR.ARPA domain, since Internet network numbers are either 1,
+2, or 3 octets. Network nodes are used to hold pointers to the primary
+host names of gateways attached to that network. Since a gateway is, by
+definition, on more than one network, it will typically have two or more
+network nodes which point at it. Gateways will also have host level
+pointers at their fully qualified addresses.
+
+Both the gateway pointers at network nodes and the normal host pointers
+at full address nodes use the PTR RR to point back to the primary domain
+names of the corresponding hosts.
+
+For example, the IN-ADDR.ARPA domain will contain information about the
+ISI gateway between net 10 and 26, an MIT gateway from net 10 to MIT's
+
+
+
+Mockapetris [Page 22]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+net 18, and hosts A.ISI.EDU and MULTICS.MIT.EDU. Assuming that ISI
+gateway has addresses 10.2.0.22 and 26.0.0.103, and a name MILNET-
+GW.ISI.EDU, and the MIT gateway has addresses 10.0.0.77 and 18.10.0.4
+and a name GW.LCS.MIT.EDU, the domain database would contain:
+
+ 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 22.0.2.10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 103.0.0.26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 77.0.0.10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 4.0.10.18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 103.0.3.26.IN-ADDR.ARPA. PTR A.ISI.EDU.
+ 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU.
+
+Thus a program which wanted to locate gateways on net 10 would originate
+a query of the form QTYPE=PTR, QCLASS=IN, QNAME=10.IN-ADDR.ARPA. It
+would receive two RRs in response:
+
+ 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+
+The program could then originate QTYPE=A, QCLASS=IN queries for MILNET-
+GW.ISI.EDU. and GW.LCS.MIT.EDU. to discover the Internet addresses of
+these gateways.
+
+A resolver which wanted to find the host name corresponding to Internet
+host address 10.0.0.6 would pursue a query of the form QTYPE=PTR,
+QCLASS=IN, QNAME=6.0.0.10.IN-ADDR.ARPA, and would receive:
+
+ 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU.
+
+Several cautions apply to the use of these services:
+ - Since the IN-ADDR.ARPA special domain and the normal domain
+ for a particular host or gateway will be in different zones,
+ the possibility exists that that the data may be inconsistent.
+
+ - Gateways will often have two names in separate domains, only
+ one of which can be primary.
+
+ - Systems that use the domain database to initialize their
+ routing tables must start with enough gateway information to
+ guarantee that they can access the appropriate name server.
+
+ - The gateway data only reflects the existence of a gateway in a
+ manner equivalent to the current HOSTS.TXT file. It doesn't
+ replace the dynamic availability information from GGP or EGP.
+
+
+
+Mockapetris [Page 23]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.6. Defining new types, classes, and special namespaces
+
+The previously defined types and classes are the ones in use as of the
+date of this memo. New definitions should be expected. This section
+makes some recommendations to designers considering additions to the
+existing facilities. The mailing list NAMEDROPPERS@SRI-NIC.ARPA is the
+forum where general discussion of design issues takes place.
+
+In general, a new type is appropriate when new information is to be
+added to the database about an existing object, or we need new data
+formats for some totally new object. Designers should attempt to define
+types and their RDATA formats that are generally applicable to all
+classes, and which avoid duplication of information. New classes are
+appropriate when the DNS is to be used for a new protocol, etc which
+requires new class-specific data formats, or when a copy of the existing
+name space is desired, but a separate management domain is necessary.
+
+New types and classes need mnemonics for master files; the format of the
+master files requires that the mnemonics for type and class be disjoint.
+
+TYPE and CLASS values must be a proper subset of QTYPEs and QCLASSes
+respectively.
+
+The present system uses multiple RRs to represent multiple values of a
+type rather than storing multiple values in the RDATA section of a
+single RR. This is less efficient for most applications, but does keep
+RRs shorter. The multiple RRs assumption is incorporated in some
+experimental work on dynamic update methods.
+
+The present system attempts to minimize the duplication of data in the
+database in order to insure consistency. Thus, in order to find the
+address of the host for a mail exchange, you map the mail domain name to
+a host name, then the host name to addresses, rather than a direct
+mapping to host address. This approach is preferred because it avoids
+the opportunity for inconsistency.
+
+In defining a new type of data, multiple RR types should not be used to
+create an ordering between entries or express different formats for
+equivalent bindings, instead this information should be carried in the
+body of the RR and a single type used. This policy avoids problems with
+caching multiple types and defining QTYPEs to match multiple types.
+
+For example, the original form of mail exchange binding used two RR
+types one to represent a "closer" exchange (MD) and one to represent a
+"less close" exchange (MF). The difficulty is that the presence of one
+RR type in a cache doesn't convey any information about the other
+because the query which acquired the cached information might have used
+a QTYPE of MF, MD, or MAILA (which matched both). The redesigned
+
+
+
+Mockapetris [Page 24]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+service used a single type (MX) with a "preference" value in the RDATA
+section which can order different RRs. However, if any MX RRs are found
+in the cache, then all should be there.
+
+4. MESSAGES
+
+4.1. Format
+
+All communications inside of the domain protocol are carried in a single
+format called a message. The top level format of message is divided
+into 5 sections (some of which are empty in certain cases) shown below:
+
+ +---------------------+
+ | Header |
+ +---------------------+
+ | Question | the question for the name server
+ +---------------------+
+ | Answer | RRs answering the question
+ +---------------------+
+ | Authority | RRs pointing toward an authority
+ +---------------------+
+ | Additional | RRs holding additional information
+ +---------------------+
+
+The header section is always present. The header includes fields that
+specify which of the remaining sections are present, and also specify
+whether the message is a query or a response, a standard query or some
+other opcode, etc.
+
+The names of the sections after the header are derived from their use in
+standard queries. The question section contains fields that describe a
+question to a name server. These fields are a query type (QTYPE), a
+query class (QCLASS), and a query domain name (QNAME). The last three
+sections have the same format: a possibly empty list of concatenated
+resource records (RRs). The answer section contains RRs that answer the
+question; the authority section contains RRs that point toward an
+authoritative name server; the additional records section contains RRs
+which relate to the query, but are not strictly answers for the
+question.
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 25]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+4.1.1. Header section format
+
+The header contains the following fields:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ID |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QDCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ANCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | NSCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ARCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+ID A 16 bit identifier assigned by the program that
+ generates any kind of query. This identifier is copied
+ the corresponding reply and can be used by the requester
+ to match up replies to outstanding queries.
+
+QR A one bit field that specifies whether this message is a
+ query (0), or a response (1).
+
+OPCODE A four bit field that specifies kind of query in this
+ message. This value is set by the originator of a query
+ and copied into the response. The values are:
+
+ 0 a standard query (QUERY)
+
+ 1 an inverse query (IQUERY)
+
+ 2 a server status request (STATUS)
+
+ 3-15 reserved for future use
+
+AA Authoritative Answer - this bit is valid in responses,
+ and specifies that the responding name server is an
+ authority for the domain name in question section.
+
+ Note that the contents of the answer section may have
+ multiple owner names because of aliases. The AA bit
+
+
+
+Mockapetris [Page 26]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ corresponds to the name which matches the query name, or
+ the first owner name in the answer section.
+
+TC TrunCation - specifies that this message was truncated
+ due to length greater than that permitted on the
+ transmission channel.
+
+RD Recursion Desired - this bit may be set in a query and
+ is copied into the response. If RD is set, it directs
+ the name server to pursue the query recursively.
+ Recursive query support is optional.
+
+RA Recursion Available - this be is set or cleared in a
+ response, and denotes whether recursive query support is
+ available in the name server.
+
+Z Reserved for future use. Must be zero in all queries
+ and responses.
+
+RCODE Response code - this 4 bit field is set as part of
+ responses. The values have the following
+ interpretation:
+
+ 0 No error condition
+
+ 1 Format error - The name server was
+ unable to interpret the query.
+
+ 2 Server failure - The name server was
+ unable to process this query due to a
+ problem with the name server.
+
+ 3 Name Error - Meaningful only for
+ responses from an authoritative name
+ server, this code signifies that the
+ domain name referenced in the query does
+ not exist.
+
+ 4 Not Implemented - The name server does
+ not support the requested kind of query.
+
+ 5 Refused - The name server refuses to
+ perform the specified operation for
+ policy reasons. For example, a name
+ server may not wish to provide the
+ information to the particular requester,
+ or a name server may not wish to perform
+ a particular operation (e.g., zone
+
+
+
+Mockapetris [Page 27]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ transfer) for particular data.
+
+ 6-15 Reserved for future use.
+
+QDCOUNT an unsigned 16 bit integer specifying the number of
+ entries in the question section.
+
+ANCOUNT an unsigned 16 bit integer specifying the number of
+ resource records in the answer section.
+
+NSCOUNT an unsigned 16 bit integer specifying the number of name
+ server resource records in the authority records
+ section.
+
+ARCOUNT an unsigned 16 bit integer specifying the number of
+ resource records in the additional records section.
+
+4.1.2. Question section format
+
+The question section is used to carry the "question" in most queries,
+i.e., the parameters that define what is being asked. The section
+contains QDCOUNT (usually 1) entries, each of the following format:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / QNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QTYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QCLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+QNAME a domain name represented as a sequence of labels, where
+ each label consists of a length octet followed by that
+ number of octets. The domain name terminates with the
+ zero length octet for the null label of the root. Note
+ that this field may be an odd number of octets; no
+ padding is used.
+
+QTYPE a two octet code which specifies the type of the query.
+ The values for this field include all codes valid for a
+ TYPE field, together with some more general codes which
+ can match more than one type of RR.
+
+
+
+Mockapetris [Page 28]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+QCLASS a two octet code that specifies the class of the query.
+ For example, the QCLASS field is IN for the Internet.
+
+4.1.3. Resource record format
+
+The answer, authority, and additional sections all share the same
+format: a variable number of resource records, where the number of
+records is specified in the corresponding count field in the header.
+Each resource record has the following format:
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / /
+ / NAME /
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | CLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TTL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RDLENGTH |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+ / RDATA /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+NAME a domain name to which this resource record pertains.
+
+TYPE two octets containing one of the RR type codes. This
+ field specifies the meaning of the data in the RDATA
+ field.
+
+CLASS two octets which specify the class of the data in the
+ RDATA field.
+
+TTL a 32 bit unsigned integer that specifies the time
+ interval (in seconds) that the resource record may be
+ cached before it should be discarded. Zero values are
+ interpreted to mean that the RR can only be used for the
+ transaction in progress, and should not be cached.
+
+
+
+
+
+Mockapetris [Page 29]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+RDLENGTH an unsigned 16 bit integer that specifies the length in
+ octets of the RDATA field.
+
+RDATA a variable length string of octets that describes the
+ resource. The format of this information varies
+ according to the TYPE and CLASS of the resource record.
+ For example, the if the TYPE is A and the CLASS is IN,
+ the RDATA field is a 4 octet ARPA Internet address.
+
+4.1.4. Message compression
+
+In order to reduce the size of messages, the domain system utilizes a
+compression scheme which eliminates the repetition of domain names in a
+message. In this scheme, an entire domain name or a list of labels at
+the end of a domain name is replaced with a pointer to a prior occurance
+of the same name.
+
+The pointer takes the form of a two octet sequence:
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | 1 1| OFFSET |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+The first two bits are ones. This allows a pointer to be distinguished
+from a label, since the label must begin with two zero bits because
+labels are restricted to 63 octets or less. (The 10 and 01 combinations
+are reserved for future use.) The OFFSET field specifies an offset from
+the start of the message (i.e., the first octet of the ID field in the
+domain header). A zero offset specifies the first byte of the ID field,
+etc.
+
+The compression scheme allows a domain name in a message to be
+represented as either:
+
+ - a sequence of labels ending in a zero octet
+
+ - a pointer
+
+ - a sequence of labels ending with a pointer
+
+Pointers can only be used for occurances of a domain name where the
+format is not class specific. If this were not the case, a name server
+or resolver would be required to know the format of all RRs it handled.
+As yet, there are no such cases, but they may occur in future RDATA
+formats.
+
+If a domain name is contained in a part of the message subject to a
+length field (such as the RDATA section of an RR), and compression is
+
+
+
+Mockapetris [Page 30]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+used, the length of the compressed name is used in the length
+calculation, rather than the length of the expanded name.
+
+Programs are free to avoid using pointers in messages they generate,
+although this will reduce datagram capacity, and may cause truncation.
+However all programs are required to understand arriving messages that
+contain pointers.
+
+For example, a datagram might need to use the domain names F.ISI.ARPA,
+FOO.F.ISI.ARPA, ARPA, and the root. Ignoring the other fields of the
+message, these domain names might be represented as:
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 20 | 1 | F |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 22 | 3 | I |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 24 | S | I |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 26 | 4 | A |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 28 | R | P |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 30 | A | 0 |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 40 | 3 | F |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 42 | O | O |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 44 | 1 1| 20 |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 64 | 1 1| 26 |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 92 | 0 | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+The domain name for F.ISI.ARPA is shown at offset 20. The domain name
+FOO.F.ISI.ARPA is shown at offset 40; this definition uses a pointer to
+concatenate a label for FOO to the previously defined F.ISI.ARPA. The
+domain name ARPA is defined at offset 64 using a pointer to the ARPA
+component of the name F.ISI.ARPA at 20; note that this pointer relies on
+ARPA being the last label in the string at 20. The root domain name is
+
+
+
+Mockapetris [Page 31]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+defined by a single octet of zeros at 92; the root domain name has no
+labels.
+
+4.2. Transport
+
+The DNS assumes that messages will be transmitted as datagrams or in a
+byte stream carried by a virtual circuit. While virtual circuits can be
+used for any DNS activity, datagrams are preferred for queries due to
+their lower overhead and better performance. Zone refresh activities
+must use virtual circuits because of the need for reliable transfer.
+
+The Internet supports name server access using TCP [RFC-793] on server
+port 53 (decimal) as well as datagram access using UDP [RFC-768] on UDP
+port 53 (decimal).
+
+4.2.1. UDP usage
+
+Messages sent using UDP user server port 53 (decimal).
+
+Messages carried by UDP are restricted to 512 bytes (not counting the IP
+or UDP headers). Longer messages are truncated and the TC bit is set in
+the header.
+
+UDP is not acceptable for zone transfers, but is the recommended method
+for standard queries in the Internet. Queries sent using UDP may be
+lost, and hence a retransmission strategy is required. Queries or their
+responses may be reordered by the network, or by processing in name
+servers, so resolvers should not depend on them being returned in order.
+
+The optimal UDP retransmission policy will vary with performance of the
+Internet and the needs of the client, but the following are recommended:
+
+ - The client should try other servers and server addresses
+ before repeating a query to a specific address of a server.
+
+ - The retransmission interval should be based on prior
+ statistics if possible. Too aggressive retransmission can
+ easily slow responses for the community at large. Depending
+ on how well connected the client is to its expected servers,
+ the minimum retransmission interval should be 2-5 seconds.
+
+More suggestions on server selection and retransmission policy can be
+found in the resolver section of this memo.
+
+4.2.2. TCP usage
+
+Messages sent over TCP connections use server port 53 (decimal). The
+message is prefixed with a two byte length field which gives the message
+
+
+
+Mockapetris [Page 32]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+length, excluding the two byte length field. This length field allows
+the low-level processing to assemble a complete message before beginning
+to parse it.
+
+Several connection management policies are recommended:
+
+ - The server should not block other activities waiting for TCP
+ data.
+
+ - The server should support multiple connections.
+
+ - The server should assume that the client will initiate
+ connection closing, and should delay closing its end of the
+ connection until all outstanding client requests have been
+ satisfied.
+
+ - If the server needs to close a dormant connection to reclaim
+ resources, it should wait until the connection has been idle
+ for a period on the order of two minutes. In particular, the
+ server should allow the SOA and AXFR request sequence (which
+ begins a refresh operation) to be made on a single connection.
+ Since the server would be unable to answer queries anyway, a
+ unilateral close or reset may be used instead of a graceful
+ close.
+
+5. MASTER FILES
+
+Master files are text files that contain RRs in text form. Since the
+contents of a zone can be expressed in the form of a list of RRs a
+master file is most often used to define a zone, though it can be used
+to list a cache's contents. Hence, this section first discusses the
+format of RRs in a master file, and then the special considerations when
+a master file is used to create a zone in some name server.
+
+5.1. Format
+
+The format of these files is a sequence of entries. Entries are
+predominantly line-oriented, though parentheses can be used to continue
+a list of items across a line boundary, and text literals can contain
+CRLF within the text. Any combination of tabs and spaces act as a
+delimiter between the separate items that make up an entry. The end of
+any line in the master file can end with a comment. The comment starts
+with a ";" (semicolon).
+
+The following entries are defined:
+
+ <blank>[<comment>]
+
+
+
+
+Mockapetris [Page 33]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ $ORIGIN <domain-name> [<comment>]
+
+ $INCLUDE <file-name> [<domain-name>] [<comment>]
+
+ <domain-name><rr> [<comment>]
+
+ <blank><rr> [<comment>]
+
+Blank lines, with or without comments, are allowed anywhere in the file.
+
+Two control entries are defined: $ORIGIN and $INCLUDE. $ORIGIN is
+followed by a domain name, and resets the current origin for relative
+domain names to the stated name. $INCLUDE inserts the named file into
+the current file, and may optionally specify a domain name that sets the
+relative domain name origin for the included file. $INCLUDE may also
+have a comment. Note that a $INCLUDE entry never changes the relative
+origin of the parent file, regardless of changes to the relative origin
+made within the included file.
+
+The last two forms represent RRs. If an entry for an RR begins with a
+blank, then the RR is assumed to be owned by the last stated owner. If
+an RR entry begins with a <domain-name>, then the owner name is reset.
+
+<rr> contents take one of the following forms:
+
+ [<TTL>] [<class>] <type> <RDATA>
+
+ [<class>] [<TTL>] <type> <RDATA>
+
+The RR begins with optional TTL and class fields, followed by a type and
+RDATA field appropriate to the type and class. Class and type use the
+standard mnemonics, TTL is a decimal integer. Omitted class and TTL
+values are default to the last explicitly stated values. Since type and
+class mnemonics are disjoint, the parse is unique. (Note that this
+order is different from the order used in examples and the order used in
+the actual RRs; the given order allows easier parsing and defaulting.)
+
+<domain-name>s make up a large share of the data in the master file.
+The labels in the domain name are expressed as character strings and
+separated by dots. Quoting conventions allow arbitrary characters to be
+stored in domain names. Domain names that end in a dot are called
+absolute, and are taken as complete. Domain names which do not end in a
+dot are called relative; the actual domain name is the concatenation of
+the relative part with an origin specified in a $ORIGIN, $INCLUDE, or as
+an argument to the master file loading routine. A relative name is an
+error when no origin is available.
+
+
+
+
+
+Mockapetris [Page 34]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+<character-string> is expressed in one or two ways: as a contiguous set
+of characters without interior spaces, or as a string beginning with a "
+and ending with a ". Inside a " delimited string any character can
+occur, except for a " itself, which must be quoted using \ (back slash).
+
+Because these files are text files several special encodings are
+necessary to allow arbitrary data to be loaded. In particular:
+
+ of the root.
+
+@ A free standing @ is used to denote the current origin.
+
+\X where X is any character other than a digit (0-9), is
+ used to quote that character so that its special meaning
+ does not apply. For example, "\." can be used to place
+ a dot character in a label.
+
+\DDD where each D is a digit is the octet corresponding to
+ the decimal number described by DDD. The resulting
+ octet is assumed to be text and is not checked for
+ special meaning.
+
+( ) Parentheses are used to group data that crosses a line
+ boundary. In effect, line terminations are not
+ recognized within parentheses.
+
+; Semicolon is used to start a comment; the remainder of
+ the line is ignored.
+
+5.2. Use of master files to define zones
+
+When a master file is used to load a zone, the operation should be
+suppressed if any errors are encountered in the master file. The
+rationale for this is that a single error can have widespread
+consequences. For example, suppose that the RRs defining a delegation
+have syntax errors; then the server will return authoritative name
+errors for all names in the subzone (except in the case where the
+subzone is also present on the server).
+
+Several other validity checks that should be performed in addition to
+insuring that the file is syntactically correct:
+
+ 1. All RRs in the file should have the same class.
+
+ 2. Exactly one SOA RR should be present at the top of the zone.
+
+ 3. If delegations are present and glue information is required,
+ it should be present.
+
+
+
+Mockapetris [Page 35]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 4. Information present outside of the authoritative nodes in the
+ zone should be glue information, rather than the result of an
+ origin or similar error.
+
+5.3. Master file example
+
+The following is an example file which might be used to define the
+ISI.EDU zone.and is loaded with an origin of ISI.EDU:
+
+@ IN SOA VENERA Action\.domains (
+ 20 ; SERIAL
+ 7200 ; REFRESH
+ 600 ; RETRY
+ 3600000; EXPIRE
+ 60) ; MINIMUM
+
+ NS A.ISI.EDU.
+ NS VENERA
+ NS VAXA
+ MX 10 VENERA
+ MX 20 VAXA
+
+A A 26.3.0.103
+
+VENERA A 10.1.0.52
+ A 128.9.0.32
+
+VAXA A 10.2.0.27
+ A 128.9.0.33
+
+
+$INCLUDE <SUBSYS>ISI-MAILBOXES.TXT
+
+Where the file <SUBSYS>ISI-MAILBOXES.TXT is:
+
+ MOE MB A.ISI.EDU.
+ LARRY MB A.ISI.EDU.
+ CURLEY MB A.ISI.EDU.
+ STOOGES MG MOE
+ MG LARRY
+ MG CURLEY
+
+Note the use of the \ character in the SOA RR to specify the responsible
+person mailbox "Action.domains@E.ISI.EDU".
+
+
+
+
+
+
+
+Mockapetris [Page 36]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+6. NAME SERVER IMPLEMENTATION
+
+6.1. Architecture
+
+The optimal structure for the name server will depend on the host
+operating system and whether the name server is integrated with resolver
+operations, either by supporting recursive service, or by sharing its
+database with a resolver. This section discusses implementation
+considerations for a name server which shares a database with a
+resolver, but most of these concerns are present in any name server.
+
+6.1.1. Control
+
+A name server must employ multiple concurrent activities, whether they
+are implemented as separate tasks in the host's OS or multiplexing
+inside a single name server program. It is simply not acceptable for a
+name server to block the service of UDP requests while it waits for TCP
+data for refreshing or query activities. Similarly, a name server
+should not attempt to provide recursive service without processing such
+requests in parallel, though it may choose to serialize requests from a
+single client, or to regard identical requests from the same client as
+duplicates. A name server should not substantially delay requests while
+it reloads a zone from master files or while it incorporates a newly
+refreshed zone into its database.
+
+6.1.2. Database
+
+While name server implementations are free to use any internal data
+structures they choose, the suggested structure consists of three major
+parts:
+
+ - A "catalog" data structure which lists the zones available to
+ this server, and a "pointer" to the zone data structure. The
+ main purpose of this structure is to find the nearest ancestor
+ zone, if any, for arriving standard queries.
+
+ - Separate data structures for each of the zones held by the
+ name server.
+
+ - A data structure for cached data. (or perhaps separate caches
+ for different classes)
+
+All of these data structures can be implemented an identical tree
+structure format, with different data chained off the nodes in different
+parts: in the catalog the data is pointers to zones, while in the zone
+and cache data structures, the data will be RRs. In designing the tree
+framework the designer should recognize that query processing will need
+to traverse the tree using case-insensitive label comparisons; and that
+
+
+
+Mockapetris [Page 37]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+in real data, a few nodes have a very high branching factor (100-1000 or
+more), but the vast majority have a very low branching factor (0-1).
+
+One way to solve the case problem is to store the labels for each node
+in two pieces: a standardized-case representation of the label where all
+ASCII characters are in a single case, together with a bit mask that
+denotes which characters are actually of a different case. The
+branching factor diversity can be handled using a simple linked list for
+a node until the branching factor exceeds some threshold, and
+transitioning to a hash structure after the threshold is exceeded. In
+any case, hash structures used to store tree sections must insure that
+hash functions and procedures preserve the casing conventions of the
+DNS.
+
+The use of separate structures for the different parts of the database
+is motivated by several factors:
+
+ - The catalog structure can be an almost static structure that
+ need change only when the system administrator changes the
+ zones supported by the server. This structure can also be
+ used to store parameters used to control refreshing
+ activities.
+
+ - The individual data structures for zones allow a zone to be
+ replaced simply by changing a pointer in the catalog. Zone
+ refresh operations can build a new structure and, when
+ complete, splice it into the database via a simple pointer
+ replacement. It is very important that when a zone is
+ refreshed, queries should not use old and new data
+ simultaneously.
+
+ - With the proper search procedures, authoritative data in zones
+ will always "hide", and hence take precedence over, cached
+ data.
+
+ - Errors in zone definitions that cause overlapping zones, etc.,
+ may cause erroneous responses to queries, but problem
+ determination is simplified, and the contents of one "bad"
+ zone can't corrupt another.
+
+ - Since the cache is most frequently updated, it is most
+ vulnerable to corruption during system restarts. It can also
+ become full of expired RR data. In either case, it can easily
+ be discarded without disturbing zone data.
+
+A major aspect of database design is selecting a structure which allows
+the name server to deal with crashes of the name server's host. State
+information which a name server should save across system crashes
+
+
+
+Mockapetris [Page 38]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+includes the catalog structure (including the state of refreshing for
+each zone) and the zone data itself.
+
+6.1.3. Time
+
+Both the TTL data for RRs and the timing data for refreshing activities
+depends on 32 bit timers in units of seconds. Inside the database,
+refresh timers and TTLs for cached data conceptually "count down", while
+data in the zone stays with constant TTLs.
+
+A recommended implementation strategy is to store time in two ways: as
+a relative increment and as an absolute time. One way to do this is to
+use positive 32 bit numbers for one type and negative numbers for the
+other. The RRs in zones use relative times; the refresh timers and
+cache data use absolute times. Absolute numbers are taken with respect
+to some known origin and converted to relative values when placed in the
+response to a query. When an absolute TTL is negative after conversion
+to relative, then the data is expired and should be ignored.
+
+6.2. Standard query processing
+
+The major algorithm for standard query processing is presented in
+[RFC-1034].
+
+When processing queries with QCLASS=*, or some other QCLASS which
+matches multiple classes, the response should never be authoritative
+unless the server can guarantee that the response covers all classes.
+
+When composing a response, RRs which are to be inserted in the
+additional section, but duplicate RRs in the answer or authority
+sections, may be omitted from the additional section.
+
+When a response is so long that truncation is required, the truncation
+should start at the end of the response and work forward in the
+datagram. Thus if there is any data for the authority section, the
+answer section is guaranteed to be unique.
+
+The MINIMUM value in the SOA should be used to set a floor on the TTL of
+data distributed from a zone. This floor function should be done when
+the data is copied into a response. This will allow future dynamic
+update protocols to change the SOA MINIMUM field without ambiguous
+semantics.
+
+6.3. Zone refresh and reload processing
+
+In spite of a server's best efforts, it may be unable to load zone data
+from a master file due to syntax errors, etc., or be unable to refresh a
+zone within the its expiration parameter. In this case, the name server
+
+
+
+Mockapetris [Page 39]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+should answer queries as if it were not supposed to possess the zone.
+
+If a master is sending a zone out via AXFR, and a new version is created
+during the transfer, the master should continue to send the old version
+if possible. In any case, it should never send part of one version and
+part of another. If completion is not possible, the master should reset
+the connection on which the zone transfer is taking place.
+
+6.4. Inverse queries (Optional)
+
+Inverse queries are an optional part of the DNS. Name servers are not
+required to support any form of inverse queries. If a name server
+receives an inverse query that it does not support, it returns an error
+response with the "Not Implemented" error set in the header. While
+inverse query support is optional, all name servers must be at least
+able to return the error response.
+
+6.4.1. The contents of inverse queries and responses Inverse
+queries reverse the mappings performed by standard query operations;
+while a standard query maps a domain name to a resource, an inverse
+query maps a resource to a domain name. For example, a standard query
+might bind a domain name to a host address; the corresponding inverse
+query binds the host address to a domain name.
+
+Inverse queries take the form of a single RR in the answer section of
+the message, with an empty question section. The owner name of the
+query RR and its TTL are not significant. The response carries
+questions in the question section which identify all names possessing
+the query RR WHICH THE NAME SERVER KNOWS. Since no name server knows
+about all of the domain name space, the response can never be assumed to
+be complete. Thus inverse queries are primarily useful for database
+management and debugging activities. Inverse queries are NOT an
+acceptable method of mapping host addresses to host names; use the IN-
+ADDR.ARPA domain instead.
+
+Where possible, name servers should provide case-insensitive comparisons
+for inverse queries. Thus an inverse query asking for an MX RR of
+"Venera.isi.edu" should get the same response as a query for
+"VENERA.ISI.EDU"; an inverse query for HINFO RR "IBM-PC UNIX" should
+produce the same result as an inverse query for "IBM-pc unix". However,
+this cannot be guaranteed because name servers may possess RRs that
+contain character strings but the name server does not know that the
+data is character.
+
+When a name server processes an inverse query, it either returns:
+
+ 1. zero, one, or multiple domain names for the specified
+ resource as QNAMEs in the question section
+
+
+
+Mockapetris [Page 40]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 2. an error code indicating that the name server doesn't support
+ inverse mapping of the specified resource type.
+
+When the response to an inverse query contains one or more QNAMEs, the
+owner name and TTL of the RR in the answer section which defines the
+inverse query is modified to exactly match an RR found at the first
+QNAME.
+
+RRs returned in the inverse queries cannot be cached using the same
+mechanism as is used for the replies to standard queries. One reason
+for this is that a name might have multiple RRs of the same type, and
+only one would appear. For example, an inverse query for a single
+address of a multiply homed host might create the impression that only
+one address existed.
+
+6.4.2. Inverse query and response example The overall structure
+of an inverse query for retrieving the domain name that corresponds to
+Internet address 10.1.0.52 is shown below:
+
+ +-----------------------------------------+
+ Header | OPCODE=IQUERY, ID=997 |
+ +-----------------------------------------+
+ Question | <empty> |
+ +-----------------------------------------+
+ Answer | <anyname> A IN 10.1.0.52 |
+ +-----------------------------------------+
+ Authority | <empty> |
+ +-----------------------------------------+
+ Additional | <empty> |
+ +-----------------------------------------+
+
+This query asks for a question whose answer is the Internet style
+address 10.1.0.52. Since the owner name is not known, any domain name
+can be used as a placeholder (and is ignored). A single octet of zero,
+signifying the root, is usually used because it minimizes the length of
+the message. The TTL of the RR is not significant. The response to
+this query might be:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 41]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ +-----------------------------------------+
+ Header | OPCODE=RESPONSE, ID=997 |
+ +-----------------------------------------+
+ Question |QTYPE=A, QCLASS=IN, QNAME=VENERA.ISI.EDU |
+ +-----------------------------------------+
+ Answer | VENERA.ISI.EDU A IN 10.1.0.52 |
+ +-----------------------------------------+
+ Authority | <empty> |
+ +-----------------------------------------+
+ Additional | <empty> |
+ +-----------------------------------------+
+
+Note that the QTYPE in a response to an inverse query is the same as the
+TYPE field in the answer section of the inverse query. Responses to
+inverse queries may contain multiple questions when the inverse is not
+unique. If the question section in the response is not empty, then the
+RR in the answer section is modified to correspond to be an exact copy
+of an RR at the first QNAME.
+
+6.4.3. Inverse query processing
+
+Name servers that support inverse queries can support these operations
+through exhaustive searches of their databases, but this becomes
+impractical as the size of the database increases. An alternative
+approach is to invert the database according to the search key.
+
+For name servers that support multiple zones and a large amount of data,
+the recommended approach is separate inversions for each zone. When a
+particular zone is changed during a refresh, only its inversions need to
+be redone.
+
+Support for transfer of this type of inversion may be included in future
+versions of the domain system, but is not supported in this version.
+
+6.5. Completion queries and responses
+
+The optional completion services described in RFC-882 and RFC-883 have
+been deleted. Redesigned services may become available in the future.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 42]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+7. RESOLVER IMPLEMENTATION
+
+The top levels of the recommended resolver algorithm are discussed in
+[RFC-1034]. This section discusses implementation details assuming the
+database structure suggested in the name server implementation section
+of this memo.
+
+7.1. Transforming a user request into a query
+
+The first step a resolver takes is to transform the client's request,
+stated in a format suitable to the local OS, into a search specification
+for RRs at a specific name which match a specific QTYPE and QCLASS.
+Where possible, the QTYPE and QCLASS should correspond to a single type
+and a single class, because this makes the use of cached data much
+simpler. The reason for this is that the presence of data of one type
+in a cache doesn't confirm the existence or non-existence of data of
+other types, hence the only way to be sure is to consult an
+authoritative source. If QCLASS=* is used, then authoritative answers
+won't be available.
+
+Since a resolver must be able to multiplex multiple requests if it is to
+perform its function efficiently, each pending request is usually
+represented in some block of state information. This state block will
+typically contain:
+
+ - A timestamp indicating the time the request began.
+ The timestamp is used to decide whether RRs in the database
+ can be used or are out of date. This timestamp uses the
+ absolute time format previously discussed for RR storage in
+ zones and caches. Note that when an RRs TTL indicates a
+ relative time, the RR must be timely, since it is part of a
+ zone. When the RR has an absolute time, it is part of a
+ cache, and the TTL of the RR is compared against the timestamp
+ for the start of the request.
+
+ Note that using the timestamp is superior to using a current
+ time, since it allows RRs with TTLs of zero to be entered in
+ the cache in the usual manner, but still used by the current
+ request, even after intervals of many seconds due to system
+ load, query retransmission timeouts, etc.
+
+ - Some sort of parameters to limit the amount of work which will
+ be performed for this request.
+
+ The amount of work which a resolver will do in response to a
+ client request must be limited to guard against errors in the
+ database, such as circular CNAME references, and operational
+ problems, such as network partition which prevents the
+
+
+
+Mockapetris [Page 43]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ resolver from accessing the name servers it needs. While
+ local limits on the number of times a resolver will retransmit
+ a particular query to a particular name server address are
+ essential, the resolver should have a global per-request
+ counter to limit work on a single request. The counter should
+ be set to some initial value and decremented whenever the
+ resolver performs any action (retransmission timeout,
+ retransmission, etc.) If the counter passes zero, the request
+ is terminated with a temporary error.
+
+ Note that if the resolver structure allows one request to
+ start others in parallel, such as when the need to access a
+ name server for one request causes a parallel resolve for the
+ name server's addresses, the spawned request should be started
+ with a lower counter. This prevents circular references in
+ the database from starting a chain reaction of resolver
+ activity.
+
+ - The SLIST data structure discussed in [RFC-1034].
+
+ This structure keeps track of the state of a request if it
+ must wait for answers from foreign name servers.
+
+7.2. Sending the queries
+
+As described in [RFC-1034], the basic task of the resolver is to
+formulate a query which will answer the client's request and direct that
+query to name servers which can provide the information. The resolver
+will usually only have very strong hints about which servers to ask, in
+the form of NS RRs, and may have to revise the query, in response to
+CNAMEs, or revise the set of name servers the resolver is asking, in
+response to delegation responses which point the resolver to name
+servers closer to the desired information. In addition to the
+information requested by the client, the resolver may have to call upon
+its own services to determine the address of name servers it wishes to
+contact.
+
+In any case, the model used in this memo assumes that the resolver is
+multiplexing attention between multiple requests, some from the client,
+and some internally generated. Each request is represented by some
+state information, and the desired behavior is that the resolver
+transmit queries to name servers in a way that maximizes the probability
+that the request is answered, minimizes the time that the request takes,
+and avoids excessive transmissions. The key algorithm uses the state
+information of the request to select the next name server address to
+query, and also computes a timeout which will cause the next action
+should a response not arrive. The next action will usually be a
+transmission to some other server, but may be a temporary error to the
+
+
+
+Mockapetris [Page 44]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+client.
+
+The resolver always starts with a list of server names to query (SLIST).
+This list will be all NS RRs which correspond to the nearest ancestor
+zone that the resolver knows about. To avoid startup problems, the
+resolver should have a set of default servers which it will ask should
+it have no current NS RRs which are appropriate. The resolver then adds
+to SLIST all of the known addresses for the name servers, and may start
+parallel requests to acquire the addresses of the servers when the
+resolver has the name, but no addresses, for the name servers.
+
+To complete initialization of SLIST, the resolver attaches whatever
+history information it has to the each address in SLIST. This will
+usually consist of some sort of weighted averages for the response time
+of the address, and the batting average of the address (i.e., how often
+the address responded at all to the request). Note that this
+information should be kept on a per address basis, rather than on a per
+name server basis, because the response time and batting average of a
+particular server may vary considerably from address to address. Note
+also that this information is actually specific to a resolver address /
+server address pair, so a resolver with multiple addresses may wish to
+keep separate histories for each of its addresses. Part of this step
+must deal with addresses which have no such history; in this case an
+expected round trip time of 5-10 seconds should be the worst case, with
+lower estimates for the same local network, etc.
+
+Note that whenever a delegation is followed, the resolver algorithm
+reinitializes SLIST.
+
+The information establishes a partial ranking of the available name
+server addresses. Each time an address is chosen and the state should
+be altered to prevent its selection again until all other addresses have
+been tried. The timeout for each transmission should be 50-100% greater
+than the average predicted value to allow for variance in response.
+
+Some fine points:
+
+ - The resolver may encounter a situation where no addresses are
+ available for any of the name servers named in SLIST, and
+ where the servers in the list are precisely those which would
+ normally be used to look up their own addresses. This
+ situation typically occurs when the glue address RRs have a
+ smaller TTL than the NS RRs marking delegation, or when the
+ resolver caches the result of a NS search. The resolver
+ should detect this condition and restart the search at the
+ next ancestor zone, or alternatively at the root.
+
+
+
+
+
+Mockapetris [Page 45]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ - If a resolver gets a server error or other bizarre response
+ from a name server, it should remove it from SLIST, and may
+ wish to schedule an immediate transmission to the next
+ candidate server address.
+
+7.3. Processing responses
+
+The first step in processing arriving response datagrams is to parse the
+response. This procedure should include:
+
+ - Check the header for reasonableness. Discard datagrams which
+ are queries when responses are expected.
+
+ - Parse the sections of the message, and insure that all RRs are
+ correctly formatted.
+
+ - As an optional step, check the TTLs of arriving data looking
+ for RRs with excessively long TTLs. If a RR has an
+ excessively long TTL, say greater than 1 week, either discard
+ the whole response, or limit all TTLs in the response to 1
+ week.
+
+The next step is to match the response to a current resolver request.
+The recommended strategy is to do a preliminary matching using the ID
+field in the domain header, and then to verify that the question section
+corresponds to the information currently desired. This requires that
+the transmission algorithm devote several bits of the domain ID field to
+a request identifier of some sort. This step has several fine points:
+
+ - Some name servers send their responses from different
+ addresses than the one used to receive the query. That is, a
+ resolver cannot rely that a response will come from the same
+ address which it sent the corresponding query to. This name
+ server bug is typically encountered in UNIX systems.
+
+ - If the resolver retransmits a particular request to a name
+ server it should be able to use a response from any of the
+ transmissions. However, if it is using the response to sample
+ the round trip time to access the name server, it must be able
+ to determine which transmission matches the response (and keep
+ transmission times for each outgoing message), or only
+ calculate round trip times based on initial transmissions.
+
+ - A name server will occasionally not have a current copy of a
+ zone which it should have according to some NS RRs. The
+ resolver should simply remove the name server from the current
+ SLIST, and continue.
+
+
+
+
+Mockapetris [Page 46]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+7.4. Using the cache
+
+In general, we expect a resolver to cache all data which it receives in
+responses since it may be useful in answering future client requests.
+However, there are several types of data which should not be cached:
+
+ - When several RRs of the same type are available for a
+ particular owner name, the resolver should either cache them
+ all or none at all. When a response is truncated, and a
+ resolver doesn't know whether it has a complete set, it should
+ not cache a possibly partial set of RRs.
+
+ - Cached data should never be used in preference to
+ authoritative data, so if caching would cause this to happen
+ the data should not be cached.
+
+ - The results of an inverse query should not be cached.
+
+ - The results of standard queries where the QNAME contains "*"
+ labels if the data might be used to construct wildcards. The
+ reason is that the cache does not necessarily contain existing
+ RRs or zone boundary information which is necessary to
+ restrict the application of the wildcard RRs.
+
+ - RR data in responses of dubious reliability. When a resolver
+ receives unsolicited responses or RR data other than that
+ requested, it should discard it without caching it. The basic
+ implication is that all sanity checks on a packet should be
+ performed before any of it is cached.
+
+In a similar vein, when a resolver has a set of RRs for some name in a
+response, and wants to cache the RRs, it should check its cache for
+already existing RRs. Depending on the circumstances, either the data
+in the response or the cache is preferred, but the two should never be
+combined. If the data in the response is from authoritative data in the
+answer section, it is always preferred.
+
+8. MAIL SUPPORT
+
+The domain system defines a standard for mapping mailboxes into domain
+names, and two methods for using the mailbox information to derive mail
+routing information. The first method is called mail exchange binding
+and the other method is mailbox binding. The mailbox encoding standard
+and mail exchange binding are part of the DNS official protocol, and are
+the recommended method for mail routing in the Internet. Mailbox
+binding is an experimental feature which is still under development and
+subject to change.
+
+
+
+
+Mockapetris [Page 47]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+The mailbox encoding standard assumes a mailbox name of the form
+"<local-part>@<mail-domain>". While the syntax allowed in each of these
+sections varies substantially between the various mail internets, the
+preferred syntax for the ARPA Internet is given in [RFC-822].
+
+The DNS encodes the <local-part> as a single label, and encodes the
+<mail-domain> as a domain name. The single label from the <local-part>
+is prefaced to the domain name from <mail-domain> to form the domain
+name corresponding to the mailbox. Thus the mailbox HOSTMASTER@SRI-
+NIC.ARPA is mapped into the domain name HOSTMASTER.SRI-NIC.ARPA. If the
+<local-part> contains dots or other special characters, its
+representation in a master file will require the use of backslash
+quoting to ensure that the domain name is properly encoded. For
+example, the mailbox Action.domains@ISI.EDU would be represented as
+Action\.domains.ISI.EDU.
+
+8.1. Mail exchange binding
+
+Mail exchange binding uses the <mail-domain> part of a mailbox
+specification to determine where mail should be sent. The <local-part>
+is not even consulted. [RFC-974] specifies this method in detail, and
+should be consulted before attempting to use mail exchange support.
+
+One of the advantages of this method is that it decouples mail
+destination naming from the hosts used to support mail service, at the
+cost of another layer of indirection in the lookup function. However,
+the addition layer should eliminate the need for complicated "%", "!",
+etc encodings in <local-part>.
+
+The essence of the method is that the <mail-domain> is used as a domain
+name to locate type MX RRs which list hosts willing to accept mail for
+<mail-domain>, together with preference values which rank the hosts
+according to an order specified by the administrators for <mail-domain>.
+
+In this memo, the <mail-domain> ISI.EDU is used in examples, together
+with the hosts VENERA.ISI.EDU and VAXA.ISI.EDU as mail exchanges for
+ISI.EDU. If a mailer had a message for Mockapetris@ISI.EDU, it would
+route it by looking up MX RRs for ISI.EDU. The MX RRs at ISI.EDU name
+VENERA.ISI.EDU and VAXA.ISI.EDU, and type A queries can find the host
+addresses.
+
+8.2. Mailbox binding (Experimental)
+
+In mailbox binding, the mailer uses the entire mail destination
+specification to construct a domain name. The encoded domain name for
+the mailbox is used as the QNAME field in a QTYPE=MAILB query.
+
+Several outcomes are possible for this query:
+
+
+
+Mockapetris [Page 48]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 1. The query can return a name error indicating that the mailbox
+ does not exist as a domain name.
+
+ In the long term, this would indicate that the specified
+ mailbox doesn't exist. However, until the use of mailbox
+ binding is universal, this error condition should be
+ interpreted to mean that the organization identified by the
+ global part does not support mailbox binding. The
+ appropriate procedure is to revert to exchange binding at
+ this point.
+
+ 2. The query can return a Mail Rename (MR) RR.
+
+ The MR RR carries new mailbox specification in its RDATA
+ field. The mailer should replace the old mailbox with the
+ new one and retry the operation.
+
+ 3. The query can return a MB RR.
+
+ The MB RR carries a domain name for a host in its RDATA
+ field. The mailer should deliver the message to that host
+ via whatever protocol is applicable, e.g., b,SMTP.
+
+ 4. The query can return one or more Mail Group (MG) RRs.
+
+ This condition means that the mailbox was actually a mailing
+ list or mail group, rather than a single mailbox. Each MG RR
+ has a RDATA field that identifies a mailbox that is a member
+ of the group. The mailer should deliver a copy of the
+ message to each member.
+
+ 5. The query can return a MB RR as well as one or more MG RRs.
+
+ This condition means the the mailbox was actually a mailing
+ list. The mailer can either deliver the message to the host
+ specified by the MB RR, which will in turn do the delivery to
+ all members, or the mailer can use the MG RRs to do the
+ expansion itself.
+
+In any of these cases, the response may include a Mail Information
+(MINFO) RR. This RR is usually associated with a mail group, but is
+legal with a MB. The MINFO RR identifies two mailboxes. One of these
+identifies a responsible person for the original mailbox name. This
+mailbox should be used for requests to be added to a mail group, etc.
+The second mailbox name in the MINFO RR identifies a mailbox that should
+receive error messages for mail failures. This is particularly
+appropriate for mailing lists when errors in member names should be
+reported to a person other than the one who sends a message to the list.
+
+
+
+Mockapetris [Page 49]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+New fields may be added to this RR in the future.
+
+
+9. REFERENCES and BIBLIOGRAPHY
+
+[Dyer 87] S. Dyer, F. Hsu, "Hesiod", Project Athena
+ Technical Plan - Name Service, April 1987, version 1.9.
+
+ Describes the fundamentals of the Hesiod name service.
+
+[IEN-116] J. Postel, "Internet Name Server", IEN-116,
+ USC/Information Sciences Institute, August 1979.
+
+ A name service obsoleted by the Domain Name System, but
+ still in use.
+
+[Quarterman 86] J. Quarterman, and J. Hoskins, "Notable Computer Networks",
+ Communications of the ACM, October 1986, volume 29, number
+ 10.
+
+[RFC-742] K. Harrenstien, "NAME/FINGER", RFC-742, Network
+ Information Center, SRI International, December 1977.
+
+[RFC-768] J. Postel, "User Datagram Protocol", RFC-768,
+ USC/Information Sciences Institute, August 1980.
+
+[RFC-793] J. Postel, "Transmission Control Protocol", RFC-793,
+ USC/Information Sciences Institute, September 1981.
+
+[RFC-799] D. Mills, "Internet Name Domains", RFC-799, COMSAT,
+ September 1981.
+
+ Suggests introduction of a hierarchy in place of a flat
+ name space for the Internet.
+
+[RFC-805] J. Postel, "Computer Mail Meeting Notes", RFC-805,
+ USC/Information Sciences Institute, February 1982.
+
+[RFC-810] E. Feinler, K. Harrenstien, Z. Su, and V. White, "DOD
+ Internet Host Table Specification", RFC-810, Network
+ Information Center, SRI International, March 1982.
+
+ Obsolete. See RFC-952.
+
+[RFC-811] K. Harrenstien, V. White, and E. Feinler, "Hostnames
+ Server", RFC-811, Network Information Center, SRI
+ International, March 1982.
+
+
+
+
+Mockapetris [Page 50]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ Obsolete. See RFC-953.
+
+[RFC-812] K. Harrenstien, and V. White, "NICNAME/WHOIS", RFC-812,
+ Network Information Center, SRI International, March
+ 1982.
+
+[RFC-819] Z. Su, and J. Postel, "The Domain Naming Convention for
+ Internet User Applications", RFC-819, Network
+ Information Center, SRI International, August 1982.
+
+ Early thoughts on the design of the domain system.
+ Current implementation is completely different.
+
+[RFC-821] J. Postel, "Simple Mail Transfer Protocol", RFC-821,
+ USC/Information Sciences Institute, August 1980.
+
+[RFC-830] Z. Su, "A Distributed System for Internet Name Service",
+ RFC-830, Network Information Center, SRI International,
+ October 1982.
+
+ Early thoughts on the design of the domain system.
+ Current implementation is completely different.
+
+[RFC-882] P. Mockapetris, "Domain names - Concepts and
+ Facilities," RFC-882, USC/Information Sciences
+ Institute, November 1983.
+
+ Superceeded by this memo.
+
+[RFC-883] P. Mockapetris, "Domain names - Implementation and
+ Specification," RFC-883, USC/Information Sciences
+ Institute, November 1983.
+
+ Superceeded by this memo.
+
+[RFC-920] J. Postel and J. Reynolds, "Domain Requirements",
+ RFC-920, USC/Information Sciences Institute,
+ October 1984.
+
+ Explains the naming scheme for top level domains.
+
+[RFC-952] K. Harrenstien, M. Stahl, E. Feinler, "DoD Internet Host
+ Table Specification", RFC-952, SRI, October 1985.
+
+ Specifies the format of HOSTS.TXT, the host/address
+ table replaced by the DNS.
+
+
+
+
+
+Mockapetris [Page 51]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+[RFC-953] K. Harrenstien, M. Stahl, E. Feinler, "HOSTNAME Server",
+ RFC-953, SRI, October 1985.
+
+ This RFC contains the official specification of the
+ hostname server protocol, which is obsoleted by the DNS.
+ This TCP based protocol accesses information stored in
+ the RFC-952 format, and is used to obtain copies of the
+ host table.
+
+[RFC-973] P. Mockapetris, "Domain System Changes and
+ Observations", RFC-973, USC/Information Sciences
+ Institute, January 1986.
+
+ Describes changes to RFC-882 and RFC-883 and reasons for
+ them.
+
+[RFC-974] C. Partridge, "Mail routing and the domain system",
+ RFC-974, CSNET CIC BBN Labs, January 1986.
+
+ Describes the transition from HOSTS.TXT based mail
+ addressing to the more powerful MX system used with the
+ domain system.
+
+[RFC-1001] NetBIOS Working Group, "Protocol standard for a NetBIOS
+ service on a TCP/UDP transport: Concepts and Methods",
+ RFC-1001, March 1987.
+
+ This RFC and RFC-1002 are a preliminary design for
+ NETBIOS on top of TCP/IP which proposes to base NetBIOS
+ name service on top of the DNS.
+
+[RFC-1002] NetBIOS Working Group, "Protocol standard for a NetBIOS
+ service on a TCP/UDP transport: Detailed
+ Specifications", RFC-1002, March 1987.
+
+[RFC-1010] J. Reynolds, and J. Postel, "Assigned Numbers", RFC-1010,
+ USC/Information Sciences Institute, May 1987.
+
+ Contains socket numbers and mnemonics for host names,
+ operating systems, etc.
+
+[RFC-1031] W. Lazear, "MILNET Name Domain Transition", RFC-1031,
+ November 1987.
+
+ Describes a plan for converting the MILNET to the DNS.
+
+[RFC-1032] M. Stahl, "Establishing a Domain - Guidelines for
+ Administrators", RFC-1032, November 1987.
+
+
+
+Mockapetris [Page 52]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ Describes the registration policies used by the NIC to
+ administer the top level domains and delegate subzones.
+
+[RFC-1033] M. Lottor, "Domain Administrators Operations Guide",
+ RFC-1033, November 1987.
+
+ A cookbook for domain administrators.
+
+[Solomon 82] M. Solomon, L. Landweber, and D. Neuhengen, "The CSNET
+ Name Server", Computer Networks, vol 6, nr 3, July 1982.
+
+ Describes a name service for CSNET which is independent
+ from the DNS and DNS use in the CSNET.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 53]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+Index
+
+ * 13
+
+ ; 33, 35
+
+ <character-string> 35
+ <domain-name> 34
+
+ @ 35
+
+ \ 35
+
+ A 12
+
+ Byte order 8
+
+ CH 13
+ Character case 9
+ CLASS 11
+ CNAME 12
+ Completion 42
+ CS 13
+
+ Hesiod 13
+ HINFO 12
+ HS 13
+
+ IN 13
+ IN-ADDR.ARPA domain 22
+ Inverse queries 40
+
+ Mailbox names 47
+ MB 12
+ MD 12
+ MF 12
+ MG 12
+ MINFO 12
+ MINIMUM 20
+ MR 12
+ MX 12
+
+ NS 12
+ NULL 12
+
+ Port numbers 32
+ Primary server 5
+ PTR 12, 18
+
+
+
+Mockapetris [Page 54]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ QCLASS 13
+ QTYPE 12
+
+ RDATA 12
+ RDLENGTH 11
+
+ Secondary server 5
+ SOA 12
+ Stub resolvers 7
+
+ TCP 32
+ TXT 12
+ TYPE 11
+
+ UDP 32
+
+ WKS 12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 55]
+
diff --git a/bin/tests/dst/t2_data_2 b/bin/tests/dst/t2_data_2
new file mode 100644
index 0000000..7b0e35d
--- /dev/null
+++ b/bin/tests/dst/t2_data_2
@@ -0,0 +1,3077 @@
+Network Working Group P. Mockapetris
+Request for Comments: 1035 ISI
+ November 1987
+Obsoletes: RFCs 882, 883, 973
+
+ DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION
+
+
+1. STATUS OF THIS MEMO
+
+This RFC describes the details of the domain system and protocol, and
+assumes that the reader is familiar with the concepts discussed in a
+companion RFC, "Domain Names - Concepts and Facilities" [RFC-4301].
+
+The domain system is a mixture of functions and data types which are an
+official protocol and functions and data types which are still
+experimental. Since the domain system is intentionally extensible, new
+data types and experimental behavior should always be expected in parts
+of the system beyond the official protocol. The official protocol parts
+include standard queries, responses and the Internet class RR data
+formats (e.g., host addresses). Since the previous RFC set, several
+definitions have changed, so some previous definitions are obsolete.
+
+Experimental or obsolete features are clearly marked in these RFCs, and
+such information should be used with caution.
+
+The reader is especially cautioned not to depend on the values which
+appear in examples to be current or complete, since their purpose is
+primarily pedagogical. Distribution of this memo is unlimited.
+
+ Table of Contents
+
+ 1. STATUS OF THIS MEMO 1
+ 2. INTRODUCTION 3
+ 2.1. Overview 3
+ 2.2. Common configurations 4
+ 2.3. Conventions 7
+ 2.3.1. Preferred name syntax 7
+ 2.3.2. Data Transmission Order 8
+ 2.3.3. Character Case 9
+ 2.3.4. Size limits 10
+ 3. DOMAIN NAME SPACE AND RR DEFINITIONS 10
+ 3.1. Name space definitions 10
+ 3.2. RR definitions 11
+ 3.2.1. Format 11
+ 3.2.2. TYPE values 12
+ 3.2.3. QTYPE values 12
+ 3.2.4. CLASS values 13
+
+
+
+Mockapetris [Page 1]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 3.2.5. QCLASS values 13
+ 3.3. Standard RRs 13
+ 3.3.1. CNAME RDATA format 14
+ 3.3.2. HINFO RDATA format 14
+ 3.3.3. MB RDATA format (EXPERIMENTAL) 14
+ 3.3.4. MD RDATA format (Obsolete) 15
+ 3.3.5. MF RDATA format (Obsolete) 15
+ 3.3.6. MG RDATA format (EXPERIMENTAL) 16
+ 3.3.7. MINFO RDATA format (EXPERIMENTAL) 16
+ 3.3.8. MR RDATA format (EXPERIMENTAL) 17
+ 3.3.9. MX RDATA format 17
+ 3.3.10. NULL RDATA format (EXPERIMENTAL) 17
+ 3.3.11. NS RDATA format 18
+ 3.3.12. PTR RDATA format 18
+ 3.3.13. SOA RDATA format 19
+ 3.3.14. TXT RDATA format 20
+ 3.4. ARPA Internet specific RRs 20
+ 3.4.1. A RDATA format 20
+ 3.4.2. WKS RDATA format 21
+ 3.5. IN-ADDR.ARPA domain 22
+ 3.6. Defining new types, classes, and special namespaces 24
+ 4. MESSAGES 25
+ 4.1. Format 25
+ 4.1.1. Header section format 26
+ 4.1.2. Question section format 28
+ 4.1.3. Resource record format 29
+ 4.1.4. Message compression 30
+ 4.2. Transport 32
+ 4.2.1. UDP usage 32
+ 4.2.2. TCP usage 32
+ 5. MASTER FILES 33
+ 5.1. Format 33
+ 5.2. Use of master files to define zones 35
+ 5.3. Master file example 36
+ 6. NAME SERVER IMPLEMENTATION 37
+ 6.1. Architecture 37
+ 6.1.1. Control 37
+ 6.1.2. Database 37
+ 6.1.3. Time 39
+ 6.2. Standard query processing 39
+ 6.3. Zone refresh and reload processing 39
+ 6.4. Inverse queries (Optional) 40
+ 6.4.1. The contents of inverse queries and responses 40
+ 6.4.2. Inverse query and response example 41
+ 6.4.3. Inverse query processing 42
+
+
+
+
+
+
+Mockapetris [Page 2]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 6.5. Completion queries and responses 42
+ 7. RESOLVER IMPLEMENTATION 43
+ 7.1. Transforming a user request into a query 43
+ 7.2. Sending the queries 44
+ 7.3. Processing responses 46
+ 7.4. Using the cache 47
+ 8. MAIL SUPPORT 47
+ 8.1. Mail exchange binding 48
+ 8.2. Mailbox binding (Experimental) 48
+ 9. REFERENCES and BIBLIOGRAPHY 50
+ Index 54
+
+2. INTRODUCTION
+
+2.1. Overview
+
+The goal of domain names is to provide a mechanism for naming resources
+in such a way that the names are usable in different hosts, networks,
+protocol families, internets, and administrative organizations.
+
+From the user's point of view, domain names are useful as arguments to a
+local agent, called a resolver, which retrieves information associated
+with the domain name. Thus a user might ask for the host address or
+mail information associated with a particular domain name. To enable
+the user to request a particular type of information, an appropriate
+query type is passed to the resolver with the domain name. To the user,
+the domain tree is a single information space; the resolver is
+responsible for hiding the distribution of data among name servers from
+the user.
+
+From the resolver's point of view, the database that makes up the domain
+space is distributed among various name servers. Different parts of the
+domain space are stored in different name servers, although a particular
+data item will be stored redundantly in two or more name servers. The
+resolver starts with knowledge of at least one name server. When the
+resolver processes a user query it asks a known name server for the
+information; in return, the resolver either receives the desired
+information or a referral to another name server. Using these
+referrals, resolvers learn the identities and contents of other name
+servers. Resolvers are responsible for dealing with the distribution of
+the domain space and dealing with the effects of name server failure by
+consulting redundant databases in other servers.
+
+Name servers manage two kinds of data. The first kind of data held in
+sets called zones; each zone is the complete database for a particular
+"pruned" subtree of the domain space. This data is called
+authoritative. A name server periodically checks to make sure that its
+zones are up to date, and if not, obtains a new copy of updated zones
+
+
+
+Mockapetris [Page 3]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+from master files stored locally or in another name server. The second
+kind of data is cached data which was acquired by a local resolver.
+This data may be incomplete, but improves the performance of the
+retrieval process when non-local data is repeatedly accessed. Cached
+data is eventually discarded by a timeout mechanism.
+
+This functional structure isolates the problems of user interface,
+failure recovery, and distribution in the resolvers and isolates the
+database update and refresh problems in the name servers.
+
+2.2. Common configurations
+
+A host can participate in the domain name system in a number of ways,
+depending on whether the host runs programs that retrieve information
+from the domain system, name servers that answer queries from other
+hosts, or various combinations of both functions. The simplest, and
+perhaps most typical, configuration is shown below:
+
+ Local Host | Foreign
+ |
+ +---------+ +----------+ | +--------+
+ | | user queries | |queries | | |
+ | User |-------------->| |---------|->|Foreign |
+ | Program | | Resolver | | | Name |
+ | |<--------------| |<--------|--| Server |
+ | | user responses| |responses| | |
+ +---------+ +----------+ | +--------+
+ | A |
+ cache additions | | references |
+ V | |
+ +----------+ |
+ | cache | |
+ +----------+ |
+
+User programs interact with the domain name space through resolvers; the
+format of user queries and user responses is specific to the host and
+its operating system. User queries will typically be operating system
+calls, and the resolver and its cache will be part of the host operating
+system. Less capable hosts may choose to implement the resolver as a
+subroutine to be linked in with every program that needs its services.
+Resolvers answer user queries with information they acquire via queries
+to foreign name servers and the local cache.
+
+Note that the resolver may have to make several queries to several
+different foreign name servers to answer a particular user query, and
+hence the resolution of a user query may involve several network
+accesses and an arbitrary amount of time. The queries to foreign name
+servers and the corresponding responses have a standard format described
+
+
+
+Mockapetris [Page 4]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+in this memo, and may be datagrams.
+
+Depending on its capabilities, a name server could be a stand alone
+program on a dedicated machine or a process or processes on a large
+timeshared host. A simple configuration might be:
+
+ Local Host | Foreign
+ |
+ +---------+ |
+ / /| |
+ +---------+ | +----------+ | +--------+
+ | | | | |responses| | |
+ | | | | Name |---------|->|Foreign |
+ | Master |-------------->| Server | | |Resolver|
+ | files | | | |<--------|--| |
+ | |/ | | queries | +--------+
+ +---------+ +----------+ |
+
+Here a primary name server acquires information about one or more zones
+by reading master files from its local file system, and answers queries
+about those zones that arrive from foreign resolvers.
+
+The DNS requires that all zones be redundantly supported by more than
+one name server. Designated secondary servers can acquire zones and
+check for updates from the primary server using the zone transfer
+protocol of the DNS. This configuration is shown below:
+
+ Local Host | Foreign
+ |
+ +---------+ |
+ / /| |
+ +---------+ | +----------+ | +--------+
+ | | | | |responses| | |
+ | | | | Name |---------|->|Foreign |
+ | Master |-------------->| Server | | |Resolver|
+ | files | | | |<--------|--| |
+ | |/ | | queries | +--------+
+ +---------+ +----------+ |
+ A |maintenance | +--------+
+ | +------------|->| |
+ | queries | |Foreign |
+ | | | Name |
+ +------------------|--| Server |
+ maintenance responses | +--------+
+
+In this configuration, the name server periodically establishes a
+virtual circuit to a foreign name server to acquire a copy of a zone or
+to check that an existing copy has not changed. The messages sent for
+
+
+
+Mockapetris [Page 5]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+these maintenance activities follow the same form as queries and
+responses, but the message sequences are somewhat different.
+
+The information flow in a host that supports all aspects of the domain
+name system is shown below:
+
+ Local Host | Foreign
+ |
+ +---------+ +----------+ | +--------+
+ | | user queries | |queries | | |
+ | User |-------------->| |---------|->|Foreign |
+ | Program | | Resolver | | | Name |
+ | |<--------------| |<--------|--| Server |
+ | | user responses| |responses| | |
+ +---------+ +----------+ | +--------+
+ | A |
+ cache additions | | references |
+ V | |
+ +----------+ |
+ | Shared | |
+ | database | |
+ +----------+ |
+ A | |
+ +---------+ refreshes | | references |
+ / /| | V |
+ +---------+ | +----------+ | +--------+
+ | | | | |responses| | |
+ | | | | Name |---------|->|Foreign |
+ | Master |-------------->| Server | | |Resolver|
+ | files | | | |<--------|--| |
+ | |/ | | queries | +--------+
+ +---------+ +----------+ |
+ A |maintenance | +--------+
+ | +------------|->| |
+ | queries | |Foreign |
+ | | | Name |
+ +------------------|--| Server |
+ maintenance responses | +--------+
+
+The shared database holds domain space data for the local name server
+and resolver. The contents of the shared database will typically be a
+mixture of authoritative data maintained by the periodic refresh
+operations of the name server and cached data from previous resolver
+requests. The structure of the domain data and the necessity for
+synchronization between name servers and resolvers imply the general
+characteristics of this database, but the actual format is up to the
+local implementor.
+
+
+
+
+Mockapetris [Page 6]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+Information flow can also be tailored so that a group of hosts act
+together to optimize activities. Sometimes this is done to offload less
+capable hosts so that they do not have to implement a full resolver.
+This can be appropriate for PCs or hosts which want to minimize the
+amount of new network code which is required. This scheme can also
+allow a group of hosts can share a small number of caches rather than
+maintaining a large number of separate caches, on the premise that the
+centralized caches will have a higher hit ratio. In either case,
+resolvers are replaced with stub resolvers which act as front ends to
+resolvers located in a recursive server in one or more name servers
+known to perform that service:
+
+ Local Hosts | Foreign
+ |
+ +---------+ |
+ | | responses |
+ | Stub |<--------------------+ |
+ | Resolver| | |
+ | |----------------+ | |
+ +---------+ recursive | | |
+ queries | | |
+ V | |
+ +---------+ recursive +----------+ | +--------+
+ | | queries | |queries | | |
+ | Stub |-------------->| Recursive|---------|->|Foreign |
+ | Resolver| | Server | | | Name |
+ | |<--------------| |<--------|--| Server |
+ +---------+ responses | |responses| | |
+ +----------+ | +--------+
+ | Central | |
+ | cache | |
+ +----------+ |
+
+In any case, note that domain components are always replicated for
+reliability whenever possible.
+
+2.3. Conventions
+
+The domain system has several conventions dealing with low-level, but
+fundamental, issues. While the implementor is free to violate these
+conventions WITHIN HIS OWN SYSTEM, he must observe these conventions in
+ALL behavior observed from other hosts.
+
+2.3.1. Preferred name syntax
+
+The DNS specifications attempt to be as general as possible in the rules
+for constructing domain names. The idea is that the name of any
+existing object can be expressed as a domain name with minimal changes.
+
+
+
+Mockapetris [Page 7]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+However, when assigning a domain name for an object, the prudent user
+will select a name which satisfies both the rules of the domain system
+and any existing rules for the object, whether these rules are published
+or implied by existing programs.
+
+For example, when naming a mail domain, the user should satisfy both the
+rules of this memo and those in RFC-822. When creating a new host name,
+the old rules for HOSTS.TXT should be followed. This avoids problems
+when old software is converted to use domain names.
+
+The following syntax will result in fewer problems with many
+
+applications that use domain names (e.g., mail, TELNET).
+
+<domain> ::= <subdomain> | " "
+
+<subdomain> ::= <label> | <subdomain> "." <label>
+
+<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
+
+<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+
+<let-dig-hyp> ::= <let-dig> | "-"
+
+<let-dig> ::= <letter> | <digit>
+
+<letter> ::= any one of the 52 alphabetic characters A through Z in
+upper case and a through z in lower case
+
+<digit> ::= any one of the ten digits 0 through 9
+
+Note that while upper and lower case letters are allowed in domain
+names, no significance is attached to the case. That is, two names with
+the same spelling but different case are to be treated as if identical.
+
+The labels must follow the rules for ARPANET host names. They must
+start with a letter, end with a letter or digit, and have as interior
+characters only letters, digits, and hyphen. There are also some
+restrictions on the length. Labels must be 63 characters or less.
+
+For example, the following strings identify hosts in the Internet:
+
+A.ISI.EDU XX.LCS.MIT.EDU SRI-NIC.ARPA
+
+2.3.2. Data Transmission Order
+
+The order of transmission of the header and data described in this
+document is resolved to the octet level. Whenever a diagram shows a
+
+
+
+Mockapetris [Page 8]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+group of octets, the order of transmission of those octets is the normal
+order in which they are read in English. For example, in the following
+diagram, the octets are transmitted in the order they are numbered.
+
+ 0 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 1 | 2 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 3 | 4 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 5 | 6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+Whenever an octet represents a numeric quantity, the left most bit in
+the diagram is the high order or most significant bit. That is, the bit
+labeled 0 is the most significant bit. For example, the following
+diagram represents the value 170 (decimal).
+
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |1 0 1 0 1 0 1 0|
+ +-+-+-+-+-+-+-+-+
+
+Similarly, whenever a multi-octet field represents a numeric quantity
+the left most bit of the whole field is the most significant bit. When
+a multi-octet quantity is transmitted the most significant octet is
+transmitted first.
+
+2.3.3. Character Case
+
+For all parts of the DNS that are part of the official protocol, all
+comparisons between character strings (e.g., labels, domain names, etc.)
+are done in a case-insensitive manner. At present, this rule is in
+force throughout the domain system without exception. However, future
+additions beyond current usage may need to use the full binary octet
+capabilities in names, so attempts to store domain names in 7-bit ASCII
+or use of special bytes to terminate labels, etc., should be avoided.
+
+When data enters the domain system, its original case should be
+preserved whenever possible. In certain circumstances this cannot be
+done. For example, if two RRs are stored in a database, one at x.y and
+one at X.Y, they are actually stored at the same place in the database,
+and hence only one casing would be preserved. The basic rule is that
+case can be discarded only when data is used to define structure in a
+database, and two names are identical when compared in a case
+insensitive manner.
+
+
+
+
+Mockapetris [Page 9]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+Loss of case sensitive data must be minimized. Thus while data for x.y
+and X.Y may both be stored under a single location x.y or X.Y, data for
+a.x and B.X would never be stored under A.x, A.X, b.x, or b.X. In
+general, this preserves the case of the first label of a domain name,
+but forces standardization of interior node labels.
+
+Systems administrators who enter data into the domain database should
+take care to represent the data they supply to the domain system in a
+case-consistent manner if their system is case-sensitive. The data
+distribution system in the domain system will ensure that consistent
+representations are preserved.
+
+2.3.4. Size limits
+
+Various objects and parameters in the DNS have size limits. They are
+listed below. Some could be easily changed, others are more
+fundamental.
+
+labels 63 octets or less
+
+names 255 octets or less
+
+TTL positive values of a signed 32 bit number.
+
+UDP messages 512 octets or less
+
+3. DOMAIN NAME SPACE AND RR DEFINITIONS
+
+3.1. Name space definitions
+
+Domain names in messages are expressed in terms of a sequence of labels.
+Each label is represented as a one octet length field followed by that
+number of octets. Since every domain name ends with the null label of
+the root, a domain name is terminated by a length byte of zero. The
+high order two bits of every length octet must be zero, and the
+remaining six bits of the length field limit the label to 63 octets or
+less.
+
+To simplify implementations, the total length of a domain name (i.e.,
+label octets and label length octets) is restricted to 255 octets or
+less.
+
+Although labels can contain any 8 bit values in octets that make up a
+label, it is strongly recommended that labels follow the preferred
+syntax described elsewhere in this memo, which is compatible with
+existing host naming conventions. Name servers and resolvers must
+compare labels in a case-insensitive manner (i.e., A=a), assuming ASCII
+with zero parity. Non-alphabetic codes must match exactly.
+
+
+
+Mockapetris [Page 10]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.2. RR definitions
+
+3.2.1. Format
+
+All RRs have the same top level format shown below:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / /
+ / NAME /
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | CLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TTL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RDLENGTH |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+ / RDATA /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+
+where:
+
+NAME an owner name, i.e., the name of the node to which this
+ resource record pertains.
+
+TYPE two octets containing one of the RR TYPE codes.
+
+CLASS two octets containing one of the RR CLASS codes.
+
+TTL a 32 bit signed integer that specifies the time interval
+ that the resource record may be cached before the source
+ of the information should again be consulted. Zero
+ values are interpreted to mean that the RR can only be
+ used for the transaction in progress, and should not be
+ cached. For example, SOA records are always distributed
+ with a zero TTL to prohibit caching. Zero values can
+ also be used for extremely volatile data.
+
+RDLENGTH an unsigned 16 bit integer that specifies the length in
+ octets of the RDATA field.
+
+
+
+Mockapetris [Page 11]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+RDATA a variable length string of octets that describes the
+ resource. The format of this information varies
+ according to the TYPE and CLASS of the resource record.
+
+3.2.2. TYPE values
+
+TYPE fields are used in resource records. Note that these types are a
+subset of QTYPEs.
+
+TYPE value and meaning
+
+A 1 a host address
+
+NS 2 an authoritative name server
+
+MD 3 a mail destination (Obsolete - use MX)
+
+MF 4 a mail forwarder (Obsolete - use MX)
+
+CNAME 5 the canonical name for an alias
+
+SOA 6 marks the start of a zone of authority
+
+MB 7 a mailbox domain name (EXPERIMENTAL)
+
+MG 8 a mail group member (EXPERIMENTAL)
+
+MR 9 a mail rename domain name (EXPERIMENTAL)
+
+NULL 10 a null RR (EXPERIMENTAL)
+
+WKS 11 a well known service description
+
+PTR 12 a domain name pointer
+
+HINFO 13 host information
+
+MINFO 14 mailbox or mail list information
+
+MX 15 mail exchange
+
+TXT 16 text strings
+
+3.2.3. QTYPE values
+
+QTYPE fields appear in the question part of a query. QTYPES are a
+superset of TYPEs, hence all TYPEs are valid QTYPEs. In addition, the
+following QTYPEs are defined:
+
+
+
+Mockapetris [Page 12]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+AXFR 252 A request for a transfer of an entire zone
+
+MAILB 253 A request for mailbox-related records (MB, MG or MR)
+
+MAILA 254 A request for mail agent RRs (Obsolete - see MX)
+
+* 255 A request for all records
+
+3.2.4. CLASS values
+
+CLASS fields appear in resource records. The following CLASS mnemonics
+and values are defined:
+
+IN 1 the Internet
+
+CS 2 the CSNET class (Obsolete - used only for examples in
+ some obsolete RFCs)
+
+CH 3 the CHAOS class
+
+HS 4 Hesiod [Dyer 87]
+
+3.2.5. QCLASS values
+
+QCLASS fields appear in the question section of a query. QCLASS values
+are a superset of CLASS values; every CLASS is a valid QCLASS. In
+addition to CLASS values, the following QCLASSes are defined:
+
+* 255 any class
+
+3.3. Standard RRs
+
+The following RR definitions are expected to occur, at least
+potentially, in all classes. In particular, NS, SOA, CNAME, and PTR
+will be used in all classes, and have the same format in all classes.
+Because their RDATA format is known, all domain names in the RDATA
+section of these RRs may be compressed.
+
+<domain-name> is a domain name represented as a series of labels, and
+terminated by a label with zero length. <character-string> is a single
+length octet followed by that number of characters. <character-string>
+is treated as binary information, and can be up to 256 characters in
+length (including the length octet).
+
+
+
+
+
+
+
+
+Mockapetris [Page 13]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.1. CNAME RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / CNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+CNAME A <domain-name> which specifies the canonical or primary
+ name for the owner. The owner name is an alias.
+
+CNAME RRs cause no additional section processing, but name servers may
+choose to restart the query at the canonical name in certain cases. See
+the description of name server logic in [RFC-1034] for details.
+
+3.3.2. HINFO RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / CPU /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / OS /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+CPU A <character-string> which specifies the CPU type.
+
+OS A <character-string> which specifies the operating
+ system type.
+
+Standard values for CPU and OS can be found in [RFC-1010].
+
+HINFO records are used to acquire general information about a host. The
+main use is for protocols such as FTP that can use special procedures
+when talking between machines or operating systems of the same type.
+
+3.3.3. MB RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MADNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MADNAME A <domain-name> which specifies a host which has the
+ specified mailbox.
+
+
+
+Mockapetris [Page 14]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+MB records cause additional section processing which looks up an A type
+RRs corresponding to MADNAME.
+
+3.3.4. MD RDATA format (Obsolete)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MADNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MADNAME A <domain-name> which specifies a host which has a mail
+ agent for the domain which should be able to deliver
+ mail for the domain.
+
+MD records cause additional section processing which looks up an A type
+record corresponding to MADNAME.
+
+MD is obsolete. See the definition of MX and [RFC-974] for details of
+the new scheme. The recommended policy for dealing with MD RRs found in
+a master file is to reject them, or to convert them to MX RRs with a
+preference of 0.
+
+3.3.5. MF RDATA format (Obsolete)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MADNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MADNAME A <domain-name> which specifies a host which has a mail
+ agent for the domain which will accept mail for
+ forwarding to the domain.
+
+MF records cause additional section processing which looks up an A type
+record corresponding to MADNAME.
+
+MF is obsolete. See the definition of MX and [RFC-974] for details ofw
+the new scheme. The recommended policy for dealing with MD RRs found in
+a master file is to reject them, or to convert them to MX RRs with a
+preference of 10.
+
+
+
+
+
+
+
+Mockapetris [Page 15]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.6. MG RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MGMNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MGMNAME A <domain-name> which specifies a mailbox which is a
+ member of the mail group specified by the domain name.
+
+MG records cause no additional section processing.
+
+3.3.7. MINFO RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / RMAILBX /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / EMAILBX /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+RMAILBX A <domain-name> which specifies a mailbox which is
+ responsible for the mailing list or mailbox. If this
+ domain name names the root, the owner of the MINFO RR is
+ responsible for itself. Note that many existing mailing
+ lists use a mailbox X-request for the RMAILBX field of
+ mailing list X, e.g., Msgroup-request for Msgroup. This
+ field provides a more general mechanism.
+
+
+EMAILBX A <domain-name> which specifies a mailbox which is to
+ receive error messages related to the mailing list or
+ mailbox specified by the owner of the MINFO RR (similar
+ to the ERRORS-TO: field which has been proposed). If
+ this domain name names the root, errors should be
+ returned to the sender of the message.
+
+MINFO records cause no additional section processing. Although these
+records can be associated with a simple mailbox, they are usually used
+with a mailing list.
+
+
+
+
+
+
+
+
+Mockapetris [Page 16]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.8. MR RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / NEWNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+NEWNAME A <domain-name> which specifies a mailbox which is the
+ proper rename of the specified mailbox.
+
+MR records cause no additional section processing. The main use for MR
+is as a forwarding entry for a user who has moved to a different
+mailbox.
+
+3.3.9. MX RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PREFERENCE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / EXCHANGE /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+PREFERENCE A 16 bit integer which specifies the preference given to
+ this RR among others at the same owner. Lower values
+ are preferred.
+
+EXCHANGE A <domain-name> which specifies a host willing to act as
+ a mail exchange for the owner name.
+
+MX records cause type A additional section processing for the host
+specified by EXCHANGE. The use of MX RRs is explained in detail in
+[RFC-974].
+
+3.3.10. NULL RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / <anything> /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+Anything at all may be in the RDATA field so long as it is 65535 octets
+or less.
+
+
+
+
+Mockapetris [Page 17]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+NULL records cause no additional section processing. NULL RRs are not
+allowed in master files. NULLs are used as placeholders in some
+experimental extensions of the DNS.
+
+3.3.11. NS RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / NSDNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+NSDNAME A <domain-name> which specifies a host which should be
+ authoritative for the specified class and domain.
+
+NS records cause both the usual additional section processing to locate
+a type A record, and, when used in a referral, a special search of the
+zone in which they reside for glue information.
+
+The NS RR states that the named host should be expected to have a zone
+starting at owner name of the specified class. Note that the class may
+not indicate the protocol family which should be used to communicate
+with the host, although it is typically a strong hint. For example,
+hosts which are name servers for either Internet (IN) or Hesiod (HS)
+class information are normally queried using IN class protocols.
+
+3.3.12. PTR RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / PTRDNAME /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+PTRDNAME A <domain-name> which points to some location in the
+ domain name space.
+
+PTR records cause no additional section processing. These RRs are used
+in special domains to point to some other location in the domain space.
+These records are simple data, and don't imply any special processing
+similar to that performed by CNAME, which identifies aliases. See the
+description of the IN-ADDR.ARPA domain for an example.
+
+
+
+
+
+
+
+
+Mockapetris [Page 18]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.13. SOA RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / RNAME /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | SERIAL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | REFRESH |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RETRY |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | EXPIRE |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | MINIMUM |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MNAME The <domain-name> of the name server that was the
+ original or primary source of data for this zone.
+
+RNAME A <domain-name> which specifies the mailbox of the
+ person responsible for this zone.
+
+SERIAL The unsigned 32 bit version number of the original copy
+ of the zone. Zone transfers preserve this value. This
+ value wraps and should be compared using sequence space
+ arithmetic.
+
+REFRESH A 32 bit time interval before the zone should be
+ refreshed.
+
+RETRY A 32 bit time interval that should elapse before a
+ failed refresh should be retried.
+
+EXPIRE A 32 bit time value that specifies the upper limit on
+ the time interval that can elapse before the zone is no
+ longer authoritative.
+
+
+
+
+
+Mockapetris [Page 19]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+MINIMUM The unsigned 32 bit minimum TTL field that should be
+ exported with any RR from this zone.
+
+SOA records cause no additional section processing.
+
+All times are in units of seconds.
+
+Most of these fields are pertinent only for name server maintenance
+operations. However, MINIMUM is used in all query operations that
+retrieve RRs from a zone. Whenever a RR is sent in a response to a
+query, the TTL field is set to the maximum of the TTL field from the RR
+and the MINIMUM field in the appropriate SOA. Thus MINIMUM is a lower
+bound on the TTL field for all RRs in a zone. Note that this use of
+MINIMUM should occur when the RRs are copied into the response and not
+when the zone is loaded from a master file or via a zone transfer. The
+reason for this provison is to allow future dynamic update facilities to
+change the SOA RR with known semantics.
+
+
+3.3.14. TXT RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / TXT-DATA /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+TXT-DATA One or more <character-string>s.
+
+TXT RRs are used to hold descriptive text. The semantics of the text
+depends on the domain where it is found.
+
+3.4. Internet specific RRs
+
+3.4.1. A RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ADDRESS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+ADDRESS A 32 bit Internet address.
+
+Hosts that have multiple Internet addresses will have multiple A
+records.
+
+
+
+
+
+Mockapetris [Page 20]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+A records cause no additional section processing. The RDATA section of
+an A line in a master file is an Internet address expressed as four
+decimal numbers separated by dots without any imbedded spaces (e.g.,
+"10.2.0.52" or "192.0.5.6").
+
+3.4.2. WKS RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ADDRESS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PROTOCOL | |
+ +--+--+--+--+--+--+--+--+ |
+ | |
+ / <BIT MAP> /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+ADDRESS An 32 bit Internet address
+
+PROTOCOL An 8 bit IP protocol number
+
+<BIT MAP> A variable length bit map. The bit map must be a
+ multiple of 8 bits long.
+
+The WKS record is used to describe the well known services supported by
+a particular protocol on a particular internet address. The PROTOCOL
+field specifies an IP protocol number, and the bit map has one bit per
+port of the specified protocol. The first bit corresponds to port 0,
+the second to port 1, etc. If the bit map does not include a bit for a
+protocol of interest, that bit is assumed zero. The appropriate values
+and mnemonics for ports and protocols are specified in [RFC-1010].
+
+For example, if PROTOCOL=TCP (6), the 26th bit corresponds to TCP port
+25 (SMTP). If this bit is set, a SMTP server should be listening on TCP
+port 25; if zero, SMTP service is not supported on the specified
+address.
+
+The purpose of WKS RRs is to provide availability information for
+servers for TCP and UDP. If a server supports both TCP and UDP, or has
+multiple Internet addresses, then multiple WKS RRs are used.
+
+WKS RRs cause no additional section processing.
+
+In master files, both ports and protocols are expressed using mnemonics
+or decimal numbers.
+
+
+
+
+Mockapetris [Page 21]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.5. IN-ADDR.ARPA domain
+
+The Internet uses a special domain to support gateway location and
+Internet address to host mapping. Other classes may employ a similar
+strategy in other domains. The intent of this domain is to provide a
+guaranteed method to perform host address to host name mapping, and to
+facilitate queries to locate all gateways on a particular network in the
+Internet.
+
+Note that both of these services are similar to functions that could be
+performed by inverse queries; the difference is that this part of the
+domain name space is structured according to address, and hence can
+guarantee that the appropriate data can be located without an exhaustive
+search of the domain space.
+
+The domain begins at IN-ADDR.ARPA and has a substructure which follows
+the Internet addressing structure.
+
+Domain names in the IN-ADDR.ARPA domain are defined to have up to four
+labels in addition to the IN-ADDR.ARPA suffix. Each label represents
+one octet of an Internet address, and is expressed as a character string
+for a decimal value in the range 0-255 (with leading zeros omitted
+except in the case of a zero octet which is represented by a single
+zero).
+
+Host addresses are represented by domain names that have all four labels
+specified. Thus data for Internet address 10.2.0.52 is located at
+domain name 52.0.2.10.IN-ADDR.ARPA. The reversal, though awkward to
+read, allows zones to be delegated which are exactly one network of
+address space. For example, 10.IN-ADDR.ARPA can be a zone containing
+data for the ARPANET, while 26.IN-ADDR.ARPA can be a separate zone for
+MILNET. Address nodes are used to hold pointers to primary host names
+in the normal domain space.
+
+Network numbers correspond to some non-terminal nodes at various depths
+in the IN-ADDR.ARPA domain, since Internet network numbers are either 1,
+2, or 3 octets. Network nodes are used to hold pointers to the primary
+host names of gateways attached to that network. Since a gateway is, by
+definition, on more than one network, it will typically have two or more
+network nodes which point at it. Gateways will also have host level
+pointers at their fully qualified addresses.
+
+Both the gateway pointers at network nodes and the normal host pointers
+at full address nodes use the PTR RR to point back to the primary domain
+names of the corresponding hosts.
+
+For example, the IN-ADDR.ARPA domain will contain information about the
+ISI gateway between net 10 and 26, an MIT gateway from net 10 to MIT's
+
+
+
+Mockapetris [Page 22]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+net 18, and hosts A.ISI.EDU and MULTICS.MIT.EDU. Assuming that ISI
+gateway has addresses 10.2.0.22 and 26.0.0.103, and a name MILNET-
+GW.ISI.EDU, and the MIT gateway has addresses 10.0.0.77 and 18.10.0.4
+and a name GW.LCS.MIT.EDU, the domain database would contain:
+
+ 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 22.0.2.10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 103.0.0.26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 77.0.0.10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 4.0.10.18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 103.0.3.26.IN-ADDR.ARPA. PTR A.ISI.EDU.
+ 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU.
+
+Thus a program which wanted to locate gateways on net 10 would originate
+a query of the form QTYPE=PTR, QCLASS=IN, QNAME=10.IN-ADDR.ARPA. It
+would receive two RRs in response:
+
+ 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+
+The program could then originate QTYPE=A, QCLASS=IN queries for MILNET-
+GW.ISI.EDU. and GW.LCS.MIT.EDU. to discover the Internet addresses of
+these gateways.
+
+A resolver which wanted to find the host name corresponding to Internet
+host address 10.0.0.6 would pursue a query of the form QTYPE=PTR,
+QCLASS=IN, QNAME=6.0.0.10.IN-ADDR.ARPA, and would receive:
+
+ 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU.
+
+Several cautions apply to the use of these services:
+ - Since the IN-ADDR.ARPA special domain and the normal domain
+ for a particular host or gateway will be in different zones,
+ the possibility exists that that the data may be inconsistent.
+
+ - Gateways will often have two names in separate domains, only
+ one of which can be primary.
+
+ - Systems that use the domain database to initialize their
+ routing tables must start with enough gateway information to
+ guarantee that they can access the appropriate name server.
+
+ - The gateway data only reflects the existence of a gateway in a
+ manner equivalent to the current HOSTS.TXT file. It doesn't
+ replace the dynamic availability information from GGP or EGP.
+
+
+
+Mockapetris [Page 23]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.6. Defining new types, classes, and special namespaces
+
+The previously defined types and classes are the ones in use as of the
+date of this memo. New definitions should be expected. This section
+makes some recommendations to designers considering additions to the
+existing facilities. The mailing list NAMEDROPPERS@SRI-NIC.ARPA is the
+forum where general discussion of design issues takes place.
+
+In general, a new type is appropriate when new information is to be
+added to the database about an existing object, or we need new data
+formats for some totally new object. Designers should attempt to define
+types and their RDATA formats that are generally applicable to all
+classes, and which avoid duplication of information. New classes are
+appropriate when the DNS is to be used for a new protocol, etc which
+requires new class-specific data formats, or when a copy of the existing
+name space is desired, but a separate management domain is necessary.
+
+New types and classes need mnemonics for master files; the format of the
+master files requires that the mnemonics for type and class be disjoint.
+
+TYPE and CLASS values must be a proper subset of QTYPEs and QCLASSes
+respectively.
+
+The present system uses multiple RRs to represent multiple values of a
+type rather than storing multiple values in the RDATA section of a
+single RR. This is less efficient for most applications, but does keep
+RRs shorter. The multiple RRs assumption is incorporated in some
+experimental work on dynamic update methods.
+
+The present system attempts to minimize the duplication of data in the
+database in order to insure consistency. Thus, in order to find the
+address of the host for a mail exchange, you map the mail domain name to
+a host name, then the host name to addresses, rather than a direct
+mapping to host address. This approach is preferred because it avoids
+the opportunity for inconsistency.
+
+In defining a new type of data, multiple RR types should not be used to
+create an ordering between entries or express different formats for
+equivalent bindings, instead this information should be carried in the
+body of the RR and a single type used. This policy avoids problems with
+caching multiple types and defining QTYPEs to match multiple types.
+
+For example, the original form of mail exchange binding used two RR
+types one to represent a "closer" exchange (MD) and one to represent a
+"less close" exchange (MF). The difficulty is that the presence of one
+RR type in a cache doesn't convey any information about the other
+because the query which acquired the cached information might have used
+a QTYPE of MF, MD, or MAILA (which matched both). The redesigned
+
+
+
+Mockapetris [Page 24]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+service used a single type (MX) with a "preference" value in the RDATA
+section which can order different RRs. However, if any MX RRs are found
+in the cache, then all should be there.
+
+4. MESSAGES
+
+4.1. Format
+
+All communications inside of the domain protocol are carried in a single
+format called a message. The top level format of message is divided
+into 5 sections (some of which are empty in certain cases) shown below:
+
+ +---------------------+
+ | Header |
+ +---------------------+
+ | Question | the question for the name server
+ +---------------------+
+ | Answer | RRs answering the question
+ +---------------------+
+ | Authority | RRs pointing toward an authority
+ +---------------------+
+ | Additional | RRs holding additional information
+ +---------------------+
+
+The header section is always present. The header includes fields that
+specify which of the remaining sections are present, and also specify
+whether the message is a query or a response, a standard query or some
+other opcode, etc.
+
+The names of the sections after the header are derived from their use in
+standard queries. The question section contains fields that describe a
+question to a name server. These fields are a query type (QTYPE), a
+query class (QCLASS), and a query domain name (QNAME). The last three
+sections have the same format: a possibly empty list of concatenated
+resource records (RRs). The answer section contains RRs that answer the
+question; the authority section contains RRs that point toward an
+authoritative name server; the additional records section contains RRs
+which relate to the query, but are not strictly answers for the
+question.
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 25]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+4.1.1. Header section format
+
+The header contains the following fields:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ID |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QDCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ANCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | NSCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ARCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+ID A 16 bit identifier assigned by the program that
+ generates any kind of query. This identifier is copied
+ the corresponding reply and can be used by the requester
+ to match up replies to outstanding queries.
+
+QR A one bit field that specifies whether this message is a
+ query (0), or a response (1).
+
+OPCODE A four bit field that specifies kind of query in this
+ message. This value is set by the originator of a query
+ and copied into the response. The values are:
+
+ 0 a standard query (QUERY)
+
+ 1 an inverse query (IQUERY)
+
+ 2 a server status request (STATUS)
+
+ 3-15 reserved for future use
+
+AA Authoritative Answer - this bit is valid in responses,
+ and specifies that the responding name server is an
+ authority for the domain name in question section.
+
+ Note that the contents of the answer section may have
+ multiple owner names because of aliases. The AA bit
+
+
+
+Mockapetris [Page 26]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ corresponds to the name which matches the query name, or
+ the first owner name in the answer section.
+
+TC TrunCation - specifies that this message was truncated
+ due to length greater than that permitted on the
+ transmission channel.
+
+RD Recursion Desired - this bit may be set in a query and
+ is copied into the response. If RD is set, it directs
+ the name server to pursue the query recursively.
+ Recursive query support is optional.
+
+RA Recursion Available - this be is set or cleared in a
+ response, and denotes whether recursive query support is
+ available in the name server.
+
+Z Reserved for future use. Must be zero in all queries
+ and responses.
+
+RCODE Response code - this 4 bit field is set as part of
+ responses. The values have the following
+ interpretation:
+
+ 0 No error condition
+
+ 1 Format error - The name server was
+ unable to interpret the query.
+
+ 2 Server failure - The name server was
+ unable to process this query due to a
+ problem with the name server.
+
+ 3 Name Error - Meaningful only for
+ responses from an authoritative name
+ server, this code signifies that the
+ domain name referenced in the query does
+ not exist.
+
+ 4 Not Implemented - The name server does
+ not support the requested kind of query.
+
+ 5 Refused - The name server refuses to
+ perform the specified operation for
+ policy reasons. For example, a name
+ server may not wish to provide the
+ information to the particular requester,
+ or a name server may not wish to perform
+ a particular operation (e.g., zone
+
+
+
+Mockapetris [Page 27]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ transfer) for particular data.
+
+ 6-15 Reserved for future use.
+
+QDCOUNT an unsigned 16 bit integer specifying the number of
+ entries in the question section.
+
+ANCOUNT an unsigned 16 bit integer specifying the number of
+ resource records in the answer section.
+
+NSCOUNT an unsigned 16 bit integer specifying the number of name
+ server resource records in the authority records
+ section.
+
+ARCOUNT an unsigned 16 bit integer specifying the number of
+ resource records in the additional records section.
+
+4.1.2. Question section format
+
+The question section is used to carry the "question" in most queries,
+i.e., the parameters that define what is being asked. The section
+contains QDCOUNT (usually 1) entries, each of the following format:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / QNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QTYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QCLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+QNAME a domain name represented as a sequence of labels, where
+ each label consists of a length octet followed by that
+ number of octets. The domain name terminates with the
+ zero length octet for the null label of the root. Note
+ that this field may be an odd number of octets; no
+ padding is used.
+
+QTYPE a two octet code which specifies the type of the query.
+ The values for this field include all codes valid for a
+ TYPE field, together with some more general codes which
+ can match more than one type of RR.
+
+
+
+Mockapetris [Page 28]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+QCLASS a two octet code that specifies the class of the query.
+ For example, the QCLASS field is IN for the Internet.
+
+4.1.3. Resource record format
+
+The answer, authority, and additional sections all share the same
+format: a variable number of resource records, where the number of
+records is specified in the corresponding count field in the header.
+Each resource record has the following format:
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / /
+ / NAME /
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | CLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TTL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RDLENGTH |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+ / RDATA /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+NAME a domain name to which this resource record pertains.
+
+TYPE two octets containing one of the RR type codes. This
+ field specifies the meaning of the data in the RDATA
+ field.
+
+CLASS two octets which specify the class of the data in the
+ RDATA field.
+
+TTL a 32 bit unsigned integer that specifies the time
+ interval (in seconds) that the resource record may be
+ cached before it should be discarded. Zero values are
+ interpreted to mean that the RR can only be used for the
+ transaction in progress, and should not be cached.
+
+
+
+
+
+Mockapetris [Page 29]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+RDLENGTH an unsigned 16 bit integer that specifies the length in
+ octets of the RDATA field.
+
+RDATA a variable length string of octets that describes the
+ resource. The format of this information varies
+ according to the TYPE and CLASS of the resource record.
+ For example, the if the TYPE is A and the CLASS is IN,
+ the RDATA field is a 4 octet ARPA Internet address.
+
+4.1.4. Message compression
+
+In order to reduce the size of messages, the domain system utilizes a
+compression scheme which eliminates the repetition of domain names in a
+message. In this scheme, an entire domain name or a list of labels at
+the end of a domain name is replaced with a pointer to a prior occurance
+of the same name.
+
+The pointer takes the form of a two octet sequence:
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | 1 1| OFFSET |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+The first two bits are ones. This allows a pointer to be distinguished
+from a label, since the label must begin with two zero bits because
+labels are restricted to 63 octets or less. (The 10 and 01 combinations
+are reserved for future use.) The OFFSET field specifies an offset from
+the start of the message (i.e., the first octet of the ID field in the
+domain header). A zero offset specifies the first byte of the ID field,
+etc.
+
+The compression scheme allows a domain name in a message to be
+represented as either:
+
+ - a sequence of labels ending in a zero octet
+
+ - a pointer
+
+ - a sequence of labels ending with a pointer
+
+Pointers can only be used for occurances of a domain name where the
+format is not class specific. If this were not the case, a name server
+or resolver would be required to know the format of all RRs it handled.
+As yet, there are no such cases, but they may occur in future RDATA
+formats.
+
+If a domain name is contained in a part of the message subject to a
+length field (such as the RDATA section of an RR), and compression is
+
+
+
+Mockapetris [Page 30]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+used, the length of the compressed name is used in the length
+calculation, rather than the length of the expanded name.
+
+Programs are free to avoid using pointers in messages they generate,
+although this will reduce datagram capacity, and may cause truncation.
+However all programs are required to understand arriving messages that
+contain pointers.
+
+For example, a datagram might need to use the domain names F.ISI.ARPA,
+FOO.F.ISI.ARPA, ARPA, and the root. Ignoring the other fields of the
+message, these domain names might be represented as:
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 20 | 1 | F |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 22 | 3 | I |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 24 | S | I |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 26 | 4 | A |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 28 | R | P |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 30 | A | 0 |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 40 | 3 | F |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 42 | O | O |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 44 | 1 1| 20 |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 64 | 1 1| 26 |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 92 | 0 | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+The domain name for F.ISI.ARPA is shown at offset 20. The domain name
+FOO.F.ISI.ARPA is shown at offset 40; this definition uses a pointer to
+concatenate a label for FOO to the previously defined F.ISI.ARPA. The
+domain name ARPA is defined at offset 64 using a pointer to the ARPA
+component of the name F.ISI.ARPA at 20; note that this pointer relies on
+ARPA being the last label in the string at 20. The root domain name is
+
+
+
+Mockapetris [Page 31]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+defined by a single octet of zeros at 92; the root domain name has no
+labels.
+
+4.2. Transport
+
+The DNS assumes that messages will be transmitted as datagrams or in a
+byte stream carried by a virtual circuit. While virtual circuits can be
+used for any DNS activity, datagrams are preferred for queries due to
+their lower overhead and better performance. Zone refresh activities
+must use virtual circuits because of the need for reliable transfer.
+
+The Internet supports name server access using TCP [RFC-793] on server
+port 53 (decimal) as well as datagram access using UDP [RFC-768] on UDP
+port 53 (decimal).
+
+4.2.1. UDP usage
+
+Messages sent using UDP user server port 53 (decimal).
+
+Messages carried by UDP are restricted to 512 bytes (not counting the IP
+or UDP headers). Longer messages are truncated and the TC bit is set in
+the header.
+
+UDP is not acceptable for zone transfers, but is the recommended method
+for standard queries in the Internet. Queries sent using UDP may be
+lost, and hence a retransmission strategy is required. Queries or their
+responses may be reordered by the network, or by processing in name
+servers, so resolvers should not depend on them being returned in order.
+
+The optimal UDP retransmission policy will vary with performance of the
+Internet and the needs of the client, but the following are recommended:
+
+ - The client should try other servers and server addresses
+ before repeating a query to a specific address of a server.
+
+ - The retransmission interval should be based on prior
+ statistics if possible. Too aggressive retransmission can
+ easily slow responses for the community at large. Depending
+ on how well connected the client is to its expected servers,
+ the minimum retransmission interval should be 2-5 seconds.
+
+More suggestions on server selection and retransmission policy can be
+found in the resolver section of this memo.
+
+4.2.2. TCP usage
+
+Messages sent over TCP connections use server port 53 (decimal). The
+message is prefixed with a two byte length field which gives the message
+
+
+
+Mockapetris [Page 32]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+length, excluding the two byte length field. This length field allows
+the low-level processing to assemble a complete message before beginning
+to parse it.
+
+Several connection management policies are recommended:
+
+ - The server should not block other activities waiting for TCP
+ data.
+
+ - The server should support multiple connections.
+
+ - The server should assume that the client will initiate
+ connection closing, and should delay closing its end of the
+ connection until all outstanding client requests have been
+ satisfied.
+
+ - If the server needs to close a dormant connection to reclaim
+ resources, it should wait until the connection has been idle
+ for a period on the order of two minutes. In particular, the
+ server should allow the SOA and AXFR request sequence (which
+ begins a refresh operation) to be made on a single connection.
+ Since the server would be unable to answer queries anyway, a
+ unilateral close or reset may be used instead of a graceful
+ close.
+
+5. MASTER FILES
+
+Master files are text files that contain RRs in text form. Since the
+contents of a zone can be expressed in the form of a list of RRs a
+master file is most often used to define a zone, though it can be used
+to list a cache's contents. Hence, this section first discusses the
+format of RRs in a master file, and then the special considerations when
+a master file is used to create a zone in some name server.
+
+5.1. Format
+
+The format of these files is a sequence of entries. Entries are
+predominantly line-oriented, though parentheses can be used to continue
+a list of items across a line boundary, and text literals can contain
+CRLF within the text. Any combination of tabs and spaces act as a
+delimiter between the separate items that make up an entry. The end of
+any line in the master file can end with a comment. The comment starts
+with a ";" (semicolon).
+
+The following entries are defined:
+
+ <blank>[<comment>]
+
+
+
+
+Mockapetris [Page 33]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ $ORIGIN <domain-name> [<comment>]
+
+ $INCLUDE <file-name> [<domain-name>] [<comment>]
+
+ <domain-name><rr> [<comment>]
+
+ <blank><rr> [<comment>]
+
+Blank lines, with or without comments, are allowed anywhere in the file.
+
+Two control entries are defined: $ORIGIN and $INCLUDE. $ORIGIN is
+followed by a domain name, and resets the current origin for relative
+domain names to the stated name. $INCLUDE inserts the named file into
+the current file, and may optionally specify a domain name that sets the
+relative domain name origin for the included file. $INCLUDE may also
+have a comment. Note that a $INCLUDE entry never changes the relative
+origin of the parent file, regardless of changes to the relative origin
+made within the included file.
+
+The last two forms represent RRs. If an entry for an RR begins with a
+blank, then the RR is assumed to be owned by the last stated owner. If
+an RR entry begins with a <domain-name>, then the owner name is reset.
+
+<rr> contents take one of the following forms:
+
+ [<TTL>] [<class>] <type> <RDATA>
+
+ [<class>] [<TTL>] <type> <RDATA>
+
+The RR begins with optional TTL and class fields, followed by a type and
+RDATA field appropriate to the type and class. Class and type use the
+standard mnemonics, TTL is a decimal integer. Omitted class and TTL
+values are default to the last explicitly stated values. Since type and
+class mnemonics are disjoint, the parse is unique. (Note that this
+order is different from the order used in examples and the order used in
+the actual RRs; the given order allows easier parsing and defaulting.)
+
+<domain-name>s make up a large share of the data in the master file.
+The labels in the domain name are expressed as character strings and
+separated by dots. Quoting conventions allow arbitrary characters to be
+stored in domain names. Domain names that end in a dot are called
+absolute, and are taken as complete. Domain names which do not end in a
+dot are called relative; the actual domain name is the concatenation of
+the relative part with an origin specified in a $ORIGIN, $INCLUDE, or as
+an argument to the master file loading routine. A relative name is an
+error when no origin is available.
+
+
+
+
+
+Mockapetris [Page 34]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+<character-string> is expressed in one or two ways: as a contiguous set
+of characters without interior spaces, or as a string beginning with a "
+and ending with a ". Inside a " delimited string any character can
+occur, except for a " itself, which must be quoted using \ (back slash).
+
+Because these files are text files several special encodings are
+necessary to allow arbitrary data to be loaded. In particular:
+
+ of the root.
+
+@ A free standing @ is used to denote the current origin.
+
+\X where X is any character other than a digit (0-9), is
+ used to quote that character so that its special meaning
+ does not apply. For example, "\." can be used to place
+ a dot character in a label.
+
+\DDD where each D is a digit is the octet corresponding to
+ the decimal number described by DDD. The resulting
+ octet is assumed to be text and is not checked for
+ special meaning.
+
+( ) Parentheses are used to group data that crosses a line
+ boundary. In effect, line terminations are not
+ recognized within parentheses.
+
+; Semicolon is used to start a comment; the remainder of
+ the line is ignored.
+
+5.2. Use of master files to define zones
+
+When a master file is used to load a zone, the operation should be
+suppressed if any errors are encountered in the master file. The
+rationale for this is that a single error can have widespread
+consequences. For example, suppose that the RRs defining a delegation
+have syntax errors; then the server will return authoritative name
+errors for all names in the subzone (except in the case where the
+subzone is also present on the server).
+
+Several other validity checks that should be performed in addition to
+insuring that the file is syntactically correct:
+
+ 1. All RRs in the file should have the same class.
+
+ 2. Exactly one SOA RR should be present at the top of the zone.
+
+ 3. If delegations are present and glue information is required,
+ it should be present.
+
+
+
+Mockapetris [Page 35]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 4. Information present outside of the authoritative nodes in the
+ zone should be glue information, rather than the result of an
+ origin or similar error.
+
+5.3. Master file example
+
+The following is an example file which might be used to define the
+ISI.EDU zone.and is loaded with an origin of ISI.EDU:
+
+@ IN SOA VENERA Action\.domains (
+ 20 ; SERIAL
+ 7200 ; REFRESH
+ 600 ; RETRY
+ 3600000; EXPIRE
+ 60) ; MINIMUM
+
+ NS A.ISI.EDU.
+ NS VENERA
+ NS VAXA
+ MX 10 VENERA
+ MX 20 VAXA
+
+A A 26.3.0.103
+
+VENERA A 10.1.0.52
+ A 128.9.0.32
+
+VAXA A 10.2.0.27
+ A 128.9.0.33
+
+
+$INCLUDE <SUBSYS>ISI-MAILBOXES.TXT
+
+Where the file <SUBSYS>ISI-MAILBOXES.TXT is:
+
+ MOE MB A.ISI.EDU.
+ LARRY MB A.ISI.EDU.
+ CURLEY MB A.ISI.EDU.
+ STOOGES MG MOE
+ MG LARRY
+ MG CURLEY
+
+Note the use of the \ character in the SOA RR to specify the responsible
+person mailbox "Action.domains@E.ISI.EDU".
+
+
+
+
+
+
+
+Mockapetris [Page 36]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+6. NAME SERVER IMPLEMENTATION
+
+6.1. Architecture
+
+The optimal structure for the name server will depend on the host
+operating system and whether the name server is integrated with resolver
+operations, either by supporting recursive service, or by sharing its
+database with a resolver. This section discusses implementation
+considerations for a name server which shares a database with a
+resolver, but most of these concerns are present in any name server.
+
+6.1.1. Control
+
+A name server must employ multiple concurrent activities, whether they
+are implemented as separate tasks in the host's OS or multiplexing
+inside a single name server program. It is simply not acceptable for a
+name server to block the service of UDP requests while it waits for TCP
+data for refreshing or query activities. Similarly, a name server
+should not attempt to provide recursive service without processing such
+requests in parallel, though it may choose to serialize requests from a
+single client, or to regard identical requests from the same client as
+duplicates. A name server should not substantially delay requests while
+it reloads a zone from master files or while it incorporates a newly
+refreshed zone into its database.
+
+6.1.2. Database
+
+While name server implementations are free to use any internal data
+structures they choose, the suggested structure consists of three major
+parts:
+
+ - A "catalog" data structure which lists the zones available to
+ this server, and a "pointer" to the zone data structure. The
+ main purpose of this structure is to find the nearest ancestor
+ zone, if any, for arriving standard queries.
+
+ - Separate data structures for each of the zones held by the
+ name server.
+
+ - A data structure for cached data. (or perhaps separate caches
+ for different classes)
+
+All of these data structures can be implemented an identical tree
+structure format, with different data chained off the nodes in different
+parts: in the catalog the data is pointers to zones, while in the zone
+and cache data structures, the data will be RRs. In designing the tree
+framework the designer should recognize that query processing will need
+to traverse the tree using case-insensitive label comparisons; and that
+
+
+
+Mockapetris [Page 37]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+in real data, a few nodes have a very high branching factor (100-1000 or
+more), but the vast majority have a very low branching factor (0-1).
+
+One way to solve the case problem is to store the labels for each node
+in two pieces: a standardized-case representation of the label where all
+ASCII characters are in a single case, together with a bit mask that
+denotes which characters are actually of a different case. The
+branching factor diversity can be handled using a simple linked list for
+a node until the branching factor exceeds some threshold, and
+transitioning to a hash structure after the threshold is exceeded. In
+any case, hash structures used to store tree sections must insure that
+hash functions and procedures preserve the casing conventions of the
+DNS.
+
+The use of separate structures for the different parts of the database
+is motivated by several factors:
+
+ - The catalog structure can be an almost static structure that
+ need change only when the system administrator changes the
+ zones supported by the server. This structure can also be
+ used to store parameters used to control refreshing
+ activities.
+
+ - The individual data structures for zones allow a zone to be
+ replaced simply by changing a pointer in the catalog. Zone
+ refresh operations can build a new structure and, when
+ complete, splice it into the database via a simple pointer
+ replacement. It is very important that when a zone is
+ refreshed, queries should not use old and new data
+ simultaneously.
+
+ - With the proper search procedures, authoritative data in zones
+ will always "hide", and hence take precedence over, cached
+ data.
+
+ - Errors in zone definitions that cause overlapping zones, etc.,
+ may cause erroneous responses to queries, but problem
+ determination is simplified, and the contents of one "bad"
+ zone can't corrupt another.
+
+ - Since the cache is most frequently updated, it is most
+ vulnerable to corruption during system restarts. It can also
+ become full of expired RR data. In either case, it can easily
+ be discarded without disturbing zone data.
+
+A major aspect of database design is selecting a structure which allows
+the name server to deal with crashes of the name server's host. State
+information which a name server should save across system crashes
+
+
+
+Mockapetris [Page 38]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+includes the catalog structure (including the state of refreshing for
+each zone) and the zone data itself.
+
+6.1.3. Time
+
+Both the TTL data for RRs and the timing data for refreshing activities
+depends on 32 bit timers in units of seconds. Inside the database,
+refresh timers and TTLs for cached data conceptually "count down", while
+data in the zone stays with constant TTLs.
+
+A recommended implementation strategy is to store time in two ways: as
+a relative increment and as an absolute time. One way to do this is to
+use positive 32 bit numbers for one type and negative numbers for the
+other. The RRs in zones use relative times; the refresh timers and
+cache data use absolute times. Absolute numbers are taken with respect
+to some known origin and converted to relative values when placed in the
+response to a query. When an absolute TTL is negative after conversion
+to relative, then the data is expired and should be ignored.
+
+6.2. Standard query processing
+
+The major algorithm for standard query processing is presented in
+[RFC-1034].
+
+When processing queries with QCLASS=*, or some other QCLASS which
+matches multiple classes, the response should never be authoritative
+unless the server can guarantee that the response covers all classes.
+
+When composing a response, RRs which are to be inserted in the
+additional section, but duplicate RRs in the answer or authority
+sections, may be omitted from the additional section.
+
+When a response is so long that truncation is required, the truncation
+should start at the end of the response and work forward in the
+datagram. Thus if there is any data for the authority section, the
+answer section is guaranteed to be unique.
+
+The MINIMUM value in the SOA should be used to set a floor on the TTL of
+data distributed from a zone. This floor function should be done when
+the data is copied into a response. This will allow future dynamic
+update protocols to change the SOA MINIMUM field without ambiguous
+semantics.
+
+6.3. Zone refresh and reload processing
+
+In spite of a server's best efforts, it may be unable to load zone data
+from a master file due to syntax errors, etc., or be unable to refresh a
+zone within the its expiration parameter. In this case, the name server
+
+
+
+Mockapetris [Page 39]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+should answer queries as if it were not supposed to possess the zone.
+
+If a master is sending a zone out via AXFR, and a new version is created
+during the transfer, the master should continue to send the old version
+if possible. In any case, it should never send part of one version and
+part of another. If completion is not possible, the master should reset
+the connection on which the zone transfer is taking place.
+
+6.4. Inverse queries (Optional)
+
+Inverse queries are an optional part of the DNS. Name servers are not
+required to support any form of inverse queries. If a name server
+receives an inverse query that it does not support, it returns an error
+response with the "Not Implemented" error set in the header. While
+inverse query support is optional, all name servers must be at least
+able to return the error response.
+
+6.4.1. The contents of inverse queries and responses Inverse
+queries reverse the mappings performed by standard query operations;
+while a standard query maps a domain name to a resource, an inverse
+query maps a resource to a domain name. For example, a standard query
+might bind a domain name to a host address; the corresponding inverse
+query binds the host address to a domain name.
+
+Inverse queries take the form of a single RR in the answer section of
+the message, with an empty question section. The owner name of the
+query RR and its TTL are not significant. The response carries
+questions in the question section which identify all names possessing
+the query RR WHICH THE NAME SERVER KNOWS. Since no name server knows
+about all of the domain name space, the response can never be assumed to
+be complete. Thus inverse queries are primarily useful for database
+management and debugging activities. Inverse queries are NOT an
+acceptable method of mapping host addresses to host names; use the IN-
+ADDR.ARPA domain instead.
+
+Where possible, name servers should provide case-insensitive comparisons
+for inverse queries. Thus an inverse query asking for an MX RR of
+"Venera.isi.edu" should get the same response as a query for
+"VENERA.ISI.EDU"; an inverse query for HINFO RR "IBM-PC UNIX" should
+produce the same result as an inverse query for "IBM-pc unix". However,
+this cannot be guaranteed because name servers may possess RRs that
+contain character strings but the name server does not know that the
+data is character.
+
+When a name server processes an inverse query, it either returns:
+
+ 1. zero, one, or multiple domain names for the specified
+ resource as QNAMEs in the question section
+
+
+
+Mockapetris [Page 40]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 2. an error code indicating that the name server doesn't support
+ inverse mapping of the specified resource type.
+
+When the response to an inverse query contains one or more QNAMEs, the
+owner name and TTL of the RR in the answer section which defines the
+inverse query is modified to exactly match an RR found at the first
+QNAME.
+
+RRs returned in the inverse queries cannot be cached using the same
+mechanism as is used for the replies to standard queries. One reason
+for this is that a name might have multiple RRs of the same type, and
+only one would appear. For example, an inverse query for a single
+address of a multiply homed host might create the impression that only
+one address existed.
+
+6.4.2. Inverse query and response example The overall structure
+of an inverse query for retrieving the domain name that corresponds to
+Internet address 10.1.0.52 is shown below:
+
+ +-----------------------------------------+
+ Header | OPCODE=IQUERY, ID=997 |
+ +-----------------------------------------+
+ Question | <empty> |
+ +-----------------------------------------+
+ Answer | <anyname> A IN 10.1.0.52 |
+ +-----------------------------------------+
+ Authority | <empty> |
+ +-----------------------------------------+
+ Additional | <empty> |
+ +-----------------------------------------+
+
+This query asks for a question whose answer is the Internet style
+address 10.1.0.52. Since the owner name is not known, any domain name
+can be used as a placeholder (and is ignored). A single octet of zero,
+signifying the root, is usually used because it minimizes the length of
+the message. The TTL of the RR is not significant. The response to
+this query might be:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 41]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ +-----------------------------------------+
+ Header | OPCODE=RESPONSE, ID=997 |
+ +-----------------------------------------+
+ Question |QTYPE=A, QCLASS=IN, QNAME=VENERA.ISI.EDU |
+ +-----------------------------------------+
+ Answer | VENERA.ISI.EDU A IN 10.1.0.52 |
+ +-----------------------------------------+
+ Authority | <empty> |
+ +-----------------------------------------+
+ Additional | <empty> |
+ +-----------------------------------------+
+
+Note that the QTYPE in a response to an inverse query is the same as the
+TYPE field in the answer section of the inverse query. Responses to
+inverse queries may contain multiple questions when the inverse is not
+unique. If the question section in the response is not empty, then the
+RR in the answer section is modified to correspond to be an exact copy
+of an RR at the first QNAME.
+
+6.4.3. Inverse query processing
+
+Name servers that support inverse queries can support these operations
+through exhaustive searches of their databases, but this becomes
+impractical as the size of the database increases. An alternative
+approach is to invert the database according to the search key.
+
+For name servers that support multiple zones and a large amount of data,
+the recommended approach is separate inversions for each zone. When a
+particular zone is changed during a refresh, only its inversions need to
+be redone.
+
+Support for transfer of this type of inversion may be included in future
+versions of the domain system, but is not supported in this version.
+
+6.5. Completion queries and responses
+
+The optional completion services described in RFC-882 and RFC-883 have
+been deleted. Redesigned services may become available in the future.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 42]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+7. RESOLVER IMPLEMENTATION
+
+The top levels of the recommended resolver algorithm are discussed in
+[RFC-1034]. This section discusses implementation details assuming the
+database structure suggested in the name server implementation section
+of this memo.
+
+7.1. Transforming a user request into a query
+
+The first step a resolver takes is to transform the client's request,
+stated in a format suitable to the local OS, into a search specification
+for RRs at a specific name which match a specific QTYPE and QCLASS.
+Where possible, the QTYPE and QCLASS should correspond to a single type
+and a single class, because this makes the use of cached data much
+simpler. The reason for this is that the presence of data of one type
+in a cache doesn't confirm the existence or non-existence of data of
+other types, hence the only way to be sure is to consult an
+authoritative source. If QCLASS=* is used, then authoritative answers
+won't be available.
+
+Since a resolver must be able to multiplex multiple requests if it is to
+perform its function efficiently, each pending request is usually
+represented in some block of state information. This state block will
+typically contain:
+
+ - A timestamp indicating the time the request began.
+ The timestamp is used to decide whether RRs in the database
+ can be used or are out of date. This timestamp uses the
+ absolute time format previously discussed for RR storage in
+ zones and caches. Note that when an RRs TTL indicates a
+ relative time, the RR must be timely, since it is part of a
+ zone. When the RR has an absolute time, it is part of a
+ cache, and the TTL of the RR is compared against the timestamp
+ for the start of the request.
+
+ Note that using the timestamp is superior to using a current
+ time, since it allows RRs with TTLs of zero to be entered in
+ the cache in the usual manner, but still used by the current
+ request, even after intervals of many seconds due to system
+ load, query retransmission timeouts, etc.
+
+ - Some sort of parameters to limit the amount of work which will
+ be performed for this request.
+
+ The amount of work which a resolver will do in response to a
+ client request must be limited to guard against errors in the
+ database, such as circular CNAME references, and operational
+ problems, such as network partition which prevents the
+
+
+
+Mockapetris [Page 43]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ resolver from accessing the name servers it needs. While
+ local limits on the number of times a resolver will retransmit
+ a particular query to a particular name server address are
+ essential, the resolver should have a global per-request
+ counter to limit work on a single request. The counter should
+ be set to some initial value and decremented whenever the
+ resolver performs any action (retransmission timeout,
+ retransmission, etc.) If the counter passes zero, the request
+ is terminated with a temporary error.
+
+ Note that if the resolver structure allows one request to
+ start others in parallel, such as when the need to access a
+ name server for one request causes a parallel resolve for the
+ name server's addresses, the spawned request should be started
+ with a lower counter. This prevents circular references in
+ the database from starting a chain reaction of resolver
+ activity.
+
+ - The SLIST data structure discussed in [RFC-1034].
+
+ This structure keeps track of the state of a request if it
+ must wait for answers from foreign name servers.
+
+7.2. Sending the queries
+
+As described in [RFC-1034], the basic task of the resolver is to
+formulate a query which will answer the client's request and direct that
+query to name servers which can provide the information. The resolver
+will usually only have very strong hints about which servers to ask, in
+the form of NS RRs, and may have to revise the query, in response to
+CNAMEs, or revise the set of name servers the resolver is asking, in
+response to delegation responses which point the resolver to name
+servers closer to the desired information. In addition to the
+information requested by the client, the resolver may have to call upon
+its own services to determine the address of name servers it wishes to
+contact.
+
+In any case, the model used in this memo assumes that the resolver is
+multiplexing attention between multiple requests, some from the client,
+and some internally generated. Each request is represented by some
+state information, and the desired behavior is that the resolver
+transmit queries to name servers in a way that maximizes the probability
+that the request is answered, minimizes the time that the request takes,
+and avoids excessive transmissions. The key algorithm uses the state
+information of the request to select the next name server address to
+query, and also computes a timeout which will cause the next action
+should a response not arrive. The next action will usually be a
+transmission to some other server, but may be a temporary error to the
+
+
+
+Mockapetris [Page 44]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+client.
+
+The resolver always starts with a list of server names to query (SLIST).
+This list will be all NS RRs which correspond to the nearest ancestor
+zone that the resolver knows about. To avoid startup problems, the
+resolver should have a set of default servers which it will ask should
+it have no current NS RRs which are appropriate. The resolver then adds
+to SLIST all of the known addresses for the name servers, and may start
+parallel requests to acquire the addresses of the servers when the
+resolver has the name, but no addresses, for the name servers.
+
+To complete initialization of SLIST, the resolver attaches whatever
+history information it has to the each address in SLIST. This will
+usually consist of some sort of weighted averages for the response time
+of the address, and the batting average of the address (i.e., how often
+the address responded at all to the request). Note that this
+information should be kept on a per address basis, rather than on a per
+name server basis, because the response time and batting average of a
+particular server may vary considerably from address to address. Note
+also that this information is actually specific to a resolver address /
+server address pair, so a resolver with multiple addresses may wish to
+keep separate histories for each of its addresses. Part of this step
+must deal with addresses which have no such history; in this case an
+expected round trip time of 5-10 seconds should be the worst case, with
+lower estimates for the same local network, etc.
+
+Note that whenever a delegation is followed, the resolver algorithm
+reinitializes SLIST.
+
+The information establishes a partial ranking of the available name
+server addresses. Each time an address is chosen and the state should
+be altered to prevent its selection again until all other addresses have
+been tried. The timeout for each transmission should be 50-100% greater
+than the average predicted value to allow for variance in response.
+
+Some fine points:
+
+ - The resolver may encounter a situation where no addresses are
+ available for any of the name servers named in SLIST, and
+ where the servers in the list are precisely those which would
+ normally be used to look up their own addresses. This
+ situation typically occurs when the glue address RRs have a
+ smaller TTL than the NS RRs marking delegation, or when the
+ resolver caches the result of a NS search. The resolver
+ should detect this condition and restart the search at the
+ next ancestor zone, or alternatively at the root.
+
+
+
+
+
+Mockapetris [Page 45]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ - If a resolver gets a server error or other bizarre response
+ from a name server, it should remove it from SLIST, and may
+ wish to schedule an immediate transmission to the next
+ candidate server address.
+
+7.3. Processing responses
+
+The first step in processing arriving response datagrams is to parse the
+response. This procedure should include:
+
+ - Check the header for reasonableness. Discard datagrams which
+ are queries when responses are expected.
+
+ - Parse the sections of the message, and insure that all RRs are
+ correctly formatted.
+
+ - As an optional step, check the TTLs of arriving data looking
+ for RRs with excessively long TTLs. If a RR has an
+ excessively long TTL, say greater than 1 week, either discard
+ the whole response, or limit all TTLs in the response to 1
+ week.
+
+The next step is to match the response to a current resolver request.
+The recommended strategy is to do a preliminary matching using the ID
+field in the domain header, and then to verify that the question section
+corresponds to the information currently desired. This requires that
+the transmission algorithm devote several bits of the domain ID field to
+a request identifier of some sort. This step has several fine points:
+
+ - Some name servers send their responses from different
+ addresses than the one used to receive the query. That is, a
+ resolver cannot rely that a response will come from the same
+ address which it sent the corresponding query to. This name
+ server bug is typically encountered in UNIX systems.
+
+ - If the resolver retransmits a particular request to a name
+ server it should be able to use a response from any of the
+ transmissions. However, if it is using the response to sample
+ the round trip time to access the name server, it must be able
+ to determine which transmission matches the response (and keep
+ transmission times for each outgoing message), or only
+ calculate round trip times based on initial transmissions.
+
+ - A name server will occasionally not have a current copy of a
+ zone which it should have according to some NS RRs. The
+ resolver should simply remove the name server from the current
+ SLIST, and continue.
+
+
+
+
+Mockapetris [Page 46]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+7.4. Using the cache
+
+In general, we expect a resolver to cache all data which it receives in
+responses since it may be useful in answering future client requests.
+However, there are several types of data which should not be cached:
+
+ - When several RRs of the same type are available for a
+ particular owner name, the resolver should either cache them
+ all or none at all. When a response is truncated, and a
+ resolver doesn't know whether it has a complete set, it should
+ not cache a possibly partial set of RRs.
+
+ - Cached data should never be used in preference to
+ authoritative data, so if caching would cause this to happen
+ the data should not be cached.
+
+ - The results of an inverse query should not be cached.
+
+ - The results of standard queries where the QNAME contains "*"
+ labels if the data might be used to construct wildcards. The
+ reason is that the cache does not necessarily contain existing
+ RRs or zone boundary information which is necessary to
+ restrict the application of the wildcard RRs.
+
+ - RR data in responses of dubious reliability. When a resolver
+ receives unsolicited responses or RR data other than that
+ requested, it should discard it without caching it. The basic
+ implication is that all sanity checks on a packet should be
+ performed before any of it is cached.
+
+In a similar vein, when a resolver has a set of RRs for some name in a
+response, and wants to cache the RRs, it should check its cache for
+already existing RRs. Depending on the circumstances, either the data
+in the response or the cache is preferred, but the two should never be
+combined. If the data in the response is from authoritative data in the
+answer section, it is always preferred.
+
+8. MAIL SUPPORT
+
+The domain system defines a standard for mapping mailboxes into domain
+names, and two methods for using the mailbox information to derive mail
+routing information. The first method is called mail exchange binding
+and the other method is mailbox binding. The mailbox encoding standard
+and mail exchange binding are part of the DNS official protocol, and are
+the recommended method for mail routing in the Internet. Mailbox
+binding is an experimental feature which is still under development and
+subject to change.
+
+
+
+
+Mockapetris [Page 47]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+The mailbox encoding standard assumes a mailbox name of the form
+"<local-part>@<mail-domain>". While the syntax allowed in each of these
+sections varies substantially between the various mail internets, the
+preferred syntax for the ARPA Internet is given in [RFC-822].
+
+The DNS encodes the <local-part> as a single label, and encodes the
+<mail-domain> as a domain name. The single label from the <local-part>
+is prefaced to the domain name from <mail-domain> to form the domain
+name corresponding to the mailbox. Thus the mailbox HOSTMASTER@SRI-
+NIC.ARPA is mapped into the domain name HOSTMASTER.SRI-NIC.ARPA. If the
+<local-part> contains dots or other special characters, its
+representation in a master file will require the use of backslash
+quoting to ensure that the domain name is properly encoded. For
+example, the mailbox Action.domains@ISI.EDU would be represented as
+Action\.domains.ISI.EDU.
+
+8.1. Mail exchange binding
+
+Mail exchange binding uses the <mail-domain> part of a mailbox
+specification to determine where mail should be sent. The <local-part>
+is not even consulted. [RFC-974] specifies this method in detail, and
+should be consulted before attempting to use mail exchange support.
+
+One of the advantages of this method is that it decouples mail
+destination naming from the hosts used to support mail service, at the
+cost of another layer of indirection in the lookup function. However,
+the addition layer should eliminate the need for complicated "%", "!",
+etc encodings in <local-part>.
+
+The essence of the method is that the <mail-domain> is used as a domain
+name to locate type MX RRs which list hosts willing to accept mail for
+<mail-domain>, together with preference values which rank the hosts
+according to an order specified by the administrators for <mail-domain>.
+
+In this memo, the <mail-domain> ISI.EDU is used in examples, together
+with the hosts VENERA.ISI.EDU and VAXA.ISI.EDU as mail exchanges for
+ISI.EDU. If a mailer had a message for Mockapetris@ISI.EDU, it would
+route it by looking up MX RRs for ISI.EDU. The MX RRs at ISI.EDU name
+VENERA.ISI.EDU and VAXA.ISI.EDU, and type A queries can find the host
+addresses.
+
+8.2. Mailbox binding (Experimental)
+
+In mailbox binding, the mailer uses the entire mail destination
+specification to construct a domain name. The encoded domain name for
+the mailbox is used as the QNAME field in a QTYPE=MAILB query.
+
+Several outcomes are possible for this query:
+
+
+
+Mockapetris [Page 48]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 1. The query can return a name error indicating that the mailbox
+ does not exist as a domain name.
+
+ In the long term, this would indicate that the specified
+ mailbox doesn't exist. However, until the use of mailbox
+ binding is universal, this error condition should be
+ interpreted to mean that the organization identified by the
+ global part does not support mailbox binding. The
+ appropriate procedure is to revert to exchange binding at
+ this point.
+
+ 2. The query can return a Mail Rename (MR) RR.
+
+ The MR RR carries new mailbox specification in its RDATA
+ field. The mailer should replace the old mailbox with the
+ new one and retry the operation.
+
+ 3. The query can return a MB RR.
+
+ The MB RR carries a domain name for a host in its RDATA
+ field. The mailer should deliver the message to that host
+ via whatever protocol is applicable, e.g., b,SMTP.
+
+ 4. The query can return one or more Mail Group (MG) RRs.
+
+ This condition means that the mailbox was actually a mailing
+ list or mail group, rather than a single mailbox. Each MG RR
+ has a RDATA field that identifies a mailbox that is a member
+ of the group. The mailer should deliver a copy of the
+ message to each member.
+
+ 5. The query can return a MB RR as well as one or more MG RRs.
+
+ This condition means the the mailbox was actually a mailing
+ list. The mailer can either deliver the message to the host
+ specified by the MB RR, which will in turn do the delivery to
+ all members, or the mailer can use the MG RRs to do the
+ expansion itself.
+
+In any of these cases, the response may include a Mail Information
+(MINFO) RR. This RR is usually associated with a mail group, but is
+legal with a MB. The MINFO RR identifies two mailboxes. One of these
+identifies a responsible person for the original mailbox name. This
+mailbox should be used for requests to be added to a mail group, etc.
+The second mailbox name in the MINFO RR identifies a mailbox that should
+receive error messages for mail failures. This is particularly
+appropriate for mailing lists when errors in member names should be
+reported to a person other than the one who sends a message to the list.
+
+
+
+Mockapetris [Page 49]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+New fields may be added to this RR in the future.
+
+
+9. REFERENCES and BIBLIOGRAPHY
+
+[Dyer 87] S. Dyer, F. Hsu, "Hesiod", Project Athena
+ Technical Plan - Name Service, April 1987, version 1.9.
+
+ Describes the fundamentals of the Hesiod name service.
+
+[IEN-116] J. Postel, "Internet Name Server", IEN-116,
+ USC/Information Sciences Institute, August 1979.
+
+ A name service obsoleted by the Domain Name System, but
+ still in use.
+
+[Quarterman 86] J. Quarterman, and J. Hoskins, "Notable Computer Networks",
+ Communications of the ACM, October 1986, volume 29, number
+ 10.
+
+[RFC-742] K. Harrenstien, "NAME/FINGER", RFC-742, Network
+ Information Center, SRI International, December 1977.
+
+[RFC-768] J. Postel, "User Datagram Protocol", RFC-768,
+ USC/Information Sciences Institute, August 1980.
+
+[RFC-793] J. Postel, "Transmission Control Protocol", RFC-793,
+ USC/Information Sciences Institute, September 1981.
+
+[RFC-799] D. Mills, "Internet Name Domains", RFC-799, COMSAT,
+ September 1981.
+
+ Suggests introduction of a hierarchy in place of a flat
+ name space for the Internet.
+
+[RFC-805] J. Postel, "Computer Mail Meeting Notes", RFC-805,
+ USC/Information Sciences Institute, February 1982.
+
+[RFC-810] E. Feinler, K. Harrenstien, Z. Su, and V. White, "DOD
+ Internet Host Table Specification", RFC-810, Network
+ Information Center, SRI International, March 1982.
+
+ Obsolete. See RFC-952.
+
+[RFC-811] K. Harrenstien, V. White, and E. Feinler, "Hostnames
+ Server", RFC-811, Network Information Center, SRI
+ International, March 1982.
+
+
+
+
+Mockapetris [Page 50]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ Obsolete. See RFC-953.
+
+[RFC-812] K. Harrenstien, and V. White, "NICNAME/WHOIS", RFC-812,
+ Network Information Center, SRI International, March
+ 1982.
+
+[RFC-819] Z. Su, and J. Postel, "The Domain Naming Convention for
+ Internet User Applications", RFC-819, Network
+ Information Center, SRI International, August 1982.
+
+ Early thoughts on the design of the domain system.
+ Current implementation is completely different.
+
+[RFC-821] J. Postel, "Simple Mail Transfer Protocol", RFC-821,
+ USC/Information Sciences Institute, August 1980.
+
+[RFC-830] Z. Su, "A Distributed System for Internet Name Service",
+ RFC-830, Network Information Center, SRI International,
+ October 1982.
+
+ Early thoughts on the design of the domain system.
+ Current implementation is completely different.
+
+[RFC-882] P. Mockapetris, "Domain names - Concepts and
+ Facilities," RFC-882, USC/Information Sciences
+ Institute, November 1983.
+
+ Superceeded by this memo.
+
+[RFC-883] P. Mockapetris, "Domain names - Implementation and
+ Specification," RFC-883, USC/Information Sciences
+ Institute, November 1983.
+
+ Superceeded by this memo.
+
+[RFC-920] J. Postel and J. Reynolds, "Domain Requirements",
+ RFC-920, USC/Information Sciences Institute,
+ October 1984.
+
+ Explains the naming scheme for top level domains.
+
+[RFC-952] K. Harrenstien, M. Stahl, E. Feinler, "DoD Internet Host
+ Table Specification", RFC-952, SRI, October 1985.
+
+ Specifies the format of HOSTS.TXT, the host/address
+ table replaced by the DNS.
+
+
+
+
+
+Mockapetris [Page 51]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+[RFC-953] K. Harrenstien, M. Stahl, E. Feinler, "HOSTNAME Server",
+ RFC-953, SRI, October 1985.
+
+ This RFC contains the official specification of the
+ hostname server protocol, which is obsoleted by the DNS.
+ This TCP based protocol accesses information stored in
+ the RFC-952 format, and is used to obtain copies of the
+ host table.
+
+[RFC-973] P. Mockapetris, "Domain System Changes and
+ Observations", RFC-973, USC/Information Sciences
+ Institute, January 1986.
+
+ Describes changes to RFC-882 and RFC-883 and reasons for
+ them.
+
+[RFC-974] C. Partridge, "Mail routing and the domain system",
+ RFC-974, CSNET CIC BBN Labs, January 1986.
+
+ Describes the transition from HOSTS.TXT based mail
+ addressing to the more powerful MX system used with the
+ domain system.
+
+[RFC-1001] NetBIOS Working Group, "Protocol standard for a NetBIOS
+ service on a TCP/UDP transport: Concepts and Methods",
+ RFC-1001, March 1987.
+
+ This RFC and RFC-1002 are a preliminary design for
+ NETBIOS on top of TCP/IP which proposes to base NetBIOS
+ name service on top of the DNS.
+
+[RFC-1002] NetBIOS Working Group, "Protocol standard for a NetBIOS
+ service on a TCP/UDP transport: Detailed
+ Specifications", RFC-1002, March 1987.
+
+[RFC-1010] J. Reynolds, and J. Postel, "Assigned Numbers", RFC-1010,
+ USC/Information Sciences Institute, May 1987.
+
+ Contains socket numbers and mnemonics for host names,
+ operating systems, etc.
+
+[RFC-1031] W. Lazear, "MILNET Name Domain Transition", RFC-1031,
+ November 1987.
+
+ Describes a plan for converting the MILNET to the DNS.
+
+[RFC-1032] M. Stahl, "Establishing a Domain - Guidelines for
+ Administrators", RFC-1032, November 1987.
+
+
+
+Mockapetris [Page 52]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ Describes the registration policies used by the NIC to
+ administer the top level domains and delegate subzones.
+
+[RFC-1033] M. Lottor, "Domain Administrators Operations Guide",
+ RFC-1033, November 1987.
+
+ A cookbook for domain administrators.
+
+[Solomon 82] M. Solomon, L. Landweber, and D. Neuhengen, "The CSNET
+ Name Server", Computer Networks, vol 6, nr 3, July 1982.
+
+ Describes a name service for CSNET which is independent
+ from the DNS and DNS use in the CSNET.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 53]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+Index
+
+ * 13
+
+ ; 33, 35
+
+ <character-string> 35
+ <domain-name> 34
+
+ @ 35
+
+ \ 35
+
+ A 12
+
+ Byte order 8
+
+ CH 13
+ Character case 9
+ CLASS 11
+ CNAME 12
+ Completion 42
+ CS 13
+
+ Hesiod 13
+ HINFO 12
+ HS 13
+
+ IN 13
+ IN-ADDR.ARPA domain 22
+ Inverse queries 40
+
+ Mailbox names 47
+ MB 12
+ MD 12
+ MF 12
+ MG 12
+ MINFO 12
+ MINIMUM 20
+ MR 12
+ MX 12
+
+ NS 12
+ NULL 12
+
+ Port numbers 32
+ Primary server 5
+ PTR 12, 18
+
+
+
+Mockapetris [Page 54]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ QCLASS 13
+ QTYPE 12
+
+ RDATA 12
+ RDLENGTH 11
+
+ Secondary server 5
+ SOA 12
+ Stub resolvers 7
+
+ TCP 32
+ TXT 12
+ TYPE 11
+
+ UDP 32
+
+ WKS 12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 55]
+
diff --git a/bin/tests/dst/t2_dsasig b/bin/tests/dst/t2_dsasig
new file mode 100644
index 0000000..5dd12e1
--- /dev/null
+++ b/bin/tests/dst/t2_dsasig
@@ -0,0 +1,3 @@
+0009B55FDB62034326278C9371F32D92
+3D0E1161A32D491BEC38546FC452D903
+A91D806345B2F7F22E
diff --git a/bin/tests/dst/t2_rsasig b/bin/tests/dst/t2_rsasig
new file mode 100644
index 0000000..5f59ef3
--- /dev/null
+++ b/bin/tests/dst/t2_rsasig
@@ -0,0 +1,6 @@
+A8A20D2F26F792B3CE76DD0E12A85DFE
+FF66AB866EF0BDB0F515001E234E699B
+F5CD6FB41FB15D4213705ABE9B563896
+2196228648E0F8AA7F2F4EED3C19165C
+1B4C70C9D69B93A1F2BE5B2F948CE023
+
diff --git a/bin/tests/dst/t_dst.c b/bin/tests/dst/t_dst.c
new file mode 100644
index 0000000..d5e5db7
--- /dev/null
+++ b/bin/tests/dst/t_dst.c
@@ -0,0 +1,933 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: t_dst.c,v 1.55 2008/01/12 23:47:13 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h> /* Required for dirent.h */
+#include <sys/stat.h>
+
+#include <dirent.h> /* XXX */
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include <unistd.h> /* XXX */
+
+#include <isc/buffer.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+
+#include <dst/dst.h>
+#include <dst/result.h>
+
+#include <tests/t_api.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 256
+#endif
+
+/*
+ * Adapted from the original dst_test.c program.
+ * XXXDCL should use isc_dir_*.
+ */
+
+static void
+cleandir(char *path) {
+ DIR *dirp;
+ struct dirent *pe;
+ char fullname[PATH_MAX + 1];
+
+ dirp = opendir(path);
+ if (dirp == NULL) {
+ t_info("opendir(%s) failed %d\n", path, errno);
+ return;
+ }
+
+ while ((pe = readdir(dirp)) != NULL) {
+ if (! strcmp(pe->d_name, "."))
+ continue;
+ if (! strcmp(pe->d_name, ".."))
+ continue;
+ strcpy(fullname, path);
+ strcat(fullname, "/");
+ strcat(fullname, pe->d_name);
+ if (remove(fullname))
+ t_info("remove(%s) failed %d\n", fullname, errno);
+
+ }
+ (void)closedir(dirp);
+ if (rmdir(path))
+ t_info("rmdir(%s) failed %d\n", path, errno);
+
+ return;
+}
+
+static void
+use(dst_key_t *key, isc_mem_t *mctx, isc_result_t exp_result, int *nfails) {
+
+ isc_result_t ret;
+ const char *data = "This is some data";
+ unsigned char sig[512];
+ isc_buffer_t databuf, sigbuf;
+ isc_region_t datareg, sigreg;
+ dst_context_t *ctx = NULL;
+
+ isc_buffer_init(&sigbuf, sig, sizeof(sig));
+ isc_buffer_init(&databuf, data, strlen(data));
+ isc_buffer_add(&databuf, strlen(data));
+ isc_buffer_usedregion(&databuf, &datareg);
+
+ ret = dst_context_create(key, mctx, &ctx);
+ if (ret != exp_result) {
+ t_info("dst_context_create(%d) returned (%s) expected (%s)\n",
+ dst_key_alg(key), dst_result_totext(ret),
+ dst_result_totext(exp_result));
+ ++*nfails;
+ return;
+ }
+ if (exp_result != ISC_R_SUCCESS)
+ return;
+ ret = dst_context_adddata(ctx, &datareg);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("dst_context_adddata(%d) returned (%s)\n",
+ dst_key_alg(key), dst_result_totext(ret));
+ ++*nfails;
+ dst_context_destroy(&ctx);
+ return;
+ }
+ ret = dst_context_sign(ctx, &sigbuf);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("dst_context_sign(%d) returned (%s)\n",
+ dst_key_alg(key), dst_result_totext(ret));
+ ++*nfails;
+ dst_context_destroy(&ctx);
+ return;
+ }
+ dst_context_destroy(&ctx);
+
+ isc_buffer_remainingregion(&sigbuf, &sigreg);
+ ret = dst_context_create(key, mctx, &ctx);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("dst_context_create(%d) returned (%s)\n",
+ dst_key_alg(key), dst_result_totext(ret));
+ ++*nfails;
+ return;
+ }
+ ret = dst_context_adddata(ctx, &datareg);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("dst_context_adddata(%d) returned (%s)\n",
+ dst_key_alg(key), dst_result_totext(ret));
+ ++*nfails;
+ dst_context_destroy(&ctx);
+ return;
+ }
+ ret = dst_context_verify(ctx, &sigreg);
+ if (ret != exp_result) {
+ t_info("dst_context_verify(%d) returned (%s) expected (%s)\n",
+ dst_key_alg(key), dst_result_totext(ret),
+ dst_result_totext(exp_result));
+ ++*nfails;
+ dst_context_destroy(&ctx);
+ return;
+ }
+ dst_context_destroy(&ctx);
+}
+
+static void
+dh(dns_name_t *name1, int id1, dns_name_t *name2, int id2, isc_mem_t *mctx,
+ isc_result_t exp_result, int *nfails, int *nprobs)
+{
+ dst_key_t *key1 = NULL, *key2 = NULL;
+ isc_result_t ret;
+ char current[PATH_MAX + 1];
+ char tmp[PATH_MAX + 1];
+ char *p;
+ int alg = DST_ALG_DH;
+ int type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY;
+ unsigned char array1[1024], array2[1024];
+ isc_buffer_t b1, b2;
+ isc_region_t r1, r2;
+
+ UNUSED(exp_result);
+
+ p = getcwd(current, PATH_MAX);;
+ if (p == NULL) {
+ t_info("getcwd failed %d\n", errno);
+ ++*nprobs;
+ return;
+ }
+
+ ret = dst_key_fromfile(name1, id1, alg, type, current, mctx, &key1);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("dst_key_fromfile(%d) returned: %s\n",
+ alg, dst_result_totext(ret));
+ ++*nfails;
+ return;
+ }
+
+ ret = dst_key_fromfile(name2, id2, alg, type, current, mctx, &key2);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("dst_key_fromfile(%d) returned: %s\n",
+ alg, dst_result_totext(ret));
+ ++*nfails;
+ return;
+ }
+
+ ret = isc_file_mktemplate("/tmp/", tmp, sizeof(tmp));
+ if (ret != ISC_R_SUCCESS) {
+ t_info("isc_file_mktemplate failed %s\n",
+ isc_result_totext(ret));
+ ++*nprobs;
+ return;
+ }
+
+ ret = isc_dir_createunique(tmp);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("isc_dir_createunique failed %s\n",
+ isc_result_totext(ret));
+ ++*nprobs;
+ return;
+ }
+
+ ret = dst_key_tofile(key1, type, tmp);
+ if (ret != 0) {
+ t_info("dst_key_tofile(%d) returned: %s\n",
+ alg, dst_result_totext(ret));
+ ++*nfails;
+ return;
+ }
+
+ ret = dst_key_tofile(key2, type, tmp);
+ if (ret != 0) {
+ t_info("dst_key_tofile(%d) returned: %s\n",
+ alg, dst_result_totext(ret));
+ ++*nfails;
+ return;
+ }
+
+ cleandir(tmp);
+
+ isc_buffer_init(&b1, array1, sizeof(array1));
+ ret = dst_key_computesecret(key1, key2, &b1);
+ if (ret != 0) {
+ t_info("dst_computesecret() returned: %s\n",
+ dst_result_totext(ret));
+ ++*nfails;
+ return;
+ }
+
+ isc_buffer_init(&b2, array2, sizeof(array2));
+ ret = dst_key_computesecret(key2, key1, &b2);
+ if (ret != 0) {
+ t_info("dst_computesecret() returned: %s\n",
+ dst_result_totext(ret));
+ ++*nfails;
+ return;
+ }
+
+ isc_buffer_usedregion(&b1, &r1);
+ isc_buffer_usedregion(&b2, &r2);
+ if (r1.length != r2.length || memcmp(r1.base, r2.base, r1.length) != 0)
+ {
+ t_info("computed secrets don't match\n");
+ ++*nfails;
+ return;
+ }
+
+ dst_key_free(&key1);
+ dst_key_free(&key2);
+}
+
+static void
+io(dns_name_t *name, int id, int alg, int type, isc_mem_t *mctx,
+ isc_result_t exp_result, int *nfails, int *nprobs)
+{
+ dst_key_t *key = NULL;
+ isc_result_t ret;
+ char current[PATH_MAX + 1];
+ char tmp[PATH_MAX + 1];
+ char *p;
+
+ p = getcwd(current, PATH_MAX);;
+ if (p == NULL) {
+ t_info("getcwd failed %d\n", errno);
+ ++*nprobs;
+ return;
+ }
+
+ ret = dst_key_fromfile(name, id, alg, type, current, mctx, &key);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("dst_key_fromfile(%d) returned: %s\n",
+ alg, dst_result_totext(ret));
+ ++*nfails;
+ return;
+ }
+
+ ret = isc_file_mktemplate("/tmp/", tmp, sizeof(tmp));
+ if (ret != ISC_R_SUCCESS) {
+ t_info("isc_file_mktemplate failed %s\n",
+ isc_result_totext(ret));
+ ++*nprobs;
+ return;
+ }
+
+ ret = isc_dir_createunique(tmp);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("mkdir failed %d\n", errno);
+ ++*nprobs;
+ return;
+ }
+
+ ret = dst_key_tofile(key, type, tmp);
+ if (ret != 0) {
+ t_info("dst_key_tofile(%d) returned: %s\n",
+ alg, dst_result_totext(ret));
+ ++*nfails;
+ return;
+ }
+
+ if (dst_key_alg(key) != DST_ALG_DH)
+ use(key, mctx, exp_result, nfails);
+
+ cleandir(tmp);
+
+ dst_key_free(&key);
+}
+
+static void
+generate(int alg, isc_mem_t *mctx, int size, int *nfails) {
+ isc_result_t ret;
+ dst_key_t *key = NULL;
+
+ ret = dst_key_generate(dns_rootname, alg, size, 0, 0, 0,
+ dns_rdataclass_in, mctx, &key);
+ if (ret != ISC_R_SUCCESS) {
+ t_info("dst_key_generate(%d) returned: %s\n", alg,
+ dst_result_totext(ret));
+ ++*nfails;
+ return;
+ }
+
+ if (alg != DST_ALG_DH)
+ use(key, mctx, ISC_R_SUCCESS, nfails);
+ dst_key_free(&key);
+}
+
+#define DBUFSIZ 25
+
+static const char *a1 =
+ "the dst module provides the capability to "
+ "generate, store and retrieve public and private keys, "
+ "sign and verify data using the RSA, DSA and MD5 algorithms, "
+ "and compute Diffie-Hellman shared secrets.";
+static void
+t1(void) {
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ int nfails;
+ int nprobs;
+ int result;
+ isc_result_t isc_result;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_buffer_t b;
+
+ t_assert("dst", 1, T_REQUIRED, a1);
+
+ nfails = 0;
+ nprobs = 0;
+ mctx = NULL;
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ t_result(T_UNRESOLVED);
+ return;
+ }
+ ectx = NULL;
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ t_result(T_UNRESOLVED);
+ return;
+ }
+ isc_result = isc_entropy_createfilesource(ectx, "randomfile");
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ t_result(T_UNRESOLVED);
+ return;
+ }
+ isc_result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dst_lib_init failed %s\n",
+ isc_result_totext(isc_result));
+ t_result(T_UNRESOLVED);
+ return;
+ }
+
+ if (!dst_algorithm_supported(DST_ALG_RSAMD5)) {
+ dst_lib_destroy();
+ t_info("library built without crypto support\n");
+ t_result(T_UNTESTED);
+ return;
+ }
+
+ t_info("testing use of stored keys [1]\n");
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ isc_buffer_init(&b, "test.", 5);
+ isc_buffer_add(&b, 5);
+ isc_result = dns_name_fromtext(name, &b, NULL, ISC_FALSE, NULL);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ isc_result_totext(isc_result));
+ t_result(T_UNRESOLVED);
+ return;
+ }
+ io(name, 23616, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC,
+ mctx, ISC_R_SUCCESS, &nfails, &nprobs);
+ t_info("testing use of stored keys [2]\n");
+ io(name, 54622, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC,
+ mctx, ISC_R_SUCCESS, &nfails, &nprobs);
+
+ t_info("testing use of stored keys [3]\n");
+ io(name, 49667, DST_ALG_DSA, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC,
+ mctx, DST_R_NULLKEY, &nfails, &nprobs);
+ t_info("testing use of stored keys [4]\n");
+ io(name, 2, DST_ALG_RSAMD5, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC,
+ mctx, DST_R_NULLKEY, &nfails, &nprobs);
+
+ isc_buffer_init(&b, "dh.", 3);
+ isc_buffer_add(&b, 3);
+ isc_result = dns_name_fromtext(name, &b, NULL, ISC_FALSE, NULL);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ isc_result_totext(isc_result));
+ t_result(T_UNRESOLVED);
+ return;
+ }
+
+ dh(name, 18602, name, 48957, mctx, ISC_R_SUCCESS, &nfails, &nprobs);
+
+ t_info("testing use of generated keys\n");
+ generate(DST_ALG_RSAMD5, mctx, 512, &nfails);
+ generate(DST_ALG_DSA, mctx, 512, &nfails);
+ generate(DST_ALG_DH, mctx, 512, &nfails);
+ /*
+ * This one uses a constant.
+ */
+ generate(DST_ALG_DH, mctx, 768, &nfails);
+ generate(DST_ALG_HMACMD5, mctx, 512, &nfails);
+
+ dst_lib_destroy();
+
+ isc_entropy_detach(&ectx);
+
+ isc_mem_destroy(&mctx);
+
+ result = T_UNRESOLVED;
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+ t_result(result);
+
+}
+
+#define T_SIGMAX 512
+
+#undef NEWSIG /* Define NEWSIG to generate the original signature file. */
+
+#ifdef NEWSIG
+
+/*
+ * Write a sig in buf to file at path.
+ */
+static int
+sig_tofile(char *path, isc_buffer_t *buf) {
+ int rval;
+ int fd;
+ int len;
+ int nprobs;
+ int cnt;
+ unsigned char c;
+ unsigned char val;
+
+ cnt = 0;
+ nprobs = 0;
+ len = buf->used - buf->current;
+
+ t_info("buf: current %d used %d len %d\n",
+ buf->current, buf->used, len);
+
+ fd = open(path, O_CREAT|O_TRUNC|O_WRONLY, S_IRWXU|S_IRWXO|S_IRWXG);
+ if (fd < 0) {
+ t_info("open %s failed %d\n", path, errno);
+ return(1);
+ }
+
+ while (len) {
+ c = (unsigned char) isc_buffer_getuint8(buf);
+ val = ((c >> 4 ) & 0x0f);
+ if ((0 <= val) && (val <= 9))
+ val = '0' + val;
+ else
+ val = 'A' + val - 10;
+ rval = write(fd, &val, 1);
+ if (rval != 1) {
+ ++nprobs;
+ t_info("write failed %d %d\n", rval, errno);
+ break;
+ }
+ val = (c & 0x0f);
+ if ((0 <= val) && (val <= 9))
+ val = '0' + val;
+ else
+ val = 'A' + val - 10;
+ rval = write(fd, &val, 1);
+ if (rval != 1) {
+ ++nprobs;
+ t_info("write failed %d %d\n", rval, errno);
+ break;
+ }
+ --len;
+ ++cnt;
+ if ((cnt % 16) == 0) {
+ val = '\n';
+ rval = write(fd, &val, 1);
+ if (rval != 1) {
+ ++nprobs;
+ t_info("write failed %d %d\n", rval, errno);
+ break;
+ }
+ }
+ }
+ val = '\n';
+ rval = write(fd, &val, 1);
+ if (rval != 1) {
+ ++nprobs;
+ t_info("write failed %d %d\n", rval, errno);
+ }
+ (void) close(fd);
+ return(nprobs);
+}
+
+#endif /* NEWSIG */
+
+/*
+ * Read sig in file at path to buf.
+ */
+static int
+sig_fromfile(char *path, isc_buffer_t *iscbuf) {
+ int rval;
+ int len;
+ int fd;
+ unsigned char val;
+ struct stat sb;
+ char *p;
+ char *buf;
+
+ rval = stat(path, &sb);
+ if (rval != 0) {
+ t_info("stat %s failed, errno == %d\n", path, errno);
+ return(1);
+ }
+
+ buf = (char *) malloc((sb.st_size + 1) * sizeof(unsigned char));
+ if (buf == NULL) {
+ t_info("malloc failed, errno == %d\n", errno);
+ return(1);
+ }
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ t_info("open failed, errno == %d\n", errno);
+ (void) free(buf);
+ return(1);
+ }
+
+ len = sb.st_size;
+ p = buf;
+ while (len) {
+ rval = read(fd, p, len);
+ if (rval > 0) {
+ len -= rval;
+ p += rval;
+ }
+ else {
+ t_info("read failed %d, errno == %d\n", rval, errno);
+ (void) free(buf);
+ (void) close(fd);
+ return(1);
+ }
+ }
+ close(fd);
+
+ p = buf;
+ len = sb.st_size;
+ while(len) {
+ if (*p == '\n') {
+ ++p;
+ --len;
+ continue;
+ }
+ if (('0' <= *p) && (*p <= '9'))
+ val = *p - '0';
+ else
+ val = *p - 'A' + 10;
+ ++p;
+ val <<= 4;
+ --len;
+ if (('0' <= *p) && (*p <= '9'))
+ val |= (*p - '0');
+ else
+ val |= (*p - 'A' + 10);
+ ++p;
+ --len;
+ isc_buffer_putuint8(iscbuf, val);
+ }
+ (void) free(buf);
+ return(0);
+}
+
+static void
+t2_sigchk(char *datapath, char *sigpath, char *keyname,
+ int id, int alg, int type,
+ isc_mem_t *mctx, char *expected_result,
+ int *nfails, int *nprobs)
+{
+ int rval;
+ int len;
+ int fd;
+ int exp_res;
+ dst_key_t *key = NULL;
+ unsigned char sig[T_SIGMAX];
+ unsigned char *p;
+ unsigned char *data;
+ struct stat sb;
+ isc_result_t isc_result;
+ isc_buffer_t databuf;
+ isc_buffer_t sigbuf;
+ isc_region_t datareg;
+ isc_region_t sigreg;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_buffer_t b;
+ dst_context_t *ctx = NULL;
+
+ /*
+ * Read data from file in a form usable by dst_verify.
+ */
+ rval = stat(datapath, &sb);
+ if (rval != 0) {
+ t_info("t2_sigchk: stat (%s) failed %d\n", datapath, errno);
+ ++*nprobs;
+ return;
+ }
+
+ data = (unsigned char *) malloc(sb.st_size * sizeof(char));
+ if (data == NULL) {
+ t_info("t2_sigchk: malloc failed %d\n", errno);
+ ++*nprobs;
+ return;
+ }
+
+ fd = open(datapath, O_RDONLY);
+ if (fd < 0) {
+ t_info("t2_sigchk: open failed %d\n", errno);
+ (void) free(data);
+ ++*nprobs;
+ return;
+ }
+
+ p = data;
+ len = sb.st_size;
+ do {
+ rval = read(fd, p, len);
+ if (rval > 0) {
+ len -= rval;
+ p += rval;
+ }
+ } while (len);
+ (void) close(fd);
+
+ /*
+ * Read key from file in a form usable by dst_verify.
+ */
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ isc_buffer_init(&b, keyname, strlen(keyname));
+ isc_buffer_add(&b, strlen(keyname));
+ isc_result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ isc_result_totext(isc_result));
+ (void) free(data);
+ ++*nprobs;
+ return;
+ }
+ isc_result = dst_key_fromfile(name, id, alg, type, NULL, mctx, &key);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dst_key_fromfile failed %s\n",
+ isc_result_totext(isc_result));
+ (void) free(data);
+ ++*nprobs;
+ return;
+ }
+
+ isc_buffer_init(&databuf, data, sb.st_size);
+ isc_buffer_add(&databuf, sb.st_size);
+ isc_buffer_usedregion(&databuf, &datareg);
+
+#ifdef NEWSIG
+
+ /*
+ * If we're generating a signature for the first time,
+ * sign the data and save the signature to a file
+ */
+
+ memset(sig, 0, sizeof(sig));
+ isc_buffer_init(&sigbuf, sig, sizeof(sig));
+
+ isc_result = dst_context_create(key, mctx, &ctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dst_context_create(%d) failed %s\n",
+ dst_result_totext(isc_result));
+ (void) free(data);
+ dst_key_free(&key);
+ ++*nprobs;
+ return;
+ }
+ isc_result = dst_context_adddata(ctx, &datareg);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dst_context_adddata(%d) failed %s\n",
+ dst_result_totext(isc_result));
+ (void) free(data);
+ dst_key_free(&key);
+ dst_context_destroy(&ctx);
+ ++*nprobs;
+ return;
+ }
+ isc_result = dst_context_sign(ctx, &sigbuf);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dst_sign(%d) failed %s\n",
+ dst_result_totext(isc_result));
+ (void) free(data);
+ dst_key_free(&key);
+ dst_context_destroy(&ctx);
+ ++*nprobs;
+ return;
+ }
+ dst_context_destroy(&ctx);
+
+ rval = sig_tofile(sigpath, &sigbuf);
+ if (rval != 0) {
+ t_info("sig_tofile failed\n");
+ ++*nprobs;
+ (void) free(data);
+ dst_key_free(&key);
+ return;
+ }
+
+#endif /* NEWSIG */
+
+ memset(sig, 0, sizeof(sig));
+ isc_buffer_init(&sigbuf, sig, sizeof(sig));
+
+ /*
+ * Read precomputed signature from file in a form usable by dst_verify.
+ */
+ rval = sig_fromfile(sigpath, &sigbuf);
+ if (rval != 0) {
+ t_info("sig_fromfile failed\n");
+ (void) free(data);
+ dst_key_free(&key);
+ ++*nprobs;
+ return;
+ }
+
+ /*
+ * Verify that the key signed the data.
+ */
+ isc_buffer_remainingregion(&sigbuf, &sigreg);
+
+ exp_res = 0;
+ if (strstr(expected_result, "!"))
+ exp_res = 1;
+
+ isc_result = dst_context_create(key, mctx, &ctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dst_context_create returned %s\n",
+ isc_result_totext(isc_result));
+ ++*nfails;
+ }
+ isc_result = dst_context_adddata(ctx, &datareg);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dst_context_adddata returned %s\n",
+ isc_result_totext(isc_result));
+ dst_context_destroy(&ctx);
+ ++*nfails;
+ }
+ isc_result = dst_context_verify(ctx, &sigreg);
+ if ( ((exp_res == 0) && (isc_result != ISC_R_SUCCESS)) ||
+ ((exp_res != 0) && (isc_result == ISC_R_SUCCESS))) {
+
+ t_info("dst_context_verify returned %s, expected %s\n",
+ isc_result_totext(isc_result),
+ expected_result);
+ dst_context_destroy(&ctx);
+ ++*nfails;
+ }
+
+ (void) free(data);
+ dst_context_destroy(&ctx);
+ dst_key_free(&key);
+ return;
+}
+
+/*
+ * The astute observer will note that t1() signs then verifies data
+ * during the test but that t2() verifies data that has been
+ * signed at some earlier time, possibly with an entire different
+ * version or implementation of the DSA and RSA algorithms
+ */
+static const char *a2 =
+ "the dst module provides the capability to "
+ "verify data signed with the RSA and DSA algorithms";
+
+/*
+ * av == datafile, sigpath, keyname, keyid, alg, exp_result.
+ */
+static int
+t2_vfy(char **av) {
+ char *datapath;
+ char *sigpath;
+ char *keyname;
+ char *key;
+ int keyid;
+ char *alg;
+ int algid;
+ char *exp_result;
+ int nfails;
+ int nprobs;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ isc_result_t isc_result;
+ int result;
+
+ datapath = *av++;
+ sigpath = *av++;
+ keyname = *av++;
+ key = *av++;
+ keyid = atoi(key);
+ alg = *av++;
+ exp_result = *av++;
+ nfails = 0;
+ nprobs = 0;
+
+ if (! strcasecmp(alg, "DST_ALG_DSA"))
+ algid = DST_ALG_DSA;
+ else if (! strcasecmp(alg, "DST_ALG_RSAMD5"))
+ algid = DST_ALG_RSAMD5;
+ else {
+ t_info("Unknown algorithm %s\n", alg);
+ return(T_UNRESOLVED);
+ }
+
+ mctx = NULL;
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+ ectx = NULL;
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+ isc_result = isc_entropy_createfilesource(ectx, "randomfile");
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+ isc_result = dst_lib_init(mctx, ectx, ISC_ENTROPY_BLOCKING);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("dst_lib_init failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ if (!dst_algorithm_supported(DST_ALG_RSAMD5)) {
+ dst_lib_destroy();
+ t_info("library built without crypto support\n");
+ return (T_UNTESTED);
+ }
+
+ t_info("testing %s, %s, %s, %s, %s, %s\n",
+ datapath, sigpath, keyname, key, alg, exp_result);
+ t2_sigchk(datapath, sigpath, keyname, keyid,
+ algid, DST_TYPE_PRIVATE|DST_TYPE_PUBLIC,
+ mctx, exp_result,
+ &nfails, &nprobs);
+
+ dst_lib_destroy();
+
+ isc_entropy_detach(&ectx);
+
+ isc_mem_destroy(&mctx);
+
+ result = T_UNRESOLVED;
+ if (nfails)
+ result = T_FAIL;
+ else if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+
+ return(result);
+}
+
+static void
+t2(void) {
+ int result;
+ t_assert("dst", 2, T_REQUIRED, a2);
+ result = t_eval("dst_2_data", t2_vfy, 6);
+ t_result(result);
+}
+
+testspec_t T_testlist[] = {
+ { t1, "basic dst module verification" },
+ { t2, "signature ineffability" },
+ { NULL, NULL }
+};
+
diff --git a/bin/tests/entropy2_test.c b/bin/tests/entropy2_test.c
new file mode 100644
index 0000000..3561a4c
--- /dev/null
+++ b/bin/tests/entropy2_test.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: entropy2_test.c,v 1.16 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/entropy.h>
+#include <isc/keyboard.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+static void
+hex_dump(const char *msg, void *data, unsigned int length) {
+ unsigned int len;
+ unsigned char *base;
+ isc_boolean_t first = ISC_TRUE;
+
+ base = data;
+
+ printf("DUMP of %d bytes: %s\n\t", length, msg);
+ for (len = 0; len < length; len++) {
+ if (len % 16 == 0 && !first)
+ printf("\n\t");
+ printf("%02x ", base[len]);
+ first = ISC_FALSE;
+ }
+ printf("\n");
+}
+
+static void
+CHECK(const char *msg, isc_result_t result) {
+ if (result != ISC_R_SUCCESS) {
+ printf("FAILURE: %s: %s\n", msg, isc_result_totext(result));
+ exit(1);
+ }
+}
+
+static isc_result_t
+start(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
+ isc_keyboard_t *kbd = (isc_keyboard_t *)arg;
+
+ UNUSED(source);
+
+ if (blocking)
+ printf("start called, blocking mode.\n");
+ else
+ printf("start called, non-blocking mode.\n");
+
+ return (isc_keyboard_open(kbd));
+}
+
+static void
+stop(isc_entropysource_t *source, void *arg) {
+ isc_keyboard_t *kbd = (isc_keyboard_t *)arg;
+
+ UNUSED(source);
+
+ printf("ENOUGH! Stop typing, please.\r\n");
+
+ (void)isc_keyboard_close(kbd, 3);
+ printf("stop called\n");
+}
+
+static isc_result_t
+get(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
+ isc_keyboard_t *kbd = (isc_keyboard_t *)arg;
+ isc_result_t result;
+ isc_time_t t;
+ isc_uint32_t sample;
+ isc_uint32_t extra;
+ unsigned char c;
+
+ if (!blocking)
+ return (ISC_R_NOENTROPY);
+
+ result = isc_keyboard_getchar(kbd, &c);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ TIME_NOW(&t);
+
+ sample = isc_time_nanoseconds(&t);
+ extra = c;
+
+ result = isc_entropy_addcallbacksample(source, sample, extra);
+ if (result != ISC_R_SUCCESS) {
+ printf("\r\n");
+ return (result);
+ }
+
+ printf(".");
+ fflush(stdout);
+
+ return (result);
+}
+
+int
+main(int argc, char **argv) {
+ isc_mem_t *mctx;
+ unsigned char buffer[512];
+ isc_entropy_t *ent;
+ isc_entropysource_t *source;
+ unsigned int returned;
+ unsigned int flags;
+ isc_result_t result;
+ isc_keyboard_t kbd;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ mctx = NULL;
+ CHECK("isc_mem_create()",
+ isc_mem_create(0, 0, &mctx));
+
+ ent = NULL;
+ CHECK("isc_entropy_create()",
+ isc_entropy_create(mctx, &ent));
+
+ isc_entropy_stats(ent, stderr);
+
+ source = NULL;
+ result = isc_entropy_createcallbacksource(ent, start, get, stop, &kbd,
+ &source);
+ CHECK("isc_entropy_createcallbacksource()", result);
+
+ fprintf(stderr,
+ "Reading 32 bytes of GOOD random data only, partial OK\n");
+
+ flags = 0;
+ flags |= ISC_ENTROPY_GOODONLY;
+ flags |= ISC_ENTROPY_PARTIAL;
+ flags |= ISC_ENTROPY_BLOCKING;
+ returned = 0;
+ result = isc_entropy_getdata(ent, buffer, 32, &returned, flags);
+ if (result == ISC_R_NOENTROPY) {
+ fprintf(stderr, "No entropy.\r\n");
+ }
+
+ isc_entropy_stopcallbacksources(ent);
+
+ hex_dump("good data only:", buffer, returned);
+
+ isc_entropy_stats(ent, stderr);
+
+ isc_entropy_destroysource(&source);
+ isc_entropy_detach(&ent);
+
+ isc_mem_stats(mctx, stderr);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
+
diff --git a/bin/tests/entropy_test.c b/bin/tests/entropy_test.c
new file mode 100644
index 0000000..94b1804
--- /dev/null
+++ b/bin/tests/entropy_test.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: entropy_test.c,v 1.23 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+#include <isc/string.h>
+
+static void
+hex_dump(const char *msg, void *data, unsigned int length) {
+ unsigned int len;
+ unsigned char *base;
+ isc_boolean_t first = ISC_TRUE;
+
+ base = data;
+
+ printf("DUMP of %d bytes: %s\n\t", length, msg);
+ for (len = 0; len < length; len++) {
+ if (len % 16 == 0 && !first)
+ printf("\n\t");
+ printf("%02x ", base[len]);
+ first = ISC_FALSE;
+ }
+ printf("\n");
+}
+
+static void
+CHECK(const char *msg, isc_result_t result) {
+ if (result != ISC_R_SUCCESS) {
+ printf("FAILURE: %s: %s\n", msg, isc_result_totext(result));
+ exit(1);
+ }
+}
+
+int
+main(int argc, char **argv) {
+ isc_mem_t *mctx;
+ unsigned char buffer[512];
+ isc_entropy_t *ent;
+ unsigned int returned;
+ unsigned int flags;
+ isc_result_t result;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ mctx = NULL;
+ CHECK("isc_mem_create()",
+ isc_mem_create(0, 0, &mctx));
+
+ ent = NULL;
+ CHECK("isc_entropy_create()",
+ isc_entropy_create(mctx, &ent));
+
+ isc_entropy_stats(ent, stderr);
+
+#if 1
+ CHECK("isc_entropy_createfilesource() 1",
+ isc_entropy_createfilesource(ent, "/dev/random"));
+ CHECK("isc_entropy_createfilesource() 2",
+ isc_entropy_createfilesource(ent, "/dev/random"));
+#else
+ CHECK("isc_entropy_createfilesource() 3",
+ isc_entropy_createfilesource(ent, "/tmp/foo"));
+#endif
+
+ fprintf(stderr,
+ "Reading 32 bytes of GOOD random data only, partial OK\n");
+
+ flags = 0;
+ flags |= ISC_ENTROPY_GOODONLY;
+ flags |= ISC_ENTROPY_PARTIAL;
+ result = isc_entropy_getdata(ent, buffer, 32, &returned, flags);
+ if (result == ISC_R_NOENTROPY) {
+ fprintf(stderr, "No entropy.\n");
+ goto any;
+ }
+ hex_dump("good data only:", buffer, returned);
+
+ any:
+ isc_entropy_stats(ent, stderr);
+ CHECK("isc_entropy_getdata() pseudorandom",
+ isc_entropy_getdata(ent, buffer, 128, NULL, 0));
+ hex_dump("pseudorandom data", buffer, 128);
+
+ isc_entropy_stats(ent, stderr);
+ flags = 0;
+ flags |= ISC_ENTROPY_GOODONLY;
+ flags |= ISC_ENTROPY_BLOCKING;
+ result = isc_entropy_getdata(ent, buffer, sizeof(buffer), &returned,
+ flags);
+ CHECK("good data only, blocking mode", result);
+ hex_dump("blocking mode data", buffer, sizeof(buffer));
+
+ {
+ isc_entropy_t *entcopy1 = NULL;
+ isc_entropy_t *entcopy2 = NULL;
+ isc_entropy_t *entcopy3 = NULL;
+
+ isc_entropy_attach(ent, &entcopy1);
+ isc_entropy_attach(ent, &entcopy2);
+ isc_entropy_attach(ent, &entcopy3);
+
+ isc_entropy_stats(ent, stderr);
+
+ isc_entropy_detach(&entcopy1);
+ isc_entropy_detach(&entcopy2);
+ isc_entropy_detach(&entcopy3);
+ }
+
+ isc_entropy_detach(&ent);
+ isc_mem_stats(mctx, stderr);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
+
diff --git a/bin/tests/fsaccess_test.c b/bin/tests/fsaccess_test.c
new file mode 100644
index 0000000..e6147b2
--- /dev/null
+++ b/bin/tests/fsaccess_test.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: fsaccess_test.c,v 1.13 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <sys/types.h> /* Non-portable. */
+#include <sys/stat.h> /* Non-portable. */
+
+#include <isc/fsaccess.h>
+#include <isc/result.h>
+
+#define PATH "/tmp/fsaccess"
+
+int
+main(void) {
+ isc_fsaccess_t access;
+ isc_result_t result;
+
+ remove(PATH);
+ fopen(PATH, "w");
+ chmod(PATH, 0);
+
+ access = 0;
+
+ isc_fsaccess_add(ISC_FSACCESS_OWNER | ISC_FSACCESS_GROUP,
+ ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
+ &access);
+
+ printf("fsaccess=%d\n", access);
+
+ isc_fsaccess_add(ISC_FSACCESS_OTHER, ISC_FSACCESS_READ, &access);
+
+ printf("fsaccess=%d\n", access);
+
+ result = isc_fsaccess_set(PATH, access);
+ if (result != ISC_R_SUCCESS)
+ fprintf(stderr, "result = %s\n", isc_result_totext(result));
+
+ return (0);
+}
diff --git a/bin/tests/genrandom.c b/bin/tests/genrandom.c
new file mode 100644
index 0000000..34f6ac0
--- /dev/null
+++ b/bin/tests/genrandom.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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.15 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+#include <time.h>
+
+#include <isc/stdlib.h>
+
+int
+main(int argc, char **argv) {
+ unsigned int bytes;
+ unsigned int k;
+ char *endp;
+ FILE *fp;
+
+ if (argc != 3) {
+ printf("usage: genrandom k file\n");
+ exit(1);
+ }
+ k = strtoul(argv[1], &endp, 10);
+ if (*endp != 0) {
+ printf("usage: genrandom k file\n");
+ exit(1);
+ }
+ bytes = k << 10;
+
+ fp = fopen(argv[2], "w");
+ if (fp == NULL) {
+ printf("failed to open %s\n", argv[2]);
+ exit(1);
+ }
+
+#ifndef HAVE_ARC4RANDOM
+ srand(0x12345678);
+#endif
+ 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 file\n");
+ exit(1);
+ }
+ c = x >> 8;
+ if (putc(c, fp) == EOF) {
+ printf("error writing to file\n");
+ exit(1);
+ }
+ bytes -= 2;
+ }
+ fclose(fp);
+
+ return (0);
+}
diff --git a/bin/tests/gxba_test.c b/bin/tests/gxba_test.c
new file mode 100644
index 0000000..8c5558f
--- /dev/null
+++ b/bin/tests/gxba_test.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: gxba_test.c,v 1.13 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/net.h>
+
+#include <lwres/netdb.h>
+
+static void
+print_he(struct hostent *he, int error, const char *fun, const char *name) {
+ char **c;
+ int i;
+
+ if (he != NULL) {
+ printf("%s(%s):\n", fun, name);
+ printf("\tname = %s\n", he->h_name);
+ printf("\taddrtype = %d\n", he->h_addrtype);
+ printf("\tlength = %d\n", he->h_length);
+ c = he->h_aliases;
+ i = 1;
+ while (*c != NULL) {
+ printf("\talias[%d] = %s\n", i, *c);
+ i++;
+ c++;
+ }
+ c = he->h_addr_list;
+ i = 1;
+ while (*c != NULL) {
+ char buf[128];
+ inet_ntop(he->h_addrtype, *c, buf, sizeof(buf));
+ printf("\taddress[%d] = %s\n", i, buf);
+ c++;
+ i++;
+ }
+ } else {
+ printf("%s(%s): error = %d (%s)\n", fun, name, error,
+ hstrerror(error));
+ }
+}
+
+int
+main(int argc, char **argv) {
+ struct hostent *he;
+ int error;
+ struct in_addr in_addr;
+ struct in6_addr in6_addr;
+ void *addr;
+ int af;
+ size_t len;
+
+ (void)argc;
+
+ while (argv[1] != NULL) {
+ if (inet_pton(AF_INET, argv[1], &in_addr) == 1) {
+ af = AF_INET;
+ addr = &in_addr;
+ len = sizeof(in_addr);
+ } else if (inet_pton(AF_INET6, argv[1], &in6_addr) == 1) {
+ af = AF_INET6;
+ addr = &in6_addr;
+ len = sizeof(in6_addr);
+ } else {
+ printf("unable to convert \"%s\" to an address\n",
+ argv[1]);
+ argv++;
+ continue;
+ }
+ he = gethostbyaddr(addr, len, af);
+ print_he(he, h_errno, "gethostbyaddr", argv[1]);
+
+ he = getipnodebyaddr(addr, len, af, &error);
+ print_he(he, error, "getipnodebyaddr", argv[1]);
+ if (he != NULL)
+ freehostent(he);
+ argv++;
+ }
+ return (0);
+}
diff --git a/bin/tests/gxbn_test.c b/bin/tests/gxbn_test.c
new file mode 100644
index 0000000..28ca115
--- /dev/null
+++ b/bin/tests/gxbn_test.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: gxbn_test.c,v 1.16 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/net.h>
+
+#include <lwres/netdb.h>
+
+static void
+print_he(struct hostent *he, int error, const char *fun, const char *name) {
+ char **c;
+ int i;
+
+ if (he != NULL) {
+ printf("%s(%s):\n", fun, name);
+ printf("\tname = %s\n", he->h_name);
+ printf("\taddrtype = %d\n", he->h_addrtype);
+ printf("\tlength = %d\n", he->h_length);
+ c = he->h_aliases;
+ i = 1;
+ while (*c != NULL) {
+ printf("\talias[%d] = %s\n", i, *c);
+ i++;
+ c++;
+ }
+ c = he->h_addr_list;
+ i = 1;
+ while (*c != NULL) {
+ char buf[128];
+ inet_ntop(he->h_addrtype, *c, buf, sizeof(buf));
+ printf("\taddress[%d] = %s\n", i, buf);
+ c++;
+ i++;
+ }
+ } else {
+ printf("%s(%s): error = %d (%s)\n", fun, name, error,
+ hstrerror(error));
+ }
+}
+
+int
+main(int argc, char **argv) {
+ struct hostent *he;
+ int error;
+
+ (void)argc;
+
+ while (argv[1] != NULL) {
+ he = gethostbyname(argv[1]);
+ print_he(he, h_errno, "gethostbyname", argv[1]);
+
+ he = getipnodebyname(argv[1], AF_INET6, AI_DEFAULT|AI_ALL,
+ &error);
+ print_he(he, error, "getipnodebyname", argv[1]);
+ if (he != NULL)
+ freehostent(he);
+
+ he = getipnodebyname(argv[1], AF_INET6, AI_DEFAULT,
+ &error);
+ print_he(he, error, "getipnodebyname", argv[1]);
+ if (he != NULL)
+ freehostent(he);
+ argv++;
+ }
+ return (0);
+}
diff --git a/bin/tests/hash_test.c b/bin/tests/hash_test.c
new file mode 100644
index 0000000..73d397b
--- /dev/null
+++ b/bin/tests/hash_test.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2004-2007 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: hash_test.c,v 1.19 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/hmacmd5.h>
+#include <isc/hmacsha.h>
+#include <isc/md5.h>
+#include <isc/sha1.h>
+#include <isc/util.h>
+#include <isc/string.h>
+
+static void
+print_digest(const char *s, const char *hash, unsigned char *d,
+ unsigned int words)
+{
+ unsigned int i, j;
+
+ printf("hash (%s) %s:\n\t", hash, s);
+ for (i = 0; i < words; i++) {
+ printf(" ");
+ for (j = 0; j < 4; j++)
+ printf("%02x", d[i * 4 + j]);
+ }
+ printf("\n");
+}
+
+int
+main(int argc, char **argv) {
+ isc_sha1_t sha1;
+ isc_sha224_t sha224;
+ isc_md5_t md5;
+ isc_hmacmd5_t hmacmd5;
+ isc_hmacsha1_t hmacsha1;
+ isc_hmacsha224_t hmacsha224;
+ isc_hmacsha256_t hmacsha256;
+ isc_hmacsha384_t hmacsha384;
+ isc_hmacsha512_t hmacsha512;
+ unsigned char digest[ISC_SHA512_DIGESTLENGTH];
+ unsigned char buffer[1024];
+ const char *s;
+ unsigned char key[20];
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ s = "abc";
+ isc_sha1_init(&sha1);
+ memcpy(buffer, s, strlen(s));
+ isc_sha1_update(&sha1, buffer, strlen(s));
+ isc_sha1_final(&sha1, digest);
+ print_digest(s, "sha1", digest, ISC_SHA1_DIGESTLENGTH/4);
+
+ s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+ isc_sha1_init(&sha1);
+ memcpy(buffer, s, strlen(s));
+ isc_sha1_update(&sha1, buffer, strlen(s));
+ isc_sha1_final(&sha1, digest);
+ print_digest(s, "sha1", digest, ISC_SHA1_DIGESTLENGTH/4);
+
+ s = "abc";
+ isc_sha224_init(&sha224);
+ memcpy(buffer, s, strlen(s));
+ isc_sha224_update(&sha224, buffer, strlen(s));
+ isc_sha224_final(digest, &sha224);
+ print_digest(s, "sha224", digest, ISC_SHA224_DIGESTLENGTH/4);
+
+ s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+ isc_sha224_init(&sha224);
+ memcpy(buffer, s, strlen(s));
+ isc_sha224_update(&sha224, buffer, strlen(s));
+ isc_sha224_final(digest, &sha224);
+ print_digest(s, "sha224", digest, ISC_SHA224_DIGESTLENGTH/4);
+
+ s = "abc";
+ isc_md5_init(&md5);
+ memcpy(buffer, s, strlen(s));
+ isc_md5_update(&md5, buffer, strlen(s));
+ isc_md5_final(&md5, digest);
+ print_digest(s, "md5", digest, 4);
+
+ /*
+ * The 3 HMAC-MD5 examples from RFC2104
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 16);
+ isc_hmacmd5_init(&hmacmd5, key, 16);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacmd5_update(&hmacmd5, buffer, strlen(s));
+ isc_hmacmd5_sign(&hmacmd5, digest);
+ print_digest(s, "hmacmd5", digest, 4);
+
+ s = "what do ya want for nothing?";
+ strcpy((char *)key, "Jefe");
+ isc_hmacmd5_init(&hmacmd5, key, 4);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacmd5_update(&hmacmd5, buffer, strlen(s));
+ isc_hmacmd5_sign(&hmacmd5, digest);
+ print_digest(s, "hmacmd5", digest, 4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 16);
+ isc_hmacmd5_init(&hmacmd5, key, 16);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacmd5_update(&hmacmd5, buffer, strlen(s));
+ isc_hmacmd5_sign(&hmacmd5, digest);
+ print_digest(s, "hmacmd5", digest, 4);
+
+ /*
+ * The 3 HMAC-SHA1 examples from RFC4634.
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 20);
+ isc_hmacsha1_init(&hmacsha1, key, 20);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha1_update(&hmacsha1, buffer, strlen(s));
+ isc_hmacsha1_sign(&hmacsha1, digest, ISC_SHA1_DIGESTLENGTH);
+ print_digest(s, "hmacsha1", digest, ISC_SHA1_DIGESTLENGTH/4);
+
+ s = "what do ya want for nothing?";
+ strcpy((char *)key, "Jefe");
+ isc_hmacsha1_init(&hmacsha1, key, 4);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha1_update(&hmacsha1, buffer, strlen(s));
+ isc_hmacsha1_sign(&hmacsha1, digest, ISC_SHA1_DIGESTLENGTH);
+ print_digest(s, "hmacsha1", digest, ISC_SHA1_DIGESTLENGTH/4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 20);
+ isc_hmacsha1_init(&hmacsha1, key, 20);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha1_update(&hmacsha1, buffer, strlen(s));
+ isc_hmacsha1_sign(&hmacsha1, digest, ISC_SHA1_DIGESTLENGTH);
+ print_digest(s, "hmacsha1", digest, ISC_SHA1_DIGESTLENGTH/4);
+
+ /*
+ * The 3 HMAC-SHA224 examples from RFC4634.
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 20);
+ isc_hmacsha224_init(&hmacsha224, key, 20);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha224_update(&hmacsha224, buffer, strlen(s));
+ isc_hmacsha224_sign(&hmacsha224, digest, ISC_SHA224_DIGESTLENGTH);
+ print_digest(s, "hmacsha224", digest, ISC_SHA224_DIGESTLENGTH/4);
+
+ s = "what do ya want for nothing?";
+ strcpy((char *)key, "Jefe");
+ isc_hmacsha224_init(&hmacsha224, key, 4);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha224_update(&hmacsha224, buffer, strlen(s));
+ isc_hmacsha224_sign(&hmacsha224, digest, ISC_SHA224_DIGESTLENGTH);
+ print_digest(s, "hmacsha224", digest, ISC_SHA224_DIGESTLENGTH/4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 20);
+ isc_hmacsha224_init(&hmacsha224, key, 20);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha224_update(&hmacsha224, buffer, strlen(s));
+ isc_hmacsha224_sign(&hmacsha224, digest, ISC_SHA224_DIGESTLENGTH);
+ print_digest(s, "hmacsha224", digest, ISC_SHA224_DIGESTLENGTH/4);
+
+ /*
+ * The 3 HMAC-SHA256 examples from RFC4634.
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 20);
+ isc_hmacsha256_init(&hmacsha256, key, 20);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha256_update(&hmacsha256, buffer, strlen(s));
+ isc_hmacsha256_sign(&hmacsha256, digest, ISC_SHA256_DIGESTLENGTH);
+ print_digest(s, "hmacsha256", digest, ISC_SHA256_DIGESTLENGTH/4);
+
+ s = "what do ya want for nothing?";
+ strcpy((char *)key, "Jefe");
+ isc_hmacsha256_init(&hmacsha256, key, 4);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha256_update(&hmacsha256, buffer, strlen(s));
+ isc_hmacsha256_sign(&hmacsha256, digest, ISC_SHA256_DIGESTLENGTH);
+ print_digest(s, "hmacsha256", digest, ISC_SHA256_DIGESTLENGTH/4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 20);
+ isc_hmacsha256_init(&hmacsha256, key, 20);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha256_update(&hmacsha256, buffer, strlen(s));
+ isc_hmacsha256_sign(&hmacsha256, digest, ISC_SHA256_DIGESTLENGTH);
+ print_digest(s, "hmacsha256", digest, ISC_SHA256_DIGESTLENGTH/4);
+
+ /*
+ * The 3 HMAC-SHA384 examples from RFC4634.
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 20);
+ isc_hmacsha384_init(&hmacsha384, key, 20);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha384_update(&hmacsha384, buffer, strlen(s));
+ isc_hmacsha384_sign(&hmacsha384, digest, ISC_SHA384_DIGESTLENGTH);
+ print_digest(s, "hmacsha384", digest, ISC_SHA384_DIGESTLENGTH/4);
+
+ s = "what do ya want for nothing?";
+ strcpy((char *)key, "Jefe");
+ isc_hmacsha384_init(&hmacsha384, key, 4);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha384_update(&hmacsha384, buffer, strlen(s));
+ isc_hmacsha384_sign(&hmacsha384, digest, ISC_SHA384_DIGESTLENGTH);
+ print_digest(s, "hmacsha384", digest, ISC_SHA384_DIGESTLENGTH/4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 20);
+ isc_hmacsha384_init(&hmacsha384, key, 20);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha384_update(&hmacsha384, buffer, strlen(s));
+ isc_hmacsha384_sign(&hmacsha384, digest, ISC_SHA384_DIGESTLENGTH);
+ print_digest(s, "hmacsha384", digest, ISC_SHA384_DIGESTLENGTH/4);
+
+ /*
+ * The 3 HMAC-SHA512 examples from RFC4634.
+ */
+ s = "Hi There";
+ memset(key, 0x0b, 20);
+ isc_hmacsha512_init(&hmacsha512, key, 20);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha512_update(&hmacsha512, buffer, strlen(s));
+ isc_hmacsha512_sign(&hmacsha512, digest, ISC_SHA512_DIGESTLENGTH);
+ print_digest(s, "hmacsha512", digest, ISC_SHA512_DIGESTLENGTH/4);
+
+ s = "what do ya want for nothing?";
+ strcpy((char *)key, "Jefe");
+ isc_hmacsha512_init(&hmacsha512, key, 4);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha512_update(&hmacsha512, buffer, strlen(s));
+ isc_hmacsha512_sign(&hmacsha512, digest, ISC_SHA512_DIGESTLENGTH);
+ print_digest(s, "hmacsha512", digest, ISC_SHA512_DIGESTLENGTH/4);
+
+ s = "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335"
+ "\335\335\335\335\335\335\335\335\335\335";
+ memset(key, 0xaa, 20);
+ isc_hmacsha512_init(&hmacsha512, key, 20);
+ memcpy(buffer, s, strlen(s));
+ isc_hmacsha512_update(&hmacsha512, buffer, strlen(s));
+ isc_hmacsha512_sign(&hmacsha512, digest, ISC_SHA512_DIGESTLENGTH);
+ print_digest(s, "hmacsha512", digest, ISC_SHA512_DIGESTLENGTH/4);
+
+ return (0);
+}
diff --git a/bin/tests/headerdep_test.sh.in b/bin/tests/headerdep_test.sh.in
new file mode 100644
index 0000000..3f951de
--- /dev/null
+++ b/bin/tests/headerdep_test.sh.in
@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: headerdep_test.sh.in,v 1.8 2007/06/19 23:46:59 tbox Exp $
+
+#
+# Check the installed bind9 headers to make sure that no header
+# depends on another header having been included first.
+#
+
+prefix=@prefix@
+tmp=/tmp/thdr$$.tmp
+
+status=0
+
+echo "Checking for header interdependencies..."
+
+# Make a list of header files.
+(cd $prefix/include; find . -name '*.h' -print | sed 's!^./!!') > $tmp
+
+# Check each header.
+while read h
+do
+ echo " - <$h>"
+
+ # Build a test program.
+ cat <<EOF >test.c
+#include <$h>
+EOF
+
+ # Compile the test program.
+ if
+ gcc @STD_CWARNINGS@ @STD_CINCLUDES@ -I$prefix/include -c test.c 2>&1
+ then
+ :
+ else
+ status=1
+ fi
+done <$tmp
+
+rm -f test.c test.o $tmp
+
+exit $status
diff --git a/bin/tests/inter_test.c b/bin/tests/inter_test.c
new file mode 100644
index 0000000..141467c
--- /dev/null
+++ b/bin/tests/inter_test.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 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
+ * 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: inter_test.c,v 1.16 2008/03/20 23:47:00 tbox Exp $ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/interfaceiter.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+int
+main(int argc, char **argv) {
+ isc_mem_t *mctx = NULL;
+ isc_interfaceiter_t *iter = NULL;
+ isc_interface_t ifdata;
+ isc_result_t result;
+ const char * res;
+ char buf[128];
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ result = isc_interfaceiter_create(mctx, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_interfaceiter_first(iter);
+ while (result == ISC_R_SUCCESS) {
+ result = isc_interfaceiter_current(iter, &ifdata);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout, "isc_interfaceiter_current: %s",
+ isc_result_totext(result));
+ continue;
+ }
+ fprintf(stdout, "%s %d %x\n", ifdata.name, ifdata.af,
+ ifdata.flags);
+ INSIST(ifdata.af == AF_INET || ifdata.af == AF_INET6);
+ res = inet_ntop(ifdata.af, &ifdata.address.type, buf,
+ sizeof(buf));
+ if (ifdata.address.zone != 0)
+ fprintf(stdout, "address = %s (zone %u)\n",
+ res == NULL ? "BAD" : res,
+ ifdata.address.zone);
+ else
+ fprintf(stdout, "address = %s\n",
+ res == NULL ? "BAD" : res);
+ INSIST(ifdata.address.family == ifdata.af);
+ res = inet_ntop(ifdata.af, &ifdata.netmask.type, buf,
+ sizeof(buf));
+ fprintf(stdout, "netmask = %s\n", res == NULL ? "BAD" : res);
+ INSIST(ifdata.netmask.family == ifdata.af);
+ if ((ifdata.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+ res = inet_ntop(ifdata.af, &ifdata.dstaddress.type,
+ buf, sizeof(buf));
+ fprintf(stdout, "dstaddress = %s\n",
+ res == NULL ? "BAD" : res);
+
+ INSIST(ifdata.dstaddress.family == ifdata.af);
+ }
+ result = isc_interfaceiter_next(iter);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
+ fprintf(stdout, "isc_interfaceiter_next: %s",
+ isc_result_totext(result));
+ continue;
+ }
+ }
+ isc_interfaceiter_destroy(&iter);
+
+ fprintf(stdout, "\nPass 2\n\n");
+
+ result = isc_interfaceiter_create(mctx, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = isc_interfaceiter_first(iter);
+ while (result == ISC_R_SUCCESS) {
+ result = isc_interfaceiter_current(iter, &ifdata);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout, "isc_interfaceiter_current: %s",
+ isc_result_totext(result));
+ continue;
+ }
+ fprintf(stdout, "%s %d %x\n", ifdata.name, ifdata.af,
+ ifdata.flags);
+ INSIST(ifdata.af == AF_INET || ifdata.af == AF_INET6);
+ res = inet_ntop(ifdata.af, &ifdata.address.type, buf,
+ sizeof(buf));
+ if (ifdata.address.zone != 0)
+ fprintf(stdout, "address = %s (zone %u)\n",
+ res == NULL ? "BAD" : res,
+ ifdata.address.zone);
+ else
+ fprintf(stdout, "address = %s\n",
+ res == NULL ? "BAD" : res);
+ INSIST(ifdata.address.family == ifdata.af);
+ res = inet_ntop(ifdata.af, &ifdata.netmask.type, buf,
+ sizeof(buf));
+ fprintf(stdout, "netmask = %s\n", res == NULL ? "BAD" : res);
+ INSIST(ifdata.netmask.family == ifdata.af);
+ if ((ifdata.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+ res = inet_ntop(ifdata.af, &ifdata.dstaddress.type,
+ buf, sizeof(buf));
+ fprintf(stdout, "dstaddress = %s\n",
+ res == NULL ? "BAD" : res);
+
+ INSIST(ifdata.dstaddress.family == ifdata.af);
+ }
+ result = isc_interfaceiter_next(iter);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
+ fprintf(stdout, "isc_interfaceiter_next: %s",
+ isc_result_totext(result));
+ continue;
+ }
+ }
+ isc_interfaceiter_destroy(&iter);
+ cleanup:
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/journalprint.c b/bin/tests/journalprint.c
new file mode 100644
index 0000000..d8bd72b
--- /dev/null
+++ b/bin/tests/journalprint.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: journalprint.c,v 1.14 2008/09/25 04:02:38 tbox Exp $ */
+
+/*! \file */
+#include <config.h>
+
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/journal.h>
+#include <dns/log.h>
+#include <dns/result.h>
+#include <dns/types.h>
+
+#include <stdlib.h>
+
+/*
+ * 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/tests/keyboard_test.c b/bin/tests/keyboard_test.c
new file mode 100644
index 0000000..f278a2d
--- /dev/null
+++ b/bin/tests/keyboard_test.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: keyboard_test.c,v 1.13 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/keyboard.h>
+#include <isc/util.h>
+
+static void
+CHECK(const char *msg, isc_result_t result) {
+ if (result != ISC_R_SUCCESS) {
+ printf("FAILURE: %s: %s\n", msg, isc_result_totext(result));
+ exit(1);
+ }
+}
+
+int
+main(int argc, char **argv) {
+ isc_keyboard_t kbd;
+ unsigned char c;
+ isc_result_t res;
+ unsigned int count;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ printf("Type Q to exit.\n");
+
+ res = isc_keyboard_open(&kbd);
+ CHECK("isc_keyboard_open()", res);
+
+ c = 'x';
+ count = 0;
+ while (res == ISC_R_SUCCESS && c != 'Q') {
+ res = isc_keyboard_getchar(&kbd, &c);
+ printf(".");
+ fflush(stdout);
+ count++;
+ if (count % 64 == 0)
+ printf("\r\n");
+ }
+ printf("\r\n");
+ if (res != ISC_R_SUCCESS) {
+ printf("FAILURE: keyboard getchar failed: %s\r\n",
+ isc_result_totext(res));
+ goto errout;
+ }
+
+ errout:
+ res = isc_keyboard_close(&kbd, 3);
+ CHECK("isc_keyboard_close()", res);
+
+ return (0);
+}
+
diff --git a/bin/tests/lex_test.c b/bin/tests/lex_test.c
new file mode 100644
index 0000000..8eba536
--- /dev/null
+++ b/bin/tests/lex_test.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: lex_test.c,v 1.23 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+#include <config.h>
+
+#include <isc/commandline.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx;
+isc_lex_t *lex;
+
+isc_lexspecials_t specials;
+
+static void
+print_token(isc_token_t *tokenp, FILE *stream) {
+ switch (tokenp->type) {
+ case isc_tokentype_unknown:
+ fprintf(stream, "UNKNOWN");
+ break;
+ case isc_tokentype_string:
+ fprintf(stream, "STRING %.*s",
+ (int)tokenp->value.as_region.length,
+ tokenp->value.as_region.base);
+ break;
+ case isc_tokentype_number:
+ fprintf(stream, "NUMBER %lu", tokenp->value.as_ulong);
+ break;
+ case isc_tokentype_qstring:
+ fprintf(stream, "QSTRING \"%.*s\"",
+ (int)tokenp->value.as_region.length,
+ tokenp->value.as_region.base);
+ break;
+ case isc_tokentype_eol:
+ fprintf(stream, "EOL");
+ break;
+ case isc_tokentype_eof:
+ fprintf(stream, "EOF");
+ break;
+ case isc_tokentype_initialws:
+ fprintf(stream, "INITIALWS");
+ break;
+ case isc_tokentype_special:
+ fprintf(stream, "SPECIAL %c", tokenp->value.as_char);
+ break;
+ case isc_tokentype_nomore:
+ fprintf(stream, "NOMORE");
+ break;
+ default:
+ FATAL_ERROR(__FILE__, __LINE__, "Unexpected type %d",
+ tokenp->type);
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_token_t token;
+ isc_result_t result;
+ int quiet = 0;
+ int c;
+ int masterfile = 1;
+ int stats = 0;
+ unsigned int options = 0;
+ int done = 0;
+
+ while ((c = isc_commandline_parse(argc, argv, "qmcs")) != -1) {
+ switch (c) {
+ case 'q':
+ quiet = 1;
+ break;
+ case 'm':
+ masterfile = 1;
+ break;
+ case 'c':
+ masterfile = 0;
+ break;
+ case 's':
+ stats = 1;
+ break;
+ }
+ }
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_lex_create(mctx, 256, &lex) == ISC_R_SUCCESS);
+
+ if (masterfile) {
+ /* Set up to lex DNS master file. */
+
+ specials['('] = 1;
+ specials[')'] = 1;
+ specials['"'] = 1;
+ isc_lex_setspecials(lex, specials);
+ options = ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE |
+ ISC_LEXOPT_EOF |
+ ISC_LEXOPT_QSTRING | ISC_LEXOPT_NOMORE;
+ isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
+ } else {
+ /* Set up to lex DNS config file. */
+
+ specials['{'] = 1;
+ specials['}'] = 1;
+ specials[';'] = 1;
+ specials['/'] = 1;
+ specials['"'] = 1;
+ specials['!'] = 1;
+ specials['*'] = 1;
+ isc_lex_setspecials(lex, specials);
+ options = ISC_LEXOPT_EOF |
+ ISC_LEXOPT_QSTRING |
+ ISC_LEXOPT_NUMBER | ISC_LEXOPT_NOMORE;
+ isc_lex_setcomments(lex, (ISC_LEXCOMMENT_C|
+ ISC_LEXCOMMENT_CPLUSPLUS|
+ ISC_LEXCOMMENT_SHELL));
+ }
+
+ RUNTIME_CHECK(isc_lex_openstream(lex, stdin) == ISC_R_SUCCESS);
+
+ while ((result = isc_lex_gettoken(lex, options, &token)) ==
+ ISC_R_SUCCESS && !done) {
+ if (!quiet) {
+ char *name = isc_lex_getsourcename(lex);
+ print_token(&token, stdout);
+ printf(" line = %lu file = %s\n",
+ isc_lex_getsourceline(lex),
+ (name == NULL) ? "<none>" : name);
+ }
+ if (token.type == isc_tokentype_eof)
+ isc_lex_close(lex);
+ if (token.type == isc_tokentype_nomore)
+ done = 1;
+ }
+ if (result != ISC_R_SUCCESS)
+ printf("Result: %s\n", isc_result_totext(result));
+
+ isc_lex_close(lex);
+ isc_lex_destroy(&lex);
+ if (!quiet && stats)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/lfsr_test.c b/bin/tests/lfsr_test.c
new file mode 100644
index 0000000..4150b2d
--- /dev/null
+++ b/bin/tests/lfsr_test.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: lfsr_test.c,v 1.16 2007/06/19 23:46:59 tbox Exp $ */
+
+/*! \file */
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/lfsr.h>
+#include <isc/util.h>
+
+isc_uint32_t state[1024 * 64];
+
+int
+main(int argc, char **argv) {
+ isc_lfsr_t lfsr1, lfsr2;
+ int i;
+ isc_uint32_t temp;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ /*
+ * Verify that returned values are reproducable.
+ */
+ isc_lfsr_init(&lfsr1, 0, 32, 0x80000057U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr1, &state[i], 4);
+ printf("lfsr1: state[%2d] = %08x\n", i, state[i]);
+ }
+ isc_lfsr_init(&lfsr1, 0, 32, 0x80000057U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr1, &temp, 4);
+ if (state[i] != temp)
+ printf("lfsr1: state[%2d] = %08x, "
+ "but new state is %08x\n",
+ i, state[i], temp);
+ }
+
+ /*
+ * Now do the same with skipping.
+ */
+ isc_lfsr_init(&lfsr1, 0, 32, 0x80000057U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr1, &state[i], 4);
+ isc_lfsr_skip(&lfsr1, 32);
+ printf("lfsr1: state[%2d] = %08x\n", i, state[i]);
+ }
+ isc_lfsr_init(&lfsr1, 0, 32, 0x80000057U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr1, &temp, 4);
+ isc_lfsr_skip(&lfsr1, 32);
+ if (state[i] != temp)
+ printf("lfsr1: state[%2d] = %08x, "
+ "but new state is %08x\n",
+ i, state[i], temp);
+ }
+
+ /*
+ * Try to find the period of the LFSR.
+ *
+ * x^16 + x^5 + x^3 + x^2 + 1
+ */
+ isc_lfsr_init(&lfsr2, 0, 16, 0x00008016U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr2, &state[i], 4);
+ printf("lfsr2: state[%2d] = %08x\n", i, state[i]);
+ }
+ isc_lfsr_init(&lfsr2, 0, 16, 0x00008016U, 0, NULL, NULL);
+ for (i = 0; i < 32; i++) {
+ isc_lfsr_generate(&lfsr2, &temp, 4);
+ if (state[i] != temp)
+ printf("lfsr2: state[%2d] = %08x, "
+ "but new state is %08x\n",
+ i, state[i], temp);
+ }
+
+ return (0);
+}
diff --git a/bin/tests/log_test.c b/bin/tests/log_test.c
new file mode 100644
index 0000000..09b5fec
--- /dev/null
+++ b/bin/tests/log_test.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: log_test.c,v 1.26 2007/06/19 23:46:59 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+
+#include <dns/log.h>
+
+#define TEST_FILE "/tmp/test_log"
+#define SYSLOG_FILE "/var/log/daemon.log"
+#define FILE_VERSIONS 10
+
+char usage[] = "Usage: %s [-m] [-s syslog_logfile] [-r file_versions]\n";
+
+#define CHECK(expr) result = expr; \
+ if (result != ISC_R_SUCCESS) { \
+ fprintf(stderr, "%s: " #expr "%s: exiting\n", \
+ progname, isc_result_totext(result)); \
+ }
+
+int
+main(int argc, char **argv) {
+ const char *progname, *syslog_file, *message;
+ int ch, i, file_versions, stderr_line;
+ isc_boolean_t show_final_mem = ISC_FALSE;
+ isc_log_t *lctx;
+ isc_logconfig_t *lcfg;
+ isc_mem_t *mctx;
+ isc_result_t result;
+ isc_logdestination_t destination;
+ const isc_logcategory_t *category;
+ const isc_logmodule_t *module;
+
+ progname = strrchr(*argv, '/');
+ if (progname != NULL)
+ progname++;
+ else
+ progname = *argv;
+
+ syslog_file = SYSLOG_FILE;
+ file_versions = FILE_VERSIONS;
+
+ while ((ch = isc_commandline_parse(argc, argv, "ms:r:")) != -1) {
+ switch (ch) {
+ case 'm':
+ show_final_mem = ISC_TRUE;
+ break;
+ case 's':
+ syslog_file = isc_commandline_argument;
+ break;
+ case 'r':
+ file_versions = atoi(isc_commandline_argument);
+ if (file_versions < 0 &&
+ file_versions != ISC_LOG_ROLLNEVER &&
+ file_versions != ISC_LOG_ROLLINFINITE) {
+ fprintf(stderr, "%s: file rotations must be "
+ "%d (ISC_LOG_ROLLNEVER),\n\t"
+ "%d (ISC_LOG_ROLLINFINITE) "
+ "or > 0\n", progname,
+ ISC_LOG_ROLLNEVER,
+ ISC_LOG_ROLLINFINITE);
+ exit(1);
+ }
+ break;
+ case '?':
+ fprintf(stderr, usage, progname);
+ exit(1);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc > 0) {
+ fprintf(stderr, usage, progname);
+ exit(1);
+ }
+
+ fprintf(stderr, "EXPECT:\n%s%d%s%s%s",
+ "8 lines to stderr (first 4 numbered, #3 repeated)\n",
+ file_versions == 0 || file_versions == ISC_LOG_ROLLNEVER ? 1 :
+ file_versions > 0 ? file_versions + 1 : FILE_VERSIONS + 1,
+ " " TEST_FILE " files, and\n",
+ "2 lines to syslog\n",
+ "lines ending with exclamation marks are errors\n\n");
+
+ isc_log_opensyslog(progname, LOG_PID, LOG_DAEMON);
+
+ mctx = NULL;
+ lctx = NULL;
+ lcfg = NULL;
+
+ CHECK(isc_mem_create(0, 0, &mctx));
+ CHECK(isc_log_create(mctx, &lctx, &lcfg));
+
+ CHECK(isc_log_settag(lcfg, progname));
+
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ /*
+ * Test isc_log_categorybyname and isc_log_modulebyname.
+ */
+ category = isc_log_categorybyname(lctx, "notify");
+ if (category != NULL)
+ fprintf(stderr, "%s category found. (expected)\n",
+ category->name);
+ else
+ fprintf(stderr, "notify category not found!\n");
+
+ module = isc_log_modulebyname(lctx, "xyzzy");
+ if (module != NULL)
+ fprintf(stderr, "%s module found!\n", module->name);
+ else
+ fprintf(stderr, "xyzzy module not found. (expected)\n");
+
+ /*
+ * Create a file channel to test file opening, size limiting and
+ * version rolling.
+ */
+
+ destination.file.name = TEST_FILE;
+ destination.file.maximum_size = 1;
+ destination.file.versions = file_versions;
+
+ CHECK(isc_log_createchannel(lcfg, "file_test", ISC_LOG_TOFILE,
+ ISC_LOG_INFO, &destination,
+ ISC_LOG_PRINTTIME|
+ ISC_LOG_PRINTTAG|
+ ISC_LOG_PRINTLEVEL|
+ ISC_LOG_PRINTCATEGORY|
+ ISC_LOG_PRINTMODULE));
+
+ /*
+ * Create a dynamic debugging channel to a file descriptor.
+ */
+ destination.file.stream = stderr;
+
+ CHECK(isc_log_createchannel(lcfg, "debug_test", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC, &destination,
+ ISC_LOG_PRINTTIME|
+ ISC_LOG_PRINTLEVEL|
+ ISC_LOG_DEBUGONLY));
+
+ /*
+ * Test the usability of the four predefined logging channels.
+ */
+ CHECK(isc_log_usechannel(lcfg, "default_syslog",
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE));
+ CHECK(isc_log_usechannel(lcfg, "default_stderr",
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE));
+ CHECK(isc_log_usechannel(lcfg, "default_debug",
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE));
+ CHECK(isc_log_usechannel(lcfg, "null",
+ DNS_LOGCATEGORY_DATABASE,
+ NULL));
+
+ /*
+ * Use the custom channels.
+ */
+ CHECK(isc_log_usechannel(lcfg, "file_test",
+ DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DB));
+
+ CHECK(isc_log_usechannel(lcfg, "debug_test",
+ DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_RBTDB));
+
+ fprintf(stderr, "\n==> stderr begin\n");
+
+ /*
+ * Write to the internal default by testing both a category for which
+ * no channel has been specified and a category which was specified
+ * but not with the named module.
+ */
+ stderr_line = 1;
+
+ isc_log_write(lctx, DNS_LOGCATEGORY_SECURITY, DNS_LOGMODULE_RBT,
+ ISC_LOG_CRITICAL, "%s (%d)",
+ "Unspecified category and unspecified module to stderr",
+ stderr_line++);
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBT,
+ ISC_LOG_CRITICAL, "%s (%d)",
+ "Specified category and unspecified module to stderr",
+ stderr_line++);
+
+ /*
+ * Write to default_syslog, default_stderr and default_debug.
+ */
+ isc_log_write(lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
+ ISC_LOG_WARNING, "%s (%d twice)",
+ "Using the predefined channels to syslog+stderr",
+ stderr_line++);
+
+ /*
+ * Write to predefined null channel.
+ */
+ isc_log_write(lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_INFO, "This is to null and should not appear!");
+
+ /*
+ * Reset the internal default to use syslog instead of stderr,
+ * and test it.
+ */
+ CHECK(isc_log_usechannel(lcfg, "default_syslog",
+ ISC_LOGCATEGORY_DEFAULT, NULL));
+ isc_log_write(lctx, DNS_LOGCATEGORY_SECURITY, DNS_LOGMODULE_RBT,
+ ISC_LOG_ERROR, "%s%s",
+ "This message to the redefined default category should ",
+ "be second in syslog");
+ /*
+ * Write to the file channel.
+ */
+ if (file_versions >= 0 || file_versions == ISC_LOG_ROLLINFINITE) {
+
+ /*
+ * If file_versions is 0 or ISC_LOG_ROLLINFINITE, write
+ * the "should not appear" and "should be in file" messages
+ * to ensure they get rolled.
+ */
+ if (file_versions <= 0)
+ file_versions = FILE_VERSIONS;
+
+ else
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
+ "This should be rolled over "
+ "and not appear!");
+
+ for (i = file_versions - 1; i >= 0; i--)
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
+ "should be in file %d/%d", i,
+ file_versions - 1);
+
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
+ "should be in base file");
+ } else {
+ file_versions = FILE_VERSIONS;
+ for (i = 1; i <= file_versions; i++)
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
+ "This is message %d in the log file", i);
+ }
+
+
+ /*
+ * Write a debugging message to a category that has no
+ * debugging channels for the named module.
+ */
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_DB,
+ ISC_LOG_DEBUG(1),
+ "This debug message should not appear!");
+
+ /*
+ * Write debugging messages to a dynamic debugging channel.
+ */
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_CRITICAL, "This critical message should "
+ "not appear because the debug level is 0!");
+
+ isc_log_setdebuglevel(lctx, 3);
+
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_DEBUG(1), "%s (%d)",
+ "Dynamic debugging to stderr", stderr_line++);
+ isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_DEBUG(5),
+ "This debug level is too high and should not appear!");
+
+ /*
+ * Test out the duplicate filtering using the debug_test channel.
+ */
+ isc_log_setduplicateinterval(lcfg, 10);
+ message = "This message should appear only once on stderr";
+
+ isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_CRITICAL, "%s", message);
+ isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_CRITICAL, message);
+
+ isc_log_setduplicateinterval(lcfg, 1);
+ message = "This message should appear twice on stderr";
+
+ isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_CRITICAL, message);
+ sleep(2);
+ isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
+ ISC_LOG_CRITICAL, message);
+
+ /*
+ * Review where everything went.
+ * XXXDCL NT
+ */
+ fputc('\n', stderr);
+ system("head " TEST_FILE "*; rm -f " TEST_FILE "*");
+
+ freopen(syslog_file, "r", stdin);
+ fprintf(stderr, "\n==> %s <==\n", syslog_file);
+ system("tail -2");
+ fputc('\n', stderr);
+
+ isc_log_destroy(&lctx);
+
+ if (show_final_mem)
+ isc_mem_stats(mctx, stderr);
+
+ return (0);
+}
diff --git a/bin/tests/lwres_test.c b/bin/tests/lwres_test.c
new file mode 100644
index 0000000..9620258
--- /dev/null
+++ b/bin/tests/lwres_test.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwres_test.c,v 1.31 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/util.h>
+
+#include <lwres/lwres.h>
+
+#define USE_ISC_MEM
+
+static inline void
+CHECK(int val, const char *msg) {
+ if (val != 0) {
+ fprintf(stderr, "%s returned %d\n", msg, val);
+ exit(1);
+ }
+}
+
+static void
+hexdump(const char *msg, void *base, size_t len) {
+ unsigned char *p;
+ unsigned int cnt;
+
+ p = base;
+ cnt = 0;
+
+ printf("*** %s (%lu bytes @ %p)\n", msg, (unsigned long)len, base);
+
+ while (cnt < len) {
+ if (cnt % 16 == 0)
+ printf("%p: ", p);
+ else if (cnt % 8 == 0)
+ printf(" |");
+ printf(" %02x", *p++);
+ cnt++;
+
+ if (cnt % 16 == 0)
+ printf("\n");
+ }
+
+ if (cnt % 16 != 0)
+ printf("\n");
+}
+
+static const char *TESTSTRING = "This is a test. This is only a test. !!!";
+static lwres_context_t *ctx;
+
+static void
+test_noop(void) {
+ int ret;
+ lwres_lwpacket_t pkt, pkt2;
+ lwres_nooprequest_t nooprequest, *nooprequest2;
+ lwres_noopresponse_t noopresponse, *noopresponse2;
+ lwres_buffer_t b;
+
+ pkt.pktflags = 0;
+ pkt.serial = 0x11223344;
+ pkt.recvlength = 0x55667788;
+ pkt.result = 0;
+
+ nooprequest.datalength = strlen(TESTSTRING);
+ /* XXXDCL maybe "nooprequest.data" should be const. */
+ DE_CONST(TESTSTRING, nooprequest.data);
+ ret = lwres_nooprequest_render(ctx, &nooprequest, &pkt, &b);
+ CHECK(ret, "lwres_nooprequest_render");
+
+ hexdump("rendered noop request", b.base, b.used);
+
+ /*
+ * Now, parse it into a new structure.
+ */
+ lwres_buffer_first(&b);
+ ret = lwres_lwpacket_parseheader(&b, &pkt2);
+ CHECK(ret, "lwres_lwpacket_parseheader");
+
+ hexdump("parsed pkt2", &pkt2, sizeof(pkt2));
+
+ nooprequest2 = NULL;
+ ret = lwres_nooprequest_parse(ctx, &b, &pkt2, &nooprequest2);
+ CHECK(ret, "lwres_nooprequest_parse");
+
+ assert(nooprequest.datalength == nooprequest2->datalength);
+ assert(memcmp(nooprequest.data, nooprequest2->data,
+ nooprequest.datalength) == 0);
+
+ lwres_nooprequest_free(ctx, &nooprequest2);
+
+ lwres_context_freemem(ctx, b.base, b.length);
+ b.base = NULL;
+ b.length = 0;
+
+ pkt.pktflags = 0;
+ pkt.serial = 0x11223344;
+ pkt.recvlength = 0x55667788;
+ pkt.result = 0xdeadbeef;
+
+ noopresponse.datalength = strlen(TESTSTRING);
+ /* XXXDCL maybe "noopresponse.data" should be const. */
+ DE_CONST(TESTSTRING, noopresponse.data);
+ ret = lwres_noopresponse_render(ctx, &noopresponse, &pkt, &b);
+ CHECK(ret, "lwres_noopresponse_render");
+
+ hexdump("rendered noop response", b.base, b.used);
+
+ /*
+ * Now, parse it into a new structure.
+ */
+ lwres_buffer_first(&b);
+ ret = lwres_lwpacket_parseheader(&b, &pkt2);
+ CHECK(ret, "lwres_lwpacket_parseheader");
+
+ hexdump("parsed pkt2", &pkt2, sizeof(pkt2));
+
+ noopresponse2 = NULL;
+ ret = lwres_noopresponse_parse(ctx, &b, &pkt2, &noopresponse2);
+ CHECK(ret, "lwres_noopresponse_parse");
+
+ assert(noopresponse.datalength == noopresponse2->datalength);
+ assert(memcmp(noopresponse.data, noopresponse2->data,
+ noopresponse.datalength) == 0);
+
+ lwres_noopresponse_free(ctx, &noopresponse2);
+
+ lwres_context_freemem(ctx, b.base, b.length);
+ b.base = NULL;
+ b.length = 0;
+}
+
+static void
+test_gabn(const char *target) {
+ lwres_gabnresponse_t *res;
+ lwres_addr_t *addr;
+ int ret;
+ unsigned int i;
+ char outbuf[64];
+
+ res = NULL;
+ ret = lwres_getaddrsbyname(ctx, target,
+ LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6,
+ &res);
+ printf("gabn %s ret == %d\n", target, ret);
+ if (ret != 0) {
+ printf("FAILURE!\n");
+ if (res != NULL)
+ lwres_gabnresponse_free(ctx, &res);
+ return;
+ }
+
+ printf("Returned real name: (%u, %s)\n",
+ res->realnamelen, res->realname);
+ printf("%u aliases:\n", res->naliases);
+ for (i = 0; i < res->naliases; i++)
+ printf("\t(%u, %s)\n", res->aliaslen[i], res->aliases[i]);
+ printf("%u addresses:\n", res->naddrs);
+ addr = LWRES_LIST_HEAD(res->addrs);
+ for (i = 0; i < res->naddrs; i++) {
+ INSIST(addr != NULL);
+
+ if (addr->family == LWRES_ADDRTYPE_V4)
+ (void)inet_ntop(AF_INET, addr->address,
+ outbuf, sizeof(outbuf));
+ else
+ (void)inet_ntop(AF_INET6, addr->address,
+ outbuf, sizeof(outbuf));
+ printf("\tAddr len %u family %08x %s\n",
+ addr->length, addr->family, outbuf);
+ addr = LWRES_LIST_NEXT(addr, link);
+ }
+
+ lwres_gabnresponse_free(ctx, &res);
+}
+
+static void
+test_gnba(const char *target, lwres_uint32_t af) {
+ lwres_gnbaresponse_t *res;
+ int ret;
+ unsigned int i;
+ unsigned char addrbuf[16];
+ unsigned int len;
+
+ if (af == LWRES_ADDRTYPE_V4) {
+ len = 4;
+ ret = inet_pton(AF_INET, target, addrbuf);
+ assert(ret == 1);
+ } else {
+ len = 16;
+ ret = inet_pton(AF_INET6, target, addrbuf);
+ assert(ret == 1);
+ }
+
+ res = NULL;
+ ret = lwres_getnamebyaddr(ctx, af, len, addrbuf, &res);
+ printf("gnba %s ret == %d\n", target, ret);
+ assert(ret == 0);
+ assert(res != NULL);
+
+ printf("Returned real name: (%u, %s)\n",
+ res->realnamelen, res->realname);
+ printf("%u aliases:\n", res->naliases);
+ for (i = 0; i < res->naliases; i++)
+ printf("\t(%u, %s)\n", res->aliaslen[i], res->aliases[i]);
+
+ lwres_gnbaresponse_free(ctx, &res);
+}
+
+#ifdef USE_ISC_MEM
+/*
+ * Wrappers around our memory management stuff, for the lwres functions.
+ */
+static void *
+mem_alloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+static void
+mem_free(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+#endif
+
+int
+main(int argc, char *argv[]) {
+ int ret;
+#ifdef USE_ISC_MEM
+ isc_mem_t *mem;
+ isc_result_t result;
+#endif
+
+ (void)argc;
+ (void)argv;
+
+#ifdef USE_ISC_MEM
+ mem = NULL;
+ result = isc_mem_create(0, 0, &mem);
+ INSIST(result == ISC_R_SUCCESS);
+#endif
+
+ ctx = NULL;
+#ifdef USE_ISC_MEM
+ ret = lwres_context_create(&ctx, mem, mem_alloc, mem_free, 0);
+#else
+ ret = lwres_context_create(&ctx, NULL, NULL, NULL, 0);
+#endif
+
+ CHECK(ret, "lwres_context_create");
+
+ ret = lwres_conf_parse(ctx, "/etc/resolv.conf");
+ CHECK(ret, "lwres_conf_parse");
+
+ lwres_conf_print(ctx, stdout);
+
+ test_noop();
+
+ /*
+ * The following comments about tests all assume your search path is
+ * nominum.com isc.org flame.org
+ * and ndots is the default of 1.
+ */
+ test_gabn("alias-05.test"); /* exact, then search. */
+ test_gabn("f.root-servers.net.");
+ test_gabn("poofball.flame.org.");
+ test_gabn("foo.ip6.int.");
+ test_gabn("notthereatall.flame.org"); /* exact, then search (!found)*/
+ test_gabn("shell"); /* search (found in nominum.com), then exact */
+ test_gabn("kechara"); /* search (found in flame.org), then exact */
+ test_gabn("lkasdjlaksjdlkasjdlkasjdlkasjd"); /* search, exact(!found)*/
+
+ test_gnba("198.133.199.1", LWRES_ADDRTYPE_V4);
+ test_gnba("204.152.184.79", LWRES_ADDRTYPE_V4);
+ test_gnba("3ffe:8050:201:1860:42::1", LWRES_ADDRTYPE_V6);
+
+ lwres_conf_clear(ctx);
+ lwres_context_destroy(&ctx);
+
+#ifdef USE_ISC_MEM
+ isc_mem_stats(mem, stdout);
+ isc_mem_destroy(&mem);
+#endif
+
+ return (0);
+}
diff --git a/bin/tests/lwresconf_test.c b/bin/tests/lwresconf_test.c
new file mode 100644
index 0000000..48e839f
--- /dev/null
+++ b/bin/tests/lwresconf_test.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004, 2007 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: lwresconf_test.c,v 1.13 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <lwres/lwres.h>
+
+#define USE_ISC_MEM
+
+static inline void
+CHECK(int val, const char *msg) {
+ if (val != 0) {
+ fprintf(stderr, "%s returned %d\n", msg, val);
+ exit(1);
+ }
+}
+
+#ifdef USE_ISC_MEM
+/*
+ * Wrappers around our memory management stuff, for the lwres functions.
+ */
+static void *
+mem_alloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+static void
+mem_free(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+#endif
+
+int
+main(int argc, char *argv[]) {
+ lwres_context_t *ctx;
+ const char *file = "/etc/resolv.conf";
+ int ret;
+#ifdef USE_ISC_MEM
+ isc_mem_t *mem;
+ isc_result_t result;
+#endif
+
+ if (argc > 1) {
+ file = argv[1];
+ }
+
+#ifdef USE_ISC_MEM
+ mem = NULL;
+ result = isc_mem_create(0, 0, &mem);
+ INSIST(result == ISC_R_SUCCESS);
+#endif
+
+ ctx = NULL;
+#ifdef USE_ISC_MEM
+ ret = lwres_context_create(&ctx, mem, mem_alloc, mem_free, 0);
+#else
+ ret = lwres_context_create(&ctx, NULL, NULL, NULL, 0);
+#endif
+ CHECK(ret, "lwres_context_create");
+
+ lwres_conf_init(ctx);
+ if (lwres_conf_parse(ctx, file) == 0) {
+ lwres_conf_print(ctx, stderr);
+ } else {
+ perror("lwres_conf_parse");
+ }
+
+ lwres_conf_clear(ctx);
+ lwres_context_destroy(&ctx);
+
+#ifdef USE_ISC_MEM
+ isc_mem_stats(mem, stdout);
+ isc_mem_destroy(&mem);
+#endif
+
+ return (0);
+}
diff --git a/bin/tests/master/Makefile.in b/bin/tests/master/Makefile.in
new file mode 100644
index 0000000..03125da
--- /dev/null
+++ b/bin/tests/master/Makefile.in
@@ -0,0 +1,58 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-2002 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.28 2007/06/19 23:47:00 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+# Note that we do not want to use libtool for libt_api
+DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../../lib/isc/libisc.@A@
+
+DNSDEPLIBS = ../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+TLIB = ../../../lib/tests/libt_api.@A@
+
+TARGETS = t_master@EXEEXT@
+
+SRCS = t_master.c
+
+@BIND9_MAKE_RULES@
+
+t_master@EXEEXT@: t_master.@O@ ${DEPLIBS} ${TLIB}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_master.@O@ ${TLIB} ${LIBS}
+
+test: t_master@EXEEXT@
+ -@ ./t_master@EXEEXT@ -c @top_srcdir@/t_config -b @srcdir@ -a
+
+testhelp:
+ @ ./t_master@EXEEXT@ -h
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/master/dns_master_load_10_data b/bin/tests/master/dns_master_load_10_data
new file mode 100644
index 0000000..cfaa3fb
--- /dev/null
+++ b/bin/tests/master/dns_master_load_10_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 9
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master10.data test in ISC_R_SUCCESS
diff --git a/bin/tests/master/dns_master_load_11_data b/bin/tests/master/dns_master_load_11_data
new file mode 100644
index 0000000..7b667b2
--- /dev/null
+++ b/bin/tests/master/dns_master_load_11_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 11
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master11.data test in ISC_R_SUCCESS
diff --git a/bin/tests/master/dns_master_load_1_data b/bin/tests/master/dns_master_load_1_data
new file mode 100644
index 0000000..fc92c74
--- /dev/null
+++ b/bin/tests/master/dns_master_load_1_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 1
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master1.data test in ISC_R_SUCCESS
diff --git a/bin/tests/master/dns_master_load_2_data b/bin/tests/master/dns_master_load_2_data
new file mode 100644
index 0000000..a6e44b3
--- /dev/null
+++ b/bin/tests/master/dns_master_load_2_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 2
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master2.data test in ISC_R_UNEXPECTEDEND
diff --git a/bin/tests/master/dns_master_load_3_data b/bin/tests/master/dns_master_load_3_data
new file mode 100644
index 0000000..9dbdfb2
--- /dev/null
+++ b/bin/tests/master/dns_master_load_3_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 3
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master3.data test in DNS_R_NOOWNER
diff --git a/bin/tests/master/dns_master_load_4_data b/bin/tests/master/dns_master_load_4_data
new file mode 100644
index 0000000..66ad1ff
--- /dev/null
+++ b/bin/tests/master/dns_master_load_4_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 4
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master4.data test in ISC_R_SUCCESS
diff --git a/bin/tests/master/dns_master_load_5_data b/bin/tests/master/dns_master_load_5_data
new file mode 100644
index 0000000..56e33ba
--- /dev/null
+++ b/bin/tests/master/dns_master_load_5_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 5
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master5.data test in DNS_R_BADCLASS
diff --git a/bin/tests/master/dns_master_load_6_data b/bin/tests/master/dns_master_load_6_data
new file mode 100644
index 0000000..d14aa88
--- /dev/null
+++ b/bin/tests/master/dns_master_load_6_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 6
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master6.data test in ISC_R_SUCCESS
diff --git a/bin/tests/master/dns_master_load_7_data b/bin/tests/master/dns_master_load_7_data
new file mode 100644
index 0000000..dbe7ef9
--- /dev/null
+++ b/bin/tests/master/dns_master_load_7_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 7
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master7.data test in ISC_R_SUCCESS
diff --git a/bin/tests/master/dns_master_load_8_data b/bin/tests/master/dns_master_load_8_data
new file mode 100644
index 0000000..b109d43
--- /dev/null
+++ b/bin/tests/master/dns_master_load_8_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 8
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master8.data test in DNS_R_SEENINCLUDE
diff --git a/bin/tests/master/dns_master_load_9_data b/bin/tests/master/dns_master_load_9_data
new file mode 100644
index 0000000..af36072
--- /dev/null
+++ b/bin/tests/master/dns_master_load_9_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_master_load test 9
+#
+# format is:
+# masterfile origin class expected_result
+# where
+# masterfile name is the name of a file containing master data
+# origin is the origin
+# class is the zone's class
+# expected_result is a text representation of a dns_result_t
+#
+master9.data test in DNS_R_BADCLASS
diff --git a/bin/tests/master/master1.data b/bin/tests/master/master1.data
new file mode 100644
index 0000000..9b81474
--- /dev/null
+++ b/bin/tests/master/master1.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2vix.com.
+a in ns ns3vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/master/master10.data b/bin/tests/master/master10.data
new file mode 100644
index 0000000..9ee052f
--- /dev/null
+++ b/bin/tests/master/master10.data
@@ -0,0 +1,7 @@
+;
+; the following black line contains spaces
+
+;
+@ 300 IN A 10.0.0.1
+ ;
+;
diff --git a/bin/tests/master/master11.data b/bin/tests/master/master11.data
new file mode 100644
index 0000000..0aaec25
--- /dev/null
+++ b/bin/tests/master/master11.data
@@ -0,0 +1,6 @@
+;
+; The following serial number contains a leading 0 and a 9 so the
+; we can catch cases where it is incorrectly treated as a octal
+; number.
+;
+@ 300 IN SOA ns hostmaster 00090000 1200 3600 604800 300
diff --git a/bin/tests/master/master2.data b/bin/tests/master/master2.data
new file mode 100644
index 0000000..b8ca38d
--- /dev/null
+++ b/bin/tests/master/master2.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns
+a in ns ns2vix.com.
+a in ns ns3vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/master/master3.data b/bin/tests/master/master3.data
new file mode 100644
index 0000000..7283af6
--- /dev/null
+++ b/bin/tests/master/master3.data
@@ -0,0 +1,11 @@
+$TTL 1000
+ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+ in ns ns.vix.com
+ in ns ns2vix.com.
+a in ns ns3vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/master/master4.data b/bin/tests/master/master4.data
new file mode 100644
index 0000000..3a694ea
--- /dev/null
+++ b/bin/tests/master/master4.data
@@ -0,0 +1,11 @@
+
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a in ns ns.vix.com.
+a in ns ns2vix.com.
+a in ns ns3vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/master/master5.data b/bin/tests/master/master5.data
new file mode 100644
index 0000000..95234bd
--- /dev/null
+++ b/bin/tests/master/master5.data
@@ -0,0 +1,11 @@
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+a any ns ns.vix.com.
+a in ns ns2vix.com.
+a in ns ns3vix.com.
+b in a 1.2.3.4
diff --git a/bin/tests/master/master6.data b/bin/tests/master/master6.data
new file mode 100644
index 0000000..a9a37bb
--- /dev/null
+++ b/bin/tests/master/master6.data
@@ -0,0 +1,33 @@
+
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+
+secure1 3600 IN DNSKEY (
+ FLAG2|FLAG4|FLAG5|NTYP3|FLAG8|FLAG9|FLAG10|FLAG11|SIG15
+ 3 3
+ ArT0a8FtOZWEONG2YQVl9+RA34op30JPz4NPEroCxm2yImT2
+ 2OYggnPIzrgayyepgKU1PfTTypnJDTwrSrtISyEsj7tjM7/n
+ 03DP8VWSn0aLwpUuc7Sx9vtM1Wi+YeiA4Bv2Oz1VB9de4qql
+ sIq+KLn8J4wz95bGnJ0mHUB7oTDJ3Hl1zeaCMdX69Kr46yAY
+ AvGJJdGGDYxYgxzx2zNdzypkYSkxpdsNqUt38tabSfdvCn12
+ pnmSWjlVJsjHhsaYnrPhouN5acOXMNbxNVbGU5LZ8Es6EYbV
+ /7YMt8VUkA8/8UCszBBT7XAJ3OFjiMO8mvxrZZFzvwJlPBQ1
+ oFq/TNZlSe+N )
+
+secure2 3600 in DNSKEY (
+ flag2|flag4|flag5|ntyp3|flag8|flag9|flag10|flag11|sig15
+ 3 3
+ ArT0a8FtOZWEONG2YQVl9+RA34op30JPz4NPEroCxm2yImT2
+ 2OYggnPIzrgayyepgKU1PfTTypnJDTwrSrtISyEsj7tjM7/n
+ 03DP8VWSn0aLwpUuc7Sx9vtM1Wi+YeiA4Bv2Oz1VB9de4qql
+ sIq+KLn8J4wz95bGnJ0mHUB7oTDJ3Hl1zeaCMdX69Kr46yAY
+ AvGJJdGGDYxYgxzx2zNdzypkYSkxpdsNqUt38tabSfdvCn12
+ pnmSWjlVJsjHhsaYnrPhouN5acOXMNbxNVbGU5LZ8Es6EYbV
+ /7YMt8VUkA8/8UCszBBT7XAJ3OFjiMO8mvxrZZFzvwJlPBQ1
+ oFq/TNZlSe+N )
+
diff --git a/bin/tests/master/master7.data b/bin/tests/master/master7.data
new file mode 100644
index 0000000..2638b5d
--- /dev/null
+++ b/bin/tests/master/master7.data
@@ -0,0 +1,17 @@
+
+$TTL 1000
+@ in soa localhost. postmaster.localhost. (
+ 1993050801 ;serial
+ 3600 ;refresh
+ 1800 ;retry
+ 604800 ;expiration
+ 3600 ) ;minimum
+
+secure1 3600 IN DNSKEY (
+ NOKEY|FLAG2|FLAG4|FLAG5|NTYP3|FLAG8|FLAG9|FLAG10|FLAG11|SIG15
+ 3 3 )
+
+secure2 3600 in DNSKEY (
+ nokey|flag2|flag4|flag5|ntyp3|flag8|flag9|flag10|flag11|sig15
+ 3 3 )
+
diff --git a/bin/tests/master/master8.data b/bin/tests/master/master8.data
new file mode 100644
index 0000000..58bded9
--- /dev/null
+++ b/bin/tests/master/master8.data
@@ -0,0 +1,4 @@
+;
+; master7.data contains a good zone file
+;
+$include master7.data
diff --git a/bin/tests/master/master9.data b/bin/tests/master/master9.data
new file mode 100644
index 0000000..e7bcf7e
--- /dev/null
+++ b/bin/tests/master/master9.data
@@ -0,0 +1,4 @@
+;
+; master5.data is bad
+;
+$include master5.data
diff --git a/bin/tests/master/t_master.c b/bin/tests/master/t_master.c
new file mode 100644
index 0000000..4693114
--- /dev/null
+++ b/bin/tests/master/t_master.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: t_master.c,v 1.36 2007/06/19 23:47:00 tbox Exp $ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/master.h>
+#include <dns/name.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+
+#include <tests/t_api.h>
+
+#define BUFLEN 255
+#define BIGBUFLEN (64 * 1024)
+
+static isc_result_t
+t1_add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset);
+
+isc_mem_t *T1_mctx;
+char *Tokens[T_MAXTOKS + 1];
+
+static isc_result_t
+t1_add_callback(void *arg, dns_name_t *owner, dns_rdataset_t *dataset) {
+ char buf[BIGBUFLEN];
+ isc_buffer_t target;
+ isc_result_t result;
+
+ UNUSED(arg);
+
+ isc_buffer_init(&target, buf, BIGBUFLEN);
+ result = dns_rdataset_totext(dataset, owner, ISC_FALSE, ISC_FALSE,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ t_info("dns_rdataset_totext: %s\n", dns_result_totext(result));
+
+ return(result);
+}
+
+static int
+test_master(char *testfile, char *origin, char *class, isc_result_t exp_result)
+{
+ int result;
+ int len;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_name_t dns_origin;
+ isc_buffer_t source;
+ isc_buffer_t target;
+ unsigned char name_buf[BUFLEN];
+ dns_rdatacallbacks_t callbacks;
+ dns_rdataclass_t rdataclass;
+ isc_textregion_t textregion;
+
+ result = T_UNRESOLVED;
+ if (T1_mctx == NULL)
+ isc_result = isc_mem_create(0, 0, &T1_mctx);
+ else
+ isc_result = ISC_R_SUCCESS;
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+
+ len = strlen(origin);
+ isc_buffer_init(&source, origin, len);
+ isc_buffer_add(&source, len);
+ isc_buffer_setactive(&source, len);
+ isc_buffer_init(&target, name_buf, BUFLEN);
+ dns_name_init(&dns_origin, NULL);
+ dns_result = dns_name_fromtext(&dns_origin, &source, dns_rootname,
+ ISC_FALSE, &target);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(T_UNRESOLVED);
+ }
+
+ dns_rdatacallbacks_init_stdio(&callbacks);
+ callbacks.add = t1_add_callback;
+
+ textregion.base = class;
+ textregion.length = strlen(class);
+
+ dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rdataclass_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(T_UNRESOLVED);
+ }
+
+ dns_result = dns_master_loadfile( testfile,
+ &dns_origin,
+ &dns_origin,
+ rdataclass,
+ ISC_TRUE,
+ &callbacks,
+ T1_mctx);
+
+ if (dns_result == exp_result)
+ result = T_PASS;
+ else {
+ t_info("dns_master_loadfile: got %s, expected %s\n",
+ dns_result_totext(dns_result),
+ dns_result_totext(exp_result));
+ result = T_FAIL;
+ }
+ return(result);
+}
+
+static int
+test_master_x(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+
+ result = T_UNRESOLVED;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace(*p & 0xff)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ /*
+ * Name of data file, origin, zclass, expected result.
+ */
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 4) {
+ result = test_master(Tokens[0], Tokens[1],
+ Tokens[2],
+ t_dns_result_fromtext(Tokens[3]));
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ }
+ return(result);
+}
+
+static const char *a1 = "dns_master_loadfile loads a valid master file and "
+ "returns ISC_R_SUCCESS";
+static void
+t1(void) {
+ int result;
+ t_assert("dns_master_loadfile", 1, T_REQUIRED, a1);
+ result = test_master_x("dns_master_load_1_data");
+ t_result(result);
+}
+
+static const char *a2 =
+ "dns_master_loadfile returns ISC_R_UNEXPECTEDEND when the "
+ "masterfile input ends unexpectedly";
+
+static void
+t2(void) {
+ int result;
+ t_assert("dns_master_loadfile", 2, T_REQUIRED, a2);
+ result = test_master_x("dns_master_load_2_data");
+ t_result(result);
+}
+
+static const char *a3 = "dns_master_loadfile returns DNS_R_NOOWNER when the "
+ "an ownername is not specified";
+
+static void
+t3() {
+ int result;
+ t_assert("dns_master_loadfile", 3, T_REQUIRED, a3);
+ result = test_master_x("dns_master_load_3_data");
+ t_result(result);
+}
+
+static const char *a4 = "dns_master_loadfile accepts broken zone files "
+ "where the first record has an undefined TTL, "
+ "as long as it is a SOA";
+
+static void
+t4() {
+ int result;
+ t_assert("dns_master_loadfile", 4, T_REQUIRED, a4);
+ result = test_master_x("dns_master_load_4_data");
+ t_result(result);
+}
+
+static const char *a5 = "dns_master_loadfile returns DNS_R_BADCLASS when the "
+ "the record class did not match the zone class";
+
+static void
+t5() {
+ int result;
+
+ t_assert("dns_master_loadfile", 5, T_REQUIRED, a5);
+ result = test_master_x("dns_master_load_5_data");
+
+ t_result(result);
+}
+
+static const char *a6 =
+ "dns_master_loadfile understands DNSKEY RR specifications "
+ "containing key material";
+
+static void
+t6() {
+ int result;
+
+ t_assert("dns_master_loadfile", 6, T_REQUIRED, a6);
+ result = test_master_x("dns_master_load_6_data");
+
+ t_result(result);
+}
+
+static const char *a7 =
+ "dns_master_loadfile understands DNSKEY RR specifications "
+ "containing no key material";
+
+static void
+t7() {
+ int result;
+
+ t_assert("dns_master_loadfile", 7, T_REQUIRED, a7);
+ result = test_master_x("dns_master_load_7_data");
+
+ t_result(result);
+}
+
+static const char *a8 =
+ "dns_master_loadfile understands $INCLUDE";
+
+static void
+t8() {
+ int result;
+
+ t_assert("dns_master_loadfile", 8, T_REQUIRED, a8);
+ result = test_master_x("dns_master_load_8_data");
+
+ t_result(result);
+}
+
+static const char *a9 =
+ "dns_master_loadfile understands $INCLUDE with failure";
+
+static void
+t9() {
+ int result;
+
+ t_assert("dns_master_loadfile", 9, T_REQUIRED, a9);
+ result = test_master_x("dns_master_load_9_data");
+
+ t_result(result);
+}
+
+static const char *a10 =
+ "dns_master_loadfile non-empty blank lines";
+
+static void
+t10() {
+ int result;
+
+ t_assert("dns_master_loadfile", 10, T_REQUIRED, a10);
+ result = test_master_x("dns_master_load_10_data");
+
+ t_result(result);
+}
+
+static const char *a11 =
+ "dns_master_loadfile allow leading zeros in SOA";
+
+static void
+t11() {
+ int result;
+
+ t_assert("dns_master_loadfile", 11, T_REQUIRED, a11);
+ result = test_master_x("dns_master_load_11_data");
+
+ t_result(result);
+}
+
+
+testspec_t T_testlist[] = {
+ { t1, "ISC_R_SUCCESS" },
+ { t2, "ISC_R_UNEXPECTEDEND" },
+ { t3, "DNS_NOOWNER" },
+ { t4, "DNS_NOTTL" },
+ { t5, "DNS_BADCLASS" },
+ { t6, "DNSKEY RR 1" },
+ { t7, "DNSKEY RR 2" },
+ { t8, "$INCLUDE" },
+ { t9, "$INCLUDE w/ DNS_BADCLASS" },
+ { t10, "non empty blank lines" },
+ { t11, "leading zeros in serial" },
+ { NULL, NULL }
+};
+
diff --git a/bin/tests/master_test.c b/bin/tests/master_test.c
new file mode 100644
index 0000000..f77c8f6
--- /dev/null
+++ b/bin/tests/master_test.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: master_test.c,v 1.30 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/master.h>
+#include <dns/name.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+
+isc_mem_t *mctx;
+
+static isc_result_t
+print_dataset(void *arg, dns_name_t *owner, dns_rdataset_t *dataset) {
+ char buf[64*1024];
+ isc_buffer_t target;
+ isc_result_t result;
+
+ UNUSED(arg);
+
+ isc_buffer_init(&target, buf, 64*1024);
+ result = dns_rdataset_totext(dataset, owner, ISC_FALSE, ISC_FALSE,
+ &target);
+ if (result == ISC_R_SUCCESS)
+ fprintf(stdout, "%.*s\n", (int)target.used,
+ (char*)target.base);
+ else
+ fprintf(stdout, "dns_rdataset_totext: %s\n",
+ dns_result_totext(result));
+
+ return (ISC_R_SUCCESS);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ dns_name_t origin;
+ isc_buffer_t source;
+ isc_buffer_t target;
+ unsigned char name_buf[255];
+ dns_rdatacallbacks_t callbacks;
+
+ UNUSED(argc);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ if (argv[1]) {
+ isc_buffer_init(&source, argv[1], strlen(argv[1]));
+ isc_buffer_add(&source, strlen(argv[1]));
+ isc_buffer_setactive(&source, strlen(argv[1]));
+ isc_buffer_init(&target, name_buf, 255);
+ dns_name_init(&origin, NULL);
+ result = dns_name_fromtext(&origin, &source, dns_rootname,
+ ISC_FALSE, &target);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout, "dns_name_fromtext: %s\n",
+ dns_result_totext(result));
+ exit(1);
+ }
+
+ dns_rdatacallbacks_init_stdio(&callbacks);
+ callbacks.add = print_dataset;
+
+ result = dns_master_loadfile(argv[1], &origin, &origin,
+ dns_rdataclass_in, 0,
+ &callbacks, mctx);
+ fprintf(stdout, "dns_master_loadfile: %s\n",
+ dns_result_totext(result));
+ }
+ return (0);
+}
diff --git a/bin/tests/mem/Makefile.in b/bin/tests/mem/Makefile.in
new file mode 100644
index 0000000..135a8e3
--- /dev/null
+++ b/bin/tests/mem/Makefile.in
@@ -0,0 +1,55 @@
+# Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-2002 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.34 2007/06/19 23:47:00 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${TEST_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+ISCLIBS = ../../../lib/isc/libisc.@A@
+TAPIDEPLIBS = ../../../lib/tests/libt_api.@A@
+
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+TAPILIBS = ../../../lib/tests/libt_api.@A@
+
+DEPLIBS = ${TAPIDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${TAPILIBS} ${ISCLIBS} @LIBS@
+
+TARGETS = t_mem@EXEEXT@
+
+SRCS = t_mem.c
+
+@BIND9_MAKE_RULES@
+
+t_mem@EXEEXT@: t_mem.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_mem.@O@ ${LIBS}
+
+test: t_mem@EXEEXT@
+ -@./t_mem@EXEEXT@ -b @srcdir@ -q 450 -a
+
+testhelp:
+ @./t_mem@EXEEXT@ -h
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/mem/t_mem.c b/bin/tests/mem/t_mem.c
new file mode 100644
index 0000000..7313637
--- /dev/null
+++ b/bin/tests/mem/t_mem.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: t_mem.c,v 1.13 2007/06/19 23:47:00 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/mem.h>
+
+#include <tests/t_api.h>
+
+/*
+ * Adapted from the original mempool_test.c program.
+ */
+isc_mem_t *mctx;
+
+#define MP1_FREEMAX 10
+#define MP1_FILLCNT 10
+#define MP1_MAXALLOC 30
+
+#define MP2_FREEMAX 25
+#define MP2_FILLCNT 25
+
+static int
+memtest(void) {
+ int nfails;
+ void *items1[50];
+ void *items2[50];
+ void *tmp;
+ isc_mempool_t *mp1, *mp2;
+ isc_result_t isc_result;
+ unsigned int i, j;
+ int rval;
+
+
+ nfails = 0;
+ mctx = NULL;
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ ++nfails;
+ return(nfails);
+ }
+
+ mp1 = NULL;
+ isc_result = isc_mempool_create(mctx, 24, &mp1);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mempool_create failed %s\n",
+ isc_result_totext(isc_result));
+ ++nfails;
+ return(nfails);
+ }
+
+ mp2 = NULL;
+ isc_result = isc_mempool_create(mctx, 31, &mp2);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mempool_create failed %s\n",
+ isc_result_totext(isc_result));
+ ++nfails;
+ return(nfails);
+ }
+
+ if (T_debug)
+ isc_mem_stats(mctx, stderr);
+
+ t_info("setting freemax to %d\n", MP1_FREEMAX);
+ isc_mempool_setfreemax(mp1, MP1_FREEMAX);
+ t_info("setting fillcount to %d\n", MP1_FILLCNT);
+ isc_mempool_setfillcount(mp1, MP1_FILLCNT);
+ t_info("setting maxalloc to %d\n", MP1_MAXALLOC);
+ isc_mempool_setmaxalloc(mp1, MP1_MAXALLOC);
+
+ /*
+ * Allocate MP1_MAXALLOC items from the pool. This is our max.
+ */
+ for (i = 0; i < MP1_MAXALLOC; i++) {
+ items1[i] = isc_mempool_get(mp1);
+ if (items1[i] == NULL) {
+ t_info("isc_mempool_get unexpectedly failed\n");
+ ++nfails;
+ }
+ }
+
+ /*
+ * Try to allocate one more. This should fail.
+ */
+ tmp = isc_mempool_get(mp1);
+ if (tmp != NULL) {
+ t_info("isc_mempool_get unexpectedly succeeded\n");
+ ++nfails;
+ }
+
+ /*
+ * Free the first 11 items. Verify that there are 10 free items on
+ * the free list (which is our max).
+ */
+
+ for (i = 0; i < 11; i++) {
+ isc_mempool_put(mp1, items1[i]);
+ items1[i] = NULL;
+ }
+
+ rval = isc_mempool_getfreecount(mp1);
+ if (rval != 10) {
+ t_info("isc_mempool_getfreecount returned %d, expected %d\n",
+ rval, MP1_FREEMAX);
+ ++nfails;
+ }
+
+ rval = isc_mempool_getallocated(mp1);
+ if (rval != 19) {
+ t_info("isc_mempool_getallocated returned %d, expected %d\n",
+ rval, MP1_MAXALLOC - 11);
+ ++nfails;
+ }
+
+ if (T_debug)
+ isc_mem_stats(mctx, stderr);
+
+ /*
+ * Now, beat up on mp2 for a while. Allocate 50 items, then free
+ * them, then allocate 50 more, etc.
+ */
+
+ t_info("setting freemax to %d\n", MP2_FREEMAX);
+ isc_mempool_setfreemax(mp2, 25);
+ t_info("setting fillcount to %d\n", MP2_FILLCNT);
+ isc_mempool_setfillcount(mp2, 25);
+
+ t_info("exercising the memory pool\n");
+ for (j = 0; j < 500000; j++) {
+ for (i = 0; i < 50; i++) {
+ items2[i] = isc_mempool_get(mp2);
+ if (items2[i] == NULL) {
+ t_info("items2[%d] is unexpectedly null\n", i);
+ ++nfails;
+ }
+ }
+ for (i = 0; i < 50; i++) {
+ isc_mempool_put(mp2, items2[i]);
+ items2[i] = NULL;
+ }
+ if (j % 50000 == 0)
+ t_info("...\n");
+ }
+
+ /*
+ * Free all the other items and blow away this pool.
+ */
+ for (i = 11; i < MP1_MAXALLOC; i++) {
+ isc_mempool_put(mp1, items1[i]);
+ items1[i] = NULL;
+ }
+
+ isc_mempool_destroy(&mp1);
+
+ if (T_debug)
+ isc_mem_stats(mctx, stderr);
+
+ isc_mempool_destroy(&mp2);
+
+ if (T_debug)
+ isc_mem_stats(mctx, stderr);
+
+ isc_mem_destroy(&mctx);
+
+ return(0);
+}
+
+static const char *a1 =
+ "the memory module supports the creation of memory contexts "
+ "and the management of memory pools.";
+static void
+t1(void) {
+ int rval;
+ int result;
+
+ t_assert("mem", 1, T_REQUIRED, a1);
+
+ rval = memtest();
+
+ if (rval == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+ t_result(result);
+}
+
+testspec_t T_testlist[] = {
+ { t1, "basic memory subsystem" },
+ { NULL, NULL }
+};
+
diff --git a/bin/tests/mempool_test.c b/bin/tests/mempool_test.c
new file mode 100644
index 0000000..9423b3a
--- /dev/null
+++ b/bin/tests/mempool_test.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: mempool_test.c,v 1.17 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx;
+
+int
+main(int argc, char *argv[]) {
+ void *items1[50];
+ void *items2[50];
+ void *tmp;
+ isc_mempool_t *mp1, *mp2;
+ unsigned int i, j;
+ isc_mutex_t lock;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+
+ RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ mp1 = NULL;
+ RUNTIME_CHECK(isc_mempool_create(mctx, 24, &mp1) == ISC_R_SUCCESS);
+
+ mp2 = NULL;
+ RUNTIME_CHECK(isc_mempool_create(mctx, 31, &mp2) == ISC_R_SUCCESS);
+
+ isc_mempool_associatelock(mp1, &lock);
+ isc_mempool_associatelock(mp2, &lock);
+
+ isc_mem_stats(mctx, stderr);
+
+ isc_mempool_setfreemax(mp1, 10);
+ isc_mempool_setfillcount(mp1, 10);
+ isc_mempool_setmaxalloc(mp1, 30);
+
+ /*
+ * Allocate 30 items from the pool. This is our max.
+ */
+ for (i = 0; i < 30; i++) {
+ items1[i] = isc_mempool_get(mp1);
+ RUNTIME_CHECK(items1[i] != NULL);
+ }
+
+ /*
+ * Try to allocate one more. This should fail.
+ */
+ tmp = isc_mempool_get(mp1);
+ RUNTIME_CHECK(tmp == NULL);
+
+ /*
+ * Free the first 11 items. Verify that there are 10 free items on
+ * the free list (which is our max).
+ */
+
+ for (i = 0; i < 11; i++) {
+ isc_mempool_put(mp1, items1[i]);
+ items1[i] = NULL;
+ }
+
+ RUNTIME_CHECK(isc_mempool_getfreecount(mp1) == 10);
+ RUNTIME_CHECK(isc_mempool_getallocated(mp1) == 19);
+
+ isc_mem_stats(mctx, stderr);
+
+ /*
+ * Now, beat up on mp2 for a while. Allocate 50 items, then free
+ * them, then allocate 50 more, etc.
+ */
+ isc_mempool_setfreemax(mp2, 25);
+ isc_mempool_setfillcount(mp2, 25);
+ for (j = 0; j < 5000; j++) {
+ for (i = 0; i < 50; i++) {
+ items2[i] = isc_mempool_get(mp2);
+ RUNTIME_CHECK(items2[i] != NULL);
+ }
+ for (i = 0; i < 50; i++) {
+ isc_mempool_put(mp2, items2[i]);
+ items2[i] = NULL;
+ }
+ }
+
+ /*
+ * Free all the other items and blow away this pool.
+ */
+ for (i = 11; i < 30; i++) {
+ isc_mempool_put(mp1, items1[i]);
+ items1[i] = NULL;
+ }
+
+ isc_mempool_destroy(&mp1);
+
+ isc_mem_stats(mctx, stderr);
+
+ isc_mempool_destroy(&mp2);
+
+ isc_mem_stats(mctx, stderr);
+
+ isc_mem_destroy(&mctx);
+
+ DESTROYLOCK(&lock);
+
+ return (0);
+}
diff --git a/bin/tests/name_test.c b/bin/tests/name_test.c
new file mode 100644
index 0000000..799115f
--- /dev/null
+++ b/bin/tests/name_test.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: name_test.c,v 1.41 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/commandline.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/result.h>
+
+static void
+print_wirename(isc_region_t *name) {
+ unsigned char *ccurr, *cend;
+
+ if (name->length == 0) {
+ printf("<empty wire name>\n");
+ return;
+ }
+ ccurr = name->base;
+ cend = ccurr + name->length;
+ while (ccurr != cend)
+ printf("%02x ", *ccurr++);
+ printf("\n");
+}
+
+static void
+print_name(dns_name_t *name) {
+ isc_result_t result;
+ isc_buffer_t source;
+ isc_region_t r;
+ char s[1000];
+
+ isc_buffer_init(&source, s, sizeof(s));
+ if (dns_name_countlabels(name) > 0)
+ result = dns_name_totext(name, ISC_FALSE, &source);
+ else
+ result = ISC_R_SUCCESS;
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_usedregion(&source, &r);
+ if (r.length > 0)
+ printf("%.*s\n", (int)r.length, r.base);
+ else
+ printf("<empty text name>\n");
+ } else
+ printf("error: %s\n", dns_result_totext(result));
+}
+
+int
+main(int argc, char *argv[]) {
+ char s[1000];
+ isc_result_t result;
+ dns_fixedname_t wname, wname2, oname, compname, downname;
+ isc_buffer_t source;
+ isc_region_t r;
+ dns_name_t *name, *origin, *comp, *down;
+ isc_boolean_t downcase = ISC_FALSE;
+ size_t len;
+ isc_boolean_t quiet = ISC_FALSE;
+ isc_boolean_t concatenate = ISC_FALSE;
+ isc_boolean_t got_name = ISC_FALSE;
+ isc_boolean_t check_absolute = ISC_FALSE;
+ isc_boolean_t check_wildcard = ISC_FALSE;
+ isc_boolean_t test_downcase = ISC_FALSE;
+ isc_boolean_t inplace = ISC_FALSE;
+ isc_boolean_t want_split = ISC_FALSE;
+ unsigned int labels, split_label = 0;
+ dns_fixedname_t fprefix, fsuffix;
+ dns_name_t *prefix, *suffix;
+ int ch;
+
+ while ((ch = isc_commandline_parse(argc, argv, "acdiqs:w")) != -1) {
+ switch (ch) {
+ case 'a':
+ check_absolute = ISC_TRUE;
+ break;
+ case 'c':
+ concatenate = ISC_TRUE;
+ break;
+ case 'd':
+ test_downcase = ISC_TRUE;
+ break;
+ case 'i':
+ inplace = ISC_TRUE;
+ break;
+ case 'q':
+ quiet = ISC_TRUE;
+ break;
+ case 's':
+ want_split = ISC_TRUE;
+ split_label = atoi(isc_commandline_argument);
+ break;
+ case 'w':
+ check_wildcard = ISC_TRUE;
+ break;
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc > 0) {
+ if (strcasecmp("none", argv[0]) == 0)
+ origin = NULL;
+ else {
+ len = strlen(argv[0]);
+ isc_buffer_init(&source, argv[0], len);
+ isc_buffer_add(&source, len);
+ dns_fixedname_init(&oname);
+ origin = &oname.name;
+ result = dns_name_fromtext(origin, &source,
+ dns_rootname, ISC_FALSE,
+ NULL);
+ if (result != 0) {
+ fprintf(stderr,
+ "dns_name_fromtext() failed: %d\n",
+ result);
+ exit(1);
+ }
+ }
+ } else if (concatenate)
+ origin = NULL;
+ else
+ origin = dns_rootname;
+
+ if (argc >= 1) {
+ if (strcasecmp("none", argv[1]) == 0)
+ comp = NULL;
+ else {
+ len = strlen(argv[1]);
+ isc_buffer_init(&source, argv[1], len);
+ isc_buffer_add(&source, len);
+ dns_fixedname_init(&compname);
+ comp = &compname.name;
+ result = dns_name_fromtext(comp, &source,
+ origin, ISC_FALSE, NULL);
+ if (result != 0) {
+ fprintf(stderr,
+ "dns_name_fromtext() failed: %d\n",
+ result);
+ exit(1);
+ }
+ }
+ } else
+ comp = NULL;
+
+ dns_fixedname_init(&wname);
+ name = dns_fixedname_name(&wname);
+ dns_fixedname_init(&wname2);
+ while (fgets(s, sizeof(s), stdin) != NULL) {
+ len = strlen(s);
+ if (len > 0U && s[len - 1] == '\n') {
+ s[len - 1] = '\0';
+ len--;
+ }
+ isc_buffer_init(&source, s, len);
+ isc_buffer_add(&source, len);
+
+ if (len > 0U)
+ result = dns_name_fromtext(name, &source, origin,
+ downcase, NULL);
+ else {
+ if (name == dns_fixedname_name(&wname))
+ dns_fixedname_init(&wname);
+ else
+ dns_fixedname_init(&wname2);
+ result = ISC_R_SUCCESS;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ printf("%s\n", dns_result_totext(result));
+ if (name == dns_fixedname_name(&wname))
+ dns_fixedname_init(&wname);
+ else
+ dns_fixedname_init(&wname2);
+ continue;
+ }
+
+ if (check_absolute && dns_name_countlabels(name) > 0) {
+ if (dns_name_isabsolute(name))
+ printf("absolute\n");
+ else
+ printf("relative\n");
+ }
+ if (check_wildcard && dns_name_countlabels(name) > 0) {
+ if (dns_name_iswildcard(name))
+ printf("wildcard\n");
+ else
+ printf("not wildcard\n");
+ }
+ dns_name_toregion(name, &r);
+ if (!quiet) {
+ print_wirename(&r);
+ printf("%u labels, %u bytes.\n",
+ dns_name_countlabels(name), r.length);
+ }
+
+ if (concatenate) {
+ if (got_name) {
+ printf("Concatenating.\n");
+ result = dns_name_concatenate(&wname.name,
+ &wname2.name,
+ &wname2.name,
+ NULL);
+ name = &wname2.name;
+ if (result == ISC_R_SUCCESS) {
+ if (check_absolute &&
+ dns_name_countlabels(name) > 0) {
+ if (dns_name_isabsolute(name))
+ printf("absolute\n");
+ else
+ printf("relative\n");
+ }
+ if (check_wildcard &&
+ dns_name_countlabels(name) > 0) {
+ if (dns_name_iswildcard(name))
+ printf("wildcard\n");
+ else
+ printf("not "
+ "wildcard\n");
+ }
+ dns_name_toregion(name, &r);
+ if (!quiet) {
+ print_wirename(&r);
+ printf("%u labels, "
+ "%u bytes.\n",
+ dns_name_countlabels(name),
+ r.length);
+ }
+ } else
+ printf("%s\n",
+ dns_result_totext(result));
+ got_name = ISC_FALSE;
+ } else
+ got_name = ISC_TRUE;
+ }
+ isc_buffer_init(&source, s, sizeof(s));
+ if (dns_name_countlabels(name) > 0)
+ result = dns_name_totext(name, ISC_FALSE, &source);
+ else
+ result = ISC_R_SUCCESS;
+ if (result == ISC_R_SUCCESS) {
+ isc_buffer_usedregion(&source, &r);
+ if (r.length > 0)
+ printf("%.*s\n", (int)r.length, r.base);
+ else
+ printf("<empty text name>\n");
+ if (!quiet) {
+ printf("%u bytes.\n", source.used);
+ }
+ } else
+ printf("%s\n", dns_result_totext(result));
+
+ if (test_downcase) {
+ if (inplace) {
+ down = name;
+ } else {
+ dns_fixedname_init(&downname);
+ down = dns_fixedname_name(&downname);
+ }
+ result = dns_name_downcase(name, down, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+ if (!quiet) {
+ dns_name_toregion(down, &r);
+ print_wirename(&r);
+ printf("%u labels, %u bytes.\n",
+ dns_name_countlabels(down),
+ r.length);
+ }
+ isc_buffer_init(&source, s, sizeof(s));
+ print_name(down);
+ }
+
+ if (comp != NULL && dns_name_countlabels(name) > 0) {
+ int order;
+ unsigned int nlabels;
+ dns_namereln_t namereln;
+
+ namereln = dns_name_fullcompare(name, comp, &order,
+ &nlabels);
+ if (!quiet) {
+ if (order < 0)
+ printf("<");
+ else if (order > 0)
+ printf(">");
+ else
+ printf("=");
+ switch (namereln) {
+ case dns_namereln_contains:
+ printf(", contains");
+ break;
+ case dns_namereln_subdomain:
+ printf(", subdomain");
+ break;
+ case dns_namereln_commonancestor:
+ printf(", common ancestor");
+ break;
+ default:
+ break;
+ }
+ if (namereln != dns_namereln_none &&
+ namereln != dns_namereln_equal)
+ printf(", nlabels = %u", nlabels);
+ printf("\n");
+ }
+ printf("dns_name_equal() returns %s\n",
+ dns_name_equal(name, comp) ? "TRUE" : "FALSE");
+ }
+
+ labels = dns_name_countlabels(name);
+ if (want_split && split_label < labels) {
+ dns_fixedname_init(&fprefix);
+ prefix = dns_fixedname_name(&fprefix);
+ dns_fixedname_init(&fsuffix);
+ suffix = dns_fixedname_name(&fsuffix);
+ printf("splitting at label %u: ", split_label);
+ dns_name_split(name, split_label, prefix, suffix);
+ printf("\n prefix = ");
+ print_name(prefix);
+ printf(" suffix = ");
+ print_name(suffix);
+ }
+
+ if (concatenate) {
+ if (got_name)
+ name = &wname2.name;
+ else
+ name = &wname.name;
+ }
+ }
+
+ return (0);
+}
diff --git a/bin/tests/named.conf b/bin/tests/named.conf
new file mode 100644
index 0000000..1f96981
--- /dev/null
+++ b/bin/tests/named.conf
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.conf,v 1.58 2007/06/19 23:46:59 tbox Exp $ */
+
+/*
+ * This is a worthless, nonrunnable example of a named.conf file that has
+ * every conceivable syntax element in use. We use it to test the parser.
+ * It could also be used as a conceptual template for users of new features.
+ */
+
+/*
+ * C-style comments are OK
+ */
+
+// So are C++-style comments
+
+# So are shell-style comments
+
+// watch out for ";" -- it's important!
+
+options {
+ additional-from-auth true;
+ additional-from-cache false;
+
+ version "my version string";
+ random-device "/dev/random";
+ directory "/tmp";
+
+ port 666;
+
+ sig-validity-interval 33;
+
+# Obsolete
+ named-xfer "/usr/libexec/named-xfer"; // _PATH_XFER
+
+ dump-file "named_dump.db"; // _PATH_DUMPFILE
+ pid-file "/var/run/named.pid"; // _PATH_PIDFILE
+ statistics-file "named.stats"; // _PATH_STATS
+ memstatistics-file "named.memstats"; // _PATH_MEMSTATS
+
+ max-cache-ttl 999;
+ auth-nxdomain yes; // always set AA on NXDOMAIN.
+ // don't set this to 'no' unless
+ // you know what you're doing -- older
+ // servers won't like it.
+
+# Obsolete
+ deallocate-on-exit no;
+
+ dialup yes;
+
+# Obsolete
+ fake-iquery no;
+
+ fetch-glue yes;
+ has-old-clients yes;
+ host-statistics no;
+
+# Obsolete
+ multiple-cnames no; // if yes, then a name my have more
+ // than one CNAME RR. This use
+ // is non-standard and is not
+ // recommended, but it is available
+ // because previous releases supported
+ // it and it was used by large sites
+ // for load balancing.
+
+ notify yes; // send NOTIFY messages. You can set
+ // notify on a zone-by-zone
+ // basis in the "zone" statement
+ // see (below)
+ recursion yes;
+ rfc2308-type1 no;
+
+# Obsolete
+ use-id-pool yes;
+
+# Obsolete
+ treat-cr-as-space yes;
+
+ also-notify { 10.0.2.3; };
+
+ // The "forward" option is only meaningful if you've defined
+ // forwarders. "first" gives the normal BIND
+ // forwarding behavior, i.e. ask the forwarders first, and if that
+ // doesn't work then do the full lookup. You can also say
+ // "forward only;" which is what used to be specified with
+ // "slave" or "options forward-only". "only" will never attempt
+ // a full lookup; only the forwarders will be used.
+ forward first;
+ forwarders {
+ 1.2.3.4;
+ 5.6.7.8;
+ };
+
+ check-names master fail;
+ check-names slave warn;
+ check-names response ignore;
+
+ allow-query { any; };
+ allow-transfer { any; };
+ allow-recursion { !any; };
+ blackhole { 45/24; };
+
+ listen-on {
+ 10/24;
+ 10.0.0.3;
+ };
+
+ listen-on port 53 { any; };
+
+ listen-on { 5.6.7.8; };
+
+ listen-on port 1234 {
+ !1.2.3.4;
+ 1.2.3/24;
+ };
+
+ listen-on-v6 {
+ 1:1:1:1:1:1:1:1;
+ };
+
+ listen-on-v6 port 777 {
+ 2:2:2:2:2:2:2:2;
+ };
+
+ query-source-v6 address 8:7:6:5:4:3:2:1 port *;
+ query-source port * address 10.0.0.54 ;
+
+ lame-ttl 444;
+
+ max-transfer-time-in 300;
+ max-transfer-time-out 10;
+ max-transfer-idle-in 100;
+ max-transfer-idle-out 11;
+
+ max-retry-time 1234;
+ min-retry-time 1111;
+ max-refresh-time 888;
+ min-refresh-time 777;
+
+ max-ncache-ttl 333;
+ min-roots 15;
+ serial-queries 34;
+
+ transfer-format one-answer;
+
+ transfers-in 10;
+ transfers-per-ns 2;
+ transfers-out 0;
+
+ transfer-source 10.0.0.5;
+ transfer-source-v6 4:3:2:1:5:6:7:8;
+
+ request-ixfr yes;
+ provide-ixfr yes;
+
+# Now called 'provide-ixfr'
+# maintain-ixfr-base no; // If yes, keep transaction log file for IXFR
+
+ max-ixfr-log-size 20m;
+ coresize 100;
+ datasize 101;
+ files 230;
+ max-cache-size 1m;
+ stacksize 231;
+ cleaning-interval 1000;
+ heartbeat-interval 1001;
+ interface-interval 1002;
+ statistics-interval 1003;
+
+ topology {
+ 10/8;
+
+ !1.2.3/24;
+
+ { 1.2/16; 3/8; };
+
+
+ };
+
+ sortlist { 10/8; 11/8; };
+
+ tkey-domain "foo.com";
+ tkey-dhkey "xyz" 666 ;
+
+ rrset-order {
+ class IN type A name "foo" order random;
+ order cyclic;
+ };
+};
+
+/*
+ * Control listeners, for "ndc". Every nameserver needs at least one.
+ */
+controls {
+ // 'inet' lines without a 'port' defaults to 'port 953'
+ // 'keys' must be used and the list must have at least one entry
+ inet * port 52 allow { any; } keys { "key2"; };
+ unix "/var/run/ndc" perm 0600 owner 0 group 0; // ignored by named.
+ inet 10.0.0.1 allow { any; key foo; } keys { "key4";};
+ inet 10.0.0.2 allow { none; } keys { "key-1"; "key-2"; };
+ inet 10.0.0.2 allow { none; };
+};
+
+zone "master.demo.zone" {
+ type master; // what used to be called "primary"
+ database "somedb -option1 -option2 arg1 arg2 arg3";
+ file "master.demo.zone";
+ check-names fail;
+ allow-update { none; };
+ allow-update-forwarding { 10.0.0.5; !any; };
+ allow-transfer { any; };
+ allow-query { any; };
+ sig-validity-interval 990;
+ notify explicit;
+ also-notify { 1.0.0.1; }; // don't notify any nameservers other
+ // than those on the NS list for this
+ // zone
+ forward first;
+ forwarders { 10.0.0.3; 1:2:3:4:5:6:7:8; };
+};
+
+zone "slave.demo.zone" {
+ type slave; // what used to be called "secondary"
+ file "slave.demo.zone";
+ ixfr-base "slave.demo.zone.ixfr"; // File name for IXFR transaction log file
+ masters {
+ 1.2.3.4 port 10 key "foo"; // where to zone transfer from
+ 5.6.7.8;
+ 6.7.8.9 key "zippo";
+ };
+ transfer-source 10.0.0.53; // fixes multihoming problems
+ check-names warn;
+ allow-update { none; };
+ allow-transfer { any; };
+ allow-update-forwarding { any; };
+ allow-query { any; };
+ max-transfer-time-in 120; // if not set, global option is used.
+ max-transfer-time-out 1; // if not set, global option is used.
+ max-transfer-idle-in 2; // if not set, global option is used.
+ max-transfer-idle-out 3; // if not set, global option is used.
+ also-notify { 1.0.0.2; };
+ forward only;
+ forwarders { 10.45.45.45; 10.0.0.3; 1:2:3:4:5:6:7:8; };
+};
+
+key "non-viewkey" { secret "YWFh" ; algorithm "zzz" ; };
+
+view "test-view" in {
+ key "viewkey" { algorithm "xxx" ; secret "eXl5" ; };
+ also-notify { 10.2.2.3; };
+ trusted-keys {
+ foo.com. 4 3 2 "abdefghijklmnopqrstuvwxyz";
+ };
+ sig-validity-interval 45;
+ max-cache-size 100000;
+ allow-query { 10.0.0.30;};
+ additional-from-cache false;
+ additional-from-auth no;
+ match-clients { 10.0.0.1 ; };
+ check-names master warn;
+ check-names slave ignore;
+ check-names response fail;
+ auth-nxdomain false;
+ recursion true;
+ provide-ixfr false;
+ request-ixfr true;
+ fetch-glue true;
+ notify false;
+ rfc2308-type1 false;
+ transfer-source 10.0.0.55;
+ transfer-source-v6 4:3:8:1:5:6:7:8;
+ query-source port * address 10.0.0.54 ;
+ query-source-v6 address 6:6:6:6:6:6:6:6 port *;
+ max-transfer-time-out 45;
+ max-transfer-idle-out 55;
+ cleaning-interval 100;
+ min-roots 3;
+ lame-ttl 477;
+ max-ncache-ttl 333;
+ max-cache-ttl 777;
+ transfer-format many-answers;
+ max-retry-time 7;
+ min-retry-time 4;
+ max-refresh-time 999;
+ min-refresh-time 111;
+
+ zone "view-zone.com" {
+ type master;
+ allow-update-forwarding { 10.0.0.34;};
+ file "view-zone-master";
+ };
+
+ server 5.6.7.8 {
+ keys "viewkey";
+ };
+
+ server 10.9.8.7 {
+ keys "non-viewkey";
+ };
+ dialup yes;
+};
+
+
+zone "stub.demo.zone" {
+ type stub; // stub zones are like slave zones,
+ // except that only the NS records
+ // are transferred.
+ dialup yes;
+ file "stub.demo.zone";
+ masters {
+ 1.2.3.4 ; // where to zone transfer from
+ 5.6.7.8 port 999;
+ };
+ check-names warn;
+ allow-update { none; };
+ allow-transfer { any; };
+ allow-query { any; };
+
+ max-retry-time 10;
+ min-retry-time 11;
+ max-refresh-time 12;
+ min-refresh-time 13;
+
+ max-transfer-time-in 120; // if not set, global option is used.
+ pubkey 257 255 1 "a useless key";
+ pubkey 257 255 1 "another useless key";
+};
+
+zone "." {
+ type hint; // used to be specified w/ "cache"
+ file "cache.db";
+// pubkey 257 255 1 "AQP2fHpZ4VMpKo/jc9Fod821uyfY5p8j5h/Am0V/KpBTMZjdXmp9QJe6yFRoIIzkaNCgTIftASdpXGgCwFB2j2KXP/rick6gvEer5VcDEkLR5Q==";
+};
+
+trusted-keys {
+ "." 257 255 1 "AQP2fHpZ4VMpKo/jc9Fod821uyfY5p8j5h/Am0V/KpBTMZjdXmp9QJe6yFRoIIzkaNCgTIftASdpXGgCwFB2j2KXP/rick6gvEer5VcDEkLR5Q==";
+};
+
+
+acl can_query { !1.2.3/24; any; }; // network 1.2.3.0 mask 255.255.255.0
+ // is disallowed; rest are OK
+acl can_axfr { 1.2.3.4; can_query; }; // host 1.2.3.4 and any host allowed
+ // by can_query are OK
+
+zone "disabled-zone.com" {
+ type master;
+ file "bar";
+
+ max-retry-time 100;
+ min-retry-time 110;
+ max-refresh-time 120;
+ min-refresh-time 130;
+};
+
+zone "non-default-acl.demo.zone" {
+ type master;
+ file "foo";
+ allow-query { can_query; };
+ allow-transfer { can_axfr; };
+ allow-update {
+ 1.2.3.4;
+ 5.6.7.8;
+ };
+ pubkey 666 665 664 "key of the beast";
+ // Errors trapped by parser:
+ // identity or name not absolute
+ // 'wildcard' match type and no wildcard character in name
+ //
+ // issues:
+ // - certain rdatatype values (such as "key") are config file keywords and
+ // must be quoted or a syntax error will occur.
+ //
+
+ update-policy {
+ grant root.domain. subdomain host.domain. A MX CNAME;
+ grant sub.root.domain. wildcard *.host.domain. A;
+ grant root.domain. name host.domain. a ns md mf cname soa mb mg
+ mr "null" wks ptr hinfo minfo mx txt rp afsdb x25
+ isdn rt nsap sig "key" px gpos aaaa loc nxt srv naptr kx
+ cert a6 dname opt unspec tkey tsig ;
+ grant foo.bar.com. self foo.bar.com. a;
+ };
+};
+
+key sample_key { // for TSIG; supported by parser
+ algorithm hmac-md5; // but not yet implemented in the
+ secret "eW91ciBzZWNyZXQgaGVyZQ=="; // rest of the server
+};
+
+key key2 {
+ algorithm hmac-md5;
+ secret "ZXJlaCB0ZXJjZXMgcm91eQ==";
+};
+
+acl key_acl { key sample_key; }; // a request signed with sample_key
+
+server 1.2.3.4 {
+ request-ixfr no;
+ provide-ixfr no;
+ bogus no; // if yes, we won't query or listen
+ // to this server
+ transfer-format one-answer; // set transfer format for this
+ // server (see the description of
+ // 'transfer-format' above)
+ // if not specified, the global option
+ // will be used
+ transfers 0; // not implemented
+ keys { "sample_key" }; // for TSIG; supported by the parser
+ // but not yet implemented in the
+ // rest of the server
+# Now called 'request-ixfr'
+# support-ixfr yes; // for IXFR supported by server
+ // if yes, the listed server talks IXFR
+};
+
+logging {
+ /*
+ * All log output goes to one or more "channels"; you can make as
+ * many of them as you want.
+ */
+
+ channel syslog_errors { // this channel will send errors or
+ syslog user; // or worse to syslog (user facility)
+ severity error;
+ };
+
+ channel stderr_errors {
+ stderr;
+ };
+
+ /*
+ * Channels have a severity level. Messages at severity levels
+ * greater than or equal to the channel's level will be logged on
+ * the channel. In order of decreasing severity, the levels are:
+ *
+ * critical a fatal error
+ * error
+ * warning
+ * notice a normal, but significant event
+ * info an informational message
+ * debug 1 the least detailed debugging info
+ * ...
+ * debug 99 the most detailed debugging info
+ */
+
+ /*
+ * Here are the built-in channels:
+ *
+ * channel default_syslog {
+ * syslog daemon;
+ * severity info;
+ * };
+ *
+ * channel default_debug {
+ * file "named.run"; // note: stderr is used instead
+ * // of "named.run" if the server
+ * // is started with the "-f"
+ * // option.
+ * severity dynamic; // this means log debugging
+ * // at whatever debugging level
+ * // the server is at, and don't
+ * // log anything if not
+ * // debugging.
+ * };
+ *
+ * channel null { // this is the bit bucket;
+ * file "/dev/null"; // any logging to this channel
+ * // is discarded.
+ * };
+ *
+ * channel default_stderr { // writes to stderr
+ * file "<stderr>"; // this is illustrative only;
+ * // there's currently no way
+ * // of saying "stderr" in the
+ * // configuration language.
+ * // i.e. don't try this at home.
+ * severity info;
+ * };
+ *
+ * default_stderr only works before the server daemonizes (i.e.
+ * during initial startup) or when it is running in foreground
+ * mode (-f command line option).
+ */
+
+ /*
+ * There are many categories, so you can send the logs
+ * you want to see wherever you want, without seeing logs you
+ * don't want. Right now the categories are
+ *
+ * default the catch-all. many things still
+ * aren't classified into categories, and
+ * they all end up here. also, if you
+ * don't specify any channels for a
+ * category, the default category is used
+ * instead.
+ * config high-level configuration file
+ * processing
+ * parser low-level configuration file processing
+ * queries what used to be called "query logging"
+ * lame-servers messages like "Lame server on ..."
+ * statistics
+ * panic if the server has to shut itself
+ * down due to an internal problem, it
+ * logs the problem here (as well as
+ * in the problem's native category)
+ * update dynamic update
+ * ncache negative caching
+ * xfer-in zone transfers we're receiving
+ * xfer-out zone transfers we're sending
+ * db all database operations
+ * eventlib debugging info from the event system
+ * (see below)
+ * packet dumps of packets received and sent
+ * (see below)
+ * notify the NOTIFY protocol
+ * cname messages like "XX points to a CNAME"
+ * security approved/unapproved requests
+ * os operating system problems
+ * insist consistency check failures
+ * maintenance periodic maintenance
+ * load zone loading
+ * response-checks messages like
+ * "Malformed response ..."
+ * "wrong ans. name ..."
+ * "unrelated additional info ..."
+ * "invalid RR type ..."
+ * "bad referral ..."
+ */
+
+ category parser {
+ syslog_errors; // you can log to as many channels
+ default_syslog; // as you want
+ };
+
+ category lame-servers { null; }; // don't log these at all
+
+ channel moderate_debug {
+ file "foo"; // foo
+ severity debug 3; // level 3 debugging to file
+ print-time yes; // timestamp log entries
+ print-category yes; // print category name
+ print-severity yes; // print severity level
+ /*
+ * Note that debugging must have been turned on either
+ * on the command line or with a signal to get debugging
+ * output (non-debugging output will still be written to
+ * this channel).
+ */
+ };
+
+ channel another {
+ file "bar" versions 99 size 10M;
+ severity info;
+ };
+
+ channel third {
+ file "bar" size 100000 versions unlimited;
+ severity debug; // use default debug level
+ };
+
+ /*
+ * If you don't want to see "zone XXXX loaded" messages but do
+ * want to see any problems, you could do the following.
+ */
+ channel no_info_messages {
+ syslog;
+ severity notice;
+ };
+
+ category load { no_info_messages; };
+
+ /*
+ * You can also define category "default"; it gets used when no
+ * "category" statement has been given for a category.
+ */
+ category default {
+ default_syslog;
+ moderate_debug;
+ };
+
+ /*
+ * If you don't define category default yourself, the default
+ * default category will be used. It is
+ *
+ * category default { default_syslog; default_debug; };
+ */
+
+ /*
+ * If you don't define category panic yourself, the default
+ * panic category will be used. It is
+ *
+ * category panic { default_syslog; default_stderr; };
+ */
+
+ /*
+ * Two categories, 'packet' and 'eventlib', are special. Only one
+ * channel may be assigned to each of them, and it must be a
+ * file channel. If you don't define them yourself, they default to
+ *
+ * category eventlib { default_debug; };
+ *
+ * category packet { default_debug; };
+ */
+};
+
+#include "filename"; // can't do within a statement
+
diff --git a/bin/tests/names/Makefile.in b/bin/tests/names/Makefile.in
new file mode 100644
index 0000000..31b12fe
--- /dev/null
+++ b/bin/tests/names/Makefile.in
@@ -0,0 +1,58 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-2002 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.28 2007/06/19 23:47:00 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+# Note that we do not want to use libtool for libt_api
+DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../../lib/isc/libisc.@A@
+
+DNSDEPLIBS = ../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+TLIB = ../../../lib/tests/libt_api.@A@
+
+TARGETS = t_names@EXEEXT@
+
+SRCS = t_names.c
+
+@BIND9_MAKE_RULES@
+
+t_names@EXEEXT@: t_names.@O@ ${DEPLIBS} ${TLIB}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_names.@O@ ${TLIB} ${LIBS}
+
+test: t_names@EXEEXT@
+ -@./t_names@EXEEXT@ -c @top_srcdir@/t_config -b @srcdir@ -a
+
+testhelp:
+ @./t_names@EXEEXT@ -h
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/names/dns_name_compare_data b/bin/tests/names/dns_name_compare_data
new file mode 100644
index 0000000..0467fcf
--- /dev/null
+++ b/bin/tests/names/dns_name_compare_data
@@ -0,0 +1,11 @@
+#
+# test data for dns_name_compare
+# format:
+# <name1> <tab> <name2> <tab> <exp_order>
+# where: exp_order may be one of: -1, 0, 1
+#
+# and where: exp_nlabels and exp_nbits are not tested if < 0
+#
+c.d a.b.c.d -1
+a.b.c.d c.d 1
+a.b.c a.b.c 0
diff --git a/bin/tests/names/dns_name_countlabels_data b/bin/tests/names/dns_name_countlabels_data
new file mode 100644
index 0000000..f11c387
--- /dev/null
+++ b/bin/tests/names/dns_name_countlabels_data
@@ -0,0 +1,10 @@
+#
+# test data for dns_name_countlabels
+# format:
+# <name> <tab> <nlabels>
+#
+c.d 2
+c.d. 3
+a.b.c.d 4
+a.b.c 3
+. 1
diff --git a/bin/tests/names/dns_name_fromregion_data b/bin/tests/names/dns_name_fromregion_data
new file mode 100644
index 0000000..32b4220
--- /dev/null
+++ b/bin/tests/names/dns_name_fromregion_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_name_fromregion
+# format:
+# <test_name>
+# where: exp_order may be one of: -1, 0, 1
+#
+# and where: exp_nlabels and exp_nbits are not tested if < 0
+#
+a.b.c.d.
+a.b.c.d.[A].[aaa.
+Ba\x\aa.b.c\[\[o\\.Z
+Ba\x\aa.b.c\[\[o\\\..\.Z
diff --git a/bin/tests/names/dns_name_fromtext_data b/bin/tests/names/dns_name_fromtext_data
new file mode 100644
index 0000000..16554a5
--- /dev/null
+++ b/bin/tests/names/dns_name_fromtext_data
@@ -0,0 +1,9 @@
+#
+# test data for dns_name_fromtext
+# format:
+# <name1> <tab> <name2> <tab> <origin> <tab> <downcase>
+#
+a.b a.b.c.d C.d 1
+a.b a.b.c.d C.d 1
+a.b a.b.C.d C.d 0
+a.b. a.b. C.d 0
diff --git a/bin/tests/names/dns_name_fromwire_1_data b/bin/tests/names/dns_name_fromwire_1_data
new file mode 100644
index 0000000..b7ae69b
--- /dev/null
+++ b/bin/tests/names/dns_name_fromwire_1_data
@@ -0,0 +1,30 @@
+#
+# test data for dns_name_fromwire_1
+# format:
+# <msgfile> <testname_offset> <downcase>
+# <dc_method> <exp_name> <exp_result>
+#
+# where msgfile contains a DNS message in hex form
+#
+# and where testname_offset is the byte offset in this message of
+# the start of a name
+#
+# and where downcase is 1 or 0
+#
+# and where dc_method is one of
+# DNS_COMPRESS_ALL
+# DNS_COMPRESS_GLOBAL14
+# DNS_COMPRESS_NONE
+#
+# and where exp_name is the expected name after any decompression
+# or case conversion
+#
+# and where exp_result may be one of
+# ISC_R_NOSPACE
+# DNS_R_BADLABELTYPE
+# DNS_R_DISALLOWED
+# DNS_R_BADPOINTER
+# ISC_R_UNEXPECTEDEND
+# DNS_R_TOOMANYHOPS
+#
+wire_test1.data 25 1 DNS_COMPRESS_ALL vix.com. ISC_R_SUCCESS
diff --git a/bin/tests/names/dns_name_fromwire_2_data b/bin/tests/names/dns_name_fromwire_2_data
new file mode 100644
index 0000000..90dfec4
--- /dev/null
+++ b/bin/tests/names/dns_name_fromwire_2_data
@@ -0,0 +1,30 @@
+#
+# test data for dns_name_fromwire_2
+# format:
+# <msgfile> <testname_offset> <downcase>
+# <dc_method> <exp_name> <exp_result>
+#
+# where msgfile contains a DNS message in hex form
+#
+# and where testname_offset is the byte offset in this message of
+# the start of a name
+#
+# and where downcase is 1 or 0
+#
+# and where dc_method is one of
+# DNS_COMPRESS_ALL
+# DNS_COMPRESS_GLOBAL14
+# DNS_COMPRESS_NONE
+#
+# and where exp_name is the expected name after any decompression
+# or case conversion
+#
+# and where exp_result may be one of
+# ISC_R_NOSPACE
+# DNS_R_BADLABELTYPE
+# DNS_R_DISALLOWED
+# DNS_R_BADPOINTER
+# ISC_R_UNEXPECTEDEND
+# DNS_R_TOOMANYHOPS
+#
+wire_test2.data 25 1 DNS_COMPRESS_ALL vix.com. ISC_R_NOSPACE
diff --git a/bin/tests/names/dns_name_fromwire_3_data b/bin/tests/names/dns_name_fromwire_3_data
new file mode 100644
index 0000000..f4253b4
--- /dev/null
+++ b/bin/tests/names/dns_name_fromwire_3_data
@@ -0,0 +1,31 @@
+#
+# test data for dns_name_fromwire_3
+# format:
+# <msgfile> <testname_offset> <downcase>
+# <dc_method> <exp_name> <exp_result>
+#
+# where msgfile contains a DNS message in hex form
+#
+# and where testname_offset is the byte offset in this message of
+# the start of a name
+#
+# and where downcase is 1 or 0
+#
+# and where dc_method is one of
+# DNS_COMPRESS_ALL
+# DNS_COMPRESS_GLOBAL14
+# DNS_COMPRESS_NONE
+#
+# and where exp_name is the expected name after any decompression
+# or case conversion
+#
+# and where exp_result may be one of
+# ISC_R_NOSPACE
+# DNS_R_BADLABELTYPE
+# DNS_R_DISALLOWED
+# DNS_R_BADPOINTER
+# ISC_R_UNEXPECTEDEND
+# DNS_R_TOOMANYHOPS
+#
+wire_test3_1.data 25 1 DNS_COMPRESS_ALL vix.com. DNS_R_BADLABELTYPE
+wire_test3_2.data 25 1 DNS_COMPRESS_ALL vix.com. DNS_R_BADLABELTYPE
diff --git a/bin/tests/names/dns_name_fromwire_4_data b/bin/tests/names/dns_name_fromwire_4_data
new file mode 100644
index 0000000..b76b326
--- /dev/null
+++ b/bin/tests/names/dns_name_fromwire_4_data
@@ -0,0 +1,30 @@
+#
+# test data for dns_name_fromwire_4
+# format:
+# <msgfile> <testname_offset> <downcase>
+# <dc_method> <exp_name> <exp_result>
+#
+# where msgfile contains a DNS message in hex form
+#
+# and where testname_offset is the byte offset in this message of
+# the start of a name
+#
+# and where downcase is 1 or 0
+#
+# and where dc_method is one of
+# DNS_COMPRESS_ALL
+# DNS_COMPRESS_GLOBAL14
+# DNS_COMPRESS_NONE
+#
+# and where exp_name is the expected name after any decompression
+# or case conversion
+#
+# and where exp_result may be one of
+# ISC_R_NOSPACE
+# DNS_R_BADLABELTYPE
+# DNS_R_DISALLOWED
+# DNS_R_BADPOINTER
+# ISC_R_UNEXPECTEDEND
+# DNS_R_TOOMANYHOPS
+#
+wire_test4.data 550 1 DNS_COMPRESS_ALL vix.com. DNS_R_NAMETOOLONG
diff --git a/bin/tests/names/dns_name_fromwire_5_data b/bin/tests/names/dns_name_fromwire_5_data
new file mode 100644
index 0000000..1a4221b
--- /dev/null
+++ b/bin/tests/names/dns_name_fromwire_5_data
@@ -0,0 +1,30 @@
+#
+# test data for dns_name_fromwire_5
+# format:
+# <msgfile> <testname_offset> <downcase>
+# <dc_method> <exp_name> <exp_result>
+#
+# where msgfile contains a DNS message in hex form
+#
+# and where testname_offset is the byte offset in this message of
+# the start of a name
+#
+# and where downcase is 1 or 0
+#
+# and where dc_method is one of
+# DNS_COMPRESS_ALL
+# DNS_COMPRESS_GLOBAL14
+# DNS_COMPRESS_NONE
+#
+# and where exp_name is the expected name after any decompression
+# or case conversion
+#
+# and where exp_result may be one of
+# ISC_R_NOSPACE
+# DNS_R_BADLABELTYPE
+# DNS_R_DISALLOWED
+# DNS_R_BADPOINTER
+# ISC_R_UNEXPECTEDEND
+# DNS_R_TOOMANYHOPS
+#
+wire_test5.data 25 1 DNS_COMPRESS_NONE vix.com. DNS_R_DISALLOWED
diff --git a/bin/tests/names/dns_name_fromwire_6_data b/bin/tests/names/dns_name_fromwire_6_data
new file mode 100644
index 0000000..e4460ce
--- /dev/null
+++ b/bin/tests/names/dns_name_fromwire_6_data
@@ -0,0 +1,30 @@
+#
+# test data for dns_name_fromwire_6
+# format:
+# <msgfile> <testname_offset> <downcase>
+# <dc_method> <exp_name> <exp_result>
+#
+# where msgfile contains a DNS message in hex form
+#
+# and where testname_offset is the byte offset in this message of
+# the start of a name
+#
+# and where downcase is 1 or 0
+#
+# and where dc_method is one of
+# DNS_COMPRESS_ALL
+# DNS_COMPRESS_GLOBAL14
+# DNS_COMPRESS_NONE
+#
+# and where exp_name is the expected name after any decompression
+# or case conversion
+#
+# and where exp_result may be one of
+# ISC_R_NOSPACE
+# DNS_R_BADLABELTYPE
+# DNS_R_DISALLOWED
+# DNS_R_BADPOINTER
+# ISC_R_UNEXPECTEDEND
+# DNS_R_TOOMANYHOPS
+#
+wire_test6.data 25 1 DNS_COMPRESS_ALL vix.com. DNS_R_BADPOINTER
diff --git a/bin/tests/names/dns_name_fromwire_7_data b/bin/tests/names/dns_name_fromwire_7_data
new file mode 100644
index 0000000..5828bfc
--- /dev/null
+++ b/bin/tests/names/dns_name_fromwire_7_data
@@ -0,0 +1,30 @@
+#
+# test data for dns_name_fromwire_7
+# format:
+# <msgfile> <testname_offset> <downcase>
+# <dc_method> <exp_name> <exp_result>
+#
+# where msgfile contains a DNS message in hex form
+#
+# and where testname_offset is the byte offset in this message of
+# the start of a name
+#
+# and where downcase is 1 or 0
+#
+# and where dc_method is one of
+# DNS_COMPRESS_ALL
+# DNS_COMPRESS_GLOBAL14
+# DNS_COMPRESS_NONE
+#
+# and where exp_name is the expected name after any decompression
+# or case conversion
+#
+# and where exp_result may be one of
+# ISC_R_NOSPACE
+# DNS_R_BADLABELTYPE
+# DNS_R_DISALLOWED
+# DNS_R_BADPOINTER
+# ISC_R_UNEXPECTEDEND
+# DNS_R_TOOMANYHOPS
+#
+wire_test7.data 25 1 DNS_COMPRESS_ALL vix.com. ISC_R_UNEXPECTEDEND
diff --git a/bin/tests/names/dns_name_fromwire_8_data b/bin/tests/names/dns_name_fromwire_8_data
new file mode 100644
index 0000000..9ddd3f3
--- /dev/null
+++ b/bin/tests/names/dns_name_fromwire_8_data
@@ -0,0 +1,30 @@
+#
+# test data for dns_name_fromwire_9
+# format:
+# <msgfile> <testname_offset> <downcase>
+# <dc_method> <exp_name> <exp_result>
+#
+# where msgfile contains a DNS message in hex form
+#
+# and where testname_offset is the byte offset in this message of
+# the start of a name
+#
+# and where downcase is 1 or 0
+#
+# and where dc_method is one of
+# DNS_COMPRESS_ALL
+# DNS_COMPRESS_GLOBAL14
+# DNS_COMPRESS_NONE
+#
+# and where exp_name is the expected name after any decompression
+# or case conversion
+#
+# and where exp_result may be one of
+# ISC_R_NOSPACE
+# DNS_R_BADLABELTYPE
+# DNS_R_DISALLOWED
+# DNS_R_BADPOINTER
+# ISC_R_UNEXPECTEDEND
+# DNS_R_TOOMANYHOPS
+#
+wire_test8.data 25 1 DNS_COMPRESS_ALL vix.com. ISC_R_NOSPACE
diff --git a/bin/tests/names/dns_name_fullcompare_data b/bin/tests/names/dns_name_fullcompare_data
new file mode 100644
index 0000000..f40e7e6
--- /dev/null
+++ b/bin/tests/names/dns_name_fullcompare_data
@@ -0,0 +1,10 @@
+#
+# test data for dns_name_fullcompare
+# format:
+# <name1> <tab> <name2> <tab> <exp_reln> <tab> <exp_order> <tab> <exp_nlabels> <tab> <exp_nbits>
+# where: exp_reln may be one of:
+# none, equal, contains, subdomain, commonancestor
+# and where: exp_nlabels and exp_nbits are not tested if < 0
+#
+c.d a.b.c.d contains -1 2 0
+a.b.c.d c.d subdomain 1 2 0
diff --git a/bin/tests/names/dns_name_getlabel_data b/bin/tests/names/dns_name_getlabel_data
new file mode 100644
index 0000000..d8dc880
--- /dev/null
+++ b/bin/tests/names/dns_name_getlabel_data
@@ -0,0 +1,10 @@
+#
+# test data for dns_name_compare
+# format:
+# <name1> <tab> <label1_pos> <tab> <name2> <tab> <label2_pos>
+# where: label1_pos and label2_pos identify the label position of
+# the common label shared by name1 and name2 respectively
+#
+c.d 1 a.b.c.d 3
+a.b.c.d 3 c.d 1
+a.b.c. 3 a.b.c. 3
diff --git a/bin/tests/names/dns_name_getlabelsequence_data b/bin/tests/names/dns_name_getlabelsequence_data
new file mode 100644
index 0000000..339604a
--- /dev/null
+++ b/bin/tests/names/dns_name_getlabelsequence_data
@@ -0,0 +1,9 @@
+#
+# test data for dns_name_getlabelsequence
+# format:
+# <name1> <tab> <label1_start> <tab> <name2> <tab> <label2_start> <tab> <extent>
+#
+#
+c.d 1 a.b.c.d 3 1
+a.b.c.d.e 2 c.d 0 2
+a.b.c 0 a.b.c 0 3
diff --git a/bin/tests/names/dns_name_hash_data b/bin/tests/names/dns_name_hash_data
new file mode 100644
index 0000000..093ba45
--- /dev/null
+++ b/bin/tests/names/dns_name_hash_data
@@ -0,0 +1,12 @@
+#
+# test data for dns_name_hash
+# format:
+# <testname1> <tab> <testname2> <tab> <cshm> <tab> <cishm>
+# where:
+# cshm is 0 if a case sensitive hash of testname1 should match a
+# case sensitive hash of testname2, otherwise cshm != 0
+# and:
+# cishm is 0 if a case insensitive hash of testname1 should match a
+# case insensitive hash of testname2, otherwise cishm != 0
+#
+a.b.c.d a.b.c.d. 0 0
diff --git a/bin/tests/names/dns_name_isabsolute_data b/bin/tests/names/dns_name_isabsolute_data
new file mode 100644
index 0000000..a17c9b8
--- /dev/null
+++ b/bin/tests/names/dns_name_isabsolute_data
@@ -0,0 +1,8 @@
+#
+# test data for dns_name_isabsolute
+# format is:
+# <testname> <tab> <expected value>
+#
+x. 1
+a.b.c.d 0
+x.z. 1
diff --git a/bin/tests/names/dns_name_issubdomain_data b/bin/tests/names/dns_name_issubdomain_data
new file mode 100644
index 0000000..102b072
--- /dev/null
+++ b/bin/tests/names/dns_name_issubdomain_data
@@ -0,0 +1,11 @@
+#
+# test data for dns_name_issubdomain
+# format:
+# <name1> <tab> <name2> <tab> <issubdomain>
+# where: issubdomain is 0 if false, else non-zero
+#
+# and where: exp_nlabels and exp_nbits are not tested if < 0
+#
+c.d a.b.c.d 0
+a.b.c.d c.d 1
+a.b.c. a.b.c. 1
diff --git a/bin/tests/names/dns_name_rdatacompare_data b/bin/tests/names/dns_name_rdatacompare_data
new file mode 100644
index 0000000..7f0c6a2
--- /dev/null
+++ b/bin/tests/names/dns_name_rdatacompare_data
@@ -0,0 +1,11 @@
+#
+# test data for dns_name_rdatacompare
+# format:
+# <name1> <tab> <name2> <tab> <exp_order>
+# where: exp_order may be one of: -1, 0, 1
+#
+# and where: exp_nlabels and exp_nbits are not tested if < 0
+#
+c.d. a.b.c.d. 1
+a.b.c.d. c.d. -1
+a.b.c. a.b.c. 0
diff --git a/bin/tests/names/dns_name_toregion_data b/bin/tests/names/dns_name_toregion_data
new file mode 100644
index 0000000..00c10f4
--- /dev/null
+++ b/bin/tests/names/dns_name_toregion_data
@@ -0,0 +1,8 @@
+#
+# test data for dns_name_toregion
+# format:
+# <test_name>
+#
+a.b.c.d.
+a.b.c.d.[A].[aaa.
+Ba\x\aa.b.c\[\[o\\.Z
diff --git a/bin/tests/names/dns_name_totext_data b/bin/tests/names/dns_name_totext_data
new file mode 100644
index 0000000..9db22aa
--- /dev/null
+++ b/bin/tests/names/dns_name_totext_data
@@ -0,0 +1,9 @@
+#
+# test data for dns_name_totext
+# format:
+# <name1> <tab> <omit_final_dot>
+#
+a.b.c.d 1
+a.\\[\[.c.d 1
+a.b.C.d 0
+a.b. 0
diff --git a/bin/tests/names/dns_name_towire_1_data b/bin/tests/names/dns_name_towire_1_data
new file mode 100644
index 0000000..a45d80a
--- /dev/null
+++ b/bin/tests/names/dns_name_towire_1_data
@@ -0,0 +1,17 @@
+# test data for dns_name_towire_1
+# format:
+# <testname> <dc_method> <exp_data>
+# <exp_data_len> <exp_result>
+#
+# where testname is the test name to be converted to wire format
+#
+# and where dc_method is one of
+# DNS_COMPRESS_ALL
+# DNS_COMPRESS_GLOBAL14
+# DNS_COMPRESS_NONE
+#
+# and where exp_data is the expected wire format data in hex format
+# and where exp_data_len is the length of the expected data in decimal format
+# and where exp_result is the expected return value of dns_name_towire
+#
+a.vix.com. DNS_COMPRESS_NONE 01610376697803636f6d00 11 ISC_R_SUCCESS
diff --git a/bin/tests/names/dns_name_towire_2_data b/bin/tests/names/dns_name_towire_2_data
new file mode 100644
index 0000000..35479be
--- /dev/null
+++ b/bin/tests/names/dns_name_towire_2_data
@@ -0,0 +1,17 @@
+# test data for dns_name_towire_1
+# format:
+# <testname> <dc_method> <exp_data>
+# <exp_data_len> <exp_result>
+#
+# where testname is the test name to be converted to wire format
+#
+# and where dc_method is one of
+# DNS_COMPRESS_ALL
+# DNS_COMPRESS_GLOBAL14
+# DNS_COMPRESS_NONE
+#
+# and where exp_data is the expected wire format data in hex format
+# and where exp_data_len is the length of the expected data in decimal format
+# and where exp_result is the expected return value of dns_name_towire
+#
+a.vix.com DNS_COMPRESS_NONE 01610376697803636f6d 10 ISC_R_NOSPACE
diff --git a/bin/tests/names/t_names.c b/bin/tests/names/t_names.c
new file mode 100644
index 0000000..68ce53b
--- /dev/null
+++ b/bin/tests/names/t_names.c
@@ -0,0 +1,2345 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: t_names.c,v 1.46 2008/01/18 23:46:57 tbox Exp $ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+
+#include <dns/compress.h>
+#include <dns/name.h>
+#include <dns/result.h>
+
+#include <tests/t_api.h>
+
+#define MAXTOKS 16
+#define BUFLEN 256
+#define BIGBUFLEN 4096
+
+static char *Tokens[MAXTOKS + 1];
+
+
+#ifdef NEED_PBUF
+
+/*%
+ * get a hex formatted dns message from a data
+ * file into an isc_buffer_t
+ * caller supplies data storage and the isc_buffer
+ * we read the file, convert, setup the buffer
+ * and return the data length
+ */
+
+static char *
+ctoh(unsigned char c) {
+ int val;
+ static char buf[3];
+
+ val = (c >> 4) & 0x0f;
+ if ((0 <= val) && (val <= 9))
+ buf[0] = '0' + val;
+ else if ((10 <= val) && (val <= 16))
+ buf[0] = 'a' + val - 10;
+ val = c & 0x0f;
+ if ((0 <= val) && (val <= 9))
+ buf[1] = '0' + val;
+ else if ((10 <= val) && (val <= 16))
+ buf[1] = 'a' + val - 10;
+ buf[2] = '\0';
+ return (buf);
+}
+
+static void
+pbuf(isc_buffer_t *pbuf) {
+ size_t len;
+ unsigned char *p;
+
+ len = 0;
+ p = pbuf->base;
+ while (len < pbuf->length) {
+ printf("%s", ctoh(*p));
+ ++p;
+ ++len;
+ if ((len % 40) == 0)
+ printf("\n");
+ }
+}
+
+#endif /* NEED_PBUF */
+
+/*%
+ * Compare data at buf with data in hex representation at exp_data,
+ * of length exp_data_len, for equality.
+ * Return 0 if equal, else non-zero.
+ */
+
+static int
+chkdata(unsigned char *buf, size_t buflen, char *exp_data,
+ size_t exp_data_len)
+{
+ int result;
+ unsigned char *p;
+ unsigned char *v;
+ char *q;
+ unsigned char *data;
+ size_t cnt;
+
+ if (buflen == exp_data_len) {
+ data = (unsigned char *)malloc(exp_data_len *
+ sizeof(unsigned char));
+ if (data == NULL) {
+ t_info("malloc failed unexpectedly\n");
+ return (-1);
+ }
+
+ /*
+ * First convert exp_data from hex format.
+ */
+ p = data;
+ q = exp_data;
+ cnt = 0;
+ while (cnt < exp_data_len) {
+
+ if (('0' <= *q) && (*q <= '9'))
+ *p = *q - '0';
+ else if (('a' <= *q) && (*q <= 'z'))
+ *p = *q - 'a' + 10;
+ else if (('A' <= *q) && (*q <= 'Z'))
+ *p = *q - 'A' + 10;
+ ++q;
+
+ *p <<= 4;
+
+ if (('0' <= *q) && (*q <= '9'))
+ *p |= ((*q - '0') & 0x0f);
+ else if (('a' <= *q) && (*q <= 'z'))
+ *p |= ((*q - 'a' + 10) & 0x0f);
+ else if (('A' <= *q) && (*q <= 'Z'))
+ *p |= ((*q - 'A' + 10) & 0x0f);
+ ++p;
+ ++q;
+ ++cnt;
+ }
+
+ /*
+ * Now compare data.
+ */
+ p = buf;
+ v = data;
+ for (cnt = 0; cnt < exp_data_len; ++cnt) {
+ if (*p != *v)
+ break;
+ ++p;
+ ++v;
+ }
+ if (cnt == exp_data_len)
+ result = 0;
+ else {
+ t_info("bad data at position %lu, "
+ "got 0x%.2x, expected 0x%.2x\n",
+ (unsigned long)cnt, *p, *q);
+ result = cnt + 1;
+ }
+ (void)free(data);
+ } else {
+ t_info("data length error, expected %lu, got %lu\n",
+ (unsigned long)exp_data_len, (unsigned long)buflen);
+ result = exp_data_len - buflen;
+ }
+ return (result);
+}
+
+/*%
+ * Get a hex formatted dns message from a data file into an isc_buffer_t.
+ * Caller supplies data storage and the isc_buffer. We read the file, convert,
+ * setup the buffer and return the data length.
+ */
+static int
+getmsg(char *datafile_name, unsigned char *buf, int buflen, isc_buffer_t *pbuf)
+{
+ int c;
+ int len;
+ int cnt;
+ unsigned int val;
+ unsigned char *p;
+ FILE *fp;
+
+ fp = fopen(datafile_name, "r");
+ if (fp == NULL) {
+ t_info("No such file %s\n", datafile_name);
+ return (0);
+ }
+
+ p = buf;
+ cnt = 0;
+ len = 0;
+ val = 0;
+ while ((c = getc(fp)) != EOF) {
+ if ( (c == ' ') || (c == '\t') ||
+ (c == '\r') || (c == '\n'))
+ continue;
+ if (c == '#') {
+ while ((c = getc(fp)) != '\n')
+ ;
+ continue;
+ }
+ if (('0' <= c) && (c <= '9'))
+ val = c - '0';
+ else if (('a' <= c) && (c <= 'z'))
+ val = c - 'a' + 10;
+ else if (('A' <= c) && (c <= 'Z'))
+ val = c - 'A'+ 10;
+ else {
+ (void)fclose(fp);
+ t_info("Bad format in datafile\n");
+ return (0);
+ }
+ if ((len % 2) == 0) {
+ *p = (val << 4);
+ } else {
+ *p += val;
+ ++p;
+ ++cnt;
+ if (cnt >= buflen) {
+ /*
+ * Buffer too small.
+ */
+ (void)fclose(fp);
+ t_info("Buffer overflow error\n");
+ return (0);
+ }
+ }
+ ++len;
+ }
+ (void)fclose(fp);
+
+ if (len % 2) {
+ t_info("Bad format in %s\n", datafile_name);
+ return (0);
+ }
+
+ *p = '\0';
+ isc_buffer_init(pbuf, buf, cnt);
+ isc_buffer_add(pbuf, cnt);
+ return (cnt);
+}
+
+static int
+bustline(char *line, char **toks) {
+ int cnt;
+ char *p;
+
+ cnt = 0;
+ if (line && *line) {
+ while ((p = strtok(line, "\t")) && (cnt < MAXTOKS)) {
+ *toks++ = p;
+ line = NULL;
+ ++cnt;
+ }
+ }
+ return (cnt);
+}
+
+
+#ifdef NEED_HNAME_TO_TNAME
+
+/*%
+ * convert a name from hex representation to text form
+ * format of hex notation is:
+ * %xXXXXXXXX
+ */
+
+static int
+hname_to_tname(char *src, char *target, size_t len) {
+ int i;
+ int c;
+ unsigned int val;
+ size_t srclen;
+ char *p;
+ char *q;
+
+ p = src;
+ srclen = strlen(p);
+ if ((srclen >= 2) && ((*p != '%') || (*(p+1) != 'x'))) {
+ /*
+ * No conversion needed.
+ */
+ if (srclen >= len)
+ return (1);
+ memcpy(target, src, srclen + 1);
+ return (0);
+ }
+
+ i = 0;
+ p += 2;
+ q = target;
+ while (*p) {
+ c = *p;
+ if (('0' < c) && (c <= '9'))
+ val = c - '0';
+ else if (('a' <= c) && (c <= 'z'))
+ val = c + 10 - 'a';
+ else if (('A' <= c) && (c <= 'Z'))
+ val = c + 10 - 'A';
+ else {
+ return (1);
+ }
+ if (i % 2) {
+ *q |= val;
+ ++q;
+ } else
+ *q = (val << 4);
+ ++i;
+ ++p;
+ }
+ if (i % 2) {
+ return (1);
+ } else {
+ *q = '\0';
+ return (0);
+ }
+}
+
+#endif /* NEED_HNAME_TO_TNAME */
+
+/*%
+ * initialize a dns_name_t from a text name, hiding all
+ * buffer and other object initialization from the caller
+ *
+ */
+
+static isc_result_t
+dname_from_tname(char *name, dns_name_t *dns_name) {
+ int len;
+ isc_buffer_t txtbuf;
+ isc_buffer_t *binbuf;
+ unsigned char *junk;
+ isc_result_t result;
+
+ len = strlen(name);
+ isc_buffer_init(&txtbuf, name, len);
+ isc_buffer_add(&txtbuf, len);
+ junk = (unsigned char *)malloc(sizeof(unsigned char) * BUFLEN);
+ binbuf = (isc_buffer_t *)malloc(sizeof(isc_buffer_t));
+ if ((junk != NULL) && (binbuf != NULL)) {
+ isc_buffer_init(binbuf, junk, BUFLEN);
+ dns_name_init(dns_name, NULL);
+ dns_name_setbuffer(dns_name, binbuf);
+ result = dns_name_fromtext(dns_name, &txtbuf,
+ NULL, ISC_FALSE, NULL);
+ } else {
+ result = ISC_R_NOSPACE;
+ if (junk != NULL)
+ (void)free(junk);
+ if (binbuf != NULL)
+ (void)free(binbuf);
+ }
+ return (result);
+}
+
+static const char *a3 = "dns_name_init initializes 'name' to the empty name";
+
+static void
+t_dns_name_init(void) {
+ int rval;
+ int result;
+ dns_name_t name;
+ unsigned char offsets[1];
+
+ rval = 0;
+ t_assert("dns_name_init", 1, T_REQUIRED, a3);
+
+ dns_name_init(&name, offsets);
+ /* magic is hidden in name.c ...
+ if (name.magic != NAME_MAGIC) {
+ t_info("name.magic is not set to NAME_MAGIC\n");
+ ++rval;
+ }
+ */
+ if (name.ndata != NULL) {
+ t_info("name.ndata is not NULL\n");
+ ++rval;
+ }
+ if (name.length != 0) {
+ t_info("name.length is not 0\n");
+ ++rval;
+ }
+ if (name.labels != 0) {
+ t_info("name.labels is not 0\n");
+ ++rval;
+ }
+ if (name.attributes != 0) {
+ t_info("name.attributes is not 0\n");
+ ++rval;
+ }
+ if (name.offsets != offsets) {
+ t_info("name.offsets is incorrect\n");
+ ++rval;
+ }
+ if (name.buffer != NULL) {
+ t_info("name.buffer is not NULL\n");
+ ++rval;
+ }
+
+ if (rval == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+ t_result(result);
+}
+
+static const char *a4 = "dns_name_invalidate invalidates 'name'";
+
+static void
+t_dns_name_invalidate(void) {
+ int rval;
+ int result;
+ dns_name_t name;
+ unsigned char offsets[1];
+
+ t_assert("dns_name_invalidate", 1, T_REQUIRED, a4);
+
+ rval = 0;
+ dns_name_init(&name, offsets);
+ dns_name_invalidate(&name);
+
+ /* magic is hidden in name.c ...
+ if (name.magic != 0) {
+ t_info("name.magic is not set to NAME_MAGIC\n");
+ ++rval;
+ }
+ */
+ if (name.ndata != NULL) {
+ t_info("name.ndata is not NULL\n");
+ ++rval;
+ }
+ if (name.length != 0) {
+ t_info("name.length is not 0\n");
+ ++rval;
+ }
+ if (name.labels != 0) {
+ t_info("name.labels is not 0\n");
+ ++rval;
+ }
+ if (name.attributes != 0) {
+ t_info("name.attributes is not 0\n");
+ ++rval;
+ }
+ if (name.offsets != NULL) {
+ t_info("name.offsets is not NULL\n");
+ ++rval;
+ }
+ if (name.buffer != NULL) {
+ t_info("name.buffer is not NULL\n");
+ ++rval;
+ }
+
+ if (rval == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+ t_result(result);
+}
+
+static const char *a5 = "dns_name_setbuffer dedicates a buffer for use "
+ "with 'name'";
+
+static void
+t_dns_name_setbuffer(void) {
+ int result;
+ unsigned char junk[BUFLEN];
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ t_assert("dns_name_setbuffer", 1, T_REQUIRED, a5);
+
+ isc_buffer_init(&buffer, junk, BUFLEN);
+ dns_name_init(&name, NULL);
+ dns_name_setbuffer(&name, &buffer);
+ if (name.buffer == &buffer)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+
+ t_result(result);
+}
+
+static const char *a6 = "dns_name_hasbuffer returns ISC_TRUE if 'name' has a "
+ "dedicated buffer, otherwise it returns ISC_FALSE";
+
+static void
+t_dns_name_hasbuffer(void) {
+ int result;
+ int rval;
+ unsigned char junk[BUFLEN];
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ t_assert("dns_name_hasbuffer", 1, T_REQUIRED, a6);
+
+ rval = 0;
+ isc_buffer_init(&buffer, junk, BUFLEN);
+ dns_name_init(&name, NULL);
+ if (dns_name_hasbuffer(&name) != ISC_FALSE)
+ ++rval;
+ dns_name_setbuffer(&name, &buffer);
+ if (dns_name_hasbuffer(&name) != ISC_TRUE)
+ ++rval;
+ if (rval == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+
+ t_result(result);
+}
+
+static const char *a7 = "dns_name_isabsolute returns ISC_TRUE if 'name' ends "
+ "in the root label";
+
+static int
+test_dns_name_isabsolute(char *test_name, isc_boolean_t expected) {
+ dns_name_t name;
+ isc_buffer_t buf;
+ isc_buffer_t binbuf;
+ unsigned char junk[BUFLEN];
+ int len;
+ int rval;
+ isc_boolean_t isabs_p;
+ isc_result_t result;
+
+ rval = T_UNRESOLVED;
+
+ t_info("testing name %s\n", test_name);
+ len = strlen(test_name);
+ isc_buffer_init(&buf, test_name, len);
+ isc_buffer_add(&buf, len);
+ isc_buffer_init(&binbuf, &junk[0], BUFLEN);
+ dns_name_init(&name, NULL);
+ dns_name_setbuffer(&name, &binbuf);
+ result = dns_name_fromtext(&name, &buf, NULL, ISC_FALSE, NULL);
+ if (result == ISC_R_SUCCESS) {
+ isabs_p = dns_name_isabsolute(&name);
+ if (isabs_p == expected)
+ rval = T_PASS;
+ else
+ rval = T_FAIL;
+ } else {
+ t_info("dns_name_fromtext %s failed, result = %s\n",
+ test_name, dns_result_totext(result));
+ }
+ return (rval);
+}
+
+static void
+t_dns_name_isabsolute(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_isabsolute", 1, T_REQUIRED, a7);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_isabsolute_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 2) {
+ /*
+ * label, bitpos, expected value.
+ */
+ result = test_dns_name_isabsolute(Tokens[0],
+ atoi(Tokens[1])
+ == 0 ?
+ ISC_FALSE :
+ ISC_TRUE);
+ } else {
+ t_info("bad datafile format at line %d\n",
+ line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_isabsolute_data\n");
+ t_result(result);
+ }
+}
+
+static const char *a8 = "dns_name_hash(name, case_sensitive) returns "
+ "a hash of 'name' which is case_sensitive if case_sensitive "
+ "is true";
+
+/*%
+ * a9 merged with a8.
+ */
+
+static int
+test_dns_name_hash(char *test_name1, char *test_name2,
+ isc_boolean_t csh_match, isc_boolean_t cish_match) {
+ int rval;
+ int failures;
+ isc_boolean_t match;
+ unsigned int hash1;
+ unsigned int hash2;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+ isc_result_t result;
+
+ rval = T_UNRESOLVED;
+ failures = 0;
+
+ t_info("testing names %s and %s\n", test_name1, test_name2);
+
+ result = dname_from_tname(test_name1, &dns_name1);
+ if (result == ISC_R_SUCCESS) {
+ result = dname_from_tname(test_name2, &dns_name2);
+ if (result == ISC_R_SUCCESS) {
+ hash1 = dns_name_hash(&dns_name1, ISC_TRUE);
+ hash2 = dns_name_hash(&dns_name2, ISC_TRUE);
+ match = ISC_FALSE;
+ if (hash1 == hash2)
+ match = ISC_TRUE;
+ if (match != csh_match) {
+ ++failures;
+ t_info("hash mismatch when ISC_TRUE\n");
+ }
+ hash1 = dns_name_hash(&dns_name1, ISC_FALSE);
+ hash2 = dns_name_hash(&dns_name2, ISC_FALSE);
+ match = ISC_FALSE;
+ if (hash1 == hash2)
+ match = ISC_TRUE;
+ if (match != cish_match) {
+ ++failures;
+ t_info("hash mismatch when ISC_FALSE\n");
+ }
+ if (failures == 0)
+ rval = T_PASS;
+ else
+ rval = T_FAIL;
+ } else {
+ t_info("dns_fromtext %s failed, result = %s\n",
+ test_name2, dns_result_totext(result));
+ }
+ } else {
+ t_info("dns_fromtext %s failed, result = %s\n",
+ test_name1, dns_result_totext(result));
+ }
+ return (rval);
+}
+
+static void
+t_dns_name_hash(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_hash", 1, T_REQUIRED, a8);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_hash_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 4) {
+ /*
+ * name1, name2, exp match value if
+ * case_sensitive true,
+ * exp match value of case_sensitive false
+ */
+ result = test_dns_name_hash(
+ Tokens[0],
+ Tokens[1],
+ atoi(Tokens[2]) == 0 ?
+ ISC_FALSE : ISC_TRUE,
+ atoi(Tokens[3]) == 0 ?
+ ISC_FALSE : ISC_TRUE);
+ } else {
+ t_info("bad datafile format at line %d\n",
+ line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_hash_data\n");
+ t_result(result);
+ }
+}
+
+static const char *a10 =
+ "dns_name_fullcompare(name1, name2, orderp, nlabelsp) "
+ "returns the DNSSEC ordering relationship between name1 and "
+ "name2, sets orderp to -1 if name1 < name2, to 0 if "
+ "name1 == name2, or to 1 if name1 > name2, sets nlabelsp "
+ "to the number of labels name1 and name2 have in common, "
+ "and sets nbitsp to the number of bits name1 and name2 "
+ "have in common";
+
+/*%
+ * a11 thru a22 merged into a10.
+ */
+static const char *
+dns_namereln_to_text(dns_namereln_t reln) {
+ const char *p;
+
+ if (reln == dns_namereln_contains)
+ p = "contains";
+ else if (reln == dns_namereln_subdomain)
+ p = "subdomain";
+ else if (reln == dns_namereln_equal)
+ p = "equal";
+ else if (reln == dns_namereln_none)
+ p = "none";
+ else if (reln == dns_namereln_commonancestor)
+ p = "commonancestor";
+ else
+ p = "unknown";
+
+ return (p);
+}
+
+static int
+test_dns_name_fullcompare(char *name1, char *name2,
+ dns_namereln_t exp_dns_reln,
+ int exp_order, int exp_nlabels)
+{
+ int result;
+ int nfails;
+ int order;
+ unsigned int nlabels;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+ isc_result_t dns_result;
+ dns_namereln_t dns_reln;
+
+ nfails = 0;
+ result = T_UNRESOLVED;
+
+
+ t_info("testing names %s and %s for relation %s\n", name1, name2,
+ dns_namereln_to_text(exp_dns_reln));
+
+ dns_result = dname_from_tname(name1, &dns_name1);
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_result = dname_from_tname(name2, &dns_name2);
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_reln = dns_name_fullcompare(&dns_name1, &dns_name2,
+ &order, &nlabels);
+
+ if (dns_reln != exp_dns_reln) {
+ ++nfails;
+ t_info("expected relationship of %s, got %s\n",
+ dns_namereln_to_text(exp_dns_reln),
+ dns_namereln_to_text(dns_reln));
+ }
+ /*
+ * Normalize order.
+ */
+ if (order < 0)
+ order = -1;
+ else if (order > 0)
+ order = 1;
+ if (order != exp_order) {
+ ++nfails;
+ t_info("expected ordering %d, got %d\n",
+ exp_order, order);
+ }
+ if ((exp_nlabels >= 0) &&
+ (nlabels != (unsigned int)exp_nlabels)) {
+ ++nfails;
+ t_info("expecting %d labels, got %d\n",
+ exp_nlabels, nlabels);
+ }
+ if (nfails == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+ } else {
+ t_info("dname_from_tname failed, result == %s\n",
+ dns_result_totext(result));
+ }
+ } else {
+ t_info("dname_from_tname failed, result == %s\n",
+ dns_result_totext(result));
+ }
+
+ return (result);
+}
+
+static void
+t_dns_name_fullcompare(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+ dns_namereln_t reln;
+
+ t_assert("dns_name_fullcompare", 1, T_REQUIRED, a10);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_fullcompare_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 6) {
+ /*
+ * name1, name2, exp_reln, exp_order,
+ * exp_nlabels
+ */
+ if (!strcmp(Tokens[2], "none"))
+ reln = dns_namereln_none;
+ else if (!strcmp(Tokens[2], "contains"))
+ reln = dns_namereln_contains;
+ else if (!strcmp(Tokens[2], "subdomain"))
+ reln = dns_namereln_subdomain;
+ else if (!strcmp(Tokens[2], "equal"))
+ reln = dns_namereln_equal;
+ else if (!strcmp(Tokens[2], "commonancestor"))
+ reln = dns_namereln_commonancestor;
+ else {
+ t_info("bad format at line %d\n",
+ line);
+ continue;
+ }
+ result = test_dns_name_fullcompare(
+ Tokens[0],
+ Tokens[1],
+ reln,
+ atoi(Tokens[3]),
+ atoi(Tokens[4]));
+ } else {
+ t_info("bad format at line %d\n", line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_fullcompare_data\n");
+ t_result(result);
+ }
+}
+
+static const char *a23 =
+ "dns_name_compare(name1, name2) returns information about "
+ "the relative ordering under the DNSSEC ordering relationship "
+ "of name1 and name2";
+
+/*%
+ * a24 thru a29 merged into a23.
+ */
+
+static int
+test_dns_name_compare(char *name1, char *name2, int exp_order) {
+ int result;
+ int order;
+ isc_result_t dns_result;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+
+ result = T_UNRESOLVED;
+
+ t_info("testing %s %s %s\n", name1,
+ exp_order == 0 ? "==": (exp_order == -1 ? "<" : ">"),
+ name2);
+
+ dns_result = dname_from_tname(name1, &dns_name1);
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_result = dname_from_tname(name2, &dns_name2);
+ if (dns_result == ISC_R_SUCCESS) {
+ order = dns_name_compare(&dns_name1, &dns_name2);
+ /*
+ * Normalize order.
+ */
+ if (order < 0)
+ order = -1;
+ else if (order > 0)
+ order = 1;
+ if (order != exp_order) {
+ t_info("expected order of %d, got %d\n",
+ exp_order, order);
+ result = T_FAIL;
+ } else
+ result = T_PASS;
+ } else {
+ t_info("dname_from_tname failed, result == %s\n",
+ dns_result_totext(result));
+ }
+ } else {
+ t_info("dname_from_tname failed, result == %s\n",
+ dns_result_totext(result));
+ }
+
+ return (result);
+}
+
+static void
+t_dns_name_compare(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_compare", 1, T_REQUIRED, a23);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_compare_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 3) {
+ /*
+ * name1, name2, order.
+ */
+ result = test_dns_name_compare(
+ Tokens[0],
+ Tokens[1],
+ atoi(Tokens[2]));
+ } else {
+ t_info("bad datafile format at line %d\n",
+ line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_compare_data\n");
+ t_result(result);
+ }
+}
+
+static const char *a30 =
+ "dns_name_rdatacompare(name1, name2) returns information "
+ "about the relative ordering of name1 and name2 as if they "
+ "are part of rdata in DNSSEC canonical form";
+
+/*%
+ * a31, a32 merged into a30.
+ */
+
+static int
+test_dns_name_rdatacompare(char *name1, char *name2, int exp_order) {
+ int result;
+ int order;
+ isc_result_t dns_result;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+
+ result = T_UNRESOLVED;
+
+ t_info("testing %s %s %s\n", name1,
+ exp_order == 0 ? "==": (exp_order == -1 ? "<" : ">"), name2);
+
+ dns_result = dname_from_tname(name1, &dns_name1);
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_result = dname_from_tname(name2, &dns_name2);
+ if (dns_result == ISC_R_SUCCESS) {
+ order = dns_name_rdatacompare(&dns_name1, &dns_name2);
+ /*
+ * Normalize order.
+ */
+ if (order < 0)
+ order = -1;
+ else if (order > 0)
+ order = 1;
+ if (order != exp_order) {
+ t_info("expected order of %d, got %d\n",
+ exp_order, order);
+ result = T_FAIL;
+ } else
+ result = T_PASS;
+ } else {
+ t_info("dname_from_tname failed, result == %s\n",
+ dns_result_totext(result));
+ }
+ } else {
+ t_info("dname_from_tname failed, result == %s\n",
+ dns_result_totext(result));
+ }
+
+ return (result);
+}
+
+static void
+t_dns_name_rdatacompare(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_rdatacompare", 1, T_REQUIRED, a30);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_rdatacompare_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 3) {
+ /*
+ * name1, name2, order.
+ */
+ result = test_dns_name_rdatacompare(
+ Tokens[0],
+ Tokens[1],
+ atoi(Tokens[2]));
+ } else {
+ t_info("bad datafile format at line %d\n",
+ line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_rdatacompare_data\n");
+ t_result(result);
+ }
+}
+
+
+static const char *a33 =
+ "when name1 is a subdomain of name2, "
+ "dns_name_issubdomain(name1, name2) returns true, "
+ "otherwise it returns false.";
+
+/*%
+ * a34 merged into a33.
+ */
+
+static int
+test_dns_name_issubdomain(char *name1, char *name2, isc_boolean_t exp_rval) {
+ int result;
+ isc_boolean_t rval;
+ isc_result_t dns_result;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+
+ result = T_UNRESOLVED;
+
+ t_info("testing %s %s a subdomain of %s\n", name1,
+ exp_rval == 0 ? "is not" : "is", name2);
+
+ dns_result = dname_from_tname(name1, &dns_name1);
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_result = dname_from_tname(name2, &dns_name2);
+ if (dns_result == ISC_R_SUCCESS) {
+ rval = dns_name_issubdomain(&dns_name1, &dns_name2);
+
+ if (rval != exp_rval) {
+ t_info("expected return value of %s, got %s\n",
+ exp_rval == ISC_TRUE ? "true" : "false",
+ rval == ISC_TRUE ? "true" : "false");
+ result = T_FAIL;
+ } else
+ result = T_PASS;
+ } else {
+ t_info("dname_from_tname failed, result == %s\n",
+ dns_result_totext(result));
+ }
+ } else {
+ t_info("dname_from_tname failed, result == %s\n",
+ dns_result_totext(result));
+ }
+
+ return (result);
+}
+
+static void
+t_dns_name_issubdomain(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_issubdomain", 1, T_REQUIRED, a33);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_issubdomain_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 3) {
+ /*
+ * name1, name2, issubdomain_p.
+ */
+ result = test_dns_name_issubdomain(
+ Tokens[0],
+ Tokens[1],
+ atoi(Tokens[2]) == 0 ?
+ ISC_FALSE : ISC_TRUE);
+ } else {
+ t_info("bad datafile format at line %d\n",
+ line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_issubdomain_data\n");
+ t_result(result);
+ }
+}
+
+static const char *a35 =
+ "dns_name_countlabels(name) returns the number "
+ "of labels in name";
+
+static int
+test_dns_name_countlabels(char *test_name, unsigned int exp_nlabels) {
+ int result;
+ unsigned int nlabels;
+ isc_result_t dns_result;
+ dns_name_t dns_name;
+
+ result = T_UNRESOLVED;
+
+ t_info("testing %s\n", test_name);
+
+ dns_result = dname_from_tname(test_name, &dns_name);
+ if (dns_result == ISC_R_SUCCESS) {
+ nlabels = dns_name_countlabels(&dns_name);
+
+ if (nlabels != exp_nlabels) {
+ t_info("expected %d, got %d\n", exp_nlabels, nlabels);
+ result = T_FAIL;
+ } else
+ result = T_PASS;
+ } else {
+ t_info("dname_from_tname failed, result == %s\n",
+ dns_result_totext(dns_result));
+ }
+
+ return (result);
+}
+
+static void
+t_dns_name_countlabels(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_countlabels", 1, T_REQUIRED, a35);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_countlabels_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 2) {
+ /*
+ * name, nlabels.
+ */
+ result = test_dns_name_countlabels(Tokens[0],
+ atoi(Tokens[1]));
+ } else {
+ t_info("bad format at line %d\n", line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_countlabels_data\n");
+ t_result(result);
+ }
+}
+
+static const char *a36 =
+ "when n is less than the number of labels in name, "
+ "dns_name_getlabel(name, n, labelp) initializes labelp "
+ "to point to the nth label in name";
+
+/*%
+ * The strategy here is two take two dns names with a shared label in
+ * different positions, get the two labels and compare them for equality.
+ * If they don't match, dns_name_getlabel failed.
+ */
+
+static int
+test_dns_name_getlabel(char *test_name1, int label1_pos, char *test_name2,
+ int label2_pos)
+{
+ int result;
+ int nfails;
+ unsigned int cnt;
+ unsigned char *p;
+ unsigned char *q;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+ dns_label_t dns_label1;
+ dns_label_t dns_label2;
+ isc_result_t dns_result;
+
+ nfails = 0;
+ result = T_UNRESOLVED;
+
+ t_info("testing with %s and %s\n", test_name1, test_name2);
+
+ dns_result = dname_from_tname(test_name1, &dns_name1);
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_result = dname_from_tname(test_name2, &dns_name2);
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_name_getlabel(&dns_name1, label1_pos, &dns_label1);
+ dns_name_getlabel(&dns_name2, label2_pos, &dns_label2);
+ if (dns_label1.length != dns_label2.length) {
+ t_info("label lengths differ\n");
+ ++nfails;
+ }
+ p = dns_label1.base;
+ q = dns_label2.base;
+ for (cnt = 0; cnt < dns_label1.length; ++cnt) {
+ if (*p++ != *q++) {
+ t_info("labels differ at position %d",
+ cnt);
+ ++nfails;
+ }
+ }
+ if (nfails == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+ } else {
+ t_info("dname_from_tname failed, result == %s",
+ dns_result_totext(result));
+ }
+ } else {
+ t_info("dname_from_tname failed, result == %s",
+ dns_result_totext(result));
+ }
+ return (result);
+}
+
+static void
+t_dns_name_getlabel(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_getlabel", 1, T_REQUIRED, a36);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_getlabel_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 4) {
+ /*
+ * name1, name2, nlabels.
+ */
+ result = test_dns_name_getlabel(Tokens[0],
+ atoi(Tokens[1]),
+ Tokens[2],
+ atoi(Tokens[3]));
+ } else {
+ t_info("bad format at line %d\n", line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_getlabel_data\n");
+ t_result(result);
+ }
+}
+
+static const char *a37 =
+ "when source contains at least first + n labels, "
+ "dns_name_getlabelsequence(source, first, n, target) "
+ "initializes target to point to the n label sequence of "
+ "labels in source starting with first";
+
+/*%
+ * We adopt a similiar strategy to that used by the dns_name_getlabel test.
+ */
+
+static int
+test_dns_name_getlabelsequence(char *test_name1, int label1_start,
+ char *test_name2, int label2_start, int range)
+{
+ int result;
+ int nfails;
+ unsigned int cnt;
+ unsigned char *p;
+ unsigned char *q;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+ dns_name_t dns_targetname1;
+ dns_name_t dns_targetname2;
+ isc_result_t dns_result;
+ isc_buffer_t buffer1;
+ isc_buffer_t buffer2;
+ unsigned char junk1[BUFLEN];
+ unsigned char junk2[BUFLEN];
+
+ nfails = 0;
+ result = T_UNRESOLVED;
+ dns_result = dname_from_tname(test_name1, &dns_name1);
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_result = dname_from_tname(test_name2, &dns_name2);
+ if (dns_result == ISC_R_SUCCESS) {
+ t_info("testing %s %s\n", test_name1, test_name2);
+ dns_name_init(&dns_targetname1, NULL);
+ dns_name_init(&dns_targetname2, NULL);
+ dns_name_getlabelsequence(&dns_name1, label1_start,
+ range, &dns_targetname1);
+ dns_name_getlabelsequence(&dns_name2, label2_start,
+ range, &dns_targetname2);
+
+ /*
+ * Now convert both targets to text for comparison.
+ */
+ isc_buffer_init(&buffer1, junk1, BUFLEN);
+ isc_buffer_init(&buffer2, junk2, BUFLEN);
+ dns_name_totext(&dns_targetname1, ISC_TRUE, &buffer1);
+ dns_name_totext(&dns_targetname2, ISC_TRUE, &buffer2);
+ if (buffer1.used == buffer2.used) {
+ p = buffer1.base;
+ q = buffer2.base;
+ for (cnt = 0; cnt < buffer1.used; ++cnt) {
+ if (*p != *q) {
+ ++nfails;
+ t_info("names differ at %d\n",
+ cnt);
+ break;
+ }
+ ++p; ++q;
+ }
+ } else {
+ ++nfails;
+ t_info("lengths differ\n");
+ }
+ if (nfails == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+ } else {
+ t_info("dname_from_tname failed, result == %s",
+ dns_result_totext(dns_result));
+ }
+ } else {
+ t_info("dname_from_tname failed, result == %s",
+ dns_result_totext(dns_result));
+ }
+ return (result);
+}
+
+static void
+t_dns_name_getlabelsequence(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_getlabelsequence", 1, T_REQUIRED, a37);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_getlabelsequence_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 5) {
+ /*
+ * name1, name2, nlabels.
+ */
+ result = test_dns_name_getlabelsequence(
+ Tokens[0],
+ atoi(Tokens[1]),
+ Tokens[2],
+ atoi(Tokens[3]),
+ atoi(Tokens[4]));
+ } else {
+ t_info("bad format at line %d\n", line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_getlabelsequence_data\n");
+ t_result(result);
+ }
+}
+
+static const char *a38 =
+ "dns_name_fromregion(name, region) converts a DNS name "
+ "from a region representation to a name representation";
+
+static int
+test_dns_name_fromregion(char *test_name) {
+ int result;
+ int order;
+ unsigned int nlabels;
+ isc_result_t dns_result;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+ dns_namereln_t dns_namereln;
+ isc_region_t region;
+
+ result = T_UNRESOLVED;
+
+ t_info("testing %s\n", test_name);
+
+ dns_result = dname_from_tname(test_name, &dns_name1);
+ if (dns_result == ISC_R_SUCCESS) {
+
+ dns_name_toregion(&dns_name1, &region);
+
+ dns_name_init(&dns_name2, NULL);
+ dns_name_fromregion(&dns_name2, &region);
+ dns_namereln = dns_name_fullcompare(&dns_name1, &dns_name2,
+ &order, &nlabels);
+ if (dns_namereln == dns_namereln_equal)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+ } else {
+ t_info("dname_from_tname failed, result == %s\n",
+ dns_result_totext(result));
+ }
+ return (result);
+}
+
+static void
+t_dns_name_fromregion(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_fromregion", 1, T_REQUIRED, a38);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_fromregion_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 1) {
+ /*
+ * test_name.
+ */
+ result = test_dns_name_fromregion(Tokens[0]);
+ } else {
+ t_info("bad format at line %d\n", line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_fromregion_data\n");
+ t_result(result);
+ }
+}
+
+static const char *a39 =
+ "dns_name_toregion(name, region) converts a DNS name "
+ "from a region representation to a name representation";
+
+static void
+t_dns_name_toregion(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_toregion", 1, T_REQUIRED, a39);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_toregion_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 1) {
+ /*
+ * test_name.
+ */
+ result = test_dns_name_fromregion(Tokens[0]);
+ } else {
+ t_info("bad format at line %d\n", line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_toregion_data\n");
+ t_result(result);
+ }
+}
+
+static const char *a40 =
+ "dns_name_fromtext(name, source, origin, downcase, target) "
+ "converts the textual representation of a DNS name at source "
+ "into uncompressed wire form at target, appending origin to "
+ "the converted name if origin is non-NULL and converting "
+ "upper case to lower case during conversion "
+ "if downcase is true.";
+
+static int
+test_dns_name_fromtext(char *test_name1, char *test_name2, char *test_origin,
+ isc_boolean_t downcase)
+{
+ int result;
+ int order;
+ unsigned int nlabels;
+ unsigned char junk1[BUFLEN];
+ unsigned char junk2[BUFLEN];
+ unsigned char junk3[BUFLEN];
+ isc_buffer_t binbuf1;
+ isc_buffer_t binbuf2;
+ isc_buffer_t binbuf3;
+ isc_buffer_t txtbuf1;
+ isc_buffer_t txtbuf2;
+ isc_buffer_t txtbuf3;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+ dns_name_t dns_name3;
+ isc_result_t dns_result;
+ dns_namereln_t dns_namereln;
+
+ result = T_UNRESOLVED;
+
+ t_info("testing %s %s %s\n", test_name1, test_name2, test_origin);
+
+ isc_buffer_init(&binbuf1, junk1, BUFLEN);
+ isc_buffer_init(&binbuf2, junk2, BUFLEN);
+ isc_buffer_init(&binbuf3, junk3, BUFLEN);
+
+ isc_buffer_init(&txtbuf1, test_name1, strlen(test_name1));
+ isc_buffer_add(&txtbuf1, strlen(test_name1));
+
+ isc_buffer_init(&txtbuf2, test_name2, strlen(test_name2));
+ isc_buffer_add(&txtbuf2, strlen(test_name2));
+
+ isc_buffer_init(&txtbuf3, test_origin, strlen(test_origin));
+ isc_buffer_add(&txtbuf3, strlen(test_origin));
+ dns_name_init(&dns_name1, NULL);
+ dns_name_init(&dns_name2, NULL);
+ dns_name_init(&dns_name3, NULL);
+ dns_name_setbuffer(&dns_name1, &binbuf1);
+ dns_name_setbuffer(&dns_name2, &binbuf2);
+ dns_name_setbuffer(&dns_name3, &binbuf3);
+
+ dns_result = dns_name_fromtext(&dns_name3, &txtbuf3, NULL,
+ ISC_FALSE, &binbuf3);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext(dns_name3) failed, result == %s\n",
+ dns_result_totext(dns_result));
+ return (T_FAIL);
+ }
+
+ dns_result = dns_name_fromtext(&dns_name1, &txtbuf1, &dns_name3,
+ downcase, &binbuf1);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext(dns_name1) failed, result == %s\n",
+ dns_result_totext(dns_result));
+ return (T_FAIL);
+ }
+
+ dns_result = dns_name_fromtext(&dns_name2, &txtbuf2, NULL,
+ ISC_FALSE, &binbuf2);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext(dns_name2) failed, result == %s\n",
+ dns_result_totext(dns_result));
+ return (T_FAIL);
+ }
+
+ dns_namereln = dns_name_fullcompare(&dns_name1, &dns_name2, &order,
+ &nlabels);
+
+ if (dns_namereln == dns_namereln_equal)
+ result = T_PASS;
+ else {
+ t_info("dns_name_fullcompare returned %s\n",
+ dns_namereln_to_text(dns_namereln));
+ result = T_FAIL;
+ }
+
+ return (result);
+}
+
+static void
+t_dns_name_fromtext(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_fromtext", 1, T_REQUIRED, a40);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_fromtext_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 4) {
+ /*
+ * test_name1, test_name2, test_origin,
+ * downcase.
+ */
+ result = test_dns_name_fromtext(Tokens[0],
+ Tokens[1],
+ Tokens[2],
+ atoi(Tokens[3])
+ == 0 ?
+ ISC_FALSE :
+ ISC_TRUE);
+ } else {
+ t_info("bad format at line %d\n", line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_fromtext\n");
+ t_result(result);
+ }
+}
+
+static const char *a41 =
+ "dns_name_totext(name, omit_final_dot, target) converts "
+ "the DNS name 'name' in wire format to textual format "
+ "at target, and adds a final '.' to the name if "
+ "omit_final_dot is false";
+
+static int
+test_dns_name_totext(char *test_name, isc_boolean_t omit_final) {
+ int result;
+ int len;
+ int order;
+ unsigned int nlabels;
+ unsigned char junk1[BUFLEN];
+ unsigned char junk2[BUFLEN];
+ unsigned char junk3[BUFLEN];
+ isc_buffer_t buf1;
+ isc_buffer_t buf2;
+ isc_buffer_t buf3;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+ isc_result_t dns_result;
+ dns_namereln_t dns_namereln;
+
+ result = T_UNRESOLVED;
+
+ t_info("testing %s\n", test_name);
+
+ len = strlen(test_name);
+ isc_buffer_init(&buf1, test_name, len);
+ isc_buffer_add(&buf1, len);
+
+ dns_name_init(&dns_name1, NULL);
+ isc_buffer_init(&buf2, junk2, BUFLEN);
+
+ /*
+ * Out of the data file to dns_name1.
+ */
+ dns_result = dns_name_fromtext(&dns_name1, &buf1, NULL, ISC_FALSE,
+ &buf2);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed, result == %s\n",
+ dns_result_totext(dns_result));
+ return (T_UNRESOLVED);
+ }
+
+ /*
+ * From dns_name1 into a text buffer.
+ */
+ isc_buffer_invalidate(&buf1);
+ isc_buffer_init(&buf1, junk1, BUFLEN);
+ dns_result = dns_name_totext(&dns_name1, omit_final, &buf1);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_totext failed, result == %s\n",
+ dns_result_totext(dns_result));
+ return (T_FAIL);
+ }
+
+ /*
+ * From the text buffer into dns_name2.
+ */
+ dns_name_init(&dns_name2, NULL);
+ isc_buffer_init(&buf3, junk3, BUFLEN);
+ dns_result = dns_name_fromtext(&dns_name2, &buf1, NULL, ISC_FALSE,
+ &buf3);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed, result == %s\n",
+ dns_result_totext(dns_result));
+ return (T_UNRESOLVED);
+ }
+
+ dns_namereln = dns_name_fullcompare(&dns_name1, &dns_name2,
+ &order, &nlabels);
+ if (dns_namereln == dns_namereln_equal)
+ result = T_PASS;
+ else {
+ t_info("dns_name_fullcompare returned %s\n",
+ dns_namereln_to_text(dns_namereln));
+ result = T_FAIL;
+ }
+
+ return (result);
+}
+
+static void
+t_dns_name_totext(void) {
+ int line;
+ int cnt;
+ int result;
+ char *p;
+ FILE *fp;
+
+ t_assert("dns_name_totext", 1, T_REQUIRED, a41);
+
+ result = T_UNRESOLVED;
+ fp = fopen("dns_name_totext_data", "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 2) {
+ /*
+ * test_name, omit_final.
+ */
+ result = test_dns_name_totext(Tokens[0],
+ atoi(Tokens[1]) == 0 ?
+ ISC_FALSE :
+ ISC_TRUE);
+ } else {
+ t_info("bad format at line %d\n", line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile dns_name_totext\n");
+ t_result(result);
+ }
+}
+
+static const char *a42 =
+ "dns_name_fromwire(name, source, dctx, downcase, target) "
+ "converts the possibly compressed DNS name 'name' in wire "
+ "format to canonicalized form at target, performing upper to "
+ "lower case conversion if downcase is true, and returns "
+ "ISC_R_SUCCESS";
+
+#if 0
+ /*
+ * XXXRTH these tests appear to be broken, so I have
+ * disabled them.
+ */
+static const char *a43 =
+ "when a label length is invalid, dns_name_fromwire() "
+ "returns DNS_R_FORMERR";
+
+static const char *a44 =
+ "when a label type is invalid, dns_name_fromwire() "
+ "returns DNS_R_BADLABELTYPE";
+#endif
+
+static const char *a45 =
+ "when a name length is invalid, dns_name_fromwire() "
+ "returns DNS_R_FORMERR";
+
+static const char *a46 =
+ "when a compression type is invalid, dns_name_fromwire() "
+ "returns DNS_R_DISALLOWED";
+
+static const char *a47 =
+ "when a bad compression pointer is encountered, "
+ "dns_name_fromwire() returns DNS_R_BADPOINTER";
+
+static const char *a48 =
+ "when input ends unexpected, dns_name_fromwire() "
+ "returns ISC_R_UNEXPECTEDEND";
+
+static const char *a49 =
+ "when there is not enough space in target, "
+ "dns_name_fromwire(name, source, dcts, downcase, target) "
+ "returns ISC_R_NOSPACE";
+
+static int
+test_dns_name_fromwire(char *datafile_name, int testname_offset, int downcase,
+ unsigned int dc_method, char *exp_name,
+ isc_result_t exp_result, size_t buflen)
+{
+ int result;
+ int order;
+ unsigned int nlabels;
+ int len;
+ unsigned char buf1[BIGBUFLEN];
+ char buf2[BUFLEN];
+ isc_buffer_t iscbuf1;
+ isc_buffer_t iscbuf2;
+ dns_name_t dns_name1;
+ dns_name_t dns_name2;
+ isc_result_t dns_result;
+ dns_namereln_t dns_namereln;
+ dns_decompress_t dctx;
+
+ result = T_UNRESOLVED;
+
+ t_info("testing using %s\n", datafile_name);
+ len = getmsg(datafile_name, buf1, BIGBUFLEN, &iscbuf1);
+
+ isc_buffer_setactive(&iscbuf1, len);
+ iscbuf1.current = testname_offset;
+
+ isc_buffer_init(&iscbuf2, buf2, buflen);
+ dns_name_init(&dns_name1, NULL);
+ dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT);
+ dns_decompress_setmethods(&dctx, dc_method);
+ dns_result = dns_name_fromwire(&dns_name1, &iscbuf1,
+ &dctx, downcase ? ISC_TRUE : ISC_FALSE,
+ &iscbuf2);
+
+ if ((dns_result == exp_result) && (exp_result == ISC_R_SUCCESS)) {
+
+ dns_result = dname_from_tname(exp_name, &dns_name2);
+ if (dns_result == ISC_R_SUCCESS) {
+ dns_namereln = dns_name_fullcompare(&dns_name1,
+ &dns_name2,
+ &order, &nlabels);
+ if (dns_namereln != dns_namereln_equal) {
+ t_info("dns_name_fullcompare returned %s\n",
+ dns_namereln_to_text(dns_namereln));
+ result = T_FAIL;
+ } else {
+ result = T_PASS;
+ }
+ } else {
+ t_info("dns_name_fromtext %s failed, result = %s\n",
+ exp_name, dns_result_totext(dns_result));
+ result = T_UNRESOLVED;
+ }
+ } else if (dns_result == exp_result) {
+ result = T_PASS;
+ } else {
+ t_info("dns_name_fromwire returned %s\n",
+ dns_result_totext(dns_result));
+ result = T_FAIL;
+ }
+
+ return (result);
+}
+
+static void
+t_dns_name_fromwire_x(const char *testfile, size_t buflen) {
+ int line;
+ int cnt;
+ int result;
+ unsigned int dc_method;
+ isc_result_t exp_result;
+ char *p;
+ char *tok;
+ FILE *fp;
+
+ result = T_UNRESOLVED;
+ fp = fopen(testfile, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 6) {
+ /*
+ * datafile_name, testname_offset,
+ * downcase, dc_method,
+ * exp_name, exp_result.
+ */
+
+ tok = Tokens[5];
+ exp_result = ISC_R_SUCCESS;
+ if (! strcmp(tok, "ISC_R_SUCCESS"))
+ exp_result = ISC_R_SUCCESS;
+ else if (! strcmp(tok, "ISC_R_NOSPACE"))
+ exp_result = ISC_R_NOSPACE;
+ else if (! strcmp(tok, "DNS_R_BADLABELTYPE"))
+ exp_result = DNS_R_BADLABELTYPE;
+ else if (! strcmp(tok, "DNS_R_FORMERR"))
+ exp_result = DNS_R_FORMERR;
+ else if (! strcmp(tok, "DNS_R_BADPOINTER"))
+ exp_result = DNS_R_BADPOINTER;
+ else if (! strcmp(tok, "ISC_R_UNEXPECTEDEND"))
+ exp_result = ISC_R_UNEXPECTEDEND;
+ else if (! strcmp(tok, "DNS_R_TOOMANYHOPS"))
+ exp_result = DNS_R_TOOMANYHOPS;
+ else if (! strcmp(tok, "DNS_R_DISALLOWED"))
+ exp_result = DNS_R_DISALLOWED;
+ else if (! strcmp(tok, "DNS_R_NAMETOOLONG"))
+ exp_result = DNS_R_NAMETOOLONG;
+
+ tok = Tokens[3];
+ dc_method = DNS_COMPRESS_NONE;
+ if (! strcmp(tok, "DNS_COMPRESS_GLOBAL14"))
+ dc_method = DNS_COMPRESS_GLOBAL14;
+ else if (! strcmp(tok, "DNS_COMPRESS_ALL"))
+ dc_method = DNS_COMPRESS_ALL;
+
+ result = test_dns_name_fromwire(Tokens[0],
+ atoi(Tokens[1]),
+ atoi(Tokens[2]),
+ dc_method,
+ Tokens[4],
+ exp_result,
+ buflen);
+ } else {
+ t_info("bad format at line %d\n", line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", testfile);
+ t_result(result);
+ }
+}
+
+static void
+t_dns_name_fromwire(void) {
+ t_assert("dns_name_fromwire", 1, T_REQUIRED, a42);
+ t_dns_name_fromwire_x("dns_name_fromwire_1_data", BUFLEN);
+
+#if 0
+ /*
+ * XXXRTH these tests appear to be broken, so I have
+ * disabled them.
+ */
+ t_assert("dns_name_fromwire", 2, T_REQUIRED, a43);
+ t_dns_name_fromwire_x("dns_name_fromwire_2_data", BUFLEN);
+
+ t_assert("dns_name_fromwire", 3, T_REQUIRED, a44);
+ t_dns_name_fromwire_x("dns_name_fromwire_3_data", BUFLEN);
+#endif
+
+ t_assert("dns_name_fromwire", 4, T_REQUIRED, a45);
+ t_dns_name_fromwire_x("dns_name_fromwire_4_data", BUFLEN);
+
+ t_assert("dns_name_fromwire", 5, T_REQUIRED, a46);
+ t_dns_name_fromwire_x("dns_name_fromwire_5_data", BUFLEN);
+
+ t_assert("dns_name_fromwire", 6, T_REQUIRED, a47);
+ t_dns_name_fromwire_x("dns_name_fromwire_6_data", BUFLEN);
+
+ t_assert("dns_name_fromwire", 7, T_REQUIRED, a48);
+ t_dns_name_fromwire_x("dns_name_fromwire_7_data", BUFLEN);
+
+ t_assert("dns_name_fromwire", 9, T_REQUIRED, a49);
+ t_dns_name_fromwire_x("dns_name_fromwire_8_data", 2);
+}
+
+
+static const char *a51 =
+ "dns_name_towire(name, cctx, target) converts the DNS name "
+ "'name' into wire format, compresses it as specified "
+ "by the compression context cctx, stores the result in "
+ "target and returns DNS_SUCCESS";
+
+static const char *a52 =
+ "when not enough space exists in target, "
+ "dns_name_towire(name, cctx, target) returns ISC_R_NOSPACE";
+
+static int
+test_dns_name_towire(char *testname, unsigned int dc_method, char *exp_data,
+ int exp_data_len, isc_result_t exp_result, size_t buflen)
+{
+ int result;
+ int val;
+ int len;
+ unsigned char buf2[BUFLEN];
+ unsigned char buf3[BUFLEN];
+ isc_buffer_t iscbuf1;
+ isc_buffer_t iscbuf2;
+ isc_buffer_t iscbuf3;
+ dns_name_t dns_name;
+ isc_result_t dns_result;
+ isc_result_t isc_result;
+ dns_compress_t cctx;
+ isc_mem_t *mctx;
+
+ t_info("testing using %s\n", testname);
+
+ result = T_UNRESOLVED;
+ mctx = NULL;
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed\n");
+ return (result);
+ }
+ dns_compress_init(&cctx, -1, mctx);
+ dns_compress_setmethods(&cctx, dc_method);
+ dns_name_init(&dns_name, NULL);
+ len = strlen(testname);
+ isc_buffer_init(&iscbuf1, testname, len);
+ isc_buffer_add(&iscbuf1, len);
+ isc_buffer_init(&iscbuf2, buf2, BUFLEN);
+ dns_result = dns_name_fromtext(&dns_name, &iscbuf1, NULL, ISC_FALSE,
+ &iscbuf2);
+ if (dns_result == ISC_R_SUCCESS) {
+ isc_buffer_init(&iscbuf3, buf3, buflen);
+ dns_result = dns_name_towire(&dns_name, &cctx, &iscbuf3);
+ if (dns_result == exp_result) {
+ if (exp_result == ISC_R_SUCCESS) {
+ /*
+ * Compare results with expected data.
+ */
+ val = chkdata(buf3, iscbuf3.used, exp_data,
+ exp_data_len);
+ if (val == 0)
+ result = T_PASS;
+ else
+ result = T_FAIL;
+ } else
+ result = T_PASS;
+ } else {
+ t_info("dns_name_towire unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ result = T_FAIL;
+ }
+ } else {
+ t_info("dns_name_fromtext %s failed, result = %s\n",
+ testname, dns_result_totext(dns_result));
+ }
+ return (result);
+}
+
+static void
+t_dns_name_towire_x(const char *testfile, size_t buflen) {
+ int line;
+ int cnt;
+ int result;
+ unsigned int dc_method;
+ isc_result_t exp_result;
+ char *p;
+ FILE *fp;
+
+ result = T_UNRESOLVED;
+ fp = fopen(testfile, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = bustline(p, Tokens);
+ if (cnt == 5) {
+ /*
+ * testname, dc_method,
+ * exp_data, exp_data_len,
+ * exp_result.
+ */
+
+ dc_method = t_dc_method_fromtext(Tokens[3]);
+ exp_result = t_dns_result_fromtext(Tokens[4]);
+
+ result = test_dns_name_towire(Tokens[0],
+ dc_method,
+ Tokens[2],
+ atoi(Tokens[3]),
+ exp_result,
+ buflen);
+ } else {
+ t_info("bad format at line %d\n", line);
+ }
+
+ (void)free(p);
+ t_result(result);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", testfile);
+ t_result(result);
+ }
+}
+
+static void
+t_dns_name_towire_1(void) {
+ t_assert("dns_name_towire", 1, T_REQUIRED, a51);
+ t_dns_name_towire_x("dns_name_towire_1_data", BUFLEN);
+}
+
+static void
+t_dns_name_towire_2(void) {
+ t_assert("dns_name_towire", 2, T_REQUIRED, a52);
+ t_dns_name_towire_x("dns_name_towire_2_data", 2);
+}
+
+static void
+t_dns_name_towire(void) {
+ t_dns_name_towire_1();
+ t_dns_name_towire_2();
+}
+
+#if 0 /* This is silly. A test should either exist, or not, but not
+ * one that just returns "UNTESTED."
+ */
+static const char *a53 =
+ "dns_name_concatenate(prefix, suffix, name, target) "
+ "concatenates prefix and suffix, stores the result "
+ "in target, canonicalizes any bitstring labels "
+ "and returns ISC_R_SUCCESS";
+
+static void
+t_dns_name_concatenate(void) {
+ t_assert("dns_name_concatenate", 1, T_REQUIRED, a53);
+ t_result(T_UNTESTED);
+}
+#endif
+
+testspec_t T_testlist[] = {
+ { t_dns_name_init, "dns_name_init" },
+ { t_dns_name_invalidate, "dns_name_invalidate" },
+ { t_dns_name_setbuffer, "dns_name_setbuffer" },
+ { t_dns_name_hasbuffer, "dns_name_hasbuffer" },
+ { t_dns_name_isabsolute, "dns_name_isabsolute" },
+ { t_dns_name_hash, "dns_name_hash" },
+ { t_dns_name_fullcompare, "dns_name_fullcompare" },
+ { t_dns_name_compare, "dns_name_compare" },
+ { t_dns_name_rdatacompare, "dns_name_rdatacompare" },
+ { t_dns_name_issubdomain, "dns_name_issubdomain" },
+ { t_dns_name_countlabels, "dns_name_countlabels" },
+ { t_dns_name_getlabel, "dns_name_getlabel" },
+ { t_dns_name_getlabelsequence, "dns_name_getlabelsequence" },
+ { t_dns_name_fromregion, "dns_name_fromregion" },
+ { t_dns_name_toregion, "dns_name_toregion" },
+ { t_dns_name_fromwire, "dns_name_fromwire" },
+ { t_dns_name_towire, "dns_name_towire" },
+ { t_dns_name_fromtext, "dns_name_fromtext" },
+ { t_dns_name_totext, "dns_name_totext" },
+#if 0
+ { t_dns_name_concatenate, "dns_name_concatenate" },
+#endif
+ { NULL, NULL }
+
+};
+
diff --git a/bin/tests/names/wire_test1.data b/bin/tests/names/wire_test1.data
new file mode 100644
index 0000000..505134a
--- /dev/null
+++ b/bin/tests/names/wire_test1.data
@@ -0,0 +1,13 @@
+#
+# a global14 compression pointer
+#
+000a85800001000300000003
+0376697803636f6d0000020001c00c00
+02000100000e10000b05697372763102
+7061c00cc00c0002000100000e100009
+066e732d657874c00cc00c0002000100
+000e10000e036e733104676e61630363
+6f6d00c0250001000100000e100004cc
+98b886c03c0001000100000e100004cc
+98b840c051000100010002a14a0004c6
+97f8f6
diff --git a/bin/tests/names/wire_test2.data b/bin/tests/names/wire_test2.data
new file mode 100644
index 0000000..ea03557
--- /dev/null
+++ b/bin/tests/names/wire_test2.data
@@ -0,0 +1,13 @@
+#
+# a global14 compression pointer
+#
+000a85800001000300000003
+8376697803636f6d0000020001c00c00
+02000100000e10000b05697372763102
+7061c00cc00c0002000100000e100009
+066e732d657874c00cc00c0002000100
+000e10000e036e733104676e61630363
+6f6d00c0250001000100000e100004cc
+98b886c03c0001000100000e100004cc
+98b840c051000100010002a14a0004c6
+97f8f6
diff --git a/bin/tests/names/wire_test3_1.data b/bin/tests/names/wire_test3_1.data
new file mode 100644
index 0000000..5f5ec59
--- /dev/null
+++ b/bin/tests/names/wire_test3_1.data
@@ -0,0 +1,11 @@
+#
+# a bad compression pointer starting with the bits 1111
+#
+000a85800001000300000003
+03766978 03636f6d 00 0002 0001
+f00c 0002 0001 0000 0e10 000b 056973727631 027061 c00c
+c00c 0002 0001 0000 0e10 0009 066e732d657874 c00c
+c00c 0002 0001 0000 0e10 000e 036e7331 04676e6163 03636f6d 00
+c025 0001 0001 0000 0e10 0004 cc98b886
+c03c 0001 0001 0000 0e10 0004 cc98b840
+c051 0001 0001 0002 a14a 0004 c697f8f6
diff --git a/bin/tests/names/wire_test3_2.data b/bin/tests/names/wire_test3_2.data
new file mode 100644
index 0000000..fae2fe2
--- /dev/null
+++ b/bin/tests/names/wire_test3_2.data
@@ -0,0 +1,12 @@
+#
+# a bad compression pointer due to forward reference of 0x30 to
+# another compression pointer with a valid backreference
+#
+000a85800001000300000003
+03766978 03636f6d 00 0002 0001
+c030 0002 0001 0000 0e10 000b 056973727631 027061 c00c
+c00c 0002 0001 0000 0e10 0009 066e732d657874 c00c
+c00c 0002 0001 0000 0e10 000e 036e7331 04676e6163 03636f6d 00
+c025 0001 0001 0000 0e10 0004 cc98b886
+c03c 0001 0001 0000 0e10 0004 cc98b840
+c051 0001 0001 0002 a14a 0004 c697f8f6
diff --git a/bin/tests/names/wire_test4.data b/bin/tests/names/wire_test4.data
new file mode 100644
index 0000000..dba6035
--- /dev/null
+++ b/bin/tests/names/wire_test4.data
@@ -0,0 +1,45 @@
+#
+# invalid name length, pointer at offset 0x0226 points to
+# long name at offset 0x25
+#
+000a 8580 0001 0003 0000 0001
+03 766978 03 636f6d 00 0002 0001
+c00c 0002 0001 00000e10
+0101
+# long name starts here
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a
+03616263 0358595a 03616263 0358595a
+03414243 0378797a 03414243 0378797a 00
+# compression pointer start here and refers back to long name
+c023 0002 0001 00000e10 0009 066e732d657874 c00c
+c00c 0002 0001 00000e10 000e 036e733104676e616303636f6d00
+c025 0001 0001 00000e10 0004 cc98b886
diff --git a/bin/tests/names/wire_test5.data b/bin/tests/names/wire_test5.data
new file mode 100644
index 0000000..505134a
--- /dev/null
+++ b/bin/tests/names/wire_test5.data
@@ -0,0 +1,13 @@
+#
+# a global14 compression pointer
+#
+000a85800001000300000003
+0376697803636f6d0000020001c00c00
+02000100000e10000b05697372763102
+7061c00cc00c0002000100000e100009
+066e732d657874c00cc00c0002000100
+000e10000e036e733104676e61630363
+6f6d00c0250001000100000e100004cc
+98b886c03c0001000100000e100004cc
+98b840c051000100010002a14a0004c6
+97f8f6
diff --git a/bin/tests/names/wire_test6.data b/bin/tests/names/wire_test6.data
new file mode 100644
index 0000000..1a05d26
--- /dev/null
+++ b/bin/tests/names/wire_test6.data
@@ -0,0 +1,13 @@
+#
+# a bad pointer
+#
+000a85800001000300000003
+0376697803636f6d0000020001f00c00
+02000100000e10000b05697372763102
+7061c00cc00c0002000100000e100009
+066e732d657874c00cc00c0002000100
+000e10000e036e733104676e61630363
+6f6d00c0250001000100000e100004cc
+98b886c03c0001000100000e100004cc
+98b840c051000100010002a14a0004c6
+97f8f6
diff --git a/bin/tests/names/wire_test7.data b/bin/tests/names/wire_test7.data
new file mode 100644
index 0000000..40fbbed
--- /dev/null
+++ b/bin/tests/names/wire_test7.data
@@ -0,0 +1,5 @@
+#
+# input ends unexpectedly
+#
+000a85800001000300000003
+0376697803636f6d0000020001c0
diff --git a/bin/tests/names/wire_test8.data b/bin/tests/names/wire_test8.data
new file mode 100644
index 0000000..beabbf7
--- /dev/null
+++ b/bin/tests/names/wire_test8.data
@@ -0,0 +1,28 @@
+#
+# too many hops DNS_POINTER_MAXHOPS is defined as 16
+# in lib/dns/include/dns/name.h
+#
+000a85800001000300000013
+03 766978 03 636f6d 00 0002 0001
+c00c 0002 0001 00000e10 000b 056973727631027061 c00c
+c019 0002 0001 00000e10 0009 066e732d657874 c00c
+c030 0002 0001 00000e10 000e 036e7331 04676e6163 03636f6d 00
+c045 0001 0001 00000e10 0004 cc98b886
+c05f 0001 0001 00000e10 0004 cc98b840
+c06f 0001 0001 0002a14a 0004 c697f8f6
+c07f 0001 0001 0002a14a 0004 c697f8f6
+c08f 0001 0001 0002a14a 0004 c697f8f6
+c09f 0001 0001 0002a14a 0004 c697f8f6
+c0af 0001 0001 0002a14a 0004 c697f8f6
+c0bf 0001 0001 0002a14a 0004 c697f8f6
+c0cf 0001 0001 0002a14a 0004 c697f8f6
+c0df 0001 0001 0002a14a 0004 c697f8f6
+c0ef 0001 0001 0002a14a 0004 c697f8f6
+c0ff 0001 0001 0002a14a 0004 c697f8f6
+c10f 0001 0001 0002a14a 0004 c697f8f6
+c11f 0001 0001 0002a14a 0004 c697f8f6
+c12f 0001 0001 0002a14a 0004 c697f8f6
+c13f 0001 0001 0002a14a 0004 c697f8f6
+c14f 0001 0001 0002a14a 0004 c697f8f6
+c15f 0001 0001 0002a14a 0004 c697f8f6
+c16f 0001 0001 0002a14a 0004 c697f8f6
diff --git a/bin/tests/ndc.conf b/bin/tests/ndc.conf
new file mode 100644
index 0000000..bc2c0c6
--- /dev/null
+++ b/bin/tests/ndc.conf
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2004, 2007 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: ndc.conf,v 1.11 2007/06/19 23:46:59 tbox Exp $ */
+
+options {
+ default-server "velo.jab.fr" ;
+# [ default-key key_name; ]
+};
+
+server "velo.jab.fr" {
+ key "akey";
+ host "1.2.3.4";
+};
+
+include "ndc.conf-include";
+
+key "akey" {
+ algorithm "algo";
+ secret "c2Vj";
+};
+
diff --git a/bin/tests/ndc.conf-include b/bin/tests/ndc.conf-include
new file mode 100644
index 0000000..58d1534
--- /dev/null
+++ b/bin/tests/ndc.conf-include
@@ -0,0 +1,25 @@
+/*
+ * 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: ndc.conf-include,v 1.6 2007/06/19 23:46:59 tbox Exp $ */
+
+key "another-key" {
+ algorithm "al-gore-rhythm";
+ secret "R29yZSBpbiAyMDA0IQo"; # "Gore in 2004!"
+};
+
+
diff --git a/bin/tests/net/Makefile.in b/bin/tests/net/Makefile.in
new file mode 100644
index 0000000..0c75c28
--- /dev/null
+++ b/bin/tests/net/Makefile.in
@@ -0,0 +1,53 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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.16 2007/06/19 23:47:00 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+ISCLIBS = ../../../lib/isc/libisc.@A@
+
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${ISCDEPLIBS}
+
+LIBS = ${ISCLIBS} @LIBS@
+
+TARGETS = t_net@EXEEXT@
+
+SRCS = driver.c netaddr_multicast.c sockaddr_multicast.c
+
+OBJS = driver.@O@ netaddr_multicast.@O@ sockaddr_multicast.@O@
+
+@BIND9_MAKE_RULES@
+
+t_net@EXEEXT@: ${OBJS} ${DEPLIBS} ${TLIB}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${TLIB} ${LIBS}
+
+test: t_net@EXEEXT@
+ -@./t_net@EXEEXT@
+
+clean distclean::
+ rm -f ${TARGETS}
+ rm -f ${OBJS}
diff --git a/bin/tests/net/driver.c b/bin/tests/net/driver.c
new file mode 100644
index 0000000..a8b3bf7
--- /dev/null
+++ b/bin/tests/net/driver.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2004, 2007 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: driver.c,v 1.11 2007/06/19 23:47:00 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include "driver.h"
+
+#include "testsuite.h"
+
+#define NTESTS (sizeof(tests) / sizeof(test_t))
+
+const char *gettime(void);
+const char *test_result_totext(test_result_t);
+
+/*
+ * Not thread safe.
+ */
+const char *
+gettime(void) {
+ static char now[512];
+ time_t t;
+
+ (void)time(&t);
+
+ strftime(now, sizeof(now) - 1,
+ "%A %d %B %H:%M:%S %Y",
+ localtime(&t));
+
+ return (now);
+}
+
+const char *
+test_result_totext(test_result_t result) {
+ const char *s;
+ switch (result) {
+ case PASSED:
+ s = "PASS";
+ break;
+ case FAILED:
+ s = "FAIL";
+ break;
+ case UNTESTED:
+ s = "UNTESTED";
+ break;
+ case UNKNOWN:
+ default:
+ s = "UNKNOWN";
+ break;
+ }
+
+ return (s);
+}
+
+int
+main(int argc, char **argv) {
+ test_t *test;
+ test_result_t result;
+ unsigned int n_failed;
+ unsigned int testno;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ printf("S:%s:%s\n", SUITENAME, gettime());
+
+ n_failed = 0;
+ for (testno = 0; testno < NTESTS; testno++) {
+ test = &tests[testno];
+ printf("T:%s:%u:A\n", test->tag, testno + 1);
+ printf("A:%s\n", test->description);
+ result = test->func();
+ printf("R:%s\n", test_result_totext(result));
+ if (result != PASSED)
+ n_failed++;
+ }
+
+ printf("E:%s:%s\n", SUITENAME, gettime());
+
+ if (n_failed > 0)
+ exit(1);
+
+ return (0);
+}
+
diff --git a/bin/tests/net/driver.h b/bin/tests/net/driver.h
new file mode 100644
index 0000000..1121efc
--- /dev/null
+++ b/bin/tests/net/driver.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2004, 2007 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: driver.h,v 1.8 2007/06/19 23:47:00 tbox Exp $ */
+
+/*
+ * PASSED and FAILED mean the particular test passed or failed.
+ *
+ * UNKNOWN means that for one reason or another, the test process itself
+ * failed. For instance, missing files, error when parsing files or
+ * IP addresses, etc. That is, the test itself is broken, not what is
+ * being tested.
+ *
+ * UNTESTED means the test was unable to be run because a prerequisite test
+ * failed, the test is disabled, or the test needs a system component
+ * (for instance, Perl) and cannot run.
+ */
+typedef enum {
+ PASSED = 0,
+ FAILED = 1,
+ UNKNOWN = 2,
+ UNTESTED = 3
+} test_result_t;
+
+typedef test_result_t (*test_func_t)(void);
+
+typedef struct {
+ const char *tag;
+ const char *description;
+ test_func_t func;
+} test_t;
+
+#define TESTDECL(name) test_result_t name(void)
+
diff --git a/bin/tests/net/netaddr_multicast.c b/bin/tests/net/netaddr_multicast.c
new file mode 100644
index 0000000..79f260b
--- /dev/null
+++ b/bin/tests/net/netaddr_multicast.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004, 2007 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: netaddr_multicast.c,v 1.12 2007/06/19 23:47:00 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include "driver.h"
+
+TESTDECL(netaddr_multicast);
+
+typedef struct {
+ int family;
+ const char *addr;
+ isc_boolean_t is_multicast;
+} t_addr_t;
+
+static t_addr_t addrs[] = {
+ { AF_INET, "1.2.3.4", ISC_FALSE },
+ { AF_INET, "4.3.2.1", ISC_FALSE },
+ { AF_INET, "224.1.1.1", ISC_TRUE },
+ { AF_INET, "1.1.1.244", ISC_FALSE },
+ { AF_INET6, "::1", ISC_FALSE },
+ { AF_INET6, "ff02::1", ISC_TRUE }
+};
+#define NADDRS (sizeof(addrs) / sizeof(t_addr_t))
+
+static isc_result_t to_netaddr(t_addr_t *, isc_netaddr_t *);
+
+static isc_result_t
+to_netaddr(t_addr_t *addr, isc_netaddr_t *na) {
+ int r;
+ struct in_addr in;
+ struct in6_addr in6;
+
+ switch (addr->family) {
+ case AF_INET:
+ r = inet_pton(AF_INET, addr->addr, (unsigned char *)&in);
+ if (r != 1)
+ return (ISC_R_FAILURE);
+ isc_netaddr_fromin(na, &in);
+ break;
+ case AF_INET6:
+ r = inet_pton(AF_INET6, addr->addr, (unsigned char *)&in6);
+ if (r != 1)
+ return (ISC_R_FAILURE);
+ isc_netaddr_fromin6(na, &in6);
+ break;
+ default:
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+test_result_t
+netaddr_multicast(void) {
+ isc_netaddr_t na;
+ unsigned int n_fail;
+ t_addr_t *addr;
+ unsigned int i;
+ isc_result_t result;
+ isc_boolean_t tf;
+
+ n_fail = 0;
+ for (i = 0; i < NADDRS; i++) {
+ addr = &addrs[i];
+ result = to_netaddr(addr, &na);
+ if (result != ISC_R_SUCCESS) {
+ printf("I:to_netaddr() returned %s on item %u\n",
+ isc_result_totext(result), i);
+ return (UNKNOWN);
+ }
+ tf = isc_netaddr_ismulticast(&na);
+ if (tf == addr->is_multicast) {
+ printf("I:%s is%s multicast (PASSED)\n",
+ (addr->addr), (tf ? "" : " not"));
+ } else {
+ printf("I:%s is%s multicast (FAILED)\n",
+ (addr->addr), (tf ? "" : " not"));
+ n_fail++;
+ }
+ }
+
+ if (n_fail > 0)
+ return (FAILED);
+
+ return (PASSED);
+}
diff --git a/bin/tests/net/sockaddr_multicast.c b/bin/tests/net/sockaddr_multicast.c
new file mode 100644
index 0000000..cfe04dc
--- /dev/null
+++ b/bin/tests/net/sockaddr_multicast.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2004, 2007 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: sockaddr_multicast.c,v 1.8 2007/06/19 23:47:00 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include "driver.h"
+
+TESTDECL(sockaddr_multicast);
+
+test_result_t
+sockaddr_multicast(void) {
+
+ return (PASSED);
+}
diff --git a/bin/tests/net/testsuite.h b/bin/tests/net/testsuite.h
new file mode 100644
index 0000000..68a214c
--- /dev/null
+++ b/bin/tests/net/testsuite.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004, 2007 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: testsuite.h,v 1.7 2007/06/19 23:47:00 tbox Exp $ */
+
+#define SUITENAME "net"
+
+TESTDECL(netaddr_multicast);
+TESTDECL(sockaddr_multicast);
+
+static test_t tests[] = {
+ { "isc_netaddr_ismulticast",
+ "Checking to see if multicast addresses are detected properly",
+ netaddr_multicast },
+ { "isc_sockaddr_ismulticast",
+ "Checking to see if multicast addresses are detected properly",
+ sockaddr_multicast },
+
+};
diff --git a/bin/tests/nsec3hash.c b/bin/tests/nsec3hash.c
new file mode 100644
index 0000000..4a4a782
--- /dev/null
+++ b/bin/tests/nsec3hash.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2006, 2008 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.4 2008/09/26 01:31:19 marka Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <isc/base32.h>
+#include <isc/buffer.h>
+#include <isc/hex.h>
+#include <isc/iterated_hash.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/types.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/types.h>
+
+const char *program = "nsec3hash";
+
+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[255];
+ 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 > 255U)
+ 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(&region, 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/tests/nsecify.c b/bin/tests/nsecify.c
new file mode 100644
index 0000000..2e055c6
--- /dev/null
+++ b/bin/tests/nsecify.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 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
+ * 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: nsecify.c,v 1.8 2008/09/25 04:02:38 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/nsec.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+
+static isc_mem_t *mctx = NULL;
+
+static inline void
+fatal(const char *message) {
+ fprintf(stderr, "%s\n", message);
+ exit(1);
+}
+
+static inline void
+check_result(isc_result_t result, const char *message) {
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "%s: %s\n", message,
+ isc_result_totext(result));
+ exit(1);
+ }
+}
+
+static inline isc_boolean_t
+active_node(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
+ dns_rdatasetiter_t *rdsiter;
+ isc_boolean_t active = ISC_FALSE;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ if (rdataset.type != dns_rdatatype_nsec)
+ active = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ if (!active)
+ result = dns_rdatasetiter_next(rdsiter);
+ else
+ result = ISC_R_NOMORE;
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdataset iteration failed");
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ if (!active) {
+ /*
+ * Make sure there is no NSEC record for this node.
+ */
+ result = dns_db_deleterdataset(db, node, version,
+ dns_rdatatype_nsec, 0);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ check_result(result, "dns_db_deleterdataset");
+ }
+
+ return (active);
+}
+
+static inline isc_result_t
+next_active(dns_db_t *db, dns_dbversion_t *version, dns_dbiterator_t *dbiter,
+ dns_name_t *name, dns_dbnode_t **nodep)
+{
+ isc_result_t result;
+ isc_boolean_t active;
+
+ do {
+ active = ISC_FALSE;
+ result = dns_dbiterator_current(dbiter, nodep, name);
+ if (result == ISC_R_SUCCESS) {
+ active = active_node(db, version, *nodep);
+ if (!active) {
+ dns_db_detachnode(db, nodep);
+ result = dns_dbiterator_next(dbiter);
+ }
+ }
+ } while (result == ISC_R_SUCCESS && !active);
+
+ return (result);
+}
+
+static void
+nsecify(char *filename) {
+ isc_result_t result;
+ dns_db_t *db;
+ dns_dbversion_t *wversion;
+ dns_dbnode_t *node, *nextnode;
+ char *origintext;
+ dns_fixedname_t fname, fnextname;
+ dns_name_t *name, *nextname, *target;
+ isc_buffer_t b;
+ size_t len;
+ dns_dbiterator_t *dbiter;
+ char newfilename[1024];
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_fixedname_init(&fnextname);
+ nextname = dns_fixedname_name(&fnextname);
+
+ origintext = strrchr(filename, '/');
+ if (origintext == NULL)
+ origintext = filename;
+ else
+ origintext++; /* Skip '/'. */
+ len = strlen(origintext);
+ isc_buffer_init(&b, origintext, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
+ check_result(result, "dns_name_fromtext()");
+
+ db = NULL;
+ result = dns_db_create(mctx, "rbt", name, dns_dbtype_zone,
+ dns_rdataclass_in, 0, NULL, &db);
+ check_result(result, "dns_db_create()");
+ result = dns_db_load(db, filename);
+ if (result == DNS_R_SEENINCLUDE)
+ result = ISC_R_SUCCESS;
+ check_result(result, "dns_db_load()");
+ wversion = NULL;
+ result = dns_db_newversion(db, &wversion);
+ check_result(result, "dns_db_newversion()");
+ dbiter = NULL;
+ result = dns_db_createiterator(db, 0, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+ result = dns_dbiterator_first(dbiter);
+ node = NULL;
+ result = next_active(db, wversion, dbiter, name, &node);
+ while (result == ISC_R_SUCCESS) {
+ nextnode = NULL;
+ result = dns_dbiterator_next(dbiter);
+ if (result == ISC_R_SUCCESS)
+ result = next_active(db, wversion, dbiter, nextname,
+ &nextnode);
+ if (result == ISC_R_SUCCESS)
+ target = nextname;
+ else if (result == ISC_R_NOMORE)
+ target = dns_db_origin(db);
+ else {
+ target = NULL; /* Make compiler happy. */
+ fatal("db iteration failed");
+ }
+ dns_nsec_build(db, wversion, node, target, 3600); /* XXX BEW */
+ dns_db_detachnode(db, &node);
+ node = nextnode;
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("db iteration failed");
+ dns_dbiterator_destroy(&dbiter);
+ /*
+ * XXXRTH For now, we don't increment the SOA serial.
+ */
+ dns_db_closeversion(db, &wversion, ISC_TRUE);
+ len = strlen(filename);
+ if (len + 4 + 1 > sizeof(newfilename))
+ fatal("filename too long");
+ sprintf(newfilename, "%s.new", filename);
+ result = dns_db_dump(db, NULL, newfilename);
+ check_result(result, "dns_db_dump");
+ dns_db_detach(&db);
+}
+
+int
+main(int argc, char *argv[]) {
+ int i;
+ isc_result_t result;
+
+ dns_result_register();
+
+ result = isc_mem_create(0, 0, &mctx);
+ check_result(result, "isc_mem_create()");
+
+ argc--;
+ argv++;
+
+ for (i = 0; i < argc; i++)
+ nsecify(argv[i]);
+
+ /* isc_mem_stats(mctx, stdout); */
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/printmsg.c b/bin/tests/printmsg.c
new file mode 100644
index 0000000..c500e85
--- /dev/null
+++ b/bin/tests/printmsg.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: printmsg.c,v 1.29 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/util.h>
+
+#include <dns/name.h>
+#include <dns/rdataset.h>
+
+#include "printmsg.h"
+
+static const char *opcodetext[] = {
+ "QUERY",
+ "IQUERY",
+ "STATUS",
+ "RESERVED3",
+ "NOTIFY",
+ "UPDATE",
+ "RESERVED6",
+ "RESERVED7",
+ "RESERVED8",
+ "RESERVED9",
+ "RESERVED10",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15"
+};
+
+static const char *rcodetext[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15",
+ "BADVERS"
+};
+
+static isc_result_t
+printsection(dns_message_t *msg, dns_section_t sectionid,
+ const char *section_name)
+{
+ dns_name_t *name, *print_name;
+ dns_rdataset_t *rdataset;
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ dns_name_t empty_name;
+ char t[65536];
+ isc_boolean_t first;
+ isc_boolean_t no_rdata;
+
+ if (sectionid == DNS_SECTION_QUESTION)
+ no_rdata = ISC_TRUE;
+ else
+ no_rdata = ISC_FALSE;
+
+ printf(";; %s SECTION:\n", section_name);
+
+ dns_name_init(&empty_name, NULL);
+
+ result = dns_message_firstname(msg, sectionid);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, sectionid, &name);
+
+ isc_buffer_init(&target, t, sizeof(t));
+ first = ISC_TRUE;
+ print_name = name;
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ result = dns_rdataset_totext(rdataset,
+ print_name,
+ ISC_FALSE,
+ no_rdata,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#ifdef USEINITALWS
+ if (first) {
+ print_name = &empty_name;
+ first = ISC_FALSE;
+ }
+#endif
+ }
+ isc_buffer_usedregion(&target, &r);
+ printf("%.*s", (int)r.length, (char *)r.base);
+
+ result = dns_message_nextname(msg, sectionid);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner,
+ const char *set_name)
+{
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ char t[65536];
+
+ UNUSED(msg);
+ printf(";; %s SECTION:\n", set_name);
+
+ 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_result_t
+printmessage(dns_message_t *msg) {
+ isc_boolean_t did_flag = ISC_FALSE;
+ isc_result_t result;
+ dns_rdataset_t *opt, *tsig;
+ dns_name_t *tsigname;
+
+ result = ISC_R_SUCCESS;
+
+ printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n",
+ opcodetext[msg->opcode], rcodetext[msg->rcode], msg->id);
+
+ printf(";; flags: ");
+ if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
+ printf("qr");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
+ printf("%saa", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
+ printf("%stc", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
+ printf("%srd", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
+ printf("%sra", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
+ printf("%sad", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
+ printf("%scd", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ printf("; QUERY: %u, ANSWER: %u, AUTHORITY: %u, ADDITIONAL: %u\n",
+ msg->counts[DNS_SECTION_QUESTION],
+ msg->counts[DNS_SECTION_ANSWER],
+ msg->counts[DNS_SECTION_AUTHORITY],
+ msg->counts[DNS_SECTION_ADDITIONAL]);
+ opt = dns_message_getopt(msg);
+ if (opt != NULL)
+ printf(";; EDNS: version: %u, udp=%u\n",
+ (unsigned int)((opt->ttl & 0x00ff0000) >> 16),
+ (unsigned int)opt->rdclass);
+
+ tsigname = NULL;
+ tsig = dns_message_gettsig(msg, &tsigname);
+ if (tsig != NULL)
+ printf(";; PSEUDOSECTIONS: TSIG\n");
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION])) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY])) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL])) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_ADDITIONAL,
+ "ADDITIONAL");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (tsig != NULL) {
+ printf("\n");
+ result = printrdata(msg, tsig, tsigname,
+ "PSEUDOSECTION TSIG");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ printf("\n");
+
+ return (result);
+}
diff --git a/bin/tests/printmsg.h b/bin/tests/printmsg.h
new file mode 100644
index 0000000..c918561
--- /dev/null
+++ b/bin/tests/printmsg.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: printmsg.h,v 1.12 2007/06/19 23:46:59 tbox Exp $ */
+
+#ifndef TEST_PRINTMSG_H
+#define TEST_PRINTMSG_H
+
+#include <dns/message.h>
+
+isc_result_t printmessage(dns_message_t *message);
+
+#endif /* TEST_PRINTMSG_H */
diff --git a/bin/tests/ratelimiter_test.c b/bin/tests/ratelimiter_test.c
new file mode 100644
index 0000000..9fd4a13
--- /dev/null
+++ b/bin/tests/ratelimiter_test.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: ratelimiter_test.c,v 1.18 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/app.h>
+#include <isc/mem.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/ratelimiter.h>
+#include <isc/util.h>
+
+isc_ratelimiter_t *rlim = NULL;
+isc_taskmgr_t *taskmgr = NULL;
+isc_timermgr_t *timermgr = NULL;
+isc_task_t *g_task = NULL;
+isc_mem_t *mctx = NULL;
+
+static void utick(isc_task_t *task, isc_event_t *event);
+static void shutdown_rl(isc_task_t *task, isc_event_t *event);
+static void shutdown_all(isc_task_t *task, isc_event_t *event);
+
+typedef struct {
+ int milliseconds;
+ void (*fun)(isc_task_t *, isc_event_t *);
+} schedule_t;
+
+schedule_t schedule[] = {
+ { 100, utick },
+ { 200, utick },
+ { 300, utick },
+ { 3000, utick },
+ { 3100, utick },
+ { 3200, utick },
+ { 3300, shutdown_rl },
+ { 5000, utick },
+ { 6000, shutdown_all }
+};
+
+#define NEVENTS (int)(sizeof(schedule)/sizeof(schedule[0]))
+
+isc_timer_t *timers[NEVENTS];
+
+static void
+ltick(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+ printf("** ltick%s **\n",
+ (event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ?
+ " (canceled)" : "");
+ isc_event_free(&event);
+}
+
+static void
+utick(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ UNUSED(task);
+ event->ev_action = ltick;
+ event->ev_sender = NULL;
+ result = isc_ratelimiter_enqueue(rlim, g_task, &event);
+ printf("enqueue: %s\n",
+ result == ISC_R_SUCCESS ? "ok" : "failed");
+}
+
+static void
+shutdown_rl(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+ UNUSED(event);
+ printf("shutdown ratelimiter\n");
+ isc_ratelimiter_shutdown(rlim);
+}
+
+static void
+shutdown_all(isc_task_t *task, isc_event_t *event) {
+ int i;
+ UNUSED(task);
+ UNUSED(event);
+ printf("shutdown all\n");
+ for (i = 0; i < NEVENTS; i++) {
+ isc_timer_detach(&timers[i]);
+ }
+
+ isc_app_shutdown();
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_interval_t linterval;
+ int i;
+
+ UNUSED(argc);
+ UNUSED(argv);
+
+ isc_app_start();
+ isc_interval_set(&linterval, 1, 0);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, 3, 0, &taskmgr) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(taskmgr, 0, &g_task) ==
+ ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_ratelimiter_create(mctx, timermgr, g_task,
+ &rlim) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_ratelimiter_setinterval(rlim, &linterval) ==
+ ISC_R_SUCCESS);
+
+ for (i = 0; i < NEVENTS; i++) {
+ isc_interval_t uinterval;
+ int ms = schedule[i].milliseconds;
+ isc_interval_set(&uinterval, ms / 1000,
+ (ms % 1000) * 1000000);
+ timers[i] = NULL;
+ RUNTIME_CHECK(isc_timer_create(timermgr,
+ isc_timertype_once, NULL,
+ &uinterval,
+ g_task, schedule[i].fun, NULL,
+ &timers[i]) == ISC_R_SUCCESS);
+ }
+
+ isc_app_run();
+
+ isc_task_destroy(&g_task);
+
+ isc_ratelimiter_detach(&rlim);
+
+ isc_timermgr_destroy(&timermgr);
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_mem_stats(mctx, stdout);
+
+ isc_app_finish();
+ return (0);
+}
diff --git a/bin/tests/rbt/Makefile.in b/bin/tests/rbt/Makefile.in
new file mode 100644
index 0000000..d551297
--- /dev/null
+++ b/bin/tests/rbt/Makefile.in
@@ -0,0 +1,58 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-2002 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.28 2007/06/19 23:47:00 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${TEST_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+# Note that we do not want to use libtool for libt_api
+DNSLIBS = ../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../../lib/isc/libisc.@A@
+
+DNSDEPLIBS = ../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+TLIB = ../../../lib/tests/libt_api.@A@
+
+TARGETS = t_rbt@EXEEXT@
+
+SRCS = t_rbt.c
+
+@BIND9_MAKE_RULES@
+
+t_rbt@EXEEXT@: t_rbt.@O@ ${DEPLIBS} ${TLIB}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_rbt.@O@ ${TLIB} ${LIBS}
+
+test: t_rbt@EXEEXT@
+ -@./t_rbt@EXEEXT@ -c @top_srcdir@/t_config -b @srcdir@ -a
+
+testhelp:
+ @./t_rbt@EXEEXT@ -h
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/rbt/dns_rbt.data b/bin/tests/rbt/dns_rbt.data
new file mode 100644
index 0000000..e58eb45
--- /dev/null
+++ b/bin/tests/rbt/dns_rbt.data
@@ -0,0 +1,14 @@
+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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+a.b.c.d.e.f.vix.com
+a.d.e.f.vix.com
+a.vix.com
+b.b.c.d.e.f.vix.com
+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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+b.vix.com
+c.b.c.d.e.f.vix.com
+c.vix.com
+d.e.f.vix.com
+g.h.vix.com
+q.d.e.f.vix.com
+x.a.vix.com
+y.x.a.vix.com
diff --git a/bin/tests/rbt/dns_rbt_addname_1_data b/bin/tests/rbt/dns_rbt_addname_1_data
new file mode 100644
index 0000000..89dca40
--- /dev/null
+++ b/bin/tests/rbt/dns_rbt_addname_1_data
@@ -0,0 +1,6 @@
+#
+# test data for dns_rbt_addname assertion 1
+#
+# format is: <dbfile> <command> <testname> <exp_result>
+#
+dns_rbt.data add new.name ISC_R_SUCCESS
diff --git a/bin/tests/rbt/dns_rbt_addname_2_data b/bin/tests/rbt/dns_rbt_addname_2_data
new file mode 100644
index 0000000..762bd8b
--- /dev/null
+++ b/bin/tests/rbt/dns_rbt_addname_2_data
@@ -0,0 +1,6 @@
+#
+# test data for dns_rbt_addname assertion 2
+#
+# format is: <dbfile> <command> <testname> <exp_result>
+#
+dns_rbt.data add a.vix.com ISC_R_EXISTS
diff --git a/bin/tests/rbt/dns_rbt_bitstring.data b/bin/tests/rbt/dns_rbt_bitstring.data
new file mode 100644
index 0000000..2b34cc6
--- /dev/null
+++ b/bin/tests/rbt/dns_rbt_bitstring.data
@@ -0,0 +1,10 @@
+a.vix.com
+b.vix.com
+c.vix.com
+a.a.vix.com
+a.a.a.vix.com
+a.a.a.a.vix.com
+a.a.a.a.a.vix.com
+a.a.a.a.a.a.vix.com
+a.a.a.a.a.a.a.vix.com
+a.a.a.a.a.a.a.a.vix.com
diff --git a/bin/tests/rbt/dns_rbt_create_1_data b/bin/tests/rbt/dns_rbt_create_1_data
new file mode 100644
index 0000000..72f8dc4
--- /dev/null
+++ b/bin/tests/rbt/dns_rbt_create_1_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_rbt_create assertion 1
+#
+# format is: <dbfile> <command> <testname> <exp_result>
+#
+dns_rbt.data create not.used ISC_R_SUCCESS
+dns_rbt_bitstring.data create not.used ISC_R_SUCCESS
diff --git a/bin/tests/rbt/dns_rbt_deletename_1_data b/bin/tests/rbt/dns_rbt_deletename_1_data
new file mode 100644
index 0000000..2e00e50
--- /dev/null
+++ b/bin/tests/rbt/dns_rbt_deletename_1_data
@@ -0,0 +1,6 @@
+#
+# test data for dns_rbt_delete assertion 1
+#
+# format is: <dbfile> <command> <testname> <exp_result>
+#
+dns_rbt.data delete a.vix.com ISC_R_SUCCESS
diff --git a/bin/tests/rbt/dns_rbt_deletename_2_data b/bin/tests/rbt/dns_rbt_deletename_2_data
new file mode 100644
index 0000000..0b1fdb7
--- /dev/null
+++ b/bin/tests/rbt/dns_rbt_deletename_2_data
@@ -0,0 +1,6 @@
+#
+# test data for dns_rbt_delete assertion 2
+#
+# format is: <dbfile> <command> <testname> <exp_result>
+#
+dns_rbt.data delete new.name ISC_R_NOTFOUND
diff --git a/bin/tests/rbt/dns_rbt_findname_1_data b/bin/tests/rbt/dns_rbt_findname_1_data
new file mode 100644
index 0000000..2a3728d
--- /dev/null
+++ b/bin/tests/rbt/dns_rbt_findname_1_data
@@ -0,0 +1,6 @@
+#
+# test data for dns_rbt_findname assertion 1
+#
+# format is: <dbfile> <command> <testname> <exp_result>
+#
+dns_rbt.data search a.vix.com ISC_R_SUCCESS
diff --git a/bin/tests/rbt/dns_rbt_findname_2_data b/bin/tests/rbt/dns_rbt_findname_2_data
new file mode 100644
index 0000000..eb3d467
--- /dev/null
+++ b/bin/tests/rbt/dns_rbt_findname_2_data
@@ -0,0 +1,6 @@
+#
+# test data for dns_rbt_findname assertion 2
+#
+# format is: <dbfile> <command> <testname> <exp_result>
+#
+dns_rbt.data search not.used.here ISC_R_NOTFOUND
diff --git a/bin/tests/rbt/dns_rbt_findname_3_data b/bin/tests/rbt/dns_rbt_findname_3_data
new file mode 100644
index 0000000..4ea2db3
--- /dev/null
+++ b/bin/tests/rbt/dns_rbt_findname_3_data
@@ -0,0 +1,6 @@
+#
+# test data for dns_rbt_findname assertion 3
+#
+# format is: <dbfile> <command> <testname> <exp_result>
+#
+dns_rbt.data search a.b.vix.com DNS_R_PARTIALMATCH
diff --git a/bin/tests/rbt/dns_rbtnodechain_first_1.data b/bin/tests/rbt/dns_rbtnodechain_first_1.data
new file mode 100644
index 0000000..85bd8c2
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_first_1.data
@@ -0,0 +1,13 @@
+b.com
+a.vix.com
+b.vix.com
+c.vix.com
+a.a.vix.com
+b.a.vix.com
+a.b.vix.com
+b.b.vix.com
+a.c.vix.com
+b.c.vix.com
+iengines.net
+isc.org
+
diff --git a/bin/tests/rbt/dns_rbtnodechain_first_2.data b/bin/tests/rbt/dns_rbtnodechain_first_2.data
new file mode 100644
index 0000000..268376b
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_first_2.data
@@ -0,0 +1,9 @@
+a.a.vix.com
+b.a.vix.com
+a.b.vix.com
+b.b.vix.com
+a.c.vix.com
+b.c.vix.com
+iengines.net
+isc.org
+
diff --git a/bin/tests/rbt/dns_rbtnodechain_first_data b/bin/tests/rbt/dns_rbtnodechain_first_data
new file mode 100644
index 0000000..057a1d6
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_first_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_rbtnodechain_first
+#
+# format is: <dbfile> <firstname> <firstorigin> <nextname> <nextorigin>
+#
+dns_rbtnodechain_first_1.data @ . com .
+dns_rbtnodechain_first_2.data @ . vix.com .
diff --git a/bin/tests/rbt/dns_rbtnodechain_init.data b/bin/tests/rbt/dns_rbtnodechain_init.data
new file mode 100644
index 0000000..1e0bfc9
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_init.data
@@ -0,0 +1,13 @@
+vix.com
+a.vix.com
+b.vix.com
+c.vix.com
+a.a.vix.com
+b.a.vix.com
+a.b.vix.com
+b.b.vix.com
+a.c.vix.com
+b.c.vix.com
+iengines.net
+isc.org
+
diff --git a/bin/tests/rbt/dns_rbtnodechain_init_data b/bin/tests/rbt/dns_rbtnodechain_init_data
new file mode 100644
index 0000000..f1a6aa4
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_init_data
@@ -0,0 +1,6 @@
+#
+# test data for dns_rbtnodechain_init
+#
+# format is: <dbfile> <findnode> <next> <nextorigin> <prev> <prevorigin> <first> <firstorigin> <last> <lastorigin>
+#
+dns_rbtnodechain_init.data b.vix.com. a b.vix.com. b a.vix.com. @ . isc.org .
diff --git a/bin/tests/rbt/dns_rbtnodechain_last_1.data b/bin/tests/rbt/dns_rbtnodechain_last_1.data
new file mode 100644
index 0000000..1e0bfc9
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_last_1.data
@@ -0,0 +1,13 @@
+vix.com
+a.vix.com
+b.vix.com
+c.vix.com
+a.a.vix.com
+b.a.vix.com
+a.b.vix.com
+b.b.vix.com
+a.c.vix.com
+b.c.vix.com
+iengines.net
+isc.org
+
diff --git a/bin/tests/rbt/dns_rbtnodechain_last_2.data b/bin/tests/rbt/dns_rbtnodechain_last_2.data
new file mode 100644
index 0000000..4d0c76d
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_last_2.data
@@ -0,0 +1,7 @@
+a.b.vix.com
+b.b.vix.com
+a.c.vix.com
+b.c.vix.com
+vayu.com
+isc.org
+
diff --git a/bin/tests/rbt/dns_rbtnodechain_last_data b/bin/tests/rbt/dns_rbtnodechain_last_data
new file mode 100644
index 0000000..bf06a21
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_last_data
@@ -0,0 +1,7 @@
+#
+# test data for dns_rbtnodechain_last
+#
+# format is: <dbfile> <last> <lastorigin> <prev> <prevorigin>
+#
+dns_rbtnodechain_last_1.data isc.org . iengines.net .
+dns_rbtnodechain_last_2.data isc.org . b c.vix.com.
diff --git a/bin/tests/rbt/dns_rbtnodechain_next.data b/bin/tests/rbt/dns_rbtnodechain_next.data
new file mode 100644
index 0000000..1e0bfc9
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_next.data
@@ -0,0 +1,13 @@
+vix.com
+a.vix.com
+b.vix.com
+c.vix.com
+a.a.vix.com
+b.a.vix.com
+a.b.vix.com
+b.b.vix.com
+a.c.vix.com
+b.c.vix.com
+iengines.net
+isc.org
+
diff --git a/bin/tests/rbt/dns_rbtnodechain_next_data b/bin/tests/rbt/dns_rbtnodechain_next_data
new file mode 100644
index 0000000..a69ab37
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_next_data
@@ -0,0 +1,6 @@
+#
+# test data for dns_rbtnodechain_next
+#
+# format is: <dbfile> <startname> <expected_name> <expected_origin>
+#
+dns_rbtnodechain_next.data c.vix.com. a c.vix.com.
diff --git a/bin/tests/rbt/dns_rbtnodechain_prev.data b/bin/tests/rbt/dns_rbtnodechain_prev.data
new file mode 100644
index 0000000..1e0bfc9
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_prev.data
@@ -0,0 +1,13 @@
+vix.com
+a.vix.com
+b.vix.com
+c.vix.com
+a.a.vix.com
+b.a.vix.com
+a.b.vix.com
+b.b.vix.com
+a.c.vix.com
+b.c.vix.com
+iengines.net
+isc.org
+
diff --git a/bin/tests/rbt/dns_rbtnodechain_prev_data b/bin/tests/rbt/dns_rbtnodechain_prev_data
new file mode 100644
index 0000000..4c8450d
--- /dev/null
+++ b/bin/tests/rbt/dns_rbtnodechain_prev_data
@@ -0,0 +1,6 @@
+#
+# test data for dns_rbtnodechain_prev
+#
+# format is: <dbfile> <startname> <expected_name> <expected_origin>
+#
+dns_rbtnodechain_prev.data a.b.vix.com. b vix.com.
diff --git a/bin/tests/rbt/t_rbt.c b/bin/tests/rbt/t_rbt.c
new file mode 100644
index 0000000..171e633
--- /dev/null
+++ b/bin/tests/rbt/t_rbt.c
@@ -0,0 +1,1857 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: t_rbt.c,v 1.30 2007/06/19 23:47:00 tbox Exp $ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+#include <isc/hash.h>
+#include <isc/string.h>
+
+#include <dns/fixedname.h>
+#include <dns/rbt.h>
+#include <dns/result.h>
+
+#include <tests/t_api.h>
+
+#define BUFLEN 1024
+#define DNSNAMELEN 255
+
+char *progname;
+char *Tokens[T_MAXTOKS];
+
+static int
+t_dns_rbtnodechain_init(char *dbfile, char *findname,
+ char *firstname, char *firstorigin,
+ char *nextname, char *nextorigin,
+ char *prevname, char *prevorigin,
+ char *lastname, char *lastorigin);
+static char *
+fixedname_totext(dns_fixedname_t *name);
+
+static int
+fixedname_cmp(dns_fixedname_t *dns_name, char *txtname);
+
+static char *
+dnsname_totext(dns_name_t *name);
+
+static int
+t_namechk(isc_result_t dns_result, dns_fixedname_t *dns_name, char *exp_name,
+ dns_fixedname_t *dns_origin, char *exp_origin,
+ isc_result_t exp_result);
+
+/*
+ * Parts adapted from the original rbt_test.c.
+ */
+static int
+fixedname_cmp(dns_fixedname_t *dns_name, char *txtname) {
+ char *name;
+
+ name = dnsname_totext(dns_fixedname_name(dns_name));
+ if (strcmp(txtname, "NULL") == 0) {
+ if ((name == NULL) || (*name == '\0'))
+ return(0);
+ return(1);
+ } else {
+ return(strcmp(name, txtname));
+ }
+}
+
+static char *
+dnsname_totext(dns_name_t *name) {
+ static char buf[BUFLEN];
+ isc_buffer_t target;
+
+ isc_buffer_init(&target, buf, BUFLEN);
+ dns_name_totext(name, ISC_FALSE, &target);
+ *((char *)(target.base) + target.used) = '\0';
+ return(target.base);
+}
+
+static char *
+fixedname_totext(dns_fixedname_t *name) {
+ static char buf[BUFLEN];
+ isc_buffer_t target;
+
+ memset(buf, 0, BUFLEN);
+ isc_buffer_init(&target, buf, BUFLEN);
+ dns_name_totext(dns_fixedname_name(name), ISC_FALSE, &target);
+ *((char *)(target.base) + target.used) = '\0';
+ return(target.base);
+}
+
+#ifdef NEED_PRINT_DATA
+
+static isc_result_t
+print_data(void *data) {
+ isc_result_t dns_result;
+ isc_buffer_t target;
+ char *buffer[DNSNAMELEN];
+
+ isc_buffer_init(&target, buffer, sizeof(buffer));
+
+ dns_result = dns_name_totext(data, ISC_FALSE, &target);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_totext failed %s\n",
+ dns_result_totext(dns_result));
+ }
+ return(dns_result);
+}
+
+#endif /* NEED_PRINT_DATA */
+
+static int
+create_name(char *s, isc_mem_t *mctx, dns_name_t **dns_name) {
+ int nfails;
+ int length;
+ isc_result_t result;
+ isc_buffer_t source;
+ isc_buffer_t target;
+ dns_name_t *name;
+
+ nfails = 0;
+
+ if (s && *s) {
+
+ length = strlen(s);
+
+ isc_buffer_init(&source, s, length);
+ isc_buffer_add(&source, length);
+
+ /*
+ * The buffer for the actual name will immediately follow the
+ * name structure.
+ */
+ name = isc_mem_get(mctx, sizeof(*name) + DNSNAMELEN);
+ if (name == NULL) {
+ t_info("isc_mem_get failed\n");
+ ++nfails;
+ } else {
+
+ dns_name_init(name, NULL);
+ isc_buffer_init(&target, name + 1, DNSNAMELEN);
+
+ result = dns_name_fromtext(name, &source, dns_rootname,
+ ISC_FALSE, &target);
+
+ if (result != ISC_R_SUCCESS) {
+ ++nfails;
+ t_info("dns_name_fromtext(%s) failed %s\n",
+ s, dns_result_totext(result));
+ isc_mem_put(mctx, name,
+ sizeof(*name) + DNSNAMELEN);
+ } else
+ *dns_name = name;
+ }
+ } else {
+ ++nfails;
+ t_info("create_name: empty name\n");
+ }
+
+ return(nfails);
+}
+
+static void
+delete_name(void *data, void *arg) {
+ isc_mem_put((isc_mem_t *)arg, data, sizeof(dns_name_t) + DNSNAMELEN);
+}
+
+
+/*
+ * Adapted from the original rbt_test.c.
+ */
+static int
+t1_add(char *name, dns_rbt_t *rbt, isc_mem_t *mctx, isc_result_t *dns_result) {
+ int nprobs;
+ dns_name_t *dns_name;
+
+ nprobs = 0;
+ if (name && dns_result) {
+ if (create_name(name, mctx, &dns_name) == 0) {
+ if (T_debug)
+ t_info("dns_rbt_addname succeeded\n");
+ *dns_result = dns_rbt_addname(rbt, dns_name, dns_name);
+ if (*dns_result != ISC_R_SUCCESS) {
+ delete_name(dns_name, mctx);
+ t_info("dns_rbt_addname failed %s\n",
+ dns_result_totext(*dns_result));
+ ++nprobs;
+ }
+ } else {
+ ++nprobs;
+ }
+ } else {
+ ++nprobs;
+ }
+ return(nprobs);
+}
+
+static int
+t1_delete(char *name, dns_rbt_t *rbt, isc_mem_t *mctx,
+ isc_result_t *dns_result)
+{
+ int nprobs;
+ dns_name_t *dns_name;
+
+ nprobs = 0;
+ if (name && dns_result) {
+ if (create_name(name, mctx, &dns_name) == 0) {
+ *dns_result = dns_rbt_deletename(rbt, dns_name,
+ ISC_FALSE);
+ delete_name(dns_name, mctx);
+ } else {
+ ++nprobs;
+ }
+ } else {
+ ++nprobs;
+ }
+ return(nprobs);
+}
+
+static int
+t1_search(char *name, dns_rbt_t *rbt, isc_mem_t *mctx,
+ isc_result_t *dns_result)
+{
+ int nprobs;
+ dns_name_t *dns_searchname;
+ dns_name_t *dns_foundname;
+ dns_fixedname_t dns_fixedname;
+ void *data;
+
+ nprobs = 0;
+ if (name && dns_result) {
+ if (create_name(name, mctx, &dns_searchname) == 0) {
+ dns_fixedname_init(&dns_fixedname);
+ dns_foundname = dns_fixedname_name(&dns_fixedname);
+ data = NULL;
+ *dns_result = dns_rbt_findname(rbt, dns_searchname, 0,
+ dns_foundname, &data);
+ delete_name(dns_searchname, mctx);
+ } else {
+ ++nprobs;
+ }
+ } else {
+ ++nprobs;
+ }
+ return(nprobs);
+}
+
+/*
+ * Initialize a database from filename.
+ */
+static int
+rbt_init(char *filename, dns_rbt_t **rbt, isc_mem_t *mctx) {
+ int rval;
+ isc_result_t dns_result;
+ char *p;
+ FILE *fp;
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ t_info("No such file %s\n", filename);
+ return(1);
+ }
+
+ dns_result = dns_rbt_create(mctx, delete_name, mctx, rbt);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rbt_create failed %s\n",
+ dns_result_totext(dns_result));
+ fclose(fp);
+ return(1);
+ }
+
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ /*
+ * Skip any comment lines.
+ */
+ if ((*p == '#') || (*p == '\0') || (*p == ' ')) {
+ (void)free(p);
+ continue;
+ }
+
+ if (T_debug)
+ t_info("adding name %s to the rbt\n", p);
+
+ rval = t1_add(p, *rbt, mctx, &dns_result);
+ if ((rval != 0) || (dns_result != ISC_R_SUCCESS)) {
+ t_info("add of %s failed\n", p);
+ dns_rbt_destroy(rbt);
+ fclose(fp);
+ return(1);
+ }
+ (void) free(p);
+ }
+ fclose(fp);
+ return(0);
+}
+
+static int
+test_rbt_gen(char *filename, char *command, char *testname,
+ isc_result_t exp_result)
+{
+ int rval;
+ int result;
+ dns_rbt_t *rbt;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_name_t *dns_name;
+
+ result = T_UNRESOLVED;
+
+ if (strcmp(command, "create") != 0)
+ t_info("testing using name %s\n", testname);
+
+ mctx = NULL;
+ ectx = NULL;
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ rbt = NULL;
+ if (rbt_init(filename, &rbt, mctx) != 0) {
+ if (strcmp(command, "create") == 0)
+ result = T_FAIL;
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ /*
+ * Now try the database command.
+ */
+ if (strcmp(command, "create") == 0) {
+ result = T_PASS;
+ } else if (strcmp(command, "add") == 0) {
+ if (create_name(testname, mctx, &dns_name) == 0) {
+ dns_result = dns_rbt_addname(rbt, dns_name, dns_name);
+
+ if (dns_result != ISC_R_SUCCESS)
+ delete_name(dns_name, mctx);
+
+ if (dns_result == exp_result) {
+ if (dns_result == ISC_R_SUCCESS) {
+ rval = t1_search(testname, rbt, mctx,
+ &dns_result);
+ if (rval == 0) {
+ if (dns_result == ISC_R_SUCCESS) {
+ result = T_PASS;
+ } else {
+ result = T_FAIL;
+ }
+ } else {
+ t_info("t1_search failed\n");
+ result = T_UNRESOLVED;
+ }
+ } else {
+ result = T_PASS;
+ }
+ } else {
+ t_info("dns_rbt_addname returned %s, "
+ "expected %s\n",
+ dns_result_totext(dns_result),
+ dns_result_totext(exp_result));
+ result = T_FAIL;
+ }
+ } else {
+ t_info("create_name failed %s\n",
+ dns_result_totext(dns_result));
+ result = T_UNRESOLVED;
+ }
+ } else if ((strcmp(command, "delete") == 0) ||
+ (strcmp(command, "nuke") == 0)) {
+ rval = t1_delete(testname, rbt, mctx, &dns_result);
+ if (rval == 0) {
+ if (dns_result == exp_result) {
+ rval = t1_search(testname, rbt, mctx,
+ &dns_result);
+ if (rval == 0) {
+ if (dns_result == ISC_R_SUCCESS) {
+ t_info("dns_rbt_deletename "
+ "didn't delete "
+ "the name");
+ result = T_FAIL;
+ } else {
+ result = T_PASS;
+ }
+ }
+ } else {
+ t_info("delete returned %s, expected %s\n",
+ dns_result_totext(dns_result),
+ dns_result_totext(exp_result));
+ result = T_FAIL;
+ }
+ }
+ } else if (strcmp(command, "search") == 0) {
+ rval = t1_search(testname, rbt, mctx, &dns_result);
+ if (rval == 0) {
+ if (dns_result == exp_result) {
+ result = T_PASS;
+ } else {
+ t_info("find returned %s, expected %s\n",
+ dns_result_totext(dns_result),
+ dns_result_totext(exp_result));
+ result = T_FAIL;
+ }
+ }
+ }
+
+ dns_rbt_destroy(&rbt);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+}
+
+static int
+test_dns_rbt_x(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ /*
+ * Name of db file, command, testname,
+ * expected result.
+ */
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 4) {
+ result = test_rbt_gen(Tokens[0], Tokens[1],
+ Tokens[2],
+ t_dns_result_fromtext(Tokens[3]));
+ if (result != T_PASS)
+ ++nfails;
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+
+static const char *a1 = "dns_rbt_create creates a rbt and returns "
+ "ISC_R_SUCCESS on success";
+
+static void
+t1() {
+ int result;
+
+ t_assert("dns_rbt_create", 1, T_REQUIRED, a1);
+ result = test_dns_rbt_x("dns_rbt_create_1_data");
+ t_result(result);
+}
+
+static const char *a2 = "dns_rbt_addname adds a name to a database and "
+ "returns ISC_R_SUCCESS on success";
+
+static void
+t2() {
+ int result;
+
+ t_assert("dns_rbt_addname", 2, T_REQUIRED, a2);
+ result = test_dns_rbt_x("dns_rbt_addname_1_data");
+ t_result(result);
+}
+
+static const char *a3 = "when name already exists, dns_rbt_addname() "
+ "returns ISC_R_EXISTS";
+
+static void
+t3() {
+ int result;
+
+ t_assert("dns_rbt_addname", 3, T_REQUIRED, a3);
+ result = test_dns_rbt_x("dns_rbt_addname_2_data");
+ t_result(result);
+}
+
+static const char *a4 = "when name exists, dns_rbt_deletename() returns "
+ "ISC_R_SUCCESS";
+
+static void
+t4() {
+ int result;
+
+ t_assert("dns_rbt_deletename", 4, T_REQUIRED, a4);
+ result = test_dns_rbt_x("dns_rbt_deletename_1_data");
+ t_result(result);
+}
+
+static const char *a5 = "when name does not exist, dns_rbt_deletename() "
+ "returns ISC_R_NOTFOUND";
+static void
+t5() {
+ int result;
+
+ t_assert("dns_rbt_deletename", 5, T_REQUIRED, a5);
+ result = test_dns_rbt_x("dns_rbt_deletename_2_data");
+ t_result(result);
+}
+
+static const char *a6 = "when name exists and exactly matches the "
+ "search name dns_rbt_findname() returns ISC_R_SUCCESS";
+
+static void
+t6() {
+ int result;
+
+ t_assert("dns_rbt_findname", 6, T_REQUIRED, a6);
+ result = test_dns_rbt_x("dns_rbt_findname_1_data");
+ t_result(result);
+}
+
+static const char *a7 = "when a name does not exist, "
+ "dns_rbt_findname returns ISC_R_NOTFOUND";
+
+static void
+t7() {
+ int result;
+
+ t_assert("dns_rbt_findname", 7, T_REQUIRED, a7);
+ result = test_dns_rbt_x("dns_rbt_findname_2_data");
+ t_result(result);
+}
+
+static const char *a8 = "when a superdomain is found with data matching name, "
+ "dns_rbt_findname returns DNS_R_PARTIALMATCH";
+
+static void
+t8() {
+ int result;
+
+ t_assert("dns_rbt_findname", 8, T_REQUIRED, a8);
+ result = test_dns_rbt_x("dns_rbt_findname_3_data");
+ t_result(result);
+}
+
+
+static const char *a9 = "a call to dns_rbtnodechain_init(chain, mctx) "
+ "initializes chain";
+
+static int
+t9_walkchain(dns_rbtnodechain_t *chain, dns_rbt_t *rbt) {
+ int cnt;
+ int order;
+ unsigned int nlabels;
+ int nprobs;
+ isc_result_t dns_result;
+
+ dns_fixedname_t name;
+ dns_fixedname_t origin;
+ dns_fixedname_t fullname1;
+ dns_fixedname_t fullname2;
+
+ cnt = 0;
+ nprobs = 0;
+
+ do {
+
+ if (cnt == 0) {
+ dns_fixedname_init(&name);
+ dns_fixedname_init(&origin);
+ dns_result = dns_rbtnodechain_first(chain, rbt,
+ dns_fixedname_name(&name),
+ dns_fixedname_name(&origin));
+ if (dns_result != DNS_R_NEWORIGIN) {
+ t_info("dns_rbtnodechain_first returned %s, "
+ "expecting DNS_R_NEWORIGIN\n",
+ dns_result_totext(dns_result));
+ ++nprobs;
+ break;
+ }
+ t_info("first name:\t<%s>\n", fixedname_totext(&name));
+ t_info("first origin:\t<%s>\n",
+ fixedname_totext(&origin));
+ } else {
+ dns_fixedname_init(&fullname1);
+ dns_result = dns_name_concatenate(
+ dns_fixedname_name(&name),
+ dns_name_isabsolute(dns_fixedname_name(&name)) ?
+ NULL : dns_fixedname_name(&origin),
+ dns_fixedname_name(&fullname1), NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_concatenate failed %s\n",
+ dns_result_totext(dns_result));
+ ++nprobs;
+ break;
+ }
+
+ /*
+ * Expecting origin not to get touched if next
+ * doesn't return NEWORIGIN.
+ */
+ dns_fixedname_init(&name);
+ dns_result = dns_rbtnodechain_next(chain,
+ dns_fixedname_name(&name),
+ dns_fixedname_name(&origin));
+ if ((dns_result != ISC_R_SUCCESS) &&
+ (dns_result != DNS_R_NEWORIGIN)) {
+ if (dns_result != ISC_R_NOMORE) {
+ t_info("dns_rbtnodechain_next "
+ "failed %s\n",
+ dns_result_totext(dns_result));
+ ++nprobs;
+ }
+ break;
+ }
+
+ t_info("next name:\t<%s>\n", fixedname_totext(&name));
+ t_info("next origin:\t<%s>\n",
+ fixedname_totext(&origin));
+
+ dns_fixedname_init(&fullname2);
+ dns_result = dns_name_concatenate(
+ dns_fixedname_name(&name),
+ dns_name_isabsolute(dns_fixedname_name(&name)) ?
+ NULL : dns_fixedname_name(&origin),
+ dns_fixedname_name(&fullname2), NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_concatenate failed %s\n",
+ dns_result_totext(dns_result));
+ ++nprobs;
+ break;
+ }
+
+ t_info("comparing\t<%s>\n",
+ fixedname_totext(&fullname1));
+ t_info("\twith\t<%s>\n", fixedname_totext(&fullname2));
+
+ (void)dns_name_fullcompare(
+ dns_fixedname_name(&fullname1),
+ dns_fixedname_name(&fullname2),
+ &order, &nlabels);
+
+ if (order >= 0) {
+ t_info("unexpected order %s %s %s\n",
+ dnsname_totext(dns_fixedname_name(&fullname1)),
+ order == -1 ? "<" : (order == 0 ? "==" : ">"),
+ dnsname_totext(dns_fixedname_name(&fullname2)));
+ ++nprobs;
+ }
+ }
+
+ ++cnt;
+ } while (1);
+
+ return (nprobs);
+}
+
+/*
+ * Test by exercising the first|last|next|prev funcs in useful ways.
+ */
+
+static int
+t_namechk(isc_result_t dns_result, dns_fixedname_t *dns_name, char *exp_name,
+ dns_fixedname_t *dns_origin, char *exp_origin,
+ isc_result_t exp_result)
+{
+ int nfails;
+
+ nfails = 0;
+
+ if (fixedname_cmp(dns_name, exp_name)) {
+ t_info("\texpected name of %s, got %s\n",
+ exp_name, fixedname_totext(dns_name));
+ ++nfails;
+ }
+ if (exp_origin != NULL) {
+ t_info("checking for DNS_R_NEWORIGIN\n");
+ if (dns_result == exp_result) {
+ if (fixedname_cmp(dns_origin, exp_origin)) {
+ t_info("\torigin %s, expected %s\n",
+ fixedname_totext(dns_origin),
+ exp_origin);
+ ++nfails;
+ }
+ } else {
+ t_info("\tgot %s\n", dns_result_totext(dns_result));
+ ++nfails;
+ }
+ }
+ return(nfails);
+}
+
+static int
+t_dns_rbtnodechain_init(char *dbfile, char *findname,
+ char *nextname, char *nextorigin,
+ char *prevname, char *prevorigin,
+ char *firstname, char *firstorigin,
+ char *lastname, char *lastorigin)
+{
+ int result;
+ int len;
+ int nfails;
+ dns_rbt_t *rbt;
+ dns_rbtnode_t *node;
+ dns_rbtnodechain_t chain;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_fixedname_t dns_findname;
+ dns_fixedname_t dns_foundname;
+ dns_fixedname_t dns_firstname;
+ dns_fixedname_t dns_lastname;
+ dns_fixedname_t dns_prevname;
+ dns_fixedname_t dns_nextname;
+ dns_fixedname_t dns_origin;
+ isc_buffer_t isc_buffer;
+
+ result = T_UNRESOLVED;
+
+ nfails = 0;
+ mctx = NULL;
+ ectx = NULL;
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(result);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ rbt = NULL;
+ if (rbt_init(dbfile, &rbt, mctx)) {
+ t_info("rbt_init %s failed\n", dbfile);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ len = strlen(findname);
+ isc_buffer_init(&isc_buffer, findname, len);
+ isc_buffer_add(&isc_buffer, len);
+
+ dns_fixedname_init(&dns_foundname);
+ dns_fixedname_init(&dns_findname);
+ dns_fixedname_init(&dns_firstname);
+ dns_fixedname_init(&dns_origin);
+ dns_fixedname_init(&dns_lastname);
+ dns_fixedname_init(&dns_prevname);
+ dns_fixedname_init(&dns_nextname);
+
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname),
+ &isc_buffer, NULL, ISC_FALSE, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Set the starting node.
+ */
+ node = NULL;
+ dns_result = dns_rbt_findnode(rbt, dns_fixedname_name(&dns_findname),
+ dns_fixedname_name(&dns_foundname),
+ &node, &chain, DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rbt_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Check next.
+ */
+ t_info("checking for next name of %s and new origin of %s\n",
+ nextname, nextorigin);
+ dns_result = dns_rbtnodechain_next(&chain,
+ dns_fixedname_name(&dns_nextname),
+ dns_fixedname_name(&dns_origin));
+
+ if ((dns_result != ISC_R_SUCCESS) &&
+ (dns_result != DNS_R_NEWORIGIN)) {
+ t_info("dns_rbtnodechain_next unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+
+ nfails += t_namechk(dns_result, &dns_nextname, nextname, &dns_origin,
+ nextorigin, DNS_R_NEWORIGIN);
+
+ /*
+ * Set the starting node again.
+ */
+ node = NULL;
+ dns_fixedname_init(&dns_foundname);
+ dns_result = dns_rbt_findnode(rbt, dns_fixedname_name(&dns_findname),
+ dns_fixedname_name(&dns_foundname),
+ &node, &chain, DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("\tdns_rbt_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Check previous.
+ */
+ t_info("checking for previous name of %s and new origin of %s\n",
+ prevname, prevorigin);
+ dns_fixedname_init(&dns_origin);
+ dns_result = dns_rbtnodechain_prev(&chain,
+ dns_fixedname_name(&dns_prevname),
+ dns_fixedname_name(&dns_origin));
+
+ if ((dns_result != ISC_R_SUCCESS) &&
+ (dns_result != DNS_R_NEWORIGIN)) {
+ t_info("dns_rbtnodechain_prev unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+ nfails += t_namechk(dns_result, &dns_prevname, prevname, &dns_origin,
+ prevorigin, DNS_R_NEWORIGIN);
+
+ /*
+ * Check first.
+ */
+ t_info("checking for first name of %s and new origin of %s\n",
+ firstname, firstorigin);
+ dns_result = dns_rbtnodechain_first(&chain, rbt,
+ dns_fixedname_name(&dns_firstname),
+ dns_fixedname_name(&dns_origin));
+
+ if (dns_result != DNS_R_NEWORIGIN) {
+ t_info("dns_rbtnodechain_first unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+ nfails += t_namechk(dns_result, &dns_firstname, firstname,
+ &dns_origin, firstorigin, DNS_R_NEWORIGIN);
+
+ /*
+ * Check last.
+ */
+ t_info("checking for last name of %s\n", lastname);
+ dns_result = dns_rbtnodechain_last(&chain, rbt,
+ dns_fixedname_name(&dns_lastname),
+ dns_fixedname_name(&dns_origin));
+
+ if (dns_result != DNS_R_NEWORIGIN) {
+ t_info("dns_rbtnodechain_last unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+ nfails += t_namechk(dns_result, &dns_lastname, lastname, &dns_origin,
+ lastorigin, DNS_R_NEWORIGIN);
+
+ /*
+ * Check node ordering.
+ */
+ t_info("checking node ordering\n");
+ nfails += t9_walkchain(&chain, rbt);
+
+ if (nfails)
+ result = T_FAIL;
+ else
+ result = T_PASS;
+
+ dns_rbtnodechain_invalidate(&chain);
+ dns_rbt_destroy(&rbt);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static int
+test_dns_rbtnodechain_init(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 10) {
+ result = t_dns_rbtnodechain_init(
+ Tokens[0], /* dbfile */
+ Tokens[1], /* startname */
+ Tokens[2], /* nextname */
+ Tokens[3], /* nextorigin */
+ Tokens[4], /* prevname */
+ Tokens[5], /* prevorigin */
+ Tokens[6], /* firstname */
+ Tokens[7], /* firstorigin */
+ Tokens[8], /* lastname */
+ Tokens[9]); /* lastorigin */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static void
+t9() {
+ int result;
+
+ t_assert("dns_rbtnodechain_init", 9, T_REQUIRED, a9);
+ result = test_dns_rbtnodechain_init("dns_rbtnodechain_init_data");
+ t_result(result);
+}
+
+static int
+t_dns_rbtnodechain_first(char *dbfile, char *expected_firstname,
+ char *expected_firstorigin,
+ char *expected_nextname,
+ char *expected_nextorigin)
+{
+ int result;
+ int nfails;
+ dns_rbt_t *rbt;
+ dns_rbtnodechain_t chain;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_fixedname_t dns_name;
+ dns_fixedname_t dns_origin;
+ isc_result_t expected_result;
+
+ result = T_UNRESOLVED;
+
+ nfails = 0;
+ mctx = NULL;
+ ectx = NULL;
+
+ dns_fixedname_init(&dns_name);
+ dns_fixedname_init(&dns_origin);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(result);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ rbt = NULL;
+ if (rbt_init(dbfile, &rbt, mctx)) {
+ t_info("rbt_init %s failed\n", dbfile);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ t_info("testing for first name of %s, origin of %s\n",
+ expected_firstname, expected_firstorigin);
+
+ dns_result = dns_rbtnodechain_first(&chain, rbt,
+ dns_fixedname_name(&dns_name),
+ dns_fixedname_name(&dns_origin));
+
+ if (dns_result != DNS_R_NEWORIGIN)
+ t_info("dns_rbtnodechain_first unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+
+ nfails = t_namechk(dns_result, &dns_name, expected_firstname,
+ &dns_origin, expected_firstorigin, DNS_R_NEWORIGIN);
+
+ dns_fixedname_init(&dns_name);
+ dns_result = dns_rbtnodechain_next(&chain,
+ dns_fixedname_name(&dns_name),
+ dns_fixedname_name(&dns_origin));
+
+ t_info("testing for next name of %s, origin of %s\n",
+ expected_nextname, expected_nextorigin);
+
+ if ((dns_result != ISC_R_SUCCESS) && (dns_result != DNS_R_NEWORIGIN))
+ t_info("dns_rbtnodechain_next unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+
+ if (strcasecmp(expected_firstorigin, expected_nextorigin) == 0)
+ expected_result = ISC_R_SUCCESS;
+ else
+ expected_result = DNS_R_NEWORIGIN;
+ nfails += t_namechk(dns_result, &dns_name, expected_nextname,
+ &dns_origin, expected_nextorigin, expected_result);
+
+ if (nfails)
+ result = T_FAIL;
+ else
+ result = T_PASS;
+
+ dns_rbtnodechain_invalidate(&chain);
+
+ dns_rbt_destroy(&rbt);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+}
+
+static int
+test_dns_rbtnodechain_first(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 5) {
+ result = t_dns_rbtnodechain_first(
+ Tokens[0], /* dbfile */
+ Tokens[1], /* firstname */
+ Tokens[2], /* firstorigin */
+ Tokens[3], /* nextname */
+ Tokens[4]); /* nextorigin */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a10 = "a call to "
+ "dns_rbtnodechain_first(chain, rbt, name, origin) "
+ "sets name to point to the root of the tree, "
+ "origin to point to the origin, "
+ "and returns DNS_R_NEWORIGIN";
+
+static void
+t10() {
+ int result;
+
+ t_assert("dns_rbtnodechain_first", 10, T_REQUIRED, a10);
+ result = test_dns_rbtnodechain_first("dns_rbtnodechain_first_data");
+ t_result(result);
+}
+
+static int
+t_dns_rbtnodechain_last(char *dbfile, char *expected_lastname,
+ char *expected_lastorigin,
+ char *expected_prevname,
+ char *expected_prevorigin)
+{
+
+ int result;
+ int nfails;
+ dns_rbt_t *rbt;
+ dns_rbtnodechain_t chain;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_fixedname_t dns_name;
+ dns_fixedname_t dns_origin;
+ isc_result_t expected_result;
+
+ result = T_UNRESOLVED;
+
+ nfails = 0;
+ mctx = NULL;
+ ectx = NULL;
+
+ dns_fixedname_init(&dns_name);
+ dns_fixedname_init(&dns_origin);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(result);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ rbt = NULL;
+ if (rbt_init(dbfile, &rbt, mctx)) {
+ t_info("rbt_init %s failed\n", dbfile);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ t_info("testing for last name of %s, origin of %s\n",
+ expected_lastname, expected_lastorigin);
+
+ dns_result = dns_rbtnodechain_last(&chain, rbt,
+ dns_fixedname_name(&dns_name),
+ dns_fixedname_name(&dns_origin));
+
+ if (dns_result != DNS_R_NEWORIGIN) {
+ t_info("dns_rbtnodechain_last unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+ nfails = t_namechk(dns_result, &dns_name, expected_lastname,
+ &dns_origin, expected_lastorigin, DNS_R_NEWORIGIN);
+
+ t_info("testing for previous name of %s, origin of %s\n",
+ expected_prevname, expected_prevorigin);
+
+ dns_fixedname_init(&dns_name);
+ dns_result = dns_rbtnodechain_prev(&chain,
+ dns_fixedname_name(&dns_name),
+ dns_fixedname_name(&dns_origin));
+
+ if ((dns_result != ISC_R_SUCCESS) &&
+ (dns_result != DNS_R_NEWORIGIN)) {
+ t_info("dns_rbtnodechain_prev unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+ if (strcasecmp(expected_lastorigin, expected_prevorigin) == 0)
+ expected_result = ISC_R_SUCCESS;
+ else
+ expected_result = DNS_R_NEWORIGIN;
+ nfails += t_namechk(dns_result, &dns_name, expected_prevname,
+ &dns_origin, expected_prevorigin, expected_result);
+
+ if (nfails)
+ result = T_FAIL;
+ else
+ result = T_PASS;
+
+ dns_rbtnodechain_invalidate(&chain);
+ dns_rbt_destroy(&rbt);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static int
+test_dns_rbtnodechain_last(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 5) {
+ result = t_dns_rbtnodechain_last(
+ Tokens[0], /* dbfile */
+ Tokens[1], /* lastname */
+ Tokens[2], /* lastorigin */
+ Tokens[3], /* prevname */
+ Tokens[4]); /* prevorigin */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a11 = "a call to "
+ "dns_rbtnodechain_last(chain, rbt, name, origin) "
+ "sets name to point to the last node of the megatree, "
+ "origin to the name of the level above it, "
+ "and returns DNS_R_NEWORIGIN";
+
+static void
+t11() {
+ int result;
+
+ t_assert("dns_rbtnodechain_last", 11, T_REQUIRED, a11);
+ result = test_dns_rbtnodechain_last("dns_rbtnodechain_last_data");
+ t_result(result);
+}
+
+static int
+t_dns_rbtnodechain_next(char *dbfile, char *findname,
+ char *nextname, char *nextorigin)
+{
+
+ int result;
+ int len;
+ int nfails;
+ dns_rbt_t *rbt;
+ dns_rbtnode_t *node;
+ dns_rbtnodechain_t chain;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_fixedname_t dns_findname;
+ dns_fixedname_t dns_foundname;
+ dns_fixedname_t dns_nextname;
+ dns_fixedname_t dns_origin;
+ isc_buffer_t isc_buffer;
+
+ result = T_UNRESOLVED;
+
+ nfails = 0;
+ mctx = NULL;
+ ectx = NULL;
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(result);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ rbt = NULL;
+ if (rbt_init(dbfile, &rbt, mctx)) {
+ t_info("rbt_init %s failed\n", dbfile);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ len = strlen(findname);
+ isc_buffer_init(&isc_buffer, findname, len);
+ isc_buffer_add(&isc_buffer, len);
+
+ dns_fixedname_init(&dns_foundname);
+ dns_fixedname_init(&dns_findname);
+ dns_fixedname_init(&dns_nextname);
+ dns_fixedname_init(&dns_origin);
+
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname),
+ &isc_buffer, NULL, ISC_FALSE, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Set the starting node.
+ */
+ node = NULL;
+ dns_result = dns_rbt_findnode(rbt, dns_fixedname_name(&dns_findname),
+ dns_fixedname_name(&dns_foundname),
+ &node, &chain, DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rbt_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Check next.
+ */
+ t_info("checking for next name of %s and new origin of %s\n",
+ nextname, nextorigin);
+ dns_result = dns_rbtnodechain_next(&chain,
+ dns_fixedname_name(&dns_nextname),
+ dns_fixedname_name(&dns_origin));
+
+ if ((dns_result != ISC_R_SUCCESS) && (dns_result != DNS_R_NEWORIGIN)) {
+ t_info("dns_rbtnodechain_next unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+
+ nfails += t_namechk(dns_result, &dns_nextname, nextname, &dns_origin,
+ nextorigin, DNS_R_NEWORIGIN);
+
+ if (nfails)
+ result = T_FAIL;
+ else
+ result = T_PASS;
+
+ dns_rbtnodechain_invalidate(&chain);
+ dns_rbt_destroy(&rbt);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static int
+test_dns_rbtnodechain_next(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 4) {
+ result = t_dns_rbtnodechain_next(
+ Tokens[0], /* dbfile */
+ Tokens[1], /* findname */
+ Tokens[2], /* nextname */
+ Tokens[3]); /* nextorigin */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a12 = "a call to "
+ "dns_rbtnodechain_next(chain, name, origin) "
+ "sets name to point to the next node of the tree "
+ "and returns ISC_R_SUCCESS or "
+ "DNS_R_NEWORIGIN on success";
+
+
+static void
+t12() {
+ int result;
+
+ t_assert("dns_rbtnodechain_next", 12, T_REQUIRED, a12);
+ result = test_dns_rbtnodechain_next("dns_rbtnodechain_next_data");
+ t_result(result);
+}
+
+static int
+t_dns_rbtnodechain_prev(char *dbfile, char *findname, char *prevname,
+ char *prevorigin)
+{
+ int result;
+ int len;
+ int nfails;
+ dns_rbt_t *rbt;
+ dns_rbtnode_t *node;
+ dns_rbtnodechain_t chain;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx = NULL;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_fixedname_t dns_findname;
+ dns_fixedname_t dns_foundname;
+ dns_fixedname_t dns_prevname;
+ dns_fixedname_t dns_origin;
+ isc_buffer_t isc_buffer;
+
+ result = T_UNRESOLVED;
+
+ nfails = 0;
+ mctx = NULL;
+ ectx = NULL;
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(result);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ rbt = NULL;
+ if (rbt_init(dbfile, &rbt, mctx)) {
+ t_info("rbt_init %s failed\n", dbfile);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ len = strlen(findname);
+ isc_buffer_init(&isc_buffer, findname, len);
+ isc_buffer_add(&isc_buffer, len);
+
+ dns_fixedname_init(&dns_foundname);
+ dns_fixedname_init(&dns_findname);
+ dns_fixedname_init(&dns_prevname);
+ dns_fixedname_init(&dns_origin);
+
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname),
+ &isc_buffer, NULL, ISC_FALSE, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Set the starting node.
+ */
+ node = NULL;
+ dns_result = dns_rbt_findnode(rbt, dns_fixedname_name(&dns_findname),
+ dns_fixedname_name(&dns_foundname),
+ &node, &chain, DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rbt_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Check next.
+ */
+ t_info("checking for next name of %s and new origin of %s\n",
+ prevname, prevorigin);
+ dns_result = dns_rbtnodechain_prev(&chain,
+ dns_fixedname_name(&dns_prevname),
+ dns_fixedname_name(&dns_origin));
+
+ if ((dns_result != ISC_R_SUCCESS) && (dns_result != DNS_R_NEWORIGIN)) {
+ t_info("dns_rbtnodechain_prev unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+
+ nfails += t_namechk(dns_result, &dns_prevname, prevname, &dns_origin,
+ prevorigin, DNS_R_NEWORIGIN);
+
+ if (nfails)
+ result = T_FAIL;
+ else
+ result = T_PASS;
+
+ dns_rbtnodechain_invalidate(&chain);
+ dns_rbt_destroy(&rbt);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static int
+test_dns_rbtnodechain_prev(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 4) {
+ result = t_dns_rbtnodechain_prev(
+ Tokens[0], /* dbfile */
+ Tokens[1], /* findname */
+ Tokens[2], /* prevname */
+ Tokens[3]); /* prevorigin */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a13 = "a call to "
+ "dns_rbtnodechain_prev(chain, name, origin) "
+ "sets name to point to the previous node of the tree "
+ "and returns ISC_R_SUCCESS or "
+ "DNS_R_NEWORIGIN on success";
+
+static void
+t13() {
+ int result;
+
+ t_assert("dns_rbtnodechain_prev", 13, T_REQUIRED, a13);
+ result = test_dns_rbtnodechain_prev("dns_rbtnodechain_prev_data");
+ t_result(result);
+}
+
+
+
+testspec_t T_testlist[] = {
+ { t1, "dns_rbt_create" },
+ { t2, "dns_rbt_addname 1" },
+ { t3, "dns_rbt_addname 2" },
+ { t4, "dns_rbt_deletename 1" },
+ { t5, "dns_rbt_deletename 2" },
+ { t6, "dns_rbt_findname 1" },
+ { t7, "dns_rbt_findname 2" },
+ { t8, "dns_rbt_findname 3" },
+ { t9, "dns_rbtnodechain_init" },
+ { t10, "dns_rbtnodechain_first" },
+ { t11, "dns_rbtnodechain_last" },
+ { t12, "dns_rbtnodechain_next" },
+ { t13, "dns_rbtnodechain_prev" },
+ { NULL, NULL }
+};
+
diff --git a/bin/tests/rbt_test.c b/bin/tests/rbt_test.c
new file mode 100644
index 0000000..ac8db14
--- /dev/null
+++ b/bin/tests/rbt_test.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rbt_test.c,v 1.48 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/rbt.h>
+#include <dns/fixedname.h>
+#include <dns/result.h>
+
+char *progname;
+isc_mem_t *mctx;
+
+#define DNSNAMELEN 255
+
+static dns_name_t *
+create_name(char *s) {
+ int length;
+ isc_result_t result;
+ isc_buffer_t source, target;
+ static dns_name_t *name;
+
+ if (s == NULL || *s == '\0') {
+ printf("missing name argument\n");
+ return (NULL);
+ }
+
+ length = strlen(s);
+
+ isc_buffer_init(&source, s, length);
+ isc_buffer_add(&source, length);
+
+ /*
+ * It isn't really necessary in this program to create individual
+ * memory spaces for each name structure and its associated character
+ * string. It is done here to provide a relatively easy way to test
+ * the callback from dns_rbt_deletename that is supposed to free the
+ * data associated with a node.
+ *
+ * The buffer for the actual name will immediately follow the
+ * name structure.
+ */
+ name = isc_mem_get(mctx, sizeof(*name) + DNSNAMELEN);
+ if (name == NULL) {
+ printf("out of memory!\n");
+ return (NULL);
+ }
+
+ dns_name_init(name, NULL);
+ isc_buffer_init(&target, name + 1, DNSNAMELEN);
+
+ result = dns_name_fromtext(name, &source, dns_rootname,
+ ISC_FALSE, &target);
+
+ if (result != ISC_R_SUCCESS) {
+ printf("dns_name_fromtext(%s) failed: %s\n",
+ s, dns_result_totext(result));
+ return (NULL);
+ }
+
+ return (name);
+}
+
+static void
+delete_name(void *data, void *arg) {
+ dns_name_t *name;
+
+ UNUSED(arg);
+ name = data;
+ isc_mem_put(mctx, data, sizeof(dns_name_t) + DNSNAMELEN);
+}
+
+static void
+print_name(dns_name_t *name) {
+ isc_buffer_t target;
+ char buffer[1024];
+
+ isc_buffer_init(&target, buffer, sizeof(buffer));
+
+ /*
+ * ISC_FALSE means absolute names have the final dot added.
+ */
+ dns_name_totext(name, ISC_FALSE, &target);
+
+ printf("%.*s", (int)target.used, (char *)target.base);
+}
+
+static void
+detail(dns_rbt_t *rbt, dns_name_t *name) {
+ dns_name_t *foundname, *origin, *fullname;
+ dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname;
+ dns_rbtnode_t *node1, *node2;
+ dns_rbtnodechain_t chain;
+ isc_result_t result;
+ isc_boolean_t nodes_should_match = ISC_FALSE;
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ dns_fixedname_init(&fixedorigin);
+ dns_fixedname_init(&fixedfullname);
+ dns_fixedname_init(&fixedfoundname);
+
+ origin = dns_fixedname_name(&fixedorigin);
+ fullname = dns_fixedname_name(&fixedfullname);
+ foundname = dns_fixedname_name(&fixedfoundname);
+
+ node1 = node2 = NULL;
+
+ printf("checking chain information for ");
+ print_name(name);
+ printf("\n");
+
+ result = dns_rbt_findnode(rbt, name, foundname, &node1, &chain,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ printf(" found exact.");
+ nodes_should_match = ISC_TRUE;
+ break;
+ case DNS_R_PARTIALMATCH:
+ printf(" found parent.");
+ break;
+ case ISC_R_NOTFOUND:
+ printf(" name not found.");
+ break;
+ default:
+ printf(" unexpected result: %s\n", dns_result_totext(result));
+ return;
+ }
+
+ if (node1 != NULL && node1->data != NULL) {
+ printf(" data at node: ");
+ print_name(node1->data);
+ } else
+ printf(" no data at node.");
+
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
+ printf("\n name from dns_rbt_findnode: ");
+ print_name(foundname);
+ }
+
+ result = dns_rbtnodechain_current(&chain, foundname, origin, &node2);
+
+ if (result == ISC_R_SUCCESS) {
+ printf("\n name from dns_rbtnodechain_current: ");
+
+ result = dns_name_concatenate(foundname, origin,
+ fullname, NULL);
+ if (result == ISC_R_SUCCESS)
+ print_name(fullname);
+ else
+ printf("%s\n", dns_result_totext(result));
+ printf("\n (foundname = ");
+ print_name(foundname);
+ printf(", origin = ");
+ print_name(origin);
+ printf(")\n");
+ if (nodes_should_match && node1 != node2)
+ printf(" nodes returned from each function "
+ "DO NOT match!\n");
+
+ } else
+ printf("\n result from dns_rbtnodechain_current: %s\n",
+ dns_result_totext(result));
+
+ printf(" level_matches = %d, level_count = %d\n",
+ chain.level_matches, chain.level_count);
+}
+
+static void
+iterate(dns_rbt_t *rbt, isc_boolean_t forward) {
+ dns_name_t foundname, *origin;
+ dns_rbtnodechain_t chain;
+ dns_fixedname_t fixedorigin;
+ isc_result_t result;
+ isc_result_t (*move)(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin);
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ dns_name_init(&foundname, NULL);
+ dns_fixedname_init(&fixedorigin);
+ origin = dns_fixedname_name(&fixedorigin);
+
+ if (forward) {
+ printf("iterating forward\n" );
+ move = dns_rbtnodechain_next;
+
+ result = dns_rbtnodechain_first(&chain, rbt, &foundname,
+ origin);
+
+ } else {
+ printf("iterating backward\n" );
+ move = dns_rbtnodechain_prev;
+
+ result = dns_rbtnodechain_last(&chain, rbt, &foundname,
+ origin);
+ }
+
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+ printf("start not found!\n");
+
+ else {
+ for (;;) {
+ if (result == DNS_R_NEWORIGIN) {
+ printf(" new origin: ");
+ print_name(origin);
+ printf("\n");
+ }
+
+ if (result == ISC_R_SUCCESS ||
+ result == DNS_R_NEWORIGIN) {
+ print_name(&foundname);
+ printf("\n");
+
+ } else {
+ if (result != ISC_R_NOMORE)
+ printf("UNEXEPCTED ITERATION ERROR: %s",
+ dns_result_totext(result));
+ break;
+ }
+
+ result = move(&chain, &foundname, origin);
+ }
+ }
+}
+
+
+#define CMDCHECK(s) (strncasecmp(command, (s), length) == 0)
+#define PRINTERR(r) if (r != ISC_R_SUCCESS) \
+ printf("... %s\n", dns_result_totext(r));
+
+int
+main(int argc, char **argv) {
+ char *command, *arg, buffer[1024];
+ const char *whitespace;
+ dns_name_t *name, *foundname;
+ dns_fixedname_t fixedname;
+ dns_rbt_t *rbt = NULL;
+ int length, ch;
+ isc_boolean_t show_final_mem = ISC_FALSE;
+ isc_result_t result;
+ void *data;
+
+ progname = strrchr(*argv, '/');
+ if (progname != NULL)
+ progname++;
+ else
+ progname = *argv;
+
+ while ((ch = isc_commandline_parse(argc, argv, "m")) != -1) {
+ switch (ch) {
+ case 'm':
+ show_final_mem = ISC_TRUE;
+ break;
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc > 1) {
+ printf("Usage: %s [-m]\n", progname);
+ exit(1);
+ }
+
+ setbuf(stdout, NULL);
+
+ /*
+ * So isc_mem_stats() can report any allocation leaks.
+ */
+ isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS) {
+ printf("isc_mem_create: %s: exiting\n",
+ dns_result_totext(result));
+ exit(1);
+ }
+
+ result = dns_rbt_create(mctx, delete_name, NULL, &rbt);
+ if (result != ISC_R_SUCCESS) {
+ printf("dns_rbt_create: %s: exiting\n",
+ dns_result_totext(result));
+ exit(1);
+ }
+
+ whitespace = " \t";
+
+ while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
+ length = strlen(buffer);
+
+ if (buffer[length - 1] != '\n') {
+ printf("line to long (%lu max), ignored\n",
+ (unsigned long)sizeof(buffer) - 2);
+ continue;
+ }
+
+ buffer[length - 1] = '\0';
+
+ command = buffer + strspn(buffer, whitespace);
+
+ if (*command == '#')
+ continue;
+
+ arg = strpbrk(command, whitespace);
+ if (arg != NULL) {
+ *arg++ = '\0';
+ arg += strspn(arg, whitespace);
+ }
+
+ length = strlen(command);
+ if (*command != '\0') {
+ if (CMDCHECK("add")) {
+ name = create_name(arg);
+ if (name != NULL) {
+ printf("adding name %s\n", arg);
+ result = dns_rbt_addname(rbt,
+ name, name);
+ PRINTERR(result);
+ }
+
+ } else if (CMDCHECK("delete")) {
+ name = create_name(arg);
+ if (name != NULL) {
+ printf("deleting name %s\n", arg);
+ result = dns_rbt_deletename(rbt, name,
+ ISC_FALSE);
+ PRINTERR(result);
+ delete_name(name, NULL);
+ }
+
+ } else if (CMDCHECK("nuke")) {
+ name = create_name(arg);
+ if (name != NULL) {
+ printf("nuking name %s "
+ "and its descendants\n", arg);
+ result = dns_rbt_deletename(rbt, name,
+ ISC_TRUE);
+ PRINTERR(result);
+ delete_name(name, NULL);
+ }
+
+ } else if (CMDCHECK("search")) {
+ name = create_name(arg);
+ if (name != NULL) {
+ printf("searching for name %s ... ",
+ arg);
+
+ dns_fixedname_init(&fixedname);
+ foundname =
+ dns_fixedname_name(&fixedname);
+ data = NULL;
+
+ result = dns_rbt_findname(rbt, name, 0,
+ foundname,
+ &data);
+ switch (result) {
+ case ISC_R_SUCCESS:
+ printf("found exact: ");
+ print_name(data);
+ putchar('\n');
+ break;
+ case DNS_R_PARTIALMATCH:
+ printf("found parent: ");
+ print_name(data);
+ printf("\n\t(foundname: ");
+ print_name(foundname);
+ printf(")\n");
+ break;
+ case ISC_R_NOTFOUND:
+ printf("NOT FOUND!\n");
+ break;
+ case ISC_R_NOMEMORY:
+ printf("OUT OF MEMORY!\n");
+ break;
+ default:
+ printf("UNEXPECTED RESULT\n");
+ }
+
+ delete_name(name, NULL);
+ }
+
+ } else if (CMDCHECK("check")) {
+ /*
+ * Or "chain". I know, I know. Lame name.
+ * I was having a hard time thinking of a
+ * name (especially one that did not have
+ * a conflicting first letter with another
+ * command) that would differentiate this
+ * from the search command.
+ *
+ * But it is just a test program, eh?
+ */
+ name = create_name(arg);
+ if (name != NULL) {
+ detail(rbt, name);
+
+ delete_name(name, NULL);
+ }
+
+ } else if (CMDCHECK("forward")) {
+ iterate(rbt, ISC_TRUE);
+
+ } else if (CMDCHECK("backward")) {
+ iterate(rbt, ISC_FALSE);
+
+ } else if (CMDCHECK("print")) {
+ if (arg == NULL || *arg == '\0')
+ dns_rbt_printall(rbt);
+ else
+ printf("usage: print\n");
+
+ } else if (CMDCHECK("quit")) {
+ if (arg == NULL || *arg == '\0')
+ break;
+ else
+ printf("usage: quit\n");
+ } else {
+ printf("a(dd) NAME, d(elete) NAME, "
+ "s(earch) NAME, p(rint), or q(uit)\n");
+
+ }
+ }
+
+ }
+
+ dns_rbt_destroy(&rbt);
+
+ if (show_final_mem)
+ isc_mem_stats(mctx, stderr);
+
+ return (0);
+}
diff --git a/bin/tests/rbt_test.out b/bin/tests/rbt_test.out
new file mode 100644
index 0000000..95bf4f9
--- /dev/null
+++ b/bin/tests/rbt_test.out
@@ -0,0 +1,395 @@
+adding name a.vix.com
+adding name b.vix.com
+adding name c.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (RED from b)
+ NULL
+ NULL
+ c (RED from b)
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+adding name a.b.c.d.e.f.vix.com
+adding name b.b.c.d.e.f.vix.com
+adding name c.b.c.d.e.f.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ NULL
+ NULL
+ c (black from b)
+ NULL
+ b.c.d.e.f (RED from c)
+ ++ BEG down from b.c.d.e.f
+ b (black)
+ a (RED from b)
+ NULL
+ NULL
+ c (RED from b)
+ NULL
+ NULL
+ -- END down from b.c.d.e.f
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+adding name a.d.e.f.vix.com
+adding name q.d.e.f.vix.com
+adding name d.e.f.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ NULL
+ NULL
+ c (black from b)
+ NULL
+ d.e.f (RED from c)
+ ++ BEG down from d.e.f
+ b.c (black)
+ ++ BEG down from b.c
+ b (black)
+ a (RED from b)
+ NULL
+ NULL
+ c (RED from b)
+ NULL
+ NULL
+ -- END down from b.c
+ a (RED from b.c)
+ NULL
+ NULL
+ q (RED from b.c)
+ NULL
+ NULL
+ -- END down from d.e.f
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+adding name g.h.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ NULL
+ NULL
+ d.e.f (black from b)
+ ++ BEG down from d.e.f
+ b.c (black)
+ ++ BEG down from b.c
+ b (black)
+ a (RED from b)
+ NULL
+ NULL
+ c (RED from b)
+ NULL
+ NULL
+ -- END down from b.c
+ a (RED from b.c)
+ NULL
+ NULL
+ q (RED from b.c)
+ NULL
+ NULL
+ -- END down from d.e.f
+ c (RED from d.e.f)
+ NULL
+ NULL
+ g.h (RED from d.e.f)
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+searching for name q.d.e.f.vix.com ... found exact: q.d.e.f.vix.com.
+searching for name just-parent.a.vix.com ... found parent: a.vix.com.
+ (foundname: a.vix.com.)
+searching for name no-real-parent.vix.com ... NOT FOUND!
+searching for name does.not.exist.at.all ... NOT FOUND!
+iterating forward
+ new origin: .
+vix.com
+ new origin: vix.com.
+a
+b
+c
+d.e.f
+ new origin: d.e.f.vix.com.
+a
+b.c
+ new origin: b.c.d.e.f.vix.com.
+a
+b
+c
+ new origin: d.e.f.vix.com.
+q
+ new origin: vix.com.
+g.h
+iterating backward
+ new origin: vix.com.
+g.h
+ new origin: d.e.f.vix.com.
+q
+ new origin: b.c.d.e.f.vix.com.
+c
+b
+a
+ new origin: d.e.f.vix.com.
+b.c
+a
+ new origin: vix.com.
+d.e.f
+c
+b
+a
+ new origin: .
+vix.com
+checking chain information for vix.com.
+ found exact. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: vix.com.
+ (foundname = vix.com, origin = .)
+ level_matches = 0, level_count = 0
+checking chain information for zzz.com.
+ name not found. no data at node.
+ name from dns_rbtnodechain_current: g.h.vix.com.
+ (foundname = g.h, origin = vix.com.)
+ level_matches = 0, level_count = 1
+checking chain information for 0.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: vix.com.
+ (foundname = vix.com, origin = .)
+ level_matches = 0, level_count = 0
+checking chain information for d.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: c.vix.com.
+ (foundname = c, origin = vix.com.)
+ level_matches = 0, level_count = 1
+checking chain information for f.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: c.vix.com.
+ (foundname = c, origin = vix.com.)
+ level_matches = 0, level_count = 1
+checking chain information for a.e.f.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: c.vix.com.
+ (foundname = c, origin = vix.com.)
+ level_matches = 0, level_count = 1
+checking chain information for z.e.f.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: q.d.e.f.vix.com.
+ (foundname = q, origin = d.e.f.vix.com.)
+ level_matches = 0, level_count = 2
+checking chain information for g.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: q.d.e.f.vix.com.
+ (foundname = q, origin = d.e.f.vix.com.)
+ level_matches = 0, level_count = 2
+checking chain information for i.vix.com.
+ found parent. no data at node.
+ name from dns_rbt_findnode: vix.com.
+ name from dns_rbtnodechain_current: g.h.vix.com.
+ (foundname = g.h, origin = vix.com.)
+ level_matches = 0, level_count = 1
+checking chain information for b.c.vix.com.
+ found parent. data at node: c.vix.com.
+ name from dns_rbt_findnode: c.vix.com.
+ name from dns_rbtnodechain_current: c.vix.com.
+ (foundname = c, origin = vix.com.)
+ level_matches = 1, level_count = 1
+nuking name d.e.f.vix.com and its descendants
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ NULL
+ NULL
+ g.h (black from b)
+ c (RED from g.h)
+ NULL
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+adding name x.a.vix.com
+adding name y.x.a.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ ++ BEG down from a
+ x (black)
+ ++ BEG down from x
+ y (black)
+ NULL
+ NULL
+ -- END down from x
+ NULL
+ NULL
+ -- END down from a
+ NULL
+ NULL
+ g.h (black from b)
+ c (RED from g.h)
+ NULL
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+deleting name a.vix.com
+deleting name x.a.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ b (black)
+ a (black from b)
+ ++ BEG down from a
+ x (black)
+ ++ BEG down from x
+ y (black)
+ NULL
+ NULL
+ -- END down from x
+ NULL
+ NULL
+ -- END down from a
+ NULL
+ NULL
+ g.h (black from b)
+ c (RED from g.h)
+ NULL
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+deleting name b.vix.com
+deleting name c.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ g.h (black)
+ a (RED from g.h)
+ ++ BEG down from a
+ x (black)
+ ++ BEG down from x
+ y (black)
+ NULL
+ NULL
+ -- END down from x
+ NULL
+ NULL
+ -- END down from a
+ NULL
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+deleting name y.x.a.vix.com
+vix.com. (black)
+ ++ BEG down from vix.com.
+ g.h (black)
+ a (RED from g.h)
+ ++ BEG down from a
+ x (black)
+ NULL
+ NULL
+ -- END down from a
+ NULL
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+deleting name g.h.vix.com.
+adding name \[b100000].vix.com.
+adding name \[b010000].vix.com.
+adding name \[b001000].vix.com.
+adding name \[b000100].vix.com.
+adding name \[b000010].vix.com.
+adding name \[b000001].vix.com.
+vix.com. (black)
+ ++ BEG down from vix.com.
+ \[x80/6] (black)
+ \[x0/1] (RED from \[x80/6])
+ ++ BEG down from \[x0/1]
+ \[x80/5] (black)
+ \[x0/1] (RED from \[x80/5])
+ ++ BEG down from \[x0/1]
+ \[x8/4] (black)
+ \[x0/1] (RED from \[x8/4])
+ ++ BEG down from \[x0/1]
+ \[x8/3] (black)
+ \[x0/1] (RED from \[x8/3])
+ ++ BEG down from \[x0/1]
+ \[x8/2] (black)
+ \[x4/2] (RED from \[x8/2])
+ NULL
+ NULL
+ NULL
+ -- END down from \[x0/1]
+ NULL
+ NULL
+ NULL
+ -- END down from \[x0/1]
+ NULL
+ NULL
+ NULL
+ -- END down from \[x0/1]
+ NULL
+ NULL
+ NULL
+ -- END down from \[x0/1]
+ NULL
+ NULL
+ a (RED from \[x80/6])
+ ++ BEG down from a
+ x (black)
+ NULL
+ NULL
+ -- END down from a
+ NULL
+ NULL
+ -- END down from vix.com.
+ NULL
+ NULL
+searching for name \[b000100].vix.com. ... found exact: \[x10/6].vix.com.
+adding name vix.com.
+nuking name vix.com. and its descendants
+adding name 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+adding name 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w. (black)
+ ++ BEG down from 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+ a (black)
+ NULL
+ NULL
+ -- END down from 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+ NULL
+ NULL
+adding name .
+nuking name . and its descendants
+adding name \[xFFFF/16].\[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/256].com
+adding name \[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/128].com
+\[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/128].com. (black)
+ ++ BEG down from \[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/128].com.
+ \[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/144] (black)
+ NULL
+ NULL
+ -- END down from \[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/128].com.
+ NULL
+ NULL
diff --git a/bin/tests/rbt_test.txt b/bin/tests/rbt_test.txt
new file mode 100644
index 0000000..bf50b12
--- /dev/null
+++ b/bin/tests/rbt_test.txt
@@ -0,0 +1,93 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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: rbt_test.txt,v 1.17 2007/06/19 23:46:59 tbox Exp $
+
+add a.vix.com
+add b.vix.com
+add c.vix.com
+print
+add a.b.c.d.e.f.vix.com
+add b.b.c.d.e.f.vix.com
+add c.b.c.d.e.f.vix.com
+print
+add a.d.e.f.vix.com
+add q.d.e.f.vix.com
+add d.e.f.vix.com
+print
+add g.h.vix.com
+print
+search q.d.e.f.vix.com
+search just-parent.a.vix.com
+search no-real-parent.vix.com
+search does.not.exist.at.all
+forward
+backward
+# existing name
+check vix.com.
+# greater than stop node, which has down pointer
+check zzz.com.
+# less than lowest in level (would be left link from stop node)
+check 0.vix.com
+# greater than stop node, no down pointer
+check d.vix.com
+# superdomain stored in existing node
+check f.vix.com
+# common ancestor stored in existing node; existing is successor
+check a.e.f.vix.com
+# common ancestor stored in existing node; existing is less but not predecessor
+check z.e.f.vix.com
+#
+check g.vix.com
+#
+check i.vix.com
+#
+check b.c.vix.com
+nuke d.e.f.vix.com
+print
+add x.a.vix.com
+add y.x.a.vix.com
+print
+delete a.vix.com
+delete x.a.vix.com
+print
+delete b.vix.com
+delete c.vix.com
+print
+delete y.x.a.vix.com
+print
+delete g.h.vix.com.
+add \[b100000].vix.com.
+add \[b010000].vix.com.
+add \[b001000].vix.com.
+add \[b000100].vix.com.
+add \[b000010].vix.com.
+add \[b000001].vix.com.
+p
+search \[b000100].vix.com.
+# zap the entire tree
+add vix.com.
+nuke vix.com.
+add 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+add 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.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.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.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.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.
+print
+add .
+# zap it again
+nuke .
+# test splitting of maximal bitstring
+add \[xFFFF/16].\[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/256].com
+add \[xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF/128].com
+print
+quit
diff --git a/bin/tests/rdata_test.c b/bin/tests/rdata_test.c
new file mode 100644
index 0000000..7955737
--- /dev/null
+++ b/bin/tests/rdata_test.c
@@ -0,0 +1,1182 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: rdata_test.c,v 1.48 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/rdata.h>
+#include <dns/compress.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+
+isc_mem_t *mctx;
+isc_lex_t *lex;
+
+isc_lexspecials_t specials;
+
+static void
+viastruct(dns_rdata_t *rdata, isc_mem_t *mctx,
+ dns_rdata_t *rdata2, isc_buffer_t *b)
+{
+ isc_result_t result;
+ void *sp = NULL;
+ isc_boolean_t need_free = ISC_FALSE;
+ dns_rdatatype_t rdt;
+ dns_rdataclass_t rdc;
+
+ UNUSED(rdata2); /* XXXMPA remove when fromstruct is ready. */
+ UNUSED(b);
+
+ switch (rdata->type) {
+ case dns_rdatatype_a6: {
+ dns_rdata_in_a6_t in_a6;
+ result = dns_rdata_tostruct(rdata, sp = &in_a6, NULL);
+ break;
+ }
+ case dns_rdatatype_a: {
+ switch (rdata->rdclass) {
+ case dns_rdataclass_hs: {
+ dns_rdata_hs_a_t hs_a;
+ result = dns_rdata_tostruct(rdata, sp = &hs_a, NULL);
+ break;
+ }
+ case dns_rdataclass_in: {
+ dns_rdata_in_a_t in_a;
+ result = dns_rdata_tostruct(rdata, sp = &in_a, NULL);
+ break;
+ }
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ break;
+ }
+ case dns_rdatatype_aaaa: {
+ dns_rdata_in_aaaa_t in_aaaa;
+ result = dns_rdata_tostruct(rdata, sp = &in_aaaa, NULL);
+ break;
+ }
+ case dns_rdatatype_afsdb: {
+ dns_rdata_afsdb_t afsdb;
+ result = dns_rdata_tostruct(rdata, sp = &afsdb, NULL);
+ break;
+ }
+ case dns_rdatatype_any: {
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ case dns_rdatatype_apl: {
+ switch (rdata->rdclass) {
+ case dns_rdataclass_in: {
+ dns_rdata_in_apl_t in_apl;
+ result = dns_rdata_tostruct(rdata, sp = &in_apl, NULL);
+ break;
+ }
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ break;
+ }
+ case dns_rdatatype_cert: {
+ dns_rdata_cert_t cert;
+ result = dns_rdata_tostruct(rdata, sp = &cert, NULL);
+ break;
+ }
+ case dns_rdatatype_cname: {
+ dns_rdata_cname_t cname;
+ result = dns_rdata_tostruct(rdata, sp = &cname, NULL);
+ break;
+ }
+ case dns_rdatatype_dname: {
+ dns_rdata_dname_t dname;
+ result = dns_rdata_tostruct(rdata, sp = &dname, NULL);
+ break;
+ }
+ case dns_rdatatype_gpos: {
+ dns_rdata_gpos_t gpos;
+ result = dns_rdata_tostruct(rdata, sp = &gpos, NULL);
+ break;
+ }
+ case dns_rdatatype_hinfo: {
+ dns_rdata_hinfo_t hinfo;
+ result = dns_rdata_tostruct(rdata, sp = &hinfo, NULL);
+ break;
+ }
+ case dns_rdatatype_isdn: {
+ dns_rdata_isdn_t isdn;
+ result = dns_rdata_tostruct(rdata, sp = &isdn, NULL);
+ break;
+ }
+ case dns_rdatatype_key: {
+ dns_rdata_key_t key;
+ result = dns_rdata_tostruct(rdata, sp = &key, NULL);
+ break;
+ }
+ case dns_rdatatype_kx: {
+ dns_rdata_in_kx_t in_kx;
+ result = dns_rdata_tostruct(rdata, sp = &in_kx, NULL);
+ break;
+ }
+ case dns_rdatatype_loc: {
+ dns_rdata_loc_t loc;
+ result = dns_rdata_tostruct(rdata, sp = &loc, NULL);
+ break;
+ }
+ case dns_rdatatype_mb: {
+ dns_rdata_mb_t mb;
+ result = dns_rdata_tostruct(rdata, sp = &mb, NULL);
+ break;
+ }
+ case dns_rdatatype_md: {
+ dns_rdata_md_t md;
+ result = dns_rdata_tostruct(rdata, sp = &md, NULL);
+ break;
+ }
+ case dns_rdatatype_mf: {
+ dns_rdata_mf_t mf;
+ result = dns_rdata_tostruct(rdata, sp = &mf, NULL);
+ break;
+ }
+ case dns_rdatatype_mg: {
+ dns_rdata_mg_t mg;
+ result = dns_rdata_tostruct(rdata, sp = &mg, NULL);
+ break;
+ }
+ case dns_rdatatype_minfo: {
+ dns_rdata_minfo_t minfo;
+ result = dns_rdata_tostruct(rdata, sp = &minfo, NULL);
+ break;
+ }
+ case dns_rdatatype_mr: {
+ dns_rdata_mr_t mr;
+ result = dns_rdata_tostruct(rdata, sp = &mr, NULL);
+ break;
+ }
+ case dns_rdatatype_mx: {
+ dns_rdata_mx_t mx;
+ result = dns_rdata_tostruct(rdata, sp = &mx, NULL);
+ break;
+ }
+ case dns_rdatatype_naptr: {
+ dns_rdata_in_naptr_t in_naptr;
+ result = dns_rdata_tostruct(rdata, sp = &in_naptr, NULL);
+ break;
+ }
+ case dns_rdatatype_ns: {
+ dns_rdata_ns_t ns;
+ result = dns_rdata_tostruct(rdata, sp = &ns, NULL);
+ break;
+ }
+ case dns_rdatatype_nsap: {
+ dns_rdata_in_nsap_t in_nsap;
+ result = dns_rdata_tostruct(rdata, sp = &in_nsap, NULL);
+ break;
+ }
+ case dns_rdatatype_nsap_ptr: {
+ dns_rdata_in_nsap_ptr_t in_nsap_ptr;
+ result = dns_rdata_tostruct(rdata, sp = &in_nsap_ptr, NULL);
+ break;
+ }
+ case dns_rdatatype_null: {
+ dns_rdata_null_t null;
+ result = dns_rdata_tostruct(rdata, sp = &null, NULL);
+ break;
+ }
+ case dns_rdatatype_nxt: {
+ dns_rdata_nxt_t nxt;
+ result = dns_rdata_tostruct(rdata, sp = &nxt, NULL);
+ break;
+ }
+ case dns_rdatatype_opt: {
+ dns_rdata_opt_t opt;
+ result = dns_rdata_tostruct(rdata, sp = &opt, NULL);
+ break;
+ }
+ case dns_rdatatype_ptr: {
+ dns_rdata_ptr_t ptr;
+ result = dns_rdata_tostruct(rdata, sp = &ptr, NULL);
+ break;
+ }
+ case dns_rdatatype_px: {
+ dns_rdata_in_px_t in_px;
+ result = dns_rdata_tostruct(rdata, sp = &in_px, NULL);
+ break;
+ }
+ case dns_rdatatype_rp: {
+ dns_rdata_rp_t rp;
+ result = dns_rdata_tostruct(rdata, sp = &rp, NULL);
+ break;
+ }
+ case dns_rdatatype_rt: {
+ dns_rdata_rt_t rt;
+ result = dns_rdata_tostruct(rdata, sp = &rt, NULL);
+ break;
+ }
+ case dns_rdatatype_sig: {
+ dns_rdata_sig_t sig;
+ result = dns_rdata_tostruct(rdata, sp = &sig, NULL);
+ break;
+ }
+ case dns_rdatatype_soa: {
+ dns_rdata_soa_t soa;
+ result = dns_rdata_tostruct(rdata, sp = &soa, NULL);
+ break;
+ }
+ case dns_rdatatype_srv: {
+ dns_rdata_in_srv_t in_srv;
+ result = dns_rdata_tostruct(rdata, sp = &in_srv, NULL);
+ break;
+ }
+ case dns_rdatatype_tkey: {
+ dns_rdata_tkey_t tkey;
+ result = dns_rdata_tostruct(rdata, sp = &tkey, NULL);
+ break;
+ }
+ case dns_rdatatype_tsig: {
+ dns_rdata_any_tsig_t tsig;
+ result = dns_rdata_tostruct(rdata, sp = &tsig, NULL);
+ break;
+ }
+ case dns_rdatatype_txt: {
+ dns_rdata_txt_t txt;
+ result = dns_rdata_tostruct(rdata, sp = &txt, NULL);
+ break;
+ }
+ case dns_rdatatype_spf: {
+ dns_rdata_spf_t spf;
+ result = dns_rdata_tostruct(rdata, sp = &spf, NULL);
+ break;
+ }
+ case dns_rdatatype_unspec: {
+ dns_rdata_unspec_t unspec;
+ result = dns_rdata_tostruct(rdata, sp = &unspec, NULL);
+ break;
+ }
+ case dns_rdatatype_wks: {
+ dns_rdata_in_wks_t in_wks;
+ result = dns_rdata_tostruct(rdata, sp = &in_wks, NULL);
+ break;
+ }
+ case dns_rdatatype_x25: {
+ dns_rdata_x25_t x25;
+ result = dns_rdata_tostruct(rdata, sp = &x25, NULL);
+ break;
+ }
+ case dns_rdatatype_nsec: {
+ dns_rdata_nsec_t nsec;
+ result = dns_rdata_tostruct(rdata, sp = &nsec, NULL);
+ break;
+ }
+ case dns_rdatatype_rrsig: {
+ dns_rdata_rrsig_t rrsig;
+ result = dns_rdata_tostruct(rdata, sp = &rrsig, NULL);
+ break;
+ }
+ case dns_rdatatype_dnskey: {
+ dns_rdata_dnskey_t dnskey;
+ result = dns_rdata_tostruct(rdata, sp = &dnskey, NULL);
+ break;
+ }
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ if (result != ISC_R_SUCCESS)
+ fprintf(stdout, "viastruct: tostruct %d %d return %s\n",
+ rdata->type, rdata->rdclass,
+ dns_result_totext(result));
+ else
+ dns_rdata_freestruct(sp);
+
+ switch (rdata->type) {
+ case dns_rdatatype_a6: {
+ dns_rdata_in_a6_t in_a6;
+ result = dns_rdata_tostruct(rdata, sp = &in_a6, mctx);
+ break;
+ }
+ case dns_rdatatype_a: {
+ switch (rdata->rdclass) {
+ case dns_rdataclass_hs: {
+ dns_rdata_hs_a_t hs_a;
+ result = dns_rdata_tostruct(rdata, sp = &hs_a, mctx);
+ break;
+ }
+ case dns_rdataclass_in: {
+ dns_rdata_in_a_t in_a;
+ result = dns_rdata_tostruct(rdata, sp = &in_a, mctx);
+ break;
+ }
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ break;
+ }
+ case dns_rdatatype_aaaa: {
+ dns_rdata_in_aaaa_t in_aaaa;
+ result = dns_rdata_tostruct(rdata, sp = &in_aaaa, mctx);
+ break;
+ }
+ case dns_rdatatype_afsdb: {
+ dns_rdata_afsdb_t afsdb;
+ result = dns_rdata_tostruct(rdata, sp = &afsdb, mctx);
+ break;
+ }
+ case dns_rdatatype_any: {
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ case dns_rdatatype_apl: {
+ switch (rdata->rdclass) {
+ case dns_rdataclass_in: {
+ dns_rdata_in_apl_t in_apl;
+ result = dns_rdata_tostruct(rdata, sp = &in_apl, mctx);
+ break;
+ }
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ break;
+ }
+ case dns_rdatatype_cert: {
+ dns_rdata_cert_t cert;
+ result = dns_rdata_tostruct(rdata, sp = &cert, mctx);
+ break;
+ }
+ case dns_rdatatype_cname: {
+ dns_rdata_cname_t cname;
+ result = dns_rdata_tostruct(rdata, sp = &cname, mctx);
+ break;
+ }
+ case dns_rdatatype_dname: {
+ dns_rdata_dname_t dname;
+ result = dns_rdata_tostruct(rdata, sp = &dname, mctx);
+ break;
+ }
+ case dns_rdatatype_gpos: {
+ dns_rdata_gpos_t gpos;
+ result = dns_rdata_tostruct(rdata, sp = &gpos, mctx);
+ break;
+ }
+ case dns_rdatatype_hinfo: {
+ dns_rdata_hinfo_t hinfo;
+ result = dns_rdata_tostruct(rdata, sp = &hinfo, mctx);
+ break;
+ }
+ case dns_rdatatype_isdn: {
+ dns_rdata_isdn_t isdn;
+ result = dns_rdata_tostruct(rdata, sp = &isdn, mctx);
+ break;
+ }
+ case dns_rdatatype_key: {
+ dns_rdata_key_t key;
+ result = dns_rdata_tostruct(rdata, sp = &key, mctx);
+ break;
+ }
+ case dns_rdatatype_kx: {
+ dns_rdata_in_kx_t in_kx;
+ result = dns_rdata_tostruct(rdata, sp = &in_kx, mctx);
+ break;
+ }
+ case dns_rdatatype_loc: {
+ dns_rdata_loc_t loc;
+ result = dns_rdata_tostruct(rdata, sp = &loc, mctx);
+ break;
+ }
+ case dns_rdatatype_mb: {
+ dns_rdata_mb_t mb;
+ result = dns_rdata_tostruct(rdata, sp = &mb, mctx);
+ break;
+ }
+ case dns_rdatatype_md: {
+ dns_rdata_md_t md;
+ result = dns_rdata_tostruct(rdata, sp = &md, mctx);
+ break;
+ }
+ case dns_rdatatype_mf: {
+ dns_rdata_mf_t mf;
+ result = dns_rdata_tostruct(rdata, sp = &mf, mctx);
+ break;
+ }
+ case dns_rdatatype_mg: {
+ dns_rdata_mg_t mg;
+ result = dns_rdata_tostruct(rdata, sp = &mg, mctx);
+ break;
+ }
+ case dns_rdatatype_minfo: {
+ dns_rdata_minfo_t minfo;
+ result = dns_rdata_tostruct(rdata, sp = &minfo, mctx);
+ break;
+ }
+ case dns_rdatatype_mr: {
+ dns_rdata_mr_t mr;
+ result = dns_rdata_tostruct(rdata, sp = &mr, mctx);
+ break;
+ }
+ case dns_rdatatype_mx: {
+ dns_rdata_mx_t mx;
+ result = dns_rdata_tostruct(rdata, sp = &mx, mctx);
+ break;
+ }
+ case dns_rdatatype_naptr: {
+ dns_rdata_in_naptr_t in_naptr;
+ result = dns_rdata_tostruct(rdata, sp = &in_naptr, mctx);
+ break;
+ }
+ case dns_rdatatype_ns: {
+ dns_rdata_ns_t ns;
+ result = dns_rdata_tostruct(rdata, sp = &ns, mctx);
+ break;
+ }
+ case dns_rdatatype_nsap: {
+ dns_rdata_in_nsap_t in_nsap;
+ result = dns_rdata_tostruct(rdata, sp = &in_nsap, mctx);
+ break;
+ }
+ case dns_rdatatype_nsap_ptr: {
+ dns_rdata_in_nsap_ptr_t in_nsap_ptr;
+ result = dns_rdata_tostruct(rdata, sp = &in_nsap_ptr, mctx);
+ break;
+ }
+ case dns_rdatatype_null: {
+ dns_rdata_null_t null;
+ result = dns_rdata_tostruct(rdata, sp = &null, mctx);
+ break;
+ }
+ case dns_rdatatype_nxt: {
+ dns_rdata_nxt_t nxt;
+ result = dns_rdata_tostruct(rdata, sp = &nxt, mctx);
+ break;
+ }
+ case dns_rdatatype_opt: {
+ dns_rdata_opt_t opt;
+ result = dns_rdata_tostruct(rdata, sp = &opt, mctx);
+ break;
+ }
+ case dns_rdatatype_ptr: {
+ dns_rdata_ptr_t ptr;
+ result = dns_rdata_tostruct(rdata, sp = &ptr, mctx);
+ break;
+ }
+ case dns_rdatatype_px: {
+ dns_rdata_in_px_t in_px;
+ result = dns_rdata_tostruct(rdata, sp = &in_px, mctx);
+ break;
+ }
+ case dns_rdatatype_rp: {
+ dns_rdata_rp_t rp;
+ result = dns_rdata_tostruct(rdata, sp = &rp, mctx);
+ break;
+ }
+ case dns_rdatatype_rt: {
+ dns_rdata_rt_t rt;
+ result = dns_rdata_tostruct(rdata, sp = &rt, mctx);
+ break;
+ }
+ case dns_rdatatype_sig: {
+ dns_rdata_sig_t sig;
+ result = dns_rdata_tostruct(rdata, sp = &sig, mctx);
+ break;
+ }
+ case dns_rdatatype_soa: {
+ dns_rdata_soa_t soa;
+ result = dns_rdata_tostruct(rdata, sp = &soa, mctx);
+ break;
+ }
+ case dns_rdatatype_srv: {
+ dns_rdata_in_srv_t in_srv;
+ result = dns_rdata_tostruct(rdata, sp = &in_srv, mctx);
+ break;
+ }
+ case dns_rdatatype_tkey: {
+ dns_rdata_tkey_t tkey;
+ result = dns_rdata_tostruct(rdata, sp = &tkey, mctx);
+ break;
+ }
+ case dns_rdatatype_tsig: {
+ dns_rdata_any_tsig_t tsig;
+ result = dns_rdata_tostruct(rdata, sp = &tsig, mctx);
+ break;
+ }
+ case dns_rdatatype_txt: {
+ dns_rdata_txt_t txt;
+ result = dns_rdata_tostruct(rdata, sp = &txt, mctx);
+ break;
+ }
+ case dns_rdatatype_spf: {
+ dns_rdata_spf_t spf;
+ result = dns_rdata_tostruct(rdata, sp = &spf, mctx);
+ break;
+ }
+ case dns_rdatatype_unspec: {
+ dns_rdata_unspec_t unspec;
+ result = dns_rdata_tostruct(rdata, sp = &unspec, mctx);
+ break;
+ }
+ case dns_rdatatype_wks: {
+ dns_rdata_in_wks_t in_wks;
+ result = dns_rdata_tostruct(rdata, sp = &in_wks, mctx);
+ break;
+ }
+ case dns_rdatatype_x25: {
+ dns_rdata_x25_t x25;
+ result = dns_rdata_tostruct(rdata, sp = &x25, mctx);
+ break;
+ }
+ case dns_rdatatype_nsec: {
+ dns_rdata_nsec_t nsec;
+ result = dns_rdata_tostruct(rdata, sp = &nsec, mctx);
+ break;
+ }
+ case dns_rdatatype_rrsig: {
+ dns_rdata_rrsig_t rrsig;
+ result = dns_rdata_tostruct(rdata, sp = &rrsig, mctx);
+ break;
+ }
+ case dns_rdatatype_dnskey: {
+ dns_rdata_dnskey_t dnskey;
+ result = dns_rdata_tostruct(rdata, sp = &dnskey, mctx);
+ break;
+ }
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ if (result != ISC_R_SUCCESS)
+ fprintf(stdout, "viastruct: tostruct %d %d return %s\n",
+ rdata->type, rdata->rdclass,
+ dns_result_totext(result));
+ else {
+ need_free = ISC_TRUE;
+
+ rdc = rdata->rdclass;
+ rdt = rdata->type;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, sp, b);
+ if (result != ISC_R_SUCCESS)
+ fprintf(stdout,
+ "viastruct: fromstruct %d %d return %s\n",
+ rdata->type, rdata->rdclass,
+ dns_result_totext(result));
+ else if (rdata->length != rdata2->length ||
+ memcmp(rdata->data, rdata2->data, rdata->length) != 0)
+ {
+ isc_uint32_t i;
+ isc_uint32_t l;
+
+ fprintf(stdout, "viastruct: memcmp failed\n");
+
+ fprintf(stdout, "%d %d\n",
+ rdata->length, rdata2->length);
+ l = rdata->length;
+ if (rdata2->length < l)
+ l = rdata2->length;
+ for (i = 0; i < l; i++)
+ fprintf(stdout, "%02x %02x\n",
+ rdata->data[i], rdata2->data[i]);
+ }
+ }
+#if 0
+ switch (rdata->type) {
+ case dns_rdatatype_a6: {
+ dns_rdata_in_a6_t in_a6;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_a6, b);
+ break;
+ }
+ case dns_rdatatype_a: {
+ switch (rdata->rdclass) {
+ case dns_rdataclass_hs: {
+ dns_rdata_hs_a_t hs_a;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt,
+ &hs_a, b);
+ break;
+ }
+ case dns_rdataclass_in: {
+ dns_rdata_in_a_t in_a;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt,
+ &in_a, b);
+ break;
+ }
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ break;
+ }
+ case dns_rdatatype_aaaa: {
+ dns_rdata_in_aaaa_t in_aaaa;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_aaaa, b);
+ break;
+ }
+ case dns_rdatatype_afsdb: {
+ dns_rdata_afsdb_t afsdb;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &afsdb, b);
+ break;
+ }
+ case dns_rdatatype_any: {
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ case dns_rdatatype_apl: {
+ switch (rdata->rdclass) {
+ case dns_rdataclass_in: {
+ dns_rdata_in_apl_t in_apl;
+ result = dns_rdata_fromstruct(rdata, rdc, rdt, &in_apl, b);
+ break;
+ }
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ break;
+ }
+ case dns_rdatatype_cert: {
+ dns_rdata_cert_t cert;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &cert, b);
+ break;
+ }
+ case dns_rdatatype_cname: {
+ dns_rdata_cname_t cname;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &cname, b);
+ break;
+ }
+ case dns_rdatatype_dname: {
+ dns_rdata_dname_t dname;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &dname, b);
+ break;
+ }
+ case dns_rdatatype_gpos: {
+ dns_rdata_gpos_t gpos;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &gpos, b);
+ break;
+ }
+ case dns_rdatatype_hinfo: {
+ dns_rdata_hinfo_t hinfo;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &hinfo, b);
+ break;
+ }
+ case dns_rdatatype_isdn: {
+ dns_rdata_isdn_t isdn;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &isdn, b);
+ break;
+ }
+ case dns_rdatatype_key: {
+ dns_rdata_key_t key;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &key, b);
+ break;
+ }
+ case dns_rdatatype_kx: {
+ dns_rdata_in_kx_t in_kx;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_kx, b);
+ break;
+ }
+ case dns_rdatatype_loc: {
+ dns_rdata_loc_t loc;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &loc, b);
+ break;
+ }
+ case dns_rdatatype_mb: {
+ dns_rdata_mb_t mb;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mb, b);
+ break;
+ }
+ case dns_rdatatype_md: {
+ dns_rdata_md_t md;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &md, b);
+ break;
+ }
+ case dns_rdatatype_mf: {
+ dns_rdata_mf_t mf;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mf, b);
+ break;
+ }
+ case dns_rdatatype_mg: {
+ dns_rdata_mg_t mg;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mg, b);
+ break;
+ }
+ case dns_rdatatype_minfo: {
+ dns_rdata_minfo_t minfo;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &minfo, b);
+ break;
+ }
+ case dns_rdatatype_mr: {
+ dns_rdata_mr_t mr;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mr, b);
+ break;
+ }
+ case dns_rdatatype_mx: {
+ dns_rdata_mx_t mx;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &mx, b);
+ break;
+ }
+ case dns_rdatatype_naptr: {
+ dns_rdata_in_naptr_t in_naptr;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_naptr, b);
+ break;
+ }
+ case dns_rdatatype_ns: {
+ dns_rdata_ns_t ns;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &ns, b);
+ break;
+ }
+ case dns_rdatatype_nsap: {
+ dns_rdata_in_nsap_t in_nsap;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_nsap, b);
+ break;
+ }
+ case dns_rdatatype_nsap_ptr: {
+ dns_rdata_in_nsap_ptr_t in_nsap_ptr;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_nsap_ptr,
+ b);
+ break;
+ }
+ case dns_rdatatype_null: {
+ dns_rdata_null_t null;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &null, b);
+ break;
+ }
+ case dns_rdatatype_nxt: {
+ dns_rdata_nxt_t nxt;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &nxt, b);
+ break;
+ }
+ case dns_rdatatype_opt: {
+ dns_rdata_opt_t opt;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &opt, b);
+ break;
+ }
+ case dns_rdatatype_ptr: {
+ dns_rdata_ptr_t ptr;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &ptr, b);
+ break;
+ }
+ case dns_rdatatype_px: {
+ dns_rdata_in_px_t in_px;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_px, b);
+ break;
+ }
+ case dns_rdatatype_rp: {
+ dns_rdata_rp_t rp;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rp, b);
+ break;
+ }
+ case dns_rdatatype_rt: {
+ dns_rdata_rt_t rt;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rt, b);
+ break;
+ }
+ case dns_rdatatype_sig: {
+ dns_rdata_sig_t sig;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &sig, b);
+ break;
+ }
+ case dns_rdatatype_soa: {
+ dns_rdata_soa_t soa;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &soa, b);
+ break;
+ }
+ case dns_rdatatype_srv: {
+ dns_rdata_in_srv_t in_srv;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_srv, b);
+ break;
+ }
+ case dns_rdatatype_tkey: {
+ dns_rdata_tkey_t tkey;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &tkey, b);
+ break;
+ }
+ case dns_rdatatype_tsig: {
+ dns_rdata_any_tsig_t tsig;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &tsig, b);
+ break;
+ }
+ case dns_rdatatype_txt: {
+ dns_rdata_txt_t txt;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &txt, b);
+ break;
+ }
+ case dns_rdatatype_spf: {
+ dns_rdata_spf_t spf;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &spf, b);
+ break;
+ }
+ case dns_rdatatype_unspec: {
+ dns_rdata_unspec_t unspec;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &unspec, b);
+ break;
+ }
+ case dns_rdatatype_wks: {
+ dns_rdata_in_wks_t in_wks;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &in_wks, b);
+ break;
+ }
+ case dns_rdatatype_x25: {
+ dns_rdata_x25_t x25;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &x25, b);
+ break;
+ }
+ case dns_rdatatype_nsec: {
+ dns_rdata_nsec_t nsec;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &nsec, b);
+ break;
+ }
+ case dns_rdatatype_rrsig: {
+ dns_rdata_rrsig_t rrsig;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &rrsig, b);
+ break;
+ }
+ case dns_rdatatype_dnskey: {
+ dns_rdata_dnskey_t dnskey;
+ result = dns_rdata_fromstruct(rdata2, rdc, rdt, &dnskey, b);
+ break;
+ }
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+#endif
+ if (need_free)
+ dns_rdata_freestruct(sp);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_token_t token;
+ isc_result_t result;
+ int quiet = 0;
+ int c;
+ int stats = 0;
+ unsigned int options = 0;
+ dns_rdatatype_t type;
+ dns_rdataclass_t class;
+ dns_rdatatype_t lasttype = 0;
+ char outbuf[16*1024];
+ char inbuf[16*1024];
+ char wirebuf[16*1024];
+ char viabuf[16*1024];
+ isc_buffer_t dbuf;
+ isc_buffer_t tbuf;
+ isc_buffer_t wbuf;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_t last = DNS_RDATA_INIT;
+ int need_eol = 0;
+ int wire = 0;
+ dns_compress_t cctx;
+ dns_decompress_t dctx;
+ int trunc = 0;
+ int add = 0;
+ int len;
+ int zero = 0;
+ int debug = 0;
+ isc_region_t region;
+ int first = 1;
+ int raw = 0;
+ int tostruct = 0;
+
+ while ((c = isc_commandline_parse(argc, argv, "dqswtarzS")) != -1) {
+ switch (c) {
+ case 'd':
+ debug = 1;
+ quiet = 0;
+ break;
+ case 'q':
+ quiet = 1;
+ debug = 0;
+ break;
+ case 's':
+ stats = 1;
+ break;
+ case 'w':
+ wire = 1;
+ break;
+ case 't':
+ trunc = 1;
+ break;
+ case 'a':
+ add = 1;
+ break;
+ case 'z':
+ zero = 1;
+ break;
+ case 'r':
+ raw++;
+ break;
+ case 'S':
+ tostruct++;
+ break;
+ }
+ }
+
+ memset(&dctx, 0, sizeof(dctx));
+ dctx.allowed = DNS_COMPRESS_ALL;
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_lex_create(mctx, 256, &lex) == ISC_R_SUCCESS);
+
+ /*
+ * Set up to lex DNS master file.
+ */
+
+ specials['('] = 1;
+ specials[')'] = 1;
+ specials['"'] = 1;
+ isc_lex_setspecials(lex, specials);
+ options = ISC_LEXOPT_EOL;
+ isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
+
+ RUNTIME_CHECK(isc_lex_openstream(lex, stdin) == ISC_R_SUCCESS);
+
+ dns_rdata_init(&last);
+ while ((result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER,
+ &token)) == ISC_R_SUCCESS) {
+ if (debug) fprintf(stdout, "token.type = %d\n", token.type);
+ if (need_eol) {
+ if (token.type == isc_tokentype_eol)
+ need_eol = 0;
+ continue;
+ }
+ if (token.type == isc_tokentype_eof)
+ break;
+
+ /*
+ * Get type.
+ */
+ if (token.type == isc_tokentype_number) {
+ type = token.value.as_ulong;
+ isc_buffer_init(&tbuf, outbuf, sizeof(outbuf));
+ result = dns_rdatatype_totext(type, &tbuf);
+ fprintf(stdout, "type = %.*s(%d)\n",
+ (int)tbuf.used, (char*)tbuf.base, type);
+ } else if (token.type == isc_tokentype_string) {
+ result = dns_rdatatype_fromtext(&type,
+ &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout,
+ "dns_rdatatype_fromtext "
+ "returned %s(%d)\n",
+ dns_result_totext(result), result);
+ fflush(stdout);
+ need_eol = 1;
+ continue;
+ }
+ fprintf(stdout, "type = %.*s(%d)\n",
+ (int)token.value.as_textregion.length,
+ token.value.as_textregion.base, type);
+ } else
+ continue;
+
+ result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER,
+ &token);
+ if (result != ISC_R_SUCCESS)
+ break;
+ if (token.type == isc_tokentype_eol)
+ continue;
+ if (token.type == isc_tokentype_eof)
+ break;
+ if (token.type == isc_tokentype_number) {
+ class = token.value.as_ulong;
+ isc_buffer_init(&tbuf, outbuf, sizeof(outbuf));
+ result = dns_rdatatype_totext(class, &tbuf);
+ fprintf(stdout, "class = %.*s(%d)\n",
+ (int)tbuf.used, (char*)tbuf.base, class);
+ } else if (token.type == isc_tokentype_string) {
+ result = dns_rdataclass_fromtext(&class,
+ &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout, "dns_rdataclass_fromtext "
+ "returned %s(%d)\n",
+ dns_result_totext(result), result);
+ fflush(stdout);
+ need_eol = 1;
+ continue;
+ }
+ fprintf(stdout, "class = %.*s(%d)\n",
+ (int)token.value.as_textregion.length,
+ token.value.as_textregion.base, class);
+ } else
+ continue;
+
+ fflush(stdout);
+ dns_rdata_init(&rdata);
+ isc_buffer_init(&dbuf, inbuf, sizeof(inbuf));
+ result = dns_rdata_fromtext(&rdata, class, type, lex,
+ NULL, 0, mctx, &dbuf,
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout,
+ "dns_rdata_fromtext returned %s(%d)\n",
+ dns_result_totext(result), result);
+ fflush(stdout);
+ continue;
+ }
+ if (raw) {
+ unsigned int i;
+ for (i = 0; i < rdata.length; /* */ ) {
+ fprintf(stdout, "%02x", rdata.data[i]);
+ if ((++i % 20) == 0)
+ fputs("\n", stdout);
+ else
+ if (i == rdata.length)
+ fputs("\n", stdout);
+ else
+ fputs(" ", stdout);
+ }
+ }
+
+ /*
+ * Convert to wire and back?
+ */
+ if (wire) {
+ result = dns_compress_init(&cctx, -1, mctx);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout,
+ "dns_compress_init returned %s(%d)\n",
+ dns_result_totext(result), result);
+ continue;
+ }
+ isc_buffer_init(&wbuf, wirebuf, sizeof(wirebuf));
+ result = dns_rdata_towire(&rdata, &cctx, &wbuf);
+ dns_compress_invalidate(&cctx);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout,
+ "dns_rdata_towire returned %s(%d)\n",
+ dns_result_totext(result), result);
+ continue;
+ }
+ len = wbuf.used - wbuf.current;
+ if (raw > 2) {
+ unsigned int i;
+ fputs("\n", stdout);
+ for (i = 0; i < (unsigned int)len; /* */ ) {
+ fprintf(stdout, "%02x",
+ ((unsigned char*)wbuf.base)[i + wbuf.current]);
+ if ((++i % 20) == 0)
+ fputs("\n", stdout);
+ else
+ if (i == wbuf.used)
+ fputs("\n", stdout);
+ else
+ fputs(" ", stdout);
+ }
+ }
+ if (zero)
+ len = 0;
+ if (trunc)
+ len = (len * 3) / 4;
+ if (add) {
+ isc_buffer_add(&wbuf, len / 4 + 1);
+ len += len / 4 + 1;
+ }
+
+ isc_buffer_setactive(&wbuf, len);
+ dns_rdata_init(&rdata);
+ isc_buffer_init(&dbuf, inbuf, sizeof(inbuf));
+ dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
+ result = dns_rdata_fromwire(&rdata, class, type, &wbuf,
+ &dctx, 0, &dbuf);
+ dns_decompress_invalidate(&dctx);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stdout,
+ "dns_rdata_fromwire returned %s(%d)\n",
+ dns_result_totext(result), result);
+ fflush(stdout);
+ continue;
+ }
+ }
+ if (raw > 1) {
+ unsigned int i;
+ fputs("\n", stdout);
+ for (i = 0; i < rdata.length; /* */ ) {
+ fprintf(stdout, "%02x", rdata.data[i]);
+ if ((++i % 20) == 0)
+ fputs("\n", stdout);
+ else
+ if (i == rdata.length)
+ fputs("\n", stdout);
+ else
+ fputs(" ", stdout);
+ }
+ }
+ if (tostruct) {
+ isc_mem_t *mctx2 = NULL;
+ dns_rdata_t rdata2 = DNS_RDATA_INIT;
+ isc_buffer_t vbuf;
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx2)
+ == ISC_R_SUCCESS);
+
+ isc_buffer_init(&vbuf, viabuf, sizeof(viabuf));
+ dns_rdata_init(&rdata2);
+ viastruct(&rdata, mctx2, &rdata2, &vbuf);
+ if (!quiet && stats)
+ isc_mem_stats(mctx2, stdout);
+ isc_mem_destroy(&mctx2);
+ }
+
+ isc_buffer_init(&tbuf, outbuf, sizeof(outbuf));
+ result = dns_rdata_totext(&rdata, NULL, &tbuf);
+ if (result != ISC_R_SUCCESS)
+ fprintf(stdout, "dns_rdata_totext returned %s(%d)\n",
+ dns_result_totext(result), result);
+ else
+ fprintf(stdout, "\"%.*s\"\n",
+ (int)tbuf.used, (char*)tbuf.base);
+ fflush(stdout);
+ if (lasttype == type) {
+ fprintf(stdout, "dns_rdata_compare = %d\n",
+ dns_rdata_compare(&rdata, &last));
+
+ }
+ if (!first) {
+ free(last.data);
+ }
+ dns_rdata_init(&last);
+ region.base = malloc(region.length = rdata.length);
+ if (region.base) {
+ memcpy(region.base, rdata.data, rdata.length);
+ dns_rdata_fromregion(&last, class, type, &region);
+ lasttype = type;
+ first = 0;
+ } else
+ first = 1;
+
+ }
+ if (result != ISC_R_EOF)
+ printf("Result: %s\n", isc_result_totext(result));
+
+ isc_lex_close(lex);
+ isc_lex_destroy(&lex);
+ if (!quiet && stats)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/resolv.conf.sample b/bin/tests/resolv.conf.sample
new file mode 100644
index 0000000..e9e349d
--- /dev/null
+++ b/bin/tests/resolv.conf.sample
@@ -0,0 +1,38 @@
+# Copyright (C) 2004, 2007 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: resolv.conf.sample,v 1.11 2007/06/19 23:46:59 tbox Exp $
+
+domain jab.fr
+nameserver 194.150.1.2 ; ignore that
+
+; ignore this comment
+
+nameserver 194.150.1.1 # ignore this comment too
+
+a-bad-entry-that-will be ignored
+
+option debug ; foo
+option ndots:10
+
+sortlist 10.0.0.0/255.244.33.0 11.0.0.0
+
+search aaa bbb ccc ddd ; blank stuff
+# search eee fff ggg hhh
+
+#
+# Bar
+### bar bar bar
+#
diff --git a/bin/tests/rwlock_test.c b/bin/tests/rwlock_test.c
new file mode 100644
index 0000000..9aa05b5
--- /dev/null
+++ b/bin/tests/rwlock_test.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: rwlock_test.c,v 1.26 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/print.h>
+#include <isc/thread.h>
+#include <isc/rwlock.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+isc_rwlock_t lock;
+
+static void *
+run1(void *arg) {
+ char *message = arg;
+
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ printf("%s got READ lock\n", message);
+ sleep(1);
+ printf("%s giving up READ lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ printf("%s got READ lock\n", message);
+ sleep(1);
+ printf("%s giving up READ lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ printf("%s got WRITE lock\n", message);
+ sleep(1);
+ printf("%s giving up WRITE lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ return (NULL);
+}
+
+static void *
+run2(void *arg) {
+ char *message = arg;
+
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ printf("%s got WRITE lock\n", message);
+ sleep(1);
+ printf("%s giving up WRITE lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ printf("%s got WRITE lock\n", message);
+ sleep(1);
+ printf("%s giving up WRITE lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_write) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_rwlock_lock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ printf("%s got READ lock\n", message);
+ sleep(1);
+ printf("%s giving up READ lock\n", message);
+ RUNTIME_CHECK(isc_rwlock_unlock(&lock, isc_rwlocktype_read) ==
+ ISC_R_SUCCESS);
+ return (NULL);
+}
+
+int
+main(int argc, char *argv[]) {
+ unsigned int nworkers;
+ unsigned int i;
+ isc_thread_t workers[100];
+ char name[100];
+ void *dupname;
+
+ if (argc > 1)
+ nworkers = atoi(argv[1]);
+ else
+ nworkers = 2;
+ if (nworkers > 100)
+ nworkers = 100;
+ printf("%d workers\n", nworkers);
+
+ RUNTIME_CHECK(isc_rwlock_init(&lock, 5, 10) == ISC_R_SUCCESS);
+
+ for (i = 0; i < nworkers; i++) {
+ sprintf(name, "%02u", i);
+ dupname = strdup(name);
+ RUNTIME_CHECK(dupname != NULL);
+ if (i != 0 && i % 3 == 0)
+ RUNTIME_CHECK(isc_thread_create(run1, dupname,
+ &workers[i]) ==
+ ISC_R_SUCCESS);
+ else
+ RUNTIME_CHECK(isc_thread_create(run2, dupname,
+ &workers[i]) ==
+ ISC_R_SUCCESS);
+ }
+
+ for (i = 0; i < nworkers; i++)
+ (void)isc_thread_join(workers[i], NULL);
+
+ isc_rwlock_destroy(&lock);
+
+ return (0);
+}
+
+#else
+
+int
+main(int argc, char *argv[]) {
+ UNUSED(argc);
+ UNUSED(argv);
+ fprintf(stderr, "This test requires threads.\n");
+ return(1);
+}
+
+#endif
diff --git a/bin/tests/serial_test.c b/bin/tests/serial_test.c
new file mode 100644
index 0000000..3cc8ade
--- /dev/null
+++ b/bin/tests/serial_test.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004, 2007 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
+ * 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: serial_test.c,v 1.15 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/serial.h>
+#include <isc/stdlib.h>
+
+int
+main() {
+ isc_uint32_t a, b;
+ char buf[1024];
+ char *s, *e;
+
+ while (fgets(buf, sizeof(buf), stdin) != NULL) {
+ buf[sizeof(buf) - 1] = '\0';
+ s = buf;
+ a = strtoul(s, &e, 0);
+ if (s == e)
+ continue;
+ s = e;
+ b = strtoul(s, &e, 0);
+ if (s == e)
+ continue;
+ fprintf(stdout, "%u %u gt:%d lt:%d ge:%d le:%d eq:%d ne:%d\n",
+ a, b,
+ isc_serial_gt(a,b), isc_serial_lt(a,b),
+ isc_serial_ge(a,b), isc_serial_le(a,b),
+ isc_serial_eq(a,b), isc_serial_ne(a,b));
+ }
+ return (0);
+}
diff --git a/bin/tests/shutdown_test.c b/bin/tests/shutdown_test.c
new file mode 100644
index 0000000..4b53cd0
--- /dev/null
+++ b/bin/tests/shutdown_test.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: shutdown_test.c,v 1.23 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+typedef struct {
+ isc_mem_t * mctx;
+ isc_task_t * task;
+ isc_timer_t * timer;
+ unsigned int ticks;
+ char name[16];
+ isc_boolean_t exiting;
+ isc_task_t * peer;
+} t_info;
+
+#define MAX_TASKS 3
+#define T2_SHUTDOWNOK (ISC_EVENTCLASS(1024) + 0)
+#define T2_SHUTDOWNDONE (ISC_EVENTCLASS(1024) + 1)
+#define FOO_EVENT (ISC_EVENTCLASS(1024) + 2)
+
+static t_info tasks[MAX_TASKS];
+static unsigned int task_count;
+static isc_taskmgr_t * task_manager;
+static isc_timermgr_t * timer_manager;
+
+static void
+t1_shutdown(isc_task_t *task, isc_event_t *event) {
+ t_info *info = event->ev_arg;
+
+ printf("task %s (%p) t1_shutdown\n", info->name, task);
+ isc_task_detach(&info->task);
+ isc_event_free(&event);
+}
+
+static void
+t2_shutdown(isc_task_t *task, isc_event_t *event) {
+ t_info *info = event->ev_arg;
+
+ printf("task %s (%p) t2_shutdown\n", info->name, task);
+ info->exiting = ISC_TRUE;
+ isc_event_free(&event);
+}
+
+static void
+shutdown_action(isc_task_t *task, isc_event_t *event) {
+ t_info *info = event->ev_arg;
+ isc_event_t *nevent;
+
+ INSIST(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
+
+ printf("task %s (%p) shutdown\n", info->name, task);
+ if (strcmp(info->name, "0") == 0) {
+ isc_timer_detach(&info->timer);
+ nevent = isc_event_allocate(info->mctx, info, T2_SHUTDOWNOK,
+ t2_shutdown, &tasks[1],
+ sizeof(*event));
+ RUNTIME_CHECK(nevent != NULL);
+ info->exiting = ISC_TRUE;
+ isc_task_sendanddetach(&info->peer, &nevent);
+ }
+ isc_event_free(&event);
+}
+
+static void
+foo_event(isc_task_t *task, isc_event_t *event) {
+ printf("task(%p) foo\n", task);
+ isc_event_free(&event);
+}
+
+static void
+tick(isc_task_t *task, isc_event_t *event) {
+ t_info *info = event->ev_arg;
+ isc_event_t *nevent;
+
+ INSIST(event->ev_type == ISC_TIMEREVENT_TICK);
+
+ printf("task %s (%p) tick\n", info->name, task);
+
+ info->ticks++;
+ if (strcmp(info->name, "1") == 0) {
+ if (info->ticks == 10) {
+ RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
+ } else if (info->ticks >= 15 && info->exiting) {
+ isc_timer_detach(&info->timer);
+ isc_task_detach(&info->task);
+ nevent = isc_event_allocate(info->mctx, info,
+ T2_SHUTDOWNDONE,
+ t1_shutdown, &tasks[0],
+ sizeof(*event));
+ RUNTIME_CHECK(nevent != NULL);
+ isc_task_send(info->peer, &nevent);
+ isc_task_detach(&info->peer);
+ }
+ } else if (strcmp(info->name, "foo") == 0) {
+ isc_timer_detach(&info->timer);
+ nevent = isc_event_allocate(info->mctx, info,
+ FOO_EVENT,
+ foo_event, task,
+ sizeof(*event));
+ RUNTIME_CHECK(nevent != NULL);
+ isc_task_sendanddetach(&task, &nevent);
+ }
+
+ isc_event_free(&event);
+}
+
+static t_info *
+new_task(isc_mem_t *mctx, const char *name) {
+ t_info *ti;
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ RUNTIME_CHECK(task_count < MAX_TASKS);
+ ti = &tasks[task_count];
+ ti->mctx = mctx;
+ ti->task = NULL;
+ ti->timer = NULL;
+ ti->ticks = 0;
+ if (name != NULL) {
+ INSIST(strlen(name) < sizeof(ti->name));
+ strcpy(ti->name, name);
+ } else
+ sprintf(ti->name, "%d", task_count);
+ RUNTIME_CHECK(isc_task_create(task_manager, 0, &ti->task) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(ti->task, shutdown_action, ti) ==
+ ISC_R_SUCCESS);
+
+ isc_time_settoepoch(&expires);
+ isc_interval_set(&interval, 1, 0);
+ RUNTIME_CHECK(isc_timer_create(timer_manager, isc_timertype_ticker,
+ &expires, &interval, ti->task,
+ tick, ti, &ti->timer) ==
+ ISC_R_SUCCESS);
+
+ task_count++;
+
+ return (ti);
+}
+
+int
+main(int argc, char *argv[]) {
+ unsigned int workers;
+ t_info *t1, *t2, *t3;
+ isc_task_t *task;
+ isc_mem_t *mctx, *mctx2;
+
+ RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
+
+ if (argc > 1)
+ workers = atoi(argv[1]);
+ else
+ workers = 2;
+ printf("%d workers\n", workers);
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ mctx2 = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx2) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &task_manager) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timer_manager) ==
+ ISC_R_SUCCESS);
+
+ t1 = new_task(mctx, NULL);
+ t2 = new_task(mctx2, NULL);
+ isc_task_attach(t2->task, &t1->peer);
+ isc_task_attach(t1->task, &t2->peer);
+
+ /*
+ * Test run-triggered shutdown.
+ */
+ t3 = new_task(mctx2, "foo");
+
+ /*
+ * Test implicit shutdown.
+ */
+ task = NULL;
+ RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) ==
+ ISC_R_SUCCESS);
+ isc_task_detach(&task);
+
+ /*
+ * Test anti-zombie code.
+ */
+ RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) ==
+ ISC_R_SUCCESS);
+ isc_task_detach(&task);
+
+ RUNTIME_CHECK(isc_app_run() == ISC_R_SUCCESS);
+
+ isc_taskmgr_destroy(&task_manager);
+ isc_timermgr_destroy(&timer_manager);
+
+ printf("Statistics for mctx:\n");
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+ printf("Statistics for mctx2:\n");
+ isc_mem_stats(mctx2, stdout);
+ isc_mem_destroy(&mctx2);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/sig0_test.c b/bin/tests/sig0_test.c
new file mode 100644
index 0000000..f36bbee
--- /dev/null
+++ b/bin/tests/sig0_test.c
@@ -0,0 +1,305 @@
+/*
+ * 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
+ * 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: sig0_test.c,v 1.17 2008/07/22 23:47:04 tbox Exp $ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/boolean.h>
+#include <isc/assertions.h>
+#include <isc/commandline.h>
+#include <isc/entropy.h>
+#include <isc/error.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/socket.h>
+#include <isc/util.h>
+
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdataset.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/types.h>
+
+#include <dst/result.h>
+#include <dst/dst.h>
+
+#define CHECK(str, x) { \
+ if ((x) != ISC_R_SUCCESS) { \
+ printf("%s: %s\n", (str), isc_result_totext(x)); \
+ exit(-1); \
+ } \
+}
+
+isc_mutex_t lock;
+dst_key_t *key;
+isc_mem_t *mctx;
+unsigned char qdata[1024], rdata[1024];
+isc_buffer_t qbuffer, rbuffer;
+isc_taskmgr_t *taskmgr;
+isc_entropy_t *ent = NULL;
+isc_task_t *task1;
+isc_log_t *lctx = NULL;
+isc_logconfig_t *logconfig = NULL;
+isc_socket_t *s;
+isc_sockaddr_t address;
+char output[10 * 1024];
+isc_buffer_t outbuf;
+static const dns_master_style_t *style = &dns_master_style_debug;
+
+static void
+senddone(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+
+ REQUIRE(sevent != NULL);
+ REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);
+ REQUIRE(task == task1);
+
+ printf("senddone\n");
+
+ isc_event_free(&event);
+}
+
+static void
+recvdone(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ isc_buffer_t source;
+ isc_result_t result;
+ dns_message_t *response;
+
+ REQUIRE(sevent != NULL);
+ REQUIRE(sevent->ev_type == ISC_SOCKEVENT_RECVDONE);
+ REQUIRE(task == task1);
+
+ printf("recvdone\n");
+ if (sevent->result != ISC_R_SUCCESS) {
+ printf("failed\n");
+ exit(-1);
+ }
+
+ isc_buffer_init(&source, sevent->region.base, sevent->region.length);
+ isc_buffer_add(&source, sevent->n);
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+ result = dns_message_parse(response, &source, 0);
+ CHECK("dns_message_parse", result);
+
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(response, style, 0, &outbuf);
+ CHECK("dns_message_totext", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+
+ dns_message_destroy(&response);
+ isc_event_free(&event);
+
+ isc_app_shutdown();
+}
+
+static void
+buildquery(void) {
+ isc_result_t result;
+ dns_rdataset_t *question = NULL;
+ dns_name_t *qname = NULL;
+ isc_region_t r, inr;
+ dns_message_t *query;
+ char nametext[] = "host.example";
+ isc_buffer_t namesrc, namedst;
+ unsigned char namedata[256];
+ isc_sockaddr_t sa;
+ dns_compress_t cctx;
+
+ query = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+ CHECK("dns_message_create", result);
+ result = dns_message_setsig0key(query, key);
+ CHECK("dns_message_setsig0key", result);
+
+ result = dns_message_gettemprdataset(query, &question);
+ CHECK("dns_message_gettemprdataset", result);
+ dns_rdataset_init(question);
+ dns_rdataset_makequestion(question, dns_rdataclass_in,
+ dns_rdatatype_a);
+ result = dns_message_gettempname(query, &qname);
+ CHECK("dns_message_gettempname", result);
+ isc_buffer_init(&namesrc, nametext, strlen(nametext));
+ isc_buffer_add(&namesrc, strlen(nametext));
+ isc_buffer_init(&namedst, namedata, sizeof(namedata));
+ dns_name_init(qname, NULL);
+ result = dns_name_fromtext(qname, &namesrc, dns_rootname, ISC_FALSE,
+ &namedst);
+ CHECK("dns_name_fromtext", result);
+ ISC_LIST_APPEND(qname->list, question, link);
+ dns_message_addname(query, qname, DNS_SECTION_QUESTION);
+
+ isc_buffer_init(&qbuffer, qdata, sizeof(qdata));
+
+ result = dns_compress_init(&cctx, -1, mctx);
+ CHECK("dns_compress_init", result);
+ result = dns_message_renderbegin(query, &cctx, &qbuffer);
+ CHECK("dns_message_renderbegin", result);
+ result = dns_message_rendersection(query, DNS_SECTION_QUESTION, 0);
+ CHECK("dns_message_rendersection(question)", result);
+ result = dns_message_rendersection(query, DNS_SECTION_ANSWER, 0);
+ CHECK("dns_message_rendersection(answer)", result);
+ result = dns_message_rendersection(query, DNS_SECTION_AUTHORITY, 0);
+ CHECK("dns_message_rendersection(auth)", result);
+ result = dns_message_rendersection(query, DNS_SECTION_ADDITIONAL, 0);
+ CHECK("dns_message_rendersection(add)", result);
+ result = dns_message_renderend(query);
+ CHECK("dns_message_renderend", result);
+ dns_compress_invalidate(&cctx);
+
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(query, style, 0, &outbuf);
+ CHECK("dns_message_totext", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+
+ isc_buffer_usedregion(&qbuffer, &r);
+ isc_sockaddr_any(&sa);
+ result = isc_socket_bind(s, &sa, 0);
+ CHECK("isc_socket_bind", result);
+ result = isc_socket_sendto(s, &r, task1, senddone, NULL, &address,
+ NULL);
+ CHECK("isc_socket_sendto", result);
+
+ inr.base = rdata;
+ inr.length = sizeof(rdata);
+ result = isc_socket_recv(s, &inr, 1, task1, recvdone, NULL);
+ CHECK("isc_socket_recv", result);
+ dns_message_destroy(&query);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_boolean_t verbose = ISC_FALSE;
+ isc_socketmgr_t *socketmgr;
+ isc_timermgr_t *timermgr;
+ struct in_addr inaddr;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_buffer_t b;
+ int ch;
+ isc_result_t result;
+ in_port_t port = 53;
+
+ RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ while ((ch = isc_commandline_parse(argc, argv, "vp:")) != -1) {
+ switch (ch) {
+ case 'v':
+ verbose = ISC_TRUE;
+ break;
+ case 'p':
+ port = (unsigned int)atoi(isc_commandline_argument);
+ break;
+ }
+ }
+
+ RUNTIME_CHECK(isc_entropy_create(mctx, &ent) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dst_lib_init(mctx, ent, 0) == ISC_R_SUCCESS);
+
+ dns_result_register();
+ dst_result_register();
+
+ taskmgr = NULL;
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, 2, 0, &taskmgr) ==
+ ISC_R_SUCCESS);
+ task1 = NULL;
+ RUNTIME_CHECK(isc_task_create(taskmgr, 0, &task1) == ISC_R_SUCCESS);
+
+ timermgr = NULL;
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
+ socketmgr = NULL;
+ RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_log_create(mctx, &lctx, &logconfig) == ISC_R_SUCCESS);
+
+ s = NULL;
+ RUNTIME_CHECK(isc_socket_create(socketmgr, PF_INET,
+ isc_sockettype_udp, &s) ==
+ ISC_R_SUCCESS);
+
+ inaddr.s_addr = htonl(INADDR_LOOPBACK);
+ isc_sockaddr_fromin(&address, &inaddr, port);
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ isc_buffer_init(&b, "child.example.", strlen("child.example."));
+ isc_buffer_add(&b, strlen("child.example."));
+ result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ key = NULL;
+ result = dst_key_fromfile(name, 4017, DNS_KEYALG_DSA,
+ DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
+ NULL, mctx, &key);
+ CHECK("dst_key_fromfile", result);
+
+ buildquery();
+
+ (void)isc_app_run();
+
+ isc_task_shutdown(task1);
+ isc_task_detach(&task1);
+ isc_taskmgr_destroy(&taskmgr);
+
+ isc_socket_detach(&s);
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ dst_key_free(&key);
+
+ dst_lib_destroy();
+
+ isc_entropy_detach(&ent);
+
+ isc_log_destroy(&lctx);
+
+ if (verbose)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ DESTROYLOCK(&lock);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/sock_test.c b/bin/tests/sock_test.c
new file mode 100644
index 0000000..c9612f7
--- /dev/null
+++ b/bin/tests/sock_test.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: sock_test.c,v 1.55 2008/07/23 23:27:54 marka Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/task.h>
+#include <isc/socket.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx;
+isc_taskmgr_t *manager;
+
+static void
+my_shutdown(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+
+ printf("shutdown %s (%p)\n", name, task);
+ fflush(stdout);
+ isc_event_free(&event);
+}
+
+static void
+my_send(isc_task_t *task, isc_event_t *event) {
+ isc_socket_t *sock;
+ isc_socketevent_t *dev;
+
+ sock = event->ev_sender;
+ dev = (isc_socketevent_t *)event;
+
+ printf("my_send: %s task %p\n\t(sock %p, base %p, length %d, n %d, "
+ "result %d)\n",
+ (char *)(event->ev_arg), task, sock,
+ dev->region.base, dev->region.length,
+ dev->n, dev->result);
+
+ if (dev->result != ISC_R_SUCCESS) {
+ isc_socket_detach(&sock);
+ isc_task_shutdown(task);
+ }
+
+ isc_mem_put(mctx, dev->region.base, dev->region.length);
+
+ isc_event_free(&event);
+}
+
+static void
+my_recv(isc_task_t *task, isc_event_t *event) {
+ isc_socket_t *sock;
+ isc_socketevent_t *dev;
+ isc_region_t region;
+ char buf[1024];
+ char host[256];
+
+ sock = event->ev_sender;
+ dev = (isc_socketevent_t *)event;
+
+ printf("Socket %s (sock %p, base %p, length %d, n %d, result %d)\n",
+ (char *)(event->ev_arg), sock,
+ dev->region.base, dev->region.length,
+ dev->n, dev->result);
+ if (dev->address.type.sa.sa_family == AF_INET6) {
+ inet_ntop(AF_INET6, &dev->address.type.sin6.sin6_addr,
+ host, sizeof(host));
+ printf("\tFrom: %s port %d\n", host,
+ ntohs(dev->address.type.sin6.sin6_port));
+ } else {
+ inet_ntop(AF_INET, &dev->address.type.sin.sin_addr,
+ host, sizeof(host));
+ printf("\tFrom: %s port %d\n", host,
+ ntohs(dev->address.type.sin.sin_port));
+ }
+
+ if (dev->result != ISC_R_SUCCESS) {
+ isc_socket_detach(&sock);
+
+ isc_mem_put(mctx, dev->region.base,
+ dev->region.length);
+ isc_event_free(&event);
+
+ isc_task_shutdown(task);
+ return;
+ }
+
+ /*
+ * Echo the data back.
+ */
+ if (strcmp(event->ev_arg, "so2") != 0) {
+ region = dev->region;
+ sprintf(buf, "\r\nReceived: %.*s\r\n\r\n",
+ (int)dev->n, (char *)region.base);
+ region.base = isc_mem_get(mctx, strlen(buf) + 1);
+ region.length = strlen(buf) + 1;
+ strcpy((char *)region.base, buf); /* strcpy is safe */
+ isc_socket_send(sock, &region, task, my_send, event->ev_arg);
+ } else {
+ region = dev->region;
+ printf("\r\nReceived: %.*s\r\n\r\n",
+ (int)dev->n, (char *)region.base);
+ }
+
+ isc_socket_recv(sock, &dev->region, 1, task, my_recv, event->ev_arg);
+
+ isc_event_free(&event);
+}
+
+static void
+my_http_get(isc_task_t *task, isc_event_t *event) {
+ isc_socket_t *sock;
+ isc_socketevent_t *dev;
+
+ sock = event->ev_sender;
+ dev = (isc_socketevent_t *)event;
+
+ printf("my_http_get: %s task %p\n\t(sock %p, base %p, length %d, "
+ "n %d, result %d)\n",
+ (char *)(event->ev_arg), task, sock,
+ dev->region.base, dev->region.length,
+ dev->n, dev->result);
+
+ if (dev->result != ISC_R_SUCCESS) {
+ isc_socket_detach(&sock);
+ isc_task_shutdown(task);
+ isc_event_free(&event);
+ return;
+ }
+
+ isc_socket_recv(sock, &dev->region, 1, task, my_recv, event->ev_arg);
+
+ isc_event_free(&event);
+}
+
+static void
+my_connect(isc_task_t *task, isc_event_t *event) {
+ isc_socket_t *sock;
+ isc_socket_connev_t *dev;
+ isc_region_t region;
+ char buf[1024];
+
+ sock = event->ev_sender;
+ dev = (isc_socket_connev_t *)event;
+
+ printf("%s: Connection result: %d\n", (char *)(event->ev_arg),
+ dev->result);
+
+ if (dev->result != ISC_R_SUCCESS) {
+ isc_socket_detach(&sock);
+ isc_event_free(&event);
+ isc_task_shutdown(task);
+ return;
+ }
+
+ /*
+ * Send a GET string, and set up to receive (and just display)
+ * the result.
+ */
+ strcpy(buf, "GET / HTTP/1.1\r\nHost: www.flame.org\r\n"
+ "Connection: Close\r\n\r\n");
+ region.base = isc_mem_get(mctx, strlen(buf) + 1);
+ region.length = strlen(buf) + 1;
+ strcpy((char *)region.base, buf); /* This strcpy is safe. */
+
+ isc_socket_send(sock, &region, task, my_http_get, event->ev_arg);
+
+ isc_event_free(&event);
+}
+
+static void
+my_listen(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+ isc_socket_newconnev_t *dev;
+ isc_region_t region;
+ isc_socket_t *oldsock;
+ isc_task_t *newtask;
+
+ dev = (isc_socket_newconnev_t *)event;
+
+ printf("newcon %s (task %p, oldsock %p, newsock %p, result %d)\n",
+ name, task, event->ev_sender, dev->newsocket, dev->result);
+ fflush(stdout);
+
+ if (dev->result == ISC_R_SUCCESS) {
+ /*
+ * Queue another listen on this socket.
+ */
+ isc_socket_accept(event->ev_sender, task, my_listen,
+ event->ev_arg);
+
+ region.base = isc_mem_get(mctx, 20);
+ region.length = 20;
+
+ /*
+ * Create a new task for this socket, and queue up a
+ * recv on it.
+ */
+ newtask = NULL;
+ RUNTIME_CHECK(isc_task_create(manager, 0, &newtask)
+ == ISC_R_SUCCESS);
+ isc_socket_recv(dev->newsocket, &region, 1,
+ newtask, my_recv, event->ev_arg);
+ isc_task_detach(&newtask);
+ } else {
+ printf("detaching from socket %p\n", event->ev_sender);
+ oldsock = event->ev_sender;
+
+ isc_socket_detach(&oldsock);
+
+ isc_event_free(&event);
+ isc_task_shutdown(task);
+ return;
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+timeout(isc_task_t *task, isc_event_t *event) {
+ isc_socket_t *sock = event->ev_arg;
+
+ printf("Timeout, canceling IO on socket %p (task %p)\n", sock, task);
+
+ isc_socket_cancel(sock, NULL, ISC_SOCKCANCEL_ALL);
+ isc_timer_detach((isc_timer_t **)&event->ev_sender);
+ isc_event_free(&event);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_task_t *t1, *t2;
+ isc_timermgr_t *timgr;
+ isc_time_t expires;
+ isc_interval_t interval;
+ isc_timer_t *ti1;
+ unsigned int workers;
+ isc_socketmgr_t *socketmgr;
+ isc_socket_t *so1, *so2;
+ isc_sockaddr_t sockaddr;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ isc_result_t result;
+ int pf;
+
+ if (argc > 1)
+ workers = atoi(argv[1]);
+ else
+ workers = 2;
+ printf("%d workers\n", workers);
+
+ if (isc_net_probeipv6() == ISC_R_SUCCESS)
+ pf = PF_INET6;
+ else
+ pf = PF_INET;
+
+ /*
+ * EVERYTHING needs a memory context.
+ */
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ /*
+ * The task manager is independent (other than memory context)
+ */
+ manager = NULL;
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &manager) ==
+ ISC_R_SUCCESS);
+
+ /*
+ * Timer manager depends only on the memory context as well.
+ */
+ timgr = NULL;
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timgr) == ISC_R_SUCCESS);
+
+ t1 = NULL;
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t1) == ISC_R_SUCCESS);
+ t2 = NULL;
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t2) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t1, my_shutdown, "1") ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t2, my_shutdown, "2") ==
+ ISC_R_SUCCESS);
+
+ printf("task 1 = %p\n", t1);
+ printf("task 2 = %p\n", t2);
+
+ socketmgr = NULL;
+ RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
+
+ /*
+ * Open up a listener socket.
+ */
+ so1 = NULL;
+
+ if (pf == PF_INET6) {
+ in6a = in6addr_any;
+ isc_sockaddr_fromin6(&sockaddr, &in6a, 5544);
+ } else {
+ ina.s_addr = INADDR_ANY;
+ isc_sockaddr_fromin(&sockaddr, &ina, 5544);
+ }
+ RUNTIME_CHECK(isc_socket_create(socketmgr, pf, isc_sockettype_tcp,
+ &so1) == ISC_R_SUCCESS);
+ result = isc_socket_bind(so1, &sockaddr, ISC_SOCKET_REUSEADDRESS);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_socket_listen(so1, 0) == ISC_R_SUCCESS);
+
+ /*
+ * Queue up the first accept event.
+ */
+ RUNTIME_CHECK(isc_socket_accept(so1, t1, my_listen, "so1")
+ == ISC_R_SUCCESS);
+ isc_time_settoepoch(&expires);
+ isc_interval_set(&interval, 10, 0);
+ ti1 = NULL;
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_once, &expires,
+ &interval, t1, timeout, so1, &ti1) ==
+ ISC_R_SUCCESS);
+
+ /*
+ * Open up a socket that will connect to www.flame.org, port 80.
+ * Why not. :)
+ */
+ so2 = NULL;
+ ina.s_addr = inet_addr("204.152.184.97");
+ if (0 && pf == PF_INET6)
+ isc_sockaddr_v6fromin(&sockaddr, &ina, 80);
+ else
+ isc_sockaddr_fromin(&sockaddr, &ina, 80);
+ RUNTIME_CHECK(isc_socket_create(socketmgr, isc_sockaddr_pf(&sockaddr),
+ isc_sockettype_tcp,
+ &so2) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_socket_connect(so2, &sockaddr, t2,
+ my_connect, "so2") == ISC_R_SUCCESS);
+
+ /*
+ * Detaching these is safe, since the socket will attach to the
+ * task for any outstanding requests.
+ */
+ isc_task_detach(&t1);
+ isc_task_detach(&t2);
+
+ /*
+ * Wait a short while.
+ */
+ sleep(10);
+
+ fprintf(stderr, "Destroying socket manager\n");
+ isc_socketmgr_destroy(&socketmgr);
+
+ fprintf(stderr, "Destroying timer manager\n");
+ isc_timermgr_destroy(&timgr);
+
+ fprintf(stderr, "Destroying task manager\n");
+ isc_taskmgr_destroy(&manager);
+
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/sockaddr/Makefile.in b/bin/tests/sockaddr/Makefile.in
new file mode 100644
index 0000000..f0dbbfb
--- /dev/null
+++ b/bin/tests/sockaddr/Makefile.in
@@ -0,0 +1,55 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-2002 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.21 2007/06/19 23:47:00 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${TEST_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+ISCLIBS = ../../../lib/isc/libisc.@A@
+TAPIDEPLIBS = ../../../lib/tests/libt_api.@A@
+
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+TAPILIBS = ../../../lib/tests/libt_api.@A@
+
+DEPLIBS = ${TAPIDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${TAPILIBS} ${ISCLIBS} @LIBS@
+
+TARGETS = t_sockaddr@EXEEXT@
+
+SRCS = t_sockaddr.c
+
+@BIND9_MAKE_RULES@
+
+t_sockaddr@EXEEXT@: t_sockaddr.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_sockaddr.@O@ ${LIBS}
+
+test: t_sockaddr@EXEEXT@
+ -@./t_sockaddr@EXEEXT@ -b @srcdir@ -a
+
+testhelp:
+ @./t_sockaddr@EXEEXT@ -h
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/sockaddr/t_sockaddr.c b/bin/tests/sockaddr/t_sockaddr.c
new file mode 100644
index 0000000..46003f1
--- /dev/null
+++ b/bin/tests/sockaddr/t_sockaddr.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: t_sockaddr.c,v 1.14 2007/06/19 23:47:00 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/netaddr.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+
+#include <tests/t_api.h>
+
+static int
+test_isc_sockaddr_eqaddrprefix(void) {
+ struct in_addr ina_a;
+ struct in_addr ina_b;
+ struct in_addr ina_c;
+ isc_sockaddr_t isa_a;
+ isc_sockaddr_t isa_b;
+ isc_sockaddr_t isa_c;
+
+ if (inet_pton(AF_INET, "194.100.32.87", &ina_a) < 0)
+ return T_FAIL;
+ if (inet_pton(AF_INET, "194.100.32.80", &ina_b) < 0)
+ return T_FAIL;
+ if (inet_pton(AF_INET, "194.101.32.87", &ina_c) < 0)
+ return T_FAIL;
+ isc_sockaddr_fromin(&isa_a, &ina_a, 0);
+ isc_sockaddr_fromin(&isa_b, &ina_b, 42);
+ isc_sockaddr_fromin(&isa_c, &ina_c, 0);
+
+ if (isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 0) != ISC_TRUE)
+ return T_FAIL;
+ if (isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 29) != ISC_TRUE)
+ return T_FAIL;
+ if (isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 30) != ISC_FALSE)
+ return T_FAIL;
+ if (isc_sockaddr_eqaddrprefix(&isa_a, &isa_b, 32) != ISC_FALSE)
+ return T_FAIL;
+ if (isc_sockaddr_eqaddrprefix(&isa_a, &isa_c, 8) != ISC_TRUE)
+ return T_FAIL;
+ if (isc_sockaddr_eqaddrprefix(&isa_a, &isa_c, 16) != ISC_FALSE)
+ return T_FAIL;
+
+ return T_PASS;
+}
+
+static void
+t1(void) {
+ int result;
+ t_assert("isc_sockaddr_eqaddrprefix", 1, T_REQUIRED,
+ "isc_sockaddr_eqaddrprefix() returns ISC_TRUE when "
+ "prefixes of a and b are equal, and ISC_FALSE when "
+ "they are not equal");
+ result = test_isc_sockaddr_eqaddrprefix();
+ t_result(result);
+}
+
+static int
+test_isc_netaddr_masktoprefixlen(void) {
+ struct in_addr na_a;
+ struct in_addr na_b;
+ struct in_addr na_c;
+ struct in_addr na_d;
+ isc_netaddr_t ina_a;
+ isc_netaddr_t ina_b;
+ isc_netaddr_t ina_c;
+ isc_netaddr_t ina_d;
+ unsigned int plen;
+
+ if (inet_pton(AF_INET, "0.0.0.0", &na_a) < 0)
+ return T_FAIL;
+ if (inet_pton(AF_INET, "255.255.255.254", &na_b) < 0)
+ return T_FAIL;
+ if (inet_pton(AF_INET, "255.255.255.255", &na_c) < 0)
+ return T_FAIL;
+ if (inet_pton(AF_INET, "255.255.255.0", &na_d) < 0)
+ return T_FAIL;
+ isc_netaddr_fromin(&ina_a, &na_a);
+ isc_netaddr_fromin(&ina_b, &na_b);
+ isc_netaddr_fromin(&ina_c, &na_c);
+ isc_netaddr_fromin(&ina_d, &na_d);
+
+ if (isc_netaddr_masktoprefixlen(&ina_a, &plen) != ISC_R_SUCCESS)
+ return T_FAIL;
+ if (plen != 0)
+ return T_FAIL;
+
+ if (isc_netaddr_masktoprefixlen(&ina_b, &plen) != ISC_R_SUCCESS)
+ return T_FAIL;
+ if (plen != 31)
+ return T_FAIL;
+
+ if (isc_netaddr_masktoprefixlen(&ina_c, &plen) != ISC_R_SUCCESS)
+ return T_FAIL;
+ if (plen != 32)
+ return T_FAIL;
+
+ if (isc_netaddr_masktoprefixlen(&ina_d, &plen) != ISC_R_SUCCESS)
+ return T_FAIL;
+ if (plen != 24)
+ return T_FAIL;
+
+ return T_PASS;
+}
+
+static void
+t2(void) {
+ int result;
+ t_assert("isc_netaddr_masktoprefixlen", 1, T_REQUIRED,
+ "isc_netaddr_masktoprefixlen() calculates "
+ "correct prefix lengths ");
+ result = test_isc_netaddr_masktoprefixlen();
+ t_result(result);
+}
+
+testspec_t T_testlist[] = {
+ { t1, "isc_sockaddr_eqaddrprefix" },
+ { t2, "isc_netaddr_masktoprefixlen" },
+ { NULL, NULL }
+};
+
diff --git a/bin/tests/sym_test.c b/bin/tests/sym_test.c
new file mode 100644
index 0000000..0daa498
--- /dev/null
+++ b/bin/tests/sym_test.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: sym_test.c,v 1.28 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/symtab.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx;
+isc_symtab_t *st;
+
+static void
+undefine_action(char *key, unsigned int type, isc_symvalue_t value, void *arg)
+{
+ UNUSED(arg);
+
+ INSIST(type == 1);
+ isc_mem_free(mctx, key);
+ isc_mem_free(mctx, value.as_pointer);
+}
+
+int
+main(int argc, char *argv[]) {
+ char s[1000], *cp, *key;
+ size_t len;
+ isc_result_t result;
+ isc_symvalue_t value;
+ int trace = 0;
+ int c;
+ isc_symexists_t exists_policy = isc_symexists_reject;
+ isc_boolean_t case_sensitive = ISC_FALSE;
+
+ while ((c = isc_commandline_parse(argc, argv, "tarc")) != -1) {
+ switch (c) {
+ case 't':
+ trace = 1;
+ break;
+ case 'a':
+ exists_policy = isc_symexists_add;
+ break;
+ case 'r':
+ exists_policy = isc_symexists_replace;
+ break;
+ case 'c':
+ case_sensitive = ISC_TRUE;
+ break;
+ }
+ }
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_symtab_create(mctx, 691, undefine_action, NULL,
+ case_sensitive, &st) == ISC_R_SUCCESS);
+
+ while (fgets(s, sizeof(s), stdin) != NULL) {
+ len = strlen(s);
+ if (len > 0U && s[len - 1] == '\n') {
+ s[len - 1] = '\0';
+ len--;
+ }
+
+ cp = s;
+
+ if (cp[0] == '!') {
+ cp++;
+ result = isc_symtab_undefine(st, cp, 1);
+ if (trace || result != ISC_R_SUCCESS)
+ printf("undefine('%s'): %s\n", cp,
+ isc_result_totext(result));
+ } else {
+ key = cp;
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+ cp++;
+ if (*cp == '\0') {
+ result = isc_symtab_lookup(st, key, 0, &value);
+ if (trace || result != ISC_R_SUCCESS) {
+ printf("lookup('%s'): %s", key,
+ isc_result_totext(result));
+ if (result == ISC_R_SUCCESS) {
+ cp = value.as_pointer;
+ printf(", value == '%s'", cp);
+ }
+ printf("\n");
+ }
+ } else {
+ *cp++ = '\0';
+ key = isc_mem_strdup(mctx, key);
+ value.as_pointer = isc_mem_strdup(mctx, cp);
+ result = isc_symtab_define(st, key, 1, value,
+ exists_policy);
+ if (trace || result != ISC_R_SUCCESS) {
+ printf("define('%s', '%s'): %s\n",
+ key, cp,
+ isc_result_totext(result));
+ if (result != ISC_R_SUCCESS)
+ undefine_action(key, 1,
+ value, NULL);
+ }
+ }
+ }
+ }
+
+ isc_symtab_destroy(&st);
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/system/Makefile.in b/bin/tests/system/Makefile.in
new file mode 100644
index 0000000..ef8fc58
--- /dev/null
+++ b/bin/tests/system/Makefile.in
@@ -0,0 +1,45 @@
+# Copyright (C) 2004, 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
+# 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.31 2008/09/25 04:02:38 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+SUBDIRS = lwresd tkey
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+# Running the scripts below is bypassed when a separate
+# build directory is used.
+
+check: test
+
+test: subdirs
+ if test -f ./runall.sh; then sh ./runall.sh; fi
+
+testclean clean distclean::
+ if test -f ./cleanall.sh; then sh ./cleanall.sh; fi
+
+distclean::
+ rm -f conf.sh
+
+installdirs:
+
+install::
diff --git a/bin/tests/system/README b/bin/tests/system/README
new file mode 100644
index 0000000..be79650
--- /dev/null
+++ b/bin/tests/system/README
@@ -0,0 +1,54 @@
+Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2000, 2001 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+This is a simple test environment for running bind9 system tests
+involving multiple name servers.
+
+There are multiple test suites, each in a separate subdirectory and
+involving a different DNS setup. They are:
+
+ dnssec/ DNSSEC tests
+ forward/ Forwarding tests
+ glue/ Glue handling tests
+ limits/ Tests of handling of large data (close to server limits)
+ lwresd/ Tests of the lightweight resolver library and daemon
+ notify/ More NOTIFY tests
+ nsupdate/ Dynamic update and IXFR tests
+ resolver/ Regression tests for resolver bugs that have been fixed
+ (not a complete resolver test suite)
+ stub/ Tests of stub zone functionality
+ unknown/ Unknown type and class tests
+ upforwd/ Update forwarding tests
+ views/ Tests of the "views" statement
+ xfer/ Zone transfer tests
+ xferquota/ Zone transfer quota tests
+
+Typically each test suite sets up 2-5 name servers and then performs
+one or more tests against them. Within the test suite subdirectory,
+each name server has a separate subdirectory containing its
+configuration data. By convention, these subdirectories are named
+"ns1", "ns2", etc.
+
+The tests are completely self-contained and do not require access to
+the real DNS. Generally, one of the test servers (ns1) is set up as a
+root name server and is listed in the hints file of the others.
+
+To enable all servers to run on the same machine, they bind to
+separate virtual IP address on the loopback interface. ns1 runs on
+10.53.0.1, ns2 on 10.53.0.2, etc. Before running any tests, you must
+set up these addresses by running "ifconfig.sh up" as root.
+
+The servers use port 5300 instead of the usual port 53, so they can be
+run without root privileges once the interfaces have been set up.
+
+The tests can be run individually like this:
+
+ sh run.sh xfer
+ sh run.sh notify
+ etc.
+
+To run all the tests, just type "make test".
+
+
+$Id: README,v 1.12 2004/03/05 04:59:12 marka Exp $
diff --git a/bin/tests/system/acl/clean.sh b/bin/tests/system/acl/clean.sh
new file mode 100644
index 0000000..80ce516
--- /dev/null
+++ b/bin/tests/system/acl/clean.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) 2008 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: clean.sh,v 1.3 2008/01/10 23:47:01 tbox Exp $
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f dig.out
+rm -f ns2/example.db ns2/tsigzone.db ns2/example.db.jnl ns2/named.conf
+rm -f */named.memstats
diff --git a/bin/tests/system/acl/ns2/named1.conf b/bin/tests/system/acl/ns2/named1.conf
new file mode 100644
index 0000000..b70d1dd
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named1.conf
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2008 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: named1.conf,v 1.2 2008/01/10 01:10:01 marka Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+};
+
+include "../../common/controls.conf";
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ file "tsigzone.db";
+ allow-transfer { !key one; any; };
+};
diff --git a/bin/tests/system/acl/ns2/named2.conf b/bin/tests/system/acl/ns2/named2.conf
new file mode 100644
index 0000000..bcd7e0d
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named2.conf
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 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: named2.conf,v 1.3 2008/01/21 20:38:54 each Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+};
+
+include "../../common/controls.conf";
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ file "tsigzone.db";
+ /*
+ * 0a00::/8 and 10/8 are the same bits, but different address
+ * families. This should *not* match IPv4 queries from 10.*.
+ */
+ allow-transfer { 0a00::/8; !10/8; key one; };
+};
diff --git a/bin/tests/system/acl/ns2/named3.conf b/bin/tests/system/acl/ns2/named3.conf
new file mode 100644
index 0000000..ea2cbcb
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named3.conf
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 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: named3.conf,v 1.2 2008/01/10 01:10:01 marka Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+};
+
+include "../../common/controls.conf";
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key three {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+acl reject {
+ !key one; !key two; any;
+};
+
+acl accept {
+ 10.53.0.1; 10.53.0.2;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ file "tsigzone.db";
+ allow-transfer { !reject; accept; };
+};
diff --git a/bin/tests/system/acl/ns2/named4.conf b/bin/tests/system/acl/ns2/named4.conf
new file mode 100644
index 0000000..99edf7e
--- /dev/null
+++ b/bin/tests/system/acl/ns2/named4.conf
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2008 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: named4.conf,v 1.2 2008/01/10 01:10:01 marka Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+};
+
+include "../../common/controls.conf";
+
+key one {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+key two {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+acl rejectkeys {
+ !key one; !key two; any;
+};
+
+acl rejectaddrs {
+ !10.53.0.1; !10.53.0.2; any;
+};
+
+acl check1 { !key one; 10.53.0.1; };
+
+acl check2 { !key two; 10.53.0.2; };
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ file "tsigzone.db";
+ allow-transfer { !rejectkeys; !rejectaddrs; !check1; !check2; any; };
+};
diff --git a/bin/tests/system/acl/setup.sh b/bin/tests/system/acl/setup.sh
new file mode 100644
index 0000000..9cc07f1
--- /dev/null
+++ b/bin/tests/system/acl/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) 2008 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: setup.sh,v 1.3 2008/01/10 23:47:01 tbox Exp $
+
+sh ../genzone.sh 2 3 >ns2/example.db
+sh ../genzone.sh 2 3 >ns2/tsigzone.db
+cp -f ns2/named1.conf ns2/named.conf
diff --git a/bin/tests/system/acl/tests.sh b/bin/tests/system/acl/tests.sh
new file mode 100644
index 0000000..8d2d564
--- /dev/null
+++ b/bin/tests/system/acl/tests.sh
@@ -0,0 +1,144 @@
+#!/bin/sh
+#
+# Copyright (C) 2008 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: tests.sh,v 1.4 2008/07/19 00:02:14 each Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd"
+
+status=0
+t=0
+
+echo "I:testing basic ACL processing"
+# key "one" should fail
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; }
+
+# any other key should be fine
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; }
+
+cp -f ns2/named2.conf ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
+sleep 5
+
+# prefix 10/8 should fail
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; }
+
+# any other address should work, as long as it sends key "one"
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 127.0.0.1 axfr -y two:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; }
+
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 127.0.0.1 axfr -y one:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; }
+
+echo "I:testing nested ACL processing"
+# all combinations of 10.53.0.{1|2} with key {one|two}, should succeed
+cp -f ns2/named3.conf ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
+sleep 5
+
+# should succeed
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 axfr -y two:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; }
+
+# should succeed
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 axfr -y one:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; }
+
+# should succeed
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; }
+
+# should succeed
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; }
+
+# but only one or the other should fail
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 127.0.0.1 axfr -y one:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; }
+
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 axfr -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $tt failed" ; status=1; }
+
+# and other values? right out
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 127.0.0.1 axfr -y three:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; }
+
+# now we only allow 10.53.0.1 *and* key one, or 10.53.0.2 *and* key two
+cp -f ns2/named4.conf ns2/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
+sleep 5
+
+# should succeed
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 axfr -y two:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; }
+
+# should succeed
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y one:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 && { echo "I:test $t failed" ; status=1; }
+
+# should fail
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.2 axfr -y one:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; }
+
+# should fail
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.1 axfr -y two:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; }
+
+# should fail
+t=`expr $t + 1`
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 -b 10.53.0.3 axfr -y one:1234abcd8765 -p 5300 > dig.out
+grep "^;" dig.out > /dev/null 2>&1 || { echo "I:test $t failed" ; status=1; }
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/cacheclean/clean.sh b/bin/tests/system/cacheclean/clean.sh
new file mode 100644
index 0000000..10388ba
--- /dev/null
+++ b/bin/tests/system/cacheclean/clean.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# 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: clean.sh,v 1.6 2007/09/26 03:22:43 marka Exp $
+
+#
+# Clean up after cache cleaner tests.
+#
+
+rm -f dig.out.ns2
+rm -f */named.memstats
diff --git a/bin/tests/system/cacheclean/dig.batch b/bin/tests/system/cacheclean/dig.batch
new file mode 100644
index 0000000..d185204
--- /dev/null
+++ b/bin/tests/system/cacheclean/dig.batch
@@ -0,0 +1,924 @@
+YA.AKAMAI.com. IN A
+UPR1.UPR.CLU.EDU. IN A
+integra.s-integra.co.JP. IN A
+avalon.iks-jena.de. IN A
+NS1.GLOBALDNS.com. IN A
+NS.RDU.BELLSOUTH.net. IN A
+ns.space.net. IN A
+SUN.MHS-RELAY.AC.UK. IN A
+AYAX.UNIANDES.EDU.CO. IN A
+DNS.NIC.CD. IN A
+NS.DNS.PT. IN A
+NS1.INTERNETSHARE.com. IN A
+MASTER.DNS.BE. IN A
+CATAMOUNT.middlebury.EDU. IN A
+FM03.FM. IN A
+NAAMAK.NCST.ERNET.IN. IN A
+gateway2.BFG.com. IN A
+NS3.NS.ESAT.net. IN A
+DNS1.INTUIT.com. IN A
+DEN-NS2.FWIDCSERVICES.net. IN A
+SOL.UNDPBI.TELEPAC.net. IN A
+NS2.tridog.com. IN A
+DNS2.KW. IN A
+NS2.MAIL.com. IN A
+NS.FIRSTCOM.CL. IN A
+DNS4.QUICKEN.com. IN A
+bofh.cid.net. IN A
+NS1.KRNIC.net. IN A
+NS2.SR.net. IN A
+NS1.TELSTRA.net. IN A
+ns.cafax.SE. IN A
+NS1.DNS.NET.NZ. IN A
+NS.CONCOURSE.com. IN A
+35.32/27.110.16.12.IN-ADDR.ARPA. IN PTR
+CCC.champcable.com. IN A
+NS.RIPE.net. IN A
+NS.NIC.NU. IN A
+KIM.CAMNET.CM. IN A
+DOGON.SOTELMA.net. IN A
+DNS02.FLAME.org. IN A
+NS.MIA.BELLSOUTH.net. IN A
+mail.ok.RU. IN A
+NS.NIC.MX. IN A
+NS2.BERKELEY.EDU. IN A
+SHIKHAR.MOS.COM.NP. IN A
+noc.rrz.Uni-Koeln.de. IN A
+NS.KORNET.net. IN A
+keith.gazpacho.org. IN A
+NS2.appliedtheory.com. IN A
+NS.CERNET.net. IN A
+smtp.ELISTX.com. IN A
+NS-AIT.THNIC.net. IN A
+from.PL. IN A
+mailhub.icann.org. IN A
+SEC1.DNS.UK.PSI.net. IN A
+isrv3-i.isc.org. IN A
+PHLOEM.UOREGON.EDU. IN A
+CTINA.AR. IN A
+DNS2.IAM.NET.MA. IN A
+10.126.39.137.IN-ADDR.ARPA. IN PTR
+DNS.PRINCETON.EDU. IN A
+NS.BELLSOUTH.net. IN A
+NS1.SNS-FELB.DEBIS.com. IN A
+localhost. IN A
+hm6.vt.highmeadow.com. IN A
+SYRUP.hill.com. IN A
+NS99.WAIKATO.AC.NZ. IN A
+NS4.CW.net. IN A
+NS2.SLOWMOE.com. IN A
+ns2.hypa.net. IN A
+ns.sxtyptt.NET.CN. IN A
+NS2.MERCHANTWARE.com. IN A
+uunymdgds1.DOUBLECLICK.net. IN A
+e34.co.us.IBM.com. IN A
+kista.dns.swip.net. IN A
+ZEBRA.UEM.MZ. IN A
+NET2.GENDYN.com. IN A
+NS0.UTK.EDU. IN A
+NS.RELCOM.EU.net. IN A
+DNS0.AXION.BT.CO.UK. IN A
+mail.vhv.com. IN A
+DNS4.UK.MSFT.net. IN A
+NS2.ADNS.net. IN A
+NS1.SEATTLE.US.NETDNS.com. IN A
+NS2.UNIVIE.AC.at. IN A
+NS15B.BOCA15-VERIO.com. IN A
+www.BAYAREA.com. IN CNAME
+ns4.onemain.com. IN A
+NS2.EDIGITALS.com. IN A
+MICHAEL.VATICAN.VA. IN A
+AUSTIN.GH.com. IN A
+sld-ns2.CNNIC.NET.CN. IN A
+NS2.CDC.GOV. IN A
+NS.WATSON.IBM.com. IN A
+NS.NIC.SH. IN A
+NS2.BAHNHOF.net. IN A
+NS-AUTH2.cmates.com. IN A
+ISDMNL.WR.USGS.GOV. IN A
+NS2.COBEX.net. IN A
+MERLE.CIRA.CA. IN A
+NS.UVG.EDU.GT. IN A
+NS1.CWVA.DOUBLECLICK.net. IN A
+eliot.diebold.com. IN A
+NS.ALMADEN.IBM.com. IN A
+NS2.INTERNETSQUARE.com. IN A
+mail.QUEST-NET.com. IN A
+Z1.NS.LHR1.GLOBIX.net. IN A
+DNS1.AVANTEL.NET.MX. IN A
+vh80040.vh8.INFI.net. IN A
+NS.LEB.net. IN A
+NS.DCC.UCHILE.CL. IN A
+CLOUSO.RISQ.QC.CA. IN A
+muenster.westfalen.de. IN A
+us.a1.YIMG.com. IN CNAME
+NS.DEMOS.SU. IN A
+south.NAVPOINT.com. IN A
+netconsult.netconx.de. IN A
+DNS2.btinternet.com. IN A
+NS2.CINE.net. IN A
+castor.cmc.ec.gc.CA. IN A
+EX2-DNS0.AVENUEA.com. IN A
+firewall3.glaxowellcome.com. IN A
+MACU.MA.MT.NP.ELS-GMS.att.net. IN A
+NS.PA. IN A
+TGSERV.TELE.GL. IN A
+KYNSE02.MESSAGESECURE.com. IN A
+GORGON.XTRA.CO.NZ. IN A
+DNS.NIC.IT. IN A
+pop.VERMONTEL.net. IN CNAME
+NS2.REGISTRY.HM. IN A
+NAMESERVER1.CONCENTRIC.net. IN A
+47.131.127.204.IN-ADDR.ARPA. IN PTR
+mailhost.tfm.com. IN A
+NS1.MRC.GM. IN A
+NS.WIDE.AD.JP. IN A
+NS.BTA.NET.CN. IN A
+NS2.ISPC.org. IN A
+BOW.RAIN.FR. IN A
+srs.srs.state.vt.us. IN A
+NS4.WEB2010.com. IN A
+NS.TELECOM.NET.ET. IN A
+NS1.DNS.NET.KH. IN A
+GATEN.JARING.MY. IN A
+shell.nominum.com. IN A
+CHEOPS.ANU.EDU.AU. IN A
+VANGOGH.CS.BERKELEY.EDU. IN A
+NS2.NOC.NULLUS.net. IN A
+NIC.LTH.SE. IN A
+ns.farm.net. IN A
+NS.USEC.SUN.com. IN A
+NS2.YOUR-DOMAIN.com. IN A
+DNS-EAST.PREP.net. IN A
+ns.hcr.net. IN A
+NS-RCH.nortelnetworks.com. IN A
+crl.DEC.com. IN A
+NS.PIXAR.ES. IN A
+MEX1-M-213.UNINET.NET.MX. IN A
+NS.ITU.CH. IN A
+matrix.uwm.EDU.PL. IN A
+gateway1.gmcr.com. IN A
+NS2.DNS.BR. IN A
+foxharp.boston.MA.us. IN MX
+Quest-7.symquest.com. IN A
+NS2.VERIO.net. IN A
+NAME.IAD.GBLX.net. IN A
+NS2.EMIRATES.NET.AE. IN A
+supai.oit.UMASS.EDU. IN A
+QUERN.EPILOGUE.com. IN A
+NS3.TOPICA.com. IN A
+NS1.JERKY.net. IN A
+JTB.BRUNET.BN. IN A
+AUTH100.NS.UU.net. IN A
+BOW.INTNET.DJ. IN A
+OSI2.GUA.net. IN A
+AZMODAN.ULA.VE. IN A
+THUMPER.RPSLMC.EDU. IN A
+ICHU.RCP.NET.PE. IN A
+NS.NIC.AC. IN A
+DNS.NETFLIGHT.com. IN A
+ns2.UTORONTO.CA. IN A
+mail.giffordmed.org. IN A
+RATA.VUW.AC.NZ. IN A
+NS-2.ADMONITOR.net. IN A
+NCC.MOC.KW. IN A
+NS.EUNET.ES. IN A
+NS3.best.com. IN A
+zip.MAIL-LIST.com. IN MX
+JATZ.AARNET.EDU.AU. IN A
+DNS2.MAN.LODZ.PL. IN A
+NS.VERITAS.com. IN A
+218.241.103.199.IN-ADDR.ARPA. IN PTR
+BOW.SNPT.KM. IN A
+Z1.NS.SJC1.GLOBIX.net. IN A
+DNS.NIC.TT. IN A
+MAKISIG.IPHIL.net. IN A
+NS.DK.net. IN A
+NS.NI. IN A
+CIUP1.NCC.UP.PT. IN A
+ns2.verisign-grs.com. IN A
+NS1.UMASS.EDU. IN A
+NS.NEWACCOUNT.net. IN A
+UDNS2.ULTRADNS.net. IN A
+NS2.LATNET.LV. IN A
+info-server.surrey.AC.UK. IN A
+NS2.SQUONK.net. IN A
+NS2.DSO.net. IN A
+www.energyenhancement.org. IN A
+DNS1.BD. IN A
+nl.COMPUWARE.com. IN MX
+NS.DHIRAAGU.MV. IN A
+TRANTOR.UMD.EDU. IN A
+NS.ALCANET.NO. IN A
+Z6.MSFT.AKADNS.com. IN A
+NS4.ync.net. IN A
+CMTU.MT.NS.ELS-GMS.att.net. IN A
+vh40099.vh4.INFI.net. IN A
+ns2.secondary.nl. IN A
+abyssinian.sleepycat.com. IN A
+APHEX.MENTOR.BE. IN A
+webmail.fiberia.com. IN A
+localhost.moonmothers.com. IN A
+NS2.DNS.LU. IN A
+NS.VISUALCOM.ES. IN A
+TONIC.TO. IN A
+NS1.CRSNIC.net. IN A
+trurl.ispid.com.PL. IN A
+datingagentur.de. IN A
+NS2.NSIREGISTRY.net. IN A
+ICE.VIA-NET-WORKS.IE. IN A
+sgi1.map.com. IN A
+NS0.HS0.U-NET.net. IN A
+candle.pha.pa.us. IN A
+NS1.PACIFIC.NET.SG. IN A
+NS.CENIAI.NET.CU. IN A
+NS2.UUCP.NE.JP. IN A
+za.akamaitech.net. IN A
+NS.UCR.AC.CR. IN A
+DNS-02.NS.cs.com. IN A
+dns2.primary.net. IN A
+PAPPSRV.PAPP.UNDP.org. IN A
+NS1.REGME.com. IN A
+DNS.CS.KULEUVEN.AC.BE. IN A
+NS1.VERMONTLAW.net. IN A
+mail.garmontusa.com. IN A
+NS2.SAIPAN.com. IN A
+NS.ARICATRA.com. IN A
+ns2.reedmedia.net. IN A
+NS.NETLAB.SK. IN A
+RELAY.GW.tislabs.com. IN A
+b.ns.tmcs.net. IN A
+NS1.IBL.BM. IN A
+ok.RU. IN A
+NS.RICC.ALMA-ATA.SU. IN A
+KITKA.MARNET.MK. IN A
+dasher.dartmouth.EDU. IN A
+NS0.PLANET-THREE.com. IN A
+KNOCK.SER.BBNPLANET.net. IN A
+tornado.webtech.elk.PL. IN A
+AUTH2.NS.IDT.net. IN A
+host3.VTLEGALAID.org. IN A
+NS.EUNET.SK. IN A
+TULKU.NIC.AR. IN A
+RELAY.CDNNET.CA. IN A
+DNS2.TPSA.PL. IN A
+enterprise.wirbel.com. IN A
+ECNET.EC. IN A
+ENGINE1.UNA.net. IN A
+WYCU.WY.BR.NP.ELS-GMS.att.net. IN A
+ARWENA.NASK.WAW.PL. IN A
+PAC2.NIPR.MIL. IN A
+DAISY.EE.UND.AC.ZA. IN A
+odin.ietf.org. IN A
+dns.kaben-net.de. IN A
+NS2.ALTAVISTA.com. IN A
+CASTOR.TELEGLOBE.net. IN A
+CIR.RED.SV. IN A
+PIJIN.COM.SB. IN A
+NS4.CTCCOM.net. IN A
+NS1.SOL.NO. IN A
+DNS2.TK.MSFT.net. IN A
+NS.BSDI.com. IN A
+NS.SVIANED.nl. IN A
+NS.NOVELL.com. IN A
+NS.LUCKY.net. IN A
+SJC-NS2.SJC.LYCOS.com. IN A
+NS1.OP.net. IN A
+worldnet.att.net. IN A
+APIES.FRD.AC.ZA. IN A
+mail.skiinsurance.com. IN A
+NS.BELNET.BE. IN A
+KOMO.INET.GA. IN A
+EARTH.THEPLANET.net. IN A
+VASCO.USMA.AC.PA. IN A
+GODFEVER.DCCSERVER.com. IN A
+BOS-NS2.BOS.LYCOS.com. IN A
+NS2.GOTO.com. IN A
+NS1.overstock.com. IN A
+NS1-PUBLIC.ZMA.COMPAQ.com. IN A
+ns.ilovedomain.com. IN A
+ns1.anycast.net. IN A
+PASCAL.UPRR.PR. IN A
+NS3-AUTH.SPRINTLINK.net. IN A
+NS1-Y.DNS.PIPEX.net. IN A
+prue.eim.surrey.AC.UK. IN A
+TROLL-GW.GATECH.EDU. IN A
+NS.SIERRATEL.SL. IN A
+ns2.PSHIFT.com. IN A
+NS.ERS.IBM.com. IN A
+ASLAN.OPEN-RSC.org. IN A
+NS2.DOMAIN-REGISTRY.nl. IN A
+uranus.lan-ks.de. IN A
+mail.unlisys.net. IN A
+NS.AUSTRIA.EU.net. IN A
+AUTH01.CONNECT.IE. IN A
+SUN.SCSI.GOV.BY. IN A
+NS1.SIGMAHOSTING.com. IN A
+NS.CAST.EDU.JM. IN A
+DS.NIC.NET.SG. IN A
+PRADES.CESCA.ES. IN A
+ns.sta.NET.CN. IN A
+NSE00.excite.com. IN A
+NS3.ABOVE.net. IN A
+CASBAH.ELDJAZAIR.NET.DZ. IN A
+ASKIA.SOTELMA.ML. IN A
+NS.IDT.net. IN A
+FXCLPR02.IS.CHRYSLER.com. IN A
+SVC00.APNIC.net. IN A
+NS5.DCX.YAHOO.com. IN A
+ns1.ray.net. IN A
+NS.NIC.MC. IN A
+ns.runway.CN.net. IN A
+benoni.uit.NO. IN A
+SCRATCHY.MINDSPRING.net. IN A
+ns1.pcode.com. IN A
+ns1.aha.RU. IN A
+ns2.uwaterloo.CA. IN A
+ns2.NIC.AD.JP. IN A
+a.ns.foxharp.boston.MA.us. IN A
+NS.NIC.IO. IN A
+A-GTLD-SERVERS.dot-god.com. IN A
+SMTP.slac.stanford.EDU. IN A
+52.87.198.209.IN-ADDR.ARPA. IN PTR
+BARNEY.ADVSYS.CO.UK. IN A
+NS1.TELEPAC.PT. IN A
+NICOSIA.CCS.UCY.AC.CY. IN A
+NS.PUNCHDOWN.org. IN A
+SYNAESTHESIA.COGNOSCENTI.org. IN A
+NS2.PLANET-THREE.net. IN A
+DNS.CIT.CORNELL.EDU. IN A
+MODOR.VERISIGN.net. IN A
+SUNSTROKE.IS.RPSLMC.EDU. IN A
+NS2.SEG.net. IN A
+NEMUNAS.SC-UNI.KTU.LT. IN A
+MULGA.CS.MU.OZ.AU. IN A
+NS1.NPLUS.GF. IN A
+ns2.centralinfo.net. IN A
+K.GTLD-SERVERS.net. IN A
+ns1.codelocal.com. IN A
+NS2.IPNS.com. IN A
+NS0.DE.NIC.NU. IN A
+NS.USSR.EU.net. IN A
+NS.INTERNET.SK. IN A
+CORREOS.SEKER.ES. IN A
+mx1.buf.ADELPHIA.net. IN A
+aun.UNINETT.NO. IN A
+NS0.NETANET.com. IN A
+www.MANY-PATHS-ENERGY-ENHANCEMENT.com. IN A
+NS2.STARFIRE.DOUGLAS.MA.us. IN A
+NS3.IKP.PL. IN A
+pns.dtag.de. IN A
+NZ.NS.NIC.NU. IN A
+DAVER.bungi.com. IN A
+gutenberg.bucksnet.com. IN A
+DNS2.IT.net. IN A
+NS2.SNS-UT.DEBIS.com. IN A
+ISI.EDU. IN A
+amethyst.xaos.org. IN A
+PAPPILLOMA.WWEBSVS.com. IN A
+NS2.bock.com. IN A
+NS2.OAR.net. IN A
+MINION.NETPOLICY.com. IN A
+Mail.catic1.com. IN A
+NS4.DNS.space.net. IN A
+b.gtld-servers.ORSC. IN A
+bend.madriver.com. IN A
+NS4.IS-FUN.net. IN A
+NS2.JPS.net. IN A
+NS1.IP-PLUS.net. IN A
+rush.cc1.RPSLMC.EDU. IN A
+NS2.GBMTECH.net. IN A
+DNS.MSEN.com. IN A
+DNSSEC2.SINGNET.COM.SG. IN A
+NS2.HOME.net. IN A
+ACCESS.MBNET.MB.CA. IN A
+DNS0.SPIN.AD.JP. IN A
+Filer.PHOTOTRUST.com. IN A
+jpl.NASA.GOV. IN A
+NS2.TECHNOLOGIA.net. IN A
+bparker.CONNACTIVITY.com. IN A
+NS1.uvm.EDU. IN A
+NS.SENET.net. IN A
+DNS2.UTCC.UTORONTO.CA. IN A
+localhost.costorf.com. IN A
+DNS2.AD. IN A
+HYDRA.HELSINKI.FI. IN A
+NAME.PHX.GBLX.net. IN A
+NS2.FOOL.com. IN A
+NS01-SERVER.CURINFO.AN. IN A
+NS.CR. IN A
+mail.pshift.net. IN A
+NS.IRD.FR. IN A
+NS.UZ. IN A
+DNS.INTELCOM.SM. IN A
+DNS2.UNIV-NKC.MR. IN A
+HNS3.hns.com. IN A
+bay.cs.UTORONTO.CA. IN A
+NS0.BT.net. IN A
+BAYONET.SJMERCURY.com. IN A
+PAN.BIJT.net. IN A
+NAVI.SUBTEND.net. IN A
+NS.CIX.CX. IN A
+waldorf.Informatik.Uni-Dortmund.de. IN A
+NS2.ivillage.com. IN A
+DNS.NIC.XLINK.net. IN A
+NS1.MERCHANTWARE.CON. IN A
+NS.TO.GD-ES.com. IN A
+NS-A.RNC.RO. IN A
+REGGAE.NCREN.net. IN A
+SSS-NL.DENIC.de. IN A
+NS1.TDC.TO. IN A
+NS.NIC.HU. IN A
+JOANNA.WILLIAM.org. IN A
+NS0.IIJ.AD.JP. IN A
+maus.spack.org. IN A
+B.NS.VERIO.net. IN A
+SECDNS.EUNET.BE. IN A
+NS3.EUROPE.YAHOO.com. IN A
+A.ROOT-SERVERS.net. IN A
+sherickpm.com. IN MX
+NS2.MEDIASERVICES.net. IN A
+YARDBIRD.CNS.vt.EDU. IN A
+SUNIC.SUNET.SE. IN A
+NS.MT. IN A
+CNDVG001.usa.net. IN A
+NS1.CX.ESCROW.IOCOMM.NET.CX. IN A
+DNS-02.NS.AOL.com. IN A
+ns2.tesserae.com. IN A
+SV10.BATELCO.COM.BH. IN A
+dec.anr.state.vt.us. IN MX
+3.133.188.192.IN-ADDR.ARPA. IN PTR
+NS1.LONDON.UK.NETDNS.com. IN A
+NS.NIC.MG. IN A
+DNS1.VN. IN A
+DENS20.DEN.nps.GOV. IN A
+z.ip6.INT. IN A
+NS3.TRIVALLEY.com. IN A
+isis.imag.FR. IN A
+NS.SOVAM.com. IN A
+NS-SOA.DARENET.DK. IN A
+NS4.NIC.TV. IN A
+DNSSRV1X.mitre.org. IN A
+GATEKEEPER.NYTIMES.com. IN A
+D.I-DNS.net. IN A
+NS.KOLO.net. IN A
+NS4.FIRSTWORLD.net. IN A
+DECST.CERIST.DZ. IN A
+NS4.DNS.WS. IN A
+NS0.GDGSC.com. IN A
+UCTHPX.UCT.AC.ZA. IN A
+NS2.HOTWIRED.com. IN A
+ns02.ca.us.ibm.net. IN A
+NS2.SPEAKEASY.net. IN A
+TELCOM.ZPTC.CO.ZW. IN A
+NS.DK-HOSTMASTER.DK. IN A
+NS.NIC.LK. IN A
+NS2.zama.net. IN A
+CZ.EUNET.CZ. IN A
+NS.AC.ID. IN A
+NS1.CUBE.de. IN A
+NS1.QUASAR.net. IN A
+NS1.OFFSHORE.AI. IN A
+NS5.NRSITE.com. IN A
+NS.AIC.net. IN A
+OWL.NCC.nps.GOV. IN A
+MAXIM.gbch.net. IN A
+BOW.INTNET.TD. IN A
+ns1.cacheware.com. IN A
+NS2.SPEEDHOST.com. IN A
+NS1.COMMIT.GM. IN A
+NAME.ROC.GBLX.net. IN A
+90.198.245.204.IN-ADDR.ARPA. IN PTR
+BOLOGNA.NETTUNO.IT. IN A
+NIC.IBD.com. IN A
+NS.WESTOL.com. IN A
+time.SOVER.net. IN CNAME
+UNIX1.CS.UMASS.EDU. IN A
+AARDVARK.WR.UMIST.AC.UK. IN A
+NS1.NIC.YU. IN A
+mail.velco.com. IN A
+DNSAUTH2.SYS.GTEI.net. IN A
+NS.TELE.FI. IN A
+state.vt.us. IN MX
+NS.NYC.juno.com. IN A
+NS1.g-world.com. IN A
+AUTH2.AMERICA.net. IN A
+KIRA.ECS.UMASS.EDU. IN A
+CONACYT.GOB.SV. IN A
+DNS.SRCE.HR. IN A
+NS00.ns0.com. IN A
+NS2.CL.BELLSOUTH.net. IN A
+jenner.med.HARVARD.EDU. IN A
+p2.cavebear.com. IN A
+NS1.NIC.JE. IN A
+ORCU.OR.BR.NP.ELS-GMS.att.net. IN A
+NS.XBILL.org. IN A
+WRAITH.CS.UOW.EDU.AU. IN A
+12.159.145.204.IN-ADDR.ARPA. IN PTR
+ns1.pr.SUN.com. IN A
+NS.SPIN.OMNES.net. IN A
+smtp.188.net. IN A
+TERMINAL.2GLOBE.net. IN A
+NS2.HARVARD.EDU. IN A
+NAMESERVER.CNR.IT. IN A
+EARTH.SY. IN A
+DNS2.REACCIUN.VE. IN A
+NS.TMX.COM.NI. IN A
+freefour.acs.rpi.EDU. IN A
+242.84.198.209.IN-ADDR.ARPA. IN PTR
+CORREU.STA.AD. IN A
+NS.DRUKNET.NET.BT. IN A
+NS4.US.PRSERV.net. IN A
+KAASASSUK.GH.GL. IN A
+ECUA.NET.EC. IN A
+NS.CONCYT.GOB.GT. IN A
+NS2.NAP.net. IN A
+DNS2.CN.net. IN A
+MX.NSI.NASA.GOV. IN A
+NS.TDS.net. IN A
+tdns-me1.NETSCAPE.com. IN A
+NS2.METU.EDU.TR. IN A
+NS2.SETARNET.AW. IN A
+87.184.152.204.IN-ADDR.ARPA. IN PTR
+DNS.OMNIWAY.SM. IN A
+NS0.U-NET.net. IN A
+elektro.CMHNET.org. IN A
+ns2.HIGGS.net. IN A
+NS2.SKYNETWEB.com. IN A
+MAGIC.MN. IN A
+NS1.YAHOO.com. IN A
+mx1.cdp.ADELPHIA.net. IN A
+SANTO.VANUATU.COM.VU. IN A
+www.mmuuf.org. IN MX
+ns1.timeheart.net. IN A
+NS2.TOGETHER.net. IN A
+NS.AMNIC.net. IN A
+NS.EENET.EE. IN A
+www.ONLINEPHOTOCONTEST.com. IN A
+VIC20.BLIPP.com. IN A
+DNS.FROGHOUSE.org. IN A
+NS2.ELI.net. IN A
+NS.CAIS.com. IN A
+BAABEN.AFRIQ.net. IN A
+NS2.NJ.EXODUS.net. IN A
+DOMREG.NIC.CH. IN A
+NS.EU.net. IN A
+NS1.DIEBOLD.net. IN A
+NS3.CP.net. IN A
+DNS.FUW.EDU.PL. IN A
+www.retro.com. IN A
+NS2.UNI2.net. IN A
+ns1.alcatrazmedia.com. IN A
+dns6.CP.MSFT.net. IN A
+NS1.SEYCHELLES.net. IN A
+NS2.INTERNIC.net. IN A
+front.macrosoft.WAW.PL. IN A
+NISC.JVNC.net. IN A
+AUTH03.NS.DE.UU.net. IN A
+BURDELL.CC.GATECH.EDU. IN A
+NS4.AH.net. IN A
+ns1.sgh-net.de. IN A
+Leland2.stanford.EDU. IN A
+CBRU.BR.NS.ELS-GMS.att.net. IN A
+DENEB.DOMAINNT.net. IN A
+ns1.ivm.net. IN A
+NS0.CWCI.net. IN A
+35.110.16.12.IN-ADDR.ARPA. IN CNAME
+f.trns. IN A
+ODISEJ.TELEKOM.YU. IN A
+FRCU.EUN.EG. IN A
+NS.HHS.net. IN A
+FOO.GRNET.GR. IN A
+mail.WonderWorks.com. IN A
+NS1.IAFRICA.com. IN A
+NS.KACST.EDU.SA. IN A
+srs.state.vt.us. IN A
+OM4.OMANTEL.NET.OM. IN A
+Yeshua.Christ.com. IN A
+NS1.SIMORGH.com. IN A
+OLKETA.SOLOMON.COM.SB. IN A
+BANBA.DOMAINREGISTRY.IE. IN A
+NOC.IOS.com. IN A
+ns.schnism.net. IN A
+e4.ny.us.IBM.com. IN A
+DNS2.SEANET.com. IN A
+doubt.dd.org. IN A
+AMBER.ELEKTRON.PL. IN A
+gw.rge.com. IN A
+NS2.ZTNET.com. IN A
+NS3.INFI.net. IN A
+ZA.AKADNS.net. IN A
+ESTIA.CSI.FORTH.GR. IN A
+vtagr04.agr.state.vt.us. IN A
+NS1-PUBLIC.ZTX.COMPAQ.com. IN A
+ADMII.ARL.MIL. IN A
+NS.NIXU.FI. IN A
+DNS2.PIONEERNET.net. IN A
+NS.NIC.CL. IN A
+NS2.UTZ. IN A
+NS4.LUXNOC.com. IN A
+NS2.PBI.net. IN A
+annwfn.erfurt.thur.de. IN A
+NS1.MW.mediaone.net. IN A
+NS1.ISU.NET.SA. IN A
+pop.SHOREHAM.net. IN CNAME
+DNS2.GUERNSEY.net. IN A
+NS1.BEACHSHORE.net. IN A
+HKUXB.HKU.HK. IN A
+NS.DOLEH.com. IN A
+NS.hactrn.net. IN A
+MALAKULA.BONDY.IRD.FR. IN A
+NS1.mediaone.net. IN A
+NS2.GPG.com. IN A
+noc.BelWue.de. IN A
+NS2.GIP.net. IN A
+RS.ISLES.net. IN A
+BOW.INTNET.GQ. IN A
+A.OPEN.BY. IN A
+us.i1.YIMG.com. IN CNAME
+athome.wetlogic.net. IN CNAME
+NS1.NIST.GOV. IN A
+mail.jerusalem-mail.com. IN A
+ISDSUN.cr.USGS.GOV. IN A
+NS.BOSTON.juno.com. IN A
+NS2.CADABRA.com. IN A
+nps.GOV. IN MX
+RELAY.HUJI.AC.IL. IN A
+styx.tahina.priv.at. IN A
+ISGATE.IS. IN A
+ns0.lux.dot-eu.org. IN A
+BILBO.NASK.ORG.PL. IN A
+MAIL.TARSUS.com. IN A
+SUN.REDIRIS.ES. IN A
+NS2.NEASE.net. IN A
+OHCU.OH.MT.NP.ELS-GMS.att.net. IN A
+NS2.NF. IN A
+MIRAF-SERVER3.HONDUTEL.HN. IN A
+ns3.worldnet.att.net. IN A
+NS2.NETNAMES.net. IN A
+ITGBOX.IAT.CNR.IT. IN A
+NS2.ADELPHIA.net. IN A
+NS2.RIPN.net. IN A
+NS1.cinenet.net. IN A
+jengate.thur.de. IN A
+NOC.ULCC.JA.net. IN A
+NS.NOC.UZ. IN A
+NS0.JA.net. IN A
+NS2.INR.net. IN A
+netsage.org. IN A
+TERI.USP.AC.FJ. IN A
+NS2.NETSOL.com. IN A
+NS2.ABAC.com. IN A
+NS2.NIC.FR. IN A
+KANIN.ARNES.SI. IN A
+NS.EDU.GU. IN A
+DNS.INRIA.FR. IN A
+HEDNS1.GOOGLE.com. IN A
+asylum.sf.ca.us. IN A
+ACT2.ACT2000.net. IN A
+ICM1.ICP.net. IN A
+202.192.103.198.209.IN-ADDR.ARPA. IN PTR
+ECSEL.jhuapl.EDU. IN A
+NS2.DCNY.DOUBLECLICK.net. IN A
+keith.netsage.org. IN A
+MANTA.OUTREMER.com. IN A
+NS2.globalnetisp.net. IN A
+NS2.CCSRS.net. IN A
+NS1.NL.CONCENTRIC.com. IN A
+NS2.VI.net. IN A
+NS2.NEO.net. IN A
+cgi.MERCURYCENTER.com. IN CNAME
+ORSTOM.RIO.net. IN A
+NS2.CONRADPROMOTIONS.com. IN A
+YARRINA.CONNECT.COM.AU. IN A
+dns03.OPS.usa.net. IN A
+APPSRV.HAITIWORLD.com. IN A
+NS.RELCOM.KZ. IN A
+NS1.MAGIC-MOMENTS.com. IN A
+NS.ALCATEL.com. IN A
+ns2.terra.net. IN A
+NS3.hotmail.com. IN A
+vtc.VSC.EDU. IN MX
+www.vmba.org. IN MX
+NAHOURI.ONATEL.BF. IN A
+SERVER2.INFN.IT. IN A
+NS2.AI-R.com. IN A
+NS1.FREE.net. IN A
+vcmr-54.server.rpi.EDU. IN A
+haig.CS.UCL.AC.UK. IN A
+mail.nova-data.com. IN A
+MOEVAX.EDU.TW. IN A
+NS2.LTWCC.org. IN A
+NS.BA. IN A
+noc.HRZ.uni-bielefeld.de. IN A
+VANILLA.WRO.nps.GOV. IN A
+NS2.SZTAKI.HU. IN A
+SECIU.EDU.UY. IN A
+COL2.CARIBSURF.com. IN A
+NS2.QATAR.NET.QA. IN A
+NS2.E-SYNC.net. IN A
+ns1.eu.SUN.com. IN A
+NS1.UUSJ.DOUBLECLICK.net. IN A
+NS2.CUHK.EDU.HK. IN A
+NS1.MEITCA.com. IN A
+NS2.DSL.net. IN A
+techfac.techfak.uni-bielefeld.de. IN A
+listserv.performancediver.com. IN A
+foolusmf.D4P.net. IN CNAME
+pedic-med.vrx.net. IN A
+GRUMPY.NET.NA. IN A
+BK.tifosi.com. IN A
+ns3.PAIR.com. IN A
+ns2.ar.com. IN A
+MASSIRA.ONPT.NET.MA. IN A
+NS.KBFI.EE. IN A
+ns3.Algebra.com. IN A
+faerber.muc.de. IN MX
+9.206.203.192.IN-ADDR.ARPA. IN PTR
+PUKU.UNZA.ZM. IN A
+ATLNET.ATLONLINE.com. IN A
+Z1.NS.NYC1.GLOBIX.net. IN A
+www.hometownbands.com. IN A
+SIMON.CS.CORNELL.EDU. IN A
+EKEKO.RCPIP.net. IN A
+emerald.itnet.com.PL. IN A
+DNS1.ICS.FORTH.GR. IN A
+NS.ATL.BELLSOUTH.net. IN A
+ntp.ctr.COLUMBIA.EDU. IN CNAME
+NS2.GLOBECOMM.net. IN A
+UUNS1DNS1.FLONETWORK.com. IN A
+GRIN.GNOSH.net. IN A
+NS.DIGSYS.BG. IN A
+uunet.UU.net. IN MX
+ns1.vermontel.com. IN A
+NS2.GREENMOUNTAINACCESS.net. IN A
+38.241.5.198.IN-ADDR.ARPA. IN PTR
+NS1.NIC.UK. IN A
+DNS.FCCN.PT. IN A
+NS2.NIC.TJ. IN A
+NS4.NEWACCOUNT.com. IN A
+NS2.IHUG.NET.NZ. IN A
+NS.SIGNALZ.com. IN A
+DNS.NIC.AD. IN A
+3.2.39.137.IN-ADDR.ARPA. IN PTR
+UUCP-GW-2.PA.DEC.com. IN A
+NS.LANDLORDS.com. IN A
+NS2.EXODUS.net. IN A
+NS2.SCRUZ.net. IN A
+NS.PIPEX-SZ.net. IN A
+saturn.SUN.com. IN A
+e24.nc.us.IBM.com. IN A
+NMS.CYFRONET.KRAKOW.PL. IN A
+NS.TWNIC.net. IN A
+ns2.alcatel.NO. IN A
+INPAKSODNS.AKSO.nps.GOV. IN A
+mail.reptiles.org. IN A
+59.187.152.204.IN-ADDR.ARPA. IN PTR
+ns1.mobydark.com. IN A
+NS.KG. IN A
+NS.SPB.SU. IN A
+PENDRAGON.CS.PURDUE.EDU. IN A
+NS1.IGC.APC.org. IN A
+USDNS.NIC.us. IN A
+NS2.WEBTRENDS.com. IN A
+URANUS.DAIMI.AAU.DK. IN A
+ANTANA.IRD.MG. IN A
+NS.JERSEY.juno.com. IN A
+NS2.INTERNET-TOOLS.com. IN A
+ns-tk012.ocn.AD.JP. IN A
+bvt-ext.gdarm.com. IN A
+NS1.ID. IN A
+NS2.MAHNET.net. IN A
+NS.ALCANET.COM.AU. IN A
+UTAMA.BOLNET.BO. IN A
+NS.CNC.AC.CN. IN A
+NS.KREN.NE.KR. IN A
+NS1.REDHAT.com. IN A
+db.rc.VIX.com. IN A
+198.103.198.209.IN-ADDR.ARPA. IN CNAME
+alf.pbks.PL. IN A
+FLAG.EP.net. IN A
+DNS2.IUNET.IT. IN A
+NS2.QUANTIFIED.net. IN A
+INTERNET-SERVER.ZURICH.IBM.com. IN A
+seaipsvcs.idx.com. IN A
+lebanon.valley.net. IN A
+SERVER.NORDU.net. IN A
+NS.NIC.DO. IN A
+isc-01.iscvt.org. IN A
+NAC.NO. IN A
+SAVA.UTIC.NET.BA. IN A
+NS1.TOKYO.JP.NETDNS.com. IN A
+NETSERV2.ITS.rpi.EDU. IN A
+IFI.UIO.NO. IN A
+www.TOAPLAN.com. IN A
+ns2.the-frontier.org. IN A
+NS.UNAM.MX. IN A
+ARISTO.TAU.AC.IL. IN A
+DNS.CS.WISC.EDU. IN A
+NS1.NIC.IR. IN A
+NS1.RETINA.AR. IN A
+mailer.connriver.net. IN A
+NS.ATI.TN. IN A
+NS2.CLEAR.NET.NZ. IN A
+NS4.EARTHLINK.net. IN A
+mejac.palo-alto.ca.us. IN A
+New-York4.NY.ALTER.net. IN A
+falcon.tallship.net. IN A
+ZEUS.CC.UCY.AC.CY. IN A
+NS2.SECURE.net. IN A
+NS0.FLIRBLE.org. IN A
+dns.zenon.net. IN A
+SERVIDOR.MICROASTUR.ES. IN A
+DOWNSTAGE.MCS.VUW.AC.NZ. IN A
+ns2.GNAC.com. IN A
+PRIFI.EUNET.FI. IN A
+ns2.k12.vt.us. IN A
+ns2.nic.mnet. IN A
+NS0.PIPEX.net. IN A
+NS1.SANFRANCISCO.US.NETDNS.com. IN A
+AMRA.NIC.GOV.JO. IN A
+kw.com.CN. IN MX
+SHNS.163.net. IN A
+NS.ER.USGS.GOV. IN A
+FAITH.MYNET.net. IN A
+mail.smuggs.com. IN A
+MIMOS.MY. IN A
+NS.GU. IN A
+mx00.schlund.de. IN A
+CADDSYS.IPTEK.net. IN A
+NS0.TELIA.NIC.NU. IN A
+NS2.GRANITECANYON.com. IN A
+GATEKEEPER.corning.com. IN A
+NS2.2DAY.com. IN A
+1.0.0.127.IN-ADDR.ARPA. IN PTR
+RAIN.PSG.com. IN A
+STRAWB.MIT.EDU. IN A
+NS2.DIGISERVE.com. IN A
+UMACSN2.UMAC.MO. IN A
+NS.JM. IN A
+12.153.66.206.IN-ADDR.ARPA. IN PTR
+EAST.ISI.EDU. IN A
+NS2.UUNET.CA. IN A
+SUNNY.STAT-USA.GOV. IN A
+BOW.INTNET.CF. IN A
+NS4.TELE.DK. IN A
+NS2.sodak.net. IN A
+NS1.NEWYORK.US.NETDNS.com. IN A
+NS2.PSI.net. IN A
+NS.KREONET.RE.KR. IN A
+GIANT.MINDLINK.net. IN A
+NS0.SECTOR001.org. IN A
+DNS.SEABONE.net. IN A
+NS2.MANA.PF. IN A
+NRWEB.CENPAC.NET.NR. IN A
+www.TRAVELPHOTOCONTESTS.com. IN A
+NS1.REGEX.com. IN A
+BIGBIRD.ITD.nps.GOV. IN A
+CUNIXD.CC.COLUMBIA.EDU. IN A
+NS1.CLASSIFIEDMONSTER.com. IN A
+SERVER1.SANS.org. IN A
+BRONZE.COIL.com. IN A
+SCSNMS.SWITCH.CH. IN A
+SCE.CNC.UNA.PY. IN A
+RELAY.LA.TIS.com. IN A
+NS.AUSTIN.IBM.com. IN A
+SERVICE.robert-morris.EDU. IN A
+MERCURY.ML.org. IN A
+proxy.pccf.net. IN A
+DUB-NAME-SVC-1.compuserve.com. IN A
+NS.CNRI.reston.va.us. IN A
+NS.UCAD.SN. IN A
+ns01.ny.us.ibm.net. IN A
+NS4-AUTH.ALASKA.net. IN A
+BOW.INTNET.NE. IN A
+NS-JP.SINET.AD.JP. IN A
+ns.musin.de. IN A
+ip1.romkey.SEG.net. IN A
+DNS2.ITD.UMICH.EDU. IN A
+mail.rpi.EDU. IN A
+INECO.NIC.ES. IN A
+DNS2.FIREHOUSE.net. IN A
+BOW.INTNET.BJ. IN A
+sundown.vtc.VSC.EDU. IN A
+NIC.AIX.GR. IN A
+NIC.AD.JP. IN A
+NS.DC.IGC.org. IN A
+LHR.NS.GDNS.net. IN A
+NS2.WEBMAGIC.net. IN A
+MUNNARI.OZ.AU. IN A
+HIPPO.RU.AC.ZA. IN A
+PEBBLES.IOM.com. IN A
+penpal.dmz.RPSLMC.EDU. IN A
+netnews.HINET.net. IN A
+INS2.TOSA.TWTELECOM.net. IN A
+proxy6.cisco.com. IN A
+NS2.HOST4U.net. IN A
+POIPARAU.OYSTER.NET.CK. IN A
+NS-EXT.VIX.com. IN A
+NS2.NURSAT.net. IN A
+mail2.kw.com.CN. IN A
+NS-02B.ANS.net. IN A
+DNS.RCCN.net. IN A
+B.ROOT-SERVERS.ORSC. IN A
+FIREHOUSE.net. IN A
diff --git a/bin/tests/system/cacheclean/knowngood.dig.out b/bin/tests/system/cacheclean/knowngood.dig.out
new file mode 100644
index 0000000..a0f087e
--- /dev/null
+++ b/bin/tests/system/cacheclean/knowngood.dig.out
@@ -0,0 +1,953 @@
+YA.AKAMAI.com. 604800 IN A 204.178.118.68
+UPR1.UPR.CLU.EDU. 604800 IN A 136.145.1.4
+integra.s-integra.co.JP. 604800 IN A 210.162.202.34
+avalon.iks-jena.de. 604800 IN A 194.221.90.34
+NS1.GLOBALDNS.com. 604800 IN A 206.253.214.11
+NS.RDU.BELLSOUTH.net. 604800 IN A 205.152.32.20
+ns.space.net. 604800 IN A 195.30.0.1
+SUN.MHS-RELAY.AC.UK. 604800 IN A 128.86.8.25
+AYAX.UNIANDES.EDU.CO. 604800 IN A 157.253.50.30
+DNS.NIC.CD. 604800 IN A 194.38.74.11
+NS.DNS.PT. 604800 IN A 193.136.0.1
+NS1.INTERNETSHARE.com. 604800 IN A 63.207.108.53
+MASTER.DNS.BE. 604800 IN A 194.7.171.243
+CATAMOUNT.middlebury.EDU. 604800 IN A 140.233.2.204
+FM03.FM. 604800 IN A 206.49.89.4
+NAAMAK.NCST.ERNET.IN. 604800 IN A 202.41.110.66
+gateway2.BFG.com. 604800 IN A 166.102.214.66
+NS3.NS.ESAT.net. 604800 IN A 192.111.39.100
+DNS1.INTUIT.com. 604800 IN A 208.157.255.4
+DEN-NS2.FWIDCSERVICES.net. 604800 IN A 216.7.160.32
+SOL.UNDPBI.TELEPAC.net. 604800 IN A 194.65.87.2
+NS2.tridog.com. 604800 IN A 206.168.112.51
+DNS2.KW. 604800 IN A 161.252.48.150
+NS2.MAIL.com. 604800 IN A 165.251.1.3
+NS.FIRSTCOM.CL. 604800 IN A 200.27.2.2
+DNS4.QUICKEN.com. 604800 IN A 198.3.99.252
+bofh.cid.net. 604800 IN A 212.172.21.254
+NS1.KRNIC.net. 604800 IN A 202.30.50.51
+NS2.SR.net. 604800 IN A 200.1.156.11
+NS1.TELSTRA.net. 604800 IN A 139.130.4.5
+ns.cafax.SE. 604800 IN A 192.71.228.17
+NS1.DNS.NET.NZ. 604800 IN A 202.46.161.3
+NS.CONCOURSE.com. 604800 IN A 199.218.113.2
+35.32/27.110.16.12.IN-ADDR.ARPA. 604800 IN PTR mail.nova-data.com.
+CCC.champcable.com. 604800 IN A 207.41.53.11
+NS.RIPE.net. 604800 IN A 193.0.0.193
+NS.NIC.NU. 604800 IN A 128.11.47.50
+KIM.CAMNET.CM. 604800 IN A 195.24.192.35
+DOGON.SOTELMA.net. 604800 IN A 208.144.230.1
+DNS02.FLAME.org. 604800 IN A 204.152.184.97
+NS.MIA.BELLSOUTH.net. 604800 IN A 205.152.16.20
+mail.ok.RU. 604800 IN A 195.2.83.162
+NS.NIC.MX. 604800 IN A 200.23.1.1
+NS2.BERKELEY.EDU. 604800 IN A 128.32.136.12
+NS2.BERKELEY.EDU. 604800 IN A 128.32.206.12
+SHIKHAR.MOS.COM.NP. 604800 IN A 202.52.255.5
+noc.rrz.Uni-Koeln.de. 604800 IN A 134.95.100.209
+NS.KORNET.net. 604800 IN A 168.126.63.1
+keith.gazpacho.org. 604800 IN A 209.67.235.37
+NS2.appliedtheory.com. 604800 IN A 168.75.17.11
+NS.CERNET.net. 604800 IN A 202.112.0.44
+smtp.ELISTX.com. 604800 IN A 209.116.252.130
+NS-AIT.THNIC.net. 604800 IN A 192.41.170.219
+from.PL. 604800 IN A 212.160.132.114
+mailhub.icann.org. 604800 IN A 192.0.34.33
+SEC1.DNS.UK.PSI.net. 604800 IN A 154.32.105.34
+isrv3-i.isc.org. 604800 IN A 204.152.184.87
+PHLOEM.UOREGON.EDU. 604800 IN A 128.223.32.35
+CTINA.AR. 604800 IN A 200.16.97.17
+DNS2.IAM.NET.MA. 604800 IN A 212.217.0.12
+10.126.39.137.IN-ADDR.ARPA. 604800 IN PTR Fddi0-0.New-York4.NY.ALTER.NET.
+DNS.PRINCETON.EDU. 604800 IN A 128.112.129.15
+NS.BELLSOUTH.net. 604800 IN A 205.152.0.5
+NS1.SNS-FELB.DEBIS.com. 604800 IN A 53.122.1.10
+localhost. 604800 IN A 127.0.0.1
+hm6.vt.highmeadow.com. 604800 IN A 207.136.209.6
+SYRUP.hill.com. 604800 IN A 208.162.106.3
+NS99.WAIKATO.AC.NZ. 604800 IN A 130.217.76.27
+NS4.CW.net. 604800 IN A 204.70.49.234
+NS2.SLOWMOE.com. 604800 IN A 137.118.8.50
+ns2.hypa.net. 604800 IN A 63.160.181.11
+ns.sxtyptt.NET.CN. 604800 IN A 202.99.192.68
+NS2.MERCHANTWARE.com. 604800 IN A 209.170.142.35
+uunymdgds1.DOUBLECLICK.net. 604800 IN A 206.65.183.21
+e34.co.us.IBM.com. 604800 IN A 32.97.110.132
+kista.dns.swip.net. 604800 IN A 192.71.220.9
+ZEBRA.UEM.MZ. 604800 IN A 196.3.96.67
+NET2.GENDYN.com. 604800 IN A 204.60.171.9
+NS0.UTK.EDU. 604800 IN A 160.36.0.66
+NS.RELCOM.EU.net. 604800 IN A 193.124.23.3
+DNS0.AXION.BT.CO.UK. 604800 IN A 132.146.5.1
+mail.vhv.com. 604800 IN A 208.5.161.11
+DNS4.UK.MSFT.net. 604800 IN A 213.199.144.152
+NS2.ADNS.net. 604800 IN A 199.5.157.3
+NS1.SEATTLE.US.NETDNS.com. 604800 IN A 206.253.214.13
+NS2.UNIVIE.AC.at. 604800 IN A 193.171.255.66
+NS15B.BOCA15-VERIO.com. 604800 IN A 208.55.91.51
+www.BAYAREA.com. 604800 IN CNAME vh80040.vh8.infi.net.
+ns4.onemain.com. 604800 IN A 63.208.210.11
+NS2.EDIGITALS.com. 604800 IN A 211.39.139.36
+MICHAEL.VATICAN.VA. 604800 IN A 212.77.0.2
+AUSTIN.GH.com. 604800 IN A 196.3.64.1
+sld-ns2.CNNIC.NET.CN. 604800 IN A 202.97.16.197
+NS2.CDC.GOV. 604800 IN A 198.246.96.92
+NS.WATSON.IBM.com. 604800 IN A 198.81.209.2
+NS.NIC.SH. 604800 IN A 194.205.62.60
+NS2.BAHNHOF.net. 604800 IN A 212.85.64.4
+NS-AUTH2.cmates.com. 604800 IN A 208.23.213.3
+ISDMNL.WR.USGS.GOV. 604800 IN A 130.118.4.2
+NS2.COBEX.net. 604800 IN A 207.102.129.72
+MERLE.CIRA.CA. 604800 IN A 64.26.149.98
+NS.UVG.EDU.GT. 604800 IN A 168.234.68.2
+NS1.CWVA.DOUBLECLICK.net. 604800 IN A 205.138.3.20
+eliot.diebold.com. 604800 IN A 204.151.249.21
+NS.ALMADEN.IBM.com. 604800 IN A 198.4.83.35
+NS2.INTERNETSQUARE.com. 604800 IN A 205.227.232.9
+mail.QUEST-NET.com. 604800 IN A 207.140.30.11
+Z1.NS.LHR1.GLOBIX.net. 604800 IN A 212.111.32.38
+DNS1.AVANTEL.NET.MX. 604800 IN A 200.33.213.66
+vh80040.vh8.INFI.net. 604800 IN A 209.97.59.245
+NS.LEB.net. 604800 IN A 206.127.55.2
+NS.DCC.UCHILE.CL. 604800 IN A 146.83.5.204
+CLOUSO.RISQ.QC.CA. 604800 IN A 192.26.210.1
+muenster.westfalen.de. 604800 IN A 193.174.5.2
+us.a1.YIMG.com. 604800 IN CNAME a32.g.a.YIMG.com.
+NS.DEMOS.SU. 604800 IN A 194.87.0.8
+NS.DEMOS.SU. 604800 IN A 194.87.0.9
+south.NAVPOINT.com. 604800 IN A 207.106.42.12
+netconsult.netconx.de. 604800 IN A 193.141.75.1
+DNS2.btinternet.com. 604800 IN A 194.73.73.94
+NS2.CINE.net. 604800 IN A 207.168.250.12
+castor.cmc.ec.gc.CA. 604800 IN A 142.135.4.14
+EX2-DNS0.AVENUEA.com. 604800 IN A 216.34.88.20
+firewall3.glaxowellcome.com. 604800 IN A 192.58.204.207
+MACU.MA.MT.NP.ELS-GMS.att.net. 604800 IN A 199.191.145.136
+NS.PA. 604800 IN A 168.77.8.2
+TGSERV.TELE.GL. 604800 IN A 194.177.224.7
+KYNSE02.MESSAGESECURE.com. 604800 IN A 216.142.252.201
+GORGON.XTRA.CO.NZ. 604800 IN A 202.27.158.34
+DNS.NIC.IT. 604800 IN A 193.205.245.5
+pop.VERMONTEL.net. 604800 IN CNAME loomis.VERMONTEL.net.
+NS2.REGISTRY.HM. 604800 IN A 209.54.168.55
+NAMESERVER1.CONCENTRIC.net. 604800 IN A 207.155.183.73
+47.131.127.204.IN-ADDR.ARPA. 604800 IN PTR mtiwmhc22.worldnet.att.net.
+mailhost.tfm.com. 604800 IN A 192.231.224.11
+NS1.MRC.GM. 604800 IN A 212.60.69.1
+NS.WIDE.AD.JP. 604800 IN A 203.178.136.63
+NS.BTA.NET.CN. 604800 IN A 202.96.0.133
+NS2.ISPC.org. 604800 IN A 209.124.64.11
+BOW.RAIN.FR. 604800 IN A 194.51.3.49
+srs.srs.state.vt.us. 604800 IN A 159.105.101.150
+NS4.WEB2010.com. 604800 IN A 216.157.55.6
+NS.TELECOM.NET.ET. 604800 IN A 196.27.22.43
+NS1.DNS.NET.KH. 604800 IN A 203.127.100.21
+GATEN.JARING.MY. 604800 IN A 161.142.227.17
+shell.nominum.com. 604800 IN A 204.152.187.59
+CHEOPS.ANU.EDU.AU. 604800 IN A 150.203.224.24
+VANGOGH.CS.BERKELEY.EDU. 604800 IN A 128.32.33.5
+NS2.NOC.NULLUS.net. 604800 IN A 63.119.253.254
+NIC.LTH.SE. 604800 IN A 130.235.20.3
+ns.farm.net. 604800 IN A 216.112.179.160
+NS.USEC.SUN.com. 604800 IN A 192.9.48.3
+NS2.YOUR-DOMAIN.com. 604800 IN A 216.167.31.177
+DNS-EAST.PREP.net. 604800 IN A 129.250.252.10
+ns.hcr.net. 604800 IN A 208.240.246.4
+NS-RCH.nortelnetworks.com. 604800 IN A 192.135.215.2
+crl.DEC.com. 604800 IN A 192.58.206.2
+NS.PIXAR.ES. 604800 IN A 194.143.196.3
+MEX1-M-213.UNINET.NET.MX. 604800 IN A 200.33.146.213
+NS.ITU.CH. 604800 IN A 156.106.192.121
+matrix.uwm.EDU.PL. 604800 IN A 213.184.3.136
+gateway1.gmcr.com. 604800 IN A 12.34.108.130
+NS2.DNS.BR. 604800 IN A 200.19.119.99
+foxharp.boston.MA.us. 604800 IN MX 10 bparker.connactivity.com.
+Quest-7.symquest.com. 604800 IN A 64.69.102.131
+NS2.VERIO.net. 604800 IN A 129.250.31.190
+NAME.IAD.GBLX.net. 604800 IN A 204.152.166.155
+NS2.EMIRATES.NET.AE. 604800 IN A 194.170.1.7
+supai.oit.UMASS.EDU. 604800 IN A 128.119.175.6
+QUERN.EPILOGUE.com. 604800 IN A 128.224.1.136
+NS3.TOPICA.com. 604800 IN A 206.111.131.72
+NS1.JERKY.net. 604800 IN A 204.57.55.100
+JTB.BRUNET.BN. 604800 IN A 202.160.8.2
+AUTH100.NS.UU.net. 604800 IN A 198.6.1.202
+BOW.INTNET.DJ. 604800 IN A 193.251.143.253
+OSI2.GUA.net. 604800 IN A 205.161.188.3
+AZMODAN.ULA.VE. 604800 IN A 150.185.130.16
+THUMPER.RPSLMC.EDU. 604800 IN A 144.74.22.8
+ICHU.RCP.NET.PE. 604800 IN A 161.132.5.14
+NS.NIC.AC. 604800 IN A 194.205.62.120
+DNS.NETFLIGHT.com. 604800 IN A 207.88.32.2
+ns2.UTORONTO.CA. 604800 IN A 128.100.102.202
+mail.giffordmed.org. 604800 IN A 130.189.100.51
+RATA.VUW.AC.NZ. 604800 IN A 130.195.2.11
+NS-2.ADMONITOR.net. 604800 IN A 216.35.185.40
+NCC.MOC.KW. 604800 IN A 196.1.69.98
+NS.EUNET.ES. 604800 IN A 193.127.1.11
+NS3.best.com. 604800 IN A 209.24.149.42
+zip.MAIL-LIST.com. 604800 IN MX 5 zip.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 20 sluice.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 20 pipeline.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 20 transport.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 50 brisk.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 50 swifty.MAIL-LIST.com.
+zip.MAIL-LIST.com. 604800 IN MX 50 velocity.MAIL-LIST.com.
+JATZ.AARNET.EDU.AU. 604800 IN A 139.130.204.4
+DNS2.MAN.LODZ.PL. 604800 IN A 212.51.192.5
+NS.VERITAS.com. 604800 IN A 204.177.156.38
+218.241.103.199.IN-ADDR.ARPA. 604800 IN PTR abyssinian.sleepycat.com.
+BOW.SNPT.KM. 604800 IN A 195.101.19.253
+Z1.NS.SJC1.GLOBIX.net. 604800 IN A 209.10.34.55
+DNS.NIC.TT. 604800 IN A 24.3.198.194
+MAKISIG.IPHIL.net. 604800 IN A 203.176.28.135
+NS.DK.net. 604800 IN A 193.88.44.42
+NS.NI. 604800 IN A 200.30.36.8
+NS.NI. 604800 IN A 165.98.1.2
+CIUP1.NCC.UP.PT. 604800 IN A 193.136.51.52
+ns2.verisign-grs.com. 604800 IN A 198.41.3.108
+NS1.UMASS.EDU. 604800 IN A 128.119.166.14
+NS.NEWACCOUNT.net. 604800 IN A 216.121.96.26
+UDNS2.ULTRADNS.net. 604800 IN A 204.74.101.1
+NS2.LATNET.LV. 604800 IN A 159.148.108.1
+info-server.surrey.AC.UK. 604800 IN A 131.227.102.6
+NS2.SQUONK.net. 604800 IN A 63.84.12.135
+NS2.DSO.net. 604800 IN A 206.16.77.11
+www.energyenhancement.org. 604800 IN A 216.121.175.228
+DNS1.BD. 604800 IN A 209.58.24.5
+nl.COMPUWARE.com. 604800 IN MX 150 uucp.nl.net.
+nl.COMPUWARE.com. 604800 IN MX 50 bitbucket.extern.uniface.nl.
+nl.COMPUWARE.com. 604800 IN MX 100 smtp.nl.net.
+NS.DHIRAAGU.MV. 604800 IN A 202.1.192.196
+TRANTOR.UMD.EDU. 604800 IN A 128.8.10.14
+NS.ALCANET.NO. 604800 IN A 193.213.238.10
+Z6.MSFT.AKADNS.com. 604800 IN A 207.229.152.20
+NS4.ync.net. 604800 IN A 206.185.20.9
+CMTU.MT.NS.ELS-GMS.att.net. 604800 IN A 12.127.16.69
+vh40099.vh4.INFI.net. 604800 IN A 209.97.59.121
+ns2.secondary.nl. 604800 IN A 194.229.138.6
+abyssinian.sleepycat.com. 604800 IN A 199.103.241.218
+APHEX.MENTOR.BE. 604800 IN A 193.121.64.5
+webmail.fiberia.com. 604800 IN A 216.55.147.2
+localhost.moonmothers.com. 604800 IN A 127.0.0.1
+NS2.DNS.LU. 604800 IN A 158.64.229.3
+NS.VISUALCOM.ES. 604800 IN A 194.143.202.202
+TONIC.TO. 604800 IN A 206.184.59.10
+NS1.CRSNIC.net. 604800 IN A 198.41.3.39
+trurl.ispid.com.PL. 604800 IN A 195.150.99.3
+datingagentur.de. 604800 IN A 212.227.216.57
+NS2.NSIREGISTRY.net. 604800 IN A 198.41.3.108
+ICE.VIA-NET-WORKS.IE. 604800 IN A 212.17.32.2
+sgi1.map.com. 604800 IN A 204.71.19.20
+NS0.HS0.U-NET.net. 604800 IN A 194.119.128.70
+candle.pha.pa.us. 604800 IN A 162.33.245.46
+NS1.PACIFIC.NET.SG. 604800 IN A 192.169.33.3
+NS.CENIAI.NET.CU. 604800 IN A 169.158.128.136
+NS2.UUCP.NE.JP. 604800 IN A 210.141.111.69
+za.akamaitech.net. 604800 IN A 204.178.107.226
+NS.UCR.AC.CR. 604800 IN A 163.178.88.2
+DNS-02.NS.cs.com. 604800 IN A 205.188.157.235
+dns2.primary.net. 604800 IN A 205.242.187.235
+PAPPSRV.PAPP.UNDP.org. 604800 IN A 192.115.229.1
+NS1.REGME.com. 604800 IN A 207.153.57.14
+DNS.CS.KULEUVEN.AC.BE. 604800 IN A 134.58.40.4
+NS1.VERMONTLAW.net. 604800 IN A 63.89.26.15
+mail.garmontusa.com. 604800 IN A 64.30.8.178
+NS2.SAIPAN.com. 604800 IN A 202.128.28.2
+NS.ARICATRA.com. 604800 IN A 206.64.112.114
+ns2.reedmedia.net. 604800 IN A 209.241.86.6
+NS.NETLAB.SK. 604800 IN A 195.168.1.4
+RELAY.GW.tislabs.com. 604800 IN A 192.94.214.100
+b.ns.tmcs.net. 604800 IN A 209.104.33.252
+NS1.IBL.BM. 604800 IN A 199.172.192.1
+ok.RU. 604800 IN A 195.2.83.162
+NS.RICC.ALMA-ATA.SU. 604800 IN A 194.87.112.4
+KITKA.MARNET.MK. 604800 IN A 194.149.131.2
+dasher.dartmouth.EDU. 604800 IN A 129.170.208.6
+NS0.PLANET-THREE.com. 604800 IN A 212.49.219.164
+KNOCK.SER.BBNPLANET.net. 604800 IN A 192.239.16.129
+tornado.webtech.elk.PL. 604800 IN A 212.244.162.100
+AUTH2.NS.IDT.net. 604800 IN A 169.132.133.1
+host3.VTLEGALAID.org. 604800 IN A 207.136.208.115
+NS.EUNET.SK. 604800 IN A 192.108.130.33
+TULKU.NIC.AR. 604800 IN A 200.16.97.77
+RELAY.CDNNET.CA. 604800 IN A 192.73.5.1
+DNS2.TPSA.PL. 604800 IN A 194.204.152.34
+enterprise.wirbel.com. 604800 IN A 194.231.54.2
+ECNET.EC. 604800 IN A 157.100.45.2
+ENGINE1.UNA.net. 604800 IN A 208.136.52.74
+WYCU.WY.BR.NP.ELS-GMS.att.net. 604800 IN A 199.191.128.43
+ARWENA.NASK.WAW.PL. 604800 IN A 193.59.201.28
+PAC2.NIPR.MIL. 604800 IN A 199.252.155.234
+DAISY.EE.UND.AC.ZA. 604800 IN A 146.230.192.18
+odin.ietf.org. 604800 IN A 132.151.1.176
+dns.kaben-net.de. 604800 IN A 195.179.28.17
+NS2.ALTAVISTA.com. 604800 IN A 209.73.164.7
+CASTOR.TELEGLOBE.net. 604800 IN A 199.202.55.2
+CIR.RED.SV. 604800 IN A 168.243.254.1
+PIJIN.COM.SB. 604800 IN A 202.139.42.10
+NS4.CTCCOM.net. 604800 IN A 64.69.100.35
+NS1.SOL.NO. 604800 IN A 195.225.2.10
+DNS2.TK.MSFT.net. 604800 IN A 207.46.232.38
+NS.BSDI.com. 604800 IN A 207.174.116.8
+NS.SVIANED.nl. 604800 IN A 143.177.1.3
+NS.NOVELL.com. 604800 IN A 137.65.1.1
+NS.LUCKY.net. 604800 IN A 193.193.193.100
+SJC-NS2.SJC.LYCOS.com. 604800 IN A 206.79.171.40
+NS1.OP.net. 604800 IN A 209.152.193.4
+worldnet.att.net. 604800 IN A 199.70.151.234
+APIES.FRD.AC.ZA. 604800 IN A 137.214.80.1
+mail.skiinsurance.com. 604800 IN A 207.136.205.152
+NS.BELNET.BE. 604800 IN A 193.190.198.2
+NS.BELNET.BE. 604800 IN A 193.190.198.10
+KOMO.INET.GA. 604800 IN A 208.148.44.1
+EARTH.THEPLANET.net. 604800 IN A 195.92.195.222
+VASCO.USMA.AC.PA. 604800 IN A 208.141.92.2
+GODFEVER.DCCSERVER.com. 604800 IN A 208.137.22.6
+BOS-NS2.BOS.LYCOS.com. 604800 IN A 209.67.228.40
+NS2.GOTO.com. 604800 IN A 204.71.128.137
+NS1.overstock.com. 604800 IN A 207.225.194.13
+NS1-PUBLIC.ZMA.COMPAQ.com. 604800 IN A 161.114.64.24
+ns.ilovedomain.com. 604800 IN A 211.175.164.170
+ns1.anycast.net. 604800 IN A 216.196.51.4
+PASCAL.UPRR.PR. 604800 IN A 134.202.1.120
+NS3-AUTH.SPRINTLINK.net. 604800 IN A 144.228.255.10
+NS1-Y.DNS.PIPEX.net. 604800 IN A 158.43.193.89
+prue.eim.surrey.AC.UK. 604800 IN A 131.227.76.5
+TROLL-GW.GATECH.EDU. 604800 IN A 130.207.244.251
+NS.SIERRATEL.SL. 604800 IN A 194.133.124.5
+ns2.PSHIFT.com. 604800 IN A 208.153.85.21
+NS.ERS.IBM.com. 604800 IN A 204.146.173.35
+ASLAN.OPEN-RSC.org. 604800 IN A 199.5.157.128
+NS2.DOMAIN-REGISTRY.nl. 604800 IN A 193.176.144.130
+uranus.lan-ks.de. 604800 IN A 194.45.71.1
+mail.unlisys.net. 604800 IN A 195.21.255.252
+NS.AUSTRIA.EU.net. 604800 IN A 192.92.138.35
+AUTH01.CONNECT.IE. 604800 IN A 194.106.128.50
+SUN.SCSI.GOV.BY. 604800 IN A 195.50.5.103
+NS1.SIGMAHOSTING.com. 604800 IN A 209.241.86.6
+NS.CAST.EDU.JM. 604800 IN A 200.9.115.2
+DS.NIC.NET.SG. 604800 IN A 202.42.194.205
+PRADES.CESCA.ES. 604800 IN A 192.94.163.152
+ns.sta.NET.CN. 604800 IN A 202.96.199.133
+NSE00.excite.com. 604800 IN A 198.3.102.250
+NS3.ABOVE.net. 604800 IN A 207.126.105.146
+CASBAH.ELDJAZAIR.NET.DZ. 604800 IN A 193.194.81.45
+ASKIA.SOTELMA.ML. 604800 IN A 208.144.230.3
+NS.IDT.net. 604800 IN A 198.4.75.100
+FXCLPR02.IS.CHRYSLER.com. 604800 IN A 204.189.94.37
+SVC00.APNIC.net. 604800 IN A 202.12.28.131
+NS5.DCX.YAHOO.com. 604800 IN A 216.32.74.10
+ns1.ray.net. 604800 IN A 195.238.228.131
+NS.NIC.MC. 604800 IN A 195.78.6.131
+ns.runway.CN.net. 604800 IN A 211.101.132.8
+benoni.uit.NO. 604800 IN A 129.242.4.254
+SCRATCHY.MINDSPRING.net. 604800 IN A 207.69.200.211
+ns1.pcode.com. 604800 IN A 216.15.192.135
+ns1.aha.RU. 604800 IN A 195.2.80.142
+ns2.uwaterloo.CA. 604800 IN A 129.97.128.100
+ns2.NIC.AD.JP. 604800 IN A 202.12.30.133
+a.ns.foxharp.boston.MA.us. 604800 IN A 24.147.209.205
+NS.NIC.IO. 604800 IN A 194.205.62.100
+A-GTLD-SERVERS.dot-god.com. 604800 IN A 205.189.73.123
+SMTP.slac.stanford.EDU. 604800 IN A 134.79.18.80
+52.87.198.209.IN-ADDR.ARPA. 604800 IN PTR mqueue0.sover.net.
+BARNEY.ADVSYS.CO.UK. 604800 IN A 194.72.124.2
+NS1.TELEPAC.PT. 604800 IN A 194.65.3.20
+NICOSIA.CCS.UCY.AC.CY. 604800 IN A 194.42.6.97
+NS.PUNCHDOWN.org. 604800 IN A 140.174.131.100
+SYNAESTHESIA.COGNOSCENTI.org. 604800 IN A 207.208.112.4
+NS2.PLANET-THREE.net. 604800 IN A 212.49.219.190
+DNS.CIT.CORNELL.EDU. 604800 IN A 192.35.82.50
+MODOR.VERISIGN.net. 604800 IN A 205.139.94.55
+SUNSTROKE.IS.RPSLMC.EDU. 604800 IN A 144.74.21.8
+NS2.SEG.net. 604800 IN A 206.34.181.16
+NEMUNAS.SC-UNI.KTU.LT. 604800 IN A 193.219.32.13
+MULGA.CS.MU.OZ.AU. 604800 IN A 128.250.1.22
+MULGA.CS.MU.OZ.AU. 604800 IN A 128.250.37.150
+NS1.NPLUS.GF. 604800 IN A 195.6.144.3
+ns2.centralinfo.net. 604800 IN A 63.102.204.130
+K.GTLD-SERVERS.net. 604800 IN A 213.177.194.5
+ns1.codelocal.com. 604800 IN A 216.15.192.130
+NS2.IPNS.com. 604800 IN A 63.230.183.1
+NS0.DE.NIC.NU. 604800 IN A 216.200.116.40
+NS.USSR.EU.net. 604800 IN A 193.124.22.65
+NS.INTERNET.SK. 604800 IN A 192.108.130.91
+CORREOS.SEKER.ES. 604800 IN A 194.179.87.1
+mx1.buf.ADELPHIA.net. 604800 IN A 24.48.36.10
+aun.UNINETT.NO. 604800 IN A 129.241.1.99
+NS0.NETANET.com. 604800 IN A 195.172.127.72
+NS0.NETANET.com. 604800 IN A 194.6.96.218
+www.MANY-PATHS-ENERGY-ENHANCEMENT.com. 604800 IN A 66.33.4.50
+NS2.STARFIRE.DOUGLAS.MA.us. 604800 IN A 216.129.136.9
+NS3.IKP.PL. 604800 IN A 157.25.5.30
+pns.dtag.de. 604800 IN A 194.25.0.125
+NZ.NS.NIC.NU. 604800 IN A 203.97.132.66
+DAVER.bungi.com. 604800 IN A 207.126.97.2
+DAVER.bungi.com. 604800 IN A 206.14.228.2
+gutenberg.bucksnet.com. 604800 IN A 207.113.15.5
+DNS2.IT.net. 604800 IN A 151.1.2.1
+NS2.SNS-UT.DEBIS.com. 604800 IN A 53.122.2.10
+ISI.EDU. 604800 IN A 128.9.176.32
+amethyst.xaos.org. 604800 IN A 204.145.159.12
+PAPPILLOMA.WWEBSVS.com. 604800 IN A 209.233.37.10
+NS2.bock.com. 604800 IN A 64.30.29.4
+NS2.OAR.net. 604800 IN A 192.88.195.10
+MINION.NETPOLICY.com. 604800 IN A 207.87.121.66
+Mail.catic1.com. 604800 IN A 207.190.204.103
+NS4.DNS.space.net. 604800 IN A 195.222.210.93
+b.gtld-servers.ORSC. 604800 IN A 216.13.126.116
+bend.madriver.com. 604800 IN A 207.136.232.15
+NS4.IS-FUN.net. 604800 IN A 212.162.54.34
+NS2.JPS.net. 604800 IN A 216.224.156.252
+NS1.IP-PLUS.net. 604800 IN A 164.128.36.34
+rush.cc1.RPSLMC.EDU. 604800 IN A 144.74.150.23
+NS2.GBMTECH.net. 604800 IN A 208.243.164.3
+DNS.MSEN.com. 604800 IN A 148.59.19.11
+DNSSEC2.SINGNET.COM.SG. 604800 IN A 195.13.10.226
+NS2.HOME.net. 604800 IN A 24.2.0.27
+ACCESS.MBNET.MB.CA. 604800 IN A 130.179.16.143
+DNS0.SPIN.AD.JP. 604800 IN A 165.76.0.98
+Filer.PHOTOTRUST.com. 604800 IN A 64.85.86.172
+jpl.NASA.GOV. 604800 IN A 137.78.160.180
+NS2.TECHNOLOGIA.net. 604800 IN A 207.253.59.4
+bparker.CONNACTIVITY.com. 604800 IN A 206.34.200.200
+NS1.uvm.EDU. 604800 IN A 132.198.201.10
+NS.SENET.net. 604800 IN A 206.155.163.195
+DNS2.UTCC.UTORONTO.CA. 604800 IN A 128.100.102.201
+localhost.costorf.com. 604800 IN A 127.0.0.1
+DNS2.AD. 604800 IN A 194.158.64.8
+HYDRA.HELSINKI.FI. 604800 IN A 128.214.4.29
+NAME.PHX.GBLX.net. 604800 IN A 206.165.6.10
+NS2.FOOL.com. 604800 IN A 208.51.76.222
+NS01-SERVER.CURINFO.AN. 604800 IN A 200.44.117.129
+NS.CR. 604800 IN A 163.178.8.2
+mail.pshift.net. 604800 IN A 208.153.85.30
+NS.IRD.FR. 604800 IN A 195.83.14.1
+NS.UZ. 604800 IN A 213.68.88.11
+DNS.INTELCOM.SM. 604800 IN A 194.183.64.11
+DNS2.UNIV-NKC.MR. 604800 IN A 193.251.145.154
+HNS3.hns.com. 604800 IN A 208.236.67.3
+bay.cs.UTORONTO.CA. 604800 IN A 128.100.1.1
+NS0.BT.net. 604800 IN A 194.72.6.51
+BAYONET.SJMERCURY.com. 604800 IN A 207.1.134.34
+PAN.BIJT.net. 604800 IN A 213.196.2.97
+NAVI.SUBTEND.net. 604800 IN A 208.186.117.224
+NS.CIX.CX. 604800 IN A 195.222.235.216
+waldorf.Informatik.Uni-Dortmund.de. 604800 IN A 129.217.4.42
+NS2.ivillage.com. 604800 IN A 209.185.162.16
+DNS.NIC.XLINK.net. 604800 IN A 193.141.40.42
+NS1.MERCHANTWARE.CON. 604800 IN A 209.170.142.34
+NS.TO.GD-ES.com. 604800 IN A 199.107.240.66
+NS-A.RNC.RO. 604800 IN A 192.162.16.31
+REGGAE.NCREN.net. 604800 IN A 128.109.131.3
+SSS-NL.DENIC.de. 604800 IN A 193.0.0.237
+NS1.TDC.TO. 604800 IN A 206.86.247.250
+NS.NIC.HU. 604800 IN A 193.6.27.62
+JOANNA.WILLIAM.org. 604800 IN A 195.153.6.2
+NS0.IIJ.AD.JP. 604800 IN A 202.232.2.34
+maus.spack.org. 604800 IN A 204.245.198.90
+B.NS.VERIO.net. 604800 IN A 129.250.35.32
+SECDNS.EUNET.BE. 604800 IN A 193.74.208.139
+NS3.EUROPE.YAHOO.com. 604800 IN A 217.12.4.71
+A.ROOT-SERVERS.net. 604800 IN A 198.41.0.4
+sherickpm.com. 604800 IN MX 10 inbound.sherickpm.com.criticalpath.net.
+NS2.MEDIASERVICES.net. 604800 IN A 64.65.16.237
+YARDBIRD.CNS.vt.EDU. 604800 IN A 198.82.247.34
+SUNIC.SUNET.SE. 604800 IN A 192.36.125.2
+NS.MT. 604800 IN A 193.188.47.252
+CNDVG001.usa.net. 604800 IN A 165.212.12.1
+NS1.CX.ESCROW.IOCOMM.NET.CX. 604800 IN A 203.132.96.2
+DNS-02.NS.AOL.com. 604800 IN A 205.188.157.232
+ns2.tesserae.com. 604800 IN A 209.157.194.3
+SV10.BATELCO.COM.BH. 604800 IN A 193.188.124.227
+dec.anr.state.vt.us. 604800 IN MX 0 dec.anr.state.vt.us.
+dec.anr.state.vt.us. 604800 IN MX 10 mx1.state.vt.us.
+dec.anr.state.vt.us. 604800 IN MX 10 mx2.state.vt.us.
+3.133.188.192.IN-ADDR.ARPA. 604800 IN PTR elektro.com.
+NS1.LONDON.UK.NETDNS.com. 604800 IN A 212.62.6.38
+NS.NIC.MG. 604800 IN A 194.214.107.253
+DNS1.VN. 604800 IN A 203.162.3.235
+DENS20.DEN.nps.GOV. 604800 IN A 165.83.24.20
+z.ip6.INT. 604800 IN A 198.32.2.66
+NS3.TRIVALLEY.com. 604800 IN A 206.25.132.30
+isis.imag.FR. 604800 IN A 129.88.32.24
+NS.SOVAM.com. 604800 IN A 194.67.2.97
+NS-SOA.DARENET.DK. 604800 IN A 130.226.1.4
+NS4.NIC.TV. 604800 IN A 207.151.24.23
+DNSSRV1X.mitre.org. 604800 IN A 199.94.97.51
+GATEKEEPER.NYTIMES.com. 604800 IN A 199.181.175.201
+D.I-DNS.net. 604800 IN A 211.169.245.170
+NS.KOLO.net. 604800 IN A 209.66.103.20
+NS4.FIRSTWORLD.net. 604800 IN A 216.7.160.162
+DECST.CERIST.DZ. 604800 IN A 193.194.64.11
+NS4.DNS.WS. 604800 IN A 216.52.234.102
+NS0.GDGSC.com. 604800 IN A 192.160.62.66
+UCTHPX.UCT.AC.ZA. 604800 IN A 137.158.128.1
+NS2.HOTWIRED.com. 604800 IN A 209.185.151.6
+ns02.ca.us.ibm.net. 604800 IN A 165.87.201.243
+NS2.SPEAKEASY.net. 604800 IN A 216.231.41.22
+TELCOM.ZPTC.CO.ZW. 604800 IN A 194.133.122.47
+NS.DK-HOSTMASTER.DK. 604800 IN A 193.163.102.2
+NS.NIC.LK. 604800 IN A 192.248.1.65
+NS2.zama.net. 604800 IN A 203.142.130.5
+CZ.EUNET.CZ. 604800 IN A 193.85.3.130
+NS.AC.ID. 604800 IN A 202.159.124.34
+NS1.CUBE.de. 604800 IN A 212.162.54.243
+NS1.QUASAR.net. 604800 IN A 199.166.31.3
+NS1.OFFSHORE.AI. 604800 IN A 209.88.68.34
+NS5.NRSITE.com. 604800 IN A 208.178.169.4
+NS.AIC.net. 604800 IN A 195.250.64.65
+OWL.NCC.nps.GOV. 604800 IN A 165.83.34.60
+MAXIM.gbch.net. 604800 IN A 203.9.155.249
+BOW.INTNET.TD. 604800 IN A 193.251.147.253
+ns1.cacheware.com. 604800 IN A 64.221.210.242
+NS2.SPEEDHOST.com. 604800 IN A 216.42.31.169
+NS1.COMMIT.GM. 604800 IN A 63.77.152.177
+NAME.ROC.GBLX.net. 604800 IN A 209.130.187.10
+90.198.245.204.IN-ADDR.ARPA. 604800 IN PTR maus.spack.org.
+BOLOGNA.NETTUNO.IT. 604800 IN A 193.43.2.5
+NIC.IBD.com. 604800 IN A 209.249.61.18
+NS.WESTOL.com. 604800 IN A 63.93.137.4
+time.SOVER.net. 604800 IN CNAME garnet.SOVER.net.
+UNIX1.CS.UMASS.EDU. 604800 IN A 128.119.40.12
+AARDVARK.WR.UMIST.AC.UK. 604800 IN A 130.88.146.3
+AARDVARK.WR.UMIST.AC.UK. 604800 IN A 128.16.5.31
+NS1.NIC.YU. 604800 IN A 147.91.8.6
+mail.velco.com. 604800 IN A 198.136.217.106
+DNSAUTH2.SYS.GTEI.net. 604800 IN A 4.2.49.3
+NS.TELE.FI. 604800 IN A 193.210.19.19
+state.vt.us. 604800 IN MX 10 mx1.state.vt.us.
+state.vt.us. 604800 IN MX 10 mx2.state.vt.us.
+NS.NYC.juno.com. 604800 IN A 205.231.108.1
+NS1.g-world.com. 604800 IN A 216.26.39.10
+AUTH2.AMERICA.net. 604800 IN A 209.17.197.18
+KIRA.ECS.UMASS.EDU. 604800 IN A 128.119.91.10
+CONACYT.GOB.SV. 604800 IN A 168.243.64.2
+DNS.SRCE.HR. 604800 IN A 161.53.3.7
+NS00.ns0.com. 604800 IN A 216.92.60.60
+NS2.CL.BELLSOUTH.net. 604800 IN A 205.152.16.8
+jenner.med.HARVARD.EDU. 604800 IN A 134.174.141.2
+p2.cavebear.com. 604800 IN A 199.184.128.35
+NS1.NIC.JE. 604800 IN A 216.110.45.224
+ORCU.OR.BR.NP.ELS-GMS.att.net. 604800 IN A 199.191.129.139
+NS.XBILL.org. 604800 IN A 204.152.186.163
+WRAITH.CS.UOW.EDU.AU. 604800 IN A 130.130.64.1
+12.159.145.204.IN-ADDR.ARPA. 604800 IN PTR amethyst.xaos.org.
+ns1.pr.SUN.com. 604800 IN A 192.18.16.2
+NS.SPIN.OMNES.net. 604800 IN A 192.23.90.196
+smtp.188.net. 604800 IN A 202.96.125.104
+TERMINAL.2GLOBE.net. 604800 IN A 195.178.183.230
+NS2.HARVARD.EDU. 604800 IN A 128.103.1.1
+NAMESERVER.CNR.IT. 604800 IN A 194.119.192.34
+EARTH.SY. 604800 IN A 195.22.198.6
+DNS2.REACCIUN.VE. 604800 IN A 150.188.4.212
+NS.TMX.COM.NI. 604800 IN A 205.218.253.2
+freefour.acs.rpi.EDU. 604800 IN A 128.113.24.91
+242.84.198.209.IN-ADDR.ARPA. 604800 IN PTR dlawren-gw.burl.sover.net.
+CORREU.STA.AD. 604800 IN A 194.158.67.1
+NS.DRUKNET.NET.BT. 604800 IN A 202.144.128.200
+NS4.US.PRSERV.net. 604800 IN A 165.87.201.244
+KAASASSUK.GH.GL. 604800 IN A 194.177.232.3
+ECUA.NET.EC. 604800 IN A 157.100.1.2
+NS.CONCYT.GOB.GT. 604800 IN A 168.234.106.2
+NS2.NAP.net. 604800 IN A 206.54.224.1
+DNS2.CN.net. 604800 IN A 202.97.18.61
+MX.NSI.NASA.GOV. 604800 IN A 128.102.18.31
+NS.TDS.net. 604800 IN A 204.246.1.20
+tdns-me1.NETSCAPE.com. 604800 IN A 205.188.247.67
+NS2.METU.EDU.TR. 604800 IN A 144.122.199.93
+NS2.SETARNET.AW. 604800 IN A 206.48.100.11
+87.184.152.204.IN-ADDR.ARPA. 604800 IN PTR isrv3-i.isc.org.
+DNS.OMNIWAY.SM. 604800 IN A 194.183.64.10
+NS0.U-NET.net. 604800 IN A 194.119.128.65
+elektro.CMHNET.org. 604800 IN A 192.188.133.3
+ns2.HIGGS.net. 604800 IN A 204.80.125.145
+NS2.SKYNETWEB.com. 604800 IN A 208.231.1.35
+MAGIC.MN. 604800 IN A 202.131.0.10
+NS1.YAHOO.com. 604800 IN A 204.71.200.33
+mx1.cdp.ADELPHIA.net. 604800 IN A 24.48.58.221
+SANTO.VANUATU.COM.VU. 604800 IN A 202.139.40.7
+www.mmuuf.org. 604800 IN MX 10 gro.dd.org.
+ns1.timeheart.net. 604800 IN A 63.197.231.203
+NS2.TOGETHER.net. 604800 IN A 204.97.120.31
+NS.AMNIC.net. 604800 IN A 195.250.64.90
+NS.EENET.EE. 604800 IN A 193.40.56.245
+www.ONLINEPHOTOCONTEST.com. 604800 IN A 64.85.86.152
+VIC20.BLIPP.com. 604800 IN A 195.163.165.35
+DNS.FROGHOUSE.org. 604800 IN A 207.121.69.243
+NS2.ELI.net. 604800 IN A 207.173.86.2
+NS.CAIS.com. 604800 IN A 205.177.10.10
+BAABEN.AFRIQ.net. 604800 IN A 165.231.1.3
+NS2.NJ.EXODUS.net. 604800 IN A 209.1.10.234
+DOMREG.NIC.CH. 604800 IN A 130.59.1.80
+NS.EU.net. 604800 IN A 192.16.202.11
+NS1.DIEBOLD.net. 604800 IN A 65.196.80.10
+NS3.CP.net. 604800 IN A 209.228.14.4
+DNS.FUW.EDU.PL. 604800 IN A 193.0.80.11
+www.retro.com. 604800 IN A 205.179.181.195
+NS2.UNI2.net. 604800 IN A 195.82.195.99
+ns1.alcatrazmedia.com. 604800 IN A 167.160.132.2
+dns6.CP.MSFT.net. 604800 IN A 207.46.138.20
+NS1.SEYCHELLES.net. 604800 IN A 202.84.235.33
+NS2.INTERNIC.net. 604800 IN A 198.41.0.11
+front.macrosoft.WAW.PL. 604800 IN A 194.196.86.66
+NISC.JVNC.net. 604800 IN A 128.121.50.7
+AUTH03.NS.DE.UU.net. 604800 IN A 192.76.144.16
+BURDELL.CC.GATECH.EDU. 604800 IN A 130.207.3.207
+NS4.AH.net. 604800 IN A 203.21.205.20
+ns1.sgh-net.de. 604800 IN A 212.86.129.142
+Leland2.stanford.EDU. 604800 IN A 171.64.14.58
+CBRU.BR.NS.ELS-GMS.att.net. 604800 IN A 199.191.128.105
+DENEB.DOMAINNT.net. 604800 IN A 207.211.220.90
+ns1.ivm.net. 604800 IN A 62.204.1.1
+NS0.CWCI.net. 604800 IN A 194.6.79.162
+35.110.16.12.IN-ADDR.ARPA. 604800 IN CNAME 35.32/27.110.16.12.IN-ADDR.ARPA.
+f.trns. 604800 IN A 209.133.38.16
+ODISEJ.TELEKOM.YU. 604800 IN A 195.178.32.2
+FRCU.EUN.EG. 604800 IN A 193.227.1.1
+NS.HHS.net. 604800 IN A 63.93.136.29
+FOO.GRNET.GR. 604800 IN A 194.177.210.211
+mail.WonderWorks.com. 604800 IN A 192.203.206.67
+NS1.IAFRICA.com. 604800 IN A 196.7.0.139
+NS.KACST.EDU.SA. 604800 IN A 212.26.44.3
+srs.state.vt.us. 604800 IN A 159.105.101.150
+OM4.OMANTEL.NET.OM. 604800 IN A 206.49.101.5
+Yeshua.Christ.com. 604800 IN A 207.54.4.5
+NS1.SIMORGH.com. 604800 IN A 209.1.163.10
+OLKETA.SOLOMON.COM.SB. 604800 IN A 202.139.42.4
+BANBA.DOMAINREGISTRY.IE. 604800 IN A 193.1.142.2
+NOC.IOS.com. 604800 IN A 198.4.75.69
+ns.schnism.net. 604800 IN A 195.88.150.3
+e4.ny.us.IBM.com. 604800 IN A 32.97.182.104
+DNS2.SEANET.com. 604800 IN A 199.181.164.2
+doubt.dd.org. 604800 IN A 209.198.103.193
+AMBER.ELEKTRON.PL. 604800 IN A 195.117.6.10
+gw.rge.com. 604800 IN A 157.225.178.11
+NS2.ZTNET.com. 604800 IN A 63.211.17.252
+NS3.INFI.net. 604800 IN A 205.219.239.5
+ZA.AKADNS.net. 604800 IN A 209.185.188.39
+ESTIA.CSI.FORTH.GR. 604800 IN A 139.91.191.3
+vtagr04.agr.state.vt.us. 604800 IN A 159.105.50.4
+NS1-PUBLIC.ZTX.COMPAQ.com. 604800 IN A 161.114.1.204
+ADMII.ARL.MIL. 604800 IN A 128.63.31.4
+ADMII.ARL.MIL. 604800 IN A 128.63.5.4
+NS.NIXU.FI. 604800 IN A 193.209.237.29
+DNS2.PIONEERNET.net. 604800 IN A 208.240.196.10
+NS.NIC.CL. 604800 IN A 146.83.4.11
+NS2.UTZ. 604800 IN A 160.124.112.10
+NS4.LUXNOC.com. 604800 IN A 195.206.104.201
+NS2.PBI.net. 604800 IN A 206.13.29.11
+annwfn.erfurt.thur.de. 604800 IN A 194.122.210.3
+NS1.MW.mediaone.net. 604800 IN A 24.131.1.8
+NS1.ISU.NET.SA. 604800 IN A 212.26.18.3
+pop.SHOREHAM.net. 604800 IN CNAME SHOREHAM.net.
+DNS2.GUERNSEY.net. 604800 IN A 195.226.128.3
+NS1.BEACHSHORE.net. 604800 IN A 199.166.31.250
+HKUXB.HKU.HK. 604800 IN A 147.8.16.15
+NS.DOLEH.com. 604800 IN A 204.255.25.63
+NS.hactrn.net. 604800 IN A 216.254.68.12
+MALAKULA.BONDY.IRD.FR. 604800 IN A 193.50.53.1
+NS1.mediaone.net. 604800 IN A 24.128.1.80
+NS2.GPG.com. 604800 IN A 209.1.163.50
+noc.BelWue.de. 604800 IN A 129.143.2.1
+NS2.GIP.net. 604800 IN A 204.59.1.222
+RS.ISLES.net. 604800 IN A 212.100.224.90
+BOW.INTNET.GQ. 604800 IN A 195.101.152.253
+A.OPEN.BY. 604800 IN A 194.226.121.36
+us.i1.YIMG.com. 604800 IN CNAME a1.g.a.YIMG.com.
+athome.wetlogic.net. 604800 IN CNAME c1059495-a.snvl1.sfba.home.com.
+NS1.NIST.GOV. 604800 IN A 129.6.13.2
+mail.jerusalem-mail.com. 604800 IN A 216.251.232.93
+ISDSUN.cr.USGS.GOV. 604800 IN A 136.177.16.3
+NS.BOSTON.juno.com. 604800 IN A 64.136.25.53
+NS2.CADABRA.com. 604800 IN A 209.157.194.109
+nps.GOV. 604800 IN MX 10 ccmail2.itd.nps.GOV.
+nps.GOV. 604800 IN MX 5 ccmail.itd.nps.GOV.
+RELAY.HUJI.AC.IL. 604800 IN A 128.139.6.1
+styx.tahina.priv.at. 604800 IN A 194.152.163.253
+ISGATE.IS. 604800 IN A 193.4.58.51
+ns0.lux.dot-eu.org. 604800 IN A 195.206.105.102
+BILBO.NASK.ORG.PL. 604800 IN A 195.187.245.51
+BILBO.NASK.ORG.PL. 604800 IN A 148.81.16.51
+MAIL.TARSUS.com. 604800 IN A 208.130.9.252
+SUN.REDIRIS.ES. 604800 IN A 130.206.1.2
+NS2.NEASE.net. 604800 IN A 202.103.134.4
+OHCU.OH.MT.NP.ELS-GMS.att.net. 604800 IN A 199.191.144.75
+NS2.NF. 604800 IN A 203.12.249.101
+MIRAF-SERVER3.HONDUTEL.HN. 604800 IN A 206.48.104.142
+ns3.worldnet.att.net. 604800 IN A 204.127.160.1
+NS2.NETNAMES.net. 604800 IN A 212.53.77.28
+ITGBOX.IAT.CNR.IT. 604800 IN A 146.48.65.46
+NS2.ADELPHIA.net. 604800 IN A 24.48.62.35
+NS2.RIPN.net. 604800 IN A 195.209.0.6
+NS1.cinenet.net. 604800 IN A 198.147.76.65
+jengate.thur.de. 604800 IN A 193.174.15.34
+NOC.ULCC.JA.net. 604800 IN A 193.63.94.25
+NS.NOC.UZ. 604800 IN A 194.67.52.42
+NS0.JA.net. 604800 IN A 128.86.1.20
+NS0.JA.net. 604800 IN A 193.63.94.20
+NS2.INR.net. 604800 IN A 198.77.208.3
+netsage.org. 604800 IN A 209.67.235.38
+TERI.USP.AC.FJ. 604800 IN A 144.120.8.1
+NS2.NETSOL.com. 604800 IN A 198.17.208.71
+NS2.ABAC.com. 604800 IN A 216.55.144.4
+NS2.NIC.FR. 604800 IN A 192.93.0.4
+KANIN.ARNES.SI. 604800 IN A 193.2.1.66
+NS.EDU.GU. 604800 IN A 168.123.2.50
+DNS.INRIA.FR. 604800 IN A 193.51.208.13
+HEDNS1.GOOGLE.com. 604800 IN A 64.209.200.10
+asylum.sf.ca.us. 604800 IN A 192.48.232.17
+ACT2.ACT2000.net. 604800 IN A 207.42.132.227
+ICM1.ICP.net. 604800 IN A 192.94.207.66
+202.192.103.198.209.IN-ADDR.ARPA. 604800 IN PTR fraud.dd.org.
+ECSEL.jhuapl.EDU. 604800 IN A 128.244.65.29
+NS2.DCNY.DOUBLECLICK.net. 604800 IN A 204.253.104.10
+keith.netsage.org. 604800 IN A 209.67.235.37
+MANTA.OUTREMER.com. 604800 IN A 213.16.1.106
+NS2.globalnetisp.net. 604800 IN A 207.136.213.2
+NS2.CCSRS.net. 604800 IN A 206.253.214.73
+NS1.NL.CONCENTRIC.com. 604800 IN A 195.18.114.5
+NS2.VI.net. 604800 IN A 212.78.64.10
+NS2.NEO.net. 604800 IN A 206.109.7.65
+cgi.MERCURYCENTER.com. 604800 IN CNAME vh80167.vh8.infi.net.
+ORSTOM.RIO.net. 604800 IN A 192.33.151.1
+NS2.CONRADPROMOTIONS.com. 604800 IN A 208.24.118.203
+YARRINA.CONNECT.COM.AU. 604800 IN A 192.189.54.17
+dns03.OPS.usa.net. 604800 IN A 204.68.24.136
+APPSRV.HAITIWORLD.com. 604800 IN A 206.152.15.34
+NS.RELCOM.KZ. 604800 IN A 212.110.240.65
+NS1.MAGIC-MOMENTS.com. 604800 IN A 195.224.53.80
+NS.ALCATEL.com. 604800 IN A 192.160.6.91
+ns2.terra.net. 604800 IN A 199.103.128.2
+NS3.hotmail.com. 604800 IN A 209.185.130.68
+vtc.VSC.EDU. 604800 IN MX 0 eve.vtc.VSC.EDU.
+www.vmba.org. 604800 IN MX 10 gro.dd.org.
+NAHOURI.ONATEL.BF. 604800 IN A 206.82.130.195
+SERVER2.INFN.IT. 604800 IN A 131.154.1.3
+NS2.AI-R.com. 604800 IN A 66.33.4.51
+NS1.FREE.net. 604800 IN A 147.45.15.34
+vcmr-54.server.rpi.EDU. 604800 IN A 128.113.113.44
+haig.CS.UCL.AC.UK. 604800 IN A 128.16.6.8
+mail.nova-data.com. 604800 IN A 12.16.110.35
+MOEVAX.EDU.TW. 604800 IN A 140.111.1.2
+NS2.LTWCC.org. 604800 IN A 12.33.66.62
+NS.BA. 604800 IN A 195.130.35.5
+noc.HRZ.uni-bielefeld.de. 604800 IN A 129.70.5.16
+VANILLA.WRO.nps.GOV. 604800 IN A 165.83.71.3
+NS2.SZTAKI.HU. 604800 IN A 193.225.86.1
+SECIU.EDU.UY. 604800 IN A 164.73.128.5
+COL2.CARIBSURF.com. 604800 IN A 205.214.192.202
+NS2.QATAR.NET.QA. 604800 IN A 212.77.192.13
+NS2.E-SYNC.net. 604800 IN A 192.206.57.128
+ns1.eu.SUN.com. 604800 IN A 192.18.240.8
+NS1.UUSJ.DOUBLECLICK.net. 604800 IN A 204.176.177.10
+NS2.CUHK.EDU.HK. 604800 IN A 137.189.6.21
+NS1.MEITCA.com. 604800 IN A 137.203.5.1
+NS2.DSL.net. 604800 IN A 209.87.79.232
+techfac.techfak.uni-bielefeld.de. 604800 IN A 129.70.132.100
+listserv.performancediver.com. 604800 IN A 216.34.185.155
+foolusmf.D4P.net. 604800 IN CNAME a100.g.akamai.net.
+pedic-med.vrx.net. 604800 IN A 199.166.24.2
+GRUMPY.NET.NA. 604800 IN A 196.20.23.1
+BK.tifosi.com. 604800 IN A 208.58.189.13
+ns3.PAIR.com. 604800 IN A 209.68.1.15
+ns2.ar.com. 604800 IN A 64.124.80.42
+MASSIRA.ONPT.NET.MA. 604800 IN A 206.103.26.1
+NS.KBFI.EE. 604800 IN A 192.121.251.13
+ns3.Algebra.com. 604800 IN A 216.254.54.22
+faerber.muc.de. 604800 IN MX 10 slarti.muc.de.
+9.206.203.192.IN-ADDR.ARPA. 604800 IN PTR ice.WonderWorks.COM.
+PUKU.UNZA.ZM. 604800 IN A 196.7.240.1
+ATLNET.ATLONLINE.com. 604800 IN A 207.153.72.193
+Z1.NS.NYC1.GLOBIX.net. 604800 IN A 209.10.66.55
+www.hometownbands.com. 604800 IN A 209.67.235.38
+SIMON.CS.CORNELL.EDU. 604800 IN A 128.84.154.10
+EKEKO.RCPIP.net. 604800 IN A 209.45.127.2
+emerald.itnet.com.PL. 604800 IN A 195.116.64.3
+DNS1.ICS.FORTH.GR. 604800 IN A 139.91.151.70
+NS.ATL.BELLSOUTH.net. 604800 IN A 205.152.0.20
+ntp.ctr.COLUMBIA.EDU. 604800 IN CNAME sirius.ctr.COLUMBIA.EDU.
+NS2.GLOBECOMM.net. 604800 IN A 165.251.1.3
+UUNS1DNS1.FLONETWORK.com. 604800 IN A 209.167.79.5
+GRIN.GNOSH.net. 604800 IN A 216.15.87.207
+NS.DIGSYS.BG. 604800 IN A 192.92.129.1
+uunet.UU.net. 604800 IN MX 10 Mail.UU.net.
+ns1.vermontel.com. 604800 IN A 204.164.106.2
+NS2.GREENMOUNTAINACCESS.net. 604800 IN A 208.144.252.31
+38.241.5.198.IN-ADDR.ARPA. 604800 IN PTR cmr0.ash.ops.us.uu.net.
+NS1.NIC.UK. 604800 IN A 195.66.240.130
+DNS.FCCN.PT. 604800 IN A 193.136.192.10
+NS2.NIC.TJ. 604800 IN A 209.77.224.1
+NS4.NEWACCOUNT.com. 604800 IN A 209.78.16.6
+NS2.IHUG.NET.NZ. 604800 IN A 203.29.160.2
+NS.SIGNALZ.com. 604800 IN A 209.67.230.71
+DNS.NIC.AD. 604800 IN A 194.158.67.251
+3.2.39.137.IN-ADDR.ARPA. 604800 IN PTR New-York4.NY.ALTER.NET.
+UUCP-GW-2.PA.DEC.com. 604800 IN A 16.1.0.19
+NS.LANDLORDS.com. 604800 IN A 63.64.164.68
+NS2.EXODUS.net. 604800 IN A 207.82.198.150
+NS2.SCRUZ.net. 604800 IN A 165.227.2.10
+NS.PIPEX-SZ.net. 604800 IN A 196.15.232.19
+saturn.SUN.com. 604800 IN A 192.9.25.2
+e24.nc.us.IBM.com. 604800 IN A 32.97.136.230
+NMS.CYFRONET.KRAKOW.PL. 604800 IN A 149.156.1.3
+NS.TWNIC.net. 604800 IN A 192.83.166.11
+ns2.alcatel.NO. 604800 IN A 193.213.238.2
+INPAKSODNS.AKSO.nps.GOV. 604800 IN A 165.83.49.9
+mail.reptiles.org. 604800 IN A 198.96.117.157
+59.187.152.204.IN-ADDR.ARPA. 604800 IN PTR shell.nominum.com.
+ns1.mobydark.com. 604800 IN A 216.13.76.21
+NS.KG. 604800 IN A 195.38.160.36
+NS.SPB.SU. 604800 IN A 193.124.83.69
+PENDRAGON.CS.PURDUE.EDU. 604800 IN A 128.10.2.5
+NS1.IGC.APC.org. 604800 IN A 192.82.108.38
+USDNS.NIC.us. 604800 IN A 198.41.3.87
+NS2.WEBTRENDS.com. 604800 IN A 63.88.212.11
+URANUS.DAIMI.AAU.DK. 604800 IN A 130.225.16.40
+ANTANA.IRD.MG. 604800 IN A 194.214.107.1
+NS.JERSEY.juno.com. 604800 IN A 64.136.17.178
+NS2.INTERNET-TOOLS.com. 604800 IN A 206.109.113.140
+ns-tk012.ocn.AD.JP. 604800 IN A 203.139.160.74
+bvt-ext.gdarm.com. 604800 IN A 166.19.32.42
+NS1.ID. 604800 IN A 202.155.30.227
+NS2.MAHNET.net. 604800 IN A 207.219.173.132
+NS.ALCANET.COM.AU. 604800 IN A 203.62.196.10
+UTAMA.BOLNET.BO. 604800 IN A 166.114.1.40
+NS.CNC.AC.CN. 604800 IN A 159.226.1.1
+NS.KREN.NE.KR. 604800 IN A 147.47.1.1
+NS1.REDHAT.com. 604800 IN A 216.148.218.250
+db.rc.VIX.com. 604800 IN A 204.152.187.21
+198.103.198.209.IN-ADDR.ARPA. 604800 IN CNAME 198.192.103.198.209.IN-ADDR.ARPA.
+alf.pbks.PL. 604800 IN A 195.205.33.200
+FLAG.EP.net. 604800 IN A 198.32.4.13
+DNS2.IUNET.IT. 604800 IN A 192.106.1.31
+NS2.QUANTIFIED.net. 604800 IN A 63.212.171.3
+INTERNET-SERVER.ZURICH.IBM.com. 604800 IN A 195.212.119.252
+seaipsvcs.idx.com. 604800 IN A 172.22.64.42
+lebanon.valley.net. 604800 IN A 198.115.160.16
+SERVER.NORDU.net. 604800 IN A 193.10.252.19
+NS.NIC.DO. 604800 IN A 207.176.16.50
+isc-01.iscvt.org. 604800 IN A 207.136.209.131
+NAC.NO. 604800 IN A 129.240.2.40
+SAVA.UTIC.NET.BA. 604800 IN A 195.130.35.3
+NS1.TOKYO.JP.NETDNS.com. 604800 IN A 64.56.164.118
+NETSERV2.ITS.rpi.EDU. 604800 IN A 128.113.1.3
+IFI.UIO.NO. 604800 IN A 129.240.64.2
+www.TOAPLAN.com. 604800 IN A 216.42.31.169
+ns2.the-frontier.org. 604800 IN A 216.86.199.115
+NS.UNAM.MX. 604800 IN A 132.248.253.1
+ARISTO.TAU.AC.IL. 604800 IN A 132.66.32.10
+DNS.CS.WISC.EDU. 604800 IN A 128.105.2.10
+NS1.NIC.IR. 604800 IN A 194.225.70.83
+NS1.RETINA.AR. 604800 IN A 200.10.202.3
+mailer.connriver.net. 604800 IN A 63.93.137.13
+NS.ATI.TN. 604800 IN A 193.95.66.10
+NS2.CLEAR.NET.NZ. 604800 IN A 203.97.37.14
+NS4.EARTHLINK.net. 604800 IN A 209.179.179.19
+mejac.palo-alto.ca.us. 604800 IN A 192.147.236.1
+New-York4.NY.ALTER.net. 604800 IN A 137.39.2.3
+New-York4.NY.ALTER.net. 604800 IN A 137.39.126.10
+falcon.tallship.net. 604800 IN A 208.179.112.2
+ZEUS.CC.UCY.AC.CY. 604800 IN A 194.42.1.1
+NS2.SECURE.net. 604800 IN A 161.58.9.10
+NS0.FLIRBLE.org. 604800 IN A 195.40.6.20
+dns.zenon.net. 604800 IN A 195.2.83.107
+SERVIDOR.MICROASTUR.ES. 604800 IN A 195.76.178.5
+DOWNSTAGE.MCS.VUW.AC.NZ. 604800 IN A 130.195.6.10
+ns2.GNAC.com. 604800 IN A 209.182.195.77
+PRIFI.EUNET.FI. 604800 IN A 193.66.1.146
+ns2.k12.vt.us. 604800 IN A 170.222.64.130
+ns2.nic.mnet. 604800 IN A 208.109.83.110
+NS0.PIPEX.net. 604800 IN A 158.43.128.8
+NS1.SANFRANCISCO.US.NETDNS.com. 604800 IN A 207.82.50.166
+AMRA.NIC.GOV.JO. 604800 IN A 193.188.66.103
+kw.com.CN. 604800 IN MX 15 mail2.kw.com.CN.
+SHNS.163.net. 604800 IN A 61.129.65.108
+NS.ER.USGS.GOV. 604800 IN A 130.11.48.2
+FAITH.MYNET.net. 604800 IN A 207.13.11.2
+mail.smuggs.com. 604800 IN A 209.67.230.71
+MIMOS.MY. 604800 IN A 192.228.128.18
+NS.GU. 604800 IN A 168.123.4.10
+mx00.schlund.de. 604800 IN A 195.20.224.67
+mx00.schlund.de. 604800 IN A 195.20.224.68
+mx00.schlund.de. 604800 IN A 195.20.224.130
+mx00.schlund.de. 604800 IN A 195.20.224.152
+mx00.schlund.de. 604800 IN A 195.20.224.198
+CADDSYS.IPTEK.net. 604800 IN A 202.46.1.2
+NS0.TELIA.NIC.NU. 604800 IN A 212.181.91.4
+NS2.GRANITECANYON.com. 604800 IN A 204.1.217.148
+GATEKEEPER.corning.com. 604800 IN A 149.42.1.2
+NS2.2DAY.com. 604800 IN A 202.89.128.74
+1.0.0.127.IN-ADDR.ARPA. 604800 IN PTR localhost.
+RAIN.PSG.com. 604800 IN A 147.28.0.34
+STRAWB.MIT.EDU. 604800 IN A 18.71.0.151
+NS2.DIGISERVE.com. 604800 IN A 204.91.84.216
+UMACSN2.UMAC.MO. 604800 IN A 161.64.3.2
+NS.JM. 604800 IN A 196.2.1.6
+12.153.66.206.IN-ADDR.ARPA. 604800 IN PTR d.dd.org.
+EAST.ISI.EDU. 604800 IN A 38.245.76.2
+NS2.UUNET.CA. 604800 IN A 142.77.1.5
+SUNNY.STAT-USA.GOV. 604800 IN A 192.239.70.8
+BOW.INTNET.CF. 604800 IN A 194.206.73.253
+NS4.TELE.DK. 604800 IN A 194.239.134.84
+NS2.sodak.net. 604800 IN A 63.65.239.225
+NS1.NEWYORK.US.NETDNS.com. 604800 IN A 216.32.212.86
+NS2.PSI.net. 604800 IN A 38.8.50.2
+NS.KREONET.RE.KR. 604800 IN A 134.75.30.1
+GIANT.MINDLINK.net. 604800 IN A 204.174.18.2
+NS0.SECTOR001.org. 604800 IN A 24.4.49.117
+DNS.SEABONE.net. 604800 IN A 195.22.205.163
+NS2.MANA.PF. 604800 IN A 202.3.225.20
+NRWEB.CENPAC.NET.NR. 604800 IN A 203.98.224.66
+www.TRAVELPHOTOCONTESTS.com. 604800 IN A 64.85.86.156
+NS1.REGEX.com. 604800 IN A 202.152.12.227
+BIGBIRD.ITD.nps.GOV. 604800 IN A 165.83.208.5
+CUNIXD.CC.COLUMBIA.EDU. 604800 IN A 128.59.35.142
+NS1.CLASSIFIEDMONSTER.com. 604800 IN A 216.254.54.22
+SERVER1.SANS.org. 604800 IN A 167.216.133.33
+BRONZE.COIL.com. 604800 IN A 198.4.94.1
+SCSNMS.SWITCH.CH. 604800 IN A 130.59.1.30
+SCSNMS.SWITCH.CH. 604800 IN A 130.59.10.30
+SCE.CNC.UNA.PY. 604800 IN A 200.10.228.133
+RELAY.LA.TIS.com. 604800 IN A 198.51.22.11
+NS.AUSTIN.IBM.com. 604800 IN A 192.35.232.34
+SERVICE.robert-morris.EDU. 604800 IN A 205.146.48.22
+MERCURY.ML.org. 604800 IN A 209.68.0.85
+proxy.pccf.net. 604800 IN A 205.189.73.123
+DUB-NAME-SVC-1.compuserve.com. 604800 IN A 149.174.213.5
+NS.CNRI.reston.va.us. 604800 IN A 132.151.1.1
+NS.UCAD.SN. 604800 IN A 196.1.95.1
+ns01.ny.us.ibm.net. 604800 IN A 165.87.194.244
+NS4-AUTH.ALASKA.net. 604800 IN A 209.112.130.4
+BOW.INTNET.NE. 604800 IN A 194.51.164.253
+NS-JP.SINET.AD.JP. 604800 IN A 150.100.2.3
+ns.musin.de. 604800 IN A 194.113.40.45
+ip1.romkey.SEG.net. 604800 IN A 207.121.69.234
+DNS2.ITD.UMICH.EDU. 604800 IN A 141.211.125.15
+mail.rpi.EDU. 604800 IN A 128.113.100.7
+INECO.NIC.ES. 604800 IN A 194.69.254.2
+DNS2.FIREHOUSE.net. 604800 IN A 63.160.175.18
+BOW.INTNET.BJ. 604800 IN A 194.51.163.253
+sundown.vtc.VSC.EDU. 604800 IN A 155.42.12.12
+NIC.AIX.GR. 604800 IN A 195.130.89.210
+NIC.AD.JP. 604800 IN A 202.12.30.33
+NS.DC.IGC.org. 604800 IN A 199.75.208.10
+LHR.NS.GDNS.net. 604800 IN A 212.250.25.101
+NS2.WEBMAGIC.net. 604800 IN A 64.168.49.66
+MUNNARI.OZ.AU. 604800 IN A 128.250.1.21
+HIPPO.RU.AC.ZA. 604800 IN A 146.231.128.1
+PEBBLES.IOM.com. 604800 IN A 194.72.124.1
+penpal.dmz.RPSLMC.EDU. 604800 IN A 144.74.60.151
+netnews.HINET.net. 604800 IN A 168.95.195.16
+INS2.TOSA.TWTELECOM.net. 604800 IN A 204.95.160.4
+proxy6.cisco.com. 604800 IN A 203.41.198.245
+NS2.HOST4U.net. 604800 IN A 209.150.129.3
+POIPARAU.OYSTER.NET.CK. 604800 IN A 202.65.32.127
+NS-EXT.VIX.com. 604800 IN A 204.152.184.64
+NS2.NURSAT.net. 604800 IN A 212.13.167.1
+mail2.kw.com.CN. 604800 IN A 159.226.25.8
+NS-02B.ANS.net. 604800 IN A 207.24.245.178
+DNS.RCCN.net. 604800 IN A 193.136.7.17
+B.ROOT-SERVERS.ORSC. 604800 IN A 216.13.126.116
+FIREHOUSE.net. 604800 IN A 63.160.175.19
diff --git a/bin/tests/system/cacheclean/ns1/example.db b/bin/tests/system/cacheclean/ns1/example.db
new file mode 100644
index 0000000..54db5a1
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/example.db
@@ -0,0 +1,2950 @@
+; 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: example.db,v 1.5 2007/06/19 23:47:00 tbox Exp $
+
+$TTL 999999
+$ORIGIN .
+. IN SOA hostmaster.nominum.com. a.root-servers.nil. (
+ 2000042100
+ 600
+ 600
+ 1200
+ 600
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil IN A 10.53.0.1
+localhost IN A 127.0.0.1
+$ORIGIN NIC.AC.
+NS IN A 194.205.62.120
+$ORIGIN AD.
+DNS2 IN A 194.158.64.8
+DINIS IN A 194.158.64.7
+$ORIGIN NIC.AD.
+DNS IN A 194.158.67.251
+$ORIGIN STA.AD.
+CORREU IN A 194.158.67.1
+$ORIGIN EMIRATES.NET.AE.
+NS2 IN A 194.170.1.7
+NS1 IN A 194.170.1.6
+$ORIGIN BA.
+NS IN A 195.130.35.5
+$ORIGIN UTIC.NET.BA.
+SAVA IN A 195.130.35.3
+$ORIGIN OFFSHORE.AI.
+NS1 IN A 209.88.68.34
+$ORIGIN BD.
+DNS1 IN A 209.58.24.5
+DNS IN A 209.58.24.3
+$ORIGIN MENTOR.BE.
+APHEX IN A 193.121.64.5
+$ORIGIN EUNET.BE.
+SECDNS IN A 193.74.208.139
+$ORIGIN BELNET.BE.
+NS IN A 193.190.198.10
+ IN A 193.190.198.2
+$ORIGIN DNS.BE.
+MASTER IN A 194.7.171.243
+$ORIGIN CS.KULEUVEN.AC.BE.
+DNS IN A 134.58.40.4
+$ORIGIN CURINFO.AN.
+NS01-SERVER IN A 200.44.117.129
+KADUSHI IN A 200.44.117.130
+$ORIGIN ONATEL.BF.
+NAHOURI IN A 206.82.130.195
+$ORIGIN DIGSYS.BG.
+NS IN A 192.92.129.1
+$ORIGIN BATELCO.COM.BH.
+SV10 IN A 193.188.124.227
+NS2 IN A 193.188.97.212
+NS IN A 193.188.97.197
+$ORIGIN UTORONTO.CA.
+ns2 IN A 128.100.102.202
+ns1 IN A 128.100.100.129
+chime IN A 128.100.102.201
+$ORIGIN cs.UTORONTO.CA.
+bay IN A 128.100.1.1
+$ORIGIN UTCC.UTORONTO.CA.
+DNS2 IN A 128.100.102.201
+$ORIGIN UUNET.CA.
+NS2 IN A 142.77.1.5
+NS IN A 142.77.1.1
+$ORIGIN CIRA.CA.
+MERLE IN A 64.26.149.98
+$ORIGIN cmc.ec.gc.CA.
+castor IN A 142.135.4.14
+$ORIGIN RISQ.QC.CA.
+CLOUSO IN A 192.26.210.1
+$ORIGIN MBNET.MB.CA.
+ACCESS IN A 130.179.16.143
+$ORIGIN CDNNET.CA.
+RELAY IN A 192.73.5.1
+$ORIGIN uwaterloo.CA.
+ns2 IN A 129.97.128.100
+math IN A 129.97.140.144
+ IN A 129.97.216.42
+ IN MX 0 math.uwaterloo.ca.
+ns1 IN A 129.97.128.10
+$ORIGIN AR.
+CTINA IN A 200.16.97.17
+ATHEA IN A 200.16.98.2
+$ORIGIN NIC.AR.
+TULKU IN A 200.16.97.77
+$ORIGIN RETINA.AR.
+NS1 IN A 200.10.202.3
+$ORIGIN INTNET.BJ.
+BOW IN A 194.51.163.253
+$ORIGIN NIC.CD.
+DNS IN A 194.38.74.11
+$ORIGIN tahina.priv.at.
+styx IN A 194.152.163.253
+$ORIGIN UNIVIE.AC.at.
+NS2 IN A 193.171.255.66
+NS7 IN A 194.246.96.192
+NS1 IN A 193.171.255.2
+$ORIGIN OZ.AU.
+MUNNARI IN A 128.250.1.21
+$ORIGIN CS.MU.OZ.AU.
+MULGA IN A 128.250.1.22
+ IN A 128.250.37.150
+$ORIGIN AARNET.EDU.AU.
+JATZ IN A 139.130.204.4
+$ORIGIN ANU.EDU.AU.
+CHEOPS IN A 150.203.224.24
+$ORIGIN CS.UOW.EDU.AU.
+WRAITH IN A 130.130.64.1
+$ORIGIN ALCANET.COM.AU.
+NS IN A 203.62.196.10
+$ORIGIN CONNECT.COM.AU.
+YARRINA IN A 192.189.54.17
+$ORIGIN IBL.BM.
+NS1 IN A 199.172.192.1
+$ORIGIN BRUNET.BN.
+JTB IN A 202.160.8.2
+$ORIGIN INTNET.CF.
+BOW IN A 194.206.73.253
+$ORIGIN SETARNET.AW.
+NS2 IN A 206.48.100.11
+NS1 IN A 206.48.100.5
+$ORIGIN BOLNET.BO.
+UTAMA IN A 166.114.1.40
+$ORIGIN SWITCH.CH.
+SCSNMS IN A 130.59.1.30
+ IN A 130.59.10.30
+MERAPI IN A 130.59.211.10
+$ORIGIN ITU.CH.
+NS IN A 156.106.192.121
+$ORIGIN NIC.CH.
+DOMREG IN A 130.59.1.80
+$ORIGIN ip6.INT.
+z IN A 198.32.2.66
+ IN AAAA 3ffe:0:1::c60:242
+$ORIGIN DNS.BR.
+NS2 IN A 200.19.119.99
+NS1 IN A 200.255.253.234
+NS IN A 143.108.23.2
+$ORIGIN OYSTER.NET.CK.
+POIPARAU IN A 202.65.32.127
+PARAU IN A 202.65.32.128
+$ORIGIN DRUKNET.NET.BT.
+NS IN A 202.144.128.200
+$ORIGIN DCC.UCHILE.CL.
+NS IN A 146.83.5.204
+$ORIGIN NIC.CL.
+NS IN A 146.83.4.11
+$ORIGIN FIRSTCOM.CL.
+NS IN A 200.27.2.2
+$ORIGIN EDU.
+ISI IN A 128.9.176.32
+UMASS IN MX 20 vcmr-54.server.rpi.edu.
+ IN MX 1 mail.rpi.edu.
+dartmouth IN A 129.170.16.6
+ IN MX 10 donner.dartmouth.edu.
+ IN MX 10 prancer.dartmouth.edu.
+ IN MX 10 vixen.dartmouth.edu.
+ IN MX 10 blitzen.dartmouth.edu.
+ IN MX 0 mailhub.dartmouth.edu.
+ IN MX 10 dasher.dartmouth.edu.
+rush IN MX 30 penpal.dmz.rpslmc.edu.
+ IN MX 10 detox.cc1.rpslmc.edu.
+ IN MX 20 rush.cc1.rpslmc.edu.
+NYU IN A 128.122.253.92
+GATECH IN A 130.207.244.244
+ARIZONA IN A 128.196.128.233
+stanford IN A 171.64.14.120
+ IN MX 20 Leland.stanford.edu.
+ IN MX 20 Leland2.stanford.edu.
+ IN MX 20 Leland3.stanford.edu.
+$ORIGIN jhuapl.EDU.
+ECSEL IN A 128.244.65.29
+APLDNS2 IN A 128.244.194.100
+ABACUS IN A 128.244.197.32
+$ORIGIN MIT.EDU.
+STRAWB IN A 18.71.0.151
+W20NS IN A 18.70.0.160
+BITSY IN A 18.72.0.3
+$ORIGIN ITD.UMICH.EDU.
+DNS2 IN A 141.211.125.15
+$ORIGIN ISI.EDU.
+EAST IN A 38.245.76.2
+VENERA IN A 128.9.176.32
+NS IN A 128.9.128.127
+$ORIGIN CS.PURDUE.EDU.
+PENDRAGON IN A 128.10.2.5
+$ORIGIN CS.WISC.EDU.
+DNS IN A 128.105.2.10
+$ORIGIN UMD.EDU.
+TRANTOR IN A 128.8.10.14
+$ORIGIN RPSLMC.EDU.
+THUMPER IN A 144.74.22.8
+$ORIGIN dmz.RPSLMC.EDU.
+penpal IN A 144.74.60.151
+$ORIGIN cc1.RPSLMC.EDU.
+rush IN A 144.74.150.23
+detox IN A 144.74.150.44
+$ORIGIN IS.RPSLMC.EDU.
+SUNSTROKE IN A 144.74.21.8
+$ORIGIN VSC.EDU.
+vtc IN MX 0 eve.vtc.vsc.edu.
+MAZE IN A 155.42.1.89
+ENIGMA IN A 155.42.1.7
+$ORIGIN vtc.VSC.EDU.
+sundown IN A 155.42.12.12
+eve IN A 155.42.12.102
+$ORIGIN UMASS.EDU.
+NS1 IN A 128.119.166.14
+NIC IN A 128.119.175.14
+$ORIGIN oit.UMASS.EDU.
+supai IN A 128.119.175.6
+ponzi IN A 128.119.166.18
+$ORIGIN ECS.UMASS.EDU.
+KIRA IN A 128.119.91.10
+$ORIGIN CS.UMASS.EDU.
+UNIX1 IN A 128.119.40.12
+$ORIGIN UPR.CLU.EDU.
+UPR1 IN A 136.145.1.4
+$ORIGIN PRINCETON.EDU.
+DNS IN A 128.112.129.15
+$ORIGIN rpi.EDU.
+mail IN A 128.113.100.7
+$ORIGIN server.rpi.EDU.
+vcmr-54 IN A 128.113.113.44
+$ORIGIN acs.rpi.EDU.
+freefour IN A 128.113.24.91
+$ORIGIN ITS.rpi.EDU.
+NETSERV2 IN A 128.113.1.3
+NETSERV1 IN A 128.113.1.5
+$ORIGIN uvm.EDU.
+NS1 IN A 132.198.201.10
+NS2 IN A 132.198.202.10
+$ORIGIN dartmouth.EDU.
+dasher IN A 129.170.208.6
+mailhub IN A 129.170.16.6
+donner IN A 129.170.208.3
+prancer IN A 129.170.208.2
+vixen IN A 129.170.208.15
+NS1 IN A 129.170.17.4
+blitzen IN A 129.170.208.4
+NS2 IN A 129.170.16.4
+$ORIGIN middlebury.EDU.
+CATAMOUNT IN A 140.233.2.204
+LION IN A 140.233.1.4
+$ORIGIN CIT.CORNELL.EDU.
+DNS IN A 192.35.82.50
+$ORIGIN CS.CORNELL.EDU.
+SIMON IN A 128.84.154.10
+$ORIGIN BERKELEY.EDU.
+NS2 IN A 128.32.136.12
+ IN A 128.32.206.12
+NS1 IN A 128.32.136.9
+ IN A 128.32.206.9
+$ORIGIN CS.BERKELEY.EDU.
+VANGOGH IN A 128.32.33.5
+$ORIGIN ctr.COLUMBIA.EDU.
+ntp IN CNAME sirius.ctr.columbia.edu.
+sirius IN A 128.59.64.60
+$ORIGIN CC.COLUMBIA.EDU.
+CUNIXD IN A 128.59.35.142
+$ORIGIN UOREGON.EDU.
+PHLOEM IN A 128.223.32.35
+$ORIGIN GATECH.EDU.
+TROLL-GW IN A 130.207.244.251
+$ORIGIN CC.GATECH.EDU.
+BURDELL IN A 130.207.3.207
+$ORIGIN UTK.EDU.
+NS0 IN A 160.36.0.66
+NS1 IN A 160.36.128.66
+$ORIGIN robert-morris.EDU.
+SERVICE IN A 205.146.48.22
+COLONIAL-SERVER IN A 205.146.48.25
+$ORIGIN CNS.vt.EDU.
+YARDBIRD IN A 198.82.247.34
+MILO IN A 198.82.247.98
+$ORIGIN stanford.EDU.
+Leland2 IN A 171.64.14.58
+AVALLONE IN A 171.64.2.210
+ATALANTE IN A 171.64.2.220
+ARGUS IN A 171.64.2.230
+$ORIGIN slac.stanford.EDU.
+SMTP IN A 134.79.18.80
+NS2 IN A 134.79.16.10
+NS1 IN A 134.79.16.9
+$ORIGIN HARVARD.EDU.
+NS2 IN A 128.103.1.1
+ns IN A 128.103.201.100
+NS1 IN A 128.103.200.101
+$ORIGIN med.HARVARD.EDU.
+jenner IN A 134.174.141.2
+knight IN A 134.174.141.46
+eno IN A 134.174.141.50
+heckle IN A 134.174.146.152
+$ORIGIN de.
+datingagentur IN A 212.227.216.57
+ IN MX 10 mx01.schlund.de.
+ IN MX 10 mx00.schlund.de.
+$ORIGIN schlund.de.
+mx00 IN A 195.20.224.130
+ IN A 195.20.224.198
+ IN A 195.20.224.67
+ IN A 195.20.224.68
+ IN A 195.20.224.152
+ns4 IN A 195.20.225.36
+mx01 IN A 195.20.224.131
+ IN A 195.20.224.236
+ IN A 195.20.224.237
+ IN A 195.20.224.238
+ns3 IN A 195.20.224.95
+$ORIGIN Informatik.Uni-Dortmund.de.
+waldorf IN A 129.217.4.42
+$ORIGIN muc.de.
+faerber IN MX 10 slarti.muc.de.
+ IN A 193.149.49.70
+ns2 IN A 193.149.48.2
+slarti IN A 193.149.48.10
+ns1 IN A 193.149.48.11
+$ORIGIN westfalen.de.
+muenster IN A 193.174.5.2
+$ORIGIN lan-ks.de.
+uranus IN A 194.45.71.1
+$ORIGIN kaben-net.de.
+dns IN A 195.179.28.17
+$ORIGIN thur.de.
+jengate IN A 193.174.15.34
+$ORIGIN erfurt.thur.de.
+annwfn IN A 194.122.210.3
+$ORIGIN sgh-net.de.
+ns1 IN A 212.86.129.142
+$ORIGIN DENIC.de.
+SSS-NL IN A 193.0.0.237
+SSS-AT IN A 193.171.255.34
+DNS IN A 194.246.96.79
+$ORIGIN iks-jena.de.
+avalon IN A 194.221.90.34
+$ORIGIN musin.de.
+ns IN A 194.113.40.45
+$ORIGIN rrz.Uni-Koeln.de.
+noc IN A 134.95.100.209
+$ORIGIN BelWue.de.
+noc IN A 129.143.2.1
+$ORIGIN HRZ.uni-bielefeld.de.
+noc IN A 129.70.5.16
+$ORIGIN techfak.uni-bielefeld.de.
+techfac IN A 129.70.132.100
+$ORIGIN CUBE.de.
+NS1 IN A 212.162.54.243
+$ORIGIN dtag.de.
+pns IN A 194.25.0.125
+$ORIGIN netconx.de.
+netconsult IN A 193.141.75.1
+$ORIGIN CAMNET.CM.
+KIM IN A 195.24.192.35
+LOM IN A 195.24.192.34
+SANAGA IN A 195.24.192.17
+$ORIGIN sxtyptt.NET.CN.
+ns IN A 202.99.192.68
+$ORIGIN sta.NET.CN.
+ns IN A 202.96.199.133
+$ORIGIN BTA.NET.CN.
+NS IN A 202.96.0.133
+$ORIGIN CNNIC.NET.CN.
+sld-ns2 IN A 202.97.16.197
+DNS2 IN A 202.97.16.196
+sld-ns1 IN A 159.226.1.3
+$ORIGIN com.CN.
+kw IN MX 15 mail2.kw.com.cn.
+$ORIGIN kw.com.CN.
+mail2 IN A 159.226.25.8
+ns IN A 159.226.25.8
+$ORIGIN CNC.AC.CN.
+NS IN A 159.226.1.1
+$ORIGIN UNIANDES.EDU.CO.
+AYAX IN A 157.253.50.30
+CDCNET IN A 157.253.1.13
+$ORIGIN SCSI.GOV.BY.
+SUN IN A 195.50.5.103
+NS2 IN A 194.67.193.130
+$ORIGIN OPEN.BY.
+A IN A 194.226.121.36
+$ORIGIN CR.
+NS IN A 163.178.8.2
+$ORIGIN UCR.AC.CR.
+NS IN A 163.178.88.2
+$ORIGIN INTNET.DJ.
+BOW IN A 193.251.143.253
+$ORIGIN DARENET.DK.
+NS-SOA IN A 130.226.1.4
+$ORIGIN TELE.DK.
+NS4 IN A 194.239.134.84
+$ORIGIN DAIMI.AAU.DK.
+URANUS IN A 130.225.16.40
+$ORIGIN DK-HOSTMASTER.DK.
+NS IN A 193.163.102.2
+$ORIGIN EC.
+ECNET IN A 157.100.45.2
+$ORIGIN NET.EC.
+ECUA IN A 157.100.1.2
+$ORIGIN CENIAI.NET.CU.
+NS IN A 169.158.128.136
+$ORIGIN EENET.EE.
+NS IN A 193.40.56.245
+$ORIGIN KBFI.EE.
+NS IN A 192.121.251.13
+$ORIGIN NIC.DO.
+NS IN A 207.176.16.50
+$ORIGIN EUN.EG.
+FRCU IN A 193.227.1.1
+$ORIGIN CIX.CX.
+NS IN A 195.222.235.216
+$ORIGIN CX.ESCROW.IOCOMM.NET.CX.
+NS1 IN A 203.132.96.2
+$ORIGIN CCS.UCY.AC.CY.
+NICOSIA IN A 194.42.6.97
+$ORIGIN CC.UCY.AC.CY.
+ZEUS IN A 194.42.1.1
+$ORIGIN EUNET.CZ.
+CZ IN A 193.85.3.130
+$ORIGIN EUNET.FI.
+PRIFI IN A 193.66.1.146
+$ORIGIN NIXU.FI.
+NS IN A 193.209.237.29
+$ORIGIN TELE.FI.
+NS IN A 193.210.19.19
+$ORIGIN HELSINKI.FI.
+HYDRA IN A 128.214.4.29
+$ORIGIN INET.GA.
+KOMO IN A 208.148.44.1
+$ORIGIN CERIST.DZ.
+DECST IN A 193.194.64.11
+$ORIGIN ELDJAZAIR.NET.DZ.
+CASBAH IN A 193.194.81.45
+$ORIGIN USP.AC.FJ.
+TERI IN A 144.120.8.1
+$ORIGIN EUNET.ES.
+NS IN A 193.127.1.11
+$ORIGIN NIC.ES.
+INECO IN A 194.69.254.2
+NS1 IN A 194.69.254.1
+$ORIGIN VISUALCOM.ES.
+NS IN A 194.143.202.202
+$ORIGIN MICROASTUR.ES.
+SERVIDOR IN A 195.76.178.5
+$ORIGIN CESCA.ES.
+PRADES IN A 192.94.163.152
+$ORIGIN PIXAR.ES.
+NS IN A 194.143.196.3
+$ORIGIN REDIRIS.ES.
+SUN IN A 130.206.1.2
+$ORIGIN SEKER.ES.
+CORREOS IN A 194.179.87.1
+$ORIGIN TELECOM.NET.ET.
+NS IN A 196.27.22.43
+$ORIGIN FM.
+FM03 IN A 206.49.89.4
+FM01 IN A 206.49.89.2
+$ORIGIN NPLUS.GF.
+NS1 IN A 195.6.144.3
+$ORIGIN trns.
+f IN A 209.133.38.16
+d IN A 207.112.147.14
+e IN A 145.89.234.7
+c IN A 212.172.21.254
+a IN A 64.6.65.10
+$ORIGIN IRD.FR.
+NS IN A 195.83.14.1
+$ORIGIN BONDY.IRD.FR.
+MALAKULA IN A 193.50.53.1
+$ORIGIN RAIN.FR.
+BOW IN A 194.51.3.49
+$ORIGIN imag.FR.
+isis IN A 129.88.32.24
+imag IN A 129.88.30.1
+$ORIGIN INRIA.FR.
+DNS IN A 193.51.208.13
+$ORIGIN NIC.FR.
+NS2 IN A 192.93.0.4
+NS1 IN A 192.93.0.1
+NS3 IN A 192.134.0.49
+$ORIGIN GH.GL.
+KAASASSUK IN A 194.177.232.3
+$ORIGIN TELE.GL.
+TGSERV IN A 194.177.224.7
+$ORIGIN COMMIT.GM.
+NS1 IN A 63.77.152.177
+$ORIGIN MRC.GM.
+NS1 IN A 212.60.69.1
+$ORIGIN INTNET.GQ.
+BOW IN A 195.101.152.253
+$ORIGIN AIX.GR.
+NIC IN A 195.130.89.210
+$ORIGIN GRNET.GR.
+FOO IN A 194.177.210.211
+NIC IN A 194.177.210.210
+$ORIGIN CSI.FORTH.GR.
+ESTIA IN A 139.91.191.3
+$ORIGIN ICS.FORTH.GR.
+DNS1 IN A 139.91.151.70
+GRDNS IN A 139.91.1.1
+$ORIGIN HKU.HK.
+HKUXB IN A 147.8.16.15
+$ORIGIN CUHK.EDU.HK.
+NS2 IN A 137.189.6.21
+NS1 IN A 137.189.6.1
+$ORIGIN CONCYT.GOB.GT.
+NS IN A 168.234.106.2
+$ORIGIN UVG.EDU.GT.
+NS IN A 168.234.68.2
+$ORIGIN ID.
+NS1 IN A 202.155.30.227
+$ORIGIN AC.ID.
+NS IN A 202.159.124.34
+$ORIGIN GU.
+NS IN A 168.123.4.10
+$ORIGIN EDU.GU.
+NS IN A 168.123.2.50
+$ORIGIN REGISTRY.HM.
+NS2 IN A 209.54.168.55
+NS3 IN A 202.169.102.24
+NS1 IN A 204.144.183.78
+$ORIGIN CONNECT.IE.
+AUTH01 IN A 194.106.128.50
+$ORIGIN DOMAINREGISTRY.IE.
+BANBA IN A 193.1.142.2
+$ORIGIN VIA-NET-WORKS.IE.
+ICE IN A 212.17.32.2
+$ORIGIN HONDUTEL.HN.
+MIRAF-SERVER3 IN A 206.48.104.142
+$ORIGIN SRCE.HR.
+DNS IN A 161.53.3.7
+$ORIGIN HUJI.AC.IL.
+RELAY IN A 128.139.6.1
+$ORIGIN TAU.AC.IL.
+ARISTO IN A 132.66.32.10
+$ORIGIN NIC.JE.
+NS1 IN A 216.110.45.224
+$ORIGIN SZTAKI.HU.
+NS2 IN A 193.225.86.1
+$ORIGIN NIC.HU.
+NS IN A 193.6.27.62
+$ORIGIN NCST.ERNET.IN.
+NAAMAK IN A 202.41.110.66
+SS585 IN A 202.141.150.18
+$ORIGIN NIC.IO.
+NS IN A 194.205.62.100
+$ORIGIN NIC.IR.
+NS1 IN A 194.225.70.83
+$ORIGIN IS.
+ISGATE IN A 193.4.58.51
+$ORIGIN IUNET.IT.
+DNS2 IN A 192.106.1.31
+NS IN A 192.106.1.1
+$ORIGIN INFN.IT.
+SERVER2 IN A 131.154.1.3
+$ORIGIN CNR.IT.
+NAMESERVER IN A 194.119.192.34
+$ORIGIN IAT.CNR.IT.
+ITGBOX IN A 146.48.65.46
+$ORIGIN NETTUNO.IT.
+BOLOGNA IN A 193.43.2.5
+$ORIGIN NIC.IT.
+DNS IN A 193.205.245.5
+$ORIGIN JM.
+NS IN A 196.2.1.6
+$ORIGIN CAST.EDU.JM.
+NS IN A 200.9.115.2
+$ORIGIN NIC.GOV.JO.
+AMRA IN A 193.188.66.103
+PETRA IN A 193.188.66.2
+$ORIGIN KG.
+NS IN A 195.38.160.36
+$ORIGIN AD.JP.
+NIC IN A 202.12.30.33
+$ORIGIN ocn.AD.JP.
+ns-tk012 IN A 203.139.160.74
+$ORIGIN IIJ.AD.JP.
+NS0 IN A 202.232.2.34
+$ORIGIN SINET.AD.JP.
+NS-JP IN A 150.100.2.3
+$ORIGIN SPIN.AD.JP.
+DNS0 IN A 165.76.0.98
+$ORIGIN NIC.AD.JP.
+ns2 IN A 202.12.30.133
+TRF IN A 192.41.192.2
+NS-JP IN A 61.120.151.100
+NS0 IN A 202.12.30.131
+ns1 IN A 202.12.30.33
+$ORIGIN WIDE.AD.JP.
+NS IN A 203.178.136.63
+$ORIGIN co.JP.
+ IN MX 10 integra.s-integra.co.jp.
+$ORIGIN s-integra.co.JP.
+integra IN A 210.162.202.34
+$ORIGIN UUCP.NE.JP.
+NS2 IN A 210.141.111.69
+$ORIGIN DNS.NET.KH.
+NS1 IN A 203.127.100.21
+$ORIGIN org.
+netsage IN A 209.67.235.38
+ietf IN A 132.151.1.19
+ IN MX 10 odin.ietf.org.
+vmba IN MX 10 gro.dd.org.
+bnfinfo IN MX 10 mail.sover.net.
+ IN MX 20 mqueue.sover.net.
+dd IN MX 10 gro.dd.org.
+ IN MX 50 mqueue.sover.net.
+ IN MX 100 mail.uu.net.
+vtvast IN A 207.217.96.38
+ IN A 207.217.96.39
+ IN A 207.217.96.40
+ IN A 207.217.96.41
+ IN A 207.217.96.42
+ IN A 207.217.96.43
+ IN A 207.217.96.44
+ IN A 207.217.96.45
+ IN A 207.217.96.28
+ IN A 207.217.96.29
+ IN A 207.217.96.30
+ IN A 207.217.96.31
+ IN A 207.217.96.32
+ IN A 207.217.96.33
+ IN A 207.217.96.34
+ IN A 207.217.96.35
+ IN A 207.217.96.36
+ IN A 207.217.96.37
+ IN MX 10 vipmailgate.earthlink.net.
+gazpacho IN A 209.67.235.38
+bikeclub IN MX 20 pop.shoreham.net.
+ IN MX 50 smtp.america.net.
+giffordmed IN A 130.189.100.57
+ IN MX 20 quest-net.com.
+ IN MX 10 mail.giffordmed.org.
+isc IN A 204.152.184.101
+icann IN MX 100 mail.icann.org.
+ IN MX 95 mailhub.icann.org.
+xaos IN A 24.93.15.22
+ IN TXT "XAOS Associates Online Services"
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+ IN LOC 43 02 20.000 N 77 43 12.000 W 170.00m 1.00m 30.00m 10.00m
+mmuuf IN MX 10 gro.dd.org.
+reptiles IN A 198.96.117.142
+ IN MX 10 mail2.reptiles.org.
+ IN MX 20 mail.vex.net.
+ IN MX 5 mail.reptiles.org.
+iscvt IN A 207.136.209.132
+ IN MX 10 isc-01.iscvt.org.
+ IN MX 20 mqueue.sover.net.
+mailinglists IN A 63.160.175.18
+lawlinevt IN MX 20 mqueue.sover.net.
+ IN MX 10 host3.vtlegalaid.org.
+mail-abuse IN A 204.152.184.74
+$ORIGIN SECTOR001.org.
+NS0 IN A 24.4.49.117
+NS1 IN A 24.4.49.246
+$ORIGIN ML.org.
+MERCURY IN A 209.68.0.85
+$ORIGIN XBILL.org.
+NS IN A 204.152.186.163
+$ORIGIN spack.org.
+maus IN A 204.245.198.90
+$ORIGIN netsage.org.
+keith IN A 209.67.235.37
+www IN CNAME netsage.org.
+sure IN A 209.67.235.38
+$ORIGIN ietf.org.
+odin IN A 132.151.1.176
+www2 IN A 4.17.168.6
+www IN CNAME www2.ietf.org.
+$ORIGIN lux.dot-eu.org.
+ns0 IN A 195.206.105.102
+$ORIGIN the-frontier.org.
+ns2 IN A 216.86.199.115
+ns1 IN A 216.86.199.114
+$ORIGIN vmba.org.
+www IN MX 10 gro.dd.org.
+ IN A 209.198.103.206
+$ORIGIN WILLIAM.org.
+JOANNA IN A 195.153.6.2
+$ORIGIN FROGHOUSE.org.
+DNS IN A 207.121.69.243
+$ORIGIN VTLEGALAID.org.
+host3 IN A 207.136.208.115
+$ORIGIN dd.org.
+doubt IN A 209.198.103.193
+news IN CNAME gro.dd.org.
+gro IN A 209.198.103.200
+d IN A 209.198.103.199
+workgroup IN A 209.198.103.201
+dhcp1 IN A 209.198.103.194
+go IN A 209.198.103.198
+mail IN CNAME gro.dd.org.
+localhost IN A 127.0.0.1
+dhcp2 IN A 209.198.103.195
+www IN CNAME gro.dd.org.
+dhcp3 IN A 209.198.103.196
+dhcp4 IN A 209.198.103.197
+moderators IN CNAME moderators.isc.org.
+ns IN CNAME gro.dd.org.
+$ORIGIN gazpacho.org.
+keith IN A 209.67.235.37
+sure IN A 209.67.235.38
+$ORIGIN FLAME.org.
+DNS02 IN A 204.152.184.97
+www IN A 204.152.184.97
+DNS01 IN A 204.152.184.80
+$ORIGIN giffordmed.org.
+mail IN A 130.189.100.51
+$ORIGIN isc.org.
+isrv3-i IN A 204.152.184.87
+$ORIGIN energyenhancement.org.
+www IN A 216.121.175.228
+$ORIGIN icann.org.
+mailhub IN A 192.0.34.33
+mail IN A 198.32.1.99
+$ORIGIN PAPP.UNDP.org.
+PAPPSRV IN A 192.115.229.1
+$ORIGIN xaos.org.
+amethyst IN A 204.145.159.12
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+sure IN A 209.67.235.38
+taiyoo IN A 204.145.159.13
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+gw IN A 24.93.15.22
+reimei IN A 204.145.159.17
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+gwi IN A 204.145.159.2
+ IN HINFO "Firewall" "Gateway"
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+keith IN A 209.67.235.37
+axis IN A 204.145.159.20
+mail IN CNAME furii.xaos.org.
+all IN A 24.95.203.33
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+www IN CNAME gw.xaos.org.
+kadou IN A 204.145.159.14
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+furii IN A 204.145.159.11
+ IN MX 0 mail.xaos.org.
+ IN MX 5 gw.xaos.org.
+ftp IN CNAME gw.xaos.org.
+gwe IN CNAME gw.xaos.org.
+$ORIGIN PUNCHDOWN.org.
+NS IN A 140.174.131.100
+$ORIGIN mmuuf.org.
+www IN MX 10 gro.dd.org.
+ IN A 209.198.103.205
+$ORIGIN OPEN-RSC.org.
+ASLAN IN A 199.5.157.128
+UNICORN IN A 207.126.103.16
+$ORIGIN COGNOSCENTI.org.
+SYNAESTHESIA IN A 207.208.112.4
+ANAESTHESIA IN A 207.208.112.3
+$ORIGIN DC.IGC.org.
+NS IN A 199.75.208.10
+$ORIGIN mitre.org.
+DNSSRV1X IN A 199.94.97.51
+mbunix IN A 199.94.97.52
+DNSSRV3X IN A 198.76.173.100
+smtpproxy1 IN A 129.83.20.90
+linus IN A 129.83.10.1
+ IN MX 1 linus.mitre.org.
+ IN MX 5 smtpproxy1.mitre.org.
+ IN MX 10 smtpproxy2.mitre.org.
+smtpproxy2 IN A 128.29.154.90
+mwunix IN A 198.76.173.52
+$ORIGIN reptiles.org.
+mail IN A 198.96.117.157
+NS2 IN A 192.75.253.138
+NS IN A 198.96.117.136
+$ORIGIN ISPC.org.
+NS2 IN A 209.124.64.11
+NS3 IN A 207.230.32.23
+NS1 IN A 207.106.7.7
+$ORIGIN IGC.APC.org.
+NS1 IN A 192.82.108.38
+$ORIGIN iscvt.org.
+isc-01 IN A 207.136.209.131
+$ORIGIN FLIRBLE.org.
+NS0 IN A 195.40.6.20
+$ORIGIN SANS.org.
+SERVER1 IN A 167.216.133.33
+$ORIGIN LTWCC.org.
+NS2 IN A 12.33.66.62
+NS1 IN A 12.33.66.61
+$ORIGIN CMHNET.org.
+elektro IN A 192.188.133.3
+$ORIGIN SNPT.KM.
+BOW IN A 195.101.19.253
+$ORIGIN ONPT.NET.MA.
+MASSIRA IN A 206.103.26.1
+$ORIGIN IAM.NET.MA.
+DNS2 IN A 212.217.0.12
+DNS3 IN A 212.217.1.1
+DNS1 IN A 212.217.0.1
+$ORIGIN KREONET.RE.KR.
+NS IN A 134.75.30.1
+$ORIGIN KREN.NE.KR.
+NS IN A 147.47.1.1
+$ORIGIN NIC.LK.
+NS IN A 192.248.1.65
+$ORIGIN NIC.MC.
+NS IN A 195.78.6.131
+$ORIGIN 110.16.12.IN-ADDR.ARPA.
+35 IN CNAME 35.32/27.110.16.12.in-addr.arpa.
+$ORIGIN 32/27.110.16.12.IN-ADDR.ARPA.
+35 IN PTR mail.nova-data.com.
+$ORIGIN 0.0.127.IN-ADDR.ARPA.
+1 IN PTR localhost.
+$ORIGIN 184.152.204.IN-ADDR.ARPA.
+87 IN PTR isrv3-i.isc.org.
+$ORIGIN 187.152.204.IN-ADDR.ARPA.
+59 IN PTR shell.nominum.com.
+$ORIGIN 131.127.204.IN-ADDR.ARPA.
+47 IN PTR mtiwmhc22.worldnet.att.net.
+$ORIGIN 198.245.204.IN-ADDR.ARPA.
+90 IN PTR maus.spack.org.
+$ORIGIN 159.145.204.IN-ADDR.ARPA.
+12 IN PTR amethyst.xaos.org.
+13 IN PTR taiyoo.xaos.org.
+14 IN PTR kadou.xaos.org.
+17 IN PTR reimei.xaos.org.
+20 IN PTR axis.xaos.org.
+2 IN PTR gwi.xaos.org.
+11 IN PTR furii.xaos.org.
+$ORIGIN 241.5.198.IN-ADDR.ARPA.
+38 IN PTR cmr0.ash.ops.us.uu.net.
+39 IN PTR cmr1.ash.ops.us.uu.net.
+$ORIGIN 241.103.199.IN-ADDR.ARPA.
+218 IN PTR abyssinian.sleepycat.com.
+$ORIGIN 153.66.206.IN-ADDR.ARPA.
+12 IN PTR d.dd.org.
+102 IN PTR gro.dd.org.
+128 IN PTR www.vmba.org.
+1 IN PTR workgroup.dd.org.
+2 IN PTR doubt.dd.org.
+136 IN PTR www.mmuuf.org.
+4 IN PTR nila.dd.org.
+10 IN PTR go.dd.org.
+$ORIGIN 84.198.209.IN-ADDR.ARPA.
+242 IN PTR dlawren-gw.burl.sover.net.
+$ORIGIN 87.198.209.IN-ADDR.ARPA.
+52 IN PTR mqueue0.sover.net.
+$ORIGIN 103.198.209.IN-ADDR.ARPA.
+198 IN CNAME 198.192.103.198.209.in-addr.arpa.
+205 IN CNAME 205.192.103.198.209.in-addr.arpa.
+199 IN CNAME 199.192.103.198.209.in-addr.arpa.
+206 IN CNAME 206.192.103.198.209.in-addr.arpa.
+193 IN CNAME 193.192.103.198.209.in-addr.arpa.
+200 IN CNAME 200.192.103.198.209.in-addr.arpa.
+201 IN CNAME 201.192.103.198.209.in-addr.arpa.
+$ORIGIN 192.103.198.209.IN-ADDR.ARPA.
+202 IN PTR fraud.dd.org.
+195 IN PTR dhcp2.dd.org.
+203 IN PTR fraud.dd.org.
+196 IN PTR dhcp3.dd.org.
+204 IN PTR ppp.dd.org.
+197 IN PTR dhcp4.dd.org.
+205 IN PTR www.mmuuf.org.
+198 IN PTR go.dd.org.
+206 IN PTR www.vmba.org.
+199 IN PTR d.dd.org.
+207 IN PTR broadcast.dd.org.
+200 IN PTR gro.dd.org.
+193 IN PTR doubt.dd.org.
+201 IN PTR workgroup.dd.org.
+194 IN PTR dhcp1.dd.org.
+$ORIGIN 133.188.192.IN-ADDR.ARPA.
+3 IN PTR elektro.com.
+$ORIGIN 206.203.192.IN-ADDR.ARPA.
+9 IN PTR ice.WonderWorks.COM.
+$ORIGIN 2.39.137.IN-ADDR.ARPA.
+3 IN PTR New-York4.NY.ALTER.NET.
+$ORIGIN 126.39.137.IN-ADDR.ARPA.
+10 IN PTR Fddi0-0.New-York4.NY.ALTER.NET.
+$ORIGIN IRD.MG.
+ANTANA IN A 194.214.107.1
+$ORIGIN NIC.MG.
+NS IN A 194.214.107.253
+$ORIGIN KW.
+DNS2 IN A 161.252.48.150
+DNS1 IN A 161.252.48.140
+$ORIGIN MOC.KW.
+NCC IN A 196.1.69.98
+$ORIGIN NET.NA.
+GRUMPY IN A 196.20.23.1
+$ORIGIN RELCOM.KZ.
+NS IN A 212.110.240.65
+$ORIGIN MARNET.MK.
+KITKA IN A 194.149.131.2
+$ORIGIN SC-UNI.KTU.LT.
+NEMUNAS IN A 193.219.32.13
+$ORIGIN SOTELMA.ML.
+ASKIA IN A 208.144.230.3
+$ORIGIN DNS.LU.
+NS2 IN A 158.64.229.3
+NS5 IN A 194.246.96.193
+NS1 IN A 158.64.229.2
+$ORIGIN INTNET.NE.
+BOW IN A 194.51.164.253
+$ORIGIN MN.
+MAGIC IN A 202.131.0.10
+$ORIGIN NF.
+NS2 IN A 203.12.249.101
+NS1 IN A 203.12.249.100
+$ORIGIN LATNET.LV.
+NS2 IN A 159.148.108.1
+NS IN A 159.148.60.2
+$ORIGIN UMAC.MO.
+UMACSN2 IN A 161.64.3.2
+NS2 IN A 161.64.7.2
+UMACSN1 IN A 161.64.3.1
+NS1 IN A 161.64.7.1
+$ORIGIN NI.
+NS IN A 165.98.1.2
+ IN A 200.30.36.8
+$ORIGIN TMX.COM.NI.
+NS IN A 205.218.253.2
+$ORIGIN UNIV-NKC.MR.
+DNS2 IN A 193.251.145.154
+DNS1 IN A 193.251.145.155
+$ORIGIN SVIANED.nl.
+NS IN A 143.177.1.3
+$ORIGIN secondary.nl.
+ns2 IN A 194.229.138.6
+$ORIGIN DOMAIN-REGISTRY.nl.
+NS2 IN A 193.176.144.130
+NS IN A 193.176.144.2
+$ORIGIN MT.
+NS IN A 193.188.47.252
+$ORIGIN DHIRAAGU.MV.
+NS IN A 202.1.192.196
+$ORIGIN NO.
+NAC IN A 129.240.2.40
+ALCANET IN MX 15 tyholt.uninett.no.
+ IN MX 20 nac.no.
+ IN A 158.39.5.5
+$ORIGIN UIO.NO.
+IFI IN A 129.240.64.2
+$ORIGIN SOL.NO.
+NS1 IN A 195.225.2.10
+$ORIGIN uit.NO.
+benoni IN A 129.242.4.254
+$ORIGIN ALCANET.NO.
+NS IN A 193.213.238.10
+$ORIGIN UNINETT.NO.
+aun IN A 129.241.1.99
+tyholt IN A 158.38.60.10
+NN IN A 158.38.0.181
+$ORIGIN alcatel.NO.
+ns2 IN A 193.213.238.2
+$ORIGIN UNINET.NET.MX.
+MEX1-M-213 IN A 200.33.146.213
+$ORIGIN AVANTEL.NET.MX.
+DNS1 IN A 200.33.213.66
+$ORIGIN UNAM.MX.
+NS IN A 132.248.253.1
+$ORIGIN NIC.MX.
+NS IN A 200.23.1.1
+$ORIGIN MOS.COM.NP.
+SHIKHAR IN A 202.52.255.5
+$ORIGIN MY.
+MIMOS IN A 192.228.128.18
+JARING IN A 192.228.128.20
+$ORIGIN JARING.MY.
+GATEN IN A 161.142.227.17
+GATE1 IN A 161.142.2.17
+$ORIGIN PA.
+NS IN A 168.77.8.2
+$ORIGIN USMA.AC.PA.
+VASCO IN A 208.141.92.2
+$ORIGIN UEM.MZ.
+ZEBRA IN A 196.3.96.67
+OCEANO IN A 196.3.96.69
+DZOWO IN A 196.3.96.66
+$ORIGIN CENPAC.NET.NR.
+NRWEB IN A 203.98.224.66
+$ORIGIN NIC.NU.
+NS IN A 128.11.47.50
+$ORIGIN DE.NIC.NU.
+NS0 IN A 216.200.116.40
+$ORIGIN TELIA.NIC.NU.
+NS0 IN A 212.181.91.4
+$ORIGIN NS.NIC.NU.
+NZ IN A 203.97.132.66
+$ORIGIN OMANTEL.NET.OM.
+OM4 IN A 206.49.101.5
+OM10 IN A 206.49.101.6
+$ORIGIN RCP.NET.PE.
+ICHU IN A 161.132.5.14
+$ORIGIN MANA.PF.
+NS2 IN A 202.3.225.20
+NS1 IN A 202.3.225.10
+$ORIGIN QATAR.NET.QA.
+NS2 IN A 212.77.192.13
+NS3 IN A 212.77.192.15
+NS1 IN A 212.77.192.10
+$ORIGIN CLEAR.NET.NZ.
+NS2 IN A 203.97.37.14
+NS1 IN A 203.97.33.14
+$ORIGIN DNS.NET.NZ.
+NS1 IN A 202.46.161.3
+$ORIGIN IHUG.NET.NZ.
+NS2 IN A 203.29.160.2
+$ORIGIN XTRA.CO.NZ.
+GORGON IN A 202.27.158.34
+$ORIGIN WAIKATO.AC.NZ.
+NS99 IN A 130.217.76.27
+$ORIGIN VUW.AC.NZ.
+RATA IN A 130.195.2.11
+$ORIGIN MCS.VUW.AC.NZ.
+DOWNSTAGE IN A 130.195.6.10
+CIRCA IN A 130.195.5.12
+$ORIGIN PL.
+from IN A 212.160.132.114
+$ORIGIN NASK.ORG.PL.
+BILBO IN A 148.81.16.51
+ IN A 195.187.245.51
+$ORIGIN pbks.PL.
+alf IN A 195.205.33.200
+$ORIGIN CYFRONET.KRAKOW.PL.
+NMS IN A 149.156.1.3
+$ORIGIN MAN.LODZ.PL.
+DNS2 IN A 212.51.192.5
+$ORIGIN ispid.com.PL.
+trurl IN A 195.150.99.3
+$ORIGIN itnet.com.PL.
+emerald IN A 195.116.64.3
+$ORIGIN ELEKTRON.PL.
+AMBER IN A 195.117.6.10
+$ORIGIN macrosoft.WAW.PL.
+front IN A 194.196.86.66
+$ORIGIN NASK.WAW.PL.
+ARWENA IN A 193.59.201.28
+$ORIGIN webtech.elk.PL.
+tornado IN A 212.244.162.100
+$ORIGIN IKP.PL.
+NS3 IN A 157.25.5.30
+$ORIGIN TPSA.PL.
+DNS2 IN A 194.204.152.34
+$ORIGIN uwm.EDU.PL.
+matrix IN A 213.184.3.136
+$ORIGIN FUW.EDU.PL.
+DNS IN A 193.0.80.11
+$ORIGIN UPRR.PR.
+PASCAL IN A 134.202.1.120
+DESCARTES IN A 134.202.1.125
+$ORIGIN NCC.UP.PT.
+CIUP1 IN A 193.136.51.52
+$ORIGIN FCCN.PT.
+DNS IN A 193.136.192.10
+$ORIGIN DNS.PT.
+NS IN A 193.136.0.1
+$ORIGIN TELEPAC.PT.
+NS1 IN A 194.65.3.20
+VIVALDI IN A 194.65.3.21
+$ORIGIN CNC.UNA.PY.
+SCE IN A 200.10.228.133
+NS IN A 200.10.228.132
+$ORIGIN ISU.NET.SA.
+NS1 IN A 212.26.18.3
+$ORIGIN KACST.EDU.SA.
+NS IN A 212.26.44.3
+$ORIGIN COM.SB.
+PIJIN IN A 202.139.42.10
+$ORIGIN SOLOMON.COM.SB.
+OLKETA IN A 202.139.42.4
+$ORIGIN cafax.SE.
+ns IN A 192.71.228.17
+$ORIGIN LTH.SE.
+NIC IN A 130.235.20.3
+$ORIGIN SUNET.SE.
+SUNIC IN A 192.36.125.2
+$ORIGIN PACIFIC.NET.SG.
+NS1 IN A 192.169.33.3
+$ORIGIN NIC.NET.SG.
+DS IN A 202.42.194.205
+$ORIGIN SINGNET.COM.SG.
+DNSSEC2 IN A 195.13.10.226
+DNSSEC3 IN A 165.21.100.11
+DNSSEC1 IN A 165.21.83.11
+$ORIGIN RNC.RO.
+NS-A IN A 192.162.16.31
+NS IN A 192.162.16.21
+$ORIGIN NIC.SH.
+NS IN A 194.205.62.60
+$ORIGIN ARNES.SI.
+KANIN IN A 193.2.1.66
+SREBRNJAK IN A 193.2.1.91
+$ORIGIN INTERNET.SK.
+NS IN A 192.108.130.91
+$ORIGIN EUNET.SK.
+NS IN A 192.108.130.33
+$ORIGIN NETLAB.SK.
+NS IN A 195.168.1.4
+$ORIGIN SIERRATEL.SL.
+NS IN A 194.133.124.5
+$ORIGIN INTNET.TD.
+BOW IN A 193.251.147.253
+$ORIGIN RU.
+ok IN A 195.2.83.162
+ IN MX 50 mail.ok.ru.
+ IN MX 100 relay1.aha.ru.
+ IN MX 300 relay3.aha.ru.
+$ORIGIN aha.RU.
+ns1 IN A 195.2.80.142
+$ORIGIN ok.RU.
+mail IN A 195.2.83.162
+ns IN A 195.2.64.36
+$ORIGIN INTELCOM.SM.
+DNS IN A 194.183.64.11
+$ORIGIN OMNIWAY.SM.
+DNS IN A 194.183.64.10
+$ORIGIN UCAD.SN.
+NS IN A 196.1.95.1
+$ORIGIN NIC.TJ.
+NS2 IN A 209.77.224.1
+NS1 IN A 209.77.250.1
+$ORIGIN SPB.SU.
+NS IN A 193.124.83.69
+$ORIGIN RICC.ALMA-ATA.SU.
+NS IN A 194.87.112.4
+$ORIGIN DEMOS.SU.
+NS IN A 194.87.0.8
+ IN A 194.87.0.9
+$ORIGIN RED.SV.
+CIR IN A 168.243.254.1
+$ORIGIN GOB.SV.
+CONACYT IN A 168.243.64.2
+ANTEL IN A 168.243.65.1
+$ORIGIN ATI.TN.
+NS IN A 193.95.66.10
+$ORIGIN TO.
+TONIC IN A 206.184.59.10
+COLO IN A 206.86.247.253
+$ORIGIN TDC.TO.
+NS1 IN A 206.86.247.250
+$ORIGIN SY.
+EARTH IN A 195.22.198.6
+$ORIGIN VATICAN.VA.
+MICHAEL IN A 212.77.0.2
+$ORIGIN METU.EDU.TR.
+NS2 IN A 144.122.199.93
+NS1 IN A 144.122.199.90
+$ORIGIN NIC.UK.
+NS1 IN A 195.66.240.130
+$ORIGIN AXION.BT.CO.UK.
+DNS0 IN A 132.146.5.1
+$ORIGIN ADVSYS.CO.UK.
+BARNEY IN A 194.72.124.2
+$ORIGIN WR.UMIST.AC.UK.
+AARDVARK IN A 130.88.146.3
+$ORIGIN UCL.AC.UK.
+ IN A 128.16.5.31
+ IN MX 10 bells.cs.ucl.ac.uk.
+ IN MX 11 haig.cs.ucl.ac.uk.
+$ORIGIN CS.UCL.AC.UK.
+haig IN A 128.16.6.8
+bells IN A 128.16.5.31
+NS1 IN A 128.16.5.32
+$ORIGIN surrey.AC.UK.
+info-server IN A 131.227.102.6
+eim IN MX 6 phoebe.eim.surrey.ac.uk.
+ IN MX 6 prue.eim.surrey.ac.uk.
+$ORIGIN eim.surrey.AC.UK.
+prue IN A 131.227.76.5
+phoebe IN A 131.227.74.4
+$ORIGIN MHS-RELAY.AC.UK.
+SUN IN A 128.86.8.25
+$ORIGIN NIC.TT.
+DNS IN A 24.3.198.194
+$ORIGIN REACCIUN.VE.
+DNS2 IN A 150.188.4.212
+DNS IN A 150.188.4.210
+$ORIGIN ULA.VE.
+AZMODAN IN A 150.185.130.16
+$ORIGIN UTZ.
+NS2 IN A 160.124.112.10
+NS3 IN A 160.124.147.1
+NS1 IN A 160.124.48.4
+$ORIGIN NIC.TV.
+NS4 IN A 207.151.24.23
+NS2 IN A 208.184.1.167
+NS6 IN A 64.56.165.153
+NS7 IN A 64.69.172.153
+NS1 IN A 209.143.242.138
+$ORIGIN EDU.TW.
+MOEVAX IN A 140.111.1.2
+$ORIGIN vt.us.
+state IN MX 10 mx1.state.vt.us.
+ IN MX 10 mx2.state.vt.us.
+$ORIGIN k12.vt.us.
+ns2 IN A 170.222.64.130
+morristown IN MX 0 mail.k12.vt.us.
+ns1 IN A 170.222.64.130
+jericho IN MX 0 mail.k12.vt.us.
+founders IN MX 0 mail.k12.vt.us.
+$ORIGIN state.vt.us.
+srs IN A 159.105.101.150
+ IN MX 0 srs.srs.state.vt.us.
+ IN MX 10 mx1.state.vt.us.
+ IN MX 10 mx2.state.vt.us.
+defgen IN MX 0 mail.state.vt.us.
+ IN MX 10 mx1.state.vt.us.
+ IN MX 10 mx2.state.vt.us.
+ IN MX 5 vtagr02.agr.state.vt.us.
+ IN MX 15 mx1.state.vt.us.
+ IN MX 20 mx2.state.vt.us.
+mail IN A 170.222.64.134
+ns1 IN A 159.105.23.130
+ns2 IN A 170.222.64.130
+$ORIGIN srs.state.vt.us.
+srs IN A 159.105.101.150
+$ORIGIN agr.state.vt.us.
+vtagr04 IN A 159.105.50.4
+vtagr02 IN A 159.105.50.2
+$ORIGIN anr.state.vt.us.
+dec IN MX 10 mx1.state.vt.us.
+ IN MX 10 mx2.state.vt.us.
+ IN MX 0 dec.anr.state.vt.us.
+ IN A 159.105.46.4
+$ORIGIN pha.pa.us.
+candle IN A 162.33.245.46
+$ORIGIN CNRI.reston.va.us.
+NS IN A 132.151.1.1
+$ORIGIN boston.MA.us.
+foxharp IN MX 10 bparker.connactivity.com.
+$ORIGIN ns.foxharp.boston.MA.us.
+a IN A 24.147.209.205
+$ORIGIN STARFIRE.DOUGLAS.MA.us.
+NS2 IN A 216.129.136.9
+DNS IN A 206.225.44.40
+NS1 IN A 216.129.136.9
+$ORIGIN NIC.us.
+USDNS IN A 198.41.3.87
+$ORIGIN sf.ca.us.
+asylum IN A 192.48.232.17
+$ORIGIN palo-alto.ca.us.
+mejac IN A 192.147.236.1
+$ORIGIN VN.
+DNS1 IN A 203.162.3.235
+$ORIGIN EDU.UY.
+SECIU IN A 164.73.128.5
+$ORIGIN UZ.
+NS IN A 213.68.88.11
+$ORIGIN NOC.UZ.
+NS IN A 194.67.52.42
+$ORIGIN VANUATU.COM.VU.
+SANTO IN A 202.139.40.7
+FUTUNA IN A 202.139.40.3
+EFATE IN A 202.139.40.5
+$ORIGIN nic.mnet.
+ns2 IN A 208.109.83.110
+ns1 IN A 216.61.39.172
+$ORIGIN DNS.WS.
+NS4 IN A 216.52.234.102
+NS2 IN A 216.35.187.250
+NS1 IN A 202.4.48.217
+NS5 IN A 216.35.188.8
+NS3 IN A 216.52.234.99
+$ORIGIN UCT.AC.ZA.
+UCTHPX IN A 137.158.128.1
+$ORIGIN FRD.AC.ZA.
+APIES IN A 137.214.80.1
+$ORIGIN EE.UND.AC.ZA.
+DAISY IN A 146.230.192.18
+$ORIGIN RU.AC.ZA.
+HIPPO IN A 146.231.128.1
+$ORIGIN UNZA.ZM.
+PUKU IN A 196.7.240.1
+$ORIGIN NIC.YU.
+NS1 IN A 147.91.8.6
+$ORIGIN TELEKOM.YU.
+ODISEJ IN A 195.178.32.2
+$ORIGIN gtld-servers.ORSC.
+b IN A 216.13.126.116
+$ORIGIN ROOT-SERVERS.ORSC.
+B IN A 216.13.126.116
+C IN A 65.196.80.102
+A IN A 199.166.24.1
+$ORIGIN ZPTC.CO.ZW.
+TELCOM IN A 194.133.122.47
+$ORIGIN NIPR.MIL.
+PAC2 IN A 199.252.155.234
+EUR2 IN A 199.252.143.234
+CON2 IN A 199.252.173.234
+PAC1 IN A 199.252.180.234
+EUR1 IN A 199.252.154.234
+CON1 IN A 199.252.175.234
+$ORIGIN ARL.MIL.
+ADMII IN A 128.63.31.4
+ IN A 128.63.5.4
+$ORIGIN GOV.
+nps IN MX 5 ccmail.itd.nps.gov.
+ IN MX 10 ccmail2.itd.nps.gov.
+$ORIGIN STAT-USA.GOV.
+SUNNY IN A 192.239.70.8
+$ORIGIN NASA.GOV.
+jpl IN A 137.78.160.180
+NASANS4 IN A 198.116.144.33
+NASANS3 IN A 198.116.144.49
+NASANS1 IN A 192.77.84.32
+$ORIGIN NSI.NASA.GOV.
+MX IN A 128.102.18.31
+$ORIGIN CDC.GOV.
+NS2 IN A 198.246.96.92
+NS1 IN A 198.246.96.61
+$ORIGIN NIST.GOV.
+NS1 IN A 129.6.13.2
+$ORIGIN cr.USGS.GOV.
+ISDSUN IN A 136.177.16.3
+ns IN A 136.177.16.3
+rgfsparc IN A 136.177.164.192
+$ORIGIN ER.USGS.GOV.
+NS IN A 130.11.48.2
+$ORIGIN WR.USGS.GOV.
+ISDMNL IN A 130.118.4.2
+$ORIGIN DEN.nps.GOV.
+DENS20 IN A 165.83.24.20
+$ORIGIN ITD.nps.GOV.
+BIGBIRD IN A 165.83.208.5
+$ORIGIN AKSO.nps.GOV.
+INPAKSODNS IN A 165.83.49.9
+$ORIGIN WRO.nps.GOV.
+VANILLA IN A 165.83.71.3
+$ORIGIN NCC.nps.GOV.
+OWL IN A 165.83.34.60
+$ORIGIN net.
+FIREHOUSE IN A 63.160.175.19
+gbch IN MX 0 maxim.gbch.net.
+VERMONTEL IN A 63.167.45.2
+ IN MX 0 pop.vermontel.net.
+reedmedia IN A 63.145.197.178
+goldstats IN A 66.33.12.17
+zama IN A 203.142.132.46
+helicon IN A 63.93.137.2
+wetlogic IN MX 10 athome.wetlogic.net.
+188 IN A 202.96.125.100
+ IN A 202.96.125.101
+ IN MX 10 mx2.188.net.
+ IN MX 20 smtp.188.net.
+ IN MX 10 mx1.188.net.
+valley IN MX 0 lebanon.valley.net.
+primary IN A 216.87.34.253
+SOVER IN A 209.198.87.53
+ IN A 209.198.87.34
+ IN MX 10 mail.sover.net.
+ IN MX 20 mqueue.sover.net.
+UU IN MX 10 external-mail-router.UU.NET.
+connriver IN A 63.93.137.13
+ IN MX 10 ns.hcr.net.
+ IN MX 1 mailer.connriver.net.
+SHOREHAM IN A 199.170.121.2
+$ORIGIN cinenet.net.
+NS1 IN A 198.147.76.65
+$ORIGIN TOGETHER.net.
+NS2 IN A 204.97.120.31
+NS1 IN A 204.97.120.30
+$ORIGIN IPHIL.net.
+MAKISIG IN A 203.176.28.135
+$ORIGIN PLANET-THREE.net.
+NS2 IN A 212.49.219.190
+$ORIGIN FIREHOUSE.net.
+DNS2 IN A 63.160.175.18
+DNS1 IN A 63.160.175.19
+$ORIGIN space.net.
+ns IN A 195.30.0.1
+$ORIGIN DNS.space.net.
+NS4 IN A 195.222.210.93
+NS3 IN A 193.149.44.49
+$ORIGIN ALASKA.net.
+NS4-AUTH IN A 209.112.130.4
+NS1-AUTH IN A 209.112.160.4
+$ORIGIN FWIDCSERVICES.net.
+DEN-NS2 IN A 216.7.160.32
+IRV-NS1 IN A 216.23.160.51
+DEN-NS1 IN A 216.7.160.31
+NS1 IN A 64.78.224.58
+$ORIGIN BIJT.net.
+PAN IN A 213.196.2.97
+$ORIGIN SEABONE.net.
+DNS IN A 195.22.205.163
+$ORIGIN SPIN.OMNES.net.
+NS IN A 192.23.90.196
+$ORIGIN VERIO.net.
+NS2 IN A 129.250.31.190
+NS0 IN A 129.250.15.61
+NS1 IN A 204.91.99.140
+$ORIGIN NS.VERIO.net.
+B IN A 129.250.35.32
+T IN A 192.67.14.16
+$ORIGIN GNOSH.net.
+GRIN IN A 216.15.87.207
+$ORIGIN NEASE.net.
+NS2 IN A 202.103.134.4
+$ORIGIN CRSNIC.net.
+NS1 IN A 198.41.3.39
+$ORIGIN VERISIGN.net.
+MODOR IN A 205.139.94.55
+CITADEL IN A 205.139.94.15
+PAGOSA IN A 205.139.94.16
+KAOS IN A 208.202.137.126
+$ORIGIN terra.net.
+ns2 IN A 199.103.128.2
+ns1 IN A 199.103.128.1
+$ORIGIN ADMONITOR.net.
+NS-2 IN A 216.35.185.40
+ads IN A 216.35.185.145
+SC-NS1 IN A 64.70.20.85
+$ORIGIN NORDU.net.
+SERVER IN A 193.10.252.19
+$ORIGIN TELEGLOBE.net.
+CASTOR IN A 199.202.55.2
+$ORIGIN sodak.net.
+NS2 IN A 63.65.239.225
+RINGNECK IN A 63.65.238.65
+$ORIGIN gbch.net.
+MAXIM IN A 203.9.155.249
+$ORIGIN VERMONTEL.net.
+pop IN CNAME loomis.vermontel.net.
+NS2 IN A 204.164.106.8
+loomis IN A 204.164.106.19
+NS1 IN A 204.164.106.2
+$ORIGIN farm.net.
+ns IN A 216.112.179.160
+$ORIGIN NAP.net.
+NS2 IN A 206.54.224.1
+$ORIGIN AH.net.
+NS4 IN A 203.21.205.20
+NS2 IN A 203.21.205.1
+$ORIGIN NS.GDNS.net.
+LHR IN A 212.250.25.101
+DCA IN A 209.207.221.1
+$ORIGIN CONCENTRIC.net.
+NAMESERVER1 IN A 207.155.183.73
+NAMESERVER3 IN A 206.173.119.72
+NAMESERVER IN A 207.155.183.72
+NIC2 IN A 207.88.60.5
+NAMESERVER2 IN A 207.155.184.72
+$ORIGIN att.net.
+worldnet IN A 199.70.151.234
+$ORIGIN worldnet.att.net.
+ns3 IN A 204.127.160.1
+ns4 IN A 204.127.160.2
+mtiwmhc22 IN A 204.127.131.47
+ns1 IN A 204.127.129.1
+ns IN A 204.127.160.2
+ IN A 12.102.240.1
+ IN A 12.102.240.2
+ IN A 12.102.244.1
+ IN A 12.102.244.2
+ IN A 204.127.129.1
+ IN A 204.127.129.2
+ IN A 204.127.160.1
+ns2 IN A 204.127.129.2
+$ORIGIN OR.BR.NP.ELS-GMS.att.net.
+ORCU IN A 199.191.129.139
+$ORIGIN WY.BR.NP.ELS-GMS.att.net.
+WYCU IN A 199.191.128.43
+$ORIGIN OH.MT.NP.ELS-GMS.att.net.
+OHCU IN A 199.191.144.75
+$ORIGIN MA.MT.NP.ELS-GMS.att.net.
+MACU IN A 199.191.145.136
+$ORIGIN MT.NS.ELS-GMS.att.net.
+CMTU IN A 12.127.16.69
+DMTU IN A 12.127.16.70
+$ORIGIN BR.NS.ELS-GMS.att.net.
+CBRU IN A 199.191.128.105
+DBRU IN A 199.191.128.106
+$ORIGIN LEB.net.
+NS IN A 206.127.55.2
+$ORIGIN SEG.net.
+NS2 IN A 206.34.181.16
+NS1 IN A 206.34.181.15
+$ORIGIN romkey.SEG.net.
+ip1 IN A 207.121.69.234
+$ORIGIN ync.net.
+NS4 IN A 206.185.20.9
+NS2 IN A 216.34.185.21
+NS5 IN A 206.185.20.10
+NS3 IN A 206.185.20.8
+ns1 IN A 216.34.185.20
+$ORIGIN GLOBECOMM.net.
+NS2 IN A 165.251.1.3
+NS1 IN A 165.251.1.2
+$ORIGIN PREP.net.
+DNS-EAST IN A 129.250.252.10
+$ORIGIN EARTHLINK.net.
+NS4 IN A 209.179.179.19
+DNS2 IN A 207.217.77.12
+DNS3 IN A 207.217.120.13
+DNS4 IN A 209.179.179.18
+NS1 IN A 207.217.126.41
+NS2 IN A 207.217.77.42
+$ORIGIN SPRINTLINK.net.
+NS3-AUTH IN A 144.228.255.10
+NS2-AUTH IN A 144.228.254.10
+NS1-AUTH IN A 206.228.179.10
+$ORIGIN OP.net.
+NS1 IN A 209.152.193.4
+$ORIGIN CERNET.net.
+NS IN A 202.112.0.44
+$ORIGIN zenon.net.
+dns IN A 195.2.83.107
+$ORIGIN INFI.net.
+NS3 IN A 205.219.239.5
+NS4 IN A 216.33.106.19
+NS001 IN A 208.131.160.201
+NS1 IN A 198.22.1.107
+NS2 IN A 198.22.1.108
+$ORIGIN vh8.INFI.net.
+vh80040 IN A 209.97.59.245
+vh80167 IN A 209.97.57.116
+$ORIGIN vh4.INFI.net.
+vh40099 IN A 209.97.59.121
+$ORIGIN SCRUZ.net.
+NS2 IN A 165.227.2.10
+NS IN A 165.227.1.1
+$ORIGIN HINET.net.
+netnews IN A 168.95.195.16
+ IN MX 0 netnews.hinet.net.
+HNTP1 IN A 168.95.192.1
+HNTP3 IN A 168.95.192.2
+DNS IN A 168.95.1.1
+$ORIGIN reedmedia.net.
+ns2 IN A 209.241.86.6
+NS1 IN A 63.145.197.178
+$ORIGIN schnism.net.
+ns IN A 195.88.150.3
+$ORIGIN unlisys.net.
+mail IN A 195.21.255.252
+$ORIGIN AIC.net.
+NS IN A 195.250.64.65
+$ORIGIN PIPEX-SZ.net.
+NS IN A 196.15.232.19
+$ORIGIN DOMAINNT.net.
+DENEB IN A 207.211.220.90
+RIGEL IN A 212.0.205.5
+VEGA IN A 209.26.120.5
+POLARIS IN A 209.26.120.2
+ANTARES IN A 209.26.120.3
+$ORIGIN GUERNSEY.net.
+DNS2 IN A 195.226.128.3
+$ORIGIN usa.net.
+CNDVG001 IN A 165.212.12.1
+$ORIGIN OPS.usa.net.
+dns03 IN A 204.68.24.136
+DNS01 IN A 204.68.24.137
+$ORIGIN INR.net.
+NS2 IN A 198.77.208.3
+NS1 IN A 198.77.208.2
+$ORIGIN CP.MSFT.net.
+dns6 IN A 207.46.138.20
+DNS4 IN A 207.46.138.11
+dns7 IN A 207.46.138.21
+dns IN A 207.46.138.10
+DNS5 IN A 207.46.138.12
+$ORIGIN UK.MSFT.net.
+DNS4 IN A 213.199.144.152
+DNS3 IN A 213.199.144.151
+$ORIGIN TK.MSFT.net.
+DNS2 IN A 207.46.232.38
+DNS1 IN A 207.46.232.37
+$ORIGIN HHS.net.
+NS IN A 63.93.136.29
+$ORIGIN NEWACCOUNT.net.
+NS IN A 216.121.96.26
+$ORIGIN PBI.net.
+NS2 IN A 206.13.29.11
+NS1 IN A 206.13.28.11
+$ORIGIN timeheart.net.
+ns1 IN A 63.197.231.203
+$ORIGIN TOSA.TWTELECOM.net.
+INS2 IN A 204.95.160.4
+INS1 IN A 204.95.160.2
+$ORIGIN zama.net.
+NS2 IN A 203.142.130.5
+NS1 IN A 203.142.130.4
+$ORIGIN MINDLINK.net.
+GIANT IN A 204.174.18.2
+DEEP IN A 204.174.16.4
+$ORIGIN SER.BBNPLANET.net.
+KNOCK IN A 192.239.16.129
+$ORIGIN MEDIASERVICES.net.
+NS2 IN A 64.65.16.237
+NS IN A 64.65.15.147
+$ORIGIN KOLO.net.
+NS IN A 209.66.103.20
+$ORIGIN SEYCHELLES.net.
+NS1 IN A 202.84.235.33
+$ORIGIN BT.net.
+NS0 IN A 194.72.6.51
+$ORIGIN JERKY.net.
+NS1 IN A 204.57.55.100
+$ORIGIN CN.net.
+DNS2 IN A 202.97.18.61
+NS1 IN A 202.97.7.17
+NS IN A 202.97.16.195
+$ORIGIN runway.CN.net.
+ns IN A 211.101.132.8
+$ORIGIN APNIC.net.
+SVC00 IN A 202.12.28.131
+TECKLA IN A 202.12.28.129
+NS IN A 203.37.255.97
+$ORIGIN BELLSOUTH.net.
+NS IN A 205.152.0.5
+$ORIGIN ATL.BELLSOUTH.net.
+NS IN A 205.152.0.20
+$ORIGIN CL.BELLSOUTH.net.
+NS2 IN A 205.152.16.8
+NS3 IN A 205.152.32.8
+$ORIGIN MIA.BELLSOUTH.net.
+NS IN A 205.152.16.20
+$ORIGIN RDU.BELLSOUTH.net.
+NS IN A 205.152.32.20
+$ORIGIN 163.net.
+SHNS IN A 61.129.65.108
+BJNS IN A 202.108.255.202
+NS IN A 202.108.255.201
+$ORIGIN ca.us.ibm.net.
+ns02 IN A 165.87.201.243
+ns01 IN A 165.87.201.244
+$ORIGIN ny.us.ibm.net.
+ns01 IN A 165.87.194.244
+$ORIGIN CP.net.
+NS3 IN A 209.228.14.4
+NS1 IN A 209.228.15.4
+$ORIGIN tallship.net.
+falcon IN A 208.179.112.2
+condor IN A 12.28.140.20
+nomad IN A 204.107.129.2
+satan IN A 204.107.129.3
+rectum IN A 204.107.129.10
+$ORIGIN ns.tmcs.net.
+b IN A 209.104.33.252
+c IN A 209.104.39.252
+a IN A 209.104.63.252
+$ORIGIN pshift.net.
+mail IN A 208.153.85.30
+$ORIGIN CTCCOM.net.
+NS4 IN A 64.69.100.35
+NS3 IN A 64.69.100.67
+$ORIGIN cid.net.
+bofh IN A 212.172.21.254
+$ORIGIN PIPEX.net.
+NS0 IN A 158.43.128.8
+NS1 IN A 158.43.192.7
+$ORIGIN DNS.PIPEX.net.
+NS1-Y IN A 158.43.193.89
+NS0-Y IN A 158.43.129.89
+$ORIGIN SOTELMA.net.
+DOGON IN A 208.144.230.1
+CIWARA IN A 208.144.230.2
+$ORIGIN DK.net.
+NS IN A 193.88.44.42
+$ORIGIN HIGGS.net.
+ns2 IN A 204.80.125.145
+ns3 IN A 204.80.101.94
+ns IN A 204.80.101.90
+ns1 IN A 204.80.125.130
+PINE IN A 204.80.125.130
+$ORIGIN E-SYNC.net.
+NS2 IN A 192.206.57.128
+NS1 IN A 192.206.57.127
+$ORIGIN ABOVE.net.
+NS3 IN A 207.126.105.146
+NS IN A 207.126.96.162
+$ORIGIN COBEX.net.
+NS2 IN A 207.102.129.72
+NS1 IN A 207.102.129.71
+$ORIGIN NEO.net.
+NS2 IN A 206.109.7.65
+NS IN A 206.109.1.1
+$ORIGIN AFRIQ.net.
+BAABEN IN A 165.231.1.3
+NEENE IN A 165.231.1.2
+$ORIGIN CW.net.
+NS4 IN A 204.70.49.234
+NS2 IN A 204.70.57.242
+NS3 IN A 204.70.25.234
+NS IN A 204.70.128.1
+$ORIGIN hactrn.net.
+NS IN A 216.254.68.12
+$ORIGIN QUASAR.net.
+NS1 IN A 199.166.31.3
+$ORIGIN VERMONTLAW.net.
+NS1 IN A 63.89.26.15
+NS IN A 63.89.26.16
+$ORIGIN ICP.net.
+ICM1 IN A 192.94.207.66
+$ORIGIN wetlogic.net.
+athome IN CNAME c1059495-a.snvl1.sfba.home.com.
+$ORIGIN NY.ALTER.net.
+New-York4 IN A 137.39.126.10
+ IN A 137.39.2.3
+$ORIGIN pccf.net.
+proxy IN A 205.189.73.123
+$ORIGIN IS-FUN.net.
+NS4 IN A 212.162.54.34
+$ORIGIN GUA.net.
+OSI2 IN A 205.161.188.3
+$ORIGIN 2GLOBE.net.
+TERMINAL IN A 195.178.183.230
+NS IN A 195.178.183.200
+$ORIGIN SYS.GTEI.net.
+DNSAUTH2 IN A 4.2.49.3
+DNSAUTH3 IN A 4.2.49.4
+DNSAUTH1 IN A 4.2.49.2
+$ORIGIN SPEAKEASY.net.
+NS2 IN A 216.231.41.22
+NS1 IN A 216.254.0.9
+$ORIGIN PSI.net.
+NS2 IN A 38.8.50.2
+$ORIGIN DNS.UK.PSI.net.
+SEC1 IN A 154.32.105.34
+$ORIGIN ray.net.
+ns1 IN A 195.238.228.131
+$ORIGIN anycast.net.
+ns1 IN A 216.196.51.4
+$ORIGIN EP.net.
+FLAG IN A 198.32.4.13
+$ORIGIN SR.net.
+NS2 IN A 200.1.156.11
+NS1 IN A 200.1.157.10
+$ORIGIN IPTEK.net.
+CADDSYS IN A 202.46.1.2
+$ORIGIN NIC.XLINK.net.
+DNS IN A 193.141.40.42
+$ORIGIN NURSAT.net.
+NS2 IN A 212.13.167.1
+NS IN A 194.226.128.1
+$ORIGIN 188.net.
+smtp IN A 202.96.125.104
+mx2 IN A 202.96.125.101
+ns2 IN A 202.103.134.4
+mx1 IN A 202.96.125.100
+NS IN A 202.96.125.106
+$ORIGIN KORNET.net.
+NS IN A 168.126.63.1
+$ORIGIN CCSRS.net.
+NS2 IN A 206.253.214.73
+NS1 IN A 209.237.73.73
+$ORIGIN EU.net.
+NS IN A 192.16.202.11
+$ORIGIN USSR.EU.net.
+NS IN A 193.124.22.65
+$ORIGIN RELCOM.EU.net.
+NS IN A 193.124.23.3
+$ORIGIN AUSTRIA.EU.net.
+NS IN A 192.92.138.35
+NS3 IN A 193.154.160.110
+$ORIGIN hypa.net.
+ns2 IN A 63.160.181.11
+ns1 IN A 63.160.181.10
+ IN A 209.166.167.208
+$ORIGIN IDT.net.
+NS IN A 198.4.75.100
+$ORIGIN NS.IDT.net.
+AUTH2 IN A 169.132.133.1
+$ORIGIN ROOT-SERVERS.net.
+A IN A 198.41.0.4
+B IN A 128.9.0.107
+C IN A 192.33.4.12
+D IN A 128.8.10.90
+E IN A 192.203.230.10
+F IN A 192.5.5.241
+G IN A 192.112.36.4
+H IN A 128.63.2.53
+I IN A 192.36.148.17
+$ORIGIN I-DNS.net.
+D IN A 211.169.245.170
+B IN A 208.184.25.199
+F IN A 216.200.119.128
+E IN A 202.160.253.152
+C IN A 210.189.254.50
+A IN A 208.184.174.7
+$ORIGIN US.PRSERV.net.
+NS4 IN A 165.87.201.244
+NS1 IN A 165.87.194.244
+NS3 IN A 165.87.201.243
+$ORIGIN U-NET.net.
+NS0 IN A 194.119.128.65
+NS1 IN A 194.119.128.66
+$ORIGIN HS0.U-NET.net.
+NS0 IN A 194.119.128.70
+NS1 IN A 194.119.128.71
+$ORIGIN ULTRADNS.net.
+UDNS2 IN A 204.74.101.1
+UDNS1 IN A 204.69.234.1
+$ORIGIN WEBMAGIC.net.
+NS2 IN A 64.168.49.66
+NS1 IN A 209.119.182.2
+$ORIGIN HOST4U.net.
+NS2 IN A 209.150.129.3
+NS IN A 209.150.128.30
+$ORIGIN RCCN.net.
+DNS IN A 193.136.7.17
+$ORIGIN valley.net.
+lebanon IN A 198.115.160.16
+NS2 IN A 198.115.160.16
+DNS IN A 198.115.160.10
+$ORIGIN primary.net.
+dns2 IN A 205.242.187.235
+NS2 IN A 205.242.176.103
+dns1 IN A 205.242.187.234
+NS1 IN A 205.242.92.2
+$ORIGIN SQUONK.net.
+NS2 IN A 63.84.12.135
+NS1 IN A 63.84.12.133
+$ORIGIN IP-PLUS.net.
+NS1 IN A 164.128.36.34
+$ORIGIN TECHNOLOGIA.net.
+NS2 IN A 207.253.59.4
+NS1 IN A 207.253.214.199
+NS3 IN A 195.115.180.67
+$ORIGIN VI.net.
+NS2 IN A 212.78.64.10
+NS1 IN A 194.88.77.1
+$ORIGIN ISLES.net.
+RS IN A 212.100.224.90
+$ORIGIN SOVER.net.
+time IN CNAME garnet.sover.net.
+mqueue IN A 209.198.87.52
+etrn IN A 209.198.87.58
+garnet IN A 209.198.87.53
+MAPLE IN A 209.198.87.41
+CLOVER IN A 209.198.87.40
+mail IN A 209.198.87.53
+ IN A 209.198.87.34
+mqueue0 IN A 209.198.87.52
+$ORIGIN ACT2000.net.
+ACT2 IN A 207.42.132.227
+ACT1 IN A 207.42.132.226
+$ORIGIN AKADNS.net.
+ZA IN A 209.185.188.39
+ZB IN A 216.32.65.105
+ZC IN A 204.178.107.227
+ZD IN A 204.178.110.67
+ZE IN A 216.200.14.118
+ZF IN A 208.5.85.132
+ZG IN A 206.132.160.36
+ZH IN A 63.208.48.42
+$ORIGIN NS.ESAT.net.
+NS3 IN A 192.111.39.100
+$ORIGIN THEPLANET.net.
+EARTH IN A 195.92.195.222
+PLUTO IN A 194.207.6.30
+VENUS IN A 194.152.65.222
+$ORIGIN UU.net.
+uunet IN MX 10 Mail.uu.net.
+external-mail-router IN A 198.5.241.39
+ IN A 198.5.241.38
+ IN A 198.5.241.40
+NS IN A 137.39.1.3
+$ORIGIN NS.DE.UU.net.
+AUTH03 IN A 192.76.144.16
+$ORIGIN NS.UU.net.
+AUTH100 IN A 198.6.1.202
+AUTH00 IN A 198.6.1.65
+AUTH02 IN A 198.6.1.82
+AUTH03 IN A 198.6.1.83
+AUTH60 IN A 198.6.1.181
+AUTH61 IN A 198.6.1.182
+AUTH110 IN A 198.6.1.114
+AUTH50 IN A 198.6.1.161
+AUTH51 IN A 198.6.1.162
+$ORIGIN PIONEERNET.net.
+DNS2 IN A 208.240.196.10
+DNS1 IN A 208.240.196.9
+$ORIGIN HOME.net.
+NS2 IN A 24.2.0.27
+NS1 IN A 24.0.0.27
+$ORIGIN QUANTIFIED.net.
+NS2 IN A 63.212.171.3
+NS1 IN A 63.212.171.2
+$ORIGIN SECURE.net.
+NS2 IN A 161.58.9.10
+NS1 IN A 192.41.1.10
+$ORIGIN DSL.net.
+NS2 IN A 209.87.79.232
+NS1 IN A 209.87.64.70
+$ORIGIN JA.net.
+NS0 IN A 128.86.1.20
+ IN A 193.63.94.20
+$ORIGIN ULCC.JA.net.
+NOC IN A 193.63.94.25
+$ORIGIN CINE.net.
+NS2 IN A 207.168.250.12
+$ORIGIN ANS.net.
+NS-02B IN A 207.24.245.178
+NS-01B IN A 199.221.47.8
+NS-02A IN A 207.24.245.179
+NS-01A IN A 199.221.47.7
+$ORIGIN OAR.net.
+NS2 IN A 192.88.195.10
+NS1 IN A 192.88.193.144
+$ORIGIN MAHNET.net.
+NS2 IN A 207.219.173.132
+NS1 IN A 24.69.168.121
+$ORIGIN NCREN.net.
+REGGAE IN A 128.109.131.3
+NCNOC IN A 192.101.21.1
+$ORIGIN AMERICA.net.
+AUTH2 IN A 209.17.197.18
+AUTH1 IN A 209.17.197.2
+$ORIGIN EXODUS.net.
+NS2 IN A 207.82.198.150
+NS IN A 206.79.230.10
+NS3 IN A 206.79.240.13
+$ORIGIN NJ.EXODUS.net.
+NS2 IN A 209.1.10.234
+NS IN A 206.79.7.50
+$ORIGIN DOUBLECLICK.net.
+uunymdgds1 IN A 206.65.183.21
+dcnymdgds1 IN A 204.253.104.202
+exnjmdgds1 IN A 209.67.38.22
+dcnyadgds1 IN A 204.253.104.11
+bbvamdgds1 IN A 128.11.60.75
+exnjadgds1 IN A 209.67.38.48
+annyadgds1 IN A 208.184.29.250
+annyadgds2 IN A 208.184.29.252
+cwvamdgds1 IN A 205.138.3.240
+uucamdgds1 IN A 204.178.112.124
+cwvaadgds1 IN A 205.138.3.242
+spnjadgds1 IN A 208.32.211.70
+cwvaadgds2 IN A 205.138.3.243
+ctukadgds1 IN A 213.86.246.20
+tlseadgds1 IN A 194.237.107.6
+uusjmdgds1 IN A 204.176.177.20
+uuvamdgds1 IN A 204.178.112.168
+$ORIGIN DCNY.DOUBLECLICK.net.
+NS2 IN A 204.253.104.10
+NS1 IN A 208.211.225.10
+$ORIGIN UUSJ.DOUBLECLICK.net.
+NS1 IN A 204.176.177.10
+$ORIGIN CWVA.DOUBLECLICK.net.
+NS1 IN A 205.138.3.20
+$ORIGIN DSO.net.
+NS2 IN A 206.16.77.11
+NS1 IN A 206.16.77.10
+$ORIGIN GIP.net.
+NS2 IN A 204.59.1.222
+NS1 IN A 204.59.144.222
+NS3 IN A 204.59.64.222
+$ORIGIN AMNIC.net.
+NS IN A 195.250.64.90
+$ORIGIN TELSTRA.net.
+NS1 IN A 139.130.4.5
+$ORIGIN ELI.net.
+NS2 IN A 207.173.86.2
+NS IN A 209.63.0.2
+$ORIGIN TWNIC.net.
+NS IN A 192.83.166.11
+$ORIGIN BAHNHOF.net.
+NS2 IN A 212.85.64.4
+NS1 IN A 195.178.160.2
+$ORIGIN ivm.net.
+ns1 IN A 62.204.1.1
+$ORIGIN BEACHSHORE.net.
+NS1 IN A 199.166.31.250
+$ORIGIN TDS.net.
+NS IN A 204.246.1.20
+$ORIGIN FIRSTWORLD.net.
+NS4 IN A 216.7.160.162
+NS2 IN A 216.127.92.78
+NS1 IN A 216.7.160.75
+NS3 IN A 216.7.160.161
+$ORIGIN centralinfo.net.
+ns2 IN A 63.102.204.130
+ns1 IN A 63.102.200.2
+$ORIGIN NOC.NULLUS.net.
+NS2 IN A 63.119.253.254
+NS3 IN A 63.168.101.254
+NS1 IN A 209.136.161.254
+$ORIGIN FREE.net.
+NS1 IN A 147.45.15.34
+$ORIGIN mediaone.net.
+NS1 IN A 24.128.1.80
+NS2 IN A 24.128.1.81
+$ORIGIN MW.mediaone.net.
+NS1 IN A 24.131.1.8
+$ORIGIN JVNC.net.
+NISC IN A 128.121.50.7
+$ORIGIN NS.NYC1.GLOBIX.net.
+Z1 IN A 209.10.66.55
+$ORIGIN NS.LHR1.GLOBIX.net.
+Z1 IN A 212.111.32.38
+$ORIGIN NS.SJC1.GLOBIX.net.
+Z1 IN A 209.10.34.55
+$ORIGIN akamaitech.net.
+za IN A 204.178.107.226
+n6g IN A 216.52.121.175
+ZB IN A 128.11.47.240
+n2g IN A 216.52.56.47
+ZC IN A 216.32.65.14
+ZD IN A 38.144.120.147
+n5g IN A 216.52.56.33
+ZE IN A 216.200.14.134
+n1g IN A 216.52.56.36
+ZF IN A 204.178.110.73
+n8g IN A 216.52.56.33
+ZG IN A 209.185.188.14
+n4g IN A 216.52.56.33
+ZH IN A 213.161.66.165
+n0g IN A 216.52.56.33
+n7g IN A 216.52.196.5
+n3g IN A 216.52.56.48
+$ORIGIN THNIC.net.
+NS-AIT IN A 192.41.170.219
+NS IN A 202.28.0.1
+$ORIGIN connriver.net.
+mailer IN A 63.93.137.13
+ns2 IN A 208.240.246.5
+netserver IN A 204.249.74.100
+$ORIGIN IT.net.
+DNS2 IN A 151.1.2.1
+DNS IN A 151.1.1.1
+$ORIGIN D4P.net.
+foolusmf IN CNAME a100.g.akamai.net.
+$ORIGIN LUCKY.net.
+NS IN A 193.193.193.100
+$ORIGIN SENET.net.
+NS IN A 206.155.163.195
+$ORIGIN RIPE.net.
+NS IN A 193.0.0.193
+$ORIGIN ADELPHIA.net.
+NS2 IN A 24.48.62.35
+NS3 IN A 208.239.78.134
+NS1 IN A 24.48.43.3
+$ORIGIN cdp.ADELPHIA.net.
+mx1 IN A 24.48.58.221
+$ORIGIN buf.ADELPHIA.net.
+mx1 IN A 24.48.36.10
+$ORIGIN INTERNIC.net.
+NS2 IN A 198.41.0.11
+$ORIGIN UNDPBI.TELEPAC.net.
+SOL IN A 194.65.87.2
+$ORIGIN KRNIC.net.
+NS1 IN A 202.30.50.51
+NS IN A 202.30.50.50
+$ORIGIN UNI2.net.
+NS2 IN A 195.82.195.99
+NS IN A 129.142.7.99
+$ORIGIN GTLD-SERVERS.net.
+K IN A 213.177.194.5
+A IN A 198.41.3.38
+B IN A 203.181.106.5
+M IN A 202.153.114.101
+C IN A 205.188.185.18
+D IN A 208.206.240.5
+E IN A 207.200.81.69
+F IN A 198.17.208.67
+G IN A 198.41.3.101
+I IN A 192.36.144.133
+J IN A 210.132.100.101
+$ORIGIN dns.swip.net.
+kista IN A 192.71.220.9
+$ORIGIN RCPIP.net.
+EKEKO IN A 209.45.127.2
+$ORIGIN UNA.net.
+ENGINE1 IN A 208.136.52.74
+$ORIGIN hcr.net.
+ns IN A 208.240.246.4
+$ORIGIN NSIREGISTRY.net.
+NS2 IN A 198.41.3.108
+$ORIGIN SUBTEND.net.
+NAVI IN A 208.186.117.224
+NS1 IN A 208.186.117.71
+$ORIGIN IAD.GBLX.net.
+NAME IN A 204.152.166.155
+$ORIGIN PHX.GBLX.net.
+NAME IN A 206.165.6.10
+$ORIGIN ROC.GBLX.net.
+NAME IN A 209.130.187.10
+$ORIGIN SHOREHAM.net.
+pop IN CNAME shoreham.net.
+$ORIGIN GREENMOUNTAINACCESS.net.
+NS2 IN A 208.144.252.31
+NS1 IN A 208.144.252.30
+$ORIGIN MINDSPRING.net.
+SCRATCHY IN A 207.69.200.211
+ITCHY IN A 207.69.200.210
+$ORIGIN RIPN.net.
+NS2 IN A 195.209.0.6
+NS IN A 194.85.119.1
+$ORIGIN CWCI.net.
+NS0 IN A 194.6.79.162
+$ORIGIN GBMTECH.net.
+NS2 IN A 208.243.164.3
+NS1 IN A 208.243.164.2
+$ORIGIN vrx.net.
+pedic-med IN A 199.166.24.2
+ns2 IN A 65.196.80.102
+ns3 IN A 199.166.24.3
+ns1 IN A 199.166.24.1
+ IN A 216.13.76.2
+$ORIGIN globalnetisp.net.
+NS2 IN A 207.136.213.2
+NS1 IN A 207.136.213.1
+$ORIGIN MYNET.net.
+FAITH IN A 207.13.11.2
+$ORIGIN ADNS.net.
+NS2 IN A 199.5.157.3
+KOVU IN A 199.5.157.52
+NS1 IN A 199.5.157.2
+$ORIGIN DIEBOLD.net.
+NS1 IN A 65.196.80.10
+$ORIGIN JPS.net.
+NS2 IN A 216.224.156.252
+NS1 IN A 216.119.0.192
+$ORIGIN NETNAMES.net.
+NS2 IN A 212.53.77.28
+NS1 IN A 212.53.64.60
+$ORIGIN RIO.net.
+ORSTOM IN A 192.33.151.1
+$ORIGIN com.
+sherickpm IN MX 10 inbound.sherickpm.com.criticalpath.net.
+ultradevices IN A 209.249.61.20
+verisign IN A 205.139.94.60
+vermontel IN A 204.164.106.2
+ IN MX 0 pop.vermontel.net.
+TOPICA IN A 206.132.75.196
+unknown IN A 168.143.148.168
+vietmercury IN A 207.1.134.34
+moonmothers IN A 24.218.253.157
+ IN MX 10 costorf.ne.mediaone.net.
+vhv IN MX 0 mail.vhv.com.
+BURSTNET IN MX 15 mail.ar.com.
+ IN MX 5 ibd.ar.com.
+velco IN A 207.217.96.41
+ IN A 207.217.96.42
+ IN A 207.217.96.43
+ IN A 207.217.96.44
+ IN A 207.217.96.45
+ IN A 207.217.96.28
+ IN A 207.217.96.29
+ IN A 207.217.96.30
+ IN A 207.217.96.31
+ IN A 207.217.96.32
+ IN A 207.217.96.33
+ IN A 207.217.96.34
+ IN A 207.217.96.35
+ IN A 207.217.96.36
+ IN A 207.217.96.37
+ IN A 207.217.96.38
+ IN A 207.217.96.39
+ IN A 207.217.96.40
+ IN MX 10 mail.velco.com.
+ffic IN A 64.84.58.128
+ IN MX 5 mail.mailconnect.com.
+overstock IN A 64.78.130.251
+madriver IN MX 10 bend.madriver.com.
+catic1 IN MX 10 Mail.catic1.com.
+ IN MX 20 smtp-Relay.CTCCom.net.
+goldstats IN A 66.33.12.17
+nominum IN A 204.152.184.170
+hill IN A 208.162.106.6
+ IN MX 20 mail.hill.com.
+garmontusa IN MX 20 mail.garmontusa.com.
+bt IN A 62.7.244.127
+xraylitho IN MX 10 mail.sover.net.
+ IN MX 20 mqueue.sover.net.
+glaxowellcome IN MX 10 firewall1.glaxowellcome.com.
+ IN MX 10 firewall3.glaxowellcome.com.
+nova-data IN A 64.70.144.14
+ IN MX 10 mail.nova-data.com.
+AVENUEA IN MX 100 mail2.louisdreyfus.co.uk.
+ IN MX 10 ldfwsvr2.l-dreyfus.com.
+ IN MX 50 ldfwsvr02-hme1.l-dreyfus.com.
+ IN MX 75 mail.louisdreyfus.co.uk.
+best IN MX 10 mail1.best.com.
+ IN MX 10 mail2.best.com.
+ IN MX 20 mail3.best.com.
+ IN MX 20 mail4.best.com.
+biketrack IN MX 20 mqueue.sover.net.
+ IN MX 10 mail.sover.net.
+ilovedomain IN A 211.175.164.170
+symquest IN A 64.69.102.131
+ IN MX 10 Quest-7.symquest.com.
+QUEST-NET IN A 207.140.30.11
+ IN MX 5 mail.quest-net.com.
+cacheware IN A 209.128.82.20
+Algebra IN A 208.233.99.160
+gmcr IN A 12.34.108.130
+ IN MX 10 gateway1.gmcr.com.
+YAHOO IN A 216.115.108.243
+ IN A 216.115.108.245
+ogud IN MX 90 smtp.elistx.com.
+ IN MX 10 mail.dc.ogud.com.
+costorf IN A 24.218.253.157
+ IN MX 10 costorf.ne.mediaone.net.
+highmeadow IN A 207.136.209.6
+ IN MX 10 hm6.vt.highmeadow.com.
+ IN MX 20 mqueue.sover.net.
+broadsoft IN A 208.39.36.48
+cmates IN MX 10 popmail.u-net.com.
+mt-mansfield IN A 208.153.85.16
+ IN MX 10 mail.pshift.net.
+ IN MX 30 pomail.pshift.com.
+skiinsurance IN MX 10 mail.skiinsurance.com.
+ IN MX 20 etrn.sover.net.
+map IN A 206.98.40.150
+idx IN MX 30 isdev.idx.com.
+ IN MX 50 drawbridge.idx.com.
+ IN MX 10 idx.idx.com.
+ IN MX 20 bvtsweeper.idx.com.
+msgbox IN A 216.71.82.42
+sleepycat IN A 192.41.61.122
+cisco IN A 198.133.219.25
+ IN MX 10 proxy2.cisco.com.
+ IN MX 10 proxy3.cisco.com.
+ IN MX 20 proxy6.cisco.com.
+ IN MX 20 proxy9.cisco.com.
+ IN MX 10 proxy1.cisco.com.
+TOAPLAN IN A 216.42.31.169
+hometownbands IN A 209.67.235.38
+smuggs IN MX 10 mail.smuggs.com.
+clothncanvas IN A 208.153.85.16
+ IN MX 10 mail.pshift.net.
+ IN MX 30 mail.pshift.com.
+quantified IN A 63.212.171.4
+arabia IN A 216.251.232.40
+bostic IN A 199.103.241.218
+verisign-grs IN A 198.41.3.55
+gdarm IN MX 10 bvt-ext.gdarm.com.
+retro IN A 205.179.181.194
+ IN MX 10 gw.retro.com.
+ IN MX 20 www.retro.com.
+ IN MX 50 mail.scruznet.com.
+vssg IN A 216.157.26.252
+jerusalem-mail IN A 216.251.232.93
+ IN MX 10 mail.jerusalem-mail.com.
+tfm IN MX 50 mtbaker.tfm.com.
+ IN MX 20 mailhost.tfm.com.
+fratfunz IN A 216.226.16.150
+elektro IN A 192.188.133.3
+WonderWorks IN A 192.203.206.65
+ IN MX 50 mail.wonderworks.com.
+fiberia IN MX 10 webmail.fiberia.com.
+tifosi IN MX 10 gutenberg.bucksnet.com.
+ivillage IN A 209.185.162.150
+pwshift IN A 208.153.85.36
+goputney IN MX 10 mail.sover.net.
+ IN MX 20 mqueue.sover.net.
+$ORIGIN IPNS.com.
+NS2 IN A 63.230.183.1
+NS IN A 208.187.190.2
+$ORIGIN appliedtheory.com.
+NS2 IN A 168.75.17.11
+NS1 IN A 204.168.28.9
+ns3 IN A 207.127.101.8
+$ORIGIN COMPUWARE.com.
+nl IN MX 150 uucp.nl.net.
+ IN MX 50 bitbucket.extern.uniface.nl.
+ IN MX 100 smtp.nl.net.
+$ORIGIN YOUR-DOMAIN.com.
+NS2 IN A 216.167.31.177
+NS1 IN A 216.167.31.176
+$ORIGIN nortelnetworks.com.
+NS-RCH IN A 192.135.215.2
+NS-OTT IN A 192.58.194.71
+ns-har IN A 192.100.101.3
+$ORIGIN SJMERCURY.com.
+BAYONET IN A 207.1.134.34
+$ORIGIN excite.com.
+NSE00 IN A 198.3.102.250
+NS00 IN A 198.3.98.250
+NSE01 IN A 198.3.102.251
+NS01 IN A 198.3.98.251
+$ORIGIN PLANET-THREE.com.
+NS0 IN A 212.49.219.164
+$ORIGIN TOKYO.JP.NETDNS.com.
+NS1 IN A 64.56.164.118
+$ORIGIN LONDON.UK.NETDNS.com.
+NS1 IN A 212.62.6.38
+$ORIGIN SANFRANCISCO.US.NETDNS.com.
+NS1 IN A 207.82.50.166
+$ORIGIN NEWYORK.US.NETDNS.com.
+NS1 IN A 216.32.212.86
+$ORIGIN SEATTLE.US.NETDNS.com.
+NS1 IN A 206.253.214.13
+$ORIGIN ARICATRA.com.
+NS IN A 206.64.112.114
+$ORIGIN REGME.com.
+NS1 IN A 207.153.57.14
+$ORIGIN ELISTX.com.
+smtp IN A 209.116.252.130
+NS IN A 209.116.252.130
+$ORIGIN SIGMAHOSTING.com.
+NS1 IN A 209.241.86.6
+$ORIGIN champcable.com.
+CCC IN A 207.41.53.11
+$ORIGIN IAFRICA.com.
+NS1 IN A 196.7.0.139
+NS3 IN A 196.7.0.137
+$ORIGIN dot-god.com.
+A-GTLD-SERVERS IN A 205.189.73.123
+B-GTLD-SERVERS IN A 205.189.71.10
+$ORIGIN CONRADPROMOTIONS.com.
+NS2 IN A 208.24.118.203
+NS1 IN A 208.158.96.118
+$ORIGIN onemain.com.
+ns4 IN A 63.208.210.11
+NS2 IN A 166.90.148.68
+NS1 IN A 166.90.148.67
+ns3 IN A 63.208.210.10
+$ORIGIN SIMORGH.com.
+NS1 IN A 209.1.163.10
+$ORIGIN Christ.com.
+Yeshua IN A 207.54.4.5
+Abba IN A 63.229.15.59
+$ORIGIN TRAVELPHOTOCONTESTS.com.
+www IN A 64.85.86.156
+$ORIGIN WEB2010.com.
+NS4 IN A 216.157.55.6
+NS2 IN A 216.157.79.246
+NS3 IN A 216.157.47.6
+NS IN A 209.235.31.149
+$ORIGIN 2DAY.com.
+NS2 IN A 202.89.128.74
+NS1 IN A 202.37.240.13
+NS3 IN A 209.240.128.25
+$ORIGIN NETSCAPE.com.
+tdns-me1 IN A 205.188.247.67
+tdns-me2 IN A 205.188.247.68
+tdns2 IN A 207.200.77.53
+tdns3 IN A 207.200.73.72
+NS IN A 198.95.251.10
+NS2 IN A 207.200.73.80
+$ORIGIN WWEBSVS.com.
+PAPPILLOMA IN A 209.233.37.10
+$ORIGIN vermontel.com.
+ns1 IN A 204.164.106.2
+$ORIGIN LA.TIS.com.
+RELAY IN A 198.51.22.11
+$ORIGIN MSEN.com.
+DNS IN A 148.59.19.11
+$ORIGIN bungi.com.
+DAVER IN A 206.14.228.2
+ IN A 207.126.97.2
+max IN A 206.14.228.7
+ IN A 207.126.97.7
+$ORIGIN SPEEDHOST.com.
+NS2 IN A 216.42.31.169
+NS3 IN A 216.42.31.130
+$ORIGIN GPG.com.
+NS2 IN A 209.1.163.50
+NS1 IN A 209.1.163.30
+$ORIGIN NL.CONCENTRIC.com.
+NS1 IN A 195.18.114.5
+$ORIGIN SJC.LYCOS.com.
+SJC-NS2 IN A 206.79.171.40
+SJC-NS1 IN A 206.79.171.39
+$ORIGIN BOS.LYCOS.com.
+BOS-NS2 IN A 209.67.228.40
+BOS-NS1 IN A 209.67.228.39
+$ORIGIN TOPICA.com.
+NS3 IN A 206.111.131.72
+ns-ext IN A 206.132.75.195
+inmta011 IN A 206.132.75.197
+inmta009 IN A 206.132.75.226
+dns IN A 206.111.131.72
+outmta004 IN A 206.132.75.201
+inmta001 IN A 206.132.75.197
+ IN A 206.111.131.79
+inmta003 IN A 206.132.75.213
+outmta010 IN A 206.132.75.222
+inmta005 IN A 206.132.75.217
+NS1 IN A 206.132.75.195
+NS2 IN A 208.184.76.200
+$ORIGIN DOLEH.com.
+NS IN A 204.255.25.63
+$ORIGIN BSDI.com.
+NS IN A 207.174.116.8
+$ORIGIN NYTIMES.com.
+GATEKEEPER IN A 199.181.175.201
+$ORIGIN GDGSC.com.
+NS0 IN A 192.160.62.66
+NS2 IN A 204.162.124.66
+$ORIGIN EDIGITALS.com.
+NS2 IN A 211.39.139.36
+NS3 IN A 211.175.164.170
+NS1 IN A 211.39.139.35
+$ORIGIN INTERNETSQUARE.com.
+NS2 IN A 205.227.232.9
+NS1 IN A 216.226.16.146
+$ORIGIN MAIL.com.
+NS2 IN A 165.251.1.3
+GTLD IN A 165.251.1.239
+NS1 IN A 165.251.1.2
+$ORIGIN moonmothers.com.
+localhost IN A 127.0.0.1
+www IN CNAME moonmothers.com.
+$ORIGIN vhv.com.
+mail IN A 208.5.161.11
+$ORIGIN BOCA15-VERIO.com.
+NS15B IN A 208.55.91.51
+NS15A IN A 208.55.91.50
+$ORIGIN ar.com.
+ns2 IN A 64.124.80.42
+ibd IN A 63.194.205.75
+mail IN A 63.194.205.74
+NS1 IN A 63.194.205.74
+$ORIGIN BLIPP.com.
+VIC20 IN A 195.163.165.35
+$ORIGIN CONCOURSE.com.
+NS IN A 199.218.113.2
+$ORIGIN velco.com.
+mail IN A 198.136.217.106
+$ORIGIN FLONETWORK.com.
+UUNS1DNS1 IN A 209.167.79.5
+UUNS1DNS2 IN A 209.167.79.6
+$ORIGIN overstock.com.
+NS1 IN A 207.225.194.13
+$ORIGIN NEWACCOUNT.com.
+NS4 IN A 209.78.16.6
+NS2 IN A 209.78.16.5
+NS3 IN A 216.121.32.205
+NS IN A 216.121.32.10
+$ORIGIN tridog.com.
+NS2 IN A 206.168.112.51
+TRIDOG1 IN A 206.168.112.71
+$ORIGIN madriver.com.
+bend IN A 207.136.232.15
+FUSION IN A 207.136.232.11
+PRIMUS IN A 207.136.232.12
+$ORIGIN catic1.com.
+Mail IN A 207.190.204.103
+$ORIGIN IBD.com.
+NIC IN A 209.249.61.18
+$ORIGIN IOM.com.
+PEBBLES IN A 194.72.124.1
+$ORIGIN nominum.com.
+shell IN A 204.152.187.59
+GNS2 IN A 198.133.199.2
+gns1 IN A 198.133.199.1
+$ORIGIN ATLONLINE.com.
+ATLNET IN A 207.153.72.193
+ATLWEB1 IN A 207.153.72.194
+$ORIGIN hill.com.
+SYRUP IN A 208.162.106.3
+$ORIGIN garmontusa.com.
+mail IN A 64.30.8.178
+$ORIGIN VIX.com.
+NS-EXT IN A 204.152.184.64
+ns-int IN A 204.152.184.65
+$ORIGIN rc.VIX.com.
+db IN A 204.152.187.21
+$ORIGIN SOVAM.com.
+NS IN A 194.67.2.97
+$ORIGIN IOS.com.
+NOC IN A 198.4.75.69
+$ORIGIN BOSTON.juno.com.
+NS IN A 64.136.25.53
+$ORIGIN JERSEY.juno.com.
+NS IN A 64.136.17.178
+$ORIGIN NYC.juno.com.
+NS IN A 205.231.108.1
+$ORIGIN MEITCA.com.
+NS1 IN A 137.203.5.1
+$ORIGIN glaxowellcome.com.
+firewall3 IN A 192.58.204.207
+firewall1 IN A 192.58.204.204
+NS IN A 192.58.204.113
+$ORIGIN EPILOGUE.com.
+QUERN IN A 128.224.1.136
+$ORIGIN CLASSIFIEDMONSTER.com.
+NS1 IN A 216.254.54.22
+$ORIGIN nova-data.com.
+mail IN A 12.16.110.35
+$ORIGIN corning.com.
+GATEKEEPER IN A 149.42.1.2
+$ORIGIN a1.YIMG.com.
+us IN CNAME a32.g.a.yimg.com.
+$ORIGIN i1.YIMG.com.
+us IN CNAME a1.g.a.yimg.com.
+$ORIGIN nc.us.IBM.com.
+e24 IN A 32.97.136.230
+e22 IN A 32.97.136.228
+e23 IN A 32.97.136.229
+e21 IN A 32.97.136.227
+$ORIGIN co.us.IBM.com.
+e34 IN A 32.97.110.132
+e32 IN A 32.97.110.130
+e33 IN A 32.97.110.131
+e31 IN A 32.97.110.129
+$ORIGIN ny.us.IBM.com.
+e4 IN A 32.97.182.104
+e2 IN A 32.97.182.102
+e3 IN A 32.97.182.103
+e1 IN A 32.97.182.101
+$ORIGIN AUSTIN.IBM.com.
+NS IN A 192.35.232.34
+$ORIGIN ZURICH.IBM.com.
+INTERNET-SERVER IN A 195.212.119.252
+$ORIGIN ALMADEN.IBM.com.
+NS IN A 198.4.83.35
+$ORIGIN ERS.IBM.com.
+NS IN A 204.146.173.35
+$ORIGIN WATSON.IBM.com.
+NS IN A 198.81.209.2
+$ORIGIN DCCSERVER.com.
+GODFEVER IN A 208.137.22.6
+$ORIGIN SUN.com.
+saturn IN A 192.9.25.2
+venus IN A 192.9.25.5
+east IN MX 40 mars.sun.com.
+ IN MX 40 mondzo.sun.com.
+ IN MX 5 venus.sun.com.
+ IN MX 5 lukla.sun.com.
+ IN MX 5 saturn.sun.com.
+ IN MX 5 patan.sun.com.
+ IN MX 15 mercury.sun.com.
+mondzo IN A 192.18.100.1
+lukla IN A 192.18.98.31
+NS-BRM IN A 192.18.99.5
+ns-os IN A 192.9.9.6
+patan IN A 192.18.98.43
+mars IN A 192.9.22.1
+mercury IN A 192.9.25.1
+NS IN A 192.9.9.3
+$ORIGIN pr.SUN.com.
+ns1 IN A 192.18.16.2
+$ORIGIN eu.SUN.com.
+ns1 IN A 192.18.240.8
+$ORIGIN USEC.SUN.com.
+NS IN A 192.9.48.3
+$ORIGIN PSHIFT.com.
+ns2 IN A 208.153.85.21
+NS1 IN A 208.153.85.20
+$ORIGIN mobydark.com.
+ns1 IN A 216.13.76.21
+$ORIGIN compuserve.com.
+DUB-NAME-SVC-1 IN A 149.174.213.5
+ARL-NAME-SVC-1 IN A 149.174.211.5
+$ORIGIN NS.cs.com.
+DNS-02 IN A 205.188.157.235
+DNS-01 IN A 152.163.159.235
+$ORIGIN pcode.com.
+ns1 IN A 216.15.192.135
+$ORIGIN AVENUEA.com.
+EX2-DNS0 IN A 216.34.88.20
+SEA2DNS IN A 63.251.8.150
+$ORIGIN PHOTOTRUST.com.
+Filer IN A 64.85.86.172
+NS02 IN A 64.85.86.142
+www IN A 64.85.86.151
+NS01 IN A 64.85.86.141
+$ORIGIN GOOGLE.com.
+HEDNS1 IN A 64.209.200.10
+helbdns IN A 64.209.200.252
+valbdns IN A 216.239.37.252
+exlbdns IN A 64.208.34.252
+sulbdns IN A 64.208.32.252
+NS IN A 209.185.108.134
+sjlbdns IN A 216.239.35.252
+NS2 IN A 209.185.108.135
+$ORIGIN ns0.com.
+NS00 IN A 216.92.60.60
+ns0 IN A 209.197.64.1
+$ORIGIN best.com.
+NS3 IN A 209.24.149.42
+mail2 IN A 206.184.139.12
+ IN A 206.184.139.13
+ IN A 206.184.139.16
+ IN A 206.184.139.18
+mail3 IN A 206.184.139.12
+ IN A 206.184.139.13
+ IN A 206.184.139.16
+ IN A 206.184.139.18
+mail4 IN A 206.184.139.12
+ IN A 206.184.139.13
+ IN A 206.184.139.16
+ IN A 206.184.139.18
+NS1 IN A 209.24.149.41
+mail1 IN A 206.184.139.12
+ IN A 206.184.139.13
+ IN A 206.184.139.16
+ IN A 206.184.139.18
+NS2 IN A 209.157.102.11
+$ORIGIN WESTOL.com.
+NS IN A 63.93.137.4
+$ORIGIN ilovedomain.com.
+ns IN A 211.175.164.170
+$ORIGIN symquest.com.
+Quest-7 IN A 64.69.102.131
+$ORIGIN QUEST-NET.com.
+mail IN A 207.140.30.11
+NS2 IN A 207.140.30.13
+NS1 IN A 207.140.30.11
+$ORIGIN cavebear.com.
+p2 IN A 199.184.128.35
+npax IN A 192.203.17.71
+$ORIGIN cacheware.com.
+ns1 IN A 64.221.210.242
+$ORIGIN Algebra.com.
+ns3 IN A 216.254.54.22
+ns1 IN A 160.79.196.177
+NS5 IN A 208.233.99.161
+$ORIGIN gmcr.com.
+gateway1 IN A 12.34.108.130
+$ORIGIN YAHOO.com.
+NS1 IN A 204.71.200.33
+$ORIGIN EUROPE.YAHOO.com.
+NS3 IN A 217.12.4.71
+$ORIGIN DCX.YAHOO.com.
+NS5 IN A 216.32.74.10
+$ORIGIN GRANITECANYON.com.
+NS2 IN A 204.1.217.148
+NS1 IN A 205.166.226.38
+$ORIGIN costorf.com.
+localhost IN A 127.0.0.1
+www IN CNAME costorf.com.
+$ORIGIN PSG.com.
+RAIN IN A 147.28.0.34
+RIP IN A 147.28.0.39
+$ORIGIN vt.highmeadow.com.
+hm6 IN A 207.136.209.6
+$ORIGIN btinternet.com.
+DNS2 IN A 194.73.73.94
+DNS1 IN A 194.73.73.95
+$ORIGIN INTERNET-TOOLS.com.
+NS2 IN A 206.109.113.140
+NS IN A 208.239.1.2
+NS3 IN A 38.153.179.2
+$ORIGIN CADABRA.com.
+NS2 IN A 209.157.194.109
+NS IN A 209.143.240.148
+$ORIGIN SLOWMOE.com.
+NS2 IN A 137.118.8.50
+NS1 IN A 137.118.8.49
+$ORIGIN ZTNET.com.
+NS2 IN A 63.211.17.252
+NS1 IN A 63.211.17.251
+$ORIGIN HOTWIRED.com.
+NS2 IN A 209.185.151.6
+NS4 IN A 209.185.151.4
+NS1 IN A 216.32.228.8
+NS3 IN A 216.32.228.9
+$ORIGIN g-world.com.
+NS1 IN A 216.26.39.10
+$ORIGIN alcatrazmedia.com.
+ns1 IN A 167.160.132.2
+$ORIGIN MESSAGESECURE.com.
+KYNSE02 IN A 216.142.252.201
+KYNSE01 IN A 216.142.252.199
+$ORIGIN HAITIWORLD.com.
+APPSRV IN A 206.152.15.34
+NS IN A 206.152.15.33
+$ORIGIN NETSOL.com.
+NS2 IN A 198.17.208.71
+RS0 IN A 216.168.224.206
+NS3 IN A 216.168.224.201
+NS1 IN A 216.168.224.200
+$ORIGIN cmates.com.
+NS-AUTH2 IN A 208.23.213.3
+ns-auth1 IN A 208.23.213.2
+$ORIGIN skiinsurance.com.
+mail IN A 207.136.205.152
+$ORIGIN GH.com.
+AUSTIN IN A 196.3.64.1
+$ORIGIN DIGISERVE.com.
+NS2 IN A 204.91.84.216
+NS1 IN A 151.196.69.5
+$ORIGIN map.com.
+sgi1 IN A 204.71.19.20
+WORMHOLE IN A 204.71.19.10
+$ORIGIN SNS-UT.DEBIS.com.
+NS2 IN A 53.122.2.10
+$ORIGIN SNS-FELB.DEBIS.com.
+NS1 IN A 53.122.1.10
+$ORIGIN idx.com.
+seaipsvcs IN A 172.22.64.42
+BOSDOC IN A 198.114.171.109
+drawbridge IN A 204.165.241.2
+IDXNMS IN A 204.165.242.7
+idx IN A 198.114.171.160
+isdev IN A 198.181.234.9
+bvtipsvcs IN A 198.114.172.50
+bosdns IN A 198.114.171.109
+bvtsweeper IN A 198.181.234.69
+$ORIGIN VERITAS.com.
+NS IN A 204.177.156.38
+$ORIGIN BFG.com.
+gateway2 IN A 166.102.214.66
+aisvt IN MX 0 gateway2.bfg.com.
+GATEWAY IN A 131.187.253.2
+$ORIGIN sleepycat.com.
+abyssinian IN A 199.103.241.218
+$ORIGIN cisco.com.
+proxy6 IN A 203.41.198.245
+proxy9 IN A 192.135.250.71
+proxy1 IN A 192.31.7.88
+proxy2 IN A 192.31.7.89
+proxy3 IN A 192.31.7.90
+ns1 IN A 128.107.241.185
+NS2 IN A 192.135.250.69
+$ORIGIN TOAPLAN.com.
+www IN A 216.42.31.169
+$ORIGIN INTUIT.com.
+DNS1 IN A 208.157.255.4
+$ORIGIN REGEX.com.
+NS1 IN A 202.152.12.227
+$ORIGIN DEC.com.
+crl IN A 192.58.206.2
+ns IN A 204.123.2.42
+$ORIGIN PA.DEC.com.
+UUCP-GW-2 IN A 16.1.0.19
+UUCP-GW-1 IN A 16.1.0.18
+ IN A 204.123.2.18
+$ORIGIN LANDLORDS.com.
+NS IN A 63.64.164.68
+$ORIGIN hometownbands.com.
+www IN A 209.67.235.38
+$ORIGIN MSFT.AKADNS.com.
+Z6 IN A 207.229.152.20
+Z2 IN A 32.96.80.17
+Z4 IN A 208.148.96.220
+Z7 IN A 213.161.66.158
+Z3 IN A 63.215.198.67
+Z1 IN A 216.32.118.104
+$ORIGIN smuggs.com.
+mail IN A 209.67.230.71
+$ORIGIN OUTREMER.com.
+MANTA IN A 213.16.1.106
+$ORIGIN hns.com.
+HNS3 IN A 208.236.67.3
+$ORIGIN TRIVALLEY.com.
+NS3 IN A 206.25.132.30
+$ORIGIN AI-R.com.
+NS2 IN A 66.33.4.51
+NS1 IN A 66.33.0.143
+$ORIGIN ALCATEL.com.
+NS IN A 192.160.6.91
+PRIMARY IN A 192.160.6.90
+$ORIGIN GENDYN.com.
+NET2 IN A 204.60.171.9
+NET1 IN A 204.60.171.8
+$ORIGIN ONLINEPHOTOCONTEST.com.
+www IN A 64.85.86.152
+$ORIGIN performancediver.com.
+listserv IN A 216.34.185.155
+$ORIGIN rge.com.
+gw IN A 157.225.178.11
+$ORIGIN NS.AOL.com.
+DNS-02 IN A 205.188.157.232
+DNS-01 IN A 152.163.159.232
+$ORIGIN MANY-PATHS-ENERGY-ENHANCEMENT.com.
+www IN A 66.33.4.50
+$ORIGIN IS.CHRYSLER.com.
+FXCLPR02 IN A 204.189.94.37
+FXIOD01 IN A 204.189.94.70
+$ORIGIN TO.GD-ES.com.
+NS IN A 199.107.240.66
+$ORIGIN GNAC.com.
+ns2 IN A 209.182.195.77
+NS1 IN A 209.182.195.77
+$ORIGIN AKAMAI.com.
+YA IN A 204.178.118.68
+ACCESS IN A 4.17.143.9
+YB IN A 204.212.232.16
+YC IN A 209.246.46.48
+YD IN A 209.189.112.39
+YE IN A 192.215.168.18
+YF IN A 216.32.118.14
+YG IN A 204.178.110.35
+YH IN A 128.11.61.225
+$ORIGIN QUICKEN.com.
+DNS4 IN A 198.3.99.252
+DNS2 IN A 206.154.105.67
+news IN MX 10 mail1.emailpub.com.
+ IN MX 10 mail2.emailpub.com.
+ IN MX 10 mail3.emailpub.com.
+ IN MX 10 mail4.emailpub.com.
+ IN MX 10 mail5.emailpub.com.
+ IN MX 10 mail6.emailpub.com.
+ IN A 207.211.106.100
+DNS3 IN A 198.3.96.252
+DNS1 IN A 206.154.105.66
+$ORIGIN LUXNOC.com.
+NS4 IN A 195.206.104.201
+NS2 IN A 195.206.105.102
+NS0 IN A 195.206.105.1
+NS5 IN A 195.206.104.211
+NS3 IN A 195.206.104.1
+NS1 IN A 195.206.105.101
+$ORIGIN MAGIC-MOMENTS.com.
+NS1 IN A 195.224.53.80
+$ORIGIN ABAC.com.
+NS2 IN A 216.55.144.4
+NS1 IN A 216.55.128.4
+$ORIGIN GOTO.com.
+NS2 IN A 204.71.128.137
+NS1 IN A 206.132.152.241
+$ORIGIN WEBTRENDS.com.
+NS2 IN A 63.88.212.11
+NS1 IN A 63.88.212.10
+$ORIGIN hotmail.com.
+NS3 IN A 209.185.130.68
+NS1 IN A 216.200.206.140
+$ORIGIN MERCHANTWARE.com.
+NS2 IN A 209.170.142.35
+$ORIGIN MERCURYCENTER.com.
+cgi IN CNAME vh80167.vh8.infi.net.
+$ORIGIN CARIBSURF.com.
+COL2 IN A 205.214.192.202
+COL1 IN A 205.214.192.201
+$ORIGIN MAIL-LIST.com.
+zip IN MX 20 sluice.mail-list.com.
+ IN MX 20 pipeline.mail-list.com.
+ IN MX 20 transport.mail-list.com.
+ IN MX 50 swifty.mail-list.com.
+ IN MX 50 velocity.mail-list.com.
+ IN MX 50 brisk.mail-list.com.
+ IN MX 5 zip.mail-list.com.
+$ORIGIN NAVPOINT.com.
+south IN A 207.106.42.12
+north IN A 207.106.42.10
+NS2 IN A 207.106.42.12
+NS IN A 207.106.42.10
+$ORIGIN verisign-grs.com.
+ns2 IN A 198.41.3.108
+ns1 IN A 198.41.3.39
+$ORIGIN gdarm.com.
+bvt-ext IN A 166.19.32.42
+$ORIGIN REDHAT.com.
+NS1 IN A 216.148.218.250
+$ORIGIN SKYNETWEB.com.
+NS2 IN A 208.231.1.35
+NS1 IN A 208.231.1.34
+$ORIGIN COIL.com.
+BRONZE IN A 198.4.94.1
+$ORIGIN ZTX.COMPAQ.com.
+NS1-PUBLIC IN A 161.114.1.204
+$ORIGIN ZMA.COMPAQ.com.
+NS1-PUBLIC IN A 161.114.64.24
+$ORIGIN FOOL.com.
+NS2 IN A 208.51.76.222
+NS1 IN A 208.241.66.222
+$ORIGIN retro.com.
+www IN A 205.179.181.195
+gw IN A 205.179.181.194
+$ORIGIN NRSITE.com.
+NS5 IN A 208.178.169.4
+NS7 IN A 206.41.20.3
+NS3 IN A 199.172.144.20
+$ORIGIN jerusalem-mail.com.
+mail IN A 216.251.232.93
+$ORIGIN PAIR.com.
+ns3 IN A 209.68.1.15
+NS1 IN A 209.68.1.11
+$ORIGIN GLOBALDNS.com.
+NS1 IN A 206.253.214.11
+$ORIGIN tfm.com.
+mailhost IN A 192.231.224.11
+mtbaker IN A 192.231.224.2
+NS2 IN A 208.236.160.42
+NS1 IN A 209.83.142.82
+NS IN A 192.231.224.1
+$ORIGIN bock.com.
+NS2 IN A 64.30.29.4
+NS1 IN A 64.30.29.3
+$ORIGIN TARSUS.com.
+MAIL IN A 208.130.9.252
+BEAR IN A 208.130.9.248
+$ORIGIN NETANET.com.
+NS0 IN A 194.6.96.218
+ IN A 195.172.127.72
+NS1 IN A 194.6.96.218
+$ORIGIN SEANET.com.
+DNS2 IN A 199.181.164.2
+DNS3 IN A 199.181.164.3
+DNS1 IN A 199.181.164.1
+$ORIGIN INTERNETSHARE.com.
+NS1 IN A 63.207.108.53
+$ORIGIN ALTAVISTA.com.
+NS2 IN A 209.73.164.7
+NS3 IN A 209.73.176.204
+NS1 IN A 209.73.164.76
+$ORIGIN NOVELL.com.
+NS IN A 137.65.1.1
+$ORIGIN SAIPAN.com.
+NS2 IN A 202.128.28.2
+NS IN A 202.128.27.2
+$ORIGIN diebold.com.
+eliot IN A 204.151.249.21
+ness IN A 208.228.181.21
+$ORIGIN WonderWorks.com.
+mail IN A 192.203.206.67
+ice IN A 192.203.206.9
+$ORIGIN SIGNALZ.com.
+NS IN A 209.67.230.71
+$ORIGIN GW.tislabs.com.
+RELAY IN A 192.94.214.100
+$ORIGIN CAIS.com.
+NS IN A 205.177.10.10
+$ORIGIN tesserae.com.
+ns2 IN A 209.157.194.3
+NS IN A 209.157.194.2
+$ORIGIN NETPOLICY.com.
+MINION IN A 207.87.121.66
+$ORIGIN wirbel.com.
+enterprise IN A 194.231.54.2
+$ORIGIN fiberia.com.
+webmail IN A 216.55.147.2
+$ORIGIN BAYAREA.com.
+www IN CNAME vh80040.vh8.infi.net.
+$ORIGIN CONNACTIVITY.com.
+bparker IN A 206.34.200.200
+NS2 IN A 206.34.200.3
+CONNACTIVITY IN A 206.34.200.2
+$ORIGIN tifosi.com.
+BK IN A 208.58.189.13
+daytona IN A 192.104.156.3
+$ORIGIN bucksnet.com.
+gutenberg IN A 207.113.15.5
+$ORIGIN ivillage.com.
+NS2 IN A 209.185.162.16
+NS1 IN A 209.185.162.15
+$ORIGIN codelocal.com.
+ns1 IN A 216.15.192.130
+$ORIGIN NETFLIGHT.com.
+DNS IN A 207.88.32.2
+$ORIGIN MERCHANTWARE.CON.
+NS1 IN A 209.170.142.34
diff --git a/bin/tests/system/cacheclean/ns1/named.conf b/bin/tests/system/cacheclean/ns1/named.conf
new file mode 100644
index 0000000..9f34148
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns1/named.conf
@@ -0,0 +1,38 @@
+/*
+ * 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: named.conf,v 1.9 2007/06/19 23:47:01 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ check-integrity no;
+};
+
+zone "." {
+ type master;
+ file "example.db";
+};
diff --git a/bin/tests/system/cacheclean/ns2/named.conf b/bin/tests/system/cacheclean/ns2/named.conf
new file mode 100644
index 0000000..c0d9f44
--- /dev/null
+++ b/bin/tests/system/cacheclean/ns2/named.conf
@@ -0,0 +1,38 @@
+/*
+ * 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: named.conf,v 1.8 2007/06/19 23:47:01 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ notify yes;
+ max-cache-size 10000;
+ disable-empty-zone 127.IN-ADDR.ARPA;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/cacheclean/tests.sh b/bin/tests/system/cacheclean/tests.sh
new file mode 100644
index 0000000..7e1ba79
--- /dev/null
+++ b/bin/tests/system/cacheclean/tests.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+#
+# 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: tests.sh,v 1.5 2007/06/19 23:47:00 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+$DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat \
+ -f dig.batch -p 5300 @10.53.0.2 > dig.out.ns2 || status=1
+grep ";" dig.out.ns2
+
+$PERL ../digcomp.pl dig.out.ns2 knowngood.dig.out || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/checkconf/bad.conf b/bin/tests/system/checkconf/bad.conf
new file mode 100644
index 0000000..79d8832
--- /dev/null
+++ b/bin/tests/system/checkconf/bad.conf
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2005, 2007 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: bad.conf,v 1.4 2007/06/19 23:47:01 tbox Exp $ */
+
+options {
+ avoid-v4-udp-ports { 100; }
+ avoid-v6-udp-ports { 100; };
+ blackhole { 10.0.0.0/8; };
+ coresize 1G;
+ datasize 100M;
+ deallocate-on-exit yes;
+ directory ".";
+ dump-file "named_dumpdb";
+ fake-iquery yes;
+ files 1000;
+ has-old-clients no;
+ heartbeat-interval 30;
+ host-statistics yes;
+ host-statistics-max 100;
+ hostname none;
+ interface-interval 30;
+ listen-on port 90 { any; };
+ listen-on port 100 { 127.0.0.1; };
+ listen-on-v6 port 53 { none; };
+ match-mapped-addresses yes;
+ memstatistics-file "named.memstats";
+ multiple-cnames no;
+ named-xfer "this is no longer needed";
+ pid-file none;
+ port 5300;
+ querylog yes;
+ recursing-file "named.recursing";
+ random-device "/dev/random";
+ recursive-clients 3000;
+ serial-queries 10;
+ serial-query-rate 100;
+ server-id none;
+};
diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf
new file mode 100644
index 0000000..c810b47
--- /dev/null
+++ b/bin/tests/system/checkconf/good.conf
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2005, 2007 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: good.conf,v 1.4 2007/06/19 23:47:01 tbox Exp $ */
+
+/*
+ * This is just a random selection of configuration options.
+ */
+
+options {
+ avoid-v4-udp-ports { 100; };
+ avoid-v6-udp-ports { 100; };
+ blackhole { 10.0.0.0/8; };
+ coresize 1G;
+ datasize 100M;
+ deallocate-on-exit yes;
+ directory ".";
+ dump-file "named_dumpdb";
+ fake-iquery yes;
+ files 1000;
+ has-old-clients no;
+ heartbeat-interval 30;
+ host-statistics yes;
+ host-statistics-max 100;
+ hostname none;
+ interface-interval 30;
+ listen-on port 90 { any; };
+ listen-on port 100 { 127.0.0.1; };
+ listen-on-v6 port 53 { none; };
+ match-mapped-addresses yes;
+ memstatistics-file "named.memstats";
+ multiple-cnames no;
+ named-xfer "this is no longer needed";
+ pid-file none;
+ port 5300;
+ querylog yes;
+ recursing-file "named.recursing";
+ random-device "/dev/random";
+ recursive-clients 3000;
+ serial-queries 10;
+ serial-query-rate 100;
+ server-id none;
+};
diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh
new file mode 100644
index 0000000..8444664
--- /dev/null
+++ b/bin/tests/system/checkconf/tests.sh
@@ -0,0 +1,37 @@
+# Copyright (C) 2005, 2007 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: tests.sh,v 1.3 2007/06/19 23:47:01 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+echo "I: checking that named-checkconf handles a known good config"
+
+ret=0
+$CHECKCONF good.conf > /dev/null 2>&1 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I: checking that named-checkconf handles a known bad config"
+
+ret=1
+$CHECKCONF bad.conf > /dev/null 2>&1 || ret=0
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/checknames/clean.sh b/bin/tests/system/checknames/clean.sh
new file mode 100644
index 0000000..f0c46de
--- /dev/null
+++ b/bin/tests/system/checknames/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.6 2007/09/26 03:22:43 marka Exp $
+
+rm -f dig.out.ns?.test*
+rm -f nsupdate.out.test*
+rm -f ns1/*.example.db
+rm -f ns1/*.update.db
+rm -f ns1/*.update.db.jnl
+rm -f */named.memstats
diff --git a/bin/tests/system/checknames/ns1/fail.example.db.in b/bin/tests/system/checknames/ns1/fail.example.db.in
new file mode 100644
index 0000000..09a8557
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/fail.example.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) 2004, 2007 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: fail.example.db.in,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+$TTL 300
+@ SOA ns1.fail.example. hostmaster.fail.example. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.fail.example.
+ns1.fail.example. A 10.53.0.1
+xx_xx.fail.example. A 127.0.0.1
diff --git a/bin/tests/system/checknames/ns1/fail.update.db.in b/bin/tests/system/checknames/ns1/fail.update.db.in
new file mode 100644
index 0000000..515f23e
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/fail.update.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) 2004, 2007 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: fail.update.db.in,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+$TTL 300
+@ SOA ns1.fail.update. hostmaster.fail.update. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.fail.update.
+ns1.fail.update. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns1/ignore.example.db.in b/bin/tests/system/checknames/ns1/ignore.example.db.in
new file mode 100644
index 0000000..5def921
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/ignore.example.db.in
@@ -0,0 +1,23 @@
+; Copyright (C) 2004, 2007 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: ignore.example.db.in,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+$TTL 300
+@ SOA ns1.ignore.example. hostmaster.ignore.example. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.ignore.example.
+ns1.ignore.example. A 10.53.0.1
+yy_yy.ignore.example. A 10.53.0.1
+mx.ignore.example. MX 10 zz_zz.ignore.example.
diff --git a/bin/tests/system/checknames/ns1/ignore.update.db.in b/bin/tests/system/checknames/ns1/ignore.update.db.in
new file mode 100644
index 0000000..18826bd
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/ignore.update.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) 2004, 2007 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: ignore.update.db.in,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+$TTL 300
+@ SOA ns1.ignore.update. hostmaster.ignore.update. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.ignore.update.
+ns1.ignore.update. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns1/named.conf b/bin/tests/system/checknames/ns1/named.conf
new file mode 100644
index 0000000..51bf908
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/named.conf
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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.conf,v 1.9 2007/06/19 23:47:01 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ check-integrity no;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "ignore.example" {
+ type master;
+ file "ignore.example.db";
+ check-names ignore;
+};
+
+zone "warn.example" {
+ type master;
+ file "warn.example.db";
+ check-names warn;
+};
+
+zone "fail.example" {
+ type master;
+ file "fail.example.db";
+ check-names fail;
+};
+
+zone "ignore.update" {
+ type master;
+ file "ignore.update.db";
+ allow-update { any; };
+ check-names ignore;
+};
+
+zone "warn.update" {
+ type master;
+ file "warn.update.db";
+ allow-update { any; };
+ check-names warn;
+};
+
+zone "fail.update" {
+ type master;
+ file "fail.update.db";
+ allow-update { any; };
+ check-names fail;
+};
diff --git a/bin/tests/system/checknames/ns1/root.db b/bin/tests/system/checknames/ns1/root.db
new file mode 100644
index 0000000..0df0677
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/root.db
@@ -0,0 +1,35 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+$TTL 300
+@ SOA ns1. hostmaster.warn.example. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.
+ns1. A 10.53.0.1
+;
+ignore.example. NS ns1.ignore.example.
+ns1.ignore.example. A 10.53.0.1
+warn.example. NS ns1.warn.example.
+ns1.warn.example. A 10.53.0.1
+fail.example. NS ns1.fail.example.
+ns1.fail.example. A 10.53.0.1
+;
+ignore.update. NS ns1.ignore.update.
+ns1.ignore.update. A 10.53.0.1
+warn.update. NS ns1.warn.update.
+ns1.warn.update. A 10.53.0.1
+fail.update. NS ns1.fail.update.
+ns1.fail.update. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns1/warn.example.db.in b/bin/tests/system/checknames/ns1/warn.example.db.in
new file mode 100644
index 0000000..cad0524
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/warn.example.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) 2004, 2007 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: warn.example.db.in,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+$TTL 300
+@ SOA ns1.warn.example. hostmaster.warn.example. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.warn.example.
+ns1.warn.example. A 10.53.0.1
+xx_xx.warn.example. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns1/warn.update.db.in b/bin/tests/system/checknames/ns1/warn.update.db.in
new file mode 100644
index 0000000..9618d42
--- /dev/null
+++ b/bin/tests/system/checknames/ns1/warn.update.db.in
@@ -0,0 +1,21 @@
+; Copyright (C) 2004, 2007 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: warn.update.db.in,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+$TTL 300
+@ SOA ns1.warn.update. hostmaster.warn.update. (
+ 1 3600 1200 604800 3600 )
+ NS ns1.warn.update.
+ns1.warn.update. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns2/named.conf b/bin/tests/system/checknames/ns2/named.conf
new file mode 100644
index 0000000..fd22e7d
--- /dev/null
+++ b/bin/tests/system/checknames/ns2/named.conf
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.7 2007/06/18 23:47:27 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ check-names response warn;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
diff --git a/bin/tests/system/checknames/ns2/root.hints b/bin/tests/system/checknames/ns2/root.hints
new file mode 100644
index 0000000..712002b
--- /dev/null
+++ b/bin/tests/system/checknames/ns2/root.hints
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: root.hints,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+$TTL 300
+. NS ns1.
+ns1. A 10.53.0.1
diff --git a/bin/tests/system/checknames/ns3/named.conf b/bin/tests/system/checknames/ns3/named.conf
new file mode 100644
index 0000000..2702b5c
--- /dev/null
+++ b/bin/tests/system/checknames/ns3/named.conf
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.7 2007/06/18 23:47:27 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ check-names response fail;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hints";
+};
diff --git a/bin/tests/system/checknames/ns3/root.hints b/bin/tests/system/checknames/ns3/root.hints
new file mode 100644
index 0000000..712002b
--- /dev/null
+++ b/bin/tests/system/checknames/ns3/root.hints
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: root.hints,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+$TTL 300
+. NS ns1.
+ns1. A 10.53.0.1
diff --git a/bin/tests/system/checknames/setup.sh b/bin/tests/system/checknames/setup.sh
new file mode 100644
index 0000000..0027ed3
--- /dev/null
+++ b/bin/tests/system/checknames/setup.sh
@@ -0,0 +1,23 @@
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+cp ns1/ignore.example.db.in ns1/ignore.example.db
+cp ns1/warn.example.db.in ns1/warn.example.db
+cp ns1/fail.example.db.in ns1/fail.example.db
+
+cp ns1/ignore.update.db.in ns1/ignore.update.db
+cp ns1/warn.update.db.in ns1/warn.update.db
+cp ns1/fail.update.db.in ns1/fail.update.db
diff --git a/bin/tests/system/checknames/tests.sh b/bin/tests/system/checknames/tests.sh
new file mode 100644
index 0000000..dffacd2
--- /dev/null
+++ b/bin/tests/system/checknames/tests.sh
@@ -0,0 +1,134 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=1
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd -p 5300"
+
+# Entry should exist.
+echo "I: check for failure from on zone load for 'check-names fail;' ($n)"
+ret=0
+$DIG $DIGOPTS fail.example. @10.53.0.1 a > dig.out.ns1.test$n || ret=1
+grep SERVFAIL dig.out.ns1.test$n > /dev/null || ret=1
+grep 'xx_xx.fail.example: bad owner name (check-names)' ns1/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+# Entry should exist.
+echo "I: check for warnings from on zone load for 'check-names warn;' ($n)"
+ret=0
+grep 'xx_xx.warn.example: bad owner name (check-names)' ns1/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+# Entry should not exist.
+echo "I: check for warnings from on zone load for 'check-names ignore;' ($n)"
+ret=1
+grep 'yy_yy.ignore.example: bad owner name (check-names)' ns1/named.run || ret=0
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+# Entry should exist
+echo "I: check that 'check-names response warn;' works ($n)"
+ret=0
+$DIG $DIGOPTS yy_yy.ignore.example. @10.53.0.1 a > dig.out.ns1.test$n || ret=1
+$DIG $DIGOPTS yy_yy.ignore.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns1.test$n dig.out.ns2.test$n || ret=1
+grep "check-names warning yy_yy.ignore.example/A/IN" ns2/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+# Entry should exist
+echo "I: check that 'check-names response (owner) fails;' works ($n)"
+ret=0
+$DIG $DIGOPTS yy_yy.ignore.example. @10.53.0.1 a > dig.out.ns1.test$n || ret=1
+$DIG $DIGOPTS yy_yy.ignore.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+grep NOERROR dig.out.ns1.test$n > /dev/null || ret=1
+grep REFUSED dig.out.ns3.test$n > /dev/null || ret=1
+grep "check-names failure yy_yy.ignore.example/A/IN" ns3/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+# Entry should exist
+echo "I: check that 'check-names response (rdata) fails;' works ($n)"
+ret=0
+$DIG $DIGOPTS mx.ignore.example. @10.53.0.1 MX > dig.out.ns1.test$n || ret=1
+$DIG $DIGOPTS mx.ignore.example. @10.53.0.3 MX > dig.out.ns3.test$n || ret=1
+grep NOERROR dig.out.ns1.test$n > /dev/null || ret=1
+grep SERVFAIL dig.out.ns3.test$n > /dev/null || ret=1
+grep "check-names failure mx.ignore.example/MX/IN" ns3/named.run > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo "I: check that updates to 'check-names fail;' are rejected ($n)"
+ret=0
+not=1
+$NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || not=0
+server 10.53.0.1 5300
+update add xxx_xxx.fail.update. 600 A 10.10.10.1
+send
+END
+if [ $not != 0 ]; then ret=1; fi
+$DIG $DIGOPTS xxx_xxx.fail.update @10.53.0.1 A > dig.out.ns1.test$n || ret=1
+grep "xxx_xxx.fail.update/A: bad owner name (check-names)" ns1/named.run > /dev/null || ret=1
+grep NXDOMAIN dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo "I: check that updates to 'check-names warn;' succeed and are logged ($n)"
+ret=0
+$NSUPDATE -d <<END> nsupdate.out.test$n 2>&1|| ret=1
+server 10.53.0.1 5300
+update add xxx_xxx.warn.update. 600 A 10.10.10.1
+send
+END
+$DIG $DIGOPTS xxx_xxx.warn.update @10.53.0.1 A > dig.out.ns1.test$n || ret=1
+grep "xxx_xxx.warn.update/A: bad owner name (check-names)" ns1/named.run > /dev/null || ret=1
+grep NOERROR dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+echo "I: check that updates to 'check-names ignore;' succeed and are not logged ($n)"
+ret=0
+not=1
+$NSUPDATE -d <<END> nsupdate.out.test$n 2>&1 || ret=1
+server 10.53.0.1 5300
+update add xxx_xxx.ignore.update. 600 A 10.10.10.1
+send
+END
+grep "xxx_xxx.ignore.update/A.*(check-names)" ns1/named.run > /dev/null || not=0
+if [ $not != 0 ]; then ret=1; fi
+$DIG $DIGOPTS xxx_xxx.ignore.update @10.53.0.1 A > dig.out.ns1.test$n || ret=1
+grep NOERROR dig.out.ns1.test$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+n=`expr $n + 1`
+
+exit $status
diff --git a/bin/tests/system/cleanall.sh b/bin/tests/system/cleanall.sh
new file mode 100644
index 0000000..9b6aa6f
--- /dev/null
+++ b/bin/tests/system/cleanall.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: cleanall.sh,v 1.11 2007/06/19 23:47:00 tbox Exp $
+
+#
+# Clean up after system tests.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+
+find . -type f \( \
+ -name 'K*' -o -name '*~' -o -name '*.core' -o -name '*.log' \
+ -o -name '*.pid' -o -name '*.keyset' -o -name named.run \
+ -o -name lwresd.run -o -name ans.run \) -print | xargs rm -f
+
+status=0
+
+for d in $SUBDIRS
+do
+ test ! -f $d/clean.sh || ( cd $d && sh clean.sh )
+done
diff --git a/bin/tests/system/common/controls.conf b/bin/tests/system/common/controls.conf
new file mode 100644
index 0000000..b5d619e
--- /dev/null
+++ b/bin/tests/system/common/controls.conf
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2007 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: controls.conf,v 1.6 2007/06/19 23:47:01 tbox Exp $ */
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.2 port 9953 allow { any; } keys { rndc_key; };
+};
+
diff --git a/bin/tests/system/common/rndc.conf b/bin/tests/system/common/rndc.conf
new file mode 100644
index 0000000..3704ae7
--- /dev/null
+++ b/bin/tests/system/common/rndc.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004, 2007 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: rndc.conf,v 1.5 2007/06/19 23:47:01 tbox Exp $ */
+
+options {
+ default-key "rndc_key";
+};
+
+key rndc_key {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
diff --git a/bin/tests/system/common/root.hint b/bin/tests/system/common/root.hint
new file mode 100644
index 0000000..84a8c6b
--- /dev/null
+++ b/bin/tests/system/common/root.hint
@@ -0,0 +1,20 @@
+; Copyright (C) 2004, 2007 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: root.hint,v 1.5 2007/06/19 23:47:01 tbox Exp $
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.1
diff --git a/bin/tests/system/conf.sh.in b/bin/tests/system/conf.sh.in
new file mode 100644
index 0000000..23b31f1
--- /dev/null
+++ b/bin/tests/system/conf.sh.in
@@ -0,0 +1,54 @@
+#!/bin/sh
+#
+# 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
+# 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: conf.sh.in,v 1.39 2008/01/10 23:47:01 tbox Exp $
+
+#
+# Common configuration data for system tests, to be sourced into
+# other shell scripts.
+#
+
+# Find the top of the BIND9 tree.
+TOP=${SYSTEMTESTTOP:=.}/../../..
+
+# Make it absolute so that it continues to work after we cd.
+TOP=`cd $TOP && pwd`
+
+NAMED=$TOP/bin/named/named
+# We must use "named -l" instead of "lwresd" because argv[0] is lost
+# if the program is libtoolized.
+LWRESD="$TOP/bin/named/named -l"
+DIG=$TOP/bin/dig/dig
+RNDC=$TOP/bin/rndc/rndc
+NSUPDATE=$TOP/bin/nsupdate/nsupdate
+KEYGEN=$TOP/bin/dnssec/dnssec-keygen
+SIGNER=$TOP/bin/dnssec/dnssec-signzone
+CHECKZONE=$TOP/bin/check/named-checkzone
+CHECKCONF=$TOP/bin/check/named-checkconf
+
+# The "stress" test is not run by default since it creates enough
+# load on the machine to make it unusable to other users.
+# v6synth
+SUBDIRS="acl cacheclean checkconf checknames dnssec forward glue ixfr limits
+ lwresd masterfile masterformat notify nsupdate resolver rrsetorder
+ sortlist stub tkey unknown upforwd views xfer xferquota zonechecks"
+
+# PERL will be an empty string if no perl interpreter was found.
+PERL=@PERL@
+
+export NAMED LWRESD DIG NSUPDATE KEYGEN SIGNER KEYSIGNER KEYSETTOOL PERL \
+ SUBDIRS RNDC CHECKZONE
diff --git a/bin/tests/system/dialup/ns1/example.db b/bin/tests/system/dialup/ns1/example.db
new file mode 100644
index 0000000..262ed5e
--- /dev/null
+++ b/bin/tests/system/dialup/ns1/example.db
@@ -0,0 +1,25 @@
+; Copyright (C) 2004, 2007 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: example.db,v 1.6 2007/06/19 23:47:01 tbox Exp $
+
+@ 3600 SOA hostmaster.ns1 ns1 (
+ 1 3600 1200 3600000 1200 )
+ NS ns1.example.
+ NS ns2.example.
+ NS ns3.example.
+ns1 A 10.53.0.1
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/dialup/ns1/named.conf b/bin/tests/system/dialup/ns1/named.conf
new file mode 100644
index 0000000..7d75fc4
--- /dev/null
+++ b/bin/tests/system/dialup/ns1/named.conf
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.8 2007/06/19 23:47:01 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ heartbeat-interval 2;
+ recursion no;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example." {
+ type master;
+ notify explicit;
+ also-notify { 10.53.0.2; };
+ dialup yes;
+ file "example.db";
+};
diff --git a/bin/tests/system/dialup/ns1/root.db b/bin/tests/system/dialup/ns1/root.db
new file mode 100644
index 0000000..eadca60
--- /dev/null
+++ b/bin/tests/system/dialup/ns1/root.db
@@ -0,0 +1,26 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.6 2007/06/19 23:47:01 tbox Exp $
+
+@ 3600 SOA hostmaster.ns1.example ns1.example (
+ 1 3600 1200 3600000 1200 )
+ NS ns1.example
+example NS ns1.example
+ NS ns2.example
+ NS ns3.example
+ns1.example A 10.53.0.1
+ns2.example A 10.53.0.2
+ns3.example A 10.53.0.3
diff --git a/bin/tests/system/dialup/ns2/hint.db b/bin/tests/system/dialup/ns2/hint.db
new file mode 100644
index 0000000..2efbcfa
--- /dev/null
+++ b/bin/tests/system/dialup/ns2/hint.db
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: hint.db,v 1.6 2007/06/19 23:47:01 tbox Exp $
+
+. 1200 NS ns1.example
+ns1.example A 10.53.0.1
diff --git a/bin/tests/system/dialup/ns2/named.conf b/bin/tests/system/dialup/ns2/named.conf
new file mode 100644
index 0000000..c0b1549
--- /dev/null
+++ b/bin/tests/system/dialup/ns2/named.conf
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.8 2007/06/19 23:47:02 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ heartbeat-interval 2;
+ recursion no;
+};
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+zone "example." {
+ type slave;
+ dialup passive;
+ notify no;
+ file "example.bk";
+ masters { 10.53.0.1; };
+};
diff --git a/bin/tests/system/dialup/ns3/hint.db b/bin/tests/system/dialup/ns3/hint.db
new file mode 100644
index 0000000..19592f3
--- /dev/null
+++ b/bin/tests/system/dialup/ns3/hint.db
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: hint.db,v 1.6 2007/06/19 23:47:02 tbox Exp $
+
+. 1200 NS ns1.example
+ns1.example A 10.53.0.1
diff --git a/bin/tests/system/dialup/ns3/named.conf b/bin/tests/system/dialup/ns3/named.conf
new file mode 100644
index 0000000..387a716
--- /dev/null
+++ b/bin/tests/system/dialup/ns3/named.conf
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.8 2007/06/19 23:47:02 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ heartbeat-interval 2;
+ recursion no;
+};
+
+zone "." {
+ type hint;
+ file "hint.db";
+};
+
+zone "example." {
+ type slave;
+ dialup refresh;
+ notify no;
+ file "example.bk";
+ masters { 10.53.0.2; };
+};
diff --git a/bin/tests/system/dialup/setup.sh b/bin/tests/system/dialup/setup.sh
new file mode 100644
index 0000000..11ce031
--- /dev/null
+++ b/bin/tests/system/dialup/setup.sh
@@ -0,0 +1,19 @@
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.6 2007/06/19 23:47:01 tbox Exp $
+
+rm -f ns2/example.bk
+rm -f ns3/example.bk
diff --git a/bin/tests/system/dialup/tests.sh b/bin/tests/system/dialup/tests.sh
new file mode 100644
index 0000000..e48369f
--- /dev/null
+++ b/bin/tests/system/dialup/tests.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.6 2007/06/19 23:47:01 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+rm -f dig.out.*
+
+DIGOPTS="+norec +tcp +noadd +nosea +nostat +noquest +nocmd -p 5300"
+
+# Check the example. domain
+
+$DIG $DIGOPTS example. @10.53.0.1 soa > dig.out.ns1.test || ret=1
+echo "I:checking that first zone transfer worked"
+ret=0
+try=0
+while test $try -lt 120
+do
+ $DIG $DIGOPTS example. @10.53.0.2 soa > dig.out.ns2.test || ret=1
+ if grep SERVFAIL dig.out.ns2.test > /dev/null
+ then
+ try=`expr $try + 1`
+ sleep 1
+ else
+ $PERL ../digcomp.pl dig.out.ns1.test dig.out.ns2.test || ret=1
+ break;
+ fi
+done
+echo "I:try $try"
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that second zone transfer worked"
+ret=0
+try=0
+while test $try -lt 120
+do
+ $DIG $DIGOPTS example. @10.53.0.3 soa > dig.out.ns3.test || ret=1
+ if grep SERVFAIL dig.out.ns3.test > /dev/null
+ then
+ try=`expr $try + 1`
+ sleep 1
+ else
+ $PERL ../digcomp.pl dig.out.ns1.test dig.out.ns3.test || ret=1
+ break;
+ fi
+done
+echo "I:try $try"
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/digcomp.pl b/bin/tests/system/digcomp.pl
new file mode 100644
index 0000000..87e64cb
--- /dev/null
+++ b/bin/tests/system/digcomp.pl
@@ -0,0 +1,111 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2004, 2007 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: digcomp.pl,v 1.14 2007/06/19 23:47:00 tbox Exp $
+
+# Compare two files, each with the output from dig, for differences.
+# Ignore "unimportant" differences, like ordering of NS lines, TTL's,
+# etc...
+
+$file1 = $ARGV[0];
+$file2 = $ARGV[1];
+
+$count = 0;
+$firstname = "";
+$status = 0;
+$rcode1 = "none";
+$rcode2 = "none";
+
+open(FILE1, $file1) || die("open: $file1: $!\n");
+while (<FILE1>) {
+ chomp;
+ if (/^;.+status:\s+(\S+).+$/) {
+ $rcode1 = $1;
+ }
+ next if (/^;/);
+ if (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+(.+)$/) {
+ $name = $1;
+ $class = $2;
+ $type = $3;
+ $value = $4;
+ if ($type eq "SOA") {
+ $firstname = $name if ($firstname eq "");
+ if ($name eq $firstname) {
+ $name = "$name$count";
+ $count++;
+ }
+ }
+ if ($entry{"$name ; $class.$type ; $value"} ne "") {
+ $line = $entry{"$name ; $class.$type ; $value"};
+ print("Duplicate entry in $file1:\n> $_\n< $line\n");
+ } else {
+ $entry{"$name ; $class.$type ; $value"} = $_;
+ }
+ }
+}
+close(FILE1);
+
+$printed = 0;
+
+open(FILE2, $file2) || die("open: $file2: $!\n");
+while (<FILE2>) {
+ chomp;
+ if (/^;.+status:\s+(\S+).+$/) {
+ $rcode2 = $1;
+ }
+ next if (/^;/);
+ if (/^(\S+)\s+\S+\s+(\S+)\s+(\S+)\s+(.+)$/) {
+ $name = $1;
+ $class = $2;
+ $type = $3;
+ $value = $4;
+ if (($name eq $firstname) && ($type eq "SOA")) {
+ $count--;
+ $name = "$name$count";
+ }
+ if ($entry{"$name ; $class.$type ; $value"} ne "") {
+ $entry{"$name ; $class.$type ; $value"} = "";
+ } else {
+ print("Only in $file2 (missing from $file1):\n")
+ if ($printed == 0);
+ print("> $_\n");
+ $printed++;
+ $status = 1;
+ }
+ }
+}
+close(FILE2);
+
+$printed = 0;
+
+foreach $key (keys(%entry)) {
+ if ($entry{$key} ne "") {
+ print("Only in $file1 (missing from $file2):\n")
+ if ($printed == 0);
+ print("< $entry{$key}\n");
+ $status = 1;
+ $printed++;
+ }
+}
+
+if ($rcode1 ne $rcode2) {
+ print("< status: $rcode1\n");
+ print("> status: $rcode2\n");
+ $status = 1;
+}
+
+exit($status);
diff --git a/bin/tests/system/dlv/clean.sh b/bin/tests/system/dlv/clean.sh
new file mode 100644
index 0000000..872b14f
--- /dev/null
+++ b/bin/tests/system/dlv/clean.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.5 2007/09/26 03:22:43 marka Exp $
+
+rm -f random.data
+rm -f ns*/named.run
+rm -f ns3/K*
+rm -f ns3/*.db
+rm -f ns3/*.signed
+rm -f ns3/dlvset-*
+rm -f ns3/dsset-*
+rm -f ns3/keyset-*
+rm -f ns3/trusted.conf ns5/trusted.conf
+rm -f */named.memstats
diff --git a/bin/tests/system/dlv/ns1/named.conf b/bin/tests/system/dlv/ns1/named.conf
new file mode 100644
index 0000000..bfb64ed
--- /dev/null
+++ b/bin/tests/system/dlv/ns1/named.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.4 2007/06/19 23:47:02 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable no;
+};
+
+zone "." { type master; file "root.db"; };
+zone "rootservers.utld" { type master; file "rootservers.utld.db"; };
diff --git a/bin/tests/system/dlv/ns1/root.db b/bin/tests/system/dlv/ns1/root.db
new file mode 100644
index 0000000..ed7aee3
--- /dev/null
+++ b/bin/tests/system/dlv/ns1/root.db
@@ -0,0 +1,24 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 120
+@ SOA ns.rootservers.utld hostmaster.ns.rootservers.utld (
+ 1 3600 1200 604800 60 )
+@ NS ns.rootservers.utld
+ns A 10.53.0.1
+;
+utld NS ns.utld
+ns.utld A 10.53.0.2
diff --git a/bin/tests/system/dlv/ns1/rootservers.utld.db b/bin/tests/system/dlv/ns1/rootservers.utld.db
new file mode 100644
index 0000000..26abb42
--- /dev/null
+++ b/bin/tests/system/dlv/ns1/rootservers.utld.db
@@ -0,0 +1,20 @@
+; Copyright (C) 2004, 2007 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: rootservers.utld.db,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns2/hints b/bin/tests/system/dlv/ns2/hints
new file mode 100644
index 0000000..a2e549a
--- /dev/null
+++ b/bin/tests/system/dlv/ns2/hints
@@ -0,0 +1,18 @@
+; Copyright (C) 2004, 2007 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: hints,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns2/named.conf b/bin/tests/system/dlv/ns2/named.conf
new file mode 100644
index 0000000..195a46f
--- /dev/null
+++ b/bin/tests/system/dlv/ns2/named.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.4 2007/06/19 23:47:02 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable no;
+};
+
+zone "." { type hint; file "hints"; };
+zone "utld" { type master; file "utld.db"; };
diff --git a/bin/tests/system/dlv/ns2/utld.db b/bin/tests/system/dlv/ns2/utld.db
new file mode 100644
index 0000000..ac9c3d0
--- /dev/null
+++ b/bin/tests/system/dlv/ns2/utld.db
@@ -0,0 +1,56 @@
+; Copyright (C) 2004, 2007 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: utld.db,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.2
+;
+rootservers NS ns.rootservers
+ns.rootservers A 10.53.0.1
+;
+dlv NS ns.dlv
+ns.dlv A 10.53.0.3
+;
+child1 NS ns.child1
+ns.child1 A 10.53.0.3
+;
+child2 NS ns.child2
+ns.child2 A 10.53.0.4
+;
+child3 NS ns.child3
+ns.child3 A 10.53.0.3
+;
+child4 NS ns.child4
+ns.child4 A 10.53.0.3
+;
+child5 NS ns.child5
+ns.child5 A 10.53.0.3
+;
+child6 NS ns.child6
+ns.child6 A 10.53.0.4
+;
+child7 NS ns.child7
+ns.child7 A 10.53.0.3
+;
+child8 NS ns.child8
+ns.child8 A 10.53.0.3
+;
+child9 NS ns.child9
+ns.child9 A 10.53.0.3
+;
+child10 NS ns.child10
+ns.child10 A 10.53.0.3
diff --git a/bin/tests/system/dlv/ns3/child.db.in b/bin/tests/system/dlv/ns3/child.db.in
new file mode 100644
index 0000000..9411c68
--- /dev/null
+++ b/bin/tests/system/dlv/ns3/child.db.in
@@ -0,0 +1,22 @@
+; Copyright (C) 2004, 2007 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: child.db.in,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.3
+foo TXT foo
+bar TXT bar
diff --git a/bin/tests/system/dlv/ns3/dlv.db.in b/bin/tests/system/dlv/ns3/dlv.db.in
new file mode 100644
index 0000000..3f0ef6b
--- /dev/null
+++ b/bin/tests/system/dlv/ns3/dlv.db.in
@@ -0,0 +1,20 @@
+; Copyright (C) 2004, 2007 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: dlv.db.in,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.3
diff --git a/bin/tests/system/dlv/ns3/hints b/bin/tests/system/dlv/ns3/hints
new file mode 100644
index 0000000..a2e549a
--- /dev/null
+++ b/bin/tests/system/dlv/ns3/hints
@@ -0,0 +1,18 @@
+; Copyright (C) 2004, 2007 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: hints,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns3/named.conf b/bin/tests/system/dlv/ns3/named.conf
new file mode 100644
index 0000000..a03fb05
--- /dev/null
+++ b/bin/tests/system/dlv/ns3/named.conf
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.4 2007/06/19 23:47:02 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+};
+
+zone "." { type hint; file "hints"; };
+zone "dlv.utld" { type master; file "dlv.signed"; };
+zone "child1.utld" { type master; file "child1.signed"; }; // dlv
+zone "child3.utld" { type master; file "child3.signed"; }; // dlv
+zone "child4.utld" { type master; file "child4.signed"; }; // dlv
+zone "child5.utld" { type master; file "child5.signed"; }; // dlv
+zone "child7.utld" { type master; file "child7.signed"; }; // no dlv
+zone "child8.utld" { type master; file "child8.signed"; }; // no dlv
+zone "child9.utld" { type master; file "child9.signed"; }; // dlv
+zone "child10.utld" { type master; file "child.db.in"; }; // dlv unsigned
diff --git a/bin/tests/system/dlv/ns3/sign.sh b/bin/tests/system/dlv/ns3/sign.sh
new file mode 100755
index 0000000..e3382cf
--- /dev/null
+++ b/bin/tests/system/dlv/ns3/sign.sh
@@ -0,0 +1,174 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: sign.sh,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+RANDFILE=../random.data
+dlvsets=
+
+zone=child1.utld.
+infile=child.db.in
+zonefile=child1.utld.db
+outfile=child1.signed
+dlvzone=dlv.utld.
+dlvsets="$dlvsets dlvset-$zone"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null
+echo "I: signed $zone"
+
+
+zone=child3.utld.
+infile=child.db.in
+zonefile=child3.utld.db
+outfile=child3.signed
+dlvzone=dlv.utld.
+dlvsets="$dlvsets dlvset-$zone"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null
+echo "I: signed $zone"
+
+
+zone=child4.utld.
+infile=child.db.in
+zonefile=child4.utld.db
+outfile=child4.signed
+dlvzone=dlv.utld.
+dlvsets="$dlvsets dlvset-$zone"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null
+echo "I: signed $zone"
+
+
+zone=child5.utld.
+infile=child.db.in
+zonefile=child5.utld.db
+outfile=child5.signed
+dlvzone=dlv.utld.
+dlvsets="$dlvsets dlvset-$zone"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null
+echo "I: signed $zone"
+
+
+zone=child7.utld.
+infile=child.db.in
+zonefile=child7.utld.db
+outfile=child7.signed
+dlvzone=dlv.utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null
+echo "I: signed $zone"
+
+
+zone=child8.utld.
+infile=child.db.in
+zonefile=child8.utld.db
+outfile=child8.signed
+dlvzone=dlv.utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null
+echo "I: signed $zone"
+
+
+zone=child9.utld.
+infile=child.db.in
+zonefile=child9.utld.db
+outfile=child9.signed
+dlvzone=dlv.utld.
+dlvsets="$dlvsets dlvset-$zone"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null
+echo "I: signed $zone"
+
+zone=child10.utld.
+infile=child.db.in
+zonefile=child10.utld.db
+outfile=child10.signed
+dlvzone=dlv.utld.
+dlvsets="$dlvsets dlvset-$zone"
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -l $dlvzone -o $zone -f $outfile $zonefile > /dev/null
+echo "I: signed $zone"
+
+
+zone=dlv.utld.
+infile=dlv.db.in
+zonefile=dlv.utld.db
+outfile=dlv.signed
+dlvzone=dlv.utld.
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -f KSK -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $dlvsets $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null
+echo "I: signed $zone"
+
+
+cat $keyname2.key | $PERL -n -e '
+local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
+local $key = join("", @rest);
+print <<EOF
+trusted-keys {
+ "$dn" $flags $proto $alg "$key";
+};
+EOF
+' > trusted.conf
+cp trusted.conf ../ns5
diff --git a/bin/tests/system/dlv/ns4/child.db b/bin/tests/system/dlv/ns4/child.db
new file mode 100644
index 0000000..b4306f3
--- /dev/null
+++ b/bin/tests/system/dlv/ns4/child.db
@@ -0,0 +1,41 @@
+; Copyright (C) 2004, 2007 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: child.db,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 120
+@ SOA ns hostmaster.ns 1 3600 1200 604800 60
+@ NS ns
+ns A 10.53.0.3
+;
+rootservers NS ns.rootservers
+ns.rootservers A 10.53.0.1
+;
+child1 NS ns.child1
+ns.child1 A 10.53.0.3
+;
+child2 NS ns.child2
+ns.child2 A 10.53.0.4
+;
+child3 NS ns.child3
+ns.child3 A 10.53.0.3
+;
+child4 NS ns.child4
+ns.child4 A 10.53.0.3
+;
+child5 NS ns.child5
+ns.child5 A 10.53.0.3
+;
+child6 NS ns.child5
+ns.child6 A 10.53.0.4
diff --git a/bin/tests/system/dlv/ns4/hints b/bin/tests/system/dlv/ns4/hints
new file mode 100644
index 0000000..a2e549a
--- /dev/null
+++ b/bin/tests/system/dlv/ns4/hints
@@ -0,0 +1,18 @@
+; Copyright (C) 2004, 2007 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: hints,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns4/named.conf b/bin/tests/system/dlv/ns4/named.conf
new file mode 100644
index 0000000..4fa32c2
--- /dev/null
+++ b/bin/tests/system/dlv/ns4/named.conf
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.4 2007/06/19 23:47:02 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable no;
+};
+
+zone "." { type hint; file "hints"; };
+zone "child2.utld" { type master; file "child.db"; };
+zone "child6.utld" { type master; file "child.db"; };
diff --git a/bin/tests/system/dlv/ns5/hints b/bin/tests/system/dlv/ns5/hints
new file mode 100644
index 0000000..a2e549a
--- /dev/null
+++ b/bin/tests/system/dlv/ns5/hints
@@ -0,0 +1,18 @@
+; Copyright (C) 2004, 2007 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: hints,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+. 0 NS ns.rootservers.utld.
+ns.rootservers.utld. 0 A 10.53.0.1
diff --git a/bin/tests/system/dlv/ns5/named.conf b/bin/tests/system/dlv/ns5/named.conf
new file mode 100644
index 0000000..b35c4a7
--- /dev/null
+++ b/bin/tests/system/dlv/ns5/named.conf
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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.conf,v 1.8 2007/06/18 23:47:28 tbox Exp $ */
+
+/*
+ * Choose a keyname that is unlikely to clash with any real key names.
+ * This allows it to be added to the system's rndc.conf with minimal
+ * likelyhood of collision.
+ *
+ * e.g.
+ * key "cc64b3d1db63fc88d7cb5d2f9f57d258" {
+ * algorithm hmac-md5;
+ * secret "34f88008d07deabbe65bd01f1d233d47";
+ * };
+ *
+ * server "10.53.0.5" {
+ * key cc64b3d1db63fc88d7cb5d2f9f57d258;
+ * port 5353;
+ * };
+ *
+ * rndc -s 10.53.0.5 <command>
+ */
+
+key "cc64b3d1db63fc88d7cb5d2f9f57d258" {
+ algorithm hmac-md5;
+ secret "34f88008d07deabbe65bd01f1d233d47";
+};
+
+controls {
+ inet 10.53.0.5 port 5353 allow { any; }
+ keys { cc64b3d1db63fc88d7cb5d2f9f57d258; };
+};
+
+include "trusted.conf";
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ dnssec-lookaside "." trust-anchor "dlv.utld";
+};
+
+zone "." { type hint; file "hints"; };
diff --git a/bin/tests/system/dlv/ns5/rndc.conf b/bin/tests/system/dlv/ns5/rndc.conf
new file mode 100644
index 0000000..958ee98
--- /dev/null
+++ b/bin/tests/system/dlv/ns5/rndc.conf
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004, 2007 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: rndc.conf,v 1.5 2007/06/19 23:47:02 tbox Exp $ */
+
+key "cc64b3d1db63fc88d7cb5d2f9f57d258" {
+ algorithm hmac-md5;
+ secret "34f88008d07deabbe65bd01f1d233d47";
+};
+
+options {
+ default-server 10.53.0.5;
+ default-port 5353;
+};
diff --git a/bin/tests/system/dlv/setup.sh b/bin/tests/system/dlv/setup.sh
new file mode 100644
index 0000000..5f2e5b8
--- /dev/null
+++ b/bin/tests/system/dlv/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+../../genrandom 400 random.data
+
+(cd ns3 && sh -e sign.sh)
diff --git a/bin/tests/system/dlv/tests.sh b/bin/tests/system/dlv/tests.sh
new file mode 100644
index 0000000..8b595a7
--- /dev/null
+++ b/bin/tests/system/dlv/tests.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+exit 0
diff --git a/bin/tests/system/dnssec/README b/bin/tests/system/dnssec/README
new file mode 100644
index 0000000..63ea49a
--- /dev/null
+++ b/bin/tests/system/dnssec/README
@@ -0,0 +1,17 @@
+Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2000-2002 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+$Id: README,v 1.8 2004/03/05 05:00:08 marka Exp $
+
+The test setup for the DNSSEC tests has a secure root.
+
+ns1 is the root server.
+
+ns2 and ns3 are authoritative servers for the various test domains.
+
+ns4 is a caching-only server, configured with the correct trusted key
+for the root.
+
+ns5 is a caching-only server, configured with the an incorrect trusted
+key for the root. It is used for testing failure cases.
diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh
new file mode 100644
index 0000000..3f207d5
--- /dev/null
+++ b/bin/tests/system/dnssec/clean.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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: clean.sh,v 1.23 2008/09/25 04:02:38 tbox Exp $
+
+rm -f */K* */keyset-* */dsset-* */dlvset-* */signedkey-* */*.signed */trusted.conf */tmp* */*.jnl */*.bk
+rm -f ns1/root.db ns2/example.db ns3/secure.example.db
+rm -f ns3/unsecure.example.db ns3/bogus.example.db ns3/keyless.example.db
+rm -f ns3/dynamic.example.db ns3/dynamic.example.db.signed.jnl
+rm -f ns2/private.secure.example.db
+rm -f */example.bk
+rm -f dig.out.*
+rm -f random.data
+rm -f ns2/dlv.db
+rm -f ns3/multiple.example.db ns3/nsec3-unknown.example.db ns3/nsec3.example.db
+rm -f ns3/optout-unknown.example.db ns3/optout.example.db
+rm -f ns7/multiple.example.bk ns7/nsec3.example.bk ns7/optout.example.bk
+rm -f */named.memstats
+rm -f ns3/nsec3.nsec3.example.db
+rm -f ns3/nsec3.optout.example.db
+rm -f ns3/optout.nsec3.example.db
+rm -f ns3/optout.optout.example.db
+rm -f ns3/secure.nsec3.example.db
+rm -f ns3/secure.optout.example.db
diff --git a/bin/tests/system/dnssec/dnssec_update_test.pl b/bin/tests/system/dnssec/dnssec_update_test.pl
new file mode 100644
index 0000000..3a87242
--- /dev/null
+++ b/bin/tests/system/dnssec/dnssec_update_test.pl
@@ -0,0 +1,105 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2002 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.
+
+#
+# DNSSEC Dynamic update test suite.
+#
+# Usage:
+#
+# perl update_test.pl [-s server] [-p port] zone
+#
+# The server defaults to 127.0.0.1.
+# The port defaults to 53.
+#
+# Installation notes:
+#
+# This program uses the Net::DNS::Resolver module.
+# You can install it by saying
+#
+# perl -MCPAN -e "install Net::DNS"
+#
+# $Id: dnssec_update_test.pl,v 1.5 2007/06/19 23:47:02 tbox Exp $
+#
+
+use Getopt::Std;
+use Net::DNS;
+use Net::DNS::Update;
+use Net::DNS::Resolver;
+
+$opt_s = "127.0.0.1";
+$opt_p = 53;
+
+getopt('s:p:');
+
+$res = new Net::DNS::Resolver;
+$res->nameservers($opt_s);
+$res->port($opt_p);
+$res->defnames(0); # Do not append default domain.
+
+@ARGV == 1 or die
+ "usage: perl update_test.pl [-s server] [-p port] zone\n";
+
+$zone = shift @ARGV;
+
+my $failures = 0;
+
+sub assert {
+ my ($cond, $explanation) = @_;
+ if (!$cond) {
+ print "I:Test Failed: $explanation ***\n";
+ $failures++
+ }
+}
+
+sub test {
+ my ($expected, @records) = @_;
+
+ my $update = new Net::DNS::Update("$zone");
+
+ foreach $rec (@records) {
+ $update->push(@$rec);
+ }
+
+ $reply = $res->send($update);
+
+ # Did it work?
+ if (defined $reply) {
+ my $rcode = $reply->header->rcode;
+ assert($rcode eq $expected, "expected $expected, got $rcode");
+ } else {
+ print "I:Update failed: ", $res->errorstring, "\n";
+ }
+}
+
+sub section {
+ my ($msg) = @_;
+ print "I:$msg\n";
+}
+
+section("Add a name");
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]);
+
+section("Delete the name");
+test("NOERROR", ["update", rr_del("a.$zone")]);
+
+if ($failures) {
+ print "I:$failures tests failed.\n";
+} else {
+ print "I:All tests successful.\n";
+}
+
+exit $failures;
diff --git a/bin/tests/system/dnssec/ns1/named.conf b/bin/tests/system/dnssec/ns1/named.conf
new file mode 100644
index 0000000..e6b6b02
--- /dev/null
+++ b/bin/tests/system/dnssec/ns1/named.conf
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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.conf,v 1.24 2007/06/19 23:47:02 tbox Exp $ */
+
+// NS1
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns1/root.db.in b/bin/tests/system/dnssec/ns1/root.db.in
new file mode 100644
index 0000000..24c5913
--- /dev/null
+++ b/bin/tests/system/dnssec/ns1/root.db.in
@@ -0,0 +1,32 @@
+; Copyright (C) 2004, 2007 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: root.db.in,v 1.10 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+dlv. NS ns2.dlv.
+ns2.dlv. A 10.53.0.2
diff --git a/bin/tests/system/dnssec/ns1/sign.sh b/bin/tests/system/dnssec/ns1/sign.sh
new file mode 100644
index 0000000..9bc0ddd
--- /dev/null
+++ b/bin/tests/system/dnssec/ns1/sign.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2006-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
+# 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: sign.sh,v 1.25 2008/09/25 04:02:38 tbox Exp $
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+RANDFILE=../random.data
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+(cd ../ns2 && sh sign.sh )
+
+cp ../ns2/keyset-example. .
+cp ../ns2/keyset-dlv. .
+
+keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key > $zonefile
+
+echo $SIGNER -g -r $RANDFILE -o $zone $zonefile
+$SIGNER -g -r $RANDFILE -o $zone $zonefile > /dev/null
+
+# Configure the resolving server with a trusted key.
+
+cat $keyname.key | $PERL -n -e '
+local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
+local $key = join("", @rest);
+print <<EOF
+trusted-keys {
+ "$dn" $flags $proto $alg "$key";
+};
+EOF
+' > trusted.conf
+cp trusted.conf ../ns2/trusted.conf
+cp trusted.conf ../ns3/trusted.conf
+cp trusted.conf ../ns4/trusted.conf
+cp trusted.conf ../ns6/trusted.conf
+cp trusted.conf ../ns7/trusted.conf
diff --git a/bin/tests/system/dnssec/ns2/child.nsec3.example.db b/bin/tests/system/dnssec/ns2/child.nsec3.example.db
new file mode 100644
index 0000000..c432b06
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/child.nsec3.example.db
@@ -0,0 +1,25 @@
+; Copyright (C) 2006, 2008 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: child.nsec3.example.db,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2006081400 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ IN NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/child.optout.example.db b/bin/tests/system/dnssec/ns2/child.optout.example.db
new file mode 100644
index 0000000..feb73a4
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/child.optout.example.db
@@ -0,0 +1,25 @@
+; Copyright (C) 2006, 2008 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: child.optout.example.db,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2006081400 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ IN NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns2/dlv.db.in b/bin/tests/system/dnssec/ns2/dlv.db.in
new file mode 100644
index 0000000..fa09f21
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/dlv.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) 2004, 2007 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: dlv.db.in,v 1.5 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ns2 A 10.53.0.2
diff --git a/bin/tests/system/dnssec/ns2/dst.example.db.in b/bin/tests/system/dnssec/ns2/dst.example.db.in
new file mode 100644
index 0000000..5819636
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/dst.example.db.in
@@ -0,0 +1,26 @@
+; Copyright (C) 2004, 2007 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: dst.example.db.in,v 1.4 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2.example.
+a A 10.0.0.1
diff --git a/bin/tests/system/dnssec/ns2/example.db.in b/bin/tests/system/dnssec/ns2/example.db.in
new file mode 100644
index 0000000..c2b5e98
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/example.db.in
@@ -0,0 +1,97 @@
+; Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2000-2002 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: example.db.in,v 1.19 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+
+; Used for testing ANY queries
+foo TXT "testing"
+foo A 10.0.1.0
+
+; Used for testing CNAME queries
+cname1 CNAME cname1-target
+cname1-target TXT "testing cname"
+
+cname2 CNAME cname2-target
+cname2-target TXT "testing cname"
+
+; Used for testing DNAME queries
+dname1 DNAME dname1-target
+foo.dname1-target TXT "testing dname"
+
+dname2 DNAME dname2-target
+foo.dname2-target TXT "testing dname"
+
+; A secure subdomain
+secure NS ns.secure
+ns.secure A 10.53.0.3
+
+; An insecure subdomain
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+
+; A secure subdomain we're going to inject bogus data into
+bogus NS ns.bogus
+ns.bogus A 10.53.0.3
+
+; A dynamic secure subdomain
+dynamic NS dynamic
+dynamic A 10.53.0.3
+
+; A insecure subdomain
+mustbesecure NS ns.mustbesecure
+ns.mustbesecure A 10.53.0.3
+
+; A rfc2535 signed zone w/ CNAME
+rfc2535 NS ns.rfc2535
+ns.rfc2535 A 10.53.0.3
+
+z A 10.0.0.26
+
+keyless NS ns.keyless
+ns.keyless A 10.53.0.3
+
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+
+optout NS ns.optout
+ns.optout A 10.53.0.3
+
+nsec3-unknown NS ns.nsec3-unknown
+ns.nsec3-unknown A 10.53.0.3
+
+optout-unknown NS ns.optout-unknown
+ns.optout-unknown A 10.53.0.3
+
+multiple NS ns.multiple
+ns.multiple A 10.53.0.3
+
+*.wild A 10.0.0.27
diff --git a/bin/tests/system/dnssec/ns2/insecure.secure.example.db b/bin/tests/system/dnssec/ns2/insecure.secure.example.db
new file mode 100644
index 0000000..f16a2cf
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/insecure.secure.example.db
@@ -0,0 +1,32 @@
+; Copyright (C) 2004, 2007 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: insecure.secure.example.db,v 1.9 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns2/named.conf b/bin/tests/system/dnssec/ns2/named.conf
new file mode 100644
index 0000000..3160413
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/named.conf
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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.conf,v 1.30 2008/09/25 04:02:38 tbox Exp $ */
+
+// NS2
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "dlv" {
+ type master;
+ file "dlv.db.signed";
+};
+
+zone "example" {
+ type master;
+ file "example.db.signed";
+ allow-update { any; };
+};
+
+zone "private.secure.example" {
+ type master;
+ file "private.secure.example.db.signed";
+ allow-update { any; };
+};
+
+zone "insecure.secure.example" {
+ type master;
+ file "insecure.secure.example.db";
+ allow-update { any; };
+};
+
+zone "rfc2335.example" {
+ type master;
+ file "rfc2335.example.db";
+};
+
+zone "child.nsec3.example" {
+ type master;
+ file "child.nsec3.example.db";
+ allow-update { none; };
+};
+
+zone "child.optout.example" {
+ type master;
+ file "child.optout.example.db";
+ allow-update { none; };
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns2/private.secure.example.db.in b/bin/tests/system/dnssec/ns2/private.secure.example.db.in
new file mode 100644
index 0000000..2bf2787
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/private.secure.example.db.in
@@ -0,0 +1,34 @@
+; Copyright (C) 2004, 2007 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: private.secure.example.db.in,v 1.10 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.2
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+private2secure-nxdomain CNAME r.example.
+*.wild CNAME s.example.
diff --git a/bin/tests/system/dnssec/ns2/rfc2335.example.db b/bin/tests/system/dnssec/ns2/rfc2335.example.db
new file mode 100644
index 0000000..b8b477e
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/rfc2335.example.db
@@ -0,0 +1,103 @@
+; File written on Fri Apr 30 12:19:15 2004
+; dnssec_signzone version 9.2.4rc3
+rfc2335.example. 300 IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ 300 SIG SOA 1 2 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ nGPJKIzF7X/hMJbZURRz59UeEi/6HRxCn9Er
+ GqSnpw0Ea9Yx5Axu6sLKnF7jXlkZ6NHMCIpJ
+ +Lv+FDHXTs/dQg== )
+ 300 NS ns.rfc2335.example.
+ 300 SIG NS 1 2 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ Q234AL9dJYMvxdWG33lpww6AJ3GplKp+ace7
+ MUaj0oqDdkx4DtJF2XaP2xcqq7kTOObdQ8ES
+ vVxNThqOx7LFzg== )
+ 300 KEY 256 3 1 (
+ AQPZhzXIabI8y5ihWUw7F0WxN2MabnYWkOcV
+ Fn11NgaGSdjBSYPRMMwMCasD5N2KYPRUP83W
+ y8mj+ofcoW1FurcZ
+ ) ; key id = 47799
+ 300 NXT a.rfc2335.example. NS SOA SIG KEY NXT
+ 300 SIG NXT 1 2 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ Y587mqNy6pBEfbsU6+weM2XRSqLwLwRT9Sl7
+ oNuOK9kV3TR4R2M54m2S0MgJCXbRAwU+fF8Q
+ UbZkSTVe2N8Nyg== )
+a.rfc2335.example. 300 IN A 10.0.0.1
+ 300 SIG A 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ FnfWrcw5ire8ut25504zti5l///BdDMUAkJZ
+ UCLFiTW4lBGMcq1pqz64zltDZXCgJ3xUeQ2i
+ nRt19/ZxO6Z1KA== )
+ 300 NXT b.rfc2335.example. A SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ R6SpC3ndMVg4u/eZaaUsXSuMHV/hZXeaM/Op
+ bJLAe3KxMiOHfb6XgLy7wflAiC1xt6A9bWpy
+ kTc5T5gfic33kA== )
+b.rfc2335.example. 300 IN A 10.0.0.2
+ 300 SIG A 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ zjRsYXMGyhDI6ipDtu8YXC9XPN+3hGamzzxL
+ 8uPE/LPo+x19MNdbzEgWzlajAf1/mkSGr2jN
+ BDMVBA5NMKpwAA== )
+ 300 NXT d.rfc2335.example. A SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ aV87iZCYsC5Tqop827Zzb18TNqopGt0QynkR
+ gIF/lIHqZasNFRfaS1/nTnXdDKD8JS5IqxKb
+ oTJr5zswDAtCEw== )
+d.rfc2335.example. 300 IN A 10.0.0.4
+ 300 SIG A 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ NsKyvhUYZxTbOTBX4YwxTxevI5iGBpULKwmt
+ +D4l00ME4XRygOVmiqVDTT9dF1EgjDxOdfMT
+ hSjtCh5M1b2f6g== )
+ 300 NXT ns.rfc2335.example. A SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ OGqlvSDZIZdHYigh4UAFzXfPze7vcQfgj7sN
+ +cAeoh4BL1gpa00DqANCxowNCYluDk3ZCDwt
+ UHZEJa8ZjNvv4g== )
+ns.rfc2335.example. 300 IN A 10.53.0.3
+ 300 SIG A 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ T6ZGeUWflLTku8jO23x/TeAPeUl8t0I18FCh
+ qHUZaHomLQasQ2jlZQn6cLpFd2uFJkBNxZ0G
+ I39aG7G1bObXdA== )
+ 300 NXT x.rfc2335.example. A SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ l46mrf3/Ii5iRm3AiDjYeMg4ZXBgitHxXA2y
+ e/NhKpkxRRpCs7UQ94wT/RiSCjjK49E5FBe6
+ 5bRxtWq0GI7zlg== )
+x.rfc2335.example. 300 IN CNAME a.rfc2335.example.
+ 300 SIG CNAME 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ L3IOluq+kboBd2gR2Mu54uJKCUzfmyHRiWKl
+ kfx+vuFr0I8mEHQRmJtouxNDrBzmzGp5vybK
+ SdabLWw0n6uQEA== )
+ 300 NXT z.rfc2335.example. CNAME SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ CBKoJSkZzdpwiON7JS4yPFY5VVeBjfT19x/O
+ vx+5UK1JZUNKhTXWWgW1er+JlLzNf4Ot40+l
+ z9HUTyaeS0eWyw== )
+z.rfc2335.example. 300 IN A 10.0.0.26
+ 300 SIG A 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ ccqjVHnehvVwlNNd4+7n/GzGlRjj+ul0gCT3
+ X3950LTccxHsOFyjNNm8v/Ho/aurSYdqXEjY
+ jwmjC6elwkzB7A== )
+ 300 NXT rfc2335.example. A SIG NXT
+ 300 SIG NXT 1 3 300 20040530021915 (
+ 20040430021915 47799 rfc2335.example.
+ W42WoFyd9erysv8HjKo+CpHIH1x6+pAKwCDO
+ /hHnkEpQI3brewxl7cWOPYeA92Ns80Ody/ui
+ m2E28A5gnmWqPw== )
diff --git a/bin/tests/system/dnssec/ns2/sign.sh b/bin/tests/system/dnssec/ns2/sign.sh
new file mode 100644
index 0000000..4389678
--- /dev/null
+++ b/bin/tests/system/dnssec/ns2/sign.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2006-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
+# 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: sign.sh,v 1.30 2008/09/25 04:02:38 tbox Exp $
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+RANDFILE=../random.data
+
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+# Have the child generate a zone key and pass it to us.
+
+( cd ../ns3 && sh sign.sh )
+
+for subdomain in secure bogus dynamic keyless nsec3 optout nsec3-unknown optout-unknown multiple
+do
+ cp ../ns3/keyset-$subdomain.example. .
+done
+
+keyname1=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+keyname2=`$KEYGEN -r $RANDFILE -a DSA -b 768 -n zone $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -g -r $RANDFILE -o $zone -k $keyname1 $zonefile $keyname2 > /dev/null
+
+# Sign the privately secure file
+
+privzone=private.secure.example.
+privinfile=private.secure.example.db.in
+privzonefile=private.secure.example.db
+
+privkeyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $privzone`
+
+cat $privinfile $privkeyname.key >$privzonefile
+
+$SIGNER -g -r $RANDFILE -o $privzone -l dlv $privzonefile > /dev/null
+
+# Sign the DLV secure zone.
+
+
+dlvzone=dlv.
+dlvinfile=dlv.db.in
+dlvzonefile=dlv.db
+
+dlvkeyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $dlvzone`
+
+cat $dlvinfile $dlvkeyname.key dlvset-$privzone > $dlvzonefile
+
+$SIGNER -g -r $RANDFILE -o $dlvzone $dlvzonefile > /dev/null
diff --git a/bin/tests/system/dnssec/ns3/bogus.example.db.in b/bin/tests/system/dnssec/ns3/bogus.example.db.in
new file mode 100644
index 0000000..e83d07b
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/bogus.example.db.in
@@ -0,0 +1,32 @@
+; Copyright (C) 2004, 2007 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: bogus.example.db.in,v 1.9 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/dynamic.example.db.in b/bin/tests/system/dnssec/ns3/dynamic.example.db.in
new file mode 100644
index 0000000..0b5b0b0
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/dynamic.example.db.in
@@ -0,0 +1,31 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2002 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: dynamic.example.db.in,v 1.5 2007/06/19 23:47:02 tbox Exp $
+
+; This has the NS and glue at the apex because testing RT #2399
+; requires we have only one name in the zone at a certain point
+; during the test.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS @
+@ A 10.53.0.3
diff --git a/bin/tests/system/dnssec/ns3/insecure.example.db b/bin/tests/system/dnssec/ns3/insecure.example.db
new file mode 100644
index 0000000..036adc5
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.example.db
@@ -0,0 +1,32 @@
+; Copyright (C) 2004, 2007 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: insecure.example.db,v 1.9 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db b/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db
new file mode 100644
index 0000000..4518c2d
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.nsec3.example.db
@@ -0,0 +1,31 @@
+; Copyright (C) 2008 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: insecure.nsec3.example.db,v 1.2 2008/09/24 02:46:21 marka Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/insecure.optout.example.db b/bin/tests/system/dnssec/ns3/insecure.optout.example.db
new file mode 100644
index 0000000..0a3a45d
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/insecure.optout.example.db
@@ -0,0 +1,31 @@
+; Copyright (C) 2008 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: insecure.optout.example.db,v 1.2 2008/09/24 02:46:21 marka Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
diff --git a/bin/tests/system/dnssec/ns3/keyless.example.db.in b/bin/tests/system/dnssec/ns3/keyless.example.db.in
new file mode 100644
index 0000000..e2d1ffa
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/keyless.example.db.in
@@ -0,0 +1,29 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2001, 2002 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: keyless.example.db.in,v 1.5 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a.b A 10.0.0.1
diff --git a/bin/tests/system/dnssec/ns3/multiple.example.db.in b/bin/tests/system/dnssec/ns3/multiple.example.db.in
new file mode 100644
index 0000000..c805a3e
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/multiple.example.db.in
@@ -0,0 +1,34 @@
+; Copyright (C) 2006, 2008 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: multiple.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.e A 10.0.0.6
+child NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns3/named.conf b/bin/tests/system/dnssec/ns3/named.conf
new file mode 100644
index 0000000..38f4ad0
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/named.conf
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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.conf,v 1.33 2008/09/25 04:02:38 tbox Exp $ */
+
+// NS3
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "example.bk";
+};
+
+zone "secure.example" {
+ type master;
+ file "secure.example.db.signed";
+ allow-update { any; };
+};
+
+zone "bogus.example" {
+ type master;
+ file "bogus.example.db.signed";
+ allow-update { any; };
+};
+
+zone "dynamic.example" {
+ type master;
+ file "dynamic.example.db.signed";
+ allow-update { any; };
+};
+
+zone "insecure.example" {
+ type master;
+ file "insecure.example.db";
+ allow-update { any; };
+};
+
+zone "insecure.nsec3.example" {
+ type master;
+ file "insecure.nsec3.example.db";
+ allow-update { any; };
+};
+
+zone "insecure.optout.example" {
+ type master;
+ file "insecure.optout.example.db";
+ allow-update { any; };
+};
+
+zone "keyless.example" {
+ type master;
+ file "keyless.example.db.signed";
+};
+
+zone "nsec3.example" {
+ type master;
+ file "nsec3.example.db.signed";
+};
+
+zone "optout.nsec3.example" {
+ type master;
+ file "optout.nsec3.example.db.signed";
+};
+
+zone "nsec3.nsec3.example" {
+ type master;
+ file "nsec3.nsec3.example.db.signed";
+};
+
+zone "secure.nsec3.example" {
+ type master;
+ file "secure.nsec3.example.db.signed";
+};
+
+zone "optout.example" {
+ type master;
+ file "optout.example.db.signed";
+};
+
+zone "secure.optout.example" {
+ type master;
+ file "secure.optout.example.db.signed";
+};
+
+zone "nsec3.optout.example" {
+ type master;
+ file "nsec3.optout.example.db.signed";
+};
+
+zone "optout.optout.example" {
+ type master;
+ file "optout.optout.example.db.signed";
+};
+
+zone "nsec3-unknown.example" {
+ type master;
+ nsec3-test-zone yes;
+ file "nsec3-unknown.example.db.signed";
+};
+
+zone "optout-unknown.example" {
+ type master;
+ nsec3-test-zone yes;
+ file "optout-unknown.example.db.signed";
+};
+
+zone "multiple.example" {
+ type master;
+ file "multiple.example.db.signed";
+ allow-update { any; };
+};
+
+zone "mustbesecure.example" {
+ type master;
+ file "mustbesecure.example.db";
+};
+
+zone "rfc2335.example" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "rfc2335.example.bk";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in b/bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in
new file mode 100644
index 0000000..ffdd3e3
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3-unknown.example.db.in
@@ -0,0 +1,34 @@
+; Copyright (C) 2006, 2008 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: nsec3-unknown.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.e A 10.0.0.6
+child NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns3/nsec3.example.db.in b/bin/tests/system/dnssec/ns3/nsec3.example.db.in
new file mode 100644
index 0000000..97ac59c
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3.example.db.in
@@ -0,0 +1,43 @@
+; Copyright (C) 2006, 2008 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: nsec3.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.wild A 10.0.0.6
+child NS ns2.example.
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+02HC3EM7BDD011A0GMS3HKKJT2IF5VP8 A 10.0.0.17
diff --git a/bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in b/bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in
new file mode 100644
index 0000000..ca5b6e8
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3.nsec3.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) 2008 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: nsec3.nsec3.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in b/bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in
new file mode 100644
index 0000000..fd766e7
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/nsec3.optout.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) 2008 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: nsec3.optout.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in b/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in
new file mode 100644
index 0000000..b001555
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout-unknown.example.db.in
@@ -0,0 +1,34 @@
+; Copyright (C) 2006, 2008 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: optout-unknown.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.e A 10.0.0.6
+child NS ns2.example.
diff --git a/bin/tests/system/dnssec/ns3/optout.example.db.in b/bin/tests/system/dnssec/ns3/optout.example.db.in
new file mode 100644
index 0000000..e41d15b
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout.example.db.in
@@ -0,0 +1,45 @@
+; Copyright (C) 2006, 2008 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: optout.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a A 10.0.0.3
+*.wild A 10.0.0.6
+insecure NS ns.insecure
+ns.insecure A 10.53.0.3
+secure NS ns.secure
+ns.secure A 10.53.0.3
+nsec3 NS ns.nsec3
+ns.nsec3 A 10.53.0.3
+optout NS ns.optout
+ns.optout A 10.53.0.3
+child NS ns2.example.
+insecure.empty NS ns.insecure.empty
+ns.insecure.empty A 10.53.0.3
+foo.*.empty-wild NS ns
diff --git a/bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in b/bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in
new file mode 100644
index 0000000..150c386
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout.nsec3.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) 2008 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: optout.nsec3.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/optout.optout.example.db.in b/bin/tests/system/dnssec/ns3/optout.optout.example.db.in
new file mode 100644
index 0000000..91b5b89
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/optout.optout.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) 2008 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: optout.optout.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/secure.example.db.in b/bin/tests/system/dnssec/ns3/secure.example.db.in
new file mode 100644
index 0000000..9cd4d6f
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.example.db.in
@@ -0,0 +1,41 @@
+; Copyright (C) 2004, 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
+; 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: secure.example.db.in,v 1.13 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in b/bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in
new file mode 100644
index 0000000..92e720b
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.nsec3.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) 2008 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: secure.nsec3.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/secure.optout.example.db.in b/bin/tests/system/dnssec/ns3/secure.optout.example.db.in
new file mode 100644
index 0000000..d1ac6af
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/secure.optout.example.db.in
@@ -0,0 +1,40 @@
+; Copyright (C) 2008 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: secure.optout.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+d A 10.0.0.4
+z A 10.0.0.26
+a.a.a.a.a.a.a.a.a.a.e A 10.0.0.27
+x CNAME a
+
+private NS ns.private
+ns.private A 10.53.0.2
+
+insecure NS ns.insecure
+ns.insecure A 10.53.0.2
+
diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh
new file mode 100644
index 0000000..eb362aa
--- /dev/null
+++ b/bin/tests/system/dnssec/ns3/sign.sh
@@ -0,0 +1,224 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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: sign.sh,v 1.25 2008/09/25 04:02:38 tbox Exp $
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+RANDFILE=../random.data
+
+zone=secure.example.
+infile=secure.example.db.in
+zonefile=secure.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+
+zone=bogus.example.
+infile=bogus.example.db.in
+zonefile=bogus.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+
+zone=dynamic.example.
+infile=dynamic.example.db.in
+zonefile=dynamic.example.db
+
+keyname1=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+keyname2=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 1024 -n zone -f KSK $zone`
+
+cat $infile $keyname1.key $keyname2.key >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+
+zone=keyless.example.
+infile=keyless.example.db.in
+zonefile=keyless.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+
+# Change the signer field of the a.b.keyless.example SIG A
+# to point to a provably nonexistent KEY record.
+mv $zonefile.signed $zonefile.tmp
+<$zonefile.tmp perl -p -e 's/ keyless.example/ b.keyless.example/
+ if /^a.b.keyless.example/../NXT/;' >$zonefile.signed
+rm -f $zonefile.tmp
+
+#
+# NSEC3/NSEC test zone
+#
+zone=secure.nsec3.example.
+infile=secure.nsec3.example.db.in
+zonefile=secure.nsec3.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+
+#
+# NSEC3/NSEC3 test zone
+#
+zone=nsec3.nsec3.example.
+infile=nsec3.nsec3.example.db.in
+zonefile=nsec3.nsec3.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
+
+#
+# OPTOUT/NSEC3 test zone
+#
+zone=optout.nsec3.example.
+infile=optout.nsec3.example.db.in
+zonefile=optout.nsec3.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null
+
+#
+# A nsec3 zone (non-optout).
+#
+zone=nsec3.example.
+infile=nsec3.example.db.in
+zonefile=nsec3.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -g -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
+
+#
+# OPTOUT/NSEC test zone
+#
+zone=secure.optout.example.
+infile=secure.optout.example.db.in
+zonefile=secure.optout.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+
+#
+# OPTOUT/NSEC3 test zone
+#
+zone=nsec3.optout.example.
+infile=nsec3.optout.example.db.in
+zonefile=nsec3.optout.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
+
+#
+# OPTOUT/OPTOUT test zone
+#
+zone=optout.optout.example.
+infile=optout.optout.example.db.in
+zonefile=optout.optout.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null
+
+#
+# A optout nsec3 zone.
+#
+zone=optout.example.
+infile=optout.example.db.in
+zonefile=optout.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -g -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null
+
+#
+# A nsec3 zone (non-optout) with unknown hash algorithm.
+#
+zone=nsec3-unknown.example.
+infile=nsec3-unknown.example.db.in
+zonefile=nsec3-unknown.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -3 - -U -r $RANDFILE -o $zone $zonefile > /dev/null
+
+#
+# A optout nsec3 zone.
+#
+zone=optout-unknown.example.
+infile=optout-unknown.example.db.in
+zonefile=optout-unknown.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -3 - -U -A -r $RANDFILE -o $zone $zonefile > /dev/null
+
+#
+# A multiple parameter nsec3 zone.
+#
+zone=multiple.example.
+infile=multiple.example.db.in
+zonefile=multiple.example.db
+
+keyname=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -r $RANDFILE -o $zone $zonefile > /dev/null
+mv $zonefile.signed $zonefile
+$SIGNER -3 - -r $RANDFILE -o $zone $zonefile > /dev/null
+mv $zonefile.signed $zonefile
+$SIGNER -3 AAAA -r $RANDFILE -o $zone $zonefile > /dev/null
+mv $zonefile.signed $zonefile
+$SIGNER -3 BBBB -r $RANDFILE -o $zone $zonefile > /dev/null
+mv $zonefile.signed $zonefile
+$SIGNER -3 CCCC -r $RANDFILE -o $zone $zonefile > /dev/null
+mv $zonefile.signed $zonefile
+$SIGNER -3 DDDD -r $RANDFILE -o $zone $zonefile > /dev/null
diff --git a/bin/tests/system/dnssec/ns4/named.conf b/bin/tests/system/dnssec/ns4/named.conf
new file mode 100644
index 0000000..63da89c
--- /dev/null
+++ b/bin/tests/system/dnssec/ns4/named.conf
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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.conf,v 1.28 2007/06/18 23:47:28 tbox Exp $ */
+
+// NS4
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+ dnssec-must-be-secure mustbesecure.example yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns5/named.conf b/bin/tests/system/dnssec/ns5/named.conf
new file mode 100644
index 0000000..64892ca
--- /dev/null
+++ b/bin/tests/system/dnssec/ns5/named.conf
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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.conf,v 1.25 2007/06/18 23:47:28 tbox Exp $ */
+
+// NS5
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns5/trusted.conf.bad b/bin/tests/system/dnssec/ns5/trusted.conf.bad
new file mode 100644
index 0000000..b806e40
--- /dev/null
+++ b/bin/tests/system/dnssec/ns5/trusted.conf.bad
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2004, 2007 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: trusted.conf.bad,v 1.9 2007/06/19 23:47:02 tbox Exp $ */
+
+trusted-keys {
+ "." 256 3 1 "AQO6Cl+slAf+iuieDim9L3kujFHQD7s/IOj03ClMOpKYcTXtK4mRpuULVfvWxDi9Ew/gj0xLnnX7z9OJHIxLI+DSrAHd8Dm0XfBEAtVtJSn70GaPZgnLMw1rk5ap2DsEoWk=";
+};
diff --git a/bin/tests/system/dnssec/ns6/named.conf b/bin/tests/system/dnssec/ns6/named.conf
new file mode 100644
index 0000000..eb35680
--- /dev/null
+++ b/bin/tests/system/dnssec/ns6/named.conf
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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.conf,v 1.12 2007/06/18 23:47:28 tbox Exp $ */
+
+// NS6
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.6;
+ notify-source 10.53.0.6;
+ transfer-source 10.53.0.6;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.6; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+ disable-algorithms . { DSA; };
+ dnssec-enable yes;
+ dnssec-validation yes;
+ dnssec-lookaside . trust-anchor dlv;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns7/named.conf b/bin/tests/system/dnssec/ns7/named.conf
new file mode 100644
index 0000000..0b5ce89
--- /dev/null
+++ b/bin/tests/system/dnssec/ns7/named.conf
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2006, 2008 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.conf,v 1.3 2008/09/25 04:02:38 tbox Exp $ */
+
+// NS3
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.7;
+ notify-source 10.53.0.7;
+ transfer-source 10.53.0.7;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.7; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "nsec3.example" {
+ type slave;
+ masters { 10.53.0.3; };
+ file "nsec3.example.bk";
+};
+
+zone "optout.example" {
+ type slave;
+ masters { 10.53.0.3; };
+ file "optout.example.bk";
+};
+
+zone "nsec3-unknown.example" {
+ type slave;
+ masters { 10.53.0.3; };
+ file "nsec3-unknown.example.bk";
+};
+
+zone "optout-unknown.example" {
+ type slave;
+ masters { 10.53.0.3; };
+ file "optout-unknown.example.bk";
+};
+
+zone "multiple.example" {
+ type slave;
+ masters { 10.53.0.3; };
+ file "multiple.example.bk";
+};
+
+include "trusted.conf";
diff --git a/bin/tests/system/dnssec/prereq.sh b/bin/tests/system/dnssec/prereq.sh
new file mode 100644
index 0000000..8d724f9
--- /dev/null
+++ b/bin/tests/system/dnssec/prereq.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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: prereq.sh,v 1.10 2007/06/19 23:47:02 tbox Exp $
+
+../../genrandom 400 random.data
+
+if $KEYGEN -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1
+then
+ rm -f Kfoo*
+else
+ echo "I:This test requires that --with-openssl was used." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/dnssec/setup.sh b/bin/tests/system/dnssec/setup.sh
new file mode 100644
index 0000000..43a6c76
--- /dev/null
+++ b/bin/tests/system/dnssec/setup.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.14 2007/06/19 23:47:02 tbox Exp $
+
+../../genrandom 400 random.data
+
+cd ns1 && sh sign.sh
+
+echo "a.bogus.example. A 10.0.0.22" >>../ns3/bogus.example.db.signed
+
+cd ../ns5 && cp -f trusted.conf.bad trusted.conf
diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh
new file mode 100644
index 0000000..57faa63
--- /dev/null
+++ b/bin/tests/system/dnssec/tests.sh
@@ -0,0 +1,834 @@
+#!/bin/sh
+#
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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: tests.sh,v 1.53 2008/09/25 04:02:38 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=0
+
+rm -f dig.out.*
+
+DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
+
+# Check the example. domain
+
+echo "I:checking that zone transfer worked ($n)"
+ret=0
+$DIG $DIGOPTS a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS a.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns3.test$n || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking positive validation NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking positive validation NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking positive validation OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking positive wildcard validation NSEC ($n)"
+ret=0
+$DIG $DIGOPTS a.wild.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS a.wild.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking positive wildcard validation NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS a.wild.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS a.wild.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking positive wildcard validation OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS a.wild.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS a.wild.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking negative validation NXDOMAIN NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth q.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking negative validation NXDOMAIN NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth q.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth q.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking negative validation NXDOMAIN OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth q.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth q.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking negative validation NODATA NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth a.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking negative validation NODATA NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking negative validation NODATA OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking negative wildcard validation NSEC ($n)"
+ret=0
+$DIG $DIGOPTS b.wild.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS b.wild.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking negative wildcard validation NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS b.wild.nsec3.example. @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS b.wild.nsec3.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking negative wildcard validation OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS b.wild.optout.example. \
+ @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS b.wild.optout.example. \
+ @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# Check the insecure.example domain
+
+echo "I:checking 1-server insecurity proof NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking 1-server insecurity proof NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.insecure.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.insecure.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking 1-server insecurity proof OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.insecure.optout.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.insecure.optout.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking 1-server negative insecurity proof NSEC ($n)"
+ret=0
+$DIG $DIGOPTS q.insecure.example. a @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS q.insecure.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking 1-server negative insecurity proof NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS q.insecure.nsec3.example. a @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS q.insecure.nsec3.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking 1-server negative insecurity proof OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS q.insecure.optout.example. a @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS q.insecure.optout.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking 1-server negative insecurity proof with SOA hack NSEC ($n)"
+ret=0
+$DIG $DIGOPTS r.insecure.example. soa @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS r.insecure.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "0 IN SOA" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking 1-server negative insecurity proof with SOA hack NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS r.insecure.nsec3.example. soa @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS r.insecure.nsec3.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "0 IN SOA" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking 1-server negative insecurity proof with SOA hack OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS r.insecure.optout.example. soa @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS r.insecure.optout.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+grep "0 IN SOA" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# Check the secure.example domain
+
+echo "I:checking multi-stage positive validation NSEC/NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.secure.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.secure.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking multi-stage positive validation NSEC/NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking multi-stage positive validation NSEC/OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking multi-stage positive validation NSEC3/NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.secure.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.secure.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking multi-stage positive validation NSEC3/NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking multi-stage positive validation NSEC3/OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.optout.nsec3.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.optout.nsec3.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking multi-stage positive validation OPTOUT/NSEC ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.secure.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.secure.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking multi-stage positive validation OPTOUT/NSEC3 ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.nsec3.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.nsec3.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking multi-stage positive validation OPTOUT/OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.optout.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth a.optout.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking empty NODATA OPTOUT ($n)"
+ret=0
+$DIG $DIGOPTS +noauth empty.optout.example. \
+ @10.53.0.3 a > dig.out.ns3.test$n || ret=1
+$DIG $DIGOPTS +noauth empty.optout.example. \
+ @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+#grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# Check the bogus domain
+
+echo "I:checking failed validation ($n)"
+ret=0
+$DIG $DIGOPTS a.bogus.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
+grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# Try validating with a bad trusted key.
+# This should fail.
+
+echo "I:checking that validation fails with a misconfigured trusted key ($n)"
+ret=0
+$DIG $DIGOPTS example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that negative validation fails with a misconfigured trusted key ($n)"
+ret=0
+$DIG $DIGOPTS example. ptr @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that insecurity proofs fail with a misconfigured trusted key ($n)"
+ret=0
+$DIG $DIGOPTS a.insecure.example. a @10.53.0.5 > dig.out.ns5.test$n || ret=1
+grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that validation fails when key record is missing ($n)"
+ret=0
+$DIG $DIGOPTS a.b.keyless.example. a @10.53.0.4 > dig.out.ns4.test$n || ret=1
+grep "SERVFAIL" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# Check the insecure.secure.example domain (insecurity proof)
+
+echo "I:checking 2-server insecurity proof ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.2 a \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.4 a \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# Check a negative response in insecure.secure.example
+
+echo "I:checking 2-server insecurity proof with a negative answer ($n)"
+ret=0
+$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.2 a > dig.out.ns2.test$n \
+ || ret=1
+$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.4 a > dig.out.ns4.test$n \
+ || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking 2-server insecurity proof with a negative answer and SOA hack ($n)"
+ret=0
+$DIG $DIGOPTS r.insecure.secure.example. @10.53.0.2 soa > dig.out.ns2.test$n \
+ || ret=1
+$DIG $DIGOPTS r.insecure.secure.example. @10.53.0.4 soa > dig.out.ns4.test$n \
+ || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# Check that the query for a security root is successful and has ad set
+
+echo "I:checking security root query ($n)"
+ret=0
+$DIG $DIGOPTS . @10.53.0.4 key > dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# Check that the setting the cd bit works
+
+echo "I:checking cd bit on a positive answer ($n)"
+ret=0
+$DIG $DIGOPTS +noauth example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$DIG $DIGOPTS +noauth +cdflag example. soa @10.53.0.5 \
+ > dig.out.ns5.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking cd bit on a negative answer ($n)"
+ret=0
+$DIG $DIGOPTS q.example. soa @10.53.0.4 > dig.out.ns4.test$n || ret=1
+$DIG $DIGOPTS +cdflag q.example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking cd bit on a query that should fail ($n)"
+ret=0
+$DIG $DIGOPTS a.bogus.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$DIG $DIGOPTS +cdflag a.bogus.example. soa @10.53.0.5 \
+ > dig.out.ns5.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking cd bit on an insecurity proof ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.insecure.example. soa @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$DIG $DIGOPTS +noauth +cdflag a.insecure.example. soa @10.53.0.5 \
+ > dig.out.ns5.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - these are looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking cd bit on a negative insecurity proof ($n)"
+ret=0
+$DIG $DIGOPTS q.insecure.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$DIG $DIGOPTS +cdflag q.insecure.example. a @10.53.0.5 \
+ > dig.out.ns5.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns4.test$n dig.out.ns5.test$n || ret=1
+grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - these are looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns5.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that validation of an ANY query works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth foo.example. any @10.53.0.2 > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth foo.example. any @10.53.0.4 > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# 2 records in the zone, 1 NXT, 3 SIGs
+grep "ANSWER: 6" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that validation of a query returning a CNAME works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth cname1.example. txt @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth cname1.example. txt @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# the CNAME & its sig, the TXT and its SIG
+grep "ANSWER: 4" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that validation of a query returning a DNAME works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth foo.dname1.example. txt @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth foo.dname1.example. txt @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# The DNAME & its sig, the TXT and its SIG, and the synthesized CNAME.
+# It would be nice to test that the CNAME is being synthesized by the
+# recursive server and not cached, but I don't know how.
+grep "ANSWER: 5" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that validation of an ANY query returning a CNAME works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth cname2.example. any @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth cname2.example. any @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# The CNAME, NXT, and their SIGs
+grep "ANSWER: 4" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that validation of an ANY query returning a DNAME works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth foo.dname2.example. any @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth foo.dname2.example. any @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that positive validation in a privately secure zone works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that negative validation in a privately secure zone works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+grep "NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that lookups succeed after disabling a algorithm works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth example. SOA @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth example. SOA @10.53.0.6 \
+ > dig.out.ns6.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns6.test$n || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns6.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking privately secure to nxdomain works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking privately secure wildcard to nxdomain works ($n)"
+ret=0
+$DIG $DIGOPTS +noauth a.wild.private.secure.example. SOA @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+$DIG $DIGOPTS +noauth a.wild.private.secure.example. SOA @10.53.0.4 \
+ > dig.out.ns4.test$n || ret=1
+$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
+# Note - this is looking for failure, hence the &&
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+#
+# private.secure.example is served by the same server as its
+# grand parent and there is not a secure delegation from secure.example
+# to private.secure.example. In addition secure.example is using a
+# algorithm which the validation does not support.
+#
+echo "I:checking dnssec-lookaside-validation works ($n)"
+ret=0
+$DIG $DIGOPTS private.secure.example. SOA @10.53.0.6 \
+ > dig.out.ns6.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns6.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that we can load a rfc2535 signed zone ($n)"
+ret=0
+$DIG $DIGOPTS rfc2535.example. SOA @10.53.0.2 \
+ > dig.out.ns2.test$n || ret=1
+grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that we can transfer a rfc2535 signed zone ($n)"
+ret=0
+$DIG $DIGOPTS rfc2535.example. SOA @10.53.0.3 \
+ > dig.out.ns3.test$n || ret=1
+grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+# Run a minimal update test if possible. This is really just
+# a regression test for RT #2399; more tests should be added.
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ echo "I:running DNSSEC update test"
+ $PERL dnssec_update_test.pl -s 10.53.0.3 -p 5300 dynamic.example. || status=1
+else
+ echo "I:The DNSSEC update test requires the Net::DNS library." >&2
+fi
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/forward/clean.sh b/bin/tests/system/forward/clean.sh
new file mode 100644
index 0000000..b227745
--- /dev/null
+++ b/bin/tests/system/forward/clean.sh
@@ -0,0 +1,22 @@
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.6 2007/09/26 03:22:43 marka Exp $
+
+#
+# Clean up after forward tests.
+#
+rm -f dig.out.*
+rm -f */named.memstats
diff --git a/bin/tests/system/forward/ns1/example.db b/bin/tests/system/forward/ns1/example.db
new file mode 100644
index 0000000..ebbc2ae
--- /dev/null
+++ b/bin/tests/system/forward/ns1/example.db
@@ -0,0 +1,12 @@
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "recursed"
diff --git a/bin/tests/system/forward/ns1/named.conf b/bin/tests/system/forward/ns1/named.conf
new file mode 100644
index 0000000..8c3fcfa
--- /dev/null
+++ b/bin/tests/system/forward/ns1/named.conf
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.11 2007/06/19 23:47:03 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example1." {
+ type master;
+ file "example.db";
+};
+
+zone "example2." {
+ type master;
+ file "example.db";
+};
+
+zone "example3." {
+ type master;
+ file "example.db";
+};
+
+zone "example4." {
+ type master;
+ file "example.db";
+};
+
+zone "example5." {
+ type master;
+ file "example.db";
+};
diff --git a/bin/tests/system/forward/ns1/root.db b/bin/tests/system/forward/ns1/root.db
new file mode 100644
index 0000000..e84e8fb
--- /dev/null
+++ b/bin/tests/system/forward/ns1/root.db
@@ -0,0 +1,36 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.4 2007/06/19 23:47:03 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns2/example.db b/bin/tests/system/forward/ns2/example.db
new file mode 100644
index 0000000..3a5f46c
--- /dev/null
+++ b/bin/tests/system/forward/ns2/example.db
@@ -0,0 +1,12 @@
+$TTL 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "forwarded"
diff --git a/bin/tests/system/forward/ns2/named.conf b/bin/tests/system/forward/ns2/named.conf
new file mode 100644
index 0000000..d310bf2
--- /dev/null
+++ b/bin/tests/system/forward/ns2/named.conf
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.11 2007/06/19 23:47:03 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "example1." {
+ type master;
+ file "example.db";
+};
+
+zone "example2." {
+ type master;
+ file "example.db";
+};
+
+zone "example3." {
+ type master;
+ file "example.db";
+};
+
+zone "example4." {
+ type master;
+ file "example.db";
+};
diff --git a/bin/tests/system/forward/ns2/root.db b/bin/tests/system/forward/ns2/root.db
new file mode 100644
index 0000000..e84e8fb
--- /dev/null
+++ b/bin/tests/system/forward/ns2/root.db
@@ -0,0 +1,36 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.4 2007/06/19 23:47:03 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns3/named.conf b/bin/tests/system/forward/ns3/named.conf
new file mode 100644
index 0000000..459c349
--- /dev/null
+++ b/bin/tests/system/forward/ns3/named.conf
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.11 2007/06/19 23:47:03 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ forwarders { 10.53.0.2; };
+ forward first;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "example1." {
+ type forward;
+ forward first;
+ forwarders { 10.53.0.2; };
+};
+
+zone "example2." {
+ type forward;
+ forward first;
+ forwarders { };
+};
+
+zone "example3." {
+ type forward;
+ forward only;
+ forwarders { };
+};
+
diff --git a/bin/tests/system/forward/ns3/root.db b/bin/tests/system/forward/ns3/root.db
new file mode 100644
index 0000000..e84e8fb
--- /dev/null
+++ b/bin/tests/system/forward/ns3/root.db
@@ -0,0 +1,36 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.4 2007/06/19 23:47:03 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns4/named.conf b/bin/tests/system/forward/ns4/named.conf
new file mode 100644
index 0000000..f817b8a
--- /dev/null
+++ b/bin/tests/system/forward/ns4/named.conf
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.11 2007/06/19 23:47:03 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "example1." {
+ type forward;
+ forward first;
+ forwarders { 10.53.0.2; };
+};
+
+zone "example3." {
+ type forward;
+ forwarders { 10.53.0.2; };
+};
+
+zone "example5." {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.2; };
+};
diff --git a/bin/tests/system/forward/ns4/root.db b/bin/tests/system/forward/ns4/root.db
new file mode 100644
index 0000000..e84e8fb
--- /dev/null
+++ b/bin/tests/system/forward/ns4/root.db
@@ -0,0 +1,36 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.4 2007/06/19 23:47:03 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/tests.sh b/bin/tests/system/forward/tests.sh
new file mode 100644
index 0000000..c3c0bf3
--- /dev/null
+++ b/bin/tests/system/forward/tests.sh
@@ -0,0 +1,92 @@
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.7 2007/06/19 23:47:03 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+root=10.53.0.1
+hidden=10.53.0.2
+f1=10.53.0.3
+f2=10.53.0.4
+
+status=0
+
+echo "I:checking that a forward zone overrides global forwarders"
+ret=0
+$DIG txt.example1. txt @$hidden -p 5300 > dig.out.hidden || ret=1
+$DIG txt.example1. txt @$f1 -p 5300 > dig.out.f1 || ret=1
+$PERL ../digcomp.pl dig.out.hidden dig.out.f1 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that a forward first zone no forwarders recurses"
+ret=0
+$DIG txt.example2. txt @$root -p 5300 > dig.out.root || ret=1
+$DIG txt.example2. txt @$f1 -p 5300 > dig.out.f1 || ret=1
+$PERL ../digcomp.pl dig.out.root dig.out.f1 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that a forward only zone no forwarders fails"
+ret=0
+$DIG txt.example2. txt @$root -p 5300 > dig.out.root || ret=1
+$DIG txt.example2. txt @$f1 -p 5300 > dig.out.f1 || ret=1
+$PERL ../digcomp.pl dig.out.root dig.out.f1 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that global forwarders work"
+ret=0
+$DIG txt.example4. txt @$hidden -p 5300 > dig.out.hidden || ret=1
+$DIG txt.example4. txt @$f1 -p 5300 > dig.out.f1 || ret=1
+$PERL ../digcomp.pl dig.out.hidden dig.out.f1 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that a forward zone works"
+ret=0
+$DIG txt.example1. txt @$hidden -p 5300 > dig.out.hidden || ret=1
+$DIG txt.example1. txt @$f2 -p 5300 > dig.out.f2 || ret=1
+$PERL ../digcomp.pl dig.out.hidden dig.out.f2 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that forwarding doesn't spontaneously happen"
+ret=0
+$DIG txt.example2. txt @$root -p 5300 > dig.out.root || ret=1
+$DIG txt.example2. txt @$f2 -p 5300 > dig.out.f2 || ret=1
+$PERL ../digcomp.pl dig.out.root dig.out.f2 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that a forward zone with no specified policy works"
+ret=0
+$DIG txt.example3. txt @$hidden -p 5300 > dig.out.hidden || ret=1
+$DIG txt.example3. txt @$f2 -p 5300 > dig.out.f2 || ret=1
+$PERL ../digcomp.pl dig.out.hidden dig.out.f2 || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:checking that a forward only doesn't recurse"
+ret=0
+$DIG txt.example5. txt @$f2 -p 5300 > dig.out.f2 || ret=1
+grep "SERVFAIL" dig.out.f2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/genzone.sh b/bin/tests/system/genzone.sh
new file mode 100644
index 0000000..bea95e8
--- /dev/null
+++ b/bin/tests/system/genzone.sh
@@ -0,0 +1,267 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 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: genzone.sh,v 1.8 2007/06/19 23:47:00 tbox Exp $
+
+#
+# Set up a test zone
+#
+# Usage: genzone.sh master-server-number slave-server-number...
+#
+# e.g., "genzone.sh 2 3 4" means ns2 is the master and ns3, ns4
+# are slaves.
+#
+
+master="$1"
+
+cat <<EOF
+\$TTL 3600
+
+@ 86400 IN SOA ns${master} hostmaster (
+ 1397051952 ; "SER0"
+ 5
+ 5
+ 1814400
+ 3600 )
+EOF
+
+for n
+do
+ cat <<EOF
+@ NS ns${n}
+ns${n} A 10.53.0.${n}
+EOF
+done
+
+cat <<\EOF
+
+; type 1
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+
+; type 2
+; see NS records at top of file
+
+; type 3
+; md01 MD madname
+; MD .
+
+; type 4
+; mf01 MF madname
+; mf01 MF .
+
+; type 5
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+
+; type 6
+; see SOA record at top of file
+
+; type 7
+mb01 MG madname
+mb02 MG .
+
+; type 8
+mg01 MG mgmname
+mg02 MG .
+
+; type 9
+mr01 MR mrname
+mr02 MR .
+
+; type 10
+; NULL RRs are not allowed in master files per RFC1035.
+;null01 NULL
+
+; type 11
+wks01 WKS 10.0.0.1 tcp telnet ftp 0 1 2
+wks02 WKS 10.0.0.1 udp domain 0 1 2
+wks03 WKS 10.0.0.2 tcp 65535
+
+; type 12
+ptr01 PTR @
+
+; type 13
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO PC NetBSD
+
+; type 14
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+
+; type 15
+mx01 MX 10 mail
+mx02 MX 10 .
+
+; type 16
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT foo
+txt04 TXT foo bar
+txt05 TXT "foo bar"
+txt06 TXT "foo\032bar"
+txt07 TXT foo\032bar
+txt08 TXT "foo\010bar"
+txt09 TXT foo\010bar
+txt10 TXT foo\ bar
+txt11 TXT "\"foo\""
+txt12 TXT \"foo\"
+
+; type 17
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+
+; type 18
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+
+; type 19
+x2501 X25 123456789
+;x2502 X25 "123456789"
+
+; type 20
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN isdn-address
+isdn04 ISDN isdn-address subaddress
+
+; type 21
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+
+; type 22
+nsap01 NSAP (
+ 0x47.0005.80.005a00.0000.0001.e133.ffffff000161.00 )
+nsap02 NSAP (
+ 0x47.0005.80.005a00.0000.0001.e133.ffffff000161.00. )
+;nsap03 NSAP 0x
+
+; type 23
+nsap-ptr01 NSAP-PTR foo.
+nsap-ptr01 NSAP-PTR .
+
+; type 24
+;sig01 SIG NXT 1 3 ( 3600 20000102030405
+; 19961211100908 2143 foo.nil.
+; MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45I
+; kskceFGgiWCn/GxHhai6VAuHAoNUz4YoU1t
+; VfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= )
+
+; type 25
+;key01 KEY 512 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY
+; 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV
+; sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
+; a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
+
+; type 26
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+
+; type 27
+gpos01 GPOS -22.6882 116.8652 250.0
+gpos02 GPOS "" "" ""
+
+; type 29
+loc01 LOC 60 9 N 24 39 E 10 20 2000 20
+loc02 LOC 60 09 00.000 N 24 39 00.000 E 10.00m 20.00m (
+ 2000.00m 20.00m )
+
+; type 30
+;nxt01 NXT a.secure.nil. ( NS SOA MX RRSIG KEY LOC NXT )
+;nxt02 NXT . NXT NSAP-PTR
+;nxt03 NXT . 1
+;nxt04 NXT . 127
+
+; type 33
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box
+
+; type 35
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 blurgh blorf blegh foo.
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+
+; type 36
+kx01 KX 10 kdc
+kx02 KX 10 .
+
+; type 37
+cert01 CERT 65534 65535 254 (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45I
+ kskceFGgiWCn/GxHhai6VAuHAoNUz4YoU1t
+ VfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= )
+; type 38
+a601 A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+a601 A6 64 ::ffff:ffff:ffff:ffff foo.
+a601 A6 127 ::1 foo.
+a601 A6 128 .
+
+; type 39
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+
+; type 41
+; OPT is a meta-type and should never occur in master files.
+
+; type 46
+rrsig01 RRSIG NSEC 1 3 ( 3600 20000102030405
+ 19961211100908 2143 foo.nil.
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45I
+ kskceFGgiWCn/GxHhai6VAuHAoNUz4YoU1t
+ VfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= )
+
+; type 47
+nsec01 NSEC a.secure.nil. ( NS SOA MX RRSIG DNSKEY LOC NSEC )
+nsec02 NSEC . NSEC NSAP-PTR
+nsec03 NSEC . TYPE1
+nsec04 NSEC . TYPE127
+
+; type 48
+dnskey01 DNSKEY 512 ( 255 1 AQMFD5raczCJHViKtLYhWGz8hMY
+ 9UGRuniJDBzC7w0aRyzWZriO6i2odGWWQVucZqKV
+ sENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esg
+ a60zyGW6LFe9r8n6paHrlG5ojqf0BaqHT+8= )
+
+; type 249
+; TKEY is a meta-type and should never occur in master files.
+; The text representation is not specified in the draft.
+; This example was written based on the bind9 RR parsing code.
+;tkey01 TKEY 928321914 928321915 (
+; 255 ; algorithm
+; 65535 ; mode
+; 0 ; error
+; 3 ; key size
+; aaaa ; key data
+; 3 ; other size
+; bbbb ; other data
+; )
+;; A TKEY with empty "other data"
+;tkey02 TKEY 928321914 928321915 (
+; 255 ; algorithm
+; 65535 ; mode
+; 0 ; error
+; 3 ; key size
+; aaaa ; key data
+; 0 ; other size
+; ; other data
+; )
+
+; type 255
+; TSIG is a meta-type and should never occur in master files.
+EOF
diff --git a/bin/tests/system/glue/clean.sh b/bin/tests/system/glue/clean.sh
new file mode 100644
index 0000000..a3bc740
--- /dev/null
+++ b/bin/tests/system/glue/clean.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.9 2007/09/26 03:22:43 marka Exp $
+
+#
+# Clean up after glue tests.
+#
+
+rm -f dig.out ns1/cache
+rm -f */named.memstats
diff --git a/bin/tests/system/glue/fi.good b/bin/tests/system/glue/fi.good
new file mode 100644
index 0000000..a08bc7a
--- /dev/null
+++ b/bin/tests/system/glue/fi.good
@@ -0,0 +1,27 @@
+
+; <<>> DiG 9.0 <<>> +norec @10.53.0.1 -p 5300 foo.bar.fi. A
+;; global options: printcmd
+;; Got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58772
+;; flags: qr ad; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 7
+
+;; QUESTION SECTION:
+;foo.bar.fi. IN A
+
+;; AUTHORITY SECTION:
+fi. 172800 IN NS NS.EU.NET.
+fi. 172800 IN NS NS.TELE.fi.
+fi. 172800 IN NS PRIFI.EUNET.fi.
+fi. 172800 IN NS NS.UU.NET.
+fi. 172800 IN NS T.NS.VERIO.NET.
+fi. 172800 IN NS HYDRA.HELSINKI.fi.
+
+;; ADDITIONAL SECTION:
+NS.TELE.fi. 172800 IN A 193.210.19.19
+NS.TELE.fi. 172800 IN A 193.210.18.18
+PRIFI.EUNET.fi. 172800 IN A 193.66.1.146
+NS.UU.NET. 172800 IN A 137.39.1.3
+T.NS.VERIO.NET. 172800 IN A 192.67.14.16
+HYDRA.HELSINKI.fi. 172800 IN A 128.214.4.29
+NS.EU.NET. 172800 IN A 192.16.202.11
+
diff --git a/bin/tests/system/glue/noglue.good b/bin/tests/system/glue/noglue.good
new file mode 100644
index 0000000..22eca7b
--- /dev/null
+++ b/bin/tests/system/glue/noglue.good
@@ -0,0 +1,14 @@
+
+; <<>> DiG 9.0 <<>> @10.53.0.1 -p 5300 example.net a
+;; global options: printcmd
+;; Got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29409
+;; flags: qr rd ad; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 0
+
+;; QUESTION SECTION:
+;example.net. IN A
+
+;; AUTHORITY SECTION:
+example.net. 300 IN NS ns2.example.
+example.net. 300 IN NS ns1.example.
+
diff --git a/bin/tests/system/glue/ns1/cache.in b/bin/tests/system/glue/ns1/cache.in
new file mode 100644
index 0000000..4ccd206
--- /dev/null
+++ b/bin/tests/system/glue/ns1/cache.in
@@ -0,0 +1,23 @@
+; Copyright (C) 2004, 2007 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: cache.in,v 1.4 2007/06/19 23:47:03 tbox Exp $
+
+; Preloaded cache data for glue test
+
+$TTL 86400
+ns.zz. 3600 IN A 10.0.0.1
+ns.zz. IN AAAA 10::1
+ns.zz. IN A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
diff --git a/bin/tests/system/glue/ns1/mil.db b/bin/tests/system/glue/ns1/mil.db
new file mode 100644
index 0000000..6e90da8
--- /dev/null
+++ b/bin/tests/system/glue/ns1/mil.db
@@ -0,0 +1,31 @@
+; Copyright (C) 2004, 2007 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: mil.db,v 1.8 2007/06/19 23:47:03 tbox Exp $
+
+$ORIGIN mil.
+$TTL 300
+@ IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS a.root-servers.nil.
+
+ARL.MIL. 172800 IN NS NS1.ARL.MIL.
+NS1.arl.mil. 172800 IN A 128.63.16.4
+
diff --git a/bin/tests/system/glue/ns1/named.conf b/bin/tests/system/glue/ns1/named.conf
new file mode 100644
index 0000000..00a740f
--- /dev/null
+++ b/bin/tests/system/glue/ns1/named.conf
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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.conf,v 1.15 2007/06/19 23:47:03 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ cache-file "cache";
+ check-integrity no;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "root-servers.nil" {
+ type master;
+ file "root-servers.nil.db";
+};
+zone "net" {
+ type master;
+ file "net.db";
+};
+
+zone "mil" {
+ type master;
+ file "mil.db";
+};
diff --git a/bin/tests/system/glue/ns1/net.db b/bin/tests/system/glue/ns1/net.db
new file mode 100644
index 0000000..e0e718d
--- /dev/null
+++ b/bin/tests/system/glue/ns1/net.db
@@ -0,0 +1,40 @@
+; Copyright (C) 2004, 2007 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: net.db,v 1.8 2007/06/19 23:47:03 tbox Exp $
+
+$ORIGIN net.
+$TTL 300
+@ IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS a.root-servers.nil.
+
+; FI. authoritative servers, for the FI. glue test.
+uu.net. NS ns.uu.net.
+NS.UU.NET. 172800 IN A 137.39.1.3
+eu.net. NS ns.eu.net.
+NS.EU.NET. 172800 IN A 192.16.202.11
+
+; Referral outside of server authority, but with glue records present.
+; Don't hand out the glue.
+example.net. NS ns1.example.
+example.net. NS ns2.example.
+ns1.example. 172800 IN A 1.1.1.1
+ns2.example. 172800 IN A 2.2.2.2
diff --git a/bin/tests/system/glue/ns1/root-servers.nil.db b/bin/tests/system/glue/ns1/root-servers.nil.db
new file mode 100644
index 0000000..6c4c0c6
--- /dev/null
+++ b/bin/tests/system/glue/ns1/root-servers.nil.db
@@ -0,0 +1,31 @@
+; Copyright (C) 2004, 2007 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: root-servers.nil.db,v 1.7 2007/06/19 23:47:03 tbox Exp $
+
+$TTL 300
+@ IN SOA ns hostmaster (
+ 1
+ 3600
+ 1800
+ 1814400
+ 3600
+ )
+ NS a
+a A 10.53.0.1
+b A 10.53.0.2
+
+
+
diff --git a/bin/tests/system/glue/ns1/root.db b/bin/tests/system/glue/ns1/root.db
new file mode 100644
index 0000000..679c432
--- /dev/null
+++ b/bin/tests/system/glue/ns1/root.db
@@ -0,0 +1,76 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.7 2007/06/19 23:47:03 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+
+root-servers.nil. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+; Delegate some domains that contain name servers for the sample
+; ccTLDs below.
+net. 172800 IN NS a.root-servers.nil.
+mil. 172800 IN NS a.root-servers.nil.
+se. 172800 IN NS ns.uu.net.
+
+;
+; A sample ccTLD
+;
+fi. 172800 IN NS NS.TELE.fi.
+fi. 172800 IN NS PRIFI.EUNET.fi.
+fi. 172800 IN NS NS.UU.NET.
+fi. 172800 IN NS T.NS.VERIO.NET.
+fi. 172800 IN NS HYDRA.HELSINKI.fi.
+fi. 172800 IN NS NS.EU.NET.
+NS.TELE.fi. 172800 IN A 193.210.18.18
+NS.TELE.fi. 172800 IN A 193.210.19.19
+PRIFI.EUNET.fi. 172800 IN A 193.66.1.146
+NS.UU.NET. 172800 IN A 137.39.1.3
+T.NS.VERIO.NET. 172800 IN A 192.67.14.16
+HYDRA.HELSINKI.fi. 172800 IN A 128.214.4.29
+NS.EU.NET. 172800 IN A 192.16.202.11
+
+;
+; Another sample ccTLD
+;
+is. 172800 IN NS ISGATE.is.
+is. 172800 IN NS NISC.JVNC.NET.
+is. 172800 IN NS NS.EU.NET.
+is. 172800 IN NS SPARKY.ARL.MIL.
+is. 172800 IN NS SUNIC.SUNET.SE.
+ISGATE.is. 172800 IN A 193.4.58.51
+NISC.JVNC.NET. 172800 IN A 128.121.50.7
+NS.EU.NET. 172800 IN A 192.16.202.11
+SPARKY.ARL.MIL. 172800 IN A 128.63.58.18
+SUNIC.SUNET.SE. 172800 IN A 192.36.125.2
+
+;
+; A hypothetical ccTLD where we are authoritative for the NS glue.
+;
+xx. 172800 IN NS b.root-servers.nil.
+
+;
+; A hypothetical ccTLD where we have cached NS glue.
+;
+yy. 172800 IN NS ns.zz.
diff --git a/bin/tests/system/glue/setup.sh b/bin/tests/system/glue/setup.sh
new file mode 100644
index 0000000..2dbbe03
--- /dev/null
+++ b/bin/tests/system/glue/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# 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: setup.sh,v 1.6 2007/06/19 23:47:03 tbox Exp $
+
+cd ns1 && cp -f cache.in cache
diff --git a/bin/tests/system/glue/tests.sh b/bin/tests/system/glue/tests.sh
new file mode 100644
index 0000000..3ecf701
--- /dev/null
+++ b/bin/tests/system/glue/tests.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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
+# 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: tests.sh,v 1.9 2007/06/19 23:47:03 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+#
+# Do glue tests.
+#
+
+status=0
+
+echo "I:testing that a ccTLD referral gets a full glue set from the root zone"
+$DIG +norec @10.53.0.1 -p 5300 foo.bar.fi. A >dig.out || status=1
+$PERL ../digcomp.pl fi.good dig.out || status=1
+
+echo "I:testing that we find glue A RRs we are authoritative for"
+$DIG +norec @10.53.0.1 -p 5300 foo.bar.xx. a >dig.out || status=1
+$PERL ../digcomp.pl xx.good dig.out || status=1
+
+echo "I:testing that we find glue A/AAAA RRs in the cache"
+$DIG +norec @10.53.0.1 -p 5300 foo.bar.yy. a >dig.out || status=1
+$PERL ../digcomp.pl yy.good dig.out || status=1
+
+echo "I:testing that we don't find out-of-zone glue"
+$DIG +norec @10.53.0.1 -p 5300 example.net. a > dig.out || status=1
+$PERL ../digcomp.pl noglue.good dig.out || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/glue/xx.good b/bin/tests/system/glue/xx.good
new file mode 100644
index 0000000..19ae1d7
--- /dev/null
+++ b/bin/tests/system/glue/xx.good
@@ -0,0 +1,16 @@
+
+; <<>> DiG 9.0 <<>> +norec @10.53.0.1 -p 5300 foo.bar.xx. a
+;; global options: printcmd
+;; Got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41239
+;; flags: qr ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
+
+;; QUESTION SECTION:
+;foo.bar.xx. IN A
+
+;; AUTHORITY SECTION:
+xx. 172800 IN NS b.root-servers.nil.
+
+;; ADDITIONAL SECTION:
+b.root-servers.nil. 300 IN A 10.53.0.2
+
diff --git a/bin/tests/system/glue/yy.good b/bin/tests/system/glue/yy.good
new file mode 100644
index 0000000..fd97e3d
--- /dev/null
+++ b/bin/tests/system/glue/yy.good
@@ -0,0 +1,17 @@
+
+; <<>> DiG 9.0 <<>> +norec @10.53.0.1 -p 5300 foo.bar.yy. a
+;; global options: printcmd
+;; Got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6172
+;; flags: qr ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 3
+
+;; QUESTION SECTION:
+;foo.bar.yy. IN A
+
+;; AUTHORITY SECTION:
+yy. 172800 IN NS ns.zz.
+
+;; ADDITIONAL SECTION:
+ns.zz. 3463 IN A 10.0.0.1
+ns.zz. 86263 IN AAAA 10::1
+
diff --git a/bin/tests/system/ifconfig.sh b/bin/tests/system/ifconfig.sh
new file mode 100755
index 0000000..779d6f9
--- /dev/null
+++ b/bin/tests/system/ifconfig.sh
@@ -0,0 +1,189 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007, 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
+# 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: ifconfig.sh,v 1.55 2008/09/24 02:46:21 marka Exp $
+
+#
+# Set up interface aliases for bind9 system tests.
+#
+
+config_guess=""
+for f in ./config.guess ../../../config.guess
+do
+ if test -f $f
+ then
+ config_guess=$f
+ fi
+done
+
+if test "X$config_guess" = "X"
+then
+ echo <<EOF >&2
+$0: must be run from the top level source directory or the
+bin/tests/system directory
+EOF
+ exit 1
+fi
+
+# If running on hp-ux, don't even try to run config.guess.
+# It will try to create a temporary file in the current directory,
+# which fails when running as root with the current directory
+# on a NFS mounted disk.
+
+case `uname -a` in
+ *HP-UX*) sys=hpux ;;
+ *) sys=`sh $config_guess` ;;
+esac
+
+case "$2" in
+[0-9]|[1-9][0-9]|[1-9][0-9][0-9]) base=$2;;
+*) base=""
+esac
+
+case "$1" in
+
+ start|up)
+ for ns in 1 2 3 4 5 6 7
+ do
+ if test -n "$base"
+ then
+ int=`expr $ns + $base - 1`
+ else
+ int=$ns
+ fi
+ case "$sys" in
+ *-pc-solaris2.5.1)
+ ifconfig lo0:$int 10.53.0.$ns netmask 0xffffffff up
+ ;;
+ *-sun-solaris2.[6-7])
+ ifconfig lo0:$int 10.53.0.$ns netmask 0xffffffff up
+ ;;
+ *-*-solaris2.[8-9]|*-*-solaris2.1[0-9])
+ /sbin/ifconfig lo0:$int plumb
+ /sbin/ifconfig lo0:$int 10.53.0.$ns up
+ ;;
+ *-*-linux*)
+ ifconfig lo:$int 10.53.0.$ns up netmask 255.255.255.0
+ ;;
+ *-unknown-freebsd*)
+ ifconfig lo0 10.53.0.$ns alias netmask 0xffffffff
+ ;;
+ *-unknown-netbsd*)
+ ifconfig lo0 10.53.0.$ns alias netmask 255.255.255.0
+ ;;
+ *-unknown-openbsd*)
+ ifconfig lo0 10.53.0.$ns alias netmask 255.255.255.0
+ ;;
+ *-*-bsdi[3-5].*)
+ ifconfig lo0 add 10.53.0.$ns netmask 255.255.255.0
+ ;;
+ *-dec-osf[4-5].*)
+ ifconfig lo0 alias 10.53.0.$ns
+ ;;
+ *-sgi-irix6.*)
+ ifconfig lo0 alias 10.53.0.$ns
+ ;;
+ *-*-sysv5uw7*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ ifconfig lo0 10.53.0.$ns alias netmask 0xffffffff
+ ;;
+ *-ibm-aix4.*|*-ibm-aix5.*)
+ ifconfig lo0 alias 10.53.0.$ns
+ ;;
+ hpux)
+ ifconfig lo0:$int 10.53.0.$ns up
+ ;;
+ *-sco3.2v*)
+ ifconfig lo0 alias 10.53.0.$ns
+ ;;
+ *-darwin*)
+ ifconfig lo0 alias 10.53.0.$ns
+ ;;
+ *)
+ echo "Don't know how to set up interface. Giving up."
+ exit 1
+ esac
+ done
+ ;;
+
+ stop|down)
+ for ns in 7 6 5 4 3 2 1
+ do
+ if test -n "$base"
+ then
+ int=`expr $ns + $base - 1`
+ else
+ int=$ns
+ fi
+ case "$sys" in
+ *-pc-solaris2.5.1)
+ ifconfig lo0:$int 0.0.0.0 down
+ ;;
+ *-sun-solaris2.[6-7])
+ ifconfig lo0:$int 10.53.0.$ns down
+ ;;
+ *-*-solaris2.[8-9]|*-*-solaris2.1[0-9])
+ ifconfig lo0:$int 10.53.0.$ns down
+ ifconfig lo0:$int 10.53.0.$ns unplumb
+ ;;
+ *-*-linux*)
+ ifconfig lo:$int 10.53.0.$ns down
+ ;;
+ *-unknown-freebsd*)
+ ifconfig lo0 10.53.0.$ns delete
+ ;;
+ *-unknown-netbsd*)
+ ifconfig lo0 10.53.0.$ns delete
+ ;;
+ *-unknown-openbsd*)
+ ifconfig lo0 10.53.0.$ns delete
+ ;;
+ *-*-bsdi[3-5].*)
+ ifconfig lo0 remove 10.53.0.$ns
+ ;;
+ *-dec-osf[4-5].*)
+ ifconfig lo0 -alias 10.53.0.$ns
+ ;;
+ *-sgi-irix6.*)
+ ifconfig lo0 -alias 10.53.0.$ns
+ ;;
+ *-*-sysv5uw7*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ ifconfig lo0 -alias 10.53.0.$ns
+ ;;
+ *-ibm-aix4.*|*-ibm-aix5.*)
+ ifconfig lo0 delete 10.53.0.$ns
+ ;;
+ hpux)
+ ifconfig lo0:$int 10.53.0.$ns down
+ ;;
+ *-sco3.2v*)
+ ifconfig lo0 -alias 10.53.0.$ns
+ ;;
+ *darwin*)
+ ifconfig lo0 -alias 10.53.0.$ns
+ ;;
+ *)
+ echo "Don't know how to destroy interface. Giving up."
+ exit 1
+ esac
+ done
+
+ ;;
+
+ *)
+ echo "Usage: $0 { up | down } [base]"
+ exit 1
+esac
diff --git a/bin/tests/system/ixfr/ans2/ans.pl b/bin/tests/system/ixfr/ans2/ans.pl
new file mode 100644
index 0000000..ef67955
--- /dev/null
+++ b/bin/tests/system/ixfr/ans2/ans.pl
@@ -0,0 +1,157 @@
+#!/usr/bin/perl
+#
+# 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: ans.pl,v 1.6 2007/09/24 04:13:25 marka Exp $
+
+#
+# This is the name server from hell. It provides canned
+# responses based on pattern matching the queries, and
+# can be reprogrammed on-the-fly over a TCP connection.
+#
+# The server listens for control connections on port 5301.
+# A control connection is a TCP stream of lines like
+#
+# /pattern/
+# name ttl type rdata
+# name ttl type rdata
+# ...
+# /pattern/
+# name ttl type rdata
+# name ttl type rdata
+# ...
+#
+# There can be any number of patterns, each associated
+# with any number of response RRs. Each pattern is a
+# Perl regular expression.
+#
+# Each incoming query is converted into a string of the form
+# "qname qtype" (the printable query domain name, space,
+# printable query type) and matched against each pattern.
+#
+# The first pattern matching the query is selected, and
+# the RR following the pattern line are sent in the
+# answer section of the response.
+#
+# Each new control connection causes the current set of
+# patterns and responses to be cleared before adding new
+# ones.
+#
+# The server handles UDP and TCP queries. Zone transfer
+# responses work, but must fit in a single 64 k message.
+#
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $ctlsock = IO::Socket::INET->new(LocalAddr => "10.53.0.2",
+ LocalPort => 5301, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "10.53.0.2",
+ LocalPort => 5300, Proto => "udp", Reuse => 1) or die "$!";
+
+my $tcpsock = IO::Socket::INET->new(LocalAddr => "10.53.0.2",
+ LocalPort => 5300, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";;
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+my @answers = ();
+
+sub handle {
+ my ($buf) = @_;
+
+ my ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ my $r;
+ foreach $r (@rules) {
+ my $pattern = $r->{pattern};
+ warn "match $qname $qtype == $pattern";
+ if ("$qname $qtype" =~ /$pattern/) {
+ my $a;
+ foreach $a (@{$r->{answer}}) {
+ $packet->push("answer", $a);
+ }
+ last;
+ }
+ }
+
+ # $packet->print;
+
+ return $packet->data;
+}
+
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($ctlsock), 1) = 1;
+ vec($rin, fileno($tcpsock), 1) = 1;
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($ctlsock), 1)) {
+ warn "ctl conn";
+ my $conn = $ctlsock->accept;
+ @rules = ();
+ while (my $line = $conn->getline) {
+ chomp $line;
+ if ($line =~ m!^/(.*)/$!) {
+ $rule = { pattern => $1, answer => [] };
+ push(@rules, $rule);
+ } else {
+ push(@{$rule->{answer}},
+ new Net::DNS::RR($line));
+ }
+
+ }
+ $conn->close;
+ } elsif (vec($rout, fileno($udpsock), 1)) {
+ printf "UDP request\n";
+ $udpsock->recv($buf, 512);
+ $response = handle($buf);
+ $udpsock->send($response);
+ } elsif (vec($rout, fileno($tcpsock), 1)) {
+ my $conn = $tcpsock->accept;
+ for (;;) {
+ printf "TCP request\n";
+ my $n = $conn->sysread($lenbuf, 2);
+ last unless $n == 2;
+ my $len = unpack("n", $lenbuf);
+ $n = $conn->sysread($buf, $len);
+ last unless $n == $len;
+ $response = handle($buf);
+ $len = length($response);
+ $n = $conn->syswrite(pack("n", $len), 2);
+ $n = $conn->syswrite($response, $len);
+ }
+ $conn->close;
+ }
+}
diff --git a/bin/tests/system/ixfr/clean.sh b/bin/tests/system/ixfr/clean.sh
new file mode 100644
index 0000000..530f458
--- /dev/null
+++ b/bin/tests/system/ixfr/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# 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: clean.sh,v 1.6 2007/09/26 03:22:43 marka Exp $
+
+rm -f ns1/named.conf ns1/myftp.db
+rm -f */named.memstats
diff --git a/bin/tests/system/ixfr/prereq.sh b/bin/tests/system/ixfr/prereq.sh
new file mode 100644
index 0000000..aaf349b
--- /dev/null
+++ b/bin/tests/system/ixfr/prereq.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# 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: prereq.sh,v 1.5 2007/06/19 23:47:03 tbox Exp $
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ :
+else
+ echo "I:This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/ixfr/setup.sh b/bin/tests/system/ixfr/setup.sh
new file mode 100644
index 0000000..6e5b8e4
--- /dev/null
+++ b/bin/tests/system/ixfr/setup.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+#
+# 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: setup.sh,v 1.4 2007/06/19 23:47:03 tbox Exp $
+
+rm -f ns1/*.db ns1/*.jnl
+
+cat <<EOF >ns1/named.conf
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+EOF
diff --git a/bin/tests/system/ixfr/tests.sh b/bin/tests/system/ixfr/tests.sh
new file mode 100644
index 0000000..109f01e
--- /dev/null
+++ b/bin/tests/system/ixfr/tests.sh
@@ -0,0 +1,132 @@
+#!/bin/sh
+#
+# 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: tests.sh,v 1.5 2007/06/19 23:47:03 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd"
+DIGCMD="$DIG $DIGOPTS @10.53.0.1 -p 5300"
+SENDCMD="$PERL ../send.pl 10.53.0.2 5301"
+RNDCCMD="$RNDC -s 10.53.0.1 -p 9953 -c ../common/rndc.conf"
+
+echo "I:testing initial AXFR"
+
+$SENDCMD <<EOF
+/SOA/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+nil. 300 NS ns.nil.
+nil. 300 TXT "initial AXFR"
+a.nil. 60 A 10.0.0.61
+b.nil. 60 A 10.0.0.62
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+EOF
+
+sleep 1
+
+# Initially, ns1 is not authoritative for anything (see setup.sh).
+# Now that ans is up and running with the right data, we make it
+# a slave for nil.
+
+cat <<EOF >>ns1/named.conf
+zone "nil" {
+ type slave;
+ file "myftp.db";
+ masters { 10.53.0.2; };
+};
+EOF
+
+$RNDCCMD reload
+
+sleep 2
+
+$DIGCMD nil. TXT | grep 'initial AXFR' >/dev/null || {
+ echo "I:failed"
+ status=1
+}
+
+echo "I:testing successful IXFR"
+
+# We change the IP address of a.nil., and the TXT record at the apex.
+# Then we do a SOA-only update.
+
+$SENDCMD <<EOF
+/SOA/
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+/IXFR/
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+nil. 300 SOA ns.nil. root.nil. 1 300 300 604800 300
+a.nil. 60 A 10.0.0.61
+nil. 300 TXT "initial AXFR"
+nil. 300 SOA ns.nil. root.nil. 2 300 300 604800 300
+nil. 300 TXT "successful IXFR"
+a.nil. 60 A 10.0.1.61
+nil. 300 SOA ns.nil. root.nil. 2 300 300 604800 300
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+EOF
+
+sleep 1
+
+$RNDCCMD refresh nil
+
+sleep 2
+
+$DIGCMD nil. TXT | grep 'successful IXFR' >/dev/null || {
+ echo "I:failed"
+ status=1
+}
+
+echo "I:testing AXFR fallback after IXFR failure"
+
+# Provide a broken IXFR response and a working fallback AXFR response
+
+$SENDCMD <<EOF
+/SOA/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+/IXFR/
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+nil. 300 TXT "delete-nonexistent-txt-record"
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+nil. 300 TXT "this-txt-record-would-be-added"
+nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
+/AXFR/
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+nil. 300 NS ns.nil.
+nil. 300 TXT "fallback AXFR"
+nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
+EOF
+
+sleep 1
+
+$RNDCCMD refresh nil
+
+sleep 2
+
+$DIGCMD nil. TXT | grep 'fallback AXFR' >/dev/null || {
+ echo "I:failed"
+ status=1
+}
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/limits/clean.sh b/bin/tests/system/limits/clean.sh
new file mode 100644
index 0000000..bf22607
--- /dev/null
+++ b/bin/tests/system/limits/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.11 2007/09/26 03:22:44 marka Exp $
+
+#
+# Clean up after limits tests.
+#
+rm -f dig.out.*
+rm -f */named.memstats
diff --git a/bin/tests/system/limits/knowngood.dig.out.1000 b/bin/tests/system/limits/knowngood.dig.out.1000
new file mode 100644
index 0000000..3b7e01a
--- /dev/null
+++ b/bin/tests/system/limits/knowngood.dig.out.1000
@@ -0,0 +1,1023 @@
+
+; <<>> DiG 8.2 <<>> 1000.example. @10.53.0.1 a -p
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr aa rd ad; QUERY: 1, ANSWER: 1000, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; 1000.example, type = A, class = IN
+
+;; ANSWER SECTION:
+1000.example. 5M IN A 10.0.0.0
+1000.example. 5M IN A 10.0.0.1
+1000.example. 5M IN A 10.0.0.2
+1000.example. 5M IN A 10.0.0.3
+1000.example. 5M IN A 10.0.0.4
+1000.example. 5M IN A 10.0.0.5
+1000.example. 5M IN A 10.0.0.6
+1000.example. 5M IN A 10.0.0.7
+1000.example. 5M IN A 10.0.0.8
+1000.example. 5M IN A 10.0.0.9
+1000.example. 5M IN A 10.0.0.10
+1000.example. 5M IN A 10.0.0.11
+1000.example. 5M IN A 10.0.0.12
+1000.example. 5M IN A 10.0.0.13
+1000.example. 5M IN A 10.0.0.14
+1000.example. 5M IN A 10.0.0.15
+1000.example. 5M IN A 10.0.0.16
+1000.example. 5M IN A 10.0.0.17
+1000.example. 5M IN A 10.0.0.18
+1000.example. 5M IN A 10.0.0.19
+1000.example. 5M IN A 10.0.0.20
+1000.example. 5M IN A 10.0.0.21
+1000.example. 5M IN A 10.0.0.22
+1000.example. 5M IN A 10.0.0.23
+1000.example. 5M IN A 10.0.0.24
+1000.example. 5M IN A 10.0.0.25
+1000.example. 5M IN A 10.0.0.26
+1000.example. 5M IN A 10.0.0.27
+1000.example. 5M IN A 10.0.0.28
+1000.example. 5M IN A 10.0.0.29
+1000.example. 5M IN A 10.0.0.30
+1000.example. 5M IN A 10.0.0.31
+1000.example. 5M IN A 10.0.0.32
+1000.example. 5M IN A 10.0.0.33
+1000.example. 5M IN A 10.0.0.34
+1000.example. 5M IN A 10.0.0.35
+1000.example. 5M IN A 10.0.0.36
+1000.example. 5M IN A 10.0.0.37
+1000.example. 5M IN A 10.0.0.38
+1000.example. 5M IN A 10.0.0.39
+1000.example. 5M IN A 10.0.0.40
+1000.example. 5M IN A 10.0.0.41
+1000.example. 5M IN A 10.0.0.42
+1000.example. 5M IN A 10.0.0.43
+1000.example. 5M IN A 10.0.0.44
+1000.example. 5M IN A 10.0.0.45
+1000.example. 5M IN A 10.0.0.46
+1000.example. 5M IN A 10.0.0.47
+1000.example. 5M IN A 10.0.0.48
+1000.example. 5M IN A 10.0.0.49
+1000.example. 5M IN A 10.0.0.50
+1000.example. 5M IN A 10.0.0.51
+1000.example. 5M IN A 10.0.0.52
+1000.example. 5M IN A 10.0.0.53
+1000.example. 5M IN A 10.0.0.54
+1000.example. 5M IN A 10.0.0.55
+1000.example. 5M IN A 10.0.0.56
+1000.example. 5M IN A 10.0.0.57
+1000.example. 5M IN A 10.0.0.58
+1000.example. 5M IN A 10.0.0.59
+1000.example. 5M IN A 10.0.0.60
+1000.example. 5M IN A 10.0.0.61
+1000.example. 5M IN A 10.0.0.62
+1000.example. 5M IN A 10.0.0.63
+1000.example. 5M IN A 10.0.0.64
+1000.example. 5M IN A 10.0.0.65
+1000.example. 5M IN A 10.0.0.66
+1000.example. 5M IN A 10.0.0.67
+1000.example. 5M IN A 10.0.0.68
+1000.example. 5M IN A 10.0.0.69
+1000.example. 5M IN A 10.0.0.70
+1000.example. 5M IN A 10.0.0.71
+1000.example. 5M IN A 10.0.0.72
+1000.example. 5M IN A 10.0.0.73
+1000.example. 5M IN A 10.0.0.74
+1000.example. 5M IN A 10.0.0.75
+1000.example. 5M IN A 10.0.0.76
+1000.example. 5M IN A 10.0.0.77
+1000.example. 5M IN A 10.0.0.78
+1000.example. 5M IN A 10.0.0.79
+1000.example. 5M IN A 10.0.0.80
+1000.example. 5M IN A 10.0.0.81
+1000.example. 5M IN A 10.0.0.82
+1000.example. 5M IN A 10.0.0.83
+1000.example. 5M IN A 10.0.0.84
+1000.example. 5M IN A 10.0.0.85
+1000.example. 5M IN A 10.0.0.86
+1000.example. 5M IN A 10.0.0.87
+1000.example. 5M IN A 10.0.0.88
+1000.example. 5M IN A 10.0.0.89
+1000.example. 5M IN A 10.0.0.90
+1000.example. 5M IN A 10.0.0.91
+1000.example. 5M IN A 10.0.0.92
+1000.example. 5M IN A 10.0.0.93
+1000.example. 5M IN A 10.0.0.94
+1000.example. 5M IN A 10.0.0.95
+1000.example. 5M IN A 10.0.0.96
+1000.example. 5M IN A 10.0.0.97
+1000.example. 5M IN A 10.0.0.98
+1000.example. 5M IN A 10.0.0.99
+1000.example. 5M IN A 10.0.0.100
+1000.example. 5M IN A 10.0.0.101
+1000.example. 5M IN A 10.0.0.102
+1000.example. 5M IN A 10.0.0.103
+1000.example. 5M IN A 10.0.0.104
+1000.example. 5M IN A 10.0.0.105
+1000.example. 5M IN A 10.0.0.106
+1000.example. 5M IN A 10.0.0.107
+1000.example. 5M IN A 10.0.0.108
+1000.example. 5M IN A 10.0.0.109
+1000.example. 5M IN A 10.0.0.110
+1000.example. 5M IN A 10.0.0.111
+1000.example. 5M IN A 10.0.0.112
+1000.example. 5M IN A 10.0.0.113
+1000.example. 5M IN A 10.0.0.114
+1000.example. 5M IN A 10.0.0.115
+1000.example. 5M IN A 10.0.0.116
+1000.example. 5M IN A 10.0.0.117
+1000.example. 5M IN A 10.0.0.118
+1000.example. 5M IN A 10.0.0.119
+1000.example. 5M IN A 10.0.0.120
+1000.example. 5M IN A 10.0.0.121
+1000.example. 5M IN A 10.0.0.122
+1000.example. 5M IN A 10.0.0.123
+1000.example. 5M IN A 10.0.0.124
+1000.example. 5M IN A 10.0.0.125
+1000.example. 5M IN A 10.0.0.126
+1000.example. 5M IN A 10.0.0.127
+1000.example. 5M IN A 10.0.0.128
+1000.example. 5M IN A 10.0.0.129
+1000.example. 5M IN A 10.0.0.130
+1000.example. 5M IN A 10.0.0.131
+1000.example. 5M IN A 10.0.0.132
+1000.example. 5M IN A 10.0.0.133
+1000.example. 5M IN A 10.0.0.134
+1000.example. 5M IN A 10.0.0.135
+1000.example. 5M IN A 10.0.0.136
+1000.example. 5M IN A 10.0.0.137
+1000.example. 5M IN A 10.0.0.138
+1000.example. 5M IN A 10.0.0.139
+1000.example. 5M IN A 10.0.0.140
+1000.example. 5M IN A 10.0.0.141
+1000.example. 5M IN A 10.0.0.142
+1000.example. 5M IN A 10.0.0.143
+1000.example. 5M IN A 10.0.0.144
+1000.example. 5M IN A 10.0.0.145
+1000.example. 5M IN A 10.0.0.146
+1000.example. 5M IN A 10.0.0.147
+1000.example. 5M IN A 10.0.0.148
+1000.example. 5M IN A 10.0.0.149
+1000.example. 5M IN A 10.0.0.150
+1000.example. 5M IN A 10.0.0.151
+1000.example. 5M IN A 10.0.0.152
+1000.example. 5M IN A 10.0.0.153
+1000.example. 5M IN A 10.0.0.154
+1000.example. 5M IN A 10.0.0.155
+1000.example. 5M IN A 10.0.0.156
+1000.example. 5M IN A 10.0.0.157
+1000.example. 5M IN A 10.0.0.158
+1000.example. 5M IN A 10.0.0.159
+1000.example. 5M IN A 10.0.0.160
+1000.example. 5M IN A 10.0.0.161
+1000.example. 5M IN A 10.0.0.162
+1000.example. 5M IN A 10.0.0.163
+1000.example. 5M IN A 10.0.0.164
+1000.example. 5M IN A 10.0.0.165
+1000.example. 5M IN A 10.0.0.166
+1000.example. 5M IN A 10.0.0.167
+1000.example. 5M IN A 10.0.0.168
+1000.example. 5M IN A 10.0.0.169
+1000.example. 5M IN A 10.0.0.170
+1000.example. 5M IN A 10.0.0.171
+1000.example. 5M IN A 10.0.0.172
+1000.example. 5M IN A 10.0.0.173
+1000.example. 5M IN A 10.0.0.174
+1000.example. 5M IN A 10.0.0.175
+1000.example. 5M IN A 10.0.0.176
+1000.example. 5M IN A 10.0.0.177
+1000.example. 5M IN A 10.0.0.178
+1000.example. 5M IN A 10.0.0.179
+1000.example. 5M IN A 10.0.0.180
+1000.example. 5M IN A 10.0.0.181
+1000.example. 5M IN A 10.0.0.182
+1000.example. 5M IN A 10.0.0.183
+1000.example. 5M IN A 10.0.0.184
+1000.example. 5M IN A 10.0.0.185
+1000.example. 5M IN A 10.0.0.186
+1000.example. 5M IN A 10.0.0.187
+1000.example. 5M IN A 10.0.0.188
+1000.example. 5M IN A 10.0.0.189
+1000.example. 5M IN A 10.0.0.190
+1000.example. 5M IN A 10.0.0.191
+1000.example. 5M IN A 10.0.0.192
+1000.example. 5M IN A 10.0.0.193
+1000.example. 5M IN A 10.0.0.194
+1000.example. 5M IN A 10.0.0.195
+1000.example. 5M IN A 10.0.0.196
+1000.example. 5M IN A 10.0.0.197
+1000.example. 5M IN A 10.0.0.198
+1000.example. 5M IN A 10.0.0.199
+1000.example. 5M IN A 10.0.0.200
+1000.example. 5M IN A 10.0.0.201
+1000.example. 5M IN A 10.0.0.202
+1000.example. 5M IN A 10.0.0.203
+1000.example. 5M IN A 10.0.0.204
+1000.example. 5M IN A 10.0.0.205
+1000.example. 5M IN A 10.0.0.206
+1000.example. 5M IN A 10.0.0.207
+1000.example. 5M IN A 10.0.0.208
+1000.example. 5M IN A 10.0.0.209
+1000.example. 5M IN A 10.0.0.210
+1000.example. 5M IN A 10.0.0.211
+1000.example. 5M IN A 10.0.0.212
+1000.example. 5M IN A 10.0.0.213
+1000.example. 5M IN A 10.0.0.214
+1000.example. 5M IN A 10.0.0.215
+1000.example. 5M IN A 10.0.0.216
+1000.example. 5M IN A 10.0.0.217
+1000.example. 5M IN A 10.0.0.218
+1000.example. 5M IN A 10.0.0.219
+1000.example. 5M IN A 10.0.0.220
+1000.example. 5M IN A 10.0.0.221
+1000.example. 5M IN A 10.0.0.222
+1000.example. 5M IN A 10.0.0.223
+1000.example. 5M IN A 10.0.0.224
+1000.example. 5M IN A 10.0.0.225
+1000.example. 5M IN A 10.0.0.226
+1000.example. 5M IN A 10.0.0.227
+1000.example. 5M IN A 10.0.0.228
+1000.example. 5M IN A 10.0.0.229
+1000.example. 5M IN A 10.0.0.230
+1000.example. 5M IN A 10.0.0.231
+1000.example. 5M IN A 10.0.0.232
+1000.example. 5M IN A 10.0.0.233
+1000.example. 5M IN A 10.0.0.234
+1000.example. 5M IN A 10.0.0.235
+1000.example. 5M IN A 10.0.0.236
+1000.example. 5M IN A 10.0.0.237
+1000.example. 5M IN A 10.0.0.238
+1000.example. 5M IN A 10.0.0.239
+1000.example. 5M IN A 10.0.0.240
+1000.example. 5M IN A 10.0.0.241
+1000.example. 5M IN A 10.0.0.242
+1000.example. 5M IN A 10.0.0.243
+1000.example. 5M IN A 10.0.0.244
+1000.example. 5M IN A 10.0.0.245
+1000.example. 5M IN A 10.0.0.246
+1000.example. 5M IN A 10.0.0.247
+1000.example. 5M IN A 10.0.0.248
+1000.example. 5M IN A 10.0.0.249
+1000.example. 5M IN A 10.0.0.250
+1000.example. 5M IN A 10.0.0.251
+1000.example. 5M IN A 10.0.0.252
+1000.example. 5M IN A 10.0.0.253
+1000.example. 5M IN A 10.0.0.254
+1000.example. 5M IN A 10.0.0.255
+1000.example. 5M IN A 10.0.1.0
+1000.example. 5M IN A 10.0.1.1
+1000.example. 5M IN A 10.0.1.2
+1000.example. 5M IN A 10.0.1.3
+1000.example. 5M IN A 10.0.1.4
+1000.example. 5M IN A 10.0.1.5
+1000.example. 5M IN A 10.0.1.6
+1000.example. 5M IN A 10.0.1.7
+1000.example. 5M IN A 10.0.1.8
+1000.example. 5M IN A 10.0.1.9
+1000.example. 5M IN A 10.0.1.10
+1000.example. 5M IN A 10.0.1.11
+1000.example. 5M IN A 10.0.1.12
+1000.example. 5M IN A 10.0.1.13
+1000.example. 5M IN A 10.0.1.14
+1000.example. 5M IN A 10.0.1.15
+1000.example. 5M IN A 10.0.1.16
+1000.example. 5M IN A 10.0.1.17
+1000.example. 5M IN A 10.0.1.18
+1000.example. 5M IN A 10.0.1.19
+1000.example. 5M IN A 10.0.1.20
+1000.example. 5M IN A 10.0.1.21
+1000.example. 5M IN A 10.0.1.22
+1000.example. 5M IN A 10.0.1.23
+1000.example. 5M IN A 10.0.1.24
+1000.example. 5M IN A 10.0.1.25
+1000.example. 5M IN A 10.0.1.26
+1000.example. 5M IN A 10.0.1.27
+1000.example. 5M IN A 10.0.1.28
+1000.example. 5M IN A 10.0.1.29
+1000.example. 5M IN A 10.0.1.30
+1000.example. 5M IN A 10.0.1.31
+1000.example. 5M IN A 10.0.1.32
+1000.example. 5M IN A 10.0.1.33
+1000.example. 5M IN A 10.0.1.34
+1000.example. 5M IN A 10.0.1.35
+1000.example. 5M IN A 10.0.1.36
+1000.example. 5M IN A 10.0.1.37
+1000.example. 5M IN A 10.0.1.38
+1000.example. 5M IN A 10.0.1.39
+1000.example. 5M IN A 10.0.1.40
+1000.example. 5M IN A 10.0.1.41
+1000.example. 5M IN A 10.0.1.42
+1000.example. 5M IN A 10.0.1.43
+1000.example. 5M IN A 10.0.1.44
+1000.example. 5M IN A 10.0.1.45
+1000.example. 5M IN A 10.0.1.46
+1000.example. 5M IN A 10.0.1.47
+1000.example. 5M IN A 10.0.1.48
+1000.example. 5M IN A 10.0.1.49
+1000.example. 5M IN A 10.0.1.50
+1000.example. 5M IN A 10.0.1.51
+1000.example. 5M IN A 10.0.1.52
+1000.example. 5M IN A 10.0.1.53
+1000.example. 5M IN A 10.0.1.54
+1000.example. 5M IN A 10.0.1.55
+1000.example. 5M IN A 10.0.1.56
+1000.example. 5M IN A 10.0.1.57
+1000.example. 5M IN A 10.0.1.58
+1000.example. 5M IN A 10.0.1.59
+1000.example. 5M IN A 10.0.1.60
+1000.example. 5M IN A 10.0.1.61
+1000.example. 5M IN A 10.0.1.62
+1000.example. 5M IN A 10.0.1.63
+1000.example. 5M IN A 10.0.1.64
+1000.example. 5M IN A 10.0.1.65
+1000.example. 5M IN A 10.0.1.66
+1000.example. 5M IN A 10.0.1.67
+1000.example. 5M IN A 10.0.1.68
+1000.example. 5M IN A 10.0.1.69
+1000.example. 5M IN A 10.0.1.70
+1000.example. 5M IN A 10.0.1.71
+1000.example. 5M IN A 10.0.1.72
+1000.example. 5M IN A 10.0.1.73
+1000.example. 5M IN A 10.0.1.74
+1000.example. 5M IN A 10.0.1.75
+1000.example. 5M IN A 10.0.1.76
+1000.example. 5M IN A 10.0.1.77
+1000.example. 5M IN A 10.0.1.78
+1000.example. 5M IN A 10.0.1.79
+1000.example. 5M IN A 10.0.1.80
+1000.example. 5M IN A 10.0.1.81
+1000.example. 5M IN A 10.0.1.82
+1000.example. 5M IN A 10.0.1.83
+1000.example. 5M IN A 10.0.1.84
+1000.example. 5M IN A 10.0.1.85
+1000.example. 5M IN A 10.0.1.86
+1000.example. 5M IN A 10.0.1.87
+1000.example. 5M IN A 10.0.1.88
+1000.example. 5M IN A 10.0.1.89
+1000.example. 5M IN A 10.0.1.90
+1000.example. 5M IN A 10.0.1.91
+1000.example. 5M IN A 10.0.1.92
+1000.example. 5M IN A 10.0.1.93
+1000.example. 5M IN A 10.0.1.94
+1000.example. 5M IN A 10.0.1.95
+1000.example. 5M IN A 10.0.1.96
+1000.example. 5M IN A 10.0.1.97
+1000.example. 5M IN A 10.0.1.98
+1000.example. 5M IN A 10.0.1.99
+1000.example. 5M IN A 10.0.1.100
+1000.example. 5M IN A 10.0.1.101
+1000.example. 5M IN A 10.0.1.102
+1000.example. 5M IN A 10.0.1.103
+1000.example. 5M IN A 10.0.1.104
+1000.example. 5M IN A 10.0.1.105
+1000.example. 5M IN A 10.0.1.106
+1000.example. 5M IN A 10.0.1.107
+1000.example. 5M IN A 10.0.1.108
+1000.example. 5M IN A 10.0.1.109
+1000.example. 5M IN A 10.0.1.110
+1000.example. 5M IN A 10.0.1.111
+1000.example. 5M IN A 10.0.1.112
+1000.example. 5M IN A 10.0.1.113
+1000.example. 5M IN A 10.0.1.114
+1000.example. 5M IN A 10.0.1.115
+1000.example. 5M IN A 10.0.1.116
+1000.example. 5M IN A 10.0.1.117
+1000.example. 5M IN A 10.0.1.118
+1000.example. 5M IN A 10.0.1.119
+1000.example. 5M IN A 10.0.1.120
+1000.example. 5M IN A 10.0.1.121
+1000.example. 5M IN A 10.0.1.122
+1000.example. 5M IN A 10.0.1.123
+1000.example. 5M IN A 10.0.1.124
+1000.example. 5M IN A 10.0.1.125
+1000.example. 5M IN A 10.0.1.126
+1000.example. 5M IN A 10.0.1.127
+1000.example. 5M IN A 10.0.1.128
+1000.example. 5M IN A 10.0.1.129
+1000.example. 5M IN A 10.0.1.130
+1000.example. 5M IN A 10.0.1.131
+1000.example. 5M IN A 10.0.1.132
+1000.example. 5M IN A 10.0.1.133
+1000.example. 5M IN A 10.0.1.134
+1000.example. 5M IN A 10.0.1.135
+1000.example. 5M IN A 10.0.1.136
+1000.example. 5M IN A 10.0.1.137
+1000.example. 5M IN A 10.0.1.138
+1000.example. 5M IN A 10.0.1.139
+1000.example. 5M IN A 10.0.1.140
+1000.example. 5M IN A 10.0.1.141
+1000.example. 5M IN A 10.0.1.142
+1000.example. 5M IN A 10.0.1.143
+1000.example. 5M IN A 10.0.1.144
+1000.example. 5M IN A 10.0.1.145
+1000.example. 5M IN A 10.0.1.146
+1000.example. 5M IN A 10.0.1.147
+1000.example. 5M IN A 10.0.1.148
+1000.example. 5M IN A 10.0.1.149
+1000.example. 5M IN A 10.0.1.150
+1000.example. 5M IN A 10.0.1.151
+1000.example. 5M IN A 10.0.1.152
+1000.example. 5M IN A 10.0.1.153
+1000.example. 5M IN A 10.0.1.154
+1000.example. 5M IN A 10.0.1.155
+1000.example. 5M IN A 10.0.1.156
+1000.example. 5M IN A 10.0.1.157
+1000.example. 5M IN A 10.0.1.158
+1000.example. 5M IN A 10.0.1.159
+1000.example. 5M IN A 10.0.1.160
+1000.example. 5M IN A 10.0.1.161
+1000.example. 5M IN A 10.0.1.162
+1000.example. 5M IN A 10.0.1.163
+1000.example. 5M IN A 10.0.1.164
+1000.example. 5M IN A 10.0.1.165
+1000.example. 5M IN A 10.0.1.166
+1000.example. 5M IN A 10.0.1.167
+1000.example. 5M IN A 10.0.1.168
+1000.example. 5M IN A 10.0.1.169
+1000.example. 5M IN A 10.0.1.170
+1000.example. 5M IN A 10.0.1.171
+1000.example. 5M IN A 10.0.1.172
+1000.example. 5M IN A 10.0.1.173
+1000.example. 5M IN A 10.0.1.174
+1000.example. 5M IN A 10.0.1.175
+1000.example. 5M IN A 10.0.1.176
+1000.example. 5M IN A 10.0.1.177
+1000.example. 5M IN A 10.0.1.178
+1000.example. 5M IN A 10.0.1.179
+1000.example. 5M IN A 10.0.1.180
+1000.example. 5M IN A 10.0.1.181
+1000.example. 5M IN A 10.0.1.182
+1000.example. 5M IN A 10.0.1.183
+1000.example. 5M IN A 10.0.1.184
+1000.example. 5M IN A 10.0.1.185
+1000.example. 5M IN A 10.0.1.186
+1000.example. 5M IN A 10.0.1.187
+1000.example. 5M IN A 10.0.1.188
+1000.example. 5M IN A 10.0.1.189
+1000.example. 5M IN A 10.0.1.190
+1000.example. 5M IN A 10.0.1.191
+1000.example. 5M IN A 10.0.1.192
+1000.example. 5M IN A 10.0.1.193
+1000.example. 5M IN A 10.0.1.194
+1000.example. 5M IN A 10.0.1.195
+1000.example. 5M IN A 10.0.1.196
+1000.example. 5M IN A 10.0.1.197
+1000.example. 5M IN A 10.0.1.198
+1000.example. 5M IN A 10.0.1.199
+1000.example. 5M IN A 10.0.1.200
+1000.example. 5M IN A 10.0.1.201
+1000.example. 5M IN A 10.0.1.202
+1000.example. 5M IN A 10.0.1.203
+1000.example. 5M IN A 10.0.1.204
+1000.example. 5M IN A 10.0.1.205
+1000.example. 5M IN A 10.0.1.206
+1000.example. 5M IN A 10.0.1.207
+1000.example. 5M IN A 10.0.1.208
+1000.example. 5M IN A 10.0.1.209
+1000.example. 5M IN A 10.0.1.210
+1000.example. 5M IN A 10.0.1.211
+1000.example. 5M IN A 10.0.1.212
+1000.example. 5M IN A 10.0.1.213
+1000.example. 5M IN A 10.0.1.214
+1000.example. 5M IN A 10.0.1.215
+1000.example. 5M IN A 10.0.1.216
+1000.example. 5M IN A 10.0.1.217
+1000.example. 5M IN A 10.0.1.218
+1000.example. 5M IN A 10.0.1.219
+1000.example. 5M IN A 10.0.1.220
+1000.example. 5M IN A 10.0.1.221
+1000.example. 5M IN A 10.0.1.222
+1000.example. 5M IN A 10.0.1.223
+1000.example. 5M IN A 10.0.1.224
+1000.example. 5M IN A 10.0.1.225
+1000.example. 5M IN A 10.0.1.226
+1000.example. 5M IN A 10.0.1.227
+1000.example. 5M IN A 10.0.1.228
+1000.example. 5M IN A 10.0.1.229
+1000.example. 5M IN A 10.0.1.230
+1000.example. 5M IN A 10.0.1.231
+1000.example. 5M IN A 10.0.1.232
+1000.example. 5M IN A 10.0.1.233
+1000.example. 5M IN A 10.0.1.234
+1000.example. 5M IN A 10.0.1.235
+1000.example. 5M IN A 10.0.1.236
+1000.example. 5M IN A 10.0.1.237
+1000.example. 5M IN A 10.0.1.238
+1000.example. 5M IN A 10.0.1.239
+1000.example. 5M IN A 10.0.1.240
+1000.example. 5M IN A 10.0.1.241
+1000.example. 5M IN A 10.0.1.242
+1000.example. 5M IN A 10.0.1.243
+1000.example. 5M IN A 10.0.1.244
+1000.example. 5M IN A 10.0.1.245
+1000.example. 5M IN A 10.0.1.246
+1000.example. 5M IN A 10.0.1.247
+1000.example. 5M IN A 10.0.1.248
+1000.example. 5M IN A 10.0.1.249
+1000.example. 5M IN A 10.0.1.250
+1000.example. 5M IN A 10.0.1.251
+1000.example. 5M IN A 10.0.1.252
+1000.example. 5M IN A 10.0.1.253
+1000.example. 5M IN A 10.0.1.254
+1000.example. 5M IN A 10.0.1.255
+1000.example. 5M IN A 10.0.2.0
+1000.example. 5M IN A 10.0.2.1
+1000.example. 5M IN A 10.0.2.2
+1000.example. 5M IN A 10.0.2.3
+1000.example. 5M IN A 10.0.2.4
+1000.example. 5M IN A 10.0.2.5
+1000.example. 5M IN A 10.0.2.6
+1000.example. 5M IN A 10.0.2.7
+1000.example. 5M IN A 10.0.2.8
+1000.example. 5M IN A 10.0.2.9
+1000.example. 5M IN A 10.0.2.10
+1000.example. 5M IN A 10.0.2.11
+1000.example. 5M IN A 10.0.2.12
+1000.example. 5M IN A 10.0.2.13
+1000.example. 5M IN A 10.0.2.14
+1000.example. 5M IN A 10.0.2.15
+1000.example. 5M IN A 10.0.2.16
+1000.example. 5M IN A 10.0.2.17
+1000.example. 5M IN A 10.0.2.18
+1000.example. 5M IN A 10.0.2.19
+1000.example. 5M IN A 10.0.2.20
+1000.example. 5M IN A 10.0.2.21
+1000.example. 5M IN A 10.0.2.22
+1000.example. 5M IN A 10.0.2.23
+1000.example. 5M IN A 10.0.2.24
+1000.example. 5M IN A 10.0.2.25
+1000.example. 5M IN A 10.0.2.26
+1000.example. 5M IN A 10.0.2.27
+1000.example. 5M IN A 10.0.2.28
+1000.example. 5M IN A 10.0.2.29
+1000.example. 5M IN A 10.0.2.30
+1000.example. 5M IN A 10.0.2.31
+1000.example. 5M IN A 10.0.2.32
+1000.example. 5M IN A 10.0.2.33
+1000.example. 5M IN A 10.0.2.34
+1000.example. 5M IN A 10.0.2.35
+1000.example. 5M IN A 10.0.2.36
+1000.example. 5M IN A 10.0.2.37
+1000.example. 5M IN A 10.0.2.38
+1000.example. 5M IN A 10.0.2.39
+1000.example. 5M IN A 10.0.2.40
+1000.example. 5M IN A 10.0.2.41
+1000.example. 5M IN A 10.0.2.42
+1000.example. 5M IN A 10.0.2.43
+1000.example. 5M IN A 10.0.2.44
+1000.example. 5M IN A 10.0.2.45
+1000.example. 5M IN A 10.0.2.46
+1000.example. 5M IN A 10.0.2.47
+1000.example. 5M IN A 10.0.2.48
+1000.example. 5M IN A 10.0.2.49
+1000.example. 5M IN A 10.0.2.50
+1000.example. 5M IN A 10.0.2.51
+1000.example. 5M IN A 10.0.2.52
+1000.example. 5M IN A 10.0.2.53
+1000.example. 5M IN A 10.0.2.54
+1000.example. 5M IN A 10.0.2.55
+1000.example. 5M IN A 10.0.2.56
+1000.example. 5M IN A 10.0.2.57
+1000.example. 5M IN A 10.0.2.58
+1000.example. 5M IN A 10.0.2.59
+1000.example. 5M IN A 10.0.2.60
+1000.example. 5M IN A 10.0.2.61
+1000.example. 5M IN A 10.0.2.62
+1000.example. 5M IN A 10.0.2.63
+1000.example. 5M IN A 10.0.2.64
+1000.example. 5M IN A 10.0.2.65
+1000.example. 5M IN A 10.0.2.66
+1000.example. 5M IN A 10.0.2.67
+1000.example. 5M IN A 10.0.2.68
+1000.example. 5M IN A 10.0.2.69
+1000.example. 5M IN A 10.0.2.70
+1000.example. 5M IN A 10.0.2.71
+1000.example. 5M IN A 10.0.2.72
+1000.example. 5M IN A 10.0.2.73
+1000.example. 5M IN A 10.0.2.74
+1000.example. 5M IN A 10.0.2.75
+1000.example. 5M IN A 10.0.2.76
+1000.example. 5M IN A 10.0.2.77
+1000.example. 5M IN A 10.0.2.78
+1000.example. 5M IN A 10.0.2.79
+1000.example. 5M IN A 10.0.2.80
+1000.example. 5M IN A 10.0.2.81
+1000.example. 5M IN A 10.0.2.82
+1000.example. 5M IN A 10.0.2.83
+1000.example. 5M IN A 10.0.2.84
+1000.example. 5M IN A 10.0.2.85
+1000.example. 5M IN A 10.0.2.86
+1000.example. 5M IN A 10.0.2.87
+1000.example. 5M IN A 10.0.2.88
+1000.example. 5M IN A 10.0.2.89
+1000.example. 5M IN A 10.0.2.90
+1000.example. 5M IN A 10.0.2.91
+1000.example. 5M IN A 10.0.2.92
+1000.example. 5M IN A 10.0.2.93
+1000.example. 5M IN A 10.0.2.94
+1000.example. 5M IN A 10.0.2.95
+1000.example. 5M IN A 10.0.2.96
+1000.example. 5M IN A 10.0.2.97
+1000.example. 5M IN A 10.0.2.98
+1000.example. 5M IN A 10.0.2.99
+1000.example. 5M IN A 10.0.2.100
+1000.example. 5M IN A 10.0.2.101
+1000.example. 5M IN A 10.0.2.102
+1000.example. 5M IN A 10.0.2.103
+1000.example. 5M IN A 10.0.2.104
+1000.example. 5M IN A 10.0.2.105
+1000.example. 5M IN A 10.0.2.106
+1000.example. 5M IN A 10.0.2.107
+1000.example. 5M IN A 10.0.2.108
+1000.example. 5M IN A 10.0.2.109
+1000.example. 5M IN A 10.0.2.110
+1000.example. 5M IN A 10.0.2.111
+1000.example. 5M IN A 10.0.2.112
+1000.example. 5M IN A 10.0.2.113
+1000.example. 5M IN A 10.0.2.114
+1000.example. 5M IN A 10.0.2.115
+1000.example. 5M IN A 10.0.2.116
+1000.example. 5M IN A 10.0.2.117
+1000.example. 5M IN A 10.0.2.118
+1000.example. 5M IN A 10.0.2.119
+1000.example. 5M IN A 10.0.2.120
+1000.example. 5M IN A 10.0.2.121
+1000.example. 5M IN A 10.0.2.122
+1000.example. 5M IN A 10.0.2.123
+1000.example. 5M IN A 10.0.2.124
+1000.example. 5M IN A 10.0.2.125
+1000.example. 5M IN A 10.0.2.126
+1000.example. 5M IN A 10.0.2.127
+1000.example. 5M IN A 10.0.2.128
+1000.example. 5M IN A 10.0.2.129
+1000.example. 5M IN A 10.0.2.130
+1000.example. 5M IN A 10.0.2.131
+1000.example. 5M IN A 10.0.2.132
+1000.example. 5M IN A 10.0.2.133
+1000.example. 5M IN A 10.0.2.134
+1000.example. 5M IN A 10.0.2.135
+1000.example. 5M IN A 10.0.2.136
+1000.example. 5M IN A 10.0.2.137
+1000.example. 5M IN A 10.0.2.138
+1000.example. 5M IN A 10.0.2.139
+1000.example. 5M IN A 10.0.2.140
+1000.example. 5M IN A 10.0.2.141
+1000.example. 5M IN A 10.0.2.142
+1000.example. 5M IN A 10.0.2.143
+1000.example. 5M IN A 10.0.2.144
+1000.example. 5M IN A 10.0.2.145
+1000.example. 5M IN A 10.0.2.146
+1000.example. 5M IN A 10.0.2.147
+1000.example. 5M IN A 10.0.2.148
+1000.example. 5M IN A 10.0.2.149
+1000.example. 5M IN A 10.0.2.150
+1000.example. 5M IN A 10.0.2.151
+1000.example. 5M IN A 10.0.2.152
+1000.example. 5M IN A 10.0.2.153
+1000.example. 5M IN A 10.0.2.154
+1000.example. 5M IN A 10.0.2.155
+1000.example. 5M IN A 10.0.2.156
+1000.example. 5M IN A 10.0.2.157
+1000.example. 5M IN A 10.0.2.158
+1000.example. 5M IN A 10.0.2.159
+1000.example. 5M IN A 10.0.2.160
+1000.example. 5M IN A 10.0.2.161
+1000.example. 5M IN A 10.0.2.162
+1000.example. 5M IN A 10.0.2.163
+1000.example. 5M IN A 10.0.2.164
+1000.example. 5M IN A 10.0.2.165
+1000.example. 5M IN A 10.0.2.166
+1000.example. 5M IN A 10.0.2.167
+1000.example. 5M IN A 10.0.2.168
+1000.example. 5M IN A 10.0.2.169
+1000.example. 5M IN A 10.0.2.170
+1000.example. 5M IN A 10.0.2.171
+1000.example. 5M IN A 10.0.2.172
+1000.example. 5M IN A 10.0.2.173
+1000.example. 5M IN A 10.0.2.174
+1000.example. 5M IN A 10.0.2.175
+1000.example. 5M IN A 10.0.2.176
+1000.example. 5M IN A 10.0.2.177
+1000.example. 5M IN A 10.0.2.178
+1000.example. 5M IN A 10.0.2.179
+1000.example. 5M IN A 10.0.2.180
+1000.example. 5M IN A 10.0.2.181
+1000.example. 5M IN A 10.0.2.182
+1000.example. 5M IN A 10.0.2.183
+1000.example. 5M IN A 10.0.2.184
+1000.example. 5M IN A 10.0.2.185
+1000.example. 5M IN A 10.0.2.186
+1000.example. 5M IN A 10.0.2.187
+1000.example. 5M IN A 10.0.2.188
+1000.example. 5M IN A 10.0.2.189
+1000.example. 5M IN A 10.0.2.190
+1000.example. 5M IN A 10.0.2.191
+1000.example. 5M IN A 10.0.2.192
+1000.example. 5M IN A 10.0.2.193
+1000.example. 5M IN A 10.0.2.194
+1000.example. 5M IN A 10.0.2.195
+1000.example. 5M IN A 10.0.2.196
+1000.example. 5M IN A 10.0.2.197
+1000.example. 5M IN A 10.0.2.198
+1000.example. 5M IN A 10.0.2.199
+1000.example. 5M IN A 10.0.2.200
+1000.example. 5M IN A 10.0.2.201
+1000.example. 5M IN A 10.0.2.202
+1000.example. 5M IN A 10.0.2.203
+1000.example. 5M IN A 10.0.2.204
+1000.example. 5M IN A 10.0.2.205
+1000.example. 5M IN A 10.0.2.206
+1000.example. 5M IN A 10.0.2.207
+1000.example. 5M IN A 10.0.2.208
+1000.example. 5M IN A 10.0.2.209
+1000.example. 5M IN A 10.0.2.210
+1000.example. 5M IN A 10.0.2.211
+1000.example. 5M IN A 10.0.2.212
+1000.example. 5M IN A 10.0.2.213
+1000.example. 5M IN A 10.0.2.214
+1000.example. 5M IN A 10.0.2.215
+1000.example. 5M IN A 10.0.2.216
+1000.example. 5M IN A 10.0.2.217
+1000.example. 5M IN A 10.0.2.218
+1000.example. 5M IN A 10.0.2.219
+1000.example. 5M IN A 10.0.2.220
+1000.example. 5M IN A 10.0.2.221
+1000.example. 5M IN A 10.0.2.222
+1000.example. 5M IN A 10.0.2.223
+1000.example. 5M IN A 10.0.2.224
+1000.example. 5M IN A 10.0.2.225
+1000.example. 5M IN A 10.0.2.226
+1000.example. 5M IN A 10.0.2.227
+1000.example. 5M IN A 10.0.2.228
+1000.example. 5M IN A 10.0.2.229
+1000.example. 5M IN A 10.0.2.230
+1000.example. 5M IN A 10.0.2.231
+1000.example. 5M IN A 10.0.2.232
+1000.example. 5M IN A 10.0.2.233
+1000.example. 5M IN A 10.0.2.234
+1000.example. 5M IN A 10.0.2.235
+1000.example. 5M IN A 10.0.2.236
+1000.example. 5M IN A 10.0.2.237
+1000.example. 5M IN A 10.0.2.238
+1000.example. 5M IN A 10.0.2.239
+1000.example. 5M IN A 10.0.2.240
+1000.example. 5M IN A 10.0.2.241
+1000.example. 5M IN A 10.0.2.242
+1000.example. 5M IN A 10.0.2.243
+1000.example. 5M IN A 10.0.2.244
+1000.example. 5M IN A 10.0.2.245
+1000.example. 5M IN A 10.0.2.246
+1000.example. 5M IN A 10.0.2.247
+1000.example. 5M IN A 10.0.2.248
+1000.example. 5M IN A 10.0.2.249
+1000.example. 5M IN A 10.0.2.250
+1000.example. 5M IN A 10.0.2.251
+1000.example. 5M IN A 10.0.2.252
+1000.example. 5M IN A 10.0.2.253
+1000.example. 5M IN A 10.0.2.254
+1000.example. 5M IN A 10.0.2.255
+1000.example. 5M IN A 10.0.3.0
+1000.example. 5M IN A 10.0.3.1
+1000.example. 5M IN A 10.0.3.2
+1000.example. 5M IN A 10.0.3.3
+1000.example. 5M IN A 10.0.3.4
+1000.example. 5M IN A 10.0.3.5
+1000.example. 5M IN A 10.0.3.6
+1000.example. 5M IN A 10.0.3.7
+1000.example. 5M IN A 10.0.3.8
+1000.example. 5M IN A 10.0.3.9
+1000.example. 5M IN A 10.0.3.10
+1000.example. 5M IN A 10.0.3.11
+1000.example. 5M IN A 10.0.3.12
+1000.example. 5M IN A 10.0.3.13
+1000.example. 5M IN A 10.0.3.14
+1000.example. 5M IN A 10.0.3.15
+1000.example. 5M IN A 10.0.3.16
+1000.example. 5M IN A 10.0.3.17
+1000.example. 5M IN A 10.0.3.18
+1000.example. 5M IN A 10.0.3.19
+1000.example. 5M IN A 10.0.3.20
+1000.example. 5M IN A 10.0.3.21
+1000.example. 5M IN A 10.0.3.22
+1000.example. 5M IN A 10.0.3.23
+1000.example. 5M IN A 10.0.3.24
+1000.example. 5M IN A 10.0.3.25
+1000.example. 5M IN A 10.0.3.26
+1000.example. 5M IN A 10.0.3.27
+1000.example. 5M IN A 10.0.3.28
+1000.example. 5M IN A 10.0.3.29
+1000.example. 5M IN A 10.0.3.30
+1000.example. 5M IN A 10.0.3.31
+1000.example. 5M IN A 10.0.3.32
+1000.example. 5M IN A 10.0.3.33
+1000.example. 5M IN A 10.0.3.34
+1000.example. 5M IN A 10.0.3.35
+1000.example. 5M IN A 10.0.3.36
+1000.example. 5M IN A 10.0.3.37
+1000.example. 5M IN A 10.0.3.38
+1000.example. 5M IN A 10.0.3.39
+1000.example. 5M IN A 10.0.3.40
+1000.example. 5M IN A 10.0.3.41
+1000.example. 5M IN A 10.0.3.42
+1000.example. 5M IN A 10.0.3.43
+1000.example. 5M IN A 10.0.3.44
+1000.example. 5M IN A 10.0.3.45
+1000.example. 5M IN A 10.0.3.46
+1000.example. 5M IN A 10.0.3.47
+1000.example. 5M IN A 10.0.3.48
+1000.example. 5M IN A 10.0.3.49
+1000.example. 5M IN A 10.0.3.50
+1000.example. 5M IN A 10.0.3.51
+1000.example. 5M IN A 10.0.3.52
+1000.example. 5M IN A 10.0.3.53
+1000.example. 5M IN A 10.0.3.54
+1000.example. 5M IN A 10.0.3.55
+1000.example. 5M IN A 10.0.3.56
+1000.example. 5M IN A 10.0.3.57
+1000.example. 5M IN A 10.0.3.58
+1000.example. 5M IN A 10.0.3.59
+1000.example. 5M IN A 10.0.3.60
+1000.example. 5M IN A 10.0.3.61
+1000.example. 5M IN A 10.0.3.62
+1000.example. 5M IN A 10.0.3.63
+1000.example. 5M IN A 10.0.3.64
+1000.example. 5M IN A 10.0.3.65
+1000.example. 5M IN A 10.0.3.66
+1000.example. 5M IN A 10.0.3.67
+1000.example. 5M IN A 10.0.3.68
+1000.example. 5M IN A 10.0.3.69
+1000.example. 5M IN A 10.0.3.70
+1000.example. 5M IN A 10.0.3.71
+1000.example. 5M IN A 10.0.3.72
+1000.example. 5M IN A 10.0.3.73
+1000.example. 5M IN A 10.0.3.74
+1000.example. 5M IN A 10.0.3.75
+1000.example. 5M IN A 10.0.3.76
+1000.example. 5M IN A 10.0.3.77
+1000.example. 5M IN A 10.0.3.78
+1000.example. 5M IN A 10.0.3.79
+1000.example. 5M IN A 10.0.3.80
+1000.example. 5M IN A 10.0.3.81
+1000.example. 5M IN A 10.0.3.82
+1000.example. 5M IN A 10.0.3.83
+1000.example. 5M IN A 10.0.3.84
+1000.example. 5M IN A 10.0.3.85
+1000.example. 5M IN A 10.0.3.86
+1000.example. 5M IN A 10.0.3.87
+1000.example. 5M IN A 10.0.3.88
+1000.example. 5M IN A 10.0.3.89
+1000.example. 5M IN A 10.0.3.90
+1000.example. 5M IN A 10.0.3.91
+1000.example. 5M IN A 10.0.3.92
+1000.example. 5M IN A 10.0.3.93
+1000.example. 5M IN A 10.0.3.94
+1000.example. 5M IN A 10.0.3.95
+1000.example. 5M IN A 10.0.3.96
+1000.example. 5M IN A 10.0.3.97
+1000.example. 5M IN A 10.0.3.98
+1000.example. 5M IN A 10.0.3.99
+1000.example. 5M IN A 10.0.3.100
+1000.example. 5M IN A 10.0.3.101
+1000.example. 5M IN A 10.0.3.102
+1000.example. 5M IN A 10.0.3.103
+1000.example. 5M IN A 10.0.3.104
+1000.example. 5M IN A 10.0.3.105
+1000.example. 5M IN A 10.0.3.106
+1000.example. 5M IN A 10.0.3.107
+1000.example. 5M IN A 10.0.3.108
+1000.example. 5M IN A 10.0.3.109
+1000.example. 5M IN A 10.0.3.110
+1000.example. 5M IN A 10.0.3.111
+1000.example. 5M IN A 10.0.3.112
+1000.example. 5M IN A 10.0.3.113
+1000.example. 5M IN A 10.0.3.114
+1000.example. 5M IN A 10.0.3.115
+1000.example. 5M IN A 10.0.3.116
+1000.example. 5M IN A 10.0.3.117
+1000.example. 5M IN A 10.0.3.118
+1000.example. 5M IN A 10.0.3.119
+1000.example. 5M IN A 10.0.3.120
+1000.example. 5M IN A 10.0.3.121
+1000.example. 5M IN A 10.0.3.122
+1000.example. 5M IN A 10.0.3.123
+1000.example. 5M IN A 10.0.3.124
+1000.example. 5M IN A 10.0.3.125
+1000.example. 5M IN A 10.0.3.126
+1000.example. 5M IN A 10.0.3.127
+1000.example. 5M IN A 10.0.3.128
+1000.example. 5M IN A 10.0.3.129
+1000.example. 5M IN A 10.0.3.130
+1000.example. 5M IN A 10.0.3.131
+1000.example. 5M IN A 10.0.3.132
+1000.example. 5M IN A 10.0.3.133
+1000.example. 5M IN A 10.0.3.134
+1000.example. 5M IN A 10.0.3.135
+1000.example. 5M IN A 10.0.3.136
+1000.example. 5M IN A 10.0.3.137
+1000.example. 5M IN A 10.0.3.138
+1000.example. 5M IN A 10.0.3.139
+1000.example. 5M IN A 10.0.3.140
+1000.example. 5M IN A 10.0.3.141
+1000.example. 5M IN A 10.0.3.142
+1000.example. 5M IN A 10.0.3.143
+1000.example. 5M IN A 10.0.3.144
+1000.example. 5M IN A 10.0.3.145
+1000.example. 5M IN A 10.0.3.146
+1000.example. 5M IN A 10.0.3.147
+1000.example. 5M IN A 10.0.3.148
+1000.example. 5M IN A 10.0.3.149
+1000.example. 5M IN A 10.0.3.150
+1000.example. 5M IN A 10.0.3.151
+1000.example. 5M IN A 10.0.3.152
+1000.example. 5M IN A 10.0.3.153
+1000.example. 5M IN A 10.0.3.154
+1000.example. 5M IN A 10.0.3.155
+1000.example. 5M IN A 10.0.3.156
+1000.example. 5M IN A 10.0.3.157
+1000.example. 5M IN A 10.0.3.158
+1000.example. 5M IN A 10.0.3.159
+1000.example. 5M IN A 10.0.3.160
+1000.example. 5M IN A 10.0.3.161
+1000.example. 5M IN A 10.0.3.162
+1000.example. 5M IN A 10.0.3.163
+1000.example. 5M IN A 10.0.3.164
+1000.example. 5M IN A 10.0.3.165
+1000.example. 5M IN A 10.0.3.166
+1000.example. 5M IN A 10.0.3.167
+1000.example. 5M IN A 10.0.3.168
+1000.example. 5M IN A 10.0.3.169
+1000.example. 5M IN A 10.0.3.170
+1000.example. 5M IN A 10.0.3.171
+1000.example. 5M IN A 10.0.3.172
+1000.example. 5M IN A 10.0.3.173
+1000.example. 5M IN A 10.0.3.174
+1000.example. 5M IN A 10.0.3.175
+1000.example. 5M IN A 10.0.3.176
+1000.example. 5M IN A 10.0.3.177
+1000.example. 5M IN A 10.0.3.178
+1000.example. 5M IN A 10.0.3.179
+1000.example. 5M IN A 10.0.3.180
+1000.example. 5M IN A 10.0.3.181
+1000.example. 5M IN A 10.0.3.182
+1000.example. 5M IN A 10.0.3.183
+1000.example. 5M IN A 10.0.3.184
+1000.example. 5M IN A 10.0.3.185
+1000.example. 5M IN A 10.0.3.186
+1000.example. 5M IN A 10.0.3.187
+1000.example. 5M IN A 10.0.3.188
+1000.example. 5M IN A 10.0.3.189
+1000.example. 5M IN A 10.0.3.190
+1000.example. 5M IN A 10.0.3.191
+1000.example. 5M IN A 10.0.3.192
+1000.example. 5M IN A 10.0.3.193
+1000.example. 5M IN A 10.0.3.194
+1000.example. 5M IN A 10.0.3.195
+1000.example. 5M IN A 10.0.3.196
+1000.example. 5M IN A 10.0.3.197
+1000.example. 5M IN A 10.0.3.198
+1000.example. 5M IN A 10.0.3.199
+1000.example. 5M IN A 10.0.3.200
+1000.example. 5M IN A 10.0.3.201
+1000.example. 5M IN A 10.0.3.202
+1000.example. 5M IN A 10.0.3.203
+1000.example. 5M IN A 10.0.3.204
+1000.example. 5M IN A 10.0.3.205
+1000.example. 5M IN A 10.0.3.206
+1000.example. 5M IN A 10.0.3.207
+1000.example. 5M IN A 10.0.3.208
+1000.example. 5M IN A 10.0.3.209
+1000.example. 5M IN A 10.0.3.210
+1000.example. 5M IN A 10.0.3.211
+1000.example. 5M IN A 10.0.3.212
+1000.example. 5M IN A 10.0.3.213
+1000.example. 5M IN A 10.0.3.214
+1000.example. 5M IN A 10.0.3.215
+1000.example. 5M IN A 10.0.3.216
+1000.example. 5M IN A 10.0.3.217
+1000.example. 5M IN A 10.0.3.218
+1000.example. 5M IN A 10.0.3.219
+1000.example. 5M IN A 10.0.3.220
+1000.example. 5M IN A 10.0.3.221
+1000.example. 5M IN A 10.0.3.222
+1000.example. 5M IN A 10.0.3.223
+1000.example. 5M IN A 10.0.3.224
+1000.example. 5M IN A 10.0.3.225
+1000.example. 5M IN A 10.0.3.226
+1000.example. 5M IN A 10.0.3.227
+1000.example. 5M IN A 10.0.3.228
+1000.example. 5M IN A 10.0.3.229
+1000.example. 5M IN A 10.0.3.230
+1000.example. 5M IN A 10.0.3.231
+
+;; AUTHORITY SECTION:
+example. 5M IN NS ns1.example.
+
+;; ADDITIONAL SECTION:
+ns1.example. 5M IN A 10.53.0.1
+
+;; Total query time: 69 msec
+;; FROM: draco to SERVER: 10.53.0.1
+;; WHEN: Fri Jun 23 12:58:14 2000
+;; MSG SIZE sent: 30 rcvd: 16064
+
diff --git a/bin/tests/system/limits/knowngood.dig.out.2000 b/bin/tests/system/limits/knowngood.dig.out.2000
new file mode 100644
index 0000000..96c9181
--- /dev/null
+++ b/bin/tests/system/limits/knowngood.dig.out.2000
@@ -0,0 +1,2023 @@
+
+; <<>> DiG 8.2 <<>> 2000.example. @10.53.0.1 a -p
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr aa rd ad; QUERY: 1, ANSWER: 2000, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; 2000.example, type = A, class = IN
+
+;; ANSWER SECTION:
+2000.example. 5M IN A 10.0.0.0
+2000.example. 5M IN A 10.0.0.1
+2000.example. 5M IN A 10.0.0.2
+2000.example. 5M IN A 10.0.0.3
+2000.example. 5M IN A 10.0.0.4
+2000.example. 5M IN A 10.0.0.5
+2000.example. 5M IN A 10.0.0.6
+2000.example. 5M IN A 10.0.0.7
+2000.example. 5M IN A 10.0.0.8
+2000.example. 5M IN A 10.0.0.9
+2000.example. 5M IN A 10.0.0.10
+2000.example. 5M IN A 10.0.0.11
+2000.example. 5M IN A 10.0.0.12
+2000.example. 5M IN A 10.0.0.13
+2000.example. 5M IN A 10.0.0.14
+2000.example. 5M IN A 10.0.0.15
+2000.example. 5M IN A 10.0.0.16
+2000.example. 5M IN A 10.0.0.17
+2000.example. 5M IN A 10.0.0.18
+2000.example. 5M IN A 10.0.0.19
+2000.example. 5M IN A 10.0.0.20
+2000.example. 5M IN A 10.0.0.21
+2000.example. 5M IN A 10.0.0.22
+2000.example. 5M IN A 10.0.0.23
+2000.example. 5M IN A 10.0.0.24
+2000.example. 5M IN A 10.0.0.25
+2000.example. 5M IN A 10.0.0.26
+2000.example. 5M IN A 10.0.0.27
+2000.example. 5M IN A 10.0.0.28
+2000.example. 5M IN A 10.0.0.29
+2000.example. 5M IN A 10.0.0.30
+2000.example. 5M IN A 10.0.0.31
+2000.example. 5M IN A 10.0.0.32
+2000.example. 5M IN A 10.0.0.33
+2000.example. 5M IN A 10.0.0.34
+2000.example. 5M IN A 10.0.0.35
+2000.example. 5M IN A 10.0.0.36
+2000.example. 5M IN A 10.0.0.37
+2000.example. 5M IN A 10.0.0.38
+2000.example. 5M IN A 10.0.0.39
+2000.example. 5M IN A 10.0.0.40
+2000.example. 5M IN A 10.0.0.41
+2000.example. 5M IN A 10.0.0.42
+2000.example. 5M IN A 10.0.0.43
+2000.example. 5M IN A 10.0.0.44
+2000.example. 5M IN A 10.0.0.45
+2000.example. 5M IN A 10.0.0.46
+2000.example. 5M IN A 10.0.0.47
+2000.example. 5M IN A 10.0.0.48
+2000.example. 5M IN A 10.0.0.49
+2000.example. 5M IN A 10.0.0.50
+2000.example. 5M IN A 10.0.0.51
+2000.example. 5M IN A 10.0.0.52
+2000.example. 5M IN A 10.0.0.53
+2000.example. 5M IN A 10.0.0.54
+2000.example. 5M IN A 10.0.0.55
+2000.example. 5M IN A 10.0.0.56
+2000.example. 5M IN A 10.0.0.57
+2000.example. 5M IN A 10.0.0.58
+2000.example. 5M IN A 10.0.0.59
+2000.example. 5M IN A 10.0.0.60
+2000.example. 5M IN A 10.0.0.61
+2000.example. 5M IN A 10.0.0.62
+2000.example. 5M IN A 10.0.0.63
+2000.example. 5M IN A 10.0.0.64
+2000.example. 5M IN A 10.0.0.65
+2000.example. 5M IN A 10.0.0.66
+2000.example. 5M IN A 10.0.0.67
+2000.example. 5M IN A 10.0.0.68
+2000.example. 5M IN A 10.0.0.69
+2000.example. 5M IN A 10.0.0.70
+2000.example. 5M IN A 10.0.0.71
+2000.example. 5M IN A 10.0.0.72
+2000.example. 5M IN A 10.0.0.73
+2000.example. 5M IN A 10.0.0.74
+2000.example. 5M IN A 10.0.0.75
+2000.example. 5M IN A 10.0.0.76
+2000.example. 5M IN A 10.0.0.77
+2000.example. 5M IN A 10.0.0.78
+2000.example. 5M IN A 10.0.0.79
+2000.example. 5M IN A 10.0.0.80
+2000.example. 5M IN A 10.0.0.81
+2000.example. 5M IN A 10.0.0.82
+2000.example. 5M IN A 10.0.0.83
+2000.example. 5M IN A 10.0.0.84
+2000.example. 5M IN A 10.0.0.85
+2000.example. 5M IN A 10.0.0.86
+2000.example. 5M IN A 10.0.0.87
+2000.example. 5M IN A 10.0.0.88
+2000.example. 5M IN A 10.0.0.89
+2000.example. 5M IN A 10.0.0.90
+2000.example. 5M IN A 10.0.0.91
+2000.example. 5M IN A 10.0.0.92
+2000.example. 5M IN A 10.0.0.93
+2000.example. 5M IN A 10.0.0.94
+2000.example. 5M IN A 10.0.0.95
+2000.example. 5M IN A 10.0.0.96
+2000.example. 5M IN A 10.0.0.97
+2000.example. 5M IN A 10.0.0.98
+2000.example. 5M IN A 10.0.0.99
+2000.example. 5M IN A 10.0.0.100
+2000.example. 5M IN A 10.0.0.101
+2000.example. 5M IN A 10.0.0.102
+2000.example. 5M IN A 10.0.0.103
+2000.example. 5M IN A 10.0.0.104
+2000.example. 5M IN A 10.0.0.105
+2000.example. 5M IN A 10.0.0.106
+2000.example. 5M IN A 10.0.0.107
+2000.example. 5M IN A 10.0.0.108
+2000.example. 5M IN A 10.0.0.109
+2000.example. 5M IN A 10.0.0.110
+2000.example. 5M IN A 10.0.0.111
+2000.example. 5M IN A 10.0.0.112
+2000.example. 5M IN A 10.0.0.113
+2000.example. 5M IN A 10.0.0.114
+2000.example. 5M IN A 10.0.0.115
+2000.example. 5M IN A 10.0.0.116
+2000.example. 5M IN A 10.0.0.117
+2000.example. 5M IN A 10.0.0.118
+2000.example. 5M IN A 10.0.0.119
+2000.example. 5M IN A 10.0.0.120
+2000.example. 5M IN A 10.0.0.121
+2000.example. 5M IN A 10.0.0.122
+2000.example. 5M IN A 10.0.0.123
+2000.example. 5M IN A 10.0.0.124
+2000.example. 5M IN A 10.0.0.125
+2000.example. 5M IN A 10.0.0.126
+2000.example. 5M IN A 10.0.0.127
+2000.example. 5M IN A 10.0.0.128
+2000.example. 5M IN A 10.0.0.129
+2000.example. 5M IN A 10.0.0.130
+2000.example. 5M IN A 10.0.0.131
+2000.example. 5M IN A 10.0.0.132
+2000.example. 5M IN A 10.0.0.133
+2000.example. 5M IN A 10.0.0.134
+2000.example. 5M IN A 10.0.0.135
+2000.example. 5M IN A 10.0.0.136
+2000.example. 5M IN A 10.0.0.137
+2000.example. 5M IN A 10.0.0.138
+2000.example. 5M IN A 10.0.0.139
+2000.example. 5M IN A 10.0.0.140
+2000.example. 5M IN A 10.0.0.141
+2000.example. 5M IN A 10.0.0.142
+2000.example. 5M IN A 10.0.0.143
+2000.example. 5M IN A 10.0.0.144
+2000.example. 5M IN A 10.0.0.145
+2000.example. 5M IN A 10.0.0.146
+2000.example. 5M IN A 10.0.0.147
+2000.example. 5M IN A 10.0.0.148
+2000.example. 5M IN A 10.0.0.149
+2000.example. 5M IN A 10.0.0.150
+2000.example. 5M IN A 10.0.0.151
+2000.example. 5M IN A 10.0.0.152
+2000.example. 5M IN A 10.0.0.153
+2000.example. 5M IN A 10.0.0.154
+2000.example. 5M IN A 10.0.0.155
+2000.example. 5M IN A 10.0.0.156
+2000.example. 5M IN A 10.0.0.157
+2000.example. 5M IN A 10.0.0.158
+2000.example. 5M IN A 10.0.0.159
+2000.example. 5M IN A 10.0.0.160
+2000.example. 5M IN A 10.0.0.161
+2000.example. 5M IN A 10.0.0.162
+2000.example. 5M IN A 10.0.0.163
+2000.example. 5M IN A 10.0.0.164
+2000.example. 5M IN A 10.0.0.165
+2000.example. 5M IN A 10.0.0.166
+2000.example. 5M IN A 10.0.0.167
+2000.example. 5M IN A 10.0.0.168
+2000.example. 5M IN A 10.0.0.169
+2000.example. 5M IN A 10.0.0.170
+2000.example. 5M IN A 10.0.0.171
+2000.example. 5M IN A 10.0.0.172
+2000.example. 5M IN A 10.0.0.173
+2000.example. 5M IN A 10.0.0.174
+2000.example. 5M IN A 10.0.0.175
+2000.example. 5M IN A 10.0.0.176
+2000.example. 5M IN A 10.0.0.177
+2000.example. 5M IN A 10.0.0.178
+2000.example. 5M IN A 10.0.0.179
+2000.example. 5M IN A 10.0.0.180
+2000.example. 5M IN A 10.0.0.181
+2000.example. 5M IN A 10.0.0.182
+2000.example. 5M IN A 10.0.0.183
+2000.example. 5M IN A 10.0.0.184
+2000.example. 5M IN A 10.0.0.185
+2000.example. 5M IN A 10.0.0.186
+2000.example. 5M IN A 10.0.0.187
+2000.example. 5M IN A 10.0.0.188
+2000.example. 5M IN A 10.0.0.189
+2000.example. 5M IN A 10.0.0.190
+2000.example. 5M IN A 10.0.0.191
+2000.example. 5M IN A 10.0.0.192
+2000.example. 5M IN A 10.0.0.193
+2000.example. 5M IN A 10.0.0.194
+2000.example. 5M IN A 10.0.0.195
+2000.example. 5M IN A 10.0.0.196
+2000.example. 5M IN A 10.0.0.197
+2000.example. 5M IN A 10.0.0.198
+2000.example. 5M IN A 10.0.0.199
+2000.example. 5M IN A 10.0.0.200
+2000.example. 5M IN A 10.0.0.201
+2000.example. 5M IN A 10.0.0.202
+2000.example. 5M IN A 10.0.0.203
+2000.example. 5M IN A 10.0.0.204
+2000.example. 5M IN A 10.0.0.205
+2000.example. 5M IN A 10.0.0.206
+2000.example. 5M IN A 10.0.0.207
+2000.example. 5M IN A 10.0.0.208
+2000.example. 5M IN A 10.0.0.209
+2000.example. 5M IN A 10.0.0.210
+2000.example. 5M IN A 10.0.0.211
+2000.example. 5M IN A 10.0.0.212
+2000.example. 5M IN A 10.0.0.213
+2000.example. 5M IN A 10.0.0.214
+2000.example. 5M IN A 10.0.0.215
+2000.example. 5M IN A 10.0.0.216
+2000.example. 5M IN A 10.0.0.217
+2000.example. 5M IN A 10.0.0.218
+2000.example. 5M IN A 10.0.0.219
+2000.example. 5M IN A 10.0.0.220
+2000.example. 5M IN A 10.0.0.221
+2000.example. 5M IN A 10.0.0.222
+2000.example. 5M IN A 10.0.0.223
+2000.example. 5M IN A 10.0.0.224
+2000.example. 5M IN A 10.0.0.225
+2000.example. 5M IN A 10.0.0.226
+2000.example. 5M IN A 10.0.0.227
+2000.example. 5M IN A 10.0.0.228
+2000.example. 5M IN A 10.0.0.229
+2000.example. 5M IN A 10.0.0.230
+2000.example. 5M IN A 10.0.0.231
+2000.example. 5M IN A 10.0.0.232
+2000.example. 5M IN A 10.0.0.233
+2000.example. 5M IN A 10.0.0.234
+2000.example. 5M IN A 10.0.0.235
+2000.example. 5M IN A 10.0.0.236
+2000.example. 5M IN A 10.0.0.237
+2000.example. 5M IN A 10.0.0.238
+2000.example. 5M IN A 10.0.0.239
+2000.example. 5M IN A 10.0.0.240
+2000.example. 5M IN A 10.0.0.241
+2000.example. 5M IN A 10.0.0.242
+2000.example. 5M IN A 10.0.0.243
+2000.example. 5M IN A 10.0.0.244
+2000.example. 5M IN A 10.0.0.245
+2000.example. 5M IN A 10.0.0.246
+2000.example. 5M IN A 10.0.0.247
+2000.example. 5M IN A 10.0.0.248
+2000.example. 5M IN A 10.0.0.249
+2000.example. 5M IN A 10.0.0.250
+2000.example. 5M IN A 10.0.0.251
+2000.example. 5M IN A 10.0.0.252
+2000.example. 5M IN A 10.0.0.253
+2000.example. 5M IN A 10.0.0.254
+2000.example. 5M IN A 10.0.0.255
+2000.example. 5M IN A 10.0.1.0
+2000.example. 5M IN A 10.0.1.1
+2000.example. 5M IN A 10.0.1.2
+2000.example. 5M IN A 10.0.1.3
+2000.example. 5M IN A 10.0.1.4
+2000.example. 5M IN A 10.0.1.5
+2000.example. 5M IN A 10.0.1.6
+2000.example. 5M IN A 10.0.1.7
+2000.example. 5M IN A 10.0.1.8
+2000.example. 5M IN A 10.0.1.9
+2000.example. 5M IN A 10.0.1.10
+2000.example. 5M IN A 10.0.1.11
+2000.example. 5M IN A 10.0.1.12
+2000.example. 5M IN A 10.0.1.13
+2000.example. 5M IN A 10.0.1.14
+2000.example. 5M IN A 10.0.1.15
+2000.example. 5M IN A 10.0.1.16
+2000.example. 5M IN A 10.0.1.17
+2000.example. 5M IN A 10.0.1.18
+2000.example. 5M IN A 10.0.1.19
+2000.example. 5M IN A 10.0.1.20
+2000.example. 5M IN A 10.0.1.21
+2000.example. 5M IN A 10.0.1.22
+2000.example. 5M IN A 10.0.1.23
+2000.example. 5M IN A 10.0.1.24
+2000.example. 5M IN A 10.0.1.25
+2000.example. 5M IN A 10.0.1.26
+2000.example. 5M IN A 10.0.1.27
+2000.example. 5M IN A 10.0.1.28
+2000.example. 5M IN A 10.0.1.29
+2000.example. 5M IN A 10.0.1.30
+2000.example. 5M IN A 10.0.1.31
+2000.example. 5M IN A 10.0.1.32
+2000.example. 5M IN A 10.0.1.33
+2000.example. 5M IN A 10.0.1.34
+2000.example. 5M IN A 10.0.1.35
+2000.example. 5M IN A 10.0.1.36
+2000.example. 5M IN A 10.0.1.37
+2000.example. 5M IN A 10.0.1.38
+2000.example. 5M IN A 10.0.1.39
+2000.example. 5M IN A 10.0.1.40
+2000.example. 5M IN A 10.0.1.41
+2000.example. 5M IN A 10.0.1.42
+2000.example. 5M IN A 10.0.1.43
+2000.example. 5M IN A 10.0.1.44
+2000.example. 5M IN A 10.0.1.45
+2000.example. 5M IN A 10.0.1.46
+2000.example. 5M IN A 10.0.1.47
+2000.example. 5M IN A 10.0.1.48
+2000.example. 5M IN A 10.0.1.49
+2000.example. 5M IN A 10.0.1.50
+2000.example. 5M IN A 10.0.1.51
+2000.example. 5M IN A 10.0.1.52
+2000.example. 5M IN A 10.0.1.53
+2000.example. 5M IN A 10.0.1.54
+2000.example. 5M IN A 10.0.1.55
+2000.example. 5M IN A 10.0.1.56
+2000.example. 5M IN A 10.0.1.57
+2000.example. 5M IN A 10.0.1.58
+2000.example. 5M IN A 10.0.1.59
+2000.example. 5M IN A 10.0.1.60
+2000.example. 5M IN A 10.0.1.61
+2000.example. 5M IN A 10.0.1.62
+2000.example. 5M IN A 10.0.1.63
+2000.example. 5M IN A 10.0.1.64
+2000.example. 5M IN A 10.0.1.65
+2000.example. 5M IN A 10.0.1.66
+2000.example. 5M IN A 10.0.1.67
+2000.example. 5M IN A 10.0.1.68
+2000.example. 5M IN A 10.0.1.69
+2000.example. 5M IN A 10.0.1.70
+2000.example. 5M IN A 10.0.1.71
+2000.example. 5M IN A 10.0.1.72
+2000.example. 5M IN A 10.0.1.73
+2000.example. 5M IN A 10.0.1.74
+2000.example. 5M IN A 10.0.1.75
+2000.example. 5M IN A 10.0.1.76
+2000.example. 5M IN A 10.0.1.77
+2000.example. 5M IN A 10.0.1.78
+2000.example. 5M IN A 10.0.1.79
+2000.example. 5M IN A 10.0.1.80
+2000.example. 5M IN A 10.0.1.81
+2000.example. 5M IN A 10.0.1.82
+2000.example. 5M IN A 10.0.1.83
+2000.example. 5M IN A 10.0.1.84
+2000.example. 5M IN A 10.0.1.85
+2000.example. 5M IN A 10.0.1.86
+2000.example. 5M IN A 10.0.1.87
+2000.example. 5M IN A 10.0.1.88
+2000.example. 5M IN A 10.0.1.89
+2000.example. 5M IN A 10.0.1.90
+2000.example. 5M IN A 10.0.1.91
+2000.example. 5M IN A 10.0.1.92
+2000.example. 5M IN A 10.0.1.93
+2000.example. 5M IN A 10.0.1.94
+2000.example. 5M IN A 10.0.1.95
+2000.example. 5M IN A 10.0.1.96
+2000.example. 5M IN A 10.0.1.97
+2000.example. 5M IN A 10.0.1.98
+2000.example. 5M IN A 10.0.1.99
+2000.example. 5M IN A 10.0.1.100
+2000.example. 5M IN A 10.0.1.101
+2000.example. 5M IN A 10.0.1.102
+2000.example. 5M IN A 10.0.1.103
+2000.example. 5M IN A 10.0.1.104
+2000.example. 5M IN A 10.0.1.105
+2000.example. 5M IN A 10.0.1.106
+2000.example. 5M IN A 10.0.1.107
+2000.example. 5M IN A 10.0.1.108
+2000.example. 5M IN A 10.0.1.109
+2000.example. 5M IN A 10.0.1.110
+2000.example. 5M IN A 10.0.1.111
+2000.example. 5M IN A 10.0.1.112
+2000.example. 5M IN A 10.0.1.113
+2000.example. 5M IN A 10.0.1.114
+2000.example. 5M IN A 10.0.1.115
+2000.example. 5M IN A 10.0.1.116
+2000.example. 5M IN A 10.0.1.117
+2000.example. 5M IN A 10.0.1.118
+2000.example. 5M IN A 10.0.1.119
+2000.example. 5M IN A 10.0.1.120
+2000.example. 5M IN A 10.0.1.121
+2000.example. 5M IN A 10.0.1.122
+2000.example. 5M IN A 10.0.1.123
+2000.example. 5M IN A 10.0.1.124
+2000.example. 5M IN A 10.0.1.125
+2000.example. 5M IN A 10.0.1.126
+2000.example. 5M IN A 10.0.1.127
+2000.example. 5M IN A 10.0.1.128
+2000.example. 5M IN A 10.0.1.129
+2000.example. 5M IN A 10.0.1.130
+2000.example. 5M IN A 10.0.1.131
+2000.example. 5M IN A 10.0.1.132
+2000.example. 5M IN A 10.0.1.133
+2000.example. 5M IN A 10.0.1.134
+2000.example. 5M IN A 10.0.1.135
+2000.example. 5M IN A 10.0.1.136
+2000.example. 5M IN A 10.0.1.137
+2000.example. 5M IN A 10.0.1.138
+2000.example. 5M IN A 10.0.1.139
+2000.example. 5M IN A 10.0.1.140
+2000.example. 5M IN A 10.0.1.141
+2000.example. 5M IN A 10.0.1.142
+2000.example. 5M IN A 10.0.1.143
+2000.example. 5M IN A 10.0.1.144
+2000.example. 5M IN A 10.0.1.145
+2000.example. 5M IN A 10.0.1.146
+2000.example. 5M IN A 10.0.1.147
+2000.example. 5M IN A 10.0.1.148
+2000.example. 5M IN A 10.0.1.149
+2000.example. 5M IN A 10.0.1.150
+2000.example. 5M IN A 10.0.1.151
+2000.example. 5M IN A 10.0.1.152
+2000.example. 5M IN A 10.0.1.153
+2000.example. 5M IN A 10.0.1.154
+2000.example. 5M IN A 10.0.1.155
+2000.example. 5M IN A 10.0.1.156
+2000.example. 5M IN A 10.0.1.157
+2000.example. 5M IN A 10.0.1.158
+2000.example. 5M IN A 10.0.1.159
+2000.example. 5M IN A 10.0.1.160
+2000.example. 5M IN A 10.0.1.161
+2000.example. 5M IN A 10.0.1.162
+2000.example. 5M IN A 10.0.1.163
+2000.example. 5M IN A 10.0.1.164
+2000.example. 5M IN A 10.0.1.165
+2000.example. 5M IN A 10.0.1.166
+2000.example. 5M IN A 10.0.1.167
+2000.example. 5M IN A 10.0.1.168
+2000.example. 5M IN A 10.0.1.169
+2000.example. 5M IN A 10.0.1.170
+2000.example. 5M IN A 10.0.1.171
+2000.example. 5M IN A 10.0.1.172
+2000.example. 5M IN A 10.0.1.173
+2000.example. 5M IN A 10.0.1.174
+2000.example. 5M IN A 10.0.1.175
+2000.example. 5M IN A 10.0.1.176
+2000.example. 5M IN A 10.0.1.177
+2000.example. 5M IN A 10.0.1.178
+2000.example. 5M IN A 10.0.1.179
+2000.example. 5M IN A 10.0.1.180
+2000.example. 5M IN A 10.0.1.181
+2000.example. 5M IN A 10.0.1.182
+2000.example. 5M IN A 10.0.1.183
+2000.example. 5M IN A 10.0.1.184
+2000.example. 5M IN A 10.0.1.185
+2000.example. 5M IN A 10.0.1.186
+2000.example. 5M IN A 10.0.1.187
+2000.example. 5M IN A 10.0.1.188
+2000.example. 5M IN A 10.0.1.189
+2000.example. 5M IN A 10.0.1.190
+2000.example. 5M IN A 10.0.1.191
+2000.example. 5M IN A 10.0.1.192
+2000.example. 5M IN A 10.0.1.193
+2000.example. 5M IN A 10.0.1.194
+2000.example. 5M IN A 10.0.1.195
+2000.example. 5M IN A 10.0.1.196
+2000.example. 5M IN A 10.0.1.197
+2000.example. 5M IN A 10.0.1.198
+2000.example. 5M IN A 10.0.1.199
+2000.example. 5M IN A 10.0.1.200
+2000.example. 5M IN A 10.0.1.201
+2000.example. 5M IN A 10.0.1.202
+2000.example. 5M IN A 10.0.1.203
+2000.example. 5M IN A 10.0.1.204
+2000.example. 5M IN A 10.0.1.205
+2000.example. 5M IN A 10.0.1.206
+2000.example. 5M IN A 10.0.1.207
+2000.example. 5M IN A 10.0.1.208
+2000.example. 5M IN A 10.0.1.209
+2000.example. 5M IN A 10.0.1.210
+2000.example. 5M IN A 10.0.1.211
+2000.example. 5M IN A 10.0.1.212
+2000.example. 5M IN A 10.0.1.213
+2000.example. 5M IN A 10.0.1.214
+2000.example. 5M IN A 10.0.1.215
+2000.example. 5M IN A 10.0.1.216
+2000.example. 5M IN A 10.0.1.217
+2000.example. 5M IN A 10.0.1.218
+2000.example. 5M IN A 10.0.1.219
+2000.example. 5M IN A 10.0.1.220
+2000.example. 5M IN A 10.0.1.221
+2000.example. 5M IN A 10.0.1.222
+2000.example. 5M IN A 10.0.1.223
+2000.example. 5M IN A 10.0.1.224
+2000.example. 5M IN A 10.0.1.225
+2000.example. 5M IN A 10.0.1.226
+2000.example. 5M IN A 10.0.1.227
+2000.example. 5M IN A 10.0.1.228
+2000.example. 5M IN A 10.0.1.229
+2000.example. 5M IN A 10.0.1.230
+2000.example. 5M IN A 10.0.1.231
+2000.example. 5M IN A 10.0.1.232
+2000.example. 5M IN A 10.0.1.233
+2000.example. 5M IN A 10.0.1.234
+2000.example. 5M IN A 10.0.1.235
+2000.example. 5M IN A 10.0.1.236
+2000.example. 5M IN A 10.0.1.237
+2000.example. 5M IN A 10.0.1.238
+2000.example. 5M IN A 10.0.1.239
+2000.example. 5M IN A 10.0.1.240
+2000.example. 5M IN A 10.0.1.241
+2000.example. 5M IN A 10.0.1.242
+2000.example. 5M IN A 10.0.1.243
+2000.example. 5M IN A 10.0.1.244
+2000.example. 5M IN A 10.0.1.245
+2000.example. 5M IN A 10.0.1.246
+2000.example. 5M IN A 10.0.1.247
+2000.example. 5M IN A 10.0.1.248
+2000.example. 5M IN A 10.0.1.249
+2000.example. 5M IN A 10.0.1.250
+2000.example. 5M IN A 10.0.1.251
+2000.example. 5M IN A 10.0.1.252
+2000.example. 5M IN A 10.0.1.253
+2000.example. 5M IN A 10.0.1.254
+2000.example. 5M IN A 10.0.1.255
+2000.example. 5M IN A 10.0.2.0
+2000.example. 5M IN A 10.0.2.1
+2000.example. 5M IN A 10.0.2.2
+2000.example. 5M IN A 10.0.2.3
+2000.example. 5M IN A 10.0.2.4
+2000.example. 5M IN A 10.0.2.5
+2000.example. 5M IN A 10.0.2.6
+2000.example. 5M IN A 10.0.2.7
+2000.example. 5M IN A 10.0.2.8
+2000.example. 5M IN A 10.0.2.9
+2000.example. 5M IN A 10.0.2.10
+2000.example. 5M IN A 10.0.2.11
+2000.example. 5M IN A 10.0.2.12
+2000.example. 5M IN A 10.0.2.13
+2000.example. 5M IN A 10.0.2.14
+2000.example. 5M IN A 10.0.2.15
+2000.example. 5M IN A 10.0.2.16
+2000.example. 5M IN A 10.0.2.17
+2000.example. 5M IN A 10.0.2.18
+2000.example. 5M IN A 10.0.2.19
+2000.example. 5M IN A 10.0.2.20
+2000.example. 5M IN A 10.0.2.21
+2000.example. 5M IN A 10.0.2.22
+2000.example. 5M IN A 10.0.2.23
+2000.example. 5M IN A 10.0.2.24
+2000.example. 5M IN A 10.0.2.25
+2000.example. 5M IN A 10.0.2.26
+2000.example. 5M IN A 10.0.2.27
+2000.example. 5M IN A 10.0.2.28
+2000.example. 5M IN A 10.0.2.29
+2000.example. 5M IN A 10.0.2.30
+2000.example. 5M IN A 10.0.2.31
+2000.example. 5M IN A 10.0.2.32
+2000.example. 5M IN A 10.0.2.33
+2000.example. 5M IN A 10.0.2.34
+2000.example. 5M IN A 10.0.2.35
+2000.example. 5M IN A 10.0.2.36
+2000.example. 5M IN A 10.0.2.37
+2000.example. 5M IN A 10.0.2.38
+2000.example. 5M IN A 10.0.2.39
+2000.example. 5M IN A 10.0.2.40
+2000.example. 5M IN A 10.0.2.41
+2000.example. 5M IN A 10.0.2.42
+2000.example. 5M IN A 10.0.2.43
+2000.example. 5M IN A 10.0.2.44
+2000.example. 5M IN A 10.0.2.45
+2000.example. 5M IN A 10.0.2.46
+2000.example. 5M IN A 10.0.2.47
+2000.example. 5M IN A 10.0.2.48
+2000.example. 5M IN A 10.0.2.49
+2000.example. 5M IN A 10.0.2.50
+2000.example. 5M IN A 10.0.2.51
+2000.example. 5M IN A 10.0.2.52
+2000.example. 5M IN A 10.0.2.53
+2000.example. 5M IN A 10.0.2.54
+2000.example. 5M IN A 10.0.2.55
+2000.example. 5M IN A 10.0.2.56
+2000.example. 5M IN A 10.0.2.57
+2000.example. 5M IN A 10.0.2.58
+2000.example. 5M IN A 10.0.2.59
+2000.example. 5M IN A 10.0.2.60
+2000.example. 5M IN A 10.0.2.61
+2000.example. 5M IN A 10.0.2.62
+2000.example. 5M IN A 10.0.2.63
+2000.example. 5M IN A 10.0.2.64
+2000.example. 5M IN A 10.0.2.65
+2000.example. 5M IN A 10.0.2.66
+2000.example. 5M IN A 10.0.2.67
+2000.example. 5M IN A 10.0.2.68
+2000.example. 5M IN A 10.0.2.69
+2000.example. 5M IN A 10.0.2.70
+2000.example. 5M IN A 10.0.2.71
+2000.example. 5M IN A 10.0.2.72
+2000.example. 5M IN A 10.0.2.73
+2000.example. 5M IN A 10.0.2.74
+2000.example. 5M IN A 10.0.2.75
+2000.example. 5M IN A 10.0.2.76
+2000.example. 5M IN A 10.0.2.77
+2000.example. 5M IN A 10.0.2.78
+2000.example. 5M IN A 10.0.2.79
+2000.example. 5M IN A 10.0.2.80
+2000.example. 5M IN A 10.0.2.81
+2000.example. 5M IN A 10.0.2.82
+2000.example. 5M IN A 10.0.2.83
+2000.example. 5M IN A 10.0.2.84
+2000.example. 5M IN A 10.0.2.85
+2000.example. 5M IN A 10.0.2.86
+2000.example. 5M IN A 10.0.2.87
+2000.example. 5M IN A 10.0.2.88
+2000.example. 5M IN A 10.0.2.89
+2000.example. 5M IN A 10.0.2.90
+2000.example. 5M IN A 10.0.2.91
+2000.example. 5M IN A 10.0.2.92
+2000.example. 5M IN A 10.0.2.93
+2000.example. 5M IN A 10.0.2.94
+2000.example. 5M IN A 10.0.2.95
+2000.example. 5M IN A 10.0.2.96
+2000.example. 5M IN A 10.0.2.97
+2000.example. 5M IN A 10.0.2.98
+2000.example. 5M IN A 10.0.2.99
+2000.example. 5M IN A 10.0.2.100
+2000.example. 5M IN A 10.0.2.101
+2000.example. 5M IN A 10.0.2.102
+2000.example. 5M IN A 10.0.2.103
+2000.example. 5M IN A 10.0.2.104
+2000.example. 5M IN A 10.0.2.105
+2000.example. 5M IN A 10.0.2.106
+2000.example. 5M IN A 10.0.2.107
+2000.example. 5M IN A 10.0.2.108
+2000.example. 5M IN A 10.0.2.109
+2000.example. 5M IN A 10.0.2.110
+2000.example. 5M IN A 10.0.2.111
+2000.example. 5M IN A 10.0.2.112
+2000.example. 5M IN A 10.0.2.113
+2000.example. 5M IN A 10.0.2.114
+2000.example. 5M IN A 10.0.2.115
+2000.example. 5M IN A 10.0.2.116
+2000.example. 5M IN A 10.0.2.117
+2000.example. 5M IN A 10.0.2.118
+2000.example. 5M IN A 10.0.2.119
+2000.example. 5M IN A 10.0.2.120
+2000.example. 5M IN A 10.0.2.121
+2000.example. 5M IN A 10.0.2.122
+2000.example. 5M IN A 10.0.2.123
+2000.example. 5M IN A 10.0.2.124
+2000.example. 5M IN A 10.0.2.125
+2000.example. 5M IN A 10.0.2.126
+2000.example. 5M IN A 10.0.2.127
+2000.example. 5M IN A 10.0.2.128
+2000.example. 5M IN A 10.0.2.129
+2000.example. 5M IN A 10.0.2.130
+2000.example. 5M IN A 10.0.2.131
+2000.example. 5M IN A 10.0.2.132
+2000.example. 5M IN A 10.0.2.133
+2000.example. 5M IN A 10.0.2.134
+2000.example. 5M IN A 10.0.2.135
+2000.example. 5M IN A 10.0.2.136
+2000.example. 5M IN A 10.0.2.137
+2000.example. 5M IN A 10.0.2.138
+2000.example. 5M IN A 10.0.2.139
+2000.example. 5M IN A 10.0.2.140
+2000.example. 5M IN A 10.0.2.141
+2000.example. 5M IN A 10.0.2.142
+2000.example. 5M IN A 10.0.2.143
+2000.example. 5M IN A 10.0.2.144
+2000.example. 5M IN A 10.0.2.145
+2000.example. 5M IN A 10.0.2.146
+2000.example. 5M IN A 10.0.2.147
+2000.example. 5M IN A 10.0.2.148
+2000.example. 5M IN A 10.0.2.149
+2000.example. 5M IN A 10.0.2.150
+2000.example. 5M IN A 10.0.2.151
+2000.example. 5M IN A 10.0.2.152
+2000.example. 5M IN A 10.0.2.153
+2000.example. 5M IN A 10.0.2.154
+2000.example. 5M IN A 10.0.2.155
+2000.example. 5M IN A 10.0.2.156
+2000.example. 5M IN A 10.0.2.157
+2000.example. 5M IN A 10.0.2.158
+2000.example. 5M IN A 10.0.2.159
+2000.example. 5M IN A 10.0.2.160
+2000.example. 5M IN A 10.0.2.161
+2000.example. 5M IN A 10.0.2.162
+2000.example. 5M IN A 10.0.2.163
+2000.example. 5M IN A 10.0.2.164
+2000.example. 5M IN A 10.0.2.165
+2000.example. 5M IN A 10.0.2.166
+2000.example. 5M IN A 10.0.2.167
+2000.example. 5M IN A 10.0.2.168
+2000.example. 5M IN A 10.0.2.169
+2000.example. 5M IN A 10.0.2.170
+2000.example. 5M IN A 10.0.2.171
+2000.example. 5M IN A 10.0.2.172
+2000.example. 5M IN A 10.0.2.173
+2000.example. 5M IN A 10.0.2.174
+2000.example. 5M IN A 10.0.2.175
+2000.example. 5M IN A 10.0.2.176
+2000.example. 5M IN A 10.0.2.177
+2000.example. 5M IN A 10.0.2.178
+2000.example. 5M IN A 10.0.2.179
+2000.example. 5M IN A 10.0.2.180
+2000.example. 5M IN A 10.0.2.181
+2000.example. 5M IN A 10.0.2.182
+2000.example. 5M IN A 10.0.2.183
+2000.example. 5M IN A 10.0.2.184
+2000.example. 5M IN A 10.0.2.185
+2000.example. 5M IN A 10.0.2.186
+2000.example. 5M IN A 10.0.2.187
+2000.example. 5M IN A 10.0.2.188
+2000.example. 5M IN A 10.0.2.189
+2000.example. 5M IN A 10.0.2.190
+2000.example. 5M IN A 10.0.2.191
+2000.example. 5M IN A 10.0.2.192
+2000.example. 5M IN A 10.0.2.193
+2000.example. 5M IN A 10.0.2.194
+2000.example. 5M IN A 10.0.2.195
+2000.example. 5M IN A 10.0.2.196
+2000.example. 5M IN A 10.0.2.197
+2000.example. 5M IN A 10.0.2.198
+2000.example. 5M IN A 10.0.2.199
+2000.example. 5M IN A 10.0.2.200
+2000.example. 5M IN A 10.0.2.201
+2000.example. 5M IN A 10.0.2.202
+2000.example. 5M IN A 10.0.2.203
+2000.example. 5M IN A 10.0.2.204
+2000.example. 5M IN A 10.0.2.205
+2000.example. 5M IN A 10.0.2.206
+2000.example. 5M IN A 10.0.2.207
+2000.example. 5M IN A 10.0.2.208
+2000.example. 5M IN A 10.0.2.209
+2000.example. 5M IN A 10.0.2.210
+2000.example. 5M IN A 10.0.2.211
+2000.example. 5M IN A 10.0.2.212
+2000.example. 5M IN A 10.0.2.213
+2000.example. 5M IN A 10.0.2.214
+2000.example. 5M IN A 10.0.2.215
+2000.example. 5M IN A 10.0.2.216
+2000.example. 5M IN A 10.0.2.217
+2000.example. 5M IN A 10.0.2.218
+2000.example. 5M IN A 10.0.2.219
+2000.example. 5M IN A 10.0.2.220
+2000.example. 5M IN A 10.0.2.221
+2000.example. 5M IN A 10.0.2.222
+2000.example. 5M IN A 10.0.2.223
+2000.example. 5M IN A 10.0.2.224
+2000.example. 5M IN A 10.0.2.225
+2000.example. 5M IN A 10.0.2.226
+2000.example. 5M IN A 10.0.2.227
+2000.example. 5M IN A 10.0.2.228
+2000.example. 5M IN A 10.0.2.229
+2000.example. 5M IN A 10.0.2.230
+2000.example. 5M IN A 10.0.2.231
+2000.example. 5M IN A 10.0.2.232
+2000.example. 5M IN A 10.0.2.233
+2000.example. 5M IN A 10.0.2.234
+2000.example. 5M IN A 10.0.2.235
+2000.example. 5M IN A 10.0.2.236
+2000.example. 5M IN A 10.0.2.237
+2000.example. 5M IN A 10.0.2.238
+2000.example. 5M IN A 10.0.2.239
+2000.example. 5M IN A 10.0.2.240
+2000.example. 5M IN A 10.0.2.241
+2000.example. 5M IN A 10.0.2.242
+2000.example. 5M IN A 10.0.2.243
+2000.example. 5M IN A 10.0.2.244
+2000.example. 5M IN A 10.0.2.245
+2000.example. 5M IN A 10.0.2.246
+2000.example. 5M IN A 10.0.2.247
+2000.example. 5M IN A 10.0.2.248
+2000.example. 5M IN A 10.0.2.249
+2000.example. 5M IN A 10.0.2.250
+2000.example. 5M IN A 10.0.2.251
+2000.example. 5M IN A 10.0.2.252
+2000.example. 5M IN A 10.0.2.253
+2000.example. 5M IN A 10.0.2.254
+2000.example. 5M IN A 10.0.2.255
+2000.example. 5M IN A 10.0.3.0
+2000.example. 5M IN A 10.0.3.1
+2000.example. 5M IN A 10.0.3.2
+2000.example. 5M IN A 10.0.3.3
+2000.example. 5M IN A 10.0.3.4
+2000.example. 5M IN A 10.0.3.5
+2000.example. 5M IN A 10.0.3.6
+2000.example. 5M IN A 10.0.3.7
+2000.example. 5M IN A 10.0.3.8
+2000.example. 5M IN A 10.0.3.9
+2000.example. 5M IN A 10.0.3.10
+2000.example. 5M IN A 10.0.3.11
+2000.example. 5M IN A 10.0.3.12
+2000.example. 5M IN A 10.0.3.13
+2000.example. 5M IN A 10.0.3.14
+2000.example. 5M IN A 10.0.3.15
+2000.example. 5M IN A 10.0.3.16
+2000.example. 5M IN A 10.0.3.17
+2000.example. 5M IN A 10.0.3.18
+2000.example. 5M IN A 10.0.3.19
+2000.example. 5M IN A 10.0.3.20
+2000.example. 5M IN A 10.0.3.21
+2000.example. 5M IN A 10.0.3.22
+2000.example. 5M IN A 10.0.3.23
+2000.example. 5M IN A 10.0.3.24
+2000.example. 5M IN A 10.0.3.25
+2000.example. 5M IN A 10.0.3.26
+2000.example. 5M IN A 10.0.3.27
+2000.example. 5M IN A 10.0.3.28
+2000.example. 5M IN A 10.0.3.29
+2000.example. 5M IN A 10.0.3.30
+2000.example. 5M IN A 10.0.3.31
+2000.example. 5M IN A 10.0.3.32
+2000.example. 5M IN A 10.0.3.33
+2000.example. 5M IN A 10.0.3.34
+2000.example. 5M IN A 10.0.3.35
+2000.example. 5M IN A 10.0.3.36
+2000.example. 5M IN A 10.0.3.37
+2000.example. 5M IN A 10.0.3.38
+2000.example. 5M IN A 10.0.3.39
+2000.example. 5M IN A 10.0.3.40
+2000.example. 5M IN A 10.0.3.41
+2000.example. 5M IN A 10.0.3.42
+2000.example. 5M IN A 10.0.3.43
+2000.example. 5M IN A 10.0.3.44
+2000.example. 5M IN A 10.0.3.45
+2000.example. 5M IN A 10.0.3.46
+2000.example. 5M IN A 10.0.3.47
+2000.example. 5M IN A 10.0.3.48
+2000.example. 5M IN A 10.0.3.49
+2000.example. 5M IN A 10.0.3.50
+2000.example. 5M IN A 10.0.3.51
+2000.example. 5M IN A 10.0.3.52
+2000.example. 5M IN A 10.0.3.53
+2000.example. 5M IN A 10.0.3.54
+2000.example. 5M IN A 10.0.3.55
+2000.example. 5M IN A 10.0.3.56
+2000.example. 5M IN A 10.0.3.57
+2000.example. 5M IN A 10.0.3.58
+2000.example. 5M IN A 10.0.3.59
+2000.example. 5M IN A 10.0.3.60
+2000.example. 5M IN A 10.0.3.61
+2000.example. 5M IN A 10.0.3.62
+2000.example. 5M IN A 10.0.3.63
+2000.example. 5M IN A 10.0.3.64
+2000.example. 5M IN A 10.0.3.65
+2000.example. 5M IN A 10.0.3.66
+2000.example. 5M IN A 10.0.3.67
+2000.example. 5M IN A 10.0.3.68
+2000.example. 5M IN A 10.0.3.69
+2000.example. 5M IN A 10.0.3.70
+2000.example. 5M IN A 10.0.3.71
+2000.example. 5M IN A 10.0.3.72
+2000.example. 5M IN A 10.0.3.73
+2000.example. 5M IN A 10.0.3.74
+2000.example. 5M IN A 10.0.3.75
+2000.example. 5M IN A 10.0.3.76
+2000.example. 5M IN A 10.0.3.77
+2000.example. 5M IN A 10.0.3.78
+2000.example. 5M IN A 10.0.3.79
+2000.example. 5M IN A 10.0.3.80
+2000.example. 5M IN A 10.0.3.81
+2000.example. 5M IN A 10.0.3.82
+2000.example. 5M IN A 10.0.3.83
+2000.example. 5M IN A 10.0.3.84
+2000.example. 5M IN A 10.0.3.85
+2000.example. 5M IN A 10.0.3.86
+2000.example. 5M IN A 10.0.3.87
+2000.example. 5M IN A 10.0.3.88
+2000.example. 5M IN A 10.0.3.89
+2000.example. 5M IN A 10.0.3.90
+2000.example. 5M IN A 10.0.3.91
+2000.example. 5M IN A 10.0.3.92
+2000.example. 5M IN A 10.0.3.93
+2000.example. 5M IN A 10.0.3.94
+2000.example. 5M IN A 10.0.3.95
+2000.example. 5M IN A 10.0.3.96
+2000.example. 5M IN A 10.0.3.97
+2000.example. 5M IN A 10.0.3.98
+2000.example. 5M IN A 10.0.3.99
+2000.example. 5M IN A 10.0.3.100
+2000.example. 5M IN A 10.0.3.101
+2000.example. 5M IN A 10.0.3.102
+2000.example. 5M IN A 10.0.3.103
+2000.example. 5M IN A 10.0.3.104
+2000.example. 5M IN A 10.0.3.105
+2000.example. 5M IN A 10.0.3.106
+2000.example. 5M IN A 10.0.3.107
+2000.example. 5M IN A 10.0.3.108
+2000.example. 5M IN A 10.0.3.109
+2000.example. 5M IN A 10.0.3.110
+2000.example. 5M IN A 10.0.3.111
+2000.example. 5M IN A 10.0.3.112
+2000.example. 5M IN A 10.0.3.113
+2000.example. 5M IN A 10.0.3.114
+2000.example. 5M IN A 10.0.3.115
+2000.example. 5M IN A 10.0.3.116
+2000.example. 5M IN A 10.0.3.117
+2000.example. 5M IN A 10.0.3.118
+2000.example. 5M IN A 10.0.3.119
+2000.example. 5M IN A 10.0.3.120
+2000.example. 5M IN A 10.0.3.121
+2000.example. 5M IN A 10.0.3.122
+2000.example. 5M IN A 10.0.3.123
+2000.example. 5M IN A 10.0.3.124
+2000.example. 5M IN A 10.0.3.125
+2000.example. 5M IN A 10.0.3.126
+2000.example. 5M IN A 10.0.3.127
+2000.example. 5M IN A 10.0.3.128
+2000.example. 5M IN A 10.0.3.129
+2000.example. 5M IN A 10.0.3.130
+2000.example. 5M IN A 10.0.3.131
+2000.example. 5M IN A 10.0.3.132
+2000.example. 5M IN A 10.0.3.133
+2000.example. 5M IN A 10.0.3.134
+2000.example. 5M IN A 10.0.3.135
+2000.example. 5M IN A 10.0.3.136
+2000.example. 5M IN A 10.0.3.137
+2000.example. 5M IN A 10.0.3.138
+2000.example. 5M IN A 10.0.3.139
+2000.example. 5M IN A 10.0.3.140
+2000.example. 5M IN A 10.0.3.141
+2000.example. 5M IN A 10.0.3.142
+2000.example. 5M IN A 10.0.3.143
+2000.example. 5M IN A 10.0.3.144
+2000.example. 5M IN A 10.0.3.145
+2000.example. 5M IN A 10.0.3.146
+2000.example. 5M IN A 10.0.3.147
+2000.example. 5M IN A 10.0.3.148
+2000.example. 5M IN A 10.0.3.149
+2000.example. 5M IN A 10.0.3.150
+2000.example. 5M IN A 10.0.3.151
+2000.example. 5M IN A 10.0.3.152
+2000.example. 5M IN A 10.0.3.153
+2000.example. 5M IN A 10.0.3.154
+2000.example. 5M IN A 10.0.3.155
+2000.example. 5M IN A 10.0.3.156
+2000.example. 5M IN A 10.0.3.157
+2000.example. 5M IN A 10.0.3.158
+2000.example. 5M IN A 10.0.3.159
+2000.example. 5M IN A 10.0.3.160
+2000.example. 5M IN A 10.0.3.161
+2000.example. 5M IN A 10.0.3.162
+2000.example. 5M IN A 10.0.3.163
+2000.example. 5M IN A 10.0.3.164
+2000.example. 5M IN A 10.0.3.165
+2000.example. 5M IN A 10.0.3.166
+2000.example. 5M IN A 10.0.3.167
+2000.example. 5M IN A 10.0.3.168
+2000.example. 5M IN A 10.0.3.169
+2000.example. 5M IN A 10.0.3.170
+2000.example. 5M IN A 10.0.3.171
+2000.example. 5M IN A 10.0.3.172
+2000.example. 5M IN A 10.0.3.173
+2000.example. 5M IN A 10.0.3.174
+2000.example. 5M IN A 10.0.3.175
+2000.example. 5M IN A 10.0.3.176
+2000.example. 5M IN A 10.0.3.177
+2000.example. 5M IN A 10.0.3.178
+2000.example. 5M IN A 10.0.3.179
+2000.example. 5M IN A 10.0.3.180
+2000.example. 5M IN A 10.0.3.181
+2000.example. 5M IN A 10.0.3.182
+2000.example. 5M IN A 10.0.3.183
+2000.example. 5M IN A 10.0.3.184
+2000.example. 5M IN A 10.0.3.185
+2000.example. 5M IN A 10.0.3.186
+2000.example. 5M IN A 10.0.3.187
+2000.example. 5M IN A 10.0.3.188
+2000.example. 5M IN A 10.0.3.189
+2000.example. 5M IN A 10.0.3.190
+2000.example. 5M IN A 10.0.3.191
+2000.example. 5M IN A 10.0.3.192
+2000.example. 5M IN A 10.0.3.193
+2000.example. 5M IN A 10.0.3.194
+2000.example. 5M IN A 10.0.3.195
+2000.example. 5M IN A 10.0.3.196
+2000.example. 5M IN A 10.0.3.197
+2000.example. 5M IN A 10.0.3.198
+2000.example. 5M IN A 10.0.3.199
+2000.example. 5M IN A 10.0.3.200
+2000.example. 5M IN A 10.0.3.201
+2000.example. 5M IN A 10.0.3.202
+2000.example. 5M IN A 10.0.3.203
+2000.example. 5M IN A 10.0.3.204
+2000.example. 5M IN A 10.0.3.205
+2000.example. 5M IN A 10.0.3.206
+2000.example. 5M IN A 10.0.3.207
+2000.example. 5M IN A 10.0.3.208
+2000.example. 5M IN A 10.0.3.209
+2000.example. 5M IN A 10.0.3.210
+2000.example. 5M IN A 10.0.3.211
+2000.example. 5M IN A 10.0.3.212
+2000.example. 5M IN A 10.0.3.213
+2000.example. 5M IN A 10.0.3.214
+2000.example. 5M IN A 10.0.3.215
+2000.example. 5M IN A 10.0.3.216
+2000.example. 5M IN A 10.0.3.217
+2000.example. 5M IN A 10.0.3.218
+2000.example. 5M IN A 10.0.3.219
+2000.example. 5M IN A 10.0.3.220
+2000.example. 5M IN A 10.0.3.221
+2000.example. 5M IN A 10.0.3.222
+2000.example. 5M IN A 10.0.3.223
+2000.example. 5M IN A 10.0.3.224
+2000.example. 5M IN A 10.0.3.225
+2000.example. 5M IN A 10.0.3.226
+2000.example. 5M IN A 10.0.3.227
+2000.example. 5M IN A 10.0.3.228
+2000.example. 5M IN A 10.0.3.229
+2000.example. 5M IN A 10.0.3.230
+2000.example. 5M IN A 10.0.3.231
+2000.example. 5M IN A 10.0.3.232
+2000.example. 5M IN A 10.0.3.233
+2000.example. 5M IN A 10.0.3.234
+2000.example. 5M IN A 10.0.3.235
+2000.example. 5M IN A 10.0.3.236
+2000.example. 5M IN A 10.0.3.237
+2000.example. 5M IN A 10.0.3.238
+2000.example. 5M IN A 10.0.3.239
+2000.example. 5M IN A 10.0.3.240
+2000.example. 5M IN A 10.0.3.241
+2000.example. 5M IN A 10.0.3.242
+2000.example. 5M IN A 10.0.3.243
+2000.example. 5M IN A 10.0.3.244
+2000.example. 5M IN A 10.0.3.245
+2000.example. 5M IN A 10.0.3.246
+2000.example. 5M IN A 10.0.3.247
+2000.example. 5M IN A 10.0.3.248
+2000.example. 5M IN A 10.0.3.249
+2000.example. 5M IN A 10.0.3.250
+2000.example. 5M IN A 10.0.3.251
+2000.example. 5M IN A 10.0.3.252
+2000.example. 5M IN A 10.0.3.253
+2000.example. 5M IN A 10.0.3.254
+2000.example. 5M IN A 10.0.3.255
+2000.example. 5M IN A 10.0.4.0
+2000.example. 5M IN A 10.0.4.1
+2000.example. 5M IN A 10.0.4.2
+2000.example. 5M IN A 10.0.4.3
+2000.example. 5M IN A 10.0.4.4
+2000.example. 5M IN A 10.0.4.5
+2000.example. 5M IN A 10.0.4.6
+2000.example. 5M IN A 10.0.4.7
+2000.example. 5M IN A 10.0.4.8
+2000.example. 5M IN A 10.0.4.9
+2000.example. 5M IN A 10.0.4.10
+2000.example. 5M IN A 10.0.4.11
+2000.example. 5M IN A 10.0.4.12
+2000.example. 5M IN A 10.0.4.13
+2000.example. 5M IN A 10.0.4.14
+2000.example. 5M IN A 10.0.4.15
+2000.example. 5M IN A 10.0.4.16
+2000.example. 5M IN A 10.0.4.17
+2000.example. 5M IN A 10.0.4.18
+2000.example. 5M IN A 10.0.4.19
+2000.example. 5M IN A 10.0.4.20
+2000.example. 5M IN A 10.0.4.21
+2000.example. 5M IN A 10.0.4.22
+2000.example. 5M IN A 10.0.4.23
+2000.example. 5M IN A 10.0.4.24
+2000.example. 5M IN A 10.0.4.25
+2000.example. 5M IN A 10.0.4.26
+2000.example. 5M IN A 10.0.4.27
+2000.example. 5M IN A 10.0.4.28
+2000.example. 5M IN A 10.0.4.29
+2000.example. 5M IN A 10.0.4.30
+2000.example. 5M IN A 10.0.4.31
+2000.example. 5M IN A 10.0.4.32
+2000.example. 5M IN A 10.0.4.33
+2000.example. 5M IN A 10.0.4.34
+2000.example. 5M IN A 10.0.4.35
+2000.example. 5M IN A 10.0.4.36
+2000.example. 5M IN A 10.0.4.37
+2000.example. 5M IN A 10.0.4.38
+2000.example. 5M IN A 10.0.4.39
+2000.example. 5M IN A 10.0.4.40
+2000.example. 5M IN A 10.0.4.41
+2000.example. 5M IN A 10.0.4.42
+2000.example. 5M IN A 10.0.4.43
+2000.example. 5M IN A 10.0.4.44
+2000.example. 5M IN A 10.0.4.45
+2000.example. 5M IN A 10.0.4.46
+2000.example. 5M IN A 10.0.4.47
+2000.example. 5M IN A 10.0.4.48
+2000.example. 5M IN A 10.0.4.49
+2000.example. 5M IN A 10.0.4.50
+2000.example. 5M IN A 10.0.4.51
+2000.example. 5M IN A 10.0.4.52
+2000.example. 5M IN A 10.0.4.53
+2000.example. 5M IN A 10.0.4.54
+2000.example. 5M IN A 10.0.4.55
+2000.example. 5M IN A 10.0.4.56
+2000.example. 5M IN A 10.0.4.57
+2000.example. 5M IN A 10.0.4.58
+2000.example. 5M IN A 10.0.4.59
+2000.example. 5M IN A 10.0.4.60
+2000.example. 5M IN A 10.0.4.61
+2000.example. 5M IN A 10.0.4.62
+2000.example. 5M IN A 10.0.4.63
+2000.example. 5M IN A 10.0.4.64
+2000.example. 5M IN A 10.0.4.65
+2000.example. 5M IN A 10.0.4.66
+2000.example. 5M IN A 10.0.4.67
+2000.example. 5M IN A 10.0.4.68
+2000.example. 5M IN A 10.0.4.69
+2000.example. 5M IN A 10.0.4.70
+2000.example. 5M IN A 10.0.4.71
+2000.example. 5M IN A 10.0.4.72
+2000.example. 5M IN A 10.0.4.73
+2000.example. 5M IN A 10.0.4.74
+2000.example. 5M IN A 10.0.4.75
+2000.example. 5M IN A 10.0.4.76
+2000.example. 5M IN A 10.0.4.77
+2000.example. 5M IN A 10.0.4.78
+2000.example. 5M IN A 10.0.4.79
+2000.example. 5M IN A 10.0.4.80
+2000.example. 5M IN A 10.0.4.81
+2000.example. 5M IN A 10.0.4.82
+2000.example. 5M IN A 10.0.4.83
+2000.example. 5M IN A 10.0.4.84
+2000.example. 5M IN A 10.0.4.85
+2000.example. 5M IN A 10.0.4.86
+2000.example. 5M IN A 10.0.4.87
+2000.example. 5M IN A 10.0.4.88
+2000.example. 5M IN A 10.0.4.89
+2000.example. 5M IN A 10.0.4.90
+2000.example. 5M IN A 10.0.4.91
+2000.example. 5M IN A 10.0.4.92
+2000.example. 5M IN A 10.0.4.93
+2000.example. 5M IN A 10.0.4.94
+2000.example. 5M IN A 10.0.4.95
+2000.example. 5M IN A 10.0.4.96
+2000.example. 5M IN A 10.0.4.97
+2000.example. 5M IN A 10.0.4.98
+2000.example. 5M IN A 10.0.4.99
+2000.example. 5M IN A 10.0.4.100
+2000.example. 5M IN A 10.0.4.101
+2000.example. 5M IN A 10.0.4.102
+2000.example. 5M IN A 10.0.4.103
+2000.example. 5M IN A 10.0.4.104
+2000.example. 5M IN A 10.0.4.105
+2000.example. 5M IN A 10.0.4.106
+2000.example. 5M IN A 10.0.4.107
+2000.example. 5M IN A 10.0.4.108
+2000.example. 5M IN A 10.0.4.109
+2000.example. 5M IN A 10.0.4.110
+2000.example. 5M IN A 10.0.4.111
+2000.example. 5M IN A 10.0.4.112
+2000.example. 5M IN A 10.0.4.113
+2000.example. 5M IN A 10.0.4.114
+2000.example. 5M IN A 10.0.4.115
+2000.example. 5M IN A 10.0.4.116
+2000.example. 5M IN A 10.0.4.117
+2000.example. 5M IN A 10.0.4.118
+2000.example. 5M IN A 10.0.4.119
+2000.example. 5M IN A 10.0.4.120
+2000.example. 5M IN A 10.0.4.121
+2000.example. 5M IN A 10.0.4.122
+2000.example. 5M IN A 10.0.4.123
+2000.example. 5M IN A 10.0.4.124
+2000.example. 5M IN A 10.0.4.125
+2000.example. 5M IN A 10.0.4.126
+2000.example. 5M IN A 10.0.4.127
+2000.example. 5M IN A 10.0.4.128
+2000.example. 5M IN A 10.0.4.129
+2000.example. 5M IN A 10.0.4.130
+2000.example. 5M IN A 10.0.4.131
+2000.example. 5M IN A 10.0.4.132
+2000.example. 5M IN A 10.0.4.133
+2000.example. 5M IN A 10.0.4.134
+2000.example. 5M IN A 10.0.4.135
+2000.example. 5M IN A 10.0.4.136
+2000.example. 5M IN A 10.0.4.137
+2000.example. 5M IN A 10.0.4.138
+2000.example. 5M IN A 10.0.4.139
+2000.example. 5M IN A 10.0.4.140
+2000.example. 5M IN A 10.0.4.141
+2000.example. 5M IN A 10.0.4.142
+2000.example. 5M IN A 10.0.4.143
+2000.example. 5M IN A 10.0.4.144
+2000.example. 5M IN A 10.0.4.145
+2000.example. 5M IN A 10.0.4.146
+2000.example. 5M IN A 10.0.4.147
+2000.example. 5M IN A 10.0.4.148
+2000.example. 5M IN A 10.0.4.149
+2000.example. 5M IN A 10.0.4.150
+2000.example. 5M IN A 10.0.4.151
+2000.example. 5M IN A 10.0.4.152
+2000.example. 5M IN A 10.0.4.153
+2000.example. 5M IN A 10.0.4.154
+2000.example. 5M IN A 10.0.4.155
+2000.example. 5M IN A 10.0.4.156
+2000.example. 5M IN A 10.0.4.157
+2000.example. 5M IN A 10.0.4.158
+2000.example. 5M IN A 10.0.4.159
+2000.example. 5M IN A 10.0.4.160
+2000.example. 5M IN A 10.0.4.161
+2000.example. 5M IN A 10.0.4.162
+2000.example. 5M IN A 10.0.4.163
+2000.example. 5M IN A 10.0.4.164
+2000.example. 5M IN A 10.0.4.165
+2000.example. 5M IN A 10.0.4.166
+2000.example. 5M IN A 10.0.4.167
+2000.example. 5M IN A 10.0.4.168
+2000.example. 5M IN A 10.0.4.169
+2000.example. 5M IN A 10.0.4.170
+2000.example. 5M IN A 10.0.4.171
+2000.example. 5M IN A 10.0.4.172
+2000.example. 5M IN A 10.0.4.173
+2000.example. 5M IN A 10.0.4.174
+2000.example. 5M IN A 10.0.4.175
+2000.example. 5M IN A 10.0.4.176
+2000.example. 5M IN A 10.0.4.177
+2000.example. 5M IN A 10.0.4.178
+2000.example. 5M IN A 10.0.4.179
+2000.example. 5M IN A 10.0.4.180
+2000.example. 5M IN A 10.0.4.181
+2000.example. 5M IN A 10.0.4.182
+2000.example. 5M IN A 10.0.4.183
+2000.example. 5M IN A 10.0.4.184
+2000.example. 5M IN A 10.0.4.185
+2000.example. 5M IN A 10.0.4.186
+2000.example. 5M IN A 10.0.4.187
+2000.example. 5M IN A 10.0.4.188
+2000.example. 5M IN A 10.0.4.189
+2000.example. 5M IN A 10.0.4.190
+2000.example. 5M IN A 10.0.4.191
+2000.example. 5M IN A 10.0.4.192
+2000.example. 5M IN A 10.0.4.193
+2000.example. 5M IN A 10.0.4.194
+2000.example. 5M IN A 10.0.4.195
+2000.example. 5M IN A 10.0.4.196
+2000.example. 5M IN A 10.0.4.197
+2000.example. 5M IN A 10.0.4.198
+2000.example. 5M IN A 10.0.4.199
+2000.example. 5M IN A 10.0.4.200
+2000.example. 5M IN A 10.0.4.201
+2000.example. 5M IN A 10.0.4.202
+2000.example. 5M IN A 10.0.4.203
+2000.example. 5M IN A 10.0.4.204
+2000.example. 5M IN A 10.0.4.205
+2000.example. 5M IN A 10.0.4.206
+2000.example. 5M IN A 10.0.4.207
+2000.example. 5M IN A 10.0.4.208
+2000.example. 5M IN A 10.0.4.209
+2000.example. 5M IN A 10.0.4.210
+2000.example. 5M IN A 10.0.4.211
+2000.example. 5M IN A 10.0.4.212
+2000.example. 5M IN A 10.0.4.213
+2000.example. 5M IN A 10.0.4.214
+2000.example. 5M IN A 10.0.4.215
+2000.example. 5M IN A 10.0.4.216
+2000.example. 5M IN A 10.0.4.217
+2000.example. 5M IN A 10.0.4.218
+2000.example. 5M IN A 10.0.4.219
+2000.example. 5M IN A 10.0.4.220
+2000.example. 5M IN A 10.0.4.221
+2000.example. 5M IN A 10.0.4.222
+2000.example. 5M IN A 10.0.4.223
+2000.example. 5M IN A 10.0.4.224
+2000.example. 5M IN A 10.0.4.225
+2000.example. 5M IN A 10.0.4.226
+2000.example. 5M IN A 10.0.4.227
+2000.example. 5M IN A 10.0.4.228
+2000.example. 5M IN A 10.0.4.229
+2000.example. 5M IN A 10.0.4.230
+2000.example. 5M IN A 10.0.4.231
+2000.example. 5M IN A 10.0.4.232
+2000.example. 5M IN A 10.0.4.233
+2000.example. 5M IN A 10.0.4.234
+2000.example. 5M IN A 10.0.4.235
+2000.example. 5M IN A 10.0.4.236
+2000.example. 5M IN A 10.0.4.237
+2000.example. 5M IN A 10.0.4.238
+2000.example. 5M IN A 10.0.4.239
+2000.example. 5M IN A 10.0.4.240
+2000.example. 5M IN A 10.0.4.241
+2000.example. 5M IN A 10.0.4.242
+2000.example. 5M IN A 10.0.4.243
+2000.example. 5M IN A 10.0.4.244
+2000.example. 5M IN A 10.0.4.245
+2000.example. 5M IN A 10.0.4.246
+2000.example. 5M IN A 10.0.4.247
+2000.example. 5M IN A 10.0.4.248
+2000.example. 5M IN A 10.0.4.249
+2000.example. 5M IN A 10.0.4.250
+2000.example. 5M IN A 10.0.4.251
+2000.example. 5M IN A 10.0.4.252
+2000.example. 5M IN A 10.0.4.253
+2000.example. 5M IN A 10.0.4.254
+2000.example. 5M IN A 10.0.4.255
+2000.example. 5M IN A 10.0.5.0
+2000.example. 5M IN A 10.0.5.1
+2000.example. 5M IN A 10.0.5.2
+2000.example. 5M IN A 10.0.5.3
+2000.example. 5M IN A 10.0.5.4
+2000.example. 5M IN A 10.0.5.5
+2000.example. 5M IN A 10.0.5.6
+2000.example. 5M IN A 10.0.5.7
+2000.example. 5M IN A 10.0.5.8
+2000.example. 5M IN A 10.0.5.9
+2000.example. 5M IN A 10.0.5.10
+2000.example. 5M IN A 10.0.5.11
+2000.example. 5M IN A 10.0.5.12
+2000.example. 5M IN A 10.0.5.13
+2000.example. 5M IN A 10.0.5.14
+2000.example. 5M IN A 10.0.5.15
+2000.example. 5M IN A 10.0.5.16
+2000.example. 5M IN A 10.0.5.17
+2000.example. 5M IN A 10.0.5.18
+2000.example. 5M IN A 10.0.5.19
+2000.example. 5M IN A 10.0.5.20
+2000.example. 5M IN A 10.0.5.21
+2000.example. 5M IN A 10.0.5.22
+2000.example. 5M IN A 10.0.5.23
+2000.example. 5M IN A 10.0.5.24
+2000.example. 5M IN A 10.0.5.25
+2000.example. 5M IN A 10.0.5.26
+2000.example. 5M IN A 10.0.5.27
+2000.example. 5M IN A 10.0.5.28
+2000.example. 5M IN A 10.0.5.29
+2000.example. 5M IN A 10.0.5.30
+2000.example. 5M IN A 10.0.5.31
+2000.example. 5M IN A 10.0.5.32
+2000.example. 5M IN A 10.0.5.33
+2000.example. 5M IN A 10.0.5.34
+2000.example. 5M IN A 10.0.5.35
+2000.example. 5M IN A 10.0.5.36
+2000.example. 5M IN A 10.0.5.37
+2000.example. 5M IN A 10.0.5.38
+2000.example. 5M IN A 10.0.5.39
+2000.example. 5M IN A 10.0.5.40
+2000.example. 5M IN A 10.0.5.41
+2000.example. 5M IN A 10.0.5.42
+2000.example. 5M IN A 10.0.5.43
+2000.example. 5M IN A 10.0.5.44
+2000.example. 5M IN A 10.0.5.45
+2000.example. 5M IN A 10.0.5.46
+2000.example. 5M IN A 10.0.5.47
+2000.example. 5M IN A 10.0.5.48
+2000.example. 5M IN A 10.0.5.49
+2000.example. 5M IN A 10.0.5.50
+2000.example. 5M IN A 10.0.5.51
+2000.example. 5M IN A 10.0.5.52
+2000.example. 5M IN A 10.0.5.53
+2000.example. 5M IN A 10.0.5.54
+2000.example. 5M IN A 10.0.5.55
+2000.example. 5M IN A 10.0.5.56
+2000.example. 5M IN A 10.0.5.57
+2000.example. 5M IN A 10.0.5.58
+2000.example. 5M IN A 10.0.5.59
+2000.example. 5M IN A 10.0.5.60
+2000.example. 5M IN A 10.0.5.61
+2000.example. 5M IN A 10.0.5.62
+2000.example. 5M IN A 10.0.5.63
+2000.example. 5M IN A 10.0.5.64
+2000.example. 5M IN A 10.0.5.65
+2000.example. 5M IN A 10.0.5.66
+2000.example. 5M IN A 10.0.5.67
+2000.example. 5M IN A 10.0.5.68
+2000.example. 5M IN A 10.0.5.69
+2000.example. 5M IN A 10.0.5.70
+2000.example. 5M IN A 10.0.5.71
+2000.example. 5M IN A 10.0.5.72
+2000.example. 5M IN A 10.0.5.73
+2000.example. 5M IN A 10.0.5.74
+2000.example. 5M IN A 10.0.5.75
+2000.example. 5M IN A 10.0.5.76
+2000.example. 5M IN A 10.0.5.77
+2000.example. 5M IN A 10.0.5.78
+2000.example. 5M IN A 10.0.5.79
+2000.example. 5M IN A 10.0.5.80
+2000.example. 5M IN A 10.0.5.81
+2000.example. 5M IN A 10.0.5.82
+2000.example. 5M IN A 10.0.5.83
+2000.example. 5M IN A 10.0.5.84
+2000.example. 5M IN A 10.0.5.85
+2000.example. 5M IN A 10.0.5.86
+2000.example. 5M IN A 10.0.5.87
+2000.example. 5M IN A 10.0.5.88
+2000.example. 5M IN A 10.0.5.89
+2000.example. 5M IN A 10.0.5.90
+2000.example. 5M IN A 10.0.5.91
+2000.example. 5M IN A 10.0.5.92
+2000.example. 5M IN A 10.0.5.93
+2000.example. 5M IN A 10.0.5.94
+2000.example. 5M IN A 10.0.5.95
+2000.example. 5M IN A 10.0.5.96
+2000.example. 5M IN A 10.0.5.97
+2000.example. 5M IN A 10.0.5.98
+2000.example. 5M IN A 10.0.5.99
+2000.example. 5M IN A 10.0.5.100
+2000.example. 5M IN A 10.0.5.101
+2000.example. 5M IN A 10.0.5.102
+2000.example. 5M IN A 10.0.5.103
+2000.example. 5M IN A 10.0.5.104
+2000.example. 5M IN A 10.0.5.105
+2000.example. 5M IN A 10.0.5.106
+2000.example. 5M IN A 10.0.5.107
+2000.example. 5M IN A 10.0.5.108
+2000.example. 5M IN A 10.0.5.109
+2000.example. 5M IN A 10.0.5.110
+2000.example. 5M IN A 10.0.5.111
+2000.example. 5M IN A 10.0.5.112
+2000.example. 5M IN A 10.0.5.113
+2000.example. 5M IN A 10.0.5.114
+2000.example. 5M IN A 10.0.5.115
+2000.example. 5M IN A 10.0.5.116
+2000.example. 5M IN A 10.0.5.117
+2000.example. 5M IN A 10.0.5.118
+2000.example. 5M IN A 10.0.5.119
+2000.example. 5M IN A 10.0.5.120
+2000.example. 5M IN A 10.0.5.121
+2000.example. 5M IN A 10.0.5.122
+2000.example. 5M IN A 10.0.5.123
+2000.example. 5M IN A 10.0.5.124
+2000.example. 5M IN A 10.0.5.125
+2000.example. 5M IN A 10.0.5.126
+2000.example. 5M IN A 10.0.5.127
+2000.example. 5M IN A 10.0.5.128
+2000.example. 5M IN A 10.0.5.129
+2000.example. 5M IN A 10.0.5.130
+2000.example. 5M IN A 10.0.5.131
+2000.example. 5M IN A 10.0.5.132
+2000.example. 5M IN A 10.0.5.133
+2000.example. 5M IN A 10.0.5.134
+2000.example. 5M IN A 10.0.5.135
+2000.example. 5M IN A 10.0.5.136
+2000.example. 5M IN A 10.0.5.137
+2000.example. 5M IN A 10.0.5.138
+2000.example. 5M IN A 10.0.5.139
+2000.example. 5M IN A 10.0.5.140
+2000.example. 5M IN A 10.0.5.141
+2000.example. 5M IN A 10.0.5.142
+2000.example. 5M IN A 10.0.5.143
+2000.example. 5M IN A 10.0.5.144
+2000.example. 5M IN A 10.0.5.145
+2000.example. 5M IN A 10.0.5.146
+2000.example. 5M IN A 10.0.5.147
+2000.example. 5M IN A 10.0.5.148
+2000.example. 5M IN A 10.0.5.149
+2000.example. 5M IN A 10.0.5.150
+2000.example. 5M IN A 10.0.5.151
+2000.example. 5M IN A 10.0.5.152
+2000.example. 5M IN A 10.0.5.153
+2000.example. 5M IN A 10.0.5.154
+2000.example. 5M IN A 10.0.5.155
+2000.example. 5M IN A 10.0.5.156
+2000.example. 5M IN A 10.0.5.157
+2000.example. 5M IN A 10.0.5.158
+2000.example. 5M IN A 10.0.5.159
+2000.example. 5M IN A 10.0.5.160
+2000.example. 5M IN A 10.0.5.161
+2000.example. 5M IN A 10.0.5.162
+2000.example. 5M IN A 10.0.5.163
+2000.example. 5M IN A 10.0.5.164
+2000.example. 5M IN A 10.0.5.165
+2000.example. 5M IN A 10.0.5.166
+2000.example. 5M IN A 10.0.5.167
+2000.example. 5M IN A 10.0.5.168
+2000.example. 5M IN A 10.0.5.169
+2000.example. 5M IN A 10.0.5.170
+2000.example. 5M IN A 10.0.5.171
+2000.example. 5M IN A 10.0.5.172
+2000.example. 5M IN A 10.0.5.173
+2000.example. 5M IN A 10.0.5.174
+2000.example. 5M IN A 10.0.5.175
+2000.example. 5M IN A 10.0.5.176
+2000.example. 5M IN A 10.0.5.177
+2000.example. 5M IN A 10.0.5.178
+2000.example. 5M IN A 10.0.5.179
+2000.example. 5M IN A 10.0.5.180
+2000.example. 5M IN A 10.0.5.181
+2000.example. 5M IN A 10.0.5.182
+2000.example. 5M IN A 10.0.5.183
+2000.example. 5M IN A 10.0.5.184
+2000.example. 5M IN A 10.0.5.185
+2000.example. 5M IN A 10.0.5.186
+2000.example. 5M IN A 10.0.5.187
+2000.example. 5M IN A 10.0.5.188
+2000.example. 5M IN A 10.0.5.189
+2000.example. 5M IN A 10.0.5.190
+2000.example. 5M IN A 10.0.5.191
+2000.example. 5M IN A 10.0.5.192
+2000.example. 5M IN A 10.0.5.193
+2000.example. 5M IN A 10.0.5.194
+2000.example. 5M IN A 10.0.5.195
+2000.example. 5M IN A 10.0.5.196
+2000.example. 5M IN A 10.0.5.197
+2000.example. 5M IN A 10.0.5.198
+2000.example. 5M IN A 10.0.5.199
+2000.example. 5M IN A 10.0.5.200
+2000.example. 5M IN A 10.0.5.201
+2000.example. 5M IN A 10.0.5.202
+2000.example. 5M IN A 10.0.5.203
+2000.example. 5M IN A 10.0.5.204
+2000.example. 5M IN A 10.0.5.205
+2000.example. 5M IN A 10.0.5.206
+2000.example. 5M IN A 10.0.5.207
+2000.example. 5M IN A 10.0.5.208
+2000.example. 5M IN A 10.0.5.209
+2000.example. 5M IN A 10.0.5.210
+2000.example. 5M IN A 10.0.5.211
+2000.example. 5M IN A 10.0.5.212
+2000.example. 5M IN A 10.0.5.213
+2000.example. 5M IN A 10.0.5.214
+2000.example. 5M IN A 10.0.5.215
+2000.example. 5M IN A 10.0.5.216
+2000.example. 5M IN A 10.0.5.217
+2000.example. 5M IN A 10.0.5.218
+2000.example. 5M IN A 10.0.5.219
+2000.example. 5M IN A 10.0.5.220
+2000.example. 5M IN A 10.0.5.221
+2000.example. 5M IN A 10.0.5.222
+2000.example. 5M IN A 10.0.5.223
+2000.example. 5M IN A 10.0.5.224
+2000.example. 5M IN A 10.0.5.225
+2000.example. 5M IN A 10.0.5.226
+2000.example. 5M IN A 10.0.5.227
+2000.example. 5M IN A 10.0.5.228
+2000.example. 5M IN A 10.0.5.229
+2000.example. 5M IN A 10.0.5.230
+2000.example. 5M IN A 10.0.5.231
+2000.example. 5M IN A 10.0.5.232
+2000.example. 5M IN A 10.0.5.233
+2000.example. 5M IN A 10.0.5.234
+2000.example. 5M IN A 10.0.5.235
+2000.example. 5M IN A 10.0.5.236
+2000.example. 5M IN A 10.0.5.237
+2000.example. 5M IN A 10.0.5.238
+2000.example. 5M IN A 10.0.5.239
+2000.example. 5M IN A 10.0.5.240
+2000.example. 5M IN A 10.0.5.241
+2000.example. 5M IN A 10.0.5.242
+2000.example. 5M IN A 10.0.5.243
+2000.example. 5M IN A 10.0.5.244
+2000.example. 5M IN A 10.0.5.245
+2000.example. 5M IN A 10.0.5.246
+2000.example. 5M IN A 10.0.5.247
+2000.example. 5M IN A 10.0.5.248
+2000.example. 5M IN A 10.0.5.249
+2000.example. 5M IN A 10.0.5.250
+2000.example. 5M IN A 10.0.5.251
+2000.example. 5M IN A 10.0.5.252
+2000.example. 5M IN A 10.0.5.253
+2000.example. 5M IN A 10.0.5.254
+2000.example. 5M IN A 10.0.5.255
+2000.example. 5M IN A 10.0.6.0
+2000.example. 5M IN A 10.0.6.1
+2000.example. 5M IN A 10.0.6.2
+2000.example. 5M IN A 10.0.6.3
+2000.example. 5M IN A 10.0.6.4
+2000.example. 5M IN A 10.0.6.5
+2000.example. 5M IN A 10.0.6.6
+2000.example. 5M IN A 10.0.6.7
+2000.example. 5M IN A 10.0.6.8
+2000.example. 5M IN A 10.0.6.9
+2000.example. 5M IN A 10.0.6.10
+2000.example. 5M IN A 10.0.6.11
+2000.example. 5M IN A 10.0.6.12
+2000.example. 5M IN A 10.0.6.13
+2000.example. 5M IN A 10.0.6.14
+2000.example. 5M IN A 10.0.6.15
+2000.example. 5M IN A 10.0.6.16
+2000.example. 5M IN A 10.0.6.17
+2000.example. 5M IN A 10.0.6.18
+2000.example. 5M IN A 10.0.6.19
+2000.example. 5M IN A 10.0.6.20
+2000.example. 5M IN A 10.0.6.21
+2000.example. 5M IN A 10.0.6.22
+2000.example. 5M IN A 10.0.6.23
+2000.example. 5M IN A 10.0.6.24
+2000.example. 5M IN A 10.0.6.25
+2000.example. 5M IN A 10.0.6.26
+2000.example. 5M IN A 10.0.6.27
+2000.example. 5M IN A 10.0.6.28
+2000.example. 5M IN A 10.0.6.29
+2000.example. 5M IN A 10.0.6.30
+2000.example. 5M IN A 10.0.6.31
+2000.example. 5M IN A 10.0.6.32
+2000.example. 5M IN A 10.0.6.33
+2000.example. 5M IN A 10.0.6.34
+2000.example. 5M IN A 10.0.6.35
+2000.example. 5M IN A 10.0.6.36
+2000.example. 5M IN A 10.0.6.37
+2000.example. 5M IN A 10.0.6.38
+2000.example. 5M IN A 10.0.6.39
+2000.example. 5M IN A 10.0.6.40
+2000.example. 5M IN A 10.0.6.41
+2000.example. 5M IN A 10.0.6.42
+2000.example. 5M IN A 10.0.6.43
+2000.example. 5M IN A 10.0.6.44
+2000.example. 5M IN A 10.0.6.45
+2000.example. 5M IN A 10.0.6.46
+2000.example. 5M IN A 10.0.6.47
+2000.example. 5M IN A 10.0.6.48
+2000.example. 5M IN A 10.0.6.49
+2000.example. 5M IN A 10.0.6.50
+2000.example. 5M IN A 10.0.6.51
+2000.example. 5M IN A 10.0.6.52
+2000.example. 5M IN A 10.0.6.53
+2000.example. 5M IN A 10.0.6.54
+2000.example. 5M IN A 10.0.6.55
+2000.example. 5M IN A 10.0.6.56
+2000.example. 5M IN A 10.0.6.57
+2000.example. 5M IN A 10.0.6.58
+2000.example. 5M IN A 10.0.6.59
+2000.example. 5M IN A 10.0.6.60
+2000.example. 5M IN A 10.0.6.61
+2000.example. 5M IN A 10.0.6.62
+2000.example. 5M IN A 10.0.6.63
+2000.example. 5M IN A 10.0.6.64
+2000.example. 5M IN A 10.0.6.65
+2000.example. 5M IN A 10.0.6.66
+2000.example. 5M IN A 10.0.6.67
+2000.example. 5M IN A 10.0.6.68
+2000.example. 5M IN A 10.0.6.69
+2000.example. 5M IN A 10.0.6.70
+2000.example. 5M IN A 10.0.6.71
+2000.example. 5M IN A 10.0.6.72
+2000.example. 5M IN A 10.0.6.73
+2000.example. 5M IN A 10.0.6.74
+2000.example. 5M IN A 10.0.6.75
+2000.example. 5M IN A 10.0.6.76
+2000.example. 5M IN A 10.0.6.77
+2000.example. 5M IN A 10.0.6.78
+2000.example. 5M IN A 10.0.6.79
+2000.example. 5M IN A 10.0.6.80
+2000.example. 5M IN A 10.0.6.81
+2000.example. 5M IN A 10.0.6.82
+2000.example. 5M IN A 10.0.6.83
+2000.example. 5M IN A 10.0.6.84
+2000.example. 5M IN A 10.0.6.85
+2000.example. 5M IN A 10.0.6.86
+2000.example. 5M IN A 10.0.6.87
+2000.example. 5M IN A 10.0.6.88
+2000.example. 5M IN A 10.0.6.89
+2000.example. 5M IN A 10.0.6.90
+2000.example. 5M IN A 10.0.6.91
+2000.example. 5M IN A 10.0.6.92
+2000.example. 5M IN A 10.0.6.93
+2000.example. 5M IN A 10.0.6.94
+2000.example. 5M IN A 10.0.6.95
+2000.example. 5M IN A 10.0.6.96
+2000.example. 5M IN A 10.0.6.97
+2000.example. 5M IN A 10.0.6.98
+2000.example. 5M IN A 10.0.6.99
+2000.example. 5M IN A 10.0.6.100
+2000.example. 5M IN A 10.0.6.101
+2000.example. 5M IN A 10.0.6.102
+2000.example. 5M IN A 10.0.6.103
+2000.example. 5M IN A 10.0.6.104
+2000.example. 5M IN A 10.0.6.105
+2000.example. 5M IN A 10.0.6.106
+2000.example. 5M IN A 10.0.6.107
+2000.example. 5M IN A 10.0.6.108
+2000.example. 5M IN A 10.0.6.109
+2000.example. 5M IN A 10.0.6.110
+2000.example. 5M IN A 10.0.6.111
+2000.example. 5M IN A 10.0.6.112
+2000.example. 5M IN A 10.0.6.113
+2000.example. 5M IN A 10.0.6.114
+2000.example. 5M IN A 10.0.6.115
+2000.example. 5M IN A 10.0.6.116
+2000.example. 5M IN A 10.0.6.117
+2000.example. 5M IN A 10.0.6.118
+2000.example. 5M IN A 10.0.6.119
+2000.example. 5M IN A 10.0.6.120
+2000.example. 5M IN A 10.0.6.121
+2000.example. 5M IN A 10.0.6.122
+2000.example. 5M IN A 10.0.6.123
+2000.example. 5M IN A 10.0.6.124
+2000.example. 5M IN A 10.0.6.125
+2000.example. 5M IN A 10.0.6.126
+2000.example. 5M IN A 10.0.6.127
+2000.example. 5M IN A 10.0.6.128
+2000.example. 5M IN A 10.0.6.129
+2000.example. 5M IN A 10.0.6.130
+2000.example. 5M IN A 10.0.6.131
+2000.example. 5M IN A 10.0.6.132
+2000.example. 5M IN A 10.0.6.133
+2000.example. 5M IN A 10.0.6.134
+2000.example. 5M IN A 10.0.6.135
+2000.example. 5M IN A 10.0.6.136
+2000.example. 5M IN A 10.0.6.137
+2000.example. 5M IN A 10.0.6.138
+2000.example. 5M IN A 10.0.6.139
+2000.example. 5M IN A 10.0.6.140
+2000.example. 5M IN A 10.0.6.141
+2000.example. 5M IN A 10.0.6.142
+2000.example. 5M IN A 10.0.6.143
+2000.example. 5M IN A 10.0.6.144
+2000.example. 5M IN A 10.0.6.145
+2000.example. 5M IN A 10.0.6.146
+2000.example. 5M IN A 10.0.6.147
+2000.example. 5M IN A 10.0.6.148
+2000.example. 5M IN A 10.0.6.149
+2000.example. 5M IN A 10.0.6.150
+2000.example. 5M IN A 10.0.6.151
+2000.example. 5M IN A 10.0.6.152
+2000.example. 5M IN A 10.0.6.153
+2000.example. 5M IN A 10.0.6.154
+2000.example. 5M IN A 10.0.6.155
+2000.example. 5M IN A 10.0.6.156
+2000.example. 5M IN A 10.0.6.157
+2000.example. 5M IN A 10.0.6.158
+2000.example. 5M IN A 10.0.6.159
+2000.example. 5M IN A 10.0.6.160
+2000.example. 5M IN A 10.0.6.161
+2000.example. 5M IN A 10.0.6.162
+2000.example. 5M IN A 10.0.6.163
+2000.example. 5M IN A 10.0.6.164
+2000.example. 5M IN A 10.0.6.165
+2000.example. 5M IN A 10.0.6.166
+2000.example. 5M IN A 10.0.6.167
+2000.example. 5M IN A 10.0.6.168
+2000.example. 5M IN A 10.0.6.169
+2000.example. 5M IN A 10.0.6.170
+2000.example. 5M IN A 10.0.6.171
+2000.example. 5M IN A 10.0.6.172
+2000.example. 5M IN A 10.0.6.173
+2000.example. 5M IN A 10.0.6.174
+2000.example. 5M IN A 10.0.6.175
+2000.example. 5M IN A 10.0.6.176
+2000.example. 5M IN A 10.0.6.177
+2000.example. 5M IN A 10.0.6.178
+2000.example. 5M IN A 10.0.6.179
+2000.example. 5M IN A 10.0.6.180
+2000.example. 5M IN A 10.0.6.181
+2000.example. 5M IN A 10.0.6.182
+2000.example. 5M IN A 10.0.6.183
+2000.example. 5M IN A 10.0.6.184
+2000.example. 5M IN A 10.0.6.185
+2000.example. 5M IN A 10.0.6.186
+2000.example. 5M IN A 10.0.6.187
+2000.example. 5M IN A 10.0.6.188
+2000.example. 5M IN A 10.0.6.189
+2000.example. 5M IN A 10.0.6.190
+2000.example. 5M IN A 10.0.6.191
+2000.example. 5M IN A 10.0.6.192
+2000.example. 5M IN A 10.0.6.193
+2000.example. 5M IN A 10.0.6.194
+2000.example. 5M IN A 10.0.6.195
+2000.example. 5M IN A 10.0.6.196
+2000.example. 5M IN A 10.0.6.197
+2000.example. 5M IN A 10.0.6.198
+2000.example. 5M IN A 10.0.6.199
+2000.example. 5M IN A 10.0.6.200
+2000.example. 5M IN A 10.0.6.201
+2000.example. 5M IN A 10.0.6.202
+2000.example. 5M IN A 10.0.6.203
+2000.example. 5M IN A 10.0.6.204
+2000.example. 5M IN A 10.0.6.205
+2000.example. 5M IN A 10.0.6.206
+2000.example. 5M IN A 10.0.6.207
+2000.example. 5M IN A 10.0.6.208
+2000.example. 5M IN A 10.0.6.209
+2000.example. 5M IN A 10.0.6.210
+2000.example. 5M IN A 10.0.6.211
+2000.example. 5M IN A 10.0.6.212
+2000.example. 5M IN A 10.0.6.213
+2000.example. 5M IN A 10.0.6.214
+2000.example. 5M IN A 10.0.6.215
+2000.example. 5M IN A 10.0.6.216
+2000.example. 5M IN A 10.0.6.217
+2000.example. 5M IN A 10.0.6.218
+2000.example. 5M IN A 10.0.6.219
+2000.example. 5M IN A 10.0.6.220
+2000.example. 5M IN A 10.0.6.221
+2000.example. 5M IN A 10.0.6.222
+2000.example. 5M IN A 10.0.6.223
+2000.example. 5M IN A 10.0.6.224
+2000.example. 5M IN A 10.0.6.225
+2000.example. 5M IN A 10.0.6.226
+2000.example. 5M IN A 10.0.6.227
+2000.example. 5M IN A 10.0.6.228
+2000.example. 5M IN A 10.0.6.229
+2000.example. 5M IN A 10.0.6.230
+2000.example. 5M IN A 10.0.6.231
+2000.example. 5M IN A 10.0.6.232
+2000.example. 5M IN A 10.0.6.233
+2000.example. 5M IN A 10.0.6.234
+2000.example. 5M IN A 10.0.6.235
+2000.example. 5M IN A 10.0.6.236
+2000.example. 5M IN A 10.0.6.237
+2000.example. 5M IN A 10.0.6.238
+2000.example. 5M IN A 10.0.6.239
+2000.example. 5M IN A 10.0.6.240
+2000.example. 5M IN A 10.0.6.241
+2000.example. 5M IN A 10.0.6.242
+2000.example. 5M IN A 10.0.6.243
+2000.example. 5M IN A 10.0.6.244
+2000.example. 5M IN A 10.0.6.245
+2000.example. 5M IN A 10.0.6.246
+2000.example. 5M IN A 10.0.6.247
+2000.example. 5M IN A 10.0.6.248
+2000.example. 5M IN A 10.0.6.249
+2000.example. 5M IN A 10.0.6.250
+2000.example. 5M IN A 10.0.6.251
+2000.example. 5M IN A 10.0.6.252
+2000.example. 5M IN A 10.0.6.253
+2000.example. 5M IN A 10.0.6.254
+2000.example. 5M IN A 10.0.6.255
+2000.example. 5M IN A 10.0.7.0
+2000.example. 5M IN A 10.0.7.1
+2000.example. 5M IN A 10.0.7.2
+2000.example. 5M IN A 10.0.7.3
+2000.example. 5M IN A 10.0.7.4
+2000.example. 5M IN A 10.0.7.5
+2000.example. 5M IN A 10.0.7.6
+2000.example. 5M IN A 10.0.7.7
+2000.example. 5M IN A 10.0.7.8
+2000.example. 5M IN A 10.0.7.9
+2000.example. 5M IN A 10.0.7.10
+2000.example. 5M IN A 10.0.7.11
+2000.example. 5M IN A 10.0.7.12
+2000.example. 5M IN A 10.0.7.13
+2000.example. 5M IN A 10.0.7.14
+2000.example. 5M IN A 10.0.7.15
+2000.example. 5M IN A 10.0.7.16
+2000.example. 5M IN A 10.0.7.17
+2000.example. 5M IN A 10.0.7.18
+2000.example. 5M IN A 10.0.7.19
+2000.example. 5M IN A 10.0.7.20
+2000.example. 5M IN A 10.0.7.21
+2000.example. 5M IN A 10.0.7.22
+2000.example. 5M IN A 10.0.7.23
+2000.example. 5M IN A 10.0.7.24
+2000.example. 5M IN A 10.0.7.25
+2000.example. 5M IN A 10.0.7.26
+2000.example. 5M IN A 10.0.7.27
+2000.example. 5M IN A 10.0.7.28
+2000.example. 5M IN A 10.0.7.29
+2000.example. 5M IN A 10.0.7.30
+2000.example. 5M IN A 10.0.7.31
+2000.example. 5M IN A 10.0.7.32
+2000.example. 5M IN A 10.0.7.33
+2000.example. 5M IN A 10.0.7.34
+2000.example. 5M IN A 10.0.7.35
+2000.example. 5M IN A 10.0.7.36
+2000.example. 5M IN A 10.0.7.37
+2000.example. 5M IN A 10.0.7.38
+2000.example. 5M IN A 10.0.7.39
+2000.example. 5M IN A 10.0.7.40
+2000.example. 5M IN A 10.0.7.41
+2000.example. 5M IN A 10.0.7.42
+2000.example. 5M IN A 10.0.7.43
+2000.example. 5M IN A 10.0.7.44
+2000.example. 5M IN A 10.0.7.45
+2000.example. 5M IN A 10.0.7.46
+2000.example. 5M IN A 10.0.7.47
+2000.example. 5M IN A 10.0.7.48
+2000.example. 5M IN A 10.0.7.49
+2000.example. 5M IN A 10.0.7.50
+2000.example. 5M IN A 10.0.7.51
+2000.example. 5M IN A 10.0.7.52
+2000.example. 5M IN A 10.0.7.53
+2000.example. 5M IN A 10.0.7.54
+2000.example. 5M IN A 10.0.7.55
+2000.example. 5M IN A 10.0.7.56
+2000.example. 5M IN A 10.0.7.57
+2000.example. 5M IN A 10.0.7.58
+2000.example. 5M IN A 10.0.7.59
+2000.example. 5M IN A 10.0.7.60
+2000.example. 5M IN A 10.0.7.61
+2000.example. 5M IN A 10.0.7.62
+2000.example. 5M IN A 10.0.7.63
+2000.example. 5M IN A 10.0.7.64
+2000.example. 5M IN A 10.0.7.65
+2000.example. 5M IN A 10.0.7.66
+2000.example. 5M IN A 10.0.7.67
+2000.example. 5M IN A 10.0.7.68
+2000.example. 5M IN A 10.0.7.69
+2000.example. 5M IN A 10.0.7.70
+2000.example. 5M IN A 10.0.7.71
+2000.example. 5M IN A 10.0.7.72
+2000.example. 5M IN A 10.0.7.73
+2000.example. 5M IN A 10.0.7.74
+2000.example. 5M IN A 10.0.7.75
+2000.example. 5M IN A 10.0.7.76
+2000.example. 5M IN A 10.0.7.77
+2000.example. 5M IN A 10.0.7.78
+2000.example. 5M IN A 10.0.7.79
+2000.example. 5M IN A 10.0.7.80
+2000.example. 5M IN A 10.0.7.81
+2000.example. 5M IN A 10.0.7.82
+2000.example. 5M IN A 10.0.7.83
+2000.example. 5M IN A 10.0.7.84
+2000.example. 5M IN A 10.0.7.85
+2000.example. 5M IN A 10.0.7.86
+2000.example. 5M IN A 10.0.7.87
+2000.example. 5M IN A 10.0.7.88
+2000.example. 5M IN A 10.0.7.89
+2000.example. 5M IN A 10.0.7.90
+2000.example. 5M IN A 10.0.7.91
+2000.example. 5M IN A 10.0.7.92
+2000.example. 5M IN A 10.0.7.93
+2000.example. 5M IN A 10.0.7.94
+2000.example. 5M IN A 10.0.7.95
+2000.example. 5M IN A 10.0.7.96
+2000.example. 5M IN A 10.0.7.97
+2000.example. 5M IN A 10.0.7.98
+2000.example. 5M IN A 10.0.7.99
+2000.example. 5M IN A 10.0.7.100
+2000.example. 5M IN A 10.0.7.101
+2000.example. 5M IN A 10.0.7.102
+2000.example. 5M IN A 10.0.7.103
+2000.example. 5M IN A 10.0.7.104
+2000.example. 5M IN A 10.0.7.105
+2000.example. 5M IN A 10.0.7.106
+2000.example. 5M IN A 10.0.7.107
+2000.example. 5M IN A 10.0.7.108
+2000.example. 5M IN A 10.0.7.109
+2000.example. 5M IN A 10.0.7.110
+2000.example. 5M IN A 10.0.7.111
+2000.example. 5M IN A 10.0.7.112
+2000.example. 5M IN A 10.0.7.113
+2000.example. 5M IN A 10.0.7.114
+2000.example. 5M IN A 10.0.7.115
+2000.example. 5M IN A 10.0.7.116
+2000.example. 5M IN A 10.0.7.117
+2000.example. 5M IN A 10.0.7.118
+2000.example. 5M IN A 10.0.7.119
+2000.example. 5M IN A 10.0.7.120
+2000.example. 5M IN A 10.0.7.121
+2000.example. 5M IN A 10.0.7.122
+2000.example. 5M IN A 10.0.7.123
+2000.example. 5M IN A 10.0.7.124
+2000.example. 5M IN A 10.0.7.125
+2000.example. 5M IN A 10.0.7.126
+2000.example. 5M IN A 10.0.7.127
+2000.example. 5M IN A 10.0.7.128
+2000.example. 5M IN A 10.0.7.129
+2000.example. 5M IN A 10.0.7.130
+2000.example. 5M IN A 10.0.7.131
+2000.example. 5M IN A 10.0.7.132
+2000.example. 5M IN A 10.0.7.133
+2000.example. 5M IN A 10.0.7.134
+2000.example. 5M IN A 10.0.7.135
+2000.example. 5M IN A 10.0.7.136
+2000.example. 5M IN A 10.0.7.137
+2000.example. 5M IN A 10.0.7.138
+2000.example. 5M IN A 10.0.7.139
+2000.example. 5M IN A 10.0.7.140
+2000.example. 5M IN A 10.0.7.141
+2000.example. 5M IN A 10.0.7.142
+2000.example. 5M IN A 10.0.7.143
+2000.example. 5M IN A 10.0.7.144
+2000.example. 5M IN A 10.0.7.145
+2000.example. 5M IN A 10.0.7.146
+2000.example. 5M IN A 10.0.7.147
+2000.example. 5M IN A 10.0.7.148
+2000.example. 5M IN A 10.0.7.149
+2000.example. 5M IN A 10.0.7.150
+2000.example. 5M IN A 10.0.7.151
+2000.example. 5M IN A 10.0.7.152
+2000.example. 5M IN A 10.0.7.153
+2000.example. 5M IN A 10.0.7.154
+2000.example. 5M IN A 10.0.7.155
+2000.example. 5M IN A 10.0.7.156
+2000.example. 5M IN A 10.0.7.157
+2000.example. 5M IN A 10.0.7.158
+2000.example. 5M IN A 10.0.7.159
+2000.example. 5M IN A 10.0.7.160
+2000.example. 5M IN A 10.0.7.161
+2000.example. 5M IN A 10.0.7.162
+2000.example. 5M IN A 10.0.7.163
+2000.example. 5M IN A 10.0.7.164
+2000.example. 5M IN A 10.0.7.165
+2000.example. 5M IN A 10.0.7.166
+2000.example. 5M IN A 10.0.7.167
+2000.example. 5M IN A 10.0.7.168
+2000.example. 5M IN A 10.0.7.169
+2000.example. 5M IN A 10.0.7.170
+2000.example. 5M IN A 10.0.7.171
+2000.example. 5M IN A 10.0.7.172
+2000.example. 5M IN A 10.0.7.173
+2000.example. 5M IN A 10.0.7.174
+2000.example. 5M IN A 10.0.7.175
+2000.example. 5M IN A 10.0.7.176
+2000.example. 5M IN A 10.0.7.177
+2000.example. 5M IN A 10.0.7.178
+2000.example. 5M IN A 10.0.7.179
+2000.example. 5M IN A 10.0.7.180
+2000.example. 5M IN A 10.0.7.181
+2000.example. 5M IN A 10.0.7.182
+2000.example. 5M IN A 10.0.7.183
+2000.example. 5M IN A 10.0.7.184
+2000.example. 5M IN A 10.0.7.185
+2000.example. 5M IN A 10.0.7.186
+2000.example. 5M IN A 10.0.7.187
+2000.example. 5M IN A 10.0.7.188
+2000.example. 5M IN A 10.0.7.189
+2000.example. 5M IN A 10.0.7.190
+2000.example. 5M IN A 10.0.7.191
+2000.example. 5M IN A 10.0.7.192
+2000.example. 5M IN A 10.0.7.193
+2000.example. 5M IN A 10.0.7.194
+2000.example. 5M IN A 10.0.7.195
+2000.example. 5M IN A 10.0.7.196
+2000.example. 5M IN A 10.0.7.197
+2000.example. 5M IN A 10.0.7.198
+2000.example. 5M IN A 10.0.7.199
+2000.example. 5M IN A 10.0.7.200
+2000.example. 5M IN A 10.0.7.201
+2000.example. 5M IN A 10.0.7.202
+2000.example. 5M IN A 10.0.7.203
+2000.example. 5M IN A 10.0.7.204
+2000.example. 5M IN A 10.0.7.205
+2000.example. 5M IN A 10.0.7.206
+2000.example. 5M IN A 10.0.7.207
+
+;; AUTHORITY SECTION:
+example. 5M IN NS ns1.example.
+
+;; ADDITIONAL SECTION:
+ns1.example. 5M IN A 10.53.0.1
+
+;; Total query time: 121 msec
+;; FROM: draco to SERVER: 10.53.0.1
+;; WHEN: Fri Jun 23 12:58:14 2000
+;; MSG SIZE sent: 30 rcvd: 32068
+
diff --git a/bin/tests/system/limits/knowngood.dig.out.3000 b/bin/tests/system/limits/knowngood.dig.out.3000
new file mode 100644
index 0000000..1932475
--- /dev/null
+++ b/bin/tests/system/limits/knowngood.dig.out.3000
@@ -0,0 +1,3023 @@
+
+; <<>> DiG 8.2 <<>> 3000.example. @10.53.0.1 a -p
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr aa rd ad; QUERY: 1, ANSWER: 3000, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; 3000.example, type = A, class = IN
+
+;; ANSWER SECTION:
+3000.example. 5M IN A 10.0.0.0
+3000.example. 5M IN A 10.0.0.1
+3000.example. 5M IN A 10.0.0.2
+3000.example. 5M IN A 10.0.0.3
+3000.example. 5M IN A 10.0.0.4
+3000.example. 5M IN A 10.0.0.5
+3000.example. 5M IN A 10.0.0.6
+3000.example. 5M IN A 10.0.0.7
+3000.example. 5M IN A 10.0.0.8
+3000.example. 5M IN A 10.0.0.9
+3000.example. 5M IN A 10.0.0.10
+3000.example. 5M IN A 10.0.0.11
+3000.example. 5M IN A 10.0.0.12
+3000.example. 5M IN A 10.0.0.13
+3000.example. 5M IN A 10.0.0.14
+3000.example. 5M IN A 10.0.0.15
+3000.example. 5M IN A 10.0.0.16
+3000.example. 5M IN A 10.0.0.17
+3000.example. 5M IN A 10.0.0.18
+3000.example. 5M IN A 10.0.0.19
+3000.example. 5M IN A 10.0.0.20
+3000.example. 5M IN A 10.0.0.21
+3000.example. 5M IN A 10.0.0.22
+3000.example. 5M IN A 10.0.0.23
+3000.example. 5M IN A 10.0.0.24
+3000.example. 5M IN A 10.0.0.25
+3000.example. 5M IN A 10.0.0.26
+3000.example. 5M IN A 10.0.0.27
+3000.example. 5M IN A 10.0.0.28
+3000.example. 5M IN A 10.0.0.29
+3000.example. 5M IN A 10.0.0.30
+3000.example. 5M IN A 10.0.0.31
+3000.example. 5M IN A 10.0.0.32
+3000.example. 5M IN A 10.0.0.33
+3000.example. 5M IN A 10.0.0.34
+3000.example. 5M IN A 10.0.0.35
+3000.example. 5M IN A 10.0.0.36
+3000.example. 5M IN A 10.0.0.37
+3000.example. 5M IN A 10.0.0.38
+3000.example. 5M IN A 10.0.0.39
+3000.example. 5M IN A 10.0.0.40
+3000.example. 5M IN A 10.0.0.41
+3000.example. 5M IN A 10.0.0.42
+3000.example. 5M IN A 10.0.0.43
+3000.example. 5M IN A 10.0.0.44
+3000.example. 5M IN A 10.0.0.45
+3000.example. 5M IN A 10.0.0.46
+3000.example. 5M IN A 10.0.0.47
+3000.example. 5M IN A 10.0.0.48
+3000.example. 5M IN A 10.0.0.49
+3000.example. 5M IN A 10.0.0.50
+3000.example. 5M IN A 10.0.0.51
+3000.example. 5M IN A 10.0.0.52
+3000.example. 5M IN A 10.0.0.53
+3000.example. 5M IN A 10.0.0.54
+3000.example. 5M IN A 10.0.0.55
+3000.example. 5M IN A 10.0.0.56
+3000.example. 5M IN A 10.0.0.57
+3000.example. 5M IN A 10.0.0.58
+3000.example. 5M IN A 10.0.0.59
+3000.example. 5M IN A 10.0.0.60
+3000.example. 5M IN A 10.0.0.61
+3000.example. 5M IN A 10.0.0.62
+3000.example. 5M IN A 10.0.0.63
+3000.example. 5M IN A 10.0.0.64
+3000.example. 5M IN A 10.0.0.65
+3000.example. 5M IN A 10.0.0.66
+3000.example. 5M IN A 10.0.0.67
+3000.example. 5M IN A 10.0.0.68
+3000.example. 5M IN A 10.0.0.69
+3000.example. 5M IN A 10.0.0.70
+3000.example. 5M IN A 10.0.0.71
+3000.example. 5M IN A 10.0.0.72
+3000.example. 5M IN A 10.0.0.73
+3000.example. 5M IN A 10.0.0.74
+3000.example. 5M IN A 10.0.0.75
+3000.example. 5M IN A 10.0.0.76
+3000.example. 5M IN A 10.0.0.77
+3000.example. 5M IN A 10.0.0.78
+3000.example. 5M IN A 10.0.0.79
+3000.example. 5M IN A 10.0.0.80
+3000.example. 5M IN A 10.0.0.81
+3000.example. 5M IN A 10.0.0.82
+3000.example. 5M IN A 10.0.0.83
+3000.example. 5M IN A 10.0.0.84
+3000.example. 5M IN A 10.0.0.85
+3000.example. 5M IN A 10.0.0.86
+3000.example. 5M IN A 10.0.0.87
+3000.example. 5M IN A 10.0.0.88
+3000.example. 5M IN A 10.0.0.89
+3000.example. 5M IN A 10.0.0.90
+3000.example. 5M IN A 10.0.0.91
+3000.example. 5M IN A 10.0.0.92
+3000.example. 5M IN A 10.0.0.93
+3000.example. 5M IN A 10.0.0.94
+3000.example. 5M IN A 10.0.0.95
+3000.example. 5M IN A 10.0.0.96
+3000.example. 5M IN A 10.0.0.97
+3000.example. 5M IN A 10.0.0.98
+3000.example. 5M IN A 10.0.0.99
+3000.example. 5M IN A 10.0.0.100
+3000.example. 5M IN A 10.0.0.101
+3000.example. 5M IN A 10.0.0.102
+3000.example. 5M IN A 10.0.0.103
+3000.example. 5M IN A 10.0.0.104
+3000.example. 5M IN A 10.0.0.105
+3000.example. 5M IN A 10.0.0.106
+3000.example. 5M IN A 10.0.0.107
+3000.example. 5M IN A 10.0.0.108
+3000.example. 5M IN A 10.0.0.109
+3000.example. 5M IN A 10.0.0.110
+3000.example. 5M IN A 10.0.0.111
+3000.example. 5M IN A 10.0.0.112
+3000.example. 5M IN A 10.0.0.113
+3000.example. 5M IN A 10.0.0.114
+3000.example. 5M IN A 10.0.0.115
+3000.example. 5M IN A 10.0.0.116
+3000.example. 5M IN A 10.0.0.117
+3000.example. 5M IN A 10.0.0.118
+3000.example. 5M IN A 10.0.0.119
+3000.example. 5M IN A 10.0.0.120
+3000.example. 5M IN A 10.0.0.121
+3000.example. 5M IN A 10.0.0.122
+3000.example. 5M IN A 10.0.0.123
+3000.example. 5M IN A 10.0.0.124
+3000.example. 5M IN A 10.0.0.125
+3000.example. 5M IN A 10.0.0.126
+3000.example. 5M IN A 10.0.0.127
+3000.example. 5M IN A 10.0.0.128
+3000.example. 5M IN A 10.0.0.129
+3000.example. 5M IN A 10.0.0.130
+3000.example. 5M IN A 10.0.0.131
+3000.example. 5M IN A 10.0.0.132
+3000.example. 5M IN A 10.0.0.133
+3000.example. 5M IN A 10.0.0.134
+3000.example. 5M IN A 10.0.0.135
+3000.example. 5M IN A 10.0.0.136
+3000.example. 5M IN A 10.0.0.137
+3000.example. 5M IN A 10.0.0.138
+3000.example. 5M IN A 10.0.0.139
+3000.example. 5M IN A 10.0.0.140
+3000.example. 5M IN A 10.0.0.141
+3000.example. 5M IN A 10.0.0.142
+3000.example. 5M IN A 10.0.0.143
+3000.example. 5M IN A 10.0.0.144
+3000.example. 5M IN A 10.0.0.145
+3000.example. 5M IN A 10.0.0.146
+3000.example. 5M IN A 10.0.0.147
+3000.example. 5M IN A 10.0.0.148
+3000.example. 5M IN A 10.0.0.149
+3000.example. 5M IN A 10.0.0.150
+3000.example. 5M IN A 10.0.0.151
+3000.example. 5M IN A 10.0.0.152
+3000.example. 5M IN A 10.0.0.153
+3000.example. 5M IN A 10.0.0.154
+3000.example. 5M IN A 10.0.0.155
+3000.example. 5M IN A 10.0.0.156
+3000.example. 5M IN A 10.0.0.157
+3000.example. 5M IN A 10.0.0.158
+3000.example. 5M IN A 10.0.0.159
+3000.example. 5M IN A 10.0.0.160
+3000.example. 5M IN A 10.0.0.161
+3000.example. 5M IN A 10.0.0.162
+3000.example. 5M IN A 10.0.0.163
+3000.example. 5M IN A 10.0.0.164
+3000.example. 5M IN A 10.0.0.165
+3000.example. 5M IN A 10.0.0.166
+3000.example. 5M IN A 10.0.0.167
+3000.example. 5M IN A 10.0.0.168
+3000.example. 5M IN A 10.0.0.169
+3000.example. 5M IN A 10.0.0.170
+3000.example. 5M IN A 10.0.0.171
+3000.example. 5M IN A 10.0.0.172
+3000.example. 5M IN A 10.0.0.173
+3000.example. 5M IN A 10.0.0.174
+3000.example. 5M IN A 10.0.0.175
+3000.example. 5M IN A 10.0.0.176
+3000.example. 5M IN A 10.0.0.177
+3000.example. 5M IN A 10.0.0.178
+3000.example. 5M IN A 10.0.0.179
+3000.example. 5M IN A 10.0.0.180
+3000.example. 5M IN A 10.0.0.181
+3000.example. 5M IN A 10.0.0.182
+3000.example. 5M IN A 10.0.0.183
+3000.example. 5M IN A 10.0.0.184
+3000.example. 5M IN A 10.0.0.185
+3000.example. 5M IN A 10.0.0.186
+3000.example. 5M IN A 10.0.0.187
+3000.example. 5M IN A 10.0.0.188
+3000.example. 5M IN A 10.0.0.189
+3000.example. 5M IN A 10.0.0.190
+3000.example. 5M IN A 10.0.0.191
+3000.example. 5M IN A 10.0.0.192
+3000.example. 5M IN A 10.0.0.193
+3000.example. 5M IN A 10.0.0.194
+3000.example. 5M IN A 10.0.0.195
+3000.example. 5M IN A 10.0.0.196
+3000.example. 5M IN A 10.0.0.197
+3000.example. 5M IN A 10.0.0.198
+3000.example. 5M IN A 10.0.0.199
+3000.example. 5M IN A 10.0.0.200
+3000.example. 5M IN A 10.0.0.201
+3000.example. 5M IN A 10.0.0.202
+3000.example. 5M IN A 10.0.0.203
+3000.example. 5M IN A 10.0.0.204
+3000.example. 5M IN A 10.0.0.205
+3000.example. 5M IN A 10.0.0.206
+3000.example. 5M IN A 10.0.0.207
+3000.example. 5M IN A 10.0.0.208
+3000.example. 5M IN A 10.0.0.209
+3000.example. 5M IN A 10.0.0.210
+3000.example. 5M IN A 10.0.0.211
+3000.example. 5M IN A 10.0.0.212
+3000.example. 5M IN A 10.0.0.213
+3000.example. 5M IN A 10.0.0.214
+3000.example. 5M IN A 10.0.0.215
+3000.example. 5M IN A 10.0.0.216
+3000.example. 5M IN A 10.0.0.217
+3000.example. 5M IN A 10.0.0.218
+3000.example. 5M IN A 10.0.0.219
+3000.example. 5M IN A 10.0.0.220
+3000.example. 5M IN A 10.0.0.221
+3000.example. 5M IN A 10.0.0.222
+3000.example. 5M IN A 10.0.0.223
+3000.example. 5M IN A 10.0.0.224
+3000.example. 5M IN A 10.0.0.225
+3000.example. 5M IN A 10.0.0.226
+3000.example. 5M IN A 10.0.0.227
+3000.example. 5M IN A 10.0.0.228
+3000.example. 5M IN A 10.0.0.229
+3000.example. 5M IN A 10.0.0.230
+3000.example. 5M IN A 10.0.0.231
+3000.example. 5M IN A 10.0.0.232
+3000.example. 5M IN A 10.0.0.233
+3000.example. 5M IN A 10.0.0.234
+3000.example. 5M IN A 10.0.0.235
+3000.example. 5M IN A 10.0.0.236
+3000.example. 5M IN A 10.0.0.237
+3000.example. 5M IN A 10.0.0.238
+3000.example. 5M IN A 10.0.0.239
+3000.example. 5M IN A 10.0.0.240
+3000.example. 5M IN A 10.0.0.241
+3000.example. 5M IN A 10.0.0.242
+3000.example. 5M IN A 10.0.0.243
+3000.example. 5M IN A 10.0.0.244
+3000.example. 5M IN A 10.0.0.245
+3000.example. 5M IN A 10.0.0.246
+3000.example. 5M IN A 10.0.0.247
+3000.example. 5M IN A 10.0.0.248
+3000.example. 5M IN A 10.0.0.249
+3000.example. 5M IN A 10.0.0.250
+3000.example. 5M IN A 10.0.0.251
+3000.example. 5M IN A 10.0.0.252
+3000.example. 5M IN A 10.0.0.253
+3000.example. 5M IN A 10.0.0.254
+3000.example. 5M IN A 10.0.0.255
+3000.example. 5M IN A 10.0.1.0
+3000.example. 5M IN A 10.0.1.1
+3000.example. 5M IN A 10.0.1.2
+3000.example. 5M IN A 10.0.1.3
+3000.example. 5M IN A 10.0.1.4
+3000.example. 5M IN A 10.0.1.5
+3000.example. 5M IN A 10.0.1.6
+3000.example. 5M IN A 10.0.1.7
+3000.example. 5M IN A 10.0.1.8
+3000.example. 5M IN A 10.0.1.9
+3000.example. 5M IN A 10.0.1.10
+3000.example. 5M IN A 10.0.1.11
+3000.example. 5M IN A 10.0.1.12
+3000.example. 5M IN A 10.0.1.13
+3000.example. 5M IN A 10.0.1.14
+3000.example. 5M IN A 10.0.1.15
+3000.example. 5M IN A 10.0.1.16
+3000.example. 5M IN A 10.0.1.17
+3000.example. 5M IN A 10.0.1.18
+3000.example. 5M IN A 10.0.1.19
+3000.example. 5M IN A 10.0.1.20
+3000.example. 5M IN A 10.0.1.21
+3000.example. 5M IN A 10.0.1.22
+3000.example. 5M IN A 10.0.1.23
+3000.example. 5M IN A 10.0.1.24
+3000.example. 5M IN A 10.0.1.25
+3000.example. 5M IN A 10.0.1.26
+3000.example. 5M IN A 10.0.1.27
+3000.example. 5M IN A 10.0.1.28
+3000.example. 5M IN A 10.0.1.29
+3000.example. 5M IN A 10.0.1.30
+3000.example. 5M IN A 10.0.1.31
+3000.example. 5M IN A 10.0.1.32
+3000.example. 5M IN A 10.0.1.33
+3000.example. 5M IN A 10.0.1.34
+3000.example. 5M IN A 10.0.1.35
+3000.example. 5M IN A 10.0.1.36
+3000.example. 5M IN A 10.0.1.37
+3000.example. 5M IN A 10.0.1.38
+3000.example. 5M IN A 10.0.1.39
+3000.example. 5M IN A 10.0.1.40
+3000.example. 5M IN A 10.0.1.41
+3000.example. 5M IN A 10.0.1.42
+3000.example. 5M IN A 10.0.1.43
+3000.example. 5M IN A 10.0.1.44
+3000.example. 5M IN A 10.0.1.45
+3000.example. 5M IN A 10.0.1.46
+3000.example. 5M IN A 10.0.1.47
+3000.example. 5M IN A 10.0.1.48
+3000.example. 5M IN A 10.0.1.49
+3000.example. 5M IN A 10.0.1.50
+3000.example. 5M IN A 10.0.1.51
+3000.example. 5M IN A 10.0.1.52
+3000.example. 5M IN A 10.0.1.53
+3000.example. 5M IN A 10.0.1.54
+3000.example. 5M IN A 10.0.1.55
+3000.example. 5M IN A 10.0.1.56
+3000.example. 5M IN A 10.0.1.57
+3000.example. 5M IN A 10.0.1.58
+3000.example. 5M IN A 10.0.1.59
+3000.example. 5M IN A 10.0.1.60
+3000.example. 5M IN A 10.0.1.61
+3000.example. 5M IN A 10.0.1.62
+3000.example. 5M IN A 10.0.1.63
+3000.example. 5M IN A 10.0.1.64
+3000.example. 5M IN A 10.0.1.65
+3000.example. 5M IN A 10.0.1.66
+3000.example. 5M IN A 10.0.1.67
+3000.example. 5M IN A 10.0.1.68
+3000.example. 5M IN A 10.0.1.69
+3000.example. 5M IN A 10.0.1.70
+3000.example. 5M IN A 10.0.1.71
+3000.example. 5M IN A 10.0.1.72
+3000.example. 5M IN A 10.0.1.73
+3000.example. 5M IN A 10.0.1.74
+3000.example. 5M IN A 10.0.1.75
+3000.example. 5M IN A 10.0.1.76
+3000.example. 5M IN A 10.0.1.77
+3000.example. 5M IN A 10.0.1.78
+3000.example. 5M IN A 10.0.1.79
+3000.example. 5M IN A 10.0.1.80
+3000.example. 5M IN A 10.0.1.81
+3000.example. 5M IN A 10.0.1.82
+3000.example. 5M IN A 10.0.1.83
+3000.example. 5M IN A 10.0.1.84
+3000.example. 5M IN A 10.0.1.85
+3000.example. 5M IN A 10.0.1.86
+3000.example. 5M IN A 10.0.1.87
+3000.example. 5M IN A 10.0.1.88
+3000.example. 5M IN A 10.0.1.89
+3000.example. 5M IN A 10.0.1.90
+3000.example. 5M IN A 10.0.1.91
+3000.example. 5M IN A 10.0.1.92
+3000.example. 5M IN A 10.0.1.93
+3000.example. 5M IN A 10.0.1.94
+3000.example. 5M IN A 10.0.1.95
+3000.example. 5M IN A 10.0.1.96
+3000.example. 5M IN A 10.0.1.97
+3000.example. 5M IN A 10.0.1.98
+3000.example. 5M IN A 10.0.1.99
+3000.example. 5M IN A 10.0.1.100
+3000.example. 5M IN A 10.0.1.101
+3000.example. 5M IN A 10.0.1.102
+3000.example. 5M IN A 10.0.1.103
+3000.example. 5M IN A 10.0.1.104
+3000.example. 5M IN A 10.0.1.105
+3000.example. 5M IN A 10.0.1.106
+3000.example. 5M IN A 10.0.1.107
+3000.example. 5M IN A 10.0.1.108
+3000.example. 5M IN A 10.0.1.109
+3000.example. 5M IN A 10.0.1.110
+3000.example. 5M IN A 10.0.1.111
+3000.example. 5M IN A 10.0.1.112
+3000.example. 5M IN A 10.0.1.113
+3000.example. 5M IN A 10.0.1.114
+3000.example. 5M IN A 10.0.1.115
+3000.example. 5M IN A 10.0.1.116
+3000.example. 5M IN A 10.0.1.117
+3000.example. 5M IN A 10.0.1.118
+3000.example. 5M IN A 10.0.1.119
+3000.example. 5M IN A 10.0.1.120
+3000.example. 5M IN A 10.0.1.121
+3000.example. 5M IN A 10.0.1.122
+3000.example. 5M IN A 10.0.1.123
+3000.example. 5M IN A 10.0.1.124
+3000.example. 5M IN A 10.0.1.125
+3000.example. 5M IN A 10.0.1.126
+3000.example. 5M IN A 10.0.1.127
+3000.example. 5M IN A 10.0.1.128
+3000.example. 5M IN A 10.0.1.129
+3000.example. 5M IN A 10.0.1.130
+3000.example. 5M IN A 10.0.1.131
+3000.example. 5M IN A 10.0.1.132
+3000.example. 5M IN A 10.0.1.133
+3000.example. 5M IN A 10.0.1.134
+3000.example. 5M IN A 10.0.1.135
+3000.example. 5M IN A 10.0.1.136
+3000.example. 5M IN A 10.0.1.137
+3000.example. 5M IN A 10.0.1.138
+3000.example. 5M IN A 10.0.1.139
+3000.example. 5M IN A 10.0.1.140
+3000.example. 5M IN A 10.0.1.141
+3000.example. 5M IN A 10.0.1.142
+3000.example. 5M IN A 10.0.1.143
+3000.example. 5M IN A 10.0.1.144
+3000.example. 5M IN A 10.0.1.145
+3000.example. 5M IN A 10.0.1.146
+3000.example. 5M IN A 10.0.1.147
+3000.example. 5M IN A 10.0.1.148
+3000.example. 5M IN A 10.0.1.149
+3000.example. 5M IN A 10.0.1.150
+3000.example. 5M IN A 10.0.1.151
+3000.example. 5M IN A 10.0.1.152
+3000.example. 5M IN A 10.0.1.153
+3000.example. 5M IN A 10.0.1.154
+3000.example. 5M IN A 10.0.1.155
+3000.example. 5M IN A 10.0.1.156
+3000.example. 5M IN A 10.0.1.157
+3000.example. 5M IN A 10.0.1.158
+3000.example. 5M IN A 10.0.1.159
+3000.example. 5M IN A 10.0.1.160
+3000.example. 5M IN A 10.0.1.161
+3000.example. 5M IN A 10.0.1.162
+3000.example. 5M IN A 10.0.1.163
+3000.example. 5M IN A 10.0.1.164
+3000.example. 5M IN A 10.0.1.165
+3000.example. 5M IN A 10.0.1.166
+3000.example. 5M IN A 10.0.1.167
+3000.example. 5M IN A 10.0.1.168
+3000.example. 5M IN A 10.0.1.169
+3000.example. 5M IN A 10.0.1.170
+3000.example. 5M IN A 10.0.1.171
+3000.example. 5M IN A 10.0.1.172
+3000.example. 5M IN A 10.0.1.173
+3000.example. 5M IN A 10.0.1.174
+3000.example. 5M IN A 10.0.1.175
+3000.example. 5M IN A 10.0.1.176
+3000.example. 5M IN A 10.0.1.177
+3000.example. 5M IN A 10.0.1.178
+3000.example. 5M IN A 10.0.1.179
+3000.example. 5M IN A 10.0.1.180
+3000.example. 5M IN A 10.0.1.181
+3000.example. 5M IN A 10.0.1.182
+3000.example. 5M IN A 10.0.1.183
+3000.example. 5M IN A 10.0.1.184
+3000.example. 5M IN A 10.0.1.185
+3000.example. 5M IN A 10.0.1.186
+3000.example. 5M IN A 10.0.1.187
+3000.example. 5M IN A 10.0.1.188
+3000.example. 5M IN A 10.0.1.189
+3000.example. 5M IN A 10.0.1.190
+3000.example. 5M IN A 10.0.1.191
+3000.example. 5M IN A 10.0.1.192
+3000.example. 5M IN A 10.0.1.193
+3000.example. 5M IN A 10.0.1.194
+3000.example. 5M IN A 10.0.1.195
+3000.example. 5M IN A 10.0.1.196
+3000.example. 5M IN A 10.0.1.197
+3000.example. 5M IN A 10.0.1.198
+3000.example. 5M IN A 10.0.1.199
+3000.example. 5M IN A 10.0.1.200
+3000.example. 5M IN A 10.0.1.201
+3000.example. 5M IN A 10.0.1.202
+3000.example. 5M IN A 10.0.1.203
+3000.example. 5M IN A 10.0.1.204
+3000.example. 5M IN A 10.0.1.205
+3000.example. 5M IN A 10.0.1.206
+3000.example. 5M IN A 10.0.1.207
+3000.example. 5M IN A 10.0.1.208
+3000.example. 5M IN A 10.0.1.209
+3000.example. 5M IN A 10.0.1.210
+3000.example. 5M IN A 10.0.1.211
+3000.example. 5M IN A 10.0.1.212
+3000.example. 5M IN A 10.0.1.213
+3000.example. 5M IN A 10.0.1.214
+3000.example. 5M IN A 10.0.1.215
+3000.example. 5M IN A 10.0.1.216
+3000.example. 5M IN A 10.0.1.217
+3000.example. 5M IN A 10.0.1.218
+3000.example. 5M IN A 10.0.1.219
+3000.example. 5M IN A 10.0.1.220
+3000.example. 5M IN A 10.0.1.221
+3000.example. 5M IN A 10.0.1.222
+3000.example. 5M IN A 10.0.1.223
+3000.example. 5M IN A 10.0.1.224
+3000.example. 5M IN A 10.0.1.225
+3000.example. 5M IN A 10.0.1.226
+3000.example. 5M IN A 10.0.1.227
+3000.example. 5M IN A 10.0.1.228
+3000.example. 5M IN A 10.0.1.229
+3000.example. 5M IN A 10.0.1.230
+3000.example. 5M IN A 10.0.1.231
+3000.example. 5M IN A 10.0.1.232
+3000.example. 5M IN A 10.0.1.233
+3000.example. 5M IN A 10.0.1.234
+3000.example. 5M IN A 10.0.1.235
+3000.example. 5M IN A 10.0.1.236
+3000.example. 5M IN A 10.0.1.237
+3000.example. 5M IN A 10.0.1.238
+3000.example. 5M IN A 10.0.1.239
+3000.example. 5M IN A 10.0.1.240
+3000.example. 5M IN A 10.0.1.241
+3000.example. 5M IN A 10.0.1.242
+3000.example. 5M IN A 10.0.1.243
+3000.example. 5M IN A 10.0.1.244
+3000.example. 5M IN A 10.0.1.245
+3000.example. 5M IN A 10.0.1.246
+3000.example. 5M IN A 10.0.1.247
+3000.example. 5M IN A 10.0.1.248
+3000.example. 5M IN A 10.0.1.249
+3000.example. 5M IN A 10.0.1.250
+3000.example. 5M IN A 10.0.1.251
+3000.example. 5M IN A 10.0.1.252
+3000.example. 5M IN A 10.0.1.253
+3000.example. 5M IN A 10.0.1.254
+3000.example. 5M IN A 10.0.1.255
+3000.example. 5M IN A 10.0.2.0
+3000.example. 5M IN A 10.0.2.1
+3000.example. 5M IN A 10.0.2.2
+3000.example. 5M IN A 10.0.2.3
+3000.example. 5M IN A 10.0.2.4
+3000.example. 5M IN A 10.0.2.5
+3000.example. 5M IN A 10.0.2.6
+3000.example. 5M IN A 10.0.2.7
+3000.example. 5M IN A 10.0.2.8
+3000.example. 5M IN A 10.0.2.9
+3000.example. 5M IN A 10.0.2.10
+3000.example. 5M IN A 10.0.2.11
+3000.example. 5M IN A 10.0.2.12
+3000.example. 5M IN A 10.0.2.13
+3000.example. 5M IN A 10.0.2.14
+3000.example. 5M IN A 10.0.2.15
+3000.example. 5M IN A 10.0.2.16
+3000.example. 5M IN A 10.0.2.17
+3000.example. 5M IN A 10.0.2.18
+3000.example. 5M IN A 10.0.2.19
+3000.example. 5M IN A 10.0.2.20
+3000.example. 5M IN A 10.0.2.21
+3000.example. 5M IN A 10.0.2.22
+3000.example. 5M IN A 10.0.2.23
+3000.example. 5M IN A 10.0.2.24
+3000.example. 5M IN A 10.0.2.25
+3000.example. 5M IN A 10.0.2.26
+3000.example. 5M IN A 10.0.2.27
+3000.example. 5M IN A 10.0.2.28
+3000.example. 5M IN A 10.0.2.29
+3000.example. 5M IN A 10.0.2.30
+3000.example. 5M IN A 10.0.2.31
+3000.example. 5M IN A 10.0.2.32
+3000.example. 5M IN A 10.0.2.33
+3000.example. 5M IN A 10.0.2.34
+3000.example. 5M IN A 10.0.2.35
+3000.example. 5M IN A 10.0.2.36
+3000.example. 5M IN A 10.0.2.37
+3000.example. 5M IN A 10.0.2.38
+3000.example. 5M IN A 10.0.2.39
+3000.example. 5M IN A 10.0.2.40
+3000.example. 5M IN A 10.0.2.41
+3000.example. 5M IN A 10.0.2.42
+3000.example. 5M IN A 10.0.2.43
+3000.example. 5M IN A 10.0.2.44
+3000.example. 5M IN A 10.0.2.45
+3000.example. 5M IN A 10.0.2.46
+3000.example. 5M IN A 10.0.2.47
+3000.example. 5M IN A 10.0.2.48
+3000.example. 5M IN A 10.0.2.49
+3000.example. 5M IN A 10.0.2.50
+3000.example. 5M IN A 10.0.2.51
+3000.example. 5M IN A 10.0.2.52
+3000.example. 5M IN A 10.0.2.53
+3000.example. 5M IN A 10.0.2.54
+3000.example. 5M IN A 10.0.2.55
+3000.example. 5M IN A 10.0.2.56
+3000.example. 5M IN A 10.0.2.57
+3000.example. 5M IN A 10.0.2.58
+3000.example. 5M IN A 10.0.2.59
+3000.example. 5M IN A 10.0.2.60
+3000.example. 5M IN A 10.0.2.61
+3000.example. 5M IN A 10.0.2.62
+3000.example. 5M IN A 10.0.2.63
+3000.example. 5M IN A 10.0.2.64
+3000.example. 5M IN A 10.0.2.65
+3000.example. 5M IN A 10.0.2.66
+3000.example. 5M IN A 10.0.2.67
+3000.example. 5M IN A 10.0.2.68
+3000.example. 5M IN A 10.0.2.69
+3000.example. 5M IN A 10.0.2.70
+3000.example. 5M IN A 10.0.2.71
+3000.example. 5M IN A 10.0.2.72
+3000.example. 5M IN A 10.0.2.73
+3000.example. 5M IN A 10.0.2.74
+3000.example. 5M IN A 10.0.2.75
+3000.example. 5M IN A 10.0.2.76
+3000.example. 5M IN A 10.0.2.77
+3000.example. 5M IN A 10.0.2.78
+3000.example. 5M IN A 10.0.2.79
+3000.example. 5M IN A 10.0.2.80
+3000.example. 5M IN A 10.0.2.81
+3000.example. 5M IN A 10.0.2.82
+3000.example. 5M IN A 10.0.2.83
+3000.example. 5M IN A 10.0.2.84
+3000.example. 5M IN A 10.0.2.85
+3000.example. 5M IN A 10.0.2.86
+3000.example. 5M IN A 10.0.2.87
+3000.example. 5M IN A 10.0.2.88
+3000.example. 5M IN A 10.0.2.89
+3000.example. 5M IN A 10.0.2.90
+3000.example. 5M IN A 10.0.2.91
+3000.example. 5M IN A 10.0.2.92
+3000.example. 5M IN A 10.0.2.93
+3000.example. 5M IN A 10.0.2.94
+3000.example. 5M IN A 10.0.2.95
+3000.example. 5M IN A 10.0.2.96
+3000.example. 5M IN A 10.0.2.97
+3000.example. 5M IN A 10.0.2.98
+3000.example. 5M IN A 10.0.2.99
+3000.example. 5M IN A 10.0.2.100
+3000.example. 5M IN A 10.0.2.101
+3000.example. 5M IN A 10.0.2.102
+3000.example. 5M IN A 10.0.2.103
+3000.example. 5M IN A 10.0.2.104
+3000.example. 5M IN A 10.0.2.105
+3000.example. 5M IN A 10.0.2.106
+3000.example. 5M IN A 10.0.2.107
+3000.example. 5M IN A 10.0.2.108
+3000.example. 5M IN A 10.0.2.109
+3000.example. 5M IN A 10.0.2.110
+3000.example. 5M IN A 10.0.2.111
+3000.example. 5M IN A 10.0.2.112
+3000.example. 5M IN A 10.0.2.113
+3000.example. 5M IN A 10.0.2.114
+3000.example. 5M IN A 10.0.2.115
+3000.example. 5M IN A 10.0.2.116
+3000.example. 5M IN A 10.0.2.117
+3000.example. 5M IN A 10.0.2.118
+3000.example. 5M IN A 10.0.2.119
+3000.example. 5M IN A 10.0.2.120
+3000.example. 5M IN A 10.0.2.121
+3000.example. 5M IN A 10.0.2.122
+3000.example. 5M IN A 10.0.2.123
+3000.example. 5M IN A 10.0.2.124
+3000.example. 5M IN A 10.0.2.125
+3000.example. 5M IN A 10.0.2.126
+3000.example. 5M IN A 10.0.2.127
+3000.example. 5M IN A 10.0.2.128
+3000.example. 5M IN A 10.0.2.129
+3000.example. 5M IN A 10.0.2.130
+3000.example. 5M IN A 10.0.2.131
+3000.example. 5M IN A 10.0.2.132
+3000.example. 5M IN A 10.0.2.133
+3000.example. 5M IN A 10.0.2.134
+3000.example. 5M IN A 10.0.2.135
+3000.example. 5M IN A 10.0.2.136
+3000.example. 5M IN A 10.0.2.137
+3000.example. 5M IN A 10.0.2.138
+3000.example. 5M IN A 10.0.2.139
+3000.example. 5M IN A 10.0.2.140
+3000.example. 5M IN A 10.0.2.141
+3000.example. 5M IN A 10.0.2.142
+3000.example. 5M IN A 10.0.2.143
+3000.example. 5M IN A 10.0.2.144
+3000.example. 5M IN A 10.0.2.145
+3000.example. 5M IN A 10.0.2.146
+3000.example. 5M IN A 10.0.2.147
+3000.example. 5M IN A 10.0.2.148
+3000.example. 5M IN A 10.0.2.149
+3000.example. 5M IN A 10.0.2.150
+3000.example. 5M IN A 10.0.2.151
+3000.example. 5M IN A 10.0.2.152
+3000.example. 5M IN A 10.0.2.153
+3000.example. 5M IN A 10.0.2.154
+3000.example. 5M IN A 10.0.2.155
+3000.example. 5M IN A 10.0.2.156
+3000.example. 5M IN A 10.0.2.157
+3000.example. 5M IN A 10.0.2.158
+3000.example. 5M IN A 10.0.2.159
+3000.example. 5M IN A 10.0.2.160
+3000.example. 5M IN A 10.0.2.161
+3000.example. 5M IN A 10.0.2.162
+3000.example. 5M IN A 10.0.2.163
+3000.example. 5M IN A 10.0.2.164
+3000.example. 5M IN A 10.0.2.165
+3000.example. 5M IN A 10.0.2.166
+3000.example. 5M IN A 10.0.2.167
+3000.example. 5M IN A 10.0.2.168
+3000.example. 5M IN A 10.0.2.169
+3000.example. 5M IN A 10.0.2.170
+3000.example. 5M IN A 10.0.2.171
+3000.example. 5M IN A 10.0.2.172
+3000.example. 5M IN A 10.0.2.173
+3000.example. 5M IN A 10.0.2.174
+3000.example. 5M IN A 10.0.2.175
+3000.example. 5M IN A 10.0.2.176
+3000.example. 5M IN A 10.0.2.177
+3000.example. 5M IN A 10.0.2.178
+3000.example. 5M IN A 10.0.2.179
+3000.example. 5M IN A 10.0.2.180
+3000.example. 5M IN A 10.0.2.181
+3000.example. 5M IN A 10.0.2.182
+3000.example. 5M IN A 10.0.2.183
+3000.example. 5M IN A 10.0.2.184
+3000.example. 5M IN A 10.0.2.185
+3000.example. 5M IN A 10.0.2.186
+3000.example. 5M IN A 10.0.2.187
+3000.example. 5M IN A 10.0.2.188
+3000.example. 5M IN A 10.0.2.189
+3000.example. 5M IN A 10.0.2.190
+3000.example. 5M IN A 10.0.2.191
+3000.example. 5M IN A 10.0.2.192
+3000.example. 5M IN A 10.0.2.193
+3000.example. 5M IN A 10.0.2.194
+3000.example. 5M IN A 10.0.2.195
+3000.example. 5M IN A 10.0.2.196
+3000.example. 5M IN A 10.0.2.197
+3000.example. 5M IN A 10.0.2.198
+3000.example. 5M IN A 10.0.2.199
+3000.example. 5M IN A 10.0.2.200
+3000.example. 5M IN A 10.0.2.201
+3000.example. 5M IN A 10.0.2.202
+3000.example. 5M IN A 10.0.2.203
+3000.example. 5M IN A 10.0.2.204
+3000.example. 5M IN A 10.0.2.205
+3000.example. 5M IN A 10.0.2.206
+3000.example. 5M IN A 10.0.2.207
+3000.example. 5M IN A 10.0.2.208
+3000.example. 5M IN A 10.0.2.209
+3000.example. 5M IN A 10.0.2.210
+3000.example. 5M IN A 10.0.2.211
+3000.example. 5M IN A 10.0.2.212
+3000.example. 5M IN A 10.0.2.213
+3000.example. 5M IN A 10.0.2.214
+3000.example. 5M IN A 10.0.2.215
+3000.example. 5M IN A 10.0.2.216
+3000.example. 5M IN A 10.0.2.217
+3000.example. 5M IN A 10.0.2.218
+3000.example. 5M IN A 10.0.2.219
+3000.example. 5M IN A 10.0.2.220
+3000.example. 5M IN A 10.0.2.221
+3000.example. 5M IN A 10.0.2.222
+3000.example. 5M IN A 10.0.2.223
+3000.example. 5M IN A 10.0.2.224
+3000.example. 5M IN A 10.0.2.225
+3000.example. 5M IN A 10.0.2.226
+3000.example. 5M IN A 10.0.2.227
+3000.example. 5M IN A 10.0.2.228
+3000.example. 5M IN A 10.0.2.229
+3000.example. 5M IN A 10.0.2.230
+3000.example. 5M IN A 10.0.2.231
+3000.example. 5M IN A 10.0.2.232
+3000.example. 5M IN A 10.0.2.233
+3000.example. 5M IN A 10.0.2.234
+3000.example. 5M IN A 10.0.2.235
+3000.example. 5M IN A 10.0.2.236
+3000.example. 5M IN A 10.0.2.237
+3000.example. 5M IN A 10.0.2.238
+3000.example. 5M IN A 10.0.2.239
+3000.example. 5M IN A 10.0.2.240
+3000.example. 5M IN A 10.0.2.241
+3000.example. 5M IN A 10.0.2.242
+3000.example. 5M IN A 10.0.2.243
+3000.example. 5M IN A 10.0.2.244
+3000.example. 5M IN A 10.0.2.245
+3000.example. 5M IN A 10.0.2.246
+3000.example. 5M IN A 10.0.2.247
+3000.example. 5M IN A 10.0.2.248
+3000.example. 5M IN A 10.0.2.249
+3000.example. 5M IN A 10.0.2.250
+3000.example. 5M IN A 10.0.2.251
+3000.example. 5M IN A 10.0.2.252
+3000.example. 5M IN A 10.0.2.253
+3000.example. 5M IN A 10.0.2.254
+3000.example. 5M IN A 10.0.2.255
+3000.example. 5M IN A 10.0.3.0
+3000.example. 5M IN A 10.0.3.1
+3000.example. 5M IN A 10.0.3.2
+3000.example. 5M IN A 10.0.3.3
+3000.example. 5M IN A 10.0.3.4
+3000.example. 5M IN A 10.0.3.5
+3000.example. 5M IN A 10.0.3.6
+3000.example. 5M IN A 10.0.3.7
+3000.example. 5M IN A 10.0.3.8
+3000.example. 5M IN A 10.0.3.9
+3000.example. 5M IN A 10.0.3.10
+3000.example. 5M IN A 10.0.3.11
+3000.example. 5M IN A 10.0.3.12
+3000.example. 5M IN A 10.0.3.13
+3000.example. 5M IN A 10.0.3.14
+3000.example. 5M IN A 10.0.3.15
+3000.example. 5M IN A 10.0.3.16
+3000.example. 5M IN A 10.0.3.17
+3000.example. 5M IN A 10.0.3.18
+3000.example. 5M IN A 10.0.3.19
+3000.example. 5M IN A 10.0.3.20
+3000.example. 5M IN A 10.0.3.21
+3000.example. 5M IN A 10.0.3.22
+3000.example. 5M IN A 10.0.3.23
+3000.example. 5M IN A 10.0.3.24
+3000.example. 5M IN A 10.0.3.25
+3000.example. 5M IN A 10.0.3.26
+3000.example. 5M IN A 10.0.3.27
+3000.example. 5M IN A 10.0.3.28
+3000.example. 5M IN A 10.0.3.29
+3000.example. 5M IN A 10.0.3.30
+3000.example. 5M IN A 10.0.3.31
+3000.example. 5M IN A 10.0.3.32
+3000.example. 5M IN A 10.0.3.33
+3000.example. 5M IN A 10.0.3.34
+3000.example. 5M IN A 10.0.3.35
+3000.example. 5M IN A 10.0.3.36
+3000.example. 5M IN A 10.0.3.37
+3000.example. 5M IN A 10.0.3.38
+3000.example. 5M IN A 10.0.3.39
+3000.example. 5M IN A 10.0.3.40
+3000.example. 5M IN A 10.0.3.41
+3000.example. 5M IN A 10.0.3.42
+3000.example. 5M IN A 10.0.3.43
+3000.example. 5M IN A 10.0.3.44
+3000.example. 5M IN A 10.0.3.45
+3000.example. 5M IN A 10.0.3.46
+3000.example. 5M IN A 10.0.3.47
+3000.example. 5M IN A 10.0.3.48
+3000.example. 5M IN A 10.0.3.49
+3000.example. 5M IN A 10.0.3.50
+3000.example. 5M IN A 10.0.3.51
+3000.example. 5M IN A 10.0.3.52
+3000.example. 5M IN A 10.0.3.53
+3000.example. 5M IN A 10.0.3.54
+3000.example. 5M IN A 10.0.3.55
+3000.example. 5M IN A 10.0.3.56
+3000.example. 5M IN A 10.0.3.57
+3000.example. 5M IN A 10.0.3.58
+3000.example. 5M IN A 10.0.3.59
+3000.example. 5M IN A 10.0.3.60
+3000.example. 5M IN A 10.0.3.61
+3000.example. 5M IN A 10.0.3.62
+3000.example. 5M IN A 10.0.3.63
+3000.example. 5M IN A 10.0.3.64
+3000.example. 5M IN A 10.0.3.65
+3000.example. 5M IN A 10.0.3.66
+3000.example. 5M IN A 10.0.3.67
+3000.example. 5M IN A 10.0.3.68
+3000.example. 5M IN A 10.0.3.69
+3000.example. 5M IN A 10.0.3.70
+3000.example. 5M IN A 10.0.3.71
+3000.example. 5M IN A 10.0.3.72
+3000.example. 5M IN A 10.0.3.73
+3000.example. 5M IN A 10.0.3.74
+3000.example. 5M IN A 10.0.3.75
+3000.example. 5M IN A 10.0.3.76
+3000.example. 5M IN A 10.0.3.77
+3000.example. 5M IN A 10.0.3.78
+3000.example. 5M IN A 10.0.3.79
+3000.example. 5M IN A 10.0.3.80
+3000.example. 5M IN A 10.0.3.81
+3000.example. 5M IN A 10.0.3.82
+3000.example. 5M IN A 10.0.3.83
+3000.example. 5M IN A 10.0.3.84
+3000.example. 5M IN A 10.0.3.85
+3000.example. 5M IN A 10.0.3.86
+3000.example. 5M IN A 10.0.3.87
+3000.example. 5M IN A 10.0.3.88
+3000.example. 5M IN A 10.0.3.89
+3000.example. 5M IN A 10.0.3.90
+3000.example. 5M IN A 10.0.3.91
+3000.example. 5M IN A 10.0.3.92
+3000.example. 5M IN A 10.0.3.93
+3000.example. 5M IN A 10.0.3.94
+3000.example. 5M IN A 10.0.3.95
+3000.example. 5M IN A 10.0.3.96
+3000.example. 5M IN A 10.0.3.97
+3000.example. 5M IN A 10.0.3.98
+3000.example. 5M IN A 10.0.3.99
+3000.example. 5M IN A 10.0.3.100
+3000.example. 5M IN A 10.0.3.101
+3000.example. 5M IN A 10.0.3.102
+3000.example. 5M IN A 10.0.3.103
+3000.example. 5M IN A 10.0.3.104
+3000.example. 5M IN A 10.0.3.105
+3000.example. 5M IN A 10.0.3.106
+3000.example. 5M IN A 10.0.3.107
+3000.example. 5M IN A 10.0.3.108
+3000.example. 5M IN A 10.0.3.109
+3000.example. 5M IN A 10.0.3.110
+3000.example. 5M IN A 10.0.3.111
+3000.example. 5M IN A 10.0.3.112
+3000.example. 5M IN A 10.0.3.113
+3000.example. 5M IN A 10.0.3.114
+3000.example. 5M IN A 10.0.3.115
+3000.example. 5M IN A 10.0.3.116
+3000.example. 5M IN A 10.0.3.117
+3000.example. 5M IN A 10.0.3.118
+3000.example. 5M IN A 10.0.3.119
+3000.example. 5M IN A 10.0.3.120
+3000.example. 5M IN A 10.0.3.121
+3000.example. 5M IN A 10.0.3.122
+3000.example. 5M IN A 10.0.3.123
+3000.example. 5M IN A 10.0.3.124
+3000.example. 5M IN A 10.0.3.125
+3000.example. 5M IN A 10.0.3.126
+3000.example. 5M IN A 10.0.3.127
+3000.example. 5M IN A 10.0.3.128
+3000.example. 5M IN A 10.0.3.129
+3000.example. 5M IN A 10.0.3.130
+3000.example. 5M IN A 10.0.3.131
+3000.example. 5M IN A 10.0.3.132
+3000.example. 5M IN A 10.0.3.133
+3000.example. 5M IN A 10.0.3.134
+3000.example. 5M IN A 10.0.3.135
+3000.example. 5M IN A 10.0.3.136
+3000.example. 5M IN A 10.0.3.137
+3000.example. 5M IN A 10.0.3.138
+3000.example. 5M IN A 10.0.3.139
+3000.example. 5M IN A 10.0.3.140
+3000.example. 5M IN A 10.0.3.141
+3000.example. 5M IN A 10.0.3.142
+3000.example. 5M IN A 10.0.3.143
+3000.example. 5M IN A 10.0.3.144
+3000.example. 5M IN A 10.0.3.145
+3000.example. 5M IN A 10.0.3.146
+3000.example. 5M IN A 10.0.3.147
+3000.example. 5M IN A 10.0.3.148
+3000.example. 5M IN A 10.0.3.149
+3000.example. 5M IN A 10.0.3.150
+3000.example. 5M IN A 10.0.3.151
+3000.example. 5M IN A 10.0.3.152
+3000.example. 5M IN A 10.0.3.153
+3000.example. 5M IN A 10.0.3.154
+3000.example. 5M IN A 10.0.3.155
+3000.example. 5M IN A 10.0.3.156
+3000.example. 5M IN A 10.0.3.157
+3000.example. 5M IN A 10.0.3.158
+3000.example. 5M IN A 10.0.3.159
+3000.example. 5M IN A 10.0.3.160
+3000.example. 5M IN A 10.0.3.161
+3000.example. 5M IN A 10.0.3.162
+3000.example. 5M IN A 10.0.3.163
+3000.example. 5M IN A 10.0.3.164
+3000.example. 5M IN A 10.0.3.165
+3000.example. 5M IN A 10.0.3.166
+3000.example. 5M IN A 10.0.3.167
+3000.example. 5M IN A 10.0.3.168
+3000.example. 5M IN A 10.0.3.169
+3000.example. 5M IN A 10.0.3.170
+3000.example. 5M IN A 10.0.3.171
+3000.example. 5M IN A 10.0.3.172
+3000.example. 5M IN A 10.0.3.173
+3000.example. 5M IN A 10.0.3.174
+3000.example. 5M IN A 10.0.3.175
+3000.example. 5M IN A 10.0.3.176
+3000.example. 5M IN A 10.0.3.177
+3000.example. 5M IN A 10.0.3.178
+3000.example. 5M IN A 10.0.3.179
+3000.example. 5M IN A 10.0.3.180
+3000.example. 5M IN A 10.0.3.181
+3000.example. 5M IN A 10.0.3.182
+3000.example. 5M IN A 10.0.3.183
+3000.example. 5M IN A 10.0.3.184
+3000.example. 5M IN A 10.0.3.185
+3000.example. 5M IN A 10.0.3.186
+3000.example. 5M IN A 10.0.3.187
+3000.example. 5M IN A 10.0.3.188
+3000.example. 5M IN A 10.0.3.189
+3000.example. 5M IN A 10.0.3.190
+3000.example. 5M IN A 10.0.3.191
+3000.example. 5M IN A 10.0.3.192
+3000.example. 5M IN A 10.0.3.193
+3000.example. 5M IN A 10.0.3.194
+3000.example. 5M IN A 10.0.3.195
+3000.example. 5M IN A 10.0.3.196
+3000.example. 5M IN A 10.0.3.197
+3000.example. 5M IN A 10.0.3.198
+3000.example. 5M IN A 10.0.3.199
+3000.example. 5M IN A 10.0.3.200
+3000.example. 5M IN A 10.0.3.201
+3000.example. 5M IN A 10.0.3.202
+3000.example. 5M IN A 10.0.3.203
+3000.example. 5M IN A 10.0.3.204
+3000.example. 5M IN A 10.0.3.205
+3000.example. 5M IN A 10.0.3.206
+3000.example. 5M IN A 10.0.3.207
+3000.example. 5M IN A 10.0.3.208
+3000.example. 5M IN A 10.0.3.209
+3000.example. 5M IN A 10.0.3.210
+3000.example. 5M IN A 10.0.3.211
+3000.example. 5M IN A 10.0.3.212
+3000.example. 5M IN A 10.0.3.213
+3000.example. 5M IN A 10.0.3.214
+3000.example. 5M IN A 10.0.3.215
+3000.example. 5M IN A 10.0.3.216
+3000.example. 5M IN A 10.0.3.217
+3000.example. 5M IN A 10.0.3.218
+3000.example. 5M IN A 10.0.3.219
+3000.example. 5M IN A 10.0.3.220
+3000.example. 5M IN A 10.0.3.221
+3000.example. 5M IN A 10.0.3.222
+3000.example. 5M IN A 10.0.3.223
+3000.example. 5M IN A 10.0.3.224
+3000.example. 5M IN A 10.0.3.225
+3000.example. 5M IN A 10.0.3.226
+3000.example. 5M IN A 10.0.3.227
+3000.example. 5M IN A 10.0.3.228
+3000.example. 5M IN A 10.0.3.229
+3000.example. 5M IN A 10.0.3.230
+3000.example. 5M IN A 10.0.3.231
+3000.example. 5M IN A 10.0.3.232
+3000.example. 5M IN A 10.0.3.233
+3000.example. 5M IN A 10.0.3.234
+3000.example. 5M IN A 10.0.3.235
+3000.example. 5M IN A 10.0.3.236
+3000.example. 5M IN A 10.0.3.237
+3000.example. 5M IN A 10.0.3.238
+3000.example. 5M IN A 10.0.3.239
+3000.example. 5M IN A 10.0.3.240
+3000.example. 5M IN A 10.0.3.241
+3000.example. 5M IN A 10.0.3.242
+3000.example. 5M IN A 10.0.3.243
+3000.example. 5M IN A 10.0.3.244
+3000.example. 5M IN A 10.0.3.245
+3000.example. 5M IN A 10.0.3.246
+3000.example. 5M IN A 10.0.3.247
+3000.example. 5M IN A 10.0.3.248
+3000.example. 5M IN A 10.0.3.249
+3000.example. 5M IN A 10.0.3.250
+3000.example. 5M IN A 10.0.3.251
+3000.example. 5M IN A 10.0.3.252
+3000.example. 5M IN A 10.0.3.253
+3000.example. 5M IN A 10.0.3.254
+3000.example. 5M IN A 10.0.3.255
+3000.example. 5M IN A 10.0.4.0
+3000.example. 5M IN A 10.0.4.1
+3000.example. 5M IN A 10.0.4.2
+3000.example. 5M IN A 10.0.4.3
+3000.example. 5M IN A 10.0.4.4
+3000.example. 5M IN A 10.0.4.5
+3000.example. 5M IN A 10.0.4.6
+3000.example. 5M IN A 10.0.4.7
+3000.example. 5M IN A 10.0.4.8
+3000.example. 5M IN A 10.0.4.9
+3000.example. 5M IN A 10.0.4.10
+3000.example. 5M IN A 10.0.4.11
+3000.example. 5M IN A 10.0.4.12
+3000.example. 5M IN A 10.0.4.13
+3000.example. 5M IN A 10.0.4.14
+3000.example. 5M IN A 10.0.4.15
+3000.example. 5M IN A 10.0.4.16
+3000.example. 5M IN A 10.0.4.17
+3000.example. 5M IN A 10.0.4.18
+3000.example. 5M IN A 10.0.4.19
+3000.example. 5M IN A 10.0.4.20
+3000.example. 5M IN A 10.0.4.21
+3000.example. 5M IN A 10.0.4.22
+3000.example. 5M IN A 10.0.4.23
+3000.example. 5M IN A 10.0.4.24
+3000.example. 5M IN A 10.0.4.25
+3000.example. 5M IN A 10.0.4.26
+3000.example. 5M IN A 10.0.4.27
+3000.example. 5M IN A 10.0.4.28
+3000.example. 5M IN A 10.0.4.29
+3000.example. 5M IN A 10.0.4.30
+3000.example. 5M IN A 10.0.4.31
+3000.example. 5M IN A 10.0.4.32
+3000.example. 5M IN A 10.0.4.33
+3000.example. 5M IN A 10.0.4.34
+3000.example. 5M IN A 10.0.4.35
+3000.example. 5M IN A 10.0.4.36
+3000.example. 5M IN A 10.0.4.37
+3000.example. 5M IN A 10.0.4.38
+3000.example. 5M IN A 10.0.4.39
+3000.example. 5M IN A 10.0.4.40
+3000.example. 5M IN A 10.0.4.41
+3000.example. 5M IN A 10.0.4.42
+3000.example. 5M IN A 10.0.4.43
+3000.example. 5M IN A 10.0.4.44
+3000.example. 5M IN A 10.0.4.45
+3000.example. 5M IN A 10.0.4.46
+3000.example. 5M IN A 10.0.4.47
+3000.example. 5M IN A 10.0.4.48
+3000.example. 5M IN A 10.0.4.49
+3000.example. 5M IN A 10.0.4.50
+3000.example. 5M IN A 10.0.4.51
+3000.example. 5M IN A 10.0.4.52
+3000.example. 5M IN A 10.0.4.53
+3000.example. 5M IN A 10.0.4.54
+3000.example. 5M IN A 10.0.4.55
+3000.example. 5M IN A 10.0.4.56
+3000.example. 5M IN A 10.0.4.57
+3000.example. 5M IN A 10.0.4.58
+3000.example. 5M IN A 10.0.4.59
+3000.example. 5M IN A 10.0.4.60
+3000.example. 5M IN A 10.0.4.61
+3000.example. 5M IN A 10.0.4.62
+3000.example. 5M IN A 10.0.4.63
+3000.example. 5M IN A 10.0.4.64
+3000.example. 5M IN A 10.0.4.65
+3000.example. 5M IN A 10.0.4.66
+3000.example. 5M IN A 10.0.4.67
+3000.example. 5M IN A 10.0.4.68
+3000.example. 5M IN A 10.0.4.69
+3000.example. 5M IN A 10.0.4.70
+3000.example. 5M IN A 10.0.4.71
+3000.example. 5M IN A 10.0.4.72
+3000.example. 5M IN A 10.0.4.73
+3000.example. 5M IN A 10.0.4.74
+3000.example. 5M IN A 10.0.4.75
+3000.example. 5M IN A 10.0.4.76
+3000.example. 5M IN A 10.0.4.77
+3000.example. 5M IN A 10.0.4.78
+3000.example. 5M IN A 10.0.4.79
+3000.example. 5M IN A 10.0.4.80
+3000.example. 5M IN A 10.0.4.81
+3000.example. 5M IN A 10.0.4.82
+3000.example. 5M IN A 10.0.4.83
+3000.example. 5M IN A 10.0.4.84
+3000.example. 5M IN A 10.0.4.85
+3000.example. 5M IN A 10.0.4.86
+3000.example. 5M IN A 10.0.4.87
+3000.example. 5M IN A 10.0.4.88
+3000.example. 5M IN A 10.0.4.89
+3000.example. 5M IN A 10.0.4.90
+3000.example. 5M IN A 10.0.4.91
+3000.example. 5M IN A 10.0.4.92
+3000.example. 5M IN A 10.0.4.93
+3000.example. 5M IN A 10.0.4.94
+3000.example. 5M IN A 10.0.4.95
+3000.example. 5M IN A 10.0.4.96
+3000.example. 5M IN A 10.0.4.97
+3000.example. 5M IN A 10.0.4.98
+3000.example. 5M IN A 10.0.4.99
+3000.example. 5M IN A 10.0.4.100
+3000.example. 5M IN A 10.0.4.101
+3000.example. 5M IN A 10.0.4.102
+3000.example. 5M IN A 10.0.4.103
+3000.example. 5M IN A 10.0.4.104
+3000.example. 5M IN A 10.0.4.105
+3000.example. 5M IN A 10.0.4.106
+3000.example. 5M IN A 10.0.4.107
+3000.example. 5M IN A 10.0.4.108
+3000.example. 5M IN A 10.0.4.109
+3000.example. 5M IN A 10.0.4.110
+3000.example. 5M IN A 10.0.4.111
+3000.example. 5M IN A 10.0.4.112
+3000.example. 5M IN A 10.0.4.113
+3000.example. 5M IN A 10.0.4.114
+3000.example. 5M IN A 10.0.4.115
+3000.example. 5M IN A 10.0.4.116
+3000.example. 5M IN A 10.0.4.117
+3000.example. 5M IN A 10.0.4.118
+3000.example. 5M IN A 10.0.4.119
+3000.example. 5M IN A 10.0.4.120
+3000.example. 5M IN A 10.0.4.121
+3000.example. 5M IN A 10.0.4.122
+3000.example. 5M IN A 10.0.4.123
+3000.example. 5M IN A 10.0.4.124
+3000.example. 5M IN A 10.0.4.125
+3000.example. 5M IN A 10.0.4.126
+3000.example. 5M IN A 10.0.4.127
+3000.example. 5M IN A 10.0.4.128
+3000.example. 5M IN A 10.0.4.129
+3000.example. 5M IN A 10.0.4.130
+3000.example. 5M IN A 10.0.4.131
+3000.example. 5M IN A 10.0.4.132
+3000.example. 5M IN A 10.0.4.133
+3000.example. 5M IN A 10.0.4.134
+3000.example. 5M IN A 10.0.4.135
+3000.example. 5M IN A 10.0.4.136
+3000.example. 5M IN A 10.0.4.137
+3000.example. 5M IN A 10.0.4.138
+3000.example. 5M IN A 10.0.4.139
+3000.example. 5M IN A 10.0.4.140
+3000.example. 5M IN A 10.0.4.141
+3000.example. 5M IN A 10.0.4.142
+3000.example. 5M IN A 10.0.4.143
+3000.example. 5M IN A 10.0.4.144
+3000.example. 5M IN A 10.0.4.145
+3000.example. 5M IN A 10.0.4.146
+3000.example. 5M IN A 10.0.4.147
+3000.example. 5M IN A 10.0.4.148
+3000.example. 5M IN A 10.0.4.149
+3000.example. 5M IN A 10.0.4.150
+3000.example. 5M IN A 10.0.4.151
+3000.example. 5M IN A 10.0.4.152
+3000.example. 5M IN A 10.0.4.153
+3000.example. 5M IN A 10.0.4.154
+3000.example. 5M IN A 10.0.4.155
+3000.example. 5M IN A 10.0.4.156
+3000.example. 5M IN A 10.0.4.157
+3000.example. 5M IN A 10.0.4.158
+3000.example. 5M IN A 10.0.4.159
+3000.example. 5M IN A 10.0.4.160
+3000.example. 5M IN A 10.0.4.161
+3000.example. 5M IN A 10.0.4.162
+3000.example. 5M IN A 10.0.4.163
+3000.example. 5M IN A 10.0.4.164
+3000.example. 5M IN A 10.0.4.165
+3000.example. 5M IN A 10.0.4.166
+3000.example. 5M IN A 10.0.4.167
+3000.example. 5M IN A 10.0.4.168
+3000.example. 5M IN A 10.0.4.169
+3000.example. 5M IN A 10.0.4.170
+3000.example. 5M IN A 10.0.4.171
+3000.example. 5M IN A 10.0.4.172
+3000.example. 5M IN A 10.0.4.173
+3000.example. 5M IN A 10.0.4.174
+3000.example. 5M IN A 10.0.4.175
+3000.example. 5M IN A 10.0.4.176
+3000.example. 5M IN A 10.0.4.177
+3000.example. 5M IN A 10.0.4.178
+3000.example. 5M IN A 10.0.4.179
+3000.example. 5M IN A 10.0.4.180
+3000.example. 5M IN A 10.0.4.181
+3000.example. 5M IN A 10.0.4.182
+3000.example. 5M IN A 10.0.4.183
+3000.example. 5M IN A 10.0.4.184
+3000.example. 5M IN A 10.0.4.185
+3000.example. 5M IN A 10.0.4.186
+3000.example. 5M IN A 10.0.4.187
+3000.example. 5M IN A 10.0.4.188
+3000.example. 5M IN A 10.0.4.189
+3000.example. 5M IN A 10.0.4.190
+3000.example. 5M IN A 10.0.4.191
+3000.example. 5M IN A 10.0.4.192
+3000.example. 5M IN A 10.0.4.193
+3000.example. 5M IN A 10.0.4.194
+3000.example. 5M IN A 10.0.4.195
+3000.example. 5M IN A 10.0.4.196
+3000.example. 5M IN A 10.0.4.197
+3000.example. 5M IN A 10.0.4.198
+3000.example. 5M IN A 10.0.4.199
+3000.example. 5M IN A 10.0.4.200
+3000.example. 5M IN A 10.0.4.201
+3000.example. 5M IN A 10.0.4.202
+3000.example. 5M IN A 10.0.4.203
+3000.example. 5M IN A 10.0.4.204
+3000.example. 5M IN A 10.0.4.205
+3000.example. 5M IN A 10.0.4.206
+3000.example. 5M IN A 10.0.4.207
+3000.example. 5M IN A 10.0.4.208
+3000.example. 5M IN A 10.0.4.209
+3000.example. 5M IN A 10.0.4.210
+3000.example. 5M IN A 10.0.4.211
+3000.example. 5M IN A 10.0.4.212
+3000.example. 5M IN A 10.0.4.213
+3000.example. 5M IN A 10.0.4.214
+3000.example. 5M IN A 10.0.4.215
+3000.example. 5M IN A 10.0.4.216
+3000.example. 5M IN A 10.0.4.217
+3000.example. 5M IN A 10.0.4.218
+3000.example. 5M IN A 10.0.4.219
+3000.example. 5M IN A 10.0.4.220
+3000.example. 5M IN A 10.0.4.221
+3000.example. 5M IN A 10.0.4.222
+3000.example. 5M IN A 10.0.4.223
+3000.example. 5M IN A 10.0.4.224
+3000.example. 5M IN A 10.0.4.225
+3000.example. 5M IN A 10.0.4.226
+3000.example. 5M IN A 10.0.4.227
+3000.example. 5M IN A 10.0.4.228
+3000.example. 5M IN A 10.0.4.229
+3000.example. 5M IN A 10.0.4.230
+3000.example. 5M IN A 10.0.4.231
+3000.example. 5M IN A 10.0.4.232
+3000.example. 5M IN A 10.0.4.233
+3000.example. 5M IN A 10.0.4.234
+3000.example. 5M IN A 10.0.4.235
+3000.example. 5M IN A 10.0.4.236
+3000.example. 5M IN A 10.0.4.237
+3000.example. 5M IN A 10.0.4.238
+3000.example. 5M IN A 10.0.4.239
+3000.example. 5M IN A 10.0.4.240
+3000.example. 5M IN A 10.0.4.241
+3000.example. 5M IN A 10.0.4.242
+3000.example. 5M IN A 10.0.4.243
+3000.example. 5M IN A 10.0.4.244
+3000.example. 5M IN A 10.0.4.245
+3000.example. 5M IN A 10.0.4.246
+3000.example. 5M IN A 10.0.4.247
+3000.example. 5M IN A 10.0.4.248
+3000.example. 5M IN A 10.0.4.249
+3000.example. 5M IN A 10.0.4.250
+3000.example. 5M IN A 10.0.4.251
+3000.example. 5M IN A 10.0.4.252
+3000.example. 5M IN A 10.0.4.253
+3000.example. 5M IN A 10.0.4.254
+3000.example. 5M IN A 10.0.4.255
+3000.example. 5M IN A 10.0.5.0
+3000.example. 5M IN A 10.0.5.1
+3000.example. 5M IN A 10.0.5.2
+3000.example. 5M IN A 10.0.5.3
+3000.example. 5M IN A 10.0.5.4
+3000.example. 5M IN A 10.0.5.5
+3000.example. 5M IN A 10.0.5.6
+3000.example. 5M IN A 10.0.5.7
+3000.example. 5M IN A 10.0.5.8
+3000.example. 5M IN A 10.0.5.9
+3000.example. 5M IN A 10.0.5.10
+3000.example. 5M IN A 10.0.5.11
+3000.example. 5M IN A 10.0.5.12
+3000.example. 5M IN A 10.0.5.13
+3000.example. 5M IN A 10.0.5.14
+3000.example. 5M IN A 10.0.5.15
+3000.example. 5M IN A 10.0.5.16
+3000.example. 5M IN A 10.0.5.17
+3000.example. 5M IN A 10.0.5.18
+3000.example. 5M IN A 10.0.5.19
+3000.example. 5M IN A 10.0.5.20
+3000.example. 5M IN A 10.0.5.21
+3000.example. 5M IN A 10.0.5.22
+3000.example. 5M IN A 10.0.5.23
+3000.example. 5M IN A 10.0.5.24
+3000.example. 5M IN A 10.0.5.25
+3000.example. 5M IN A 10.0.5.26
+3000.example. 5M IN A 10.0.5.27
+3000.example. 5M IN A 10.0.5.28
+3000.example. 5M IN A 10.0.5.29
+3000.example. 5M IN A 10.0.5.30
+3000.example. 5M IN A 10.0.5.31
+3000.example. 5M IN A 10.0.5.32
+3000.example. 5M IN A 10.0.5.33
+3000.example. 5M IN A 10.0.5.34
+3000.example. 5M IN A 10.0.5.35
+3000.example. 5M IN A 10.0.5.36
+3000.example. 5M IN A 10.0.5.37
+3000.example. 5M IN A 10.0.5.38
+3000.example. 5M IN A 10.0.5.39
+3000.example. 5M IN A 10.0.5.40
+3000.example. 5M IN A 10.0.5.41
+3000.example. 5M IN A 10.0.5.42
+3000.example. 5M IN A 10.0.5.43
+3000.example. 5M IN A 10.0.5.44
+3000.example. 5M IN A 10.0.5.45
+3000.example. 5M IN A 10.0.5.46
+3000.example. 5M IN A 10.0.5.47
+3000.example. 5M IN A 10.0.5.48
+3000.example. 5M IN A 10.0.5.49
+3000.example. 5M IN A 10.0.5.50
+3000.example. 5M IN A 10.0.5.51
+3000.example. 5M IN A 10.0.5.52
+3000.example. 5M IN A 10.0.5.53
+3000.example. 5M IN A 10.0.5.54
+3000.example. 5M IN A 10.0.5.55
+3000.example. 5M IN A 10.0.5.56
+3000.example. 5M IN A 10.0.5.57
+3000.example. 5M IN A 10.0.5.58
+3000.example. 5M IN A 10.0.5.59
+3000.example. 5M IN A 10.0.5.60
+3000.example. 5M IN A 10.0.5.61
+3000.example. 5M IN A 10.0.5.62
+3000.example. 5M IN A 10.0.5.63
+3000.example. 5M IN A 10.0.5.64
+3000.example. 5M IN A 10.0.5.65
+3000.example. 5M IN A 10.0.5.66
+3000.example. 5M IN A 10.0.5.67
+3000.example. 5M IN A 10.0.5.68
+3000.example. 5M IN A 10.0.5.69
+3000.example. 5M IN A 10.0.5.70
+3000.example. 5M IN A 10.0.5.71
+3000.example. 5M IN A 10.0.5.72
+3000.example. 5M IN A 10.0.5.73
+3000.example. 5M IN A 10.0.5.74
+3000.example. 5M IN A 10.0.5.75
+3000.example. 5M IN A 10.0.5.76
+3000.example. 5M IN A 10.0.5.77
+3000.example. 5M IN A 10.0.5.78
+3000.example. 5M IN A 10.0.5.79
+3000.example. 5M IN A 10.0.5.80
+3000.example. 5M IN A 10.0.5.81
+3000.example. 5M IN A 10.0.5.82
+3000.example. 5M IN A 10.0.5.83
+3000.example. 5M IN A 10.0.5.84
+3000.example. 5M IN A 10.0.5.85
+3000.example. 5M IN A 10.0.5.86
+3000.example. 5M IN A 10.0.5.87
+3000.example. 5M IN A 10.0.5.88
+3000.example. 5M IN A 10.0.5.89
+3000.example. 5M IN A 10.0.5.90
+3000.example. 5M IN A 10.0.5.91
+3000.example. 5M IN A 10.0.5.92
+3000.example. 5M IN A 10.0.5.93
+3000.example. 5M IN A 10.0.5.94
+3000.example. 5M IN A 10.0.5.95
+3000.example. 5M IN A 10.0.5.96
+3000.example. 5M IN A 10.0.5.97
+3000.example. 5M IN A 10.0.5.98
+3000.example. 5M IN A 10.0.5.99
+3000.example. 5M IN A 10.0.5.100
+3000.example. 5M IN A 10.0.5.101
+3000.example. 5M IN A 10.0.5.102
+3000.example. 5M IN A 10.0.5.103
+3000.example. 5M IN A 10.0.5.104
+3000.example. 5M IN A 10.0.5.105
+3000.example. 5M IN A 10.0.5.106
+3000.example. 5M IN A 10.0.5.107
+3000.example. 5M IN A 10.0.5.108
+3000.example. 5M IN A 10.0.5.109
+3000.example. 5M IN A 10.0.5.110
+3000.example. 5M IN A 10.0.5.111
+3000.example. 5M IN A 10.0.5.112
+3000.example. 5M IN A 10.0.5.113
+3000.example. 5M IN A 10.0.5.114
+3000.example. 5M IN A 10.0.5.115
+3000.example. 5M IN A 10.0.5.116
+3000.example. 5M IN A 10.0.5.117
+3000.example. 5M IN A 10.0.5.118
+3000.example. 5M IN A 10.0.5.119
+3000.example. 5M IN A 10.0.5.120
+3000.example. 5M IN A 10.0.5.121
+3000.example. 5M IN A 10.0.5.122
+3000.example. 5M IN A 10.0.5.123
+3000.example. 5M IN A 10.0.5.124
+3000.example. 5M IN A 10.0.5.125
+3000.example. 5M IN A 10.0.5.126
+3000.example. 5M IN A 10.0.5.127
+3000.example. 5M IN A 10.0.5.128
+3000.example. 5M IN A 10.0.5.129
+3000.example. 5M IN A 10.0.5.130
+3000.example. 5M IN A 10.0.5.131
+3000.example. 5M IN A 10.0.5.132
+3000.example. 5M IN A 10.0.5.133
+3000.example. 5M IN A 10.0.5.134
+3000.example. 5M IN A 10.0.5.135
+3000.example. 5M IN A 10.0.5.136
+3000.example. 5M IN A 10.0.5.137
+3000.example. 5M IN A 10.0.5.138
+3000.example. 5M IN A 10.0.5.139
+3000.example. 5M IN A 10.0.5.140
+3000.example. 5M IN A 10.0.5.141
+3000.example. 5M IN A 10.0.5.142
+3000.example. 5M IN A 10.0.5.143
+3000.example. 5M IN A 10.0.5.144
+3000.example. 5M IN A 10.0.5.145
+3000.example. 5M IN A 10.0.5.146
+3000.example. 5M IN A 10.0.5.147
+3000.example. 5M IN A 10.0.5.148
+3000.example. 5M IN A 10.0.5.149
+3000.example. 5M IN A 10.0.5.150
+3000.example. 5M IN A 10.0.5.151
+3000.example. 5M IN A 10.0.5.152
+3000.example. 5M IN A 10.0.5.153
+3000.example. 5M IN A 10.0.5.154
+3000.example. 5M IN A 10.0.5.155
+3000.example. 5M IN A 10.0.5.156
+3000.example. 5M IN A 10.0.5.157
+3000.example. 5M IN A 10.0.5.158
+3000.example. 5M IN A 10.0.5.159
+3000.example. 5M IN A 10.0.5.160
+3000.example. 5M IN A 10.0.5.161
+3000.example. 5M IN A 10.0.5.162
+3000.example. 5M IN A 10.0.5.163
+3000.example. 5M IN A 10.0.5.164
+3000.example. 5M IN A 10.0.5.165
+3000.example. 5M IN A 10.0.5.166
+3000.example. 5M IN A 10.0.5.167
+3000.example. 5M IN A 10.0.5.168
+3000.example. 5M IN A 10.0.5.169
+3000.example. 5M IN A 10.0.5.170
+3000.example. 5M IN A 10.0.5.171
+3000.example. 5M IN A 10.0.5.172
+3000.example. 5M IN A 10.0.5.173
+3000.example. 5M IN A 10.0.5.174
+3000.example. 5M IN A 10.0.5.175
+3000.example. 5M IN A 10.0.5.176
+3000.example. 5M IN A 10.0.5.177
+3000.example. 5M IN A 10.0.5.178
+3000.example. 5M IN A 10.0.5.179
+3000.example. 5M IN A 10.0.5.180
+3000.example. 5M IN A 10.0.5.181
+3000.example. 5M IN A 10.0.5.182
+3000.example. 5M IN A 10.0.5.183
+3000.example. 5M IN A 10.0.5.184
+3000.example. 5M IN A 10.0.5.185
+3000.example. 5M IN A 10.0.5.186
+3000.example. 5M IN A 10.0.5.187
+3000.example. 5M IN A 10.0.5.188
+3000.example. 5M IN A 10.0.5.189
+3000.example. 5M IN A 10.0.5.190
+3000.example. 5M IN A 10.0.5.191
+3000.example. 5M IN A 10.0.5.192
+3000.example. 5M IN A 10.0.5.193
+3000.example. 5M IN A 10.0.5.194
+3000.example. 5M IN A 10.0.5.195
+3000.example. 5M IN A 10.0.5.196
+3000.example. 5M IN A 10.0.5.197
+3000.example. 5M IN A 10.0.5.198
+3000.example. 5M IN A 10.0.5.199
+3000.example. 5M IN A 10.0.5.200
+3000.example. 5M IN A 10.0.5.201
+3000.example. 5M IN A 10.0.5.202
+3000.example. 5M IN A 10.0.5.203
+3000.example. 5M IN A 10.0.5.204
+3000.example. 5M IN A 10.0.5.205
+3000.example. 5M IN A 10.0.5.206
+3000.example. 5M IN A 10.0.5.207
+3000.example. 5M IN A 10.0.5.208
+3000.example. 5M IN A 10.0.5.209
+3000.example. 5M IN A 10.0.5.210
+3000.example. 5M IN A 10.0.5.211
+3000.example. 5M IN A 10.0.5.212
+3000.example. 5M IN A 10.0.5.213
+3000.example. 5M IN A 10.0.5.214
+3000.example. 5M IN A 10.0.5.215
+3000.example. 5M IN A 10.0.5.216
+3000.example. 5M IN A 10.0.5.217
+3000.example. 5M IN A 10.0.5.218
+3000.example. 5M IN A 10.0.5.219
+3000.example. 5M IN A 10.0.5.220
+3000.example. 5M IN A 10.0.5.221
+3000.example. 5M IN A 10.0.5.222
+3000.example. 5M IN A 10.0.5.223
+3000.example. 5M IN A 10.0.5.224
+3000.example. 5M IN A 10.0.5.225
+3000.example. 5M IN A 10.0.5.226
+3000.example. 5M IN A 10.0.5.227
+3000.example. 5M IN A 10.0.5.228
+3000.example. 5M IN A 10.0.5.229
+3000.example. 5M IN A 10.0.5.230
+3000.example. 5M IN A 10.0.5.231
+3000.example. 5M IN A 10.0.5.232
+3000.example. 5M IN A 10.0.5.233
+3000.example. 5M IN A 10.0.5.234
+3000.example. 5M IN A 10.0.5.235
+3000.example. 5M IN A 10.0.5.236
+3000.example. 5M IN A 10.0.5.237
+3000.example. 5M IN A 10.0.5.238
+3000.example. 5M IN A 10.0.5.239
+3000.example. 5M IN A 10.0.5.240
+3000.example. 5M IN A 10.0.5.241
+3000.example. 5M IN A 10.0.5.242
+3000.example. 5M IN A 10.0.5.243
+3000.example. 5M IN A 10.0.5.244
+3000.example. 5M IN A 10.0.5.245
+3000.example. 5M IN A 10.0.5.246
+3000.example. 5M IN A 10.0.5.247
+3000.example. 5M IN A 10.0.5.248
+3000.example. 5M IN A 10.0.5.249
+3000.example. 5M IN A 10.0.5.250
+3000.example. 5M IN A 10.0.5.251
+3000.example. 5M IN A 10.0.5.252
+3000.example. 5M IN A 10.0.5.253
+3000.example. 5M IN A 10.0.5.254
+3000.example. 5M IN A 10.0.5.255
+3000.example. 5M IN A 10.0.6.0
+3000.example. 5M IN A 10.0.6.1
+3000.example. 5M IN A 10.0.6.2
+3000.example. 5M IN A 10.0.6.3
+3000.example. 5M IN A 10.0.6.4
+3000.example. 5M IN A 10.0.6.5
+3000.example. 5M IN A 10.0.6.6
+3000.example. 5M IN A 10.0.6.7
+3000.example. 5M IN A 10.0.6.8
+3000.example. 5M IN A 10.0.6.9
+3000.example. 5M IN A 10.0.6.10
+3000.example. 5M IN A 10.0.6.11
+3000.example. 5M IN A 10.0.6.12
+3000.example. 5M IN A 10.0.6.13
+3000.example. 5M IN A 10.0.6.14
+3000.example. 5M IN A 10.0.6.15
+3000.example. 5M IN A 10.0.6.16
+3000.example. 5M IN A 10.0.6.17
+3000.example. 5M IN A 10.0.6.18
+3000.example. 5M IN A 10.0.6.19
+3000.example. 5M IN A 10.0.6.20
+3000.example. 5M IN A 10.0.6.21
+3000.example. 5M IN A 10.0.6.22
+3000.example. 5M IN A 10.0.6.23
+3000.example. 5M IN A 10.0.6.24
+3000.example. 5M IN A 10.0.6.25
+3000.example. 5M IN A 10.0.6.26
+3000.example. 5M IN A 10.0.6.27
+3000.example. 5M IN A 10.0.6.28
+3000.example. 5M IN A 10.0.6.29
+3000.example. 5M IN A 10.0.6.30
+3000.example. 5M IN A 10.0.6.31
+3000.example. 5M IN A 10.0.6.32
+3000.example. 5M IN A 10.0.6.33
+3000.example. 5M IN A 10.0.6.34
+3000.example. 5M IN A 10.0.6.35
+3000.example. 5M IN A 10.0.6.36
+3000.example. 5M IN A 10.0.6.37
+3000.example. 5M IN A 10.0.6.38
+3000.example. 5M IN A 10.0.6.39
+3000.example. 5M IN A 10.0.6.40
+3000.example. 5M IN A 10.0.6.41
+3000.example. 5M IN A 10.0.6.42
+3000.example. 5M IN A 10.0.6.43
+3000.example. 5M IN A 10.0.6.44
+3000.example. 5M IN A 10.0.6.45
+3000.example. 5M IN A 10.0.6.46
+3000.example. 5M IN A 10.0.6.47
+3000.example. 5M IN A 10.0.6.48
+3000.example. 5M IN A 10.0.6.49
+3000.example. 5M IN A 10.0.6.50
+3000.example. 5M IN A 10.0.6.51
+3000.example. 5M IN A 10.0.6.52
+3000.example. 5M IN A 10.0.6.53
+3000.example. 5M IN A 10.0.6.54
+3000.example. 5M IN A 10.0.6.55
+3000.example. 5M IN A 10.0.6.56
+3000.example. 5M IN A 10.0.6.57
+3000.example. 5M IN A 10.0.6.58
+3000.example. 5M IN A 10.0.6.59
+3000.example. 5M IN A 10.0.6.60
+3000.example. 5M IN A 10.0.6.61
+3000.example. 5M IN A 10.0.6.62
+3000.example. 5M IN A 10.0.6.63
+3000.example. 5M IN A 10.0.6.64
+3000.example. 5M IN A 10.0.6.65
+3000.example. 5M IN A 10.0.6.66
+3000.example. 5M IN A 10.0.6.67
+3000.example. 5M IN A 10.0.6.68
+3000.example. 5M IN A 10.0.6.69
+3000.example. 5M IN A 10.0.6.70
+3000.example. 5M IN A 10.0.6.71
+3000.example. 5M IN A 10.0.6.72
+3000.example. 5M IN A 10.0.6.73
+3000.example. 5M IN A 10.0.6.74
+3000.example. 5M IN A 10.0.6.75
+3000.example. 5M IN A 10.0.6.76
+3000.example. 5M IN A 10.0.6.77
+3000.example. 5M IN A 10.0.6.78
+3000.example. 5M IN A 10.0.6.79
+3000.example. 5M IN A 10.0.6.80
+3000.example. 5M IN A 10.0.6.81
+3000.example. 5M IN A 10.0.6.82
+3000.example. 5M IN A 10.0.6.83
+3000.example. 5M IN A 10.0.6.84
+3000.example. 5M IN A 10.0.6.85
+3000.example. 5M IN A 10.0.6.86
+3000.example. 5M IN A 10.0.6.87
+3000.example. 5M IN A 10.0.6.88
+3000.example. 5M IN A 10.0.6.89
+3000.example. 5M IN A 10.0.6.90
+3000.example. 5M IN A 10.0.6.91
+3000.example. 5M IN A 10.0.6.92
+3000.example. 5M IN A 10.0.6.93
+3000.example. 5M IN A 10.0.6.94
+3000.example. 5M IN A 10.0.6.95
+3000.example. 5M IN A 10.0.6.96
+3000.example. 5M IN A 10.0.6.97
+3000.example. 5M IN A 10.0.6.98
+3000.example. 5M IN A 10.0.6.99
+3000.example. 5M IN A 10.0.6.100
+3000.example. 5M IN A 10.0.6.101
+3000.example. 5M IN A 10.0.6.102
+3000.example. 5M IN A 10.0.6.103
+3000.example. 5M IN A 10.0.6.104
+3000.example. 5M IN A 10.0.6.105
+3000.example. 5M IN A 10.0.6.106
+3000.example. 5M IN A 10.0.6.107
+3000.example. 5M IN A 10.0.6.108
+3000.example. 5M IN A 10.0.6.109
+3000.example. 5M IN A 10.0.6.110
+3000.example. 5M IN A 10.0.6.111
+3000.example. 5M IN A 10.0.6.112
+3000.example. 5M IN A 10.0.6.113
+3000.example. 5M IN A 10.0.6.114
+3000.example. 5M IN A 10.0.6.115
+3000.example. 5M IN A 10.0.6.116
+3000.example. 5M IN A 10.0.6.117
+3000.example. 5M IN A 10.0.6.118
+3000.example. 5M IN A 10.0.6.119
+3000.example. 5M IN A 10.0.6.120
+3000.example. 5M IN A 10.0.6.121
+3000.example. 5M IN A 10.0.6.122
+3000.example. 5M IN A 10.0.6.123
+3000.example. 5M IN A 10.0.6.124
+3000.example. 5M IN A 10.0.6.125
+3000.example. 5M IN A 10.0.6.126
+3000.example. 5M IN A 10.0.6.127
+3000.example. 5M IN A 10.0.6.128
+3000.example. 5M IN A 10.0.6.129
+3000.example. 5M IN A 10.0.6.130
+3000.example. 5M IN A 10.0.6.131
+3000.example. 5M IN A 10.0.6.132
+3000.example. 5M IN A 10.0.6.133
+3000.example. 5M IN A 10.0.6.134
+3000.example. 5M IN A 10.0.6.135
+3000.example. 5M IN A 10.0.6.136
+3000.example. 5M IN A 10.0.6.137
+3000.example. 5M IN A 10.0.6.138
+3000.example. 5M IN A 10.0.6.139
+3000.example. 5M IN A 10.0.6.140
+3000.example. 5M IN A 10.0.6.141
+3000.example. 5M IN A 10.0.6.142
+3000.example. 5M IN A 10.0.6.143
+3000.example. 5M IN A 10.0.6.144
+3000.example. 5M IN A 10.0.6.145
+3000.example. 5M IN A 10.0.6.146
+3000.example. 5M IN A 10.0.6.147
+3000.example. 5M IN A 10.0.6.148
+3000.example. 5M IN A 10.0.6.149
+3000.example. 5M IN A 10.0.6.150
+3000.example. 5M IN A 10.0.6.151
+3000.example. 5M IN A 10.0.6.152
+3000.example. 5M IN A 10.0.6.153
+3000.example. 5M IN A 10.0.6.154
+3000.example. 5M IN A 10.0.6.155
+3000.example. 5M IN A 10.0.6.156
+3000.example. 5M IN A 10.0.6.157
+3000.example. 5M IN A 10.0.6.158
+3000.example. 5M IN A 10.0.6.159
+3000.example. 5M IN A 10.0.6.160
+3000.example. 5M IN A 10.0.6.161
+3000.example. 5M IN A 10.0.6.162
+3000.example. 5M IN A 10.0.6.163
+3000.example. 5M IN A 10.0.6.164
+3000.example. 5M IN A 10.0.6.165
+3000.example. 5M IN A 10.0.6.166
+3000.example. 5M IN A 10.0.6.167
+3000.example. 5M IN A 10.0.6.168
+3000.example. 5M IN A 10.0.6.169
+3000.example. 5M IN A 10.0.6.170
+3000.example. 5M IN A 10.0.6.171
+3000.example. 5M IN A 10.0.6.172
+3000.example. 5M IN A 10.0.6.173
+3000.example. 5M IN A 10.0.6.174
+3000.example. 5M IN A 10.0.6.175
+3000.example. 5M IN A 10.0.6.176
+3000.example. 5M IN A 10.0.6.177
+3000.example. 5M IN A 10.0.6.178
+3000.example. 5M IN A 10.0.6.179
+3000.example. 5M IN A 10.0.6.180
+3000.example. 5M IN A 10.0.6.181
+3000.example. 5M IN A 10.0.6.182
+3000.example. 5M IN A 10.0.6.183
+3000.example. 5M IN A 10.0.6.184
+3000.example. 5M IN A 10.0.6.185
+3000.example. 5M IN A 10.0.6.186
+3000.example. 5M IN A 10.0.6.187
+3000.example. 5M IN A 10.0.6.188
+3000.example. 5M IN A 10.0.6.189
+3000.example. 5M IN A 10.0.6.190
+3000.example. 5M IN A 10.0.6.191
+3000.example. 5M IN A 10.0.6.192
+3000.example. 5M IN A 10.0.6.193
+3000.example. 5M IN A 10.0.6.194
+3000.example. 5M IN A 10.0.6.195
+3000.example. 5M IN A 10.0.6.196
+3000.example. 5M IN A 10.0.6.197
+3000.example. 5M IN A 10.0.6.198
+3000.example. 5M IN A 10.0.6.199
+3000.example. 5M IN A 10.0.6.200
+3000.example. 5M IN A 10.0.6.201
+3000.example. 5M IN A 10.0.6.202
+3000.example. 5M IN A 10.0.6.203
+3000.example. 5M IN A 10.0.6.204
+3000.example. 5M IN A 10.0.6.205
+3000.example. 5M IN A 10.0.6.206
+3000.example. 5M IN A 10.0.6.207
+3000.example. 5M IN A 10.0.6.208
+3000.example. 5M IN A 10.0.6.209
+3000.example. 5M IN A 10.0.6.210
+3000.example. 5M IN A 10.0.6.211
+3000.example. 5M IN A 10.0.6.212
+3000.example. 5M IN A 10.0.6.213
+3000.example. 5M IN A 10.0.6.214
+3000.example. 5M IN A 10.0.6.215
+3000.example. 5M IN A 10.0.6.216
+3000.example. 5M IN A 10.0.6.217
+3000.example. 5M IN A 10.0.6.218
+3000.example. 5M IN A 10.0.6.219
+3000.example. 5M IN A 10.0.6.220
+3000.example. 5M IN A 10.0.6.221
+3000.example. 5M IN A 10.0.6.222
+3000.example. 5M IN A 10.0.6.223
+3000.example. 5M IN A 10.0.6.224
+3000.example. 5M IN A 10.0.6.225
+3000.example. 5M IN A 10.0.6.226
+3000.example. 5M IN A 10.0.6.227
+3000.example. 5M IN A 10.0.6.228
+3000.example. 5M IN A 10.0.6.229
+3000.example. 5M IN A 10.0.6.230
+3000.example. 5M IN A 10.0.6.231
+3000.example. 5M IN A 10.0.6.232
+3000.example. 5M IN A 10.0.6.233
+3000.example. 5M IN A 10.0.6.234
+3000.example. 5M IN A 10.0.6.235
+3000.example. 5M IN A 10.0.6.236
+3000.example. 5M IN A 10.0.6.237
+3000.example. 5M IN A 10.0.6.238
+3000.example. 5M IN A 10.0.6.239
+3000.example. 5M IN A 10.0.6.240
+3000.example. 5M IN A 10.0.6.241
+3000.example. 5M IN A 10.0.6.242
+3000.example. 5M IN A 10.0.6.243
+3000.example. 5M IN A 10.0.6.244
+3000.example. 5M IN A 10.0.6.245
+3000.example. 5M IN A 10.0.6.246
+3000.example. 5M IN A 10.0.6.247
+3000.example. 5M IN A 10.0.6.248
+3000.example. 5M IN A 10.0.6.249
+3000.example. 5M IN A 10.0.6.250
+3000.example. 5M IN A 10.0.6.251
+3000.example. 5M IN A 10.0.6.252
+3000.example. 5M IN A 10.0.6.253
+3000.example. 5M IN A 10.0.6.254
+3000.example. 5M IN A 10.0.6.255
+3000.example. 5M IN A 10.0.7.0
+3000.example. 5M IN A 10.0.7.1
+3000.example. 5M IN A 10.0.7.2
+3000.example. 5M IN A 10.0.7.3
+3000.example. 5M IN A 10.0.7.4
+3000.example. 5M IN A 10.0.7.5
+3000.example. 5M IN A 10.0.7.6
+3000.example. 5M IN A 10.0.7.7
+3000.example. 5M IN A 10.0.7.8
+3000.example. 5M IN A 10.0.7.9
+3000.example. 5M IN A 10.0.7.10
+3000.example. 5M IN A 10.0.7.11
+3000.example. 5M IN A 10.0.7.12
+3000.example. 5M IN A 10.0.7.13
+3000.example. 5M IN A 10.0.7.14
+3000.example. 5M IN A 10.0.7.15
+3000.example. 5M IN A 10.0.7.16
+3000.example. 5M IN A 10.0.7.17
+3000.example. 5M IN A 10.0.7.18
+3000.example. 5M IN A 10.0.7.19
+3000.example. 5M IN A 10.0.7.20
+3000.example. 5M IN A 10.0.7.21
+3000.example. 5M IN A 10.0.7.22
+3000.example. 5M IN A 10.0.7.23
+3000.example. 5M IN A 10.0.7.24
+3000.example. 5M IN A 10.0.7.25
+3000.example. 5M IN A 10.0.7.26
+3000.example. 5M IN A 10.0.7.27
+3000.example. 5M IN A 10.0.7.28
+3000.example. 5M IN A 10.0.7.29
+3000.example. 5M IN A 10.0.7.30
+3000.example. 5M IN A 10.0.7.31
+3000.example. 5M IN A 10.0.7.32
+3000.example. 5M IN A 10.0.7.33
+3000.example. 5M IN A 10.0.7.34
+3000.example. 5M IN A 10.0.7.35
+3000.example. 5M IN A 10.0.7.36
+3000.example. 5M IN A 10.0.7.37
+3000.example. 5M IN A 10.0.7.38
+3000.example. 5M IN A 10.0.7.39
+3000.example. 5M IN A 10.0.7.40
+3000.example. 5M IN A 10.0.7.41
+3000.example. 5M IN A 10.0.7.42
+3000.example. 5M IN A 10.0.7.43
+3000.example. 5M IN A 10.0.7.44
+3000.example. 5M IN A 10.0.7.45
+3000.example. 5M IN A 10.0.7.46
+3000.example. 5M IN A 10.0.7.47
+3000.example. 5M IN A 10.0.7.48
+3000.example. 5M IN A 10.0.7.49
+3000.example. 5M IN A 10.0.7.50
+3000.example. 5M IN A 10.0.7.51
+3000.example. 5M IN A 10.0.7.52
+3000.example. 5M IN A 10.0.7.53
+3000.example. 5M IN A 10.0.7.54
+3000.example. 5M IN A 10.0.7.55
+3000.example. 5M IN A 10.0.7.56
+3000.example. 5M IN A 10.0.7.57
+3000.example. 5M IN A 10.0.7.58
+3000.example. 5M IN A 10.0.7.59
+3000.example. 5M IN A 10.0.7.60
+3000.example. 5M IN A 10.0.7.61
+3000.example. 5M IN A 10.0.7.62
+3000.example. 5M IN A 10.0.7.63
+3000.example. 5M IN A 10.0.7.64
+3000.example. 5M IN A 10.0.7.65
+3000.example. 5M IN A 10.0.7.66
+3000.example. 5M IN A 10.0.7.67
+3000.example. 5M IN A 10.0.7.68
+3000.example. 5M IN A 10.0.7.69
+3000.example. 5M IN A 10.0.7.70
+3000.example. 5M IN A 10.0.7.71
+3000.example. 5M IN A 10.0.7.72
+3000.example. 5M IN A 10.0.7.73
+3000.example. 5M IN A 10.0.7.74
+3000.example. 5M IN A 10.0.7.75
+3000.example. 5M IN A 10.0.7.76
+3000.example. 5M IN A 10.0.7.77
+3000.example. 5M IN A 10.0.7.78
+3000.example. 5M IN A 10.0.7.79
+3000.example. 5M IN A 10.0.7.80
+3000.example. 5M IN A 10.0.7.81
+3000.example. 5M IN A 10.0.7.82
+3000.example. 5M IN A 10.0.7.83
+3000.example. 5M IN A 10.0.7.84
+3000.example. 5M IN A 10.0.7.85
+3000.example. 5M IN A 10.0.7.86
+3000.example. 5M IN A 10.0.7.87
+3000.example. 5M IN A 10.0.7.88
+3000.example. 5M IN A 10.0.7.89
+3000.example. 5M IN A 10.0.7.90
+3000.example. 5M IN A 10.0.7.91
+3000.example. 5M IN A 10.0.7.92
+3000.example. 5M IN A 10.0.7.93
+3000.example. 5M IN A 10.0.7.94
+3000.example. 5M IN A 10.0.7.95
+3000.example. 5M IN A 10.0.7.96
+3000.example. 5M IN A 10.0.7.97
+3000.example. 5M IN A 10.0.7.98
+3000.example. 5M IN A 10.0.7.99
+3000.example. 5M IN A 10.0.7.100
+3000.example. 5M IN A 10.0.7.101
+3000.example. 5M IN A 10.0.7.102
+3000.example. 5M IN A 10.0.7.103
+3000.example. 5M IN A 10.0.7.104
+3000.example. 5M IN A 10.0.7.105
+3000.example. 5M IN A 10.0.7.106
+3000.example. 5M IN A 10.0.7.107
+3000.example. 5M IN A 10.0.7.108
+3000.example. 5M IN A 10.0.7.109
+3000.example. 5M IN A 10.0.7.110
+3000.example. 5M IN A 10.0.7.111
+3000.example. 5M IN A 10.0.7.112
+3000.example. 5M IN A 10.0.7.113
+3000.example. 5M IN A 10.0.7.114
+3000.example. 5M IN A 10.0.7.115
+3000.example. 5M IN A 10.0.7.116
+3000.example. 5M IN A 10.0.7.117
+3000.example. 5M IN A 10.0.7.118
+3000.example. 5M IN A 10.0.7.119
+3000.example. 5M IN A 10.0.7.120
+3000.example. 5M IN A 10.0.7.121
+3000.example. 5M IN A 10.0.7.122
+3000.example. 5M IN A 10.0.7.123
+3000.example. 5M IN A 10.0.7.124
+3000.example. 5M IN A 10.0.7.125
+3000.example. 5M IN A 10.0.7.126
+3000.example. 5M IN A 10.0.7.127
+3000.example. 5M IN A 10.0.7.128
+3000.example. 5M IN A 10.0.7.129
+3000.example. 5M IN A 10.0.7.130
+3000.example. 5M IN A 10.0.7.131
+3000.example. 5M IN A 10.0.7.132
+3000.example. 5M IN A 10.0.7.133
+3000.example. 5M IN A 10.0.7.134
+3000.example. 5M IN A 10.0.7.135
+3000.example. 5M IN A 10.0.7.136
+3000.example. 5M IN A 10.0.7.137
+3000.example. 5M IN A 10.0.7.138
+3000.example. 5M IN A 10.0.7.139
+3000.example. 5M IN A 10.0.7.140
+3000.example. 5M IN A 10.0.7.141
+3000.example. 5M IN A 10.0.7.142
+3000.example. 5M IN A 10.0.7.143
+3000.example. 5M IN A 10.0.7.144
+3000.example. 5M IN A 10.0.7.145
+3000.example. 5M IN A 10.0.7.146
+3000.example. 5M IN A 10.0.7.147
+3000.example. 5M IN A 10.0.7.148
+3000.example. 5M IN A 10.0.7.149
+3000.example. 5M IN A 10.0.7.150
+3000.example. 5M IN A 10.0.7.151
+3000.example. 5M IN A 10.0.7.152
+3000.example. 5M IN A 10.0.7.153
+3000.example. 5M IN A 10.0.7.154
+3000.example. 5M IN A 10.0.7.155
+3000.example. 5M IN A 10.0.7.156
+3000.example. 5M IN A 10.0.7.157
+3000.example. 5M IN A 10.0.7.158
+3000.example. 5M IN A 10.0.7.159
+3000.example. 5M IN A 10.0.7.160
+3000.example. 5M IN A 10.0.7.161
+3000.example. 5M IN A 10.0.7.162
+3000.example. 5M IN A 10.0.7.163
+3000.example. 5M IN A 10.0.7.164
+3000.example. 5M IN A 10.0.7.165
+3000.example. 5M IN A 10.0.7.166
+3000.example. 5M IN A 10.0.7.167
+3000.example. 5M IN A 10.0.7.168
+3000.example. 5M IN A 10.0.7.169
+3000.example. 5M IN A 10.0.7.170
+3000.example. 5M IN A 10.0.7.171
+3000.example. 5M IN A 10.0.7.172
+3000.example. 5M IN A 10.0.7.173
+3000.example. 5M IN A 10.0.7.174
+3000.example. 5M IN A 10.0.7.175
+3000.example. 5M IN A 10.0.7.176
+3000.example. 5M IN A 10.0.7.177
+3000.example. 5M IN A 10.0.7.178
+3000.example. 5M IN A 10.0.7.179
+3000.example. 5M IN A 10.0.7.180
+3000.example. 5M IN A 10.0.7.181
+3000.example. 5M IN A 10.0.7.182
+3000.example. 5M IN A 10.0.7.183
+3000.example. 5M IN A 10.0.7.184
+3000.example. 5M IN A 10.0.7.185
+3000.example. 5M IN A 10.0.7.186
+3000.example. 5M IN A 10.0.7.187
+3000.example. 5M IN A 10.0.7.188
+3000.example. 5M IN A 10.0.7.189
+3000.example. 5M IN A 10.0.7.190
+3000.example. 5M IN A 10.0.7.191
+3000.example. 5M IN A 10.0.7.192
+3000.example. 5M IN A 10.0.7.193
+3000.example. 5M IN A 10.0.7.194
+3000.example. 5M IN A 10.0.7.195
+3000.example. 5M IN A 10.0.7.196
+3000.example. 5M IN A 10.0.7.197
+3000.example. 5M IN A 10.0.7.198
+3000.example. 5M IN A 10.0.7.199
+3000.example. 5M IN A 10.0.7.200
+3000.example. 5M IN A 10.0.7.201
+3000.example. 5M IN A 10.0.7.202
+3000.example. 5M IN A 10.0.7.203
+3000.example. 5M IN A 10.0.7.204
+3000.example. 5M IN A 10.0.7.205
+3000.example. 5M IN A 10.0.7.206
+3000.example. 5M IN A 10.0.7.207
+3000.example. 5M IN A 10.0.7.208
+3000.example. 5M IN A 10.0.7.209
+3000.example. 5M IN A 10.0.7.210
+3000.example. 5M IN A 10.0.7.211
+3000.example. 5M IN A 10.0.7.212
+3000.example. 5M IN A 10.0.7.213
+3000.example. 5M IN A 10.0.7.214
+3000.example. 5M IN A 10.0.7.215
+3000.example. 5M IN A 10.0.7.216
+3000.example. 5M IN A 10.0.7.217
+3000.example. 5M IN A 10.0.7.218
+3000.example. 5M IN A 10.0.7.219
+3000.example. 5M IN A 10.0.7.220
+3000.example. 5M IN A 10.0.7.221
+3000.example. 5M IN A 10.0.7.222
+3000.example. 5M IN A 10.0.7.223
+3000.example. 5M IN A 10.0.7.224
+3000.example. 5M IN A 10.0.7.225
+3000.example. 5M IN A 10.0.7.226
+3000.example. 5M IN A 10.0.7.227
+3000.example. 5M IN A 10.0.7.228
+3000.example. 5M IN A 10.0.7.229
+3000.example. 5M IN A 10.0.7.230
+3000.example. 5M IN A 10.0.7.231
+3000.example. 5M IN A 10.0.7.232
+3000.example. 5M IN A 10.0.7.233
+3000.example. 5M IN A 10.0.7.234
+3000.example. 5M IN A 10.0.7.235
+3000.example. 5M IN A 10.0.7.236
+3000.example. 5M IN A 10.0.7.237
+3000.example. 5M IN A 10.0.7.238
+3000.example. 5M IN A 10.0.7.239
+3000.example. 5M IN A 10.0.7.240
+3000.example. 5M IN A 10.0.7.241
+3000.example. 5M IN A 10.0.7.242
+3000.example. 5M IN A 10.0.7.243
+3000.example. 5M IN A 10.0.7.244
+3000.example. 5M IN A 10.0.7.245
+3000.example. 5M IN A 10.0.7.246
+3000.example. 5M IN A 10.0.7.247
+3000.example. 5M IN A 10.0.7.248
+3000.example. 5M IN A 10.0.7.249
+3000.example. 5M IN A 10.0.7.250
+3000.example. 5M IN A 10.0.7.251
+3000.example. 5M IN A 10.0.7.252
+3000.example. 5M IN A 10.0.7.253
+3000.example. 5M IN A 10.0.7.254
+3000.example. 5M IN A 10.0.7.255
+3000.example. 5M IN A 10.0.8.0
+3000.example. 5M IN A 10.0.8.1
+3000.example. 5M IN A 10.0.8.2
+3000.example. 5M IN A 10.0.8.3
+3000.example. 5M IN A 10.0.8.4
+3000.example. 5M IN A 10.0.8.5
+3000.example. 5M IN A 10.0.8.6
+3000.example. 5M IN A 10.0.8.7
+3000.example. 5M IN A 10.0.8.8
+3000.example. 5M IN A 10.0.8.9
+3000.example. 5M IN A 10.0.8.10
+3000.example. 5M IN A 10.0.8.11
+3000.example. 5M IN A 10.0.8.12
+3000.example. 5M IN A 10.0.8.13
+3000.example. 5M IN A 10.0.8.14
+3000.example. 5M IN A 10.0.8.15
+3000.example. 5M IN A 10.0.8.16
+3000.example. 5M IN A 10.0.8.17
+3000.example. 5M IN A 10.0.8.18
+3000.example. 5M IN A 10.0.8.19
+3000.example. 5M IN A 10.0.8.20
+3000.example. 5M IN A 10.0.8.21
+3000.example. 5M IN A 10.0.8.22
+3000.example. 5M IN A 10.0.8.23
+3000.example. 5M IN A 10.0.8.24
+3000.example. 5M IN A 10.0.8.25
+3000.example. 5M IN A 10.0.8.26
+3000.example. 5M IN A 10.0.8.27
+3000.example. 5M IN A 10.0.8.28
+3000.example. 5M IN A 10.0.8.29
+3000.example. 5M IN A 10.0.8.30
+3000.example. 5M IN A 10.0.8.31
+3000.example. 5M IN A 10.0.8.32
+3000.example. 5M IN A 10.0.8.33
+3000.example. 5M IN A 10.0.8.34
+3000.example. 5M IN A 10.0.8.35
+3000.example. 5M IN A 10.0.8.36
+3000.example. 5M IN A 10.0.8.37
+3000.example. 5M IN A 10.0.8.38
+3000.example. 5M IN A 10.0.8.39
+3000.example. 5M IN A 10.0.8.40
+3000.example. 5M IN A 10.0.8.41
+3000.example. 5M IN A 10.0.8.42
+3000.example. 5M IN A 10.0.8.43
+3000.example. 5M IN A 10.0.8.44
+3000.example. 5M IN A 10.0.8.45
+3000.example. 5M IN A 10.0.8.46
+3000.example. 5M IN A 10.0.8.47
+3000.example. 5M IN A 10.0.8.48
+3000.example. 5M IN A 10.0.8.49
+3000.example. 5M IN A 10.0.8.50
+3000.example. 5M IN A 10.0.8.51
+3000.example. 5M IN A 10.0.8.52
+3000.example. 5M IN A 10.0.8.53
+3000.example. 5M IN A 10.0.8.54
+3000.example. 5M IN A 10.0.8.55
+3000.example. 5M IN A 10.0.8.56
+3000.example. 5M IN A 10.0.8.57
+3000.example. 5M IN A 10.0.8.58
+3000.example. 5M IN A 10.0.8.59
+3000.example. 5M IN A 10.0.8.60
+3000.example. 5M IN A 10.0.8.61
+3000.example. 5M IN A 10.0.8.62
+3000.example. 5M IN A 10.0.8.63
+3000.example. 5M IN A 10.0.8.64
+3000.example. 5M IN A 10.0.8.65
+3000.example. 5M IN A 10.0.8.66
+3000.example. 5M IN A 10.0.8.67
+3000.example. 5M IN A 10.0.8.68
+3000.example. 5M IN A 10.0.8.69
+3000.example. 5M IN A 10.0.8.70
+3000.example. 5M IN A 10.0.8.71
+3000.example. 5M IN A 10.0.8.72
+3000.example. 5M IN A 10.0.8.73
+3000.example. 5M IN A 10.0.8.74
+3000.example. 5M IN A 10.0.8.75
+3000.example. 5M IN A 10.0.8.76
+3000.example. 5M IN A 10.0.8.77
+3000.example. 5M IN A 10.0.8.78
+3000.example. 5M IN A 10.0.8.79
+3000.example. 5M IN A 10.0.8.80
+3000.example. 5M IN A 10.0.8.81
+3000.example. 5M IN A 10.0.8.82
+3000.example. 5M IN A 10.0.8.83
+3000.example. 5M IN A 10.0.8.84
+3000.example. 5M IN A 10.0.8.85
+3000.example. 5M IN A 10.0.8.86
+3000.example. 5M IN A 10.0.8.87
+3000.example. 5M IN A 10.0.8.88
+3000.example. 5M IN A 10.0.8.89
+3000.example. 5M IN A 10.0.8.90
+3000.example. 5M IN A 10.0.8.91
+3000.example. 5M IN A 10.0.8.92
+3000.example. 5M IN A 10.0.8.93
+3000.example. 5M IN A 10.0.8.94
+3000.example. 5M IN A 10.0.8.95
+3000.example. 5M IN A 10.0.8.96
+3000.example. 5M IN A 10.0.8.97
+3000.example. 5M IN A 10.0.8.98
+3000.example. 5M IN A 10.0.8.99
+3000.example. 5M IN A 10.0.8.100
+3000.example. 5M IN A 10.0.8.101
+3000.example. 5M IN A 10.0.8.102
+3000.example. 5M IN A 10.0.8.103
+3000.example. 5M IN A 10.0.8.104
+3000.example. 5M IN A 10.0.8.105
+3000.example. 5M IN A 10.0.8.106
+3000.example. 5M IN A 10.0.8.107
+3000.example. 5M IN A 10.0.8.108
+3000.example. 5M IN A 10.0.8.109
+3000.example. 5M IN A 10.0.8.110
+3000.example. 5M IN A 10.0.8.111
+3000.example. 5M IN A 10.0.8.112
+3000.example. 5M IN A 10.0.8.113
+3000.example. 5M IN A 10.0.8.114
+3000.example. 5M IN A 10.0.8.115
+3000.example. 5M IN A 10.0.8.116
+3000.example. 5M IN A 10.0.8.117
+3000.example. 5M IN A 10.0.8.118
+3000.example. 5M IN A 10.0.8.119
+3000.example. 5M IN A 10.0.8.120
+3000.example. 5M IN A 10.0.8.121
+3000.example. 5M IN A 10.0.8.122
+3000.example. 5M IN A 10.0.8.123
+3000.example. 5M IN A 10.0.8.124
+3000.example. 5M IN A 10.0.8.125
+3000.example. 5M IN A 10.0.8.126
+3000.example. 5M IN A 10.0.8.127
+3000.example. 5M IN A 10.0.8.128
+3000.example. 5M IN A 10.0.8.129
+3000.example. 5M IN A 10.0.8.130
+3000.example. 5M IN A 10.0.8.131
+3000.example. 5M IN A 10.0.8.132
+3000.example. 5M IN A 10.0.8.133
+3000.example. 5M IN A 10.0.8.134
+3000.example. 5M IN A 10.0.8.135
+3000.example. 5M IN A 10.0.8.136
+3000.example. 5M IN A 10.0.8.137
+3000.example. 5M IN A 10.0.8.138
+3000.example. 5M IN A 10.0.8.139
+3000.example. 5M IN A 10.0.8.140
+3000.example. 5M IN A 10.0.8.141
+3000.example. 5M IN A 10.0.8.142
+3000.example. 5M IN A 10.0.8.143
+3000.example. 5M IN A 10.0.8.144
+3000.example. 5M IN A 10.0.8.145
+3000.example. 5M IN A 10.0.8.146
+3000.example. 5M IN A 10.0.8.147
+3000.example. 5M IN A 10.0.8.148
+3000.example. 5M IN A 10.0.8.149
+3000.example. 5M IN A 10.0.8.150
+3000.example. 5M IN A 10.0.8.151
+3000.example. 5M IN A 10.0.8.152
+3000.example. 5M IN A 10.0.8.153
+3000.example. 5M IN A 10.0.8.154
+3000.example. 5M IN A 10.0.8.155
+3000.example. 5M IN A 10.0.8.156
+3000.example. 5M IN A 10.0.8.157
+3000.example. 5M IN A 10.0.8.158
+3000.example. 5M IN A 10.0.8.159
+3000.example. 5M IN A 10.0.8.160
+3000.example. 5M IN A 10.0.8.161
+3000.example. 5M IN A 10.0.8.162
+3000.example. 5M IN A 10.0.8.163
+3000.example. 5M IN A 10.0.8.164
+3000.example. 5M IN A 10.0.8.165
+3000.example. 5M IN A 10.0.8.166
+3000.example. 5M IN A 10.0.8.167
+3000.example. 5M IN A 10.0.8.168
+3000.example. 5M IN A 10.0.8.169
+3000.example. 5M IN A 10.0.8.170
+3000.example. 5M IN A 10.0.8.171
+3000.example. 5M IN A 10.0.8.172
+3000.example. 5M IN A 10.0.8.173
+3000.example. 5M IN A 10.0.8.174
+3000.example. 5M IN A 10.0.8.175
+3000.example. 5M IN A 10.0.8.176
+3000.example. 5M IN A 10.0.8.177
+3000.example. 5M IN A 10.0.8.178
+3000.example. 5M IN A 10.0.8.179
+3000.example. 5M IN A 10.0.8.180
+3000.example. 5M IN A 10.0.8.181
+3000.example. 5M IN A 10.0.8.182
+3000.example. 5M IN A 10.0.8.183
+3000.example. 5M IN A 10.0.8.184
+3000.example. 5M IN A 10.0.8.185
+3000.example. 5M IN A 10.0.8.186
+3000.example. 5M IN A 10.0.8.187
+3000.example. 5M IN A 10.0.8.188
+3000.example. 5M IN A 10.0.8.189
+3000.example. 5M IN A 10.0.8.190
+3000.example. 5M IN A 10.0.8.191
+3000.example. 5M IN A 10.0.8.192
+3000.example. 5M IN A 10.0.8.193
+3000.example. 5M IN A 10.0.8.194
+3000.example. 5M IN A 10.0.8.195
+3000.example. 5M IN A 10.0.8.196
+3000.example. 5M IN A 10.0.8.197
+3000.example. 5M IN A 10.0.8.198
+3000.example. 5M IN A 10.0.8.199
+3000.example. 5M IN A 10.0.8.200
+3000.example. 5M IN A 10.0.8.201
+3000.example. 5M IN A 10.0.8.202
+3000.example. 5M IN A 10.0.8.203
+3000.example. 5M IN A 10.0.8.204
+3000.example. 5M IN A 10.0.8.205
+3000.example. 5M IN A 10.0.8.206
+3000.example. 5M IN A 10.0.8.207
+3000.example. 5M IN A 10.0.8.208
+3000.example. 5M IN A 10.0.8.209
+3000.example. 5M IN A 10.0.8.210
+3000.example. 5M IN A 10.0.8.211
+3000.example. 5M IN A 10.0.8.212
+3000.example. 5M IN A 10.0.8.213
+3000.example. 5M IN A 10.0.8.214
+3000.example. 5M IN A 10.0.8.215
+3000.example. 5M IN A 10.0.8.216
+3000.example. 5M IN A 10.0.8.217
+3000.example. 5M IN A 10.0.8.218
+3000.example. 5M IN A 10.0.8.219
+3000.example. 5M IN A 10.0.8.220
+3000.example. 5M IN A 10.0.8.221
+3000.example. 5M IN A 10.0.8.222
+3000.example. 5M IN A 10.0.8.223
+3000.example. 5M IN A 10.0.8.224
+3000.example. 5M IN A 10.0.8.225
+3000.example. 5M IN A 10.0.8.226
+3000.example. 5M IN A 10.0.8.227
+3000.example. 5M IN A 10.0.8.228
+3000.example. 5M IN A 10.0.8.229
+3000.example. 5M IN A 10.0.8.230
+3000.example. 5M IN A 10.0.8.231
+3000.example. 5M IN A 10.0.8.232
+3000.example. 5M IN A 10.0.8.233
+3000.example. 5M IN A 10.0.8.234
+3000.example. 5M IN A 10.0.8.235
+3000.example. 5M IN A 10.0.8.236
+3000.example. 5M IN A 10.0.8.237
+3000.example. 5M IN A 10.0.8.238
+3000.example. 5M IN A 10.0.8.239
+3000.example. 5M IN A 10.0.8.240
+3000.example. 5M IN A 10.0.8.241
+3000.example. 5M IN A 10.0.8.242
+3000.example. 5M IN A 10.0.8.243
+3000.example. 5M IN A 10.0.8.244
+3000.example. 5M IN A 10.0.8.245
+3000.example. 5M IN A 10.0.8.246
+3000.example. 5M IN A 10.0.8.247
+3000.example. 5M IN A 10.0.8.248
+3000.example. 5M IN A 10.0.8.249
+3000.example. 5M IN A 10.0.8.250
+3000.example. 5M IN A 10.0.8.251
+3000.example. 5M IN A 10.0.8.252
+3000.example. 5M IN A 10.0.8.253
+3000.example. 5M IN A 10.0.8.254
+3000.example. 5M IN A 10.0.8.255
+3000.example. 5M IN A 10.0.9.0
+3000.example. 5M IN A 10.0.9.1
+3000.example. 5M IN A 10.0.9.2
+3000.example. 5M IN A 10.0.9.3
+3000.example. 5M IN A 10.0.9.4
+3000.example. 5M IN A 10.0.9.5
+3000.example. 5M IN A 10.0.9.6
+3000.example. 5M IN A 10.0.9.7
+3000.example. 5M IN A 10.0.9.8
+3000.example. 5M IN A 10.0.9.9
+3000.example. 5M IN A 10.0.9.10
+3000.example. 5M IN A 10.0.9.11
+3000.example. 5M IN A 10.0.9.12
+3000.example. 5M IN A 10.0.9.13
+3000.example. 5M IN A 10.0.9.14
+3000.example. 5M IN A 10.0.9.15
+3000.example. 5M IN A 10.0.9.16
+3000.example. 5M IN A 10.0.9.17
+3000.example. 5M IN A 10.0.9.18
+3000.example. 5M IN A 10.0.9.19
+3000.example. 5M IN A 10.0.9.20
+3000.example. 5M IN A 10.0.9.21
+3000.example. 5M IN A 10.0.9.22
+3000.example. 5M IN A 10.0.9.23
+3000.example. 5M IN A 10.0.9.24
+3000.example. 5M IN A 10.0.9.25
+3000.example. 5M IN A 10.0.9.26
+3000.example. 5M IN A 10.0.9.27
+3000.example. 5M IN A 10.0.9.28
+3000.example. 5M IN A 10.0.9.29
+3000.example. 5M IN A 10.0.9.30
+3000.example. 5M IN A 10.0.9.31
+3000.example. 5M IN A 10.0.9.32
+3000.example. 5M IN A 10.0.9.33
+3000.example. 5M IN A 10.0.9.34
+3000.example. 5M IN A 10.0.9.35
+3000.example. 5M IN A 10.0.9.36
+3000.example. 5M IN A 10.0.9.37
+3000.example. 5M IN A 10.0.9.38
+3000.example. 5M IN A 10.0.9.39
+3000.example. 5M IN A 10.0.9.40
+3000.example. 5M IN A 10.0.9.41
+3000.example. 5M IN A 10.0.9.42
+3000.example. 5M IN A 10.0.9.43
+3000.example. 5M IN A 10.0.9.44
+3000.example. 5M IN A 10.0.9.45
+3000.example. 5M IN A 10.0.9.46
+3000.example. 5M IN A 10.0.9.47
+3000.example. 5M IN A 10.0.9.48
+3000.example. 5M IN A 10.0.9.49
+3000.example. 5M IN A 10.0.9.50
+3000.example. 5M IN A 10.0.9.51
+3000.example. 5M IN A 10.0.9.52
+3000.example. 5M IN A 10.0.9.53
+3000.example. 5M IN A 10.0.9.54
+3000.example. 5M IN A 10.0.9.55
+3000.example. 5M IN A 10.0.9.56
+3000.example. 5M IN A 10.0.9.57
+3000.example. 5M IN A 10.0.9.58
+3000.example. 5M IN A 10.0.9.59
+3000.example. 5M IN A 10.0.9.60
+3000.example. 5M IN A 10.0.9.61
+3000.example. 5M IN A 10.0.9.62
+3000.example. 5M IN A 10.0.9.63
+3000.example. 5M IN A 10.0.9.64
+3000.example. 5M IN A 10.0.9.65
+3000.example. 5M IN A 10.0.9.66
+3000.example. 5M IN A 10.0.9.67
+3000.example. 5M IN A 10.0.9.68
+3000.example. 5M IN A 10.0.9.69
+3000.example. 5M IN A 10.0.9.70
+3000.example. 5M IN A 10.0.9.71
+3000.example. 5M IN A 10.0.9.72
+3000.example. 5M IN A 10.0.9.73
+3000.example. 5M IN A 10.0.9.74
+3000.example. 5M IN A 10.0.9.75
+3000.example. 5M IN A 10.0.9.76
+3000.example. 5M IN A 10.0.9.77
+3000.example. 5M IN A 10.0.9.78
+3000.example. 5M IN A 10.0.9.79
+3000.example. 5M IN A 10.0.9.80
+3000.example. 5M IN A 10.0.9.81
+3000.example. 5M IN A 10.0.9.82
+3000.example. 5M IN A 10.0.9.83
+3000.example. 5M IN A 10.0.9.84
+3000.example. 5M IN A 10.0.9.85
+3000.example. 5M IN A 10.0.9.86
+3000.example. 5M IN A 10.0.9.87
+3000.example. 5M IN A 10.0.9.88
+3000.example. 5M IN A 10.0.9.89
+3000.example. 5M IN A 10.0.9.90
+3000.example. 5M IN A 10.0.9.91
+3000.example. 5M IN A 10.0.9.92
+3000.example. 5M IN A 10.0.9.93
+3000.example. 5M IN A 10.0.9.94
+3000.example. 5M IN A 10.0.9.95
+3000.example. 5M IN A 10.0.9.96
+3000.example. 5M IN A 10.0.9.97
+3000.example. 5M IN A 10.0.9.98
+3000.example. 5M IN A 10.0.9.99
+3000.example. 5M IN A 10.0.9.100
+3000.example. 5M IN A 10.0.9.101
+3000.example. 5M IN A 10.0.9.102
+3000.example. 5M IN A 10.0.9.103
+3000.example. 5M IN A 10.0.9.104
+3000.example. 5M IN A 10.0.9.105
+3000.example. 5M IN A 10.0.9.106
+3000.example. 5M IN A 10.0.9.107
+3000.example. 5M IN A 10.0.9.108
+3000.example. 5M IN A 10.0.9.109
+3000.example. 5M IN A 10.0.9.110
+3000.example. 5M IN A 10.0.9.111
+3000.example. 5M IN A 10.0.9.112
+3000.example. 5M IN A 10.0.9.113
+3000.example. 5M IN A 10.0.9.114
+3000.example. 5M IN A 10.0.9.115
+3000.example. 5M IN A 10.0.9.116
+3000.example. 5M IN A 10.0.9.117
+3000.example. 5M IN A 10.0.9.118
+3000.example. 5M IN A 10.0.9.119
+3000.example. 5M IN A 10.0.9.120
+3000.example. 5M IN A 10.0.9.121
+3000.example. 5M IN A 10.0.9.122
+3000.example. 5M IN A 10.0.9.123
+3000.example. 5M IN A 10.0.9.124
+3000.example. 5M IN A 10.0.9.125
+3000.example. 5M IN A 10.0.9.126
+3000.example. 5M IN A 10.0.9.127
+3000.example. 5M IN A 10.0.9.128
+3000.example. 5M IN A 10.0.9.129
+3000.example. 5M IN A 10.0.9.130
+3000.example. 5M IN A 10.0.9.131
+3000.example. 5M IN A 10.0.9.132
+3000.example. 5M IN A 10.0.9.133
+3000.example. 5M IN A 10.0.9.134
+3000.example. 5M IN A 10.0.9.135
+3000.example. 5M IN A 10.0.9.136
+3000.example. 5M IN A 10.0.9.137
+3000.example. 5M IN A 10.0.9.138
+3000.example. 5M IN A 10.0.9.139
+3000.example. 5M IN A 10.0.9.140
+3000.example. 5M IN A 10.0.9.141
+3000.example. 5M IN A 10.0.9.142
+3000.example. 5M IN A 10.0.9.143
+3000.example. 5M IN A 10.0.9.144
+3000.example. 5M IN A 10.0.9.145
+3000.example. 5M IN A 10.0.9.146
+3000.example. 5M IN A 10.0.9.147
+3000.example. 5M IN A 10.0.9.148
+3000.example. 5M IN A 10.0.9.149
+3000.example. 5M IN A 10.0.9.150
+3000.example. 5M IN A 10.0.9.151
+3000.example. 5M IN A 10.0.9.152
+3000.example. 5M IN A 10.0.9.153
+3000.example. 5M IN A 10.0.9.154
+3000.example. 5M IN A 10.0.9.155
+3000.example. 5M IN A 10.0.9.156
+3000.example. 5M IN A 10.0.9.157
+3000.example. 5M IN A 10.0.9.158
+3000.example. 5M IN A 10.0.9.159
+3000.example. 5M IN A 10.0.9.160
+3000.example. 5M IN A 10.0.9.161
+3000.example. 5M IN A 10.0.9.162
+3000.example. 5M IN A 10.0.9.163
+3000.example. 5M IN A 10.0.9.164
+3000.example. 5M IN A 10.0.9.165
+3000.example. 5M IN A 10.0.9.166
+3000.example. 5M IN A 10.0.9.167
+3000.example. 5M IN A 10.0.9.168
+3000.example. 5M IN A 10.0.9.169
+3000.example. 5M IN A 10.0.9.170
+3000.example. 5M IN A 10.0.9.171
+3000.example. 5M IN A 10.0.9.172
+3000.example. 5M IN A 10.0.9.173
+3000.example. 5M IN A 10.0.9.174
+3000.example. 5M IN A 10.0.9.175
+3000.example. 5M IN A 10.0.9.176
+3000.example. 5M IN A 10.0.9.177
+3000.example. 5M IN A 10.0.9.178
+3000.example. 5M IN A 10.0.9.179
+3000.example. 5M IN A 10.0.9.180
+3000.example. 5M IN A 10.0.9.181
+3000.example. 5M IN A 10.0.9.182
+3000.example. 5M IN A 10.0.9.183
+3000.example. 5M IN A 10.0.9.184
+3000.example. 5M IN A 10.0.9.185
+3000.example. 5M IN A 10.0.9.186
+3000.example. 5M IN A 10.0.9.187
+3000.example. 5M IN A 10.0.9.188
+3000.example. 5M IN A 10.0.9.189
+3000.example. 5M IN A 10.0.9.190
+3000.example. 5M IN A 10.0.9.191
+3000.example. 5M IN A 10.0.9.192
+3000.example. 5M IN A 10.0.9.193
+3000.example. 5M IN A 10.0.9.194
+3000.example. 5M IN A 10.0.9.195
+3000.example. 5M IN A 10.0.9.196
+3000.example. 5M IN A 10.0.9.197
+3000.example. 5M IN A 10.0.9.198
+3000.example. 5M IN A 10.0.9.199
+3000.example. 5M IN A 10.0.9.200
+3000.example. 5M IN A 10.0.9.201
+3000.example. 5M IN A 10.0.9.202
+3000.example. 5M IN A 10.0.9.203
+3000.example. 5M IN A 10.0.9.204
+3000.example. 5M IN A 10.0.9.205
+3000.example. 5M IN A 10.0.9.206
+3000.example. 5M IN A 10.0.9.207
+3000.example. 5M IN A 10.0.9.208
+3000.example. 5M IN A 10.0.9.209
+3000.example. 5M IN A 10.0.9.210
+3000.example. 5M IN A 10.0.9.211
+3000.example. 5M IN A 10.0.9.212
+3000.example. 5M IN A 10.0.9.213
+3000.example. 5M IN A 10.0.9.214
+3000.example. 5M IN A 10.0.9.215
+3000.example. 5M IN A 10.0.9.216
+3000.example. 5M IN A 10.0.9.217
+3000.example. 5M IN A 10.0.9.218
+3000.example. 5M IN A 10.0.9.219
+3000.example. 5M IN A 10.0.9.220
+3000.example. 5M IN A 10.0.9.221
+3000.example. 5M IN A 10.0.9.222
+3000.example. 5M IN A 10.0.9.223
+3000.example. 5M IN A 10.0.9.224
+3000.example. 5M IN A 10.0.9.225
+3000.example. 5M IN A 10.0.9.226
+3000.example. 5M IN A 10.0.9.227
+3000.example. 5M IN A 10.0.9.228
+3000.example. 5M IN A 10.0.9.229
+3000.example. 5M IN A 10.0.9.230
+3000.example. 5M IN A 10.0.9.231
+3000.example. 5M IN A 10.0.9.232
+3000.example. 5M IN A 10.0.9.233
+3000.example. 5M IN A 10.0.9.234
+3000.example. 5M IN A 10.0.9.235
+3000.example. 5M IN A 10.0.9.236
+3000.example. 5M IN A 10.0.9.237
+3000.example. 5M IN A 10.0.9.238
+3000.example. 5M IN A 10.0.9.239
+3000.example. 5M IN A 10.0.9.240
+3000.example. 5M IN A 10.0.9.241
+3000.example. 5M IN A 10.0.9.242
+3000.example. 5M IN A 10.0.9.243
+3000.example. 5M IN A 10.0.9.244
+3000.example. 5M IN A 10.0.9.245
+3000.example. 5M IN A 10.0.9.246
+3000.example. 5M IN A 10.0.9.247
+3000.example. 5M IN A 10.0.9.248
+3000.example. 5M IN A 10.0.9.249
+3000.example. 5M IN A 10.0.9.250
+3000.example. 5M IN A 10.0.9.251
+3000.example. 5M IN A 10.0.9.252
+3000.example. 5M IN A 10.0.9.253
+3000.example. 5M IN A 10.0.9.254
+3000.example. 5M IN A 10.0.9.255
+3000.example. 5M IN A 10.0.10.0
+3000.example. 5M IN A 10.0.10.1
+3000.example. 5M IN A 10.0.10.2
+3000.example. 5M IN A 10.0.10.3
+3000.example. 5M IN A 10.0.10.4
+3000.example. 5M IN A 10.0.10.5
+3000.example. 5M IN A 10.0.10.6
+3000.example. 5M IN A 10.0.10.7
+3000.example. 5M IN A 10.0.10.8
+3000.example. 5M IN A 10.0.10.9
+3000.example. 5M IN A 10.0.10.10
+3000.example. 5M IN A 10.0.10.11
+3000.example. 5M IN A 10.0.10.12
+3000.example. 5M IN A 10.0.10.13
+3000.example. 5M IN A 10.0.10.14
+3000.example. 5M IN A 10.0.10.15
+3000.example. 5M IN A 10.0.10.16
+3000.example. 5M IN A 10.0.10.17
+3000.example. 5M IN A 10.0.10.18
+3000.example. 5M IN A 10.0.10.19
+3000.example. 5M IN A 10.0.10.20
+3000.example. 5M IN A 10.0.10.21
+3000.example. 5M IN A 10.0.10.22
+3000.example. 5M IN A 10.0.10.23
+3000.example. 5M IN A 10.0.10.24
+3000.example. 5M IN A 10.0.10.25
+3000.example. 5M IN A 10.0.10.26
+3000.example. 5M IN A 10.0.10.27
+3000.example. 5M IN A 10.0.10.28
+3000.example. 5M IN A 10.0.10.29
+3000.example. 5M IN A 10.0.10.30
+3000.example. 5M IN A 10.0.10.31
+3000.example. 5M IN A 10.0.10.32
+3000.example. 5M IN A 10.0.10.33
+3000.example. 5M IN A 10.0.10.34
+3000.example. 5M IN A 10.0.10.35
+3000.example. 5M IN A 10.0.10.36
+3000.example. 5M IN A 10.0.10.37
+3000.example. 5M IN A 10.0.10.38
+3000.example. 5M IN A 10.0.10.39
+3000.example. 5M IN A 10.0.10.40
+3000.example. 5M IN A 10.0.10.41
+3000.example. 5M IN A 10.0.10.42
+3000.example. 5M IN A 10.0.10.43
+3000.example. 5M IN A 10.0.10.44
+3000.example. 5M IN A 10.0.10.45
+3000.example. 5M IN A 10.0.10.46
+3000.example. 5M IN A 10.0.10.47
+3000.example. 5M IN A 10.0.10.48
+3000.example. 5M IN A 10.0.10.49
+3000.example. 5M IN A 10.0.10.50
+3000.example. 5M IN A 10.0.10.51
+3000.example. 5M IN A 10.0.10.52
+3000.example. 5M IN A 10.0.10.53
+3000.example. 5M IN A 10.0.10.54
+3000.example. 5M IN A 10.0.10.55
+3000.example. 5M IN A 10.0.10.56
+3000.example. 5M IN A 10.0.10.57
+3000.example. 5M IN A 10.0.10.58
+3000.example. 5M IN A 10.0.10.59
+3000.example. 5M IN A 10.0.10.60
+3000.example. 5M IN A 10.0.10.61
+3000.example. 5M IN A 10.0.10.62
+3000.example. 5M IN A 10.0.10.63
+3000.example. 5M IN A 10.0.10.64
+3000.example. 5M IN A 10.0.10.65
+3000.example. 5M IN A 10.0.10.66
+3000.example. 5M IN A 10.0.10.67
+3000.example. 5M IN A 10.0.10.68
+3000.example. 5M IN A 10.0.10.69
+3000.example. 5M IN A 10.0.10.70
+3000.example. 5M IN A 10.0.10.71
+3000.example. 5M IN A 10.0.10.72
+3000.example. 5M IN A 10.0.10.73
+3000.example. 5M IN A 10.0.10.74
+3000.example. 5M IN A 10.0.10.75
+3000.example. 5M IN A 10.0.10.76
+3000.example. 5M IN A 10.0.10.77
+3000.example. 5M IN A 10.0.10.78
+3000.example. 5M IN A 10.0.10.79
+3000.example. 5M IN A 10.0.10.80
+3000.example. 5M IN A 10.0.10.81
+3000.example. 5M IN A 10.0.10.82
+3000.example. 5M IN A 10.0.10.83
+3000.example. 5M IN A 10.0.10.84
+3000.example. 5M IN A 10.0.10.85
+3000.example. 5M IN A 10.0.10.86
+3000.example. 5M IN A 10.0.10.87
+3000.example. 5M IN A 10.0.10.88
+3000.example. 5M IN A 10.0.10.89
+3000.example. 5M IN A 10.0.10.90
+3000.example. 5M IN A 10.0.10.91
+3000.example. 5M IN A 10.0.10.92
+3000.example. 5M IN A 10.0.10.93
+3000.example. 5M IN A 10.0.10.94
+3000.example. 5M IN A 10.0.10.95
+3000.example. 5M IN A 10.0.10.96
+3000.example. 5M IN A 10.0.10.97
+3000.example. 5M IN A 10.0.10.98
+3000.example. 5M IN A 10.0.10.99
+3000.example. 5M IN A 10.0.10.100
+3000.example. 5M IN A 10.0.10.101
+3000.example. 5M IN A 10.0.10.102
+3000.example. 5M IN A 10.0.10.103
+3000.example. 5M IN A 10.0.10.104
+3000.example. 5M IN A 10.0.10.105
+3000.example. 5M IN A 10.0.10.106
+3000.example. 5M IN A 10.0.10.107
+3000.example. 5M IN A 10.0.10.108
+3000.example. 5M IN A 10.0.10.109
+3000.example. 5M IN A 10.0.10.110
+3000.example. 5M IN A 10.0.10.111
+3000.example. 5M IN A 10.0.10.112
+3000.example. 5M IN A 10.0.10.113
+3000.example. 5M IN A 10.0.10.114
+3000.example. 5M IN A 10.0.10.115
+3000.example. 5M IN A 10.0.10.116
+3000.example. 5M IN A 10.0.10.117
+3000.example. 5M IN A 10.0.10.118
+3000.example. 5M IN A 10.0.10.119
+3000.example. 5M IN A 10.0.10.120
+3000.example. 5M IN A 10.0.10.121
+3000.example. 5M IN A 10.0.10.122
+3000.example. 5M IN A 10.0.10.123
+3000.example. 5M IN A 10.0.10.124
+3000.example. 5M IN A 10.0.10.125
+3000.example. 5M IN A 10.0.10.126
+3000.example. 5M IN A 10.0.10.127
+3000.example. 5M IN A 10.0.10.128
+3000.example. 5M IN A 10.0.10.129
+3000.example. 5M IN A 10.0.10.130
+3000.example. 5M IN A 10.0.10.131
+3000.example. 5M IN A 10.0.10.132
+3000.example. 5M IN A 10.0.10.133
+3000.example. 5M IN A 10.0.10.134
+3000.example. 5M IN A 10.0.10.135
+3000.example. 5M IN A 10.0.10.136
+3000.example. 5M IN A 10.0.10.137
+3000.example. 5M IN A 10.0.10.138
+3000.example. 5M IN A 10.0.10.139
+3000.example. 5M IN A 10.0.10.140
+3000.example. 5M IN A 10.0.10.141
+3000.example. 5M IN A 10.0.10.142
+3000.example. 5M IN A 10.0.10.143
+3000.example. 5M IN A 10.0.10.144
+3000.example. 5M IN A 10.0.10.145
+3000.example. 5M IN A 10.0.10.146
+3000.example. 5M IN A 10.0.10.147
+3000.example. 5M IN A 10.0.10.148
+3000.example. 5M IN A 10.0.10.149
+3000.example. 5M IN A 10.0.10.150
+3000.example. 5M IN A 10.0.10.151
+3000.example. 5M IN A 10.0.10.152
+3000.example. 5M IN A 10.0.10.153
+3000.example. 5M IN A 10.0.10.154
+3000.example. 5M IN A 10.0.10.155
+3000.example. 5M IN A 10.0.10.156
+3000.example. 5M IN A 10.0.10.157
+3000.example. 5M IN A 10.0.10.158
+3000.example. 5M IN A 10.0.10.159
+3000.example. 5M IN A 10.0.10.160
+3000.example. 5M IN A 10.0.10.161
+3000.example. 5M IN A 10.0.10.162
+3000.example. 5M IN A 10.0.10.163
+3000.example. 5M IN A 10.0.10.164
+3000.example. 5M IN A 10.0.10.165
+3000.example. 5M IN A 10.0.10.166
+3000.example. 5M IN A 10.0.10.167
+3000.example. 5M IN A 10.0.10.168
+3000.example. 5M IN A 10.0.10.169
+3000.example. 5M IN A 10.0.10.170
+3000.example. 5M IN A 10.0.10.171
+3000.example. 5M IN A 10.0.10.172
+3000.example. 5M IN A 10.0.10.173
+3000.example. 5M IN A 10.0.10.174
+3000.example. 5M IN A 10.0.10.175
+3000.example. 5M IN A 10.0.10.176
+3000.example. 5M IN A 10.0.10.177
+3000.example. 5M IN A 10.0.10.178
+3000.example. 5M IN A 10.0.10.179
+3000.example. 5M IN A 10.0.10.180
+3000.example. 5M IN A 10.0.10.181
+3000.example. 5M IN A 10.0.10.182
+3000.example. 5M IN A 10.0.10.183
+3000.example. 5M IN A 10.0.10.184
+3000.example. 5M IN A 10.0.10.185
+3000.example. 5M IN A 10.0.10.186
+3000.example. 5M IN A 10.0.10.187
+3000.example. 5M IN A 10.0.10.188
+3000.example. 5M IN A 10.0.10.189
+3000.example. 5M IN A 10.0.10.190
+3000.example. 5M IN A 10.0.10.191
+3000.example. 5M IN A 10.0.10.192
+3000.example. 5M IN A 10.0.10.193
+3000.example. 5M IN A 10.0.10.194
+3000.example. 5M IN A 10.0.10.195
+3000.example. 5M IN A 10.0.10.196
+3000.example. 5M IN A 10.0.10.197
+3000.example. 5M IN A 10.0.10.198
+3000.example. 5M IN A 10.0.10.199
+3000.example. 5M IN A 10.0.10.200
+3000.example. 5M IN A 10.0.10.201
+3000.example. 5M IN A 10.0.10.202
+3000.example. 5M IN A 10.0.10.203
+3000.example. 5M IN A 10.0.10.204
+3000.example. 5M IN A 10.0.10.205
+3000.example. 5M IN A 10.0.10.206
+3000.example. 5M IN A 10.0.10.207
+3000.example. 5M IN A 10.0.10.208
+3000.example. 5M IN A 10.0.10.209
+3000.example. 5M IN A 10.0.10.210
+3000.example. 5M IN A 10.0.10.211
+3000.example. 5M IN A 10.0.10.212
+3000.example. 5M IN A 10.0.10.213
+3000.example. 5M IN A 10.0.10.214
+3000.example. 5M IN A 10.0.10.215
+3000.example. 5M IN A 10.0.10.216
+3000.example. 5M IN A 10.0.10.217
+3000.example. 5M IN A 10.0.10.218
+3000.example. 5M IN A 10.0.10.219
+3000.example. 5M IN A 10.0.10.220
+3000.example. 5M IN A 10.0.10.221
+3000.example. 5M IN A 10.0.10.222
+3000.example. 5M IN A 10.0.10.223
+3000.example. 5M IN A 10.0.10.224
+3000.example. 5M IN A 10.0.10.225
+3000.example. 5M IN A 10.0.10.226
+3000.example. 5M IN A 10.0.10.227
+3000.example. 5M IN A 10.0.10.228
+3000.example. 5M IN A 10.0.10.229
+3000.example. 5M IN A 10.0.10.230
+3000.example. 5M IN A 10.0.10.231
+3000.example. 5M IN A 10.0.10.232
+3000.example. 5M IN A 10.0.10.233
+3000.example. 5M IN A 10.0.10.234
+3000.example. 5M IN A 10.0.10.235
+3000.example. 5M IN A 10.0.10.236
+3000.example. 5M IN A 10.0.10.237
+3000.example. 5M IN A 10.0.10.238
+3000.example. 5M IN A 10.0.10.239
+3000.example. 5M IN A 10.0.10.240
+3000.example. 5M IN A 10.0.10.241
+3000.example. 5M IN A 10.0.10.242
+3000.example. 5M IN A 10.0.10.243
+3000.example. 5M IN A 10.0.10.244
+3000.example. 5M IN A 10.0.10.245
+3000.example. 5M IN A 10.0.10.246
+3000.example. 5M IN A 10.0.10.247
+3000.example. 5M IN A 10.0.10.248
+3000.example. 5M IN A 10.0.10.249
+3000.example. 5M IN A 10.0.10.250
+3000.example. 5M IN A 10.0.10.251
+3000.example. 5M IN A 10.0.10.252
+3000.example. 5M IN A 10.0.10.253
+3000.example. 5M IN A 10.0.10.254
+3000.example. 5M IN A 10.0.10.255
+3000.example. 5M IN A 10.0.11.0
+3000.example. 5M IN A 10.0.11.1
+3000.example. 5M IN A 10.0.11.2
+3000.example. 5M IN A 10.0.11.3
+3000.example. 5M IN A 10.0.11.4
+3000.example. 5M IN A 10.0.11.5
+3000.example. 5M IN A 10.0.11.6
+3000.example. 5M IN A 10.0.11.7
+3000.example. 5M IN A 10.0.11.8
+3000.example. 5M IN A 10.0.11.9
+3000.example. 5M IN A 10.0.11.10
+3000.example. 5M IN A 10.0.11.11
+3000.example. 5M IN A 10.0.11.12
+3000.example. 5M IN A 10.0.11.13
+3000.example. 5M IN A 10.0.11.14
+3000.example. 5M IN A 10.0.11.15
+3000.example. 5M IN A 10.0.11.16
+3000.example. 5M IN A 10.0.11.17
+3000.example. 5M IN A 10.0.11.18
+3000.example. 5M IN A 10.0.11.19
+3000.example. 5M IN A 10.0.11.20
+3000.example. 5M IN A 10.0.11.21
+3000.example. 5M IN A 10.0.11.22
+3000.example. 5M IN A 10.0.11.23
+3000.example. 5M IN A 10.0.11.24
+3000.example. 5M IN A 10.0.11.25
+3000.example. 5M IN A 10.0.11.26
+3000.example. 5M IN A 10.0.11.27
+3000.example. 5M IN A 10.0.11.28
+3000.example. 5M IN A 10.0.11.29
+3000.example. 5M IN A 10.0.11.30
+3000.example. 5M IN A 10.0.11.31
+3000.example. 5M IN A 10.0.11.32
+3000.example. 5M IN A 10.0.11.33
+3000.example. 5M IN A 10.0.11.34
+3000.example. 5M IN A 10.0.11.35
+3000.example. 5M IN A 10.0.11.36
+3000.example. 5M IN A 10.0.11.37
+3000.example. 5M IN A 10.0.11.38
+3000.example. 5M IN A 10.0.11.39
+3000.example. 5M IN A 10.0.11.40
+3000.example. 5M IN A 10.0.11.41
+3000.example. 5M IN A 10.0.11.42
+3000.example. 5M IN A 10.0.11.43
+3000.example. 5M IN A 10.0.11.44
+3000.example. 5M IN A 10.0.11.45
+3000.example. 5M IN A 10.0.11.46
+3000.example. 5M IN A 10.0.11.47
+3000.example. 5M IN A 10.0.11.48
+3000.example. 5M IN A 10.0.11.49
+3000.example. 5M IN A 10.0.11.50
+3000.example. 5M IN A 10.0.11.51
+3000.example. 5M IN A 10.0.11.52
+3000.example. 5M IN A 10.0.11.53
+3000.example. 5M IN A 10.0.11.54
+3000.example. 5M IN A 10.0.11.55
+3000.example. 5M IN A 10.0.11.56
+3000.example. 5M IN A 10.0.11.57
+3000.example. 5M IN A 10.0.11.58
+3000.example. 5M IN A 10.0.11.59
+3000.example. 5M IN A 10.0.11.60
+3000.example. 5M IN A 10.0.11.61
+3000.example. 5M IN A 10.0.11.62
+3000.example. 5M IN A 10.0.11.63
+3000.example. 5M IN A 10.0.11.64
+3000.example. 5M IN A 10.0.11.65
+3000.example. 5M IN A 10.0.11.66
+3000.example. 5M IN A 10.0.11.67
+3000.example. 5M IN A 10.0.11.68
+3000.example. 5M IN A 10.0.11.69
+3000.example. 5M IN A 10.0.11.70
+3000.example. 5M IN A 10.0.11.71
+3000.example. 5M IN A 10.0.11.72
+3000.example. 5M IN A 10.0.11.73
+3000.example. 5M IN A 10.0.11.74
+3000.example. 5M IN A 10.0.11.75
+3000.example. 5M IN A 10.0.11.76
+3000.example. 5M IN A 10.0.11.77
+3000.example. 5M IN A 10.0.11.78
+3000.example. 5M IN A 10.0.11.79
+3000.example. 5M IN A 10.0.11.80
+3000.example. 5M IN A 10.0.11.81
+3000.example. 5M IN A 10.0.11.82
+3000.example. 5M IN A 10.0.11.83
+3000.example. 5M IN A 10.0.11.84
+3000.example. 5M IN A 10.0.11.85
+3000.example. 5M IN A 10.0.11.86
+3000.example. 5M IN A 10.0.11.87
+3000.example. 5M IN A 10.0.11.88
+3000.example. 5M IN A 10.0.11.89
+3000.example. 5M IN A 10.0.11.90
+3000.example. 5M IN A 10.0.11.91
+3000.example. 5M IN A 10.0.11.92
+3000.example. 5M IN A 10.0.11.93
+3000.example. 5M IN A 10.0.11.94
+3000.example. 5M IN A 10.0.11.95
+3000.example. 5M IN A 10.0.11.96
+3000.example. 5M IN A 10.0.11.97
+3000.example. 5M IN A 10.0.11.98
+3000.example. 5M IN A 10.0.11.99
+3000.example. 5M IN A 10.0.11.100
+3000.example. 5M IN A 10.0.11.101
+3000.example. 5M IN A 10.0.11.102
+3000.example. 5M IN A 10.0.11.103
+3000.example. 5M IN A 10.0.11.104
+3000.example. 5M IN A 10.0.11.105
+3000.example. 5M IN A 10.0.11.106
+3000.example. 5M IN A 10.0.11.107
+3000.example. 5M IN A 10.0.11.108
+3000.example. 5M IN A 10.0.11.109
+3000.example. 5M IN A 10.0.11.110
+3000.example. 5M IN A 10.0.11.111
+3000.example. 5M IN A 10.0.11.112
+3000.example. 5M IN A 10.0.11.113
+3000.example. 5M IN A 10.0.11.114
+3000.example. 5M IN A 10.0.11.115
+3000.example. 5M IN A 10.0.11.116
+3000.example. 5M IN A 10.0.11.117
+3000.example. 5M IN A 10.0.11.118
+3000.example. 5M IN A 10.0.11.119
+3000.example. 5M IN A 10.0.11.120
+3000.example. 5M IN A 10.0.11.121
+3000.example. 5M IN A 10.0.11.122
+3000.example. 5M IN A 10.0.11.123
+3000.example. 5M IN A 10.0.11.124
+3000.example. 5M IN A 10.0.11.125
+3000.example. 5M IN A 10.0.11.126
+3000.example. 5M IN A 10.0.11.127
+3000.example. 5M IN A 10.0.11.128
+3000.example. 5M IN A 10.0.11.129
+3000.example. 5M IN A 10.0.11.130
+3000.example. 5M IN A 10.0.11.131
+3000.example. 5M IN A 10.0.11.132
+3000.example. 5M IN A 10.0.11.133
+3000.example. 5M IN A 10.0.11.134
+3000.example. 5M IN A 10.0.11.135
+3000.example. 5M IN A 10.0.11.136
+3000.example. 5M IN A 10.0.11.137
+3000.example. 5M IN A 10.0.11.138
+3000.example. 5M IN A 10.0.11.139
+3000.example. 5M IN A 10.0.11.140
+3000.example. 5M IN A 10.0.11.141
+3000.example. 5M IN A 10.0.11.142
+3000.example. 5M IN A 10.0.11.143
+3000.example. 5M IN A 10.0.11.144
+3000.example. 5M IN A 10.0.11.145
+3000.example. 5M IN A 10.0.11.146
+3000.example. 5M IN A 10.0.11.147
+3000.example. 5M IN A 10.0.11.148
+3000.example. 5M IN A 10.0.11.149
+3000.example. 5M IN A 10.0.11.150
+3000.example. 5M IN A 10.0.11.151
+3000.example. 5M IN A 10.0.11.152
+3000.example. 5M IN A 10.0.11.153
+3000.example. 5M IN A 10.0.11.154
+3000.example. 5M IN A 10.0.11.155
+3000.example. 5M IN A 10.0.11.156
+3000.example. 5M IN A 10.0.11.157
+3000.example. 5M IN A 10.0.11.158
+3000.example. 5M IN A 10.0.11.159
+3000.example. 5M IN A 10.0.11.160
+3000.example. 5M IN A 10.0.11.161
+3000.example. 5M IN A 10.0.11.162
+3000.example. 5M IN A 10.0.11.163
+3000.example. 5M IN A 10.0.11.164
+3000.example. 5M IN A 10.0.11.165
+3000.example. 5M IN A 10.0.11.166
+3000.example. 5M IN A 10.0.11.167
+3000.example. 5M IN A 10.0.11.168
+3000.example. 5M IN A 10.0.11.169
+3000.example. 5M IN A 10.0.11.170
+3000.example. 5M IN A 10.0.11.171
+3000.example. 5M IN A 10.0.11.172
+3000.example. 5M IN A 10.0.11.173
+3000.example. 5M IN A 10.0.11.174
+3000.example. 5M IN A 10.0.11.175
+3000.example. 5M IN A 10.0.11.176
+3000.example. 5M IN A 10.0.11.177
+3000.example. 5M IN A 10.0.11.178
+3000.example. 5M IN A 10.0.11.179
+3000.example. 5M IN A 10.0.11.180
+3000.example. 5M IN A 10.0.11.181
+3000.example. 5M IN A 10.0.11.182
+3000.example. 5M IN A 10.0.11.183
+
+;; AUTHORITY SECTION:
+example. 5M IN NS ns1.example.
+
+;; ADDITIONAL SECTION:
+ns1.example. 5M IN A 10.53.0.1
+
+;; Total query time: 211 msec
+;; FROM: draco to SERVER: 10.53.0.1
+;; WHEN: Fri Jun 23 12:58:17 2000
+;; MSG SIZE sent: 30 rcvd: 48068
+
diff --git a/bin/tests/system/limits/knowngood.dig.out.4000 b/bin/tests/system/limits/knowngood.dig.out.4000
new file mode 100644
index 0000000..8b109c8
--- /dev/null
+++ b/bin/tests/system/limits/knowngood.dig.out.4000
@@ -0,0 +1,4023 @@
+
+; <<>> DiG 8.2 <<>> 4000.example. @10.53.0.1 a -p
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr aa rd ad; QUERY: 1, ANSWER: 4000, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; 4000.example, type = A, class = IN
+
+;; ANSWER SECTION:
+4000.example. 5M IN A 10.0.0.0
+4000.example. 5M IN A 10.0.0.1
+4000.example. 5M IN A 10.0.0.2
+4000.example. 5M IN A 10.0.0.3
+4000.example. 5M IN A 10.0.0.4
+4000.example. 5M IN A 10.0.0.5
+4000.example. 5M IN A 10.0.0.6
+4000.example. 5M IN A 10.0.0.7
+4000.example. 5M IN A 10.0.0.8
+4000.example. 5M IN A 10.0.0.9
+4000.example. 5M IN A 10.0.0.10
+4000.example. 5M IN A 10.0.0.11
+4000.example. 5M IN A 10.0.0.12
+4000.example. 5M IN A 10.0.0.13
+4000.example. 5M IN A 10.0.0.14
+4000.example. 5M IN A 10.0.0.15
+4000.example. 5M IN A 10.0.0.16
+4000.example. 5M IN A 10.0.0.17
+4000.example. 5M IN A 10.0.0.18
+4000.example. 5M IN A 10.0.0.19
+4000.example. 5M IN A 10.0.0.20
+4000.example. 5M IN A 10.0.0.21
+4000.example. 5M IN A 10.0.0.22
+4000.example. 5M IN A 10.0.0.23
+4000.example. 5M IN A 10.0.0.24
+4000.example. 5M IN A 10.0.0.25
+4000.example. 5M IN A 10.0.0.26
+4000.example. 5M IN A 10.0.0.27
+4000.example. 5M IN A 10.0.0.28
+4000.example. 5M IN A 10.0.0.29
+4000.example. 5M IN A 10.0.0.30
+4000.example. 5M IN A 10.0.0.31
+4000.example. 5M IN A 10.0.0.32
+4000.example. 5M IN A 10.0.0.33
+4000.example. 5M IN A 10.0.0.34
+4000.example. 5M IN A 10.0.0.35
+4000.example. 5M IN A 10.0.0.36
+4000.example. 5M IN A 10.0.0.37
+4000.example. 5M IN A 10.0.0.38
+4000.example. 5M IN A 10.0.0.39
+4000.example. 5M IN A 10.0.0.40
+4000.example. 5M IN A 10.0.0.41
+4000.example. 5M IN A 10.0.0.42
+4000.example. 5M IN A 10.0.0.43
+4000.example. 5M IN A 10.0.0.44
+4000.example. 5M IN A 10.0.0.45
+4000.example. 5M IN A 10.0.0.46
+4000.example. 5M IN A 10.0.0.47
+4000.example. 5M IN A 10.0.0.48
+4000.example. 5M IN A 10.0.0.49
+4000.example. 5M IN A 10.0.0.50
+4000.example. 5M IN A 10.0.0.51
+4000.example. 5M IN A 10.0.0.52
+4000.example. 5M IN A 10.0.0.53
+4000.example. 5M IN A 10.0.0.54
+4000.example. 5M IN A 10.0.0.55
+4000.example. 5M IN A 10.0.0.56
+4000.example. 5M IN A 10.0.0.57
+4000.example. 5M IN A 10.0.0.58
+4000.example. 5M IN A 10.0.0.59
+4000.example. 5M IN A 10.0.0.60
+4000.example. 5M IN A 10.0.0.61
+4000.example. 5M IN A 10.0.0.62
+4000.example. 5M IN A 10.0.0.63
+4000.example. 5M IN A 10.0.0.64
+4000.example. 5M IN A 10.0.0.65
+4000.example. 5M IN A 10.0.0.66
+4000.example. 5M IN A 10.0.0.67
+4000.example. 5M IN A 10.0.0.68
+4000.example. 5M IN A 10.0.0.69
+4000.example. 5M IN A 10.0.0.70
+4000.example. 5M IN A 10.0.0.71
+4000.example. 5M IN A 10.0.0.72
+4000.example. 5M IN A 10.0.0.73
+4000.example. 5M IN A 10.0.0.74
+4000.example. 5M IN A 10.0.0.75
+4000.example. 5M IN A 10.0.0.76
+4000.example. 5M IN A 10.0.0.77
+4000.example. 5M IN A 10.0.0.78
+4000.example. 5M IN A 10.0.0.79
+4000.example. 5M IN A 10.0.0.80
+4000.example. 5M IN A 10.0.0.81
+4000.example. 5M IN A 10.0.0.82
+4000.example. 5M IN A 10.0.0.83
+4000.example. 5M IN A 10.0.0.84
+4000.example. 5M IN A 10.0.0.85
+4000.example. 5M IN A 10.0.0.86
+4000.example. 5M IN A 10.0.0.87
+4000.example. 5M IN A 10.0.0.88
+4000.example. 5M IN A 10.0.0.89
+4000.example. 5M IN A 10.0.0.90
+4000.example. 5M IN A 10.0.0.91
+4000.example. 5M IN A 10.0.0.92
+4000.example. 5M IN A 10.0.0.93
+4000.example. 5M IN A 10.0.0.94
+4000.example. 5M IN A 10.0.0.95
+4000.example. 5M IN A 10.0.0.96
+4000.example. 5M IN A 10.0.0.97
+4000.example. 5M IN A 10.0.0.98
+4000.example. 5M IN A 10.0.0.99
+4000.example. 5M IN A 10.0.0.100
+4000.example. 5M IN A 10.0.0.101
+4000.example. 5M IN A 10.0.0.102
+4000.example. 5M IN A 10.0.0.103
+4000.example. 5M IN A 10.0.0.104
+4000.example. 5M IN A 10.0.0.105
+4000.example. 5M IN A 10.0.0.106
+4000.example. 5M IN A 10.0.0.107
+4000.example. 5M IN A 10.0.0.108
+4000.example. 5M IN A 10.0.0.109
+4000.example. 5M IN A 10.0.0.110
+4000.example. 5M IN A 10.0.0.111
+4000.example. 5M IN A 10.0.0.112
+4000.example. 5M IN A 10.0.0.113
+4000.example. 5M IN A 10.0.0.114
+4000.example. 5M IN A 10.0.0.115
+4000.example. 5M IN A 10.0.0.116
+4000.example. 5M IN A 10.0.0.117
+4000.example. 5M IN A 10.0.0.118
+4000.example. 5M IN A 10.0.0.119
+4000.example. 5M IN A 10.0.0.120
+4000.example. 5M IN A 10.0.0.121
+4000.example. 5M IN A 10.0.0.122
+4000.example. 5M IN A 10.0.0.123
+4000.example. 5M IN A 10.0.0.124
+4000.example. 5M IN A 10.0.0.125
+4000.example. 5M IN A 10.0.0.126
+4000.example. 5M IN A 10.0.0.127
+4000.example. 5M IN A 10.0.0.128
+4000.example. 5M IN A 10.0.0.129
+4000.example. 5M IN A 10.0.0.130
+4000.example. 5M IN A 10.0.0.131
+4000.example. 5M IN A 10.0.0.132
+4000.example. 5M IN A 10.0.0.133
+4000.example. 5M IN A 10.0.0.134
+4000.example. 5M IN A 10.0.0.135
+4000.example. 5M IN A 10.0.0.136
+4000.example. 5M IN A 10.0.0.137
+4000.example. 5M IN A 10.0.0.138
+4000.example. 5M IN A 10.0.0.139
+4000.example. 5M IN A 10.0.0.140
+4000.example. 5M IN A 10.0.0.141
+4000.example. 5M IN A 10.0.0.142
+4000.example. 5M IN A 10.0.0.143
+4000.example. 5M IN A 10.0.0.144
+4000.example. 5M IN A 10.0.0.145
+4000.example. 5M IN A 10.0.0.146
+4000.example. 5M IN A 10.0.0.147
+4000.example. 5M IN A 10.0.0.148
+4000.example. 5M IN A 10.0.0.149
+4000.example. 5M IN A 10.0.0.150
+4000.example. 5M IN A 10.0.0.151
+4000.example. 5M IN A 10.0.0.152
+4000.example. 5M IN A 10.0.0.153
+4000.example. 5M IN A 10.0.0.154
+4000.example. 5M IN A 10.0.0.155
+4000.example. 5M IN A 10.0.0.156
+4000.example. 5M IN A 10.0.0.157
+4000.example. 5M IN A 10.0.0.158
+4000.example. 5M IN A 10.0.0.159
+4000.example. 5M IN A 10.0.0.160
+4000.example. 5M IN A 10.0.0.161
+4000.example. 5M IN A 10.0.0.162
+4000.example. 5M IN A 10.0.0.163
+4000.example. 5M IN A 10.0.0.164
+4000.example. 5M IN A 10.0.0.165
+4000.example. 5M IN A 10.0.0.166
+4000.example. 5M IN A 10.0.0.167
+4000.example. 5M IN A 10.0.0.168
+4000.example. 5M IN A 10.0.0.169
+4000.example. 5M IN A 10.0.0.170
+4000.example. 5M IN A 10.0.0.171
+4000.example. 5M IN A 10.0.0.172
+4000.example. 5M IN A 10.0.0.173
+4000.example. 5M IN A 10.0.0.174
+4000.example. 5M IN A 10.0.0.175
+4000.example. 5M IN A 10.0.0.176
+4000.example. 5M IN A 10.0.0.177
+4000.example. 5M IN A 10.0.0.178
+4000.example. 5M IN A 10.0.0.179
+4000.example. 5M IN A 10.0.0.180
+4000.example. 5M IN A 10.0.0.181
+4000.example. 5M IN A 10.0.0.182
+4000.example. 5M IN A 10.0.0.183
+4000.example. 5M IN A 10.0.0.184
+4000.example. 5M IN A 10.0.0.185
+4000.example. 5M IN A 10.0.0.186
+4000.example. 5M IN A 10.0.0.187
+4000.example. 5M IN A 10.0.0.188
+4000.example. 5M IN A 10.0.0.189
+4000.example. 5M IN A 10.0.0.190
+4000.example. 5M IN A 10.0.0.191
+4000.example. 5M IN A 10.0.0.192
+4000.example. 5M IN A 10.0.0.193
+4000.example. 5M IN A 10.0.0.194
+4000.example. 5M IN A 10.0.0.195
+4000.example. 5M IN A 10.0.0.196
+4000.example. 5M IN A 10.0.0.197
+4000.example. 5M IN A 10.0.0.198
+4000.example. 5M IN A 10.0.0.199
+4000.example. 5M IN A 10.0.0.200
+4000.example. 5M IN A 10.0.0.201
+4000.example. 5M IN A 10.0.0.202
+4000.example. 5M IN A 10.0.0.203
+4000.example. 5M IN A 10.0.0.204
+4000.example. 5M IN A 10.0.0.205
+4000.example. 5M IN A 10.0.0.206
+4000.example. 5M IN A 10.0.0.207
+4000.example. 5M IN A 10.0.0.208
+4000.example. 5M IN A 10.0.0.209
+4000.example. 5M IN A 10.0.0.210
+4000.example. 5M IN A 10.0.0.211
+4000.example. 5M IN A 10.0.0.212
+4000.example. 5M IN A 10.0.0.213
+4000.example. 5M IN A 10.0.0.214
+4000.example. 5M IN A 10.0.0.215
+4000.example. 5M IN A 10.0.0.216
+4000.example. 5M IN A 10.0.0.217
+4000.example. 5M IN A 10.0.0.218
+4000.example. 5M IN A 10.0.0.219
+4000.example. 5M IN A 10.0.0.220
+4000.example. 5M IN A 10.0.0.221
+4000.example. 5M IN A 10.0.0.222
+4000.example. 5M IN A 10.0.0.223
+4000.example. 5M IN A 10.0.0.224
+4000.example. 5M IN A 10.0.0.225
+4000.example. 5M IN A 10.0.0.226
+4000.example. 5M IN A 10.0.0.227
+4000.example. 5M IN A 10.0.0.228
+4000.example. 5M IN A 10.0.0.229
+4000.example. 5M IN A 10.0.0.230
+4000.example. 5M IN A 10.0.0.231
+4000.example. 5M IN A 10.0.0.232
+4000.example. 5M IN A 10.0.0.233
+4000.example. 5M IN A 10.0.0.234
+4000.example. 5M IN A 10.0.0.235
+4000.example. 5M IN A 10.0.0.236
+4000.example. 5M IN A 10.0.0.237
+4000.example. 5M IN A 10.0.0.238
+4000.example. 5M IN A 10.0.0.239
+4000.example. 5M IN A 10.0.0.240
+4000.example. 5M IN A 10.0.0.241
+4000.example. 5M IN A 10.0.0.242
+4000.example. 5M IN A 10.0.0.243
+4000.example. 5M IN A 10.0.0.244
+4000.example. 5M IN A 10.0.0.245
+4000.example. 5M IN A 10.0.0.246
+4000.example. 5M IN A 10.0.0.247
+4000.example. 5M IN A 10.0.0.248
+4000.example. 5M IN A 10.0.0.249
+4000.example. 5M IN A 10.0.0.250
+4000.example. 5M IN A 10.0.0.251
+4000.example. 5M IN A 10.0.0.252
+4000.example. 5M IN A 10.0.0.253
+4000.example. 5M IN A 10.0.0.254
+4000.example. 5M IN A 10.0.0.255
+4000.example. 5M IN A 10.0.1.0
+4000.example. 5M IN A 10.0.1.1
+4000.example. 5M IN A 10.0.1.2
+4000.example. 5M IN A 10.0.1.3
+4000.example. 5M IN A 10.0.1.4
+4000.example. 5M IN A 10.0.1.5
+4000.example. 5M IN A 10.0.1.6
+4000.example. 5M IN A 10.0.1.7
+4000.example. 5M IN A 10.0.1.8
+4000.example. 5M IN A 10.0.1.9
+4000.example. 5M IN A 10.0.1.10
+4000.example. 5M IN A 10.0.1.11
+4000.example. 5M IN A 10.0.1.12
+4000.example. 5M IN A 10.0.1.13
+4000.example. 5M IN A 10.0.1.14
+4000.example. 5M IN A 10.0.1.15
+4000.example. 5M IN A 10.0.1.16
+4000.example. 5M IN A 10.0.1.17
+4000.example. 5M IN A 10.0.1.18
+4000.example. 5M IN A 10.0.1.19
+4000.example. 5M IN A 10.0.1.20
+4000.example. 5M IN A 10.0.1.21
+4000.example. 5M IN A 10.0.1.22
+4000.example. 5M IN A 10.0.1.23
+4000.example. 5M IN A 10.0.1.24
+4000.example. 5M IN A 10.0.1.25
+4000.example. 5M IN A 10.0.1.26
+4000.example. 5M IN A 10.0.1.27
+4000.example. 5M IN A 10.0.1.28
+4000.example. 5M IN A 10.0.1.29
+4000.example. 5M IN A 10.0.1.30
+4000.example. 5M IN A 10.0.1.31
+4000.example. 5M IN A 10.0.1.32
+4000.example. 5M IN A 10.0.1.33
+4000.example. 5M IN A 10.0.1.34
+4000.example. 5M IN A 10.0.1.35
+4000.example. 5M IN A 10.0.1.36
+4000.example. 5M IN A 10.0.1.37
+4000.example. 5M IN A 10.0.1.38
+4000.example. 5M IN A 10.0.1.39
+4000.example. 5M IN A 10.0.1.40
+4000.example. 5M IN A 10.0.1.41
+4000.example. 5M IN A 10.0.1.42
+4000.example. 5M IN A 10.0.1.43
+4000.example. 5M IN A 10.0.1.44
+4000.example. 5M IN A 10.0.1.45
+4000.example. 5M IN A 10.0.1.46
+4000.example. 5M IN A 10.0.1.47
+4000.example. 5M IN A 10.0.1.48
+4000.example. 5M IN A 10.0.1.49
+4000.example. 5M IN A 10.0.1.50
+4000.example. 5M IN A 10.0.1.51
+4000.example. 5M IN A 10.0.1.52
+4000.example. 5M IN A 10.0.1.53
+4000.example. 5M IN A 10.0.1.54
+4000.example. 5M IN A 10.0.1.55
+4000.example. 5M IN A 10.0.1.56
+4000.example. 5M IN A 10.0.1.57
+4000.example. 5M IN A 10.0.1.58
+4000.example. 5M IN A 10.0.1.59
+4000.example. 5M IN A 10.0.1.60
+4000.example. 5M IN A 10.0.1.61
+4000.example. 5M IN A 10.0.1.62
+4000.example. 5M IN A 10.0.1.63
+4000.example. 5M IN A 10.0.1.64
+4000.example. 5M IN A 10.0.1.65
+4000.example. 5M IN A 10.0.1.66
+4000.example. 5M IN A 10.0.1.67
+4000.example. 5M IN A 10.0.1.68
+4000.example. 5M IN A 10.0.1.69
+4000.example. 5M IN A 10.0.1.70
+4000.example. 5M IN A 10.0.1.71
+4000.example. 5M IN A 10.0.1.72
+4000.example. 5M IN A 10.0.1.73
+4000.example. 5M IN A 10.0.1.74
+4000.example. 5M IN A 10.0.1.75
+4000.example. 5M IN A 10.0.1.76
+4000.example. 5M IN A 10.0.1.77
+4000.example. 5M IN A 10.0.1.78
+4000.example. 5M IN A 10.0.1.79
+4000.example. 5M IN A 10.0.1.80
+4000.example. 5M IN A 10.0.1.81
+4000.example. 5M IN A 10.0.1.82
+4000.example. 5M IN A 10.0.1.83
+4000.example. 5M IN A 10.0.1.84
+4000.example. 5M IN A 10.0.1.85
+4000.example. 5M IN A 10.0.1.86
+4000.example. 5M IN A 10.0.1.87
+4000.example. 5M IN A 10.0.1.88
+4000.example. 5M IN A 10.0.1.89
+4000.example. 5M IN A 10.0.1.90
+4000.example. 5M IN A 10.0.1.91
+4000.example. 5M IN A 10.0.1.92
+4000.example. 5M IN A 10.0.1.93
+4000.example. 5M IN A 10.0.1.94
+4000.example. 5M IN A 10.0.1.95
+4000.example. 5M IN A 10.0.1.96
+4000.example. 5M IN A 10.0.1.97
+4000.example. 5M IN A 10.0.1.98
+4000.example. 5M IN A 10.0.1.99
+4000.example. 5M IN A 10.0.1.100
+4000.example. 5M IN A 10.0.1.101
+4000.example. 5M IN A 10.0.1.102
+4000.example. 5M IN A 10.0.1.103
+4000.example. 5M IN A 10.0.1.104
+4000.example. 5M IN A 10.0.1.105
+4000.example. 5M IN A 10.0.1.106
+4000.example. 5M IN A 10.0.1.107
+4000.example. 5M IN A 10.0.1.108
+4000.example. 5M IN A 10.0.1.109
+4000.example. 5M IN A 10.0.1.110
+4000.example. 5M IN A 10.0.1.111
+4000.example. 5M IN A 10.0.1.112
+4000.example. 5M IN A 10.0.1.113
+4000.example. 5M IN A 10.0.1.114
+4000.example. 5M IN A 10.0.1.115
+4000.example. 5M IN A 10.0.1.116
+4000.example. 5M IN A 10.0.1.117
+4000.example. 5M IN A 10.0.1.118
+4000.example. 5M IN A 10.0.1.119
+4000.example. 5M IN A 10.0.1.120
+4000.example. 5M IN A 10.0.1.121
+4000.example. 5M IN A 10.0.1.122
+4000.example. 5M IN A 10.0.1.123
+4000.example. 5M IN A 10.0.1.124
+4000.example. 5M IN A 10.0.1.125
+4000.example. 5M IN A 10.0.1.126
+4000.example. 5M IN A 10.0.1.127
+4000.example. 5M IN A 10.0.1.128
+4000.example. 5M IN A 10.0.1.129
+4000.example. 5M IN A 10.0.1.130
+4000.example. 5M IN A 10.0.1.131
+4000.example. 5M IN A 10.0.1.132
+4000.example. 5M IN A 10.0.1.133
+4000.example. 5M IN A 10.0.1.134
+4000.example. 5M IN A 10.0.1.135
+4000.example. 5M IN A 10.0.1.136
+4000.example. 5M IN A 10.0.1.137
+4000.example. 5M IN A 10.0.1.138
+4000.example. 5M IN A 10.0.1.139
+4000.example. 5M IN A 10.0.1.140
+4000.example. 5M IN A 10.0.1.141
+4000.example. 5M IN A 10.0.1.142
+4000.example. 5M IN A 10.0.1.143
+4000.example. 5M IN A 10.0.1.144
+4000.example. 5M IN A 10.0.1.145
+4000.example. 5M IN A 10.0.1.146
+4000.example. 5M IN A 10.0.1.147
+4000.example. 5M IN A 10.0.1.148
+4000.example. 5M IN A 10.0.1.149
+4000.example. 5M IN A 10.0.1.150
+4000.example. 5M IN A 10.0.1.151
+4000.example. 5M IN A 10.0.1.152
+4000.example. 5M IN A 10.0.1.153
+4000.example. 5M IN A 10.0.1.154
+4000.example. 5M IN A 10.0.1.155
+4000.example. 5M IN A 10.0.1.156
+4000.example. 5M IN A 10.0.1.157
+4000.example. 5M IN A 10.0.1.158
+4000.example. 5M IN A 10.0.1.159
+4000.example. 5M IN A 10.0.1.160
+4000.example. 5M IN A 10.0.1.161
+4000.example. 5M IN A 10.0.1.162
+4000.example. 5M IN A 10.0.1.163
+4000.example. 5M IN A 10.0.1.164
+4000.example. 5M IN A 10.0.1.165
+4000.example. 5M IN A 10.0.1.166
+4000.example. 5M IN A 10.0.1.167
+4000.example. 5M IN A 10.0.1.168
+4000.example. 5M IN A 10.0.1.169
+4000.example. 5M IN A 10.0.1.170
+4000.example. 5M IN A 10.0.1.171
+4000.example. 5M IN A 10.0.1.172
+4000.example. 5M IN A 10.0.1.173
+4000.example. 5M IN A 10.0.1.174
+4000.example. 5M IN A 10.0.1.175
+4000.example. 5M IN A 10.0.1.176
+4000.example. 5M IN A 10.0.1.177
+4000.example. 5M IN A 10.0.1.178
+4000.example. 5M IN A 10.0.1.179
+4000.example. 5M IN A 10.0.1.180
+4000.example. 5M IN A 10.0.1.181
+4000.example. 5M IN A 10.0.1.182
+4000.example. 5M IN A 10.0.1.183
+4000.example. 5M IN A 10.0.1.184
+4000.example. 5M IN A 10.0.1.185
+4000.example. 5M IN A 10.0.1.186
+4000.example. 5M IN A 10.0.1.187
+4000.example. 5M IN A 10.0.1.188
+4000.example. 5M IN A 10.0.1.189
+4000.example. 5M IN A 10.0.1.190
+4000.example. 5M IN A 10.0.1.191
+4000.example. 5M IN A 10.0.1.192
+4000.example. 5M IN A 10.0.1.193
+4000.example. 5M IN A 10.0.1.194
+4000.example. 5M IN A 10.0.1.195
+4000.example. 5M IN A 10.0.1.196
+4000.example. 5M IN A 10.0.1.197
+4000.example. 5M IN A 10.0.1.198
+4000.example. 5M IN A 10.0.1.199
+4000.example. 5M IN A 10.0.1.200
+4000.example. 5M IN A 10.0.1.201
+4000.example. 5M IN A 10.0.1.202
+4000.example. 5M IN A 10.0.1.203
+4000.example. 5M IN A 10.0.1.204
+4000.example. 5M IN A 10.0.1.205
+4000.example. 5M IN A 10.0.1.206
+4000.example. 5M IN A 10.0.1.207
+4000.example. 5M IN A 10.0.1.208
+4000.example. 5M IN A 10.0.1.209
+4000.example. 5M IN A 10.0.1.210
+4000.example. 5M IN A 10.0.1.211
+4000.example. 5M IN A 10.0.1.212
+4000.example. 5M IN A 10.0.1.213
+4000.example. 5M IN A 10.0.1.214
+4000.example. 5M IN A 10.0.1.215
+4000.example. 5M IN A 10.0.1.216
+4000.example. 5M IN A 10.0.1.217
+4000.example. 5M IN A 10.0.1.218
+4000.example. 5M IN A 10.0.1.219
+4000.example. 5M IN A 10.0.1.220
+4000.example. 5M IN A 10.0.1.221
+4000.example. 5M IN A 10.0.1.222
+4000.example. 5M IN A 10.0.1.223
+4000.example. 5M IN A 10.0.1.224
+4000.example. 5M IN A 10.0.1.225
+4000.example. 5M IN A 10.0.1.226
+4000.example. 5M IN A 10.0.1.227
+4000.example. 5M IN A 10.0.1.228
+4000.example. 5M IN A 10.0.1.229
+4000.example. 5M IN A 10.0.1.230
+4000.example. 5M IN A 10.0.1.231
+4000.example. 5M IN A 10.0.1.232
+4000.example. 5M IN A 10.0.1.233
+4000.example. 5M IN A 10.0.1.234
+4000.example. 5M IN A 10.0.1.235
+4000.example. 5M IN A 10.0.1.236
+4000.example. 5M IN A 10.0.1.237
+4000.example. 5M IN A 10.0.1.238
+4000.example. 5M IN A 10.0.1.239
+4000.example. 5M IN A 10.0.1.240
+4000.example. 5M IN A 10.0.1.241
+4000.example. 5M IN A 10.0.1.242
+4000.example. 5M IN A 10.0.1.243
+4000.example. 5M IN A 10.0.1.244
+4000.example. 5M IN A 10.0.1.245
+4000.example. 5M IN A 10.0.1.246
+4000.example. 5M IN A 10.0.1.247
+4000.example. 5M IN A 10.0.1.248
+4000.example. 5M IN A 10.0.1.249
+4000.example. 5M IN A 10.0.1.250
+4000.example. 5M IN A 10.0.1.251
+4000.example. 5M IN A 10.0.1.252
+4000.example. 5M IN A 10.0.1.253
+4000.example. 5M IN A 10.0.1.254
+4000.example. 5M IN A 10.0.1.255
+4000.example. 5M IN A 10.0.2.0
+4000.example. 5M IN A 10.0.2.1
+4000.example. 5M IN A 10.0.2.2
+4000.example. 5M IN A 10.0.2.3
+4000.example. 5M IN A 10.0.2.4
+4000.example. 5M IN A 10.0.2.5
+4000.example. 5M IN A 10.0.2.6
+4000.example. 5M IN A 10.0.2.7
+4000.example. 5M IN A 10.0.2.8
+4000.example. 5M IN A 10.0.2.9
+4000.example. 5M IN A 10.0.2.10
+4000.example. 5M IN A 10.0.2.11
+4000.example. 5M IN A 10.0.2.12
+4000.example. 5M IN A 10.0.2.13
+4000.example. 5M IN A 10.0.2.14
+4000.example. 5M IN A 10.0.2.15
+4000.example. 5M IN A 10.0.2.16
+4000.example. 5M IN A 10.0.2.17
+4000.example. 5M IN A 10.0.2.18
+4000.example. 5M IN A 10.0.2.19
+4000.example. 5M IN A 10.0.2.20
+4000.example. 5M IN A 10.0.2.21
+4000.example. 5M IN A 10.0.2.22
+4000.example. 5M IN A 10.0.2.23
+4000.example. 5M IN A 10.0.2.24
+4000.example. 5M IN A 10.0.2.25
+4000.example. 5M IN A 10.0.2.26
+4000.example. 5M IN A 10.0.2.27
+4000.example. 5M IN A 10.0.2.28
+4000.example. 5M IN A 10.0.2.29
+4000.example. 5M IN A 10.0.2.30
+4000.example. 5M IN A 10.0.2.31
+4000.example. 5M IN A 10.0.2.32
+4000.example. 5M IN A 10.0.2.33
+4000.example. 5M IN A 10.0.2.34
+4000.example. 5M IN A 10.0.2.35
+4000.example. 5M IN A 10.0.2.36
+4000.example. 5M IN A 10.0.2.37
+4000.example. 5M IN A 10.0.2.38
+4000.example. 5M IN A 10.0.2.39
+4000.example. 5M IN A 10.0.2.40
+4000.example. 5M IN A 10.0.2.41
+4000.example. 5M IN A 10.0.2.42
+4000.example. 5M IN A 10.0.2.43
+4000.example. 5M IN A 10.0.2.44
+4000.example. 5M IN A 10.0.2.45
+4000.example. 5M IN A 10.0.2.46
+4000.example. 5M IN A 10.0.2.47
+4000.example. 5M IN A 10.0.2.48
+4000.example. 5M IN A 10.0.2.49
+4000.example. 5M IN A 10.0.2.50
+4000.example. 5M IN A 10.0.2.51
+4000.example. 5M IN A 10.0.2.52
+4000.example. 5M IN A 10.0.2.53
+4000.example. 5M IN A 10.0.2.54
+4000.example. 5M IN A 10.0.2.55
+4000.example. 5M IN A 10.0.2.56
+4000.example. 5M IN A 10.0.2.57
+4000.example. 5M IN A 10.0.2.58
+4000.example. 5M IN A 10.0.2.59
+4000.example. 5M IN A 10.0.2.60
+4000.example. 5M IN A 10.0.2.61
+4000.example. 5M IN A 10.0.2.62
+4000.example. 5M IN A 10.0.2.63
+4000.example. 5M IN A 10.0.2.64
+4000.example. 5M IN A 10.0.2.65
+4000.example. 5M IN A 10.0.2.66
+4000.example. 5M IN A 10.0.2.67
+4000.example. 5M IN A 10.0.2.68
+4000.example. 5M IN A 10.0.2.69
+4000.example. 5M IN A 10.0.2.70
+4000.example. 5M IN A 10.0.2.71
+4000.example. 5M IN A 10.0.2.72
+4000.example. 5M IN A 10.0.2.73
+4000.example. 5M IN A 10.0.2.74
+4000.example. 5M IN A 10.0.2.75
+4000.example. 5M IN A 10.0.2.76
+4000.example. 5M IN A 10.0.2.77
+4000.example. 5M IN A 10.0.2.78
+4000.example. 5M IN A 10.0.2.79
+4000.example. 5M IN A 10.0.2.80
+4000.example. 5M IN A 10.0.2.81
+4000.example. 5M IN A 10.0.2.82
+4000.example. 5M IN A 10.0.2.83
+4000.example. 5M IN A 10.0.2.84
+4000.example. 5M IN A 10.0.2.85
+4000.example. 5M IN A 10.0.2.86
+4000.example. 5M IN A 10.0.2.87
+4000.example. 5M IN A 10.0.2.88
+4000.example. 5M IN A 10.0.2.89
+4000.example. 5M IN A 10.0.2.90
+4000.example. 5M IN A 10.0.2.91
+4000.example. 5M IN A 10.0.2.92
+4000.example. 5M IN A 10.0.2.93
+4000.example. 5M IN A 10.0.2.94
+4000.example. 5M IN A 10.0.2.95
+4000.example. 5M IN A 10.0.2.96
+4000.example. 5M IN A 10.0.2.97
+4000.example. 5M IN A 10.0.2.98
+4000.example. 5M IN A 10.0.2.99
+4000.example. 5M IN A 10.0.2.100
+4000.example. 5M IN A 10.0.2.101
+4000.example. 5M IN A 10.0.2.102
+4000.example. 5M IN A 10.0.2.103
+4000.example. 5M IN A 10.0.2.104
+4000.example. 5M IN A 10.0.2.105
+4000.example. 5M IN A 10.0.2.106
+4000.example. 5M IN A 10.0.2.107
+4000.example. 5M IN A 10.0.2.108
+4000.example. 5M IN A 10.0.2.109
+4000.example. 5M IN A 10.0.2.110
+4000.example. 5M IN A 10.0.2.111
+4000.example. 5M IN A 10.0.2.112
+4000.example. 5M IN A 10.0.2.113
+4000.example. 5M IN A 10.0.2.114
+4000.example. 5M IN A 10.0.2.115
+4000.example. 5M IN A 10.0.2.116
+4000.example. 5M IN A 10.0.2.117
+4000.example. 5M IN A 10.0.2.118
+4000.example. 5M IN A 10.0.2.119
+4000.example. 5M IN A 10.0.2.120
+4000.example. 5M IN A 10.0.2.121
+4000.example. 5M IN A 10.0.2.122
+4000.example. 5M IN A 10.0.2.123
+4000.example. 5M IN A 10.0.2.124
+4000.example. 5M IN A 10.0.2.125
+4000.example. 5M IN A 10.0.2.126
+4000.example. 5M IN A 10.0.2.127
+4000.example. 5M IN A 10.0.2.128
+4000.example. 5M IN A 10.0.2.129
+4000.example. 5M IN A 10.0.2.130
+4000.example. 5M IN A 10.0.2.131
+4000.example. 5M IN A 10.0.2.132
+4000.example. 5M IN A 10.0.2.133
+4000.example. 5M IN A 10.0.2.134
+4000.example. 5M IN A 10.0.2.135
+4000.example. 5M IN A 10.0.2.136
+4000.example. 5M IN A 10.0.2.137
+4000.example. 5M IN A 10.0.2.138
+4000.example. 5M IN A 10.0.2.139
+4000.example. 5M IN A 10.0.2.140
+4000.example. 5M IN A 10.0.2.141
+4000.example. 5M IN A 10.0.2.142
+4000.example. 5M IN A 10.0.2.143
+4000.example. 5M IN A 10.0.2.144
+4000.example. 5M IN A 10.0.2.145
+4000.example. 5M IN A 10.0.2.146
+4000.example. 5M IN A 10.0.2.147
+4000.example. 5M IN A 10.0.2.148
+4000.example. 5M IN A 10.0.2.149
+4000.example. 5M IN A 10.0.2.150
+4000.example. 5M IN A 10.0.2.151
+4000.example. 5M IN A 10.0.2.152
+4000.example. 5M IN A 10.0.2.153
+4000.example. 5M IN A 10.0.2.154
+4000.example. 5M IN A 10.0.2.155
+4000.example. 5M IN A 10.0.2.156
+4000.example. 5M IN A 10.0.2.157
+4000.example. 5M IN A 10.0.2.158
+4000.example. 5M IN A 10.0.2.159
+4000.example. 5M IN A 10.0.2.160
+4000.example. 5M IN A 10.0.2.161
+4000.example. 5M IN A 10.0.2.162
+4000.example. 5M IN A 10.0.2.163
+4000.example. 5M IN A 10.0.2.164
+4000.example. 5M IN A 10.0.2.165
+4000.example. 5M IN A 10.0.2.166
+4000.example. 5M IN A 10.0.2.167
+4000.example. 5M IN A 10.0.2.168
+4000.example. 5M IN A 10.0.2.169
+4000.example. 5M IN A 10.0.2.170
+4000.example. 5M IN A 10.0.2.171
+4000.example. 5M IN A 10.0.2.172
+4000.example. 5M IN A 10.0.2.173
+4000.example. 5M IN A 10.0.2.174
+4000.example. 5M IN A 10.0.2.175
+4000.example. 5M IN A 10.0.2.176
+4000.example. 5M IN A 10.0.2.177
+4000.example. 5M IN A 10.0.2.178
+4000.example. 5M IN A 10.0.2.179
+4000.example. 5M IN A 10.0.2.180
+4000.example. 5M IN A 10.0.2.181
+4000.example. 5M IN A 10.0.2.182
+4000.example. 5M IN A 10.0.2.183
+4000.example. 5M IN A 10.0.2.184
+4000.example. 5M IN A 10.0.2.185
+4000.example. 5M IN A 10.0.2.186
+4000.example. 5M IN A 10.0.2.187
+4000.example. 5M IN A 10.0.2.188
+4000.example. 5M IN A 10.0.2.189
+4000.example. 5M IN A 10.0.2.190
+4000.example. 5M IN A 10.0.2.191
+4000.example. 5M IN A 10.0.2.192
+4000.example. 5M IN A 10.0.2.193
+4000.example. 5M IN A 10.0.2.194
+4000.example. 5M IN A 10.0.2.195
+4000.example. 5M IN A 10.0.2.196
+4000.example. 5M IN A 10.0.2.197
+4000.example. 5M IN A 10.0.2.198
+4000.example. 5M IN A 10.0.2.199
+4000.example. 5M IN A 10.0.2.200
+4000.example. 5M IN A 10.0.2.201
+4000.example. 5M IN A 10.0.2.202
+4000.example. 5M IN A 10.0.2.203
+4000.example. 5M IN A 10.0.2.204
+4000.example. 5M IN A 10.0.2.205
+4000.example. 5M IN A 10.0.2.206
+4000.example. 5M IN A 10.0.2.207
+4000.example. 5M IN A 10.0.2.208
+4000.example. 5M IN A 10.0.2.209
+4000.example. 5M IN A 10.0.2.210
+4000.example. 5M IN A 10.0.2.211
+4000.example. 5M IN A 10.0.2.212
+4000.example. 5M IN A 10.0.2.213
+4000.example. 5M IN A 10.0.2.214
+4000.example. 5M IN A 10.0.2.215
+4000.example. 5M IN A 10.0.2.216
+4000.example. 5M IN A 10.0.2.217
+4000.example. 5M IN A 10.0.2.218
+4000.example. 5M IN A 10.0.2.219
+4000.example. 5M IN A 10.0.2.220
+4000.example. 5M IN A 10.0.2.221
+4000.example. 5M IN A 10.0.2.222
+4000.example. 5M IN A 10.0.2.223
+4000.example. 5M IN A 10.0.2.224
+4000.example. 5M IN A 10.0.2.225
+4000.example. 5M IN A 10.0.2.226
+4000.example. 5M IN A 10.0.2.227
+4000.example. 5M IN A 10.0.2.228
+4000.example. 5M IN A 10.0.2.229
+4000.example. 5M IN A 10.0.2.230
+4000.example. 5M IN A 10.0.2.231
+4000.example. 5M IN A 10.0.2.232
+4000.example. 5M IN A 10.0.2.233
+4000.example. 5M IN A 10.0.2.234
+4000.example. 5M IN A 10.0.2.235
+4000.example. 5M IN A 10.0.2.236
+4000.example. 5M IN A 10.0.2.237
+4000.example. 5M IN A 10.0.2.238
+4000.example. 5M IN A 10.0.2.239
+4000.example. 5M IN A 10.0.2.240
+4000.example. 5M IN A 10.0.2.241
+4000.example. 5M IN A 10.0.2.242
+4000.example. 5M IN A 10.0.2.243
+4000.example. 5M IN A 10.0.2.244
+4000.example. 5M IN A 10.0.2.245
+4000.example. 5M IN A 10.0.2.246
+4000.example. 5M IN A 10.0.2.247
+4000.example. 5M IN A 10.0.2.248
+4000.example. 5M IN A 10.0.2.249
+4000.example. 5M IN A 10.0.2.250
+4000.example. 5M IN A 10.0.2.251
+4000.example. 5M IN A 10.0.2.252
+4000.example. 5M IN A 10.0.2.253
+4000.example. 5M IN A 10.0.2.254
+4000.example. 5M IN A 10.0.2.255
+4000.example. 5M IN A 10.0.3.0
+4000.example. 5M IN A 10.0.3.1
+4000.example. 5M IN A 10.0.3.2
+4000.example. 5M IN A 10.0.3.3
+4000.example. 5M IN A 10.0.3.4
+4000.example. 5M IN A 10.0.3.5
+4000.example. 5M IN A 10.0.3.6
+4000.example. 5M IN A 10.0.3.7
+4000.example. 5M IN A 10.0.3.8
+4000.example. 5M IN A 10.0.3.9
+4000.example. 5M IN A 10.0.3.10
+4000.example. 5M IN A 10.0.3.11
+4000.example. 5M IN A 10.0.3.12
+4000.example. 5M IN A 10.0.3.13
+4000.example. 5M IN A 10.0.3.14
+4000.example. 5M IN A 10.0.3.15
+4000.example. 5M IN A 10.0.3.16
+4000.example. 5M IN A 10.0.3.17
+4000.example. 5M IN A 10.0.3.18
+4000.example. 5M IN A 10.0.3.19
+4000.example. 5M IN A 10.0.3.20
+4000.example. 5M IN A 10.0.3.21
+4000.example. 5M IN A 10.0.3.22
+4000.example. 5M IN A 10.0.3.23
+4000.example. 5M IN A 10.0.3.24
+4000.example. 5M IN A 10.0.3.25
+4000.example. 5M IN A 10.0.3.26
+4000.example. 5M IN A 10.0.3.27
+4000.example. 5M IN A 10.0.3.28
+4000.example. 5M IN A 10.0.3.29
+4000.example. 5M IN A 10.0.3.30
+4000.example. 5M IN A 10.0.3.31
+4000.example. 5M IN A 10.0.3.32
+4000.example. 5M IN A 10.0.3.33
+4000.example. 5M IN A 10.0.3.34
+4000.example. 5M IN A 10.0.3.35
+4000.example. 5M IN A 10.0.3.36
+4000.example. 5M IN A 10.0.3.37
+4000.example. 5M IN A 10.0.3.38
+4000.example. 5M IN A 10.0.3.39
+4000.example. 5M IN A 10.0.3.40
+4000.example. 5M IN A 10.0.3.41
+4000.example. 5M IN A 10.0.3.42
+4000.example. 5M IN A 10.0.3.43
+4000.example. 5M IN A 10.0.3.44
+4000.example. 5M IN A 10.0.3.45
+4000.example. 5M IN A 10.0.3.46
+4000.example. 5M IN A 10.0.3.47
+4000.example. 5M IN A 10.0.3.48
+4000.example. 5M IN A 10.0.3.49
+4000.example. 5M IN A 10.0.3.50
+4000.example. 5M IN A 10.0.3.51
+4000.example. 5M IN A 10.0.3.52
+4000.example. 5M IN A 10.0.3.53
+4000.example. 5M IN A 10.0.3.54
+4000.example. 5M IN A 10.0.3.55
+4000.example. 5M IN A 10.0.3.56
+4000.example. 5M IN A 10.0.3.57
+4000.example. 5M IN A 10.0.3.58
+4000.example. 5M IN A 10.0.3.59
+4000.example. 5M IN A 10.0.3.60
+4000.example. 5M IN A 10.0.3.61
+4000.example. 5M IN A 10.0.3.62
+4000.example. 5M IN A 10.0.3.63
+4000.example. 5M IN A 10.0.3.64
+4000.example. 5M IN A 10.0.3.65
+4000.example. 5M IN A 10.0.3.66
+4000.example. 5M IN A 10.0.3.67
+4000.example. 5M IN A 10.0.3.68
+4000.example. 5M IN A 10.0.3.69
+4000.example. 5M IN A 10.0.3.70
+4000.example. 5M IN A 10.0.3.71
+4000.example. 5M IN A 10.0.3.72
+4000.example. 5M IN A 10.0.3.73
+4000.example. 5M IN A 10.0.3.74
+4000.example. 5M IN A 10.0.3.75
+4000.example. 5M IN A 10.0.3.76
+4000.example. 5M IN A 10.0.3.77
+4000.example. 5M IN A 10.0.3.78
+4000.example. 5M IN A 10.0.3.79
+4000.example. 5M IN A 10.0.3.80
+4000.example. 5M IN A 10.0.3.81
+4000.example. 5M IN A 10.0.3.82
+4000.example. 5M IN A 10.0.3.83
+4000.example. 5M IN A 10.0.3.84
+4000.example. 5M IN A 10.0.3.85
+4000.example. 5M IN A 10.0.3.86
+4000.example. 5M IN A 10.0.3.87
+4000.example. 5M IN A 10.0.3.88
+4000.example. 5M IN A 10.0.3.89
+4000.example. 5M IN A 10.0.3.90
+4000.example. 5M IN A 10.0.3.91
+4000.example. 5M IN A 10.0.3.92
+4000.example. 5M IN A 10.0.3.93
+4000.example. 5M IN A 10.0.3.94
+4000.example. 5M IN A 10.0.3.95
+4000.example. 5M IN A 10.0.3.96
+4000.example. 5M IN A 10.0.3.97
+4000.example. 5M IN A 10.0.3.98
+4000.example. 5M IN A 10.0.3.99
+4000.example. 5M IN A 10.0.3.100
+4000.example. 5M IN A 10.0.3.101
+4000.example. 5M IN A 10.0.3.102
+4000.example. 5M IN A 10.0.3.103
+4000.example. 5M IN A 10.0.3.104
+4000.example. 5M IN A 10.0.3.105
+4000.example. 5M IN A 10.0.3.106
+4000.example. 5M IN A 10.0.3.107
+4000.example. 5M IN A 10.0.3.108
+4000.example. 5M IN A 10.0.3.109
+4000.example. 5M IN A 10.0.3.110
+4000.example. 5M IN A 10.0.3.111
+4000.example. 5M IN A 10.0.3.112
+4000.example. 5M IN A 10.0.3.113
+4000.example. 5M IN A 10.0.3.114
+4000.example. 5M IN A 10.0.3.115
+4000.example. 5M IN A 10.0.3.116
+4000.example. 5M IN A 10.0.3.117
+4000.example. 5M IN A 10.0.3.118
+4000.example. 5M IN A 10.0.3.119
+4000.example. 5M IN A 10.0.3.120
+4000.example. 5M IN A 10.0.3.121
+4000.example. 5M IN A 10.0.3.122
+4000.example. 5M IN A 10.0.3.123
+4000.example. 5M IN A 10.0.3.124
+4000.example. 5M IN A 10.0.3.125
+4000.example. 5M IN A 10.0.3.126
+4000.example. 5M IN A 10.0.3.127
+4000.example. 5M IN A 10.0.3.128
+4000.example. 5M IN A 10.0.3.129
+4000.example. 5M IN A 10.0.3.130
+4000.example. 5M IN A 10.0.3.131
+4000.example. 5M IN A 10.0.3.132
+4000.example. 5M IN A 10.0.3.133
+4000.example. 5M IN A 10.0.3.134
+4000.example. 5M IN A 10.0.3.135
+4000.example. 5M IN A 10.0.3.136
+4000.example. 5M IN A 10.0.3.137
+4000.example. 5M IN A 10.0.3.138
+4000.example. 5M IN A 10.0.3.139
+4000.example. 5M IN A 10.0.3.140
+4000.example. 5M IN A 10.0.3.141
+4000.example. 5M IN A 10.0.3.142
+4000.example. 5M IN A 10.0.3.143
+4000.example. 5M IN A 10.0.3.144
+4000.example. 5M IN A 10.0.3.145
+4000.example. 5M IN A 10.0.3.146
+4000.example. 5M IN A 10.0.3.147
+4000.example. 5M IN A 10.0.3.148
+4000.example. 5M IN A 10.0.3.149
+4000.example. 5M IN A 10.0.3.150
+4000.example. 5M IN A 10.0.3.151
+4000.example. 5M IN A 10.0.3.152
+4000.example. 5M IN A 10.0.3.153
+4000.example. 5M IN A 10.0.3.154
+4000.example. 5M IN A 10.0.3.155
+4000.example. 5M IN A 10.0.3.156
+4000.example. 5M IN A 10.0.3.157
+4000.example. 5M IN A 10.0.3.158
+4000.example. 5M IN A 10.0.3.159
+4000.example. 5M IN A 10.0.3.160
+4000.example. 5M IN A 10.0.3.161
+4000.example. 5M IN A 10.0.3.162
+4000.example. 5M IN A 10.0.3.163
+4000.example. 5M IN A 10.0.3.164
+4000.example. 5M IN A 10.0.3.165
+4000.example. 5M IN A 10.0.3.166
+4000.example. 5M IN A 10.0.3.167
+4000.example. 5M IN A 10.0.3.168
+4000.example. 5M IN A 10.0.3.169
+4000.example. 5M IN A 10.0.3.170
+4000.example. 5M IN A 10.0.3.171
+4000.example. 5M IN A 10.0.3.172
+4000.example. 5M IN A 10.0.3.173
+4000.example. 5M IN A 10.0.3.174
+4000.example. 5M IN A 10.0.3.175
+4000.example. 5M IN A 10.0.3.176
+4000.example. 5M IN A 10.0.3.177
+4000.example. 5M IN A 10.0.3.178
+4000.example. 5M IN A 10.0.3.179
+4000.example. 5M IN A 10.0.3.180
+4000.example. 5M IN A 10.0.3.181
+4000.example. 5M IN A 10.0.3.182
+4000.example. 5M IN A 10.0.3.183
+4000.example. 5M IN A 10.0.3.184
+4000.example. 5M IN A 10.0.3.185
+4000.example. 5M IN A 10.0.3.186
+4000.example. 5M IN A 10.0.3.187
+4000.example. 5M IN A 10.0.3.188
+4000.example. 5M IN A 10.0.3.189
+4000.example. 5M IN A 10.0.3.190
+4000.example. 5M IN A 10.0.3.191
+4000.example. 5M IN A 10.0.3.192
+4000.example. 5M IN A 10.0.3.193
+4000.example. 5M IN A 10.0.3.194
+4000.example. 5M IN A 10.0.3.195
+4000.example. 5M IN A 10.0.3.196
+4000.example. 5M IN A 10.0.3.197
+4000.example. 5M IN A 10.0.3.198
+4000.example. 5M IN A 10.0.3.199
+4000.example. 5M IN A 10.0.3.200
+4000.example. 5M IN A 10.0.3.201
+4000.example. 5M IN A 10.0.3.202
+4000.example. 5M IN A 10.0.3.203
+4000.example. 5M IN A 10.0.3.204
+4000.example. 5M IN A 10.0.3.205
+4000.example. 5M IN A 10.0.3.206
+4000.example. 5M IN A 10.0.3.207
+4000.example. 5M IN A 10.0.3.208
+4000.example. 5M IN A 10.0.3.209
+4000.example. 5M IN A 10.0.3.210
+4000.example. 5M IN A 10.0.3.211
+4000.example. 5M IN A 10.0.3.212
+4000.example. 5M IN A 10.0.3.213
+4000.example. 5M IN A 10.0.3.214
+4000.example. 5M IN A 10.0.3.215
+4000.example. 5M IN A 10.0.3.216
+4000.example. 5M IN A 10.0.3.217
+4000.example. 5M IN A 10.0.3.218
+4000.example. 5M IN A 10.0.3.219
+4000.example. 5M IN A 10.0.3.220
+4000.example. 5M IN A 10.0.3.221
+4000.example. 5M IN A 10.0.3.222
+4000.example. 5M IN A 10.0.3.223
+4000.example. 5M IN A 10.0.3.224
+4000.example. 5M IN A 10.0.3.225
+4000.example. 5M IN A 10.0.3.226
+4000.example. 5M IN A 10.0.3.227
+4000.example. 5M IN A 10.0.3.228
+4000.example. 5M IN A 10.0.3.229
+4000.example. 5M IN A 10.0.3.230
+4000.example. 5M IN A 10.0.3.231
+4000.example. 5M IN A 10.0.3.232
+4000.example. 5M IN A 10.0.3.233
+4000.example. 5M IN A 10.0.3.234
+4000.example. 5M IN A 10.0.3.235
+4000.example. 5M IN A 10.0.3.236
+4000.example. 5M IN A 10.0.3.237
+4000.example. 5M IN A 10.0.3.238
+4000.example. 5M IN A 10.0.3.239
+4000.example. 5M IN A 10.0.3.240
+4000.example. 5M IN A 10.0.3.241
+4000.example. 5M IN A 10.0.3.242
+4000.example. 5M IN A 10.0.3.243
+4000.example. 5M IN A 10.0.3.244
+4000.example. 5M IN A 10.0.3.245
+4000.example. 5M IN A 10.0.3.246
+4000.example. 5M IN A 10.0.3.247
+4000.example. 5M IN A 10.0.3.248
+4000.example. 5M IN A 10.0.3.249
+4000.example. 5M IN A 10.0.3.250
+4000.example. 5M IN A 10.0.3.251
+4000.example. 5M IN A 10.0.3.252
+4000.example. 5M IN A 10.0.3.253
+4000.example. 5M IN A 10.0.3.254
+4000.example. 5M IN A 10.0.3.255
+4000.example. 5M IN A 10.0.4.0
+4000.example. 5M IN A 10.0.4.1
+4000.example. 5M IN A 10.0.4.2
+4000.example. 5M IN A 10.0.4.3
+4000.example. 5M IN A 10.0.4.4
+4000.example. 5M IN A 10.0.4.5
+4000.example. 5M IN A 10.0.4.6
+4000.example. 5M IN A 10.0.4.7
+4000.example. 5M IN A 10.0.4.8
+4000.example. 5M IN A 10.0.4.9
+4000.example. 5M IN A 10.0.4.10
+4000.example. 5M IN A 10.0.4.11
+4000.example. 5M IN A 10.0.4.12
+4000.example. 5M IN A 10.0.4.13
+4000.example. 5M IN A 10.0.4.14
+4000.example. 5M IN A 10.0.4.15
+4000.example. 5M IN A 10.0.4.16
+4000.example. 5M IN A 10.0.4.17
+4000.example. 5M IN A 10.0.4.18
+4000.example. 5M IN A 10.0.4.19
+4000.example. 5M IN A 10.0.4.20
+4000.example. 5M IN A 10.0.4.21
+4000.example. 5M IN A 10.0.4.22
+4000.example. 5M IN A 10.0.4.23
+4000.example. 5M IN A 10.0.4.24
+4000.example. 5M IN A 10.0.4.25
+4000.example. 5M IN A 10.0.4.26
+4000.example. 5M IN A 10.0.4.27
+4000.example. 5M IN A 10.0.4.28
+4000.example. 5M IN A 10.0.4.29
+4000.example. 5M IN A 10.0.4.30
+4000.example. 5M IN A 10.0.4.31
+4000.example. 5M IN A 10.0.4.32
+4000.example. 5M IN A 10.0.4.33
+4000.example. 5M IN A 10.0.4.34
+4000.example. 5M IN A 10.0.4.35
+4000.example. 5M IN A 10.0.4.36
+4000.example. 5M IN A 10.0.4.37
+4000.example. 5M IN A 10.0.4.38
+4000.example. 5M IN A 10.0.4.39
+4000.example. 5M IN A 10.0.4.40
+4000.example. 5M IN A 10.0.4.41
+4000.example. 5M IN A 10.0.4.42
+4000.example. 5M IN A 10.0.4.43
+4000.example. 5M IN A 10.0.4.44
+4000.example. 5M IN A 10.0.4.45
+4000.example. 5M IN A 10.0.4.46
+4000.example. 5M IN A 10.0.4.47
+4000.example. 5M IN A 10.0.4.48
+4000.example. 5M IN A 10.0.4.49
+4000.example. 5M IN A 10.0.4.50
+4000.example. 5M IN A 10.0.4.51
+4000.example. 5M IN A 10.0.4.52
+4000.example. 5M IN A 10.0.4.53
+4000.example. 5M IN A 10.0.4.54
+4000.example. 5M IN A 10.0.4.55
+4000.example. 5M IN A 10.0.4.56
+4000.example. 5M IN A 10.0.4.57
+4000.example. 5M IN A 10.0.4.58
+4000.example. 5M IN A 10.0.4.59
+4000.example. 5M IN A 10.0.4.60
+4000.example. 5M IN A 10.0.4.61
+4000.example. 5M IN A 10.0.4.62
+4000.example. 5M IN A 10.0.4.63
+4000.example. 5M IN A 10.0.4.64
+4000.example. 5M IN A 10.0.4.65
+4000.example. 5M IN A 10.0.4.66
+4000.example. 5M IN A 10.0.4.67
+4000.example. 5M IN A 10.0.4.68
+4000.example. 5M IN A 10.0.4.69
+4000.example. 5M IN A 10.0.4.70
+4000.example. 5M IN A 10.0.4.71
+4000.example. 5M IN A 10.0.4.72
+4000.example. 5M IN A 10.0.4.73
+4000.example. 5M IN A 10.0.4.74
+4000.example. 5M IN A 10.0.4.75
+4000.example. 5M IN A 10.0.4.76
+4000.example. 5M IN A 10.0.4.77
+4000.example. 5M IN A 10.0.4.78
+4000.example. 5M IN A 10.0.4.79
+4000.example. 5M IN A 10.0.4.80
+4000.example. 5M IN A 10.0.4.81
+4000.example. 5M IN A 10.0.4.82
+4000.example. 5M IN A 10.0.4.83
+4000.example. 5M IN A 10.0.4.84
+4000.example. 5M IN A 10.0.4.85
+4000.example. 5M IN A 10.0.4.86
+4000.example. 5M IN A 10.0.4.87
+4000.example. 5M IN A 10.0.4.88
+4000.example. 5M IN A 10.0.4.89
+4000.example. 5M IN A 10.0.4.90
+4000.example. 5M IN A 10.0.4.91
+4000.example. 5M IN A 10.0.4.92
+4000.example. 5M IN A 10.0.4.93
+4000.example. 5M IN A 10.0.4.94
+4000.example. 5M IN A 10.0.4.95
+4000.example. 5M IN A 10.0.4.96
+4000.example. 5M IN A 10.0.4.97
+4000.example. 5M IN A 10.0.4.98
+4000.example. 5M IN A 10.0.4.99
+4000.example. 5M IN A 10.0.4.100
+4000.example. 5M IN A 10.0.4.101
+4000.example. 5M IN A 10.0.4.102
+4000.example. 5M IN A 10.0.4.103
+4000.example. 5M IN A 10.0.4.104
+4000.example. 5M IN A 10.0.4.105
+4000.example. 5M IN A 10.0.4.106
+4000.example. 5M IN A 10.0.4.107
+4000.example. 5M IN A 10.0.4.108
+4000.example. 5M IN A 10.0.4.109
+4000.example. 5M IN A 10.0.4.110
+4000.example. 5M IN A 10.0.4.111
+4000.example. 5M IN A 10.0.4.112
+4000.example. 5M IN A 10.0.4.113
+4000.example. 5M IN A 10.0.4.114
+4000.example. 5M IN A 10.0.4.115
+4000.example. 5M IN A 10.0.4.116
+4000.example. 5M IN A 10.0.4.117
+4000.example. 5M IN A 10.0.4.118
+4000.example. 5M IN A 10.0.4.119
+4000.example. 5M IN A 10.0.4.120
+4000.example. 5M IN A 10.0.4.121
+4000.example. 5M IN A 10.0.4.122
+4000.example. 5M IN A 10.0.4.123
+4000.example. 5M IN A 10.0.4.124
+4000.example. 5M IN A 10.0.4.125
+4000.example. 5M IN A 10.0.4.126
+4000.example. 5M IN A 10.0.4.127
+4000.example. 5M IN A 10.0.4.128
+4000.example. 5M IN A 10.0.4.129
+4000.example. 5M IN A 10.0.4.130
+4000.example. 5M IN A 10.0.4.131
+4000.example. 5M IN A 10.0.4.132
+4000.example. 5M IN A 10.0.4.133
+4000.example. 5M IN A 10.0.4.134
+4000.example. 5M IN A 10.0.4.135
+4000.example. 5M IN A 10.0.4.136
+4000.example. 5M IN A 10.0.4.137
+4000.example. 5M IN A 10.0.4.138
+4000.example. 5M IN A 10.0.4.139
+4000.example. 5M IN A 10.0.4.140
+4000.example. 5M IN A 10.0.4.141
+4000.example. 5M IN A 10.0.4.142
+4000.example. 5M IN A 10.0.4.143
+4000.example. 5M IN A 10.0.4.144
+4000.example. 5M IN A 10.0.4.145
+4000.example. 5M IN A 10.0.4.146
+4000.example. 5M IN A 10.0.4.147
+4000.example. 5M IN A 10.0.4.148
+4000.example. 5M IN A 10.0.4.149
+4000.example. 5M IN A 10.0.4.150
+4000.example. 5M IN A 10.0.4.151
+4000.example. 5M IN A 10.0.4.152
+4000.example. 5M IN A 10.0.4.153
+4000.example. 5M IN A 10.0.4.154
+4000.example. 5M IN A 10.0.4.155
+4000.example. 5M IN A 10.0.4.156
+4000.example. 5M IN A 10.0.4.157
+4000.example. 5M IN A 10.0.4.158
+4000.example. 5M IN A 10.0.4.159
+4000.example. 5M IN A 10.0.4.160
+4000.example. 5M IN A 10.0.4.161
+4000.example. 5M IN A 10.0.4.162
+4000.example. 5M IN A 10.0.4.163
+4000.example. 5M IN A 10.0.4.164
+4000.example. 5M IN A 10.0.4.165
+4000.example. 5M IN A 10.0.4.166
+4000.example. 5M IN A 10.0.4.167
+4000.example. 5M IN A 10.0.4.168
+4000.example. 5M IN A 10.0.4.169
+4000.example. 5M IN A 10.0.4.170
+4000.example. 5M IN A 10.0.4.171
+4000.example. 5M IN A 10.0.4.172
+4000.example. 5M IN A 10.0.4.173
+4000.example. 5M IN A 10.0.4.174
+4000.example. 5M IN A 10.0.4.175
+4000.example. 5M IN A 10.0.4.176
+4000.example. 5M IN A 10.0.4.177
+4000.example. 5M IN A 10.0.4.178
+4000.example. 5M IN A 10.0.4.179
+4000.example. 5M IN A 10.0.4.180
+4000.example. 5M IN A 10.0.4.181
+4000.example. 5M IN A 10.0.4.182
+4000.example. 5M IN A 10.0.4.183
+4000.example. 5M IN A 10.0.4.184
+4000.example. 5M IN A 10.0.4.185
+4000.example. 5M IN A 10.0.4.186
+4000.example. 5M IN A 10.0.4.187
+4000.example. 5M IN A 10.0.4.188
+4000.example. 5M IN A 10.0.4.189
+4000.example. 5M IN A 10.0.4.190
+4000.example. 5M IN A 10.0.4.191
+4000.example. 5M IN A 10.0.4.192
+4000.example. 5M IN A 10.0.4.193
+4000.example. 5M IN A 10.0.4.194
+4000.example. 5M IN A 10.0.4.195
+4000.example. 5M IN A 10.0.4.196
+4000.example. 5M IN A 10.0.4.197
+4000.example. 5M IN A 10.0.4.198
+4000.example. 5M IN A 10.0.4.199
+4000.example. 5M IN A 10.0.4.200
+4000.example. 5M IN A 10.0.4.201
+4000.example. 5M IN A 10.0.4.202
+4000.example. 5M IN A 10.0.4.203
+4000.example. 5M IN A 10.0.4.204
+4000.example. 5M IN A 10.0.4.205
+4000.example. 5M IN A 10.0.4.206
+4000.example. 5M IN A 10.0.4.207
+4000.example. 5M IN A 10.0.4.208
+4000.example. 5M IN A 10.0.4.209
+4000.example. 5M IN A 10.0.4.210
+4000.example. 5M IN A 10.0.4.211
+4000.example. 5M IN A 10.0.4.212
+4000.example. 5M IN A 10.0.4.213
+4000.example. 5M IN A 10.0.4.214
+4000.example. 5M IN A 10.0.4.215
+4000.example. 5M IN A 10.0.4.216
+4000.example. 5M IN A 10.0.4.217
+4000.example. 5M IN A 10.0.4.218
+4000.example. 5M IN A 10.0.4.219
+4000.example. 5M IN A 10.0.4.220
+4000.example. 5M IN A 10.0.4.221
+4000.example. 5M IN A 10.0.4.222
+4000.example. 5M IN A 10.0.4.223
+4000.example. 5M IN A 10.0.4.224
+4000.example. 5M IN A 10.0.4.225
+4000.example. 5M IN A 10.0.4.226
+4000.example. 5M IN A 10.0.4.227
+4000.example. 5M IN A 10.0.4.228
+4000.example. 5M IN A 10.0.4.229
+4000.example. 5M IN A 10.0.4.230
+4000.example. 5M IN A 10.0.4.231
+4000.example. 5M IN A 10.0.4.232
+4000.example. 5M IN A 10.0.4.233
+4000.example. 5M IN A 10.0.4.234
+4000.example. 5M IN A 10.0.4.235
+4000.example. 5M IN A 10.0.4.236
+4000.example. 5M IN A 10.0.4.237
+4000.example. 5M IN A 10.0.4.238
+4000.example. 5M IN A 10.0.4.239
+4000.example. 5M IN A 10.0.4.240
+4000.example. 5M IN A 10.0.4.241
+4000.example. 5M IN A 10.0.4.242
+4000.example. 5M IN A 10.0.4.243
+4000.example. 5M IN A 10.0.4.244
+4000.example. 5M IN A 10.0.4.245
+4000.example. 5M IN A 10.0.4.246
+4000.example. 5M IN A 10.0.4.247
+4000.example. 5M IN A 10.0.4.248
+4000.example. 5M IN A 10.0.4.249
+4000.example. 5M IN A 10.0.4.250
+4000.example. 5M IN A 10.0.4.251
+4000.example. 5M IN A 10.0.4.252
+4000.example. 5M IN A 10.0.4.253
+4000.example. 5M IN A 10.0.4.254
+4000.example. 5M IN A 10.0.4.255
+4000.example. 5M IN A 10.0.5.0
+4000.example. 5M IN A 10.0.5.1
+4000.example. 5M IN A 10.0.5.2
+4000.example. 5M IN A 10.0.5.3
+4000.example. 5M IN A 10.0.5.4
+4000.example. 5M IN A 10.0.5.5
+4000.example. 5M IN A 10.0.5.6
+4000.example. 5M IN A 10.0.5.7
+4000.example. 5M IN A 10.0.5.8
+4000.example. 5M IN A 10.0.5.9
+4000.example. 5M IN A 10.0.5.10
+4000.example. 5M IN A 10.0.5.11
+4000.example. 5M IN A 10.0.5.12
+4000.example. 5M IN A 10.0.5.13
+4000.example. 5M IN A 10.0.5.14
+4000.example. 5M IN A 10.0.5.15
+4000.example. 5M IN A 10.0.5.16
+4000.example. 5M IN A 10.0.5.17
+4000.example. 5M IN A 10.0.5.18
+4000.example. 5M IN A 10.0.5.19
+4000.example. 5M IN A 10.0.5.20
+4000.example. 5M IN A 10.0.5.21
+4000.example. 5M IN A 10.0.5.22
+4000.example. 5M IN A 10.0.5.23
+4000.example. 5M IN A 10.0.5.24
+4000.example. 5M IN A 10.0.5.25
+4000.example. 5M IN A 10.0.5.26
+4000.example. 5M IN A 10.0.5.27
+4000.example. 5M IN A 10.0.5.28
+4000.example. 5M IN A 10.0.5.29
+4000.example. 5M IN A 10.0.5.30
+4000.example. 5M IN A 10.0.5.31
+4000.example. 5M IN A 10.0.5.32
+4000.example. 5M IN A 10.0.5.33
+4000.example. 5M IN A 10.0.5.34
+4000.example. 5M IN A 10.0.5.35
+4000.example. 5M IN A 10.0.5.36
+4000.example. 5M IN A 10.0.5.37
+4000.example. 5M IN A 10.0.5.38
+4000.example. 5M IN A 10.0.5.39
+4000.example. 5M IN A 10.0.5.40
+4000.example. 5M IN A 10.0.5.41
+4000.example. 5M IN A 10.0.5.42
+4000.example. 5M IN A 10.0.5.43
+4000.example. 5M IN A 10.0.5.44
+4000.example. 5M IN A 10.0.5.45
+4000.example. 5M IN A 10.0.5.46
+4000.example. 5M IN A 10.0.5.47
+4000.example. 5M IN A 10.0.5.48
+4000.example. 5M IN A 10.0.5.49
+4000.example. 5M IN A 10.0.5.50
+4000.example. 5M IN A 10.0.5.51
+4000.example. 5M IN A 10.0.5.52
+4000.example. 5M IN A 10.0.5.53
+4000.example. 5M IN A 10.0.5.54
+4000.example. 5M IN A 10.0.5.55
+4000.example. 5M IN A 10.0.5.56
+4000.example. 5M IN A 10.0.5.57
+4000.example. 5M IN A 10.0.5.58
+4000.example. 5M IN A 10.0.5.59
+4000.example. 5M IN A 10.0.5.60
+4000.example. 5M IN A 10.0.5.61
+4000.example. 5M IN A 10.0.5.62
+4000.example. 5M IN A 10.0.5.63
+4000.example. 5M IN A 10.0.5.64
+4000.example. 5M IN A 10.0.5.65
+4000.example. 5M IN A 10.0.5.66
+4000.example. 5M IN A 10.0.5.67
+4000.example. 5M IN A 10.0.5.68
+4000.example. 5M IN A 10.0.5.69
+4000.example. 5M IN A 10.0.5.70
+4000.example. 5M IN A 10.0.5.71
+4000.example. 5M IN A 10.0.5.72
+4000.example. 5M IN A 10.0.5.73
+4000.example. 5M IN A 10.0.5.74
+4000.example. 5M IN A 10.0.5.75
+4000.example. 5M IN A 10.0.5.76
+4000.example. 5M IN A 10.0.5.77
+4000.example. 5M IN A 10.0.5.78
+4000.example. 5M IN A 10.0.5.79
+4000.example. 5M IN A 10.0.5.80
+4000.example. 5M IN A 10.0.5.81
+4000.example. 5M IN A 10.0.5.82
+4000.example. 5M IN A 10.0.5.83
+4000.example. 5M IN A 10.0.5.84
+4000.example. 5M IN A 10.0.5.85
+4000.example. 5M IN A 10.0.5.86
+4000.example. 5M IN A 10.0.5.87
+4000.example. 5M IN A 10.0.5.88
+4000.example. 5M IN A 10.0.5.89
+4000.example. 5M IN A 10.0.5.90
+4000.example. 5M IN A 10.0.5.91
+4000.example. 5M IN A 10.0.5.92
+4000.example. 5M IN A 10.0.5.93
+4000.example. 5M IN A 10.0.5.94
+4000.example. 5M IN A 10.0.5.95
+4000.example. 5M IN A 10.0.5.96
+4000.example. 5M IN A 10.0.5.97
+4000.example. 5M IN A 10.0.5.98
+4000.example. 5M IN A 10.0.5.99
+4000.example. 5M IN A 10.0.5.100
+4000.example. 5M IN A 10.0.5.101
+4000.example. 5M IN A 10.0.5.102
+4000.example. 5M IN A 10.0.5.103
+4000.example. 5M IN A 10.0.5.104
+4000.example. 5M IN A 10.0.5.105
+4000.example. 5M IN A 10.0.5.106
+4000.example. 5M IN A 10.0.5.107
+4000.example. 5M IN A 10.0.5.108
+4000.example. 5M IN A 10.0.5.109
+4000.example. 5M IN A 10.0.5.110
+4000.example. 5M IN A 10.0.5.111
+4000.example. 5M IN A 10.0.5.112
+4000.example. 5M IN A 10.0.5.113
+4000.example. 5M IN A 10.0.5.114
+4000.example. 5M IN A 10.0.5.115
+4000.example. 5M IN A 10.0.5.116
+4000.example. 5M IN A 10.0.5.117
+4000.example. 5M IN A 10.0.5.118
+4000.example. 5M IN A 10.0.5.119
+4000.example. 5M IN A 10.0.5.120
+4000.example. 5M IN A 10.0.5.121
+4000.example. 5M IN A 10.0.5.122
+4000.example. 5M IN A 10.0.5.123
+4000.example. 5M IN A 10.0.5.124
+4000.example. 5M IN A 10.0.5.125
+4000.example. 5M IN A 10.0.5.126
+4000.example. 5M IN A 10.0.5.127
+4000.example. 5M IN A 10.0.5.128
+4000.example. 5M IN A 10.0.5.129
+4000.example. 5M IN A 10.0.5.130
+4000.example. 5M IN A 10.0.5.131
+4000.example. 5M IN A 10.0.5.132
+4000.example. 5M IN A 10.0.5.133
+4000.example. 5M IN A 10.0.5.134
+4000.example. 5M IN A 10.0.5.135
+4000.example. 5M IN A 10.0.5.136
+4000.example. 5M IN A 10.0.5.137
+4000.example. 5M IN A 10.0.5.138
+4000.example. 5M IN A 10.0.5.139
+4000.example. 5M IN A 10.0.5.140
+4000.example. 5M IN A 10.0.5.141
+4000.example. 5M IN A 10.0.5.142
+4000.example. 5M IN A 10.0.5.143
+4000.example. 5M IN A 10.0.5.144
+4000.example. 5M IN A 10.0.5.145
+4000.example. 5M IN A 10.0.5.146
+4000.example. 5M IN A 10.0.5.147
+4000.example. 5M IN A 10.0.5.148
+4000.example. 5M IN A 10.0.5.149
+4000.example. 5M IN A 10.0.5.150
+4000.example. 5M IN A 10.0.5.151
+4000.example. 5M IN A 10.0.5.152
+4000.example. 5M IN A 10.0.5.153
+4000.example. 5M IN A 10.0.5.154
+4000.example. 5M IN A 10.0.5.155
+4000.example. 5M IN A 10.0.5.156
+4000.example. 5M IN A 10.0.5.157
+4000.example. 5M IN A 10.0.5.158
+4000.example. 5M IN A 10.0.5.159
+4000.example. 5M IN A 10.0.5.160
+4000.example. 5M IN A 10.0.5.161
+4000.example. 5M IN A 10.0.5.162
+4000.example. 5M IN A 10.0.5.163
+4000.example. 5M IN A 10.0.5.164
+4000.example. 5M IN A 10.0.5.165
+4000.example. 5M IN A 10.0.5.166
+4000.example. 5M IN A 10.0.5.167
+4000.example. 5M IN A 10.0.5.168
+4000.example. 5M IN A 10.0.5.169
+4000.example. 5M IN A 10.0.5.170
+4000.example. 5M IN A 10.0.5.171
+4000.example. 5M IN A 10.0.5.172
+4000.example. 5M IN A 10.0.5.173
+4000.example. 5M IN A 10.0.5.174
+4000.example. 5M IN A 10.0.5.175
+4000.example. 5M IN A 10.0.5.176
+4000.example. 5M IN A 10.0.5.177
+4000.example. 5M IN A 10.0.5.178
+4000.example. 5M IN A 10.0.5.179
+4000.example. 5M IN A 10.0.5.180
+4000.example. 5M IN A 10.0.5.181
+4000.example. 5M IN A 10.0.5.182
+4000.example. 5M IN A 10.0.5.183
+4000.example. 5M IN A 10.0.5.184
+4000.example. 5M IN A 10.0.5.185
+4000.example. 5M IN A 10.0.5.186
+4000.example. 5M IN A 10.0.5.187
+4000.example. 5M IN A 10.0.5.188
+4000.example. 5M IN A 10.0.5.189
+4000.example. 5M IN A 10.0.5.190
+4000.example. 5M IN A 10.0.5.191
+4000.example. 5M IN A 10.0.5.192
+4000.example. 5M IN A 10.0.5.193
+4000.example. 5M IN A 10.0.5.194
+4000.example. 5M IN A 10.0.5.195
+4000.example. 5M IN A 10.0.5.196
+4000.example. 5M IN A 10.0.5.197
+4000.example. 5M IN A 10.0.5.198
+4000.example. 5M IN A 10.0.5.199
+4000.example. 5M IN A 10.0.5.200
+4000.example. 5M IN A 10.0.5.201
+4000.example. 5M IN A 10.0.5.202
+4000.example. 5M IN A 10.0.5.203
+4000.example. 5M IN A 10.0.5.204
+4000.example. 5M IN A 10.0.5.205
+4000.example. 5M IN A 10.0.5.206
+4000.example. 5M IN A 10.0.5.207
+4000.example. 5M IN A 10.0.5.208
+4000.example. 5M IN A 10.0.5.209
+4000.example. 5M IN A 10.0.5.210
+4000.example. 5M IN A 10.0.5.211
+4000.example. 5M IN A 10.0.5.212
+4000.example. 5M IN A 10.0.5.213
+4000.example. 5M IN A 10.0.5.214
+4000.example. 5M IN A 10.0.5.215
+4000.example. 5M IN A 10.0.5.216
+4000.example. 5M IN A 10.0.5.217
+4000.example. 5M IN A 10.0.5.218
+4000.example. 5M IN A 10.0.5.219
+4000.example. 5M IN A 10.0.5.220
+4000.example. 5M IN A 10.0.5.221
+4000.example. 5M IN A 10.0.5.222
+4000.example. 5M IN A 10.0.5.223
+4000.example. 5M IN A 10.0.5.224
+4000.example. 5M IN A 10.0.5.225
+4000.example. 5M IN A 10.0.5.226
+4000.example. 5M IN A 10.0.5.227
+4000.example. 5M IN A 10.0.5.228
+4000.example. 5M IN A 10.0.5.229
+4000.example. 5M IN A 10.0.5.230
+4000.example. 5M IN A 10.0.5.231
+4000.example. 5M IN A 10.0.5.232
+4000.example. 5M IN A 10.0.5.233
+4000.example. 5M IN A 10.0.5.234
+4000.example. 5M IN A 10.0.5.235
+4000.example. 5M IN A 10.0.5.236
+4000.example. 5M IN A 10.0.5.237
+4000.example. 5M IN A 10.0.5.238
+4000.example. 5M IN A 10.0.5.239
+4000.example. 5M IN A 10.0.5.240
+4000.example. 5M IN A 10.0.5.241
+4000.example. 5M IN A 10.0.5.242
+4000.example. 5M IN A 10.0.5.243
+4000.example. 5M IN A 10.0.5.244
+4000.example. 5M IN A 10.0.5.245
+4000.example. 5M IN A 10.0.5.246
+4000.example. 5M IN A 10.0.5.247
+4000.example. 5M IN A 10.0.5.248
+4000.example. 5M IN A 10.0.5.249
+4000.example. 5M IN A 10.0.5.250
+4000.example. 5M IN A 10.0.5.251
+4000.example. 5M IN A 10.0.5.252
+4000.example. 5M IN A 10.0.5.253
+4000.example. 5M IN A 10.0.5.254
+4000.example. 5M IN A 10.0.5.255
+4000.example. 5M IN A 10.0.6.0
+4000.example. 5M IN A 10.0.6.1
+4000.example. 5M IN A 10.0.6.2
+4000.example. 5M IN A 10.0.6.3
+4000.example. 5M IN A 10.0.6.4
+4000.example. 5M IN A 10.0.6.5
+4000.example. 5M IN A 10.0.6.6
+4000.example. 5M IN A 10.0.6.7
+4000.example. 5M IN A 10.0.6.8
+4000.example. 5M IN A 10.0.6.9
+4000.example. 5M IN A 10.0.6.10
+4000.example. 5M IN A 10.0.6.11
+4000.example. 5M IN A 10.0.6.12
+4000.example. 5M IN A 10.0.6.13
+4000.example. 5M IN A 10.0.6.14
+4000.example. 5M IN A 10.0.6.15
+4000.example. 5M IN A 10.0.6.16
+4000.example. 5M IN A 10.0.6.17
+4000.example. 5M IN A 10.0.6.18
+4000.example. 5M IN A 10.0.6.19
+4000.example. 5M IN A 10.0.6.20
+4000.example. 5M IN A 10.0.6.21
+4000.example. 5M IN A 10.0.6.22
+4000.example. 5M IN A 10.0.6.23
+4000.example. 5M IN A 10.0.6.24
+4000.example. 5M IN A 10.0.6.25
+4000.example. 5M IN A 10.0.6.26
+4000.example. 5M IN A 10.0.6.27
+4000.example. 5M IN A 10.0.6.28
+4000.example. 5M IN A 10.0.6.29
+4000.example. 5M IN A 10.0.6.30
+4000.example. 5M IN A 10.0.6.31
+4000.example. 5M IN A 10.0.6.32
+4000.example. 5M IN A 10.0.6.33
+4000.example. 5M IN A 10.0.6.34
+4000.example. 5M IN A 10.0.6.35
+4000.example. 5M IN A 10.0.6.36
+4000.example. 5M IN A 10.0.6.37
+4000.example. 5M IN A 10.0.6.38
+4000.example. 5M IN A 10.0.6.39
+4000.example. 5M IN A 10.0.6.40
+4000.example. 5M IN A 10.0.6.41
+4000.example. 5M IN A 10.0.6.42
+4000.example. 5M IN A 10.0.6.43
+4000.example. 5M IN A 10.0.6.44
+4000.example. 5M IN A 10.0.6.45
+4000.example. 5M IN A 10.0.6.46
+4000.example. 5M IN A 10.0.6.47
+4000.example. 5M IN A 10.0.6.48
+4000.example. 5M IN A 10.0.6.49
+4000.example. 5M IN A 10.0.6.50
+4000.example. 5M IN A 10.0.6.51
+4000.example. 5M IN A 10.0.6.52
+4000.example. 5M IN A 10.0.6.53
+4000.example. 5M IN A 10.0.6.54
+4000.example. 5M IN A 10.0.6.55
+4000.example. 5M IN A 10.0.6.56
+4000.example. 5M IN A 10.0.6.57
+4000.example. 5M IN A 10.0.6.58
+4000.example. 5M IN A 10.0.6.59
+4000.example. 5M IN A 10.0.6.60
+4000.example. 5M IN A 10.0.6.61
+4000.example. 5M IN A 10.0.6.62
+4000.example. 5M IN A 10.0.6.63
+4000.example. 5M IN A 10.0.6.64
+4000.example. 5M IN A 10.0.6.65
+4000.example. 5M IN A 10.0.6.66
+4000.example. 5M IN A 10.0.6.67
+4000.example. 5M IN A 10.0.6.68
+4000.example. 5M IN A 10.0.6.69
+4000.example. 5M IN A 10.0.6.70
+4000.example. 5M IN A 10.0.6.71
+4000.example. 5M IN A 10.0.6.72
+4000.example. 5M IN A 10.0.6.73
+4000.example. 5M IN A 10.0.6.74
+4000.example. 5M IN A 10.0.6.75
+4000.example. 5M IN A 10.0.6.76
+4000.example. 5M IN A 10.0.6.77
+4000.example. 5M IN A 10.0.6.78
+4000.example. 5M IN A 10.0.6.79
+4000.example. 5M IN A 10.0.6.80
+4000.example. 5M IN A 10.0.6.81
+4000.example. 5M IN A 10.0.6.82
+4000.example. 5M IN A 10.0.6.83
+4000.example. 5M IN A 10.0.6.84
+4000.example. 5M IN A 10.0.6.85
+4000.example. 5M IN A 10.0.6.86
+4000.example. 5M IN A 10.0.6.87
+4000.example. 5M IN A 10.0.6.88
+4000.example. 5M IN A 10.0.6.89
+4000.example. 5M IN A 10.0.6.90
+4000.example. 5M IN A 10.0.6.91
+4000.example. 5M IN A 10.0.6.92
+4000.example. 5M IN A 10.0.6.93
+4000.example. 5M IN A 10.0.6.94
+4000.example. 5M IN A 10.0.6.95
+4000.example. 5M IN A 10.0.6.96
+4000.example. 5M IN A 10.0.6.97
+4000.example. 5M IN A 10.0.6.98
+4000.example. 5M IN A 10.0.6.99
+4000.example. 5M IN A 10.0.6.100
+4000.example. 5M IN A 10.0.6.101
+4000.example. 5M IN A 10.0.6.102
+4000.example. 5M IN A 10.0.6.103
+4000.example. 5M IN A 10.0.6.104
+4000.example. 5M IN A 10.0.6.105
+4000.example. 5M IN A 10.0.6.106
+4000.example. 5M IN A 10.0.6.107
+4000.example. 5M IN A 10.0.6.108
+4000.example. 5M IN A 10.0.6.109
+4000.example. 5M IN A 10.0.6.110
+4000.example. 5M IN A 10.0.6.111
+4000.example. 5M IN A 10.0.6.112
+4000.example. 5M IN A 10.0.6.113
+4000.example. 5M IN A 10.0.6.114
+4000.example. 5M IN A 10.0.6.115
+4000.example. 5M IN A 10.0.6.116
+4000.example. 5M IN A 10.0.6.117
+4000.example. 5M IN A 10.0.6.118
+4000.example. 5M IN A 10.0.6.119
+4000.example. 5M IN A 10.0.6.120
+4000.example. 5M IN A 10.0.6.121
+4000.example. 5M IN A 10.0.6.122
+4000.example. 5M IN A 10.0.6.123
+4000.example. 5M IN A 10.0.6.124
+4000.example. 5M IN A 10.0.6.125
+4000.example. 5M IN A 10.0.6.126
+4000.example. 5M IN A 10.0.6.127
+4000.example. 5M IN A 10.0.6.128
+4000.example. 5M IN A 10.0.6.129
+4000.example. 5M IN A 10.0.6.130
+4000.example. 5M IN A 10.0.6.131
+4000.example. 5M IN A 10.0.6.132
+4000.example. 5M IN A 10.0.6.133
+4000.example. 5M IN A 10.0.6.134
+4000.example. 5M IN A 10.0.6.135
+4000.example. 5M IN A 10.0.6.136
+4000.example. 5M IN A 10.0.6.137
+4000.example. 5M IN A 10.0.6.138
+4000.example. 5M IN A 10.0.6.139
+4000.example. 5M IN A 10.0.6.140
+4000.example. 5M IN A 10.0.6.141
+4000.example. 5M IN A 10.0.6.142
+4000.example. 5M IN A 10.0.6.143
+4000.example. 5M IN A 10.0.6.144
+4000.example. 5M IN A 10.0.6.145
+4000.example. 5M IN A 10.0.6.146
+4000.example. 5M IN A 10.0.6.147
+4000.example. 5M IN A 10.0.6.148
+4000.example. 5M IN A 10.0.6.149
+4000.example. 5M IN A 10.0.6.150
+4000.example. 5M IN A 10.0.6.151
+4000.example. 5M IN A 10.0.6.152
+4000.example. 5M IN A 10.0.6.153
+4000.example. 5M IN A 10.0.6.154
+4000.example. 5M IN A 10.0.6.155
+4000.example. 5M IN A 10.0.6.156
+4000.example. 5M IN A 10.0.6.157
+4000.example. 5M IN A 10.0.6.158
+4000.example. 5M IN A 10.0.6.159
+4000.example. 5M IN A 10.0.6.160
+4000.example. 5M IN A 10.0.6.161
+4000.example. 5M IN A 10.0.6.162
+4000.example. 5M IN A 10.0.6.163
+4000.example. 5M IN A 10.0.6.164
+4000.example. 5M IN A 10.0.6.165
+4000.example. 5M IN A 10.0.6.166
+4000.example. 5M IN A 10.0.6.167
+4000.example. 5M IN A 10.0.6.168
+4000.example. 5M IN A 10.0.6.169
+4000.example. 5M IN A 10.0.6.170
+4000.example. 5M IN A 10.0.6.171
+4000.example. 5M IN A 10.0.6.172
+4000.example. 5M IN A 10.0.6.173
+4000.example. 5M IN A 10.0.6.174
+4000.example. 5M IN A 10.0.6.175
+4000.example. 5M IN A 10.0.6.176
+4000.example. 5M IN A 10.0.6.177
+4000.example. 5M IN A 10.0.6.178
+4000.example. 5M IN A 10.0.6.179
+4000.example. 5M IN A 10.0.6.180
+4000.example. 5M IN A 10.0.6.181
+4000.example. 5M IN A 10.0.6.182
+4000.example. 5M IN A 10.0.6.183
+4000.example. 5M IN A 10.0.6.184
+4000.example. 5M IN A 10.0.6.185
+4000.example. 5M IN A 10.0.6.186
+4000.example. 5M IN A 10.0.6.187
+4000.example. 5M IN A 10.0.6.188
+4000.example. 5M IN A 10.0.6.189
+4000.example. 5M IN A 10.0.6.190
+4000.example. 5M IN A 10.0.6.191
+4000.example. 5M IN A 10.0.6.192
+4000.example. 5M IN A 10.0.6.193
+4000.example. 5M IN A 10.0.6.194
+4000.example. 5M IN A 10.0.6.195
+4000.example. 5M IN A 10.0.6.196
+4000.example. 5M IN A 10.0.6.197
+4000.example. 5M IN A 10.0.6.198
+4000.example. 5M IN A 10.0.6.199
+4000.example. 5M IN A 10.0.6.200
+4000.example. 5M IN A 10.0.6.201
+4000.example. 5M IN A 10.0.6.202
+4000.example. 5M IN A 10.0.6.203
+4000.example. 5M IN A 10.0.6.204
+4000.example. 5M IN A 10.0.6.205
+4000.example. 5M IN A 10.0.6.206
+4000.example. 5M IN A 10.0.6.207
+4000.example. 5M IN A 10.0.6.208
+4000.example. 5M IN A 10.0.6.209
+4000.example. 5M IN A 10.0.6.210
+4000.example. 5M IN A 10.0.6.211
+4000.example. 5M IN A 10.0.6.212
+4000.example. 5M IN A 10.0.6.213
+4000.example. 5M IN A 10.0.6.214
+4000.example. 5M IN A 10.0.6.215
+4000.example. 5M IN A 10.0.6.216
+4000.example. 5M IN A 10.0.6.217
+4000.example. 5M IN A 10.0.6.218
+4000.example. 5M IN A 10.0.6.219
+4000.example. 5M IN A 10.0.6.220
+4000.example. 5M IN A 10.0.6.221
+4000.example. 5M IN A 10.0.6.222
+4000.example. 5M IN A 10.0.6.223
+4000.example. 5M IN A 10.0.6.224
+4000.example. 5M IN A 10.0.6.225
+4000.example. 5M IN A 10.0.6.226
+4000.example. 5M IN A 10.0.6.227
+4000.example. 5M IN A 10.0.6.228
+4000.example. 5M IN A 10.0.6.229
+4000.example. 5M IN A 10.0.6.230
+4000.example. 5M IN A 10.0.6.231
+4000.example. 5M IN A 10.0.6.232
+4000.example. 5M IN A 10.0.6.233
+4000.example. 5M IN A 10.0.6.234
+4000.example. 5M IN A 10.0.6.235
+4000.example. 5M IN A 10.0.6.236
+4000.example. 5M IN A 10.0.6.237
+4000.example. 5M IN A 10.0.6.238
+4000.example. 5M IN A 10.0.6.239
+4000.example. 5M IN A 10.0.6.240
+4000.example. 5M IN A 10.0.6.241
+4000.example. 5M IN A 10.0.6.242
+4000.example. 5M IN A 10.0.6.243
+4000.example. 5M IN A 10.0.6.244
+4000.example. 5M IN A 10.0.6.245
+4000.example. 5M IN A 10.0.6.246
+4000.example. 5M IN A 10.0.6.247
+4000.example. 5M IN A 10.0.6.248
+4000.example. 5M IN A 10.0.6.249
+4000.example. 5M IN A 10.0.6.250
+4000.example. 5M IN A 10.0.6.251
+4000.example. 5M IN A 10.0.6.252
+4000.example. 5M IN A 10.0.6.253
+4000.example. 5M IN A 10.0.6.254
+4000.example. 5M IN A 10.0.6.255
+4000.example. 5M IN A 10.0.7.0
+4000.example. 5M IN A 10.0.7.1
+4000.example. 5M IN A 10.0.7.2
+4000.example. 5M IN A 10.0.7.3
+4000.example. 5M IN A 10.0.7.4
+4000.example. 5M IN A 10.0.7.5
+4000.example. 5M IN A 10.0.7.6
+4000.example. 5M IN A 10.0.7.7
+4000.example. 5M IN A 10.0.7.8
+4000.example. 5M IN A 10.0.7.9
+4000.example. 5M IN A 10.0.7.10
+4000.example. 5M IN A 10.0.7.11
+4000.example. 5M IN A 10.0.7.12
+4000.example. 5M IN A 10.0.7.13
+4000.example. 5M IN A 10.0.7.14
+4000.example. 5M IN A 10.0.7.15
+4000.example. 5M IN A 10.0.7.16
+4000.example. 5M IN A 10.0.7.17
+4000.example. 5M IN A 10.0.7.18
+4000.example. 5M IN A 10.0.7.19
+4000.example. 5M IN A 10.0.7.20
+4000.example. 5M IN A 10.0.7.21
+4000.example. 5M IN A 10.0.7.22
+4000.example. 5M IN A 10.0.7.23
+4000.example. 5M IN A 10.0.7.24
+4000.example. 5M IN A 10.0.7.25
+4000.example. 5M IN A 10.0.7.26
+4000.example. 5M IN A 10.0.7.27
+4000.example. 5M IN A 10.0.7.28
+4000.example. 5M IN A 10.0.7.29
+4000.example. 5M IN A 10.0.7.30
+4000.example. 5M IN A 10.0.7.31
+4000.example. 5M IN A 10.0.7.32
+4000.example. 5M IN A 10.0.7.33
+4000.example. 5M IN A 10.0.7.34
+4000.example. 5M IN A 10.0.7.35
+4000.example. 5M IN A 10.0.7.36
+4000.example. 5M IN A 10.0.7.37
+4000.example. 5M IN A 10.0.7.38
+4000.example. 5M IN A 10.0.7.39
+4000.example. 5M IN A 10.0.7.40
+4000.example. 5M IN A 10.0.7.41
+4000.example. 5M IN A 10.0.7.42
+4000.example. 5M IN A 10.0.7.43
+4000.example. 5M IN A 10.0.7.44
+4000.example. 5M IN A 10.0.7.45
+4000.example. 5M IN A 10.0.7.46
+4000.example. 5M IN A 10.0.7.47
+4000.example. 5M IN A 10.0.7.48
+4000.example. 5M IN A 10.0.7.49
+4000.example. 5M IN A 10.0.7.50
+4000.example. 5M IN A 10.0.7.51
+4000.example. 5M IN A 10.0.7.52
+4000.example. 5M IN A 10.0.7.53
+4000.example. 5M IN A 10.0.7.54
+4000.example. 5M IN A 10.0.7.55
+4000.example. 5M IN A 10.0.7.56
+4000.example. 5M IN A 10.0.7.57
+4000.example. 5M IN A 10.0.7.58
+4000.example. 5M IN A 10.0.7.59
+4000.example. 5M IN A 10.0.7.60
+4000.example. 5M IN A 10.0.7.61
+4000.example. 5M IN A 10.0.7.62
+4000.example. 5M IN A 10.0.7.63
+4000.example. 5M IN A 10.0.7.64
+4000.example. 5M IN A 10.0.7.65
+4000.example. 5M IN A 10.0.7.66
+4000.example. 5M IN A 10.0.7.67
+4000.example. 5M IN A 10.0.7.68
+4000.example. 5M IN A 10.0.7.69
+4000.example. 5M IN A 10.0.7.70
+4000.example. 5M IN A 10.0.7.71
+4000.example. 5M IN A 10.0.7.72
+4000.example. 5M IN A 10.0.7.73
+4000.example. 5M IN A 10.0.7.74
+4000.example. 5M IN A 10.0.7.75
+4000.example. 5M IN A 10.0.7.76
+4000.example. 5M IN A 10.0.7.77
+4000.example. 5M IN A 10.0.7.78
+4000.example. 5M IN A 10.0.7.79
+4000.example. 5M IN A 10.0.7.80
+4000.example. 5M IN A 10.0.7.81
+4000.example. 5M IN A 10.0.7.82
+4000.example. 5M IN A 10.0.7.83
+4000.example. 5M IN A 10.0.7.84
+4000.example. 5M IN A 10.0.7.85
+4000.example. 5M IN A 10.0.7.86
+4000.example. 5M IN A 10.0.7.87
+4000.example. 5M IN A 10.0.7.88
+4000.example. 5M IN A 10.0.7.89
+4000.example. 5M IN A 10.0.7.90
+4000.example. 5M IN A 10.0.7.91
+4000.example. 5M IN A 10.0.7.92
+4000.example. 5M IN A 10.0.7.93
+4000.example. 5M IN A 10.0.7.94
+4000.example. 5M IN A 10.0.7.95
+4000.example. 5M IN A 10.0.7.96
+4000.example. 5M IN A 10.0.7.97
+4000.example. 5M IN A 10.0.7.98
+4000.example. 5M IN A 10.0.7.99
+4000.example. 5M IN A 10.0.7.100
+4000.example. 5M IN A 10.0.7.101
+4000.example. 5M IN A 10.0.7.102
+4000.example. 5M IN A 10.0.7.103
+4000.example. 5M IN A 10.0.7.104
+4000.example. 5M IN A 10.0.7.105
+4000.example. 5M IN A 10.0.7.106
+4000.example. 5M IN A 10.0.7.107
+4000.example. 5M IN A 10.0.7.108
+4000.example. 5M IN A 10.0.7.109
+4000.example. 5M IN A 10.0.7.110
+4000.example. 5M IN A 10.0.7.111
+4000.example. 5M IN A 10.0.7.112
+4000.example. 5M IN A 10.0.7.113
+4000.example. 5M IN A 10.0.7.114
+4000.example. 5M IN A 10.0.7.115
+4000.example. 5M IN A 10.0.7.116
+4000.example. 5M IN A 10.0.7.117
+4000.example. 5M IN A 10.0.7.118
+4000.example. 5M IN A 10.0.7.119
+4000.example. 5M IN A 10.0.7.120
+4000.example. 5M IN A 10.0.7.121
+4000.example. 5M IN A 10.0.7.122
+4000.example. 5M IN A 10.0.7.123
+4000.example. 5M IN A 10.0.7.124
+4000.example. 5M IN A 10.0.7.125
+4000.example. 5M IN A 10.0.7.126
+4000.example. 5M IN A 10.0.7.127
+4000.example. 5M IN A 10.0.7.128
+4000.example. 5M IN A 10.0.7.129
+4000.example. 5M IN A 10.0.7.130
+4000.example. 5M IN A 10.0.7.131
+4000.example. 5M IN A 10.0.7.132
+4000.example. 5M IN A 10.0.7.133
+4000.example. 5M IN A 10.0.7.134
+4000.example. 5M IN A 10.0.7.135
+4000.example. 5M IN A 10.0.7.136
+4000.example. 5M IN A 10.0.7.137
+4000.example. 5M IN A 10.0.7.138
+4000.example. 5M IN A 10.0.7.139
+4000.example. 5M IN A 10.0.7.140
+4000.example. 5M IN A 10.0.7.141
+4000.example. 5M IN A 10.0.7.142
+4000.example. 5M IN A 10.0.7.143
+4000.example. 5M IN A 10.0.7.144
+4000.example. 5M IN A 10.0.7.145
+4000.example. 5M IN A 10.0.7.146
+4000.example. 5M IN A 10.0.7.147
+4000.example. 5M IN A 10.0.7.148
+4000.example. 5M IN A 10.0.7.149
+4000.example. 5M IN A 10.0.7.150
+4000.example. 5M IN A 10.0.7.151
+4000.example. 5M IN A 10.0.7.152
+4000.example. 5M IN A 10.0.7.153
+4000.example. 5M IN A 10.0.7.154
+4000.example. 5M IN A 10.0.7.155
+4000.example. 5M IN A 10.0.7.156
+4000.example. 5M IN A 10.0.7.157
+4000.example. 5M IN A 10.0.7.158
+4000.example. 5M IN A 10.0.7.159
+4000.example. 5M IN A 10.0.7.160
+4000.example. 5M IN A 10.0.7.161
+4000.example. 5M IN A 10.0.7.162
+4000.example. 5M IN A 10.0.7.163
+4000.example. 5M IN A 10.0.7.164
+4000.example. 5M IN A 10.0.7.165
+4000.example. 5M IN A 10.0.7.166
+4000.example. 5M IN A 10.0.7.167
+4000.example. 5M IN A 10.0.7.168
+4000.example. 5M IN A 10.0.7.169
+4000.example. 5M IN A 10.0.7.170
+4000.example. 5M IN A 10.0.7.171
+4000.example. 5M IN A 10.0.7.172
+4000.example. 5M IN A 10.0.7.173
+4000.example. 5M IN A 10.0.7.174
+4000.example. 5M IN A 10.0.7.175
+4000.example. 5M IN A 10.0.7.176
+4000.example. 5M IN A 10.0.7.177
+4000.example. 5M IN A 10.0.7.178
+4000.example. 5M IN A 10.0.7.179
+4000.example. 5M IN A 10.0.7.180
+4000.example. 5M IN A 10.0.7.181
+4000.example. 5M IN A 10.0.7.182
+4000.example. 5M IN A 10.0.7.183
+4000.example. 5M IN A 10.0.7.184
+4000.example. 5M IN A 10.0.7.185
+4000.example. 5M IN A 10.0.7.186
+4000.example. 5M IN A 10.0.7.187
+4000.example. 5M IN A 10.0.7.188
+4000.example. 5M IN A 10.0.7.189
+4000.example. 5M IN A 10.0.7.190
+4000.example. 5M IN A 10.0.7.191
+4000.example. 5M IN A 10.0.7.192
+4000.example. 5M IN A 10.0.7.193
+4000.example. 5M IN A 10.0.7.194
+4000.example. 5M IN A 10.0.7.195
+4000.example. 5M IN A 10.0.7.196
+4000.example. 5M IN A 10.0.7.197
+4000.example. 5M IN A 10.0.7.198
+4000.example. 5M IN A 10.0.7.199
+4000.example. 5M IN A 10.0.7.200
+4000.example. 5M IN A 10.0.7.201
+4000.example. 5M IN A 10.0.7.202
+4000.example. 5M IN A 10.0.7.203
+4000.example. 5M IN A 10.0.7.204
+4000.example. 5M IN A 10.0.7.205
+4000.example. 5M IN A 10.0.7.206
+4000.example. 5M IN A 10.0.7.207
+4000.example. 5M IN A 10.0.7.208
+4000.example. 5M IN A 10.0.7.209
+4000.example. 5M IN A 10.0.7.210
+4000.example. 5M IN A 10.0.7.211
+4000.example. 5M IN A 10.0.7.212
+4000.example. 5M IN A 10.0.7.213
+4000.example. 5M IN A 10.0.7.214
+4000.example. 5M IN A 10.0.7.215
+4000.example. 5M IN A 10.0.7.216
+4000.example. 5M IN A 10.0.7.217
+4000.example. 5M IN A 10.0.7.218
+4000.example. 5M IN A 10.0.7.219
+4000.example. 5M IN A 10.0.7.220
+4000.example. 5M IN A 10.0.7.221
+4000.example. 5M IN A 10.0.7.222
+4000.example. 5M IN A 10.0.7.223
+4000.example. 5M IN A 10.0.7.224
+4000.example. 5M IN A 10.0.7.225
+4000.example. 5M IN A 10.0.7.226
+4000.example. 5M IN A 10.0.7.227
+4000.example. 5M IN A 10.0.7.228
+4000.example. 5M IN A 10.0.7.229
+4000.example. 5M IN A 10.0.7.230
+4000.example. 5M IN A 10.0.7.231
+4000.example. 5M IN A 10.0.7.232
+4000.example. 5M IN A 10.0.7.233
+4000.example. 5M IN A 10.0.7.234
+4000.example. 5M IN A 10.0.7.235
+4000.example. 5M IN A 10.0.7.236
+4000.example. 5M IN A 10.0.7.237
+4000.example. 5M IN A 10.0.7.238
+4000.example. 5M IN A 10.0.7.239
+4000.example. 5M IN A 10.0.7.240
+4000.example. 5M IN A 10.0.7.241
+4000.example. 5M IN A 10.0.7.242
+4000.example. 5M IN A 10.0.7.243
+4000.example. 5M IN A 10.0.7.244
+4000.example. 5M IN A 10.0.7.245
+4000.example. 5M IN A 10.0.7.246
+4000.example. 5M IN A 10.0.7.247
+4000.example. 5M IN A 10.0.7.248
+4000.example. 5M IN A 10.0.7.249
+4000.example. 5M IN A 10.0.7.250
+4000.example. 5M IN A 10.0.7.251
+4000.example. 5M IN A 10.0.7.252
+4000.example. 5M IN A 10.0.7.253
+4000.example. 5M IN A 10.0.7.254
+4000.example. 5M IN A 10.0.7.255
+4000.example. 5M IN A 10.0.8.0
+4000.example. 5M IN A 10.0.8.1
+4000.example. 5M IN A 10.0.8.2
+4000.example. 5M IN A 10.0.8.3
+4000.example. 5M IN A 10.0.8.4
+4000.example. 5M IN A 10.0.8.5
+4000.example. 5M IN A 10.0.8.6
+4000.example. 5M IN A 10.0.8.7
+4000.example. 5M IN A 10.0.8.8
+4000.example. 5M IN A 10.0.8.9
+4000.example. 5M IN A 10.0.8.10
+4000.example. 5M IN A 10.0.8.11
+4000.example. 5M IN A 10.0.8.12
+4000.example. 5M IN A 10.0.8.13
+4000.example. 5M IN A 10.0.8.14
+4000.example. 5M IN A 10.0.8.15
+4000.example. 5M IN A 10.0.8.16
+4000.example. 5M IN A 10.0.8.17
+4000.example. 5M IN A 10.0.8.18
+4000.example. 5M IN A 10.0.8.19
+4000.example. 5M IN A 10.0.8.20
+4000.example. 5M IN A 10.0.8.21
+4000.example. 5M IN A 10.0.8.22
+4000.example. 5M IN A 10.0.8.23
+4000.example. 5M IN A 10.0.8.24
+4000.example. 5M IN A 10.0.8.25
+4000.example. 5M IN A 10.0.8.26
+4000.example. 5M IN A 10.0.8.27
+4000.example. 5M IN A 10.0.8.28
+4000.example. 5M IN A 10.0.8.29
+4000.example. 5M IN A 10.0.8.30
+4000.example. 5M IN A 10.0.8.31
+4000.example. 5M IN A 10.0.8.32
+4000.example. 5M IN A 10.0.8.33
+4000.example. 5M IN A 10.0.8.34
+4000.example. 5M IN A 10.0.8.35
+4000.example. 5M IN A 10.0.8.36
+4000.example. 5M IN A 10.0.8.37
+4000.example. 5M IN A 10.0.8.38
+4000.example. 5M IN A 10.0.8.39
+4000.example. 5M IN A 10.0.8.40
+4000.example. 5M IN A 10.0.8.41
+4000.example. 5M IN A 10.0.8.42
+4000.example. 5M IN A 10.0.8.43
+4000.example. 5M IN A 10.0.8.44
+4000.example. 5M IN A 10.0.8.45
+4000.example. 5M IN A 10.0.8.46
+4000.example. 5M IN A 10.0.8.47
+4000.example. 5M IN A 10.0.8.48
+4000.example. 5M IN A 10.0.8.49
+4000.example. 5M IN A 10.0.8.50
+4000.example. 5M IN A 10.0.8.51
+4000.example. 5M IN A 10.0.8.52
+4000.example. 5M IN A 10.0.8.53
+4000.example. 5M IN A 10.0.8.54
+4000.example. 5M IN A 10.0.8.55
+4000.example. 5M IN A 10.0.8.56
+4000.example. 5M IN A 10.0.8.57
+4000.example. 5M IN A 10.0.8.58
+4000.example. 5M IN A 10.0.8.59
+4000.example. 5M IN A 10.0.8.60
+4000.example. 5M IN A 10.0.8.61
+4000.example. 5M IN A 10.0.8.62
+4000.example. 5M IN A 10.0.8.63
+4000.example. 5M IN A 10.0.8.64
+4000.example. 5M IN A 10.0.8.65
+4000.example. 5M IN A 10.0.8.66
+4000.example. 5M IN A 10.0.8.67
+4000.example. 5M IN A 10.0.8.68
+4000.example. 5M IN A 10.0.8.69
+4000.example. 5M IN A 10.0.8.70
+4000.example. 5M IN A 10.0.8.71
+4000.example. 5M IN A 10.0.8.72
+4000.example. 5M IN A 10.0.8.73
+4000.example. 5M IN A 10.0.8.74
+4000.example. 5M IN A 10.0.8.75
+4000.example. 5M IN A 10.0.8.76
+4000.example. 5M IN A 10.0.8.77
+4000.example. 5M IN A 10.0.8.78
+4000.example. 5M IN A 10.0.8.79
+4000.example. 5M IN A 10.0.8.80
+4000.example. 5M IN A 10.0.8.81
+4000.example. 5M IN A 10.0.8.82
+4000.example. 5M IN A 10.0.8.83
+4000.example. 5M IN A 10.0.8.84
+4000.example. 5M IN A 10.0.8.85
+4000.example. 5M IN A 10.0.8.86
+4000.example. 5M IN A 10.0.8.87
+4000.example. 5M IN A 10.0.8.88
+4000.example. 5M IN A 10.0.8.89
+4000.example. 5M IN A 10.0.8.90
+4000.example. 5M IN A 10.0.8.91
+4000.example. 5M IN A 10.0.8.92
+4000.example. 5M IN A 10.0.8.93
+4000.example. 5M IN A 10.0.8.94
+4000.example. 5M IN A 10.0.8.95
+4000.example. 5M IN A 10.0.8.96
+4000.example. 5M IN A 10.0.8.97
+4000.example. 5M IN A 10.0.8.98
+4000.example. 5M IN A 10.0.8.99
+4000.example. 5M IN A 10.0.8.100
+4000.example. 5M IN A 10.0.8.101
+4000.example. 5M IN A 10.0.8.102
+4000.example. 5M IN A 10.0.8.103
+4000.example. 5M IN A 10.0.8.104
+4000.example. 5M IN A 10.0.8.105
+4000.example. 5M IN A 10.0.8.106
+4000.example. 5M IN A 10.0.8.107
+4000.example. 5M IN A 10.0.8.108
+4000.example. 5M IN A 10.0.8.109
+4000.example. 5M IN A 10.0.8.110
+4000.example. 5M IN A 10.0.8.111
+4000.example. 5M IN A 10.0.8.112
+4000.example. 5M IN A 10.0.8.113
+4000.example. 5M IN A 10.0.8.114
+4000.example. 5M IN A 10.0.8.115
+4000.example. 5M IN A 10.0.8.116
+4000.example. 5M IN A 10.0.8.117
+4000.example. 5M IN A 10.0.8.118
+4000.example. 5M IN A 10.0.8.119
+4000.example. 5M IN A 10.0.8.120
+4000.example. 5M IN A 10.0.8.121
+4000.example. 5M IN A 10.0.8.122
+4000.example. 5M IN A 10.0.8.123
+4000.example. 5M IN A 10.0.8.124
+4000.example. 5M IN A 10.0.8.125
+4000.example. 5M IN A 10.0.8.126
+4000.example. 5M IN A 10.0.8.127
+4000.example. 5M IN A 10.0.8.128
+4000.example. 5M IN A 10.0.8.129
+4000.example. 5M IN A 10.0.8.130
+4000.example. 5M IN A 10.0.8.131
+4000.example. 5M IN A 10.0.8.132
+4000.example. 5M IN A 10.0.8.133
+4000.example. 5M IN A 10.0.8.134
+4000.example. 5M IN A 10.0.8.135
+4000.example. 5M IN A 10.0.8.136
+4000.example. 5M IN A 10.0.8.137
+4000.example. 5M IN A 10.0.8.138
+4000.example. 5M IN A 10.0.8.139
+4000.example. 5M IN A 10.0.8.140
+4000.example. 5M IN A 10.0.8.141
+4000.example. 5M IN A 10.0.8.142
+4000.example. 5M IN A 10.0.8.143
+4000.example. 5M IN A 10.0.8.144
+4000.example. 5M IN A 10.0.8.145
+4000.example. 5M IN A 10.0.8.146
+4000.example. 5M IN A 10.0.8.147
+4000.example. 5M IN A 10.0.8.148
+4000.example. 5M IN A 10.0.8.149
+4000.example. 5M IN A 10.0.8.150
+4000.example. 5M IN A 10.0.8.151
+4000.example. 5M IN A 10.0.8.152
+4000.example. 5M IN A 10.0.8.153
+4000.example. 5M IN A 10.0.8.154
+4000.example. 5M IN A 10.0.8.155
+4000.example. 5M IN A 10.0.8.156
+4000.example. 5M IN A 10.0.8.157
+4000.example. 5M IN A 10.0.8.158
+4000.example. 5M IN A 10.0.8.159
+4000.example. 5M IN A 10.0.8.160
+4000.example. 5M IN A 10.0.8.161
+4000.example. 5M IN A 10.0.8.162
+4000.example. 5M IN A 10.0.8.163
+4000.example. 5M IN A 10.0.8.164
+4000.example. 5M IN A 10.0.8.165
+4000.example. 5M IN A 10.0.8.166
+4000.example. 5M IN A 10.0.8.167
+4000.example. 5M IN A 10.0.8.168
+4000.example. 5M IN A 10.0.8.169
+4000.example. 5M IN A 10.0.8.170
+4000.example. 5M IN A 10.0.8.171
+4000.example. 5M IN A 10.0.8.172
+4000.example. 5M IN A 10.0.8.173
+4000.example. 5M IN A 10.0.8.174
+4000.example. 5M IN A 10.0.8.175
+4000.example. 5M IN A 10.0.8.176
+4000.example. 5M IN A 10.0.8.177
+4000.example. 5M IN A 10.0.8.178
+4000.example. 5M IN A 10.0.8.179
+4000.example. 5M IN A 10.0.8.180
+4000.example. 5M IN A 10.0.8.181
+4000.example. 5M IN A 10.0.8.182
+4000.example. 5M IN A 10.0.8.183
+4000.example. 5M IN A 10.0.8.184
+4000.example. 5M IN A 10.0.8.185
+4000.example. 5M IN A 10.0.8.186
+4000.example. 5M IN A 10.0.8.187
+4000.example. 5M IN A 10.0.8.188
+4000.example. 5M IN A 10.0.8.189
+4000.example. 5M IN A 10.0.8.190
+4000.example. 5M IN A 10.0.8.191
+4000.example. 5M IN A 10.0.8.192
+4000.example. 5M IN A 10.0.8.193
+4000.example. 5M IN A 10.0.8.194
+4000.example. 5M IN A 10.0.8.195
+4000.example. 5M IN A 10.0.8.196
+4000.example. 5M IN A 10.0.8.197
+4000.example. 5M IN A 10.0.8.198
+4000.example. 5M IN A 10.0.8.199
+4000.example. 5M IN A 10.0.8.200
+4000.example. 5M IN A 10.0.8.201
+4000.example. 5M IN A 10.0.8.202
+4000.example. 5M IN A 10.0.8.203
+4000.example. 5M IN A 10.0.8.204
+4000.example. 5M IN A 10.0.8.205
+4000.example. 5M IN A 10.0.8.206
+4000.example. 5M IN A 10.0.8.207
+4000.example. 5M IN A 10.0.8.208
+4000.example. 5M IN A 10.0.8.209
+4000.example. 5M IN A 10.0.8.210
+4000.example. 5M IN A 10.0.8.211
+4000.example. 5M IN A 10.0.8.212
+4000.example. 5M IN A 10.0.8.213
+4000.example. 5M IN A 10.0.8.214
+4000.example. 5M IN A 10.0.8.215
+4000.example. 5M IN A 10.0.8.216
+4000.example. 5M IN A 10.0.8.217
+4000.example. 5M IN A 10.0.8.218
+4000.example. 5M IN A 10.0.8.219
+4000.example. 5M IN A 10.0.8.220
+4000.example. 5M IN A 10.0.8.221
+4000.example. 5M IN A 10.0.8.222
+4000.example. 5M IN A 10.0.8.223
+4000.example. 5M IN A 10.0.8.224
+4000.example. 5M IN A 10.0.8.225
+4000.example. 5M IN A 10.0.8.226
+4000.example. 5M IN A 10.0.8.227
+4000.example. 5M IN A 10.0.8.228
+4000.example. 5M IN A 10.0.8.229
+4000.example. 5M IN A 10.0.8.230
+4000.example. 5M IN A 10.0.8.231
+4000.example. 5M IN A 10.0.8.232
+4000.example. 5M IN A 10.0.8.233
+4000.example. 5M IN A 10.0.8.234
+4000.example. 5M IN A 10.0.8.235
+4000.example. 5M IN A 10.0.8.236
+4000.example. 5M IN A 10.0.8.237
+4000.example. 5M IN A 10.0.8.238
+4000.example. 5M IN A 10.0.8.239
+4000.example. 5M IN A 10.0.8.240
+4000.example. 5M IN A 10.0.8.241
+4000.example. 5M IN A 10.0.8.242
+4000.example. 5M IN A 10.0.8.243
+4000.example. 5M IN A 10.0.8.244
+4000.example. 5M IN A 10.0.8.245
+4000.example. 5M IN A 10.0.8.246
+4000.example. 5M IN A 10.0.8.247
+4000.example. 5M IN A 10.0.8.248
+4000.example. 5M IN A 10.0.8.249
+4000.example. 5M IN A 10.0.8.250
+4000.example. 5M IN A 10.0.8.251
+4000.example. 5M IN A 10.0.8.252
+4000.example. 5M IN A 10.0.8.253
+4000.example. 5M IN A 10.0.8.254
+4000.example. 5M IN A 10.0.8.255
+4000.example. 5M IN A 10.0.9.0
+4000.example. 5M IN A 10.0.9.1
+4000.example. 5M IN A 10.0.9.2
+4000.example. 5M IN A 10.0.9.3
+4000.example. 5M IN A 10.0.9.4
+4000.example. 5M IN A 10.0.9.5
+4000.example. 5M IN A 10.0.9.6
+4000.example. 5M IN A 10.0.9.7
+4000.example. 5M IN A 10.0.9.8
+4000.example. 5M IN A 10.0.9.9
+4000.example. 5M IN A 10.0.9.10
+4000.example. 5M IN A 10.0.9.11
+4000.example. 5M IN A 10.0.9.12
+4000.example. 5M IN A 10.0.9.13
+4000.example. 5M IN A 10.0.9.14
+4000.example. 5M IN A 10.0.9.15
+4000.example. 5M IN A 10.0.9.16
+4000.example. 5M IN A 10.0.9.17
+4000.example. 5M IN A 10.0.9.18
+4000.example. 5M IN A 10.0.9.19
+4000.example. 5M IN A 10.0.9.20
+4000.example. 5M IN A 10.0.9.21
+4000.example. 5M IN A 10.0.9.22
+4000.example. 5M IN A 10.0.9.23
+4000.example. 5M IN A 10.0.9.24
+4000.example. 5M IN A 10.0.9.25
+4000.example. 5M IN A 10.0.9.26
+4000.example. 5M IN A 10.0.9.27
+4000.example. 5M IN A 10.0.9.28
+4000.example. 5M IN A 10.0.9.29
+4000.example. 5M IN A 10.0.9.30
+4000.example. 5M IN A 10.0.9.31
+4000.example. 5M IN A 10.0.9.32
+4000.example. 5M IN A 10.0.9.33
+4000.example. 5M IN A 10.0.9.34
+4000.example. 5M IN A 10.0.9.35
+4000.example. 5M IN A 10.0.9.36
+4000.example. 5M IN A 10.0.9.37
+4000.example. 5M IN A 10.0.9.38
+4000.example. 5M IN A 10.0.9.39
+4000.example. 5M IN A 10.0.9.40
+4000.example. 5M IN A 10.0.9.41
+4000.example. 5M IN A 10.0.9.42
+4000.example. 5M IN A 10.0.9.43
+4000.example. 5M IN A 10.0.9.44
+4000.example. 5M IN A 10.0.9.45
+4000.example. 5M IN A 10.0.9.46
+4000.example. 5M IN A 10.0.9.47
+4000.example. 5M IN A 10.0.9.48
+4000.example. 5M IN A 10.0.9.49
+4000.example. 5M IN A 10.0.9.50
+4000.example. 5M IN A 10.0.9.51
+4000.example. 5M IN A 10.0.9.52
+4000.example. 5M IN A 10.0.9.53
+4000.example. 5M IN A 10.0.9.54
+4000.example. 5M IN A 10.0.9.55
+4000.example. 5M IN A 10.0.9.56
+4000.example. 5M IN A 10.0.9.57
+4000.example. 5M IN A 10.0.9.58
+4000.example. 5M IN A 10.0.9.59
+4000.example. 5M IN A 10.0.9.60
+4000.example. 5M IN A 10.0.9.61
+4000.example. 5M IN A 10.0.9.62
+4000.example. 5M IN A 10.0.9.63
+4000.example. 5M IN A 10.0.9.64
+4000.example. 5M IN A 10.0.9.65
+4000.example. 5M IN A 10.0.9.66
+4000.example. 5M IN A 10.0.9.67
+4000.example. 5M IN A 10.0.9.68
+4000.example. 5M IN A 10.0.9.69
+4000.example. 5M IN A 10.0.9.70
+4000.example. 5M IN A 10.0.9.71
+4000.example. 5M IN A 10.0.9.72
+4000.example. 5M IN A 10.0.9.73
+4000.example. 5M IN A 10.0.9.74
+4000.example. 5M IN A 10.0.9.75
+4000.example. 5M IN A 10.0.9.76
+4000.example. 5M IN A 10.0.9.77
+4000.example. 5M IN A 10.0.9.78
+4000.example. 5M IN A 10.0.9.79
+4000.example. 5M IN A 10.0.9.80
+4000.example. 5M IN A 10.0.9.81
+4000.example. 5M IN A 10.0.9.82
+4000.example. 5M IN A 10.0.9.83
+4000.example. 5M IN A 10.0.9.84
+4000.example. 5M IN A 10.0.9.85
+4000.example. 5M IN A 10.0.9.86
+4000.example. 5M IN A 10.0.9.87
+4000.example. 5M IN A 10.0.9.88
+4000.example. 5M IN A 10.0.9.89
+4000.example. 5M IN A 10.0.9.90
+4000.example. 5M IN A 10.0.9.91
+4000.example. 5M IN A 10.0.9.92
+4000.example. 5M IN A 10.0.9.93
+4000.example. 5M IN A 10.0.9.94
+4000.example. 5M IN A 10.0.9.95
+4000.example. 5M IN A 10.0.9.96
+4000.example. 5M IN A 10.0.9.97
+4000.example. 5M IN A 10.0.9.98
+4000.example. 5M IN A 10.0.9.99
+4000.example. 5M IN A 10.0.9.100
+4000.example. 5M IN A 10.0.9.101
+4000.example. 5M IN A 10.0.9.102
+4000.example. 5M IN A 10.0.9.103
+4000.example. 5M IN A 10.0.9.104
+4000.example. 5M IN A 10.0.9.105
+4000.example. 5M IN A 10.0.9.106
+4000.example. 5M IN A 10.0.9.107
+4000.example. 5M IN A 10.0.9.108
+4000.example. 5M IN A 10.0.9.109
+4000.example. 5M IN A 10.0.9.110
+4000.example. 5M IN A 10.0.9.111
+4000.example. 5M IN A 10.0.9.112
+4000.example. 5M IN A 10.0.9.113
+4000.example. 5M IN A 10.0.9.114
+4000.example. 5M IN A 10.0.9.115
+4000.example. 5M IN A 10.0.9.116
+4000.example. 5M IN A 10.0.9.117
+4000.example. 5M IN A 10.0.9.118
+4000.example. 5M IN A 10.0.9.119
+4000.example. 5M IN A 10.0.9.120
+4000.example. 5M IN A 10.0.9.121
+4000.example. 5M IN A 10.0.9.122
+4000.example. 5M IN A 10.0.9.123
+4000.example. 5M IN A 10.0.9.124
+4000.example. 5M IN A 10.0.9.125
+4000.example. 5M IN A 10.0.9.126
+4000.example. 5M IN A 10.0.9.127
+4000.example. 5M IN A 10.0.9.128
+4000.example. 5M IN A 10.0.9.129
+4000.example. 5M IN A 10.0.9.130
+4000.example. 5M IN A 10.0.9.131
+4000.example. 5M IN A 10.0.9.132
+4000.example. 5M IN A 10.0.9.133
+4000.example. 5M IN A 10.0.9.134
+4000.example. 5M IN A 10.0.9.135
+4000.example. 5M IN A 10.0.9.136
+4000.example. 5M IN A 10.0.9.137
+4000.example. 5M IN A 10.0.9.138
+4000.example. 5M IN A 10.0.9.139
+4000.example. 5M IN A 10.0.9.140
+4000.example. 5M IN A 10.0.9.141
+4000.example. 5M IN A 10.0.9.142
+4000.example. 5M IN A 10.0.9.143
+4000.example. 5M IN A 10.0.9.144
+4000.example. 5M IN A 10.0.9.145
+4000.example. 5M IN A 10.0.9.146
+4000.example. 5M IN A 10.0.9.147
+4000.example. 5M IN A 10.0.9.148
+4000.example. 5M IN A 10.0.9.149
+4000.example. 5M IN A 10.0.9.150
+4000.example. 5M IN A 10.0.9.151
+4000.example. 5M IN A 10.0.9.152
+4000.example. 5M IN A 10.0.9.153
+4000.example. 5M IN A 10.0.9.154
+4000.example. 5M IN A 10.0.9.155
+4000.example. 5M IN A 10.0.9.156
+4000.example. 5M IN A 10.0.9.157
+4000.example. 5M IN A 10.0.9.158
+4000.example. 5M IN A 10.0.9.159
+4000.example. 5M IN A 10.0.9.160
+4000.example. 5M IN A 10.0.9.161
+4000.example. 5M IN A 10.0.9.162
+4000.example. 5M IN A 10.0.9.163
+4000.example. 5M IN A 10.0.9.164
+4000.example. 5M IN A 10.0.9.165
+4000.example. 5M IN A 10.0.9.166
+4000.example. 5M IN A 10.0.9.167
+4000.example. 5M IN A 10.0.9.168
+4000.example. 5M IN A 10.0.9.169
+4000.example. 5M IN A 10.0.9.170
+4000.example. 5M IN A 10.0.9.171
+4000.example. 5M IN A 10.0.9.172
+4000.example. 5M IN A 10.0.9.173
+4000.example. 5M IN A 10.0.9.174
+4000.example. 5M IN A 10.0.9.175
+4000.example. 5M IN A 10.0.9.176
+4000.example. 5M IN A 10.0.9.177
+4000.example. 5M IN A 10.0.9.178
+4000.example. 5M IN A 10.0.9.179
+4000.example. 5M IN A 10.0.9.180
+4000.example. 5M IN A 10.0.9.181
+4000.example. 5M IN A 10.0.9.182
+4000.example. 5M IN A 10.0.9.183
+4000.example. 5M IN A 10.0.9.184
+4000.example. 5M IN A 10.0.9.185
+4000.example. 5M IN A 10.0.9.186
+4000.example. 5M IN A 10.0.9.187
+4000.example. 5M IN A 10.0.9.188
+4000.example. 5M IN A 10.0.9.189
+4000.example. 5M IN A 10.0.9.190
+4000.example. 5M IN A 10.0.9.191
+4000.example. 5M IN A 10.0.9.192
+4000.example. 5M IN A 10.0.9.193
+4000.example. 5M IN A 10.0.9.194
+4000.example. 5M IN A 10.0.9.195
+4000.example. 5M IN A 10.0.9.196
+4000.example. 5M IN A 10.0.9.197
+4000.example. 5M IN A 10.0.9.198
+4000.example. 5M IN A 10.0.9.199
+4000.example. 5M IN A 10.0.9.200
+4000.example. 5M IN A 10.0.9.201
+4000.example. 5M IN A 10.0.9.202
+4000.example. 5M IN A 10.0.9.203
+4000.example. 5M IN A 10.0.9.204
+4000.example. 5M IN A 10.0.9.205
+4000.example. 5M IN A 10.0.9.206
+4000.example. 5M IN A 10.0.9.207
+4000.example. 5M IN A 10.0.9.208
+4000.example. 5M IN A 10.0.9.209
+4000.example. 5M IN A 10.0.9.210
+4000.example. 5M IN A 10.0.9.211
+4000.example. 5M IN A 10.0.9.212
+4000.example. 5M IN A 10.0.9.213
+4000.example. 5M IN A 10.0.9.214
+4000.example. 5M IN A 10.0.9.215
+4000.example. 5M IN A 10.0.9.216
+4000.example. 5M IN A 10.0.9.217
+4000.example. 5M IN A 10.0.9.218
+4000.example. 5M IN A 10.0.9.219
+4000.example. 5M IN A 10.0.9.220
+4000.example. 5M IN A 10.0.9.221
+4000.example. 5M IN A 10.0.9.222
+4000.example. 5M IN A 10.0.9.223
+4000.example. 5M IN A 10.0.9.224
+4000.example. 5M IN A 10.0.9.225
+4000.example. 5M IN A 10.0.9.226
+4000.example. 5M IN A 10.0.9.227
+4000.example. 5M IN A 10.0.9.228
+4000.example. 5M IN A 10.0.9.229
+4000.example. 5M IN A 10.0.9.230
+4000.example. 5M IN A 10.0.9.231
+4000.example. 5M IN A 10.0.9.232
+4000.example. 5M IN A 10.0.9.233
+4000.example. 5M IN A 10.0.9.234
+4000.example. 5M IN A 10.0.9.235
+4000.example. 5M IN A 10.0.9.236
+4000.example. 5M IN A 10.0.9.237
+4000.example. 5M IN A 10.0.9.238
+4000.example. 5M IN A 10.0.9.239
+4000.example. 5M IN A 10.0.9.240
+4000.example. 5M IN A 10.0.9.241
+4000.example. 5M IN A 10.0.9.242
+4000.example. 5M IN A 10.0.9.243
+4000.example. 5M IN A 10.0.9.244
+4000.example. 5M IN A 10.0.9.245
+4000.example. 5M IN A 10.0.9.246
+4000.example. 5M IN A 10.0.9.247
+4000.example. 5M IN A 10.0.9.248
+4000.example. 5M IN A 10.0.9.249
+4000.example. 5M IN A 10.0.9.250
+4000.example. 5M IN A 10.0.9.251
+4000.example. 5M IN A 10.0.9.252
+4000.example. 5M IN A 10.0.9.253
+4000.example. 5M IN A 10.0.9.254
+4000.example. 5M IN A 10.0.9.255
+4000.example. 5M IN A 10.0.10.0
+4000.example. 5M IN A 10.0.10.1
+4000.example. 5M IN A 10.0.10.2
+4000.example. 5M IN A 10.0.10.3
+4000.example. 5M IN A 10.0.10.4
+4000.example. 5M IN A 10.0.10.5
+4000.example. 5M IN A 10.0.10.6
+4000.example. 5M IN A 10.0.10.7
+4000.example. 5M IN A 10.0.10.8
+4000.example. 5M IN A 10.0.10.9
+4000.example. 5M IN A 10.0.10.10
+4000.example. 5M IN A 10.0.10.11
+4000.example. 5M IN A 10.0.10.12
+4000.example. 5M IN A 10.0.10.13
+4000.example. 5M IN A 10.0.10.14
+4000.example. 5M IN A 10.0.10.15
+4000.example. 5M IN A 10.0.10.16
+4000.example. 5M IN A 10.0.10.17
+4000.example. 5M IN A 10.0.10.18
+4000.example. 5M IN A 10.0.10.19
+4000.example. 5M IN A 10.0.10.20
+4000.example. 5M IN A 10.0.10.21
+4000.example. 5M IN A 10.0.10.22
+4000.example. 5M IN A 10.0.10.23
+4000.example. 5M IN A 10.0.10.24
+4000.example. 5M IN A 10.0.10.25
+4000.example. 5M IN A 10.0.10.26
+4000.example. 5M IN A 10.0.10.27
+4000.example. 5M IN A 10.0.10.28
+4000.example. 5M IN A 10.0.10.29
+4000.example. 5M IN A 10.0.10.30
+4000.example. 5M IN A 10.0.10.31
+4000.example. 5M IN A 10.0.10.32
+4000.example. 5M IN A 10.0.10.33
+4000.example. 5M IN A 10.0.10.34
+4000.example. 5M IN A 10.0.10.35
+4000.example. 5M IN A 10.0.10.36
+4000.example. 5M IN A 10.0.10.37
+4000.example. 5M IN A 10.0.10.38
+4000.example. 5M IN A 10.0.10.39
+4000.example. 5M IN A 10.0.10.40
+4000.example. 5M IN A 10.0.10.41
+4000.example. 5M IN A 10.0.10.42
+4000.example. 5M IN A 10.0.10.43
+4000.example. 5M IN A 10.0.10.44
+4000.example. 5M IN A 10.0.10.45
+4000.example. 5M IN A 10.0.10.46
+4000.example. 5M IN A 10.0.10.47
+4000.example. 5M IN A 10.0.10.48
+4000.example. 5M IN A 10.0.10.49
+4000.example. 5M IN A 10.0.10.50
+4000.example. 5M IN A 10.0.10.51
+4000.example. 5M IN A 10.0.10.52
+4000.example. 5M IN A 10.0.10.53
+4000.example. 5M IN A 10.0.10.54
+4000.example. 5M IN A 10.0.10.55
+4000.example. 5M IN A 10.0.10.56
+4000.example. 5M IN A 10.0.10.57
+4000.example. 5M IN A 10.0.10.58
+4000.example. 5M IN A 10.0.10.59
+4000.example. 5M IN A 10.0.10.60
+4000.example. 5M IN A 10.0.10.61
+4000.example. 5M IN A 10.0.10.62
+4000.example. 5M IN A 10.0.10.63
+4000.example. 5M IN A 10.0.10.64
+4000.example. 5M IN A 10.0.10.65
+4000.example. 5M IN A 10.0.10.66
+4000.example. 5M IN A 10.0.10.67
+4000.example. 5M IN A 10.0.10.68
+4000.example. 5M IN A 10.0.10.69
+4000.example. 5M IN A 10.0.10.70
+4000.example. 5M IN A 10.0.10.71
+4000.example. 5M IN A 10.0.10.72
+4000.example. 5M IN A 10.0.10.73
+4000.example. 5M IN A 10.0.10.74
+4000.example. 5M IN A 10.0.10.75
+4000.example. 5M IN A 10.0.10.76
+4000.example. 5M IN A 10.0.10.77
+4000.example. 5M IN A 10.0.10.78
+4000.example. 5M IN A 10.0.10.79
+4000.example. 5M IN A 10.0.10.80
+4000.example. 5M IN A 10.0.10.81
+4000.example. 5M IN A 10.0.10.82
+4000.example. 5M IN A 10.0.10.83
+4000.example. 5M IN A 10.0.10.84
+4000.example. 5M IN A 10.0.10.85
+4000.example. 5M IN A 10.0.10.86
+4000.example. 5M IN A 10.0.10.87
+4000.example. 5M IN A 10.0.10.88
+4000.example. 5M IN A 10.0.10.89
+4000.example. 5M IN A 10.0.10.90
+4000.example. 5M IN A 10.0.10.91
+4000.example. 5M IN A 10.0.10.92
+4000.example. 5M IN A 10.0.10.93
+4000.example. 5M IN A 10.0.10.94
+4000.example. 5M IN A 10.0.10.95
+4000.example. 5M IN A 10.0.10.96
+4000.example. 5M IN A 10.0.10.97
+4000.example. 5M IN A 10.0.10.98
+4000.example. 5M IN A 10.0.10.99
+4000.example. 5M IN A 10.0.10.100
+4000.example. 5M IN A 10.0.10.101
+4000.example. 5M IN A 10.0.10.102
+4000.example. 5M IN A 10.0.10.103
+4000.example. 5M IN A 10.0.10.104
+4000.example. 5M IN A 10.0.10.105
+4000.example. 5M IN A 10.0.10.106
+4000.example. 5M IN A 10.0.10.107
+4000.example. 5M IN A 10.0.10.108
+4000.example. 5M IN A 10.0.10.109
+4000.example. 5M IN A 10.0.10.110
+4000.example. 5M IN A 10.0.10.111
+4000.example. 5M IN A 10.0.10.112
+4000.example. 5M IN A 10.0.10.113
+4000.example. 5M IN A 10.0.10.114
+4000.example. 5M IN A 10.0.10.115
+4000.example. 5M IN A 10.0.10.116
+4000.example. 5M IN A 10.0.10.117
+4000.example. 5M IN A 10.0.10.118
+4000.example. 5M IN A 10.0.10.119
+4000.example. 5M IN A 10.0.10.120
+4000.example. 5M IN A 10.0.10.121
+4000.example. 5M IN A 10.0.10.122
+4000.example. 5M IN A 10.0.10.123
+4000.example. 5M IN A 10.0.10.124
+4000.example. 5M IN A 10.0.10.125
+4000.example. 5M IN A 10.0.10.126
+4000.example. 5M IN A 10.0.10.127
+4000.example. 5M IN A 10.0.10.128
+4000.example. 5M IN A 10.0.10.129
+4000.example. 5M IN A 10.0.10.130
+4000.example. 5M IN A 10.0.10.131
+4000.example. 5M IN A 10.0.10.132
+4000.example. 5M IN A 10.0.10.133
+4000.example. 5M IN A 10.0.10.134
+4000.example. 5M IN A 10.0.10.135
+4000.example. 5M IN A 10.0.10.136
+4000.example. 5M IN A 10.0.10.137
+4000.example. 5M IN A 10.0.10.138
+4000.example. 5M IN A 10.0.10.139
+4000.example. 5M IN A 10.0.10.140
+4000.example. 5M IN A 10.0.10.141
+4000.example. 5M IN A 10.0.10.142
+4000.example. 5M IN A 10.0.10.143
+4000.example. 5M IN A 10.0.10.144
+4000.example. 5M IN A 10.0.10.145
+4000.example. 5M IN A 10.0.10.146
+4000.example. 5M IN A 10.0.10.147
+4000.example. 5M IN A 10.0.10.148
+4000.example. 5M IN A 10.0.10.149
+4000.example. 5M IN A 10.0.10.150
+4000.example. 5M IN A 10.0.10.151
+4000.example. 5M IN A 10.0.10.152
+4000.example. 5M IN A 10.0.10.153
+4000.example. 5M IN A 10.0.10.154
+4000.example. 5M IN A 10.0.10.155
+4000.example. 5M IN A 10.0.10.156
+4000.example. 5M IN A 10.0.10.157
+4000.example. 5M IN A 10.0.10.158
+4000.example. 5M IN A 10.0.10.159
+4000.example. 5M IN A 10.0.10.160
+4000.example. 5M IN A 10.0.10.161
+4000.example. 5M IN A 10.0.10.162
+4000.example. 5M IN A 10.0.10.163
+4000.example. 5M IN A 10.0.10.164
+4000.example. 5M IN A 10.0.10.165
+4000.example. 5M IN A 10.0.10.166
+4000.example. 5M IN A 10.0.10.167
+4000.example. 5M IN A 10.0.10.168
+4000.example. 5M IN A 10.0.10.169
+4000.example. 5M IN A 10.0.10.170
+4000.example. 5M IN A 10.0.10.171
+4000.example. 5M IN A 10.0.10.172
+4000.example. 5M IN A 10.0.10.173
+4000.example. 5M IN A 10.0.10.174
+4000.example. 5M IN A 10.0.10.175
+4000.example. 5M IN A 10.0.10.176
+4000.example. 5M IN A 10.0.10.177
+4000.example. 5M IN A 10.0.10.178
+4000.example. 5M IN A 10.0.10.179
+4000.example. 5M IN A 10.0.10.180
+4000.example. 5M IN A 10.0.10.181
+4000.example. 5M IN A 10.0.10.182
+4000.example. 5M IN A 10.0.10.183
+4000.example. 5M IN A 10.0.10.184
+4000.example. 5M IN A 10.0.10.185
+4000.example. 5M IN A 10.0.10.186
+4000.example. 5M IN A 10.0.10.187
+4000.example. 5M IN A 10.0.10.188
+4000.example. 5M IN A 10.0.10.189
+4000.example. 5M IN A 10.0.10.190
+4000.example. 5M IN A 10.0.10.191
+4000.example. 5M IN A 10.0.10.192
+4000.example. 5M IN A 10.0.10.193
+4000.example. 5M IN A 10.0.10.194
+4000.example. 5M IN A 10.0.10.195
+4000.example. 5M IN A 10.0.10.196
+4000.example. 5M IN A 10.0.10.197
+4000.example. 5M IN A 10.0.10.198
+4000.example. 5M IN A 10.0.10.199
+4000.example. 5M IN A 10.0.10.200
+4000.example. 5M IN A 10.0.10.201
+4000.example. 5M IN A 10.0.10.202
+4000.example. 5M IN A 10.0.10.203
+4000.example. 5M IN A 10.0.10.204
+4000.example. 5M IN A 10.0.10.205
+4000.example. 5M IN A 10.0.10.206
+4000.example. 5M IN A 10.0.10.207
+4000.example. 5M IN A 10.0.10.208
+4000.example. 5M IN A 10.0.10.209
+4000.example. 5M IN A 10.0.10.210
+4000.example. 5M IN A 10.0.10.211
+4000.example. 5M IN A 10.0.10.212
+4000.example. 5M IN A 10.0.10.213
+4000.example. 5M IN A 10.0.10.214
+4000.example. 5M IN A 10.0.10.215
+4000.example. 5M IN A 10.0.10.216
+4000.example. 5M IN A 10.0.10.217
+4000.example. 5M IN A 10.0.10.218
+4000.example. 5M IN A 10.0.10.219
+4000.example. 5M IN A 10.0.10.220
+4000.example. 5M IN A 10.0.10.221
+4000.example. 5M IN A 10.0.10.222
+4000.example. 5M IN A 10.0.10.223
+4000.example. 5M IN A 10.0.10.224
+4000.example. 5M IN A 10.0.10.225
+4000.example. 5M IN A 10.0.10.226
+4000.example. 5M IN A 10.0.10.227
+4000.example. 5M IN A 10.0.10.228
+4000.example. 5M IN A 10.0.10.229
+4000.example. 5M IN A 10.0.10.230
+4000.example. 5M IN A 10.0.10.231
+4000.example. 5M IN A 10.0.10.232
+4000.example. 5M IN A 10.0.10.233
+4000.example. 5M IN A 10.0.10.234
+4000.example. 5M IN A 10.0.10.235
+4000.example. 5M IN A 10.0.10.236
+4000.example. 5M IN A 10.0.10.237
+4000.example. 5M IN A 10.0.10.238
+4000.example. 5M IN A 10.0.10.239
+4000.example. 5M IN A 10.0.10.240
+4000.example. 5M IN A 10.0.10.241
+4000.example. 5M IN A 10.0.10.242
+4000.example. 5M IN A 10.0.10.243
+4000.example. 5M IN A 10.0.10.244
+4000.example. 5M IN A 10.0.10.245
+4000.example. 5M IN A 10.0.10.246
+4000.example. 5M IN A 10.0.10.247
+4000.example. 5M IN A 10.0.10.248
+4000.example. 5M IN A 10.0.10.249
+4000.example. 5M IN A 10.0.10.250
+4000.example. 5M IN A 10.0.10.251
+4000.example. 5M IN A 10.0.10.252
+4000.example. 5M IN A 10.0.10.253
+4000.example. 5M IN A 10.0.10.254
+4000.example. 5M IN A 10.0.10.255
+4000.example. 5M IN A 10.0.11.0
+4000.example. 5M IN A 10.0.11.1
+4000.example. 5M IN A 10.0.11.2
+4000.example. 5M IN A 10.0.11.3
+4000.example. 5M IN A 10.0.11.4
+4000.example. 5M IN A 10.0.11.5
+4000.example. 5M IN A 10.0.11.6
+4000.example. 5M IN A 10.0.11.7
+4000.example. 5M IN A 10.0.11.8
+4000.example. 5M IN A 10.0.11.9
+4000.example. 5M IN A 10.0.11.10
+4000.example. 5M IN A 10.0.11.11
+4000.example. 5M IN A 10.0.11.12
+4000.example. 5M IN A 10.0.11.13
+4000.example. 5M IN A 10.0.11.14
+4000.example. 5M IN A 10.0.11.15
+4000.example. 5M IN A 10.0.11.16
+4000.example. 5M IN A 10.0.11.17
+4000.example. 5M IN A 10.0.11.18
+4000.example. 5M IN A 10.0.11.19
+4000.example. 5M IN A 10.0.11.20
+4000.example. 5M IN A 10.0.11.21
+4000.example. 5M IN A 10.0.11.22
+4000.example. 5M IN A 10.0.11.23
+4000.example. 5M IN A 10.0.11.24
+4000.example. 5M IN A 10.0.11.25
+4000.example. 5M IN A 10.0.11.26
+4000.example. 5M IN A 10.0.11.27
+4000.example. 5M IN A 10.0.11.28
+4000.example. 5M IN A 10.0.11.29
+4000.example. 5M IN A 10.0.11.30
+4000.example. 5M IN A 10.0.11.31
+4000.example. 5M IN A 10.0.11.32
+4000.example. 5M IN A 10.0.11.33
+4000.example. 5M IN A 10.0.11.34
+4000.example. 5M IN A 10.0.11.35
+4000.example. 5M IN A 10.0.11.36
+4000.example. 5M IN A 10.0.11.37
+4000.example. 5M IN A 10.0.11.38
+4000.example. 5M IN A 10.0.11.39
+4000.example. 5M IN A 10.0.11.40
+4000.example. 5M IN A 10.0.11.41
+4000.example. 5M IN A 10.0.11.42
+4000.example. 5M IN A 10.0.11.43
+4000.example. 5M IN A 10.0.11.44
+4000.example. 5M IN A 10.0.11.45
+4000.example. 5M IN A 10.0.11.46
+4000.example. 5M IN A 10.0.11.47
+4000.example. 5M IN A 10.0.11.48
+4000.example. 5M IN A 10.0.11.49
+4000.example. 5M IN A 10.0.11.50
+4000.example. 5M IN A 10.0.11.51
+4000.example. 5M IN A 10.0.11.52
+4000.example. 5M IN A 10.0.11.53
+4000.example. 5M IN A 10.0.11.54
+4000.example. 5M IN A 10.0.11.55
+4000.example. 5M IN A 10.0.11.56
+4000.example. 5M IN A 10.0.11.57
+4000.example. 5M IN A 10.0.11.58
+4000.example. 5M IN A 10.0.11.59
+4000.example. 5M IN A 10.0.11.60
+4000.example. 5M IN A 10.0.11.61
+4000.example. 5M IN A 10.0.11.62
+4000.example. 5M IN A 10.0.11.63
+4000.example. 5M IN A 10.0.11.64
+4000.example. 5M IN A 10.0.11.65
+4000.example. 5M IN A 10.0.11.66
+4000.example. 5M IN A 10.0.11.67
+4000.example. 5M IN A 10.0.11.68
+4000.example. 5M IN A 10.0.11.69
+4000.example. 5M IN A 10.0.11.70
+4000.example. 5M IN A 10.0.11.71
+4000.example. 5M IN A 10.0.11.72
+4000.example. 5M IN A 10.0.11.73
+4000.example. 5M IN A 10.0.11.74
+4000.example. 5M IN A 10.0.11.75
+4000.example. 5M IN A 10.0.11.76
+4000.example. 5M IN A 10.0.11.77
+4000.example. 5M IN A 10.0.11.78
+4000.example. 5M IN A 10.0.11.79
+4000.example. 5M IN A 10.0.11.80
+4000.example. 5M IN A 10.0.11.81
+4000.example. 5M IN A 10.0.11.82
+4000.example. 5M IN A 10.0.11.83
+4000.example. 5M IN A 10.0.11.84
+4000.example. 5M IN A 10.0.11.85
+4000.example. 5M IN A 10.0.11.86
+4000.example. 5M IN A 10.0.11.87
+4000.example. 5M IN A 10.0.11.88
+4000.example. 5M IN A 10.0.11.89
+4000.example. 5M IN A 10.0.11.90
+4000.example. 5M IN A 10.0.11.91
+4000.example. 5M IN A 10.0.11.92
+4000.example. 5M IN A 10.0.11.93
+4000.example. 5M IN A 10.0.11.94
+4000.example. 5M IN A 10.0.11.95
+4000.example. 5M IN A 10.0.11.96
+4000.example. 5M IN A 10.0.11.97
+4000.example. 5M IN A 10.0.11.98
+4000.example. 5M IN A 10.0.11.99
+4000.example. 5M IN A 10.0.11.100
+4000.example. 5M IN A 10.0.11.101
+4000.example. 5M IN A 10.0.11.102
+4000.example. 5M IN A 10.0.11.103
+4000.example. 5M IN A 10.0.11.104
+4000.example. 5M IN A 10.0.11.105
+4000.example. 5M IN A 10.0.11.106
+4000.example. 5M IN A 10.0.11.107
+4000.example. 5M IN A 10.0.11.108
+4000.example. 5M IN A 10.0.11.109
+4000.example. 5M IN A 10.0.11.110
+4000.example. 5M IN A 10.0.11.111
+4000.example. 5M IN A 10.0.11.112
+4000.example. 5M IN A 10.0.11.113
+4000.example. 5M IN A 10.0.11.114
+4000.example. 5M IN A 10.0.11.115
+4000.example. 5M IN A 10.0.11.116
+4000.example. 5M IN A 10.0.11.117
+4000.example. 5M IN A 10.0.11.118
+4000.example. 5M IN A 10.0.11.119
+4000.example. 5M IN A 10.0.11.120
+4000.example. 5M IN A 10.0.11.121
+4000.example. 5M IN A 10.0.11.122
+4000.example. 5M IN A 10.0.11.123
+4000.example. 5M IN A 10.0.11.124
+4000.example. 5M IN A 10.0.11.125
+4000.example. 5M IN A 10.0.11.126
+4000.example. 5M IN A 10.0.11.127
+4000.example. 5M IN A 10.0.11.128
+4000.example. 5M IN A 10.0.11.129
+4000.example. 5M IN A 10.0.11.130
+4000.example. 5M IN A 10.0.11.131
+4000.example. 5M IN A 10.0.11.132
+4000.example. 5M IN A 10.0.11.133
+4000.example. 5M IN A 10.0.11.134
+4000.example. 5M IN A 10.0.11.135
+4000.example. 5M IN A 10.0.11.136
+4000.example. 5M IN A 10.0.11.137
+4000.example. 5M IN A 10.0.11.138
+4000.example. 5M IN A 10.0.11.139
+4000.example. 5M IN A 10.0.11.140
+4000.example. 5M IN A 10.0.11.141
+4000.example. 5M IN A 10.0.11.142
+4000.example. 5M IN A 10.0.11.143
+4000.example. 5M IN A 10.0.11.144
+4000.example. 5M IN A 10.0.11.145
+4000.example. 5M IN A 10.0.11.146
+4000.example. 5M IN A 10.0.11.147
+4000.example. 5M IN A 10.0.11.148
+4000.example. 5M IN A 10.0.11.149
+4000.example. 5M IN A 10.0.11.150
+4000.example. 5M IN A 10.0.11.151
+4000.example. 5M IN A 10.0.11.152
+4000.example. 5M IN A 10.0.11.153
+4000.example. 5M IN A 10.0.11.154
+4000.example. 5M IN A 10.0.11.155
+4000.example. 5M IN A 10.0.11.156
+4000.example. 5M IN A 10.0.11.157
+4000.example. 5M IN A 10.0.11.158
+4000.example. 5M IN A 10.0.11.159
+4000.example. 5M IN A 10.0.11.160
+4000.example. 5M IN A 10.0.11.161
+4000.example. 5M IN A 10.0.11.162
+4000.example. 5M IN A 10.0.11.163
+4000.example. 5M IN A 10.0.11.164
+4000.example. 5M IN A 10.0.11.165
+4000.example. 5M IN A 10.0.11.166
+4000.example. 5M IN A 10.0.11.167
+4000.example. 5M IN A 10.0.11.168
+4000.example. 5M IN A 10.0.11.169
+4000.example. 5M IN A 10.0.11.170
+4000.example. 5M IN A 10.0.11.171
+4000.example. 5M IN A 10.0.11.172
+4000.example. 5M IN A 10.0.11.173
+4000.example. 5M IN A 10.0.11.174
+4000.example. 5M IN A 10.0.11.175
+4000.example. 5M IN A 10.0.11.176
+4000.example. 5M IN A 10.0.11.177
+4000.example. 5M IN A 10.0.11.178
+4000.example. 5M IN A 10.0.11.179
+4000.example. 5M IN A 10.0.11.180
+4000.example. 5M IN A 10.0.11.181
+4000.example. 5M IN A 10.0.11.182
+4000.example. 5M IN A 10.0.11.183
+4000.example. 5M IN A 10.0.11.184
+4000.example. 5M IN A 10.0.11.185
+4000.example. 5M IN A 10.0.11.186
+4000.example. 5M IN A 10.0.11.187
+4000.example. 5M IN A 10.0.11.188
+4000.example. 5M IN A 10.0.11.189
+4000.example. 5M IN A 10.0.11.190
+4000.example. 5M IN A 10.0.11.191
+4000.example. 5M IN A 10.0.11.192
+4000.example. 5M IN A 10.0.11.193
+4000.example. 5M IN A 10.0.11.194
+4000.example. 5M IN A 10.0.11.195
+4000.example. 5M IN A 10.0.11.196
+4000.example. 5M IN A 10.0.11.197
+4000.example. 5M IN A 10.0.11.198
+4000.example. 5M IN A 10.0.11.199
+4000.example. 5M IN A 10.0.11.200
+4000.example. 5M IN A 10.0.11.201
+4000.example. 5M IN A 10.0.11.202
+4000.example. 5M IN A 10.0.11.203
+4000.example. 5M IN A 10.0.11.204
+4000.example. 5M IN A 10.0.11.205
+4000.example. 5M IN A 10.0.11.206
+4000.example. 5M IN A 10.0.11.207
+4000.example. 5M IN A 10.0.11.208
+4000.example. 5M IN A 10.0.11.209
+4000.example. 5M IN A 10.0.11.210
+4000.example. 5M IN A 10.0.11.211
+4000.example. 5M IN A 10.0.11.212
+4000.example. 5M IN A 10.0.11.213
+4000.example. 5M IN A 10.0.11.214
+4000.example. 5M IN A 10.0.11.215
+4000.example. 5M IN A 10.0.11.216
+4000.example. 5M IN A 10.0.11.217
+4000.example. 5M IN A 10.0.11.218
+4000.example. 5M IN A 10.0.11.219
+4000.example. 5M IN A 10.0.11.220
+4000.example. 5M IN A 10.0.11.221
+4000.example. 5M IN A 10.0.11.222
+4000.example. 5M IN A 10.0.11.223
+4000.example. 5M IN A 10.0.11.224
+4000.example. 5M IN A 10.0.11.225
+4000.example. 5M IN A 10.0.11.226
+4000.example. 5M IN A 10.0.11.227
+4000.example. 5M IN A 10.0.11.228
+4000.example. 5M IN A 10.0.11.229
+4000.example. 5M IN A 10.0.11.230
+4000.example. 5M IN A 10.0.11.231
+4000.example. 5M IN A 10.0.11.232
+4000.example. 5M IN A 10.0.11.233
+4000.example. 5M IN A 10.0.11.234
+4000.example. 5M IN A 10.0.11.235
+4000.example. 5M IN A 10.0.11.236
+4000.example. 5M IN A 10.0.11.237
+4000.example. 5M IN A 10.0.11.238
+4000.example. 5M IN A 10.0.11.239
+4000.example. 5M IN A 10.0.11.240
+4000.example. 5M IN A 10.0.11.241
+4000.example. 5M IN A 10.0.11.242
+4000.example. 5M IN A 10.0.11.243
+4000.example. 5M IN A 10.0.11.244
+4000.example. 5M IN A 10.0.11.245
+4000.example. 5M IN A 10.0.11.246
+4000.example. 5M IN A 10.0.11.247
+4000.example. 5M IN A 10.0.11.248
+4000.example. 5M IN A 10.0.11.249
+4000.example. 5M IN A 10.0.11.250
+4000.example. 5M IN A 10.0.11.251
+4000.example. 5M IN A 10.0.11.252
+4000.example. 5M IN A 10.0.11.253
+4000.example. 5M IN A 10.0.11.254
+4000.example. 5M IN A 10.0.11.255
+4000.example. 5M IN A 10.0.12.0
+4000.example. 5M IN A 10.0.12.1
+4000.example. 5M IN A 10.0.12.2
+4000.example. 5M IN A 10.0.12.3
+4000.example. 5M IN A 10.0.12.4
+4000.example. 5M IN A 10.0.12.5
+4000.example. 5M IN A 10.0.12.6
+4000.example. 5M IN A 10.0.12.7
+4000.example. 5M IN A 10.0.12.8
+4000.example. 5M IN A 10.0.12.9
+4000.example. 5M IN A 10.0.12.10
+4000.example. 5M IN A 10.0.12.11
+4000.example. 5M IN A 10.0.12.12
+4000.example. 5M IN A 10.0.12.13
+4000.example. 5M IN A 10.0.12.14
+4000.example. 5M IN A 10.0.12.15
+4000.example. 5M IN A 10.0.12.16
+4000.example. 5M IN A 10.0.12.17
+4000.example. 5M IN A 10.0.12.18
+4000.example. 5M IN A 10.0.12.19
+4000.example. 5M IN A 10.0.12.20
+4000.example. 5M IN A 10.0.12.21
+4000.example. 5M IN A 10.0.12.22
+4000.example. 5M IN A 10.0.12.23
+4000.example. 5M IN A 10.0.12.24
+4000.example. 5M IN A 10.0.12.25
+4000.example. 5M IN A 10.0.12.26
+4000.example. 5M IN A 10.0.12.27
+4000.example. 5M IN A 10.0.12.28
+4000.example. 5M IN A 10.0.12.29
+4000.example. 5M IN A 10.0.12.30
+4000.example. 5M IN A 10.0.12.31
+4000.example. 5M IN A 10.0.12.32
+4000.example. 5M IN A 10.0.12.33
+4000.example. 5M IN A 10.0.12.34
+4000.example. 5M IN A 10.0.12.35
+4000.example. 5M IN A 10.0.12.36
+4000.example. 5M IN A 10.0.12.37
+4000.example. 5M IN A 10.0.12.38
+4000.example. 5M IN A 10.0.12.39
+4000.example. 5M IN A 10.0.12.40
+4000.example. 5M IN A 10.0.12.41
+4000.example. 5M IN A 10.0.12.42
+4000.example. 5M IN A 10.0.12.43
+4000.example. 5M IN A 10.0.12.44
+4000.example. 5M IN A 10.0.12.45
+4000.example. 5M IN A 10.0.12.46
+4000.example. 5M IN A 10.0.12.47
+4000.example. 5M IN A 10.0.12.48
+4000.example. 5M IN A 10.0.12.49
+4000.example. 5M IN A 10.0.12.50
+4000.example. 5M IN A 10.0.12.51
+4000.example. 5M IN A 10.0.12.52
+4000.example. 5M IN A 10.0.12.53
+4000.example. 5M IN A 10.0.12.54
+4000.example. 5M IN A 10.0.12.55
+4000.example. 5M IN A 10.0.12.56
+4000.example. 5M IN A 10.0.12.57
+4000.example. 5M IN A 10.0.12.58
+4000.example. 5M IN A 10.0.12.59
+4000.example. 5M IN A 10.0.12.60
+4000.example. 5M IN A 10.0.12.61
+4000.example. 5M IN A 10.0.12.62
+4000.example. 5M IN A 10.0.12.63
+4000.example. 5M IN A 10.0.12.64
+4000.example. 5M IN A 10.0.12.65
+4000.example. 5M IN A 10.0.12.66
+4000.example. 5M IN A 10.0.12.67
+4000.example. 5M IN A 10.0.12.68
+4000.example. 5M IN A 10.0.12.69
+4000.example. 5M IN A 10.0.12.70
+4000.example. 5M IN A 10.0.12.71
+4000.example. 5M IN A 10.0.12.72
+4000.example. 5M IN A 10.0.12.73
+4000.example. 5M IN A 10.0.12.74
+4000.example. 5M IN A 10.0.12.75
+4000.example. 5M IN A 10.0.12.76
+4000.example. 5M IN A 10.0.12.77
+4000.example. 5M IN A 10.0.12.78
+4000.example. 5M IN A 10.0.12.79
+4000.example. 5M IN A 10.0.12.80
+4000.example. 5M IN A 10.0.12.81
+4000.example. 5M IN A 10.0.12.82
+4000.example. 5M IN A 10.0.12.83
+4000.example. 5M IN A 10.0.12.84
+4000.example. 5M IN A 10.0.12.85
+4000.example. 5M IN A 10.0.12.86
+4000.example. 5M IN A 10.0.12.87
+4000.example. 5M IN A 10.0.12.88
+4000.example. 5M IN A 10.0.12.89
+4000.example. 5M IN A 10.0.12.90
+4000.example. 5M IN A 10.0.12.91
+4000.example. 5M IN A 10.0.12.92
+4000.example. 5M IN A 10.0.12.93
+4000.example. 5M IN A 10.0.12.94
+4000.example. 5M IN A 10.0.12.95
+4000.example. 5M IN A 10.0.12.96
+4000.example. 5M IN A 10.0.12.97
+4000.example. 5M IN A 10.0.12.98
+4000.example. 5M IN A 10.0.12.99
+4000.example. 5M IN A 10.0.12.100
+4000.example. 5M IN A 10.0.12.101
+4000.example. 5M IN A 10.0.12.102
+4000.example. 5M IN A 10.0.12.103
+4000.example. 5M IN A 10.0.12.104
+4000.example. 5M IN A 10.0.12.105
+4000.example. 5M IN A 10.0.12.106
+4000.example. 5M IN A 10.0.12.107
+4000.example. 5M IN A 10.0.12.108
+4000.example. 5M IN A 10.0.12.109
+4000.example. 5M IN A 10.0.12.110
+4000.example. 5M IN A 10.0.12.111
+4000.example. 5M IN A 10.0.12.112
+4000.example. 5M IN A 10.0.12.113
+4000.example. 5M IN A 10.0.12.114
+4000.example. 5M IN A 10.0.12.115
+4000.example. 5M IN A 10.0.12.116
+4000.example. 5M IN A 10.0.12.117
+4000.example. 5M IN A 10.0.12.118
+4000.example. 5M IN A 10.0.12.119
+4000.example. 5M IN A 10.0.12.120
+4000.example. 5M IN A 10.0.12.121
+4000.example. 5M IN A 10.0.12.122
+4000.example. 5M IN A 10.0.12.123
+4000.example. 5M IN A 10.0.12.124
+4000.example. 5M IN A 10.0.12.125
+4000.example. 5M IN A 10.0.12.126
+4000.example. 5M IN A 10.0.12.127
+4000.example. 5M IN A 10.0.12.128
+4000.example. 5M IN A 10.0.12.129
+4000.example. 5M IN A 10.0.12.130
+4000.example. 5M IN A 10.0.12.131
+4000.example. 5M IN A 10.0.12.132
+4000.example. 5M IN A 10.0.12.133
+4000.example. 5M IN A 10.0.12.134
+4000.example. 5M IN A 10.0.12.135
+4000.example. 5M IN A 10.0.12.136
+4000.example. 5M IN A 10.0.12.137
+4000.example. 5M IN A 10.0.12.138
+4000.example. 5M IN A 10.0.12.139
+4000.example. 5M IN A 10.0.12.140
+4000.example. 5M IN A 10.0.12.141
+4000.example. 5M IN A 10.0.12.142
+4000.example. 5M IN A 10.0.12.143
+4000.example. 5M IN A 10.0.12.144
+4000.example. 5M IN A 10.0.12.145
+4000.example. 5M IN A 10.0.12.146
+4000.example. 5M IN A 10.0.12.147
+4000.example. 5M IN A 10.0.12.148
+4000.example. 5M IN A 10.0.12.149
+4000.example. 5M IN A 10.0.12.150
+4000.example. 5M IN A 10.0.12.151
+4000.example. 5M IN A 10.0.12.152
+4000.example. 5M IN A 10.0.12.153
+4000.example. 5M IN A 10.0.12.154
+4000.example. 5M IN A 10.0.12.155
+4000.example. 5M IN A 10.0.12.156
+4000.example. 5M IN A 10.0.12.157
+4000.example. 5M IN A 10.0.12.158
+4000.example. 5M IN A 10.0.12.159
+4000.example. 5M IN A 10.0.12.160
+4000.example. 5M IN A 10.0.12.161
+4000.example. 5M IN A 10.0.12.162
+4000.example. 5M IN A 10.0.12.163
+4000.example. 5M IN A 10.0.12.164
+4000.example. 5M IN A 10.0.12.165
+4000.example. 5M IN A 10.0.12.166
+4000.example. 5M IN A 10.0.12.167
+4000.example. 5M IN A 10.0.12.168
+4000.example. 5M IN A 10.0.12.169
+4000.example. 5M IN A 10.0.12.170
+4000.example. 5M IN A 10.0.12.171
+4000.example. 5M IN A 10.0.12.172
+4000.example. 5M IN A 10.0.12.173
+4000.example. 5M IN A 10.0.12.174
+4000.example. 5M IN A 10.0.12.175
+4000.example. 5M IN A 10.0.12.176
+4000.example. 5M IN A 10.0.12.177
+4000.example. 5M IN A 10.0.12.178
+4000.example. 5M IN A 10.0.12.179
+4000.example. 5M IN A 10.0.12.180
+4000.example. 5M IN A 10.0.12.181
+4000.example. 5M IN A 10.0.12.182
+4000.example. 5M IN A 10.0.12.183
+4000.example. 5M IN A 10.0.12.184
+4000.example. 5M IN A 10.0.12.185
+4000.example. 5M IN A 10.0.12.186
+4000.example. 5M IN A 10.0.12.187
+4000.example. 5M IN A 10.0.12.188
+4000.example. 5M IN A 10.0.12.189
+4000.example. 5M IN A 10.0.12.190
+4000.example. 5M IN A 10.0.12.191
+4000.example. 5M IN A 10.0.12.192
+4000.example. 5M IN A 10.0.12.193
+4000.example. 5M IN A 10.0.12.194
+4000.example. 5M IN A 10.0.12.195
+4000.example. 5M IN A 10.0.12.196
+4000.example. 5M IN A 10.0.12.197
+4000.example. 5M IN A 10.0.12.198
+4000.example. 5M IN A 10.0.12.199
+4000.example. 5M IN A 10.0.12.200
+4000.example. 5M IN A 10.0.12.201
+4000.example. 5M IN A 10.0.12.202
+4000.example. 5M IN A 10.0.12.203
+4000.example. 5M IN A 10.0.12.204
+4000.example. 5M IN A 10.0.12.205
+4000.example. 5M IN A 10.0.12.206
+4000.example. 5M IN A 10.0.12.207
+4000.example. 5M IN A 10.0.12.208
+4000.example. 5M IN A 10.0.12.209
+4000.example. 5M IN A 10.0.12.210
+4000.example. 5M IN A 10.0.12.211
+4000.example. 5M IN A 10.0.12.212
+4000.example. 5M IN A 10.0.12.213
+4000.example. 5M IN A 10.0.12.214
+4000.example. 5M IN A 10.0.12.215
+4000.example. 5M IN A 10.0.12.216
+4000.example. 5M IN A 10.0.12.217
+4000.example. 5M IN A 10.0.12.218
+4000.example. 5M IN A 10.0.12.219
+4000.example. 5M IN A 10.0.12.220
+4000.example. 5M IN A 10.0.12.221
+4000.example. 5M IN A 10.0.12.222
+4000.example. 5M IN A 10.0.12.223
+4000.example. 5M IN A 10.0.12.224
+4000.example. 5M IN A 10.0.12.225
+4000.example. 5M IN A 10.0.12.226
+4000.example. 5M IN A 10.0.12.227
+4000.example. 5M IN A 10.0.12.228
+4000.example. 5M IN A 10.0.12.229
+4000.example. 5M IN A 10.0.12.230
+4000.example. 5M IN A 10.0.12.231
+4000.example. 5M IN A 10.0.12.232
+4000.example. 5M IN A 10.0.12.233
+4000.example. 5M IN A 10.0.12.234
+4000.example. 5M IN A 10.0.12.235
+4000.example. 5M IN A 10.0.12.236
+4000.example. 5M IN A 10.0.12.237
+4000.example. 5M IN A 10.0.12.238
+4000.example. 5M IN A 10.0.12.239
+4000.example. 5M IN A 10.0.12.240
+4000.example. 5M IN A 10.0.12.241
+4000.example. 5M IN A 10.0.12.242
+4000.example. 5M IN A 10.0.12.243
+4000.example. 5M IN A 10.0.12.244
+4000.example. 5M IN A 10.0.12.245
+4000.example. 5M IN A 10.0.12.246
+4000.example. 5M IN A 10.0.12.247
+4000.example. 5M IN A 10.0.12.248
+4000.example. 5M IN A 10.0.12.249
+4000.example. 5M IN A 10.0.12.250
+4000.example. 5M IN A 10.0.12.251
+4000.example. 5M IN A 10.0.12.252
+4000.example. 5M IN A 10.0.12.253
+4000.example. 5M IN A 10.0.12.254
+4000.example. 5M IN A 10.0.12.255
+4000.example. 5M IN A 10.0.13.0
+4000.example. 5M IN A 10.0.13.1
+4000.example. 5M IN A 10.0.13.2
+4000.example. 5M IN A 10.0.13.3
+4000.example. 5M IN A 10.0.13.4
+4000.example. 5M IN A 10.0.13.5
+4000.example. 5M IN A 10.0.13.6
+4000.example. 5M IN A 10.0.13.7
+4000.example. 5M IN A 10.0.13.8
+4000.example. 5M IN A 10.0.13.9
+4000.example. 5M IN A 10.0.13.10
+4000.example. 5M IN A 10.0.13.11
+4000.example. 5M IN A 10.0.13.12
+4000.example. 5M IN A 10.0.13.13
+4000.example. 5M IN A 10.0.13.14
+4000.example. 5M IN A 10.0.13.15
+4000.example. 5M IN A 10.0.13.16
+4000.example. 5M IN A 10.0.13.17
+4000.example. 5M IN A 10.0.13.18
+4000.example. 5M IN A 10.0.13.19
+4000.example. 5M IN A 10.0.13.20
+4000.example. 5M IN A 10.0.13.21
+4000.example. 5M IN A 10.0.13.22
+4000.example. 5M IN A 10.0.13.23
+4000.example. 5M IN A 10.0.13.24
+4000.example. 5M IN A 10.0.13.25
+4000.example. 5M IN A 10.0.13.26
+4000.example. 5M IN A 10.0.13.27
+4000.example. 5M IN A 10.0.13.28
+4000.example. 5M IN A 10.0.13.29
+4000.example. 5M IN A 10.0.13.30
+4000.example. 5M IN A 10.0.13.31
+4000.example. 5M IN A 10.0.13.32
+4000.example. 5M IN A 10.0.13.33
+4000.example. 5M IN A 10.0.13.34
+4000.example. 5M IN A 10.0.13.35
+4000.example. 5M IN A 10.0.13.36
+4000.example. 5M IN A 10.0.13.37
+4000.example. 5M IN A 10.0.13.38
+4000.example. 5M IN A 10.0.13.39
+4000.example. 5M IN A 10.0.13.40
+4000.example. 5M IN A 10.0.13.41
+4000.example. 5M IN A 10.0.13.42
+4000.example. 5M IN A 10.0.13.43
+4000.example. 5M IN A 10.0.13.44
+4000.example. 5M IN A 10.0.13.45
+4000.example. 5M IN A 10.0.13.46
+4000.example. 5M IN A 10.0.13.47
+4000.example. 5M IN A 10.0.13.48
+4000.example. 5M IN A 10.0.13.49
+4000.example. 5M IN A 10.0.13.50
+4000.example. 5M IN A 10.0.13.51
+4000.example. 5M IN A 10.0.13.52
+4000.example. 5M IN A 10.0.13.53
+4000.example. 5M IN A 10.0.13.54
+4000.example. 5M IN A 10.0.13.55
+4000.example. 5M IN A 10.0.13.56
+4000.example. 5M IN A 10.0.13.57
+4000.example. 5M IN A 10.0.13.58
+4000.example. 5M IN A 10.0.13.59
+4000.example. 5M IN A 10.0.13.60
+4000.example. 5M IN A 10.0.13.61
+4000.example. 5M IN A 10.0.13.62
+4000.example. 5M IN A 10.0.13.63
+4000.example. 5M IN A 10.0.13.64
+4000.example. 5M IN A 10.0.13.65
+4000.example. 5M IN A 10.0.13.66
+4000.example. 5M IN A 10.0.13.67
+4000.example. 5M IN A 10.0.13.68
+4000.example. 5M IN A 10.0.13.69
+4000.example. 5M IN A 10.0.13.70
+4000.example. 5M IN A 10.0.13.71
+4000.example. 5M IN A 10.0.13.72
+4000.example. 5M IN A 10.0.13.73
+4000.example. 5M IN A 10.0.13.74
+4000.example. 5M IN A 10.0.13.75
+4000.example. 5M IN A 10.0.13.76
+4000.example. 5M IN A 10.0.13.77
+4000.example. 5M IN A 10.0.13.78
+4000.example. 5M IN A 10.0.13.79
+4000.example. 5M IN A 10.0.13.80
+4000.example. 5M IN A 10.0.13.81
+4000.example. 5M IN A 10.0.13.82
+4000.example. 5M IN A 10.0.13.83
+4000.example. 5M IN A 10.0.13.84
+4000.example. 5M IN A 10.0.13.85
+4000.example. 5M IN A 10.0.13.86
+4000.example. 5M IN A 10.0.13.87
+4000.example. 5M IN A 10.0.13.88
+4000.example. 5M IN A 10.0.13.89
+4000.example. 5M IN A 10.0.13.90
+4000.example. 5M IN A 10.0.13.91
+4000.example. 5M IN A 10.0.13.92
+4000.example. 5M IN A 10.0.13.93
+4000.example. 5M IN A 10.0.13.94
+4000.example. 5M IN A 10.0.13.95
+4000.example. 5M IN A 10.0.13.96
+4000.example. 5M IN A 10.0.13.97
+4000.example. 5M IN A 10.0.13.98
+4000.example. 5M IN A 10.0.13.99
+4000.example. 5M IN A 10.0.13.100
+4000.example. 5M IN A 10.0.13.101
+4000.example. 5M IN A 10.0.13.102
+4000.example. 5M IN A 10.0.13.103
+4000.example. 5M IN A 10.0.13.104
+4000.example. 5M IN A 10.0.13.105
+4000.example. 5M IN A 10.0.13.106
+4000.example. 5M IN A 10.0.13.107
+4000.example. 5M IN A 10.0.13.108
+4000.example. 5M IN A 10.0.13.109
+4000.example. 5M IN A 10.0.13.110
+4000.example. 5M IN A 10.0.13.111
+4000.example. 5M IN A 10.0.13.112
+4000.example. 5M IN A 10.0.13.113
+4000.example. 5M IN A 10.0.13.114
+4000.example. 5M IN A 10.0.13.115
+4000.example. 5M IN A 10.0.13.116
+4000.example. 5M IN A 10.0.13.117
+4000.example. 5M IN A 10.0.13.118
+4000.example. 5M IN A 10.0.13.119
+4000.example. 5M IN A 10.0.13.120
+4000.example. 5M IN A 10.0.13.121
+4000.example. 5M IN A 10.0.13.122
+4000.example. 5M IN A 10.0.13.123
+4000.example. 5M IN A 10.0.13.124
+4000.example. 5M IN A 10.0.13.125
+4000.example. 5M IN A 10.0.13.126
+4000.example. 5M IN A 10.0.13.127
+4000.example. 5M IN A 10.0.13.128
+4000.example. 5M IN A 10.0.13.129
+4000.example. 5M IN A 10.0.13.130
+4000.example. 5M IN A 10.0.13.131
+4000.example. 5M IN A 10.0.13.132
+4000.example. 5M IN A 10.0.13.133
+4000.example. 5M IN A 10.0.13.134
+4000.example. 5M IN A 10.0.13.135
+4000.example. 5M IN A 10.0.13.136
+4000.example. 5M IN A 10.0.13.137
+4000.example. 5M IN A 10.0.13.138
+4000.example. 5M IN A 10.0.13.139
+4000.example. 5M IN A 10.0.13.140
+4000.example. 5M IN A 10.0.13.141
+4000.example. 5M IN A 10.0.13.142
+4000.example. 5M IN A 10.0.13.143
+4000.example. 5M IN A 10.0.13.144
+4000.example. 5M IN A 10.0.13.145
+4000.example. 5M IN A 10.0.13.146
+4000.example. 5M IN A 10.0.13.147
+4000.example. 5M IN A 10.0.13.148
+4000.example. 5M IN A 10.0.13.149
+4000.example. 5M IN A 10.0.13.150
+4000.example. 5M IN A 10.0.13.151
+4000.example. 5M IN A 10.0.13.152
+4000.example. 5M IN A 10.0.13.153
+4000.example. 5M IN A 10.0.13.154
+4000.example. 5M IN A 10.0.13.155
+4000.example. 5M IN A 10.0.13.156
+4000.example. 5M IN A 10.0.13.157
+4000.example. 5M IN A 10.0.13.158
+4000.example. 5M IN A 10.0.13.159
+4000.example. 5M IN A 10.0.13.160
+4000.example. 5M IN A 10.0.13.161
+4000.example. 5M IN A 10.0.13.162
+4000.example. 5M IN A 10.0.13.163
+4000.example. 5M IN A 10.0.13.164
+4000.example. 5M IN A 10.0.13.165
+4000.example. 5M IN A 10.0.13.166
+4000.example. 5M IN A 10.0.13.167
+4000.example. 5M IN A 10.0.13.168
+4000.example. 5M IN A 10.0.13.169
+4000.example. 5M IN A 10.0.13.170
+4000.example. 5M IN A 10.0.13.171
+4000.example. 5M IN A 10.0.13.172
+4000.example. 5M IN A 10.0.13.173
+4000.example. 5M IN A 10.0.13.174
+4000.example. 5M IN A 10.0.13.175
+4000.example. 5M IN A 10.0.13.176
+4000.example. 5M IN A 10.0.13.177
+4000.example. 5M IN A 10.0.13.178
+4000.example. 5M IN A 10.0.13.179
+4000.example. 5M IN A 10.0.13.180
+4000.example. 5M IN A 10.0.13.181
+4000.example. 5M IN A 10.0.13.182
+4000.example. 5M IN A 10.0.13.183
+4000.example. 5M IN A 10.0.13.184
+4000.example. 5M IN A 10.0.13.185
+4000.example. 5M IN A 10.0.13.186
+4000.example. 5M IN A 10.0.13.187
+4000.example. 5M IN A 10.0.13.188
+4000.example. 5M IN A 10.0.13.189
+4000.example. 5M IN A 10.0.13.190
+4000.example. 5M IN A 10.0.13.191
+4000.example. 5M IN A 10.0.13.192
+4000.example. 5M IN A 10.0.13.193
+4000.example. 5M IN A 10.0.13.194
+4000.example. 5M IN A 10.0.13.195
+4000.example. 5M IN A 10.0.13.196
+4000.example. 5M IN A 10.0.13.197
+4000.example. 5M IN A 10.0.13.198
+4000.example. 5M IN A 10.0.13.199
+4000.example. 5M IN A 10.0.13.200
+4000.example. 5M IN A 10.0.13.201
+4000.example. 5M IN A 10.0.13.202
+4000.example. 5M IN A 10.0.13.203
+4000.example. 5M IN A 10.0.13.204
+4000.example. 5M IN A 10.0.13.205
+4000.example. 5M IN A 10.0.13.206
+4000.example. 5M IN A 10.0.13.207
+4000.example. 5M IN A 10.0.13.208
+4000.example. 5M IN A 10.0.13.209
+4000.example. 5M IN A 10.0.13.210
+4000.example. 5M IN A 10.0.13.211
+4000.example. 5M IN A 10.0.13.212
+4000.example. 5M IN A 10.0.13.213
+4000.example. 5M IN A 10.0.13.214
+4000.example. 5M IN A 10.0.13.215
+4000.example. 5M IN A 10.0.13.216
+4000.example. 5M IN A 10.0.13.217
+4000.example. 5M IN A 10.0.13.218
+4000.example. 5M IN A 10.0.13.219
+4000.example. 5M IN A 10.0.13.220
+4000.example. 5M IN A 10.0.13.221
+4000.example. 5M IN A 10.0.13.222
+4000.example. 5M IN A 10.0.13.223
+4000.example. 5M IN A 10.0.13.224
+4000.example. 5M IN A 10.0.13.225
+4000.example. 5M IN A 10.0.13.226
+4000.example. 5M IN A 10.0.13.227
+4000.example. 5M IN A 10.0.13.228
+4000.example. 5M IN A 10.0.13.229
+4000.example. 5M IN A 10.0.13.230
+4000.example. 5M IN A 10.0.13.231
+4000.example. 5M IN A 10.0.13.232
+4000.example. 5M IN A 10.0.13.233
+4000.example. 5M IN A 10.0.13.234
+4000.example. 5M IN A 10.0.13.235
+4000.example. 5M IN A 10.0.13.236
+4000.example. 5M IN A 10.0.13.237
+4000.example. 5M IN A 10.0.13.238
+4000.example. 5M IN A 10.0.13.239
+4000.example. 5M IN A 10.0.13.240
+4000.example. 5M IN A 10.0.13.241
+4000.example. 5M IN A 10.0.13.242
+4000.example. 5M IN A 10.0.13.243
+4000.example. 5M IN A 10.0.13.244
+4000.example. 5M IN A 10.0.13.245
+4000.example. 5M IN A 10.0.13.246
+4000.example. 5M IN A 10.0.13.247
+4000.example. 5M IN A 10.0.13.248
+4000.example. 5M IN A 10.0.13.249
+4000.example. 5M IN A 10.0.13.250
+4000.example. 5M IN A 10.0.13.251
+4000.example. 5M IN A 10.0.13.252
+4000.example. 5M IN A 10.0.13.253
+4000.example. 5M IN A 10.0.13.254
+4000.example. 5M IN A 10.0.13.255
+4000.example. 5M IN A 10.0.14.0
+4000.example. 5M IN A 10.0.14.1
+4000.example. 5M IN A 10.0.14.2
+4000.example. 5M IN A 10.0.14.3
+4000.example. 5M IN A 10.0.14.4
+4000.example. 5M IN A 10.0.14.5
+4000.example. 5M IN A 10.0.14.6
+4000.example. 5M IN A 10.0.14.7
+4000.example. 5M IN A 10.0.14.8
+4000.example. 5M IN A 10.0.14.9
+4000.example. 5M IN A 10.0.14.10
+4000.example. 5M IN A 10.0.14.11
+4000.example. 5M IN A 10.0.14.12
+4000.example. 5M IN A 10.0.14.13
+4000.example. 5M IN A 10.0.14.14
+4000.example. 5M IN A 10.0.14.15
+4000.example. 5M IN A 10.0.14.16
+4000.example. 5M IN A 10.0.14.17
+4000.example. 5M IN A 10.0.14.18
+4000.example. 5M IN A 10.0.14.19
+4000.example. 5M IN A 10.0.14.20
+4000.example. 5M IN A 10.0.14.21
+4000.example. 5M IN A 10.0.14.22
+4000.example. 5M IN A 10.0.14.23
+4000.example. 5M IN A 10.0.14.24
+4000.example. 5M IN A 10.0.14.25
+4000.example. 5M IN A 10.0.14.26
+4000.example. 5M IN A 10.0.14.27
+4000.example. 5M IN A 10.0.14.28
+4000.example. 5M IN A 10.0.14.29
+4000.example. 5M IN A 10.0.14.30
+4000.example. 5M IN A 10.0.14.31
+4000.example. 5M IN A 10.0.14.32
+4000.example. 5M IN A 10.0.14.33
+4000.example. 5M IN A 10.0.14.34
+4000.example. 5M IN A 10.0.14.35
+4000.example. 5M IN A 10.0.14.36
+4000.example. 5M IN A 10.0.14.37
+4000.example. 5M IN A 10.0.14.38
+4000.example. 5M IN A 10.0.14.39
+4000.example. 5M IN A 10.0.14.40
+4000.example. 5M IN A 10.0.14.41
+4000.example. 5M IN A 10.0.14.42
+4000.example. 5M IN A 10.0.14.43
+4000.example. 5M IN A 10.0.14.44
+4000.example. 5M IN A 10.0.14.45
+4000.example. 5M IN A 10.0.14.46
+4000.example. 5M IN A 10.0.14.47
+4000.example. 5M IN A 10.0.14.48
+4000.example. 5M IN A 10.0.14.49
+4000.example. 5M IN A 10.0.14.50
+4000.example. 5M IN A 10.0.14.51
+4000.example. 5M IN A 10.0.14.52
+4000.example. 5M IN A 10.0.14.53
+4000.example. 5M IN A 10.0.14.54
+4000.example. 5M IN A 10.0.14.55
+4000.example. 5M IN A 10.0.14.56
+4000.example. 5M IN A 10.0.14.57
+4000.example. 5M IN A 10.0.14.58
+4000.example. 5M IN A 10.0.14.59
+4000.example. 5M IN A 10.0.14.60
+4000.example. 5M IN A 10.0.14.61
+4000.example. 5M IN A 10.0.14.62
+4000.example. 5M IN A 10.0.14.63
+4000.example. 5M IN A 10.0.14.64
+4000.example. 5M IN A 10.0.14.65
+4000.example. 5M IN A 10.0.14.66
+4000.example. 5M IN A 10.0.14.67
+4000.example. 5M IN A 10.0.14.68
+4000.example. 5M IN A 10.0.14.69
+4000.example. 5M IN A 10.0.14.70
+4000.example. 5M IN A 10.0.14.71
+4000.example. 5M IN A 10.0.14.72
+4000.example. 5M IN A 10.0.14.73
+4000.example. 5M IN A 10.0.14.74
+4000.example. 5M IN A 10.0.14.75
+4000.example. 5M IN A 10.0.14.76
+4000.example. 5M IN A 10.0.14.77
+4000.example. 5M IN A 10.0.14.78
+4000.example. 5M IN A 10.0.14.79
+4000.example. 5M IN A 10.0.14.80
+4000.example. 5M IN A 10.0.14.81
+4000.example. 5M IN A 10.0.14.82
+4000.example. 5M IN A 10.0.14.83
+4000.example. 5M IN A 10.0.14.84
+4000.example. 5M IN A 10.0.14.85
+4000.example. 5M IN A 10.0.14.86
+4000.example. 5M IN A 10.0.14.87
+4000.example. 5M IN A 10.0.14.88
+4000.example. 5M IN A 10.0.14.89
+4000.example. 5M IN A 10.0.14.90
+4000.example. 5M IN A 10.0.14.91
+4000.example. 5M IN A 10.0.14.92
+4000.example. 5M IN A 10.0.14.93
+4000.example. 5M IN A 10.0.14.94
+4000.example. 5M IN A 10.0.14.95
+4000.example. 5M IN A 10.0.14.96
+4000.example. 5M IN A 10.0.14.97
+4000.example. 5M IN A 10.0.14.98
+4000.example. 5M IN A 10.0.14.99
+4000.example. 5M IN A 10.0.14.100
+4000.example. 5M IN A 10.0.14.101
+4000.example. 5M IN A 10.0.14.102
+4000.example. 5M IN A 10.0.14.103
+4000.example. 5M IN A 10.0.14.104
+4000.example. 5M IN A 10.0.14.105
+4000.example. 5M IN A 10.0.14.106
+4000.example. 5M IN A 10.0.14.107
+4000.example. 5M IN A 10.0.14.108
+4000.example. 5M IN A 10.0.14.109
+4000.example. 5M IN A 10.0.14.110
+4000.example. 5M IN A 10.0.14.111
+4000.example. 5M IN A 10.0.14.112
+4000.example. 5M IN A 10.0.14.113
+4000.example. 5M IN A 10.0.14.114
+4000.example. 5M IN A 10.0.14.115
+4000.example. 5M IN A 10.0.14.116
+4000.example. 5M IN A 10.0.14.117
+4000.example. 5M IN A 10.0.14.118
+4000.example. 5M IN A 10.0.14.119
+4000.example. 5M IN A 10.0.14.120
+4000.example. 5M IN A 10.0.14.121
+4000.example. 5M IN A 10.0.14.122
+4000.example. 5M IN A 10.0.14.123
+4000.example. 5M IN A 10.0.14.124
+4000.example. 5M IN A 10.0.14.125
+4000.example. 5M IN A 10.0.14.126
+4000.example. 5M IN A 10.0.14.127
+4000.example. 5M IN A 10.0.14.128
+4000.example. 5M IN A 10.0.14.129
+4000.example. 5M IN A 10.0.14.130
+4000.example. 5M IN A 10.0.14.131
+4000.example. 5M IN A 10.0.14.132
+4000.example. 5M IN A 10.0.14.133
+4000.example. 5M IN A 10.0.14.134
+4000.example. 5M IN A 10.0.14.135
+4000.example. 5M IN A 10.0.14.136
+4000.example. 5M IN A 10.0.14.137
+4000.example. 5M IN A 10.0.14.138
+4000.example. 5M IN A 10.0.14.139
+4000.example. 5M IN A 10.0.14.140
+4000.example. 5M IN A 10.0.14.141
+4000.example. 5M IN A 10.0.14.142
+4000.example. 5M IN A 10.0.14.143
+4000.example. 5M IN A 10.0.14.144
+4000.example. 5M IN A 10.0.14.145
+4000.example. 5M IN A 10.0.14.146
+4000.example. 5M IN A 10.0.14.147
+4000.example. 5M IN A 10.0.14.148
+4000.example. 5M IN A 10.0.14.149
+4000.example. 5M IN A 10.0.14.150
+4000.example. 5M IN A 10.0.14.151
+4000.example. 5M IN A 10.0.14.152
+4000.example. 5M IN A 10.0.14.153
+4000.example. 5M IN A 10.0.14.154
+4000.example. 5M IN A 10.0.14.155
+4000.example. 5M IN A 10.0.14.156
+4000.example. 5M IN A 10.0.14.157
+4000.example. 5M IN A 10.0.14.158
+4000.example. 5M IN A 10.0.14.159
+4000.example. 5M IN A 10.0.14.160
+4000.example. 5M IN A 10.0.14.161
+4000.example. 5M IN A 10.0.14.162
+4000.example. 5M IN A 10.0.14.163
+4000.example. 5M IN A 10.0.14.164
+4000.example. 5M IN A 10.0.14.165
+4000.example. 5M IN A 10.0.14.166
+4000.example. 5M IN A 10.0.14.167
+4000.example. 5M IN A 10.0.14.168
+4000.example. 5M IN A 10.0.14.169
+4000.example. 5M IN A 10.0.14.170
+4000.example. 5M IN A 10.0.14.171
+4000.example. 5M IN A 10.0.14.172
+4000.example. 5M IN A 10.0.14.173
+4000.example. 5M IN A 10.0.14.174
+4000.example. 5M IN A 10.0.14.175
+4000.example. 5M IN A 10.0.14.176
+4000.example. 5M IN A 10.0.14.177
+4000.example. 5M IN A 10.0.14.178
+4000.example. 5M IN A 10.0.14.179
+4000.example. 5M IN A 10.0.14.180
+4000.example. 5M IN A 10.0.14.181
+4000.example. 5M IN A 10.0.14.182
+4000.example. 5M IN A 10.0.14.183
+4000.example. 5M IN A 10.0.14.184
+4000.example. 5M IN A 10.0.14.185
+4000.example. 5M IN A 10.0.14.186
+4000.example. 5M IN A 10.0.14.187
+4000.example. 5M IN A 10.0.14.188
+4000.example. 5M IN A 10.0.14.189
+4000.example. 5M IN A 10.0.14.190
+4000.example. 5M IN A 10.0.14.191
+4000.example. 5M IN A 10.0.14.192
+4000.example. 5M IN A 10.0.14.193
+4000.example. 5M IN A 10.0.14.194
+4000.example. 5M IN A 10.0.14.195
+4000.example. 5M IN A 10.0.14.196
+4000.example. 5M IN A 10.0.14.197
+4000.example. 5M IN A 10.0.14.198
+4000.example. 5M IN A 10.0.14.199
+4000.example. 5M IN A 10.0.14.200
+4000.example. 5M IN A 10.0.14.201
+4000.example. 5M IN A 10.0.14.202
+4000.example. 5M IN A 10.0.14.203
+4000.example. 5M IN A 10.0.14.204
+4000.example. 5M IN A 10.0.14.205
+4000.example. 5M IN A 10.0.14.206
+4000.example. 5M IN A 10.0.14.207
+4000.example. 5M IN A 10.0.14.208
+4000.example. 5M IN A 10.0.14.209
+4000.example. 5M IN A 10.0.14.210
+4000.example. 5M IN A 10.0.14.211
+4000.example. 5M IN A 10.0.14.212
+4000.example. 5M IN A 10.0.14.213
+4000.example. 5M IN A 10.0.14.214
+4000.example. 5M IN A 10.0.14.215
+4000.example. 5M IN A 10.0.14.216
+4000.example. 5M IN A 10.0.14.217
+4000.example. 5M IN A 10.0.14.218
+4000.example. 5M IN A 10.0.14.219
+4000.example. 5M IN A 10.0.14.220
+4000.example. 5M IN A 10.0.14.221
+4000.example. 5M IN A 10.0.14.222
+4000.example. 5M IN A 10.0.14.223
+4000.example. 5M IN A 10.0.14.224
+4000.example. 5M IN A 10.0.14.225
+4000.example. 5M IN A 10.0.14.226
+4000.example. 5M IN A 10.0.14.227
+4000.example. 5M IN A 10.0.14.228
+4000.example. 5M IN A 10.0.14.229
+4000.example. 5M IN A 10.0.14.230
+4000.example. 5M IN A 10.0.14.231
+4000.example. 5M IN A 10.0.14.232
+4000.example. 5M IN A 10.0.14.233
+4000.example. 5M IN A 10.0.14.234
+4000.example. 5M IN A 10.0.14.235
+4000.example. 5M IN A 10.0.14.236
+4000.example. 5M IN A 10.0.14.237
+4000.example. 5M IN A 10.0.14.238
+4000.example. 5M IN A 10.0.14.239
+4000.example. 5M IN A 10.0.14.240
+4000.example. 5M IN A 10.0.14.241
+4000.example. 5M IN A 10.0.14.242
+4000.example. 5M IN A 10.0.14.243
+4000.example. 5M IN A 10.0.14.244
+4000.example. 5M IN A 10.0.14.245
+4000.example. 5M IN A 10.0.14.246
+4000.example. 5M IN A 10.0.14.247
+4000.example. 5M IN A 10.0.14.248
+4000.example. 5M IN A 10.0.14.249
+4000.example. 5M IN A 10.0.14.250
+4000.example. 5M IN A 10.0.14.251
+4000.example. 5M IN A 10.0.14.252
+4000.example. 5M IN A 10.0.14.253
+4000.example. 5M IN A 10.0.14.254
+4000.example. 5M IN A 10.0.14.255
+4000.example. 5M IN A 10.0.15.0
+4000.example. 5M IN A 10.0.15.1
+4000.example. 5M IN A 10.0.15.2
+4000.example. 5M IN A 10.0.15.3
+4000.example. 5M IN A 10.0.15.4
+4000.example. 5M IN A 10.0.15.5
+4000.example. 5M IN A 10.0.15.6
+4000.example. 5M IN A 10.0.15.7
+4000.example. 5M IN A 10.0.15.8
+4000.example. 5M IN A 10.0.15.9
+4000.example. 5M IN A 10.0.15.10
+4000.example. 5M IN A 10.0.15.11
+4000.example. 5M IN A 10.0.15.12
+4000.example. 5M IN A 10.0.15.13
+4000.example. 5M IN A 10.0.15.14
+4000.example. 5M IN A 10.0.15.15
+4000.example. 5M IN A 10.0.15.16
+4000.example. 5M IN A 10.0.15.17
+4000.example. 5M IN A 10.0.15.18
+4000.example. 5M IN A 10.0.15.19
+4000.example. 5M IN A 10.0.15.20
+4000.example. 5M IN A 10.0.15.21
+4000.example. 5M IN A 10.0.15.22
+4000.example. 5M IN A 10.0.15.23
+4000.example. 5M IN A 10.0.15.24
+4000.example. 5M IN A 10.0.15.25
+4000.example. 5M IN A 10.0.15.26
+4000.example. 5M IN A 10.0.15.27
+4000.example. 5M IN A 10.0.15.28
+4000.example. 5M IN A 10.0.15.29
+4000.example. 5M IN A 10.0.15.30
+4000.example. 5M IN A 10.0.15.31
+4000.example. 5M IN A 10.0.15.32
+4000.example. 5M IN A 10.0.15.33
+4000.example. 5M IN A 10.0.15.34
+4000.example. 5M IN A 10.0.15.35
+4000.example. 5M IN A 10.0.15.36
+4000.example. 5M IN A 10.0.15.37
+4000.example. 5M IN A 10.0.15.38
+4000.example. 5M IN A 10.0.15.39
+4000.example. 5M IN A 10.0.15.40
+4000.example. 5M IN A 10.0.15.41
+4000.example. 5M IN A 10.0.15.42
+4000.example. 5M IN A 10.0.15.43
+4000.example. 5M IN A 10.0.15.44
+4000.example. 5M IN A 10.0.15.45
+4000.example. 5M IN A 10.0.15.46
+4000.example. 5M IN A 10.0.15.47
+4000.example. 5M IN A 10.0.15.48
+4000.example. 5M IN A 10.0.15.49
+4000.example. 5M IN A 10.0.15.50
+4000.example. 5M IN A 10.0.15.51
+4000.example. 5M IN A 10.0.15.52
+4000.example. 5M IN A 10.0.15.53
+4000.example. 5M IN A 10.0.15.54
+4000.example. 5M IN A 10.0.15.55
+4000.example. 5M IN A 10.0.15.56
+4000.example. 5M IN A 10.0.15.57
+4000.example. 5M IN A 10.0.15.58
+4000.example. 5M IN A 10.0.15.59
+4000.example. 5M IN A 10.0.15.60
+4000.example. 5M IN A 10.0.15.61
+4000.example. 5M IN A 10.0.15.62
+4000.example. 5M IN A 10.0.15.63
+4000.example. 5M IN A 10.0.15.64
+4000.example. 5M IN A 10.0.15.65
+4000.example. 5M IN A 10.0.15.66
+4000.example. 5M IN A 10.0.15.67
+4000.example. 5M IN A 10.0.15.68
+4000.example. 5M IN A 10.0.15.69
+4000.example. 5M IN A 10.0.15.70
+4000.example. 5M IN A 10.0.15.71
+4000.example. 5M IN A 10.0.15.72
+4000.example. 5M IN A 10.0.15.73
+4000.example. 5M IN A 10.0.15.74
+4000.example. 5M IN A 10.0.15.75
+4000.example. 5M IN A 10.0.15.76
+4000.example. 5M IN A 10.0.15.77
+4000.example. 5M IN A 10.0.15.78
+4000.example. 5M IN A 10.0.15.79
+4000.example. 5M IN A 10.0.15.80
+4000.example. 5M IN A 10.0.15.81
+4000.example. 5M IN A 10.0.15.82
+4000.example. 5M IN A 10.0.15.83
+4000.example. 5M IN A 10.0.15.84
+4000.example. 5M IN A 10.0.15.85
+4000.example. 5M IN A 10.0.15.86
+4000.example. 5M IN A 10.0.15.87
+4000.example. 5M IN A 10.0.15.88
+4000.example. 5M IN A 10.0.15.89
+4000.example. 5M IN A 10.0.15.90
+4000.example. 5M IN A 10.0.15.91
+4000.example. 5M IN A 10.0.15.92
+4000.example. 5M IN A 10.0.15.93
+4000.example. 5M IN A 10.0.15.94
+4000.example. 5M IN A 10.0.15.95
+4000.example. 5M IN A 10.0.15.96
+4000.example. 5M IN A 10.0.15.97
+4000.example. 5M IN A 10.0.15.98
+4000.example. 5M IN A 10.0.15.99
+4000.example. 5M IN A 10.0.15.100
+4000.example. 5M IN A 10.0.15.101
+4000.example. 5M IN A 10.0.15.102
+4000.example. 5M IN A 10.0.15.103
+4000.example. 5M IN A 10.0.15.104
+4000.example. 5M IN A 10.0.15.105
+4000.example. 5M IN A 10.0.15.106
+4000.example. 5M IN A 10.0.15.107
+4000.example. 5M IN A 10.0.15.108
+4000.example. 5M IN A 10.0.15.109
+4000.example. 5M IN A 10.0.15.110
+4000.example. 5M IN A 10.0.15.111
+4000.example. 5M IN A 10.0.15.112
+4000.example. 5M IN A 10.0.15.113
+4000.example. 5M IN A 10.0.15.114
+4000.example. 5M IN A 10.0.15.115
+4000.example. 5M IN A 10.0.15.116
+4000.example. 5M IN A 10.0.15.117
+4000.example. 5M IN A 10.0.15.118
+4000.example. 5M IN A 10.0.15.119
+4000.example. 5M IN A 10.0.15.120
+4000.example. 5M IN A 10.0.15.121
+4000.example. 5M IN A 10.0.15.122
+4000.example. 5M IN A 10.0.15.123
+4000.example. 5M IN A 10.0.15.124
+4000.example. 5M IN A 10.0.15.125
+4000.example. 5M IN A 10.0.15.126
+4000.example. 5M IN A 10.0.15.127
+4000.example. 5M IN A 10.0.15.128
+4000.example. 5M IN A 10.0.15.129
+4000.example. 5M IN A 10.0.15.130
+4000.example. 5M IN A 10.0.15.131
+4000.example. 5M IN A 10.0.15.132
+4000.example. 5M IN A 10.0.15.133
+4000.example. 5M IN A 10.0.15.134
+4000.example. 5M IN A 10.0.15.135
+4000.example. 5M IN A 10.0.15.136
+4000.example. 5M IN A 10.0.15.137
+4000.example. 5M IN A 10.0.15.138
+4000.example. 5M IN A 10.0.15.139
+4000.example. 5M IN A 10.0.15.140
+4000.example. 5M IN A 10.0.15.141
+4000.example. 5M IN A 10.0.15.142
+4000.example. 5M IN A 10.0.15.143
+4000.example. 5M IN A 10.0.15.144
+4000.example. 5M IN A 10.0.15.145
+4000.example. 5M IN A 10.0.15.146
+4000.example. 5M IN A 10.0.15.147
+4000.example. 5M IN A 10.0.15.148
+4000.example. 5M IN A 10.0.15.149
+4000.example. 5M IN A 10.0.15.150
+4000.example. 5M IN A 10.0.15.151
+4000.example. 5M IN A 10.0.15.152
+4000.example. 5M IN A 10.0.15.153
+4000.example. 5M IN A 10.0.15.154
+4000.example. 5M IN A 10.0.15.155
+4000.example. 5M IN A 10.0.15.156
+4000.example. 5M IN A 10.0.15.157
+4000.example. 5M IN A 10.0.15.158
+4000.example. 5M IN A 10.0.15.159
+
+;; AUTHORITY SECTION:
+example. 5M IN NS ns1.example.
+
+;; ADDITIONAL SECTION:
+ns1.example. 5M IN A 10.53.0.1
+
+;; Total query time: 279 msec
+;; FROM: draco to SERVER: 10.53.0.1
+;; WHEN: Fri Jun 23 12:58:20 2000
+;; MSG SIZE sent: 30 rcvd: 64068
+
diff --git a/bin/tests/system/limits/knowngood.dig.out.a-maximum-rrset b/bin/tests/system/limits/knowngood.dig.out.a-maximum-rrset
new file mode 100644
index 0000000..1688e83
--- /dev/null
+++ b/bin/tests/system/limits/knowngood.dig.out.a-maximum-rrset
@@ -0,0 +1,4114 @@
+
+; <<>> DiG 8.2 <<>> a-maximum-rrset.example. @10.53.0.1 a -p
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr aa rd ad; QUERY: 1, ANSWER: 4091, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; a-maximum-rrset.example, type = A, class = IN
+
+;; ANSWER SECTION:
+a-maximum-rrset.example. 5M IN A 10.0.0.0
+a-maximum-rrset.example. 5M IN A 10.0.0.1
+a-maximum-rrset.example. 5M IN A 10.0.0.2
+a-maximum-rrset.example. 5M IN A 10.0.0.3
+a-maximum-rrset.example. 5M IN A 10.0.0.4
+a-maximum-rrset.example. 5M IN A 10.0.0.5
+a-maximum-rrset.example. 5M IN A 10.0.0.6
+a-maximum-rrset.example. 5M IN A 10.0.0.7
+a-maximum-rrset.example. 5M IN A 10.0.0.8
+a-maximum-rrset.example. 5M IN A 10.0.0.9
+a-maximum-rrset.example. 5M IN A 10.0.0.10
+a-maximum-rrset.example. 5M IN A 10.0.0.11
+a-maximum-rrset.example. 5M IN A 10.0.0.12
+a-maximum-rrset.example. 5M IN A 10.0.0.13
+a-maximum-rrset.example. 5M IN A 10.0.0.14
+a-maximum-rrset.example. 5M IN A 10.0.0.15
+a-maximum-rrset.example. 5M IN A 10.0.0.16
+a-maximum-rrset.example. 5M IN A 10.0.0.17
+a-maximum-rrset.example. 5M IN A 10.0.0.18
+a-maximum-rrset.example. 5M IN A 10.0.0.19
+a-maximum-rrset.example. 5M IN A 10.0.0.20
+a-maximum-rrset.example. 5M IN A 10.0.0.21
+a-maximum-rrset.example. 5M IN A 10.0.0.22
+a-maximum-rrset.example. 5M IN A 10.0.0.23
+a-maximum-rrset.example. 5M IN A 10.0.0.24
+a-maximum-rrset.example. 5M IN A 10.0.0.25
+a-maximum-rrset.example. 5M IN A 10.0.0.26
+a-maximum-rrset.example. 5M IN A 10.0.0.27
+a-maximum-rrset.example. 5M IN A 10.0.0.28
+a-maximum-rrset.example. 5M IN A 10.0.0.29
+a-maximum-rrset.example. 5M IN A 10.0.0.30
+a-maximum-rrset.example. 5M IN A 10.0.0.31
+a-maximum-rrset.example. 5M IN A 10.0.0.32
+a-maximum-rrset.example. 5M IN A 10.0.0.33
+a-maximum-rrset.example. 5M IN A 10.0.0.34
+a-maximum-rrset.example. 5M IN A 10.0.0.35
+a-maximum-rrset.example. 5M IN A 10.0.0.36
+a-maximum-rrset.example. 5M IN A 10.0.0.37
+a-maximum-rrset.example. 5M IN A 10.0.0.38
+a-maximum-rrset.example. 5M IN A 10.0.0.39
+a-maximum-rrset.example. 5M IN A 10.0.0.40
+a-maximum-rrset.example. 5M IN A 10.0.0.41
+a-maximum-rrset.example. 5M IN A 10.0.0.42
+a-maximum-rrset.example. 5M IN A 10.0.0.43
+a-maximum-rrset.example. 5M IN A 10.0.0.44
+a-maximum-rrset.example. 5M IN A 10.0.0.45
+a-maximum-rrset.example. 5M IN A 10.0.0.46
+a-maximum-rrset.example. 5M IN A 10.0.0.47
+a-maximum-rrset.example. 5M IN A 10.0.0.48
+a-maximum-rrset.example. 5M IN A 10.0.0.49
+a-maximum-rrset.example. 5M IN A 10.0.0.50
+a-maximum-rrset.example. 5M IN A 10.0.0.51
+a-maximum-rrset.example. 5M IN A 10.0.0.52
+a-maximum-rrset.example. 5M IN A 10.0.0.53
+a-maximum-rrset.example. 5M IN A 10.0.0.54
+a-maximum-rrset.example. 5M IN A 10.0.0.55
+a-maximum-rrset.example. 5M IN A 10.0.0.56
+a-maximum-rrset.example. 5M IN A 10.0.0.57
+a-maximum-rrset.example. 5M IN A 10.0.0.58
+a-maximum-rrset.example. 5M IN A 10.0.0.59
+a-maximum-rrset.example. 5M IN A 10.0.0.60
+a-maximum-rrset.example. 5M IN A 10.0.0.61
+a-maximum-rrset.example. 5M IN A 10.0.0.62
+a-maximum-rrset.example. 5M IN A 10.0.0.63
+a-maximum-rrset.example. 5M IN A 10.0.0.64
+a-maximum-rrset.example. 5M IN A 10.0.0.65
+a-maximum-rrset.example. 5M IN A 10.0.0.66
+a-maximum-rrset.example. 5M IN A 10.0.0.67
+a-maximum-rrset.example. 5M IN A 10.0.0.68
+a-maximum-rrset.example. 5M IN A 10.0.0.69
+a-maximum-rrset.example. 5M IN A 10.0.0.70
+a-maximum-rrset.example. 5M IN A 10.0.0.71
+a-maximum-rrset.example. 5M IN A 10.0.0.72
+a-maximum-rrset.example. 5M IN A 10.0.0.73
+a-maximum-rrset.example. 5M IN A 10.0.0.74
+a-maximum-rrset.example. 5M IN A 10.0.0.75
+a-maximum-rrset.example. 5M IN A 10.0.0.76
+a-maximum-rrset.example. 5M IN A 10.0.0.77
+a-maximum-rrset.example. 5M IN A 10.0.0.78
+a-maximum-rrset.example. 5M IN A 10.0.0.79
+a-maximum-rrset.example. 5M IN A 10.0.0.80
+a-maximum-rrset.example. 5M IN A 10.0.0.81
+a-maximum-rrset.example. 5M IN A 10.0.0.82
+a-maximum-rrset.example. 5M IN A 10.0.0.83
+a-maximum-rrset.example. 5M IN A 10.0.0.84
+a-maximum-rrset.example. 5M IN A 10.0.0.85
+a-maximum-rrset.example. 5M IN A 10.0.0.86
+a-maximum-rrset.example. 5M IN A 10.0.0.87
+a-maximum-rrset.example. 5M IN A 10.0.0.88
+a-maximum-rrset.example. 5M IN A 10.0.0.89
+a-maximum-rrset.example. 5M IN A 10.0.0.90
+a-maximum-rrset.example. 5M IN A 10.0.0.91
+a-maximum-rrset.example. 5M IN A 10.0.0.92
+a-maximum-rrset.example. 5M IN A 10.0.0.93
+a-maximum-rrset.example. 5M IN A 10.0.0.94
+a-maximum-rrset.example. 5M IN A 10.0.0.95
+a-maximum-rrset.example. 5M IN A 10.0.0.96
+a-maximum-rrset.example. 5M IN A 10.0.0.97
+a-maximum-rrset.example. 5M IN A 10.0.0.98
+a-maximum-rrset.example. 5M IN A 10.0.0.99
+a-maximum-rrset.example. 5M IN A 10.0.0.100
+a-maximum-rrset.example. 5M IN A 10.0.0.101
+a-maximum-rrset.example. 5M IN A 10.0.0.102
+a-maximum-rrset.example. 5M IN A 10.0.0.103
+a-maximum-rrset.example. 5M IN A 10.0.0.104
+a-maximum-rrset.example. 5M IN A 10.0.0.105
+a-maximum-rrset.example. 5M IN A 10.0.0.106
+a-maximum-rrset.example. 5M IN A 10.0.0.107
+a-maximum-rrset.example. 5M IN A 10.0.0.108
+a-maximum-rrset.example. 5M IN A 10.0.0.109
+a-maximum-rrset.example. 5M IN A 10.0.0.110
+a-maximum-rrset.example. 5M IN A 10.0.0.111
+a-maximum-rrset.example. 5M IN A 10.0.0.112
+a-maximum-rrset.example. 5M IN A 10.0.0.113
+a-maximum-rrset.example. 5M IN A 10.0.0.114
+a-maximum-rrset.example. 5M IN A 10.0.0.115
+a-maximum-rrset.example. 5M IN A 10.0.0.116
+a-maximum-rrset.example. 5M IN A 10.0.0.117
+a-maximum-rrset.example. 5M IN A 10.0.0.118
+a-maximum-rrset.example. 5M IN A 10.0.0.119
+a-maximum-rrset.example. 5M IN A 10.0.0.120
+a-maximum-rrset.example. 5M IN A 10.0.0.121
+a-maximum-rrset.example. 5M IN A 10.0.0.122
+a-maximum-rrset.example. 5M IN A 10.0.0.123
+a-maximum-rrset.example. 5M IN A 10.0.0.124
+a-maximum-rrset.example. 5M IN A 10.0.0.125
+a-maximum-rrset.example. 5M IN A 10.0.0.126
+a-maximum-rrset.example. 5M IN A 10.0.0.127
+a-maximum-rrset.example. 5M IN A 10.0.0.128
+a-maximum-rrset.example. 5M IN A 10.0.0.129
+a-maximum-rrset.example. 5M IN A 10.0.0.130
+a-maximum-rrset.example. 5M IN A 10.0.0.131
+a-maximum-rrset.example. 5M IN A 10.0.0.132
+a-maximum-rrset.example. 5M IN A 10.0.0.133
+a-maximum-rrset.example. 5M IN A 10.0.0.134
+a-maximum-rrset.example. 5M IN A 10.0.0.135
+a-maximum-rrset.example. 5M IN A 10.0.0.136
+a-maximum-rrset.example. 5M IN A 10.0.0.137
+a-maximum-rrset.example. 5M IN A 10.0.0.138
+a-maximum-rrset.example. 5M IN A 10.0.0.139
+a-maximum-rrset.example. 5M IN A 10.0.0.140
+a-maximum-rrset.example. 5M IN A 10.0.0.141
+a-maximum-rrset.example. 5M IN A 10.0.0.142
+a-maximum-rrset.example. 5M IN A 10.0.0.143
+a-maximum-rrset.example. 5M IN A 10.0.0.144
+a-maximum-rrset.example. 5M IN A 10.0.0.145
+a-maximum-rrset.example. 5M IN A 10.0.0.146
+a-maximum-rrset.example. 5M IN A 10.0.0.147
+a-maximum-rrset.example. 5M IN A 10.0.0.148
+a-maximum-rrset.example. 5M IN A 10.0.0.149
+a-maximum-rrset.example. 5M IN A 10.0.0.150
+a-maximum-rrset.example. 5M IN A 10.0.0.151
+a-maximum-rrset.example. 5M IN A 10.0.0.152
+a-maximum-rrset.example. 5M IN A 10.0.0.153
+a-maximum-rrset.example. 5M IN A 10.0.0.154
+a-maximum-rrset.example. 5M IN A 10.0.0.155
+a-maximum-rrset.example. 5M IN A 10.0.0.156
+a-maximum-rrset.example. 5M IN A 10.0.0.157
+a-maximum-rrset.example. 5M IN A 10.0.0.158
+a-maximum-rrset.example. 5M IN A 10.0.0.159
+a-maximum-rrset.example. 5M IN A 10.0.0.160
+a-maximum-rrset.example. 5M IN A 10.0.0.161
+a-maximum-rrset.example. 5M IN A 10.0.0.162
+a-maximum-rrset.example. 5M IN A 10.0.0.163
+a-maximum-rrset.example. 5M IN A 10.0.0.164
+a-maximum-rrset.example. 5M IN A 10.0.0.165
+a-maximum-rrset.example. 5M IN A 10.0.0.166
+a-maximum-rrset.example. 5M IN A 10.0.0.167
+a-maximum-rrset.example. 5M IN A 10.0.0.168
+a-maximum-rrset.example. 5M IN A 10.0.0.169
+a-maximum-rrset.example. 5M IN A 10.0.0.170
+a-maximum-rrset.example. 5M IN A 10.0.0.171
+a-maximum-rrset.example. 5M IN A 10.0.0.172
+a-maximum-rrset.example. 5M IN A 10.0.0.173
+a-maximum-rrset.example. 5M IN A 10.0.0.174
+a-maximum-rrset.example. 5M IN A 10.0.0.175
+a-maximum-rrset.example. 5M IN A 10.0.0.176
+a-maximum-rrset.example. 5M IN A 10.0.0.177
+a-maximum-rrset.example. 5M IN A 10.0.0.178
+a-maximum-rrset.example. 5M IN A 10.0.0.179
+a-maximum-rrset.example. 5M IN A 10.0.0.180
+a-maximum-rrset.example. 5M IN A 10.0.0.181
+a-maximum-rrset.example. 5M IN A 10.0.0.182
+a-maximum-rrset.example. 5M IN A 10.0.0.183
+a-maximum-rrset.example. 5M IN A 10.0.0.184
+a-maximum-rrset.example. 5M IN A 10.0.0.185
+a-maximum-rrset.example. 5M IN A 10.0.0.186
+a-maximum-rrset.example. 5M IN A 10.0.0.187
+a-maximum-rrset.example. 5M IN A 10.0.0.188
+a-maximum-rrset.example. 5M IN A 10.0.0.189
+a-maximum-rrset.example. 5M IN A 10.0.0.190
+a-maximum-rrset.example. 5M IN A 10.0.0.191
+a-maximum-rrset.example. 5M IN A 10.0.0.192
+a-maximum-rrset.example. 5M IN A 10.0.0.193
+a-maximum-rrset.example. 5M IN A 10.0.0.194
+a-maximum-rrset.example. 5M IN A 10.0.0.195
+a-maximum-rrset.example. 5M IN A 10.0.0.196
+a-maximum-rrset.example. 5M IN A 10.0.0.197
+a-maximum-rrset.example. 5M IN A 10.0.0.198
+a-maximum-rrset.example. 5M IN A 10.0.0.199
+a-maximum-rrset.example. 5M IN A 10.0.0.200
+a-maximum-rrset.example. 5M IN A 10.0.0.201
+a-maximum-rrset.example. 5M IN A 10.0.0.202
+a-maximum-rrset.example. 5M IN A 10.0.0.203
+a-maximum-rrset.example. 5M IN A 10.0.0.204
+a-maximum-rrset.example. 5M IN A 10.0.0.205
+a-maximum-rrset.example. 5M IN A 10.0.0.206
+a-maximum-rrset.example. 5M IN A 10.0.0.207
+a-maximum-rrset.example. 5M IN A 10.0.0.208
+a-maximum-rrset.example. 5M IN A 10.0.0.209
+a-maximum-rrset.example. 5M IN A 10.0.0.210
+a-maximum-rrset.example. 5M IN A 10.0.0.211
+a-maximum-rrset.example. 5M IN A 10.0.0.212
+a-maximum-rrset.example. 5M IN A 10.0.0.213
+a-maximum-rrset.example. 5M IN A 10.0.0.214
+a-maximum-rrset.example. 5M IN A 10.0.0.215
+a-maximum-rrset.example. 5M IN A 10.0.0.216
+a-maximum-rrset.example. 5M IN A 10.0.0.217
+a-maximum-rrset.example. 5M IN A 10.0.0.218
+a-maximum-rrset.example. 5M IN A 10.0.0.219
+a-maximum-rrset.example. 5M IN A 10.0.0.220
+a-maximum-rrset.example. 5M IN A 10.0.0.221
+a-maximum-rrset.example. 5M IN A 10.0.0.222
+a-maximum-rrset.example. 5M IN A 10.0.0.223
+a-maximum-rrset.example. 5M IN A 10.0.0.224
+a-maximum-rrset.example. 5M IN A 10.0.0.225
+a-maximum-rrset.example. 5M IN A 10.0.0.226
+a-maximum-rrset.example. 5M IN A 10.0.0.227
+a-maximum-rrset.example. 5M IN A 10.0.0.228
+a-maximum-rrset.example. 5M IN A 10.0.0.229
+a-maximum-rrset.example. 5M IN A 10.0.0.230
+a-maximum-rrset.example. 5M IN A 10.0.0.231
+a-maximum-rrset.example. 5M IN A 10.0.0.232
+a-maximum-rrset.example. 5M IN A 10.0.0.233
+a-maximum-rrset.example. 5M IN A 10.0.0.234
+a-maximum-rrset.example. 5M IN A 10.0.0.235
+a-maximum-rrset.example. 5M IN A 10.0.0.236
+a-maximum-rrset.example. 5M IN A 10.0.0.237
+a-maximum-rrset.example. 5M IN A 10.0.0.238
+a-maximum-rrset.example. 5M IN A 10.0.0.239
+a-maximum-rrset.example. 5M IN A 10.0.0.240
+a-maximum-rrset.example. 5M IN A 10.0.0.241
+a-maximum-rrset.example. 5M IN A 10.0.0.242
+a-maximum-rrset.example. 5M IN A 10.0.0.243
+a-maximum-rrset.example. 5M IN A 10.0.0.244
+a-maximum-rrset.example. 5M IN A 10.0.0.245
+a-maximum-rrset.example. 5M IN A 10.0.0.246
+a-maximum-rrset.example. 5M IN A 10.0.0.247
+a-maximum-rrset.example. 5M IN A 10.0.0.248
+a-maximum-rrset.example. 5M IN A 10.0.0.249
+a-maximum-rrset.example. 5M IN A 10.0.0.250
+a-maximum-rrset.example. 5M IN A 10.0.0.251
+a-maximum-rrset.example. 5M IN A 10.0.0.252
+a-maximum-rrset.example. 5M IN A 10.0.0.253
+a-maximum-rrset.example. 5M IN A 10.0.0.254
+a-maximum-rrset.example. 5M IN A 10.0.0.255
+a-maximum-rrset.example. 5M IN A 10.0.1.0
+a-maximum-rrset.example. 5M IN A 10.0.1.1
+a-maximum-rrset.example. 5M IN A 10.0.1.2
+a-maximum-rrset.example. 5M IN A 10.0.1.3
+a-maximum-rrset.example. 5M IN A 10.0.1.4
+a-maximum-rrset.example. 5M IN A 10.0.1.5
+a-maximum-rrset.example. 5M IN A 10.0.1.6
+a-maximum-rrset.example. 5M IN A 10.0.1.7
+a-maximum-rrset.example. 5M IN A 10.0.1.8
+a-maximum-rrset.example. 5M IN A 10.0.1.9
+a-maximum-rrset.example. 5M IN A 10.0.1.10
+a-maximum-rrset.example. 5M IN A 10.0.1.11
+a-maximum-rrset.example. 5M IN A 10.0.1.12
+a-maximum-rrset.example. 5M IN A 10.0.1.13
+a-maximum-rrset.example. 5M IN A 10.0.1.14
+a-maximum-rrset.example. 5M IN A 10.0.1.15
+a-maximum-rrset.example. 5M IN A 10.0.1.16
+a-maximum-rrset.example. 5M IN A 10.0.1.17
+a-maximum-rrset.example. 5M IN A 10.0.1.18
+a-maximum-rrset.example. 5M IN A 10.0.1.19
+a-maximum-rrset.example. 5M IN A 10.0.1.20
+a-maximum-rrset.example. 5M IN A 10.0.1.21
+a-maximum-rrset.example. 5M IN A 10.0.1.22
+a-maximum-rrset.example. 5M IN A 10.0.1.23
+a-maximum-rrset.example. 5M IN A 10.0.1.24
+a-maximum-rrset.example. 5M IN A 10.0.1.25
+a-maximum-rrset.example. 5M IN A 10.0.1.26
+a-maximum-rrset.example. 5M IN A 10.0.1.27
+a-maximum-rrset.example. 5M IN A 10.0.1.28
+a-maximum-rrset.example. 5M IN A 10.0.1.29
+a-maximum-rrset.example. 5M IN A 10.0.1.30
+a-maximum-rrset.example. 5M IN A 10.0.1.31
+a-maximum-rrset.example. 5M IN A 10.0.1.32
+a-maximum-rrset.example. 5M IN A 10.0.1.33
+a-maximum-rrset.example. 5M IN A 10.0.1.34
+a-maximum-rrset.example. 5M IN A 10.0.1.35
+a-maximum-rrset.example. 5M IN A 10.0.1.36
+a-maximum-rrset.example. 5M IN A 10.0.1.37
+a-maximum-rrset.example. 5M IN A 10.0.1.38
+a-maximum-rrset.example. 5M IN A 10.0.1.39
+a-maximum-rrset.example. 5M IN A 10.0.1.40
+a-maximum-rrset.example. 5M IN A 10.0.1.41
+a-maximum-rrset.example. 5M IN A 10.0.1.42
+a-maximum-rrset.example. 5M IN A 10.0.1.43
+a-maximum-rrset.example. 5M IN A 10.0.1.44
+a-maximum-rrset.example. 5M IN A 10.0.1.45
+a-maximum-rrset.example. 5M IN A 10.0.1.46
+a-maximum-rrset.example. 5M IN A 10.0.1.47
+a-maximum-rrset.example. 5M IN A 10.0.1.48
+a-maximum-rrset.example. 5M IN A 10.0.1.49
+a-maximum-rrset.example. 5M IN A 10.0.1.50
+a-maximum-rrset.example. 5M IN A 10.0.1.51
+a-maximum-rrset.example. 5M IN A 10.0.1.52
+a-maximum-rrset.example. 5M IN A 10.0.1.53
+a-maximum-rrset.example. 5M IN A 10.0.1.54
+a-maximum-rrset.example. 5M IN A 10.0.1.55
+a-maximum-rrset.example. 5M IN A 10.0.1.56
+a-maximum-rrset.example. 5M IN A 10.0.1.57
+a-maximum-rrset.example. 5M IN A 10.0.1.58
+a-maximum-rrset.example. 5M IN A 10.0.1.59
+a-maximum-rrset.example. 5M IN A 10.0.1.60
+a-maximum-rrset.example. 5M IN A 10.0.1.61
+a-maximum-rrset.example. 5M IN A 10.0.1.62
+a-maximum-rrset.example. 5M IN A 10.0.1.63
+a-maximum-rrset.example. 5M IN A 10.0.1.64
+a-maximum-rrset.example. 5M IN A 10.0.1.65
+a-maximum-rrset.example. 5M IN A 10.0.1.66
+a-maximum-rrset.example. 5M IN A 10.0.1.67
+a-maximum-rrset.example. 5M IN A 10.0.1.68
+a-maximum-rrset.example. 5M IN A 10.0.1.69
+a-maximum-rrset.example. 5M IN A 10.0.1.70
+a-maximum-rrset.example. 5M IN A 10.0.1.71
+a-maximum-rrset.example. 5M IN A 10.0.1.72
+a-maximum-rrset.example. 5M IN A 10.0.1.73
+a-maximum-rrset.example. 5M IN A 10.0.1.74
+a-maximum-rrset.example. 5M IN A 10.0.1.75
+a-maximum-rrset.example. 5M IN A 10.0.1.76
+a-maximum-rrset.example. 5M IN A 10.0.1.77
+a-maximum-rrset.example. 5M IN A 10.0.1.78
+a-maximum-rrset.example. 5M IN A 10.0.1.79
+a-maximum-rrset.example. 5M IN A 10.0.1.80
+a-maximum-rrset.example. 5M IN A 10.0.1.81
+a-maximum-rrset.example. 5M IN A 10.0.1.82
+a-maximum-rrset.example. 5M IN A 10.0.1.83
+a-maximum-rrset.example. 5M IN A 10.0.1.84
+a-maximum-rrset.example. 5M IN A 10.0.1.85
+a-maximum-rrset.example. 5M IN A 10.0.1.86
+a-maximum-rrset.example. 5M IN A 10.0.1.87
+a-maximum-rrset.example. 5M IN A 10.0.1.88
+a-maximum-rrset.example. 5M IN A 10.0.1.89
+a-maximum-rrset.example. 5M IN A 10.0.1.90
+a-maximum-rrset.example. 5M IN A 10.0.1.91
+a-maximum-rrset.example. 5M IN A 10.0.1.92
+a-maximum-rrset.example. 5M IN A 10.0.1.93
+a-maximum-rrset.example. 5M IN A 10.0.1.94
+a-maximum-rrset.example. 5M IN A 10.0.1.95
+a-maximum-rrset.example. 5M IN A 10.0.1.96
+a-maximum-rrset.example. 5M IN A 10.0.1.97
+a-maximum-rrset.example. 5M IN A 10.0.1.98
+a-maximum-rrset.example. 5M IN A 10.0.1.99
+a-maximum-rrset.example. 5M IN A 10.0.1.100
+a-maximum-rrset.example. 5M IN A 10.0.1.101
+a-maximum-rrset.example. 5M IN A 10.0.1.102
+a-maximum-rrset.example. 5M IN A 10.0.1.103
+a-maximum-rrset.example. 5M IN A 10.0.1.104
+a-maximum-rrset.example. 5M IN A 10.0.1.105
+a-maximum-rrset.example. 5M IN A 10.0.1.106
+a-maximum-rrset.example. 5M IN A 10.0.1.107
+a-maximum-rrset.example. 5M IN A 10.0.1.108
+a-maximum-rrset.example. 5M IN A 10.0.1.109
+a-maximum-rrset.example. 5M IN A 10.0.1.110
+a-maximum-rrset.example. 5M IN A 10.0.1.111
+a-maximum-rrset.example. 5M IN A 10.0.1.112
+a-maximum-rrset.example. 5M IN A 10.0.1.113
+a-maximum-rrset.example. 5M IN A 10.0.1.114
+a-maximum-rrset.example. 5M IN A 10.0.1.115
+a-maximum-rrset.example. 5M IN A 10.0.1.116
+a-maximum-rrset.example. 5M IN A 10.0.1.117
+a-maximum-rrset.example. 5M IN A 10.0.1.118
+a-maximum-rrset.example. 5M IN A 10.0.1.119
+a-maximum-rrset.example. 5M IN A 10.0.1.120
+a-maximum-rrset.example. 5M IN A 10.0.1.121
+a-maximum-rrset.example. 5M IN A 10.0.1.122
+a-maximum-rrset.example. 5M IN A 10.0.1.123
+a-maximum-rrset.example. 5M IN A 10.0.1.124
+a-maximum-rrset.example. 5M IN A 10.0.1.125
+a-maximum-rrset.example. 5M IN A 10.0.1.126
+a-maximum-rrset.example. 5M IN A 10.0.1.127
+a-maximum-rrset.example. 5M IN A 10.0.1.128
+a-maximum-rrset.example. 5M IN A 10.0.1.129
+a-maximum-rrset.example. 5M IN A 10.0.1.130
+a-maximum-rrset.example. 5M IN A 10.0.1.131
+a-maximum-rrset.example. 5M IN A 10.0.1.132
+a-maximum-rrset.example. 5M IN A 10.0.1.133
+a-maximum-rrset.example. 5M IN A 10.0.1.134
+a-maximum-rrset.example. 5M IN A 10.0.1.135
+a-maximum-rrset.example. 5M IN A 10.0.1.136
+a-maximum-rrset.example. 5M IN A 10.0.1.137
+a-maximum-rrset.example. 5M IN A 10.0.1.138
+a-maximum-rrset.example. 5M IN A 10.0.1.139
+a-maximum-rrset.example. 5M IN A 10.0.1.140
+a-maximum-rrset.example. 5M IN A 10.0.1.141
+a-maximum-rrset.example. 5M IN A 10.0.1.142
+a-maximum-rrset.example. 5M IN A 10.0.1.143
+a-maximum-rrset.example. 5M IN A 10.0.1.144
+a-maximum-rrset.example. 5M IN A 10.0.1.145
+a-maximum-rrset.example. 5M IN A 10.0.1.146
+a-maximum-rrset.example. 5M IN A 10.0.1.147
+a-maximum-rrset.example. 5M IN A 10.0.1.148
+a-maximum-rrset.example. 5M IN A 10.0.1.149
+a-maximum-rrset.example. 5M IN A 10.0.1.150
+a-maximum-rrset.example. 5M IN A 10.0.1.151
+a-maximum-rrset.example. 5M IN A 10.0.1.152
+a-maximum-rrset.example. 5M IN A 10.0.1.153
+a-maximum-rrset.example. 5M IN A 10.0.1.154
+a-maximum-rrset.example. 5M IN A 10.0.1.155
+a-maximum-rrset.example. 5M IN A 10.0.1.156
+a-maximum-rrset.example. 5M IN A 10.0.1.157
+a-maximum-rrset.example. 5M IN A 10.0.1.158
+a-maximum-rrset.example. 5M IN A 10.0.1.159
+a-maximum-rrset.example. 5M IN A 10.0.1.160
+a-maximum-rrset.example. 5M IN A 10.0.1.161
+a-maximum-rrset.example. 5M IN A 10.0.1.162
+a-maximum-rrset.example. 5M IN A 10.0.1.163
+a-maximum-rrset.example. 5M IN A 10.0.1.164
+a-maximum-rrset.example. 5M IN A 10.0.1.165
+a-maximum-rrset.example. 5M IN A 10.0.1.166
+a-maximum-rrset.example. 5M IN A 10.0.1.167
+a-maximum-rrset.example. 5M IN A 10.0.1.168
+a-maximum-rrset.example. 5M IN A 10.0.1.169
+a-maximum-rrset.example. 5M IN A 10.0.1.170
+a-maximum-rrset.example. 5M IN A 10.0.1.171
+a-maximum-rrset.example. 5M IN A 10.0.1.172
+a-maximum-rrset.example. 5M IN A 10.0.1.173
+a-maximum-rrset.example. 5M IN A 10.0.1.174
+a-maximum-rrset.example. 5M IN A 10.0.1.175
+a-maximum-rrset.example. 5M IN A 10.0.1.176
+a-maximum-rrset.example. 5M IN A 10.0.1.177
+a-maximum-rrset.example. 5M IN A 10.0.1.178
+a-maximum-rrset.example. 5M IN A 10.0.1.179
+a-maximum-rrset.example. 5M IN A 10.0.1.180
+a-maximum-rrset.example. 5M IN A 10.0.1.181
+a-maximum-rrset.example. 5M IN A 10.0.1.182
+a-maximum-rrset.example. 5M IN A 10.0.1.183
+a-maximum-rrset.example. 5M IN A 10.0.1.184
+a-maximum-rrset.example. 5M IN A 10.0.1.185
+a-maximum-rrset.example. 5M IN A 10.0.1.186
+a-maximum-rrset.example. 5M IN A 10.0.1.187
+a-maximum-rrset.example. 5M IN A 10.0.1.188
+a-maximum-rrset.example. 5M IN A 10.0.1.189
+a-maximum-rrset.example. 5M IN A 10.0.1.190
+a-maximum-rrset.example. 5M IN A 10.0.1.191
+a-maximum-rrset.example. 5M IN A 10.0.1.192
+a-maximum-rrset.example. 5M IN A 10.0.1.193
+a-maximum-rrset.example. 5M IN A 10.0.1.194
+a-maximum-rrset.example. 5M IN A 10.0.1.195
+a-maximum-rrset.example. 5M IN A 10.0.1.196
+a-maximum-rrset.example. 5M IN A 10.0.1.197
+a-maximum-rrset.example. 5M IN A 10.0.1.198
+a-maximum-rrset.example. 5M IN A 10.0.1.199
+a-maximum-rrset.example. 5M IN A 10.0.1.200
+a-maximum-rrset.example. 5M IN A 10.0.1.201
+a-maximum-rrset.example. 5M IN A 10.0.1.202
+a-maximum-rrset.example. 5M IN A 10.0.1.203
+a-maximum-rrset.example. 5M IN A 10.0.1.204
+a-maximum-rrset.example. 5M IN A 10.0.1.205
+a-maximum-rrset.example. 5M IN A 10.0.1.206
+a-maximum-rrset.example. 5M IN A 10.0.1.207
+a-maximum-rrset.example. 5M IN A 10.0.1.208
+a-maximum-rrset.example. 5M IN A 10.0.1.209
+a-maximum-rrset.example. 5M IN A 10.0.1.210
+a-maximum-rrset.example. 5M IN A 10.0.1.211
+a-maximum-rrset.example. 5M IN A 10.0.1.212
+a-maximum-rrset.example. 5M IN A 10.0.1.213
+a-maximum-rrset.example. 5M IN A 10.0.1.214
+a-maximum-rrset.example. 5M IN A 10.0.1.215
+a-maximum-rrset.example. 5M IN A 10.0.1.216
+a-maximum-rrset.example. 5M IN A 10.0.1.217
+a-maximum-rrset.example. 5M IN A 10.0.1.218
+a-maximum-rrset.example. 5M IN A 10.0.1.219
+a-maximum-rrset.example. 5M IN A 10.0.1.220
+a-maximum-rrset.example. 5M IN A 10.0.1.221
+a-maximum-rrset.example. 5M IN A 10.0.1.222
+a-maximum-rrset.example. 5M IN A 10.0.1.223
+a-maximum-rrset.example. 5M IN A 10.0.1.224
+a-maximum-rrset.example. 5M IN A 10.0.1.225
+a-maximum-rrset.example. 5M IN A 10.0.1.226
+a-maximum-rrset.example. 5M IN A 10.0.1.227
+a-maximum-rrset.example. 5M IN A 10.0.1.228
+a-maximum-rrset.example. 5M IN A 10.0.1.229
+a-maximum-rrset.example. 5M IN A 10.0.1.230
+a-maximum-rrset.example. 5M IN A 10.0.1.231
+a-maximum-rrset.example. 5M IN A 10.0.1.232
+a-maximum-rrset.example. 5M IN A 10.0.1.233
+a-maximum-rrset.example. 5M IN A 10.0.1.234
+a-maximum-rrset.example. 5M IN A 10.0.1.235
+a-maximum-rrset.example. 5M IN A 10.0.1.236
+a-maximum-rrset.example. 5M IN A 10.0.1.237
+a-maximum-rrset.example. 5M IN A 10.0.1.238
+a-maximum-rrset.example. 5M IN A 10.0.1.239
+a-maximum-rrset.example. 5M IN A 10.0.1.240
+a-maximum-rrset.example. 5M IN A 10.0.1.241
+a-maximum-rrset.example. 5M IN A 10.0.1.242
+a-maximum-rrset.example. 5M IN A 10.0.1.243
+a-maximum-rrset.example. 5M IN A 10.0.1.244
+a-maximum-rrset.example. 5M IN A 10.0.1.245
+a-maximum-rrset.example. 5M IN A 10.0.1.246
+a-maximum-rrset.example. 5M IN A 10.0.1.247
+a-maximum-rrset.example. 5M IN A 10.0.1.248
+a-maximum-rrset.example. 5M IN A 10.0.1.249
+a-maximum-rrset.example. 5M IN A 10.0.1.250
+a-maximum-rrset.example. 5M IN A 10.0.1.251
+a-maximum-rrset.example. 5M IN A 10.0.1.252
+a-maximum-rrset.example. 5M IN A 10.0.1.253
+a-maximum-rrset.example. 5M IN A 10.0.1.254
+a-maximum-rrset.example. 5M IN A 10.0.1.255
+a-maximum-rrset.example. 5M IN A 10.0.2.0
+a-maximum-rrset.example. 5M IN A 10.0.2.1
+a-maximum-rrset.example. 5M IN A 10.0.2.2
+a-maximum-rrset.example. 5M IN A 10.0.2.3
+a-maximum-rrset.example. 5M IN A 10.0.2.4
+a-maximum-rrset.example. 5M IN A 10.0.2.5
+a-maximum-rrset.example. 5M IN A 10.0.2.6
+a-maximum-rrset.example. 5M IN A 10.0.2.7
+a-maximum-rrset.example. 5M IN A 10.0.2.8
+a-maximum-rrset.example. 5M IN A 10.0.2.9
+a-maximum-rrset.example. 5M IN A 10.0.2.10
+a-maximum-rrset.example. 5M IN A 10.0.2.11
+a-maximum-rrset.example. 5M IN A 10.0.2.12
+a-maximum-rrset.example. 5M IN A 10.0.2.13
+a-maximum-rrset.example. 5M IN A 10.0.2.14
+a-maximum-rrset.example. 5M IN A 10.0.2.15
+a-maximum-rrset.example. 5M IN A 10.0.2.16
+a-maximum-rrset.example. 5M IN A 10.0.2.17
+a-maximum-rrset.example. 5M IN A 10.0.2.18
+a-maximum-rrset.example. 5M IN A 10.0.2.19
+a-maximum-rrset.example. 5M IN A 10.0.2.20
+a-maximum-rrset.example. 5M IN A 10.0.2.21
+a-maximum-rrset.example. 5M IN A 10.0.2.22
+a-maximum-rrset.example. 5M IN A 10.0.2.23
+a-maximum-rrset.example. 5M IN A 10.0.2.24
+a-maximum-rrset.example. 5M IN A 10.0.2.25
+a-maximum-rrset.example. 5M IN A 10.0.2.26
+a-maximum-rrset.example. 5M IN A 10.0.2.27
+a-maximum-rrset.example. 5M IN A 10.0.2.28
+a-maximum-rrset.example. 5M IN A 10.0.2.29
+a-maximum-rrset.example. 5M IN A 10.0.2.30
+a-maximum-rrset.example. 5M IN A 10.0.2.31
+a-maximum-rrset.example. 5M IN A 10.0.2.32
+a-maximum-rrset.example. 5M IN A 10.0.2.33
+a-maximum-rrset.example. 5M IN A 10.0.2.34
+a-maximum-rrset.example. 5M IN A 10.0.2.35
+a-maximum-rrset.example. 5M IN A 10.0.2.36
+a-maximum-rrset.example. 5M IN A 10.0.2.37
+a-maximum-rrset.example. 5M IN A 10.0.2.38
+a-maximum-rrset.example. 5M IN A 10.0.2.39
+a-maximum-rrset.example. 5M IN A 10.0.2.40
+a-maximum-rrset.example. 5M IN A 10.0.2.41
+a-maximum-rrset.example. 5M IN A 10.0.2.42
+a-maximum-rrset.example. 5M IN A 10.0.2.43
+a-maximum-rrset.example. 5M IN A 10.0.2.44
+a-maximum-rrset.example. 5M IN A 10.0.2.45
+a-maximum-rrset.example. 5M IN A 10.0.2.46
+a-maximum-rrset.example. 5M IN A 10.0.2.47
+a-maximum-rrset.example. 5M IN A 10.0.2.48
+a-maximum-rrset.example. 5M IN A 10.0.2.49
+a-maximum-rrset.example. 5M IN A 10.0.2.50
+a-maximum-rrset.example. 5M IN A 10.0.2.51
+a-maximum-rrset.example. 5M IN A 10.0.2.52
+a-maximum-rrset.example. 5M IN A 10.0.2.53
+a-maximum-rrset.example. 5M IN A 10.0.2.54
+a-maximum-rrset.example. 5M IN A 10.0.2.55
+a-maximum-rrset.example. 5M IN A 10.0.2.56
+a-maximum-rrset.example. 5M IN A 10.0.2.57
+a-maximum-rrset.example. 5M IN A 10.0.2.58
+a-maximum-rrset.example. 5M IN A 10.0.2.59
+a-maximum-rrset.example. 5M IN A 10.0.2.60
+a-maximum-rrset.example. 5M IN A 10.0.2.61
+a-maximum-rrset.example. 5M IN A 10.0.2.62
+a-maximum-rrset.example. 5M IN A 10.0.2.63
+a-maximum-rrset.example. 5M IN A 10.0.2.64
+a-maximum-rrset.example. 5M IN A 10.0.2.65
+a-maximum-rrset.example. 5M IN A 10.0.2.66
+a-maximum-rrset.example. 5M IN A 10.0.2.67
+a-maximum-rrset.example. 5M IN A 10.0.2.68
+a-maximum-rrset.example. 5M IN A 10.0.2.69
+a-maximum-rrset.example. 5M IN A 10.0.2.70
+a-maximum-rrset.example. 5M IN A 10.0.2.71
+a-maximum-rrset.example. 5M IN A 10.0.2.72
+a-maximum-rrset.example. 5M IN A 10.0.2.73
+a-maximum-rrset.example. 5M IN A 10.0.2.74
+a-maximum-rrset.example. 5M IN A 10.0.2.75
+a-maximum-rrset.example. 5M IN A 10.0.2.76
+a-maximum-rrset.example. 5M IN A 10.0.2.77
+a-maximum-rrset.example. 5M IN A 10.0.2.78
+a-maximum-rrset.example. 5M IN A 10.0.2.79
+a-maximum-rrset.example. 5M IN A 10.0.2.80
+a-maximum-rrset.example. 5M IN A 10.0.2.81
+a-maximum-rrset.example. 5M IN A 10.0.2.82
+a-maximum-rrset.example. 5M IN A 10.0.2.83
+a-maximum-rrset.example. 5M IN A 10.0.2.84
+a-maximum-rrset.example. 5M IN A 10.0.2.85
+a-maximum-rrset.example. 5M IN A 10.0.2.86
+a-maximum-rrset.example. 5M IN A 10.0.2.87
+a-maximum-rrset.example. 5M IN A 10.0.2.88
+a-maximum-rrset.example. 5M IN A 10.0.2.89
+a-maximum-rrset.example. 5M IN A 10.0.2.90
+a-maximum-rrset.example. 5M IN A 10.0.2.91
+a-maximum-rrset.example. 5M IN A 10.0.2.92
+a-maximum-rrset.example. 5M IN A 10.0.2.93
+a-maximum-rrset.example. 5M IN A 10.0.2.94
+a-maximum-rrset.example. 5M IN A 10.0.2.95
+a-maximum-rrset.example. 5M IN A 10.0.2.96
+a-maximum-rrset.example. 5M IN A 10.0.2.97
+a-maximum-rrset.example. 5M IN A 10.0.2.98
+a-maximum-rrset.example. 5M IN A 10.0.2.99
+a-maximum-rrset.example. 5M IN A 10.0.2.100
+a-maximum-rrset.example. 5M IN A 10.0.2.101
+a-maximum-rrset.example. 5M IN A 10.0.2.102
+a-maximum-rrset.example. 5M IN A 10.0.2.103
+a-maximum-rrset.example. 5M IN A 10.0.2.104
+a-maximum-rrset.example. 5M IN A 10.0.2.105
+a-maximum-rrset.example. 5M IN A 10.0.2.106
+a-maximum-rrset.example. 5M IN A 10.0.2.107
+a-maximum-rrset.example. 5M IN A 10.0.2.108
+a-maximum-rrset.example. 5M IN A 10.0.2.109
+a-maximum-rrset.example. 5M IN A 10.0.2.110
+a-maximum-rrset.example. 5M IN A 10.0.2.111
+a-maximum-rrset.example. 5M IN A 10.0.2.112
+a-maximum-rrset.example. 5M IN A 10.0.2.113
+a-maximum-rrset.example. 5M IN A 10.0.2.114
+a-maximum-rrset.example. 5M IN A 10.0.2.115
+a-maximum-rrset.example. 5M IN A 10.0.2.116
+a-maximum-rrset.example. 5M IN A 10.0.2.117
+a-maximum-rrset.example. 5M IN A 10.0.2.118
+a-maximum-rrset.example. 5M IN A 10.0.2.119
+a-maximum-rrset.example. 5M IN A 10.0.2.120
+a-maximum-rrset.example. 5M IN A 10.0.2.121
+a-maximum-rrset.example. 5M IN A 10.0.2.122
+a-maximum-rrset.example. 5M IN A 10.0.2.123
+a-maximum-rrset.example. 5M IN A 10.0.2.124
+a-maximum-rrset.example. 5M IN A 10.0.2.125
+a-maximum-rrset.example. 5M IN A 10.0.2.126
+a-maximum-rrset.example. 5M IN A 10.0.2.127
+a-maximum-rrset.example. 5M IN A 10.0.2.128
+a-maximum-rrset.example. 5M IN A 10.0.2.129
+a-maximum-rrset.example. 5M IN A 10.0.2.130
+a-maximum-rrset.example. 5M IN A 10.0.2.131
+a-maximum-rrset.example. 5M IN A 10.0.2.132
+a-maximum-rrset.example. 5M IN A 10.0.2.133
+a-maximum-rrset.example. 5M IN A 10.0.2.134
+a-maximum-rrset.example. 5M IN A 10.0.2.135
+a-maximum-rrset.example. 5M IN A 10.0.2.136
+a-maximum-rrset.example. 5M IN A 10.0.2.137
+a-maximum-rrset.example. 5M IN A 10.0.2.138
+a-maximum-rrset.example. 5M IN A 10.0.2.139
+a-maximum-rrset.example. 5M IN A 10.0.2.140
+a-maximum-rrset.example. 5M IN A 10.0.2.141
+a-maximum-rrset.example. 5M IN A 10.0.2.142
+a-maximum-rrset.example. 5M IN A 10.0.2.143
+a-maximum-rrset.example. 5M IN A 10.0.2.144
+a-maximum-rrset.example. 5M IN A 10.0.2.145
+a-maximum-rrset.example. 5M IN A 10.0.2.146
+a-maximum-rrset.example. 5M IN A 10.0.2.147
+a-maximum-rrset.example. 5M IN A 10.0.2.148
+a-maximum-rrset.example. 5M IN A 10.0.2.149
+a-maximum-rrset.example. 5M IN A 10.0.2.150
+a-maximum-rrset.example. 5M IN A 10.0.2.151
+a-maximum-rrset.example. 5M IN A 10.0.2.152
+a-maximum-rrset.example. 5M IN A 10.0.2.153
+a-maximum-rrset.example. 5M IN A 10.0.2.154
+a-maximum-rrset.example. 5M IN A 10.0.2.155
+a-maximum-rrset.example. 5M IN A 10.0.2.156
+a-maximum-rrset.example. 5M IN A 10.0.2.157
+a-maximum-rrset.example. 5M IN A 10.0.2.158
+a-maximum-rrset.example. 5M IN A 10.0.2.159
+a-maximum-rrset.example. 5M IN A 10.0.2.160
+a-maximum-rrset.example. 5M IN A 10.0.2.161
+a-maximum-rrset.example. 5M IN A 10.0.2.162
+a-maximum-rrset.example. 5M IN A 10.0.2.163
+a-maximum-rrset.example. 5M IN A 10.0.2.164
+a-maximum-rrset.example. 5M IN A 10.0.2.165
+a-maximum-rrset.example. 5M IN A 10.0.2.166
+a-maximum-rrset.example. 5M IN A 10.0.2.167
+a-maximum-rrset.example. 5M IN A 10.0.2.168
+a-maximum-rrset.example. 5M IN A 10.0.2.169
+a-maximum-rrset.example. 5M IN A 10.0.2.170
+a-maximum-rrset.example. 5M IN A 10.0.2.171
+a-maximum-rrset.example. 5M IN A 10.0.2.172
+a-maximum-rrset.example. 5M IN A 10.0.2.173
+a-maximum-rrset.example. 5M IN A 10.0.2.174
+a-maximum-rrset.example. 5M IN A 10.0.2.175
+a-maximum-rrset.example. 5M IN A 10.0.2.176
+a-maximum-rrset.example. 5M IN A 10.0.2.177
+a-maximum-rrset.example. 5M IN A 10.0.2.178
+a-maximum-rrset.example. 5M IN A 10.0.2.179
+a-maximum-rrset.example. 5M IN A 10.0.2.180
+a-maximum-rrset.example. 5M IN A 10.0.2.181
+a-maximum-rrset.example. 5M IN A 10.0.2.182
+a-maximum-rrset.example. 5M IN A 10.0.2.183
+a-maximum-rrset.example. 5M IN A 10.0.2.184
+a-maximum-rrset.example. 5M IN A 10.0.2.185
+a-maximum-rrset.example. 5M IN A 10.0.2.186
+a-maximum-rrset.example. 5M IN A 10.0.2.187
+a-maximum-rrset.example. 5M IN A 10.0.2.188
+a-maximum-rrset.example. 5M IN A 10.0.2.189
+a-maximum-rrset.example. 5M IN A 10.0.2.190
+a-maximum-rrset.example. 5M IN A 10.0.2.191
+a-maximum-rrset.example. 5M IN A 10.0.2.192
+a-maximum-rrset.example. 5M IN A 10.0.2.193
+a-maximum-rrset.example. 5M IN A 10.0.2.194
+a-maximum-rrset.example. 5M IN A 10.0.2.195
+a-maximum-rrset.example. 5M IN A 10.0.2.196
+a-maximum-rrset.example. 5M IN A 10.0.2.197
+a-maximum-rrset.example. 5M IN A 10.0.2.198
+a-maximum-rrset.example. 5M IN A 10.0.2.199
+a-maximum-rrset.example. 5M IN A 10.0.2.200
+a-maximum-rrset.example. 5M IN A 10.0.2.201
+a-maximum-rrset.example. 5M IN A 10.0.2.202
+a-maximum-rrset.example. 5M IN A 10.0.2.203
+a-maximum-rrset.example. 5M IN A 10.0.2.204
+a-maximum-rrset.example. 5M IN A 10.0.2.205
+a-maximum-rrset.example. 5M IN A 10.0.2.206
+a-maximum-rrset.example. 5M IN A 10.0.2.207
+a-maximum-rrset.example. 5M IN A 10.0.2.208
+a-maximum-rrset.example. 5M IN A 10.0.2.209
+a-maximum-rrset.example. 5M IN A 10.0.2.210
+a-maximum-rrset.example. 5M IN A 10.0.2.211
+a-maximum-rrset.example. 5M IN A 10.0.2.212
+a-maximum-rrset.example. 5M IN A 10.0.2.213
+a-maximum-rrset.example. 5M IN A 10.0.2.214
+a-maximum-rrset.example. 5M IN A 10.0.2.215
+a-maximum-rrset.example. 5M IN A 10.0.2.216
+a-maximum-rrset.example. 5M IN A 10.0.2.217
+a-maximum-rrset.example. 5M IN A 10.0.2.218
+a-maximum-rrset.example. 5M IN A 10.0.2.219
+a-maximum-rrset.example. 5M IN A 10.0.2.220
+a-maximum-rrset.example. 5M IN A 10.0.2.221
+a-maximum-rrset.example. 5M IN A 10.0.2.222
+a-maximum-rrset.example. 5M IN A 10.0.2.223
+a-maximum-rrset.example. 5M IN A 10.0.2.224
+a-maximum-rrset.example. 5M IN A 10.0.2.225
+a-maximum-rrset.example. 5M IN A 10.0.2.226
+a-maximum-rrset.example. 5M IN A 10.0.2.227
+a-maximum-rrset.example. 5M IN A 10.0.2.228
+a-maximum-rrset.example. 5M IN A 10.0.2.229
+a-maximum-rrset.example. 5M IN A 10.0.2.230
+a-maximum-rrset.example. 5M IN A 10.0.2.231
+a-maximum-rrset.example. 5M IN A 10.0.2.232
+a-maximum-rrset.example. 5M IN A 10.0.2.233
+a-maximum-rrset.example. 5M IN A 10.0.2.234
+a-maximum-rrset.example. 5M IN A 10.0.2.235
+a-maximum-rrset.example. 5M IN A 10.0.2.236
+a-maximum-rrset.example. 5M IN A 10.0.2.237
+a-maximum-rrset.example. 5M IN A 10.0.2.238
+a-maximum-rrset.example. 5M IN A 10.0.2.239
+a-maximum-rrset.example. 5M IN A 10.0.2.240
+a-maximum-rrset.example. 5M IN A 10.0.2.241
+a-maximum-rrset.example. 5M IN A 10.0.2.242
+a-maximum-rrset.example. 5M IN A 10.0.2.243
+a-maximum-rrset.example. 5M IN A 10.0.2.244
+a-maximum-rrset.example. 5M IN A 10.0.2.245
+a-maximum-rrset.example. 5M IN A 10.0.2.246
+a-maximum-rrset.example. 5M IN A 10.0.2.247
+a-maximum-rrset.example. 5M IN A 10.0.2.248
+a-maximum-rrset.example. 5M IN A 10.0.2.249
+a-maximum-rrset.example. 5M IN A 10.0.2.250
+a-maximum-rrset.example. 5M IN A 10.0.2.251
+a-maximum-rrset.example. 5M IN A 10.0.2.252
+a-maximum-rrset.example. 5M IN A 10.0.2.253
+a-maximum-rrset.example. 5M IN A 10.0.2.254
+a-maximum-rrset.example. 5M IN A 10.0.2.255
+a-maximum-rrset.example. 5M IN A 10.0.3.0
+a-maximum-rrset.example. 5M IN A 10.0.3.1
+a-maximum-rrset.example. 5M IN A 10.0.3.2
+a-maximum-rrset.example. 5M IN A 10.0.3.3
+a-maximum-rrset.example. 5M IN A 10.0.3.4
+a-maximum-rrset.example. 5M IN A 10.0.3.5
+a-maximum-rrset.example. 5M IN A 10.0.3.6
+a-maximum-rrset.example. 5M IN A 10.0.3.7
+a-maximum-rrset.example. 5M IN A 10.0.3.8
+a-maximum-rrset.example. 5M IN A 10.0.3.9
+a-maximum-rrset.example. 5M IN A 10.0.3.10
+a-maximum-rrset.example. 5M IN A 10.0.3.11
+a-maximum-rrset.example. 5M IN A 10.0.3.12
+a-maximum-rrset.example. 5M IN A 10.0.3.13
+a-maximum-rrset.example. 5M IN A 10.0.3.14
+a-maximum-rrset.example. 5M IN A 10.0.3.15
+a-maximum-rrset.example. 5M IN A 10.0.3.16
+a-maximum-rrset.example. 5M IN A 10.0.3.17
+a-maximum-rrset.example. 5M IN A 10.0.3.18
+a-maximum-rrset.example. 5M IN A 10.0.3.19
+a-maximum-rrset.example. 5M IN A 10.0.3.20
+a-maximum-rrset.example. 5M IN A 10.0.3.21
+a-maximum-rrset.example. 5M IN A 10.0.3.22
+a-maximum-rrset.example. 5M IN A 10.0.3.23
+a-maximum-rrset.example. 5M IN A 10.0.3.24
+a-maximum-rrset.example. 5M IN A 10.0.3.25
+a-maximum-rrset.example. 5M IN A 10.0.3.26
+a-maximum-rrset.example. 5M IN A 10.0.3.27
+a-maximum-rrset.example. 5M IN A 10.0.3.28
+a-maximum-rrset.example. 5M IN A 10.0.3.29
+a-maximum-rrset.example. 5M IN A 10.0.3.30
+a-maximum-rrset.example. 5M IN A 10.0.3.31
+a-maximum-rrset.example. 5M IN A 10.0.3.32
+a-maximum-rrset.example. 5M IN A 10.0.3.33
+a-maximum-rrset.example. 5M IN A 10.0.3.34
+a-maximum-rrset.example. 5M IN A 10.0.3.35
+a-maximum-rrset.example. 5M IN A 10.0.3.36
+a-maximum-rrset.example. 5M IN A 10.0.3.37
+a-maximum-rrset.example. 5M IN A 10.0.3.38
+a-maximum-rrset.example. 5M IN A 10.0.3.39
+a-maximum-rrset.example. 5M IN A 10.0.3.40
+a-maximum-rrset.example. 5M IN A 10.0.3.41
+a-maximum-rrset.example. 5M IN A 10.0.3.42
+a-maximum-rrset.example. 5M IN A 10.0.3.43
+a-maximum-rrset.example. 5M IN A 10.0.3.44
+a-maximum-rrset.example. 5M IN A 10.0.3.45
+a-maximum-rrset.example. 5M IN A 10.0.3.46
+a-maximum-rrset.example. 5M IN A 10.0.3.47
+a-maximum-rrset.example. 5M IN A 10.0.3.48
+a-maximum-rrset.example. 5M IN A 10.0.3.49
+a-maximum-rrset.example. 5M IN A 10.0.3.50
+a-maximum-rrset.example. 5M IN A 10.0.3.51
+a-maximum-rrset.example. 5M IN A 10.0.3.52
+a-maximum-rrset.example. 5M IN A 10.0.3.53
+a-maximum-rrset.example. 5M IN A 10.0.3.54
+a-maximum-rrset.example. 5M IN A 10.0.3.55
+a-maximum-rrset.example. 5M IN A 10.0.3.56
+a-maximum-rrset.example. 5M IN A 10.0.3.57
+a-maximum-rrset.example. 5M IN A 10.0.3.58
+a-maximum-rrset.example. 5M IN A 10.0.3.59
+a-maximum-rrset.example. 5M IN A 10.0.3.60
+a-maximum-rrset.example. 5M IN A 10.0.3.61
+a-maximum-rrset.example. 5M IN A 10.0.3.62
+a-maximum-rrset.example. 5M IN A 10.0.3.63
+a-maximum-rrset.example. 5M IN A 10.0.3.64
+a-maximum-rrset.example. 5M IN A 10.0.3.65
+a-maximum-rrset.example. 5M IN A 10.0.3.66
+a-maximum-rrset.example. 5M IN A 10.0.3.67
+a-maximum-rrset.example. 5M IN A 10.0.3.68
+a-maximum-rrset.example. 5M IN A 10.0.3.69
+a-maximum-rrset.example. 5M IN A 10.0.3.70
+a-maximum-rrset.example. 5M IN A 10.0.3.71
+a-maximum-rrset.example. 5M IN A 10.0.3.72
+a-maximum-rrset.example. 5M IN A 10.0.3.73
+a-maximum-rrset.example. 5M IN A 10.0.3.74
+a-maximum-rrset.example. 5M IN A 10.0.3.75
+a-maximum-rrset.example. 5M IN A 10.0.3.76
+a-maximum-rrset.example. 5M IN A 10.0.3.77
+a-maximum-rrset.example. 5M IN A 10.0.3.78
+a-maximum-rrset.example. 5M IN A 10.0.3.79
+a-maximum-rrset.example. 5M IN A 10.0.3.80
+a-maximum-rrset.example. 5M IN A 10.0.3.81
+a-maximum-rrset.example. 5M IN A 10.0.3.82
+a-maximum-rrset.example. 5M IN A 10.0.3.83
+a-maximum-rrset.example. 5M IN A 10.0.3.84
+a-maximum-rrset.example. 5M IN A 10.0.3.85
+a-maximum-rrset.example. 5M IN A 10.0.3.86
+a-maximum-rrset.example. 5M IN A 10.0.3.87
+a-maximum-rrset.example. 5M IN A 10.0.3.88
+a-maximum-rrset.example. 5M IN A 10.0.3.89
+a-maximum-rrset.example. 5M IN A 10.0.3.90
+a-maximum-rrset.example. 5M IN A 10.0.3.91
+a-maximum-rrset.example. 5M IN A 10.0.3.92
+a-maximum-rrset.example. 5M IN A 10.0.3.93
+a-maximum-rrset.example. 5M IN A 10.0.3.94
+a-maximum-rrset.example. 5M IN A 10.0.3.95
+a-maximum-rrset.example. 5M IN A 10.0.3.96
+a-maximum-rrset.example. 5M IN A 10.0.3.97
+a-maximum-rrset.example. 5M IN A 10.0.3.98
+a-maximum-rrset.example. 5M IN A 10.0.3.99
+a-maximum-rrset.example. 5M IN A 10.0.3.100
+a-maximum-rrset.example. 5M IN A 10.0.3.101
+a-maximum-rrset.example. 5M IN A 10.0.3.102
+a-maximum-rrset.example. 5M IN A 10.0.3.103
+a-maximum-rrset.example. 5M IN A 10.0.3.104
+a-maximum-rrset.example. 5M IN A 10.0.3.105
+a-maximum-rrset.example. 5M IN A 10.0.3.106
+a-maximum-rrset.example. 5M IN A 10.0.3.107
+a-maximum-rrset.example. 5M IN A 10.0.3.108
+a-maximum-rrset.example. 5M IN A 10.0.3.109
+a-maximum-rrset.example. 5M IN A 10.0.3.110
+a-maximum-rrset.example. 5M IN A 10.0.3.111
+a-maximum-rrset.example. 5M IN A 10.0.3.112
+a-maximum-rrset.example. 5M IN A 10.0.3.113
+a-maximum-rrset.example. 5M IN A 10.0.3.114
+a-maximum-rrset.example. 5M IN A 10.0.3.115
+a-maximum-rrset.example. 5M IN A 10.0.3.116
+a-maximum-rrset.example. 5M IN A 10.0.3.117
+a-maximum-rrset.example. 5M IN A 10.0.3.118
+a-maximum-rrset.example. 5M IN A 10.0.3.119
+a-maximum-rrset.example. 5M IN A 10.0.3.120
+a-maximum-rrset.example. 5M IN A 10.0.3.121
+a-maximum-rrset.example. 5M IN A 10.0.3.122
+a-maximum-rrset.example. 5M IN A 10.0.3.123
+a-maximum-rrset.example. 5M IN A 10.0.3.124
+a-maximum-rrset.example. 5M IN A 10.0.3.125
+a-maximum-rrset.example. 5M IN A 10.0.3.126
+a-maximum-rrset.example. 5M IN A 10.0.3.127
+a-maximum-rrset.example. 5M IN A 10.0.3.128
+a-maximum-rrset.example. 5M IN A 10.0.3.129
+a-maximum-rrset.example. 5M IN A 10.0.3.130
+a-maximum-rrset.example. 5M IN A 10.0.3.131
+a-maximum-rrset.example. 5M IN A 10.0.3.132
+a-maximum-rrset.example. 5M IN A 10.0.3.133
+a-maximum-rrset.example. 5M IN A 10.0.3.134
+a-maximum-rrset.example. 5M IN A 10.0.3.135
+a-maximum-rrset.example. 5M IN A 10.0.3.136
+a-maximum-rrset.example. 5M IN A 10.0.3.137
+a-maximum-rrset.example. 5M IN A 10.0.3.138
+a-maximum-rrset.example. 5M IN A 10.0.3.139
+a-maximum-rrset.example. 5M IN A 10.0.3.140
+a-maximum-rrset.example. 5M IN A 10.0.3.141
+a-maximum-rrset.example. 5M IN A 10.0.3.142
+a-maximum-rrset.example. 5M IN A 10.0.3.143
+a-maximum-rrset.example. 5M IN A 10.0.3.144
+a-maximum-rrset.example. 5M IN A 10.0.3.145
+a-maximum-rrset.example. 5M IN A 10.0.3.146
+a-maximum-rrset.example. 5M IN A 10.0.3.147
+a-maximum-rrset.example. 5M IN A 10.0.3.148
+a-maximum-rrset.example. 5M IN A 10.0.3.149
+a-maximum-rrset.example. 5M IN A 10.0.3.150
+a-maximum-rrset.example. 5M IN A 10.0.3.151
+a-maximum-rrset.example. 5M IN A 10.0.3.152
+a-maximum-rrset.example. 5M IN A 10.0.3.153
+a-maximum-rrset.example. 5M IN A 10.0.3.154
+a-maximum-rrset.example. 5M IN A 10.0.3.155
+a-maximum-rrset.example. 5M IN A 10.0.3.156
+a-maximum-rrset.example. 5M IN A 10.0.3.157
+a-maximum-rrset.example. 5M IN A 10.0.3.158
+a-maximum-rrset.example. 5M IN A 10.0.3.159
+a-maximum-rrset.example. 5M IN A 10.0.3.160
+a-maximum-rrset.example. 5M IN A 10.0.3.161
+a-maximum-rrset.example. 5M IN A 10.0.3.162
+a-maximum-rrset.example. 5M IN A 10.0.3.163
+a-maximum-rrset.example. 5M IN A 10.0.3.164
+a-maximum-rrset.example. 5M IN A 10.0.3.165
+a-maximum-rrset.example. 5M IN A 10.0.3.166
+a-maximum-rrset.example. 5M IN A 10.0.3.167
+a-maximum-rrset.example. 5M IN A 10.0.3.168
+a-maximum-rrset.example. 5M IN A 10.0.3.169
+a-maximum-rrset.example. 5M IN A 10.0.3.170
+a-maximum-rrset.example. 5M IN A 10.0.3.171
+a-maximum-rrset.example. 5M IN A 10.0.3.172
+a-maximum-rrset.example. 5M IN A 10.0.3.173
+a-maximum-rrset.example. 5M IN A 10.0.3.174
+a-maximum-rrset.example. 5M IN A 10.0.3.175
+a-maximum-rrset.example. 5M IN A 10.0.3.176
+a-maximum-rrset.example. 5M IN A 10.0.3.177
+a-maximum-rrset.example. 5M IN A 10.0.3.178
+a-maximum-rrset.example. 5M IN A 10.0.3.179
+a-maximum-rrset.example. 5M IN A 10.0.3.180
+a-maximum-rrset.example. 5M IN A 10.0.3.181
+a-maximum-rrset.example. 5M IN A 10.0.3.182
+a-maximum-rrset.example. 5M IN A 10.0.3.183
+a-maximum-rrset.example. 5M IN A 10.0.3.184
+a-maximum-rrset.example. 5M IN A 10.0.3.185
+a-maximum-rrset.example. 5M IN A 10.0.3.186
+a-maximum-rrset.example. 5M IN A 10.0.3.187
+a-maximum-rrset.example. 5M IN A 10.0.3.188
+a-maximum-rrset.example. 5M IN A 10.0.3.189
+a-maximum-rrset.example. 5M IN A 10.0.3.190
+a-maximum-rrset.example. 5M IN A 10.0.3.191
+a-maximum-rrset.example. 5M IN A 10.0.3.192
+a-maximum-rrset.example. 5M IN A 10.0.3.193
+a-maximum-rrset.example. 5M IN A 10.0.3.194
+a-maximum-rrset.example. 5M IN A 10.0.3.195
+a-maximum-rrset.example. 5M IN A 10.0.3.196
+a-maximum-rrset.example. 5M IN A 10.0.3.197
+a-maximum-rrset.example. 5M IN A 10.0.3.198
+a-maximum-rrset.example. 5M IN A 10.0.3.199
+a-maximum-rrset.example. 5M IN A 10.0.3.200
+a-maximum-rrset.example. 5M IN A 10.0.3.201
+a-maximum-rrset.example. 5M IN A 10.0.3.202
+a-maximum-rrset.example. 5M IN A 10.0.3.203
+a-maximum-rrset.example. 5M IN A 10.0.3.204
+a-maximum-rrset.example. 5M IN A 10.0.3.205
+a-maximum-rrset.example. 5M IN A 10.0.3.206
+a-maximum-rrset.example. 5M IN A 10.0.3.207
+a-maximum-rrset.example. 5M IN A 10.0.3.208
+a-maximum-rrset.example. 5M IN A 10.0.3.209
+a-maximum-rrset.example. 5M IN A 10.0.3.210
+a-maximum-rrset.example. 5M IN A 10.0.3.211
+a-maximum-rrset.example. 5M IN A 10.0.3.212
+a-maximum-rrset.example. 5M IN A 10.0.3.213
+a-maximum-rrset.example. 5M IN A 10.0.3.214
+a-maximum-rrset.example. 5M IN A 10.0.3.215
+a-maximum-rrset.example. 5M IN A 10.0.3.216
+a-maximum-rrset.example. 5M IN A 10.0.3.217
+a-maximum-rrset.example. 5M IN A 10.0.3.218
+a-maximum-rrset.example. 5M IN A 10.0.3.219
+a-maximum-rrset.example. 5M IN A 10.0.3.220
+a-maximum-rrset.example. 5M IN A 10.0.3.221
+a-maximum-rrset.example. 5M IN A 10.0.3.222
+a-maximum-rrset.example. 5M IN A 10.0.3.223
+a-maximum-rrset.example. 5M IN A 10.0.3.224
+a-maximum-rrset.example. 5M IN A 10.0.3.225
+a-maximum-rrset.example. 5M IN A 10.0.3.226
+a-maximum-rrset.example. 5M IN A 10.0.3.227
+a-maximum-rrset.example. 5M IN A 10.0.3.228
+a-maximum-rrset.example. 5M IN A 10.0.3.229
+a-maximum-rrset.example. 5M IN A 10.0.3.230
+a-maximum-rrset.example. 5M IN A 10.0.3.231
+a-maximum-rrset.example. 5M IN A 10.0.3.232
+a-maximum-rrset.example. 5M IN A 10.0.3.233
+a-maximum-rrset.example. 5M IN A 10.0.3.234
+a-maximum-rrset.example. 5M IN A 10.0.3.235
+a-maximum-rrset.example. 5M IN A 10.0.3.236
+a-maximum-rrset.example. 5M IN A 10.0.3.237
+a-maximum-rrset.example. 5M IN A 10.0.3.238
+a-maximum-rrset.example. 5M IN A 10.0.3.239
+a-maximum-rrset.example. 5M IN A 10.0.3.240
+a-maximum-rrset.example. 5M IN A 10.0.3.241
+a-maximum-rrset.example. 5M IN A 10.0.3.242
+a-maximum-rrset.example. 5M IN A 10.0.3.243
+a-maximum-rrset.example. 5M IN A 10.0.3.244
+a-maximum-rrset.example. 5M IN A 10.0.3.245
+a-maximum-rrset.example. 5M IN A 10.0.3.246
+a-maximum-rrset.example. 5M IN A 10.0.3.247
+a-maximum-rrset.example. 5M IN A 10.0.3.248
+a-maximum-rrset.example. 5M IN A 10.0.3.249
+a-maximum-rrset.example. 5M IN A 10.0.3.250
+a-maximum-rrset.example. 5M IN A 10.0.3.251
+a-maximum-rrset.example. 5M IN A 10.0.3.252
+a-maximum-rrset.example. 5M IN A 10.0.3.253
+a-maximum-rrset.example. 5M IN A 10.0.3.254
+a-maximum-rrset.example. 5M IN A 10.0.3.255
+a-maximum-rrset.example. 5M IN A 10.0.4.0
+a-maximum-rrset.example. 5M IN A 10.0.4.1
+a-maximum-rrset.example. 5M IN A 10.0.4.2
+a-maximum-rrset.example. 5M IN A 10.0.4.3
+a-maximum-rrset.example. 5M IN A 10.0.4.4
+a-maximum-rrset.example. 5M IN A 10.0.4.5
+a-maximum-rrset.example. 5M IN A 10.0.4.6
+a-maximum-rrset.example. 5M IN A 10.0.4.7
+a-maximum-rrset.example. 5M IN A 10.0.4.8
+a-maximum-rrset.example. 5M IN A 10.0.4.9
+a-maximum-rrset.example. 5M IN A 10.0.4.10
+a-maximum-rrset.example. 5M IN A 10.0.4.11
+a-maximum-rrset.example. 5M IN A 10.0.4.12
+a-maximum-rrset.example. 5M IN A 10.0.4.13
+a-maximum-rrset.example. 5M IN A 10.0.4.14
+a-maximum-rrset.example. 5M IN A 10.0.4.15
+a-maximum-rrset.example. 5M IN A 10.0.4.16
+a-maximum-rrset.example. 5M IN A 10.0.4.17
+a-maximum-rrset.example. 5M IN A 10.0.4.18
+a-maximum-rrset.example. 5M IN A 10.0.4.19
+a-maximum-rrset.example. 5M IN A 10.0.4.20
+a-maximum-rrset.example. 5M IN A 10.0.4.21
+a-maximum-rrset.example. 5M IN A 10.0.4.22
+a-maximum-rrset.example. 5M IN A 10.0.4.23
+a-maximum-rrset.example. 5M IN A 10.0.4.24
+a-maximum-rrset.example. 5M IN A 10.0.4.25
+a-maximum-rrset.example. 5M IN A 10.0.4.26
+a-maximum-rrset.example. 5M IN A 10.0.4.27
+a-maximum-rrset.example. 5M IN A 10.0.4.28
+a-maximum-rrset.example. 5M IN A 10.0.4.29
+a-maximum-rrset.example. 5M IN A 10.0.4.30
+a-maximum-rrset.example. 5M IN A 10.0.4.31
+a-maximum-rrset.example. 5M IN A 10.0.4.32
+a-maximum-rrset.example. 5M IN A 10.0.4.33
+a-maximum-rrset.example. 5M IN A 10.0.4.34
+a-maximum-rrset.example. 5M IN A 10.0.4.35
+a-maximum-rrset.example. 5M IN A 10.0.4.36
+a-maximum-rrset.example. 5M IN A 10.0.4.37
+a-maximum-rrset.example. 5M IN A 10.0.4.38
+a-maximum-rrset.example. 5M IN A 10.0.4.39
+a-maximum-rrset.example. 5M IN A 10.0.4.40
+a-maximum-rrset.example. 5M IN A 10.0.4.41
+a-maximum-rrset.example. 5M IN A 10.0.4.42
+a-maximum-rrset.example. 5M IN A 10.0.4.43
+a-maximum-rrset.example. 5M IN A 10.0.4.44
+a-maximum-rrset.example. 5M IN A 10.0.4.45
+a-maximum-rrset.example. 5M IN A 10.0.4.46
+a-maximum-rrset.example. 5M IN A 10.0.4.47
+a-maximum-rrset.example. 5M IN A 10.0.4.48
+a-maximum-rrset.example. 5M IN A 10.0.4.49
+a-maximum-rrset.example. 5M IN A 10.0.4.50
+a-maximum-rrset.example. 5M IN A 10.0.4.51
+a-maximum-rrset.example. 5M IN A 10.0.4.52
+a-maximum-rrset.example. 5M IN A 10.0.4.53
+a-maximum-rrset.example. 5M IN A 10.0.4.54
+a-maximum-rrset.example. 5M IN A 10.0.4.55
+a-maximum-rrset.example. 5M IN A 10.0.4.56
+a-maximum-rrset.example. 5M IN A 10.0.4.57
+a-maximum-rrset.example. 5M IN A 10.0.4.58
+a-maximum-rrset.example. 5M IN A 10.0.4.59
+a-maximum-rrset.example. 5M IN A 10.0.4.60
+a-maximum-rrset.example. 5M IN A 10.0.4.61
+a-maximum-rrset.example. 5M IN A 10.0.4.62
+a-maximum-rrset.example. 5M IN A 10.0.4.63
+a-maximum-rrset.example. 5M IN A 10.0.4.64
+a-maximum-rrset.example. 5M IN A 10.0.4.65
+a-maximum-rrset.example. 5M IN A 10.0.4.66
+a-maximum-rrset.example. 5M IN A 10.0.4.67
+a-maximum-rrset.example. 5M IN A 10.0.4.68
+a-maximum-rrset.example. 5M IN A 10.0.4.69
+a-maximum-rrset.example. 5M IN A 10.0.4.70
+a-maximum-rrset.example. 5M IN A 10.0.4.71
+a-maximum-rrset.example. 5M IN A 10.0.4.72
+a-maximum-rrset.example. 5M IN A 10.0.4.73
+a-maximum-rrset.example. 5M IN A 10.0.4.74
+a-maximum-rrset.example. 5M IN A 10.0.4.75
+a-maximum-rrset.example. 5M IN A 10.0.4.76
+a-maximum-rrset.example. 5M IN A 10.0.4.77
+a-maximum-rrset.example. 5M IN A 10.0.4.78
+a-maximum-rrset.example. 5M IN A 10.0.4.79
+a-maximum-rrset.example. 5M IN A 10.0.4.80
+a-maximum-rrset.example. 5M IN A 10.0.4.81
+a-maximum-rrset.example. 5M IN A 10.0.4.82
+a-maximum-rrset.example. 5M IN A 10.0.4.83
+a-maximum-rrset.example. 5M IN A 10.0.4.84
+a-maximum-rrset.example. 5M IN A 10.0.4.85
+a-maximum-rrset.example. 5M IN A 10.0.4.86
+a-maximum-rrset.example. 5M IN A 10.0.4.87
+a-maximum-rrset.example. 5M IN A 10.0.4.88
+a-maximum-rrset.example. 5M IN A 10.0.4.89
+a-maximum-rrset.example. 5M IN A 10.0.4.90
+a-maximum-rrset.example. 5M IN A 10.0.4.91
+a-maximum-rrset.example. 5M IN A 10.0.4.92
+a-maximum-rrset.example. 5M IN A 10.0.4.93
+a-maximum-rrset.example. 5M IN A 10.0.4.94
+a-maximum-rrset.example. 5M IN A 10.0.4.95
+a-maximum-rrset.example. 5M IN A 10.0.4.96
+a-maximum-rrset.example. 5M IN A 10.0.4.97
+a-maximum-rrset.example. 5M IN A 10.0.4.98
+a-maximum-rrset.example. 5M IN A 10.0.4.99
+a-maximum-rrset.example. 5M IN A 10.0.4.100
+a-maximum-rrset.example. 5M IN A 10.0.4.101
+a-maximum-rrset.example. 5M IN A 10.0.4.102
+a-maximum-rrset.example. 5M IN A 10.0.4.103
+a-maximum-rrset.example. 5M IN A 10.0.4.104
+a-maximum-rrset.example. 5M IN A 10.0.4.105
+a-maximum-rrset.example. 5M IN A 10.0.4.106
+a-maximum-rrset.example. 5M IN A 10.0.4.107
+a-maximum-rrset.example. 5M IN A 10.0.4.108
+a-maximum-rrset.example. 5M IN A 10.0.4.109
+a-maximum-rrset.example. 5M IN A 10.0.4.110
+a-maximum-rrset.example. 5M IN A 10.0.4.111
+a-maximum-rrset.example. 5M IN A 10.0.4.112
+a-maximum-rrset.example. 5M IN A 10.0.4.113
+a-maximum-rrset.example. 5M IN A 10.0.4.114
+a-maximum-rrset.example. 5M IN A 10.0.4.115
+a-maximum-rrset.example. 5M IN A 10.0.4.116
+a-maximum-rrset.example. 5M IN A 10.0.4.117
+a-maximum-rrset.example. 5M IN A 10.0.4.118
+a-maximum-rrset.example. 5M IN A 10.0.4.119
+a-maximum-rrset.example. 5M IN A 10.0.4.120
+a-maximum-rrset.example. 5M IN A 10.0.4.121
+a-maximum-rrset.example. 5M IN A 10.0.4.122
+a-maximum-rrset.example. 5M IN A 10.0.4.123
+a-maximum-rrset.example. 5M IN A 10.0.4.124
+a-maximum-rrset.example. 5M IN A 10.0.4.125
+a-maximum-rrset.example. 5M IN A 10.0.4.126
+a-maximum-rrset.example. 5M IN A 10.0.4.127
+a-maximum-rrset.example. 5M IN A 10.0.4.128
+a-maximum-rrset.example. 5M IN A 10.0.4.129
+a-maximum-rrset.example. 5M IN A 10.0.4.130
+a-maximum-rrset.example. 5M IN A 10.0.4.131
+a-maximum-rrset.example. 5M IN A 10.0.4.132
+a-maximum-rrset.example. 5M IN A 10.0.4.133
+a-maximum-rrset.example. 5M IN A 10.0.4.134
+a-maximum-rrset.example. 5M IN A 10.0.4.135
+a-maximum-rrset.example. 5M IN A 10.0.4.136
+a-maximum-rrset.example. 5M IN A 10.0.4.137
+a-maximum-rrset.example. 5M IN A 10.0.4.138
+a-maximum-rrset.example. 5M IN A 10.0.4.139
+a-maximum-rrset.example. 5M IN A 10.0.4.140
+a-maximum-rrset.example. 5M IN A 10.0.4.141
+a-maximum-rrset.example. 5M IN A 10.0.4.142
+a-maximum-rrset.example. 5M IN A 10.0.4.143
+a-maximum-rrset.example. 5M IN A 10.0.4.144
+a-maximum-rrset.example. 5M IN A 10.0.4.145
+a-maximum-rrset.example. 5M IN A 10.0.4.146
+a-maximum-rrset.example. 5M IN A 10.0.4.147
+a-maximum-rrset.example. 5M IN A 10.0.4.148
+a-maximum-rrset.example. 5M IN A 10.0.4.149
+a-maximum-rrset.example. 5M IN A 10.0.4.150
+a-maximum-rrset.example. 5M IN A 10.0.4.151
+a-maximum-rrset.example. 5M IN A 10.0.4.152
+a-maximum-rrset.example. 5M IN A 10.0.4.153
+a-maximum-rrset.example. 5M IN A 10.0.4.154
+a-maximum-rrset.example. 5M IN A 10.0.4.155
+a-maximum-rrset.example. 5M IN A 10.0.4.156
+a-maximum-rrset.example. 5M IN A 10.0.4.157
+a-maximum-rrset.example. 5M IN A 10.0.4.158
+a-maximum-rrset.example. 5M IN A 10.0.4.159
+a-maximum-rrset.example. 5M IN A 10.0.4.160
+a-maximum-rrset.example. 5M IN A 10.0.4.161
+a-maximum-rrset.example. 5M IN A 10.0.4.162
+a-maximum-rrset.example. 5M IN A 10.0.4.163
+a-maximum-rrset.example. 5M IN A 10.0.4.164
+a-maximum-rrset.example. 5M IN A 10.0.4.165
+a-maximum-rrset.example. 5M IN A 10.0.4.166
+a-maximum-rrset.example. 5M IN A 10.0.4.167
+a-maximum-rrset.example. 5M IN A 10.0.4.168
+a-maximum-rrset.example. 5M IN A 10.0.4.169
+a-maximum-rrset.example. 5M IN A 10.0.4.170
+a-maximum-rrset.example. 5M IN A 10.0.4.171
+a-maximum-rrset.example. 5M IN A 10.0.4.172
+a-maximum-rrset.example. 5M IN A 10.0.4.173
+a-maximum-rrset.example. 5M IN A 10.0.4.174
+a-maximum-rrset.example. 5M IN A 10.0.4.175
+a-maximum-rrset.example. 5M IN A 10.0.4.176
+a-maximum-rrset.example. 5M IN A 10.0.4.177
+a-maximum-rrset.example. 5M IN A 10.0.4.178
+a-maximum-rrset.example. 5M IN A 10.0.4.179
+a-maximum-rrset.example. 5M IN A 10.0.4.180
+a-maximum-rrset.example. 5M IN A 10.0.4.181
+a-maximum-rrset.example. 5M IN A 10.0.4.182
+a-maximum-rrset.example. 5M IN A 10.0.4.183
+a-maximum-rrset.example. 5M IN A 10.0.4.184
+a-maximum-rrset.example. 5M IN A 10.0.4.185
+a-maximum-rrset.example. 5M IN A 10.0.4.186
+a-maximum-rrset.example. 5M IN A 10.0.4.187
+a-maximum-rrset.example. 5M IN A 10.0.4.188
+a-maximum-rrset.example. 5M IN A 10.0.4.189
+a-maximum-rrset.example. 5M IN A 10.0.4.190
+a-maximum-rrset.example. 5M IN A 10.0.4.191
+a-maximum-rrset.example. 5M IN A 10.0.4.192
+a-maximum-rrset.example. 5M IN A 10.0.4.193
+a-maximum-rrset.example. 5M IN A 10.0.4.194
+a-maximum-rrset.example. 5M IN A 10.0.4.195
+a-maximum-rrset.example. 5M IN A 10.0.4.196
+a-maximum-rrset.example. 5M IN A 10.0.4.197
+a-maximum-rrset.example. 5M IN A 10.0.4.198
+a-maximum-rrset.example. 5M IN A 10.0.4.199
+a-maximum-rrset.example. 5M IN A 10.0.4.200
+a-maximum-rrset.example. 5M IN A 10.0.4.201
+a-maximum-rrset.example. 5M IN A 10.0.4.202
+a-maximum-rrset.example. 5M IN A 10.0.4.203
+a-maximum-rrset.example. 5M IN A 10.0.4.204
+a-maximum-rrset.example. 5M IN A 10.0.4.205
+a-maximum-rrset.example. 5M IN A 10.0.4.206
+a-maximum-rrset.example. 5M IN A 10.0.4.207
+a-maximum-rrset.example. 5M IN A 10.0.4.208
+a-maximum-rrset.example. 5M IN A 10.0.4.209
+a-maximum-rrset.example. 5M IN A 10.0.4.210
+a-maximum-rrset.example. 5M IN A 10.0.4.211
+a-maximum-rrset.example. 5M IN A 10.0.4.212
+a-maximum-rrset.example. 5M IN A 10.0.4.213
+a-maximum-rrset.example. 5M IN A 10.0.4.214
+a-maximum-rrset.example. 5M IN A 10.0.4.215
+a-maximum-rrset.example. 5M IN A 10.0.4.216
+a-maximum-rrset.example. 5M IN A 10.0.4.217
+a-maximum-rrset.example. 5M IN A 10.0.4.218
+a-maximum-rrset.example. 5M IN A 10.0.4.219
+a-maximum-rrset.example. 5M IN A 10.0.4.220
+a-maximum-rrset.example. 5M IN A 10.0.4.221
+a-maximum-rrset.example. 5M IN A 10.0.4.222
+a-maximum-rrset.example. 5M IN A 10.0.4.223
+a-maximum-rrset.example. 5M IN A 10.0.4.224
+a-maximum-rrset.example. 5M IN A 10.0.4.225
+a-maximum-rrset.example. 5M IN A 10.0.4.226
+a-maximum-rrset.example. 5M IN A 10.0.4.227
+a-maximum-rrset.example. 5M IN A 10.0.4.228
+a-maximum-rrset.example. 5M IN A 10.0.4.229
+a-maximum-rrset.example. 5M IN A 10.0.4.230
+a-maximum-rrset.example. 5M IN A 10.0.4.231
+a-maximum-rrset.example. 5M IN A 10.0.4.232
+a-maximum-rrset.example. 5M IN A 10.0.4.233
+a-maximum-rrset.example. 5M IN A 10.0.4.234
+a-maximum-rrset.example. 5M IN A 10.0.4.235
+a-maximum-rrset.example. 5M IN A 10.0.4.236
+a-maximum-rrset.example. 5M IN A 10.0.4.237
+a-maximum-rrset.example. 5M IN A 10.0.4.238
+a-maximum-rrset.example. 5M IN A 10.0.4.239
+a-maximum-rrset.example. 5M IN A 10.0.4.240
+a-maximum-rrset.example. 5M IN A 10.0.4.241
+a-maximum-rrset.example. 5M IN A 10.0.4.242
+a-maximum-rrset.example. 5M IN A 10.0.4.243
+a-maximum-rrset.example. 5M IN A 10.0.4.244
+a-maximum-rrset.example. 5M IN A 10.0.4.245
+a-maximum-rrset.example. 5M IN A 10.0.4.246
+a-maximum-rrset.example. 5M IN A 10.0.4.247
+a-maximum-rrset.example. 5M IN A 10.0.4.248
+a-maximum-rrset.example. 5M IN A 10.0.4.249
+a-maximum-rrset.example. 5M IN A 10.0.4.250
+a-maximum-rrset.example. 5M IN A 10.0.4.251
+a-maximum-rrset.example. 5M IN A 10.0.4.252
+a-maximum-rrset.example. 5M IN A 10.0.4.253
+a-maximum-rrset.example. 5M IN A 10.0.4.254
+a-maximum-rrset.example. 5M IN A 10.0.4.255
+a-maximum-rrset.example. 5M IN A 10.0.5.0
+a-maximum-rrset.example. 5M IN A 10.0.5.1
+a-maximum-rrset.example. 5M IN A 10.0.5.2
+a-maximum-rrset.example. 5M IN A 10.0.5.3
+a-maximum-rrset.example. 5M IN A 10.0.5.4
+a-maximum-rrset.example. 5M IN A 10.0.5.5
+a-maximum-rrset.example. 5M IN A 10.0.5.6
+a-maximum-rrset.example. 5M IN A 10.0.5.7
+a-maximum-rrset.example. 5M IN A 10.0.5.8
+a-maximum-rrset.example. 5M IN A 10.0.5.9
+a-maximum-rrset.example. 5M IN A 10.0.5.10
+a-maximum-rrset.example. 5M IN A 10.0.5.11
+a-maximum-rrset.example. 5M IN A 10.0.5.12
+a-maximum-rrset.example. 5M IN A 10.0.5.13
+a-maximum-rrset.example. 5M IN A 10.0.5.14
+a-maximum-rrset.example. 5M IN A 10.0.5.15
+a-maximum-rrset.example. 5M IN A 10.0.5.16
+a-maximum-rrset.example. 5M IN A 10.0.5.17
+a-maximum-rrset.example. 5M IN A 10.0.5.18
+a-maximum-rrset.example. 5M IN A 10.0.5.19
+a-maximum-rrset.example. 5M IN A 10.0.5.20
+a-maximum-rrset.example. 5M IN A 10.0.5.21
+a-maximum-rrset.example. 5M IN A 10.0.5.22
+a-maximum-rrset.example. 5M IN A 10.0.5.23
+a-maximum-rrset.example. 5M IN A 10.0.5.24
+a-maximum-rrset.example. 5M IN A 10.0.5.25
+a-maximum-rrset.example. 5M IN A 10.0.5.26
+a-maximum-rrset.example. 5M IN A 10.0.5.27
+a-maximum-rrset.example. 5M IN A 10.0.5.28
+a-maximum-rrset.example. 5M IN A 10.0.5.29
+a-maximum-rrset.example. 5M IN A 10.0.5.30
+a-maximum-rrset.example. 5M IN A 10.0.5.31
+a-maximum-rrset.example. 5M IN A 10.0.5.32
+a-maximum-rrset.example. 5M IN A 10.0.5.33
+a-maximum-rrset.example. 5M IN A 10.0.5.34
+a-maximum-rrset.example. 5M IN A 10.0.5.35
+a-maximum-rrset.example. 5M IN A 10.0.5.36
+a-maximum-rrset.example. 5M IN A 10.0.5.37
+a-maximum-rrset.example. 5M IN A 10.0.5.38
+a-maximum-rrset.example. 5M IN A 10.0.5.39
+a-maximum-rrset.example. 5M IN A 10.0.5.40
+a-maximum-rrset.example. 5M IN A 10.0.5.41
+a-maximum-rrset.example. 5M IN A 10.0.5.42
+a-maximum-rrset.example. 5M IN A 10.0.5.43
+a-maximum-rrset.example. 5M IN A 10.0.5.44
+a-maximum-rrset.example. 5M IN A 10.0.5.45
+a-maximum-rrset.example. 5M IN A 10.0.5.46
+a-maximum-rrset.example. 5M IN A 10.0.5.47
+a-maximum-rrset.example. 5M IN A 10.0.5.48
+a-maximum-rrset.example. 5M IN A 10.0.5.49
+a-maximum-rrset.example. 5M IN A 10.0.5.50
+a-maximum-rrset.example. 5M IN A 10.0.5.51
+a-maximum-rrset.example. 5M IN A 10.0.5.52
+a-maximum-rrset.example. 5M IN A 10.0.5.53
+a-maximum-rrset.example. 5M IN A 10.0.5.54
+a-maximum-rrset.example. 5M IN A 10.0.5.55
+a-maximum-rrset.example. 5M IN A 10.0.5.56
+a-maximum-rrset.example. 5M IN A 10.0.5.57
+a-maximum-rrset.example. 5M IN A 10.0.5.58
+a-maximum-rrset.example. 5M IN A 10.0.5.59
+a-maximum-rrset.example. 5M IN A 10.0.5.60
+a-maximum-rrset.example. 5M IN A 10.0.5.61
+a-maximum-rrset.example. 5M IN A 10.0.5.62
+a-maximum-rrset.example. 5M IN A 10.0.5.63
+a-maximum-rrset.example. 5M IN A 10.0.5.64
+a-maximum-rrset.example. 5M IN A 10.0.5.65
+a-maximum-rrset.example. 5M IN A 10.0.5.66
+a-maximum-rrset.example. 5M IN A 10.0.5.67
+a-maximum-rrset.example. 5M IN A 10.0.5.68
+a-maximum-rrset.example. 5M IN A 10.0.5.69
+a-maximum-rrset.example. 5M IN A 10.0.5.70
+a-maximum-rrset.example. 5M IN A 10.0.5.71
+a-maximum-rrset.example. 5M IN A 10.0.5.72
+a-maximum-rrset.example. 5M IN A 10.0.5.73
+a-maximum-rrset.example. 5M IN A 10.0.5.74
+a-maximum-rrset.example. 5M IN A 10.0.5.75
+a-maximum-rrset.example. 5M IN A 10.0.5.76
+a-maximum-rrset.example. 5M IN A 10.0.5.77
+a-maximum-rrset.example. 5M IN A 10.0.5.78
+a-maximum-rrset.example. 5M IN A 10.0.5.79
+a-maximum-rrset.example. 5M IN A 10.0.5.80
+a-maximum-rrset.example. 5M IN A 10.0.5.81
+a-maximum-rrset.example. 5M IN A 10.0.5.82
+a-maximum-rrset.example. 5M IN A 10.0.5.83
+a-maximum-rrset.example. 5M IN A 10.0.5.84
+a-maximum-rrset.example. 5M IN A 10.0.5.85
+a-maximum-rrset.example. 5M IN A 10.0.5.86
+a-maximum-rrset.example. 5M IN A 10.0.5.87
+a-maximum-rrset.example. 5M IN A 10.0.5.88
+a-maximum-rrset.example. 5M IN A 10.0.5.89
+a-maximum-rrset.example. 5M IN A 10.0.5.90
+a-maximum-rrset.example. 5M IN A 10.0.5.91
+a-maximum-rrset.example. 5M IN A 10.0.5.92
+a-maximum-rrset.example. 5M IN A 10.0.5.93
+a-maximum-rrset.example. 5M IN A 10.0.5.94
+a-maximum-rrset.example. 5M IN A 10.0.5.95
+a-maximum-rrset.example. 5M IN A 10.0.5.96
+a-maximum-rrset.example. 5M IN A 10.0.5.97
+a-maximum-rrset.example. 5M IN A 10.0.5.98
+a-maximum-rrset.example. 5M IN A 10.0.5.99
+a-maximum-rrset.example. 5M IN A 10.0.5.100
+a-maximum-rrset.example. 5M IN A 10.0.5.101
+a-maximum-rrset.example. 5M IN A 10.0.5.102
+a-maximum-rrset.example. 5M IN A 10.0.5.103
+a-maximum-rrset.example. 5M IN A 10.0.5.104
+a-maximum-rrset.example. 5M IN A 10.0.5.105
+a-maximum-rrset.example. 5M IN A 10.0.5.106
+a-maximum-rrset.example. 5M IN A 10.0.5.107
+a-maximum-rrset.example. 5M IN A 10.0.5.108
+a-maximum-rrset.example. 5M IN A 10.0.5.109
+a-maximum-rrset.example. 5M IN A 10.0.5.110
+a-maximum-rrset.example. 5M IN A 10.0.5.111
+a-maximum-rrset.example. 5M IN A 10.0.5.112
+a-maximum-rrset.example. 5M IN A 10.0.5.113
+a-maximum-rrset.example. 5M IN A 10.0.5.114
+a-maximum-rrset.example. 5M IN A 10.0.5.115
+a-maximum-rrset.example. 5M IN A 10.0.5.116
+a-maximum-rrset.example. 5M IN A 10.0.5.117
+a-maximum-rrset.example. 5M IN A 10.0.5.118
+a-maximum-rrset.example. 5M IN A 10.0.5.119
+a-maximum-rrset.example. 5M IN A 10.0.5.120
+a-maximum-rrset.example. 5M IN A 10.0.5.121
+a-maximum-rrset.example. 5M IN A 10.0.5.122
+a-maximum-rrset.example. 5M IN A 10.0.5.123
+a-maximum-rrset.example. 5M IN A 10.0.5.124
+a-maximum-rrset.example. 5M IN A 10.0.5.125
+a-maximum-rrset.example. 5M IN A 10.0.5.126
+a-maximum-rrset.example. 5M IN A 10.0.5.127
+a-maximum-rrset.example. 5M IN A 10.0.5.128
+a-maximum-rrset.example. 5M IN A 10.0.5.129
+a-maximum-rrset.example. 5M IN A 10.0.5.130
+a-maximum-rrset.example. 5M IN A 10.0.5.131
+a-maximum-rrset.example. 5M IN A 10.0.5.132
+a-maximum-rrset.example. 5M IN A 10.0.5.133
+a-maximum-rrset.example. 5M IN A 10.0.5.134
+a-maximum-rrset.example. 5M IN A 10.0.5.135
+a-maximum-rrset.example. 5M IN A 10.0.5.136
+a-maximum-rrset.example. 5M IN A 10.0.5.137
+a-maximum-rrset.example. 5M IN A 10.0.5.138
+a-maximum-rrset.example. 5M IN A 10.0.5.139
+a-maximum-rrset.example. 5M IN A 10.0.5.140
+a-maximum-rrset.example. 5M IN A 10.0.5.141
+a-maximum-rrset.example. 5M IN A 10.0.5.142
+a-maximum-rrset.example. 5M IN A 10.0.5.143
+a-maximum-rrset.example. 5M IN A 10.0.5.144
+a-maximum-rrset.example. 5M IN A 10.0.5.145
+a-maximum-rrset.example. 5M IN A 10.0.5.146
+a-maximum-rrset.example. 5M IN A 10.0.5.147
+a-maximum-rrset.example. 5M IN A 10.0.5.148
+a-maximum-rrset.example. 5M IN A 10.0.5.149
+a-maximum-rrset.example. 5M IN A 10.0.5.150
+a-maximum-rrset.example. 5M IN A 10.0.5.151
+a-maximum-rrset.example. 5M IN A 10.0.5.152
+a-maximum-rrset.example. 5M IN A 10.0.5.153
+a-maximum-rrset.example. 5M IN A 10.0.5.154
+a-maximum-rrset.example. 5M IN A 10.0.5.155
+a-maximum-rrset.example. 5M IN A 10.0.5.156
+a-maximum-rrset.example. 5M IN A 10.0.5.157
+a-maximum-rrset.example. 5M IN A 10.0.5.158
+a-maximum-rrset.example. 5M IN A 10.0.5.159
+a-maximum-rrset.example. 5M IN A 10.0.5.160
+a-maximum-rrset.example. 5M IN A 10.0.5.161
+a-maximum-rrset.example. 5M IN A 10.0.5.162
+a-maximum-rrset.example. 5M IN A 10.0.5.163
+a-maximum-rrset.example. 5M IN A 10.0.5.164
+a-maximum-rrset.example. 5M IN A 10.0.5.165
+a-maximum-rrset.example. 5M IN A 10.0.5.166
+a-maximum-rrset.example. 5M IN A 10.0.5.167
+a-maximum-rrset.example. 5M IN A 10.0.5.168
+a-maximum-rrset.example. 5M IN A 10.0.5.169
+a-maximum-rrset.example. 5M IN A 10.0.5.170
+a-maximum-rrset.example. 5M IN A 10.0.5.171
+a-maximum-rrset.example. 5M IN A 10.0.5.172
+a-maximum-rrset.example. 5M IN A 10.0.5.173
+a-maximum-rrset.example. 5M IN A 10.0.5.174
+a-maximum-rrset.example. 5M IN A 10.0.5.175
+a-maximum-rrset.example. 5M IN A 10.0.5.176
+a-maximum-rrset.example. 5M IN A 10.0.5.177
+a-maximum-rrset.example. 5M IN A 10.0.5.178
+a-maximum-rrset.example. 5M IN A 10.0.5.179
+a-maximum-rrset.example. 5M IN A 10.0.5.180
+a-maximum-rrset.example. 5M IN A 10.0.5.181
+a-maximum-rrset.example. 5M IN A 10.0.5.182
+a-maximum-rrset.example. 5M IN A 10.0.5.183
+a-maximum-rrset.example. 5M IN A 10.0.5.184
+a-maximum-rrset.example. 5M IN A 10.0.5.185
+a-maximum-rrset.example. 5M IN A 10.0.5.186
+a-maximum-rrset.example. 5M IN A 10.0.5.187
+a-maximum-rrset.example. 5M IN A 10.0.5.188
+a-maximum-rrset.example. 5M IN A 10.0.5.189
+a-maximum-rrset.example. 5M IN A 10.0.5.190
+a-maximum-rrset.example. 5M IN A 10.0.5.191
+a-maximum-rrset.example. 5M IN A 10.0.5.192
+a-maximum-rrset.example. 5M IN A 10.0.5.193
+a-maximum-rrset.example. 5M IN A 10.0.5.194
+a-maximum-rrset.example. 5M IN A 10.0.5.195
+a-maximum-rrset.example. 5M IN A 10.0.5.196
+a-maximum-rrset.example. 5M IN A 10.0.5.197
+a-maximum-rrset.example. 5M IN A 10.0.5.198
+a-maximum-rrset.example. 5M IN A 10.0.5.199
+a-maximum-rrset.example. 5M IN A 10.0.5.200
+a-maximum-rrset.example. 5M IN A 10.0.5.201
+a-maximum-rrset.example. 5M IN A 10.0.5.202
+a-maximum-rrset.example. 5M IN A 10.0.5.203
+a-maximum-rrset.example. 5M IN A 10.0.5.204
+a-maximum-rrset.example. 5M IN A 10.0.5.205
+a-maximum-rrset.example. 5M IN A 10.0.5.206
+a-maximum-rrset.example. 5M IN A 10.0.5.207
+a-maximum-rrset.example. 5M IN A 10.0.5.208
+a-maximum-rrset.example. 5M IN A 10.0.5.209
+a-maximum-rrset.example. 5M IN A 10.0.5.210
+a-maximum-rrset.example. 5M IN A 10.0.5.211
+a-maximum-rrset.example. 5M IN A 10.0.5.212
+a-maximum-rrset.example. 5M IN A 10.0.5.213
+a-maximum-rrset.example. 5M IN A 10.0.5.214
+a-maximum-rrset.example. 5M IN A 10.0.5.215
+a-maximum-rrset.example. 5M IN A 10.0.5.216
+a-maximum-rrset.example. 5M IN A 10.0.5.217
+a-maximum-rrset.example. 5M IN A 10.0.5.218
+a-maximum-rrset.example. 5M IN A 10.0.5.219
+a-maximum-rrset.example. 5M IN A 10.0.5.220
+a-maximum-rrset.example. 5M IN A 10.0.5.221
+a-maximum-rrset.example. 5M IN A 10.0.5.222
+a-maximum-rrset.example. 5M IN A 10.0.5.223
+a-maximum-rrset.example. 5M IN A 10.0.5.224
+a-maximum-rrset.example. 5M IN A 10.0.5.225
+a-maximum-rrset.example. 5M IN A 10.0.5.226
+a-maximum-rrset.example. 5M IN A 10.0.5.227
+a-maximum-rrset.example. 5M IN A 10.0.5.228
+a-maximum-rrset.example. 5M IN A 10.0.5.229
+a-maximum-rrset.example. 5M IN A 10.0.5.230
+a-maximum-rrset.example. 5M IN A 10.0.5.231
+a-maximum-rrset.example. 5M IN A 10.0.5.232
+a-maximum-rrset.example. 5M IN A 10.0.5.233
+a-maximum-rrset.example. 5M IN A 10.0.5.234
+a-maximum-rrset.example. 5M IN A 10.0.5.235
+a-maximum-rrset.example. 5M IN A 10.0.5.236
+a-maximum-rrset.example. 5M IN A 10.0.5.237
+a-maximum-rrset.example. 5M IN A 10.0.5.238
+a-maximum-rrset.example. 5M IN A 10.0.5.239
+a-maximum-rrset.example. 5M IN A 10.0.5.240
+a-maximum-rrset.example. 5M IN A 10.0.5.241
+a-maximum-rrset.example. 5M IN A 10.0.5.242
+a-maximum-rrset.example. 5M IN A 10.0.5.243
+a-maximum-rrset.example. 5M IN A 10.0.5.244
+a-maximum-rrset.example. 5M IN A 10.0.5.245
+a-maximum-rrset.example. 5M IN A 10.0.5.246
+a-maximum-rrset.example. 5M IN A 10.0.5.247
+a-maximum-rrset.example. 5M IN A 10.0.5.248
+a-maximum-rrset.example. 5M IN A 10.0.5.249
+a-maximum-rrset.example. 5M IN A 10.0.5.250
+a-maximum-rrset.example. 5M IN A 10.0.5.251
+a-maximum-rrset.example. 5M IN A 10.0.5.252
+a-maximum-rrset.example. 5M IN A 10.0.5.253
+a-maximum-rrset.example. 5M IN A 10.0.5.254
+a-maximum-rrset.example. 5M IN A 10.0.5.255
+a-maximum-rrset.example. 5M IN A 10.0.6.0
+a-maximum-rrset.example. 5M IN A 10.0.6.1
+a-maximum-rrset.example. 5M IN A 10.0.6.2
+a-maximum-rrset.example. 5M IN A 10.0.6.3
+a-maximum-rrset.example. 5M IN A 10.0.6.4
+a-maximum-rrset.example. 5M IN A 10.0.6.5
+a-maximum-rrset.example. 5M IN A 10.0.6.6
+a-maximum-rrset.example. 5M IN A 10.0.6.7
+a-maximum-rrset.example. 5M IN A 10.0.6.8
+a-maximum-rrset.example. 5M IN A 10.0.6.9
+a-maximum-rrset.example. 5M IN A 10.0.6.10
+a-maximum-rrset.example. 5M IN A 10.0.6.11
+a-maximum-rrset.example. 5M IN A 10.0.6.12
+a-maximum-rrset.example. 5M IN A 10.0.6.13
+a-maximum-rrset.example. 5M IN A 10.0.6.14
+a-maximum-rrset.example. 5M IN A 10.0.6.15
+a-maximum-rrset.example. 5M IN A 10.0.6.16
+a-maximum-rrset.example. 5M IN A 10.0.6.17
+a-maximum-rrset.example. 5M IN A 10.0.6.18
+a-maximum-rrset.example. 5M IN A 10.0.6.19
+a-maximum-rrset.example. 5M IN A 10.0.6.20
+a-maximum-rrset.example. 5M IN A 10.0.6.21
+a-maximum-rrset.example. 5M IN A 10.0.6.22
+a-maximum-rrset.example. 5M IN A 10.0.6.23
+a-maximum-rrset.example. 5M IN A 10.0.6.24
+a-maximum-rrset.example. 5M IN A 10.0.6.25
+a-maximum-rrset.example. 5M IN A 10.0.6.26
+a-maximum-rrset.example. 5M IN A 10.0.6.27
+a-maximum-rrset.example. 5M IN A 10.0.6.28
+a-maximum-rrset.example. 5M IN A 10.0.6.29
+a-maximum-rrset.example. 5M IN A 10.0.6.30
+a-maximum-rrset.example. 5M IN A 10.0.6.31
+a-maximum-rrset.example. 5M IN A 10.0.6.32
+a-maximum-rrset.example. 5M IN A 10.0.6.33
+a-maximum-rrset.example. 5M IN A 10.0.6.34
+a-maximum-rrset.example. 5M IN A 10.0.6.35
+a-maximum-rrset.example. 5M IN A 10.0.6.36
+a-maximum-rrset.example. 5M IN A 10.0.6.37
+a-maximum-rrset.example. 5M IN A 10.0.6.38
+a-maximum-rrset.example. 5M IN A 10.0.6.39
+a-maximum-rrset.example. 5M IN A 10.0.6.40
+a-maximum-rrset.example. 5M IN A 10.0.6.41
+a-maximum-rrset.example. 5M IN A 10.0.6.42
+a-maximum-rrset.example. 5M IN A 10.0.6.43
+a-maximum-rrset.example. 5M IN A 10.0.6.44
+a-maximum-rrset.example. 5M IN A 10.0.6.45
+a-maximum-rrset.example. 5M IN A 10.0.6.46
+a-maximum-rrset.example. 5M IN A 10.0.6.47
+a-maximum-rrset.example. 5M IN A 10.0.6.48
+a-maximum-rrset.example. 5M IN A 10.0.6.49
+a-maximum-rrset.example. 5M IN A 10.0.6.50
+a-maximum-rrset.example. 5M IN A 10.0.6.51
+a-maximum-rrset.example. 5M IN A 10.0.6.52
+a-maximum-rrset.example. 5M IN A 10.0.6.53
+a-maximum-rrset.example. 5M IN A 10.0.6.54
+a-maximum-rrset.example. 5M IN A 10.0.6.55
+a-maximum-rrset.example. 5M IN A 10.0.6.56
+a-maximum-rrset.example. 5M IN A 10.0.6.57
+a-maximum-rrset.example. 5M IN A 10.0.6.58
+a-maximum-rrset.example. 5M IN A 10.0.6.59
+a-maximum-rrset.example. 5M IN A 10.0.6.60
+a-maximum-rrset.example. 5M IN A 10.0.6.61
+a-maximum-rrset.example. 5M IN A 10.0.6.62
+a-maximum-rrset.example. 5M IN A 10.0.6.63
+a-maximum-rrset.example. 5M IN A 10.0.6.64
+a-maximum-rrset.example. 5M IN A 10.0.6.65
+a-maximum-rrset.example. 5M IN A 10.0.6.66
+a-maximum-rrset.example. 5M IN A 10.0.6.67
+a-maximum-rrset.example. 5M IN A 10.0.6.68
+a-maximum-rrset.example. 5M IN A 10.0.6.69
+a-maximum-rrset.example. 5M IN A 10.0.6.70
+a-maximum-rrset.example. 5M IN A 10.0.6.71
+a-maximum-rrset.example. 5M IN A 10.0.6.72
+a-maximum-rrset.example. 5M IN A 10.0.6.73
+a-maximum-rrset.example. 5M IN A 10.0.6.74
+a-maximum-rrset.example. 5M IN A 10.0.6.75
+a-maximum-rrset.example. 5M IN A 10.0.6.76
+a-maximum-rrset.example. 5M IN A 10.0.6.77
+a-maximum-rrset.example. 5M IN A 10.0.6.78
+a-maximum-rrset.example. 5M IN A 10.0.6.79
+a-maximum-rrset.example. 5M IN A 10.0.6.80
+a-maximum-rrset.example. 5M IN A 10.0.6.81
+a-maximum-rrset.example. 5M IN A 10.0.6.82
+a-maximum-rrset.example. 5M IN A 10.0.6.83
+a-maximum-rrset.example. 5M IN A 10.0.6.84
+a-maximum-rrset.example. 5M IN A 10.0.6.85
+a-maximum-rrset.example. 5M IN A 10.0.6.86
+a-maximum-rrset.example. 5M IN A 10.0.6.87
+a-maximum-rrset.example. 5M IN A 10.0.6.88
+a-maximum-rrset.example. 5M IN A 10.0.6.89
+a-maximum-rrset.example. 5M IN A 10.0.6.90
+a-maximum-rrset.example. 5M IN A 10.0.6.91
+a-maximum-rrset.example. 5M IN A 10.0.6.92
+a-maximum-rrset.example. 5M IN A 10.0.6.93
+a-maximum-rrset.example. 5M IN A 10.0.6.94
+a-maximum-rrset.example. 5M IN A 10.0.6.95
+a-maximum-rrset.example. 5M IN A 10.0.6.96
+a-maximum-rrset.example. 5M IN A 10.0.6.97
+a-maximum-rrset.example. 5M IN A 10.0.6.98
+a-maximum-rrset.example. 5M IN A 10.0.6.99
+a-maximum-rrset.example. 5M IN A 10.0.6.100
+a-maximum-rrset.example. 5M IN A 10.0.6.101
+a-maximum-rrset.example. 5M IN A 10.0.6.102
+a-maximum-rrset.example. 5M IN A 10.0.6.103
+a-maximum-rrset.example. 5M IN A 10.0.6.104
+a-maximum-rrset.example. 5M IN A 10.0.6.105
+a-maximum-rrset.example. 5M IN A 10.0.6.106
+a-maximum-rrset.example. 5M IN A 10.0.6.107
+a-maximum-rrset.example. 5M IN A 10.0.6.108
+a-maximum-rrset.example. 5M IN A 10.0.6.109
+a-maximum-rrset.example. 5M IN A 10.0.6.110
+a-maximum-rrset.example. 5M IN A 10.0.6.111
+a-maximum-rrset.example. 5M IN A 10.0.6.112
+a-maximum-rrset.example. 5M IN A 10.0.6.113
+a-maximum-rrset.example. 5M IN A 10.0.6.114
+a-maximum-rrset.example. 5M IN A 10.0.6.115
+a-maximum-rrset.example. 5M IN A 10.0.6.116
+a-maximum-rrset.example. 5M IN A 10.0.6.117
+a-maximum-rrset.example. 5M IN A 10.0.6.118
+a-maximum-rrset.example. 5M IN A 10.0.6.119
+a-maximum-rrset.example. 5M IN A 10.0.6.120
+a-maximum-rrset.example. 5M IN A 10.0.6.121
+a-maximum-rrset.example. 5M IN A 10.0.6.122
+a-maximum-rrset.example. 5M IN A 10.0.6.123
+a-maximum-rrset.example. 5M IN A 10.0.6.124
+a-maximum-rrset.example. 5M IN A 10.0.6.125
+a-maximum-rrset.example. 5M IN A 10.0.6.126
+a-maximum-rrset.example. 5M IN A 10.0.6.127
+a-maximum-rrset.example. 5M IN A 10.0.6.128
+a-maximum-rrset.example. 5M IN A 10.0.6.129
+a-maximum-rrset.example. 5M IN A 10.0.6.130
+a-maximum-rrset.example. 5M IN A 10.0.6.131
+a-maximum-rrset.example. 5M IN A 10.0.6.132
+a-maximum-rrset.example. 5M IN A 10.0.6.133
+a-maximum-rrset.example. 5M IN A 10.0.6.134
+a-maximum-rrset.example. 5M IN A 10.0.6.135
+a-maximum-rrset.example. 5M IN A 10.0.6.136
+a-maximum-rrset.example. 5M IN A 10.0.6.137
+a-maximum-rrset.example. 5M IN A 10.0.6.138
+a-maximum-rrset.example. 5M IN A 10.0.6.139
+a-maximum-rrset.example. 5M IN A 10.0.6.140
+a-maximum-rrset.example. 5M IN A 10.0.6.141
+a-maximum-rrset.example. 5M IN A 10.0.6.142
+a-maximum-rrset.example. 5M IN A 10.0.6.143
+a-maximum-rrset.example. 5M IN A 10.0.6.144
+a-maximum-rrset.example. 5M IN A 10.0.6.145
+a-maximum-rrset.example. 5M IN A 10.0.6.146
+a-maximum-rrset.example. 5M IN A 10.0.6.147
+a-maximum-rrset.example. 5M IN A 10.0.6.148
+a-maximum-rrset.example. 5M IN A 10.0.6.149
+a-maximum-rrset.example. 5M IN A 10.0.6.150
+a-maximum-rrset.example. 5M IN A 10.0.6.151
+a-maximum-rrset.example. 5M IN A 10.0.6.152
+a-maximum-rrset.example. 5M IN A 10.0.6.153
+a-maximum-rrset.example. 5M IN A 10.0.6.154
+a-maximum-rrset.example. 5M IN A 10.0.6.155
+a-maximum-rrset.example. 5M IN A 10.0.6.156
+a-maximum-rrset.example. 5M IN A 10.0.6.157
+a-maximum-rrset.example. 5M IN A 10.0.6.158
+a-maximum-rrset.example. 5M IN A 10.0.6.159
+a-maximum-rrset.example. 5M IN A 10.0.6.160
+a-maximum-rrset.example. 5M IN A 10.0.6.161
+a-maximum-rrset.example. 5M IN A 10.0.6.162
+a-maximum-rrset.example. 5M IN A 10.0.6.163
+a-maximum-rrset.example. 5M IN A 10.0.6.164
+a-maximum-rrset.example. 5M IN A 10.0.6.165
+a-maximum-rrset.example. 5M IN A 10.0.6.166
+a-maximum-rrset.example. 5M IN A 10.0.6.167
+a-maximum-rrset.example. 5M IN A 10.0.6.168
+a-maximum-rrset.example. 5M IN A 10.0.6.169
+a-maximum-rrset.example. 5M IN A 10.0.6.170
+a-maximum-rrset.example. 5M IN A 10.0.6.171
+a-maximum-rrset.example. 5M IN A 10.0.6.172
+a-maximum-rrset.example. 5M IN A 10.0.6.173
+a-maximum-rrset.example. 5M IN A 10.0.6.174
+a-maximum-rrset.example. 5M IN A 10.0.6.175
+a-maximum-rrset.example. 5M IN A 10.0.6.176
+a-maximum-rrset.example. 5M IN A 10.0.6.177
+a-maximum-rrset.example. 5M IN A 10.0.6.178
+a-maximum-rrset.example. 5M IN A 10.0.6.179
+a-maximum-rrset.example. 5M IN A 10.0.6.180
+a-maximum-rrset.example. 5M IN A 10.0.6.181
+a-maximum-rrset.example. 5M IN A 10.0.6.182
+a-maximum-rrset.example. 5M IN A 10.0.6.183
+a-maximum-rrset.example. 5M IN A 10.0.6.184
+a-maximum-rrset.example. 5M IN A 10.0.6.185
+a-maximum-rrset.example. 5M IN A 10.0.6.186
+a-maximum-rrset.example. 5M IN A 10.0.6.187
+a-maximum-rrset.example. 5M IN A 10.0.6.188
+a-maximum-rrset.example. 5M IN A 10.0.6.189
+a-maximum-rrset.example. 5M IN A 10.0.6.190
+a-maximum-rrset.example. 5M IN A 10.0.6.191
+a-maximum-rrset.example. 5M IN A 10.0.6.192
+a-maximum-rrset.example. 5M IN A 10.0.6.193
+a-maximum-rrset.example. 5M IN A 10.0.6.194
+a-maximum-rrset.example. 5M IN A 10.0.6.195
+a-maximum-rrset.example. 5M IN A 10.0.6.196
+a-maximum-rrset.example. 5M IN A 10.0.6.197
+a-maximum-rrset.example. 5M IN A 10.0.6.198
+a-maximum-rrset.example. 5M IN A 10.0.6.199
+a-maximum-rrset.example. 5M IN A 10.0.6.200
+a-maximum-rrset.example. 5M IN A 10.0.6.201
+a-maximum-rrset.example. 5M IN A 10.0.6.202
+a-maximum-rrset.example. 5M IN A 10.0.6.203
+a-maximum-rrset.example. 5M IN A 10.0.6.204
+a-maximum-rrset.example. 5M IN A 10.0.6.205
+a-maximum-rrset.example. 5M IN A 10.0.6.206
+a-maximum-rrset.example. 5M IN A 10.0.6.207
+a-maximum-rrset.example. 5M IN A 10.0.6.208
+a-maximum-rrset.example. 5M IN A 10.0.6.209
+a-maximum-rrset.example. 5M IN A 10.0.6.210
+a-maximum-rrset.example. 5M IN A 10.0.6.211
+a-maximum-rrset.example. 5M IN A 10.0.6.212
+a-maximum-rrset.example. 5M IN A 10.0.6.213
+a-maximum-rrset.example. 5M IN A 10.0.6.214
+a-maximum-rrset.example. 5M IN A 10.0.6.215
+a-maximum-rrset.example. 5M IN A 10.0.6.216
+a-maximum-rrset.example. 5M IN A 10.0.6.217
+a-maximum-rrset.example. 5M IN A 10.0.6.218
+a-maximum-rrset.example. 5M IN A 10.0.6.219
+a-maximum-rrset.example. 5M IN A 10.0.6.220
+a-maximum-rrset.example. 5M IN A 10.0.6.221
+a-maximum-rrset.example. 5M IN A 10.0.6.222
+a-maximum-rrset.example. 5M IN A 10.0.6.223
+a-maximum-rrset.example. 5M IN A 10.0.6.224
+a-maximum-rrset.example. 5M IN A 10.0.6.225
+a-maximum-rrset.example. 5M IN A 10.0.6.226
+a-maximum-rrset.example. 5M IN A 10.0.6.227
+a-maximum-rrset.example. 5M IN A 10.0.6.228
+a-maximum-rrset.example. 5M IN A 10.0.6.229
+a-maximum-rrset.example. 5M IN A 10.0.6.230
+a-maximum-rrset.example. 5M IN A 10.0.6.231
+a-maximum-rrset.example. 5M IN A 10.0.6.232
+a-maximum-rrset.example. 5M IN A 10.0.6.233
+a-maximum-rrset.example. 5M IN A 10.0.6.234
+a-maximum-rrset.example. 5M IN A 10.0.6.235
+a-maximum-rrset.example. 5M IN A 10.0.6.236
+a-maximum-rrset.example. 5M IN A 10.0.6.237
+a-maximum-rrset.example. 5M IN A 10.0.6.238
+a-maximum-rrset.example. 5M IN A 10.0.6.239
+a-maximum-rrset.example. 5M IN A 10.0.6.240
+a-maximum-rrset.example. 5M IN A 10.0.6.241
+a-maximum-rrset.example. 5M IN A 10.0.6.242
+a-maximum-rrset.example. 5M IN A 10.0.6.243
+a-maximum-rrset.example. 5M IN A 10.0.6.244
+a-maximum-rrset.example. 5M IN A 10.0.6.245
+a-maximum-rrset.example. 5M IN A 10.0.6.246
+a-maximum-rrset.example. 5M IN A 10.0.6.247
+a-maximum-rrset.example. 5M IN A 10.0.6.248
+a-maximum-rrset.example. 5M IN A 10.0.6.249
+a-maximum-rrset.example. 5M IN A 10.0.6.250
+a-maximum-rrset.example. 5M IN A 10.0.6.251
+a-maximum-rrset.example. 5M IN A 10.0.6.252
+a-maximum-rrset.example. 5M IN A 10.0.6.253
+a-maximum-rrset.example. 5M IN A 10.0.6.254
+a-maximum-rrset.example. 5M IN A 10.0.6.255
+a-maximum-rrset.example. 5M IN A 10.0.7.0
+a-maximum-rrset.example. 5M IN A 10.0.7.1
+a-maximum-rrset.example. 5M IN A 10.0.7.2
+a-maximum-rrset.example. 5M IN A 10.0.7.3
+a-maximum-rrset.example. 5M IN A 10.0.7.4
+a-maximum-rrset.example. 5M IN A 10.0.7.5
+a-maximum-rrset.example. 5M IN A 10.0.7.6
+a-maximum-rrset.example. 5M IN A 10.0.7.7
+a-maximum-rrset.example. 5M IN A 10.0.7.8
+a-maximum-rrset.example. 5M IN A 10.0.7.9
+a-maximum-rrset.example. 5M IN A 10.0.7.10
+a-maximum-rrset.example. 5M IN A 10.0.7.11
+a-maximum-rrset.example. 5M IN A 10.0.7.12
+a-maximum-rrset.example. 5M IN A 10.0.7.13
+a-maximum-rrset.example. 5M IN A 10.0.7.14
+a-maximum-rrset.example. 5M IN A 10.0.7.15
+a-maximum-rrset.example. 5M IN A 10.0.7.16
+a-maximum-rrset.example. 5M IN A 10.0.7.17
+a-maximum-rrset.example. 5M IN A 10.0.7.18
+a-maximum-rrset.example. 5M IN A 10.0.7.19
+a-maximum-rrset.example. 5M IN A 10.0.7.20
+a-maximum-rrset.example. 5M IN A 10.0.7.21
+a-maximum-rrset.example. 5M IN A 10.0.7.22
+a-maximum-rrset.example. 5M IN A 10.0.7.23
+a-maximum-rrset.example. 5M IN A 10.0.7.24
+a-maximum-rrset.example. 5M IN A 10.0.7.25
+a-maximum-rrset.example. 5M IN A 10.0.7.26
+a-maximum-rrset.example. 5M IN A 10.0.7.27
+a-maximum-rrset.example. 5M IN A 10.0.7.28
+a-maximum-rrset.example. 5M IN A 10.0.7.29
+a-maximum-rrset.example. 5M IN A 10.0.7.30
+a-maximum-rrset.example. 5M IN A 10.0.7.31
+a-maximum-rrset.example. 5M IN A 10.0.7.32
+a-maximum-rrset.example. 5M IN A 10.0.7.33
+a-maximum-rrset.example. 5M IN A 10.0.7.34
+a-maximum-rrset.example. 5M IN A 10.0.7.35
+a-maximum-rrset.example. 5M IN A 10.0.7.36
+a-maximum-rrset.example. 5M IN A 10.0.7.37
+a-maximum-rrset.example. 5M IN A 10.0.7.38
+a-maximum-rrset.example. 5M IN A 10.0.7.39
+a-maximum-rrset.example. 5M IN A 10.0.7.40
+a-maximum-rrset.example. 5M IN A 10.0.7.41
+a-maximum-rrset.example. 5M IN A 10.0.7.42
+a-maximum-rrset.example. 5M IN A 10.0.7.43
+a-maximum-rrset.example. 5M IN A 10.0.7.44
+a-maximum-rrset.example. 5M IN A 10.0.7.45
+a-maximum-rrset.example. 5M IN A 10.0.7.46
+a-maximum-rrset.example. 5M IN A 10.0.7.47
+a-maximum-rrset.example. 5M IN A 10.0.7.48
+a-maximum-rrset.example. 5M IN A 10.0.7.49
+a-maximum-rrset.example. 5M IN A 10.0.7.50
+a-maximum-rrset.example. 5M IN A 10.0.7.51
+a-maximum-rrset.example. 5M IN A 10.0.7.52
+a-maximum-rrset.example. 5M IN A 10.0.7.53
+a-maximum-rrset.example. 5M IN A 10.0.7.54
+a-maximum-rrset.example. 5M IN A 10.0.7.55
+a-maximum-rrset.example. 5M IN A 10.0.7.56
+a-maximum-rrset.example. 5M IN A 10.0.7.57
+a-maximum-rrset.example. 5M IN A 10.0.7.58
+a-maximum-rrset.example. 5M IN A 10.0.7.59
+a-maximum-rrset.example. 5M IN A 10.0.7.60
+a-maximum-rrset.example. 5M IN A 10.0.7.61
+a-maximum-rrset.example. 5M IN A 10.0.7.62
+a-maximum-rrset.example. 5M IN A 10.0.7.63
+a-maximum-rrset.example. 5M IN A 10.0.7.64
+a-maximum-rrset.example. 5M IN A 10.0.7.65
+a-maximum-rrset.example. 5M IN A 10.0.7.66
+a-maximum-rrset.example. 5M IN A 10.0.7.67
+a-maximum-rrset.example. 5M IN A 10.0.7.68
+a-maximum-rrset.example. 5M IN A 10.0.7.69
+a-maximum-rrset.example. 5M IN A 10.0.7.70
+a-maximum-rrset.example. 5M IN A 10.0.7.71
+a-maximum-rrset.example. 5M IN A 10.0.7.72
+a-maximum-rrset.example. 5M IN A 10.0.7.73
+a-maximum-rrset.example. 5M IN A 10.0.7.74
+a-maximum-rrset.example. 5M IN A 10.0.7.75
+a-maximum-rrset.example. 5M IN A 10.0.7.76
+a-maximum-rrset.example. 5M IN A 10.0.7.77
+a-maximum-rrset.example. 5M IN A 10.0.7.78
+a-maximum-rrset.example. 5M IN A 10.0.7.79
+a-maximum-rrset.example. 5M IN A 10.0.7.80
+a-maximum-rrset.example. 5M IN A 10.0.7.81
+a-maximum-rrset.example. 5M IN A 10.0.7.82
+a-maximum-rrset.example. 5M IN A 10.0.7.83
+a-maximum-rrset.example. 5M IN A 10.0.7.84
+a-maximum-rrset.example. 5M IN A 10.0.7.85
+a-maximum-rrset.example. 5M IN A 10.0.7.86
+a-maximum-rrset.example. 5M IN A 10.0.7.87
+a-maximum-rrset.example. 5M IN A 10.0.7.88
+a-maximum-rrset.example. 5M IN A 10.0.7.89
+a-maximum-rrset.example. 5M IN A 10.0.7.90
+a-maximum-rrset.example. 5M IN A 10.0.7.91
+a-maximum-rrset.example. 5M IN A 10.0.7.92
+a-maximum-rrset.example. 5M IN A 10.0.7.93
+a-maximum-rrset.example. 5M IN A 10.0.7.94
+a-maximum-rrset.example. 5M IN A 10.0.7.95
+a-maximum-rrset.example. 5M IN A 10.0.7.96
+a-maximum-rrset.example. 5M IN A 10.0.7.97
+a-maximum-rrset.example. 5M IN A 10.0.7.98
+a-maximum-rrset.example. 5M IN A 10.0.7.99
+a-maximum-rrset.example. 5M IN A 10.0.7.100
+a-maximum-rrset.example. 5M IN A 10.0.7.101
+a-maximum-rrset.example. 5M IN A 10.0.7.102
+a-maximum-rrset.example. 5M IN A 10.0.7.103
+a-maximum-rrset.example. 5M IN A 10.0.7.104
+a-maximum-rrset.example. 5M IN A 10.0.7.105
+a-maximum-rrset.example. 5M IN A 10.0.7.106
+a-maximum-rrset.example. 5M IN A 10.0.7.107
+a-maximum-rrset.example. 5M IN A 10.0.7.108
+a-maximum-rrset.example. 5M IN A 10.0.7.109
+a-maximum-rrset.example. 5M IN A 10.0.7.110
+a-maximum-rrset.example. 5M IN A 10.0.7.111
+a-maximum-rrset.example. 5M IN A 10.0.7.112
+a-maximum-rrset.example. 5M IN A 10.0.7.113
+a-maximum-rrset.example. 5M IN A 10.0.7.114
+a-maximum-rrset.example. 5M IN A 10.0.7.115
+a-maximum-rrset.example. 5M IN A 10.0.7.116
+a-maximum-rrset.example. 5M IN A 10.0.7.117
+a-maximum-rrset.example. 5M IN A 10.0.7.118
+a-maximum-rrset.example. 5M IN A 10.0.7.119
+a-maximum-rrset.example. 5M IN A 10.0.7.120
+a-maximum-rrset.example. 5M IN A 10.0.7.121
+a-maximum-rrset.example. 5M IN A 10.0.7.122
+a-maximum-rrset.example. 5M IN A 10.0.7.123
+a-maximum-rrset.example. 5M IN A 10.0.7.124
+a-maximum-rrset.example. 5M IN A 10.0.7.125
+a-maximum-rrset.example. 5M IN A 10.0.7.126
+a-maximum-rrset.example. 5M IN A 10.0.7.127
+a-maximum-rrset.example. 5M IN A 10.0.7.128
+a-maximum-rrset.example. 5M IN A 10.0.7.129
+a-maximum-rrset.example. 5M IN A 10.0.7.130
+a-maximum-rrset.example. 5M IN A 10.0.7.131
+a-maximum-rrset.example. 5M IN A 10.0.7.132
+a-maximum-rrset.example. 5M IN A 10.0.7.133
+a-maximum-rrset.example. 5M IN A 10.0.7.134
+a-maximum-rrset.example. 5M IN A 10.0.7.135
+a-maximum-rrset.example. 5M IN A 10.0.7.136
+a-maximum-rrset.example. 5M IN A 10.0.7.137
+a-maximum-rrset.example. 5M IN A 10.0.7.138
+a-maximum-rrset.example. 5M IN A 10.0.7.139
+a-maximum-rrset.example. 5M IN A 10.0.7.140
+a-maximum-rrset.example. 5M IN A 10.0.7.141
+a-maximum-rrset.example. 5M IN A 10.0.7.142
+a-maximum-rrset.example. 5M IN A 10.0.7.143
+a-maximum-rrset.example. 5M IN A 10.0.7.144
+a-maximum-rrset.example. 5M IN A 10.0.7.145
+a-maximum-rrset.example. 5M IN A 10.0.7.146
+a-maximum-rrset.example. 5M IN A 10.0.7.147
+a-maximum-rrset.example. 5M IN A 10.0.7.148
+a-maximum-rrset.example. 5M IN A 10.0.7.149
+a-maximum-rrset.example. 5M IN A 10.0.7.150
+a-maximum-rrset.example. 5M IN A 10.0.7.151
+a-maximum-rrset.example. 5M IN A 10.0.7.152
+a-maximum-rrset.example. 5M IN A 10.0.7.153
+a-maximum-rrset.example. 5M IN A 10.0.7.154
+a-maximum-rrset.example. 5M IN A 10.0.7.155
+a-maximum-rrset.example. 5M IN A 10.0.7.156
+a-maximum-rrset.example. 5M IN A 10.0.7.157
+a-maximum-rrset.example. 5M IN A 10.0.7.158
+a-maximum-rrset.example. 5M IN A 10.0.7.159
+a-maximum-rrset.example. 5M IN A 10.0.7.160
+a-maximum-rrset.example. 5M IN A 10.0.7.161
+a-maximum-rrset.example. 5M IN A 10.0.7.162
+a-maximum-rrset.example. 5M IN A 10.0.7.163
+a-maximum-rrset.example. 5M IN A 10.0.7.164
+a-maximum-rrset.example. 5M IN A 10.0.7.165
+a-maximum-rrset.example. 5M IN A 10.0.7.166
+a-maximum-rrset.example. 5M IN A 10.0.7.167
+a-maximum-rrset.example. 5M IN A 10.0.7.168
+a-maximum-rrset.example. 5M IN A 10.0.7.169
+a-maximum-rrset.example. 5M IN A 10.0.7.170
+a-maximum-rrset.example. 5M IN A 10.0.7.171
+a-maximum-rrset.example. 5M IN A 10.0.7.172
+a-maximum-rrset.example. 5M IN A 10.0.7.173
+a-maximum-rrset.example. 5M IN A 10.0.7.174
+a-maximum-rrset.example. 5M IN A 10.0.7.175
+a-maximum-rrset.example. 5M IN A 10.0.7.176
+a-maximum-rrset.example. 5M IN A 10.0.7.177
+a-maximum-rrset.example. 5M IN A 10.0.7.178
+a-maximum-rrset.example. 5M IN A 10.0.7.179
+a-maximum-rrset.example. 5M IN A 10.0.7.180
+a-maximum-rrset.example. 5M IN A 10.0.7.181
+a-maximum-rrset.example. 5M IN A 10.0.7.182
+a-maximum-rrset.example. 5M IN A 10.0.7.183
+a-maximum-rrset.example. 5M IN A 10.0.7.184
+a-maximum-rrset.example. 5M IN A 10.0.7.185
+a-maximum-rrset.example. 5M IN A 10.0.7.186
+a-maximum-rrset.example. 5M IN A 10.0.7.187
+a-maximum-rrset.example. 5M IN A 10.0.7.188
+a-maximum-rrset.example. 5M IN A 10.0.7.189
+a-maximum-rrset.example. 5M IN A 10.0.7.190
+a-maximum-rrset.example. 5M IN A 10.0.7.191
+a-maximum-rrset.example. 5M IN A 10.0.7.192
+a-maximum-rrset.example. 5M IN A 10.0.7.193
+a-maximum-rrset.example. 5M IN A 10.0.7.194
+a-maximum-rrset.example. 5M IN A 10.0.7.195
+a-maximum-rrset.example. 5M IN A 10.0.7.196
+a-maximum-rrset.example. 5M IN A 10.0.7.197
+a-maximum-rrset.example. 5M IN A 10.0.7.198
+a-maximum-rrset.example. 5M IN A 10.0.7.199
+a-maximum-rrset.example. 5M IN A 10.0.7.200
+a-maximum-rrset.example. 5M IN A 10.0.7.201
+a-maximum-rrset.example. 5M IN A 10.0.7.202
+a-maximum-rrset.example. 5M IN A 10.0.7.203
+a-maximum-rrset.example. 5M IN A 10.0.7.204
+a-maximum-rrset.example. 5M IN A 10.0.7.205
+a-maximum-rrset.example. 5M IN A 10.0.7.206
+a-maximum-rrset.example. 5M IN A 10.0.7.207
+a-maximum-rrset.example. 5M IN A 10.0.7.208
+a-maximum-rrset.example. 5M IN A 10.0.7.209
+a-maximum-rrset.example. 5M IN A 10.0.7.210
+a-maximum-rrset.example. 5M IN A 10.0.7.211
+a-maximum-rrset.example. 5M IN A 10.0.7.212
+a-maximum-rrset.example. 5M IN A 10.0.7.213
+a-maximum-rrset.example. 5M IN A 10.0.7.214
+a-maximum-rrset.example. 5M IN A 10.0.7.215
+a-maximum-rrset.example. 5M IN A 10.0.7.216
+a-maximum-rrset.example. 5M IN A 10.0.7.217
+a-maximum-rrset.example. 5M IN A 10.0.7.218
+a-maximum-rrset.example. 5M IN A 10.0.7.219
+a-maximum-rrset.example. 5M IN A 10.0.7.220
+a-maximum-rrset.example. 5M IN A 10.0.7.221
+a-maximum-rrset.example. 5M IN A 10.0.7.222
+a-maximum-rrset.example. 5M IN A 10.0.7.223
+a-maximum-rrset.example. 5M IN A 10.0.7.224
+a-maximum-rrset.example. 5M IN A 10.0.7.225
+a-maximum-rrset.example. 5M IN A 10.0.7.226
+a-maximum-rrset.example. 5M IN A 10.0.7.227
+a-maximum-rrset.example. 5M IN A 10.0.7.228
+a-maximum-rrset.example. 5M IN A 10.0.7.229
+a-maximum-rrset.example. 5M IN A 10.0.7.230
+a-maximum-rrset.example. 5M IN A 10.0.7.231
+a-maximum-rrset.example. 5M IN A 10.0.7.232
+a-maximum-rrset.example. 5M IN A 10.0.7.233
+a-maximum-rrset.example. 5M IN A 10.0.7.234
+a-maximum-rrset.example. 5M IN A 10.0.7.235
+a-maximum-rrset.example. 5M IN A 10.0.7.236
+a-maximum-rrset.example. 5M IN A 10.0.7.237
+a-maximum-rrset.example. 5M IN A 10.0.7.238
+a-maximum-rrset.example. 5M IN A 10.0.7.239
+a-maximum-rrset.example. 5M IN A 10.0.7.240
+a-maximum-rrset.example. 5M IN A 10.0.7.241
+a-maximum-rrset.example. 5M IN A 10.0.7.242
+a-maximum-rrset.example. 5M IN A 10.0.7.243
+a-maximum-rrset.example. 5M IN A 10.0.7.244
+a-maximum-rrset.example. 5M IN A 10.0.7.245
+a-maximum-rrset.example. 5M IN A 10.0.7.246
+a-maximum-rrset.example. 5M IN A 10.0.7.247
+a-maximum-rrset.example. 5M IN A 10.0.7.248
+a-maximum-rrset.example. 5M IN A 10.0.7.249
+a-maximum-rrset.example. 5M IN A 10.0.7.250
+a-maximum-rrset.example. 5M IN A 10.0.7.251
+a-maximum-rrset.example. 5M IN A 10.0.7.252
+a-maximum-rrset.example. 5M IN A 10.0.7.253
+a-maximum-rrset.example. 5M IN A 10.0.7.254
+a-maximum-rrset.example. 5M IN A 10.0.7.255
+a-maximum-rrset.example. 5M IN A 10.0.8.0
+a-maximum-rrset.example. 5M IN A 10.0.8.1
+a-maximum-rrset.example. 5M IN A 10.0.8.2
+a-maximum-rrset.example. 5M IN A 10.0.8.3
+a-maximum-rrset.example. 5M IN A 10.0.8.4
+a-maximum-rrset.example. 5M IN A 10.0.8.5
+a-maximum-rrset.example. 5M IN A 10.0.8.6
+a-maximum-rrset.example. 5M IN A 10.0.8.7
+a-maximum-rrset.example. 5M IN A 10.0.8.8
+a-maximum-rrset.example. 5M IN A 10.0.8.9
+a-maximum-rrset.example. 5M IN A 10.0.8.10
+a-maximum-rrset.example. 5M IN A 10.0.8.11
+a-maximum-rrset.example. 5M IN A 10.0.8.12
+a-maximum-rrset.example. 5M IN A 10.0.8.13
+a-maximum-rrset.example. 5M IN A 10.0.8.14
+a-maximum-rrset.example. 5M IN A 10.0.8.15
+a-maximum-rrset.example. 5M IN A 10.0.8.16
+a-maximum-rrset.example. 5M IN A 10.0.8.17
+a-maximum-rrset.example. 5M IN A 10.0.8.18
+a-maximum-rrset.example. 5M IN A 10.0.8.19
+a-maximum-rrset.example. 5M IN A 10.0.8.20
+a-maximum-rrset.example. 5M IN A 10.0.8.21
+a-maximum-rrset.example. 5M IN A 10.0.8.22
+a-maximum-rrset.example. 5M IN A 10.0.8.23
+a-maximum-rrset.example. 5M IN A 10.0.8.24
+a-maximum-rrset.example. 5M IN A 10.0.8.25
+a-maximum-rrset.example. 5M IN A 10.0.8.26
+a-maximum-rrset.example. 5M IN A 10.0.8.27
+a-maximum-rrset.example. 5M IN A 10.0.8.28
+a-maximum-rrset.example. 5M IN A 10.0.8.29
+a-maximum-rrset.example. 5M IN A 10.0.8.30
+a-maximum-rrset.example. 5M IN A 10.0.8.31
+a-maximum-rrset.example. 5M IN A 10.0.8.32
+a-maximum-rrset.example. 5M IN A 10.0.8.33
+a-maximum-rrset.example. 5M IN A 10.0.8.34
+a-maximum-rrset.example. 5M IN A 10.0.8.35
+a-maximum-rrset.example. 5M IN A 10.0.8.36
+a-maximum-rrset.example. 5M IN A 10.0.8.37
+a-maximum-rrset.example. 5M IN A 10.0.8.38
+a-maximum-rrset.example. 5M IN A 10.0.8.39
+a-maximum-rrset.example. 5M IN A 10.0.8.40
+a-maximum-rrset.example. 5M IN A 10.0.8.41
+a-maximum-rrset.example. 5M IN A 10.0.8.42
+a-maximum-rrset.example. 5M IN A 10.0.8.43
+a-maximum-rrset.example. 5M IN A 10.0.8.44
+a-maximum-rrset.example. 5M IN A 10.0.8.45
+a-maximum-rrset.example. 5M IN A 10.0.8.46
+a-maximum-rrset.example. 5M IN A 10.0.8.47
+a-maximum-rrset.example. 5M IN A 10.0.8.48
+a-maximum-rrset.example. 5M IN A 10.0.8.49
+a-maximum-rrset.example. 5M IN A 10.0.8.50
+a-maximum-rrset.example. 5M IN A 10.0.8.51
+a-maximum-rrset.example. 5M IN A 10.0.8.52
+a-maximum-rrset.example. 5M IN A 10.0.8.53
+a-maximum-rrset.example. 5M IN A 10.0.8.54
+a-maximum-rrset.example. 5M IN A 10.0.8.55
+a-maximum-rrset.example. 5M IN A 10.0.8.56
+a-maximum-rrset.example. 5M IN A 10.0.8.57
+a-maximum-rrset.example. 5M IN A 10.0.8.58
+a-maximum-rrset.example. 5M IN A 10.0.8.59
+a-maximum-rrset.example. 5M IN A 10.0.8.60
+a-maximum-rrset.example. 5M IN A 10.0.8.61
+a-maximum-rrset.example. 5M IN A 10.0.8.62
+a-maximum-rrset.example. 5M IN A 10.0.8.63
+a-maximum-rrset.example. 5M IN A 10.0.8.64
+a-maximum-rrset.example. 5M IN A 10.0.8.65
+a-maximum-rrset.example. 5M IN A 10.0.8.66
+a-maximum-rrset.example. 5M IN A 10.0.8.67
+a-maximum-rrset.example. 5M IN A 10.0.8.68
+a-maximum-rrset.example. 5M IN A 10.0.8.69
+a-maximum-rrset.example. 5M IN A 10.0.8.70
+a-maximum-rrset.example. 5M IN A 10.0.8.71
+a-maximum-rrset.example. 5M IN A 10.0.8.72
+a-maximum-rrset.example. 5M IN A 10.0.8.73
+a-maximum-rrset.example. 5M IN A 10.0.8.74
+a-maximum-rrset.example. 5M IN A 10.0.8.75
+a-maximum-rrset.example. 5M IN A 10.0.8.76
+a-maximum-rrset.example. 5M IN A 10.0.8.77
+a-maximum-rrset.example. 5M IN A 10.0.8.78
+a-maximum-rrset.example. 5M IN A 10.0.8.79
+a-maximum-rrset.example. 5M IN A 10.0.8.80
+a-maximum-rrset.example. 5M IN A 10.0.8.81
+a-maximum-rrset.example. 5M IN A 10.0.8.82
+a-maximum-rrset.example. 5M IN A 10.0.8.83
+a-maximum-rrset.example. 5M IN A 10.0.8.84
+a-maximum-rrset.example. 5M IN A 10.0.8.85
+a-maximum-rrset.example. 5M IN A 10.0.8.86
+a-maximum-rrset.example. 5M IN A 10.0.8.87
+a-maximum-rrset.example. 5M IN A 10.0.8.88
+a-maximum-rrset.example. 5M IN A 10.0.8.89
+a-maximum-rrset.example. 5M IN A 10.0.8.90
+a-maximum-rrset.example. 5M IN A 10.0.8.91
+a-maximum-rrset.example. 5M IN A 10.0.8.92
+a-maximum-rrset.example. 5M IN A 10.0.8.93
+a-maximum-rrset.example. 5M IN A 10.0.8.94
+a-maximum-rrset.example. 5M IN A 10.0.8.95
+a-maximum-rrset.example. 5M IN A 10.0.8.96
+a-maximum-rrset.example. 5M IN A 10.0.8.97
+a-maximum-rrset.example. 5M IN A 10.0.8.98
+a-maximum-rrset.example. 5M IN A 10.0.8.99
+a-maximum-rrset.example. 5M IN A 10.0.8.100
+a-maximum-rrset.example. 5M IN A 10.0.8.101
+a-maximum-rrset.example. 5M IN A 10.0.8.102
+a-maximum-rrset.example. 5M IN A 10.0.8.103
+a-maximum-rrset.example. 5M IN A 10.0.8.104
+a-maximum-rrset.example. 5M IN A 10.0.8.105
+a-maximum-rrset.example. 5M IN A 10.0.8.106
+a-maximum-rrset.example. 5M IN A 10.0.8.107
+a-maximum-rrset.example. 5M IN A 10.0.8.108
+a-maximum-rrset.example. 5M IN A 10.0.8.109
+a-maximum-rrset.example. 5M IN A 10.0.8.110
+a-maximum-rrset.example. 5M IN A 10.0.8.111
+a-maximum-rrset.example. 5M IN A 10.0.8.112
+a-maximum-rrset.example. 5M IN A 10.0.8.113
+a-maximum-rrset.example. 5M IN A 10.0.8.114
+a-maximum-rrset.example. 5M IN A 10.0.8.115
+a-maximum-rrset.example. 5M IN A 10.0.8.116
+a-maximum-rrset.example. 5M IN A 10.0.8.117
+a-maximum-rrset.example. 5M IN A 10.0.8.118
+a-maximum-rrset.example. 5M IN A 10.0.8.119
+a-maximum-rrset.example. 5M IN A 10.0.8.120
+a-maximum-rrset.example. 5M IN A 10.0.8.121
+a-maximum-rrset.example. 5M IN A 10.0.8.122
+a-maximum-rrset.example. 5M IN A 10.0.8.123
+a-maximum-rrset.example. 5M IN A 10.0.8.124
+a-maximum-rrset.example. 5M IN A 10.0.8.125
+a-maximum-rrset.example. 5M IN A 10.0.8.126
+a-maximum-rrset.example. 5M IN A 10.0.8.127
+a-maximum-rrset.example. 5M IN A 10.0.8.128
+a-maximum-rrset.example. 5M IN A 10.0.8.129
+a-maximum-rrset.example. 5M IN A 10.0.8.130
+a-maximum-rrset.example. 5M IN A 10.0.8.131
+a-maximum-rrset.example. 5M IN A 10.0.8.132
+a-maximum-rrset.example. 5M IN A 10.0.8.133
+a-maximum-rrset.example. 5M IN A 10.0.8.134
+a-maximum-rrset.example. 5M IN A 10.0.8.135
+a-maximum-rrset.example. 5M IN A 10.0.8.136
+a-maximum-rrset.example. 5M IN A 10.0.8.137
+a-maximum-rrset.example. 5M IN A 10.0.8.138
+a-maximum-rrset.example. 5M IN A 10.0.8.139
+a-maximum-rrset.example. 5M IN A 10.0.8.140
+a-maximum-rrset.example. 5M IN A 10.0.8.141
+a-maximum-rrset.example. 5M IN A 10.0.8.142
+a-maximum-rrset.example. 5M IN A 10.0.8.143
+a-maximum-rrset.example. 5M IN A 10.0.8.144
+a-maximum-rrset.example. 5M IN A 10.0.8.145
+a-maximum-rrset.example. 5M IN A 10.0.8.146
+a-maximum-rrset.example. 5M IN A 10.0.8.147
+a-maximum-rrset.example. 5M IN A 10.0.8.148
+a-maximum-rrset.example. 5M IN A 10.0.8.149
+a-maximum-rrset.example. 5M IN A 10.0.8.150
+a-maximum-rrset.example. 5M IN A 10.0.8.151
+a-maximum-rrset.example. 5M IN A 10.0.8.152
+a-maximum-rrset.example. 5M IN A 10.0.8.153
+a-maximum-rrset.example. 5M IN A 10.0.8.154
+a-maximum-rrset.example. 5M IN A 10.0.8.155
+a-maximum-rrset.example. 5M IN A 10.0.8.156
+a-maximum-rrset.example. 5M IN A 10.0.8.157
+a-maximum-rrset.example. 5M IN A 10.0.8.158
+a-maximum-rrset.example. 5M IN A 10.0.8.159
+a-maximum-rrset.example. 5M IN A 10.0.8.160
+a-maximum-rrset.example. 5M IN A 10.0.8.161
+a-maximum-rrset.example. 5M IN A 10.0.8.162
+a-maximum-rrset.example. 5M IN A 10.0.8.163
+a-maximum-rrset.example. 5M IN A 10.0.8.164
+a-maximum-rrset.example. 5M IN A 10.0.8.165
+a-maximum-rrset.example. 5M IN A 10.0.8.166
+a-maximum-rrset.example. 5M IN A 10.0.8.167
+a-maximum-rrset.example. 5M IN A 10.0.8.168
+a-maximum-rrset.example. 5M IN A 10.0.8.169
+a-maximum-rrset.example. 5M IN A 10.0.8.170
+a-maximum-rrset.example. 5M IN A 10.0.8.171
+a-maximum-rrset.example. 5M IN A 10.0.8.172
+a-maximum-rrset.example. 5M IN A 10.0.8.173
+a-maximum-rrset.example. 5M IN A 10.0.8.174
+a-maximum-rrset.example. 5M IN A 10.0.8.175
+a-maximum-rrset.example. 5M IN A 10.0.8.176
+a-maximum-rrset.example. 5M IN A 10.0.8.177
+a-maximum-rrset.example. 5M IN A 10.0.8.178
+a-maximum-rrset.example. 5M IN A 10.0.8.179
+a-maximum-rrset.example. 5M IN A 10.0.8.180
+a-maximum-rrset.example. 5M IN A 10.0.8.181
+a-maximum-rrset.example. 5M IN A 10.0.8.182
+a-maximum-rrset.example. 5M IN A 10.0.8.183
+a-maximum-rrset.example. 5M IN A 10.0.8.184
+a-maximum-rrset.example. 5M IN A 10.0.8.185
+a-maximum-rrset.example. 5M IN A 10.0.8.186
+a-maximum-rrset.example. 5M IN A 10.0.8.187
+a-maximum-rrset.example. 5M IN A 10.0.8.188
+a-maximum-rrset.example. 5M IN A 10.0.8.189
+a-maximum-rrset.example. 5M IN A 10.0.8.190
+a-maximum-rrset.example. 5M IN A 10.0.8.191
+a-maximum-rrset.example. 5M IN A 10.0.8.192
+a-maximum-rrset.example. 5M IN A 10.0.8.193
+a-maximum-rrset.example. 5M IN A 10.0.8.194
+a-maximum-rrset.example. 5M IN A 10.0.8.195
+a-maximum-rrset.example. 5M IN A 10.0.8.196
+a-maximum-rrset.example. 5M IN A 10.0.8.197
+a-maximum-rrset.example. 5M IN A 10.0.8.198
+a-maximum-rrset.example. 5M IN A 10.0.8.199
+a-maximum-rrset.example. 5M IN A 10.0.8.200
+a-maximum-rrset.example. 5M IN A 10.0.8.201
+a-maximum-rrset.example. 5M IN A 10.0.8.202
+a-maximum-rrset.example. 5M IN A 10.0.8.203
+a-maximum-rrset.example. 5M IN A 10.0.8.204
+a-maximum-rrset.example. 5M IN A 10.0.8.205
+a-maximum-rrset.example. 5M IN A 10.0.8.206
+a-maximum-rrset.example. 5M IN A 10.0.8.207
+a-maximum-rrset.example. 5M IN A 10.0.8.208
+a-maximum-rrset.example. 5M IN A 10.0.8.209
+a-maximum-rrset.example. 5M IN A 10.0.8.210
+a-maximum-rrset.example. 5M IN A 10.0.8.211
+a-maximum-rrset.example. 5M IN A 10.0.8.212
+a-maximum-rrset.example. 5M IN A 10.0.8.213
+a-maximum-rrset.example. 5M IN A 10.0.8.214
+a-maximum-rrset.example. 5M IN A 10.0.8.215
+a-maximum-rrset.example. 5M IN A 10.0.8.216
+a-maximum-rrset.example. 5M IN A 10.0.8.217
+a-maximum-rrset.example. 5M IN A 10.0.8.218
+a-maximum-rrset.example. 5M IN A 10.0.8.219
+a-maximum-rrset.example. 5M IN A 10.0.8.220
+a-maximum-rrset.example. 5M IN A 10.0.8.221
+a-maximum-rrset.example. 5M IN A 10.0.8.222
+a-maximum-rrset.example. 5M IN A 10.0.8.223
+a-maximum-rrset.example. 5M IN A 10.0.8.224
+a-maximum-rrset.example. 5M IN A 10.0.8.225
+a-maximum-rrset.example. 5M IN A 10.0.8.226
+a-maximum-rrset.example. 5M IN A 10.0.8.227
+a-maximum-rrset.example. 5M IN A 10.0.8.228
+a-maximum-rrset.example. 5M IN A 10.0.8.229
+a-maximum-rrset.example. 5M IN A 10.0.8.230
+a-maximum-rrset.example. 5M IN A 10.0.8.231
+a-maximum-rrset.example. 5M IN A 10.0.8.232
+a-maximum-rrset.example. 5M IN A 10.0.8.233
+a-maximum-rrset.example. 5M IN A 10.0.8.234
+a-maximum-rrset.example. 5M IN A 10.0.8.235
+a-maximum-rrset.example. 5M IN A 10.0.8.236
+a-maximum-rrset.example. 5M IN A 10.0.8.237
+a-maximum-rrset.example. 5M IN A 10.0.8.238
+a-maximum-rrset.example. 5M IN A 10.0.8.239
+a-maximum-rrset.example. 5M IN A 10.0.8.240
+a-maximum-rrset.example. 5M IN A 10.0.8.241
+a-maximum-rrset.example. 5M IN A 10.0.8.242
+a-maximum-rrset.example. 5M IN A 10.0.8.243
+a-maximum-rrset.example. 5M IN A 10.0.8.244
+a-maximum-rrset.example. 5M IN A 10.0.8.245
+a-maximum-rrset.example. 5M IN A 10.0.8.246
+a-maximum-rrset.example. 5M IN A 10.0.8.247
+a-maximum-rrset.example. 5M IN A 10.0.8.248
+a-maximum-rrset.example. 5M IN A 10.0.8.249
+a-maximum-rrset.example. 5M IN A 10.0.8.250
+a-maximum-rrset.example. 5M IN A 10.0.8.251
+a-maximum-rrset.example. 5M IN A 10.0.8.252
+a-maximum-rrset.example. 5M IN A 10.0.8.253
+a-maximum-rrset.example. 5M IN A 10.0.8.254
+a-maximum-rrset.example. 5M IN A 10.0.8.255
+a-maximum-rrset.example. 5M IN A 10.0.9.0
+a-maximum-rrset.example. 5M IN A 10.0.9.1
+a-maximum-rrset.example. 5M IN A 10.0.9.2
+a-maximum-rrset.example. 5M IN A 10.0.9.3
+a-maximum-rrset.example. 5M IN A 10.0.9.4
+a-maximum-rrset.example. 5M IN A 10.0.9.5
+a-maximum-rrset.example. 5M IN A 10.0.9.6
+a-maximum-rrset.example. 5M IN A 10.0.9.7
+a-maximum-rrset.example. 5M IN A 10.0.9.8
+a-maximum-rrset.example. 5M IN A 10.0.9.9
+a-maximum-rrset.example. 5M IN A 10.0.9.10
+a-maximum-rrset.example. 5M IN A 10.0.9.11
+a-maximum-rrset.example. 5M IN A 10.0.9.12
+a-maximum-rrset.example. 5M IN A 10.0.9.13
+a-maximum-rrset.example. 5M IN A 10.0.9.14
+a-maximum-rrset.example. 5M IN A 10.0.9.15
+a-maximum-rrset.example. 5M IN A 10.0.9.16
+a-maximum-rrset.example. 5M IN A 10.0.9.17
+a-maximum-rrset.example. 5M IN A 10.0.9.18
+a-maximum-rrset.example. 5M IN A 10.0.9.19
+a-maximum-rrset.example. 5M IN A 10.0.9.20
+a-maximum-rrset.example. 5M IN A 10.0.9.21
+a-maximum-rrset.example. 5M IN A 10.0.9.22
+a-maximum-rrset.example. 5M IN A 10.0.9.23
+a-maximum-rrset.example. 5M IN A 10.0.9.24
+a-maximum-rrset.example. 5M IN A 10.0.9.25
+a-maximum-rrset.example. 5M IN A 10.0.9.26
+a-maximum-rrset.example. 5M IN A 10.0.9.27
+a-maximum-rrset.example. 5M IN A 10.0.9.28
+a-maximum-rrset.example. 5M IN A 10.0.9.29
+a-maximum-rrset.example. 5M IN A 10.0.9.30
+a-maximum-rrset.example. 5M IN A 10.0.9.31
+a-maximum-rrset.example. 5M IN A 10.0.9.32
+a-maximum-rrset.example. 5M IN A 10.0.9.33
+a-maximum-rrset.example. 5M IN A 10.0.9.34
+a-maximum-rrset.example. 5M IN A 10.0.9.35
+a-maximum-rrset.example. 5M IN A 10.0.9.36
+a-maximum-rrset.example. 5M IN A 10.0.9.37
+a-maximum-rrset.example. 5M IN A 10.0.9.38
+a-maximum-rrset.example. 5M IN A 10.0.9.39
+a-maximum-rrset.example. 5M IN A 10.0.9.40
+a-maximum-rrset.example. 5M IN A 10.0.9.41
+a-maximum-rrset.example. 5M IN A 10.0.9.42
+a-maximum-rrset.example. 5M IN A 10.0.9.43
+a-maximum-rrset.example. 5M IN A 10.0.9.44
+a-maximum-rrset.example. 5M IN A 10.0.9.45
+a-maximum-rrset.example. 5M IN A 10.0.9.46
+a-maximum-rrset.example. 5M IN A 10.0.9.47
+a-maximum-rrset.example. 5M IN A 10.0.9.48
+a-maximum-rrset.example. 5M IN A 10.0.9.49
+a-maximum-rrset.example. 5M IN A 10.0.9.50
+a-maximum-rrset.example. 5M IN A 10.0.9.51
+a-maximum-rrset.example. 5M IN A 10.0.9.52
+a-maximum-rrset.example. 5M IN A 10.0.9.53
+a-maximum-rrset.example. 5M IN A 10.0.9.54
+a-maximum-rrset.example. 5M IN A 10.0.9.55
+a-maximum-rrset.example. 5M IN A 10.0.9.56
+a-maximum-rrset.example. 5M IN A 10.0.9.57
+a-maximum-rrset.example. 5M IN A 10.0.9.58
+a-maximum-rrset.example. 5M IN A 10.0.9.59
+a-maximum-rrset.example. 5M IN A 10.0.9.60
+a-maximum-rrset.example. 5M IN A 10.0.9.61
+a-maximum-rrset.example. 5M IN A 10.0.9.62
+a-maximum-rrset.example. 5M IN A 10.0.9.63
+a-maximum-rrset.example. 5M IN A 10.0.9.64
+a-maximum-rrset.example. 5M IN A 10.0.9.65
+a-maximum-rrset.example. 5M IN A 10.0.9.66
+a-maximum-rrset.example. 5M IN A 10.0.9.67
+a-maximum-rrset.example. 5M IN A 10.0.9.68
+a-maximum-rrset.example. 5M IN A 10.0.9.69
+a-maximum-rrset.example. 5M IN A 10.0.9.70
+a-maximum-rrset.example. 5M IN A 10.0.9.71
+a-maximum-rrset.example. 5M IN A 10.0.9.72
+a-maximum-rrset.example. 5M IN A 10.0.9.73
+a-maximum-rrset.example. 5M IN A 10.0.9.74
+a-maximum-rrset.example. 5M IN A 10.0.9.75
+a-maximum-rrset.example. 5M IN A 10.0.9.76
+a-maximum-rrset.example. 5M IN A 10.0.9.77
+a-maximum-rrset.example. 5M IN A 10.0.9.78
+a-maximum-rrset.example. 5M IN A 10.0.9.79
+a-maximum-rrset.example. 5M IN A 10.0.9.80
+a-maximum-rrset.example. 5M IN A 10.0.9.81
+a-maximum-rrset.example. 5M IN A 10.0.9.82
+a-maximum-rrset.example. 5M IN A 10.0.9.83
+a-maximum-rrset.example. 5M IN A 10.0.9.84
+a-maximum-rrset.example. 5M IN A 10.0.9.85
+a-maximum-rrset.example. 5M IN A 10.0.9.86
+a-maximum-rrset.example. 5M IN A 10.0.9.87
+a-maximum-rrset.example. 5M IN A 10.0.9.88
+a-maximum-rrset.example. 5M IN A 10.0.9.89
+a-maximum-rrset.example. 5M IN A 10.0.9.90
+a-maximum-rrset.example. 5M IN A 10.0.9.91
+a-maximum-rrset.example. 5M IN A 10.0.9.92
+a-maximum-rrset.example. 5M IN A 10.0.9.93
+a-maximum-rrset.example. 5M IN A 10.0.9.94
+a-maximum-rrset.example. 5M IN A 10.0.9.95
+a-maximum-rrset.example. 5M IN A 10.0.9.96
+a-maximum-rrset.example. 5M IN A 10.0.9.97
+a-maximum-rrset.example. 5M IN A 10.0.9.98
+a-maximum-rrset.example. 5M IN A 10.0.9.99
+a-maximum-rrset.example. 5M IN A 10.0.9.100
+a-maximum-rrset.example. 5M IN A 10.0.9.101
+a-maximum-rrset.example. 5M IN A 10.0.9.102
+a-maximum-rrset.example. 5M IN A 10.0.9.103
+a-maximum-rrset.example. 5M IN A 10.0.9.104
+a-maximum-rrset.example. 5M IN A 10.0.9.105
+a-maximum-rrset.example. 5M IN A 10.0.9.106
+a-maximum-rrset.example. 5M IN A 10.0.9.107
+a-maximum-rrset.example. 5M IN A 10.0.9.108
+a-maximum-rrset.example. 5M IN A 10.0.9.109
+a-maximum-rrset.example. 5M IN A 10.0.9.110
+a-maximum-rrset.example. 5M IN A 10.0.9.111
+a-maximum-rrset.example. 5M IN A 10.0.9.112
+a-maximum-rrset.example. 5M IN A 10.0.9.113
+a-maximum-rrset.example. 5M IN A 10.0.9.114
+a-maximum-rrset.example. 5M IN A 10.0.9.115
+a-maximum-rrset.example. 5M IN A 10.0.9.116
+a-maximum-rrset.example. 5M IN A 10.0.9.117
+a-maximum-rrset.example. 5M IN A 10.0.9.118
+a-maximum-rrset.example. 5M IN A 10.0.9.119
+a-maximum-rrset.example. 5M IN A 10.0.9.120
+a-maximum-rrset.example. 5M IN A 10.0.9.121
+a-maximum-rrset.example. 5M IN A 10.0.9.122
+a-maximum-rrset.example. 5M IN A 10.0.9.123
+a-maximum-rrset.example. 5M IN A 10.0.9.124
+a-maximum-rrset.example. 5M IN A 10.0.9.125
+a-maximum-rrset.example. 5M IN A 10.0.9.126
+a-maximum-rrset.example. 5M IN A 10.0.9.127
+a-maximum-rrset.example. 5M IN A 10.0.9.128
+a-maximum-rrset.example. 5M IN A 10.0.9.129
+a-maximum-rrset.example. 5M IN A 10.0.9.130
+a-maximum-rrset.example. 5M IN A 10.0.9.131
+a-maximum-rrset.example. 5M IN A 10.0.9.132
+a-maximum-rrset.example. 5M IN A 10.0.9.133
+a-maximum-rrset.example. 5M IN A 10.0.9.134
+a-maximum-rrset.example. 5M IN A 10.0.9.135
+a-maximum-rrset.example. 5M IN A 10.0.9.136
+a-maximum-rrset.example. 5M IN A 10.0.9.137
+a-maximum-rrset.example. 5M IN A 10.0.9.138
+a-maximum-rrset.example. 5M IN A 10.0.9.139
+a-maximum-rrset.example. 5M IN A 10.0.9.140
+a-maximum-rrset.example. 5M IN A 10.0.9.141
+a-maximum-rrset.example. 5M IN A 10.0.9.142
+a-maximum-rrset.example. 5M IN A 10.0.9.143
+a-maximum-rrset.example. 5M IN A 10.0.9.144
+a-maximum-rrset.example. 5M IN A 10.0.9.145
+a-maximum-rrset.example. 5M IN A 10.0.9.146
+a-maximum-rrset.example. 5M IN A 10.0.9.147
+a-maximum-rrset.example. 5M IN A 10.0.9.148
+a-maximum-rrset.example. 5M IN A 10.0.9.149
+a-maximum-rrset.example. 5M IN A 10.0.9.150
+a-maximum-rrset.example. 5M IN A 10.0.9.151
+a-maximum-rrset.example. 5M IN A 10.0.9.152
+a-maximum-rrset.example. 5M IN A 10.0.9.153
+a-maximum-rrset.example. 5M IN A 10.0.9.154
+a-maximum-rrset.example. 5M IN A 10.0.9.155
+a-maximum-rrset.example. 5M IN A 10.0.9.156
+a-maximum-rrset.example. 5M IN A 10.0.9.157
+a-maximum-rrset.example. 5M IN A 10.0.9.158
+a-maximum-rrset.example. 5M IN A 10.0.9.159
+a-maximum-rrset.example. 5M IN A 10.0.9.160
+a-maximum-rrset.example. 5M IN A 10.0.9.161
+a-maximum-rrset.example. 5M IN A 10.0.9.162
+a-maximum-rrset.example. 5M IN A 10.0.9.163
+a-maximum-rrset.example. 5M IN A 10.0.9.164
+a-maximum-rrset.example. 5M IN A 10.0.9.165
+a-maximum-rrset.example. 5M IN A 10.0.9.166
+a-maximum-rrset.example. 5M IN A 10.0.9.167
+a-maximum-rrset.example. 5M IN A 10.0.9.168
+a-maximum-rrset.example. 5M IN A 10.0.9.169
+a-maximum-rrset.example. 5M IN A 10.0.9.170
+a-maximum-rrset.example. 5M IN A 10.0.9.171
+a-maximum-rrset.example. 5M IN A 10.0.9.172
+a-maximum-rrset.example. 5M IN A 10.0.9.173
+a-maximum-rrset.example. 5M IN A 10.0.9.174
+a-maximum-rrset.example. 5M IN A 10.0.9.175
+a-maximum-rrset.example. 5M IN A 10.0.9.176
+a-maximum-rrset.example. 5M IN A 10.0.9.177
+a-maximum-rrset.example. 5M IN A 10.0.9.178
+a-maximum-rrset.example. 5M IN A 10.0.9.179
+a-maximum-rrset.example. 5M IN A 10.0.9.180
+a-maximum-rrset.example. 5M IN A 10.0.9.181
+a-maximum-rrset.example. 5M IN A 10.0.9.182
+a-maximum-rrset.example. 5M IN A 10.0.9.183
+a-maximum-rrset.example. 5M IN A 10.0.9.184
+a-maximum-rrset.example. 5M IN A 10.0.9.185
+a-maximum-rrset.example. 5M IN A 10.0.9.186
+a-maximum-rrset.example. 5M IN A 10.0.9.187
+a-maximum-rrset.example. 5M IN A 10.0.9.188
+a-maximum-rrset.example. 5M IN A 10.0.9.189
+a-maximum-rrset.example. 5M IN A 10.0.9.190
+a-maximum-rrset.example. 5M IN A 10.0.9.191
+a-maximum-rrset.example. 5M IN A 10.0.9.192
+a-maximum-rrset.example. 5M IN A 10.0.9.193
+a-maximum-rrset.example. 5M IN A 10.0.9.194
+a-maximum-rrset.example. 5M IN A 10.0.9.195
+a-maximum-rrset.example. 5M IN A 10.0.9.196
+a-maximum-rrset.example. 5M IN A 10.0.9.197
+a-maximum-rrset.example. 5M IN A 10.0.9.198
+a-maximum-rrset.example. 5M IN A 10.0.9.199
+a-maximum-rrset.example. 5M IN A 10.0.9.200
+a-maximum-rrset.example. 5M IN A 10.0.9.201
+a-maximum-rrset.example. 5M IN A 10.0.9.202
+a-maximum-rrset.example. 5M IN A 10.0.9.203
+a-maximum-rrset.example. 5M IN A 10.0.9.204
+a-maximum-rrset.example. 5M IN A 10.0.9.205
+a-maximum-rrset.example. 5M IN A 10.0.9.206
+a-maximum-rrset.example. 5M IN A 10.0.9.207
+a-maximum-rrset.example. 5M IN A 10.0.9.208
+a-maximum-rrset.example. 5M IN A 10.0.9.209
+a-maximum-rrset.example. 5M IN A 10.0.9.210
+a-maximum-rrset.example. 5M IN A 10.0.9.211
+a-maximum-rrset.example. 5M IN A 10.0.9.212
+a-maximum-rrset.example. 5M IN A 10.0.9.213
+a-maximum-rrset.example. 5M IN A 10.0.9.214
+a-maximum-rrset.example. 5M IN A 10.0.9.215
+a-maximum-rrset.example. 5M IN A 10.0.9.216
+a-maximum-rrset.example. 5M IN A 10.0.9.217
+a-maximum-rrset.example. 5M IN A 10.0.9.218
+a-maximum-rrset.example. 5M IN A 10.0.9.219
+a-maximum-rrset.example. 5M IN A 10.0.9.220
+a-maximum-rrset.example. 5M IN A 10.0.9.221
+a-maximum-rrset.example. 5M IN A 10.0.9.222
+a-maximum-rrset.example. 5M IN A 10.0.9.223
+a-maximum-rrset.example. 5M IN A 10.0.9.224
+a-maximum-rrset.example. 5M IN A 10.0.9.225
+a-maximum-rrset.example. 5M IN A 10.0.9.226
+a-maximum-rrset.example. 5M IN A 10.0.9.227
+a-maximum-rrset.example. 5M IN A 10.0.9.228
+a-maximum-rrset.example. 5M IN A 10.0.9.229
+a-maximum-rrset.example. 5M IN A 10.0.9.230
+a-maximum-rrset.example. 5M IN A 10.0.9.231
+a-maximum-rrset.example. 5M IN A 10.0.9.232
+a-maximum-rrset.example. 5M IN A 10.0.9.233
+a-maximum-rrset.example. 5M IN A 10.0.9.234
+a-maximum-rrset.example. 5M IN A 10.0.9.235
+a-maximum-rrset.example. 5M IN A 10.0.9.236
+a-maximum-rrset.example. 5M IN A 10.0.9.237
+a-maximum-rrset.example. 5M IN A 10.0.9.238
+a-maximum-rrset.example. 5M IN A 10.0.9.239
+a-maximum-rrset.example. 5M IN A 10.0.9.240
+a-maximum-rrset.example. 5M IN A 10.0.9.241
+a-maximum-rrset.example. 5M IN A 10.0.9.242
+a-maximum-rrset.example. 5M IN A 10.0.9.243
+a-maximum-rrset.example. 5M IN A 10.0.9.244
+a-maximum-rrset.example. 5M IN A 10.0.9.245
+a-maximum-rrset.example. 5M IN A 10.0.9.246
+a-maximum-rrset.example. 5M IN A 10.0.9.247
+a-maximum-rrset.example. 5M IN A 10.0.9.248
+a-maximum-rrset.example. 5M IN A 10.0.9.249
+a-maximum-rrset.example. 5M IN A 10.0.9.250
+a-maximum-rrset.example. 5M IN A 10.0.9.251
+a-maximum-rrset.example. 5M IN A 10.0.9.252
+a-maximum-rrset.example. 5M IN A 10.0.9.253
+a-maximum-rrset.example. 5M IN A 10.0.9.254
+a-maximum-rrset.example. 5M IN A 10.0.9.255
+a-maximum-rrset.example. 5M IN A 10.0.10.0
+a-maximum-rrset.example. 5M IN A 10.0.10.1
+a-maximum-rrset.example. 5M IN A 10.0.10.2
+a-maximum-rrset.example. 5M IN A 10.0.10.3
+a-maximum-rrset.example. 5M IN A 10.0.10.4
+a-maximum-rrset.example. 5M IN A 10.0.10.5
+a-maximum-rrset.example. 5M IN A 10.0.10.6
+a-maximum-rrset.example. 5M IN A 10.0.10.7
+a-maximum-rrset.example. 5M IN A 10.0.10.8
+a-maximum-rrset.example. 5M IN A 10.0.10.9
+a-maximum-rrset.example. 5M IN A 10.0.10.10
+a-maximum-rrset.example. 5M IN A 10.0.10.11
+a-maximum-rrset.example. 5M IN A 10.0.10.12
+a-maximum-rrset.example. 5M IN A 10.0.10.13
+a-maximum-rrset.example. 5M IN A 10.0.10.14
+a-maximum-rrset.example. 5M IN A 10.0.10.15
+a-maximum-rrset.example. 5M IN A 10.0.10.16
+a-maximum-rrset.example. 5M IN A 10.0.10.17
+a-maximum-rrset.example. 5M IN A 10.0.10.18
+a-maximum-rrset.example. 5M IN A 10.0.10.19
+a-maximum-rrset.example. 5M IN A 10.0.10.20
+a-maximum-rrset.example. 5M IN A 10.0.10.21
+a-maximum-rrset.example. 5M IN A 10.0.10.22
+a-maximum-rrset.example. 5M IN A 10.0.10.23
+a-maximum-rrset.example. 5M IN A 10.0.10.24
+a-maximum-rrset.example. 5M IN A 10.0.10.25
+a-maximum-rrset.example. 5M IN A 10.0.10.26
+a-maximum-rrset.example. 5M IN A 10.0.10.27
+a-maximum-rrset.example. 5M IN A 10.0.10.28
+a-maximum-rrset.example. 5M IN A 10.0.10.29
+a-maximum-rrset.example. 5M IN A 10.0.10.30
+a-maximum-rrset.example. 5M IN A 10.0.10.31
+a-maximum-rrset.example. 5M IN A 10.0.10.32
+a-maximum-rrset.example. 5M IN A 10.0.10.33
+a-maximum-rrset.example. 5M IN A 10.0.10.34
+a-maximum-rrset.example. 5M IN A 10.0.10.35
+a-maximum-rrset.example. 5M IN A 10.0.10.36
+a-maximum-rrset.example. 5M IN A 10.0.10.37
+a-maximum-rrset.example. 5M IN A 10.0.10.38
+a-maximum-rrset.example. 5M IN A 10.0.10.39
+a-maximum-rrset.example. 5M IN A 10.0.10.40
+a-maximum-rrset.example. 5M IN A 10.0.10.41
+a-maximum-rrset.example. 5M IN A 10.0.10.42
+a-maximum-rrset.example. 5M IN A 10.0.10.43
+a-maximum-rrset.example. 5M IN A 10.0.10.44
+a-maximum-rrset.example. 5M IN A 10.0.10.45
+a-maximum-rrset.example. 5M IN A 10.0.10.46
+a-maximum-rrset.example. 5M IN A 10.0.10.47
+a-maximum-rrset.example. 5M IN A 10.0.10.48
+a-maximum-rrset.example. 5M IN A 10.0.10.49
+a-maximum-rrset.example. 5M IN A 10.0.10.50
+a-maximum-rrset.example. 5M IN A 10.0.10.51
+a-maximum-rrset.example. 5M IN A 10.0.10.52
+a-maximum-rrset.example. 5M IN A 10.0.10.53
+a-maximum-rrset.example. 5M IN A 10.0.10.54
+a-maximum-rrset.example. 5M IN A 10.0.10.55
+a-maximum-rrset.example. 5M IN A 10.0.10.56
+a-maximum-rrset.example. 5M IN A 10.0.10.57
+a-maximum-rrset.example. 5M IN A 10.0.10.58
+a-maximum-rrset.example. 5M IN A 10.0.10.59
+a-maximum-rrset.example. 5M IN A 10.0.10.60
+a-maximum-rrset.example. 5M IN A 10.0.10.61
+a-maximum-rrset.example. 5M IN A 10.0.10.62
+a-maximum-rrset.example. 5M IN A 10.0.10.63
+a-maximum-rrset.example. 5M IN A 10.0.10.64
+a-maximum-rrset.example. 5M IN A 10.0.10.65
+a-maximum-rrset.example. 5M IN A 10.0.10.66
+a-maximum-rrset.example. 5M IN A 10.0.10.67
+a-maximum-rrset.example. 5M IN A 10.0.10.68
+a-maximum-rrset.example. 5M IN A 10.0.10.69
+a-maximum-rrset.example. 5M IN A 10.0.10.70
+a-maximum-rrset.example. 5M IN A 10.0.10.71
+a-maximum-rrset.example. 5M IN A 10.0.10.72
+a-maximum-rrset.example. 5M IN A 10.0.10.73
+a-maximum-rrset.example. 5M IN A 10.0.10.74
+a-maximum-rrset.example. 5M IN A 10.0.10.75
+a-maximum-rrset.example. 5M IN A 10.0.10.76
+a-maximum-rrset.example. 5M IN A 10.0.10.77
+a-maximum-rrset.example. 5M IN A 10.0.10.78
+a-maximum-rrset.example. 5M IN A 10.0.10.79
+a-maximum-rrset.example. 5M IN A 10.0.10.80
+a-maximum-rrset.example. 5M IN A 10.0.10.81
+a-maximum-rrset.example. 5M IN A 10.0.10.82
+a-maximum-rrset.example. 5M IN A 10.0.10.83
+a-maximum-rrset.example. 5M IN A 10.0.10.84
+a-maximum-rrset.example. 5M IN A 10.0.10.85
+a-maximum-rrset.example. 5M IN A 10.0.10.86
+a-maximum-rrset.example. 5M IN A 10.0.10.87
+a-maximum-rrset.example. 5M IN A 10.0.10.88
+a-maximum-rrset.example. 5M IN A 10.0.10.89
+a-maximum-rrset.example. 5M IN A 10.0.10.90
+a-maximum-rrset.example. 5M IN A 10.0.10.91
+a-maximum-rrset.example. 5M IN A 10.0.10.92
+a-maximum-rrset.example. 5M IN A 10.0.10.93
+a-maximum-rrset.example. 5M IN A 10.0.10.94
+a-maximum-rrset.example. 5M IN A 10.0.10.95
+a-maximum-rrset.example. 5M IN A 10.0.10.96
+a-maximum-rrset.example. 5M IN A 10.0.10.97
+a-maximum-rrset.example. 5M IN A 10.0.10.98
+a-maximum-rrset.example. 5M IN A 10.0.10.99
+a-maximum-rrset.example. 5M IN A 10.0.10.100
+a-maximum-rrset.example. 5M IN A 10.0.10.101
+a-maximum-rrset.example. 5M IN A 10.0.10.102
+a-maximum-rrset.example. 5M IN A 10.0.10.103
+a-maximum-rrset.example. 5M IN A 10.0.10.104
+a-maximum-rrset.example. 5M IN A 10.0.10.105
+a-maximum-rrset.example. 5M IN A 10.0.10.106
+a-maximum-rrset.example. 5M IN A 10.0.10.107
+a-maximum-rrset.example. 5M IN A 10.0.10.108
+a-maximum-rrset.example. 5M IN A 10.0.10.109
+a-maximum-rrset.example. 5M IN A 10.0.10.110
+a-maximum-rrset.example. 5M IN A 10.0.10.111
+a-maximum-rrset.example. 5M IN A 10.0.10.112
+a-maximum-rrset.example. 5M IN A 10.0.10.113
+a-maximum-rrset.example. 5M IN A 10.0.10.114
+a-maximum-rrset.example. 5M IN A 10.0.10.115
+a-maximum-rrset.example. 5M IN A 10.0.10.116
+a-maximum-rrset.example. 5M IN A 10.0.10.117
+a-maximum-rrset.example. 5M IN A 10.0.10.118
+a-maximum-rrset.example. 5M IN A 10.0.10.119
+a-maximum-rrset.example. 5M IN A 10.0.10.120
+a-maximum-rrset.example. 5M IN A 10.0.10.121
+a-maximum-rrset.example. 5M IN A 10.0.10.122
+a-maximum-rrset.example. 5M IN A 10.0.10.123
+a-maximum-rrset.example. 5M IN A 10.0.10.124
+a-maximum-rrset.example. 5M IN A 10.0.10.125
+a-maximum-rrset.example. 5M IN A 10.0.10.126
+a-maximum-rrset.example. 5M IN A 10.0.10.127
+a-maximum-rrset.example. 5M IN A 10.0.10.128
+a-maximum-rrset.example. 5M IN A 10.0.10.129
+a-maximum-rrset.example. 5M IN A 10.0.10.130
+a-maximum-rrset.example. 5M IN A 10.0.10.131
+a-maximum-rrset.example. 5M IN A 10.0.10.132
+a-maximum-rrset.example. 5M IN A 10.0.10.133
+a-maximum-rrset.example. 5M IN A 10.0.10.134
+a-maximum-rrset.example. 5M IN A 10.0.10.135
+a-maximum-rrset.example. 5M IN A 10.0.10.136
+a-maximum-rrset.example. 5M IN A 10.0.10.137
+a-maximum-rrset.example. 5M IN A 10.0.10.138
+a-maximum-rrset.example. 5M IN A 10.0.10.139
+a-maximum-rrset.example. 5M IN A 10.0.10.140
+a-maximum-rrset.example. 5M IN A 10.0.10.141
+a-maximum-rrset.example. 5M IN A 10.0.10.142
+a-maximum-rrset.example. 5M IN A 10.0.10.143
+a-maximum-rrset.example. 5M IN A 10.0.10.144
+a-maximum-rrset.example. 5M IN A 10.0.10.145
+a-maximum-rrset.example. 5M IN A 10.0.10.146
+a-maximum-rrset.example. 5M IN A 10.0.10.147
+a-maximum-rrset.example. 5M IN A 10.0.10.148
+a-maximum-rrset.example. 5M IN A 10.0.10.149
+a-maximum-rrset.example. 5M IN A 10.0.10.150
+a-maximum-rrset.example. 5M IN A 10.0.10.151
+a-maximum-rrset.example. 5M IN A 10.0.10.152
+a-maximum-rrset.example. 5M IN A 10.0.10.153
+a-maximum-rrset.example. 5M IN A 10.0.10.154
+a-maximum-rrset.example. 5M IN A 10.0.10.155
+a-maximum-rrset.example. 5M IN A 10.0.10.156
+a-maximum-rrset.example. 5M IN A 10.0.10.157
+a-maximum-rrset.example. 5M IN A 10.0.10.158
+a-maximum-rrset.example. 5M IN A 10.0.10.159
+a-maximum-rrset.example. 5M IN A 10.0.10.160
+a-maximum-rrset.example. 5M IN A 10.0.10.161
+a-maximum-rrset.example. 5M IN A 10.0.10.162
+a-maximum-rrset.example. 5M IN A 10.0.10.163
+a-maximum-rrset.example. 5M IN A 10.0.10.164
+a-maximum-rrset.example. 5M IN A 10.0.10.165
+a-maximum-rrset.example. 5M IN A 10.0.10.166
+a-maximum-rrset.example. 5M IN A 10.0.10.167
+a-maximum-rrset.example. 5M IN A 10.0.10.168
+a-maximum-rrset.example. 5M IN A 10.0.10.169
+a-maximum-rrset.example. 5M IN A 10.0.10.170
+a-maximum-rrset.example. 5M IN A 10.0.10.171
+a-maximum-rrset.example. 5M IN A 10.0.10.172
+a-maximum-rrset.example. 5M IN A 10.0.10.173
+a-maximum-rrset.example. 5M IN A 10.0.10.174
+a-maximum-rrset.example. 5M IN A 10.0.10.175
+a-maximum-rrset.example. 5M IN A 10.0.10.176
+a-maximum-rrset.example. 5M IN A 10.0.10.177
+a-maximum-rrset.example. 5M IN A 10.0.10.178
+a-maximum-rrset.example. 5M IN A 10.0.10.179
+a-maximum-rrset.example. 5M IN A 10.0.10.180
+a-maximum-rrset.example. 5M IN A 10.0.10.181
+a-maximum-rrset.example. 5M IN A 10.0.10.182
+a-maximum-rrset.example. 5M IN A 10.0.10.183
+a-maximum-rrset.example. 5M IN A 10.0.10.184
+a-maximum-rrset.example. 5M IN A 10.0.10.185
+a-maximum-rrset.example. 5M IN A 10.0.10.186
+a-maximum-rrset.example. 5M IN A 10.0.10.187
+a-maximum-rrset.example. 5M IN A 10.0.10.188
+a-maximum-rrset.example. 5M IN A 10.0.10.189
+a-maximum-rrset.example. 5M IN A 10.0.10.190
+a-maximum-rrset.example. 5M IN A 10.0.10.191
+a-maximum-rrset.example. 5M IN A 10.0.10.192
+a-maximum-rrset.example. 5M IN A 10.0.10.193
+a-maximum-rrset.example. 5M IN A 10.0.10.194
+a-maximum-rrset.example. 5M IN A 10.0.10.195
+a-maximum-rrset.example. 5M IN A 10.0.10.196
+a-maximum-rrset.example. 5M IN A 10.0.10.197
+a-maximum-rrset.example. 5M IN A 10.0.10.198
+a-maximum-rrset.example. 5M IN A 10.0.10.199
+a-maximum-rrset.example. 5M IN A 10.0.10.200
+a-maximum-rrset.example. 5M IN A 10.0.10.201
+a-maximum-rrset.example. 5M IN A 10.0.10.202
+a-maximum-rrset.example. 5M IN A 10.0.10.203
+a-maximum-rrset.example. 5M IN A 10.0.10.204
+a-maximum-rrset.example. 5M IN A 10.0.10.205
+a-maximum-rrset.example. 5M IN A 10.0.10.206
+a-maximum-rrset.example. 5M IN A 10.0.10.207
+a-maximum-rrset.example. 5M IN A 10.0.10.208
+a-maximum-rrset.example. 5M IN A 10.0.10.209
+a-maximum-rrset.example. 5M IN A 10.0.10.210
+a-maximum-rrset.example. 5M IN A 10.0.10.211
+a-maximum-rrset.example. 5M IN A 10.0.10.212
+a-maximum-rrset.example. 5M IN A 10.0.10.213
+a-maximum-rrset.example. 5M IN A 10.0.10.214
+a-maximum-rrset.example. 5M IN A 10.0.10.215
+a-maximum-rrset.example. 5M IN A 10.0.10.216
+a-maximum-rrset.example. 5M IN A 10.0.10.217
+a-maximum-rrset.example. 5M IN A 10.0.10.218
+a-maximum-rrset.example. 5M IN A 10.0.10.219
+a-maximum-rrset.example. 5M IN A 10.0.10.220
+a-maximum-rrset.example. 5M IN A 10.0.10.221
+a-maximum-rrset.example. 5M IN A 10.0.10.222
+a-maximum-rrset.example. 5M IN A 10.0.10.223
+a-maximum-rrset.example. 5M IN A 10.0.10.224
+a-maximum-rrset.example. 5M IN A 10.0.10.225
+a-maximum-rrset.example. 5M IN A 10.0.10.226
+a-maximum-rrset.example. 5M IN A 10.0.10.227
+a-maximum-rrset.example. 5M IN A 10.0.10.228
+a-maximum-rrset.example. 5M IN A 10.0.10.229
+a-maximum-rrset.example. 5M IN A 10.0.10.230
+a-maximum-rrset.example. 5M IN A 10.0.10.231
+a-maximum-rrset.example. 5M IN A 10.0.10.232
+a-maximum-rrset.example. 5M IN A 10.0.10.233
+a-maximum-rrset.example. 5M IN A 10.0.10.234
+a-maximum-rrset.example. 5M IN A 10.0.10.235
+a-maximum-rrset.example. 5M IN A 10.0.10.236
+a-maximum-rrset.example. 5M IN A 10.0.10.237
+a-maximum-rrset.example. 5M IN A 10.0.10.238
+a-maximum-rrset.example. 5M IN A 10.0.10.239
+a-maximum-rrset.example. 5M IN A 10.0.10.240
+a-maximum-rrset.example. 5M IN A 10.0.10.241
+a-maximum-rrset.example. 5M IN A 10.0.10.242
+a-maximum-rrset.example. 5M IN A 10.0.10.243
+a-maximum-rrset.example. 5M IN A 10.0.10.244
+a-maximum-rrset.example. 5M IN A 10.0.10.245
+a-maximum-rrset.example. 5M IN A 10.0.10.246
+a-maximum-rrset.example. 5M IN A 10.0.10.247
+a-maximum-rrset.example. 5M IN A 10.0.10.248
+a-maximum-rrset.example. 5M IN A 10.0.10.249
+a-maximum-rrset.example. 5M IN A 10.0.10.250
+a-maximum-rrset.example. 5M IN A 10.0.10.251
+a-maximum-rrset.example. 5M IN A 10.0.10.252
+a-maximum-rrset.example. 5M IN A 10.0.10.253
+a-maximum-rrset.example. 5M IN A 10.0.10.254
+a-maximum-rrset.example. 5M IN A 10.0.10.255
+a-maximum-rrset.example. 5M IN A 10.0.11.0
+a-maximum-rrset.example. 5M IN A 10.0.11.1
+a-maximum-rrset.example. 5M IN A 10.0.11.2
+a-maximum-rrset.example. 5M IN A 10.0.11.3
+a-maximum-rrset.example. 5M IN A 10.0.11.4
+a-maximum-rrset.example. 5M IN A 10.0.11.5
+a-maximum-rrset.example. 5M IN A 10.0.11.6
+a-maximum-rrset.example. 5M IN A 10.0.11.7
+a-maximum-rrset.example. 5M IN A 10.0.11.8
+a-maximum-rrset.example. 5M IN A 10.0.11.9
+a-maximum-rrset.example. 5M IN A 10.0.11.10
+a-maximum-rrset.example. 5M IN A 10.0.11.11
+a-maximum-rrset.example. 5M IN A 10.0.11.12
+a-maximum-rrset.example. 5M IN A 10.0.11.13
+a-maximum-rrset.example. 5M IN A 10.0.11.14
+a-maximum-rrset.example. 5M IN A 10.0.11.15
+a-maximum-rrset.example. 5M IN A 10.0.11.16
+a-maximum-rrset.example. 5M IN A 10.0.11.17
+a-maximum-rrset.example. 5M IN A 10.0.11.18
+a-maximum-rrset.example. 5M IN A 10.0.11.19
+a-maximum-rrset.example. 5M IN A 10.0.11.20
+a-maximum-rrset.example. 5M IN A 10.0.11.21
+a-maximum-rrset.example. 5M IN A 10.0.11.22
+a-maximum-rrset.example. 5M IN A 10.0.11.23
+a-maximum-rrset.example. 5M IN A 10.0.11.24
+a-maximum-rrset.example. 5M IN A 10.0.11.25
+a-maximum-rrset.example. 5M IN A 10.0.11.26
+a-maximum-rrset.example. 5M IN A 10.0.11.27
+a-maximum-rrset.example. 5M IN A 10.0.11.28
+a-maximum-rrset.example. 5M IN A 10.0.11.29
+a-maximum-rrset.example. 5M IN A 10.0.11.30
+a-maximum-rrset.example. 5M IN A 10.0.11.31
+a-maximum-rrset.example. 5M IN A 10.0.11.32
+a-maximum-rrset.example. 5M IN A 10.0.11.33
+a-maximum-rrset.example. 5M IN A 10.0.11.34
+a-maximum-rrset.example. 5M IN A 10.0.11.35
+a-maximum-rrset.example. 5M IN A 10.0.11.36
+a-maximum-rrset.example. 5M IN A 10.0.11.37
+a-maximum-rrset.example. 5M IN A 10.0.11.38
+a-maximum-rrset.example. 5M IN A 10.0.11.39
+a-maximum-rrset.example. 5M IN A 10.0.11.40
+a-maximum-rrset.example. 5M IN A 10.0.11.41
+a-maximum-rrset.example. 5M IN A 10.0.11.42
+a-maximum-rrset.example. 5M IN A 10.0.11.43
+a-maximum-rrset.example. 5M IN A 10.0.11.44
+a-maximum-rrset.example. 5M IN A 10.0.11.45
+a-maximum-rrset.example. 5M IN A 10.0.11.46
+a-maximum-rrset.example. 5M IN A 10.0.11.47
+a-maximum-rrset.example. 5M IN A 10.0.11.48
+a-maximum-rrset.example. 5M IN A 10.0.11.49
+a-maximum-rrset.example. 5M IN A 10.0.11.50
+a-maximum-rrset.example. 5M IN A 10.0.11.51
+a-maximum-rrset.example. 5M IN A 10.0.11.52
+a-maximum-rrset.example. 5M IN A 10.0.11.53
+a-maximum-rrset.example. 5M IN A 10.0.11.54
+a-maximum-rrset.example. 5M IN A 10.0.11.55
+a-maximum-rrset.example. 5M IN A 10.0.11.56
+a-maximum-rrset.example. 5M IN A 10.0.11.57
+a-maximum-rrset.example. 5M IN A 10.0.11.58
+a-maximum-rrset.example. 5M IN A 10.0.11.59
+a-maximum-rrset.example. 5M IN A 10.0.11.60
+a-maximum-rrset.example. 5M IN A 10.0.11.61
+a-maximum-rrset.example. 5M IN A 10.0.11.62
+a-maximum-rrset.example. 5M IN A 10.0.11.63
+a-maximum-rrset.example. 5M IN A 10.0.11.64
+a-maximum-rrset.example. 5M IN A 10.0.11.65
+a-maximum-rrset.example. 5M IN A 10.0.11.66
+a-maximum-rrset.example. 5M IN A 10.0.11.67
+a-maximum-rrset.example. 5M IN A 10.0.11.68
+a-maximum-rrset.example. 5M IN A 10.0.11.69
+a-maximum-rrset.example. 5M IN A 10.0.11.70
+a-maximum-rrset.example. 5M IN A 10.0.11.71
+a-maximum-rrset.example. 5M IN A 10.0.11.72
+a-maximum-rrset.example. 5M IN A 10.0.11.73
+a-maximum-rrset.example. 5M IN A 10.0.11.74
+a-maximum-rrset.example. 5M IN A 10.0.11.75
+a-maximum-rrset.example. 5M IN A 10.0.11.76
+a-maximum-rrset.example. 5M IN A 10.0.11.77
+a-maximum-rrset.example. 5M IN A 10.0.11.78
+a-maximum-rrset.example. 5M IN A 10.0.11.79
+a-maximum-rrset.example. 5M IN A 10.0.11.80
+a-maximum-rrset.example. 5M IN A 10.0.11.81
+a-maximum-rrset.example. 5M IN A 10.0.11.82
+a-maximum-rrset.example. 5M IN A 10.0.11.83
+a-maximum-rrset.example. 5M IN A 10.0.11.84
+a-maximum-rrset.example. 5M IN A 10.0.11.85
+a-maximum-rrset.example. 5M IN A 10.0.11.86
+a-maximum-rrset.example. 5M IN A 10.0.11.87
+a-maximum-rrset.example. 5M IN A 10.0.11.88
+a-maximum-rrset.example. 5M IN A 10.0.11.89
+a-maximum-rrset.example. 5M IN A 10.0.11.90
+a-maximum-rrset.example. 5M IN A 10.0.11.91
+a-maximum-rrset.example. 5M IN A 10.0.11.92
+a-maximum-rrset.example. 5M IN A 10.0.11.93
+a-maximum-rrset.example. 5M IN A 10.0.11.94
+a-maximum-rrset.example. 5M IN A 10.0.11.95
+a-maximum-rrset.example. 5M IN A 10.0.11.96
+a-maximum-rrset.example. 5M IN A 10.0.11.97
+a-maximum-rrset.example. 5M IN A 10.0.11.98
+a-maximum-rrset.example. 5M IN A 10.0.11.99
+a-maximum-rrset.example. 5M IN A 10.0.11.100
+a-maximum-rrset.example. 5M IN A 10.0.11.101
+a-maximum-rrset.example. 5M IN A 10.0.11.102
+a-maximum-rrset.example. 5M IN A 10.0.11.103
+a-maximum-rrset.example. 5M IN A 10.0.11.104
+a-maximum-rrset.example. 5M IN A 10.0.11.105
+a-maximum-rrset.example. 5M IN A 10.0.11.106
+a-maximum-rrset.example. 5M IN A 10.0.11.107
+a-maximum-rrset.example. 5M IN A 10.0.11.108
+a-maximum-rrset.example. 5M IN A 10.0.11.109
+a-maximum-rrset.example. 5M IN A 10.0.11.110
+a-maximum-rrset.example. 5M IN A 10.0.11.111
+a-maximum-rrset.example. 5M IN A 10.0.11.112
+a-maximum-rrset.example. 5M IN A 10.0.11.113
+a-maximum-rrset.example. 5M IN A 10.0.11.114
+a-maximum-rrset.example. 5M IN A 10.0.11.115
+a-maximum-rrset.example. 5M IN A 10.0.11.116
+a-maximum-rrset.example. 5M IN A 10.0.11.117
+a-maximum-rrset.example. 5M IN A 10.0.11.118
+a-maximum-rrset.example. 5M IN A 10.0.11.119
+a-maximum-rrset.example. 5M IN A 10.0.11.120
+a-maximum-rrset.example. 5M IN A 10.0.11.121
+a-maximum-rrset.example. 5M IN A 10.0.11.122
+a-maximum-rrset.example. 5M IN A 10.0.11.123
+a-maximum-rrset.example. 5M IN A 10.0.11.124
+a-maximum-rrset.example. 5M IN A 10.0.11.125
+a-maximum-rrset.example. 5M IN A 10.0.11.126
+a-maximum-rrset.example. 5M IN A 10.0.11.127
+a-maximum-rrset.example. 5M IN A 10.0.11.128
+a-maximum-rrset.example. 5M IN A 10.0.11.129
+a-maximum-rrset.example. 5M IN A 10.0.11.130
+a-maximum-rrset.example. 5M IN A 10.0.11.131
+a-maximum-rrset.example. 5M IN A 10.0.11.132
+a-maximum-rrset.example. 5M IN A 10.0.11.133
+a-maximum-rrset.example. 5M IN A 10.0.11.134
+a-maximum-rrset.example. 5M IN A 10.0.11.135
+a-maximum-rrset.example. 5M IN A 10.0.11.136
+a-maximum-rrset.example. 5M IN A 10.0.11.137
+a-maximum-rrset.example. 5M IN A 10.0.11.138
+a-maximum-rrset.example. 5M IN A 10.0.11.139
+a-maximum-rrset.example. 5M IN A 10.0.11.140
+a-maximum-rrset.example. 5M IN A 10.0.11.141
+a-maximum-rrset.example. 5M IN A 10.0.11.142
+a-maximum-rrset.example. 5M IN A 10.0.11.143
+a-maximum-rrset.example. 5M IN A 10.0.11.144
+a-maximum-rrset.example. 5M IN A 10.0.11.145
+a-maximum-rrset.example. 5M IN A 10.0.11.146
+a-maximum-rrset.example. 5M IN A 10.0.11.147
+a-maximum-rrset.example. 5M IN A 10.0.11.148
+a-maximum-rrset.example. 5M IN A 10.0.11.149
+a-maximum-rrset.example. 5M IN A 10.0.11.150
+a-maximum-rrset.example. 5M IN A 10.0.11.151
+a-maximum-rrset.example. 5M IN A 10.0.11.152
+a-maximum-rrset.example. 5M IN A 10.0.11.153
+a-maximum-rrset.example. 5M IN A 10.0.11.154
+a-maximum-rrset.example. 5M IN A 10.0.11.155
+a-maximum-rrset.example. 5M IN A 10.0.11.156
+a-maximum-rrset.example. 5M IN A 10.0.11.157
+a-maximum-rrset.example. 5M IN A 10.0.11.158
+a-maximum-rrset.example. 5M IN A 10.0.11.159
+a-maximum-rrset.example. 5M IN A 10.0.11.160
+a-maximum-rrset.example. 5M IN A 10.0.11.161
+a-maximum-rrset.example. 5M IN A 10.0.11.162
+a-maximum-rrset.example. 5M IN A 10.0.11.163
+a-maximum-rrset.example. 5M IN A 10.0.11.164
+a-maximum-rrset.example. 5M IN A 10.0.11.165
+a-maximum-rrset.example. 5M IN A 10.0.11.166
+a-maximum-rrset.example. 5M IN A 10.0.11.167
+a-maximum-rrset.example. 5M IN A 10.0.11.168
+a-maximum-rrset.example. 5M IN A 10.0.11.169
+a-maximum-rrset.example. 5M IN A 10.0.11.170
+a-maximum-rrset.example. 5M IN A 10.0.11.171
+a-maximum-rrset.example. 5M IN A 10.0.11.172
+a-maximum-rrset.example. 5M IN A 10.0.11.173
+a-maximum-rrset.example. 5M IN A 10.0.11.174
+a-maximum-rrset.example. 5M IN A 10.0.11.175
+a-maximum-rrset.example. 5M IN A 10.0.11.176
+a-maximum-rrset.example. 5M IN A 10.0.11.177
+a-maximum-rrset.example. 5M IN A 10.0.11.178
+a-maximum-rrset.example. 5M IN A 10.0.11.179
+a-maximum-rrset.example. 5M IN A 10.0.11.180
+a-maximum-rrset.example. 5M IN A 10.0.11.181
+a-maximum-rrset.example. 5M IN A 10.0.11.182
+a-maximum-rrset.example. 5M IN A 10.0.11.183
+a-maximum-rrset.example. 5M IN A 10.0.11.184
+a-maximum-rrset.example. 5M IN A 10.0.11.185
+a-maximum-rrset.example. 5M IN A 10.0.11.186
+a-maximum-rrset.example. 5M IN A 10.0.11.187
+a-maximum-rrset.example. 5M IN A 10.0.11.188
+a-maximum-rrset.example. 5M IN A 10.0.11.189
+a-maximum-rrset.example. 5M IN A 10.0.11.190
+a-maximum-rrset.example. 5M IN A 10.0.11.191
+a-maximum-rrset.example. 5M IN A 10.0.11.192
+a-maximum-rrset.example. 5M IN A 10.0.11.193
+a-maximum-rrset.example. 5M IN A 10.0.11.194
+a-maximum-rrset.example. 5M IN A 10.0.11.195
+a-maximum-rrset.example. 5M IN A 10.0.11.196
+a-maximum-rrset.example. 5M IN A 10.0.11.197
+a-maximum-rrset.example. 5M IN A 10.0.11.198
+a-maximum-rrset.example. 5M IN A 10.0.11.199
+a-maximum-rrset.example. 5M IN A 10.0.11.200
+a-maximum-rrset.example. 5M IN A 10.0.11.201
+a-maximum-rrset.example. 5M IN A 10.0.11.202
+a-maximum-rrset.example. 5M IN A 10.0.11.203
+a-maximum-rrset.example. 5M IN A 10.0.11.204
+a-maximum-rrset.example. 5M IN A 10.0.11.205
+a-maximum-rrset.example. 5M IN A 10.0.11.206
+a-maximum-rrset.example. 5M IN A 10.0.11.207
+a-maximum-rrset.example. 5M IN A 10.0.11.208
+a-maximum-rrset.example. 5M IN A 10.0.11.209
+a-maximum-rrset.example. 5M IN A 10.0.11.210
+a-maximum-rrset.example. 5M IN A 10.0.11.211
+a-maximum-rrset.example. 5M IN A 10.0.11.212
+a-maximum-rrset.example. 5M IN A 10.0.11.213
+a-maximum-rrset.example. 5M IN A 10.0.11.214
+a-maximum-rrset.example. 5M IN A 10.0.11.215
+a-maximum-rrset.example. 5M IN A 10.0.11.216
+a-maximum-rrset.example. 5M IN A 10.0.11.217
+a-maximum-rrset.example. 5M IN A 10.0.11.218
+a-maximum-rrset.example. 5M IN A 10.0.11.219
+a-maximum-rrset.example. 5M IN A 10.0.11.220
+a-maximum-rrset.example. 5M IN A 10.0.11.221
+a-maximum-rrset.example. 5M IN A 10.0.11.222
+a-maximum-rrset.example. 5M IN A 10.0.11.223
+a-maximum-rrset.example. 5M IN A 10.0.11.224
+a-maximum-rrset.example. 5M IN A 10.0.11.225
+a-maximum-rrset.example. 5M IN A 10.0.11.226
+a-maximum-rrset.example. 5M IN A 10.0.11.227
+a-maximum-rrset.example. 5M IN A 10.0.11.228
+a-maximum-rrset.example. 5M IN A 10.0.11.229
+a-maximum-rrset.example. 5M IN A 10.0.11.230
+a-maximum-rrset.example. 5M IN A 10.0.11.231
+a-maximum-rrset.example. 5M IN A 10.0.11.232
+a-maximum-rrset.example. 5M IN A 10.0.11.233
+a-maximum-rrset.example. 5M IN A 10.0.11.234
+a-maximum-rrset.example. 5M IN A 10.0.11.235
+a-maximum-rrset.example. 5M IN A 10.0.11.236
+a-maximum-rrset.example. 5M IN A 10.0.11.237
+a-maximum-rrset.example. 5M IN A 10.0.11.238
+a-maximum-rrset.example. 5M IN A 10.0.11.239
+a-maximum-rrset.example. 5M IN A 10.0.11.240
+a-maximum-rrset.example. 5M IN A 10.0.11.241
+a-maximum-rrset.example. 5M IN A 10.0.11.242
+a-maximum-rrset.example. 5M IN A 10.0.11.243
+a-maximum-rrset.example. 5M IN A 10.0.11.244
+a-maximum-rrset.example. 5M IN A 10.0.11.245
+a-maximum-rrset.example. 5M IN A 10.0.11.246
+a-maximum-rrset.example. 5M IN A 10.0.11.247
+a-maximum-rrset.example. 5M IN A 10.0.11.248
+a-maximum-rrset.example. 5M IN A 10.0.11.249
+a-maximum-rrset.example. 5M IN A 10.0.11.250
+a-maximum-rrset.example. 5M IN A 10.0.11.251
+a-maximum-rrset.example. 5M IN A 10.0.11.252
+a-maximum-rrset.example. 5M IN A 10.0.11.253
+a-maximum-rrset.example. 5M IN A 10.0.11.254
+a-maximum-rrset.example. 5M IN A 10.0.11.255
+a-maximum-rrset.example. 5M IN A 10.0.12.0
+a-maximum-rrset.example. 5M IN A 10.0.12.1
+a-maximum-rrset.example. 5M IN A 10.0.12.2
+a-maximum-rrset.example. 5M IN A 10.0.12.3
+a-maximum-rrset.example. 5M IN A 10.0.12.4
+a-maximum-rrset.example. 5M IN A 10.0.12.5
+a-maximum-rrset.example. 5M IN A 10.0.12.6
+a-maximum-rrset.example. 5M IN A 10.0.12.7
+a-maximum-rrset.example. 5M IN A 10.0.12.8
+a-maximum-rrset.example. 5M IN A 10.0.12.9
+a-maximum-rrset.example. 5M IN A 10.0.12.10
+a-maximum-rrset.example. 5M IN A 10.0.12.11
+a-maximum-rrset.example. 5M IN A 10.0.12.12
+a-maximum-rrset.example. 5M IN A 10.0.12.13
+a-maximum-rrset.example. 5M IN A 10.0.12.14
+a-maximum-rrset.example. 5M IN A 10.0.12.15
+a-maximum-rrset.example. 5M IN A 10.0.12.16
+a-maximum-rrset.example. 5M IN A 10.0.12.17
+a-maximum-rrset.example. 5M IN A 10.0.12.18
+a-maximum-rrset.example. 5M IN A 10.0.12.19
+a-maximum-rrset.example. 5M IN A 10.0.12.20
+a-maximum-rrset.example. 5M IN A 10.0.12.21
+a-maximum-rrset.example. 5M IN A 10.0.12.22
+a-maximum-rrset.example. 5M IN A 10.0.12.23
+a-maximum-rrset.example. 5M IN A 10.0.12.24
+a-maximum-rrset.example. 5M IN A 10.0.12.25
+a-maximum-rrset.example. 5M IN A 10.0.12.26
+a-maximum-rrset.example. 5M IN A 10.0.12.27
+a-maximum-rrset.example. 5M IN A 10.0.12.28
+a-maximum-rrset.example. 5M IN A 10.0.12.29
+a-maximum-rrset.example. 5M IN A 10.0.12.30
+a-maximum-rrset.example. 5M IN A 10.0.12.31
+a-maximum-rrset.example. 5M IN A 10.0.12.32
+a-maximum-rrset.example. 5M IN A 10.0.12.33
+a-maximum-rrset.example. 5M IN A 10.0.12.34
+a-maximum-rrset.example. 5M IN A 10.0.12.35
+a-maximum-rrset.example. 5M IN A 10.0.12.36
+a-maximum-rrset.example. 5M IN A 10.0.12.37
+a-maximum-rrset.example. 5M IN A 10.0.12.38
+a-maximum-rrset.example. 5M IN A 10.0.12.39
+a-maximum-rrset.example. 5M IN A 10.0.12.40
+a-maximum-rrset.example. 5M IN A 10.0.12.41
+a-maximum-rrset.example. 5M IN A 10.0.12.42
+a-maximum-rrset.example. 5M IN A 10.0.12.43
+a-maximum-rrset.example. 5M IN A 10.0.12.44
+a-maximum-rrset.example. 5M IN A 10.0.12.45
+a-maximum-rrset.example. 5M IN A 10.0.12.46
+a-maximum-rrset.example. 5M IN A 10.0.12.47
+a-maximum-rrset.example. 5M IN A 10.0.12.48
+a-maximum-rrset.example. 5M IN A 10.0.12.49
+a-maximum-rrset.example. 5M IN A 10.0.12.50
+a-maximum-rrset.example. 5M IN A 10.0.12.51
+a-maximum-rrset.example. 5M IN A 10.0.12.52
+a-maximum-rrset.example. 5M IN A 10.0.12.53
+a-maximum-rrset.example. 5M IN A 10.0.12.54
+a-maximum-rrset.example. 5M IN A 10.0.12.55
+a-maximum-rrset.example. 5M IN A 10.0.12.56
+a-maximum-rrset.example. 5M IN A 10.0.12.57
+a-maximum-rrset.example. 5M IN A 10.0.12.58
+a-maximum-rrset.example. 5M IN A 10.0.12.59
+a-maximum-rrset.example. 5M IN A 10.0.12.60
+a-maximum-rrset.example. 5M IN A 10.0.12.61
+a-maximum-rrset.example. 5M IN A 10.0.12.62
+a-maximum-rrset.example. 5M IN A 10.0.12.63
+a-maximum-rrset.example. 5M IN A 10.0.12.64
+a-maximum-rrset.example. 5M IN A 10.0.12.65
+a-maximum-rrset.example. 5M IN A 10.0.12.66
+a-maximum-rrset.example. 5M IN A 10.0.12.67
+a-maximum-rrset.example. 5M IN A 10.0.12.68
+a-maximum-rrset.example. 5M IN A 10.0.12.69
+a-maximum-rrset.example. 5M IN A 10.0.12.70
+a-maximum-rrset.example. 5M IN A 10.0.12.71
+a-maximum-rrset.example. 5M IN A 10.0.12.72
+a-maximum-rrset.example. 5M IN A 10.0.12.73
+a-maximum-rrset.example. 5M IN A 10.0.12.74
+a-maximum-rrset.example. 5M IN A 10.0.12.75
+a-maximum-rrset.example. 5M IN A 10.0.12.76
+a-maximum-rrset.example. 5M IN A 10.0.12.77
+a-maximum-rrset.example. 5M IN A 10.0.12.78
+a-maximum-rrset.example. 5M IN A 10.0.12.79
+a-maximum-rrset.example. 5M IN A 10.0.12.80
+a-maximum-rrset.example. 5M IN A 10.0.12.81
+a-maximum-rrset.example. 5M IN A 10.0.12.82
+a-maximum-rrset.example. 5M IN A 10.0.12.83
+a-maximum-rrset.example. 5M IN A 10.0.12.84
+a-maximum-rrset.example. 5M IN A 10.0.12.85
+a-maximum-rrset.example. 5M IN A 10.0.12.86
+a-maximum-rrset.example. 5M IN A 10.0.12.87
+a-maximum-rrset.example. 5M IN A 10.0.12.88
+a-maximum-rrset.example. 5M IN A 10.0.12.89
+a-maximum-rrset.example. 5M IN A 10.0.12.90
+a-maximum-rrset.example. 5M IN A 10.0.12.91
+a-maximum-rrset.example. 5M IN A 10.0.12.92
+a-maximum-rrset.example. 5M IN A 10.0.12.93
+a-maximum-rrset.example. 5M IN A 10.0.12.94
+a-maximum-rrset.example. 5M IN A 10.0.12.95
+a-maximum-rrset.example. 5M IN A 10.0.12.96
+a-maximum-rrset.example. 5M IN A 10.0.12.97
+a-maximum-rrset.example. 5M IN A 10.0.12.98
+a-maximum-rrset.example. 5M IN A 10.0.12.99
+a-maximum-rrset.example. 5M IN A 10.0.12.100
+a-maximum-rrset.example. 5M IN A 10.0.12.101
+a-maximum-rrset.example. 5M IN A 10.0.12.102
+a-maximum-rrset.example. 5M IN A 10.0.12.103
+a-maximum-rrset.example. 5M IN A 10.0.12.104
+a-maximum-rrset.example. 5M IN A 10.0.12.105
+a-maximum-rrset.example. 5M IN A 10.0.12.106
+a-maximum-rrset.example. 5M IN A 10.0.12.107
+a-maximum-rrset.example. 5M IN A 10.0.12.108
+a-maximum-rrset.example. 5M IN A 10.0.12.109
+a-maximum-rrset.example. 5M IN A 10.0.12.110
+a-maximum-rrset.example. 5M IN A 10.0.12.111
+a-maximum-rrset.example. 5M IN A 10.0.12.112
+a-maximum-rrset.example. 5M IN A 10.0.12.113
+a-maximum-rrset.example. 5M IN A 10.0.12.114
+a-maximum-rrset.example. 5M IN A 10.0.12.115
+a-maximum-rrset.example. 5M IN A 10.0.12.116
+a-maximum-rrset.example. 5M IN A 10.0.12.117
+a-maximum-rrset.example. 5M IN A 10.0.12.118
+a-maximum-rrset.example. 5M IN A 10.0.12.119
+a-maximum-rrset.example. 5M IN A 10.0.12.120
+a-maximum-rrset.example. 5M IN A 10.0.12.121
+a-maximum-rrset.example. 5M IN A 10.0.12.122
+a-maximum-rrset.example. 5M IN A 10.0.12.123
+a-maximum-rrset.example. 5M IN A 10.0.12.124
+a-maximum-rrset.example. 5M IN A 10.0.12.125
+a-maximum-rrset.example. 5M IN A 10.0.12.126
+a-maximum-rrset.example. 5M IN A 10.0.12.127
+a-maximum-rrset.example. 5M IN A 10.0.12.128
+a-maximum-rrset.example. 5M IN A 10.0.12.129
+a-maximum-rrset.example. 5M IN A 10.0.12.130
+a-maximum-rrset.example. 5M IN A 10.0.12.131
+a-maximum-rrset.example. 5M IN A 10.0.12.132
+a-maximum-rrset.example. 5M IN A 10.0.12.133
+a-maximum-rrset.example. 5M IN A 10.0.12.134
+a-maximum-rrset.example. 5M IN A 10.0.12.135
+a-maximum-rrset.example. 5M IN A 10.0.12.136
+a-maximum-rrset.example. 5M IN A 10.0.12.137
+a-maximum-rrset.example. 5M IN A 10.0.12.138
+a-maximum-rrset.example. 5M IN A 10.0.12.139
+a-maximum-rrset.example. 5M IN A 10.0.12.140
+a-maximum-rrset.example. 5M IN A 10.0.12.141
+a-maximum-rrset.example. 5M IN A 10.0.12.142
+a-maximum-rrset.example. 5M IN A 10.0.12.143
+a-maximum-rrset.example. 5M IN A 10.0.12.144
+a-maximum-rrset.example. 5M IN A 10.0.12.145
+a-maximum-rrset.example. 5M IN A 10.0.12.146
+a-maximum-rrset.example. 5M IN A 10.0.12.147
+a-maximum-rrset.example. 5M IN A 10.0.12.148
+a-maximum-rrset.example. 5M IN A 10.0.12.149
+a-maximum-rrset.example. 5M IN A 10.0.12.150
+a-maximum-rrset.example. 5M IN A 10.0.12.151
+a-maximum-rrset.example. 5M IN A 10.0.12.152
+a-maximum-rrset.example. 5M IN A 10.0.12.153
+a-maximum-rrset.example. 5M IN A 10.0.12.154
+a-maximum-rrset.example. 5M IN A 10.0.12.155
+a-maximum-rrset.example. 5M IN A 10.0.12.156
+a-maximum-rrset.example. 5M IN A 10.0.12.157
+a-maximum-rrset.example. 5M IN A 10.0.12.158
+a-maximum-rrset.example. 5M IN A 10.0.12.159
+a-maximum-rrset.example. 5M IN A 10.0.12.160
+a-maximum-rrset.example. 5M IN A 10.0.12.161
+a-maximum-rrset.example. 5M IN A 10.0.12.162
+a-maximum-rrset.example. 5M IN A 10.0.12.163
+a-maximum-rrset.example. 5M IN A 10.0.12.164
+a-maximum-rrset.example. 5M IN A 10.0.12.165
+a-maximum-rrset.example. 5M IN A 10.0.12.166
+a-maximum-rrset.example. 5M IN A 10.0.12.167
+a-maximum-rrset.example. 5M IN A 10.0.12.168
+a-maximum-rrset.example. 5M IN A 10.0.12.169
+a-maximum-rrset.example. 5M IN A 10.0.12.170
+a-maximum-rrset.example. 5M IN A 10.0.12.171
+a-maximum-rrset.example. 5M IN A 10.0.12.172
+a-maximum-rrset.example. 5M IN A 10.0.12.173
+a-maximum-rrset.example. 5M IN A 10.0.12.174
+a-maximum-rrset.example. 5M IN A 10.0.12.175
+a-maximum-rrset.example. 5M IN A 10.0.12.176
+a-maximum-rrset.example. 5M IN A 10.0.12.177
+a-maximum-rrset.example. 5M IN A 10.0.12.178
+a-maximum-rrset.example. 5M IN A 10.0.12.179
+a-maximum-rrset.example. 5M IN A 10.0.12.180
+a-maximum-rrset.example. 5M IN A 10.0.12.181
+a-maximum-rrset.example. 5M IN A 10.0.12.182
+a-maximum-rrset.example. 5M IN A 10.0.12.183
+a-maximum-rrset.example. 5M IN A 10.0.12.184
+a-maximum-rrset.example. 5M IN A 10.0.12.185
+a-maximum-rrset.example. 5M IN A 10.0.12.186
+a-maximum-rrset.example. 5M IN A 10.0.12.187
+a-maximum-rrset.example. 5M IN A 10.0.12.188
+a-maximum-rrset.example. 5M IN A 10.0.12.189
+a-maximum-rrset.example. 5M IN A 10.0.12.190
+a-maximum-rrset.example. 5M IN A 10.0.12.191
+a-maximum-rrset.example. 5M IN A 10.0.12.192
+a-maximum-rrset.example. 5M IN A 10.0.12.193
+a-maximum-rrset.example. 5M IN A 10.0.12.194
+a-maximum-rrset.example. 5M IN A 10.0.12.195
+a-maximum-rrset.example. 5M IN A 10.0.12.196
+a-maximum-rrset.example. 5M IN A 10.0.12.197
+a-maximum-rrset.example. 5M IN A 10.0.12.198
+a-maximum-rrset.example. 5M IN A 10.0.12.199
+a-maximum-rrset.example. 5M IN A 10.0.12.200
+a-maximum-rrset.example. 5M IN A 10.0.12.201
+a-maximum-rrset.example. 5M IN A 10.0.12.202
+a-maximum-rrset.example. 5M IN A 10.0.12.203
+a-maximum-rrset.example. 5M IN A 10.0.12.204
+a-maximum-rrset.example. 5M IN A 10.0.12.205
+a-maximum-rrset.example. 5M IN A 10.0.12.206
+a-maximum-rrset.example. 5M IN A 10.0.12.207
+a-maximum-rrset.example. 5M IN A 10.0.12.208
+a-maximum-rrset.example. 5M IN A 10.0.12.209
+a-maximum-rrset.example. 5M IN A 10.0.12.210
+a-maximum-rrset.example. 5M IN A 10.0.12.211
+a-maximum-rrset.example. 5M IN A 10.0.12.212
+a-maximum-rrset.example. 5M IN A 10.0.12.213
+a-maximum-rrset.example. 5M IN A 10.0.12.214
+a-maximum-rrset.example. 5M IN A 10.0.12.215
+a-maximum-rrset.example. 5M IN A 10.0.12.216
+a-maximum-rrset.example. 5M IN A 10.0.12.217
+a-maximum-rrset.example. 5M IN A 10.0.12.218
+a-maximum-rrset.example. 5M IN A 10.0.12.219
+a-maximum-rrset.example. 5M IN A 10.0.12.220
+a-maximum-rrset.example. 5M IN A 10.0.12.221
+a-maximum-rrset.example. 5M IN A 10.0.12.222
+a-maximum-rrset.example. 5M IN A 10.0.12.223
+a-maximum-rrset.example. 5M IN A 10.0.12.224
+a-maximum-rrset.example. 5M IN A 10.0.12.225
+a-maximum-rrset.example. 5M IN A 10.0.12.226
+a-maximum-rrset.example. 5M IN A 10.0.12.227
+a-maximum-rrset.example. 5M IN A 10.0.12.228
+a-maximum-rrset.example. 5M IN A 10.0.12.229
+a-maximum-rrset.example. 5M IN A 10.0.12.230
+a-maximum-rrset.example. 5M IN A 10.0.12.231
+a-maximum-rrset.example. 5M IN A 10.0.12.232
+a-maximum-rrset.example. 5M IN A 10.0.12.233
+a-maximum-rrset.example. 5M IN A 10.0.12.234
+a-maximum-rrset.example. 5M IN A 10.0.12.235
+a-maximum-rrset.example. 5M IN A 10.0.12.236
+a-maximum-rrset.example. 5M IN A 10.0.12.237
+a-maximum-rrset.example. 5M IN A 10.0.12.238
+a-maximum-rrset.example. 5M IN A 10.0.12.239
+a-maximum-rrset.example. 5M IN A 10.0.12.240
+a-maximum-rrset.example. 5M IN A 10.0.12.241
+a-maximum-rrset.example. 5M IN A 10.0.12.242
+a-maximum-rrset.example. 5M IN A 10.0.12.243
+a-maximum-rrset.example. 5M IN A 10.0.12.244
+a-maximum-rrset.example. 5M IN A 10.0.12.245
+a-maximum-rrset.example. 5M IN A 10.0.12.246
+a-maximum-rrset.example. 5M IN A 10.0.12.247
+a-maximum-rrset.example. 5M IN A 10.0.12.248
+a-maximum-rrset.example. 5M IN A 10.0.12.249
+a-maximum-rrset.example. 5M IN A 10.0.12.250
+a-maximum-rrset.example. 5M IN A 10.0.12.251
+a-maximum-rrset.example. 5M IN A 10.0.12.252
+a-maximum-rrset.example. 5M IN A 10.0.12.253
+a-maximum-rrset.example. 5M IN A 10.0.12.254
+a-maximum-rrset.example. 5M IN A 10.0.12.255
+a-maximum-rrset.example. 5M IN A 10.0.13.0
+a-maximum-rrset.example. 5M IN A 10.0.13.1
+a-maximum-rrset.example. 5M IN A 10.0.13.2
+a-maximum-rrset.example. 5M IN A 10.0.13.3
+a-maximum-rrset.example. 5M IN A 10.0.13.4
+a-maximum-rrset.example. 5M IN A 10.0.13.5
+a-maximum-rrset.example. 5M IN A 10.0.13.6
+a-maximum-rrset.example. 5M IN A 10.0.13.7
+a-maximum-rrset.example. 5M IN A 10.0.13.8
+a-maximum-rrset.example. 5M IN A 10.0.13.9
+a-maximum-rrset.example. 5M IN A 10.0.13.10
+a-maximum-rrset.example. 5M IN A 10.0.13.11
+a-maximum-rrset.example. 5M IN A 10.0.13.12
+a-maximum-rrset.example. 5M IN A 10.0.13.13
+a-maximum-rrset.example. 5M IN A 10.0.13.14
+a-maximum-rrset.example. 5M IN A 10.0.13.15
+a-maximum-rrset.example. 5M IN A 10.0.13.16
+a-maximum-rrset.example. 5M IN A 10.0.13.17
+a-maximum-rrset.example. 5M IN A 10.0.13.18
+a-maximum-rrset.example. 5M IN A 10.0.13.19
+a-maximum-rrset.example. 5M IN A 10.0.13.20
+a-maximum-rrset.example. 5M IN A 10.0.13.21
+a-maximum-rrset.example. 5M IN A 10.0.13.22
+a-maximum-rrset.example. 5M IN A 10.0.13.23
+a-maximum-rrset.example. 5M IN A 10.0.13.24
+a-maximum-rrset.example. 5M IN A 10.0.13.25
+a-maximum-rrset.example. 5M IN A 10.0.13.26
+a-maximum-rrset.example. 5M IN A 10.0.13.27
+a-maximum-rrset.example. 5M IN A 10.0.13.28
+a-maximum-rrset.example. 5M IN A 10.0.13.29
+a-maximum-rrset.example. 5M IN A 10.0.13.30
+a-maximum-rrset.example. 5M IN A 10.0.13.31
+a-maximum-rrset.example. 5M IN A 10.0.13.32
+a-maximum-rrset.example. 5M IN A 10.0.13.33
+a-maximum-rrset.example. 5M IN A 10.0.13.34
+a-maximum-rrset.example. 5M IN A 10.0.13.35
+a-maximum-rrset.example. 5M IN A 10.0.13.36
+a-maximum-rrset.example. 5M IN A 10.0.13.37
+a-maximum-rrset.example. 5M IN A 10.0.13.38
+a-maximum-rrset.example. 5M IN A 10.0.13.39
+a-maximum-rrset.example. 5M IN A 10.0.13.40
+a-maximum-rrset.example. 5M IN A 10.0.13.41
+a-maximum-rrset.example. 5M IN A 10.0.13.42
+a-maximum-rrset.example. 5M IN A 10.0.13.43
+a-maximum-rrset.example. 5M IN A 10.0.13.44
+a-maximum-rrset.example. 5M IN A 10.0.13.45
+a-maximum-rrset.example. 5M IN A 10.0.13.46
+a-maximum-rrset.example. 5M IN A 10.0.13.47
+a-maximum-rrset.example. 5M IN A 10.0.13.48
+a-maximum-rrset.example. 5M IN A 10.0.13.49
+a-maximum-rrset.example. 5M IN A 10.0.13.50
+a-maximum-rrset.example. 5M IN A 10.0.13.51
+a-maximum-rrset.example. 5M IN A 10.0.13.52
+a-maximum-rrset.example. 5M IN A 10.0.13.53
+a-maximum-rrset.example. 5M IN A 10.0.13.54
+a-maximum-rrset.example. 5M IN A 10.0.13.55
+a-maximum-rrset.example. 5M IN A 10.0.13.56
+a-maximum-rrset.example. 5M IN A 10.0.13.57
+a-maximum-rrset.example. 5M IN A 10.0.13.58
+a-maximum-rrset.example. 5M IN A 10.0.13.59
+a-maximum-rrset.example. 5M IN A 10.0.13.60
+a-maximum-rrset.example. 5M IN A 10.0.13.61
+a-maximum-rrset.example. 5M IN A 10.0.13.62
+a-maximum-rrset.example. 5M IN A 10.0.13.63
+a-maximum-rrset.example. 5M IN A 10.0.13.64
+a-maximum-rrset.example. 5M IN A 10.0.13.65
+a-maximum-rrset.example. 5M IN A 10.0.13.66
+a-maximum-rrset.example. 5M IN A 10.0.13.67
+a-maximum-rrset.example. 5M IN A 10.0.13.68
+a-maximum-rrset.example. 5M IN A 10.0.13.69
+a-maximum-rrset.example. 5M IN A 10.0.13.70
+a-maximum-rrset.example. 5M IN A 10.0.13.71
+a-maximum-rrset.example. 5M IN A 10.0.13.72
+a-maximum-rrset.example. 5M IN A 10.0.13.73
+a-maximum-rrset.example. 5M IN A 10.0.13.74
+a-maximum-rrset.example. 5M IN A 10.0.13.75
+a-maximum-rrset.example. 5M IN A 10.0.13.76
+a-maximum-rrset.example. 5M IN A 10.0.13.77
+a-maximum-rrset.example. 5M IN A 10.0.13.78
+a-maximum-rrset.example. 5M IN A 10.0.13.79
+a-maximum-rrset.example. 5M IN A 10.0.13.80
+a-maximum-rrset.example. 5M IN A 10.0.13.81
+a-maximum-rrset.example. 5M IN A 10.0.13.82
+a-maximum-rrset.example. 5M IN A 10.0.13.83
+a-maximum-rrset.example. 5M IN A 10.0.13.84
+a-maximum-rrset.example. 5M IN A 10.0.13.85
+a-maximum-rrset.example. 5M IN A 10.0.13.86
+a-maximum-rrset.example. 5M IN A 10.0.13.87
+a-maximum-rrset.example. 5M IN A 10.0.13.88
+a-maximum-rrset.example. 5M IN A 10.0.13.89
+a-maximum-rrset.example. 5M IN A 10.0.13.90
+a-maximum-rrset.example. 5M IN A 10.0.13.91
+a-maximum-rrset.example. 5M IN A 10.0.13.92
+a-maximum-rrset.example. 5M IN A 10.0.13.93
+a-maximum-rrset.example. 5M IN A 10.0.13.94
+a-maximum-rrset.example. 5M IN A 10.0.13.95
+a-maximum-rrset.example. 5M IN A 10.0.13.96
+a-maximum-rrset.example. 5M IN A 10.0.13.97
+a-maximum-rrset.example. 5M IN A 10.0.13.98
+a-maximum-rrset.example. 5M IN A 10.0.13.99
+a-maximum-rrset.example. 5M IN A 10.0.13.100
+a-maximum-rrset.example. 5M IN A 10.0.13.101
+a-maximum-rrset.example. 5M IN A 10.0.13.102
+a-maximum-rrset.example. 5M IN A 10.0.13.103
+a-maximum-rrset.example. 5M IN A 10.0.13.104
+a-maximum-rrset.example. 5M IN A 10.0.13.105
+a-maximum-rrset.example. 5M IN A 10.0.13.106
+a-maximum-rrset.example. 5M IN A 10.0.13.107
+a-maximum-rrset.example. 5M IN A 10.0.13.108
+a-maximum-rrset.example. 5M IN A 10.0.13.109
+a-maximum-rrset.example. 5M IN A 10.0.13.110
+a-maximum-rrset.example. 5M IN A 10.0.13.111
+a-maximum-rrset.example. 5M IN A 10.0.13.112
+a-maximum-rrset.example. 5M IN A 10.0.13.113
+a-maximum-rrset.example. 5M IN A 10.0.13.114
+a-maximum-rrset.example. 5M IN A 10.0.13.115
+a-maximum-rrset.example. 5M IN A 10.0.13.116
+a-maximum-rrset.example. 5M IN A 10.0.13.117
+a-maximum-rrset.example. 5M IN A 10.0.13.118
+a-maximum-rrset.example. 5M IN A 10.0.13.119
+a-maximum-rrset.example. 5M IN A 10.0.13.120
+a-maximum-rrset.example. 5M IN A 10.0.13.121
+a-maximum-rrset.example. 5M IN A 10.0.13.122
+a-maximum-rrset.example. 5M IN A 10.0.13.123
+a-maximum-rrset.example. 5M IN A 10.0.13.124
+a-maximum-rrset.example. 5M IN A 10.0.13.125
+a-maximum-rrset.example. 5M IN A 10.0.13.126
+a-maximum-rrset.example. 5M IN A 10.0.13.127
+a-maximum-rrset.example. 5M IN A 10.0.13.128
+a-maximum-rrset.example. 5M IN A 10.0.13.129
+a-maximum-rrset.example. 5M IN A 10.0.13.130
+a-maximum-rrset.example. 5M IN A 10.0.13.131
+a-maximum-rrset.example. 5M IN A 10.0.13.132
+a-maximum-rrset.example. 5M IN A 10.0.13.133
+a-maximum-rrset.example. 5M IN A 10.0.13.134
+a-maximum-rrset.example. 5M IN A 10.0.13.135
+a-maximum-rrset.example. 5M IN A 10.0.13.136
+a-maximum-rrset.example. 5M IN A 10.0.13.137
+a-maximum-rrset.example. 5M IN A 10.0.13.138
+a-maximum-rrset.example. 5M IN A 10.0.13.139
+a-maximum-rrset.example. 5M IN A 10.0.13.140
+a-maximum-rrset.example. 5M IN A 10.0.13.141
+a-maximum-rrset.example. 5M IN A 10.0.13.142
+a-maximum-rrset.example. 5M IN A 10.0.13.143
+a-maximum-rrset.example. 5M IN A 10.0.13.144
+a-maximum-rrset.example. 5M IN A 10.0.13.145
+a-maximum-rrset.example. 5M IN A 10.0.13.146
+a-maximum-rrset.example. 5M IN A 10.0.13.147
+a-maximum-rrset.example. 5M IN A 10.0.13.148
+a-maximum-rrset.example. 5M IN A 10.0.13.149
+a-maximum-rrset.example. 5M IN A 10.0.13.150
+a-maximum-rrset.example. 5M IN A 10.0.13.151
+a-maximum-rrset.example. 5M IN A 10.0.13.152
+a-maximum-rrset.example. 5M IN A 10.0.13.153
+a-maximum-rrset.example. 5M IN A 10.0.13.154
+a-maximum-rrset.example. 5M IN A 10.0.13.155
+a-maximum-rrset.example. 5M IN A 10.0.13.156
+a-maximum-rrset.example. 5M IN A 10.0.13.157
+a-maximum-rrset.example. 5M IN A 10.0.13.158
+a-maximum-rrset.example. 5M IN A 10.0.13.159
+a-maximum-rrset.example. 5M IN A 10.0.13.160
+a-maximum-rrset.example. 5M IN A 10.0.13.161
+a-maximum-rrset.example. 5M IN A 10.0.13.162
+a-maximum-rrset.example. 5M IN A 10.0.13.163
+a-maximum-rrset.example. 5M IN A 10.0.13.164
+a-maximum-rrset.example. 5M IN A 10.0.13.165
+a-maximum-rrset.example. 5M IN A 10.0.13.166
+a-maximum-rrset.example. 5M IN A 10.0.13.167
+a-maximum-rrset.example. 5M IN A 10.0.13.168
+a-maximum-rrset.example. 5M IN A 10.0.13.169
+a-maximum-rrset.example. 5M IN A 10.0.13.170
+a-maximum-rrset.example. 5M IN A 10.0.13.171
+a-maximum-rrset.example. 5M IN A 10.0.13.172
+a-maximum-rrset.example. 5M IN A 10.0.13.173
+a-maximum-rrset.example. 5M IN A 10.0.13.174
+a-maximum-rrset.example. 5M IN A 10.0.13.175
+a-maximum-rrset.example. 5M IN A 10.0.13.176
+a-maximum-rrset.example. 5M IN A 10.0.13.177
+a-maximum-rrset.example. 5M IN A 10.0.13.178
+a-maximum-rrset.example. 5M IN A 10.0.13.179
+a-maximum-rrset.example. 5M IN A 10.0.13.180
+a-maximum-rrset.example. 5M IN A 10.0.13.181
+a-maximum-rrset.example. 5M IN A 10.0.13.182
+a-maximum-rrset.example. 5M IN A 10.0.13.183
+a-maximum-rrset.example. 5M IN A 10.0.13.184
+a-maximum-rrset.example. 5M IN A 10.0.13.185
+a-maximum-rrset.example. 5M IN A 10.0.13.186
+a-maximum-rrset.example. 5M IN A 10.0.13.187
+a-maximum-rrset.example. 5M IN A 10.0.13.188
+a-maximum-rrset.example. 5M IN A 10.0.13.189
+a-maximum-rrset.example. 5M IN A 10.0.13.190
+a-maximum-rrset.example. 5M IN A 10.0.13.191
+a-maximum-rrset.example. 5M IN A 10.0.13.192
+a-maximum-rrset.example. 5M IN A 10.0.13.193
+a-maximum-rrset.example. 5M IN A 10.0.13.194
+a-maximum-rrset.example. 5M IN A 10.0.13.195
+a-maximum-rrset.example. 5M IN A 10.0.13.196
+a-maximum-rrset.example. 5M IN A 10.0.13.197
+a-maximum-rrset.example. 5M IN A 10.0.13.198
+a-maximum-rrset.example. 5M IN A 10.0.13.199
+a-maximum-rrset.example. 5M IN A 10.0.13.200
+a-maximum-rrset.example. 5M IN A 10.0.13.201
+a-maximum-rrset.example. 5M IN A 10.0.13.202
+a-maximum-rrset.example. 5M IN A 10.0.13.203
+a-maximum-rrset.example. 5M IN A 10.0.13.204
+a-maximum-rrset.example. 5M IN A 10.0.13.205
+a-maximum-rrset.example. 5M IN A 10.0.13.206
+a-maximum-rrset.example. 5M IN A 10.0.13.207
+a-maximum-rrset.example. 5M IN A 10.0.13.208
+a-maximum-rrset.example. 5M IN A 10.0.13.209
+a-maximum-rrset.example. 5M IN A 10.0.13.210
+a-maximum-rrset.example. 5M IN A 10.0.13.211
+a-maximum-rrset.example. 5M IN A 10.0.13.212
+a-maximum-rrset.example. 5M IN A 10.0.13.213
+a-maximum-rrset.example. 5M IN A 10.0.13.214
+a-maximum-rrset.example. 5M IN A 10.0.13.215
+a-maximum-rrset.example. 5M IN A 10.0.13.216
+a-maximum-rrset.example. 5M IN A 10.0.13.217
+a-maximum-rrset.example. 5M IN A 10.0.13.218
+a-maximum-rrset.example. 5M IN A 10.0.13.219
+a-maximum-rrset.example. 5M IN A 10.0.13.220
+a-maximum-rrset.example. 5M IN A 10.0.13.221
+a-maximum-rrset.example. 5M IN A 10.0.13.222
+a-maximum-rrset.example. 5M IN A 10.0.13.223
+a-maximum-rrset.example. 5M IN A 10.0.13.224
+a-maximum-rrset.example. 5M IN A 10.0.13.225
+a-maximum-rrset.example. 5M IN A 10.0.13.226
+a-maximum-rrset.example. 5M IN A 10.0.13.227
+a-maximum-rrset.example. 5M IN A 10.0.13.228
+a-maximum-rrset.example. 5M IN A 10.0.13.229
+a-maximum-rrset.example. 5M IN A 10.0.13.230
+a-maximum-rrset.example. 5M IN A 10.0.13.231
+a-maximum-rrset.example. 5M IN A 10.0.13.232
+a-maximum-rrset.example. 5M IN A 10.0.13.233
+a-maximum-rrset.example. 5M IN A 10.0.13.234
+a-maximum-rrset.example. 5M IN A 10.0.13.235
+a-maximum-rrset.example. 5M IN A 10.0.13.236
+a-maximum-rrset.example. 5M IN A 10.0.13.237
+a-maximum-rrset.example. 5M IN A 10.0.13.238
+a-maximum-rrset.example. 5M IN A 10.0.13.239
+a-maximum-rrset.example. 5M IN A 10.0.13.240
+a-maximum-rrset.example. 5M IN A 10.0.13.241
+a-maximum-rrset.example. 5M IN A 10.0.13.242
+a-maximum-rrset.example. 5M IN A 10.0.13.243
+a-maximum-rrset.example. 5M IN A 10.0.13.244
+a-maximum-rrset.example. 5M IN A 10.0.13.245
+a-maximum-rrset.example. 5M IN A 10.0.13.246
+a-maximum-rrset.example. 5M IN A 10.0.13.247
+a-maximum-rrset.example. 5M IN A 10.0.13.248
+a-maximum-rrset.example. 5M IN A 10.0.13.249
+a-maximum-rrset.example. 5M IN A 10.0.13.250
+a-maximum-rrset.example. 5M IN A 10.0.13.251
+a-maximum-rrset.example. 5M IN A 10.0.13.252
+a-maximum-rrset.example. 5M IN A 10.0.13.253
+a-maximum-rrset.example. 5M IN A 10.0.13.254
+a-maximum-rrset.example. 5M IN A 10.0.13.255
+a-maximum-rrset.example. 5M IN A 10.0.14.0
+a-maximum-rrset.example. 5M IN A 10.0.14.1
+a-maximum-rrset.example. 5M IN A 10.0.14.2
+a-maximum-rrset.example. 5M IN A 10.0.14.3
+a-maximum-rrset.example. 5M IN A 10.0.14.4
+a-maximum-rrset.example. 5M IN A 10.0.14.5
+a-maximum-rrset.example. 5M IN A 10.0.14.6
+a-maximum-rrset.example. 5M IN A 10.0.14.7
+a-maximum-rrset.example. 5M IN A 10.0.14.8
+a-maximum-rrset.example. 5M IN A 10.0.14.9
+a-maximum-rrset.example. 5M IN A 10.0.14.10
+a-maximum-rrset.example. 5M IN A 10.0.14.11
+a-maximum-rrset.example. 5M IN A 10.0.14.12
+a-maximum-rrset.example. 5M IN A 10.0.14.13
+a-maximum-rrset.example. 5M IN A 10.0.14.14
+a-maximum-rrset.example. 5M IN A 10.0.14.15
+a-maximum-rrset.example. 5M IN A 10.0.14.16
+a-maximum-rrset.example. 5M IN A 10.0.14.17
+a-maximum-rrset.example. 5M IN A 10.0.14.18
+a-maximum-rrset.example. 5M IN A 10.0.14.19
+a-maximum-rrset.example. 5M IN A 10.0.14.20
+a-maximum-rrset.example. 5M IN A 10.0.14.21
+a-maximum-rrset.example. 5M IN A 10.0.14.22
+a-maximum-rrset.example. 5M IN A 10.0.14.23
+a-maximum-rrset.example. 5M IN A 10.0.14.24
+a-maximum-rrset.example. 5M IN A 10.0.14.25
+a-maximum-rrset.example. 5M IN A 10.0.14.26
+a-maximum-rrset.example. 5M IN A 10.0.14.27
+a-maximum-rrset.example. 5M IN A 10.0.14.28
+a-maximum-rrset.example. 5M IN A 10.0.14.29
+a-maximum-rrset.example. 5M IN A 10.0.14.30
+a-maximum-rrset.example. 5M IN A 10.0.14.31
+a-maximum-rrset.example. 5M IN A 10.0.14.32
+a-maximum-rrset.example. 5M IN A 10.0.14.33
+a-maximum-rrset.example. 5M IN A 10.0.14.34
+a-maximum-rrset.example. 5M IN A 10.0.14.35
+a-maximum-rrset.example. 5M IN A 10.0.14.36
+a-maximum-rrset.example. 5M IN A 10.0.14.37
+a-maximum-rrset.example. 5M IN A 10.0.14.38
+a-maximum-rrset.example. 5M IN A 10.0.14.39
+a-maximum-rrset.example. 5M IN A 10.0.14.40
+a-maximum-rrset.example. 5M IN A 10.0.14.41
+a-maximum-rrset.example. 5M IN A 10.0.14.42
+a-maximum-rrset.example. 5M IN A 10.0.14.43
+a-maximum-rrset.example. 5M IN A 10.0.14.44
+a-maximum-rrset.example. 5M IN A 10.0.14.45
+a-maximum-rrset.example. 5M IN A 10.0.14.46
+a-maximum-rrset.example. 5M IN A 10.0.14.47
+a-maximum-rrset.example. 5M IN A 10.0.14.48
+a-maximum-rrset.example. 5M IN A 10.0.14.49
+a-maximum-rrset.example. 5M IN A 10.0.14.50
+a-maximum-rrset.example. 5M IN A 10.0.14.51
+a-maximum-rrset.example. 5M IN A 10.0.14.52
+a-maximum-rrset.example. 5M IN A 10.0.14.53
+a-maximum-rrset.example. 5M IN A 10.0.14.54
+a-maximum-rrset.example. 5M IN A 10.0.14.55
+a-maximum-rrset.example. 5M IN A 10.0.14.56
+a-maximum-rrset.example. 5M IN A 10.0.14.57
+a-maximum-rrset.example. 5M IN A 10.0.14.58
+a-maximum-rrset.example. 5M IN A 10.0.14.59
+a-maximum-rrset.example. 5M IN A 10.0.14.60
+a-maximum-rrset.example. 5M IN A 10.0.14.61
+a-maximum-rrset.example. 5M IN A 10.0.14.62
+a-maximum-rrset.example. 5M IN A 10.0.14.63
+a-maximum-rrset.example. 5M IN A 10.0.14.64
+a-maximum-rrset.example. 5M IN A 10.0.14.65
+a-maximum-rrset.example. 5M IN A 10.0.14.66
+a-maximum-rrset.example. 5M IN A 10.0.14.67
+a-maximum-rrset.example. 5M IN A 10.0.14.68
+a-maximum-rrset.example. 5M IN A 10.0.14.69
+a-maximum-rrset.example. 5M IN A 10.0.14.70
+a-maximum-rrset.example. 5M IN A 10.0.14.71
+a-maximum-rrset.example. 5M IN A 10.0.14.72
+a-maximum-rrset.example. 5M IN A 10.0.14.73
+a-maximum-rrset.example. 5M IN A 10.0.14.74
+a-maximum-rrset.example. 5M IN A 10.0.14.75
+a-maximum-rrset.example. 5M IN A 10.0.14.76
+a-maximum-rrset.example. 5M IN A 10.0.14.77
+a-maximum-rrset.example. 5M IN A 10.0.14.78
+a-maximum-rrset.example. 5M IN A 10.0.14.79
+a-maximum-rrset.example. 5M IN A 10.0.14.80
+a-maximum-rrset.example. 5M IN A 10.0.14.81
+a-maximum-rrset.example. 5M IN A 10.0.14.82
+a-maximum-rrset.example. 5M IN A 10.0.14.83
+a-maximum-rrset.example. 5M IN A 10.0.14.84
+a-maximum-rrset.example. 5M IN A 10.0.14.85
+a-maximum-rrset.example. 5M IN A 10.0.14.86
+a-maximum-rrset.example. 5M IN A 10.0.14.87
+a-maximum-rrset.example. 5M IN A 10.0.14.88
+a-maximum-rrset.example. 5M IN A 10.0.14.89
+a-maximum-rrset.example. 5M IN A 10.0.14.90
+a-maximum-rrset.example. 5M IN A 10.0.14.91
+a-maximum-rrset.example. 5M IN A 10.0.14.92
+a-maximum-rrset.example. 5M IN A 10.0.14.93
+a-maximum-rrset.example. 5M IN A 10.0.14.94
+a-maximum-rrset.example. 5M IN A 10.0.14.95
+a-maximum-rrset.example. 5M IN A 10.0.14.96
+a-maximum-rrset.example. 5M IN A 10.0.14.97
+a-maximum-rrset.example. 5M IN A 10.0.14.98
+a-maximum-rrset.example. 5M IN A 10.0.14.99
+a-maximum-rrset.example. 5M IN A 10.0.14.100
+a-maximum-rrset.example. 5M IN A 10.0.14.101
+a-maximum-rrset.example. 5M IN A 10.0.14.102
+a-maximum-rrset.example. 5M IN A 10.0.14.103
+a-maximum-rrset.example. 5M IN A 10.0.14.104
+a-maximum-rrset.example. 5M IN A 10.0.14.105
+a-maximum-rrset.example. 5M IN A 10.0.14.106
+a-maximum-rrset.example. 5M IN A 10.0.14.107
+a-maximum-rrset.example. 5M IN A 10.0.14.108
+a-maximum-rrset.example. 5M IN A 10.0.14.109
+a-maximum-rrset.example. 5M IN A 10.0.14.110
+a-maximum-rrset.example. 5M IN A 10.0.14.111
+a-maximum-rrset.example. 5M IN A 10.0.14.112
+a-maximum-rrset.example. 5M IN A 10.0.14.113
+a-maximum-rrset.example. 5M IN A 10.0.14.114
+a-maximum-rrset.example. 5M IN A 10.0.14.115
+a-maximum-rrset.example. 5M IN A 10.0.14.116
+a-maximum-rrset.example. 5M IN A 10.0.14.117
+a-maximum-rrset.example. 5M IN A 10.0.14.118
+a-maximum-rrset.example. 5M IN A 10.0.14.119
+a-maximum-rrset.example. 5M IN A 10.0.14.120
+a-maximum-rrset.example. 5M IN A 10.0.14.121
+a-maximum-rrset.example. 5M IN A 10.0.14.122
+a-maximum-rrset.example. 5M IN A 10.0.14.123
+a-maximum-rrset.example. 5M IN A 10.0.14.124
+a-maximum-rrset.example. 5M IN A 10.0.14.125
+a-maximum-rrset.example. 5M IN A 10.0.14.126
+a-maximum-rrset.example. 5M IN A 10.0.14.127
+a-maximum-rrset.example. 5M IN A 10.0.14.128
+a-maximum-rrset.example. 5M IN A 10.0.14.129
+a-maximum-rrset.example. 5M IN A 10.0.14.130
+a-maximum-rrset.example. 5M IN A 10.0.14.131
+a-maximum-rrset.example. 5M IN A 10.0.14.132
+a-maximum-rrset.example. 5M IN A 10.0.14.133
+a-maximum-rrset.example. 5M IN A 10.0.14.134
+a-maximum-rrset.example. 5M IN A 10.0.14.135
+a-maximum-rrset.example. 5M IN A 10.0.14.136
+a-maximum-rrset.example. 5M IN A 10.0.14.137
+a-maximum-rrset.example. 5M IN A 10.0.14.138
+a-maximum-rrset.example. 5M IN A 10.0.14.139
+a-maximum-rrset.example. 5M IN A 10.0.14.140
+a-maximum-rrset.example. 5M IN A 10.0.14.141
+a-maximum-rrset.example. 5M IN A 10.0.14.142
+a-maximum-rrset.example. 5M IN A 10.0.14.143
+a-maximum-rrset.example. 5M IN A 10.0.14.144
+a-maximum-rrset.example. 5M IN A 10.0.14.145
+a-maximum-rrset.example. 5M IN A 10.0.14.146
+a-maximum-rrset.example. 5M IN A 10.0.14.147
+a-maximum-rrset.example. 5M IN A 10.0.14.148
+a-maximum-rrset.example. 5M IN A 10.0.14.149
+a-maximum-rrset.example. 5M IN A 10.0.14.150
+a-maximum-rrset.example. 5M IN A 10.0.14.151
+a-maximum-rrset.example. 5M IN A 10.0.14.152
+a-maximum-rrset.example. 5M IN A 10.0.14.153
+a-maximum-rrset.example. 5M IN A 10.0.14.154
+a-maximum-rrset.example. 5M IN A 10.0.14.155
+a-maximum-rrset.example. 5M IN A 10.0.14.156
+a-maximum-rrset.example. 5M IN A 10.0.14.157
+a-maximum-rrset.example. 5M IN A 10.0.14.158
+a-maximum-rrset.example. 5M IN A 10.0.14.159
+a-maximum-rrset.example. 5M IN A 10.0.14.160
+a-maximum-rrset.example. 5M IN A 10.0.14.161
+a-maximum-rrset.example. 5M IN A 10.0.14.162
+a-maximum-rrset.example. 5M IN A 10.0.14.163
+a-maximum-rrset.example. 5M IN A 10.0.14.164
+a-maximum-rrset.example. 5M IN A 10.0.14.165
+a-maximum-rrset.example. 5M IN A 10.0.14.166
+a-maximum-rrset.example. 5M IN A 10.0.14.167
+a-maximum-rrset.example. 5M IN A 10.0.14.168
+a-maximum-rrset.example. 5M IN A 10.0.14.169
+a-maximum-rrset.example. 5M IN A 10.0.14.170
+a-maximum-rrset.example. 5M IN A 10.0.14.171
+a-maximum-rrset.example. 5M IN A 10.0.14.172
+a-maximum-rrset.example. 5M IN A 10.0.14.173
+a-maximum-rrset.example. 5M IN A 10.0.14.174
+a-maximum-rrset.example. 5M IN A 10.0.14.175
+a-maximum-rrset.example. 5M IN A 10.0.14.176
+a-maximum-rrset.example. 5M IN A 10.0.14.177
+a-maximum-rrset.example. 5M IN A 10.0.14.178
+a-maximum-rrset.example. 5M IN A 10.0.14.179
+a-maximum-rrset.example. 5M IN A 10.0.14.180
+a-maximum-rrset.example. 5M IN A 10.0.14.181
+a-maximum-rrset.example. 5M IN A 10.0.14.182
+a-maximum-rrset.example. 5M IN A 10.0.14.183
+a-maximum-rrset.example. 5M IN A 10.0.14.184
+a-maximum-rrset.example. 5M IN A 10.0.14.185
+a-maximum-rrset.example. 5M IN A 10.0.14.186
+a-maximum-rrset.example. 5M IN A 10.0.14.187
+a-maximum-rrset.example. 5M IN A 10.0.14.188
+a-maximum-rrset.example. 5M IN A 10.0.14.189
+a-maximum-rrset.example. 5M IN A 10.0.14.190
+a-maximum-rrset.example. 5M IN A 10.0.14.191
+a-maximum-rrset.example. 5M IN A 10.0.14.192
+a-maximum-rrset.example. 5M IN A 10.0.14.193
+a-maximum-rrset.example. 5M IN A 10.0.14.194
+a-maximum-rrset.example. 5M IN A 10.0.14.195
+a-maximum-rrset.example. 5M IN A 10.0.14.196
+a-maximum-rrset.example. 5M IN A 10.0.14.197
+a-maximum-rrset.example. 5M IN A 10.0.14.198
+a-maximum-rrset.example. 5M IN A 10.0.14.199
+a-maximum-rrset.example. 5M IN A 10.0.14.200
+a-maximum-rrset.example. 5M IN A 10.0.14.201
+a-maximum-rrset.example. 5M IN A 10.0.14.202
+a-maximum-rrset.example. 5M IN A 10.0.14.203
+a-maximum-rrset.example. 5M IN A 10.0.14.204
+a-maximum-rrset.example. 5M IN A 10.0.14.205
+a-maximum-rrset.example. 5M IN A 10.0.14.206
+a-maximum-rrset.example. 5M IN A 10.0.14.207
+a-maximum-rrset.example. 5M IN A 10.0.14.208
+a-maximum-rrset.example. 5M IN A 10.0.14.209
+a-maximum-rrset.example. 5M IN A 10.0.14.210
+a-maximum-rrset.example. 5M IN A 10.0.14.211
+a-maximum-rrset.example. 5M IN A 10.0.14.212
+a-maximum-rrset.example. 5M IN A 10.0.14.213
+a-maximum-rrset.example. 5M IN A 10.0.14.214
+a-maximum-rrset.example. 5M IN A 10.0.14.215
+a-maximum-rrset.example. 5M IN A 10.0.14.216
+a-maximum-rrset.example. 5M IN A 10.0.14.217
+a-maximum-rrset.example. 5M IN A 10.0.14.218
+a-maximum-rrset.example. 5M IN A 10.0.14.219
+a-maximum-rrset.example. 5M IN A 10.0.14.220
+a-maximum-rrset.example. 5M IN A 10.0.14.221
+a-maximum-rrset.example. 5M IN A 10.0.14.222
+a-maximum-rrset.example. 5M IN A 10.0.14.223
+a-maximum-rrset.example. 5M IN A 10.0.14.224
+a-maximum-rrset.example. 5M IN A 10.0.14.225
+a-maximum-rrset.example. 5M IN A 10.0.14.226
+a-maximum-rrset.example. 5M IN A 10.0.14.227
+a-maximum-rrset.example. 5M IN A 10.0.14.228
+a-maximum-rrset.example. 5M IN A 10.0.14.229
+a-maximum-rrset.example. 5M IN A 10.0.14.230
+a-maximum-rrset.example. 5M IN A 10.0.14.231
+a-maximum-rrset.example. 5M IN A 10.0.14.232
+a-maximum-rrset.example. 5M IN A 10.0.14.233
+a-maximum-rrset.example. 5M IN A 10.0.14.234
+a-maximum-rrset.example. 5M IN A 10.0.14.235
+a-maximum-rrset.example. 5M IN A 10.0.14.236
+a-maximum-rrset.example. 5M IN A 10.0.14.237
+a-maximum-rrset.example. 5M IN A 10.0.14.238
+a-maximum-rrset.example. 5M IN A 10.0.14.239
+a-maximum-rrset.example. 5M IN A 10.0.14.240
+a-maximum-rrset.example. 5M IN A 10.0.14.241
+a-maximum-rrset.example. 5M IN A 10.0.14.242
+a-maximum-rrset.example. 5M IN A 10.0.14.243
+a-maximum-rrset.example. 5M IN A 10.0.14.244
+a-maximum-rrset.example. 5M IN A 10.0.14.245
+a-maximum-rrset.example. 5M IN A 10.0.14.246
+a-maximum-rrset.example. 5M IN A 10.0.14.247
+a-maximum-rrset.example. 5M IN A 10.0.14.248
+a-maximum-rrset.example. 5M IN A 10.0.14.249
+a-maximum-rrset.example. 5M IN A 10.0.14.250
+a-maximum-rrset.example. 5M IN A 10.0.14.251
+a-maximum-rrset.example. 5M IN A 10.0.14.252
+a-maximum-rrset.example. 5M IN A 10.0.14.253
+a-maximum-rrset.example. 5M IN A 10.0.14.254
+a-maximum-rrset.example. 5M IN A 10.0.14.255
+a-maximum-rrset.example. 5M IN A 10.0.15.0
+a-maximum-rrset.example. 5M IN A 10.0.15.1
+a-maximum-rrset.example. 5M IN A 10.0.15.2
+a-maximum-rrset.example. 5M IN A 10.0.15.3
+a-maximum-rrset.example. 5M IN A 10.0.15.4
+a-maximum-rrset.example. 5M IN A 10.0.15.5
+a-maximum-rrset.example. 5M IN A 10.0.15.6
+a-maximum-rrset.example. 5M IN A 10.0.15.7
+a-maximum-rrset.example. 5M IN A 10.0.15.8
+a-maximum-rrset.example. 5M IN A 10.0.15.9
+a-maximum-rrset.example. 5M IN A 10.0.15.10
+a-maximum-rrset.example. 5M IN A 10.0.15.11
+a-maximum-rrset.example. 5M IN A 10.0.15.12
+a-maximum-rrset.example. 5M IN A 10.0.15.13
+a-maximum-rrset.example. 5M IN A 10.0.15.14
+a-maximum-rrset.example. 5M IN A 10.0.15.15
+a-maximum-rrset.example. 5M IN A 10.0.15.16
+a-maximum-rrset.example. 5M IN A 10.0.15.17
+a-maximum-rrset.example. 5M IN A 10.0.15.18
+a-maximum-rrset.example. 5M IN A 10.0.15.19
+a-maximum-rrset.example. 5M IN A 10.0.15.20
+a-maximum-rrset.example. 5M IN A 10.0.15.21
+a-maximum-rrset.example. 5M IN A 10.0.15.22
+a-maximum-rrset.example. 5M IN A 10.0.15.23
+a-maximum-rrset.example. 5M IN A 10.0.15.24
+a-maximum-rrset.example. 5M IN A 10.0.15.25
+a-maximum-rrset.example. 5M IN A 10.0.15.26
+a-maximum-rrset.example. 5M IN A 10.0.15.27
+a-maximum-rrset.example. 5M IN A 10.0.15.28
+a-maximum-rrset.example. 5M IN A 10.0.15.29
+a-maximum-rrset.example. 5M IN A 10.0.15.30
+a-maximum-rrset.example. 5M IN A 10.0.15.31
+a-maximum-rrset.example. 5M IN A 10.0.15.32
+a-maximum-rrset.example. 5M IN A 10.0.15.33
+a-maximum-rrset.example. 5M IN A 10.0.15.34
+a-maximum-rrset.example. 5M IN A 10.0.15.35
+a-maximum-rrset.example. 5M IN A 10.0.15.36
+a-maximum-rrset.example. 5M IN A 10.0.15.37
+a-maximum-rrset.example. 5M IN A 10.0.15.38
+a-maximum-rrset.example. 5M IN A 10.0.15.39
+a-maximum-rrset.example. 5M IN A 10.0.15.40
+a-maximum-rrset.example. 5M IN A 10.0.15.41
+a-maximum-rrset.example. 5M IN A 10.0.15.42
+a-maximum-rrset.example. 5M IN A 10.0.15.43
+a-maximum-rrset.example. 5M IN A 10.0.15.44
+a-maximum-rrset.example. 5M IN A 10.0.15.45
+a-maximum-rrset.example. 5M IN A 10.0.15.46
+a-maximum-rrset.example. 5M IN A 10.0.15.47
+a-maximum-rrset.example. 5M IN A 10.0.15.48
+a-maximum-rrset.example. 5M IN A 10.0.15.49
+a-maximum-rrset.example. 5M IN A 10.0.15.50
+a-maximum-rrset.example. 5M IN A 10.0.15.51
+a-maximum-rrset.example. 5M IN A 10.0.15.52
+a-maximum-rrset.example. 5M IN A 10.0.15.53
+a-maximum-rrset.example. 5M IN A 10.0.15.54
+a-maximum-rrset.example. 5M IN A 10.0.15.55
+a-maximum-rrset.example. 5M IN A 10.0.15.56
+a-maximum-rrset.example. 5M IN A 10.0.15.57
+a-maximum-rrset.example. 5M IN A 10.0.15.58
+a-maximum-rrset.example. 5M IN A 10.0.15.59
+a-maximum-rrset.example. 5M IN A 10.0.15.60
+a-maximum-rrset.example. 5M IN A 10.0.15.61
+a-maximum-rrset.example. 5M IN A 10.0.15.62
+a-maximum-rrset.example. 5M IN A 10.0.15.63
+a-maximum-rrset.example. 5M IN A 10.0.15.64
+a-maximum-rrset.example. 5M IN A 10.0.15.65
+a-maximum-rrset.example. 5M IN A 10.0.15.66
+a-maximum-rrset.example. 5M IN A 10.0.15.67
+a-maximum-rrset.example. 5M IN A 10.0.15.68
+a-maximum-rrset.example. 5M IN A 10.0.15.69
+a-maximum-rrset.example. 5M IN A 10.0.15.70
+a-maximum-rrset.example. 5M IN A 10.0.15.71
+a-maximum-rrset.example. 5M IN A 10.0.15.72
+a-maximum-rrset.example. 5M IN A 10.0.15.73
+a-maximum-rrset.example. 5M IN A 10.0.15.74
+a-maximum-rrset.example. 5M IN A 10.0.15.75
+a-maximum-rrset.example. 5M IN A 10.0.15.76
+a-maximum-rrset.example. 5M IN A 10.0.15.77
+a-maximum-rrset.example. 5M IN A 10.0.15.78
+a-maximum-rrset.example. 5M IN A 10.0.15.79
+a-maximum-rrset.example. 5M IN A 10.0.15.80
+a-maximum-rrset.example. 5M IN A 10.0.15.81
+a-maximum-rrset.example. 5M IN A 10.0.15.82
+a-maximum-rrset.example. 5M IN A 10.0.15.83
+a-maximum-rrset.example. 5M IN A 10.0.15.84
+a-maximum-rrset.example. 5M IN A 10.0.15.85
+a-maximum-rrset.example. 5M IN A 10.0.15.86
+a-maximum-rrset.example. 5M IN A 10.0.15.87
+a-maximum-rrset.example. 5M IN A 10.0.15.88
+a-maximum-rrset.example. 5M IN A 10.0.15.89
+a-maximum-rrset.example. 5M IN A 10.0.15.90
+a-maximum-rrset.example. 5M IN A 10.0.15.91
+a-maximum-rrset.example. 5M IN A 10.0.15.92
+a-maximum-rrset.example. 5M IN A 10.0.15.93
+a-maximum-rrset.example. 5M IN A 10.0.15.94
+a-maximum-rrset.example. 5M IN A 10.0.15.95
+a-maximum-rrset.example. 5M IN A 10.0.15.96
+a-maximum-rrset.example. 5M IN A 10.0.15.97
+a-maximum-rrset.example. 5M IN A 10.0.15.98
+a-maximum-rrset.example. 5M IN A 10.0.15.99
+a-maximum-rrset.example. 5M IN A 10.0.15.100
+a-maximum-rrset.example. 5M IN A 10.0.15.101
+a-maximum-rrset.example. 5M IN A 10.0.15.102
+a-maximum-rrset.example. 5M IN A 10.0.15.103
+a-maximum-rrset.example. 5M IN A 10.0.15.104
+a-maximum-rrset.example. 5M IN A 10.0.15.105
+a-maximum-rrset.example. 5M IN A 10.0.15.106
+a-maximum-rrset.example. 5M IN A 10.0.15.107
+a-maximum-rrset.example. 5M IN A 10.0.15.108
+a-maximum-rrset.example. 5M IN A 10.0.15.109
+a-maximum-rrset.example. 5M IN A 10.0.15.110
+a-maximum-rrset.example. 5M IN A 10.0.15.111
+a-maximum-rrset.example. 5M IN A 10.0.15.112
+a-maximum-rrset.example. 5M IN A 10.0.15.113
+a-maximum-rrset.example. 5M IN A 10.0.15.114
+a-maximum-rrset.example. 5M IN A 10.0.15.115
+a-maximum-rrset.example. 5M IN A 10.0.15.116
+a-maximum-rrset.example. 5M IN A 10.0.15.117
+a-maximum-rrset.example. 5M IN A 10.0.15.118
+a-maximum-rrset.example. 5M IN A 10.0.15.119
+a-maximum-rrset.example. 5M IN A 10.0.15.120
+a-maximum-rrset.example. 5M IN A 10.0.15.121
+a-maximum-rrset.example. 5M IN A 10.0.15.122
+a-maximum-rrset.example. 5M IN A 10.0.15.123
+a-maximum-rrset.example. 5M IN A 10.0.15.124
+a-maximum-rrset.example. 5M IN A 10.0.15.125
+a-maximum-rrset.example. 5M IN A 10.0.15.126
+a-maximum-rrset.example. 5M IN A 10.0.15.127
+a-maximum-rrset.example. 5M IN A 10.0.15.128
+a-maximum-rrset.example. 5M IN A 10.0.15.129
+a-maximum-rrset.example. 5M IN A 10.0.15.130
+a-maximum-rrset.example. 5M IN A 10.0.15.131
+a-maximum-rrset.example. 5M IN A 10.0.15.132
+a-maximum-rrset.example. 5M IN A 10.0.15.133
+a-maximum-rrset.example. 5M IN A 10.0.15.134
+a-maximum-rrset.example. 5M IN A 10.0.15.135
+a-maximum-rrset.example. 5M IN A 10.0.15.136
+a-maximum-rrset.example. 5M IN A 10.0.15.137
+a-maximum-rrset.example. 5M IN A 10.0.15.138
+a-maximum-rrset.example. 5M IN A 10.0.15.139
+a-maximum-rrset.example. 5M IN A 10.0.15.140
+a-maximum-rrset.example. 5M IN A 10.0.15.141
+a-maximum-rrset.example. 5M IN A 10.0.15.142
+a-maximum-rrset.example. 5M IN A 10.0.15.143
+a-maximum-rrset.example. 5M IN A 10.0.15.144
+a-maximum-rrset.example. 5M IN A 10.0.15.145
+a-maximum-rrset.example. 5M IN A 10.0.15.146
+a-maximum-rrset.example. 5M IN A 10.0.15.147
+a-maximum-rrset.example. 5M IN A 10.0.15.148
+a-maximum-rrset.example. 5M IN A 10.0.15.149
+a-maximum-rrset.example. 5M IN A 10.0.15.150
+a-maximum-rrset.example. 5M IN A 10.0.15.151
+a-maximum-rrset.example. 5M IN A 10.0.15.152
+a-maximum-rrset.example. 5M IN A 10.0.15.153
+a-maximum-rrset.example. 5M IN A 10.0.15.154
+a-maximum-rrset.example. 5M IN A 10.0.15.155
+a-maximum-rrset.example. 5M IN A 10.0.15.156
+a-maximum-rrset.example. 5M IN A 10.0.15.157
+a-maximum-rrset.example. 5M IN A 10.0.15.158
+a-maximum-rrset.example. 5M IN A 10.0.15.159
+a-maximum-rrset.example. 5M IN A 10.1.0.0
+a-maximum-rrset.example. 5M IN A 10.1.0.1
+a-maximum-rrset.example. 5M IN A 10.1.0.2
+a-maximum-rrset.example. 5M IN A 10.1.0.3
+a-maximum-rrset.example. 5M IN A 10.1.0.4
+a-maximum-rrset.example. 5M IN A 10.1.0.5
+a-maximum-rrset.example. 5M IN A 10.1.0.6
+a-maximum-rrset.example. 5M IN A 10.1.0.7
+a-maximum-rrset.example. 5M IN A 10.1.0.8
+a-maximum-rrset.example. 5M IN A 10.1.0.9
+a-maximum-rrset.example. 5M IN A 10.1.0.10
+a-maximum-rrset.example. 5M IN A 10.1.0.11
+a-maximum-rrset.example. 5M IN A 10.1.0.12
+a-maximum-rrset.example. 5M IN A 10.1.0.13
+a-maximum-rrset.example. 5M IN A 10.1.0.14
+a-maximum-rrset.example. 5M IN A 10.1.0.15
+a-maximum-rrset.example. 5M IN A 10.1.0.16
+a-maximum-rrset.example. 5M IN A 10.1.0.17
+a-maximum-rrset.example. 5M IN A 10.1.0.18
+a-maximum-rrset.example. 5M IN A 10.1.0.19
+a-maximum-rrset.example. 5M IN A 10.1.0.20
+a-maximum-rrset.example. 5M IN A 10.1.0.21
+a-maximum-rrset.example. 5M IN A 10.1.0.22
+a-maximum-rrset.example. 5M IN A 10.1.0.23
+a-maximum-rrset.example. 5M IN A 10.1.0.24
+a-maximum-rrset.example. 5M IN A 10.1.0.25
+a-maximum-rrset.example. 5M IN A 10.1.0.26
+a-maximum-rrset.example. 5M IN A 10.1.0.27
+a-maximum-rrset.example. 5M IN A 10.1.0.28
+a-maximum-rrset.example. 5M IN A 10.1.0.29
+a-maximum-rrset.example. 5M IN A 10.1.0.30
+a-maximum-rrset.example. 5M IN A 10.1.0.31
+a-maximum-rrset.example. 5M IN A 10.1.0.32
+a-maximum-rrset.example. 5M IN A 10.1.0.33
+a-maximum-rrset.example. 5M IN A 10.1.0.34
+a-maximum-rrset.example. 5M IN A 10.1.0.35
+a-maximum-rrset.example. 5M IN A 10.1.0.36
+a-maximum-rrset.example. 5M IN A 10.1.0.37
+a-maximum-rrset.example. 5M IN A 10.1.0.38
+a-maximum-rrset.example. 5M IN A 10.1.0.39
+a-maximum-rrset.example. 5M IN A 10.1.0.40
+a-maximum-rrset.example. 5M IN A 10.1.0.41
+a-maximum-rrset.example. 5M IN A 10.1.0.42
+a-maximum-rrset.example. 5M IN A 10.1.0.43
+a-maximum-rrset.example. 5M IN A 10.1.0.44
+a-maximum-rrset.example. 5M IN A 10.1.0.45
+a-maximum-rrset.example. 5M IN A 10.1.0.46
+a-maximum-rrset.example. 5M IN A 10.1.0.47
+a-maximum-rrset.example. 5M IN A 10.1.0.48
+a-maximum-rrset.example. 5M IN A 10.1.0.49
+a-maximum-rrset.example. 5M IN A 10.1.0.50
+a-maximum-rrset.example. 5M IN A 10.1.0.51
+a-maximum-rrset.example. 5M IN A 10.1.0.52
+a-maximum-rrset.example. 5M IN A 10.1.0.53
+a-maximum-rrset.example. 5M IN A 10.1.0.54
+a-maximum-rrset.example. 5M IN A 10.1.0.55
+a-maximum-rrset.example. 5M IN A 10.1.0.56
+a-maximum-rrset.example. 5M IN A 10.1.0.57
+a-maximum-rrset.example. 5M IN A 10.1.0.58
+a-maximum-rrset.example. 5M IN A 10.1.0.59
+a-maximum-rrset.example. 5M IN A 10.1.0.60
+a-maximum-rrset.example. 5M IN A 10.1.0.61
+a-maximum-rrset.example. 5M IN A 10.1.0.62
+a-maximum-rrset.example. 5M IN A 10.1.0.63
+a-maximum-rrset.example. 5M IN A 10.1.0.64
+a-maximum-rrset.example. 5M IN A 10.1.0.65
+a-maximum-rrset.example. 5M IN A 10.1.0.66
+a-maximum-rrset.example. 5M IN A 10.1.0.67
+a-maximum-rrset.example. 5M IN A 10.1.0.68
+a-maximum-rrset.example. 5M IN A 10.1.0.69
+a-maximum-rrset.example. 5M IN A 10.1.0.70
+a-maximum-rrset.example. 5M IN A 10.1.0.71
+a-maximum-rrset.example. 5M IN A 10.1.0.72
+a-maximum-rrset.example. 5M IN A 10.1.0.73
+a-maximum-rrset.example. 5M IN A 10.1.0.74
+a-maximum-rrset.example. 5M IN A 10.1.0.75
+a-maximum-rrset.example. 5M IN A 10.1.0.76
+a-maximum-rrset.example. 5M IN A 10.1.0.77
+a-maximum-rrset.example. 5M IN A 10.1.0.78
+a-maximum-rrset.example. 5M IN A 10.1.0.79
+a-maximum-rrset.example. 5M IN A 10.1.0.80
+a-maximum-rrset.example. 5M IN A 10.1.0.81
+a-maximum-rrset.example. 5M IN A 10.1.0.82
+a-maximum-rrset.example. 5M IN A 10.1.0.83
+a-maximum-rrset.example. 5M IN A 10.1.0.84
+a-maximum-rrset.example. 5M IN A 10.1.0.85
+a-maximum-rrset.example. 5M IN A 10.1.0.86
+a-maximum-rrset.example. 5M IN A 10.1.0.87
+a-maximum-rrset.example. 5M IN A 10.1.0.88
+a-maximum-rrset.example. 5M IN A 10.1.0.89
+a-maximum-rrset.example. 5M IN A 10.1.0.90
+
+;; AUTHORITY SECTION:
+example. 5M IN NS ns1.example.
+
+;; ADDITIONAL SECTION:
+ns1.example. 5M IN A 10.53.0.1
+
+;; Total query time: 308 msec
+;; FROM: draco to SERVER: 10.53.0.1
+;; WHEN: Fri Jun 23 12:58:22 2000
+;; MSG SIZE sent: 41 rcvd: 65535
+
diff --git a/bin/tests/system/limits/ns1/example.db b/bin/tests/system/limits/ns1/example.db
new file mode 100644
index 0000000..836b766
--- /dev/null
+++ b/bin/tests/system/limits/ns1/example.db
@@ -0,0 +1,19118 @@
+; Copyright (C) 2004, 2007 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: example.db,v 1.10 2007/06/19 23:47:03 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns1.example. hostmaster.example. (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+@ NS ns1.example.
+ns1 A 10.53.0.1
+1000 A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+2000 A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+ A 10.0.3.232
+ A 10.0.3.233
+ A 10.0.3.234
+ A 10.0.3.235
+ A 10.0.3.236
+ A 10.0.3.237
+ A 10.0.3.238
+ A 10.0.3.239
+ A 10.0.3.240
+ A 10.0.3.241
+ A 10.0.3.242
+ A 10.0.3.243
+ A 10.0.3.244
+ A 10.0.3.245
+ A 10.0.3.246
+ A 10.0.3.247
+ A 10.0.3.248
+ A 10.0.3.249
+ A 10.0.3.250
+ A 10.0.3.251
+ A 10.0.3.252
+ A 10.0.3.253
+ A 10.0.3.254
+ A 10.0.3.255
+ A 10.0.4.0
+ A 10.0.4.1
+ A 10.0.4.2
+ A 10.0.4.3
+ A 10.0.4.4
+ A 10.0.4.5
+ A 10.0.4.6
+ A 10.0.4.7
+ A 10.0.4.8
+ A 10.0.4.9
+ A 10.0.4.10
+ A 10.0.4.11
+ A 10.0.4.12
+ A 10.0.4.13
+ A 10.0.4.14
+ A 10.0.4.15
+ A 10.0.4.16
+ A 10.0.4.17
+ A 10.0.4.18
+ A 10.0.4.19
+ A 10.0.4.20
+ A 10.0.4.21
+ A 10.0.4.22
+ A 10.0.4.23
+ A 10.0.4.24
+ A 10.0.4.25
+ A 10.0.4.26
+ A 10.0.4.27
+ A 10.0.4.28
+ A 10.0.4.29
+ A 10.0.4.30
+ A 10.0.4.31
+ A 10.0.4.32
+ A 10.0.4.33
+ A 10.0.4.34
+ A 10.0.4.35
+ A 10.0.4.36
+ A 10.0.4.37
+ A 10.0.4.38
+ A 10.0.4.39
+ A 10.0.4.40
+ A 10.0.4.41
+ A 10.0.4.42
+ A 10.0.4.43
+ A 10.0.4.44
+ A 10.0.4.45
+ A 10.0.4.46
+ A 10.0.4.47
+ A 10.0.4.48
+ A 10.0.4.49
+ A 10.0.4.50
+ A 10.0.4.51
+ A 10.0.4.52
+ A 10.0.4.53
+ A 10.0.4.54
+ A 10.0.4.55
+ A 10.0.4.56
+ A 10.0.4.57
+ A 10.0.4.58
+ A 10.0.4.59
+ A 10.0.4.60
+ A 10.0.4.61
+ A 10.0.4.62
+ A 10.0.4.63
+ A 10.0.4.64
+ A 10.0.4.65
+ A 10.0.4.66
+ A 10.0.4.67
+ A 10.0.4.68
+ A 10.0.4.69
+ A 10.0.4.70
+ A 10.0.4.71
+ A 10.0.4.72
+ A 10.0.4.73
+ A 10.0.4.74
+ A 10.0.4.75
+ A 10.0.4.76
+ A 10.0.4.77
+ A 10.0.4.78
+ A 10.0.4.79
+ A 10.0.4.80
+ A 10.0.4.81
+ A 10.0.4.82
+ A 10.0.4.83
+ A 10.0.4.84
+ A 10.0.4.85
+ A 10.0.4.86
+ A 10.0.4.87
+ A 10.0.4.88
+ A 10.0.4.89
+ A 10.0.4.90
+ A 10.0.4.91
+ A 10.0.4.92
+ A 10.0.4.93
+ A 10.0.4.94
+ A 10.0.4.95
+ A 10.0.4.96
+ A 10.0.4.97
+ A 10.0.4.98
+ A 10.0.4.99
+ A 10.0.4.100
+ A 10.0.4.101
+ A 10.0.4.102
+ A 10.0.4.103
+ A 10.0.4.104
+ A 10.0.4.105
+ A 10.0.4.106
+ A 10.0.4.107
+ A 10.0.4.108
+ A 10.0.4.109
+ A 10.0.4.110
+ A 10.0.4.111
+ A 10.0.4.112
+ A 10.0.4.113
+ A 10.0.4.114
+ A 10.0.4.115
+ A 10.0.4.116
+ A 10.0.4.117
+ A 10.0.4.118
+ A 10.0.4.119
+ A 10.0.4.120
+ A 10.0.4.121
+ A 10.0.4.122
+ A 10.0.4.123
+ A 10.0.4.124
+ A 10.0.4.125
+ A 10.0.4.126
+ A 10.0.4.127
+ A 10.0.4.128
+ A 10.0.4.129
+ A 10.0.4.130
+ A 10.0.4.131
+ A 10.0.4.132
+ A 10.0.4.133
+ A 10.0.4.134
+ A 10.0.4.135
+ A 10.0.4.136
+ A 10.0.4.137
+ A 10.0.4.138
+ A 10.0.4.139
+ A 10.0.4.140
+ A 10.0.4.141
+ A 10.0.4.142
+ A 10.0.4.143
+ A 10.0.4.144
+ A 10.0.4.145
+ A 10.0.4.146
+ A 10.0.4.147
+ A 10.0.4.148
+ A 10.0.4.149
+ A 10.0.4.150
+ A 10.0.4.151
+ A 10.0.4.152
+ A 10.0.4.153
+ A 10.0.4.154
+ A 10.0.4.155
+ A 10.0.4.156
+ A 10.0.4.157
+ A 10.0.4.158
+ A 10.0.4.159
+ A 10.0.4.160
+ A 10.0.4.161
+ A 10.0.4.162
+ A 10.0.4.163
+ A 10.0.4.164
+ A 10.0.4.165
+ A 10.0.4.166
+ A 10.0.4.167
+ A 10.0.4.168
+ A 10.0.4.169
+ A 10.0.4.170
+ A 10.0.4.171
+ A 10.0.4.172
+ A 10.0.4.173
+ A 10.0.4.174
+ A 10.0.4.175
+ A 10.0.4.176
+ A 10.0.4.177
+ A 10.0.4.178
+ A 10.0.4.179
+ A 10.0.4.180
+ A 10.0.4.181
+ A 10.0.4.182
+ A 10.0.4.183
+ A 10.0.4.184
+ A 10.0.4.185
+ A 10.0.4.186
+ A 10.0.4.187
+ A 10.0.4.188
+ A 10.0.4.189
+ A 10.0.4.190
+ A 10.0.4.191
+ A 10.0.4.192
+ A 10.0.4.193
+ A 10.0.4.194
+ A 10.0.4.195
+ A 10.0.4.196
+ A 10.0.4.197
+ A 10.0.4.198
+ A 10.0.4.199
+ A 10.0.4.200
+ A 10.0.4.201
+ A 10.0.4.202
+ A 10.0.4.203
+ A 10.0.4.204
+ A 10.0.4.205
+ A 10.0.4.206
+ A 10.0.4.207
+ A 10.0.4.208
+ A 10.0.4.209
+ A 10.0.4.210
+ A 10.0.4.211
+ A 10.0.4.212
+ A 10.0.4.213
+ A 10.0.4.214
+ A 10.0.4.215
+ A 10.0.4.216
+ A 10.0.4.217
+ A 10.0.4.218
+ A 10.0.4.219
+ A 10.0.4.220
+ A 10.0.4.221
+ A 10.0.4.222
+ A 10.0.4.223
+ A 10.0.4.224
+ A 10.0.4.225
+ A 10.0.4.226
+ A 10.0.4.227
+ A 10.0.4.228
+ A 10.0.4.229
+ A 10.0.4.230
+ A 10.0.4.231
+ A 10.0.4.232
+ A 10.0.4.233
+ A 10.0.4.234
+ A 10.0.4.235
+ A 10.0.4.236
+ A 10.0.4.237
+ A 10.0.4.238
+ A 10.0.4.239
+ A 10.0.4.240
+ A 10.0.4.241
+ A 10.0.4.242
+ A 10.0.4.243
+ A 10.0.4.244
+ A 10.0.4.245
+ A 10.0.4.246
+ A 10.0.4.247
+ A 10.0.4.248
+ A 10.0.4.249
+ A 10.0.4.250
+ A 10.0.4.251
+ A 10.0.4.252
+ A 10.0.4.253
+ A 10.0.4.254
+ A 10.0.4.255
+ A 10.0.5.0
+ A 10.0.5.1
+ A 10.0.5.2
+ A 10.0.5.3
+ A 10.0.5.4
+ A 10.0.5.5
+ A 10.0.5.6
+ A 10.0.5.7
+ A 10.0.5.8
+ A 10.0.5.9
+ A 10.0.5.10
+ A 10.0.5.11
+ A 10.0.5.12
+ A 10.0.5.13
+ A 10.0.5.14
+ A 10.0.5.15
+ A 10.0.5.16
+ A 10.0.5.17
+ A 10.0.5.18
+ A 10.0.5.19
+ A 10.0.5.20
+ A 10.0.5.21
+ A 10.0.5.22
+ A 10.0.5.23
+ A 10.0.5.24
+ A 10.0.5.25
+ A 10.0.5.26
+ A 10.0.5.27
+ A 10.0.5.28
+ A 10.0.5.29
+ A 10.0.5.30
+ A 10.0.5.31
+ A 10.0.5.32
+ A 10.0.5.33
+ A 10.0.5.34
+ A 10.0.5.35
+ A 10.0.5.36
+ A 10.0.5.37
+ A 10.0.5.38
+ A 10.0.5.39
+ A 10.0.5.40
+ A 10.0.5.41
+ A 10.0.5.42
+ A 10.0.5.43
+ A 10.0.5.44
+ A 10.0.5.45
+ A 10.0.5.46
+ A 10.0.5.47
+ A 10.0.5.48
+ A 10.0.5.49
+ A 10.0.5.50
+ A 10.0.5.51
+ A 10.0.5.52
+ A 10.0.5.53
+ A 10.0.5.54
+ A 10.0.5.55
+ A 10.0.5.56
+ A 10.0.5.57
+ A 10.0.5.58
+ A 10.0.5.59
+ A 10.0.5.60
+ A 10.0.5.61
+ A 10.0.5.62
+ A 10.0.5.63
+ A 10.0.5.64
+ A 10.0.5.65
+ A 10.0.5.66
+ A 10.0.5.67
+ A 10.0.5.68
+ A 10.0.5.69
+ A 10.0.5.70
+ A 10.0.5.71
+ A 10.0.5.72
+ A 10.0.5.73
+ A 10.0.5.74
+ A 10.0.5.75
+ A 10.0.5.76
+ A 10.0.5.77
+ A 10.0.5.78
+ A 10.0.5.79
+ A 10.0.5.80
+ A 10.0.5.81
+ A 10.0.5.82
+ A 10.0.5.83
+ A 10.0.5.84
+ A 10.0.5.85
+ A 10.0.5.86
+ A 10.0.5.87
+ A 10.0.5.88
+ A 10.0.5.89
+ A 10.0.5.90
+ A 10.0.5.91
+ A 10.0.5.92
+ A 10.0.5.93
+ A 10.0.5.94
+ A 10.0.5.95
+ A 10.0.5.96
+ A 10.0.5.97
+ A 10.0.5.98
+ A 10.0.5.99
+ A 10.0.5.100
+ A 10.0.5.101
+ A 10.0.5.102
+ A 10.0.5.103
+ A 10.0.5.104
+ A 10.0.5.105
+ A 10.0.5.106
+ A 10.0.5.107
+ A 10.0.5.108
+ A 10.0.5.109
+ A 10.0.5.110
+ A 10.0.5.111
+ A 10.0.5.112
+ A 10.0.5.113
+ A 10.0.5.114
+ A 10.0.5.115
+ A 10.0.5.116
+ A 10.0.5.117
+ A 10.0.5.118
+ A 10.0.5.119
+ A 10.0.5.120
+ A 10.0.5.121
+ A 10.0.5.122
+ A 10.0.5.123
+ A 10.0.5.124
+ A 10.0.5.125
+ A 10.0.5.126
+ A 10.0.5.127
+ A 10.0.5.128
+ A 10.0.5.129
+ A 10.0.5.130
+ A 10.0.5.131
+ A 10.0.5.132
+ A 10.0.5.133
+ A 10.0.5.134
+ A 10.0.5.135
+ A 10.0.5.136
+ A 10.0.5.137
+ A 10.0.5.138
+ A 10.0.5.139
+ A 10.0.5.140
+ A 10.0.5.141
+ A 10.0.5.142
+ A 10.0.5.143
+ A 10.0.5.144
+ A 10.0.5.145
+ A 10.0.5.146
+ A 10.0.5.147
+ A 10.0.5.148
+ A 10.0.5.149
+ A 10.0.5.150
+ A 10.0.5.151
+ A 10.0.5.152
+ A 10.0.5.153
+ A 10.0.5.154
+ A 10.0.5.155
+ A 10.0.5.156
+ A 10.0.5.157
+ A 10.0.5.158
+ A 10.0.5.159
+ A 10.0.5.160
+ A 10.0.5.161
+ A 10.0.5.162
+ A 10.0.5.163
+ A 10.0.5.164
+ A 10.0.5.165
+ A 10.0.5.166
+ A 10.0.5.167
+ A 10.0.5.168
+ A 10.0.5.169
+ A 10.0.5.170
+ A 10.0.5.171
+ A 10.0.5.172
+ A 10.0.5.173
+ A 10.0.5.174
+ A 10.0.5.175
+ A 10.0.5.176
+ A 10.0.5.177
+ A 10.0.5.178
+ A 10.0.5.179
+ A 10.0.5.180
+ A 10.0.5.181
+ A 10.0.5.182
+ A 10.0.5.183
+ A 10.0.5.184
+ A 10.0.5.185
+ A 10.0.5.186
+ A 10.0.5.187
+ A 10.0.5.188
+ A 10.0.5.189
+ A 10.0.5.190
+ A 10.0.5.191
+ A 10.0.5.192
+ A 10.0.5.193
+ A 10.0.5.194
+ A 10.0.5.195
+ A 10.0.5.196
+ A 10.0.5.197
+ A 10.0.5.198
+ A 10.0.5.199
+ A 10.0.5.200
+ A 10.0.5.201
+ A 10.0.5.202
+ A 10.0.5.203
+ A 10.0.5.204
+ A 10.0.5.205
+ A 10.0.5.206
+ A 10.0.5.207
+ A 10.0.5.208
+ A 10.0.5.209
+ A 10.0.5.210
+ A 10.0.5.211
+ A 10.0.5.212
+ A 10.0.5.213
+ A 10.0.5.214
+ A 10.0.5.215
+ A 10.0.5.216
+ A 10.0.5.217
+ A 10.0.5.218
+ A 10.0.5.219
+ A 10.0.5.220
+ A 10.0.5.221
+ A 10.0.5.222
+ A 10.0.5.223
+ A 10.0.5.224
+ A 10.0.5.225
+ A 10.0.5.226
+ A 10.0.5.227
+ A 10.0.5.228
+ A 10.0.5.229
+ A 10.0.5.230
+ A 10.0.5.231
+ A 10.0.5.232
+ A 10.0.5.233
+ A 10.0.5.234
+ A 10.0.5.235
+ A 10.0.5.236
+ A 10.0.5.237
+ A 10.0.5.238
+ A 10.0.5.239
+ A 10.0.5.240
+ A 10.0.5.241
+ A 10.0.5.242
+ A 10.0.5.243
+ A 10.0.5.244
+ A 10.0.5.245
+ A 10.0.5.246
+ A 10.0.5.247
+ A 10.0.5.248
+ A 10.0.5.249
+ A 10.0.5.250
+ A 10.0.5.251
+ A 10.0.5.252
+ A 10.0.5.253
+ A 10.0.5.254
+ A 10.0.5.255
+ A 10.0.6.0
+ A 10.0.6.1
+ A 10.0.6.2
+ A 10.0.6.3
+ A 10.0.6.4
+ A 10.0.6.5
+ A 10.0.6.6
+ A 10.0.6.7
+ A 10.0.6.8
+ A 10.0.6.9
+ A 10.0.6.10
+ A 10.0.6.11
+ A 10.0.6.12
+ A 10.0.6.13
+ A 10.0.6.14
+ A 10.0.6.15
+ A 10.0.6.16
+ A 10.0.6.17
+ A 10.0.6.18
+ A 10.0.6.19
+ A 10.0.6.20
+ A 10.0.6.21
+ A 10.0.6.22
+ A 10.0.6.23
+ A 10.0.6.24
+ A 10.0.6.25
+ A 10.0.6.26
+ A 10.0.6.27
+ A 10.0.6.28
+ A 10.0.6.29
+ A 10.0.6.30
+ A 10.0.6.31
+ A 10.0.6.32
+ A 10.0.6.33
+ A 10.0.6.34
+ A 10.0.6.35
+ A 10.0.6.36
+ A 10.0.6.37
+ A 10.0.6.38
+ A 10.0.6.39
+ A 10.0.6.40
+ A 10.0.6.41
+ A 10.0.6.42
+ A 10.0.6.43
+ A 10.0.6.44
+ A 10.0.6.45
+ A 10.0.6.46
+ A 10.0.6.47
+ A 10.0.6.48
+ A 10.0.6.49
+ A 10.0.6.50
+ A 10.0.6.51
+ A 10.0.6.52
+ A 10.0.6.53
+ A 10.0.6.54
+ A 10.0.6.55
+ A 10.0.6.56
+ A 10.0.6.57
+ A 10.0.6.58
+ A 10.0.6.59
+ A 10.0.6.60
+ A 10.0.6.61
+ A 10.0.6.62
+ A 10.0.6.63
+ A 10.0.6.64
+ A 10.0.6.65
+ A 10.0.6.66
+ A 10.0.6.67
+ A 10.0.6.68
+ A 10.0.6.69
+ A 10.0.6.70
+ A 10.0.6.71
+ A 10.0.6.72
+ A 10.0.6.73
+ A 10.0.6.74
+ A 10.0.6.75
+ A 10.0.6.76
+ A 10.0.6.77
+ A 10.0.6.78
+ A 10.0.6.79
+ A 10.0.6.80
+ A 10.0.6.81
+ A 10.0.6.82
+ A 10.0.6.83
+ A 10.0.6.84
+ A 10.0.6.85
+ A 10.0.6.86
+ A 10.0.6.87
+ A 10.0.6.88
+ A 10.0.6.89
+ A 10.0.6.90
+ A 10.0.6.91
+ A 10.0.6.92
+ A 10.0.6.93
+ A 10.0.6.94
+ A 10.0.6.95
+ A 10.0.6.96
+ A 10.0.6.97
+ A 10.0.6.98
+ A 10.0.6.99
+ A 10.0.6.100
+ A 10.0.6.101
+ A 10.0.6.102
+ A 10.0.6.103
+ A 10.0.6.104
+ A 10.0.6.105
+ A 10.0.6.106
+ A 10.0.6.107
+ A 10.0.6.108
+ A 10.0.6.109
+ A 10.0.6.110
+ A 10.0.6.111
+ A 10.0.6.112
+ A 10.0.6.113
+ A 10.0.6.114
+ A 10.0.6.115
+ A 10.0.6.116
+ A 10.0.6.117
+ A 10.0.6.118
+ A 10.0.6.119
+ A 10.0.6.120
+ A 10.0.6.121
+ A 10.0.6.122
+ A 10.0.6.123
+ A 10.0.6.124
+ A 10.0.6.125
+ A 10.0.6.126
+ A 10.0.6.127
+ A 10.0.6.128
+ A 10.0.6.129
+ A 10.0.6.130
+ A 10.0.6.131
+ A 10.0.6.132
+ A 10.0.6.133
+ A 10.0.6.134
+ A 10.0.6.135
+ A 10.0.6.136
+ A 10.0.6.137
+ A 10.0.6.138
+ A 10.0.6.139
+ A 10.0.6.140
+ A 10.0.6.141
+ A 10.0.6.142
+ A 10.0.6.143
+ A 10.0.6.144
+ A 10.0.6.145
+ A 10.0.6.146
+ A 10.0.6.147
+ A 10.0.6.148
+ A 10.0.6.149
+ A 10.0.6.150
+ A 10.0.6.151
+ A 10.0.6.152
+ A 10.0.6.153
+ A 10.0.6.154
+ A 10.0.6.155
+ A 10.0.6.156
+ A 10.0.6.157
+ A 10.0.6.158
+ A 10.0.6.159
+ A 10.0.6.160
+ A 10.0.6.161
+ A 10.0.6.162
+ A 10.0.6.163
+ A 10.0.6.164
+ A 10.0.6.165
+ A 10.0.6.166
+ A 10.0.6.167
+ A 10.0.6.168
+ A 10.0.6.169
+ A 10.0.6.170
+ A 10.0.6.171
+ A 10.0.6.172
+ A 10.0.6.173
+ A 10.0.6.174
+ A 10.0.6.175
+ A 10.0.6.176
+ A 10.0.6.177
+ A 10.0.6.178
+ A 10.0.6.179
+ A 10.0.6.180
+ A 10.0.6.181
+ A 10.0.6.182
+ A 10.0.6.183
+ A 10.0.6.184
+ A 10.0.6.185
+ A 10.0.6.186
+ A 10.0.6.187
+ A 10.0.6.188
+ A 10.0.6.189
+ A 10.0.6.190
+ A 10.0.6.191
+ A 10.0.6.192
+ A 10.0.6.193
+ A 10.0.6.194
+ A 10.0.6.195
+ A 10.0.6.196
+ A 10.0.6.197
+ A 10.0.6.198
+ A 10.0.6.199
+ A 10.0.6.200
+ A 10.0.6.201
+ A 10.0.6.202
+ A 10.0.6.203
+ A 10.0.6.204
+ A 10.0.6.205
+ A 10.0.6.206
+ A 10.0.6.207
+ A 10.0.6.208
+ A 10.0.6.209
+ A 10.0.6.210
+ A 10.0.6.211
+ A 10.0.6.212
+ A 10.0.6.213
+ A 10.0.6.214
+ A 10.0.6.215
+ A 10.0.6.216
+ A 10.0.6.217
+ A 10.0.6.218
+ A 10.0.6.219
+ A 10.0.6.220
+ A 10.0.6.221
+ A 10.0.6.222
+ A 10.0.6.223
+ A 10.0.6.224
+ A 10.0.6.225
+ A 10.0.6.226
+ A 10.0.6.227
+ A 10.0.6.228
+ A 10.0.6.229
+ A 10.0.6.230
+ A 10.0.6.231
+ A 10.0.6.232
+ A 10.0.6.233
+ A 10.0.6.234
+ A 10.0.6.235
+ A 10.0.6.236
+ A 10.0.6.237
+ A 10.0.6.238
+ A 10.0.6.239
+ A 10.0.6.240
+ A 10.0.6.241
+ A 10.0.6.242
+ A 10.0.6.243
+ A 10.0.6.244
+ A 10.0.6.245
+ A 10.0.6.246
+ A 10.0.6.247
+ A 10.0.6.248
+ A 10.0.6.249
+ A 10.0.6.250
+ A 10.0.6.251
+ A 10.0.6.252
+ A 10.0.6.253
+ A 10.0.6.254
+ A 10.0.6.255
+ A 10.0.7.0
+ A 10.0.7.1
+ A 10.0.7.2
+ A 10.0.7.3
+ A 10.0.7.4
+ A 10.0.7.5
+ A 10.0.7.6
+ A 10.0.7.7
+ A 10.0.7.8
+ A 10.0.7.9
+ A 10.0.7.10
+ A 10.0.7.11
+ A 10.0.7.12
+ A 10.0.7.13
+ A 10.0.7.14
+ A 10.0.7.15
+ A 10.0.7.16
+ A 10.0.7.17
+ A 10.0.7.18
+ A 10.0.7.19
+ A 10.0.7.20
+ A 10.0.7.21
+ A 10.0.7.22
+ A 10.0.7.23
+ A 10.0.7.24
+ A 10.0.7.25
+ A 10.0.7.26
+ A 10.0.7.27
+ A 10.0.7.28
+ A 10.0.7.29
+ A 10.0.7.30
+ A 10.0.7.31
+ A 10.0.7.32
+ A 10.0.7.33
+ A 10.0.7.34
+ A 10.0.7.35
+ A 10.0.7.36
+ A 10.0.7.37
+ A 10.0.7.38
+ A 10.0.7.39
+ A 10.0.7.40
+ A 10.0.7.41
+ A 10.0.7.42
+ A 10.0.7.43
+ A 10.0.7.44
+ A 10.0.7.45
+ A 10.0.7.46
+ A 10.0.7.47
+ A 10.0.7.48
+ A 10.0.7.49
+ A 10.0.7.50
+ A 10.0.7.51
+ A 10.0.7.52
+ A 10.0.7.53
+ A 10.0.7.54
+ A 10.0.7.55
+ A 10.0.7.56
+ A 10.0.7.57
+ A 10.0.7.58
+ A 10.0.7.59
+ A 10.0.7.60
+ A 10.0.7.61
+ A 10.0.7.62
+ A 10.0.7.63
+ A 10.0.7.64
+ A 10.0.7.65
+ A 10.0.7.66
+ A 10.0.7.67
+ A 10.0.7.68
+ A 10.0.7.69
+ A 10.0.7.70
+ A 10.0.7.71
+ A 10.0.7.72
+ A 10.0.7.73
+ A 10.0.7.74
+ A 10.0.7.75
+ A 10.0.7.76
+ A 10.0.7.77
+ A 10.0.7.78
+ A 10.0.7.79
+ A 10.0.7.80
+ A 10.0.7.81
+ A 10.0.7.82
+ A 10.0.7.83
+ A 10.0.7.84
+ A 10.0.7.85
+ A 10.0.7.86
+ A 10.0.7.87
+ A 10.0.7.88
+ A 10.0.7.89
+ A 10.0.7.90
+ A 10.0.7.91
+ A 10.0.7.92
+ A 10.0.7.93
+ A 10.0.7.94
+ A 10.0.7.95
+ A 10.0.7.96
+ A 10.0.7.97
+ A 10.0.7.98
+ A 10.0.7.99
+ A 10.0.7.100
+ A 10.0.7.101
+ A 10.0.7.102
+ A 10.0.7.103
+ A 10.0.7.104
+ A 10.0.7.105
+ A 10.0.7.106
+ A 10.0.7.107
+ A 10.0.7.108
+ A 10.0.7.109
+ A 10.0.7.110
+ A 10.0.7.111
+ A 10.0.7.112
+ A 10.0.7.113
+ A 10.0.7.114
+ A 10.0.7.115
+ A 10.0.7.116
+ A 10.0.7.117
+ A 10.0.7.118
+ A 10.0.7.119
+ A 10.0.7.120
+ A 10.0.7.121
+ A 10.0.7.122
+ A 10.0.7.123
+ A 10.0.7.124
+ A 10.0.7.125
+ A 10.0.7.126
+ A 10.0.7.127
+ A 10.0.7.128
+ A 10.0.7.129
+ A 10.0.7.130
+ A 10.0.7.131
+ A 10.0.7.132
+ A 10.0.7.133
+ A 10.0.7.134
+ A 10.0.7.135
+ A 10.0.7.136
+ A 10.0.7.137
+ A 10.0.7.138
+ A 10.0.7.139
+ A 10.0.7.140
+ A 10.0.7.141
+ A 10.0.7.142
+ A 10.0.7.143
+ A 10.0.7.144
+ A 10.0.7.145
+ A 10.0.7.146
+ A 10.0.7.147
+ A 10.0.7.148
+ A 10.0.7.149
+ A 10.0.7.150
+ A 10.0.7.151
+ A 10.0.7.152
+ A 10.0.7.153
+ A 10.0.7.154
+ A 10.0.7.155
+ A 10.0.7.156
+ A 10.0.7.157
+ A 10.0.7.158
+ A 10.0.7.159
+ A 10.0.7.160
+ A 10.0.7.161
+ A 10.0.7.162
+ A 10.0.7.163
+ A 10.0.7.164
+ A 10.0.7.165
+ A 10.0.7.166
+ A 10.0.7.167
+ A 10.0.7.168
+ A 10.0.7.169
+ A 10.0.7.170
+ A 10.0.7.171
+ A 10.0.7.172
+ A 10.0.7.173
+ A 10.0.7.174
+ A 10.0.7.175
+ A 10.0.7.176
+ A 10.0.7.177
+ A 10.0.7.178
+ A 10.0.7.179
+ A 10.0.7.180
+ A 10.0.7.181
+ A 10.0.7.182
+ A 10.0.7.183
+ A 10.0.7.184
+ A 10.0.7.185
+ A 10.0.7.186
+ A 10.0.7.187
+ A 10.0.7.188
+ A 10.0.7.189
+ A 10.0.7.190
+ A 10.0.7.191
+ A 10.0.7.192
+ A 10.0.7.193
+ A 10.0.7.194
+ A 10.0.7.195
+ A 10.0.7.196
+ A 10.0.7.197
+ A 10.0.7.198
+ A 10.0.7.199
+ A 10.0.7.200
+ A 10.0.7.201
+ A 10.0.7.202
+ A 10.0.7.203
+ A 10.0.7.204
+ A 10.0.7.205
+ A 10.0.7.206
+ A 10.0.7.207
+3000 A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+ A 10.0.3.232
+ A 10.0.3.233
+ A 10.0.3.234
+ A 10.0.3.235
+ A 10.0.3.236
+ A 10.0.3.237
+ A 10.0.3.238
+ A 10.0.3.239
+ A 10.0.3.240
+ A 10.0.3.241
+ A 10.0.3.242
+ A 10.0.3.243
+ A 10.0.3.244
+ A 10.0.3.245
+ A 10.0.3.246
+ A 10.0.3.247
+ A 10.0.3.248
+ A 10.0.3.249
+ A 10.0.3.250
+ A 10.0.3.251
+ A 10.0.3.252
+ A 10.0.3.253
+ A 10.0.3.254
+ A 10.0.3.255
+ A 10.0.4.0
+ A 10.0.4.1
+ A 10.0.4.2
+ A 10.0.4.3
+ A 10.0.4.4
+ A 10.0.4.5
+ A 10.0.4.6
+ A 10.0.4.7
+ A 10.0.4.8
+ A 10.0.4.9
+ A 10.0.4.10
+ A 10.0.4.11
+ A 10.0.4.12
+ A 10.0.4.13
+ A 10.0.4.14
+ A 10.0.4.15
+ A 10.0.4.16
+ A 10.0.4.17
+ A 10.0.4.18
+ A 10.0.4.19
+ A 10.0.4.20
+ A 10.0.4.21
+ A 10.0.4.22
+ A 10.0.4.23
+ A 10.0.4.24
+ A 10.0.4.25
+ A 10.0.4.26
+ A 10.0.4.27
+ A 10.0.4.28
+ A 10.0.4.29
+ A 10.0.4.30
+ A 10.0.4.31
+ A 10.0.4.32
+ A 10.0.4.33
+ A 10.0.4.34
+ A 10.0.4.35
+ A 10.0.4.36
+ A 10.0.4.37
+ A 10.0.4.38
+ A 10.0.4.39
+ A 10.0.4.40
+ A 10.0.4.41
+ A 10.0.4.42
+ A 10.0.4.43
+ A 10.0.4.44
+ A 10.0.4.45
+ A 10.0.4.46
+ A 10.0.4.47
+ A 10.0.4.48
+ A 10.0.4.49
+ A 10.0.4.50
+ A 10.0.4.51
+ A 10.0.4.52
+ A 10.0.4.53
+ A 10.0.4.54
+ A 10.0.4.55
+ A 10.0.4.56
+ A 10.0.4.57
+ A 10.0.4.58
+ A 10.0.4.59
+ A 10.0.4.60
+ A 10.0.4.61
+ A 10.0.4.62
+ A 10.0.4.63
+ A 10.0.4.64
+ A 10.0.4.65
+ A 10.0.4.66
+ A 10.0.4.67
+ A 10.0.4.68
+ A 10.0.4.69
+ A 10.0.4.70
+ A 10.0.4.71
+ A 10.0.4.72
+ A 10.0.4.73
+ A 10.0.4.74
+ A 10.0.4.75
+ A 10.0.4.76
+ A 10.0.4.77
+ A 10.0.4.78
+ A 10.0.4.79
+ A 10.0.4.80
+ A 10.0.4.81
+ A 10.0.4.82
+ A 10.0.4.83
+ A 10.0.4.84
+ A 10.0.4.85
+ A 10.0.4.86
+ A 10.0.4.87
+ A 10.0.4.88
+ A 10.0.4.89
+ A 10.0.4.90
+ A 10.0.4.91
+ A 10.0.4.92
+ A 10.0.4.93
+ A 10.0.4.94
+ A 10.0.4.95
+ A 10.0.4.96
+ A 10.0.4.97
+ A 10.0.4.98
+ A 10.0.4.99
+ A 10.0.4.100
+ A 10.0.4.101
+ A 10.0.4.102
+ A 10.0.4.103
+ A 10.0.4.104
+ A 10.0.4.105
+ A 10.0.4.106
+ A 10.0.4.107
+ A 10.0.4.108
+ A 10.0.4.109
+ A 10.0.4.110
+ A 10.0.4.111
+ A 10.0.4.112
+ A 10.0.4.113
+ A 10.0.4.114
+ A 10.0.4.115
+ A 10.0.4.116
+ A 10.0.4.117
+ A 10.0.4.118
+ A 10.0.4.119
+ A 10.0.4.120
+ A 10.0.4.121
+ A 10.0.4.122
+ A 10.0.4.123
+ A 10.0.4.124
+ A 10.0.4.125
+ A 10.0.4.126
+ A 10.0.4.127
+ A 10.0.4.128
+ A 10.0.4.129
+ A 10.0.4.130
+ A 10.0.4.131
+ A 10.0.4.132
+ A 10.0.4.133
+ A 10.0.4.134
+ A 10.0.4.135
+ A 10.0.4.136
+ A 10.0.4.137
+ A 10.0.4.138
+ A 10.0.4.139
+ A 10.0.4.140
+ A 10.0.4.141
+ A 10.0.4.142
+ A 10.0.4.143
+ A 10.0.4.144
+ A 10.0.4.145
+ A 10.0.4.146
+ A 10.0.4.147
+ A 10.0.4.148
+ A 10.0.4.149
+ A 10.0.4.150
+ A 10.0.4.151
+ A 10.0.4.152
+ A 10.0.4.153
+ A 10.0.4.154
+ A 10.0.4.155
+ A 10.0.4.156
+ A 10.0.4.157
+ A 10.0.4.158
+ A 10.0.4.159
+ A 10.0.4.160
+ A 10.0.4.161
+ A 10.0.4.162
+ A 10.0.4.163
+ A 10.0.4.164
+ A 10.0.4.165
+ A 10.0.4.166
+ A 10.0.4.167
+ A 10.0.4.168
+ A 10.0.4.169
+ A 10.0.4.170
+ A 10.0.4.171
+ A 10.0.4.172
+ A 10.0.4.173
+ A 10.0.4.174
+ A 10.0.4.175
+ A 10.0.4.176
+ A 10.0.4.177
+ A 10.0.4.178
+ A 10.0.4.179
+ A 10.0.4.180
+ A 10.0.4.181
+ A 10.0.4.182
+ A 10.0.4.183
+ A 10.0.4.184
+ A 10.0.4.185
+ A 10.0.4.186
+ A 10.0.4.187
+ A 10.0.4.188
+ A 10.0.4.189
+ A 10.0.4.190
+ A 10.0.4.191
+ A 10.0.4.192
+ A 10.0.4.193
+ A 10.0.4.194
+ A 10.0.4.195
+ A 10.0.4.196
+ A 10.0.4.197
+ A 10.0.4.198
+ A 10.0.4.199
+ A 10.0.4.200
+ A 10.0.4.201
+ A 10.0.4.202
+ A 10.0.4.203
+ A 10.0.4.204
+ A 10.0.4.205
+ A 10.0.4.206
+ A 10.0.4.207
+ A 10.0.4.208
+ A 10.0.4.209
+ A 10.0.4.210
+ A 10.0.4.211
+ A 10.0.4.212
+ A 10.0.4.213
+ A 10.0.4.214
+ A 10.0.4.215
+ A 10.0.4.216
+ A 10.0.4.217
+ A 10.0.4.218
+ A 10.0.4.219
+ A 10.0.4.220
+ A 10.0.4.221
+ A 10.0.4.222
+ A 10.0.4.223
+ A 10.0.4.224
+ A 10.0.4.225
+ A 10.0.4.226
+ A 10.0.4.227
+ A 10.0.4.228
+ A 10.0.4.229
+ A 10.0.4.230
+ A 10.0.4.231
+ A 10.0.4.232
+ A 10.0.4.233
+ A 10.0.4.234
+ A 10.0.4.235
+ A 10.0.4.236
+ A 10.0.4.237
+ A 10.0.4.238
+ A 10.0.4.239
+ A 10.0.4.240
+ A 10.0.4.241
+ A 10.0.4.242
+ A 10.0.4.243
+ A 10.0.4.244
+ A 10.0.4.245
+ A 10.0.4.246
+ A 10.0.4.247
+ A 10.0.4.248
+ A 10.0.4.249
+ A 10.0.4.250
+ A 10.0.4.251
+ A 10.0.4.252
+ A 10.0.4.253
+ A 10.0.4.254
+ A 10.0.4.255
+ A 10.0.5.0
+ A 10.0.5.1
+ A 10.0.5.2
+ A 10.0.5.3
+ A 10.0.5.4
+ A 10.0.5.5
+ A 10.0.5.6
+ A 10.0.5.7
+ A 10.0.5.8
+ A 10.0.5.9
+ A 10.0.5.10
+ A 10.0.5.11
+ A 10.0.5.12
+ A 10.0.5.13
+ A 10.0.5.14
+ A 10.0.5.15
+ A 10.0.5.16
+ A 10.0.5.17
+ A 10.0.5.18
+ A 10.0.5.19
+ A 10.0.5.20
+ A 10.0.5.21
+ A 10.0.5.22
+ A 10.0.5.23
+ A 10.0.5.24
+ A 10.0.5.25
+ A 10.0.5.26
+ A 10.0.5.27
+ A 10.0.5.28
+ A 10.0.5.29
+ A 10.0.5.30
+ A 10.0.5.31
+ A 10.0.5.32
+ A 10.0.5.33
+ A 10.0.5.34
+ A 10.0.5.35
+ A 10.0.5.36
+ A 10.0.5.37
+ A 10.0.5.38
+ A 10.0.5.39
+ A 10.0.5.40
+ A 10.0.5.41
+ A 10.0.5.42
+ A 10.0.5.43
+ A 10.0.5.44
+ A 10.0.5.45
+ A 10.0.5.46
+ A 10.0.5.47
+ A 10.0.5.48
+ A 10.0.5.49
+ A 10.0.5.50
+ A 10.0.5.51
+ A 10.0.5.52
+ A 10.0.5.53
+ A 10.0.5.54
+ A 10.0.5.55
+ A 10.0.5.56
+ A 10.0.5.57
+ A 10.0.5.58
+ A 10.0.5.59
+ A 10.0.5.60
+ A 10.0.5.61
+ A 10.0.5.62
+ A 10.0.5.63
+ A 10.0.5.64
+ A 10.0.5.65
+ A 10.0.5.66
+ A 10.0.5.67
+ A 10.0.5.68
+ A 10.0.5.69
+ A 10.0.5.70
+ A 10.0.5.71
+ A 10.0.5.72
+ A 10.0.5.73
+ A 10.0.5.74
+ A 10.0.5.75
+ A 10.0.5.76
+ A 10.0.5.77
+ A 10.0.5.78
+ A 10.0.5.79
+ A 10.0.5.80
+ A 10.0.5.81
+ A 10.0.5.82
+ A 10.0.5.83
+ A 10.0.5.84
+ A 10.0.5.85
+ A 10.0.5.86
+ A 10.0.5.87
+ A 10.0.5.88
+ A 10.0.5.89
+ A 10.0.5.90
+ A 10.0.5.91
+ A 10.0.5.92
+ A 10.0.5.93
+ A 10.0.5.94
+ A 10.0.5.95
+ A 10.0.5.96
+ A 10.0.5.97
+ A 10.0.5.98
+ A 10.0.5.99
+ A 10.0.5.100
+ A 10.0.5.101
+ A 10.0.5.102
+ A 10.0.5.103
+ A 10.0.5.104
+ A 10.0.5.105
+ A 10.0.5.106
+ A 10.0.5.107
+ A 10.0.5.108
+ A 10.0.5.109
+ A 10.0.5.110
+ A 10.0.5.111
+ A 10.0.5.112
+ A 10.0.5.113
+ A 10.0.5.114
+ A 10.0.5.115
+ A 10.0.5.116
+ A 10.0.5.117
+ A 10.0.5.118
+ A 10.0.5.119
+ A 10.0.5.120
+ A 10.0.5.121
+ A 10.0.5.122
+ A 10.0.5.123
+ A 10.0.5.124
+ A 10.0.5.125
+ A 10.0.5.126
+ A 10.0.5.127
+ A 10.0.5.128
+ A 10.0.5.129
+ A 10.0.5.130
+ A 10.0.5.131
+ A 10.0.5.132
+ A 10.0.5.133
+ A 10.0.5.134
+ A 10.0.5.135
+ A 10.0.5.136
+ A 10.0.5.137
+ A 10.0.5.138
+ A 10.0.5.139
+ A 10.0.5.140
+ A 10.0.5.141
+ A 10.0.5.142
+ A 10.0.5.143
+ A 10.0.5.144
+ A 10.0.5.145
+ A 10.0.5.146
+ A 10.0.5.147
+ A 10.0.5.148
+ A 10.0.5.149
+ A 10.0.5.150
+ A 10.0.5.151
+ A 10.0.5.152
+ A 10.0.5.153
+ A 10.0.5.154
+ A 10.0.5.155
+ A 10.0.5.156
+ A 10.0.5.157
+ A 10.0.5.158
+ A 10.0.5.159
+ A 10.0.5.160
+ A 10.0.5.161
+ A 10.0.5.162
+ A 10.0.5.163
+ A 10.0.5.164
+ A 10.0.5.165
+ A 10.0.5.166
+ A 10.0.5.167
+ A 10.0.5.168
+ A 10.0.5.169
+ A 10.0.5.170
+ A 10.0.5.171
+ A 10.0.5.172
+ A 10.0.5.173
+ A 10.0.5.174
+ A 10.0.5.175
+ A 10.0.5.176
+ A 10.0.5.177
+ A 10.0.5.178
+ A 10.0.5.179
+ A 10.0.5.180
+ A 10.0.5.181
+ A 10.0.5.182
+ A 10.0.5.183
+ A 10.0.5.184
+ A 10.0.5.185
+ A 10.0.5.186
+ A 10.0.5.187
+ A 10.0.5.188
+ A 10.0.5.189
+ A 10.0.5.190
+ A 10.0.5.191
+ A 10.0.5.192
+ A 10.0.5.193
+ A 10.0.5.194
+ A 10.0.5.195
+ A 10.0.5.196
+ A 10.0.5.197
+ A 10.0.5.198
+ A 10.0.5.199
+ A 10.0.5.200
+ A 10.0.5.201
+ A 10.0.5.202
+ A 10.0.5.203
+ A 10.0.5.204
+ A 10.0.5.205
+ A 10.0.5.206
+ A 10.0.5.207
+ A 10.0.5.208
+ A 10.0.5.209
+ A 10.0.5.210
+ A 10.0.5.211
+ A 10.0.5.212
+ A 10.0.5.213
+ A 10.0.5.214
+ A 10.0.5.215
+ A 10.0.5.216
+ A 10.0.5.217
+ A 10.0.5.218
+ A 10.0.5.219
+ A 10.0.5.220
+ A 10.0.5.221
+ A 10.0.5.222
+ A 10.0.5.223
+ A 10.0.5.224
+ A 10.0.5.225
+ A 10.0.5.226
+ A 10.0.5.227
+ A 10.0.5.228
+ A 10.0.5.229
+ A 10.0.5.230
+ A 10.0.5.231
+ A 10.0.5.232
+ A 10.0.5.233
+ A 10.0.5.234
+ A 10.0.5.235
+ A 10.0.5.236
+ A 10.0.5.237
+ A 10.0.5.238
+ A 10.0.5.239
+ A 10.0.5.240
+ A 10.0.5.241
+ A 10.0.5.242
+ A 10.0.5.243
+ A 10.0.5.244
+ A 10.0.5.245
+ A 10.0.5.246
+ A 10.0.5.247
+ A 10.0.5.248
+ A 10.0.5.249
+ A 10.0.5.250
+ A 10.0.5.251
+ A 10.0.5.252
+ A 10.0.5.253
+ A 10.0.5.254
+ A 10.0.5.255
+ A 10.0.6.0
+ A 10.0.6.1
+ A 10.0.6.2
+ A 10.0.6.3
+ A 10.0.6.4
+ A 10.0.6.5
+ A 10.0.6.6
+ A 10.0.6.7
+ A 10.0.6.8
+ A 10.0.6.9
+ A 10.0.6.10
+ A 10.0.6.11
+ A 10.0.6.12
+ A 10.0.6.13
+ A 10.0.6.14
+ A 10.0.6.15
+ A 10.0.6.16
+ A 10.0.6.17
+ A 10.0.6.18
+ A 10.0.6.19
+ A 10.0.6.20
+ A 10.0.6.21
+ A 10.0.6.22
+ A 10.0.6.23
+ A 10.0.6.24
+ A 10.0.6.25
+ A 10.0.6.26
+ A 10.0.6.27
+ A 10.0.6.28
+ A 10.0.6.29
+ A 10.0.6.30
+ A 10.0.6.31
+ A 10.0.6.32
+ A 10.0.6.33
+ A 10.0.6.34
+ A 10.0.6.35
+ A 10.0.6.36
+ A 10.0.6.37
+ A 10.0.6.38
+ A 10.0.6.39
+ A 10.0.6.40
+ A 10.0.6.41
+ A 10.0.6.42
+ A 10.0.6.43
+ A 10.0.6.44
+ A 10.0.6.45
+ A 10.0.6.46
+ A 10.0.6.47
+ A 10.0.6.48
+ A 10.0.6.49
+ A 10.0.6.50
+ A 10.0.6.51
+ A 10.0.6.52
+ A 10.0.6.53
+ A 10.0.6.54
+ A 10.0.6.55
+ A 10.0.6.56
+ A 10.0.6.57
+ A 10.0.6.58
+ A 10.0.6.59
+ A 10.0.6.60
+ A 10.0.6.61
+ A 10.0.6.62
+ A 10.0.6.63
+ A 10.0.6.64
+ A 10.0.6.65
+ A 10.0.6.66
+ A 10.0.6.67
+ A 10.0.6.68
+ A 10.0.6.69
+ A 10.0.6.70
+ A 10.0.6.71
+ A 10.0.6.72
+ A 10.0.6.73
+ A 10.0.6.74
+ A 10.0.6.75
+ A 10.0.6.76
+ A 10.0.6.77
+ A 10.0.6.78
+ A 10.0.6.79
+ A 10.0.6.80
+ A 10.0.6.81
+ A 10.0.6.82
+ A 10.0.6.83
+ A 10.0.6.84
+ A 10.0.6.85
+ A 10.0.6.86
+ A 10.0.6.87
+ A 10.0.6.88
+ A 10.0.6.89
+ A 10.0.6.90
+ A 10.0.6.91
+ A 10.0.6.92
+ A 10.0.6.93
+ A 10.0.6.94
+ A 10.0.6.95
+ A 10.0.6.96
+ A 10.0.6.97
+ A 10.0.6.98
+ A 10.0.6.99
+ A 10.0.6.100
+ A 10.0.6.101
+ A 10.0.6.102
+ A 10.0.6.103
+ A 10.0.6.104
+ A 10.0.6.105
+ A 10.0.6.106
+ A 10.0.6.107
+ A 10.0.6.108
+ A 10.0.6.109
+ A 10.0.6.110
+ A 10.0.6.111
+ A 10.0.6.112
+ A 10.0.6.113
+ A 10.0.6.114
+ A 10.0.6.115
+ A 10.0.6.116
+ A 10.0.6.117
+ A 10.0.6.118
+ A 10.0.6.119
+ A 10.0.6.120
+ A 10.0.6.121
+ A 10.0.6.122
+ A 10.0.6.123
+ A 10.0.6.124
+ A 10.0.6.125
+ A 10.0.6.126
+ A 10.0.6.127
+ A 10.0.6.128
+ A 10.0.6.129
+ A 10.0.6.130
+ A 10.0.6.131
+ A 10.0.6.132
+ A 10.0.6.133
+ A 10.0.6.134
+ A 10.0.6.135
+ A 10.0.6.136
+ A 10.0.6.137
+ A 10.0.6.138
+ A 10.0.6.139
+ A 10.0.6.140
+ A 10.0.6.141
+ A 10.0.6.142
+ A 10.0.6.143
+ A 10.0.6.144
+ A 10.0.6.145
+ A 10.0.6.146
+ A 10.0.6.147
+ A 10.0.6.148
+ A 10.0.6.149
+ A 10.0.6.150
+ A 10.0.6.151
+ A 10.0.6.152
+ A 10.0.6.153
+ A 10.0.6.154
+ A 10.0.6.155
+ A 10.0.6.156
+ A 10.0.6.157
+ A 10.0.6.158
+ A 10.0.6.159
+ A 10.0.6.160
+ A 10.0.6.161
+ A 10.0.6.162
+ A 10.0.6.163
+ A 10.0.6.164
+ A 10.0.6.165
+ A 10.0.6.166
+ A 10.0.6.167
+ A 10.0.6.168
+ A 10.0.6.169
+ A 10.0.6.170
+ A 10.0.6.171
+ A 10.0.6.172
+ A 10.0.6.173
+ A 10.0.6.174
+ A 10.0.6.175
+ A 10.0.6.176
+ A 10.0.6.177
+ A 10.0.6.178
+ A 10.0.6.179
+ A 10.0.6.180
+ A 10.0.6.181
+ A 10.0.6.182
+ A 10.0.6.183
+ A 10.0.6.184
+ A 10.0.6.185
+ A 10.0.6.186
+ A 10.0.6.187
+ A 10.0.6.188
+ A 10.0.6.189
+ A 10.0.6.190
+ A 10.0.6.191
+ A 10.0.6.192
+ A 10.0.6.193
+ A 10.0.6.194
+ A 10.0.6.195
+ A 10.0.6.196
+ A 10.0.6.197
+ A 10.0.6.198
+ A 10.0.6.199
+ A 10.0.6.200
+ A 10.0.6.201
+ A 10.0.6.202
+ A 10.0.6.203
+ A 10.0.6.204
+ A 10.0.6.205
+ A 10.0.6.206
+ A 10.0.6.207
+ A 10.0.6.208
+ A 10.0.6.209
+ A 10.0.6.210
+ A 10.0.6.211
+ A 10.0.6.212
+ A 10.0.6.213
+ A 10.0.6.214
+ A 10.0.6.215
+ A 10.0.6.216
+ A 10.0.6.217
+ A 10.0.6.218
+ A 10.0.6.219
+ A 10.0.6.220
+ A 10.0.6.221
+ A 10.0.6.222
+ A 10.0.6.223
+ A 10.0.6.224
+ A 10.0.6.225
+ A 10.0.6.226
+ A 10.0.6.227
+ A 10.0.6.228
+ A 10.0.6.229
+ A 10.0.6.230
+ A 10.0.6.231
+ A 10.0.6.232
+ A 10.0.6.233
+ A 10.0.6.234
+ A 10.0.6.235
+ A 10.0.6.236
+ A 10.0.6.237
+ A 10.0.6.238
+ A 10.0.6.239
+ A 10.0.6.240
+ A 10.0.6.241
+ A 10.0.6.242
+ A 10.0.6.243
+ A 10.0.6.244
+ A 10.0.6.245
+ A 10.0.6.246
+ A 10.0.6.247
+ A 10.0.6.248
+ A 10.0.6.249
+ A 10.0.6.250
+ A 10.0.6.251
+ A 10.0.6.252
+ A 10.0.6.253
+ A 10.0.6.254
+ A 10.0.6.255
+ A 10.0.7.0
+ A 10.0.7.1
+ A 10.0.7.2
+ A 10.0.7.3
+ A 10.0.7.4
+ A 10.0.7.5
+ A 10.0.7.6
+ A 10.0.7.7
+ A 10.0.7.8
+ A 10.0.7.9
+ A 10.0.7.10
+ A 10.0.7.11
+ A 10.0.7.12
+ A 10.0.7.13
+ A 10.0.7.14
+ A 10.0.7.15
+ A 10.0.7.16
+ A 10.0.7.17
+ A 10.0.7.18
+ A 10.0.7.19
+ A 10.0.7.20
+ A 10.0.7.21
+ A 10.0.7.22
+ A 10.0.7.23
+ A 10.0.7.24
+ A 10.0.7.25
+ A 10.0.7.26
+ A 10.0.7.27
+ A 10.0.7.28
+ A 10.0.7.29
+ A 10.0.7.30
+ A 10.0.7.31
+ A 10.0.7.32
+ A 10.0.7.33
+ A 10.0.7.34
+ A 10.0.7.35
+ A 10.0.7.36
+ A 10.0.7.37
+ A 10.0.7.38
+ A 10.0.7.39
+ A 10.0.7.40
+ A 10.0.7.41
+ A 10.0.7.42
+ A 10.0.7.43
+ A 10.0.7.44
+ A 10.0.7.45
+ A 10.0.7.46
+ A 10.0.7.47
+ A 10.0.7.48
+ A 10.0.7.49
+ A 10.0.7.50
+ A 10.0.7.51
+ A 10.0.7.52
+ A 10.0.7.53
+ A 10.0.7.54
+ A 10.0.7.55
+ A 10.0.7.56
+ A 10.0.7.57
+ A 10.0.7.58
+ A 10.0.7.59
+ A 10.0.7.60
+ A 10.0.7.61
+ A 10.0.7.62
+ A 10.0.7.63
+ A 10.0.7.64
+ A 10.0.7.65
+ A 10.0.7.66
+ A 10.0.7.67
+ A 10.0.7.68
+ A 10.0.7.69
+ A 10.0.7.70
+ A 10.0.7.71
+ A 10.0.7.72
+ A 10.0.7.73
+ A 10.0.7.74
+ A 10.0.7.75
+ A 10.0.7.76
+ A 10.0.7.77
+ A 10.0.7.78
+ A 10.0.7.79
+ A 10.0.7.80
+ A 10.0.7.81
+ A 10.0.7.82
+ A 10.0.7.83
+ A 10.0.7.84
+ A 10.0.7.85
+ A 10.0.7.86
+ A 10.0.7.87
+ A 10.0.7.88
+ A 10.0.7.89
+ A 10.0.7.90
+ A 10.0.7.91
+ A 10.0.7.92
+ A 10.0.7.93
+ A 10.0.7.94
+ A 10.0.7.95
+ A 10.0.7.96
+ A 10.0.7.97
+ A 10.0.7.98
+ A 10.0.7.99
+ A 10.0.7.100
+ A 10.0.7.101
+ A 10.0.7.102
+ A 10.0.7.103
+ A 10.0.7.104
+ A 10.0.7.105
+ A 10.0.7.106
+ A 10.0.7.107
+ A 10.0.7.108
+ A 10.0.7.109
+ A 10.0.7.110
+ A 10.0.7.111
+ A 10.0.7.112
+ A 10.0.7.113
+ A 10.0.7.114
+ A 10.0.7.115
+ A 10.0.7.116
+ A 10.0.7.117
+ A 10.0.7.118
+ A 10.0.7.119
+ A 10.0.7.120
+ A 10.0.7.121
+ A 10.0.7.122
+ A 10.0.7.123
+ A 10.0.7.124
+ A 10.0.7.125
+ A 10.0.7.126
+ A 10.0.7.127
+ A 10.0.7.128
+ A 10.0.7.129
+ A 10.0.7.130
+ A 10.0.7.131
+ A 10.0.7.132
+ A 10.0.7.133
+ A 10.0.7.134
+ A 10.0.7.135
+ A 10.0.7.136
+ A 10.0.7.137
+ A 10.0.7.138
+ A 10.0.7.139
+ A 10.0.7.140
+ A 10.0.7.141
+ A 10.0.7.142
+ A 10.0.7.143
+ A 10.0.7.144
+ A 10.0.7.145
+ A 10.0.7.146
+ A 10.0.7.147
+ A 10.0.7.148
+ A 10.0.7.149
+ A 10.0.7.150
+ A 10.0.7.151
+ A 10.0.7.152
+ A 10.0.7.153
+ A 10.0.7.154
+ A 10.0.7.155
+ A 10.0.7.156
+ A 10.0.7.157
+ A 10.0.7.158
+ A 10.0.7.159
+ A 10.0.7.160
+ A 10.0.7.161
+ A 10.0.7.162
+ A 10.0.7.163
+ A 10.0.7.164
+ A 10.0.7.165
+ A 10.0.7.166
+ A 10.0.7.167
+ A 10.0.7.168
+ A 10.0.7.169
+ A 10.0.7.170
+ A 10.0.7.171
+ A 10.0.7.172
+ A 10.0.7.173
+ A 10.0.7.174
+ A 10.0.7.175
+ A 10.0.7.176
+ A 10.0.7.177
+ A 10.0.7.178
+ A 10.0.7.179
+ A 10.0.7.180
+ A 10.0.7.181
+ A 10.0.7.182
+ A 10.0.7.183
+ A 10.0.7.184
+ A 10.0.7.185
+ A 10.0.7.186
+ A 10.0.7.187
+ A 10.0.7.188
+ A 10.0.7.189
+ A 10.0.7.190
+ A 10.0.7.191
+ A 10.0.7.192
+ A 10.0.7.193
+ A 10.0.7.194
+ A 10.0.7.195
+ A 10.0.7.196
+ A 10.0.7.197
+ A 10.0.7.198
+ A 10.0.7.199
+ A 10.0.7.200
+ A 10.0.7.201
+ A 10.0.7.202
+ A 10.0.7.203
+ A 10.0.7.204
+ A 10.0.7.205
+ A 10.0.7.206
+ A 10.0.7.207
+ A 10.0.7.208
+ A 10.0.7.209
+ A 10.0.7.210
+ A 10.0.7.211
+ A 10.0.7.212
+ A 10.0.7.213
+ A 10.0.7.214
+ A 10.0.7.215
+ A 10.0.7.216
+ A 10.0.7.217
+ A 10.0.7.218
+ A 10.0.7.219
+ A 10.0.7.220
+ A 10.0.7.221
+ A 10.0.7.222
+ A 10.0.7.223
+ A 10.0.7.224
+ A 10.0.7.225
+ A 10.0.7.226
+ A 10.0.7.227
+ A 10.0.7.228
+ A 10.0.7.229
+ A 10.0.7.230
+ A 10.0.7.231
+ A 10.0.7.232
+ A 10.0.7.233
+ A 10.0.7.234
+ A 10.0.7.235
+ A 10.0.7.236
+ A 10.0.7.237
+ A 10.0.7.238
+ A 10.0.7.239
+ A 10.0.7.240
+ A 10.0.7.241
+ A 10.0.7.242
+ A 10.0.7.243
+ A 10.0.7.244
+ A 10.0.7.245
+ A 10.0.7.246
+ A 10.0.7.247
+ A 10.0.7.248
+ A 10.0.7.249
+ A 10.0.7.250
+ A 10.0.7.251
+ A 10.0.7.252
+ A 10.0.7.253
+ A 10.0.7.254
+ A 10.0.7.255
+ A 10.0.8.0
+ A 10.0.8.1
+ A 10.0.8.2
+ A 10.0.8.3
+ A 10.0.8.4
+ A 10.0.8.5
+ A 10.0.8.6
+ A 10.0.8.7
+ A 10.0.8.8
+ A 10.0.8.9
+ A 10.0.8.10
+ A 10.0.8.11
+ A 10.0.8.12
+ A 10.0.8.13
+ A 10.0.8.14
+ A 10.0.8.15
+ A 10.0.8.16
+ A 10.0.8.17
+ A 10.0.8.18
+ A 10.0.8.19
+ A 10.0.8.20
+ A 10.0.8.21
+ A 10.0.8.22
+ A 10.0.8.23
+ A 10.0.8.24
+ A 10.0.8.25
+ A 10.0.8.26
+ A 10.0.8.27
+ A 10.0.8.28
+ A 10.0.8.29
+ A 10.0.8.30
+ A 10.0.8.31
+ A 10.0.8.32
+ A 10.0.8.33
+ A 10.0.8.34
+ A 10.0.8.35
+ A 10.0.8.36
+ A 10.0.8.37
+ A 10.0.8.38
+ A 10.0.8.39
+ A 10.0.8.40
+ A 10.0.8.41
+ A 10.0.8.42
+ A 10.0.8.43
+ A 10.0.8.44
+ A 10.0.8.45
+ A 10.0.8.46
+ A 10.0.8.47
+ A 10.0.8.48
+ A 10.0.8.49
+ A 10.0.8.50
+ A 10.0.8.51
+ A 10.0.8.52
+ A 10.0.8.53
+ A 10.0.8.54
+ A 10.0.8.55
+ A 10.0.8.56
+ A 10.0.8.57
+ A 10.0.8.58
+ A 10.0.8.59
+ A 10.0.8.60
+ A 10.0.8.61
+ A 10.0.8.62
+ A 10.0.8.63
+ A 10.0.8.64
+ A 10.0.8.65
+ A 10.0.8.66
+ A 10.0.8.67
+ A 10.0.8.68
+ A 10.0.8.69
+ A 10.0.8.70
+ A 10.0.8.71
+ A 10.0.8.72
+ A 10.0.8.73
+ A 10.0.8.74
+ A 10.0.8.75
+ A 10.0.8.76
+ A 10.0.8.77
+ A 10.0.8.78
+ A 10.0.8.79
+ A 10.0.8.80
+ A 10.0.8.81
+ A 10.0.8.82
+ A 10.0.8.83
+ A 10.0.8.84
+ A 10.0.8.85
+ A 10.0.8.86
+ A 10.0.8.87
+ A 10.0.8.88
+ A 10.0.8.89
+ A 10.0.8.90
+ A 10.0.8.91
+ A 10.0.8.92
+ A 10.0.8.93
+ A 10.0.8.94
+ A 10.0.8.95
+ A 10.0.8.96
+ A 10.0.8.97
+ A 10.0.8.98
+ A 10.0.8.99
+ A 10.0.8.100
+ A 10.0.8.101
+ A 10.0.8.102
+ A 10.0.8.103
+ A 10.0.8.104
+ A 10.0.8.105
+ A 10.0.8.106
+ A 10.0.8.107
+ A 10.0.8.108
+ A 10.0.8.109
+ A 10.0.8.110
+ A 10.0.8.111
+ A 10.0.8.112
+ A 10.0.8.113
+ A 10.0.8.114
+ A 10.0.8.115
+ A 10.0.8.116
+ A 10.0.8.117
+ A 10.0.8.118
+ A 10.0.8.119
+ A 10.0.8.120
+ A 10.0.8.121
+ A 10.0.8.122
+ A 10.0.8.123
+ A 10.0.8.124
+ A 10.0.8.125
+ A 10.0.8.126
+ A 10.0.8.127
+ A 10.0.8.128
+ A 10.0.8.129
+ A 10.0.8.130
+ A 10.0.8.131
+ A 10.0.8.132
+ A 10.0.8.133
+ A 10.0.8.134
+ A 10.0.8.135
+ A 10.0.8.136
+ A 10.0.8.137
+ A 10.0.8.138
+ A 10.0.8.139
+ A 10.0.8.140
+ A 10.0.8.141
+ A 10.0.8.142
+ A 10.0.8.143
+ A 10.0.8.144
+ A 10.0.8.145
+ A 10.0.8.146
+ A 10.0.8.147
+ A 10.0.8.148
+ A 10.0.8.149
+ A 10.0.8.150
+ A 10.0.8.151
+ A 10.0.8.152
+ A 10.0.8.153
+ A 10.0.8.154
+ A 10.0.8.155
+ A 10.0.8.156
+ A 10.0.8.157
+ A 10.0.8.158
+ A 10.0.8.159
+ A 10.0.8.160
+ A 10.0.8.161
+ A 10.0.8.162
+ A 10.0.8.163
+ A 10.0.8.164
+ A 10.0.8.165
+ A 10.0.8.166
+ A 10.0.8.167
+ A 10.0.8.168
+ A 10.0.8.169
+ A 10.0.8.170
+ A 10.0.8.171
+ A 10.0.8.172
+ A 10.0.8.173
+ A 10.0.8.174
+ A 10.0.8.175
+ A 10.0.8.176
+ A 10.0.8.177
+ A 10.0.8.178
+ A 10.0.8.179
+ A 10.0.8.180
+ A 10.0.8.181
+ A 10.0.8.182
+ A 10.0.8.183
+ A 10.0.8.184
+ A 10.0.8.185
+ A 10.0.8.186
+ A 10.0.8.187
+ A 10.0.8.188
+ A 10.0.8.189
+ A 10.0.8.190
+ A 10.0.8.191
+ A 10.0.8.192
+ A 10.0.8.193
+ A 10.0.8.194
+ A 10.0.8.195
+ A 10.0.8.196
+ A 10.0.8.197
+ A 10.0.8.198
+ A 10.0.8.199
+ A 10.0.8.200
+ A 10.0.8.201
+ A 10.0.8.202
+ A 10.0.8.203
+ A 10.0.8.204
+ A 10.0.8.205
+ A 10.0.8.206
+ A 10.0.8.207
+ A 10.0.8.208
+ A 10.0.8.209
+ A 10.0.8.210
+ A 10.0.8.211
+ A 10.0.8.212
+ A 10.0.8.213
+ A 10.0.8.214
+ A 10.0.8.215
+ A 10.0.8.216
+ A 10.0.8.217
+ A 10.0.8.218
+ A 10.0.8.219
+ A 10.0.8.220
+ A 10.0.8.221
+ A 10.0.8.222
+ A 10.0.8.223
+ A 10.0.8.224
+ A 10.0.8.225
+ A 10.0.8.226
+ A 10.0.8.227
+ A 10.0.8.228
+ A 10.0.8.229
+ A 10.0.8.230
+ A 10.0.8.231
+ A 10.0.8.232
+ A 10.0.8.233
+ A 10.0.8.234
+ A 10.0.8.235
+ A 10.0.8.236
+ A 10.0.8.237
+ A 10.0.8.238
+ A 10.0.8.239
+ A 10.0.8.240
+ A 10.0.8.241
+ A 10.0.8.242
+ A 10.0.8.243
+ A 10.0.8.244
+ A 10.0.8.245
+ A 10.0.8.246
+ A 10.0.8.247
+ A 10.0.8.248
+ A 10.0.8.249
+ A 10.0.8.250
+ A 10.0.8.251
+ A 10.0.8.252
+ A 10.0.8.253
+ A 10.0.8.254
+ A 10.0.8.255
+ A 10.0.9.0
+ A 10.0.9.1
+ A 10.0.9.2
+ A 10.0.9.3
+ A 10.0.9.4
+ A 10.0.9.5
+ A 10.0.9.6
+ A 10.0.9.7
+ A 10.0.9.8
+ A 10.0.9.9
+ A 10.0.9.10
+ A 10.0.9.11
+ A 10.0.9.12
+ A 10.0.9.13
+ A 10.0.9.14
+ A 10.0.9.15
+ A 10.0.9.16
+ A 10.0.9.17
+ A 10.0.9.18
+ A 10.0.9.19
+ A 10.0.9.20
+ A 10.0.9.21
+ A 10.0.9.22
+ A 10.0.9.23
+ A 10.0.9.24
+ A 10.0.9.25
+ A 10.0.9.26
+ A 10.0.9.27
+ A 10.0.9.28
+ A 10.0.9.29
+ A 10.0.9.30
+ A 10.0.9.31
+ A 10.0.9.32
+ A 10.0.9.33
+ A 10.0.9.34
+ A 10.0.9.35
+ A 10.0.9.36
+ A 10.0.9.37
+ A 10.0.9.38
+ A 10.0.9.39
+ A 10.0.9.40
+ A 10.0.9.41
+ A 10.0.9.42
+ A 10.0.9.43
+ A 10.0.9.44
+ A 10.0.9.45
+ A 10.0.9.46
+ A 10.0.9.47
+ A 10.0.9.48
+ A 10.0.9.49
+ A 10.0.9.50
+ A 10.0.9.51
+ A 10.0.9.52
+ A 10.0.9.53
+ A 10.0.9.54
+ A 10.0.9.55
+ A 10.0.9.56
+ A 10.0.9.57
+ A 10.0.9.58
+ A 10.0.9.59
+ A 10.0.9.60
+ A 10.0.9.61
+ A 10.0.9.62
+ A 10.0.9.63
+ A 10.0.9.64
+ A 10.0.9.65
+ A 10.0.9.66
+ A 10.0.9.67
+ A 10.0.9.68
+ A 10.0.9.69
+ A 10.0.9.70
+ A 10.0.9.71
+ A 10.0.9.72
+ A 10.0.9.73
+ A 10.0.9.74
+ A 10.0.9.75
+ A 10.0.9.76
+ A 10.0.9.77
+ A 10.0.9.78
+ A 10.0.9.79
+ A 10.0.9.80
+ A 10.0.9.81
+ A 10.0.9.82
+ A 10.0.9.83
+ A 10.0.9.84
+ A 10.0.9.85
+ A 10.0.9.86
+ A 10.0.9.87
+ A 10.0.9.88
+ A 10.0.9.89
+ A 10.0.9.90
+ A 10.0.9.91
+ A 10.0.9.92
+ A 10.0.9.93
+ A 10.0.9.94
+ A 10.0.9.95
+ A 10.0.9.96
+ A 10.0.9.97
+ A 10.0.9.98
+ A 10.0.9.99
+ A 10.0.9.100
+ A 10.0.9.101
+ A 10.0.9.102
+ A 10.0.9.103
+ A 10.0.9.104
+ A 10.0.9.105
+ A 10.0.9.106
+ A 10.0.9.107
+ A 10.0.9.108
+ A 10.0.9.109
+ A 10.0.9.110
+ A 10.0.9.111
+ A 10.0.9.112
+ A 10.0.9.113
+ A 10.0.9.114
+ A 10.0.9.115
+ A 10.0.9.116
+ A 10.0.9.117
+ A 10.0.9.118
+ A 10.0.9.119
+ A 10.0.9.120
+ A 10.0.9.121
+ A 10.0.9.122
+ A 10.0.9.123
+ A 10.0.9.124
+ A 10.0.9.125
+ A 10.0.9.126
+ A 10.0.9.127
+ A 10.0.9.128
+ A 10.0.9.129
+ A 10.0.9.130
+ A 10.0.9.131
+ A 10.0.9.132
+ A 10.0.9.133
+ A 10.0.9.134
+ A 10.0.9.135
+ A 10.0.9.136
+ A 10.0.9.137
+ A 10.0.9.138
+ A 10.0.9.139
+ A 10.0.9.140
+ A 10.0.9.141
+ A 10.0.9.142
+ A 10.0.9.143
+ A 10.0.9.144
+ A 10.0.9.145
+ A 10.0.9.146
+ A 10.0.9.147
+ A 10.0.9.148
+ A 10.0.9.149
+ A 10.0.9.150
+ A 10.0.9.151
+ A 10.0.9.152
+ A 10.0.9.153
+ A 10.0.9.154
+ A 10.0.9.155
+ A 10.0.9.156
+ A 10.0.9.157
+ A 10.0.9.158
+ A 10.0.9.159
+ A 10.0.9.160
+ A 10.0.9.161
+ A 10.0.9.162
+ A 10.0.9.163
+ A 10.0.9.164
+ A 10.0.9.165
+ A 10.0.9.166
+ A 10.0.9.167
+ A 10.0.9.168
+ A 10.0.9.169
+ A 10.0.9.170
+ A 10.0.9.171
+ A 10.0.9.172
+ A 10.0.9.173
+ A 10.0.9.174
+ A 10.0.9.175
+ A 10.0.9.176
+ A 10.0.9.177
+ A 10.0.9.178
+ A 10.0.9.179
+ A 10.0.9.180
+ A 10.0.9.181
+ A 10.0.9.182
+ A 10.0.9.183
+ A 10.0.9.184
+ A 10.0.9.185
+ A 10.0.9.186
+ A 10.0.9.187
+ A 10.0.9.188
+ A 10.0.9.189
+ A 10.0.9.190
+ A 10.0.9.191
+ A 10.0.9.192
+ A 10.0.9.193
+ A 10.0.9.194
+ A 10.0.9.195
+ A 10.0.9.196
+ A 10.0.9.197
+ A 10.0.9.198
+ A 10.0.9.199
+ A 10.0.9.200
+ A 10.0.9.201
+ A 10.0.9.202
+ A 10.0.9.203
+ A 10.0.9.204
+ A 10.0.9.205
+ A 10.0.9.206
+ A 10.0.9.207
+ A 10.0.9.208
+ A 10.0.9.209
+ A 10.0.9.210
+ A 10.0.9.211
+ A 10.0.9.212
+ A 10.0.9.213
+ A 10.0.9.214
+ A 10.0.9.215
+ A 10.0.9.216
+ A 10.0.9.217
+ A 10.0.9.218
+ A 10.0.9.219
+ A 10.0.9.220
+ A 10.0.9.221
+ A 10.0.9.222
+ A 10.0.9.223
+ A 10.0.9.224
+ A 10.0.9.225
+ A 10.0.9.226
+ A 10.0.9.227
+ A 10.0.9.228
+ A 10.0.9.229
+ A 10.0.9.230
+ A 10.0.9.231
+ A 10.0.9.232
+ A 10.0.9.233
+ A 10.0.9.234
+ A 10.0.9.235
+ A 10.0.9.236
+ A 10.0.9.237
+ A 10.0.9.238
+ A 10.0.9.239
+ A 10.0.9.240
+ A 10.0.9.241
+ A 10.0.9.242
+ A 10.0.9.243
+ A 10.0.9.244
+ A 10.0.9.245
+ A 10.0.9.246
+ A 10.0.9.247
+ A 10.0.9.248
+ A 10.0.9.249
+ A 10.0.9.250
+ A 10.0.9.251
+ A 10.0.9.252
+ A 10.0.9.253
+ A 10.0.9.254
+ A 10.0.9.255
+ A 10.0.10.0
+ A 10.0.10.1
+ A 10.0.10.2
+ A 10.0.10.3
+ A 10.0.10.4
+ A 10.0.10.5
+ A 10.0.10.6
+ A 10.0.10.7
+ A 10.0.10.8
+ A 10.0.10.9
+ A 10.0.10.10
+ A 10.0.10.11
+ A 10.0.10.12
+ A 10.0.10.13
+ A 10.0.10.14
+ A 10.0.10.15
+ A 10.0.10.16
+ A 10.0.10.17
+ A 10.0.10.18
+ A 10.0.10.19
+ A 10.0.10.20
+ A 10.0.10.21
+ A 10.0.10.22
+ A 10.0.10.23
+ A 10.0.10.24
+ A 10.0.10.25
+ A 10.0.10.26
+ A 10.0.10.27
+ A 10.0.10.28
+ A 10.0.10.29
+ A 10.0.10.30
+ A 10.0.10.31
+ A 10.0.10.32
+ A 10.0.10.33
+ A 10.0.10.34
+ A 10.0.10.35
+ A 10.0.10.36
+ A 10.0.10.37
+ A 10.0.10.38
+ A 10.0.10.39
+ A 10.0.10.40
+ A 10.0.10.41
+ A 10.0.10.42
+ A 10.0.10.43
+ A 10.0.10.44
+ A 10.0.10.45
+ A 10.0.10.46
+ A 10.0.10.47
+ A 10.0.10.48
+ A 10.0.10.49
+ A 10.0.10.50
+ A 10.0.10.51
+ A 10.0.10.52
+ A 10.0.10.53
+ A 10.0.10.54
+ A 10.0.10.55
+ A 10.0.10.56
+ A 10.0.10.57
+ A 10.0.10.58
+ A 10.0.10.59
+ A 10.0.10.60
+ A 10.0.10.61
+ A 10.0.10.62
+ A 10.0.10.63
+ A 10.0.10.64
+ A 10.0.10.65
+ A 10.0.10.66
+ A 10.0.10.67
+ A 10.0.10.68
+ A 10.0.10.69
+ A 10.0.10.70
+ A 10.0.10.71
+ A 10.0.10.72
+ A 10.0.10.73
+ A 10.0.10.74
+ A 10.0.10.75
+ A 10.0.10.76
+ A 10.0.10.77
+ A 10.0.10.78
+ A 10.0.10.79
+ A 10.0.10.80
+ A 10.0.10.81
+ A 10.0.10.82
+ A 10.0.10.83
+ A 10.0.10.84
+ A 10.0.10.85
+ A 10.0.10.86
+ A 10.0.10.87
+ A 10.0.10.88
+ A 10.0.10.89
+ A 10.0.10.90
+ A 10.0.10.91
+ A 10.0.10.92
+ A 10.0.10.93
+ A 10.0.10.94
+ A 10.0.10.95
+ A 10.0.10.96
+ A 10.0.10.97
+ A 10.0.10.98
+ A 10.0.10.99
+ A 10.0.10.100
+ A 10.0.10.101
+ A 10.0.10.102
+ A 10.0.10.103
+ A 10.0.10.104
+ A 10.0.10.105
+ A 10.0.10.106
+ A 10.0.10.107
+ A 10.0.10.108
+ A 10.0.10.109
+ A 10.0.10.110
+ A 10.0.10.111
+ A 10.0.10.112
+ A 10.0.10.113
+ A 10.0.10.114
+ A 10.0.10.115
+ A 10.0.10.116
+ A 10.0.10.117
+ A 10.0.10.118
+ A 10.0.10.119
+ A 10.0.10.120
+ A 10.0.10.121
+ A 10.0.10.122
+ A 10.0.10.123
+ A 10.0.10.124
+ A 10.0.10.125
+ A 10.0.10.126
+ A 10.0.10.127
+ A 10.0.10.128
+ A 10.0.10.129
+ A 10.0.10.130
+ A 10.0.10.131
+ A 10.0.10.132
+ A 10.0.10.133
+ A 10.0.10.134
+ A 10.0.10.135
+ A 10.0.10.136
+ A 10.0.10.137
+ A 10.0.10.138
+ A 10.0.10.139
+ A 10.0.10.140
+ A 10.0.10.141
+ A 10.0.10.142
+ A 10.0.10.143
+ A 10.0.10.144
+ A 10.0.10.145
+ A 10.0.10.146
+ A 10.0.10.147
+ A 10.0.10.148
+ A 10.0.10.149
+ A 10.0.10.150
+ A 10.0.10.151
+ A 10.0.10.152
+ A 10.0.10.153
+ A 10.0.10.154
+ A 10.0.10.155
+ A 10.0.10.156
+ A 10.0.10.157
+ A 10.0.10.158
+ A 10.0.10.159
+ A 10.0.10.160
+ A 10.0.10.161
+ A 10.0.10.162
+ A 10.0.10.163
+ A 10.0.10.164
+ A 10.0.10.165
+ A 10.0.10.166
+ A 10.0.10.167
+ A 10.0.10.168
+ A 10.0.10.169
+ A 10.0.10.170
+ A 10.0.10.171
+ A 10.0.10.172
+ A 10.0.10.173
+ A 10.0.10.174
+ A 10.0.10.175
+ A 10.0.10.176
+ A 10.0.10.177
+ A 10.0.10.178
+ A 10.0.10.179
+ A 10.0.10.180
+ A 10.0.10.181
+ A 10.0.10.182
+ A 10.0.10.183
+ A 10.0.10.184
+ A 10.0.10.185
+ A 10.0.10.186
+ A 10.0.10.187
+ A 10.0.10.188
+ A 10.0.10.189
+ A 10.0.10.190
+ A 10.0.10.191
+ A 10.0.10.192
+ A 10.0.10.193
+ A 10.0.10.194
+ A 10.0.10.195
+ A 10.0.10.196
+ A 10.0.10.197
+ A 10.0.10.198
+ A 10.0.10.199
+ A 10.0.10.200
+ A 10.0.10.201
+ A 10.0.10.202
+ A 10.0.10.203
+ A 10.0.10.204
+ A 10.0.10.205
+ A 10.0.10.206
+ A 10.0.10.207
+ A 10.0.10.208
+ A 10.0.10.209
+ A 10.0.10.210
+ A 10.0.10.211
+ A 10.0.10.212
+ A 10.0.10.213
+ A 10.0.10.214
+ A 10.0.10.215
+ A 10.0.10.216
+ A 10.0.10.217
+ A 10.0.10.218
+ A 10.0.10.219
+ A 10.0.10.220
+ A 10.0.10.221
+ A 10.0.10.222
+ A 10.0.10.223
+ A 10.0.10.224
+ A 10.0.10.225
+ A 10.0.10.226
+ A 10.0.10.227
+ A 10.0.10.228
+ A 10.0.10.229
+ A 10.0.10.230
+ A 10.0.10.231
+ A 10.0.10.232
+ A 10.0.10.233
+ A 10.0.10.234
+ A 10.0.10.235
+ A 10.0.10.236
+ A 10.0.10.237
+ A 10.0.10.238
+ A 10.0.10.239
+ A 10.0.10.240
+ A 10.0.10.241
+ A 10.0.10.242
+ A 10.0.10.243
+ A 10.0.10.244
+ A 10.0.10.245
+ A 10.0.10.246
+ A 10.0.10.247
+ A 10.0.10.248
+ A 10.0.10.249
+ A 10.0.10.250
+ A 10.0.10.251
+ A 10.0.10.252
+ A 10.0.10.253
+ A 10.0.10.254
+ A 10.0.10.255
+ A 10.0.11.0
+ A 10.0.11.1
+ A 10.0.11.2
+ A 10.0.11.3
+ A 10.0.11.4
+ A 10.0.11.5
+ A 10.0.11.6
+ A 10.0.11.7
+ A 10.0.11.8
+ A 10.0.11.9
+ A 10.0.11.10
+ A 10.0.11.11
+ A 10.0.11.12
+ A 10.0.11.13
+ A 10.0.11.14
+ A 10.0.11.15
+ A 10.0.11.16
+ A 10.0.11.17
+ A 10.0.11.18
+ A 10.0.11.19
+ A 10.0.11.20
+ A 10.0.11.21
+ A 10.0.11.22
+ A 10.0.11.23
+ A 10.0.11.24
+ A 10.0.11.25
+ A 10.0.11.26
+ A 10.0.11.27
+ A 10.0.11.28
+ A 10.0.11.29
+ A 10.0.11.30
+ A 10.0.11.31
+ A 10.0.11.32
+ A 10.0.11.33
+ A 10.0.11.34
+ A 10.0.11.35
+ A 10.0.11.36
+ A 10.0.11.37
+ A 10.0.11.38
+ A 10.0.11.39
+ A 10.0.11.40
+ A 10.0.11.41
+ A 10.0.11.42
+ A 10.0.11.43
+ A 10.0.11.44
+ A 10.0.11.45
+ A 10.0.11.46
+ A 10.0.11.47
+ A 10.0.11.48
+ A 10.0.11.49
+ A 10.0.11.50
+ A 10.0.11.51
+ A 10.0.11.52
+ A 10.0.11.53
+ A 10.0.11.54
+ A 10.0.11.55
+ A 10.0.11.56
+ A 10.0.11.57
+ A 10.0.11.58
+ A 10.0.11.59
+ A 10.0.11.60
+ A 10.0.11.61
+ A 10.0.11.62
+ A 10.0.11.63
+ A 10.0.11.64
+ A 10.0.11.65
+ A 10.0.11.66
+ A 10.0.11.67
+ A 10.0.11.68
+ A 10.0.11.69
+ A 10.0.11.70
+ A 10.0.11.71
+ A 10.0.11.72
+ A 10.0.11.73
+ A 10.0.11.74
+ A 10.0.11.75
+ A 10.0.11.76
+ A 10.0.11.77
+ A 10.0.11.78
+ A 10.0.11.79
+ A 10.0.11.80
+ A 10.0.11.81
+ A 10.0.11.82
+ A 10.0.11.83
+ A 10.0.11.84
+ A 10.0.11.85
+ A 10.0.11.86
+ A 10.0.11.87
+ A 10.0.11.88
+ A 10.0.11.89
+ A 10.0.11.90
+ A 10.0.11.91
+ A 10.0.11.92
+ A 10.0.11.93
+ A 10.0.11.94
+ A 10.0.11.95
+ A 10.0.11.96
+ A 10.0.11.97
+ A 10.0.11.98
+ A 10.0.11.99
+ A 10.0.11.100
+ A 10.0.11.101
+ A 10.0.11.102
+ A 10.0.11.103
+ A 10.0.11.104
+ A 10.0.11.105
+ A 10.0.11.106
+ A 10.0.11.107
+ A 10.0.11.108
+ A 10.0.11.109
+ A 10.0.11.110
+ A 10.0.11.111
+ A 10.0.11.112
+ A 10.0.11.113
+ A 10.0.11.114
+ A 10.0.11.115
+ A 10.0.11.116
+ A 10.0.11.117
+ A 10.0.11.118
+ A 10.0.11.119
+ A 10.0.11.120
+ A 10.0.11.121
+ A 10.0.11.122
+ A 10.0.11.123
+ A 10.0.11.124
+ A 10.0.11.125
+ A 10.0.11.126
+ A 10.0.11.127
+ A 10.0.11.128
+ A 10.0.11.129
+ A 10.0.11.130
+ A 10.0.11.131
+ A 10.0.11.132
+ A 10.0.11.133
+ A 10.0.11.134
+ A 10.0.11.135
+ A 10.0.11.136
+ A 10.0.11.137
+ A 10.0.11.138
+ A 10.0.11.139
+ A 10.0.11.140
+ A 10.0.11.141
+ A 10.0.11.142
+ A 10.0.11.143
+ A 10.0.11.144
+ A 10.0.11.145
+ A 10.0.11.146
+ A 10.0.11.147
+ A 10.0.11.148
+ A 10.0.11.149
+ A 10.0.11.150
+ A 10.0.11.151
+ A 10.0.11.152
+ A 10.0.11.153
+ A 10.0.11.154
+ A 10.0.11.155
+ A 10.0.11.156
+ A 10.0.11.157
+ A 10.0.11.158
+ A 10.0.11.159
+ A 10.0.11.160
+ A 10.0.11.161
+ A 10.0.11.162
+ A 10.0.11.163
+ A 10.0.11.164
+ A 10.0.11.165
+ A 10.0.11.166
+ A 10.0.11.167
+ A 10.0.11.168
+ A 10.0.11.169
+ A 10.0.11.170
+ A 10.0.11.171
+ A 10.0.11.172
+ A 10.0.11.173
+ A 10.0.11.174
+ A 10.0.11.175
+ A 10.0.11.176
+ A 10.0.11.177
+ A 10.0.11.178
+ A 10.0.11.179
+ A 10.0.11.180
+ A 10.0.11.181
+ A 10.0.11.182
+ A 10.0.11.183
+4000 A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+ A 10.0.3.232
+ A 10.0.3.233
+ A 10.0.3.234
+ A 10.0.3.235
+ A 10.0.3.236
+ A 10.0.3.237
+ A 10.0.3.238
+ A 10.0.3.239
+ A 10.0.3.240
+ A 10.0.3.241
+ A 10.0.3.242
+ A 10.0.3.243
+ A 10.0.3.244
+ A 10.0.3.245
+ A 10.0.3.246
+ A 10.0.3.247
+ A 10.0.3.248
+ A 10.0.3.249
+ A 10.0.3.250
+ A 10.0.3.251
+ A 10.0.3.252
+ A 10.0.3.253
+ A 10.0.3.254
+ A 10.0.3.255
+ A 10.0.4.0
+ A 10.0.4.1
+ A 10.0.4.2
+ A 10.0.4.3
+ A 10.0.4.4
+ A 10.0.4.5
+ A 10.0.4.6
+ A 10.0.4.7
+ A 10.0.4.8
+ A 10.0.4.9
+ A 10.0.4.10
+ A 10.0.4.11
+ A 10.0.4.12
+ A 10.0.4.13
+ A 10.0.4.14
+ A 10.0.4.15
+ A 10.0.4.16
+ A 10.0.4.17
+ A 10.0.4.18
+ A 10.0.4.19
+ A 10.0.4.20
+ A 10.0.4.21
+ A 10.0.4.22
+ A 10.0.4.23
+ A 10.0.4.24
+ A 10.0.4.25
+ A 10.0.4.26
+ A 10.0.4.27
+ A 10.0.4.28
+ A 10.0.4.29
+ A 10.0.4.30
+ A 10.0.4.31
+ A 10.0.4.32
+ A 10.0.4.33
+ A 10.0.4.34
+ A 10.0.4.35
+ A 10.0.4.36
+ A 10.0.4.37
+ A 10.0.4.38
+ A 10.0.4.39
+ A 10.0.4.40
+ A 10.0.4.41
+ A 10.0.4.42
+ A 10.0.4.43
+ A 10.0.4.44
+ A 10.0.4.45
+ A 10.0.4.46
+ A 10.0.4.47
+ A 10.0.4.48
+ A 10.0.4.49
+ A 10.0.4.50
+ A 10.0.4.51
+ A 10.0.4.52
+ A 10.0.4.53
+ A 10.0.4.54
+ A 10.0.4.55
+ A 10.0.4.56
+ A 10.0.4.57
+ A 10.0.4.58
+ A 10.0.4.59
+ A 10.0.4.60
+ A 10.0.4.61
+ A 10.0.4.62
+ A 10.0.4.63
+ A 10.0.4.64
+ A 10.0.4.65
+ A 10.0.4.66
+ A 10.0.4.67
+ A 10.0.4.68
+ A 10.0.4.69
+ A 10.0.4.70
+ A 10.0.4.71
+ A 10.0.4.72
+ A 10.0.4.73
+ A 10.0.4.74
+ A 10.0.4.75
+ A 10.0.4.76
+ A 10.0.4.77
+ A 10.0.4.78
+ A 10.0.4.79
+ A 10.0.4.80
+ A 10.0.4.81
+ A 10.0.4.82
+ A 10.0.4.83
+ A 10.0.4.84
+ A 10.0.4.85
+ A 10.0.4.86
+ A 10.0.4.87
+ A 10.0.4.88
+ A 10.0.4.89
+ A 10.0.4.90
+ A 10.0.4.91
+ A 10.0.4.92
+ A 10.0.4.93
+ A 10.0.4.94
+ A 10.0.4.95
+ A 10.0.4.96
+ A 10.0.4.97
+ A 10.0.4.98
+ A 10.0.4.99
+ A 10.0.4.100
+ A 10.0.4.101
+ A 10.0.4.102
+ A 10.0.4.103
+ A 10.0.4.104
+ A 10.0.4.105
+ A 10.0.4.106
+ A 10.0.4.107
+ A 10.0.4.108
+ A 10.0.4.109
+ A 10.0.4.110
+ A 10.0.4.111
+ A 10.0.4.112
+ A 10.0.4.113
+ A 10.0.4.114
+ A 10.0.4.115
+ A 10.0.4.116
+ A 10.0.4.117
+ A 10.0.4.118
+ A 10.0.4.119
+ A 10.0.4.120
+ A 10.0.4.121
+ A 10.0.4.122
+ A 10.0.4.123
+ A 10.0.4.124
+ A 10.0.4.125
+ A 10.0.4.126
+ A 10.0.4.127
+ A 10.0.4.128
+ A 10.0.4.129
+ A 10.0.4.130
+ A 10.0.4.131
+ A 10.0.4.132
+ A 10.0.4.133
+ A 10.0.4.134
+ A 10.0.4.135
+ A 10.0.4.136
+ A 10.0.4.137
+ A 10.0.4.138
+ A 10.0.4.139
+ A 10.0.4.140
+ A 10.0.4.141
+ A 10.0.4.142
+ A 10.0.4.143
+ A 10.0.4.144
+ A 10.0.4.145
+ A 10.0.4.146
+ A 10.0.4.147
+ A 10.0.4.148
+ A 10.0.4.149
+ A 10.0.4.150
+ A 10.0.4.151
+ A 10.0.4.152
+ A 10.0.4.153
+ A 10.0.4.154
+ A 10.0.4.155
+ A 10.0.4.156
+ A 10.0.4.157
+ A 10.0.4.158
+ A 10.0.4.159
+ A 10.0.4.160
+ A 10.0.4.161
+ A 10.0.4.162
+ A 10.0.4.163
+ A 10.0.4.164
+ A 10.0.4.165
+ A 10.0.4.166
+ A 10.0.4.167
+ A 10.0.4.168
+ A 10.0.4.169
+ A 10.0.4.170
+ A 10.0.4.171
+ A 10.0.4.172
+ A 10.0.4.173
+ A 10.0.4.174
+ A 10.0.4.175
+ A 10.0.4.176
+ A 10.0.4.177
+ A 10.0.4.178
+ A 10.0.4.179
+ A 10.0.4.180
+ A 10.0.4.181
+ A 10.0.4.182
+ A 10.0.4.183
+ A 10.0.4.184
+ A 10.0.4.185
+ A 10.0.4.186
+ A 10.0.4.187
+ A 10.0.4.188
+ A 10.0.4.189
+ A 10.0.4.190
+ A 10.0.4.191
+ A 10.0.4.192
+ A 10.0.4.193
+ A 10.0.4.194
+ A 10.0.4.195
+ A 10.0.4.196
+ A 10.0.4.197
+ A 10.0.4.198
+ A 10.0.4.199
+ A 10.0.4.200
+ A 10.0.4.201
+ A 10.0.4.202
+ A 10.0.4.203
+ A 10.0.4.204
+ A 10.0.4.205
+ A 10.0.4.206
+ A 10.0.4.207
+ A 10.0.4.208
+ A 10.0.4.209
+ A 10.0.4.210
+ A 10.0.4.211
+ A 10.0.4.212
+ A 10.0.4.213
+ A 10.0.4.214
+ A 10.0.4.215
+ A 10.0.4.216
+ A 10.0.4.217
+ A 10.0.4.218
+ A 10.0.4.219
+ A 10.0.4.220
+ A 10.0.4.221
+ A 10.0.4.222
+ A 10.0.4.223
+ A 10.0.4.224
+ A 10.0.4.225
+ A 10.0.4.226
+ A 10.0.4.227
+ A 10.0.4.228
+ A 10.0.4.229
+ A 10.0.4.230
+ A 10.0.4.231
+ A 10.0.4.232
+ A 10.0.4.233
+ A 10.0.4.234
+ A 10.0.4.235
+ A 10.0.4.236
+ A 10.0.4.237
+ A 10.0.4.238
+ A 10.0.4.239
+ A 10.0.4.240
+ A 10.0.4.241
+ A 10.0.4.242
+ A 10.0.4.243
+ A 10.0.4.244
+ A 10.0.4.245
+ A 10.0.4.246
+ A 10.0.4.247
+ A 10.0.4.248
+ A 10.0.4.249
+ A 10.0.4.250
+ A 10.0.4.251
+ A 10.0.4.252
+ A 10.0.4.253
+ A 10.0.4.254
+ A 10.0.4.255
+ A 10.0.5.0
+ A 10.0.5.1
+ A 10.0.5.2
+ A 10.0.5.3
+ A 10.0.5.4
+ A 10.0.5.5
+ A 10.0.5.6
+ A 10.0.5.7
+ A 10.0.5.8
+ A 10.0.5.9
+ A 10.0.5.10
+ A 10.0.5.11
+ A 10.0.5.12
+ A 10.0.5.13
+ A 10.0.5.14
+ A 10.0.5.15
+ A 10.0.5.16
+ A 10.0.5.17
+ A 10.0.5.18
+ A 10.0.5.19
+ A 10.0.5.20
+ A 10.0.5.21
+ A 10.0.5.22
+ A 10.0.5.23
+ A 10.0.5.24
+ A 10.0.5.25
+ A 10.0.5.26
+ A 10.0.5.27
+ A 10.0.5.28
+ A 10.0.5.29
+ A 10.0.5.30
+ A 10.0.5.31
+ A 10.0.5.32
+ A 10.0.5.33
+ A 10.0.5.34
+ A 10.0.5.35
+ A 10.0.5.36
+ A 10.0.5.37
+ A 10.0.5.38
+ A 10.0.5.39
+ A 10.0.5.40
+ A 10.0.5.41
+ A 10.0.5.42
+ A 10.0.5.43
+ A 10.0.5.44
+ A 10.0.5.45
+ A 10.0.5.46
+ A 10.0.5.47
+ A 10.0.5.48
+ A 10.0.5.49
+ A 10.0.5.50
+ A 10.0.5.51
+ A 10.0.5.52
+ A 10.0.5.53
+ A 10.0.5.54
+ A 10.0.5.55
+ A 10.0.5.56
+ A 10.0.5.57
+ A 10.0.5.58
+ A 10.0.5.59
+ A 10.0.5.60
+ A 10.0.5.61
+ A 10.0.5.62
+ A 10.0.5.63
+ A 10.0.5.64
+ A 10.0.5.65
+ A 10.0.5.66
+ A 10.0.5.67
+ A 10.0.5.68
+ A 10.0.5.69
+ A 10.0.5.70
+ A 10.0.5.71
+ A 10.0.5.72
+ A 10.0.5.73
+ A 10.0.5.74
+ A 10.0.5.75
+ A 10.0.5.76
+ A 10.0.5.77
+ A 10.0.5.78
+ A 10.0.5.79
+ A 10.0.5.80
+ A 10.0.5.81
+ A 10.0.5.82
+ A 10.0.5.83
+ A 10.0.5.84
+ A 10.0.5.85
+ A 10.0.5.86
+ A 10.0.5.87
+ A 10.0.5.88
+ A 10.0.5.89
+ A 10.0.5.90
+ A 10.0.5.91
+ A 10.0.5.92
+ A 10.0.5.93
+ A 10.0.5.94
+ A 10.0.5.95
+ A 10.0.5.96
+ A 10.0.5.97
+ A 10.0.5.98
+ A 10.0.5.99
+ A 10.0.5.100
+ A 10.0.5.101
+ A 10.0.5.102
+ A 10.0.5.103
+ A 10.0.5.104
+ A 10.0.5.105
+ A 10.0.5.106
+ A 10.0.5.107
+ A 10.0.5.108
+ A 10.0.5.109
+ A 10.0.5.110
+ A 10.0.5.111
+ A 10.0.5.112
+ A 10.0.5.113
+ A 10.0.5.114
+ A 10.0.5.115
+ A 10.0.5.116
+ A 10.0.5.117
+ A 10.0.5.118
+ A 10.0.5.119
+ A 10.0.5.120
+ A 10.0.5.121
+ A 10.0.5.122
+ A 10.0.5.123
+ A 10.0.5.124
+ A 10.0.5.125
+ A 10.0.5.126
+ A 10.0.5.127
+ A 10.0.5.128
+ A 10.0.5.129
+ A 10.0.5.130
+ A 10.0.5.131
+ A 10.0.5.132
+ A 10.0.5.133
+ A 10.0.5.134
+ A 10.0.5.135
+ A 10.0.5.136
+ A 10.0.5.137
+ A 10.0.5.138
+ A 10.0.5.139
+ A 10.0.5.140
+ A 10.0.5.141
+ A 10.0.5.142
+ A 10.0.5.143
+ A 10.0.5.144
+ A 10.0.5.145
+ A 10.0.5.146
+ A 10.0.5.147
+ A 10.0.5.148
+ A 10.0.5.149
+ A 10.0.5.150
+ A 10.0.5.151
+ A 10.0.5.152
+ A 10.0.5.153
+ A 10.0.5.154
+ A 10.0.5.155
+ A 10.0.5.156
+ A 10.0.5.157
+ A 10.0.5.158
+ A 10.0.5.159
+ A 10.0.5.160
+ A 10.0.5.161
+ A 10.0.5.162
+ A 10.0.5.163
+ A 10.0.5.164
+ A 10.0.5.165
+ A 10.0.5.166
+ A 10.0.5.167
+ A 10.0.5.168
+ A 10.0.5.169
+ A 10.0.5.170
+ A 10.0.5.171
+ A 10.0.5.172
+ A 10.0.5.173
+ A 10.0.5.174
+ A 10.0.5.175
+ A 10.0.5.176
+ A 10.0.5.177
+ A 10.0.5.178
+ A 10.0.5.179
+ A 10.0.5.180
+ A 10.0.5.181
+ A 10.0.5.182
+ A 10.0.5.183
+ A 10.0.5.184
+ A 10.0.5.185
+ A 10.0.5.186
+ A 10.0.5.187
+ A 10.0.5.188
+ A 10.0.5.189
+ A 10.0.5.190
+ A 10.0.5.191
+ A 10.0.5.192
+ A 10.0.5.193
+ A 10.0.5.194
+ A 10.0.5.195
+ A 10.0.5.196
+ A 10.0.5.197
+ A 10.0.5.198
+ A 10.0.5.199
+ A 10.0.5.200
+ A 10.0.5.201
+ A 10.0.5.202
+ A 10.0.5.203
+ A 10.0.5.204
+ A 10.0.5.205
+ A 10.0.5.206
+ A 10.0.5.207
+ A 10.0.5.208
+ A 10.0.5.209
+ A 10.0.5.210
+ A 10.0.5.211
+ A 10.0.5.212
+ A 10.0.5.213
+ A 10.0.5.214
+ A 10.0.5.215
+ A 10.0.5.216
+ A 10.0.5.217
+ A 10.0.5.218
+ A 10.0.5.219
+ A 10.0.5.220
+ A 10.0.5.221
+ A 10.0.5.222
+ A 10.0.5.223
+ A 10.0.5.224
+ A 10.0.5.225
+ A 10.0.5.226
+ A 10.0.5.227
+ A 10.0.5.228
+ A 10.0.5.229
+ A 10.0.5.230
+ A 10.0.5.231
+ A 10.0.5.232
+ A 10.0.5.233
+ A 10.0.5.234
+ A 10.0.5.235
+ A 10.0.5.236
+ A 10.0.5.237
+ A 10.0.5.238
+ A 10.0.5.239
+ A 10.0.5.240
+ A 10.0.5.241
+ A 10.0.5.242
+ A 10.0.5.243
+ A 10.0.5.244
+ A 10.0.5.245
+ A 10.0.5.246
+ A 10.0.5.247
+ A 10.0.5.248
+ A 10.0.5.249
+ A 10.0.5.250
+ A 10.0.5.251
+ A 10.0.5.252
+ A 10.0.5.253
+ A 10.0.5.254
+ A 10.0.5.255
+ A 10.0.6.0
+ A 10.0.6.1
+ A 10.0.6.2
+ A 10.0.6.3
+ A 10.0.6.4
+ A 10.0.6.5
+ A 10.0.6.6
+ A 10.0.6.7
+ A 10.0.6.8
+ A 10.0.6.9
+ A 10.0.6.10
+ A 10.0.6.11
+ A 10.0.6.12
+ A 10.0.6.13
+ A 10.0.6.14
+ A 10.0.6.15
+ A 10.0.6.16
+ A 10.0.6.17
+ A 10.0.6.18
+ A 10.0.6.19
+ A 10.0.6.20
+ A 10.0.6.21
+ A 10.0.6.22
+ A 10.0.6.23
+ A 10.0.6.24
+ A 10.0.6.25
+ A 10.0.6.26
+ A 10.0.6.27
+ A 10.0.6.28
+ A 10.0.6.29
+ A 10.0.6.30
+ A 10.0.6.31
+ A 10.0.6.32
+ A 10.0.6.33
+ A 10.0.6.34
+ A 10.0.6.35
+ A 10.0.6.36
+ A 10.0.6.37
+ A 10.0.6.38
+ A 10.0.6.39
+ A 10.0.6.40
+ A 10.0.6.41
+ A 10.0.6.42
+ A 10.0.6.43
+ A 10.0.6.44
+ A 10.0.6.45
+ A 10.0.6.46
+ A 10.0.6.47
+ A 10.0.6.48
+ A 10.0.6.49
+ A 10.0.6.50
+ A 10.0.6.51
+ A 10.0.6.52
+ A 10.0.6.53
+ A 10.0.6.54
+ A 10.0.6.55
+ A 10.0.6.56
+ A 10.0.6.57
+ A 10.0.6.58
+ A 10.0.6.59
+ A 10.0.6.60
+ A 10.0.6.61
+ A 10.0.6.62
+ A 10.0.6.63
+ A 10.0.6.64
+ A 10.0.6.65
+ A 10.0.6.66
+ A 10.0.6.67
+ A 10.0.6.68
+ A 10.0.6.69
+ A 10.0.6.70
+ A 10.0.6.71
+ A 10.0.6.72
+ A 10.0.6.73
+ A 10.0.6.74
+ A 10.0.6.75
+ A 10.0.6.76
+ A 10.0.6.77
+ A 10.0.6.78
+ A 10.0.6.79
+ A 10.0.6.80
+ A 10.0.6.81
+ A 10.0.6.82
+ A 10.0.6.83
+ A 10.0.6.84
+ A 10.0.6.85
+ A 10.0.6.86
+ A 10.0.6.87
+ A 10.0.6.88
+ A 10.0.6.89
+ A 10.0.6.90
+ A 10.0.6.91
+ A 10.0.6.92
+ A 10.0.6.93
+ A 10.0.6.94
+ A 10.0.6.95
+ A 10.0.6.96
+ A 10.0.6.97
+ A 10.0.6.98
+ A 10.0.6.99
+ A 10.0.6.100
+ A 10.0.6.101
+ A 10.0.6.102
+ A 10.0.6.103
+ A 10.0.6.104
+ A 10.0.6.105
+ A 10.0.6.106
+ A 10.0.6.107
+ A 10.0.6.108
+ A 10.0.6.109
+ A 10.0.6.110
+ A 10.0.6.111
+ A 10.0.6.112
+ A 10.0.6.113
+ A 10.0.6.114
+ A 10.0.6.115
+ A 10.0.6.116
+ A 10.0.6.117
+ A 10.0.6.118
+ A 10.0.6.119
+ A 10.0.6.120
+ A 10.0.6.121
+ A 10.0.6.122
+ A 10.0.6.123
+ A 10.0.6.124
+ A 10.0.6.125
+ A 10.0.6.126
+ A 10.0.6.127
+ A 10.0.6.128
+ A 10.0.6.129
+ A 10.0.6.130
+ A 10.0.6.131
+ A 10.0.6.132
+ A 10.0.6.133
+ A 10.0.6.134
+ A 10.0.6.135
+ A 10.0.6.136
+ A 10.0.6.137
+ A 10.0.6.138
+ A 10.0.6.139
+ A 10.0.6.140
+ A 10.0.6.141
+ A 10.0.6.142
+ A 10.0.6.143
+ A 10.0.6.144
+ A 10.0.6.145
+ A 10.0.6.146
+ A 10.0.6.147
+ A 10.0.6.148
+ A 10.0.6.149
+ A 10.0.6.150
+ A 10.0.6.151
+ A 10.0.6.152
+ A 10.0.6.153
+ A 10.0.6.154
+ A 10.0.6.155
+ A 10.0.6.156
+ A 10.0.6.157
+ A 10.0.6.158
+ A 10.0.6.159
+ A 10.0.6.160
+ A 10.0.6.161
+ A 10.0.6.162
+ A 10.0.6.163
+ A 10.0.6.164
+ A 10.0.6.165
+ A 10.0.6.166
+ A 10.0.6.167
+ A 10.0.6.168
+ A 10.0.6.169
+ A 10.0.6.170
+ A 10.0.6.171
+ A 10.0.6.172
+ A 10.0.6.173
+ A 10.0.6.174
+ A 10.0.6.175
+ A 10.0.6.176
+ A 10.0.6.177
+ A 10.0.6.178
+ A 10.0.6.179
+ A 10.0.6.180
+ A 10.0.6.181
+ A 10.0.6.182
+ A 10.0.6.183
+ A 10.0.6.184
+ A 10.0.6.185
+ A 10.0.6.186
+ A 10.0.6.187
+ A 10.0.6.188
+ A 10.0.6.189
+ A 10.0.6.190
+ A 10.0.6.191
+ A 10.0.6.192
+ A 10.0.6.193
+ A 10.0.6.194
+ A 10.0.6.195
+ A 10.0.6.196
+ A 10.0.6.197
+ A 10.0.6.198
+ A 10.0.6.199
+ A 10.0.6.200
+ A 10.0.6.201
+ A 10.0.6.202
+ A 10.0.6.203
+ A 10.0.6.204
+ A 10.0.6.205
+ A 10.0.6.206
+ A 10.0.6.207
+ A 10.0.6.208
+ A 10.0.6.209
+ A 10.0.6.210
+ A 10.0.6.211
+ A 10.0.6.212
+ A 10.0.6.213
+ A 10.0.6.214
+ A 10.0.6.215
+ A 10.0.6.216
+ A 10.0.6.217
+ A 10.0.6.218
+ A 10.0.6.219
+ A 10.0.6.220
+ A 10.0.6.221
+ A 10.0.6.222
+ A 10.0.6.223
+ A 10.0.6.224
+ A 10.0.6.225
+ A 10.0.6.226
+ A 10.0.6.227
+ A 10.0.6.228
+ A 10.0.6.229
+ A 10.0.6.230
+ A 10.0.6.231
+ A 10.0.6.232
+ A 10.0.6.233
+ A 10.0.6.234
+ A 10.0.6.235
+ A 10.0.6.236
+ A 10.0.6.237
+ A 10.0.6.238
+ A 10.0.6.239
+ A 10.0.6.240
+ A 10.0.6.241
+ A 10.0.6.242
+ A 10.0.6.243
+ A 10.0.6.244
+ A 10.0.6.245
+ A 10.0.6.246
+ A 10.0.6.247
+ A 10.0.6.248
+ A 10.0.6.249
+ A 10.0.6.250
+ A 10.0.6.251
+ A 10.0.6.252
+ A 10.0.6.253
+ A 10.0.6.254
+ A 10.0.6.255
+ A 10.0.7.0
+ A 10.0.7.1
+ A 10.0.7.2
+ A 10.0.7.3
+ A 10.0.7.4
+ A 10.0.7.5
+ A 10.0.7.6
+ A 10.0.7.7
+ A 10.0.7.8
+ A 10.0.7.9
+ A 10.0.7.10
+ A 10.0.7.11
+ A 10.0.7.12
+ A 10.0.7.13
+ A 10.0.7.14
+ A 10.0.7.15
+ A 10.0.7.16
+ A 10.0.7.17
+ A 10.0.7.18
+ A 10.0.7.19
+ A 10.0.7.20
+ A 10.0.7.21
+ A 10.0.7.22
+ A 10.0.7.23
+ A 10.0.7.24
+ A 10.0.7.25
+ A 10.0.7.26
+ A 10.0.7.27
+ A 10.0.7.28
+ A 10.0.7.29
+ A 10.0.7.30
+ A 10.0.7.31
+ A 10.0.7.32
+ A 10.0.7.33
+ A 10.0.7.34
+ A 10.0.7.35
+ A 10.0.7.36
+ A 10.0.7.37
+ A 10.0.7.38
+ A 10.0.7.39
+ A 10.0.7.40
+ A 10.0.7.41
+ A 10.0.7.42
+ A 10.0.7.43
+ A 10.0.7.44
+ A 10.0.7.45
+ A 10.0.7.46
+ A 10.0.7.47
+ A 10.0.7.48
+ A 10.0.7.49
+ A 10.0.7.50
+ A 10.0.7.51
+ A 10.0.7.52
+ A 10.0.7.53
+ A 10.0.7.54
+ A 10.0.7.55
+ A 10.0.7.56
+ A 10.0.7.57
+ A 10.0.7.58
+ A 10.0.7.59
+ A 10.0.7.60
+ A 10.0.7.61
+ A 10.0.7.62
+ A 10.0.7.63
+ A 10.0.7.64
+ A 10.0.7.65
+ A 10.0.7.66
+ A 10.0.7.67
+ A 10.0.7.68
+ A 10.0.7.69
+ A 10.0.7.70
+ A 10.0.7.71
+ A 10.0.7.72
+ A 10.0.7.73
+ A 10.0.7.74
+ A 10.0.7.75
+ A 10.0.7.76
+ A 10.0.7.77
+ A 10.0.7.78
+ A 10.0.7.79
+ A 10.0.7.80
+ A 10.0.7.81
+ A 10.0.7.82
+ A 10.0.7.83
+ A 10.0.7.84
+ A 10.0.7.85
+ A 10.0.7.86
+ A 10.0.7.87
+ A 10.0.7.88
+ A 10.0.7.89
+ A 10.0.7.90
+ A 10.0.7.91
+ A 10.0.7.92
+ A 10.0.7.93
+ A 10.0.7.94
+ A 10.0.7.95
+ A 10.0.7.96
+ A 10.0.7.97
+ A 10.0.7.98
+ A 10.0.7.99
+ A 10.0.7.100
+ A 10.0.7.101
+ A 10.0.7.102
+ A 10.0.7.103
+ A 10.0.7.104
+ A 10.0.7.105
+ A 10.0.7.106
+ A 10.0.7.107
+ A 10.0.7.108
+ A 10.0.7.109
+ A 10.0.7.110
+ A 10.0.7.111
+ A 10.0.7.112
+ A 10.0.7.113
+ A 10.0.7.114
+ A 10.0.7.115
+ A 10.0.7.116
+ A 10.0.7.117
+ A 10.0.7.118
+ A 10.0.7.119
+ A 10.0.7.120
+ A 10.0.7.121
+ A 10.0.7.122
+ A 10.0.7.123
+ A 10.0.7.124
+ A 10.0.7.125
+ A 10.0.7.126
+ A 10.0.7.127
+ A 10.0.7.128
+ A 10.0.7.129
+ A 10.0.7.130
+ A 10.0.7.131
+ A 10.0.7.132
+ A 10.0.7.133
+ A 10.0.7.134
+ A 10.0.7.135
+ A 10.0.7.136
+ A 10.0.7.137
+ A 10.0.7.138
+ A 10.0.7.139
+ A 10.0.7.140
+ A 10.0.7.141
+ A 10.0.7.142
+ A 10.0.7.143
+ A 10.0.7.144
+ A 10.0.7.145
+ A 10.0.7.146
+ A 10.0.7.147
+ A 10.0.7.148
+ A 10.0.7.149
+ A 10.0.7.150
+ A 10.0.7.151
+ A 10.0.7.152
+ A 10.0.7.153
+ A 10.0.7.154
+ A 10.0.7.155
+ A 10.0.7.156
+ A 10.0.7.157
+ A 10.0.7.158
+ A 10.0.7.159
+ A 10.0.7.160
+ A 10.0.7.161
+ A 10.0.7.162
+ A 10.0.7.163
+ A 10.0.7.164
+ A 10.0.7.165
+ A 10.0.7.166
+ A 10.0.7.167
+ A 10.0.7.168
+ A 10.0.7.169
+ A 10.0.7.170
+ A 10.0.7.171
+ A 10.0.7.172
+ A 10.0.7.173
+ A 10.0.7.174
+ A 10.0.7.175
+ A 10.0.7.176
+ A 10.0.7.177
+ A 10.0.7.178
+ A 10.0.7.179
+ A 10.0.7.180
+ A 10.0.7.181
+ A 10.0.7.182
+ A 10.0.7.183
+ A 10.0.7.184
+ A 10.0.7.185
+ A 10.0.7.186
+ A 10.0.7.187
+ A 10.0.7.188
+ A 10.0.7.189
+ A 10.0.7.190
+ A 10.0.7.191
+ A 10.0.7.192
+ A 10.0.7.193
+ A 10.0.7.194
+ A 10.0.7.195
+ A 10.0.7.196
+ A 10.0.7.197
+ A 10.0.7.198
+ A 10.0.7.199
+ A 10.0.7.200
+ A 10.0.7.201
+ A 10.0.7.202
+ A 10.0.7.203
+ A 10.0.7.204
+ A 10.0.7.205
+ A 10.0.7.206
+ A 10.0.7.207
+ A 10.0.7.208
+ A 10.0.7.209
+ A 10.0.7.210
+ A 10.0.7.211
+ A 10.0.7.212
+ A 10.0.7.213
+ A 10.0.7.214
+ A 10.0.7.215
+ A 10.0.7.216
+ A 10.0.7.217
+ A 10.0.7.218
+ A 10.0.7.219
+ A 10.0.7.220
+ A 10.0.7.221
+ A 10.0.7.222
+ A 10.0.7.223
+ A 10.0.7.224
+ A 10.0.7.225
+ A 10.0.7.226
+ A 10.0.7.227
+ A 10.0.7.228
+ A 10.0.7.229
+ A 10.0.7.230
+ A 10.0.7.231
+ A 10.0.7.232
+ A 10.0.7.233
+ A 10.0.7.234
+ A 10.0.7.235
+ A 10.0.7.236
+ A 10.0.7.237
+ A 10.0.7.238
+ A 10.0.7.239
+ A 10.0.7.240
+ A 10.0.7.241
+ A 10.0.7.242
+ A 10.0.7.243
+ A 10.0.7.244
+ A 10.0.7.245
+ A 10.0.7.246
+ A 10.0.7.247
+ A 10.0.7.248
+ A 10.0.7.249
+ A 10.0.7.250
+ A 10.0.7.251
+ A 10.0.7.252
+ A 10.0.7.253
+ A 10.0.7.254
+ A 10.0.7.255
+ A 10.0.8.0
+ A 10.0.8.1
+ A 10.0.8.2
+ A 10.0.8.3
+ A 10.0.8.4
+ A 10.0.8.5
+ A 10.0.8.6
+ A 10.0.8.7
+ A 10.0.8.8
+ A 10.0.8.9
+ A 10.0.8.10
+ A 10.0.8.11
+ A 10.0.8.12
+ A 10.0.8.13
+ A 10.0.8.14
+ A 10.0.8.15
+ A 10.0.8.16
+ A 10.0.8.17
+ A 10.0.8.18
+ A 10.0.8.19
+ A 10.0.8.20
+ A 10.0.8.21
+ A 10.0.8.22
+ A 10.0.8.23
+ A 10.0.8.24
+ A 10.0.8.25
+ A 10.0.8.26
+ A 10.0.8.27
+ A 10.0.8.28
+ A 10.0.8.29
+ A 10.0.8.30
+ A 10.0.8.31
+ A 10.0.8.32
+ A 10.0.8.33
+ A 10.0.8.34
+ A 10.0.8.35
+ A 10.0.8.36
+ A 10.0.8.37
+ A 10.0.8.38
+ A 10.0.8.39
+ A 10.0.8.40
+ A 10.0.8.41
+ A 10.0.8.42
+ A 10.0.8.43
+ A 10.0.8.44
+ A 10.0.8.45
+ A 10.0.8.46
+ A 10.0.8.47
+ A 10.0.8.48
+ A 10.0.8.49
+ A 10.0.8.50
+ A 10.0.8.51
+ A 10.0.8.52
+ A 10.0.8.53
+ A 10.0.8.54
+ A 10.0.8.55
+ A 10.0.8.56
+ A 10.0.8.57
+ A 10.0.8.58
+ A 10.0.8.59
+ A 10.0.8.60
+ A 10.0.8.61
+ A 10.0.8.62
+ A 10.0.8.63
+ A 10.0.8.64
+ A 10.0.8.65
+ A 10.0.8.66
+ A 10.0.8.67
+ A 10.0.8.68
+ A 10.0.8.69
+ A 10.0.8.70
+ A 10.0.8.71
+ A 10.0.8.72
+ A 10.0.8.73
+ A 10.0.8.74
+ A 10.0.8.75
+ A 10.0.8.76
+ A 10.0.8.77
+ A 10.0.8.78
+ A 10.0.8.79
+ A 10.0.8.80
+ A 10.0.8.81
+ A 10.0.8.82
+ A 10.0.8.83
+ A 10.0.8.84
+ A 10.0.8.85
+ A 10.0.8.86
+ A 10.0.8.87
+ A 10.0.8.88
+ A 10.0.8.89
+ A 10.0.8.90
+ A 10.0.8.91
+ A 10.0.8.92
+ A 10.0.8.93
+ A 10.0.8.94
+ A 10.0.8.95
+ A 10.0.8.96
+ A 10.0.8.97
+ A 10.0.8.98
+ A 10.0.8.99
+ A 10.0.8.100
+ A 10.0.8.101
+ A 10.0.8.102
+ A 10.0.8.103
+ A 10.0.8.104
+ A 10.0.8.105
+ A 10.0.8.106
+ A 10.0.8.107
+ A 10.0.8.108
+ A 10.0.8.109
+ A 10.0.8.110
+ A 10.0.8.111
+ A 10.0.8.112
+ A 10.0.8.113
+ A 10.0.8.114
+ A 10.0.8.115
+ A 10.0.8.116
+ A 10.0.8.117
+ A 10.0.8.118
+ A 10.0.8.119
+ A 10.0.8.120
+ A 10.0.8.121
+ A 10.0.8.122
+ A 10.0.8.123
+ A 10.0.8.124
+ A 10.0.8.125
+ A 10.0.8.126
+ A 10.0.8.127
+ A 10.0.8.128
+ A 10.0.8.129
+ A 10.0.8.130
+ A 10.0.8.131
+ A 10.0.8.132
+ A 10.0.8.133
+ A 10.0.8.134
+ A 10.0.8.135
+ A 10.0.8.136
+ A 10.0.8.137
+ A 10.0.8.138
+ A 10.0.8.139
+ A 10.0.8.140
+ A 10.0.8.141
+ A 10.0.8.142
+ A 10.0.8.143
+ A 10.0.8.144
+ A 10.0.8.145
+ A 10.0.8.146
+ A 10.0.8.147
+ A 10.0.8.148
+ A 10.0.8.149
+ A 10.0.8.150
+ A 10.0.8.151
+ A 10.0.8.152
+ A 10.0.8.153
+ A 10.0.8.154
+ A 10.0.8.155
+ A 10.0.8.156
+ A 10.0.8.157
+ A 10.0.8.158
+ A 10.0.8.159
+ A 10.0.8.160
+ A 10.0.8.161
+ A 10.0.8.162
+ A 10.0.8.163
+ A 10.0.8.164
+ A 10.0.8.165
+ A 10.0.8.166
+ A 10.0.8.167
+ A 10.0.8.168
+ A 10.0.8.169
+ A 10.0.8.170
+ A 10.0.8.171
+ A 10.0.8.172
+ A 10.0.8.173
+ A 10.0.8.174
+ A 10.0.8.175
+ A 10.0.8.176
+ A 10.0.8.177
+ A 10.0.8.178
+ A 10.0.8.179
+ A 10.0.8.180
+ A 10.0.8.181
+ A 10.0.8.182
+ A 10.0.8.183
+ A 10.0.8.184
+ A 10.0.8.185
+ A 10.0.8.186
+ A 10.0.8.187
+ A 10.0.8.188
+ A 10.0.8.189
+ A 10.0.8.190
+ A 10.0.8.191
+ A 10.0.8.192
+ A 10.0.8.193
+ A 10.0.8.194
+ A 10.0.8.195
+ A 10.0.8.196
+ A 10.0.8.197
+ A 10.0.8.198
+ A 10.0.8.199
+ A 10.0.8.200
+ A 10.0.8.201
+ A 10.0.8.202
+ A 10.0.8.203
+ A 10.0.8.204
+ A 10.0.8.205
+ A 10.0.8.206
+ A 10.0.8.207
+ A 10.0.8.208
+ A 10.0.8.209
+ A 10.0.8.210
+ A 10.0.8.211
+ A 10.0.8.212
+ A 10.0.8.213
+ A 10.0.8.214
+ A 10.0.8.215
+ A 10.0.8.216
+ A 10.0.8.217
+ A 10.0.8.218
+ A 10.0.8.219
+ A 10.0.8.220
+ A 10.0.8.221
+ A 10.0.8.222
+ A 10.0.8.223
+ A 10.0.8.224
+ A 10.0.8.225
+ A 10.0.8.226
+ A 10.0.8.227
+ A 10.0.8.228
+ A 10.0.8.229
+ A 10.0.8.230
+ A 10.0.8.231
+ A 10.0.8.232
+ A 10.0.8.233
+ A 10.0.8.234
+ A 10.0.8.235
+ A 10.0.8.236
+ A 10.0.8.237
+ A 10.0.8.238
+ A 10.0.8.239
+ A 10.0.8.240
+ A 10.0.8.241
+ A 10.0.8.242
+ A 10.0.8.243
+ A 10.0.8.244
+ A 10.0.8.245
+ A 10.0.8.246
+ A 10.0.8.247
+ A 10.0.8.248
+ A 10.0.8.249
+ A 10.0.8.250
+ A 10.0.8.251
+ A 10.0.8.252
+ A 10.0.8.253
+ A 10.0.8.254
+ A 10.0.8.255
+ A 10.0.9.0
+ A 10.0.9.1
+ A 10.0.9.2
+ A 10.0.9.3
+ A 10.0.9.4
+ A 10.0.9.5
+ A 10.0.9.6
+ A 10.0.9.7
+ A 10.0.9.8
+ A 10.0.9.9
+ A 10.0.9.10
+ A 10.0.9.11
+ A 10.0.9.12
+ A 10.0.9.13
+ A 10.0.9.14
+ A 10.0.9.15
+ A 10.0.9.16
+ A 10.0.9.17
+ A 10.0.9.18
+ A 10.0.9.19
+ A 10.0.9.20
+ A 10.0.9.21
+ A 10.0.9.22
+ A 10.0.9.23
+ A 10.0.9.24
+ A 10.0.9.25
+ A 10.0.9.26
+ A 10.0.9.27
+ A 10.0.9.28
+ A 10.0.9.29
+ A 10.0.9.30
+ A 10.0.9.31
+ A 10.0.9.32
+ A 10.0.9.33
+ A 10.0.9.34
+ A 10.0.9.35
+ A 10.0.9.36
+ A 10.0.9.37
+ A 10.0.9.38
+ A 10.0.9.39
+ A 10.0.9.40
+ A 10.0.9.41
+ A 10.0.9.42
+ A 10.0.9.43
+ A 10.0.9.44
+ A 10.0.9.45
+ A 10.0.9.46
+ A 10.0.9.47
+ A 10.0.9.48
+ A 10.0.9.49
+ A 10.0.9.50
+ A 10.0.9.51
+ A 10.0.9.52
+ A 10.0.9.53
+ A 10.0.9.54
+ A 10.0.9.55
+ A 10.0.9.56
+ A 10.0.9.57
+ A 10.0.9.58
+ A 10.0.9.59
+ A 10.0.9.60
+ A 10.0.9.61
+ A 10.0.9.62
+ A 10.0.9.63
+ A 10.0.9.64
+ A 10.0.9.65
+ A 10.0.9.66
+ A 10.0.9.67
+ A 10.0.9.68
+ A 10.0.9.69
+ A 10.0.9.70
+ A 10.0.9.71
+ A 10.0.9.72
+ A 10.0.9.73
+ A 10.0.9.74
+ A 10.0.9.75
+ A 10.0.9.76
+ A 10.0.9.77
+ A 10.0.9.78
+ A 10.0.9.79
+ A 10.0.9.80
+ A 10.0.9.81
+ A 10.0.9.82
+ A 10.0.9.83
+ A 10.0.9.84
+ A 10.0.9.85
+ A 10.0.9.86
+ A 10.0.9.87
+ A 10.0.9.88
+ A 10.0.9.89
+ A 10.0.9.90
+ A 10.0.9.91
+ A 10.0.9.92
+ A 10.0.9.93
+ A 10.0.9.94
+ A 10.0.9.95
+ A 10.0.9.96
+ A 10.0.9.97
+ A 10.0.9.98
+ A 10.0.9.99
+ A 10.0.9.100
+ A 10.0.9.101
+ A 10.0.9.102
+ A 10.0.9.103
+ A 10.0.9.104
+ A 10.0.9.105
+ A 10.0.9.106
+ A 10.0.9.107
+ A 10.0.9.108
+ A 10.0.9.109
+ A 10.0.9.110
+ A 10.0.9.111
+ A 10.0.9.112
+ A 10.0.9.113
+ A 10.0.9.114
+ A 10.0.9.115
+ A 10.0.9.116
+ A 10.0.9.117
+ A 10.0.9.118
+ A 10.0.9.119
+ A 10.0.9.120
+ A 10.0.9.121
+ A 10.0.9.122
+ A 10.0.9.123
+ A 10.0.9.124
+ A 10.0.9.125
+ A 10.0.9.126
+ A 10.0.9.127
+ A 10.0.9.128
+ A 10.0.9.129
+ A 10.0.9.130
+ A 10.0.9.131
+ A 10.0.9.132
+ A 10.0.9.133
+ A 10.0.9.134
+ A 10.0.9.135
+ A 10.0.9.136
+ A 10.0.9.137
+ A 10.0.9.138
+ A 10.0.9.139
+ A 10.0.9.140
+ A 10.0.9.141
+ A 10.0.9.142
+ A 10.0.9.143
+ A 10.0.9.144
+ A 10.0.9.145
+ A 10.0.9.146
+ A 10.0.9.147
+ A 10.0.9.148
+ A 10.0.9.149
+ A 10.0.9.150
+ A 10.0.9.151
+ A 10.0.9.152
+ A 10.0.9.153
+ A 10.0.9.154
+ A 10.0.9.155
+ A 10.0.9.156
+ A 10.0.9.157
+ A 10.0.9.158
+ A 10.0.9.159
+ A 10.0.9.160
+ A 10.0.9.161
+ A 10.0.9.162
+ A 10.0.9.163
+ A 10.0.9.164
+ A 10.0.9.165
+ A 10.0.9.166
+ A 10.0.9.167
+ A 10.0.9.168
+ A 10.0.9.169
+ A 10.0.9.170
+ A 10.0.9.171
+ A 10.0.9.172
+ A 10.0.9.173
+ A 10.0.9.174
+ A 10.0.9.175
+ A 10.0.9.176
+ A 10.0.9.177
+ A 10.0.9.178
+ A 10.0.9.179
+ A 10.0.9.180
+ A 10.0.9.181
+ A 10.0.9.182
+ A 10.0.9.183
+ A 10.0.9.184
+ A 10.0.9.185
+ A 10.0.9.186
+ A 10.0.9.187
+ A 10.0.9.188
+ A 10.0.9.189
+ A 10.0.9.190
+ A 10.0.9.191
+ A 10.0.9.192
+ A 10.0.9.193
+ A 10.0.9.194
+ A 10.0.9.195
+ A 10.0.9.196
+ A 10.0.9.197
+ A 10.0.9.198
+ A 10.0.9.199
+ A 10.0.9.200
+ A 10.0.9.201
+ A 10.0.9.202
+ A 10.0.9.203
+ A 10.0.9.204
+ A 10.0.9.205
+ A 10.0.9.206
+ A 10.0.9.207
+ A 10.0.9.208
+ A 10.0.9.209
+ A 10.0.9.210
+ A 10.0.9.211
+ A 10.0.9.212
+ A 10.0.9.213
+ A 10.0.9.214
+ A 10.0.9.215
+ A 10.0.9.216
+ A 10.0.9.217
+ A 10.0.9.218
+ A 10.0.9.219
+ A 10.0.9.220
+ A 10.0.9.221
+ A 10.0.9.222
+ A 10.0.9.223
+ A 10.0.9.224
+ A 10.0.9.225
+ A 10.0.9.226
+ A 10.0.9.227
+ A 10.0.9.228
+ A 10.0.9.229
+ A 10.0.9.230
+ A 10.0.9.231
+ A 10.0.9.232
+ A 10.0.9.233
+ A 10.0.9.234
+ A 10.0.9.235
+ A 10.0.9.236
+ A 10.0.9.237
+ A 10.0.9.238
+ A 10.0.9.239
+ A 10.0.9.240
+ A 10.0.9.241
+ A 10.0.9.242
+ A 10.0.9.243
+ A 10.0.9.244
+ A 10.0.9.245
+ A 10.0.9.246
+ A 10.0.9.247
+ A 10.0.9.248
+ A 10.0.9.249
+ A 10.0.9.250
+ A 10.0.9.251
+ A 10.0.9.252
+ A 10.0.9.253
+ A 10.0.9.254
+ A 10.0.9.255
+ A 10.0.10.0
+ A 10.0.10.1
+ A 10.0.10.2
+ A 10.0.10.3
+ A 10.0.10.4
+ A 10.0.10.5
+ A 10.0.10.6
+ A 10.0.10.7
+ A 10.0.10.8
+ A 10.0.10.9
+ A 10.0.10.10
+ A 10.0.10.11
+ A 10.0.10.12
+ A 10.0.10.13
+ A 10.0.10.14
+ A 10.0.10.15
+ A 10.0.10.16
+ A 10.0.10.17
+ A 10.0.10.18
+ A 10.0.10.19
+ A 10.0.10.20
+ A 10.0.10.21
+ A 10.0.10.22
+ A 10.0.10.23
+ A 10.0.10.24
+ A 10.0.10.25
+ A 10.0.10.26
+ A 10.0.10.27
+ A 10.0.10.28
+ A 10.0.10.29
+ A 10.0.10.30
+ A 10.0.10.31
+ A 10.0.10.32
+ A 10.0.10.33
+ A 10.0.10.34
+ A 10.0.10.35
+ A 10.0.10.36
+ A 10.0.10.37
+ A 10.0.10.38
+ A 10.0.10.39
+ A 10.0.10.40
+ A 10.0.10.41
+ A 10.0.10.42
+ A 10.0.10.43
+ A 10.0.10.44
+ A 10.0.10.45
+ A 10.0.10.46
+ A 10.0.10.47
+ A 10.0.10.48
+ A 10.0.10.49
+ A 10.0.10.50
+ A 10.0.10.51
+ A 10.0.10.52
+ A 10.0.10.53
+ A 10.0.10.54
+ A 10.0.10.55
+ A 10.0.10.56
+ A 10.0.10.57
+ A 10.0.10.58
+ A 10.0.10.59
+ A 10.0.10.60
+ A 10.0.10.61
+ A 10.0.10.62
+ A 10.0.10.63
+ A 10.0.10.64
+ A 10.0.10.65
+ A 10.0.10.66
+ A 10.0.10.67
+ A 10.0.10.68
+ A 10.0.10.69
+ A 10.0.10.70
+ A 10.0.10.71
+ A 10.0.10.72
+ A 10.0.10.73
+ A 10.0.10.74
+ A 10.0.10.75
+ A 10.0.10.76
+ A 10.0.10.77
+ A 10.0.10.78
+ A 10.0.10.79
+ A 10.0.10.80
+ A 10.0.10.81
+ A 10.0.10.82
+ A 10.0.10.83
+ A 10.0.10.84
+ A 10.0.10.85
+ A 10.0.10.86
+ A 10.0.10.87
+ A 10.0.10.88
+ A 10.0.10.89
+ A 10.0.10.90
+ A 10.0.10.91
+ A 10.0.10.92
+ A 10.0.10.93
+ A 10.0.10.94
+ A 10.0.10.95
+ A 10.0.10.96
+ A 10.0.10.97
+ A 10.0.10.98
+ A 10.0.10.99
+ A 10.0.10.100
+ A 10.0.10.101
+ A 10.0.10.102
+ A 10.0.10.103
+ A 10.0.10.104
+ A 10.0.10.105
+ A 10.0.10.106
+ A 10.0.10.107
+ A 10.0.10.108
+ A 10.0.10.109
+ A 10.0.10.110
+ A 10.0.10.111
+ A 10.0.10.112
+ A 10.0.10.113
+ A 10.0.10.114
+ A 10.0.10.115
+ A 10.0.10.116
+ A 10.0.10.117
+ A 10.0.10.118
+ A 10.0.10.119
+ A 10.0.10.120
+ A 10.0.10.121
+ A 10.0.10.122
+ A 10.0.10.123
+ A 10.0.10.124
+ A 10.0.10.125
+ A 10.0.10.126
+ A 10.0.10.127
+ A 10.0.10.128
+ A 10.0.10.129
+ A 10.0.10.130
+ A 10.0.10.131
+ A 10.0.10.132
+ A 10.0.10.133
+ A 10.0.10.134
+ A 10.0.10.135
+ A 10.0.10.136
+ A 10.0.10.137
+ A 10.0.10.138
+ A 10.0.10.139
+ A 10.0.10.140
+ A 10.0.10.141
+ A 10.0.10.142
+ A 10.0.10.143
+ A 10.0.10.144
+ A 10.0.10.145
+ A 10.0.10.146
+ A 10.0.10.147
+ A 10.0.10.148
+ A 10.0.10.149
+ A 10.0.10.150
+ A 10.0.10.151
+ A 10.0.10.152
+ A 10.0.10.153
+ A 10.0.10.154
+ A 10.0.10.155
+ A 10.0.10.156
+ A 10.0.10.157
+ A 10.0.10.158
+ A 10.0.10.159
+ A 10.0.10.160
+ A 10.0.10.161
+ A 10.0.10.162
+ A 10.0.10.163
+ A 10.0.10.164
+ A 10.0.10.165
+ A 10.0.10.166
+ A 10.0.10.167
+ A 10.0.10.168
+ A 10.0.10.169
+ A 10.0.10.170
+ A 10.0.10.171
+ A 10.0.10.172
+ A 10.0.10.173
+ A 10.0.10.174
+ A 10.0.10.175
+ A 10.0.10.176
+ A 10.0.10.177
+ A 10.0.10.178
+ A 10.0.10.179
+ A 10.0.10.180
+ A 10.0.10.181
+ A 10.0.10.182
+ A 10.0.10.183
+ A 10.0.10.184
+ A 10.0.10.185
+ A 10.0.10.186
+ A 10.0.10.187
+ A 10.0.10.188
+ A 10.0.10.189
+ A 10.0.10.190
+ A 10.0.10.191
+ A 10.0.10.192
+ A 10.0.10.193
+ A 10.0.10.194
+ A 10.0.10.195
+ A 10.0.10.196
+ A 10.0.10.197
+ A 10.0.10.198
+ A 10.0.10.199
+ A 10.0.10.200
+ A 10.0.10.201
+ A 10.0.10.202
+ A 10.0.10.203
+ A 10.0.10.204
+ A 10.0.10.205
+ A 10.0.10.206
+ A 10.0.10.207
+ A 10.0.10.208
+ A 10.0.10.209
+ A 10.0.10.210
+ A 10.0.10.211
+ A 10.0.10.212
+ A 10.0.10.213
+ A 10.0.10.214
+ A 10.0.10.215
+ A 10.0.10.216
+ A 10.0.10.217
+ A 10.0.10.218
+ A 10.0.10.219
+ A 10.0.10.220
+ A 10.0.10.221
+ A 10.0.10.222
+ A 10.0.10.223
+ A 10.0.10.224
+ A 10.0.10.225
+ A 10.0.10.226
+ A 10.0.10.227
+ A 10.0.10.228
+ A 10.0.10.229
+ A 10.0.10.230
+ A 10.0.10.231
+ A 10.0.10.232
+ A 10.0.10.233
+ A 10.0.10.234
+ A 10.0.10.235
+ A 10.0.10.236
+ A 10.0.10.237
+ A 10.0.10.238
+ A 10.0.10.239
+ A 10.0.10.240
+ A 10.0.10.241
+ A 10.0.10.242
+ A 10.0.10.243
+ A 10.0.10.244
+ A 10.0.10.245
+ A 10.0.10.246
+ A 10.0.10.247
+ A 10.0.10.248
+ A 10.0.10.249
+ A 10.0.10.250
+ A 10.0.10.251
+ A 10.0.10.252
+ A 10.0.10.253
+ A 10.0.10.254
+ A 10.0.10.255
+ A 10.0.11.0
+ A 10.0.11.1
+ A 10.0.11.2
+ A 10.0.11.3
+ A 10.0.11.4
+ A 10.0.11.5
+ A 10.0.11.6
+ A 10.0.11.7
+ A 10.0.11.8
+ A 10.0.11.9
+ A 10.0.11.10
+ A 10.0.11.11
+ A 10.0.11.12
+ A 10.0.11.13
+ A 10.0.11.14
+ A 10.0.11.15
+ A 10.0.11.16
+ A 10.0.11.17
+ A 10.0.11.18
+ A 10.0.11.19
+ A 10.0.11.20
+ A 10.0.11.21
+ A 10.0.11.22
+ A 10.0.11.23
+ A 10.0.11.24
+ A 10.0.11.25
+ A 10.0.11.26
+ A 10.0.11.27
+ A 10.0.11.28
+ A 10.0.11.29
+ A 10.0.11.30
+ A 10.0.11.31
+ A 10.0.11.32
+ A 10.0.11.33
+ A 10.0.11.34
+ A 10.0.11.35
+ A 10.0.11.36
+ A 10.0.11.37
+ A 10.0.11.38
+ A 10.0.11.39
+ A 10.0.11.40
+ A 10.0.11.41
+ A 10.0.11.42
+ A 10.0.11.43
+ A 10.0.11.44
+ A 10.0.11.45
+ A 10.0.11.46
+ A 10.0.11.47
+ A 10.0.11.48
+ A 10.0.11.49
+ A 10.0.11.50
+ A 10.0.11.51
+ A 10.0.11.52
+ A 10.0.11.53
+ A 10.0.11.54
+ A 10.0.11.55
+ A 10.0.11.56
+ A 10.0.11.57
+ A 10.0.11.58
+ A 10.0.11.59
+ A 10.0.11.60
+ A 10.0.11.61
+ A 10.0.11.62
+ A 10.0.11.63
+ A 10.0.11.64
+ A 10.0.11.65
+ A 10.0.11.66
+ A 10.0.11.67
+ A 10.0.11.68
+ A 10.0.11.69
+ A 10.0.11.70
+ A 10.0.11.71
+ A 10.0.11.72
+ A 10.0.11.73
+ A 10.0.11.74
+ A 10.0.11.75
+ A 10.0.11.76
+ A 10.0.11.77
+ A 10.0.11.78
+ A 10.0.11.79
+ A 10.0.11.80
+ A 10.0.11.81
+ A 10.0.11.82
+ A 10.0.11.83
+ A 10.0.11.84
+ A 10.0.11.85
+ A 10.0.11.86
+ A 10.0.11.87
+ A 10.0.11.88
+ A 10.0.11.89
+ A 10.0.11.90
+ A 10.0.11.91
+ A 10.0.11.92
+ A 10.0.11.93
+ A 10.0.11.94
+ A 10.0.11.95
+ A 10.0.11.96
+ A 10.0.11.97
+ A 10.0.11.98
+ A 10.0.11.99
+ A 10.0.11.100
+ A 10.0.11.101
+ A 10.0.11.102
+ A 10.0.11.103
+ A 10.0.11.104
+ A 10.0.11.105
+ A 10.0.11.106
+ A 10.0.11.107
+ A 10.0.11.108
+ A 10.0.11.109
+ A 10.0.11.110
+ A 10.0.11.111
+ A 10.0.11.112
+ A 10.0.11.113
+ A 10.0.11.114
+ A 10.0.11.115
+ A 10.0.11.116
+ A 10.0.11.117
+ A 10.0.11.118
+ A 10.0.11.119
+ A 10.0.11.120
+ A 10.0.11.121
+ A 10.0.11.122
+ A 10.0.11.123
+ A 10.0.11.124
+ A 10.0.11.125
+ A 10.0.11.126
+ A 10.0.11.127
+ A 10.0.11.128
+ A 10.0.11.129
+ A 10.0.11.130
+ A 10.0.11.131
+ A 10.0.11.132
+ A 10.0.11.133
+ A 10.0.11.134
+ A 10.0.11.135
+ A 10.0.11.136
+ A 10.0.11.137
+ A 10.0.11.138
+ A 10.0.11.139
+ A 10.0.11.140
+ A 10.0.11.141
+ A 10.0.11.142
+ A 10.0.11.143
+ A 10.0.11.144
+ A 10.0.11.145
+ A 10.0.11.146
+ A 10.0.11.147
+ A 10.0.11.148
+ A 10.0.11.149
+ A 10.0.11.150
+ A 10.0.11.151
+ A 10.0.11.152
+ A 10.0.11.153
+ A 10.0.11.154
+ A 10.0.11.155
+ A 10.0.11.156
+ A 10.0.11.157
+ A 10.0.11.158
+ A 10.0.11.159
+ A 10.0.11.160
+ A 10.0.11.161
+ A 10.0.11.162
+ A 10.0.11.163
+ A 10.0.11.164
+ A 10.0.11.165
+ A 10.0.11.166
+ A 10.0.11.167
+ A 10.0.11.168
+ A 10.0.11.169
+ A 10.0.11.170
+ A 10.0.11.171
+ A 10.0.11.172
+ A 10.0.11.173
+ A 10.0.11.174
+ A 10.0.11.175
+ A 10.0.11.176
+ A 10.0.11.177
+ A 10.0.11.178
+ A 10.0.11.179
+ A 10.0.11.180
+ A 10.0.11.181
+ A 10.0.11.182
+ A 10.0.11.183
+ A 10.0.11.184
+ A 10.0.11.185
+ A 10.0.11.186
+ A 10.0.11.187
+ A 10.0.11.188
+ A 10.0.11.189
+ A 10.0.11.190
+ A 10.0.11.191
+ A 10.0.11.192
+ A 10.0.11.193
+ A 10.0.11.194
+ A 10.0.11.195
+ A 10.0.11.196
+ A 10.0.11.197
+ A 10.0.11.198
+ A 10.0.11.199
+ A 10.0.11.200
+ A 10.0.11.201
+ A 10.0.11.202
+ A 10.0.11.203
+ A 10.0.11.204
+ A 10.0.11.205
+ A 10.0.11.206
+ A 10.0.11.207
+ A 10.0.11.208
+ A 10.0.11.209
+ A 10.0.11.210
+ A 10.0.11.211
+ A 10.0.11.212
+ A 10.0.11.213
+ A 10.0.11.214
+ A 10.0.11.215
+ A 10.0.11.216
+ A 10.0.11.217
+ A 10.0.11.218
+ A 10.0.11.219
+ A 10.0.11.220
+ A 10.0.11.221
+ A 10.0.11.222
+ A 10.0.11.223
+ A 10.0.11.224
+ A 10.0.11.225
+ A 10.0.11.226
+ A 10.0.11.227
+ A 10.0.11.228
+ A 10.0.11.229
+ A 10.0.11.230
+ A 10.0.11.231
+ A 10.0.11.232
+ A 10.0.11.233
+ A 10.0.11.234
+ A 10.0.11.235
+ A 10.0.11.236
+ A 10.0.11.237
+ A 10.0.11.238
+ A 10.0.11.239
+ A 10.0.11.240
+ A 10.0.11.241
+ A 10.0.11.242
+ A 10.0.11.243
+ A 10.0.11.244
+ A 10.0.11.245
+ A 10.0.11.246
+ A 10.0.11.247
+ A 10.0.11.248
+ A 10.0.11.249
+ A 10.0.11.250
+ A 10.0.11.251
+ A 10.0.11.252
+ A 10.0.11.253
+ A 10.0.11.254
+ A 10.0.11.255
+ A 10.0.12.0
+ A 10.0.12.1
+ A 10.0.12.2
+ A 10.0.12.3
+ A 10.0.12.4
+ A 10.0.12.5
+ A 10.0.12.6
+ A 10.0.12.7
+ A 10.0.12.8
+ A 10.0.12.9
+ A 10.0.12.10
+ A 10.0.12.11
+ A 10.0.12.12
+ A 10.0.12.13
+ A 10.0.12.14
+ A 10.0.12.15
+ A 10.0.12.16
+ A 10.0.12.17
+ A 10.0.12.18
+ A 10.0.12.19
+ A 10.0.12.20
+ A 10.0.12.21
+ A 10.0.12.22
+ A 10.0.12.23
+ A 10.0.12.24
+ A 10.0.12.25
+ A 10.0.12.26
+ A 10.0.12.27
+ A 10.0.12.28
+ A 10.0.12.29
+ A 10.0.12.30
+ A 10.0.12.31
+ A 10.0.12.32
+ A 10.0.12.33
+ A 10.0.12.34
+ A 10.0.12.35
+ A 10.0.12.36
+ A 10.0.12.37
+ A 10.0.12.38
+ A 10.0.12.39
+ A 10.0.12.40
+ A 10.0.12.41
+ A 10.0.12.42
+ A 10.0.12.43
+ A 10.0.12.44
+ A 10.0.12.45
+ A 10.0.12.46
+ A 10.0.12.47
+ A 10.0.12.48
+ A 10.0.12.49
+ A 10.0.12.50
+ A 10.0.12.51
+ A 10.0.12.52
+ A 10.0.12.53
+ A 10.0.12.54
+ A 10.0.12.55
+ A 10.0.12.56
+ A 10.0.12.57
+ A 10.0.12.58
+ A 10.0.12.59
+ A 10.0.12.60
+ A 10.0.12.61
+ A 10.0.12.62
+ A 10.0.12.63
+ A 10.0.12.64
+ A 10.0.12.65
+ A 10.0.12.66
+ A 10.0.12.67
+ A 10.0.12.68
+ A 10.0.12.69
+ A 10.0.12.70
+ A 10.0.12.71
+ A 10.0.12.72
+ A 10.0.12.73
+ A 10.0.12.74
+ A 10.0.12.75
+ A 10.0.12.76
+ A 10.0.12.77
+ A 10.0.12.78
+ A 10.0.12.79
+ A 10.0.12.80
+ A 10.0.12.81
+ A 10.0.12.82
+ A 10.0.12.83
+ A 10.0.12.84
+ A 10.0.12.85
+ A 10.0.12.86
+ A 10.0.12.87
+ A 10.0.12.88
+ A 10.0.12.89
+ A 10.0.12.90
+ A 10.0.12.91
+ A 10.0.12.92
+ A 10.0.12.93
+ A 10.0.12.94
+ A 10.0.12.95
+ A 10.0.12.96
+ A 10.0.12.97
+ A 10.0.12.98
+ A 10.0.12.99
+ A 10.0.12.100
+ A 10.0.12.101
+ A 10.0.12.102
+ A 10.0.12.103
+ A 10.0.12.104
+ A 10.0.12.105
+ A 10.0.12.106
+ A 10.0.12.107
+ A 10.0.12.108
+ A 10.0.12.109
+ A 10.0.12.110
+ A 10.0.12.111
+ A 10.0.12.112
+ A 10.0.12.113
+ A 10.0.12.114
+ A 10.0.12.115
+ A 10.0.12.116
+ A 10.0.12.117
+ A 10.0.12.118
+ A 10.0.12.119
+ A 10.0.12.120
+ A 10.0.12.121
+ A 10.0.12.122
+ A 10.0.12.123
+ A 10.0.12.124
+ A 10.0.12.125
+ A 10.0.12.126
+ A 10.0.12.127
+ A 10.0.12.128
+ A 10.0.12.129
+ A 10.0.12.130
+ A 10.0.12.131
+ A 10.0.12.132
+ A 10.0.12.133
+ A 10.0.12.134
+ A 10.0.12.135
+ A 10.0.12.136
+ A 10.0.12.137
+ A 10.0.12.138
+ A 10.0.12.139
+ A 10.0.12.140
+ A 10.0.12.141
+ A 10.0.12.142
+ A 10.0.12.143
+ A 10.0.12.144
+ A 10.0.12.145
+ A 10.0.12.146
+ A 10.0.12.147
+ A 10.0.12.148
+ A 10.0.12.149
+ A 10.0.12.150
+ A 10.0.12.151
+ A 10.0.12.152
+ A 10.0.12.153
+ A 10.0.12.154
+ A 10.0.12.155
+ A 10.0.12.156
+ A 10.0.12.157
+ A 10.0.12.158
+ A 10.0.12.159
+ A 10.0.12.160
+ A 10.0.12.161
+ A 10.0.12.162
+ A 10.0.12.163
+ A 10.0.12.164
+ A 10.0.12.165
+ A 10.0.12.166
+ A 10.0.12.167
+ A 10.0.12.168
+ A 10.0.12.169
+ A 10.0.12.170
+ A 10.0.12.171
+ A 10.0.12.172
+ A 10.0.12.173
+ A 10.0.12.174
+ A 10.0.12.175
+ A 10.0.12.176
+ A 10.0.12.177
+ A 10.0.12.178
+ A 10.0.12.179
+ A 10.0.12.180
+ A 10.0.12.181
+ A 10.0.12.182
+ A 10.0.12.183
+ A 10.0.12.184
+ A 10.0.12.185
+ A 10.0.12.186
+ A 10.0.12.187
+ A 10.0.12.188
+ A 10.0.12.189
+ A 10.0.12.190
+ A 10.0.12.191
+ A 10.0.12.192
+ A 10.0.12.193
+ A 10.0.12.194
+ A 10.0.12.195
+ A 10.0.12.196
+ A 10.0.12.197
+ A 10.0.12.198
+ A 10.0.12.199
+ A 10.0.12.200
+ A 10.0.12.201
+ A 10.0.12.202
+ A 10.0.12.203
+ A 10.0.12.204
+ A 10.0.12.205
+ A 10.0.12.206
+ A 10.0.12.207
+ A 10.0.12.208
+ A 10.0.12.209
+ A 10.0.12.210
+ A 10.0.12.211
+ A 10.0.12.212
+ A 10.0.12.213
+ A 10.0.12.214
+ A 10.0.12.215
+ A 10.0.12.216
+ A 10.0.12.217
+ A 10.0.12.218
+ A 10.0.12.219
+ A 10.0.12.220
+ A 10.0.12.221
+ A 10.0.12.222
+ A 10.0.12.223
+ A 10.0.12.224
+ A 10.0.12.225
+ A 10.0.12.226
+ A 10.0.12.227
+ A 10.0.12.228
+ A 10.0.12.229
+ A 10.0.12.230
+ A 10.0.12.231
+ A 10.0.12.232
+ A 10.0.12.233
+ A 10.0.12.234
+ A 10.0.12.235
+ A 10.0.12.236
+ A 10.0.12.237
+ A 10.0.12.238
+ A 10.0.12.239
+ A 10.0.12.240
+ A 10.0.12.241
+ A 10.0.12.242
+ A 10.0.12.243
+ A 10.0.12.244
+ A 10.0.12.245
+ A 10.0.12.246
+ A 10.0.12.247
+ A 10.0.12.248
+ A 10.0.12.249
+ A 10.0.12.250
+ A 10.0.12.251
+ A 10.0.12.252
+ A 10.0.12.253
+ A 10.0.12.254
+ A 10.0.12.255
+ A 10.0.13.0
+ A 10.0.13.1
+ A 10.0.13.2
+ A 10.0.13.3
+ A 10.0.13.4
+ A 10.0.13.5
+ A 10.0.13.6
+ A 10.0.13.7
+ A 10.0.13.8
+ A 10.0.13.9
+ A 10.0.13.10
+ A 10.0.13.11
+ A 10.0.13.12
+ A 10.0.13.13
+ A 10.0.13.14
+ A 10.0.13.15
+ A 10.0.13.16
+ A 10.0.13.17
+ A 10.0.13.18
+ A 10.0.13.19
+ A 10.0.13.20
+ A 10.0.13.21
+ A 10.0.13.22
+ A 10.0.13.23
+ A 10.0.13.24
+ A 10.0.13.25
+ A 10.0.13.26
+ A 10.0.13.27
+ A 10.0.13.28
+ A 10.0.13.29
+ A 10.0.13.30
+ A 10.0.13.31
+ A 10.0.13.32
+ A 10.0.13.33
+ A 10.0.13.34
+ A 10.0.13.35
+ A 10.0.13.36
+ A 10.0.13.37
+ A 10.0.13.38
+ A 10.0.13.39
+ A 10.0.13.40
+ A 10.0.13.41
+ A 10.0.13.42
+ A 10.0.13.43
+ A 10.0.13.44
+ A 10.0.13.45
+ A 10.0.13.46
+ A 10.0.13.47
+ A 10.0.13.48
+ A 10.0.13.49
+ A 10.0.13.50
+ A 10.0.13.51
+ A 10.0.13.52
+ A 10.0.13.53
+ A 10.0.13.54
+ A 10.0.13.55
+ A 10.0.13.56
+ A 10.0.13.57
+ A 10.0.13.58
+ A 10.0.13.59
+ A 10.0.13.60
+ A 10.0.13.61
+ A 10.0.13.62
+ A 10.0.13.63
+ A 10.0.13.64
+ A 10.0.13.65
+ A 10.0.13.66
+ A 10.0.13.67
+ A 10.0.13.68
+ A 10.0.13.69
+ A 10.0.13.70
+ A 10.0.13.71
+ A 10.0.13.72
+ A 10.0.13.73
+ A 10.0.13.74
+ A 10.0.13.75
+ A 10.0.13.76
+ A 10.0.13.77
+ A 10.0.13.78
+ A 10.0.13.79
+ A 10.0.13.80
+ A 10.0.13.81
+ A 10.0.13.82
+ A 10.0.13.83
+ A 10.0.13.84
+ A 10.0.13.85
+ A 10.0.13.86
+ A 10.0.13.87
+ A 10.0.13.88
+ A 10.0.13.89
+ A 10.0.13.90
+ A 10.0.13.91
+ A 10.0.13.92
+ A 10.0.13.93
+ A 10.0.13.94
+ A 10.0.13.95
+ A 10.0.13.96
+ A 10.0.13.97
+ A 10.0.13.98
+ A 10.0.13.99
+ A 10.0.13.100
+ A 10.0.13.101
+ A 10.0.13.102
+ A 10.0.13.103
+ A 10.0.13.104
+ A 10.0.13.105
+ A 10.0.13.106
+ A 10.0.13.107
+ A 10.0.13.108
+ A 10.0.13.109
+ A 10.0.13.110
+ A 10.0.13.111
+ A 10.0.13.112
+ A 10.0.13.113
+ A 10.0.13.114
+ A 10.0.13.115
+ A 10.0.13.116
+ A 10.0.13.117
+ A 10.0.13.118
+ A 10.0.13.119
+ A 10.0.13.120
+ A 10.0.13.121
+ A 10.0.13.122
+ A 10.0.13.123
+ A 10.0.13.124
+ A 10.0.13.125
+ A 10.0.13.126
+ A 10.0.13.127
+ A 10.0.13.128
+ A 10.0.13.129
+ A 10.0.13.130
+ A 10.0.13.131
+ A 10.0.13.132
+ A 10.0.13.133
+ A 10.0.13.134
+ A 10.0.13.135
+ A 10.0.13.136
+ A 10.0.13.137
+ A 10.0.13.138
+ A 10.0.13.139
+ A 10.0.13.140
+ A 10.0.13.141
+ A 10.0.13.142
+ A 10.0.13.143
+ A 10.0.13.144
+ A 10.0.13.145
+ A 10.0.13.146
+ A 10.0.13.147
+ A 10.0.13.148
+ A 10.0.13.149
+ A 10.0.13.150
+ A 10.0.13.151
+ A 10.0.13.152
+ A 10.0.13.153
+ A 10.0.13.154
+ A 10.0.13.155
+ A 10.0.13.156
+ A 10.0.13.157
+ A 10.0.13.158
+ A 10.0.13.159
+ A 10.0.13.160
+ A 10.0.13.161
+ A 10.0.13.162
+ A 10.0.13.163
+ A 10.0.13.164
+ A 10.0.13.165
+ A 10.0.13.166
+ A 10.0.13.167
+ A 10.0.13.168
+ A 10.0.13.169
+ A 10.0.13.170
+ A 10.0.13.171
+ A 10.0.13.172
+ A 10.0.13.173
+ A 10.0.13.174
+ A 10.0.13.175
+ A 10.0.13.176
+ A 10.0.13.177
+ A 10.0.13.178
+ A 10.0.13.179
+ A 10.0.13.180
+ A 10.0.13.181
+ A 10.0.13.182
+ A 10.0.13.183
+ A 10.0.13.184
+ A 10.0.13.185
+ A 10.0.13.186
+ A 10.0.13.187
+ A 10.0.13.188
+ A 10.0.13.189
+ A 10.0.13.190
+ A 10.0.13.191
+ A 10.0.13.192
+ A 10.0.13.193
+ A 10.0.13.194
+ A 10.0.13.195
+ A 10.0.13.196
+ A 10.0.13.197
+ A 10.0.13.198
+ A 10.0.13.199
+ A 10.0.13.200
+ A 10.0.13.201
+ A 10.0.13.202
+ A 10.0.13.203
+ A 10.0.13.204
+ A 10.0.13.205
+ A 10.0.13.206
+ A 10.0.13.207
+ A 10.0.13.208
+ A 10.0.13.209
+ A 10.0.13.210
+ A 10.0.13.211
+ A 10.0.13.212
+ A 10.0.13.213
+ A 10.0.13.214
+ A 10.0.13.215
+ A 10.0.13.216
+ A 10.0.13.217
+ A 10.0.13.218
+ A 10.0.13.219
+ A 10.0.13.220
+ A 10.0.13.221
+ A 10.0.13.222
+ A 10.0.13.223
+ A 10.0.13.224
+ A 10.0.13.225
+ A 10.0.13.226
+ A 10.0.13.227
+ A 10.0.13.228
+ A 10.0.13.229
+ A 10.0.13.230
+ A 10.0.13.231
+ A 10.0.13.232
+ A 10.0.13.233
+ A 10.0.13.234
+ A 10.0.13.235
+ A 10.0.13.236
+ A 10.0.13.237
+ A 10.0.13.238
+ A 10.0.13.239
+ A 10.0.13.240
+ A 10.0.13.241
+ A 10.0.13.242
+ A 10.0.13.243
+ A 10.0.13.244
+ A 10.0.13.245
+ A 10.0.13.246
+ A 10.0.13.247
+ A 10.0.13.248
+ A 10.0.13.249
+ A 10.0.13.250
+ A 10.0.13.251
+ A 10.0.13.252
+ A 10.0.13.253
+ A 10.0.13.254
+ A 10.0.13.255
+ A 10.0.14.0
+ A 10.0.14.1
+ A 10.0.14.2
+ A 10.0.14.3
+ A 10.0.14.4
+ A 10.0.14.5
+ A 10.0.14.6
+ A 10.0.14.7
+ A 10.0.14.8
+ A 10.0.14.9
+ A 10.0.14.10
+ A 10.0.14.11
+ A 10.0.14.12
+ A 10.0.14.13
+ A 10.0.14.14
+ A 10.0.14.15
+ A 10.0.14.16
+ A 10.0.14.17
+ A 10.0.14.18
+ A 10.0.14.19
+ A 10.0.14.20
+ A 10.0.14.21
+ A 10.0.14.22
+ A 10.0.14.23
+ A 10.0.14.24
+ A 10.0.14.25
+ A 10.0.14.26
+ A 10.0.14.27
+ A 10.0.14.28
+ A 10.0.14.29
+ A 10.0.14.30
+ A 10.0.14.31
+ A 10.0.14.32
+ A 10.0.14.33
+ A 10.0.14.34
+ A 10.0.14.35
+ A 10.0.14.36
+ A 10.0.14.37
+ A 10.0.14.38
+ A 10.0.14.39
+ A 10.0.14.40
+ A 10.0.14.41
+ A 10.0.14.42
+ A 10.0.14.43
+ A 10.0.14.44
+ A 10.0.14.45
+ A 10.0.14.46
+ A 10.0.14.47
+ A 10.0.14.48
+ A 10.0.14.49
+ A 10.0.14.50
+ A 10.0.14.51
+ A 10.0.14.52
+ A 10.0.14.53
+ A 10.0.14.54
+ A 10.0.14.55
+ A 10.0.14.56
+ A 10.0.14.57
+ A 10.0.14.58
+ A 10.0.14.59
+ A 10.0.14.60
+ A 10.0.14.61
+ A 10.0.14.62
+ A 10.0.14.63
+ A 10.0.14.64
+ A 10.0.14.65
+ A 10.0.14.66
+ A 10.0.14.67
+ A 10.0.14.68
+ A 10.0.14.69
+ A 10.0.14.70
+ A 10.0.14.71
+ A 10.0.14.72
+ A 10.0.14.73
+ A 10.0.14.74
+ A 10.0.14.75
+ A 10.0.14.76
+ A 10.0.14.77
+ A 10.0.14.78
+ A 10.0.14.79
+ A 10.0.14.80
+ A 10.0.14.81
+ A 10.0.14.82
+ A 10.0.14.83
+ A 10.0.14.84
+ A 10.0.14.85
+ A 10.0.14.86
+ A 10.0.14.87
+ A 10.0.14.88
+ A 10.0.14.89
+ A 10.0.14.90
+ A 10.0.14.91
+ A 10.0.14.92
+ A 10.0.14.93
+ A 10.0.14.94
+ A 10.0.14.95
+ A 10.0.14.96
+ A 10.0.14.97
+ A 10.0.14.98
+ A 10.0.14.99
+ A 10.0.14.100
+ A 10.0.14.101
+ A 10.0.14.102
+ A 10.0.14.103
+ A 10.0.14.104
+ A 10.0.14.105
+ A 10.0.14.106
+ A 10.0.14.107
+ A 10.0.14.108
+ A 10.0.14.109
+ A 10.0.14.110
+ A 10.0.14.111
+ A 10.0.14.112
+ A 10.0.14.113
+ A 10.0.14.114
+ A 10.0.14.115
+ A 10.0.14.116
+ A 10.0.14.117
+ A 10.0.14.118
+ A 10.0.14.119
+ A 10.0.14.120
+ A 10.0.14.121
+ A 10.0.14.122
+ A 10.0.14.123
+ A 10.0.14.124
+ A 10.0.14.125
+ A 10.0.14.126
+ A 10.0.14.127
+ A 10.0.14.128
+ A 10.0.14.129
+ A 10.0.14.130
+ A 10.0.14.131
+ A 10.0.14.132
+ A 10.0.14.133
+ A 10.0.14.134
+ A 10.0.14.135
+ A 10.0.14.136
+ A 10.0.14.137
+ A 10.0.14.138
+ A 10.0.14.139
+ A 10.0.14.140
+ A 10.0.14.141
+ A 10.0.14.142
+ A 10.0.14.143
+ A 10.0.14.144
+ A 10.0.14.145
+ A 10.0.14.146
+ A 10.0.14.147
+ A 10.0.14.148
+ A 10.0.14.149
+ A 10.0.14.150
+ A 10.0.14.151
+ A 10.0.14.152
+ A 10.0.14.153
+ A 10.0.14.154
+ A 10.0.14.155
+ A 10.0.14.156
+ A 10.0.14.157
+ A 10.0.14.158
+ A 10.0.14.159
+ A 10.0.14.160
+ A 10.0.14.161
+ A 10.0.14.162
+ A 10.0.14.163
+ A 10.0.14.164
+ A 10.0.14.165
+ A 10.0.14.166
+ A 10.0.14.167
+ A 10.0.14.168
+ A 10.0.14.169
+ A 10.0.14.170
+ A 10.0.14.171
+ A 10.0.14.172
+ A 10.0.14.173
+ A 10.0.14.174
+ A 10.0.14.175
+ A 10.0.14.176
+ A 10.0.14.177
+ A 10.0.14.178
+ A 10.0.14.179
+ A 10.0.14.180
+ A 10.0.14.181
+ A 10.0.14.182
+ A 10.0.14.183
+ A 10.0.14.184
+ A 10.0.14.185
+ A 10.0.14.186
+ A 10.0.14.187
+ A 10.0.14.188
+ A 10.0.14.189
+ A 10.0.14.190
+ A 10.0.14.191
+ A 10.0.14.192
+ A 10.0.14.193
+ A 10.0.14.194
+ A 10.0.14.195
+ A 10.0.14.196
+ A 10.0.14.197
+ A 10.0.14.198
+ A 10.0.14.199
+ A 10.0.14.200
+ A 10.0.14.201
+ A 10.0.14.202
+ A 10.0.14.203
+ A 10.0.14.204
+ A 10.0.14.205
+ A 10.0.14.206
+ A 10.0.14.207
+ A 10.0.14.208
+ A 10.0.14.209
+ A 10.0.14.210
+ A 10.0.14.211
+ A 10.0.14.212
+ A 10.0.14.213
+ A 10.0.14.214
+ A 10.0.14.215
+ A 10.0.14.216
+ A 10.0.14.217
+ A 10.0.14.218
+ A 10.0.14.219
+ A 10.0.14.220
+ A 10.0.14.221
+ A 10.0.14.222
+ A 10.0.14.223
+ A 10.0.14.224
+ A 10.0.14.225
+ A 10.0.14.226
+ A 10.0.14.227
+ A 10.0.14.228
+ A 10.0.14.229
+ A 10.0.14.230
+ A 10.0.14.231
+ A 10.0.14.232
+ A 10.0.14.233
+ A 10.0.14.234
+ A 10.0.14.235
+ A 10.0.14.236
+ A 10.0.14.237
+ A 10.0.14.238
+ A 10.0.14.239
+ A 10.0.14.240
+ A 10.0.14.241
+ A 10.0.14.242
+ A 10.0.14.243
+ A 10.0.14.244
+ A 10.0.14.245
+ A 10.0.14.246
+ A 10.0.14.247
+ A 10.0.14.248
+ A 10.0.14.249
+ A 10.0.14.250
+ A 10.0.14.251
+ A 10.0.14.252
+ A 10.0.14.253
+ A 10.0.14.254
+ A 10.0.14.255
+ A 10.0.15.0
+ A 10.0.15.1
+ A 10.0.15.2
+ A 10.0.15.3
+ A 10.0.15.4
+ A 10.0.15.5
+ A 10.0.15.6
+ A 10.0.15.7
+ A 10.0.15.8
+ A 10.0.15.9
+ A 10.0.15.10
+ A 10.0.15.11
+ A 10.0.15.12
+ A 10.0.15.13
+ A 10.0.15.14
+ A 10.0.15.15
+ A 10.0.15.16
+ A 10.0.15.17
+ A 10.0.15.18
+ A 10.0.15.19
+ A 10.0.15.20
+ A 10.0.15.21
+ A 10.0.15.22
+ A 10.0.15.23
+ A 10.0.15.24
+ A 10.0.15.25
+ A 10.0.15.26
+ A 10.0.15.27
+ A 10.0.15.28
+ A 10.0.15.29
+ A 10.0.15.30
+ A 10.0.15.31
+ A 10.0.15.32
+ A 10.0.15.33
+ A 10.0.15.34
+ A 10.0.15.35
+ A 10.0.15.36
+ A 10.0.15.37
+ A 10.0.15.38
+ A 10.0.15.39
+ A 10.0.15.40
+ A 10.0.15.41
+ A 10.0.15.42
+ A 10.0.15.43
+ A 10.0.15.44
+ A 10.0.15.45
+ A 10.0.15.46
+ A 10.0.15.47
+ A 10.0.15.48
+ A 10.0.15.49
+ A 10.0.15.50
+ A 10.0.15.51
+ A 10.0.15.52
+ A 10.0.15.53
+ A 10.0.15.54
+ A 10.0.15.55
+ A 10.0.15.56
+ A 10.0.15.57
+ A 10.0.15.58
+ A 10.0.15.59
+ A 10.0.15.60
+ A 10.0.15.61
+ A 10.0.15.62
+ A 10.0.15.63
+ A 10.0.15.64
+ A 10.0.15.65
+ A 10.0.15.66
+ A 10.0.15.67
+ A 10.0.15.68
+ A 10.0.15.69
+ A 10.0.15.70
+ A 10.0.15.71
+ A 10.0.15.72
+ A 10.0.15.73
+ A 10.0.15.74
+ A 10.0.15.75
+ A 10.0.15.76
+ A 10.0.15.77
+ A 10.0.15.78
+ A 10.0.15.79
+ A 10.0.15.80
+ A 10.0.15.81
+ A 10.0.15.82
+ A 10.0.15.83
+ A 10.0.15.84
+ A 10.0.15.85
+ A 10.0.15.86
+ A 10.0.15.87
+ A 10.0.15.88
+ A 10.0.15.89
+ A 10.0.15.90
+ A 10.0.15.91
+ A 10.0.15.92
+ A 10.0.15.93
+ A 10.0.15.94
+ A 10.0.15.95
+ A 10.0.15.96
+ A 10.0.15.97
+ A 10.0.15.98
+ A 10.0.15.99
+ A 10.0.15.100
+ A 10.0.15.101
+ A 10.0.15.102
+ A 10.0.15.103
+ A 10.0.15.104
+ A 10.0.15.105
+ A 10.0.15.106
+ A 10.0.15.107
+ A 10.0.15.108
+ A 10.0.15.109
+ A 10.0.15.110
+ A 10.0.15.111
+ A 10.0.15.112
+ A 10.0.15.113
+ A 10.0.15.114
+ A 10.0.15.115
+ A 10.0.15.116
+ A 10.0.15.117
+ A 10.0.15.118
+ A 10.0.15.119
+ A 10.0.15.120
+ A 10.0.15.121
+ A 10.0.15.122
+ A 10.0.15.123
+ A 10.0.15.124
+ A 10.0.15.125
+ A 10.0.15.126
+ A 10.0.15.127
+ A 10.0.15.128
+ A 10.0.15.129
+ A 10.0.15.130
+ A 10.0.15.131
+ A 10.0.15.132
+ A 10.0.15.133
+ A 10.0.15.134
+ A 10.0.15.135
+ A 10.0.15.136
+ A 10.0.15.137
+ A 10.0.15.138
+ A 10.0.15.139
+ A 10.0.15.140
+ A 10.0.15.141
+ A 10.0.15.142
+ A 10.0.15.143
+ A 10.0.15.144
+ A 10.0.15.145
+ A 10.0.15.146
+ A 10.0.15.147
+ A 10.0.15.148
+ A 10.0.15.149
+ A 10.0.15.150
+ A 10.0.15.151
+ A 10.0.15.152
+ A 10.0.15.153
+ A 10.0.15.154
+ A 10.0.15.155
+ A 10.0.15.156
+ A 10.0.15.157
+ A 10.0.15.158
+ A 10.0.15.159
+5000 A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+ A 10.0.3.232
+ A 10.0.3.233
+ A 10.0.3.234
+ A 10.0.3.235
+ A 10.0.3.236
+ A 10.0.3.237
+ A 10.0.3.238
+ A 10.0.3.239
+ A 10.0.3.240
+ A 10.0.3.241
+ A 10.0.3.242
+ A 10.0.3.243
+ A 10.0.3.244
+ A 10.0.3.245
+ A 10.0.3.246
+ A 10.0.3.247
+ A 10.0.3.248
+ A 10.0.3.249
+ A 10.0.3.250
+ A 10.0.3.251
+ A 10.0.3.252
+ A 10.0.3.253
+ A 10.0.3.254
+ A 10.0.3.255
+ A 10.0.4.0
+ A 10.0.4.1
+ A 10.0.4.2
+ A 10.0.4.3
+ A 10.0.4.4
+ A 10.0.4.5
+ A 10.0.4.6
+ A 10.0.4.7
+ A 10.0.4.8
+ A 10.0.4.9
+ A 10.0.4.10
+ A 10.0.4.11
+ A 10.0.4.12
+ A 10.0.4.13
+ A 10.0.4.14
+ A 10.0.4.15
+ A 10.0.4.16
+ A 10.0.4.17
+ A 10.0.4.18
+ A 10.0.4.19
+ A 10.0.4.20
+ A 10.0.4.21
+ A 10.0.4.22
+ A 10.0.4.23
+ A 10.0.4.24
+ A 10.0.4.25
+ A 10.0.4.26
+ A 10.0.4.27
+ A 10.0.4.28
+ A 10.0.4.29
+ A 10.0.4.30
+ A 10.0.4.31
+ A 10.0.4.32
+ A 10.0.4.33
+ A 10.0.4.34
+ A 10.0.4.35
+ A 10.0.4.36
+ A 10.0.4.37
+ A 10.0.4.38
+ A 10.0.4.39
+ A 10.0.4.40
+ A 10.0.4.41
+ A 10.0.4.42
+ A 10.0.4.43
+ A 10.0.4.44
+ A 10.0.4.45
+ A 10.0.4.46
+ A 10.0.4.47
+ A 10.0.4.48
+ A 10.0.4.49
+ A 10.0.4.50
+ A 10.0.4.51
+ A 10.0.4.52
+ A 10.0.4.53
+ A 10.0.4.54
+ A 10.0.4.55
+ A 10.0.4.56
+ A 10.0.4.57
+ A 10.0.4.58
+ A 10.0.4.59
+ A 10.0.4.60
+ A 10.0.4.61
+ A 10.0.4.62
+ A 10.0.4.63
+ A 10.0.4.64
+ A 10.0.4.65
+ A 10.0.4.66
+ A 10.0.4.67
+ A 10.0.4.68
+ A 10.0.4.69
+ A 10.0.4.70
+ A 10.0.4.71
+ A 10.0.4.72
+ A 10.0.4.73
+ A 10.0.4.74
+ A 10.0.4.75
+ A 10.0.4.76
+ A 10.0.4.77
+ A 10.0.4.78
+ A 10.0.4.79
+ A 10.0.4.80
+ A 10.0.4.81
+ A 10.0.4.82
+ A 10.0.4.83
+ A 10.0.4.84
+ A 10.0.4.85
+ A 10.0.4.86
+ A 10.0.4.87
+ A 10.0.4.88
+ A 10.0.4.89
+ A 10.0.4.90
+ A 10.0.4.91
+ A 10.0.4.92
+ A 10.0.4.93
+ A 10.0.4.94
+ A 10.0.4.95
+ A 10.0.4.96
+ A 10.0.4.97
+ A 10.0.4.98
+ A 10.0.4.99
+ A 10.0.4.100
+ A 10.0.4.101
+ A 10.0.4.102
+ A 10.0.4.103
+ A 10.0.4.104
+ A 10.0.4.105
+ A 10.0.4.106
+ A 10.0.4.107
+ A 10.0.4.108
+ A 10.0.4.109
+ A 10.0.4.110
+ A 10.0.4.111
+ A 10.0.4.112
+ A 10.0.4.113
+ A 10.0.4.114
+ A 10.0.4.115
+ A 10.0.4.116
+ A 10.0.4.117
+ A 10.0.4.118
+ A 10.0.4.119
+ A 10.0.4.120
+ A 10.0.4.121
+ A 10.0.4.122
+ A 10.0.4.123
+ A 10.0.4.124
+ A 10.0.4.125
+ A 10.0.4.126
+ A 10.0.4.127
+ A 10.0.4.128
+ A 10.0.4.129
+ A 10.0.4.130
+ A 10.0.4.131
+ A 10.0.4.132
+ A 10.0.4.133
+ A 10.0.4.134
+ A 10.0.4.135
+ A 10.0.4.136
+ A 10.0.4.137
+ A 10.0.4.138
+ A 10.0.4.139
+ A 10.0.4.140
+ A 10.0.4.141
+ A 10.0.4.142
+ A 10.0.4.143
+ A 10.0.4.144
+ A 10.0.4.145
+ A 10.0.4.146
+ A 10.0.4.147
+ A 10.0.4.148
+ A 10.0.4.149
+ A 10.0.4.150
+ A 10.0.4.151
+ A 10.0.4.152
+ A 10.0.4.153
+ A 10.0.4.154
+ A 10.0.4.155
+ A 10.0.4.156
+ A 10.0.4.157
+ A 10.0.4.158
+ A 10.0.4.159
+ A 10.0.4.160
+ A 10.0.4.161
+ A 10.0.4.162
+ A 10.0.4.163
+ A 10.0.4.164
+ A 10.0.4.165
+ A 10.0.4.166
+ A 10.0.4.167
+ A 10.0.4.168
+ A 10.0.4.169
+ A 10.0.4.170
+ A 10.0.4.171
+ A 10.0.4.172
+ A 10.0.4.173
+ A 10.0.4.174
+ A 10.0.4.175
+ A 10.0.4.176
+ A 10.0.4.177
+ A 10.0.4.178
+ A 10.0.4.179
+ A 10.0.4.180
+ A 10.0.4.181
+ A 10.0.4.182
+ A 10.0.4.183
+ A 10.0.4.184
+ A 10.0.4.185
+ A 10.0.4.186
+ A 10.0.4.187
+ A 10.0.4.188
+ A 10.0.4.189
+ A 10.0.4.190
+ A 10.0.4.191
+ A 10.0.4.192
+ A 10.0.4.193
+ A 10.0.4.194
+ A 10.0.4.195
+ A 10.0.4.196
+ A 10.0.4.197
+ A 10.0.4.198
+ A 10.0.4.199
+ A 10.0.4.200
+ A 10.0.4.201
+ A 10.0.4.202
+ A 10.0.4.203
+ A 10.0.4.204
+ A 10.0.4.205
+ A 10.0.4.206
+ A 10.0.4.207
+ A 10.0.4.208
+ A 10.0.4.209
+ A 10.0.4.210
+ A 10.0.4.211
+ A 10.0.4.212
+ A 10.0.4.213
+ A 10.0.4.214
+ A 10.0.4.215
+ A 10.0.4.216
+ A 10.0.4.217
+ A 10.0.4.218
+ A 10.0.4.219
+ A 10.0.4.220
+ A 10.0.4.221
+ A 10.0.4.222
+ A 10.0.4.223
+ A 10.0.4.224
+ A 10.0.4.225
+ A 10.0.4.226
+ A 10.0.4.227
+ A 10.0.4.228
+ A 10.0.4.229
+ A 10.0.4.230
+ A 10.0.4.231
+ A 10.0.4.232
+ A 10.0.4.233
+ A 10.0.4.234
+ A 10.0.4.235
+ A 10.0.4.236
+ A 10.0.4.237
+ A 10.0.4.238
+ A 10.0.4.239
+ A 10.0.4.240
+ A 10.0.4.241
+ A 10.0.4.242
+ A 10.0.4.243
+ A 10.0.4.244
+ A 10.0.4.245
+ A 10.0.4.246
+ A 10.0.4.247
+ A 10.0.4.248
+ A 10.0.4.249
+ A 10.0.4.250
+ A 10.0.4.251
+ A 10.0.4.252
+ A 10.0.4.253
+ A 10.0.4.254
+ A 10.0.4.255
+ A 10.0.5.0
+ A 10.0.5.1
+ A 10.0.5.2
+ A 10.0.5.3
+ A 10.0.5.4
+ A 10.0.5.5
+ A 10.0.5.6
+ A 10.0.5.7
+ A 10.0.5.8
+ A 10.0.5.9
+ A 10.0.5.10
+ A 10.0.5.11
+ A 10.0.5.12
+ A 10.0.5.13
+ A 10.0.5.14
+ A 10.0.5.15
+ A 10.0.5.16
+ A 10.0.5.17
+ A 10.0.5.18
+ A 10.0.5.19
+ A 10.0.5.20
+ A 10.0.5.21
+ A 10.0.5.22
+ A 10.0.5.23
+ A 10.0.5.24
+ A 10.0.5.25
+ A 10.0.5.26
+ A 10.0.5.27
+ A 10.0.5.28
+ A 10.0.5.29
+ A 10.0.5.30
+ A 10.0.5.31
+ A 10.0.5.32
+ A 10.0.5.33
+ A 10.0.5.34
+ A 10.0.5.35
+ A 10.0.5.36
+ A 10.0.5.37
+ A 10.0.5.38
+ A 10.0.5.39
+ A 10.0.5.40
+ A 10.0.5.41
+ A 10.0.5.42
+ A 10.0.5.43
+ A 10.0.5.44
+ A 10.0.5.45
+ A 10.0.5.46
+ A 10.0.5.47
+ A 10.0.5.48
+ A 10.0.5.49
+ A 10.0.5.50
+ A 10.0.5.51
+ A 10.0.5.52
+ A 10.0.5.53
+ A 10.0.5.54
+ A 10.0.5.55
+ A 10.0.5.56
+ A 10.0.5.57
+ A 10.0.5.58
+ A 10.0.5.59
+ A 10.0.5.60
+ A 10.0.5.61
+ A 10.0.5.62
+ A 10.0.5.63
+ A 10.0.5.64
+ A 10.0.5.65
+ A 10.0.5.66
+ A 10.0.5.67
+ A 10.0.5.68
+ A 10.0.5.69
+ A 10.0.5.70
+ A 10.0.5.71
+ A 10.0.5.72
+ A 10.0.5.73
+ A 10.0.5.74
+ A 10.0.5.75
+ A 10.0.5.76
+ A 10.0.5.77
+ A 10.0.5.78
+ A 10.0.5.79
+ A 10.0.5.80
+ A 10.0.5.81
+ A 10.0.5.82
+ A 10.0.5.83
+ A 10.0.5.84
+ A 10.0.5.85
+ A 10.0.5.86
+ A 10.0.5.87
+ A 10.0.5.88
+ A 10.0.5.89
+ A 10.0.5.90
+ A 10.0.5.91
+ A 10.0.5.92
+ A 10.0.5.93
+ A 10.0.5.94
+ A 10.0.5.95
+ A 10.0.5.96
+ A 10.0.5.97
+ A 10.0.5.98
+ A 10.0.5.99
+ A 10.0.5.100
+ A 10.0.5.101
+ A 10.0.5.102
+ A 10.0.5.103
+ A 10.0.5.104
+ A 10.0.5.105
+ A 10.0.5.106
+ A 10.0.5.107
+ A 10.0.5.108
+ A 10.0.5.109
+ A 10.0.5.110
+ A 10.0.5.111
+ A 10.0.5.112
+ A 10.0.5.113
+ A 10.0.5.114
+ A 10.0.5.115
+ A 10.0.5.116
+ A 10.0.5.117
+ A 10.0.5.118
+ A 10.0.5.119
+ A 10.0.5.120
+ A 10.0.5.121
+ A 10.0.5.122
+ A 10.0.5.123
+ A 10.0.5.124
+ A 10.0.5.125
+ A 10.0.5.126
+ A 10.0.5.127
+ A 10.0.5.128
+ A 10.0.5.129
+ A 10.0.5.130
+ A 10.0.5.131
+ A 10.0.5.132
+ A 10.0.5.133
+ A 10.0.5.134
+ A 10.0.5.135
+ A 10.0.5.136
+ A 10.0.5.137
+ A 10.0.5.138
+ A 10.0.5.139
+ A 10.0.5.140
+ A 10.0.5.141
+ A 10.0.5.142
+ A 10.0.5.143
+ A 10.0.5.144
+ A 10.0.5.145
+ A 10.0.5.146
+ A 10.0.5.147
+ A 10.0.5.148
+ A 10.0.5.149
+ A 10.0.5.150
+ A 10.0.5.151
+ A 10.0.5.152
+ A 10.0.5.153
+ A 10.0.5.154
+ A 10.0.5.155
+ A 10.0.5.156
+ A 10.0.5.157
+ A 10.0.5.158
+ A 10.0.5.159
+ A 10.0.5.160
+ A 10.0.5.161
+ A 10.0.5.162
+ A 10.0.5.163
+ A 10.0.5.164
+ A 10.0.5.165
+ A 10.0.5.166
+ A 10.0.5.167
+ A 10.0.5.168
+ A 10.0.5.169
+ A 10.0.5.170
+ A 10.0.5.171
+ A 10.0.5.172
+ A 10.0.5.173
+ A 10.0.5.174
+ A 10.0.5.175
+ A 10.0.5.176
+ A 10.0.5.177
+ A 10.0.5.178
+ A 10.0.5.179
+ A 10.0.5.180
+ A 10.0.5.181
+ A 10.0.5.182
+ A 10.0.5.183
+ A 10.0.5.184
+ A 10.0.5.185
+ A 10.0.5.186
+ A 10.0.5.187
+ A 10.0.5.188
+ A 10.0.5.189
+ A 10.0.5.190
+ A 10.0.5.191
+ A 10.0.5.192
+ A 10.0.5.193
+ A 10.0.5.194
+ A 10.0.5.195
+ A 10.0.5.196
+ A 10.0.5.197
+ A 10.0.5.198
+ A 10.0.5.199
+ A 10.0.5.200
+ A 10.0.5.201
+ A 10.0.5.202
+ A 10.0.5.203
+ A 10.0.5.204
+ A 10.0.5.205
+ A 10.0.5.206
+ A 10.0.5.207
+ A 10.0.5.208
+ A 10.0.5.209
+ A 10.0.5.210
+ A 10.0.5.211
+ A 10.0.5.212
+ A 10.0.5.213
+ A 10.0.5.214
+ A 10.0.5.215
+ A 10.0.5.216
+ A 10.0.5.217
+ A 10.0.5.218
+ A 10.0.5.219
+ A 10.0.5.220
+ A 10.0.5.221
+ A 10.0.5.222
+ A 10.0.5.223
+ A 10.0.5.224
+ A 10.0.5.225
+ A 10.0.5.226
+ A 10.0.5.227
+ A 10.0.5.228
+ A 10.0.5.229
+ A 10.0.5.230
+ A 10.0.5.231
+ A 10.0.5.232
+ A 10.0.5.233
+ A 10.0.5.234
+ A 10.0.5.235
+ A 10.0.5.236
+ A 10.0.5.237
+ A 10.0.5.238
+ A 10.0.5.239
+ A 10.0.5.240
+ A 10.0.5.241
+ A 10.0.5.242
+ A 10.0.5.243
+ A 10.0.5.244
+ A 10.0.5.245
+ A 10.0.5.246
+ A 10.0.5.247
+ A 10.0.5.248
+ A 10.0.5.249
+ A 10.0.5.250
+ A 10.0.5.251
+ A 10.0.5.252
+ A 10.0.5.253
+ A 10.0.5.254
+ A 10.0.5.255
+ A 10.0.6.0
+ A 10.0.6.1
+ A 10.0.6.2
+ A 10.0.6.3
+ A 10.0.6.4
+ A 10.0.6.5
+ A 10.0.6.6
+ A 10.0.6.7
+ A 10.0.6.8
+ A 10.0.6.9
+ A 10.0.6.10
+ A 10.0.6.11
+ A 10.0.6.12
+ A 10.0.6.13
+ A 10.0.6.14
+ A 10.0.6.15
+ A 10.0.6.16
+ A 10.0.6.17
+ A 10.0.6.18
+ A 10.0.6.19
+ A 10.0.6.20
+ A 10.0.6.21
+ A 10.0.6.22
+ A 10.0.6.23
+ A 10.0.6.24
+ A 10.0.6.25
+ A 10.0.6.26
+ A 10.0.6.27
+ A 10.0.6.28
+ A 10.0.6.29
+ A 10.0.6.30
+ A 10.0.6.31
+ A 10.0.6.32
+ A 10.0.6.33
+ A 10.0.6.34
+ A 10.0.6.35
+ A 10.0.6.36
+ A 10.0.6.37
+ A 10.0.6.38
+ A 10.0.6.39
+ A 10.0.6.40
+ A 10.0.6.41
+ A 10.0.6.42
+ A 10.0.6.43
+ A 10.0.6.44
+ A 10.0.6.45
+ A 10.0.6.46
+ A 10.0.6.47
+ A 10.0.6.48
+ A 10.0.6.49
+ A 10.0.6.50
+ A 10.0.6.51
+ A 10.0.6.52
+ A 10.0.6.53
+ A 10.0.6.54
+ A 10.0.6.55
+ A 10.0.6.56
+ A 10.0.6.57
+ A 10.0.6.58
+ A 10.0.6.59
+ A 10.0.6.60
+ A 10.0.6.61
+ A 10.0.6.62
+ A 10.0.6.63
+ A 10.0.6.64
+ A 10.0.6.65
+ A 10.0.6.66
+ A 10.0.6.67
+ A 10.0.6.68
+ A 10.0.6.69
+ A 10.0.6.70
+ A 10.0.6.71
+ A 10.0.6.72
+ A 10.0.6.73
+ A 10.0.6.74
+ A 10.0.6.75
+ A 10.0.6.76
+ A 10.0.6.77
+ A 10.0.6.78
+ A 10.0.6.79
+ A 10.0.6.80
+ A 10.0.6.81
+ A 10.0.6.82
+ A 10.0.6.83
+ A 10.0.6.84
+ A 10.0.6.85
+ A 10.0.6.86
+ A 10.0.6.87
+ A 10.0.6.88
+ A 10.0.6.89
+ A 10.0.6.90
+ A 10.0.6.91
+ A 10.0.6.92
+ A 10.0.6.93
+ A 10.0.6.94
+ A 10.0.6.95
+ A 10.0.6.96
+ A 10.0.6.97
+ A 10.0.6.98
+ A 10.0.6.99
+ A 10.0.6.100
+ A 10.0.6.101
+ A 10.0.6.102
+ A 10.0.6.103
+ A 10.0.6.104
+ A 10.0.6.105
+ A 10.0.6.106
+ A 10.0.6.107
+ A 10.0.6.108
+ A 10.0.6.109
+ A 10.0.6.110
+ A 10.0.6.111
+ A 10.0.6.112
+ A 10.0.6.113
+ A 10.0.6.114
+ A 10.0.6.115
+ A 10.0.6.116
+ A 10.0.6.117
+ A 10.0.6.118
+ A 10.0.6.119
+ A 10.0.6.120
+ A 10.0.6.121
+ A 10.0.6.122
+ A 10.0.6.123
+ A 10.0.6.124
+ A 10.0.6.125
+ A 10.0.6.126
+ A 10.0.6.127
+ A 10.0.6.128
+ A 10.0.6.129
+ A 10.0.6.130
+ A 10.0.6.131
+ A 10.0.6.132
+ A 10.0.6.133
+ A 10.0.6.134
+ A 10.0.6.135
+ A 10.0.6.136
+ A 10.0.6.137
+ A 10.0.6.138
+ A 10.0.6.139
+ A 10.0.6.140
+ A 10.0.6.141
+ A 10.0.6.142
+ A 10.0.6.143
+ A 10.0.6.144
+ A 10.0.6.145
+ A 10.0.6.146
+ A 10.0.6.147
+ A 10.0.6.148
+ A 10.0.6.149
+ A 10.0.6.150
+ A 10.0.6.151
+ A 10.0.6.152
+ A 10.0.6.153
+ A 10.0.6.154
+ A 10.0.6.155
+ A 10.0.6.156
+ A 10.0.6.157
+ A 10.0.6.158
+ A 10.0.6.159
+ A 10.0.6.160
+ A 10.0.6.161
+ A 10.0.6.162
+ A 10.0.6.163
+ A 10.0.6.164
+ A 10.0.6.165
+ A 10.0.6.166
+ A 10.0.6.167
+ A 10.0.6.168
+ A 10.0.6.169
+ A 10.0.6.170
+ A 10.0.6.171
+ A 10.0.6.172
+ A 10.0.6.173
+ A 10.0.6.174
+ A 10.0.6.175
+ A 10.0.6.176
+ A 10.0.6.177
+ A 10.0.6.178
+ A 10.0.6.179
+ A 10.0.6.180
+ A 10.0.6.181
+ A 10.0.6.182
+ A 10.0.6.183
+ A 10.0.6.184
+ A 10.0.6.185
+ A 10.0.6.186
+ A 10.0.6.187
+ A 10.0.6.188
+ A 10.0.6.189
+ A 10.0.6.190
+ A 10.0.6.191
+ A 10.0.6.192
+ A 10.0.6.193
+ A 10.0.6.194
+ A 10.0.6.195
+ A 10.0.6.196
+ A 10.0.6.197
+ A 10.0.6.198
+ A 10.0.6.199
+ A 10.0.6.200
+ A 10.0.6.201
+ A 10.0.6.202
+ A 10.0.6.203
+ A 10.0.6.204
+ A 10.0.6.205
+ A 10.0.6.206
+ A 10.0.6.207
+ A 10.0.6.208
+ A 10.0.6.209
+ A 10.0.6.210
+ A 10.0.6.211
+ A 10.0.6.212
+ A 10.0.6.213
+ A 10.0.6.214
+ A 10.0.6.215
+ A 10.0.6.216
+ A 10.0.6.217
+ A 10.0.6.218
+ A 10.0.6.219
+ A 10.0.6.220
+ A 10.0.6.221
+ A 10.0.6.222
+ A 10.0.6.223
+ A 10.0.6.224
+ A 10.0.6.225
+ A 10.0.6.226
+ A 10.0.6.227
+ A 10.0.6.228
+ A 10.0.6.229
+ A 10.0.6.230
+ A 10.0.6.231
+ A 10.0.6.232
+ A 10.0.6.233
+ A 10.0.6.234
+ A 10.0.6.235
+ A 10.0.6.236
+ A 10.0.6.237
+ A 10.0.6.238
+ A 10.0.6.239
+ A 10.0.6.240
+ A 10.0.6.241
+ A 10.0.6.242
+ A 10.0.6.243
+ A 10.0.6.244
+ A 10.0.6.245
+ A 10.0.6.246
+ A 10.0.6.247
+ A 10.0.6.248
+ A 10.0.6.249
+ A 10.0.6.250
+ A 10.0.6.251
+ A 10.0.6.252
+ A 10.0.6.253
+ A 10.0.6.254
+ A 10.0.6.255
+ A 10.0.7.0
+ A 10.0.7.1
+ A 10.0.7.2
+ A 10.0.7.3
+ A 10.0.7.4
+ A 10.0.7.5
+ A 10.0.7.6
+ A 10.0.7.7
+ A 10.0.7.8
+ A 10.0.7.9
+ A 10.0.7.10
+ A 10.0.7.11
+ A 10.0.7.12
+ A 10.0.7.13
+ A 10.0.7.14
+ A 10.0.7.15
+ A 10.0.7.16
+ A 10.0.7.17
+ A 10.0.7.18
+ A 10.0.7.19
+ A 10.0.7.20
+ A 10.0.7.21
+ A 10.0.7.22
+ A 10.0.7.23
+ A 10.0.7.24
+ A 10.0.7.25
+ A 10.0.7.26
+ A 10.0.7.27
+ A 10.0.7.28
+ A 10.0.7.29
+ A 10.0.7.30
+ A 10.0.7.31
+ A 10.0.7.32
+ A 10.0.7.33
+ A 10.0.7.34
+ A 10.0.7.35
+ A 10.0.7.36
+ A 10.0.7.37
+ A 10.0.7.38
+ A 10.0.7.39
+ A 10.0.7.40
+ A 10.0.7.41
+ A 10.0.7.42
+ A 10.0.7.43
+ A 10.0.7.44
+ A 10.0.7.45
+ A 10.0.7.46
+ A 10.0.7.47
+ A 10.0.7.48
+ A 10.0.7.49
+ A 10.0.7.50
+ A 10.0.7.51
+ A 10.0.7.52
+ A 10.0.7.53
+ A 10.0.7.54
+ A 10.0.7.55
+ A 10.0.7.56
+ A 10.0.7.57
+ A 10.0.7.58
+ A 10.0.7.59
+ A 10.0.7.60
+ A 10.0.7.61
+ A 10.0.7.62
+ A 10.0.7.63
+ A 10.0.7.64
+ A 10.0.7.65
+ A 10.0.7.66
+ A 10.0.7.67
+ A 10.0.7.68
+ A 10.0.7.69
+ A 10.0.7.70
+ A 10.0.7.71
+ A 10.0.7.72
+ A 10.0.7.73
+ A 10.0.7.74
+ A 10.0.7.75
+ A 10.0.7.76
+ A 10.0.7.77
+ A 10.0.7.78
+ A 10.0.7.79
+ A 10.0.7.80
+ A 10.0.7.81
+ A 10.0.7.82
+ A 10.0.7.83
+ A 10.0.7.84
+ A 10.0.7.85
+ A 10.0.7.86
+ A 10.0.7.87
+ A 10.0.7.88
+ A 10.0.7.89
+ A 10.0.7.90
+ A 10.0.7.91
+ A 10.0.7.92
+ A 10.0.7.93
+ A 10.0.7.94
+ A 10.0.7.95
+ A 10.0.7.96
+ A 10.0.7.97
+ A 10.0.7.98
+ A 10.0.7.99
+ A 10.0.7.100
+ A 10.0.7.101
+ A 10.0.7.102
+ A 10.0.7.103
+ A 10.0.7.104
+ A 10.0.7.105
+ A 10.0.7.106
+ A 10.0.7.107
+ A 10.0.7.108
+ A 10.0.7.109
+ A 10.0.7.110
+ A 10.0.7.111
+ A 10.0.7.112
+ A 10.0.7.113
+ A 10.0.7.114
+ A 10.0.7.115
+ A 10.0.7.116
+ A 10.0.7.117
+ A 10.0.7.118
+ A 10.0.7.119
+ A 10.0.7.120
+ A 10.0.7.121
+ A 10.0.7.122
+ A 10.0.7.123
+ A 10.0.7.124
+ A 10.0.7.125
+ A 10.0.7.126
+ A 10.0.7.127
+ A 10.0.7.128
+ A 10.0.7.129
+ A 10.0.7.130
+ A 10.0.7.131
+ A 10.0.7.132
+ A 10.0.7.133
+ A 10.0.7.134
+ A 10.0.7.135
+ A 10.0.7.136
+ A 10.0.7.137
+ A 10.0.7.138
+ A 10.0.7.139
+ A 10.0.7.140
+ A 10.0.7.141
+ A 10.0.7.142
+ A 10.0.7.143
+ A 10.0.7.144
+ A 10.0.7.145
+ A 10.0.7.146
+ A 10.0.7.147
+ A 10.0.7.148
+ A 10.0.7.149
+ A 10.0.7.150
+ A 10.0.7.151
+ A 10.0.7.152
+ A 10.0.7.153
+ A 10.0.7.154
+ A 10.0.7.155
+ A 10.0.7.156
+ A 10.0.7.157
+ A 10.0.7.158
+ A 10.0.7.159
+ A 10.0.7.160
+ A 10.0.7.161
+ A 10.0.7.162
+ A 10.0.7.163
+ A 10.0.7.164
+ A 10.0.7.165
+ A 10.0.7.166
+ A 10.0.7.167
+ A 10.0.7.168
+ A 10.0.7.169
+ A 10.0.7.170
+ A 10.0.7.171
+ A 10.0.7.172
+ A 10.0.7.173
+ A 10.0.7.174
+ A 10.0.7.175
+ A 10.0.7.176
+ A 10.0.7.177
+ A 10.0.7.178
+ A 10.0.7.179
+ A 10.0.7.180
+ A 10.0.7.181
+ A 10.0.7.182
+ A 10.0.7.183
+ A 10.0.7.184
+ A 10.0.7.185
+ A 10.0.7.186
+ A 10.0.7.187
+ A 10.0.7.188
+ A 10.0.7.189
+ A 10.0.7.190
+ A 10.0.7.191
+ A 10.0.7.192
+ A 10.0.7.193
+ A 10.0.7.194
+ A 10.0.7.195
+ A 10.0.7.196
+ A 10.0.7.197
+ A 10.0.7.198
+ A 10.0.7.199
+ A 10.0.7.200
+ A 10.0.7.201
+ A 10.0.7.202
+ A 10.0.7.203
+ A 10.0.7.204
+ A 10.0.7.205
+ A 10.0.7.206
+ A 10.0.7.207
+ A 10.0.7.208
+ A 10.0.7.209
+ A 10.0.7.210
+ A 10.0.7.211
+ A 10.0.7.212
+ A 10.0.7.213
+ A 10.0.7.214
+ A 10.0.7.215
+ A 10.0.7.216
+ A 10.0.7.217
+ A 10.0.7.218
+ A 10.0.7.219
+ A 10.0.7.220
+ A 10.0.7.221
+ A 10.0.7.222
+ A 10.0.7.223
+ A 10.0.7.224
+ A 10.0.7.225
+ A 10.0.7.226
+ A 10.0.7.227
+ A 10.0.7.228
+ A 10.0.7.229
+ A 10.0.7.230
+ A 10.0.7.231
+ A 10.0.7.232
+ A 10.0.7.233
+ A 10.0.7.234
+ A 10.0.7.235
+ A 10.0.7.236
+ A 10.0.7.237
+ A 10.0.7.238
+ A 10.0.7.239
+ A 10.0.7.240
+ A 10.0.7.241
+ A 10.0.7.242
+ A 10.0.7.243
+ A 10.0.7.244
+ A 10.0.7.245
+ A 10.0.7.246
+ A 10.0.7.247
+ A 10.0.7.248
+ A 10.0.7.249
+ A 10.0.7.250
+ A 10.0.7.251
+ A 10.0.7.252
+ A 10.0.7.253
+ A 10.0.7.254
+ A 10.0.7.255
+ A 10.0.8.0
+ A 10.0.8.1
+ A 10.0.8.2
+ A 10.0.8.3
+ A 10.0.8.4
+ A 10.0.8.5
+ A 10.0.8.6
+ A 10.0.8.7
+ A 10.0.8.8
+ A 10.0.8.9
+ A 10.0.8.10
+ A 10.0.8.11
+ A 10.0.8.12
+ A 10.0.8.13
+ A 10.0.8.14
+ A 10.0.8.15
+ A 10.0.8.16
+ A 10.0.8.17
+ A 10.0.8.18
+ A 10.0.8.19
+ A 10.0.8.20
+ A 10.0.8.21
+ A 10.0.8.22
+ A 10.0.8.23
+ A 10.0.8.24
+ A 10.0.8.25
+ A 10.0.8.26
+ A 10.0.8.27
+ A 10.0.8.28
+ A 10.0.8.29
+ A 10.0.8.30
+ A 10.0.8.31
+ A 10.0.8.32
+ A 10.0.8.33
+ A 10.0.8.34
+ A 10.0.8.35
+ A 10.0.8.36
+ A 10.0.8.37
+ A 10.0.8.38
+ A 10.0.8.39
+ A 10.0.8.40
+ A 10.0.8.41
+ A 10.0.8.42
+ A 10.0.8.43
+ A 10.0.8.44
+ A 10.0.8.45
+ A 10.0.8.46
+ A 10.0.8.47
+ A 10.0.8.48
+ A 10.0.8.49
+ A 10.0.8.50
+ A 10.0.8.51
+ A 10.0.8.52
+ A 10.0.8.53
+ A 10.0.8.54
+ A 10.0.8.55
+ A 10.0.8.56
+ A 10.0.8.57
+ A 10.0.8.58
+ A 10.0.8.59
+ A 10.0.8.60
+ A 10.0.8.61
+ A 10.0.8.62
+ A 10.0.8.63
+ A 10.0.8.64
+ A 10.0.8.65
+ A 10.0.8.66
+ A 10.0.8.67
+ A 10.0.8.68
+ A 10.0.8.69
+ A 10.0.8.70
+ A 10.0.8.71
+ A 10.0.8.72
+ A 10.0.8.73
+ A 10.0.8.74
+ A 10.0.8.75
+ A 10.0.8.76
+ A 10.0.8.77
+ A 10.0.8.78
+ A 10.0.8.79
+ A 10.0.8.80
+ A 10.0.8.81
+ A 10.0.8.82
+ A 10.0.8.83
+ A 10.0.8.84
+ A 10.0.8.85
+ A 10.0.8.86
+ A 10.0.8.87
+ A 10.0.8.88
+ A 10.0.8.89
+ A 10.0.8.90
+ A 10.0.8.91
+ A 10.0.8.92
+ A 10.0.8.93
+ A 10.0.8.94
+ A 10.0.8.95
+ A 10.0.8.96
+ A 10.0.8.97
+ A 10.0.8.98
+ A 10.0.8.99
+ A 10.0.8.100
+ A 10.0.8.101
+ A 10.0.8.102
+ A 10.0.8.103
+ A 10.0.8.104
+ A 10.0.8.105
+ A 10.0.8.106
+ A 10.0.8.107
+ A 10.0.8.108
+ A 10.0.8.109
+ A 10.0.8.110
+ A 10.0.8.111
+ A 10.0.8.112
+ A 10.0.8.113
+ A 10.0.8.114
+ A 10.0.8.115
+ A 10.0.8.116
+ A 10.0.8.117
+ A 10.0.8.118
+ A 10.0.8.119
+ A 10.0.8.120
+ A 10.0.8.121
+ A 10.0.8.122
+ A 10.0.8.123
+ A 10.0.8.124
+ A 10.0.8.125
+ A 10.0.8.126
+ A 10.0.8.127
+ A 10.0.8.128
+ A 10.0.8.129
+ A 10.0.8.130
+ A 10.0.8.131
+ A 10.0.8.132
+ A 10.0.8.133
+ A 10.0.8.134
+ A 10.0.8.135
+ A 10.0.8.136
+ A 10.0.8.137
+ A 10.0.8.138
+ A 10.0.8.139
+ A 10.0.8.140
+ A 10.0.8.141
+ A 10.0.8.142
+ A 10.0.8.143
+ A 10.0.8.144
+ A 10.0.8.145
+ A 10.0.8.146
+ A 10.0.8.147
+ A 10.0.8.148
+ A 10.0.8.149
+ A 10.0.8.150
+ A 10.0.8.151
+ A 10.0.8.152
+ A 10.0.8.153
+ A 10.0.8.154
+ A 10.0.8.155
+ A 10.0.8.156
+ A 10.0.8.157
+ A 10.0.8.158
+ A 10.0.8.159
+ A 10.0.8.160
+ A 10.0.8.161
+ A 10.0.8.162
+ A 10.0.8.163
+ A 10.0.8.164
+ A 10.0.8.165
+ A 10.0.8.166
+ A 10.0.8.167
+ A 10.0.8.168
+ A 10.0.8.169
+ A 10.0.8.170
+ A 10.0.8.171
+ A 10.0.8.172
+ A 10.0.8.173
+ A 10.0.8.174
+ A 10.0.8.175
+ A 10.0.8.176
+ A 10.0.8.177
+ A 10.0.8.178
+ A 10.0.8.179
+ A 10.0.8.180
+ A 10.0.8.181
+ A 10.0.8.182
+ A 10.0.8.183
+ A 10.0.8.184
+ A 10.0.8.185
+ A 10.0.8.186
+ A 10.0.8.187
+ A 10.0.8.188
+ A 10.0.8.189
+ A 10.0.8.190
+ A 10.0.8.191
+ A 10.0.8.192
+ A 10.0.8.193
+ A 10.0.8.194
+ A 10.0.8.195
+ A 10.0.8.196
+ A 10.0.8.197
+ A 10.0.8.198
+ A 10.0.8.199
+ A 10.0.8.200
+ A 10.0.8.201
+ A 10.0.8.202
+ A 10.0.8.203
+ A 10.0.8.204
+ A 10.0.8.205
+ A 10.0.8.206
+ A 10.0.8.207
+ A 10.0.8.208
+ A 10.0.8.209
+ A 10.0.8.210
+ A 10.0.8.211
+ A 10.0.8.212
+ A 10.0.8.213
+ A 10.0.8.214
+ A 10.0.8.215
+ A 10.0.8.216
+ A 10.0.8.217
+ A 10.0.8.218
+ A 10.0.8.219
+ A 10.0.8.220
+ A 10.0.8.221
+ A 10.0.8.222
+ A 10.0.8.223
+ A 10.0.8.224
+ A 10.0.8.225
+ A 10.0.8.226
+ A 10.0.8.227
+ A 10.0.8.228
+ A 10.0.8.229
+ A 10.0.8.230
+ A 10.0.8.231
+ A 10.0.8.232
+ A 10.0.8.233
+ A 10.0.8.234
+ A 10.0.8.235
+ A 10.0.8.236
+ A 10.0.8.237
+ A 10.0.8.238
+ A 10.0.8.239
+ A 10.0.8.240
+ A 10.0.8.241
+ A 10.0.8.242
+ A 10.0.8.243
+ A 10.0.8.244
+ A 10.0.8.245
+ A 10.0.8.246
+ A 10.0.8.247
+ A 10.0.8.248
+ A 10.0.8.249
+ A 10.0.8.250
+ A 10.0.8.251
+ A 10.0.8.252
+ A 10.0.8.253
+ A 10.0.8.254
+ A 10.0.8.255
+ A 10.0.9.0
+ A 10.0.9.1
+ A 10.0.9.2
+ A 10.0.9.3
+ A 10.0.9.4
+ A 10.0.9.5
+ A 10.0.9.6
+ A 10.0.9.7
+ A 10.0.9.8
+ A 10.0.9.9
+ A 10.0.9.10
+ A 10.0.9.11
+ A 10.0.9.12
+ A 10.0.9.13
+ A 10.0.9.14
+ A 10.0.9.15
+ A 10.0.9.16
+ A 10.0.9.17
+ A 10.0.9.18
+ A 10.0.9.19
+ A 10.0.9.20
+ A 10.0.9.21
+ A 10.0.9.22
+ A 10.0.9.23
+ A 10.0.9.24
+ A 10.0.9.25
+ A 10.0.9.26
+ A 10.0.9.27
+ A 10.0.9.28
+ A 10.0.9.29
+ A 10.0.9.30
+ A 10.0.9.31
+ A 10.0.9.32
+ A 10.0.9.33
+ A 10.0.9.34
+ A 10.0.9.35
+ A 10.0.9.36
+ A 10.0.9.37
+ A 10.0.9.38
+ A 10.0.9.39
+ A 10.0.9.40
+ A 10.0.9.41
+ A 10.0.9.42
+ A 10.0.9.43
+ A 10.0.9.44
+ A 10.0.9.45
+ A 10.0.9.46
+ A 10.0.9.47
+ A 10.0.9.48
+ A 10.0.9.49
+ A 10.0.9.50
+ A 10.0.9.51
+ A 10.0.9.52
+ A 10.0.9.53
+ A 10.0.9.54
+ A 10.0.9.55
+ A 10.0.9.56
+ A 10.0.9.57
+ A 10.0.9.58
+ A 10.0.9.59
+ A 10.0.9.60
+ A 10.0.9.61
+ A 10.0.9.62
+ A 10.0.9.63
+ A 10.0.9.64
+ A 10.0.9.65
+ A 10.0.9.66
+ A 10.0.9.67
+ A 10.0.9.68
+ A 10.0.9.69
+ A 10.0.9.70
+ A 10.0.9.71
+ A 10.0.9.72
+ A 10.0.9.73
+ A 10.0.9.74
+ A 10.0.9.75
+ A 10.0.9.76
+ A 10.0.9.77
+ A 10.0.9.78
+ A 10.0.9.79
+ A 10.0.9.80
+ A 10.0.9.81
+ A 10.0.9.82
+ A 10.0.9.83
+ A 10.0.9.84
+ A 10.0.9.85
+ A 10.0.9.86
+ A 10.0.9.87
+ A 10.0.9.88
+ A 10.0.9.89
+ A 10.0.9.90
+ A 10.0.9.91
+ A 10.0.9.92
+ A 10.0.9.93
+ A 10.0.9.94
+ A 10.0.9.95
+ A 10.0.9.96
+ A 10.0.9.97
+ A 10.0.9.98
+ A 10.0.9.99
+ A 10.0.9.100
+ A 10.0.9.101
+ A 10.0.9.102
+ A 10.0.9.103
+ A 10.0.9.104
+ A 10.0.9.105
+ A 10.0.9.106
+ A 10.0.9.107
+ A 10.0.9.108
+ A 10.0.9.109
+ A 10.0.9.110
+ A 10.0.9.111
+ A 10.0.9.112
+ A 10.0.9.113
+ A 10.0.9.114
+ A 10.0.9.115
+ A 10.0.9.116
+ A 10.0.9.117
+ A 10.0.9.118
+ A 10.0.9.119
+ A 10.0.9.120
+ A 10.0.9.121
+ A 10.0.9.122
+ A 10.0.9.123
+ A 10.0.9.124
+ A 10.0.9.125
+ A 10.0.9.126
+ A 10.0.9.127
+ A 10.0.9.128
+ A 10.0.9.129
+ A 10.0.9.130
+ A 10.0.9.131
+ A 10.0.9.132
+ A 10.0.9.133
+ A 10.0.9.134
+ A 10.0.9.135
+ A 10.0.9.136
+ A 10.0.9.137
+ A 10.0.9.138
+ A 10.0.9.139
+ A 10.0.9.140
+ A 10.0.9.141
+ A 10.0.9.142
+ A 10.0.9.143
+ A 10.0.9.144
+ A 10.0.9.145
+ A 10.0.9.146
+ A 10.0.9.147
+ A 10.0.9.148
+ A 10.0.9.149
+ A 10.0.9.150
+ A 10.0.9.151
+ A 10.0.9.152
+ A 10.0.9.153
+ A 10.0.9.154
+ A 10.0.9.155
+ A 10.0.9.156
+ A 10.0.9.157
+ A 10.0.9.158
+ A 10.0.9.159
+ A 10.0.9.160
+ A 10.0.9.161
+ A 10.0.9.162
+ A 10.0.9.163
+ A 10.0.9.164
+ A 10.0.9.165
+ A 10.0.9.166
+ A 10.0.9.167
+ A 10.0.9.168
+ A 10.0.9.169
+ A 10.0.9.170
+ A 10.0.9.171
+ A 10.0.9.172
+ A 10.0.9.173
+ A 10.0.9.174
+ A 10.0.9.175
+ A 10.0.9.176
+ A 10.0.9.177
+ A 10.0.9.178
+ A 10.0.9.179
+ A 10.0.9.180
+ A 10.0.9.181
+ A 10.0.9.182
+ A 10.0.9.183
+ A 10.0.9.184
+ A 10.0.9.185
+ A 10.0.9.186
+ A 10.0.9.187
+ A 10.0.9.188
+ A 10.0.9.189
+ A 10.0.9.190
+ A 10.0.9.191
+ A 10.0.9.192
+ A 10.0.9.193
+ A 10.0.9.194
+ A 10.0.9.195
+ A 10.0.9.196
+ A 10.0.9.197
+ A 10.0.9.198
+ A 10.0.9.199
+ A 10.0.9.200
+ A 10.0.9.201
+ A 10.0.9.202
+ A 10.0.9.203
+ A 10.0.9.204
+ A 10.0.9.205
+ A 10.0.9.206
+ A 10.0.9.207
+ A 10.0.9.208
+ A 10.0.9.209
+ A 10.0.9.210
+ A 10.0.9.211
+ A 10.0.9.212
+ A 10.0.9.213
+ A 10.0.9.214
+ A 10.0.9.215
+ A 10.0.9.216
+ A 10.0.9.217
+ A 10.0.9.218
+ A 10.0.9.219
+ A 10.0.9.220
+ A 10.0.9.221
+ A 10.0.9.222
+ A 10.0.9.223
+ A 10.0.9.224
+ A 10.0.9.225
+ A 10.0.9.226
+ A 10.0.9.227
+ A 10.0.9.228
+ A 10.0.9.229
+ A 10.0.9.230
+ A 10.0.9.231
+ A 10.0.9.232
+ A 10.0.9.233
+ A 10.0.9.234
+ A 10.0.9.235
+ A 10.0.9.236
+ A 10.0.9.237
+ A 10.0.9.238
+ A 10.0.9.239
+ A 10.0.9.240
+ A 10.0.9.241
+ A 10.0.9.242
+ A 10.0.9.243
+ A 10.0.9.244
+ A 10.0.9.245
+ A 10.0.9.246
+ A 10.0.9.247
+ A 10.0.9.248
+ A 10.0.9.249
+ A 10.0.9.250
+ A 10.0.9.251
+ A 10.0.9.252
+ A 10.0.9.253
+ A 10.0.9.254
+ A 10.0.9.255
+ A 10.0.10.0
+ A 10.0.10.1
+ A 10.0.10.2
+ A 10.0.10.3
+ A 10.0.10.4
+ A 10.0.10.5
+ A 10.0.10.6
+ A 10.0.10.7
+ A 10.0.10.8
+ A 10.0.10.9
+ A 10.0.10.10
+ A 10.0.10.11
+ A 10.0.10.12
+ A 10.0.10.13
+ A 10.0.10.14
+ A 10.0.10.15
+ A 10.0.10.16
+ A 10.0.10.17
+ A 10.0.10.18
+ A 10.0.10.19
+ A 10.0.10.20
+ A 10.0.10.21
+ A 10.0.10.22
+ A 10.0.10.23
+ A 10.0.10.24
+ A 10.0.10.25
+ A 10.0.10.26
+ A 10.0.10.27
+ A 10.0.10.28
+ A 10.0.10.29
+ A 10.0.10.30
+ A 10.0.10.31
+ A 10.0.10.32
+ A 10.0.10.33
+ A 10.0.10.34
+ A 10.0.10.35
+ A 10.0.10.36
+ A 10.0.10.37
+ A 10.0.10.38
+ A 10.0.10.39
+ A 10.0.10.40
+ A 10.0.10.41
+ A 10.0.10.42
+ A 10.0.10.43
+ A 10.0.10.44
+ A 10.0.10.45
+ A 10.0.10.46
+ A 10.0.10.47
+ A 10.0.10.48
+ A 10.0.10.49
+ A 10.0.10.50
+ A 10.0.10.51
+ A 10.0.10.52
+ A 10.0.10.53
+ A 10.0.10.54
+ A 10.0.10.55
+ A 10.0.10.56
+ A 10.0.10.57
+ A 10.0.10.58
+ A 10.0.10.59
+ A 10.0.10.60
+ A 10.0.10.61
+ A 10.0.10.62
+ A 10.0.10.63
+ A 10.0.10.64
+ A 10.0.10.65
+ A 10.0.10.66
+ A 10.0.10.67
+ A 10.0.10.68
+ A 10.0.10.69
+ A 10.0.10.70
+ A 10.0.10.71
+ A 10.0.10.72
+ A 10.0.10.73
+ A 10.0.10.74
+ A 10.0.10.75
+ A 10.0.10.76
+ A 10.0.10.77
+ A 10.0.10.78
+ A 10.0.10.79
+ A 10.0.10.80
+ A 10.0.10.81
+ A 10.0.10.82
+ A 10.0.10.83
+ A 10.0.10.84
+ A 10.0.10.85
+ A 10.0.10.86
+ A 10.0.10.87
+ A 10.0.10.88
+ A 10.0.10.89
+ A 10.0.10.90
+ A 10.0.10.91
+ A 10.0.10.92
+ A 10.0.10.93
+ A 10.0.10.94
+ A 10.0.10.95
+ A 10.0.10.96
+ A 10.0.10.97
+ A 10.0.10.98
+ A 10.0.10.99
+ A 10.0.10.100
+ A 10.0.10.101
+ A 10.0.10.102
+ A 10.0.10.103
+ A 10.0.10.104
+ A 10.0.10.105
+ A 10.0.10.106
+ A 10.0.10.107
+ A 10.0.10.108
+ A 10.0.10.109
+ A 10.0.10.110
+ A 10.0.10.111
+ A 10.0.10.112
+ A 10.0.10.113
+ A 10.0.10.114
+ A 10.0.10.115
+ A 10.0.10.116
+ A 10.0.10.117
+ A 10.0.10.118
+ A 10.0.10.119
+ A 10.0.10.120
+ A 10.0.10.121
+ A 10.0.10.122
+ A 10.0.10.123
+ A 10.0.10.124
+ A 10.0.10.125
+ A 10.0.10.126
+ A 10.0.10.127
+ A 10.0.10.128
+ A 10.0.10.129
+ A 10.0.10.130
+ A 10.0.10.131
+ A 10.0.10.132
+ A 10.0.10.133
+ A 10.0.10.134
+ A 10.0.10.135
+ A 10.0.10.136
+ A 10.0.10.137
+ A 10.0.10.138
+ A 10.0.10.139
+ A 10.0.10.140
+ A 10.0.10.141
+ A 10.0.10.142
+ A 10.0.10.143
+ A 10.0.10.144
+ A 10.0.10.145
+ A 10.0.10.146
+ A 10.0.10.147
+ A 10.0.10.148
+ A 10.0.10.149
+ A 10.0.10.150
+ A 10.0.10.151
+ A 10.0.10.152
+ A 10.0.10.153
+ A 10.0.10.154
+ A 10.0.10.155
+ A 10.0.10.156
+ A 10.0.10.157
+ A 10.0.10.158
+ A 10.0.10.159
+ A 10.0.10.160
+ A 10.0.10.161
+ A 10.0.10.162
+ A 10.0.10.163
+ A 10.0.10.164
+ A 10.0.10.165
+ A 10.0.10.166
+ A 10.0.10.167
+ A 10.0.10.168
+ A 10.0.10.169
+ A 10.0.10.170
+ A 10.0.10.171
+ A 10.0.10.172
+ A 10.0.10.173
+ A 10.0.10.174
+ A 10.0.10.175
+ A 10.0.10.176
+ A 10.0.10.177
+ A 10.0.10.178
+ A 10.0.10.179
+ A 10.0.10.180
+ A 10.0.10.181
+ A 10.0.10.182
+ A 10.0.10.183
+ A 10.0.10.184
+ A 10.0.10.185
+ A 10.0.10.186
+ A 10.0.10.187
+ A 10.0.10.188
+ A 10.0.10.189
+ A 10.0.10.190
+ A 10.0.10.191
+ A 10.0.10.192
+ A 10.0.10.193
+ A 10.0.10.194
+ A 10.0.10.195
+ A 10.0.10.196
+ A 10.0.10.197
+ A 10.0.10.198
+ A 10.0.10.199
+ A 10.0.10.200
+ A 10.0.10.201
+ A 10.0.10.202
+ A 10.0.10.203
+ A 10.0.10.204
+ A 10.0.10.205
+ A 10.0.10.206
+ A 10.0.10.207
+ A 10.0.10.208
+ A 10.0.10.209
+ A 10.0.10.210
+ A 10.0.10.211
+ A 10.0.10.212
+ A 10.0.10.213
+ A 10.0.10.214
+ A 10.0.10.215
+ A 10.0.10.216
+ A 10.0.10.217
+ A 10.0.10.218
+ A 10.0.10.219
+ A 10.0.10.220
+ A 10.0.10.221
+ A 10.0.10.222
+ A 10.0.10.223
+ A 10.0.10.224
+ A 10.0.10.225
+ A 10.0.10.226
+ A 10.0.10.227
+ A 10.0.10.228
+ A 10.0.10.229
+ A 10.0.10.230
+ A 10.0.10.231
+ A 10.0.10.232
+ A 10.0.10.233
+ A 10.0.10.234
+ A 10.0.10.235
+ A 10.0.10.236
+ A 10.0.10.237
+ A 10.0.10.238
+ A 10.0.10.239
+ A 10.0.10.240
+ A 10.0.10.241
+ A 10.0.10.242
+ A 10.0.10.243
+ A 10.0.10.244
+ A 10.0.10.245
+ A 10.0.10.246
+ A 10.0.10.247
+ A 10.0.10.248
+ A 10.0.10.249
+ A 10.0.10.250
+ A 10.0.10.251
+ A 10.0.10.252
+ A 10.0.10.253
+ A 10.0.10.254
+ A 10.0.10.255
+ A 10.0.11.0
+ A 10.0.11.1
+ A 10.0.11.2
+ A 10.0.11.3
+ A 10.0.11.4
+ A 10.0.11.5
+ A 10.0.11.6
+ A 10.0.11.7
+ A 10.0.11.8
+ A 10.0.11.9
+ A 10.0.11.10
+ A 10.0.11.11
+ A 10.0.11.12
+ A 10.0.11.13
+ A 10.0.11.14
+ A 10.0.11.15
+ A 10.0.11.16
+ A 10.0.11.17
+ A 10.0.11.18
+ A 10.0.11.19
+ A 10.0.11.20
+ A 10.0.11.21
+ A 10.0.11.22
+ A 10.0.11.23
+ A 10.0.11.24
+ A 10.0.11.25
+ A 10.0.11.26
+ A 10.0.11.27
+ A 10.0.11.28
+ A 10.0.11.29
+ A 10.0.11.30
+ A 10.0.11.31
+ A 10.0.11.32
+ A 10.0.11.33
+ A 10.0.11.34
+ A 10.0.11.35
+ A 10.0.11.36
+ A 10.0.11.37
+ A 10.0.11.38
+ A 10.0.11.39
+ A 10.0.11.40
+ A 10.0.11.41
+ A 10.0.11.42
+ A 10.0.11.43
+ A 10.0.11.44
+ A 10.0.11.45
+ A 10.0.11.46
+ A 10.0.11.47
+ A 10.0.11.48
+ A 10.0.11.49
+ A 10.0.11.50
+ A 10.0.11.51
+ A 10.0.11.52
+ A 10.0.11.53
+ A 10.0.11.54
+ A 10.0.11.55
+ A 10.0.11.56
+ A 10.0.11.57
+ A 10.0.11.58
+ A 10.0.11.59
+ A 10.0.11.60
+ A 10.0.11.61
+ A 10.0.11.62
+ A 10.0.11.63
+ A 10.0.11.64
+ A 10.0.11.65
+ A 10.0.11.66
+ A 10.0.11.67
+ A 10.0.11.68
+ A 10.0.11.69
+ A 10.0.11.70
+ A 10.0.11.71
+ A 10.0.11.72
+ A 10.0.11.73
+ A 10.0.11.74
+ A 10.0.11.75
+ A 10.0.11.76
+ A 10.0.11.77
+ A 10.0.11.78
+ A 10.0.11.79
+ A 10.0.11.80
+ A 10.0.11.81
+ A 10.0.11.82
+ A 10.0.11.83
+ A 10.0.11.84
+ A 10.0.11.85
+ A 10.0.11.86
+ A 10.0.11.87
+ A 10.0.11.88
+ A 10.0.11.89
+ A 10.0.11.90
+ A 10.0.11.91
+ A 10.0.11.92
+ A 10.0.11.93
+ A 10.0.11.94
+ A 10.0.11.95
+ A 10.0.11.96
+ A 10.0.11.97
+ A 10.0.11.98
+ A 10.0.11.99
+ A 10.0.11.100
+ A 10.0.11.101
+ A 10.0.11.102
+ A 10.0.11.103
+ A 10.0.11.104
+ A 10.0.11.105
+ A 10.0.11.106
+ A 10.0.11.107
+ A 10.0.11.108
+ A 10.0.11.109
+ A 10.0.11.110
+ A 10.0.11.111
+ A 10.0.11.112
+ A 10.0.11.113
+ A 10.0.11.114
+ A 10.0.11.115
+ A 10.0.11.116
+ A 10.0.11.117
+ A 10.0.11.118
+ A 10.0.11.119
+ A 10.0.11.120
+ A 10.0.11.121
+ A 10.0.11.122
+ A 10.0.11.123
+ A 10.0.11.124
+ A 10.0.11.125
+ A 10.0.11.126
+ A 10.0.11.127
+ A 10.0.11.128
+ A 10.0.11.129
+ A 10.0.11.130
+ A 10.0.11.131
+ A 10.0.11.132
+ A 10.0.11.133
+ A 10.0.11.134
+ A 10.0.11.135
+ A 10.0.11.136
+ A 10.0.11.137
+ A 10.0.11.138
+ A 10.0.11.139
+ A 10.0.11.140
+ A 10.0.11.141
+ A 10.0.11.142
+ A 10.0.11.143
+ A 10.0.11.144
+ A 10.0.11.145
+ A 10.0.11.146
+ A 10.0.11.147
+ A 10.0.11.148
+ A 10.0.11.149
+ A 10.0.11.150
+ A 10.0.11.151
+ A 10.0.11.152
+ A 10.0.11.153
+ A 10.0.11.154
+ A 10.0.11.155
+ A 10.0.11.156
+ A 10.0.11.157
+ A 10.0.11.158
+ A 10.0.11.159
+ A 10.0.11.160
+ A 10.0.11.161
+ A 10.0.11.162
+ A 10.0.11.163
+ A 10.0.11.164
+ A 10.0.11.165
+ A 10.0.11.166
+ A 10.0.11.167
+ A 10.0.11.168
+ A 10.0.11.169
+ A 10.0.11.170
+ A 10.0.11.171
+ A 10.0.11.172
+ A 10.0.11.173
+ A 10.0.11.174
+ A 10.0.11.175
+ A 10.0.11.176
+ A 10.0.11.177
+ A 10.0.11.178
+ A 10.0.11.179
+ A 10.0.11.180
+ A 10.0.11.181
+ A 10.0.11.182
+ A 10.0.11.183
+ A 10.0.11.184
+ A 10.0.11.185
+ A 10.0.11.186
+ A 10.0.11.187
+ A 10.0.11.188
+ A 10.0.11.189
+ A 10.0.11.190
+ A 10.0.11.191
+ A 10.0.11.192
+ A 10.0.11.193
+ A 10.0.11.194
+ A 10.0.11.195
+ A 10.0.11.196
+ A 10.0.11.197
+ A 10.0.11.198
+ A 10.0.11.199
+ A 10.0.11.200
+ A 10.0.11.201
+ A 10.0.11.202
+ A 10.0.11.203
+ A 10.0.11.204
+ A 10.0.11.205
+ A 10.0.11.206
+ A 10.0.11.207
+ A 10.0.11.208
+ A 10.0.11.209
+ A 10.0.11.210
+ A 10.0.11.211
+ A 10.0.11.212
+ A 10.0.11.213
+ A 10.0.11.214
+ A 10.0.11.215
+ A 10.0.11.216
+ A 10.0.11.217
+ A 10.0.11.218
+ A 10.0.11.219
+ A 10.0.11.220
+ A 10.0.11.221
+ A 10.0.11.222
+ A 10.0.11.223
+ A 10.0.11.224
+ A 10.0.11.225
+ A 10.0.11.226
+ A 10.0.11.227
+ A 10.0.11.228
+ A 10.0.11.229
+ A 10.0.11.230
+ A 10.0.11.231
+ A 10.0.11.232
+ A 10.0.11.233
+ A 10.0.11.234
+ A 10.0.11.235
+ A 10.0.11.236
+ A 10.0.11.237
+ A 10.0.11.238
+ A 10.0.11.239
+ A 10.0.11.240
+ A 10.0.11.241
+ A 10.0.11.242
+ A 10.0.11.243
+ A 10.0.11.244
+ A 10.0.11.245
+ A 10.0.11.246
+ A 10.0.11.247
+ A 10.0.11.248
+ A 10.0.11.249
+ A 10.0.11.250
+ A 10.0.11.251
+ A 10.0.11.252
+ A 10.0.11.253
+ A 10.0.11.254
+ A 10.0.11.255
+ A 10.0.12.0
+ A 10.0.12.1
+ A 10.0.12.2
+ A 10.0.12.3
+ A 10.0.12.4
+ A 10.0.12.5
+ A 10.0.12.6
+ A 10.0.12.7
+ A 10.0.12.8
+ A 10.0.12.9
+ A 10.0.12.10
+ A 10.0.12.11
+ A 10.0.12.12
+ A 10.0.12.13
+ A 10.0.12.14
+ A 10.0.12.15
+ A 10.0.12.16
+ A 10.0.12.17
+ A 10.0.12.18
+ A 10.0.12.19
+ A 10.0.12.20
+ A 10.0.12.21
+ A 10.0.12.22
+ A 10.0.12.23
+ A 10.0.12.24
+ A 10.0.12.25
+ A 10.0.12.26
+ A 10.0.12.27
+ A 10.0.12.28
+ A 10.0.12.29
+ A 10.0.12.30
+ A 10.0.12.31
+ A 10.0.12.32
+ A 10.0.12.33
+ A 10.0.12.34
+ A 10.0.12.35
+ A 10.0.12.36
+ A 10.0.12.37
+ A 10.0.12.38
+ A 10.0.12.39
+ A 10.0.12.40
+ A 10.0.12.41
+ A 10.0.12.42
+ A 10.0.12.43
+ A 10.0.12.44
+ A 10.0.12.45
+ A 10.0.12.46
+ A 10.0.12.47
+ A 10.0.12.48
+ A 10.0.12.49
+ A 10.0.12.50
+ A 10.0.12.51
+ A 10.0.12.52
+ A 10.0.12.53
+ A 10.0.12.54
+ A 10.0.12.55
+ A 10.0.12.56
+ A 10.0.12.57
+ A 10.0.12.58
+ A 10.0.12.59
+ A 10.0.12.60
+ A 10.0.12.61
+ A 10.0.12.62
+ A 10.0.12.63
+ A 10.0.12.64
+ A 10.0.12.65
+ A 10.0.12.66
+ A 10.0.12.67
+ A 10.0.12.68
+ A 10.0.12.69
+ A 10.0.12.70
+ A 10.0.12.71
+ A 10.0.12.72
+ A 10.0.12.73
+ A 10.0.12.74
+ A 10.0.12.75
+ A 10.0.12.76
+ A 10.0.12.77
+ A 10.0.12.78
+ A 10.0.12.79
+ A 10.0.12.80
+ A 10.0.12.81
+ A 10.0.12.82
+ A 10.0.12.83
+ A 10.0.12.84
+ A 10.0.12.85
+ A 10.0.12.86
+ A 10.0.12.87
+ A 10.0.12.88
+ A 10.0.12.89
+ A 10.0.12.90
+ A 10.0.12.91
+ A 10.0.12.92
+ A 10.0.12.93
+ A 10.0.12.94
+ A 10.0.12.95
+ A 10.0.12.96
+ A 10.0.12.97
+ A 10.0.12.98
+ A 10.0.12.99
+ A 10.0.12.100
+ A 10.0.12.101
+ A 10.0.12.102
+ A 10.0.12.103
+ A 10.0.12.104
+ A 10.0.12.105
+ A 10.0.12.106
+ A 10.0.12.107
+ A 10.0.12.108
+ A 10.0.12.109
+ A 10.0.12.110
+ A 10.0.12.111
+ A 10.0.12.112
+ A 10.0.12.113
+ A 10.0.12.114
+ A 10.0.12.115
+ A 10.0.12.116
+ A 10.0.12.117
+ A 10.0.12.118
+ A 10.0.12.119
+ A 10.0.12.120
+ A 10.0.12.121
+ A 10.0.12.122
+ A 10.0.12.123
+ A 10.0.12.124
+ A 10.0.12.125
+ A 10.0.12.126
+ A 10.0.12.127
+ A 10.0.12.128
+ A 10.0.12.129
+ A 10.0.12.130
+ A 10.0.12.131
+ A 10.0.12.132
+ A 10.0.12.133
+ A 10.0.12.134
+ A 10.0.12.135
+ A 10.0.12.136
+ A 10.0.12.137
+ A 10.0.12.138
+ A 10.0.12.139
+ A 10.0.12.140
+ A 10.0.12.141
+ A 10.0.12.142
+ A 10.0.12.143
+ A 10.0.12.144
+ A 10.0.12.145
+ A 10.0.12.146
+ A 10.0.12.147
+ A 10.0.12.148
+ A 10.0.12.149
+ A 10.0.12.150
+ A 10.0.12.151
+ A 10.0.12.152
+ A 10.0.12.153
+ A 10.0.12.154
+ A 10.0.12.155
+ A 10.0.12.156
+ A 10.0.12.157
+ A 10.0.12.158
+ A 10.0.12.159
+ A 10.0.12.160
+ A 10.0.12.161
+ A 10.0.12.162
+ A 10.0.12.163
+ A 10.0.12.164
+ A 10.0.12.165
+ A 10.0.12.166
+ A 10.0.12.167
+ A 10.0.12.168
+ A 10.0.12.169
+ A 10.0.12.170
+ A 10.0.12.171
+ A 10.0.12.172
+ A 10.0.12.173
+ A 10.0.12.174
+ A 10.0.12.175
+ A 10.0.12.176
+ A 10.0.12.177
+ A 10.0.12.178
+ A 10.0.12.179
+ A 10.0.12.180
+ A 10.0.12.181
+ A 10.0.12.182
+ A 10.0.12.183
+ A 10.0.12.184
+ A 10.0.12.185
+ A 10.0.12.186
+ A 10.0.12.187
+ A 10.0.12.188
+ A 10.0.12.189
+ A 10.0.12.190
+ A 10.0.12.191
+ A 10.0.12.192
+ A 10.0.12.193
+ A 10.0.12.194
+ A 10.0.12.195
+ A 10.0.12.196
+ A 10.0.12.197
+ A 10.0.12.198
+ A 10.0.12.199
+ A 10.0.12.200
+ A 10.0.12.201
+ A 10.0.12.202
+ A 10.0.12.203
+ A 10.0.12.204
+ A 10.0.12.205
+ A 10.0.12.206
+ A 10.0.12.207
+ A 10.0.12.208
+ A 10.0.12.209
+ A 10.0.12.210
+ A 10.0.12.211
+ A 10.0.12.212
+ A 10.0.12.213
+ A 10.0.12.214
+ A 10.0.12.215
+ A 10.0.12.216
+ A 10.0.12.217
+ A 10.0.12.218
+ A 10.0.12.219
+ A 10.0.12.220
+ A 10.0.12.221
+ A 10.0.12.222
+ A 10.0.12.223
+ A 10.0.12.224
+ A 10.0.12.225
+ A 10.0.12.226
+ A 10.0.12.227
+ A 10.0.12.228
+ A 10.0.12.229
+ A 10.0.12.230
+ A 10.0.12.231
+ A 10.0.12.232
+ A 10.0.12.233
+ A 10.0.12.234
+ A 10.0.12.235
+ A 10.0.12.236
+ A 10.0.12.237
+ A 10.0.12.238
+ A 10.0.12.239
+ A 10.0.12.240
+ A 10.0.12.241
+ A 10.0.12.242
+ A 10.0.12.243
+ A 10.0.12.244
+ A 10.0.12.245
+ A 10.0.12.246
+ A 10.0.12.247
+ A 10.0.12.248
+ A 10.0.12.249
+ A 10.0.12.250
+ A 10.0.12.251
+ A 10.0.12.252
+ A 10.0.12.253
+ A 10.0.12.254
+ A 10.0.12.255
+ A 10.0.13.0
+ A 10.0.13.1
+ A 10.0.13.2
+ A 10.0.13.3
+ A 10.0.13.4
+ A 10.0.13.5
+ A 10.0.13.6
+ A 10.0.13.7
+ A 10.0.13.8
+ A 10.0.13.9
+ A 10.0.13.10
+ A 10.0.13.11
+ A 10.0.13.12
+ A 10.0.13.13
+ A 10.0.13.14
+ A 10.0.13.15
+ A 10.0.13.16
+ A 10.0.13.17
+ A 10.0.13.18
+ A 10.0.13.19
+ A 10.0.13.20
+ A 10.0.13.21
+ A 10.0.13.22
+ A 10.0.13.23
+ A 10.0.13.24
+ A 10.0.13.25
+ A 10.0.13.26
+ A 10.0.13.27
+ A 10.0.13.28
+ A 10.0.13.29
+ A 10.0.13.30
+ A 10.0.13.31
+ A 10.0.13.32
+ A 10.0.13.33
+ A 10.0.13.34
+ A 10.0.13.35
+ A 10.0.13.36
+ A 10.0.13.37
+ A 10.0.13.38
+ A 10.0.13.39
+ A 10.0.13.40
+ A 10.0.13.41
+ A 10.0.13.42
+ A 10.0.13.43
+ A 10.0.13.44
+ A 10.0.13.45
+ A 10.0.13.46
+ A 10.0.13.47
+ A 10.0.13.48
+ A 10.0.13.49
+ A 10.0.13.50
+ A 10.0.13.51
+ A 10.0.13.52
+ A 10.0.13.53
+ A 10.0.13.54
+ A 10.0.13.55
+ A 10.0.13.56
+ A 10.0.13.57
+ A 10.0.13.58
+ A 10.0.13.59
+ A 10.0.13.60
+ A 10.0.13.61
+ A 10.0.13.62
+ A 10.0.13.63
+ A 10.0.13.64
+ A 10.0.13.65
+ A 10.0.13.66
+ A 10.0.13.67
+ A 10.0.13.68
+ A 10.0.13.69
+ A 10.0.13.70
+ A 10.0.13.71
+ A 10.0.13.72
+ A 10.0.13.73
+ A 10.0.13.74
+ A 10.0.13.75
+ A 10.0.13.76
+ A 10.0.13.77
+ A 10.0.13.78
+ A 10.0.13.79
+ A 10.0.13.80
+ A 10.0.13.81
+ A 10.0.13.82
+ A 10.0.13.83
+ A 10.0.13.84
+ A 10.0.13.85
+ A 10.0.13.86
+ A 10.0.13.87
+ A 10.0.13.88
+ A 10.0.13.89
+ A 10.0.13.90
+ A 10.0.13.91
+ A 10.0.13.92
+ A 10.0.13.93
+ A 10.0.13.94
+ A 10.0.13.95
+ A 10.0.13.96
+ A 10.0.13.97
+ A 10.0.13.98
+ A 10.0.13.99
+ A 10.0.13.100
+ A 10.0.13.101
+ A 10.0.13.102
+ A 10.0.13.103
+ A 10.0.13.104
+ A 10.0.13.105
+ A 10.0.13.106
+ A 10.0.13.107
+ A 10.0.13.108
+ A 10.0.13.109
+ A 10.0.13.110
+ A 10.0.13.111
+ A 10.0.13.112
+ A 10.0.13.113
+ A 10.0.13.114
+ A 10.0.13.115
+ A 10.0.13.116
+ A 10.0.13.117
+ A 10.0.13.118
+ A 10.0.13.119
+ A 10.0.13.120
+ A 10.0.13.121
+ A 10.0.13.122
+ A 10.0.13.123
+ A 10.0.13.124
+ A 10.0.13.125
+ A 10.0.13.126
+ A 10.0.13.127
+ A 10.0.13.128
+ A 10.0.13.129
+ A 10.0.13.130
+ A 10.0.13.131
+ A 10.0.13.132
+ A 10.0.13.133
+ A 10.0.13.134
+ A 10.0.13.135
+ A 10.0.13.136
+ A 10.0.13.137
+ A 10.0.13.138
+ A 10.0.13.139
+ A 10.0.13.140
+ A 10.0.13.141
+ A 10.0.13.142
+ A 10.0.13.143
+ A 10.0.13.144
+ A 10.0.13.145
+ A 10.0.13.146
+ A 10.0.13.147
+ A 10.0.13.148
+ A 10.0.13.149
+ A 10.0.13.150
+ A 10.0.13.151
+ A 10.0.13.152
+ A 10.0.13.153
+ A 10.0.13.154
+ A 10.0.13.155
+ A 10.0.13.156
+ A 10.0.13.157
+ A 10.0.13.158
+ A 10.0.13.159
+ A 10.0.13.160
+ A 10.0.13.161
+ A 10.0.13.162
+ A 10.0.13.163
+ A 10.0.13.164
+ A 10.0.13.165
+ A 10.0.13.166
+ A 10.0.13.167
+ A 10.0.13.168
+ A 10.0.13.169
+ A 10.0.13.170
+ A 10.0.13.171
+ A 10.0.13.172
+ A 10.0.13.173
+ A 10.0.13.174
+ A 10.0.13.175
+ A 10.0.13.176
+ A 10.0.13.177
+ A 10.0.13.178
+ A 10.0.13.179
+ A 10.0.13.180
+ A 10.0.13.181
+ A 10.0.13.182
+ A 10.0.13.183
+ A 10.0.13.184
+ A 10.0.13.185
+ A 10.0.13.186
+ A 10.0.13.187
+ A 10.0.13.188
+ A 10.0.13.189
+ A 10.0.13.190
+ A 10.0.13.191
+ A 10.0.13.192
+ A 10.0.13.193
+ A 10.0.13.194
+ A 10.0.13.195
+ A 10.0.13.196
+ A 10.0.13.197
+ A 10.0.13.198
+ A 10.0.13.199
+ A 10.0.13.200
+ A 10.0.13.201
+ A 10.0.13.202
+ A 10.0.13.203
+ A 10.0.13.204
+ A 10.0.13.205
+ A 10.0.13.206
+ A 10.0.13.207
+ A 10.0.13.208
+ A 10.0.13.209
+ A 10.0.13.210
+ A 10.0.13.211
+ A 10.0.13.212
+ A 10.0.13.213
+ A 10.0.13.214
+ A 10.0.13.215
+ A 10.0.13.216
+ A 10.0.13.217
+ A 10.0.13.218
+ A 10.0.13.219
+ A 10.0.13.220
+ A 10.0.13.221
+ A 10.0.13.222
+ A 10.0.13.223
+ A 10.0.13.224
+ A 10.0.13.225
+ A 10.0.13.226
+ A 10.0.13.227
+ A 10.0.13.228
+ A 10.0.13.229
+ A 10.0.13.230
+ A 10.0.13.231
+ A 10.0.13.232
+ A 10.0.13.233
+ A 10.0.13.234
+ A 10.0.13.235
+ A 10.0.13.236
+ A 10.0.13.237
+ A 10.0.13.238
+ A 10.0.13.239
+ A 10.0.13.240
+ A 10.0.13.241
+ A 10.0.13.242
+ A 10.0.13.243
+ A 10.0.13.244
+ A 10.0.13.245
+ A 10.0.13.246
+ A 10.0.13.247
+ A 10.0.13.248
+ A 10.0.13.249
+ A 10.0.13.250
+ A 10.0.13.251
+ A 10.0.13.252
+ A 10.0.13.253
+ A 10.0.13.254
+ A 10.0.13.255
+ A 10.0.14.0
+ A 10.0.14.1
+ A 10.0.14.2
+ A 10.0.14.3
+ A 10.0.14.4
+ A 10.0.14.5
+ A 10.0.14.6
+ A 10.0.14.7
+ A 10.0.14.8
+ A 10.0.14.9
+ A 10.0.14.10
+ A 10.0.14.11
+ A 10.0.14.12
+ A 10.0.14.13
+ A 10.0.14.14
+ A 10.0.14.15
+ A 10.0.14.16
+ A 10.0.14.17
+ A 10.0.14.18
+ A 10.0.14.19
+ A 10.0.14.20
+ A 10.0.14.21
+ A 10.0.14.22
+ A 10.0.14.23
+ A 10.0.14.24
+ A 10.0.14.25
+ A 10.0.14.26
+ A 10.0.14.27
+ A 10.0.14.28
+ A 10.0.14.29
+ A 10.0.14.30
+ A 10.0.14.31
+ A 10.0.14.32
+ A 10.0.14.33
+ A 10.0.14.34
+ A 10.0.14.35
+ A 10.0.14.36
+ A 10.0.14.37
+ A 10.0.14.38
+ A 10.0.14.39
+ A 10.0.14.40
+ A 10.0.14.41
+ A 10.0.14.42
+ A 10.0.14.43
+ A 10.0.14.44
+ A 10.0.14.45
+ A 10.0.14.46
+ A 10.0.14.47
+ A 10.0.14.48
+ A 10.0.14.49
+ A 10.0.14.50
+ A 10.0.14.51
+ A 10.0.14.52
+ A 10.0.14.53
+ A 10.0.14.54
+ A 10.0.14.55
+ A 10.0.14.56
+ A 10.0.14.57
+ A 10.0.14.58
+ A 10.0.14.59
+ A 10.0.14.60
+ A 10.0.14.61
+ A 10.0.14.62
+ A 10.0.14.63
+ A 10.0.14.64
+ A 10.0.14.65
+ A 10.0.14.66
+ A 10.0.14.67
+ A 10.0.14.68
+ A 10.0.14.69
+ A 10.0.14.70
+ A 10.0.14.71
+ A 10.0.14.72
+ A 10.0.14.73
+ A 10.0.14.74
+ A 10.0.14.75
+ A 10.0.14.76
+ A 10.0.14.77
+ A 10.0.14.78
+ A 10.0.14.79
+ A 10.0.14.80
+ A 10.0.14.81
+ A 10.0.14.82
+ A 10.0.14.83
+ A 10.0.14.84
+ A 10.0.14.85
+ A 10.0.14.86
+ A 10.0.14.87
+ A 10.0.14.88
+ A 10.0.14.89
+ A 10.0.14.90
+ A 10.0.14.91
+ A 10.0.14.92
+ A 10.0.14.93
+ A 10.0.14.94
+ A 10.0.14.95
+ A 10.0.14.96
+ A 10.0.14.97
+ A 10.0.14.98
+ A 10.0.14.99
+ A 10.0.14.100
+ A 10.0.14.101
+ A 10.0.14.102
+ A 10.0.14.103
+ A 10.0.14.104
+ A 10.0.14.105
+ A 10.0.14.106
+ A 10.0.14.107
+ A 10.0.14.108
+ A 10.0.14.109
+ A 10.0.14.110
+ A 10.0.14.111
+ A 10.0.14.112
+ A 10.0.14.113
+ A 10.0.14.114
+ A 10.0.14.115
+ A 10.0.14.116
+ A 10.0.14.117
+ A 10.0.14.118
+ A 10.0.14.119
+ A 10.0.14.120
+ A 10.0.14.121
+ A 10.0.14.122
+ A 10.0.14.123
+ A 10.0.14.124
+ A 10.0.14.125
+ A 10.0.14.126
+ A 10.0.14.127
+ A 10.0.14.128
+ A 10.0.14.129
+ A 10.0.14.130
+ A 10.0.14.131
+ A 10.0.14.132
+ A 10.0.14.133
+ A 10.0.14.134
+ A 10.0.14.135
+ A 10.0.14.136
+ A 10.0.14.137
+ A 10.0.14.138
+ A 10.0.14.139
+ A 10.0.14.140
+ A 10.0.14.141
+ A 10.0.14.142
+ A 10.0.14.143
+ A 10.0.14.144
+ A 10.0.14.145
+ A 10.0.14.146
+ A 10.0.14.147
+ A 10.0.14.148
+ A 10.0.14.149
+ A 10.0.14.150
+ A 10.0.14.151
+ A 10.0.14.152
+ A 10.0.14.153
+ A 10.0.14.154
+ A 10.0.14.155
+ A 10.0.14.156
+ A 10.0.14.157
+ A 10.0.14.158
+ A 10.0.14.159
+ A 10.0.14.160
+ A 10.0.14.161
+ A 10.0.14.162
+ A 10.0.14.163
+ A 10.0.14.164
+ A 10.0.14.165
+ A 10.0.14.166
+ A 10.0.14.167
+ A 10.0.14.168
+ A 10.0.14.169
+ A 10.0.14.170
+ A 10.0.14.171
+ A 10.0.14.172
+ A 10.0.14.173
+ A 10.0.14.174
+ A 10.0.14.175
+ A 10.0.14.176
+ A 10.0.14.177
+ A 10.0.14.178
+ A 10.0.14.179
+ A 10.0.14.180
+ A 10.0.14.181
+ A 10.0.14.182
+ A 10.0.14.183
+ A 10.0.14.184
+ A 10.0.14.185
+ A 10.0.14.186
+ A 10.0.14.187
+ A 10.0.14.188
+ A 10.0.14.189
+ A 10.0.14.190
+ A 10.0.14.191
+ A 10.0.14.192
+ A 10.0.14.193
+ A 10.0.14.194
+ A 10.0.14.195
+ A 10.0.14.196
+ A 10.0.14.197
+ A 10.0.14.198
+ A 10.0.14.199
+ A 10.0.14.200
+ A 10.0.14.201
+ A 10.0.14.202
+ A 10.0.14.203
+ A 10.0.14.204
+ A 10.0.14.205
+ A 10.0.14.206
+ A 10.0.14.207
+ A 10.0.14.208
+ A 10.0.14.209
+ A 10.0.14.210
+ A 10.0.14.211
+ A 10.0.14.212
+ A 10.0.14.213
+ A 10.0.14.214
+ A 10.0.14.215
+ A 10.0.14.216
+ A 10.0.14.217
+ A 10.0.14.218
+ A 10.0.14.219
+ A 10.0.14.220
+ A 10.0.14.221
+ A 10.0.14.222
+ A 10.0.14.223
+ A 10.0.14.224
+ A 10.0.14.225
+ A 10.0.14.226
+ A 10.0.14.227
+ A 10.0.14.228
+ A 10.0.14.229
+ A 10.0.14.230
+ A 10.0.14.231
+ A 10.0.14.232
+ A 10.0.14.233
+ A 10.0.14.234
+ A 10.0.14.235
+ A 10.0.14.236
+ A 10.0.14.237
+ A 10.0.14.238
+ A 10.0.14.239
+ A 10.0.14.240
+ A 10.0.14.241
+ A 10.0.14.242
+ A 10.0.14.243
+ A 10.0.14.244
+ A 10.0.14.245
+ A 10.0.14.246
+ A 10.0.14.247
+ A 10.0.14.248
+ A 10.0.14.249
+ A 10.0.14.250
+ A 10.0.14.251
+ A 10.0.14.252
+ A 10.0.14.253
+ A 10.0.14.254
+ A 10.0.14.255
+ A 10.0.15.0
+ A 10.0.15.1
+ A 10.0.15.2
+ A 10.0.15.3
+ A 10.0.15.4
+ A 10.0.15.5
+ A 10.0.15.6
+ A 10.0.15.7
+ A 10.0.15.8
+ A 10.0.15.9
+ A 10.0.15.10
+ A 10.0.15.11
+ A 10.0.15.12
+ A 10.0.15.13
+ A 10.0.15.14
+ A 10.0.15.15
+ A 10.0.15.16
+ A 10.0.15.17
+ A 10.0.15.18
+ A 10.0.15.19
+ A 10.0.15.20
+ A 10.0.15.21
+ A 10.0.15.22
+ A 10.0.15.23
+ A 10.0.15.24
+ A 10.0.15.25
+ A 10.0.15.26
+ A 10.0.15.27
+ A 10.0.15.28
+ A 10.0.15.29
+ A 10.0.15.30
+ A 10.0.15.31
+ A 10.0.15.32
+ A 10.0.15.33
+ A 10.0.15.34
+ A 10.0.15.35
+ A 10.0.15.36
+ A 10.0.15.37
+ A 10.0.15.38
+ A 10.0.15.39
+ A 10.0.15.40
+ A 10.0.15.41
+ A 10.0.15.42
+ A 10.0.15.43
+ A 10.0.15.44
+ A 10.0.15.45
+ A 10.0.15.46
+ A 10.0.15.47
+ A 10.0.15.48
+ A 10.0.15.49
+ A 10.0.15.50
+ A 10.0.15.51
+ A 10.0.15.52
+ A 10.0.15.53
+ A 10.0.15.54
+ A 10.0.15.55
+ A 10.0.15.56
+ A 10.0.15.57
+ A 10.0.15.58
+ A 10.0.15.59
+ A 10.0.15.60
+ A 10.0.15.61
+ A 10.0.15.62
+ A 10.0.15.63
+ A 10.0.15.64
+ A 10.0.15.65
+ A 10.0.15.66
+ A 10.0.15.67
+ A 10.0.15.68
+ A 10.0.15.69
+ A 10.0.15.70
+ A 10.0.15.71
+ A 10.0.15.72
+ A 10.0.15.73
+ A 10.0.15.74
+ A 10.0.15.75
+ A 10.0.15.76
+ A 10.0.15.77
+ A 10.0.15.78
+ A 10.0.15.79
+ A 10.0.15.80
+ A 10.0.15.81
+ A 10.0.15.82
+ A 10.0.15.83
+ A 10.0.15.84
+ A 10.0.15.85
+ A 10.0.15.86
+ A 10.0.15.87
+ A 10.0.15.88
+ A 10.0.15.89
+ A 10.0.15.90
+ A 10.0.15.91
+ A 10.0.15.92
+ A 10.0.15.93
+ A 10.0.15.94
+ A 10.0.15.95
+ A 10.0.15.96
+ A 10.0.15.97
+ A 10.0.15.98
+ A 10.0.15.99
+ A 10.0.15.100
+ A 10.0.15.101
+ A 10.0.15.102
+ A 10.0.15.103
+ A 10.0.15.104
+ A 10.0.15.105
+ A 10.0.15.106
+ A 10.0.15.107
+ A 10.0.15.108
+ A 10.0.15.109
+ A 10.0.15.110
+ A 10.0.15.111
+ A 10.0.15.112
+ A 10.0.15.113
+ A 10.0.15.114
+ A 10.0.15.115
+ A 10.0.15.116
+ A 10.0.15.117
+ A 10.0.15.118
+ A 10.0.15.119
+ A 10.0.15.120
+ A 10.0.15.121
+ A 10.0.15.122
+ A 10.0.15.123
+ A 10.0.15.124
+ A 10.0.15.125
+ A 10.0.15.126
+ A 10.0.15.127
+ A 10.0.15.128
+ A 10.0.15.129
+ A 10.0.15.130
+ A 10.0.15.131
+ A 10.0.15.132
+ A 10.0.15.133
+ A 10.0.15.134
+ A 10.0.15.135
+ A 10.0.15.136
+ A 10.0.15.137
+ A 10.0.15.138
+ A 10.0.15.139
+ A 10.0.15.140
+ A 10.0.15.141
+ A 10.0.15.142
+ A 10.0.15.143
+ A 10.0.15.144
+ A 10.0.15.145
+ A 10.0.15.146
+ A 10.0.15.147
+ A 10.0.15.148
+ A 10.0.15.149
+ A 10.0.15.150
+ A 10.0.15.151
+ A 10.0.15.152
+ A 10.0.15.153
+ A 10.0.15.154
+ A 10.0.15.155
+ A 10.0.15.156
+ A 10.0.15.157
+ A 10.0.15.158
+ A 10.0.15.159
+ A 10.0.15.160
+ A 10.0.15.161
+ A 10.0.15.162
+ A 10.0.15.163
+ A 10.0.15.164
+ A 10.0.15.165
+ A 10.0.15.166
+ A 10.0.15.167
+ A 10.0.15.168
+ A 10.0.15.169
+ A 10.0.15.170
+ A 10.0.15.171
+ A 10.0.15.172
+ A 10.0.15.173
+ A 10.0.15.174
+ A 10.0.15.175
+ A 10.0.15.176
+ A 10.0.15.177
+ A 10.0.15.178
+ A 10.0.15.179
+ A 10.0.15.180
+ A 10.0.15.181
+ A 10.0.15.182
+ A 10.0.15.183
+ A 10.0.15.184
+ A 10.0.15.185
+ A 10.0.15.186
+ A 10.0.15.187
+ A 10.0.15.188
+ A 10.0.15.189
+ A 10.0.15.190
+ A 10.0.15.191
+ A 10.0.15.192
+ A 10.0.15.193
+ A 10.0.15.194
+ A 10.0.15.195
+ A 10.0.15.196
+ A 10.0.15.197
+ A 10.0.15.198
+ A 10.0.15.199
+ A 10.0.15.200
+ A 10.0.15.201
+ A 10.0.15.202
+ A 10.0.15.203
+ A 10.0.15.204
+ A 10.0.15.205
+ A 10.0.15.206
+ A 10.0.15.207
+ A 10.0.15.208
+ A 10.0.15.209
+ A 10.0.15.210
+ A 10.0.15.211
+ A 10.0.15.212
+ A 10.0.15.213
+ A 10.0.15.214
+ A 10.0.15.215
+ A 10.0.15.216
+ A 10.0.15.217
+ A 10.0.15.218
+ A 10.0.15.219
+ A 10.0.15.220
+ A 10.0.15.221
+ A 10.0.15.222
+ A 10.0.15.223
+ A 10.0.15.224
+ A 10.0.15.225
+ A 10.0.15.226
+ A 10.0.15.227
+ A 10.0.15.228
+ A 10.0.15.229
+ A 10.0.15.230
+ A 10.0.15.231
+ A 10.0.15.232
+ A 10.0.15.233
+ A 10.0.15.234
+ A 10.0.15.235
+ A 10.0.15.236
+ A 10.0.15.237
+ A 10.0.15.238
+ A 10.0.15.239
+ A 10.0.15.240
+ A 10.0.15.241
+ A 10.0.15.242
+ A 10.0.15.243
+ A 10.0.15.244
+ A 10.0.15.245
+ A 10.0.15.246
+ A 10.0.15.247
+ A 10.0.15.248
+ A 10.0.15.249
+ A 10.0.15.250
+ A 10.0.15.251
+ A 10.0.15.252
+ A 10.0.15.253
+ A 10.0.15.254
+ A 10.0.15.255
+ A 10.0.16.0
+ A 10.0.16.1
+ A 10.0.16.2
+ A 10.0.16.3
+ A 10.0.16.4
+ A 10.0.16.5
+ A 10.0.16.6
+ A 10.0.16.7
+ A 10.0.16.8
+ A 10.0.16.9
+ A 10.0.16.10
+ A 10.0.16.11
+ A 10.0.16.12
+ A 10.0.16.13
+ A 10.0.16.14
+ A 10.0.16.15
+ A 10.0.16.16
+ A 10.0.16.17
+ A 10.0.16.18
+ A 10.0.16.19
+ A 10.0.16.20
+ A 10.0.16.21
+ A 10.0.16.22
+ A 10.0.16.23
+ A 10.0.16.24
+ A 10.0.16.25
+ A 10.0.16.26
+ A 10.0.16.27
+ A 10.0.16.28
+ A 10.0.16.29
+ A 10.0.16.30
+ A 10.0.16.31
+ A 10.0.16.32
+ A 10.0.16.33
+ A 10.0.16.34
+ A 10.0.16.35
+ A 10.0.16.36
+ A 10.0.16.37
+ A 10.0.16.38
+ A 10.0.16.39
+ A 10.0.16.40
+ A 10.0.16.41
+ A 10.0.16.42
+ A 10.0.16.43
+ A 10.0.16.44
+ A 10.0.16.45
+ A 10.0.16.46
+ A 10.0.16.47
+ A 10.0.16.48
+ A 10.0.16.49
+ A 10.0.16.50
+ A 10.0.16.51
+ A 10.0.16.52
+ A 10.0.16.53
+ A 10.0.16.54
+ A 10.0.16.55
+ A 10.0.16.56
+ A 10.0.16.57
+ A 10.0.16.58
+ A 10.0.16.59
+ A 10.0.16.60
+ A 10.0.16.61
+ A 10.0.16.62
+ A 10.0.16.63
+ A 10.0.16.64
+ A 10.0.16.65
+ A 10.0.16.66
+ A 10.0.16.67
+ A 10.0.16.68
+ A 10.0.16.69
+ A 10.0.16.70
+ A 10.0.16.71
+ A 10.0.16.72
+ A 10.0.16.73
+ A 10.0.16.74
+ A 10.0.16.75
+ A 10.0.16.76
+ A 10.0.16.77
+ A 10.0.16.78
+ A 10.0.16.79
+ A 10.0.16.80
+ A 10.0.16.81
+ A 10.0.16.82
+ A 10.0.16.83
+ A 10.0.16.84
+ A 10.0.16.85
+ A 10.0.16.86
+ A 10.0.16.87
+ A 10.0.16.88
+ A 10.0.16.89
+ A 10.0.16.90
+ A 10.0.16.91
+ A 10.0.16.92
+ A 10.0.16.93
+ A 10.0.16.94
+ A 10.0.16.95
+ A 10.0.16.96
+ A 10.0.16.97
+ A 10.0.16.98
+ A 10.0.16.99
+ A 10.0.16.100
+ A 10.0.16.101
+ A 10.0.16.102
+ A 10.0.16.103
+ A 10.0.16.104
+ A 10.0.16.105
+ A 10.0.16.106
+ A 10.0.16.107
+ A 10.0.16.108
+ A 10.0.16.109
+ A 10.0.16.110
+ A 10.0.16.111
+ A 10.0.16.112
+ A 10.0.16.113
+ A 10.0.16.114
+ A 10.0.16.115
+ A 10.0.16.116
+ A 10.0.16.117
+ A 10.0.16.118
+ A 10.0.16.119
+ A 10.0.16.120
+ A 10.0.16.121
+ A 10.0.16.122
+ A 10.0.16.123
+ A 10.0.16.124
+ A 10.0.16.125
+ A 10.0.16.126
+ A 10.0.16.127
+ A 10.0.16.128
+ A 10.0.16.129
+ A 10.0.16.130
+ A 10.0.16.131
+ A 10.0.16.132
+ A 10.0.16.133
+ A 10.0.16.134
+ A 10.0.16.135
+ A 10.0.16.136
+ A 10.0.16.137
+ A 10.0.16.138
+ A 10.0.16.139
+ A 10.0.16.140
+ A 10.0.16.141
+ A 10.0.16.142
+ A 10.0.16.143
+ A 10.0.16.144
+ A 10.0.16.145
+ A 10.0.16.146
+ A 10.0.16.147
+ A 10.0.16.148
+ A 10.0.16.149
+ A 10.0.16.150
+ A 10.0.16.151
+ A 10.0.16.152
+ A 10.0.16.153
+ A 10.0.16.154
+ A 10.0.16.155
+ A 10.0.16.156
+ A 10.0.16.157
+ A 10.0.16.158
+ A 10.0.16.159
+ A 10.0.16.160
+ A 10.0.16.161
+ A 10.0.16.162
+ A 10.0.16.163
+ A 10.0.16.164
+ A 10.0.16.165
+ A 10.0.16.166
+ A 10.0.16.167
+ A 10.0.16.168
+ A 10.0.16.169
+ A 10.0.16.170
+ A 10.0.16.171
+ A 10.0.16.172
+ A 10.0.16.173
+ A 10.0.16.174
+ A 10.0.16.175
+ A 10.0.16.176
+ A 10.0.16.177
+ A 10.0.16.178
+ A 10.0.16.179
+ A 10.0.16.180
+ A 10.0.16.181
+ A 10.0.16.182
+ A 10.0.16.183
+ A 10.0.16.184
+ A 10.0.16.185
+ A 10.0.16.186
+ A 10.0.16.187
+ A 10.0.16.188
+ A 10.0.16.189
+ A 10.0.16.190
+ A 10.0.16.191
+ A 10.0.16.192
+ A 10.0.16.193
+ A 10.0.16.194
+ A 10.0.16.195
+ A 10.0.16.196
+ A 10.0.16.197
+ A 10.0.16.198
+ A 10.0.16.199
+ A 10.0.16.200
+ A 10.0.16.201
+ A 10.0.16.202
+ A 10.0.16.203
+ A 10.0.16.204
+ A 10.0.16.205
+ A 10.0.16.206
+ A 10.0.16.207
+ A 10.0.16.208
+ A 10.0.16.209
+ A 10.0.16.210
+ A 10.0.16.211
+ A 10.0.16.212
+ A 10.0.16.213
+ A 10.0.16.214
+ A 10.0.16.215
+ A 10.0.16.216
+ A 10.0.16.217
+ A 10.0.16.218
+ A 10.0.16.219
+ A 10.0.16.220
+ A 10.0.16.221
+ A 10.0.16.222
+ A 10.0.16.223
+ A 10.0.16.224
+ A 10.0.16.225
+ A 10.0.16.226
+ A 10.0.16.227
+ A 10.0.16.228
+ A 10.0.16.229
+ A 10.0.16.230
+ A 10.0.16.231
+ A 10.0.16.232
+ A 10.0.16.233
+ A 10.0.16.234
+ A 10.0.16.235
+ A 10.0.16.236
+ A 10.0.16.237
+ A 10.0.16.238
+ A 10.0.16.239
+ A 10.0.16.240
+ A 10.0.16.241
+ A 10.0.16.242
+ A 10.0.16.243
+ A 10.0.16.244
+ A 10.0.16.245
+ A 10.0.16.246
+ A 10.0.16.247
+ A 10.0.16.248
+ A 10.0.16.249
+ A 10.0.16.250
+ A 10.0.16.251
+ A 10.0.16.252
+ A 10.0.16.253
+ A 10.0.16.254
+ A 10.0.16.255
+ A 10.0.17.0
+ A 10.0.17.1
+ A 10.0.17.2
+ A 10.0.17.3
+ A 10.0.17.4
+ A 10.0.17.5
+ A 10.0.17.6
+ A 10.0.17.7
+ A 10.0.17.8
+ A 10.0.17.9
+ A 10.0.17.10
+ A 10.0.17.11
+ A 10.0.17.12
+ A 10.0.17.13
+ A 10.0.17.14
+ A 10.0.17.15
+ A 10.0.17.16
+ A 10.0.17.17
+ A 10.0.17.18
+ A 10.0.17.19
+ A 10.0.17.20
+ A 10.0.17.21
+ A 10.0.17.22
+ A 10.0.17.23
+ A 10.0.17.24
+ A 10.0.17.25
+ A 10.0.17.26
+ A 10.0.17.27
+ A 10.0.17.28
+ A 10.0.17.29
+ A 10.0.17.30
+ A 10.0.17.31
+ A 10.0.17.32
+ A 10.0.17.33
+ A 10.0.17.34
+ A 10.0.17.35
+ A 10.0.17.36
+ A 10.0.17.37
+ A 10.0.17.38
+ A 10.0.17.39
+ A 10.0.17.40
+ A 10.0.17.41
+ A 10.0.17.42
+ A 10.0.17.43
+ A 10.0.17.44
+ A 10.0.17.45
+ A 10.0.17.46
+ A 10.0.17.47
+ A 10.0.17.48
+ A 10.0.17.49
+ A 10.0.17.50
+ A 10.0.17.51
+ A 10.0.17.52
+ A 10.0.17.53
+ A 10.0.17.54
+ A 10.0.17.55
+ A 10.0.17.56
+ A 10.0.17.57
+ A 10.0.17.58
+ A 10.0.17.59
+ A 10.0.17.60
+ A 10.0.17.61
+ A 10.0.17.62
+ A 10.0.17.63
+ A 10.0.17.64
+ A 10.0.17.65
+ A 10.0.17.66
+ A 10.0.17.67
+ A 10.0.17.68
+ A 10.0.17.69
+ A 10.0.17.70
+ A 10.0.17.71
+ A 10.0.17.72
+ A 10.0.17.73
+ A 10.0.17.74
+ A 10.0.17.75
+ A 10.0.17.76
+ A 10.0.17.77
+ A 10.0.17.78
+ A 10.0.17.79
+ A 10.0.17.80
+ A 10.0.17.81
+ A 10.0.17.82
+ A 10.0.17.83
+ A 10.0.17.84
+ A 10.0.17.85
+ A 10.0.17.86
+ A 10.0.17.87
+ A 10.0.17.88
+ A 10.0.17.89
+ A 10.0.17.90
+ A 10.0.17.91
+ A 10.0.17.92
+ A 10.0.17.93
+ A 10.0.17.94
+ A 10.0.17.95
+ A 10.0.17.96
+ A 10.0.17.97
+ A 10.0.17.98
+ A 10.0.17.99
+ A 10.0.17.100
+ A 10.0.17.101
+ A 10.0.17.102
+ A 10.0.17.103
+ A 10.0.17.104
+ A 10.0.17.105
+ A 10.0.17.106
+ A 10.0.17.107
+ A 10.0.17.108
+ A 10.0.17.109
+ A 10.0.17.110
+ A 10.0.17.111
+ A 10.0.17.112
+ A 10.0.17.113
+ A 10.0.17.114
+ A 10.0.17.115
+ A 10.0.17.116
+ A 10.0.17.117
+ A 10.0.17.118
+ A 10.0.17.119
+ A 10.0.17.120
+ A 10.0.17.121
+ A 10.0.17.122
+ A 10.0.17.123
+ A 10.0.17.124
+ A 10.0.17.125
+ A 10.0.17.126
+ A 10.0.17.127
+ A 10.0.17.128
+ A 10.0.17.129
+ A 10.0.17.130
+ A 10.0.17.131
+ A 10.0.17.132
+ A 10.0.17.133
+ A 10.0.17.134
+ A 10.0.17.135
+ A 10.0.17.136
+ A 10.0.17.137
+ A 10.0.17.138
+ A 10.0.17.139
+ A 10.0.17.140
+ A 10.0.17.141
+ A 10.0.17.142
+ A 10.0.17.143
+ A 10.0.17.144
+ A 10.0.17.145
+ A 10.0.17.146
+ A 10.0.17.147
+ A 10.0.17.148
+ A 10.0.17.149
+ A 10.0.17.150
+ A 10.0.17.151
+ A 10.0.17.152
+ A 10.0.17.153
+ A 10.0.17.154
+ A 10.0.17.155
+ A 10.0.17.156
+ A 10.0.17.157
+ A 10.0.17.158
+ A 10.0.17.159
+ A 10.0.17.160
+ A 10.0.17.161
+ A 10.0.17.162
+ A 10.0.17.163
+ A 10.0.17.164
+ A 10.0.17.165
+ A 10.0.17.166
+ A 10.0.17.167
+ A 10.0.17.168
+ A 10.0.17.169
+ A 10.0.17.170
+ A 10.0.17.171
+ A 10.0.17.172
+ A 10.0.17.173
+ A 10.0.17.174
+ A 10.0.17.175
+ A 10.0.17.176
+ A 10.0.17.177
+ A 10.0.17.178
+ A 10.0.17.179
+ A 10.0.17.180
+ A 10.0.17.181
+ A 10.0.17.182
+ A 10.0.17.183
+ A 10.0.17.184
+ A 10.0.17.185
+ A 10.0.17.186
+ A 10.0.17.187
+ A 10.0.17.188
+ A 10.0.17.189
+ A 10.0.17.190
+ A 10.0.17.191
+ A 10.0.17.192
+ A 10.0.17.193
+ A 10.0.17.194
+ A 10.0.17.195
+ A 10.0.17.196
+ A 10.0.17.197
+ A 10.0.17.198
+ A 10.0.17.199
+ A 10.0.17.200
+ A 10.0.17.201
+ A 10.0.17.202
+ A 10.0.17.203
+ A 10.0.17.204
+ A 10.0.17.205
+ A 10.0.17.206
+ A 10.0.17.207
+ A 10.0.17.208
+ A 10.0.17.209
+ A 10.0.17.210
+ A 10.0.17.211
+ A 10.0.17.212
+ A 10.0.17.213
+ A 10.0.17.214
+ A 10.0.17.215
+ A 10.0.17.216
+ A 10.0.17.217
+ A 10.0.17.218
+ A 10.0.17.219
+ A 10.0.17.220
+ A 10.0.17.221
+ A 10.0.17.222
+ A 10.0.17.223
+ A 10.0.17.224
+ A 10.0.17.225
+ A 10.0.17.226
+ A 10.0.17.227
+ A 10.0.17.228
+ A 10.0.17.229
+ A 10.0.17.230
+ A 10.0.17.231
+ A 10.0.17.232
+ A 10.0.17.233
+ A 10.0.17.234
+ A 10.0.17.235
+ A 10.0.17.236
+ A 10.0.17.237
+ A 10.0.17.238
+ A 10.0.17.239
+ A 10.0.17.240
+ A 10.0.17.241
+ A 10.0.17.242
+ A 10.0.17.243
+ A 10.0.17.244
+ A 10.0.17.245
+ A 10.0.17.246
+ A 10.0.17.247
+ A 10.0.17.248
+ A 10.0.17.249
+ A 10.0.17.250
+ A 10.0.17.251
+ A 10.0.17.252
+ A 10.0.17.253
+ A 10.0.17.254
+ A 10.0.17.255
+ A 10.0.18.0
+ A 10.0.18.1
+ A 10.0.18.2
+ A 10.0.18.3
+ A 10.0.18.4
+ A 10.0.18.5
+ A 10.0.18.6
+ A 10.0.18.7
+ A 10.0.18.8
+ A 10.0.18.9
+ A 10.0.18.10
+ A 10.0.18.11
+ A 10.0.18.12
+ A 10.0.18.13
+ A 10.0.18.14
+ A 10.0.18.15
+ A 10.0.18.16
+ A 10.0.18.17
+ A 10.0.18.18
+ A 10.0.18.19
+ A 10.0.18.20
+ A 10.0.18.21
+ A 10.0.18.22
+ A 10.0.18.23
+ A 10.0.18.24
+ A 10.0.18.25
+ A 10.0.18.26
+ A 10.0.18.27
+ A 10.0.18.28
+ A 10.0.18.29
+ A 10.0.18.30
+ A 10.0.18.31
+ A 10.0.18.32
+ A 10.0.18.33
+ A 10.0.18.34
+ A 10.0.18.35
+ A 10.0.18.36
+ A 10.0.18.37
+ A 10.0.18.38
+ A 10.0.18.39
+ A 10.0.18.40
+ A 10.0.18.41
+ A 10.0.18.42
+ A 10.0.18.43
+ A 10.0.18.44
+ A 10.0.18.45
+ A 10.0.18.46
+ A 10.0.18.47
+ A 10.0.18.48
+ A 10.0.18.49
+ A 10.0.18.50
+ A 10.0.18.51
+ A 10.0.18.52
+ A 10.0.18.53
+ A 10.0.18.54
+ A 10.0.18.55
+ A 10.0.18.56
+ A 10.0.18.57
+ A 10.0.18.58
+ A 10.0.18.59
+ A 10.0.18.60
+ A 10.0.18.61
+ A 10.0.18.62
+ A 10.0.18.63
+ A 10.0.18.64
+ A 10.0.18.65
+ A 10.0.18.66
+ A 10.0.18.67
+ A 10.0.18.68
+ A 10.0.18.69
+ A 10.0.18.70
+ A 10.0.18.71
+ A 10.0.18.72
+ A 10.0.18.73
+ A 10.0.18.74
+ A 10.0.18.75
+ A 10.0.18.76
+ A 10.0.18.77
+ A 10.0.18.78
+ A 10.0.18.79
+ A 10.0.18.80
+ A 10.0.18.81
+ A 10.0.18.82
+ A 10.0.18.83
+ A 10.0.18.84
+ A 10.0.18.85
+ A 10.0.18.86
+ A 10.0.18.87
+ A 10.0.18.88
+ A 10.0.18.89
+ A 10.0.18.90
+ A 10.0.18.91
+ A 10.0.18.92
+ A 10.0.18.93
+ A 10.0.18.94
+ A 10.0.18.95
+ A 10.0.18.96
+ A 10.0.18.97
+ A 10.0.18.98
+ A 10.0.18.99
+ A 10.0.18.100
+ A 10.0.18.101
+ A 10.0.18.102
+ A 10.0.18.103
+ A 10.0.18.104
+ A 10.0.18.105
+ A 10.0.18.106
+ A 10.0.18.107
+ A 10.0.18.108
+ A 10.0.18.109
+ A 10.0.18.110
+ A 10.0.18.111
+ A 10.0.18.112
+ A 10.0.18.113
+ A 10.0.18.114
+ A 10.0.18.115
+ A 10.0.18.116
+ A 10.0.18.117
+ A 10.0.18.118
+ A 10.0.18.119
+ A 10.0.18.120
+ A 10.0.18.121
+ A 10.0.18.122
+ A 10.0.18.123
+ A 10.0.18.124
+ A 10.0.18.125
+ A 10.0.18.126
+ A 10.0.18.127
+ A 10.0.18.128
+ A 10.0.18.129
+ A 10.0.18.130
+ A 10.0.18.131
+ A 10.0.18.132
+ A 10.0.18.133
+ A 10.0.18.134
+ A 10.0.18.135
+ A 10.0.18.136
+ A 10.0.18.137
+ A 10.0.18.138
+ A 10.0.18.139
+ A 10.0.18.140
+ A 10.0.18.141
+ A 10.0.18.142
+ A 10.0.18.143
+ A 10.0.18.144
+ A 10.0.18.145
+ A 10.0.18.146
+ A 10.0.18.147
+ A 10.0.18.148
+ A 10.0.18.149
+ A 10.0.18.150
+ A 10.0.18.151
+ A 10.0.18.152
+ A 10.0.18.153
+ A 10.0.18.154
+ A 10.0.18.155
+ A 10.0.18.156
+ A 10.0.18.157
+ A 10.0.18.158
+ A 10.0.18.159
+ A 10.0.18.160
+ A 10.0.18.161
+ A 10.0.18.162
+ A 10.0.18.163
+ A 10.0.18.164
+ A 10.0.18.165
+ A 10.0.18.166
+ A 10.0.18.167
+ A 10.0.18.168
+ A 10.0.18.169
+ A 10.0.18.170
+ A 10.0.18.171
+ A 10.0.18.172
+ A 10.0.18.173
+ A 10.0.18.174
+ A 10.0.18.175
+ A 10.0.18.176
+ A 10.0.18.177
+ A 10.0.18.178
+ A 10.0.18.179
+ A 10.0.18.180
+ A 10.0.18.181
+ A 10.0.18.182
+ A 10.0.18.183
+ A 10.0.18.184
+ A 10.0.18.185
+ A 10.0.18.186
+ A 10.0.18.187
+ A 10.0.18.188
+ A 10.0.18.189
+ A 10.0.18.190
+ A 10.0.18.191
+ A 10.0.18.192
+ A 10.0.18.193
+ A 10.0.18.194
+ A 10.0.18.195
+ A 10.0.18.196
+ A 10.0.18.197
+ A 10.0.18.198
+ A 10.0.18.199
+ A 10.0.18.200
+ A 10.0.18.201
+ A 10.0.18.202
+ A 10.0.18.203
+ A 10.0.18.204
+ A 10.0.18.205
+ A 10.0.18.206
+ A 10.0.18.207
+ A 10.0.18.208
+ A 10.0.18.209
+ A 10.0.18.210
+ A 10.0.18.211
+ A 10.0.18.212
+ A 10.0.18.213
+ A 10.0.18.214
+ A 10.0.18.215
+ A 10.0.18.216
+ A 10.0.18.217
+ A 10.0.18.218
+ A 10.0.18.219
+ A 10.0.18.220
+ A 10.0.18.221
+ A 10.0.18.222
+ A 10.0.18.223
+ A 10.0.18.224
+ A 10.0.18.225
+ A 10.0.18.226
+ A 10.0.18.227
+ A 10.0.18.228
+ A 10.0.18.229
+ A 10.0.18.230
+ A 10.0.18.231
+ A 10.0.18.232
+ A 10.0.18.233
+ A 10.0.18.234
+ A 10.0.18.235
+ A 10.0.18.236
+ A 10.0.18.237
+ A 10.0.18.238
+ A 10.0.18.239
+ A 10.0.18.240
+ A 10.0.18.241
+ A 10.0.18.242
+ A 10.0.18.243
+ A 10.0.18.244
+ A 10.0.18.245
+ A 10.0.18.246
+ A 10.0.18.247
+ A 10.0.18.248
+ A 10.0.18.249
+ A 10.0.18.250
+ A 10.0.18.251
+ A 10.0.18.252
+ A 10.0.18.253
+ A 10.0.18.254
+ A 10.0.18.255
+ A 10.0.19.0
+ A 10.0.19.1
+ A 10.0.19.2
+ A 10.0.19.3
+ A 10.0.19.4
+ A 10.0.19.5
+ A 10.0.19.6
+ A 10.0.19.7
+ A 10.0.19.8
+ A 10.0.19.9
+ A 10.0.19.10
+ A 10.0.19.11
+ A 10.0.19.12
+ A 10.0.19.13
+ A 10.0.19.14
+ A 10.0.19.15
+ A 10.0.19.16
+ A 10.0.19.17
+ A 10.0.19.18
+ A 10.0.19.19
+ A 10.0.19.20
+ A 10.0.19.21
+ A 10.0.19.22
+ A 10.0.19.23
+ A 10.0.19.24
+ A 10.0.19.25
+ A 10.0.19.26
+ A 10.0.19.27
+ A 10.0.19.28
+ A 10.0.19.29
+ A 10.0.19.30
+ A 10.0.19.31
+ A 10.0.19.32
+ A 10.0.19.33
+ A 10.0.19.34
+ A 10.0.19.35
+ A 10.0.19.36
+ A 10.0.19.37
+ A 10.0.19.38
+ A 10.0.19.39
+ A 10.0.19.40
+ A 10.0.19.41
+ A 10.0.19.42
+ A 10.0.19.43
+ A 10.0.19.44
+ A 10.0.19.45
+ A 10.0.19.46
+ A 10.0.19.47
+ A 10.0.19.48
+ A 10.0.19.49
+ A 10.0.19.50
+ A 10.0.19.51
+ A 10.0.19.52
+ A 10.0.19.53
+ A 10.0.19.54
+ A 10.0.19.55
+ A 10.0.19.56
+ A 10.0.19.57
+ A 10.0.19.58
+ A 10.0.19.59
+ A 10.0.19.60
+ A 10.0.19.61
+ A 10.0.19.62
+ A 10.0.19.63
+ A 10.0.19.64
+ A 10.0.19.65
+ A 10.0.19.66
+ A 10.0.19.67
+ A 10.0.19.68
+ A 10.0.19.69
+ A 10.0.19.70
+ A 10.0.19.71
+ A 10.0.19.72
+ A 10.0.19.73
+ A 10.0.19.74
+ A 10.0.19.75
+ A 10.0.19.76
+ A 10.0.19.77
+ A 10.0.19.78
+ A 10.0.19.79
+ A 10.0.19.80
+ A 10.0.19.81
+ A 10.0.19.82
+ A 10.0.19.83
+ A 10.0.19.84
+ A 10.0.19.85
+ A 10.0.19.86
+ A 10.0.19.87
+ A 10.0.19.88
+ A 10.0.19.89
+ A 10.0.19.90
+ A 10.0.19.91
+ A 10.0.19.92
+ A 10.0.19.93
+ A 10.0.19.94
+ A 10.0.19.95
+ A 10.0.19.96
+ A 10.0.19.97
+ A 10.0.19.98
+ A 10.0.19.99
+ A 10.0.19.100
+ A 10.0.19.101
+ A 10.0.19.102
+ A 10.0.19.103
+ A 10.0.19.104
+ A 10.0.19.105
+ A 10.0.19.106
+ A 10.0.19.107
+ A 10.0.19.108
+ A 10.0.19.109
+ A 10.0.19.110
+ A 10.0.19.111
+ A 10.0.19.112
+ A 10.0.19.113
+ A 10.0.19.114
+ A 10.0.19.115
+ A 10.0.19.116
+ A 10.0.19.117
+ A 10.0.19.118
+ A 10.0.19.119
+ A 10.0.19.120
+ A 10.0.19.121
+ A 10.0.19.122
+ A 10.0.19.123
+ A 10.0.19.124
+ A 10.0.19.125
+ A 10.0.19.126
+ A 10.0.19.127
+ A 10.0.19.128
+ A 10.0.19.129
+ A 10.0.19.130
+ A 10.0.19.131
+ A 10.0.19.132
+ A 10.0.19.133
+ A 10.0.19.134
+ A 10.0.19.135
+a-maximum-rrset A 10.0.0.0
+ A 10.0.0.1
+ A 10.0.0.2
+ A 10.0.0.3
+ A 10.0.0.4
+ A 10.0.0.5
+ A 10.0.0.6
+ A 10.0.0.7
+ A 10.0.0.8
+ A 10.0.0.9
+ A 10.0.0.10
+ A 10.0.0.11
+ A 10.0.0.12
+ A 10.0.0.13
+ A 10.0.0.14
+ A 10.0.0.15
+ A 10.0.0.16
+ A 10.0.0.17
+ A 10.0.0.18
+ A 10.0.0.19
+ A 10.0.0.20
+ A 10.0.0.21
+ A 10.0.0.22
+ A 10.0.0.23
+ A 10.0.0.24
+ A 10.0.0.25
+ A 10.0.0.26
+ A 10.0.0.27
+ A 10.0.0.28
+ A 10.0.0.29
+ A 10.0.0.30
+ A 10.0.0.31
+ A 10.0.0.32
+ A 10.0.0.33
+ A 10.0.0.34
+ A 10.0.0.35
+ A 10.0.0.36
+ A 10.0.0.37
+ A 10.0.0.38
+ A 10.0.0.39
+ A 10.0.0.40
+ A 10.0.0.41
+ A 10.0.0.42
+ A 10.0.0.43
+ A 10.0.0.44
+ A 10.0.0.45
+ A 10.0.0.46
+ A 10.0.0.47
+ A 10.0.0.48
+ A 10.0.0.49
+ A 10.0.0.50
+ A 10.0.0.51
+ A 10.0.0.52
+ A 10.0.0.53
+ A 10.0.0.54
+ A 10.0.0.55
+ A 10.0.0.56
+ A 10.0.0.57
+ A 10.0.0.58
+ A 10.0.0.59
+ A 10.0.0.60
+ A 10.0.0.61
+ A 10.0.0.62
+ A 10.0.0.63
+ A 10.0.0.64
+ A 10.0.0.65
+ A 10.0.0.66
+ A 10.0.0.67
+ A 10.0.0.68
+ A 10.0.0.69
+ A 10.0.0.70
+ A 10.0.0.71
+ A 10.0.0.72
+ A 10.0.0.73
+ A 10.0.0.74
+ A 10.0.0.75
+ A 10.0.0.76
+ A 10.0.0.77
+ A 10.0.0.78
+ A 10.0.0.79
+ A 10.0.0.80
+ A 10.0.0.81
+ A 10.0.0.82
+ A 10.0.0.83
+ A 10.0.0.84
+ A 10.0.0.85
+ A 10.0.0.86
+ A 10.0.0.87
+ A 10.0.0.88
+ A 10.0.0.89
+ A 10.0.0.90
+ A 10.0.0.91
+ A 10.0.0.92
+ A 10.0.0.93
+ A 10.0.0.94
+ A 10.0.0.95
+ A 10.0.0.96
+ A 10.0.0.97
+ A 10.0.0.98
+ A 10.0.0.99
+ A 10.0.0.100
+ A 10.0.0.101
+ A 10.0.0.102
+ A 10.0.0.103
+ A 10.0.0.104
+ A 10.0.0.105
+ A 10.0.0.106
+ A 10.0.0.107
+ A 10.0.0.108
+ A 10.0.0.109
+ A 10.0.0.110
+ A 10.0.0.111
+ A 10.0.0.112
+ A 10.0.0.113
+ A 10.0.0.114
+ A 10.0.0.115
+ A 10.0.0.116
+ A 10.0.0.117
+ A 10.0.0.118
+ A 10.0.0.119
+ A 10.0.0.120
+ A 10.0.0.121
+ A 10.0.0.122
+ A 10.0.0.123
+ A 10.0.0.124
+ A 10.0.0.125
+ A 10.0.0.126
+ A 10.0.0.127
+ A 10.0.0.128
+ A 10.0.0.129
+ A 10.0.0.130
+ A 10.0.0.131
+ A 10.0.0.132
+ A 10.0.0.133
+ A 10.0.0.134
+ A 10.0.0.135
+ A 10.0.0.136
+ A 10.0.0.137
+ A 10.0.0.138
+ A 10.0.0.139
+ A 10.0.0.140
+ A 10.0.0.141
+ A 10.0.0.142
+ A 10.0.0.143
+ A 10.0.0.144
+ A 10.0.0.145
+ A 10.0.0.146
+ A 10.0.0.147
+ A 10.0.0.148
+ A 10.0.0.149
+ A 10.0.0.150
+ A 10.0.0.151
+ A 10.0.0.152
+ A 10.0.0.153
+ A 10.0.0.154
+ A 10.0.0.155
+ A 10.0.0.156
+ A 10.0.0.157
+ A 10.0.0.158
+ A 10.0.0.159
+ A 10.0.0.160
+ A 10.0.0.161
+ A 10.0.0.162
+ A 10.0.0.163
+ A 10.0.0.164
+ A 10.0.0.165
+ A 10.0.0.166
+ A 10.0.0.167
+ A 10.0.0.168
+ A 10.0.0.169
+ A 10.0.0.170
+ A 10.0.0.171
+ A 10.0.0.172
+ A 10.0.0.173
+ A 10.0.0.174
+ A 10.0.0.175
+ A 10.0.0.176
+ A 10.0.0.177
+ A 10.0.0.178
+ A 10.0.0.179
+ A 10.0.0.180
+ A 10.0.0.181
+ A 10.0.0.182
+ A 10.0.0.183
+ A 10.0.0.184
+ A 10.0.0.185
+ A 10.0.0.186
+ A 10.0.0.187
+ A 10.0.0.188
+ A 10.0.0.189
+ A 10.0.0.190
+ A 10.0.0.191
+ A 10.0.0.192
+ A 10.0.0.193
+ A 10.0.0.194
+ A 10.0.0.195
+ A 10.0.0.196
+ A 10.0.0.197
+ A 10.0.0.198
+ A 10.0.0.199
+ A 10.0.0.200
+ A 10.0.0.201
+ A 10.0.0.202
+ A 10.0.0.203
+ A 10.0.0.204
+ A 10.0.0.205
+ A 10.0.0.206
+ A 10.0.0.207
+ A 10.0.0.208
+ A 10.0.0.209
+ A 10.0.0.210
+ A 10.0.0.211
+ A 10.0.0.212
+ A 10.0.0.213
+ A 10.0.0.214
+ A 10.0.0.215
+ A 10.0.0.216
+ A 10.0.0.217
+ A 10.0.0.218
+ A 10.0.0.219
+ A 10.0.0.220
+ A 10.0.0.221
+ A 10.0.0.222
+ A 10.0.0.223
+ A 10.0.0.224
+ A 10.0.0.225
+ A 10.0.0.226
+ A 10.0.0.227
+ A 10.0.0.228
+ A 10.0.0.229
+ A 10.0.0.230
+ A 10.0.0.231
+ A 10.0.0.232
+ A 10.0.0.233
+ A 10.0.0.234
+ A 10.0.0.235
+ A 10.0.0.236
+ A 10.0.0.237
+ A 10.0.0.238
+ A 10.0.0.239
+ A 10.0.0.240
+ A 10.0.0.241
+ A 10.0.0.242
+ A 10.0.0.243
+ A 10.0.0.244
+ A 10.0.0.245
+ A 10.0.0.246
+ A 10.0.0.247
+ A 10.0.0.248
+ A 10.0.0.249
+ A 10.0.0.250
+ A 10.0.0.251
+ A 10.0.0.252
+ A 10.0.0.253
+ A 10.0.0.254
+ A 10.0.0.255
+ A 10.0.1.0
+ A 10.0.1.1
+ A 10.0.1.2
+ A 10.0.1.3
+ A 10.0.1.4
+ A 10.0.1.5
+ A 10.0.1.6
+ A 10.0.1.7
+ A 10.0.1.8
+ A 10.0.1.9
+ A 10.0.1.10
+ A 10.0.1.11
+ A 10.0.1.12
+ A 10.0.1.13
+ A 10.0.1.14
+ A 10.0.1.15
+ A 10.0.1.16
+ A 10.0.1.17
+ A 10.0.1.18
+ A 10.0.1.19
+ A 10.0.1.20
+ A 10.0.1.21
+ A 10.0.1.22
+ A 10.0.1.23
+ A 10.0.1.24
+ A 10.0.1.25
+ A 10.0.1.26
+ A 10.0.1.27
+ A 10.0.1.28
+ A 10.0.1.29
+ A 10.0.1.30
+ A 10.0.1.31
+ A 10.0.1.32
+ A 10.0.1.33
+ A 10.0.1.34
+ A 10.0.1.35
+ A 10.0.1.36
+ A 10.0.1.37
+ A 10.0.1.38
+ A 10.0.1.39
+ A 10.0.1.40
+ A 10.0.1.41
+ A 10.0.1.42
+ A 10.0.1.43
+ A 10.0.1.44
+ A 10.0.1.45
+ A 10.0.1.46
+ A 10.0.1.47
+ A 10.0.1.48
+ A 10.0.1.49
+ A 10.0.1.50
+ A 10.0.1.51
+ A 10.0.1.52
+ A 10.0.1.53
+ A 10.0.1.54
+ A 10.0.1.55
+ A 10.0.1.56
+ A 10.0.1.57
+ A 10.0.1.58
+ A 10.0.1.59
+ A 10.0.1.60
+ A 10.0.1.61
+ A 10.0.1.62
+ A 10.0.1.63
+ A 10.0.1.64
+ A 10.0.1.65
+ A 10.0.1.66
+ A 10.0.1.67
+ A 10.0.1.68
+ A 10.0.1.69
+ A 10.0.1.70
+ A 10.0.1.71
+ A 10.0.1.72
+ A 10.0.1.73
+ A 10.0.1.74
+ A 10.0.1.75
+ A 10.0.1.76
+ A 10.0.1.77
+ A 10.0.1.78
+ A 10.0.1.79
+ A 10.0.1.80
+ A 10.0.1.81
+ A 10.0.1.82
+ A 10.0.1.83
+ A 10.0.1.84
+ A 10.0.1.85
+ A 10.0.1.86
+ A 10.0.1.87
+ A 10.0.1.88
+ A 10.0.1.89
+ A 10.0.1.90
+ A 10.0.1.91
+ A 10.0.1.92
+ A 10.0.1.93
+ A 10.0.1.94
+ A 10.0.1.95
+ A 10.0.1.96
+ A 10.0.1.97
+ A 10.0.1.98
+ A 10.0.1.99
+ A 10.0.1.100
+ A 10.0.1.101
+ A 10.0.1.102
+ A 10.0.1.103
+ A 10.0.1.104
+ A 10.0.1.105
+ A 10.0.1.106
+ A 10.0.1.107
+ A 10.0.1.108
+ A 10.0.1.109
+ A 10.0.1.110
+ A 10.0.1.111
+ A 10.0.1.112
+ A 10.0.1.113
+ A 10.0.1.114
+ A 10.0.1.115
+ A 10.0.1.116
+ A 10.0.1.117
+ A 10.0.1.118
+ A 10.0.1.119
+ A 10.0.1.120
+ A 10.0.1.121
+ A 10.0.1.122
+ A 10.0.1.123
+ A 10.0.1.124
+ A 10.0.1.125
+ A 10.0.1.126
+ A 10.0.1.127
+ A 10.0.1.128
+ A 10.0.1.129
+ A 10.0.1.130
+ A 10.0.1.131
+ A 10.0.1.132
+ A 10.0.1.133
+ A 10.0.1.134
+ A 10.0.1.135
+ A 10.0.1.136
+ A 10.0.1.137
+ A 10.0.1.138
+ A 10.0.1.139
+ A 10.0.1.140
+ A 10.0.1.141
+ A 10.0.1.142
+ A 10.0.1.143
+ A 10.0.1.144
+ A 10.0.1.145
+ A 10.0.1.146
+ A 10.0.1.147
+ A 10.0.1.148
+ A 10.0.1.149
+ A 10.0.1.150
+ A 10.0.1.151
+ A 10.0.1.152
+ A 10.0.1.153
+ A 10.0.1.154
+ A 10.0.1.155
+ A 10.0.1.156
+ A 10.0.1.157
+ A 10.0.1.158
+ A 10.0.1.159
+ A 10.0.1.160
+ A 10.0.1.161
+ A 10.0.1.162
+ A 10.0.1.163
+ A 10.0.1.164
+ A 10.0.1.165
+ A 10.0.1.166
+ A 10.0.1.167
+ A 10.0.1.168
+ A 10.0.1.169
+ A 10.0.1.170
+ A 10.0.1.171
+ A 10.0.1.172
+ A 10.0.1.173
+ A 10.0.1.174
+ A 10.0.1.175
+ A 10.0.1.176
+ A 10.0.1.177
+ A 10.0.1.178
+ A 10.0.1.179
+ A 10.0.1.180
+ A 10.0.1.181
+ A 10.0.1.182
+ A 10.0.1.183
+ A 10.0.1.184
+ A 10.0.1.185
+ A 10.0.1.186
+ A 10.0.1.187
+ A 10.0.1.188
+ A 10.0.1.189
+ A 10.0.1.190
+ A 10.0.1.191
+ A 10.0.1.192
+ A 10.0.1.193
+ A 10.0.1.194
+ A 10.0.1.195
+ A 10.0.1.196
+ A 10.0.1.197
+ A 10.0.1.198
+ A 10.0.1.199
+ A 10.0.1.200
+ A 10.0.1.201
+ A 10.0.1.202
+ A 10.0.1.203
+ A 10.0.1.204
+ A 10.0.1.205
+ A 10.0.1.206
+ A 10.0.1.207
+ A 10.0.1.208
+ A 10.0.1.209
+ A 10.0.1.210
+ A 10.0.1.211
+ A 10.0.1.212
+ A 10.0.1.213
+ A 10.0.1.214
+ A 10.0.1.215
+ A 10.0.1.216
+ A 10.0.1.217
+ A 10.0.1.218
+ A 10.0.1.219
+ A 10.0.1.220
+ A 10.0.1.221
+ A 10.0.1.222
+ A 10.0.1.223
+ A 10.0.1.224
+ A 10.0.1.225
+ A 10.0.1.226
+ A 10.0.1.227
+ A 10.0.1.228
+ A 10.0.1.229
+ A 10.0.1.230
+ A 10.0.1.231
+ A 10.0.1.232
+ A 10.0.1.233
+ A 10.0.1.234
+ A 10.0.1.235
+ A 10.0.1.236
+ A 10.0.1.237
+ A 10.0.1.238
+ A 10.0.1.239
+ A 10.0.1.240
+ A 10.0.1.241
+ A 10.0.1.242
+ A 10.0.1.243
+ A 10.0.1.244
+ A 10.0.1.245
+ A 10.0.1.246
+ A 10.0.1.247
+ A 10.0.1.248
+ A 10.0.1.249
+ A 10.0.1.250
+ A 10.0.1.251
+ A 10.0.1.252
+ A 10.0.1.253
+ A 10.0.1.254
+ A 10.0.1.255
+ A 10.0.2.0
+ A 10.0.2.1
+ A 10.0.2.2
+ A 10.0.2.3
+ A 10.0.2.4
+ A 10.0.2.5
+ A 10.0.2.6
+ A 10.0.2.7
+ A 10.0.2.8
+ A 10.0.2.9
+ A 10.0.2.10
+ A 10.0.2.11
+ A 10.0.2.12
+ A 10.0.2.13
+ A 10.0.2.14
+ A 10.0.2.15
+ A 10.0.2.16
+ A 10.0.2.17
+ A 10.0.2.18
+ A 10.0.2.19
+ A 10.0.2.20
+ A 10.0.2.21
+ A 10.0.2.22
+ A 10.0.2.23
+ A 10.0.2.24
+ A 10.0.2.25
+ A 10.0.2.26
+ A 10.0.2.27
+ A 10.0.2.28
+ A 10.0.2.29
+ A 10.0.2.30
+ A 10.0.2.31
+ A 10.0.2.32
+ A 10.0.2.33
+ A 10.0.2.34
+ A 10.0.2.35
+ A 10.0.2.36
+ A 10.0.2.37
+ A 10.0.2.38
+ A 10.0.2.39
+ A 10.0.2.40
+ A 10.0.2.41
+ A 10.0.2.42
+ A 10.0.2.43
+ A 10.0.2.44
+ A 10.0.2.45
+ A 10.0.2.46
+ A 10.0.2.47
+ A 10.0.2.48
+ A 10.0.2.49
+ A 10.0.2.50
+ A 10.0.2.51
+ A 10.0.2.52
+ A 10.0.2.53
+ A 10.0.2.54
+ A 10.0.2.55
+ A 10.0.2.56
+ A 10.0.2.57
+ A 10.0.2.58
+ A 10.0.2.59
+ A 10.0.2.60
+ A 10.0.2.61
+ A 10.0.2.62
+ A 10.0.2.63
+ A 10.0.2.64
+ A 10.0.2.65
+ A 10.0.2.66
+ A 10.0.2.67
+ A 10.0.2.68
+ A 10.0.2.69
+ A 10.0.2.70
+ A 10.0.2.71
+ A 10.0.2.72
+ A 10.0.2.73
+ A 10.0.2.74
+ A 10.0.2.75
+ A 10.0.2.76
+ A 10.0.2.77
+ A 10.0.2.78
+ A 10.0.2.79
+ A 10.0.2.80
+ A 10.0.2.81
+ A 10.0.2.82
+ A 10.0.2.83
+ A 10.0.2.84
+ A 10.0.2.85
+ A 10.0.2.86
+ A 10.0.2.87
+ A 10.0.2.88
+ A 10.0.2.89
+ A 10.0.2.90
+ A 10.0.2.91
+ A 10.0.2.92
+ A 10.0.2.93
+ A 10.0.2.94
+ A 10.0.2.95
+ A 10.0.2.96
+ A 10.0.2.97
+ A 10.0.2.98
+ A 10.0.2.99
+ A 10.0.2.100
+ A 10.0.2.101
+ A 10.0.2.102
+ A 10.0.2.103
+ A 10.0.2.104
+ A 10.0.2.105
+ A 10.0.2.106
+ A 10.0.2.107
+ A 10.0.2.108
+ A 10.0.2.109
+ A 10.0.2.110
+ A 10.0.2.111
+ A 10.0.2.112
+ A 10.0.2.113
+ A 10.0.2.114
+ A 10.0.2.115
+ A 10.0.2.116
+ A 10.0.2.117
+ A 10.0.2.118
+ A 10.0.2.119
+ A 10.0.2.120
+ A 10.0.2.121
+ A 10.0.2.122
+ A 10.0.2.123
+ A 10.0.2.124
+ A 10.0.2.125
+ A 10.0.2.126
+ A 10.0.2.127
+ A 10.0.2.128
+ A 10.0.2.129
+ A 10.0.2.130
+ A 10.0.2.131
+ A 10.0.2.132
+ A 10.0.2.133
+ A 10.0.2.134
+ A 10.0.2.135
+ A 10.0.2.136
+ A 10.0.2.137
+ A 10.0.2.138
+ A 10.0.2.139
+ A 10.0.2.140
+ A 10.0.2.141
+ A 10.0.2.142
+ A 10.0.2.143
+ A 10.0.2.144
+ A 10.0.2.145
+ A 10.0.2.146
+ A 10.0.2.147
+ A 10.0.2.148
+ A 10.0.2.149
+ A 10.0.2.150
+ A 10.0.2.151
+ A 10.0.2.152
+ A 10.0.2.153
+ A 10.0.2.154
+ A 10.0.2.155
+ A 10.0.2.156
+ A 10.0.2.157
+ A 10.0.2.158
+ A 10.0.2.159
+ A 10.0.2.160
+ A 10.0.2.161
+ A 10.0.2.162
+ A 10.0.2.163
+ A 10.0.2.164
+ A 10.0.2.165
+ A 10.0.2.166
+ A 10.0.2.167
+ A 10.0.2.168
+ A 10.0.2.169
+ A 10.0.2.170
+ A 10.0.2.171
+ A 10.0.2.172
+ A 10.0.2.173
+ A 10.0.2.174
+ A 10.0.2.175
+ A 10.0.2.176
+ A 10.0.2.177
+ A 10.0.2.178
+ A 10.0.2.179
+ A 10.0.2.180
+ A 10.0.2.181
+ A 10.0.2.182
+ A 10.0.2.183
+ A 10.0.2.184
+ A 10.0.2.185
+ A 10.0.2.186
+ A 10.0.2.187
+ A 10.0.2.188
+ A 10.0.2.189
+ A 10.0.2.190
+ A 10.0.2.191
+ A 10.0.2.192
+ A 10.0.2.193
+ A 10.0.2.194
+ A 10.0.2.195
+ A 10.0.2.196
+ A 10.0.2.197
+ A 10.0.2.198
+ A 10.0.2.199
+ A 10.0.2.200
+ A 10.0.2.201
+ A 10.0.2.202
+ A 10.0.2.203
+ A 10.0.2.204
+ A 10.0.2.205
+ A 10.0.2.206
+ A 10.0.2.207
+ A 10.0.2.208
+ A 10.0.2.209
+ A 10.0.2.210
+ A 10.0.2.211
+ A 10.0.2.212
+ A 10.0.2.213
+ A 10.0.2.214
+ A 10.0.2.215
+ A 10.0.2.216
+ A 10.0.2.217
+ A 10.0.2.218
+ A 10.0.2.219
+ A 10.0.2.220
+ A 10.0.2.221
+ A 10.0.2.222
+ A 10.0.2.223
+ A 10.0.2.224
+ A 10.0.2.225
+ A 10.0.2.226
+ A 10.0.2.227
+ A 10.0.2.228
+ A 10.0.2.229
+ A 10.0.2.230
+ A 10.0.2.231
+ A 10.0.2.232
+ A 10.0.2.233
+ A 10.0.2.234
+ A 10.0.2.235
+ A 10.0.2.236
+ A 10.0.2.237
+ A 10.0.2.238
+ A 10.0.2.239
+ A 10.0.2.240
+ A 10.0.2.241
+ A 10.0.2.242
+ A 10.0.2.243
+ A 10.0.2.244
+ A 10.0.2.245
+ A 10.0.2.246
+ A 10.0.2.247
+ A 10.0.2.248
+ A 10.0.2.249
+ A 10.0.2.250
+ A 10.0.2.251
+ A 10.0.2.252
+ A 10.0.2.253
+ A 10.0.2.254
+ A 10.0.2.255
+ A 10.0.3.0
+ A 10.0.3.1
+ A 10.0.3.2
+ A 10.0.3.3
+ A 10.0.3.4
+ A 10.0.3.5
+ A 10.0.3.6
+ A 10.0.3.7
+ A 10.0.3.8
+ A 10.0.3.9
+ A 10.0.3.10
+ A 10.0.3.11
+ A 10.0.3.12
+ A 10.0.3.13
+ A 10.0.3.14
+ A 10.0.3.15
+ A 10.0.3.16
+ A 10.0.3.17
+ A 10.0.3.18
+ A 10.0.3.19
+ A 10.0.3.20
+ A 10.0.3.21
+ A 10.0.3.22
+ A 10.0.3.23
+ A 10.0.3.24
+ A 10.0.3.25
+ A 10.0.3.26
+ A 10.0.3.27
+ A 10.0.3.28
+ A 10.0.3.29
+ A 10.0.3.30
+ A 10.0.3.31
+ A 10.0.3.32
+ A 10.0.3.33
+ A 10.0.3.34
+ A 10.0.3.35
+ A 10.0.3.36
+ A 10.0.3.37
+ A 10.0.3.38
+ A 10.0.3.39
+ A 10.0.3.40
+ A 10.0.3.41
+ A 10.0.3.42
+ A 10.0.3.43
+ A 10.0.3.44
+ A 10.0.3.45
+ A 10.0.3.46
+ A 10.0.3.47
+ A 10.0.3.48
+ A 10.0.3.49
+ A 10.0.3.50
+ A 10.0.3.51
+ A 10.0.3.52
+ A 10.0.3.53
+ A 10.0.3.54
+ A 10.0.3.55
+ A 10.0.3.56
+ A 10.0.3.57
+ A 10.0.3.58
+ A 10.0.3.59
+ A 10.0.3.60
+ A 10.0.3.61
+ A 10.0.3.62
+ A 10.0.3.63
+ A 10.0.3.64
+ A 10.0.3.65
+ A 10.0.3.66
+ A 10.0.3.67
+ A 10.0.3.68
+ A 10.0.3.69
+ A 10.0.3.70
+ A 10.0.3.71
+ A 10.0.3.72
+ A 10.0.3.73
+ A 10.0.3.74
+ A 10.0.3.75
+ A 10.0.3.76
+ A 10.0.3.77
+ A 10.0.3.78
+ A 10.0.3.79
+ A 10.0.3.80
+ A 10.0.3.81
+ A 10.0.3.82
+ A 10.0.3.83
+ A 10.0.3.84
+ A 10.0.3.85
+ A 10.0.3.86
+ A 10.0.3.87
+ A 10.0.3.88
+ A 10.0.3.89
+ A 10.0.3.90
+ A 10.0.3.91
+ A 10.0.3.92
+ A 10.0.3.93
+ A 10.0.3.94
+ A 10.0.3.95
+ A 10.0.3.96
+ A 10.0.3.97
+ A 10.0.3.98
+ A 10.0.3.99
+ A 10.0.3.100
+ A 10.0.3.101
+ A 10.0.3.102
+ A 10.0.3.103
+ A 10.0.3.104
+ A 10.0.3.105
+ A 10.0.3.106
+ A 10.0.3.107
+ A 10.0.3.108
+ A 10.0.3.109
+ A 10.0.3.110
+ A 10.0.3.111
+ A 10.0.3.112
+ A 10.0.3.113
+ A 10.0.3.114
+ A 10.0.3.115
+ A 10.0.3.116
+ A 10.0.3.117
+ A 10.0.3.118
+ A 10.0.3.119
+ A 10.0.3.120
+ A 10.0.3.121
+ A 10.0.3.122
+ A 10.0.3.123
+ A 10.0.3.124
+ A 10.0.3.125
+ A 10.0.3.126
+ A 10.0.3.127
+ A 10.0.3.128
+ A 10.0.3.129
+ A 10.0.3.130
+ A 10.0.3.131
+ A 10.0.3.132
+ A 10.0.3.133
+ A 10.0.3.134
+ A 10.0.3.135
+ A 10.0.3.136
+ A 10.0.3.137
+ A 10.0.3.138
+ A 10.0.3.139
+ A 10.0.3.140
+ A 10.0.3.141
+ A 10.0.3.142
+ A 10.0.3.143
+ A 10.0.3.144
+ A 10.0.3.145
+ A 10.0.3.146
+ A 10.0.3.147
+ A 10.0.3.148
+ A 10.0.3.149
+ A 10.0.3.150
+ A 10.0.3.151
+ A 10.0.3.152
+ A 10.0.3.153
+ A 10.0.3.154
+ A 10.0.3.155
+ A 10.0.3.156
+ A 10.0.3.157
+ A 10.0.3.158
+ A 10.0.3.159
+ A 10.0.3.160
+ A 10.0.3.161
+ A 10.0.3.162
+ A 10.0.3.163
+ A 10.0.3.164
+ A 10.0.3.165
+ A 10.0.3.166
+ A 10.0.3.167
+ A 10.0.3.168
+ A 10.0.3.169
+ A 10.0.3.170
+ A 10.0.3.171
+ A 10.0.3.172
+ A 10.0.3.173
+ A 10.0.3.174
+ A 10.0.3.175
+ A 10.0.3.176
+ A 10.0.3.177
+ A 10.0.3.178
+ A 10.0.3.179
+ A 10.0.3.180
+ A 10.0.3.181
+ A 10.0.3.182
+ A 10.0.3.183
+ A 10.0.3.184
+ A 10.0.3.185
+ A 10.0.3.186
+ A 10.0.3.187
+ A 10.0.3.188
+ A 10.0.3.189
+ A 10.0.3.190
+ A 10.0.3.191
+ A 10.0.3.192
+ A 10.0.3.193
+ A 10.0.3.194
+ A 10.0.3.195
+ A 10.0.3.196
+ A 10.0.3.197
+ A 10.0.3.198
+ A 10.0.3.199
+ A 10.0.3.200
+ A 10.0.3.201
+ A 10.0.3.202
+ A 10.0.3.203
+ A 10.0.3.204
+ A 10.0.3.205
+ A 10.0.3.206
+ A 10.0.3.207
+ A 10.0.3.208
+ A 10.0.3.209
+ A 10.0.3.210
+ A 10.0.3.211
+ A 10.0.3.212
+ A 10.0.3.213
+ A 10.0.3.214
+ A 10.0.3.215
+ A 10.0.3.216
+ A 10.0.3.217
+ A 10.0.3.218
+ A 10.0.3.219
+ A 10.0.3.220
+ A 10.0.3.221
+ A 10.0.3.222
+ A 10.0.3.223
+ A 10.0.3.224
+ A 10.0.3.225
+ A 10.0.3.226
+ A 10.0.3.227
+ A 10.0.3.228
+ A 10.0.3.229
+ A 10.0.3.230
+ A 10.0.3.231
+ A 10.0.3.232
+ A 10.0.3.233
+ A 10.0.3.234
+ A 10.0.3.235
+ A 10.0.3.236
+ A 10.0.3.237
+ A 10.0.3.238
+ A 10.0.3.239
+ A 10.0.3.240
+ A 10.0.3.241
+ A 10.0.3.242
+ A 10.0.3.243
+ A 10.0.3.244
+ A 10.0.3.245
+ A 10.0.3.246
+ A 10.0.3.247
+ A 10.0.3.248
+ A 10.0.3.249
+ A 10.0.3.250
+ A 10.0.3.251
+ A 10.0.3.252
+ A 10.0.3.253
+ A 10.0.3.254
+ A 10.0.3.255
+ A 10.0.4.0
+ A 10.0.4.1
+ A 10.0.4.2
+ A 10.0.4.3
+ A 10.0.4.4
+ A 10.0.4.5
+ A 10.0.4.6
+ A 10.0.4.7
+ A 10.0.4.8
+ A 10.0.4.9
+ A 10.0.4.10
+ A 10.0.4.11
+ A 10.0.4.12
+ A 10.0.4.13
+ A 10.0.4.14
+ A 10.0.4.15
+ A 10.0.4.16
+ A 10.0.4.17
+ A 10.0.4.18
+ A 10.0.4.19
+ A 10.0.4.20
+ A 10.0.4.21
+ A 10.0.4.22
+ A 10.0.4.23
+ A 10.0.4.24
+ A 10.0.4.25
+ A 10.0.4.26
+ A 10.0.4.27
+ A 10.0.4.28
+ A 10.0.4.29
+ A 10.0.4.30
+ A 10.0.4.31
+ A 10.0.4.32
+ A 10.0.4.33
+ A 10.0.4.34
+ A 10.0.4.35
+ A 10.0.4.36
+ A 10.0.4.37
+ A 10.0.4.38
+ A 10.0.4.39
+ A 10.0.4.40
+ A 10.0.4.41
+ A 10.0.4.42
+ A 10.0.4.43
+ A 10.0.4.44
+ A 10.0.4.45
+ A 10.0.4.46
+ A 10.0.4.47
+ A 10.0.4.48
+ A 10.0.4.49
+ A 10.0.4.50
+ A 10.0.4.51
+ A 10.0.4.52
+ A 10.0.4.53
+ A 10.0.4.54
+ A 10.0.4.55
+ A 10.0.4.56
+ A 10.0.4.57
+ A 10.0.4.58
+ A 10.0.4.59
+ A 10.0.4.60
+ A 10.0.4.61
+ A 10.0.4.62
+ A 10.0.4.63
+ A 10.0.4.64
+ A 10.0.4.65
+ A 10.0.4.66
+ A 10.0.4.67
+ A 10.0.4.68
+ A 10.0.4.69
+ A 10.0.4.70
+ A 10.0.4.71
+ A 10.0.4.72
+ A 10.0.4.73
+ A 10.0.4.74
+ A 10.0.4.75
+ A 10.0.4.76
+ A 10.0.4.77
+ A 10.0.4.78
+ A 10.0.4.79
+ A 10.0.4.80
+ A 10.0.4.81
+ A 10.0.4.82
+ A 10.0.4.83
+ A 10.0.4.84
+ A 10.0.4.85
+ A 10.0.4.86
+ A 10.0.4.87
+ A 10.0.4.88
+ A 10.0.4.89
+ A 10.0.4.90
+ A 10.0.4.91
+ A 10.0.4.92
+ A 10.0.4.93
+ A 10.0.4.94
+ A 10.0.4.95
+ A 10.0.4.96
+ A 10.0.4.97
+ A 10.0.4.98
+ A 10.0.4.99
+ A 10.0.4.100
+ A 10.0.4.101
+ A 10.0.4.102
+ A 10.0.4.103
+ A 10.0.4.104
+ A 10.0.4.105
+ A 10.0.4.106
+ A 10.0.4.107
+ A 10.0.4.108
+ A 10.0.4.109
+ A 10.0.4.110
+ A 10.0.4.111
+ A 10.0.4.112
+ A 10.0.4.113
+ A 10.0.4.114
+ A 10.0.4.115
+ A 10.0.4.116
+ A 10.0.4.117
+ A 10.0.4.118
+ A 10.0.4.119
+ A 10.0.4.120
+ A 10.0.4.121
+ A 10.0.4.122
+ A 10.0.4.123
+ A 10.0.4.124
+ A 10.0.4.125
+ A 10.0.4.126
+ A 10.0.4.127
+ A 10.0.4.128
+ A 10.0.4.129
+ A 10.0.4.130
+ A 10.0.4.131
+ A 10.0.4.132
+ A 10.0.4.133
+ A 10.0.4.134
+ A 10.0.4.135
+ A 10.0.4.136
+ A 10.0.4.137
+ A 10.0.4.138
+ A 10.0.4.139
+ A 10.0.4.140
+ A 10.0.4.141
+ A 10.0.4.142
+ A 10.0.4.143
+ A 10.0.4.144
+ A 10.0.4.145
+ A 10.0.4.146
+ A 10.0.4.147
+ A 10.0.4.148
+ A 10.0.4.149
+ A 10.0.4.150
+ A 10.0.4.151
+ A 10.0.4.152
+ A 10.0.4.153
+ A 10.0.4.154
+ A 10.0.4.155
+ A 10.0.4.156
+ A 10.0.4.157
+ A 10.0.4.158
+ A 10.0.4.159
+ A 10.0.4.160
+ A 10.0.4.161
+ A 10.0.4.162
+ A 10.0.4.163
+ A 10.0.4.164
+ A 10.0.4.165
+ A 10.0.4.166
+ A 10.0.4.167
+ A 10.0.4.168
+ A 10.0.4.169
+ A 10.0.4.170
+ A 10.0.4.171
+ A 10.0.4.172
+ A 10.0.4.173
+ A 10.0.4.174
+ A 10.0.4.175
+ A 10.0.4.176
+ A 10.0.4.177
+ A 10.0.4.178
+ A 10.0.4.179
+ A 10.0.4.180
+ A 10.0.4.181
+ A 10.0.4.182
+ A 10.0.4.183
+ A 10.0.4.184
+ A 10.0.4.185
+ A 10.0.4.186
+ A 10.0.4.187
+ A 10.0.4.188
+ A 10.0.4.189
+ A 10.0.4.190
+ A 10.0.4.191
+ A 10.0.4.192
+ A 10.0.4.193
+ A 10.0.4.194
+ A 10.0.4.195
+ A 10.0.4.196
+ A 10.0.4.197
+ A 10.0.4.198
+ A 10.0.4.199
+ A 10.0.4.200
+ A 10.0.4.201
+ A 10.0.4.202
+ A 10.0.4.203
+ A 10.0.4.204
+ A 10.0.4.205
+ A 10.0.4.206
+ A 10.0.4.207
+ A 10.0.4.208
+ A 10.0.4.209
+ A 10.0.4.210
+ A 10.0.4.211
+ A 10.0.4.212
+ A 10.0.4.213
+ A 10.0.4.214
+ A 10.0.4.215
+ A 10.0.4.216
+ A 10.0.4.217
+ A 10.0.4.218
+ A 10.0.4.219
+ A 10.0.4.220
+ A 10.0.4.221
+ A 10.0.4.222
+ A 10.0.4.223
+ A 10.0.4.224
+ A 10.0.4.225
+ A 10.0.4.226
+ A 10.0.4.227
+ A 10.0.4.228
+ A 10.0.4.229
+ A 10.0.4.230
+ A 10.0.4.231
+ A 10.0.4.232
+ A 10.0.4.233
+ A 10.0.4.234
+ A 10.0.4.235
+ A 10.0.4.236
+ A 10.0.4.237
+ A 10.0.4.238
+ A 10.0.4.239
+ A 10.0.4.240
+ A 10.0.4.241
+ A 10.0.4.242
+ A 10.0.4.243
+ A 10.0.4.244
+ A 10.0.4.245
+ A 10.0.4.246
+ A 10.0.4.247
+ A 10.0.4.248
+ A 10.0.4.249
+ A 10.0.4.250
+ A 10.0.4.251
+ A 10.0.4.252
+ A 10.0.4.253
+ A 10.0.4.254
+ A 10.0.4.255
+ A 10.0.5.0
+ A 10.0.5.1
+ A 10.0.5.2
+ A 10.0.5.3
+ A 10.0.5.4
+ A 10.0.5.5
+ A 10.0.5.6
+ A 10.0.5.7
+ A 10.0.5.8
+ A 10.0.5.9
+ A 10.0.5.10
+ A 10.0.5.11
+ A 10.0.5.12
+ A 10.0.5.13
+ A 10.0.5.14
+ A 10.0.5.15
+ A 10.0.5.16
+ A 10.0.5.17
+ A 10.0.5.18
+ A 10.0.5.19
+ A 10.0.5.20
+ A 10.0.5.21
+ A 10.0.5.22
+ A 10.0.5.23
+ A 10.0.5.24
+ A 10.0.5.25
+ A 10.0.5.26
+ A 10.0.5.27
+ A 10.0.5.28
+ A 10.0.5.29
+ A 10.0.5.30
+ A 10.0.5.31
+ A 10.0.5.32
+ A 10.0.5.33
+ A 10.0.5.34
+ A 10.0.5.35
+ A 10.0.5.36
+ A 10.0.5.37
+ A 10.0.5.38
+ A 10.0.5.39
+ A 10.0.5.40
+ A 10.0.5.41
+ A 10.0.5.42
+ A 10.0.5.43
+ A 10.0.5.44
+ A 10.0.5.45
+ A 10.0.5.46
+ A 10.0.5.47
+ A 10.0.5.48
+ A 10.0.5.49
+ A 10.0.5.50
+ A 10.0.5.51
+ A 10.0.5.52
+ A 10.0.5.53
+ A 10.0.5.54
+ A 10.0.5.55
+ A 10.0.5.56
+ A 10.0.5.57
+ A 10.0.5.58
+ A 10.0.5.59
+ A 10.0.5.60
+ A 10.0.5.61
+ A 10.0.5.62
+ A 10.0.5.63
+ A 10.0.5.64
+ A 10.0.5.65
+ A 10.0.5.66
+ A 10.0.5.67
+ A 10.0.5.68
+ A 10.0.5.69
+ A 10.0.5.70
+ A 10.0.5.71
+ A 10.0.5.72
+ A 10.0.5.73
+ A 10.0.5.74
+ A 10.0.5.75
+ A 10.0.5.76
+ A 10.0.5.77
+ A 10.0.5.78
+ A 10.0.5.79
+ A 10.0.5.80
+ A 10.0.5.81
+ A 10.0.5.82
+ A 10.0.5.83
+ A 10.0.5.84
+ A 10.0.5.85
+ A 10.0.5.86
+ A 10.0.5.87
+ A 10.0.5.88
+ A 10.0.5.89
+ A 10.0.5.90
+ A 10.0.5.91
+ A 10.0.5.92
+ A 10.0.5.93
+ A 10.0.5.94
+ A 10.0.5.95
+ A 10.0.5.96
+ A 10.0.5.97
+ A 10.0.5.98
+ A 10.0.5.99
+ A 10.0.5.100
+ A 10.0.5.101
+ A 10.0.5.102
+ A 10.0.5.103
+ A 10.0.5.104
+ A 10.0.5.105
+ A 10.0.5.106
+ A 10.0.5.107
+ A 10.0.5.108
+ A 10.0.5.109
+ A 10.0.5.110
+ A 10.0.5.111
+ A 10.0.5.112
+ A 10.0.5.113
+ A 10.0.5.114
+ A 10.0.5.115
+ A 10.0.5.116
+ A 10.0.5.117
+ A 10.0.5.118
+ A 10.0.5.119
+ A 10.0.5.120
+ A 10.0.5.121
+ A 10.0.5.122
+ A 10.0.5.123
+ A 10.0.5.124
+ A 10.0.5.125
+ A 10.0.5.126
+ A 10.0.5.127
+ A 10.0.5.128
+ A 10.0.5.129
+ A 10.0.5.130
+ A 10.0.5.131
+ A 10.0.5.132
+ A 10.0.5.133
+ A 10.0.5.134
+ A 10.0.5.135
+ A 10.0.5.136
+ A 10.0.5.137
+ A 10.0.5.138
+ A 10.0.5.139
+ A 10.0.5.140
+ A 10.0.5.141
+ A 10.0.5.142
+ A 10.0.5.143
+ A 10.0.5.144
+ A 10.0.5.145
+ A 10.0.5.146
+ A 10.0.5.147
+ A 10.0.5.148
+ A 10.0.5.149
+ A 10.0.5.150
+ A 10.0.5.151
+ A 10.0.5.152
+ A 10.0.5.153
+ A 10.0.5.154
+ A 10.0.5.155
+ A 10.0.5.156
+ A 10.0.5.157
+ A 10.0.5.158
+ A 10.0.5.159
+ A 10.0.5.160
+ A 10.0.5.161
+ A 10.0.5.162
+ A 10.0.5.163
+ A 10.0.5.164
+ A 10.0.5.165
+ A 10.0.5.166
+ A 10.0.5.167
+ A 10.0.5.168
+ A 10.0.5.169
+ A 10.0.5.170
+ A 10.0.5.171
+ A 10.0.5.172
+ A 10.0.5.173
+ A 10.0.5.174
+ A 10.0.5.175
+ A 10.0.5.176
+ A 10.0.5.177
+ A 10.0.5.178
+ A 10.0.5.179
+ A 10.0.5.180
+ A 10.0.5.181
+ A 10.0.5.182
+ A 10.0.5.183
+ A 10.0.5.184
+ A 10.0.5.185
+ A 10.0.5.186
+ A 10.0.5.187
+ A 10.0.5.188
+ A 10.0.5.189
+ A 10.0.5.190
+ A 10.0.5.191
+ A 10.0.5.192
+ A 10.0.5.193
+ A 10.0.5.194
+ A 10.0.5.195
+ A 10.0.5.196
+ A 10.0.5.197
+ A 10.0.5.198
+ A 10.0.5.199
+ A 10.0.5.200
+ A 10.0.5.201
+ A 10.0.5.202
+ A 10.0.5.203
+ A 10.0.5.204
+ A 10.0.5.205
+ A 10.0.5.206
+ A 10.0.5.207
+ A 10.0.5.208
+ A 10.0.5.209
+ A 10.0.5.210
+ A 10.0.5.211
+ A 10.0.5.212
+ A 10.0.5.213
+ A 10.0.5.214
+ A 10.0.5.215
+ A 10.0.5.216
+ A 10.0.5.217
+ A 10.0.5.218
+ A 10.0.5.219
+ A 10.0.5.220
+ A 10.0.5.221
+ A 10.0.5.222
+ A 10.0.5.223
+ A 10.0.5.224
+ A 10.0.5.225
+ A 10.0.5.226
+ A 10.0.5.227
+ A 10.0.5.228
+ A 10.0.5.229
+ A 10.0.5.230
+ A 10.0.5.231
+ A 10.0.5.232
+ A 10.0.5.233
+ A 10.0.5.234
+ A 10.0.5.235
+ A 10.0.5.236
+ A 10.0.5.237
+ A 10.0.5.238
+ A 10.0.5.239
+ A 10.0.5.240
+ A 10.0.5.241
+ A 10.0.5.242
+ A 10.0.5.243
+ A 10.0.5.244
+ A 10.0.5.245
+ A 10.0.5.246
+ A 10.0.5.247
+ A 10.0.5.248
+ A 10.0.5.249
+ A 10.0.5.250
+ A 10.0.5.251
+ A 10.0.5.252
+ A 10.0.5.253
+ A 10.0.5.254
+ A 10.0.5.255
+ A 10.0.6.0
+ A 10.0.6.1
+ A 10.0.6.2
+ A 10.0.6.3
+ A 10.0.6.4
+ A 10.0.6.5
+ A 10.0.6.6
+ A 10.0.6.7
+ A 10.0.6.8
+ A 10.0.6.9
+ A 10.0.6.10
+ A 10.0.6.11
+ A 10.0.6.12
+ A 10.0.6.13
+ A 10.0.6.14
+ A 10.0.6.15
+ A 10.0.6.16
+ A 10.0.6.17
+ A 10.0.6.18
+ A 10.0.6.19
+ A 10.0.6.20
+ A 10.0.6.21
+ A 10.0.6.22
+ A 10.0.6.23
+ A 10.0.6.24
+ A 10.0.6.25
+ A 10.0.6.26
+ A 10.0.6.27
+ A 10.0.6.28
+ A 10.0.6.29
+ A 10.0.6.30
+ A 10.0.6.31
+ A 10.0.6.32
+ A 10.0.6.33
+ A 10.0.6.34
+ A 10.0.6.35
+ A 10.0.6.36
+ A 10.0.6.37
+ A 10.0.6.38
+ A 10.0.6.39
+ A 10.0.6.40
+ A 10.0.6.41
+ A 10.0.6.42
+ A 10.0.6.43
+ A 10.0.6.44
+ A 10.0.6.45
+ A 10.0.6.46
+ A 10.0.6.47
+ A 10.0.6.48
+ A 10.0.6.49
+ A 10.0.6.50
+ A 10.0.6.51
+ A 10.0.6.52
+ A 10.0.6.53
+ A 10.0.6.54
+ A 10.0.6.55
+ A 10.0.6.56
+ A 10.0.6.57
+ A 10.0.6.58
+ A 10.0.6.59
+ A 10.0.6.60
+ A 10.0.6.61
+ A 10.0.6.62
+ A 10.0.6.63
+ A 10.0.6.64
+ A 10.0.6.65
+ A 10.0.6.66
+ A 10.0.6.67
+ A 10.0.6.68
+ A 10.0.6.69
+ A 10.0.6.70
+ A 10.0.6.71
+ A 10.0.6.72
+ A 10.0.6.73
+ A 10.0.6.74
+ A 10.0.6.75
+ A 10.0.6.76
+ A 10.0.6.77
+ A 10.0.6.78
+ A 10.0.6.79
+ A 10.0.6.80
+ A 10.0.6.81
+ A 10.0.6.82
+ A 10.0.6.83
+ A 10.0.6.84
+ A 10.0.6.85
+ A 10.0.6.86
+ A 10.0.6.87
+ A 10.0.6.88
+ A 10.0.6.89
+ A 10.0.6.90
+ A 10.0.6.91
+ A 10.0.6.92
+ A 10.0.6.93
+ A 10.0.6.94
+ A 10.0.6.95
+ A 10.0.6.96
+ A 10.0.6.97
+ A 10.0.6.98
+ A 10.0.6.99
+ A 10.0.6.100
+ A 10.0.6.101
+ A 10.0.6.102
+ A 10.0.6.103
+ A 10.0.6.104
+ A 10.0.6.105
+ A 10.0.6.106
+ A 10.0.6.107
+ A 10.0.6.108
+ A 10.0.6.109
+ A 10.0.6.110
+ A 10.0.6.111
+ A 10.0.6.112
+ A 10.0.6.113
+ A 10.0.6.114
+ A 10.0.6.115
+ A 10.0.6.116
+ A 10.0.6.117
+ A 10.0.6.118
+ A 10.0.6.119
+ A 10.0.6.120
+ A 10.0.6.121
+ A 10.0.6.122
+ A 10.0.6.123
+ A 10.0.6.124
+ A 10.0.6.125
+ A 10.0.6.126
+ A 10.0.6.127
+ A 10.0.6.128
+ A 10.0.6.129
+ A 10.0.6.130
+ A 10.0.6.131
+ A 10.0.6.132
+ A 10.0.6.133
+ A 10.0.6.134
+ A 10.0.6.135
+ A 10.0.6.136
+ A 10.0.6.137
+ A 10.0.6.138
+ A 10.0.6.139
+ A 10.0.6.140
+ A 10.0.6.141
+ A 10.0.6.142
+ A 10.0.6.143
+ A 10.0.6.144
+ A 10.0.6.145
+ A 10.0.6.146
+ A 10.0.6.147
+ A 10.0.6.148
+ A 10.0.6.149
+ A 10.0.6.150
+ A 10.0.6.151
+ A 10.0.6.152
+ A 10.0.6.153
+ A 10.0.6.154
+ A 10.0.6.155
+ A 10.0.6.156
+ A 10.0.6.157
+ A 10.0.6.158
+ A 10.0.6.159
+ A 10.0.6.160
+ A 10.0.6.161
+ A 10.0.6.162
+ A 10.0.6.163
+ A 10.0.6.164
+ A 10.0.6.165
+ A 10.0.6.166
+ A 10.0.6.167
+ A 10.0.6.168
+ A 10.0.6.169
+ A 10.0.6.170
+ A 10.0.6.171
+ A 10.0.6.172
+ A 10.0.6.173
+ A 10.0.6.174
+ A 10.0.6.175
+ A 10.0.6.176
+ A 10.0.6.177
+ A 10.0.6.178
+ A 10.0.6.179
+ A 10.0.6.180
+ A 10.0.6.181
+ A 10.0.6.182
+ A 10.0.6.183
+ A 10.0.6.184
+ A 10.0.6.185
+ A 10.0.6.186
+ A 10.0.6.187
+ A 10.0.6.188
+ A 10.0.6.189
+ A 10.0.6.190
+ A 10.0.6.191
+ A 10.0.6.192
+ A 10.0.6.193
+ A 10.0.6.194
+ A 10.0.6.195
+ A 10.0.6.196
+ A 10.0.6.197
+ A 10.0.6.198
+ A 10.0.6.199
+ A 10.0.6.200
+ A 10.0.6.201
+ A 10.0.6.202
+ A 10.0.6.203
+ A 10.0.6.204
+ A 10.0.6.205
+ A 10.0.6.206
+ A 10.0.6.207
+ A 10.0.6.208
+ A 10.0.6.209
+ A 10.0.6.210
+ A 10.0.6.211
+ A 10.0.6.212
+ A 10.0.6.213
+ A 10.0.6.214
+ A 10.0.6.215
+ A 10.0.6.216
+ A 10.0.6.217
+ A 10.0.6.218
+ A 10.0.6.219
+ A 10.0.6.220
+ A 10.0.6.221
+ A 10.0.6.222
+ A 10.0.6.223
+ A 10.0.6.224
+ A 10.0.6.225
+ A 10.0.6.226
+ A 10.0.6.227
+ A 10.0.6.228
+ A 10.0.6.229
+ A 10.0.6.230
+ A 10.0.6.231
+ A 10.0.6.232
+ A 10.0.6.233
+ A 10.0.6.234
+ A 10.0.6.235
+ A 10.0.6.236
+ A 10.0.6.237
+ A 10.0.6.238
+ A 10.0.6.239
+ A 10.0.6.240
+ A 10.0.6.241
+ A 10.0.6.242
+ A 10.0.6.243
+ A 10.0.6.244
+ A 10.0.6.245
+ A 10.0.6.246
+ A 10.0.6.247
+ A 10.0.6.248
+ A 10.0.6.249
+ A 10.0.6.250
+ A 10.0.6.251
+ A 10.0.6.252
+ A 10.0.6.253
+ A 10.0.6.254
+ A 10.0.6.255
+ A 10.0.7.0
+ A 10.0.7.1
+ A 10.0.7.2
+ A 10.0.7.3
+ A 10.0.7.4
+ A 10.0.7.5
+ A 10.0.7.6
+ A 10.0.7.7
+ A 10.0.7.8
+ A 10.0.7.9
+ A 10.0.7.10
+ A 10.0.7.11
+ A 10.0.7.12
+ A 10.0.7.13
+ A 10.0.7.14
+ A 10.0.7.15
+ A 10.0.7.16
+ A 10.0.7.17
+ A 10.0.7.18
+ A 10.0.7.19
+ A 10.0.7.20
+ A 10.0.7.21
+ A 10.0.7.22
+ A 10.0.7.23
+ A 10.0.7.24
+ A 10.0.7.25
+ A 10.0.7.26
+ A 10.0.7.27
+ A 10.0.7.28
+ A 10.0.7.29
+ A 10.0.7.30
+ A 10.0.7.31
+ A 10.0.7.32
+ A 10.0.7.33
+ A 10.0.7.34
+ A 10.0.7.35
+ A 10.0.7.36
+ A 10.0.7.37
+ A 10.0.7.38
+ A 10.0.7.39
+ A 10.0.7.40
+ A 10.0.7.41
+ A 10.0.7.42
+ A 10.0.7.43
+ A 10.0.7.44
+ A 10.0.7.45
+ A 10.0.7.46
+ A 10.0.7.47
+ A 10.0.7.48
+ A 10.0.7.49
+ A 10.0.7.50
+ A 10.0.7.51
+ A 10.0.7.52
+ A 10.0.7.53
+ A 10.0.7.54
+ A 10.0.7.55
+ A 10.0.7.56
+ A 10.0.7.57
+ A 10.0.7.58
+ A 10.0.7.59
+ A 10.0.7.60
+ A 10.0.7.61
+ A 10.0.7.62
+ A 10.0.7.63
+ A 10.0.7.64
+ A 10.0.7.65
+ A 10.0.7.66
+ A 10.0.7.67
+ A 10.0.7.68
+ A 10.0.7.69
+ A 10.0.7.70
+ A 10.0.7.71
+ A 10.0.7.72
+ A 10.0.7.73
+ A 10.0.7.74
+ A 10.0.7.75
+ A 10.0.7.76
+ A 10.0.7.77
+ A 10.0.7.78
+ A 10.0.7.79
+ A 10.0.7.80
+ A 10.0.7.81
+ A 10.0.7.82
+ A 10.0.7.83
+ A 10.0.7.84
+ A 10.0.7.85
+ A 10.0.7.86
+ A 10.0.7.87
+ A 10.0.7.88
+ A 10.0.7.89
+ A 10.0.7.90
+ A 10.0.7.91
+ A 10.0.7.92
+ A 10.0.7.93
+ A 10.0.7.94
+ A 10.0.7.95
+ A 10.0.7.96
+ A 10.0.7.97
+ A 10.0.7.98
+ A 10.0.7.99
+ A 10.0.7.100
+ A 10.0.7.101
+ A 10.0.7.102
+ A 10.0.7.103
+ A 10.0.7.104
+ A 10.0.7.105
+ A 10.0.7.106
+ A 10.0.7.107
+ A 10.0.7.108
+ A 10.0.7.109
+ A 10.0.7.110
+ A 10.0.7.111
+ A 10.0.7.112
+ A 10.0.7.113
+ A 10.0.7.114
+ A 10.0.7.115
+ A 10.0.7.116
+ A 10.0.7.117
+ A 10.0.7.118
+ A 10.0.7.119
+ A 10.0.7.120
+ A 10.0.7.121
+ A 10.0.7.122
+ A 10.0.7.123
+ A 10.0.7.124
+ A 10.0.7.125
+ A 10.0.7.126
+ A 10.0.7.127
+ A 10.0.7.128
+ A 10.0.7.129
+ A 10.0.7.130
+ A 10.0.7.131
+ A 10.0.7.132
+ A 10.0.7.133
+ A 10.0.7.134
+ A 10.0.7.135
+ A 10.0.7.136
+ A 10.0.7.137
+ A 10.0.7.138
+ A 10.0.7.139
+ A 10.0.7.140
+ A 10.0.7.141
+ A 10.0.7.142
+ A 10.0.7.143
+ A 10.0.7.144
+ A 10.0.7.145
+ A 10.0.7.146
+ A 10.0.7.147
+ A 10.0.7.148
+ A 10.0.7.149
+ A 10.0.7.150
+ A 10.0.7.151
+ A 10.0.7.152
+ A 10.0.7.153
+ A 10.0.7.154
+ A 10.0.7.155
+ A 10.0.7.156
+ A 10.0.7.157
+ A 10.0.7.158
+ A 10.0.7.159
+ A 10.0.7.160
+ A 10.0.7.161
+ A 10.0.7.162
+ A 10.0.7.163
+ A 10.0.7.164
+ A 10.0.7.165
+ A 10.0.7.166
+ A 10.0.7.167
+ A 10.0.7.168
+ A 10.0.7.169
+ A 10.0.7.170
+ A 10.0.7.171
+ A 10.0.7.172
+ A 10.0.7.173
+ A 10.0.7.174
+ A 10.0.7.175
+ A 10.0.7.176
+ A 10.0.7.177
+ A 10.0.7.178
+ A 10.0.7.179
+ A 10.0.7.180
+ A 10.0.7.181
+ A 10.0.7.182
+ A 10.0.7.183
+ A 10.0.7.184
+ A 10.0.7.185
+ A 10.0.7.186
+ A 10.0.7.187
+ A 10.0.7.188
+ A 10.0.7.189
+ A 10.0.7.190
+ A 10.0.7.191
+ A 10.0.7.192
+ A 10.0.7.193
+ A 10.0.7.194
+ A 10.0.7.195
+ A 10.0.7.196
+ A 10.0.7.197
+ A 10.0.7.198
+ A 10.0.7.199
+ A 10.0.7.200
+ A 10.0.7.201
+ A 10.0.7.202
+ A 10.0.7.203
+ A 10.0.7.204
+ A 10.0.7.205
+ A 10.0.7.206
+ A 10.0.7.207
+ A 10.0.7.208
+ A 10.0.7.209
+ A 10.0.7.210
+ A 10.0.7.211
+ A 10.0.7.212
+ A 10.0.7.213
+ A 10.0.7.214
+ A 10.0.7.215
+ A 10.0.7.216
+ A 10.0.7.217
+ A 10.0.7.218
+ A 10.0.7.219
+ A 10.0.7.220
+ A 10.0.7.221
+ A 10.0.7.222
+ A 10.0.7.223
+ A 10.0.7.224
+ A 10.0.7.225
+ A 10.0.7.226
+ A 10.0.7.227
+ A 10.0.7.228
+ A 10.0.7.229
+ A 10.0.7.230
+ A 10.0.7.231
+ A 10.0.7.232
+ A 10.0.7.233
+ A 10.0.7.234
+ A 10.0.7.235
+ A 10.0.7.236
+ A 10.0.7.237
+ A 10.0.7.238
+ A 10.0.7.239
+ A 10.0.7.240
+ A 10.0.7.241
+ A 10.0.7.242
+ A 10.0.7.243
+ A 10.0.7.244
+ A 10.0.7.245
+ A 10.0.7.246
+ A 10.0.7.247
+ A 10.0.7.248
+ A 10.0.7.249
+ A 10.0.7.250
+ A 10.0.7.251
+ A 10.0.7.252
+ A 10.0.7.253
+ A 10.0.7.254
+ A 10.0.7.255
+ A 10.0.8.0
+ A 10.0.8.1
+ A 10.0.8.2
+ A 10.0.8.3
+ A 10.0.8.4
+ A 10.0.8.5
+ A 10.0.8.6
+ A 10.0.8.7
+ A 10.0.8.8
+ A 10.0.8.9
+ A 10.0.8.10
+ A 10.0.8.11
+ A 10.0.8.12
+ A 10.0.8.13
+ A 10.0.8.14
+ A 10.0.8.15
+ A 10.0.8.16
+ A 10.0.8.17
+ A 10.0.8.18
+ A 10.0.8.19
+ A 10.0.8.20
+ A 10.0.8.21
+ A 10.0.8.22
+ A 10.0.8.23
+ A 10.0.8.24
+ A 10.0.8.25
+ A 10.0.8.26
+ A 10.0.8.27
+ A 10.0.8.28
+ A 10.0.8.29
+ A 10.0.8.30
+ A 10.0.8.31
+ A 10.0.8.32
+ A 10.0.8.33
+ A 10.0.8.34
+ A 10.0.8.35
+ A 10.0.8.36
+ A 10.0.8.37
+ A 10.0.8.38
+ A 10.0.8.39
+ A 10.0.8.40
+ A 10.0.8.41
+ A 10.0.8.42
+ A 10.0.8.43
+ A 10.0.8.44
+ A 10.0.8.45
+ A 10.0.8.46
+ A 10.0.8.47
+ A 10.0.8.48
+ A 10.0.8.49
+ A 10.0.8.50
+ A 10.0.8.51
+ A 10.0.8.52
+ A 10.0.8.53
+ A 10.0.8.54
+ A 10.0.8.55
+ A 10.0.8.56
+ A 10.0.8.57
+ A 10.0.8.58
+ A 10.0.8.59
+ A 10.0.8.60
+ A 10.0.8.61
+ A 10.0.8.62
+ A 10.0.8.63
+ A 10.0.8.64
+ A 10.0.8.65
+ A 10.0.8.66
+ A 10.0.8.67
+ A 10.0.8.68
+ A 10.0.8.69
+ A 10.0.8.70
+ A 10.0.8.71
+ A 10.0.8.72
+ A 10.0.8.73
+ A 10.0.8.74
+ A 10.0.8.75
+ A 10.0.8.76
+ A 10.0.8.77
+ A 10.0.8.78
+ A 10.0.8.79
+ A 10.0.8.80
+ A 10.0.8.81
+ A 10.0.8.82
+ A 10.0.8.83
+ A 10.0.8.84
+ A 10.0.8.85
+ A 10.0.8.86
+ A 10.0.8.87
+ A 10.0.8.88
+ A 10.0.8.89
+ A 10.0.8.90
+ A 10.0.8.91
+ A 10.0.8.92
+ A 10.0.8.93
+ A 10.0.8.94
+ A 10.0.8.95
+ A 10.0.8.96
+ A 10.0.8.97
+ A 10.0.8.98
+ A 10.0.8.99
+ A 10.0.8.100
+ A 10.0.8.101
+ A 10.0.8.102
+ A 10.0.8.103
+ A 10.0.8.104
+ A 10.0.8.105
+ A 10.0.8.106
+ A 10.0.8.107
+ A 10.0.8.108
+ A 10.0.8.109
+ A 10.0.8.110
+ A 10.0.8.111
+ A 10.0.8.112
+ A 10.0.8.113
+ A 10.0.8.114
+ A 10.0.8.115
+ A 10.0.8.116
+ A 10.0.8.117
+ A 10.0.8.118
+ A 10.0.8.119
+ A 10.0.8.120
+ A 10.0.8.121
+ A 10.0.8.122
+ A 10.0.8.123
+ A 10.0.8.124
+ A 10.0.8.125
+ A 10.0.8.126
+ A 10.0.8.127
+ A 10.0.8.128
+ A 10.0.8.129
+ A 10.0.8.130
+ A 10.0.8.131
+ A 10.0.8.132
+ A 10.0.8.133
+ A 10.0.8.134
+ A 10.0.8.135
+ A 10.0.8.136
+ A 10.0.8.137
+ A 10.0.8.138
+ A 10.0.8.139
+ A 10.0.8.140
+ A 10.0.8.141
+ A 10.0.8.142
+ A 10.0.8.143
+ A 10.0.8.144
+ A 10.0.8.145
+ A 10.0.8.146
+ A 10.0.8.147
+ A 10.0.8.148
+ A 10.0.8.149
+ A 10.0.8.150
+ A 10.0.8.151
+ A 10.0.8.152
+ A 10.0.8.153
+ A 10.0.8.154
+ A 10.0.8.155
+ A 10.0.8.156
+ A 10.0.8.157
+ A 10.0.8.158
+ A 10.0.8.159
+ A 10.0.8.160
+ A 10.0.8.161
+ A 10.0.8.162
+ A 10.0.8.163
+ A 10.0.8.164
+ A 10.0.8.165
+ A 10.0.8.166
+ A 10.0.8.167
+ A 10.0.8.168
+ A 10.0.8.169
+ A 10.0.8.170
+ A 10.0.8.171
+ A 10.0.8.172
+ A 10.0.8.173
+ A 10.0.8.174
+ A 10.0.8.175
+ A 10.0.8.176
+ A 10.0.8.177
+ A 10.0.8.178
+ A 10.0.8.179
+ A 10.0.8.180
+ A 10.0.8.181
+ A 10.0.8.182
+ A 10.0.8.183
+ A 10.0.8.184
+ A 10.0.8.185
+ A 10.0.8.186
+ A 10.0.8.187
+ A 10.0.8.188
+ A 10.0.8.189
+ A 10.0.8.190
+ A 10.0.8.191
+ A 10.0.8.192
+ A 10.0.8.193
+ A 10.0.8.194
+ A 10.0.8.195
+ A 10.0.8.196
+ A 10.0.8.197
+ A 10.0.8.198
+ A 10.0.8.199
+ A 10.0.8.200
+ A 10.0.8.201
+ A 10.0.8.202
+ A 10.0.8.203
+ A 10.0.8.204
+ A 10.0.8.205
+ A 10.0.8.206
+ A 10.0.8.207
+ A 10.0.8.208
+ A 10.0.8.209
+ A 10.0.8.210
+ A 10.0.8.211
+ A 10.0.8.212
+ A 10.0.8.213
+ A 10.0.8.214
+ A 10.0.8.215
+ A 10.0.8.216
+ A 10.0.8.217
+ A 10.0.8.218
+ A 10.0.8.219
+ A 10.0.8.220
+ A 10.0.8.221
+ A 10.0.8.222
+ A 10.0.8.223
+ A 10.0.8.224
+ A 10.0.8.225
+ A 10.0.8.226
+ A 10.0.8.227
+ A 10.0.8.228
+ A 10.0.8.229
+ A 10.0.8.230
+ A 10.0.8.231
+ A 10.0.8.232
+ A 10.0.8.233
+ A 10.0.8.234
+ A 10.0.8.235
+ A 10.0.8.236
+ A 10.0.8.237
+ A 10.0.8.238
+ A 10.0.8.239
+ A 10.0.8.240
+ A 10.0.8.241
+ A 10.0.8.242
+ A 10.0.8.243
+ A 10.0.8.244
+ A 10.0.8.245
+ A 10.0.8.246
+ A 10.0.8.247
+ A 10.0.8.248
+ A 10.0.8.249
+ A 10.0.8.250
+ A 10.0.8.251
+ A 10.0.8.252
+ A 10.0.8.253
+ A 10.0.8.254
+ A 10.0.8.255
+ A 10.0.9.0
+ A 10.0.9.1
+ A 10.0.9.2
+ A 10.0.9.3
+ A 10.0.9.4
+ A 10.0.9.5
+ A 10.0.9.6
+ A 10.0.9.7
+ A 10.0.9.8
+ A 10.0.9.9
+ A 10.0.9.10
+ A 10.0.9.11
+ A 10.0.9.12
+ A 10.0.9.13
+ A 10.0.9.14
+ A 10.0.9.15
+ A 10.0.9.16
+ A 10.0.9.17
+ A 10.0.9.18
+ A 10.0.9.19
+ A 10.0.9.20
+ A 10.0.9.21
+ A 10.0.9.22
+ A 10.0.9.23
+ A 10.0.9.24
+ A 10.0.9.25
+ A 10.0.9.26
+ A 10.0.9.27
+ A 10.0.9.28
+ A 10.0.9.29
+ A 10.0.9.30
+ A 10.0.9.31
+ A 10.0.9.32
+ A 10.0.9.33
+ A 10.0.9.34
+ A 10.0.9.35
+ A 10.0.9.36
+ A 10.0.9.37
+ A 10.0.9.38
+ A 10.0.9.39
+ A 10.0.9.40
+ A 10.0.9.41
+ A 10.0.9.42
+ A 10.0.9.43
+ A 10.0.9.44
+ A 10.0.9.45
+ A 10.0.9.46
+ A 10.0.9.47
+ A 10.0.9.48
+ A 10.0.9.49
+ A 10.0.9.50
+ A 10.0.9.51
+ A 10.0.9.52
+ A 10.0.9.53
+ A 10.0.9.54
+ A 10.0.9.55
+ A 10.0.9.56
+ A 10.0.9.57
+ A 10.0.9.58
+ A 10.0.9.59
+ A 10.0.9.60
+ A 10.0.9.61
+ A 10.0.9.62
+ A 10.0.9.63
+ A 10.0.9.64
+ A 10.0.9.65
+ A 10.0.9.66
+ A 10.0.9.67
+ A 10.0.9.68
+ A 10.0.9.69
+ A 10.0.9.70
+ A 10.0.9.71
+ A 10.0.9.72
+ A 10.0.9.73
+ A 10.0.9.74
+ A 10.0.9.75
+ A 10.0.9.76
+ A 10.0.9.77
+ A 10.0.9.78
+ A 10.0.9.79
+ A 10.0.9.80
+ A 10.0.9.81
+ A 10.0.9.82
+ A 10.0.9.83
+ A 10.0.9.84
+ A 10.0.9.85
+ A 10.0.9.86
+ A 10.0.9.87
+ A 10.0.9.88
+ A 10.0.9.89
+ A 10.0.9.90
+ A 10.0.9.91
+ A 10.0.9.92
+ A 10.0.9.93
+ A 10.0.9.94
+ A 10.0.9.95
+ A 10.0.9.96
+ A 10.0.9.97
+ A 10.0.9.98
+ A 10.0.9.99
+ A 10.0.9.100
+ A 10.0.9.101
+ A 10.0.9.102
+ A 10.0.9.103
+ A 10.0.9.104
+ A 10.0.9.105
+ A 10.0.9.106
+ A 10.0.9.107
+ A 10.0.9.108
+ A 10.0.9.109
+ A 10.0.9.110
+ A 10.0.9.111
+ A 10.0.9.112
+ A 10.0.9.113
+ A 10.0.9.114
+ A 10.0.9.115
+ A 10.0.9.116
+ A 10.0.9.117
+ A 10.0.9.118
+ A 10.0.9.119
+ A 10.0.9.120
+ A 10.0.9.121
+ A 10.0.9.122
+ A 10.0.9.123
+ A 10.0.9.124
+ A 10.0.9.125
+ A 10.0.9.126
+ A 10.0.9.127
+ A 10.0.9.128
+ A 10.0.9.129
+ A 10.0.9.130
+ A 10.0.9.131
+ A 10.0.9.132
+ A 10.0.9.133
+ A 10.0.9.134
+ A 10.0.9.135
+ A 10.0.9.136
+ A 10.0.9.137
+ A 10.0.9.138
+ A 10.0.9.139
+ A 10.0.9.140
+ A 10.0.9.141
+ A 10.0.9.142
+ A 10.0.9.143
+ A 10.0.9.144
+ A 10.0.9.145
+ A 10.0.9.146
+ A 10.0.9.147
+ A 10.0.9.148
+ A 10.0.9.149
+ A 10.0.9.150
+ A 10.0.9.151
+ A 10.0.9.152
+ A 10.0.9.153
+ A 10.0.9.154
+ A 10.0.9.155
+ A 10.0.9.156
+ A 10.0.9.157
+ A 10.0.9.158
+ A 10.0.9.159
+ A 10.0.9.160
+ A 10.0.9.161
+ A 10.0.9.162
+ A 10.0.9.163
+ A 10.0.9.164
+ A 10.0.9.165
+ A 10.0.9.166
+ A 10.0.9.167
+ A 10.0.9.168
+ A 10.0.9.169
+ A 10.0.9.170
+ A 10.0.9.171
+ A 10.0.9.172
+ A 10.0.9.173
+ A 10.0.9.174
+ A 10.0.9.175
+ A 10.0.9.176
+ A 10.0.9.177
+ A 10.0.9.178
+ A 10.0.9.179
+ A 10.0.9.180
+ A 10.0.9.181
+ A 10.0.9.182
+ A 10.0.9.183
+ A 10.0.9.184
+ A 10.0.9.185
+ A 10.0.9.186
+ A 10.0.9.187
+ A 10.0.9.188
+ A 10.0.9.189
+ A 10.0.9.190
+ A 10.0.9.191
+ A 10.0.9.192
+ A 10.0.9.193
+ A 10.0.9.194
+ A 10.0.9.195
+ A 10.0.9.196
+ A 10.0.9.197
+ A 10.0.9.198
+ A 10.0.9.199
+ A 10.0.9.200
+ A 10.0.9.201
+ A 10.0.9.202
+ A 10.0.9.203
+ A 10.0.9.204
+ A 10.0.9.205
+ A 10.0.9.206
+ A 10.0.9.207
+ A 10.0.9.208
+ A 10.0.9.209
+ A 10.0.9.210
+ A 10.0.9.211
+ A 10.0.9.212
+ A 10.0.9.213
+ A 10.0.9.214
+ A 10.0.9.215
+ A 10.0.9.216
+ A 10.0.9.217
+ A 10.0.9.218
+ A 10.0.9.219
+ A 10.0.9.220
+ A 10.0.9.221
+ A 10.0.9.222
+ A 10.0.9.223
+ A 10.0.9.224
+ A 10.0.9.225
+ A 10.0.9.226
+ A 10.0.9.227
+ A 10.0.9.228
+ A 10.0.9.229
+ A 10.0.9.230
+ A 10.0.9.231
+ A 10.0.9.232
+ A 10.0.9.233
+ A 10.0.9.234
+ A 10.0.9.235
+ A 10.0.9.236
+ A 10.0.9.237
+ A 10.0.9.238
+ A 10.0.9.239
+ A 10.0.9.240
+ A 10.0.9.241
+ A 10.0.9.242
+ A 10.0.9.243
+ A 10.0.9.244
+ A 10.0.9.245
+ A 10.0.9.246
+ A 10.0.9.247
+ A 10.0.9.248
+ A 10.0.9.249
+ A 10.0.9.250
+ A 10.0.9.251
+ A 10.0.9.252
+ A 10.0.9.253
+ A 10.0.9.254
+ A 10.0.9.255
+ A 10.0.10.0
+ A 10.0.10.1
+ A 10.0.10.2
+ A 10.0.10.3
+ A 10.0.10.4
+ A 10.0.10.5
+ A 10.0.10.6
+ A 10.0.10.7
+ A 10.0.10.8
+ A 10.0.10.9
+ A 10.0.10.10
+ A 10.0.10.11
+ A 10.0.10.12
+ A 10.0.10.13
+ A 10.0.10.14
+ A 10.0.10.15
+ A 10.0.10.16
+ A 10.0.10.17
+ A 10.0.10.18
+ A 10.0.10.19
+ A 10.0.10.20
+ A 10.0.10.21
+ A 10.0.10.22
+ A 10.0.10.23
+ A 10.0.10.24
+ A 10.0.10.25
+ A 10.0.10.26
+ A 10.0.10.27
+ A 10.0.10.28
+ A 10.0.10.29
+ A 10.0.10.30
+ A 10.0.10.31
+ A 10.0.10.32
+ A 10.0.10.33
+ A 10.0.10.34
+ A 10.0.10.35
+ A 10.0.10.36
+ A 10.0.10.37
+ A 10.0.10.38
+ A 10.0.10.39
+ A 10.0.10.40
+ A 10.0.10.41
+ A 10.0.10.42
+ A 10.0.10.43
+ A 10.0.10.44
+ A 10.0.10.45
+ A 10.0.10.46
+ A 10.0.10.47
+ A 10.0.10.48
+ A 10.0.10.49
+ A 10.0.10.50
+ A 10.0.10.51
+ A 10.0.10.52
+ A 10.0.10.53
+ A 10.0.10.54
+ A 10.0.10.55
+ A 10.0.10.56
+ A 10.0.10.57
+ A 10.0.10.58
+ A 10.0.10.59
+ A 10.0.10.60
+ A 10.0.10.61
+ A 10.0.10.62
+ A 10.0.10.63
+ A 10.0.10.64
+ A 10.0.10.65
+ A 10.0.10.66
+ A 10.0.10.67
+ A 10.0.10.68
+ A 10.0.10.69
+ A 10.0.10.70
+ A 10.0.10.71
+ A 10.0.10.72
+ A 10.0.10.73
+ A 10.0.10.74
+ A 10.0.10.75
+ A 10.0.10.76
+ A 10.0.10.77
+ A 10.0.10.78
+ A 10.0.10.79
+ A 10.0.10.80
+ A 10.0.10.81
+ A 10.0.10.82
+ A 10.0.10.83
+ A 10.0.10.84
+ A 10.0.10.85
+ A 10.0.10.86
+ A 10.0.10.87
+ A 10.0.10.88
+ A 10.0.10.89
+ A 10.0.10.90
+ A 10.0.10.91
+ A 10.0.10.92
+ A 10.0.10.93
+ A 10.0.10.94
+ A 10.0.10.95
+ A 10.0.10.96
+ A 10.0.10.97
+ A 10.0.10.98
+ A 10.0.10.99
+ A 10.0.10.100
+ A 10.0.10.101
+ A 10.0.10.102
+ A 10.0.10.103
+ A 10.0.10.104
+ A 10.0.10.105
+ A 10.0.10.106
+ A 10.0.10.107
+ A 10.0.10.108
+ A 10.0.10.109
+ A 10.0.10.110
+ A 10.0.10.111
+ A 10.0.10.112
+ A 10.0.10.113
+ A 10.0.10.114
+ A 10.0.10.115
+ A 10.0.10.116
+ A 10.0.10.117
+ A 10.0.10.118
+ A 10.0.10.119
+ A 10.0.10.120
+ A 10.0.10.121
+ A 10.0.10.122
+ A 10.0.10.123
+ A 10.0.10.124
+ A 10.0.10.125
+ A 10.0.10.126
+ A 10.0.10.127
+ A 10.0.10.128
+ A 10.0.10.129
+ A 10.0.10.130
+ A 10.0.10.131
+ A 10.0.10.132
+ A 10.0.10.133
+ A 10.0.10.134
+ A 10.0.10.135
+ A 10.0.10.136
+ A 10.0.10.137
+ A 10.0.10.138
+ A 10.0.10.139
+ A 10.0.10.140
+ A 10.0.10.141
+ A 10.0.10.142
+ A 10.0.10.143
+ A 10.0.10.144
+ A 10.0.10.145
+ A 10.0.10.146
+ A 10.0.10.147
+ A 10.0.10.148
+ A 10.0.10.149
+ A 10.0.10.150
+ A 10.0.10.151
+ A 10.0.10.152
+ A 10.0.10.153
+ A 10.0.10.154
+ A 10.0.10.155
+ A 10.0.10.156
+ A 10.0.10.157
+ A 10.0.10.158
+ A 10.0.10.159
+ A 10.0.10.160
+ A 10.0.10.161
+ A 10.0.10.162
+ A 10.0.10.163
+ A 10.0.10.164
+ A 10.0.10.165
+ A 10.0.10.166
+ A 10.0.10.167
+ A 10.0.10.168
+ A 10.0.10.169
+ A 10.0.10.170
+ A 10.0.10.171
+ A 10.0.10.172
+ A 10.0.10.173
+ A 10.0.10.174
+ A 10.0.10.175
+ A 10.0.10.176
+ A 10.0.10.177
+ A 10.0.10.178
+ A 10.0.10.179
+ A 10.0.10.180
+ A 10.0.10.181
+ A 10.0.10.182
+ A 10.0.10.183
+ A 10.0.10.184
+ A 10.0.10.185
+ A 10.0.10.186
+ A 10.0.10.187
+ A 10.0.10.188
+ A 10.0.10.189
+ A 10.0.10.190
+ A 10.0.10.191
+ A 10.0.10.192
+ A 10.0.10.193
+ A 10.0.10.194
+ A 10.0.10.195
+ A 10.0.10.196
+ A 10.0.10.197
+ A 10.0.10.198
+ A 10.0.10.199
+ A 10.0.10.200
+ A 10.0.10.201
+ A 10.0.10.202
+ A 10.0.10.203
+ A 10.0.10.204
+ A 10.0.10.205
+ A 10.0.10.206
+ A 10.0.10.207
+ A 10.0.10.208
+ A 10.0.10.209
+ A 10.0.10.210
+ A 10.0.10.211
+ A 10.0.10.212
+ A 10.0.10.213
+ A 10.0.10.214
+ A 10.0.10.215
+ A 10.0.10.216
+ A 10.0.10.217
+ A 10.0.10.218
+ A 10.0.10.219
+ A 10.0.10.220
+ A 10.0.10.221
+ A 10.0.10.222
+ A 10.0.10.223
+ A 10.0.10.224
+ A 10.0.10.225
+ A 10.0.10.226
+ A 10.0.10.227
+ A 10.0.10.228
+ A 10.0.10.229
+ A 10.0.10.230
+ A 10.0.10.231
+ A 10.0.10.232
+ A 10.0.10.233
+ A 10.0.10.234
+ A 10.0.10.235
+ A 10.0.10.236
+ A 10.0.10.237
+ A 10.0.10.238
+ A 10.0.10.239
+ A 10.0.10.240
+ A 10.0.10.241
+ A 10.0.10.242
+ A 10.0.10.243
+ A 10.0.10.244
+ A 10.0.10.245
+ A 10.0.10.246
+ A 10.0.10.247
+ A 10.0.10.248
+ A 10.0.10.249
+ A 10.0.10.250
+ A 10.0.10.251
+ A 10.0.10.252
+ A 10.0.10.253
+ A 10.0.10.254
+ A 10.0.10.255
+ A 10.0.11.0
+ A 10.0.11.1
+ A 10.0.11.2
+ A 10.0.11.3
+ A 10.0.11.4
+ A 10.0.11.5
+ A 10.0.11.6
+ A 10.0.11.7
+ A 10.0.11.8
+ A 10.0.11.9
+ A 10.0.11.10
+ A 10.0.11.11
+ A 10.0.11.12
+ A 10.0.11.13
+ A 10.0.11.14
+ A 10.0.11.15
+ A 10.0.11.16
+ A 10.0.11.17
+ A 10.0.11.18
+ A 10.0.11.19
+ A 10.0.11.20
+ A 10.0.11.21
+ A 10.0.11.22
+ A 10.0.11.23
+ A 10.0.11.24
+ A 10.0.11.25
+ A 10.0.11.26
+ A 10.0.11.27
+ A 10.0.11.28
+ A 10.0.11.29
+ A 10.0.11.30
+ A 10.0.11.31
+ A 10.0.11.32
+ A 10.0.11.33
+ A 10.0.11.34
+ A 10.0.11.35
+ A 10.0.11.36
+ A 10.0.11.37
+ A 10.0.11.38
+ A 10.0.11.39
+ A 10.0.11.40
+ A 10.0.11.41
+ A 10.0.11.42
+ A 10.0.11.43
+ A 10.0.11.44
+ A 10.0.11.45
+ A 10.0.11.46
+ A 10.0.11.47
+ A 10.0.11.48
+ A 10.0.11.49
+ A 10.0.11.50
+ A 10.0.11.51
+ A 10.0.11.52
+ A 10.0.11.53
+ A 10.0.11.54
+ A 10.0.11.55
+ A 10.0.11.56
+ A 10.0.11.57
+ A 10.0.11.58
+ A 10.0.11.59
+ A 10.0.11.60
+ A 10.0.11.61
+ A 10.0.11.62
+ A 10.0.11.63
+ A 10.0.11.64
+ A 10.0.11.65
+ A 10.0.11.66
+ A 10.0.11.67
+ A 10.0.11.68
+ A 10.0.11.69
+ A 10.0.11.70
+ A 10.0.11.71
+ A 10.0.11.72
+ A 10.0.11.73
+ A 10.0.11.74
+ A 10.0.11.75
+ A 10.0.11.76
+ A 10.0.11.77
+ A 10.0.11.78
+ A 10.0.11.79
+ A 10.0.11.80
+ A 10.0.11.81
+ A 10.0.11.82
+ A 10.0.11.83
+ A 10.0.11.84
+ A 10.0.11.85
+ A 10.0.11.86
+ A 10.0.11.87
+ A 10.0.11.88
+ A 10.0.11.89
+ A 10.0.11.90
+ A 10.0.11.91
+ A 10.0.11.92
+ A 10.0.11.93
+ A 10.0.11.94
+ A 10.0.11.95
+ A 10.0.11.96
+ A 10.0.11.97
+ A 10.0.11.98
+ A 10.0.11.99
+ A 10.0.11.100
+ A 10.0.11.101
+ A 10.0.11.102
+ A 10.0.11.103
+ A 10.0.11.104
+ A 10.0.11.105
+ A 10.0.11.106
+ A 10.0.11.107
+ A 10.0.11.108
+ A 10.0.11.109
+ A 10.0.11.110
+ A 10.0.11.111
+ A 10.0.11.112
+ A 10.0.11.113
+ A 10.0.11.114
+ A 10.0.11.115
+ A 10.0.11.116
+ A 10.0.11.117
+ A 10.0.11.118
+ A 10.0.11.119
+ A 10.0.11.120
+ A 10.0.11.121
+ A 10.0.11.122
+ A 10.0.11.123
+ A 10.0.11.124
+ A 10.0.11.125
+ A 10.0.11.126
+ A 10.0.11.127
+ A 10.0.11.128
+ A 10.0.11.129
+ A 10.0.11.130
+ A 10.0.11.131
+ A 10.0.11.132
+ A 10.0.11.133
+ A 10.0.11.134
+ A 10.0.11.135
+ A 10.0.11.136
+ A 10.0.11.137
+ A 10.0.11.138
+ A 10.0.11.139
+ A 10.0.11.140
+ A 10.0.11.141
+ A 10.0.11.142
+ A 10.0.11.143
+ A 10.0.11.144
+ A 10.0.11.145
+ A 10.0.11.146
+ A 10.0.11.147
+ A 10.0.11.148
+ A 10.0.11.149
+ A 10.0.11.150
+ A 10.0.11.151
+ A 10.0.11.152
+ A 10.0.11.153
+ A 10.0.11.154
+ A 10.0.11.155
+ A 10.0.11.156
+ A 10.0.11.157
+ A 10.0.11.158
+ A 10.0.11.159
+ A 10.0.11.160
+ A 10.0.11.161
+ A 10.0.11.162
+ A 10.0.11.163
+ A 10.0.11.164
+ A 10.0.11.165
+ A 10.0.11.166
+ A 10.0.11.167
+ A 10.0.11.168
+ A 10.0.11.169
+ A 10.0.11.170
+ A 10.0.11.171
+ A 10.0.11.172
+ A 10.0.11.173
+ A 10.0.11.174
+ A 10.0.11.175
+ A 10.0.11.176
+ A 10.0.11.177
+ A 10.0.11.178
+ A 10.0.11.179
+ A 10.0.11.180
+ A 10.0.11.181
+ A 10.0.11.182
+ A 10.0.11.183
+ A 10.0.11.184
+ A 10.0.11.185
+ A 10.0.11.186
+ A 10.0.11.187
+ A 10.0.11.188
+ A 10.0.11.189
+ A 10.0.11.190
+ A 10.0.11.191
+ A 10.0.11.192
+ A 10.0.11.193
+ A 10.0.11.194
+ A 10.0.11.195
+ A 10.0.11.196
+ A 10.0.11.197
+ A 10.0.11.198
+ A 10.0.11.199
+ A 10.0.11.200
+ A 10.0.11.201
+ A 10.0.11.202
+ A 10.0.11.203
+ A 10.0.11.204
+ A 10.0.11.205
+ A 10.0.11.206
+ A 10.0.11.207
+ A 10.0.11.208
+ A 10.0.11.209
+ A 10.0.11.210
+ A 10.0.11.211
+ A 10.0.11.212
+ A 10.0.11.213
+ A 10.0.11.214
+ A 10.0.11.215
+ A 10.0.11.216
+ A 10.0.11.217
+ A 10.0.11.218
+ A 10.0.11.219
+ A 10.0.11.220
+ A 10.0.11.221
+ A 10.0.11.222
+ A 10.0.11.223
+ A 10.0.11.224
+ A 10.0.11.225
+ A 10.0.11.226
+ A 10.0.11.227
+ A 10.0.11.228
+ A 10.0.11.229
+ A 10.0.11.230
+ A 10.0.11.231
+ A 10.0.11.232
+ A 10.0.11.233
+ A 10.0.11.234
+ A 10.0.11.235
+ A 10.0.11.236
+ A 10.0.11.237
+ A 10.0.11.238
+ A 10.0.11.239
+ A 10.0.11.240
+ A 10.0.11.241
+ A 10.0.11.242
+ A 10.0.11.243
+ A 10.0.11.244
+ A 10.0.11.245
+ A 10.0.11.246
+ A 10.0.11.247
+ A 10.0.11.248
+ A 10.0.11.249
+ A 10.0.11.250
+ A 10.0.11.251
+ A 10.0.11.252
+ A 10.0.11.253
+ A 10.0.11.254
+ A 10.0.11.255
+ A 10.0.12.0
+ A 10.0.12.1
+ A 10.0.12.2
+ A 10.0.12.3
+ A 10.0.12.4
+ A 10.0.12.5
+ A 10.0.12.6
+ A 10.0.12.7
+ A 10.0.12.8
+ A 10.0.12.9
+ A 10.0.12.10
+ A 10.0.12.11
+ A 10.0.12.12
+ A 10.0.12.13
+ A 10.0.12.14
+ A 10.0.12.15
+ A 10.0.12.16
+ A 10.0.12.17
+ A 10.0.12.18
+ A 10.0.12.19
+ A 10.0.12.20
+ A 10.0.12.21
+ A 10.0.12.22
+ A 10.0.12.23
+ A 10.0.12.24
+ A 10.0.12.25
+ A 10.0.12.26
+ A 10.0.12.27
+ A 10.0.12.28
+ A 10.0.12.29
+ A 10.0.12.30
+ A 10.0.12.31
+ A 10.0.12.32
+ A 10.0.12.33
+ A 10.0.12.34
+ A 10.0.12.35
+ A 10.0.12.36
+ A 10.0.12.37
+ A 10.0.12.38
+ A 10.0.12.39
+ A 10.0.12.40
+ A 10.0.12.41
+ A 10.0.12.42
+ A 10.0.12.43
+ A 10.0.12.44
+ A 10.0.12.45
+ A 10.0.12.46
+ A 10.0.12.47
+ A 10.0.12.48
+ A 10.0.12.49
+ A 10.0.12.50
+ A 10.0.12.51
+ A 10.0.12.52
+ A 10.0.12.53
+ A 10.0.12.54
+ A 10.0.12.55
+ A 10.0.12.56
+ A 10.0.12.57
+ A 10.0.12.58
+ A 10.0.12.59
+ A 10.0.12.60
+ A 10.0.12.61
+ A 10.0.12.62
+ A 10.0.12.63
+ A 10.0.12.64
+ A 10.0.12.65
+ A 10.0.12.66
+ A 10.0.12.67
+ A 10.0.12.68
+ A 10.0.12.69
+ A 10.0.12.70
+ A 10.0.12.71
+ A 10.0.12.72
+ A 10.0.12.73
+ A 10.0.12.74
+ A 10.0.12.75
+ A 10.0.12.76
+ A 10.0.12.77
+ A 10.0.12.78
+ A 10.0.12.79
+ A 10.0.12.80
+ A 10.0.12.81
+ A 10.0.12.82
+ A 10.0.12.83
+ A 10.0.12.84
+ A 10.0.12.85
+ A 10.0.12.86
+ A 10.0.12.87
+ A 10.0.12.88
+ A 10.0.12.89
+ A 10.0.12.90
+ A 10.0.12.91
+ A 10.0.12.92
+ A 10.0.12.93
+ A 10.0.12.94
+ A 10.0.12.95
+ A 10.0.12.96
+ A 10.0.12.97
+ A 10.0.12.98
+ A 10.0.12.99
+ A 10.0.12.100
+ A 10.0.12.101
+ A 10.0.12.102
+ A 10.0.12.103
+ A 10.0.12.104
+ A 10.0.12.105
+ A 10.0.12.106
+ A 10.0.12.107
+ A 10.0.12.108
+ A 10.0.12.109
+ A 10.0.12.110
+ A 10.0.12.111
+ A 10.0.12.112
+ A 10.0.12.113
+ A 10.0.12.114
+ A 10.0.12.115
+ A 10.0.12.116
+ A 10.0.12.117
+ A 10.0.12.118
+ A 10.0.12.119
+ A 10.0.12.120
+ A 10.0.12.121
+ A 10.0.12.122
+ A 10.0.12.123
+ A 10.0.12.124
+ A 10.0.12.125
+ A 10.0.12.126
+ A 10.0.12.127
+ A 10.0.12.128
+ A 10.0.12.129
+ A 10.0.12.130
+ A 10.0.12.131
+ A 10.0.12.132
+ A 10.0.12.133
+ A 10.0.12.134
+ A 10.0.12.135
+ A 10.0.12.136
+ A 10.0.12.137
+ A 10.0.12.138
+ A 10.0.12.139
+ A 10.0.12.140
+ A 10.0.12.141
+ A 10.0.12.142
+ A 10.0.12.143
+ A 10.0.12.144
+ A 10.0.12.145
+ A 10.0.12.146
+ A 10.0.12.147
+ A 10.0.12.148
+ A 10.0.12.149
+ A 10.0.12.150
+ A 10.0.12.151
+ A 10.0.12.152
+ A 10.0.12.153
+ A 10.0.12.154
+ A 10.0.12.155
+ A 10.0.12.156
+ A 10.0.12.157
+ A 10.0.12.158
+ A 10.0.12.159
+ A 10.0.12.160
+ A 10.0.12.161
+ A 10.0.12.162
+ A 10.0.12.163
+ A 10.0.12.164
+ A 10.0.12.165
+ A 10.0.12.166
+ A 10.0.12.167
+ A 10.0.12.168
+ A 10.0.12.169
+ A 10.0.12.170
+ A 10.0.12.171
+ A 10.0.12.172
+ A 10.0.12.173
+ A 10.0.12.174
+ A 10.0.12.175
+ A 10.0.12.176
+ A 10.0.12.177
+ A 10.0.12.178
+ A 10.0.12.179
+ A 10.0.12.180
+ A 10.0.12.181
+ A 10.0.12.182
+ A 10.0.12.183
+ A 10.0.12.184
+ A 10.0.12.185
+ A 10.0.12.186
+ A 10.0.12.187
+ A 10.0.12.188
+ A 10.0.12.189
+ A 10.0.12.190
+ A 10.0.12.191
+ A 10.0.12.192
+ A 10.0.12.193
+ A 10.0.12.194
+ A 10.0.12.195
+ A 10.0.12.196
+ A 10.0.12.197
+ A 10.0.12.198
+ A 10.0.12.199
+ A 10.0.12.200
+ A 10.0.12.201
+ A 10.0.12.202
+ A 10.0.12.203
+ A 10.0.12.204
+ A 10.0.12.205
+ A 10.0.12.206
+ A 10.0.12.207
+ A 10.0.12.208
+ A 10.0.12.209
+ A 10.0.12.210
+ A 10.0.12.211
+ A 10.0.12.212
+ A 10.0.12.213
+ A 10.0.12.214
+ A 10.0.12.215
+ A 10.0.12.216
+ A 10.0.12.217
+ A 10.0.12.218
+ A 10.0.12.219
+ A 10.0.12.220
+ A 10.0.12.221
+ A 10.0.12.222
+ A 10.0.12.223
+ A 10.0.12.224
+ A 10.0.12.225
+ A 10.0.12.226
+ A 10.0.12.227
+ A 10.0.12.228
+ A 10.0.12.229
+ A 10.0.12.230
+ A 10.0.12.231
+ A 10.0.12.232
+ A 10.0.12.233
+ A 10.0.12.234
+ A 10.0.12.235
+ A 10.0.12.236
+ A 10.0.12.237
+ A 10.0.12.238
+ A 10.0.12.239
+ A 10.0.12.240
+ A 10.0.12.241
+ A 10.0.12.242
+ A 10.0.12.243
+ A 10.0.12.244
+ A 10.0.12.245
+ A 10.0.12.246
+ A 10.0.12.247
+ A 10.0.12.248
+ A 10.0.12.249
+ A 10.0.12.250
+ A 10.0.12.251
+ A 10.0.12.252
+ A 10.0.12.253
+ A 10.0.12.254
+ A 10.0.12.255
+ A 10.0.13.0
+ A 10.0.13.1
+ A 10.0.13.2
+ A 10.0.13.3
+ A 10.0.13.4
+ A 10.0.13.5
+ A 10.0.13.6
+ A 10.0.13.7
+ A 10.0.13.8
+ A 10.0.13.9
+ A 10.0.13.10
+ A 10.0.13.11
+ A 10.0.13.12
+ A 10.0.13.13
+ A 10.0.13.14
+ A 10.0.13.15
+ A 10.0.13.16
+ A 10.0.13.17
+ A 10.0.13.18
+ A 10.0.13.19
+ A 10.0.13.20
+ A 10.0.13.21
+ A 10.0.13.22
+ A 10.0.13.23
+ A 10.0.13.24
+ A 10.0.13.25
+ A 10.0.13.26
+ A 10.0.13.27
+ A 10.0.13.28
+ A 10.0.13.29
+ A 10.0.13.30
+ A 10.0.13.31
+ A 10.0.13.32
+ A 10.0.13.33
+ A 10.0.13.34
+ A 10.0.13.35
+ A 10.0.13.36
+ A 10.0.13.37
+ A 10.0.13.38
+ A 10.0.13.39
+ A 10.0.13.40
+ A 10.0.13.41
+ A 10.0.13.42
+ A 10.0.13.43
+ A 10.0.13.44
+ A 10.0.13.45
+ A 10.0.13.46
+ A 10.0.13.47
+ A 10.0.13.48
+ A 10.0.13.49
+ A 10.0.13.50
+ A 10.0.13.51
+ A 10.0.13.52
+ A 10.0.13.53
+ A 10.0.13.54
+ A 10.0.13.55
+ A 10.0.13.56
+ A 10.0.13.57
+ A 10.0.13.58
+ A 10.0.13.59
+ A 10.0.13.60
+ A 10.0.13.61
+ A 10.0.13.62
+ A 10.0.13.63
+ A 10.0.13.64
+ A 10.0.13.65
+ A 10.0.13.66
+ A 10.0.13.67
+ A 10.0.13.68
+ A 10.0.13.69
+ A 10.0.13.70
+ A 10.0.13.71
+ A 10.0.13.72
+ A 10.0.13.73
+ A 10.0.13.74
+ A 10.0.13.75
+ A 10.0.13.76
+ A 10.0.13.77
+ A 10.0.13.78
+ A 10.0.13.79
+ A 10.0.13.80
+ A 10.0.13.81
+ A 10.0.13.82
+ A 10.0.13.83
+ A 10.0.13.84
+ A 10.0.13.85
+ A 10.0.13.86
+ A 10.0.13.87
+ A 10.0.13.88
+ A 10.0.13.89
+ A 10.0.13.90
+ A 10.0.13.91
+ A 10.0.13.92
+ A 10.0.13.93
+ A 10.0.13.94
+ A 10.0.13.95
+ A 10.0.13.96
+ A 10.0.13.97
+ A 10.0.13.98
+ A 10.0.13.99
+ A 10.0.13.100
+ A 10.0.13.101
+ A 10.0.13.102
+ A 10.0.13.103
+ A 10.0.13.104
+ A 10.0.13.105
+ A 10.0.13.106
+ A 10.0.13.107
+ A 10.0.13.108
+ A 10.0.13.109
+ A 10.0.13.110
+ A 10.0.13.111
+ A 10.0.13.112
+ A 10.0.13.113
+ A 10.0.13.114
+ A 10.0.13.115
+ A 10.0.13.116
+ A 10.0.13.117
+ A 10.0.13.118
+ A 10.0.13.119
+ A 10.0.13.120
+ A 10.0.13.121
+ A 10.0.13.122
+ A 10.0.13.123
+ A 10.0.13.124
+ A 10.0.13.125
+ A 10.0.13.126
+ A 10.0.13.127
+ A 10.0.13.128
+ A 10.0.13.129
+ A 10.0.13.130
+ A 10.0.13.131
+ A 10.0.13.132
+ A 10.0.13.133
+ A 10.0.13.134
+ A 10.0.13.135
+ A 10.0.13.136
+ A 10.0.13.137
+ A 10.0.13.138
+ A 10.0.13.139
+ A 10.0.13.140
+ A 10.0.13.141
+ A 10.0.13.142
+ A 10.0.13.143
+ A 10.0.13.144
+ A 10.0.13.145
+ A 10.0.13.146
+ A 10.0.13.147
+ A 10.0.13.148
+ A 10.0.13.149
+ A 10.0.13.150
+ A 10.0.13.151
+ A 10.0.13.152
+ A 10.0.13.153
+ A 10.0.13.154
+ A 10.0.13.155
+ A 10.0.13.156
+ A 10.0.13.157
+ A 10.0.13.158
+ A 10.0.13.159
+ A 10.0.13.160
+ A 10.0.13.161
+ A 10.0.13.162
+ A 10.0.13.163
+ A 10.0.13.164
+ A 10.0.13.165
+ A 10.0.13.166
+ A 10.0.13.167
+ A 10.0.13.168
+ A 10.0.13.169
+ A 10.0.13.170
+ A 10.0.13.171
+ A 10.0.13.172
+ A 10.0.13.173
+ A 10.0.13.174
+ A 10.0.13.175
+ A 10.0.13.176
+ A 10.0.13.177
+ A 10.0.13.178
+ A 10.0.13.179
+ A 10.0.13.180
+ A 10.0.13.181
+ A 10.0.13.182
+ A 10.0.13.183
+ A 10.0.13.184
+ A 10.0.13.185
+ A 10.0.13.186
+ A 10.0.13.187
+ A 10.0.13.188
+ A 10.0.13.189
+ A 10.0.13.190
+ A 10.0.13.191
+ A 10.0.13.192
+ A 10.0.13.193
+ A 10.0.13.194
+ A 10.0.13.195
+ A 10.0.13.196
+ A 10.0.13.197
+ A 10.0.13.198
+ A 10.0.13.199
+ A 10.0.13.200
+ A 10.0.13.201
+ A 10.0.13.202
+ A 10.0.13.203
+ A 10.0.13.204
+ A 10.0.13.205
+ A 10.0.13.206
+ A 10.0.13.207
+ A 10.0.13.208
+ A 10.0.13.209
+ A 10.0.13.210
+ A 10.0.13.211
+ A 10.0.13.212
+ A 10.0.13.213
+ A 10.0.13.214
+ A 10.0.13.215
+ A 10.0.13.216
+ A 10.0.13.217
+ A 10.0.13.218
+ A 10.0.13.219
+ A 10.0.13.220
+ A 10.0.13.221
+ A 10.0.13.222
+ A 10.0.13.223
+ A 10.0.13.224
+ A 10.0.13.225
+ A 10.0.13.226
+ A 10.0.13.227
+ A 10.0.13.228
+ A 10.0.13.229
+ A 10.0.13.230
+ A 10.0.13.231
+ A 10.0.13.232
+ A 10.0.13.233
+ A 10.0.13.234
+ A 10.0.13.235
+ A 10.0.13.236
+ A 10.0.13.237
+ A 10.0.13.238
+ A 10.0.13.239
+ A 10.0.13.240
+ A 10.0.13.241
+ A 10.0.13.242
+ A 10.0.13.243
+ A 10.0.13.244
+ A 10.0.13.245
+ A 10.0.13.246
+ A 10.0.13.247
+ A 10.0.13.248
+ A 10.0.13.249
+ A 10.0.13.250
+ A 10.0.13.251
+ A 10.0.13.252
+ A 10.0.13.253
+ A 10.0.13.254
+ A 10.0.13.255
+ A 10.0.14.0
+ A 10.0.14.1
+ A 10.0.14.2
+ A 10.0.14.3
+ A 10.0.14.4
+ A 10.0.14.5
+ A 10.0.14.6
+ A 10.0.14.7
+ A 10.0.14.8
+ A 10.0.14.9
+ A 10.0.14.10
+ A 10.0.14.11
+ A 10.0.14.12
+ A 10.0.14.13
+ A 10.0.14.14
+ A 10.0.14.15
+ A 10.0.14.16
+ A 10.0.14.17
+ A 10.0.14.18
+ A 10.0.14.19
+ A 10.0.14.20
+ A 10.0.14.21
+ A 10.0.14.22
+ A 10.0.14.23
+ A 10.0.14.24
+ A 10.0.14.25
+ A 10.0.14.26
+ A 10.0.14.27
+ A 10.0.14.28
+ A 10.0.14.29
+ A 10.0.14.30
+ A 10.0.14.31
+ A 10.0.14.32
+ A 10.0.14.33
+ A 10.0.14.34
+ A 10.0.14.35
+ A 10.0.14.36
+ A 10.0.14.37
+ A 10.0.14.38
+ A 10.0.14.39
+ A 10.0.14.40
+ A 10.0.14.41
+ A 10.0.14.42
+ A 10.0.14.43
+ A 10.0.14.44
+ A 10.0.14.45
+ A 10.0.14.46
+ A 10.0.14.47
+ A 10.0.14.48
+ A 10.0.14.49
+ A 10.0.14.50
+ A 10.0.14.51
+ A 10.0.14.52
+ A 10.0.14.53
+ A 10.0.14.54
+ A 10.0.14.55
+ A 10.0.14.56
+ A 10.0.14.57
+ A 10.0.14.58
+ A 10.0.14.59
+ A 10.0.14.60
+ A 10.0.14.61
+ A 10.0.14.62
+ A 10.0.14.63
+ A 10.0.14.64
+ A 10.0.14.65
+ A 10.0.14.66
+ A 10.0.14.67
+ A 10.0.14.68
+ A 10.0.14.69
+ A 10.0.14.70
+ A 10.0.14.71
+ A 10.0.14.72
+ A 10.0.14.73
+ A 10.0.14.74
+ A 10.0.14.75
+ A 10.0.14.76
+ A 10.0.14.77
+ A 10.0.14.78
+ A 10.0.14.79
+ A 10.0.14.80
+ A 10.0.14.81
+ A 10.0.14.82
+ A 10.0.14.83
+ A 10.0.14.84
+ A 10.0.14.85
+ A 10.0.14.86
+ A 10.0.14.87
+ A 10.0.14.88
+ A 10.0.14.89
+ A 10.0.14.90
+ A 10.0.14.91
+ A 10.0.14.92
+ A 10.0.14.93
+ A 10.0.14.94
+ A 10.0.14.95
+ A 10.0.14.96
+ A 10.0.14.97
+ A 10.0.14.98
+ A 10.0.14.99
+ A 10.0.14.100
+ A 10.0.14.101
+ A 10.0.14.102
+ A 10.0.14.103
+ A 10.0.14.104
+ A 10.0.14.105
+ A 10.0.14.106
+ A 10.0.14.107
+ A 10.0.14.108
+ A 10.0.14.109
+ A 10.0.14.110
+ A 10.0.14.111
+ A 10.0.14.112
+ A 10.0.14.113
+ A 10.0.14.114
+ A 10.0.14.115
+ A 10.0.14.116
+ A 10.0.14.117
+ A 10.0.14.118
+ A 10.0.14.119
+ A 10.0.14.120
+ A 10.0.14.121
+ A 10.0.14.122
+ A 10.0.14.123
+ A 10.0.14.124
+ A 10.0.14.125
+ A 10.0.14.126
+ A 10.0.14.127
+ A 10.0.14.128
+ A 10.0.14.129
+ A 10.0.14.130
+ A 10.0.14.131
+ A 10.0.14.132
+ A 10.0.14.133
+ A 10.0.14.134
+ A 10.0.14.135
+ A 10.0.14.136
+ A 10.0.14.137
+ A 10.0.14.138
+ A 10.0.14.139
+ A 10.0.14.140
+ A 10.0.14.141
+ A 10.0.14.142
+ A 10.0.14.143
+ A 10.0.14.144
+ A 10.0.14.145
+ A 10.0.14.146
+ A 10.0.14.147
+ A 10.0.14.148
+ A 10.0.14.149
+ A 10.0.14.150
+ A 10.0.14.151
+ A 10.0.14.152
+ A 10.0.14.153
+ A 10.0.14.154
+ A 10.0.14.155
+ A 10.0.14.156
+ A 10.0.14.157
+ A 10.0.14.158
+ A 10.0.14.159
+ A 10.0.14.160
+ A 10.0.14.161
+ A 10.0.14.162
+ A 10.0.14.163
+ A 10.0.14.164
+ A 10.0.14.165
+ A 10.0.14.166
+ A 10.0.14.167
+ A 10.0.14.168
+ A 10.0.14.169
+ A 10.0.14.170
+ A 10.0.14.171
+ A 10.0.14.172
+ A 10.0.14.173
+ A 10.0.14.174
+ A 10.0.14.175
+ A 10.0.14.176
+ A 10.0.14.177
+ A 10.0.14.178
+ A 10.0.14.179
+ A 10.0.14.180
+ A 10.0.14.181
+ A 10.0.14.182
+ A 10.0.14.183
+ A 10.0.14.184
+ A 10.0.14.185
+ A 10.0.14.186
+ A 10.0.14.187
+ A 10.0.14.188
+ A 10.0.14.189
+ A 10.0.14.190
+ A 10.0.14.191
+ A 10.0.14.192
+ A 10.0.14.193
+ A 10.0.14.194
+ A 10.0.14.195
+ A 10.0.14.196
+ A 10.0.14.197
+ A 10.0.14.198
+ A 10.0.14.199
+ A 10.0.14.200
+ A 10.0.14.201
+ A 10.0.14.202
+ A 10.0.14.203
+ A 10.0.14.204
+ A 10.0.14.205
+ A 10.0.14.206
+ A 10.0.14.207
+ A 10.0.14.208
+ A 10.0.14.209
+ A 10.0.14.210
+ A 10.0.14.211
+ A 10.0.14.212
+ A 10.0.14.213
+ A 10.0.14.214
+ A 10.0.14.215
+ A 10.0.14.216
+ A 10.0.14.217
+ A 10.0.14.218
+ A 10.0.14.219
+ A 10.0.14.220
+ A 10.0.14.221
+ A 10.0.14.222
+ A 10.0.14.223
+ A 10.0.14.224
+ A 10.0.14.225
+ A 10.0.14.226
+ A 10.0.14.227
+ A 10.0.14.228
+ A 10.0.14.229
+ A 10.0.14.230
+ A 10.0.14.231
+ A 10.0.14.232
+ A 10.0.14.233
+ A 10.0.14.234
+ A 10.0.14.235
+ A 10.0.14.236
+ A 10.0.14.237
+ A 10.0.14.238
+ A 10.0.14.239
+ A 10.0.14.240
+ A 10.0.14.241
+ A 10.0.14.242
+ A 10.0.14.243
+ A 10.0.14.244
+ A 10.0.14.245
+ A 10.0.14.246
+ A 10.0.14.247
+ A 10.0.14.248
+ A 10.0.14.249
+ A 10.0.14.250
+ A 10.0.14.251
+ A 10.0.14.252
+ A 10.0.14.253
+ A 10.0.14.254
+ A 10.0.14.255
+ A 10.0.15.0
+ A 10.0.15.1
+ A 10.0.15.2
+ A 10.0.15.3
+ A 10.0.15.4
+ A 10.0.15.5
+ A 10.0.15.6
+ A 10.0.15.7
+ A 10.0.15.8
+ A 10.0.15.9
+ A 10.0.15.10
+ A 10.0.15.11
+ A 10.0.15.12
+ A 10.0.15.13
+ A 10.0.15.14
+ A 10.0.15.15
+ A 10.0.15.16
+ A 10.0.15.17
+ A 10.0.15.18
+ A 10.0.15.19
+ A 10.0.15.20
+ A 10.0.15.21
+ A 10.0.15.22
+ A 10.0.15.23
+ A 10.0.15.24
+ A 10.0.15.25
+ A 10.0.15.26
+ A 10.0.15.27
+ A 10.0.15.28
+ A 10.0.15.29
+ A 10.0.15.30
+ A 10.0.15.31
+ A 10.0.15.32
+ A 10.0.15.33
+ A 10.0.15.34
+ A 10.0.15.35
+ A 10.0.15.36
+ A 10.0.15.37
+ A 10.0.15.38
+ A 10.0.15.39
+ A 10.0.15.40
+ A 10.0.15.41
+ A 10.0.15.42
+ A 10.0.15.43
+ A 10.0.15.44
+ A 10.0.15.45
+ A 10.0.15.46
+ A 10.0.15.47
+ A 10.0.15.48
+ A 10.0.15.49
+ A 10.0.15.50
+ A 10.0.15.51
+ A 10.0.15.52
+ A 10.0.15.53
+ A 10.0.15.54
+ A 10.0.15.55
+ A 10.0.15.56
+ A 10.0.15.57
+ A 10.0.15.58
+ A 10.0.15.59
+ A 10.0.15.60
+ A 10.0.15.61
+ A 10.0.15.62
+ A 10.0.15.63
+ A 10.0.15.64
+ A 10.0.15.65
+ A 10.0.15.66
+ A 10.0.15.67
+ A 10.0.15.68
+ A 10.0.15.69
+ A 10.0.15.70
+ A 10.0.15.71
+ A 10.0.15.72
+ A 10.0.15.73
+ A 10.0.15.74
+ A 10.0.15.75
+ A 10.0.15.76
+ A 10.0.15.77
+ A 10.0.15.78
+ A 10.0.15.79
+ A 10.0.15.80
+ A 10.0.15.81
+ A 10.0.15.82
+ A 10.0.15.83
+ A 10.0.15.84
+ A 10.0.15.85
+ A 10.0.15.86
+ A 10.0.15.87
+ A 10.0.15.88
+ A 10.0.15.89
+ A 10.0.15.90
+ A 10.0.15.91
+ A 10.0.15.92
+ A 10.0.15.93
+ A 10.0.15.94
+ A 10.0.15.95
+ A 10.0.15.96
+ A 10.0.15.97
+ A 10.0.15.98
+ A 10.0.15.99
+ A 10.0.15.100
+ A 10.0.15.101
+ A 10.0.15.102
+ A 10.0.15.103
+ A 10.0.15.104
+ A 10.0.15.105
+ A 10.0.15.106
+ A 10.0.15.107
+ A 10.0.15.108
+ A 10.0.15.109
+ A 10.0.15.110
+ A 10.0.15.111
+ A 10.0.15.112
+ A 10.0.15.113
+ A 10.0.15.114
+ A 10.0.15.115
+ A 10.0.15.116
+ A 10.0.15.117
+ A 10.0.15.118
+ A 10.0.15.119
+ A 10.0.15.120
+ A 10.0.15.121
+ A 10.0.15.122
+ A 10.0.15.123
+ A 10.0.15.124
+ A 10.0.15.125
+ A 10.0.15.126
+ A 10.0.15.127
+ A 10.0.15.128
+ A 10.0.15.129
+ A 10.0.15.130
+ A 10.0.15.131
+ A 10.0.15.132
+ A 10.0.15.133
+ A 10.0.15.134
+ A 10.0.15.135
+ A 10.0.15.136
+ A 10.0.15.137
+ A 10.0.15.138
+ A 10.0.15.139
+ A 10.0.15.140
+ A 10.0.15.141
+ A 10.0.15.142
+ A 10.0.15.143
+ A 10.0.15.144
+ A 10.0.15.145
+ A 10.0.15.146
+ A 10.0.15.147
+ A 10.0.15.148
+ A 10.0.15.149
+ A 10.0.15.150
+ A 10.0.15.151
+ A 10.0.15.152
+ A 10.0.15.153
+ A 10.0.15.154
+ A 10.0.15.155
+ A 10.0.15.156
+ A 10.0.15.157
+ A 10.0.15.158
+ A 10.0.15.159
+ A 10.1.0.0
+ A 10.1.0.1
+ A 10.1.0.2
+ A 10.1.0.3
+ A 10.1.0.4
+ A 10.1.0.5
+ A 10.1.0.6
+ A 10.1.0.7
+ A 10.1.0.8
+ A 10.1.0.9
+ A 10.1.0.10
+ A 10.1.0.11
+ A 10.1.0.12
+ A 10.1.0.13
+ A 10.1.0.14
+ A 10.1.0.15
+ A 10.1.0.16
+ A 10.1.0.17
+ A 10.1.0.18
+ A 10.1.0.19
+ A 10.1.0.20
+ A 10.1.0.21
+ A 10.1.0.22
+ A 10.1.0.23
+ A 10.1.0.24
+ A 10.1.0.25
+ A 10.1.0.26
+ A 10.1.0.27
+ A 10.1.0.28
+ A 10.1.0.29
+ A 10.1.0.30
+ A 10.1.0.31
+ A 10.1.0.32
+ A 10.1.0.33
+ A 10.1.0.34
+ A 10.1.0.35
+ A 10.1.0.36
+ A 10.1.0.37
+ A 10.1.0.38
+ A 10.1.0.39
+ A 10.1.0.40
+ A 10.1.0.41
+ A 10.1.0.42
+ A 10.1.0.43
+ A 10.1.0.44
+ A 10.1.0.45
+ A 10.1.0.46
+ A 10.1.0.47
+ A 10.1.0.48
+ A 10.1.0.49
+ A 10.1.0.50
+ A 10.1.0.51
+ A 10.1.0.52
+ A 10.1.0.53
+ A 10.1.0.54
+ A 10.1.0.55
+ A 10.1.0.56
+ A 10.1.0.57
+ A 10.1.0.58
+ A 10.1.0.59
+ A 10.1.0.60
+ A 10.1.0.61
+ A 10.1.0.62
+ A 10.1.0.63
+ A 10.1.0.64
+ A 10.1.0.65
+ A 10.1.0.66
+ A 10.1.0.67
+ A 10.1.0.68
+ A 10.1.0.69
+ A 10.1.0.70
+ A 10.1.0.71
+ A 10.1.0.72
+ A 10.1.0.73
+ A 10.1.0.74
+ A 10.1.0.75
+ A 10.1.0.76
+ A 10.1.0.77
+ A 10.1.0.78
+ A 10.1.0.79
+ A 10.1.0.80
+ A 10.1.0.81
+ A 10.1.0.82
+ A 10.1.0.83
+ A 10.1.0.84
+ A 10.1.0.85
+ A 10.1.0.86
+ A 10.1.0.87
+ A 10.1.0.88
+ A 10.1.0.89
+ A 10.1.0.90
diff --git a/bin/tests/system/limits/ns1/named.conf b/bin/tests/system/limits/ns1/named.conf
new file mode 100644
index 0000000..e8e439e
--- /dev/null
+++ b/bin/tests/system/limits/ns1/named.conf
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.14 2007/06/19 23:47:03 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
diff --git a/bin/tests/system/limits/ns1/root.db b/bin/tests/system/limits/ns1/root.db
new file mode 100644
index 0000000..635dfce
--- /dev/null
+++ b/bin/tests/system/limits/ns1/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.9 2007/06/19 23:47:03 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns1.example.
+ns1.example. A 10.53.0.1
diff --git a/bin/tests/system/limits/tests.sh b/bin/tests/system/limits/tests.sh
new file mode 100644
index 0000000..f2728d2
--- /dev/null
+++ b/bin/tests/system/limits/tests.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.17 2007/06/19 23:47:03 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+echo "I:1000 A records"
+$DIG +tcp +norec 1000.example. @10.53.0.1 a -p 5300 > dig.out.1000 || status=1
+#dig 1000.example. @10.53.0.1 a -p 5300 > knowngood.dig.out.1000
+$PERL ../digcomp.pl knowngood.dig.out.1000 dig.out.1000 || status=1
+
+echo "I:2000 A records"
+$DIG +tcp +norec 2000.example. @10.53.0.1 a -p 5300 > dig.out.2000 || status=1
+#dig 2000.example. @10.53.0.1 a -p 5300 > knowngood.dig.out.2000
+$PERL ../digcomp.pl knowngood.dig.out.2000 dig.out.2000 || status=1
+
+echo "I:3000 A records"
+$DIG +tcp +norec 3000.example. @10.53.0.1 a -p 5300 > dig.out.3000 || status=1
+#dig 3000.example. @10.53.0.1 a -p 5300 > knowngood.dig.out.3000
+$PERL ../digcomp.pl knowngood.dig.out.3000 dig.out.3000 || status=1
+
+echo "I:4000 A records"
+$DIG +tcp +norec 4000.example. @10.53.0.1 a -p 5300 > dig.out.4000 || status=1
+#dig 4000.example. @10.53.0.1 a -p 5300 > knowngood.dig.out.4000
+$PERL ../digcomp.pl knowngood.dig.out.4000 dig.out.4000 || status=1
+
+echo "I:exactly maximum rrset"
+$DIG +tcp +norec a-maximum-rrset.example. @10.53.0.1 a -p 5300 > dig.out.a-maximum-rrset \
+ || status=1
+#dig a-maximum-rrset.example. @10.53.0.1 a -p 5300 > knowngood.dig.out.a-maximum-rrset
+$PERL ../digcomp.pl knowngood.dig.out.a-maximum-rrset dig.out.a-maximum-rrset || status=1
+
+echo "I:exceed maximum rrset (5000 A records)"
+$DIG +tcp +norec 5000.example. @10.53.0.1 a -p 5300 > dig.out.exceed || status=1
+# Look for truncation bit (tc).
+grep 'flags: .*tc.*;' dig.out.exceed > /dev/null || {
+ echo "I:TC bit was not set"
+ status=1
+}
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/lwresd/Makefile.in b/bin/tests/system/lwresd/Makefile.in
new file mode 100644
index 0000000..807349d
--- /dev/null
+++ b/bin/tests/system/lwresd/Makefile.in
@@ -0,0 +1,56 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 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.19 2007/06/19 23:47:03 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${LWRES_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+LWRESLIBS = ../../../../lib/lwres/liblwres.@A@
+ISCLIBS = ../../../../lib/isc/libisc.@A@
+
+LWRESDEPLIBS = ../../../../lib/lwres/liblwres.@A@
+ISCDEPLIBS = ../../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${LWRESDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${LWRESLIBS} ${ISCLIBS} @LIBS@
+
+TARGETS = lwtest@EXEEXT@
+
+OBJS = lwtest.@O@
+
+SRCS = lwtest.c
+
+@BIND9_MAKE_RULES@
+
+all: lwtest@EXEEXT@
+
+lwtest@EXEEXT@: ${OBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS}
+
diff --git a/bin/tests/system/lwresd/clean.sh b/bin/tests/system/lwresd/clean.sh
new file mode 100644
index 0000000..107a020
--- /dev/null
+++ b/bin/tests/system/lwresd/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) 2008 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: clean.sh,v 1.1 2008/07/17 01:14:16 marka Exp $
+
+#
+# Clean up after lwresd tests.
+#
+rm -f */named.memstats
diff --git a/bin/tests/system/lwresd/lwresd1/lwresd.conf b/bin/tests/system/lwresd/lwresd1/lwresd.conf
new file mode 100644
index 0000000..272cab6
--- /dev/null
+++ b/bin/tests/system/lwresd/lwresd1/lwresd.conf
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004, 2007 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: lwresd.conf,v 1.8 2007/06/19 23:47:04 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ port 5300;
+ pid-file "lwresd.pid";
+ forwarders {10.53.0.1;};
+ forward only;
+};
+
+lwres {
+ listen-on {10.53.0.1 port 9210;};
+ view "_default";
+ search {example1.;};
+ ndots 1;
+};
diff --git a/bin/tests/system/lwresd/lwresd1/resolv.conf b/bin/tests/system/lwresd/lwresd1/resolv.conf
new file mode 100644
index 0000000..1aa88c9
--- /dev/null
+++ b/bin/tests/system/lwresd/lwresd1/resolv.conf
@@ -0,0 +1,21 @@
+# Copyright (C) 2004, 2007 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: resolv.conf,v 1.11 2007/06/19 23:47:04 tbox Exp $
+
+nameserver 10.53.0.1
+lwserver 10.53.0.1
+search example1.
+ndots 1
diff --git a/bin/tests/system/lwresd/lwtest.c b/bin/tests/system/lwresd/lwtest.c
new file mode 100644
index 0000000..534e999
--- /dev/null
+++ b/bin/tests/system/lwresd/lwtest.c
@@ -0,0 +1,773 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: lwtest.c,v 1.32 2008/04/02 02:37:42 marka Exp $ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <isc/net.h>
+#include <isc/string.h>
+
+#include <lwres/lwres.h>
+#include <lwres/netdb.h>
+#include <lwres/net.h>
+
+/*
+ * XXX getnameinfo errors, which don't appear to be standard.
+ */
+#define ENI_NOSERVNAME 1
+#define ENI_NOHOSTNAME 2
+#define ENI_MEMORY 3
+#define ENI_SYSTEM 4
+#define ENI_FAMILY 5
+#define ENI_SALEN 6
+#define ENI_NOSOCKET 7
+
+static int fails = 0;
+
+static void
+CHECK(lwres_result_t val, const char *msg) {
+ if (val != 0) {
+ printf("I:%s returned %d\n", msg, val);
+ exit(1);
+ }
+}
+
+static unsigned char TESTSTRING[] =
+ "This is a test. This is only a test. !!!";
+
+static lwres_context_t *ctx;
+
+static void
+test_noop(void) {
+ lwres_result_t ret;
+ lwres_lwpacket_t pkt, pkt2;
+ lwres_nooprequest_t nooprequest, *nooprequest2;
+ lwres_noopresponse_t noopresponse, *noopresponse2;
+ lwres_buffer_t b;
+
+ pkt.pktflags = 0;
+ pkt.serial = 0x11223344;
+ pkt.recvlength = 0x55667788;
+ pkt.result = 0;
+
+ nooprequest.datalength = strlen((char *)TESTSTRING);
+ nooprequest.data = TESTSTRING;
+ ret = lwres_nooprequest_render(ctx, &nooprequest, &pkt, &b);
+ CHECK(ret, "lwres_nooprequest_render");
+
+ /*
+ * Now, parse it into a new structure.
+ */
+ lwres_buffer_first(&b);
+ ret = lwres_lwpacket_parseheader(&b, &pkt2);
+ CHECK(ret, "lwres_lwpacket_parseheader");
+
+ nooprequest2 = NULL;
+ ret = lwres_nooprequest_parse(ctx, &b, &pkt2, &nooprequest2);
+ CHECK(ret, "lwres_nooprequest_parse");
+
+ assert(nooprequest.datalength == nooprequest2->datalength);
+ assert(memcmp(nooprequest.data, nooprequest2->data,
+ nooprequest.datalength) == 0);
+
+ lwres_nooprequest_free(ctx, &nooprequest2);
+
+ lwres_context_freemem(ctx, b.base, b.length);
+ b.base = NULL;
+ b.length = 0;
+
+ pkt.pktflags = 0;
+ pkt.serial = 0x11223344;
+ pkt.recvlength = 0x55667788;
+ pkt.result = 0xdeadbeef;
+
+ noopresponse.datalength = strlen((char *)TESTSTRING);
+ noopresponse.data = TESTSTRING;
+ ret = lwres_noopresponse_render(ctx, &noopresponse, &pkt, &b);
+ CHECK(ret, "lwres_noopresponse_render");
+
+ /*
+ * Now, parse it into a new structure.
+ */
+ lwres_buffer_first(&b);
+ ret = lwres_lwpacket_parseheader(&b, &pkt2);
+ CHECK(ret, "lwres_lwpacket_parseheader");
+
+ noopresponse2 = NULL;
+ ret = lwres_noopresponse_parse(ctx, &b, &pkt2, &noopresponse2);
+ CHECK(ret, "lwres_noopresponse_parse");
+
+ assert(noopresponse.datalength == noopresponse2->datalength);
+ assert(memcmp(noopresponse.data, noopresponse2->data,
+ noopresponse.datalength) == 0);
+
+ lwres_noopresponse_free(ctx, &noopresponse2);
+
+ lwres_context_freemem(ctx, b.base, b.length);
+ b.base = NULL;
+ b.length = 0;
+}
+
+static void
+test_gabn(const char *target, lwres_result_t expected, const char *address,
+ lwres_uint32_t af)
+{
+ lwres_gabnresponse_t *res;
+ unsigned char addrbuf[16];
+ lwres_addr_t *addr;
+ char outbuf[64];
+ unsigned int len;
+ lwres_result_t ret;
+
+ res = NULL;
+ ret = lwres_getaddrsbyname(ctx, target,
+ LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6,
+ &res);
+ if (ret != expected) {
+ printf("I:gabn(%s) failed: %d\n", target, ret);
+ if (res != NULL)
+ lwres_gabnresponse_free(ctx, &res);
+ fails++;
+ return;
+ }
+ if (ret == LWRES_R_SUCCESS) {
+ if (af == LWRES_ADDRTYPE_V4) {
+ len = 4;
+ ret = inet_pton(AF_INET, address, addrbuf);
+ assert(ret == 1);
+ } else {
+ len = 16;
+ ret = inet_pton(AF_INET6, address, addrbuf);
+ assert(ret == 1);
+ }
+ addr = LWRES_LIST_HEAD(res->addrs);
+ if (addr == NULL) {
+ printf("I:gabn(%s) returned empty list\n", target);
+ fails++;
+ return;
+ }
+ while (addr != NULL) {
+ if (addr->family != af || addr->length != len ||
+ memcmp(addr->address, addrbuf, len) == 0)
+ break;
+ addr = LWRES_LIST_NEXT(addr, link);
+ }
+ if (addr == NULL) {
+ addr = LWRES_LIST_HEAD(res->addrs);
+ if (addr->family == LWRES_ADDRTYPE_V4)
+ (void)inet_ntop(AF_INET, addr->address,
+ outbuf, sizeof(outbuf));
+ else
+ (void)inet_ntop(AF_INET6, addr->address,
+ outbuf, sizeof(outbuf));
+ printf("I:gabn(%s) returned %s, expected %s\n",
+ target, outbuf, address);
+ fails++;
+ return;
+ }
+ }
+ if (res != NULL)
+ lwres_gabnresponse_free(ctx, &res);
+}
+
+static void
+test_gnba(const char *target, lwres_uint32_t af, lwres_result_t expected,
+ const char *name)
+{
+ lwres_gnbaresponse_t *res;
+ lwres_result_t ret;
+ unsigned char addrbuf[16];
+ unsigned int len;
+
+ if (af == LWRES_ADDRTYPE_V4) {
+ len = 4;
+ ret = inet_pton(AF_INET, target, addrbuf);
+ assert(ret == 1);
+ } else {
+ len = 16;
+ ret = inet_pton(AF_INET6, target, addrbuf);
+ assert(ret == 1);
+ }
+
+ res = NULL;
+ ret = lwres_getnamebyaddr(ctx, af, len, addrbuf, &res);
+ if (ret != expected) {
+ printf("I:gnba(%s) failed: %d\n", target, ret);
+ if (res != NULL)
+ lwres_gnbaresponse_free(ctx, &res);
+ fails++;
+ return;
+ }
+ if (ret == LWRES_R_SUCCESS && strcasecmp(res->realname, name) != 0) {
+ printf("I:gnba(%s) returned %s, expected %s\n",
+ target, res->realname, name);
+ fails++;
+ return;
+ }
+ if (res != NULL)
+ lwres_gnbaresponse_free(ctx, &res);
+}
+
+static void
+test_gethostbyname(const char *name, const char *address) {
+ struct hostent *hp;
+ unsigned char addrbuf[16];
+ int ret;
+
+ hp = gethostbyname(name);
+ if (hp == NULL) {
+ if (address == NULL && h_errno == HOST_NOT_FOUND)
+ return;
+ else if (h_errno != HOST_NOT_FOUND) {
+ printf("I:gethostbyname(%s) failed: %s\n",
+ name, hstrerror(h_errno));
+ fails++;
+ return;
+ } else {
+ printf("I:gethostbyname(%s) returned not found\n",
+ name);
+ fails++;
+ return;
+ }
+ } else {
+ ret = inet_pton(AF_INET, address, addrbuf);
+ assert(ret == 1);
+ if (memcmp(hp->h_addr_list[0], addrbuf, hp->h_length) != 0) {
+ char outbuf[16];
+ (void)inet_ntop(AF_INET, hp->h_addr_list[0],
+ outbuf, sizeof(outbuf));
+ printf("I:gethostbyname(%s) returned %s, "
+ "expected %s\n", name, outbuf, address);
+ fails++;
+ return;
+ }
+ }
+}
+
+static void
+test_gethostbyname2(const char *name, const char *address, int af) {
+ struct hostent *hp;
+ unsigned char addrbuf[16];
+ int len, ret;
+
+ hp = gethostbyname2(name, af);
+ if (hp == NULL) {
+ if (address == NULL && h_errno == HOST_NOT_FOUND)
+ return;
+ else if (h_errno != HOST_NOT_FOUND) {
+ printf("I:gethostbyname(%s) failed: %s\n",
+ name, hstrerror(h_errno));
+ fails++;
+ return;
+ } else {
+ printf("I:gethostbyname(%s) returned not found\n",
+ name);
+ fails++;
+ return;
+ }
+ } else {
+ if (af == AF_INET)
+ len = 4;
+ else
+ len = 16;
+ ret = inet_pton(af, address, addrbuf);
+ assert(ret == 1);
+ if (hp->h_addrtype != af) {
+ printf("I:gethostbyname(%s) returned wrong family\n",
+ name);
+ fails++;
+ return;
+ }
+ if (len != (int)hp->h_length ||
+ memcmp(hp->h_addr_list[0], addrbuf, hp->h_length) != 0)
+ {
+ char outbuf[16];
+ (void)inet_ntop(af, hp->h_addr_list[0],
+ outbuf, sizeof(outbuf));
+ printf("I:gethostbyname(%s) returned %s, "
+ "expected %s\n", name, outbuf, address);
+ fails++;
+ return;
+ }
+ }
+}
+
+static void
+test_getipnodebyname(const char *name, const char *address, int af,
+ int v4map, int all)
+{
+ struct hostent *hp;
+ unsigned char addrbuf[16];
+ int len, ret;
+ int error_num;
+ int flags = 0;
+
+ if (v4map)
+ flags |= AI_V4MAPPED;
+ if (all)
+ flags |= AI_ALL;
+
+ hp = getipnodebyname(name, af, flags, &error_num);
+ if (hp == NULL) {
+ if (address == NULL && error_num == HOST_NOT_FOUND)
+ return;
+ else if (error_num != HOST_NOT_FOUND) {
+ printf("I:getipnodebyname(%s) failed: %d\n",
+ name, error_num);
+ fails++;
+ return;
+ } else {
+ printf("I:getipnodebyname(%s) returned not found\n",
+ name);
+ fails++;
+ return;
+ }
+ } else {
+ if (af == AF_INET)
+ len = 4;
+ else
+ len = 16;
+ ret = inet_pton(af, address, addrbuf);
+ assert(ret == 1);
+ if (hp->h_addrtype != af) {
+ printf("I:getipnodebyname(%s) returned wrong family\n",
+ name);
+ freehostent(hp);
+ fails++;
+ return;
+ }
+ if (len != (int)hp->h_length ||
+ memcmp(hp->h_addr_list[0], addrbuf, hp->h_length) != 0)
+ {
+ char outbuf[16];
+ (void)inet_ntop(af, hp->h_addr_list[0],
+ outbuf, sizeof(outbuf));
+ printf("I:getipnodebyname(%s) returned %s, "
+ "expected %s\n", name, outbuf, address);
+ freehostent(hp);
+ fails++;
+ return;
+ }
+ freehostent(hp);
+ }
+}
+
+static void
+test_gethostbyaddr(const char *address, int af, const char *name) {
+ struct hostent *hp;
+ char addrbuf[16];
+ int len, ret;
+
+ if (af == AF_INET)
+ len = 4;
+ else
+ len = 16;
+ ret = inet_pton(af, address, addrbuf);
+ assert(ret == 1);
+
+ hp = gethostbyaddr(addrbuf, len, af);
+
+ if (hp == NULL) {
+ if (name == NULL && h_errno == HOST_NOT_FOUND)
+ return;
+ else if (h_errno != HOST_NOT_FOUND) {
+ printf("I:gethostbyaddr(%s) failed: %s\n",
+ address, hstrerror(h_errno));
+ fails++;
+ return;
+ } else {
+ printf("I:gethostbyaddr(%s) returned not found\n",
+ address);
+ fails++;
+ return;
+ }
+ } else {
+ if (strcmp(hp->h_name, name) != 0) {
+ printf("I:gethostbyname(%s) returned %s, "
+ "expected %s\n", address, hp->h_name, name);
+ fails++;
+ return;
+ }
+ }
+}
+
+static void
+test_getipnodebyaddr(const char *address, int af, const char *name) {
+ struct hostent *hp;
+ char addrbuf[16];
+ int len, ret;
+ int error_num;
+
+ if (af == AF_INET)
+ len = 4;
+ else
+ len = 16;
+ ret = inet_pton(af, address, addrbuf);
+ assert(ret == 1);
+
+ hp = getipnodebyaddr(addrbuf, len, af, &error_num);
+
+ if (hp == NULL) {
+ if (name == NULL && error_num == HOST_NOT_FOUND)
+ return;
+ else if (error_num != HOST_NOT_FOUND) {
+ printf("I:getipnodebyaddr(%s) failed: %d\n",
+ address, error_num);
+ fails++;
+ return;
+ } else {
+ printf("I:getipnodebyaddr(%s) returned not found\n",
+ address);
+ fails++;
+ return;
+ }
+ } else {
+ if (strcmp(hp->h_name, name) != 0) {
+ printf("I:getipnodebyaddr(%s) returned %s, "
+ "expected %s\n", address, hp->h_name, name);
+ freehostent(hp);
+ fails++;
+ return;
+ }
+ freehostent(hp);
+ }
+}
+
+static void
+test_getaddrinfo(const char *name, int af, int v4ok, int v6ok,
+ const char *address)
+{
+ unsigned int len;
+ int ret;
+ struct addrinfo *ai;
+ struct addrinfo hint;
+ unsigned char addrbuf[16];
+
+ if (v4ok == 1 && v6ok== 1) {
+ ret = getaddrinfo(name, NULL, NULL, &ai);
+ } else {
+ memset(&hint, 0, sizeof(hint));
+ if (v4ok)
+ hint.ai_family = AF_INET;
+ else
+ hint.ai_family = AF_INET6;
+ ret = getaddrinfo(name, NULL, &hint, &ai);
+ }
+ if (ret != 0) {
+ if (address == NULL && ret == EAI_NODATA)
+ return;
+ else if (ret != EAI_NODATA) {
+ printf("I:getaddrinfo(%s,%d,%d) failed: %s\n",
+ name, v4ok, v6ok, gai_strerror(ret));
+ fails++;
+ return;
+ } else {
+ printf("I:getaddrinfo(%s,%d,%d) returned not found\n",
+ name, v4ok, v6ok);
+ fails++;
+ return;
+ }
+ } else {
+ if (af == AF_INET)
+ len = sizeof(struct sockaddr_in);
+ else
+ len = sizeof(struct sockaddr_in6);
+ ret = inet_pton(af, address, addrbuf);
+ assert(ret == 1);
+ if (ai->ai_family != af) {
+ printf("I:getaddrinfo(%s) returned wrong family\n",
+ name);
+ fails++;
+ freeaddrinfo(ai);
+ return;
+ }
+ if (len != (unsigned int) ai->ai_addrlen) {
+ char outbuf[16];
+ (void)inet_ntop(af, ai->ai_addr,
+ outbuf, sizeof(outbuf));
+ printf("I:getaddrinfo(%s) returned %lub, "
+ "expected %ub\n", name,
+ (unsigned long)ai->ai_addrlen, len);
+ fails++;
+ freeaddrinfo(ai);
+ return;
+ } else if (af == AF_INET) {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *) ai->ai_addr;
+ if (memcmp(&sin->sin_addr.s_addr, addrbuf, 4) != 0) {
+ char outbuf[16];
+ (void)inet_ntop(af, &sin->sin_addr.s_addr,
+ outbuf, sizeof(outbuf));
+ printf("I:getaddrinfo(%s) returned %s, "
+ "expected %s\n", name, outbuf, address);
+ fails++;
+ freeaddrinfo(ai);
+ return;
+ }
+ } else {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *) ai->ai_addr;
+ if (memcmp(sin6->sin6_addr.s6_addr, addrbuf, 16) != 0)
+ {
+ char outbuf[16];
+ (void)inet_ntop(af, &sin6->sin6_addr.s6_addr,
+ outbuf, sizeof(outbuf));
+ printf("I:getaddrinfo(%s) returned %s, "
+ "expected %s\n", name, outbuf, address);
+ fails++;
+ freeaddrinfo(ai);
+ return;
+ }
+ }
+ freeaddrinfo(ai);
+ }
+}
+
+static void
+test_getnameinfo(const char *address, int af, const char *name) {
+ int ret;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr *sa;
+ int salen;
+ char host[1025];
+
+ if (af == AF_INET) {
+ memset(&sin, 0, sizeof(sin));
+ ret = inet_pton(AF_INET, address, &sin.sin_addr.s_addr);
+ assert(ret == 1);
+ sin.sin_family = AF_INET;
+#ifdef LWRES_PLATFORM_HAVESALEN
+ sin.sin_len = sizeof(sin);
+#endif
+ sa = (struct sockaddr *) &sin;
+ salen = sizeof(sin);
+ } else {
+ memset(&sin6, 0, sizeof(sin6));
+ ret = inet_pton(AF_INET6, address, sin6.sin6_addr.s6_addr);
+ assert(ret == 1);
+ sin6.sin6_family = AF_INET6;
+#ifdef LWRES_PLATFORM_HAVESALEN
+ sin6.sin6_len = sizeof(sin6);
+#endif
+ sa = (struct sockaddr *) &sin6;
+ salen = sizeof(sin6);
+ }
+ sa->sa_family = af;
+
+ ret = getnameinfo(sa, salen, host, sizeof(host), NULL, 0, NI_NAMEREQD);
+
+ if (ret != 0) {
+ if (name == NULL && ret == ENI_NOHOSTNAME)
+ return;
+ else if (ret != ENI_NOHOSTNAME) {
+ printf("I:getnameinfo(%s) failed: %d\n",
+ address, ret);
+ fails++;
+ return;
+ } else {
+ printf("I:getnameinfo(%s) returned not found\n",
+ address);
+ fails++;
+ return;
+ }
+ } else {
+ if (name == NULL) {
+ printf("I:getnameinfo(%s) returned %s, "
+ "expected NULL\n", address, host);
+ fails++;
+ return;
+ } else if (strcmp(host, name) != 0) {
+ printf("I:getnameinfo(%s) returned %s, expected %s\n",
+ address, host, name);
+ fails++;
+ return;
+ }
+ }
+}
+
+static void
+test_getrrsetbyname(const char *name, int rdclass, int rdtype,
+ unsigned int nrdatas, unsigned int nsigs,
+ int should_pass)
+{
+ int ret;
+ struct rrsetinfo *rrinfo = NULL;
+ ret = getrrsetbyname(name, rdclass, rdtype, 0, &rrinfo);
+ if (ret != 0 && should_pass == 1) {
+ printf("I:getrrsetbyname(%s, %d) failed\n", name, rdtype);
+ fails++;
+ return;
+ } else if (ret == 0 && should_pass == 0) {
+ printf("I:getrrsetbyname(%s, %d) unexpectedly succeeded\n",
+ name, rdtype);
+ fails++;
+ freerrset(rrinfo);
+ return;
+ } else if (ret != 0)
+ return;
+ if (rrinfo->rri_nrdatas != nrdatas) {
+ printf("I:getrrsetbyname(%s, %d): got %d rr, expected %d\n",
+ name, rdtype, rrinfo->rri_nrdatas, nrdatas);
+ fails++;
+ }
+ if (rrinfo->rri_nsigs != nsigs) {
+ printf("I:getrrsetbyname(%s, %d): got %d sig, expected %d\n",
+ name, rdtype, rrinfo->rri_nsigs, nsigs);
+ fails++;
+ }
+ freerrset(rrinfo);
+ return;
+}
+
+int
+main(void) {
+ lwres_result_t ret;
+
+ lwres_udp_port = 9210;
+ lwres_resolv_conf = "resolv.conf";
+
+ ret = lwres_context_create(&ctx, NULL, NULL, NULL, 0);
+ CHECK(ret, "lwres_context_create");
+
+ ret = lwres_conf_parse(ctx, "resolv.conf");
+ CHECK(ret, "lwres_conf_parse");
+
+ test_noop();
+
+ test_gabn("a.example1", LWRES_R_SUCCESS, "10.0.1.1",
+ LWRES_ADDRTYPE_V4);
+ test_gabn("a.example1.", LWRES_R_SUCCESS, "10.0.1.1",
+ LWRES_ADDRTYPE_V4);
+ test_gabn("a.example2", LWRES_R_SUCCESS, "10.0.2.1",
+ LWRES_ADDRTYPE_V4);
+ test_gabn("a.example2.", LWRES_R_SUCCESS, "10.0.2.1",
+ LWRES_ADDRTYPE_V4);
+ test_gabn("a.example3", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V4);
+ test_gabn("a.example3.", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V4);
+ test_gabn("a", LWRES_R_SUCCESS, "10.0.1.1", LWRES_ADDRTYPE_V4);
+ test_gabn("a.", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V4);
+
+ test_gabn("a2", LWRES_R_SUCCESS, "10.0.1.1", LWRES_ADDRTYPE_V4);
+ test_gabn("a3", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V4);
+
+ test_gabn("b.example1", LWRES_R_SUCCESS,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ LWRES_ADDRTYPE_V6);
+ test_gabn("b.example1.", LWRES_R_SUCCESS,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ LWRES_ADDRTYPE_V6);
+ test_gabn("b.example2", LWRES_R_SUCCESS,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ LWRES_ADDRTYPE_V6);
+ test_gabn("b.example2.", LWRES_R_SUCCESS,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ LWRES_ADDRTYPE_V6);
+ test_gabn("b.example3", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V6);
+ test_gabn("b.example3.", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V6);
+ test_gabn("b", LWRES_R_SUCCESS,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ LWRES_ADDRTYPE_V6);
+ test_gabn("b.", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V6);
+
+ test_gabn("d.example1", LWRES_R_NOTFOUND, NULL, LWRES_ADDRTYPE_V6);
+
+ test_gabn("x", LWRES_R_SUCCESS, "10.1.10.1", LWRES_ADDRTYPE_V4);
+ test_gabn("x.", LWRES_R_SUCCESS, "10.1.10.1", LWRES_ADDRTYPE_V4);
+
+ test_gnba("10.10.10.1", LWRES_ADDRTYPE_V4, LWRES_R_SUCCESS,
+ "ipv4.example");
+ test_gnba("10.10.10.17", LWRES_ADDRTYPE_V4, LWRES_R_NOTFOUND,
+ NULL);
+ test_gnba("0123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ LWRES_ADDRTYPE_V6, LWRES_R_SUCCESS, "ip6.int.example");
+ test_gnba("0123:4567:89ab:cdef:0123:4567:89ab:cde0",
+ LWRES_ADDRTYPE_V6, LWRES_R_NOTFOUND, NULL);
+ test_gnba("1123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ LWRES_ADDRTYPE_V6, LWRES_R_SUCCESS, "ip6.arpa.example");
+ test_gnba("1123:4567:89ab:cdef:0123:4567:89ab:cde0",
+ LWRES_ADDRTYPE_V6, LWRES_R_NOTFOUND, NULL);
+
+ test_gethostbyname("a.example1.", "10.0.1.1");
+ test_gethostbyname("q.example1.", NULL);
+
+ test_gethostbyname2("a.example1.", "10.0.1.1", AF_INET);
+ test_gethostbyname2("b.example1.",
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ AF_INET6);
+ test_gethostbyname2("q.example1.", NULL, AF_INET);
+
+ test_getipnodebyname("a.example1.", "10.0.1.1", AF_INET, 0, 0);
+ test_getipnodebyname("b.example1.",
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ AF_INET6, 0, 0);
+ test_getipnodebyname("a.example1.",
+ "::ffff:10.0.1.1", AF_INET6, 1, 0);
+ test_getipnodebyname("a.example1.",
+ "::ffff:10.0.1.1", AF_INET6, 1, 1);
+ test_getipnodebyname("b.example1.",
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff",
+ AF_INET6, 1, 1);
+ test_getipnodebyname("q.example1.", NULL, AF_INET, 0, 0);
+
+ test_gethostbyaddr("10.10.10.1", AF_INET, "ipv4.example");
+ test_gethostbyaddr("10.10.10.17", AF_INET, NULL);
+ test_gethostbyaddr("0123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.int.example");
+ test_gethostbyaddr("1123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.arpa.example");
+
+ test_getipnodebyaddr("10.10.10.1", AF_INET, "ipv4.example");
+ test_getipnodebyaddr("10.10.10.17", AF_INET, NULL);
+ test_getipnodebyaddr("0123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.int.example");
+ test_getipnodebyaddr("1123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.arpa.example");
+
+ test_getaddrinfo("a.example1.", AF_INET, 1, 1, "10.0.1.1");
+ test_getaddrinfo("a.example1.", AF_INET, 1, 0, "10.0.1.1");
+ test_getaddrinfo("a.example1.", AF_INET, 0, 1, NULL);
+ test_getaddrinfo("b.example1.", AF_INET6, 1, 1,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff");
+ test_getaddrinfo("b.example1.", AF_INET6, 1, 0, NULL);
+ test_getaddrinfo("b.example1.", AF_INET6, 0, 1,
+ "eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff");
+
+ test_getnameinfo("10.10.10.1", AF_INET, "ipv4.example");
+ test_getnameinfo("10.10.10.17", AF_INET, NULL);
+ test_getnameinfo("0123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.int.example");
+ test_getnameinfo("1123:4567:89ab:cdef:0123:4567:89ab:cdef",
+ AF_INET6, "ip6.arpa.example");
+ test_getnameinfo("1122:3344:5566:7788:99aa:bbcc:ddee:ff00",
+ AF_INET6, "dname.example1");
+
+ test_getrrsetbyname("a", 1, 1, 1, 0, 1);
+ test_getrrsetbyname("a.example1.", 1, 1, 1, 0, 1);
+ test_getrrsetbyname("e.example1.", 1, 1, 1, 1, 1);
+ test_getrrsetbyname("e.example1.", 1, 255, 1, 1, 0);
+ test_getrrsetbyname("e.example1.", 1, 46, 2, 0, 1);
+ test_getrrsetbyname("", 1, 1, 0, 0, 0);
+
+ if (fails == 0)
+ printf("I:ok\n");
+ return (fails);
+}
diff --git a/bin/tests/system/lwresd/ns1/10.10.10.in-addr.arpa.db b/bin/tests/system/lwresd/ns1/10.10.10.in-addr.arpa.db
new file mode 100644
index 0000000..8c8adca
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/10.10.10.in-addr.arpa.db
@@ -0,0 +1,29 @@
+; Copyright (C) 2004, 2007 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: 10.10.10.in-addr.arpa.db,v 1.10 2007/06/19 23:47:04 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000062001 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+1 PTR ipv4.example.
diff --git a/bin/tests/system/lwresd/ns1/e.example1.db b/bin/tests/system/lwresd/ns1/e.example1.db
new file mode 100644
index 0000000..2d9587c
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/e.example1.db
@@ -0,0 +1,54 @@
+; File written on Wed Mar 5 10:20:40 2008
+; dnssec_signzone version 9.3.4-P1
+e.example1. 300 IN SOA mname1. . (
+ 2002082210 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ 300 RRSIG SOA 5 2 300 20010101000000 (
+ 20000101000000 14043 e.example1.
+ KtYwrnKM7Tu53BNf8XuTix53r9kDdCneJ1X7
+ xklFbp4YjRKC3NhwVK9PFe0jdHOkIDMtrwxn
+ n7/Rp07xIyURqw== )
+ 300 NS ns.e.example1.
+ 300 RRSIG NS 5 2 300 20010101000000 (
+ 20000101000000 14043 e.example1.
+ KBPx3XmNl4swVPdwuUEFuzZedMSfsyK2a0Fu
+ o2wBnbCuS7G7DtfW9690lP/eTyixLOIwlFLQ
+ MrjN3+XgpkdgIw== )
+ 300 A 10.0.1.1
+ 300 RRSIG A 5 2 300 20010101000000 (
+ 20000101000000 14043 e.example1.
+ KYlxMQUvv8DQtVgS23lNL5tFYmRppJ7vTgH3
+ btvgKbyHxW/04ewRsgCa82iu3iJipdEhKM11
+ ALkRNhqL7frnig== )
+ 3600 NSEC ns.e.example1. A NS SOA RRSIG NSEC DNSKEY
+ 3600 RRSIG NSEC 5 2 3600 20010101000000 (
+ 20000101000000 14043 e.example1.
+ azSgagb7bldM06qSZg8nDZWOY2FbqeZY0/T8
+ nC+6VhCs7YTfNvXynLWmvmpqL7gVT6/O+Yi2
+ 2lmdntld7GORrQ== )
+ 300 DNSKEY 256 3 5 (
+ AwEAAcvAUMfH7wA0z077fJaF7RMrxAFyvo0/
+ 7aAL4d2/yA5TqTaUCVnJtE+XgGO34kH9mwae
+ we+Nyv2kRWDeLl6nhGk=
+ ) ; key id = 14043
+ 300 RRSIG DNSKEY 5 2 300 20010101000000 (
+ 20000101000000 14043 e.example1.
+ BQFWOHopXuBNdzcopkdl1YVKGF0QvIaYpywM
+ fcpG5gi+sy9EoTofQ1UGsLOjU3nFXCvJFG4K
+ 1gUhzEEti440/g== )
+ns.e.example1. 300 IN A 10.53.0.1
+ 300 RRSIG A 5 3 300 20010101000000 (
+ 20000101000000 14043 e.example1.
+ cYPzsWNQ/eL4h2lihKRjKT2jhGpOqV9woGJA
+ /Jstx2iethOAvYtgY22CsAbCUr/6E4bSgBZR
+ TMoC604cNdFzIw== )
+ 3600 NSEC e.example1. A RRSIG NSEC
+ 3600 RRSIG NSEC 5 3 3600 20010101000000 (
+ 20000101000000 14043 e.example1.
+ J8Md544zDLP4GjyAtkjH/rSFvpzXY/7bgJRS
+ YDoARwFQRmlrJvavXEjqElb2fTQqlNNz1cal
+ QROz/WJ3GLwOWw== )
diff --git a/bin/tests/system/lwresd/ns1/example1.db b/bin/tests/system/lwresd/ns1/example1.db
new file mode 100644
index 0000000..16a53f4
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/example1.db
@@ -0,0 +1,35 @@
+; Copyright (C) 2004, 2007, 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
+; 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: example1.db,v 1.19 2008/04/02 23:46:57 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2002082210 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+a A 10.0.1.1
+a2 CNAME a
+a3 CNAME nowhere
+b AAAA eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff
+8.8.7.7 DNAME net
+0.0.f.f.e.e.d.d.c.c.b.b.a.a.9.9.net PTR dname
+e NS ns.e
diff --git a/bin/tests/system/lwresd/ns1/example2.db b/bin/tests/system/lwresd/ns1/example2.db
new file mode 100644
index 0000000..495f2f6
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/example2.db
@@ -0,0 +1,30 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2000-2002 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: example2.db,v 1.10 2007/06/19 23:47:04 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000062001 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+a A 10.0.2.1
+b AAAA eeee:eeee:eeee:eeee:ffff:ffff:ffff:ffff
diff --git a/bin/tests/system/lwresd/ns1/ip6.arpa.db b/bin/tests/system/lwresd/ns1/ip6.arpa.db
new file mode 100644
index 0000000..d2a1965
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/ip6.arpa.db
@@ -0,0 +1,30 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2000-2002 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: ip6.arpa.db,v 1.11 2007/06/19 23:47:04 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2002082300 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.1 PTR ip6.arpa.example.
+6.6.5.5.4.4.3.3.2.2.1.1 DNAME example1.
diff --git a/bin/tests/system/lwresd/ns1/ip6.int.db b/bin/tests/system/lwresd/ns1/ip6.int.db
new file mode 100644
index 0000000..8085426
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/ip6.int.db
@@ -0,0 +1,29 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2000-2002 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: ip6.int.db,v 1.11 2007/06/19 23:47:04 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2002082300 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0 PTR ip6.int.example.
diff --git a/bin/tests/system/lwresd/ns1/named.conf b/bin/tests/system/lwresd/ns1/named.conf
new file mode 100644
index 0000000..2d649c7
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/named.conf
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004, 2006-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
+ * 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.conf,v 1.21 2008/04/02 23:46:57 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example1." {
+ type master;
+ file "example1.db";
+};
+
+zone "e.example1." {
+ type master;
+ file "e.example1.db";
+};
+
+zone "example2." {
+ type master;
+ file "example2.db";
+};
+
+zone "10.10.10.in-addr.arpa." {
+ type master;
+ file "10.10.10.in-addr.arpa.db";
+};
+
+zone "ip6.int." {
+ type master;
+ file "ip6.int.db";
+};
+
+zone "ip6.arpa." {
+ type master;
+ file "ip6.arpa.db";
+};
diff --git a/bin/tests/system/lwresd/ns1/root.db b/bin/tests/system/lwresd/ns1/root.db
new file mode 100644
index 0000000..9cd0a16
--- /dev/null
+++ b/bin/tests/system/lwresd/ns1/root.db
@@ -0,0 +1,33 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.9 2007/06/19 23:47:04 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1. NS ns.example1.
+ns.example1. A 10.53.0.2
+example2. NS ns.example2.
+ns.example2. A 10.53.0.2
+x A 10.1.10.1
diff --git a/bin/tests/system/lwresd/resolv.conf b/bin/tests/system/lwresd/resolv.conf
new file mode 100644
index 0000000..1aa88c9
--- /dev/null
+++ b/bin/tests/system/lwresd/resolv.conf
@@ -0,0 +1,21 @@
+# Copyright (C) 2004, 2007 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: resolv.conf,v 1.11 2007/06/19 23:47:04 tbox Exp $
+
+nameserver 10.53.0.1
+lwserver 10.53.0.1
+search example1.
+ndots 1
diff --git a/bin/tests/system/lwresd/tests.sh b/bin/tests/system/lwresd/tests.sh
new file mode 100644
index 0000000..c425410
--- /dev/null
+++ b/bin/tests/system/lwresd/tests.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.18 2007/06/18 23:47:29 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+echo "I:using resolv.conf"
+ret=0
+./lwtest || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+fi
+status=`expr $status + $ret`
+
+$PERL $SYSTEMTESTTOP/stop.pl . lwresd1
+
+$PERL $SYSTEMTESTTOP/start.pl . lwresd1 -- "-m record,size,mctx -c lwresd.conf -d 99 -g"
+
+echo "I:using lwresd.conf"
+ret=0
+./lwtest || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+fi
+status=`expr $status + $ret`
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/masterfile/clean.sh b/bin/tests/system/masterfile/clean.sh
new file mode 100644
index 0000000..d90a65d
--- /dev/null
+++ b/bin/tests/system/masterfile/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# 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: clean.sh,v 1.5 2007/09/26 03:22:44 marka Exp $
+
+rm -f dig.out
+rm -f */named.memstats
diff --git a/bin/tests/system/masterfile/knowngood.dig.out b/bin/tests/system/masterfile/knowngood.dig.out
new file mode 100644
index 0000000..56de555
--- /dev/null
+++ b/bin/tests/system/masterfile/knowngood.dig.out
@@ -0,0 +1,33 @@
+include. 300 IN SOA ns.include. hostmaster.include. 1 3600 1800 1814400 3600
+include. 300 IN NS ns.include.
+a.include. 300 IN A 10.0.0.1
+a.include. 300 IN A 10.0.0.99
+a.a.include. 300 IN A 10.0.1.1
+b.foo.a.include. 300 IN A 10.0.2.2
+b.include. 300 IN A 10.0.0.2
+b.include. 300 IN A 10.0.0.99
+a.b.include. 300 IN A 10.0.1.1
+c.b.include. 300 IN A 10.0.0.3
+b.foo.b.include. 300 IN A 10.0.2.2
+ns.include. 300 IN A 127.0.0.1
+include. 300 IN SOA ns.include. hostmaster.include. 1 3600 1800 1814400 3600
+ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3
+ttl2. 1 IN NS ns.ttl2.
+a.ttl2. 1 IN TXT "inherited ttl 1"
+b.ttl2. 2 IN TXT "explicit ttl 2"
+c.ttl2. 2 IN TXT "inherited ttl 2"
+d.ttl2. 3 IN TXT "default ttl 3"
+e.ttl2. 2 IN TXT "explicit ttl 2"
+f.ttl2. 3 IN TXT "default ttl 3"
+ns.ttl2. 1 IN A 10.53.0.1
+ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3
+ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3
+ttl2. 1 IN NS ns.ttl2.
+a.ttl2. 1 IN TXT "inherited ttl 1"
+b.ttl2. 2 IN TXT "explicit ttl 2"
+c.ttl2. 2 IN TXT "inherited ttl 2"
+d.ttl2. 3 IN TXT "default ttl 3"
+e.ttl2. 2 IN TXT "explicit ttl 2"
+f.ttl2. 3 IN TXT "default ttl 3"
+ns.ttl2. 1 IN A 10.53.0.1
+ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3
diff --git a/bin/tests/system/masterfile/ns1/include.db b/bin/tests/system/masterfile/ns1/include.db
new file mode 100644
index 0000000..47c985f
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/include.db
@@ -0,0 +1,41 @@
+; 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: include.db,v 1.5 2007/06/19 23:47:04 tbox Exp $
+
+; Test $INCLUDE current domain name and origin semantics
+
+$TTL 300
+@ IN SOA ns hostmaster (
+ 1 ; serial
+ 3600
+ 1800
+ 1814400
+ 3600
+ )
+ NS ns
+
+ns A 127.0.0.1
+
+a A 10.0.0.1
+$INCLUDE sub.db a
+; use the current domain name
+ A 10.0.0.99
+b A 10.0.0.2
+$ORIGIN b
+$INCLUDE sub.db
+; use the current domain name
+ A 10.0.0.99
+c A 10.0.0.3
diff --git a/bin/tests/system/masterfile/ns1/named.conf b/bin/tests/system/masterfile/ns1/named.conf
new file mode 100644
index 0000000..1669f94
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/named.conf
@@ -0,0 +1,47 @@
+/*
+ * 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: named.conf,v 1.6 2007/06/19 23:47:04 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "include" {
+ type master;
+ file "include.db";
+};
+
+zone "ttl1" {
+ type master;
+ file "ttl1.db";
+};
+
+zone "ttl2" {
+ type master;
+ file "ttl2.db";
+};
diff --git a/bin/tests/system/masterfile/ns1/sub.db b/bin/tests/system/masterfile/ns1/sub.db
new file mode 100644
index 0000000..d6186f1
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/sub.db
@@ -0,0 +1,21 @@
+; 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: sub.db,v 1.5 2007/06/19 23:47:04 tbox Exp $
+
+a A 10.0.1.1
+$ORIGIN foo
+b A 10.0.2.2
+
diff --git a/bin/tests/system/masterfile/ns1/ttl1.db b/bin/tests/system/masterfile/ns1/ttl1.db
new file mode 100644
index 0000000..c575cec
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/ttl1.db
@@ -0,0 +1,33 @@
+; 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: ttl1.db,v 1.6 2007/06/19 23:47:04 tbox Exp $
+
+@ IN SOA ns hostmaster (
+ 1 ; serial
+ 3600
+ 1800
+ 1814400
+ 3
+ )
+ NS ns
+ns A 10.53.0.1
+a TXT "soa minttl 3"
+b 2 TXT "explicit ttl 2"
+c TXT "soa minttl 3"
+$TTL 1
+d TXT "default ttl 1"
+e 4 TXT "explicit ttl 4"
+f TXT "default ttl 1"
diff --git a/bin/tests/system/masterfile/ns1/ttl2.db b/bin/tests/system/masterfile/ns1/ttl2.db
new file mode 100644
index 0000000..2a01123
--- /dev/null
+++ b/bin/tests/system/masterfile/ns1/ttl2.db
@@ -0,0 +1,36 @@
+; 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: ttl2.db,v 1.6 2007/06/19 23:47:04 tbox Exp $
+
+@ 1 IN SOA ns hostmaster (
+ 1 ; serial
+ 3600
+ 1800
+ 1814400
+ 3
+ )
+ NS ns
+ns A 10.53.0.1
+a TXT "inherited ttl 1"
+b 2 TXT "explicit ttl 2"
+c TXT "inherited ttl 2"
+$TTL 3
+d TXT "default ttl 3"
+e 2 TXT "explicit ttl 2"
+f TXT "default ttl 3"
+
+
+
diff --git a/bin/tests/system/masterfile/tests.sh b/bin/tests/system/masterfile/tests.sh
new file mode 100644
index 0000000..beebcdc
--- /dev/null
+++ b/bin/tests/system/masterfile/tests.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# 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: tests.sh,v 1.5 2007/06/19 23:47:04 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+echo "I:test master file \$INCLUDE semantics"
+$DIG +nostats +nocmd include. axfr @10.53.0.1 -p 5300 >dig.out
+
+echo "I:test master file BIND 8 compatibility TTL and \$TTL semantics"
+$DIG +nostats +nocmd ttl2. axfr @10.53.0.1 -p 5300 >>dig.out
+
+echo "I:test of master file RFC1035 TTL and \$TTL semantics"
+$DIG +nostats +nocmd ttl2. axfr @10.53.0.1 -p 5300 >>dig.out
+
+diff dig.out knowngood.dig.out || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/masterformat/clean.sh b/bin/tests/system/masterformat/clean.sh
new file mode 100755
index 0000000..1909dc2
--- /dev/null
+++ b/bin/tests/system/masterformat/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) 2005, 2007 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: clean.sh,v 1.5 2007/09/26 03:22:44 marka Exp $
+
+rm -f named-compilezone
+rm -f ns1/example.db.raw
+rm -f ns2/example.db
+rm -f dig.out.*
+rm -f */named.memstats
diff --git a/bin/tests/system/masterformat/ns1/compile.sh b/bin/tests/system/masterformat/ns1/compile.sh
new file mode 100755
index 0000000..551a01f
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/compile.sh
@@ -0,0 +1,17 @@
+# Copyright (C) 2005-2007 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: compile.sh,v 1.6 2007/06/19 23:47:04 tbox Exp $
+
+../named-compilezone -D -F raw -o example.db.raw example example.db
diff --git a/bin/tests/system/masterformat/ns1/example.db b/bin/tests/system/masterformat/ns1/example.db
new file mode 100644
index 0000000..c216706
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/example.db
@@ -0,0 +1,54 @@
+; Copyright (C) 2005, 2007 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: example.db,v 1.5 2007/06/19 23:47:04 tbox Exp $
+
+$TTL 1D
+
+@ IN SOA ns hostmaster (
+ 1
+ 3600
+ 1800
+ 1814400
+ 3
+ )
+ NS ns
+ns A 10.53.0.1
+mx MX 10 mail
+a A 10.53.0.1
+ A 10.53.0.2
+aaaa AAAA 2001:db8::53
+cname CNAME cname-target
+dname DNAME dname-target
+txt TXT "this is text"
+
+;;
+;; we are not testing DNSSEC behavior, so we don't care about the semantics
+;; of the following records.
+dnskey 300 DNSKEY 256 3 1 (
+ AQPTpWyReB/e9Ii6mVGnakS8hX2zkh/iUYAg
+ +Ge4noWROpTWOIBvm76zeJPWs4Zfqa1IsswD
+ Ix5Mqeg0zwclz59uecKsKyx5w9IhtZ8plc4R
+ b9VIE5x7KNHAYTvTO5d4S8M=
+ )
+ds 300 DS 30795 1 1 (
+ 310D27F4D82C1FC2400704EA9939FE6E1CEA
+ A3B9 )
+nsec 600 NSEC nsecnext NS DS RRSIG NSEC
+rrsig 300 RRSIG SOA 1 0 300 20050714214747 (
+ 20050614214747 30795 .
+ yi/RRPAQmn6rnjDQaCqVValBa+ICF00ZldKf
+ ZSDaoew5mMUh83DlrrPPNeAxrzMSNzDGlJ6P
+ fdyIFgzPn/CvthF4kjBUAiJTp4r2zhlaUJQ+
+ QFo+drYXYgVJo6aA36fj )
diff --git a/bin/tests/system/masterformat/ns1/named.conf b/bin/tests/system/masterformat/ns1/named.conf
new file mode 100644
index 0000000..a2971f5
--- /dev/null
+++ b/bin/tests/system/masterformat/ns1/named.conf
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2005, 2007 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.conf,v 1.4 2007/06/19 23:47:04 tbox Exp $ */
+
+// NS1
+
+controls { /* empty */ };
+
+options {
+ pid-file "named.pid";
+ listen-on port 5300 { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-enable yes;
+};
+
+zone "example" {
+ type master;
+ masterfile-format raw;
+ file "example.db.raw";
+};
diff --git a/bin/tests/system/masterformat/ns2/named.conf b/bin/tests/system/masterformat/ns2/named.conf
new file mode 100644
index 0000000..3cda00e
--- /dev/null
+++ b/bin/tests/system/masterformat/ns2/named.conf
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2005, 2007 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.conf,v 1.4 2007/06/19 23:47:04 tbox Exp $ */
+
+// NS2
+
+controls { /* empty */ };
+
+options {
+ pid-file "named.pid";
+ listen-on port 5300 { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ dnssec-enable yes;
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
diff --git a/bin/tests/system/masterformat/setup.sh b/bin/tests/system/masterformat/setup.sh
new file mode 100755
index 0000000..4c85ab7
--- /dev/null
+++ b/bin/tests/system/masterformat/setup.sh
@@ -0,0 +1,20 @@
+# Copyright (C) 2005-2007 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: setup.sh,v 1.6 2007/06/19 23:47:04 tbox Exp $
+
+ln -s $CHECKZONE named-compilezone
+rm -f ns1/example.db.raw
+cp ns1/example.db ns2/
+cd ns1 && sh compile.sh
diff --git a/bin/tests/system/masterformat/tests.sh b/bin/tests/system/masterformat/tests.sh
new file mode 100755
index 0000000..71c115d
--- /dev/null
+++ b/bin/tests/system/masterformat/tests.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# Copyright (C) 2005, 2007 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: tests.sh,v 1.4 2007/06/19 23:47:04 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noauth +noadd +nosea +nostat +noquest +nocomm +nocmd"
+
+status=0
+
+echo "I:checking that master file in the raw format worked"
+
+for server in 1 2
+do
+ for name in ns mx a aaaa cname dname txt rrsig nsec dnskey ds
+ do
+ $DIG $DIGOPTS $name.example. $name @10.53.0.$server -p 5300
+ echo
+ done > dig.out.$server
+done
+
+diff dig.out.1 dig.out.2 || status=1
+
+echo "I:exit status: $status"
+exit $status
+#!/bin/sh
+#
+# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND 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: tests.sh,v 1.4 2007/06/19 23:47:04 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noauth +noadd +nosea +nostat +noquest +nocomm +nocmd"
+
+status=0
+
+echo "I:checking that master file in the raw format worked"
+
+for server in 1 2
+do
+ for name in ns mx a aaaa cname dname txt rrsig nsec dnskey ds
+ do
+ $DIG $DIGOPTS $name.example. $name @10.53.0.$server -p 5300
+ echo
+ done > dig.out.$server
+done
+
+diff dig.out.1 dig.out.2 || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/notify/clean.sh b/bin/tests/system/notify/clean.sh
new file mode 100644
index 0000000..6a08bab
--- /dev/null
+++ b/bin/tests/system/notify/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.12 2007/09/26 03:22:44 marka Exp $
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f ns3/example.bk dig.out.ns2 dig.out.ns3
+rm -f ns2/example.db
+rm -f */named.memstats
diff --git a/bin/tests/system/notify/ns1/named.conf b/bin/tests/system/notify/ns1/named.conf
new file mode 100644
index 0000000..29b22e5
--- /dev/null
+++ b/bin/tests/system/notify/ns1/named.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.18 2007/06/19 23:47:04 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/notify/ns1/root.db b/bin/tests/system/notify/ns1/root.db
new file mode 100644
index 0000000..cff7b81
--- /dev/null
+++ b/bin/tests/system/notify/ns1/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.9 2007/06/19 23:47:04 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/notify/ns2/example1.db b/bin/tests/system/notify/ns2/example1.db
new file mode 100644
index 0000000..f081693
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example1.db
@@ -0,0 +1,150 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2000-2002 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: example1.db,v 1.12 2007/06/19 23:47:04 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.0.0.1
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.
+ns A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/notify/ns2/example2.db b/bin/tests/system/notify/ns2/example2.db
new file mode 100644
index 0000000..93ae040
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example2.db
@@ -0,0 +1,150 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2000-2002 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: example2.db,v 1.12 2007/06/19 23:47:04 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 2 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.0.0.2
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.
+ns A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/notify/ns2/example3.db b/bin/tests/system/notify/ns2/example3.db
new file mode 100644
index 0000000..3afbaa6
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example3.db
@@ -0,0 +1,150 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2000-2002 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: example3.db,v 1.12 2007/06/19 23:47:04 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 3 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.0.0.3
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.
+ns A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/notify/ns2/example4.db b/bin/tests/system/notify/ns2/example4.db
new file mode 100644
index 0000000..8c18a37
--- /dev/null
+++ b/bin/tests/system/notify/ns2/example4.db
@@ -0,0 +1,150 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2000-2002 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: example4.db,v 1.12 2007/06/19 23:47:04 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 4 ; serial
+ 300 ; refresh (300 seconds)
+ 300 ; retry (300 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.0.0.4
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.
+ns A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/notify/ns2/named.conf b/bin/tests/system/notify/ns2/named.conf
new file mode 100644
index 0000000..f57a107
--- /dev/null
+++ b/bin/tests/system/notify/ns2/named.conf
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.20 2007/06/19 23:47:04 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/notify/ns3/named.conf b/bin/tests/system/notify/ns3/named.conf
new file mode 100644
index 0000000..5316957
--- /dev/null
+++ b/bin/tests/system/notify/ns3/named.conf
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.24 2007/06/18 23:47:29 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "example.bk";
+};
+
+
diff --git a/bin/tests/system/notify/setup.sh b/bin/tests/system/notify/setup.sh
new file mode 100644
index 0000000..eebcbf1
--- /dev/null
+++ b/bin/tests/system/notify/setup.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.10 2007/06/19 23:47:04 tbox Exp $
+
+cp -f ns2/example1.db ns2/example.db
diff --git a/bin/tests/system/notify/tests.sh b/bin/tests/system/notify/tests.sh
new file mode 100644
index 0000000..0f14240
--- /dev/null
+++ b/bin/tests/system/notify/tests.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.33 2007/06/19 23:47:04 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd a.example.\
+ @10.53.0.2 a -p 5300 > dig.out.ns2 || status=1
+grep ";" dig.out.ns2
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd a.example.\
+ @10.53.0.3 a -p 5300 > dig.out.ns3 || status=1
+grep ";" dig.out.ns3
+
+$PERL ../digcomp.pl dig.out.ns2 dig.out.ns3 || status=1
+
+rm -f ns2/example.db
+cp -f ns2/example2.db ns2/example.db
+kill -HUP `cat ns2/named.pid`
+sleep 45
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd a.example.\
+ @10.53.0.2 a -p 5300 > dig.out.ns2 || status=1
+grep ";" dig.out.ns2
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd a.example.\
+ @10.53.0.3 a -p 5300 > dig.out.ns3 || status=1
+grep ";" dig.out.ns3
+
+$PERL ../digcomp.pl dig.out.ns2 dig.out.ns3 || status=1
+
+###
+# Why does not doing the stop not cause problems with the start further on?
+###
+$PERL $SYSTEMTESTTOP/stop.pl . ns3
+
+rm -f ns2/example.db
+cp -f ns2/example3.db ns2/example.db
+kill -HUP `cat ns2/named.pid`
+sleep 45
+
+$PERL $SYSTEMTESTTOP/start.pl . ns3
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd a.example.\
+ @10.53.0.2 a -p 5300 > dig.out.ns2 || status=1
+grep ";" dig.out.ns2
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd a.example.\
+ @10.53.0.3 a -p 5300 > dig.out.ns3 || status=1
+grep ";" dig.out.ns3
+
+$PERL ../digcomp.pl dig.out.ns2 dig.out.ns3 || status=1
+
+$PERL $SYSTEMTESTTOP/stop.pl . ns2
+
+rm -f ns2/example.db
+cp -f ns2/example4.db ns2/example.db
+
+$PERL $SYSTEMTESTTOP/start.pl . ns2
+
+sleep 45
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd a.example.\
+ @10.53.0.2 a -p 5300 > dig.out.ns2 || status=1
+grep ";" dig.out.ns2
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd a.example.\
+ @10.53.0.3 a -p 5300 > dig.out.ns3 || status=1
+grep ";" dig.out.ns3
+
+$PERL ../digcomp.pl dig.out.ns2 dig.out.ns3 || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/nsupdate/clean.sh b/bin/tests/system/nsupdate/clean.sh
new file mode 100644
index 0000000..565c97b
--- /dev/null
+++ b/bin/tests/system/nsupdate/clean.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.12 2007/09/26 03:22:44 marka Exp $
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f dig.out.ns1 dig.out.ns2 dig.out.ns1.after ns1/*.jnl ns2/*.jnl \
+ ns1/example.db ns1/update.db
+rm -f ns2/example.bk
+rm -f ns2/update.bk
+rm -f */named.memstats
diff --git a/bin/tests/system/nsupdate/knowngood.ns1.after b/bin/tests/system/nsupdate/knowngood.ns1.after
new file mode 100644
index 0000000..32e1c8d
--- /dev/null
+++ b/bin/tests/system/nsupdate/knowngood.ns1.after
@@ -0,0 +1,99 @@
+example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 2 2000 2000 1814400 3600
+example.nil. 300 IN NS ns1.example.nil.
+example.nil. 300 IN NS ns2.example.nil.
+*.example.nil. 300 IN MX 10 mail.example.nil.
+a.example.nil. 300 IN TXT "foo foo foo"
+a.example.nil. 300 IN PTR foo.net.
+a01.example.nil. 3600 IN A 0.0.0.0
+a02.example.nil. 3600 IN A 255.255.255.255
+a601.example.nil. 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01.example.nil. 3600 IN AFSDB 0 hostname.example.nil.
+afsdb02.example.nil. 3600 IN AFSDB 65535 .
+b.example.nil. 300 IN CNAME foo.net.
+c.example.nil. 300 IN A 73.80.65.49
+cert01.example.nil. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+cname01.example.nil. 3600 IN CNAME cname-target.
+cname02.example.nil. 3600 IN CNAME cname-target.example.nil.
+cname03.example.nil. 3600 IN CNAME .
+d.example.nil. 300 IN A 73.80.65.49
+dname01.example.nil. 3600 IN DNAME dname-target.
+dname02.example.nil. 3600 IN DNAME dname-target.example.nil.
+dname03.example.nil. 3600 IN DNAME .
+e.example.nil. 300 IN MX 10 mail.example.nil.
+e.example.nil. 300 IN TXT "one"
+e.example.nil. 300 IN TXT "two"
+e.example.nil. 300 IN TXT "three"
+e.example.nil. 300 IN A 73.80.65.49
+e.example.nil. 300 IN A 73.80.65.50
+e.example.nil. 300 IN A 73.80.65.51
+e.example.nil. 300 IN A 73.80.65.52
+f.example.nil. 300 IN A 73.80.65.52
+gpos01.example.nil. 3600 IN GPOS "-22.6882" "116.8652" "250.0"
+gpos02.example.nil. 3600 IN GPOS "" "" ""
+hinfo01.example.nil. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02.example.nil. 3600 IN HINFO "PC" "NetBSD"
+isdn01.example.nil. 3600 IN ISDN "isdn-address"
+isdn02.example.nil. 3600 IN ISDN "isdn-address" "subaddress"
+isdn03.example.nil. 3600 IN ISDN "isdn-address"
+isdn04.example.nil. 3600 IN ISDN "isdn-address" "subaddress"
+key01.example.nil. 3600 IN KEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+kx01.example.nil. 3600 IN KX 10 kdc.example.nil.
+kx02.example.nil. 3600 IN KX 10 .
+loc01.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01.example.nil. 3600 IN MG madname.example.nil.
+mb02.example.nil. 3600 IN MG .
+mg01.example.nil. 3600 IN MG mgmname.example.nil.
+mg02.example.nil. 3600 IN MG .
+minfo01.example.nil. 3600 IN MINFO rmailbx.example.nil. emailbx.example.nil.
+minfo02.example.nil. 3600 IN MINFO . .
+mr01.example.nil. 3600 IN MR mrname.example.nil.
+mr02.example.nil. 3600 IN MR .
+mx01.example.nil. 3600 IN MX 10 mail.example.nil.
+mx02.example.nil. 3600 IN MX 10 .
+naptr01.example.nil. 3600 IN NAPTR 0 0 "" "" "" .
+naptr02.example.nil. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+ns1.example.nil. 300 IN A 10.53.0.1
+ns2.example.nil. 300 IN A 10.53.0.2
+nsap-ptr01.example.nil. 3600 IN NSAP-PTR .
+nsap-ptr01.example.nil. 3600 IN NSAP-PTR foo.
+nsap01.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01.example.nil. 3600 IN NXT a.secure.example.nil. NS SOA MX SIG KEY LOC NXT
+nxt02.example.nil. 3600 IN NXT . NSAP-PTR NXT
+nxt03.example.nil. 3600 IN NXT . A
+nxt04.example.nil. 3600 IN NXT . 127
+ptr01.example.nil. 3600 IN PTR example.nil.
+px01.example.nil. 3600 IN PX 65535 foo. bar.
+px02.example.nil. 3600 IN PX 65535 . .
+rp01.example.nil. 3600 IN RP mbox-dname.example.nil. txt-dname.example.nil.
+rp02.example.nil. 3600 IN RP . .
+rt01.example.nil. 3600 IN RT 0 intermediate-host.example.nil.
+rt02.example.nil. 3600 IN RT 65535 .
+s.example.nil. 300 IN NS ns.s.example.nil.
+ns.s.example.nil. 300 IN A 73.80.65.49
+sig01.example.nil. 3600 IN SIG NXT 1 3 3600 20000102030405 19961211100908 2143 foo.example.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+srv01.example.nil. 3600 IN SRV 0 0 0 .
+srv02.example.nil. 3600 IN SRV 65535 65535 65535 old-slow-box.example.com.
+txt01.example.nil. 3600 IN TXT "foo"
+txt02.example.nil. 3600 IN TXT "foo" "bar"
+txt03.example.nil. 3600 IN TXT "foo"
+txt04.example.nil. 3600 IN TXT "foo" "bar"
+txt05.example.nil. 3600 IN TXT "foo bar"
+txt06.example.nil. 3600 IN TXT "foo bar"
+txt07.example.nil. 3600 IN TXT "foo bar"
+txt08.example.nil. 3600 IN TXT "foo\010bar"
+txt09.example.nil. 3600 IN TXT "foo\010bar"
+txt10.example.nil. 3600 IN TXT "foo bar"
+txt11.example.nil. 3600 IN TXT "\"foo\""
+txt12.example.nil. 3600 IN TXT "\"foo\""
+u.example.nil. 300 IN TXT "txt-not-in-nxt"
+a.u.example.nil. 300 IN A 73.80.65.49
+b.u.example.nil. 300 IN A 73.80.65.49
+updated.example.nil. 600 IN TXT "Foo"
+updated.example.nil. 600 IN A 10.10.10.1
+wks01.example.nil. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23
+wks02.example.nil. 3600 IN WKS 10.0.0.1 17 0 1 2 53
+wks03.example.nil. 3600 IN WKS 10.0.0.2 6 65535
+x2501.example.nil. 3600 IN X25 "123456789"
+example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 2 2000 2000 1814400 3600
diff --git a/bin/tests/system/nsupdate/knowngood.ns1.afterstop b/bin/tests/system/nsupdate/knowngood.ns1.afterstop
new file mode 100644
index 0000000..e871d4c
--- /dev/null
+++ b/bin/tests/system/nsupdate/knowngood.ns1.afterstop
@@ -0,0 +1,3 @@
+updated4.example.nil. 600 IN A 10.10.10.3
+example.nil. 300 IN NS ns1.example.nil.
+example.nil. 300 IN NS ns2.example.nil.
diff --git a/bin/tests/system/nsupdate/knowngood.ns1.before b/bin/tests/system/nsupdate/knowngood.ns1.before
new file mode 100644
index 0000000..e108c2a
--- /dev/null
+++ b/bin/tests/system/nsupdate/knowngood.ns1.before
@@ -0,0 +1,98 @@
+example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 1 2000 2000 1814400 3600
+example.nil. 300 IN NS ns1.example.nil.
+example.nil. 300 IN NS ns2.example.nil.
+*.example.nil. 300 IN MX 10 mail.example.nil.
+a.example.nil. 300 IN TXT "foo foo foo"
+a.example.nil. 300 IN PTR foo.net.
+a01.example.nil. 3600 IN A 0.0.0.0
+a02.example.nil. 3600 IN A 255.255.255.255
+a601.example.nil. 3600 IN AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01.example.nil. 3600 IN AFSDB 0 hostname.example.nil.
+afsdb02.example.nil. 3600 IN AFSDB 65535 .
+b.example.nil. 300 IN CNAME foo.net.
+c.example.nil. 300 IN A 73.80.65.49
+cert01.example.nil. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+cname01.example.nil. 3600 IN CNAME cname-target.
+cname02.example.nil. 3600 IN CNAME cname-target.example.nil.
+cname03.example.nil. 3600 IN CNAME .
+d.example.nil. 300 IN A 73.80.65.49
+dname01.example.nil. 3600 IN DNAME dname-target.
+dname02.example.nil. 3600 IN DNAME dname-target.example.nil.
+dname03.example.nil. 3600 IN DNAME .
+e.example.nil. 300 IN MX 10 mail.example.nil.
+e.example.nil. 300 IN TXT "one"
+e.example.nil. 300 IN TXT "two"
+e.example.nil. 300 IN TXT "three"
+e.example.nil. 300 IN A 73.80.65.49
+e.example.nil. 300 IN A 73.80.65.50
+e.example.nil. 300 IN A 73.80.65.51
+e.example.nil. 300 IN A 73.80.65.52
+f.example.nil. 300 IN A 73.80.65.52
+gpos01.example.nil. 3600 IN GPOS "-22.6882" "116.8652" "250.0"
+gpos02.example.nil. 3600 IN GPOS "" "" ""
+hinfo01.example.nil. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02.example.nil. 3600 IN HINFO "PC" "NetBSD"
+isdn01.example.nil. 3600 IN ISDN "isdn-address"
+isdn02.example.nil. 3600 IN ISDN "isdn-address" "subaddress"
+isdn03.example.nil. 3600 IN ISDN "isdn-address"
+isdn04.example.nil. 3600 IN ISDN "isdn-address" "subaddress"
+key01.example.nil. 3600 IN KEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+kx01.example.nil. 3600 IN KX 10 kdc.example.nil.
+kx02.example.nil. 3600 IN KX 10 .
+loc01.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02.example.nil. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01.example.nil. 3600 IN MG madname.example.nil.
+mb02.example.nil. 3600 IN MG .
+mg01.example.nil. 3600 IN MG mgmname.example.nil.
+mg02.example.nil. 3600 IN MG .
+minfo01.example.nil. 3600 IN MINFO rmailbx.example.nil. emailbx.example.nil.
+minfo02.example.nil. 3600 IN MINFO . .
+mr01.example.nil. 3600 IN MR mrname.example.nil.
+mr02.example.nil. 3600 IN MR .
+mx01.example.nil. 3600 IN MX 10 mail.example.nil.
+mx02.example.nil. 3600 IN MX 10 .
+naptr01.example.nil. 3600 IN NAPTR 0 0 "" "" "" .
+naptr02.example.nil. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+ns1.example.nil. 300 IN A 10.53.0.1
+ns2.example.nil. 300 IN A 10.53.0.2
+nsap-ptr01.example.nil. 3600 IN NSAP-PTR .
+nsap-ptr01.example.nil. 3600 IN NSAP-PTR foo.
+nsap01.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02.example.nil. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01.example.nil. 3600 IN NXT a.secure.example.nil. NS SOA MX SIG KEY LOC NXT
+nxt02.example.nil. 3600 IN NXT . NSAP-PTR NXT
+nxt03.example.nil. 3600 IN NXT . A
+nxt04.example.nil. 3600 IN NXT . 127
+ptr01.example.nil. 3600 IN PTR example.nil.
+px01.example.nil. 3600 IN PX 65535 foo. bar.
+px02.example.nil. 3600 IN PX 65535 . .
+rp01.example.nil. 3600 IN RP mbox-dname.example.nil. txt-dname.example.nil.
+rp02.example.nil. 3600 IN RP . .
+rt01.example.nil. 3600 IN RT 0 intermediate-host.example.nil.
+rt02.example.nil. 3600 IN RT 65535 .
+s.example.nil. 300 IN NS ns.s.example.nil.
+ns.s.example.nil. 300 IN A 73.80.65.49
+sig01.example.nil. 3600 IN SIG NXT 1 3 3600 20000102030405 19961211100908 2143 foo.example.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+srv01.example.nil. 3600 IN SRV 0 0 0 .
+srv02.example.nil. 3600 IN SRV 65535 65535 65535 old-slow-box.example.com.
+t.example.nil. 301 IN A 73.80.65.49
+txt01.example.nil. 3600 IN TXT "foo"
+txt02.example.nil. 3600 IN TXT "foo" "bar"
+txt03.example.nil. 3600 IN TXT "foo"
+txt04.example.nil. 3600 IN TXT "foo" "bar"
+txt05.example.nil. 3600 IN TXT "foo bar"
+txt06.example.nil. 3600 IN TXT "foo bar"
+txt07.example.nil. 3600 IN TXT "foo bar"
+txt08.example.nil. 3600 IN TXT "foo\010bar"
+txt09.example.nil. 3600 IN TXT "foo\010bar"
+txt10.example.nil. 3600 IN TXT "foo bar"
+txt11.example.nil. 3600 IN TXT "\"foo\""
+txt12.example.nil. 3600 IN TXT "\"foo\""
+u.example.nil. 300 IN TXT "txt-not-in-nxt"
+a.u.example.nil. 300 IN A 73.80.65.49
+b.u.example.nil. 300 IN A 73.80.65.49
+wks01.example.nil. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23
+wks02.example.nil. 3600 IN WKS 10.0.0.1 17 0 1 2 53
+wks03.example.nil. 3600 IN WKS 10.0.0.2 6 65535
+x2501.example.nil. 3600 IN X25 "123456789"
+example.nil. 300 IN SOA ns1.example.nil. hostmaster.example.nil. 1 2000 2000 1814400 3600
diff --git a/bin/tests/system/nsupdate/ns1/example1.db b/bin/tests/system/nsupdate/ns1/example1.db
new file mode 100644
index 0000000..e8856fe
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/example1.db
@@ -0,0 +1,152 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2000-2002 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: example1.db,v 1.8 2007/06/19 23:47:04 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example.nil IN SOA ns1.example.nil. hostmaster.example.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example.nil. NS ns1.example.nil.
+ns1.example.nil. A 10.53.0.1
+example.nil. NS ns2.example.nil.
+ns2.example.nil. A 10.53.0.2
+
+$ORIGIN example.nil.
+* MX 10 mail
+a TXT "foo foo foo"
+ PTR foo.net.
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.nil.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.nil.
+ns A 73.80.65.49
+$ORIGIN example.nil.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.nil.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.nil.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/nsupdate/ns1/named.conf b/bin/tests/system/nsupdate/ns1/named.conf
new file mode 100644
index 0000000..0c0e8ff
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns1/named.conf
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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.conf,v 1.17 2007/06/19 23:47:04 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.1 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "example.nil" {
+ type master;
+ file "example.db";
+ check-integrity no;
+ allow-update { any; };
+ allow-transfer { any; };
+};
+
+zone "update.nil" {
+ type master;
+ file "update.db";
+ check-integrity no;
+ allow-update { any; };
+ allow-transfer { any; };
+ also-notify { 10.53.0.2; };
+};
diff --git a/bin/tests/system/nsupdate/ns2/named.conf b/bin/tests/system/nsupdate/ns2/named.conf
new file mode 100644
index 0000000..77e4013
--- /dev/null
+++ b/bin/tests/system/nsupdate/ns2/named.conf
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.14 2007/06/18 23:47:30 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "example.nil" {
+ type slave;
+ masters { 10.53.0.1; };
+ file "example.bk";
+ allow-transfer { any; };
+};
+
+zone "update.nil" {
+ type slave;
+ masters { 10.53.0.1; };
+ file "update.bk";
+ allow-transfer { any; };
+};
+
+
diff --git a/bin/tests/system/nsupdate/setup.sh b/bin/tests/system/nsupdate/setup.sh
new file mode 100644
index 0000000..2d9d51b
--- /dev/null
+++ b/bin/tests/system/nsupdate/setup.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.10 2007/06/19 23:47:04 tbox Exp $
+
+#
+# jnl and database files MUST be removed before we start
+#
+
+rm -f ns1/*.jnl ns1/example.db ns2/*.jnl ns2/example.bk
+
+cp -f ns1/example1.db ns1/example.db
+
+# update_test.pl has its own zone file because it
+# requires a specific NS record set.
+cat <<\EOF >ns1/update.db
+$ORIGIN .
+$TTL 300 ; 5 minutes
+update.nil IN SOA ns1.example.nil. hostmaster.example.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+update.nil. NS ns1.update.nil.
+ns1.update.nil. A 10.53.0.2
+EOF
diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh
new file mode 100644
index 0000000..c6a26bb
--- /dev/null
+++ b/bin/tests/system/nsupdate/tests.sh
@@ -0,0 +1,161 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.25 2007/06/19 23:47:04 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+echo "I:fetching first copy of zone before update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.1 axfr -p 5300 > dig.out.ns1 || status=1
+
+echo "I:fetching second copy of zone before update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.1 axfr -p 5300 > dig.out.ns2 || status=1
+
+echo "I:comparing pre-update copies to known good data"
+$PERL ../digcomp.pl knowngood.ns1.before dig.out.ns1 || status=1
+$PERL ../digcomp.pl knowngood.ns1.before dig.out.ns2 || status=1
+
+echo "I:updating zone"
+# nsupdate will print a ">" prompt to stdout as it gets each input line.
+$NSUPDATE <<END > /dev/null || status=1
+server 10.53.0.1 5300
+update add updated.example.nil. 600 A 10.10.10.1
+update add updated.example.nil. 600 TXT Foo
+update delete t.example.nil.
+
+END
+echo "I:sleeping 15 seconds for server to incorporate changes"
+sleep 15
+
+echo "I:fetching first copy of zone after update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.1 axfr -p 5300 > dig.out.ns1 || status=1
+
+echo "I:fetching second copy of zone after update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.2 axfr -p 5300 > dig.out.ns2 || status=1
+
+echo "I:comparing post-update copies to known good data"
+$PERL ../digcomp.pl knowngood.ns1.after dig.out.ns1 || status=1
+$PERL ../digcomp.pl knowngood.ns1.after dig.out.ns2 || status=1
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ echo "I:running update.pl test"
+ $PERL update_test.pl -s 10.53.0.1 -p 5300 update.nil. || status=1
+else
+ echo "I:The second part of this test requires the Net::DNS library." >&2
+fi
+
+echo "I:fetching first copy of test zone"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.1 axfr -p 5300 > dig.out.ns1 || status=1
+
+echo "I:fetching second copy of test zone"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.2 axfr -p 5300 > dig.out.ns2 || status=1
+
+echo "I:comparing zones"
+$PERL ../digcomp.pl dig.out.ns1 dig.out.ns2 || status=1
+
+echo "I:SIGKILL and restart server ns1"
+cd ns1
+kill -KILL `cat named.pid`
+rm named.pid
+cd ..
+sleep 10
+if
+ $PERL $SYSTEMTESTTOP/start.pl --noclean . ns1
+then
+ echo "I:restarted server ns1"
+else
+ echo "I:could not restart server ns1"
+ exit 1
+fi
+sleep 10
+
+echo "I:fetching ns1 after hard restart"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ @10.53.0.1 axfr -p 5300 > dig.out.ns1.after || status=1
+
+echo "I:comparing zones"
+$PERL ../digcomp.pl dig.out.ns1 dig.out.ns1.after || status=1
+
+echo "I:begin RT #482 regression test"
+
+echo "I:update master"
+$NSUPDATE <<END > /dev/null || status=1
+server 10.53.0.1 5300
+update add updated2.example.nil. 600 A 10.10.10.2
+update add updated2.example.nil. 600 TXT Bar
+update delete c.example.nil.
+send
+END
+
+sleep 5
+
+echo "I:SIGHUP slave"
+kill -HUP `cat ns2/named.pid`
+
+sleep 5
+
+echo "I:update master again"
+$NSUPDATE <<END > /dev/null || status=1
+server 10.53.0.1 5300
+update add updated3.example.nil. 600 A 10.10.10.3
+update add updated3.example.nil. 600 TXT Zap
+update delete d.example.nil.
+send
+END
+
+sleep 5
+
+echo "I:SIGHUP slave again"
+kill -HUP `cat ns2/named.pid`
+
+sleep 5
+
+if grep "out of sync" ns2/named.run
+then
+ status=1
+fi
+
+echo "I:end RT #482 regression test"
+
+echo "I:testing that rndc stop updates the master file"
+$NSUPDATE <<END > /dev/null || status=1
+server 10.53.0.1 5300
+update add updated4.example.nil. 600 A 10.10.10.3
+send
+END
+$PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns1
+# Removing the journal file and restarting the server means
+# that the data served by the new server process are exactly
+# those dumped to the master file by "rndc stop".
+rm -f ns1/*jnl
+$PERL $SYSTEMTESTTOP/start.pl --noclean . ns1
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd updated4.example.nil.\
+ @10.53.0.1 a -p 5300 > dig.out.ns1 || status=1
+$PERL ../digcomp.pl knowngood.ns1.afterstop dig.out.ns1 || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/nsupdate/update_test.pl b/bin/tests/system/nsupdate/update_test.pl
new file mode 100644
index 0000000..ef41b00
--- /dev/null
+++ b/bin/tests/system/nsupdate/update_test.pl
@@ -0,0 +1,426 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2004, 2007 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.
+
+#
+# Dynamic update test suite.
+#
+# Usage:
+#
+# perl update_test.pl [-s server] [-p port] zone
+#
+# The server defaults to 127.0.0.1.
+# The port defaults to 53.
+#
+# The "Special NS rules" tests will only work correctly if the
+# zone has no NS records to begin with, or alternatively has a
+# single NS record pointing at the name "ns1" (relative to
+# the zone name).
+#
+# Installation notes:
+#
+# This program uses the Net::DNS::Resolver module.
+# You can install it by saying
+#
+# perl -MCPAN -e "install Net::DNS"
+#
+# $Id: update_test.pl,v 1.10 2007/06/19 23:47:04 tbox Exp $
+#
+
+use Getopt::Std;
+use Net::DNS;
+use Net::DNS::Update;
+use Net::DNS::Resolver;
+
+$opt_s = "127.0.0.1";
+$opt_p = 53;
+
+getopt('s:p:');
+
+$res = new Net::DNS::Resolver;
+$res->nameservers($opt_s);
+$res->port($opt_p);
+$res->defnames(0); # Do not append default domain.
+
+@ARGV == 1 or die
+ "usage: perl update_test.pl [-s server] [-p port] zone\n";
+
+$zone = shift @ARGV;
+
+my $failures = 0;
+
+sub assert {
+ my ($cond, $explanation) = @_;
+ if (!$cond) {
+ print "I:Test Failed: $explanation ***\n";
+ $failures++
+ }
+}
+
+sub test {
+ my ($expected, @records) = @_;
+
+ my $update = new Net::DNS::Update("$zone");
+
+ foreach $rec (@records) {
+ $update->push(@$rec);
+ }
+
+ $reply = $res->send($update);
+
+ # Did it work?
+ if (defined $reply) {
+ my $rcode = $reply->header->rcode;
+ assert($rcode eq $expected, "expected $expected, got $rcode");
+ } else {
+ print "I:Update failed: ", $res->errorstring, "\n";
+ }
+}
+
+sub section {
+ my ($msg) = @_;
+ print "I:$msg\n";
+}
+
+section("Delete any leftovers from previous tests");
+test("NOERROR", ["update", rr_del("a.$zone")]);
+test("NOERROR", ["update", rr_del("b.$zone")]);
+test("NOERROR", ["update", rr_del("c.$zone")]);
+test("NOERROR", ["update", rr_del("d.$zone")]);
+test("NOERROR", ["update", rr_del("e.$zone")]);
+test("NOERROR", ["update", rr_del("f.$zone")]);
+test("NOERROR", ["update", rr_del("ns.s.$zone")]);
+test("NOERROR", ["update", rr_del("s.$zone")]);
+test("NOERROR", ["update", rr_del("t.$zone")]);
+test("NOERROR", ["update", rr_del("*.$zone")]);
+test("NOERROR", ["update", rr_del("u.$zone")]);
+test("NOERROR", ["update", rr_del("a.u.$zone")]);
+test("NOERROR", ["update", rr_del("b.u.$zone")]);
+
+section("Simple prerequisites in the absence of data");
+# Name is in Use
+test("NXDOMAIN", ["pre", yxdomain("a.$zone")]);
+# RRset exists (value independent)
+test("NXRRSET", ["pre", yxrrset("a.$zone A")]);
+# Name is not in use
+test("NOERROR", ["pre", nxdomain("a.$zone")]);
+# RRset does not exist
+test("NOERROR", ["pre", nxrrset("a.$zone A")]);
+# RRset exists (value dependent)
+test("NXRRSET", ["pre", yxrrset("a.$zone 300 A 73.80.65.49")]);
+
+
+section ("Simple creation of data");
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]);
+
+section ("Simple prerequisites in the presence of data");
+# Name is in use
+test("NOERROR", ["pre", yxdomain("a.$zone")]);
+# RRset exists (value independent)
+test("NOERROR", ["pre", yxrrset("a.$zone A")]);
+# Name is not in use
+test("YXDOMAIN", ["pre", nxdomain("a.$zone")]);
+# RRset does not exist
+test("YXRRSET", ["pre", nxrrset("a.$zone A")]);
+# RRset exists (value dependent)
+test("NOERROR", ["pre", yxrrset("a.$zone 300 A 73.80.65.49")]);
+
+#
+# Merging of RRsets
+#
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]);
+
+section("Detailed tests of \"RRset exists (value dependent)\" prerequisites");
+test("NOERROR", ["pre",
+ yxrrset("a.$zone 300 A 73.80.65.49"),
+ yxrrset("a.$zone 300 A 73.80.65.50")]);
+test("NOERROR", ["pre",
+ yxrrset("a.$zone 300 A 73.80.65.50"),
+ yxrrset("a.$zone 300 A 73.80.65.49")]);
+test("NXRRSET", ["pre", yxrrset("a.$zone 300 A 73.80.65.49")]);
+test("NXRRSET", ["pre", yxrrset("a.$zone 300 A 73.80.65.50")]);
+test("NXRRSET", ["pre",
+ yxrrset("a.$zone 300 A 73.80.65.49"),
+ yxrrset("a.$zone 300 A 73.80.65.50"),
+ yxrrset("a.$zone 300 A 73.80.65.51")]);
+
+
+section("Torture test of \"RRset exists (value dependent)\" prerequisites.");
+
+test("NOERROR", ["update",
+ rr_add("e.$zone 300 A 73.80.65.49"),
+ rr_add("e.$zone 300 TXT 'one'"),
+ rr_add("e.$zone 300 A 73.80.65.50")]);
+test("NOERROR", ["update",
+ rr_add("e.$zone 300 A 73.80.65.52"),
+ rr_add("f.$zone 300 A 73.80.65.52"),
+ rr_add("e.$zone 300 A 73.80.65.51")]);
+test("NOERROR", ["update",
+ rr_add("e.$zone 300 TXT 'three'"),
+ rr_add("e.$zone 300 TXT 'two'")]);
+test("NOERROR", ["update",
+ rr_add("e.$zone 300 MX 10 mail.$zone")]);
+
+test("NOERROR", ["pre",
+ yxrrset("e.$zone 300 A 73.80.65.52"),
+ yxrrset("e.$zone 300 TXT 'two'"),
+ yxrrset("e.$zone 300 A 73.80.65.51"),
+ yxrrset("e.$zone 300 TXT 'three'"),
+ yxrrset("e.$zone 300 A 73.80.65.50"),
+ yxrrset("f.$zone 300 A 73.80.65.52"),
+ yxrrset("e.$zone 300 A 73.80.65.49"),
+ yxrrset("e.$zone 300 TXT 'one'")]);
+
+
+section("Subtraction of RRsets");
+test("NOERROR", ["update", rr_del("a.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["pre",
+ yxrrset("a.$zone 300 A 73.80.65.50")]);
+
+test("NOERROR", ["update", rr_del("a.$zone 300 A 73.80.65.50")]);
+test("NOERROR", ["pre", nxrrset("a.$zone 300 A")]);
+test("NOERROR", ["pre", nxdomain("a.$zone")]);
+
+section("Other forms of deletion");
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]);
+test("NOERROR", ["update", rr_add("a.$zone 300 MX 10 mail.$zone")]);
+test("NOERROR", ["update", rr_del("a.$zone 300 A")]);
+test("NOERROR", ["pre", nxrrset("a.$zone 300 A")]);
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update", rr_add("a.$zone 300 A 73.80.65.50")]);
+test("NOERROR", ["update", rr_del("a.$zone")]);
+test("NOERROR", ["pre", nxdomain("a.$zone")]);
+
+section("Case insensitivity");
+test("NOERROR", ["update", rr_add("a.$zone 300 PTR foo.net.")]);
+test("NOERROR", ["pre", yxrrset("A.$zone 300 PTR fOo.NeT.")]);
+
+section("Special CNAME rules");
+test("NOERROR", ["update", rr_add("b.$zone 300 CNAME foo.net.")]);
+test("NOERROR", ["update", rr_add("b.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["pre", yxrrset("b.$zone 300 CNAME foo.net.")]);
+test("NOERROR", ["pre", nxrrset("b.$zone A")]);
+
+test("NOERROR", ["update", rr_add("c.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update", rr_add("c.$zone 300 CNAME foo.net.")]);
+test("NOERROR", ["pre", yxrrset("c.$zone A")]);
+test("NOERROR", ["pre", nxrrset("c.$zone CNAME")]);
+
+# XXX should test with SIG, KEY, NXT, too.
+
+#
+# Currently commented out because Net::DNS does not properly
+# support WKS records.
+#
+#section("Special WKS rules");
+#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 TCP telnet ftp")]);
+#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 UDP telnet ftp")]);
+#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.50 TCP telnet ftp")]);
+#test("NOERROR", ["update", rr_add("c.$zone 300 WKS 73.80.65.49 TCP smtp")]);
+#test("NOERROR", ["pre",
+# yxrrset("c.$zone 300 WKS 73.80.65.49 TCP smtp"),
+# yxrrset("c.$zone 300 WKS 73.80.65.49 UDP telnet ftp"),
+# yxrrset("c.$zone 300 WKS 73.80.65.50 TCP telnet ftp")]);
+
+
+section("Special NS rules");
+
+# Deleting the last NS record using "Delete an RR from an RRset"
+# should fail at the zone apex and work elsewhere. The pseudocode
+# in RFC2136 says it should fail everywhere, but this is in conflict
+# with the actual text.
+
+# Apex
+test("NOERROR", ["update",
+ rr_add("$zone 300 NS ns1.$zone"),
+ rr_add("$zone 300 NS ns2.$zone")]);
+test("NOERROR", ["update", rr_del("$zone 300 NS ns1.$zone")]);
+test("NOERROR", ["update", rr_del("$zone 300 NS ns2.$zone")]);
+test("NOERROR", ["pre",
+ yxrrset("$zone 300 NS ns2.$zone")]);
+
+# Non-apex
+test("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]);
+test("NOERROR", ["update", rr_del("n.$zone 300 NS ns1.$zone")]);
+test("NOERROR", ["pre", nxrrset("n.$zone 300 NS")]);
+
+# Other ways of deleting NS records should also fail at the apex
+# and work elsewhere.
+
+# Non-apex
+test("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]);
+test("NOERROR", ["update", rr_del("n.$zone 300 NS")]);
+test("NOERROR", ["pre", nxrrset("n.$zone 300 NS")]);
+
+test("NOERROR", ["update", rr_add("n.$zone 300 NS ns1.$zone")]);
+test("NOERROR", ["pre", yxrrset("n.$zone 300 NS")]);
+test("NOERROR", ["update", rr_del("n.$zone")]);
+test("NOERROR", ["pre", nxrrset("n.$zone 300 NS")]);
+
+# Apex
+test("NOERROR", ["update", rr_del("$zone NS")]);
+test("NOERROR", ["pre",
+ yxrrset("$zone 300 NS ns2.$zone")]);
+
+test("NOERROR", ["update", rr_del("$zone")]);
+test("NOERROR", ["pre",
+ yxrrset("$zone 300 NS ns2.$zone")]);
+
+# They should not touch the SOA, either.
+
+test("NOERROR", ["update", rr_del("$zone SOA")]);
+test("NOERROR", ["pre", yxrrset("$zone SOA")]);
+
+
+section("Idempotency");
+
+test("NOERROR", ["update", rr_add("d.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["pre", yxrrset("d.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update",
+ rr_add("d.$zone 300 A 73.80.65.49"),
+ rr_del("d.$zone A")]);
+test("NOERROR", ["pre", nxrrset("d.$zone 300 A 73.80.65.49")]);
+
+test("NOERROR", ["update", rr_del("d.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["pre", nxrrset("d.$zone 300 A")]);
+test("NOERROR", ["update",
+ rr_del("d.$zone 300 A"),
+ rr_add("d.$zone 300 A 73.80.65.49")]);
+
+test("NOERROR", ["pre", yxrrset("d.$zone 300 A")]);
+
+section("Out-of-zone prerequisites and updates");
+test("NOTZONE", ["pre", yxrrset("a.somewhere.else. 300 A 73.80.65.49")]);
+test("NOTZONE", ["update", rr_add("a.somewhere.else. 300 A 73.80.65.49")]);
+
+
+section("Glue");
+test("NOERROR", ["update", rr_add("s.$zone 300 NS ns.s.$zone")]);
+test("NOERROR", ["update", rr_add("ns.s.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["pre", yxrrset("ns.s.$zone 300 A 73.80.65.49")]);
+
+section("Wildcards");
+test("NOERROR", ["update", rr_add("*.$zone 300 MX 10 mail.$zone")]);
+test("NOERROR", ["pre", yxrrset("*.$zone 300 MX 10 mail.$zone")]);
+test("NXRRSET", ["pre", yxrrset("w.$zone 300 MX 10 mail.$zone")]);
+test("NOERROR", ["pre", nxrrset("w.$zone MX")]);
+test("NOERROR", ["pre", nxdomain("w.$zone")]);
+
+
+section("SOA serial handling");
+
+my $soatimers = "20 20 1814400 3600";
+
+# Get the current SOA serial number.
+my $query = $res->query($zone, "SOA");
+my ($old_soa) = $query->answer;
+
+my $old_serial = $old_soa->serial;
+
+# Increment it by 10.
+my $new_serial = $old_serial + 10;
+if ($new_serial > 0xFFFFFFFF) {
+ $new_serial -= 0x80000000;
+ $new_serial -= 0x80000000;
+}
+
+# Replace the SOA with a new one.
+test("NOERROR", ["update", rr_add("$zone 300 SOA mname1. . $new_serial $soatimers")]);
+
+# Check that the SOA really got replaced.
+($db_soa) = $res->query($zone, "SOA")->answer;
+assert($db_soa->mname eq "mname1");
+
+# Check that attempts to decrement the serial number are ignored.
+$new_serial = $old_serial - 10;
+if ($new_serial < 0) {
+ $new_serial += 0x80000000;
+ $new_serial += 0x80000000;
+}
+test("NOERROR", ["update", rr_add("$zone 300 SOA mname2. . $new_serial $soatimers")]);
+assert($db_soa->mname eq "mname1");
+
+# Check that attempts to leave the serial number unchanged are ignored.
+($old_soa) = $res->query($zone, "SOA")->answer;
+$old_serial = $old_soa->serial;
+test("NOERROR", ["update", rr_add("$zone 300 SOA mname3. . $old_serial " .
+ $soatimers)]);
+($db_soa) = $res->query($zone, "SOA")->answer;
+assert($db_soa->mname eq "mname1");
+
+#
+# Currently commented out because Net::DNS does not properly
+# support multiple strings in TXT records.
+#
+#section("Big data");
+#test("NOERROR", ["update", rr_add("a.$zone 300 TXT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")]);
+#test("NOERROR", ["update", rr_del("a.$zone 300 TXT aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc")]);
+test("NOERROR", ["update", rr_add("a.$zone 300 TXT " . ("foo " x 3))]);
+
+section("Updating TTLs only");
+
+test("NOERROR", ["update", rr_add("t.$zone 300 A 73.80.65.49")]);
+($a) = $res->query("t.$zone", "A")->answer;
+$ttl = $a->ttl;
+assert($ttl == 300, "incorrect TTL value $ttl != 300");
+test("NOERROR", ["update",
+ rr_del("t.$zone 300 A 73.80.65.49"),
+ rr_add("t.$zone 301 A 73.80.65.49")]);
+($a) = $res->query("t.$zone", "A")->answer;
+$ttl = $a->ttl;
+assert($ttl == 301, "incorrect TTL value $ttl != 301");
+
+# Add an RR that is identical to an existing one except for the TTL.
+# RFC2136 is not clear about what this should do; it says "duplicate RRs
+# will be silently ignored" but is an RR differing only in TTL
+# to be considered a duplicate or not? The test assumes that it
+# should not be considered a duplicate.
+test("NOERROR", ["update", rr_add("t.$zone 302 A 73.80.65.50")]);
+($a) = $res->query("t.$zone", "A")->answer;
+$ttl = $a->ttl;
+assert($ttl == 302, "incorrect TTL value $ttl != 302");
+
+section("TTL normalization");
+
+# The desired behaviour is that the old RRs get their TTL
+# changed to match the new one. RFC2136 does not explicitly
+# specify this, but I think it makes more sense than the
+# alternatives.
+
+test("NOERROR", ["update", rr_add("t.$zone 303 A 73.80.65.51")]);
+(@answers) = $res->query("t.$zone", "A")->answer;
+$nanswers = scalar @answers;
+assert($nanswers == 3, "wrong number of answers $nanswers != 3");
+foreach $a (@answers) {
+ $ttl = $a->ttl;
+ assert($ttl == 303, "incorrect TTL value $ttl != 303");
+}
+
+section("Obscuring existing data by zone cut");
+test("NOERROR", ["update", rr_add("a.u.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update", rr_add("b.u.$zone 300 A 73.80.65.49")]);
+test("NOERROR", ["update", rr_add("u.$zone 300 TXT txt-not-in-nxt")]);
+test("NOERROR", ["update", rr_add("u.$zone 300 NS ns.u.$zone")]);
+
+test("NOERROR", ["update", rr_del("u.$zone 300 NS ns.u.$zone")]);
+
+if ($failures) {
+ print "I:$failures tests failed.\n";
+} else {
+ print "I:All tests successful.\n";
+}
+exit $failures;
diff --git a/bin/tests/system/resolver/ans2/ans.pl b/bin/tests/system/resolver/ans2/ans.pl
new file mode 100644
index 0000000..b41f198
--- /dev/null
+++ b/bin/tests/system/resolver/ans2/ans.pl
@@ -0,0 +1,75 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2004, 2007 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: ans.pl,v 1.10 2007/09/24 04:13:25 marka Exp $
+
+#
+# Ad hoc name server
+#
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.2",
+ LocalPort => 5300, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+for (;;) {
+ $sock->recv($buf, 512);
+
+ print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
+
+ my ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+
+ if ($qname eq "cname1.example.com") {
+ # Data for the "cname + other data / 1" test
+ $packet->push("answer", new Net::DNS::RR("cname1.example.com 300 CNAME cname1.example.com"));
+ $packet->push("answer", new Net::DNS::RR("cname1.example.com 300 A 1.2.3.4"));
+ } elsif ($qname eq "cname2.example.com") {
+ # Data for the "cname + other data / 2" test: same RRs in opposite order
+ $packet->push("answer", new Net::DNS::RR("cname2.example.com 300 A 1.2.3.4"));
+ $packet->push("answer", new Net::DNS::RR("cname2.example.com 300 CNAME cname2.example.com"));
+ } else {
+ # Data for the "bogus referrals" test
+ $packet->push("authority", new Net::DNS::RR("below.www.example.com 300 NS ns.below.www.example.com"));
+ $packet->push("additional", new Net::DNS::RR("ns.below.www.example.com 300 A 10.53.0.3"));
+ }
+
+ $sock->send($packet->data);
+
+ print "RESPONSE:\n";
+ $packet->print;
+ print "\n";
+}
diff --git a/bin/tests/system/resolver/ans3/ans.pl b/bin/tests/system/resolver/ans3/ans.pl
new file mode 100644
index 0000000..3053b25
--- /dev/null
+++ b/bin/tests/system/resolver/ans3/ans.pl
@@ -0,0 +1,60 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2004, 2007 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: ans.pl,v 1.9 2007/09/24 04:13:25 marka Exp $
+
+#
+# Ad hoc name server
+#
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.3",
+ LocalPort => 5300, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+for (;;) {
+ $sock->recv($buf, 512);
+
+ print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
+
+ my ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+
+ $packet->push("answer", new Net::DNS::RR("www.example.com 300 A 1.2.3.4"));
+
+ $sock->send($packet->data);
+
+ print "RESPONSE:\n";
+ $packet->print;
+ print "\n";
+}
diff --git a/bin/tests/system/resolver/clean.sh b/bin/tests/system/resolver/clean.sh
new file mode 100644
index 0000000..c79da92
--- /dev/null
+++ b/bin/tests/system/resolver/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) 2008 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: clean.sh,v 1.1 2008/07/17 01:15:34 marka Exp $
+
+#
+# Clean up after resolver tests.
+#
+rm -f */named.memstats
diff --git a/bin/tests/system/resolver/ns1/named.conf b/bin/tests/system/resolver/ns1/named.conf
new file mode 100644
index 0000000..4b0c80a
--- /dev/null
+++ b/bin/tests/system/resolver/ns1/named.conf
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.13 2007/06/18 23:47:30 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+};
+
+zone "." {
+ type hint;
+ file "root.hint";
+};
+
diff --git a/bin/tests/system/resolver/ns1/root.hint b/bin/tests/system/resolver/ns1/root.hint
new file mode 100644
index 0000000..2fd180e
--- /dev/null
+++ b/bin/tests/system/resolver/ns1/root.hint
@@ -0,0 +1,20 @@
+; Copyright (C) 2004, 2007 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: root.hint,v 1.7 2007/06/19 23:47:05 tbox Exp $
+
+$TTL 999999
+. IN NS a.root-servers.nil.
+a.root-servers.nil. IN A 10.53.0.2
diff --git a/bin/tests/system/resolver/prereq.sh b/bin/tests/system/resolver/prereq.sh
new file mode 100644
index 0000000..c0dbb7b
--- /dev/null
+++ b/bin/tests/system/resolver/prereq.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: prereq.sh,v 1.7 2007/06/19 23:47:05 tbox Exp $
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ :
+else
+ echo "I:This test requires the Net::DNS library." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/resolver/tests.sh b/bin/tests/system/resolver/tests.sh
new file mode 100644
index 0000000..585455c
--- /dev/null
+++ b/bin/tests/system/resolver/tests.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.9 2007/06/19 23:47:05 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+echo "I:checking handling of bogus referrals"
+# If the server has the "INSIST(!external)" bug, this query will kill it.
+$DIG +tcp www.example.com. a @10.53.0.1 -p 5300 >/dev/null || status=1
+
+echo "I:check handling of cname + other data / 1"
+$DIG +tcp cname1.example.com. a @10.53.0.1 -p 5300 >/dev/null || status=1
+
+echo "I:check handling of cname + other data / 2"
+$DIG +tcp cname2.example.com. a @10.53.0.1 -p 5300 >/dev/null || status=1
+
+echo "I:check that server is still running"
+$DIG +tcp www.example.com. a @10.53.0.1 -p 5300 >/dev/null || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/rrsetorder/clean.sh b/bin/tests/system/rrsetorder/clean.sh
new file mode 100644
index 0000000..d5b245c
--- /dev/null
+++ b/bin/tests/system/rrsetorder/clean.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) 2006-2008 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: clean.sh,v 1.8 2008/04/24 23:46:59 tbox Exp $
+
+rm -f dig.out.cyclic dig.out.fixed dig.out.random
+rm -f dig.out.0 dig.out.1 dig.out.2 dig.out.3
+rm -f ns2/root.bk
+rm -f ns?/named.run ns?/named.core
+rm -f */named.memstats
diff --git a/bin/tests/system/rrsetorder/dig.out.fixed.good b/bin/tests/system/rrsetorder/dig.out.fixed.good
new file mode 100644
index 0000000..eaf9c63
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.fixed.good
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.3
+1.2.3.1
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good1 b/bin/tests/system/rrsetorder/dig.out.random.good1
new file mode 100644
index 0000000..c272c75
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good1
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.2
+1.2.3.3
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good10 b/bin/tests/system/rrsetorder/dig.out.random.good10
new file mode 100644
index 0000000..6a39e3f
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good10
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.3
+1.2.3.4
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good11 b/bin/tests/system/rrsetorder/dig.out.random.good11
new file mode 100644
index 0000000..efbc792
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good11
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.4
+1.2.3.1
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good12 b/bin/tests/system/rrsetorder/dig.out.random.good12
new file mode 100644
index 0000000..c859a2e
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good12
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.4
+1.2.3.3
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good13 b/bin/tests/system/rrsetorder/dig.out.random.good13
new file mode 100644
index 0000000..49bf54b
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good13
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.1
+1.2.3.2
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good14 b/bin/tests/system/rrsetorder/dig.out.random.good14
new file mode 100644
index 0000000..974aa89
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good14
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.1
+1.2.3.4
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good15 b/bin/tests/system/rrsetorder/dig.out.random.good15
new file mode 100644
index 0000000..e8deb67
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good15
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.2
+1.2.3.1
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good16 b/bin/tests/system/rrsetorder/dig.out.random.good16
new file mode 100644
index 0000000..f467087
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good16
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.2
+1.2.3.4
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good17 b/bin/tests/system/rrsetorder/dig.out.random.good17
new file mode 100644
index 0000000..6082a25
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good17
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.4
+1.2.3.1
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good18 b/bin/tests/system/rrsetorder/dig.out.random.good18
new file mode 100644
index 0000000..07eefa0
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good18
@@ -0,0 +1,4 @@
+1.2.3.3
+1.2.3.4
+1.2.3.2
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good19 b/bin/tests/system/rrsetorder/dig.out.random.good19
new file mode 100644
index 0000000..a5530c6
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good19
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.1
+1.2.3.2
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good2 b/bin/tests/system/rrsetorder/dig.out.random.good2
new file mode 100644
index 0000000..00da93a
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good2
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.2
+1.2.3.4
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good20 b/bin/tests/system/rrsetorder/dig.out.random.good20
new file mode 100644
index 0000000..6dcf6da
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good20
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.1
+1.2.3.3
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good21 b/bin/tests/system/rrsetorder/dig.out.random.good21
new file mode 100644
index 0000000..9dcc63f
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good21
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.2
+1.2.3.1
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good22 b/bin/tests/system/rrsetorder/dig.out.random.good22
new file mode 100644
index 0000000..4c51aa6
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good22
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.2
+1.2.3.3
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good23 b/bin/tests/system/rrsetorder/dig.out.random.good23
new file mode 100644
index 0000000..eaf9c63
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good23
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.3
+1.2.3.1
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good24 b/bin/tests/system/rrsetorder/dig.out.random.good24
new file mode 100644
index 0000000..c25c756
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good24
@@ -0,0 +1,4 @@
+1.2.3.4
+1.2.3.3
+1.2.3.2
+1.2.3.1
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good3 b/bin/tests/system/rrsetorder/dig.out.random.good3
new file mode 100644
index 0000000..4d50059
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good3
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.3
+1.2.3.2
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good4 b/bin/tests/system/rrsetorder/dig.out.random.good4
new file mode 100644
index 0000000..0b34afa
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good4
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.3
+1.2.3.4
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good5 b/bin/tests/system/rrsetorder/dig.out.random.good5
new file mode 100644
index 0000000..efe0e25
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good5
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.4
+1.2.3.2
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good6 b/bin/tests/system/rrsetorder/dig.out.random.good6
new file mode 100644
index 0000000..d2ca6fc
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good6
@@ -0,0 +1,4 @@
+1.2.3.1
+1.2.3.4
+1.2.3.3
+1.2.3.2
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good7 b/bin/tests/system/rrsetorder/dig.out.random.good7
new file mode 100644
index 0000000..0d8312a
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good7
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.1
+1.2.3.3
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good8 b/bin/tests/system/rrsetorder/dig.out.random.good8
new file mode 100644
index 0000000..3b27693
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good8
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.1
+1.2.3.4
+1.2.3.3
diff --git a/bin/tests/system/rrsetorder/dig.out.random.good9 b/bin/tests/system/rrsetorder/dig.out.random.good9
new file mode 100644
index 0000000..61192af
--- /dev/null
+++ b/bin/tests/system/rrsetorder/dig.out.random.good9
@@ -0,0 +1,4 @@
+1.2.3.2
+1.2.3.3
+1.2.3.1
+1.2.3.4
diff --git a/bin/tests/system/rrsetorder/ns1/named.conf b/bin/tests/system/rrsetorder/ns1/named.conf
new file mode 100644
index 0000000..f228a07
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns1/named.conf
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2006, 2007 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.conf,v 1.4 2007/06/19 23:47:05 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ rrset-order {
+ name "fixed.example" order fixed;
+ name "random.example" order random;
+ name "cyclic.example" order cyclic;
+ type NS order random;
+ order cyclic;
+ };
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/rrsetorder/ns1/root.db b/bin/tests/system/rrsetorder/ns1/root.db
new file mode 100644
index 0000000..dd2f08f
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns1/root.db
@@ -0,0 +1,40 @@
+; Copyright (C) 2006, 2007 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: root.db,v 1.4 2007/06/19 23:47:05 tbox Exp $
+
+$TTL 3600
+. SOA hostmaster.isc.org. a.root-servers.nil. (
+ 2000042100
+ 600
+ 600
+ 1200
+ 600 )
+. NS a.root-servers.nil.
+a.root-servers.nil A 10.53.0.1
+;
+fixed.example. A 1.2.3.4
+fixed.example. A 1.2.3.3
+fixed.example. A 1.2.3.1
+fixed.example. A 1.2.3.2
+;
+random.example. A 1.2.3.1
+random.example. A 1.2.3.2
+random.example. A 1.2.3.3
+random.example. A 1.2.3.4
+;
+cyclic.example. A 1.2.3.4
+cyclic.example. A 1.2.3.3
+cyclic.example. A 1.2.3.2
+cyclic.example. A 1.2.3.1
diff --git a/bin/tests/system/rrsetorder/ns2/named.conf b/bin/tests/system/rrsetorder/ns2/named.conf
new file mode 100644
index 0000000..0a1e9b9
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns2/named.conf
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006, 2007 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.conf,v 1.4 2007/06/19 23:47:05 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ // flush-zones-on-shutdown yes;
+ rrset-order {
+ name "fixed.example" order fixed;
+ name "random.example" order random;
+ name "cyclic.example" order cyclic;
+ type NS order random;
+ order cyclic;
+ };
+};
+
+zone "." {
+ type slave;
+ masters { 10.53.0.1; };
+ file "root.bk";
+};
diff --git a/bin/tests/system/rrsetorder/ns3/named.conf b/bin/tests/system/rrsetorder/ns3/named.conf
new file mode 100644
index 0000000..fa8bfc9
--- /dev/null
+++ b/bin/tests/system/rrsetorder/ns3/named.conf
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2006, 2007 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.conf,v 1.5 2007/06/18 23:47:30 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+ rrset-order {
+ name "fixed.example" order fixed;
+ name "random.example" order random;
+ name "cyclic.example" order cyclic;
+ type NS order random;
+ order cyclic;
+ };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
diff --git a/bin/tests/system/rrsetorder/tests.sh b/bin/tests/system/rrsetorder/tests.sh
new file mode 100644
index 0000000..a05e34f
--- /dev/null
+++ b/bin/tests/system/rrsetorder/tests.sh
@@ -0,0 +1,332 @@
+#!/bin/sh
+#
+# Copyright (C) 2006-2008 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: tests.sh,v 1.8 2008/10/09 21:27:52 each Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+if grep "^#define DNS_RDATASET_FIXED" $TOP/config.h > /dev/null 2>&1 ; then
+ test_fixed=true
+else
+ echo "I: Order 'fixed' disabled at compile time"
+ test_fixed=false
+fi
+
+#
+#
+#
+if $test_fixed; then
+ echo "I: Checking order fixed (master)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ $DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.1 fixed.example > dig.out.fixed || ret=1
+ cmp -s dig.out.fixed dig.out.fixed.good || ret=1
+ done
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
+fi
+
+#
+#
+#
+echo "I: Checking order cyclic (master)"
+ret=0
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=`expr $i % 4`
+ $DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.1 cyclic.example > dig.out.cyclic || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic dig.out.$j
+ else
+ cmp -s dig.out.cyclic dig.out.$j && matches=`expr $matches + 1`
+ fi
+done
+cmp -s dig.out.0 dig.out.1 && ret=1
+cmp -s dig.out.0 dig.out.2 && ret=1
+cmp -s dig.out.0 dig.out.3 && ret=1
+cmp -s dig.out.1 dig.out.2 && ret=1
+cmp -s dig.out.1 dig.out.3 && ret=1
+cmp -s dig.out.2 dig.out.3 && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I: Checking order random (master)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+do
+ eval match$i=0
+done
+for i in 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 0 1 2 3 4 5 6 7 9
+do
+$DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.1 random.example > dig.out.random || ret=1
+ match=0
+ for j in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ eval "cmp -s dig.out.random dig.out.random.good$j && match$j=1 match=1"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+do
+ eval "match=\`expr \$match + \$match$i\`"
+done
+echo "I: Random selection return $match of 24 possible orders in 36 samples"
+if [ $match -lt 8 ]; then echo ret=1; fi
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+#
+#
+#
+if $test_fixed; then
+ echo "I: Checking order fixed (slave)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ $DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.2 fixed.example > dig.out.fixed || ret=1
+ cmp -s dig.out.fixed dig.out.fixed.good || ret=1
+ done
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
+fi
+
+#
+#
+#
+echo "I: Checking order cyclic (slave)"
+ret=0
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=`expr $i % 4`
+ $DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.2 cyclic.example > dig.out.cyclic || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic dig.out.$j
+ else
+ cmp -s dig.out.cyclic dig.out.$j && matches=`expr $matches + 1`
+ fi
+done
+cmp -s dig.out.0 dig.out.1 && ret=1
+cmp -s dig.out.0 dig.out.2 && ret=1
+cmp -s dig.out.0 dig.out.3 && ret=1
+cmp -s dig.out.1 dig.out.2 && ret=1
+cmp -s dig.out.1 dig.out.3 && ret=1
+cmp -s dig.out.2 dig.out.3 && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I: Checking order random (slave)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+do
+ eval match$i=0
+done
+for i in 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 0 1 2 3 4 5 6 7 9
+do
+$DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.2 random.example > dig.out.random || ret=1
+ match=0
+ for j in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ eval "cmp -s dig.out.random dig.out.random.good$j && match$j=1 match=1"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+do
+eval "match=\`expr \$match + \$match$i\`"
+done
+echo "I: Random selection return $match of 24 possible orders in 36 samples"
+if [ $match -lt 8 ]; then echo ret=1; fi
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I: Shutting down slave"
+
+(cd ..; sh stop.sh rrsetorder ns2 )
+
+echo "I: Checking for slave's on disk copy of zone"
+
+if [ ! -f ns2/root.bk ]
+then
+ echo "I:failed";
+ status=`expr $status + 1`
+fi
+
+echo "I: Re-starting slave"
+
+(cd ..; sh start.sh --noclean rrsetorder ns2 )
+
+#
+#
+#
+if $test_fixed; then
+ echo "I: Checking order fixed (slave loaded from disk)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ $DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.2 fixed.example > dig.out.fixed || ret=1
+ cmp -s dig.out.fixed dig.out.fixed.good || ret=1
+ done
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
+fi
+
+#
+#
+#
+echo "I: Checking order cyclic (slave loaded from disk)"
+ret=0
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=`expr $i % 4`
+ $DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.2 cyclic.example > dig.out.cyclic || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic dig.out.$j
+ else
+ cmp -s dig.out.cyclic dig.out.$j && matches=`expr $matches + 1`
+ fi
+done
+cmp -s dig.out.0 dig.out.1 && ret=1
+cmp -s dig.out.0 dig.out.2 && ret=1
+cmp -s dig.out.0 dig.out.3 && ret=1
+cmp -s dig.out.1 dig.out.2 && ret=1
+cmp -s dig.out.1 dig.out.3 && ret=1
+cmp -s dig.out.2 dig.out.3 && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I: Checking order random (slave loaded from disk)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+do
+ eval match$i=0
+done
+for i in 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 0 1 2 3 4 5 6 7 9
+do
+$DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.2 random.example > dig.out.random || ret=1
+ match=0
+ for j in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ eval "cmp -s dig.out.random dig.out.random.good$j && match$j=1 match=1"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+do
+eval "match=\`expr \$match + \$match$i\`"
+done
+echo "I: Random selection return $match of 24 possible orders in 36 samples"
+if [ $match -lt 8 ]; then echo ret=1; fi
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+#
+#
+#
+if $test_fixed; then
+ echo "I: Checking order fixed (cache)"
+ ret=0
+ for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+ do
+ $DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.3 fixed.example > dig.out.fixed || ret=1
+ cmp -s dig.out.fixed dig.out.fixed.good || ret=1
+ done
+ if [ $ret != 0 ]; then echo "I:failed"; fi
+ status=`expr $status + $ret`
+fi
+
+#
+#
+#
+echo "I: Checking order cyclic (cache)"
+ret=0
+matches=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+do
+ j=`expr $i % 4`
+ $DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.3 cyclic.example > dig.out.cyclic || ret=1
+ if [ $i -le 4 ]; then
+ cp dig.out.cyclic dig.out.$j
+ else
+ cmp -s dig.out.cyclic dig.out.$j && matches=`expr $matches + 1`
+ fi
+done
+cmp -s dig.out.0 dig.out.1 && ret=1
+cmp -s dig.out.0 dig.out.2 && ret=1
+cmp -s dig.out.0 dig.out.3 && ret=1
+cmp -s dig.out.1 dig.out.2 && ret=1
+cmp -s dig.out.1 dig.out.3 && ret=1
+cmp -s dig.out.2 dig.out.3 && ret=1
+if [ $matches -ne 16 ]; then ret=1; fi
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I: Checking order random (cache)"
+ret=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+do
+ eval match$i=0
+done
+for i in 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 0 1 2 3 4 5 6 7 9
+do
+$DIG +nosea +nocomm +nocmd +noquest +noadd +noauth +nocomm +nostat +short \
+ -p 5300 @10.53.0.3 random.example > dig.out.random || ret=1
+ match=0
+ for j in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ do
+ eval "cmp -s dig.out.random dig.out.random.good$j && match$j=1 match=1"
+ if [ $match -eq 1 ]; then break; fi
+ done
+ if [ $match -eq 0 ]; then ret=1; fi
+done
+match=0
+for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+do
+eval "match=\`expr \$match + \$match$i\`"
+done
+echo "I: Random selection return $match of 24 possible orders in 36 samples"
+if [ $match -lt 8 ]; then echo ret=1; fi
+if [ $ret != 0 ]; then echo "I:failed"; fi
+
+status=`expr $status + $ret`
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/run.sh b/bin/tests/system/run.sh
new file mode 100644
index 0000000..8d4a6ad
--- /dev/null
+++ b/bin/tests/system/run.sh
@@ -0,0 +1,115 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: run.sh,v 1.42 2007/06/19 23:47:00 tbox Exp $
+
+#
+# Run a system test.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+stopservers=true
+
+case $1 in
+ --keep) stopservers=false; shift ;;
+esac
+
+test $# -gt 0 || { echo "usage: $0 [--keep] test-directory" >&2; exit 1; }
+
+test=$1
+shift
+
+test -d $test || { echo "$0: $test: no such test" >&2; exit 1; }
+
+echo "S:$test:`date`" >&2
+echo "T:$test:1:A" >&2
+echo "A:System test $test" >&2
+
+if [ x$PERL = x ]
+then
+ echo "I:Perl not available. Skipping test." >&2
+ echo "R:UNTESTED" >&2
+ echo "E:$test:`date`" >&2
+ exit 0;
+fi
+
+$PERL testsock.pl || {
+ echo "I:Network interface aliases not set up. Skipping test." >&2;
+ echo "R:UNTESTED" >&2;
+ echo "E:$test:`date`" >&2;
+ exit 0;
+}
+
+
+# Check for test-specific prerequisites.
+if
+ test ! -f $test/prereq.sh ||
+ ( cd $test && sh prereq.sh "$@" )
+then
+ : prereqs ok
+else
+ echo "I:Prerequisites for $test missing, skipping test." >&2
+ echo "R:UNTESTED" >&2
+ echo "E:$test:`date`" >&2
+ exit 0
+fi
+
+# Set up any dynamically generated test data
+if test -f $test/setup.sh
+then
+ ( cd $test && sh setup.sh "$@" )
+fi
+
+# Start name servers running
+$PERL start.pl $test || exit 1
+
+# Run the tests
+( cd $test ; sh tests.sh )
+
+status=$?
+
+if $stopservers
+then
+ :
+else
+ exit $status
+fi
+
+# Shutdown
+$PERL stop.pl $test
+
+status=`expr $status + $?`
+
+if [ $status != 0 ]; then
+ echo "R:FAIL"
+ # Don't clean up - we need the evidence.
+ find . -name core -exec chmod 0644 '{}' \;
+else
+ echo "R:PASS"
+
+ # Clean up.
+ if test -f $test/clean.sh
+ then
+ ( cd $test && sh clean.sh "$@" )
+ fi
+fi
+
+echo "E:$test:`date`"
+
+exit $status
diff --git a/bin/tests/system/runall.sh b/bin/tests/system/runall.sh
new file mode 100644
index 0000000..23ad53f
--- /dev/null
+++ b/bin/tests/system/runall.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: runall.sh,v 1.8 2007/06/19 23:47:00 tbox Exp $
+
+#
+# Run all the system tests.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+for d in $SUBDIRS
+do
+ sh run.sh $d || status=1
+done
+
+$PERL testsock.pl || {
+ cat <<EOF >&2
+I:
+I:NOTE: Many of the tests were skipped because they require that
+I: the IP addresses 10.53.0.1 through 10.53.0.5 are configured
+I: as alias addresses on the loopback interface. Please run
+I: "bin/tests/system/ifconfig.sh up" as root to configure them
+I: and rerun the tests.
+EOF
+ exit 0;
+}
+
+exit $status
diff --git a/bin/tests/system/send.pl b/bin/tests/system/send.pl
new file mode 100644
index 0000000..bda9b6d
--- /dev/null
+++ b/bin/tests/system/send.pl
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+#
+# 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: send.pl,v 1.5 2007/06/19 23:47:00 tbox Exp $
+
+#
+# Send a file to a given address and port using TCP. Used for
+# configuring the test server in ixfr/ans2/ans.pl.
+#
+
+use IO::File;
+use IO::Socket;
+
+@ARGV == 2 or die "usage: send.pl host port [file ...]\n";
+
+my $host = shift @ARGV;
+my $port = shift @ARGV;
+
+my $sock = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port,
+ Proto => "tcp",) or die "$!";
+while (<>) {
+ $sock->syswrite($_, length $_);
+}
+
+$sock->close;
diff --git a/bin/tests/system/setup.sh b/bin/tests/system/setup.sh
new file mode 100644
index 0000000..8418e2e
--- /dev/null
+++ b/bin/tests/system/setup.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.11 2007/06/19 23:47:00 tbox Exp $
+
+#
+# Run a system test.
+#
+
+SYSTEMTESTTOP=.
+. $SYSTEMTESTTOP/conf.sh
+
+test $# -gt 0 || { echo "usage: $0 test-directory" >&2; exit 1; }
+
+test=$1
+shift
+
+test -d $test || { echo "$0: $test: no such test" >&2; exit 1; }
+
+# Set up any dynamically generated test data
+if test -f $test/setup.sh
+then
+ ( cd $test && sh setup.sh "$@" )
+fi
+
+
diff --git a/bin/tests/system/sortlist/clean.sh b/bin/tests/system/sortlist/clean.sh
new file mode 100644
index 0000000..bb71507
--- /dev/null
+++ b/bin/tests/system/sortlist/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.7 2007/09/26 03:22:44 marka Exp $
+
+rm -f *.dig *.good
+rm -f */named.memstats
diff --git a/bin/tests/system/sortlist/ns1/example.db b/bin/tests/system/sortlist/ns1/example.db
new file mode 100644
index 0000000..7e408db
--- /dev/null
+++ b/bin/tests/system/sortlist/ns1/example.db
@@ -0,0 +1,43 @@
+; Copyright (C) 2004, 2007 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: example.db,v 1.7 2007/06/19 23:47:05 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ IN SOA ns1.example. hostmaster.example. (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns1.example.
+ns1.example. A 10.53.0.1
+
+; Let's see what the sortlist picks out of this...
+a A 1.1.1.1
+a A 1.1.1.5
+a A 1.1.1.2
+a A 192.168.3.1
+a A 1.1.1.3
+a A 192.168.1.1
+a A 1.1.1.4
+
+b A 10.53.0.1
+b A 10.53.0.2
+b A 10.53.0.3
+b A 10.53.0.4
+b A 10.53.0.5
+
diff --git a/bin/tests/system/sortlist/ns1/named.conf b/bin/tests/system/sortlist/ns1/named.conf
new file mode 100644
index 0000000..5d149ec
--- /dev/null
+++ b/bin/tests/system/sortlist/ns1/named.conf
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.10 2007/06/19 23:47:05 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+
+ sortlist {
+ { 10.53.0.1; // IF 10.53.0.1
+ {
+ !1.1.1.4; !1.1.1.2; !1.1.1.3; !1.1.1.1; // sort these last,
+ 192.168.3/24; // this first
+ { 192.168.2/24; 192.168.1/24; }; }; }; // and these next
+ { { 10.53.0.2; 10.53.0.3; }; }; // Prefer self
+ 10.53.0.4; // BIND 8 compat
+ { 10.53.0.5; 10.53.0.5; }; // BIND 8 compat
+ };
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
diff --git a/bin/tests/system/sortlist/ns1/root.db b/bin/tests/system/sortlist/ns1/root.db
new file mode 100644
index 0000000..f300adc
--- /dev/null
+++ b/bin/tests/system/sortlist/ns1/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.5 2007/06/19 23:47:05 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/sortlist/tests.sh b/bin/tests/system/sortlist/tests.sh
new file mode 100644
index 0000000..06f175a
--- /dev/null
+++ b/bin/tests/system/sortlist/tests.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.9 2007/09/14 01:46:05 marka Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+echo "I:test 2-element sortlist statement"
+cat <<EOF >test1.good
+a.example. 300 IN A 192.168.3.1
+a.example. 300 IN A 192.168.1.1
+a.example. 300 IN A 1.1.1.5
+a.example. 300 IN A 1.1.1.1
+a.example. 300 IN A 1.1.1.3
+a.example. 300 IN A 1.1.1.2
+a.example. 300 IN A 1.1.1.4
+EOF
+$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd a.example. \
+ @10.53.0.1 -b 10.53.0.1 -p 5300 >test1.dig
+# Note that this can't use digcomp.pl because here, the ordering of the
+# result RRs is significant.
+diff test1.dig test1.good || status=1
+
+echo "I:test 1-element sortlist statement and undocumented BIND 8 features"
+ cat <<EOF >test2.good
+b.example. 300 IN A 10.53.0.$n
+EOF
+
+$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd \
+ b.example. @10.53.0.1 -b 10.53.0.2 -p 5300 | sed 1q | \
+ egrep '10.53.0.(2|3)$' > test2.out &&
+$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd \
+ b.example. @10.53.0.1 -b 10.53.0.3 -p 5300 | sed 1q | \
+ egrep '10.53.0.(2|3)$' >> test2.out &&
+$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd \
+ b.example. @10.53.0.1 -b 10.53.0.4 -p 5300 | sed 1q | \
+ egrep '10.53.0.4$' >> test2.out &&
+$DIG +tcp +noadd +nosea +nostat +noquest +noauth +nocomm +nocmd \
+ b.example. @10.53.0.1 -b 10.53.0.5 -p 5300 | sed 1q | \
+ egrep '10.53.0.5$' >> test2.out || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/start.pl b/bin/tests/system/start.pl
new file mode 100644
index 0000000..1f461b5
--- /dev/null
+++ b/bin/tests/system/start.pl
@@ -0,0 +1,209 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2004-2008 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: start.pl,v 1.13 2008/01/02 23:47:01 tbox Exp $
+
+# Framework for starting test servers.
+# Based on the type of server specified, check for port availability, remove
+# temporary files, start the server, and verify that the server is running.
+# If a server is specified, start it. Otherwise, start all servers for test.
+
+use strict;
+use Cwd 'abs_path';
+use Getopt::Long;
+
+# Option handling
+# --noclean test [server [options]]
+#
+# --noclean - Do not cleanup files in server directory
+# test - name of the test directory
+# server - name of the server directory
+# options - alternate options for the server
+
+my $usage = "usage: $0 [--noclean] test-directory [server-directory [server-options]]";
+my $noclean;
+GetOptions('noclean' => \$noclean);
+my $test = $ARGV[0];
+my $server = $ARGV[1];
+my $options = $ARGV[2];
+
+if (!$test) {
+ print "$usage\n";
+}
+if (!-d $test) {
+ print "No test directory: \"$test\"\n";
+}
+if ($server && !-d "$test/$server") {
+ print "No server directory: \"$test/$server\"\n";
+}
+
+# Global variables
+my $topdir = abs_path("$test/..");
+my $testdir = abs_path("$test");
+my $NAMED = $ENV{'NAMED'};
+my $LWRESD = $ENV{'LWRESD'};
+my $DIG = $ENV{'DIG'};
+my $PERL = $ENV{'PERL'};
+
+# Start the server(s)
+
+if ($server) {
+ if ($server =~ /^ns/) {
+ &check_ports($server);
+ }
+ &start_server($server, $options);
+ if ($server =~ /^ns/) {
+ &verify_server($server);
+ }
+} else {
+ # Determine which servers need to be started for this test.
+ opendir DIR, $testdir;
+ my @files = sort readdir DIR;
+ closedir DIR;
+
+ my @ns = grep /^ns[0-9]*$/, @files;
+ my @lwresd = grep /^lwresd[0-9]*$/, @files;
+ my @ans = grep /^ans[0-9]*$/, @files;
+
+ # Start the servers we found.
+ &check_ports();
+ foreach (@ns, @lwresd, @ans) {
+ &start_server($_);
+ }
+ foreach (@ns) {
+ &verify_server($_);
+ }
+}
+
+# Subroutines
+
+sub check_ports {
+ my $server = shift;
+ my $options = "";
+
+ if ($server && $server =~ /(\d+)$/) {
+ $options = "-i $1";
+ }
+
+ my $tries = 0;
+ while (1) {
+ my $return = system("$PERL $topdir/testsock.pl -p 5300 $options");
+ last if ($return == 0);
+ if (++$tries > 4) {
+ print "$0: could not bind to server addresses, still running?\n";
+ print "I:server sockets not available\n";
+ print "R:FAIL\n";
+ system("$PERL $topdir/stop.pl $testdir"); # Is this the correct behavior?
+ exit 1;
+ }
+ print "I:Couldn't bind to socket (yet)\n";
+ sleep 2;
+ }
+}
+
+sub start_server {
+ my $server = shift;
+ my $options = shift;
+
+ my $cleanup_files;
+ my $command;
+ my $pid_file;
+
+ if ($server =~ /^ns/) {
+ $cleanup_files = "{*.jnl,*.bk,*.st,named.run}";
+ $command = "$NAMED ";
+ if ($options) {
+ $command .= "$options";
+ } else {
+ $command .= "-m record,size,mctx ";
+ $command .= "-T clienttest ";
+ $command .= "-c named.conf -d 99 -g";
+ }
+ $command .= " >named.run 2>&1 &";
+ $pid_file = "named.pid";
+ } elsif ($server =~ /^lwresd/) {
+ $cleanup_files = "{lwresd.run}";
+ $command = "$LWRESD ";
+ if ($options) {
+ $command .= "$options";
+ } else {
+ $command .= "-m record,size,mctx ";
+ $command .= "-T clienttest ";
+ $command .= "-C resolv.conf -d 99 -g ";
+ $command .= "-i lwresd.pid -P 9210 -p 5300";
+ }
+ $command .= " >lwresd.run 2>&1 &";
+ $pid_file = "lwresd.pid";
+ } elsif ($server =~ /^ans/) {
+ $cleanup_files = "{ans.run}";
+ $command = "$PERL ./ans.pl ";
+ if ($options) {
+ $command .= "$options";
+ } else {
+ $command .= "";
+ }
+ $command .= " >ans.run 2>&1 &";
+ $pid_file = "ans.pid";
+ } else {
+ print "I:Unknown server type $server\n";
+ print "R:FAIL\n";
+ system "$PERL $topdir/stop.pl $testdir";
+ exit 1;
+ }
+
+ # print "I:starting server $server\n";
+
+ chdir "$testdir/$server";
+
+ unless ($noclean) {
+ unlink glob $cleanup_files;
+ }
+
+ system "$command";
+
+ my $tries = 0;
+ while (!-f $pid_file) {
+ if (++$tries > 14) {
+ print "I:Couldn't start server $server\n";
+ print "R:FAIL\n";
+ system "$PERL $topdir/stop.pl $testdir";
+ exit 1;
+ }
+ sleep 1;
+ }
+}
+
+sub verify_server {
+ my $server = shift;
+ my $n = $server;
+ $n =~ s/^ns//;
+
+ my $tries = 0;
+ while (1) {
+ my $return = system("$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p 5300 version.bind. chaos txt \@10.53.0.$n > dig.out");
+ last if ($return == 0);
+ print `grep ";" dig.out`;
+ if (++$tries >= 30) {
+ print "I:no response from $server\n";
+ print "R:FAIL\n";
+ system("$PERL $topdir/stop.pl $testdir");
+ exit 1;
+ }
+ sleep 2;
+ }
+ unlink "dig.out";
+}
diff --git a/bin/tests/system/start.sh b/bin/tests/system/start.sh
new file mode 100644
index 0000000..7c128db
--- /dev/null
+++ b/bin/tests/system/start.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: start.sh,v 1.42 2007/06/18 23:47:27 tbox Exp $
+
+. ./conf.sh
+$PERL start.pl "$@"
diff --git a/bin/tests/system/stop.pl b/bin/tests/system/stop.pl
new file mode 100644
index 0000000..3d4b804
--- /dev/null
+++ b/bin/tests/system/stop.pl
@@ -0,0 +1,188 @@
+#!/usr/bin/perl -w
+#
+# 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: stop.pl,v 1.12 2007/06/19 23:47:00 tbox Exp $
+
+# Framework for stopping test servers
+# Based on the type of server specified, signal the server to stop, wait
+# briefly for it to die, and then kill it if it is still alive.
+# If a server is specified, stop it. Otherwise, stop all servers for test.
+
+use strict;
+use Cwd 'abs_path';
+
+# Option handling
+# [--use-rndc] test [server]
+#
+# test - name of the test directory
+# server - name of the server directory
+
+my $usage = "usage: $0 [--use-rndc] test-directory [server-directory]";
+my $use_rndc;
+
+while (@ARGV && $ARGV[0] =~ /^-/) {
+ my $opt = shift @ARGV;
+ if ($opt eq '--use-rndc') {
+ $use_rndc = 1;
+ } else {
+ die "$usage\n";
+ }
+}
+
+my $test = $ARGV[0];
+my $server = $ARGV[1];
+
+my $errors = 0;
+
+die "$usage\n" unless defined($test);
+die "No test directory: \"$test\"\n" unless (-d $test);
+die "No server directory: \"$server\"\n" if (defined($server) && !-d "$test/$server");
+
+# Global variables
+my $testdir = abs_path($test);
+my @servers;
+
+
+# Determine which servers need to be stopped.
+if (defined $server) {
+ @servers = ($server);
+} else {
+ local *DIR;
+ opendir DIR, $testdir or die "$testdir: $!\n";
+ my @files = sort readdir DIR;
+ closedir DIR;
+
+ my @ns = grep /^ns[0-9]*$/, @files;
+ my @lwresd = grep /^lwresd[0-9]*$/, @files;
+ my @ans = grep /^ans[0-9]*$/, @files;
+
+ push @servers, @ns, @lwresd, @ans;
+}
+
+
+# Stop the server(s), pass 1: rndc.
+if ($use_rndc) {
+ foreach my $server (grep /^ns/, @servers) {
+ stop_rndc($server);
+ }
+
+ wait_for_servers(30, grep /^ns/, @servers);
+}
+
+
+# Pass 2: SIGTERM
+foreach my $server (@servers) {
+ stop_signal($server, "TERM");
+}
+
+wait_for_servers(60, @servers);
+
+# Pass 3: SIGABRT
+foreach my $server (@servers) {
+ stop_signal($server, "ABRT");
+}
+
+exit($errors ? 1 : 0);
+
+# Subroutines
+
+# Return the full path to a given server's PID file.
+sub server_pid_file {
+ my($server) = @_;
+
+ my $pid_file;
+ if ($server =~ /^ns/) {
+ $pid_file = "named.pid";
+ } elsif ($server =~ /^lwresd/) {
+ $pid_file = "lwresd.pid";
+ } elsif ($server =~ /^ans/) {
+ $pid_file = "ans.pid";
+ } else {
+ print "I:Unknown server type $server\n";
+ exit 1;
+ }
+ $pid_file = "$testdir/$server/$pid_file";
+}
+
+# Read a PID.
+sub read_pid {
+ my($pid_file) = @_;
+
+ local *FH;
+ my $result = open FH, "< $pid_file";
+ if (!$result) {
+ print "I:$pid_file: $!\n";
+ unlink $pid_file;
+ return;
+ }
+
+ my $pid = <FH>;
+ chomp($pid);
+ return $pid;
+}
+
+# Stop a named process with rndc.
+sub stop_rndc {
+ my($server) = @_;
+
+ return unless ($server =~ /^ns(\d+)$/);
+ my $ip = "10.53.0.$1";
+
+ # Ugly, but should work.
+ system("$ENV{RNDC} -c $testdir/../common/rndc.conf -s $ip -p 9953 stop | sed 's/^/I:$server /'");
+ return;
+}
+
+# Stop a server by sending a signal to it.
+sub stop_signal {
+ my($server, $sig) = @_;
+
+ my $pid_file = server_pid_file($server);
+ return unless -f $pid_file;
+
+ my $pid = read_pid($pid_file);
+ return unless defined($pid);
+
+ if ($sig eq 'ABRT') {
+ print "I:$server didn't die when sent a SIGTERM\n";
+ $errors++;
+ }
+
+ my $result = kill $sig, $pid;
+ if (!$result) {
+ print "I:$server died before a SIG$sig was sent\n";
+ unlink $pid_file;
+ $errors++;
+ }
+
+ return;
+}
+
+sub wait_for_servers {
+ my($timeout, @servers) = @_;
+
+ my @pid_files = grep { defined($_) }
+ map { server_pid_file($_) } @servers;
+
+ while ($timeout > 0 && @pid_files > 0) {
+ @pid_files = grep { -f $_ } @pid_files;
+ sleep 1 if (@pid_files > 0);
+ $timeout--;
+ }
+
+ return;
+}
diff --git a/bin/tests/system/stop.sh b/bin/tests/system/stop.sh
new file mode 100644
index 0000000..5eb6cdd
--- /dev/null
+++ b/bin/tests/system/stop.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: stop.sh,v 1.25 2007/06/18 23:47:27 tbox Exp $
+
+. ./conf.sh
+$PERL ./stop.pl "$@"
+
diff --git a/bin/tests/system/stress/clean.sh b/bin/tests/system/stress/clean.sh
new file mode 100644
index 0000000..1a3fa60
--- /dev/null
+++ b/bin/tests/system/stress/clean.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.6 2007/09/26 03:22:44 marka Exp $
+
+rm -f reload.pid
+
+rm -f ns?/zones.conf
+rm -f ns?/zone*.bk
+
+rm -f ns1/delegations.db
+
+rm -f ns2/zone0*.db
+rm -f ns2/zone0*.jnl
+rm -f */named.memstats
diff --git a/bin/tests/system/stress/ns1/named.conf b/bin/tests/system/stress/ns1/named.conf
new file mode 100644
index 0000000..3d88d8e
--- /dev/null
+++ b/bin/tests/system/stress/ns1/named.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.6 2007/06/19 23:47:05 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/stress/ns2/named.conf b/bin/tests/system/stress/ns2/named.conf
new file mode 100644
index 0000000..812b833
--- /dev/null
+++ b/bin/tests/system/stress/ns2/named.conf
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.7 2007/06/19 23:47:05 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "zones.conf";
diff --git a/bin/tests/system/stress/ns3/named.conf b/bin/tests/system/stress/ns3/named.conf
new file mode 100644
index 0000000..9ff09d7
--- /dev/null
+++ b/bin/tests/system/stress/ns3/named.conf
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.8 2007/06/18 23:47:30 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+server 10.53.0.4 {
+ provide-ixfr no;
+};
+server 10.53.0.2 {
+ request-ixfr no;
+};
+
+include "zones.conf";
diff --git a/bin/tests/system/stress/ns4/named.conf b/bin/tests/system/stress/ns4/named.conf
new file mode 100644
index 0000000..e40a0a5
--- /dev/null
+++ b/bin/tests/system/stress/ns4/named.conf
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.8 2007/06/18 23:47:31 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+include "zones.conf";
+
diff --git a/bin/tests/system/stress/setup.pl b/bin/tests/system/stress/setup.pl
new file mode 100644
index 0000000..5ae0928
--- /dev/null
+++ b/bin/tests/system/stress/setup.pl
@@ -0,0 +1,91 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2004, 2007 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: setup.pl,v 1.6 2007/06/19 23:47:05 tbox Exp $
+
+#
+# Set up test data for zone transfer quota tests.
+#
+use FileHandle;
+
+my $n_zones = 5;
+my $n_names = 1000;
+
+make_zones(2, undef);
+make_zones(3, "10.53.0.2");
+make_zones(4, "10.53.0.3");
+
+my $rootdelegations =
+ new FileHandle("ns1/root.db", "w") or die;
+
+print $rootdelegations <<END;
+\$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+END
+
+for ($z = 0; $z < $n_zones; $z++) {
+ my $zn = sprintf("zone%06d.example", $z);
+ foreach $ns (qw(2 3 4)) {
+ print $rootdelegations "$zn. NS ns$ns.$zn.\n";
+ print $rootdelegations "ns$ns.$zn. A 10.53.0.$ns\n";
+ }
+}
+close $rootdelegations;
+
+sub make_zones {
+ my ($nsno, $slaved_from) = @_;
+ my $namedconf = new FileHandle("ns$nsno/zones.conf", "w") or die;
+ for ($z = 0; $z < $n_zones; $z++) {
+ my $zn = sprintf("zone%06d.example", $z);
+ if (defined($slaved_from)) {
+ print $namedconf "zone \"$zn\" { type slave; " .
+ "file \"$zn.bk\"; masters { $slaved_from; }; };\n";
+ } else {
+ print $namedconf "zone \"$zn\" { " .
+ "type master; " .
+ "allow-update { any; }; " .
+ "file \"$zn.db\"; };\n";
+
+ my $fn = "ns$nsno/$zn.db";
+ my $f = new FileHandle($fn, "w") or die "open: $fn: $!";
+ print $f "\$TTL 300
+\@ IN SOA ns2.$zn. hostmaster 1 300 120 3600 86400
+@ NS ns2.$zn.
+ns2.$zn. A 10.53.0.2
+@ NS ns3.$zn.
+ns3.$zn. A 10.53.0.3
+@ NS ns4.$zn.
+ns4.$zn. A 10.53.0.4
+ MX 10 mail1.isp.example.
+ MX 20 mail2.isp.example.
+";
+ for ($i = 0; $i < $n_names; $i++) {
+ print $f sprintf("name%06d", $i) .
+ " A 10.0.0.1\n";
+ }
+ $f->close;
+ }
+ }
+}
diff --git a/bin/tests/system/stress/setup.sh b/bin/tests/system/stress/setup.sh
new file mode 100644
index 0000000..2737998
--- /dev/null
+++ b/bin/tests/system/stress/setup.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.5 2007/06/19 23:47:05 tbox Exp $
+
+#
+# Set up test data for zone transfer quota tests.
+#
+
+$PERL setup.pl
diff --git a/bin/tests/system/stress/tests.sh b/bin/tests/system/stress/tests.sh
new file mode 100644
index 0000000..1c5e75e
--- /dev/null
+++ b/bin/tests/system/stress/tests.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.5 2007/06/19 23:47:05 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+if $PERL -e 'use Net::DNS;' 2>/dev/null
+then
+ :
+else
+ echo "I:This test requires the Net::DNS library." >&2
+ exit 1
+fi
+
+(
+sh -c "while true
+ do $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reload 2>&1 |
+ sed 's/^/I:ns3 /';
+ sleep 1
+ done" & echo $! >reload.pid
+) &
+
+for i in 0 1 2 3 4
+do
+ $PERL update.pl -s 10.53.0.2 -p 5300 zone00000$i.example. &
+done
+
+echo "I:waiting for background processes to finish"
+wait
+
+echo "I:killing reload loop"
+kill `cat reload.pid`
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/stress/update.pl b/bin/tests/system/stress/update.pl
new file mode 100644
index 0000000..6a4a6fb
--- /dev/null
+++ b/bin/tests/system/stress/update.pl
@@ -0,0 +1,107 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2004, 2007 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.
+
+#
+# Dynamic update test suite.
+#
+# Usage:
+#
+# perl update_test.pl [-s server] [-p port] zone
+#
+# The server defaults to 127.0.0.1.
+# The port defaults to 53.
+#
+# The "Special NS rules" tests will only work correctly if the
+# has no NS records to begin with, or alternatively has a
+# single NS record pointing at the name "ns1" (relative to
+# the zone name).
+#
+# Installation notes:
+#
+# This program uses the Net::DNS::Resolver module.
+# You can install it by saying
+#
+# perl -MCPAN -e "install Net::DNS"
+#
+# $Id: update.pl,v 1.5 2007/06/19 23:47:05 tbox Exp $
+#
+
+use Getopt::Std;
+use Net::DNS;
+use Net::DNS::Update;
+use Net::DNS::Resolver;
+
+$opt_s = "127.0.0.1";
+$opt_p = 53;
+
+getopt('s:p:');
+
+$res = new Net::DNS::Resolver;
+$res->nameservers($opt_s);
+$res->port($opt_p);
+$res->defnames(0); # Do not append default domain.
+
+@ARGV == 1 or die
+ "usage: perl update_test.pl [-s server] [-p port] zone\n";
+
+$zone = shift @ARGV;
+
+my $failures = 0;
+
+sub assert {
+ my ($cond, $explanation) = @_;
+ if (!$cond) {
+ print "I:Test Failed: $explanation ***\n";
+ $failures++
+ }
+}
+
+sub test {
+ my ($expected, @records) = @_;
+
+ my $update = new Net::DNS::Update("$zone");
+
+ foreach $rec (@records) {
+ $update->push(@$rec);
+ }
+
+ $reply = $res->send($update);
+
+ # Did it work?
+ if (defined $reply) {
+ my $rcode = $reply->header->rcode;
+ assert($rcode eq $expected, "expected $expected, got $rcode");
+ } else {
+ print "I:Update failed: ", $res->errorstring, "\n";
+ }
+}
+
+sub section {
+ my ($msg) = @_;
+ print "I:$msg\n";
+}
+
+for ($i = 0; $i < 1000; $i++) {
+ test("NOERROR", ["update", rr_add("dynamic-$i.$zone 300 TXT txt-$i" )]);
+}
+
+if ($failures) {
+ print "I:$failures tests failed.\n";
+} else {
+ print "I:Update of $opt_s zone $zone successful.\n";
+}
+exit $failures;
diff --git a/bin/tests/system/stub/clean.sh b/bin/tests/system/stub/clean.sh
new file mode 100644
index 0000000..dadd765
--- /dev/null
+++ b/bin/tests/system/stub/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.10 2007/09/26 03:22:44 marka Exp $
+
+#
+# Clean up after stub tests.
+#
+rm -f dig.out.ns3 ns3/child.example.st
+rm -f */named.memstats
diff --git a/bin/tests/system/stub/knowngood.dig.out.norec b/bin/tests/system/stub/knowngood.dig.out.norec
new file mode 100644
index 0000000..ca0e458
--- /dev/null
+++ b/bin/tests/system/stub/knowngood.dig.out.norec
@@ -0,0 +1,21 @@
+
+; <<>> DiG 8.2 <<>> -p @10.53.0.3 +norec data.child.example txt
+; (1 server found)
+;; res options: init defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 216
+;; flags: qr ra ad; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; data.child.example, type = TXT, class = IN
+
+;; AUTHORITY SECTION:
+child.example. 5M IN NS ns2.child.example.
+
+;; ADDITIONAL SECTION:
+ns2.child.example. 5M IN A 10.53.0.2
+
+;; Total query time: 3 msec
+;; FROM: draco to SERVER: 10.53.0.3
+;; WHEN: Wed Jun 21 10:58:37 2000
+;; MSG SIZE sent: 36 rcvd: 70
+
diff --git a/bin/tests/system/stub/knowngood.dig.out.rec b/bin/tests/system/stub/knowngood.dig.out.rec
new file mode 100644
index 0000000..9f2e4ee
--- /dev/null
+++ b/bin/tests/system/stub/knowngood.dig.out.rec
@@ -0,0 +1,24 @@
+
+; <<>> DiG 8.2 <<>> -p @10.53.0.3 data.child.example txt
+; (1 server found)
+;; res options: init recurs defnam dnsrch
+;; got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6
+;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
+;; QUERY SECTION:
+;; data.child.example, type = TXT, class = IN
+
+;; ANSWER SECTION:
+data.child.example. 5M IN TXT "some" "test" "data"
+
+;; AUTHORITY SECTION:
+child.example. 5M IN NS ns2.child.example.
+
+;; ADDITIONAL SECTION:
+ns2.child.example. 5M IN A 10.53.0.2
+
+;; Total query time: 8 msec
+;; FROM: draco to SERVER: 10.53.0.3
+;; WHEN: Wed Jun 21 10:58:54 2000
+;; MSG SIZE sent: 36 rcvd: 97
+
diff --git a/bin/tests/system/stub/ns1/named.conf b/bin/tests/system/stub/ns1/named.conf
new file mode 100644
index 0000000..858506b
--- /dev/null
+++ b/bin/tests/system/stub/ns1/named.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.14 2007/06/19 23:47:05 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/stub/ns1/root.db b/bin/tests/system/stub/ns1/root.db
new file mode 100644
index 0000000..a811e47
--- /dev/null
+++ b/bin/tests/system/stub/ns1/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.9 2007/06/19 23:47:05 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
diff --git a/bin/tests/system/stub/ns2/child.example.db b/bin/tests/system/stub/ns2/child.example.db
new file mode 100644
index 0000000..327a3b8
--- /dev/null
+++ b/bin/tests/system/stub/ns2/child.example.db
@@ -0,0 +1,28 @@
+; Copyright (C) 2004, 2007 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: child.example.db,v 1.9 2007/06/19 23:47:05 tbox Exp $
+
+$TTL 300 ; 5 minutes
+child.example. IN SOA ns2.child.example. hostmaster.child.example. (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+child.example. NS ns2.child.example.
+ns2.child.example. A 10.53.0.2
+data TXT some test data
diff --git a/bin/tests/system/stub/ns2/named.conf b/bin/tests/system/stub/ns2/named.conf
new file mode 100644
index 0000000..888b5e0
--- /dev/null
+++ b/bin/tests/system/stub/ns2/named.conf
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.14 2007/06/19 23:47:05 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "child.example" {
+ type master;
+ file "child.example.db";
+};
diff --git a/bin/tests/system/stub/ns3/example.db b/bin/tests/system/stub/ns3/example.db
new file mode 100644
index 0000000..25e17e4
--- /dev/null
+++ b/bin/tests/system/stub/ns3/example.db
@@ -0,0 +1,28 @@
+; Copyright (C) 2004, 2007 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: example.db,v 1.9 2007/06/19 23:47:05 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA ns3.example. hostmaster.example. (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
diff --git a/bin/tests/system/stub/ns3/named.conf b/bin/tests/system/stub/ns3/named.conf
new file mode 100644
index 0000000..89ba16e
--- /dev/null
+++ b/bin/tests/system/stub/ns3/named.conf
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.16 2007/06/18 23:47:31 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "child.example" {
+ type stub;
+ file "child.example.st";
+ masters { 10.53.0.2; };
+};
diff --git a/bin/tests/system/stub/tests.sh b/bin/tests/system/stub/tests.sh
new file mode 100644
index 0000000..ad7fe0b
--- /dev/null
+++ b/bin/tests/system/stub/tests.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.14 2007/06/19 23:47:05 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+echo "I:trying an axfr that should be denied (NOTAUTH)"
+$DIG +tcp data.child.example. @10.53.0.3 axfr -p 5300 > dig.out.ns3 || status=1
+grep "; Transfer failed." dig.out.ns3 > /dev/null || status=1
+
+echo "I:look for stub zone data without recursion (should not be found)"
+$DIG +tcp +norec data.child.example. @10.53.0.3 txt -p 5300 > dig.out.ns3 \
+ || status=1
+$PERL ../digcomp.pl knowngood.dig.out.norec dig.out.ns3 || status=1
+
+echo "I:look for stub zone data with recursion (should be found)"
+$DIG +tcp data.child.example. @10.53.0.3 txt -p 5300 > dig.out.ns3 || status=1
+$PERL ../digcomp.pl knowngood.dig.out.rec dig.out.ns3 || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/testsock.pl b/bin/tests/system/testsock.pl
new file mode 100644
index 0000000..a658086
--- /dev/null
+++ b/bin/tests/system/testsock.pl
@@ -0,0 +1,51 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2004, 2007 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: testsock.pl,v 1.16 2007/06/19 23:47:00 tbox Exp $
+
+# Test whether the interfaces on 10.53.0.* are up.
+
+require 5.001;
+
+use Socket;
+use Getopt::Long;
+
+my $port = 0;
+my $id = 0;
+GetOptions("p=i" => \$port,
+ "i=i" => \$id);
+
+my @ids;
+if ($id != 0) {
+ @ids = ($id);
+} else {
+ @ids = (1..5);
+}
+
+foreach $id (@ids) {
+ my $addr = pack("C4", 10, 53, 0, $id);
+ my $sa = pack_sockaddr_in($port, $addr);
+ socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname("tcp"))
+ or die "$0: socket: $!\n";
+ setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1));
+
+ bind(SOCK, $sa)
+ or die sprintf("$0: bind(%s, %d): $!\n",
+ inet_ntoa($addr), $port);
+ close(SOCK);
+ sleep(1);
+}
diff --git a/bin/tests/system/tkey/Makefile.in b/bin/tests/system/tkey/Makefile.in
new file mode 100644
index 0000000..684fb1a
--- /dev/null
+++ b/bin/tests/system/tkey/Makefile.in
@@ -0,0 +1,60 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2001, 2002 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.11 2007/06/19 23:47:06 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+DNSLIBS = ../../../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+ISCLIBS = ../../../../lib/isc/libisc.@A@
+
+DNSDEPLIBS = ../../../../lib/dns/libdns.@A@
+ISCDEPLIBS = ../../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+TARGETS = keycreate@EXEEXT@ keydelete@EXEEXT@
+
+CREATEOBJS = keycreate.@O@
+DELETEOBJS = keydelete.@O@
+
+SRCS = keycreate.c keydelete.c
+
+@BIND9_MAKE_RULES@
+
+all: keycreate@EXEEXT@ keydelete@EXEEXT@
+
+keycreate@EXEEXT@: ${CREATEOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${CREATEOBJS} ${LIBS}
+
+keydelete@EXEEXT@: ${DELETEOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${DELETEOBJS} ${LIBS}
+
+clean distclean::
+ rm -f ${TARGETS}
+
diff --git a/bin/tests/system/tkey/clean.sh b/bin/tests/system/tkey/clean.sh
new file mode 100644
index 0000000..7d64de5
--- /dev/null
+++ b/bin/tests/system/tkey/clean.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# 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: clean.sh,v 1.6 2007/09/26 03:22:44 marka Exp $
+
+rm -f dig.out.* random.data ns1/named.conf
+rm -f K* ns1/K*
+rm -f */named.memstats
diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c
new file mode 100644
index 0000000..5540866
--- /dev/null
+++ b/bin/tests/system/tkey/keycreate.c
@@ -0,0 +1,329 @@
+/*
+ * 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: keycreate.c,v 1.15 2007/06/19 23:47:06 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/dispatch.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/request.h>
+#include <dns/result.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+
+#include <dst/result.h>
+
+#define CHECK(str, x) { \
+ if ((x) != ISC_R_SUCCESS) { \
+ fprintf(stderr, "I:%s: %s\n", (str), isc_result_totext(x)); \
+ exit(-1); \
+ } \
+}
+
+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+
+#define PORT 5300
+#define TIMEOUT 30
+
+static dst_key_t *ourkey;
+static isc_mem_t *mctx;
+static dns_tsigkey_t *tsigkey, *initialkey;
+static dns_tsig_keyring_t *ring;
+static unsigned char noncedata[16];
+static isc_buffer_t nonce;
+static dns_requestmgr_t *requestmgr;
+static const char *ownername_str = ".";
+
+static void
+recvquery(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result;
+ dns_message_t *query, *response;
+ char keyname[256];
+ isc_buffer_t keynamebuf;
+ int type;
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ exit(-1);
+ }
+
+ query = reqev->ev_arg;
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = ISC_RESULTCLASS_DNSRCODE + response->rcode;
+ fprintf(stderr, "I:response rcode: %s\n",
+ isc_result_totext(result));
+ exit(-1);
+ }
+
+ result = dns_tkey_processdhresponse(query, response, ourkey, &nonce,
+ &tsigkey, ring);
+ CHECK("dns_tkey_processdhresponse", result);
+
+ /*
+ * Yes, this is a hack.
+ */
+ isc_buffer_init(&keynamebuf, keyname, sizeof(keyname));
+ result = dst_key_buildfilename(tsigkey->key, 0, "", &keynamebuf);
+ CHECK("dst_key_buildfilename", result);
+ printf("%.*s\n", (int)isc_buffer_usedlength(&keynamebuf),
+ (char *)isc_buffer_base(&keynamebuf));
+ type = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC | DST_TYPE_KEY;
+ result = dst_key_tofile(tsigkey->key, type, "");
+ CHECK("dst_key_tofile", result);
+
+ dns_message_destroy(&query);
+ dns_message_destroy(&response);
+ dns_request_destroy(&reqev->request);
+ isc_event_free(&event);
+ isc_app_shutdown();
+ return;
+}
+
+static void
+sendquery(isc_task_t *task, isc_event_t *event) {
+ struct in_addr inaddr;
+ isc_sockaddr_t address;
+ isc_region_t r;
+ isc_result_t result;
+ dns_fixedname_t keyname;
+ dns_fixedname_t ownername;
+ isc_buffer_t namestr, keybuf;
+ unsigned char keydata[9];
+ dns_message_t *query;
+ dns_request_t *request;
+ static char keystr[] = "0123456789ab";
+
+ isc_event_free(&event);
+
+ result = ISC_R_FAILURE;
+ if (inet_pton(AF_INET, "10.53.0.1", &inaddr) != 1)
+ CHECK("inet_pton", result);
+ isc_sockaddr_fromin(&address, &inaddr, PORT);
+
+ dns_fixedname_init(&keyname);
+ isc_buffer_init(&namestr, "tkeytest.", 9);
+ isc_buffer_add(&namestr, 9);
+ result = dns_name_fromtext(dns_fixedname_name(&keyname), &namestr,
+ NULL, ISC_FALSE, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ dns_fixedname_init(&ownername);
+ isc_buffer_init(&namestr, ownername_str, strlen(ownername_str));
+ isc_buffer_add(&namestr, strlen(ownername_str));
+ result = dns_name_fromtext(dns_fixedname_name(&ownername), &namestr,
+ NULL, ISC_FALSE, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ isc_buffer_init(&keybuf, keydata, 9);
+ result = isc_base64_decodestring(keystr, &keybuf);
+ CHECK("isc_base64_decodestring", result);
+
+ isc_buffer_usedregion(&keybuf, &r);
+
+ initialkey = NULL;
+ result = dns_tsigkey_create(dns_fixedname_name(&keyname),
+ DNS_TSIG_HMACMD5_NAME,
+ isc_buffer_base(&keybuf),
+ isc_buffer_usedlength(&keybuf),
+ ISC_FALSE, NULL, 0, 0, mctx, ring,
+ &initialkey);
+ CHECK("dns_tsigkey_create", result);
+
+ query = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+ CHECK("dns_message_create", result);
+
+ result = dns_tkey_builddhquery(query, ourkey,
+ dns_fixedname_name(&ownername),
+ DNS_TSIG_HMACMD5_NAME, &nonce, 3600);
+ CHECK("dns_tkey_builddhquery", result);
+
+ request = NULL;
+ result = dns_request_create(requestmgr, query, &address,
+ 0, initialkey, TIMEOUT, task,
+ recvquery, query, &request);
+ CHECK("dns_request_create", result);
+}
+
+int
+main(int argc, char *argv[]) {
+ char *ourkeyname;
+ isc_taskmgr_t *taskmgr;
+ isc_timermgr_t *timermgr;
+ isc_socketmgr_t *socketmgr;
+ isc_socket_t *sock;
+ unsigned int attrs, attrmask;
+ isc_sockaddr_t bind_any;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_dispatch_t *dispatchv4;
+ dns_view_t *view;
+ isc_entropy_t *ectx;
+ dns_tkeyctx_t *tctx;
+ isc_log_t *log;
+ isc_logconfig_t *logconfig;
+ isc_task_t *task;
+ isc_result_t result;
+ int type;
+
+ RUNCHECK(isc_app_start());
+
+ if (argc < 2) {
+ fprintf(stderr, "I:no DH key provided\n");
+ exit(-1);
+ }
+ ourkeyname = argv[1];
+
+ if (argc >= 3)
+ ownername_str = argv[2];
+
+ dns_result_register();
+
+ mctx = NULL;
+ RUNCHECK(isc_mem_create(0, 0, &mctx));
+
+ ectx = NULL;
+ RUNCHECK(isc_entropy_create(mctx, &ectx));
+ RUNCHECK(isc_entropy_createfilesource(ectx, "random.data"));
+ RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
+
+ log = NULL;
+ logconfig = NULL;
+ RUNCHECK(isc_log_create(mctx, &log, &logconfig));
+
+ RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
+
+ taskmgr = NULL;
+ RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
+ task = NULL;
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ timermgr = NULL;
+ RUNCHECK(isc_timermgr_create(mctx, &timermgr));
+ socketmgr = NULL;
+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
+ dispatchmgr = NULL;
+ RUNCHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr));
+ isc_sockaddr_any(&bind_any);
+ attrs = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_MAKEQUERY |
+ DNS_DISPATCHATTR_IPV4;
+ attrmask = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_TCP |
+ DNS_DISPATCHATTR_IPV4 |
+ DNS_DISPATCHATTR_IPV6;
+ dispatchv4 = NULL;
+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any, 4096, 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv4));
+ requestmgr = NULL;
+ RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
+ dispatchmgr, dispatchv4, NULL,
+ &requestmgr));
+
+ ring = NULL;
+ RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
+ tctx = NULL;
+ RUNCHECK(dns_tkeyctx_create(mctx, ectx, &tctx));
+
+ view = NULL;
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+ dns_view_setkeyring(view, ring);
+
+ sock = NULL;
+ RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
+ &sock));
+
+ RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
+
+ ourkey = NULL;
+ type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
+ result = dst_key_fromnamedfile(ourkeyname, type, mctx, &ourkey);
+ CHECK("dst_key_fromnamedfile", result);
+
+ isc_buffer_init(&nonce, noncedata, sizeof(noncedata));
+ result = isc_entropy_getdata(ectx, noncedata, sizeof(noncedata),
+ NULL, ISC_ENTROPY_BLOCKING);
+ CHECK("isc_entropy_getdata", result);
+ isc_buffer_add(&nonce, sizeof(noncedata));
+
+ (void)isc_app_run();
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+ dns_dispatch_detach(&dispatchv4);
+ dns_dispatchmgr_destroy(&dispatchmgr);
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_socket_detach(&sock);
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ dst_key_free(&ourkey);
+ dns_tsigkey_detach(&initialkey);
+ dns_tsigkey_detach(&tsigkey);
+
+ dns_tkeyctx_destroy(&tctx);
+
+ dns_view_detach(&view);
+
+ isc_log_destroy(&log);
+
+ dst_lib_destroy();
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c
new file mode 100644
index 0000000..cb028ad
--- /dev/null
+++ b/bin/tests/system/tkey/keydelete.c
@@ -0,0 +1,267 @@
+/*
+ * 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: keydelete.c,v 1.11 2007/06/19 23:47:06 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/dispatch.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/request.h>
+#include <dns/result.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+
+#include <dst/result.h>
+
+#define CHECK(str, x) { \
+ if ((x) != ISC_R_SUCCESS) { \
+ fprintf(stderr, "I:%s: %s\n", (str), isc_result_totext(x)); \
+ exit(-1); \
+ } \
+}
+
+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+
+#define PORT 5300
+#define TIMEOUT 30
+
+static isc_mem_t *mctx;
+static dns_tsigkey_t *tsigkey;
+static dns_tsig_keyring_t *ring;
+static dns_requestmgr_t *requestmgr;
+
+static void
+recvquery(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result;
+ dns_message_t *query, *response;
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "I:request event result: %s\n",
+ isc_result_totext(reqev->result));
+ exit(-1);
+ }
+
+ query = reqev->ev_arg;
+
+ response = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+ CHECK("dns_message_create", result);
+
+ result = dns_request_getresponse(reqev->request, response,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+ CHECK("dns_request_getresponse", result);
+
+ if (response->rcode != dns_rcode_noerror) {
+ result = ISC_RESULTCLASS_DNSRCODE + response->rcode;
+ fprintf(stderr, "I:response rcode: %s\n",
+ isc_result_totext(result));
+ exit(-1);
+ }
+
+ result = dns_tkey_processdeleteresponse(query, response, ring);
+ CHECK("dns_tkey_processdhresponse", result);
+
+ dns_message_destroy(&query);
+ dns_message_destroy(&response);
+ dns_request_destroy(&reqev->request);
+ isc_event_free(&event);
+ isc_app_shutdown();
+ return;
+}
+
+static void
+sendquery(isc_task_t *task, isc_event_t *event) {
+ struct in_addr inaddr;
+ isc_sockaddr_t address;
+ isc_result_t result;
+ dns_message_t *query;
+ dns_request_t *request;
+
+ isc_event_free(&event);
+
+ result = ISC_R_FAILURE;
+ if (inet_pton(AF_INET, "10.53.0.1", &inaddr) != 1)
+ CHECK("inet_pton", result);
+ isc_sockaddr_fromin(&address, &inaddr, PORT);
+
+ query = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
+ CHECK("dns_message_create", result);
+
+ result = dns_tkey_builddeletequery(query, tsigkey);
+ CHECK("dns_tkey_builddeletequery", result);
+
+ request = NULL;
+ result = dns_request_create(requestmgr, query, &address,
+ 0, tsigkey, TIMEOUT, task,
+ recvquery, query, &request);
+ CHECK("dns_request_create", result);
+}
+
+int
+main(int argc, char **argv) {
+ char *keyname;
+ isc_taskmgr_t *taskmgr;
+ isc_timermgr_t *timermgr;
+ isc_socketmgr_t *socketmgr;
+ isc_socket_t *sock;
+ unsigned int attrs, attrmask;
+ isc_sockaddr_t bind_any;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_dispatch_t *dispatchv4;
+ dns_view_t *view;
+ isc_entropy_t *ectx;
+ dns_tkeyctx_t *tctx;
+ dst_key_t *dstkey;
+ isc_log_t *log;
+ isc_logconfig_t *logconfig;
+ isc_task_t *task;
+ isc_result_t result;
+ int type;
+
+ RUNCHECK(isc_app_start());
+
+ if (argc < 2) {
+ fprintf(stderr, "I:no key to delete\n");
+ exit(-1);
+ }
+ keyname = argv[1];
+
+ dns_result_register();
+
+ mctx = NULL;
+ RUNCHECK(isc_mem_create(0, 0, &mctx));
+
+ ectx = NULL;
+ RUNCHECK(isc_entropy_create(mctx, &ectx));
+ RUNCHECK(isc_entropy_createfilesource(ectx, "random.data"));
+ RUNCHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE));
+
+ log = NULL;
+ logconfig = NULL;
+ RUNCHECK(isc_log_create(mctx, &log, &logconfig));
+
+ RUNCHECK(dst_lib_init(mctx, ectx, ISC_ENTROPY_GOODONLY));
+
+ taskmgr = NULL;
+ RUNCHECK(isc_taskmgr_create(mctx, 1, 0, &taskmgr));
+ task = NULL;
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ timermgr = NULL;
+ RUNCHECK(isc_timermgr_create(mctx, &timermgr));
+ socketmgr = NULL;
+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
+ dispatchmgr = NULL;
+ RUNCHECK(dns_dispatchmgr_create(mctx, NULL, &dispatchmgr));
+ isc_sockaddr_any(&bind_any);
+ attrs = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_MAKEQUERY |
+ DNS_DISPATCHATTR_IPV4;
+ attrmask = DNS_DISPATCHATTR_UDP |
+ DNS_DISPATCHATTR_TCP |
+ DNS_DISPATCHATTR_IPV4 |
+ DNS_DISPATCHATTR_IPV6;
+ dispatchv4 = NULL;
+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ &bind_any, 4096, 4, 2, 3, 5,
+ attrs, attrmask, &dispatchv4));
+ requestmgr = NULL;
+ RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr,
+ dispatchmgr, dispatchv4, NULL,
+ &requestmgr));
+
+ ring = NULL;
+ RUNCHECK(dns_tsigkeyring_create(mctx, &ring));
+ tctx = NULL;
+ RUNCHECK(dns_tkeyctx_create(mctx, ectx, &tctx));
+
+ view = NULL;
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+ dns_view_setkeyring(view, ring);
+
+ sock = NULL;
+ RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp,
+ &sock));
+
+ RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL));
+
+ dstkey = NULL;
+ type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY;
+ result = dst_key_fromnamedfile(keyname, type, mctx, &dstkey);
+ CHECK("dst_key_fromnamedfile", result);
+ result = dns_tsigkey_createfromkey(dst_key_name(dstkey),
+ DNS_TSIG_HMACMD5_NAME,
+ dstkey, ISC_TRUE, NULL, 0, 0,
+ mctx, ring, &tsigkey);
+ CHECK("dns_tsigkey_createfromkey", result);
+
+ (void)isc_app_run();
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+ dns_dispatch_detach(&dispatchv4);
+ dns_dispatchmgr_destroy(&dispatchmgr);
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_socket_detach(&sock);
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ dns_tsigkey_detach(&tsigkey);
+
+ dns_tkeyctx_destroy(&tctx);
+
+ dns_view_detach(&view);
+
+ isc_log_destroy(&log);
+
+ dst_lib_destroy();
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tests/system/tkey/ns1/named.conf.in b/bin/tests/system/tkey/ns1/named.conf.in
new file mode 100644
index 0000000..27e0d6b
--- /dev/null
+++ b/bin/tests/system/tkey/ns1/named.conf.in
@@ -0,0 +1,39 @@
+/*
+ * 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: named.conf.in,v 1.6 2007/06/19 23:47:06 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+ tkey-domain "server";
+ tkey-dhkey "server" KEYID;
+};
+
+key "tkeytest." {
+ algorithm hmac-md5;
+ secret "0123456789ab";
+};
diff --git a/bin/tests/system/tkey/ns1/setup.sh b/bin/tests/system/tkey/ns1/setup.sh
new file mode 100644
index 0000000..c54e17f
--- /dev/null
+++ b/bin/tests/system/tkey/ns1/setup.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# 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: setup.sh,v 1.8 2007/06/19 23:47:06 tbox Exp $
+
+RANDFILE=../random.data
+
+keyname=`$KEYGEN -k -a DH -b 768 -n host -r $RANDFILE server`
+keyid=`echo $keyname | $PERL -p -e 's/^.*\+0*//;'`
+rm -f named.conf
+perl -p -e "s/KEYID/$keyid/;" < named.conf.in > named.conf
diff --git a/bin/tests/system/tkey/prereq.sh b/bin/tests/system/tkey/prereq.sh
new file mode 100644
index 0000000..9c162a4
--- /dev/null
+++ b/bin/tests/system/tkey/prereq.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2006, 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: prereq.sh,v 1.10 2007/06/19 23:47:06 tbox Exp $
+
+../../genrandom 400 random.data
+
+if $KEYGEN -a RSAMD5 -b 512 -n zone -r random.data foo > /dev/null 2>&1
+then
+ rm -f foo*
+else
+ echo "I:This test requires that --with-openssl was used." >&2
+ exit 1
+fi
diff --git a/bin/tests/system/tkey/setup.sh b/bin/tests/system/tkey/setup.sh
new file mode 100644
index 0000000..d4aee8b
--- /dev/null
+++ b/bin/tests/system/tkey/setup.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# 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: setup.sh,v 1.5 2007/06/19 23:47:06 tbox Exp $
+
+RANDFILE=random.data
+
+../../genrandom 100 $RANDFILE
+
+cd ns1 && sh setup.sh
diff --git a/bin/tests/system/tkey/tests.sh b/bin/tests/system/tkey/tests.sh
new file mode 100644
index 0000000..199a3b9
--- /dev/null
+++ b/bin/tests/system/tkey/tests.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+#
+# 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: tests.sh,v 1.7 2007/06/19 23:47:06 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="@10.53.0.1 -p 5300"
+
+status=0
+
+RANDFILE=random.data
+
+echo "I:generating new DH key"
+ret=0
+dhkeyname=`$KEYGEN -k -a DH -b 768 -n host -r $RANDFILE client` || ret=1
+if [ $ret != 0 ]; then
+ echo "I:failed"
+ echo "I:exit status: $status"
+ exit $status
+fi
+status=`expr $status + $ret`
+
+for owner in . foo.example.
+do
+ echo "I:creating new key using owner name \"$owner\""
+ ret=0
+ keyname=`./keycreate $dhkeyname $owner` || ret=1
+ if [ $ret != 0 ]; then
+ echo "I:failed"
+ echo "I:exit status: $status"
+ exit $status
+ fi
+ status=`expr $status + $ret`
+
+ echo "I:checking the new key"
+ ret=0
+ $DIG $DIGOPTS . ns -k $keyname > dig.out.1 || ret=1
+ grep "status: NOERROR" dig.out.1 > /dev/null || ret=1
+ grep "TSIG.*hmac-md5.*NOERROR" dig.out.1 > /dev/null || ret=1
+ grep "Some TSIG could not be validated" dig.out.1 > /dev/null && ret=1
+ if [ $ret != 0 ]; then
+ echo "I:failed"
+ fi
+ status=`expr $status + $ret`
+
+ echo "I:deleting new key"
+ ret=0
+ ./keydelete $keyname || ret=1
+ if [ $ret != 0 ]; then
+ echo "I:failed"
+ fi
+ status=`expr $status + $ret`
+
+ echo "I:checking that new key has been deleted"
+ ret=0
+ $DIG $DIGOPTS . ns -k $keyname > dig.out.2 || ret=1
+ grep "status: NOERROR" dig.out.2 > /dev/null && ret=1
+ grep "TSIG.*hmac-md5.*NOERROR" dig.out.2 > /dev/null && ret=1
+ grep "Some TSIG could not be validated" dig.out.2 > /dev/null || ret=1
+ if [ $ret != 0 ]; then
+ echo "I:failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/tsig/clean.sh b/bin/tests/system/tsig/clean.sh
new file mode 100644
index 0000000..47e7172
--- /dev/null
+++ b/bin/tests/system/tsig/clean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Copyright (C) 2005-2007 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: clean.sh,v 1.6 2007/09/26 03:22:44 marka Exp $
+
+#
+# Clean up after tsig tests.
+#
+
+rm -f dig.out.*
+rm -f */named.memstats
diff --git a/bin/tests/system/tsig/ns1/example.db b/bin/tests/system/tsig/ns1/example.db
new file mode 100644
index 0000000..1dd6522
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/example.db
@@ -0,0 +1,151 @@
+; Copyright (C) 2005-2007 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: example.db,v 1.5 2007/06/19 23:47:06 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example.nil IN SOA ns1.example.nil. hostmaster.example.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example.nil. NS ns1.example.nil.
+ns1.example.nil. A 10.53.0.1
+example.nil. NS ns2.example.nil.
+ns2.example.nil. A 10.53.0.2
+
+$ORIGIN example.nil.
+* MX 10 mail
+a TXT "foo foo foo"
+ PTR foo.net.
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.nil.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.nil.
+ns A 73.80.65.49
+$ORIGIN example.nil.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.nil.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.nil.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/tsig/ns1/named.conf b/bin/tests/system/tsig/ns1/named.conf
new file mode 100644
index 0000000..b48de83
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/named.conf
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2005-2007 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.conf,v 1.5 2007/06/19 23:47:06 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+};
+
+key "md5" {
+ secret "97rnFx24Tfna4mHPfgnerA==";
+ algorithm hmac-md5;
+};
+
+key "sha1" {
+ secret "FrSt77yPTFx6hTs4i2tKLB9LmE0=";
+ algorithm hmac-sha1;
+};
+
+key "sha224" {
+ secret "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA==";
+ algorithm hmac-sha224;
+};
+
+key "sha256" {
+ secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=";
+ algorithm hmac-sha256;
+};
+
+key "sha384" {
+ secret "OaDdoAk2LAcLtYeUnsT7A9XHjsb6ZEma7OCvUpMraQIJX6HetGrlKmF7yglO1G2h";
+ algorithm hmac-sha384;
+};
+
+key "sha512" {
+ secret "jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg==";
+ algorithm hmac-sha512;
+};
+
+key "md5-trunc" {
+ secret "97rnFx24Tfna4mHPfgnerA==";
+ algorithm hmac-md5-80;
+};
+
+key "sha1-trunc" {
+ secret "FrSt77yPTFx6hTs4i2tKLB9LmE0=";
+ algorithm hmac-sha1-80;
+};
+
+key "sha224-trunc" {
+ secret "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA==";
+ algorithm hmac-sha224-112;
+};
+
+key "sha256-trunc" {
+ secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=";
+ algorithm hmac-sha256-128;
+};
+
+key "sha384-trunc" {
+ secret "OaDdoAk2LAcLtYeUnsT7A9XHjsb6ZEma7OCvUpMraQIJX6HetGrlKmF7yglO1G2h";
+ algorithm hmac-sha384-192;
+};
+
+key "sha512-trunc" {
+ secret "jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg==";
+ algorithm hmac-sha512-256;
+};
+
+zone "example.nil" {
+ type master;
+ file "example.db";
+};
diff --git a/bin/tests/system/tsig/tests.sh b/bin/tests/system/tsig/tests.sh
new file mode 100644
index 0000000..d2391c1
--- /dev/null
+++ b/bin/tests/system/tsig/tests.sh
@@ -0,0 +1,218 @@
+#!/bin/sh
+#
+# Copyright (C) 2005-2007 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: tests.sh,v 1.5 2007/06/19 23:47:06 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+#
+# Shared secrets.
+#
+md5="97rnFx24Tfna4mHPfgnerA=="
+sha1="FrSt77yPTFx6hTs4i2tKLB9LmE0="
+sha224="hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA=="
+sha256="R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY="
+sha384="OaDdoAk2LAcLtYeUnsT7A9XHjsb6ZEma7OCvUpMraQIJX6HetGrlKmF7yglO1G2h"
+sha512="jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg=="
+
+status=0
+
+echo "I:fetching using hmac-md5 (old form)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "md5:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5.old || ret=1
+grep -i "md5.*TSIG.*NOERROR" dig.out.md5.old > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-md5 (new form)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-md5:md5:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5.new || ret=1
+grep -i "md5.*TSIG.*NOERROR" dig.out.md5.new > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha1"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha1:sha1:$sha1" @10.53.0.1 soa -p 5300 > dig.out.sha1 || ret=1
+grep -i "sha1.*TSIG.*NOERROR" dig.out.sha1 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha224"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha224:sha224:$sha224" @10.53.0.1 soa -p 5300 > dig.out.sha224 || ret=1
+grep -i "sha224.*TSIG.*NOERROR" dig.out.sha224 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha256"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha256:sha256:$sha256" @10.53.0.1 soa -p 5300 > dig.out.sha256 || ret=1
+grep -i "sha256.*TSIG.*NOERROR" dig.out.sha256 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha384"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha384:sha384:$sha384" @10.53.0.1 soa -p 5300 > dig.out.sha384 || ret=1
+grep -i "sha384.*TSIG.*NOERROR" dig.out.sha384 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha512"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha512:sha512:$sha512" @10.53.0.1 soa -p 5300 > dig.out.sha512 || ret=1
+grep -i "sha512.*TSIG.*NOERROR" dig.out.sha512 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+#
+#
+# Truncated TSIG
+#
+#
+echo "I:fetching using hmac-md5 (trunc)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-md5-80:md5-trunc:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5.trunc || ret=1
+grep -i "md5-trunc.*TSIG.*NOERROR" dig.out.md5.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha1 (trunc)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha1-80:sha1-trunc:$sha1" @10.53.0.1 soa -p 5300 > dig.out.sha1.trunc || ret=1
+grep -i "sha1.*TSIG.*NOERROR" dig.out.sha1.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha224 (trunc)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha224-112:sha224-trunc:$sha224" @10.53.0.1 soa -p 5300 > dig.out.sha224.trunc || ret=1
+grep -i "sha224-trunc.*TSIG.*NOERROR" dig.out.sha224.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha256 (trunc)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha256-128:sha256-trunc:$sha256" @10.53.0.1 soa -p 5300 > dig.out.sha256.trunc || ret=1
+grep -i "sha256-trunc.*TSIG.*NOERROR" dig.out.sha256.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha384 (trunc)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha384-192:sha384-trunc:$sha384" @10.53.0.1 soa -p 5300 > dig.out.sha384.trunc || ret=1
+grep -i "sha384-trunc.*TSIG.*NOERROR" dig.out.sha384.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha512-256 (trunc)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha512-256:sha512-trunc:$sha512" @10.53.0.1 soa -p 5300 > dig.out.sha512.trunc || ret=1
+grep -i "sha512-trunc.*TSIG.*NOERROR" dig.out.sha512.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+
+#
+#
+# Check for bad truncation.
+#
+#
+echo "I:fetching using hmac-md5-80 (BADTRUNC)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-md5-80:md5:$md5" @10.53.0.1 soa -p 5300 > dig.out.md5-80 || ret=1
+grep -i "md5.*TSIG.*BADTRUNC" dig.out.md5-80 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha1-80 (BADTRUNC)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha1-80:sha1:$sha1" @10.53.0.1 soa -p 5300 > dig.out.sha1-80 || ret=1
+grep -i "sha1.*TSIG.*BADTRUNC" dig.out.sha1-80 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha224-112 (BADTRUNC)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha224-112:sha224:$sha224" @10.53.0.1 soa -p 5300 > dig.out.sha224-112 || ret=1
+grep -i "sha224.*TSIG.*BADTRUNC" dig.out.sha224-112 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha256-128 (BADTRUNC)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha256-128:sha256:$sha256" @10.53.0.1 soa -p 5300 > dig.out.sha256-128 || ret=1
+grep -i "sha256.*TSIG.*BADTRUNC" dig.out.sha256-128 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha384-192 (BADTRUNC)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha384-192:sha384:$sha384" @10.53.0.1 soa -p 5300 > dig.out.sha384-192 || ret=1
+grep -i "sha384.*TSIG.*BADTRUNC" dig.out.sha384-192 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+echo "I:fetching using hmac-sha512-256 (BADTRUNC)"
+ret=0
+$DIG +tcp +nosea +nostat +noquest +nocomm +nocmd example.nil.\
+ -y "hmac-sha512-256:sha512:$sha512" @10.53.0.1 soa -p 5300 > dig.out.sha512-256 || ret=1
+grep -i "sha512.*TSIG.*BADTRUNC" dig.out.sha512-256 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo "I: failed"; status=1
+fi
+
+exit $status
+
+
diff --git a/bin/tests/system/unknown/clean.sh b/bin/tests/system/unknown/clean.sh
new file mode 100644
index 0000000..98acac5
--- /dev/null
+++ b/bin/tests/system/unknown/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.7 2007/09/26 03:22:44 marka Exp $
+
+rm -f dig.out
+rm -f */named.memstats
diff --git a/bin/tests/system/unknown/ns1/broken1.db b/bin/tests/system/unknown/ns1/broken1.db
new file mode 100644
index 0000000..657c75e
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken1.db
@@ -0,0 +1,29 @@
+; Copyright (C) 2004, 2007 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: broken1.db,v 1.5 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+a A \# 5 0A000001
diff --git a/bin/tests/system/unknown/ns1/broken2.db b/bin/tests/system/unknown/ns1/broken2.db
new file mode 100644
index 0000000..47e2942
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken2.db
@@ -0,0 +1,29 @@
+; Copyright (C) 2004, 2007 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: broken2.db,v 1.5 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+a A \# 4 0A00000100
diff --git a/bin/tests/system/unknown/ns1/broken3.db b/bin/tests/system/unknown/ns1/broken3.db
new file mode 100644
index 0000000..a292a4e
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken3.db
@@ -0,0 +1,29 @@
+; Copyright (C) 2004, 2007 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: broken3.db,v 1.5 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+a A \# 5 0A00000100
diff --git a/bin/tests/system/unknown/ns1/broken4.db b/bin/tests/system/unknown/ns1/broken4.db
new file mode 100644
index 0000000..9abb02b
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken4.db
@@ -0,0 +1,29 @@
+; Copyright (C) 2004, 2007 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: broken4.db,v 1.6 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+soa SOA \# 32 026E73013300 04726F6F74C4 00000001 00000001 00000001 00000001 00000001
diff --git a/bin/tests/system/unknown/ns1/broken5.db b/bin/tests/system/unknown/ns1/broken5.db
new file mode 100644
index 0000000..5501a77
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/broken5.db
@@ -0,0 +1,29 @@
+; Copyright (C) 2004, 2007 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: broken5.db,v 1.5 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+any TYPE255 \# 2 AB CD
diff --git a/bin/tests/system/unknown/ns1/class10.hints b/bin/tests/system/unknown/ns1/class10.hints
new file mode 100644
index 0000000..c283a31
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/class10.hints
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: class10.hints,v 1.5 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 3600
+. NS ns.
diff --git a/bin/tests/system/unknown/ns1/example-class10.db b/bin/tests/system/unknown/ns1/example-class10.db
new file mode 100644
index 0000000..834b558
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/example-class10.db
@@ -0,0 +1,37 @@
+; Copyright (C) 2004, 2007 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: example-class10.db,v 1.5 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+
+a1 A \# 4 0A000001
+a2 CLASS10 A \# 4 0A000001
+
+txt1 TXT \# 6 0568656C6C6F
+txt2 TXT "hello"
+txt3 CLASS10 TXT \# 6 0568656C6C6F
+txt4 CLASS10 TXT "hello"
+
+unk1 TYPE123 \# 1 00
+unk2 CLASS10 TYPE123 \# 1 00
diff --git a/bin/tests/system/unknown/ns1/example-in.db b/bin/tests/system/unknown/ns1/example-in.db
new file mode 100644
index 0000000..579bed8
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/example-in.db
@@ -0,0 +1,52 @@
+; Copyright (C) 2004, 2007 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: example-in.db,v 1.7 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 300 ; 5 minutes
+@ SOA mname1. . (
+ 2000062101 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+a1 A \# 4 0A000001
+a2 A \# 4 0A 00 00 01
+a3 CLASS1 A 10.0.0.1
+a4 CLASS1 A \# 4 0A000001
+a5 TYPE1 10.0.0.1
+a6 TYPE1 \# 4 0A000001
+a7 CLASS1 TYPE1 10.0.0.1
+a8 CLASS1 TYPE1 \# 4 0A000001
+a9 IN TYPE1 10.0.0.1
+a10 IN TYPE1 \# 4 0A000001
+a11 IN TYPE1 \# 4 0a000001
+a12 IN A \# 4 0A000001
+
+txt1 IN TXT "hello"
+txt2 CLASS1 TXT "hello"
+txt3 IN TYPE16 "hello"
+txt4 CLASS1 TYPE16 "hello"
+txt5 TXT \# 6 0568656C6C6F
+txt6 TYPE16 \# 6 0568656C6C6F
+txt7 IN TXT \# 6 0568656C6C6F
+
+unk1 TYPE123 \# 1 00
+unk2 CLASS1 TYPE123 \# 1 00
+unk3 IN TYPE123 \# 1 00
diff --git a/bin/tests/system/unknown/ns1/named.conf b/bin/tests/system/unknown/ns1/named.conf
new file mode 100644
index 0000000..be3b57e
--- /dev/null
+++ b/bin/tests/system/unknown/ns1/named.conf
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.11 2007/06/19 23:47:06 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+};
+
+view "in" {
+ zone "example." {
+ type master;
+ file "example-in.db";
+ };
+
+ zone "broken1." {
+ type master;
+ file "broken1.db";
+ };
+
+ zone "broken2." {
+ type master;
+ file "broken2.db";
+ };
+
+ zone "broken3." {
+ type master;
+ file "broken3.db";
+ };
+
+ zone "broken4." {
+ type master;
+ file "broken4.db";
+ };
+
+ zone "broken5." {
+ type master;
+ file "broken5.db";
+ };
+};
+
+view "class10" class10 {
+ zone "." class10 {
+ type hint;
+ file "class10.hints";
+ };
+
+ zone "example." class10 {
+ type master;
+ file "example-class10.db";
+ };
+};
diff --git a/bin/tests/system/unknown/tests.sh b/bin/tests/system/unknown/tests.sh
new file mode 100644
index 0000000..c234178
--- /dev/null
+++ b/bin/tests/system/unknown/tests.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.10 2007/06/19 23:47:06 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+DIGOPTS="@10.53.0.1 -p 5300"
+
+echo "I:querying for various representations of an IN A record"
+for i in 1 2 3 4 5 6 7 8 9 10 11 12
+do
+ ret=0
+ $DIG +short $DIGOPTS a$i.example a in > dig.out || ret=1
+ echo 10.0.0.1 | diff - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo "I:querying for various representations of an IN TXT record"
+for i in 1 2 3 4 5 6 7
+do
+ ret=0
+ $DIG +short $DIGOPTS txt$i.example txt in > dig.out || ret=1
+ echo '"hello"' | diff - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo "I:querying for various representations of an IN TYPE123 record"
+for i in 1 2 3
+do
+ ret=0
+ $DIG +short $DIGOPTS unk$i.example type123 in > dig.out || ret=1
+ echo '\# 1 00' | diff - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo "I:querying for various representations of a CLASS10 TYPE1 record"
+for i in 1 2
+do
+ ret=0
+ $DIG +short $DIGOPTS a$i.example a class10 > dig.out || ret=1
+ echo '\# 4 0A000001' | diff - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo "I:querying for various representations of a CLASS10 TXT record"
+for i in 1 2 3 4
+do
+ ret=0
+ $DIG +short $DIGOPTS txt$i.example txt class10 > dig.out || ret=1
+ echo '"hello"' | diff - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo "I:querying for various representations of a CLASS10 TYPE123 record"
+for i in 1 2
+do
+ ret=0
+ $DIG +short $DIGOPTS unk$i.example type123 class10 > dig.out || ret=1
+ echo '\# 1 00' | diff - dig.out || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo "I:querying for SOAs of zone that should have failed to load"
+for i in 1 2 3 4
+do
+ ret=0
+ $DIG $DIGOPTS broken$i. soa in > dig.out || ret=1
+ grep "SERVFAIL" dig.out > /dev/null || ret=1
+ if [ $ret != 0 ]
+ then
+ echo "#$i failed"
+ fi
+ status=`expr $status + $ret`
+done
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/upforwd/clean.sh b/bin/tests/system/upforwd/clean.sh
new file mode 100644
index 0000000..5d4054e
--- /dev/null
+++ b/bin/tests/system/upforwd/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.9 2007/09/26 03:22:44 marka Exp $
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f dig.out.ns1 dig.out.ns2 dig.out.ns1 dig.out.ns3 dig.out.ns1.after
+rm -f ns1/*.jnl ns2/*.jnl ns3/*.jnl ns1/example.db ns2/*.bk ns3/*.bk
+rm -f */named.memstats
diff --git a/bin/tests/system/upforwd/knowngood.after1 b/bin/tests/system/upforwd/knowngood.after1
new file mode 100644
index 0000000..7fc424c
--- /dev/null
+++ b/bin/tests/system/upforwd/knowngood.after1
@@ -0,0 +1,10 @@
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 2 3600 1200 604800 7200
+example. 3600 IN NS ns2.example.
+example. 3600 IN NS ns3.example.
+ns1.example. 3600 IN A 10.53.0.1
+ns2.example. 3600 IN A 10.53.0.2
+ns3.example. 3600 IN A 10.53.0.3
+updated.example. 600 IN TXT "Foo"
+updated.example. 600 IN A 10.10.10.1
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 2 3600 1200 604800 7200
+
diff --git a/bin/tests/system/upforwd/knowngood.after2 b/bin/tests/system/upforwd/knowngood.after2
new file mode 100644
index 0000000..eab7a2c
--- /dev/null
+++ b/bin/tests/system/upforwd/knowngood.after2
@@ -0,0 +1,11 @@
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 3 3600 1200 604800 7200
+example. 3600 IN NS ns2.example.
+example. 3600 IN NS ns3.example.
+ns1.example. 3600 IN A 10.53.0.1
+ns2.example. 3600 IN A 10.53.0.2
+ns3.example. 3600 IN A 10.53.0.3
+unsigned.example. 600 IN TXT "Foo"
+unsigned.example. 600 IN A 10.10.10.1
+updated.example. 600 IN TXT "Foo"
+updated.example. 600 IN A 10.10.10.1
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 3 3600 1200 604800 7200
diff --git a/bin/tests/system/upforwd/knowngood.before b/bin/tests/system/upforwd/knowngood.before
new file mode 100644
index 0000000..4bde819
--- /dev/null
+++ b/bin/tests/system/upforwd/knowngood.before
@@ -0,0 +1,8 @@
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 1 3600 1200 604800 7200
+example. 3600 IN NS ns2.example.
+example. 3600 IN NS ns3.example.
+ns1.example. 3600 IN A 10.53.0.1
+ns2.example. 3600 IN A 10.53.0.2
+ns3.example. 3600 IN A 10.53.0.3
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 1 3600 1200 604800 7200
+
diff --git a/bin/tests/system/upforwd/knowngood.ns2.before b/bin/tests/system/upforwd/knowngood.ns2.before
new file mode 100644
index 0000000..bb3c355
--- /dev/null
+++ b/bin/tests/system/upforwd/knowngood.ns2.before
@@ -0,0 +1,6 @@
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 1 3600 1200 604800 7200
+example. 3600 IN NS ns2.example.
+ns1.example. 3600 IN A 10.53.0.1
+ns2.example. 3600 IN A 10.53.0.2
+example. 3600 IN SOA n1.example. hostmaster.ns1.example. 1 3600 1200 604800 7200
+
diff --git a/bin/tests/system/upforwd/ns1/example1.db b/bin/tests/system/upforwd/ns1/example1.db
new file mode 100644
index 0000000..940b9fd
--- /dev/null
+++ b/bin/tests/system/upforwd/ns1/example1.db
@@ -0,0 +1,24 @@
+; Copyright (C) 2004, 2007 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: example1.db,v 1.4 2007/06/19 23:47:06 tbox Exp $
+
+@ 3600 SOA n1.example. hostmaster.ns1.example. (
+ 1 3600 1200 604800 7200 )
+ NS ns2.example.
+ NS ns3.example.
+ns1 A 10.53.0.1
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
diff --git a/bin/tests/system/upforwd/ns1/named.conf b/bin/tests/system/upforwd/ns1/named.conf
new file mode 100644
index 0000000..8d9d2fa
--- /dev/null
+++ b/bin/tests/system/upforwd/ns1/named.conf
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.11 2007/06/18 23:47:31 tbox Exp $ */
+
+key "update.example." {
+ algorithm "hmac-md5";
+ secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
+};
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ allow-update { key update.example.; 10.53.0.3; };
+};
diff --git a/bin/tests/system/upforwd/ns2/named.conf b/bin/tests/system/upforwd/ns2/named.conf
new file mode 100644
index 0000000..57ad4b0
--- /dev/null
+++ b/bin/tests/system/upforwd/ns2/named.conf
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.10 2007/06/18 23:47:31 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "example" {
+ type slave;
+ file "example.bk";
+ masters { 10.53.0.1; };
+};
diff --git a/bin/tests/system/upforwd/ns3/named.conf b/bin/tests/system/upforwd/ns3/named.conf
new file mode 100644
index 0000000..b1fe854
--- /dev/null
+++ b/bin/tests/system/upforwd/ns3/named.conf
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.10 2007/06/18 23:47:31 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "example" {
+ type slave;
+ file "example.bk";
+ allow-update-forwarding { any; };
+ masters { 10.53.0.1; };
+};
diff --git a/bin/tests/system/upforwd/setup.sh b/bin/tests/system/upforwd/setup.sh
new file mode 100644
index 0000000..21a0e36
--- /dev/null
+++ b/bin/tests/system/upforwd/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.8 2007/06/19 23:47:06 tbox Exp $
+
+cp -f ns1/example1.db ns1/example.db
+rm -f ns1/example.db.jnl ns2/example.bk ns2/example.bk.jnl
diff --git a/bin/tests/system/upforwd/tests.sh b/bin/tests/system/upforwd/tests.sh
new file mode 100644
index 0000000..81156c8
--- /dev/null
+++ b/bin/tests/system/upforwd/tests.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.10 2007/06/19 23:47:06 tbox Exp $
+
+# ns1 = stealth master
+# ns2 = slave with update forwarding disabled; not currently used
+# ns3 = slave with update forwarding enabled
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+echo "I:fetching master copy of zone before update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.\
+ @10.53.0.1 axfr -p 5300 > dig.out.ns1 || status=1
+
+echo "I:fetching slave 1 copy of zone before update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.\
+ @10.53.0.2 axfr -p 5300 > dig.out.ns2 || status=1
+
+echo "I:fetching slave 2 copy of zone before update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.\
+ @10.53.0.3 axfr -p 5300 > dig.out.ns3 || status=1
+
+echo "I:comparing pre-update copies to known good data"
+$PERL ../digcomp.pl knowngood.before dig.out.ns1 || status=1
+$PERL ../digcomp.pl knowngood.before dig.out.ns2 || status=1
+$PERL ../digcomp.pl knowngood.before dig.out.ns3 || status=1
+
+echo "I:updating zone (signed)"
+$NSUPDATE -y update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K -- - <<EOF || status=1
+server 10.53.0.3 5300
+update add updated.example. 600 A 10.10.10.1
+update add updated.example. 600 TXT Foo
+send
+EOF
+
+echo "I:sleeping 15 seconds for server to incorporate changes"
+sleep 15
+
+echo "I:fetching master copy of zone after update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.\
+ @10.53.0.1 axfr -p 5300 > dig.out.ns1 || status=1
+
+echo "I:fetching slave 1 copy of zone after update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.\
+ @10.53.0.2 axfr -p 5300 > dig.out.ns2 || status=1
+
+echo "I:fetching slave 2 copy of zone after update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.\
+ @10.53.0.3 axfr -p 5300 > dig.out.ns3 || status=1
+
+echo "I:comparing post-update copies to known good data"
+$PERL ../digcomp.pl knowngood.after1 dig.out.ns1 || status=1
+$PERL ../digcomp.pl knowngood.after1 dig.out.ns2 || status=1
+$PERL ../digcomp.pl knowngood.after1 dig.out.ns3 || status=1
+
+echo "I:updating zone (unsigned)"
+$NSUPDATE -- - <<EOF || status=1
+server 10.53.0.3 5300
+update add unsigned.example. 600 A 10.10.10.1
+update add unsigned.example. 600 TXT Foo
+send
+EOF
+
+echo "I:sleeping 15 seconds for server to incorporate changes"
+sleep 15
+
+echo "I:fetching master copy of zone after update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.\
+ @10.53.0.1 axfr -p 5300 > dig.out.ns1 || status=1
+
+echo "I:fetching slave 1 copy of zone after update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.\
+ @10.53.0.2 axfr -p 5300 > dig.out.ns2 || status=1
+
+echo "I:fetching slave 2 copy of zone after update"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.\
+ @10.53.0.3 axfr -p 5300 > dig.out.ns3 || status=1
+
+echo "I:comparing post-update copies to known good data"
+$PERL ../digcomp.pl knowngood.after2 dig.out.ns1 || status=1
+$PERL ../digcomp.pl knowngood.after2 dig.out.ns2 || status=1
+$PERL ../digcomp.pl knowngood.after2 dig.out.ns3 || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/v6synth/clean.sh b/bin/tests/system/v6synth/clean.sh
new file mode 100644
index 0000000..5f9157b
--- /dev/null
+++ b/bin/tests/system/v6synth/clean.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# 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: clean.sh,v 1.5 2007/09/26 03:22:44 marka Exp $
+
+rm -f *.out
+rm -f */named.memstats
diff --git a/bin/tests/system/v6synth/ns1/named.conf b/bin/tests/system/v6synth/ns1/named.conf
new file mode 100644
index 0000000..fdf7e56
--- /dev/null
+++ b/bin/tests/system/v6synth/ns1/named.conf
@@ -0,0 +1,37 @@
+/*
+ * 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: named.conf,v 1.5 2007/06/19 23:47:06 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/v6synth/ns1/root.db b/bin/tests/system/v6synth/ns1/root.db
new file mode 100644
index 0000000..0208038
--- /dev/null
+++ b/bin/tests/system/v6synth/ns1/root.db
@@ -0,0 +1,33 @@
+; 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: root.db,v 1.4 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+ip6.int. NS ns2.example.
+ip6.arpa. NS ns2.example.
diff --git a/bin/tests/system/v6synth/ns2/example.db b/bin/tests/system/v6synth/ns2/example.db
new file mode 100644
index 0000000..120b87d
--- /dev/null
+++ b/bin/tests/system/v6synth/ns2/example.db
@@ -0,0 +1,38 @@
+; 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: example.db,v 1.4 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 86400
+@ IN SOA ns2 hostmaster (
+ 2001010604 3600 1800 1814400 3600 )
+ NS ns2.example.
+ns2.example. A 10.53.0.2
+
+a A 10.0.0.1
+aaaa AAAA 12:34:56::ff
+a6 A6 0 12:34:56::ff
+chain A6 64 0::ff:ff prefix
+prefix A6 0 12:34:56::0
+alias CNAME chain
+alias2 CNAME alias
+dname DNAME foo
+
+loop CNAME loop
+
+loop2 CNAME loop3
+loop3 CNAME loop2
+
+aaaa.foo AAAA 12:34:56::ff
diff --git a/bin/tests/system/v6synth/ns2/ip6.arpa.db b/bin/tests/system/v6synth/ns2/ip6.arpa.db
new file mode 100644
index 0000000..c99c8d9
--- /dev/null
+++ b/bin/tests/system/v6synth/ns2/ip6.arpa.db
@@ -0,0 +1,24 @@
+; Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+; Copyright (C) 2001, 2002 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: ip6.arpa.db,v 1.5 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 86400
+@ IN SOA ns2 hostmaster (
+ 2001010604 3600 1800 1814400 3600 )
+ NS ns2.example.
+ns2.example. A 10.53.0.2
+
+f.f.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.5.4.3.2.1 PTR foo.
diff --git a/bin/tests/system/v6synth/ns2/ip6.int.db b/bin/tests/system/v6synth/ns2/ip6.int.db
new file mode 100644
index 0000000..374e02a
--- /dev/null
+++ b/bin/tests/system/v6synth/ns2/ip6.int.db
@@ -0,0 +1,24 @@
+; 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: ip6.int.db,v 1.4 2007/06/19 23:47:06 tbox Exp $
+
+$TTL 86400
+@ IN SOA ns2 hostmaster (
+ 2001010604 3600 1800 1814400 3600 )
+ NS ns2.example.
+ns2.example. A 10.53.0.2
+
+f.f.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.5.4.3.2.1 PTR bar.
diff --git a/bin/tests/system/v6synth/ns2/named.conf b/bin/tests/system/v6synth/ns2/named.conf
new file mode 100644
index 0000000..1eb6d33
--- /dev/null
+++ b/bin/tests/system/v6synth/ns2/named.conf
@@ -0,0 +1,49 @@
+/*
+ * 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: named.conf,v 1.6 2007/06/18 23:47:31 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "ip6.int" {
+ type master;
+ file "ip6.int.db";
+};
+
+zone "ip6.arpa" {
+ type master;
+ file "ip6.arpa.db";
+};
+
diff --git a/bin/tests/system/v6synth/ns3/named.conf b/bin/tests/system/v6synth/ns3/named.conf
new file mode 100644
index 0000000..bacaab7
--- /dev/null
+++ b/bin/tests/system/v6synth/ns3/named.conf
@@ -0,0 +1,39 @@
+/*
+ * 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: named.conf,v 1.6 2007/06/18 23:47:31 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+ allow-v6-synthesis { any; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
diff --git a/bin/tests/system/v6synth/tests.sh b/bin/tests/system/v6synth/tests.sh
new file mode 100644
index 0000000..8cc67f9
--- /dev/null
+++ b/bin/tests/system/v6synth/tests.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# 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: tests.sh,v 1.4 2007/06/19 23:47:06 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+# ns1 = root server
+# ns2 = authoritative server
+# ns3 = recursive server doing v6 synthesis
+
+status=0
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd"
+
+for name in aaaa a6 chain alias2 aaaa.dname loop loop2
+do
+ $DIG $DIGOPTS $name.example. aaaa @10.53.0.3 -p 5300
+ echo
+done >dig.out
+
+for i in 1 2
+do
+ $DIG $DIGOPTS f.f.$i.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.5.4.3.2.1.ip6.int. PTR @10.53.0.3 -p 5300
+ echo
+done >>dig.out
+
+cat <<EOF >good.out
+aaaa.example. 0 IN AAAA 12:34:56::ff
+
+a6.example. 0 IN AAAA 12:34:56::ff
+
+chain.example. 0 IN AAAA 12:34:56::ff:ff
+
+alias2.example. 0 IN CNAME alias.example.
+alias.example. 0 IN CNAME chain.example.
+chain.example. 0 IN AAAA 12:34:56::ff:ff
+
+aaaa.dname.example. 0 IN CNAME aaaa.foo.example.
+aaaa.foo.example. 0 IN AAAA 12:34:56::ff
+
+loop.example. 0 IN CNAME loop.example.
+
+loop2.example. 0 IN CNAME loop3.example.
+loop3.example. 0 IN CNAME loop2.example.
+
+f.f.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.5.4.3.2.1.ip6.int. 0 IN PTR foo.
+
+f.f.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.5.4.3.2.1.ip6.int. 0 IN PTR bar.
+
+EOF
+
+diff good.out dig.out || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/views/clean.sh b/bin/tests/system/views/clean.sh
new file mode 100644
index 0000000..1eebccf
--- /dev/null
+++ b/bin/tests/system/views/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2005, 2007 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: clean.sh,v 1.14 2007/09/26 03:22:44 marka Exp $
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f ns3/example.bk dig.out.ns?.?
+rm -f ns2/named.conf ns2/example.db ns3/named.conf ns3/internal.bk
+rm -f */named.memstats
diff --git a/bin/tests/system/views/ns1/named.conf b/bin/tests/system/views/ns1/named.conf
new file mode 100644
index 0000000..46a0a02
--- /dev/null
+++ b/bin/tests/system/views/ns1/named.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.17 2007/06/19 23:47:07 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/views/ns1/root.db b/bin/tests/system/views/ns1/root.db
new file mode 100644
index 0000000..683f585
--- /dev/null
+++ b/bin/tests/system/views/ns1/root.db
@@ -0,0 +1,30 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.9 2007/06/19 23:47:07 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
diff --git a/bin/tests/system/views/ns2/example1.db b/bin/tests/system/views/ns2/example1.db
new file mode 100644
index 0000000..c8d7ec8
--- /dev/null
+++ b/bin/tests/system/views/ns2/example1.db
@@ -0,0 +1,34 @@
+; Copyright (C) 2004, 2007 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: example1.db,v 1.9 2007/06/19 23:47:07 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+$ORIGIN example.
+a A 10.0.0.1
+ MX 10 mail.example.
+
+mail A 10.0.0.2
diff --git a/bin/tests/system/views/ns2/example2.db b/bin/tests/system/views/ns2/example2.db
new file mode 100644
index 0000000..d7ea37e
--- /dev/null
+++ b/bin/tests/system/views/ns2/example2.db
@@ -0,0 +1,34 @@
+; Copyright (C) 2004, 2007 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: example2.db,v 1.10 2007/06/19 23:47:07 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.4
+
+$ORIGIN example.
+a A 10.0.0.1
+ MX 10 mail.example.
+
+mail A 10.0.0.2
diff --git a/bin/tests/system/views/ns2/internal.db b/bin/tests/system/views/ns2/internal.db
new file mode 100644
index 0000000..1a97057
--- /dev/null
+++ b/bin/tests/system/views/ns2/internal.db
@@ -0,0 +1,36 @@
+; Copyright (C) 2004, 2007 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: internal.db,v 1.9 2007/06/19 23:47:07 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 2 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.1.0.1
+ MX 10 intmail.example.
+
+intmail A 10.1.0.2
diff --git a/bin/tests/system/views/ns2/named1.conf b/bin/tests/system/views/ns2/named1.conf
new file mode 100644
index 0000000..a09d069
--- /dev/null
+++ b/bin/tests/system/views/ns2/named1.conf
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2007 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: named1.conf,v 1.20 2007/06/19 23:47:07 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+include "../../common/controls.conf";
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+ allow-update { any; };
+};
diff --git a/bin/tests/system/views/ns2/named2.conf b/bin/tests/system/views/ns2/named2.conf
new file mode 100644
index 0000000..e4180f2
--- /dev/null
+++ b/bin/tests/system/views/ns2/named2.conf
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004, 2007 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: named2.conf,v 1.22 2007/06/19 23:47:07 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+include "../../common/controls.conf";
+
+view "internal" {
+ match-clients { 10.53.0.2;
+ 10.53.0.3; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "example" {
+ type master;
+ file "internal.db";
+ allow-update { any; };
+ };
+};
+
+view "external" {
+ match-clients { any; };
+
+ zone "." {
+ type hint;
+ file "../../common/root.hint";
+ };
+
+ zone "example" {
+ type master;
+ file "example.db";
+ };
+};
+
diff --git a/bin/tests/system/views/ns3/internal.db b/bin/tests/system/views/ns3/internal.db
new file mode 100644
index 0000000..3d33d7f
--- /dev/null
+++ b/bin/tests/system/views/ns3/internal.db
@@ -0,0 +1,34 @@
+; Copyright (C) 2004, 2007 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: internal.db,v 1.9 2007/06/19 23:47:07 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 1 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+a A 10.1.0.1
+ MX 10 intmail.example.
+
+intmail A 10.1.0.2
diff --git a/bin/tests/system/views/ns3/named1.conf b/bin/tests/system/views/ns3/named1.conf
new file mode 100644
index 0000000..9723e08
--- /dev/null
+++ b/bin/tests/system/views/ns3/named1.conf
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004, 2007 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: named1.conf,v 1.19 2007/06/19 23:47:07 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ allow-update { any; };
+ file "internal.db";
+};
+
+
diff --git a/bin/tests/system/views/ns3/named2.conf b/bin/tests/system/views/ns3/named2.conf
new file mode 100644
index 0000000..27d4955
--- /dev/null
+++ b/bin/tests/system/views/ns3/named2.conf
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004, 2007 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: named2.conf,v 1.19 2007/06/19 23:47:07 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ directory ".";
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.3 port 11953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type slave;
+ masters { 10.53.0.2; };
+ allow-update { any; };
+ file "internal.bk";
+};
diff --git a/bin/tests/system/views/setup.sh b/bin/tests/system/views/setup.sh
new file mode 100644
index 0000000..c572a87
--- /dev/null
+++ b/bin/tests/system/views/setup.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.10 2007/06/19 23:47:06 tbox Exp $
+
+
+cp -f ns2/example1.db ns2/example.db
+cp -f ns2/named1.conf ns2/named.conf
+cp -f ns3/named1.conf ns3/named.conf
diff --git a/bin/tests/system/views/tests.sh b/bin/tests/system/views/tests.sh
new file mode 100644
index 0000000..b6fb552
--- /dev/null
+++ b/bin/tests/system/views/tests.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.30 2007/06/19 23:47:06 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+echo "I:fetching a.example from ns2's initial configuration"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd +noauth \
+ a.example. @10.53.0.2 any -p 5300 > dig.out.ns2.1 || status=1
+grep ";" dig.out.ns2.1 # XXXDCL why is this here?
+
+echo "I:fetching a.example from ns3's initial configuration"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd +noauth \
+ a.example. @10.53.0.3 any -p 5300 > dig.out.ns3.1 || status=1
+grep ";" dig.out.ns3.1 # XXXDCL why is this here?
+
+echo "I:copying in new configurations for ns2 and ns3"
+rm -f ns2/named.conf ns3/named.conf ns2/example.db
+cp -f ns2/named2.conf ns2/named.conf
+cp -f ns3/named2.conf ns3/named.conf
+cp -f ns2/example2.db ns2/example.db
+
+echo "I:reloading ns2 and ns3 with rndc"
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reload 2>&1 | sed 's/^/I:ns3 /'
+
+echo "I:sleeping for 20 seconds"
+sleep 20
+
+echo "I:fetching a.example from ns2's 10.53.0.4, source address 10.53.0.4"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd +noauth \
+ -b 10.53.0.4 a.example. @10.53.0.4 any -p 5300 > dig.out.ns4.2 \
+ || status=1
+grep ";" dig.out.ns4.2 # XXXDCL why is this here?
+
+echo "I:fetching a.example from ns2's 10.53.0.2, source address 10.53.0.2"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd +noauth \
+ -b 10.53.0.2 a.example. @10.53.0.2 any -p 5300 > dig.out.ns2.2 \
+ || status=1
+grep ";" dig.out.ns2.2 # XXXDCL why is this here?
+
+echo "I:fetching a.example from ns3's 10.53.0.3, source address defaulted"
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd +noauth \
+ @10.53.0.3 a.example. any -p 5300 > dig.out.ns3.2 || status=1
+grep ";" dig.out.ns3.2 # XXXDCL why is this here?
+
+echo "I:comparing ns3's initial a.example to one from reconfigured 10.53.0.2"
+$PERL ../digcomp.pl dig.out.ns3.1 dig.out.ns2.2 || status=1
+
+echo "I:comparing ns3's initial a.example to one from reconfigured 10.53.0.3"
+$PERL ../digcomp.pl dig.out.ns3.1 dig.out.ns3.2 || status=1
+
+echo "I:comparing ns2's initial a.example to one from reconfigured 10.53.0.4"
+$PERL ../digcomp.pl dig.out.ns2.1 dig.out.ns4.2 || status=1
+
+echo "I:comparing ns2's initial a.example to one from reconfigured 10.53.0.3"
+echo "I:(should be different)"
+if $PERL ../digcomp.pl dig.out.ns2.1 dig.out.ns3.2 >/dev/null
+then
+ echo "I:no differences found. something's wrong."
+ status=1
+fi
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/xfer/clean.sh b/bin/tests/system/xfer/clean.sh
new file mode 100644
index 0000000..132530a
--- /dev/null
+++ b/bin/tests/system/xfer/clean.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.14 2007/09/26 03:22:44 marka Exp $
+
+#
+# Clean up after zone transfer tests.
+#
+
+rm -f dig.out.ns2 dig.out.ns3
+rm -f ns2/example.db ns2/tsigzone.db ns2/example.db.jnl
+rm -f ns3/example.bk ns3/tsigzone.bk ns3/example.bk.jnl
+rm -f */named.memstats
diff --git a/bin/tests/system/xfer/dig1.good b/bin/tests/system/xfer/dig1.good
new file mode 100644
index 0000000..b7f3f79
--- /dev/null
+++ b/bin/tests/system/xfer/dig1.good
@@ -0,0 +1,80 @@
+example. 86400 IN SOA ns2.example. hostmaster.example. 1397051952 5 5 1814400 3600
+example. 3600 IN NS ns2.example.
+example. 3600 IN NS ns3.example.
+a01.example. 3600 IN A 0.0.0.0
+a02.example. 3600 IN A 255.255.255.255
+a601.example. 3600 IN A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+a601.example. 3600 IN A6 64 ::ffff:ffff:ffff:ffff foo.
+a601.example. 3600 IN A6 127 ::1 foo.
+a601.example. 3600 IN A6 128 .
+afsdb01.example. 3600 IN AFSDB 0 hostname.example.
+afsdb02.example. 3600 IN AFSDB 65535 .
+cert01.example. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+cname01.example. 3600 IN CNAME cname-target.
+cname02.example. 3600 IN CNAME cname-target.example.
+cname03.example. 3600 IN CNAME .
+dname01.example. 3600 IN DNAME dname-target.
+dname02.example. 3600 IN DNAME dname-target.example.
+dname03.example. 3600 IN DNAME .
+gpos01.example. 3600 IN GPOS "-22.6882" "116.8652" "250.0"
+gpos02.example. 3600 IN GPOS "" "" ""
+hinfo01.example. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02.example. 3600 IN HINFO "PC" "NetBSD"
+isdn01.example. 3600 IN ISDN "isdn-address"
+isdn02.example. 3600 IN ISDN "isdn-address" "subaddress"
+isdn03.example. 3600 IN ISDN "isdn-address"
+isdn04.example. 3600 IN ISDN "isdn-address" "subaddress"
+dnskey01.example. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+kx01.example. 3600 IN KX 10 kdc.example.
+kx02.example. 3600 IN KX 10 .
+loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01.example. 3600 IN MG madname.example.
+mb02.example. 3600 IN MG .
+mg01.example. 3600 IN MG mgmname.example.
+mg02.example. 3600 IN MG .
+minfo01.example. 3600 IN MINFO rmailbx.example. emailbx.example.
+minfo02.example. 3600 IN MINFO . .
+mr01.example. 3600 IN MR mrname.example.
+mr02.example. 3600 IN MR .
+mx01.example. 3600 IN MX 10 mail.example.
+mx02.example. 3600 IN MX 10 .
+naptr01.example. 3600 IN NAPTR 0 0 "" "" "" .
+naptr02.example. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+ns2.example. 3600 IN A 10.53.0.2
+ns3.example. 3600 IN A 10.53.0.3
+nsap-ptr01.example. 3600 IN NSAP-PTR .
+nsap-ptr01.example. 3600 IN NSAP-PTR foo.
+nsap01.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsec01.example. 3600 IN NSEC a.secure.nil. NS SOA MX LOC RRSIG NSEC DNSKEY
+nsec02.example. 3600 IN NSEC . NSAP-PTR NSEC
+nsec03.example. 3600 IN NSEC . A
+nsec04.example. 3600 IN NSEC . TYPE127
+ptr01.example. 3600 IN PTR example.
+px01.example. 3600 IN PX 65535 foo. bar.
+px02.example. 3600 IN PX 65535 . .
+rp01.example. 3600 IN RP mbox-dname.example. txt-dname.example.
+rp02.example. 3600 IN RP . .
+rt01.example. 3600 IN RT 0 intermediate-host.example.
+rt02.example. 3600 IN RT 65535 .
+rrsig01.example. 3600 IN RRSIG NSEC 1 3 3600 20000102030405 19961211100908 2143 foo.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+srv01.example. 3600 IN SRV 0 0 0 .
+srv02.example. 3600 IN SRV 65535 65535 65535 old-slow-box.example.
+txt01.example. 3600 IN TXT "foo"
+txt02.example. 3600 IN TXT "foo" "bar"
+txt03.example. 3600 IN TXT "foo"
+txt04.example. 3600 IN TXT "foo" "bar"
+txt05.example. 3600 IN TXT "foo bar"
+txt06.example. 3600 IN TXT "foo bar"
+txt07.example. 3600 IN TXT "foo bar"
+txt08.example. 3600 IN TXT "foo\010bar"
+txt09.example. 3600 IN TXT "foo\010bar"
+txt10.example. 3600 IN TXT "foo bar"
+txt11.example. 3600 IN TXT "\"foo\""
+txt12.example. 3600 IN TXT "\"foo\""
+wks01.example. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23
+wks02.example. 3600 IN WKS 10.0.0.1 17 0 1 2 53
+wks03.example. 3600 IN WKS 10.0.0.2 6 65535
+x2501.example. 3600 IN X25 "123456789"
+example. 86400 IN SOA ns2.example. hostmaster.example. 1397051952 5 5 1814400 3600
diff --git a/bin/tests/system/xfer/dig2.good b/bin/tests/system/xfer/dig2.good
new file mode 100644
index 0000000..9f2cece
--- /dev/null
+++ b/bin/tests/system/xfer/dig2.good
@@ -0,0 +1,80 @@
+example. 86400 IN SOA ns2.example. hostmaster.example. 1397051953 5 5 1814400 3600
+example. 3600 IN NS ns2.example.
+example. 3600 IN NS ns3.example.
+a01.example. 3600 IN A 0.0.0.1
+a02.example. 3600 IN A 255.255.255.255
+a601.example. 3600 IN A6 0 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+a601.example. 3600 IN A6 64 ::ffff:ffff:ffff:ffff foo.
+a601.example. 3600 IN A6 127 ::1 foo.
+a601.example. 3600 IN A6 128 .
+afsdb01.example. 3600 IN AFSDB 0 hostname.example.
+afsdb02.example. 3600 IN AFSDB 65535 .
+cert01.example. 3600 IN CERT 65534 65535 PRIVATEOID MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+cname01.example. 3600 IN CNAME cname-target.
+cname02.example. 3600 IN CNAME cname-target.example.
+cname03.example. 3600 IN CNAME .
+dname01.example. 3600 IN DNAME dname-target.
+dname02.example. 3600 IN DNAME dname-target.example.
+dname03.example. 3600 IN DNAME .
+gpos01.example. 3600 IN GPOS "-22.6882" "116.8652" "250.0"
+gpos02.example. 3600 IN GPOS "" "" ""
+hinfo01.example. 3600 IN HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02.example. 3600 IN HINFO "PC" "NetBSD"
+isdn01.example. 3600 IN ISDN "isdn-address"
+isdn02.example. 3600 IN ISDN "isdn-address" "subaddress"
+isdn03.example. 3600 IN ISDN "isdn-address"
+isdn04.example. 3600 IN ISDN "isdn-address" "subaddress"
+dnskey01.example. 3600 IN DNSKEY 512 255 1 AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aRyzWZriO6i2od GWWQVucZqKVsENW91IOW4vqudngPZsY3GvQ/xVA8/7pyFj6b7Esga60z yGW6LFe9r8n6paHrlG5ojqf0BaqHT+8=
+kx01.example. 3600 IN KX 10 kdc.example.
+kx02.example. 3600 IN KX 10 .
+loc01.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02.example. 3600 IN LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01.example. 3600 IN MG madname.example.
+mb02.example. 3600 IN MG .
+mg01.example. 3600 IN MG mgmname.example.
+mg02.example. 3600 IN MG .
+minfo01.example. 3600 IN MINFO rmailbx.example. emailbx.example.
+minfo02.example. 3600 IN MINFO . .
+mr01.example. 3600 IN MR mrname.example.
+mr02.example. 3600 IN MR .
+mx01.example. 3600 IN MX 10 mail.example.
+mx02.example. 3600 IN MX 10 .
+naptr01.example. 3600 IN NAPTR 0 0 "" "" "" .
+naptr02.example. 3600 IN NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+ns2.example. 3600 IN A 10.53.0.2
+ns3.example. 3600 IN A 10.53.0.3
+nsap-ptr01.example. 3600 IN NSAP-PTR .
+nsap-ptr01.example. 3600 IN NSAP-PTR foo.
+nsap01.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02.example. 3600 IN NSAP 0x47000580005a0000000001e133ffffff00016100
+nsec01.example. 3600 IN NSEC a.secure.nil. NS SOA MX LOC RRSIG NSEC DNSKEY
+nsec02.example. 3600 IN NSEC . NSAP-PTR NSEC
+nsec03.example. 3600 IN NSEC . A
+nsec04.example. 3600 IN NSEC . TYPE127
+ptr01.example. 3600 IN PTR example.
+px01.example. 3600 IN PX 65535 foo. bar.
+px02.example. 3600 IN PX 65535 . .
+rp01.example. 3600 IN RP mbox-dname.example. txt-dname.example.
+rp02.example. 3600 IN RP . .
+rt01.example. 3600 IN RT 0 intermediate-host.example.
+rt02.example. 3600 IN RT 65535 .
+rrsig01.example. 3600 IN RRSIG NSEC 1 3 3600 20000102030405 19961211100908 2143 foo.nil. MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6V AuHAoNUz4YoU1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY=
+srv01.example. 3600 IN SRV 0 0 0 .
+srv02.example. 3600 IN SRV 65535 65535 65535 old-slow-box.example.
+txt01.example. 3600 IN TXT "foo"
+txt02.example. 3600 IN TXT "foo" "bar"
+txt03.example. 3600 IN TXT "foo"
+txt04.example. 3600 IN TXT "foo" "bar"
+txt05.example. 3600 IN TXT "foo bar"
+txt06.example. 3600 IN TXT "foo bar"
+txt07.example. 3600 IN TXT "foo bar"
+txt08.example. 3600 IN TXT "foo\010bar"
+txt09.example. 3600 IN TXT "foo\010bar"
+txt10.example. 3600 IN TXT "foo bar"
+txt11.example. 3600 IN TXT "\"foo\""
+txt12.example. 3600 IN TXT "\"foo\""
+wks01.example. 3600 IN WKS 10.0.0.1 6 0 1 2 21 23
+wks02.example. 3600 IN WKS 10.0.0.1 17 0 1 2 53
+wks03.example. 3600 IN WKS 10.0.0.2 6 65535
+x2501.example. 3600 IN X25 "123456789"
+example. 86400 IN SOA ns2.example. hostmaster.example. 1397051953 5 5 1814400 3600
diff --git a/bin/tests/system/xfer/ns1/named.conf b/bin/tests/system/xfer/ns1/named.conf
new file mode 100644
index 0000000..4c945ca
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/named.conf
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.18 2007/06/19 23:47:07 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
diff --git a/bin/tests/system/xfer/ns1/root.db b/bin/tests/system/xfer/ns1/root.db
new file mode 100644
index 0000000..ee1e74b
--- /dev/null
+++ b/bin/tests/system/xfer/ns1/root.db
@@ -0,0 +1,33 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.10 2007/06/19 23:47:07 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+tsigzone. NS ns2.tsigzone.
+ns2.tsigzone. A 10.53.0.2
diff --git a/bin/tests/system/xfer/ns2/named.conf b/bin/tests/system/xfer/ns2/named.conf
new file mode 100644
index 0000000..53a64ab
--- /dev/null
+++ b/bin/tests/system/xfer/ns2/named.conf
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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.conf,v 1.24 2007/12/20 01:48:29 marka Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ ixfr-from-differences yes;
+ check-integrity no;
+};
+
+include "../../common/controls.conf";
+
+key tsigzone. {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+acl tzkey {
+ key tsigzone.;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type master;
+ file "example.db";
+};
+
+zone "tsigzone" {
+ type master;
+ file "tsigzone.db";
+ allow-transfer { tzkey; };
+};
diff --git a/bin/tests/system/xfer/ns3/named.conf b/bin/tests/system/xfer/ns3/named.conf
new file mode 100644
index 0000000..2dd1254
--- /dev/null
+++ b/bin/tests/system/xfer/ns3/named.conf
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.21 2007/06/18 23:47:32 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ notify yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.3 port 9953 allow { any; } keys { rndc_key; };
+};
+
+key tsigzone. {
+ algorithm hmac-md5;
+ secret "1234abcd8765";
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "example" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "example.bk";
+};
+
+server 10.53.0.2 {
+ keys { tsigzone.; };
+};
+
+zone "tsigzone" {
+ type slave;
+ masters { 10.53.0.2; };
+ file "tsigzone.bk";
+ allow-transfer { key tsigzone.; };
+};
+
+
diff --git a/bin/tests/system/xfer/setup.sh b/bin/tests/system/xfer/setup.sh
new file mode 100644
index 0000000..8faadcb
--- /dev/null
+++ b/bin/tests/system/xfer/setup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2001, 2002 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: setup.sh,v 1.5 2007/06/19 23:47:07 tbox Exp $
+
+sh ../genzone.sh 2 3 >ns2/example.db
+sh ../genzone.sh 2 3 >ns2/tsigzone.db
diff --git a/bin/tests/system/xfer/tests.sh b/bin/tests/system/xfer/tests.sh
new file mode 100644
index 0000000..3356f81
--- /dev/null
+++ b/bin/tests/system/xfer/tests.sh
@@ -0,0 +1,102 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2005, 2007 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: tests.sh,v 1.31 2007/06/19 23:47:07 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd"
+
+status=0
+
+echo "I:testing basic zone transfer functionality"
+$DIG $DIGOPTS example. \
+ @10.53.0.2 axfr -p 5300 > dig.out.ns2 || status=1
+grep ";" dig.out.ns2
+
+#
+# Spin to allow the zone to tranfer.
+#
+for i in 1 2 3 4 5
+do
+tmp=0
+$DIG $DIGOPTS example. \
+ @10.53.0.3 axfr -p 5300 > dig.out.ns3 || tmp=1
+ grep ";" dig.out.ns3 > /dev/null
+ if test $? -ne 0 ; then break; fi
+ echo "I: plain zone re-transfer"
+ sleep 5
+done
+if test $tmp -eq 1 ; then status=1; fi
+grep ";" dig.out.ns3
+
+$PERL ../digcomp.pl dig1.good dig.out.ns2 || status=1
+
+$PERL ../digcomp.pl dig1.good dig.out.ns3 || status=1
+
+echo "I:testing TSIG signed zone transfers"
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.2 axfr -y tsigzone.:1234abcd8765 -p 5300 \
+ > dig.out.ns2 || status=1
+grep ";" dig.out.ns2
+
+#
+# Spin to allow the zone to tranfer.
+#
+for i in 1 2 3 4 5
+do
+tmp=0
+$DIG $DIGOPTS tsigzone. \
+ @10.53.0.3 axfr -y tsigzone.:1234abcd8765 -p 5300 \
+ > dig.out.ns3 || tmp=1
+ grep ";" dig.out.ns3 > /dev/null
+ if test $? -ne 0 ; then break; fi
+ echo "I: plain zone re-transfer"
+ sleep 5
+done
+if test $tmp -eq 1 ; then status=1; fi
+grep ";" dig.out.ns3
+
+$PERL ../digcomp.pl dig.out.ns2 dig.out.ns3 || status=1
+
+echo "I:testing ixfr-from-differences"
+
+$PERL -i -p -e '
+ s/0\.0\.0\.0/0.0.0.1/;
+ s/1397051952/1397051953/
+' ns2/example.db
+
+$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 reload 2>&1 | sed 's/^/I:ns2 /'
+
+sleep 5
+
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reload 2>&1 | sed 's/^/I:ns3 /'
+
+sleep 5
+
+$DIG $DIGOPTS example. \
+ @10.53.0.3 axfr -p 5300 > dig.out.ns3 || status=1
+grep ";" dig.out.ns3
+
+$PERL ../digcomp.pl dig2.good dig.out.ns3 || status=1
+
+# ns3 has a journal iff it received an IXFR.
+test -f ns3/example.bk.jnl || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/xferquota/clean.sh b/bin/tests/system/xferquota/clean.sh
new file mode 100644
index 0000000..9ca8830
--- /dev/null
+++ b/bin/tests/system/xferquota/clean.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.14 2007/09/26 03:22:44 marka Exp $
+
+#
+# Clean up after zone transfer quota tests.
+#
+
+rm -f ns1/zone*.example.db ns1/zones.conf
+rm -f ns2/zone*.example.bk ns2/zones.conf
+rm -f dig.out.* ns2/changing.bk
+rm -f ns1/changing.db
+rm -f */named.memstats
diff --git a/bin/tests/system/xferquota/ns1/changing1.db b/bin/tests/system/xferquota/ns1/changing1.db
new file mode 100644
index 0000000..70b9016
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/changing1.db
@@ -0,0 +1,33 @@
+; Copyright (C) 2004, 2007 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: changing1.db,v 1.10 2007/06/19 23:47:07 tbox Exp $
+
+$TTL 600
+
+@ IN SOA dns1.changing. postmaster.changing. (
+ 1 ;; serial
+ 3600 ;; refresh period
+ 1800 ;; retry interval
+ 604800 ;; expire time
+ 600 ) ;; default TTL
+
+ IN NS dns1.changing.
+ NS dns2.changing.
+
+dns1 IN A 10.53.0.1
+dns2 IN A 10.53.0.2
+
+a IN A 10.0.0.1
diff --git a/bin/tests/system/xferquota/ns1/changing2.db b/bin/tests/system/xferquota/ns1/changing2.db
new file mode 100644
index 0000000..bcf73e0
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/changing2.db
@@ -0,0 +1,33 @@
+; Copyright (C) 2004, 2007 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: changing2.db,v 1.10 2007/06/19 23:47:07 tbox Exp $
+
+$TTL 600
+
+@ IN SOA dns1.changing. postmaster.changing. (
+ 2 ;; serial
+ 3600 ;; refresh period
+ 1800 ;; retry interval
+ 604800 ;; expire time
+ 600 ) ;; default TTL
+
+ IN NS dns1.changing.
+ NS dns2.changing.
+
+dns1 IN A 10.53.0.1
+dns2 IN A 10.53.0.2
+
+a IN A 10.0.0.2
diff --git a/bin/tests/system/xferquota/ns1/named.conf b/bin/tests/system/xferquota/ns1/named.conf
new file mode 100644
index 0000000..a49e790
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/named.conf
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.21 2007/06/19 23:47:07 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+};
+
+zone "." {
+ type master;
+ file "root.db";
+};
+
+zone "changing." {
+ type master;
+ file "changing.db";
+};
+
+include "zones.conf";
diff --git a/bin/tests/system/xferquota/ns1/root.db b/bin/tests/system/xferquota/ns1/root.db
new file mode 100644
index 0000000..beca386
--- /dev/null
+++ b/bin/tests/system/xferquota/ns1/root.db
@@ -0,0 +1,35 @@
+; Copyright (C) 2004, 2007 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: root.db,v 1.10 2007/06/19 23:47:07 tbox Exp $
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+
+changing. NS dns1.changing.
+ A 10.53.0.1
+ NS dns2.changing.
+ A 10.53.0.2
diff --git a/bin/tests/system/xferquota/ns2/example.db b/bin/tests/system/xferquota/ns2/example.db
new file mode 100644
index 0000000..8e5a7be
--- /dev/null
+++ b/bin/tests/system/xferquota/ns2/example.db
@@ -0,0 +1,152 @@
+; Copyright (C) 2004, 2007 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: example.db,v 1.12 2007/06/19 23:47:07 tbox Exp $
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example IN SOA mname1. . (
+ 2000042795 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
+example. NS ns3.example.
+ns3.example. A 10.53.0.3
+
+$ORIGIN example.
+* MX 10 mail
+a TXT "foo foo foo"
+ PTR foo.net.
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+dnskey01 DNSKEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" "blegh" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsec01 NSEC a.secure ( NS SOA MX RRSIG DNSKEY LOC NSEC )
+nsec02 NSEC . ( NSAP-PTR NSEC )
+nsec03 NSEC . ( A )
+nsec04 NSEC . ( 127 )
+ptr01 PTR example.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.
+ns A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+rrsig01 RRSIG NSEC 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nsec"
+$ORIGIN u.example.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
diff --git a/bin/tests/system/xferquota/ns2/named.conf b/bin/tests/system/xferquota/ns2/named.conf
new file mode 100644
index 0000000..5930eea
--- /dev/null
+++ b/bin/tests/system/xferquota/ns2/named.conf
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2004, 2007 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.conf,v 1.22 2007/06/19 23:47:07 tbox Exp $ */
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify no;
+
+ transfers-in 5;
+ transfers-per-ns 5;
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
+
+zone "changing." {
+ type slave;
+ masters { 10.53.0.1; };
+ file "changing.bk";
+};
+
+include "zones.conf";
diff --git a/bin/tests/system/xferquota/setup.pl b/bin/tests/system/xferquota/setup.pl
new file mode 100644
index 0000000..19ed4e8
--- /dev/null
+++ b/bin/tests/system/xferquota/setup.pl
@@ -0,0 +1,46 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2004, 2007 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: setup.pl,v 1.14 2007/06/19 23:47:07 tbox Exp $
+
+#
+# Set up test data for zone transfer quota tests.
+#
+use FileHandle;
+
+my $masterconf = new FileHandle("ns1/zones.conf", "w") or die;
+my $slaveconf = new FileHandle("ns2/zones.conf", "w") or die;
+
+for ($z = 0; $z < 300; $z++) {
+ my $zn = sprintf("zone%06d.example", $z);
+ print $masterconf "zone \"$zn\" { type master; file \"$zn.db\"; };\n";
+ print $slaveconf "zone \"$zn\" { type slave; file \"$zn.bk\"; masters { 10.53.0.1; }; };\n";
+ my $fn = "ns1/$zn.db";
+ my $f = new FileHandle($fn, "w") or die "open: $fn: $!";
+ print $f "\$TTL 300
+\@ IN SOA ns1 . 1 300 120 3600 86400
+ NS ns1
+ NS ns2
+ns1 A 10.53.0.1
+ns2 A 10.53.0.2
+ MX 10 mail1.isp.example.
+ MX 20 mail2.isp.example.
+www A 10.0.0.1
+xyzzy A 10.0.0.2
+";
+ $f->close;
+}
diff --git a/bin/tests/system/xferquota/setup.sh b/bin/tests/system/xferquota/setup.sh
new file mode 100644
index 0000000..d45cc88
--- /dev/null
+++ b/bin/tests/system/xferquota/setup.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: setup.sh,v 1.15 2007/06/19 23:47:07 tbox Exp $
+
+#
+# Set up test data for zone transfer quota tests.
+#
+
+$PERL setup.pl
+
+cp -f ns1/changing1.db ns1/changing.db
diff --git a/bin/tests/system/xferquota/tests.sh b/bin/tests/system/xferquota/tests.sh
new file mode 100644
index 0000000..9d077e5
--- /dev/null
+++ b/bin/tests/system/xferquota/tests.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.25 2007/06/19 23:47:07 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+#
+# Perform tests
+#
+
+count=0
+ticks=0
+while [ $count != 300 ]; do
+ if [ $ticks = 1 ]; then
+ echo "I:Changing test zone..."
+ cp -f ns1/changing2.db ns1/changing.db
+ kill -HUP `cat ns1/named.pid`
+ fi
+ sleep 1
+ ticks=`expr $ticks + 1`
+ seconds=`expr $ticks \* 1`
+ if [ $ticks = 360 ]; then
+ echo "I:Took too long to load zones"
+ exit 1
+ fi
+ count=`cat ns2/zone*.bk | grep xyzzy | wc -l`
+ echo "I:Have $count zones up in $seconds seconds"
+done
+
+status=0
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ zone000099.example. @10.53.0.1 axfr -p 5300 > dig.out.ns1 || status=1
+grep ";" dig.out.ns1
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ zone000099.example. @10.53.0.2 axfr -p 5300 > dig.out.ns2 || status=1
+grep ";" dig.out.ns2
+
+$PERL ../digcomp.pl dig.out.ns1 dig.out.ns2 || status=1
+
+sleep 15
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ a.changing. @10.53.0.1 a -p 5300 > dig.out.ns1 || status=1
+grep ";" dig.out.ns1
+
+$DIG +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ a.changing. @10.53.0.2 a -p 5300 > dig.out.ns2 || status=1
+grep ";" dig.out.ns2
+
+$PERL ../digcomp.pl dig.out.ns1 dig.out.ns2 || status=1
+
+echo "I:exit status: $status"
+exit $status
diff --git a/bin/tests/system/zonechecks/a.db b/bin/tests/system/zonechecks/a.db
new file mode 100644
index 0000000..2f90e8e
--- /dev/null
+++ b/bin/tests/system/zonechecks/a.db
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: a.db,v 1.5 2007/06/19 23:47:07 tbox Exp $
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS 127.0.0.1
+127.0.0.1 3600 IN A 127.0.0.1
diff --git a/bin/tests/system/zonechecks/aaaa.db b/bin/tests/system/zonechecks/aaaa.db
new file mode 100644
index 0000000..bcf26f4
--- /dev/null
+++ b/bin/tests/system/zonechecks/aaaa.db
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: aaaa.db,v 1.5 2007/06/19 23:47:07 tbox Exp $
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS ::1
+::1 3600 IN AAAA ::1
diff --git a/bin/tests/system/zonechecks/clean.sh b/bin/tests/system/zonechecks/clean.sh
new file mode 100644
index 0000000..c103c59
--- /dev/null
+++ b/bin/tests/system/zonechecks/clean.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: clean.sh,v 1.6 2007/09/26 03:22:44 marka Exp $
+
+rm -f *.out
+rm -f */named.memstats
diff --git a/bin/tests/system/zonechecks/cname.db b/bin/tests/system/zonechecks/cname.db
new file mode 100644
index 0000000..75e3f38
--- /dev/null
+++ b/bin/tests/system/zonechecks/cname.db
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: cname.db,v 1.5 2007/06/19 23:47:07 tbox Exp $
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS ns
+ns 3600 IN CNAME @
diff --git a/bin/tests/system/zonechecks/dname.db b/bin/tests/system/zonechecks/dname.db
new file mode 100644
index 0000000..fdbc128
--- /dev/null
+++ b/bin/tests/system/zonechecks/dname.db
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: dname.db,v 1.5 2007/06/19 23:47:07 tbox Exp $
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS ns
+@ 3600 IN DNAME .
diff --git a/bin/tests/system/zonechecks/noaddress.db b/bin/tests/system/zonechecks/noaddress.db
new file mode 100644
index 0000000..e457626
--- /dev/null
+++ b/bin/tests/system/zonechecks/noaddress.db
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: noaddress.db,v 1.5 2007/06/19 23:47:07 tbox Exp $
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS ns
+ns 3600 IN TXT this name has no address records
diff --git a/bin/tests/system/zonechecks/nxdomain.db b/bin/tests/system/zonechecks/nxdomain.db
new file mode 100644
index 0000000..d5981bb
--- /dev/null
+++ b/bin/tests/system/zonechecks/nxdomain.db
@@ -0,0 +1,19 @@
+; Copyright (C) 2004, 2007 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: nxdomain.db,v 1.5 2007/06/19 23:47:07 tbox Exp $
+
+@ 3600 IN SOA ns hostmaster 1 3600 1200 604800 3600
+@ 3600 IN NS ns
+; There are no records at all with the ownername of "ns".
diff --git a/bin/tests/system/zonechecks/tests.sh b/bin/tests/system/zonechecks/tests.sh
new file mode 100644
index 0000000..2a1b850
--- /dev/null
+++ b/bin/tests/system/zonechecks/tests.sh
@@ -0,0 +1,164 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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: tests.sh,v 1.4 2007/06/19 23:47:07 tbox Exp $
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+
+#
+echo "I: checking that we detect a NS which refers to a CNAME"
+if $CHECKZONE . cname.db > cname.out 2>&1
+then
+ echo "I:failed (status)"; status=1
+else
+ if grep "is a CNAME" cname.out > /dev/null
+ then
+ :
+ else
+ echo "I:failed (message)"; status=1
+ fi
+fi
+
+#
+echo "I: checking that we detect a NS which is below a DNAME"
+if $CHECKZONE . dname.db > dname.out 2>&1
+then
+ echo "I:failed (status)"; status=1
+else
+ if grep "is below a DNAME" dname.out > /dev/null
+ then
+ :
+ else
+ echo "I:failed (message)"; status=1
+ fi
+fi
+
+#
+echo "I: checking that we detect a NS which has no address records (A/AAAA)"
+if $CHECKZONE . noaddress.db > noaddress.out
+then
+ echo "I:failed (status)"; status=1
+else
+ if grep "has no address records" noaddress.out > /dev/null
+ then
+ :
+ else
+ echo "I:failed (message)"; status=1
+ fi
+fi
+
+#
+echo "I: checking that we detect a NS which has no records"
+if $CHECKZONE . nxdomain.db > nxdomain.out
+then
+ echo "I:failed (status)"; status=1
+else
+ if grep "has no address records" noaddress.out > /dev/null
+ then
+ :
+ else
+ echo "I:failed (message)"; status=1
+ fi
+fi
+
+#
+echo "I: checking that we detect a NS which looks like a A record (fail)"
+if $CHECKZONE -n fail . a.db > a.out 2>&1
+then
+ echo "I:failed (status)"; status=1
+else
+ if grep "appears to be an address" a.out > /dev/null
+ then
+ :
+ else
+ echo "I:failed (message)"; status=1
+ fi
+fi
+
+#
+echo "I: checking that we detect a NS which looks like a A record (warn=default)"
+if $CHECKZONE . a.db > a.out 2>&1
+then
+ if grep "appears to be an address" a.out > /dev/null
+ then
+ :
+ else
+ echo "I:failed (message)"; status=1
+ fi
+else
+ echo "I:failed (status)"; status=1
+fi
+
+#
+echo "I: checking that we detect a NS which looks like a A record (ignore)"
+if $CHECKZONE -n ignore . a.db > a.out 2>&1
+then
+ if grep "appears to be an address" a.out > /dev/null
+ then
+ echo "I:failed (message)"; status=1
+ else
+ :
+ fi
+else
+ echo "I:failed (status)"; status=1
+fi
+
+#
+echo "I: checking that we detect a NS which looks like a AAAA record (fail)"
+if $CHECKZONE -n fail . aaaa.db > aaaa.out 2>&1
+then
+ echo "I:failed (status)"; status=1
+else
+ if grep "appears to be an address" aaaa.out > /dev/null
+ then
+ :
+ else
+ echo "I:failed (message)"; status=1
+ fi
+fi
+
+#
+echo "I: checking that we detect a NS which looks like a AAAA record (warn=default)"
+if $CHECKZONE . aaaa.db > aaaa.out 2>&1
+then
+ if grep "appears to be an address" aaaa.out > /dev/null
+ then
+ :
+ else
+ echo "I:failed (message)"; status=1
+ fi
+else
+ echo "I:failed (status)"; status=1
+fi
+
+#
+echo "I: checking that we detect a NS which looks like a AAAA record (ignore)"
+if $CHECKZONE -n ignore . aaaa.db > aaaa.out 2>&1
+then
+ if grep "appears to be an address" aaaa.out > /dev/null
+ then
+ echo "I:failed (message)"; status=1
+ else
+ :
+ fi
+else
+ echo "I:failed (status)"; status=1
+fi
+echo "I:exit status: $status"
+exit $?
diff --git a/bin/tests/t_api.pl b/bin/tests/t_api.pl
new file mode 100644
index 0000000..daf0161
--- /dev/null
+++ b/bin/tests/t_api.pl
@@ -0,0 +1,223 @@
+#!/usr/local/bin/perl
+#
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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: t_api.pl,v 1.10 2007/06/19 23:46:59 tbox Exp $
+
+require "getopts.pl";
+
+#
+# a minimalistic test api in perl compatable with the C api
+# used for the bind 9 regression tests
+#
+
+sub t_info {
+ package t_api;
+ local($format, @rest) = @_;
+ printf("I:${format}%s", @rest);
+}
+
+sub t_result {
+ package t_api;
+ local($result) = @_;
+ $T_inresult = 1;
+ printf("R:$result\n");
+}
+
+sub t_assert {
+ package t_api;
+ local($component, $anum, $class, $what, @rest) = @_;
+ printf("A:%s:%d:%s:$what\n", $component, $anum, $class, @rest);
+}
+
+sub t_getenv {
+ package t_api;
+ local($name) = @_;
+ return($T_env{$name}) if (defined($T_env{$name}));
+}
+
+package t_api;
+
+$| = 1;
+
+sub t_on_abort {
+ $T_aborted = 1;
+ &t_info("got abort\n");
+ die;
+}
+
+sub t_on_alarm {
+ $T_timedout = 1;
+ &t_info("got alarm\n");
+ die;
+}
+
+sub t_on_int {
+ $T_terminated = 1;
+ &t_info("got int\n");
+ die;
+}
+
+# initialize the test environment
+sub t_initconf {
+ local($cfile) = @_;
+ local($name, $value);
+
+ if ((-f $cfile) && (-s _)) {
+ open(XXX, "< $cfile");
+ while (<XXX>) {
+ next if (/^\#/);
+ next unless (/=/);
+ chop;
+ ($name, $value) = split(/=/, $_, 2);
+ $T_env{$name} = $value;
+ }
+ close(XXX);
+ }
+}
+
+# dump the configuration to the journal
+sub t_dumpconf {
+ local($name, $value);
+
+ foreach $name (sort keys %T_env) {
+ &main't_info("%s\t%s\n", $name, $T_env{$name});
+ }
+}
+
+# run a test
+sub doTestN {
+ package main;
+ local($testnumber) = @_;
+ local($status);
+
+ if (defined($T_testlist[$testnumber])) {
+
+ $t_api'T_inresult = 0;
+ $t_api'T_aborted = 0;
+ $t_api'T_timedout = 0;
+ $t_api'T_terminated = 0;
+ $t_api'T_unresolved = 0;
+
+ alarm($t_api'T_timeout);
+ $status = eval($T_testlist[$testnumber]);
+ alarm(0);
+
+ if (! defined($status)) {
+ &t_info("The test case timed out\n") if ($t_api'T_timedout);
+ &t_info("The test case was terminated\n") if ($t_api'T_terminated);
+ &t_info("The test case was aborted\n") if ($t_api'T_aborted);
+ &t_result("UNRESOLVED");
+ }
+ elsif (! $t_api'T_inresult) {
+ &t_result("NORESULT");
+ }
+ }
+ else {
+ &t_info("Test %d is not defined\n", $testnumber);
+ &t_result("UNTESTED");
+ }
+}
+
+$T_usage = "Usage:
+ a : run all tests
+ b <dir> : cd to dir before running tests
+ c <configfile> : use configfile instead of t_config
+ d <level> : set debug level to level
+ h : print test info (not implemented)
+ u : print usage info
+ n <testnumber> : run test number testnumber
+ t <name> : run test named testname (not implemented)
+ q <seconds> : use seconds as the timeout value
+ x : don't execute tests in a subproc (n/a)
+";
+
+# get command line args
+&main'Getopts('ab:c:d:hun:t:q:x');
+
+# if -u, print usage and exit
+if (defined($main'opt_u)) {
+ print $T_usage;
+ exit(0);
+}
+
+# implement -h and -t after we add test descriptions to T_testlist ZZZ
+if (defined($main'opt_h)) {
+ print "the -h option is not implemented\n";
+ exit(0);
+}
+
+if (defined($main'opt_t)) {
+ print "the -t option is not implemented\n";
+ exit(0);
+}
+
+#
+# silently ignore the -x option
+# this exists in the C version of the api
+# to facilitate exception debugging with gdb
+# and is not meaningful here
+#
+
+$T_configfile = "t_config";
+$T_debug = 0;
+$T_timeout = 10;
+$T_testnum = -1;
+
+$T_dir = $main'opt_b if (defined($main'opt_b));
+$T_debug = $main'opt_d if (defined($main'opt_d));
+$T_configfile = $main'opt_c if (defined($main'opt_c));
+$T_testnum = $main'opt_n if (defined($main'opt_n));
+$T_timeout = $main'opt_q if (defined($main'opt_q));
+
+$SIG{'ABRT'} = 't_api\'t_on_abort';
+$SIG{'ALRM'} = 't_api\'t_on_alarm';
+$SIG{'INT'} = 't_api\'t_on_int';
+$SIG{'QUIT'} = 't_api\'t_on_int';
+
+# print the start line
+$date = `date`;
+chop $date;
+($cmd = $0) =~ s/\.\///g;
+printf("S:$cmd:$date\n");
+
+# initialize the test environment
+&t_initconf($T_configfile);
+&t_dumpconf() if ($T_debug);
+
+# establish working directory if requested
+chdir("$T_dir") if (defined($T_dir) && (-d "$T_dir"));
+
+# run the tests
+if ($T_testnum == -1) {
+ # run all tests
+ $T_ntests = $#main'T_testlist + 1;
+ for ($T_cnt = 0; $T_cnt < $T_ntests; ++$T_cnt) {
+ &doTestN($T_cnt);
+ }
+}
+else {
+ # otherwise run the specified test
+ &doTest($T_testnum);
+}
+
+# print the end line
+$date = `date`;
+chop $date;
+printf("E:$cmd:$date\n");
+
+1;
+
diff --git a/bin/tests/task_test.c b/bin/tests/task_test.c
new file mode 100644
index 0000000..e3ff26b
--- /dev/null
+++ b/bin/tests/task_test.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: task_test.c,v 1.51 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/mem.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx = NULL;
+
+static void
+my_callback(isc_task_t *task, isc_event_t *event) {
+ int i, j;
+ char *name = event->ev_arg;
+
+ j = 0;
+ for (i = 0; i < 1000000; i++)
+ j += 100;
+ printf("task %s (%p): %d\n", name, task, j);
+ isc_event_free(&event);
+}
+
+static void
+my_shutdown(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+
+ printf("shutdown %s (%p)\n", name, task);
+ isc_event_free(&event);
+}
+
+static void
+my_tick(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+
+ printf("task %p tick %s\n", task, name);
+ isc_event_free(&event);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_taskmgr_t *manager = NULL;
+ isc_task_t *t1 = NULL, *t2 = NULL;
+ isc_task_t *t3 = NULL, *t4 = NULL;
+ isc_event_t *event;
+ unsigned int workers;
+ isc_timermgr_t *timgr;
+ isc_timer_t *ti1, *ti2;
+ struct isc_interval interval;
+
+ if (argc > 1)
+ workers = atoi(argv[1]);
+ else
+ workers = 2;
+ printf("%d workers\n", workers);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &manager) ==
+ ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t1) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t2) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t3) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t4) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_task_onshutdown(t1, my_shutdown, "1") ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t2, my_shutdown, "2") ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t3, my_shutdown, "3") ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t4, my_shutdown, "4") ==
+ ISC_R_SUCCESS);
+
+ timgr = NULL;
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timgr) == ISC_R_SUCCESS);
+ ti1 = NULL;
+
+ isc_interval_set(&interval, 1, 0);
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_ticker, NULL,
+ &interval, t1, my_tick, "foo", &ti1) ==
+ ISC_R_SUCCESS);
+
+ ti2 = NULL;
+ isc_interval_set(&interval, 1, 0);
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_ticker, NULL,
+ &interval, t2, my_tick, "bar", &ti2) ==
+ ISC_R_SUCCESS);
+
+ printf("task 1 = %p\n", t1);
+ printf("task 2 = %p\n", t2);
+ sleep(2);
+
+ /*
+ * Note: (void *)1 is used as a sender here, since some compilers
+ * don't like casting a function pointer to a (void *).
+ *
+ * In a real use, it is more likely the sender would be a
+ * structure (socket, timer, task, etc) but this is just a test
+ * program.
+ */
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "1",
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "1",
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "1",
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "1",
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "1",
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "1",
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "1",
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "1",
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "1",
+ sizeof(*event));
+ isc_task_send(t1, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "2",
+ sizeof(*event));
+ isc_task_send(t2, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "3",
+ sizeof(*event));
+ isc_task_send(t3, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "4",
+ sizeof(*event));
+ isc_task_send(t4, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "2",
+ sizeof(*event));
+ isc_task_send(t2, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "3",
+ sizeof(*event));
+ isc_task_send(t3, &event);
+ event = isc_event_allocate(mctx, (void *)1, 1, my_callback, "4",
+ sizeof(*event));
+ isc_task_send(t4, &event);
+ isc_task_purgerange(t3,
+ NULL,
+ ISC_EVENTTYPE_FIRSTEVENT,
+ ISC_EVENTTYPE_LASTEVENT, NULL);
+
+ isc_task_detach(&t1);
+ isc_task_detach(&t2);
+ isc_task_detach(&t3);
+ isc_task_detach(&t4);
+
+ sleep(10);
+ printf("destroy\n");
+ isc_timer_detach(&ti1);
+ isc_timer_detach(&ti2);
+ isc_timermgr_destroy(&timgr);
+ isc_taskmgr_destroy(&manager);
+ printf("destroyed\n");
+
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/tests/tasks/Makefile.in b/bin/tests/tasks/Makefile.in
new file mode 100644
index 0000000..f7fc908
--- /dev/null
+++ b/bin/tests/tasks/Makefile.in
@@ -0,0 +1,55 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-2002 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.30 2007/06/19 23:47:07 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${TEST_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+ISCLIBS = ../../../lib/isc/libisc.@A@
+TAPIDEPLIBS = ../../../lib/tests/libt_api.@A@
+
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+TAPILIBS = ../../../lib/tests/libt_api.@A@
+
+DEPLIBS = ${TAPIDEPLIBS} ${ISCDEPLIBS}
+
+LIBS = ${TAPILIBS} ${ISCLIBS} @LIBS@
+
+TARGETS = t_tasks@EXEEXT@
+
+SRCS = t_tasks.c
+
+@BIND9_MAKE_RULES@
+
+t_tasks@EXEEXT@: t_tasks.@O@ ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_tasks.@O@ ${LIBS}
+
+test: t_tasks@EXEEXT@
+ -@./t_tasks@EXEEXT@ -c @top_srcdir@/t_config -b @srcdir@ -a
+
+testhelp:
+ @./t_tasks@EXEEXT@ -h
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/tasks/t_tasks.c b/bin/tests/tasks/t_tasks.c
new file mode 100644
index 0000000..b8a4d24
--- /dev/null
+++ b/bin/tests/tasks/t_tasks.c
@@ -0,0 +1,2293 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: t_tasks.c,v 1.40 2007/06/19 23:47:07 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h> /* uintptr_t */
+#endif
+#include <isc/condition.h>
+#include <isc/mem.h>
+#include <isc/platform.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <tests/t_api.h>
+
+
+#ifdef ISC_PLATFORM_USETHREADS
+isc_boolean_t threaded = ISC_TRUE;
+#else
+isc_boolean_t threaded = ISC_FALSE;
+#endif
+
+static int senders[4];
+
+static void
+require_threads(void) {
+ t_info("This test requires threads\n");
+ t_result(T_THREADONLY);
+ return;
+}
+
+static void
+t1_callback(isc_task_t *task, isc_event_t *event) {
+ int i;
+ int j;
+
+ UNUSED(task);
+
+ j = 0;
+
+ for (i = 0; i < 1000000; i++)
+ j += 100;
+
+ t_info("task %s\n", (char *)event->ev_arg);
+ isc_event_free(&event);
+}
+
+static void
+t1_shutdown(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ t_info("shutdown %s\n", (char *)event->ev_arg);
+ isc_event_free(&event);
+}
+
+static void
+my_tick(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ t_info("%s\n", (char *)event->ev_arg);
+ isc_event_free(&event);
+}
+
+/*
+ * Adapted from RTH's original task_test program
+ */
+
+static int
+t_tasks1(void) {
+ char *p;
+ isc_mem_t *mctx;
+ isc_taskmgr_t *manager;
+ isc_task_t *task1;
+ isc_task_t *task2;
+ isc_task_t *task3;
+ isc_task_t *task4;
+ isc_event_t *event;
+ unsigned int workers;
+ isc_timermgr_t *timgr;
+ isc_timer_t *ti1;
+ isc_timer_t *ti2;
+ isc_result_t isc_result;
+ struct isc_time absolute;
+ struct isc_interval interval;
+
+ manager = NULL;
+ task1 = NULL;
+ task2 = NULL;
+ task3 = NULL;
+ task4 = NULL;
+ mctx = NULL;
+
+ workers = 2;
+ p = t_getenv("ISC_TASK_WORKERS");
+ if (p != NULL)
+ workers = atoi(p);
+ if (workers < 1) {
+ t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_taskmgr_create(mctx, workers, 0, &manager);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_taskmgr_create failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ isc_result = isc_task_create(manager, 0, &task1);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ isc_result = isc_task_create(manager, 0, &task2);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ isc_result = isc_task_create(manager, 0, &task3);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ isc_result = isc_task_create(manager, 0, &task4);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ isc_result = isc_task_onshutdown(task1, t1_shutdown, "1");
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_onshutdown failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ isc_result = isc_task_onshutdown(task2, t1_shutdown, "2");
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_onshutdown failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ isc_result = isc_task_onshutdown(task3, t1_shutdown, "3");
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_onshutdown failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ isc_result = isc_task_onshutdown(task4, t1_shutdown, "4");
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_onshutdown failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ timgr = NULL;
+ isc_result = isc_timermgr_create(mctx, &timgr);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_timermgr_create %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+
+ ti1 = NULL;
+ isc_time_settoepoch(&absolute);
+ isc_interval_set(&interval, 1, 0);
+ isc_result = isc_timer_create(timgr, isc_timertype_ticker,
+ &absolute, &interval,
+ task1, my_tick, "tick", &ti1);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_timer_create %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+
+ ti2 = NULL;
+ isc_time_settoepoch(&absolute);
+ isc_interval_set(&interval, 1, 0);
+ isc_result = isc_timer_create(timgr, isc_timertype_ticker,
+ &absolute, &interval,
+ task2, my_tick, "tock", &ti2);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_timer_create %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+
+
+ sleep(2);
+
+ /*
+ * Note: (void *)1 is used as a sender here, since some compilers
+ * don't like casting a function pointer to a (void *).
+ *
+ * In a real use, it is more likely the sender would be a
+ * structure (socket, timer, task, etc) but this is just a test
+ * program.
+ */
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task1, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task1, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task1, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task1, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task1, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task1, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task1, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task1, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "1",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task1, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "2",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task2, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "3",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task3, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "4",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task4, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "2",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task2, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "3",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task3, &event);
+
+ event = isc_event_allocate(mctx, (void *)1, 1, t1_callback, "4",
+ sizeof(*event));
+ if (event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_send(task4, &event);
+
+ (void)isc_task_purge(task3, NULL, 0, 0);
+
+ isc_task_detach(&task1);
+ isc_task_detach(&task2);
+ isc_task_detach(&task3);
+ isc_task_detach(&task4);
+
+ sleep(10);
+ isc_timer_detach(&ti1);
+ isc_timer_detach(&ti2);
+ isc_timermgr_destroy(&timgr);
+ isc_taskmgr_destroy(&manager);
+
+ isc_mem_destroy(&mctx);
+ return(T_PASS);
+}
+
+static const char *a1 = "The task subsystem can create and manage tasks";
+
+static void
+t1(void) {
+ int result;
+
+ t_assert("tasks", 1, T_REQUIRED, a1);
+ result = t_tasks1();
+ t_result(result);
+}
+
+#define T2_NTASKS 10000
+
+static isc_event_t *T2_event;
+static isc_taskmgr_t *T2_manager;
+static isc_mem_t *T2_mctx;
+static isc_condition_t T2_cv;
+static isc_mutex_t T2_mx;
+static int T2_done;
+static int T2_nprobs;
+static int T2_nfails;
+static int T2_ntasks;
+
+static void
+t2_shutdown(isc_task_t *task, isc_event_t *event) {
+
+ isc_result_t isc_result;
+
+ task = task; /* notused */
+
+ if (event->ev_arg != NULL) {
+ isc_task_destroy((isc_task_t**) &event->ev_arg);
+ }
+ else {
+ isc_result = isc_mutex_lock(&T2_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %d\n", isc_result);
+ ++T2_nprobs;
+ }
+
+ T2_done = 1;
+
+ isc_result = isc_condition_signal(&T2_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_signal failed %d\n", isc_result);
+ ++T2_nprobs;
+ }
+
+ isc_result = isc_mutex_unlock(&T2_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %d\n", isc_result);
+ ++T2_nprobs;
+ }
+
+ isc_event_free(&T2_event);
+ isc_taskmgr_destroy(&T2_manager);
+ isc_mem_destroy(&T2_mctx);
+ }
+}
+
+static void
+t2_callback(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+ isc_task_t *newtask;
+
+ ++T2_ntasks;
+
+ if (T_debug && ((T2_ntasks % 100) == 0)) {
+ t_info("T2_ntasks %d\n", T2_ntasks);
+ }
+
+ if (event->ev_arg) {
+
+ event->ev_arg = (void *)(((uintptr_t) event->ev_arg) - 1);
+
+ /*
+ * Create a new task and forward the message.
+ */
+ newtask = NULL;
+ isc_result = isc_task_create(T2_manager, 0, &newtask);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %d\n", isc_result);
+ ++T2_nfails;
+ return;
+ }
+
+ isc_result = isc_task_onshutdown(newtask, t2_shutdown,
+ (void *)task);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_onshutdown failed %d\n",
+ isc_result);
+ ++T2_nfails;
+ return;
+ }
+
+ isc_task_send(newtask, &event);
+ } else {
+ /*
+ * Time to unwind, shutdown should perc back up.
+ */
+ isc_task_destroy(&task);
+ }
+}
+
+static int
+t_tasks2(void) {
+ uintptr_t ntasks;
+ int result;
+ char *p;
+ isc_event_t *event;
+ unsigned int workers;
+ isc_result_t isc_result;
+
+ T2_manager = NULL;
+ T2_done = 0;
+ T2_nprobs = 0;
+ T2_nfails = 0;
+ T2_ntasks = 0;
+
+ workers = 2;
+ p = t_getenv("ISC_TASK_WORKERS");
+ if (p != NULL)
+ workers = atoi(p);
+ if (workers < 1) {
+ t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers);
+ return(T_UNRESOLVED);
+ }
+
+ p = t_getenv("ISC_TASKS_MIN");
+ if (p != NULL)
+ ntasks = atoi(p);
+ else
+ ntasks = T2_NTASKS;
+ if (ntasks == 0U) {
+ t_info("Bad config value for ISC_TASKS_MIN, %lu\n",
+ (unsigned long)ntasks);
+ return(T_UNRESOLVED);
+ }
+
+ t_info("Testing with %lu tasks\n", (unsigned long)ntasks);
+
+ isc_result = isc_mutex_init(&T2_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_init failed %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_condition_init(&T2_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_init failed %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mem_create(0, 0, &T2_mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_taskmgr_create(T2_mctx, workers, 0, &T2_manager);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_taskmgr_create failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ T2_event = isc_event_allocate(T2_mctx, (void *)1, 1, t2_callback,
+ (void *)ntasks, sizeof(*event));
+ if (T2_event == NULL) {
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mutex_lock(&T2_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+
+ t2_callback(NULL, T2_event);
+
+ while (T2_done == 0) {
+ isc_result = isc_condition_wait(&T2_cv, &T2_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_wait failed %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((T2_nfails == 0) && (T2_nprobs == 0))
+ result = T_PASS;
+ else if (T2_nfails != 0)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a2 = "The task subsystem can create ISC_TASKS_MIN tasks";
+
+static void
+t2(void) {
+ t_assert("tasks", 2, T_REQUIRED, a2);
+
+ if (threaded)
+ t_result(t_tasks2());
+ else
+ require_threads();
+}
+
+#define T3_NEVENTS 256
+
+static int T3_flag;
+static int T3_nevents;
+static int T3_nsdevents;
+static isc_mutex_t T3_mx;
+static isc_condition_t T3_cv;
+static int T3_nfails;
+static int T3_nprobs;
+
+static void
+t3_sde1(isc_task_t *task, isc_event_t *event) {
+ task = task;
+
+ if (T3_nevents != T3_NEVENTS) {
+ t_info("Some events were not processed\n");
+ ++T3_nprobs;
+ }
+ if (T3_nsdevents == 1) {
+ ++T3_nsdevents;
+ } else {
+ t_info("Shutdown events not processed in LIFO order\n");
+ ++T3_nfails;
+ }
+ isc_event_free(&event);
+}
+
+static void
+t3_sde2(isc_task_t *task, isc_event_t *event) {
+
+ task = task;
+
+ if (T3_nevents != T3_NEVENTS) {
+ t_info("Some events were not processed\n");
+ ++T3_nprobs;
+ }
+ if (T3_nsdevents == 0) {
+ ++T3_nsdevents;
+ } else {
+ t_info("Shutdown events not processed in LIFO order\n");
+ ++T3_nfails;
+ }
+ isc_event_free(&event);
+}
+
+static void
+t3_event1(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+
+ task = task;
+
+ isc_result = isc_mutex_lock(&T3_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T3_nprobs;
+ }
+ while (T3_flag != 1) {
+ (void) isc_condition_wait(&T3_cv, &T3_mx);
+ }
+
+ isc_result = isc_mutex_unlock(&T3_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T3_nprobs;
+ }
+ isc_event_free(&event);
+}
+
+static void
+t3_event2(isc_task_t *task, isc_event_t *event) {
+ task = task;
+
+ ++T3_nevents;
+ isc_event_free(&event);
+}
+
+static int
+t_tasks3(void) {
+ int cnt;
+ int result;
+ char *p;
+ isc_mem_t *mctx;
+ isc_taskmgr_t *tmgr;
+ isc_task_t *task;
+ unsigned int workers;
+ isc_event_t *event;
+ isc_result_t isc_result;
+ isc_eventtype_t event_type;
+
+ T3_flag = 0;
+ T3_nevents = 0;
+ T3_nsdevents = 0;
+ T3_nfails = 0;
+ T3_nprobs = 0;
+
+ event_type = 3;
+
+ workers = 2;
+ p = t_getenv("ISC_TASK_WORKERS");
+ if (p != NULL)
+ workers = atoi(p);
+
+ mctx = NULL;
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mutex_init(&T3_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_init failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_condition_init(&T3_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_init failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ tmgr = NULL;
+ isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_taskmgr_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mutex_lock(&T3_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ task = NULL;
+ isc_result = isc_task_create(tmgr, 0, &task);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mutex_unlock(&T3_mx);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * This event causes the task to wait on T3_cv.
+ */
+ event = isc_event_allocate(mctx, &senders[1], event_type, t3_event1,
+ NULL, sizeof(*event));
+ isc_task_send(task, &event);
+
+ /*
+ * Now we fill up the task's event queue with some events.
+ */
+ for (cnt = 0; cnt < T3_NEVENTS; ++cnt) {
+ event = isc_event_allocate(mctx, &senders[1], event_type,
+ t3_event2, NULL, sizeof(*event));
+ isc_task_send(task, &event);
+ }
+
+ /*
+ * Now we register two shutdown events.
+ */
+ isc_result = isc_task_onshutdown(task, t3_sde1, NULL);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_send failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mutex_unlock(&T3_mx);
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_task_onshutdown(task, t3_sde2, NULL);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_send failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mutex_unlock(&T3_mx);
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_task_shutdown(task);
+
+ /*
+ * Now we free the task by signaling T3_cv.
+ */
+ T3_flag = 1;
+ isc_result = isc_condition_signal(&T3_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_send failed %s\n",
+ isc_result_totext(isc_result));
+ ++T3_nprobs;
+ }
+
+ isc_result = isc_mutex_unlock(&T3_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_send failed %s\n",
+ isc_result_totext(isc_result));
+ ++T3_nprobs;
+ }
+
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+
+ if (T3_nsdevents != 2) {
+ t_info("T3_nsdevents == %d, expected 2\n", T3_nsdevents);
+ ++T3_nfails;
+ }
+
+ if (T3_nevents != T3_nevents) {
+ t_info("T3_nevents == %d, expected 2\n", T3_nevents);
+ ++T3_nfails;
+ }
+
+ result = T_UNRESOLVED;
+
+ if (T3_nfails != 0)
+ result = T_FAIL;
+ else if ((T3_nfails == 0) && (T3_nprobs == 0))
+ result = T_PASS;
+
+ return(result);
+}
+
+static const char *a3 = "When isc_task_shutdown() is called, any shutdown "
+ "events that have been requested via prior "
+ "isc_task_onshutdown() calls are posted in "
+ "LIFO order.";
+static void
+t3(void) {
+ t_assert("tasks", 3, T_REQUIRED, a3);
+
+ if (threaded)
+ t_result(t_tasks3());
+ else
+ require_threads();
+}
+
+static isc_mutex_t T4_mx;
+static isc_condition_t T4_cv;
+static int T4_flag;
+static int T4_nprobs;
+static int T4_nfails;
+
+static void
+t4_event1(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+
+ UNUSED(task);
+
+ isc_result = isc_mutex_lock(&T4_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T4_nprobs;
+ }
+ while (T4_flag != 1) {
+ (void) isc_condition_wait(&T4_cv, &T4_mx);
+ }
+
+ isc_result = isc_mutex_unlock(&T4_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T4_nprobs;
+ }
+ isc_event_free(&event);
+}
+
+static void
+t4_sde(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ /*
+ * No-op.
+ */
+
+ isc_event_free(&event);
+}
+
+static int
+t_tasks4(void) {
+ int result;
+ char *p;
+ isc_mem_t *mctx;
+ isc_taskmgr_t *tmgr;
+ isc_task_t *task;
+ unsigned int workers;
+ isc_result_t isc_result;
+ isc_eventtype_t event_type;
+ isc_event_t *event;
+
+ T4_nprobs = 0;
+ T4_nfails = 0;
+ T4_flag = 0;
+
+ result = T_UNRESOLVED;
+ event_type = 4;
+
+ workers = 2;
+ p = t_getenv("ISC_TASK_WORKERS");
+ if (p != NULL)
+ workers = atoi(p);
+
+ mctx = NULL;
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mutex_init(&T4_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_init failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_condition_init(&T4_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_init failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T4_mx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ tmgr = NULL;
+ isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_taskmgr_create failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T4_mx);
+ isc_condition_destroy(&T4_cv);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mutex_lock(&T4_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T4_mx);
+ isc_condition_destroy(&T4_cv);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ task = NULL;
+ isc_result = isc_task_create(tmgr, 0, &task);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T4_mx);
+ isc_condition_destroy(&T4_cv);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * This event causes the task to wait on T4_cv.
+ */
+ event = isc_event_allocate(mctx, &senders[1], event_type, t4_event1,
+ NULL, sizeof(*event));
+ isc_task_send(task, &event);
+
+ isc_task_shutdown(task);
+
+ isc_result = isc_task_onshutdown(task, t4_sde, NULL);
+ if (isc_result != ISC_R_SHUTTINGDOWN) {
+ t_info("isc_task_onshutdown returned %s\n",
+ isc_result_totext(isc_result));
+ ++T4_nfails;
+ }
+
+ /*
+ * Release the task.
+ */
+ T4_flag = 1;
+
+ isc_result = isc_condition_signal(&T4_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_signal failed %s\n",
+ isc_result_totext(isc_result));
+ ++T4_nprobs;
+ }
+
+ isc_result = isc_mutex_unlock(&T4_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T4_nprobs;
+ }
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ isc_condition_destroy(&T4_cv);
+ DESTROYLOCK(&T4_mx);
+
+ result = T_UNRESOLVED;
+
+ if (T4_nfails != 0)
+ result = T_FAIL;
+ else if ((T4_nfails == 0) && (T4_nprobs == 0))
+ result = T_PASS;
+
+ return(result);
+}
+
+static const char *a4 =
+ "After isc_task_shutdown() has been called, any call to "
+ "isc_task_onshutdown() will return ISC_R_SHUTTINGDOWN.";
+
+static void
+t4(void) {
+ t_assert("tasks", 4, T_REQUIRED, a4);
+
+ if (threaded)
+ t_result(t_tasks4());
+ else
+ require_threads();
+}
+
+static int T7_nprobs;
+static int T7_eflag;
+static int T7_sdflag;
+static isc_mutex_t T7_mx;
+static isc_condition_t T7_cv;
+
+static int T7_nfails;
+
+static void
+t7_event1(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ ++T7_eflag;
+
+ isc_event_free(&event);
+}
+
+static void
+t7_sde(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+
+ UNUSED(task);
+
+ isc_result = isc_mutex_lock(&T7_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T7_nprobs;
+ }
+
+ ++T7_sdflag;
+
+ isc_result = isc_condition_signal(&T7_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_signal failed %s\n",
+ isc_result_totext(isc_result));
+ ++T7_nprobs;
+ }
+
+ isc_result = isc_mutex_unlock(&T7_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T7_nprobs;
+ }
+
+ isc_event_free(&event);
+}
+
+static int
+t_tasks7(void) {
+ int result;
+ char *p;
+ isc_mem_t *mctx;
+ isc_taskmgr_t *tmgr;
+ isc_task_t *task;
+ unsigned int workers;
+ isc_result_t isc_result;
+ isc_eventtype_t event_type;
+ isc_event_t *event;
+ isc_time_t now;
+ isc_interval_t interval;
+
+ T7_nprobs = 0;
+ T7_nfails = 0;
+ T7_sdflag = 0;
+ T7_eflag = 0;
+
+ result = T_UNRESOLVED;
+ event_type = 7;
+
+ workers = 2;
+ p = t_getenv("ISC_TASK_WORKERS");
+ if (p != NULL)
+ workers = atoi(p);
+
+ mctx = NULL;
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mutex_init(&T7_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_init failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_condition_init(&T7_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_init failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T7_mx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ tmgr = NULL;
+ isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_taskmgr_create failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T7_mx);
+ isc_condition_destroy(&T7_cv);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mutex_lock(&T7_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T7_mx);
+ isc_condition_destroy(&T7_cv);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ task = NULL;
+ isc_result = isc_task_create(tmgr, 0, &task);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T7_mx);
+ isc_condition_destroy(&T7_cv);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+
+ isc_result = isc_task_onshutdown(task, t7_sde, NULL);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_onshutdown returned %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T7_mx);
+ isc_condition_destroy(&T7_cv);
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ event = isc_event_allocate(mctx, &senders[1], event_type, t7_event1,
+ NULL, sizeof(*event));
+ isc_task_send(task, &event);
+
+ isc_task_shutdown(task);
+
+ interval.seconds = 5;
+ interval.nanoseconds = 0;
+
+ while (T7_sdflag == 0) {
+ isc_result = isc_time_nowplusinterval(&now, &interval);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_nowplusinterval failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T7_mx);
+ isc_condition_destroy(&T7_cv);
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_condition_waituntil(&T7_cv, &T7_mx, &now);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_waituntil returned %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T7_mx);
+ isc_condition_destroy(&T7_cv);
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ return(T_FAIL);
+ }
+ }
+
+ isc_result = isc_mutex_unlock(&T7_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T7_nprobs;
+ }
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ isc_condition_destroy(&T7_cv);
+ DESTROYLOCK(&T7_mx);
+
+ result = T_UNRESOLVED;
+
+ if (T7_eflag == 0)
+ ++T7_nfails;
+
+ if (T7_nfails != 0)
+ result = T_FAIL;
+ else if ((T7_nfails == 0) && (T7_nprobs == 0))
+ result = T_PASS;
+
+ return(result);
+}
+
+static const char *a7 = "A call to isc_task_create() creates a task that can "
+ "receive events.";
+
+static void
+t7(void) {
+ t_assert("tasks", 7, T_REQUIRED, a7);
+
+ if (threaded)
+ t_result(t_tasks7());
+ else
+ require_threads();
+}
+
+#define T10_SENDERCNT 3
+#define T10_TYPECNT 4
+#define T10_TAGCNT 5
+#define T10_NEVENTS (T10_SENDERCNT*T10_TYPECNT*T10_TAGCNT)
+#define T_CONTROL 99999
+
+static int T10_nprobs;
+static int T10_nfails;
+static int T10_startflag;
+static int T10_shutdownflag;
+static int T10_eventcnt;
+static isc_mutex_t T10_mx;
+static isc_condition_t T10_cv;
+
+static void *T10_purge_sender;
+static isc_eventtype_t T10_purge_type_first;
+static isc_eventtype_t T10_purge_type_last;
+static void *T10_purge_tag;
+static int T10_testrange;
+
+static void
+t10_event1(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+
+ task = task;
+
+ isc_result = isc_mutex_lock(&T10_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T10_nprobs;
+ }
+
+ while (T10_startflag == 0) {
+ isc_result = isc_condition_wait(&T10_cv, &T10_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T10_nprobs;
+ }
+ }
+
+ isc_result = isc_mutex_unlock(&T10_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T10_nprobs;
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+t10_event2(isc_task_t *task, isc_event_t *event) {
+
+ int sender_match;
+ int type_match;
+ int tag_match;
+
+ task = task;
+
+ sender_match = 0;
+ type_match = 0;
+ tag_match = 0;
+
+ if (T_debug) {
+ t_info("Event %p,%d,%p,%s\n",
+ event->ev_sender,
+ (int)event->ev_type,
+ event->ev_tag,
+ event->ev_attributes & ISC_EVENTATTR_NOPURGE ?
+ "NP" : "P");
+ }
+
+ if ((T10_purge_sender == NULL) ||
+ (T10_purge_sender == event->ev_sender)) {
+ sender_match = 1;
+ }
+ if (T10_testrange == 0) {
+ if (T10_purge_type_first == event->ev_type) {
+ type_match = 1;
+ }
+ } else {
+ if ((T10_purge_type_first <= event->ev_type) &&
+ (event->ev_type <= T10_purge_type_last)) {
+ type_match = 1;
+ }
+ }
+ if ((T10_purge_tag == NULL) ||
+ (T10_purge_tag == event->ev_tag)) {
+ tag_match = 1;
+ }
+
+ if (sender_match && type_match && tag_match) {
+ if (event->ev_attributes & ISC_EVENTATTR_NOPURGE) {
+ t_info("event %p,%d,%p matched but was not purgable\n",
+ event->ev_sender, (int)event->ev_type,
+ event->ev_tag);
+ ++T10_eventcnt;
+ } else {
+ t_info("*** event %p,%d,%p not purged\n",
+ event->ev_sender, (int)event->ev_type,
+ event->ev_tag);
+ }
+ } else {
+ ++T10_eventcnt;
+ }
+ isc_event_free(&event);
+}
+
+
+static void
+t10_sde(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+
+ task = task;
+
+ isc_result = isc_mutex_lock(&T10_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T10_nprobs;
+ }
+
+ ++T10_shutdownflag;
+
+ isc_result = isc_condition_signal(&T10_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_signal failed %s\n",
+ isc_result_totext(isc_result));
+ ++T10_nprobs;
+ }
+
+ isc_result = isc_mutex_unlock(&T10_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T10_nprobs;
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+t_taskpurge_x(int sender, int type, int tag, void *purge_sender,
+ int purge_type_first, int purge_type_last, void *purge_tag,
+ int exp_nevents, int *nfails, int *nprobs, int testrange)
+{
+ char *p;
+ isc_mem_t *mctx;
+ isc_taskmgr_t *tmgr;
+ isc_task_t *task;
+ unsigned int workers;
+ isc_result_t isc_result;
+ isc_event_t *event;
+ isc_time_t now;
+ isc_interval_t interval;
+ int sender_cnt;
+ int type_cnt;
+ int tag_cnt;
+ int event_cnt;
+ int cnt;
+ int nevents;
+ isc_event_t *eventtab[T10_NEVENTS];
+
+
+ T10_startflag = 0;
+ T10_shutdownflag = 0;
+ T10_eventcnt = 0;
+ T10_purge_sender = purge_sender;
+ T10_purge_type_first = (isc_eventtype_t) purge_type_first;
+ T10_purge_type_last = (isc_eventtype_t) purge_type_last;
+ T10_purge_tag = purge_tag;
+ T10_testrange = testrange;
+
+ workers = 2;
+ p = t_getenv("ISC_TASK_WORKERS");
+ if (p != NULL)
+ workers = atoi(p);
+
+ mctx = NULL;
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ ++*nprobs;
+ return;
+ }
+
+ isc_result = isc_mutex_init(&T10_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_init failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ ++*nprobs;
+ return;
+ }
+
+ isc_result = isc_condition_init(&T10_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_init failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T10_mx);
+ ++*nprobs;
+ return;
+ }
+
+ tmgr = NULL;
+ isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_taskmgr_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T10_mx);
+ isc_condition_destroy(&T10_cv);
+ ++*nprobs;
+ return;
+ }
+
+ task = NULL;
+ isc_result = isc_task_create(tmgr, 0, &task);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T10_mx);
+ isc_condition_destroy(&T10_cv);
+ ++*nprobs;
+ return;
+ }
+
+ isc_result = isc_task_onshutdown(task, t10_sde, NULL);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_onshutdown returned %s\n",
+ isc_result_totext(isc_result));
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T10_mx);
+ isc_condition_destroy(&T10_cv);
+ ++*nprobs;
+ return;
+ }
+
+ /*
+ * Block the task on T10_cv.
+ */
+ event = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)T_CONTROL,
+ t10_event1, NULL, sizeof(*event));
+
+ isc_task_send(task, &event);
+
+ /*
+ * Fill the task's queue with some messages with varying
+ * sender, type, tag, and purgable attribute values.
+ */
+
+ event_cnt = 0;
+ for (sender_cnt = 0; sender_cnt < T10_SENDERCNT; ++sender_cnt) {
+ for (type_cnt = 0; type_cnt < T10_TYPECNT; ++type_cnt) {
+ for (tag_cnt = 0; tag_cnt < T10_TAGCNT; ++tag_cnt) {
+ eventtab[event_cnt] =
+ isc_event_allocate(mctx,
+ &senders[sender + sender_cnt],
+ (isc_eventtype_t)(type + type_cnt),
+ t10_event2, NULL, sizeof(*event));
+
+ eventtab[event_cnt]->ev_tag =
+ (void *)((uintptr_t)tag + tag_cnt);
+
+ /*
+ * Make all odd message non-purgable.
+ */
+ if ((sender_cnt % 2) && (type_cnt %2) &&
+ (tag_cnt %2))
+ eventtab[event_cnt]->ev_attributes |=
+ ISC_EVENTATTR_NOPURGE;
+ ++event_cnt;
+ }
+ }
+ }
+
+ for (cnt = 0; cnt < event_cnt; ++cnt)
+ isc_task_send(task, &eventtab[cnt]);
+
+ if (T_debug)
+ t_info("%d events queued\n", cnt);
+
+ if (testrange == 0) {
+ /*
+ * We're testing isc_task_purge.
+ */
+ nevents = isc_task_purge(task, purge_sender,
+ (isc_eventtype_t)purge_type_first,
+ purge_tag);
+ if (nevents != exp_nevents) {
+ t_info("*** isc_task_purge returned %d, expected %d\n",
+ nevents, exp_nevents);
+ ++*nfails;
+ } else if (T_debug)
+ t_info("isc_task_purge returned %d\n", nevents);
+ } else {
+ /*
+ * We're testing isc_task_purgerange.
+ */
+ nevents = isc_task_purgerange(task, purge_sender,
+ (isc_eventtype_t)purge_type_first,
+ (isc_eventtype_t)purge_type_last,
+ purge_tag);
+ if (nevents != exp_nevents) {
+ t_info("*** isc_task_purgerange returned %d, "
+ "expected %d\n", nevents, exp_nevents);
+ ++*nfails;
+ } else if (T_debug)
+ t_info("isc_task_purgerange returned %d\n", nevents);
+ }
+
+ isc_result = isc_mutex_lock(&T10_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T10_mx);
+ isc_condition_destroy(&T10_cv);
+ ++*nprobs;
+ return;
+ }
+
+ /*
+ * Unblock the task, allowing event processing.
+ */
+ T10_startflag = 1;
+ isc_result = isc_condition_signal(&T10_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_signal failed %s\n",
+ isc_result_totext(isc_result));
+ ++*nprobs;
+ }
+
+ isc_task_shutdown(task);
+
+ interval.seconds = 5;
+ interval.nanoseconds = 0;
+
+ /*
+ * Wait for shutdown processing to complete.
+ */
+ while (T10_shutdownflag == 0) {
+ isc_result = isc_time_nowplusinterval(&now, &interval);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_nowplusinterval failed %s\n",
+ isc_result_totext(isc_result));
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T10_mx);
+ isc_condition_destroy(&T10_cv);
+ ++*nprobs;
+ return;
+ }
+
+ isc_result = isc_condition_waituntil(&T10_cv, &T10_mx, &now);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_waituntil returned %s\n",
+ isc_result_totext(isc_result));
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T10_mx);
+ isc_condition_destroy(&T10_cv);
+ ++*nfails;
+ return;
+ }
+ }
+
+ isc_result = isc_mutex_unlock(&T10_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++*nprobs;
+ }
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T10_mx);
+ isc_condition_destroy(&T10_cv);
+
+ if (T_debug)
+ t_info("task processed %d events\n", T10_eventcnt);
+
+ if ((T10_eventcnt + nevents) != event_cnt) {
+ t_info("*** processed %d, purged %d, total %d\n",
+ T10_eventcnt, nevents, event_cnt);
+ ++*nfails;
+ }
+}
+
+static int
+t_tasks10(void) {
+ int result;
+
+ T10_nprobs = 0;
+ T10_nfails = 0;
+
+ /*
+ * Try purging on a specific sender.
+ */
+ t_info("testing purge on 2,4,8 expecting 1\n");
+ t_taskpurge_x(1, 4, 7, &senders[2], 4, 4, (void *)8, 1, &T10_nfails,
+ &T10_nprobs, 0);
+
+ /*
+ * Try purging on all senders.
+ */
+ t_info("testing purge on 0,4,8 expecting 3\n");
+ t_taskpurge_x(1, 4, 7, NULL, 4, 4, (void *)8, 3, &T10_nfails,
+ &T10_nprobs, 0);
+
+ /*
+ * Try purging on all senders, specified type, all tags.
+ */
+ t_info("testing purge on 0,4,0 expecting 15\n");
+ t_taskpurge_x(1, 4, 7, NULL, 4, 4, NULL, 15, &T10_nfails,
+ &T10_nprobs, 0);
+
+ /*
+ * Try purging on a specified tag, no such type.
+ */
+ t_info("testing purge on 0,99,8 expecting 0\n");
+ t_taskpurge_x(1, 4, 7, NULL, 99, 99, (void *)8, 0, &T10_nfails,
+ &T10_nprobs, 0);
+
+ /*
+ * Try purging on specified sender, type, all tags.
+ */
+ t_info("testing purge on 0,5,0 expecting 5\n");
+ t_taskpurge_x(1, 4, 7, &senders[3], 5, 5, NULL, 5, &T10_nfails,
+ &T10_nprobs, 0);
+
+ result = T_UNRESOLVED;
+
+ if ((T10_nfails == 0) && (T10_nprobs == 0))
+ result = T_PASS;
+ else if (T10_nfails != 0)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a10 =
+ "A call to isc_task_purge(task, sender, type, tag) "
+ "purges all events of type 'type' and with tag 'tag' "
+ "not marked as unpurgable from sender from the task's "
+ "queue and returns the number of events purged.";
+
+static void
+t10(void) {
+ t_assert("tasks", 10, T_REQUIRED, a10);
+
+ if (threaded)
+ t_result(t_tasks10());
+ else
+ require_threads();
+}
+
+static int T11_nprobs;
+static int T11_nfails;
+static int T11_startflag;
+static int T11_shutdownflag;
+static int T11_eventcnt;
+static isc_mutex_t T11_mx;
+static isc_condition_t T11_cv;
+
+static void
+t11_event1(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+
+ task = task;
+
+ isc_result = isc_mutex_lock(&T11_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+
+ while (T11_startflag == 0) {
+ isc_result = isc_condition_wait(&T11_cv, &T11_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+ }
+
+ isc_result = isc_mutex_unlock(&T11_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+t11_event2(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ ++T11_eventcnt;
+ isc_event_free(&event);
+}
+
+
+static void
+t11_sde(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+
+ UNUSED(task);
+
+ isc_result = isc_mutex_lock(&T11_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+
+ ++T11_shutdownflag;
+
+ isc_result = isc_condition_signal(&T11_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_signal failed %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+
+ isc_result = isc_mutex_unlock(&T11_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+
+ isc_event_free(&event);
+}
+
+static int
+t_tasks11(int purgable) {
+ char *p;
+ isc_mem_t *mctx;
+ isc_taskmgr_t *tmgr;
+ isc_task_t *task;
+ isc_boolean_t rval;
+ unsigned int workers;
+ isc_result_t isc_result;
+ isc_event_t *event1;
+ isc_event_t *event2, *event2_clone;
+ isc_time_t now;
+ isc_interval_t interval;
+ int result;
+
+ T11_startflag = 0;
+ T11_shutdownflag = 0;
+ T11_eventcnt = 0;
+
+ workers = 2;
+ p = t_getenv("ISC_TASK_WORKERS");
+ if (p != NULL)
+ workers = atoi(p);
+
+ mctx = NULL;
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mutex_init(&T11_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_init failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_condition_init(&T11_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_init failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T11_mx);
+ return(T_UNRESOLVED);
+ }
+
+ tmgr = NULL;
+ isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_taskmgr_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T11_mx);
+ isc_condition_destroy(&T11_cv);
+ return(T_UNRESOLVED);
+ }
+
+ task = NULL;
+ isc_result = isc_task_create(tmgr, 0, &task);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T11_mx);
+ isc_condition_destroy(&T11_cv);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_task_onshutdown(task, t11_sde, NULL);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_onshutdown returned %s\n",
+ isc_result_totext(isc_result));
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T11_mx);
+ isc_condition_destroy(&T11_cv);
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Block the task on T11_cv.
+ */
+ event1 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1,
+ t11_event1, NULL, sizeof(*event1));
+
+ isc_task_send(task, &event1);
+
+ event2 = isc_event_allocate(mctx, (void *)1, (isc_eventtype_t)1,
+ t11_event2, NULL, sizeof(*event2));
+ event2_clone = event2;
+ if (purgable)
+ event2->ev_attributes &= ~ISC_EVENTATTR_NOPURGE;
+ else
+ event2->ev_attributes |= ISC_EVENTATTR_NOPURGE;
+
+ isc_task_send(task, &event2);
+
+ rval = isc_task_purgeevent(task, event2_clone);
+ if (rval != (purgable ? ISC_TRUE : ISC_FALSE)) {
+ t_info("isc_task_purgeevent returned %s, expected %s\n",
+ (rval ? "ISC_TRUE" : "ISC_FALSE"),
+ (purgable ? "ISC_TRUE" : "ISC_FALSE"));
+ ++T11_nfails;
+ }
+
+ isc_result = isc_mutex_lock(&T11_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+
+ /*
+ * Unblock the task, allowing event processing.
+ */
+ T11_startflag = 1;
+ isc_result = isc_condition_signal(&T11_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_signal failed %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+
+ isc_task_shutdown(task);
+
+ interval.seconds = 5;
+ interval.nanoseconds = 0;
+
+ /*
+ * Wait for shutdown processing to complete.
+ */
+ while (T11_shutdownflag == 0) {
+ isc_result = isc_time_nowplusinterval(&now, &interval);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_nowplusinterval failed %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+
+ isc_result = isc_condition_waituntil(&T11_cv, &T11_mx, &now);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_waituntil returned %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+ }
+
+ isc_result = isc_mutex_unlock(&T11_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T11_nprobs;
+ }
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_mem_destroy(&mctx);
+ DESTROYLOCK(&T11_mx);
+ isc_condition_destroy(&T11_cv);
+
+ if (T11_eventcnt != (purgable ? 0 : 1)) {
+ t_info("Event was %s purged\n",
+ (purgable ? "not" : "unexpectedly"));
+ ++T11_nfails;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((T11_nfails == 0) && (T11_nprobs == 0))
+ result = T_PASS;
+ else if (T11_nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a11 =
+ "When the event is marked as purgable, a call to "
+ "isc_task_purgeevent(task, event) purges the event 'event' "
+ "from the task's queue and returns ISC_TRUE.";
+
+static void
+t11(void) {
+ t_assert("tasks", 11, T_REQUIRED, a11);
+
+ if (threaded)
+ t_result(t_tasks11(1));
+ else
+ require_threads();
+}
+
+static const char *a12 =
+ "When the event is not marked as purgable, a call to "
+ "isc_task_purgeevent(task, event) does not purge the "
+ "event 'event' from the task's queue and returns "
+ "ISC_FALSE.";
+
+static int
+t_tasks12(void) {
+ return(t_tasks11(0));
+}
+
+static void
+t12(void) {
+ t_assert("tasks", 12, T_REQUIRED, a12);
+
+ if (threaded)
+ t_result(t_tasks12());
+ else
+ require_threads();
+}
+
+static int T13_nfails;
+static int T13_nprobs;
+
+static const char *a13 =
+ "A call to "
+ "isc_event_purgerange(task, sender, first, last, tag) "
+ "purges all events not marked unpurgable from "
+ "sender 'sender' and of type within the range 'first' "
+ "to 'last' inclusive from the task's event queue and "
+ "returns the number of tasks purged.";
+
+static int
+t_tasks13(void) {
+ int result;
+
+ T13_nfails = 0;
+ T13_nprobs = 0;
+
+ /*
+ * First let's try the same cases we used in t10.
+ */
+
+ /*
+ * Try purging on a specific sender.
+ */
+ t_info("testing purge on 2,4,8 expecting 1\n");
+ t_taskpurge_x(1, 4, 7, &senders[2], 4, 4, (void *)8, 1,
+ &T13_nfails, &T13_nprobs, 1);
+
+ /*
+ * Try purging on all senders.
+ */
+ t_info("testing purge on 0,4,8 expecting 3\n");
+ t_taskpurge_x(1, 4, 7, NULL, 4, 4, (void *)8, 3,
+ &T13_nfails, &T13_nprobs, 1);
+
+ /*
+ * Try purging on all senders, specified type, all tags.
+ */
+ t_info("testing purge on 0,4,0 expecting 15\n");
+ t_taskpurge_x(1, 4, 7, NULL, 4, 4, NULL, 15, &T13_nfails, &T13_nprobs, 1);
+
+ /*
+ * Try purging on a specified tag, no such type.
+ */
+ t_info("testing purge on 0,99,8 expecting 0\n");
+ t_taskpurge_x(1, 4, 7, NULL, 99, 99, (void *)8, 0,
+ &T13_nfails, &T13_nprobs, 1);
+
+ /*
+ * Try purging on specified sender, type, all tags.
+ */
+ t_info("testing purge on 3,5,0 expecting 5\n");
+ t_taskpurge_x(1, 4, 7, &senders[3], 5, 5, 0, 5, &T13_nfails, &T13_nprobs, 1);
+
+ /*
+ * Now let's try some ranges.
+ */
+
+ t_info("testing purgerange on 2,4-5,8 expecting 2\n");
+ t_taskpurge_x(1, 4, 7, &senders[2], 4, 5, (void *)8, 1,
+ &T13_nfails, &T13_nprobs, 1);
+
+ /*
+ * Try purging on all senders.
+ */
+ t_info("testing purge on 0,4-5,8 expecting 5\n");
+ t_taskpurge_x(1, 4, 7, NULL, 4, 5, (void *)8, 5,
+ &T13_nfails, &T13_nprobs, 1);
+
+ /*
+ * Try purging on all senders, specified type, all tags.
+ */
+ t_info("testing purge on 0,5-6,0 expecting 28\n");
+ t_taskpurge_x(1, 4, 7, NULL, 5, 6, NULL, 28, &T13_nfails, &T13_nprobs, 1);
+
+ /*
+ * Try purging on a specified tag, no such type.
+ */
+ t_info("testing purge on 0,99-101,8 expecting 0\n");
+ t_taskpurge_x(1, 4, 7, NULL, 99, 101, (void *)8, 0,
+ &T13_nfails, &T13_nprobs, 1);
+
+ /*
+ * Try purging on specified sender, type, all tags.
+ */
+ t_info("testing purge on 3,5-6,0 expecting 10\n");
+ t_taskpurge_x(1, 4, 7, &senders[3], 5, 6, NULL, 10, &T13_nfails,
+ &T13_nprobs, 1);
+
+ result = T_UNRESOLVED;
+
+ if ((T13_nfails == 0) && (T13_nprobs == 0))
+ result = T_PASS;
+ else if (T13_nfails)
+ result = T_FAIL;
+
+ return (result);
+}
+
+static void
+t13(void) {
+ t_assert("tasks", 13, T_REQUIRED, a13);
+
+ if (threaded)
+ t_result(t_tasks13());
+ else
+ require_threads();
+}
+
+#define T14_NTASKS 10
+#define T14_EXCLTASK 6
+
+int t14_exclusiveerror = ISC_R_SUCCESS;
+int t14_error = 0;
+int t14_done = 0;
+
+int spin(int n);
+
+int t14_active[T14_NTASKS];
+
+static void
+t14_callback(isc_task_t *task, isc_event_t *event) {
+ int taskno = *(int *)(event->ev_arg);
+
+
+ t_info("task enter %d\n", taskno);
+ if (taskno == T14_EXCLTASK) {
+ int i;
+ t14_exclusiveerror = isc_task_beginexclusive(task);
+ if (t14_exclusiveerror == ISC_R_SUCCESS)
+ t_info("task %d got exclusive access\n", taskno);
+ else
+ t_info("task %d failed to got exclusive access: %d\n",
+ taskno, t14_exclusiveerror);
+ for (i = 0; i < T14_NTASKS; i++) {
+ t_info("task %d state %d\n", i , t14_active[i]);
+ if (t14_active[i])
+ t14_error++;
+ }
+ isc_task_endexclusive(task);
+ t14_done = 1;
+ } else {
+ t14_active[taskno]++;
+ (void) spin(10000000);
+ t14_active[taskno]--;
+ }
+ t_info("task exit %d\n", taskno);
+ if (t14_done) {
+ isc_mem_put(event->ev_destroy_arg, event->ev_arg, sizeof (int));
+ isc_event_free(&event);
+ } else {
+ isc_task_send(task, &event);
+ }
+}
+
+int spin(int n) {
+ int i;
+ int r = 0;
+ for (i = 0; i < n; i++) {
+ r += i;
+ if (r > 1000000)
+ r = 0;
+ }
+ return (r);
+}
+
+static int
+t_tasks14(void) {
+ char *p;
+ isc_mem_t *mctx;
+ isc_taskmgr_t *manager;
+ isc_task_t *tasks[T14_NTASKS];
+ unsigned int workers;
+ isc_result_t isc_result;
+ int i;
+
+ manager = NULL;
+ mctx = NULL;
+
+ for (i = 0; i < T14_NTASKS; i++)
+ tasks[i] = NULL;
+
+ workers = 4;
+ p = t_getenv("ISC_TASK_WORKERS");
+ if (p != NULL)
+ workers = atoi(p);
+ if (workers < 1) {
+ t_info("Bad config value for ISC_TASK_WORKERS, %d\n", workers);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %d\n", isc_result);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_taskmgr_create(mctx, workers, 0, &manager);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_taskmgr_create failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ for (i = 0; i < T14_NTASKS; i++) {
+ isc_event_t *event;
+ int *v;
+
+ isc_result = isc_task_create(manager, 0, &tasks[i]);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %d\n", isc_result);
+ return(T_FAIL);
+ }
+
+ v = isc_mem_get(mctx, sizeof *v);
+ if (v == NULL) {
+ isc_task_detach(&tasks[i]);
+ t_info("isc_mem_get failed\n");
+ return(T_FAIL);
+ }
+ *v = i;
+
+ event = isc_event_allocate(mctx, NULL, 1, t14_callback,
+ v, sizeof(*event));
+ if (event == NULL) {
+ isc_mem_put(mctx, v, sizeof *v);
+ t_info("isc_event_allocate failed\n");
+ return(T_UNRESOLVED);
+ }
+ isc_task_send(tasks[i], &event);
+ }
+
+ for (i = 0; i < T14_NTASKS; i++) {
+ isc_task_detach(&tasks[i]);
+ }
+
+ isc_taskmgr_destroy(&manager);
+
+ if (t14_exclusiveerror != ISC_R_SUCCESS || t14_error) {
+ if (t14_exclusiveerror != ISC_R_SUCCESS)
+ t_info("isc_task_beginexclusive() failed\n");
+ if (t14_error)
+ t_info("mutual access occurred\n");
+ return(T_FAIL);
+ }
+
+ isc_mem_destroy(&mctx);
+ return(T_PASS);
+}
+
+static void
+t14(void) {
+ int result;
+
+ t_assert("tasks", 14, T_REQUIRED,
+ "isc_task_beginexclusive() gets exclusive access");
+ result = t_tasks14();
+ t_result(result);
+}
+
+testspec_t T_testlist[] = {
+ { t1, "basic task subsystem" },
+ { t2, "maxtasks" },
+ { t3, "isc_task_shutdown" },
+ { t4, "isc_task_shutdown" },
+ { t7, "isc_task_create" },
+ { t10, "isc_task_purge" },
+ { t11, "isc_task_purgeevent" },
+ { t12, "isc_task_purgeevent" },
+ { t13, "isc_task_purgerange" },
+ { t14, "isc_task_beginexclusive" },
+ { NULL, NULL }
+};
diff --git a/bin/tests/timer_test.c b/bin/tests/timer_test.c
new file mode 100644
index 0000000..2825dc5
--- /dev/null
+++ b/bin/tests/timer_test.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: timer_test.c,v 1.40 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/mem.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+isc_mem_t *mctx1, *mctx2, *mctx3;
+isc_task_t *t1, *t2, *t3;
+isc_timer_t *ti1, *ti2, *ti3;
+int tick_count = 0;
+
+static void
+shutdown_task(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+
+ printf("task %p shutdown %s\n", task, name);
+ isc_event_free(&event);
+}
+
+static void
+tick(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+
+ INSIST(event->ev_type == ISC_TIMEREVENT_TICK);
+
+ printf("task %s (%p) tick\n", name, task);
+
+ tick_count++;
+ if (ti3 != NULL && tick_count % 3 == 0)
+ isc_timer_touch(ti3);
+
+ if (ti3 != NULL && tick_count == 7) {
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ isc_interval_set(&interval, 5, 0);
+ (void)isc_time_nowplusinterval(&expires, &interval);
+ isc_interval_set(&interval, 4, 0);
+ printf("*** resetting ti3 ***\n");
+ RUNTIME_CHECK(isc_timer_reset(ti3, isc_timertype_once,
+ &expires, &interval, ISC_TRUE) ==
+ ISC_R_SUCCESS);
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+timeout(isc_task_t *task, isc_event_t *event) {
+ char *name = event->ev_arg;
+ const char *type;
+
+ INSIST(event->ev_type == ISC_TIMEREVENT_IDLE ||
+ event->ev_type == ISC_TIMEREVENT_LIFE);
+
+ if (event->ev_type == ISC_TIMEREVENT_IDLE)
+ type = "idle";
+ else
+ type = "life";
+ printf("task %s (%p) %s timeout\n", name, task, type);
+
+ if (strcmp(name, "3") == 0) {
+ printf("*** saving task 3 ***\n");
+ isc_event_free(&event);
+ return;
+ }
+
+ isc_event_free(&event);
+ isc_task_shutdown(task);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_taskmgr_t *manager = NULL;
+ isc_timermgr_t *timgr = NULL;
+ unsigned int workers;
+ isc_time_t expires, now;
+ isc_interval_t interval;
+
+ if (argc > 1)
+ workers = atoi(argv[1]);
+ else
+ workers = 2;
+ printf("%d workers\n", workers);
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx1) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_taskmgr_create(mctx1, workers, 0, &manager) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_timermgr_create(mctx1, &timgr) == ISC_R_SUCCESS);
+
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t1) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t2) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_create(manager, 0, &t3) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t1, shutdown_task, "1") ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t2, shutdown_task, "2") ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_task_onshutdown(t3, shutdown_task, "3") ==
+ ISC_R_SUCCESS);
+
+ printf("task 1: %p\n", t1);
+ printf("task 2: %p\n", t2);
+ printf("task 3: %p\n", t3);
+
+ TIME_NOW(&now);
+
+ isc_interval_set(&interval, 2, 0);
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_once, NULL,
+ &interval, t2, timeout, "2", &ti2) ==
+ ISC_R_SUCCESS);
+
+ isc_interval_set(&interval, 1, 0);
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_ticker, NULL,
+ &interval, t1, tick, "1", &ti1) ==
+ ISC_R_SUCCESS);
+
+ isc_interval_set(&interval, 10, 0);
+ RUNTIME_CHECK(isc_time_add(&now, &interval, &expires) ==
+ ISC_R_SUCCESS);
+ isc_interval_set(&interval, 2, 0);
+ RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_once, &expires,
+ &interval, t3, timeout, "3", &ti3) ==
+ ISC_R_SUCCESS);
+
+ isc_task_detach(&t1);
+ isc_task_detach(&t2);
+ isc_task_detach(&t3);
+
+ sleep(15);
+ printf("destroy\n");
+ isc_timer_detach(&ti1);
+ isc_timer_detach(&ti2);
+ isc_timer_detach(&ti3);
+ sleep(2);
+ isc_timermgr_destroy(&timgr);
+ isc_taskmgr_destroy(&manager);
+ printf("destroyed\n");
+
+ printf("Statistics for mctx1:\n");
+ isc_mem_stats(mctx1, stdout);
+ isc_mem_destroy(&mctx1);
+
+ return (0);
+}
diff --git a/bin/tests/timers/Makefile.in b/bin/tests/timers/Makefile.in
new file mode 100644
index 0000000..0ba198a
--- /dev/null
+++ b/bin/tests/timers/Makefile.in
@@ -0,0 +1,55 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-2002 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.28 2007/06/19 23:47:07 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${TEST_INCLUDES} ${ISC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+ISCLIBS = ../../../lib/isc/libisc.@A@
+
+ISCDEPLIBS = ../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${ISCDEPLIBS}
+
+LIBS = ${ISCLIBS} @LIBS@
+
+TLIB = ../../../lib/tests/libt_api.@A@
+
+TARGETS = t_timers@EXEEXT@
+
+SRCS = t_timers.c
+
+@BIND9_MAKE_RULES@
+
+t_timers@EXEEXT@: t_timers.@O@ ${DEPLIBS} ${TLIB}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ t_timers.@O@ ${TLIB} ${LIBS}
+
+test: t_timers@EXEEXT@
+ -@./t_timers@EXEEXT@ -c @top_srcdir@/t_config -b @srcdir@ -q 60 -a
+
+testhelp:
+ @./t_timers@EXEEXT@ -h
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tests/timers/t_timers.c b/bin/tests/timers/t_timers.c
new file mode 100644
index 0000000..7705364
--- /dev/null
+++ b/bin/tests/timers/t_timers.c
@@ -0,0 +1,1128 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: t_timers.c,v 1.28 2008/01/12 23:47:13 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/condition.h>
+#include <isc/mem.h>
+#include <isc/platform.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <tests/t_api.h>
+
+#ifdef ISC_PLATFORM_USETHREADS
+isc_boolean_t threaded = ISC_TRUE;
+#else
+isc_boolean_t threaded = ISC_FALSE;
+#endif
+
+#define Tx_FUDGE_SECONDS 0 /* in absence of clock_getres() */
+#define Tx_FUDGE_NANOSECONDS 500000000 /* in absence of clock_getres() */
+
+static isc_time_t Tx_endtime;
+static isc_time_t Tx_lasttime;
+static int Tx_eventcnt;
+static int Tx_nevents;
+static isc_mutex_t Tx_mx;
+static isc_condition_t Tx_cv;
+static int Tx_nfails;
+static int Tx_nprobs;
+static isc_timer_t *Tx_timer;
+static int Tx_seconds;
+static int Tx_nanoseconds;
+
+static void
+require_threads(void) {
+ t_info("This test requires threads\n");
+ t_result(T_THREADONLY);
+ return;
+}
+
+static void
+tx_sde(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+
+ task = task;
+ event = event;
+
+ /*
+ * Signal shutdown processing complete.
+ */
+ isc_result = isc_mutex_lock(&Tx_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+
+ isc_result = isc_condition_signal(&Tx_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_signal failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+
+ isc_result = isc_mutex_unlock(&Tx_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+tx_te(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+ isc_time_t now;
+ isc_time_t base;
+ isc_time_t ulim;
+ isc_time_t llim;
+ isc_interval_t interval;
+ isc_eventtype_t expected_event_type;
+
+ ++Tx_eventcnt;
+
+ t_info("tick %d\n", Tx_eventcnt);
+
+ expected_event_type = ISC_TIMEREVENT_LIFE;
+ if ((isc_timertype_t) event->ev_arg == isc_timertype_ticker)
+ expected_event_type = ISC_TIMEREVENT_TICK;
+
+ if (event->ev_type != expected_event_type) {
+ t_info("expected event type %d, got %d\n",
+ expected_event_type, (int) event->ev_type);
+ ++Tx_nfails;
+ }
+
+ isc_result = isc_time_now(&now);
+ if (isc_result == ISC_R_SUCCESS) {
+ interval.seconds = Tx_seconds;
+ interval.nanoseconds = Tx_nanoseconds;
+ isc_result = isc_time_add(&Tx_lasttime, &interval, &base);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_add failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ } else {
+ t_info("isc_time_now failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ interval.seconds = Tx_FUDGE_SECONDS;
+ interval.nanoseconds = Tx_FUDGE_NANOSECONDS;
+ isc_result = isc_time_add(&base, &interval, &ulim);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_add failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ isc_result = isc_time_subtract(&base, &interval, &llim);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_subtract failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ if (isc_time_compare(&llim, &now) > 0) {
+ t_info("timer range error: early by "
+ "%lu microseconds\n",
+ (unsigned long)isc_time_microdiff(&base, &now));
+ ++Tx_nfails;
+ } else if (isc_time_compare(&ulim, &now) < 0) {
+ t_info("timer range error: late by "
+ "%lu microseconds\n",
+ (unsigned long)isc_time_microdiff(&now, &base));
+ ++Tx_nfails;
+ }
+ Tx_lasttime = now;
+ }
+
+ if (Tx_eventcnt == Tx_nevents) {
+ isc_result = isc_time_now(&Tx_endtime);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_now failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ isc_timer_detach(&Tx_timer);
+ isc_task_shutdown(task);
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+t_timers_x(isc_timertype_t timertype, isc_time_t *expires,
+ isc_interval_t *interval,
+ void (*action)(isc_task_t *, isc_event_t *))
+{
+ char *p;
+ isc_mem_t *mctx;
+ isc_taskmgr_t *tmgr;
+ isc_task_t *task;
+ unsigned int workers;
+ isc_result_t isc_result;
+ isc_timermgr_t *timermgr;
+
+ Tx_eventcnt = 0;
+ isc_time_settoepoch(&Tx_endtime);
+
+ workers = 2;
+ p = t_getenv("ISC_TASK_WORKERS");
+ if (p != NULL)
+ workers = atoi(p);
+
+ mctx = NULL;
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ return;
+ }
+
+ isc_result = isc_mutex_init(&Tx_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_init failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ ++Tx_nprobs;
+ return;
+ }
+
+ isc_result = isc_condition_init(&Tx_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_init failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&Tx_mx);
+ isc_mem_destroy(&mctx);
+ ++Tx_nprobs;
+ return;
+ }
+
+ tmgr = NULL;
+ isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_taskmgr_create failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&Tx_mx);
+ isc_condition_destroy(&Tx_cv);
+ isc_mem_destroy(&mctx);
+ ++Tx_nprobs;
+ return;
+ }
+
+ timermgr = NULL;
+ isc_result = isc_timermgr_create(mctx, &timermgr);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_timermgr_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&Tx_mx);
+ isc_condition_destroy(&Tx_cv);
+ isc_mem_destroy(&mctx);
+ ++Tx_nprobs;
+ return;
+ }
+
+ isc_result = isc_mutex_lock(&Tx_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ isc_timermgr_destroy(&timermgr);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&Tx_mx);
+ isc_condition_destroy(&Tx_cv);
+ isc_mem_destroy(&mctx);
+ ++Tx_nprobs;
+ return;
+ }
+
+ task = NULL;
+ isc_result = isc_task_create(tmgr, 0, &task);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_timermgr_destroy(&timermgr);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&Tx_mx);
+ isc_condition_destroy(&Tx_cv);
+ isc_mem_destroy(&mctx);
+ ++Tx_nprobs;
+ return;
+ }
+
+ isc_result = isc_task_onshutdown(task, tx_sde, NULL);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_onshutdown failed %s\n",
+ isc_result_totext(isc_result));
+ isc_timermgr_destroy(&timermgr);
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&Tx_mx);
+ isc_condition_destroy(&Tx_cv);
+ isc_mem_destroy(&mctx);
+ ++Tx_nprobs;
+ return;
+ }
+
+ isc_result = isc_time_now(&Tx_lasttime);
+ if (isc_result != ISC_R_SUCCESS) {
+ isc_timermgr_destroy(&timermgr);
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&Tx_mx);
+ isc_condition_destroy(&Tx_cv);
+ isc_mem_destroy(&mctx);
+ ++Tx_nprobs;
+ return;
+ }
+
+ Tx_timer = NULL;
+ isc_result = isc_timer_create(timermgr, timertype, expires, interval,
+ task, action, (void *)timertype,
+ &Tx_timer);
+
+ if (isc_result != ISC_R_SUCCESS) {
+ isc_timermgr_destroy(&timermgr);
+ isc_task_destroy(&task);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&Tx_mx);
+ isc_condition_destroy(&Tx_cv);
+ isc_mem_destroy(&mctx);
+ ++Tx_nprobs;
+ return;
+ }
+
+ /*
+ * Wait for shutdown processing to complete.
+ */
+ while (Tx_eventcnt != Tx_nevents) {
+ isc_result = isc_condition_wait(&Tx_cv, &Tx_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_waituntil failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ }
+
+ isc_result = isc_mutex_unlock(&Tx_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+
+ isc_task_detach(&task);
+ isc_taskmgr_destroy(&tmgr);
+ isc_timermgr_destroy(&timermgr);
+ DESTROYLOCK(&Tx_mx);
+ isc_condition_destroy(&Tx_cv);
+ isc_mem_destroy(&mctx);
+
+}
+
+#define T1_SECONDS 2
+#define T1_NANOSECONDS 500000000
+
+static const char *a1 =
+ "When type is isc_timertype_ticker, a call to isc_timer_create() "
+ "creates a timer that posts an ISC_TIMEREVENT_TICK event to the "
+ "specified task every 'interval' seconds and returns ISC_R_SUCCESS.";
+
+static void
+t1(void) {
+ int result;
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ t_assert("isc_timer_create", 1, T_REQUIRED, a1);
+
+ if (threaded) {
+ Tx_nfails = 0;
+ Tx_nprobs = 0;
+ Tx_nevents = 12;
+ Tx_seconds = T1_SECONDS;
+ Tx_nanoseconds = T1_NANOSECONDS;
+ isc_interval_set(&interval, Tx_seconds, Tx_nanoseconds);
+ isc_time_settoepoch(&expires);
+
+ t_timers_x(isc_timertype_ticker, &expires, &interval, tx_te);
+
+ result = T_UNRESOLVED;
+
+ if ((Tx_nfails == 0) && (Tx_nprobs == 0))
+ result = T_PASS;
+ else if (Tx_nfails)
+ result = T_FAIL;
+
+ t_result(result);
+ } else
+ require_threads();
+}
+
+#define T2_SECONDS 5
+#define T2_NANOSECONDS 300000000;
+
+static const char *a2 =
+ "When type is isc_timertype_once, a call to isc_timer_create() "
+ "creates a timer that posts an ISC_TIMEEVENT_LIFE event to the "
+ "specified task when the current time reaches or exceeds the time "
+ "specified by 'expires'.";
+
+static void
+t2(void) {
+ int result;
+ int isc_result;
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ t_assert("isc_timer_create", 2, T_REQUIRED, a2);
+
+ if (threaded) {
+ Tx_nfails = 0;
+ Tx_nprobs = 0;
+ Tx_nevents = 1;
+ Tx_seconds = T2_SECONDS;
+ Tx_nanoseconds = T2_NANOSECONDS;
+ isc_interval_set(&interval, Tx_seconds, Tx_nanoseconds);
+
+ isc_result = isc_time_nowplusinterval(&expires, &interval);
+ if (isc_result == ISC_R_SUCCESS) {
+
+ isc_interval_set(&interval, 0, 0);
+ t_timers_x(isc_timertype_once, &expires, &interval,
+ tx_te);
+
+ } else {
+ t_info("isc_time_nowplusinterval failed %s\n",
+ isc_result_totext(isc_result));
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((Tx_nfails == 0) && (Tx_nprobs == 0))
+ result = T_PASS;
+ else if (Tx_nfails)
+ result = T_FAIL;
+
+ t_result(result);
+ } else
+ require_threads();
+}
+
+static void
+t3_te(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+ isc_time_t now;
+ isc_time_t base;
+ isc_time_t ulim;
+ isc_time_t llim;
+ isc_interval_t interval;
+
+ ++Tx_eventcnt;
+
+ t_info("tick %d\n", Tx_eventcnt);
+
+ isc_result = isc_time_now(&now);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_now failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ interval.seconds = Tx_seconds;
+ interval.nanoseconds = Tx_nanoseconds;
+ isc_result = isc_time_add(&Tx_lasttime, &interval, &base);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_add failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ interval.seconds = Tx_FUDGE_SECONDS;
+ interval.nanoseconds = Tx_FUDGE_NANOSECONDS;
+ isc_result = isc_time_add(&base, &interval, &ulim);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_add failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ isc_result = isc_time_subtract(&base, &interval, &llim);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_subtract failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ if (isc_time_compare(&llim, &now) > 0) {
+ t_info("timer range error: early by "
+ "%lu microseconds\n",
+ (unsigned long)isc_time_microdiff(&base, &now));
+ ++Tx_nfails;
+ } else if (isc_time_compare(&ulim, &now) < 0) {
+ t_info("timer range error: late by "
+ "%lu microseconds\n",
+ (unsigned long)isc_time_microdiff(&now, &base));
+ ++Tx_nfails;
+ }
+ Tx_lasttime = now;
+ }
+
+ if (event->ev_type != ISC_TIMEREVENT_IDLE) {
+ t_info("received event type %d, expected type %d\n",
+ event->ev_type, ISC_TIMEREVENT_IDLE);
+ ++Tx_nfails;
+ }
+
+ isc_timer_detach(&Tx_timer);
+ isc_task_shutdown(task);
+ isc_event_free(&event);
+}
+
+#define T3_SECONDS 4
+#define T3_NANOSECONDS 400000000
+
+static const char *a3 =
+ "When type is isc_timertype_once, a call to isc_timer_create() "
+ "creates a timer that posts an ISC_TIMEEVENT_IDLE event to the "
+ "specified task when the timer has been idle for 'interval' seconds.";
+
+static void
+t3(void) {
+ int result;
+ int isc_result;
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ t_assert("isc_timer_create", 3, T_REQUIRED, a3);
+
+ if (threaded) {
+ Tx_nfails = 0;
+ Tx_nprobs = 0;
+ Tx_nevents = 1;
+ Tx_seconds = T3_SECONDS;
+ Tx_nanoseconds = T3_NANOSECONDS;
+
+ isc_interval_set(&interval, Tx_seconds + 1, Tx_nanoseconds);
+
+ isc_result = isc_time_nowplusinterval(&expires, &interval);
+ if (isc_result == ISC_R_SUCCESS) {
+ isc_interval_set(&interval, Tx_seconds,
+ Tx_nanoseconds);
+ t_timers_x(isc_timertype_once, &expires, &interval,
+ t3_te);
+ } else {
+ t_info("isc_time_nowplusinterval failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((Tx_nfails == 0) && (Tx_nprobs == 0))
+ result = T_PASS;
+ else if (Tx_nfails)
+ result = T_FAIL;
+
+ t_result(result);
+ } else
+ require_threads();
+}
+
+#define T4_SECONDS 2
+#define T4_NANOSECONDS 500000000
+
+static void
+t4_te(isc_task_t *task, isc_event_t *event) {
+
+ isc_result_t isc_result;
+ isc_time_t now;
+ isc_time_t base;
+ isc_time_t ulim;
+ isc_time_t llim;
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ ++Tx_eventcnt;
+
+ t_info("tick %d\n", Tx_eventcnt);
+
+ /*
+ * Check expired time.
+ */
+
+ isc_result = isc_time_now(&now);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_now failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ interval.seconds = Tx_seconds;
+ interval.nanoseconds = Tx_nanoseconds;
+ isc_result = isc_time_add(&Tx_lasttime, &interval, &base);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_add failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ interval.seconds = Tx_FUDGE_SECONDS;
+ interval.nanoseconds = Tx_FUDGE_NANOSECONDS;
+ isc_result = isc_time_add(&base, &interval, &ulim);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_add failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ isc_result = isc_time_subtract(&base, &interval, &llim);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_time_subtract failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ }
+
+ if (isc_result == ISC_R_SUCCESS) {
+ if (isc_time_compare(&llim, &now) > 0) {
+ t_info("timer range error: early by "
+ "%lu microseconds\n",
+ (unsigned long)isc_time_microdiff(&base, &now));
+ ++Tx_nfails;
+ } else if (isc_time_compare(&ulim, &now) < 0) {
+ t_info("timer range error: late by "
+ "%lu microseconds\n",
+ (unsigned long)isc_time_microdiff(&now, &base));
+ ++Tx_nfails;
+ }
+ Tx_lasttime = now;
+ }
+
+ if (Tx_eventcnt < 3) {
+ if (event->ev_type != ISC_TIMEREVENT_TICK) {
+ t_info("received event type %d, expected type %d\n",
+ event->ev_type, ISC_TIMEREVENT_IDLE);
+ ++Tx_nfails;
+ }
+ if (Tx_eventcnt == 2) {
+ isc_interval_set(&interval, T4_SECONDS,
+ T4_NANOSECONDS);
+ isc_result = isc_time_nowplusinterval(&expires,
+ &interval);
+ if (isc_result == ISC_R_SUCCESS) {
+ isc_interval_set(&interval, 0, 0);
+ isc_result =
+ isc_timer_reset(Tx_timer,
+ isc_timertype_once,
+ &expires, &interval,
+ ISC_FALSE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_timer_reset failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nfails;
+ }
+ } else {
+ t_info("isc_time_nowplusinterval failed %s\n",
+ isc_result_totext(isc_result));
+ ++Tx_nprobs;
+ }
+ }
+ } else {
+ if (event->ev_type != ISC_TIMEREVENT_LIFE) {
+ t_info("received event type %d, expected type %d\n",
+ event->ev_type, ISC_TIMEREVENT_IDLE);
+ ++Tx_nfails;
+ }
+
+ isc_timer_detach(&Tx_timer);
+ isc_task_shutdown(task);
+ }
+
+ isc_event_free(&event);
+}
+
+static const char *a4 =
+ "A call to isc_timer_reset() changes the timer's type, expires and "
+ "interval values to the given values.";
+
+static void
+t4(void) {
+ int result;
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ t_assert("isc_timer_reset", 4, T_REQUIRED, a4);
+
+ if (threaded) {
+ Tx_nfails = 0;
+ Tx_nprobs = 0;
+ Tx_nevents = 3;
+ Tx_seconds = T4_SECONDS;
+ Tx_nanoseconds = T4_NANOSECONDS;
+
+ isc_interval_set(&interval, T4_SECONDS, T4_NANOSECONDS);
+ isc_time_settoepoch(&expires);
+ t_timers_x(isc_timertype_ticker, &expires, &interval, t4_te);
+
+ result = T_UNRESOLVED;
+
+ if ((Tx_nfails == 0) && (Tx_nprobs == 0))
+ result = T_PASS;
+ else if (Tx_nfails)
+ result = T_FAIL;
+
+ t_result(result);
+ } else
+ require_threads();
+}
+
+#define T5_NTICKS 4
+#define T5_SECONDS 3
+
+static int T5_startflag;
+static int T5_shutdownflag;
+static int T5_eventcnt;
+static isc_mutex_t T5_mx;
+static isc_condition_t T5_cv;
+static int T5_nfails;
+static int T5_nprobs;
+static isc_timer_t *T5_tickertimer;
+static isc_timer_t *T5_oncetimer;
+static isc_task_t *T5_task1;
+static isc_task_t *T5_task2;
+
+/*
+ * T5_task1 blocks on T5_mx while events accumulate
+ * in it's queue, until signaled by T5_task2.
+ */
+
+static void
+t5_start_event(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+
+ UNUSED(task);
+
+ t_info("t5_start_event\n");
+
+ isc_result = isc_mutex_lock(&T5_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nprobs;
+ }
+
+ while (! T5_startflag) {
+ (void) isc_condition_wait(&T5_cv, &T5_mx);
+ }
+
+ isc_result = isc_mutex_unlock(&T5_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nprobs;
+ }
+ isc_event_free(&event);
+}
+
+static void
+t5_tick_event(isc_task_t *task, isc_event_t *event) {
+ isc_result_t isc_result;
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ task = task;
+
+ ++T5_eventcnt;
+ t_info("t5_tick_event %d\n", T5_eventcnt);
+
+ /*
+ * On the first tick, purge all remaining tick events
+ * and then shut down the task.
+ */
+ if (T5_eventcnt == 1) {
+ isc_time_settoepoch(&expires);
+ isc_interval_set(&interval, T5_SECONDS, 0);
+ isc_result = isc_timer_reset(T5_tickertimer,
+ isc_timertype_ticker, &expires,
+ &interval, ISC_TRUE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_timer_reset failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nfails;
+ }
+ isc_task_shutdown(task);
+ }
+ isc_event_free(&event);
+}
+
+static void
+t5_once_event(isc_task_t *task, isc_event_t *event) {
+
+ isc_result_t isc_result;
+
+ t_info("t5_once_event\n");
+
+ /*
+ * Allow task1 to start processing events.
+ */
+ isc_result = isc_mutex_lock(&T5_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nprobs;
+ }
+
+ T5_startflag = 1;
+
+ isc_result = isc_condition_broadcast(&T5_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_broadcast failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nprobs;
+ }
+
+ isc_result = isc_mutex_unlock(&T5_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nprobs;
+ }
+
+ isc_event_free(&event);
+ isc_task_shutdown(task);
+}
+
+static void
+t5_shutdown_event(isc_task_t *task, isc_event_t *event) {
+
+ isc_result_t isc_result;
+
+ UNUSED(task);
+ UNUSED(event);
+
+ t_info("t5_shutdown_event\n");
+
+ /*
+ * Signal shutdown processing complete.
+ */
+ isc_result = isc_mutex_lock(&T5_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nprobs;
+ }
+
+ T5_shutdownflag = 1;
+
+ isc_result = isc_condition_signal(&T5_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_signal failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nprobs;
+ }
+
+ isc_result = isc_mutex_unlock(&T5_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nprobs;
+ }
+ isc_event_free(&event);
+}
+
+static int
+t_timers5(void) {
+ char *p;
+ int result;
+ isc_mem_t *mctx;
+ isc_taskmgr_t *tmgr;
+ unsigned int workers;
+ isc_result_t isc_result;
+ isc_timermgr_t *timermgr;
+ isc_event_t *event;
+ isc_time_t expires;
+ isc_interval_t interval;
+
+ T5_startflag = 0;
+ T5_shutdownflag = 0;
+ T5_eventcnt = 0;
+
+ workers = 2;
+ p = t_getenv("ISC_TASK_WORKERS");
+ if (p != NULL)
+ workers = atoi(p);
+
+ mctx = NULL;
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mutex_init(&T5_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_init failed %s\n",
+ isc_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_condition_init(&T5_cv);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_init failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T5_mx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ tmgr = NULL;
+ isc_result = isc_taskmgr_create(mctx, workers, 0, &tmgr);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_taskmgr_create failed %s\n",
+ isc_result_totext(isc_result));
+ DESTROYLOCK(&T5_mx);
+ isc_condition_destroy(&T5_cv);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ timermgr = NULL;
+ isc_result = isc_timermgr_create(mctx, &timermgr);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_timermgr_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&T5_mx);
+ isc_condition_destroy(&T5_cv);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ T5_task1 = NULL;
+ isc_result = isc_task_create(tmgr, 0, &T5_task1);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_timermgr_destroy(&timermgr);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&T5_mx);
+ isc_condition_destroy(&T5_cv);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_task_onshutdown(T5_task1, t5_shutdown_event, NULL);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_onshutdown failed %s\n",
+ isc_result_totext(isc_result));
+ isc_timermgr_destroy(&timermgr);
+ isc_task_destroy(&T5_task1);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&T5_mx);
+ isc_condition_destroy(&T5_cv);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ T5_task2 = NULL;
+ isc_result = isc_task_create(tmgr, 0, &T5_task2);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_task_create failed %s\n",
+ isc_result_totext(isc_result));
+ isc_timermgr_destroy(&timermgr);
+ isc_task_destroy(&T5_task1);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&T5_mx);
+ isc_condition_destroy(&T5_cv);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_mutex_lock(&T5_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_lock failed %s\n",
+ isc_result_totext(isc_result));
+ isc_timermgr_destroy(&timermgr);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&T5_mx);
+ isc_condition_destroy(&T5_cv);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ event = isc_event_allocate(mctx, (void *)1 , (isc_eventtype_t)1,
+ t5_start_event, NULL, sizeof(*event));
+ isc_task_send(T5_task1, &event);
+
+ isc_time_settoepoch(&expires);
+ isc_interval_set(&interval, T5_SECONDS, 0);
+
+ T5_tickertimer = NULL;
+ isc_result = isc_timer_create(timermgr, isc_timertype_ticker,
+ &expires, &interval, T5_task1,
+ t5_tick_event, NULL, &T5_tickertimer);
+
+ if (isc_result != ISC_R_SUCCESS) {
+ isc_timermgr_destroy(&timermgr);
+ (void) isc_condition_signal(&T5_cv);
+ (void) isc_mutex_unlock(&T5_mx);
+ isc_task_destroy(&T5_task1);
+ isc_task_destroy(&T5_task2);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&T5_mx);
+ isc_condition_destroy(&T5_cv);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ T5_oncetimer = NULL;
+ isc_interval_set(&interval, (T5_SECONDS * T5_NTICKS) + 2, 0);
+ isc_result = isc_time_nowplusinterval(&expires, &interval);
+ if (isc_result != ISC_R_SUCCESS) {
+ isc_timer_detach(&T5_tickertimer);
+ isc_timermgr_destroy(&timermgr);
+ (void)isc_condition_signal(&T5_cv);
+ (void)isc_mutex_unlock(&T5_mx);
+ isc_task_destroy(&T5_task1);
+ isc_task_destroy(&T5_task2);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&T5_mx);
+ isc_condition_destroy(&T5_cv);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_interval_set(&interval, 0, 0);
+ isc_result = isc_timer_create(timermgr, isc_timertype_once,
+ &expires, &interval, T5_task2,
+ t5_once_event, NULL, &T5_oncetimer);
+
+ if (isc_result != ISC_R_SUCCESS) {
+ isc_timer_detach(&T5_tickertimer);
+ isc_timermgr_destroy(&timermgr);
+ (void) isc_condition_signal(&T5_cv);
+ (void) isc_mutex_unlock(&T5_mx);
+ isc_task_destroy(&T5_task1);
+ isc_task_destroy(&T5_task2);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&T5_mx);
+ isc_condition_destroy(&T5_cv);
+ isc_mem_destroy(&mctx);
+ ++T5_nprobs;
+ return(T_UNRESOLVED);
+ }
+
+ /*
+ * Wait for shutdown processing to complete.
+ */
+ while (! T5_shutdownflag) {
+ isc_result = isc_condition_wait(&T5_cv, &T5_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_condition_waituntil failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nprobs;
+ }
+ }
+
+ isc_result = isc_mutex_unlock(&T5_mx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mutex_unlock failed %s\n",
+ isc_result_totext(isc_result));
+ ++T5_nprobs;
+ }
+
+ if (T5_eventcnt != 1) {
+ t_info("processed %d events\n", T5_eventcnt);
+ ++T5_nfails;
+ }
+
+ isc_timer_detach(&T5_tickertimer);
+ isc_timer_detach(&T5_oncetimer);
+ isc_timermgr_destroy(&timermgr);
+ isc_task_destroy(&T5_task1);
+ isc_task_destroy(&T5_task2);
+ isc_taskmgr_destroy(&tmgr);
+ DESTROYLOCK(&T5_mx);
+ isc_condition_destroy(&T5_cv);
+ isc_mem_destroy(&mctx);
+
+ result = T_UNRESOLVED;
+
+ if ((T5_nfails == 0) && (T5_nprobs == 0))
+ result = T_PASS;
+ else if (T5_nfails)
+ result = T_FAIL;
+
+ return (result);
+}
+
+static const char *a5 =
+ "When 'purge' is TRUE, a call to isc_timer_reset() purges any pending "
+ "events from 'timer' from the task's event queue.";
+
+static void
+t5(void) {
+ t_assert("isc_timer_reset", 5, T_REQUIRED, a5);
+
+ if (threaded)
+ t_result(t_timers5());
+ else
+ require_threads();
+}
+
+testspec_t T_testlist[] = {
+ { t1, "timer_create" },
+ { t2, "timer_create" },
+ { t3, "timer_create" },
+ { t4, "timer_reset" },
+ { t5, "timer_reset" },
+ { NULL, NULL }
+};
diff --git a/bin/tests/wire_test.c b/bin/tests/wire_test.c
new file mode 100644
index 0000000..ee7de98
--- /dev/null
+++ b/bin/tests/wire_test.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: wire_test.c,v 1.67 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/result.h>
+
+#include "printmsg.h"
+
+int parseflags = 0;
+isc_mem_t *mctx;
+isc_boolean_t printmemstats = ISC_FALSE;
+isc_boolean_t dorender = ISC_FALSE;
+
+static void
+process_message(isc_buffer_t *source);
+
+static inline void
+CHECKRESULT(isc_result_t result, const char *msg) {
+ if (result != ISC_R_SUCCESS) {
+ printf("%s: %s\n", msg, dns_result_totext(result));
+
+ exit(1);
+ }
+}
+
+static int
+fromhex(char c) {
+ if (c >= '0' && c <= '9')
+ return (c - '0');
+ else if (c >= 'a' && c <= 'f')
+ return (c - 'a' + 10);
+ else if (c >= 'A' && c <= 'F')
+ return (c - 'A' + 10);
+
+ printf("bad input format: %02x\n", c);
+ exit(3);
+ /* NOTREACHED */
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "wire_test [-p] [-b] [-s] [-r]\n");
+ fprintf(stderr, "\t-p\tPreserve order of the records in messages\n");
+ fprintf(stderr, "\t-b\tBest-effort parsing (ignore some errors)\n");
+ fprintf(stderr, "\t-s\tPrint memory statistics\n");
+ fprintf(stderr, "\t-r\tAfter parsing, re-render the message\n");
+ fprintf(stderr, "\t-t\tTCP mode - ignore the first 2 bytes\n");
+}
+
+int
+main(int argc, char *argv[]) {
+ char *rp, *wp;
+ unsigned char *bp;
+ isc_buffer_t source;
+ size_t len, i;
+ int n;
+ FILE *f;
+ isc_boolean_t need_close = ISC_FALSE;
+ unsigned char b[64 * 1024];
+ char s[4000];
+ isc_boolean_t tcp = ISC_FALSE;
+ int ch;
+
+ mctx = NULL;
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ while ((ch = isc_commandline_parse(argc, argv, "pbsrt")) != -1) {
+ switch (ch) {
+ case 'p':
+ parseflags |= DNS_MESSAGEPARSE_PRESERVEORDER;
+ break;
+ case 'b':
+ parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
+ break;
+ case 's':
+ printmemstats = ISC_TRUE;
+ break;
+ case 'r':
+ dorender = ISC_TRUE;
+ break;
+ case 't':
+ tcp = ISC_TRUE;
+ break;
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc > 1) {
+ f = fopen(argv[1], "r");
+ if (f == NULL) {
+ printf("fopen failed\n");
+ exit(1);
+ }
+ need_close = ISC_TRUE;
+ } else
+ f = stdin;
+
+ bp = b;
+ while (fgets(s, sizeof(s), f) != NULL) {
+ rp = s;
+ wp = s;
+ len = 0;
+ while (*rp != '\0') {
+ if (*rp == '#')
+ break;
+ if (*rp != ' ' && *rp != '\t' &&
+ *rp != '\r' && *rp != '\n') {
+ *wp++ = *rp;
+ len++;
+ }
+ rp++;
+ }
+ if (len == 0U)
+ break;
+ if (len % 2 != 0U) {
+ printf("bad input format: %lu\n", (unsigned long)len);
+ exit(1);
+ }
+ if (len > sizeof(b) * 2) {
+ printf("input too long\n");
+ exit(2);
+ }
+ rp = s;
+ for (i = 0; i < len; i += 2) {
+ n = fromhex(*rp++);
+ n *= 16;
+ n += fromhex(*rp++);
+ *bp++ = n;
+ }
+ }
+
+ if (need_close)
+ fclose(f);
+
+ if (tcp) {
+ unsigned char *p = b;
+ while (p < bp) {
+ unsigned int len;
+
+ if (p + 2 > bp) {
+ printf("premature end of packet\n");
+ exit(1);
+ }
+ len = p[0] << 8 | p[1];
+
+ if (p + 2 + len > bp) {
+ printf("premature end of packet\n");
+ exit(1);
+ }
+ isc_buffer_init(&source, p + 2, len);
+ isc_buffer_add(&source, len);
+ process_message(&source);
+ p += 2 + len;
+ }
+ } else {
+ isc_buffer_init(&source, b, sizeof(b));
+ isc_buffer_add(&source, bp - b);
+ process_message(&source);
+ }
+
+ if (printmemstats)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
+
+static void
+process_message(isc_buffer_t *source) {
+ dns_message_t *message;
+ isc_result_t result;
+ int i;
+
+ message = NULL;
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message);
+ CHECKRESULT(result, "dns_message_create failed");
+
+ result = dns_message_parse(message, source, parseflags);
+ if (result == DNS_R_RECOVERABLE)
+ result = ISC_R_SUCCESS;
+ CHECKRESULT(result, "dns_message_parse failed");
+
+ result = printmessage(message);
+ CHECKRESULT(result, "printmessage() failed");
+
+ if (printmemstats)
+ isc_mem_stats(mctx, stdout);
+
+ if (dorender) {
+ unsigned char b2[64 * 1024];
+ isc_buffer_t buffer;
+ dns_compress_t cctx;
+
+ isc_buffer_init(&buffer, b2, sizeof(b2));
+
+ /*
+ * XXXMLG
+ * Changing this here is a hack, and should not be done in
+ * reasonable application code, ever.
+ */
+ message->from_to_wire = DNS_MESSAGE_INTENTRENDER;
+
+ for (i = 0; i < DNS_SECTION_MAX; i++)
+ message->counts[i] = 0; /* Another hack XXX */
+
+ result = dns_compress_init(&cctx, -1, mctx);
+ CHECKRESULT(result, "dns_compress_init() failed");
+
+ result = dns_message_renderbegin(message, &cctx, &buffer);
+ CHECKRESULT(result, "dns_message_renderbegin() failed");
+
+ result = dns_message_rendersection(message,
+ DNS_SECTION_QUESTION, 0);
+ CHECKRESULT(result,
+ "dns_message_rendersection(QUESTION) failed");
+
+ result = dns_message_rendersection(message,
+ DNS_SECTION_ANSWER, 0);
+ CHECKRESULT(result,
+ "dns_message_rendersection(ANSWER) failed");
+
+ result = dns_message_rendersection(message,
+ DNS_SECTION_AUTHORITY, 0);
+ CHECKRESULT(result,
+ "dns_message_rendersection(AUTHORITY) failed");
+
+ result = dns_message_rendersection(message,
+ DNS_SECTION_ADDITIONAL, 0);
+ CHECKRESULT(result,
+ "dns_message_rendersection(ADDITIONAL) failed");
+
+ dns_message_renderend(message);
+
+ dns_compress_invalidate(&cctx);
+
+ message->from_to_wire = DNS_MESSAGE_INTENTPARSE;
+ dns_message_destroy(&message);
+
+ printf("Message rendered.\n");
+ if (printmemstats)
+ isc_mem_stats(mctx, stdout);
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
+ &message);
+ CHECKRESULT(result, "dns_message_create failed");
+
+ result = dns_message_parse(message, &buffer, parseflags);
+ CHECKRESULT(result, "dns_message_parse failed");
+
+ result = printmessage(message);
+ CHECKRESULT(result, "printmessage() failed");
+ }
+ dns_message_destroy(&message);
+}
diff --git a/bin/tests/wire_test.data b/bin/tests/wire_test.data
new file mode 100644
index 0000000..cbda586
--- /dev/null
+++ b/bin/tests/wire_test.data
@@ -0,0 +1,9 @@
+000a 8580 0001 0003 0000 0003 # message header
+0376697803636f6d00 0002 0001 # question section: vix.com IN NS
+c00c 0002 0001 00000e10 # vix.com IN NS 3600
+000b 056973727631027061c00c # rdlen=0xb isrv1.pa.vix.com
+c00c 0002 0001 00000e10 0009 066e732d657874c00c
+c00c 0002 0001 00000e10 000e 036e733104676e616303636f6d00
+c025 0001 0001 00000e10 0004 cc98b886
+c03c 0001 0001 00000e10 0004 cc98b840
+c051 0001 0001 0002a14a 0004 c697f8f6
diff --git a/bin/tests/wire_test.data2 b/bin/tests/wire_test.data2
new file mode 100644
index 0000000..503eac7
--- /dev/null
+++ b/bin/tests/wire_test.data2
@@ -0,0 +1,14 @@
+1707 8180
+ 0001 0005 0002 0002 027a 6202 6d78 0361
+ 6f6c 0363 6f6d 0000 0100 01c0 0c00 0100
+ 0100 000b a100 04c6 5110 21c0 0c00 0100
+ 0100 000b a100 04c6 5110 22c0 0c00 0100
+ 0100 000b a100 04c6 5110 23c0 0c00 0100
+ 0100 000b a100 04c6 5110 24c0 0c00 0100
+ 0100 000b a100 04c6 5110 2502 6d78 0341
+ 4f4c 0363 6f6d 0000 0200 0100 000d 9900
+ 0c06 646e 732d 3031 026e 73c0 72c0 6f00
+ 0200 0100 000d 9900 0906 646e 732d 3032
+ c08c c085 0001 0001 0000 0d99 0004 c651
+ 11e8 c09d 0001 0001 0000 0d99 0004 cdbc
+ 9de8
diff --git a/bin/tests/wire_test.data3 b/bin/tests/wire_test.data3
new file mode 100644
index 0000000..86a80ab
--- /dev/null
+++ b/bin/tests/wire_test.data3
@@ -0,0 +1,14 @@
+1706 8180
+ 0001 0005 0002 0002 027a 6102 6d78 0361
+ 6f6c 0363 6f6d 0000 0100 01c0 0c00 0100
+ 0100 000b a100 04c6 5110 05c0 0c00 0100
+ 0100 000b a100 04c6 5110 01c0 0c00 0100
+ 0100 000b a100 04c6 5110 02c0 0c00 0100
+ 0100 000b a100 04c6 5110 03c0 0c00 0100
+ 0100 000b a100 04c6 5110 0402 6d78 0341
+ 4f4c 0363 6f6d 0000 0200 0100 000d 9900
+ 0c06 646e 732d 3031 026e 73c0 72c0 6f00
+ 0200 0100 000d 9900 0906 646e 732d 3032
+ c08c c085 0001 0001 0000 0d99 0004 c651
+ 11e8 c09d 0001 0001 0000 0d99 0004 cdbc
+ 9de8
diff --git a/bin/tests/wire_test.data4 b/bin/tests/wire_test.data4
new file mode 100644
index 0000000..b934a60
--- /dev/null
+++ b/bin/tests/wire_test.data4
@@ -0,0 +1,31 @@
+00068180
+000100070002001103616f6c03636f6d
+00000f0001c00c000f000100000d1b00
+0a000f027a64026d78c00cc00c000f00
+0100000d1b0007000f027962c02ac00c
+000f000100000d1b0007000f027963c0
+2ac00c000f000100000d1b0007000f02
+7964c02ac00c000f000100000d1b0007
+000f027a61c02ac00c000f000100000d
+1b0007000f027a62c02ac00c000f0001
+00000d1b0007000f027a63c02ac00c00
+02000100000d1b000c06444e532d3031
+024e53c00cc00c0002000100000d1b00
+0906444e532d3032c0b4c02700010001
+00000d1c0004c6511062c02700010001
+00000d1c0004c6511063c02700010001
+00000d1c0004c6511064c02700010001
+00000d1c0004c6511065c02700010001
+00000d1c0004c6511061c03d00010001
+00000d1c0004cdbc9c63c03d00010001
+00000d1c0004cdbc9c64c03d00010001
+00000d1c0004cdbc9c65c03d00010001
+00000d1c0004cdbc9c61c03d00010001
+00000d1c0004cdbc9c62c05000010001
+00000d1c0004cdbc9c83c05000010001
+00000d1c0004cdbc9c84c05000010001
+00000d1c0004cdbc9c85c05000010001
+00000d1c0004cdbc9c81c05000010001
+00000d1c0004cdbc9c82c0ad00010001
+00000d1c0004c65111e8c0c500010001
+00000d1c0004cdbc9de8
diff --git a/bin/tests/zone_test.c b/bin/tests/zone_test.c
new file mode 100644
index 0000000..7983bba
--- /dev/null
+++ b/bin/tests/zone_test.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: zone_test.c,v 1.33 2007/06/19 23:46:59 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/mem.h>
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/fixedname.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+#include <dns/zone.h>
+
+#ifdef ISC_PLATFORM_NEEDSYSSELECTH
+#include <sys/select.h>
+#endif
+
+static int debug = 0;
+static int quiet = 0;
+static int stats = 0;
+static isc_mem_t *mctx = NULL;
+dns_zone_t *zone = NULL;
+isc_taskmgr_t *taskmgr = NULL;
+isc_timermgr_t *timermgr = NULL;
+isc_socketmgr_t *socketmgr = NULL;
+dns_zonemgr_t *zonemgr = NULL;
+dns_zonetype_t zonetype = dns_zone_master;
+isc_sockaddr_t addr;
+
+#define ERRRET(result, function) \
+ do { \
+ if (result != ISC_R_SUCCESS) { \
+ fprintf(stderr, "%s() returned %s\n", \
+ function, dns_result_totext(result)); \
+ return; \
+ } \
+ } while (0)
+
+#define ERRCONT(result, function) \
+ if (result != ISC_R_SUCCESS) { \
+ fprintf(stderr, "%s() returned %s\n", \
+ function, dns_result_totext(result)); \
+ continue; \
+ } else \
+ (void)NULL
+
+static void
+usage() {
+ fprintf(stderr,
+ "usage: zone_test [-dqsSM] [-c class] [-f file] zone\n");
+ exit(1);
+}
+
+static void
+setup(const char *zonename, const char *filename, const char *classname) {
+ isc_result_t result;
+ dns_rdataclass_t rdclass;
+ isc_consttextregion_t region;
+ isc_buffer_t buffer;
+ dns_fixedname_t fixorigin;
+ dns_name_t *origin;
+ const char *rbt = "rbt";
+
+ if (debug)
+ fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
+ zonename, filename, classname);
+ result = dns_zone_create(&zone, mctx);
+ ERRRET(result, "dns_zone_new");
+
+ dns_zone_settype(zone, zonetype);
+
+ isc_buffer_init(&buffer, zonename, strlen(zonename));
+ isc_buffer_add(&buffer, strlen(zonename));
+ dns_fixedname_init(&fixorigin);
+ result = dns_name_fromtext(dns_fixedname_name(&fixorigin),
+ &buffer, dns_rootname, ISC_FALSE, NULL);
+ ERRRET(result, "dns_name_fromtext");
+ origin = dns_fixedname_name(&fixorigin);
+
+ result = dns_zone_setorigin(zone, origin);
+ ERRRET(result, "dns_zone_setorigin");
+
+ result = dns_zone_setdbtype(zone, 1, &rbt);
+ ERRRET(result, "dns_zone_setdatabase");
+
+ result = dns_zone_setfile(zone, filename);
+ ERRRET(result, "dns_zone_setfile");
+
+ region.base = classname;
+ region.length = strlen(classname);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)(void*)&region);
+ ERRRET(result, "dns_rdataclass_fromtext");
+
+ dns_zone_setclass(zone, rdclass);
+
+ if (zonetype == dns_zone_slave)
+ dns_zone_setmasters(zone, &addr, 1);
+
+ result = dns_zone_load(zone);
+ ERRRET(result, "dns_zone_load");
+
+ result = dns_zonemgr_managezone(zonemgr, zone);
+ ERRRET(result, "dns_zonemgr_managezone");
+}
+
+static void
+print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset) {
+ isc_buffer_t text;
+ char t[1000];
+ isc_result_t result;
+ isc_region_t r;
+
+ isc_buffer_init(&text, t, sizeof(t));
+ result = dns_rdataset_totext(rdataset, name, ISC_FALSE, ISC_FALSE,
+ &text);
+ isc_buffer_usedregion(&text, &r);
+ if (result == ISC_R_SUCCESS)
+ printf("%.*s", (int)r.length, (char *)r.base);
+ else
+ printf("%s\n", dns_result_totext(result));
+}
+
+static void
+query(void) {
+ char buf[1024];
+ dns_fixedname_t name;
+ dns_fixedname_t found;
+ dns_db_t *db;
+ char *s;
+ isc_buffer_t buffer;
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdataset_t sigset;
+ fd_set rfdset;
+
+ db = NULL;
+ result = dns_zone_getdb(zone, &db);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "%s() returned %s\n", "dns_zone_getdb",
+ dns_result_totext(result));
+ return;
+ }
+
+ dns_fixedname_init(&found);
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&sigset);
+
+ do {
+
+ fprintf(stdout, "zone_test ");
+ fflush(stdout);
+ FD_ZERO(&rfdset);
+ FD_SET(0, &rfdset);
+ select(1, &rfdset, NULL, NULL, NULL);
+ if (fgets(buf, sizeof(buf), stdin) == NULL) {
+ fprintf(stdout, "\n");
+ break;
+ }
+ buf[sizeof(buf) - 1] = '\0';
+
+ s = strchr(buf, '\n');
+ if (s != NULL)
+ *s = '\0';
+ s = strchr(buf, '\r');
+ if (s != NULL)
+ *s = '\0';
+ if (strcmp(buf, "dump") == 0) {
+ dns_zone_dumptostream(zone, stdout);
+ continue;
+ }
+ if (strlen(buf) == 0U)
+ continue;
+ dns_fixedname_init(&name);
+ isc_buffer_init(&buffer, buf, strlen(buf));
+ isc_buffer_add(&buffer, strlen(buf));
+ result = dns_name_fromtext(dns_fixedname_name(&name),
+ &buffer, dns_rootname, ISC_FALSE, NULL);
+ ERRCONT(result, "dns_name_fromtext");
+
+ result = dns_db_find(db, dns_fixedname_name(&name),
+ NULL /*vesion*/,
+ dns_rdatatype_a,
+ 0 /*options*/,
+ 0 /*time*/,
+ NULL /*nodep*/,
+ dns_fixedname_name(&found),
+ &rdataset, &sigset);
+ fprintf(stderr, "%s() returned %s\n", "dns_db_find",
+ dns_result_totext(result));
+ switch (result) {
+ case DNS_R_DELEGATION:
+ print_rdataset(dns_fixedname_name(&found), &rdataset);
+ break;
+ case ISC_R_SUCCESS:
+ print_rdataset(dns_fixedname_name(&name), &rdataset);
+ break;
+ default:
+ break;
+ }
+
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (dns_rdataset_isassociated(&sigset))
+ dns_rdataset_disassociate(&sigset);
+ } while (1);
+ dns_rdataset_invalidate(&rdataset);
+ dns_db_detach(&db);
+}
+
+int
+main(int argc, char **argv) {
+ int c;
+ char *filename = NULL;
+ const char *classname = "IN";
+
+ while ((c = isc_commandline_parse(argc, argv, "cdf:m:qsMS")) != EOF) {
+ switch (c) {
+ case 'c':
+ classname = isc_commandline_argument;
+ break;
+ case 'd':
+ debug++;
+ break;
+ case 'f':
+ if (filename != NULL)
+ usage();
+ filename = isc_commandline_argument;
+ break;
+ case 'm':
+ memset(&addr, 0, sizeof(addr));
+ addr.type.sin.sin_family = AF_INET;
+ inet_pton(AF_INET, isc_commandline_argument,
+ &addr.type.sin.sin_addr);
+ addr.type.sin.sin_port = htons(53);
+ break;
+ case 'q':
+ quiet++;
+ break;
+ case 's':
+ stats++;
+ break;
+ case 'S':
+ zonetype = dns_zone_slave;
+ break;
+ case 'M':
+ zonetype = dns_zone_master;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (argv[isc_commandline_index] == NULL)
+ usage();
+
+ RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_taskmgr_create(mctx, 2, 0, &taskmgr) ==
+ ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr,
+ &zonemgr) == ISC_R_SUCCESS);
+ if (filename == NULL)
+ filename = argv[isc_commandline_index];
+ setup(argv[isc_commandline_index], filename, classname);
+ query();
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+ dns_zonemgr_shutdown(zonemgr);
+ dns_zonemgr_detach(&zonemgr);
+ isc_socketmgr_destroy(&socketmgr);
+ isc_taskmgr_destroy(&taskmgr);
+ isc_timermgr_destroy(&timermgr);
+ if (!quiet && stats)
+ isc_mem_stats(mctx, stdout);
+ isc_mem_destroy(&mctx);
+
+ return (0);
+}
diff --git a/bin/win32/BINDInstall/AccountInfo.cpp b/bin/win32/BINDInstall/AccountInfo.cpp
new file mode 100644
index 0000000..5b28a23
--- /dev/null
+++ b/bin/win32/BINDInstall/AccountInfo.cpp
@@ -0,0 +1,438 @@
+/*
+ * Portions Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2001, 2002 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: AccountInfo.cpp,v 1.8 2007/06/19 23:47:07 tbox Exp $ */
+
+#ifndef UNICODE
+#define UNICODE
+#endif /* UNICODE */
+
+#include "stdafx.h"
+
+#include <windows.h>
+#include <lm.h>
+#include <ntsecapi.h>
+
+#include <isc/ntgroups.h>
+#include <isc/result.h>
+#include "AccountInfo.h"
+
+#define MAX_NAME_LENGTH 256
+
+NTSTATUS
+OpenPolicy(
+ LPWSTR ServerName, /* machine to open policy on (Unicode) */
+ DWORD DesiredAccess, /* desired access to policy */
+ PLSA_HANDLE PolicyHandle /* resultant policy handle */
+ );
+
+BOOL
+GetAccountSid(
+ LPTSTR SystemName, /* where to lookup account */
+ LPTSTR AccountName, /* account of interest */
+ PSID *Sid /* resultant buffer containing SID */
+ );
+
+NTSTATUS
+SetPrivilegeOnAccount(
+ LSA_HANDLE PolicyHandle, /* open policy handle */
+ PSID AccountSid, /* SID to grant privilege to */
+ LPWSTR PrivilegeName, /* privilege to grant (Unicode) */
+ BOOL bEnable /* enable or disable */
+ );
+
+NTSTATUS
+GetPrivilegesOnAccount(
+ LSA_HANDLE PolicyHandle, /* open policy handle */
+ PSID AccountSid, /* SID to grant privilege to */
+ wchar_t **PrivList, /* Ptr to List of Privileges found */
+ unsigned int *PrivCount /* total number of Privileges in list */
+ );
+
+NTSTATUS
+AddPrivilegeToAcccount(
+ LPTSTR AccountName, /* Name of the account */
+ LPWSTR PrivilegeName /* Privilege to Add */
+ );
+
+void
+InitLsaString(
+ PLSA_UNICODE_STRING LsaString, /* destination */
+ LPWSTR String /* source (Unicode) */
+ );
+
+void
+DisplayNtStatus(
+ LPSTR szAPI, /* pointer to function name (ANSI) */
+ NTSTATUS Status /* NTSTATUS error value */
+ );
+
+void
+DisplayWinError(
+ LPSTR szAPI, /* pointer to function name (ANSI) */
+ DWORD WinError /* DWORD WinError */
+ );
+
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+#endif
+
+/*
+ * Note that this code only retrieves the list of privileges of the
+ * requested account or group. However, all accounts belong to the
+ * Everyone group even though that group is not returned by the
+ * calls to get the groups to which that account belongs.
+ * The Everyone group has two privileges associated with it:
+ * SeChangeNotifyPrivilege and SeNetworkLogonRight
+ * It is not advisable to disable or remove these privileges
+ * from the group nor can the account be removed from the Everyone
+ * group
+ * The None group has no privileges associated with it and is the group
+ * to which an account belongs if it is associated with no group.
+ */
+
+int
+GetAccountPrivileges(char *name, wchar_t **PrivList, unsigned int *PrivCount,
+ char **Accounts, unsigned int *totalAccounts,
+ int maxAccounts)
+{
+ LSA_HANDLE PolicyHandle;
+ TCHAR AccountName[256]; /* static account name buffer */
+ PSID pSid;
+ unsigned int i;
+ NTSTATUS Status;
+ isc_result_t istatus;
+ int iRetVal = RTN_ERROR; /* assume error from main */
+
+ /*
+ * Open the policy on the target machine.
+ */
+ if ((Status = OpenPolicy(NULL,
+ POLICY_LOOKUP_NAMES,
+ &PolicyHandle)) != STATUS_SUCCESS)
+ return (RTN_ERROR);
+
+ /*
+ * Let's see if the account exists. Return if not
+ */
+ wsprintf(AccountName, TEXT("%hS"), name);
+ if (!GetAccountSid(NULL, AccountName, &pSid))
+ return (RTN_NOACCOUNT);
+ /*
+ * Find out what groups the account belongs to
+ */
+ istatus = isc_ntsecurity_getaccountgroups(name, Accounts, maxAccounts,
+ totalAccounts);
+ if (istatus == ISC_R_NOMEMORY)
+ return (RTN_NOMEMORY);
+ else if (istatus != ISC_R_SUCCESS)
+ return (RTN_ERROR);
+
+ Accounts[*totalAccounts] = name; /* Add the account to the list */
+ (*totalAccounts)++;
+
+ /*
+ * Loop through each Account to get the list of privileges
+ */
+ for (i = 0; i < *totalAccounts; i++) {
+ wsprintf(AccountName, TEXT("%hS"), Accounts[i]);
+ /* Obtain the SID of the user/group. */
+ if (!GetAccountSid(NULL, AccountName, &pSid))
+ continue; /* Try the next one */
+ /* Get the Privileges allocated to this SID */
+ if ((Status = GetPrivilegesOnAccount(PolicyHandle, pSid,
+ PrivList, PrivCount)) == STATUS_SUCCESS)
+ {
+ iRetVal=RTN_OK;
+ if (pSid != NULL)
+ HeapFree(GetProcessHeap(), 0, pSid);
+ } else {
+ if (pSid != NULL)
+ HeapFree(GetProcessHeap(), 0, pSid);
+ continue; /* Try the next one */
+ }
+ }
+ /*
+ * Close the policy handle.
+ */
+ LsaClose(PolicyHandle);
+
+ (*totalAccounts)--; /* Correct for the number of groups */
+ return iRetVal;
+}
+
+BOOL
+CreateServiceAccount(char *name, char *password) {
+ NTSTATUS retstat;
+ USER_INFO_1 ui;
+ DWORD dwLevel = 1;
+ DWORD dwError = 0;
+ NET_API_STATUS nStatus;
+
+ unsigned int namelen = strlen(name);
+ unsigned int passwdlen = strlen(password);
+ wchar_t AccountName[MAX_NAME_LENGTH];
+ wchar_t AccountPassword[MAX_NAME_LENGTH];
+
+ mbstowcs(AccountName, name, namelen + 1);
+ mbstowcs(AccountPassword, password, passwdlen + 1);
+
+ /*
+ * Set up the USER_INFO_1 structure.
+ * USER_PRIV_USER: name is required here when creating an account
+ * rather than an administrator or a guest.
+ */
+
+ ui.usri1_name = (LPWSTR) &AccountName;
+ ui.usri1_password = (LPWSTR) &AccountPassword;
+ ui.usri1_priv = USER_PRIV_USER;
+ ui.usri1_home_dir = NULL;
+ ui.usri1_comment = L"ISC BIND Service Account";
+ ui.usri1_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD |
+ UF_SCRIPT;
+ ui.usri1_script_path = NULL;
+ /*
+ * Call the NetUserAdd function, specifying level 1.
+ */
+ nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError);
+
+ if (nStatus != NERR_Success)
+ return (FALSE);
+
+ retstat = AddPrivilegeToAcccount(name, SE_SERVICE_LOGON_PRIV);
+ return (TRUE);
+}
+
+NTSTATUS
+AddPrivilegeToAcccount(LPTSTR name, LPWSTR PrivilegeName) {
+ LSA_HANDLE PolicyHandle;
+ TCHAR AccountName[256]; /* static account name buffer */
+ PSID pSid;
+ NTSTATUS Status;
+ unsigned long err;
+
+ /*
+ * Open the policy on the target machine.
+ */
+ if ((Status = OpenPolicy(NULL, POLICY_ALL_ACCESS, &PolicyHandle))
+ != STATUS_SUCCESS)
+ return (RTN_ERROR);
+
+ /*
+ * Let's see if the account exists. Return if not
+ */
+ wsprintf(AccountName, TEXT("%hS"), name);
+ if (!GetAccountSid(NULL, AccountName, &pSid))
+ return (RTN_NOACCOUNT);
+
+ err = LsaNtStatusToWinError(SetPrivilegeOnAccount(PolicyHandle,
+ pSid, PrivilegeName, TRUE));
+
+ LsaClose(PolicyHandle);
+ if (err == ERROR_SUCCESS)
+ return (RTN_OK);
+ else
+ return (err);
+}
+
+void
+InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String){
+ DWORD StringLength;
+
+ if (String == NULL) {
+ LsaString->Buffer = NULL;
+ LsaString->Length = 0;
+ LsaString->MaximumLength = 0;
+ return;
+ }
+
+ StringLength = wcslen(String);
+ LsaString->Buffer = String;
+ LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
+ LsaString->MaximumLength = (USHORT)(StringLength+1) * sizeof(WCHAR);
+}
+
+NTSTATUS
+OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle){
+ LSA_OBJECT_ATTRIBUTES ObjectAttributes;
+ LSA_UNICODE_STRING ServerString;
+ PLSA_UNICODE_STRING Server = NULL;
+
+ /*
+ * Always initialize the object attributes to all zeroes.
+ */
+ ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
+
+ if (ServerName != NULL) {
+ /*
+ * Make a LSA_UNICODE_STRING out of the LPWSTR passed in
+ */
+ InitLsaString(&ServerString, ServerName);
+ Server = &ServerString;
+ }
+
+ /*
+ * Attempt to open the policy.
+ */
+ return (LsaOpenPolicy(Server, &ObjectAttributes, DesiredAccess,
+ PolicyHandle));
+}
+
+BOOL
+GetAccountSid(LPTSTR SystemName, LPTSTR AccountName, PSID *Sid) {
+ LPTSTR ReferencedDomain = NULL;
+ DWORD cbSid = 128; /* initial allocation attempt */
+ DWORD cbReferencedDomain = 16; /* initial allocation size */
+ SID_NAME_USE peUse;
+ BOOL bSuccess = FALSE; /* assume this function will fail */
+
+ __try {
+ /*
+ * initial memory allocations
+ */
+ if ((*Sid = HeapAlloc(GetProcessHeap(), 0, cbSid)) == NULL)
+ __leave;
+
+ if ((ReferencedDomain = (LPTSTR) HeapAlloc(GetProcessHeap(), 0,
+ cbReferencedDomain)) == NULL) __leave;
+
+ /*
+ * Obtain the SID of the specified account on the specified system.
+ */
+ while (!LookupAccountName(SystemName, AccountName, *Sid, &cbSid,
+ ReferencedDomain, &cbReferencedDomain,
+ &peUse))
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ /* reallocate memory */
+ if ((*Sid = HeapReAlloc(GetProcessHeap(), 0,
+ *Sid, cbSid)) == NULL) __leave;
+
+ if ((ReferencedDomain= (LPTSTR) HeapReAlloc(
+ GetProcessHeap(), 0, ReferencedDomain,
+ cbReferencedDomain)) == NULL)
+ __leave;
+ }
+ else
+ __leave;
+ }
+ bSuccess = TRUE;
+ } /* finally */
+ __finally {
+
+ /* Cleanup and indicate failure, if appropriate. */
+
+ HeapFree(GetProcessHeap(), 0, ReferencedDomain);
+
+ if (!bSuccess) {
+ if (*Sid != NULL) {
+ HeapFree(GetProcessHeap(), 0, *Sid);
+ *Sid = NULL;
+ }
+ }
+
+ }
+
+ return (bSuccess);
+}
+
+NTSTATUS
+SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
+ LPWSTR PrivilegeName, BOOL bEnable)
+{
+ LSA_UNICODE_STRING PrivilegeString;
+
+ /* Create a LSA_UNICODE_STRING for the privilege name. */
+ InitLsaString(&PrivilegeString, PrivilegeName);
+
+ /* grant or revoke the privilege, accordingly */
+ if (bEnable)
+ return (LsaAddAccountRights(PolicyHandle, AccountSid,
+ &PrivilegeString, 1));
+ else
+ return (LsaRemoveAccountRights(PolicyHandle, AccountSid,
+ FALSE, &PrivilegeString, 1));
+}
+
+NTSTATUS
+GetPrivilegesOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
+ wchar_t **PrivList, unsigned int *PrivCount)
+{
+ NTSTATUS Status;
+ LSA_UNICODE_STRING *UserRights;
+ ULONG CountOfRights;
+ unsigned int retlen = 0;
+ DWORD i, j;
+ int found;
+
+ Status = LsaEnumerateAccountRights(PolicyHandle, AccountSid,
+ &UserRights, &CountOfRights);
+ /* Only continue if there is something */
+ if (UserRights == NULL || Status != STATUS_SUCCESS)
+ return (Status);
+
+ for (i = 0; i < CountOfRights; i++) {
+ found = -1;
+ retlen = UserRights[i].Length/sizeof(wchar_t);
+ for (j = 0; j < *PrivCount; j++) {
+ found = wcsncmp(PrivList[j], UserRights[i].Buffer,
+ retlen);
+ if (found == 0)
+ break;
+ }
+ if (found != 0) {
+ PrivList[*PrivCount] =
+ (wchar_t *)malloc(UserRights[i].MaximumLength);
+ if (PrivList[*PrivCount] == NULL)
+ return (RTN_NOMEMORY);
+
+ wcsncpy(PrivList[*PrivCount], UserRights[i].Buffer,
+ retlen);
+ PrivList[*PrivCount][retlen] = L'\0';
+ (*PrivCount)++;
+ }
+
+ }
+
+ return (Status);
+}
+
+void
+DisplayNtStatus(LPSTR szAPI, NTSTATUS Status) {
+ /* Convert the NTSTATUS to Winerror. Then call DisplayWinError(). */
+ DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
+}
+
+void
+DisplayWinError(LPSTR szAPI, DWORD WinError) {
+ LPSTR MessageBuffer;
+ DWORD dwBufferLength;
+
+ if (dwBufferLength=FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, WinError, GetUserDefaultLangID(),
+ (LPSTR) &MessageBuffer, 0, NULL)){
+ DWORD dwBytesWritten; /* unused */
+
+ /* Output message string on stderr. */
+ WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer,
+ dwBufferLength, &dwBytesWritten, NULL);
+
+ /* Free the buffer allocated by the system. */
+ LocalFree(MessageBuffer);
+ }
+}
diff --git a/bin/win32/BINDInstall/AccountInfo.h b/bin/win32/BINDInstall/AccountInfo.h
new file mode 100644
index 0000000..4e8098f
--- /dev/null
+++ b/bin/win32/BINDInstall/AccountInfo.h
@@ -0,0 +1,48 @@
+/*
+ * 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: AccountInfo.h,v 1.6 2007/06/19 23:47:07 tbox Exp $ */
+
+
+#define RTN_OK 0
+#define RTN_NOACCOUNT 1
+#define RTN_NOMEMORY 2
+#define RTN_ERROR 10
+
+#define SE_SERVICE_LOGON_PRIV L"SeServiceLogonRight"
+
+/*
+ * This routine retrieves the list of all Privileges associated with
+ * a given account as well as the groups to which it beongs
+ */
+int
+GetAccountPrivileges(
+ char *name, /* Name of Account */
+ wchar_t **PrivList, /* List of Privileges returned */
+ unsigned int *PrivCount, /* Count of Privileges returned */
+ char **Groups, /* List of Groups to which account belongs */
+ unsigned int *totalGroups, /* Count of Groups returned */
+ int maxGroups /* Maximum number of Groups to return */
+ );
+
+/*
+ * This routine creates an account with the given name which has just
+ * the logon service privilege and no membership of any groups,
+ * i.e. it's part of the None group.
+ */
+BOOL
+CreateServiceAccount(char *name, char *password);
diff --git a/bin/win32/BINDInstall/BINDInstall.cpp b/bin/win32/BINDInstall/BINDInstall.cpp
new file mode 100644
index 0000000..f9dc5bc
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.cpp
@@ -0,0 +1,106 @@
+/*
+ * Portions Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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: BINDInstall.cpp,v 1.7 2007/06/19 23:47:07 tbox Exp $ */
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "stdafx.h"
+#include "BINDInstall.h"
+#include "BINDInstallDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallApp
+
+BEGIN_MESSAGE_MAP(CBINDInstallApp, CWinApp)
+ //{{AFX_MSG_MAP(CBINDInstallApp)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG
+ ON_COMMAND(ID_HELP, CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallApp construction
+
+CBINDInstallApp::CBINDInstallApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CBINDInstallApp object
+
+CBINDInstallApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallApp initialization
+
+BOOL CBINDInstallApp::InitInstance()
+{
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+#if _MSC_VER < 1300
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+#endif
+
+ CBINDInstallDlg dlg;
+ m_pMainWnd = &dlg;
+ int nResponse = dlg.DoModal();
+ if (nResponse == IDOK)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with OK
+ }
+ else if (nResponse == IDCANCEL)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with Cancel
+ }
+
+ // Since the dialog has been closed, return FALSE so that we exit the
+ // application, rather than start the application's message pump.
+ return FALSE;
+}
diff --git a/bin/win32/BINDInstall/BINDInstall.dsp b/bin/win32/BINDInstall/BINDInstall.dsp
new file mode 100644
index 0000000..6585d51
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.dsp
@@ -0,0 +1,177 @@
+# Microsoft Developer Studio Project File - Name="BINDInstall" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=BINDInstall - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "BINDInstall.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "BINDInstall.mak" CFG="BINDInstall - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BINDInstall - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "BINDInstall - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /TP /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 version.lib netapi32.lib /nologo /subsystem:windows /pdb:none /machine:I386 /out:"..\..\..\Build\Release\BINDInstall.exe"
+
+!ELSEIF "$(CFG)" == "BINDInstall - Win32 Debug"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /Yu"stdafx.h" /FD /TP /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 version.lib netapi32.lib /nologo /subsystem:windows /pdb:none /debug /machine:I386 /out:"..\..\..\Build\Debug\BINDInstall.exe"
+
+!ENDIF
+
+# Begin Target
+
+# Name "BINDInstall - Win32 Release"
+# Name "BINDInstall - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\AccountInfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BINDInstall.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BINDInstallDlg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\DirBrowse.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\lib\isc\win32\ntgroups.c
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\VersionInfo.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\Accountinfo.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\BINDInstall.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\BINDInstallDlg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DirBrowse.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\lib\isc\win32\include\isc\ntgroups.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\VersionInfo.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\BINDInstall.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\BINDInstall.rc2
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\BINDInstall.rc
+# End Source File
+# End Target
+# End Project
diff --git a/bin/win32/BINDInstall/BINDInstall.dsw b/bin/win32/BINDInstall/BINDInstall.dsw
new file mode 100644
index 0000000..c949bc7
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "BINDInstall"=.\BINDInstall.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/win32/BINDInstall/BINDInstall.h b/bin/win32/BINDInstall/BINDInstall.h
new file mode 100644
index 0000000..4251f25
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.h
@@ -0,0 +1,64 @@
+/*
+ * Portions Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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: BINDInstall.h,v 1.6 2007/06/19 23:47:07 tbox Exp $ */
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * 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 BINDINSTALL_H
+#define BINDINSTALL_H
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+
+class CBINDInstallApp : public CWinApp
+{
+public:
+ CBINDInstallApp();
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CBINDInstallApp)
+ public:
+ virtual BOOL InitInstance();
+ //}}AFX_VIRTUAL
+
+ //{{AFX_MSG(CBINDInstallApp)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif
diff --git a/bin/win32/BINDInstall/BINDInstall.mak b/bin/win32/BINDInstall/BINDInstall.mak
new file mode 100644
index 0000000..c814517
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.mak
@@ -0,0 +1,428 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on BINDInstall.dsp
+!IF "$(CFG)" == ""
+CFG=BINDInstall - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to BINDInstall - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "BINDInstall - Win32 Release" && "$(CFG)" != "BINDInstall - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "BINDInstall.mak" CFG="BINDInstall - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BINDInstall - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "BINDInstall - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\BINDInstall.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\AccountInfo.obj"
+ -@erase "$(INTDIR)\BINDInstall.obj"
+ -@erase "$(INTDIR)\BINDInstall.pch"
+ -@erase "$(INTDIR)\BINDInstall.res"
+ -@erase "$(INTDIR)\BINDInstallDlg.obj"
+ -@erase "$(INTDIR)\DirBrowse.obj"
+ -@erase "$(INTDIR)\ntgroups.obj"
+ -@erase "$(INTDIR)\StdAfx.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\VersionInfo.obj"
+ -@erase "..\..\..\Build\Release\BINDInstall.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fp"$(INTDIR)\BINDInstall.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /c
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\BINDInstall.res" /d "NDEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\BINDInstall.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=version.lib netapi32.lib /nologo /subsystem:windows /pdb:none /machine:I386 /out:"..\..\..\Build\Release\BINDInstall.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\AccountInfo.obj" \
+ "$(INTDIR)\BINDInstall.obj" \
+ "$(INTDIR)\BINDInstallDlg.obj" \
+ "$(INTDIR)\DirBrowse.obj" \
+ "$(INTDIR)\ntgroups.obj" \
+ "$(INTDIR)\StdAfx.obj" \
+ "$(INTDIR)\VersionInfo.obj" \
+ "$(INTDIR)\BINDInstall.res"
+
+"..\..\..\Build\Release\BINDInstall.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "BINDInstall - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\BINDInstall.exe" "$(OUTDIR)\BINDInstall.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\AccountInfo.obj"
+ -@erase "$(INTDIR)\AccountInfo.sbr"
+ -@erase "$(INTDIR)\BINDInstall.obj"
+ -@erase "$(INTDIR)\BINDInstall.pch"
+ -@erase "$(INTDIR)\BINDInstall.res"
+ -@erase "$(INTDIR)\BINDInstall.sbr"
+ -@erase "$(INTDIR)\BINDInstallDlg.obj"
+ -@erase "$(INTDIR)\BINDInstallDlg.sbr"
+ -@erase "$(INTDIR)\DirBrowse.obj"
+ -@erase "$(INTDIR)\DirBrowse.sbr"
+ -@erase "$(INTDIR)\ntgroups.obj"
+ -@erase "$(INTDIR)\ntgroups.sbr"
+ -@erase "$(INTDIR)\StdAfx.obj"
+ -@erase "$(INTDIR)\StdAfx.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\VersionInfo.obj"
+ -@erase "$(INTDIR)\VersionInfo.sbr"
+ -@erase "$(OUTDIR)\BINDInstall.bsc"
+ -@erase "..\..\..\Build\Debug\BINDInstall.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\BINDInstall.pch" /Yu"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /GZ /c
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\BINDInstall.res" /d "_DEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\BINDInstall.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\AccountInfo.sbr" \
+ "$(INTDIR)\BINDInstall.sbr" \
+ "$(INTDIR)\BINDInstallDlg.sbr" \
+ "$(INTDIR)\DirBrowse.sbr" \
+ "$(INTDIR)\ntgroups.sbr" \
+ "$(INTDIR)\StdAfx.sbr" \
+ "$(INTDIR)\VersionInfo.sbr"
+
+"$(OUTDIR)\BINDInstall.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=version.lib netapi32.lib /nologo /subsystem:windows /pdb:none /debug /machine:I386 /out:"..\..\..\Build\Debug\BINDInstall.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\AccountInfo.obj" \
+ "$(INTDIR)\BINDInstall.obj" \
+ "$(INTDIR)\BINDInstallDlg.obj" \
+ "$(INTDIR)\DirBrowse.obj" \
+ "$(INTDIR)\ntgroups.obj" \
+ "$(INTDIR)\StdAfx.obj" \
+ "$(INTDIR)\VersionInfo.obj" \
+ "$(INTDIR)\BINDInstall.res"
+
+"..\..\..\Build\Debug\BINDInstall.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("BINDInstall.dep")
+!INCLUDE "BINDInstall.dep"
+!ELSE
+!MESSAGE Warning: cannot find "BINDInstall.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release" || "$(CFG)" == "BINDInstall - Win32 Debug"
+SOURCE=.\AccountInfo.cpp
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release"
+
+
+"$(INTDIR)\AccountInfo.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - Win32 Debug"
+
+
+"$(INTDIR)\AccountInfo.obj" "$(INTDIR)\AccountInfo.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ENDIF
+
+SOURCE=.\BINDInstall.cpp
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release"
+
+
+"$(INTDIR)\BINDInstall.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - Win32 Debug"
+
+
+"$(INTDIR)\BINDInstall.obj" "$(INTDIR)\BINDInstall.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ENDIF
+
+SOURCE=.\BINDInstallDlg.cpp
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release"
+
+
+"$(INTDIR)\BINDInstallDlg.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - Win32 Debug"
+
+
+"$(INTDIR)\BINDInstallDlg.obj" "$(INTDIR)\BINDInstallDlg.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ENDIF
+
+SOURCE=.\DirBrowse.cpp
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release"
+
+
+"$(INTDIR)\DirBrowse.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - Win32 Debug"
+
+
+"$(INTDIR)\DirBrowse.obj" "$(INTDIR)\DirBrowse.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ENDIF
+
+SOURCE=..\..\..\lib\isc\win32\ntgroups.c
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release"
+
+CPP_SWITCHES=/nologo /MT /W3 /GX /O2 /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /c
+
+"$(INTDIR)\ntgroups.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - Win32 Debug"
+
+CPP_SWITCHES=/nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /GZ /c
+
+"$(INTDIR)\ntgroups.obj" "$(INTDIR)\ntgroups.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+SOURCE=.\StdAfx.cpp
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release"
+
+CPP_SWITCHES=/nologo /MT /W3 /GX /O2 /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Fp"$(INTDIR)\BINDInstall.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /c
+
+"$(INTDIR)\StdAfx.obj" "$(INTDIR)\BINDInstall.pch" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - Win32 Debug"
+
+CPP_SWITCHES=/nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\..\include" /I "..\..\named\win32\include" /I "..\..\..\lib\isc\win32\include" /I "..\..\..\lib\isc\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\BINDInstall.pch" /Yc"stdafx.h" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /TP /GZ /c
+
+"$(INTDIR)\StdAfx.obj" "$(INTDIR)\StdAfx.sbr" "$(INTDIR)\BINDInstall.pch" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+SOURCE=.\VersionInfo.cpp
+
+!IF "$(CFG)" == "BINDInstall - Win32 Release"
+
+
+"$(INTDIR)\VersionInfo.obj" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ELSEIF "$(CFG)" == "BINDInstall - Win32 Debug"
+
+
+"$(INTDIR)\VersionInfo.obj" "$(INTDIR)\VersionInfo.sbr" : $(SOURCE) "$(INTDIR)" "$(INTDIR)\BINDInstall.pch"
+
+
+!ENDIF
+
+SOURCE=.\BINDInstall.rc
+
+"$(INTDIR)\BINDInstall.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/win32/BINDInstall/BINDInstall.rc b/bin/win32/BINDInstall/BINDInstall.rc
new file mode 100644
index 0000000..8bcb636
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstall.rc
@@ -0,0 +1,338 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif //_WIN32\r\n"
+ "#include ""res\\BINDInstall.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "res\\BINDInstall.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_BINDINSTALL_DIALOG DIALOGEX 0, 0, 210, 301
+STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION |
+ WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "BIND 9 Installer"
+FONT 8, "MS Sans Serif",0,0,0x1
+BEGIN
+ EDITTEXT IDC_TARGETDIR,7,62,196,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_ACCOUNT_NAME,7,94,196,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_ACCOUNT_PASSWORD,7,122,196,14,ES_PASSWORD |
+ ES_AUTOHSCROLL
+ EDITTEXT IDC_ACCOUNT_PASSWORD_CONFIRM,7,151,196,14,ES_PASSWORD |
+ ES_AUTOHSCROLL
+ DEFPUSHBUTTON "&Install",IDC_INSTALL,153,7,50,14
+ PUSHBUTTON "E&xit",IDC_EXIT,153,39,50,14
+ CONTROL "&Automatic Startup",IDC_AUTO_START,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,14,190,72,10
+ CONTROL "&Keep Config Files After Uninstall",IDC_KEEP_FILES,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,200,116,10
+ CONTROL "&Start BIND Service After Install",IDC_START,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,14,210,113,10
+ PUSHBUTTON "&Uninstall",IDC_UNINSTALL,153,23,50,14
+ PUSHBUTTON "Browse",IDC_BROWSE,7,22,50,14
+ LTEXT "Target Directory:",IDC_STATIC,7,53,54,8
+ GROUPBOX "Progress",IDC_STATIC,7,224,196,70
+ RTEXT "",IDC_COPY_TAG,14,261,78,8
+ LTEXT "",IDC_COPY_FILE,105,261,90,8
+ RTEXT "",IDC_SERVICE_TAG,15,271,77,8
+ LTEXT "",IDC_REG_SERVICE,105,271,89,8
+ RTEXT "",IDC_MESSAGE_TAG,15,281,77,8
+ LTEXT "",IDC_REG_MESSAGE,105,281,88,8
+ RTEXT "",IDC_DIR_TAG,15,251,77,8
+ GROUPBOX "Options",IDC_STATIC,7,172,196,49
+ CTEXT "Version Unknown",IDC_VERSION,7,7,61,10,SS_CENTERIMAGE |
+ SS_SUNKEN
+ RTEXT "Current Operation:",IDC_CURRENT_TAG,34,235,58,8
+ LTEXT "",IDC_CURRENT,105,235,90,8
+ LTEXT "",IDC_CREATE_DIR,105,251,88,8
+ LTEXT "Service Account Name",IDC_STATIC,7,84,74,8
+ LTEXT "Service Account Password",IDC_STATIC,7,112,86,8
+ LTEXT "Confirm Service Account Password",IDC_STATIC,7,140,112,
+ 8
+END
+
+IDD_BROWSE DIALOG DISCARDABLE 0, 0, 227, 117
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Select Directory"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,170,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,170,24,50,14
+ LISTBOX IDC_DIRLIST,7,28,155,82,LBS_SORT | LBS_NOINTEGRALHEIGHT |
+ WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_CURDIR,7,7,155,14,ES_AUTOHSCROLL
+ COMBOBOX IDC_DRIVES,170,98,50,74,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_VSCROLL | WS_TABSTOP
+END
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,129,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 2,0,0,0
+ PRODUCTVERSION 2,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", "Internet Software Consortium\0"
+ VALUE "FileDescription", "ISC BIND Install Utility\0"
+ VALUE "FileVersion", "2.0.0\0"
+ VALUE "InternalName", "BINDInstall\0"
+ VALUE "LegalCopyright", "Copyright © 2000\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "BINDInstall.EXE\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "ISC BIND\0"
+ VALUE "ProductVersion", "9.3.0\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_BINDINSTALL_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 203
+ VERTGUIDE, 14
+ VERTGUIDE, 92
+ VERTGUIDE, 105
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 294
+ HORZGUIDE, 195
+ HORZGUIDE, 205
+ HORZGUIDE, 215
+ HORZGUIDE, 239
+ HORZGUIDE, 255
+ HORZGUIDE, 265
+ HORZGUIDE, 275
+ HORZGUIDE, 285
+ END
+
+ IDD_BROWSE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 220
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 110
+ END
+
+ IDD_DIALOG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_MAINFRAME "BIND 9 Installer"
+ IDS_CREATEDIR "Directory %s does not exist.\nDo you wish to create it?"
+ IDS_SUCCESS "BIND installation completed successfully"
+ IDS_FAIL "BIND installation failed"
+ IDS_DIREXIST "Directory %s exists.\n Install here anyway?"
+ IDS_INSTALL_DIR "Create Directories..."
+ IDS_INSTALL_FILE "Copy Files..."
+ IDS_INSTALL_SERVICE "Register Service..."
+ IDS_INSTALL_MESSAGE "Register Messages..."
+ IDS_UNINSTALL "Do you wish to uninstall BIND?"
+ IDS_UNINSTALL_DONE "BIND Uninstall Completed"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_CREATE_KEY "Creating BIND registry key"
+ IDS_ADD_REMOVE "Setting up Add/Remove Programs entry"
+ IDS_CLEANUP "Cleaning up"
+ IDS_INSTALL_DONE "Finished Installing"
+ IDS_CREATE_DIR "Creating directory %s"
+ IDS_REMOVE_DIR "Removing directory %s"
+ IDS_COPY_FILE "Copying file %s"
+ IDS_DELETE_FILE "Deleting file %s"
+ IDS_OPEN_SCM "Opening Service Control Manager"
+ IDS_CREATE_SERVICE "Creating BIND service"
+ IDS_OPEN_SERVICE "Opening BIND service"
+ IDS_REMOVE_SERVICE "Removing BIND service"
+ IDS_REGISTER_MESSAGES "Registering BIND message source"
+ IDS_UNREGISTER_MESSAGES "Unregistering BIND message source"
+ IDS_STOP_SERVICE "Stopping BIND service"
+ IDS_START_SERVICE "Starting BIND service"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_UNINSTALL_DIR "Remove Directories..."
+ IDS_UNINSTALL_FILES "Delete Files..."
+ IDS_UNINSTALL_SERVICE "Unregister Service..."
+ IDS_UNINSTALL_MESSAGE "Unregister Messages..."
+ IDS_ERR_OPEN_SCM "Could not open Service Control Manager\n(%s)"
+ IDS_ERR_OPEN_SERVICE "Could not open BIND Service\n(%s)"
+ IDS_ERR_STOP_SERVICE "Could not stop BIND Service\n(%s)"
+ IDS_ERR_NONCRIT_FILE "An error occurred while copying non-critical file %s\n(%s)\nDo you wish to continue?"
+ IDS_ERR_COPY_FILE "An error occurred while copying file %s\n(%s)\nInstallation will be terminated"
+ IDS_ERR_CREATE_SERVICE "Error creating service\n(%s)"
+ IDS_ERR_REMOVE_SERVICE "Error removing service\n(%s)"
+ IDS_REBOOT "BINDInstall needs to restart Windows.\nDo you wish to restart now?"
+ IDS_BAD_PRIVILEGES "This user cannot acquire the privileges necessary to install BIND. Please ensure you are logged on as a member of the Administrators group."
+ IDS_ERR_CREATE_DIR "An error occurred while creating directory %s\n(%s)"
+ IDS_VERSION "Version %s"
+ IDS_ERR_CREATE_KEY "An error occured while creating registry keys\n(%s)"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_ERR_SET_VALUE "An error occured while setting registry key values\n(%s)"
+ IDS_NO_VERSION "Version Unknown"
+ IDS_EXISTING_NEWER "%s\nThe existing version of this file is newer than the version being installed.\nDo you wish to overwrite the existing file?"
+ IDS_FILE_BAD "Could not retrieve version info for file %s. Do you wish to continue?\n(Continuing may overwrite a newer version of the file) "
+ IDS_ERR_TOOPRIVED "Chosen account has too many privileges. Do you wish to choose a different account name?"
+ IDS_ERR_BADACCOUNT "Error Validating Account. Unable to install service using this account."
+ IDS_ERR_WRONGPRIV "The wrong privilege: %s was detected. Only the Service Logon Right privilege should be enabled for this account."
+ IDS_CREATEACCOUNT_FAILED "Unable to Create Account for the Service."
+ IDS_ERR_PASSWORD "Passwords entered did not match. Please reenter password."
+ IDS_ERR_UPDATE_SERVICE "Error updating service\n(%s)"
+ IDS_ERR_NULLPASSWORD "Service account password cannot be null"
+ IDS_ERR_WHITESPACE "Service account password has leading/trailing whitespace"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif //_WIN32
+#include "res\BINDInstall.rc2" // non-Microsoft Visual C++ edited resources
+#include "afxres.rc" // Standard components
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/bin/win32/BINDInstall/BINDInstallDlg.cpp b/bin/win32/BINDInstall/BINDInstallDlg.cpp
new file mode 100644
index 0000000..88d5b72
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstallDlg.cpp
@@ -0,0 +1,1288 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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: BINDInstallDlg.cpp,v 1.37 2007/10/31 01:34:19 marka Exp $ */
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * 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.
+ */
+
+/*
+ * Define this to make a standalone installer that will copy msvcrt.dll
+ * and/or msvcrtd.dll during the install
+ */
+// #define BINARIES_INSTALL
+
+/*
+ * msvcrt.dll is the release c-runtime library for MSVC. msvcrtd.dll is the debug
+ * c-runtime library for MSVC. If you have debug binaries you want to have DEBUG_BINARIES
+ * defined. If you have release binaries you want to have RELEASE_BINARIES defined.
+ * If you have both, then define them both.
+ * Of course, you need msvcrt[d].dll present to install it!
+ */
+#ifdef BINARIES_INSTALL
+// # define DEBUG_BINARIES
+// # define RELEASE_BINARIES
+#endif
+
+#include "stdafx.h"
+#include "BINDInstall.h"
+#include "BINDInstallDlg.h"
+#include "DirBrowse.h"
+#include <winsvc.h>
+#include <named/ntservice.h>
+#include <isc/bind_registry.h>
+#include <isc/ntgroups.h>
+#include <direct.h>
+#include "AccountInfo.h"
+#include "versioninfo.h"
+
+#define MAX_GROUPS 100
+#define MAX_PRIVS 50
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+typedef struct _xexception
+{
+ _xexception(UINT string, ...);
+
+ CString resString;
+} Exception;
+
+_xexception::_xexception(UINT string, ...)
+{
+ CString format;
+ va_list va;
+
+ format.LoadString(string);
+
+ va_start(va, string);
+ resString.FormatV(format, va);
+ va_end(va);
+}
+
+typedef struct _filedata {
+ enum FileDestinations {TargetDir, BinDir, EtcDir, WinSystem};
+ enum FileImportance {Trivial, Normal, Critical};
+
+ char *filename;
+ int destination;
+ int importance;
+ BOOL checkVer;
+
+} FileData;
+
+const FileData installFiles[] =
+{
+#ifdef BINARIES_INSTALL
+# ifdef DEBUG_BINARIES
+ {"msvcrtd.dll", FileData::WinSystem, FileData::Critical, TRUE},
+# endif
+# ifdef RELEASE_BINARIES
+ {"msvcrt.dll", FileData::WinSystem, FileData::Critical, TRUE},
+# endif
+#endif
+#if _MSC_VER < 1400
+#if _MSC_VER >= 1310
+ {"mfc71.dll", FileData::WinSystem, FileData::Critical, TRUE},
+ {"msvcr71.dll", FileData::WinSystem, FileData::Critical, TRUE},
+#elif _MSC_VER > 1200 && _MSC_VER < 1310
+ {"mfc70.dll", FileData::WinSystem, FileData::Critical, TRUE},
+ {"msvcr70.dll", FileData::WinSystem, FileData::Critical, TRUE},
+#endif
+#endif
+ {"bindevt.dll", FileData::BinDir, FileData::Normal, FALSE},
+ {"libbind9.dll", FileData::BinDir, FileData::Critical, FALSE},
+ {"libisc.dll", FileData::BinDir, FileData::Critical, FALSE},
+ {"libisccfg.dll", FileData::BinDir, FileData::Critical, FALSE},
+ {"libisccc.dll", FileData::BinDir, FileData::Critical, FALSE},
+ {"libdns.dll", FileData::BinDir, FileData::Critical, FALSE},
+ {"liblwres.dll", FileData::BinDir, FileData::Critical, FALSE},
+ {"libeay32.dll", FileData::BinDir, FileData::Critical, FALSE},
+ {"named.exe", FileData::BinDir, FileData::Critical, FALSE},
+ {"nsupdate.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"BINDInstall.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"rndc.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"dig.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"host.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"nslookup.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"rndc-confgen.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"dnssec-keygen.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"dnssec-signzone.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"named-checkconf.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"named-checkzone.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"named-compilezone.exe", FileData::BinDir, FileData::Normal, FALSE},
+ {"readme1st.txt", FileData::BinDir, FileData::Trivial, FALSE},
+ {NULL, -1, -1}
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallDlg dialog
+
+CBINDInstallDlg::CBINDInstallDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CBINDInstallDlg::IDD, pParent) {
+ char buf[MAX_PATH];
+
+ //{{AFX_DATA_INIT(CBINDInstallDlg)
+ m_targetDir = _T("");
+ m_version = _T("");
+ m_autoStart = FALSE;
+ m_keepFiles = FALSE;
+ m_current = _T("");
+ m_startOnInstall = FALSE;
+ m_accountName = _T("");
+ m_accountPassword = _T("");
+ m_accountName = _T("");
+ //}}AFX_DATA_INIT
+ // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
+ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+
+ GetSystemDirectory(buf, MAX_PATH);
+ m_winSysDir = buf;
+ m_defaultDir = buf;
+ m_defaultDir += "\\dns";
+ m_installed = FALSE;
+ m_accountExists = FALSE;
+ m_accountUsed = FALSE;
+ m_serviceExists = TRUE;
+ GetCurrentServiceAccountName();
+ m_currentAccount = m_accountName;
+ if (m_accountName == "") {
+ m_accountName = "named";
+ }
+}
+
+void CBINDInstallDlg::DoDataExchange(CDataExchange* pDX) {
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CBINDInstallDlg)
+ DDX_Text(pDX, IDC_TARGETDIR, m_targetDir);
+ DDX_Text(pDX, IDC_VERSION, m_version);
+ DDX_Text(pDX, IDC_ACCOUNT_NAME, m_accountName);
+ DDX_Text(pDX, IDC_ACCOUNT_PASSWORD, m_accountPassword);
+ DDX_Text(pDX, IDC_ACCOUNT_PASSWORD_CONFIRM, m_accountPasswordConfirm);
+ DDX_Check(pDX, IDC_AUTO_START, m_autoStart);
+ DDX_Check(pDX, IDC_KEEP_FILES, m_keepFiles);
+ DDX_Text(pDX, IDC_CURRENT, m_current);
+ DDX_Check(pDX, IDC_START, m_startOnInstall);
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CBINDInstallDlg, CDialog)
+ //{{AFX_MSG_MAP(CBINDInstallDlg)
+ ON_WM_PAINT()
+ ON_WM_QUERYDRAGICON()
+ ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
+ ON_BN_CLICKED(IDC_INSTALL, OnInstall)
+ ON_BN_CLICKED(IDC_EXIT, OnExit)
+ ON_BN_CLICKED(IDC_UNINSTALL, OnUninstall)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallDlg message handlers
+
+BOOL CBINDInstallDlg::OnInitDialog() {
+ CDialog::OnInitDialog();
+
+ // Set the icon for this dialog. The framework does this automatically
+ // when the application's main window is not a dialog
+ SetIcon(m_hIcon, TRUE); // Set big icon
+ SetIcon(m_hIcon, FALSE); // Set small icon
+
+ char filename[MAX_PATH];
+ char dirname[MAX_PATH];
+ char *fptr = &filename[0];
+ GetModuleFileName(NULL, filename, MAX_PATH);
+ char *dptr = strrchr(filename,'\\');
+ int index = dptr - fptr;
+ strncpy(dirname, filename, index);
+ dirname[index] = '\0';
+ CString Dirname(dirname);
+ m_currentDir = Dirname;
+
+ CVersionInfo bindInst(filename);
+ if(bindInst.IsValid())
+ m_version.Format(IDS_VERSION, bindInst.GetFileVersionString());
+ else
+ m_version.LoadString(IDS_NO_VERSION);
+
+ DWORD dwBufLen = MAX_PATH;
+ char buf[MAX_PATH];
+ HKEY hKey;
+
+ m_startOnInstall = CheckBINDService();
+
+ /* See if we are installed already */
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SUBKEY, 0, KEY_READ, &hKey)
+ == ERROR_SUCCESS) {
+ m_installed = TRUE;
+ memset(buf, 0, MAX_PATH);
+ // Get the install directory
+ if (RegQueryValueEx(hKey, "InstallDir", NULL, NULL, (LPBYTE)buf,
+ &dwBufLen) == ERROR_SUCCESS)
+ if (strcmp(buf, ""))
+ m_defaultDir = buf;
+
+ RegCloseKey(hKey);
+ }
+ m_targetDir = m_defaultDir;
+
+ // Set checkbox defaults
+ m_autoStart = TRUE;
+ m_keepFiles = TRUE;
+
+ UpdateData(FALSE);
+
+ return (TRUE); /* return(TRUE) unless you set the focus to a control */
+}
+
+/*
+ * If you add a minimize button to your dialog, you will need the code below
+ * to draw the icon. For MFC applications using the document/view model,
+ * this is automatically done for you by the framework.
+ */
+
+void CBINDInstallDlg::OnPaint() {
+ if (IsIconic()) {
+ CPaintDC dc(this); // device context for painting
+
+ SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
+
+ // Center icon in client rectangle
+ int cxIcon = GetSystemMetrics(SM_CXICON);
+ int cyIcon = GetSystemMetrics(SM_CYICON);
+ CRect rect;
+ GetClientRect(&rect);
+ int x = (rect.Width() - cxIcon + 1) / 2;
+ int y = (rect.Height() - cyIcon + 1) / 2;
+
+ // Draw the icon
+ dc.DrawIcon(x, y, m_hIcon);
+ }
+ else {
+ CDialog::OnPaint();
+ }
+}
+
+// The system calls this to obtain the cursor to display while the user drags
+// the minimized window.
+HCURSOR CBINDInstallDlg::OnQueryDragIcon() {
+ return((HCURSOR)m_hIcon);
+}
+
+void CBINDInstallDlg::OnBrowse() {
+
+ CDirBrowse browse;
+
+ if (browse.DoModal() == IDOK) {
+ //m_targetDir = browse.m_selectedDir;
+ UpdateData(FALSE);
+ }
+}
+
+/*
+ * User pressed the exit button
+ */
+void CBINDInstallDlg::OnExit() {
+ EndDialog(0);
+}
+
+/*
+ * User pressed the uninstall button. Make it go.
+ */
+void CBINDInstallDlg::OnUninstall() {
+ UpdateData();
+
+ if (MsgBox(IDS_UNINSTALL, MB_YESNO) == IDYES) {
+ if (CheckBINDService())
+ StopBINDService();
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL,
+ SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ return;
+ }
+
+ SC_HANDLE hService = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (!hService && GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST){
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ return;
+ }
+
+ SERVICE_STATUS ss;
+ QueryServiceStatus(hService, &ss);
+ if (ss.dwCurrentState == SERVICE_RUNNING) {
+ BOOL rc = ControlService(hService,
+ SERVICE_CONTROL_STOP, &ss);
+ if (rc == FALSE || ss.dwCurrentState != SERVICE_STOPPED) {
+ MsgBox(IDS_ERR_STOP_SERVICE, GetErrMessage());
+ return;
+ }
+
+ }
+ CloseServiceHandle(hService);
+ CloseServiceHandle(hSCManager);
+
+ // Directories
+ m_etcDir = m_targetDir + "\\etc";
+ m_binDir = m_targetDir + "\\bin";
+
+ UninstallTags();
+ UnregisterMessages(TRUE);
+ UnregisterService(TRUE);
+ DeleteFiles(TRUE);
+ if (m_keepFiles == FALSE)
+ RemoveDirs(TRUE);
+ else
+ GetDlgItem(IDC_CREATE_DIR)->SetWindowText("Not Removed");
+
+
+ // Delete registry keys for named
+ RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_SESSION_SUBKEY);
+ RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_SUBKEY);
+ RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_UNINSTALL_SUBKEY);
+
+ ProgramGroup(FALSE);
+
+ SetCurrent(IDS_UNINSTALL_DONE);
+ MsgBox(IDS_UNINSTALL_DONE);
+ }
+}
+
+/*
+ * User pressed the install button. Make it go.
+ */
+void CBINDInstallDlg::OnInstall() {
+#if _MSC_VER >= 1400
+ char Vcredist_x86[MAX_PATH];
+#endif
+ BOOL success = FALSE;
+ int oldlen;
+
+ if (CheckBINDService())
+ StopBINDService();
+
+ InstallTags();
+
+ UpdateData();
+
+ /*
+ * Check that the Passwords entered match.
+ */
+ if (m_accountPassword != m_accountPasswordConfirm) {
+ MsgBox(IDS_ERR_PASSWORD);
+ return;
+ }
+
+ /*
+ * Check that there is not leading / trailing whitespace.
+ * This is for compatability with the standard password dialog.
+ * Passwords really should be treated as opaque blobs.
+ */
+ oldlen = m_accountPassword.GetLength();
+ m_accountPassword.TrimLeft();
+ m_accountPassword.TrimRight();
+ if (m_accountPassword.GetLength() != oldlen) {
+ MsgBox(IDS_ERR_WHITESPACE);
+ return;
+ }
+
+ /*
+ * Check the entered account name.
+ */
+ if (ValidateServiceAccount() == FALSE)
+ return;
+
+ /*
+ * For Registration we need to know if account was changed.
+ */
+ if (m_accountName != m_currentAccount)
+ m_accountUsed = FALSE;
+
+ if (m_accountUsed == FALSE && m_serviceExists == FALSE)
+ {
+ /*
+ * Check that the Password is not null.
+ */
+ if (m_accountPassword.GetLength() == 0) {
+ MsgBox(IDS_ERR_NULLPASSWORD);
+ return;
+ }
+ }
+
+ /* Directories */
+ m_etcDir = m_targetDir + "\\etc";
+ m_binDir = m_targetDir + "\\bin";
+
+ if (m_defaultDir != m_targetDir) {
+ if (GetFileAttributes(m_targetDir) != 0xFFFFFFFF)
+ {
+ int install = MsgBox(IDS_DIREXIST,
+ MB_YESNO | MB_ICONQUESTION, m_targetDir);
+ if (install == IDNO)
+ return;
+ }
+ else {
+ int createDir = MsgBox(IDS_CREATEDIR,
+ MB_YESNO | MB_ICONQUESTION, m_targetDir);
+ if (createDir == IDNO)
+ return;
+ }
+ }
+
+ if (m_accountExists == FALSE) {
+ success = CreateServiceAccount(m_accountName.GetBuffer(30),
+ m_accountPassword.GetBuffer(30));
+ if (success == FALSE) {
+ MsgBox(IDS_CREATEACCOUNT_FAILED);
+ return;
+ }
+ m_accountExists = TRUE;
+ }
+
+ ProgramGroup(FALSE);
+
+#if _MSC_VER >= 1400
+ /*
+ * Install Visual Studio libraries. As per:
+ * http://blogs.msdn.com/astebner/archive/2006/08/23/715755.aspx
+ *
+ * Vcredist_x86.exe /q:a /c:"msiexec /i vcredist.msi /qn /l*v %temp%\vcredist_x86.log"
+ */
+ /*system(".\\Vcredist_x86.exe /q:a /c:\"msiexec /i vcredist.msi /qn /l*v %temp%\vcredist_x86.log\"");*/
+
+ /*
+ * Enclose full path to Vcredist_x86.exe in quotes as
+ * m_currentDir may contain spaces.
+ */
+ sprintf(Vcredist_x86, "\"%s\\Vcredist_x86.exe\"",
+ (LPCTSTR) m_currentDir);
+ system(Vcredist_x86);
+#endif
+ try {
+ CreateDirs();
+ CopyFiles();
+ RegisterService();
+ RegisterMessages();
+
+ HKEY hKey;
+
+ /* Create a new key for named */
+ SetCurrent(IDS_CREATE_KEY);
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_SUBKEY,
+ &hKey) == ERROR_SUCCESS) {
+ // Get the install directory
+ RegSetValueEx(hKey, "InstallDir", 0, REG_SZ,
+ (LPBYTE)(LPCTSTR)m_targetDir,
+ m_targetDir.GetLength());
+ RegCloseKey(hKey);
+ }
+
+
+ SetCurrent(IDS_ADD_REMOVE);
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_UNINSTALL_SUBKEY,
+ &hKey) == ERROR_SUCCESS) {
+ CString buf(BIND_DISPLAY_NAME);
+
+ RegSetValueEx(hKey, "DisplayName", 0, REG_SZ,
+ (LPBYTE)(LPCTSTR)buf, buf.GetLength());
+
+ buf.Format("%s\\BINDInstall.exe", m_binDir);
+ RegSetValueEx(hKey, "UninstallString", 0, REG_SZ,
+ (LPBYTE)(LPCTSTR)buf, buf.GetLength());
+ RegCloseKey(hKey);
+ }
+
+ ProgramGroup(FALSE);
+
+ if (m_startOnInstall)
+ StartBINDService();
+ }
+ catch(Exception e) {
+ MessageBox(e.resString);
+ SetCurrent(IDS_CLEANUP);
+ FailedInstall();
+ MsgBox(IDS_FAIL);
+ return;
+ }
+ catch(DWORD dw) {
+ CString msg;
+ msg.Format("A fatal error occured\n(%s)", GetErrMessage(dw));
+ MessageBox(msg);
+ SetCurrent(IDS_CLEANUP);
+ FailedInstall();
+ MsgBox(IDS_FAIL);
+ return;
+ }
+
+ SetCurrent(IDS_INSTALL_DONE);
+ MsgBox(IDS_SUCCESS);
+}
+
+/*
+ * Methods to do the work
+ */
+void CBINDInstallDlg::CreateDirs() {
+ /* s'OK if the directories already exist */
+ SetCurrent(IDS_CREATE_DIR, m_targetDir);
+ if (!CreateDirectory(m_targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_DIR, m_targetDir, GetErrMessage()));
+
+ SetCurrent(IDS_CREATE_DIR, m_etcDir);
+ if (!CreateDirectory(m_etcDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_DIR, m_etcDir, GetErrMessage()));
+
+ SetCurrent(IDS_CREATE_DIR, m_binDir);
+ if (!CreateDirectory(m_binDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_DIR, m_binDir, GetErrMessage()));
+
+ SetItemStatus(IDC_CREATE_DIR);
+}
+
+void CBINDInstallDlg::RemoveDirs(BOOL uninstall) {
+ if (!m_keepFiles) {
+ SetCurrent(IDS_REMOVE_DIR, m_binDir);
+ // Check for existence then remove if present
+ if (GetFileAttributes(m_binDir) != 0xFFFFFFFF)
+ RemoveDirectory(m_binDir);
+
+ SetCurrent(IDS_REMOVE_DIR, m_etcDir);
+ if (GetFileAttributes(m_etcDir) != 0xFFFFFFFF)
+ RemoveDirectory(m_etcDir);
+
+ SetCurrent(IDS_REMOVE_DIR, m_targetDir);
+ if (GetFileAttributes(m_targetDir) != 0xFFFFFFFF)
+ RemoveDirectory(m_targetDir);
+ }
+
+ if (uninstall)
+ SetItemStatus(IDC_CREATE_DIR, TRUE);
+}
+
+void CBINDInstallDlg::CopyFiles() {
+ CString destFile;
+
+ for (int i = 0; installFiles[i].filename; i++) {
+ SetCurrent(IDS_COPY_FILE, installFiles[i].filename);
+
+ destFile = DestDir(installFiles[i].destination) + "\\" +
+ installFiles[i].filename;
+ CString filespec = m_currentDir + "\\" + installFiles[i].filename;
+ CVersionInfo bindFile(destFile);
+
+ CVersionInfo origFile(filespec);
+ if (!origFile.IsValid() && installFiles[i].checkVer) {
+ if (MsgBox(IDS_FILE_BAD, MB_YESNO,
+ installFiles[i].filename) == IDNO)
+ throw(Exception(IDS_ERR_COPY_FILE,
+ installFiles[i].filename,
+ GetErrMessage()));
+ }
+
+ try {
+/*
+ * Ignore Version checking. We need to make sure that all files get copied regardless
+ * of whether or not they are earlier or later versions since we cannot guarantee
+ * that we have either backward or forward compatibility between versions.
+ */
+ bindFile.CopyFileNoVersion(origFile);
+ }
+ catch(...) {
+ if (installFiles[i].importance != FileData::Trivial) {
+ if (installFiles[i].importance ==
+ FileData::Critical ||
+ MsgBox(IDS_ERR_NONCRIT_FILE, MB_YESNO,
+ installFiles[i].filename,
+ GetErrMessage()) == IDNO)
+ {
+ SetItemStatus(IDC_COPY_FILE, FALSE);
+ throw(Exception(IDS_ERR_COPY_FILE,
+ installFiles[i].filename,
+ GetErrMessage()));
+ }
+ }
+ }
+ }
+
+ SetItemStatus(IDC_COPY_FILE);
+}
+
+void CBINDInstallDlg::DeleteFiles(BOOL uninstall) {
+ CString destFile;
+
+ for (int i = 0; installFiles[i].filename; i++) {
+ if (installFiles[i].checkVer)
+ continue;
+
+ destFile = DestDir(installFiles[i].destination) + "\\" +
+ installFiles[i].filename;
+
+ if (uninstall)
+ SetCurrent(IDS_DELETE_FILE, installFiles[i].filename);
+
+ DeleteFile(destFile);
+ }
+
+ if (!m_keepFiles) {
+ WIN32_FIND_DATA findData;
+ CString file = m_etcDir + "\\*.*";
+ BOOL rc;
+ HANDLE hFile;
+
+ hFile = FindFirstFile(file, &findData);
+ rc = hFile != INVALID_HANDLE_VALUE;
+
+ while (rc == TRUE) {
+ if (strcmp(findData.cFileName, ".") &&
+ strcmp(findData.cFileName, "..")) {
+ file = m_etcDir + "\\" + findData.cFileName;
+ SetCurrent(IDS_DELETE_FILE, file);
+ DeleteFile(file);
+ }
+ rc = FindNextFile(hFile, &findData);
+ }
+ FindClose(hFile);
+ }
+
+ if (uninstall)
+ SetItemStatus(IDC_COPY_FILE, TRUE);
+}
+
+/*
+ * Get the service account name out of the registry, if any
+ */
+void
+CBINDInstallDlg::GetCurrentServiceAccountName() {
+ HKEY hKey;
+ BOOL keyFound = FALSE;
+ char accountName[MAX_PATH];
+ DWORD nameLen = MAX_PATH;
+ CString Tmp;
+ m_accountUsed = FALSE;
+
+ memset(accountName, 0, nameLen);
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SERVICE_SUBKEY, 0, KEY_READ,
+ &hKey) == ERROR_SUCCESS) {
+ keyFound = TRUE;
+ }
+ else {
+ m_serviceExists = FALSE;
+ }
+
+ if (keyFound == TRUE) {
+ /* Get the named service account, if one was specified */
+ if (RegQueryValueEx(hKey, "ObjectName", NULL, NULL,
+ (LPBYTE)accountName, &nameLen) != ERROR_SUCCESS)
+ keyFound = FALSE;
+ }
+
+ RegCloseKey(hKey);
+ if(keyFound == FALSE)
+ m_accountName = "";
+ else {
+ /*
+ * LocalSystem is not a regular account and is equivalent
+ * to no account but with lots of privileges
+ */
+ Tmp = accountName;
+ if (Tmp == ".\\LocalSystem")
+ m_accountName = "";
+ /* Found account strip any ".\" from it */
+ if (Tmp.Left(2) == ".\\") {
+ m_accountName = Tmp.Mid(2);
+ m_accountUsed = TRUE;
+ }
+ }
+}
+
+BOOL
+CBINDInstallDlg::ValidateServiceAccount() {
+ wchar_t *PrivList[MAX_PRIVS];
+ unsigned int PrivCount = 0;
+ char *Groups[MAX_GROUPS];
+ unsigned int totalGroups = 0;
+ int status;
+ char *name;
+
+ name = m_accountName.GetBuffer(30);
+
+ status = GetAccountPrivileges(name, PrivList, &PrivCount,
+ Groups, &totalGroups, MAX_GROUPS);
+ if (status == RTN_NOACCOUNT) {
+ m_accountExists = FALSE;
+ /* We need to do this in case an account was previously used */
+ m_accountUsed = FALSE;
+ return (TRUE);
+ }
+ if (status != RTN_OK) {
+ MsgBox(IDS_ERR_BADACCOUNT);
+ return (FALSE);
+ }
+
+ m_accountExists = TRUE;
+ if (PrivCount > 1) {
+ if (MsgBox(IDS_ERR_TOOPRIVED, MB_YESNO) == IDYES)
+ return (FALSE);
+ else
+ return (TRUE);
+ }
+
+ /* See if we have the correct privilege */
+ if (wcscmp(PrivList[0], SE_SERVICE_LOGON_PRIV) != 0) {
+ MsgBox(IDS_ERR_WRONGPRIV, PrivList[0]);
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+void
+CBINDInstallDlg::RegisterService() {
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+ CString StartName = ".\\" + m_accountName;
+
+ /*
+ * We need to change the service rather than create it
+ * if the service already exists. Do nothing if we are already
+ * using that account
+ */
+ if(m_serviceExists == TRUE) {
+ if(m_accountUsed == FALSE) {
+ UpdateService();
+ SetItemStatus(IDC_REG_SERVICE);
+ return;
+ }
+ else {
+ SetItemStatus(IDC_REG_SERVICE);
+ return;
+ }
+ }
+
+ SetCurrent(IDS_OPEN_SCM);
+ hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager)
+ throw(Exception(IDS_ERR_OPEN_SCM, GetErrMessage()));
+
+ DWORD dwStart = SERVICE_DEMAND_START;
+ if (m_autoStart)
+ dwStart = SERVICE_AUTO_START;
+
+ DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+
+ CString namedLoc;
+ namedLoc.Format("%s\\bin\\named.exe", m_targetDir);
+
+ SetCurrent(IDS_CREATE_SERVICE);
+ hService = CreateService(hSCManager, BIND_SERVICE_NAME,
+ BIND_DISPLAY_NAME, SERVICE_ALL_ACCESS, dwServiceType, dwStart,
+ SERVICE_ERROR_NORMAL, namedLoc, NULL, NULL, NULL, StartName,
+ m_accountPassword);
+
+ if (!hService && GetLastError() != ERROR_SERVICE_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_SERVICE, GetErrMessage()));
+
+ if (hService)
+ CloseServiceHandle(hService);
+
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+
+ SetItemStatus(IDC_REG_SERVICE);
+}
+
+void
+CBINDInstallDlg::UpdateService() {
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+ CString StartName = ".\\" + m_accountName;
+
+ SetCurrent(IDS_OPEN_SCM);
+ hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ return;
+ }
+
+ DWORD dwStart = SERVICE_DEMAND_START;
+ if (m_autoStart)
+ dwStart = SERVICE_AUTO_START;
+
+ DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+
+ CString namedLoc;
+ namedLoc.Format("%s\\bin\\named.exe", m_targetDir);
+
+ SetCurrent(IDS_OPEN_SERVICE);
+ hService = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_CHANGE_CONFIG);
+ if (!hService)
+ {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+ return;
+ }
+ else {
+ if (ChangeServiceConfig(hService, dwServiceType, dwStart,
+ SERVICE_ERROR_NORMAL, namedLoc, NULL, NULL, NULL,
+ StartName, m_accountPassword,BIND_DISPLAY_NAME)
+ != TRUE) {
+ DWORD err = GetLastError();
+ MsgBox(IDS_ERR_UPDATE_SERVICE, GetErrMessage());
+ }
+ }
+
+ if (hService)
+ CloseServiceHandle(hService);
+
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+
+ SetItemStatus(IDC_REG_SERVICE);
+}
+
+void CBINDInstallDlg::UnregisterService(BOOL uninstall) {
+ BOOL rc = FALSE;
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+
+ while(1) {
+ SetCurrent(IDS_OPEN_SCM);
+ hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager && uninstall == TRUE) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ break;
+ }
+
+ SetCurrent(IDS_OPEN_SERVICE);
+ hService = OpenService(hSCManager, BIND_SERVICE_NAME,
+ STANDARD_RIGHTS_REQUIRED);
+ if (!hService && uninstall == TRUE)
+ {
+ if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ break;
+ }
+ }
+ else {
+ SetCurrent(IDS_REMOVE_SERVICE);
+ if (!DeleteService(hService) && uninstall == TRUE) {
+ DWORD err = GetLastError();
+ if (err != ERROR_SERVICE_MARKED_FOR_DELETE &&
+ err != ERROR_SERVICE_DOES_NOT_EXIST) {
+ MsgBox(IDS_ERR_REMOVE_SERVICE, GetErrMessage());
+ break;
+ }
+ }
+ }
+
+ rc = TRUE;
+ break;
+ }
+
+ if (hService)
+ CloseServiceHandle(hService);
+
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+
+ if (uninstall)
+ SetItemStatus(IDC_REG_SERVICE, rc);
+}
+
+void CBINDInstallDlg::RegisterMessages() {
+ HKEY hKey;
+ DWORD dwData;
+ char pszMsgDLL[MAX_PATH];
+
+ sprintf(pszMsgDLL, "%s\\%s", (LPCTSTR)m_binDir, "bindevt.dll");
+
+ SetCurrent(IDS_REGISTER_MESSAGES);
+ /* Create a new key for named */
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_MESSAGE_SUBKEY, &hKey)
+ != ERROR_SUCCESS)
+ throw(Exception(IDS_ERR_CREATE_KEY, GetErrMessage()));
+
+ /* Add the Event-ID message-file name to the subkey. */
+ if (RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ,
+ (LPBYTE)pszMsgDLL, strlen(pszMsgDLL) + 1) != ERROR_SUCCESS)
+ throw(Exception(IDS_ERR_SET_VALUE, GetErrMessage()));
+
+ /* Set the supported types flags and addit to the subkey. */
+ dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
+ if (RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD,
+ (LPBYTE)&dwData, sizeof(DWORD)) != ERROR_SUCCESS)
+ throw(Exception(IDS_ERR_SET_VALUE, GetErrMessage()));
+
+ RegCloseKey(hKey);
+
+ SetItemStatus(IDC_REG_MESSAGE);
+}
+
+void CBINDInstallDlg::UnregisterMessages(BOOL uninstall) {
+ BOOL rc = FALSE;
+ HKEY hKey = NULL;
+
+ while(1) {
+ SetCurrent(IDS_UNREGISTER_MESSAGES);
+ /* Open key for Application Event Log */
+ if (RegOpenKey(HKEY_LOCAL_MACHINE, EVENTLOG_APP_SUBKEY, &hKey)
+ != ERROR_SUCCESS)
+ break;
+
+ /* Remove named from the list of messages sources */
+ if (RegDeleteKey(hKey, BIND_MESSAGE_NAME) != ERROR_SUCCESS)
+ break;
+
+ rc = TRUE;
+ break;
+ }
+
+ if (hKey)
+ RegCloseKey(hKey);
+
+ if (uninstall)
+ SetItemStatus(IDC_REG_MESSAGE, rc);
+}
+
+/*
+ * Install failed - clean up quietly
+ */
+void CBINDInstallDlg::FailedInstall() {
+ UnregisterMessages(FALSE);
+ UnregisterService(FALSE);
+ DeleteFiles(FALSE);
+ RemoveDirs(FALSE);
+}
+
+/*
+ * Set the checklist tags for install
+ */
+void CBINDInstallDlg::InstallTags() {
+ CString tag;
+
+ tag.LoadString(IDS_INSTALL_FILE);
+ GetDlgItem(IDC_COPY_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_COPY_FILE)->SetWindowText("");
+
+ tag.LoadString(IDS_INSTALL_DIR);
+ GetDlgItem(IDC_DIR_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_CREATE_DIR)->SetWindowText("");
+ GetDlgItem(IDC_REG_SERVICE)->SetWindowText("");
+
+ tag.LoadString(IDS_INSTALL_SERVICE);
+ GetDlgItem(IDC_SERVICE_TAG)->SetWindowText(tag);
+
+ tag.LoadString(IDS_INSTALL_MESSAGE);
+ GetDlgItem(IDC_MESSAGE_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_REG_MESSAGE)->SetWindowText("");
+}
+
+/*
+ * Set the checklist tags for uninstall
+ */
+void CBINDInstallDlg::UninstallTags() {
+ CString tag;
+
+ tag.LoadString(IDS_UNINSTALL_FILES);
+ GetDlgItem(IDC_COPY_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_COPY_FILE)->SetWindowText("");
+
+ tag.LoadString(IDS_UNINSTALL_DIR);
+ GetDlgItem(IDC_DIR_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_CREATE_DIR)->SetWindowText("");
+
+ tag.LoadString(IDS_UNINSTALL_SERVICE);
+ GetDlgItem(IDC_SERVICE_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_REG_SERVICE)->SetWindowText("");
+
+ tag.LoadString(IDS_UNINSTALL_MESSAGE);
+ GetDlgItem(IDC_MESSAGE_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_REG_MESSAGE)->SetWindowText("");
+}
+
+void CBINDInstallDlg::SetItemStatus(UINT nID, BOOL bSuccess) {
+ GetDlgItem(nID)->SetWindowText(bSuccess == TRUE ? "Done" : "Failed");
+}
+
+
+/*
+ * Set the text in the current operation field - use a string table string
+ */
+void CBINDInstallDlg::SetCurrent(int id, ...) {
+ CString format;
+ va_list va;
+ char buf[128];
+
+ format.LoadString(id);
+ memset(buf, 0, 128);
+
+ va_start(va, id);
+ vsprintf(buf, format, va);
+ va_end(va);
+
+ m_current.Format("%s", buf);
+ UpdateData(FALSE);
+}
+
+/*
+ * Stop the BIND service
+ */
+void CBINDInstallDlg::StopBINDService() {
+ SERVICE_STATUS svcStatus;
+
+ SetCurrent(IDS_STOP_SERVICE);
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ }
+
+ SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (!hBINDSvc) {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ }
+
+ BOOL rc = ControlService(hBINDSvc, SERVICE_CONTROL_STOP, &svcStatus);
+}
+
+/*
+ * Start the BIND service
+ */
+void CBINDInstallDlg::StartBINDService() {
+ SetCurrent(IDS_START_SERVICE);
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ }
+
+ SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (!hBINDSvc) {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ }
+ BOOL rc = StartService(hBINDSvc, 0, NULL);
+}
+
+/*
+ * Check to see if the BIND service is running or not
+ */
+BOOL CBINDInstallDlg::CheckBINDService() {
+ SERVICE_STATUS svcStatus;
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (hSCManager) {
+ SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (hBINDSvc) {
+ BOOL rc = ControlService(hBINDSvc,
+ SERVICE_CONTROL_INTERROGATE, &svcStatus);
+ if (!rc)
+ DWORD err = GetLastError();
+
+ return (svcStatus.dwCurrentState == SERVICE_RUNNING);
+ }
+ }
+ return (FALSE);
+}
+
+/*
+ * Display message boxes with variable args, using string table strings
+ * for the format specifiers
+ */
+int CBINDInstallDlg::MsgBox(int id, ...) {
+ CString format;
+ va_list va;
+ char buf[BUFSIZ];
+
+ format.LoadString(id);
+ memset(buf, 0, BUFSIZ);
+
+ va_start(va, id);
+ vsprintf(buf, format, va);
+ va_end(va);
+
+ return (MessageBox(buf));
+}
+
+int CBINDInstallDlg::MsgBox(int id, UINT type, ...) {
+ CString format;
+ va_list va;
+ char buf[BUFSIZ];
+
+ format.LoadString(id);
+ memset(buf, 0, BUFSIZ);
+
+ va_start(va, type);
+ vsprintf(buf, format, va);
+ va_end(va);
+
+ return(MessageBox(buf, NULL, type));
+}
+
+/*
+ * Call GetLastError(), retrieve the message associated with the error
+ */
+CString CBINDInstallDlg::GetErrMessage(DWORD err) {
+ LPVOID msgBuf;
+ static char buf[BUFSIZ];
+
+ DWORD len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err == -1 ? GetLastError() : err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msgBuf, 0, NULL );
+
+
+ strcpy(buf, (LPTSTR)msgBuf);
+ LocalFree(msgBuf);
+ /* Strip off the period and the \n */
+ buf[len - 3] = 0;
+ return(buf);
+}
+
+void CBINDInstallDlg::ProgramGroup(BOOL create) {
+ TCHAR path[MAX_PATH], commonPath[MAX_PATH], fileloc[MAX_PATH], linkpath[MAX_PATH];
+ HRESULT hres;
+ IShellLink *psl = NULL;
+ LPMALLOC pMalloc = NULL;
+ ITEMIDLIST *itemList = NULL;
+
+ HRESULT hr = SHGetMalloc(&pMalloc);
+ if (hr != NOERROR) {
+ MessageBox("Could not get a handle to Shell memory object");
+ return;
+ }
+
+ hr = SHGetSpecialFolderLocation(m_hWnd, CSIDL_COMMON_PROGRAMS, &itemList);
+ if (hr != NOERROR) {
+ MessageBox("Could not get a handle to the Common Programs folder");
+ if (itemList) {
+ pMalloc->Free(itemList);
+ }
+ return;
+ }
+
+ hr = SHGetPathFromIDList(itemList, commonPath);
+ pMalloc->Free(itemList);
+
+ if (create) {
+ sprintf(path, "%s\\ISC", commonPath);
+ CreateDirectory(path, NULL);
+
+ sprintf(path, "%s\\ISC\\BIND", commonPath);
+ CreateDirectory(path, NULL);
+
+ hres = CoInitialize(NULL);
+
+ if (SUCCEEDED(hres)) {
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl);
+ if (SUCCEEDED(hres))
+ {
+ IPersistFile* ppf;
+ sprintf(linkpath, "%s\\BINDCtrl.lnk", path);
+ sprintf(fileloc, "%s\\BINDCtrl.exe", m_binDir);
+
+ psl->SetPath(fileloc);
+ psl->SetDescription("BIND Control Panel");
+
+ hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
+ if (SUCCEEDED(hres)) {
+ WCHAR wsz[MAX_PATH];
+
+ MultiByteToWideChar(CP_ACP, 0, linkpath, -1, wsz, MAX_PATH);
+ hres = ppf->Save(wsz, TRUE);
+ ppf->Release();
+ }
+
+ if (GetFileAttributes("readme.txt") != -1) {
+ sprintf(fileloc, "%s\\Readme.txt", m_targetDir);
+ sprintf(linkpath, "%s\\Readme.lnk", path);
+
+ psl->SetPath(fileloc);
+ psl->SetDescription("BIND Readme");
+
+ hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
+ if (SUCCEEDED(hres)) {
+ WCHAR wsz[MAX_PATH];
+
+ MultiByteToWideChar(CP_ACP, 0, linkpath, -1, wsz, MAX_PATH);
+ hres = ppf->Save(wsz, TRUE);
+ ppf->Release();
+ }
+ psl->Release();
+ }
+ }
+ CoUninitialize();
+ }
+ }
+ else {
+ TCHAR filename[MAX_PATH];
+ WIN32_FIND_DATA fd;
+
+ sprintf(path, "%s\\ISC\\BIND", commonPath);
+
+ sprintf(filename, "%s\\*.*", path);
+ HANDLE hFind = FindFirstFile(filename, &fd);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ if (strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..")) {
+ sprintf(filename, "%s\\%s", path, fd.cFileName);
+ DeleteFile(filename);
+ }
+ } while (FindNextFile(hFind, &fd));
+ FindClose(hFind);
+ }
+ RemoveDirectory(path);
+ sprintf(path, "%s\\ISC", commonPath);
+ RemoveDirectory(path);
+ }
+}
+
+CString CBINDInstallDlg::DestDir(int destination) {
+ switch(destination) {
+ case FileData::TargetDir:
+ return m_targetDir;
+ case FileData::BinDir:
+ return m_binDir;
+ case FileData::EtcDir:
+ return m_etcDir;
+ case FileData::WinSystem:
+ return m_winSysDir;
+ }
+ return("");
+}
diff --git a/bin/win32/BINDInstall/BINDInstallDlg.h b/bin/win32/BINDInstall/BINDInstallDlg.h
new file mode 100644
index 0000000..597f7a3
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstallDlg.h
@@ -0,0 +1,127 @@
+/*
+ * Portions Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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: BINDInstallDlg.h,v 1.8 2007/06/19 23:47:07 tbox Exp $ */
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * 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 BINDINSTALLDLG_H
+#define BINDINSTALLDLG_H
+
+class CBINDInstallDlg : public CDialog
+{
+public:
+ CBINDInstallDlg(CWnd* pParent = NULL); // standard constructor
+
+ //{{AFX_DATA(CBINDInstallDlg)
+ enum { IDD = IDD_BINDINSTALL_DIALOG };
+ CString m_targetDir;
+ CString m_version;
+ BOOL m_autoStart;
+ BOOL m_keepFiles;
+ CString m_current;
+ BOOL m_startOnInstall;
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CBINDInstallDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+protected:
+ void StartBINDService();
+ void StopBINDService();
+
+ void InstallTags();
+ void UninstallTags();
+
+ void CreateDirs();
+ void RemoveDirs(BOOL uninstall);
+
+ void CopyFiles();
+ void DeleteFiles(BOOL uninstall);
+
+ void RegisterService();
+ void UpdateService();
+ void UnregisterService(BOOL uninstall);
+
+ void RegisterMessages();
+ void UnregisterMessages(BOOL uninstall);
+
+ void FailedInstall();
+ void SetItemStatus(UINT nID, BOOL bSuccess = TRUE);
+
+ void GetCurrentServiceAccountName();
+ BOOL ValidateServiceAccount();
+protected:
+ CString DestDir(int destination);
+ int MsgBox(int id, ...);
+ int MsgBox(int id, UINT type, ...);
+ CString GetErrMessage(DWORD err = -1);
+ BOOL CheckBINDService();
+ void SetCurrent(int id, ...);
+ void ProgramGroup(BOOL create = TRUE);
+
+ HICON m_hIcon;
+ CString m_defaultDir;
+ CString m_etcDir;
+ CString m_binDir;
+ CString m_winSysDir;
+ BOOL m_installed;
+ CString m_currentDir;
+ BOOL m_accountExists;
+ BOOL m_accountUsed;
+ CString m_currentAccount;
+ CString m_accountName;
+ CString m_accountPasswordConfirm;
+ CString m_accountPassword;
+ BOOL m_serviceExists;
+
+ // Generated message map functions
+ //{{AFX_MSG(CBINDInstallDlg)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnPaint();
+ afx_msg HCURSOR OnQueryDragIcon();
+ afx_msg void OnBrowse();
+ afx_msg void OnChangeTargetdir();
+ afx_msg void OnInstall();
+ afx_msg void OnExit();
+ afx_msg void OnUninstall();
+ afx_msg void OnAutoStart();
+ afx_msg void OnKeepFiles();
+ afx_msg void OnStartOnInstall();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif
diff --git a/bin/win32/BINDInstall/DirBrowse.cpp b/bin/win32/BINDInstall/DirBrowse.cpp
new file mode 100644
index 0000000..b4fbf91
--- /dev/null
+++ b/bin/win32/BINDInstall/DirBrowse.cpp
@@ -0,0 +1,103 @@
+/*
+ * Portions Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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: DirBrowse.cpp,v 1.6 2007/06/19 23:47:07 tbox Exp $ */
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include "stdafx.h"
+#include "BINDInstall.h"
+#include "DirBrowse.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CDirBrowse dialog
+
+
+CDirBrowse::CDirBrowse(CString initialDir, CWnd* pParent /*=NULL*/)
+ : CDialog(CDirBrowse::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CDirBrowse)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+ m_selectedDir = initialDir;
+}
+
+
+void CDirBrowse::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CDirBrowse)
+ // NOTE: the ClassWizard will add DDX and DDV calls here
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CDirBrowse, CDialog)
+ //{{AFX_MSG_MAP(CDirBrowse)
+ ON_LBN_DBLCLK(IDC_DIRLIST, OnDblclkDirlist)
+ ON_LBN_SELCHANGE(IDC_DIRLIST, OnSelchangeDirlist)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CDirBrowse message handlers
+
+BOOL CDirBrowse::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+ DlgDirList((LPTSTR)(LPCTSTR)m_selectedDir, IDC_DIRLIST, IDC_CURDIR, DDL_DIRECTORY);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+void CDirBrowse::OnDblclkDirlist()
+{
+ CListBox *lb = (CListBox *)GetDlgItem(IDC_DIRLIST);
+ CString curSel;
+
+ lb->GetText(lb->GetCurSel(), curSel);
+ DlgDirList((LPTSTR)(LPCTSTR)curSel, IDC_DIRLIST, IDC_CURDIR, DDL_DIRECTORY);
+}
+
+void CDirBrowse::OnSelchangeDirlist()
+{
+ // TODO: Add your control notification handler code here
+
+}
diff --git a/bin/win32/BINDInstall/DirBrowse.h b/bin/win32/BINDInstall/DirBrowse.h
new file mode 100644
index 0000000..a81605f
--- /dev/null
+++ b/bin/win32/BINDInstall/DirBrowse.h
@@ -0,0 +1,71 @@
+/*
+ * Portions Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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: DirBrowse.h,v 1.6 2007/06/19 23:47:07 tbox Exp $ */
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * 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 DIRBROWSE_H
+#define DIRBROWSE_H
+
+class CDirBrowse : public CDialog
+{
+// Construction
+public:
+ CDirBrowse(CString initialDir = "\\", CWnd* pParent = NULL); // standard constructor
+ CString GetSelectedDir() {return(m_selectedDir);}
+
+ //{{AFX_DATA(CDirBrowse)
+ enum { IDD = IDD_BROWSE };
+ // NOTE: the ClassWizard will add data members here
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CDirBrowse)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CDirBrowse)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnDblclkDirlist();
+ afx_msg void OnSelchangeDirlist();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+private:
+ CString m_selectedDir;
+};
+
+#endif
diff --git a/bin/win32/BINDInstall/StdAfx.cpp b/bin/win32/BINDInstall/StdAfx.cpp
new file mode 100644
index 0000000..a4195ca
--- /dev/null
+++ b/bin/win32/BINDInstall/StdAfx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// BINDInstall.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
+
diff --git a/bin/win32/BINDInstall/StdAfx.h b/bin/win32/BINDInstall/StdAfx.h
new file mode 100644
index 0000000..d5929bb
--- /dev/null
+++ b/bin/win32/BINDInstall/StdAfx.h
@@ -0,0 +1,30 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#if !defined(AFX_STDAFX_H__61537819_39FC_11D3_A97A_00105A12BD65__INCLUDED_)
+#define AFX_STDAFX_H__61537819_39FC_11D3_A97A_00105A12BD65__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__61537819_39FC_11D3_A97A_00105A12BD65__INCLUDED_)
diff --git a/bin/win32/BINDInstall/VersionInfo.cpp b/bin/win32/BINDInstall/VersionInfo.cpp
new file mode 100644
index 0000000..e940e9e
--- /dev/null
+++ b/bin/win32/BINDInstall/VersionInfo.cpp
@@ -0,0 +1,286 @@
+// VersionInfo.cpp: implementation of the CVersionInfo class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "stdafx.h"
+#include "bindinstall.h"
+#include "VersionInfo.h"
+#include <winver.h>
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CVersionInfo::CVersionInfo(CString filename)
+{
+ HANDLE hFile;
+ WIN32_FIND_DATA fd;
+ memset(&fd, 0, sizeof(WIN32_FIND_DATA));
+
+ m_status = ERROR_SUCCESS;
+ m_isValid = FALSE;
+ m_filename = filename;
+
+ // See if the given file exists
+ hFile = FindFirstFile(filename, &fd);
+ if(hFile == INVALID_HANDLE_VALUE)
+ {
+ m_status = ERROR_FILE_NOT_FOUND;
+ m_versionInfo = NULL;
+ return;
+ }
+ FindClose(hFile);
+
+ // Extract the file info
+ DWORD handle;
+ DWORD viSize = GetFileVersionInfoSize((LPTSTR)(LPCTSTR)filename, &handle);
+ m_versionInfo = NULL;
+
+ if(viSize == 0)
+ {
+ m_status = GetLastError();
+ }
+ else
+ {
+ m_versionInfo = new char[viSize];
+
+ // Get the block of version info from the file
+ if(!GetFileVersionInfo((LPTSTR)(LPCTSTR)filename, handle, viSize, m_versionInfo))
+ {
+ if(m_versionInfo)
+ {
+ delete [] m_versionInfo;
+ m_versionInfo = NULL;
+ }
+ return;
+ }
+
+ // Now extract the sub block we are interested in
+ UINT versionLen = 0;
+ LPVOID viBlob = NULL;
+ if(!VerQueryValue(m_versionInfo, "\\", &viBlob, &versionLen))
+ {
+ if(m_versionInfo)
+ {
+ delete [] m_versionInfo;
+ m_versionInfo = NULL;
+ }
+ return;
+ }
+
+ // And finally the version info is ours
+ m_fixedInfo = (VS_FIXEDFILEINFO *)viBlob;
+
+ UINT blobLen = 0;
+
+ // If we got here, all is good
+ }
+ m_isValid = TRUE;
+}
+
+CVersionInfo::~CVersionInfo()
+{
+ m_fixedInfo = NULL;
+ if(m_versionInfo)
+ {
+ delete [] m_versionInfo;
+ m_versionInfo = NULL;
+ }
+}
+
+CString CVersionInfo::GetFileVersionString()
+{
+ return(QueryStringValue("FileVersion"));
+}
+
+CString CVersionInfo::GetProductVersionString()
+{
+ return(QueryStringValue("ProductVersion"));
+}
+
+CString CVersionInfo::GetComments()
+{
+ return(QueryStringValue("Comments"));
+}
+
+CString CVersionInfo::GetFileDescription()
+{
+ return(QueryStringValue("FileDescription"));
+}
+
+CString CVersionInfo::GetInternalName()
+{
+ return(QueryStringValue("InternalName"));
+}
+
+CString CVersionInfo::GetLegalCopyright()
+{
+ return(QueryStringValue("LegalCopyright"));
+}
+
+CString CVersionInfo::GetLegalTrademarks()
+{
+ return(QueryStringValue("LegalTrademarks"));
+}
+
+CString CVersionInfo::GetOriginalFileName()
+{
+ return(QueryStringValue("OriginalFilename"));
+}
+
+CString CVersionInfo::GetProductName()
+{
+ return(QueryStringValue("ProductName"));
+}
+
+CString CVersionInfo::GetSpecialBuildString()
+{
+ return(QueryStringValue("SpecialBuild"));
+}
+
+CString CVersionInfo::GetPrivateBuildString()
+{
+ return(QueryStringValue("PrivateBuild"));
+}
+
+CString CVersionInfo::GetCompanyName()
+{
+ return(QueryStringValue("CompanyName"));
+}
+
+#ifdef NOTUSED
+BOOL CVersionInfo::CopyFileCheckVersion(CVersionInfo &originalFile)
+{
+ _int64 myVer = GetFileVersion();
+ _int64 origVer = originalFile.GetFileVersion();
+
+ if(origVer > myVer)
+ {
+ CString msg;
+ msg.Format(IDS_EXISTING_NEWER, m_filename);
+ DWORD query = AfxMessageBox(msg, MB_YESNO);
+ if(query == IDNO)
+ return(TRUE);
+ }
+
+ return(CopyFileNoVersion(originalFile));
+}
+#endif
+
+BOOL CVersionInfo::CopyFileNoVersion(CVersionInfo &originalFile)
+{
+ int x = 7;
+ return(CopyFile(originalFile.GetFilename(), m_filename, FALSE));
+}
+
+
+_int64 CVersionInfo::GetFileVersion()
+{
+ _int64 ver = 0;
+
+ if(m_versionInfo)
+ {
+ ver = m_fixedInfo->dwFileVersionMS;
+ ver <<= 32;
+ ver += m_fixedInfo->dwFileVersionLS;
+ }
+ return(ver);
+}
+
+_int64 CVersionInfo::GetProductVersion()
+{
+ _int64 ver = 0;
+
+ if(m_versionInfo)
+ {
+ ver = m_fixedInfo->dwProductVersionMS;
+ ver <<= 32;
+ ver += m_fixedInfo->dwProductVersionLS;
+ }
+ return(ver);
+}
+
+_int64 CVersionInfo::GetFileDate()
+{
+ _int64 fDate = 0;
+
+ if(m_versionInfo)
+ {
+ fDate = m_fixedInfo->dwFileDateMS;
+ fDate <<= 32;
+ fDate += m_fixedInfo->dwFileDateLS;
+ }
+ return(fDate);
+}
+
+DWORD CVersionInfo::GetFileFlagMask()
+{
+ if(m_versionInfo)
+ {
+ return(m_fixedInfo->dwFileFlagsMask);
+ }
+ return(0);
+}
+
+DWORD CVersionInfo::GetFileFlags()
+{
+ if(m_versionInfo)
+ {
+ return(m_fixedInfo->dwFileFlags);
+ }
+ return(0);
+}
+
+DWORD CVersionInfo::GetFileOS()
+{
+ if(m_versionInfo)
+ {
+ return(m_fixedInfo->dwFileOS);
+ }
+ return(VOS_UNKNOWN);
+}
+
+DWORD CVersionInfo::GetFileType()
+{
+ if(m_versionInfo)
+ {
+ return(m_fixedInfo->dwFileType);
+ }
+ return(VFT_UNKNOWN);
+}
+
+DWORD CVersionInfo::GetFileSubType()
+{
+ if(m_versionInfo)
+ {
+ return(m_fixedInfo->dwFileSubtype);
+ }
+ return(VFT2_UNKNOWN);
+}
+
+CString CVersionInfo::QueryStringValue(CString value)
+{
+ UINT blobLen = 0;
+ LPVOID viBlob = NULL;
+
+ if(m_versionInfo)
+ {
+ char queryString[256];
+
+ // This code page value is for American English. If you change the resources to be other than that
+ // You probably should change this to match it.
+ DWORD codePage = 0x040904B0;
+
+ sprintf(queryString, "\\StringFileInfo\\%08X\\%s", codePage, value);
+
+ if(VerQueryValue(m_versionInfo, queryString, &viBlob, &blobLen))
+ return((char *)viBlob);
+ }
+ return("Not Available");
+}
diff --git a/bin/win32/BINDInstall/VersionInfo.h b/bin/win32/BINDInstall/VersionInfo.h
new file mode 100644
index 0000000..ec21540
--- /dev/null
+++ b/bin/win32/BINDInstall/VersionInfo.h
@@ -0,0 +1,62 @@
+// VersionInfo.h: interface for the CVersionInfo class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_VERSIONINFO_H__F82E9FF3_5298_11D4_AB87_00C04F789BA0__INCLUDED_)
+#define AFX_VERSIONINFO_H__F82E9FF3_5298_11D4_AB87_00C04F789BA0__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class CVersionInfo
+{
+public:
+ CVersionInfo(CString filename);
+ virtual ~CVersionInfo();
+ BOOL IsValid() {return m_isValid;}
+ DWORD GetStatus() {return m_status;}
+
+ BOOL CopyFileCheckVersion(CVersionInfo &originalFile);
+ BOOL CopyFileNoVersion(CVersionInfo &originalFile);
+
+ const CString &GetFilename() {return m_filename;}
+
+ // Extract the elements of the file's string info block
+ CString GetFileVersionString();
+ CString GetProductVersionString();
+ CString GetComments();
+ CString GetFileDescription();
+ CString GetInternalName();
+ CString GetLegalCopyright();
+ CString GetLegalTrademarks();
+ CString GetOriginalFileName();
+ CString GetProductName();
+ CString GetSpecialBuildString();
+ CString GetPrivateBuildString();
+ CString GetCompanyName();
+
+
+ // Extract the elements of the file's VS_FIXEDFILEINFO block
+ _int64 GetFileVersion();
+ _int64 GetProductVersion();
+ _int64 GetFileDate();
+
+ DWORD GetFileFlagMask();
+ DWORD GetFileFlags();
+ DWORD GetFileOS();
+ DWORD GetFileType();
+ DWORD GetFileSubType();
+
+private:
+ CString m_filename;
+ BOOL m_isValid;
+ LPVOID m_versionInfo;
+ VS_FIXEDFILEINFO *m_fixedInfo;
+ DWORD m_codePage;
+ DWORD m_status;
+
+ CString QueryStringValue(CString value);
+};
+
+#endif // !defined(AFX_VERSIONINFO_H__F82E9FF3_5298_11D4_AB87_00C04F789BA0__INCLUDED_)
diff --git a/bin/win32/BINDInstall/res/BINDInstall.ico b/bin/win32/BINDInstall/res/BINDInstall.ico
new file mode 100644
index 0000000..2cf25fe
--- /dev/null
+++ b/bin/win32/BINDInstall/res/BINDInstall.ico
Binary files differ
diff --git a/bin/win32/BINDInstall/res/BINDInstall.rc2 b/bin/win32/BINDInstall/res/BINDInstall.rc2
new file mode 100644
index 0000000..4fc93bb
--- /dev/null
+++ b/bin/win32/BINDInstall/res/BINDInstall.rc2
@@ -0,0 +1,13 @@
+//
+// BINDINSTALL.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/bin/win32/BINDInstall/resource.h b/bin/win32/BINDInstall/resource.h
new file mode 100644
index 0000000..14b5084
--- /dev/null
+++ b/bin/win32/BINDInstall/resource.h
@@ -0,0 +1,103 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by BINDInstall.rc
+//
+#define IDS_MAINFRAME 1
+#define IDS_CREATEDIR 2
+#define IDS_SUCCESS 3
+#define IDS_FAIL 4
+#define IDS_DIREXIST 5
+#define IDS_INSTALL_DIR 6
+#define IDS_INSTALL_FILE 7
+#define IDS_INSTALL_SERVICE 8
+#define IDS_INSTALL_MESSAGE 9
+#define IDS_UNINSTALL 14
+#define IDS_UNINSTALL_DONE 15
+#define IDS_CREATE_KEY 16
+#define IDS_ADD_REMOVE 17
+#define IDS_CLEANUP 18
+#define IDS_INSTALL_DONE 19
+#define IDS_CREATE_DIR 20
+#define IDS_REMOVE_DIR 21
+#define IDS_COPY_FILE 22
+#define IDS_DELETE_FILE 23
+#define IDS_OPEN_SCM 24
+#define IDS_CREATE_SERVICE 25
+#define IDS_OPEN_SERVICE 26
+#define IDS_REMOVE_SERVICE 27
+#define IDS_REGISTER_MESSAGES 28
+#define IDS_UNREGISTER_MESSAGES 29
+#define IDS_STOP_SERVICE 30
+#define IDS_START_SERVICE 31
+#define IDS_UNINSTALL_DIR 32
+#define IDS_UNINSTALL_FILES 33
+#define IDS_UNINSTALL_SERVICE 34
+#define IDS_UNINSTALL_MESSAGE 35
+#define IDS_ERR_OPEN_SCM 36
+#define IDS_ERR_OPEN_SERVICE 37
+#define IDS_ERR_STOP_SERVICE 38
+#define IDS_ERR_NONCRIT_FILE 39
+#define IDS_ERR_CRITICAL_FILE 40
+#define IDS_ERR_COPY_FILE 40
+#define IDS_ERR_CREATE_SERVICE 41
+#define IDS_ERR_REMOVE_SERVICE 42
+#define IDS_REBOOT 43
+#define IDS_BAD_PRIVILEGES 44
+#define IDS_ERR_CREATE_DIR 45
+#define IDS_VERSION 46
+#define IDS_ERR_CREATE_KEY 47
+#define IDS_ERR_SET_VALUE 48
+#define IDS_NO_VERSION 49
+#define IDS_EXISTING_NEWER 50
+#define IDS_FILE_BAD 51
+#define IDS_ERR_TOOPRIVED 52
+#define IDS_ERR_BADACCOUNT 53
+#define IDS_ERR_WRONGPRIV 54
+#define IDS_CREATEACCOUNT_FAILED 55
+#define IDS_ERR_PASSWORD 56
+#define IDS_ERR_UPDATE_SERVICE 57
+#define IDS_ERR_NULLPASSWORD 58
+#define IDS_ERR_WHITESPACE 59
+#define IDD_BINDINSTALL_DIALOG 102
+#define IDR_MAINFRAME 128
+#define IDD_BROWSE 129
+#define IDI_CHECK 130
+#define IDI_X 132
+#define IDC_CURSOR1 142
+#define IDD_DIALOG1 143
+#define IDC_TARGETDIR 1001
+#define IDC_BROWSE 1002
+#define IDC_DIRLIST 1004
+#define IDC_CURDIR 1005
+#define IDC_INSTALL 1006
+#define IDC_COPY_FILE 1007
+#define IDC_REG_SERVICE 1008
+#define IDC_REG_MESSAGE 1009
+#define IDC_CREATE_DIR 1010
+#define IDC_EXIT 1011
+#define IDC_DIR_TAG 1012
+#define IDC_COPY_TAG 1013
+#define IDC_SERVICE_TAG 1014
+#define IDC_MESSAGE_TAG 1015
+#define IDC_AUTO_START 1016
+#define IDC_UNINSTALL 1017
+#define IDC_VERSION 1018
+#define IDC_KEEP_FILES 1019
+#define IDC_CURRENT_TAG 1020
+#define IDC_DRIVES 1021
+#define IDC_CURRENT 1021
+#define IDC_START 1022
+#define IDC_ACCOUNT_NAME 1030
+#define IDC_ACCOUNT_PASSWORD 1031
+#define IDC_ACCOUNT_PASSWORD_CONFIRM 1032
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 144
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1027
+#define _APS_NEXT_SYMED_VALUE 104
+#endif
+#endif
diff --git a/config.guess b/config.guess
new file mode 100644
index 0000000..7d0185e
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1447 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+timestamp='2004-09-07'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "${UNAME_VERSION}" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amd64:OpenBSD:*:*)
+ echo x86_64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ cats:OpenBSD:*:*)
+ echo arm-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ luna88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips64-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:MirBSD:*:*)
+ echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE="alpha" ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE="alpha" ;;
+ "EV5 (21164)")
+ UNAME_MACHINE="alphaev5" ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE="alphaev56" ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE="alphapca56" ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE="alphapca57" ;;
+ "EV6 (21264)")
+ UNAME_MACHINE="alphaev6" ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE="alphaev67" ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE="alphaev68" ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE="alphaev69" ;;
+ "EV7 (21364)")
+ UNAME_MACHINE="alphaev7" ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE="alphaev79" ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit 0 ;;
+ DRS?6000:UNIX_SV:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7 && exit 0 ;;
+ esac ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c \
+ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && exit 0
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ ${HP_ARCH} = "hppa2.0w" ]
+ then
+ # avoid double evaluation of $set_cc_for_build
+ test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ then
+ HP_ARCH="hppa2.0w"
+ else
+ HP_ARCH="hppa64"
+ fi
+ fi
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:[34]*)
+ echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+ exit 0 ;;
+ [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ cris:Linux:*:*)
+ echo cris-axis-linux-gnu
+ exit 0 ;;
+ crisv32:Linux:*:*)
+ echo crisv32-axis-linux-gnu
+ exit 0 ;;
+ frv:Linux:*:*)
+ echo frv-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ mips64:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips64
+ #undef mips64el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mips64el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips64
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh64*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit 0 ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit 0 ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ *86) UNAME_PROCESSOR=i686 ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit 0 ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms && exit 0 ;;
+ I*) echo ia64-dec-vms && exit 0 ;;
+ V*) echo vax-dec-vms && exit 0 ;;
+ esac
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..ac28b56
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,340 @@
+/* config.h.in. Generated from configure.in by autoheader. */
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: config.h.in,v 1.106 2008/10/21 02:43:07 marka Exp $ */
+
+/*! \file */
+
+/***
+ *** This file is not to be included by any public header files, because
+ *** it does not get installed.
+ ***/
+
+/** define to `int' if <sys/types.h> doesn't define. */
+#undef ssize_t
+
+/** define on DEC OSF to enable 4.4BSD style sa_len support */
+#undef _SOCKADDR_LEN
+
+/** define if your system needs pthread_init() before using pthreads */
+#undef NEED_PTHREAD_INIT
+
+/** define if your system has sigwait() */
+#undef HAVE_SIGWAIT
+
+/** define if sigwait() is the UnixWare flavor */
+#undef HAVE_UNIXWARE_SIGWAIT
+
+/** define on Solaris to get sigwait() to work using pthreads semantics */
+#undef _POSIX_PTHREAD_SEMANTICS
+
+/** define if LinuxThreads is in use */
+#undef HAVE_LINUXTHREADS
+
+/** define if sysconf() is available */
+#undef HAVE_SYSCONF
+
+/** define if sysctlbyname() is available */
+#undef HAVE_SYSCTLBYNAME
+
+/** define if catgets() is available */
+#undef HAVE_CATGETS
+
+/** define if getifaddrs() exists */
+#undef HAVE_GETIFADDRS
+
+/** define if you have the NET_RT_IFLIST sysctl variable and sys/sysctl.h */
+#undef HAVE_IFLIST_SYSCTL
+
+/** define if chroot() is available */
+#undef HAVE_CHROOT
+
+/** define if tzset() is available */
+#undef HAVE_TZSET
+
+/** define if struct addrinfo exists */
+#undef HAVE_ADDRINFO
+
+/** define if getaddrinfo() exists */
+#undef HAVE_GETADDRINFO
+
+/** define if gai_strerror() exists */
+#undef HAVE_GAISTRERROR
+
+/** define if arc4random() exists */
+#undef HAVE_ARC4RANDOM
+
+/**
+ * define if pthread_setconcurrency() should be called to tell the
+ * OS how many threads we might want to run.
+ */
+#undef CALL_PTHREAD_SETCONCURRENCY
+
+/** define if IPv6 is not disabled */
+#undef WANT_IPV6
+
+/** define if flockfile() is available */
+#undef HAVE_FLOCKFILE
+
+/** define if getc_unlocked() is available */
+#undef HAVE_GETCUNLOCKED
+
+/** Shut up warnings about sputaux in stdio.h on BSD/OS pre-4.1 */
+#undef SHUTUP_SPUTAUX
+#ifdef SHUTUP_SPUTAUX
+struct __sFILE;
+extern __inline int __sputaux(int _c, struct __sFILE *_p);
+#endif
+
+/** Shut up warnings about missing sigwait prototype on BSD/OS 4.0* */
+#undef SHUTUP_SIGWAIT
+#ifdef SHUTUP_SIGWAIT
+int sigwait(const unsigned int *set, int *sig);
+#endif
+
+/** Shut up warnings from gcc -Wcast-qual on BSD/OS 4.1. */
+#undef SHUTUP_STDARG_CAST
+#if defined(SHUTUP_STDARG_CAST) && defined(__GNUC__)
+#include <stdarg.h> /** Grr. Must be included *every time*. */
+/**
+ * The silly continuation line is to keep configure from
+ * commenting out the #undef.
+ */
+
+#undef \
+ va_start
+#define va_start(ap, last) \
+ do { \
+ union { const void *konst; long *var; } _u; \
+ _u.konst = &(last); \
+ ap = (va_list)(_u.var + __va_words(__typeof(last))); \
+ } while (0)
+#endif /** SHUTUP_STDARG_CAST && __GNUC__ */
+
+/** define if the system has a random number generating device */
+#undef PATH_RANDOMDEV
+
+/** define if pthread_attr_getstacksize() is available */
+#undef HAVE_PTHREAD_ATTR_GETSTACKSIZE
+
+/** define if pthread_attr_setstacksize() is available */
+#undef HAVE_PTHREAD_ATTR_SETSTACKSIZE
+
+/** define if you have strerror in the C library. */
+#undef HAVE_STRERROR
+
+/** Define if you are running under Compaq TruCluster. */
+#undef HAVE_TRUCLUSTER
+
+/* Define if OpenSSL includes DSA support */
+#undef HAVE_OPENSSL_DSA
+
+/* Define to the length type used by the socket API (socklen_t, size_t, int). */
+#undef ISC_SOCKADDR_LEN_T
+
+/* Define if threads need PTHREAD_SCOPE_SYSTEM */
+#undef NEED_PTHREAD_SCOPE_SYSTEM
+
+/* Define if recvmsg() does not meet all of the BSD socket API specifications.
+ */
+#undef BROKEN_RECVMSG
+
+/* Define if you cannot bind() before connect() for TCP sockets. */
+#undef BROKEN_TCP_BIND_BEFORE_CONNECT
+
+/* Define to enable "rrset-order fixed" syntax. */
+#undef DNS_RDATASET_FIXED
+
+/* Solaris hack to get select_large_fdset. */
+#undef FD_SETSIZE
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_H
+
+/* Define to 1 if you have the <gssapi.h> header file. */
+#undef HAVE_GSSAPI_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `c' library (-lc). */
+#undef HAVE_LIBC
+
+/* Define to 1 if you have the `cap' library (-lcap). */
+#undef HAVE_LIBCAP
+
+/* Define to 1 if you have the `c_r' library (-lc_r). */
+#undef HAVE_LIBC_R
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if you have the `pthread' library (-lpthread). */
+#undef HAVE_LIBPTHREAD
+
+/* Define to 1 if you have the `scf' library (-lscf). */
+#undef HAVE_LIBSCF
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define to 1 if you have the `thr' library (-lthr). */
+#undef HAVE_LIBTHR
+
+/* Define if libxml2 was found */
+#undef HAVE_LIBXML2
+
+/* Define to 1 if you have the <linux/capability.h> header file. */
+#undef HAVE_LINUX_CAPABILITY_H
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <net/if6.h> header file. */
+#undef HAVE_NET_IF6_H
+
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/capability.h> header file. */
+#undef HAVE_SYS_CAPABILITY_H
+
+/* Define to 1 if you have the <sys/devpoll.h> header file. */
+#undef HAVE_SYS_DEVPOLL_H
+
+/* Define to 1 if you have the <sys/dyntune.h> header file. */
+#undef HAVE_SYS_DYNTUNE_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/prctl.h> header file. */
+#undef HAVE_SYS_PRCTL_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define if running under Compaq TruCluster */
+#undef HAVE_TRUCLUSTER
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Defined if extern char *optarg is not declared. */
+#undef NEED_OPTARG
+
+/* Define if connect does not honour the permission on the UNIX domain socket.
+ */
+#undef NEED_SECURE_DIRECTORY
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Sets which flag to pass to open/fcntl to make non-blocking
+ (O_NDELAY/O_NONBLOCK). */
+#undef PORT_NONBLOCK
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Defined if you need to use ioctl(FIONBIO) instead a fcntl call to make
+ non-blocking. */
+#undef USE_FIONBIO_IOCTL
+
+/* define if idnkit support is to be included. */
+#undef WITH_IDN
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* 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
+#undef inline
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
+
+/* Define to `unsigned long' if <sys/types.h> does not define. */
+#undef uintptr_t
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+ code using `volatile' can become incorrect without. Disable with care. */
+#undef volatile
diff --git a/config.h.win32 b/config.h.win32
new file mode 100644
index 0000000..e172a41
--- /dev/null
+++ b/config.h.win32
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: config.h.win32,v 1.19 2008/09/25 07:44:12 marka Exp $ */
+
+/*
+ * win32 configuration file
+ * All definitions, declarations, macros and includes are
+ * specific to the requirements of the Windows NT and Windows 2000
+ * platforms
+ */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define as __inline if that's what the C compiler calls it. */
+#define inline __inline
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/*
+ * ANSI C compliance enabled
+ */
+#define __STDC__ 1
+
+/*
+ * Silence compiler warnings about using strcpy and friends.
+ */
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+/*
+ * Use 32 bit time.
+ */
+#define _USE_32BIT_TIME_T 1
+
+/*
+ * Windows NT and 2K only
+ */
+#define _WIN32_WINNT 0x0400
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* define on DEC OSF to enable 4.4BSD style sa_len support */
+/* #undef _SOCKADDR_LEN */
+
+/* define if your system needs pthread_init() before using pthreads */
+/* #undef NEED_PTHREAD_INIT */
+
+/* define if your system has sigwait() */
+/* #undef HAVE_SIGWAIT */
+
+/* define on Solaris to get sigwait() to work using pthreads semantics */
+/* #undef _POSIX_PTHREAD_SEMANTICS */
+
+/* define if LinuxThreads is in use */
+/* #undef HAVE_LINUXTHREADS */
+
+/* define if catgets() is available */
+/* #undef HAVE_CATGETS */
+
+/* define if you have the NET_RT_IFLIST sysctl variable. */
+#define HAVE_IFLIST_SYSCTL 1
+
+/* define if you need to #define _XPG4_2 before including sys/socket.h */
+/* #undef NEED_XPG4_2_BEFORE_SOCKET_H */
+
+/* define if you need to #define _XOPEN_SOURCE_ENTENDED before including
+ * sys/socket.h
+ */
+/* #undef NEED_XSE_BEFORE_SOCKET_H */
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the c_r library (-lc_r). */
+/* #undef HAVE_LIBC_R */
+
+/* Define if you have the nsl library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define if you have the pthread library (-lpthread). */
+/* #undef HAVE_LIBPTHREAD */
+
+/* Define if you have the socket library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define if you have h_errno */
+#define HAVE_H_ERRNO
+
+/* Define if you have RSA_generate_key(). */
+#define HAVE_RSA_GENERATE_KEY
+
+/* Define if you have DSA_generate_parameters(). */
+#define HAVE_DSA_GENERATE_PARAMETERS
+
+/* Define if you have DH_generate_parameters(). */
+#define HAVE_DH_GENERATE_PARAMETERS
+
+#define WANT_IPV6
+
+#define S_IFMT _S_IFMT /* file type mask */
+#define S_IFDIR _S_IFDIR /* directory */
+#define S_IFCHR _S_IFCHR /* character special */
+#define S_IFIFO _S_IFIFO /* pipe */
+#define S_IFREG _S_IFREG /* regular */
+#define S_IREAD _S_IREAD /* read permission, owner */
+#define S_IWRITE _S_IWRITE /* write permission, owner */
+#define S_IEXEC _S_IEXEC /* execute/search permission, owner */
+
+#define O_RDONLY _O_RDONLY
+#define O_WRONLY _O_WRONLY
+#define O_RDWR _O_RDWR
+#define O_APPEND _O_APPEND
+#define O_CREAT _O_CREAT
+#define O_TRUNC _O_TRUNC
+#define O_EXCL _O_EXCL
+
+/* open() under unix allows setting of read/write permissions
+ * at the owner, group and other levels. These don't exist in NT
+ * We'll just map them all to the NT equivalent
+ */
+
+#define S_IRUSR _S_IREAD /* Owner read permission */
+#define S_IWUSR _S_IWRITE /* Owner write permission */
+#define S_IRGRP _S_IREAD /* Group read permission */
+#define S_IWGRP _S_IWRITE /* Group write permission */
+#define S_IROTH _S_IREAD /* Other read permission */
+#define S_IWOTH _S_IWRITE /* Other write permission */
+
+
+/*
+ * WIN32 specials until some other way of dealing with these is decided.
+ */
+
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+#define strdup _strdup
+#define sopen _sopen
+#define isascii __isascii
+#define stat _stat
+#define fstat _fstat
+#define fileno _fileno
+#define unlink _unlink
+#define chdir _chdir
+#define mkdir _mkdir
+#define getcwd _getcwd
+#define utime _utime
+#define utimbuf _utimbuf
+
+/* #define EAFNOSUPPORT EINVAL */
+#define chmod _chmod
+#define getpid _getpid
+#define getppid _getpid /* WARNING!!! For now this gets the same pid */
+#define random rand /* Random number generator */
+#define srandom srand /* Random number generator seeding */
+/* for the config file */
+typedef unsigned int uid_t; /* user id */
+typedef unsigned int gid_t; /* group id */
+typedef long pid_t; /* PID */
+typedef int ssize_t;
+typedef long off_t;
+
+/*
+ * Set up the Version Information
+ */
+#include <versions.h>
+
+/* We actually are using the CryptAPI and not a device */
+#define PATH_RANDOMDEV "CryptAPI"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+/*
+ * Applications may need to get the configuration path
+ */
+#ifndef _USRDLL
+#include <isc/ntpaths.h>
+#endif
+
+#define fdopen _fdopen
+#define read _read
+#define open _open
+#define close _close
+#define write _write
+#include <io.h>
+#define isatty _isatty
+
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
+#endif
+
+/*
+ * Make the number of available sockets large
+ * The number of sockets needed can get large and memory's cheap
+ * This must be defined before winsock2.h gets included as the
+ * macro is used there.
+ */
+
+#define FD_SETSIZE 16384
+#include <windows.h>
+
+/*
+ * Windows doesn't use configure so just set "default" here.
+ */
+#define CONFIGARGS "default"
diff --git a/config.sub b/config.sub
new file mode 100644
index 0000000..edb6b66
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1555 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+timestamp='2004-08-29'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+ kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dlx | dsp16xx \
+ | fr30 | frv \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | ip2k | iq2000 \
+ | m32r | m32rle | m68000 | m68k | m88k | mcore \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64vr | mips64vrel \
+ | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | msp430 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic4x | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+ | clipper-* | craynv-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | msp430-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16c)
+ basic_machine=cr16c-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tic55x | c55x*)
+ basic_machine=tic55x-unknown
+ os=-coff
+ ;;
+ tic6x | c6x*)
+ basic_machine=tic6x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -aros*)
+ os=-aros
+ ;;
+ -kaos*)
+ os=-kaos
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.threads.in b/config.threads.in
new file mode 100644
index 0000000..c1c113b
--- /dev/null
+++ b/config.threads.in
@@ -0,0 +1,177 @@
+#
+# Begin pthreads checking.
+#
+# First, decide whether to use multithreading or not.
+#
+# Enable multithreading by default on systems where it is known
+# to work well, and where debugging of multithreaded programs
+# is supported.
+#
+
+AC_MSG_CHECKING(whether to build with thread support)
+
+case $host in
+*-dec-osf*)
+ use_threads=true ;;
+[*-solaris2.[0-6]])
+ # Thread signals are broken on Solaris 2.6; they are sometimes
+ # delivered to the wrong thread.
+ use_threads=false ;;
+*-solaris*)
+ use_threads=true ;;
+*-ibm-aix*)
+ use_threads=true ;;
+*-hp-hpux10*)
+ use_threads=false ;;
+*-hp-hpux11*)
+ use_threads=true ;;
+*-sgi-irix*)
+ use_threads=true ;;
+*-sco-sysv*uw*|*-*-sysv*UnixWare*)
+ # UnixWare
+ use_threads=false ;;
+*-*-sysv*OpenUNIX*)
+ # UnixWare
+ use_threads=true ;;
+*-netbsd*)
+ if test -r /usr/lib/libpthread.so ; then
+ use_threads=true
+ else
+ # Socket I/O optimizations introduced in 9.2 expose a
+ # bug in unproven-pthreads; see PR #12650
+ use_threads=false
+ fi
+ ;;
+*-openbsd*)
+ # OpenBSD users have reported that named dumps core on
+ # startup when built with threads.
+ use_threads=false ;;
+*-freebsd*)
+ use_threads=false ;;
+*-bsdi[234]*)
+ # Thread signals do not work reliably on some versions of BSD/OS.
+ use_threads=false ;;
+*-bsdi5*)
+ use_threads=true ;;
+*-linux*)
+ # Threads are disabled on Linux by default because most
+ # Linux kernels produce unusable core dumps from multithreaded
+ # programs, and because of limitations in setuid().
+ use_threads=false ;;
+*)
+ use_threads=false ;;
+esac
+
+AC_ARG_ENABLE(threads,
+ [ --enable-threads enable multithreading])
+case "$enable_threads" in
+ yes)
+ use_threads=true
+ ;;
+ no)
+ use_threads=false
+ ;;
+ '')
+ # Use system-dependent default
+ ;;
+ *)
+ AC_MSG_ERROR([--enable-threads takes yes or no])
+ ;;
+esac
+
+if $use_threads
+then
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+if $use_threads
+then
+ #
+ # Search for / configure pthreads in a system-dependent fashion.
+ #
+ case "$host" in
+ *-netbsd*)
+ # NetBSD has multiple pthreads implementations. The
+ # recommended one to use is "unproven-pthreads". The
+ # older "mit-pthreads" may also work on some NetBSD
+ # versions. The PTL2 thread library does not
+ # currently work with bind9, but can be chosen with
+ # the --with-ptl2 option for those who wish to
+ # experiment with it.
+ CC="gcc"
+ AC_MSG_CHECKING(which NetBSD thread library to use)
+
+ AC_ARG_WITH(ptl2,
+[ --with-ptl2 on NetBSD, use the ptl2 thread library (experimental)],
+ use_ptl2="$withval", use_ptl2="no")
+
+ : ${LOCALBASE:=/usr/pkg}
+
+ if test "X$use_ptl2" = "Xyes"
+ then
+ AC_MSG_RESULT(PTL2)
+ AC_MSG_WARN(
+[linking with PTL2 is highly experimental and not expected to work])
+ CC=ptlgcc
+ else
+ if test -r /usr/lib/libpthread.so
+ then
+ AC_MSG_RESULT(native)
+ LIBS="-lpthread $LIBS"
+ else
+ if test ! -d $LOCALBASE/pthreads
+ then
+ AC_MSG_RESULT(none)
+ AC_MSG_ERROR("could not find thread libraries")
+ fi
+
+ if $use_threads
+ then
+ AC_MSG_RESULT(mit-pthreads/unproven-pthreads)
+ pkg="$LOCALBASE/pthreads"
+ lib1="-L$pkg/lib -Wl,-R$pkg/lib"
+ lib2="-lpthread -lm -lgcc -lpthread"
+ LIBS="$lib1 $lib2 $LIBS"
+ CPPFLAGS="$CPPFLAGS -I$pkg/include"
+ STD_CINCLUDES="$STD_CINCLUDES -I$pkg/include"
+ fi
+ fi
+ fi
+ ;;
+ *-freebsd*)
+ # We don't want to set -lpthread as that break
+ # the ability to choose threads library at final
+ # link time and is not valid for all architectures.
+
+ PTHREAD=
+ if test "X$GCC" = "Xyes"; then
+ saved_cc="$CC"
+ CC="$CC -pthread"
+ AC_MSG_CHECKING(for gcc -pthread support);
+ AC_TRY_LINK([#include <pthread.h>],
+ [printf("%x\n", pthread_create);],
+ PTHREAD="yes"
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no))
+ CC="$saved_cc"
+ fi
+ if test "X$PTHREAD" != "Xyes"; then
+ AC_CHECK_LIB(pthread, pthread_create,,
+ AC_CHECK_LIB(thr, thread_create,,
+ AC_CHECK_LIB(c_r, pthread_create,,
+ AC_CHECK_LIB(c, pthread_create,,
+ AC_MSG_ERROR("could not find thread libraries")))))
+ fi
+ ;;
+ *)
+ AC_CHECK_LIB(pthread, pthread_create,,
+ AC_CHECK_LIB(pthread, __pthread_create,,
+ AC_CHECK_LIB(pthread, __pthread_create_system,,
+ AC_CHECK_LIB(c_r, pthread_create,,
+ AC_CHECK_LIB(c, pthread_create,,
+ AC_MSG_ERROR("could not find thread libraries"))))))
+ ;;
+ esac
+fi
diff --git a/configure b/configure
new file mode 100755
index 0000000..e6fa6ac
--- /dev/null
+++ b/configure
@@ -0,0 +1,33235 @@
+#! /bin/sh
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1996-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: configure,v 1.443 2008/10/29 10:09:21 fdupont Exp $
+#
+# Portions Copyright (C) 1996-2001 Nominum, Inc.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM 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.
+# From configure.in Revision: 1.456 .
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+ echo_test_string="`eval $cmd`" &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "$0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo"
+fi
+
+
+
+
+tagnames=${tagnames+${tagnames},}CXX
+
+tagnames=${tagnames+${tagnames},}F77
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="lib/dns/name.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+build
+build_cpu
+build_vendor
+build_os
+host
+host_cpu
+host_vendor
+host_os
+SET_MAKE
+RANLIB
+INSTALL_PROGRAM
+INSTALL_SCRIPT
+INSTALL_DATA
+LN_S
+STD_CINCLUDES
+STD_CDEFINES
+STD_CWARNINGS
+CCOPT
+AR
+ARFLAGS
+LN
+ETAGS
+PERL
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CPP
+GREP
+EGREP
+ISC_SOCKADDR_LEN_T
+ISC_PLATFORM_HAVELONGLONG
+ISC_PLATFORM_HAVELIFCONF
+ISC_PLATFORM_HAVEKQUEUE
+ISC_PLATFORM_HAVEEPOLL
+ISC_PLATFORM_HAVEDEVPOLL
+ISC_PLATFORM_NEEDSYSSELECTH
+LWRES_PLATFORM_NEEDSYSSELECTH
+USE_OPENSSL
+DST_OPENSSL_INC
+USE_PKCS11
+ISC_PLATFORM_HAVEGSSAPI
+ISC_PLATFORM_GSSAPIHEADER
+USE_GSSAPI
+DST_GSSAPI_INC
+DNS_GSSAPI_LIBS
+DNS_CRYPTO_LIBS
+ALWAYS_DEFINES
+ISC_PLATFORM_USETHREADS
+ISC_THREAD_DIR
+MKDEPCC
+MKDEPCFLAGS
+MKDEPPROG
+IRIX_DNSSEC_WARNINGS_HACK
+purify_path
+PURIFY
+ECHO
+STRIP
+CXX
+CXXFLAGS
+ac_ct_CXX
+CXXCPP
+F77
+FFLAGS
+ac_ct_F77
+LIBTOOL
+O
+A
+SA
+LIBTOOL_MKDEP_SED
+LIBTOOL_MODE_COMPILE
+LIBTOOL_MODE_INSTALL
+LIBTOOL_MODE_LINK
+LIBTOOL_ALLOW_UNDEFINED
+LIBTOOL_IN_MAIN
+ISC_PLATFORM_HAVEIPV6
+LWRES_PLATFORM_HAVEIPV6
+ISC_PLATFORM_NEEDNETINETIN6H
+LWRES_PLATFORM_NEEDNETINETIN6H
+ISC_PLATFORM_NEEDNETINET6IN6H
+LWRES_PLATFORM_NEEDNETINET6IN6H
+ISC_PLATFORM_HAVEINADDR6
+LWRES_PLATFORM_HAVEINADDR6
+ISC_PLATFORM_NEEDIN6ADDRANY
+LWRES_PLATFORM_NEEDIN6ADDRANY
+ISC_PLATFORM_NEEDIN6ADDRLOOPBACK
+LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK
+ISC_PLATFORM_HAVEIN6PKTINFO
+ISC_PLATFORM_FIXIN6ISADDR
+ISC_IPV6_H
+ISC_IPV6_O
+ISC_ISCIPV6_O
+ISC_IPV6_C
+LWRES_HAVE_SIN6_SCOPE_ID
+ISC_PLATFORM_HAVESCOPEID
+ISC_PLATFORM_HAVEIF_LADDRREQ
+ISC_PLATFORM_HAVEIF_LADDRCONF
+ISC_PLATFORM_NEEDNTOP
+ISC_PLATFORM_NEEDPTON
+ISC_PLATFORM_NEEDATON
+ISC_PLATFORM_HAVESALEN
+LWRES_PLATFORM_HAVESALEN
+ISC_PLATFORM_MSGHDRFLAVOR
+ISC_PLATFORM_NEEDPORTT
+ISC_LWRES_NEEDADDRINFO
+ISC_LWRES_NEEDRRSETINFO
+ISC_LWRES_SETHOSTENTINT
+ISC_LWRES_ENDHOSTENTINT
+ISC_LWRES_GETNETBYADDRINADDR
+ISC_LWRES_SETNETENTINT
+ISC_LWRES_ENDNETENTINT
+ISC_LWRES_GETHOSTBYADDRVOID
+ISC_LWRES_NEEDHERRNO
+ISC_LWRES_GETIPNODEPROTO
+ISC_LWRES_GETADDRINFOPROTO
+ISC_LWRES_GETNAMEINFOPROTO
+ISC_PLATFORM_NEEDSTRSEP
+ISC_PLATFORM_NEEDMEMMOVE
+ISC_PLATFORM_NEEDSTRTOUL
+LWRES_PLATFORM_NEEDSTRTOUL
+GENRANDOMLIB
+ISC_PLATFORM_NEEDSTRLCPY
+ISC_PLATFORM_NEEDSTRLCAT
+ISC_PLATFORM_NEEDSPRINTF
+LWRES_PLATFORM_NEEDSPRINTF
+ISC_PLATFORM_NEEDVSNPRINTF
+LWRES_PLATFORM_NEEDVSNPRINTF
+ISC_EXTRA_OBJS
+ISC_EXTRA_SRCS
+USE_ISC_SPNEGO
+DST_EXTRA_OBJS
+DST_EXTRA_SRCS
+ISC_PLATFORM_QUADFORMAT
+LWRES_PLATFORM_QUADFORMAT
+ISC_PLATFORM_HAVESYSUNH
+ISC_PLATFORM_RLIMITTYPE
+ISC_PLATFORM_USEDECLSPEC
+LWRES_PLATFORM_USEDECLSPEC
+ISC_PLATFORM_BRACEPTHREADONCEINIT
+ISC_PLATFORM_HAVESTRINGSH
+ISC_PLATFORM_HAVEIFNAMETOINDEX
+ISC_PLATFORM_HAVEXADD
+ISC_PLATFORM_HAVEXADDQ
+ISC_PLATFORM_HAVECMPXCHG
+ISC_PLATFORM_HAVEATOMICSTORE
+ISC_PLATFORM_USEGCCASM
+ISC_PLATFORM_USEOSFASM
+ISC_PLATFORM_USESTDASM
+ISC_PLATFORM_USEMACASM
+ISC_ARCH_DIR
+LATEX
+PDFLATEX
+W3M
+XSLTPROC
+XMLLINT
+DOXYGEN
+XSLT_DOCBOOK_STYLE_HTML
+XSLT_DOCBOOK_STYLE_XHTML
+XSLT_DOCBOOK_STYLE_MAN
+XSLT_DOCBOOK_CHUNK_HTML
+XSLT_DOCBOOK_CHUNK_XHTML
+XSLT_DOCBOOK_CHUNKTOC_HTML
+XSLT_DOCBOOK_CHUNKTOC_XHTML
+XSLT_DOCBOOK_MAKETOC_HTML
+XSLT_DOCBOOK_MAKETOC_XHTML
+XSLT_DB2LATEX_STYLE
+XSLT_DB2LATEX_ADMONITIONS
+IDNLIBS
+BIND9_TOP_BUILDDIR
+BIND9_ISC_BUILDINCLUDE
+BIND9_ISCCC_BUILDINCLUDE
+BIND9_ISCCFG_BUILDINCLUDE
+BIND9_DNS_BUILDINCLUDE
+BIND9_LWRES_BUILDINCLUDE
+BIND9_BIND9_BUILDINCLUDE
+BIND9_VERSION
+BIND9_CONFIGARGS
+PG_CONFIG
+USE_DLZ
+DLZ_DRIVER_INCLUDES
+DLZ_DRIVER_LIBS
+DLZ_DRIVER_SRCS
+DLZ_DRIVER_OBJS
+BUILD_CC
+BUILD_CFLAGS
+BUILD_CPPFLAGS
+BUILD_LDFLAGS
+BUILD_LIBS
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files='BIND9_MAKE_INCLUDES
+BIND9_MAKE_RULES
+LIBISC_API
+LIBISCCC_API
+LIBISCCFG_API
+LIBDNS_API
+LIBBIND9_API
+LIBLWRES_API
+DLZ_DRIVER_RULES'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+CXX
+CXXFLAGS
+CCC
+CXXCPP
+F77
+FFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-libbind deprecated
+ --enable-kqueue use BSD kqueue when available [default=yes]
+ --enable-epoll use Linux epoll when available [default=yes]
+ --enable-devpoll use /dev/poll when available [default=yes]
+ --enable-openssl-version-check
+ Check OpenSSL Version [default=yes]
+ --enable-threads enable multithreading
+ --enable-largefile 64-bit file support
+ --enable-shared[=PKGS] build shared libraries [default=yes]
+ --enable-static[=PKGS] build static libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-libtool-lock avoid locking (might break parallel builds)
+ --enable-ipv6 use IPv6 default=autodetect
+ --enable-getifaddrs Enable the use of getifaddrs() [yes|no].
+ --disable-isc-spnego use SPNEGO from GSSAPI library
+ --disable-linux-caps disable linux capabilities
+ --enable-atomic enable machine specific atomic operations
+ [default=autodetect]
+ --enable-fixed-rrset enable fixed rrset ordering
+ [default=no]
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-openssl=PATH Build with OpenSSL yes|no|path.
+ (Required for DNSSEC)
+ --with-pkcs11 Build with PKCS11 support
+ --with-gssapi=PATH Specify path for system-supplied GSSAPI
+ --with-randomdev=PATH Specify path for random device
+ --with-ptl2 on NetBSD, use the ptl2 thread library (experimental)
+ --with-libxml2=PATH Build with libxml2 library yes|no|path
+ --with-purify=PATH use Rational purify
+ --with-libtool use GNU libtool (following indented options supported)
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+ --with-pic try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-tags[=TAGS] include additional configurations [automatic]
+ --with-kame=PATH use Kame IPv6 default path /usr/local/v6
+ --with-docbook-xsl=PATH Specify path for Docbook-XSL stylesheets
+ --with-idn=MPREFIX enable IDN support using idnkit default PREFIX
+ --with-libiconv=IPREFIX GNU libiconv are in IPREFIX default PREFIX
+ --with-iconv=LIBSPEC specify iconv library default -liconv
+ --with-idnlib=ARG specify libidnkit
+ --with-dlz-postgres=PATH Build with Postgres DLZ driver yes|no|path.
+ (Required to use Postgres with DLZ)
+ --with-dlz-mysql=PATH Build with MySQL DLZ driver yes|no|path.
+ (Required to use MySQL with DLZ)
+ --with-dlz-bdb=PATH Build with Berkeley DB DLZ driver yes|no|path.
+ (Required to use Berkeley DB with DLZ)
+ --with-dlz-filesystem=PATH Build with filesystem DLZ driver yes|no.
+ (Required to use file system driver with DLZ)
+ --with-dlz-ldap=PATH Build with LDAP DLZ driver yes|no|path.
+ (Required to use LDAP with DLZ)
+ --with-dlz-odbc=PATH Build with ODBC DLZ driver yes|no|path.
+ (Required to use ODBC with DLZ)
+ --with-dlz-stub=PATH Build with stub DLZ driver yes|no.
+ (Required to use stub driver with DLZ)
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CXXCPP C++ preprocessor
+ F77 Fortran 77 compiler command
+ FFLAGS Fortran 77 compiler flags
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+ { (exit 1); exit 1; }; }
+
+{ echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+if test "${ac_cv_build+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+ { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+echo "$as_me: error: invalid value of canonical build" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+if test "${ac_cv_host+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+echo "$as_me: error: invalid value of canonical host" >&2;}
+ { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; }
+set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ SET_MAKE=
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+IFS=$as_save_IFS
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6; }
+fi
+
+
+
+
+
+
+
+# Warn if the user specified libbind, which is now deprecated
+# Check whether --enable-libbind was given.
+if test "${enable_libbind+set}" = set; then
+ enableval=$enable_libbind;
+fi
+
+
+case "$enable_libbind" in
+ yes)
+ { { echo "$as_me:$LINENO: error: 'libbind' is no longer part of the BIND 9 distribution.
+It is available from http://www.isc.org as a separate download." >&5
+echo "$as_me: error: 'libbind' is no longer part of the BIND 9 distribution.
+It is available from http://www.isc.org as a separate download." >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ no|'')
+ ;;
+esac
+
+
+#
+# Make very sure that these are the first files processed by
+# config.status, since we use the processed output as the input for
+# AC_SUBST_FILE() subsitutions in other files.
+#
+ac_config_files="$ac_config_files make/rules make/includes"
+
+
+# Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $AR in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_AR="$AR" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+AR=$ac_cv_path_AR
+if test -n "$AR"; then
+ { echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ARFLAGS="cruv"
+
+
+
+# The POSIX ln(1) program. Non-POSIX systems may substitute
+# "copy" or something.
+LN=ln
+
+
+case "$AR" in
+ "")
+ { { echo "$as_me:$LINENO: error:
+ar program not found. Please fix your PATH to include the directory in
+which ar resides, or set AR in the environment with the full path to ar.
+" >&5
+echo "$as_me: error:
+ar program not found. Please fix your PATH to include the directory in
+which ar resides, or set AR in the environment with the full path to ar.
+" >&2;}
+ { (exit 1); exit 1; }; }
+
+ ;;
+esac
+
+#
+# Etags.
+#
+for ac_prog in etags emacs-etags
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_ETAGS+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $ETAGS in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ETAGS="$ETAGS" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_ETAGS="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ETAGS=$ac_cv_path_ETAGS
+if test -n "$ETAGS"; then
+ { echo "$as_me:$LINENO: result: $ETAGS" >&5
+echo "${ECHO_T}$ETAGS" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ETAGS" && break
+done
+
+
+#
+# Some systems, e.g. RH7, have the Exuberant Ctags etags instead of
+# GNU emacs etags, and it requires the -L flag.
+#
+if test "X$ETAGS" != "X"; then
+ { echo "$as_me:$LINENO: checking for Exuberant Ctags etags" >&5
+echo $ECHO_N "checking for Exuberant Ctags etags... $ECHO_C" >&6; }
+ if $ETAGS --version 2>&1 | grep 'Exuberant Ctags' >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ETAGS="$ETAGS -L"
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ fi
+fi
+
+
+#
+# Perl is optional; it is used only by some of the system test scripts.
+#
+for ac_prog in perl5 perl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_PERL+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $PERL in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PERL=$ac_cv_path_PERL
+if test -n "$PERL"; then
+ { echo "$as_me:$LINENO: result: $PERL" >&5
+echo "${ECHO_T}$PERL" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$PERL" && break
+done
+
+
+
+#
+# Special processing of paths depending on whether --prefix,
+# --sysconfdir or --localstatedir arguments were given. What's
+# desired is some compatibility with the way previous versions
+# of BIND built; they defaulted to /usr/local for most parts of
+# the installation, but named.boot/named.conf was in /etc
+# and named.pid was in /var/run.
+#
+# So ... if none of --prefix, --sysconfdir or --localstatedir are
+# specified, set things up that way. If --prefix is given, use
+# it for sysconfdir and localstatedir the way configure normally
+# would. To change the prefix for everything but leave named.conf
+# in /etc or named.pid in /var/run, then do this the usual configure way:
+# ./configure --prefix=/somewhere --sysconfdir=/etc
+# ./configure --prefix=/somewhere --localstatedir=/var
+#
+# To put named.conf and named.pid in /usr/local with everything else,
+# set the prefix explicitly to /usr/local even though that's the default:
+# ./configure --prefix=/usr/local
+#
+case "$prefix" in
+ NONE)
+ case "$sysconfdir" in
+ '${prefix}/etc')
+ sysconfdir=/etc
+ ;;
+ esac
+ case "$localstatedir" in
+ '${prefix}/var')
+ localstatedir=/var
+ ;;
+ esac
+ ;;
+esac
+
+#
+# Make sure INSTALL uses an absolute path, else it will be wrong in all
+# Makefiles, since they use make/rules.in and INSTALL will be adjusted by
+# configure based on the location of the file where it is substituted.
+# Since in BIND9 INSTALL is only substituted into make/rules.in, an immediate
+# subdirectory of install-sh, This relative path will be wrong for all
+# directories more than one level down from install-sh.
+#
+case "$INSTALL" in
+ /*)
+ ;;
+ *)
+ #
+ # Not all systems have dirname.
+ #
+
+ ac_dir="`echo $INSTALL | sed 's%/[^/]*$%%'`"
+
+
+ ac_prog="`echo $INSTALL | sed 's%.*/%%'`"
+ test "$ac_dir" = "$ac_prog" && ac_dir=.
+ test -d "$ac_dir" && ac_dir="`(cd \"$ac_dir\" && pwd)`"
+ INSTALL="$ac_dir/$ac_prog"
+ ;;
+esac
+
+#
+# On these hosts, we really want to use cc, not gcc, even if it is
+# found. The gcc that these systems have will not correctly handle
+# pthreads.
+#
+# However, if the user sets $CC to be something, let that override
+# our change.
+#
+if test "X$CC" = "X" ; then
+ case "$host" in
+ *-dec-osf*)
+ CC="cc"
+ ;;
+ *-solaris*)
+ # Use Sun's cc if it is available, but watch
+ # out for /usr/ucb/cc; it will never be the right
+ # compiler to use.
+ #
+ # If setting CC here fails, the AC_PROG_CC done
+ # below might still find gcc.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ case "$ac_dir" in
+ /usr/ucb)
+ # exclude
+ ;;
+ *)
+ if test -f "$ac_dir/cc"; then
+ CC="$ac_dir/cc"
+ break
+ fi
+ ;;
+ esac
+ done
+ IFS="$ac_save_ifs"
+ ;;
+ *-hp-hpux*)
+ CC="cc"
+ ;;
+ mips-sgi-irix*)
+ CC="cc"
+ ;;
+ esac
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+#
+# gcc's optimiser is broken at -02 for ultrasparc
+#
+if test "$ac_env_CFLAGS_set" != set -a "X$GCC" = "Xyes"; then
+ case "$host" in
+ sparc-*)
+ CCFLAGS="-g -O1"
+ ;;
+ esac
+fi
+
+#
+# OS dependent CC flags
+#
+case "$host" in
+ # OSF 5.0: recv/send are only avaliable with -D_POSIX_PII_SOCKET or
+ # -D_XOPEN_SOURCE_EXTENDED.
+ *-dec-osf*)
+ STD_CDEFINES="$STD_CDEFINES -D_POSIX_PII_SOCKET"
+ CPPFLAGS="$CPPFLAGS -D_POSIX_PII_SOCKET"
+ ;;
+ #HP-UX: need -D_XOPEN_SOURCE_EXTENDED and -lxnet for CMSG macros
+ *-hp-hpux*)
+ STD_CDEFINES="$STD_CDEFINES -D_XOPEN_SOURCE_EXTENDED"
+ CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE_EXTENDED"
+ LIBS="-lxnet $LIBS"
+ ;;
+ # Solaris: need -D_XPG4_2 and -D__EXTENSIONS__ for CMSG macros
+ *-solaris*)
+ STD_CDEFINES="$STD_CDEFINES -D_XPG4_2 -D__EXTENSIONS__"
+ CPPFLAGS="$CPPFLAGS -D_XPG4_2 -D__EXTENSIONS__"
+ ;;
+ # POSIX doesn't include the IPv6 Advanced Socket API and glibc hides
+ # parts of the IPv6 Advanced Socket API as a result. This is stupid
+ # as it breaks how the two halves (Basic and Advanced) of the IPv6
+ # Socket API were designed to be used but we have to live with it.
+ # Define _GNU_SOURCE to pull in the IPv6 Advanced Socket API.
+ *-linux*)
+ STD_CDEFINES="$STD_CDEFINES -D_GNU_SOURCE"
+ CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
+ ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+ # Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_GREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+ # Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ ac_count=`expr $ac_count + 1`
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+ $ac_path_EGREP_found && break 3
+ done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+ { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+
+
+
+for ac_header in fcntl.h sys/time.h unistd.h sys/sockio.h sys/select.h sys/param.h sys/sysctl.h net/if6.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset cs;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *pcpcc;
+ char **ppc;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ pcpcc = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ if (s) return 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ if (!foo) return 0;
+ }
+ return !cs[0] && !zero.x;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6; }
+if test "${ac_cv_c_inline+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_inline=$ac_kw
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6; }
+
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for working volatile" >&5
+echo $ECHO_N "checking for working volatile... $ECHO_C" >&6; }
+if test "${ac_cv_c_volatile+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+volatile int x;
+int * volatile y = (int *) 0;
+return !x && !y;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_volatile=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_volatile=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_volatile" >&5
+echo "${ECHO_T}$ac_cv_c_volatile" >&6; }
+if test $ac_cv_c_volatile = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define volatile
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for sysctlbyname" >&5
+echo $ECHO_N "checking for sysctlbyname... $ECHO_C" >&6; }
+if test "${ac_cv_func_sysctlbyname+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define sysctlbyname to an innocuous variant, in case <limits.h> declares sysctlbyname.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define sysctlbyname innocuous_sysctlbyname
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char sysctlbyname (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef sysctlbyname
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sysctlbyname ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_sysctlbyname || defined __stub___sysctlbyname
+choke me
+#endif
+
+int
+main ()
+{
+return sysctlbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_sysctlbyname=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_sysctlbyname=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_sysctlbyname" >&5
+echo "${ECHO_T}$ac_cv_func_sysctlbyname" >&6; }
+if test $ac_cv_func_sysctlbyname = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYSCTLBYNAME 1
+_ACEOF
+
+fi
+
+
+#
+# UnixWare 7.1.1 with the feature supplement to the UDK compiler
+# is reported to not support "static inline" (RT #1212).
+#
+{ echo "$as_me:$LINENO: checking for static inline breakage" >&5
+echo $ECHO_N "checking for static inline breakage... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ foo1();
+ }
+
+ static inline int foo1() {
+ return 0;
+ }
+
+ static inline int foo2() {
+ return foo1();
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ cat >>confdefs.h <<\_ACEOF
+#define inline
+_ACEOF
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_size_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef size_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_size_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_size_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6; }
+if test $ac_cv_type_size_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for ssize_t" >&5
+echo $ECHO_N "checking for ssize_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_ssize_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef ssize_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_ssize_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_ssize_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_ssize_t" >&5
+echo "${ECHO_T}$ac_cv_type_ssize_t" >&6; }
+if test $ac_cv_type_ssize_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t int
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for uintptr_t" >&5
+echo $ECHO_N "checking for uintptr_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_uintptr_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+typedef uintptr_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_uintptr_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_uintptr_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_uintptr_t" >&5
+echo "${ECHO_T}$ac_cv_type_uintptr_t" >&6; }
+if test $ac_cv_type_uintptr_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define uintptr_t unsigned long
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for socklen_t" >&5
+echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_socklen_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+
+typedef socklen_t ac__type_new_;
+int
+main ()
+{
+if ((ac__type_new_ *) 0)
+ return 0;
+if (sizeof (ac__type_new_))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_socklen_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_socklen_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5
+echo "${ECHO_T}$ac_cv_type_socklen_t" >&6; }
+if test $ac_cv_type_socklen_t = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define ISC_SOCKADDR_LEN_T socklen_t
+_ACEOF
+
+else
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+int getsockname(int, struct sockaddr *, size_t *);
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ cat >>confdefs.h <<\_ACEOF
+#define ISC_SOCKADDR_LEN_T size_t
+_ACEOF
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ cat >>confdefs.h <<\_ACEOF
+#define ISC_SOCKADDR_LEN_T int
+_ACEOF
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; }
+if test "${ac_cv_header_time+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_header_time=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_header_time=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for long long" >&5
+echo $ECHO_N "checking for long long... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+long long i = 0; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_HAVELONGLONG="#define ISC_PLATFORM_HAVELONGLONG 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_HAVELONGLONG="#undef ISC_PLATFORM_HAVELONGLONG"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+#
+# check if we have lifconf
+#
+{ echo "$as_me:$LINENO: checking for struct lifconf" >&5
+echo $ECHO_N "checking for struct lifconf... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+int
+main ()
+{
+
+struct lifconf lifconf;
+lifconf.lifc_len = 0;
+
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_HAVELIFCONF="#define ISC_PLATFORM_HAVELIFCONF 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_HAVELIFCONF="#undef ISC_PLATFORM_HAVELIFCONF"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+#
+# check if we have kqueue
+#
+# Check whether --enable-kqueue was given.
+if test "${enable_kqueue+set}" = set; then
+ enableval=$enable_kqueue; want_kqueue="$enableval"
+else
+ want_kqueue="yes"
+fi
+
+case $want_kqueue in
+yes)
+ { echo "$as_me:$LINENO: checking for kqueue" >&5
+echo $ECHO_N "checking for kqueue... $ECHO_C" >&6; }
+if test "${ac_cv_func_kqueue+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define kqueue to an innocuous variant, in case <limits.h> declares kqueue.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define kqueue innocuous_kqueue
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char kqueue (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef kqueue
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char kqueue ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_kqueue || defined __stub___kqueue
+choke me
+#endif
+
+int
+main ()
+{
+return kqueue ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_kqueue=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_kqueue=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_kqueue" >&5
+echo "${ECHO_T}$ac_cv_func_kqueue" >&6; }
+if test $ac_cv_func_kqueue = yes; then
+ ac_cv_have_kqueue=yes
+else
+ ac_cv_have_kqueue=no
+fi
+
+ case $ac_cv_have_kqueue in
+ yes)
+ ISC_PLATFORM_HAVEKQUEUE="#define ISC_PLATFORM_HAVEKQUEUE 1"
+ ;;
+ *)
+ ISC_PLATFORM_HAVEKQUEUE="#undef ISC_PLATFORM_HAVEKQUEUE"
+ ;;
+ esac
+ ;;
+*)
+ ISC_PLATFORM_HAVEKQUEUE="#undef ISC_PLATFORM_HAVEKQUEUE"
+ ;;
+esac
+
+
+#
+# check if we have epoll. Linux kernel 2.4 has epoll_create() which fails,
+# so we need to try running the code, not just test its existence.
+#
+# Check whether --enable-epoll was given.
+if test "${enable_epoll+set}" = set; then
+ enableval=$enable_epoll; want_epoll="$enableval"
+else
+ want_epoll="yes"
+fi
+
+case $want_epoll in
+yes)
+ { echo "$as_me:$LINENO: checking epoll support" >&5
+echo $ECHO_N "checking epoll support... $ECHO_C" >&6; }
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run test program while cross compiling
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/epoll.h>
+int main() {
+ if (epoll_create(1) < 0)
+ return (1);
+ return (0);
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_HAVEEPOLL="#define ISC_PLATFORM_HAVEEPOLL 1"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_HAVEEPOLL="#undef ISC_PLATFORM_HAVEEPOLL"
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+ ;;
+*)
+ ISC_PLATFORM_HAVEEPOLL="#undef ISC_PLATFORM_HAVEEPOLL"
+ ;;
+esac
+
+
+#
+# check if we support /dev/poll
+#
+# Check whether --enable-devpoll was given.
+if test "${enable_devpoll+set}" = set; then
+ enableval=$enable_devpoll; want_devpoll="$enableval"
+else
+ want_devpoll="yes"
+fi
+
+case $want_devpoll in
+yes)
+
+for ac_header in sys/devpoll.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ ISC_PLATFORM_HAVEDEVPOLL="#define ISC_PLATFORM_HAVEDEVPOLL 1"
+
+else
+ ISC_PLATFORM_HAVEDEVPOLL="#undef ISC_PLATFORM_HAVEDEVPOLL"
+
+fi
+
+done
+
+ ;;
+*)
+ ISC_PLATFORM_HAVEDEVPOLL="#undef ISC_PLATFORM_HAVEDEVPOLL"
+ ;;
+esac
+
+
+#
+# check if we need to #include sys/select.h explicitly
+#
+case $ac_cv_header_unistd_h in
+yes)
+{ echo "$as_me:$LINENO: checking if unistd.h or sys/types.h defines fd_set" >&5
+echo $ECHO_N "checking if unistd.h or sys/types.h defines fd_set... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h> /* Ultrix */
+#include <unistd.h>
+int
+main ()
+{
+fd_set read_set; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_NEEDSYSSELECTH="#undef ISC_PLATFORM_NEEDSYSSELECTH"
+ LWRES_PLATFORM_NEEDSYSSELECTH="#undef LWRES_PLATFORM_NEEDSYSSELECTH"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ case $ac_cv_header_sys_select_h in
+ yes)
+ ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
+ LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1"
+ ;;
+ no)
+ { { echo "$as_me:$LINENO: error: need either working unistd.h or sys/select.h" >&5
+echo "$as_me: error: need either working unistd.h or sys/select.h" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+no)
+ case $ac_cv_header_sys_select_h in
+ yes)
+ ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
+ LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1"
+ ;;
+ no)
+ { { echo "$as_me:$LINENO: error: need either unistd.h or sys/select.h" >&5
+echo "$as_me: error: need either unistd.h or sys/select.h" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+ ;;
+esac
+
+
+
+#
+# Find the machine's endian flavor.
+#
+{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN \
+ && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
+ bogus endian macros
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_c_bigendian=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_c_bigendian=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # It does not; compile a test program.
+if test "$cross_compiling" = yes; then
+ # try to guess the endianness by grepping values into an object file
+ ac_cv_c_bigendian=unknown
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
+short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
+int
+main ()
+{
+ _ascii (); _ebcdic ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null ; then
+ ac_cv_c_bigendian=yes
+fi
+if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_bigendian=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6; }
+case $ac_cv_c_bigendian in
+ yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define WORDS_BIGENDIAN 1
+_ACEOF
+ ;;
+ no)
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&5
+echo "$as_me: error: unknown endianness
+presetting ac_cv_c_bigendian=no (or yes) will help" >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+
+
+
+#
+# was --with-openssl specified?
+#
+OPENSSL_WARNING=
+{ echo "$as_me:$LINENO: checking for OpenSSL library" >&5
+echo $ECHO_N "checking for OpenSSL library... $ECHO_C" >&6; }
+
+# Check whether --with-openssl was given.
+if test "${with_openssl+set}" = set; then
+ withval=$with_openssl; use_openssl="$withval"
+else
+ use_openssl="auto"
+fi
+
+
+openssldirs="/usr /usr/local /usr/local/ssl /usr/pkg /usr/sfw"
+if test "$use_openssl" = "auto"
+then
+ for d in $openssldirs
+ do
+ if test -f $d/include/openssl/opensslv.h
+ then
+ use_openssl=$d
+ break
+ fi
+ done
+fi
+case "$use_openssl" in
+ no)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ DST_OPENSSL_INC=""
+ USE_OPENSSL=""
+ ;;
+ auto)
+ DST_OPENSSL_INC=""
+ USE_OPENSSL=""
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ ;;
+ *)
+ if test "$use_openssl" = "yes"
+ then
+ # User did not specify a path - guess it
+ for d in $openssldirs
+ do
+ if test -f $d/include/openssl/opensslv.h
+ then
+ use_openssl=$d
+ break
+ fi
+ done
+ if test "$use_openssl" = "yes"
+ then
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ { { echo "$as_me:$LINENO: error: OpenSSL was not found in any of $openssldirs; use --with-openssl=/path" >&5
+echo "$as_me: error: OpenSSL was not found in any of $openssldirs; use --with-openssl=/path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+ USE_OPENSSL='-DOPENSSL'
+ if test "$use_openssl" = "/usr"
+ then
+ DST_OPENSSL_INC=""
+ DNS_OPENSSL_LIBS="-lcrypto"
+ else
+ DST_OPENSSL_INC="-I$use_openssl/include"
+ case $host in
+ *-solaris*)
+ DNS_OPENSSL_LIBS="-L$use_openssl/lib -R$use_openssl/lib -lcrypto"
+ ;;
+ *-hp-hpux*)
+ DNS_OPENSSL_LIBS="-L$use_openssl/lib -Wl,+b: -lcrypto"
+ ;;
+ *-apple-darwin*)
+ #
+ # Apple's ld seaches for serially for dynamic
+ # then static libraries. This means you can't
+ # use -L to override dynamic system libraries
+ # with static ones when linking. Instead
+ # we specify a absolute path.
+ #
+ if test -f "$use_openssl/lib/libcrypto.dylib"
+ then
+ DNS_OPENSSL_LIBS="-L$use_openssl/lib -lcrypto"
+ else
+ DNS_OPENSSL_LIBS="$use_openssl/lib/libcrypto.a"
+ fi
+ ;;
+ *)
+ DNS_OPENSSL_LIBS="-L$use_openssl/lib -lcrypto"
+ ;;
+ esac
+ fi
+ { echo "$as_me:$LINENO: result: using OpenSSL from $use_openssl/lib and $use_openssl/include" >&5
+echo "${ECHO_T}using OpenSSL from $use_openssl/lib and $use_openssl/include" >&6; }
+
+ saved_cflags="$CFLAGS"
+ saved_libs="$LIBS"
+ CFLAGS="$CFLAGS $DST_OPENSSL_INC"
+ LIBS="$LIBS $DNS_OPENSSL_LIBS"
+ { echo "$as_me:$LINENO: checking whether linking with OpenSSL works" >&5
+echo $ECHO_N "checking whether linking with OpenSSL works... $ECHO_C" >&6; }
+ if test "$cross_compiling" = yes; then
+ { echo "$as_me:$LINENO: result: assuming it does work on target platform" >&5
+echo "${ECHO_T}assuming it does work on target platform" >&6; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <openssl/err.h>
+int main() {
+ ERR_clear_error();
+ return (0);
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ { { echo "$as_me:$LINENO: error: Could not run test program using OpenSSL from
+$use_openssl/lib and $use_openssl/include.
+Please check the argument to --with-openssl and your
+shared library configuration (e.g., LD_LIBRARY_PATH)." >&5
+echo "$as_me: error: Could not run test program using OpenSSL from
+$use_openssl/lib and $use_openssl/include.
+Please check the argument to --with-openssl and your
+shared library configuration (e.g., LD_LIBRARY_PATH)." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+ { echo "$as_me:$LINENO: checking whether linking with OpenSSL requires -ldl" >&5
+echo $ECHO_N "checking whether linking with OpenSSL requires -ldl... $ECHO_C" >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <openssl/err.h>
+int
+main ()
+{
+ DSO_METHOD_dlfcn();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ LIBS="$LIBS -ldl"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <openssl/err.h>
+
+int
+main ()
+{
+ DSO_METHOD_dlfcn();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ DNS_OPENSSL_LIBS="$DNS_OPENSSL_LIBS -ldl"
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: unknown" >&5
+echo "${ECHO_T}unknown" >&6; }
+ { { echo "$as_me:$LINENO: error: OpenSSL has unsupported dynamic loading" >&5
+echo "$as_me: error: OpenSSL has unsupported dynamic loading" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+
+# Check whether --enable-openssl-version-check was given.
+if test "${enable_openssl_version_check+set}" = set; then
+ enableval=$enable_openssl_version_check;
+fi
+
+case "$enable_openssl_version_check" in
+yes|'')
+ { echo "$as_me:$LINENO: checking OpenSSL library version" >&5
+echo $ECHO_N "checking OpenSSL library version... $ECHO_C" >&6; }
+ if test "$cross_compiling" = yes; then
+ { echo "$as_me:$LINENO: result: assuming target platform has compatible version" >&5
+echo "${ECHO_T}assuming target platform has compatible version" >&6; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <stdio.h>
+#include <openssl/opensslv.h>
+int main() {
+ if ((OPENSSL_VERSION_NUMBER >= 0x009070cfL &&
+ OPENSSL_VERSION_NUMBER < 0x00908000L) ||
+ OPENSSL_VERSION_NUMBER >= 0x0090804fL)
+ return (0);
+ printf("\n\nFound OPENSSL_VERSION_NUMBER %#010x\n",
+ OPENSSL_VERSION_NUMBER);
+ printf("Require OPENSSL_VERSION_NUMBER 0x009070cf or greater (0.9.7l)\n"
+ "Require OPENSSL_VERSION_NUMBER 0x0090804f or greater (0.9.8d)\n\n");
+ return (1);
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ { echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6; }
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ echo "$as_me:$LINENO: result: not compatible" >&5
+echo "${ECHO_T}not compatible" >&6; }
+ OPENSSL_WARNING=yes
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+;;
+no)
+ { echo "$as_me:$LINENO: result: Skipped OpenSSL version check" >&5
+echo "${ECHO_T}Skipped OpenSSL version check" >&6; }
+;;
+esac
+
+ { echo "$as_me:$LINENO: checking for OpenSSL DSA support" >&5
+echo $ECHO_N "checking for OpenSSL DSA support... $ECHO_C" >&6; }
+ if test -f $use_openssl/include/openssl/dsa.h
+ then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_OPENSSL_DSA 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ fi
+ CFLAGS="$saved_cflags"
+ LIBS="$saved_libs"
+ ;;
+esac
+
+#
+# This would include the system openssl path (and linker options to use
+# it as needed) if it is found.
+#
+
+
+
+DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_OPENSSL_LIBS"
+
+#
+# PKCS11 (aka crypto hardware) support
+#
+# This works only with the right OpenSSL with PKCS11 engine!
+#
+
+{ echo "$as_me:$LINENO: checking for PKCS11 support" >&5
+echo $ECHO_N "checking for PKCS11 support... $ECHO_C" >&6; }
+
+# Check whether --with-pkcs11 was given.
+if test "${with_pkcs11+set}" = set; then
+ withval=$with_pkcs11; use_pkcs11="yes"
+else
+ use_pkcs11="no"
+fi
+
+
+case "$use_pkcs11" in
+ no)
+ { echo "$as_me:$LINENO: result: disabled" >&5
+echo "${ECHO_T}disabled" >&6; }
+ USE_PKCS11=""
+ ;;
+ yes)
+ { echo "$as_me:$LINENO: result: using OpenSSL with PKCS11 support" >&5
+echo "${ECHO_T}using OpenSSL with PKCS11 support" >&6; }
+ USE_PKCS11='-DUSE_PKCS11'
+ ;;
+esac
+
+
+
+{ echo "$as_me:$LINENO: checking for GSSAPI library" >&5
+echo $ECHO_N "checking for GSSAPI library... $ECHO_C" >&6; }
+
+# Check whether --with-gssapi was given.
+if test "${with_gssapi+set}" = set; then
+ withval=$with_gssapi; use_gssapi="$withval"
+else
+ use_gssapi="no"
+fi
+
+
+gssapidirs="/usr/local /usr/pkg /usr/kerberos /usr"
+if test "$use_gssapi" = "yes"
+then
+ for d in $gssapidirs
+ do
+ if test -f $d/include/gssapi/gssapi.h -o -f $d/include/gssapi.h
+ then
+ use_gssapi=$d
+ break
+ fi
+ done
+fi
+
+case "$use_gssapi" in
+ no)
+ { echo "$as_me:$LINENO: result: disabled" >&5
+echo "${ECHO_T}disabled" >&6; }
+ USE_GSSAPI=''
+ ;;
+ yes)
+ { { echo "$as_me:$LINENO: error: --with-gssapi must specify a path" >&5
+echo "$as_me: error: --with-gssapi must specify a path" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ *)
+ { echo "$as_me:$LINENO: result: looking in $use_gssapi/lib" >&5
+echo "${ECHO_T}looking in $use_gssapi/lib" >&6; }
+ USE_GSSAPI='-DGSSAPI'
+ saved_cppflags="$CPPFLAGS"
+ CPPFLAGS="-I$use_gssapi/include $CPPFLAGS"
+
+
+for ac_header in gssapi.h gssapi/gssapi.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ ISC_PLATFORM_GSSAPIHEADER="#define ISC_PLATFORM_GSSAPIHEADER <$ac_header>"
+fi
+
+done
+
+
+ if test "$ISC_PLATFORM_GSSAPIHEADER" = ""; then
+ { { echo "$as_me:$LINENO: error: gssapi.h not found" >&5
+echo "$as_me: error: gssapi.h not found" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ CPPFLAGS="$saved_cppflags"
+
+ #
+ # XXXDCL This probably doesn't work right on all systems.
+ # It will need to be worked on as problems become evident.
+ #
+ # Essentially the problems here relate to two different
+ # areas. The first area is building with either KTH
+ # or MIT Kerberos, particularly when both are present on
+ # the machine. The other is static versus dynamic linking.
+ #
+ # On the KTH vs MIT issue, Both have libkrb5 that can mess
+ # up the works if one implementation ends up trying to
+ # use the other's krb. This is unfortunately a situation
+ # that very easily arises.
+ #
+ # Dynamic linking when the dependency information is built
+ # into MIT's libgssapi_krb5 or KTH's libgssapi magically makes
+ # all such problems go away, but when that setup is not
+ # present, because either the dynamic libraries lack
+ # dependencies or static linking is being done, then the
+ # problems start to show up.
+ saved_libs="$LIBS"
+ for TRY_LIBS in \
+ "-lgssapi_krb5" \
+ "-lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err" \
+ "-lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lresolv" \
+ "-lgssapi" \
+ "-lgssapi -lkrb5 -ldes -lcrypt -lasn1 -lroken -lcom_err" \
+ "-lgssapi -lkrb5 -lcrypto -lcrypt -lasn1 -lroken -lcom_err" \
+ "-lgss"
+ do
+ # Note that this does not include $saved_libs, because
+ # on FreeBSD machines this configure script has added
+ # -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"
+ { echo "$as_me:$LINENO: checking linking as $TRY_LIBS" >&5
+echo $ECHO_N "checking linking as $TRY_LIBS... $ECHO_C" >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+gss_acquire_cred();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ gssapi_linked=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ gssapi_linked=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ case $gssapi_linked in
+ yes) { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }; break ;;
+ no) { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; } ;;
+ esac
+ done
+
+ case $gssapi_linked in
+ no) { { echo "$as_me:$LINENO: error: could not determine proper GSSAPI linkage" >&5
+echo "$as_me: error: could not determine proper GSSAPI linkage" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+
+ #
+ # XXXDCL Major kludge. Tries to cope with KTH in /usr/lib
+ # but MIT in /usr/local/lib and trying to build with KTH.
+ # /usr/local/lib can end up earlier on the link lines.
+ # Like most kludges, this one is not only inelegant it
+ # is also likely to be the wrong thing to do at least as
+ # many times as it is the right thing. Something better
+ # needs to be done.
+ #
+ if test "$use_gssapi" = "/usr" -a \
+ -f /usr/local/lib/libkrb5.a; then
+ FIX_KTH_VS_MIT=yes
+ fi
+
+ case "$FIX_KTH_VS_MIT" in
+ yes)
+ case "$enable_static_linking" in
+ yes) gssapi_lib_suffix=".a" ;;
+ *) gssapi_lib_suffix=".so" ;;
+ esac
+
+ for lib in $LIBS; do
+ case $lib in
+ -L*)
+ ;;
+ -l*)
+ new_lib=`echo $lib |
+ sed -e s%^-l%$use_gssapi/lib/lib% \
+ -e s%$%$gssapi_lib_suffix%`
+ NEW_LIBS="$NEW_LIBS $new_lib"
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: KTH vs MIT Kerberos confusion!" >&5
+echo "$as_me: error: KTH vs MIT Kerberos confusion!" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+ done
+ LIBS="$NEW_LIBS"
+ ;;
+ esac
+
+ DST_GSSAPI_INC="-I$use_gssapi/include"
+ DNS_GSSAPI_LIBS="$LIBS"
+
+ { echo "$as_me:$LINENO: result: using GSSAPI from $use_gssapi/lib and $use_gssapi/include" >&5
+echo "${ECHO_T}using GSSAPI from $use_gssapi/lib and $use_gssapi/include" >&6; }
+ LIBS="$saved_libs"
+ ;;
+esac
+
+
+
+
+
+
+
+DNS_CRYPTO_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_LIBS"
+
+#
+# Applications linking with libdns also need to link with these libraries.
+#
+
+
+
+#
+# was --with-randomdev specified?
+#
+{ echo "$as_me:$LINENO: checking for random device" >&5
+echo $ECHO_N "checking for random device... $ECHO_C" >&6; }
+
+# Check whether --with-randomdev was given.
+if test "${with_randomdev+set}" = set; then
+ withval=$with_randomdev; use_randomdev="$withval"
+else
+ use_randomdev="unspec"
+fi
+
+
+case "$use_randomdev" in
+ unspec)
+ case "$host" in
+ *-openbsd*)
+ devrandom=/dev/arandom
+ ;;
+ *)
+ devrandom=/dev/random
+ ;;
+ esac
+ { echo "$as_me:$LINENO: result: $devrandom" >&5
+echo "${ECHO_T}$devrandom" >&6; }
+ as_ac_File=`echo "ac_cv_file_$devrandom" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $devrandom" >&5
+echo $ECHO_N "checking for $devrandom... $ECHO_C" >&6; }
+if { as_var=$as_ac_File; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ test "$cross_compiling" = yes &&
+ { { echo "$as_me:$LINENO: error: cannot check for file existence when cross compiling" >&5
+echo "$as_me: error: cannot check for file existence when cross compiling" >&2;}
+ { (exit 1); exit 1; }; }
+if test -r "$devrandom"; then
+ eval "$as_ac_File=yes"
+else
+ eval "$as_ac_File=no"
+fi
+fi
+ac_res=`eval echo '${'$as_ac_File'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_File'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define PATH_RANDOMDEV "$devrandom"
+_ACEOF
+
+fi
+
+ ;;
+ yes)
+ { { echo "$as_me:$LINENO: error: --with-randomdev must specify a path" >&5
+echo "$as_me: error: --with-randomdev must specify a path" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ no)
+ { echo "$as_me:$LINENO: result: disabled" >&5
+echo "${ECHO_T}disabled" >&6; }
+ ;;
+ *)
+ cat >>confdefs.h <<_ACEOF
+#define PATH_RANDOMDEV "$use_randomdev"
+_ACEOF
+
+ { echo "$as_me:$LINENO: result: using \"$use_randomdev\"" >&5
+echo "${ECHO_T}using \"$use_randomdev\"" >&6; }
+ ;;
+esac
+
+#
+# Do we have arc4random() ?
+#
+{ echo "$as_me:$LINENO: checking for arc4random" >&5
+echo $ECHO_N "checking for arc4random... $ECHO_C" >&6; }
+if test "${ac_cv_func_arc4random+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define arc4random to an innocuous variant, in case <limits.h> declares arc4random.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define arc4random innocuous_arc4random
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char arc4random (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef arc4random
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char arc4random ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_arc4random || defined __stub___arc4random
+choke me
+#endif
+
+int
+main ()
+{
+return arc4random ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_arc4random=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_arc4random=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_arc4random" >&5
+echo "${ECHO_T}$ac_cv_func_arc4random" >&6; }
+if test $ac_cv_func_arc4random = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_ARC4RANDOM 1
+_ACEOF
+
+fi
+
+
+#
+# Begin pthreads checking.
+#
+# First, decide whether to use multithreading or not.
+#
+# Enable multithreading by default on systems where it is known
+# to work well, and where debugging of multithreaded programs
+# is supported.
+#
+
+{ echo "$as_me:$LINENO: checking whether to build with thread support" >&5
+echo $ECHO_N "checking whether to build with thread support... $ECHO_C" >&6; }
+
+case $host in
+*-dec-osf*)
+ use_threads=true ;;
+*-solaris2.[0-6])
+ # Thread signals are broken on Solaris 2.6; they are sometimes
+ # delivered to the wrong thread.
+ use_threads=false ;;
+*-solaris*)
+ use_threads=true ;;
+*-ibm-aix*)
+ use_threads=true ;;
+*-hp-hpux10*)
+ use_threads=false ;;
+*-hp-hpux11*)
+ use_threads=true ;;
+*-sgi-irix*)
+ use_threads=true ;;
+*-sco-sysv*uw*|*-*-sysv*UnixWare*)
+ # UnixWare
+ use_threads=false ;;
+*-*-sysv*OpenUNIX*)
+ # UnixWare
+ use_threads=true ;;
+*-netbsd*)
+ if test -r /usr/lib/libpthread.so ; then
+ use_threads=true
+ else
+ # Socket I/O optimizations introduced in 9.2 expose a
+ # bug in unproven-pthreads; see PR #12650
+ use_threads=false
+ fi
+ ;;
+*-openbsd*)
+ # OpenBSD users have reported that named dumps core on
+ # startup when built with threads.
+ use_threads=false ;;
+*-freebsd*)
+ use_threads=false ;;
+*-bsdi234*)
+ # Thread signals do not work reliably on some versions of BSD/OS.
+ use_threads=false ;;
+*-bsdi5*)
+ use_threads=true ;;
+*-linux*)
+ # Threads are disabled on Linux by default because most
+ # Linux kernels produce unusable core dumps from multithreaded
+ # programs, and because of limitations in setuid().
+ use_threads=false ;;
+*)
+ use_threads=false ;;
+esac
+
+# Check whether --enable-threads was given.
+if test "${enable_threads+set}" = set; then
+ enableval=$enable_threads;
+fi
+
+case "$enable_threads" in
+ yes)
+ use_threads=true
+ ;;
+ no)
+ use_threads=false
+ ;;
+ '')
+ # Use system-dependent default
+ ;;
+ *)
+ { { echo "$as_me:$LINENO: error: --enable-threads takes yes or no" >&5
+echo "$as_me: error: --enable-threads takes yes or no" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+esac
+
+if $use_threads
+then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+if $use_threads
+then
+ #
+ # Search for / configure pthreads in a system-dependent fashion.
+ #
+ case "$host" in
+ *-netbsd*)
+ # NetBSD has multiple pthreads implementations. The
+ # recommended one to use is "unproven-pthreads". The
+ # older "mit-pthreads" may also work on some NetBSD
+ # versions. The PTL2 thread library does not
+ # currently work with bind9, but can be chosen with
+ # the --with-ptl2 option for those who wish to
+ # experiment with it.
+ CC="gcc"
+ { echo "$as_me:$LINENO: checking which NetBSD thread library to use" >&5
+echo $ECHO_N "checking which NetBSD thread library to use... $ECHO_C" >&6; }
+
+
+# Check whether --with-ptl2 was given.
+if test "${with_ptl2+set}" = set; then
+ withval=$with_ptl2; use_ptl2="$withval"
+else
+ use_ptl2="no"
+fi
+
+
+ : ${LOCALBASE:=/usr/pkg}
+
+ if test "X$use_ptl2" = "Xyes"
+ then
+ { echo "$as_me:$LINENO: result: PTL2" >&5
+echo "${ECHO_T}PTL2" >&6; }
+ { echo "$as_me:$LINENO: WARNING: linking with PTL2 is highly experimental and not expected to work" >&5
+echo "$as_me: WARNING: linking with PTL2 is highly experimental and not expected to work" >&2;}
+ CC=ptlgcc
+ else
+ if test -r /usr/lib/libpthread.so
+ then
+ { echo "$as_me:$LINENO: result: native" >&5
+echo "${ECHO_T}native" >&6; }
+ LIBS="-lpthread $LIBS"
+ else
+ if test ! -d $LOCALBASE/pthreads
+ then
+ { echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6; }
+ { { echo "$as_me:$LINENO: error: \"could not find thread libraries\"" >&5
+echo "$as_me: error: \"could not find thread libraries\"" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ if $use_threads
+ then
+ { echo "$as_me:$LINENO: result: mit-pthreads/unproven-pthreads" >&5
+echo "${ECHO_T}mit-pthreads/unproven-pthreads" >&6; }
+ pkg="$LOCALBASE/pthreads"
+ lib1="-L$pkg/lib -Wl,-R$pkg/lib"
+ lib2="-lpthread -lm -lgcc -lpthread"
+ LIBS="$lib1 $lib2 $LIBS"
+ CPPFLAGS="$CPPFLAGS -I$pkg/include"
+ STD_CINCLUDES="$STD_CINCLUDES -I$pkg/include"
+ fi
+ fi
+ fi
+ ;;
+ *-freebsd*)
+ # We don't want to set -lpthread as that break
+ # the ability to choose threads library at final
+ # link time and is not valid for all architectures.
+
+ PTHREAD=
+ if test "X$GCC" = "Xyes"; then
+ saved_cc="$CC"
+ CC="$CC -pthread"
+ { echo "$as_me:$LINENO: checking for gcc -pthread support" >&5
+echo $ECHO_N "checking for gcc -pthread support... $ECHO_C" >&6; };
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <pthread.h>
+int
+main ()
+{
+printf("%x\n", pthread_create);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ PTHREAD="yes"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ CC="$saved_cc"
+ fi
+ if test "X$PTHREAD" != "Xyes"; then
+
+{ echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5
+echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6; }
+if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_pthread_pthread_create=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_pthread_pthread_create=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6; }
+if test $ac_cv_lib_pthread_pthread_create = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPTHREAD 1
+_ACEOF
+
+ LIBS="-lpthread $LIBS"
+
+else
+
+{ echo "$as_me:$LINENO: checking for thread_create in -lthr" >&5
+echo $ECHO_N "checking for thread_create in -lthr... $ECHO_C" >&6; }
+if test "${ac_cv_lib_thr_thread_create+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lthr $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char thread_create ();
+int
+main ()
+{
+return thread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_thr_thread_create=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_thr_thread_create=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_thr_thread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_thr_thread_create" >&6; }
+if test $ac_cv_lib_thr_thread_create = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBTHR 1
+_ACEOF
+
+ LIBS="-lthr $LIBS"
+
+else
+
+{ echo "$as_me:$LINENO: checking for pthread_create in -lc_r" >&5
+echo $ECHO_N "checking for pthread_create in -lc_r... $ECHO_C" >&6; }
+if test "${ac_cv_lib_c_r_pthread_create+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc_r $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_c_r_pthread_create=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_c_r_pthread_create=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_pthread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_c_r_pthread_create" >&6; }
+if test $ac_cv_lib_c_r_pthread_create = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBC_R 1
+_ACEOF
+
+ LIBS="-lc_r $LIBS"
+
+else
+
+{ echo "$as_me:$LINENO: checking for pthread_create in -lc" >&5
+echo $ECHO_N "checking for pthread_create in -lc... $ECHO_C" >&6; }
+if test "${ac_cv_lib_c_pthread_create+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_c_pthread_create=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_c_pthread_create=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_pthread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_c_pthread_create" >&6; }
+if test $ac_cv_lib_c_pthread_create = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBC 1
+_ACEOF
+
+ LIBS="-lc $LIBS"
+
+else
+ { { echo "$as_me:$LINENO: error: \"could not find thread libraries\"" >&5
+echo "$as_me: error: \"could not find thread libraries\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+
+fi
+
+fi
+
+ fi
+ ;;
+ *)
+
+{ echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5
+echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6; }
+if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_pthread_pthread_create=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_pthread_pthread_create=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6; }
+if test $ac_cv_lib_pthread_pthread_create = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPTHREAD 1
+_ACEOF
+
+ LIBS="-lpthread $LIBS"
+
+else
+
+{ echo "$as_me:$LINENO: checking for __pthread_create in -lpthread" >&5
+echo $ECHO_N "checking for __pthread_create in -lpthread... $ECHO_C" >&6; }
+if test "${ac_cv_lib_pthread___pthread_create+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char __pthread_create ();
+int
+main ()
+{
+return __pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_pthread___pthread_create=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_pthread___pthread_create=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread___pthread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread___pthread_create" >&6; }
+if test $ac_cv_lib_pthread___pthread_create = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPTHREAD 1
+_ACEOF
+
+ LIBS="-lpthread $LIBS"
+
+else
+
+{ echo "$as_me:$LINENO: checking for __pthread_create_system in -lpthread" >&5
+echo $ECHO_N "checking for __pthread_create_system in -lpthread... $ECHO_C" >&6; }
+if test "${ac_cv_lib_pthread___pthread_create_system+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char __pthread_create_system ();
+int
+main ()
+{
+return __pthread_create_system ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_pthread___pthread_create_system=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_pthread___pthread_create_system=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread___pthread_create_system" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread___pthread_create_system" >&6; }
+if test $ac_cv_lib_pthread___pthread_create_system = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPTHREAD 1
+_ACEOF
+
+ LIBS="-lpthread $LIBS"
+
+else
+
+{ echo "$as_me:$LINENO: checking for pthread_create in -lc_r" >&5
+echo $ECHO_N "checking for pthread_create in -lc_r... $ECHO_C" >&6; }
+if test "${ac_cv_lib_c_r_pthread_create+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc_r $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_c_r_pthread_create=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_c_r_pthread_create=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_pthread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_c_r_pthread_create" >&6; }
+if test $ac_cv_lib_c_r_pthread_create = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBC_R 1
+_ACEOF
+
+ LIBS="-lc_r $LIBS"
+
+else
+
+{ echo "$as_me:$LINENO: checking for pthread_create in -lc" >&5
+echo $ECHO_N "checking for pthread_create in -lc... $ECHO_C" >&6; }
+if test "${ac_cv_lib_c_pthread_create+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_c_pthread_create=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_c_pthread_create=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_pthread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_c_pthread_create" >&6; }
+if test $ac_cv_lib_c_pthread_create = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBC 1
+_ACEOF
+
+ LIBS="-lc $LIBS"
+
+else
+ { { echo "$as_me:$LINENO: error: \"could not find thread libraries\"" >&5
+echo "$as_me: error: \"could not find thread libraries\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+
+fi
+
+fi
+
+fi
+
+ ;;
+ esac
+fi
+
+if $use_threads
+then
+ if test "X$GCC" = "Xyes"; then
+ case "$host" in
+ *-freebsd*)
+ CC="$CC -pthread"
+ CCOPT="$CCOPT -pthread"
+ STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE"
+ ;;
+ *-openbsd*)
+ CC="$CC -pthread"
+ CCOPT="$CCOPT -pthread"
+ ;;
+ *-solaris*)
+ LIBS="$LIBS -lthread"
+ ;;
+ *-ibm-aix*)
+ STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE"
+ ;;
+ esac
+ else
+ case $host in
+ *-dec-osf*)
+ CC="$CC -pthread"
+ CCOPT="$CCOPT -pthread"
+ ;;
+ *-solaris*)
+ CC="$CC -mt"
+ CCOPT="$CCOPT -mt"
+ ;;
+ *-ibm-aix*)
+ STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE"
+ ;;
+ *-sco-sysv*uw*|*-*-sysv*UnixWare*)
+ CC="$CC -Kthread"
+ CCOPT="$CCOPT -Kthread"
+ ;;
+ *-*-sysv*OpenUNIX*)
+ CC="$CC -Kpthread"
+ CCOPT="$CCOPT -Kpthread"
+ ;;
+ esac
+ fi
+ ALWAYS_DEFINES="-D_REENTRANT"
+ ISC_PLATFORM_USETHREADS="#define ISC_PLATFORM_USETHREADS 1"
+ thread_dir=pthreads
+ #
+ # We'd like to use sigwait() too
+ #
+ { echo "$as_me:$LINENO: checking for sigwait" >&5
+echo $ECHO_N "checking for sigwait... $ECHO_C" >&6; }
+if test "${ac_cv_func_sigwait+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define sigwait to an innocuous variant, in case <limits.h> declares sigwait.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define sigwait innocuous_sigwait
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char sigwait (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef sigwait
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sigwait ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_sigwait || defined __stub___sigwait
+choke me
+#endif
+
+int
+main ()
+{
+return sigwait ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_sigwait=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_sigwait=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_sigwait" >&5
+echo "${ECHO_T}$ac_cv_func_sigwait" >&6; }
+if test $ac_cv_func_sigwait = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SIGWAIT 1
+_ACEOF
+
+else
+ { echo "$as_me:$LINENO: checking for sigwait in -lc" >&5
+echo $ECHO_N "checking for sigwait in -lc... $ECHO_C" >&6; }
+if test "${ac_cv_lib_c_sigwait+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sigwait ();
+int
+main ()
+{
+return sigwait ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_c_sigwait=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_c_sigwait=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_sigwait" >&5
+echo "${ECHO_T}$ac_cv_lib_c_sigwait" >&6; }
+if test $ac_cv_lib_c_sigwait = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SIGWAIT 1
+_ACEOF
+
+else
+ { echo "$as_me:$LINENO: checking for sigwait in -lpthread" >&5
+echo $ECHO_N "checking for sigwait in -lpthread... $ECHO_C" >&6; }
+if test "${ac_cv_lib_pthread_sigwait+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sigwait ();
+int
+main ()
+{
+return sigwait ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_pthread_sigwait=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_pthread_sigwait=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_sigwait" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread_sigwait" >&6; }
+if test $ac_cv_lib_pthread_sigwait = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SIGWAIT 1
+_ACEOF
+
+else
+ { echo "$as_me:$LINENO: checking for _Psigwait in -lpthread" >&5
+echo $ECHO_N "checking for _Psigwait in -lpthread... $ECHO_C" >&6; }
+if test "${ac_cv_lib_pthread__Psigwait+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char _Psigwait ();
+int
+main ()
+{
+return _Psigwait ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_pthread__Psigwait=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_pthread__Psigwait=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread__Psigwait" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread__Psigwait" >&6; }
+if test $ac_cv_lib_pthread__Psigwait = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SIGWAIT 1
+_ACEOF
+
+fi
+
+fi
+
+fi
+
+fi
+
+
+ { echo "$as_me:$LINENO: checking for pthread_attr_getstacksize" >&5
+echo $ECHO_N "checking for pthread_attr_getstacksize... $ECHO_C" >&6; }
+if test "${ac_cv_func_pthread_attr_getstacksize+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define pthread_attr_getstacksize to an innocuous variant, in case <limits.h> declares pthread_attr_getstacksize.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define pthread_attr_getstacksize innocuous_pthread_attr_getstacksize
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char pthread_attr_getstacksize (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef pthread_attr_getstacksize
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_attr_getstacksize ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_pthread_attr_getstacksize || defined __stub___pthread_attr_getstacksize
+choke me
+#endif
+
+int
+main ()
+{
+return pthread_attr_getstacksize ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_pthread_attr_getstacksize=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_pthread_attr_getstacksize=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_pthread_attr_getstacksize" >&5
+echo "${ECHO_T}$ac_cv_func_pthread_attr_getstacksize" >&6; }
+if test $ac_cv_func_pthread_attr_getstacksize = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTHREAD_ATTR_GETSTACKSIZE 1
+_ACEOF
+
+fi
+
+
+ { echo "$as_me:$LINENO: checking for pthread_attr_setstacksize" >&5
+echo $ECHO_N "checking for pthread_attr_setstacksize... $ECHO_C" >&6; }
+if test "${ac_cv_func_pthread_attr_setstacksize+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define pthread_attr_setstacksize to an innocuous variant, in case <limits.h> declares pthread_attr_setstacksize.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define pthread_attr_setstacksize innocuous_pthread_attr_setstacksize
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char pthread_attr_setstacksize (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef pthread_attr_setstacksize
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_attr_setstacksize ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_pthread_attr_setstacksize || defined __stub___pthread_attr_setstacksize
+choke me
+#endif
+
+int
+main ()
+{
+return pthread_attr_setstacksize ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_pthread_attr_setstacksize=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_pthread_attr_setstacksize=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_pthread_attr_setstacksize" >&5
+echo "${ECHO_T}$ac_cv_func_pthread_attr_setstacksize" >&6; }
+if test $ac_cv_func_pthread_attr_setstacksize = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
+_ACEOF
+
+fi
+
+
+ #
+ # Additional OS-specific issues related to pthreads and sigwait.
+ #
+ case "$host" in
+ #
+ # One more place to look for sigwait.
+ #
+ *-freebsd*)
+ { echo "$as_me:$LINENO: checking for sigwait in -lc_r" >&5
+echo $ECHO_N "checking for sigwait in -lc_r... $ECHO_C" >&6; }
+if test "${ac_cv_lib_c_r_sigwait+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc_r $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sigwait ();
+int
+main ()
+{
+return sigwait ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_c_r_sigwait=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_c_r_sigwait=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_sigwait" >&5
+echo "${ECHO_T}$ac_cv_lib_c_r_sigwait" >&6; }
+if test $ac_cv_lib_c_r_sigwait = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SIGWAIT 1
+_ACEOF
+
+fi
+
+ case $host in
+ *-freebsd5.[012]|*-freebsd5.[012].*);;
+ *-freebsd5.[3456789]|*-freebsd5.[3456789].*)
+ cat >>confdefs.h <<\_ACEOF
+#define NEED_PTHREAD_SCOPE_SYSTEM 1
+_ACEOF
+
+ ;;
+ *-freebsd6.*)
+ cat >>confdefs.h <<\_ACEOF
+#define NEED_PTHREAD_SCOPE_SYSTEM 1
+_ACEOF
+
+ ;;
+ esac
+ ;;
+ #
+ # BSDI 3.0 through 4.0.1 needs pthread_init() to be
+ # called before certain pthreads calls. This is deprecated
+ # in BSD/OS 4.1.
+ #
+ *-bsdi3.*|*-bsdi4.0*)
+ cat >>confdefs.h <<\_ACEOF
+#define NEED_PTHREAD_INIT 1
+_ACEOF
+
+ ;;
+ #
+ # LinuxThreads requires some changes to the way we
+ # deal with signals.
+ #
+ *-linux*)
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_LINUXTHREADS 1
+_ACEOF
+
+ ;;
+ #
+ # Ensure the right sigwait() semantics on Solaris and make
+ # sure we call pthread_setconcurrency.
+ #
+ *-solaris*)
+ cat >>confdefs.h <<\_ACEOF
+#define _POSIX_PTHREAD_SEMANTICS 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: checking for pthread_setconcurrency" >&5
+echo $ECHO_N "checking for pthread_setconcurrency... $ECHO_C" >&6; }
+if test "${ac_cv_func_pthread_setconcurrency+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define pthread_setconcurrency to an innocuous variant, in case <limits.h> declares pthread_setconcurrency.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define pthread_setconcurrency innocuous_pthread_setconcurrency
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char pthread_setconcurrency (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef pthread_setconcurrency
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_setconcurrency ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_pthread_setconcurrency || defined __stub___pthread_setconcurrency
+choke me
+#endif
+
+int
+main ()
+{
+return pthread_setconcurrency ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_pthread_setconcurrency=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_pthread_setconcurrency=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_pthread_setconcurrency" >&5
+echo "${ECHO_T}$ac_cv_func_pthread_setconcurrency" >&6; }
+if test $ac_cv_func_pthread_setconcurrency = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define CALL_PTHREAD_SETCONCURRENCY 1
+_ACEOF
+
+fi
+
+ ;;
+ #
+ # UnixWare does things its own way.
+ #
+ *-sco-sysv*uw*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_UNIXWARE_SIGWAIT 1
+_ACEOF
+
+ ;;
+ esac
+
+ #
+ # Look for sysconf to allow detection of the number of processors.
+ #
+ { echo "$as_me:$LINENO: checking for sysconf" >&5
+echo $ECHO_N "checking for sysconf... $ECHO_C" >&6; }
+if test "${ac_cv_func_sysconf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define sysconf to an innocuous variant, in case <limits.h> declares sysconf.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define sysconf innocuous_sysconf
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char sysconf (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef sysconf
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sysconf ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_sysconf || defined __stub___sysconf
+choke me
+#endif
+
+int
+main ()
+{
+return sysconf ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_sysconf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_sysconf=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_sysconf" >&5
+echo "${ECHO_T}$ac_cv_func_sysconf" >&6; }
+if test $ac_cv_func_sysconf = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYSCONF 1
+_ACEOF
+
+fi
+
+
+else
+ ISC_PLATFORM_USETHREADS="#undef ISC_PLATFORM_USETHREADS"
+ thread_dir=nothreads
+ ALWAYS_DEFINES=""
+fi
+
+
+
+ISC_THREAD_DIR=$thread_dir
+
+
+#
+# was --with-libxml2 specified?
+#
+{ echo "$as_me:$LINENO: checking for libxml2 library" >&5
+echo $ECHO_N "checking for libxml2 library... $ECHO_C" >&6; }
+
+# Check whether --with-libxml2 was given.
+if test "${with_libxml2+set}" = set; then
+ withval=$with_libxml2; use_libxml2="$withval"
+else
+ use_libxml2="auto"
+fi
+
+
+case "$use_libxml2" in
+ no)
+ DST_LIBXML2_INC=""
+ ;;
+ auto|yes)
+ case X`(xml2-config --version) 2>/dev/null` in
+ X2.[67].*)
+ libxml2_libs=`xml2-config --libs`
+ libxml2_cflags=`xml2-config --cflags`
+ ;;
+ *)
+ libxml2_libs=
+ libxml2_cflags=
+ ;;
+ esac
+ ;;
+ *)
+ if test -f "$use_libxml2/bin/xml2-config" ; then
+ libxml2_libs=`$use_libxml2/bin/xml2-config --libs`
+ libxml2_cflags=`$use_libxml2/bin/xml2-config --cflags`
+ fi
+ ;;
+esac
+
+if test "X$libxml2_libs" != "X"
+then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ CFLAGS="$CFLAGS $libxml2_cflags"
+ LIBS="$LIBS $libxml2_libs"
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBXML2 1
+_ACEOF
+
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+#
+# In solaris 10, SMF can manage named service
+#
+
+{ echo "$as_me:$LINENO: checking for smf_enable_instance in -lscf" >&5
+echo $ECHO_N "checking for smf_enable_instance in -lscf... $ECHO_C" >&6; }
+if test "${ac_cv_lib_scf_smf_enable_instance+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lscf $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char smf_enable_instance ();
+int
+main ()
+{
+return smf_enable_instance ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_scf_smf_enable_instance=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_scf_smf_enable_instance=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_scf_smf_enable_instance" >&5
+echo "${ECHO_T}$ac_cv_lib_scf_smf_enable_instance" >&6; }
+if test $ac_cv_lib_scf_smf_enable_instance = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSCF 1
+_ACEOF
+
+ LIBS="-lscf $LIBS"
+
+fi
+
+
+#
+# flockfile is usually provided by pthreads, but we may want to use it
+# even if compiled with --disable-threads. getc_unlocked might also not
+# be defined.
+#
+{ echo "$as_me:$LINENO: checking for flockfile" >&5
+echo $ECHO_N "checking for flockfile... $ECHO_C" >&6; }
+if test "${ac_cv_func_flockfile+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define flockfile to an innocuous variant, in case <limits.h> declares flockfile.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define flockfile innocuous_flockfile
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char flockfile (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef flockfile
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char flockfile ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_flockfile || defined __stub___flockfile
+choke me
+#endif
+
+int
+main ()
+{
+return flockfile ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_flockfile=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_flockfile=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_flockfile" >&5
+echo "${ECHO_T}$ac_cv_func_flockfile" >&6; }
+if test $ac_cv_func_flockfile = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_FLOCKFILE 1
+_ACEOF
+
+fi
+
+{ echo "$as_me:$LINENO: checking for getc_unlocked" >&5
+echo $ECHO_N "checking for getc_unlocked... $ECHO_C" >&6; }
+if test "${ac_cv_func_getc_unlocked+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getc_unlocked to an innocuous variant, in case <limits.h> declares getc_unlocked.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getc_unlocked innocuous_getc_unlocked
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getc_unlocked (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getc_unlocked
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getc_unlocked ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_getc_unlocked || defined __stub___getc_unlocked
+choke me
+#endif
+
+int
+main ()
+{
+return getc_unlocked ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_getc_unlocked=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_getc_unlocked=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_getc_unlocked" >&5
+echo "${ECHO_T}$ac_cv_func_getc_unlocked" >&6; }
+if test $ac_cv_func_getc_unlocked = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETCUNLOCKED 1
+_ACEOF
+
+fi
+
+
+#
+# Indicate what the final decision was regarding threads.
+#
+{ echo "$as_me:$LINENO: checking whether to build with threads" >&5
+echo $ECHO_N "checking whether to build with threads... $ECHO_C" >&6; }
+if $use_threads; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+#
+# End of pthreads stuff.
+#
+
+#
+# Large File
+#
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+ enableval=$enable_largefile; want_largefile="yes"
+else
+ want_largefile="no"
+fi
+
+case $want_largefile in
+ yes)
+ ALWAYS_DEFINES="$ALWAYS_DEFINES -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+ ;;
+ *)
+ ;;
+esac
+
+#
+# Additional compiler settings.
+#
+MKDEPCC="$CC"
+MKDEPCFLAGS="-M"
+IRIX_DNSSEC_WARNINGS_HACK=""
+
+if test "X$GCC" = "Xyes"; then
+ { echo "$as_me:$LINENO: checking if \"$CC\" supports -fno-strict-aliasing" >&5
+echo $ECHO_N "checking if \"$CC\" supports -fno-strict-aliasing... $ECHO_C" >&6; }
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS=-fno-strict-aliasing
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ FNOSTRICTALIASING=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ FNOSTRICTALIASING=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$SAVE_CFLAGS
+ if test "$FNOSTRICTALIASING" = "yes"; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ STD_CWARNINGS="$STD_CWARNINGS -W -Wall -Wmissing-prototypes -Wcast-qual -Wwrite-strings -Wformat -Wpointer-arith -fno-strict-aliasing"
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ STD_CWARNINGS="$STD_CWARNINGS -W -Wall -Wmissing-prototypes -Wcast-qual -Wwrite-strings -Wformat -Wpointer-arith"
+ fi
+ case "$host" in
+ *-hp-hpux*)
+ LDFLAGS="-Wl,+vnocompatwarnings $LDFLAGS"
+ ;;
+ esac
+else
+ case $host in
+ *-dec-osf*)
+ CC="$CC -std"
+ CCOPT="$CCOPT -std"
+ MKDEPCC="$CC"
+ ;;
+ *-hp-hpux*)
+ CC="$CC -Ae -z"
+ # The version of the C compiler that constantly warns about
+ # 'const' as well as alignment issues is unfortunately not
+ # able to be discerned via the version of the operating
+ # system, nor does cc have a version flag.
+ case "`$CC +W 123 2>&1`" in
+ *Unknown?option*)
+ STD_CWARNINGS="+w1"
+ ;;
+ *)
+ # Turn off the pointlessly noisy warnings.
+ STD_CWARNINGS="+w1 +W 474,530,2193,2236"
+ ;;
+ esac
+ CCOPT="$CCOPT -Ae -z"
+ LDFLAGS="-Wl,+vnocompatwarnings $LDFLAGS"
+ MKDEPPROG='cc -Ae -E -Wp,-M >/dev/null 2>>$TMP'
+ ;;
+ *-sgi-irix*)
+ STD_CWARNINGS="-fullwarn -woff 1209"
+ #
+ # Silence more than 250 instances of
+ # "prototyped function redeclared without prototype"
+ # and 11 instances of
+ # "variable ... was set but never used"
+ # from lib/dns/sec/openssl.
+ #
+ IRIX_DNSSEC_WARNINGS_HACK="-woff 1692,1552"
+ ;;
+ *-solaris*)
+ MKDEPCFLAGS="-xM"
+ ;;
+ *-sco-sysv*uw*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ # UnixWare
+ CC="$CC -w"
+ ;;
+ esac
+fi
+
+
+
+
+
+
+#
+# NLS
+#
+{ echo "$as_me:$LINENO: checking for catgets" >&5
+echo $ECHO_N "checking for catgets... $ECHO_C" >&6; }
+if test "${ac_cv_func_catgets+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define catgets to an innocuous variant, in case <limits.h> declares catgets.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define catgets innocuous_catgets
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char catgets (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef catgets
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char catgets ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_catgets || defined __stub___catgets
+choke me
+#endif
+
+int
+main ()
+{
+return catgets ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_catgets=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_catgets=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_catgets" >&5
+echo "${ECHO_T}$ac_cv_func_catgets" >&6; }
+if test $ac_cv_func_catgets = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_CATGETS 1
+_ACEOF
+
+fi
+
+
+#
+# -lxnet buys us one big porting headache... standards, gotta love 'em.
+#
+# AC_CHECK_LIB(xnet, socket, ,
+# AC_CHECK_LIB(socket, socket)
+# AC_CHECK_LIB(nsl, inet_ntoa)
+# )
+#
+# Use this for now, instead:
+#
+case "$host" in
+ mips-sgi-irix*)
+ ;;
+ *)
+
+{ echo "$as_me:$LINENO: checking for socket in -lsocket" >&5
+echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6; }
+if test "${ac_cv_lib_socket_socket+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_socket_socket=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_socket_socket=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6; }
+if test $ac_cv_lib_socket_socket = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
+
+ LIBS="-lsocket $LIBS"
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for inet_ntoa in -lnsl" >&5
+echo $ECHO_N "checking for inet_ntoa in -lnsl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_nsl_inet_ntoa+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inet_ntoa ();
+int
+main ()
+{
+return inet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_nsl_inet_ntoa=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_nsl_inet_ntoa=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_inet_ntoa" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_inet_ntoa" >&6; }
+if test $ac_cv_lib_nsl_inet_ntoa = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNSL 1
+_ACEOF
+
+ LIBS="-lnsl $LIBS"
+
+fi
+
+ ;;
+esac
+
+#
+# Work around Solaris's select() limitations.
+#
+case "$host" in
+ *-solaris2.[89]|*-solaris2.1?)
+
+cat >>confdefs.h <<\_ACEOF
+#define FD_SETSIZE 65536
+_ACEOF
+
+ ;;
+esac
+
+#
+# Purify support
+#
+{ echo "$as_me:$LINENO: checking whether to use purify" >&5
+echo $ECHO_N "checking whether to use purify... $ECHO_C" >&6; }
+
+# Check whether --with-purify was given.
+if test "${with_purify+set}" = set; then
+ withval=$with_purify; use_purify="$withval"
+else
+ use_purify="no"
+fi
+
+
+case "$use_purify" in
+ no)
+ ;;
+ yes)
+ # Extract the first word of "purify", so it can be a program name with args.
+set dummy purify; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_purify_path+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $purify_path in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_purify_path="$purify_path" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_purify_path="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_purify_path" && ac_cv_path_purify_path="purify"
+ ;;
+esac
+fi
+purify_path=$ac_cv_path_purify_path
+if test -n "$purify_path"; then
+ { echo "$as_me:$LINENO: result: $purify_path" >&5
+echo "${ECHO_T}$purify_path" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ ;;
+ *)
+ purify_path="$use_purify"
+ ;;
+esac
+
+case "$use_purify" in
+ no)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ PURIFY=""
+ ;;
+ *)
+ if test -f $purify_path || test $purify_path = purify; then
+ { echo "$as_me:$LINENO: result: $purify_path" >&5
+echo "${ECHO_T}$purify_path" >&6; }
+ PURIFYFLAGS="`echo $PURIFYOPTIONS`"
+ PURIFY="$purify_path $PURIFYFLAGS"
+ else
+ { { echo "$as_me:$LINENO: error: $purify_path not found.
+
+Please choose the proper path with the following command:
+
+ configure --with-purify=PATH
+" >&5
+echo "$as_me: error: $purify_path not found.
+
+Please choose the proper path with the following command:
+
+ configure --with-purify=PATH
+" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ ;;
+esac
+
+
+
+#
+# GNU libtool support
+#
+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
+
+
+# Check whether --with-libtool was given.
+if test "${with_libtool+set}" = set; then
+ withval=$with_libtool; use_libtool="$withval"
+else
+ use_libtool="no"
+fi
+
+
+case $use_libtool in
+ yes)
+ # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval=$enable_shared; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_shared=yes
+fi
+
+
+# Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then
+ enableval=$enable_static; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_static=yes
+fi
+
+
+# Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+ enableval=$enable_fast_install; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_fast_install=yes
+fi
+
+
+{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; }
+if test "${lt_cv_path_SED+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && break
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+
+fi
+
+SED=$lt_cv_path_SED
+{ echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6; }
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+else
+ { echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ { echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+{ echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; }
+if test "${lt_cv_ld_reload_flag+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_ld_reload_flag='-r'
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$CC -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; }
+if test "${lt_cv_path_NM+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/${ac_tool_prefix}nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
+echo "${ECHO_T}$lt_cv_path_NM" >&6; }
+NM="$lt_cv_path_NM"
+
+{ echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5
+echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6; }
+if test "${lt_cv_deplibs_check_method+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[45]*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump'.
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | kfreebsd*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case "$host_cpu" in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx*)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sco3.2v5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '#line 10029 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ case "`/usr/bin/file conftest.o`" in
+ *32-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ { echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; }
+if test "${lt_cv_cc_needs_belf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ lt_cv_cc_needs_belf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ lt_cv_cc_needs_belf=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; }
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CXXFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; }
+if test -z "$CXXCPP"; then
+ if test "${ac_cv_prog_CXXCPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+fi
+
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$F77"; then
+ ac_cv_prog_F77="$F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+F77=$ac_cv_prog_F77
+if test -n "$F77"; then
+ { echo "$as_me:$LINENO: result: $F77" >&5
+echo "${ECHO_T}$F77" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$F77" && break
+ done
+fi
+if test -z "$F77"; then
+ ac_ct_F77=$F77
+ for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgf95 lf95 ftn
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_F77"; then
+ ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_F77="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_F77=$ac_cv_prog_ac_ct_F77
+if test -n "$ac_ct_F77"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
+echo "${ECHO_T}$ac_ct_F77" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_F77" && break
+done
+
+ if test "x$ac_ct_F77" = x; then
+ F77=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ F77=$ac_ct_F77
+ fi
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+rm -f a.out
+
+# If we don't use `.F' as extension, the preprocessor is not run on the
+# input file. (Note that this only needs to work for GNU compilers.)
+ac_save_ext=$ac_ext
+ac_ext=F
+{ echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; }
+if test "${ac_cv_f77_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+#ifndef __GNUC__
+ choke me
+#endif
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_f77_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_f77_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; }
+ac_ext=$ac_save_ext
+ac_test_FFLAGS=${FFLAGS+set}
+ac_save_FFLAGS=$FFLAGS
+FFLAGS=
+{ echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
+echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_f77_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ FFLAGS=-g
+cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_f77_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_f77_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_prog_f77_g=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; }
+if test "$ac_test_FFLAGS" = set; then
+ FFLAGS=$ac_save_FFLAGS
+elif test $ac_cv_prog_f77_g = yes; then
+ if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+ FFLAGS="-g -O2"
+ else
+ FFLAGS="-g"
+ fi
+else
+ if test "x$ac_cv_f77_compiler_gnu" = xyes; then
+ FFLAGS="-O2"
+ else
+ FFLAGS=
+ fi
+fi
+
+G77=`test $ac_compiler_gnu = yes && echo yes`
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+
+# find the maximum length of command line arguments
+{ echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; }
+if test "${lt_cv_sys_max_cmd_len+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* )
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for *BSD
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ ;;
+
+ *)
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \
+ = "XX$teststring") >/dev/null 2>&1 &&
+ new_result=`expr "X$teststring" : ".*" 2>&1` &&
+ lt_cv_sys_max_cmd_len=$new_result &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on massive
+ # amounts of additional arguments before passing them to the linker.
+ # It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ ;;
+ esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+ { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; }
+else
+ { echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6; }
+fi
+
+
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
+echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; }
+if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDEGRST]'
+ fi
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+linux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDGIRSTW]'
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
+osf*)
+ symcode='[BCDEGQRST]'
+ ;;
+solaris* | sysv5*)
+ symcode='[BDRT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Write the raw and C identifiers.
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5
+ (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if grep ' nm_test_var$' "$nlist" >/dev/null; then
+ if grep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ { echo "$as_me:$LINENO: result: failed" >&5
+echo "${ECHO_T}failed" >&6; }
+else
+ { echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6; }
+fi
+
+{ echo "$as_me:$LINENO: checking for objdir" >&5
+echo $ECHO_N "checking for objdir... $ECHO_C" >&6; }
+if test "${lt_cv_objdir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
+echo "${ECHO_T}$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_AR="ar"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
+ ;;
+ *)
+ old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ { echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/${ac_tool_prefix}file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ { echo "$as_me:$LINENO: checking for file" >&5
+echo $ECHO_N "checking for file... $ECHO_C" >&6; }
+if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ { echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ else
+ MAGIC_CMD=:
+ fi
+fi
+
+ fi
+ ;;
+esac
+
+enable_dlopen=no
+enable_win32_dll=no
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then
+ withval=$with_pic; pic_mode="$withval"
+else
+ pic_mode=default
+fi
+
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+#
+# Check for any special shared library compilation flags.
+#
+lt_prog_cc_shlib=
+if test "$GCC" = no; then
+ case $host_os in
+ sco3.2v5*)
+ lt_prog_cc_shlib='-belf'
+ ;;
+ esac
+fi
+if test -n "$lt_prog_cc_shlib"; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&5
+echo "$as_me: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&2;}
+ if echo "$old_CC $old_CFLAGS " | grep "[ ]$lt_prog_cc_shlib[ ]" >/dev/null; then :
+ else
+ { echo "$as_me:$LINENO: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5
+echo "$as_me: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;}
+ lt_cv_prog_cc_can_build_shared=no
+ fi
+fi
+
+
+#
+# Check to make sure the static flag actually works.
+#
+{ echo "$as_me:$LINENO: checking if $compiler static flag $lt_prog_compiler_static works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_prog_compiler_static works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_static_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_static_works=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_prog_compiler_static"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ else
+ lt_prog_compiler_static_works=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; }
+
+if test x"$lt_prog_compiler_static_works" = xyes; then
+ :
+else
+ lt_prog_compiler_static=
+fi
+
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin'
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:12151: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:12155: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s conftest.err; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case "$cc_basename" in
+ xlc*)
+ lt_prog_compiler_pic='-qnocommon'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ linux*)
+ case $CC in
+ icc* | ecc*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ sco3.2v5*)
+ lt_prog_compiler_pic='-Kpic'
+ lt_prog_compiler_static='-dn'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl='-Qoption ld '
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic='-Kconform_pic'
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic='-pic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:12394: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:12398: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s conftest.err; then
+ lt_prog_compiler_pic_works=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_prog_compiler_pic_works" = xyes; then
+ case $lt_prog_compiler_pic in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+ esac
+else
+ lt_prog_compiler_pic=
+ lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+case "$host_os" in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic=
+ ;;
+ *)
+ lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:12454: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:12458: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s out/conftest.err; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w .
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+ runpath_var=
+ allow_undefined_flag=
+ enable_shared_with_static_runtimes=no
+ archive_cmds=
+ archive_expsym_cmds=
+ old_archive_From_new_cmds=
+ old_archive_from_expsyms_cmds=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ thread_safe_flag_spec=
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_flag_spec_ld=
+ hardcode_libdir_separator=
+ hardcode_direct=no
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=unsupported
+ link_all_deplibs=unknown
+ hardcode_automatic=no
+ module_cmds=
+ module_expsym_cmds=
+ always_export_symbols=no
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ allow_undefined_flag=unsupported
+ always_export_symbols=no
+ enable_shared_with_static_runtimes=yes
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris* | sysv5*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_cmds="$tmp_archive_cmds"
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~
+cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+$echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ else
+ archive_expsym_cmds="$tmp_archive_cmds"
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = yes; then
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes && test -z "$link_static_flag"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds=''
+ hardcode_direct=yes
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.012|aix4.012.*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct=yes
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ esac
+ shared_flag='-shared'
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag=' ${wl}-bernotok'
+ allow_undefined_flag=' ${wl}-berok'
+ # -bexpall does not export symbols beginning with underscore (_)
+ always_export_symbols=yes
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec=' '
+ archive_cmds_need_lc=yes
+ # This is similar to how AIX traditionally builds it's shared libraries.
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case "$host_os" in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ whole_archive_flag_spec=''
+ link_all_deplibs=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case "$cc_basename" in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ hpux10* | hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ archive_cmds='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
+ ;;
+ *)
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ case "$host_cpu" in
+ hppa*64*)
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_flag_spec_ld='+b $libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ ;;
+ ia64*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ *)
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ link_all_deplibs=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+
+ sco3.2v5*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='${wl}-Bexport'
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z text'
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds='$CC -r -o $output$reload_objs'
+ hardcode_direct=no
+ ;;
+ motorola)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4.2uw2*)
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=no
+ hardcode_runpath_var=yes
+ runpath_var=LD_RUN_PATH
+ ;;
+
+ sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*)
+ no_undefined_flag='${wl}-z ${wl}text'
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv5*)
+ no_undefined_flag=' -z text'
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ hardcode_libdir_flag_spec=
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+echo "${ECHO_T}$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc=no
+ else
+ archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ { echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
+echo "${ECHO_T}$archive_cmds_need_lc" >&6; }
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.01* | freebsdelf3.01*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ *) # from 3.2 on
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case "$host_cpu" in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var" || \
+ test "X$hardcode_automatic" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action" >&5
+echo "${ECHO_T}$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+striplib=
+old_striplib=
+{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+ ;;
+ *)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ esac
+fi
+
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ *)
+ { echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; }
+if test "${ac_cv_func_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_shl_load || defined __stub___shl_load
+choke me
+#endif
+
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6; }
+if test $ac_cv_func_shl_load = yes; then
+ lt_cv_dlopen="shl_load"
+else
+ { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dld_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dld_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; }
+if test $ac_cv_lib_dld_shl_load = yes; then
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+ { echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; }
+if test "${ac_cv_func_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_dlopen || defined __stub___dlopen
+choke me
+#endif
+
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6; }
+if test $ac_cv_func_dlopen = yes; then
+ lt_cv_dlopen="dlopen"
+else
+ { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_svld_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_svld_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; }
+if test $ac_cv_lib_svld_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+ { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dld_dld_link=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dld_dld_link=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; }
+if test $ac_cv_lib_dld_dld_link = yes; then
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 14602 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_unknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6; }
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+ { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 14700 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; }
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+# Report which libraries types will actually be built
+{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; }
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+{ echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6; }
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler \
+ CC \
+ LD \
+ lt_prog_compiler_wl \
+ lt_prog_compiler_pic \
+ lt_prog_compiler_static \
+ lt_prog_compiler_no_builtin_flag \
+ export_dynamic_flag_spec \
+ thread_safe_flag_spec \
+ whole_archive_flag_spec \
+ enable_shared_with_static_runtimes \
+ old_archive_cmds \
+ old_archive_from_new_cmds \
+ predep_objects \
+ postdep_objects \
+ predeps \
+ postdeps \
+ compiler_lib_search_path \
+ archive_cmds \
+ archive_expsym_cmds \
+ postinstall_cmds \
+ postuninstall_cmds \
+ old_archive_from_expsyms_cmds \
+ allow_undefined_flag \
+ no_undefined_flag \
+ export_symbols_cmds \
+ hardcode_libdir_flag_spec \
+ hardcode_libdir_flag_spec_ld \
+ hardcode_libdir_separator \
+ hardcode_automatic \
+ module_cmds \
+ module_expsym_cmds \
+ lt_cv_prog_compiler_c_o \
+ exclude_expsyms \
+ include_expsyms; do
+
+ case $var in
+ old_archive_cmds | \
+ old_archive_from_new_cmds | \
+ archive_cmds | \
+ archive_expsym_cmds | \
+ module_cmds | \
+ module_expsym_cmds | \
+ old_archive_from_expsyms_cmds | \
+ export_symbols_cmds | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="${ofile}T"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ $rm -f "$cfgfile"
+ { echo "$as_me:$LINENO: creating $ofile" >&5
+echo "$as_me: creating $ofile" >&6;}
+
+ cat <<__EOF__ >> "$cfgfile"
+#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# A language-specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# ### END LIBTOOL CONFIG
+
+__EOF__
+
+
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" || \
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+
+# Check whether --with-tags was given.
+if test "${with_tags+set}" = set; then
+ withval=$with_tags; tagnames="$withval"
+fi
+
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+ if test ! -f "${ofile}"; then
+ { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;}
+ fi
+
+ if test -z "$LTCC"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+ if test -z "$LTCC"; then
+ { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5
+echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;}
+ else
+ { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5
+echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;}
+ fi
+ fi
+
+ # Extract list of available tagged configurations in $ofile.
+ # Note that this assumes the entire list is on one line.
+ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for tagname in $tagnames; do
+ IFS="$lt_save_ifs"
+ # Check whether tagname contains only valid characters
+ case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in
+ "") ;;
+ *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5
+echo "$as_me: error: invalid tag name: $tagname" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+ then
+ { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5
+echo "$as_me: error: tag name \"$tagname\" already exists" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ # Update the list of available tags.
+ if test -n "$tagname"; then
+ echo appending configuration tag \"$tagname\" to $ofile
+
+ case $tagname in
+ CXX)
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_automatic_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+# Source file extension for C++ test sources.
+ac_ext=cc
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+ unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+ unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+compiler_CXX=$CC
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+ lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+else
+ lt_prog_compiler_no_builtin_flag_CXX=
+fi
+
+if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+else
+ { echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ { echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
+echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+{ echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+ grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_CXX=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+ld_shlibs_CXX=yes
+case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_CXX=''
+ hardcode_direct_CXX=yes
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.012|aix4.012.*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_CXX=yes
+ else
+ # We have old collect2
+ hardcode_direct_CXX=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_CXX=yes
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ hardcode_libdir_separator_CXX=
+ fi
+ esac
+ shared_flag='-shared'
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_CXX=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_CXX='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_CXX="-z nodefs"
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_CXX=' ${wl}-bernotok'
+ allow_undefined_flag_CXX=' ${wl}-berok'
+ # -bexpall does not export symbols beginning with underscore (_)
+ always_export_symbols_CXX=yes
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_CXX=' '
+ archive_cmds_need_lc_CXX=yes
+ # This is similar to how AIX traditionally builds it's shared libraries.
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ allow_undefined_flag_CXX=unsupported
+ always_export_symbols_CXX=no
+ enable_shared_with_static_runtimes_CXX=yes
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ case "$host_os" in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_direct_CXX=no
+ hardcode_automatic_CXX=yes
+ hardcode_shlibpath_var_CXX=unsupported
+ whole_archive_flag_spec_CXX=''
+ link_all_deplibs_CXX=yes
+
+ if test "$GXX" = yes ; then
+ lt_int_apple_cc_single_mod=no
+ output_verbose_link_cmd='echo'
+ if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+ lt_int_apple_cc_single_mod=yes
+ fi
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ else
+ archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ fi
+ module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case "$cc_basename" in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ ghcx)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ freebsd12*)
+ # C++ shared libraries reported to be fairly broken before switch to ELF
+ ld_shlibs_CXX=no
+ ;;
+ freebsd-elf*)
+ archive_cmds_need_lc_CXX=no
+ ;;
+ freebsd* | kfreebsd*-gnu)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ ld_shlibs_CXX=yes
+ ;;
+ gnu*)
+ ;;
+ hpux9*)
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC)
+ archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ case "$host_cpu" in
+ hppa*64*)
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_flag_spec_ld_CXX='+b $libdir'
+ hardcode_libdir_separator_CXX=:
+ ;;
+ ia64*)
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ ;;
+ *)
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ ;;
+ esac
+ fi
+ case "$host_cpu" in
+ hppa*64*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ ;;
+ ia64*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ *)
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC)
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case "$host_cpu" in
+ ia64*|hppa*64*)
+ archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC)
+ # SGI C++
+ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+ else
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+ fi
+ fi
+ link_all_deplibs_CXX=yes
+ ;;
+ esac
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc)
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ cxx)
+ # Compaq C++
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ esac
+ ;;
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ m88k*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ ld_shlibs_CXX=no
+ ;;
+ openbsd*)
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd='echo'
+ ;;
+ osf3*)
+ case $cc_basename in
+ KCC)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+
+ ;;
+ RCC)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx)
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ osf4* | osf5*)
+ case $cc_basename in
+ KCC)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -o $oldlib $oldobjs'
+ ;;
+ RCC)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx)
+ allow_undefined_flag_CXX=' -expect_unresolved \*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+ archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~
+ $rm $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+ psos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ sco*)
+ archive_cmds_need_lc_CXX=no
+ case $cc_basename in
+ CC)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ lcc)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ no_undefined_flag_CXX=' -zdefs'
+ archive_cmds_CXX='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_shlibpath_var_CXX=no
+ case $host_os in
+ solaris2.0-5 | solaris2.0-5.*) ;;
+ *)
+ # The C++ compiler is used as linker so we must use $wl
+ # flag to pass the commands to the underlying system
+ # linker.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ link_all_deplibs_CXX=yes
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[LR]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx)
+ # Green Hills C++ Compiler
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+ if $CC --version | grep -v '^2\.7' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+ fi
+ ;;
+ esac
+ ;;
+ sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*)
+ archive_cmds_need_lc_CXX=no
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+GCC_CXX="$GXX"
+LD_CXX="$LD"
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+
+cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+EOF
+
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ # The `*' in the case matches for architectures that use `case' in
+ # $output_verbose_cmd can trigger glob expansion during the loop
+ # eval without this substitution.
+ output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`"
+
+ for p in `eval $output_verbose_link_cmd`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" \
+ || test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$compiler_lib_search_path_CXX"; then
+ compiler_lib_search_path_CXX="${prev}${p}"
+ else
+ compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$postdeps_CXX"; then
+ postdeps_CXX="${prev}${p}"
+ else
+ postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$predep_objects_CXX"; then
+ predep_objects_CXX="$p"
+ else
+ predep_objects_CXX="$predep_objects_CXX $p"
+ fi
+ else
+ if test -z "$postdep_objects_CXX"; then
+ postdep_objects_CXX="$p"
+ else
+ postdep_objects_CXX="$postdep_objects_CXX $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$rm -f confest.$objext
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+
+lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ fi
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | os2* | pw32*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_CXX='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ lt_prog_compiler_pic_CXX=
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_CXX=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix4* | aix5*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ else
+ lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68)
+ # Green Hills C++ Compiler
+ # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case "$cc_basename" in
+ xlc*)
+ lt_prog_compiler_pic_CXX='-qnocommon'
+ lt_prog_compiler_wl_CXX='-Wl,'
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++)
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ ghcx)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | kfreebsd*-gnu)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
+ if test "$host_cpu" != ia64; then
+ lt_prog_compiler_pic_CXX='+Z'
+ fi
+ ;;
+ aCC)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC)
+ # KAI C++ Compiler
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ icpc)
+ # Intel C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-static'
+ ;;
+ cxx)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx)
+ lt_prog_compiler_pic_CXX='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC)
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ ;;
+ RCC)
+ # Rational C++ 2.4.1
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ cxx)
+ # Digital/Compaq C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ sco*)
+ case $cc_basename in
+ CC)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ lt_prog_compiler_wl_CXX='-Qoption ld '
+ ;;
+ gcx)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC)
+ # Sun C++ 4.x
+ lt_prog_compiler_pic_CXX='-pic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ lcc)
+ # Lucid
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC)
+ # NonStop-UX NCC 3.20
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ unixware*)
+ ;;
+ vxworks*)
+ ;;
+ *)
+ lt_prog_compiler_can_build_shared_CXX=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_CXX=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:16893: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:16897: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s conftest.err; then
+ lt_prog_compiler_pic_works_CXX=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then
+ case $lt_prog_compiler_pic_CXX in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+ esac
+else
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+case "$host_os" in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_CXX=
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_CXX=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:16953: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:16957: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s out/conftest.err; then
+ lt_cv_prog_compiler_c_o_CXX=yes
+ fi
+ fi
+ chmod u+w .
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix4* | aix5*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ export_symbols_cmds_CXX="$ltdll_cmds"
+ ;;
+ cygwin* | mingw*)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_CXX=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_CXX in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_CXX
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+ allow_undefined_flag_CXX=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_CXX=no
+ else
+ archive_cmds_need_lc_CXX=yes
+ fi
+ allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; }
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.01* | freebsdelf3.01*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ *) # from 3.2 on
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case "$host_cpu" in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" || \
+ test -n "$runpath_var_CXX" || \
+ test "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_CXX" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+ test "$hardcode_minus_L_CXX" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_CXX=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_CXX=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_CXX=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5
+echo "${ECHO_T}$hardcode_action_CXX" >&6; }
+
+if test "$hardcode_action_CXX" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+striplib=
+old_striplib=
+{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+ ;;
+ *)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ esac
+fi
+
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ *)
+ { echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; }
+if test "${ac_cv_func_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_shl_load || defined __stub___shl_load
+choke me
+#endif
+
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6; }
+if test $ac_cv_func_shl_load = yes; then
+ lt_cv_dlopen="shl_load"
+else
+ { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dld_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dld_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; }
+if test $ac_cv_lib_dld_shl_load = yes; then
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+ { echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; }
+if test "${ac_cv_func_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_dlopen || defined __stub___dlopen
+choke me
+#endif
+
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6; }
+if test $ac_cv_func_dlopen = yes; then
+ lt_cv_dlopen="dlopen"
+else
+ { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_svld_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_svld_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; }
+if test $ac_cv_lib_svld_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+ { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dld_dld_link=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dld_dld_link=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; }
+if test $ac_cv_lib_dld_dld_link = yes; then
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 18281 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_unknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6; }
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+ { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 18379 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; }
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_CXX \
+ CC_CXX \
+ LD_CXX \
+ lt_prog_compiler_wl_CXX \
+ lt_prog_compiler_pic_CXX \
+ lt_prog_compiler_static_CXX \
+ lt_prog_compiler_no_builtin_flag_CXX \
+ export_dynamic_flag_spec_CXX \
+ thread_safe_flag_spec_CXX \
+ whole_archive_flag_spec_CXX \
+ enable_shared_with_static_runtimes_CXX \
+ old_archive_cmds_CXX \
+ old_archive_from_new_cmds_CXX \
+ predep_objects_CXX \
+ postdep_objects_CXX \
+ predeps_CXX \
+ postdeps_CXX \
+ compiler_lib_search_path_CXX \
+ archive_cmds_CXX \
+ archive_expsym_cmds_CXX \
+ postinstall_cmds_CXX \
+ postuninstall_cmds_CXX \
+ old_archive_from_expsyms_cmds_CXX \
+ allow_undefined_flag_CXX \
+ no_undefined_flag_CXX \
+ export_symbols_cmds_CXX \
+ hardcode_libdir_flag_spec_CXX \
+ hardcode_libdir_flag_spec_ld_CXX \
+ hardcode_libdir_separator_CXX \
+ hardcode_automatic_CXX \
+ module_cmds_CXX \
+ module_expsym_cmds_CXX \
+ lt_cv_prog_compiler_c_o_CXX \
+ exclude_expsyms_CXX \
+ include_expsyms_CXX; do
+
+ case $var in
+ old_archive_cmds_CXX | \
+ old_archive_from_new_cmds_CXX | \
+ archive_cmds_CXX | \
+ archive_expsym_cmds_CXX | \
+ module_cmds_CXX | \
+ module_expsym_cmds_CXX | \
+ old_archive_from_expsyms_cmds_CXX | \
+ export_symbols_cmds_CXX | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# A language-specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_CXX
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_CXX
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_CXX
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_CXX
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_CXX"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ F77)
+ if test -n "$F77" && test "X$F77" != "Xno"; then
+
+ac_ext=f
+ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
+ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_f77_compiler_gnu
+
+
+archive_cmds_need_lc_F77=no
+allow_undefined_flag_F77=
+always_export_symbols_F77=no
+archive_expsym_cmds_F77=
+export_dynamic_flag_spec_F77=
+hardcode_direct_F77=no
+hardcode_libdir_flag_spec_F77=
+hardcode_libdir_flag_spec_ld_F77=
+hardcode_libdir_separator_F77=
+hardcode_minus_L_F77=no
+hardcode_automatic_F77=no
+module_cmds_F77=
+module_expsym_cmds_F77=
+link_all_deplibs_F77=unknown
+old_archive_cmds_F77=$old_archive_cmds
+no_undefined_flag_F77=
+whole_archive_flag_spec_F77=
+enable_shared_with_static_runtimes_F77=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+objext_F77=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code=" subroutine t\n return\n end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=" program t\n end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+compiler_F77=$CC
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
+
+{ echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+aix4* | aix5*)
+ test "$enable_shared" = yes && enable_static=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; }
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+{ echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6; }
+
+test "$ld_shlibs_F77" = no && can_build_shared=no
+
+GCC_F77="$G77"
+LD_F77="$LD"
+
+lt_prog_compiler_wl_F77=
+lt_prog_compiler_pic_F77=
+lt_prog_compiler_static_F77=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_static_F77='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_F77='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_F77='-fno-common'
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared_F77=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_F77=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_F77='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic_F77='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_F77='-Bstatic'
+ else
+ lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case "$cc_basename" in
+ xlc*)
+ lt_prog_compiler_pic_F77='-qnocommon'
+ lt_prog_compiler_wl_F77='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_F77='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_F77='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static_F77='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ linux*)
+ case $CC in
+ icc* | ecc*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-static'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static_F77='-non_shared'
+ ;;
+
+ sco3.2v5*)
+ lt_prog_compiler_pic_F77='-Kpic'
+ lt_prog_compiler_static_F77='-dn'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl_F77='-Qoption ld '
+ lt_prog_compiler_pic_F77='-PIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ lt_prog_compiler_wl_F77='-Wl,'
+ lt_prog_compiler_pic_F77='-KPIC'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic_F77='-Kconform_pic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ fi
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic_F77='-pic'
+ lt_prog_compiler_static_F77='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared_F77=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_F77"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_F77=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_F77"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:19216: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:19220: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s conftest.err; then
+ lt_prog_compiler_pic_works_F77=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_F77" = xyes; then
+ case $lt_prog_compiler_pic_F77 in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;;
+ esac
+else
+ lt_prog_compiler_pic_F77=
+ lt_prog_compiler_can_build_shared_F77=no
+fi
+
+fi
+case "$host_os" in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_F77=
+ ;;
+ *)
+ lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77"
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_F77=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:19276: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:19280: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s out/conftest.err; then
+ lt_cv_prog_compiler_c_o_F77=yes
+ fi
+ fi
+ chmod u+w .
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+ runpath_var=
+ allow_undefined_flag_F77=
+ enable_shared_with_static_runtimes_F77=no
+ archive_cmds_F77=
+ archive_expsym_cmds_F77=
+ old_archive_From_new_cmds_F77=
+ old_archive_from_expsyms_cmds_F77=
+ export_dynamic_flag_spec_F77=
+ whole_archive_flag_spec_F77=
+ thread_safe_flag_spec_F77=
+ hardcode_libdir_flag_spec_F77=
+ hardcode_libdir_flag_spec_ld_F77=
+ hardcode_libdir_separator_F77=
+ hardcode_direct_F77=no
+ hardcode_minus_L_F77=no
+ hardcode_shlibpath_var_F77=unsupported
+ link_all_deplibs_F77=unknown
+ hardcode_automatic_F77=no
+ module_cmds_F77=
+ module_expsym_cmds_F77=
+ always_export_symbols_F77=no
+ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms_F77=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs_F77=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs_F77=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs_F77=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_F77=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ allow_undefined_flag_F77=unsupported
+ always_export_symbols_F77=no
+ enable_shared_with_static_runtimes_F77=yes
+ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris* | sysv5*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs_F77=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ sunos4*)
+ archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_cmds_F77="$tmp_archive_cmds"
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~
+cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+$echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ else
+ archive_expsym_cmds_F77="$tmp_archive_cmds"
+ fi
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_F77=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs_F77" = yes; then
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_F77='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_F77=
+ fi
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag_F77=unsupported
+ always_export_symbols_F77=yes
+ archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L_F77=yes
+ if test "$GCC" = yes && test -z "$link_static_flag"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct_F77=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_F77=''
+ hardcode_direct_F77=yes
+ hardcode_libdir_separator_F77=':'
+ link_all_deplibs_F77=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.012|aix4.012.*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_F77=yes
+ else
+ # We have old collect2
+ hardcode_direct_F77=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_F77=yes
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_libdir_separator_F77=
+ fi
+ esac
+ shared_flag='-shared'
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_F77=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_F77='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_f77_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_F77="-z nodefs"
+ archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+ program main
+
+ end
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_f77_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_F77=' ${wl}-bernotok'
+ allow_undefined_flag_F77=' ${wl}-berok'
+ # -bexpall does not export symbols beginning with underscore (_)
+ always_export_symbols_F77=yes
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_F77=' '
+ archive_cmds_need_lc_F77=yes
+ # This is similar to how AIX traditionally builds it's shared libraries.
+ archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs_F77=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec_F77=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec_F77=' '
+ allow_undefined_flag_F77=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds_F77='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes_F77=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case "$host_os" in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_F77='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_F77='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_F77='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_F77=no
+ hardcode_direct_F77=no
+ hardcode_automatic_F77=yes
+ hardcode_shlibpath_var_F77=unsupported
+ whole_archive_flag_spec_F77=''
+ link_all_deplibs_F77=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case "$cc_basename" in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_F77=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs_F77=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu)
+ archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_direct_F77=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+ ;;
+
+ hpux10* | hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ archive_cmds_F77='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
+ ;;
+ *)
+ archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ case "$host_cpu" in
+ hppa*64*)
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_flag_spec_ld_F77='+b $libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_direct_F77=no
+ hardcode_shlibpath_var_F77=no
+ ;;
+ ia64*)
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_direct_F77=no
+ hardcode_shlibpath_var_F77=no
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ ;;
+ *)
+ hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_direct_F77=yes
+ export_dynamic_flag_spec_F77='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_F77=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld_F77='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ link_all_deplibs_F77=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ newsos6)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ openbsd*)
+ hardcode_direct_F77=yes
+ hardcode_shlibpath_var_F77=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_F77='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ ;;
+ *)
+ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_minus_L_F77=yes
+ allow_undefined_flag_F77=unsupported
+ archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag_F77=' -expect_unresolved \*'
+ archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_F77=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag_F77=' -expect_unresolved \*'
+ archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec_F77='-rpath $libdir'
+ fi
+ hardcode_libdir_separator_F77=:
+ ;;
+
+ sco3.2v5*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ export_dynamic_flag_spec_F77='${wl}-Bexport'
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ;;
+
+ solaris*)
+ no_undefined_flag_F77=' -z text'
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec_F77='-R$libdir'
+ hardcode_shlibpath_var_F77=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;;
+ esac
+ link_all_deplibs_F77=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=yes
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds_F77='$CC -r -o $output$reload_objs'
+ hardcode_direct_F77=no
+ ;;
+ motorola)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ export_dynamic_flag_spec_F77='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_F77=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs_F77=yes
+ fi
+ ;;
+
+ sysv4.2uw2*)
+ archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_F77=yes
+ hardcode_minus_L_F77=no
+ hardcode_shlibpath_var_F77=no
+ hardcode_runpath_var=yes
+ runpath_var=LD_RUN_PATH
+ ;;
+
+ sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*)
+ no_undefined_flag_F77='${wl}-z ${wl}text'
+ if test "$GCC" = yes; then
+ archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_F77='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ sysv5*)
+ no_undefined_flag_F77=' -z text'
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ hardcode_libdir_flag_spec_F77=
+ hardcode_shlibpath_var_F77=no
+ runpath_var='LD_RUN_PATH'
+ ;;
+
+ uts4*)
+ archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_F77='-L$libdir'
+ hardcode_shlibpath_var_F77=no
+ ;;
+
+ *)
+ ld_shlibs_F77=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5
+echo "${ECHO_T}$ld_shlibs_F77" >&6; }
+test "$ld_shlibs_F77" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_F77" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_F77=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_F77 in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_F77
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_F77
+ allow_undefined_flag_F77=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_F77=no
+ else
+ archive_cmds_need_lc_F77=yes
+ fi
+ allow_undefined_flag_F77=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; }
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.01* | freebsdelf3.01*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ *) # from 3.2 on
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case "$host_cpu" in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_F77=
+if test -n "$hardcode_libdir_flag_spec_F77" || \
+ test -n "$runpath_var_F77" || \
+ test "X$hardcode_automatic_F77" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_F77" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no &&
+ test "$hardcode_minus_L_F77" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_F77=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_F77=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_F77=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5
+echo "${ECHO_T}$hardcode_action_F77" >&6; }
+
+if test "$hardcode_action_F77" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+striplib=
+old_striplib=
+{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+ ;;
+ *)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ esac
+fi
+
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_F77 \
+ CC_F77 \
+ LD_F77 \
+ lt_prog_compiler_wl_F77 \
+ lt_prog_compiler_pic_F77 \
+ lt_prog_compiler_static_F77 \
+ lt_prog_compiler_no_builtin_flag_F77 \
+ export_dynamic_flag_spec_F77 \
+ thread_safe_flag_spec_F77 \
+ whole_archive_flag_spec_F77 \
+ enable_shared_with_static_runtimes_F77 \
+ old_archive_cmds_F77 \
+ old_archive_from_new_cmds_F77 \
+ predep_objects_F77 \
+ postdep_objects_F77 \
+ predeps_F77 \
+ postdeps_F77 \
+ compiler_lib_search_path_F77 \
+ archive_cmds_F77 \
+ archive_expsym_cmds_F77 \
+ postinstall_cmds_F77 \
+ postuninstall_cmds_F77 \
+ old_archive_from_expsyms_cmds_F77 \
+ allow_undefined_flag_F77 \
+ no_undefined_flag_F77 \
+ export_symbols_cmds_F77 \
+ hardcode_libdir_flag_spec_F77 \
+ hardcode_libdir_flag_spec_ld_F77 \
+ hardcode_libdir_separator_F77 \
+ hardcode_automatic_F77 \
+ module_cmds_F77 \
+ module_expsym_cmds_F77 \
+ lt_cv_prog_compiler_c_o_F77 \
+ exclude_expsyms_F77 \
+ include_expsyms_F77; do
+
+ case $var in
+ old_archive_cmds_F77 | \
+ old_archive_from_new_cmds_F77 | \
+ archive_cmds_F77 | \
+ archive_expsym_cmds_F77 | \
+ module_cmds_F77 | \
+ module_expsym_cmds_F77 | \
+ old_archive_from_expsyms_cmds_F77 | \
+ export_symbols_cmds_F77 | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_F77
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# A language-specific compiler.
+CC=$lt_compiler_F77
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_F77
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_F77
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_F77
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_F77
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_F77
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_F77
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_F77
+archive_expsym_cmds=$lt_archive_expsym_cmds_F77
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_F77
+module_expsym_cmds=$lt_module_expsym_cmds_F77
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_F77
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_F77
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_F77
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_F77
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_F77
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_F77
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_F77
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_F77
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_F77
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_F77
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_F77
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_F77
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_F77"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_F77
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_F77
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_F77
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_F77
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ GCJ)
+ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+objext_GCJ=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+compiler_GCJ=$CC
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+archive_cmds_need_lc_GCJ=no
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+
+lt_prog_compiler_no_builtin_flag_GCJ=
+
+if test "$GCC" = yes; then
+ lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin'
+
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:21310: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:21314: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s conftest.err; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+lt_prog_compiler_wl_GCJ=
+lt_prog_compiler_pic_GCJ=
+lt_prog_compiler_static_GCJ=
+
+{ echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_static_GCJ='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_GCJ='-fno-common'
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared_GCJ=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_GCJ=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ lt_prog_compiler_pic_GCJ='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ else
+ lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case "$cc_basename" in
+ xlc*)
+ lt_prog_compiler_pic_GCJ='-qnocommon'
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic_GCJ='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ linux*)
+ case $CC in
+ icc* | ecc*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-static'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static_GCJ='-non_shared'
+ ;;
+
+ sco3.2v5*)
+ lt_prog_compiler_pic_GCJ='-Kpic'
+ lt_prog_compiler_static_GCJ='-dn'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl_GCJ='-Qoption ld '
+ lt_prog_compiler_pic_GCJ='-PIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ lt_prog_compiler_wl_GCJ='-Wl,'
+ lt_prog_compiler_pic_GCJ='-KPIC'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic_GCJ='-Kconform_pic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ fi
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic_GCJ='-pic'
+ lt_prog_compiler_static_GCJ='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared_GCJ=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; }
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_GCJ"; then
+
+{ echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; }
+if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_prog_compiler_pic_works_GCJ=no
+ ac_outfile=conftest.$ac_objext
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_GCJ"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:21553: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:21557: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s conftest.err; then
+ lt_prog_compiler_pic_works_GCJ=yes
+ fi
+ fi
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; }
+
+if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then
+ case $lt_prog_compiler_pic_GCJ in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;;
+ esac
+else
+ lt_prog_compiler_pic_GCJ=
+ lt_prog_compiler_can_build_shared_GCJ=no
+fi
+
+fi
+case "$host_os" in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_GCJ=
+ ;;
+ *)
+ lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ"
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ lt_cv_prog_compiler_c_o_GCJ=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:21613: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:21617: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s out/conftest.err; then
+ lt_cv_prog_compiler_c_o_GCJ=yes
+ fi
+ fi
+ chmod u+w .
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; }
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+{ echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+
+ runpath_var=
+ allow_undefined_flag_GCJ=
+ enable_shared_with_static_runtimes_GCJ=no
+ archive_cmds_GCJ=
+ archive_expsym_cmds_GCJ=
+ old_archive_From_new_cmds_GCJ=
+ old_archive_from_expsyms_cmds_GCJ=
+ export_dynamic_flag_spec_GCJ=
+ whole_archive_flag_spec_GCJ=
+ thread_safe_flag_spec_GCJ=
+ hardcode_libdir_flag_spec_GCJ=
+ hardcode_libdir_flag_spec_ld_GCJ=
+ hardcode_libdir_separator_GCJ=
+ hardcode_direct_GCJ=no
+ hardcode_minus_L_GCJ=no
+ hardcode_shlibpath_var_GCJ=unsupported
+ link_all_deplibs_GCJ=unknown
+ hardcode_automatic_GCJ=no
+ module_cmds_GCJ=
+ module_expsym_cmds_GCJ=
+ always_export_symbols_GCJ=no
+ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms_GCJ=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs_GCJ=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs_GCJ=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ ld_shlibs_GCJ=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_GCJ=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ allow_undefined_flag_GCJ=unsupported
+ always_export_symbols_GCJ=no
+ enable_shared_with_static_runtimes_GCJ=yes
+ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris* | sysv5*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs_GCJ=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ sunos4*)
+ archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_cmds_GCJ="$tmp_archive_cmds"
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+ if test $supports_anon_versioning = yes; then
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~
+cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+$echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ else
+ archive_expsym_cmds_GCJ="$tmp_archive_cmds"
+ fi
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs_GCJ=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs_GCJ" = yes; then
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_GCJ=
+ fi
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag_GCJ=unsupported
+ always_export_symbols_GCJ=yes
+ archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L_GCJ=yes
+ if test "$GCC" = yes && test -z "$link_static_flag"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct_GCJ=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_GCJ=''
+ hardcode_direct_GCJ=yes
+ hardcode_libdir_separator_GCJ=':'
+ link_all_deplibs_GCJ=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.012|aix4.012.*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct_GCJ=yes
+ else
+ # We have old collect2
+ hardcode_direct_GCJ=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_GCJ=yes
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_libdir_separator_GCJ=
+ fi
+ esac
+ shared_flag='-shared'
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols_GCJ=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_GCJ='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_GCJ="-z nodefs"
+ archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_GCJ=' ${wl}-bernotok'
+ allow_undefined_flag_GCJ=' ${wl}-berok'
+ # -bexpall does not export symbols beginning with underscore (_)
+ always_export_symbols_GCJ=yes
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_GCJ=' '
+ archive_cmds_need_lc_GCJ=yes
+ # This is similar to how AIX traditionally builds it's shared libraries.
+ archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs_GCJ=no
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec_GCJ=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec_GCJ=' '
+ allow_undefined_flag_GCJ=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_From_new_cmds_GCJ='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes_GCJ=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case "$host_os" in
+ rhapsody* | darwin1.[012])
+ allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[012])
+ allow_undefined_flag_GCJ='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ allow_undefined_flag_GCJ='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ archive_cmds_need_lc_GCJ=no
+ hardcode_direct_GCJ=no
+ hardcode_automatic_GCJ=yes
+ hardcode_shlibpath_var_GCJ=unsupported
+ whole_archive_flag_spec_GCJ=''
+ link_all_deplibs_GCJ=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case "$cc_basename" in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ ld_shlibs_GCJ=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ freebsd1*)
+ ld_shlibs_GCJ=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu)
+ archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_direct_GCJ=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ ;;
+
+ hpux10* | hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ archive_cmds_GCJ='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
+ ;;
+ *)
+ archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ case "$host_cpu" in
+ hppa*64*)
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_flag_spec_ld_GCJ='+b $libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_direct_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+ ia64*)
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_direct_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ ;;
+ *)
+ hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_direct_GCJ=yes
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L_GCJ=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ link_all_deplibs_GCJ=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ newsos6)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ openbsd*)
+ hardcode_direct_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_GCJ='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ ;;
+ *)
+ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_minus_L_GCJ=yes
+ allow_undefined_flag_GCJ=unsupported
+ archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag_GCJ=' -expect_unresolved \*'
+ archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_GCJ=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag_GCJ=' -expect_unresolved \*'
+ archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec_GCJ='-rpath $libdir'
+ fi
+ hardcode_libdir_separator_GCJ=:
+ ;;
+
+ sco3.2v5*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ export_dynamic_flag_spec_GCJ='${wl}-Bexport'
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ;;
+
+ solaris*)
+ no_undefined_flag_GCJ=' -z text'
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ hardcode_libdir_flag_spec_GCJ='-R$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;;
+ esac
+ link_all_deplibs_GCJ=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=yes
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds_GCJ='$CC -r -o $output$reload_objs'
+ hardcode_direct_GCJ=no
+ ;;
+ motorola)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ export_dynamic_flag_spec_GCJ='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var_GCJ=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs_GCJ=yes
+ fi
+ ;;
+
+ sysv4.2uw2*)
+ archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct_GCJ=yes
+ hardcode_minus_L_GCJ=no
+ hardcode_shlibpath_var_GCJ=no
+ hardcode_runpath_var=yes
+ runpath_var=LD_RUN_PATH
+ ;;
+
+ sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*)
+ no_undefined_flag_GCJ='${wl}-z ${wl}text'
+ if test "$GCC" = yes; then
+ archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds_GCJ='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ sysv5*)
+ no_undefined_flag_GCJ=' -z text'
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ hardcode_libdir_flag_spec_GCJ=
+ hardcode_shlibpath_var_GCJ=no
+ runpath_var='LD_RUN_PATH'
+ ;;
+
+ uts4*)
+ archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec_GCJ='-L$libdir'
+ hardcode_shlibpath_var_GCJ=no
+ ;;
+
+ *)
+ ld_shlibs_GCJ=no
+ ;;
+ esac
+ fi
+
+{ echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5
+echo "${ECHO_T}$ld_shlibs_GCJ" >&6; }
+test "$ld_shlibs_GCJ" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_GCJ" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_GCJ=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_GCJ in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_GCJ
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ
+ allow_undefined_flag_GCJ=
+ if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5
+ (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ then
+ archive_cmds_need_lc_GCJ=no
+ else
+ archive_cmds_need_lc_GCJ=yes
+ fi
+ allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ { echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; }
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.01* | freebsdelf3.01*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ *) # from 3.2 on
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case "$host_cpu" in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`$SED -e 's/:,\t/ /g;s/=^=*$//;s/=^= * / /g' /etc/ld.so.conf | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+{ echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+hardcode_action_GCJ=
+if test -n "$hardcode_libdir_flag_spec_GCJ" || \
+ test -n "$runpath_var_GCJ" || \
+ test "X$hardcode_automatic_GCJ" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct_GCJ" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no &&
+ test "$hardcode_minus_L_GCJ" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_GCJ=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_GCJ=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_GCJ=unsupported
+fi
+{ echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5
+echo "${ECHO_T}$hardcode_action_GCJ" >&6; }
+
+if test "$hardcode_action_GCJ" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+striplib=
+old_striplib=
+{ echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+ ;;
+ *)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ esac
+fi
+
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ *)
+ { echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; }
+if test "${ac_cv_func_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define shl_load to an innocuous variant, in case <limits.h> declares shl_load.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define shl_load innocuous_shl_load
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef shl_load
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_shl_load || defined __stub___shl_load
+choke me
+#endif
+
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6; }
+if test $ac_cv_func_shl_load = yes; then
+ lt_cv_dlopen="shl_load"
+else
+ { echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_shl_load+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dld_shl_load=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dld_shl_load=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; }
+if test $ac_cv_lib_dld_shl_load = yes; then
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
+else
+ { echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; }
+if test "${ac_cv_func_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define dlopen to an innocuous variant, in case <limits.h> declares dlopen.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define dlopen innocuous_dlopen
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef dlopen
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_dlopen || defined __stub___dlopen
+choke me
+#endif
+
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6; }
+if test $ac_cv_func_dlopen = yes; then
+ lt_cv_dlopen="dlopen"
+else
+ { echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dl_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dl_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dl_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+if test $ac_cv_lib_dl_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ { echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_svld_dlopen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_svld_dlopen=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_svld_dlopen=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; }
+if test $ac_cv_lib_svld_dlopen = yes; then
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+ { echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dld_dld_link+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dld_dld_link=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dld_dld_link=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; }
+if test $ac_cv_lib_dld_dld_link = yes; then
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ { echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 23761 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_unknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6; }
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+ { echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; }
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+#line 23859 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+
+ exit (status);
+}
+EOF
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; }
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_GCJ \
+ CC_GCJ \
+ LD_GCJ \
+ lt_prog_compiler_wl_GCJ \
+ lt_prog_compiler_pic_GCJ \
+ lt_prog_compiler_static_GCJ \
+ lt_prog_compiler_no_builtin_flag_GCJ \
+ export_dynamic_flag_spec_GCJ \
+ thread_safe_flag_spec_GCJ \
+ whole_archive_flag_spec_GCJ \
+ enable_shared_with_static_runtimes_GCJ \
+ old_archive_cmds_GCJ \
+ old_archive_from_new_cmds_GCJ \
+ predep_objects_GCJ \
+ postdep_objects_GCJ \
+ predeps_GCJ \
+ postdeps_GCJ \
+ compiler_lib_search_path_GCJ \
+ archive_cmds_GCJ \
+ archive_expsym_cmds_GCJ \
+ postinstall_cmds_GCJ \
+ postuninstall_cmds_GCJ \
+ old_archive_from_expsyms_cmds_GCJ \
+ allow_undefined_flag_GCJ \
+ no_undefined_flag_GCJ \
+ export_symbols_cmds_GCJ \
+ hardcode_libdir_flag_spec_GCJ \
+ hardcode_libdir_flag_spec_ld_GCJ \
+ hardcode_libdir_separator_GCJ \
+ hardcode_automatic_GCJ \
+ module_cmds_GCJ \
+ module_expsym_cmds_GCJ \
+ lt_cv_prog_compiler_c_o_GCJ \
+ exclude_expsyms_GCJ \
+ include_expsyms_GCJ; do
+
+ case $var in
+ old_archive_cmds_GCJ | \
+ old_archive_from_new_cmds_GCJ | \
+ archive_cmds_GCJ | \
+ archive_expsym_cmds_GCJ | \
+ module_cmds_GCJ | \
+ module_expsym_cmds_GCJ | \
+ old_archive_from_expsyms_cmds_GCJ | \
+ export_symbols_cmds_GCJ | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_GCJ
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# A language-specific compiler.
+CC=$lt_compiler_GCJ
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_GCJ
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_GCJ
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_GCJ
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_GCJ
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_GCJ
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_GCJ
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_GCJ
+archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_GCJ
+module_expsym_cmds=$lt_module_expsym_cmds_GCJ
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_GCJ
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_GCJ
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_GCJ
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_GCJ
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_GCJ
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_GCJ
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_GCJ
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_GCJ
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_GCJ
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_GCJ
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_GCJ"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_GCJ
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_GCJ
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_GCJ
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_GCJ
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ else
+ tagname=""
+ fi
+ ;;
+
+ RC)
+
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+objext_RC=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+compiler_RC=$CC
+lt_cv_prog_compiler_c_o_RC=yes
+
+# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ compiler_RC \
+ CC_RC \
+ LD_RC \
+ lt_prog_compiler_wl_RC \
+ lt_prog_compiler_pic_RC \
+ lt_prog_compiler_static_RC \
+ lt_prog_compiler_no_builtin_flag_RC \
+ export_dynamic_flag_spec_RC \
+ thread_safe_flag_spec_RC \
+ whole_archive_flag_spec_RC \
+ enable_shared_with_static_runtimes_RC \
+ old_archive_cmds_RC \
+ old_archive_from_new_cmds_RC \
+ predep_objects_RC \
+ postdep_objects_RC \
+ predeps_RC \
+ postdeps_RC \
+ compiler_lib_search_path_RC \
+ archive_cmds_RC \
+ archive_expsym_cmds_RC \
+ postinstall_cmds_RC \
+ postuninstall_cmds_RC \
+ old_archive_from_expsyms_cmds_RC \
+ allow_undefined_flag_RC \
+ no_undefined_flag_RC \
+ export_symbols_cmds_RC \
+ hardcode_libdir_flag_spec_RC \
+ hardcode_libdir_flag_spec_ld_RC \
+ hardcode_libdir_separator_RC \
+ hardcode_automatic_RC \
+ module_cmds_RC \
+ module_expsym_cmds_RC \
+ lt_cv_prog_compiler_c_o_RC \
+ exclude_expsyms_RC \
+ include_expsyms_RC; do
+
+ case $var in
+ old_archive_cmds_RC | \
+ old_archive_from_new_cmds_RC | \
+ archive_cmds_RC | \
+ archive_expsym_cmds_RC | \
+ module_cmds_RC | \
+ module_expsym_cmds_RC | \
+ old_archive_from_expsyms_cmds_RC | \
+ export_symbols_cmds_RC | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\$0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+cfgfile="$ofile"
+
+ cat <<__EOF__ >> "$cfgfile"
+# ### BEGIN LIBTOOL TAG CONFIG: $tagname
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_RC
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# A language-specific compiler.
+CC=$lt_compiler_RC
+
+# Is the compiler the GNU C compiler?
+with_gcc=$GCC_RC
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_LD_RC
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_RC
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_RC
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_RC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_old_archive_cmds_RC
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_archive_cmds_RC
+archive_expsym_cmds=$lt_archive_expsym_cmds_RC
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_module_cmds_RC
+module_expsym_cmds=$lt_module_expsym_cmds_RC
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_predep_objects_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_postdep_objects_RC
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_predeps_RC
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_postdeps_RC
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_RC
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_RC
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_RC
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_RC
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct_RC
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L_RC
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_RC
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$hardcode_automatic_RC
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_RC
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path_RC"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols_RC
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_RC
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_RC
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_RC
+
+# ### END LIBTOOL TAG CONFIG: $tagname
+
+__EOF__
+
+
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC="$lt_save_CC"
+
+ ;;
+
+ *)
+ { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5
+echo "$as_me: error: Unsupported tag name: $tagname" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ esac
+
+ # Append the new tag name to the list of available tags.
+ if test -n "$tagname" ; then
+ available_tags="$available_tags $tagname"
+ fi
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ # Now substitute the updated list of available tags.
+ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+ mv "${ofile}T" "$ofile"
+ chmod +x "$ofile"
+ else
+ rm -f "${ofile}T"
+ { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5
+echo "$as_me: error: unable to update list of available tagged configurations." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+fi
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Prevent multiple expansion
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ O=lo
+ A=la
+ LIBTOOL_MKDEP_SED='s;\.o;\.lo;'
+ LIBTOOL_MODE_COMPILE='--mode=compile'
+ LIBTOOL_MODE_INSTALL='--mode=install'
+ LIBTOOL_MODE_LINK='--mode=link'
+ case "$host" in
+ *) LIBTOOL_ALLOW_UNDEFINED= ;;
+ esac
+ case "$host" in
+ *-ibm-aix*) LIBTOOL_IN_MAIN="-Wl,-bI:T_testlist.imp" ;;
+ *) LIBTOOL_IN_MAIN= ;;
+ esac;
+ ;;
+ *)
+ O=o
+ A=a
+ LIBTOOL=
+
+ LIBTOOL_MKDEP_SED=
+ LIBTOOL_MODE_COMPILE=
+ LIBTOOL_MODE_INSTALL=
+ LIBTOOL_MODE_LINK=
+ LIBTOOL_ALLOW_UNDEFINED=
+ LIBTOOL_IN_MAIN=
+ ;;
+esac
+
+#
+# File name extension for static archive files, for those few places
+# where they are treated differently from dynamic ones.
+#
+SA=a
+
+
+
+
+
+
+
+
+
+
+
+#
+# Here begins a very long section to determine the system's networking
+# capabilities. The order of the tests is signficant.
+#
+
+#
+# IPv6
+#
+# Check whether --enable-ipv6 was given.
+if test "${enable_ipv6+set}" = set; then
+ enableval=$enable_ipv6;
+fi
+
+
+case "$enable_ipv6" in
+ yes|''|autodetect)
+ cat >>confdefs.h <<\_ACEOF
+#define WANT_IPV6 1
+_ACEOF
+
+ ;;
+ no)
+ ;;
+esac
+
+#
+# We do the IPv6 compilation checking after libtool so that we can put
+# the right suffix on the files.
+#
+{ echo "$as_me:$LINENO: checking for IPv6 structures" >&5
+echo $ECHO_N "checking for IPv6 structures... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+int
+main ()
+{
+struct sockaddr_in6 sin6; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ found_ipv6=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ found_ipv6=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+#
+# See whether IPv6 support is provided via a Kame add-on.
+# This is done before other IPv6 linking tests to LIBS is properly set.
+#
+{ echo "$as_me:$LINENO: checking for Kame IPv6 support" >&5
+echo $ECHO_N "checking for Kame IPv6 support... $ECHO_C" >&6; }
+
+# Check whether --with-kame was given.
+if test "${with_kame+set}" = set; then
+ withval=$with_kame; use_kame="$withval"
+else
+ use_kame="no"
+fi
+
+
+case "$use_kame" in
+ no)
+ ;;
+ yes)
+ kame_path=/usr/local/v6
+ ;;
+ *)
+ kame_path="$use_kame"
+ ;;
+esac
+
+case "$use_kame" in
+ no)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ *)
+ if test -f $kame_path/lib/libinet6.a; then
+ { echo "$as_me:$LINENO: result: $kame_path/lib/libinet6.a" >&5
+echo "${ECHO_T}$kame_path/lib/libinet6.a" >&6; }
+ LIBS="-L$kame_path/lib -linet6 $LIBS"
+ else
+ { { echo "$as_me:$LINENO: error: $kame_path/lib/libinet6.a not found.
+
+Please choose the proper path with the following command:
+
+ configure --with-kame=PATH
+" >&5
+echo "$as_me: error: $kame_path/lib/libinet6.a not found.
+
+Please choose the proper path with the following command:
+
+ configure --with-kame=PATH
+" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ ;;
+esac
+
+#
+# Whether netinet6/in6.h is needed has to be defined in isc/platform.h.
+# Including it on Kame-using platforms is very bad, though, because
+# Kame uses #error against direct inclusion. So include it on only
+# the platform that is otherwise broken without it -- BSD/OS 4.0 through 4.1.
+# This is done before the in6_pktinfo check because that's what
+# netinet6/in6.h is needed for.
+#
+
+case "$host" in
+*-bsdi4.[01]*)
+ ISC_PLATFORM_NEEDNETINET6IN6H="#define ISC_PLATFORM_NEEDNETINET6IN6H 1"
+ LWRES_PLATFORM_NEEDNETINET6IN6H="#define LWRES_PLATFORM_NEEDNETINET6IN6H 1"
+ isc_netinet6in6_hack="#include <netinet6/in6.h>"
+ ;;
+*)
+ ISC_PLATFORM_NEEDNETINET6IN6H="#undef ISC_PLATFORM_NEEDNETINET6IN6H"
+ LWRES_PLATFORM_NEEDNETINET6IN6H="#undef LWRES_PLATFORM_NEEDNETINET6IN6H"
+ isc_netinet6in6_hack=""
+ ;;
+esac
+
+
+#
+# This is similar to the netinet6/in6.h issue.
+#
+case "$host" in
+*-sco-sysv*uw*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ # UnixWare
+ ISC_PLATFORM_NEEDNETINETIN6H="#define ISC_PLATFORM_NEEDNETINETIN6H 1"
+ LWRES_PLATFORM_NEEDNETINETIN6H="#define LWRES_PLATFORM_NEEDNETINETIN6H 1"
+ ISC_PLATFORM_FIXIN6ISADDR="#define ISC_PLATFORM_FIXIN6ISADDR 1"
+ isc_netinetin6_hack="#include <netinet/in6.h>"
+ ;;
+*)
+ ISC_PLATFORM_NEEDNETINETIN6H="#undef ISC_PLATFORM_NEEDNETINETIN6H"
+ LWRES_PLATFORM_NEEDNETINETIN6H="#undef LWRES_PLATFORM_NEEDNETINETIN6H"
+ ISC_PLATFORM_FIXIN6ISADDR="#undef ISC_PLATFORM_FIXIN6ISADDR"
+ isc_netinetin6_hack=""
+ ;;
+esac
+
+#
+# Now delve deeper into the suitability of the IPv6 support.
+#
+case "$found_ipv6" in
+ yes)
+ ISC_PLATFORM_HAVEIPV6="#define ISC_PLATFORM_HAVEIPV6 1"
+ LWRES_PLATFORM_HAVEIPV6="#define LWRES_PLATFORM_HAVEIPV6 1"
+
+ { echo "$as_me:$LINENO: checking for in6_addr" >&5
+echo $ECHO_N "checking for in6_addr... $ECHO_C" >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+$isc_netinetin6_hack
+$isc_netinet6in6_hack
+
+int
+main ()
+{
+struct in6_addr in6; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_HAVEINADDR6="#undef ISC_PLATFORM_HAVEINADDR6"
+ LWRES_PLATFORM_HAVEINADDR6="#undef LWRES_PLATFORM_HAVEINADDR6"
+ isc_in_addr6_hack=""
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_HAVEINADDR6="#define ISC_PLATFORM_HAVEINADDR6 1"
+ LWRES_PLATFORM_HAVEINADDR6="#define LWRES_PLATFORM_HAVEINADDR6 1"
+ isc_in_addr6_hack="#define in6_addr in_addr6"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ { echo "$as_me:$LINENO: checking for in6addr_any" >&5
+echo $ECHO_N "checking for in6addr_any... $ECHO_C" >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+$isc_netinetin6_hack
+$isc_netinet6in6_hack
+$isc_in_addr6_hack
+
+int
+main ()
+{
+struct in6_addr in6; in6 = in6addr_any; return (in6.s6_addr[0]);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_NEEDIN6ADDRANY="#undef ISC_PLATFORM_NEEDIN6ADDRANY"
+ LWRES_PLATFORM_NEEDIN6ADDRANY="#undef LWRES_PLATFORM_NEEDIN6ADDRANY"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_NEEDIN6ADDRANY="#define ISC_PLATFORM_NEEDIN6ADDRANY 1"
+ LWRES_PLATFORM_NEEDIN6ADDRANY="#define LWRES_PLATFORM_NEEDIN6ADDRANY 1"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+
+ { echo "$as_me:$LINENO: checking for in6addr_loopback" >&5
+echo $ECHO_N "checking for in6addr_loopback... $ECHO_C" >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+$isc_netinetin6_hack
+$isc_netinet6in6_hack
+$isc_in_addr6_hack
+
+int
+main ()
+{
+struct in6_addr in6; in6 = in6addr_loopback; return (in6.s6_addr[0]);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_NEEDIN6ADDRLOOPBACK="#undef ISC_PLATFORM_NEEDIN6ADDRLOOPBACK"
+ LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK="#undef LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_NEEDIN6ADDRLOOPBACK="#define ISC_PLATFORM_NEEDIN6ADDRLOOPBACK 1"
+ LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK="#define LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK 1"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+
+ { echo "$as_me:$LINENO: checking for sin6_scope_id in struct sockaddr_in6" >&5
+echo $ECHO_N "checking for sin6_scope_id in struct sockaddr_in6... $ECHO_C" >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+$isc_netinetin6_hack
+$isc_netinet6in6_hack
+
+int
+main ()
+{
+struct sockaddr_in6 xyzzy; xyzzy.sin6_scope_id = 0; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_HAVESCOPEID="#define ISC_PLATFORM_HAVESCOPEID 1"
+ result="#define LWRES_HAVE_SIN6_SCOPE_ID 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_HAVESCOPEID="#undef ISC_PLATFORM_HAVESCOPEID"
+ result="#undef LWRES_HAVE_SIN6_SCOPE_ID"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ LWRES_HAVE_SIN6_SCOPE_ID="$result"
+
+ { echo "$as_me:$LINENO: checking for in6_pktinfo" >&5
+echo $ECHO_N "checking for in6_pktinfo... $ECHO_C" >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+$isc_netinetin6_hack
+$isc_netinet6in6_hack
+
+int
+main ()
+{
+struct in6_pktinfo xyzzy; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_HAVEIN6PKTINFO="#define ISC_PLATFORM_HAVEIN6PKTINFO 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no -- disabling runtime ipv6 support" >&5
+echo "${ECHO_T}no -- disabling runtime ipv6 support" >&6; }
+ ISC_PLATFORM_HAVEIN6PKTINFO="#undef ISC_PLATFORM_HAVEIN6PKTINFO"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+ no)
+ ISC_PLATFORM_HAVEIPV6="#undef ISC_PLATFORM_HAVEIPV6"
+ LWRES_PLATFORM_HAVEIPV6="#undef LWRES_PLATFORM_HAVEIPV6"
+ ISC_PLATFORM_NEEDIN6ADDRANY="#undef ISC_PLATFORM_NEEDIN6ADDRANY"
+ LWRES_PLATFORM_NEEDIN6ADDRANY="#undef LWRES_PLATFORM_NEEDIN6ADDRANY"
+ ISC_PLATFORM_HAVEIN6PKTINFO="#undef ISC_PLATFORM_HAVEIN6PKTINFO"
+ LWRES_HAVE_SIN6_SCOPE_ID="#define LWRES_HAVE_SIN6_SCOPE_ID 1"
+ ISC_PLATFORM_HAVESCOPEID="#define ISC_PLATFORM_HAVESCOPEID 1"
+ ISC_IPV6_H="ipv6.h"
+ ISC_IPV6_O="ipv6.$O"
+ ISC_ISCIPV6_O="unix/ipv6.$O"
+ ISC_IPV6_C="ipv6.c"
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ echo "$as_me:$LINENO: checking for struct if_laddrreq" >&5
+echo $ECHO_N "checking for struct if_laddrreq... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <net/if6.h>
+
+int
+main ()
+{
+ struct if_laddrreq a;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_HAVEIF_LADDRREQ="#define ISC_PLATFORM_HAVEIF_LADDRREQ 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_HAVEIF_LADDRREQ="#undef ISC_PLATFORM_HAVEIF_LADDRREQ"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+
+
+{ echo "$as_me:$LINENO: checking for struct if_laddrconf" >&5
+echo $ECHO_N "checking for struct if_laddrconf... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <net/if6.h>
+
+int
+main ()
+{
+ struct if_laddrconf a;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_HAVEIF_LADDRCONF="#define ISC_PLATFORM_HAVEIF_LADDRCONF 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_HAVEIF_LADDRCONF="#undef ISC_PLATFORM_HAVEIF_LADDRCONF"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+
+
+#
+# Check for network functions that are often missing. We do this
+# after the libtool checking, so we can put the right suffix on
+# the files. It also needs to come after checking for a Kame add-on,
+# which provides some (all?) of the desired functions.
+#
+
+{ echo "$as_me:$LINENO: checking for inet_ntop with IPv6 support" >&5
+echo $ECHO_N "checking for inet_ntop with IPv6 support... $ECHO_C" >&6; }
+if test "$cross_compiling" = yes; then
+ { echo "$as_me:$LINENO: result: assuming inet_ntop needed" >&5
+echo "${ECHO_T}assuming inet_ntop needed" >&6; }
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
+ ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+main() {
+char a[16],b[64]; return(inet_ntop(AF_INET6, a, b, sizeof(b)) == (char*)0);}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_NEEDNTOP="#undef ISC_PLATFORM_NEEDNTOP"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
+ ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+
+# On NetBSD 1.4.2 and maybe others, inet_pton() incorrectly accepts
+# addresses with less than four octets, like "1.2.3". Also leading
+# zeros should also be rejected.
+
+{ echo "$as_me:$LINENO: checking for working inet_pton with IPv6 support" >&5
+echo $ECHO_N "checking for working inet_pton with IPv6 support... $ECHO_C" >&6; }
+if test "$cross_compiling" = yes; then
+ { echo "$as_me:$LINENO: result: assuming target platform has working inet_pton" >&5
+echo "${ECHO_T}assuming target platform has working inet_pton" >&6; }
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+main() { char a[16]; return (inet_pton(AF_INET, "1.2.3", a) == 1 ? 1 :
+ inet_pton(AF_INET, "1.2.3.04", a) == 1 ? 1 :
+ (inet_pton(AF_INET6, "::1.2.3.4", a) != 1)); }
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c"
+ ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1"
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking for inet_aton" >&5
+echo $ECHO_N "checking for inet_aton... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+int
+main ()
+{
+struct in_addr in; inet_aton(0, &in); return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_NEEDATON="#undef ISC_PLATFORM_NEEDATON"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_aton.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_aton.c"
+ ISC_PLATFORM_NEEDATON="#define ISC_PLATFORM_NEEDATON 1"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+
+
+
+
+
+#
+# Look for a 4.4BSD-style sa_len member in struct sockaddr.
+#
+case "$host" in
+ *-dec-osf*)
+ # Turn on 4.4BSD style sa_len support.
+ cat >>confdefs.h <<\_ACEOF
+#define _SOCKADDR_LEN 1
+_ACEOF
+
+ ;;
+esac
+
+{ echo "$as_me:$LINENO: checking for sa_len in struct sockaddr" >&5
+echo $ECHO_N "checking for sa_len in struct sockaddr... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+int
+main ()
+{
+struct sockaddr sa; sa.sa_len = 0; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_HAVESALEN="#define ISC_PLATFORM_HAVESALEN 1"
+ LWRES_PLATFORM_HAVESALEN="#define LWRES_PLATFORM_HAVESALEN 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_HAVESALEN="#undef ISC_PLATFORM_HAVESALEN"
+ LWRES_PLATFORM_HAVESALEN="#undef LWRES_PLATFORM_HAVESALEN"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+
+#
+# Look for a 4.4BSD or 4.3BSD struct msghdr
+#
+{ echo "$as_me:$LINENO: checking for struct msghdr flavor" >&5
+echo $ECHO_N "checking for struct msghdr flavor... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+int
+main ()
+{
+struct msghdr msg; msg.msg_flags = 0; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: 4.4BSD" >&5
+echo "${ECHO_T}4.4BSD" >&6; }
+ ISC_PLATFORM_MSGHDRFLAVOR="#define ISC_NET_BSD44MSGHDR 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: 4.3BSD" >&5
+echo "${ECHO_T}4.3BSD" >&6; }
+ ISC_PLATFORM_MSGHDRFLAVOR="#define ISC_NET_BSD43MSGHDR 1"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+#
+# Look for in_port_t.
+#
+{ echo "$as_me:$LINENO: checking for type in_port_t" >&5
+echo $ECHO_N "checking for type in_port_t... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+int
+main ()
+{
+in_port_t port = 25; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_NEEDPORTT="#undef ISC_PLATFORM_NEEDPORTT"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_PLATFORM_NEEDPORTT="#define ISC_PLATFORM_NEEDPORTT 1"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+#
+# Check for addrinfo
+#
+{ echo "$as_me:$LINENO: checking for struct addrinfo" >&5
+echo $ECHO_N "checking for struct addrinfo... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <netdb.h>
+int
+main ()
+{
+struct addrinfo a; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_LWRES_NEEDADDRINFO="#undef ISC_LWRES_NEEDADDRINFO"
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_ADDRINFO 1
+_ACEOF
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_LWRES_NEEDADDRINFO="#define ISC_LWRES_NEEDADDRINFO 1"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+#
+# Check for rrsetinfo
+#
+{ echo "$as_me:$LINENO: checking for struct rrsetinfo" >&5
+echo $ECHO_N "checking for struct rrsetinfo... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <netdb.h>
+int
+main ()
+{
+struct rrsetinfo r; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_LWRES_NEEDRRSETINFO="#undef ISC_LWRES_NEEDRRSETINFO"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_LWRES_NEEDRRSETINFO="#define ISC_LWRES_NEEDRRSETINFO 1"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+{ echo "$as_me:$LINENO: checking for int sethostent" >&5
+echo $ECHO_N "checking for int sethostent... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <netdb.h>
+int
+main ()
+{
+int i = sethostent(0); return(0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_LWRES_SETHOSTENTINT="#define ISC_LWRES_SETHOSTENTINT 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_LWRES_SETHOSTENTINT="#undef ISC_LWRES_SETHOSTENTINT"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+{ echo "$as_me:$LINENO: checking for int endhostent" >&5
+echo $ECHO_N "checking for int endhostent... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <netdb.h>
+int
+main ()
+{
+int i = endhostent(); return(0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_LWRES_ENDHOSTENTINT="#define ISC_LWRES_ENDHOSTENTINT 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_LWRES_ENDHOSTENTINT="#undef ISC_LWRES_ENDHOSTENTINT"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+{ echo "$as_me:$LINENO: checking for getnetbyaddr(in_addr_t, ...)" >&5
+echo $ECHO_N "checking for getnetbyaddr(in_addr_t, ...)... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <netdb.h>
+struct netent *getnetbyaddr(in_addr_t, int);
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_LWRES_GETNETBYADDRINADDR="#define ISC_LWRES_GETNETBYADDRINADDR 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_LWRES_GETNETBYADDRINADDR="#undef ISC_LWRES_GETNETBYADDRINADDR"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+{ echo "$as_me:$LINENO: checking for int setnetent" >&5
+echo $ECHO_N "checking for int setnetent... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <netdb.h>
+int
+main ()
+{
+int i = setnetent(0); return(0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_LWRES_SETNETENTINT="#define ISC_LWRES_SETNETENTINT 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_LWRES_SETNETENTINT="#undef ISC_LWRES_SETNETENTINT"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+{ echo "$as_me:$LINENO: checking for int endnetent" >&5
+echo $ECHO_N "checking for int endnetent... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <netdb.h>
+int
+main ()
+{
+int i = endnetent(); return(0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_LWRES_ENDNETENTINT="#define ISC_LWRES_ENDNETENTINT 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_LWRES_ENDNETENTINT="#undef ISC_LWRES_ENDNETENTINT"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+{ echo "$as_me:$LINENO: checking for gethostbyaddr(const void *, size_t, ...)" >&5
+echo $ECHO_N "checking for gethostbyaddr(const void *, size_t, ...)... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <netdb.h>
+struct hostent *gethostbyaddr(const void *, size_t, int);
+int
+main ()
+{
+return(0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_LWRES_GETHOSTBYADDRVOID="#define ISC_LWRES_GETHOSTBYADDRVOID 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_LWRES_GETHOSTBYADDRVOID="#undef ISC_LWRES_GETHOSTBYADDRVOID"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+{ echo "$as_me:$LINENO: checking for h_errno in netdb.h" >&5
+echo $ECHO_N "checking for h_errno in netdb.h... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <netdb.h>
+int
+main ()
+{
+h_errno = 1; return(0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_LWRES_NEEDHERRNO="#undef ISC_LWRES_NEEDHERRNO"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ISC_LWRES_NEEDHERRNO="#define ISC_LWRES_NEEDHERRNO 1"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+{ echo "$as_me:$LINENO: checking for getipnodebyname" >&5
+echo $ECHO_N "checking for getipnodebyname... $ECHO_C" >&6; }
+if test "${ac_cv_func_getipnodebyname+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getipnodebyname to an innocuous variant, in case <limits.h> declares getipnodebyname.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getipnodebyname innocuous_getipnodebyname
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getipnodebyname (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getipnodebyname
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getipnodebyname ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_getipnodebyname || defined __stub___getipnodebyname
+choke me
+#endif
+
+int
+main ()
+{
+return getipnodebyname ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_getipnodebyname=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_getipnodebyname=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_getipnodebyname" >&5
+echo "${ECHO_T}$ac_cv_func_getipnodebyname" >&6; }
+if test $ac_cv_func_getipnodebyname = yes; then
+ ISC_LWRES_GETIPNODEPROTO="#undef ISC_LWRES_GETIPNODEPROTO"
+else
+ ISC_LWRES_GETIPNODEPROTO="#define ISC_LWRES_GETIPNODEPROTO 1"
+fi
+
+{ echo "$as_me:$LINENO: checking for getnameinfo" >&5
+echo $ECHO_N "checking for getnameinfo... $ECHO_C" >&6; }
+if test "${ac_cv_func_getnameinfo+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getnameinfo to an innocuous variant, in case <limits.h> declares getnameinfo.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getnameinfo innocuous_getnameinfo
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getnameinfo (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getnameinfo
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getnameinfo ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_getnameinfo || defined __stub___getnameinfo
+choke me
+#endif
+
+int
+main ()
+{
+return getnameinfo ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_getnameinfo=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_getnameinfo=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_getnameinfo" >&5
+echo "${ECHO_T}$ac_cv_func_getnameinfo" >&6; }
+if test $ac_cv_func_getnameinfo = yes; then
+ ISC_LWRES_GETNAMEINFOPROTO="#undef ISC_LWRES_GETNAMEINFOPROTO"
+else
+ ISC_LWRES_GETNAMEINFOPROTO="#define ISC_LWRES_GETNAMEINFOPROTO 1"
+fi
+
+{ echo "$as_me:$LINENO: checking for getaddrinfo" >&5
+echo $ECHO_N "checking for getaddrinfo... $ECHO_C" >&6; }
+if test "${ac_cv_func_getaddrinfo+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getaddrinfo to an innocuous variant, in case <limits.h> declares getaddrinfo.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getaddrinfo innocuous_getaddrinfo
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getaddrinfo (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getaddrinfo
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getaddrinfo ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_getaddrinfo || defined __stub___getaddrinfo
+choke me
+#endif
+
+int
+main ()
+{
+return getaddrinfo ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_getaddrinfo=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_getaddrinfo=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_getaddrinfo" >&5
+echo "${ECHO_T}$ac_cv_func_getaddrinfo" >&6; }
+if test $ac_cv_func_getaddrinfo = yes; then
+ ISC_LWRES_GETADDRINFOPROTO="#undef ISC_LWRES_GETADDRINFOPROTO"
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETADDRINFO 1
+_ACEOF
+
+else
+ ISC_LWRES_GETADDRINFOPROTO="#define ISC_LWRES_GETADDRINFOPROTO 1"
+fi
+
+{ echo "$as_me:$LINENO: checking for gai_strerror" >&5
+echo $ECHO_N "checking for gai_strerror... $ECHO_C" >&6; }
+if test "${ac_cv_func_gai_strerror+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define gai_strerror to an innocuous variant, in case <limits.h> declares gai_strerror.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define gai_strerror innocuous_gai_strerror
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char gai_strerror (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef gai_strerror
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gai_strerror ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_gai_strerror || defined __stub___gai_strerror
+choke me
+#endif
+
+int
+main ()
+{
+return gai_strerror ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_gai_strerror=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_gai_strerror=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_gai_strerror" >&5
+echo "${ECHO_T}$ac_cv_func_gai_strerror" >&6; }
+if test $ac_cv_func_gai_strerror = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_GAISTRERROR 1
+_ACEOF
+
+fi
+
+
+
+
+
+# Check whether --enable-getifaddrs was given.
+if test "${enable_getifaddrs+set}" = set; then
+ enableval=$enable_getifaddrs; want_getifaddrs="$enableval"
+else
+ want_getifaddrs="yes"
+fi
+
+
+#
+# This interface iteration code for getifaddrs() will fall back to using
+# /proc/net/if_inet6 if getifaddrs() in glibc doesn't return any IPv6
+# addresses.
+#
+case $want_getifaddrs in
+glibc)
+{ echo "$as_me:$LINENO: WARNING: \"--enable-getifaddrs=glibc is no longer required\"" >&5
+echo "$as_me: WARNING: \"--enable-getifaddrs=glibc is no longer required\"" >&2;}
+{ echo "$as_me:$LINENO: checking for getifaddrs" >&5
+echo $ECHO_N "checking for getifaddrs... $ECHO_C" >&6; }
+if test "${ac_cv_func_getifaddrs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getifaddrs to an innocuous variant, in case <limits.h> declares getifaddrs.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getifaddrs innocuous_getifaddrs
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getifaddrs (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getifaddrs
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getifaddrs ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_getifaddrs || defined __stub___getifaddrs
+choke me
+#endif
+
+int
+main ()
+{
+return getifaddrs ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_getifaddrs=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_getifaddrs=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_getifaddrs" >&5
+echo "${ECHO_T}$ac_cv_func_getifaddrs" >&6; }
+if test $ac_cv_func_getifaddrs = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETIFADDRS 1
+_ACEOF
+
+fi
+
+;;
+yes)
+{ echo "$as_me:$LINENO: checking for getifaddrs" >&5
+echo $ECHO_N "checking for getifaddrs... $ECHO_C" >&6; }
+if test "${ac_cv_func_getifaddrs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getifaddrs to an innocuous variant, in case <limits.h> declares getifaddrs.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getifaddrs innocuous_getifaddrs
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getifaddrs (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getifaddrs
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getifaddrs ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_getifaddrs || defined __stub___getifaddrs
+choke me
+#endif
+
+int
+main ()
+{
+return getifaddrs ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_getifaddrs=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_getifaddrs=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_getifaddrs" >&5
+echo "${ECHO_T}$ac_cv_func_getifaddrs" >&6; }
+if test $ac_cv_func_getifaddrs = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETIFADDRS 1
+_ACEOF
+
+fi
+
+;;
+no)
+;;
+esac
+
+#
+# Look for a sysctl call to get the list of network interfaces.
+#
+case $ac_cv_header_sys_sysctl_h in
+yes)
+{ echo "$as_me:$LINENO: checking for interface list sysctl" >&5
+echo $ECHO_N "checking for interface list sysctl... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#ifdef NET_RT_IFLIST
+found_rt_iflist
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "found_rt_iflist" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_IFLIST_SYSCTL 1
+_ACEOF
+
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+rm -f conftest*
+
+;;
+esac
+
+#
+# Check for some other useful functions that are not ever-present.
+#
+
+# We test for strsep() using AC_TRY_LINK instead of AC_CHECK_FUNC
+# because AIX 4.3.3 with patches for bos.adt.include to version 4.3.3.77
+# reportedly defines strsep() without declaring it in <string.h> when
+# -D_LINUX_SOURCE_COMPAT is not defined [RT #2190], and
+# AC_CHECK_FUNC() incorrectly succeeds because it declares
+# the function itself.
+{ echo "$as_me:$LINENO: checking for correctly declared strsep()" >&5
+echo $ECHO_N "checking for correctly declared strsep()... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+int
+main ()
+{
+char *sp; char *foo = strsep(&sp, ".");
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }; ISC_PLATFORM_NEEDSTRSEP="#undef ISC_PLATFORM_NEEDSTRSEP"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }; ISC_PLATFORM_NEEDSTRSEP="#define ISC_PLATFORM_NEEDSTRSEP 1"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+
+
+{ echo "$as_me:$LINENO: checking for memmove" >&5
+echo $ECHO_N "checking for memmove... $ECHO_C" >&6; }
+if test "${ac_cv_func_memmove+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define memmove to an innocuous variant, in case <limits.h> declares memmove.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define memmove innocuous_memmove
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char memmove (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef memmove
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char memmove ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_memmove || defined __stub___memmove
+choke me
+#endif
+
+int
+main ()
+{
+return memmove ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_memmove=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_memmove=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_memmove" >&5
+echo "${ECHO_T}$ac_cv_func_memmove" >&6; }
+if test $ac_cv_func_memmove = yes; then
+ ISC_PLATFORM_NEEDMEMMOVE="#undef ISC_PLATFORM_NEEDMEMMOVE"
+else
+ ISC_PLATFORM_NEEDMEMMOVE="#define ISC_PLATFORM_NEEDMEMMOVE 1"
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking for strtoul" >&5
+echo $ECHO_N "checking for strtoul... $ECHO_C" >&6; }
+if test "${ac_cv_func_strtoul+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strtoul to an innocuous variant, in case <limits.h> declares strtoul.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strtoul innocuous_strtoul
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strtoul (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strtoul
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strtoul ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_strtoul || defined __stub___strtoul
+choke me
+#endif
+
+int
+main ()
+{
+return strtoul ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_strtoul=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_strtoul=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_strtoul" >&5
+echo "${ECHO_T}$ac_cv_func_strtoul" >&6; }
+if test $ac_cv_func_strtoul = yes; then
+ ISC_PLATFORM_NEEDSTRTOUL="#undef ISC_PLATFORM_NEEDSTRTOUL"
+ LWRES_PLATFORM_NEEDSTRTOUL="#undef LWRES_PLATFORM_NEEDSTRTOUL"
+ GENRANDOMLIB=""
+else
+ ISC_PLATFORM_NEEDSTRTOUL="#define ISC_PLATFORM_NEEDSTRTOUL 1"
+ LWRES_PLATFORM_NEEDSTRTOUL="#define LWRES_PLATFORM_NEEDSTRTOUL 1"
+ GENRANDOMLIB='${ISCLIBS}'
+fi
+
+
+
+
+
+{ echo "$as_me:$LINENO: checking for strlcpy" >&5
+echo $ECHO_N "checking for strlcpy... $ECHO_C" >&6; }
+if test "${ac_cv_func_strlcpy+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strlcpy to an innocuous variant, in case <limits.h> declares strlcpy.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strlcpy innocuous_strlcpy
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strlcpy (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strlcpy
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strlcpy ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_strlcpy || defined __stub___strlcpy
+choke me
+#endif
+
+int
+main ()
+{
+return strlcpy ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_strlcpy=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_strlcpy=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_strlcpy" >&5
+echo "${ECHO_T}$ac_cv_func_strlcpy" >&6; }
+if test $ac_cv_func_strlcpy = yes; then
+ ISC_PLATFORM_NEEDSTRLCPY="#undef ISC_PLATFORM_NEEDSTRLCPY"
+else
+ ISC_PLATFORM_NEEDSTRLCPY="#define ISC_PLATFORM_NEEDSTRLCPY 1"
+fi
+
+
+
+{ echo "$as_me:$LINENO: checking for strlcat" >&5
+echo $ECHO_N "checking for strlcat... $ECHO_C" >&6; }
+if test "${ac_cv_func_strlcat+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strlcat to an innocuous variant, in case <limits.h> declares strlcat.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strlcat innocuous_strlcat
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strlcat (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strlcat
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strlcat ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_strlcat || defined __stub___strlcat
+choke me
+#endif
+
+int
+main ()
+{
+return strlcat ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_strlcat=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_strlcat=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_strlcat" >&5
+echo "${ECHO_T}$ac_cv_func_strlcat" >&6; }
+if test $ac_cv_func_strlcat = yes; then
+ ISC_PLATFORM_NEEDSTRLCAT="#undef ISC_PLATFORM_NEEDSTRLCAT"
+else
+ ISC_PLATFORM_NEEDSTRLCAT="#define ISC_PLATFORM_NEEDSTRLCAT 1"
+fi
+
+
+
+ISC_PRINT_OBJS=
+ISC_PRINT_SRCS=
+{ echo "$as_me:$LINENO: checking sprintf" >&5
+echo $ECHO_N "checking sprintf... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <stdio.h>
+
+int
+main ()
+{
+ char buf[2]; return(*sprintf(buf,"x"));
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+
+ISC_PRINT_OBJS="print.$O"
+ISC_PRINT_SRCS="print.c"
+ISC_PLATFORM_NEEDSPRINTF="#define ISC_PLATFORM_NEEDSPRINTF"
+LWRES_PLATFORM_NEEDSPRINTF="#define LWRES_PLATFORM_NEEDSPRINTF"
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ISC_PLATFORM_NEEDSPRINTF="#undef ISC_PLATFORM_NEEDSPRINTF"
+ LWRES_PLATFORM_NEEDSPRINTF="#undef LWRES_PLATFORM_NEEDSPRINTF"
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+
+{ echo "$as_me:$LINENO: checking for vsnprintf" >&5
+echo $ECHO_N "checking for vsnprintf... $ECHO_C" >&6; }
+if test "${ac_cv_func_vsnprintf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define vsnprintf to an innocuous variant, in case <limits.h> declares vsnprintf.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define vsnprintf innocuous_vsnprintf
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vsnprintf (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef vsnprintf
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char vsnprintf ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_vsnprintf || defined __stub___vsnprintf
+choke me
+#endif
+
+int
+main ()
+{
+return vsnprintf ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_vsnprintf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_vsnprintf=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_vsnprintf" >&5
+echo "${ECHO_T}$ac_cv_func_vsnprintf" >&6; }
+if test $ac_cv_func_vsnprintf = yes; then
+ ISC_PLATFORM_NEEDVSNPRINTF="#undef ISC_PLATFORM_NEEDVSNPRINTF"
+ LWRES_PLATFORM_NEEDVSNPRINTF="#undef LWRES_PLATFORM_NEEDVSNPRINTF"
+else
+ ISC_PRINT_OBJS="print.$O"
+ ISC_PRINT_SRCS="print.c"
+ ISC_PLATFORM_NEEDVSNPRINTF="#define ISC_PLATFORM_NEEDVSNPRINTF 1"
+ LWRES_PLATFORM_NEEDVSNPRINTF="#define LWRES_PLATFORM_NEEDVSNPRINTF 1"
+fi
+
+
+
+ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS $ISC_PRINT_OBJS"
+ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS $ISC_PRINT_SRCS"
+
+{ echo "$as_me:$LINENO: checking for strerror" >&5
+echo $ECHO_N "checking for strerror... $ECHO_C" >&6; }
+if test "${ac_cv_func_strerror+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define strerror to an innocuous variant, in case <limits.h> declares strerror.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define strerror innocuous_strerror
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strerror (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef strerror
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char strerror ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_strerror || defined __stub___strerror
+choke me
+#endif
+
+int
+main ()
+{
+return strerror ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_strerror=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_strerror=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_strerror" >&5
+echo "${ECHO_T}$ac_cv_func_strerror" >&6; }
+if test $ac_cv_func_strerror = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRERROR 1
+_ACEOF
+
+fi
+
+
+
+
+
+#
+# Use our own SPNEGO implementation?
+#
+# Check whether --enable-isc-spnego was given.
+if test "${enable_isc_spnego+set}" = set; then
+ enableval=$enable_isc_spnego;
+fi
+
+
+if test -n "$USE_GSSAPI"
+then
+ case "$enable_isc_spnego" in
+ yes|'')
+ USE_ISC_SPNEGO='-DUSE_ISC_SPNEGO'
+ DST_EXTRA_OBJS="$DST_EXTRA_OBJS spnego.$O"
+ DST_EXTRA_SRCS="$DST_EXTRA_SRCS spnego.c"
+ { echo "$as_me:$LINENO: result: using SPNEGO from lib/dns" >&5
+echo "${ECHO_T}using SPNEGO from lib/dns" >&6; }
+ ;;
+ no)
+ { echo "$as_me:$LINENO: result: using SPNEGO from GSSAPI library" >&5
+echo "${ECHO_T}using SPNEGO from GSSAPI library" >&6; }
+ ;;
+ esac
+fi
+
+
+
+
+
+
+# Determine the printf format characters to use when printing
+# values of type isc_int64_t. This will normally be "ll", but where
+# the compiler treats "long long" as a alias for "long" and printf
+# doesn't know about "long long" use "l". Hopefully the sprintf
+# will produce a inconsistant result in the later case. If the compiler
+# fails due to seeing "%lld" we fall back to "l".
+#
+# Digital Unix 4.0 (gcc?) (long long) is 64 bits as is its long. It uses
+# %ld even for (long long)/
+#
+# Win32 uses "%I64d", but that's defined elsewhere since we don't use
+# configure on Win32.
+#
+{ echo "$as_me:$LINENO: checking printf format modifier for 64-bit integers" >&5
+echo $ECHO_N "checking printf format modifier for 64-bit integers... $ECHO_C" >&6; }
+if test "$cross_compiling" = yes; then
+ { echo "$as_me:$LINENO: result: assuming target platform uses ll" >&5
+echo "${ECHO_T}assuming target platform uses ll" >&6; }
+ ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "ll"'
+ LWRES_PLATFORM_QUADFORMAT='#define LWRES_PLATFORM_QUADFORMAT "ll"'
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <stdio.h>
+main() {
+ long long int j = 0;
+ char buf[100];
+ buf[0] = 0;
+ sprintf(buf, "%lld", j);
+ exit((sizeof(long long int) != sizeof(long int))? 0 :
+ (strcmp(buf, "0") != 0));
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ { echo "$as_me:$LINENO: result: ll" >&5
+echo "${ECHO_T}ll" >&6; }
+ ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "ll"'
+ LWRES_PLATFORM_QUADFORMAT='#define LWRES_PLATFORM_QUADFORMAT "ll"'
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ echo "$as_me:$LINENO: result: l" >&5
+echo "${ECHO_T}l" >&6; }
+ ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "l"'
+ LWRES_PLATFORM_QUADFORMAT='#define LWRES_PLATFORM_QUADFORMAT "l"'
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+
+
+#
+# Security Stuff
+#
+{ echo "$as_me:$LINENO: checking for chroot" >&5
+echo $ECHO_N "checking for chroot... $ECHO_C" >&6; }
+if test "${ac_cv_func_chroot+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define chroot to an innocuous variant, in case <limits.h> declares chroot.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define chroot innocuous_chroot
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char chroot (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef chroot
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char chroot ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_chroot || defined __stub___chroot
+choke me
+#endif
+
+int
+main ()
+{
+return chroot ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_chroot=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_chroot=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_chroot" >&5
+echo "${ECHO_T}$ac_cv_func_chroot" >&6; }
+if test $ac_cv_func_chroot = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_CHROOT 1
+_ACEOF
+
+fi
+
+# Check whether --enable-linux-caps was given.
+if test "${enable_linux_caps+set}" = set; then
+ enableval=$enable_linux_caps;
+fi
+
+case "$enable_linux_caps" in
+ yes|'')
+
+
+for ac_header in linux/capability.h sys/capability.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+{ echo "$as_me:$LINENO: checking for cap_set_proc in -lcap" >&5
+echo $ECHO_N "checking for cap_set_proc in -lcap... $ECHO_C" >&6; }
+if test "${ac_cv_lib_cap_cap_set_proc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcap $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char cap_set_proc ();
+int
+main ()
+{
+return cap_set_proc ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_cap_cap_set_proc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_cap_cap_set_proc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_cap_cap_set_proc" >&5
+echo "${ECHO_T}$ac_cv_lib_cap_cap_set_proc" >&6; }
+if test $ac_cv_lib_cap_cap_set_proc = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCAP 1
+_ACEOF
+
+ LIBS="-lcap $LIBS"
+
+fi
+
+ ;;
+ no)
+ ;;
+esac
+
+for ac_header in sys/prctl.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in sys/un.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ ISC_PLATFORM_HAVESYSUNH="#define ISC_PLATFORM_HAVESYSUNH 1"
+
+else
+ ISC_PLATFORM_HAVESYSUNH="#undef ISC_PLATFORM_HAVESYSUNH"
+
+fi
+
+done
+
+
+
+case "$host" in
+*-solaris*)
+
+cat >>confdefs.h <<\_ACEOF
+#define NEED_SECURE_DIRECTORY 1
+_ACEOF
+
+ ;;
+*-sunos*)
+
+cat >>confdefs.h <<\_ACEOF
+#define NEED_SECURE_DIRECTORY 1
+_ACEOF
+
+ ;;
+esac
+
+#
+# Time Zone Stuff
+#
+{ echo "$as_me:$LINENO: checking for tzset" >&5
+echo $ECHO_N "checking for tzset... $ECHO_C" >&6; }
+if test "${ac_cv_func_tzset+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define tzset to an innocuous variant, in case <limits.h> declares tzset.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define tzset innocuous_tzset
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char tzset (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef tzset
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char tzset ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_tzset || defined __stub___tzset
+choke me
+#endif
+
+int
+main ()
+{
+return tzset ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_tzset=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_tzset=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_tzset" >&5
+echo "${ECHO_T}$ac_cv_func_tzset" >&6; }
+if test $ac_cv_func_tzset = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_TZSET 1
+_ACEOF
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for optarg decarartion" >&5
+echo $ECHO_N "checking for optarg decarartion... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <unistd.h>
+
+int
+main ()
+{
+optarg = 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+GEN_NEED_OPTARG="-DNEED_OPTARG=1"
+
+cat >>confdefs.h <<\_ACEOF
+#define NEED_OPTARG 1
+_ACEOF
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+#
+# BSD/OS, and perhaps some others, don't define rlim_t.
+#
+{ echo "$as_me:$LINENO: checking for type rlim_t" >&5
+echo $ECHO_N "checking for type rlim_t... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+int
+main ()
+{
+rlim_t rl = 19671212; return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE rlim_t"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+
+{ echo "$as_me:$LINENO: checking type of rlim_cur" >&5
+echo $ECHO_N "checking type of rlim_cur... $ECHO_C" >&6; }
+if test "$cross_compiling" = yes; then
+
+ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long long int"
+{ echo "$as_me:$LINENO: result: cannot determine type of rlim_cur when cross compiling - assuming long long int" >&5
+echo "${ECHO_T}cannot determine type of rlim_cur when cross compiling - assuming long long int" >&6; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(int)));}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ { echo "$as_me:$LINENO: result: int" >&5
+echo "${ECHO_T}int" >&6; }
+ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE int"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+
+if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: this cannot happen" >&5
+echo "$as_me: error: this cannot happen" >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(long int)));}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ { echo "$as_me:$LINENO: result: long int" >&5
+echo "${ECHO_T}long int" >&6; }
+ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long int"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+
+if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: this cannot happen" >&5
+echo "$as_me: error: this cannot happen" >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+main() { struct rlimit r; exit((!sizeof(r.rlim_cur) == sizeof(long long int)));}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ { echo "$as_me:$LINENO: result: long long int" >&5
+echo "${ECHO_T}long long int" >&6; }
+ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long long int"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: unable to determine sizeof rlim_cur" >&5
+echo "$as_me: error: unable to determine sizeof rlim_cur" >&2;}
+ { (exit 1); exit 1; }; }
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+#
+# Older HP-UX doesn't have gettune
+#
+case "$host" in
+ *-hp-hpux*)
+
+for ac_header in sys/dyntune.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ ;;
+ *)
+ ;;
+esac
+
+
+#
+# Compaq TruCluster requires more code for handling cluster IP aliases
+#
+case "$host" in
+ *-dec-osf*)
+ { echo "$as_me:$LINENO: checking for clua_getaliasaddress in -lclua" >&5
+echo $ECHO_N "checking for clua_getaliasaddress in -lclua... $ECHO_C" >&6; }
+if test "${ac_cv_lib_clua_clua_getaliasaddress+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lclua $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clua_getaliasaddress ();
+int
+main ()
+{
+return clua_getaliasaddress ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_clua_clua_getaliasaddress=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_clua_clua_getaliasaddress=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_clua_clua_getaliasaddress" >&5
+echo "${ECHO_T}$ac_cv_lib_clua_clua_getaliasaddress" >&6; }
+if test $ac_cv_lib_clua_clua_getaliasaddress = yes; then
+ LIBS="-lclua $LIBS"
+fi
+
+ { echo "$as_me:$LINENO: checking for clua_getaliasaddress" >&5
+echo $ECHO_N "checking for clua_getaliasaddress... $ECHO_C" >&6; }
+if test "${ac_cv_func_clua_getaliasaddress+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define clua_getaliasaddress to an innocuous variant, in case <limits.h> declares clua_getaliasaddress.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define clua_getaliasaddress innocuous_clua_getaliasaddress
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char clua_getaliasaddress (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef clua_getaliasaddress
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clua_getaliasaddress ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_clua_getaliasaddress || defined __stub___clua_getaliasaddress
+choke me
+#endif
+
+int
+main ()
+{
+return clua_getaliasaddress ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_clua_getaliasaddress=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_clua_getaliasaddress=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_clua_getaliasaddress" >&5
+echo "${ECHO_T}$ac_cv_func_clua_getaliasaddress" >&6; }
+if test $ac_cv_func_clua_getaliasaddress = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_TRUCLUSTER 1
+_ACEOF
+
+fi
+
+ ;;
+ *)
+ ;;
+esac
+
+#
+# Some hosts need msg_namelen to match the size of the socket structure.
+# Some hosts don't set msg_namelen appropriately on return from recvmsg().
+#
+case $host in
+*os2*|*hp-mpeix*)
+
+cat >>confdefs.h <<\_ACEOF
+#define BROKEN_RECVMSG 1
+_ACEOF
+
+ ;;
+esac
+
+#
+# Microsoft has their own way of handling shared libraries that requires
+# additional qualifiers on extern variables. Unix systems don't need it.
+#
+
+ISC_PLATFORM_USEDECLSPEC="#undef ISC_PLATFORM_USEDECLSPEC"
+
+LWRES_PLATFORM_USEDECLSPEC="#undef LWRES_PLATFORM_USEDECLSPEC"
+
+#
+# Random remaining OS-specific issues involving compiler warnings.
+# XXXDCL print messages to indicate some compensation is being done?
+#
+
+ISC_PLATFORM_BRACEPTHREADONCEINIT="#undef ISC_PLATFORM_BRACEPTHREADONCEINIT"
+
+case "$host" in
+ *-aix5.[123].*)
+ hack_shutup_pthreadonceinit=yes
+ ;;
+ *-bsdi3.1*)
+ hack_shutup_sputaux=yes
+ ;;
+ *-bsdi4.0*)
+ hack_shutup_sigwait=yes
+ hack_shutup_sputaux=yes
+ ;;
+ *-bsdi4.[12]*)
+ hack_shutup_stdargcast=yes
+ ;;
+ *-solaris2.[89])
+ hack_shutup_pthreadonceinit=yes
+ ;;
+ *-solaris2.1[0-9])
+ hack_shutup_pthreadonceinit=yes
+ ;;
+esac
+
+case "$hack_shutup_pthreadonceinit" in
+ yes)
+ #
+ # Shut up PTHREAD_ONCE_INIT unbraced initializer warnings.
+ #
+ ISC_PLATFORM_BRACEPTHREADONCEINIT="#define ISC_PLATFORM_BRACEPTHREADONCEINIT 1"
+ ;;
+esac
+
+case "$hack_shutup_sigwait" in
+ yes)
+ #
+ # Shut up a -Wmissing-prototypes warning for sigwait().
+ #
+ cat >>confdefs.h <<\_ACEOF
+#define SHUTUP_SIGWAIT 1
+_ACEOF
+
+ ;;
+esac
+
+case "$hack_shutup_sputaux" in
+ yes)
+ #
+ # Shut up a -Wmissing-prototypes warning from <stdio.h>.
+ #
+ cat >>confdefs.h <<\_ACEOF
+#define SHUTUP_SPUTAUX 1
+_ACEOF
+
+ ;;
+esac
+
+case "$hack_shutup_stdargcast" in
+ yes)
+ #
+ # Shut up a -Wcast-qual warning from va_start().
+ #
+ cat >>confdefs.h <<\_ACEOF
+#define SHUTUP_STDARG_CAST 1
+_ACEOF
+
+ ;;
+esac
+
+
+for ac_header in strings.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ ISC_PLATFORM_HAVESTRINGSH="#define ISC_PLATFORM_HAVESTRINGSH 1"
+
+else
+ ISC_PLATFORM_HAVESTRINGSH="#undef ISC_PLATFORM_HAVESTRINGSH"
+
+fi
+
+done
+
+
+
+#
+# Check for if_nametoindex() for IPv6 scoped addresses support
+#
+{ echo "$as_me:$LINENO: checking for if_nametoindex" >&5
+echo $ECHO_N "checking for if_nametoindex... $ECHO_C" >&6; }
+if test "${ac_cv_func_if_nametoindex+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define if_nametoindex to an innocuous variant, in case <limits.h> declares if_nametoindex.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define if_nametoindex innocuous_if_nametoindex
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char if_nametoindex (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef if_nametoindex
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char if_nametoindex ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_if_nametoindex || defined __stub___if_nametoindex
+choke me
+#endif
+
+int
+main ()
+{
+return if_nametoindex ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_if_nametoindex=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_if_nametoindex=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_if_nametoindex" >&5
+echo "${ECHO_T}$ac_cv_func_if_nametoindex" >&6; }
+if test $ac_cv_func_if_nametoindex = yes; then
+ ac_cv_have_if_nametoindex=yes
+else
+ ac_cv_have_if_nametoindex=no
+fi
+
+case $ac_cv_have_if_nametoindex in
+no)
+ case "$host" in
+ *-hp-hpux*)
+ { echo "$as_me:$LINENO: checking for if_nametoindex in -lipv6" >&5
+echo $ECHO_N "checking for if_nametoindex in -lipv6... $ECHO_C" >&6; }
+if test "${ac_cv_lib_ipv6_if_nametoindex+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lipv6 $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char if_nametoindex ();
+int
+main ()
+{
+return if_nametoindex ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_ipv6_if_nametoindex=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_ipv6_if_nametoindex=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_ipv6_if_nametoindex" >&5
+echo "${ECHO_T}$ac_cv_lib_ipv6_if_nametoindex" >&6; }
+if test $ac_cv_lib_ipv6_if_nametoindex = yes; then
+ ac_cv_have_if_nametoindex=yes
+ LIBS="-lipv6 $LIBS"
+fi
+
+ ;;
+ esac
+esac
+case $ac_cv_have_if_nametoindex in
+yes)
+ ISC_PLATFORM_HAVEIFNAMETOINDEX="#define ISC_PLATFORM_HAVEIFNAMETOINDEX 1"
+ ;;
+*)
+ ISC_PLATFORM_HAVEIFNAMETOINDEX="#undef ISC_PLATFORM_HAVEIFNAMETOINDEX"
+ ;;
+esac
+
+
+#
+# Machine architecture dependent features
+#
+# Check whether --enable-atomic was given.
+if test "${enable_atomic+set}" = set; then
+ enableval=$enable_atomic; enable_atomic="$enableval"
+else
+ enable_atomic="autodetect"
+fi
+
+case "$enable_atomic" in
+ yes|''|autodetect)
+ use_atomic=yes
+ ;;
+ no)
+ use_atomic=no
+ arch=noatomic
+ ;;
+esac
+
+ISC_PLATFORM_USEOSFASM="#undef ISC_PLATFORM_USEOSFASM"
+if test "$use_atomic" = "yes"; then
+ { echo "$as_me:$LINENO: checking architecture type for atomic operations" >&5
+echo $ECHO_N "checking architecture type for atomic operations... $ECHO_C" >&6; }
+ have_atomic=yes # set default
+ case "$host" in
+ i[3456]86-*)
+ # XXX: some old x86 architectures actually do not support
+ # (some of) these operations. Do we need stricter checks?
+if test "$cross_compiling" = yes; then
+ arch=x86_32
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+main() {
+ exit((sizeof(void *) == 8) ? 0 : 1);
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ arch=x86_64
+ have_xaddq=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+arch=x86_32
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+ ;;
+ x86_64-*)
+ have_xaddq=yes
+ arch=x86_64
+ ;;
+ alpha*-*)
+ arch=alpha
+ ;;
+ powerpc-*)
+ arch=powerpc
+ ;;
+ mips-*|mipsel-*|mips64-*|mips64el-*)
+ arch=mips
+ ;;
+ ia64-*)
+ arch=ia64
+ ;;
+ *)
+ have_atomic=no
+ arch=noatomic
+ ;;
+ esac
+ { echo "$as_me:$LINENO: result: $arch" >&5
+echo "${ECHO_T}$arch" >&6; }
+fi
+
+if test "$have_atomic" = "yes"; then
+ { echo "$as_me:$LINENO: checking compiler support for inline assembly code" >&5
+echo $ECHO_N "checking compiler support for inline assembly code... $ECHO_C" >&6; }
+
+ compiler=generic
+ # Check whether the compiler supports the assembly syntax we provide.
+ if test "X$GCC" = "Xyes"; then
+ # GCC's ASM extension always works
+ compiler=gcc
+ if test $arch = "x86_64"; then
+ # We can share the same code for gcc with x86_32
+ arch=x86_32
+ fi
+ if test $arch = "powerpc"; then
+ #
+ # The MacOS (and maybe others) uses "r0" for register
+ # zero. Under linux/ibm it is "0" for register 0.
+ # Probe to see if we have a MacOS style assembler.
+ #
+ { echo "$as_me:$LINENO: checking Checking for MacOS style assembler syntax" >&5
+echo $ECHO_N "checking Checking for MacOS style assembler syntax... $ECHO_C" >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ __asm__ volatile ("li r0, 0x0\n"::);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ compiler="mac"
+ ISC_PLATFORM_USEMACASM="#define ISC_PLATFORM_USEMACASM 1"
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ else
+ case "$host" in
+ alpha*-dec-osf*)
+ # Tru64 compiler has its own syntax for inline
+ # assembly.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+#ifndef __DECC
+#error "unexpected compiler"
+#endif
+ return (0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ compiler=osf
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+ powerpc-ibm-aix*)
+ compiler=aix
+ ;;
+ esac
+ fi
+ case "$compiler" in
+ gcc)
+ ISC_PLATFORM_USEGCCASM="#define ISC_PLATFORM_USEGCCASM 1"
+ ;;
+ osf)
+ ISC_PLATFORM_USEOSFASM="#define ISC_PLATFORM_USEOSFASM 1"
+ ;;
+ aix)
+ ;;
+ mac)
+ ;;
+ *)
+ # See if the generic __asm function works. If not,
+ # we need to disable the atomic operations.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ __asm("nop")
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ compiler="standard"
+ ISC_PLATFORM_USESTDASM="#define ISC_PLATFORM_USESTDASM 1"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ compiler="not supported (atomic operations disabled)"
+ have_atomic=no
+ arch=noatomic
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext;
+ ;;
+ esac
+
+ { echo "$as_me:$LINENO: result: $compiler" >&5
+echo "${ECHO_T}$compiler" >&6; }
+fi
+
+if test "$have_atomic" = "yes"; then
+ ISC_PLATFORM_HAVEXADD="#define ISC_PLATFORM_HAVEXADD 1"
+ ISC_PLATFORM_HAVECMPXCHG="#define ISC_PLATFORM_HAVECMPXCHG 1"
+ ISC_PLATFORM_HAVEATOMICSTORE="#define ISC_PLATFORM_HAVEATOMICSTORE 1"
+else
+ ISC_PLATFORM_HAVEXADD="#undef ISC_PLATFORM_HAVEXADD"
+ ISC_PLATFORM_HAVECMPXCHG="#undef ISC_PLATFORM_HAVECMPXCHG"
+ ISC_PLATFORM_HAVEATOMICSTORE="#undef ISC_PLATFORM_HAVEATOMICSTORE"
+fi
+
+if test "$have_xaddq" = "yes"; then
+ ISC_PLATFORM_HAVEXADDQ="#define ISC_PLATFORM_HAVEXADDQ 1"
+else
+ ISC_PLATFORM_HAVEXADDQ="#undef ISC_PLATFORM_HAVEXADDQ"
+fi
+
+
+
+
+
+
+
+
+
+
+
+ISC_ARCH_DIR=$arch
+
+
+#
+# Activate "rrset-order fixed" or not?
+#
+# Check whether --enable-fixed-rrset was given.
+if test "${enable_fixed_rrset+set}" = set; then
+ enableval=$enable_fixed_rrset; enable_fixed="$enableval"
+else
+ enable_fixed="no"
+fi
+
+case "$enable_fixed" in
+ yes)
+
+cat >>confdefs.h <<\_ACEOF
+#define DNS_RDATASET_FIXED 1
+_ACEOF
+
+ ;;
+ no)
+ ;;
+ *)
+ ;;
+esac
+
+#
+# The following sets up how non-blocking i/o is established.
+# Sunos, cygwin and solaris 2.x (x<5) require special handling.
+#
+case "$host" in
+*-sunos*) cat >>confdefs.h <<\_ACEOF
+#define PORT_NONBLOCK O_NDELAY
+_ACEOF
+;;
+*-cygwin*) cat >>confdefs.h <<\_ACEOF
+#define PORT_NONBLOCK O_NDELAY
+_ACEOF
+;;
+*-solaris2.[01234])
+ cat >>confdefs.h <<\_ACEOF
+#define PORT_NONBLOCK O_NONBLOCK
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_FIONBIO_IOCTL 1
+_ACEOF
+
+ ;;
+*)
+cat >>confdefs.h <<\_ACEOF
+#define PORT_NONBLOCK O_NONBLOCK
+_ACEOF
+
+ ;;
+esac
+#
+# Solaris 2.5.1 and earlier cannot bind() then connect() a TCP socket.
+# This prevents the source address being set.
+#
+case "$host" in
+*-solaris2.[012345]|*-solaris2.5.1)
+
+cat >>confdefs.h <<\_ACEOF
+#define BROKEN_TCP_BIND_BEFORE_CONNECT 1
+_ACEOF
+
+ ;;
+esac
+#
+# The following sections deal with tools used for formatting
+# the documentation. They are all optional, unless you are
+# a developer editing the documentation source.
+#
+
+#
+# Look for TeX.
+#
+
+for ac_prog in latex
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_LATEX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $LATEX in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_LATEX="$LATEX" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_LATEX="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+LATEX=$ac_cv_path_LATEX
+if test -n "$LATEX"; then
+ { echo "$as_me:$LINENO: result: $LATEX" >&5
+echo "${ECHO_T}$LATEX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$LATEX" && break
+done
+test -n "$LATEX" || LATEX="latex"
+
+
+
+for ac_prog in pdflatex
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_PDFLATEX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $PDFLATEX in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PDFLATEX="$PDFLATEX" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PDFLATEX="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PDFLATEX=$ac_cv_path_PDFLATEX
+if test -n "$PDFLATEX"; then
+ { echo "$as_me:$LINENO: result: $PDFLATEX" >&5
+echo "${ECHO_T}$PDFLATEX" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$PDFLATEX" && break
+done
+test -n "$PDFLATEX" || PDFLATEX="pdflatex"
+
+
+
+#
+# Look for w3m
+#
+
+for ac_prog in w3m
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_W3M+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $W3M in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_W3M="$W3M" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_W3M="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+W3M=$ac_cv_path_W3M
+if test -n "$W3M"; then
+ { echo "$as_me:$LINENO: result: $W3M" >&5
+echo "${ECHO_T}$W3M" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$W3M" && break
+done
+test -n "$W3M" || W3M="w3m"
+
+
+
+#
+# Look for xsltproc (libxslt)
+#
+
+# Extract the first word of "xsltproc", so it can be a program name with args.
+set dummy xsltproc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_XSLTPROC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $XSLTPROC in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_XSLTPROC="$XSLTPROC" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_XSLTPROC="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_XSLTPROC" && ac_cv_path_XSLTPROC="xsltproc"
+ ;;
+esac
+fi
+XSLTPROC=$ac_cv_path_XSLTPROC
+if test -n "$XSLTPROC"; then
+ { echo "$as_me:$LINENO: result: $XSLTPROC" >&5
+echo "${ECHO_T}$XSLTPROC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+
+#
+# Look for xmllint (libxml2)
+#
+
+# Extract the first word of "xmllint", so it can be a program name with args.
+set dummy xmllint; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_XMLLINT+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $XMLLINT in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_XMLLINT="$XMLLINT" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_XMLLINT="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_XMLLINT" && ac_cv_path_XMLLINT="xmllint"
+ ;;
+esac
+fi
+XMLLINT=$ac_cv_path_XMLLINT
+if test -n "$XMLLINT"; then
+ { echo "$as_me:$LINENO: result: $XMLLINT" >&5
+echo "${ECHO_T}$XMLLINT" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+
+#
+# Look for Doxygen
+#
+
+# Extract the first word of "doxygen", so it can be a program name with args.
+set dummy doxygen; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_DOXYGEN+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $DOXYGEN in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_DOXYGEN="$DOXYGEN" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_DOXYGEN="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_DOXYGEN" && ac_cv_path_DOXYGEN="doxygen"
+ ;;
+esac
+fi
+DOXYGEN=$ac_cv_path_DOXYGEN
+if test -n "$DOXYGEN"; then
+ { echo "$as_me:$LINENO: result: $DOXYGEN" >&5
+echo "${ECHO_T}$DOXYGEN" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+
+
+#
+# Subroutine for searching for an ordinary file (e.g., a stylesheet)
+# in a number of directories:
+#
+# NOM_PATH_FILE(VARIABLE, FILENAME, DIRECTORIES)
+#
+# If the file FILENAME is found in one of the DIRECTORIES, the shell
+# variable VARIABLE is defined to its absolute pathname. Otherwise,
+# it is set to FILENAME, with no directory prefix (that's not terribly
+# useful, but looks less confusing in substitutions than leaving it
+# empty). The variable VARIABLE will be substituted into output files.
+#
+
+
+
+#
+# Look for Docbook-XSL stylesheets. Location probably varies by system.
+# If it's not explicitly specified, guess where it might be found, based on
+# where SGML stuff lives on some systems (FreeBSD is the only one we're sure
+# of at the moment).
+#
+{ echo "$as_me:$LINENO: checking for Docbook-XSL path" >&5
+echo $ECHO_N "checking for Docbook-XSL path... $ECHO_C" >&6; }
+
+# Check whether --with-docbook-xsl was given.
+if test "${with_docbook_xsl+set}" = set; then
+ withval=$with_docbook_xsl; docbook_path="$withval"
+else
+ docbook_path="auto"
+fi
+
+case "$docbook_path" in
+auto)
+ { echo "$as_me:$LINENO: result: auto" >&5
+echo "${ECHO_T}auto" >&6; }
+ docbook_xsl_trees="/usr/pkg/share/xsl/docbook /usr/local/share/xsl/docbook /usr/share/xsl/docbook"
+ ;;
+*)
+ docbook_xsl_trees="$withval"
+ { echo "$as_me:$LINENO: result: $docbook_xsl_trees" >&5
+echo "${ECHO_T}$docbook_xsl_trees" >&6; }
+ ;;
+esac
+
+#
+# Look for stylesheets we need.
+#
+
+
+XSLT_DOCBOOK_STYLE_HTML=""
+{ echo "$as_me:$LINENO: checking for html/docbook.xsl" >&5
+echo $ECHO_N "checking for html/docbook.xsl... $ECHO_C" >&6; }
+for d in $docbook_xsl_trees
+do
+ f=$d/html/docbook.xsl
+ if test -f $f
+ then
+ XSLT_DOCBOOK_STYLE_HTML=$f
+ { echo "$as_me:$LINENO: result: $f" >&5
+echo "${ECHO_T}$f" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DOCBOOK_STYLE_HTML" = "X"
+then
+ { echo "$as_me:$LINENO: result: \"not found\"" >&5
+echo "${ECHO_T}\"not found\"" >&6; };
+ XSLT_DOCBOOK_STYLE_HTML=html/docbook.xsl
+fi
+
+
+
+XSLT_DOCBOOK_STYLE_XHTML=""
+{ echo "$as_me:$LINENO: checking for xhtml/docbook.xsl" >&5
+echo $ECHO_N "checking for xhtml/docbook.xsl... $ECHO_C" >&6; }
+for d in $docbook_xsl_trees
+do
+ f=$d/xhtml/docbook.xsl
+ if test -f $f
+ then
+ XSLT_DOCBOOK_STYLE_XHTML=$f
+ { echo "$as_me:$LINENO: result: $f" >&5
+echo "${ECHO_T}$f" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DOCBOOK_STYLE_XHTML" = "X"
+then
+ { echo "$as_me:$LINENO: result: \"not found\"" >&5
+echo "${ECHO_T}\"not found\"" >&6; };
+ XSLT_DOCBOOK_STYLE_XHTML=xhtml/docbook.xsl
+fi
+
+
+
+XSLT_DOCBOOK_STYLE_MAN=""
+{ echo "$as_me:$LINENO: checking for manpages/docbook.xsl" >&5
+echo $ECHO_N "checking for manpages/docbook.xsl... $ECHO_C" >&6; }
+for d in $docbook_xsl_trees
+do
+ f=$d/manpages/docbook.xsl
+ if test -f $f
+ then
+ XSLT_DOCBOOK_STYLE_MAN=$f
+ { echo "$as_me:$LINENO: result: $f" >&5
+echo "${ECHO_T}$f" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DOCBOOK_STYLE_MAN" = "X"
+then
+ { echo "$as_me:$LINENO: result: \"not found\"" >&5
+echo "${ECHO_T}\"not found\"" >&6; };
+ XSLT_DOCBOOK_STYLE_MAN=manpages/docbook.xsl
+fi
+
+
+
+XSLT_DOCBOOK_CHUNK_HTML=""
+{ echo "$as_me:$LINENO: checking for html/chunk.xsl" >&5
+echo $ECHO_N "checking for html/chunk.xsl... $ECHO_C" >&6; }
+for d in $docbook_xsl_trees
+do
+ f=$d/html/chunk.xsl
+ if test -f $f
+ then
+ XSLT_DOCBOOK_CHUNK_HTML=$f
+ { echo "$as_me:$LINENO: result: $f" >&5
+echo "${ECHO_T}$f" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DOCBOOK_CHUNK_HTML" = "X"
+then
+ { echo "$as_me:$LINENO: result: \"not found\"" >&5
+echo "${ECHO_T}\"not found\"" >&6; };
+ XSLT_DOCBOOK_CHUNK_HTML=html/chunk.xsl
+fi
+
+
+
+XSLT_DOCBOOK_CHUNK_XHTML=""
+{ echo "$as_me:$LINENO: checking for xhtml/chunk.xsl" >&5
+echo $ECHO_N "checking for xhtml/chunk.xsl... $ECHO_C" >&6; }
+for d in $docbook_xsl_trees
+do
+ f=$d/xhtml/chunk.xsl
+ if test -f $f
+ then
+ XSLT_DOCBOOK_CHUNK_XHTML=$f
+ { echo "$as_me:$LINENO: result: $f" >&5
+echo "${ECHO_T}$f" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DOCBOOK_CHUNK_XHTML" = "X"
+then
+ { echo "$as_me:$LINENO: result: \"not found\"" >&5
+echo "${ECHO_T}\"not found\"" >&6; };
+ XSLT_DOCBOOK_CHUNK_XHTML=xhtml/chunk.xsl
+fi
+
+
+
+XSLT_DOCBOOK_CHUNKTOC_HTML=""
+{ echo "$as_me:$LINENO: checking for html/chunktoc.xsl" >&5
+echo $ECHO_N "checking for html/chunktoc.xsl... $ECHO_C" >&6; }
+for d in $docbook_xsl_trees
+do
+ f=$d/html/chunktoc.xsl
+ if test -f $f
+ then
+ XSLT_DOCBOOK_CHUNKTOC_HTML=$f
+ { echo "$as_me:$LINENO: result: $f" >&5
+echo "${ECHO_T}$f" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DOCBOOK_CHUNKTOC_HTML" = "X"
+then
+ { echo "$as_me:$LINENO: result: \"not found\"" >&5
+echo "${ECHO_T}\"not found\"" >&6; };
+ XSLT_DOCBOOK_CHUNKTOC_HTML=html/chunktoc.xsl
+fi
+
+
+
+XSLT_DOCBOOK_CHUNKTOC_XHTML=""
+{ echo "$as_me:$LINENO: checking for xhtml/chunktoc.xsl" >&5
+echo $ECHO_N "checking for xhtml/chunktoc.xsl... $ECHO_C" >&6; }
+for d in $docbook_xsl_trees
+do
+ f=$d/xhtml/chunktoc.xsl
+ if test -f $f
+ then
+ XSLT_DOCBOOK_CHUNKTOC_XHTML=$f
+ { echo "$as_me:$LINENO: result: $f" >&5
+echo "${ECHO_T}$f" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DOCBOOK_CHUNKTOC_XHTML" = "X"
+then
+ { echo "$as_me:$LINENO: result: \"not found\"" >&5
+echo "${ECHO_T}\"not found\"" >&6; };
+ XSLT_DOCBOOK_CHUNKTOC_XHTML=xhtml/chunktoc.xsl
+fi
+
+
+
+XSLT_DOCBOOK_MAKETOC_HTML=""
+{ echo "$as_me:$LINENO: checking for html/maketoc.xsl" >&5
+echo $ECHO_N "checking for html/maketoc.xsl... $ECHO_C" >&6; }
+for d in $docbook_xsl_trees
+do
+ f=$d/html/maketoc.xsl
+ if test -f $f
+ then
+ XSLT_DOCBOOK_MAKETOC_HTML=$f
+ { echo "$as_me:$LINENO: result: $f" >&5
+echo "${ECHO_T}$f" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DOCBOOK_MAKETOC_HTML" = "X"
+then
+ { echo "$as_me:$LINENO: result: \"not found\"" >&5
+echo "${ECHO_T}\"not found\"" >&6; };
+ XSLT_DOCBOOK_MAKETOC_HTML=html/maketoc.xsl
+fi
+
+
+
+XSLT_DOCBOOK_MAKETOC_XHTML=""
+{ echo "$as_me:$LINENO: checking for xhtml/maketoc.xsl" >&5
+echo $ECHO_N "checking for xhtml/maketoc.xsl... $ECHO_C" >&6; }
+for d in $docbook_xsl_trees
+do
+ f=$d/xhtml/maketoc.xsl
+ if test -f $f
+ then
+ XSLT_DOCBOOK_MAKETOC_XHTML=$f
+ { echo "$as_me:$LINENO: result: $f" >&5
+echo "${ECHO_T}$f" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DOCBOOK_MAKETOC_XHTML" = "X"
+then
+ { echo "$as_me:$LINENO: result: \"not found\"" >&5
+echo "${ECHO_T}\"not found\"" >&6; };
+ XSLT_DOCBOOK_MAKETOC_XHTML=xhtml/maketoc.xsl
+fi
+
+
+
+#
+# Same dance for db2latex
+#
+# No idea where this lives except on FreeBSD.
+#
+
+db2latex_xsl_trees="/usr/local/share"
+
+#
+# Look for stylesheets we need.
+#
+
+
+XSLT_DB2LATEX_STYLE=""
+{ echo "$as_me:$LINENO: checking for db2latex/xsl/docbook.xsl" >&5
+echo $ECHO_N "checking for db2latex/xsl/docbook.xsl... $ECHO_C" >&6; }
+for d in $db2latex_xsl_trees
+do
+ f=$d/db2latex/xsl/docbook.xsl
+ if test -f $f
+ then
+ XSLT_DB2LATEX_STYLE=$f
+ { echo "$as_me:$LINENO: result: $f" >&5
+echo "${ECHO_T}$f" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DB2LATEX_STYLE" = "X"
+then
+ { echo "$as_me:$LINENO: result: \"not found\"" >&5
+echo "${ECHO_T}\"not found\"" >&6; };
+ XSLT_DB2LATEX_STYLE=db2latex/xsl/docbook.xsl
+fi
+
+
+
+#
+# Look for "admonition" image directory. Can't use NOM_PATH_FILE()
+# because it's a directory, so just do the same things, inline.
+#
+
+{ echo "$as_me:$LINENO: checking for db2latex/xsl/figures" >&5
+echo $ECHO_N "checking for db2latex/xsl/figures... $ECHO_C" >&6; }
+for d in $db2latex_xsl_trees
+do
+ dd=$d/db2latex/xsl/figures
+ if test -d $dd
+ then
+ XSLT_DB2LATEX_ADMONITIONS=$dd
+ { echo "$as_me:$LINENO: result: $dd" >&5
+echo "${ECHO_T}$dd" >&6; }
+ break
+ fi
+done
+if test "X$XSLT_DB2LATEX_ADMONITIONS" = "X"
+then
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ XSLT_DB2LATEX_ADMONITIONS=db2latex/xsl/figures
+fi
+
+
+#
+# IDN support
+#
+
+# Check whether --with-idn was given.
+if test "${with_idn+set}" = set; then
+ withval=$with_idn; use_idn="$withval"
+else
+ use_idn="no"
+fi
+
+case "$use_idn" in
+yes)
+ if test X$prefix = XNONE ; then
+ idn_path=/usr/local
+ else
+ idn_path=$prefix
+ fi
+ ;;
+no)
+ ;;
+*)
+ idn_path="$use_idn"
+ ;;
+esac
+
+iconvinc=
+iconvlib=
+
+# Check whether --with-libiconv was given.
+if test "${with_libiconv+set}" = set; then
+ withval=$with_libiconv; use_libiconv="$withval"
+else
+ use_libiconv="no"
+fi
+
+case "$use_libiconv" in
+yes)
+ if test X$prefix = XNONE ; then
+ iconvlib="-L/usr/local/lib -R/usr/local/lib -liconv"
+ else
+ iconvlib="-L$prefix/lib -R$prefix/lib -liconv"
+ fi
+ ;;
+no)
+ iconvlib=
+ ;;
+*)
+ iconvlib="-L$use_libiconv/lib -R$use_libiconv/lib -liconv"
+ ;;
+esac
+
+
+# Check whether --with-iconv was given.
+if test "${with_iconv+set}" = set; then
+ withval=$with_iconv; iconvlib="$withval"
+fi
+
+case "$iconvlib" in
+no)
+ iconvlib=
+ ;;
+yes)
+ iconvlib=-liconv
+ ;;
+esac
+
+
+# Check whether --with-idnlib was given.
+if test "${with_idnlib+set}" = set; then
+ withval=$with_idnlib; idnlib="$withval"
+else
+ idnlib="no"
+fi
+
+if test "$idnlib" = yes; then
+ { { echo "$as_me:$LINENO: error: You must specify ARG for --with-idnlib." >&5
+echo "$as_me: error: You must specify ARG for --with-idnlib." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+IDNLIBS=
+if test "$use_idn" != no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define WITH_IDN 1
+_ACEOF
+
+ STD_CINCLUDES="$STD_CINCLUDES -I$idn_path/include"
+ if test "$idnlib" != no; then
+ IDNLIBS="$idnlib $iconvlib"
+ else
+ IDNLIBS="-L$idn_path/lib -lidnkit $iconvlib"
+ fi
+fi
+
+
+
+for ac_header in locale.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in setlocale
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+#
+# Substitutions
+#
+
+BIND9_TOP_BUILDDIR=`pwd`
+
+
+
+
+
+
+
+if test "X$srcdir" != "X"; then
+ BIND9_ISC_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isc/include"
+ BIND9_ISCCC_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isccc/include"
+ BIND9_ISCCFG_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isccfg/include"
+ BIND9_DNS_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/dns/include"
+ BIND9_LWRES_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/lwres/include"
+ BIND9_BIND9_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/bind9/include"
+else
+ BIND9_ISC_BUILDINCLUDE=""
+ BIND9_ISCCC_BUILDINCLUDE=""
+ BIND9_ISCCFG_BUILDINCLUDE=""
+ BIND9_DNS_BUILDINCLUDE=""
+ BIND9_LWRES_BUILDINCLUDE=""
+ BIND9_BIND9_BUILDINCLUDE=""
+fi
+
+
+BIND9_MAKE_INCLUDES=$BIND9_TOP_BUILDDIR/make/includes
+
+
+BIND9_MAKE_RULES=$BIND9_TOP_BUILDDIR/make/rules
+
+. $srcdir/version
+BIND9_VERSION="VERSION=${MAJORVER}.${MINORVER}.${PATCHVER}${RELEASETYPE}${RELEASEVER}"
+
+
+if test -z "$ac_configure_args"; then
+ BIND9_CONFIGARGS="defaults"
+else
+ for a in $ac_configure_args
+ do
+ BIND9_CONFIGARGS="$BIND9_CONFIGARGS $a"
+ done
+fi
+BIND9_CONFIGARGS="`echo $BIND9_CONFIGARGS | sed 's/^ //'`"
+BIND9_CONFIGARGS="CONFIGARGS=${BIND9_CONFIGARGS}"
+
+
+
+LIBISC_API=$srcdir/lib/isc/api
+
+
+LIBISCCC_API=$srcdir/lib/isccc/api
+
+
+LIBISCCFG_API=$srcdir/lib/isccfg/api
+
+
+LIBDNS_API=$srcdir/lib/dns/api
+
+
+LIBBIND9_API=$srcdir/lib/bind9/api
+
+
+LIBLWRES_API=$srcdir/lib/lwres/api
+
+#
+# Configure any DLZ drivers.
+#
+# If config.dlz.in selects one or more DLZ drivers, it will set
+# USE_DLZ to a non-empty value, which will be our clue to
+# enable the DLZ core functions.
+#
+# This section has to come after the libtool stuff because it needs to
+# know how to name the driver object files.
+#
+
+USE_DLZ=""
+DLZ_DRIVER_INCLUDES=""
+DLZ_DRIVER_LIBS=""
+DLZ_DRIVER_SRCS=""
+DLZ_DRIVER_OBJS=""
+
+# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND 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.
+
+#
+# Shorthand. Note quoting: DLZ_DRIVER_DIR expanded in Makefile, not here.
+#
+dlzdir='${DLZ_DRIVER_DIR}'
+
+#
+# Private autoconf macro to simplify configuring drivers:
+#
+# DLZ_ADD_DRIVER(DEFINE, DRIVER, INCLUDES, LIBS)
+#
+# where:
+# DEFINE is FOO (to define -DDLZ_FOO)
+# DRIVER is dlz_foo_driver (sources without the .c)
+# INCLUDES is any necessary include definitions
+# LIBS is any necessary library definitions
+#
+
+
+#
+# Check for the various DLZ drivers
+#
+
+#
+# Was --with-dlz-postgres specified?
+#
+
+{ echo "$as_me:$LINENO: checking for Postgres DLZ driver" >&5
+echo $ECHO_N "checking for Postgres DLZ driver... $ECHO_C" >&6; }
+
+# Check whether --with-dlz_postgres was given.
+if test "${with_dlz_postgres+set}" = set; then
+ withval=$with_dlz_postgres; use_dlz_postgres="$withval"
+else
+ use_dlz_postgres="no"
+fi
+
+
+if test "$use_dlz_postgres" = "yes"
+then
+ # User did not specify a path - guess it
+ # Ask Postgres to tell us where it is
+
+ for ac_prog in pg_config
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_path_PG_CONFIG+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $PG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PG_CONFIG="$PG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_PG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PG_CONFIG=$ac_cv_path_PG_CONFIG
+if test -n "$PG_CONFIG"; then
+ { echo "$as_me:$LINENO: result: $PG_CONFIG" >&5
+echo "${ECHO_T}$PG_CONFIG" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$PG_CONFIG" && break
+done
+test -n "$PG_CONFIG" || PG_CONFIG="not found"
+
+
+ if test "$PG_CONFIG" != "not found"
+ then
+ use_dlz_postgres=`$PG_CONFIG --includedir`
+ use_dlz_postgres_lib=`$PG_CONFIG --libdir`
+ fi
+fi
+
+if test "$use_dlz_postgres" = "yes"
+then
+ # User did not specify path and Postgres didn't say - guess it
+
+ pgdirs="/usr /usr/local /usr/local/pgsql /usr/pkg"
+ for d in $pgdirs
+ do
+ if test -f $d/include/libpq-fe.h
+ then
+ use_dlz_postgres=$d/include
+ use_dlz_postgres_lib=$d/lib
+ break
+ fi
+ done
+fi
+
+if test "$use_dlz_postgres" = "yes"
+then
+ # Still no joy, give up
+
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ { { echo "$as_me:$LINENO: error: No pg_config and PostgreSQL was not found in any of $pgdirs; use --with-dlz-postgres=/path or put pg_config in your path" >&5
+echo "$as_me: error: No pg_config and PostgreSQL was not found in any of $pgdirs; use --with-dlz-postgres=/path or put pg_config in your path" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+case "$use_dlz_postgres" in
+ no)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ *)
+
+ USE_DLZ="$USE_DLZ -DDLZ_POSTGRES"
+ for i in dlz_postgres_driver
+ do
+ DLZ_DRIVER_SRCS="$DLZ_DRIVER_SRCS $dlzdir/$i.c"
+ DLZ_DRIVER_OBJS="$DLZ_DRIVER_OBJS $i.$O"
+ done
+ if test -n "-I$use_dlz_postgres"
+ then
+ DLZ_DRIVER_INCLUDES="$DLZ_DRIVER_INCLUDES -I$use_dlz_postgres"
+ fi
+ if test -n "-L$use_dlz_postgres_lib -lpq"
+ then
+ DLZ_DRIVER_LIBS="$DLZ_DRIVER_LIBS -L$use_dlz_postgres_lib -lpq"
+ fi
+
+
+ { echo "$as_me:$LINENO: result: using PostgreSQL from $use_dlz_postgres_lib and $use_dlz_postgres" >&5
+echo "${ECHO_T}using PostgreSQL from $use_dlz_postgres_lib and $use_dlz_postgres" >&6; }
+ ;;
+esac
+
+
+#
+# Was --with-dlz-mysql specified?
+#
+
+{ echo "$as_me:$LINENO: checking for MySQL DLZ driver" >&5
+echo $ECHO_N "checking for MySQL DLZ driver... $ECHO_C" >&6; }
+
+# Check whether --with-dlz_mysql was given.
+if test "${with_dlz_mysql+set}" = set; then
+ withval=$with_dlz_mysql; use_dlz_mysql="$withval"
+else
+ use_dlz_mysql="no"
+fi
+
+
+mysql_include=""
+mysql_lib=""
+if test "$use_dlz_mysql" = "yes"
+then
+ # User did not specify a path - guess it
+ mysqldirs="/usr /usr/local /usr/local/mysql /usr/pkg"
+ for d in $mysqldirs
+ do
+ if test -f $d/include/mysql/mysql.h
+ then
+ use_dlz_mysql=$d
+ mysql_include=$d/include/mysql
+ if test -d $d/lib/mysql
+ then
+ mysql_lib=$d/lib/mysql
+ else
+ mysql_lib=$d/lib
+ fi
+ break
+ elif test -f $d/include/mysql.h
+ then
+ use_dlz_mysql=$d
+ mysql_include=$d/include
+ if test -d $d/lib/mysql
+ then
+ mysql_lib=$d/lib/mysql
+ else
+ mysql_lib=$d/lib
+ fi
+ break
+ fi
+ done
+elif test "$use_dlz_mysql" != "no"
+then
+ d=$use_dlz_mysql
+ if test -f $d/include/mysql/mysql.h
+ then
+ mysql_include=$d/include/mysql
+ if test -d $d/lib/mysql
+ then
+ mysql_lib=$d/lib/mysql
+ else
+ mysql_lib=$d/lib
+ fi
+ elif test -f $d/include/mysql.h
+ then
+ mysql_include=$d/include
+ if test -d $d/lib/mysql
+ then
+ mysql_lib=$d/lib/mysql
+ else
+ mysql_lib=$d/lib
+ fi
+ fi
+fi
+
+if test "$use_dlz_mysql" = "yes"
+then
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ { { echo "$as_me:$LINENO: error: MySQL was not found in any of $mysqldirs; use --with-dlz-mysql=/path" >&5
+echo "$as_me: error: MySQL was not found in any of $mysqldirs; use --with-dlz-mysql=/path" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+case "$use_dlz_mysql" in
+ no)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ *)
+
+ USE_DLZ="$USE_DLZ -DDLZ_MYSQL"
+ for i in dlz_mysql_driver
+ do
+ DLZ_DRIVER_SRCS="$DLZ_DRIVER_SRCS $dlzdir/$i.c"
+ DLZ_DRIVER_OBJS="$DLZ_DRIVER_OBJS $i.$O"
+ done
+ if test -n "-I${mysql_include}"
+ then
+ DLZ_DRIVER_INCLUDES="$DLZ_DRIVER_INCLUDES -I${mysql_include}"
+ fi
+ if test -n "-L${mysql_lib} -lmysqlclient -lz -lcrypt -lm"
+ then
+ DLZ_DRIVER_LIBS="$DLZ_DRIVER_LIBS -L${mysql_lib} -lmysqlclient -lz -lcrypt -lm"
+ fi
+
+
+ { echo "$as_me:$LINENO: result: using mysql from ${mysql_lib} and ${mysql_include}" >&5
+echo "${ECHO_T}using mysql from ${mysql_lib} and ${mysql_include}" >&6; }
+ ;;
+esac
+
+
+#
+# Was --with-dlz-bdb specified?
+#
+
+{ echo "$as_me:$LINENO: checking for Berkeley DB DLZ driver" >&5
+echo $ECHO_N "checking for Berkeley DB DLZ driver... $ECHO_C" >&6; }
+
+# Check whether --with-dlz_bdb was given.
+if test "${with_dlz_bdb+set}" = set; then
+ withval=$with_dlz_bdb; use_dlz_bdb="$withval"
+else
+ use_dlz_bdb="no"
+fi
+
+
+case "$use_dlz_bdb" in
+ no)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ *)
+ if test "$use_dlz_bdb" = "yes"
+ then
+ # User did not specify a path - guess directories
+ bdbdirs="/usr/local /usr/pkg /usr"
+ elif test -d "$use_dlz_bdb"
+ then
+ # User specified directory and it exists
+ bdbdirs="$use_dlz_bdb"
+ else
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ { { echo "$as_me:$LINENO: error: path $use_dlz_bdb does not exist" >&5
+echo "$as_me: error: path $use_dlz_bdb does not exist" >&2;}
+ { (exit 1); exit 1; }; }
+ bdbdirs=""
+ fi
+
+ # Use path we were given or guessed. This is insanely
+ # complicated because we have to search for a bunch of
+ # platform-specific variations and have to check
+ # separately for include and library directories.
+
+ # Set both to yes, so we can check them later
+ dlz_bdb_inc="yes"
+ dlz_bdb_libs="yes"
+
+ for dd in $bdbdirs
+ do
+ # Skip nonexistant directories
+ if test ! -d "$dd"
+ then
+ continue
+ fi
+
+ # Check other locations for includes.
+ # Order is important (sigh).
+
+ bdb_incdirs="/ /db42/ /db41/ /db4/ /db/"
+ for d in $bdb_incdirs
+ do
+ if test -f "$dd/include${d}db.h"
+ then
+ dlz_bdb_inc="-I$dd/include${d}"
+ break
+ fi
+ done
+
+ # Give up on this directory if we couldn't
+ # find the include subdir
+
+ if test "$dlz_bdb_inc" = "yes"
+ then
+ continue
+ fi
+
+ # Look for libname other than libdb.so.
+ # Order is important (sigh).
+
+ bdb_libnames="db42 db-4.2 db41 db-4.1 db"
+ for d in $bdb_libnames
+ do
+ if test -f "$dd/lib/lib${d}.so"
+ then
+ if test "$dd" != "/usr"
+ then
+ dlz_bdb_libs="-L${dd}/lib "
+ else
+ dlz_bdb_libs=""
+ fi
+ dlz_bdb_libs="${dlz_bdb_libs}-l${d}"
+ break
+ fi
+ done
+
+ # If we found both incdir and lib, we're done
+ if test "$dlz_bdb_libs" != "yes"
+ then
+ break
+ fi
+
+ # Otherwise, we're starting over
+
+ dlz_bdb_inc="yes"
+ dlz_bdb_libs="yes"
+ done
+
+ # Done searching, now make sure we got everything.
+
+ if test "$dlz_bdb_inc" = "yes"
+ then
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ { { echo "$as_me:$LINENO: error: could not find Berkeley DB include directory" >&5
+echo "$as_me: error: could not find Berkeley DB include directory" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ if test "$dlz_bdb_libs" = "yes"
+ then
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ { { echo "$as_me:$LINENO: error: could not find Berkeley DB library" >&5
+echo "$as_me: error: could not find Berkeley DB library" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+
+ USE_DLZ="$USE_DLZ -DDLZ_BDB"
+ for i in dlz_bdb_driver dlz_bdbhpt_driver
+ do
+ DLZ_DRIVER_SRCS="$DLZ_DRIVER_SRCS $dlzdir/$i.c"
+ DLZ_DRIVER_OBJS="$DLZ_DRIVER_OBJS $i.$O"
+ done
+ if test -n "$dlz_bdb_inc"
+ then
+ DLZ_DRIVER_INCLUDES="$DLZ_DRIVER_INCLUDES $dlz_bdb_inc"
+ fi
+ if test -n "$dlz_bdb_libs"
+ then
+ DLZ_DRIVER_LIBS="$DLZ_DRIVER_LIBS $dlz_bdb_libs"
+ fi
+
+
+ { echo "$as_me:$LINENO: result: using Berkeley DB: $dlz_bdb_inc $dlz_bdb_libs" >&5
+echo "${ECHO_T}using Berkeley DB: $dlz_bdb_inc $dlz_bdb_libs" >&6; }
+
+ ac_config_files="$ac_config_files contrib/dlz/bin/dlzbdb/Makefile"
+
+ ;;
+esac
+
+
+#
+# Was --with-dlz-filesystem specified?
+#
+
+{ echo "$as_me:$LINENO: checking for file system DLZ driver" >&5
+echo $ECHO_N "checking for file system DLZ driver... $ECHO_C" >&6; }
+
+# Check whether --with-dlz_filesystem was given.
+if test "${with_dlz_filesystem+set}" = set; then
+ withval=$with_dlz_filesystem; use_dlz_filesystem="$withval"
+else
+ use_dlz_filesystem="no"
+fi
+
+
+case "$use_dlz_filesystem" in
+ no)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ *)
+
+ USE_DLZ="$USE_DLZ -DDLZ_FILESYSTEM"
+ for i in dlz_filesystem_driver
+ do
+ DLZ_DRIVER_SRCS="$DLZ_DRIVER_SRCS $dlzdir/$i.c"
+ DLZ_DRIVER_OBJS="$DLZ_DRIVER_OBJS $i.$O"
+ done
+ if test -n ""
+ then
+ DLZ_DRIVER_INCLUDES="$DLZ_DRIVER_INCLUDES "
+ fi
+ if test -n ""
+ then
+ DLZ_DRIVER_LIBS="$DLZ_DRIVER_LIBS "
+ fi
+
+
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ;;
+esac
+
+
+#
+# Was --with-dlz-ldap specified?
+#
+
+{ echo "$as_me:$LINENO: checking for LDAP DLZ driver" >&5
+echo $ECHO_N "checking for LDAP DLZ driver... $ECHO_C" >&6; }
+
+# Check whether --with-dlz_ldap was given.
+if test "${with_dlz_ldap+set}" = set; then
+ withval=$with_dlz_ldap; use_dlz_ldap="$withval"
+else
+ use_dlz_ldap="no"
+fi
+
+
+if test "$use_dlz_ldap" = "yes"
+then
+ # User did not specify a path - guess it
+ ldapdirs="/usr /usr/local /usr/pkg"
+ for d in $ldapdirs
+ do
+ if test -f $d/include/ldap.h
+ then
+ use_dlz_ldap=$d
+ break
+ fi
+ done
+fi
+
+if test "$use_dlz_ldap" = "yes"
+then
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ { { echo "$as_me:$LINENO: error: LDAP headers were not found in any of $ldapdirs; use --with-dlz-ldap=/path" >&5
+echo "$as_me: error: LDAP headers were not found in any of $ldapdirs; use --with-dlz-ldap=/path" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+case "$use_dlz_ldap" in
+ no)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ *)
+
+ USE_DLZ="$USE_DLZ -DDLZ_LDAP"
+ for i in dlz_ldap_driver
+ do
+ DLZ_DRIVER_SRCS="$DLZ_DRIVER_SRCS $dlzdir/$i.c"
+ DLZ_DRIVER_OBJS="$DLZ_DRIVER_OBJS $i.$O"
+ done
+ if test -n "-I$use_dlz_ldap/include"
+ then
+ DLZ_DRIVER_INCLUDES="$DLZ_DRIVER_INCLUDES -I$use_dlz_ldap/include"
+ fi
+ if test -n "-L$use_dlz_ldap/lib -lldap -llber"
+ then
+ DLZ_DRIVER_LIBS="$DLZ_DRIVER_LIBS -L$use_dlz_ldap/lib -lldap -llber"
+ fi
+
+
+ { echo "$as_me:$LINENO: result: using LDAP from $use_dlz_ldap/lib and $use_dlz_ldap/include" >&5
+echo "${ECHO_T}using LDAP from $use_dlz_ldap/lib and $use_dlz_ldap/include" >&6; }
+ ;;
+esac
+
+
+#
+# Was --with-dlz-odbc specified?
+#
+
+{ echo "$as_me:$LINENO: checking for ODBC DLZ driver" >&5
+echo $ECHO_N "checking for ODBC DLZ driver... $ECHO_C" >&6; }
+
+# Check whether --with-dlz_odbc was given.
+if test "${with_dlz_odbc+set}" = set; then
+ withval=$with_dlz_odbc; use_dlz_odbc="$withval"
+else
+ use_dlz_odbc="no"
+fi
+
+
+if test "$use_dlz_odbc" = "yes"
+then
+ # User did not specify a path - guess it
+ odbcdirs="/usr /usr/local /usr/pkg"
+ for d in $odbcdirs
+ do
+ if test -f $d/include/sql.h -a -f $d/lib/libodbc.a
+ then
+ use_dlz_odbc=$d
+ break
+ fi
+ done
+fi
+
+case "$use_dlz_odbc" in
+ no)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ yes)
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ { { echo "$as_me:$LINENO: error: ODBC headers were not found in any of $odbcdirs; use --with-dlz-odbc=/path" >&5
+echo "$as_me: error: ODBC headers were not found in any of $odbcdirs; use --with-dlz-odbc=/path" >&2;}
+ { (exit 1); exit 1; }; }
+ ;;
+ *)
+
+ USE_DLZ="$USE_DLZ -DDLZ_ODBC"
+ for i in dlz_odbc_driver
+ do
+ DLZ_DRIVER_SRCS="$DLZ_DRIVER_SRCS $dlzdir/$i.c"
+ DLZ_DRIVER_OBJS="$DLZ_DRIVER_OBJS $i.$O"
+ done
+ if test -n "-I$use_dlz_odbc/include"
+ then
+ DLZ_DRIVER_INCLUDES="$DLZ_DRIVER_INCLUDES -I$use_dlz_odbc/include"
+ fi
+ if test -n "-L$use_dlz_odbc/lib -lodbc"
+ then
+ DLZ_DRIVER_LIBS="$DLZ_DRIVER_LIBS -L$use_dlz_odbc/lib -lodbc"
+ fi
+
+
+ { echo "$as_me:$LINENO: result: using ODBC from $use_dlz_odbc" >&5
+echo "${ECHO_T}using ODBC from $use_dlz_odbc" >&6; }
+ ;;
+esac
+
+
+#
+# Was --with-dlz-stub specified?
+#
+
+{ echo "$as_me:$LINENO: checking for stub DLZ driver" >&5
+echo $ECHO_N "checking for stub DLZ driver... $ECHO_C" >&6; }
+
+# Check whether --with-dlz_stub was given.
+if test "${with_dlz_stub+set}" = set; then
+ withval=$with_dlz_stub; use_dlz_stub="$withval"
+else
+ use_dlz_stub="no"
+fi
+
+
+case "$use_dlz_stub" in
+ no)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+ *)
+
+
+ USE_DLZ="$USE_DLZ -DDLZ_STUB"
+ for i in dlz_stub_driver
+ do
+ DLZ_DRIVER_SRCS="$DLZ_DRIVER_SRCS $dlzdir/$i.c"
+ DLZ_DRIVER_OBJS="$DLZ_DRIVER_OBJS $i.$O"
+ done
+ if test -n ""
+ then
+ DLZ_DRIVER_INCLUDES="$DLZ_DRIVER_INCLUDES "
+ fi
+ if test -n ""
+ then
+ DLZ_DRIVER_LIBS="$DLZ_DRIVER_LIBS "
+ fi
+
+
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ;;
+esac
+
+
+# Add any additional DLZ drivers here.
+
+#
+# Finally, some generic stuff that applies to all drivers, assuming
+# we're compiling DLZ at all.
+#
+if test -n "$USE_DLZ"
+then
+ #
+ # Where to find DLZ driver header files.
+ #
+ DLZ_DRIVER_INCLUDES="-I$dlzdir/include $DLZ_DRIVER_INCLUDES"
+
+ #
+ # Initialization and shutdown wrappers, helper functions.
+ #
+ DLZ_DRIVER_SRCS="$dlzdir/dlz_drivers.c $dlzdir/sdlz_helper.c $DLZ_DRIVER_SRCS"
+ DLZ_DRIVER_OBJS="dlz_drivers.$O sdlz_helper.$O $DLZ_DRIVER_OBJS"
+fi
+
+
+{ echo "$as_me:$LINENO: checking for DLZ" >&5
+echo $ECHO_N "checking for DLZ... $ECHO_C" >&6; }
+
+if test -n "$USE_DLZ"
+then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ USE_DLZ="-DDLZ $USE_DLZ"
+ DLZ_DRIVER_RULES=contrib/dlz/drivers/rules
+ ac_config_files="$ac_config_files $DLZ_DRIVER_RULES"
+
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ DLZ_DRIVER_RULES=/dev/null
+fi
+
+
+
+
+
+
+
+
+if test "$cross_compiling" = "yes"; then
+ if test -z "$BUILD_CC"; then
+ { { echo "$as_me:$LINENO: error: BUILD_CC not set" >&5
+echo "$as_me: error: BUILD_CC not set" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ BUILD_CFLAGS="$BUILD_CFLAGS"
+ BUILD_CPPFLAGS="$BUILD_CPPFLAGS"
+ BUILD_LDFLAGS="$BUILD_LDFLAGS"
+ BUILD_LIBS="$BUILD_LIBS"
+else
+ BUILD_CC="$CC"
+ BUILD_CFLAGS="$CFLAGS"
+ BUILD_CPPFLAGS="$CPPFLAGS $GEN_NEED_OPTARG"
+ BUILD_LDFLAGS="$LDFLAGS"
+ BUILD_LIBS="$LIBS"
+fi
+
+NEWFLAGS=""
+for e in $BUILD_LDFLAGS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ solaris*)
+ ee=`echo $e | sed -e 's%^-L%-R%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+BUILD_LDFLAGS="$NEWFLAGS"
+
+NEWFLAGS=""
+for e in $DNS_GSSAPI_LIBS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ solaris*)
+ ee=`echo $e | sed -e 's%^-L%-R%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+DNS_GSSAPI_LIBS="$NEWFLAGS"
+
+NEWFLAGS=""
+for e in $DNS_CRYPTO_LIBS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ solaris*)
+ ee=`echo $e | sed -e 's%^-L%-R%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+DNS_CRYPTO_LIBS="$NEWFLAGS"
+
+
+
+
+
+
+
+#
+# Commands to run at the end of config.status.
+# Don't just put these into configure, it won't work right if somebody
+# runs config.status directly (which autoconf allows).
+#
+
+ac_config_commands="$ac_config_commands chmod"
+
+
+#
+# Files to configure. These are listed here because we used to
+# specify them as arguments to AC_OUTPUT. It's (now) ok to move these
+# elsewhere if there's a good reason for doing so.
+#
+
+ac_config_files="$ac_config_files Makefile make/Makefile make/mkdep lib/Makefile lib/isc/Makefile lib/isc/include/Makefile lib/isc/include/isc/Makefile lib/isc/include/isc/platform.h 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 lib/lwres/include/lwres/netdb.h lib/lwres/include/lwres/platform.h lib/lwres/man/Makefile lib/lwres/unix/Makefile lib/lwres/unix/include/Makefile lib/lwres/unix/include/lwres/Makefile 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/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"
+
+
+#
+# Do it
+#
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "make/rules") CONFIG_FILES="$CONFIG_FILES make/rules" ;;
+ "make/includes") CONFIG_FILES="$CONFIG_FILES make/includes" ;;
+ "contrib/dlz/bin/dlzbdb/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/dlz/bin/dlzbdb/Makefile" ;;
+ "$DLZ_DRIVER_RULES") CONFIG_FILES="$CONFIG_FILES $DLZ_DRIVER_RULES" ;;
+ "chmod") CONFIG_COMMANDS="$CONFIG_COMMANDS chmod" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "make/Makefile") CONFIG_FILES="$CONFIG_FILES make/Makefile" ;;
+ "make/mkdep") CONFIG_FILES="$CONFIG_FILES make/mkdep" ;;
+ "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
+ "lib/isc/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/Makefile" ;;
+ "lib/isc/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/include/Makefile" ;;
+ "lib/isc/include/isc/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/include/isc/Makefile" ;;
+ "lib/isc/include/isc/platform.h") CONFIG_FILES="$CONFIG_FILES lib/isc/include/isc/platform.h" ;;
+ "lib/isc/unix/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/unix/Makefile" ;;
+ "lib/isc/unix/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/unix/include/Makefile" ;;
+ "lib/isc/unix/include/isc/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/unix/include/isc/Makefile" ;;
+ "lib/isc/nls/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/nls/Makefile" ;;
+ "lib/isc/$thread_dir/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/$thread_dir/Makefile" ;;
+ "lib/isc/$thread_dir/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/$thread_dir/include/Makefile" ;;
+ "lib/isc/$thread_dir/include/isc/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/$thread_dir/include/isc/Makefile" ;;
+ "lib/isc/$arch/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/$arch/Makefile" ;;
+ "lib/isc/$arch/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/$arch/include/Makefile" ;;
+ "lib/isc/$arch/include/isc/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isc/$arch/include/isc/Makefile" ;;
+ "lib/isccc/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isccc/Makefile" ;;
+ "lib/isccc/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isccc/include/Makefile" ;;
+ "lib/isccc/include/isccc/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isccc/include/isccc/Makefile" ;;
+ "lib/isccfg/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isccfg/Makefile" ;;
+ "lib/isccfg/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isccfg/include/Makefile" ;;
+ "lib/isccfg/include/isccfg/Makefile") CONFIG_FILES="$CONFIG_FILES lib/isccfg/include/isccfg/Makefile" ;;
+ "lib/dns/Makefile") CONFIG_FILES="$CONFIG_FILES lib/dns/Makefile" ;;
+ "lib/dns/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/dns/include/Makefile" ;;
+ "lib/dns/include/dns/Makefile") CONFIG_FILES="$CONFIG_FILES lib/dns/include/dns/Makefile" ;;
+ "lib/dns/include/dst/Makefile") CONFIG_FILES="$CONFIG_FILES lib/dns/include/dst/Makefile" ;;
+ "lib/bind9/Makefile") CONFIG_FILES="$CONFIG_FILES lib/bind9/Makefile" ;;
+ "lib/bind9/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/bind9/include/Makefile" ;;
+ "lib/bind9/include/bind9/Makefile") CONFIG_FILES="$CONFIG_FILES lib/bind9/include/bind9/Makefile" ;;
+ "lib/lwres/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lwres/Makefile" ;;
+ "lib/lwres/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lwres/include/Makefile" ;;
+ "lib/lwres/include/lwres/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lwres/include/lwres/Makefile" ;;
+ "lib/lwres/include/lwres/netdb.h") CONFIG_FILES="$CONFIG_FILES lib/lwres/include/lwres/netdb.h" ;;
+ "lib/lwres/include/lwres/platform.h") CONFIG_FILES="$CONFIG_FILES lib/lwres/include/lwres/platform.h" ;;
+ "lib/lwres/man/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lwres/man/Makefile" ;;
+ "lib/lwres/unix/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lwres/unix/Makefile" ;;
+ "lib/lwres/unix/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lwres/unix/include/Makefile" ;;
+ "lib/lwres/unix/include/lwres/Makefile") CONFIG_FILES="$CONFIG_FILES lib/lwres/unix/include/lwres/Makefile" ;;
+ "lib/tests/Makefile") CONFIG_FILES="$CONFIG_FILES lib/tests/Makefile" ;;
+ "lib/tests/include/Makefile") CONFIG_FILES="$CONFIG_FILES lib/tests/include/Makefile" ;;
+ "lib/tests/include/tests/Makefile") CONFIG_FILES="$CONFIG_FILES lib/tests/include/tests/Makefile" ;;
+ "bin/Makefile") CONFIG_FILES="$CONFIG_FILES bin/Makefile" ;;
+ "bin/check/Makefile") CONFIG_FILES="$CONFIG_FILES bin/check/Makefile" ;;
+ "bin/named/Makefile") CONFIG_FILES="$CONFIG_FILES bin/named/Makefile" ;;
+ "bin/named/unix/Makefile") CONFIG_FILES="$CONFIG_FILES bin/named/unix/Makefile" ;;
+ "bin/rndc/Makefile") CONFIG_FILES="$CONFIG_FILES bin/rndc/Makefile" ;;
+ "bin/rndc/unix/Makefile") CONFIG_FILES="$CONFIG_FILES bin/rndc/unix/Makefile" ;;
+ "bin/dig/Makefile") CONFIG_FILES="$CONFIG_FILES bin/dig/Makefile" ;;
+ "bin/nsupdate/Makefile") CONFIG_FILES="$CONFIG_FILES bin/nsupdate/Makefile" ;;
+ "bin/tests/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/Makefile" ;;
+ "bin/tests/names/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/names/Makefile" ;;
+ "bin/tests/master/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/master/Makefile" ;;
+ "bin/tests/rbt/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/rbt/Makefile" ;;
+ "bin/tests/db/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/db/Makefile" ;;
+ "bin/tests/tasks/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/tasks/Makefile" ;;
+ "bin/tests/timers/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/timers/Makefile" ;;
+ "bin/tests/dst/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/dst/Makefile" ;;
+ "bin/tests/mem/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/mem/Makefile" ;;
+ "bin/tests/net/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/net/Makefile" ;;
+ "bin/tests/sockaddr/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/sockaddr/Makefile" ;;
+ "bin/tests/system/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/Makefile" ;;
+ "bin/tests/system/conf.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/system/conf.sh" ;;
+ "bin/tests/system/lwresd/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/lwresd/Makefile" ;;
+ "bin/tests/system/tkey/Makefile") CONFIG_FILES="$CONFIG_FILES bin/tests/system/tkey/Makefile" ;;
+ "bin/tests/headerdep_test.sh") CONFIG_FILES="$CONFIG_FILES bin/tests/headerdep_test.sh" ;;
+ "bin/dnssec/Makefile") CONFIG_FILES="$CONFIG_FILES bin/dnssec/Makefile" ;;
+ "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+ "doc/arm/Makefile") CONFIG_FILES="$CONFIG_FILES doc/arm/Makefile" ;;
+ "doc/misc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/misc/Makefile" ;;
+ "isc-config.sh") CONFIG_FILES="$CONFIG_FILES isc-config.sh" ;;
+ "doc/xsl/Makefile") CONFIG_FILES="$CONFIG_FILES doc/xsl/Makefile" ;;
+ "doc/xsl/isc-docbook-chunk.xsl") CONFIG_FILES="$CONFIG_FILES doc/xsl/isc-docbook-chunk.xsl" ;;
+ "doc/xsl/isc-docbook-html.xsl") CONFIG_FILES="$CONFIG_FILES doc/xsl/isc-docbook-html.xsl" ;;
+ "doc/xsl/isc-docbook-latex.xsl") CONFIG_FILES="$CONFIG_FILES doc/xsl/isc-docbook-latex.xsl" ;;
+ "doc/xsl/isc-manpage.xsl") CONFIG_FILES="$CONFIG_FILES doc/xsl/isc-manpage.xsl" ;;
+ "doc/doxygen/Doxyfile") CONFIG_FILES="$CONFIG_FILES doc/doxygen/Doxyfile" ;;
+ "doc/doxygen/Makefile") CONFIG_FILES="$CONFIG_FILES doc/doxygen/Makefile" ;;
+ "doc/doxygen/doxygen-input-filter") CONFIG_FILES="$CONFIG_FILES doc/doxygen/doxygen-input-filter" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+# Create sed commands to just substitute file output variables.
+
+# Remaining file output variables are in a fragment that also has non-file
+# output varibles.
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+build!$build$ac_delim
+build_cpu!$build_cpu$ac_delim
+build_vendor!$build_vendor$ac_delim
+build_os!$build_os$ac_delim
+host!$host$ac_delim
+host_cpu!$host_cpu$ac_delim
+host_vendor!$host_vendor$ac_delim
+host_os!$host_os$ac_delim
+SET_MAKE!$SET_MAKE$ac_delim
+RANLIB!$RANLIB$ac_delim
+INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
+INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
+INSTALL_DATA!$INSTALL_DATA$ac_delim
+LN_S!$LN_S$ac_delim
+STD_CINCLUDES!$STD_CINCLUDES$ac_delim
+STD_CDEFINES!$STD_CDEFINES$ac_delim
+STD_CWARNINGS!$STD_CWARNINGS$ac_delim
+CCOPT!$CCOPT$ac_delim
+AR!$AR$ac_delim
+ARFLAGS!$ARFLAGS$ac_delim
+LN!$LN$ac_delim
+ETAGS!$ETAGS$ac_delim
+PERL!$PERL$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 70; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+/^[ ]*@BIND9_MAKE_INCLUDES@[ ]*$/{
+r $BIND9_MAKE_INCLUDES
+d
+}
+/^[ ]*@BIND9_MAKE_RULES@[ ]*$/{
+r $BIND9_MAKE_RULES
+d
+}
+/^[ ]*@LIBISC_API@[ ]*$/{
+r $LIBISC_API
+d
+}
+/^[ ]*@LIBISCCC_API@[ ]*$/{
+r $LIBISCCC_API
+d
+}
+/^[ ]*@LIBISCCFG_API@[ ]*$/{
+r $LIBISCCFG_API
+d
+}
+/^[ ]*@LIBDNS_API@[ ]*$/{
+r $LIBDNS_API
+d
+}
+/^[ ]*@LIBBIND9_API@[ ]*$/{
+r $LIBBIND9_API
+d
+}
+/^[ ]*@LIBLWRES_API@[ ]*$/{
+r $LIBLWRES_API
+d
+}
+/^[ ]*@DLZ_DRIVER_RULES@[ ]*$/{
+r $DLZ_DRIVER_RULES
+d
+}
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+ISC_SOCKADDR_LEN_T!$ISC_SOCKADDR_LEN_T$ac_delim
+ISC_PLATFORM_HAVELONGLONG!$ISC_PLATFORM_HAVELONGLONG$ac_delim
+ISC_PLATFORM_HAVELIFCONF!$ISC_PLATFORM_HAVELIFCONF$ac_delim
+ISC_PLATFORM_HAVEKQUEUE!$ISC_PLATFORM_HAVEKQUEUE$ac_delim
+ISC_PLATFORM_HAVEEPOLL!$ISC_PLATFORM_HAVEEPOLL$ac_delim
+ISC_PLATFORM_HAVEDEVPOLL!$ISC_PLATFORM_HAVEDEVPOLL$ac_delim
+ISC_PLATFORM_NEEDSYSSELECTH!$ISC_PLATFORM_NEEDSYSSELECTH$ac_delim
+LWRES_PLATFORM_NEEDSYSSELECTH!$LWRES_PLATFORM_NEEDSYSSELECTH$ac_delim
+USE_OPENSSL!$USE_OPENSSL$ac_delim
+DST_OPENSSL_INC!$DST_OPENSSL_INC$ac_delim
+USE_PKCS11!$USE_PKCS11$ac_delim
+ISC_PLATFORM_HAVEGSSAPI!$ISC_PLATFORM_HAVEGSSAPI$ac_delim
+ISC_PLATFORM_GSSAPIHEADER!$ISC_PLATFORM_GSSAPIHEADER$ac_delim
+USE_GSSAPI!$USE_GSSAPI$ac_delim
+DST_GSSAPI_INC!$DST_GSSAPI_INC$ac_delim
+DNS_GSSAPI_LIBS!$DNS_GSSAPI_LIBS$ac_delim
+DNS_CRYPTO_LIBS!$DNS_CRYPTO_LIBS$ac_delim
+ALWAYS_DEFINES!$ALWAYS_DEFINES$ac_delim
+ISC_PLATFORM_USETHREADS!$ISC_PLATFORM_USETHREADS$ac_delim
+ISC_THREAD_DIR!$ISC_THREAD_DIR$ac_delim
+MKDEPCC!$MKDEPCC$ac_delim
+MKDEPCFLAGS!$MKDEPCFLAGS$ac_delim
+MKDEPPROG!$MKDEPPROG$ac_delim
+IRIX_DNSSEC_WARNINGS_HACK!$IRIX_DNSSEC_WARNINGS_HACK$ac_delim
+purify_path!$purify_path$ac_delim
+PURIFY!$PURIFY$ac_delim
+ECHO!$ECHO$ac_delim
+STRIP!$STRIP$ac_delim
+CXX!$CXX$ac_delim
+CXXFLAGS!$CXXFLAGS$ac_delim
+ac_ct_CXX!$ac_ct_CXX$ac_delim
+CXXCPP!$CXXCPP$ac_delim
+F77!$F77$ac_delim
+FFLAGS!$FFLAGS$ac_delim
+ac_ct_F77!$ac_ct_F77$ac_delim
+LIBTOOL!$LIBTOOL$ac_delim
+O!$O$ac_delim
+A!$A$ac_delim
+SA!$SA$ac_delim
+LIBTOOL_MKDEP_SED!$LIBTOOL_MKDEP_SED$ac_delim
+LIBTOOL_MODE_COMPILE!$LIBTOOL_MODE_COMPILE$ac_delim
+LIBTOOL_MODE_INSTALL!$LIBTOOL_MODE_INSTALL$ac_delim
+LIBTOOL_MODE_LINK!$LIBTOOL_MODE_LINK$ac_delim
+LIBTOOL_ALLOW_UNDEFINED!$LIBTOOL_ALLOW_UNDEFINED$ac_delim
+LIBTOOL_IN_MAIN!$LIBTOOL_IN_MAIN$ac_delim
+ISC_PLATFORM_HAVEIPV6!$ISC_PLATFORM_HAVEIPV6$ac_delim
+LWRES_PLATFORM_HAVEIPV6!$LWRES_PLATFORM_HAVEIPV6$ac_delim
+ISC_PLATFORM_NEEDNETINETIN6H!$ISC_PLATFORM_NEEDNETINETIN6H$ac_delim
+LWRES_PLATFORM_NEEDNETINETIN6H!$LWRES_PLATFORM_NEEDNETINETIN6H$ac_delim
+ISC_PLATFORM_NEEDNETINET6IN6H!$ISC_PLATFORM_NEEDNETINET6IN6H$ac_delim
+LWRES_PLATFORM_NEEDNETINET6IN6H!$LWRES_PLATFORM_NEEDNETINET6IN6H$ac_delim
+ISC_PLATFORM_HAVEINADDR6!$ISC_PLATFORM_HAVEINADDR6$ac_delim
+LWRES_PLATFORM_HAVEINADDR6!$LWRES_PLATFORM_HAVEINADDR6$ac_delim
+ISC_PLATFORM_NEEDIN6ADDRANY!$ISC_PLATFORM_NEEDIN6ADDRANY$ac_delim
+LWRES_PLATFORM_NEEDIN6ADDRANY!$LWRES_PLATFORM_NEEDIN6ADDRANY$ac_delim
+ISC_PLATFORM_NEEDIN6ADDRLOOPBACK!$ISC_PLATFORM_NEEDIN6ADDRLOOPBACK$ac_delim
+LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK!$LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK$ac_delim
+ISC_PLATFORM_HAVEIN6PKTINFO!$ISC_PLATFORM_HAVEIN6PKTINFO$ac_delim
+ISC_PLATFORM_FIXIN6ISADDR!$ISC_PLATFORM_FIXIN6ISADDR$ac_delim
+ISC_IPV6_H!$ISC_IPV6_H$ac_delim
+ISC_IPV6_O!$ISC_IPV6_O$ac_delim
+ISC_ISCIPV6_O!$ISC_ISCIPV6_O$ac_delim
+ISC_IPV6_C!$ISC_IPV6_C$ac_delim
+LWRES_HAVE_SIN6_SCOPE_ID!$LWRES_HAVE_SIN6_SCOPE_ID$ac_delim
+ISC_PLATFORM_HAVESCOPEID!$ISC_PLATFORM_HAVESCOPEID$ac_delim
+ISC_PLATFORM_HAVEIF_LADDRREQ!$ISC_PLATFORM_HAVEIF_LADDRREQ$ac_delim
+ISC_PLATFORM_HAVEIF_LADDRCONF!$ISC_PLATFORM_HAVEIF_LADDRCONF$ac_delim
+ISC_PLATFORM_NEEDNTOP!$ISC_PLATFORM_NEEDNTOP$ac_delim
+ISC_PLATFORM_NEEDPTON!$ISC_PLATFORM_NEEDPTON$ac_delim
+ISC_PLATFORM_NEEDATON!$ISC_PLATFORM_NEEDATON$ac_delim
+ISC_PLATFORM_HAVESALEN!$ISC_PLATFORM_HAVESALEN$ac_delim
+LWRES_PLATFORM_HAVESALEN!$LWRES_PLATFORM_HAVESALEN$ac_delim
+ISC_PLATFORM_MSGHDRFLAVOR!$ISC_PLATFORM_MSGHDRFLAVOR$ac_delim
+ISC_PLATFORM_NEEDPORTT!$ISC_PLATFORM_NEEDPORTT$ac_delim
+ISC_LWRES_NEEDADDRINFO!$ISC_LWRES_NEEDADDRINFO$ac_delim
+ISC_LWRES_NEEDRRSETINFO!$ISC_LWRES_NEEDRRSETINFO$ac_delim
+ISC_LWRES_SETHOSTENTINT!$ISC_LWRES_SETHOSTENTINT$ac_delim
+ISC_LWRES_ENDHOSTENTINT!$ISC_LWRES_ENDHOSTENTINT$ac_delim
+ISC_LWRES_GETNETBYADDRINADDR!$ISC_LWRES_GETNETBYADDRINADDR$ac_delim
+ISC_LWRES_SETNETENTINT!$ISC_LWRES_SETNETENTINT$ac_delim
+ISC_LWRES_ENDNETENTINT!$ISC_LWRES_ENDNETENTINT$ac_delim
+ISC_LWRES_GETHOSTBYADDRVOID!$ISC_LWRES_GETHOSTBYADDRVOID$ac_delim
+ISC_LWRES_NEEDHERRNO!$ISC_LWRES_NEEDHERRNO$ac_delim
+ISC_LWRES_GETIPNODEPROTO!$ISC_LWRES_GETIPNODEPROTO$ac_delim
+ISC_LWRES_GETADDRINFOPROTO!$ISC_LWRES_GETADDRINFOPROTO$ac_delim
+ISC_LWRES_GETNAMEINFOPROTO!$ISC_LWRES_GETNAMEINFOPROTO$ac_delim
+ISC_PLATFORM_NEEDSTRSEP!$ISC_PLATFORM_NEEDSTRSEP$ac_delim
+ISC_PLATFORM_NEEDMEMMOVE!$ISC_PLATFORM_NEEDMEMMOVE$ac_delim
+ISC_PLATFORM_NEEDSTRTOUL!$ISC_PLATFORM_NEEDSTRTOUL$ac_delim
+LWRES_PLATFORM_NEEDSTRTOUL!$LWRES_PLATFORM_NEEDSTRTOUL$ac_delim
+GENRANDOMLIB!$GENRANDOMLIB$ac_delim
+ISC_PLATFORM_NEEDSTRLCPY!$ISC_PLATFORM_NEEDSTRLCPY$ac_delim
+ISC_PLATFORM_NEEDSTRLCAT!$ISC_PLATFORM_NEEDSTRLCAT$ac_delim
+ISC_PLATFORM_NEEDSPRINTF!$ISC_PLATFORM_NEEDSPRINTF$ac_delim
+LWRES_PLATFORM_NEEDSPRINTF!$LWRES_PLATFORM_NEEDSPRINTF$ac_delim
+ISC_PLATFORM_NEEDVSNPRINTF!$ISC_PLATFORM_NEEDVSNPRINTF$ac_delim
+LWRES_PLATFORM_NEEDVSNPRINTF!$LWRES_PLATFORM_NEEDVSNPRINTF$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+CEOF$ac_eof
+_ACEOF
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+ISC_EXTRA_OBJS!$ISC_EXTRA_OBJS$ac_delim
+ISC_EXTRA_SRCS!$ISC_EXTRA_SRCS$ac_delim
+USE_ISC_SPNEGO!$USE_ISC_SPNEGO$ac_delim
+DST_EXTRA_OBJS!$DST_EXTRA_OBJS$ac_delim
+DST_EXTRA_SRCS!$DST_EXTRA_SRCS$ac_delim
+ISC_PLATFORM_QUADFORMAT!$ISC_PLATFORM_QUADFORMAT$ac_delim
+LWRES_PLATFORM_QUADFORMAT!$LWRES_PLATFORM_QUADFORMAT$ac_delim
+ISC_PLATFORM_HAVESYSUNH!$ISC_PLATFORM_HAVESYSUNH$ac_delim
+ISC_PLATFORM_RLIMITTYPE!$ISC_PLATFORM_RLIMITTYPE$ac_delim
+ISC_PLATFORM_USEDECLSPEC!$ISC_PLATFORM_USEDECLSPEC$ac_delim
+LWRES_PLATFORM_USEDECLSPEC!$LWRES_PLATFORM_USEDECLSPEC$ac_delim
+ISC_PLATFORM_BRACEPTHREADONCEINIT!$ISC_PLATFORM_BRACEPTHREADONCEINIT$ac_delim
+ISC_PLATFORM_HAVESTRINGSH!$ISC_PLATFORM_HAVESTRINGSH$ac_delim
+ISC_PLATFORM_HAVEIFNAMETOINDEX!$ISC_PLATFORM_HAVEIFNAMETOINDEX$ac_delim
+ISC_PLATFORM_HAVEXADD!$ISC_PLATFORM_HAVEXADD$ac_delim
+ISC_PLATFORM_HAVEXADDQ!$ISC_PLATFORM_HAVEXADDQ$ac_delim
+ISC_PLATFORM_HAVECMPXCHG!$ISC_PLATFORM_HAVECMPXCHG$ac_delim
+ISC_PLATFORM_HAVEATOMICSTORE!$ISC_PLATFORM_HAVEATOMICSTORE$ac_delim
+ISC_PLATFORM_USEGCCASM!$ISC_PLATFORM_USEGCCASM$ac_delim
+ISC_PLATFORM_USEOSFASM!$ISC_PLATFORM_USEOSFASM$ac_delim
+ISC_PLATFORM_USESTDASM!$ISC_PLATFORM_USESTDASM$ac_delim
+ISC_PLATFORM_USEMACASM!$ISC_PLATFORM_USEMACASM$ac_delim
+ISC_ARCH_DIR!$ISC_ARCH_DIR$ac_delim
+LATEX!$LATEX$ac_delim
+PDFLATEX!$PDFLATEX$ac_delim
+W3M!$W3M$ac_delim
+XSLTPROC!$XSLTPROC$ac_delim
+XMLLINT!$XMLLINT$ac_delim
+DOXYGEN!$DOXYGEN$ac_delim
+XSLT_DOCBOOK_STYLE_HTML!$XSLT_DOCBOOK_STYLE_HTML$ac_delim
+XSLT_DOCBOOK_STYLE_XHTML!$XSLT_DOCBOOK_STYLE_XHTML$ac_delim
+XSLT_DOCBOOK_STYLE_MAN!$XSLT_DOCBOOK_STYLE_MAN$ac_delim
+XSLT_DOCBOOK_CHUNK_HTML!$XSLT_DOCBOOK_CHUNK_HTML$ac_delim
+XSLT_DOCBOOK_CHUNK_XHTML!$XSLT_DOCBOOK_CHUNK_XHTML$ac_delim
+XSLT_DOCBOOK_CHUNKTOC_HTML!$XSLT_DOCBOOK_CHUNKTOC_HTML$ac_delim
+XSLT_DOCBOOK_CHUNKTOC_XHTML!$XSLT_DOCBOOK_CHUNKTOC_XHTML$ac_delim
+XSLT_DOCBOOK_MAKETOC_HTML!$XSLT_DOCBOOK_MAKETOC_HTML$ac_delim
+XSLT_DOCBOOK_MAKETOC_XHTML!$XSLT_DOCBOOK_MAKETOC_XHTML$ac_delim
+XSLT_DB2LATEX_STYLE!$XSLT_DB2LATEX_STYLE$ac_delim
+XSLT_DB2LATEX_ADMONITIONS!$XSLT_DB2LATEX_ADMONITIONS$ac_delim
+IDNLIBS!$IDNLIBS$ac_delim
+BIND9_TOP_BUILDDIR!$BIND9_TOP_BUILDDIR$ac_delim
+BIND9_ISC_BUILDINCLUDE!$BIND9_ISC_BUILDINCLUDE$ac_delim
+BIND9_ISCCC_BUILDINCLUDE!$BIND9_ISCCC_BUILDINCLUDE$ac_delim
+BIND9_ISCCFG_BUILDINCLUDE!$BIND9_ISCCFG_BUILDINCLUDE$ac_delim
+BIND9_DNS_BUILDINCLUDE!$BIND9_DNS_BUILDINCLUDE$ac_delim
+BIND9_LWRES_BUILDINCLUDE!$BIND9_LWRES_BUILDINCLUDE$ac_delim
+BIND9_BIND9_BUILDINCLUDE!$BIND9_BIND9_BUILDINCLUDE$ac_delim
+BIND9_VERSION!$BIND9_VERSION$ac_delim
+BIND9_CONFIGARGS!$BIND9_CONFIGARGS$ac_delim
+PG_CONFIG!$PG_CONFIG$ac_delim
+USE_DLZ!$USE_DLZ$ac_delim
+DLZ_DRIVER_INCLUDES!$DLZ_DRIVER_INCLUDES$ac_delim
+DLZ_DRIVER_LIBS!$DLZ_DRIVER_LIBS$ac_delim
+DLZ_DRIVER_SRCS!$DLZ_DRIVER_SRCS$ac_delim
+DLZ_DRIVER_OBJS!$DLZ_DRIVER_OBJS$ac_delim
+BUILD_CC!$BUILD_CC$ac_delim
+BUILD_CFLAGS!$BUILD_CFLAGS$ac_delim
+BUILD_CPPFLAGS!$BUILD_CPPFLAGS$ac_delim
+BUILD_LDFLAGS!$BUILD_LDFLAGS$ac_delim
+BUILD_LIBS!$BUILD_LIBS$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 63; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-3.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" | sed -f "$tmp/subs-3.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+ ;;
+
+ :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5
+echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "chmod":C) chmod a+x isc-config.sh doc/doxygen/doxygen-input-filter ;;
+
+ esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+if test "X$OPENSSL_WARNING" != "X"; then
+cat << \EOF
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+WARNING WARNING
+WARNING Your OpenSSL crypto library may be vulnerable to WARNING
+WARNING one or more of the the following known security WARNING
+WARNING flaws: WARNING
+WARNING WARNING
+WARNING CAN-2002-0659, CAN-2006-4339, CVE-2006-2937 and WARNING
+WARNING CVE-2006-2940. WARNING
+WARNING WARNING
+WARNING It is recommended that you upgrade to OpenSSL WARNING
+WARNING version 0.9.8d/0.9.7l (or greater). WARNING
+WARNING WARNING
+WARNING You can disable this warning by specifying: WARNING
+WARNING WARNING
+WARNING --disable-openssl-version-check WARNING
+WARNING WARNING
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+EOF
+fi
+
+# Tell Emacs to edit this file in shell mode.
+# Local Variables:
+# mode: sh
+# End:
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..2a1163a
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,2990 @@
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.
+
+dnl
+AC_DIVERT_PUSH(1)dnl
+esyscmd([sed "s/^/# /" COPYRIGHT])dnl
+AC_DIVERT_POP()dnl
+
+AC_REVISION($Revision: 1.457 $)
+
+AC_INIT(lib/dns/name.c)
+AC_PREREQ(2.59)
+
+AC_CONFIG_HEADER(config.h)
+
+AC_CANONICAL_HOST
+
+AC_PROG_MAKE_SET
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+AC_PROG_LN_S
+
+AC_SUBST(STD_CINCLUDES)
+AC_SUBST(STD_CDEFINES)
+AC_SUBST(STD_CWARNINGS)
+AC_SUBST(CCOPT)
+
+# Warn if the user specified libbind, which is now deprecated
+AC_ARG_ENABLE(libbind, [ --enable-libbind deprecated])
+
+case "$enable_libbind" in
+ yes)
+ AC_MSG_ERROR(['libbind' is no longer part of the BIND 9 distribution.
+It is available from http://www.isc.org as a separate download.])
+ ;;
+ no|'')
+ ;;
+esac
+
+
+#
+# Make very sure that these are the first files processed by
+# config.status, since we use the processed output as the input for
+# AC_SUBST_FILE() subsitutions in other files.
+#
+AC_CONFIG_FILES([make/rules make/includes])
+
+AC_PATH_PROG(AR, ar)
+ARFLAGS="cruv"
+AC_SUBST(AR)
+AC_SUBST(ARFLAGS)
+
+# The POSIX ln(1) program. Non-POSIX systems may substitute
+# "copy" or something.
+LN=ln
+AC_SUBST(LN)
+
+case "$AR" in
+ "")
+ AC_MSG_ERROR([
+ar program not found. Please fix your PATH to include the directory in
+which ar resides, or set AR in the environment with the full path to ar.
+])
+
+ ;;
+esac
+
+#
+# Etags.
+#
+AC_PATH_PROGS(ETAGS, etags emacs-etags)
+
+#
+# Some systems, e.g. RH7, have the Exuberant Ctags etags instead of
+# GNU emacs etags, and it requires the -L flag.
+#
+if test "X$ETAGS" != "X"; then
+ AC_MSG_CHECKING(for Exuberant Ctags etags)
+ if $ETAGS --version 2>&1 | grep 'Exuberant Ctags' >/dev/null 2>&1; then
+ AC_MSG_RESULT(yes)
+ ETAGS="$ETAGS -L"
+ else
+ AC_MSG_RESULT(no)
+ fi
+fi
+AC_SUBST(ETAGS)
+
+#
+# Perl is optional; it is used only by some of the system test scripts.
+#
+AC_PATH_PROGS(PERL, perl5 perl)
+AC_SUBST(PERL)
+
+#
+# Special processing of paths depending on whether --prefix,
+# --sysconfdir or --localstatedir arguments were given. What's
+# desired is some compatibility with the way previous versions
+# of BIND built; they defaulted to /usr/local for most parts of
+# the installation, but named.boot/named.conf was in /etc
+# and named.pid was in /var/run.
+#
+# So ... if none of --prefix, --sysconfdir or --localstatedir are
+# specified, set things up that way. If --prefix is given, use
+# it for sysconfdir and localstatedir the way configure normally
+# would. To change the prefix for everything but leave named.conf
+# in /etc or named.pid in /var/run, then do this the usual configure way:
+# ./configure --prefix=/somewhere --sysconfdir=/etc
+# ./configure --prefix=/somewhere --localstatedir=/var
+#
+# To put named.conf and named.pid in /usr/local with everything else,
+# set the prefix explicitly to /usr/local even though that's the default:
+# ./configure --prefix=/usr/local
+#
+case "$prefix" in
+ NONE)
+ case "$sysconfdir" in
+ '${prefix}/etc')
+ sysconfdir=/etc
+ ;;
+ esac
+ case "$localstatedir" in
+ '${prefix}/var')
+ localstatedir=/var
+ ;;
+ esac
+ ;;
+esac
+
+#
+# Make sure INSTALL uses an absolute path, else it will be wrong in all
+# Makefiles, since they use make/rules.in and INSTALL will be adjusted by
+# configure based on the location of the file where it is substituted.
+# Since in BIND9 INSTALL is only substituted into make/rules.in, an immediate
+# subdirectory of install-sh, This relative path will be wrong for all
+# directories more than one level down from install-sh.
+#
+case "$INSTALL" in
+ /*)
+ ;;
+ *)
+ #
+ # Not all systems have dirname.
+ #
+ changequote({, })
+ ac_dir="`echo $INSTALL | sed 's%/[^/]*$%%'`"
+ changequote([, ])
+
+ ac_prog="`echo $INSTALL | sed 's%.*/%%'`"
+ test "$ac_dir" = "$ac_prog" && ac_dir=.
+ test -d "$ac_dir" && ac_dir="`(cd \"$ac_dir\" && pwd)`"
+ INSTALL="$ac_dir/$ac_prog"
+ ;;
+esac
+
+#
+# On these hosts, we really want to use cc, not gcc, even if it is
+# found. The gcc that these systems have will not correctly handle
+# pthreads.
+#
+# However, if the user sets $CC to be something, let that override
+# our change.
+#
+if test "X$CC" = "X" ; then
+ case "$host" in
+ *-dec-osf*)
+ CC="cc"
+ ;;
+ *-solaris*)
+ # Use Sun's cc if it is available, but watch
+ # out for /usr/ucb/cc; it will never be the right
+ # compiler to use.
+ #
+ # If setting CC here fails, the AC_PROG_CC done
+ # below might still find gcc.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ case "$ac_dir" in
+ /usr/ucb)
+ # exclude
+ ;;
+ *)
+ if test -f "$ac_dir/cc"; then
+ CC="$ac_dir/cc"
+ break
+ fi
+ ;;
+ esac
+ done
+ IFS="$ac_save_ifs"
+ ;;
+ *-hp-hpux*)
+ CC="cc"
+ ;;
+ mips-sgi-irix*)
+ CC="cc"
+ ;;
+ esac
+fi
+
+AC_PROG_CC
+
+#
+# gcc's optimiser is broken at -02 for ultrasparc
+#
+if test "$ac_env_CFLAGS_set" != set -a "X$GCC" = "Xyes"; then
+ case "$host" in
+ sparc-*)
+ CCFLAGS="-g -O1"
+ ;;
+ esac
+fi
+
+#
+# OS dependent CC flags
+#
+case "$host" in
+ # OSF 5.0: recv/send are only avaliable with -D_POSIX_PII_SOCKET or
+ # -D_XOPEN_SOURCE_EXTENDED.
+ *-dec-osf*)
+ STD_CDEFINES="$STD_CDEFINES -D_POSIX_PII_SOCKET"
+ CPPFLAGS="$CPPFLAGS -D_POSIX_PII_SOCKET"
+ ;;
+ #HP-UX: need -D_XOPEN_SOURCE_EXTENDED and -lxnet for CMSG macros
+ *-hp-hpux*)
+ STD_CDEFINES="$STD_CDEFINES -D_XOPEN_SOURCE_EXTENDED"
+ CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE_EXTENDED"
+ LIBS="-lxnet $LIBS"
+ ;;
+ # Solaris: need -D_XPG4_2 and -D__EXTENSIONS__ for CMSG macros
+ *-solaris*)
+ STD_CDEFINES="$STD_CDEFINES -D_XPG4_2 -D__EXTENSIONS__"
+ CPPFLAGS="$CPPFLAGS -D_XPG4_2 -D__EXTENSIONS__"
+ ;;
+ # POSIX doesn't include the IPv6 Advanced Socket API and glibc hides
+ # parts of the IPv6 Advanced Socket API as a result. This is stupid
+ # as it breaks how the two halves (Basic and Advanced) of the IPv6
+ # Socket API were designed to be used but we have to live with it.
+ # Define _GNU_SOURCE to pull in the IPv6 Advanced Socket API.
+ *-linux*)
+ STD_CDEFINES="$STD_CDEFINES -D_GNU_SOURCE"
+ CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
+ ;;
+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_includes_default
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+])
+
+AC_C_CONST
+AC_C_INLINE
+AC_C_VOLATILE
+AC_CHECK_FUNC(sysctlbyname, AC_DEFINE(HAVE_SYSCTLBYNAME))
+
+#
+# UnixWare 7.1.1 with the feature supplement to the UDK compiler
+# is reported to not support "static inline" (RT #1212).
+#
+AC_MSG_CHECKING(for static inline breakage)
+AC_TRY_COMPILE(, [
+ foo1();
+ }
+
+ static inline int foo1() {
+ return 0;
+ }
+
+ static inline int foo2() {
+ return foo1();
+ ],
+ [AC_MSG_RESULT(no)],
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE(inline, )])
+
+AC_TYPE_SIZE_T
+AC_CHECK_TYPE(ssize_t, int)
+AC_CHECK_TYPE(uintptr_t,unsigned long)
+AC_CHECK_TYPE(socklen_t,
+[AC_DEFINE(ISC_SOCKADDR_LEN_T, socklen_t)],
+[
+AC_TRY_COMPILE(
+[
+#include <sys/types.h>
+#include <sys/socket.h>
+int getsockname(int, struct sockaddr *, size_t *);
+],[],
+[AC_DEFINE(ISC_SOCKADDR_LEN_T, size_t)],
+[AC_DEFINE(ISC_SOCKADDR_LEN_T, int)])
+],
+[
+#include <sys/types.h>
+#include <sys/socket.h>
+])
+AC_SUBST(ISC_SOCKADDR_LEN_T)
+AC_HEADER_TIME
+AC_MSG_CHECKING(for long long)
+AC_TRY_COMPILE([],[long long i = 0; return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_HAVELONGLONG="#define ISC_PLATFORM_HAVELONGLONG 1"],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_HAVELONGLONG="#undef ISC_PLATFORM_HAVELONGLONG"])
+AC_SUBST(ISC_PLATFORM_HAVELONGLONG)
+
+#
+# check if we have lifconf
+#
+AC_MSG_CHECKING(for struct lifconf)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+],
+[
+struct lifconf lifconf;
+lifconf.lifc_len = 0;
+]
+,
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_HAVELIFCONF="#define ISC_PLATFORM_HAVELIFCONF 1"],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_HAVELIFCONF="#undef ISC_PLATFORM_HAVELIFCONF"])
+AC_SUBST(ISC_PLATFORM_HAVELIFCONF)
+
+#
+# check if we have kqueue
+#
+AC_ARG_ENABLE(kqueue,
+ [ --enable-kqueue use BSD kqueue when available [[default=yes]]],
+ want_kqueue="$enableval", want_kqueue="yes")
+case $want_kqueue in
+yes)
+ AC_CHECK_FUNC(kqueue, ac_cv_have_kqueue=yes, ac_cv_have_kqueue=no)
+ case $ac_cv_have_kqueue in
+ yes)
+ ISC_PLATFORM_HAVEKQUEUE="#define ISC_PLATFORM_HAVEKQUEUE 1"
+ ;;
+ *)
+ ISC_PLATFORM_HAVEKQUEUE="#undef ISC_PLATFORM_HAVEKQUEUE"
+ ;;
+ esac
+ ;;
+*)
+ ISC_PLATFORM_HAVEKQUEUE="#undef ISC_PLATFORM_HAVEKQUEUE"
+ ;;
+esac
+AC_SUBST(ISC_PLATFORM_HAVEKQUEUE)
+
+#
+# check if we have epoll. Linux kernel 2.4 has epoll_create() which fails,
+# so we need to try running the code, not just test its existence.
+#
+AC_ARG_ENABLE(epoll,
+ [ --enable-epoll use Linux epoll when available [[default=yes]]],
+ want_epoll="$enableval", want_epoll="yes")
+case $want_epoll in
+yes)
+ AC_MSG_CHECKING(epoll support)
+ AC_TRY_RUN([
+#include <sys/epoll.h>
+int main() {
+ if (epoll_create(1) < 0)
+ return (1);
+ return (0);
+}
+],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_HAVEEPOLL="#define ISC_PLATFORM_HAVEEPOLL 1"],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_HAVEEPOLL="#undef ISC_PLATFORM_HAVEEPOLL"])
+ ;;
+*)
+ ISC_PLATFORM_HAVEEPOLL="#undef ISC_PLATFORM_HAVEEPOLL"
+ ;;
+esac
+AC_SUBST(ISC_PLATFORM_HAVEEPOLL)
+
+#
+# check if we support /dev/poll
+#
+AC_ARG_ENABLE(devpoll,
+ [ --enable-devpoll use /dev/poll when available [[default=yes]]],
+ want_devpoll="$enableval", want_devpoll="yes")
+case $want_devpoll in
+yes)
+ AC_CHECK_HEADERS(sys/devpoll.h,
+ ISC_PLATFORM_HAVEDEVPOLL="#define ISC_PLATFORM_HAVEDEVPOLL 1"
+ ,
+ ISC_PLATFORM_HAVEDEVPOLL="#undef ISC_PLATFORM_HAVEDEVPOLL"
+ )
+ ;;
+*)
+ ISC_PLATFORM_HAVEDEVPOLL="#undef ISC_PLATFORM_HAVEDEVPOLL"
+ ;;
+esac
+AC_SUBST(ISC_PLATFORM_HAVEDEVPOLL)
+
+#
+# check if we need to #include sys/select.h explicitly
+#
+case $ac_cv_header_unistd_h in
+yes)
+AC_MSG_CHECKING(if unistd.h or sys/types.h defines fd_set)
+AC_TRY_COMPILE([
+#include <sys/types.h> /* Ultrix */
+#include <unistd.h>],
+[fd_set read_set; return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_NEEDSYSSELECTH="#undef ISC_PLATFORM_NEEDSYSSELECTH"
+ LWRES_PLATFORM_NEEDSYSSELECTH="#undef LWRES_PLATFORM_NEEDSYSSELECTH"],
+ [AC_MSG_RESULT(no)
+ case $ac_cv_header_sys_select_h in
+ yes)
+ ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
+ LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1"
+ ;;
+ no)
+ AC_MSG_ERROR([need either working unistd.h or sys/select.h])
+ ;;
+ esac
+ ])
+ ;;
+no)
+ case $ac_cv_header_sys_select_h in
+ yes)
+ ISC_PLATFORM_NEEDSYSSELECTH="#define ISC_PLATFORM_NEEDSYSSELECTH 1"
+ LWRES_PLATFORM_NEEDSYSSELECTH="#define LWRES_PLATFORM_NEEDSYSSELECTH 1"
+ ;;
+ no)
+ AC_MSG_ERROR([need either unistd.h or sys/select.h])
+ ;;
+ esac
+ ;;
+esac
+AC_SUBST(ISC_PLATFORM_NEEDSYSSELECTH)
+AC_SUBST(LWRES_PLATFORM_NEEDSYSSELECTH)
+
+#
+# Find the machine's endian flavor.
+#
+AC_C_BIGENDIAN
+
+
+#
+# was --with-openssl specified?
+#
+OPENSSL_WARNING=
+AC_MSG_CHECKING(for OpenSSL library)
+AC_ARG_WITH(openssl,
+[ --with-openssl[=PATH] Build with OpenSSL [yes|no|path].
+ (Required for DNSSEC)],
+ use_openssl="$withval", use_openssl="auto")
+
+openssldirs="/usr /usr/local /usr/local/ssl /usr/pkg /usr/sfw"
+if test "$use_openssl" = "auto"
+then
+ for d in $openssldirs
+ do
+ if test -f $d/include/openssl/opensslv.h
+ then
+ use_openssl=$d
+ break
+ fi
+ done
+fi
+case "$use_openssl" in
+ no)
+ AC_MSG_RESULT(no)
+ DST_OPENSSL_INC=""
+ USE_OPENSSL=""
+ ;;
+ auto)
+ DST_OPENSSL_INC=""
+ USE_OPENSSL=""
+ AC_MSG_RESULT(not found)
+ ;;
+ *)
+ if test "$use_openssl" = "yes"
+ then
+ # User did not specify a path - guess it
+ for d in $openssldirs
+ do
+ if test -f $d/include/openssl/opensslv.h
+ then
+ use_openssl=$d
+ break
+ fi
+ done
+ if test "$use_openssl" = "yes"
+ then
+ AC_MSG_RESULT(not found)
+ AC_MSG_ERROR(
+[OpenSSL was not found in any of $openssldirs; use --with-openssl=/path])
+ fi
+ fi
+ USE_OPENSSL='-DOPENSSL'
+ if test "$use_openssl" = "/usr"
+ then
+ DST_OPENSSL_INC=""
+ DNS_OPENSSL_LIBS="-lcrypto"
+ else
+ DST_OPENSSL_INC="-I$use_openssl/include"
+ case $host in
+ *-solaris*)
+ DNS_OPENSSL_LIBS="-L$use_openssl/lib -R$use_openssl/lib -lcrypto"
+ ;;
+ *-hp-hpux*)
+ DNS_OPENSSL_LIBS="-L$use_openssl/lib -Wl,+b: -lcrypto"
+ ;;
+ *-apple-darwin*)
+ #
+ # Apple's ld seaches for serially for dynamic
+ # then static libraries. This means you can't
+ # use -L to override dynamic system libraries
+ # with static ones when linking. Instead
+ # we specify a absolute path.
+ #
+ if test -f "$use_openssl/lib/libcrypto.dylib"
+ then
+ DNS_OPENSSL_LIBS="-L$use_openssl/lib -lcrypto"
+ else
+ DNS_OPENSSL_LIBS="$use_openssl/lib/libcrypto.a"
+ fi
+ ;;
+ *)
+ DNS_OPENSSL_LIBS="-L$use_openssl/lib -lcrypto"
+ ;;
+ esac
+ fi
+ AC_MSG_RESULT(using OpenSSL from $use_openssl/lib and $use_openssl/include)
+
+ saved_cflags="$CFLAGS"
+ saved_libs="$LIBS"
+ CFLAGS="$CFLAGS $DST_OPENSSL_INC"
+ LIBS="$LIBS $DNS_OPENSSL_LIBS"
+ AC_MSG_CHECKING(whether linking with OpenSSL works)
+ AC_TRY_RUN([
+#include <openssl/err.h>
+int main() {
+ ERR_clear_error();
+ return (0);
+}
+],
+ [AC_MSG_RESULT(yes)],
+ [AC_MSG_RESULT(no)
+ AC_MSG_ERROR(Could not run test program using OpenSSL from
+$use_openssl/lib and $use_openssl/include.
+Please check the argument to --with-openssl and your
+shared library configuration (e.g., LD_LIBRARY_PATH).)],
+ [AC_MSG_RESULT(assuming it does work on target platform)])
+
+ AC_MSG_CHECKING(whether linking with OpenSSL requires -ldl)
+ AC_TRY_LINK([
+#include <openssl/err.h>],
+[ DSO_METHOD_dlfcn(); ],
+ [AC_MSG_RESULT(no)],
+ [LIBS="$LIBS -ldl"
+ AC_TRY_LINK([
+#include <openssl/err.h>
+],[ DSO_METHOD_dlfcn(); ],
+ [AC_MSG_RESULT(yes)
+ DNS_OPENSSL_LIBS="$DNS_OPENSSL_LIBS -ldl"
+ ],
+ [AC_MSG_RESULT(unknown)
+ AC_MSG_ERROR(OpenSSL has unsupported dynamic loading)],
+ [AC_MSG_RESULT(assuming it does work on target platform)])
+ ],
+ [AC_MSG_RESULT(assuming it does work on target platform)]
+ )
+
+AC_ARG_ENABLE(openssl-version-check,
+[AC_HELP_STRING([--enable-openssl-version-check],
+ [Check OpenSSL Version @<:@default=yes@:>@])])
+case "$enable_openssl_version_check" in
+yes|'')
+ AC_MSG_CHECKING(OpenSSL library version)
+ AC_TRY_RUN([
+#include <stdio.h>
+#include <openssl/opensslv.h>
+int main() {
+ if ((OPENSSL_VERSION_NUMBER >= 0x009070cfL &&
+ OPENSSL_VERSION_NUMBER < 0x00908000L) ||
+ OPENSSL_VERSION_NUMBER >= 0x0090804fL)
+ return (0);
+ printf("\n\nFound OPENSSL_VERSION_NUMBER %#010x\n",
+ OPENSSL_VERSION_NUMBER);
+ printf("Require OPENSSL_VERSION_NUMBER 0x009070cf or greater (0.9.7l)\n"
+ "Require OPENSSL_VERSION_NUMBER 0x0090804f or greater (0.9.8d)\n\n");
+ return (1);
+}
+ ],
+ [AC_MSG_RESULT(ok)],
+ [AC_MSG_RESULT(not compatible)
+ OPENSSL_WARNING=yes
+ ],
+ [AC_MSG_RESULT(assuming target platform has compatible version)])
+;;
+no)
+ AC_MSG_RESULT(Skipped OpenSSL version check)
+;;
+esac
+
+ AC_MSG_CHECKING(for OpenSSL DSA support)
+ if test -f $use_openssl/include/openssl/dsa.h
+ then
+ AC_DEFINE(HAVE_OPENSSL_DSA)
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ CFLAGS="$saved_cflags"
+ LIBS="$saved_libs"
+ ;;
+esac
+
+#
+# This would include the system openssl path (and linker options to use
+# it as needed) if it is found.
+#
+
+AC_SUBST(USE_OPENSSL)
+AC_SUBST(DST_OPENSSL_INC)
+DNS_CRYPTO_LIBS="$DNS_CRYPTO_LIBS $DNS_OPENSSL_LIBS"
+
+#
+# PKCS11 (aka crypto hardware) support
+#
+# This works only with the right OpenSSL with PKCS11 engine!
+#
+
+AC_MSG_CHECKING(for PKCS11 support)
+AC_ARG_WITH(pkcs11,
+[ --with-pkcs11 Build with PKCS11 support],
+ use_pkcs11="yes", use_pkcs11="no")
+
+case "$use_pkcs11" in
+ no)
+ AC_MSG_RESULT(disabled)
+ USE_PKCS11=""
+ ;;
+ yes)
+ AC_MSG_RESULT(using OpenSSL with PKCS11 support)
+ USE_PKCS11='-DUSE_PKCS11'
+ ;;
+esac
+
+AC_SUBST(USE_PKCS11)
+
+AC_MSG_CHECKING(for GSSAPI library)
+AC_ARG_WITH(gssapi,
+[ --with-gssapi=PATH Specify path for system-supplied GSSAPI],
+ use_gssapi="$withval", use_gssapi="no")
+
+gssapidirs="/usr/local /usr/pkg /usr/kerberos /usr"
+if test "$use_gssapi" = "yes"
+then
+ for d in $gssapidirs
+ do
+ if test -f $d/include/gssapi/gssapi.h -o -f $d/include/gssapi.h
+ then
+ use_gssapi=$d
+ break
+ fi
+ done
+fi
+
+case "$use_gssapi" in
+ no)
+ AC_MSG_RESULT(disabled)
+ USE_GSSAPI=''
+ ;;
+ yes)
+ AC_MSG_ERROR([--with-gssapi must specify a path])
+ ;;
+ *)
+ AC_MSG_RESULT(looking in $use_gssapi/lib)
+ USE_GSSAPI='-DGSSAPI'
+ saved_cppflags="$CPPFLAGS"
+ CPPFLAGS="-I$use_gssapi/include $CPPFLAGS"
+ AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h,
+ [ISC_PLATFORM_GSSAPIHEADER="#define ISC_PLATFORM_GSSAPIHEADER <$ac_header>"])
+
+ if test "$ISC_PLATFORM_GSSAPIHEADER" = ""; then
+ AC_MSG_ERROR([gssapi.h not found])
+ fi
+
+ CPPFLAGS="$saved_cppflags"
+
+ #
+ # XXXDCL This probably doesn't work right on all systems.
+ # It will need to be worked on as problems become evident.
+ #
+ # Essentially the problems here relate to two different
+ # areas. The first area is building with either KTH
+ # or MIT Kerberos, particularly when both are present on
+ # the machine. The other is static versus dynamic linking.
+ #
+ # On the KTH vs MIT issue, Both have libkrb5 that can mess
+ # up the works if one implementation ends up trying to
+ # use the other's krb. This is unfortunately a situation
+ # that very easily arises.
+ #
+ # Dynamic linking when the dependency information is built
+ # into MIT's libgssapi_krb5 or KTH's libgssapi magically makes
+ # all such problems go away, but when that setup is not
+ # present, because either the dynamic libraries lack
+ # dependencies or static linking is being done, then the
+ # problems start to show up.
+ saved_libs="$LIBS"
+ for TRY_LIBS in \
+ "-lgssapi_krb5" \
+ "-lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err" \
+ "-lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lresolv" \
+ "-lgssapi" \
+ "-lgssapi -lkrb5 -ldes -lcrypt -lasn1 -lroken -lcom_err" \
+ "-lgssapi -lkrb5 -lcrypto -lcrypt -lasn1 -lroken -lcom_err" \
+ "-lgss"
+ do
+ # Note that this does not include $saved_libs, because
+ # on FreeBSD machines this configure script has added
+ # -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"
+ AC_MSG_CHECKING(linking as $TRY_LIBS)
+ AC_TRY_LINK( , [gss_acquire_cred();],
+ gssapi_linked=yes, gssapi_linked=no)
+ case $gssapi_linked in
+ yes) AC_MSG_RESULT(yes); break ;;
+ no) AC_MSG_RESULT(no) ;;
+ esac
+ done
+
+ case $gssapi_linked in
+ no) AC_MSG_ERROR(could not determine proper GSSAPI linkage) ;;
+ esac
+
+ #
+ # XXXDCL Major kludge. Tries to cope with KTH in /usr/lib
+ # but MIT in /usr/local/lib and trying to build with KTH.
+ # /usr/local/lib can end up earlier on the link lines.
+ # Like most kludges, this one is not only inelegant it
+ # is also likely to be the wrong thing to do at least as
+ # many times as it is the right thing. Something better
+ # needs to be done.
+ #
+ if test "$use_gssapi" = "/usr" -a \
+ -f /usr/local/lib/libkrb5.a; then
+ FIX_KTH_VS_MIT=yes
+ fi
+
+ case "$FIX_KTH_VS_MIT" in
+ yes)
+ case "$enable_static_linking" in
+ yes) gssapi_lib_suffix=".a" ;;
+ *) gssapi_lib_suffix=".so" ;;
+ esac
+
+ for lib in $LIBS; do
+ case $lib in
+ -L*)
+ ;;
+ -l*)
+ new_lib=`echo $lib |
+ sed -e s%^-l%$use_gssapi/lib/lib% \
+ -e s%$%$gssapi_lib_suffix%`
+ NEW_LIBS="$NEW_LIBS $new_lib"
+ ;;
+ *)
+ AC_MSG_ERROR([KTH vs MIT Kerberos confusion!])
+ ;;
+ esac
+ done
+ LIBS="$NEW_LIBS"
+ ;;
+ esac
+
+ DST_GSSAPI_INC="-I$use_gssapi/include"
+ DNS_GSSAPI_LIBS="$LIBS"
+
+ AC_MSG_RESULT(using GSSAPI from $use_gssapi/lib and $use_gssapi/include)
+ LIBS="$saved_libs"
+ ;;
+esac
+
+AC_SUBST(ISC_PLATFORM_HAVEGSSAPI)
+AC_SUBST(ISC_PLATFORM_GSSAPIHEADER)
+
+AC_SUBST(USE_GSSAPI)
+AC_SUBST(DST_GSSAPI_INC)
+AC_SUBST(DNS_GSSAPI_LIBS)
+DNS_CRYPTO_LIBS="$DNS_GSSAPI_LIBS $DNS_CRYPTO_LIBS"
+
+#
+# Applications linking with libdns also need to link with these libraries.
+#
+
+AC_SUBST(DNS_CRYPTO_LIBS)
+
+#
+# was --with-randomdev specified?
+#
+AC_MSG_CHECKING(for random device)
+AC_ARG_WITH(randomdev,
+[ --with-randomdev=PATH Specify path for random device],
+ use_randomdev="$withval", use_randomdev="unspec")
+
+case "$use_randomdev" in
+ unspec)
+ case "$host" in
+ *-openbsd*)
+ devrandom=/dev/arandom
+ ;;
+ *)
+ devrandom=/dev/random
+ ;;
+ esac
+ AC_MSG_RESULT($devrandom)
+ AC_CHECK_FILE($devrandom,
+ AC_DEFINE_UNQUOTED(PATH_RANDOMDEV,
+ "$devrandom"),)
+ ;;
+ yes)
+ AC_MSG_ERROR([--with-randomdev must specify a path])
+ ;;
+ no)
+ AC_MSG_RESULT(disabled)
+ ;;
+ *)
+ AC_DEFINE_UNQUOTED(PATH_RANDOMDEV, "$use_randomdev")
+ AC_MSG_RESULT(using "$use_randomdev")
+ ;;
+esac
+
+#
+# Do we have arc4random() ?
+#
+AC_CHECK_FUNC(arc4random, AC_DEFINE(HAVE_ARC4RANDOM))
+
+sinclude(config.threads.in)dnl
+
+if $use_threads
+then
+ if test "X$GCC" = "Xyes"; then
+ case "$host" in
+ *-freebsd*)
+ CC="$CC -pthread"
+ CCOPT="$CCOPT -pthread"
+ STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE"
+ ;;
+ *-openbsd*)
+ CC="$CC -pthread"
+ CCOPT="$CCOPT -pthread"
+ ;;
+ *-solaris*)
+ LIBS="$LIBS -lthread"
+ ;;
+ *-ibm-aix*)
+ STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE"
+ ;;
+ esac
+ else
+ case $host in
+ *-dec-osf*)
+ CC="$CC -pthread"
+ CCOPT="$CCOPT -pthread"
+ ;;
+ *-solaris*)
+ CC="$CC -mt"
+ CCOPT="$CCOPT -mt"
+ ;;
+ *-ibm-aix*)
+ STD_CDEFINES="$STD_CDEFINES -D_THREAD_SAFE"
+ ;;
+ *-sco-sysv*uw*|*-*-sysv*UnixWare*)
+ CC="$CC -Kthread"
+ CCOPT="$CCOPT -Kthread"
+ ;;
+ *-*-sysv*OpenUNIX*)
+ CC="$CC -Kpthread"
+ CCOPT="$CCOPT -Kpthread"
+ ;;
+ esac
+ fi
+ ALWAYS_DEFINES="-D_REENTRANT"
+ ISC_PLATFORM_USETHREADS="#define ISC_PLATFORM_USETHREADS 1"
+ thread_dir=pthreads
+ #
+ # We'd like to use sigwait() too
+ #
+ AC_CHECK_FUNC(sigwait,
+ AC_DEFINE(HAVE_SIGWAIT),
+ AC_CHECK_LIB(c, sigwait,
+ AC_DEFINE(HAVE_SIGWAIT),
+ AC_CHECK_LIB(pthread, sigwait,
+ AC_DEFINE(HAVE_SIGWAIT),
+ AC_CHECK_LIB(pthread, _Psigwait,
+ AC_DEFINE(HAVE_SIGWAIT),))))
+
+ AC_CHECK_FUNC(pthread_attr_getstacksize,
+ AC_DEFINE(HAVE_PTHREAD_ATTR_GETSTACKSIZE),)
+
+ AC_CHECK_FUNC(pthread_attr_setstacksize,
+ AC_DEFINE(HAVE_PTHREAD_ATTR_SETSTACKSIZE),)
+
+ #
+ # Additional OS-specific issues related to pthreads and sigwait.
+ #
+ case "$host" in
+ #
+ # One more place to look for sigwait.
+ #
+ *-freebsd*)
+ AC_CHECK_LIB(c_r, sigwait, AC_DEFINE(HAVE_SIGWAIT),)
+ case $host in
+ *-freebsd5.[[012]]|*-freebsd5.[[012]].*);;
+ *-freebsd5.[[3456789]]|*-freebsd5.[[3456789]].*)
+ AC_DEFINE(NEED_PTHREAD_SCOPE_SYSTEM)
+ ;;
+ *-freebsd6.*)
+ AC_DEFINE(NEED_PTHREAD_SCOPE_SYSTEM)
+ ;;
+ esac
+ ;;
+ #
+ # BSDI 3.0 through 4.0.1 needs pthread_init() to be
+ # called before certain pthreads calls. This is deprecated
+ # in BSD/OS 4.1.
+ #
+ *-bsdi3.*|*-bsdi4.0*)
+ AC_DEFINE(NEED_PTHREAD_INIT)
+ ;;
+ #
+ # LinuxThreads requires some changes to the way we
+ # deal with signals.
+ #
+ *-linux*)
+ AC_DEFINE(HAVE_LINUXTHREADS)
+ ;;
+ #
+ # Ensure the right sigwait() semantics on Solaris and make
+ # sure we call pthread_setconcurrency.
+ #
+ *-solaris*)
+ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS)
+ AC_CHECK_FUNC(pthread_setconcurrency,
+ AC_DEFINE(CALL_PTHREAD_SETCONCURRENCY))
+ ;;
+ #
+ # UnixWare does things its own way.
+ #
+ *-sco-sysv*uw*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ AC_DEFINE(HAVE_UNIXWARE_SIGWAIT)
+ ;;
+ esac
+
+ #
+ # Look for sysconf to allow detection of the number of processors.
+ #
+ AC_CHECK_FUNC(sysconf, AC_DEFINE(HAVE_SYSCONF),)
+
+else
+ ISC_PLATFORM_USETHREADS="#undef ISC_PLATFORM_USETHREADS"
+ thread_dir=nothreads
+ ALWAYS_DEFINES=""
+fi
+
+AC_SUBST(ALWAYS_DEFINES)
+AC_SUBST(ISC_PLATFORM_USETHREADS)
+ISC_THREAD_DIR=$thread_dir
+AC_SUBST(ISC_THREAD_DIR)
+
+#
+# was --with-libxml2 specified?
+#
+AC_MSG_CHECKING(for libxml2 library)
+AC_ARG_WITH(libxml2,
+[ --with-libxml2[=PATH] Build with libxml2 library [yes|no|path]],
+ use_libxml2="$withval", use_libxml2="auto")
+
+case "$use_libxml2" in
+ no)
+ DST_LIBXML2_INC=""
+ ;;
+ auto|yes)
+ case X`(xml2-config --version) 2>/dev/null` in
+ X2.[[67]].*)
+ libxml2_libs=`xml2-config --libs`
+ libxml2_cflags=`xml2-config --cflags`
+ ;;
+ *)
+ libxml2_libs=
+ libxml2_cflags=
+ ;;
+ esac
+ ;;
+ *)
+ if test -f "$use_libxml2/bin/xml2-config" ; then
+ libxml2_libs=`$use_libxml2/bin/xml2-config --libs`
+ libxml2_cflags=`$use_libxml2/bin/xml2-config --cflags`
+ fi
+ ;;
+esac
+
+if test "X$libxml2_libs" != "X"
+then
+ AC_MSG_RESULT(yes)
+ CFLAGS="$CFLAGS $libxml2_cflags"
+ LIBS="$LIBS $libxml2_libs"
+ AC_DEFINE(HAVE_LIBXML2, 1, [Define if libxml2 was found])
+else
+ AC_MSG_RESULT(no)
+fi
+
+#
+# In solaris 10, SMF can manage named service
+#
+AC_CHECK_LIB(scf, smf_enable_instance)
+
+#
+# flockfile is usually provided by pthreads, but we may want to use it
+# even if compiled with --disable-threads. getc_unlocked might also not
+# be defined.
+#
+AC_CHECK_FUNC(flockfile, AC_DEFINE(HAVE_FLOCKFILE),)
+AC_CHECK_FUNC(getc_unlocked, AC_DEFINE(HAVE_GETCUNLOCKED),)
+
+#
+# Indicate what the final decision was regarding threads.
+#
+AC_MSG_CHECKING(whether to build with threads)
+if $use_threads; then
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+#
+# End of pthreads stuff.
+#
+
+#
+# Large File
+#
+AC_ARG_ENABLE(largefile, [ --enable-largefile 64-bit file support],
+ want_largefile="yes", want_largefile="no")
+case $want_largefile in
+ yes)
+ ALWAYS_DEFINES="$ALWAYS_DEFINES -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+ ;;
+ *)
+ ;;
+esac
+
+#
+# Additional compiler settings.
+#
+MKDEPCC="$CC"
+MKDEPCFLAGS="-M"
+IRIX_DNSSEC_WARNINGS_HACK=""
+
+if test "X$GCC" = "Xyes"; then
+ AC_MSG_CHECKING(if "$CC" supports -fno-strict-aliasing)
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS=-fno-strict-aliasing
+ AC_TRY_COMPILE(,, [FNOSTRICTALIASING=yes],[FNOSTRICTALIASING=no])
+ CFLAGS=$SAVE_CFLAGS
+ if test "$FNOSTRICTALIASING" = "yes"; then
+ AC_MSG_RESULT(yes)
+ STD_CWARNINGS="$STD_CWARNINGS -W -Wall -Wmissing-prototypes -Wcast-qual -Wwrite-strings -Wformat -Wpointer-arith -fno-strict-aliasing"
+ else
+ AC_MSG_RESULT(no)
+ STD_CWARNINGS="$STD_CWARNINGS -W -Wall -Wmissing-prototypes -Wcast-qual -Wwrite-strings -Wformat -Wpointer-arith"
+ fi
+ case "$host" in
+ *-hp-hpux*)
+ LDFLAGS="-Wl,+vnocompatwarnings $LDFLAGS"
+ ;;
+ esac
+else
+ case $host in
+ *-dec-osf*)
+ CC="$CC -std"
+ CCOPT="$CCOPT -std"
+ MKDEPCC="$CC"
+ ;;
+ *-hp-hpux*)
+ CC="$CC -Ae -z"
+ # The version of the C compiler that constantly warns about
+ # 'const' as well as alignment issues is unfortunately not
+ # able to be discerned via the version of the operating
+ # system, nor does cc have a version flag.
+ case "`$CC +W 123 2>&1`" in
+ *Unknown?option*)
+ STD_CWARNINGS="+w1"
+ ;;
+ *)
+ # Turn off the pointlessly noisy warnings.
+ STD_CWARNINGS="+w1 +W 474,530,2193,2236"
+ ;;
+ esac
+ CCOPT="$CCOPT -Ae -z"
+ LDFLAGS="-Wl,+vnocompatwarnings $LDFLAGS"
+ MKDEPPROG='cc -Ae -E -Wp,-M >/dev/null 2>>$TMP'
+ ;;
+ *-sgi-irix*)
+ STD_CWARNINGS="-fullwarn -woff 1209"
+ #
+ # Silence more than 250 instances of
+ # "prototyped function redeclared without prototype"
+ # and 11 instances of
+ # "variable ... was set but never used"
+ # from lib/dns/sec/openssl.
+ #
+ IRIX_DNSSEC_WARNINGS_HACK="-woff 1692,1552"
+ ;;
+ *-solaris*)
+ MKDEPCFLAGS="-xM"
+ ;;
+ *-sco-sysv*uw*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ # UnixWare
+ CC="$CC -w"
+ ;;
+ esac
+fi
+
+AC_SUBST(MKDEPCC)
+AC_SUBST(MKDEPCFLAGS)
+AC_SUBST(MKDEPPROG)
+AC_SUBST(IRIX_DNSSEC_WARNINGS_HACK)
+
+#
+# NLS
+#
+AC_CHECK_FUNC(catgets, AC_DEFINE(HAVE_CATGETS),)
+
+#
+# -lxnet buys us one big porting headache... standards, gotta love 'em.
+#
+# AC_CHECK_LIB(xnet, socket, ,
+# AC_CHECK_LIB(socket, socket)
+# AC_CHECK_LIB(nsl, inet_ntoa)
+# )
+#
+# Use this for now, instead:
+#
+case "$host" in
+ mips-sgi-irix*)
+ ;;
+ *)
+ AC_CHECK_LIB(socket, socket)
+ AC_CHECK_LIB(nsl, inet_ntoa)
+ ;;
+esac
+
+#
+# Work around Solaris's select() limitations.
+#
+case "$host" in
+ *-solaris2.[[89]]|*-solaris2.1?)
+ AC_DEFINE(FD_SETSIZE, 65536,
+ [Solaris hack to get select_large_fdset.])
+ ;;
+esac
+
+#
+# Purify support
+#
+AC_MSG_CHECKING(whether to use purify)
+AC_ARG_WITH(purify,
+ [ --with-purify[=PATH] use Rational purify],
+ use_purify="$withval", use_purify="no")
+
+case "$use_purify" in
+ no)
+ ;;
+ yes)
+ AC_PATH_PROG(purify_path, purify, purify)
+ ;;
+ *)
+ purify_path="$use_purify"
+ ;;
+esac
+
+case "$use_purify" in
+ no)
+ AC_MSG_RESULT(no)
+ PURIFY=""
+ ;;
+ *)
+ if test -f $purify_path || test $purify_path = purify; then
+ AC_MSG_RESULT($purify_path)
+ PURIFYFLAGS="`echo $PURIFYOPTIONS`"
+ PURIFY="$purify_path $PURIFYFLAGS"
+ else
+ AC_MSG_ERROR([$purify_path not found.
+
+Please choose the proper path with the following command:
+
+ configure --with-purify=PATH
+])
+ fi
+ ;;
+esac
+
+AC_SUBST(PURIFY)
+
+#
+# GNU libtool support
+#
+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
+
+AC_ARG_WITH(libtool,
+ [ --with-libtool use GNU libtool (following indented options supported)],
+ use_libtool="$withval", use_libtool="no")
+
+case $use_libtool in
+ yes)
+ AM_PROG_LIBTOOL
+ O=lo
+ A=la
+ LIBTOOL_MKDEP_SED='s;\.o;\.lo;'
+ LIBTOOL_MODE_COMPILE='--mode=compile'
+ LIBTOOL_MODE_INSTALL='--mode=install'
+ LIBTOOL_MODE_LINK='--mode=link'
+ case "$host" in
+ *) LIBTOOL_ALLOW_UNDEFINED= ;;
+ esac
+ case "$host" in
+ *-ibm-aix*) LIBTOOL_IN_MAIN="-Wl,-bI:T_testlist.imp" ;;
+ *) LIBTOOL_IN_MAIN= ;;
+ esac;
+ ;;
+ *)
+ O=o
+ A=a
+ LIBTOOL=
+ AC_SUBST(LIBTOOL)
+ LIBTOOL_MKDEP_SED=
+ LIBTOOL_MODE_COMPILE=
+ LIBTOOL_MODE_INSTALL=
+ LIBTOOL_MODE_LINK=
+ LIBTOOL_ALLOW_UNDEFINED=
+ LIBTOOL_IN_MAIN=
+ ;;
+esac
+
+#
+# File name extension for static archive files, for those few places
+# where they are treated differently from dynamic ones.
+#
+SA=a
+
+AC_SUBST(O)
+AC_SUBST(A)
+AC_SUBST(SA)
+AC_SUBST(LIBTOOL_MKDEP_SED)
+AC_SUBST(LIBTOOL_MODE_COMPILE)
+AC_SUBST(LIBTOOL_MODE_INSTALL)
+AC_SUBST(LIBTOOL_MODE_LINK)
+AC_SUBST(LIBTOOL_ALLOW_UNDEFINED)
+AC_SUBST(LIBTOOL_IN_MAIN)
+
+#
+# Here begins a very long section to determine the system's networking
+# capabilities. The order of the tests is signficant.
+#
+
+#
+# IPv6
+#
+AC_ARG_ENABLE(ipv6,
+ [ --enable-ipv6 use IPv6 [default=autodetect]])
+
+case "$enable_ipv6" in
+ yes|''|autodetect)
+ AC_DEFINE(WANT_IPV6)
+ ;;
+ no)
+ ;;
+esac
+
+#
+# We do the IPv6 compilation checking after libtool so that we can put
+# the right suffix on the files.
+#
+AC_MSG_CHECKING(for IPv6 structures)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>],
+[struct sockaddr_in6 sin6; return (0);],
+ [AC_MSG_RESULT(yes)
+ found_ipv6=yes],
+ [AC_MSG_RESULT(no)
+ found_ipv6=no])
+
+#
+# See whether IPv6 support is provided via a Kame add-on.
+# This is done before other IPv6 linking tests to LIBS is properly set.
+#
+AC_MSG_CHECKING(for Kame IPv6 support)
+AC_ARG_WITH(kame,
+ [ --with-kame[=PATH] use Kame IPv6 [default path /usr/local/v6]],
+ use_kame="$withval", use_kame="no")
+
+case "$use_kame" in
+ no)
+ ;;
+ yes)
+ kame_path=/usr/local/v6
+ ;;
+ *)
+ kame_path="$use_kame"
+ ;;
+esac
+
+case "$use_kame" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ if test -f $kame_path/lib/libinet6.a; then
+ AC_MSG_RESULT($kame_path/lib/libinet6.a)
+ LIBS="-L$kame_path/lib -linet6 $LIBS"
+ else
+ AC_MSG_ERROR([$kame_path/lib/libinet6.a not found.
+
+Please choose the proper path with the following command:
+
+ configure --with-kame=PATH
+])
+ fi
+ ;;
+esac
+
+#
+# Whether netinet6/in6.h is needed has to be defined in isc/platform.h.
+# Including it on Kame-using platforms is very bad, though, because
+# Kame uses #error against direct inclusion. So include it on only
+# the platform that is otherwise broken without it -- BSD/OS 4.0 through 4.1.
+# This is done before the in6_pktinfo check because that's what
+# netinet6/in6.h is needed for.
+#
+changequote({, })
+case "$host" in
+*-bsdi4.[01]*)
+ ISC_PLATFORM_NEEDNETINET6IN6H="#define ISC_PLATFORM_NEEDNETINET6IN6H 1"
+ LWRES_PLATFORM_NEEDNETINET6IN6H="#define LWRES_PLATFORM_NEEDNETINET6IN6H 1"
+ isc_netinet6in6_hack="#include <netinet6/in6.h>"
+ ;;
+*)
+ ISC_PLATFORM_NEEDNETINET6IN6H="#undef ISC_PLATFORM_NEEDNETINET6IN6H"
+ LWRES_PLATFORM_NEEDNETINET6IN6H="#undef LWRES_PLATFORM_NEEDNETINET6IN6H"
+ isc_netinet6in6_hack=""
+ ;;
+esac
+changequote([, ])
+
+#
+# This is similar to the netinet6/in6.h issue.
+#
+case "$host" in
+*-sco-sysv*uw*|*-*-sysv*UnixWare*|*-*-sysv*OpenUNIX*)
+ # UnixWare
+ ISC_PLATFORM_NEEDNETINETIN6H="#define ISC_PLATFORM_NEEDNETINETIN6H 1"
+ LWRES_PLATFORM_NEEDNETINETIN6H="#define LWRES_PLATFORM_NEEDNETINETIN6H 1"
+ ISC_PLATFORM_FIXIN6ISADDR="#define ISC_PLATFORM_FIXIN6ISADDR 1"
+ isc_netinetin6_hack="#include <netinet/in6.h>"
+ ;;
+*)
+ ISC_PLATFORM_NEEDNETINETIN6H="#undef ISC_PLATFORM_NEEDNETINETIN6H"
+ LWRES_PLATFORM_NEEDNETINETIN6H="#undef LWRES_PLATFORM_NEEDNETINETIN6H"
+ ISC_PLATFORM_FIXIN6ISADDR="#undef ISC_PLATFORM_FIXIN6ISADDR"
+ isc_netinetin6_hack=""
+ ;;
+esac
+
+#
+# Now delve deeper into the suitability of the IPv6 support.
+#
+case "$found_ipv6" in
+ yes)
+ ISC_PLATFORM_HAVEIPV6="#define ISC_PLATFORM_HAVEIPV6 1"
+ LWRES_PLATFORM_HAVEIPV6="#define LWRES_PLATFORM_HAVEIPV6 1"
+
+ AC_MSG_CHECKING(for in6_addr)
+ AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+$isc_netinetin6_hack
+$isc_netinet6in6_hack
+],
+[struct in6_addr in6; return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_HAVEINADDR6="#undef ISC_PLATFORM_HAVEINADDR6"
+ LWRES_PLATFORM_HAVEINADDR6="#undef LWRES_PLATFORM_HAVEINADDR6"
+ isc_in_addr6_hack=""],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_HAVEINADDR6="#define ISC_PLATFORM_HAVEINADDR6 1"
+ LWRES_PLATFORM_HAVEINADDR6="#define LWRES_PLATFORM_HAVEINADDR6 1"
+ isc_in_addr6_hack="#define in6_addr in_addr6"])
+
+ AC_MSG_CHECKING(for in6addr_any)
+ AC_TRY_LINK([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+$isc_netinetin6_hack
+$isc_netinet6in6_hack
+$isc_in_addr6_hack
+],
+ [struct in6_addr in6; in6 = in6addr_any; return (in6.s6_addr[0]);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_NEEDIN6ADDRANY="#undef ISC_PLATFORM_NEEDIN6ADDRANY"
+ LWRES_PLATFORM_NEEDIN6ADDRANY="#undef LWRES_PLATFORM_NEEDIN6ADDRANY"],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_NEEDIN6ADDRANY="#define ISC_PLATFORM_NEEDIN6ADDRANY 1"
+ LWRES_PLATFORM_NEEDIN6ADDRANY="#define LWRES_PLATFORM_NEEDIN6ADDRANY 1"])
+
+ AC_MSG_CHECKING(for in6addr_loopback)
+ AC_TRY_LINK([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+$isc_netinetin6_hack
+$isc_netinet6in6_hack
+$isc_in_addr6_hack
+],
+ [struct in6_addr in6; in6 = in6addr_loopback; return (in6.s6_addr[0]);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_NEEDIN6ADDRLOOPBACK="#undef ISC_PLATFORM_NEEDIN6ADDRLOOPBACK"
+ LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK="#undef LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK"],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_NEEDIN6ADDRLOOPBACK="#define ISC_PLATFORM_NEEDIN6ADDRLOOPBACK 1"
+ LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK="#define LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK 1"])
+
+ AC_MSG_CHECKING(for sin6_scope_id in struct sockaddr_in6)
+ AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+$isc_netinetin6_hack
+$isc_netinet6in6_hack
+],
+ [struct sockaddr_in6 xyzzy; xyzzy.sin6_scope_id = 0; return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_HAVESCOPEID="#define ISC_PLATFORM_HAVESCOPEID 1"
+ result="#define LWRES_HAVE_SIN6_SCOPE_ID 1"],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_HAVESCOPEID="#undef ISC_PLATFORM_HAVESCOPEID"
+ result="#undef LWRES_HAVE_SIN6_SCOPE_ID"])
+ LWRES_HAVE_SIN6_SCOPE_ID="$result"
+
+ AC_MSG_CHECKING(for in6_pktinfo)
+ AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+$isc_netinetin6_hack
+$isc_netinet6in6_hack
+],
+ [struct in6_pktinfo xyzzy; return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_HAVEIN6PKTINFO="#define ISC_PLATFORM_HAVEIN6PKTINFO 1"],
+ [AC_MSG_RESULT(no -- disabling runtime ipv6 support)
+ ISC_PLATFORM_HAVEIN6PKTINFO="#undef ISC_PLATFORM_HAVEIN6PKTINFO"])
+ ;;
+ no)
+ ISC_PLATFORM_HAVEIPV6="#undef ISC_PLATFORM_HAVEIPV6"
+ LWRES_PLATFORM_HAVEIPV6="#undef LWRES_PLATFORM_HAVEIPV6"
+ ISC_PLATFORM_NEEDIN6ADDRANY="#undef ISC_PLATFORM_NEEDIN6ADDRANY"
+ LWRES_PLATFORM_NEEDIN6ADDRANY="#undef LWRES_PLATFORM_NEEDIN6ADDRANY"
+ ISC_PLATFORM_HAVEIN6PKTINFO="#undef ISC_PLATFORM_HAVEIN6PKTINFO"
+ LWRES_HAVE_SIN6_SCOPE_ID="#define LWRES_HAVE_SIN6_SCOPE_ID 1"
+ ISC_PLATFORM_HAVESCOPEID="#define ISC_PLATFORM_HAVESCOPEID 1"
+ ISC_IPV6_H="ipv6.h"
+ ISC_IPV6_O="ipv6.$O"
+ ISC_ISCIPV6_O="unix/ipv6.$O"
+ ISC_IPV6_C="ipv6.c"
+ ;;
+esac
+
+AC_SUBST(ISC_PLATFORM_HAVEIPV6)
+AC_SUBST(LWRES_PLATFORM_HAVEIPV6)
+AC_SUBST(ISC_PLATFORM_NEEDNETINETIN6H)
+AC_SUBST(LWRES_PLATFORM_NEEDNETINETIN6H)
+AC_SUBST(ISC_PLATFORM_NEEDNETINET6IN6H)
+AC_SUBST(LWRES_PLATFORM_NEEDNETINET6IN6H)
+AC_SUBST(ISC_PLATFORM_HAVEINADDR6)
+AC_SUBST(LWRES_PLATFORM_HAVEINADDR6)
+AC_SUBST(ISC_PLATFORM_NEEDIN6ADDRANY)
+AC_SUBST(LWRES_PLATFORM_NEEDIN6ADDRANY)
+AC_SUBST(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK)
+AC_SUBST(LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK)
+AC_SUBST(ISC_PLATFORM_HAVEIN6PKTINFO)
+AC_SUBST(ISC_PLATFORM_FIXIN6ISADDR)
+AC_SUBST(ISC_IPV6_H)
+AC_SUBST(ISC_IPV6_O)
+AC_SUBST(ISC_ISCIPV6_O)
+AC_SUBST(ISC_IPV6_C)
+AC_SUBST(LWRES_HAVE_SIN6_SCOPE_ID)
+AC_SUBST(ISC_PLATFORM_HAVESCOPEID)
+
+AC_MSG_CHECKING([for struct if_laddrreq])
+AC_TRY_LINK([
+#include <sys/types.h>
+#include <net/if6.h>
+],[ struct if_laddrreq a; ],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_HAVEIF_LADDRREQ="#define ISC_PLATFORM_HAVEIF_LADDRREQ 1"],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_HAVEIF_LADDRREQ="#undef ISC_PLATFORM_HAVEIF_LADDRREQ"])
+AC_SUBST(ISC_PLATFORM_HAVEIF_LADDRREQ)
+
+AC_MSG_CHECKING([for struct if_laddrconf])
+AC_TRY_LINK([
+#include <sys/types.h>
+#include <net/if6.h>
+],[ struct if_laddrconf a; ],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_HAVEIF_LADDRCONF="#define ISC_PLATFORM_HAVEIF_LADDRCONF 1"],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_HAVEIF_LADDRCONF="#undef ISC_PLATFORM_HAVEIF_LADDRCONF"])
+AC_SUBST(ISC_PLATFORM_HAVEIF_LADDRCONF)
+
+#
+# Check for network functions that are often missing. We do this
+# after the libtool checking, so we can put the right suffix on
+# the files. It also needs to come after checking for a Kame add-on,
+# which provides some (all?) of the desired functions.
+#
+
+AC_MSG_CHECKING([for inet_ntop with IPv6 support])
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+main() {
+char a[16],b[64]; return(inet_ntop(AF_INET6, a, b, sizeof(b)) == (char*)0);}],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_NEEDNTOP="#undef ISC_PLATFORM_NEEDNTOP"],
+
+ [AC_MSG_RESULT(no)
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
+ ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"],
+ [AC_MSG_RESULT(assuming inet_ntop needed)
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_ntop.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_ntop.c"
+ ISC_PLATFORM_NEEDNTOP="#define ISC_PLATFORM_NEEDNTOP 1"])
+
+
+# On NetBSD 1.4.2 and maybe others, inet_pton() incorrectly accepts
+# addresses with less than four octets, like "1.2.3". Also leading
+# zeros should also be rejected.
+
+AC_MSG_CHECKING([for working inet_pton with IPv6 support])
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+main() { char a[16]; return (inet_pton(AF_INET, "1.2.3", a) == 1 ? 1 :
+ inet_pton(AF_INET, "1.2.3.04", a) == 1 ? 1 :
+ (inet_pton(AF_INET6, "::1.2.3.4", a) != 1)); }],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"],
+ [AC_MSG_RESULT(no)
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c"
+ ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1"],
+ [AC_MSG_RESULT(assuming target platform has working inet_pton)
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"],
+ [AC_MSG_RESULT(assuming inet_pton needed)
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_pton.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_pton.c"
+ ISC_PLATFORM_NEEDPTON="#define ISC_PLATFORM_NEEDPTON 1"],
+ [AC_MSG_RESULT(assuming target platform has working inet_pton)
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"])
+
+AC_MSG_CHECKING([for inet_aton])
+AC_TRY_LINK([
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>],
+ [struct in_addr in; inet_aton(0, &in); return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_NEEDATON="#undef ISC_PLATFORM_NEEDATON"],
+
+ [AC_MSG_RESULT(no)
+ ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS inet_aton.$O"
+ ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS inet_aton.c"
+ ISC_PLATFORM_NEEDATON="#define ISC_PLATFORM_NEEDATON 1"])
+
+AC_SUBST(ISC_PLATFORM_NEEDNTOP)
+AC_SUBST(ISC_PLATFORM_NEEDPTON)
+AC_SUBST(ISC_PLATFORM_NEEDATON)
+
+#
+# Look for a 4.4BSD-style sa_len member in struct sockaddr.
+#
+case "$host" in
+ *-dec-osf*)
+ # Turn on 4.4BSD style sa_len support.
+ AC_DEFINE(_SOCKADDR_LEN)
+ ;;
+esac
+
+AC_MSG_CHECKING(for sa_len in struct sockaddr)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/socket.h>],
+[struct sockaddr sa; sa.sa_len = 0; return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_HAVESALEN="#define ISC_PLATFORM_HAVESALEN 1"
+ LWRES_PLATFORM_HAVESALEN="#define LWRES_PLATFORM_HAVESALEN 1"],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_HAVESALEN="#undef ISC_PLATFORM_HAVESALEN"
+ LWRES_PLATFORM_HAVESALEN="#undef LWRES_PLATFORM_HAVESALEN"])
+AC_SUBST(ISC_PLATFORM_HAVESALEN)
+AC_SUBST(LWRES_PLATFORM_HAVESALEN)
+
+#
+# Look for a 4.4BSD or 4.3BSD struct msghdr
+#
+AC_MSG_CHECKING(for struct msghdr flavor)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/socket.h>],
+[struct msghdr msg; msg.msg_flags = 0; return (0);],
+ [AC_MSG_RESULT(4.4BSD)
+ ISC_PLATFORM_MSGHDRFLAVOR="#define ISC_NET_BSD44MSGHDR 1"],
+ [AC_MSG_RESULT(4.3BSD)
+ ISC_PLATFORM_MSGHDRFLAVOR="#define ISC_NET_BSD43MSGHDR 1"])
+AC_SUBST(ISC_PLATFORM_MSGHDRFLAVOR)
+
+#
+# Look for in_port_t.
+#
+AC_MSG_CHECKING(for type in_port_t)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <netinet/in.h>],
+[in_port_t port = 25; return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_PLATFORM_NEEDPORTT="#undef ISC_PLATFORM_NEEDPORTT"],
+ [AC_MSG_RESULT(no)
+ ISC_PLATFORM_NEEDPORTT="#define ISC_PLATFORM_NEEDPORTT 1"])
+AC_SUBST(ISC_PLATFORM_NEEDPORTT)
+
+#
+# Check for addrinfo
+#
+AC_MSG_CHECKING(for struct addrinfo)
+AC_TRY_COMPILE([
+#include <netdb.h>],
+[struct addrinfo a; return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_LWRES_NEEDADDRINFO="#undef ISC_LWRES_NEEDADDRINFO"
+ AC_DEFINE(HAVE_ADDRINFO)],
+ [AC_MSG_RESULT(no)
+ ISC_LWRES_NEEDADDRINFO="#define ISC_LWRES_NEEDADDRINFO 1"])
+AC_SUBST(ISC_LWRES_NEEDADDRINFO)
+
+#
+# Check for rrsetinfo
+#
+AC_MSG_CHECKING(for struct rrsetinfo)
+AC_TRY_COMPILE([
+#include <netdb.h>],
+[struct rrsetinfo r; return (0);],
+ [AC_MSG_RESULT(yes)
+ ISC_LWRES_NEEDRRSETINFO="#undef ISC_LWRES_NEEDRRSETINFO"],
+ [AC_MSG_RESULT(no)
+ ISC_LWRES_NEEDRRSETINFO="#define ISC_LWRES_NEEDRRSETINFO 1"])
+AC_SUBST(ISC_LWRES_NEEDRRSETINFO)
+
+AC_MSG_CHECKING(for int sethostent)
+AC_TRY_COMPILE([
+#include <netdb.h>],
+[int i = sethostent(0); return(0);],
+ [AC_MSG_RESULT(yes)
+ ISC_LWRES_SETHOSTENTINT="#define ISC_LWRES_SETHOSTENTINT 1"],
+ [AC_MSG_RESULT(no)
+ ISC_LWRES_SETHOSTENTINT="#undef ISC_LWRES_SETHOSTENTINT"])
+AC_SUBST(ISC_LWRES_SETHOSTENTINT)
+
+AC_MSG_CHECKING(for int endhostent)
+AC_TRY_COMPILE([
+#include <netdb.h>],
+[int i = endhostent(); return(0);],
+ [AC_MSG_RESULT(yes)
+ ISC_LWRES_ENDHOSTENTINT="#define ISC_LWRES_ENDHOSTENTINT 1"],
+ [AC_MSG_RESULT(no)
+ ISC_LWRES_ENDHOSTENTINT="#undef ISC_LWRES_ENDHOSTENTINT"])
+AC_SUBST(ISC_LWRES_ENDHOSTENTINT)
+
+AC_MSG_CHECKING(for getnetbyaddr(in_addr_t, ...))
+AC_TRY_COMPILE([
+#include <netdb.h>
+struct netent *getnetbyaddr(in_addr_t, int);],
+[],
+ [AC_MSG_RESULT(yes)
+ ISC_LWRES_GETNETBYADDRINADDR="#define ISC_LWRES_GETNETBYADDRINADDR 1"],
+ [AC_MSG_RESULT(no)
+ ISC_LWRES_GETNETBYADDRINADDR="#undef ISC_LWRES_GETNETBYADDRINADDR"])
+AC_SUBST(ISC_LWRES_GETNETBYADDRINADDR)
+
+AC_MSG_CHECKING(for int setnetent)
+AC_TRY_COMPILE([
+#include <netdb.h>],
+[int i = setnetent(0); return(0);],
+ [AC_MSG_RESULT(yes)
+ ISC_LWRES_SETNETENTINT="#define ISC_LWRES_SETNETENTINT 1"],
+ [AC_MSG_RESULT(no)
+ ISC_LWRES_SETNETENTINT="#undef ISC_LWRES_SETNETENTINT"])
+AC_SUBST(ISC_LWRES_SETNETENTINT)
+
+AC_MSG_CHECKING(for int endnetent)
+AC_TRY_COMPILE([
+#include <netdb.h>],
+[int i = endnetent(); return(0);],
+ [AC_MSG_RESULT(yes)
+ ISC_LWRES_ENDNETENTINT="#define ISC_LWRES_ENDNETENTINT 1"],
+ [AC_MSG_RESULT(no)
+ ISC_LWRES_ENDNETENTINT="#undef ISC_LWRES_ENDNETENTINT"])
+AC_SUBST(ISC_LWRES_ENDNETENTINT)
+
+AC_MSG_CHECKING(for gethostbyaddr(const void *, size_t, ...))
+AC_TRY_COMPILE([
+#include <netdb.h>
+struct hostent *gethostbyaddr(const void *, size_t, int);],
+[return(0);],
+ [AC_MSG_RESULT(yes)
+ ISC_LWRES_GETHOSTBYADDRVOID="#define ISC_LWRES_GETHOSTBYADDRVOID 1"],
+ [AC_MSG_RESULT(no)
+ ISC_LWRES_GETHOSTBYADDRVOID="#undef ISC_LWRES_GETHOSTBYADDRVOID"])
+AC_SUBST(ISC_LWRES_GETHOSTBYADDRVOID)
+
+AC_MSG_CHECKING(for h_errno in netdb.h)
+AC_TRY_COMPILE([
+#include <netdb.h>],
+[h_errno = 1; return(0);],
+ [AC_MSG_RESULT(yes)
+ ISC_LWRES_NEEDHERRNO="#undef ISC_LWRES_NEEDHERRNO"],
+ [AC_MSG_RESULT(no)
+ ISC_LWRES_NEEDHERRNO="#define ISC_LWRES_NEEDHERRNO 1"])
+AC_SUBST(ISC_LWRES_NEEDHERRNO)
+
+AC_CHECK_FUNC(getipnodebyname,
+ [ISC_LWRES_GETIPNODEPROTO="#undef ISC_LWRES_GETIPNODEPROTO"],
+ [ISC_LWRES_GETIPNODEPROTO="#define ISC_LWRES_GETIPNODEPROTO 1"])
+AC_CHECK_FUNC(getnameinfo,
+ [ISC_LWRES_GETNAMEINFOPROTO="#undef ISC_LWRES_GETNAMEINFOPROTO"],
+ [ISC_LWRES_GETNAMEINFOPROTO="#define ISC_LWRES_GETNAMEINFOPROTO 1"])
+AC_CHECK_FUNC(getaddrinfo,
+ [ISC_LWRES_GETADDRINFOPROTO="#undef ISC_LWRES_GETADDRINFOPROTO"
+ AC_DEFINE(HAVE_GETADDRINFO)],
+ [ISC_LWRES_GETADDRINFOPROTO="#define ISC_LWRES_GETADDRINFOPROTO 1"])
+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_ARG_ENABLE(getifaddrs,
+[ --enable-getifaddrs Enable the use of getifaddrs() [[yes|no]].],
+ want_getifaddrs="$enableval", want_getifaddrs="yes")
+
+#
+# This interface iteration code for getifaddrs() will fall back to using
+# /proc/net/if_inet6 if getifaddrs() in glibc doesn't return any IPv6
+# addresses.
+#
+case $want_getifaddrs in
+glibc)
+AC_MSG_WARN("--enable-getifaddrs=glibc is no longer required")
+AC_CHECK_FUNC(getifaddrs, AC_DEFINE(HAVE_GETIFADDRS))
+;;
+yes)
+AC_CHECK_FUNC(getifaddrs, AC_DEFINE(HAVE_GETIFADDRS))
+;;
+no)
+;;
+esac
+
+#
+# Look for a sysctl call to get the list of network interfaces.
+#
+case $ac_cv_header_sys_sysctl_h in
+yes)
+AC_MSG_CHECKING(for interface list sysctl)
+AC_EGREP_CPP(found_rt_iflist, [
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#ifdef NET_RT_IFLIST
+found_rt_iflist
+#endif
+],
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_IFLIST_SYSCTL)],
+ [AC_MSG_RESULT(no)])
+;;
+esac
+
+#
+# Check for some other useful functions that are not ever-present.
+#
+
+# We test for strsep() using AC_TRY_LINK instead of AC_CHECK_FUNC
+# because AIX 4.3.3 with patches for bos.adt.include to version 4.3.3.77
+# reportedly defines strsep() without declaring it in <string.h> when
+# -D_LINUX_SOURCE_COMPAT is not defined [RT #2190], and
+# AC_CHECK_FUNC() incorrectly succeeds because it declares
+# the function itself.
+AC_MSG_CHECKING(for correctly declared strsep())
+AC_TRY_LINK([#include <string.h>], [char *sp; char *foo = strsep(&sp, ".");],
+ [AC_MSG_RESULT(yes); ISC_PLATFORM_NEEDSTRSEP="#undef ISC_PLATFORM_NEEDSTRSEP"],
+ [AC_MSG_RESULT(no); ISC_PLATFORM_NEEDSTRSEP="#define ISC_PLATFORM_NEEDSTRSEP 1"])
+AC_SUBST(ISC_PLATFORM_NEEDSTRSEP)
+
+AC_CHECK_FUNC(memmove,
+ [ISC_PLATFORM_NEEDMEMMOVE="#undef ISC_PLATFORM_NEEDMEMMOVE"],
+ [ISC_PLATFORM_NEEDMEMMOVE="#define ISC_PLATFORM_NEEDMEMMOVE 1"])
+AC_SUBST(ISC_PLATFORM_NEEDMEMMOVE)
+
+AC_CHECK_FUNC(strtoul,
+ [ISC_PLATFORM_NEEDSTRTOUL="#undef ISC_PLATFORM_NEEDSTRTOUL"
+ LWRES_PLATFORM_NEEDSTRTOUL="#undef LWRES_PLATFORM_NEEDSTRTOUL"
+ GENRANDOMLIB=""],
+ [ISC_PLATFORM_NEEDSTRTOUL="#define ISC_PLATFORM_NEEDSTRTOUL 1"
+ LWRES_PLATFORM_NEEDSTRTOUL="#define LWRES_PLATFORM_NEEDSTRTOUL 1"
+ GENRANDOMLIB='${ISCLIBS}'])
+AC_SUBST(ISC_PLATFORM_NEEDSTRTOUL)
+AC_SUBST(LWRES_PLATFORM_NEEDSTRTOUL)
+AC_SUBST(GENRANDOMLIB)
+
+AC_CHECK_FUNC(strlcpy,
+ [ISC_PLATFORM_NEEDSTRLCPY="#undef ISC_PLATFORM_NEEDSTRLCPY"],
+ [ISC_PLATFORM_NEEDSTRLCPY="#define ISC_PLATFORM_NEEDSTRLCPY 1"])
+AC_SUBST(ISC_PLATFORM_NEEDSTRLCPY)
+
+AC_CHECK_FUNC(strlcat,
+ [ISC_PLATFORM_NEEDSTRLCAT="#undef ISC_PLATFORM_NEEDSTRLCAT"],
+ [ISC_PLATFORM_NEEDSTRLCAT="#define ISC_PLATFORM_NEEDSTRLCAT 1"])
+AC_SUBST(ISC_PLATFORM_NEEDSTRLCAT)
+
+ISC_PRINT_OBJS=
+ISC_PRINT_SRCS=
+AC_MSG_CHECKING(sprintf)
+AC_TRY_COMPILE([
+#include <stdio.h>
+],
+[ char buf[2]; return(*sprintf(buf,"x"));],
+[
+ISC_PRINT_OBJS="print.$O"
+ISC_PRINT_SRCS="print.c"
+ISC_PLATFORM_NEEDSPRINTF="#define ISC_PLATFORM_NEEDSPRINTF"
+LWRES_PLATFORM_NEEDSPRINTF="#define LWRES_PLATFORM_NEEDSPRINTF"
+],
+[ISC_PLATFORM_NEEDSPRINTF="#undef ISC_PLATFORM_NEEDSPRINTF"
+ LWRES_PLATFORM_NEEDSPRINTF="#undef LWRES_PLATFORM_NEEDSPRINTF"]
+)
+AC_SUBST(ISC_PLATFORM_NEEDSPRINTF)
+AC_SUBST(LWRES_PLATFORM_NEEDSPRINTF)
+
+AC_CHECK_FUNC(vsnprintf,
+ [ISC_PLATFORM_NEEDVSNPRINTF="#undef ISC_PLATFORM_NEEDVSNPRINTF"
+ LWRES_PLATFORM_NEEDVSNPRINTF="#undef LWRES_PLATFORM_NEEDVSNPRINTF"],
+ [ISC_PRINT_OBJS="print.$O"
+ ISC_PRINT_SRCS="print.c"
+ ISC_PLATFORM_NEEDVSNPRINTF="#define ISC_PLATFORM_NEEDVSNPRINTF 1"
+ LWRES_PLATFORM_NEEDVSNPRINTF="#define LWRES_PLATFORM_NEEDVSNPRINTF 1"])
+AC_SUBST(ISC_PLATFORM_NEEDVSNPRINTF)
+AC_SUBST(LWRES_PLATFORM_NEEDVSNPRINTF)
+ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS $ISC_PRINT_OBJS"
+ISC_EXTRA_SRCS="$ISC_EXTRA_SRCS $ISC_PRINT_SRCS"
+
+AC_CHECK_FUNC(strerror, AC_DEFINE(HAVE_STRERROR))
+
+AC_SUBST(ISC_EXTRA_OBJS)
+AC_SUBST(ISC_EXTRA_SRCS)
+
+#
+# Use our own SPNEGO implementation?
+#
+AC_ARG_ENABLE(isc-spnego,
+ [ --disable-isc-spnego use SPNEGO from GSSAPI library])
+
+if test -n "$USE_GSSAPI"
+then
+ case "$enable_isc_spnego" in
+ yes|'')
+ USE_ISC_SPNEGO='-DUSE_ISC_SPNEGO'
+ DST_EXTRA_OBJS="$DST_EXTRA_OBJS spnego.$O"
+ DST_EXTRA_SRCS="$DST_EXTRA_SRCS spnego.c"
+ AC_MSG_RESULT(using SPNEGO from lib/dns)
+ ;;
+ no)
+ AC_MSG_RESULT(using SPNEGO from GSSAPI library)
+ ;;
+ esac
+fi
+
+AC_SUBST(USE_ISC_SPNEGO)
+
+AC_SUBST(DST_EXTRA_OBJS)
+AC_SUBST(DST_EXTRA_SRCS)
+
+# Determine the printf format characters to use when printing
+# values of type isc_int64_t. This will normally be "ll", but where
+# the compiler treats "long long" as a alias for "long" and printf
+# doesn't know about "long long" use "l". Hopefully the sprintf
+# will produce a inconsistant result in the later case. If the compiler
+# fails due to seeing "%lld" we fall back to "l".
+#
+# Digital Unix 4.0 (gcc?) (long long) is 64 bits as is its long. It uses
+# %ld even for (long long)/
+#
+# Win32 uses "%I64d", but that's defined elsewhere since we don't use
+# configure on Win32.
+#
+AC_MSG_CHECKING(printf format modifier for 64-bit integers)
+AC_TRY_RUN([
+#include <stdio.h>
+main() {
+ long long int j = 0;
+ char buf[100];
+ buf[0] = 0;
+ sprintf(buf, "%lld", j);
+ exit((sizeof(long long int) != sizeof(long int))? 0 :
+ (strcmp(buf, "0") != 0));
+}
+],
+ [AC_MSG_RESULT(ll)
+ ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "ll"'
+ LWRES_PLATFORM_QUADFORMAT='#define LWRES_PLATFORM_QUADFORMAT "ll"'],
+ [AC_MSG_RESULT(l)
+ ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "l"'
+ LWRES_PLATFORM_QUADFORMAT='#define LWRES_PLATFORM_QUADFORMAT "l"'],
+ [AC_MSG_RESULT(assuming target platform uses ll)
+ ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "ll"'
+ LWRES_PLATFORM_QUADFORMAT='#define LWRES_PLATFORM_QUADFORMAT "ll"'])
+AC_SUBST(ISC_PLATFORM_QUADFORMAT)
+AC_SUBST(LWRES_PLATFORM_QUADFORMAT)
+
+#
+# Security Stuff
+#
+AC_CHECK_FUNC(chroot, AC_DEFINE(HAVE_CHROOT))
+AC_ARG_ENABLE(linux-caps,
+ [ --disable-linux-caps disable linux capabilities])
+case "$enable_linux_caps" in
+ yes|'')
+ AC_CHECK_HEADERS(linux/capability.h sys/capability.h)
+ AC_CHECK_LIB(cap, cap_set_proc)
+ ;;
+ no)
+ ;;
+esac
+AC_CHECK_HEADERS(sys/prctl.h)
+
+AC_CHECK_HEADERS(sys/un.h,
+ISC_PLATFORM_HAVESYSUNH="#define ISC_PLATFORM_HAVESYSUNH 1"
+,
+ISC_PLATFORM_HAVESYSUNH="#undef ISC_PLATFORM_HAVESYSUNH"
+)
+AC_SUBST(ISC_PLATFORM_HAVESYSUNH)
+
+case "$host" in
+*-solaris*)
+ AC_DEFINE(NEED_SECURE_DIRECTORY, 1,
+ [Define if connect does not honour the permission on the UNIX domain socket.])
+ ;;
+*-sunos*)
+ AC_DEFINE(NEED_SECURE_DIRECTORY, 1,
+ [Define if connect does not honour the permission on the UNIX domain socket.])
+ ;;
+esac
+
+#
+# Time Zone Stuff
+#
+AC_CHECK_FUNC(tzset, AC_DEFINE(HAVE_TZSET))
+
+AC_MSG_CHECKING(for optarg decarartion)
+AC_TRY_COMPILE([
+#include <unistd.h>
+],
+[optarg = 0;],
+[AC_MSG_RESULT(yes)],
+[AC_MSG_RESULT(no)
+GEN_NEED_OPTARG="-DNEED_OPTARG=1"
+AC_DEFINE(NEED_OPTARG, 1, [Defined if extern char *optarg is not declared.])])
+
+#
+# BSD/OS, and perhaps some others, don't define rlim_t.
+#
+AC_MSG_CHECKING(for type rlim_t)
+AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>],
+[rlim_t rl = 19671212; return (0);],
+[AC_MSG_RESULT(yes)
+ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE rlim_t"],
+[AC_MSG_RESULT(no)
+
+AC_MSG_CHECKING(type of rlim_cur)
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(int)));}],
+[AC_MSG_RESULT(int)
+ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE int"],
+[
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(long int)));}],
+[AC_MSG_RESULT(long int)
+ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long int"],
+[
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+main() { struct rlimit r; exit((!sizeof(r.rlim_cur) == sizeof(long long int)));}],
+[AC_MSG_RESULT(long long int)
+ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long long int"],
+[AC_MSG_ERROR([unable to determine sizeof rlim_cur])
+],[AC_MSG_ERROR(this cannot happen)])
+],[AC_MSG_ERROR(this cannot happen)])
+],[
+ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long long int"
+AC_MSG_RESULT(cannot determine type of rlim_cur when cross compiling - assuming long long int)])
+])
+AC_SUBST(ISC_PLATFORM_RLIMITTYPE)
+
+#
+# Older HP-UX doesn't have gettune
+#
+case "$host" in
+ *-hp-hpux*)
+ AC_CHECK_HEADERS(sys/dyntune.h)
+ ;;
+ *)
+ ;;
+esac
+
+
+#
+# Compaq TruCluster requires more code for handling cluster IP aliases
+#
+case "$host" in
+ *-dec-osf*)
+ AC_CHECK_LIB(clua, clua_getaliasaddress, LIBS="-lclua $LIBS")
+ AC_CHECK_FUNC(clua_getaliasaddress,
+ AC_DEFINE(HAVE_TRUCLUSTER, 1,
+ [Define if running under Compaq TruCluster]))
+ ;;
+ *)
+ ;;
+esac
+
+#
+# Some hosts need msg_namelen to match the size of the socket structure.
+# Some hosts don't set msg_namelen appropriately on return from recvmsg().
+#
+case $host in
+*os2*|*hp-mpeix*)
+ AC_DEFINE(BROKEN_RECVMSG, 1,
+ [Define if recvmsg() does not meet all of the BSD socket API specifications.])
+ ;;
+esac
+
+#
+# Microsoft has their own way of handling shared libraries that requires
+# additional qualifiers on extern variables. Unix systems don't need it.
+#
+AC_SUBST(ISC_PLATFORM_USEDECLSPEC)
+ISC_PLATFORM_USEDECLSPEC="#undef ISC_PLATFORM_USEDECLSPEC"
+AC_SUBST(LWRES_PLATFORM_USEDECLSPEC)
+LWRES_PLATFORM_USEDECLSPEC="#undef LWRES_PLATFORM_USEDECLSPEC"
+
+#
+# Random remaining OS-specific issues involving compiler warnings.
+# XXXDCL print messages to indicate some compensation is being done?
+#
+AC_SUBST(ISC_PLATFORM_BRACEPTHREADONCEINIT)
+ISC_PLATFORM_BRACEPTHREADONCEINIT="#undef ISC_PLATFORM_BRACEPTHREADONCEINIT"
+
+case "$host" in
+ *-aix5.[[123]].*)
+ hack_shutup_pthreadonceinit=yes
+ ;;
+ *-bsdi3.1*)
+ hack_shutup_sputaux=yes
+ ;;
+ *-bsdi4.0*)
+ hack_shutup_sigwait=yes
+ hack_shutup_sputaux=yes
+ ;;
+ [*-bsdi4.[12]*])
+ hack_shutup_stdargcast=yes
+ ;;
+ [*-solaris2.[89]])
+ hack_shutup_pthreadonceinit=yes
+ ;;
+ *-solaris2.1[[0-9]])
+ hack_shutup_pthreadonceinit=yes
+ ;;
+esac
+
+case "$hack_shutup_pthreadonceinit" in
+ yes)
+ #
+ # Shut up PTHREAD_ONCE_INIT unbraced initializer warnings.
+ #
+ ISC_PLATFORM_BRACEPTHREADONCEINIT="#define ISC_PLATFORM_BRACEPTHREADONCEINIT 1"
+ ;;
+esac
+
+case "$hack_shutup_sigwait" in
+ yes)
+ #
+ # Shut up a -Wmissing-prototypes warning for sigwait().
+ #
+ AC_DEFINE(SHUTUP_SIGWAIT)
+ ;;
+esac
+
+case "$hack_shutup_sputaux" in
+ yes)
+ #
+ # Shut up a -Wmissing-prototypes warning from <stdio.h>.
+ #
+ AC_DEFINE(SHUTUP_SPUTAUX)
+ ;;
+esac
+
+case "$hack_shutup_stdargcast" in
+ yes)
+ #
+ # Shut up a -Wcast-qual warning from va_start().
+ #
+ AC_DEFINE(SHUTUP_STDARG_CAST)
+ ;;
+esac
+
+AC_CHECK_HEADERS(strings.h,
+ ISC_PLATFORM_HAVESTRINGSH="#define ISC_PLATFORM_HAVESTRINGSH 1"
+,
+ ISC_PLATFORM_HAVESTRINGSH="#undef ISC_PLATFORM_HAVESTRINGSH"
+)
+AC_SUBST(ISC_PLATFORM_HAVESTRINGSH)
+
+#
+# Check for if_nametoindex() for IPv6 scoped addresses support
+#
+AC_CHECK_FUNC(if_nametoindex, ac_cv_have_if_nametoindex=yes,
+ ac_cv_have_if_nametoindex=no)
+case $ac_cv_have_if_nametoindex in
+no)
+ case "$host" in
+ *-hp-hpux*)
+ AC_CHECK_LIB(ipv6, if_nametoindex,
+ ac_cv_have_if_nametoindex=yes
+ LIBS="-lipv6 $LIBS",)
+ ;;
+ esac
+esac
+case $ac_cv_have_if_nametoindex in
+yes)
+ ISC_PLATFORM_HAVEIFNAMETOINDEX="#define ISC_PLATFORM_HAVEIFNAMETOINDEX 1"
+ ;;
+*)
+ ISC_PLATFORM_HAVEIFNAMETOINDEX="#undef ISC_PLATFORM_HAVEIFNAMETOINDEX"
+ ;;
+esac
+AC_SUBST(ISC_PLATFORM_HAVEIFNAMETOINDEX)
+
+#
+# Machine architecture dependent features
+#
+AC_ARG_ENABLE(atomic,
+ [ --enable-atomic enable machine specific atomic operations
+ [[default=autodetect]]],
+ enable_atomic="$enableval",
+ enable_atomic="autodetect")
+case "$enable_atomic" in
+ yes|''|autodetect)
+ use_atomic=yes
+ ;;
+ no)
+ use_atomic=no
+ arch=noatomic
+ ;;
+esac
+
+ISC_PLATFORM_USEOSFASM="#undef ISC_PLATFORM_USEOSFASM"
+if test "$use_atomic" = "yes"; then
+ AC_MSG_CHECKING([architecture type for atomic operations])
+ have_atomic=yes # set default
+ case "$host" in
+ [i[3456]86-*])
+ # XXX: some old x86 architectures actually do not support
+ # (some of) these operations. Do we need stricter checks?
+AC_TRY_RUN([
+main() {
+ exit((sizeof(void *) == 8) ? 0 : 1);
+}
+],
+ [arch=x86_64
+ have_xaddq=yes],
+ [arch=x86_32],
+ [arch=x86_32])
+ ;;
+ x86_64-*)
+ have_xaddq=yes
+ arch=x86_64
+ ;;
+ alpha*-*)
+ arch=alpha
+ ;;
+ powerpc-*)
+ arch=powerpc
+ ;;
+ mips-*|mipsel-*|mips64-*|mips64el-*)
+ arch=mips
+ ;;
+ ia64-*)
+ arch=ia64
+ ;;
+ *)
+ have_atomic=no
+ arch=noatomic
+ ;;
+ esac
+ AC_MSG_RESULT($arch)
+fi
+
+if test "$have_atomic" = "yes"; then
+ AC_MSG_CHECKING([compiler support for inline assembly code])
+
+ compiler=generic
+ # Check whether the compiler supports the assembly syntax we provide.
+ if test "X$GCC" = "Xyes"; then
+ # GCC's ASM extension always works
+ compiler=gcc
+ if test $arch = "x86_64"; then
+ # We can share the same code for gcc with x86_32
+ arch=x86_32
+ fi
+ if test $arch = "powerpc"; then
+ #
+ # The MacOS (and maybe others) uses "r0" for register
+ # zero. Under linux/ibm it is "0" for register 0.
+ # Probe to see if we have a MacOS style assembler.
+ #
+ AC_MSG_CHECKING([Checking for MacOS style assembler syntax])
+ AC_TRY_COMPILE(, [
+ __asm__ volatile ("li r0, 0x0\n"::);
+ ], [
+ AC_MSG_RESULT(yes)
+ compiler="mac"
+ ISC_PLATFORM_USEMACASM="#define ISC_PLATFORM_USEMACASM 1"
+ ], [AC_MSG_RESULT(no)])
+ fi
+ else
+ case "$host" in
+ alpha*-dec-osf*)
+ # Tru64 compiler has its own syntax for inline
+ # assembly.
+ AC_TRY_COMPILE(, [
+#ifndef __DECC
+#error "unexpected compiler"
+#endif
+ return (0);],
+ [compiler=osf],)
+ ;;
+ powerpc-ibm-aix*)
+ compiler=aix
+ ;;
+ esac
+ fi
+ case "$compiler" in
+ gcc)
+ ISC_PLATFORM_USEGCCASM="#define ISC_PLATFORM_USEGCCASM 1"
+ ;;
+ osf)
+ ISC_PLATFORM_USEOSFASM="#define ISC_PLATFORM_USEOSFASM 1"
+ ;;
+ aix)
+ ;;
+ mac)
+ ;;
+ *)
+ # See if the generic __asm function works. If not,
+ # we need to disable the atomic operations.
+ AC_TRY_LINK(, [
+ __asm("nop")
+ ],
+ [compiler="standard"
+ ISC_PLATFORM_USESTDASM="#define ISC_PLATFORM_USESTDASM 1"],
+ [compiler="not supported (atomic operations disabled)"
+ have_atomic=no
+ arch=noatomic ]);
+ ;;
+ esac
+
+ AC_MSG_RESULT($compiler)
+fi
+
+if test "$have_atomic" = "yes"; then
+ ISC_PLATFORM_HAVEXADD="#define ISC_PLATFORM_HAVEXADD 1"
+ ISC_PLATFORM_HAVECMPXCHG="#define ISC_PLATFORM_HAVECMPXCHG 1"
+ ISC_PLATFORM_HAVEATOMICSTORE="#define ISC_PLATFORM_HAVEATOMICSTORE 1"
+else
+ ISC_PLATFORM_HAVEXADD="#undef ISC_PLATFORM_HAVEXADD"
+ ISC_PLATFORM_HAVECMPXCHG="#undef ISC_PLATFORM_HAVECMPXCHG"
+ ISC_PLATFORM_HAVEATOMICSTORE="#undef ISC_PLATFORM_HAVEATOMICSTORE"
+fi
+
+if test "$have_xaddq" = "yes"; then
+ ISC_PLATFORM_HAVEXADDQ="#define ISC_PLATFORM_HAVEXADDQ 1"
+else
+ ISC_PLATFORM_HAVEXADDQ="#undef ISC_PLATFORM_HAVEXADDQ"
+fi
+
+AC_SUBST(ISC_PLATFORM_HAVEXADD)
+AC_SUBST(ISC_PLATFORM_HAVEXADDQ)
+AC_SUBST(ISC_PLATFORM_HAVECMPXCHG)
+AC_SUBST(ISC_PLATFORM_HAVEATOMICSTORE)
+
+AC_SUBST(ISC_PLATFORM_USEGCCASM)
+AC_SUBST(ISC_PLATFORM_USEOSFASM)
+AC_SUBST(ISC_PLATFORM_USESTDASM)
+AC_SUBST(ISC_PLATFORM_USEMACASM)
+
+ISC_ARCH_DIR=$arch
+AC_SUBST(ISC_ARCH_DIR)
+
+#
+# Activate "rrset-order fixed" or not?
+#
+AC_ARG_ENABLE(fixed-rrset,
+ [ --enable-fixed-rrset enable fixed rrset ordering
+ [[default=no]]],
+ enable_fixed="$enableval",
+ enable_fixed="no")
+case "$enable_fixed" in
+ yes)
+ AC_DEFINE(DNS_RDATASET_FIXED, 1,
+ [Define to enable "rrset-order fixed" syntax.])
+ ;;
+ no)
+ ;;
+ *)
+ ;;
+esac
+
+#
+# The following sets up how non-blocking i/o is established.
+# Sunos, cygwin and solaris 2.x (x<5) require special handling.
+#
+case "$host" in
+*-sunos*) AC_DEFINE(PORT_NONBLOCK, O_NDELAY);;
+*-cygwin*) AC_DEFINE(PORT_NONBLOCK, O_NDELAY);;
+*-solaris2.[[01234]])
+ AC_DEFINE(PORT_NONBLOCK, O_NONBLOCK)
+ AC_DEFINE(USE_FIONBIO_IOCTL, 1,
+ [Defined if you need to use ioctl(FIONBIO) instead a fcntl call to make non-blocking.])
+ ;;
+*) AC_DEFINE(PORT_NONBLOCK, O_NONBLOCK,
+ [Sets which flag to pass to open/fcntl to make non-blocking (O_NDELAY/O_NONBLOCK).])
+ ;;
+esac
+#
+# Solaris 2.5.1 and earlier cannot bind() then connect() a TCP socket.
+# This prevents the source address being set.
+#
+case "$host" in
+*-solaris2.[[012345]]|*-solaris2.5.1)
+ AC_DEFINE(BROKEN_TCP_BIND_BEFORE_CONNECT, 1,
+ [Define if you cannot bind() before connect() for TCP sockets.])
+ ;;
+esac
+#
+# The following sections deal with tools used for formatting
+# the documentation. They are all optional, unless you are
+# a developer editing the documentation source.
+#
+
+#
+# Look for TeX.
+#
+
+AC_PATH_PROGS(LATEX, latex, latex)
+AC_SUBST(LATEX)
+
+AC_PATH_PROGS(PDFLATEX, pdflatex, pdflatex)
+AC_SUBST(PDFLATEX)
+
+#
+# Look for w3m
+#
+
+AC_PATH_PROGS(W3M, w3m, w3m)
+AC_SUBST(W3M)
+
+#
+# Look for xsltproc (libxslt)
+#
+
+AC_PATH_PROG(XSLTPROC, xsltproc, xsltproc)
+AC_SUBST(XSLTPROC)
+
+#
+# Look for xmllint (libxml2)
+#
+
+AC_PATH_PROG(XMLLINT, xmllint, xmllint)
+AC_SUBST(XMLLINT)
+
+#
+# Look for Doxygen
+#
+
+AC_PATH_PROG(DOXYGEN, doxygen, doxygen)
+AC_SUBST(DOXYGEN)
+
+#
+# Subroutine for searching for an ordinary file (e.g., a stylesheet)
+# in a number of directories:
+#
+# NOM_PATH_FILE(VARIABLE, FILENAME, DIRECTORIES)
+#
+# If the file FILENAME is found in one of the DIRECTORIES, the shell
+# variable VARIABLE is defined to its absolute pathname. Otherwise,
+# it is set to FILENAME, with no directory prefix (that's not terribly
+# useful, but looks less confusing in substitutions than leaving it
+# empty). The variable VARIABLE will be substituted into output files.
+#
+
+AC_DEFUN(NOM_PATH_FILE, [
+$1=""
+AC_MSG_CHECKING(for $2)
+for d in $3
+do
+ f=$d/$2
+ if test -f $f
+ then
+ $1=$f
+ AC_MSG_RESULT($f)
+ break
+ fi
+done
+if test "X[$]$1" = "X"
+then
+ AC_MSG_RESULT("not found");
+ $1=$2
+fi
+AC_SUBST($1)
+])
+
+#
+# Look for Docbook-XSL stylesheets. Location probably varies by system.
+# If it's not explicitly specified, guess where it might be found, based on
+# where SGML stuff lives on some systems (FreeBSD is the only one we're sure
+# of at the moment).
+#
+AC_MSG_CHECKING(for Docbook-XSL path)
+AC_ARG_WITH(docbook-xsl,
+[ --with-docbook-xsl=PATH Specify path for Docbook-XSL stylesheets],
+ docbook_path="$withval", docbook_path="auto")
+case "$docbook_path" in
+auto)
+ AC_MSG_RESULT(auto)
+ docbook_xsl_trees="/usr/pkg/share/xsl/docbook /usr/local/share/xsl/docbook /usr/share/xsl/docbook"
+ ;;
+*)
+ docbook_xsl_trees="$withval"
+ AC_MSG_RESULT($docbook_xsl_trees)
+ ;;
+esac
+
+#
+# Look for stylesheets we need.
+#
+
+NOM_PATH_FILE(XSLT_DOCBOOK_STYLE_HTML, html/docbook.xsl, $docbook_xsl_trees)
+NOM_PATH_FILE(XSLT_DOCBOOK_STYLE_XHTML, xhtml/docbook.xsl, $docbook_xsl_trees)
+NOM_PATH_FILE(XSLT_DOCBOOK_STYLE_MAN, manpages/docbook.xsl, $docbook_xsl_trees)
+NOM_PATH_FILE(XSLT_DOCBOOK_CHUNK_HTML, html/chunk.xsl, $docbook_xsl_trees)
+NOM_PATH_FILE(XSLT_DOCBOOK_CHUNK_XHTML, xhtml/chunk.xsl, $docbook_xsl_trees)
+NOM_PATH_FILE(XSLT_DOCBOOK_CHUNKTOC_HTML, html/chunktoc.xsl, $docbook_xsl_trees)
+NOM_PATH_FILE(XSLT_DOCBOOK_CHUNKTOC_XHTML, xhtml/chunktoc.xsl, $docbook_xsl_trees)
+NOM_PATH_FILE(XSLT_DOCBOOK_MAKETOC_HTML, html/maketoc.xsl, $docbook_xsl_trees)
+NOM_PATH_FILE(XSLT_DOCBOOK_MAKETOC_XHTML, xhtml/maketoc.xsl, $docbook_xsl_trees)
+
+#
+# Same dance for db2latex
+#
+# No idea where this lives except on FreeBSD.
+#
+
+db2latex_xsl_trees="/usr/local/share"
+
+#
+# Look for stylesheets we need.
+#
+
+NOM_PATH_FILE(XSLT_DB2LATEX_STYLE, db2latex/xsl/docbook.xsl, $db2latex_xsl_trees)
+
+#
+# Look for "admonition" image directory. Can't use NOM_PATH_FILE()
+# because it's a directory, so just do the same things, inline.
+#
+
+AC_MSG_CHECKING(for db2latex/xsl/figures)
+for d in $db2latex_xsl_trees
+do
+ dd=$d/db2latex/xsl/figures
+ if test -d $dd
+ then
+ XSLT_DB2LATEX_ADMONITIONS=$dd
+ AC_MSG_RESULT($dd)
+ break
+ fi
+done
+if test "X$XSLT_DB2LATEX_ADMONITIONS" = "X"
+then
+ AC_MSG_RESULT(not found)
+ XSLT_DB2LATEX_ADMONITIONS=db2latex/xsl/figures
+fi
+AC_SUBST(XSLT_DB2LATEX_ADMONITIONS)
+
+#
+# IDN support
+#
+AC_ARG_WITH(idn,
+ [ --with-idn[=MPREFIX] enable IDN support using idnkit [default PREFIX]],
+ use_idn="$withval", use_idn="no")
+case "$use_idn" in
+yes)
+ if test X$prefix = XNONE ; then
+ idn_path=/usr/local
+ else
+ idn_path=$prefix
+ fi
+ ;;
+no)
+ ;;
+*)
+ idn_path="$use_idn"
+ ;;
+esac
+
+iconvinc=
+iconvlib=
+AC_ARG_WITH(libiconv,
+ [ --with-libiconv[=IPREFIX] GNU libiconv are in IPREFIX [default PREFIX]],
+ use_libiconv="$withval", use_libiconv="no")
+case "$use_libiconv" in
+yes)
+ if test X$prefix = XNONE ; then
+ iconvlib="-L/usr/local/lib -R/usr/local/lib -liconv"
+ else
+ iconvlib="-L$prefix/lib -R$prefix/lib -liconv"
+ fi
+ ;;
+no)
+ iconvlib=
+ ;;
+*)
+ iconvlib="-L$use_libiconv/lib -R$use_libiconv/lib -liconv"
+ ;;
+esac
+
+AC_ARG_WITH(iconv,
+ [ --with-iconv[=LIBSPEC] specify iconv library [default -liconv]],
+ iconvlib="$withval")
+case "$iconvlib" in
+no)
+ iconvlib=
+ ;;
+yes)
+ iconvlib=-liconv
+ ;;
+esac
+
+AC_ARG_WITH(idnlib,
+ [ --with-idnlib=ARG specify libidnkit],
+ idnlib="$withval", idnlib="no")
+if test "$idnlib" = yes; then
+ AC_MSG_ERROR([You must specify ARG for --with-idnlib.])
+fi
+
+IDNLIBS=
+if test "$use_idn" != no; then
+ AC_DEFINE(WITH_IDN, 1, [define if idnkit support is to be included.])
+ STD_CINCLUDES="$STD_CINCLUDES -I$idn_path/include"
+ if test "$idnlib" != no; then
+ IDNLIBS="$idnlib $iconvlib"
+ else
+ IDNLIBS="-L$idn_path/lib -lidnkit $iconvlib"
+ fi
+fi
+AC_SUBST(IDNLIBS)
+
+AC_CHECK_HEADERS(locale.h)
+AC_CHECK_FUNCS(setlocale)
+
+#
+# Substitutions
+#
+AC_SUBST(BIND9_TOP_BUILDDIR)
+BIND9_TOP_BUILDDIR=`pwd`
+
+AC_SUBST(BIND9_ISC_BUILDINCLUDE)
+AC_SUBST(BIND9_ISCCC_BUILDINCLUDE)
+AC_SUBST(BIND9_ISCCFG_BUILDINCLUDE)
+AC_SUBST(BIND9_DNS_BUILDINCLUDE)
+AC_SUBST(BIND9_LWRES_BUILDINCLUDE)
+AC_SUBST(BIND9_BIND9_BUILDINCLUDE)
+if test "X$srcdir" != "X"; then
+ BIND9_ISC_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isc/include"
+ BIND9_ISCCC_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isccc/include"
+ BIND9_ISCCFG_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/isccfg/include"
+ BIND9_DNS_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/dns/include"
+ BIND9_LWRES_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/lwres/include"
+ BIND9_BIND9_BUILDINCLUDE="-I${BIND9_TOP_BUILDDIR}/lib/bind9/include"
+else
+ BIND9_ISC_BUILDINCLUDE=""
+ BIND9_ISCCC_BUILDINCLUDE=""
+ BIND9_ISCCFG_BUILDINCLUDE=""
+ BIND9_DNS_BUILDINCLUDE=""
+ BIND9_LWRES_BUILDINCLUDE=""
+ BIND9_BIND9_BUILDINCLUDE=""
+fi
+
+AC_SUBST_FILE(BIND9_MAKE_INCLUDES)
+BIND9_MAKE_INCLUDES=$BIND9_TOP_BUILDDIR/make/includes
+
+AC_SUBST_FILE(BIND9_MAKE_RULES)
+BIND9_MAKE_RULES=$BIND9_TOP_BUILDDIR/make/rules
+
+. $srcdir/version
+BIND9_VERSION="VERSION=${MAJORVER}.${MINORVER}.${PATCHVER}${RELEASETYPE}${RELEASEVER}"
+AC_SUBST(BIND9_VERSION)
+
+if test -z "$ac_configure_args"; then
+ BIND9_CONFIGARGS="defaults"
+else
+ for a in $ac_configure_args
+ do
+ BIND9_CONFIGARGS="$BIND9_CONFIGARGS $a"
+ done
+fi
+BIND9_CONFIGARGS="`echo $BIND9_CONFIGARGS | sed 's/^ //'`"
+BIND9_CONFIGARGS="CONFIGARGS=${BIND9_CONFIGARGS}"
+AC_SUBST(BIND9_CONFIGARGS)
+
+AC_SUBST_FILE(LIBISC_API)
+LIBISC_API=$srcdir/lib/isc/api
+
+AC_SUBST_FILE(LIBISCCC_API)
+LIBISCCC_API=$srcdir/lib/isccc/api
+
+AC_SUBST_FILE(LIBISCCFG_API)
+LIBISCCFG_API=$srcdir/lib/isccfg/api
+
+AC_SUBST_FILE(LIBDNS_API)
+LIBDNS_API=$srcdir/lib/dns/api
+
+AC_SUBST_FILE(LIBBIND9_API)
+LIBBIND9_API=$srcdir/lib/bind9/api
+
+AC_SUBST_FILE(LIBLWRES_API)
+LIBLWRES_API=$srcdir/lib/lwres/api
+
+#
+# Configure any DLZ drivers.
+#
+# If config.dlz.in selects one or more DLZ drivers, it will set
+# USE_DLZ to a non-empty value, which will be our clue to
+# enable the DLZ core functions.
+#
+# This section has to come after the libtool stuff because it needs to
+# know how to name the driver object files.
+#
+
+USE_DLZ=""
+DLZ_DRIVER_INCLUDES=""
+DLZ_DRIVER_LIBS=""
+DLZ_DRIVER_SRCS=""
+DLZ_DRIVER_OBJS=""
+
+sinclude(contrib/dlz/config.dlz.in)
+
+AC_MSG_CHECKING(for DLZ)
+
+if test -n "$USE_DLZ"
+then
+ AC_MSG_RESULT(yes)
+ USE_DLZ="-DDLZ $USE_DLZ"
+ DLZ_DRIVER_RULES=contrib/dlz/drivers/rules
+ AC_CONFIG_FILES([$DLZ_DRIVER_RULES])
+else
+ AC_MSG_RESULT(no)
+ DLZ_DRIVER_RULES=/dev/null
+fi
+
+AC_SUBST(USE_DLZ)
+AC_SUBST(DLZ_DRIVER_INCLUDES)
+AC_SUBST(DLZ_DRIVER_LIBS)
+AC_SUBST(DLZ_DRIVER_SRCS)
+AC_SUBST(DLZ_DRIVER_OBJS)
+AC_SUBST_FILE(DLZ_DRIVER_RULES)
+
+if test "$cross_compiling" = "yes"; then
+ if test -z "$BUILD_CC"; then
+ AC_ERROR([BUILD_CC not set])
+ fi
+ BUILD_CFLAGS="$BUILD_CFLAGS"
+ BUILD_CPPFLAGS="$BUILD_CPPFLAGS"
+ BUILD_LDFLAGS="$BUILD_LDFLAGS"
+ BUILD_LIBS="$BUILD_LIBS"
+else
+ BUILD_CC="$CC"
+ BUILD_CFLAGS="$CFLAGS"
+ BUILD_CPPFLAGS="$CPPFLAGS $GEN_NEED_OPTARG"
+ BUILD_LDFLAGS="$LDFLAGS"
+ BUILD_LIBS="$LIBS"
+fi
+
+NEWFLAGS=""
+for e in $BUILD_LDFLAGS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ solaris*)
+ ee=`echo $e | sed -e 's%^-L%-R%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+BUILD_LDFLAGS="$NEWFLAGS"
+
+NEWFLAGS=""
+for e in $DNS_GSSAPI_LIBS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ solaris*)
+ ee=`echo $e | sed -e 's%^-L%-R%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+DNS_GSSAPI_LIBS="$NEWFLAGS"
+
+NEWFLAGS=""
+for e in $DNS_CRYPTO_LIBS ; do
+ case $e in
+ -L*)
+ case $host_os in
+ netbsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ freebsd*)
+ ee=`echo $e | sed -e 's%^-L%-Wl,-rpath,%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ solaris*)
+ ee=`echo $e | sed -e 's%^-L%-R%'`
+ NEWFLAGS="$NEWFLAGS $e $ee"
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+ ;;
+ *)
+ NEWFLAGS="$NEWFLAGS $e"
+ ;;
+ esac
+done
+DNS_CRYPTO_LIBS="$NEWFLAGS"
+
+AC_SUBST(BUILD_CC)
+AC_SUBST(BUILD_CFLAGS)
+AC_SUBST(BUILD_CPPFLAGS)
+AC_SUBST(BUILD_LDFLAGS)
+AC_SUBST(BUILD_LIBS)
+
+#
+# Commands to run at the end of config.status.
+# Don't just put these into configure, it won't work right if somebody
+# runs config.status directly (which autoconf allows).
+#
+
+AC_CONFIG_COMMANDS(
+ [chmod],
+ [chmod a+x isc-config.sh doc/doxygen/doxygen-input-filter])
+
+#
+# Files to configure. These are listed here because we used to
+# specify them as arguments to AC_OUTPUT. It's (now) ok to move these
+# elsewhere if there's a good reason for doing so.
+#
+
+AC_CONFIG_FILES([
+ Makefile
+ make/Makefile
+ make/mkdep
+ lib/Makefile
+ lib/isc/Makefile
+ lib/isc/include/Makefile
+ lib/isc/include/isc/Makefile
+ lib/isc/include/isc/platform.h
+ 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
+ lib/lwres/include/lwres/netdb.h
+ lib/lwres/include/lwres/platform.h
+ lib/lwres/man/Makefile
+ lib/lwres/unix/Makefile
+ lib/lwres/unix/include/Makefile
+ lib/lwres/unix/include/lwres/Makefile
+ 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/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
+])
+
+#
+# Do it
+#
+
+AC_OUTPUT
+
+if test "X$OPENSSL_WARNING" != "X"; then
+cat << \EOF
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+WARNING WARNING
+WARNING Your OpenSSL crypto library may be vulnerable to WARNING
+WARNING one or more of the the following known security WARNING
+WARNING flaws: WARNING
+WARNING WARNING
+WARNING CAN-2002-0659, CAN-2006-4339, CVE-2006-2937 and WARNING
+WARNING CVE-2006-2940. WARNING
+WARNING WARNING
+WARNING It is recommended that you upgrade to OpenSSL WARNING
+WARNING version 0.9.8d/0.9.7l (or greater). WARNING
+WARNING WARNING
+WARNING You can disable this warning by specifying: WARNING
+WARNING WARNING
+WARNING --disable-openssl-version-check WARNING
+WARNING WARNING
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+EOF
+fi
+
+# Tell Emacs to edit this file in shell mode.
+# Local Variables:
+# mode: sh
+# End:
diff --git a/contrib/dbus/GetForwarders b/contrib/dbus/GetForwarders
new file mode 100755
index 0000000..838706d
--- /dev/null
+++ b/contrib/dbus/GetForwarders
@@ -0,0 +1,31 @@
+#!/bin/bash
+#
+# This script uses the named D-BUS support, which must be enabled in
+# the running named with the named '-D' option, to get and print the
+# list of forwarding zones in the running server.
+#
+# It accepts an optional <zone> first argument which is the DNS name
+# of the zone whose forwarders (if any) will be retrieved.
+#
+# If no zone argument is specified, all forwarding zones will be listed.
+#
+# Usage: GetForwarders [ <zone> ]
+#
+# Copyright(C) Jason Vas Dias<jvdias@redhat.com> Red Hat Inc. 2005
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation at
+# http://www.fsf.org/licensing/licenses/gpl.txt
+# and included in this software distribution as the "LICENSE" file.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+zone=''
+if [ $# -gt 0 ]; then
+ zone="string:$1";
+fi
+dbus-send --system --type=method_call --print-reply --reply-timeout=20000 --dest=com.redhat.named /com/redhat/named com.redhat.named.text.GetForwarders $zone;
diff --git a/contrib/dbus/INSTALL b/contrib/dbus/INSTALL
new file mode 100644
index 0000000..2ad526e
--- /dev/null
+++ b/contrib/dbus/INSTALL
@@ -0,0 +1,9 @@
+To build named with D-BUS support, run
+# make
+in this directory.
+Then cd to the top-level BIND source directory,
+(../..), and
+# ./configure ...; make
+After building, cd back to contrib/dbus and run:
+# make install
+as root to install the D-BUS configuration files.
diff --git a/contrib/dbus/Makefile.9.3.2b1 b/contrib/dbus/Makefile.9.3.2b1
new file mode 100644
index 0000000..6285034
--- /dev/null
+++ b/contrib/dbus/Makefile.9.3.2b1
@@ -0,0 +1,20 @@
+# contrib/dbus/Makefile
+#
+# This Makefile will install D-BUS support into the ISC BIND 9.3.2b1+ source,
+# necessary to support dynamic forwarding table management with D-BUS, for
+# Red Hat NetworkManager support.
+#
+# After running "make" in this directory, simply run make in the top level
+# BIND source directory, and D-BUS support will be enabled.
+#
+
+all:
+ echo 'Enabling D-BUS support...'
+ @ cp -fp dbus_mgr.c dbus_service.c ../../bin/named;
+ @ cp -fp dbus_mgr.h dbus_service.h ../../bin/named/include/named;
+ @ cp -fp README.DBUS ../../doc/misc
+ @ cd ../..; patch -s -p1 -b --suffix=.dbus < contrib/dbus/bind-9.3.2b1-dbus.patch
+
+install:
+ install -o root -g root -m 640 named-dbus-system.conf /etc/dbus-1/system.d/named.conf
+ install -o root -g root -m 640 named-dbus.service /usr/share/dbus-1/services/named.service
diff --git a/contrib/dbus/Makefile.9.3.3rc2 b/contrib/dbus/Makefile.9.3.3rc2
new file mode 100644
index 0000000..91a0ffe
--- /dev/null
+++ b/contrib/dbus/Makefile.9.3.3rc2
@@ -0,0 +1,20 @@
+# contrib/dbus/Makefile
+#
+# This Makefile will install D-BUS support into the ISC BIND 9.3.2b1+ source,
+# necessary to support dynamic forwarding table management with D-BUS, for
+# Red Hat NetworkManager support.
+#
+# After running "make" in this directory, simply run make in the top level
+# BIND source directory, and D-BUS support will be enabled.
+#
+
+all:
+ echo 'Enabling D-BUS support...'
+ @ cp -fp dbus_mgr.c dbus_service.c ../../bin/named;
+ @ cp -fp dbus_mgr.h dbus_service.h ../../bin/named/include/named;
+ @ cp -fp README.DBUS ../../doc/misc
+ @ cd ../..; patch -s -p1 -b --suffix=.dbus < contrib/dbus/bind-9.3.3rc2-dbus.patch
+
+install:
+ install -o root -g root -m 640 named-dbus-system.conf /etc/dbus-1/system.d/named.conf
+ install -o root -g root -m 640 named-dbus.service /usr/share/dbus-1/services/named.service
diff --git a/contrib/dbus/README.DBUS b/contrib/dbus/README.DBUS
new file mode 100644
index 0000000..8c5c73f
--- /dev/null
+++ b/contrib/dbus/README.DBUS
@@ -0,0 +1,259 @@
+Dynamic Management of the ISC BIND named Forwarding Table with D-BUS
+
+ Jason Vas Dias<jvdias@redhat.com>, Red Hat Inc., May 2005
+
+
+Overview:
+
+ Red Hat has developed an extension to named that is enabled during
+ rpmbuild of the bind SRPM with the option --define 'WITH_DBUS=1',
+ and at named runtime with the -D named option.
+
+ You can obtain the latest version of the source code for the BIND
+ D-BUS extensions from:
+
+ http://people.redhat.com/~jvdias/bind-dbus/
+
+ The Red Hat BIND D-BUS extensions allow services such as Red Hat's
+ NetworkManager and dhcdbd (the DHCP Client controller D-Bus daemon)
+ to tell named which name servers to forward requests to dynamically,
+ instead of only with the "forward" and "forwarders" named.conf options.
+
+ Dynamic forwarding table management allows named to be an effective
+ and efficient caching nameserver for configurations with multiple
+ wireless or VPN IP interfaces that are not always active, and whose
+ name service parameters are typically configured with DHCP.
+
+ Problems with trying to configure such systems automatically using
+ only the libc resolver, causing conflicts over the contents of the
+ /etc/resolv.conf file, are avoided; the resolv.conf file can contain
+ only the users chosen search path and the single "nameserver 127.0.0.1"
+ entry.
+
+ named also provides a much more efficient, both in terms of caching
+ performance and resolving time, and much more feature rich DNS resolver
+ than does the libc resolver library and nscd, and has the benefit of
+ existing improved IPv6 and DNSSEC support over glibc and nscd.
+
+Operation Guide for Developers:
+
+ Programs can access named's dynamic forward table management services
+ using D-BUS, the "service messagebus" sysv-init service that is started
+ by default at boot (see the D-BUS documentation for details).
+
+ When named is started with the -D option (by adding -D to the $OPTIONS
+ variable in /etc/sysconfig/named), named provides two D-BUS methods:
+
+ These D-BUS names are common to all named D-BUS methods:
+ D-BUS Destination D-BUS Path D-BUS interface
+ ~~~~~~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~~~~~~~~~~
+ com.redhat.named /com/redhat/named com.redhat.named
+
+ D-BUS Members:
+ ~~~~~~~~~~~~~~
+
+ SetForwarders ( { [ string:<domain name>,
+ ~~~~~~~~~~~~~ [ ( uint32:<nameserver IPv4 address>
+ | array of 4 bytes : <nameserver IPv4 address>
+ | array of 16 bytes : <nameserver IPv6 address>
+ | string: <nameserver dotted-quad IPv4 or RFC2374 IPv6 address>
+ )
+ [ uint16: <nameserver port>, ]
+ [ uint8: <forward policy> ]
+ ]
+ ]
+ } , ...
+ )
+
+ SetForwarders will create or delete members of the forwarding table.
+
+ It accepts a list of tuples of up to 4 members: only the <domain name>
+ is required.
+
+ If ONLY the <domain name> is specified, the forwarding entry for
+ EXACTLY that domain name is deleted if it exists.
+
+ Only a specification of at least one <nameserver IP address> is required to
+ create a forwarding entry.
+
+ The IP address can be IPv4:
+ ( 32-bit integer OR array of 4 bytes OR dotted-quad string )
+ Or IPv6:
+ ( array of 16 bytes
+ OR RFC 2373/4 ascii string of 8 ':' separate hex quads as supported by inet_pton(3)
+ )
+
+ 32 and 16-bit integer parameters MUST be given in network byte order; ie the IPv4 address
+ 192.168.2.1 would be specified as uint32:16951488 on an i386 and port 53 would be uint16:13568.
+
+ There are an optional <port> 16-bit integer parameter, to specify the name server socket
+ address port associated with the preceding IP address, and a <forward policy>
+ parameter, which sets the forward policy as follows:
+ 0: "none" : never forward to this nameserver for this domain.
+ 1: "first": forward first to this server, and then search its authoritative data.
+ 2: "only" : always forward to this nameserver for this domain.
+
+ If not specified, <port> will have the value 53, and <forward policy> will be "2": "only".
+ named's default forward policy is "first" .
+
+ Creation of forwarding domains is not "exact", as is deletion, but is "inclusive":
+ creating forwarding entry for the '.' domain sets the default set of nameservers named
+ will query for ALL domains, and creating an entry for "redhat.com" creates a set of
+ nameservers to be queried for all names suffixed by "redhat.com." . If both are specified,
+ the "redhat.com" servers will be tried first, followed by the "." servers.
+
+ Forwarding entries are ONLY created in the first DNS View that matches the "localhost" client
+ (127.0.0.1) and destination. The default view, which exists if no views have been specified
+ in named.conf, matches ALL clients and destinations. If the user has configured views, none
+ of which match the localhost client, then no forwarding will be dynamically configurable.
+ Users are also free to configure a view that matches the localhost, for which forwarding
+ will be dynamically configurable, and other views which do not match the localhost, so that
+ other, remote clients can be served that will not be subject to dynamic forwarding. So it
+ is a fully supported configuration that users can serve authoritative data to external
+ clients and still use named's forwarding features for their localhost resolver.
+
+ SetForwarders returns uint32:0 on success or a DBUS_ERROR message on failure .
+
+
+ GetForwarders ( [ string:<domain name> ] )
+ ~~~~~~~~~~~~~
+ Using the default "com.redhat.named" interface, returns the EXACT forwarding entry for
+ <domain name> as binary D-BUS types; there is also a com.redhat.named.text interface
+ supported by GetForwarders which returns all values as string: text .
+
+ If a <domain name> is not specified, all forwarding table entries are dumped.
+
+
+ Examples:
+ ~~~~~~~~
+
+ Suppose we start out with the named.conf configuration:
+
+
+ options { ...
+ forwarders { 172.16.80.118; };
+ ...
+ };
+
+ zone "redhat.com" {
+ forward only;
+ forwarders { 172.16.76.10; 172.16.52.28; };
+ };
+
+ Using a "dbus-send" trivially modified to support uint16 parameters (!) :
+
+ $ dbus-send --system --type=method_call --print-reply --reply-timeout=20000 \
+ --dest=com.redhat.named /com/redhat/named com.redhat.named.GetForwarders
+ method return sender=:1.367 -> dest=:1.368
+ 0 string "redhat.com"
+ 1 byte 2
+ 2 uint32 172757164
+ 3 uint16 13568
+ 4 uint32 473174188
+ 5 uint16 13568
+ 6 string "."
+ 7 byte 1
+ 8 uint32 1984958636
+ 9 uint16 13568
+
+ ie. GetForwarders always returns a list of tuples of
+ ( <domain name>, <forward policy>, <ip address>, <port> )
+
+ If the "text" interface was specified:
+
+ $ dbus-send --system --type=method_call --print-reply --reply-timeout=20000 \
+ --dest=com.redhat.named /com/redhat/named com.redhat.named.text.GetForwarders
+ method return sender=:1.367 -> dest=:1.370
+ 0 string "redhat.com"
+ 1 string "only"
+ 2 string "172.16.76.10"
+ 3 string "53"
+ 4 string "172.16.52.28"
+ 5 string "53"
+ 6 string "."
+ 7 string "first"
+ 8 string "172.16.80.118"
+ 9 string "53"
+
+ So we could set the default nameserver for the root zone as follows:
+
+ $ dbus-send --system --type=method_call --print-reply --reply-timeout=20000 \
+ --dest=com.redhat.named /com/redhat/named com.redhat.named.SetForwarders \
+ string:'.' string:'192.33.14.30' string:'2001:503:231d::2:30'
+ method return sender=:1.367 -> dest=:1.371
+ 0 uint32 0
+ $ dbus-send --system --type=method_call --print-reply --reply-timeout=20000 \
+ --dest=com.redhat.named /com/redhat/named com.redhat.named.text.GetForwarders
+ method return sender=:1.367 -> dest=:1.372
+ 0 string "redhat.com"
+ 1 string "only"
+ 2 string "172.16.76.10"
+ 3 string "53"
+ 4 string "172.16.52.28"
+ 5 string "53"
+ 6 string "."
+ 7 string "only"
+ 8 string "192.33.14.30"
+ 9 string "53"
+ 10 string "2001:503:231d::2:30"
+ 11 string "53"
+
+ Using tcpdump one can verify that named will attempt to contact 192.33.14.30, then
+ 2001:503:231d::2:30, for all zones not in redhat.com; for redhat.com zones, 172.16.76.10
+ and 192.33.14.30 will be tried in that order.
+
+ If the D-BUS driver dbus-daemon should shut down, named will emit the syslog message:
+ "D-BUS service disabled."
+ And will retry connecting to D-BUS every 10 seconds - once it has connected, the message:
+ "D-BUS service enabled."
+ will be logged.
+
+ NOTE: there are the "SetForwarders" and "GetForwarders" scripts in the contrib/dbus directory
+ of the BIND source code distribution which are wrappers around the dbus-send commands above.
+ Usage: SetForwarders [ -t first | only ] <zone> [ <server> [...<server>] ]
+ GetForwarders [ <zone> ]
+
+
+ DHCP Integration
+ ~~~~~~~~~~~~~~~~
+
+ With the -D option, named will try to subscribe to dhcdbd, the DHCP Client D-BUS Daemon, to
+ be notified of DHCP "reason", "domain-name", "domain-name-server", "ip-address", and "subnet-mask"
+ DHCP options when the dhclient program has received them from a DHCP server .
+
+ If it cannot subscribe to dhcdbd, named will emit the message :
+ "D-BUS dhcdbd subscription disabled."
+ and will monitor D-BUS "NameOwnerChanged" messages for the appearance of a new owner
+ for "com.redhat.dhcp". When the name is owned, named will send a "com.redhat.dhcp.subscribe.binary"
+ message to dhcdbd to subscribe to the above options for all interfaces (provided by dhcdbd-1.5+),
+ and emit the log message:
+ "D-BUS dhcdbd subscription enabled."
+
+ named will match on signals from the com.redhat.dhcp.subscribe.binary interface for those option
+ settings, and , when the last option is received (indicated by a "reason" of 15: END_OPTIONS), it
+ will configure the forwarding table .
+
+ For each whitespace separated member of "domain-name-servers", AND for the reverse IPv4 in-addr.arpa
+ class C or less domain of the ip-address masked by the subnet-mask, it will create a forwarding entry
+ to query each "domain-server" .
+
+ To support CIDR-based reverse subnet forwarding, Views would have to be configured dynamically, a
+ possible future direction which is not yet implemented. (It would perhaps be easier to add a
+ "match-queries" ACL to the forwarders table).
+
+ When dhclient acquires a lease, named will configure forwarding, and emit the message:
+ "D-BUS: dhclient for interface eth0 acquired new lease - creating forwarders."
+
+ When a lease expires or the interface is brought down (dhclient is stopped with dhcdbd), it
+ will revert any forwarding entries from the initial, static configuration that were modified
+ by the DHCP subscription to their initial values; ie. if redhat.com had a forwarder configured
+ in named.conf, and then an DHCP session specified forwarders for redhat.com, when the DHCP
+ session ends the forwarders for redhat.com are reverted to their named.conf values; thus
+ when all DHCP interfaces have released their leases, and if no SetForwarders commands were issued,
+ the forwarding configuration will be identical to that at named startup.
+
+
+ To Do:
+ - Sending signals when any Forwarding entry is changed (easy to implement if it would be desirable).
+ - CIDR based reverse Forwarding
+
diff --git a/contrib/dbus/SetForwarders b/contrib/dbus/SetForwarders
new file mode 100755
index 0000000..8ee4ce1
--- /dev/null
+++ b/contrib/dbus/SetForwarders
@@ -0,0 +1,52 @@
+#!/bin/bash
+#
+# This script uses the named D-BUS support, which must be enabled in
+# the running named with the named '-D' option, to set the forwarding zones
+# in the running server.
+#
+# One zone argument is required, followed by any number of server IP (v4 or v6)
+# addresses. If the server IP address list is empty, any forwarders for the zone
+# will be removed.
+#
+# Usage:
+# SetForwarders [ -t <'first' | 'only'> ] <zone> [ <server IP> [...<server IP>] ]
+#
+# Copyright(C) Jason Vas Dias<jvdias@redhat.com> Red Hat Inc. 2005
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation at
+# http://www.fsf.org/licensing/licenses/gpl.txt
+# and included in this software distribution as the "LICENSE" file.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+usage() { echo "Usage: SetForwarders [ -t <'first' | 'only'> ] <zone> [ <server> [...<server>] ]"; }
+type=''
+if [ $# -eq 0 ]; then
+ usage;
+ exit 1;
+elif [ "$1" = "-t" ]; then
+ if [ $# -lt 2 ]; then
+ echo '-t option requires an argument.'
+ exit 1;
+ fi;
+ type=$2;
+ shift 2;
+fi;
+if [ $# -lt 1 ]; then
+ echo '<zone> first argument required.'
+ exit 1;
+fi;
+zone='string:'"$1";
+shift;
+servers='';
+if [ $# -gt 0 ]; then
+ for svr in $*; do
+ servers="$servers string:$svr";
+ done
+fi;
+dbus-send --system --type=method_call --print-reply --reply-timeout=20000 --dest=com.redhat.named /com/redhat/named com.redhat.named.text.SetForwarders $zone $type $servers;
diff --git a/contrib/dbus/bind-9.3.2b1-dbus.patch b/contrib/dbus/bind-9.3.2b1-dbus.patch
new file mode 100644
index 0000000..cdf50d6
--- /dev/null
+++ b/contrib/dbus/bind-9.3.2b1-dbus.patch
@@ -0,0 +1,713 @@
+--- bind-9.3.2b1/lib/dns/rbt.c.dbus 2005-06-17 21:03:24.000000000 -0400
++++ bind-9.3.2b1/lib/dns/rbt.c 2005-10-07 12:43:26.000000000 -0400
+@@ -2172,6 +2172,47 @@
+ dns_rbt_printtree(rbt->root, NULL, 0);
+ }
+
++static void
++dns_rbt_traverse_tree(dns_rbtnode_t *root, dns_rbt_traverse_callback_t cb, void *cb_arg1, void *cb_arg2 ) {
++/*
++ * This is used ONLY to traverse the forward table by dbus_mgr at the moment.
++ * Since the forward table is not likely to be large, this can be recursive.
++ */
++ dns_name_t name;
++ dns_offsets_t offsets;
++ char buf[DNS_NAME_MAXWIRE];
++ isc_buffer_t buffer;
++
++ if (root != NULL) {
++
++ if (DOWN(root))
++ dns_rbt_traverse_tree(DOWN(root), cb, cb_arg1, cb_arg2);
++
++ if( LEFT(root) != NULL )
++ dns_rbt_traverse_tree(LEFT(root), cb, cb_arg1, cb_arg2);
++
++ if( RIGHT(root) != NULL )
++ dns_rbt_traverse_tree(RIGHT(root), cb, cb_arg1, cb_arg2);
++
++ if( DATA(root) == 0L )
++ return;
++
++ dns_name_init(&name, offsets);
++ isc_buffer_init(&buffer, buf, DNS_NAME_MAXWIRE);
++ dns_name_setbuffer( &name, &buffer);
++ dns_rbt_fullnamefromnode(root, &name);
++
++ (*cb)(&name, DATA(root), cb_arg1, cb_arg2);
++ }
++}
++
++void dns_rbt_traverse( dns_rbt_t *rbt, dns_rbt_traverse_callback_t cb, void *cb_arg1, void *cb_arg2 )
++{
++ REQUIRE(VALID_RBT(rbt));
++
++ dns_rbt_traverse_tree( rbt->root, cb, cb_arg1, cb_arg2 );
++}
++
+ /*
+ * Chain Functions
+ */
+--- bind-9.3.2b1/lib/dns/forward.c.dbus 2005-03-16 22:58:30.000000000 -0500
++++ bind-9.3.2b1/lib/dns/forward.c 2005-10-07 12:43:26.000000000 -0400
+@@ -200,3 +200,89 @@
+ }
+ isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
+ }
++
++/***
++ *** new D-BUS Dynamic Forwarding Zones functions:
++ ***/
++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);
++
++ return (result);
++}
++
++isc_result_t
++dns_fwdtable_find_closest(dns_fwdtable_t *fwdtable,
++ dns_name_t *name,
++ dns_name_t *foundname,
++ dns_forwarders_t **forwardersp)
++{
++ isc_result_t result;
++
++ REQUIRE(VALID_FWDTABLE(fwdtable));
++
++ RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
++
++ result = dns_rbt_findname(fwdtable->table, name, 0, foundname,
++ (void **)forwardersp);
++
++ if(result == DNS_R_PARTIALMATCH)
++ result = ISC_R_SUCCESS;
++
++ RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
++
++ return (result);
++}
++
++isc_result_t
++dns_fwdtable_find_exact(dns_fwdtable_t *fwdtable, dns_name_t *name,
++ dns_forwarders_t **forwardersp)
++{
++ isc_result_t result;
++
++ REQUIRE(VALID_FWDTABLE(fwdtable));
++
++ REQUIRE(forwardersp != 0L);
++
++ RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
++
++ result = dns_rbt_findname(fwdtable->table, name, 0, NULL,
++ (void **)forwardersp);
++
++ if( result != ISC_R_SUCCESS )
++ *forwardersp = 0L;
++
++ RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
++
++ return (result);
++}
++
++static
++void dns_fwdtable_traverse
++(
++ dns_name_t *name,
++ void *node_data,
++ void *cbp,
++ void *cb_arg
++)
++{
++ dns_fwdtable_callback_t cb = (dns_fwdtable_callback_t) cbp;
++
++ (*cb)( name, node_data, cb_arg);
++}
++
++void dns_fwdtable_foreach(dns_fwdtable_t *fwdtable, dns_fwdtable_callback_t cb, void *cb_arg )
++{
++ REQUIRE(VALID_FWDTABLE(fwdtable));
++
++ dns_rbt_traverse( fwdtable->table, dns_fwdtable_traverse, cb, cb_arg );
++}
+--- bind-9.3.2b1/lib/dns/include/dns/forward.h.dbus 2005-03-16 22:58:31.000000000 -0500
++++ bind-9.3.2b1/lib/dns/include/dns/forward.h 2005-10-07 12:43:26.000000000 -0400
+@@ -98,6 +98,37 @@
+ * all memory associated with the forwarding table is freed.
+ */
+
++
++/* These are ONLY used by dbus_mgr :
++ */
++
++isc_result_t
++dns_fwdtable_delete( dns_fwdtable_t *fwdtable, dns_name_t *name );
++/*
++ * Removes an entry from the forwarding table.
++ */
++
++isc_result_t
++dns_fwdtable_find_exact(dns_fwdtable_t *fwdtable, dns_name_t *name,
++ dns_forwarders_t **forwardersp);
++/*
++ * Finds an exact match for "name" in the forwarding table.
++ */
++
++isc_result_t
++dns_fwdtable_find_closest(dns_fwdtable_t *fwdtable, dns_name_t *name, dns_name_t *foundname,
++ dns_forwarders_t **forwardersp);
++/*
++ * Finds the closest match for "*name" in the forwarding table, returning
++ * the actual name matching in *name if different to *name passed in.
++ */
++
++typedef void (*dns_fwdtable_callback_t)( dns_name_t *, dns_forwarders_t *, void *);
++void dns_fwdtable_foreach(dns_fwdtable_t *fwdtable, dns_fwdtable_callback_t cb, void * );
++/* Invoke cb for each member of fwdtable
++ */
++
++
+ ISC_LANG_ENDDECLS
+
+ #endif /* DNS_FORWARD_H */
+--- bind-9.3.2b1/lib/dns/include/dns/rbt.h.dbus 2004-10-11 01:55:51.000000000 -0400
++++ bind-9.3.2b1/lib/dns/include/dns/rbt.h 2005-10-07 12:43:26.000000000 -0400
+@@ -833,6 +833,17 @@
+ * <something_else> Any error result from dns_name_concatenate.
+ */
+
++
++typedef void (*dns_rbt_traverse_callback_t)( dns_name_t *name,
++ void *node_data,
++ void *cb_arg1,
++ void *cb_arg2);
++
++void dns_rbt_traverse( dns_rbt_t *rbt, dns_rbt_traverse_callback_t cb, void *cb_arg1, void *cb_arg2 );
++/* tree traversal function (only used by D-BUS dynamic forwarding dbus_mgr at
++ * the moment)
++ */
++
+ ISC_LANG_ENDDECLS
+
+ #endif /* DNS_RBT_H */
+--- bind-9.3.2b1/lib/isc/unix/socket.c.dbus 2005-08-25 00:32:55.000000000 -0400
++++ bind-9.3.2b1/lib/isc/unix/socket.c 2005-10-07 13:40:03.000000000 -0400
+@@ -148,6 +148,11 @@
+ ISC_LIST(isc_socketevent_t) recv_list;
+ ISC_LIST(isc_socket_newconnev_t) accept_list;
+ isc_socket_connev_t *connect_ev;
++
++ /* these are used only by isc_sockettype_fd sockets:*/
++ isc_socketevent_t *read_ready_event;
++ isc_socketevent_t *write_ready_event;
++ isc_socketevent_t *selected_event;
+
+ /*
+ * Internal events. Posted when a descriptor is readable or
+@@ -304,7 +309,7 @@
+
+ static void
+ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
+- isc_socket_t *sock;
++ isc_socket_t *sock=0L;
+
+ /*
+ * This is a wakeup on a socket. If the socket is not in the
+@@ -1266,6 +1271,9 @@
+ sock->connected = 0;
+ sock->connecting = 0;
+ sock->bound = 0;
++ sock->read_ready_event = 0L;
++ sock->write_ready_event = 0L;
++ sock->selected_event = 0L;
+
+ /*
+ * initialize the lock
+@@ -1378,13 +1386,16 @@
+ case isc_sockettype_tcp:
+ sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
+ break;
++
++ case isc_sockettype_fd:
++ sock->fd = pf;
+ }
+
+ #ifdef F_DUPFD
+ /*
+ * Leave a space for stdio to work in.
+ */
+- if (sock->fd >= 0 && sock->fd < 20) {
++ if ( (type != isc_sockettype_fd) && (sock->fd >= 0) && (sock->fd < 20) ) {
+ int new, tmp;
+ new = fcntl(sock->fd, F_DUPFD, 20);
+ tmp = errno;
+@@ -1438,7 +1449,7 @@
+ }
+ }
+
+- if (make_nonblock(sock->fd) != ISC_R_SUCCESS) {
++ if ((type != isc_sockettype_fd) && (make_nonblock(sock->fd) != ISC_R_SUCCESS)) {
+ (void)close(sock->fd);
+ free_socket(&sock);
+ return (ISC_R_UNEXPECTED);
+@@ -1706,6 +1717,38 @@
+ isc_task_send(ev->ev_sender, (isc_event_t **)&iev);
+ }
+
++static
++isc_event_t *dispatch_read_ready(isc_socketmgr_t *manager, isc_socket_t *sock)
++{
++ isc_event_t *dev = (isc_event_t*)sock->read_ready_event, *ev;
++
++ ev = isc_mem_get(manager->mctx, dev->ev_size);
++ memcpy(ev,dev,dev->ev_size);
++ ISC_LINK_INIT(ev,ev_link);
++ isc_task_send(dev->ev_sender, &ev );
++ return (isc_event_t *)sock->selected_event;
++}
++
++static
++isc_event_t *dispatch_write_ready(isc_socketmgr_t *manager,isc_socket_t *sock)
++{
++ isc_event_t *dev = (isc_event_t*)sock->write_ready_event, *ev;
++ ev = isc_mem_get(manager->mctx, dev->ev_size);
++ memcpy(ev,dev,dev->ev_size);
++ ISC_LINK_INIT(ev,ev_link);
++ isc_task_send(dev->ev_sender, &ev );
++ return (isc_event_t *)sock->selected_event;
++}
++
++static
++void dispatch_selected(isc_socketmgr_t *manager, isc_event_t *dev)
++{ isc_event_t *ev;
++ ev = isc_mem_get(manager->mctx, dev->ev_size);
++ memcpy(ev,dev,dev->ev_size);
++ ISC_LINK_INIT(ev,ev_link);
++ isc_task_send(dev->ev_sender, &ev );
++}
++
+ /*
+ * Dequeue an item off the given socket's read queue, set the result code
+ * in the done event to the one provided, and send it to the task it was
+@@ -2113,6 +2156,7 @@
+ int i;
+ isc_socket_t *sock;
+ isc_boolean_t unlock_sock;
++ isc_event_t *sock_selected = 0L;
+
+ REQUIRE(maxfd <= (int)FD_SETSIZE);
+
+@@ -2146,11 +2190,15 @@
+ unlock_sock = ISC_TRUE;
+ LOCK(&sock->lock);
+ if (!SOCK_DEAD(sock)) {
++ if( sock->type != isc_sockettype_fd )
++ {
+ if (sock->listener)
+ dispatch_accept(sock);
+ else
+ dispatch_recv(sock);
+- }
++ }else
++ sock_selected = dispatch_read_ready(manager,sock);
++ }
+ FD_CLR(i, &manager->read_fds);
+ }
+ check_write:
+@@ -2164,16 +2212,24 @@
+ LOCK(&sock->lock);
+ }
+ if (!SOCK_DEAD(sock)) {
++ if( sock->type != isc_sockettype_fd )
++ {
+ if (sock->connecting)
+ dispatch_connect(sock);
+ else
+ dispatch_send(sock);
++ }else
++ sock_selected = dispatch_write_ready(manager,sock);
+ }
+ FD_CLR(i, &manager->write_fds);
+ }
+ if (unlock_sock)
+ UNLOCK(&sock->lock);
+ }
++ if( sock_selected != 0L )
++ {
++ dispatch_selected(manager, sock_selected);
++ }
+ }
+
+ #ifdef ISC_PLATFORM_USETHREADS
+@@ -2192,7 +2248,7 @@
+ int cc;
+ fd_set readfds;
+ fd_set writefds;
+- int msg, fd;
++ int msg, fd = -1;
+ int maxfd;
+ char strbuf[ISC_STRERRORSIZE];
+
+@@ -3523,3 +3579,55 @@
+ return (ISC_R_SUCCESS);
+ }
+ #endif /* ISC_PLATFORM_USETHREADS */
++
++isc_socketevent_t*
++isc_socket_fd_handle_reads( isc_socket_t *sock, isc_socketevent_t *dev )
++{
++ REQUIRE(VALID_SOCKET(sock));
++ if(dev != 0L)
++ {
++ sock->references=1;
++ sock->read_ready_event = dev;
++ select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
++ }else
++ {
++ dev = sock->read_ready_event ;
++ sock->read_ready_event = 0L ;
++ }
++ return dev;
++}
++
++isc_socketevent_t*
++isc_socket_fd_handle_writes( isc_socket_t *sock, isc_socketevent_t *dev )
++{
++ REQUIRE(VALID_SOCKET(sock));
++ if(dev != 0L)
++ {
++ sock->references=1;
++ sock->write_ready_event = dev;
++ select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
++ }else
++ {
++ dev = sock->write_ready_event;
++ sock->write_ready_event = 0L;
++ }
++ return dev;
++}
++
++isc_socketevent_t*
++isc_socket_fd_handle_selected( isc_socket_t *sock, isc_socketevent_t *dev )
++{
++ REQUIRE(VALID_SOCKET(sock));
++ if(dev != 0L)
++ {
++ sock->references=1;
++ sock->selected_event = dev;
++ }else
++ {
++ dev = sock->selected_event;
++ sock->selected_event = 0L;
++ sock->references=0;
++ destroy(&sock);
++ }
++ return dev;
++}
+--- bind-9.3.2b1/lib/isc/include/isc/socket.h.dbus 2004-03-08 04:04:53.000000000 -0500
++++ bind-9.3.2b1/lib/isc/include/isc/socket.h 2005-10-07 12:43:26.000000000 -0400
+@@ -136,6 +136,10 @@
+ #define ISC_SOCKEVENT_NEWCONN (ISC_EVENTCLASS_SOCKET + 3)
+ #define ISC_SOCKEVENT_CONNECT (ISC_EVENTCLASS_SOCKET + 4)
+
++#define ISC_SOCKEVENT_READ_READY (ISC_EVENTCLASS_SOCKET + 5)
++#define ISC_SOCKEVENT_WRITE_READY (ISC_EVENTCLASS_SOCKET + 6)
++#define ISC_SOCKEVENT_SELECTED (ISC_EVENTCLASS_SOCKET + 7)
++
+ /*
+ * Internal events.
+ */
+@@ -144,7 +148,8 @@
+
+ typedef enum {
+ isc_sockettype_udp = 1,
+- isc_sockettype_tcp = 2
++ isc_sockettype_tcp = 2,
++ isc_sockettype_fd = 8
+ } isc_sockettype_t;
+
+ /*
+@@ -699,6 +704,30 @@
+ * 'sock' is a valid socket.
+ */
+
++isc_socketevent_t*
++isc_socket_fd_handle_reads( isc_socket_t *sock, isc_socketevent_t *dev );
++/* register the "dev" event to be sent when the isc_sockettype_fd sock
++ * was select()-ed for read. If there is already an event registered, it
++ * is returned, otherwise 0 is returned. If dev is 0, removes any existing
++ * registered event.
++ */
++
++isc_socketevent_t*
++isc_socket_fd_handle_writes( isc_socket_t *sock, isc_socketevent_t *dev );
++/* register the "dev" event to be sent when the isc_sockettype_fd sock
++ * was select()-ed for write. If there is already an event registered, it
++ * is returned, otherwise 0 is returned. If dev is 0, removes any existing
++ * registered event.
++ */
++
++isc_socketevent_t*
++isc_socket_fd_handle_selected( isc_socket_t *sock, isc_socketevent_t *dev );
++/* register the "dev" event to be sent when ALL isc_sockettype_fd sockets
++ * have been select()-ed . If there is already an event registered, it
++ * is returned, otherwise 0 is returned. If dev is 0, removes any existing
++ * registered event.
++ */
++
+ ISC_LANG_ENDDECLS
+
+ #endif /* ISC_SOCKET_H */
+--- bind-9.3.2b1/bin/named/log.c.dbus 2005-05-24 19:58:17.000000000 -0400
++++ bind-9.3.2b1/bin/named/log.c 2005-10-07 12:43:26.000000000 -0400
+@@ -41,6 +41,7 @@
+ { "queries", 0 },
+ { "unmatched", 0 },
+ { "update-security", 0 },
++ { "dbus", 0 },
+ { NULL, 0 }
+ };
+
+@@ -60,6 +61,7 @@
+ { "notify", 0 },
+ { "control", 0 },
+ { "lwresd", 0 },
++ { "dbus", 0 },
+ { NULL, 0 }
+ };
+
+--- bind-9.3.2b1/bin/named/Makefile.in.dbus 2004-09-06 17:47:25.000000000 -0400
++++ bind-9.3.2b1/bin/named/Makefile.in 2005-10-07 13:44:22.000000000 -0400
+@@ -35,7 +35,9 @@
+ ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \
+ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \
+ ${DBDRIVER_INCLUDES}
+-
++DBUS_ARCHDEP_LIBDIR ?= lib
++DBUS_INCLUDES = \
++ -I/usr/${DBUS_ARCHDEP_LIBDIR}/dbus-1.0/include -I/usr/include/dbus-1.0
+ CDEFINES =
+ CWARNINGS =
+
+@@ -52,6 +54,7 @@
+ ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
++DBUSLIBS= -ldbus-1
+
+ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \
+ ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${ISCDEPLIBS}
+@@ -71,6 +74,7 @@
+ zoneconf.@O@ \
+ lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \
+ lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ \
++ dbus_service.@O@ dbus_mgr.@O@ \
+ $(DBDRIVER_OBJS)
+
+ UOBJS = unix/os.@O@
+@@ -83,6 +87,7 @@
+ zoneconf.c \
+ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \
+ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \
++ dbus_service.c dbus_mgr.c \
+ $(DBDRIVER_SRCS)
+
+ MANPAGES = named.8 lwresd.8 named.conf.5
+@@ -105,9 +110,14 @@
+ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \
+ -c ${srcdir}/config.c
+
++dbus_service.@O@: dbus_service.c
++ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
++ ${DBUS_INCLUDES} \
++ -c ${srcdir}/dbus_service.c
++
+ named@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+- ${OBJS} ${UOBJS} ${LIBS}
++ ${OBJS} ${UOBJS} ${LIBS} ${DBUSLIBS}
+
+ lwresd@EXEEXT@: named@EXEEXT@
+ rm -f lwresd@EXEEXT@
+--- bind-9.3.2b1/bin/named/named.8.dbus 2005-05-12 22:43:20.000000000 -0400
++++ bind-9.3.2b1/bin/named/named.8 2005-10-07 13:50:12.000000000 -0400
+@@ -41,7 +41,7 @@
+ named \- Internet domain name server
+ .SH "SYNOPSIS"
+ .HP 6
+-\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fIconfig\-file\fR\fR] [\fB\-d\ \fIdebug\-level\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-n\ \fI#cpus\fR\fR] [\fB\-p\ \fIport\fR\fR] [\fB\-s\fR] [\fB\-t\ \fIdirectory\fR\fR] [\fB\-u\ \fIuser\fR\fR] [\fB\-v\fR] [\fB\-x\ \fIcache\-file\fR\fR]
++\fBnamed\fR [\fB\-4\fR] [\fB\-6\fR] [\fB\-c\ \fIconfig\-file\fR\fR] [\fB\-d\ \fIdebug\-level\fR\fR] [\fB\-f\fR] [\fB\-g\fR] [\fB\-n\ \fI#cpus\fR\fR] [\fB\-p\ \fIport\fR\fR] [\fB\-s\fR] [\fB\-t\ \fIdirectory\fR\fR] [\fB\-u\ \fIuser\fR\fR] [\fB\-v\fR] [\fB\-x\ \fIcache\-file\fR\fR] [\fB\-D\fR]
+ .SH "DESCRIPTION"
+ .PP
+ \fBnamed\fR is a Domain Name System (DNS) server, part of the BIND 9 distribution from ISC\&. For more information on the DNS, see RFCs 1033, 1034, and 1035\&.
+@@ -103,6 +103,13 @@
+ .B "Warning:"
+ This option must not be used\&. It is only of interest to BIND 9 developers and may be removed or changed in a future release\&.
+ .RE
++.sp
++.TP
++\fB\-D\fR
++Enable dynamic management of the forwarding table with D-BUS
++messages. This option is required for Red Hat NetworkManager
++support. See doc/README.DBUS .
++.sp
+ .SH "SIGNALS"
+ .PP
+ In routine operation, signals should not be used to control the nameserver; \fBrndc\fR should be used instead\&.
+@@ -117,6 +124,7 @@
+ .SH "CONFIGURATION"
+ .PP
+ The \fBnamed\fR configuration file is too complex to describe in detail here\&. A complete description is provided in the BIND 9 Administrator Reference Manual\&.
++.PP
+ .SH "FILES"
+ .TP
+ \fI/etc/named\&.conf\fR
+--- bind-9.3.2b1/bin/named/main.c.dbus 2005-04-28 21:04:47.000000000 -0400
++++ bind-9.3.2b1/bin/named/main.c 2005-10-07 12:43:26.000000000 -0400
+@@ -239,7 +239,8 @@
+ "usage: named [-4|-6] [-c conffile] [-d debuglevel] "
+ "[-f|-g] [-n number_of_cpus]\n"
+ " [-p port] [-s] [-t chrootdir] [-u username]\n"
+- " [-m {usage|trace|record}]\n");
++ " [-m {usage|trace|record}]\n"
++ " [-D ]\n");
+ }
+
+ static void
+@@ -345,7 +346,7 @@
+
+ isc_commandline_errprint = ISC_FALSE;
+ while ((ch = isc_commandline_parse(argc, argv,
+- "46c:C:d:fgi:lm:n:N:p:P:st:u:vx:")) != -1) {
++ "46c:C:d:fgi:lm:n:N:p:P:st:u:vx:D")) != -1) {
+ switch (ch) {
+ case '4':
+ if (disable4)
+@@ -434,6 +435,9 @@
+ case 'v':
+ printf("BIND %s\n", ns_g_version);
+ exit(0);
++ case 'D':
++ ns_g_dbus = 1;
++ break;
+ case '?':
+ usage();
+ ns_main_earlyfatal("unknown option '-%c'",
+--- bind-9.3.2b1/bin/named/server.c.dbus 2005-07-26 22:53:15.000000000 -0400
++++ bind-9.3.2b1/bin/named/server.c 2005-10-07 12:43:26.000000000 -0400
+@@ -86,6 +86,8 @@
+ #include <stdlib.h>
+ #endif
+
++#include <named/dbus_mgr.h>
++
+ /*
+ * Check an operation for failure. Assumes that the function
+ * using it has a 'result' variable and a 'cleanup' label.
+@@ -1496,12 +1498,12 @@
+ if (result != ISC_R_SUCCESS) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(origin, namebuf, sizeof(namebuf));
+- cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
+- "could not set up forwarding for domain '%s': %s",
++ cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_NOTICE,
++ "setting up forwarding failed for domain '%s': %s",
+ namebuf, isc_result_totext(result));
+ goto cleanup;
+ }
+-
++
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+@@ -2873,6 +2875,20 @@
+
+ CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones");
+
++ server->dbus_mgr = 0L;
++ if( ns_g_dbus )
++ if( dbus_mgr_create
++ ( ns_g_mctx, ns_g_taskmgr, ns_g_socketmgr, ns_g_timermgr,
++ &server->dbus_mgr
++ ) != ISC_R_SUCCESS
++ )
++ {
++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
++ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
++ "dbus_mgr initialization failed. D-BUS service is disabled."
++ );
++ }
++
+ ns_os_started();
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_NOTICE, "running");
+@@ -2935,6 +2951,9 @@
+
+ dns_db_detach(&server->in_roothints);
+
++ if( server->dbus_mgr != 0L )
++ dbus_mgr_shutdown(server->dbus_mgr);
++
+ isc_task_endexclusive(server->task);
+
+ isc_task_detach(&server->task);
+--- bind-9.3.2b1/bin/named/include/named/globals.h.dbus 2004-03-07 23:04:20.000000000 -0500
++++ bind-9.3.2b1/bin/named/include/named/globals.h 2005-10-07 13:47:36.000000000 -0400
+@@ -112,6 +112,8 @@
+
+ EXTERN int ns_g_listen INIT(3);
+
++EXTERN int ns_g_dbus INIT(0);
++
+ #undef EXTERN
+ #undef INIT
+
+--- bind-9.3.2b1/bin/named/include/named/server.h.dbus 2004-03-07 23:04:21.000000000 -0500
++++ bind-9.3.2b1/bin/named/include/named/server.h 2005-10-07 12:43:26.000000000 -0400
+@@ -91,7 +91,8 @@
+ ns_controls_t * controls; /* Control channels */
+ unsigned int dispatchgen;
+ ns_dispatchlist_t dispatches;
+-
++
++ ns_dbus_mgr_t * dbus_mgr;
+ };
+
+ #define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R')
+--- bind-9.3.2b1/bin/named/include/named/log.h.dbus 2004-03-07 23:04:21.000000000 -0500
++++ bind-9.3.2b1/bin/named/include/named/log.h 2005-10-07 12:43:26.000000000 -0400
+@@ -34,6 +34,7 @@
+ #define NS_LOGCATEGORY_QUERIES (&ns_g_categories[4])
+ #define NS_LOGCATEGORY_UNMATCHED (&ns_g_categories[5])
+ #define NS_LOGCATEGORY_UPDATE_SECURITY (&ns_g_categories[6])
++#define NS_LOGCATEGORY_DBUS (&ns_g_categories[7])
+
+ /*
+ * Backwards compatibility.
+@@ -51,6 +52,7 @@
+ #define NS_LOGMODULE_NOTIFY (&ns_g_modules[8])
+ #define NS_LOGMODULE_CONTROL (&ns_g_modules[9])
+ #define NS_LOGMODULE_LWRESD (&ns_g_modules[10])
++#define NS_LOGMODULE_DBUS (&ns_g_modules[11])
+
+ isc_result_t
+ ns_log_init(isc_boolean_t safe);
+--- bind-9.3.2b1/bin/named/include/named/types.h.dbus 2004-03-06 05:21:26.000000000 -0500
++++ bind-9.3.2b1/bin/named/include/named/types.h 2005-10-07 12:43:26.000000000 -0400
+@@ -38,4 +38,6 @@
+ typedef struct ns_dispatch ns_dispatch_t;
+ typedef ISC_LIST(ns_dispatch_t) ns_dispatchlist_t;
+
++typedef struct ns_dbus_mgr ns_dbus_mgr_t ;
++
+ #endif /* NAMED_TYPES_H */
diff --git a/contrib/dbus/bind-9.3.3rc2-dbus.patch b/contrib/dbus/bind-9.3.3rc2-dbus.patch
new file mode 100644
index 0000000..9048db7
--- /dev/null
+++ b/contrib/dbus/bind-9.3.3rc2-dbus.patch
@@ -0,0 +1,778 @@
+--- bind-9.3.3rc2/lib/dns/forward.c.dbus 2005-03-17 04:58:30.000000000 +0100
++++ bind-9.3.3rc2/lib/dns/forward.c 2006-09-18 10:08:37.000000000 +0200
+@@ -200,3 +200,89 @@
+ }
+ isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
+ }
++
++/***
++ *** new D-BUS Dynamic Forwarding Zones functions:
++ ***/
++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);
++
++ return (result);
++}
++
++isc_result_t
++dns_fwdtable_find_closest(dns_fwdtable_t *fwdtable,
++ dns_name_t *name,
++ dns_name_t *foundname,
++ dns_forwarders_t **forwardersp)
++{
++ isc_result_t result;
++
++ REQUIRE(VALID_FWDTABLE(fwdtable));
++
++ RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
++
++ result = dns_rbt_findname(fwdtable->table, name, 0, foundname,
++ (void **)forwardersp);
++
++ if(result == DNS_R_PARTIALMATCH)
++ result = ISC_R_SUCCESS;
++
++ RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
++
++ return (result);
++}
++
++isc_result_t
++dns_fwdtable_find_exact(dns_fwdtable_t *fwdtable, dns_name_t *name,
++ dns_forwarders_t **forwardersp)
++{
++ isc_result_t result;
++
++ REQUIRE(VALID_FWDTABLE(fwdtable));
++
++ REQUIRE(forwardersp != 0L);
++
++ RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
++
++ result = dns_rbt_findname(fwdtable->table, name, 0, NULL,
++ (void **)forwardersp);
++
++ if( result != ISC_R_SUCCESS )
++ *forwardersp = 0L;
++
++ RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
++
++ return (result);
++}
++
++static
++void dns_fwdtable_traverse
++(
++ dns_name_t *name,
++ void *node_data,
++ void *cbp,
++ void *cb_arg
++)
++{
++ dns_fwdtable_callback_t cb = (dns_fwdtable_callback_t) cbp;
++
++ (*cb)( name, node_data, cb_arg);
++}
++
++void dns_fwdtable_foreach(dns_fwdtable_t *fwdtable, dns_fwdtable_callback_t cb, void *cb_arg )
++{
++ REQUIRE(VALID_FWDTABLE(fwdtable));
++
++ dns_rbt_traverse( fwdtable->table, dns_fwdtable_traverse, cb, cb_arg );
++}
+--- bind-9.3.3rc2/lib/dns/include/dns/forward.h.dbus 2005-03-17 04:58:31.000000000 +0100
++++ bind-9.3.3rc2/lib/dns/include/dns/forward.h 2006-09-18 10:08:37.000000000 +0200
+@@ -98,6 +98,37 @@
+ * all memory associated with the forwarding table is freed.
+ */
+
++
++/* These are ONLY used by dbus_mgr :
++ */
++
++isc_result_t
++dns_fwdtable_delete( dns_fwdtable_t *fwdtable, dns_name_t *name );
++/*
++ * Removes an entry from the forwarding table.
++ */
++
++isc_result_t
++dns_fwdtable_find_exact(dns_fwdtable_t *fwdtable, dns_name_t *name,
++ dns_forwarders_t **forwardersp);
++/*
++ * Finds an exact match for "name" in the forwarding table.
++ */
++
++isc_result_t
++dns_fwdtable_find_closest(dns_fwdtable_t *fwdtable, dns_name_t *name, dns_name_t *foundname,
++ dns_forwarders_t **forwardersp);
++/*
++ * Finds the closest match for "*name" in the forwarding table, returning
++ * the actual name matching in *name if different to *name passed in.
++ */
++
++typedef void (*dns_fwdtable_callback_t)( dns_name_t *, dns_forwarders_t *, void *);
++void dns_fwdtable_foreach(dns_fwdtable_t *fwdtable, dns_fwdtable_callback_t cb, void * );
++/* Invoke cb for each member of fwdtable
++ */
++
++
+ ISC_LANG_ENDDECLS
+
+ #endif /* DNS_FORWARD_H */
+--- bind-9.3.3rc2/lib/dns/include/dns/rbt.h.dbus 2004-10-11 07:55:51.000000000 +0200
++++ bind-9.3.3rc2/lib/dns/include/dns/rbt.h 2006-09-18 10:08:37.000000000 +0200
+@@ -833,6 +833,17 @@
+ * <something_else> Any error result from dns_name_concatenate.
+ */
+
++
++typedef void (*dns_rbt_traverse_callback_t)( dns_name_t *name,
++ void *node_data,
++ void *cb_arg1,
++ void *cb_arg2);
++
++void dns_rbt_traverse( dns_rbt_t *rbt, dns_rbt_traverse_callback_t cb, void *cb_arg1, void *cb_arg2 );
++/* tree traversal function (only used by D-BUS dynamic forwarding dbus_mgr at
++ * the moment)
++ */
++
+ ISC_LANG_ENDDECLS
+
+ #endif /* DNS_RBT_H */
+--- bind-9.3.3rc2/lib/dns/rbt.c.dbus 2005-06-18 03:03:24.000000000 +0200
++++ bind-9.3.3rc2/lib/dns/rbt.c 2006-09-18 10:08:37.000000000 +0200
+@@ -2172,6 +2172,47 @@
+ dns_rbt_printtree(rbt->root, NULL, 0);
+ }
+
++static void
++dns_rbt_traverse_tree(dns_rbtnode_t *root, dns_rbt_traverse_callback_t cb, void *cb_arg1, void *cb_arg2 ) {
++/*
++ * This is used ONLY to traverse the forward table by dbus_mgr at the moment.
++ * Since the forward table is not likely to be large, this can be recursive.
++ */
++ dns_name_t name;
++ dns_offsets_t offsets;
++ char buf[DNS_NAME_MAXWIRE];
++ isc_buffer_t buffer;
++
++ if (root != NULL) {
++
++ if (DOWN(root))
++ dns_rbt_traverse_tree(DOWN(root), cb, cb_arg1, cb_arg2);
++
++ if( LEFT(root) != NULL )
++ dns_rbt_traverse_tree(LEFT(root), cb, cb_arg1, cb_arg2);
++
++ if( RIGHT(root) != NULL )
++ dns_rbt_traverse_tree(RIGHT(root), cb, cb_arg1, cb_arg2);
++
++ if( DATA(root) == 0L )
++ return;
++
++ dns_name_init(&name, offsets);
++ isc_buffer_init(&buffer, buf, DNS_NAME_MAXWIRE);
++ dns_name_setbuffer( &name, &buffer);
++ dns_rbt_fullnamefromnode(root, &name);
++
++ (*cb)(&name, DATA(root), cb_arg1, cb_arg2);
++ }
++}
++
++void dns_rbt_traverse( dns_rbt_t *rbt, dns_rbt_traverse_callback_t cb, void *cb_arg1, void *cb_arg2 )
++{
++ REQUIRE(VALID_RBT(rbt));
++
++ dns_rbt_traverse_tree( rbt->root, cb, cb_arg1, cb_arg2 );
++}
++
+ /*
+ * Chain Functions
+ */
+--- bind-9.3.3rc2/lib/isc/include/isc/socket.h.dbus 2004-03-08 10:04:53.000000000 +0100
++++ bind-9.3.3rc2/lib/isc/include/isc/socket.h 2006-09-18 10:08:37.000000000 +0200
+@@ -136,6 +136,10 @@
+ #define ISC_SOCKEVENT_NEWCONN (ISC_EVENTCLASS_SOCKET + 3)
+ #define ISC_SOCKEVENT_CONNECT (ISC_EVENTCLASS_SOCKET + 4)
+
++#define ISC_SOCKEVENT_READ_READY (ISC_EVENTCLASS_SOCKET + 5)
++#define ISC_SOCKEVENT_WRITE_READY (ISC_EVENTCLASS_SOCKET + 6)
++#define ISC_SOCKEVENT_SELECTED (ISC_EVENTCLASS_SOCKET + 7)
++
+ /*
+ * Internal events.
+ */
+@@ -144,7 +148,8 @@
+
+ typedef enum {
+ isc_sockettype_udp = 1,
+- isc_sockettype_tcp = 2
++ isc_sockettype_tcp = 2,
++ isc_sockettype_fd = 8
+ } isc_sockettype_t;
+
+ /*
+@@ -699,6 +704,30 @@
+ * 'sock' is a valid socket.
+ */
+
++isc_socketevent_t*
++isc_socket_fd_handle_reads( isc_socket_t *sock, isc_socketevent_t *dev );
++/* register the "dev" event to be sent when the isc_sockettype_fd sock
++ * was select()-ed for read. If there is already an event registered, it
++ * is returned, otherwise 0 is returned. If dev is 0, removes any existing
++ * registered event.
++ */
++
++isc_socketevent_t*
++isc_socket_fd_handle_writes( isc_socket_t *sock, isc_socketevent_t *dev );
++/* register the "dev" event to be sent when the isc_sockettype_fd sock
++ * was select()-ed for write. If there is already an event registered, it
++ * is returned, otherwise 0 is returned. If dev is 0, removes any existing
++ * registered event.
++ */
++
++isc_socketevent_t*
++isc_socket_fd_handle_selected( isc_socket_t *sock, isc_socketevent_t *dev );
++/* register the "dev" event to be sent when ALL isc_sockettype_fd sockets
++ * have been select()-ed . If there is already an event registered, it
++ * is returned, otherwise 0 is returned. If dev is 0, removes any existing
++ * registered event.
++ */
++
+ ISC_LANG_ENDDECLS
+
+ #endif /* ISC_SOCKET_H */
+--- bind-9.3.3rc2/lib/isc/unix/socket.c.dbus 2006-05-19 04:53:36.000000000 +0200
++++ bind-9.3.3rc2/lib/isc/unix/socket.c 2006-09-18 10:08:37.000000000 +0200
+@@ -148,6 +148,11 @@
+ ISC_LIST(isc_socketevent_t) recv_list;
+ ISC_LIST(isc_socket_newconnev_t) accept_list;
+ isc_socket_connev_t *connect_ev;
++
++ /* these are used only by isc_sockettype_fd sockets:*/
++ isc_socketevent_t *read_ready_event;
++ isc_socketevent_t *write_ready_event;
++ isc_socketevent_t *selected_event;
+
+ /*
+ * Internal events. Posted when a descriptor is readable or
+@@ -304,7 +309,7 @@
+
+ static void
+ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
+- isc_socket_t *sock;
++ isc_socket_t *sock=0L;
+
+ /*
+ * This is a wakeup on a socket. If the socket is not in the
+@@ -1289,6 +1294,9 @@
+ sock->connected = 0;
+ sock->connecting = 0;
+ sock->bound = 0;
++ sock->read_ready_event = 0L;
++ sock->write_ready_event = 0L;
++ sock->selected_event = 0L;
+
+ /*
+ * initialize the lock
+@@ -1401,13 +1409,16 @@
+ case isc_sockettype_tcp:
+ sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
+ break;
++
++ case isc_sockettype_fd:
++ sock->fd = pf;
+ }
+
+ #ifdef F_DUPFD
+ /*
+ * Leave a space for stdio to work in.
+ */
+- if (sock->fd >= 0 && sock->fd < 20) {
++ if ( (type != isc_sockettype_fd) && (sock->fd >= 0) && (sock->fd < 20) ) {
+ int new, tmp;
+ new = fcntl(sock->fd, F_DUPFD, 20);
+ tmp = errno;
+@@ -1461,7 +1472,7 @@
+ }
+ }
+
+- if (make_nonblock(sock->fd) != ISC_R_SUCCESS) {
++ if ((type != isc_sockettype_fd) && (make_nonblock(sock->fd) != ISC_R_SUCCESS)) {
+ (void)close(sock->fd);
+ free_socket(&sock);
+ return (ISC_R_UNEXPECTED);
+@@ -1729,6 +1740,38 @@
+ isc_task_send(ev->ev_sender, (isc_event_t **)&iev);
+ }
+
++static
++isc_event_t *dispatch_read_ready(isc_socketmgr_t *manager, isc_socket_t *sock)
++{
++ isc_event_t *dev = (isc_event_t*)sock->read_ready_event, *ev;
++
++ ev = isc_mem_get(manager->mctx, dev->ev_size);
++ memcpy(ev,dev,dev->ev_size);
++ ISC_LINK_INIT(ev,ev_link);
++ isc_task_send(dev->ev_sender, &ev );
++ return (isc_event_t *)sock->selected_event;
++}
++
++static
++isc_event_t *dispatch_write_ready(isc_socketmgr_t *manager,isc_socket_t *sock)
++{
++ isc_event_t *dev = (isc_event_t*)sock->write_ready_event, *ev;
++ ev = isc_mem_get(manager->mctx, dev->ev_size);
++ memcpy(ev,dev,dev->ev_size);
++ ISC_LINK_INIT(ev,ev_link);
++ isc_task_send(dev->ev_sender, &ev );
++ return (isc_event_t *)sock->selected_event;
++}
++
++static
++void dispatch_selected(isc_socketmgr_t *manager, isc_event_t *dev)
++{ isc_event_t *ev;
++ ev = isc_mem_get(manager->mctx, dev->ev_size);
++ memcpy(ev,dev,dev->ev_size);
++ ISC_LINK_INIT(ev,ev_link);
++ isc_task_send(dev->ev_sender, &ev );
++}
++
+ /*
+ * Dequeue an item off the given socket's read queue, set the result code
+ * in the done event to the one provided, and send it to the task it was
+@@ -2136,6 +2179,7 @@
+ int i;
+ isc_socket_t *sock;
+ isc_boolean_t unlock_sock;
++ isc_event_t *sock_selected = 0L;
+
+ REQUIRE(maxfd <= (int)FD_SETSIZE);
+
+@@ -2169,11 +2213,15 @@
+ unlock_sock = ISC_TRUE;
+ LOCK(&sock->lock);
+ if (!SOCK_DEAD(sock)) {
++ if( sock->type != isc_sockettype_fd )
++ {
+ if (sock->listener)
+ dispatch_accept(sock);
+ else
+ dispatch_recv(sock);
+- }
++ }else
++ sock_selected = dispatch_read_ready(manager,sock);
++ }
+ FD_CLR(i, &manager->read_fds);
+ }
+ check_write:
+@@ -2187,16 +2235,24 @@
+ LOCK(&sock->lock);
+ }
+ if (!SOCK_DEAD(sock)) {
++ if( sock->type != isc_sockettype_fd )
++ {
+ if (sock->connecting)
+ dispatch_connect(sock);
+ else
+ dispatch_send(sock);
++ }else
++ sock_selected = dispatch_write_ready(manager,sock);
+ }
+ FD_CLR(i, &manager->write_fds);
+ }
+ if (unlock_sock)
+ UNLOCK(&sock->lock);
+ }
++ if( sock_selected != 0L )
++ {
++ dispatch_selected(manager, sock_selected);
++ }
+ }
+
+ #ifdef ISC_PLATFORM_USETHREADS
+@@ -2215,7 +2271,7 @@
+ int cc;
+ fd_set readfds;
+ fd_set writefds;
+- int msg, fd;
++ int msg, fd = -1;
+ int maxfd;
+ char strbuf[ISC_STRERRORSIZE];
+
+@@ -3546,3 +3602,55 @@
+ return (ISC_R_SUCCESS);
+ }
+ #endif /* ISC_PLATFORM_USETHREADS */
++
++isc_socketevent_t*
++isc_socket_fd_handle_reads( isc_socket_t *sock, isc_socketevent_t *dev )
++{
++ REQUIRE(VALID_SOCKET(sock));
++ if(dev != 0L)
++ {
++ sock->references=1;
++ sock->read_ready_event = dev;
++ select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
++ }else
++ {
++ dev = sock->read_ready_event ;
++ sock->read_ready_event = 0L ;
++ }
++ return dev;
++}
++
++isc_socketevent_t*
++isc_socket_fd_handle_writes( isc_socket_t *sock, isc_socketevent_t *dev )
++{
++ REQUIRE(VALID_SOCKET(sock));
++ if(dev != 0L)
++ {
++ sock->references=1;
++ sock->write_ready_event = dev;
++ select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
++ }else
++ {
++ dev = sock->write_ready_event;
++ sock->write_ready_event = 0L;
++ }
++ return dev;
++}
++
++isc_socketevent_t*
++isc_socket_fd_handle_selected( isc_socket_t *sock, isc_socketevent_t *dev )
++{
++ REQUIRE(VALID_SOCKET(sock));
++ if(dev != 0L)
++ {
++ sock->references=1;
++ sock->selected_event = dev;
++ }else
++ {
++ dev = sock->selected_event;
++ sock->selected_event = 0L;
++ sock->references=0;
++ destroy(&sock);
++ }
++ return dev;
++}
+--- bind-9.3.3rc2/bin/named/named.8.dbus 2006-06-29 15:02:30.000000000 +0200
++++ bind-9.3.3rc2/bin/named/named.8 2006-09-18 10:08:37.000000000 +0200
+@@ -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\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\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\-f\fR] [\fB\-g\fR] [\fB\-n\ \fR\fB\fI#cpus\fR\fR] [\fB\-p\ \fR\fB\fIport\fR\fR] [\fB\-s\fR] [\fB\-t\ \fR\fB\fIdirectory\fR\fR] [\fB\-u\ \fR\fB\fIuser\fR\fR] [\fB\-v\fR] [\fB\-x\ \fR\fB\fIcache\-file\fR\fR] [\fB\-D\fR]
+ .SH "DESCRIPTION"
+ .PP
+ \fBnamed\fR
+@@ -146,6 +146,13 @@
+ .B "Warning:"
+ This option must not be used. It is only of interest to BIND 9 developers and may be removed or changed in a future release.
+ .RE
++.sp
++.TP
++\fB\-D\fR
++Enable dynamic management of the forwarding table with D-BUS
++messages. This option is required for Red Hat NetworkManager
++support. See doc/README.DBUS .
++.sp
+ .SH "SIGNALS"
+ .PP
+ In routine operation, signals should not be used to control the nameserver;
+@@ -165,6 +172,73 @@
+ \fBnamed\fR
+ configuration file is too complex to describe in detail here. A complete description is provided in the
+ BIND 9 Administrator Reference Manual.
++.PP
++.SH "NOTES"
++.PP
++.TP
++\fBRed Hat SELinux BIND Security Profile:\fR
++.PP
++By default, Red Hat ships BIND with the most secure SELinux policy
++that will not prevent normal BIND operation and will prevent exploitation
++of all known BIND security vulnerabilities . See the selinux(8) man page
++for information about SElinux.
++.PP
++It is not necessary to run named in a chroot environment if the Red Hat
++SELinux policy for named is enabled. When enabled, this policy is far
++more secure than a chroot environment.
++.PP
++With this extra security comes some restrictions:
++.br
++By default, the SELinux policy does not allow named to write any master
++zone database files. Only the root user may create files in the $ROOTDIR/var/named
++zone database file directory (the options { "directory" } option), where
++$ROOTDIR is set in /etc/sysconfig/named.
++.br
++The "named" group must be granted read privelege to
++these files in order for named to be enabled to read them.
++.br
++Any file created in the zone database file directory is automatically assigned
++the SELinux file context named_zone_t .
++.br
++By default, SELinux prevents any role from modifying named_zone_t files; this
++means that files in the zone database directory cannot be modified by dynamic
++DNS (DDNS) updates or zone transfers.
++.br
++The Red Hat BIND distribution and SELinux policy creates two directories where
++named is allowed to create and modify files: $ROOTDIR/var/named/slaves and
++$ROOTDIR/var/named/data. By placing files you want named to modify, such as
++slave or DDNS updateable zone files and database / statistics dump files in
++these directories, named will work normally and no further operator action is
++required. Files in these directories are automatically assigned the 'named_cache_t'
++file context, which SELinux allows named to write.
++.br
++You can enable the named_t domain to write and create named_zone_t files by use
++of the SELinux tunable boolean variable "named_write_master_zones", using the
++setsebool(8) command or the system-config-security GUI . If you do this, you
++must also set the ENABLE_ZONE_WRITE variable in /etc/sysconfig/named to
++1 / yes to set the ownership of files in the $ROOTDIR/var/named directory
++to named:named in order for named to be allowed to write them.
++.PP
++\fBRed Hat BIND named_sdb SDB support:\fR
++.PP
++Red Hat ships the bind-sdb RPM that provides the /usr/sbin/named_sdb program,
++which is named compiled with the Simplified Database Backend modules that ISC
++provides in the "contrib/sdb" directory.
++.br
++The SDB modules for LDAP, PostGreSQL and DirDB are compiled into named_sdb.
++.br
++To run named_sdb, set the ENABLE_SDB variable in /etc/sysconfig/named to 1 or "yes",
++and then the "service named start" named initscript will run named_sdb instead
++of named .
++.br
++See the documentation for the various SDB modules in /usr/share/doc/bind-sdb-*/ .
++.PP
++\fBRed Hat system-config-bind:\fR
++.PP
++Red Hat provides the system-config-bind GUI to configure named.conf and zone
++database files. Run the "system-config-bind" command and access the manual
++by selecting the Help menu.
++.PP
+ .SH "FILES"
+ .TP 3n
+ \fI/etc/named.conf\fR
+--- bind-9.3.3rc2/bin/named/include/named/globals.h.dbus 2006-03-02 01:37:20.000000000 +0100
++++ bind-9.3.3rc2/bin/named/include/named/globals.h 2006-09-18 10:08:37.000000000 +0200
+@@ -112,6 +112,8 @@
+
+ EXTERN int ns_g_listen INIT(3);
+
++EXTERN int ns_g_dbus INIT(0);
++
+ #undef EXTERN
+ #undef INIT
+
+--- bind-9.3.3rc2/bin/named/include/named/log.h.dbus 2004-03-08 05:04:21.000000000 +0100
++++ bind-9.3.3rc2/bin/named/include/named/log.h 2006-09-18 10:08:37.000000000 +0200
+@@ -34,6 +34,7 @@
+ #define NS_LOGCATEGORY_QUERIES (&ns_g_categories[4])
+ #define NS_LOGCATEGORY_UNMATCHED (&ns_g_categories[5])
+ #define NS_LOGCATEGORY_UPDATE_SECURITY (&ns_g_categories[6])
++#define NS_LOGCATEGORY_DBUS (&ns_g_categories[7])
+
+ /*
+ * Backwards compatibility.
+@@ -51,6 +52,7 @@
+ #define NS_LOGMODULE_NOTIFY (&ns_g_modules[8])
+ #define NS_LOGMODULE_CONTROL (&ns_g_modules[9])
+ #define NS_LOGMODULE_LWRESD (&ns_g_modules[10])
++#define NS_LOGMODULE_DBUS (&ns_g_modules[11])
+
+ isc_result_t
+ ns_log_init(isc_boolean_t safe);
+--- bind-9.3.3rc2/bin/named/include/named/server.h.dbus 2006-03-02 01:37:20.000000000 +0100
++++ bind-9.3.3rc2/bin/named/include/named/server.h 2006-09-18 10:08:37.000000000 +0200
+@@ -91,7 +91,8 @@
+ ns_controls_t * controls; /* Control channels */
+ unsigned int dispatchgen;
+ ns_dispatchlist_t dispatches;
+-
++
++ ns_dbus_mgr_t * dbus_mgr;
+ };
+
+ #define NS_SERVER_MAGIC ISC_MAGIC('S','V','E','R')
+--- bind-9.3.3rc2/bin/named/include/named/types.h.dbus 2004-03-06 11:21:26.000000000 +0100
++++ bind-9.3.3rc2/bin/named/include/named/types.h 2006-09-18 10:08:37.000000000 +0200
+@@ -38,4 +38,6 @@
+ typedef struct ns_dispatch ns_dispatch_t;
+ typedef ISC_LIST(ns_dispatch_t) ns_dispatchlist_t;
+
++typedef struct ns_dbus_mgr ns_dbus_mgr_t ;
++
+ #endif /* NAMED_TYPES_H */
+--- bind-9.3.3rc2/bin/named/log.c.dbus 2005-05-25 01:58:17.000000000 +0200
++++ bind-9.3.3rc2/bin/named/log.c 2006-09-18 10:08:37.000000000 +0200
+@@ -41,6 +41,7 @@
+ { "queries", 0 },
+ { "unmatched", 0 },
+ { "update-security", 0 },
++ { "dbus", 0 },
+ { NULL, 0 }
+ };
+
+@@ -60,6 +61,7 @@
+ { "notify", 0 },
+ { "control", 0 },
+ { "lwresd", 0 },
++ { "dbus", 0 },
+ { NULL, 0 }
+ };
+
+--- bind-9.3.3rc2/bin/named/main.c.dbus 2006-01-06 01:01:42.000000000 +0100
++++ bind-9.3.3rc2/bin/named/main.c 2006-09-18 10:08:37.000000000 +0200
+@@ -239,7 +239,8 @@
+ "usage: named [-4|-6] [-c conffile] [-d debuglevel] "
+ "[-f|-g] [-n number_of_cpus]\n"
+ " [-p port] [-s] [-t chrootdir] [-u username]\n"
+- " [-m {usage|trace|record}]\n");
++ " [-m {usage|trace|record}]\n"
++ " [-D ]\n");
+ }
+
+ static void
+@@ -345,7 +346,7 @@
+
+ isc_commandline_errprint = ISC_FALSE;
+ while ((ch = isc_commandline_parse(argc, argv,
+- "46c:C:d:fgi:lm:n:N:p:P:st:u:vx:")) != -1) {
++ "46c:C:d:fgi:lm:n:N:p:P:st:u:vx:D")) != -1) {
+ switch (ch) {
+ case '4':
+ if (disable4)
+@@ -434,6 +435,9 @@
+ case 'v':
+ printf("BIND %s\n", ns_g_version);
+ exit(0);
++ case 'D':
++ ns_g_dbus = 1;
++ break;
+ case '?':
+ usage();
+ ns_main_earlyfatal("unknown option '-%c'",
+--- bind-9.3.3rc2/bin/named/server.c.dbus 2006-05-24 06:30:24.000000000 +0200
++++ bind-9.3.3rc2/bin/named/server.c 2006-09-18 10:08:37.000000000 +0200
+@@ -86,6 +86,8 @@
+ #include <stdlib.h>
+ #endif
+
++#include <named/dbus_mgr.h>
++
+ /*
+ * Check an operation for failure. Assumes that the function
+ * using it has a 'result' variable and a 'cleanup' label.
+@@ -1495,12 +1497,12 @@
+ if (result != ISC_R_SUCCESS) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(origin, namebuf, sizeof(namebuf));
+- cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_WARNING,
+- "could not set up forwarding for domain '%s': %s",
++ cfg_obj_log(forwarders, ns_g_lctx, ISC_LOG_NOTICE,
++ "setting up forwarding failed for domain '%s': %s",
+ namebuf, isc_result_totext(result));
+ goto cleanup;
+ }
+-
++
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+@@ -2875,6 +2877,20 @@
+
+ CHECKFATAL(load_zones(server, ISC_FALSE), "loading zones");
+
++ server->dbus_mgr = 0L;
++ if( ns_g_dbus )
++ if( dbus_mgr_create
++ ( ns_g_mctx, ns_g_taskmgr, ns_g_socketmgr, ns_g_timermgr,
++ &server->dbus_mgr
++ ) != ISC_R_SUCCESS
++ )
++ {
++ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
++ NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
++ "dbus_mgr initialization failed. D-BUS service is disabled."
++ );
++ }
++
+ ns_os_started();
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
+ ISC_LOG_NOTICE, "running");
+@@ -2937,6 +2953,9 @@
+
+ dns_db_detach(&server->in_roothints);
+
++ if( server->dbus_mgr != 0L )
++ dbus_mgr_shutdown(server->dbus_mgr);
++
+ isc_task_endexclusive(server->task);
+
+ isc_task_detach(&server->task);
+--- bind-9.3.3rc2/bin/named/Makefile.in.dbus 2004-09-06 23:47:25.000000000 +0200
++++ bind-9.3.3rc2/bin/named/Makefile.in 2006-09-18 10:10:58.000000000 +0200
+@@ -35,7 +35,8 @@
+ ${LWRES_INCLUDES} ${DNS_INCLUDES} ${BIND9_INCLUDES} \
+ ${ISCCFG_INCLUDES} ${ISCCC_INCLUDES} ${ISC_INCLUDES} \
+ ${DBDRIVER_INCLUDES}
+-
++DBUS_INCLUDES = \
++ -I/usr/lib/dbus-1.0/include -I/usr/include/dbus-1.0
+ CDEFINES =
+ CWARNINGS =
+
+@@ -52,6 +53,7 @@
+ ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+ BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
++DBUSLIBS= -ldbus-1
+
+ DEPLIBS = ${LWRESDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} \
+ ${ISCCFGDEPLIBS} ${ISCCCDEPLIBS} ${ISCDEPLIBS}
+@@ -71,6 +73,7 @@
+ zoneconf.@O@ \
+ lwaddr.@O@ lwresd.@O@ lwdclient.@O@ lwderror.@O@ lwdgabn.@O@ \
+ lwdgnba.@O@ lwdgrbn.@O@ lwdnoop.@O@ lwsearch.@O@ \
++ dbus_service.@O@ dbus_mgr.@O@ \
+ $(DBDRIVER_OBJS)
+
+ UOBJS = unix/os.@O@
+@@ -83,6 +86,7 @@
+ zoneconf.c \
+ lwaddr.c lwresd.c lwdclient.c lwderror.c lwdgabn.c \
+ lwdgnba.c lwdgrbn.c lwdnoop.c lwsearch.c \
++ dbus_service.c dbus_mgr.c \
+ $(DBDRIVER_SRCS)
+
+ MANPAGES = named.8 lwresd.8 named.conf.5
+@@ -105,9 +109,14 @@
+ -DNS_LOCALSTATEDIR=\"${localstatedir}\" \
+ -c ${srcdir}/config.c
+
++dbus_service.o: dbus_service.c
++ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} \
++ ${DBUS_INCLUDES} \
++ -c ${srcdir}/dbus_service.c
++
+ named@EXEEXT@: ${OBJS} ${UOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+- ${OBJS} ${UOBJS} ${LIBS}
++ ${OBJS} ${UOBJS} ${LIBS} ${DBUSLIBS}
+
+ lwresd@EXEEXT@: named@EXEEXT@
+ rm -f lwresd@EXEEXT@
diff --git a/contrib/dbus/dbus_mgr.c b/contrib/dbus/dbus_mgr.c
new file mode 100644
index 0000000..b744790
--- /dev/null
+++ b/contrib/dbus/dbus_mgr.c
@@ -0,0 +1,2458 @@
+/* dbus_mgr.c
+ *
+ * named module to provide dynamic forwarding zones in
+ * response to D-BUS dhcp events or commands.
+ *
+ * Copyright(C) Jason Vas Dias, Red Hat Inc., 2005
+ * Modified by Adam Tkac, Red Hat Inc., 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at
+ * http://www.fsf.org/licensing/licenses/gpl.txt
+ * and included in this software distribution as the "LICENSE" file.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <config.h>
+#include <isc/types.h>
+#include <isc/net.h>
+#include <isc/mem.h>
+#include <isc/magic.h>
+#include <isc/list.h>
+#include <isc/task.h>
+#include <isc/event.h>
+#include <isc/socket.h>
+#include <isc/timer.h>
+#include <isc/netaddr.h>
+#include <isc/sockaddr.h>
+#include <isc/buffer.h>
+#include <isc/log.h>
+
+#include <dns/name.h>
+#include <dns/acl.h>
+#include <dns/fixedname.h>
+#include <dns/view.h>
+#include <dns/forward.h>
+
+#include <named/types.h>
+#include <named/config.h>
+#include <named/server.h>
+#include <named/globals.h>
+#include <named/log.h>
+
+#include <named/dbus_service.h>
+#include <named/dbus_mgr.h>
+
+#include <string.h>
+#include <search.h>
+
+typedef void (*__free_fn_t) (void *__nodep);
+extern void tdestroy (void *__root, __free_fn_t __freefct);
+extern void free(void*);
+
+#ifdef ISC_USE_INTERNAL_MALLOC
+# if ISC_USE_INTERNAL_MALLOC
+# error dbus_mgr cannot be used if ISC_USE_INTERNAL_MALLOC==1
+# endif
+#endif
+
+#define DBUSMGR_DESTINATION "com.redhat.named"
+#define DBUSMGR_OBJECT_PATH "/com/redhat/named"
+#define DBUSMGR_INTERFACE "com.redhat.named"
+
+#define DBUSMGR_MAGIC ISC_MAGIC('D', 'B', 'U', 'S')
+
+struct ns_dbus_mgr
+{
+ unsigned int magic;
+ isc_mem_t * mctx; /* Memory context. */
+ isc_taskmgr_t * taskmgr; /* Task manager. */
+ isc_socketmgr_t * socketmgr; /* Socket manager. */
+ isc_timermgr_t * timermgr; /* Timer manager. */
+ isc_task_t * task; /* task */
+ isc_timer_t * timer; /* dbus_init retry */
+ void * sockets; /* dbus fd tree */
+ void * dhc_if; /* dhcp interface tree */
+ void * ifwdt; /* initial forwarder tree */
+ char * dhcdbd_name; /* dhcdbd destination */
+ DBUS_SVC dbus; /* dbus handle */
+};
+
+typedef
+struct dbus_mgr_sock_s
+{
+ int fd;
+ struct ns_dbus_mgr *mgr;
+ isc_socket_t *sock;
+ isc_socketevent_t *ser;
+ isc_socketevent_t *sew;
+ isc_socketevent_t *sel;
+} DBusMgrSocket;
+
+typedef
+enum dhc_state_e
+{
+ DHC_NBI, /* no broadcast interfaces found */
+ DHC_PREINIT, /* configuration started */
+ DHC_BOUND, /* lease obtained */
+ DHC_RENEW, /* lease renewed */
+ DHC_REBOOT, /* have valid lease, but now obtained a different one */
+ DHC_REBIND, /* new, different lease */
+ DHC_STOP, /* remove old lease */
+ DHC_MEDIUM, /* media selection begun */
+ DHC_TIMEOUT, /* timed out contacting DHCP server */
+ DHC_FAIL, /* all attempts to contact server timed out, sleeping */
+ DHC_EXPIRE, /* lease has expired, renewing */
+ DHC_RELEASE, /* releasing lease */
+ DHC_START, /* sent when dhclient started OK */
+ DHC_ABEND, /* dhclient exited abnormally */
+ DHC_END, /* dhclient exited normally */
+ DHC_END_OPTIONS, /* last option in subscription sent */
+ DHC_INVALID=255
+} DHC_State;
+
+typedef ISC_LIST(dns_name_t) DNSNameList;
+
+typedef ISC_LIST(isc_sockaddr_t) SockAddrList;
+
+typedef struct dbm_fwdr_s
+{
+ dns_fwdpolicy_t fwdpolicy;
+ dns_name_t dn;
+ SockAddrList sa;
+ ISC_LINK( struct dbm_fwdr_s ) link;
+} DBusMgrInitialFwdr;
+
+typedef
+struct dhc_if_s
+{
+ char *if_name;
+ DHC_State dhc_state;
+ DHC_State previous_state;
+ struct in_addr ip;
+ struct in_addr subnet_mask;
+ DNSNameList dn;
+ SockAddrList dns;
+} DHC_IF;
+
+static void
+dbus_mgr_watch_handler( int fd, dbus_svc_WatchFlags flags, void *mgrp );
+
+static
+dbus_svc_HandlerResult
+dbus_mgr_message_handler
+(
+ DBusMsgHandlerArgs
+);
+
+static
+void dbus_mgr_close_socket( const void *p, const VISIT which, const int level);
+
+static
+void dbus_mgr_destroy_socket( void *p );
+
+static
+void dbus_mgr_free_dhc( void *p );
+
+static void
+dbus_mgr_watches_selected(isc_task_t *t, isc_event_t *ev);
+
+static isc_result_t
+dbus_mgr_init_dbus(ns_dbus_mgr_t *);
+
+static isc_result_t
+dbus_mgr_record_initial_fwdtable(ns_dbus_mgr_t *);
+
+static
+dns_fwdtable_t *dbus_mgr_get_fwdtable(void);
+
+static void
+dbus_mgr_free_initial_fwdtable(ns_dbus_mgr_t *);
+
+static
+uint8_t dbus_mgr_subscribe_to_dhcdbd( ns_dbus_mgr_t * );
+
+static
+void dbus_mgr_dbus_shutdown_handler ( ns_dbus_mgr_t * );
+
+static
+int dbus_mgr_log_err( const char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ isc_log_vwrite(ns_g_lctx,
+ NS_LOGCATEGORY_DBUS,
+ NS_LOGMODULE_DBUS,
+ ISC_LOG_NOTICE,
+ fmt, va
+ );
+ va_end(va);
+ return 0;
+}
+
+static
+int dbus_mgr_log_dbg( const char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ isc_log_vwrite(ns_g_lctx,
+ NS_LOGCATEGORY_DBUS,
+ NS_LOGMODULE_DBUS,
+ ISC_LOG_DEBUG(80),
+ fmt, va
+ );
+ va_end(va);
+ return 0;
+}
+
+static
+int dbus_mgr_log_info( const char *fmt, ...)
+{
+ va_list va;
+ va_start(va, fmt);
+ isc_log_vwrite(ns_g_lctx,
+ NS_LOGCATEGORY_DBUS,
+ NS_LOGMODULE_DBUS,
+ ISC_LOG_DEBUG(1),
+ fmt, va
+ );
+ va_end(va);
+ return 0;
+}
+
+isc_result_t
+dbus_mgr_create
+( isc_mem_t *mctx,
+ isc_taskmgr_t *taskmgr,
+ isc_socketmgr_t *socketmgr,
+ isc_timermgr_t *timermgr,
+ ns_dbus_mgr_t **dbus_mgr
+)
+{
+ isc_result_t result;
+ ns_dbus_mgr_t *mgr;
+
+ *dbus_mgr = 0L;
+
+ mgr = isc_mem_get(mctx, sizeof(*mgr));
+ if (mgr == NULL)
+ return (ISC_R_NOMEMORY);
+
+ mgr->magic = DBUSMGR_MAGIC;
+ mgr->mctx = mctx;
+ mgr->taskmgr = taskmgr;
+ mgr->socketmgr = socketmgr;
+ mgr->timermgr = timermgr;
+ mgr->task = 0L;
+ mgr->sockets = 0L;
+ mgr->timer = 0L;
+ mgr->dhc_if = 0L;
+ mgr->ifwdt = 0L;
+ mgr->dhcdbd_name = 0L;
+
+ if( (result = isc_task_create( taskmgr, 100, &(mgr->task)))
+ != ISC_R_SUCCESS
+ ) goto cleanup_mgr;
+
+ isc_task_setname( mgr->task, "dbusmgr", mgr );
+
+ mgr->dbus = 0L;
+
+ if( (result = dbus_mgr_record_initial_fwdtable( mgr ))
+ != ISC_R_SUCCESS
+ ) goto cleanup_mgr;
+
+ if( (result = dbus_mgr_init_dbus( mgr ))
+ != ISC_R_SUCCESS
+ ) goto cleanup_mgr;
+
+ *dbus_mgr = mgr;
+
+ return ISC_R_SUCCESS;
+
+ cleanup_mgr:
+ if ( dbus_mgr_get_fwdtable() != NULL)
+ dbus_mgr_free_initial_fwdtable (mgr);
+ if( mgr->task != 0L )
+ isc_task_detach(&(mgr->task));
+ isc_mem_put(mctx, mgr, sizeof(*mgr));
+ return (result);
+}
+
+static isc_result_t
+dbus_mgr_init_dbus(ns_dbus_mgr_t * mgr)
+{
+ char destination[]=DBUSMGR_DESTINATION;
+ isc_result_t result;
+
+ if( mgr->sockets != 0L )
+ {
+ isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
+ twalk(mgr->sockets, dbus_mgr_close_socket);
+ tdestroy(mgr->sockets, dbus_mgr_destroy_socket);
+ mgr->sockets = 0L;
+ }
+
+ if( mgr->dbus != 0L )
+ {
+ dbus_svc_shutdown(mgr->dbus);
+ mgr->dbus = 0L;
+ }
+
+ result = dbus_svc_init(DBUS_PRIVATE_SYSTEM, destination, &mgr->dbus,
+ dbus_mgr_watch_handler, 0L, 0L, mgr);
+
+ if(result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ if( mgr->dbus == 0L )
+ {
+ if( mgr->timer == 0L)
+ {
+ isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
+ if( mgr->sockets != 0L )
+ {
+ twalk(mgr->sockets, dbus_mgr_close_socket);
+ tdestroy(mgr->sockets, dbus_mgr_destroy_socket);
+ mgr->sockets = 0L;
+ }
+ dbus_mgr_dbus_shutdown_handler ( mgr );
+ return ISC_R_SUCCESS;
+ }
+ goto cleanup;
+ }
+
+ if( !dbus_svc_add_filter
+ ( mgr->dbus, dbus_mgr_message_handler, mgr, 4,
+ "type=signal,path=/org/freedesktop/DBus,member=NameOwnerChanged",
+ "type=signal,path=/org/freedesktop/DBus/Local,member=Disconnected",
+ "type=signal,interface=com.redhat.dhcp.subscribe.binary",
+ "type=method_call,destination=com.redhat.named,path=/com/redhat/named"
+ )
+ )
+ {
+ dbus_mgr_log_err( "dbus_svc_add_filter failed" );
+ goto cleanup;
+ }
+
+ if( mgr->timer != 0L )
+ {
+ isc_timer_reset(mgr->timer,
+ isc_timertype_inactive,
+ NULL, NULL, ISC_TRUE
+ );
+ }
+
+ if( !dbus_mgr_subscribe_to_dhcdbd( mgr ) )
+ dbus_mgr_log_err("D-BUS dhcdbd subscription disabled.");
+
+ dbus_mgr_log_err("D-BUS service enabled.");
+ return ISC_R_SUCCESS;
+
+ cleanup:
+ isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
+ twalk(mgr->sockets, dbus_mgr_close_socket);
+ tdestroy(mgr->sockets, dbus_mgr_destroy_socket);
+ mgr->sockets = 0L;
+ if( mgr->dbus )
+ {
+ dbus_svc_shutdown(mgr->dbus);
+ mgr->dbus = 0L;
+ }
+ return ISC_R_FAILURE;
+}
+
+static
+uint8_t dbus_mgr_subscribe_to_dhcdbd( ns_dbus_mgr_t *mgr )
+{
+ DBUS_SVC dbus = mgr->dbus;
+ char subs[1024], path[1024],
+ dhcdbd_destination[]="com.redhat.dhcp", *ddp[1]={ &(dhcdbd_destination[0]) },
+ *dhcdbd_name=0L;
+ const char *options[] = { "reason", "ip-address", "subnet-mask",
+ "domain-name", "domain-name-servers"
+ };
+ dbus_svc_MessageHandle msg;
+ int i, n_opts = 5;
+
+ if( mgr->dhcdbd_name == 0L )
+ {
+ msg = dbus_svc_call
+ ( dbus,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "GetNameOwner",
+ "org.freedesktop.DBus",
+ TYPE_STRING, &ddp,
+ TYPE_INVALID
+ );
+ if( msg == 0L )
+ return 0;
+
+ if( !dbus_svc_get_args(dbus, msg,
+ TYPE_STRING, &(dhcdbd_name),
+ TYPE_INVALID
+ )
+ ) return 0;
+
+ mgr->dhcdbd_name = isc_mem_get(mgr->mctx, strlen(dhcdbd_name) + 1);
+ if( mgr->dhcdbd_name == 0L )
+ return 0;
+
+ strcpy(mgr->dhcdbd_name, dhcdbd_name);
+
+ }
+
+ sprintf(path,"/com/redhat/dhcp/subscribe");
+ sprintf(subs,"com.redhat.dhcp.binary");
+
+ for(i = 0; i < n_opts; i++)
+ {
+ msg = dbus_svc_call
+ ( dbus,
+ "com.redhat.dhcp",
+ path,
+ "binary",
+ subs,
+ TYPE_STRING, &(options[i]),
+ TYPE_INVALID
+ );
+ if(msg == 0L)
+ return 0;
+ if ( dbus_svc_message_type( msg ) == ERROR )
+ return 0;
+ }
+ dbus_mgr_log_err("D-BUS dhcdbd subscription enabled.");
+ return 1;
+}
+
+void
+dbus_mgr_shutdown
+( ns_dbus_mgr_t *mgr
+)
+{
+ if( mgr->timer != 0L )
+ isc_timer_detach(&(mgr->timer));
+ if( mgr->dbus != 0L )
+ {
+ isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
+ if( mgr->sockets != 0L )
+ {
+ twalk(mgr->sockets, dbus_mgr_close_socket);
+ tdestroy(mgr->sockets, dbus_mgr_destroy_socket);
+ mgr->sockets = 0L;
+ }
+ dbus_svc_shutdown(mgr->dbus);
+ }
+ if( mgr->dhc_if != 0L )
+ tdestroy(mgr->dhc_if, dbus_mgr_free_dhc);
+ if( mgr->dhcdbd_name != 0L )
+ isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name) + 1);
+ isc_task_detach(&(mgr->task));
+ dbus_mgr_free_initial_fwdtable(mgr);
+ isc_mem_put(mgr->mctx, mgr, sizeof(ns_dbus_mgr_t));
+}
+
+static
+void dbus_mgr_restart_dbus(isc_task_t *t, isc_event_t *ev)
+{
+ ns_dbus_mgr_t *mgr = (ns_dbus_mgr_t*)(ev->ev_arg) ;
+ t=t;
+ isc_event_free(&ev);
+ dbus_mgr_log_dbg("attempting to connect to D-BUS");
+ dbus_mgr_init_dbus( mgr );
+}
+
+static
+void dbus_mgr_handle_dbus_shutdown_event(isc_task_t *t, isc_event_t *ev)
+{
+ ns_dbus_mgr_t *mgr = ev->ev_arg;
+ isc_time_t tick={10,0};
+ isc_interval_t tock={10,0};
+ DBUS_SVC dbus = mgr->dbus;
+ t = t;
+
+ mgr->dbus = 0L;
+
+ isc_event_free(&ev);
+
+ if ( dbus != 0L )
+ {
+ isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
+ if( mgr->sockets != 0L )
+ {
+ twalk(mgr->sockets, dbus_mgr_close_socket);
+ tdestroy(mgr->sockets, dbus_mgr_destroy_socket);
+ mgr->sockets = 0L;
+ }
+ dbus_svc_shutdown(dbus);
+ }
+
+ dbus_mgr_log_err( "D-BUS service disabled." );
+
+ if( mgr->timer != 0L )
+ {
+ isc_timer_reset(mgr->timer,
+ isc_timertype_ticker,
+ &tick, &tock, ISC_TRUE
+ );
+ }else
+ if( isc_timer_create
+ ( mgr->timermgr,
+ isc_timertype_ticker,
+ &tick, &tock,
+ mgr->task,
+ dbus_mgr_restart_dbus,
+ mgr,
+ &(mgr->timer)
+ ) != ISC_R_SUCCESS
+ )
+ {
+ dbus_mgr_log_err( "D-BUS service cannot be restored." );
+ }
+}
+
+static
+void dbus_mgr_dbus_shutdown_handler ( ns_dbus_mgr_t *mgr )
+{
+ isc_event_t *dbus_shutdown_event =
+ isc_event_allocate
+ ( mgr->mctx,
+ mgr->task,
+ 1,
+ dbus_mgr_handle_dbus_shutdown_event,
+ mgr,
+ sizeof(isc_event_t)
+ );
+ if( dbus_shutdown_event != 0L )
+ {
+ isc_task_purgerange(mgr->task, 0L, ISC_SOCKEVENT_READ_READY, ISC_SOCKEVENT_SELECTED, 0L);
+ isc_task_send( mgr->task, &dbus_shutdown_event );
+ }else
+ dbus_mgr_log_err("unable to allocate dbus shutdown event");
+}
+
+static
+dns_view_t *dbus_mgr_get_localhost_view(void)
+{
+ dns_view_t *view;
+ isc_netaddr_t localhost = { AF_INET, { { htonl( ( 127 << 24 ) | 1 ) } }, 0 };
+ int match;
+
+ for (view = ISC_LIST_HEAD(ns_g_server->viewlist);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)
+ )
+ {
+ /* return first view matching "localhost" source and dest */
+
+ if(( (view->matchclients != 0L ) /* 0L: accept "any" */
+ &&(( dns_acl_match( &localhost,
+ NULL, /* unsigned queries */
+ view->matchclients,
+ &(ns_g_server->aclenv),
+ &match,
+ NULL /* no match list */
+ ) != ISC_R_SUCCESS
+ ) || (match <= 0)
+ )
+ )
+ ||( (view->matchdestinations != 0L ) /* 0L: accept "any" */
+ &&(( dns_acl_match( &localhost,
+ NULL, /* unsigned queries */
+ view->matchdestinations,
+ &(ns_g_server->aclenv),
+ &match,
+ NULL /* no match list */
+ ) != ISC_R_SUCCESS
+ ) || (match <= 0)
+ )
+ )
+ ) continue;
+
+ break;
+ }
+ return view;
+}
+
+static
+dns_fwdtable_t *dbus_mgr_get_fwdtable(void)
+{
+ dns_view_t *view = dbus_mgr_get_localhost_view();
+ if( view != 0L )
+ return view->fwdtable;
+ return 0L;
+}
+
+static
+dns_fwdtable_t *dbus_mgr_get_view_and_fwdtable( dns_view_t **viewp )
+{
+ *viewp = dbus_mgr_get_localhost_view();
+ if( *viewp != 0L )
+ return (*viewp)->fwdtable;
+ return 0L;
+}
+
+static int dbus_mgr_ifwdr_comparator( const void *p1, const void *p2 )
+{
+ char n1buf[ DNS_NAME_FORMATSIZE ]="", *n1p=&(n1buf[0]),
+ n2buf[ DNS_NAME_FORMATSIZE ]="", *n2p=&(n2buf[0]);
+ dns_name_t *dn1;
+ dns_name_t *dn2;
+ DE_CONST(&(((const DBusMgrInitialFwdr*)p1)->dn), dn1);
+ DE_CONST(&(((const DBusMgrInitialFwdr*)p2)->dn), dn2);
+ dns_name_format(dn1, n1p, DNS_NAME_FORMATSIZE );
+ dns_name_format(dn2, n2p, DNS_NAME_FORMATSIZE );
+ return strcmp(n1buf, n2buf);
+}
+
+static int dbus_mgr_dhc_if_comparator( const void *p1, const void *p2 );
+
+static void dbus_mgr_record_initial_forwarder( dns_name_t *name, dns_forwarders_t *fwdr, void *mp )
+{
+ ns_dbus_mgr_t *mgr = mp;
+ isc_sockaddr_t *sa, *nsa;
+ DBusMgrInitialFwdr *ifwdr;
+
+ if( ISC_LIST_HEAD(fwdr->addrs) == 0L)
+ return;
+
+ if( (ifwdr = isc_mem_get(mgr->mctx, sizeof(DBusMgrInitialFwdr))) == 0L)
+ return;
+
+ ifwdr->fwdpolicy = fwdr->fwdpolicy;
+
+ dns_name_init(&(ifwdr->dn), NULL);
+ if( dns_name_dupwithoffsets(name, mgr->mctx, &(ifwdr->dn)) != ISC_R_SUCCESS )
+ goto namedup_err;
+
+ ISC_LIST_INIT(ifwdr->sa);
+
+ for( sa = ISC_LIST_HEAD(fwdr->addrs);
+ sa != 0L;
+ sa = ISC_LIST_NEXT(sa,link)
+ )
+ {
+ nsa = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
+ if( nsa == 0L )
+ goto nsa_err;
+ *nsa = *sa;
+ ISC_LINK_INIT(nsa, link);
+ ISC_LIST_APPEND(ifwdr->sa, nsa, link);
+ }
+ ISC_LINK_INIT(ifwdr, link);
+ tsearch( ifwdr, &(mgr->ifwdt), dbus_mgr_ifwdr_comparator);
+
+ return;
+
+nsa_err:
+ while ( (sa = ISC_LIST_HEAD (ifwdr->sa)) != NULL) {
+ ISC_LIST_UNLINK (ifwdr->sa, sa, link);
+ isc_mem_put (mgr->mctx, sa, sizeof (*sa));
+ }
+
+namedup_err:
+ isc_mem_put (mgr->mctx, ifwdr, sizeof (*ifwdr));
+
+ return;
+}
+
+static isc_result_t
+dbus_mgr_record_initial_fwdtable( ns_dbus_mgr_t *mgr )
+{
+ dns_fwdtable_t *fwdtable = dbus_mgr_get_fwdtable();
+
+ if( fwdtable == 0L )
+ return ISC_R_SUCCESS; /* no initial fwdtable */
+ dns_fwdtable_foreach( fwdtable, dbus_mgr_record_initial_forwarder, mgr);
+ return ISC_R_SUCCESS;
+}
+
+static void
+dbus_mgr_free_initial_forwarder( void *p )
+{
+ DBusMgrInitialFwdr *ifwdr = p;
+ isc_sockaddr_t *sa;
+
+ dns_name_free(&(ifwdr->dn), ns_g_mctx);
+ for( sa = ISC_LIST_HEAD( ifwdr->sa );
+ sa != 0L;
+ sa = ISC_LIST_HEAD( ifwdr->sa )
+ )
+ {
+ if( ISC_LINK_LINKED(sa, link) )
+ ISC_LIST_UNLINK(ifwdr->sa, sa, link);
+ isc_mem_put(ns_g_mctx, sa, sizeof(isc_sockaddr_t));
+ }
+ isc_mem_put(ns_g_mctx, ifwdr, sizeof(DBusMgrInitialFwdr));
+}
+
+static void
+dbus_mgr_free_initial_fwdtable( ns_dbus_mgr_t *mgr )
+{
+ tdestroy(mgr->ifwdt, dbus_mgr_free_initial_forwarder);
+ mgr->ifwdt = 0L;
+}
+
+static void
+dbus_mgr_log_forwarders( const char *pfx, dns_name_t *name, SockAddrList *saList)
+{
+ isc_sockaddr_t *sa;
+ char nameP[DNS_NAME_FORMATSIZE], addrP[128];
+ int s=0;
+ dns_name_format(name, nameP, DNS_NAME_FORMATSIZE );
+ for( sa = ISC_LIST_HEAD(*saList);
+ sa != 0L;
+ sa = ISC_LIST_NEXT(sa,link)
+ )
+ {
+ isc_sockaddr_format(sa, addrP, 128);
+ dbus_mgr_log_info("%s zone %s server %d: %s", pfx, nameP, s++, addrP);
+ }
+}
+
+static
+isc_result_t dbus_mgr_set_forwarders
+(
+ ns_dbus_mgr_t *mgr,
+ DNSNameList *nameList,
+ SockAddrList *saList,
+ dns_fwdpolicy_t fwdpolicy
+)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_fwdtable_t *fwdtable;
+ dns_view_t *view=0L;
+ dns_name_t *dnsName;
+ isc_sockaddr_t *sa, *nsa;
+ dns_forwarders_t *fwdr=0L;
+
+ fwdtable = dbus_mgr_get_view_and_fwdtable(&view);
+
+ if( fwdtable == 0L )
+ {
+ if( ISC_LIST_HEAD(*saList) == 0L )
+ return ISC_R_SUCCESS;/* deletion not required */
+
+ view = dbus_mgr_get_localhost_view();
+ if( view == 0L )
+ return ISC_R_NOPERM; /* if configuration does not allow localhost clients,
+ * then we really shouldn't be creating a forwarding table.
+ */
+ result = isc_task_beginexclusive(mgr->task);
+
+ if( result == ISC_R_SUCCESS )
+ {
+ result = dns_fwdtable_create( mgr->mctx, &(view->fwdtable) );
+
+ isc_task_endexclusive(mgr->task);
+
+ if( result != ISC_R_SUCCESS )
+ return result;
+
+ if( view->fwdtable == 0L )
+ return ISC_R_NOMEMORY;
+
+ if( isc_log_getdebuglevel(ns_g_lctx) >= 1 )
+ dbus_mgr_log_info("Created forwarder table.");
+ }
+ }
+
+ for( dnsName = ISC_LIST_HEAD(*nameList);
+ dnsName != NULL;
+ dnsName = ISC_LIST_NEXT(dnsName,link)
+ )
+ {
+ fwdr = 0L;
+ if( ( dns_fwdtable_find_exact( fwdtable, dnsName, &fwdr ) != ISC_R_SUCCESS )
+ ||( fwdr == 0L )
+ )
+ {
+ if( ISC_LIST_HEAD( *saList ) == 0L )
+ continue;
+ /* no forwarders for name - add forwarders */
+
+ result = isc_task_beginexclusive(mgr->task);
+
+ if( result == ISC_R_SUCCESS )
+ {
+ result = dns_fwdtable_add( fwdtable, dnsName,
+ (isc_sockaddrlist_t*)saList,
+ fwdpolicy
+ ) ;
+
+ if( view != 0L )
+ dns_view_flushcache( view );
+
+ isc_task_endexclusive(mgr->task);
+
+ if( result != ISC_R_SUCCESS )
+ return result;
+
+ if( isc_log_getdebuglevel(ns_g_lctx) >= 1 )
+ dbus_mgr_log_forwarders("Created forwarder",dnsName, saList);
+ }
+ continue;
+ }
+
+ if( ISC_LIST_HEAD( *saList ) == 0L )
+ { /* empty forwarders list - delete forwarder entry */
+
+ if( isc_log_getdebuglevel(ns_g_lctx) >= 1 )
+ dbus_mgr_log_forwarders("Deleting forwarder", dnsName, (SockAddrList*)&(fwdr->addrs));
+
+ result = isc_task_beginexclusive(mgr->task);
+ if( result == ISC_R_SUCCESS )
+ {
+ result = dns_fwdtable_delete( fwdtable, dnsName );
+
+ if( view != 0L )
+ dns_view_flushcache( view );
+
+ isc_task_endexclusive(mgr->task);
+
+ if( result != ISC_R_SUCCESS )
+ return result;
+ }
+ continue;
+ }
+
+ result = isc_task_beginexclusive(mgr->task);
+
+ if( result == ISC_R_SUCCESS )
+ {
+ fwdr->fwdpolicy = fwdpolicy;
+
+ if( isc_log_getdebuglevel(ns_g_lctx) >= 1 )
+ dbus_mgr_log_forwarders("Removing forwarder", dnsName, (SockAddrList*)&(fwdr->addrs));
+
+ for( sa = ISC_LIST_HEAD(fwdr->addrs);
+ sa != 0L ;
+ sa = ISC_LIST_HEAD(fwdr->addrs)
+ )
+ {
+ if( ISC_LINK_LINKED(sa, link) )
+ ISC_LIST_UNLINK(fwdr->addrs, sa, link);
+ isc_mem_put(mgr->mctx, sa, sizeof(isc_sockaddr_t));
+ }
+
+ ISC_LIST_INIT( fwdr->addrs );
+
+ for( sa = ISC_LIST_HEAD(*saList);
+ sa != 0L;
+ sa = ISC_LIST_NEXT(sa,link)
+ )
+ {
+ nsa = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
+ if( nsa == 0L )
+ {
+ result = ISC_R_NOMEMORY;
+ break;
+ }
+ *nsa = *sa;
+ ISC_LINK_INIT( nsa, link );
+ ISC_LIST_APPEND( fwdr->addrs, nsa, link );
+ }
+
+ if( view != 0L )
+ dns_view_flushcache( view );
+
+ isc_task_endexclusive(mgr->task);
+
+ if( isc_log_getdebuglevel(ns_g_lctx) >= 1 )
+ dbus_mgr_log_forwarders("Added forwarder", dnsName, (SockAddrList*)&(fwdr->addrs));
+
+ }else
+ return result;
+
+ }
+ return (result);
+}
+
+static void
+dbus_mgr_get_name_list
+(
+ ns_dbus_mgr_t *mgr,
+ char *domains,
+ DNSNameList *nameList,
+ char *error_name,
+ char *error_message
+)
+{
+ char *name, *endName, *endp;
+ dns_fixedname_t *fixedname;
+ dns_name_t *dnsName;
+ isc_buffer_t buffer;
+ isc_result_t result;
+ uint32_t total_length;
+
+ total_length = strlen(domains);
+ endp = domains + total_length;
+
+ ISC_LIST_INIT( *nameList );
+
+ for( name = domains + strspn(domains," \t\n"),
+ endName = name + strcspn(name," \t\n");
+ (name < endp) && (endName <= endp);
+ name = endName + 1 + strspn(endName+1," \t\n"),
+ endName = name + strcspn(name," \t\n")
+ )
+ { /* name loop */
+ *endName = '\0';
+
+ isc_buffer_init( &buffer, name, endName - name );
+ isc_buffer_add(&buffer, endName - name);
+
+ fixedname = isc_mem_get( mgr->mctx, sizeof( dns_fixedname_t ));
+
+ dns_fixedname_init(fixedname);
+
+ dnsName = dns_fixedname_name(fixedname);
+
+ result= dns_name_fromtext
+ ( dnsName, &buffer, ( *(endp-1) != '.') ? dns_rootname : NULL, ISC_FALSE, NULL
+ );
+
+ if( result != ISC_R_SUCCESS )
+ {
+ sprintf(error_name, "com.redhat.named.InvalidArgument");
+ sprintf(error_message,"Invalid DNS name initial argument: %s", name);
+
+ isc_mem_put( mgr->mctx, fixedname, sizeof( dns_fixedname_t ) );
+
+ for( dnsName = ISC_LIST_HEAD( *nameList );
+ (dnsName != 0L);
+ dnsName = ISC_LIST_HEAD( *nameList )
+ )
+ {
+ if( ISC_LINK_LINKED(dnsName,link) )
+ ISC_LIST_DEQUEUE( *nameList, dnsName, link );
+ isc_mem_put( mgr->mctx, dnsName, sizeof( dns_fixedname_t ) );
+ }
+ ISC_LIST_INIT(*nameList);
+ return;
+ }
+ ISC_LINK_INIT(dnsName, link);
+ ISC_LIST_ENQUEUE( *nameList, dnsName, link );
+ }
+}
+
+static isc_result_t
+dbus_mgr_get_sa_list
+(
+ ns_dbus_mgr_t *mgr,
+ dbus_svc_MessageIterator iter,
+ SockAddrList *saList ,
+ uint8_t *fwdpolicy,
+ char *error_name,
+ char *error_message
+)
+{
+ DBUS_SVC dbus = mgr->dbus;
+ isc_sockaddr_t *nsSA=0L, *nsSA_Q=0L;
+ uint32_t argType = dbus_svc_message_next_arg_type( dbus, iter ),
+ length;
+ isc_result_t result;
+ in_port_t port;
+ char *ip;
+ uint8_t *iparray=0L;
+
+ ISC_LIST_INIT(*saList);
+
+ if( argType == TYPE_INVALID )
+ return ISC_R_SUCCESS; /* address list "removal" */
+
+ do
+ {
+ switch( argType )
+ {
+ case TYPE_UINT32:
+
+ nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
+ if( nsSA != 0L )
+ {
+ memset(nsSA,'\0', sizeof(isc_sockaddr_t));
+ nsSA_Q = nsSA;
+ dbus_svc_message_next_arg(dbus, iter, &(nsSA->type.sin.sin_addr.s_addr));
+ nsSA->type.sa.sa_family = AF_INET;
+ nsSA->length = sizeof( nsSA->type.sin );
+ }
+ break;
+
+ case TYPE_ARRAY:
+
+ argType = dbus_svc_message_element_type( dbus, iter );
+ if( argType == TYPE_BYTE )
+ {
+ iparray = 0L;
+ length = 0;
+
+ dbus_svc_message_get_elements(dbus, iter, &length, &iparray);
+
+ if( iparray != 0L )
+ {
+ if (length == sizeof( struct in_addr ))
+ {
+ nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
+ if( nsSA != 0L )
+ {
+ memset(nsSA,'\0', sizeof(isc_sockaddr_t));
+ nsSA_Q = nsSA;
+
+ memcpy(&(nsSA->type.sin.sin_addr), iparray, sizeof( struct in_addr ));
+ nsSA->type.sa.sa_family = AF_INET;
+ nsSA->length = sizeof( nsSA->type.sin );
+ }
+ }else
+ if (length == sizeof( struct in6_addr ))
+ {
+ nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
+ if( nsSA != 0L )
+ {
+ memset(nsSA,'\0', sizeof(isc_sockaddr_t));
+ nsSA_Q = nsSA;
+
+ memcpy(&(nsSA->type.sin6.sin6_addr), iparray, sizeof( struct in6_addr ));
+ nsSA->type.sa.sa_family = AF_INET6;
+ nsSA->length = sizeof( nsSA->type.sin6 );
+ }
+ }
+ }
+ }
+ break;
+
+ case TYPE_STRING:
+
+ ip = 0L;
+ dbus_svc_message_next_arg(dbus, iter, &(ip));
+ if( ip != 0L )
+ {
+ length = strlen(ip);
+ if( strspn(ip, "0123456789.") == length )
+ {
+ nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
+ if( nsSA != 0L)
+ {
+ memset(nsSA,'\0', sizeof(isc_sockaddr_t));
+ if( inet_pton( AF_INET, ip, &(nsSA->type.sin.sin_addr)) )
+ {
+ nsSA->type.sa.sa_family = AF_INET;
+ nsSA->length = sizeof(nsSA->type.sin);
+ nsSA_Q = nsSA;
+ }
+ }
+ }else
+ if( strspn(ip, "0123456789AaBbCcDdEeFf:.") == length)
+ {
+ nsSA = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
+ if( nsSA != 0L )
+ {
+ memset(nsSA,'\0', sizeof(isc_sockaddr_t));
+ if( inet_pton( AF_INET6, ip, &(nsSA->type.sin6.sin6_addr)) )
+ {
+ nsSA->type.sa.sa_family = AF_INET6;
+ nsSA->length = sizeof(nsSA->type.sin6);
+ nsSA_Q = nsSA;
+ }
+ }
+ }
+ }
+ break;
+
+ case TYPE_UINT16:
+
+ if( (nsSA == 0L) || (nsSA->type.sa.sa_family == AF_UNSPEC) )
+ break;
+ else
+ if( nsSA->type.sa.sa_family == AF_INET )
+ dbus_svc_message_next_arg(dbus, iter, &(nsSA->type.sin.sin_port));
+ else
+ if( nsSA->type.sa.sa_family == AF_INET6 )
+ dbus_svc_message_next_arg(dbus, iter, &(nsSA->type.sin6.sin6_port));
+ break;
+
+ case TYPE_BYTE:
+
+ dbus_svc_message_next_arg(dbus, iter, fwdpolicy);
+ if(*fwdpolicy > dns_fwdpolicy_only)
+ *fwdpolicy = dns_fwdpolicy_only;
+ break;
+
+ default:
+
+ if(nsSA != 0L)
+ nsSA->type.sa.sa_family = AF_UNSPEC;
+ sprintf(error_message,"Unhandled argument type: %c", argType);
+ break;
+ }
+
+ if( (nsSA != 0L)
+ &&(nsSA->type.sa.sa_family == AF_UNSPEC)
+ )
+ {
+ sprintf(error_name, "com.redhat.named.InvalidArgument");
+ if( error_message[0]=='\0')
+ {
+ if( nsSA == 0L )
+ sprintf(error_message,"Missing IP Address Name Server argument");
+ else
+ sprintf(error_message,"Bad IP Address Name Server argument");
+ }
+ if( nsSA != 0L )
+ isc_mem_put(mgr->mctx, nsSA, sizeof(isc_sockaddr_t));
+ nsSA = 0L;
+ for( nsSA = ISC_LIST_HEAD( *saList );
+ (nsSA != 0L);
+ nsSA = ISC_LIST_HEAD( *saList )
+ )
+ {
+ if(ISC_LINK_LINKED(nsSA, link))
+ ISC_LIST_DEQUEUE( *saList, nsSA, link );
+ isc_mem_put( mgr->mctx, nsSA, sizeof( isc_sockaddr_t ) );
+ }
+ ISC_LIST_INIT(*saList);
+ return ISC_R_FAILURE;
+ }
+
+ if( nsSA != 0L )
+ {
+ if( nsSA->type.sin.sin_port == 0 )
+ {
+ if( ns_g_port != 0L )
+ nsSA->type.sin.sin_port = htons(ns_g_port);
+ else
+ {
+ result = ns_config_getport(ns_g_config, &(port) );
+ if( result != ISC_R_SUCCESS )
+ port = 53;
+ nsSA->type.sin.sin_port = htons( port );
+ }
+ }
+
+ if( nsSA_Q != 0L )
+ {
+ ISC_LINK_INIT(nsSA,link);
+ ISC_LIST_ENQUEUE(*saList, nsSA, link);
+ nsSA_Q = 0L;
+ }
+ }
+
+ argType = dbus_svc_message_next_arg_type( dbus, iter );
+
+ } while ( argType != TYPE_INVALID );
+
+ return ISC_R_SUCCESS;
+}
+
+static void
+dbus_mgr_handle_set_forwarders
+(
+ ns_dbus_mgr_t *mgr,
+ DBUS_SVC dbus,
+ uint8_t reply_expected,
+ uint32_t serial,
+ const char *path,
+ const char *member,
+ const char *interface,
+ const char *sender,
+ dbus_svc_MessageHandle msg
+)
+{
+ dbus_svc_MessageIterator iter;
+ char error_name[1024]="", error_message[1024]="", *domains=0L;
+ uint32_t argType, new_serial;
+ DNSNameList nameList;
+ dns_name_t *dnsName;
+ SockAddrList saList;
+ isc_sockaddr_t *nsSA;
+ isc_result_t result;
+ uint8_t fwdpolicy = dns_fwdpolicy_only;
+
+ iter = dbus_svc_message_iterator_new( dbus, msg );
+
+ if( iter == 0L )
+ {
+ if( reply_expected )
+ {
+ sprintf(error_name, "com.redhat.named.InvalidArguments");
+ sprintf(error_message,"SetForwarders requires DNS name and nameservers arguments.");
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ }
+ return;
+ }
+
+ argType = dbus_svc_message_next_arg_type( dbus, iter );
+
+ if( argType != TYPE_STRING )
+ {
+ if( reply_expected )
+ {
+ sprintf(error_name, "com.redhat.named.InvalidArguments");
+ sprintf(error_message,"SetForwarders requires DNS name string initial argument.");
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ }
+ return;
+ }
+
+ dbus_svc_message_next_arg( dbus, iter, &domains );
+
+ if( ( domains == 0L ) || (*domains == '\0') )
+ {
+ if( reply_expected )
+ {
+ sprintf(error_name, "com.redhat.named.InvalidArguments");
+ sprintf(error_message,"SetForwarders requires DNS name string initial argument.");
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ }
+ return;
+ }
+
+ dbus_mgr_get_name_list( mgr, domains, &nameList, error_name, error_message );
+
+ if( error_name[0] != '\0' )
+ {
+ if( reply_expected )
+ {
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ }
+ return;
+ }
+
+ if( ISC_LIST_HEAD( nameList ) == 0L )
+ return;
+
+ result = dbus_mgr_get_sa_list( mgr, iter, &saList , &fwdpolicy, error_name, error_message );
+
+ if( result == ISC_R_SUCCESS )
+ {
+ result = dbus_mgr_set_forwarders( mgr, &nameList, &saList, fwdpolicy );
+
+ if( result != ISC_R_SUCCESS )
+ {
+ if( reply_expected )
+ {
+ sprintf(error_name, "com.redhat.named.Failure");
+ sprintf(error_message, isc_result_totext(result));
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ }
+ }else
+ if( reply_expected )
+ dbus_svc_send( dbus, RETURN, serial, &new_serial, sender, path, interface, member,
+ TYPE_UINT32, &result, TYPE_INVALID
+ );
+ }else
+ {
+ if( reply_expected )
+ {
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ }
+ }
+
+ for( dnsName = ISC_LIST_HEAD( nameList );
+ (dnsName != 0L) ;
+ dnsName = ISC_LIST_HEAD( nameList )
+ )
+ {
+ if( ISC_LINK_LINKED(dnsName,link) )
+ ISC_LIST_DEQUEUE( nameList, dnsName, link );
+ isc_mem_put( mgr->mctx, dnsName, sizeof( dns_fixedname_t ) );
+ }
+
+ for( nsSA = ISC_LIST_HEAD(saList);
+ (nsSA != 0L) ;
+ nsSA = ISC_LIST_HEAD(saList)
+ )
+ {
+ if( ISC_LINK_LINKED(nsSA,link) )
+ ISC_LIST_DEQUEUE( saList, nsSA, link );
+ isc_mem_put(mgr->mctx, nsSA, sizeof(isc_sockaddr_t));
+ }
+}
+
+static
+int dbus_mgr_msg_append_dns_name
+( DBUS_SVC dbus,
+ dbus_svc_MessageHandle msg,
+ dns_name_t *name
+)
+{
+ char nameBuf[ DNS_NAME_FORMATSIZE ]="", *nameP=&(nameBuf[0]);
+
+ dns_name_format(name, nameP, DNS_NAME_FORMATSIZE );
+
+ if( *nameP == '\0' )
+ return 0;
+
+ return dbus_svc_message_append_args( dbus, msg, TYPE_STRING, &nameP, TYPE_INVALID ) > 0;
+}
+
+typedef enum dbmoi_e
+{
+ OUTPUT_BINARY,
+ OUTPUT_TEXT
+} DBusMgrOutputInterface;
+
+static
+int dbus_mgr_msg_append_forwarders
+( DBUS_SVC dbus,
+ dbus_svc_MessageHandle msg,
+ dns_forwarders_t *fwdr,
+ DBusMgrOutputInterface outputType
+)
+{
+ isc_sockaddr_t *sa;
+ char policyBuf[16]="", *pbp[1]={&(policyBuf[0])}, addressBuf[64]="", *abp[1]={&(addressBuf[0])};
+ uint8_t *byteArray[1];
+
+ if( outputType == OUTPUT_BINARY )
+ {
+ if(!dbus_svc_message_append_args
+ ( dbus, msg,
+ TYPE_BYTE, &(fwdr->fwdpolicy),
+ TYPE_INVALID
+ )
+ ) return 0;
+ }else
+ if( outputType == OUTPUT_TEXT )
+ {
+ sprintf(policyBuf,"%s",
+ (fwdr->fwdpolicy == dns_fwdpolicy_none)
+ ? "none"
+ : (fwdr->fwdpolicy == dns_fwdpolicy_first)
+ ? "first"
+ : "only"
+ );
+ if(!dbus_svc_message_append_args
+ ( dbus, msg,
+ TYPE_STRING, pbp,
+ TYPE_INVALID
+ )
+ ) return 0;
+ }else
+ return 0;
+
+ for( sa = ISC_LIST_HEAD(fwdr->addrs);
+ sa != 0L;
+ sa = ISC_LIST_NEXT(sa, link)
+ )
+ {
+ if( outputType == OUTPUT_BINARY )
+ {
+ if( sa->type.sa.sa_family == AF_INET )
+ {
+ if(!dbus_svc_message_append_args
+ ( dbus, msg,
+ TYPE_UINT32, &(sa->type.sin.sin_addr.s_addr),
+ TYPE_INVALID
+ )
+ ) return 0;
+
+ if(!dbus_svc_message_append_args
+ ( dbus, msg,
+ TYPE_UINT16, &(sa->type.sin.sin_port),
+ TYPE_INVALID
+ )
+ ) return 0;
+ }else
+ if( sa->type.sa.sa_family == AF_INET6 )
+ {
+ byteArray[0] = (uint8_t*)&(sa->type.sin6.sin6_addr);
+ if(!dbus_svc_message_append_args
+ ( dbus, msg,
+ TYPE_ARRAY, TYPE_BYTE, &byteArray, sizeof(struct in6_addr),
+ TYPE_INVALID
+ )
+ ) return 0;
+
+ if(!dbus_svc_message_append_args
+ ( dbus, msg,
+ TYPE_UINT16, &(sa->type.sin6.sin6_port),
+ TYPE_INVALID
+ )
+ ) return 0;
+ }else
+ continue;
+ }else
+ if( outputType == OUTPUT_TEXT )
+ {
+ if( sa->type.sa.sa_family == AF_INET )
+ {
+ if( inet_ntop( AF_INET, &(sa->type.sin.sin_addr), addressBuf, sizeof(addressBuf)) == 0L )
+ continue;
+ if(!dbus_svc_message_append_args
+ ( dbus, msg,
+ TYPE_STRING, abp,
+ TYPE_INVALID
+ )
+ ) return 0;
+ sprintf(addressBuf, "%hu", ntohs( sa->type.sin.sin_port ));
+ if(!dbus_svc_message_append_args
+ ( dbus, msg,
+ TYPE_STRING, abp,
+ TYPE_INVALID
+ )
+ ) return 0;
+ }else
+ if( sa->type.sa.sa_family == AF_INET6 )
+ {
+ if( inet_ntop( AF_INET6, &(sa->type.sin6.sin6_addr), addressBuf, sizeof(addressBuf)) == 0L )
+ continue;
+ if(!dbus_svc_message_append_args
+ ( dbus, msg,
+ TYPE_STRING, abp,
+ TYPE_INVALID
+ )
+ ) return 0;
+ sprintf(addressBuf, "%hu", ntohs( sa->type.sin6.sin6_port ));
+ if(!dbus_svc_message_append_args
+ ( dbus, msg,
+ TYPE_STRING, abp,
+ TYPE_INVALID
+ )
+ ) return 0;
+ }else
+ continue;
+ }else
+ return 0;
+ }
+ return 1;
+}
+
+typedef struct dbm_m_s
+{
+ DBUS_SVC dbus;
+ dbus_svc_MessageHandle msg;
+ DBusMgrOutputInterface outputType;
+} DBusMgrMsg;
+
+static
+void forwarders_to_msg( dns_name_t *name, dns_forwarders_t *fwdr, void *mp )
+{
+ DBusMgrMsg *m = mp;
+
+ if( (fwdr == 0L) || (name == 0L) || (mp == 0L))
+ return;
+ dbus_mgr_msg_append_dns_name ( m->dbus, m->msg, name );
+ dbus_mgr_msg_append_forwarders( m->dbus, m->msg, fwdr, m->outputType );
+}
+
+static void
+dbus_mgr_handle_list_forwarders
+(
+ DBUS_SVC dbus,
+ uint8_t reply_expected,
+ uint32_t serial,
+ const char *path,
+ const char *member,
+ const char *interface,
+ const char *sender,
+ dbus_svc_MessageHandle msg
+)
+{
+ char error_name[1024], error_message[1024];
+ DBusMgrMsg m;
+ uint32_t new_serial;
+ dns_fwdtable_t *fwdtable = dbus_mgr_get_fwdtable();
+ DBusMgrOutputInterface outputType = OUTPUT_BINARY;
+ uint32_t length = strlen(interface);
+
+ if( !reply_expected )
+ return;
+
+ if( (length > 4) && (strcmp(interface + (length - 4), "text")==0))
+ outputType = OUTPUT_TEXT;
+
+ if( fwdtable == 0L )
+ {
+ sprintf(error_name,"com.redhat.dbus.Failure");
+ sprintf(error_message, "%s", isc_result_totext(ISC_R_NOPERM));
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ return;
+ }
+
+ msg = dbus_svc_new_message( dbus, RETURN, serial, sender, path, interface, member);
+
+ m.dbus = dbus;
+ m.msg = msg;
+ m.outputType = outputType;
+
+ if( msg == 0L )
+ {
+ sprintf(error_name,"com.redhat.dbus.OutOfMemory");
+ sprintf(error_message,"out of memory");
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ }
+
+ dns_fwdtable_foreach( fwdtable, forwarders_to_msg, &m );
+
+ dbus_svc_send_message( dbus, msg, &new_serial );
+}
+
+static void
+dbus_mgr_handle_get_forwarders
+(
+ DBUS_SVC dbus,
+ uint8_t reply_expected,
+ uint32_t serial,
+ const char *path,
+ const char *member,
+ const char *interface,
+ const char *sender,
+ dbus_svc_MessageHandle msg
+)
+{
+ char error_name[1024], error_message[1024], *domain=0L;
+ isc_result_t result;
+ dns_fixedname_t fixedname;
+ dns_name_t *dnsName;
+ isc_buffer_t buffer;
+ uint32_t length, new_serial;
+ dns_fwdtable_t *fwdtable;
+ dns_forwarders_t *fwdr=0L;
+ dns_name_t *foundname;
+ dns_fixedname_t fixedFoundName;
+ DBusMgrOutputInterface outputType = OUTPUT_BINARY;
+
+ if( !reply_expected )
+ return;
+
+ length = strlen(interface);
+
+ if( (length > 4) && (strcmp(interface + (length - 4), "text")==0))
+ outputType = OUTPUT_TEXT;
+
+ if( (!dbus_svc_get_args( dbus, msg, TYPE_STRING, &domain, TYPE_INVALID))
+ ||(domain == 0L)
+ ||(*domain == '\0')
+ )
+ {
+
+ sprintf(error_name,"com.redhat.dbus.InvalidArguments");
+ sprintf(error_message,"domain name argument expected");
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ return;
+ }
+
+ length = strlen( domain );
+
+ isc_buffer_init( &buffer, domain, length);
+
+ isc_buffer_add(&buffer, length);
+
+ dns_fixedname_init(&fixedname);
+
+ dnsName = dns_fixedname_name(&fixedname);
+
+ result = dns_name_fromtext
+ ( dnsName, &buffer, dns_rootname, ISC_FALSE, NULL
+ );
+
+ if( result != ISC_R_SUCCESS )
+ {
+ sprintf(error_name,"com.redhat.dbus.InvalidArguments");
+ sprintf(error_message,"invalid domain name argument: %s", domain);
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ return;
+ }
+
+ msg = dbus_svc_new_message( dbus, RETURN, serial, sender, path, interface, member);
+
+ if( msg == 0L )
+ {
+ sprintf(error_name,"com.redhat.dbus.OutOfMemory");
+ sprintf(error_message,"out of memory");
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ return;
+ }
+
+ fwdtable = dbus_mgr_get_fwdtable();
+
+ if( fwdtable == 0L )
+ {
+ sprintf(error_name,"com.redhat.dbus.Failure");
+ sprintf(error_message, "%s", isc_result_totext(ISC_R_NOPERM));
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ return;
+ }
+
+ dns_fixedname_init(&fixedFoundName);
+ foundname = dns_fixedname_name(&fixedFoundName);
+
+ if( ( dns_fwdtable_find_closest( fwdtable, dnsName, foundname, &fwdr ) == ISC_R_SUCCESS )
+ &&( fwdr != 0L )
+ )
+ {
+ if( (!dbus_mgr_msg_append_dns_name( dbus, msg, foundname ))
+ ||(!dbus_mgr_msg_append_forwarders( dbus, msg, fwdr, outputType ))
+ )
+ {
+ sprintf(error_name,"com.redhat.dbus.OutOfMemory");
+ sprintf(error_message,"out of memory");
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ return;
+ }
+
+ }else
+ {
+ result = ISC_R_NOTFOUND;
+ if( outputType == OUTPUT_BINARY )
+ {
+ dbus_svc_message_append_args( dbus, msg,
+ TYPE_UINT32, &(result),
+ TYPE_INVALID
+ ) ;
+ }else
+ {
+ sprintf(error_name,"com.redhat.dbus.NotFound");
+ sprintf(error_message,"Not Found");
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ return;
+ }
+ }
+ dbus_svc_send_message( dbus, msg, &new_serial );
+}
+
+static void
+dbus_mgr_check_dhcdbd_state( ns_dbus_mgr_t *mgr, dbus_svc_MessageHandle msg )
+{
+ DBUS_SVC dbus = mgr->dbus;
+ char *name_owned = 0L,
+ *old_owner = 0L,
+ *new_owner = 0L;
+
+ if( !dbus_svc_get_args( dbus, msg,
+ TYPE_STRING, &name_owned,
+ TYPE_STRING, &old_owner,
+ TYPE_STRING, &new_owner,
+ TYPE_INVALID
+ )
+ ) return;
+
+ dbus_mgr_log_dbg("NameOwnerChanged: %s %s %s ( %s )", name_owned, old_owner, new_owner, mgr->dhcdbd_name);
+
+ if( (name_owned == 0L) || (new_owner == 0L) || (old_owner == 0L) )
+ return;
+
+ if( strcmp( name_owned, "com.redhat.dhcp" ) == 0 )
+ {
+ if( *new_owner == '\0' )
+ {
+ isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name) + 1);
+ mgr->dhcdbd_name = 0L;
+ dbus_mgr_log_err("D-BUS dhcdbd subscription disabled.");
+ return;
+ }
+ if( (mgr->dhcdbd_name == 0L)
+ ||( strcmp( mgr->dhcdbd_name, new_owner) != 0 )
+ )
+ {
+ if( mgr->dhcdbd_name != 0L )
+ {
+ isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name)+1);
+ mgr->dhcdbd_name = 0L;
+ }
+ mgr->dhcdbd_name = isc_mem_get(mgr->mctx, strlen(new_owner) + 1);
+ if( mgr->dhcdbd_name == 0L )
+ return;
+ strcpy( mgr->dhcdbd_name, new_owner );
+ dbus_mgr_subscribe_to_dhcdbd( mgr );
+ }
+ }else
+ if( ( mgr->dhcdbd_name != 0L )
+ && ( strcmp(mgr->dhcdbd_name, name_owned) == 0L )
+ && ( *new_owner == '\0' )
+ )
+ {
+ isc_mem_put(mgr->mctx, mgr->dhcdbd_name, strlen(mgr->dhcdbd_name));
+ mgr->dhcdbd_name = 0L;
+ dbus_mgr_log_err("D-BUS dhcdbd subscription disabled.");
+ }
+}
+
+static int dbus_mgr_dhc_if_comparator( const void *p1, const void *p2 )
+{
+ return( strcmp( ((const DHC_IF*)p1)->if_name, ((const DHC_IF*)p2)->if_name) );
+}
+
+static
+dns_name_t *dbus_mgr_if_reverse_ip_name
+( ns_dbus_mgr_t *mgr,
+ struct in_addr ip_address,
+ struct in_addr subnet_mask
+)
+{
+ dns_name_t *dns_name =0L;
+ dns_fixedname_t *fixedname=0L;
+ char name [ DNS_NAME_FORMATSIZE ], *p;
+ uint32_t ip = (ntohl(ip_address.s_addr) & ntohl(subnet_mask.s_addr)), i;
+ isc_buffer_t buffer;
+ isc_result_t result;
+
+ if( (ip == 0) || (ip == 0xffffffff) )
+ return 0L;
+
+ for(i = 8, p = name; (i < 32); i += 8)
+ if( ip & ( 0xff << i ) )
+ p += sprintf(p, "%u.", (((ip & ( 0xff << i )) >> i ) & 0xff) );
+
+ if( p > name )
+ {
+ p += sprintf(p, "in-addr.arpa");
+ isc_buffer_init( &buffer, name, p - name );
+ isc_buffer_add(&buffer, p - name);
+
+ fixedname = isc_mem_get( mgr->mctx, sizeof( dns_fixedname_t ));
+
+ dns_fixedname_init(fixedname);
+
+ dns_name = dns_fixedname_name(fixedname);
+
+ result= dns_name_fromtext
+ ( dns_name, &buffer, dns_rootname, ISC_FALSE, NULL
+ );
+
+ ISC_LINK_INIT(dns_name, link);
+ if( result == ISC_R_SUCCESS )
+ return dns_name;
+ }
+ return 0L;
+}
+
+static void
+dbus_mgr_free_dhc( void *p )
+{
+ DHC_IF *d_if = p;
+ dns_name_t *dn;
+ isc_sockaddr_t *sa;
+
+ isc_mem_put( ns_g_mctx, d_if->if_name, strlen(d_if->if_name) + 1);
+ for( sa = ISC_LIST_HEAD( d_if->dns );
+ sa != NULL;
+ sa = ISC_LIST_HEAD( d_if->dns )
+ )
+ {
+ if( ISC_LINK_LINKED( sa, link ) )
+ ISC_LIST_UNLINK( d_if->dns, sa, link );
+ isc_mem_put(ns_g_mctx, sa, sizeof(isc_sockaddr_t));
+ }
+ for( dn = ISC_LIST_HEAD( d_if->dn );
+ dn != NULL;
+ dn = ISC_LIST_HEAD( d_if->dn )
+ )
+ {
+ if( ISC_LINK_LINKED( dn, link ) )
+ ISC_LIST_UNLINK( d_if->dn, dn, link );
+ isc_mem_put( ns_g_mctx, dn, sizeof( dns_fixedname_t ) );
+ }
+ isc_mem_put( ns_g_mctx, d_if, sizeof(DHC_IF));
+}
+
+static void
+dbus_mgr_handle_dhcdbd_message
+(
+ ns_dbus_mgr_t *mgr,
+ const char *path,
+ const char *member,
+ dbus_svc_MessageHandle msg
+)
+{
+ DBUS_SVC dbus = mgr->dbus;
+ DHC_IF *d_if, *const*d_ifpp, dif;
+ DHC_State dhc_state;
+ char *if_name, *opt_name, error_name[1024]="", error_message[1024]="";
+ uint8_t *value=0L;
+ uint32_t length;
+ isc_result_t result;
+ isc_sockaddr_t *sa = 0L;
+ dns_name_t *dn = 0L;
+ struct in_addr *ip;
+ in_port_t port;
+ char dnBuf[ DNS_NAME_FORMATSIZE ];
+ isc_buffer_t buffer;
+ DBusMgrInitialFwdr *ifwdr, *const*ifwdpp, ifwd;
+ ISC_LIST(DBusMgrInitialFwdr) ifwdrList;
+ DNSNameList nameList;
+ dbus_mgr_log_dbg("Got dhcdbd message: %s %s %p", path, member, msg );
+
+ if( ( if_name = strrchr(path,'/') ) == 0L )
+ {
+ dbus_mgr_log_err("bad path in dhcdbd message:", path);
+ return;
+ }
+
+ ++if_name;
+ dif.if_name = if_name;
+
+ if( ((d_ifpp=tfind( &dif, &(mgr->dhc_if), dbus_mgr_dhc_if_comparator)) == 0L)
+ ||((d_if = *d_ifpp) == 0L)
+ )
+ {
+ d_if = isc_mem_get( mgr->mctx, sizeof(DHC_IF));
+ if( d_if == 0L )
+ {
+ dbus_mgr_log_err("out of memory");
+ return;
+ }
+ memset(d_if, '\0', sizeof(DHC_IF));
+ if((d_if->if_name = isc_mem_get( mgr->mctx, strlen(if_name) + 1)) == 0L)
+ {
+ dbus_mgr_log_err("out of memory");
+ return;
+ }
+ strcpy(d_if->if_name, if_name);
+ d_if->dhc_state = DHC_INVALID;
+ d_if->previous_state = DHC_INVALID;
+ ISC_LIST_INIT( d_if->dn );
+ ISC_LIST_INIT( d_if->dns );
+ if( tsearch( d_if, &(mgr->dhc_if), dbus_mgr_dhc_if_comparator) == 0L )
+ {
+ dbus_mgr_log_err("out of memory");
+ return;
+ }
+ }
+
+ if( strcmp(member, "reason") == 0 )
+ {
+ if( (!dbus_svc_get_args( dbus, msg,
+ TYPE_STRING, &opt_name,
+ TYPE_ARRAY, TYPE_BYTE, &value, &length,
+ TYPE_INVALID
+ )
+ )
+ ||( value == 0L)
+ ||( length != sizeof(uint32_t))
+ ||( *((uint32_t*)value) > DHC_END_OPTIONS)
+ )
+ {
+ dbus_mgr_log_err("Invalid DHC reason value received from dhcdbd");
+ return;
+ }
+ dhc_state = (DHC_State) *((uint32_t*)value);
+ dbus_mgr_log_dbg("reason: %d %d %d", dhc_state, d_if->dhc_state, d_if->previous_state);
+ switch( dhc_state )
+ {
+
+ case DHC_END_OPTIONS:
+ switch( d_if->dhc_state )
+ {
+ case DHC_END_OPTIONS:
+ break;
+
+ case DHC_RENEW:
+ case DHC_REBIND:
+ if( ( d_if->previous_state != DHC_INVALID )
+ &&( d_if->previous_state != DHC_RELEASE )
+ ) break;
+ /* DHC_RENEW means the same lease parameters were obtained.
+ * Only do configuration if we started up with existing dhclient
+ * which has now renewed - else we are already configured correctly.
+ */
+ dbus_mgr_log_err("D-BUS: existing dhclient for interface %s RENEWed lease", if_name);
+
+ case DHC_REBOOT:
+ case DHC_BOUND:
+ d_if->previous_state = d_if->dhc_state;
+ d_if->dhc_state = DHC_BOUND;
+ if( (dn = dbus_mgr_if_reverse_ip_name(mgr, d_if->ip, d_if->subnet_mask )) != 0L )
+ {
+ ISC_LIST_APPEND(d_if->dn, dn, link );
+ }
+ if( ( ISC_LIST_HEAD( d_if->dn ) != NULL )
+ &&( ISC_LIST_HEAD( d_if->dns ) != NULL )
+ )
+ {
+ dbus_mgr_log_err("D-BUS: dhclient for interface %s acquired new lease - creating forwarders.",
+ if_name
+ );
+ result = dbus_mgr_set_forwarders( mgr, &(d_if->dn), &(d_if->dns), dns_fwdpolicy_only );
+ if( result != ISC_R_SUCCESS )
+ {
+ dbus_mgr_log_err("D-BUS: forwarder configuration failed: %s", isc_result_totext(result));
+ }
+ }
+ break;
+
+ case DHC_STOP:
+ case DHC_TIMEOUT:
+ case DHC_FAIL:
+ case DHC_EXPIRE:
+ case DHC_RELEASE:
+ d_if->previous_state = d_if->dhc_state;
+ d_if->dhc_state = DHC_RELEASE;
+ if( ISC_LIST_HEAD( d_if->dn ) != NULL )
+ {
+ dbus_mgr_log_err("D-BUS: dhclient for interface %s released lease - removing forwarders.",
+ if_name);
+ for( sa = ISC_LIST_HEAD( d_if->dns );
+ sa != 0L;
+ sa = ISC_LIST_HEAD( d_if->dns )
+ )
+ {
+ if( ISC_LINK_LINKED( sa, link ) )
+ ISC_LIST_UNLINK( d_if->dns, sa, link );
+ isc_mem_put( mgr->mctx, sa, sizeof(isc_sockaddr_t));
+ }
+ ISC_LIST_INIT( d_if->dns );
+ ISC_LIST_INIT( ifwdrList );
+
+ for( dn = ISC_LIST_HEAD( d_if->dn );
+ dn != 0L;
+ dn = ISC_LIST_NEXT( dn, link )
+ )
+ {
+ dns_name_init( &(ifwd.dn), NULL );
+ isc_buffer_init( &buffer, dnBuf, DNS_NAME_FORMATSIZE);
+ dns_name_setbuffer( &(ifwd.dn), &buffer);
+ dns_name_copy(dn, &(ifwd.dn), NULL);
+ if( ((ifwdpp = tfind(&ifwd, &(mgr->ifwdt), dbus_mgr_ifwdr_comparator)) != 0L )
+ &&((ifwdr = *ifwdpp) != 0L)
+ )
+ {
+ ISC_LIST_APPEND( ifwdrList, ifwdr, link );
+ }
+ }
+
+ result = dbus_mgr_set_forwarders( mgr, &(d_if->dn), &(d_if->dns), dns_fwdpolicy_none );
+ if( result != ISC_R_SUCCESS )
+ {
+ dbus_mgr_log_err("D-BUS: removal of forwarders failed: %s", isc_result_totext(result));
+ }
+
+ for( dn = ISC_LIST_HEAD( d_if->dn );
+ dn != 0L;
+ dn = ISC_LIST_HEAD( d_if->dn )
+ )
+ {
+ if( ISC_LINK_LINKED( dn, link ) )
+ ISC_LIST_UNLINK( d_if->dn, dn, link );
+ isc_mem_put( mgr->mctx, dn, sizeof( dns_fixedname_t ) );
+ }
+ ISC_LIST_INIT( d_if->dn );
+
+ for( ifwdr = ISC_LIST_HEAD( ifwdrList );
+ ifwdr != 0L;
+ ifwdr = ISC_LIST_HEAD( ifwdrList )
+ )
+ {
+ if( ISC_LINK_LINKED( ifwdr, link ) )
+ ISC_LIST_UNLINK( ifwdrList, ifwdr, link );
+ ISC_LINK_INIT(ifwdr, link);
+ ISC_LIST_INIT(nameList);
+ ISC_LINK_INIT(&(ifwdr->dn), link);
+ ISC_LIST_APPEND( nameList, &(ifwdr->dn), link );
+ result = dbus_mgr_set_forwarders( mgr, &nameList,
+ &(ifwdr->sa),
+ ifwdr->fwdpolicy
+ );
+ if( result != ISC_R_SUCCESS )
+ {
+ dbus_mgr_log_err("D-BUS: restore of forwarders failed: %s", isc_result_totext(result));
+ }
+ }
+ }
+
+ case DHC_ABEND:
+ case DHC_END:
+ case DHC_NBI:
+ case DHC_PREINIT:
+ case DHC_MEDIUM:
+ case DHC_START:
+ case DHC_INVALID:
+ default:
+ break;
+ }
+ break;
+
+ case DHC_BOUND:
+ case DHC_REBOOT:
+ case DHC_REBIND:
+ case DHC_RENEW:
+ case DHC_STOP:
+ case DHC_TIMEOUT:
+ case DHC_FAIL:
+ case DHC_EXPIRE:
+ case DHC_RELEASE:
+ d_if->previous_state = d_if->dhc_state;
+ d_if->dhc_state = dhc_state;
+
+ case DHC_ABEND:
+ case DHC_END:
+ case DHC_NBI:
+ case DHC_PREINIT:
+ case DHC_MEDIUM:
+ case DHC_START:
+ case DHC_INVALID:
+ default:
+ break;
+ }
+ }else
+ if( strcmp( member, "domain_name" ) == 0 )
+ {
+ if( (!dbus_svc_get_args( dbus, msg,
+ TYPE_STRING, &opt_name,
+ TYPE_ARRAY, TYPE_BYTE, &value, &length,
+ TYPE_INVALID
+ )
+ )
+ ||( value == 0L)
+ ||( length == 0)
+ )
+ {
+ dbus_mgr_log_err("Invalid domain_name value received from dhcdbd");
+ return;
+ }
+ dbus_mgr_log_dbg("domain-name %s", (char*)value);
+ dbus_mgr_get_name_list( mgr, (char*)value, &(d_if->dn), error_name, error_message );
+ if( ( error_message[0] != '\0' ) || (ISC_LIST_HEAD(d_if->dn) == 0L ))
+ {
+ dbus_mgr_log_err("Bad domain_name value: %s", error_message );
+ }
+ }else
+ if( strcmp( member, "domain_name_servers") == 0 )
+ {
+ if( (!dbus_svc_get_args( dbus, msg,
+ TYPE_STRING, &opt_name,
+ TYPE_ARRAY, TYPE_BYTE, &value, &length,
+ TYPE_INVALID
+ )
+ )
+ ||( value == 0L)
+ ||( length == 0)
+ )
+ {
+ dbus_mgr_log_err("Invalid domain_name_servers value received from dhcdbd");
+ return;
+ }
+ for(ip = (struct in_addr*) value; ip < ((struct in_addr*)(value + length)); ip++)
+ {
+ dbus_mgr_log_dbg("domain-name-servers: %s", inet_ntop(AF_INET, value, error_name, 16));
+ sa = isc_mem_get(mgr->mctx, sizeof(isc_sockaddr_t));
+ memset(sa, '\0', sizeof(isc_sockaddr_t));
+ sa->type.sin.sin_addr = *ip;
+ sa->type.sa.sa_family = AF_INET;
+ sa->length = sizeof(sa->type.sin);
+ result = ns_config_getport(ns_g_config, &(port) );
+ if( result != ISC_R_SUCCESS )
+ port = 53;
+ sa->type.sin.sin_port = htons( port );
+ ISC_LIST_APPEND(d_if->dns, sa, link);
+ }
+ }else
+ if( strcmp(member, "ip_address") == 0)
+ {
+ if( (!dbus_svc_get_args( dbus, msg,
+ TYPE_STRING, &opt_name,
+ TYPE_ARRAY, TYPE_BYTE, &value, &length,
+ TYPE_INVALID
+ )
+ )
+ ||( value == 0L)
+ ||( length != sizeof(struct in_addr) )
+ )
+ {
+ dbus_mgr_log_err("Invalid ip_address value received from dhcdbd");
+ return;
+ }
+ dbus_mgr_log_dbg("ip-address: %s", inet_ntop(AF_INET, value, error_name, 16));
+ d_if->ip = *((struct in_addr*)value);
+
+ }else
+ if( strcmp(member, "subnet_mask") == 0 )
+ {
+ if( (!dbus_svc_get_args( dbus, msg,
+ TYPE_STRING, &opt_name,
+ TYPE_ARRAY, TYPE_BYTE, &value, &length,
+ TYPE_INVALID
+ )
+ )
+ ||( value == 0L)
+ ||( length != sizeof(struct in_addr) )
+ )
+ {
+ dbus_mgr_log_err("Invalid subnet_mask value received from dhcdbd");
+ return;
+ }
+ dbus_mgr_log_dbg("subnet-mask: %s", inet_ntop(AF_INET, value, error_name, 16));
+ d_if->subnet_mask = *((struct in_addr*)value);
+ }
+}
+
+static
+dbus_svc_HandlerResult
+dbus_mgr_message_handler
+(
+ DBusMsgHandlerArgs
+)
+{
+ char error_name[1024], error_message[1024];
+ ns_dbus_mgr_t *mgr = object;
+ uint32_t new_serial;
+
+ if_suffix = prefix = suffix = prefixObject = 0L;
+
+ dbus_mgr_log_dbg("D-BUS message: %u %u %u %s %s %s %s %s %s",
+ type, reply_expected, serial, destination, path, member, interface, sender, signature
+ );
+
+ if ( ( type == SIGNAL )
+ &&( strcmp(path,"/org/freedesktop/DBus/Local") == 0 )
+ )
+ {
+ if( strcmp(member,"Disconnected") == 0 )
+ dbus_mgr_dbus_shutdown_handler( mgr );
+ }else
+ if( ( type == SIGNAL )
+ &&( strcmp(path,"/org/freedesktop/DBus") == 0 )
+ &&(strcmp(member,"NameOwnerChanged") == 0)
+ &&(strcmp(signature, "sss") == 0)
+ )
+ {
+ dbus_mgr_check_dhcdbd_state( mgr, msg );
+ }else
+ if( ( type == SIGNAL )
+ &&( (sender != 0L) && (mgr->dhcdbd_name != 0L) && (strcmp(sender,mgr->dhcdbd_name) == 0))
+ &&( strcmp(interface,"com.redhat.dhcp.subscribe.binary") == 0 )
+ )
+ {
+ dbus_mgr_handle_dhcdbd_message( mgr, path, member, msg );
+ }else
+ if( (type == CALL)
+ &&( strcmp(destination, DBUSMGR_DESTINATION)==0)
+ &&( strcmp(path, DBUSMGR_OBJECT_PATH)==0)
+ )
+ {
+ if( strcmp(member, "SetForwarders") == 0 )
+ dbus_mgr_handle_set_forwarders
+ ( mgr, dbus, reply_expected, serial, path, member, interface, sender, msg );
+ else
+ if( strcmp(member, "GetForwarders") == 0 )
+ {
+ if( *signature != '\0' )
+ dbus_mgr_handle_get_forwarders
+ ( dbus, reply_expected, serial, path, member, interface, sender, msg );
+ else
+ dbus_mgr_handle_list_forwarders
+ ( dbus, reply_expected, serial, path, member, interface, sender, msg );
+ }else
+ if( reply_expected )
+ {
+ sprintf(error_name, "InvalidOperation");
+ sprintf(error_message, "Unrecognized path / interface / member");
+ dbus_svc_send( dbus, ERROR, serial, &new_serial, sender, path, interface, member,
+ TYPE_STRING, error_name, TYPE_STRING, error_message, TYPE_INVALID
+ );
+ }
+ }
+ return HANDLED;
+}
+
+static void
+dbus_mgr_read_watch_activated(isc_task_t *t, isc_event_t *ev)
+{
+ DBusMgrSocket *sfd = (DBusMgrSocket*)(ev->ev_arg);
+ t = t;
+ isc_mem_put(sfd->mgr->mctx, ev, ev->ev_size);
+ dbus_mgr_log_dbg("watch %d READ",sfd->fd);
+ isc_socket_fd_handle_reads( sfd->sock, sfd->ser );
+ dbus_svc_handle_watch( sfd->mgr->dbus, sfd->fd, WATCH_ENABLE | WATCH_READ );
+}
+
+static void
+dbus_mgr_write_watch_activated(isc_task_t *t, isc_event_t *ev)
+{
+ DBusMgrSocket *sfd = (DBusMgrSocket*)(ev->ev_arg);
+ t = t;
+ isc_mem_put(sfd->mgr->mctx, ev, ev->ev_size);
+ dbus_mgr_log_dbg("watch %d WRITE",sfd->fd);
+ isc_socket_fd_handle_writes( sfd->sock, sfd->ser );
+ dbus_svc_handle_watch( sfd->mgr->dbus, sfd->fd, WATCH_ENABLE | WATCH_WRITE );
+}
+
+static void
+dbus_mgr_watches_selected(isc_task_t *t, isc_event_t *ev)
+{
+ ns_dbus_mgr_t *mgr = (ns_dbus_mgr_t*)(ev->ev_arg);
+ t = t;
+ isc_mem_put(mgr->mctx, ev, ev->ev_size);
+ if( ( mgr->dbus == 0L ) || (mgr->sockets == 0L))
+ {
+ return;
+ }
+ dbus_mgr_log_dbg("watches selected");
+ dbus_svc_dispatch( mgr->dbus );
+ dbus_mgr_log_dbg("dispatch complete");
+}
+
+static int dbus_mgr_socket_comparator( const void *p1, const void *p2 )
+{
+ return( ( ((const DBusMgrSocket*)p1)->fd
+ == ((const DBusMgrSocket*)p2)->fd
+ ) ? 0
+ : ( ((const DBusMgrSocket*)p1)->fd
+ > ((const DBusMgrSocket*)p2)->fd
+ ) ? 1
+ : -1
+ );
+}
+
+static void
+dbus_mgr_watch_handler( int fd, dbus_svc_WatchFlags flags, void *mgrp )
+{
+ ns_dbus_mgr_t *mgr = mgrp;
+ DBusMgrSocket sockFd, *sfd=0L, *const*spp=0L;
+ isc_result_t result=ISC_R_SUCCESS;
+ isc_socketevent_t *sev;
+ isc_event_t *pev[1];
+
+ if(mgr == 0L)
+ return;
+
+ if( (flags & 7) == WATCH_ERROR )
+ return;
+
+ sockFd.fd = fd;
+
+ dbus_mgr_log_dbg("watch handler: fd %d %d", fd, flags);
+
+ if( ((spp = tfind( &sockFd, &(mgr->sockets), dbus_mgr_socket_comparator) ) == 0L )
+ ||((sfd = *spp) == 0L )
+ )
+ {
+ if( ( flags & WATCH_ENABLE ) == 0 )
+ return;
+
+ sfd = isc_mem_get(mgr->mctx, sizeof(DBusMgrSocket));
+ if( sfd == 0L )
+ {
+ dbus_mgr_log_err("dbus_mgr: out of memory" );
+ return;
+ }
+ sfd->fd = fd;
+ sfd->mgr = mgr;
+ sfd->ser = sfd->sew = sfd->sel = 0L;
+
+ if( tsearch(sfd, &(mgr->sockets), dbus_mgr_socket_comparator) == 0L )
+ {
+ dbus_mgr_log_err("dbus_mgr: out of memory" );
+ isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
+ return;
+ }
+ sfd->sock = 0L;
+ result = isc_socket_create( mgr->socketmgr, fd, isc_sockettype_fd, &(sfd->sock) );
+ if( result != ISC_R_SUCCESS )
+ {
+ dbus_mgr_log_err("dbus_mgr: isc_socket_create failed: %s",
+ isc_result_totext(result)
+ );
+ tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator);
+ isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
+ return;
+ }
+ }
+
+ if( (flags & WATCH_ENABLE) == WATCH_ENABLE )
+ {
+ if( (flags & WATCH_READ) == WATCH_READ )
+ {
+ if( sfd->ser == 0L )
+ {
+ sfd->ser = (isc_socketevent_t *)
+ isc_event_allocate
+ (
+ mgr->mctx, mgr->task,
+ ISC_SOCKEVENT_READ_READY,
+ dbus_mgr_read_watch_activated,
+ sfd,
+ sizeof(isc_socketevent_t)
+ );
+
+ if( sfd->ser == 0L )
+ {
+ dbus_mgr_log_err("dbus_mgr: out of memory" );
+ tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator);
+ isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
+ return;
+ }
+
+ sev = isc_socket_fd_handle_reads(sfd->sock, sfd->ser );
+
+ }else
+ {
+ sev = isc_socket_fd_handle_reads(sfd->sock, sfd->ser );
+ }
+ }
+ if( (flags & WATCH_WRITE) == WATCH_WRITE )
+ {
+ if( sfd->sew == 0L )
+ {
+ sfd->sew = (isc_socketevent_t *)
+ isc_event_allocate
+ (
+ mgr->mctx, mgr->task,
+ ISC_SOCKEVENT_WRITE_READY,
+ dbus_mgr_write_watch_activated,
+ sfd,
+ sizeof(isc_socketevent_t)
+ );
+ if( sfd->sew == 0L )
+ {
+ dbus_mgr_log_err("dbus_mgr: out of memory" );
+ tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator);
+ isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
+ return;
+ }
+
+ sev = isc_socket_fd_handle_writes(sfd->sock, sfd->sew );
+
+ }else
+ {
+ sev = isc_socket_fd_handle_writes(sfd->sock, sfd->sew );
+ }
+ }
+ if( (sfd->ser != 0L) || (sfd->sew != 0L) )
+ {
+ if( sfd->sel == 0L )
+ {
+ sfd->sel = (isc_socketevent_t *)
+ isc_event_allocate
+ (
+ mgr->mctx, mgr->task,
+ ISC_SOCKEVENT_SELECTED,
+ dbus_mgr_watches_selected,
+ mgr,
+ sizeof(isc_socketevent_t)
+ );
+ if( sfd->sel == 0L )
+ {
+ dbus_mgr_log_err("dbus_mgr: out of memory" );
+ tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator);
+ isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
+ return;
+ }
+
+ sev = isc_socket_fd_handle_selected(sfd->sock, sfd->sel );
+
+ }else
+ {
+ sev = isc_socket_fd_handle_selected(sfd->sock, sfd->sel);
+ }
+ }
+ }else
+ {
+ dbus_mgr_log_dbg("watch %d disabled",fd);
+ if(flags & WATCH_READ)
+ {
+ sev = isc_socket_fd_handle_reads( sfd->sock, 0L );
+ if( sev != 0L )
+ {
+ pev[0]=(isc_event_t*)sev;
+ isc_event_free(pev);
+ }
+ sfd->ser = 0L;
+ }
+
+ if( flags & WATCH_WRITE )
+ {
+ sev = isc_socket_fd_handle_writes( sfd->sock, 0L );
+ if( sev != 0L )
+ {
+ pev[0]=(isc_event_t*)sev;
+ isc_event_free(pev);
+ }
+ sfd->sew = 0L;
+ }
+
+ if( (sfd->ser == 0L) && (sfd->sew == 0L) )
+ {
+ sev = isc_socket_fd_handle_selected( sfd->sock, 0L );
+ if( sev != 0L )
+ {
+ pev[0]=(isc_event_t*)sev;
+ isc_event_free(pev);
+ }
+ sfd->sel = 0L;
+
+ tdelete(sfd, &(mgr->sockets), dbus_mgr_socket_comparator);
+
+ isc_mem_put(mgr->mctx, sfd, sizeof(DBusMgrSocket));
+ }
+ }
+}
+
+static
+void dbus_mgr_close_socket( const void *p, const VISIT which, const int level)
+{
+ DBusMgrSocket *const*spp=p, *sfd;
+ isc_event_t *ev ;
+ int i = level ? 0 :1;
+ i &= i;
+
+ if( (spp==0L) || ((sfd = *spp)==0L)
+ ||((which != leaf) && (which != postorder))
+ ) return;
+
+ if( sfd->ser != 0L )
+ {
+ ev = (isc_event_t *)isc_socket_fd_handle_reads(sfd->sock, 0);
+ if( ev != 0L )
+ isc_event_free((isc_event_t **)&ev);
+ sfd->ser = 0L;
+ }
+
+ if( sfd->sew != 0L )
+ {
+ ev = (isc_event_t *)isc_socket_fd_handle_writes(sfd->sock, 0);
+ if( ev != 0L )
+ isc_event_free((isc_event_t **)&ev);
+ sfd->sew = 0L;
+ }
+
+ if( sfd->sel != 0L )
+ {
+ ev = (isc_event_t *)isc_socket_fd_handle_selected(sfd->sock, 0);
+ if( ev != 0L )
+ isc_event_free((isc_event_t **)&ev);
+ sfd->sel = 0L;
+ dbus_mgr_log_dbg("CLOSED socket %d", sfd->fd);
+ }
+}
+
+static
+void dbus_mgr_destroy_socket( void *p )
+{
+ DBusMgrSocket *sfd = p;
+
+ isc_mem_put( sfd->mgr->mctx, sfd, sizeof(DBusMgrSocket) );
+}
diff --git a/contrib/dbus/dbus_mgr.h b/contrib/dbus/dbus_mgr.h
new file mode 100644
index 0000000..78be0d0
--- /dev/null
+++ b/contrib/dbus/dbus_mgr.h
@@ -0,0 +1,37 @@
+/* dbus_mgr.h
+ *
+ * named module to provide dynamic forwarding zones in
+ * response to D-BUS dhcp events
+ *
+ * Copyright(C) Jason Vas Dias, Red Hat Inc., 2005
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at
+ * http://www.fsf.org/licensing/licenses/gpl.txt
+ * and included in this software distribution as the "LICENSE" file.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+extern isc_result_t
+dbus_mgr_create
+( isc_mem_t *mctx,
+ isc_taskmgr_t *taskmgr,
+ isc_socketmgr_t *socketmgr,
+ isc_timermgr_t *timermgr,
+ ns_dbus_mgr_t **dbus_mgr
+);
+
+extern void
+dbus_mgr_shutdown
+( ns_dbus_mgr_t *dus_mgr_t
+);
+
+
+
+
+
diff --git a/contrib/dbus/dbus_service.c b/contrib/dbus/dbus_service.c
new file mode 100644
index 0000000..47d55d5
--- /dev/null
+++ b/contrib/dbus/dbus_service.c
@@ -0,0 +1,1161 @@
+/* dbus_service.c
+ *
+ * D-BUS Service Utilities
+ *
+ * Provides MINIMAL utilities for construction of D-BUS "Services".
+ *
+ * Copyright(C) Jason Vas Dias, Red Hat Inc., 2005
+ * Modified by Adam Tkac, Red Hat Inc., 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at
+ * http://www.fsf.org/licensing/licenses/gpl.txt
+ * and included in this software distribution as the "LICENSE" file.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <linux/limits.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <signal.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <string.h>
+extern size_t strnlen(const char *s, size_t maxlen);
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <search.h>
+#include <getopt.h>
+typedef void (*__free_fn_t) (void *__nodep);
+extern void tdestroy (void *__root, __free_fn_t __freefct);
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <errno.h>
+#define DBUS_API_SUBJECT_TO_CHANGE "Very Annoying and Silly!"
+#include <dbus/dbus.h>
+
+#include <named/dbus_service.h>
+#include <isc/result.h>
+
+typedef struct dbcs_s
+{
+ DBusConnection *connection;
+ DBusDispatchStatus dispatchStatus;
+ uint32_t status;
+ dbus_svc_WatchHandler wh;
+ void * wh_arg;
+ const char * unique_name;
+ dbus_svc_MessageHandler mh;
+ void * def_mh_obj;
+ dbus_svc_MessageHandler mf;
+ void * def_mf_obj;
+ dbus_svc_ShutdownHandler sh;
+ void * sh_obj;
+ dbus_svc_ErrorHandler eh;
+ dbus_svc_ErrorHandler dh;
+ /*{ glibc b-trees: */
+ void * roots;
+ void * timeouts;
+ void * watches;
+ void * filters;
+ /*}*/
+ int n;
+ fd_set r_fds;
+ fd_set s_r_fds;
+ fd_set w_fds;
+ fd_set s_w_fds;
+ fd_set e_fds;
+ fd_set s_e_fds;
+ DBusMessage *currentMessage;
+ int rejectMessage;
+} DBusConnectionState;
+
+typedef struct root_s
+{
+ char *path;
+ char *if_prefix;
+ DBUS_SVC cs;
+ dbus_svc_MessageHandler mh;
+ void *object;
+ void *tree;
+} Root;
+
+typedef struct mhn_s
+{
+ char *path;
+ dbus_svc_MessageHandler mh;
+ void *object;
+} MessageHandlerNode;
+
+typedef struct mfn_s
+{
+ DBusConnectionState *cs;
+ dbus_svc_MessageHandler mf;
+ void *obj;
+ int n_matches;
+ char **matches;
+} MessageFilterNode;
+
+typedef struct dbto_s
+{
+ DBusTimeout *to;
+ DBusConnectionState *cs;
+ struct timeval tv;
+} DBusConnectionTimeout;
+
+static void no_free( void *p){ p=0; }
+
+static int ptr_key_comparator( const void *p1, const void *p2 )
+{
+ return
+ ( (p1 == p2)
+ ? 0
+ :( (p1 > p2)
+ ? 1
+ : -1
+ )
+ );
+}
+
+static DBusHandlerResult
+default_message_filter
+( DBusConnection *connection,
+ DBusMessage *message,
+ void *p
+)
+{
+ DBusConnectionState *cs = p;
+ uint32_t type =dbus_message_get_type( message ),
+ serial =dbus_message_get_serial( message );
+ uint8_t reply =dbus_message_get_no_reply( message )==0;
+ const char
+ *path = dbus_message_get_path( message ),
+ *dest = dbus_message_get_destination( message ),
+ *member = dbus_message_get_member( message ),
+ *interface=dbus_message_get_interface( message ),
+ *sender =dbus_message_get_sender( message ),
+ *signature=dbus_message_get_signature( message );
+ connection = connection;
+ if(cs->mf)
+ return
+ (*(cs->mf))( cs, type, reply, serial, dest, path, member, interface, 0L,
+ sender, signature, message, 0L, 0L, 0L, cs->def_mf_obj
+ ) ;
+ return HANDLED;
+}
+
+uint8_t
+dbus_svc_add_filter
+( DBusConnectionState *cs, dbus_svc_MessageHandler mh, void *obj, int n_matches, ... )
+{
+ DBusError error;
+ va_list va;
+ char *m;
+
+ va_start(va, n_matches );
+
+ cs->mf = mh;
+ cs->def_mf_obj = obj;
+
+ if ( ! dbus_connection_add_filter (cs->connection, default_message_filter, cs, NULL))
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_add_filter: dbus_connection_add_filter failed");
+ va_end(va);
+ return( 0 );
+ }
+
+ if( n_matches )
+ {
+ memset(&error,'\0',sizeof(DBusError));
+ dbus_error_init(&error);
+ while( n_matches-- )
+ {
+ m = va_arg(va, char* ) ;
+
+ dbus_bus_add_match(cs->connection, m, &error);
+
+ if( dbus_error_is_set(&error))
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_add_filter: dbus_bus_add_match failed for %s: %s %s",
+ m, error.name, error.message
+ );
+ va_end(va);
+ return(0);
+ }
+ }
+ }
+ va_end(va);
+ return( 1 );
+}
+
+
+uint8_t
+dbus_svc_get_args_va(DBusConnectionState *cs, DBusMessage* msg, dbus_svc_DataType firstType, va_list va)
+{
+ DBusError error;
+ memset(&error,'\0',sizeof(DBusError));
+ dbus_error_init(&error);
+ if( (!dbus_message_get_args_valist(msg, &error, firstType, va)) || dbus_error_is_set(&error) )
+ {
+ if( dbus_error_is_set(&error) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_get_args failed: %s %s",error.name, error.message);
+ dbus_error_free(&error);
+ }else
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_get_args failed: dbus_message_get_args_valist failed");
+ return( 0 );
+ }
+ return( 1 );
+}
+
+uint8_t
+dbus_svc_get_args(DBusConnectionState *cs, DBusMessage* msg, dbus_svc_DataType firstType, ...)
+{
+ va_list va;
+ uint8_t r;
+ va_start(va, firstType);
+ r = dbus_svc_get_args_va( cs, msg, firstType, va);
+ va_end(va);
+ return r;
+}
+
+uint8_t
+dbus_svc_send_va
+( DBusConnectionState *cs,
+ dbus_svc_MessageType type,
+ int32_t reply_serial,
+ uint32_t *new_serial,
+ const char *destination,
+ const char *path,
+ const char *interface,
+ const char *member,
+ dbus_svc_DataType firstType,
+ va_list va
+)
+{
+ DBusMessageIter iter;
+ char *e;
+ DBusMessage *msg =
+ dbus_svc_new_message
+ ( cs,
+ type,
+ reply_serial,
+ destination,
+ path,
+ interface,
+ member
+ );
+
+ if(msg == 0L)
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_svc_new_message failed");
+ return 0;
+ }
+
+ if( type != DBUS_MESSAGE_TYPE_ERROR )
+ {
+ if( !dbus_message_append_args_valist( msg, firstType, va ) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_append_args_valist failed");
+ return 0;
+ }
+ }else
+ {
+ if( firstType == DBUS_TYPE_STRING )
+ {
+ e = 0L;
+ e = va_arg( va, char* );
+ if( (e == 0L) || !dbus_message_set_error_name( msg, e ) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_set_error_name failed");
+ return 0;
+ }
+ firstType = va_arg(va, int);
+ if( firstType == DBUS_TYPE_STRING )
+ {
+ e = 0L;
+ e = va_arg( va, char* );
+ if( e == 0L )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: NULL error message");
+ return 0;
+ }
+ dbus_message_iter_init_append (msg, &iter);
+ if( !dbus_message_iter_append_basic
+ (&iter, DBUS_TYPE_STRING, &e)
+ )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_iter_append_basic failed");
+ return 0;
+ }
+ }
+ }else
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: unhandled type for error name: %c", firstType);
+ return 0;
+ }
+ }
+
+ if( !dbus_connection_send(cs->connection, msg, new_serial) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_send failed");
+ return 0;
+ }
+ if( cs->dh != 0L ) (*(cs->dh))("Sending message");
+ dbus_connection_flush(cs->connection);
+ return 1;
+}
+
+uint8_t
+dbus_svc_send
+( DBusConnectionState *cs,
+ dbus_svc_MessageType type,
+ int32_t reply_serial,
+ uint32_t *new_serial,
+ const char *destination,
+ const char *path,
+ const char *interface,
+ const char *member,
+ dbus_svc_DataType firstType,
+ ...
+)
+{
+ uint8_t r;
+ va_list va;
+ va_start(va, firstType);
+ r = dbus_svc_send_va(cs, type, reply_serial, new_serial, destination, path,interface,member,firstType,va);
+ va_end(va);
+ return ( r ) ;
+}
+
+dbus_svc_MessageHandle
+dbus_svc_new_message
+( DBusConnectionState* cs,
+ dbus_svc_MessageType type,
+ int32_t reply_serial,
+ const char *destination,
+ const char *path,
+ const char *interface,
+ const char *member
+)
+{
+ DBusMessage *msg = dbus_message_new(type);
+
+ if( msg == 0L)
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_reply_serial failed");
+ return 0;
+ }
+
+ if( reply_serial != -1 )
+ {
+ if( !dbus_message_set_reply_serial(msg,reply_serial) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_reply_serial failed");
+ return 0;
+ }
+ }
+
+ if( (destination !=0L) && !dbus_message_set_destination(msg, destination) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_destination failed");
+ return 0;
+ }
+
+ if( !dbus_message_set_path(msg, path) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_path failed");
+ return 0;
+ }
+
+ if( ! dbus_message_set_interface(msg,interface) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_interface failed - %s", interface);
+ return 0;
+ }
+
+ if( !dbus_message_set_member(msg,member) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_member failed");
+ return 0;
+ }
+
+ return msg;
+}
+
+extern uint8_t
+dbus_svc_send_message
+(
+ DBusConnectionState *cs,
+ dbus_svc_MessageHandle msg,
+ uint32_t *new_serial
+)
+{
+ if( !dbus_connection_send(cs->connection, msg, new_serial) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_send failed");
+ return 0;
+ }
+ if( cs->dh != 0L ) (*(cs->dh))("Sending message");
+ dbus_connection_flush(cs->connection);
+ return 1;
+}
+
+uint8_t
+dbus_svc_message_append_args(DBusConnectionState *cs, dbus_svc_MessageHandle msg, dbus_svc_DataType firstType, ...)
+{
+ va_list va;
+ va_start(va, firstType);
+ if( !dbus_message_append_args_valist( msg, firstType, va ) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_append_args failed");
+ va_end(va);
+ return 0;
+ }
+ va_end(va);
+ return ( 1 ) ;
+}
+
+dbus_svc_MessageHandle
+dbus_svc_call
+( DBusConnectionState *cs,
+ const char *destination,
+ const char *path,
+ const char *member,
+ const char *interface,
+ dbus_svc_DataType firstType,
+ ...
+)
+{
+ DBusMessage *message=0L, *reply=0L;
+ va_list va;
+ DBusError error;
+ int reply_timeout=20000;
+
+ va_start(va, firstType);
+
+ memset(&error,'\0',sizeof(DBusError));
+ dbus_error_init(&error);
+
+ if(( message =
+ dbus_message_new_method_call
+ ( destination,
+ path,
+ interface,
+ member
+ )
+ ) == 0L
+ )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_new_method_call failed");
+ va_end(va);
+ return(0L);
+ };
+
+ if( !dbus_message_append_args_valist( message, firstType, va ) )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_append_args_valist failed");
+ va_end(va);
+ return(0L);
+ }
+
+ if((reply =
+ dbus_connection_send_with_reply_and_block
+ (cs->connection,
+ message, reply_timeout,
+ &error
+ )
+ ) == 0L
+ )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_send_with_reply_and_block failed: %s %s",
+ error.name, error.message
+ );
+ va_end(va);
+ return(0L);
+ }
+ va_end(va);
+ return reply;
+}
+
+dbus_svc_MessageIterator
+dbus_svc_message_iterator_new( DBusConnectionState *cs, DBusMessage *msg)
+{
+ DBusMessageIter *iter = malloc( sizeof(DBusMessageIter) );
+ void *p =cs;
+ p++;
+ if( iter != 0L )
+ {
+ if( !dbus_message_iter_init( msg, iter ))
+ {
+ free( iter ) ;
+ iter = 0L;
+ }
+ }
+ return iter;
+}
+
+uint32_t
+dbus_svc_message_next_arg_type( DBusConnectionState *cs, dbus_svc_MessageIterator iter )
+{
+ void *p =cs;
+ p++;
+ return dbus_message_iter_get_arg_type( iter );
+}
+
+void
+dbus_svc_message_next_arg( DBusConnectionState *cs, dbus_svc_MessageIterator iter, void *value )
+{
+ void *p =cs;
+ p++;
+ dbus_message_iter_get_basic( iter, value );
+ dbus_message_iter_next( iter );
+}
+
+uint32_t
+dbus_svc_message_element_type(DBusConnectionState *cs , dbus_svc_MessageIterator iter)
+{
+ void *p =cs;
+ p++;
+ return dbus_message_iter_get_element_type(iter);
+}
+
+void
+dbus_svc_message_get_elements( DBusConnectionState *cs , dbus_svc_MessageIterator iter, uint32_t *n, void *array )
+{
+ void *p =cs;
+ p++;
+ dbus_message_iter_get_fixed_array( iter, n, array);
+}
+
+void dbus_svc_message_iterator_free( DBusConnectionState *cs, dbus_svc_MessageIterator iter )
+{
+ void *p =cs;
+ p++;
+ free( iter );
+}
+
+uint8_t dbus_svc_message_type( DBusMessage *msg )
+{
+ return dbus_message_get_type( msg );
+}
+
+static DBusConnectionState *
+dbcs_new( DBusConnection *connection )
+{
+ DBusConnectionState *dbcs = (DBusConnectionState *) malloc( sizeof(DBusConnectionState) );
+ if ( dbcs )
+ {
+ memset( dbcs, '\0', sizeof( DBusConnectionState ));
+ dbcs->connection = connection;
+ }
+ return(dbcs);
+}
+
+static DBusConnectionTimeout *
+timeout_new( DBusTimeout *timeout )
+{
+ DBusConnectionTimeout *to = (DBusConnectionTimeout *) malloc ( sizeof(DBusConnectionTimeout) );
+ if( to != 0L )
+ {
+ to->to = timeout;
+ dbus_timeout_set_data(timeout, to, 0L);
+ if( dbus_timeout_get_enabled(timeout) )
+ gettimeofday(&(to->tv),0L);
+ else
+ {
+ to->tv.tv_sec = 0 ;
+ to->tv.tv_usec = 0 ;
+ }
+ }
+ return( to );
+}
+
+static dbus_bool_t
+add_timeout( DBusTimeout *timeout, void *csp )
+{
+ DBusConnectionState *cs = csp;
+ DBusConnectionTimeout *to = timeout_new(timeout);
+ if( cs->dh != 0L ) (*(cs->dh))("add_timeout: %d", dbus_timeout_get_interval(timeout));
+ to->cs = cs;
+ if ( to )
+ {
+ if( tsearch((void*)to, &(cs->timeouts), ptr_key_comparator) != 0L )
+ return TRUE;
+ }
+ if( cs->eh != 0L ) (*(cs->eh))("add_timeout: out of memory");
+ return FALSE;
+}
+
+static void
+remove_timeout( DBusTimeout *timeout, void *csp )
+{
+ DBusConnectionState *cs = csp;
+ DBusConnectionTimeout *to = dbus_timeout_get_data(timeout);
+ if( (to != 0L) && (to->to == timeout) )
+ {
+ if( cs->dh != 0L ) (*(cs->dh))("remove_timeout: %d", dbus_timeout_get_interval(to->to));
+ if( tdelete((const void*)to, &(cs->timeouts), ptr_key_comparator) != 0L )
+ {
+ free(to);
+ }else
+ if( cs->eh != 0L ) (*(cs->eh))("remove_timeout: can't happen?!?: timeout data %p not found", to);
+ }else
+ if( cs->eh != 0L ) (*(cs->eh))("remove_timeout: can't happen?!?: timeout %p did not record data %p %p",
+ timeout, to, ((to != 0L) ? to->to : 0L)
+ );
+}
+
+static void
+toggle_timeout( DBusTimeout *timeout, void *csp )
+{
+ DBusConnectionState *cs = csp;
+ DBusConnectionTimeout **top = tfind( (const void*) dbus_timeout_get_data(timeout),
+ &(cs->timeouts),
+ ptr_key_comparator
+ ),
+ *to=0L;
+ if( (top != 0L) && ((to=*top) != 0L) && (to->to == timeout) )
+ {
+ if( cs->dh != 0L ) (*(cs->dh))("toggle_timeout: %d", dbus_timeout_get_interval(to->to));
+ if( dbus_timeout_get_enabled(timeout) )
+ gettimeofday(&(to->tv),0L);
+ else
+ {
+ to->tv.tv_sec = 0 ;
+ to->tv.tv_usec = 0 ;
+ }
+ }else
+ if( cs->eh != 0L ) (*(cs->eh))("toggle_timeout: can't happen?!?: timeout %p %s %p %p", timeout,
+ ((to==0L) ? "did not record data" : "not found"),
+ to, ((to != 0L) ? to->to : 0L)
+ );
+}
+
+static void
+process_timeout( const void *p, const VISIT which, const int level)
+{
+ DBusConnectionState *cs;
+ void * const *tpp = p;
+ DBusConnectionTimeout *to;
+ struct timeval tv;
+ float now, then, interval;
+ int l = level ? 1 : 0;
+ l=l;
+
+ gettimeofday(&tv,0L);
+
+ if( (tpp != 0L) && (*tpp != 0L) && ((which == postorder) || (which == leaf)) )
+ {
+ to = (DBusConnectionTimeout*)*tpp;
+ cs = to->cs;
+ if ( !dbus_timeout_get_enabled(to->to) )
+ return;
+ cs = dbus_timeout_get_data(to->to);
+ then = ((float)to->tv.tv_sec) + (((float)to->tv.tv_usec) / 1000000.0);
+ if( then != 0.0 )
+ {
+ interval = ((float)dbus_timeout_get_interval(to->to)) / 1000.0;
+ now = ((float)tv.tv_sec) + (( (float)tv.tv_usec) / 1000000.0);
+ if( (now - then) >= interval )
+ {
+ if( cs->dh != 0L ) (*(cs->dh))("handle_timeout: %d - %f %f %f", dbus_timeout_get_interval(to->to), then, now, interval);
+ dbus_timeout_handle( to->to );
+ to->tv=tv;
+ }
+ }else
+ {
+ to->tv = tv;
+ }
+ }
+}
+
+static void
+process_timeouts ( DBusConnectionState *cs )
+{
+ twalk( cs->timeouts, process_timeout );
+}
+
+static void
+set_watch_fds( DBusWatch *watch, DBusConnectionState *cs )
+{
+ uint8_t flags = dbus_watch_get_flags(watch);
+ int fd = dbus_watch_get_fd(watch);
+
+ if ( cs->n <= fd )
+ cs->n = fd + 1;
+
+ if ( dbus_watch_get_enabled(watch) )
+ {
+ if ( flags & DBUS_WATCH_READABLE )
+ {
+ FD_SET(fd , &(cs->r_fds));
+ if( cs->wh != 0L )
+ (*(cs->wh))( fd, WATCH_ENABLE | WATCH_READ, cs->wh_arg );
+ }else
+ {
+ FD_CLR(fd , &(cs->r_fds));
+ if( cs->wh != 0L )
+ (*(cs->wh))( fd, WATCH_READ, cs->wh_arg );
+ }
+
+ if ( flags & DBUS_WATCH_WRITABLE )
+ {
+ FD_SET(fd , &(cs->w_fds));
+ if( cs->wh != 0L )
+ (*(cs->wh))( fd, WATCH_ENABLE | WATCH_WRITE, cs->wh_arg );
+ }else
+ {
+ FD_CLR(fd , &(cs->w_fds));
+ if( cs->wh != 0L )
+ (*(cs->wh))( fd, WATCH_WRITE, cs->wh_arg );
+ }
+ if ( flags & DBUS_WATCH_ERROR )
+ {
+ FD_SET(fd , &(cs->e_fds));
+ if( cs->wh != 0L )
+ (*(cs->wh))( fd, WATCH_ENABLE | WATCH_ERROR, cs->wh_arg );
+ }else
+ {
+ FD_CLR(fd , &(cs->e_fds));
+ if( cs->wh != 0L )
+ (*(cs->wh))( fd, WATCH_ERROR, cs->wh_arg );
+ }
+ }else
+ {
+ if( FD_ISSET( fd, &(cs->r_fds)) )
+ if( cs->wh != 0L )
+ (*(cs->wh))( fd, WATCH_READ, cs->wh_arg );
+ FD_CLR(fd , &(cs->r_fds));
+
+ if( FD_ISSET( fd, &(cs->w_fds)) )
+ if( cs->wh != 0L )
+ (*(cs->wh))( fd, WATCH_WRITE, cs->wh_arg );
+ FD_CLR(fd , &(cs->w_fds));
+
+ if( FD_ISSET( fd, &(cs->e_fds)) )
+ if( cs->wh != 0L )
+ (*(cs->wh))( fd, WATCH_ERROR, cs->wh_arg );
+ FD_CLR(fd , &(cs->e_fds));
+ }
+}
+
+static dbus_bool_t
+add_watch ( DBusWatch *watch, void *csp )
+{
+ DBusConnectionState *cs = csp;
+
+ dbus_watch_set_data(watch, cs, no_free );
+ if( cs->dh != 0L ) (*(cs->dh))("add_watch: %d", dbus_watch_get_fd(watch));
+ if( tsearch((const void*)watch,&(cs->watches),ptr_key_comparator) == 0L )
+ {
+ if( cs->eh != 0L ) (*(cs->eh))("add_watch: out of memory");
+ return FALSE;
+ }
+ set_watch_fds(watch,cs);
+ return TRUE;
+}
+
+static void
+remove_watch ( DBusWatch *watch, void *csp )
+{
+ DBusConnectionState *cs = csp;
+ int fd = dbus_watch_get_fd(watch);
+ if( tdelete((const void*)watch, &(cs->watches), ptr_key_comparator) == 0L )
+ if( cs->eh != 0L ) (*(cs->eh))("remove_watch: can't happen?!?: watch not found");
+ if( cs->dh != 0L ) (*(cs->dh))("remove_watch: %d", dbus_watch_get_fd(watch));
+ FD_CLR(fd , &(cs->r_fds));
+ FD_CLR(fd , &(cs->w_fds));
+ FD_CLR(fd , &(cs->e_fds));
+ if( cs->wh != 0L )
+ (*(cs->wh))(dbus_watch_get_fd(watch), WATCH_READ | WATCH_WRITE | WATCH_ERROR, cs->wh_arg );
+}
+
+static void
+toggle_watch ( DBusWatch *watch, void *csp )
+{
+ DBusConnectionState *cs = csp;
+ if( cs->dh != 0L ) (*(cs->dh))("toggle_watch: %d", dbus_watch_get_fd(watch));
+ set_watch_fds(watch,cs);
+}
+
+static void
+process_watch( const void *p, const VISIT which, const int level)
+{
+ void * const *wpp=p;
+ DBusWatch *w;
+ int fd;
+ uint8_t flags;
+ DBusConnectionState *cs;
+ int l = level ? 1 : 0;
+ l=l;
+
+ if((wpp != 0L) && (*wpp != 0L) && ( (which == postorder) || (which == leaf) ) )
+ {
+ w = (DBusWatch*)*wpp;
+ cs = dbus_watch_get_data( w );
+ if( cs == 0 )
+ return;
+ if( ! dbus_watch_get_enabled(w) )
+ return;
+ fd = dbus_watch_get_fd( w );
+ flags = dbus_watch_get_flags( w );
+ if( cs->dh != 0L ) (*(cs->dh))("handle_watch: %d", dbus_watch_get_fd( w ));
+ if ( (flags & DBUS_WATCH_READABLE) && (FD_ISSET(fd, &(cs->s_r_fds))) )
+ dbus_watch_handle(w, DBUS_WATCH_READABLE);
+ if ( (flags & DBUS_WATCH_WRITABLE) && (FD_ISSET(fd, &(cs->s_w_fds))) )
+ dbus_watch_handle(w, DBUS_WATCH_READABLE);
+ if ( (flags & DBUS_WATCH_ERROR) && (FD_ISSET(fd, &(cs->s_e_fds))) )
+ dbus_watch_handle(w, DBUS_WATCH_ERROR);
+ }
+}
+
+static void
+process_watches ( DBusConnectionState *cs )
+{
+ twalk( cs->watches, process_watch );
+}
+
+void dbus_svc_handle_watch( DBusConnectionState *cs, int fd, dbus_svc_WatchFlags action )
+{
+ switch( action & 7 )
+ {
+ case WATCH_READ:
+ FD_SET(fd, &(cs->s_r_fds));
+ break;
+
+ case WATCH_WRITE:
+ FD_SET(fd, &(cs->s_w_fds));
+ break;
+
+ case WATCH_ERROR:
+ FD_SET(fd, &(cs->s_e_fds));
+ break;
+ }
+}
+
+static void
+dispatch_status
+( DBusConnection *connection,
+ DBusDispatchStatus new_status,
+ void *csp
+)
+{
+ connection=connection;
+ DBusConnectionState *cs = csp;
+ cs->dispatchStatus = new_status;
+}
+
+void
+dbus_svc_main_loop( DBusConnectionState *cs, void (*idle_handler)(DBusConnectionState *) )
+{
+ struct timeval timeout={0,200000};
+ int n_fds;
+
+ while( cs->status != SHUTDOWN )
+ {
+ cs->s_r_fds = cs->r_fds;
+ cs->s_w_fds = cs->w_fds;
+ cs->s_e_fds = cs->e_fds;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec= 200000;
+
+ if ( (n_fds = select(cs->n, &(cs->s_r_fds), &(cs->s_w_fds), &(cs->s_e_fds), &timeout)) < 0 )
+ {
+ if (errno != EINTR)
+ {
+ if( cs->eh != 0L ) (*(cs->eh))( "select failed: %d : %s", errno, strerror(errno));
+ return;
+ }
+ }
+
+ if( n_fds > 0 )
+ process_watches(cs);
+
+ process_timeouts(cs);
+
+ if ( cs->dispatchStatus != DBUS_DISPATCH_COMPLETE )
+ dbus_connection_dispatch( cs->connection );
+
+ if( idle_handler != 0L )
+ (*idle_handler)(cs);
+ }
+}
+
+void dbus_svc_dispatch(DBusConnectionState *cs)
+{
+ process_watches(cs);
+
+ FD_ZERO(&(cs->s_r_fds));
+ FD_ZERO(&(cs->s_w_fds));
+ FD_ZERO(&(cs->s_e_fds));
+
+ process_timeouts(cs);
+
+ while ( cs->dispatchStatus != DBUS_DISPATCH_COMPLETE )
+ dbus_connection_dispatch( cs->connection );
+}
+
+void
+dbus_svc_quit( DBusConnectionState *cs )
+{
+ cs->status = SHUTDOWN;
+}
+
+static isc_result_t
+connection_setup
+( DBusConnection *connection,
+ DBUS_SVC *dbus,
+ dbus_svc_WatchHandler wh,
+ dbus_svc_ErrorHandler eh,
+ dbus_svc_ErrorHandler dh,
+ void *wh_arg
+)
+{
+ *dbus = dbcs_new( connection );
+
+ if ( *dbus == 0L )
+ {
+ if(eh)(*(eh))("connection_setup: out of memory");
+ goto fail;
+ }
+ (*dbus)->wh = wh;
+ (*dbus)->wh_arg = wh_arg;
+ (*dbus)->eh = eh;
+ (*dbus)->dh = dh;
+
+ if (!dbus_connection_set_watch_functions
+ ( (*dbus)->connection,
+ add_watch,
+ remove_watch,
+ toggle_watch,
+ *dbus,
+ no_free
+ )
+ )
+ {
+ if( (*dbus)->eh != 0L ) (*((*dbus)->eh))("connection_setup: dbus_connection_set_watch_functions failed");
+ goto fail;
+ }
+
+ if (!dbus_connection_set_timeout_functions
+ ( connection,
+ add_timeout,
+ remove_timeout,
+ toggle_timeout,
+ *dbus,
+ no_free
+ )
+ )
+ {
+ if( (*dbus)->eh != 0L ) (*((*dbus)->eh))("connection_setup: dbus_connection_set_timeout_functions failed");
+ goto fail;
+ }
+
+ dbus_connection_set_dispatch_status_function
+ ( connection,
+ dispatch_status,
+ *dbus,
+ no_free
+ );
+
+ if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
+ dbus_connection_ref(connection);
+
+ return ISC_R_SUCCESS;
+
+ fail:
+ if( *dbus != 0L )
+ free(*dbus);
+
+ dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
+ dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
+ dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
+
+ return ISC_R_FAILURE;
+}
+
+isc_result_t
+dbus_svc_init
+(
+ dbus_svc_DBUS_TYPE bus,
+ char *name,
+ DBUS_SVC *dbus,
+ dbus_svc_WatchHandler wh ,
+ dbus_svc_ErrorHandler eh ,
+ dbus_svc_ErrorHandler dh ,
+ void *wh_arg
+)
+{
+ DBusConnection *connection;
+ DBusError error;
+ char *session_bus_address=0L;
+
+ memset(&error,'\0',sizeof(DBusError));
+
+ dbus_error_init(&error);
+
+ switch( bus )
+ {
+ /* DBUS_PRIVATE_* bus types are the only type which allow reconnection if the dbus-daemon is restarted
+ */
+ case DBUS_PRIVATE_SYSTEM:
+
+ if ( (connection = dbus_connection_open_private("unix:path=/var/run/dbus/system_bus_socket", &error)) == 0L )
+ {
+ if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
+ return ISC_R_FAILURE;
+ }
+
+ if ( ! dbus_bus_register(connection,&error) )
+ {
+ if(eh)(*eh)("dbus_bus_register failed: %s %s", error.name, error.message);
+ dbus_connection_close(connection);
+ free(connection);
+ return ISC_R_FAILURE;
+ }
+ break;
+
+ case DBUS_PRIVATE_SESSION:
+
+ session_bus_address = getenv("DBUS_SESSION_BUS_ADDRESS");
+ if ( session_bus_address == 0L )
+ {
+ if(eh)(*eh)("dbus_svc_init failed: DBUS_SESSION_BUS_ADDRESS environment variable not set");
+ return ISC_R_FAILURE;
+ }
+
+ if ( (connection = dbus_connection_open_private(session_bus_address, &error)) == 0L )
+ {
+ if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
+ return ISC_R_FAILURE;
+ }
+
+ if ( ! dbus_bus_register(connection,&error) )
+ {
+ if(eh)(*eh)("dbus_bus_register failed: %s %s", error.name, error.message);
+ dbus_connection_close(connection);
+ free(connection);
+ return ISC_R_FAILURE;
+ }
+ break;
+
+ case DBUS_SYSTEM:
+ case DBUS_SESSION:
+
+ if ( (connection = dbus_bus_get (bus, &error)) == 0L )
+ {
+ if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
+ return ISC_R_FAILURE;
+ }
+ break;
+
+ default:
+ if(eh)(*eh)("dbus_svc_init failed: unknown bus type %d", bus);
+ return ISC_R_FAILURE;
+ }
+
+ dbus_connection_set_exit_on_disconnect(connection, FALSE);
+
+ if ( (connection_setup(connection, dbus, wh, eh, dh, wh_arg)) != ISC_R_SUCCESS)
+ {
+ if(eh)(*eh)("dbus_svc_init failed: connection_setup failed");
+ return ISC_R_FAILURE;
+ }
+
+ if( name == 0L )
+ return ISC_R_SUCCESS;
+
+ (*dbus)->unique_name = dbus_bus_get_unique_name(connection);
+
+ switch
+ ( dbus_bus_request_name
+ ( connection, name,
+#ifdef DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT
+ DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT ,
+#else
+ 0 ,
+#endif
+ &error
+ )
+ )
+ {
+ case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
+ break;
+ case DBUS_REQUEST_NAME_REPLY_EXISTS:
+ case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
+ case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
+ if(eh)(*eh)("dbus_svc_init: dbus_bus_request_name failed: Name already registered");
+ goto give_up;
+ default:
+ if(eh)(*eh)("dbus_svc_init: dbus_bus_request_name failed: %s %s", error.name, error.message);
+ goto give_up;
+ }
+ return ISC_R_SUCCESS;
+
+ give_up:
+ dbus_connection_close( connection );
+ dbus_connection_unref( connection );
+ if( *dbus )
+ {
+ dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
+ dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
+ dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
+ free(*dbus);
+ }
+ return ISC_R_FAILURE;
+}
+
+const char *dbus_svc_unique_name(DBusConnectionState *cs)
+{
+ return cs->unique_name;
+}
+
+void
+dbus_svc_shutdown ( DBusConnectionState *cs )
+{
+ if (!dbus_connection_set_watch_functions
+ ( cs->connection,
+ NULL, NULL, NULL, NULL, NULL
+ )
+ ) if( cs->eh != 0L ) (*(cs->eh))("connection_shutdown: dbus_connection_set_watch_functions: No Memory."
+ "Setting watch functions to NULL failed."
+ );
+
+ if (!dbus_connection_set_timeout_functions
+ ( cs->connection,
+ NULL, NULL, NULL, NULL, NULL
+ )
+ ) if( cs->eh != 0L ) (*(cs->eh))("connection_shutdown: dbus_connection_set_timeout_functions: No Memory."
+ "Setting timeout functions to NULL failed."
+ );
+
+ dbus_connection_set_dispatch_status_function (cs->connection, NULL, NULL, NULL);
+
+ tdestroy( cs->timeouts, free);
+ cs->timeouts=0L;
+ tdestroy( cs->watches, no_free);
+ cs->watches=0L;
+
+ dbus_connection_close( cs->connection );
+ dbus_connection_unref( cs->connection );
+
+ free( cs );
+}
diff --git a/contrib/dbus/dbus_service.h b/contrib/dbus/dbus_service.h
new file mode 100644
index 0000000..d8a21f1
--- /dev/null
+++ b/contrib/dbus/dbus_service.h
@@ -0,0 +1,287 @@
+/* D-BUS Service Utilities
+ *
+ * Provides utilities for construction of D-BUS "Services"
+ *
+ * Copyright(C) Jason Vas Dias, Red Hat Inc., 2005
+ * Modified by Adam Tkac, Red Hat Inc., 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation at
+ * http://www.fsf.org/licensing/licenses/gpl.txt
+ * and included in this software distribution as the "LICENSE" file.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef D_BUS_SERVER_UTILITIES_H
+#define D_BUS_SERVER_UTILITIES_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <isc/types.h>
+
+typedef struct dbcs_s* DBUS_SVC;
+
+typedef enum
+{ HANDLED, NOT_HANDLED, HANDLED_NOW
+} dbus_svc_HandlerResult;
+
+typedef enum
+{ INVALID, CALL, RETURN, ERROR, SIGNAL
+} dbus_svc_MessageType;
+
+typedef enum
+{
+ DBUS_SESSION,
+ DBUS_SYSTEM,
+ DBUS_STARTER,
+ DBUS_PRIVATE_SYSTEM,
+ DBUS_PRIVATE_SESSION
+} dbus_svc_DBUS_TYPE;
+
+typedef enum /* D-BUS Protocol Type Codes / Signature Chars */
+{
+ TYPE_INVALID = (int)'\0',
+ TYPE_BYTE = (int)'y',
+ TYPE_BOOLEAN = (int)'b',
+ TYPE_INT16 = (int)'n',
+ TYPE_UINT16 = (int)'q',
+ TYPE_INT32 = (int)'i',
+ TYPE_UINT32 = (int)'u',
+ TYPE_INT64 = (int)'x',
+ TYPE_UINT64 = (int)'t',
+ TYPE_DOUBLE = (int)'d',
+ TYPE_STRING = (int)'s',
+ TYPE_OBJECT_PATH =(int)'o',
+ TYPE_SIGNATURE= (int)'g',
+ TYPE_ARRAY = (int)'a',
+ TYPE_VARIANT = (int)'v',
+ TYPE_STRUCT = (int)'r',
+ TYPE_DICT_ENTRY = (int)'e',
+ STRUCT_BEGIN = (int)'(',
+ STRUCT_END = (int)')',
+ DICT_ENTRY_BEGIN =(int)'{',
+ DICT_ENTRY_END =(int)'}'
+} dbus_svc_DataType;
+
+typedef struct DBusMessage* dbus_svc_MessageHandle;
+
+typedef int
+(*dbus_svc_ErrorHandler)
+( const char *errorFmt, ...
+); /* Error Handler function prototype - handle FATAL errors from D-BUS calls */
+
+typedef enum
+{
+ WATCH_ENABLE = 8,
+ WATCH_ERROR = 4,
+ WATCH_WRITE = 2,
+ WATCH_READ = 1
+} dbus_svc_WatchFlags;
+
+typedef void (*dbus_svc_WatchHandler)( int, dbus_svc_WatchFlags, void *arg );
+
+typedef dbus_svc_HandlerResult
+(*dbus_svc_MessageHandler)
+( DBUS_SVC dbus,
+ dbus_svc_MessageType type,
+ uint8_t reply_expected, /* 1 / 0 */
+ uint32_t serial, /* serial number of message; needed to reply */
+ const char *destination, /* D-BUS connection name / destination */
+ const char *path, /* D-BUS Object Path */
+ const char *member, /* D-BUS Object Member */
+ const char *interface, /* D-BUS Object interface */
+ const char *if_suffix, /* remainder of interface prefixed by ifPrefix */
+ const char *sender, /* Senders' connection destination */
+ const char *signature, /* Signature String composed of Type Codes */
+ dbus_svc_MessageHandle msg,/* Message pointer: call dbus_svc_get_args(msg,...) to get data */
+ const char *prefix, /* If non-null, this is the root prefix for this sub-path message */
+ const char *suffix, /* If non-null, this is the suffix of this sub-path message */
+ void *prefixObject, /* If non-null, this is the object that was registered for the prefix */
+ void *object /* If non-null, this is the object that was registered for the complete path */
+); /* Message Handler function prototype */
+
+#define DBusMsgHandlerArgs \
+ DBUS_SVC dbus, \
+ dbus_svc_MessageType type, \
+ uint8_t reply_expected, \
+ uint32_t serial, \
+ const char *destination, \
+ const char *path, \
+ const char *member, \
+ const char *interface, \
+ const char *if_suffix, \
+ const char *sender, \
+ const char *signature, \
+ dbus_svc_MessageHandle msg, \
+ const char *prefix, \
+ const char *suffix, \
+ void *prefixObject, \
+ void *object
+
+#define SHUTDOWN 255
+
+extern isc_result_t dbus_svc_init
+( dbus_svc_DBUS_TYPE bus,
+ char *name, /* name to register with D-BUS */
+ DBUS_SVC *dbus, /* dbus handle */
+ dbus_svc_WatchHandler wh, /* optional handler for watch events */
+ dbus_svc_ErrorHandler eh, /* optional error log message handler */
+ dbus_svc_ErrorHandler dh, /* optional debug / info log message handler */
+ void *wh_arg /* optional watch handler arg */
+);
+/*
+ * Obtains connection to DBUS_BUS_STARTER and registers "name".
+ * "eh" will be called for all errors from this server session.
+ */
+
+/* EITHER :
+ * pass a NULL WatchHandler to dbus_svc_init and use dbus_svc_main_loop
+ * OR:
+ * supply a valid WatchHandler, and call dbus_svc_handle_watch when
+ * select() returns the watch fd as ready for the watch action, and
+ * call dbus_svc_dispatch when all watches have been handled.
+ */
+
+
+uint8_t
+dbus_svc_add_filter
+( DBUS_SVC, dbus_svc_MessageHandler mh, void *obj, int n_matches, ... );
+/*
+ * Registers SINGLE message handler to handle ALL messages, adding match rules
+ */
+
+void dbus_svc_main_loop( DBUS_SVC, void (*idle_handler)(DBUS_SVC) );
+
+void dbus_svc_handle_watch( DBUS_SVC, int watch_fd, dbus_svc_WatchFlags action);
+
+void dbus_svc_dispatch( DBUS_SVC );
+
+/*
+ * Enter message processing loop.
+ * If "idle_handler" is non-null, it will be called once per iteration of loop.
+ */
+
+const char *dbus_svc_unique_name( DBUS_SVC );
+/*
+ * Returns connection "unique" (socket) name
+ */
+
+void dbus_svc_quit( DBUS_SVC );
+/*
+ * Exit message processing loop
+ */
+
+void dbus_svc_shutdown( DBUS_SVC );
+/*
+ * Close connections and clean up.
+ * DBUS_SVC pointer is invalid after this.
+ */
+
+uint8_t
+dbus_svc_get_args( DBUS_SVC, dbus_svc_MessageHandle, dbus_svc_DataType, ... );
+/* get arguments from message */
+
+uint8_t
+dbus_svc_get_args_va( DBUS_SVC, dbus_svc_MessageHandle, dbus_svc_DataType, va_list );
+/* get arguments from message */
+
+
+typedef void (*dbus_svc_ShutdownHandler) ( DBUS_SVC, void * );
+uint8_t
+dbus_svc_add_shutdown_filter
+(
+ DBUS_SVC, dbus_svc_ShutdownHandler sh, void *obj
+);
+/* Registers a filter for D-BUS shutdown event.
+ * Cannot be used in conjunction with dbus_svc_add_message_filter.
+ */
+
+uint8_t
+dbus_svc_remove_message_filter
+( DBUS_SVC, dbus_svc_MessageHandler mh);
+/* Unregisters the message filter */
+
+uint8_t
+dbus_svc_send
+( DBUS_SVC,
+ dbus_svc_MessageType type,
+ int32_t reply_serial,
+ uint32_t *new_serial,
+ const char *destination,
+ const char *path,
+ const char *member,
+ const char *interface,
+ dbus_svc_DataType firstType,
+ ... /* pointer, { (dbus_svc_DataType, pointer )...} */
+); /* sends messages / replies to "destination" */
+
+uint8_t
+dbus_svc_send_va
+( DBUS_SVC cs,
+ dbus_svc_MessageType type,
+ int32_t reply_serial,
+ uint32_t *new_serial,
+ const char *destination,
+ const char *path,
+ const char *member,
+ const char *interface,
+ dbus_svc_DataType firstType,
+ va_list va
+); /* sends messages / replies to "destination" */
+
+dbus_svc_MessageHandle
+dbus_svc_call
+( DBUS_SVC cs,
+ const char *destination,
+ const char *path,
+ const char *member,
+ const char *interface,
+ dbus_svc_DataType firstType,
+ ...
+); /* constructs message, sends it, returns reply */
+
+dbus_svc_MessageHandle
+dbus_svc_new_message
+( DBUS_SVC cs,
+ dbus_svc_MessageType type,
+ int32_t reply_serial,
+ const char *destination,
+ const char *path,
+ const char *interface,
+ const char *member
+);
+
+uint8_t
+dbus_svc_send_message(DBUS_SVC , dbus_svc_MessageHandle , uint32_t * );
+
+uint8_t
+dbus_svc_message_append_args( DBUS_SVC , dbus_svc_MessageHandle, dbus_svc_DataType, ...);
+
+typedef struct DBusMessageIter *dbus_svc_MessageIterator;
+
+dbus_svc_MessageIterator
+dbus_svc_message_iterator_new( DBUS_SVC, dbus_svc_MessageHandle );
+
+uint32_t
+dbus_svc_message_next_arg_type( DBUS_SVC, dbus_svc_MessageIterator );
+
+void
+dbus_svc_message_next_arg( DBUS_SVC, dbus_svc_MessageIterator, void * );
+
+uint32_t
+dbus_svc_message_element_type( DBUS_SVC, dbus_svc_MessageIterator );
+
+void
+dbus_svc_message_get_elements( DBUS_SVC, dbus_svc_MessageIterator, uint32_t *n, void *array );
+
+uint8_t dbus_svc_message_type( dbus_svc_MessageHandle );
+
+void dbus_svc_message_iterator_free( DBUS_SVC, dbus_svc_MessageIterator );
+
+#endif
diff --git a/contrib/dbus/named-dbus-system.conf b/contrib/dbus/named-dbus-system.conf
new file mode 100644
index 0000000..2cb99bd
--- /dev/null
+++ b/contrib/dbus/named-dbus-system.conf
@@ -0,0 +1,20 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <servicedir>/usr/share/dbus-1/services</servicedir>
+ <policy user="named">
+ <allow own="com.redhat.named"/>
+ <allow send_interface="com.redhat.named"/>
+ <allow send_destination="com.redhat.named"/>
+ </policy>
+ <policy user="root">
+ <allow send_interface="com.redhat.named"/>
+ <allow send_destination="com.redhat.named"/>
+ </policy>
+ <policy context="default">
+ <deny own="com.redhat.named"/>
+ <deny send_destination="com.redhat.named"/>
+ <deny send_interface="com.redhat.named"/>
+ </policy>
+</busconfig>
+
diff --git a/contrib/dbus/named-dbus.service b/contrib/dbus/named-dbus.service
new file mode 100644
index 0000000..ddf40e7
--- /dev/null
+++ b/contrib/dbus/named-dbus.service
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=com.redhat.named
+Exec=/usr/sbin/named
diff --git a/contrib/dlz/bin/dlzbdb/Makefile.in b/contrib/dlz/bin/dlzbdb/Makefile.in
new file mode 100644
index 0000000..a31c503
--- /dev/null
+++ b/contrib/dlz/bin/dlzbdb/Makefile.in
@@ -0,0 +1,73 @@
+# Copyright (C) 1998-2001 Internet Software Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# $Id: Makefile.in,v 1.3 2007/09/07 06:53:03 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+DLZINCLUDES = @DLZ_DRIVER_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include \
+ ${ISC_INCLUDES} ${DLZINCLUDES}
+
+CDEFINES = @USE_DLZ@
+CWARNINGS =
+
+DLZLIBS = @DLZ_DRIVER_LIBS@
+ISCLIBS = ../../../../lib/isc/libisc.@A@
+
+DEPLIBS = ${ISCDEPLIBS}
+
+LIBS = ${ISCLIBS} ${DLZLIBS} @LIBS@
+
+TARGETS = dlzbdb
+
+SRCS = dlzbdb.c
+
+#MANPAGES =
+
+#HTMLPAGES =
+
+#MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+dlzbdb.@O@: dlzbdb.c
+ ${LIBTOOL} ${CC} ${ALL_CFLAGS} -DVERSION=\"${VERSION}\" \
+ -c ${srcdir}/dlzbdb.c
+
+dlzbdb: dlzbdb.@O@ ${DEPLIBS}
+ ${LIBTOOL} ${PURIFY} ${CC} ${CFLAGS} -o $@ dlzbdb.@O@ ${LIBS}
+
+doc man:: ${MANOBJS}
+
+#docclean manclean maintainer-clean::
+# rm -f ${MANOBJS}
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+# $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man8
+
+install:: dlzbdb installdirs
+ ${LIBTOOL} ${INSTALL_PROGRAM} dlzbdb ${DESTDIR}${sbindir}
diff --git a/contrib/dlz/bin/dlzbdb/dlzbdb.c b/contrib/dlz/bin/dlzbdb/dlzbdb.c
new file mode 100644
index 0000000..aedc953
--- /dev/null
+++ b/contrib/dlz/bin/dlzbdb/dlzbdb.c
@@ -0,0 +1,1273 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef DLZ_BDB
+
+/*
+ * exit codes
+ * 0 everything ok
+ * 1 error parsing command line
+ * 2 Missing, too many or invalid combination of command line parameters
+ * 3 Unable to open BDB database.
+ * 4 Unable to allocate memory for, or create lexer.
+ * 5 unable to perform BDB cursor operation
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/formatcheck.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <db.h>
+
+/* shut up compiler warnings about no previous prototype */
+
+static void
+show_usage(void);
+
+int
+getzone(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey);
+
+int
+gethost(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey);
+
+void
+bdb_cleanup(void);
+
+isc_result_t
+bdb_opendb(DBTYPE db_type, DB **db_out, const char *db_name, int flags);
+
+void
+put_data(isc_boolean_t dns_data, char *input_key, char *input_data);
+
+void
+insert_data(void);
+
+isc_result_t
+openBDB(void);
+
+isc_result_t
+open_lexer(void);
+
+void
+close_lexer(void);
+
+isc_result_t
+bulk_write(char type, DB *database, DBC *dbcursor, DBT *bdbkey, DBT *bdbdata);
+
+void
+operation_add(void);
+
+void
+operation_bulk(void);
+
+void
+operation_listOrDelete(isc_boolean_t dlt);
+
+
+/*%
+ * Maximum length of a single data line that
+ * may be inserted into database by this program.
+ * If you need to insert a line of data that is more
+ * than 10,000 characters change this definition.
+ */
+
+#define max_data_len 10000
+
+/*%
+ * BDB database names. If you want to use different
+ * database names change them here.
+ */
+
+#define dlz_data "dns_data"
+#define dlz_zone "dns_zone"
+#define dlz_host "dns_host"
+#define dlz_client "dns_client"
+
+
+/*%
+ * Error code returned by BDB secondary index callback functions.
+ * This error is returned if the callback function could not create
+ * the secondary index for any reason.
+ */
+
+#define BDBparseErr 1
+
+/* A struct to hold all the relevant info about the database */
+
+typedef struct bdb_instance {
+ DB_ENV *dbenv; /* BDB environment */
+ DB *data; /* dns_data database handle */
+ DBC *cursor; /* database cursor */
+ DBC *cursor2; /* second cursor used during list operation. */
+ DBC *cursor3; /* third cursor used during list operation */
+ DBC *cursor4; /* fourth cursor used during list operation */
+ DB *zone; /* zone database handle */
+ DB *host; /* host database handle */
+ DB *client; /* client database handle */
+} bdb_instance_t;
+
+/* Possible operations */
+
+#define list 1 /* list data */
+#define dele 2 /* delete data */
+#define add 3 /* add a single piece of data */
+#define bulk 4 /* bulk load data */
+
+
+/*%
+ * quit macro is used instead of exit. quit always trys to close the lexer
+ * and the BDB database before exiting.
+ */
+
+#define quit(i) close_lexer(); bdb_cleanup(); exit(i);
+
+/*%
+ * checkOp is used to verify that only one operation (list, del, add,
+ * bulk from file, bulk from stdin) is specified on the command line.
+ * This prevents a user from specifying two operations on the command
+ * line, which would make no sense anyway.
+ */
+
+#define checkOp(x) if (x != 0) {fprintf(stderr, "\nonly one operation "\
+ "(l e d a f s) may be specified\n"); quit(2);}
+
+/*%
+ * checkParam is used to only allow a parameter to be specified once.
+ * I.E. the parameter key can only be used on the command line once.
+ * any attempt to use it twice causes an error.
+ */
+
+#define checkParam(x, y) if (x != NULL) {fprintf(stderr, "\n%s may only "\
+ "be specified once\n", y); quit(2);}
+
+/*%
+ * checkInvalidParam is used to only allow paramters which make sense for
+ * the operation selected. I.E. passing the key parameter makes no sense
+ * for the add operation, and thus it isn't allowed.
+ */
+
+#define checkInvalidParam(x, y, z) if (x != NULL) {fprintf(stderr, "\n%s "\
+ "may not be specified %s\n", y, z); quit(2);}
+
+/*%
+ * checkInvalidOption is used to only allow paramters which make sense for
+ * the operation selected - but checks boolean options.
+ * I.E. passing the "b" bare_list parameter makes no sense for the add
+ * operation, and thus it isn't allowed.
+ * if w == x then output error message "flag", "message"
+ */
+
+#define checkInvalidOption(w, x, y, z) if (w == x) {fprintf(stderr, "\n%s "\
+ "may not be specified %s\n", y, z); quit(2);}
+
+/* Global Variables */
+
+int operation = 0; /*%< operation to perform. */
+/*% allow new lock files or DB to be created. */
+isc_boolean_t create_allowed = isc_boolean_false;
+char *key = NULL; /*%< key to use in list & del operations */
+
+/*% dump DB in DLZBDB bulk format */
+isc_boolean_t list_everything = isc_boolean_false;
+unsigned int key_val; /*%< key as unsigned int used in list & del operations */
+char *zone = NULL; /*%< zone to use in list operations */
+char *host = NULL; /*%< host to use in list operations */
+char *c_zone = NULL; /*%< client zone to use in list operations */
+char *c_ip = NULL; /*%< client IP to use in list operations */
+char *a_data = NULL; /*%< data in add operation */
+char *bulk_file = NULL; /*%< bulk data file to load */
+char *db_envdir = NULL; /*%< BDB environment location */
+char *db_file = NULL; /*%< BDB database file location. */
+bdb_instance_t db; /* BDB instance we are operating on */
+isc_lex_t *lexer = NULL; /*%< lexer for use to use in parsing input */
+isc_mem_t *lex_mctx = NULL; /*%< memory context for lexer */
+char lex_data_buf[max_data_len]; /*%< data array to use for lex_buffer below */
+isc_buffer_t lex_buffer; /*%< buffer for lexer during add operation */
+
+
+/*%
+ * Displays usage message
+ */
+
+static void
+show_usage(void) {
+ fprintf(stderr, "\n\n\
+---Usage:---------------------------------------------------------------------\
+\n\n\
+ List data:\n\
+ dlzbdb -l [-k key] [-z zone] [-h host] [-c client_zone] [-i client_ip]\n\
+ BDB_environment BDB_database\n\n\
+ Delete data:\n\
+ dlzbdb -d [-k key] [-c client_zone] [-i client_ip]\n\
+ BDB_environment BDB_database\n\n\
+ Bulk load data from file:\n\
+ dlzbdb -f file_to_load BDB_environment BDB_database\n\n\
+ Bulk load data from stdin\n\
+ dlzbdb -s BDB_environment BDB_database\n\n\
+ Add data:\n\
+ dlzbdb -a \"dns data to be added\" BDB_environment BDB_database\n\n\
+ Export data:\n\
+ dlzbdb -e BDB_environment BDB_database\n\n\
+ Normally operations can only be performed on an existing database files.\n\
+ Use the -n flag with any operation to allow files to be created.\n\
+ Existing files will NOT be truncated by using the -n flag.\n\
+ The -n flag will allow a new database to be created, or allow new\n\
+ environment files to be created for an existing database.\n\n\
+---Format for -f & -a options:------------------------------------------------\
+\n\n\
+db_type zone host dns_type ttl ip\n\
+db_type zone host dns_type ttl mx_priority mail_host\n\
+db_type zone host dns_type ttl nm_svr resp_psn serial refresh retry expire min\
+\n\
+db_type zone client_ip\n\n\
+---Examples:------------------------------------------------------------------\
+\n\n\
+d mynm.com www A 10 127.0.0.1\n\
+d mynm.com @ MX 10 5 mail\n\
+d mynm.com @ SOA 10 ns1.mynm.com. root.mynm.com. 2 28800 7200 604800 86400\n\
+c mynm.com 127.0.0.1\n\
+c mynm.com 192.168.0.10\n\
+");
+quit(1);
+}
+
+
+/*% BDB callback to create zone secondary index */
+
+int
+getzone(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey) {
+ char *tmp;
+ char *left;
+ char *right;
+ int result=0;
+
+ UNUSED(dbp);
+ UNUSED(pkey);
+
+ /* Allocate memory to use in parsing the string */
+ tmp = right = malloc(pdata->size + 1);
+
+ /* verify memory was allocated */
+ if (right == NULL) {
+ result = BDBparseErr;
+ goto getzone_cleanup;
+ }
+
+ /* copy data string into newly allocated memory */
+ strncpy(right, pdata->data, pdata->size);
+ right[pdata->size] = '\0';
+
+ /* split string at the first space */
+ left = isc_string_separate(&right, " ");
+
+ /* copy string for "zone" secondary index */
+ skey->data = strdup(left);
+ if (skey->data == NULL) {
+ result = BDBparseErr;
+ goto getzone_cleanup;
+ }
+ /* set required values for BDB */
+ skey->size = strlen(skey->data);
+ skey->flags = DB_DBT_APPMALLOC;
+
+ getzone_cleanup:
+
+ /* cleanup memory */
+ if (tmp != NULL)
+ free(tmp);
+
+ return result;
+}
+
+/*%
+ * BDB callback to create host secondary index
+ */
+
+int
+gethost(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey) {
+ char *tmp;
+ char *left;
+ char *right;
+ int result=0;
+
+ UNUSED(dbp);
+ UNUSED(pkey);
+
+ /* allocate memory to use in parsing the string */
+ tmp = right = malloc(pdata->size + 1);
+
+ /* verify memory was allocated */
+ if (tmp == NULL) {
+ result = BDBparseErr;
+ goto gethost_cleanup;
+ }
+
+ /* copy data string into newly allocated memory */
+ strncpy(right, pdata->data, pdata->size);
+ right[pdata->size] = '\0';
+
+ /* we don't care about left string. */
+ /* memory of left string will be freed when tmp is freed. */
+ isc_string_separate(&right, " ");
+
+ /* verify right still has some characters left */
+ if (right == NULL) {
+ result = BDBparseErr;
+ goto gethost_cleanup;
+ }
+
+ /* get "host" from data string */
+ left = isc_string_separate(&right, " ");
+ /* copy string for "host" secondary index */
+ skey->data = strdup(left);
+ if (skey->data == NULL) {
+ result = BDBparseErr;
+ goto gethost_cleanup;
+ }
+ /* set required values for BDB */
+ skey->size = strlen(skey->data);
+ skey->flags = DB_DBT_APPMALLOC;
+
+ gethost_cleanup:
+
+ /* cleanup memory */
+ if (tmp != NULL)
+ free(tmp);
+
+ return result;
+}
+
+/*%
+ * Performs BDB cleanup. Close each database that we opened.
+ * Close environment. Set each var to NULL so we know they
+ * were closed and don't accidentally try to close them twice.
+ */
+
+void
+bdb_cleanup(void) {
+
+ /* close cursors */
+ if (db.cursor4 != NULL) {
+ db.cursor4->c_close(db.cursor4);
+ db.cursor4 = NULL;
+ }
+
+ if (db.cursor3 != NULL) {
+ db.cursor3->c_close(db.cursor3);
+ db.cursor3 = NULL;
+ }
+
+ if (db.cursor2 != NULL) {
+ db.cursor2->c_close(db.cursor2);
+ db.cursor2 = NULL;
+ }
+
+ if (db.cursor != NULL) {
+ db.cursor->c_close(db.cursor);
+ db.cursor = NULL;
+ }
+
+ /* close databases */
+ if (db.data != NULL) {
+ db.data->close(db.data, 0);
+ db.data = NULL;
+ }
+ if (db.host != NULL) {
+ db.host->close(db.host, 0);
+ db.host = NULL;
+ }
+ if (db.zone != NULL) {
+ db.zone->close(db.zone, 0);
+ db.zone = NULL;
+ }
+ if (db.client != NULL) {
+ db.client->close(db.client, 0);
+ db.client = NULL;
+ }
+
+ /* close environment */
+ if (db.dbenv != NULL) {
+ db.dbenv->close(db.dbenv, 0);
+ db.dbenv = NULL;
+ }
+}
+
+/*% Initializes, sets flags and then opens Berkeley databases. */
+
+isc_result_t
+bdb_opendb(DBTYPE db_type, DB **db_out, const char *db_name, int flags) {
+
+ int result;
+ int createFlag = 0;
+
+ /* Initialize the database. */
+ if ((result = db_create(db_out, db.dbenv, 0)) != 0) {
+ fprintf(stderr, "BDB could not initialize %s database. BDB error: %s",
+ db_name, db_strerror(result));
+ return ISC_R_FAILURE;
+ }
+
+ /* set database flags. */
+ if ((result = (*db_out)->set_flags(*db_out, flags)) != 0) {
+ fprintf(stderr, "BDB could not set flags for %s database. BDB error: %s",
+ db_name, db_strerror(result));
+ return ISC_R_FAILURE;
+ }
+
+ if (create_allowed == isc_boolean_true) {
+ createFlag = DB_CREATE;
+ }
+ /* open the database. */
+ if ((result = (*db_out)->open(*db_out, NULL, db_file, db_name, db_type,
+ createFlag, 0)) != 0) {
+ fprintf(stderr, "BDB could not open %s database in %s. BDB error: %s",
+ db_name, db_file, db_strerror(result));
+ return ISC_R_FAILURE;
+ }
+
+ return ISC_R_SUCCESS;
+}
+
+/*%
+ * parses input and adds it to the BDB database
+ * Lexer should be instantiated, and either a file or buffer opened for it.
+ * The insert_data function is used by both the add, and bulk insert
+ * operations
+ */
+
+void
+put_data(isc_boolean_t dns_data, char *input_key, char *input_data) {
+
+ int bdbres;
+ DBT key, data;
+
+ /* make sure key & data are completely empty */
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ /* if client data, setup key for insertion */
+ if (!dns_data && input_key != NULL) {
+ key.data = input_key;
+ key.size = strlen(input_key);
+ key.flags = 0;
+ }
+ /* always setup data for insertion */
+ data.data = input_data;
+ data.size = strlen(input_data);
+ data.flags = 0;
+
+ /* execute insert against appropriate database. */
+ if (dns_data) {
+ bdbres = db.data->put(db.data, NULL, &key, &data, DB_APPEND);
+ } else {
+ bdbres = db.client->put(db.client, NULL, &key, &data, 0);
+ }
+
+ /* if something went wrong, log error and quit */
+ if (bdbres != 0) {
+ fprintf(stderr, "BDB could not insert data. Error: %s",
+ db_strerror(bdbres));
+ quit(5);
+ }
+}
+
+void
+insert_data(void) {
+ unsigned int opt =
+ ISC_LEXOPT_EOL | /* Want end-of-line token. */
+ ISC_LEXOPT_EOF | /* Want end-of-file token. */
+ ISC_LEXOPT_QSTRING | /* Recognize qstrings. */
+ ISC_LEXOPT_QSTRINGMULTILINE; /* Allow multiline "" strings */
+
+ isc_result_t result;
+ isc_token_t token; /* token from lexer */
+ isc_boolean_t loop = isc_boolean_true;
+ isc_boolean_t have_czone = isc_boolean_false;
+ char data_arr[max_data_len];
+ isc_buffer_t buf;
+ char data_arr2[max_data_len];
+ isc_buffer_t buf2;
+ char data_type = 'u'; /* u =unknown, b =bad token, d/D =DNS, c/C =client IP */
+
+ /* Initialize buffers */
+ isc_buffer_init(&buf, &data_arr, max_data_len);
+ isc_buffer_init(&buf2, &data_arr2, max_data_len);
+
+ while (loop) {
+ result = isc_lex_gettoken(lexer, opt, &token);
+ if (result != ISC_R_SUCCESS)
+ goto data_cleanup;
+
+ switch(token.type) {
+ case isc_tokentype_string:
+ if (data_type == 'u') {
+ /* store data_type */
+ strncpy(&data_type, token.value.as_pointer, 1);
+ /* verify data_type was specified correctly on input */
+ if (strlen(token.value.as_pointer) > 1 || (
+ data_type != 'd' && data_type != 'D' &&
+ data_type != 'c' && data_type != 'C') ) {
+ /* if not, set to 'b' so this line is ignored. */
+ data_type = 'b';
+ }
+ } else if (data_type == 'c' || data_type == 'C') {
+ if (have_czone == isc_boolean_true) {
+ isc_buffer_putstr(&buf2, token.value.as_pointer);
+ /* add string terminator to buffer */
+ isc_buffer_putmem(&buf2, "\0", 1);
+ } else {
+ isc_buffer_putstr(&buf, token.value.as_pointer);
+ /* add string terminator to buffer */
+ isc_buffer_putmem(&buf, "\0", 1);
+ have_czone = isc_boolean_true;
+ }
+ } else {
+ isc_buffer_putstr(&buf, token.value.as_pointer);
+ isc_buffer_putstr(&buf, " ");
+ }
+ break;
+ case isc_tokentype_qstring:
+ isc_buffer_putstr(&buf, "\"");
+ isc_buffer_putstr(&buf, token.value.as_pointer);
+ isc_buffer_putstr(&buf, "\" ");
+ break;
+ case isc_tokentype_eol:
+ case isc_tokentype_eof:
+
+ if ((data_type != 'u' && isc_buffer_usedlength(&buf) > 0) || data_type == 'b') {
+ /* perform insert operation */
+ if (data_type == 'd' || data_type == 'D') {
+ /* add string terminator to buffer */
+ isc_buffer_putmem(&buf, "\0", 1);
+ put_data(isc_boolean_true, NULL, (char *) &data_arr);
+ } else if (data_type == 'c' || data_type == 'C') {
+ put_data(isc_boolean_false, (char *) &data_arr,
+ (char *) &data_arr2);
+ } else if (data_type == 'b') {
+ fprintf(stderr, "Bad / unknown token encountered on line %lu."\
+ " Skipping line.", isc_lex_getsourceline(lexer) - 1);
+ } else {
+ fprintf(stderr, "Bad / unknown db data type encountered on " \
+ "line %lu. Skipping line\n", isc_lex_getsourceline(lexer) - 1);
+ }
+ }
+
+ if (token.type == isc_tokentype_eof) {
+ loop = isc_boolean_false;
+ }
+
+ /* reset buffer for next insert */
+ isc_buffer_clear(&buf);
+ isc_buffer_clear(&buf2);
+ have_czone = isc_boolean_false;
+ data_type ='u';
+ break;
+ default:
+ data_type = 'b';
+ break;
+ }
+ }
+
+ return;
+
+ data_cleanup:
+ /* let user know we had problems */
+ fprintf(stderr, "Unknown error processing tokens during \"add\" or " \
+ "\"bulk\" operation.\nStoped processing on line %lu.",
+ isc_lex_getsourceline(lexer));
+}
+
+
+isc_result_t
+openBDB(void) {
+
+ int bdbres;
+ isc_result_t result;
+
+ /* create BDB environment */
+ /* Basically BDB allocates and assigns memory to db->dbenv */
+ bdbres = db_env_create(&db.dbenv, 0);
+ if (bdbres != 0) {
+ fprintf(stderr, "BDB environment could not be created. BDB error: %s",
+ db_strerror(bdbres));
+ result = ISC_R_FAILURE;
+ goto openBDB_cleanup;
+ }
+
+ /* open BDB environment */
+ if (create_allowed == isc_boolean_true) {
+ /* allowed to create new files */
+ bdbres = db.dbenv->open(db.dbenv, db_envdir,
+ DB_INIT_CDB | DB_INIT_MPOOL | DB_CREATE, 0);
+ } else { /* not allowed to create new files. */
+ bdbres = db.dbenv->open(db.dbenv, db_envdir,
+ DB_INIT_CDB | DB_INIT_MPOOL, 0);
+ }
+ if (bdbres != 0) {
+ fprintf(stderr, "BDB environment at '%s' could not be opened. BDB " \
+ "error: %s", db_envdir, db_strerror(bdbres));
+ result = ISC_R_FAILURE;
+ goto openBDB_cleanup;
+ }
+
+ /* open dlz_data database. */
+
+ result = bdb_opendb(DB_RECNO, &db.data, dlz_data, 0);
+ if (result != ISC_R_SUCCESS)
+ goto openBDB_cleanup;
+
+ /* open dlz_host database */
+ result = bdb_opendb(DB_BTREE, &db.host, dlz_host, DB_DUP | DB_DUPSORT);
+ if (result != ISC_R_SUCCESS)
+ goto openBDB_cleanup;
+
+ /* open dlz_zone database. */
+ result = bdb_opendb(DB_BTREE, &db.zone, dlz_zone, DB_DUP | DB_DUPSORT);
+ if (result != ISC_R_SUCCESS)
+ goto openBDB_cleanup;
+
+ /* open dlz_client database. */
+ result = bdb_opendb(DB_BTREE, &db.client, dlz_client, DB_DUP | DB_DUPSORT);
+ if (result != ISC_R_SUCCESS)
+ goto openBDB_cleanup;
+
+ /* associate the host secondary database with the primary database */
+ bdbres = db.data->associate(db.data, NULL, db.host, gethost, 0);
+ if (bdbres != 0) {
+ fprintf(stderr, "BDB could not associate %s database with %s. BDB "\
+ "error: %s", dlz_host, dlz_data, db_strerror(bdbres));
+ result = ISC_R_FAILURE;
+ goto openBDB_cleanup;
+ }
+
+ /* associate the zone secondary database with the primary database */
+ bdbres = db.data->associate(db.data, NULL, db.zone, getzone, 0);
+ if (bdbres != 0) {
+ fprintf(stderr, "BDB could not associate %s database with %s. BDB "\
+ "error: %s", dlz_zone, dlz_data, db_strerror(bdbres));
+ result = ISC_R_FAILURE;
+ goto openBDB_cleanup;
+ }
+
+ return result;
+
+ openBDB_cleanup:
+
+ bdb_cleanup();
+ return result;
+}
+
+/*% Create & open lexer to parse input data */
+
+isc_result_t
+open_lexer(void) {
+ isc_result_t result;
+
+ /* check if we already opened the lexer, if we did, return success */
+ if (lexer != NULL)
+ return ISC_R_SUCCESS;
+
+ /* allocate memory for lexer, and verify it was allocated */
+ result = isc_mem_create(0, 0, &lex_mctx);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "unexpected error creating lexer\n");
+ return result;
+ }
+
+ /* create lexer */
+ result = isc_lex_create(lex_mctx, 1500, &lexer);
+ if (result != ISC_R_SUCCESS)
+ fprintf(stderr, "unexpected error creating lexer\n");
+
+ /* set allowed commenting style */
+ isc_lex_setcomments(lexer, ISC_LEXCOMMENT_C | /* Allow C comments */
+ ISC_LEXCOMMENT_CPLUSPLUS | /* Allow C++ comments */
+ ISC_LEXCOMMENT_SHELL); /* Allow shellcomments */
+
+ isc_buffer_init(&lex_buffer, &lex_data_buf, max_data_len);
+
+ return result;
+}
+
+/*% Close the lexer, and cleanup memory */
+
+void
+close_lexer(void) {
+
+ /* If lexer is still open, close it & destroy it. */
+ if (lexer != NULL) {
+ isc_lex_close(lexer);
+ isc_lex_destroy(&lexer);
+ }
+
+ /* if lexer memory is still allocated, destroy it. */
+ if (lex_mctx != NULL)
+ isc_mem_destroy(&lex_mctx);
+}
+
+/*% Perform add operation */
+
+void
+operation_add(void) {
+ /* check for any parameters that are not allowed during add */
+ checkInvalidParam(key, "k", "for add operation");
+ checkInvalidParam(zone, "z", "for add operation");
+ checkInvalidParam(host, "h", "for add operation");
+ checkInvalidParam(c_zone, "c", "for add operation");
+ checkInvalidParam(c_ip, "i", "for add operation");
+ checkInvalidOption(list_everything, isc_boolean_true, "e",
+ "for add operation");
+
+ /* if open lexer fails it alread prints error messages. */
+ if (open_lexer() != ISC_R_SUCCESS) {
+ quit(4);
+ }
+
+ /* copy input data to buffer */
+ isc_buffer_putstr(&lex_buffer, a_data);
+
+ /* tell lexer to use buffer as input */
+ if (isc_lex_openbuffer(lexer, &lex_buffer) != ISC_R_SUCCESS) {
+ fprintf(stderr, "unexpected error opening lexer buffer");
+ quit(4);
+ }
+
+ /*common logic for "add" & "bulk" operations are handled by insert_data */
+ insert_data();
+}
+
+/*% Perform bulk insert operation */
+
+void
+operation_bulk(void) {
+ /* check for any parameters that are not allowed during bulk */
+ checkInvalidParam(key, "k", "for bulk load operation");
+ checkInvalidParam(zone, "z", "for bulk load operation");
+ checkInvalidParam(host, "h", "for bulk load operation");
+ checkInvalidParam(c_zone, "c", "for bulk load operation");
+ checkInvalidParam(c_ip, "i", "for bulk load operation");
+ checkInvalidOption(list_everything, isc_boolean_true, "e",
+ "for bulk load operation");
+
+ /* if open lexer fails it already prints error messages. */
+ if (open_lexer() != ISC_R_SUCCESS) {
+ quit(4);
+ }
+
+ if (bulk_file == NULL) {
+ if (isc_lex_openstream(lexer, stdin) != ISC_R_SUCCESS) {
+ fprintf(stderr, "unexpected error opening stdin by lexer.");
+ quit(4);
+ }
+ } else if (isc_lex_openfile(lexer, bulk_file) != ISC_R_SUCCESS) {
+ fprintf(stderr, "unexpected error opening %s by lexer.", bulk_file);
+ quit(4);
+ }
+
+ /* common logic for "add" & "bulk" operations are handled by insert_data */
+ insert_data();
+}
+
+isc_result_t
+bulk_write(char type, DB *database, DBC *dbcursor, DBT *bdbkey, DBT *bdbdata) {
+
+ int bdbres;
+ db_recno_t recNum;
+ char *retkey = NULL, *retdata;
+ size_t retklen = 0, retdlen;
+ void *p;
+
+ /* use a 5MB buffer for the bulk dump */
+ int buffer_size = 5 * 1024 * 1024;
+
+ /* try to allocate a 5 MB buffer, if we fail write err msg, die. */
+ bdbdata->data = malloc(buffer_size);
+ if (bdbdata->data == NULL) {
+ fprintf(stderr,
+ "Unable to allocate 5 MB buffer for bulk database dump\n");
+ return ISC_R_FAILURE;
+ }
+ bdbdata->ulen = buffer_size;
+ bdbdata->flags = DB_DBT_USERMEM;
+
+ /* get a cursor, make sure it worked. */
+ bdbres = database->cursor(database, NULL, &dbcursor, 0);
+ if (bdbres != 0) {
+ fprintf(stderr, "Unexpected error. BDB Error: %s\n",db_strerror(bdbres));
+ free(bdbdata->data);
+ return ISC_R_FAILURE;
+ }
+
+ /* loop and dump all data */
+ for (;;) {
+
+ /* loop through data until DB_NOTFOUND is returned */
+ bdbres = dbcursor->c_get(dbcursor, bdbkey, bdbdata,
+ DB_MULTIPLE_KEY | DB_NEXT);
+ /* if not successful did we encounter DB_NOTFOUND, or */
+ /* have a different problem. */
+ if (bdbres != 0) {
+ if (bdbres != DB_NOTFOUND) {
+ fprintf(stderr, "Unexpected error. BDB Error: %s\n",
+ db_strerror(bdbres));
+ free(bdbdata->data);
+ return ISC_R_FAILURE;
+ }
+ /* Hit DB_NOTFOUND which means end of data. */
+ break;
+ } /* end of if (bdbres !=0) */
+
+ for (DB_MULTIPLE_INIT(p, bdbdata);;) {
+ if (type == 'c')
+ DB_MULTIPLE_KEY_NEXT(p, bdbdata, retkey, retklen, retdata, retdlen);
+ else
+ DB_MULTIPLE_RECNO_NEXT(p, bdbdata, recNum, retdata, retdlen);
+
+ if (p == NULL)
+ break;
+ if (type == 'c')
+ printf("c %.*s %.*s\n",(int)retklen, retkey,(int)retdlen, retdata);
+ else
+ printf("d %.*s\n", (int)retdlen, retdata);
+ } /* end of for (DB_MULTIPLE_INIT....) */
+
+ } /* end of for (;;) */
+
+ /* free the buffer we created earlier */
+ free(bdbdata->data);
+
+ return ISC_R_SUCCESS;
+}
+
+/*%
+ * Perform listOrDelete operation
+ * if dlt == true, delete data
+ * else list data
+ */
+
+void
+operation_listOrDelete(isc_boolean_t dlt) {
+
+ int bdbres = 0;
+ DBC *curList[3];
+ DBT bdbkey, bdbdata;
+ db_recno_t recno;
+ int curIndex = 0;
+
+
+ /* verify that only allowed parameters were passed. */
+ if (dlt == isc_boolean_true) {
+ checkInvalidParam(zone, "z", "for delete operation");
+ checkInvalidParam(host, "h", "for delete operation");
+ checkInvalidOption(list_everything, isc_boolean_true, "e",
+ "for delete operation");
+ checkInvalidOption(create_allowed, isc_boolean_true, "n",
+ "for delete operation");
+ } else if (key != NULL || zone != NULL || host != NULL) {
+ checkInvalidParam(c_zone, "c", "for list when k, z or h are specified");
+ checkInvalidParam(c_ip, "i", "for list when k, z, or h are specified");
+ checkInvalidOption(list_everything, isc_boolean_true, "e",
+ "for list when k, z, or h are specified");
+ checkInvalidOption(create_allowed, isc_boolean_true, "n",
+ "for list operation");
+ } else if (c_ip != NULL || c_zone != NULL) {
+ checkInvalidOption(list_everything, isc_boolean_true, "e",
+ "for list when c or i are specified");
+ checkInvalidOption(create_allowed, isc_boolean_true, "n",
+ "for list operation");
+ }
+
+ memset(&bdbkey, 0, sizeof(bdbkey));
+ memset(&bdbdata, 0, sizeof(bdbdata));
+
+ /* Dump database in "dlzbdb" bulk format */
+ if (list_everything == isc_boolean_true) {
+ if (bulk_write('c', db.client, db.cursor, &bdbkey, &bdbdata)
+ != ISC_R_SUCCESS)
+ return;
+ memset(&bdbkey, 0, sizeof(bdbkey));
+ memset(&bdbdata, 0, sizeof(bdbdata));
+ bulk_write('d', db.data, db.cursor2, &bdbkey, &bdbdata);
+ return;
+ } /* end if (list_everything) */
+
+ /* set NULL the 2nd and 3rd positions in curList. */
+ /* that way later when add cursors to the join list */
+ /* it is already null terminated. */
+ curList[1] = curList[2] = NULL;
+
+ if (key != NULL) {
+ /* make sure other parameters weren't */
+ checkInvalidParam(zone, "z", "when k is specified");
+ checkInvalidParam(host, "h", "when k is specified");
+
+ recno = key_val;
+ bdbkey.data = &recno;
+ bdbkey.size = sizeof(recno);
+
+ if (dlt == isc_boolean_true) {
+ bdbres = db.data->del(db.data, NULL, &bdbkey, 0);
+ } else {
+ bdbdata.flags = DB_DBT_REALLOC;
+ bdbres = db.data->get(db.data, NULL, &bdbkey, &bdbdata, 0);
+
+ if (bdbres == 0) {
+ printf("KEY | DATA\n");
+ printf("%lu | %.*s\n", *(u_long *) bdbkey.data,
+ (int)bdbdata.size, (char *)bdbdata.data);
+ }
+ } /* closes else of if (dlt == isc_boolean_true) */
+ if (bdbres == DB_NOTFOUND) {
+ printf("Key not found in database");
+ }
+ } /* closes if (key != NULL) */
+
+ /* if zone is passed */
+ if (zone != NULL) {
+ /* create a cursor and make sure it worked */
+ bdbres = db.zone->cursor(db.zone, NULL, &db.cursor2, 0);
+ if (bdbres != 0) {
+ fprintf(stderr, "Unexpected error. BDB Error: %s\n",
+ db_strerror(bdbres));
+ return;
+ }
+
+ bdbkey.data = zone;
+ bdbkey.size = strlen(zone);
+ bdbres = db.cursor2->c_get(db.cursor2, &bdbkey, &bdbdata, DB_SET);
+ if (bdbres != 0) {
+ if (bdbres != DB_NOTFOUND) {
+ fprintf(stderr, "Unexpected error. BDB Error: %s\n",
+ db_strerror(bdbres));
+ } else {
+ printf("Zone not found in database");
+ }
+ return;
+ }
+
+ /* add cursor to cursor list for later use in join */
+ curList[curIndex++] = db.cursor2;
+ }
+
+ /* if host is passed */
+ if (host != NULL) {
+
+ /* create a cursor and make sure it worked. */
+ bdbres = db.host->cursor(db.host, NULL, &db.cursor3, 0);
+ if (bdbres != 0) {
+ fprintf(stderr, "Unexpected error. BDB Error: %s\n",
+ db_strerror(bdbres));
+ return;
+ }
+ bdbkey.data = host;
+ bdbkey.size = strlen(host);
+ bdbres = db.cursor3->c_get(db.cursor3, &bdbkey, &bdbdata, DB_SET);
+ if (bdbres != 0) {
+ if (bdbres != DB_NOTFOUND) {
+ fprintf(stderr, "Unexpected error. BDB Error: %s\n",
+ db_strerror(bdbres));
+ } else {
+ printf("Host not found in database");
+ }
+ return;
+ }
+
+ /* add cursor to cursor list for later use in join */
+ curList[curIndex++] = db.cursor3;
+ }
+
+
+ if (zone != NULL || host != NULL) {
+
+ /* join any cursors */
+ bdbres = db.data->join(db.data, curList, &db.cursor4, 0);
+ if (bdbres != 0) {
+ fprintf(stderr, "Unexpected error. BDB Error: %s\n",
+ db_strerror(bdbres));
+ return;
+ }
+
+ memset(&bdbkey, 0, sizeof(bdbkey));
+ bdbkey.flags = DB_DBT_REALLOC;
+ memset(&bdbdata, 0, sizeof(bdbdata));
+ bdbdata.flags = DB_DBT_REALLOC;
+
+ /* print a header to explain the output */
+ printf("KEY | DATA\n");
+ /* loop and list all results. */
+ while (bdbres == 0) {
+ /* get data */
+ bdbres = db.cursor4->c_get(db.cursor4, &bdbkey, &bdbdata, 0);
+ /* verify call had no errors */
+ if (bdbres != 0) {
+ break;
+ }
+ printf("%lu | %.*s\n", *(u_long *) bdbkey.data,
+ (int)bdbdata.size, (char *)bdbdata.data);
+ } /* closes while loop */
+ }
+
+ if (c_ip != NULL && c_zone == NULL) {
+ fprintf(stderr, "i may only be specified when c is also specified\n");
+ quit(2);
+ }
+ /* if client_zone was passed */
+ if (c_zone != NULL) {
+
+ /* create a cursor and make sure it worked. */
+ if (dlt == isc_boolean_true) {
+ /* open read-write cursor */
+ bdbres = db.client->cursor(db.client, NULL, &db.cursor,
+ DB_WRITECURSOR);
+ } else {
+ /* open read only cursor */
+ bdbres = db.client->cursor(db.client, NULL, &db.cursor, 0);
+ /* print a header to explain the output */
+ printf("CLIENT_ZONE | CLIENT_IP\n");
+ }
+
+ bdbkey.data = c_zone;
+ bdbkey.size = strlen(c_zone);
+
+ if (c_ip != NULL) {
+ bdbdata.data = c_ip;
+ bdbdata.size = strlen(c_ip);
+ bdbres = db.cursor->c_get(db.cursor, &bdbkey, &bdbdata, DB_GET_BOTH);
+ if (bdbres == DB_NOTFOUND) {
+ printf("Client zone & IP not found in database");
+ }
+ } else {
+ bdbdata.flags = DB_DBT_REALLOC;
+ bdbres = db.cursor->c_get(db.cursor, &bdbkey, &bdbdata, DB_SET);
+ if (bdbres == DB_NOTFOUND) {
+ printf("Client zone not found in database");
+ }
+ }
+
+ while (bdbres == 0) {
+ if (dlt == isc_boolean_false) {
+ printf("%.*s | %.*s\n", (int)bdbkey.size, (char *) bdbkey.data,
+ (int)bdbdata.size, (char *) bdbdata.data);
+ } else {
+ /* delete record. */
+ bdbres = db.cursor->c_del(db.cursor, 0);
+ if (bdbres != 0) {
+ fprintf(stderr, "Unexpected error. BDB Error: %s\n",
+ db_strerror(bdbres));
+ break;
+ }
+ }
+ if (c_ip != NULL) {
+ break;
+ }
+ bdbres = db.cursor->c_get(db.cursor, &bdbkey, &bdbdata, DB_NEXT_DUP);
+ if (bdbres != 0) {
+ break;
+ }
+ } /* end while loop */
+ }
+
+
+ if (bdbres != 0 && bdbres != DB_NOTFOUND) {
+ fprintf(stderr, "Unexpected error during list operation " \
+ "BDB error: %s", db_strerror(bdbres));
+ }
+
+ if (bdbkey.flags == DB_DBT_REALLOC && bdbkey.data != NULL) {
+ free(bdbkey.data);
+ }
+ if (bdbdata.flags == DB_DBT_REALLOC && bdbdata.data != NULL) {
+ free(bdbdata.data);
+ }
+}
+
+
+int
+main(int argc, char **argv) {
+
+ int ch;
+ char *endp;
+
+ /* there has to be at least 2 args, some operations require more */
+ if (argc < 2)
+ show_usage();
+
+ /* use the ISC commandline parser to get all the program arguments */
+ while ((ch= isc_commandline_parse(argc, argv, "ldesna:f:k:z:h:c:i:")) != -1) {
+ switch (ch) {
+ case 'n':
+ create_allowed = isc_boolean_true;
+ break;
+ case 'l':
+ checkOp(operation);
+ operation = list;
+ break;
+ case 'd':
+ checkOp(operation);
+ operation = dele;
+ break;
+ case 'a':
+ checkOp(operation);
+ operation = add;
+ a_data = isc_commandline_argument;
+ break;
+ case 'f':
+ checkOp(operation);
+ operation = bulk;
+ bulk_file = isc_commandline_argument;
+ break;
+ case 's':
+ checkOp(operation);
+ operation = bulk;
+ break;
+ case 'k':
+ checkParam(key, "k");
+ key = isc_commandline_argument;
+ key_val = strtoul(key, &endp, 10);
+ if (*endp != '\0' || key_val < 1) {
+ fprintf(stderr, "Error converting key to integer");
+ }
+ break;
+ case 'z':
+ checkParam(zone, "z");
+ zone = isc_commandline_argument;
+ break;
+ case 'h':
+ checkParam(host, "h");
+ host = isc_commandline_argument;
+ break;
+ case 'c':
+ checkParam(c_zone, "c");
+ c_zone = isc_commandline_argument;
+ break;
+ case 'i':
+ checkParam(c_ip, "i");
+ c_ip = isc_commandline_argument;
+ break;
+ case 'e':
+ checkOp(operation);
+ operation = list;
+ list_everything = isc_boolean_true;
+ break;
+ case '?':
+ show_usage();
+ break;
+ default:
+ /* should never reach this point */
+ fprintf(stderr, "unexpected error parsing command arguments\n");
+ quit(1);
+ break;
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ /* argc & argv have been modified, so now only "extra" parameters are */
+ /* left in argc & argv. "Extra" parameters are any parameters that were */
+ /* not passed using a command line flag. Exactly 2 args should be left. */
+ /* The first should be the BDB environment path, the second should be the */
+ /* BDB database. The BDB database path can be either relative to the */
+ /* BDB environment path, or absolute. */
+ if (argc < 2) {
+ fprintf(stderr, "Both a Berkeley DB environment and file "\
+ "must be specified");
+ quit(2);
+ } else if (argc > 2) {
+ fprintf(stderr, "Too many parameters. Check command line for errors.");
+ quit(2);
+ }
+
+ /* get db_file to operate on */
+ db_envdir = argv[0];
+ db_file = argv[1];
+
+ if (openBDB() != ISC_R_SUCCESS) {
+ /* openBDB already prints error messages, don't do it here. */
+ bdb_cleanup();
+ quit(3);
+ }
+
+ switch(operation) {
+ case list:
+ operation_listOrDelete(isc_boolean_false);
+ break;
+ case dele:
+ operation_listOrDelete(isc_boolean_true);
+ break;
+ case add:
+ operation_add();
+ break;
+ case bulk:
+ operation_bulk();
+ break;
+ default:
+ fprintf(stderr, "\nNo operation was selected. "\
+ "Select an operation (l d a f)");
+ quit(2);
+ break;
+ }
+
+ quit(0);
+}
+#endif
+
diff --git a/contrib/dlz/config.dlz.in b/contrib/dlz/config.dlz.in
new file mode 100644
index 0000000..f78e907
--- /dev/null
+++ b/contrib/dlz/config.dlz.in
@@ -0,0 +1,478 @@
+# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND 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.
+
+#
+# Shorthand. Note quoting: DLZ_DRIVER_DIR expanded in Makefile, not here.
+#
+dlzdir='${DLZ_DRIVER_DIR}'
+
+#
+# Private autoconf macro to simplify configuring drivers:
+#
+# DLZ_ADD_DRIVER(DEFINE, DRIVER, INCLUDES, LIBS)
+#
+# where:
+# DEFINE is FOO (to define -DDLZ_FOO)
+# DRIVER is dlz_foo_driver (sources without the .c)
+# INCLUDES is any necessary include definitions
+# LIBS is any necessary library definitions
+#
+AC_DEFUN(DLZ_ADD_DRIVER, [
+ USE_DLZ="$USE_DLZ -DDLZ_$1"
+ for i in $2
+ do
+ DLZ_DRIVER_SRCS="$DLZ_DRIVER_SRCS $dlzdir/$i.c"
+ DLZ_DRIVER_OBJS="$DLZ_DRIVER_OBJS $i.$O"
+ done
+ if test -n "$3"
+ then
+ DLZ_DRIVER_INCLUDES="$DLZ_DRIVER_INCLUDES $3"
+ fi
+ if test -n "$4"
+ then
+ DLZ_DRIVER_LIBS="$DLZ_DRIVER_LIBS $4"
+ fi
+])
+
+#
+# Check for the various DLZ drivers
+#
+
+#
+# Was --with-dlz-postgres specified?
+#
+
+AC_MSG_CHECKING(for Postgres DLZ driver)
+AC_ARG_WITH(dlz_postgres,
+[ --with-dlz-postgres[=PATH] Build with Postgres DLZ driver [yes|no|path].
+ (Required to use Postgres with DLZ)],
+ use_dlz_postgres="$withval", use_dlz_postgres="no")
+
+if test "$use_dlz_postgres" = "yes"
+then
+ # User did not specify a path - guess it
+ # Ask Postgres to tell us where it is
+
+ AC_PATH_PROGS(PG_CONFIG, pg_config, [not found])
+
+ if test "$PG_CONFIG" != "not found"
+ then
+ use_dlz_postgres=`$PG_CONFIG --includedir`
+ use_dlz_postgres_lib=`$PG_CONFIG --libdir`
+ fi
+fi
+
+if test "$use_dlz_postgres" = "yes"
+then
+ # User did not specify path and Postgres didn't say - guess it
+
+ pgdirs="/usr /usr/local /usr/local/pgsql /usr/pkg"
+ for d in $pgdirs
+ do
+ if test -f $d/include/libpq-fe.h
+ then
+ use_dlz_postgres=$d/include
+ use_dlz_postgres_lib=$d/lib
+ break
+ fi
+ done
+fi
+
+if test "$use_dlz_postgres" = "yes"
+then
+ # Still no joy, give up
+
+ AC_MSG_RESULT(not found)
+ AC_MSG_ERROR(
+[No pg_config and PostgreSQL was not found in any of $pgdirs; use --with-dlz-postgres=/path or put pg_config in your path])
+fi
+
+case "$use_dlz_postgres" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ DLZ_ADD_DRIVER(POSTGRES, dlz_postgres_driver,
+ [-I$use_dlz_postgres],
+ [-L$use_dlz_postgres_lib -lpq])
+
+ AC_MSG_RESULT(
+[using PostgreSQL from $use_dlz_postgres_lib and $use_dlz_postgres])
+ ;;
+esac
+
+
+#
+# Was --with-dlz-mysql specified?
+#
+
+AC_MSG_CHECKING(for MySQL DLZ driver)
+AC_ARG_WITH(dlz_mysql,
+[ --with-dlz-mysql[=PATH] Build with MySQL DLZ driver [yes|no|path].
+ (Required to use MySQL with DLZ)],
+ use_dlz_mysql="$withval", use_dlz_mysql="no")
+
+mysql_include=""
+mysql_lib=""
+if test "$use_dlz_mysql" = "yes"
+then
+ # User did not specify a path - guess it
+ mysqldirs="/usr /usr/local /usr/local/mysql /usr/pkg"
+ for d in $mysqldirs
+ do
+ if test -f $d/include/mysql/mysql.h
+ then
+ use_dlz_mysql=$d
+ mysql_include=$d/include/mysql
+ if test -d $d/lib/mysql
+ then
+ mysql_lib=$d/lib/mysql
+ else
+ mysql_lib=$d/lib
+ fi
+ break
+ elif test -f $d/include/mysql.h
+ then
+ use_dlz_mysql=$d
+ mysql_include=$d/include
+ if test -d $d/lib/mysql
+ then
+ mysql_lib=$d/lib/mysql
+ else
+ mysql_lib=$d/lib
+ fi
+ break
+ fi
+ done
+elif test "$use_dlz_mysql" != "no"
+then
+ d=$use_dlz_mysql
+ if test -f $d/include/mysql/mysql.h
+ then
+ mysql_include=$d/include/mysql
+ if test -d $d/lib/mysql
+ then
+ mysql_lib=$d/lib/mysql
+ else
+ mysql_lib=$d/lib
+ fi
+ elif test -f $d/include/mysql.h
+ then
+ mysql_include=$d/include
+ if test -d $d/lib/mysql
+ then
+ mysql_lib=$d/lib/mysql
+ else
+ mysql_lib=$d/lib
+ fi
+ fi
+fi
+
+if test "$use_dlz_mysql" = "yes"
+then
+ AC_MSG_RESULT(not found)
+ AC_MSG_ERROR(
+[MySQL was not found in any of $mysqldirs; use --with-dlz-mysql=/path])
+fi
+
+case "$use_dlz_mysql" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ DLZ_ADD_DRIVER(MYSQL, dlz_mysql_driver,
+ [-I${mysql_include}],
+ [-L${mysql_lib} -lmysqlclient -lz -lcrypt -lm])
+
+ AC_MSG_RESULT(
+[using mysql from ${mysql_lib} and ${mysql_include}])
+ ;;
+esac
+
+
+#
+# Was --with-dlz-bdb specified?
+#
+
+AC_MSG_CHECKING(for Berkeley DB DLZ driver)
+AC_ARG_WITH(dlz_bdb,
+[ --with-dlz-bdb[=PATH] Build with Berkeley DB DLZ driver [yes|no|path].
+ (Required to use Berkeley DB with DLZ)],
+ use_dlz_bdb="$withval", use_dlz_bdb="no")
+
+case "$use_dlz_bdb" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ if test "$use_dlz_bdb" = "yes"
+ then
+ # User did not specify a path - guess directories
+ bdbdirs="/usr/local /usr/pkg /usr"
+ elif test -d "$use_dlz_bdb"
+ then
+ # User specified directory and it exists
+ bdbdirs="$use_dlz_bdb"
+ else
+ AC_MSG_RESULT(not found)
+ AC_MSG_ERROR([path $use_dlz_bdb does not exist])
+ bdbdirs=""
+ fi
+
+ # Use path we were given or guessed. This is insanely
+ # complicated because we have to search for a bunch of
+ # platform-specific variations and have to check
+ # separately for include and library directories.
+
+ # Set both to yes, so we can check them later
+ dlz_bdb_inc="yes"
+ dlz_bdb_libs="yes"
+
+ for dd in $bdbdirs
+ do
+ # Skip nonexistant directories
+ if test ! -d "$dd"
+ then
+ continue
+ fi
+
+ # Check other locations for includes.
+ # Order is important (sigh).
+
+ bdb_incdirs="/ /db42/ /db41/ /db4/ /db/"
+ for d in $bdb_incdirs
+ do
+ if test -f "$dd/include${d}db.h"
+ then
+ dlz_bdb_inc="-I$dd/include${d}"
+ break
+ fi
+ done
+
+ # Give up on this directory if we couldn't
+ # find the include subdir
+
+ if test "$dlz_bdb_inc" = "yes"
+ then
+ continue
+ fi
+
+ # Look for libname other than libdb.so.
+ # Order is important (sigh).
+
+ bdb_libnames="db42 db-4.2 db41 db-4.1 db"
+ for d in $bdb_libnames
+ do
+ if test -f "$dd/lib/lib${d}.so"
+ then
+ if test "$dd" != "/usr"
+ then
+ dlz_bdb_libs="-L${dd}/lib "
+ else
+ dlz_bdb_libs=""
+ fi
+ dlz_bdb_libs="${dlz_bdb_libs}-l${d}"
+ break
+ fi
+ done
+
+ # If we found both incdir and lib, we're done
+ if test "$dlz_bdb_libs" != "yes"
+ then
+ break
+ fi
+
+ # Otherwise, we're starting over
+
+ dlz_bdb_inc="yes"
+ dlz_bdb_libs="yes"
+ done
+
+ # Done searching, now make sure we got everything.
+
+ if test "$dlz_bdb_inc" = "yes"
+ then
+ AC_MSG_RESULT(not found)
+ AC_MSG_ERROR([could not find Berkeley DB include directory])
+ fi
+
+ if test "$dlz_bdb_libs" = "yes"
+ then
+ AC_MSG_RESULT(not found)
+ AC_MSG_ERROR([could not find Berkeley DB library])
+ fi
+
+ DLZ_ADD_DRIVER(BDB, dlz_bdb_driver dlz_bdbhpt_driver,
+ [$dlz_bdb_inc], [$dlz_bdb_libs])
+
+ AC_MSG_RESULT([using Berkeley DB: $dlz_bdb_inc $dlz_bdb_libs])
+
+ AC_CONFIG_FILES([contrib/dlz/bin/dlzbdb/Makefile])
+ ;;
+esac
+
+
+#
+# Was --with-dlz-filesystem specified?
+#
+
+AC_MSG_CHECKING(for file system DLZ driver)
+AC_ARG_WITH(dlz_filesystem,
+[ --with-dlz-filesystem[=PATH] Build with filesystem DLZ driver [yes|no].
+ (Required to use file system driver with DLZ)],
+ use_dlz_filesystem="$withval", use_dlz_filesystem="no")
+
+case "$use_dlz_filesystem" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ DLZ_ADD_DRIVER(FILESYSTEM, dlz_filesystem_driver)
+
+ AC_MSG_RESULT(yes)
+ ;;
+esac
+
+
+#
+# Was --with-dlz-ldap specified?
+#
+
+AC_MSG_CHECKING(for LDAP DLZ driver)
+AC_ARG_WITH(dlz_ldap,
+[ --with-dlz-ldap[=PATH] Build with LDAP DLZ driver [yes|no|path].
+ (Required to use LDAP with DLZ)],
+ use_dlz_ldap="$withval", use_dlz_ldap="no")
+
+if test "$use_dlz_ldap" = "yes"
+then
+ # User did not specify a path - guess it
+ ldapdirs="/usr /usr/local /usr/pkg"
+ for d in $ldapdirs
+ do
+ if test -f $d/include/ldap.h
+ then
+ use_dlz_ldap=$d
+ break
+ fi
+ done
+fi
+
+if test "$use_dlz_ldap" = "yes"
+then
+ AC_MSG_RESULT(not found)
+ AC_MSG_ERROR(
+[LDAP headers were not found in any of $ldapdirs; use --with-dlz-ldap=/path])
+fi
+
+case "$use_dlz_ldap" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ DLZ_ADD_DRIVER(LDAP, dlz_ldap_driver,
+ [-I$use_dlz_ldap/include],
+ [-L$use_dlz_ldap/lib -lldap -llber])
+
+ AC_MSG_RESULT(
+[using LDAP from $use_dlz_ldap/lib and $use_dlz_ldap/include])
+ ;;
+esac
+
+
+#
+# Was --with-dlz-odbc specified?
+#
+
+AC_MSG_CHECKING(for ODBC DLZ driver)
+AC_ARG_WITH(dlz_odbc,
+[ --with-dlz-odbc[=PATH] Build with ODBC DLZ driver [yes|no|path].
+ (Required to use ODBC with DLZ)],
+ use_dlz_odbc="$withval", use_dlz_odbc="no")
+
+if test "$use_dlz_odbc" = "yes"
+then
+ # User did not specify a path - guess it
+ odbcdirs="/usr /usr/local /usr/pkg"
+ for d in $odbcdirs
+ do
+ if test -f $d/include/sql.h -a -f $d/lib/libodbc.a
+ then
+ use_dlz_odbc=$d
+ break
+ fi
+ done
+fi
+
+case "$use_dlz_odbc" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ yes)
+ AC_MSG_RESULT(not found)
+ AC_MSG_ERROR(
+[ODBC headers were not found in any of $odbcdirs; use --with-dlz-odbc=/path])
+ ;;
+ *)
+ DLZ_ADD_DRIVER(ODBC, dlz_odbc_driver,
+ [-I$use_dlz_odbc/include],
+ [-L$use_dlz_odbc/lib -lodbc])
+
+ AC_MSG_RESULT([using ODBC from $use_dlz_odbc])
+ ;;
+esac
+
+
+#
+# Was --with-dlz-stub specified?
+#
+
+AC_MSG_CHECKING(for stub DLZ driver)
+AC_ARG_WITH(dlz_stub,
+[ --with-dlz-stub[=PATH] Build with stub DLZ driver [yes|no].
+ (Required to use stub driver with DLZ)],
+ use_dlz_stub="$withval", use_dlz_stub="no")
+
+case "$use_dlz_stub" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+
+ DLZ_ADD_DRIVER(STUB, dlz_stub_driver)
+
+ AC_MSG_RESULT(yes)
+ ;;
+esac
+
+
+# Add any additional DLZ drivers here.
+
+#
+# Finally, some generic stuff that applies to all drivers, assuming
+# we're compiling DLZ at all.
+#
+if test -n "$USE_DLZ"
+then
+ #
+ # Where to find DLZ driver header files.
+ #
+ DLZ_DRIVER_INCLUDES="-I$dlzdir/include $DLZ_DRIVER_INCLUDES"
+
+ #
+ # Initialization and shutdown wrappers, helper functions.
+ #
+ DLZ_DRIVER_SRCS="$dlzdir/dlz_drivers.c $dlzdir/sdlz_helper.c $DLZ_DRIVER_SRCS"
+ DLZ_DRIVER_OBJS="dlz_drivers.$O sdlz_helper.$O $DLZ_DRIVER_OBJS"
+fi
diff --git a/contrib/dlz/drivers/dlz_bdb_driver.c b/contrib/dlz/drivers/dlz_bdb_driver.c
new file mode 100644
index 0000000..5aa96a5
--- /dev/null
+++ b/contrib/dlz/drivers/dlz_bdb_driver.c
@@ -0,0 +1,797 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef DLZ_BDB
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <dns/log.h>
+#include <dns/sdlz.h>
+#include <dns/result.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+
+#include <dlz/dlz_bdb_driver.h>
+
+#include <db.h>
+
+static dns_sdlzimplementation_t *dlz_bdb = NULL;
+
+/* should the bdb driver use threads. */
+#ifdef ISC_PLATFORM_USETHREADS
+#define bdb_threads DB_THREAD
+#else
+#define bdb_threads 0
+#endif
+
+/* BDB database names */
+#define dlz_data "dns_data"
+#define dlz_zone "dns_zone"
+#define dlz_host "dns_host"
+#define dlz_client "dns_client"
+
+/*%
+ * This structure contains all the Berkeley DB handles
+ * for this instance of the BDB driver.
+ */
+
+typedef struct bdb_instance {
+ DB_ENV *dbenv; /*%< BDB environment */
+ DB *data; /*%< dns_data database handle */
+ DB *zone; /*%< zone database handle */
+ DB *host; /*%< host database handle */
+ DB *client; /*%< client database handle */
+ isc_mem_t *mctx; /*%< memory context */
+
+} bdb_instance_t;
+
+typedef struct parsed_data {
+ char *zone;
+ char *host;
+ char *type;
+ int ttl;
+ char *data;
+} parsed_data_t;
+
+
+/* forward reference */
+
+static isc_result_t
+bdb_findzone(void *driverarg, void *dbdata, const char *name);
+
+/*%
+ * Parses the DBT from the Berkeley DB into a parsed_data record
+ * The parsed_data record should be allocated before and passed into the
+ * bdb_parse_data function. The char (type & data) fields should not
+ * be "free"d as that memory is part of the DBT data field. It will be
+ * "free"d when the DBT is freed.
+ */
+
+static isc_result_t
+bdb_parse_data(char *in, parsed_data_t *pd) {
+
+ char *endp, *ttlStr;
+ char *tmp = in;
+ char *lastchar = (char *) &tmp[strlen(tmp) + 1];
+
+ /*%
+ * String should be formated as:
+ * zone(a space)host(a space)ttl(a space)type(a space)remaining data
+ * examples:
+ * example.com www 10 A 127.0.0.1
+ * example.com mail 10 A 127.0.0.2
+ * example.com @ 10 MX 20 mail.example.com
+ */
+
+ /* save pointer to zone */
+ pd->zone = tmp;
+
+ /* find space after zone and change it to a '\0' */
+ tmp = strchr(tmp, ' ');
+ /* verify we found a space */
+ if (tmp == NULL)
+ return ISC_R_FAILURE;
+ /* change the space to a null (string terminator) */
+ tmp[0] = '\0';
+ /* make sure it is safe to increment pointer */
+ if (++tmp > lastchar)
+ return ISC_R_FAILURE;
+
+ /* save pointer to host */
+ pd->host = tmp;
+
+ /* find space after type and change it to a '\0' */
+ tmp = strchr(tmp, ' ');
+ /* verify we found a space */
+ if (tmp == NULL)
+ return ISC_R_FAILURE;
+ /* change the space to a null (string terminator) */
+ tmp[0] = '\0';
+ /* make sure it is safe to increment pointer */
+ if (++tmp > lastchar)
+ return ISC_R_FAILURE;
+
+ /* save pointer to dns type */
+ pd->type = tmp;
+
+ /* find space after type and change it to a '\0' */
+ tmp = strchr(tmp, ' ');
+ /* verify we found a space */
+ if (tmp == NULL)
+ return ISC_R_FAILURE;
+ /* change the space to a null (string terminator) */
+ tmp[0] = '\0';
+ /* make sure it is safe to increment pointer */
+ if (++tmp > lastchar)
+ return ISC_R_FAILURE;
+
+ /* save pointer to dns ttl */
+ ttlStr = tmp;
+
+ /* find space after ttl and change it to a '\0' */
+ tmp = strchr(tmp, ' ');
+ /* verify we found a space */
+ if (tmp == NULL)
+ return ISC_R_FAILURE;
+ /* change the space to a null (string terminator) */
+ tmp[0] = '\0';
+ /* make sure it is safe to increment pointer */
+ if (++tmp > lastchar)
+ return ISC_R_FAILURE;
+
+ /* save pointer to remainder of DNS data */
+ pd->data = tmp;
+
+ /* convert ttl string to integer */
+ pd->ttl = strtol(ttlStr, &endp, 10);
+ if (*endp != '\0' || pd->ttl < 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "BDB driver ttl must be a postive number");
+ return ISC_R_FAILURE;
+ }
+
+ /* if we get this far everything should have worked. */
+ return ISC_R_SUCCESS;
+}
+
+/*
+ * DLZ methods
+ */
+
+static isc_result_t
+bdb_allowzonexfr(void *driverarg, void *dbdata, const char *name,
+ const char *client)
+{
+ isc_result_t result;
+ bdb_instance_t *db = (bdb_instance_t *) dbdata;
+ DBC *client_cursor = NULL;
+ DBT key, data;
+
+ /* check to see if we are authoritative for the zone first. */
+ result = bdb_findzone(driverarg, dbdata, name);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_NOTFOUND);
+
+ memset(&key, 0, sizeof(DBT));
+ key.flags = DB_DBT_MALLOC;
+ key.data = strdup(name);
+ if (key.data == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto xfr_cleanup;
+ }
+ key.size = strlen(key.data);
+
+ memset(&data, 0, sizeof(DBT));
+ data.flags = DB_DBT_MALLOC;
+ data.data = strdup(client);
+ if (data.data == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto xfr_cleanup;
+ }
+ data.size = strlen(data.data);
+
+ /* get a cursor to loop through zone data */
+ if (db->client->cursor(db->client, NULL, &client_cursor, 0) != 0) {
+ result = ISC_R_FAILURE;
+ goto xfr_cleanup;
+ }
+
+ switch(client_cursor->c_get(client_cursor, &key, &data, DB_GET_BOTH)) {
+ case DB_NOTFOUND:
+ case DB_SECONDARY_BAD:
+ result = ISC_R_NOTFOUND;
+ break;
+ case 0:
+ result = ISC_R_SUCCESS;
+ break;
+ default:
+ result = ISC_R_FAILURE;
+ }
+
+ xfr_cleanup:
+
+ /* free any memory duplicate string in the key field */
+ if (key.data != NULL)
+ free(key.data);
+
+ /* free any memory allocated to the data field. */
+ if (data.data != NULL)
+ free(data.data);
+
+ /* get rid of zone_cursor */
+ if (client_cursor != NULL)
+ client_cursor->c_close(client_cursor);
+
+ return result;
+
+}
+
+static isc_result_t
+bdb_allnodes(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzallnodes_t *allnodes)
+{
+
+ isc_result_t result = ISC_R_NOTFOUND;
+ bdb_instance_t *db = (bdb_instance_t *) dbdata;
+ DBC *zone_cursor = NULL;
+ DBT key, data;
+ int flags;
+ int bdbres;
+ parsed_data_t pd;
+ char *tmp = NULL, *tmp_zone;
+
+ UNUSED(driverarg);
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+
+ key.data = tmp_zone = strdup(zone);
+
+ if (key.data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ key.size = strlen(key.data);
+
+ /* get a cursor to loop through zone data */
+ if (db->zone->cursor(db->zone, NULL, &zone_cursor, 0) != 0) {
+ result = ISC_R_FAILURE;
+ goto allnodes_cleanup;
+ }
+
+ flags = DB_SET;
+
+ while ((bdbres = zone_cursor->c_get(zone_cursor, &key, &data,
+ flags)) == 0) {
+
+ flags = DB_NEXT_DUP;
+
+ tmp = realloc(tmp, data.size + 1);
+ if (tmp == NULL)
+ goto allnodes_cleanup;
+
+ strncpy(tmp, data.data, data.size);
+ tmp[data.size] = '\0';
+
+ if (bdb_parse_data(tmp, &pd) != ISC_R_SUCCESS)
+ goto allnodes_cleanup;
+
+ result = dns_sdlz_putnamedrr(allnodes, pd.host, pd.type,
+ pd.ttl, pd.data);
+ if (result != ISC_R_SUCCESS)
+ goto allnodes_cleanup;
+
+ } /* end while loop */
+
+ allnodes_cleanup:
+
+ if (tmp != NULL)
+ free(tmp);
+
+ /* free any memory duplicate string in the key field */
+ if (tmp_zone != NULL)
+ free(tmp_zone);
+
+ /* get rid of zone_cursor */
+ if (zone_cursor != NULL)
+ zone_cursor->c_close(zone_cursor);
+
+ return result;
+
+}
+
+/*%
+ * Performs BDB cleanup.
+ * Used by bdb_create if there is an error starting up.
+ * Used by bdb_destroy when the driver is shutting down.
+ */
+
+static void
+bdb_cleanup(bdb_instance_t *db) {
+
+ isc_mem_t *mctx;
+
+ /* close databases */
+ if (db->data != NULL)
+ db->data->close(db->data, 0);
+ if (db->host != NULL)
+ db->host->close(db->host, 0);
+ if (db->zone != NULL)
+ db->zone->close(db->zone, 0);
+ if (db->client != NULL)
+ db->client->close(db->client, 0);
+
+ /* close environment */
+ if (db->dbenv != NULL)
+ db->dbenv->close(db->dbenv, 0);
+
+ /* cleanup memory */
+ if (db->mctx != NULL) {
+ /* save mctx for later */
+ mctx = db->mctx;
+ /* return, and detach the memory */
+ isc_mem_put(mctx, db, sizeof(bdb_instance_t));
+ isc_mem_detach(&mctx);
+ }
+}
+
+static isc_result_t
+bdb_findzone(void *driverarg, void *dbdata, const char *name)
+{
+
+ isc_result_t result;
+ bdb_instance_t *db = (bdb_instance_t *) dbdata;
+ DBC *zone_cursor = NULL;
+ DBT key, data;
+
+ UNUSED(driverarg);
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+ data.flags = DB_DBT_MALLOC;
+
+ key.data = strdup(name);
+
+ if (key.data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ key.size = strlen(key.data);
+
+ /* get a cursor to loop through zone data */
+ if (db->zone->cursor(db->zone, NULL, &zone_cursor, 0) != 0) {
+ result = ISC_R_NOTFOUND;
+ goto findzone_cleanup;
+ }
+
+ switch(zone_cursor->c_get(zone_cursor, &key, &data, DB_SET)) {
+ case DB_NOTFOUND:
+ case DB_SECONDARY_BAD:
+ result = ISC_R_NOTFOUND;
+ break;
+ case 0:
+ result = ISC_R_SUCCESS;
+ break;
+ default:
+ result = ISC_R_FAILURE;
+ }
+
+ findzone_cleanup:
+
+ /* free any memory duplicate string in the key field */
+ if (key.data != NULL)
+ free(key.data);
+
+ /* free any memory allocated to the data field. */
+ if (data.data != NULL)
+ free(data.data);
+
+ /* get rid of zone_cursor */
+ if (zone_cursor != NULL)
+ zone_cursor->c_close(zone_cursor);
+
+ return result;
+}
+
+static isc_result_t
+bdb_lookup(const char *zone, const char *name, void *driverarg,
+ void *dbdata, dns_sdlzlookup_t *lookup)
+{
+
+ isc_result_t result = ISC_R_NOTFOUND;
+ bdb_instance_t *db = (bdb_instance_t *) dbdata;
+ DBC *zone_cursor = NULL;
+ DBC *host_cursor = NULL;
+ DBC *join_cursor = NULL;
+ DBT key, data;
+ DBC *cur_arr[3];
+ int bdbres;
+ parsed_data_t pd;
+ char *tmp_zone, *tmp_host = NULL;
+ char *tmp = NULL;
+
+ UNUSED(driverarg);
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+
+ /* set zone key */
+ key.data = tmp_zone = strdup(zone);
+ if (key.data == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto lookup_cleanup;
+ }
+ key.size = strlen(key.data);
+
+ /* get a cursor to loop through zone data */
+ if (db->zone->cursor(db->zone, NULL, &zone_cursor, 0) != 0) {
+ result = ISC_R_FAILURE;
+ goto lookup_cleanup;
+ }
+
+ /* initialize zone_cursor with zone_key */
+ if (zone_cursor->c_get(zone_cursor, &key, &data, DB_SET) != 0) {
+ result = ISC_R_NOTFOUND;
+ goto lookup_cleanup;
+ }
+
+ /* set host key */
+ key.data = tmp_host = strdup(name);
+ if (key.data == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto lookup_cleanup;
+ }
+ key.size = strlen(key.data);
+
+ /* get a cursor to loop through host data */
+ if (db->host->cursor(db->host, NULL, &host_cursor, 0) != 0) {
+ result = ISC_R_FAILURE;
+ goto lookup_cleanup;
+ }
+
+ /* initialize host_cursor with host_key */
+ if (host_cursor->c_get(host_cursor, &key, &data, DB_SET) != 0) {
+ result = ISC_R_NOTFOUND;
+ goto lookup_cleanup;
+ }
+
+ cur_arr[0] = zone_cursor;
+ cur_arr[1] = host_cursor;
+ cur_arr[2] = NULL;
+
+ db->data->join(db->data, cur_arr, &join_cursor, 0);
+
+ while ((bdbres = join_cursor->c_get(join_cursor, &key,
+ &data, 0)) == 0) {
+
+ tmp = realloc(tmp, data.size + 1);
+ if (tmp == NULL)
+ goto lookup_cleanup;
+
+ strncpy(tmp, data.data, data.size);
+ tmp[data.size] = '\0';
+
+ if (bdb_parse_data(tmp, &pd) != ISC_R_SUCCESS)
+ goto lookup_cleanup;
+
+ result = dns_sdlz_putrr(lookup, pd.type, pd.ttl, pd.data);
+
+ if (result != ISC_R_SUCCESS)
+ goto lookup_cleanup;
+ } /* end while loop */
+
+ lookup_cleanup:
+
+ if (tmp != NULL)
+ free(tmp);
+ if (tmp_zone != NULL)
+ free(tmp_zone);
+ if (tmp_host != NULL)
+ free(tmp_host);
+
+ /* get rid of the joined cusor */
+ if (join_cursor != NULL)
+ join_cursor->c_close(join_cursor);
+
+ /* get rid of zone_cursor */
+ if (zone_cursor != NULL)
+ zone_cursor->c_close(zone_cursor);
+
+ /* get rid of host_cursor */
+ if (host_cursor != NULL)
+ host_cursor->c_close(host_cursor);
+
+ return result;
+
+ return ISC_R_NOTFOUND;
+}
+
+
+/*% Initializes, sets flags and then opens Berkeley databases. */
+
+static isc_result_t
+bdb_opendb(DB_ENV *db_env, DBTYPE db_type, DB **db, const char *db_name,
+ char *db_file, int flags) {
+
+ int result;
+
+ /* Initialize the database. */
+ if ((result = db_create(db, db_env, 0)) != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "BDB could not initialize %s database. "
+ "BDB error: %s",
+ db_name, db_strerror(result));
+ return ISC_R_FAILURE;
+ }
+
+ /* set database flags. */
+ if ((result = (*db)->set_flags(*db, flags)) != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "BDB could not set flags for %s database. "
+ "BDB error: %s",
+ db_name, db_strerror(result));
+ return ISC_R_FAILURE;
+ }
+
+ /* open the database. */
+ if ((result = (*db)->open(*db, NULL, db_file, db_name, db_type,
+ DB_RDONLY | bdb_threads, 0)) != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "BDB could not open %s database in %s. "
+ "BDB error: %s",
+ db_name, db_file, db_strerror(result));
+ return ISC_R_FAILURE;
+ }
+
+ return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+bdb_create(const char *dlzname, unsigned int argc, char *argv[],
+ void *driverarg, void **dbdata)
+{
+ isc_result_t result;
+ int bdbres;
+ bdb_instance_t *db = NULL;
+
+ UNUSED(dlzname);
+ UNUSED(driverarg);
+
+ /* verify we have 3 arg's passed to the driver */
+ if (argc != 3) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Berkeley DB driver requires at least "
+ "2 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* allocate and zero memory for driver structure */
+ db = isc_mem_get(ns_g_mctx, sizeof(bdb_instance_t));
+ if (db == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Could not allocate memory for "
+ "database instance object.");
+ return (ISC_R_NOMEMORY);
+ }
+ memset(db, 0, sizeof(bdb_instance_t));
+
+ /* attach to the memory context */
+ isc_mem_attach(ns_g_mctx, &db->mctx);
+
+ /* create BDB environment
+ * Basically BDB allocates and assigns memory to db->dbenv
+ */
+ bdbres = db_env_create(&db->dbenv, 0);
+ if (bdbres != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "BDB environment could not be created. "
+ "BDB error: %s",
+ db_strerror(bdbres));
+ result = ISC_R_FAILURE;
+ goto init_cleanup;
+ }
+
+ /* open BDB environment */
+ bdbres = db->dbenv->open(db->dbenv, argv[1],
+ DB_INIT_CDB | DB_INIT_MPOOL |
+ bdb_threads | DB_CREATE,
+ 0);
+ if (bdbres != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "BDB environment at '%s' could not be opened. "
+ "BDB error: %s",
+ argv[1], db_strerror(bdbres));
+ result = ISC_R_FAILURE;
+ goto init_cleanup;
+ }
+
+ /* open dlz_data database. */
+ result = bdb_opendb(db->dbenv, DB_UNKNOWN, &db->data,
+ dlz_data, argv[2], 0);
+ if (result != ISC_R_SUCCESS)
+ goto init_cleanup;
+
+ /* open dlz_host database. */
+ result = bdb_opendb(db->dbenv, DB_UNKNOWN, &db->host,
+ dlz_host, argv[2],
+ DB_DUP | DB_DUPSORT);
+ if (result != ISC_R_SUCCESS)
+ goto init_cleanup;
+
+ /* open dlz_zone database. */
+ result = bdb_opendb(db->dbenv, DB_UNKNOWN, &db->zone,
+ dlz_zone, argv[2],
+ DB_DUP | DB_DUPSORT);
+ if (result != ISC_R_SUCCESS)
+ goto init_cleanup;
+
+ /* open dlz_client database. */
+ result = bdb_opendb(db->dbenv, DB_UNKNOWN, &db->client,
+ dlz_client, argv[2], DB_DUP | DB_DUPSORT);
+ if (result != ISC_R_SUCCESS)
+ goto init_cleanup;
+
+ /* associate the host secondary database with the primary database */
+ bdbres = db->data->associate(db->data, NULL, db->host, NULL, 0);
+ if (bdbres != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "BDB could not associate %s database with %s. "
+ "BDB error: %s",
+ dlz_host, dlz_data, db_strerror(bdbres));
+ result = ISC_R_FAILURE;
+ goto init_cleanup;
+ }
+
+ /* associate the zone secondary database with the primary database */
+ bdbres = db->data->associate(db->data, NULL, db->zone, NULL, 0);
+ if (bdbres != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "BDB could not associate %s database with %s. "
+ "BDB error: %s",
+ dlz_zone, dlz_data, db_strerror(bdbres));
+ result = ISC_R_FAILURE;
+ goto init_cleanup;
+ }
+
+ *dbdata = db;
+
+ return(ISC_R_SUCCESS);
+
+ init_cleanup:
+
+ bdb_cleanup(db);
+ return result;
+}
+
+static void
+bdb_destroy(void *driverarg, void *dbdata)
+{
+ UNUSED(driverarg);
+
+ bdb_cleanup((bdb_instance_t *) dbdata);
+}
+
+/* bdb_authority not needed as authority data is returned by lookup */
+static dns_sdlzmethods_t dlz_bdb_methods = {
+ bdb_create,
+ bdb_destroy,
+ bdb_findzone,
+ bdb_lookup,
+ NULL,
+ bdb_allnodes,
+ bdb_allowzonexfr
+};
+
+/*%
+ * Wrapper around dns_sdlzregister().
+ */
+isc_result_t
+dlz_bdb_init(void) {
+ isc_result_t result;
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Registering DLZ bdb driver.");
+
+ result = dns_sdlzregister("bdb", &dlz_bdb_methods, NULL,
+ DNS_SDLZFLAG_RELATIVEOWNER |
+ DNS_SDLZFLAG_RELATIVERDATA |
+ DNS_SDLZFLAG_THREADSAFE,
+ ns_g_mctx, &dlz_bdb);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+
+ return result;
+}
+
+/*%
+ * Wrapper around dns_sdlzunregister().
+ */
+void
+dlz_bdb_clear(void) {
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Unregistering DLZ bdb driver.");
+
+ if (dlz_bdb != NULL)
+ dns_sdlzunregister(&dlz_bdb);
+}
+
+#endif
diff --git a/contrib/dlz/drivers/dlz_bdbhpt_driver.c b/contrib/dlz/drivers/dlz_bdbhpt_driver.c
new file mode 100644
index 0000000..da5b235
--- /dev/null
+++ b/contrib/dlz/drivers/dlz_bdbhpt_driver.c
@@ -0,0 +1,860 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef DLZ_BDB
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <dns/log.h>
+#include <dns/sdlz.h>
+#include <dns/result.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+
+#include <dlz/dlz_bdbhpt_driver.h>
+
+#include <db.h>
+
+static dns_sdlzimplementation_t *dlz_bdbhpt = NULL;
+
+/* should the bdb driver use threads. */
+#ifdef ISC_PLATFORM_USETHREADS
+#define bdbhpt_threads DB_THREAD
+#else
+#define bdbhpt_threads 0
+#endif
+
+/* bdbhpt database names */
+#define dlz_data "dns_data"
+#define dlz_zone "dns_zone"
+#define dlz_xfr "dns_xfr"
+#define dlz_client "dns_client"
+
+ /* This structure contains all the Berkeley DB handles
+ * for this instance of the bdbhpt driver.
+ */
+
+typedef struct bdbhpt_instance {
+ DB_ENV *dbenv; /*%< bdbhpt environment */
+ DB *data; /*%< dns_data database handle */
+ DB *zone; /*%< zone database handle */
+ DB *xfr; /*%< zone xfr database handle */
+ DB *client; /*%< client database handle */
+ isc_mem_t *mctx; /*%< memory context */
+
+} bdbhpt_instance_t;
+
+typedef struct bdbhpt_parsed_data {
+ char *host;
+ char *type;
+ int ttl;
+ char *data;
+} bdbhpt_parsed_data_t;
+
+
+/* forward reference */
+
+static isc_result_t
+bdbhpt_findzone(void *driverarg, void *dbdata, const char *name);
+
+/*%
+ * Reverses a string in place.
+ */
+
+static char *bdbhpt_strrev(char *str)
+{
+ char *p1, *p2;
+
+ if (! str || ! *str)
+ return str;
+ for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
+ {
+ *p1 ^= *p2;
+ *p2 ^= *p1;
+ *p1 ^= *p2;
+ }
+ return str;
+}
+
+/*%
+ * Parses the DBT from the Berkeley DB into a parsed_data record
+ * The parsed_data record should be allocated before and passed into the
+ * bdbhpt_parse_data function. The char (type & data) fields should not
+ * be "free"d as that memory is part of the DBT data field. It will be
+ * "free"d when the DBT is freed.
+ */
+
+static isc_result_t
+bdbhpt_parse_data(char *in, bdbhpt_parsed_data_t *pd) {
+
+ char *endp, *ttlStr;
+ char *tmp = in;
+ char *lastchar = (char *) &tmp[strlen(tmp)];
+
+ /*%
+ * String should be formated as:
+ * replication_id
+ * (a space)
+ * host_name
+ * (a space)
+ * ttl
+ * (a space)
+ * type
+ * (a space)
+ * remaining data
+ *
+ * examples:
+ *
+ * 9191 host 10 A 127.0.0.1
+ * server1_212 host 10 A 127.0.0.2
+ * {xxxx-xxxx-xxxx-xxxx-xxxx} host 10 MX 20 mail.example.com
+ */
+
+ /*
+ * we don't need the replication id, so don't
+ * bother saving a pointer to it.
+ */
+
+ /* find space after replication id */
+ tmp = strchr(tmp, ' ');
+ /* verify we found a space */
+ if (tmp == NULL)
+ return ISC_R_FAILURE;
+ /* make sure it is safe to increment pointer */
+ if (++tmp > lastchar)
+ return ISC_R_FAILURE;
+
+ /* save pointer to host */
+ pd->host = tmp;
+
+ /* find space after host and change it to a '\0' */
+ tmp = strchr(tmp, ' ');
+ /* verify we found a space */
+ if (tmp == NULL)
+ return ISC_R_FAILURE;
+ /* change the space to a null (string terminator) */
+ tmp[0] = '\0';
+ /* make sure it is safe to increment pointer */
+ if (++tmp > lastchar)
+ return ISC_R_FAILURE;
+
+ /* save pointer to ttl string */
+ ttlStr = tmp;
+
+ /* find space after ttl and change it to a '\0' */
+ tmp = strchr(tmp, ' ');
+ /* verify we found a space */
+ if (tmp == NULL)
+ return ISC_R_FAILURE;
+ /* change the space to a null (string terminator) */
+ tmp[0] = '\0';
+ /* make sure it is safe to increment pointer */
+ if (++tmp > lastchar)
+ return ISC_R_FAILURE;
+
+ /* save pointer to dns type */
+ pd->type = tmp;
+
+ /* find space after type and change it to a '\0' */
+ tmp = strchr(tmp, ' ');
+ /* verify we found a space */
+ if (tmp == NULL)
+ return ISC_R_FAILURE;
+ /* change the space to a null (string terminator) */
+ tmp[0] = '\0';
+ /* make sure it is safe to increment pointer */
+ if (++tmp > lastchar)
+ return ISC_R_FAILURE;
+
+ /* save pointer to remainder of DNS data */
+ pd->data = tmp;
+
+ /* convert ttl string to integer */
+ pd->ttl = strtol(ttlStr, &endp, 10);
+ if (*endp != '\0' || pd->ttl < 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "bdbhpt driver ttl must be a postive number");
+ return ISC_R_FAILURE;
+ }
+
+ /* if we get this far everything should have worked. */
+ return ISC_R_SUCCESS;
+}
+
+/*
+ * DLZ methods
+ */
+
+static isc_result_t
+bdbhpt_allowzonexfr(void *driverarg, void *dbdata, const char *name,
+ const char *client)
+{
+ isc_result_t result;
+ bdbhpt_instance_t *db = (bdbhpt_instance_t *) dbdata;
+ DBT key, data;
+
+ /* check to see if we are authoritative for the zone first. */
+ result = bdbhpt_findzone(driverarg, dbdata, name);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_NOTFOUND);
+
+ memset(&key, 0, sizeof(DBT));
+ key.flags = DB_DBT_MALLOC;
+ key.data = strdup(name);
+ if (key.data == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto xfr_cleanup;
+ }
+ key.size = strlen(key.data);
+
+ memset(&data, 0, sizeof(DBT));
+ data.flags = DB_DBT_MALLOC;
+ data.data = strdup(client);
+ if (data.data == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto xfr_cleanup;
+ }
+ data.size = strlen(data.data);
+
+ switch(db->client->get(db->client, NULL, &key, &data, DB_GET_BOTH)) {
+ case DB_NOTFOUND:
+ result = ISC_R_NOTFOUND;
+ break;
+ case 0:
+ result = ISC_R_SUCCESS;
+ break;
+ default:
+ result = ISC_R_FAILURE;
+ }
+
+ xfr_cleanup:
+
+ /* free any memory duplicate string in the key field */
+ if (key.data != NULL)
+ free(key.data);
+
+ /* free any memory allocated to the data field. */
+ if (data.data != NULL)
+ free(data.data);
+
+ return result;
+
+}
+
+/*%
+ * BDB does not allow a secondary index on a database that allows
+ * duplicates. We have a few options:
+ *
+ * 1) kill speed by having lookup method use a secondary db which
+ * is associated to the primary DB with the DNS data. Then have
+ * another secondary db for zone transfer which also points to
+ * the dns_data primary. NO - The point of this driver is
+ * lookup performance.
+ *
+ * 2) Blow up database size by storing DNS data twice. Once for
+ * the lookup (dns_data) database, and a second time for the zone
+ * transfer (dns_xfr) database. NO - That would probably require
+ * a larger cache to provide good performance. Also, that would
+ * make the DB larger on disk potentially slowing it as well.
+ *
+ * 3) Loop through the dns_xfr database with a cursor to get
+ * all the different hosts in a zone. Then use the zone & host
+ * together to lookup the data in the dns_data database. YES -
+ * This may slow down zone xfr's a little, but that's ok they
+ * don't happen as often and don't need to be as fast. We can
+ * also use this table when deleting a zone (The BDB driver
+ * is read only - the delete would be used during replication
+ * updates by a separate process).
+ */
+
+static isc_result_t
+bdbhpt_allnodes(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzallnodes_t *allnodes)
+{
+
+ isc_result_t result = ISC_R_NOTFOUND;
+ bdbhpt_instance_t *db = (bdbhpt_instance_t *) dbdata;
+ DBC *xfr_cursor = NULL;
+ DBC *dns_cursor = NULL;
+ DBT xfr_key, xfr_data, dns_key, dns_data;
+ int xfr_flags;
+ int dns_flags;
+ int bdbhptres;
+ bdbhpt_parsed_data_t pd;
+ char *tmp = NULL, *tmp_zone, *tmp_zone_host = NULL;
+
+ UNUSED(driverarg);
+
+ memset(&xfr_key, 0, sizeof(DBT));
+ memset(&xfr_data, 0, sizeof(DBT));
+ memset(&dns_key, 0, sizeof(DBT));
+ memset(&dns_data, 0, sizeof(DBT));
+
+ xfr_key.data = tmp_zone = strdup(zone);
+ if (xfr_key.data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ xfr_key.size = strlen(xfr_key.data);
+
+ /* get a cursor to loop through dns_xfr table */
+ if (db->xfr->cursor(db->xfr, NULL, &xfr_cursor, 0) != 0) {
+ result = ISC_R_FAILURE;
+ goto allnodes_cleanup;
+ }
+
+ /* get a cursor to loop through dns_data table */
+ if (db->data->cursor(db->data, NULL, &dns_cursor, 0) != 0) {
+ result = ISC_R_FAILURE;
+ goto allnodes_cleanup;
+ }
+
+ xfr_flags = DB_SET;
+
+ /* loop through xfr table for specified zone. */
+ while ((bdbhptres = xfr_cursor->c_get(xfr_cursor, &xfr_key, &xfr_data,
+ xfr_flags)) == 0) {
+
+ xfr_flags = DB_NEXT_DUP;
+
+ /* +1 to allow for space between zone and host names */
+ dns_key.size = xfr_data.size + xfr_key.size + 1;
+
+ /* +1 to allow for null term at end of string. */
+ dns_key.data = tmp_zone_host = malloc(dns_key.size + 1);
+ if (dns_key.data == NULL)
+ goto allnodes_cleanup;
+
+ /*
+ * construct search key for dns_data.
+ * zone_name(a space)host_name
+ */
+ strcpy(dns_key.data, zone);
+ strcat(dns_key.data, " ");
+ strncat(dns_key.data, xfr_data.data, xfr_data.size);
+
+ dns_flags = DB_SET;
+
+ while ((bdbhptres = dns_cursor->c_get(dns_cursor, &dns_key,
+ &dns_data,
+ dns_flags)) == 0) {
+
+ dns_flags = DB_NEXT_DUP;
+
+ /* +1 to allow for null term at end of string. */
+ tmp = realloc(tmp, dns_data.size + 1);
+ if (tmp == NULL)
+ goto allnodes_cleanup;
+
+ /* copy data to tmp string, and append null term. */
+ strncpy(tmp, dns_data.data, dns_data.size);
+ tmp[dns_data.size] = '\0';
+
+ /* split string into dns data parts. */
+ if (bdbhpt_parse_data(tmp, &pd) != ISC_R_SUCCESS)
+ goto allnodes_cleanup;
+
+ result = dns_sdlz_putnamedrr(allnodes, pd.host,
+ pd.type, pd.ttl, pd.data);
+ if (result != ISC_R_SUCCESS)
+ goto allnodes_cleanup;
+
+ } /* end inner while loop */
+
+ /* clean up memory */
+ if (tmp_zone_host != NULL) {
+ free(tmp_zone_host);
+ tmp_zone_host = NULL;
+ }
+ } /* end outer while loop */
+
+ allnodes_cleanup:
+
+ /* free any memory */
+ if (tmp != NULL)
+ free(tmp);
+
+ if (tmp_zone_host != NULL)
+ free(tmp_zone_host);
+
+ if (tmp_zone != NULL)
+ free(tmp_zone);
+
+ /* get rid of cursors */
+ if (xfr_cursor != NULL)
+ xfr_cursor->c_close(xfr_cursor);
+
+ if (dns_cursor != NULL)
+ dns_cursor->c_close(xfr_cursor);
+
+ return result;
+}
+
+/*%
+ * Performs bdbhpt cleanup.
+ * Used by bdbhpt_create if there is an error starting up.
+ * Used by bdbhpt_destroy when the driver is shutting down.
+ */
+
+static void
+bdbhpt_cleanup(bdbhpt_instance_t *db) {
+
+ isc_mem_t *mctx;
+
+ /* close databases */
+ if (db->data != NULL)
+ db->data->close(db->data, 0);
+ if (db->xfr != NULL)
+ db->xfr->close(db->xfr, 0);
+ if (db->zone != NULL)
+ db->zone->close(db->zone, 0);
+ if (db->client != NULL)
+ db->client->close(db->client, 0);
+
+ /* close environment */
+ if (db->dbenv != NULL)
+ db->dbenv->close(db->dbenv, 0);
+
+ /* cleanup memory */
+ if (db->mctx != NULL) {
+ /* save mctx for later */
+ mctx = db->mctx;
+ /* return, and detach the memory */
+ isc_mem_put(mctx, db, sizeof(bdbhpt_instance_t));
+ isc_mem_detach(&mctx);
+ }
+}
+
+static isc_result_t
+bdbhpt_findzone(void *driverarg, void *dbdata, const char *name)
+{
+
+ isc_result_t result;
+ bdbhpt_instance_t *db = (bdbhpt_instance_t *) dbdata;
+ DBT key, data;
+
+ UNUSED(driverarg);
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+ data.flags = DB_DBT_MALLOC;
+
+ key.data = strdup(name);
+
+ if (key.data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /*
+ * reverse string to take advantage of BDB locality of reference
+ * if we need futher lookups because the zone doesn't match the
+ * first time.
+ */
+ key.data = bdbhpt_strrev(key.data);
+ key.size = strlen(key.data);
+
+ switch(db->zone->get(db->zone, NULL, &key, &data, 0)) {
+ case DB_NOTFOUND:
+ result = ISC_R_NOTFOUND;
+ break;
+ case 0:
+ result = ISC_R_SUCCESS;
+ break;
+ default:
+ result = ISC_R_FAILURE;
+ }
+
+ /* free any memory duplicate string in the key field */
+ if (key.data != NULL)
+ free(key.data);
+
+ /* free any memory allocated to the data field. */
+ if (data.data != NULL)
+ free(data.data);
+
+ return result;
+}
+
+static isc_result_t
+bdbhpt_lookup(const char *zone, const char *name, void *driverarg,
+ void *dbdata, dns_sdlzlookup_t *lookup)
+{
+
+ isc_result_t result = ISC_R_NOTFOUND;
+ bdbhpt_instance_t *db = (bdbhpt_instance_t *) dbdata;
+ DBC *data_cursor = NULL;
+ DBT key, data;
+ int bdbhptres;
+ int flags;
+
+ bdbhpt_parsed_data_t pd;
+ char *tmp = NULL;
+ char *keyStr = NULL;
+
+ UNUSED(driverarg);
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+
+ key.size = strlen(zone) + strlen(name) + 1;
+
+ /* allocate mem for key */
+ key.data = keyStr = malloc((key.size + 1) * sizeof(char));
+
+ if (keyStr == NULL)
+ return ISC_R_NOMEMORY;
+
+ strcpy(keyStr, zone);
+ strcat(keyStr, " ");
+ strcat(keyStr, name);
+
+ /* get a cursor to loop through data */
+ if (db->data->cursor(db->data, NULL, &data_cursor, 0) != 0) {
+ result = ISC_R_FAILURE;
+ goto lookup_cleanup;
+ }
+
+ result = ISC_R_NOTFOUND;
+
+ flags = DB_SET;
+ while ((bdbhptres = data_cursor->c_get(data_cursor, &key, &data,
+ flags)) == 0) {
+
+ flags = DB_NEXT_DUP;
+ tmp = realloc(tmp, data.size + 1);
+ if (tmp == NULL)
+ goto lookup_cleanup;
+
+ strncpy(tmp, data.data, data.size);
+ tmp[data.size] = '\0';
+
+ if (bdbhpt_parse_data(tmp, &pd) != ISC_R_SUCCESS)
+ goto lookup_cleanup;
+
+ result = dns_sdlz_putrr(lookup, pd.type, pd.ttl, pd.data);
+
+ if (result != ISC_R_SUCCESS)
+ goto lookup_cleanup;
+ } /* end while loop */
+
+ lookup_cleanup:
+
+ /* get rid of cursor */
+ if (data_cursor != NULL)
+ data_cursor->c_close(data_cursor);
+
+ if (keyStr != NULL)
+ free(keyStr);
+ if (tmp != NULL)
+ free(tmp);
+
+ return result;
+}
+
+/*% Initializes, sets flags and then opens Berkeley databases. */
+
+static isc_result_t
+bdbhpt_opendb(DB_ENV *db_env, DBTYPE db_type, DB **db, const char *db_name,
+ char *db_file, int flags) {
+
+ int result;
+
+ /* Initialize the database. */
+ if ((result = db_create(db, db_env, 0)) != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "bdbhpt could not initialize %s database. "
+ "bdbhpt error: %s",
+ db_name, db_strerror(result));
+ return ISC_R_FAILURE;
+ }
+
+ /* set database flags. */
+ if ((result = (*db)->set_flags(*db, flags)) != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "bdbhpt could not set flags for %s database. "
+ "bdbhpt error: %s",
+ db_name, db_strerror(result));
+ return ISC_R_FAILURE;
+ }
+
+ /* open the database. */
+ if ((result = (*db)->open(*db, NULL, db_file, db_name, db_type,
+ DB_RDONLY | bdbhpt_threads, 0)) != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "bdbhpt could not open %s database in %s. "
+ "bdbhpt error: %s",
+ db_name, db_file, db_strerror(result));
+ return ISC_R_FAILURE;
+ }
+
+ return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+bdbhpt_create(const char *dlzname, unsigned int argc, char *argv[],
+ void *driverarg, void **dbdata)
+{
+ isc_result_t result;
+ int bdbhptres;
+ int bdbFlags = 0;
+ bdbhpt_instance_t *db = NULL;
+
+ UNUSED(dlzname);
+ UNUSED(driverarg);
+
+ /* verify we have 4 arg's passed to the driver */
+ if (argc != 4) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "bdbhpt driver requires at least "
+ "3 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ switch((char) *argv[1]) {
+ /*
+ * Transactional mode. Highest safety - lowest speed.
+ */
+ case 'T':
+ case 't':
+ bdbFlags = DB_INIT_MPOOL | DB_INIT_LOCK |
+ DB_INIT_LOG | DB_INIT_TXN;
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "bdbhpt driver using transactional mode.");
+ break;
+ /*
+ * Concurrent mode. Lower safety (no rollback) -
+ * higher speed.
+ */
+ case 'C':
+ case 'c':
+ bdbFlags = DB_INIT_CDB | DB_INIT_MPOOL;
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "bdbhpt driver using concurrent mode.");
+ break;
+ /*
+ * Private mode. No inter-process communication & no locking.
+ * Lowest saftey - highest speed.
+ */
+ case 'P':
+ case 'p':
+ bdbFlags = DB_PRIVATE | DB_INIT_MPOOL;
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "bdbhpt driver using private mode.");
+ break;
+ default:
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "bdbhpt driver requires the operating mode "
+ "be set to P or C or T. You specified '%s'",
+ argv[1]);
+ return (ISC_R_FAILURE);
+ }
+
+ /* allocate and zero memory for driver structure */
+ db = isc_mem_get(ns_g_mctx, sizeof(bdbhpt_instance_t));
+ if (db == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Could not allocate memory for "
+ "database instance object.");
+ return (ISC_R_NOMEMORY);
+ }
+ memset(db, 0, sizeof(bdbhpt_instance_t));
+
+ /* attach to the memory context */
+ isc_mem_attach(ns_g_mctx, &db->mctx);
+
+ /*
+ * create bdbhpt environment
+ * Basically bdbhpt allocates and assigns memory to db->dbenv
+ */
+ bdbhptres = db_env_create(&db->dbenv, 0);
+ if (bdbhptres != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "bdbhpt environment could not be created. "
+ "bdbhpt error: %s",
+ db_strerror(bdbhptres));
+ result = ISC_R_FAILURE;
+ goto init_cleanup;
+ }
+
+ /* open bdbhpt environment */
+ bdbhptres = db->dbenv->open(db->dbenv, argv[2],
+ bdbFlags | bdbhpt_threads | DB_CREATE, 0);
+ if (bdbhptres != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "bdbhpt environment at '%s' could not be opened."
+ " bdbhpt error: %s",
+ argv[2], db_strerror(bdbhptres));
+ result = ISC_R_FAILURE;
+ goto init_cleanup;
+ }
+
+ /* open dlz_data database. */
+ result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->data,
+ dlz_data, argv[3], DB_DUP | DB_DUPSORT);
+ if (result != ISC_R_SUCCESS)
+ goto init_cleanup;
+
+ /* open dlz_xfr database. */
+ result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->xfr,
+ dlz_xfr, argv[3], DB_DUP | DB_DUPSORT);
+ if (result != ISC_R_SUCCESS)
+ goto init_cleanup;
+
+ /* open dlz_zone database. */
+ result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->zone,
+ dlz_zone, argv[3], 0);
+ if (result != ISC_R_SUCCESS)
+ goto init_cleanup;
+
+ /* open dlz_client database. */
+ result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->client,
+ dlz_client, argv[3], DB_DUP | DB_DUPSORT);
+ if (result != ISC_R_SUCCESS)
+ goto init_cleanup;
+
+ *dbdata = db;
+
+ return(ISC_R_SUCCESS);
+
+ init_cleanup:
+
+ bdbhpt_cleanup(db);
+ return result;
+}
+
+static void
+bdbhpt_destroy(void *driverarg, void *dbdata)
+{
+ UNUSED(driverarg);
+
+ bdbhpt_cleanup((bdbhpt_instance_t *) dbdata);
+}
+
+/*
+ * bdbhpt_authority not needed as authority data is returned by lookup
+ */
+static dns_sdlzmethods_t dlz_bdbhpt_methods = {
+ bdbhpt_create,
+ bdbhpt_destroy,
+ bdbhpt_findzone,
+ bdbhpt_lookup,
+ NULL,
+ bdbhpt_allnodes,
+ bdbhpt_allowzonexfr
+};
+
+/*%
+ * Wrapper around dns_sdlzregister().
+ */
+isc_result_t
+dlz_bdbhpt_init(void) {
+ isc_result_t result;
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Registering DLZ bdbhpt driver.");
+
+ result = dns_sdlzregister("bdbhpt", &dlz_bdbhpt_methods, NULL,
+ DNS_SDLZFLAG_RELATIVEOWNER |
+ DNS_SDLZFLAG_RELATIVERDATA |
+ DNS_SDLZFLAG_THREADSAFE,
+ ns_g_mctx, &dlz_bdbhpt);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+
+ return result;
+}
+
+/*%
+ * Wrapper around dns_sdlzunregister().
+ */
+void
+dlz_bdbhpt_clear(void) {
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Unregistering DLZ bdbhpt driver.");
+
+ if (dlz_bdbhpt != NULL)
+ dns_sdlzunregister(&dlz_bdbhpt);
+}
+
+#endif
diff --git a/contrib/dlz/drivers/dlz_drivers.c b/contrib/dlz/drivers/dlz_drivers.c
new file mode 100644
index 0000000..e2c6a6e
--- /dev/null
+++ b/contrib/dlz/drivers/dlz_drivers.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND 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: dlz_drivers.c,v 1.2 2005/09/05 00:10:55 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/result.h>
+
+/*
+ * Pull in declarations for this module's functions.
+ */
+
+#include <dlz/dlz_drivers.h>
+
+/*
+ * Pull in driver-specific stuff.
+ */
+
+#ifdef DLZ_STUB
+#include <dlz/dlz_stub_driver.h>
+#endif
+
+#ifdef DLZ_POSTGRES
+#include <dlz/dlz_postgres_driver.h>
+#endif
+
+#ifdef DLZ_MYSQL
+#include <dlz/dlz_mysql_driver.h>
+#endif
+
+#ifdef DLZ_FILESYSTEM
+#include <dlz/dlz_filesystem_driver.h>
+#endif
+
+#ifdef DLZ_BDB
+#include <dlz/dlz_bdb_driver.h>
+#include <dlz/dlz_bdbhpt_driver.h>
+#endif
+
+#ifdef DLZ_LDAP
+#include <dlz/dlz_ldap_driver.h>
+#endif
+
+#ifdef DLZ_ODBC
+#include <dlz/dlz_odbc_driver.h>
+#endif
+
+/*%
+ * Call init functions for all relevant DLZ drivers.
+ */
+
+isc_result_t
+dlz_drivers_init(void) {
+
+ isc_result_t result = ISC_R_SUCCESS;
+
+#ifdef DLZ_STUB
+ result = dlz_stub_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#endif
+
+#ifdef DLZ_POSTGRES
+ result = dlz_postgres_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#endif
+
+#ifdef DLZ_MYSQL
+ result = dlz_mysql_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#endif
+
+#ifdef DLZ_FILESYSTEM
+ result = dlz_fs_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#endif
+
+#ifdef DLZ_BDB
+ result = dlz_bdb_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dlz_bdbhpt_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#endif
+
+#ifdef DLZ_LDAP
+ result = dlz_ldap_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#endif
+
+#ifdef DLZ_ODBC
+ result = dlz_odbc_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#endif
+
+ return (result);
+}
+
+/*%
+ * Call shutdown functions for all relevant DLZ drivers.
+ */
+
+void
+dlz_drivers_clear(void) {
+
+#ifdef DLZ_STUB
+ dlz_stub_clear();
+#endif
+
+#ifdef DLZ_POSTGRES
+ dlz_postgres_clear();
+#endif
+
+#ifdef DLZ_MYSQL
+ dlz_mysql_clear();
+#endif
+
+#ifdef DLZ_FILESYSTEM
+ dlz_fs_clear();
+#endif
+
+#ifdef DLZ_BDB
+ dlz_bdb_clear();
+ dlz_bdbhpt_clear();
+#endif
+
+#ifdef DLZ_LDAP
+ dlz_ldap_clear();
+#endif
+
+#ifdef DLZ_ODBC
+ dlz_odbc_clear();
+#endif
+
+}
diff --git a/contrib/dlz/drivers/dlz_filesystem_driver.c b/contrib/dlz/drivers/dlz_filesystem_driver.c
new file mode 100644
index 0000000..d41d5ac
--- /dev/null
+++ b/contrib/dlz/drivers/dlz_filesystem_driver.c
@@ -0,0 +1,1048 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef DLZ_FILESYSTEM
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <sys/stat.h>
+
+#include <dns/log.h>
+#include <dns/sdlz.h>
+#include <dns/result.h>
+
+#include <isc/dir.h>
+#include <isc/mem.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+
+#include <dlz/dlz_filesystem_driver.h>
+
+static dns_sdlzimplementation_t *dlz_fs = NULL;
+
+typedef struct config_data {
+ char *basedir;
+ int basedirsize;
+ char *datadir;
+ int datadirsize;
+ char *xfrdir;
+ int xfrdirsize;
+ int splitcnt;
+ char separator;
+ char pathsep;
+ isc_mem_t *mctx;
+} config_data_t;
+
+typedef struct dir_entry dir_entry_t;
+
+struct dir_entry {
+ char dirpath[ISC_DIR_PATHMAX];
+ ISC_LINK(dir_entry_t) link;
+};
+
+typedef ISC_LIST(dir_entry_t) dlist_t;
+
+/* forward reference */
+
+static void
+fs_destroy(void *driverarg, void *dbdata);
+
+/*
+ * Private methods
+ */
+
+static isc_boolean_t
+is_safe(const char *input)
+{
+ unsigned int i;
+ unsigned int len = strlen(input);
+
+ /* check that only allowed characters are in the domain name */
+ for (i=0; i < len; i++) {
+ /* '.' is allowed, but has special requirements */
+ if (input[i] == '.') {
+ /* '.' is not allowed as first char */
+ if (i == 0)
+ return ISC_FALSE;
+ /* '..', two dots together is not allowed. */
+ else if (input[i-1] == '.')
+ return ISC_FALSE;
+ /* '.' is not allowed as last char */
+ if (i == len)
+ return ISC_FALSE;
+ /* only 1 dot in ok location, continue at next char */
+ continue;
+ }
+ /* '-' is allowed, continue at next char */
+ if (input[i] == '-')
+ continue;
+ /* 0-9 is allowed, continue at next char */
+ if (input[i] >= '0' && input[i] <= '9')
+ continue;
+ /* A-Z uppercase is allowed, continue at next char */
+ if (input[i] >= 'A' && input[i] <= 'Z')
+ continue;
+ /* a-z lowercase is allowed, continue at next char */
+ if (input[i] >= 'a' && input[i] <= 'z')
+ continue;
+
+ /*
+ * colon needs to be allowed for IPV6 client
+ * addresses. Not dangerous in domain names, as not a
+ * special char.
+ */
+ if (input[i] == ':')
+ continue;
+
+ /*
+ * '@' needs to be allowed for in zone data. Not
+ * dangerous in domain names, as not a special char.
+ */
+ if (input[i] == '@')
+ continue;
+
+ /*
+ * if we reach this point we have encountered a
+ * disallowed char!
+ */
+ return ISC_FALSE;
+ }
+ /* everything ok. */
+ return ISC_TRUE;
+}
+
+static isc_result_t
+create_path_helper(char *out, const char *in, config_data_t *cd)
+{
+
+ char *tmpString;
+ char *tmpPtr;
+ int i;
+
+ tmpString = isc_mem_strdup(ns_g_mctx, in);
+ if (tmpString == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /*
+ * don't forget is_safe guarantees '.' will NOT be the
+ * first/last char
+ */
+ while ((tmpPtr = strrchr(tmpString, '.')) != NULL) {
+ i = 0;
+ while (tmpPtr[i+1] != '\0') {
+ if (cd->splitcnt < 1)
+ strcat(out, (char *) &tmpPtr[i+1]);
+ else
+ strncat(out, (char *) &tmpPtr[i+1],
+ cd->splitcnt);
+ strncat(out, (char *) &cd->pathsep, 1);
+ if (cd->splitcnt == 0)
+ break;
+ if (strlen((char *) &tmpPtr[i+1]) <=
+ (unsigned int) cd->splitcnt)
+ break;
+ i += cd->splitcnt;
+ }
+ tmpPtr[0] = '\0';
+ }
+
+ /* handle the "first" label properly */
+ i=0;
+ tmpPtr = tmpString;
+ while (tmpPtr[i] != '\0') {
+ if (cd->splitcnt < 1)
+ strcat(out, (char *) &tmpPtr[i]);
+ else
+ strncat(out, (char *) &tmpPtr[i], cd->splitcnt);
+ strncat(out, (char *) &cd->pathsep, 1);
+ if (cd->splitcnt == 0)
+ break;
+ if (strlen((char *) &tmpPtr[i]) <=
+ (unsigned int) cd->splitcnt)
+ break;
+ i += cd->splitcnt;
+ }
+
+ isc_mem_free(ns_g_mctx, tmpString);
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Checks to make sure zone and host are safe. If safe, then
+ * hashes zone and host strings to build a path. If zone / host
+ * are not safe an error is returned.
+ */
+
+static isc_result_t
+create_path(const char *zone, const char *host, const char *client,
+ config_data_t *cd, char **path)
+{
+
+ char *tmpPath;
+ int pathsize;
+ int len;
+ isc_result_t result;
+
+ /* we require a zone & cd parameter */
+ REQUIRE(zone != NULL);
+ REQUIRE(cd != NULL);
+ /* require path to be a pointer to NULL */
+ REQUIRE(path != NULL && *path == NULL);
+ /*
+ * client and host may both be NULL, but they can't both be
+ * NON-NULL
+ */
+ REQUIRE( (host == NULL && client == NULL) ||
+ (host != NULL && client == NULL) ||
+ (host == NULL && client != NULL) );
+
+ /* if the requested zone is "unsafe", return error */
+ if (is_safe(zone) != ISC_TRUE)
+ return (ISC_R_FAILURE);
+
+ /* if host was passed, verify that it is safe */
+ if ((host != NULL) && (is_safe(host) != ISC_TRUE) )
+ return (ISC_R_FAILURE);
+
+ /* if host was passed, verify that it is safe */
+ if ((client != NULL) && (is_safe(client) != ISC_TRUE) )
+ return (ISC_R_FAILURE);
+
+ /* Determine how much memory the split up string will require */
+ if (host != NULL)
+ len = strlen(zone) + strlen(host);
+ else if (client != NULL)
+ len = strlen(zone) + strlen(client);
+ else
+ len = strlen(zone);
+
+ /*
+ * even though datadir and xfrdir will never be in the same
+ * string we only waste a few bytes by allocating for both,
+ * and then we are safe from buffer overruns.
+ */
+ pathsize = len + cd->basedirsize +
+ cd->datadirsize + cd->xfrdirsize + 4;
+
+ /* if we are splitting names, we will need extra space. */
+ if (cd->splitcnt > 0)
+ pathsize += len/cd->splitcnt;
+
+ tmpPath = isc_mem_allocate(ns_g_mctx , pathsize * sizeof(char));
+ if (tmpPath == NULL) {
+ /* write error message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Filesystem driver unable to "
+ "allocate memory in create_path().");
+ result = ISC_R_NOMEMORY;
+ goto cleanup_mem;
+ }
+
+ /*
+ * build path string.
+ * start out with base directory.
+ */
+ strcpy(tmpPath, cd->basedir);
+
+ /* add zone name - parsed properly */
+ if ((result = create_path_helper(tmpPath, zone, cd)) != ISC_R_SUCCESS)
+ goto cleanup_mem;
+
+ /*
+ * When neither client or host is passed we are building a
+ * path to see if a zone is supported. We require that a zone
+ * path have the "data dir" directory contained within it so
+ * that we know this zone is really supported. Otherwise,
+ * this zone may not really be supported because we are
+ * supporting a delagated sub zone.
+ *
+ * Example:
+ *
+ * We are supporting long.domain.com and using a splitcnt of
+ * 0. the base dir is "/base-dir/" and the data dir is
+ * "/.datadir" We want to see if we are authoritative for
+ * domain.com. Path /base-dir/com/domain/.datadir since
+ * /base-dir/com/domain/.datadir does not exist, we are not
+ * authoritative for the domain "domain.com". However we are
+ * authoritative for the domain "long.domain.com" because the
+ * path /base-dir/com/domain/long/.datadir does exist!
+ */
+
+ /* if client is passed append xfr dir, otherwise append data dir */
+ if (client != NULL) {
+ strcat(tmpPath, cd->xfrdir);
+ strncat(tmpPath, (char *) &cd->pathsep, 1);
+ strcat(tmpPath, client);
+ } else {
+ strcat(tmpPath, cd->datadir);
+ }
+
+ /* if host not null, add it. */
+ if (host != NULL) {
+ strncat(tmpPath, (char *) &cd->pathsep, 1);
+ if ((result = create_path_helper(tmpPath, host,
+ cd)) != ISC_R_SUCCESS)
+ goto cleanup_mem;
+ }
+
+ /* return the path we built. */
+ *path = tmpPath;
+
+ /* return success */
+ result = ISC_R_SUCCESS;
+
+ cleanup_mem:
+ /* cleanup memory */
+
+ /* free tmpPath memory */
+ if (tmpPath != NULL && result != ISC_R_SUCCESS)
+ isc_mem_free(ns_g_mctx, tmpPath);
+
+ /* free tmpPath memory */
+ return result;
+}
+
+static isc_result_t
+process_dir(isc_dir_t dir, void *passback, config_data_t *cd,
+ dlist_t *dir_list, unsigned int basedirlen)
+{
+
+ char tmp[ISC_DIR_PATHMAX + ISC_DIR_NAMEMAX];
+ int astPos;
+ struct stat sb;
+ isc_result_t result = ISC_R_FAILURE;
+ char *endp;
+ char *type;
+ char *ttlStr;
+ char *data;
+ char host[ISC_DIR_NAMEMAX];
+ char *tmpString;
+ char *tmpPtr;
+ int ttl;
+ int i;
+ int len;
+ dir_entry_t *direntry;
+ isc_boolean_t foundHost;
+
+ tmp[0] = '\0'; /* set 1st byte to '\0' so strcpy works right. */
+ host[0] = '\0';
+ foundHost = ISC_FALSE;
+
+ /* copy base directory name to tmp. */
+ strcpy(tmp, dir.dirname);
+
+ /* dir.dirname will always have '*' as the last char. */
+ astPos = strlen(dir.dirname) - 1;
+
+ /* if dir_list != NULL, were are performing a zone xfr */
+ if (dir_list != NULL) {
+ /* if splitcnt == 0, determine host from path. */
+ if (cd->splitcnt == 0) {
+ if (strlen(tmp) - 3 > basedirlen) {
+ tmp[astPos-1] = '\0';
+ tmpString = (char *) &tmp[basedirlen+1];
+ /* handle filesystem's special wildcard "-" */
+ if (strcmp(tmpString, "-") == 0) {
+ strcpy(host, "*");
+ } else {
+ /*
+ * not special wildcard -- normal name
+ */
+ while ((tmpPtr = strrchr(tmpString,
+ cd->pathsep))
+ != NULL) {
+ strcat(host, tmpPtr + 1);
+ strcat(host, ".");
+ tmpPtr[0] = '\0';
+ }
+ strcat(host, tmpString);
+ }
+
+ foundHost = ISC_TRUE;
+ /* set tmp again for use later */
+ strcpy(tmp, dir.dirname);
+ }
+ } else {
+ /*
+ * if splitcnt != 0 determine host from
+ * ".host" directory entry
+ */
+ while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
+ if (strncasecmp(".host",
+ dir.entry.name, 5) == 0) {
+ /*
+ * handle filesystem's special
+ * wildcard "-"
+ */
+ if (strcmp((char *) &dir.entry.name[6],
+ "-") == 0)
+ strcpy(host, "*");
+ else
+ strcpy(host,
+ (char *)
+ &dir.entry.name[6]);
+ foundHost = ISC_TRUE;
+ break;
+ }
+ }
+ /* reset dir list for use later */
+ isc_dir_reset(&dir);
+ } /* end of else */
+ }
+
+ while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "Filesystem driver Dir name:"
+ " '%s' Dir entry: '%s'\n",
+ dir.dirname, dir.entry.name);
+
+ /* skip any entries starting with "." */
+ if (dir.entry.name[0] == '.')
+ continue;
+
+ /*
+ * get rid of '*', set to NULL. Effectively trims
+ * string from previous loop to base directory only
+ * while still leaving memory for concat to be
+ * performed next.
+ */
+
+ tmp[astPos] = '\0';
+
+ /* add name to base directory name. */
+ strcat(tmp, dir.entry.name);
+
+ /* make sure we can stat entry */
+ if (stat(tmp, &sb) == 0 ) {
+ /* if entry is a directory */
+ if ((sb.st_mode & S_IFDIR) != 0) {
+ /*
+ * if dir list is NOT NULL, add dir to
+ * dir list
+ */
+ if (dir_list != NULL) {
+ direntry =
+ isc_mem_get(ns_g_mctx,
+ sizeof(dir_entry_t));
+ if (direntry == NULL)
+ return (ISC_R_NOMEMORY);
+ strcpy(direntry->dirpath, tmp);
+ ISC_LINK_INIT(direntry, link);
+ ISC_LIST_APPEND(*dir_list, direntry,
+ link);
+ result = ISC_R_SUCCESS;
+ }
+ continue;
+
+ /*
+ * if entry is a file be sure we do
+ * not add entry to DNS results if we
+ * are performing a zone xfr and we
+ * could not find a host entry.
+ */
+
+ } else if (dir_list != NULL &&
+ foundHost == ISC_FALSE) {
+ continue;
+ }
+ } else /* if we cannot stat entry, skip it. */
+ continue;
+
+ type = dir.entry.name;
+ ttlStr = strchr(type, cd->separator);
+ if (ttlStr == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Filesystem driver: "
+ "%s could not be parsed properly",
+ tmp);
+ return ISC_R_FAILURE;
+ }
+
+ /* replace separator char with NULL to split string */
+ ttlStr[0] = '\0';
+ /* start string after NULL of previous string */
+ ttlStr = (char *) &ttlStr[1];
+
+ data = strchr(ttlStr, cd->separator);
+ if (data == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Filesystem driver: "
+ "%s could not be parsed properly",
+ tmp);
+ return ISC_R_FAILURE;
+ }
+
+ /* replace separator char with NULL to split string */
+ data[0] = '\0';
+
+ /* start string after NULL of previous string */
+ data = (char *) &data[1];
+
+ /* replace all cd->separator chars with a space. */
+ len = strlen(data);
+
+ for (i=0; i < len; i++) {
+ if (data[i] == cd->separator)
+ data[i] = ' ';
+ }
+
+ /* convert text to int, make sure it worked right */
+ ttl = strtol(ttlStr, &endp, 10);
+ if (*endp != '\0' || ttl < 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Filesystem driver "
+ "ttl must be a postive number");
+ }
+
+ /* pass data back to Bind */
+ if (dir_list == NULL)
+ result = dns_sdlz_putrr((dns_sdlzlookup_t *) passback,
+ type, ttl, data);
+ else
+ result = dns_sdlz_putnamedrr((dns_sdlzallnodes_t *)
+ passback,
+ (char *) host,
+ type, ttl, data);
+
+ /* if error, return error right away */
+ if (result != ISC_R_SUCCESS)
+ return result;
+ } /* end of while loop */
+
+ return result;
+}
+
+/*
+ * SDLZ interface methods
+ */
+
+static isc_result_t
+fs_allowzonexfr(void *driverarg, void *dbdata, const char *name,
+ const char *client)
+{
+
+ isc_result_t result;
+ char *path;
+ struct stat sb;
+ config_data_t *cd;
+ path = NULL;
+
+ UNUSED(driverarg);
+
+ cd = (config_data_t *) dbdata;
+
+ if (create_path(name, NULL, client, cd, &path) != ISC_R_SUCCESS) {
+ return (ISC_R_NOTFOUND);
+ }
+
+ if (stat(path, &sb) != 0) {
+ result = ISC_R_NOTFOUND;
+ goto complete_AXFR;
+ }
+
+ if ((sb.st_mode & S_IFREG) != 0) {
+ result = ISC_R_SUCCESS;
+ goto complete_AXFR;
+ }
+
+ result = ISC_R_NOTFOUND;
+
+ complete_AXFR:
+ isc_mem_free(ns_g_mctx, path);
+ return result;
+}
+
+static isc_result_t
+fs_allnodes(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzallnodes_t *allnodes)
+{
+
+ isc_result_t result;
+ dlist_t *dir_list;
+ config_data_t *cd;
+ char *basepath;
+ unsigned int basepathlen;
+ struct stat sb;
+ isc_dir_t dir;
+ dir_entry_t *dir_entry;
+ dir_entry_t *next_de;
+
+ basepath = NULL;
+ dir_list = NULL;
+
+ UNUSED(driverarg);
+ UNUSED(allnodes);
+
+ cd = (config_data_t *) dbdata;
+
+ /* allocate memory for list */
+ dir_list = isc_mem_get(ns_g_mctx, sizeof(dlist_t));
+ if (dir_list == NULL) {
+ result = ISC_R_NOTFOUND;
+ goto complete_allnds;
+ }
+
+ /* initialize list */
+ ISC_LIST_INIT(*dir_list);
+
+ if (create_path(zone, NULL, NULL, cd, &basepath) != ISC_R_SUCCESS) {
+ return (ISC_R_NOTFOUND);
+ }
+
+ /* remove path separator at end of path so stat works properly */
+ basepathlen = strlen(basepath);
+
+ if (stat(basepath, &sb) != 0) {
+ result = ISC_R_NOTFOUND;
+ goto complete_allnds;
+ }
+
+ if ((sb.st_mode & S_IFDIR) == 0) {
+ result = ISC_R_NOTFOUND;
+ goto complete_allnds;
+ }
+
+ /* initialize and open directory */
+ isc_dir_init(&dir);
+ result = isc_dir_open(&dir, basepath);
+
+ /* if directory open failed, return error. */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Unable to open %s directory to read entries.",
+ basepath);
+ result = ISC_R_FAILURE;
+ goto complete_allnds;
+ }
+
+ /* process the directory */
+ result = process_dir(dir, allnodes, cd, dir_list, basepathlen);
+
+ /* close the directory */
+ isc_dir_close(&dir);
+
+ if (result != ISC_R_SUCCESS)
+ goto complete_allnds;
+
+ /* get first dir entry from list. */
+ dir_entry = ISC_LIST_HEAD(*dir_list);
+ while (dir_entry != NULL) {
+
+ result = isc_dir_open(&dir, dir_entry->dirpath);
+ /* if directory open failed, return error. */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Unable to open %s "
+ "directory to read entries.",
+ basepath);
+ result = ISC_R_FAILURE;
+ goto complete_allnds;
+ }
+
+ /* process the directory */
+ result = process_dir(dir, allnodes, cd, dir_list, basepathlen);
+
+ /* close the directory */
+ isc_dir_close(&dir);
+
+ if (result != ISC_R_SUCCESS)
+ goto complete_allnds;
+
+ dir_entry = ISC_LIST_NEXT(dir_entry, link);
+ } /* end while */
+
+ complete_allnds:
+ if (dir_list != NULL) {
+ /* clean up entries from list. */
+ dir_entry = ISC_LIST_HEAD(*dir_list);
+ while (dir_entry != NULL) {
+ next_de = ISC_LIST_NEXT(dir_entry, link);
+ isc_mem_put(ns_g_mctx, dir_entry, sizeof(dir_entry_t));
+ dir_entry = next_de;
+ } /* end while */
+ isc_mem_put(ns_g_mctx, dir_list, sizeof(dlist_t));
+ }
+
+ if (basepath != NULL)
+ isc_mem_free(ns_g_mctx, basepath);
+
+ return result;
+}
+
+static isc_result_t
+fs_findzone(void *driverarg, void *dbdata, const char *name)
+{
+
+ isc_result_t result;
+ char *path;
+ struct stat sb;
+ path = NULL;
+
+ UNUSED(driverarg);
+
+ if (create_path(name, NULL, NULL, (config_data_t *) dbdata,
+ &path) != ISC_R_SUCCESS) {
+ return (ISC_R_NOTFOUND);
+ }
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "Filesystem driver Findzone() Checking for path: '%s'\n",
+ path);
+
+ if (stat(path, &sb) != 0) {
+ result = ISC_R_NOTFOUND;
+ goto complete_FZ;
+ }
+
+ if ((sb.st_mode & S_IFDIR) != 0) {
+ result = ISC_R_SUCCESS;
+ goto complete_FZ;
+ }
+
+ result = ISC_R_NOTFOUND;
+
+ complete_FZ:
+
+ isc_mem_free(ns_g_mctx, path);
+ return result;
+}
+
+static isc_result_t
+fs_lookup(const char *zone, const char *name, void *driverarg,
+ void *dbdata, dns_sdlzlookup_t *lookup)
+{
+ isc_result_t result;
+ char *path;
+ struct stat sb;
+ isc_dir_t dir;
+ path = NULL;
+
+ UNUSED(driverarg);
+ UNUSED(lookup);
+
+ if (strcmp(name, "*") == 0)
+ /*
+ * handle filesystem's special wildcard "-"
+ */
+ result = create_path(zone, "-", NULL,
+ (config_data_t *) dbdata, &path);
+ else
+ result = create_path(zone, name, NULL,
+ (config_data_t *) dbdata, &path);
+
+ if ( result != ISC_R_SUCCESS) {
+ return (ISC_R_NOTFOUND);
+ }
+
+ /* remove path separator at end of path so stat works properly */
+ path[strlen(path)-1] = '\0';
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "Filesystem driver lookup() Checking for path: '%s'\n",
+ path);
+
+
+ if (stat(path, &sb) != 0) {
+ result = ISC_R_NOTFOUND;
+ goto complete_lkup;
+ }
+
+ if ((sb.st_mode & S_IFDIR) == 0) {
+ result = ISC_R_NOTFOUND;
+ goto complete_lkup;
+ }
+
+ /* initialize and open directory */
+ isc_dir_init(&dir);
+ result = isc_dir_open(&dir, path);
+
+ /* if directory open failed, return error. */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Unable to open %s directory to read entries.",
+ path);
+ result = ISC_R_FAILURE;
+ goto complete_lkup;
+ }
+
+ /* process any records in the directory */
+ result = process_dir(dir, lookup, (config_data_t *) dbdata, NULL, 0);
+
+ /* close the directory */
+ isc_dir_close(&dir);
+
+ complete_lkup:
+
+ isc_mem_free(ns_g_mctx, path);
+ return result;
+}
+
+static isc_result_t
+fs_create(const char *dlzname, unsigned int argc, char *argv[],
+ void *driverarg, void **dbdata)
+{
+ config_data_t *cd;
+ char *endp;
+ int len;
+ char pathsep;
+
+ UNUSED(driverarg);
+ UNUSED(dlzname);
+
+ /* we require 5 command line args. */
+ if (argc != 6) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Filesystem driver requires "
+ "6 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ if (strlen(argv[5]) > 1) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Filesystem driver can only "
+ "accept a single character for separator.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* verify base dir ends with '/' or '\' */
+ len = strlen(argv[1]);
+ if (argv[1][len-1] != '\\' && argv[1][len-1] != '/') {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Base dir parameter for filesystem driver "
+ "should end with %s",
+ "either '/' or '\\' ");
+ return (ISC_R_FAILURE);
+ }
+
+ /* determine and save path separator for later */
+ if (argv[1][len-1] == '\\')
+ pathsep = '\\';
+ else
+ pathsep = '/';
+
+ /* allocate memory for our config data */
+ cd = isc_mem_get(ns_g_mctx, sizeof(config_data_t));
+ if (cd == NULL)
+ goto no_mem;
+
+ /* zero the memory */
+ memset(cd, 0, sizeof(config_data_t));
+
+ cd->pathsep = pathsep;
+
+ /* get and store our base directory */
+ cd->basedir = isc_mem_strdup(ns_g_mctx, argv[1]);
+ if (cd->basedir == NULL)
+ goto no_mem;
+ cd->basedirsize = strlen(cd->basedir);
+
+ /* get and store our data sub-dir */
+ cd->datadir = isc_mem_strdup(ns_g_mctx, argv[2]);
+ if (cd->datadir == NULL)
+ goto no_mem;
+ cd->datadirsize = strlen(cd->datadir);
+
+ /* get and store our zone xfr sub-dir */
+ cd->xfrdir = isc_mem_strdup(ns_g_mctx, argv[3]);
+ if (cd->xfrdir == NULL)
+ goto no_mem;
+ cd->xfrdirsize = strlen(cd->xfrdir);
+
+ /* get and store our directory split count */
+ cd->splitcnt = strtol(argv[4], &endp, 10);
+ if (*endp != '\0' || cd->splitcnt < 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Directory split count must be zero (0) "
+ "or a postive number");
+ }
+
+ /* get and store our separator character */
+ cd->separator = *argv[5];
+
+ /* attach config data to memory context */
+ isc_mem_attach(ns_g_mctx, &cd->mctx);
+
+ /* pass back config data */
+ *dbdata = cd;
+
+ /* return success */
+ return(ISC_R_SUCCESS);
+
+ /* handle no memory error */
+ no_mem:
+
+ /* if we allocated a config data object clean it up */
+ if (cd != NULL)
+ fs_destroy(NULL, cd);
+
+ /* write error message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Filesystem driver unable to "
+ "allocate memory for config data.");
+
+ /* return error */
+ return (ISC_R_NOMEMORY);
+}
+
+static void
+fs_destroy(void *driverarg, void *dbdata)
+{
+ isc_mem_t *mctx;
+ config_data_t *cd;
+
+ UNUSED(driverarg);
+
+ cd = (config_data_t *) dbdata;
+
+ /*
+ * free memory for each section of config data that was
+ * allocated
+ */
+ if (cd->basedir != NULL)
+ isc_mem_free(ns_g_mctx, cd->basedir);
+
+ if (cd->datadir != NULL)
+ isc_mem_free(ns_g_mctx, cd->datadir);
+
+ if (cd->xfrdir != NULL)
+ isc_mem_free(ns_g_mctx, cd->xfrdir);
+
+ /* hold memory context to use later */
+ mctx = cd->mctx;
+
+ /* free config data memory */
+ isc_mem_put(mctx, cd, sizeof(config_data_t));
+
+ /* detach memory from context */
+ isc_mem_detach(&mctx);
+}
+
+static dns_sdlzmethods_t dlz_fs_methods = {
+ fs_create,
+ fs_destroy,
+ fs_findzone,
+ fs_lookup,
+ NULL,
+ fs_allnodes,
+ fs_allowzonexfr
+};
+
+/*%
+ * Wrapper around dns_sdlzregister().
+ */
+isc_result_t
+dlz_fs_init(void)
+{
+ isc_result_t result;
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Registering DLZ filesystem driver.");
+
+ result = dns_sdlzregister("filesystem", &dlz_fs_methods, NULL,
+ DNS_SDLZFLAG_RELATIVEOWNER |
+ DNS_SDLZFLAG_RELATIVERDATA,
+ ns_g_mctx, &dlz_fs);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+ return result;
+}
+
+/*%
+ * Wrapper around dns_sdlzunregister().
+ */
+void
+dlz_fs_clear(void) {
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Unregistering DLZ filesystem driver.");
+
+ if (dlz_fs != NULL)
+ dns_sdlzunregister(&dlz_fs);
+}
+
+#endif
diff --git a/contrib/dlz/drivers/dlz_ldap_driver.c b/contrib/dlz/drivers/dlz_ldap_driver.c
new file mode 100644
index 0000000..35d7548
--- /dev/null
+++ b/contrib/dlz/drivers/dlz_ldap_driver.c
@@ -0,0 +1,1339 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef DLZ_LDAP
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <dns/log.h>
+#include <dns/sdlz.h>
+#include <dns/result.h>
+
+#include <isc/mem.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+
+#include <dlz/sdlz_helper.h>
+#include <dlz/dlz_ldap_driver.h>
+
+/*
+ * Need older API functions from ldap.h.
+ */
+#define LDAP_DEPRECATED 1
+
+#include <ldap.h>
+
+#define SIMPLE "simple"
+#define KRB41 "krb41"
+#define KRB42 "krb42"
+#define V2 "v2"
+#define V3 "v3"
+
+static dns_sdlzimplementation_t *dlz_ldap = NULL;
+
+#define dbc_search_limit 30
+#define ALLNODES 1
+#define ALLOWXFR 2
+#define AUTHORITY 3
+#define FINDZONE 4
+#define LOOKUP 5
+
+/*%
+ * Structure to hold everthing needed by this "instance" of the LDAP
+ * driver remember, the driver code is only loaded once, but may have
+ * many separate instances.
+ */
+
+typedef struct {
+
+#ifdef ISC_PLATFORM_USETHREADS
+ db_list_t *db; /*%< handle to a list of DB */
+#else
+ dbinstance_t *db; /*%< handle to db */
+#endif
+ int method; /*%< security authentication method */
+ char *user; /*%< who is authenticating */
+ char *cred; /*%< password for simple authentication method */
+ int protocol; /*%< LDAP communication protocol version */
+ char *hosts; /*%< LDAP server hosts */
+
+} ldap_instance_t;
+
+/* forward references */
+
+static isc_result_t
+dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name);
+
+static void
+dlz_ldap_destroy(void *driverarg, void *dbdata);
+
+/*
+ * Private methods
+ */
+
+/*% checks that the LDAP URL parameters make sense */
+
+static isc_result_t
+dlz_ldap_checkURL(char *URL, int attrCnt, const char *msg) {
+
+ isc_result_t result = ISC_R_SUCCESS;
+ int ldap_result;
+ LDAPURLDesc *ldap_url = NULL;
+
+ if (!ldap_is_ldap_url(URL)) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%s query is not a valid LDAP URL", msg);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ ldap_result = ldap_url_parse(URL, &ldap_url);
+ if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "parsing %s query failed", msg);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ if (ldap_count_values(ldap_url->lud_attrs) < attrCnt) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%s query must specify at least "
+ "%d attributes to return",
+ msg, attrCnt);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ if (ldap_url->lud_host != NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%s query must not specify a host", msg);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ if (ldap_url->lud_port != 389) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%s query must not specify a port", msg);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ if (ldap_url->lud_dn == NULL || strlen (ldap_url->lud_dn) < 1) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%s query must specify a search base", msg);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ if (ldap_url->lud_exts != NULL || ldap_url->lud_crit_exts != 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%s uses extensions. "
+ "The driver does not support LDAP extensions.",
+ msg);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ cleanup:
+
+ if (ldap_url != NULL)
+ ldap_free_urldesc(ldap_url);
+
+ return result;
+}
+/*% Connects / reconnects to LDAP server */
+
+static isc_result_t
+dlz_ldap_connect(ldap_instance_t *dbi, dbinstance_t *dbc) {
+
+ isc_result_t result;
+ int ldap_result;
+
+ /* if we have a connection, get ride of it. */
+ if (dbc->dbconn != NULL) {
+ ldap_unbind_s((LDAP *) dbc->dbconn);
+ dbc->dbconn = NULL;
+ }
+
+ /* now connect / reconnect. */
+
+ /* initialize. */
+ dbc->dbconn = ldap_init(dbi->hosts, LDAP_PORT);
+ if (dbc->dbconn == NULL)
+ return ISC_R_NOMEMORY;
+
+ /* set protocol version. */
+ ldap_result = ldap_set_option((LDAP *) dbc->dbconn,
+ LDAP_OPT_PROTOCOL_VERSION,
+ &(dbi->protocol));
+ if (ldap_result != LDAP_SUCCESS) {
+ result = ISC_R_NOPERM;
+ goto cleanup;
+ }
+
+ /* "bind" to server. i.e. send username / pass */
+ ldap_result = ldap_bind_s((LDAP *) dbc->dbconn, dbi->user,
+ dbi->cred, dbi->method);
+ if (ldap_result != LDAP_SUCCESS) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ return ISC_R_SUCCESS;
+
+ cleanup:
+
+ /* cleanup if failure. */
+ if (dbc->dbconn != NULL) {
+ ldap_unbind_s((LDAP *) dbc->dbconn);
+ dbc->dbconn = NULL;
+ }
+
+ return result;
+}
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+
+/*%
+ * Properly cleans up a list of database instances.
+ * This function is only used when the driver is compiled for
+ * multithreaded operation.
+ */
+static void
+ldap_destroy_dblist(db_list_t *dblist)
+{
+
+ dbinstance_t *ndbi = NULL;
+ dbinstance_t *dbi = NULL;
+
+ /* get the first DBI in the list */
+ ndbi = ISC_LIST_HEAD(*dblist);
+
+ /* loop through the list */
+ while (ndbi != NULL) {
+ dbi = ndbi;
+ /* get the next DBI in the list */
+ ndbi = ISC_LIST_NEXT(dbi, link);
+ /* release DB connection */
+ if (dbi->dbconn != NULL)
+ ldap_unbind_s((LDAP *) dbi->dbconn);
+ /* release all memory that comprised a DBI */
+ destroy_sqldbinstance(dbi);
+ }
+ /* release memory for the list structure */
+ isc_mem_put(ns_g_mctx, dblist, sizeof(db_list_t));
+}
+
+/*%
+ * Loops through the list of DB instances, attempting to lock
+ * on the mutex. If successful, the DBI is reserved for use
+ * and the thread can perform queries against the database.
+ * If the lock fails, the next one in the list is tried.
+ * looping continues until a lock is obtained, or until
+ * the list has been searched dbc_search_limit times.
+ * This function is only used when the driver is compiled for
+ * multithreaded operation.
+ */
+
+static dbinstance_t *
+ldap_find_avail_conn(db_list_t *dblist)
+{
+ dbinstance_t *dbi = NULL;
+ dbinstance_t *head;
+ int count = 0;
+
+ /* get top of list */
+ head = dbi = ISC_LIST_HEAD(*dblist);
+
+ /* loop through list */
+ while (count < dbc_search_limit) {
+ /* try to lock on the mutex */
+ if (isc_mutex_trylock(&dbi->instance_lock) == ISC_R_SUCCESS)
+ return dbi; /* success, return the DBI for use. */
+
+ /* not successful, keep trying */
+ dbi = ISC_LIST_NEXT(dbi, link);
+
+ /* check to see if we have gone to the top of the list. */
+ if (dbi == NULL) {
+ count++;
+ dbi = head;
+ }
+ }
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "LDAP driver unable to find available connection "
+ "after searching %d times",
+ count);
+ return NULL;
+}
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+static isc_result_t
+ldap_process_results(LDAP *dbc, LDAPMessage *msg, char ** attrs,
+ void *ptr, isc_boolean_t allnodes)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ int i = 0;
+ int j;
+ int len;
+ char *attribute = NULL;
+ LDAPMessage *entry;
+ char *endp = NULL;
+ char *host = NULL;
+ char *type = NULL;
+ char *data = NULL;
+ char **vals = NULL;
+ int ttl;
+
+ /* make sure there are at least some attributes to process. */
+ REQUIRE(attrs != NULL || attrs[0] != NULL);
+
+ /* get the first entry to process */
+ entry = ldap_first_entry(dbc, msg);
+ if (entry == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "LDAP no entries to process.");
+ return ISC_R_FAILURE;
+ }
+
+ /* loop through all entries returned */
+ while (entry != NULL) {
+
+ /* reset for this loop */
+ ttl = 0;
+ len = 0;
+ i = 0;
+ attribute = attrs[i];
+
+ /* determine how much space we need for data string */
+ for (j=0; attrs[j] != NULL; j++) {
+ /* get the list of values for this attribute. */
+ vals = ldap_get_values(dbc, entry, attrs[j]);
+ /* skip empty attributes. */
+ if (vals == NULL || ldap_count_values(vals) < 1)
+ continue;
+ /*
+ * we only use the first value. this driver
+ * does not support multi-valued attributes.
+ */
+ len = len + strlen(vals[0]) + 1;
+ /* free vals for next loop */
+ ldap_value_free(vals);
+ } /* end for (j=0; attrs[j] != NULL, j++) loop */
+
+ /* allocate memory for data string */
+ data = isc_mem_allocate(ns_g_mctx, len + 1);
+ if (data == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver unable to allocate memory "
+ "while processing results");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /*
+ * Make sure data is null termed at the beginning so
+ * we can check if any data was stored to it later.
+ */
+ data[0] = '\0';
+
+ /* reset j to re-use below */
+ j = 0;
+
+ /* loop through the attributes in the order specified. */
+ while (attribute != NULL) {
+
+ /* get the list of values for this attribute. */
+ vals = ldap_get_values(dbc, entry, attribute);
+
+ /* skip empty attributes. */
+ if (vals == NULL || vals[0] == NULL) {
+ /* increment attibute pointer */
+ attribute = attrs[++i];
+ /* start loop over */
+ continue;
+ }
+
+ /*
+ * j initially = 0. Increment j each time we
+ * set a field that way next loop will set
+ * next field.
+ */
+ switch(j) {
+ case 0:
+ j++;
+ /*
+ * convert text to int, make sure it
+ * worked right
+ */
+ ttl = strtol(vals[0], &endp, 10);
+ if (*endp != '\0' || ttl < 0) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ,
+ ISC_LOG_ERROR,
+ "LDAP driver ttl must "
+ "be a postive number");
+ goto cleanup;
+ }
+ break;
+ case 1:
+ j++;
+ type = isc_mem_strdup(ns_g_mctx, vals[0]);
+ break;
+ case 2:
+ j++;
+ if (allnodes == isc_boolean_true) {
+ host = isc_mem_strdup(ns_g_mctx,
+ vals[0]);
+ } else {
+ strcpy(data, vals[0]);
+ }
+ break;
+ case 3:
+ j++;
+ if (allnodes == isc_boolean_true) {
+ strcpy(data, vals[0]);
+ } else {
+ strcat(data, " ");
+ strcat(data, vals[0]);
+ }
+ break;
+ default:
+ strcat(data, " ");
+ strcat(data, vals[0]);
+ break;
+ } /* end switch(j) */
+
+ /* free values */
+ ldap_value_free(vals);
+ vals = NULL;
+
+ /* increment attibute pointer */
+ attribute = attrs[++i];
+ } /* end while (attribute != NULL) */
+
+ if (type == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver unable "
+ "to retrieve dns type");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ if (strlen(data) < 1) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver unable "
+ "to retrieve dns data");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ if (allnodes == isc_boolean_true) {
+ if (strcasecmp(host, "~") == 0)
+ result = dns_sdlz_putnamedrr(
+ (dns_sdlzallnodes_t *) ptr,
+ "*", type, ttl, data);
+ else
+ result = dns_sdlz_putnamedrr(
+ (dns_sdlzallnodes_t *) ptr,
+ host, type, ttl, data);
+ }
+ else
+ result = dns_sdlz_putrr((dns_sdlzlookup_t *) ptr,
+ type, ttl, data);
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver failed "
+ "while sending data to Bind.");
+ goto cleanup;
+ }
+
+ /* free memory for type, data and host for next loop */
+ isc_mem_free(ns_g_mctx, type);
+ isc_mem_free(ns_g_mctx, data);
+ if (host != NULL)
+ isc_mem_free(ns_g_mctx, host);
+
+ /* get the next entry to process */
+ entry = ldap_next_entry(dbc, entry);
+ } /* end while (entry != NULL) */
+
+ cleanup:
+
+ /* de-allocate memory */
+ if (vals != NULL)
+ ldap_value_free(vals);
+ if (host != NULL)
+ isc_mem_free(ns_g_mctx, host);
+ if (type != NULL)
+ isc_mem_free(ns_g_mctx, type);
+ if (data != NULL)
+ isc_mem_free(ns_g_mctx, data);
+
+ return result;
+}
+
+/*%
+ * This function is the real core of the driver. Zone, record
+ * and client strings are passed in (or NULL is passed if the
+ * string is not available). The type of query we want to run
+ * is indicated by the query flag, and the dbdata object is passed
+ * passed in to. dbdata really holds either:
+ * 1) a list of database instances (in multithreaded mode) OR
+ * 2) a single database instance (in single threaded mode)
+ * The function will construct the query and obtain an available
+ * database instance (DBI). It will then run the query and hopefully
+ * obtain a result set.
+ */
+static isc_result_t
+ldap_get_results(const char *zone, const char *record,
+ const char *client, unsigned int query,
+ void *dbdata, void *ptr)
+{
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+ char *querystring = NULL;
+ LDAPURLDesc *ldap_url = NULL;
+ int ldap_result = 0;
+ LDAPMessage *ldap_msg = NULL;
+ int i;
+ int entries;
+
+ /* get db instance / connection */
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* find an available DBI from the list */
+ dbi = ldap_find_avail_conn((db_list_t *)
+ ((ldap_instance_t *)dbdata)->db);
+
+#else /* ISC_PLATFORM_USETHREADS */
+
+ /*
+ * only 1 DBI - no need to lock instance lock either
+ * only 1 thread in the whole process, no possible contention.
+ */
+ dbi = (dbinstance_t *) ((ldap_instance_t *)dbdata)->db;
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* if DBI is null, can't do anything else */
+ if (dbi == NULL)
+ return ISC_R_FAILURE;
+
+ /* set fields */
+ if (zone != NULL) {
+ dbi->zone = isc_mem_strdup(ns_g_mctx, zone);
+ if (dbi->zone == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else {
+ dbi->zone = NULL;
+ }
+ if (record != NULL) {
+ dbi->record = isc_mem_strdup(ns_g_mctx, record);
+ if (dbi->record == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else {
+ dbi->record = NULL;
+ }
+ if (client != NULL) {
+ dbi->client = isc_mem_strdup(ns_g_mctx, client);
+ if (dbi->client == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else {
+ dbi->client = NULL;
+ }
+
+ /* what type of query are we going to run? */
+ switch(query) {
+ case ALLNODES:
+ /*
+ * if the query was not passed in from the config file
+ * then we can't run it. return not_implemented, so
+ * it's like the code for that operation was never
+ * built into the driver.... AHHH flexibility!!!
+ */
+ if (dbi->allnodes_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ } else {
+ querystring = build_querystring(ns_g_mctx,
+ dbi->allnodes_q);
+ }
+ break;
+ case ALLOWXFR:
+ /* same as comments as ALLNODES */
+ if (dbi->allowxfr_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ } else {
+ querystring = build_querystring(ns_g_mctx,
+ dbi->allowxfr_q);
+ }
+ break;
+ case AUTHORITY:
+ /* same as comments as ALLNODES */
+ if (dbi->authority_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ } else {
+ querystring = build_querystring(ns_g_mctx,
+ dbi->authority_q);
+ }
+ break;
+ case FINDZONE:
+ /* this is required. It's the whole point of DLZ! */
+ if (dbi->findzone_q == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "No query specified for findzone. "
+ "Findzone requires a query");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ } else {
+ querystring = build_querystring(ns_g_mctx,
+ dbi->findzone_q);
+ }
+ break;
+ case LOOKUP:
+ /* this is required. It's also a major point of DLZ! */
+ if (dbi->lookup_q == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "No query specified for lookup. "
+ "Lookup requires a query");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ } else {
+ querystring = build_querystring(ns_g_mctx,
+ dbi->lookup_q);
+ }
+ break;
+ default:
+ /*
+ * this should never happen. If it does, the code is
+ * screwed up!
+ */
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "Incorrect query flag passed to "
+ "ldap_get_results");
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+ /* if the querystring is null, Bummer, outta RAM. UPGRADE TIME!!! */
+ if (querystring == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ /*
+ * output the full query string during debug so we can see
+ * what lame error the query has.
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "\nQuery String: %s\n", querystring);
+
+ /* break URL down into it's component parts, if error cleanup */
+ ldap_result = ldap_url_parse(querystring, &ldap_url);
+ if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ for (i=0; i < 3; i++) {
+
+ /*
+ * dbi->dbconn may be null if trying to reconnect on a
+ * previous query failed.
+ */
+ if (dbi->dbconn == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "LDAP driver attempting to re-connect");
+
+ result = dlz_ldap_connect((ldap_instance_t *) dbdata,
+ dbi);
+ if (result != ISC_R_SUCCESS) {
+ result = ISC_R_FAILURE;
+ continue;
+ }
+ }
+
+ /* perform ldap search syncronously */
+ ldap_result = ldap_search_s((LDAP *) dbi->dbconn,
+ ldap_url->lud_dn,
+ ldap_url->lud_scope,
+ ldap_url->lud_filter,
+ ldap_url->lud_attrs, 0, &ldap_msg);
+
+ /*
+ * check return code. No such object is ok, just
+ * didn't find what we wanted
+ */
+ switch(ldap_result) {
+ case LDAP_NO_SUCH_OBJECT:
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "No object found matching "
+ "query requirements");
+ result = ISC_R_NOTFOUND;
+ goto cleanup;
+ break;
+ case LDAP_SUCCESS: /* on success do nothing */
+ result = ISC_R_SUCCESS;
+ i = 3;
+ break;
+ case LDAP_SERVER_DOWN:
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "LDAP driver attempting to re-connect");
+ result = dlz_ldap_connect((ldap_instance_t *) dbdata,
+ dbi);
+ if (result != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ break;
+ default:
+ /*
+ * other errors not ok. Log error message and
+ * get out
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP error: %s",
+ ldap_err2string(ldap_result));
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ break;
+ } /* close switch(ldap_result) */
+ } /* end for (int i=0 i < 3; i++) */
+
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ switch(query) {
+ case ALLNODES:
+ result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg,
+ ldap_url->lud_attrs,
+ ptr, isc_boolean_true);
+ break;
+ case AUTHORITY:
+ case LOOKUP:
+ result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg,
+ ldap_url->lud_attrs,
+ ptr, isc_boolean_false);
+ break;
+ case ALLOWXFR:
+ entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
+ if (entries == 0)
+ result = ISC_R_NOPERM;
+ else if (entries > 0)
+ result = ISC_R_SUCCESS;
+ else
+ result = ISC_R_FAILURE;
+ break;
+ case FINDZONE:
+ entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
+ if (entries == 0)
+ result = ISC_R_NOTFOUND;
+ else if (entries > 0)
+ result = ISC_R_SUCCESS;
+ else
+ result = ISC_R_FAILURE;
+ break;
+ default:
+ /*
+ * this should never happen. If it does, the code is
+ * screwed up!
+ */
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "Incorrect query flag passed to "
+ "ldap_get_results");
+ result = ISC_R_UNEXPECTED;
+ }
+
+
+ cleanup:
+ /* it's always good to cleanup after yourself */
+
+ /* if we retrieved results, free them */
+ if (ldap_msg != NULL)
+ ldap_msgfree(ldap_msg);
+
+ if (ldap_url != NULL)
+ ldap_free_urldesc(ldap_url);
+
+ /* cleanup */
+ if (dbi->zone != NULL)
+ isc_mem_free(ns_g_mctx, dbi->zone);
+ if (dbi->record != NULL)
+ isc_mem_free(ns_g_mctx, dbi->record);
+ if (dbi->client != NULL)
+ isc_mem_free(ns_g_mctx, dbi->client);
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* release the lock so another thread can use this dbi */
+ isc_mutex_unlock(&dbi->instance_lock);
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* release query string */
+ if (querystring != NULL)
+ isc_mem_free(ns_g_mctx, querystring );
+
+ /* return result */
+ return result;
+}
+
+/*
+ * DLZ methods
+ */
+
+static isc_result_t
+dlz_ldap_allowzonexfr(void *driverarg, void *dbdata, const char *name,
+ const char *client)
+{
+ isc_result_t result;
+
+ UNUSED(driverarg);
+
+ /* check to see if we are authoritative for the zone first */
+ result = dlz_ldap_findzone(driverarg, dbdata, name);
+ if (result != ISC_R_SUCCESS) {
+ return result;
+ }
+
+ /* get all the zone data */
+ return ldap_get_results(name, NULL, client, ALLOWXFR, dbdata, NULL);
+}
+
+static isc_result_t
+dlz_ldap_allnodes(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzallnodes_t *allnodes)
+{
+ UNUSED(driverarg);
+ return ldap_get_results(zone, NULL, NULL, ALLNODES, dbdata, allnodes);
+}
+
+static isc_result_t
+dlz_ldap_authority(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzlookup_t *lookup)
+{
+ UNUSED(driverarg);
+ return ldap_get_results(zone, NULL, NULL, AUTHORITY, dbdata, lookup);
+}
+
+static isc_result_t
+dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name)
+{
+ UNUSED(driverarg);
+ return ldap_get_results(name, NULL, NULL, FINDZONE, dbdata, NULL);
+}
+
+static isc_result_t
+dlz_ldap_lookup(const char *zone, const char *name, void *driverarg,
+ void *dbdata, dns_sdlzlookup_t *lookup)
+{
+ UNUSED(driverarg);
+ if (strcmp(name, "*") == 0)
+ return ldap_get_results(zone, "~", NULL,
+ LOOKUP, dbdata, lookup);
+ else
+ return ldap_get_results(zone, name, NULL,
+ LOOKUP, dbdata, lookup);
+}
+
+
+static isc_result_t
+dlz_ldap_create(const char *dlzname, unsigned int argc, char *argv[],
+ void *driverarg, void **dbdata)
+{
+
+ isc_result_t result;
+ ldap_instance_t *ldap_inst = NULL;
+ dbinstance_t *dbi = NULL;
+ int protocol;
+ int method;
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /* if multi-threaded, we need a few extra variables. */
+ int dbcount;
+ char *endp;
+/* db_list_t *dblist = NULL; */
+ int i;
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ UNUSED(dlzname);
+ UNUSED(driverarg);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /* if debugging, let user know we are multithreaded. */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "LDAP driver running multithreaded");
+#else /* ISC_PLATFORM_USETHREADS */
+ /* if debugging, let user know we are single threaded. */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "LDAP driver running single threaded");
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ if (argc < 9) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver requires at least "
+ "8 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* no more than 13 arg's should be passed to the driver */
+ if (argc > 12) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver cannot accept more than "
+ "11 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* determine protocol version. */
+ if (strncasecmp(argv[2], V2, strlen(V2)) == 0) {
+ protocol = 2;
+ } else if (strncasecmp(argv[2], V3, strlen(V3)) == 0) {
+ protocol = 3;
+ } else {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver protocol must be either %s or %s",
+ V2, V3);
+ return (ISC_R_FAILURE);
+ }
+
+ /* determine connection method. */
+ if (strncasecmp(argv[3], SIMPLE, strlen(SIMPLE)) == 0) {
+ method = LDAP_AUTH_SIMPLE;
+ } else if (strncasecmp(argv[3], KRB41, strlen(KRB41)) == 0) {
+ method = LDAP_AUTH_KRBV41;
+ } else if (strncasecmp(argv[3], KRB42, strlen(KRB42)) == 0) {
+ method = LDAP_AUTH_KRBV42;
+ } else {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver authentication method must be "
+ "one of %s, %s or %s",
+ SIMPLE, KRB41, KRB42);
+ return (ISC_R_FAILURE);
+ }
+
+ /* multithreaded build can have multiple DB connections */
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* check how many db connections we should create */
+ dbcount = strtol(argv[1], &endp, 10);
+ if (*endp != '\0' || dbcount < 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver database connection count "
+ "must be positive.");
+ return (ISC_R_FAILURE);
+ }
+#endif
+
+ /* check that LDAP URL parameters make sense */
+ switch(argc) {
+ case 12:
+ result = dlz_ldap_checkURL(argv[11], 0, "allow zone transfer");
+ if (result != ISC_R_SUCCESS)
+ return result;
+ case 11:
+ result = dlz_ldap_checkURL(argv[10], 3, "all nodes");
+ if (result != ISC_R_SUCCESS)
+ return result;
+ case 10:
+ if (strlen(argv[9]) > 0) {
+ result = dlz_ldap_checkURL(argv[9], 3, "authority");
+ if (result != ISC_R_SUCCESS)
+ return result;
+ }
+ case 9:
+ result = dlz_ldap_checkURL(argv[8], 3, "lookup");
+ if (result != ISC_R_SUCCESS)
+ return result;
+ result = dlz_ldap_checkURL(argv[7], 0, "find zone");
+ if (result != ISC_R_SUCCESS)
+ return result;
+ break;
+ default:
+ /* not really needed, should shut up compiler. */
+ result = ISC_R_FAILURE;
+ }
+
+ /* allocate memory for LDAP instance */
+ ldap_inst = isc_mem_get(ns_g_mctx, sizeof(ldap_instance_t));
+ if (ldap_inst == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(ldap_inst, 0, sizeof(ldap_instance_t));
+
+ /* store info needed to automatically re-connect. */
+ ldap_inst->protocol = protocol;
+ ldap_inst->method = method;
+ ldap_inst->hosts = isc_mem_strdup(ns_g_mctx, argv[6]);
+ if (ldap_inst->hosts == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ ldap_inst->user = isc_mem_strdup(ns_g_mctx, argv[4]);
+ if (ldap_inst->user == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ ldap_inst->cred = isc_mem_strdup(ns_g_mctx, argv[5]);
+ if (ldap_inst->cred == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /* allocate memory for database connection list */
+ ldap_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
+ if (ldap_inst->db == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ /* initialize DB connection list */
+ ISC_LIST_INIT(*(ldap_inst->db));
+
+ /*
+ * create the appropriate number of database instances (DBI)
+ * append each new DBI to the end of the list
+ */
+ for (i = 0; i < dbcount; i++) {
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* how many queries were passed in from config file? */
+ switch(argc) {
+ case 9:
+ result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
+ NULL, argv[7], argv[8],
+ NULL, &dbi);
+ break;
+ case 10:
+ result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
+ argv[9], argv[7], argv[8],
+ NULL, &dbi);
+ break;
+ case 11:
+ result = build_sqldbinstance(ns_g_mctx, argv[10], NULL,
+ argv[9], argv[7], argv[8],
+ NULL, &dbi);
+ break;
+ case 12:
+ result = build_sqldbinstance(ns_g_mctx, argv[10],
+ argv[11], argv[9],
+ argv[7], argv[8],
+ NULL, &dbi);
+ break;
+ default:
+ /* not really needed, should shut up compiler. */
+ result = ISC_R_FAILURE;
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "LDAP driver created "
+ "database instance object.");
+ } else { /* unsuccessful?, log err msg and cleanup. */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver could not create "
+ "database instance object.");
+ goto cleanup;
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /* when multithreaded, build a list of DBI's */
+ ISC_LINK_INIT(dbi, link);
+ ISC_LIST_APPEND(*(ldap_inst->db), dbi, link);
+#else
+ /*
+ * when single threaded, hold onto the one connection
+ * instance.
+ */
+ ldap_inst->db = dbi;
+
+#endif
+ /* attempt to connect */
+ result = dlz_ldap_connect(ldap_inst, dbi);
+
+ /*
+ * if db connection cannot be created, log err msg and
+ * cleanup.
+ */
+ switch(result) {
+ /* success, do nothing */
+ case ISC_R_SUCCESS:
+ break;
+ /*
+ * no memory means ldap_init could not
+ * allocate memory
+ */
+ case ISC_R_NOMEMORY:
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver could not allocate memory "
+ "for connection number %u",
+ i+1);
+#else
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver could not allocate memory "
+ "for connection");
+#endif
+ goto cleanup;
+ break;
+ /*
+ * no perm means ldap_set_option could not set
+ * protocol version
+ */
+ case ISC_R_NOPERM:
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver could not "
+ "set protocol version.");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ break;
+ /* failure means couldn't connect to ldap server */
+ case ISC_R_FAILURE:
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver could not "
+ "bind connection number %u to server.",
+ i+1);
+#else
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "LDAP driver could not "
+ "bind connection to server.");
+#endif
+ goto cleanup;
+ break;
+ /*
+ * default should never happen. If it does,
+ * major errors.
+ */
+ default:
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dlz_ldap_create() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ break;
+ } /* end switch(result) */
+
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* set DBI = null for next loop through. */
+ dbi = NULL;
+ } /* end for loop */
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+
+ /* set dbdata to the ldap_instance we created. */
+ *dbdata = ldap_inst;
+
+ /* hey, we got through all of that ok, return success. */
+ return(ISC_R_SUCCESS);
+
+ cleanup:
+
+ dlz_ldap_destroy(NULL, ldap_inst);
+
+ return(ISC_R_FAILURE);
+}
+
+void
+dlz_ldap_destroy(void *driverarg, void *dbdata)
+{
+
+ UNUSED(driverarg);
+
+ if (dbdata != NULL) {
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* cleanup the list of DBI's */
+ ldap_destroy_dblist((db_list_t *)
+ ((ldap_instance_t *)dbdata)->db);
+
+#else /* ISC_PLATFORM_USETHREADS */
+
+ /* release connection */
+ if (((ldap_instance_t *)dbdata)->db->dbconn != NULL)
+ ldap_unbind_s((LDAP *)
+ ((ldap_instance_t *)dbdata)->db->dbconn);
+
+ /* destroy single DB instance */
+ destroy_sqldbinstance(((ldap_instance_t *)dbdata)->db);
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ if (((ldap_instance_t *)dbdata)->hosts != NULL)
+ isc_mem_free(ns_g_mctx,
+ ((ldap_instance_t *)dbdata)->hosts);
+
+ if (((ldap_instance_t *)dbdata)->user != NULL)
+ isc_mem_free(ns_g_mctx,
+ ((ldap_instance_t *)dbdata)->user);
+
+ if (((ldap_instance_t *)dbdata)->cred != NULL)
+ isc_mem_free(ns_g_mctx,
+ ((ldap_instance_t *)dbdata)->cred);
+
+ isc_mem_put(ns_g_mctx, dbdata, sizeof(ldap_instance_t));
+ }
+}
+
+static dns_sdlzmethods_t dlz_ldap_methods = {
+ dlz_ldap_create,
+ dlz_ldap_destroy,
+ dlz_ldap_findzone,
+ dlz_ldap_lookup,
+ dlz_ldap_authority,
+ dlz_ldap_allnodes,
+ dlz_ldap_allowzonexfr
+};
+
+/*%
+ * Wrapper around dns_sdlzregister().
+ */
+isc_result_t
+dlz_ldap_init(void) {
+ isc_result_t result;
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Registering DLZ ldap driver.");
+
+ result = dns_sdlzregister("ldap", &dlz_ldap_methods, NULL,
+ DNS_SDLZFLAG_RELATIVEOWNER |
+ DNS_SDLZFLAG_RELATIVERDATA,
+ ns_g_mctx, &dlz_ldap);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+
+ return result;
+}
+
+/*%
+ * Wrapper around dns_sdlzunregister().
+ */
+void
+dlz_ldap_clear(void) {
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Unregistering DLZ ldap driver.");
+
+ if (dlz_ldap != NULL)
+ dns_sdlzunregister(&dlz_ldap);
+}
+
+#endif
diff --git a/contrib/dlz/drivers/dlz_mysql_driver.c b/contrib/dlz/drivers/dlz_mysql_driver.c
new file mode 100644
index 0000000..ea32d39
--- /dev/null
+++ b/contrib/dlz/drivers/dlz_mysql_driver.c
@@ -0,0 +1,1060 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef DLZ_MYSQL
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <dns/log.h>
+#include <dns/sdlz.h>
+#include <dns/result.h>
+
+#include <isc/mem.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+
+#include <dlz/sdlz_helper.h>
+#include <dlz/dlz_mysql_driver.h>
+
+#include <mysql.h>
+
+static dns_sdlzimplementation_t *dlz_mysql = NULL;
+
+#define dbc_search_limit 30
+#define ALLNODES 1
+#define ALLOWXFR 2
+#define AUTHORITY 3
+#define FINDZONE 4
+#define COUNTZONE 5
+#define LOOKUP 6
+
+#define safeGet(in) in == NULL ? "" : in
+
+/*
+ * Private methods
+ */
+
+/*%
+ * Allocates memory for a new string, and then constructs the new
+ * string by "escaping" the input string. The new string is
+ * safe to be used in queries. This is necessary because we cannot
+ * be sure of what types of strings are passed to us, and we don't
+ * want special characters in the string causing problems.
+ */
+
+static char *
+mysqldrv_escape_string(MYSQL *mysql, const char *instr) {
+
+ char *outstr;
+ unsigned int len;
+
+ if (instr == NULL)
+ return NULL;
+
+ len = strlen(instr);
+
+ outstr = isc_mem_allocate(ns_g_mctx ,(2 * len * sizeof(char)) + 1);
+ if (outstr == NULL)
+ return NULL;
+
+ mysql_real_escape_string(mysql, outstr, instr, len);
+
+ return outstr;
+}
+
+/*%
+ * This function is the real core of the driver. Zone, record
+ * and client strings are passed in (or NULL is passed if the
+ * string is not available). The type of query we want to run
+ * is indicated by the query flag, and the dbdata object is passed
+ * passed in to. dbdata really holds a single database instance.
+ * The function will construct and run the query, hopefully getting
+ * a result set.
+ */
+
+static isc_result_t
+mysql_get_resultset(const char *zone, const char *record,
+ const char *client, unsigned int query,
+ void *dbdata, MYSQL_RES **rs)
+{
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+ char *querystring = NULL;
+ unsigned int i = 0;
+ unsigned int j = 0;
+ int qres = 0;
+
+ if (query != COUNTZONE)
+ REQUIRE(*rs == NULL);
+ else
+ REQUIRE(rs == NULL);
+
+ /* get db instance / connection */
+ dbi = (dbinstance_t *) dbdata;
+
+ /* if DBI is null, can't do anything else */
+ if (dbi == NULL) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /* what type of query are we going to run? */
+ switch(query) {
+ case ALLNODES:
+ /*
+ * if the query was not passed in from the config file
+ * then we can't run it. return not_implemented, so
+ * it's like the code for that operation was never
+ * built into the driver.... AHHH flexibility!!!
+ */
+ if (dbi->allnodes_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ break;
+ case ALLOWXFR:
+ /* same as comments as ALLNODES */
+ if (dbi->allowxfr_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ break;
+ case AUTHORITY:
+ /* same as comments as ALLNODES */
+ if (dbi->authority_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ break;
+ case FINDZONE:
+ /* this is required. It's the whole point of DLZ! */
+ if (dbi->findzone_q == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "No query specified for findzone. "
+ "Findzone requires a query");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ break;
+ case COUNTZONE:
+ /* same as comments as ALLNODES */
+ if (dbi->countzone_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ break;
+ case LOOKUP:
+ /* this is required. It's also a major point of DLZ! */
+ if (dbi->lookup_q == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "No query specified for lookup. "
+ "Lookup requires a query");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ break;
+ default:
+ /*
+ * this should never happen. If it does, the code is
+ * screwed up!
+ */
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "Incorrect query flag passed to "
+ "mysql_get_resultset");
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+
+ /*
+ * was a zone string passed? If so, make it safe for use in
+ * queries.
+ */
+ if (zone != NULL) {
+ dbi->zone = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
+ zone);
+ if (dbi->zone == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else { /* no string passed, set the string pointer to NULL */
+ dbi->zone = NULL;
+ }
+
+ /*
+ * was a record string passed? If so, make it safe for use in
+ * queries.
+ */
+ if (record != NULL) {
+ dbi->record = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
+ record);
+ if (dbi->record == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else { /* no string passed, set the string pointer to NULL */
+ dbi->record = NULL;
+ }
+
+ /*
+ * was a client string passed? If so, make it safe for use in
+ * queries.
+ */
+ if (client != NULL) {
+ dbi->client = mysqldrv_escape_string((MYSQL *) dbi->dbconn,
+ client);
+ if (dbi->client == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else { /* no string passed, set the string pointer to NULL */
+ dbi->client = NULL;
+ }
+
+ /*
+ * what type of query are we going to run? this time we build
+ * the actual query to run.
+ */
+ switch(query) {
+ case ALLNODES:
+ querystring = build_querystring(ns_g_mctx, dbi->allnodes_q);
+ break;
+ case ALLOWXFR:
+ querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q);
+ break;
+ case AUTHORITY:
+ querystring = build_querystring(ns_g_mctx, dbi->authority_q);
+ break;
+ case FINDZONE:
+ querystring = build_querystring(ns_g_mctx, dbi->findzone_q);
+ break;
+ case COUNTZONE:
+ querystring = build_querystring(ns_g_mctx, dbi->countzone_q);
+ break;
+ case LOOKUP:
+ querystring = build_querystring(ns_g_mctx, dbi->lookup_q);
+ break;
+ default:
+ /*
+ * this should never happen. If it does, the code is
+ * screwed up!
+ */
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "Incorrect query flag passed to "
+ "mysql_get_resultset");
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+ /* if the querystring is null, Bummer, outta RAM. UPGRADE TIME!!! */
+ if (querystring == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ /*
+ * output the full query string during debug so we can see
+ * what lame error the query has.
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "\nQuery String: %s\n", querystring);
+
+ /* attempt query up to 3 times. */
+ for (i=0; i < 3; i++) {
+ qres = mysql_query((MYSQL *) dbi->dbconn, querystring);
+ if (qres == 0)
+ break;
+ for (j=0; mysql_ping((MYSQL *) dbi->dbconn) != 0 && j < 4; j++)
+ ;
+ }
+
+ if (qres == 0) {
+ result = ISC_R_SUCCESS;
+ if (query != COUNTZONE) {
+ *rs = mysql_store_result((MYSQL *) dbi->dbconn);
+ if (*rs == NULL)
+ result = ISC_R_FAILURE;
+ }
+ } else {
+ result = ISC_R_FAILURE;
+ }
+
+
+ cleanup:
+ /* it's always good to cleanup after yourself */
+
+ /* if we couldn't even get DBI, just return NULL */
+ if (dbi == NULL)
+ return ISC_R_FAILURE;
+
+ /* free dbi->zone string */
+ if (dbi->zone != NULL)
+ isc_mem_free(ns_g_mctx, dbi->zone);
+
+ /* free dbi->record string */
+ if (dbi->record != NULL)
+ isc_mem_free(ns_g_mctx, dbi->record);
+
+ /* free dbi->client string */
+ if (dbi->client != NULL)
+ isc_mem_free(ns_g_mctx, dbi->client);
+
+ /* release query string */
+ if (querystring != NULL)
+ isc_mem_free(ns_g_mctx, querystring);
+
+ /* return result */
+ return result;
+}
+
+/*%
+ * The processing of result sets for lookup and authority are
+ * exactly the same. So that functionality has been moved
+ * into this function to minimize code.
+ */
+
+static isc_result_t
+mysql_process_rs(dns_sdlzlookup_t *lookup, MYSQL_RES *rs)
+{
+ isc_result_t result = ISC_R_NOTFOUND;
+ MYSQL_ROW row;
+ unsigned int fields;
+ unsigned int j;
+ unsigned int len;
+ char *tmpString;
+ char *endp;
+ int ttl;
+
+ row = mysql_fetch_row(rs); /* get a row from the result set */
+ fields = mysql_num_fields(rs); /* how many columns in result set */
+ while (row != NULL) {
+ switch(fields) {
+ case 1:
+ /*
+ * one column in rs, it's the data field. use
+ * default type of A record, and default TTL
+ * of 86400
+ */
+ result = dns_sdlz_putrr(lookup, "a", 86400,
+ safeGet(row[0]));
+ break;
+ case 2:
+ /*
+ * two columns, data field, and data type.
+ * use default TTL of 86400.
+ */
+ result = dns_sdlz_putrr(lookup, safeGet(row[0]), 86400,
+ safeGet(row[1]));
+ break;
+ case 3:
+ /*
+ * three columns, all data no defaults.
+ * convert text to int, make sure it worked
+ * right.
+ */
+ ttl = strtol(safeGet(row[0]), &endp, 10);
+ if (*endp != '\0' || ttl < 0) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver ttl must be "
+ "a postive number");
+ }
+ result = dns_sdlz_putrr(lookup, safeGet(row[1]), ttl,
+ safeGet(row[2]));
+ break;
+ default:
+ /*
+ * more than 3 fields, concatenate the last
+ * ones together. figure out how long to make
+ * string.
+ */
+ for (j=2, len=0; j < fields; j++) {
+ len += strlen(safeGet(row[j])) + 1;
+ }
+ /*
+ * allocate string memory, allow for NULL to
+ * term string
+ */
+ tmpString = isc_mem_allocate(ns_g_mctx, len + 1);
+ if (tmpString == NULL) {
+ /* major bummer, need more ram */
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver unable "
+ "to allocate memory for "
+ "temporary string");
+ mysql_free_result(rs);
+ return (ISC_R_FAILURE); /* Yeah, I'd say! */
+ }
+ /* copy field to tmpString */
+ strcpy(tmpString, safeGet(row[2]));
+
+
+ /*
+ * concat the rest of fields together, space
+ * between each one.
+ */
+ for (j=3; j < fields; j++) {
+ strcat(tmpString, " ");
+ strcat(tmpString, safeGet(row[j]));
+ }
+ /* convert text to int, make sure it worked right */
+ ttl = strtol(safeGet(row[0]), &endp, 10);
+ if (*endp != '\0' || ttl < 0) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver ttl must be "
+ "a postive number");
+ }
+ /* ok, now tell Bind about it. */
+ result = dns_sdlz_putrr(lookup, safeGet(row[1]),
+ ttl, tmpString);
+ /* done, get rid of this thing. */
+ isc_mem_free(ns_g_mctx, tmpString);
+ }
+ /* I sure hope we were successful */
+ if (result != ISC_R_SUCCESS) {
+ /* nope, get rid of the Result set, and log a msg */
+ mysql_free_result(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "dns_sdlz_putrr returned error. "
+ "Error code was: %s",
+ isc_result_totext(result));
+ return (ISC_R_FAILURE);
+ }
+ row = mysql_fetch_row(rs); /* get next row */
+ }
+
+ /* free result set memory */
+ mysql_free_result(rs);
+
+ /* return result code */
+ return result;
+}
+
+/*
+ * SDLZ interface methods
+ */
+
+/*% determine if the zone is supported by (in) the database */
+
+static isc_result_t
+mysql_findzone(void *driverarg, void *dbdata, const char *name)
+{
+ isc_result_t result;
+ MYSQL_RES *rs = NULL;
+ my_ulonglong rows;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = mysql_get_resultset(name, NULL, NULL, FINDZONE, dbdata, &rs);
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS || rs == NULL) {
+ if (rs != NULL)
+ mysql_free_result(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver unable to return "
+ "result set for findzone query");
+ return (ISC_R_FAILURE);
+ }
+ /* count how many rows in result set */
+ rows = mysql_num_rows(rs);
+ /* get rid of result set, we are done with it. */
+ mysql_free_result(rs);
+
+ /* if we returned any rows, zone is supported. */
+ if (rows > 0) {
+ mysql_get_resultset(name, NULL, NULL, COUNTZONE, dbdata, NULL);
+ return (ISC_R_SUCCESS);
+ }
+
+ /* no rows returned, zone is not supported. */
+ return (ISC_R_NOTFOUND);
+}
+
+/*% Determine if the client is allowed to perform a zone transfer */
+static isc_result_t
+mysql_allowzonexfr(void *driverarg, void *dbdata, const char *name,
+ const char *client)
+{
+ isc_result_t result;
+ MYSQL_RES *rs = NULL;
+ my_ulonglong rows;
+
+ UNUSED(driverarg);
+
+ /* first check if the zone is supported by the database. */
+ result = mysql_findzone(driverarg, dbdata, name);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_NOTFOUND);
+
+ /*
+ * if we get to this point we know the zone is supported by
+ * the database the only questions now are is the zone
+ * transfer is allowed for this client and did the config file
+ * have an allow zone xfr query.
+ *
+ * Run our query, and get a result set from the database.
+ */
+ result = mysql_get_resultset(name, NULL, client, ALLOWXFR,
+ dbdata, &rs);
+ /* if we get "not implemented", send it along. */
+ if (result == ISC_R_NOTIMPLEMENTED)
+ return result;
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS || rs == NULL) {
+ if (rs != NULL)
+ mysql_free_result(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver unable to return "
+ "result set for allow xfr query");
+ return (ISC_R_FAILURE);
+ }
+ /* count how many rows in result set */
+ rows = mysql_num_rows(rs);
+ /* get rid of result set, we are done with it. */
+ mysql_free_result(rs);
+
+ /* if we returned any rows, zone xfr is allowed. */
+ if (rows > 0)
+ return (ISC_R_SUCCESS);
+
+ /* no rows returned, zone xfr not allowed */
+ return (ISC_R_NOPERM);
+}
+
+/*%
+ * If the client is allowed to perform a zone transfer, the next order of
+ * business is to get all the nodes in the zone, so bind can respond to the
+ * query.
+ */
+static isc_result_t
+mysql_allnodes(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzallnodes_t *allnodes)
+{
+ isc_result_t result;
+ MYSQL_RES *rs = NULL;
+ MYSQL_ROW row;
+ unsigned int fields;
+ unsigned int j;
+ unsigned int len;
+ char *tmpString;
+ char *endp;
+ int ttl;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = mysql_get_resultset(zone, NULL, NULL, ALLNODES, dbdata, &rs);
+ /* if we get "not implemented", send it along */
+ if (result == ISC_R_NOTIMPLEMENTED)
+ return result;
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ if (rs != NULL)
+ mysql_free_result(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver unable to return "
+ "result set for all nodes query");
+ return (ISC_R_FAILURE);
+ }
+
+ result = ISC_R_NOTFOUND;
+
+ row = mysql_fetch_row(rs); /* get a row from the result set */
+ fields = mysql_num_fields(rs); /* how many columns in result set */
+ while (row != NULL) {
+ if (fields < 4) { /* gotta have at least 4 columns */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver too few fields returned "
+ "by all nodes query");
+ }
+ /* convert text to int, make sure it worked right */
+ ttl = strtol(safeGet(row[0]), &endp, 10);
+ if (*endp != '\0' || ttl < 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver ttl must be "
+ "a postive number");
+ }
+ if (fields == 4) {
+ /* tell Bind about it. */
+ result = dns_sdlz_putnamedrr(allnodes, safeGet(row[2]),
+ safeGet(row[1]), ttl,
+ safeGet(row[3]));
+ } else {
+ /*
+ * more than 4 fields, concatenate the last
+ * ones together. figure out how long to make
+ * string.
+ */
+ for (j=3, len=0; j < fields; j++) {
+ len += strlen(safeGet(row[j])) + 1;
+ }
+ /* allocate memory, allow for NULL to term string */
+ tmpString = isc_mem_allocate(ns_g_mctx, len + 1);
+ if (tmpString == NULL) { /* we need more ram. */
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver unable "
+ "to allocate memory for "
+ "temporary string");
+ mysql_free_result(rs);
+ return (ISC_R_FAILURE);
+ }
+ /* copy this field to tmpString */
+ strcpy(tmpString, safeGet(row[3]));
+ /* concatonate the rest, with spaces between */
+ for (j=4; j < fields; j++) {
+ strcat(tmpString, " ");
+ strcat(tmpString, safeGet(row[j]));
+ }
+ /* tell Bind about it. */
+ result = dns_sdlz_putnamedrr(allnodes, safeGet(row[2]),
+ safeGet(row[1]),
+ ttl, tmpString);
+ isc_mem_free(ns_g_mctx, tmpString);
+ }
+ /* if we weren't successful, log err msg */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "dns_sdlz_putnamedrr returned error. "
+ "Error code was: %s",
+ isc_result_totext(result));
+ result = ISC_R_FAILURE;
+ break;
+ }
+ /* get next row from the result set */
+ row = mysql_fetch_row(rs);
+ }
+
+ /* free result set memory */
+ mysql_free_result(rs);
+
+ return result;
+}
+
+/*% if the lookup function does not return SOA or NS records for the zone,
+ * use this function to get that information for Bind.
+ */
+
+static isc_result_t
+mysql_authority(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzlookup_t *lookup)
+{
+ isc_result_t result;
+ MYSQL_RES *rs = NULL;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = mysql_get_resultset(zone, NULL, NULL, AUTHORITY, dbdata, &rs);
+ /* if we get "not implemented", send it along */
+ if (result == ISC_R_NOTIMPLEMENTED)
+ return result;
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ if (rs != NULL)
+ mysql_free_result(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver unable to return "
+ "result set for authority query");
+ return (ISC_R_FAILURE);
+ }
+ /*
+ * lookup and authority result sets are processed in the same
+ * manner mysql_process_rs does the job for both functions.
+ */
+ return mysql_process_rs(lookup, rs);
+}
+
+/*% if zone is supported, lookup up a (or multiple) record(s) in it */
+static isc_result_t
+mysql_lookup(const char *zone, const char *name, void *driverarg,
+ void *dbdata, dns_sdlzlookup_t *lookup)
+{
+ isc_result_t result;
+ MYSQL_RES *rs = NULL;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = mysql_get_resultset(zone, name, NULL, LOOKUP, dbdata, &rs);
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ if (rs != NULL)
+ mysql_free_result(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver unable to return "
+ "result set for lookup query");
+ return (ISC_R_FAILURE);
+ }
+ /*
+ * lookup and authority result sets are processed in the same manner
+ * mysql_process_rs does the job for both functions.
+ */
+ return mysql_process_rs(lookup, rs);
+}
+
+/*%
+ * create an instance of the driver. Remember, only 1 copy of the driver's
+ * code is ever loaded, the driver has to remember which context it's
+ * operating in. This is done via use of the dbdata argument which is
+ * passed into all query functions.
+ */
+static isc_result_t
+mysql_create(const char *dlzname, unsigned int argc, char *argv[],
+ void *driverarg, void **dbdata)
+{
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+ char *tmp = NULL;
+ char *dbname = NULL;
+ char *host = NULL;
+ char *user = NULL;
+ char *pass = NULL;
+ char *socket = NULL;
+ int port;
+ MYSQL *dbc;
+ char *endp;
+ int j;
+ unsigned int flags = 0;
+
+ UNUSED(driverarg);
+ UNUSED(dlzname);
+
+ /* verify we have at least 4 arg's passed to the driver */
+ if (argc < 4) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver requires "
+ "at least 4 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* no more than 8 arg's should be passed to the driver */
+ if (argc > 8) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver cannot accept "
+ "more than 7 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* parse connection string and get paramters. */
+
+ /* get db name - required */
+ dbname = getParameterValue(argv[1], "dbname=");
+ if (dbname == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver requires a dbname parameter.");
+ result = ISC_R_FAILURE;
+ goto full_cleanup;
+ }
+
+ /* get db port. Not required, but must be > 0 if specified */
+ tmp = getParameterValue(argv[1], "port=");
+ if (tmp == NULL) {
+ port = 0;
+ } else {
+ port = strtol(tmp, &endp, 10);
+ if (*endp != '\0' || port < 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Mysql driver port "
+ "must be a positive number.");
+ isc_mem_free(ns_g_mctx, tmp);
+ result = ISC_R_FAILURE;
+ goto full_cleanup;
+ }
+ isc_mem_free(ns_g_mctx, tmp);
+ }
+
+ /* how many queries were passed in from config file? */
+ switch(argc) {
+ case 4:
+ result = build_sqldbinstance(ns_g_mctx, NULL, NULL, NULL,
+ argv[2], argv[3], NULL, &dbi);
+ break;
+ case 5:
+ result = build_sqldbinstance(ns_g_mctx, NULL, NULL, argv[4],
+ argv[2], argv[3], NULL, &dbi);
+ break;
+ case 6:
+ result = build_sqldbinstance(ns_g_mctx, argv[5], NULL, argv[4],
+ argv[2], argv[3], NULL, &dbi);
+ break;
+ case 7:
+ result = build_sqldbinstance(ns_g_mctx, argv[5],
+ argv[6], argv[4],
+ argv[2], argv[3], NULL, &dbi);
+ break;
+ case 8:
+ result = build_sqldbinstance(ns_g_mctx, argv[5],
+ argv[6], argv[4],
+ argv[2], argv[3], argv[7], &dbi);
+ break;
+ default:
+ /* not really needed, should shut up compiler. */
+ result = ISC_R_FAILURE;
+ }
+
+ /* unsuccessful?, log err msg and cleanup. */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver could not create "
+ "database instance object.");
+ result = ISC_R_FAILURE;
+ goto full_cleanup;
+ }
+
+ /* create and set db connection */
+ dbi->dbconn = mysql_init(NULL);
+
+ /* if db connection cannot be created, log err msg and cleanup. */
+ if (dbi->dbconn == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver could not allocate "
+ "memory for database connection");
+ result = ISC_R_FAILURE;
+ goto full_cleanup;
+ }
+
+ tmp = getParameterValue(argv[1], "compress=");
+ if (tmp != NULL) {
+ if (strcasecmp(tmp, "true") == 0)
+ flags = CLIENT_COMPRESS;
+ isc_mem_free(ns_g_mctx, tmp);
+ }
+
+ tmp = getParameterValue(argv[1], "ssl=");
+ if (tmp != NULL) {
+ if (strcasecmp(tmp, "true") == 0)
+ flags = flags | CLIENT_SSL;
+ isc_mem_free(ns_g_mctx, tmp);
+ }
+
+ tmp = getParameterValue(argv[1], "space=");
+ if (tmp != NULL) {
+ if (strcasecmp(tmp, "ignore") == 0)
+ flags = flags | CLIENT_IGNORE_SPACE;
+ isc_mem_free(ns_g_mctx, tmp);
+ }
+
+ dbc = NULL;
+ host = getParameterValue(argv[1], "host=");
+ user = getParameterValue(argv[1], "user=");
+ pass = getParameterValue(argv[1], "pass=");
+ socket = getParameterValue(argv[1], "socket=");
+
+ for (j=0; dbc == NULL && j < 4; j++)
+ dbc = mysql_real_connect((MYSQL *) dbi->dbconn, host,
+ user, pass, dbname, port, socket,
+ flags);
+
+ /* let user know if we couldn't connect. */
+ if (dbc == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "mysql driver failed to create "
+ "database connection after 4 attempts");
+ result = ISC_R_FAILURE;
+ goto full_cleanup;
+ }
+
+ /* return db connection via dbdata */
+ *dbdata = dbi;
+
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+
+ full_cleanup:
+
+ destroy_sqldbinstance(dbi);
+
+ cleanup:
+
+ if (dbname != NULL)
+ isc_mem_free(ns_g_mctx, dbname);
+ if (host != NULL)
+ isc_mem_free(ns_g_mctx, host);
+ if (user != NULL)
+ isc_mem_free(ns_g_mctx, user);
+ if (pass != NULL)
+ isc_mem_free(ns_g_mctx, pass);
+ if (socket != NULL)
+ isc_mem_free(ns_g_mctx, socket);
+
+
+ return result;
+}
+
+/*%
+ * destroy the driver. Remember, only 1 copy of the driver's
+ * code is ever loaded, the driver has to remember which context it's
+ * operating in. This is done via use of the dbdata argument.
+ * so we really only need to clean it up since we are not using driverarg.
+ */
+
+static void
+mysql_destroy(void *driverarg, void *dbdata)
+{
+ dbinstance_t *dbi;
+
+ UNUSED(driverarg);
+
+ dbi = (dbinstance_t *) dbdata;
+
+ /* release DB connection */
+ if (dbi->dbconn != NULL)
+ mysql_close((MYSQL *) dbi->dbconn);
+
+ /* destroy DB instance */
+ destroy_sqldbinstance(dbi);
+}
+
+/* pointers to all our runtime methods. */
+/* this is used during driver registration */
+/* i.e. in dlz_mysql_init below. */
+static dns_sdlzmethods_t dlz_mysql_methods = {
+ mysql_create,
+ mysql_destroy,
+ mysql_findzone,
+ mysql_lookup,
+ mysql_authority,
+ mysql_allnodes,
+ mysql_allowzonexfr
+};
+
+/*%
+ * Wrapper around dns_sdlzregister().
+ */
+isc_result_t
+dlz_mysql_init(void) {
+ isc_result_t result;
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Registering DLZ mysql driver.");
+
+ /* Driver is always threadsafe. Because of the way MySQL handles
+ * threads the MySQL driver can only be used when bind is run single
+ * threaded. Using MySQL with Bind running multi-threaded is not
+ * allowed. When using the MySQL driver "-n1" should always be
+ * passed to Bind to guarantee single threaded operation.
+ */
+ result = dns_sdlzregister("mysql", &dlz_mysql_methods, NULL,
+ DNS_SDLZFLAG_RELATIVEOWNER |
+ DNS_SDLZFLAG_RELATIVERDATA |
+ DNS_SDLZFLAG_THREADSAFE,
+ ns_g_mctx, &dlz_mysql);
+ /* if we can't register the driver, there are big problems. */
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+
+ return result;
+}
+
+/*%
+ * Wrapper around dns_sdlzunregister().
+ */
+void
+dlz_mysql_clear(void) {
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Unregistering DLZ mysql driver.");
+
+ /* unregister the driver. */
+ if (dlz_mysql != NULL)
+ dns_sdlzunregister(&dlz_mysql);
+}
+
+#endif
diff --git a/contrib/dlz/drivers/dlz_odbc_driver.c b/contrib/dlz/drivers/dlz_odbc_driver.c
new file mode 100644
index 0000000..eb088a2
--- /dev/null
+++ b/contrib/dlz/drivers/dlz_odbc_driver.c
@@ -0,0 +1,1568 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef DLZ_ODBC
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <dns/log.h>
+#include <dns/sdlz.h>
+#include <dns/result.h>
+
+#include <isc/mem.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+
+#include <dlz/sdlz_helper.h>
+#include <dlz/dlz_odbc_driver.h>
+
+#include <sql.h>
+#include <sqlext.h>
+#include <sqltypes.h>
+
+static dns_sdlzimplementation_t *dlz_odbc = NULL;
+
+#define dbc_search_limit 30
+#define ALLNODES 1
+#define ALLOWXFR 2
+#define AUTHORITY 3
+#define FINDZONE 4
+#define LOOKUP 5
+
+#define sqlOK(a) ((a == SQL_SUCCESS || a == SQL_SUCCESS_WITH_INFO) ? -1 : 0)
+
+/*
+ * Private Structures
+ */
+
+/*
+ * structure to hold ODBC connection & statement
+ */
+
+typedef struct{
+ SQLHDBC dbc;
+ SQLHSTMT stmnt;
+} odbc_db_t;
+
+/*
+ * Structure to hold everthing needed by this "instance" of the odbc driver
+ * remember, the driver code is only loaded once, but may have many separate
+ * instances
+ */
+
+typedef struct {
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ db_list_t *db; /* handle to a list of DB */
+
+#else
+
+ dbinstance_t *db; /* handle to db */
+
+#endif
+
+ SQLHENV sql_env; /* handle to SQL environment */
+ SQLCHAR *dsn;
+ SQLCHAR *user;
+ SQLCHAR *pass;
+} odbc_instance_t;
+
+/* forward reference */
+
+static size_t
+odbc_makesafe(char *to, const char *from, size_t length);
+
+/*
+ * Private methods
+ */
+
+static SQLSMALLINT
+safeLen(void *a) {
+ if (a == NULL)
+ return 0;
+ return strlen((char *) a);
+}
+
+/*% propertly cleans up an odbc_instance_t */
+
+static void
+destroy_odbc_instance(odbc_instance_t *odbc_inst) {
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ dbinstance_t *ndbi = NULL;
+ dbinstance_t *dbi = NULL;
+
+ /* get the first DBI in the list */
+ ndbi = ISC_LIST_HEAD(*odbc_inst->db);
+
+ /* loop through the list */
+ while (ndbi != NULL) {
+ dbi = ndbi;
+ /* get the next DBI in the list */
+ ndbi = ISC_LIST_NEXT(dbi, link);
+
+ /* if we have a connection / statement object in memory */
+ if (dbi->dbconn != NULL) {
+ /* free statement handle */
+ if (((odbc_db_t *) (dbi->dbconn))->stmnt != NULL) {
+ SQLFreeHandle(SQL_HANDLE_STMT,
+ ((odbc_db_t *)
+ (dbi->dbconn))->stmnt);
+ ((odbc_db_t *) (dbi->dbconn))->stmnt = NULL;
+ }
+
+ /* disconnect from database & free connection handle */
+ if (((odbc_db_t *) (dbi->dbconn))->dbc != NULL) {
+ SQLDisconnect(((odbc_db_t *)
+ dbi->dbconn)->dbc);
+ SQLFreeHandle(SQL_HANDLE_DBC,
+ ((odbc_db_t *)
+ (dbi->dbconn))->dbc);
+ ((odbc_db_t *) (dbi->dbconn))->dbc = NULL;
+ }
+
+ /* free memory that held connection & statement. */
+ isc_mem_free(ns_g_mctx, dbi->dbconn);
+ }
+ /* release all memory that comprised a DBI */
+ destroy_sqldbinstance(dbi);
+ }
+ /* release memory for the list structure */
+ isc_mem_put(ns_g_mctx, odbc_inst->db, sizeof(db_list_t));
+
+#else /* ISC_PLATFORM_USETHREADS */
+
+ /* free statement handle */
+ if (((odbc_db_t *) (odbc_inst->db->dbconn))->stmnt != NULL) {
+ SQLFreeHandle(SQL_HANDLE_STMT,
+ ((odbc_db_t *) (odbc_inst->db->dbconn))->stmnt);
+ ((odbc_db_t *) (odbc_inst->db->dbconn))->stmnt = NULL;
+ }
+
+ /* disconnect from database, free connection handle */
+ if (((odbc_db_t *) (odbc_inst->db->dbconn))->dbc != NULL) {
+ SQLDisconnect(((odbc_db_t *) (odbc_inst->db->dbconn))->dbc);
+ SQLFreeHandle(SQL_HANDLE_DBC,
+ ((odbc_db_t *) (odbc_inst->db->dbconn))->dbc);
+ ((odbc_db_t *) (odbc_inst->db->dbconn))->dbc = NULL;
+ }
+ /* free mem for the odbc_db_t structure held in db */
+ if (((odbc_db_t *) odbc_inst->db->dbconn) != NULL) {
+ isc_mem_free(ns_g_mctx, odbc_inst->db->dbconn);
+ odbc_inst->db->dbconn = NULL;
+ }
+
+ if (odbc_inst->db != NULL)
+ destroy_sqldbinstance(odbc_inst->db);
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+
+ /* free sql environment */
+ if (odbc_inst->sql_env != NULL)
+ SQLFreeHandle(SQL_HANDLE_ENV, odbc_inst->sql_env);
+
+ /* free ODBC instance strings */
+ if (odbc_inst->dsn != NULL)
+ isc_mem_free(ns_g_mctx, odbc_inst->dsn);
+ if (odbc_inst->pass != NULL)
+ isc_mem_free(ns_g_mctx, odbc_inst->pass);
+ if (odbc_inst->user != NULL)
+ isc_mem_free(ns_g_mctx, odbc_inst->user);
+
+ /* free memory for odbc_inst */
+ if (odbc_inst != NULL)
+ isc_mem_put(ns_g_mctx, odbc_inst, sizeof(odbc_instance_t));
+
+}
+
+/*% Connects to database, and creates ODBC statements */
+
+static isc_result_t
+odbc_connect(odbc_instance_t *dbi, odbc_db_t **dbc) {
+
+ odbc_db_t *ndb = *dbc;
+ SQLRETURN sqlRes;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ if (ndb != NULL) {
+ /*
+ * if db != null, we have to do some cleanup
+ * if statement handle != null free it
+ */
+ if (ndb->stmnt != NULL) {
+ SQLFreeHandle(SQL_HANDLE_STMT, ndb->stmnt);
+ ndb->stmnt = NULL;
+ }
+
+ /* if connection handle != null free it */
+ if (ndb->dbc != NULL) {
+ SQLFreeHandle(SQL_HANDLE_DBC, ndb->dbc);
+ ndb->dbc = NULL;
+ }
+ } else {
+ ndb = isc_mem_allocate(ns_g_mctx, sizeof(odbc_db_t));
+ if (ndb == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver unable to allocate memory");
+ return ISC_R_NOMEMORY;
+ }
+ memset(ndb, 0, sizeof(odbc_db_t));
+ }
+
+ sqlRes = SQLAllocHandle(SQL_HANDLE_DBC, dbi->sql_env, &(ndb->dbc));
+ if (!sqlOK(sqlRes)) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver unable to allocate memory");
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ sqlRes = SQLConnect(ndb->dbc, dbi->dsn, safeLen(dbi->dsn), dbi->user,
+ safeLen(dbi->user), dbi->pass, safeLen(dbi->pass));
+ if (!sqlOK(sqlRes)) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver unable to connect");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ sqlRes = SQLAllocHandle(SQL_HANDLE_STMT, ndb->dbc, &(ndb->stmnt));
+ if (!sqlOK(sqlRes)) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver unable to allocate memory");
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ *dbc = ndb;
+
+ return ISC_R_SUCCESS;
+
+ cleanup:
+
+ if (ndb != NULL) {
+
+ /* if statement handle != null free it */
+ if (ndb->stmnt != NULL) {
+ SQLFreeHandle(SQL_HANDLE_STMT, ndb->stmnt);
+ ndb->stmnt = NULL;
+ }
+
+ /* if connection handle != null free it */
+ if (ndb->dbc != NULL) {
+ SQLDisconnect(ndb->dbc);
+ SQLFreeHandle(SQL_HANDLE_DBC, ndb->dbc);
+ ndb->dbc = NULL;
+ }
+ /* free memory holding ndb */
+ isc_mem_free(ns_g_mctx, ndb);
+ }
+
+ return result;
+}
+
+/*%
+ * Loops through the list of DB instances, attempting to lock
+ * on the mutex. If successful, the DBI is reserved for use
+ * and the thread can perform queries against the database.
+ * If the lock fails, the next one in the list is tried.
+ * looping continues until a lock is obtained, or until
+ * the list has been searched dbc_search_limit times.
+ * This function is only used when the driver is compiled for
+ * multithreaded operation.
+ */
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+static dbinstance_t *
+odbc_find_avail_conn(db_list_t *dblist)
+{
+ dbinstance_t *dbi = NULL;
+ dbinstance_t *head;
+ int count = 0;
+
+ /* get top of list */
+ head = dbi = ISC_LIST_HEAD(*dblist);
+
+ /* loop through list */
+ while (count < dbc_search_limit) {
+ /* try to lock on the mutex */
+ if (isc_mutex_trylock(&dbi->instance_lock) == ISC_R_SUCCESS)
+ return dbi; /* success, return the DBI for use. */
+
+ /* not successful, keep trying */
+ dbi = ISC_LIST_NEXT(dbi, link);
+
+ /* check to see if we have gone to the top of the list. */
+ if (dbi == NULL) {
+ count++;
+ dbi = head;
+ }
+ }
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "Odbc driver unable to find available "
+ "connection after searching %d times",
+ count);
+ return NULL;
+}
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+/*% Allocates memory for a new string, and then constructs the new
+ * string by "escaping" the input string. The new string is
+ * safe to be used in queries. This is necessary because we cannot
+ * be sure of what types of strings are passed to us, and we don't
+ * want special characters in the string causing problems.
+ */
+
+static char *
+odbc_escape_string(const char *instr) {
+
+ char *outstr;
+ unsigned int len;
+
+ if (instr == NULL)
+ return NULL;
+
+ len = strlen(instr);
+
+ outstr = isc_mem_allocate(ns_g_mctx ,(2 * len * sizeof(char)) + 1);
+ if (outstr == NULL)
+ return NULL;
+
+ odbc_makesafe(outstr, instr, len);
+
+ return outstr;
+}
+
+/* ---------------
+ * Escaping arbitrary strings to get valid SQL strings/identifiers.
+ *
+ * Replaces "\\" with "\\\\" and "'" with "''".
+ * length is the length of the buffer pointed to by
+ * from. The buffer at to must be at least 2*length + 1 characters
+ * long. A terminating NUL character is written.
+ *
+ * NOTICE!!!
+ * This function was borrowed directly from PostgreSQL's libpq.
+ *
+ * The copyright statements from the original file containing this
+ * function are included below:
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ * ---------------
+ */
+
+static size_t
+odbc_makesafe(char *to, const char *from, size_t length)
+{
+ const char *source = from;
+ char *target = to;
+ unsigned int remaining = length;
+
+ while (remaining > 0)
+ {
+ switch (*source)
+ {
+ case '\\':
+ *target = '\\';
+ target++;
+ *target = '\\';
+ /* target and remaining are updated below. */
+ break;
+
+ case '\'':
+ *target = '\'';
+ target++;
+ *target = '\'';
+ /* target and remaining are updated below. */
+ break;
+
+ default:
+ *target = *source;
+ /* target and remaining are updated below. */
+ }
+ source++;
+ target++;
+ remaining--;
+ }
+
+ /* Write the terminating NUL character. */
+ *target = '\0';
+
+ return target - to;
+}
+
+/*%
+ * This function is the real core of the driver. Zone, record
+ * and client strings are passed in (or NULL is passed if the
+ * string is not available). The type of query we want to run
+ * is indicated by the query flag, and the dbdata object is passed
+ * passed in to. dbdata really holds either:
+ * 1) a list of database instances (in multithreaded mode) OR
+ * 2) a single database instance (in single threaded mode)
+ * The function will construct the query and obtain an available
+ * database instance (DBI). It will then run the query and hopefully
+ * obtain a result set. The data base instance that is used is returned
+ * to the caller so they can get the data from the result set from it.
+ * If successfull, it will be the responsibility of the caller to close
+ * the cursor, and unlock the mutex of the DBI when they are done with it.
+ * If not successfull, this function will perform all the cleanup.
+ */
+
+
+static isc_result_t
+odbc_get_resultset(const char *zone, const char *record,
+ const char *client, unsigned int query,
+ void *dbdata, dbinstance_t **r_dbi)
+{
+
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+ char *querystring = NULL;
+ unsigned int j = 0;
+ SQLRETURN sqlRes;
+
+ REQUIRE(*r_dbi == NULL);
+
+ /* get db instance / connection */
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* find an available DBI from the list */
+ dbi = odbc_find_avail_conn(((odbc_instance_t *) dbdata)->db);
+
+#else /* ISC_PLATFORM_USETHREADS */
+
+ /*
+ * only 1 DBI - no need to lock instance lock either
+ * only 1 thread in the whole process, no possible contention.
+ */
+ dbi = (dbinstance_t *) ((odbc_instance_t *) dbdata)->db;
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* if DBI is null, can't do anything else */
+ if (dbi == NULL) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /* what type of query are we going to run? */
+ switch(query) {
+ case ALLNODES:
+ /*
+ * if the query was not passed in from the config file
+ * then we can't run it. return not_implemented, so
+ * it's like the code for that operation was never
+ * built into the driver.... AHHH flexibility!!!
+ */
+ if (dbi->allnodes_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ break;
+ case ALLOWXFR:
+ /* same as comments as ALLNODES */
+ if (dbi->allowxfr_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ break;
+ case AUTHORITY:
+ /* same as comments as ALLNODES */
+ if (dbi->authority_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ break;
+ case FINDZONE:
+ /* this is required. It's the whole point of DLZ! */
+ if (dbi->findzone_q == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "No query specified for findzone. "
+ "Findzone requires a query");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ break;
+ case LOOKUP:
+ /* this is required. It's also a major point of DLZ! */
+ if (dbi->lookup_q == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "No query specified for lookup. "
+ "Lookup requires a query");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ break;
+ default:
+ /*
+ * this should never happen. If it does, the code is
+ * screwed up!
+ */
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "Incorrect query flag passed to "
+ "odbc_get_resultset");
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+
+ /*
+ * was a zone string passed? If so, make it safe for use in
+ * queries.
+ */
+ if (zone != NULL) {
+ dbi->zone = odbc_escape_string(zone);
+ if (dbi->zone == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else { /* no string passed, set the string pointer to NULL */
+ dbi->zone = NULL;
+ }
+
+ /*
+ * was a record string passed? If so, make it safe for use in
+ * queries.
+ */
+ if (record != NULL) {
+ dbi->record = odbc_escape_string(record);
+ if (dbi->record == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else { /* no string passed, set the string pointer to NULL */
+ dbi->record = NULL;
+ }
+
+ /*
+ * was a client string passed? If so, make it safe for use in
+ * queries.
+ */
+ if (client != NULL) {
+ dbi->client = odbc_escape_string(client);
+ if (dbi->client == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else { /* no string passed, set the string pointer to NULL */
+ dbi->client = NULL;
+ }
+
+ /*
+ * what type of query are we going to run?
+ * this time we build the actual query to run.
+ */
+ switch(query) {
+ case ALLNODES:
+ querystring = build_querystring(ns_g_mctx, dbi->allnodes_q);
+ break;
+ case ALLOWXFR:
+ querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q);
+ break;
+ case AUTHORITY:
+ querystring = build_querystring(ns_g_mctx, dbi->authority_q);
+ break;
+ case FINDZONE:
+ querystring = build_querystring(ns_g_mctx, dbi->findzone_q);
+ break;
+ case LOOKUP:
+ querystring = build_querystring(ns_g_mctx, dbi->lookup_q);
+ break;
+ default:
+ /*
+ * this should never happen. If it does, the code is
+ * screwed up!
+ */
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "Incorrect query flag passed to "
+ "odbc_get_resultset");
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+ /* if the querystring is null, Bummer, outta RAM. UPGRADE TIME!!! */
+ if (querystring == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ /* output the full query string during debug so we can see */
+ /* what lame error the query has. */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "\nQuery String: %s\n", querystring);
+
+ /* attempt query up to 3 times. */
+ for (j=0; j < 3; j++) {
+ /* try to get result set */
+ sqlRes = SQLExecDirect(((odbc_db_t *) dbi->dbconn)->stmnt,
+ (SQLCHAR *) querystring,
+ (SQLINTEGER) strlen(querystring));
+
+ /* if error, reset DB connection */
+ if (!sqlOK(sqlRes)) {
+ /* close cursor */
+ SQLCloseCursor(((odbc_db_t *) dbi->dbconn)->stmnt);
+ /* attempt to reconnect */
+ result = odbc_connect((odbc_instance_t *) dbdata,
+ (odbc_db_t **) &(dbi->dbconn));
+ /* check if we reconnected */
+ if (result != ISC_R_SUCCESS)
+ break;
+ /* incase this is the last time through the loop */
+ result = ISC_R_FAILURE;
+ } else {
+ result = ISC_R_SUCCESS;
+ /* return dbi */
+ *r_dbi = dbi;
+ /* result set ok, break loop */
+ break;
+ }
+ } /* end for loop */
+
+ cleanup: /* it's always good to cleanup after yourself */
+
+ /* if we couldn't even allocate DBI, just return NULL */
+ if (dbi == NULL)
+ return ISC_R_FAILURE;
+
+ /* free dbi->zone string */
+ if (dbi->zone != NULL)
+ isc_mem_free(ns_g_mctx, dbi->zone);
+
+ /* free dbi->record string */
+ if (dbi->record != NULL)
+ isc_mem_free(ns_g_mctx, dbi->record);
+
+ /* free dbi->client string */
+ if (dbi->client != NULL)
+ isc_mem_free(ns_g_mctx, dbi->client);
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* if we are done using this dbi, release the lock */
+ if (result != ISC_R_SUCCESS)
+ isc_mutex_unlock(&dbi->instance_lock);
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* release query string */
+ if (querystring != NULL)
+ isc_mem_free(ns_g_mctx, querystring );
+
+ /* return result */
+ return result;
+
+}
+
+/*%
+ * Gets a single field from the ODBC statement. The memory for the
+ * returned data is dynamically allocated. If this method is successful
+ * it is the reponsibility of the caller to free the memory using
+ * isc_mem_free(ns_g_mctx, *ptr);
+ */
+
+static isc_result_t
+odbc_getField(SQLHSTMT *stmnt, SQLSMALLINT field, char **data) {
+
+ SQLINTEGER size;
+
+ REQUIRE(data != NULL && *data == NULL);
+
+ if (sqlOK(SQLColAttribute(stmnt, field, SQL_DESC_DISPLAY_SIZE,
+ NULL, 0, NULL, &size)) && size > 0) {
+ *data = isc_mem_allocate(ns_g_mctx, size + 1);
+ if (data != NULL) {
+ if (sqlOK(SQLGetData(stmnt, field, SQL_C_CHAR,
+ *data, size + 1,&size)))
+ return ISC_R_SUCCESS;
+ isc_mem_free(ns_g_mctx, *data);
+ }
+ }
+ return ISC_R_FAILURE;
+}
+
+/*%
+ * Gets multiple fields from the ODBC statement. The memory for the
+ * returned data is dynamically allocated. If this method is successful
+ * it is the reponsibility of the caller to free the memory using
+ * isc_mem_free(ns_g_mctx, *ptr);
+ */
+
+static isc_result_t
+odbc_getManyFields(SQLHSTMT *stmnt, SQLSMALLINT startField,
+ SQLSMALLINT endField, char **retData) {
+
+ isc_result_t result;
+ SQLINTEGER size;
+ int totSize = 0;
+ SQLSMALLINT i;
+ int j = 0;
+ char *data;
+
+ REQUIRE(retData != NULL && *retData == NULL);
+ REQUIRE(startField > 0 && startField <= endField);
+
+ /* determine how large the data is */
+ for (i=startField; i <= endField; i++)
+ if (sqlOK(SQLColAttribute(stmnt, i, SQL_DESC_DISPLAY_SIZE,
+ NULL, 0, NULL, &size)) && size > 0) {
+ /* always allow for a " " (space) character */
+ totSize += (size + 1);
+ /* after the data item */
+ }
+
+ if (totSize < 1)
+ return ISC_R_FAILURE;
+
+ /* allow for a "\n" at the end of the string/ */
+ data = isc_mem_allocate(ns_g_mctx, ++totSize);
+ if (data == NULL)
+ return ISC_R_NOMEMORY;
+
+ result = ISC_R_FAILURE;
+
+ /* get the data and concat all fields into a large string */
+ for (i=startField; i <= endField; i++) {
+ if (sqlOK(SQLGetData(stmnt, i, SQL_C_CHAR, &(data[j]),
+ totSize - j, &size))) {
+ if (size > 0) {
+ j += size;
+ data[j++] = ' ';
+ data[j] = '\0';
+ result = ISC_R_SUCCESS;
+ }
+ } else {
+ isc_mem_free(ns_g_mctx, data);
+ return ISC_R_FAILURE;
+ }
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_free(ns_g_mctx, data);
+ return result;
+ }
+
+ *retData = data;
+ return ISC_R_SUCCESS;
+
+}
+
+/*%
+ * The processing of result sets for lookup and authority are
+ * exactly the same. So that functionality has been moved
+ * into this function to minimize code.
+ */
+
+static isc_result_t
+odbc_process_rs(dns_sdlzlookup_t *lookup, dbinstance_t *dbi)
+{
+
+
+ isc_result_t result;
+ SQLSMALLINT fields;
+ SQLHSTMT *stmnt;
+ char *ttl_s;
+ char *type;
+ char *data;
+ char *endp;
+ int ttl;
+
+ REQUIRE(dbi != NULL);
+
+ stmnt = ((odbc_db_t *) (dbi->dbconn))->stmnt;
+
+ /* get number of columns */
+ if (!sqlOK(SQLNumResultCols(stmnt, &fields))) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver unable to process result set");
+ result = ISC_R_FAILURE;
+ goto process_rs_cleanup;
+ }
+
+ /* get things ready for processing */
+ result = ISC_R_FAILURE;
+
+ while (sqlOK(SQLFetch(stmnt))) {
+
+ /* set to null for next pass through */
+ data = type = ttl_s = NULL;
+
+ switch(fields) {
+ case 1:
+ /*
+ * one column in rs, it's the data field. use
+ * default type of A record, and default TTL
+ * of 86400. attempt to get data, & tell bind
+ * about it.
+ */
+ if ((result = odbc_getField(stmnt, 1,
+ &data)) == ISC_R_SUCCESS) {
+ result = dns_sdlz_putrr(lookup, "a",
+ 86400, data);
+ }
+ break;
+ case 2:
+ /*
+ * two columns, data field, and data type.
+ * use default TTL of 86400. attempt to get
+ * DNS type & data, then tell bind about it.
+ */
+ if ((result = odbc_getField(stmnt, 1,
+ &type)) == ISC_R_SUCCESS &&
+ (result = odbc_getField(stmnt, 2,
+ &data)) == ISC_R_SUCCESS) {
+ result = dns_sdlz_putrr(lookup, type,
+ 86400, data);
+ }
+ break;
+ default:
+ /*
+ * 3 fields or more, concatenate the last ones
+ * together. attempt to get DNS ttl, type,
+ * data then tell Bind about them.
+ */
+ if ((result = odbc_getField(stmnt, 1, &ttl_s))
+ == ISC_R_SUCCESS &&
+ (result = odbc_getField(stmnt, 2, &type))
+ == ISC_R_SUCCESS &&
+ (result = odbc_getManyFields(stmnt, 3,
+ fields, &data))
+ == ISC_R_SUCCESS) {
+ /* try to convert ttl string to int */
+ ttl = strtol(ttl_s, &endp, 10);
+ /* failure converting ttl. */
+ if (*endp != '\0' || ttl < 0) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ,
+ ISC_LOG_ERROR,
+ "Odbc driver ttl must "
+ "be a postive number");
+ result = ISC_R_FAILURE;
+ } else {
+ /*
+ * successful converting TTL,
+ * tell Bind everything
+ */
+ result = dns_sdlz_putrr(lookup, type,
+ ttl, data);
+ }
+ } /* closes bid if () */
+ } /* closes switch(fields) */
+
+ /* clean up mem */
+ if (ttl_s != NULL)
+ isc_mem_free(ns_g_mctx, ttl_s);
+ if (type != NULL)
+ isc_mem_free(ns_g_mctx, type);
+ if (data != NULL)
+ isc_mem_free(ns_g_mctx, data);
+
+ /* I sure hope we were successful */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "dns_sdlz_putrr returned error. "
+ "Error code was: %s",
+ isc_result_totext(result));
+ result = ISC_R_FAILURE;
+ goto process_rs_cleanup;
+ }
+ } /* closes while loop */
+
+ process_rs_cleanup:
+
+ /* close cursor */
+ SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt);
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* free lock on dbi so someone else can use it. */
+ isc_mutex_unlock(&dbi->instance_lock);
+
+#endif
+
+ return result;
+}
+
+/*
+ * SDLZ interface methods
+ */
+
+/*% determine if the zone is supported by (in) the database */
+
+static isc_result_t
+odbc_findzone(void *driverarg, void *dbdata, const char *name)
+{
+
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ /* if result != ISC_R_SUCCESS cursor and mutex already cleaned up. */
+ /* so we don't have to do it here. */
+ result = odbc_get_resultset(name, NULL, NULL, FINDZONE, dbdata, &dbi);
+
+ /* Check that we got a result set with data */
+ if (result == ISC_R_SUCCESS &&
+ !sqlOK(SQLFetch(((odbc_db_t *) (dbi->dbconn))->stmnt))) {
+ result = ISC_R_NOTFOUND;
+ }
+
+ if (dbi != NULL) {
+ /* get rid of result set, we are done with it. */
+ SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt);
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* free lock on dbi so someone else can use it. */
+ isc_mutex_unlock(&dbi->instance_lock);
+#endif
+ }
+
+ return result;
+}
+
+/*% Determine if the client is allowed to perform a zone transfer */
+static isc_result_t
+odbc_allowzonexfr(void *driverarg, void *dbdata, const char *name,
+ const char *client)
+{
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+
+ UNUSED(driverarg);
+
+ /* first check if the zone is supported by the database. */
+ result = odbc_findzone(driverarg, dbdata, name);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_NOTFOUND);
+
+ /*
+ * if we get to this point we know the zone is supported by
+ * the database. the only questions now are is the zone
+ * transfer is allowed for this client and did the config file
+ * have an allow zone xfr query
+ *
+ * Run our query, and get a result set from the database. if
+ * result != ISC_R_SUCCESS cursor and mutex already cleaned
+ * up, so we don't have to do it here.
+ */
+ result = odbc_get_resultset(name, NULL, client, ALLOWXFR,
+ dbdata, &dbi);
+
+ /* if we get "not implemented", send it along. */
+ if (result == ISC_R_NOTIMPLEMENTED)
+ return result;
+
+ /* Check that we got a result set with data */
+ if (result == ISC_R_SUCCESS &&
+ !sqlOK(SQLFetch(((odbc_db_t *) (dbi->dbconn))->stmnt))) {
+ result = ISC_R_NOPERM;
+ }
+
+ if (dbi != NULL) {
+ /* get rid of result set, we are done with it. */
+ SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt);
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* free lock on dbi so someone else can use it. */
+ isc_mutex_unlock(&dbi->instance_lock);
+#endif
+
+ }
+
+ return result;
+}
+
+/*%
+ * If the client is allowed to perform a zone transfer, the next order of
+ * business is to get all the nodes in the zone, so bind can respond to the
+ * query.
+ */
+
+static isc_result_t
+odbc_allnodes(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzallnodes_t *allnodes)
+{
+
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+ SQLHSTMT *stmnt;
+ SQLSMALLINT fields;
+ char *data;
+ char *type;
+ char *ttl_s;
+ int ttl;
+ char *host;
+ char *endp;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = odbc_get_resultset(zone, NULL, NULL, ALLNODES, dbdata, &dbi);
+
+ /* if we get "not implemented", send it along */
+ if (result == ISC_R_NOTIMPLEMENTED)
+ return result;
+
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver unable to return "
+ "result set for all nodes query");
+ return (ISC_R_FAILURE);
+ }
+
+ stmnt = ((odbc_db_t *) (dbi->dbconn))->stmnt;
+
+ /* get number of columns */
+ if (!sqlOK(SQLNumResultCols(stmnt, &fields))) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver unable to process result set");
+ result = ISC_R_FAILURE;
+ goto allnodes_cleanup;
+ }
+
+ if (fields < 4) { /* gotta have at least 4 columns */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver too few fields returned by "
+ "all nodes query");
+ result = ISC_R_FAILURE;
+ goto allnodes_cleanup;
+ }
+
+ /* get things ready for processing */
+ result = ISC_R_FAILURE;
+
+ while (sqlOK(SQLFetch(stmnt))) {
+
+ /* set to null for next pass through */
+ data = host = type = ttl_s = NULL;
+
+ /*
+ * attempt to get DNS ttl, type, host, data then tell
+ * Bind about them
+ */
+ if ((result = odbc_getField(stmnt, 1,
+ &ttl_s)) == ISC_R_SUCCESS &&
+ (result = odbc_getField(stmnt, 2,
+ &type)) == ISC_R_SUCCESS &&
+ (result = odbc_getField(stmnt, 3,
+ &host)) == ISC_R_SUCCESS &&
+ (result = odbc_getManyFields(stmnt, 4, fields,
+ &data)) == ISC_R_SUCCESS) {
+ /* convert ttl string to int */
+ ttl = strtol(ttl_s, &endp, 10);
+ /* failure converting ttl. */
+ if (*endp != '\0' || ttl < 0) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver ttl must be "
+ "a postive number");
+ result = ISC_R_FAILURE;
+ } else {
+ /* successful converting TTL, tell Bind */
+ result = dns_sdlz_putnamedrr(allnodes, host,
+ type, ttl, data);
+ }
+ } /* closes big if () */
+
+ /* clean up mem */
+ if (ttl_s != NULL)
+ isc_mem_free(ns_g_mctx, ttl_s);
+ if (type != NULL)
+ isc_mem_free(ns_g_mctx, type);
+ if (host != NULL)
+ isc_mem_free(ns_g_mctx, host);
+ if (data != NULL)
+ isc_mem_free(ns_g_mctx, data);
+
+ /* if we weren't successful, log err msg */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "dns_sdlz_putnamedrr returned error. "
+ "Error code was: %s",
+ isc_result_totext(result));
+ result = ISC_R_FAILURE;
+ goto allnodes_cleanup;
+ }
+ } /* closes while loop */
+
+ allnodes_cleanup:
+
+ /* close cursor */
+ SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt);
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* free lock on dbi so someone else can use it. */
+ isc_mutex_unlock(&dbi->instance_lock);
+
+#endif
+
+ return result;
+}
+
+/*%
+ * if the lookup function does not return SOA or NS records for the zone,
+ * use this function to get that information for Bind.
+ */
+
+static isc_result_t
+odbc_authority(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzlookup_t *lookup)
+{
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = odbc_get_resultset(zone, NULL, NULL, AUTHORITY, dbdata, &dbi);
+ /* if we get "not implemented", send it along */
+ if (result == ISC_R_NOTIMPLEMENTED)
+ return result;
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver unable to return "
+ "result set for authority query");
+ return (ISC_R_FAILURE);
+ }
+ /* lookup and authority result sets are processed in the same manner */
+ /* odbc_process_rs does the job for both functions. */
+ return odbc_process_rs(lookup, dbi);
+}
+
+/*% if zone is supported, lookup up a (or multiple) record(s) in it */
+
+static isc_result_t
+odbc_lookup(const char *zone, const char *name, void *driverarg,
+ void *dbdata, dns_sdlzlookup_t *lookup)
+{
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = odbc_get_resultset(zone, name, NULL, LOOKUP, dbdata, &dbi);
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver unable to return "
+ "result set for lookup query");
+ return (ISC_R_FAILURE);
+ }
+ /* lookup and authority result sets are processed in the same manner */
+ /* odbc_process_rs does the job for both functions. */
+ return odbc_process_rs(lookup, dbi);
+}
+
+/*%
+ * create an instance of the driver. Remember, only 1 copy of the driver's
+ * code is ever loaded, the driver has to remember which context it's
+ * operating in. This is done via use of the dbdata argument which is
+ * passed into all query functions.
+ */
+static isc_result_t
+odbc_create(const char *dlzname, unsigned int argc, char *argv[],
+ void *driverarg, void **dbdata)
+{
+ isc_result_t result;
+ odbc_instance_t *odbc_inst = NULL;
+ dbinstance_t *db = NULL;
+ SQLRETURN sqlRes;
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /* if multi-threaded, we need a few extra variables. */
+ int dbcount;
+ int i;
+ char *endp;
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ UNUSED(dlzname);
+ UNUSED(driverarg);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /* if debugging, let user know we are multithreaded. */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "Odbc driver running multithreaded");
+#else /* ISC_PLATFORM_USETHREADS */
+ /* if debugging, let user know we are single threaded. */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "Odbc driver running single threaded");
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* verify we have at least 5 arg's passed to the driver */
+ if (argc < 5) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver requires at least "
+ "4 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* no more than 8 arg's should be passed to the driver */
+ if (argc > 8) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver cannot accept more than "
+ "7 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* multithreaded build can have multiple DB connections */
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* check how many db connections we should create */
+ dbcount = strtol(argv[1], &endp, 10);
+ if (*endp != '\0' || dbcount < 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver database connection count "
+ "must be positive.");
+ return (ISC_R_FAILURE);
+ }
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* allocate memory for odbc instance */
+ odbc_inst = isc_mem_get(ns_g_mctx, sizeof(odbc_instance_t));
+ if (odbc_inst == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(odbc_inst, 0, sizeof(odbc_instance_t));
+
+ /* parse connection string and get paramters. */
+
+ /* get odbc database dsn - required */
+ odbc_inst->dsn = (SQLCHAR *) getParameterValue(argv[2],
+ "dsn=");
+ if (odbc_inst->dsn == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "odbc driver requires a dns parameter.");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ /* get odbc database username */
+ /* if no username was passed, set odbc_inst.user = NULL; */
+ odbc_inst->user = (SQLCHAR *) getParameterValue(argv[2],
+ "user=");
+
+ /* get odbc database password */
+ /* if no password was passed, set odbc_inst.pass = NULL; */
+ odbc_inst->pass = (SQLCHAR *) getParameterValue(argv[2], "pass=");
+
+ /* create odbc environment & set environment to ODBC V3 */
+ if (odbc_inst->sql_env == NULL) {
+ /* create environment handle */
+ sqlRes = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE,
+ &(odbc_inst->sql_env));
+ if (!sqlOK(sqlRes)) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "Odbc driver unable to allocate memory");
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ /*set ODBC version = 3 */
+ sqlRes = SQLSetEnvAttr(odbc_inst->sql_env,
+ SQL_ATTR_ODBC_VERSION,
+ (void *) SQL_OV_ODBC3, 0);
+ if (!sqlOK(sqlRes)) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "Unable to configure ODBC environment");
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* allocate memory for database connection list */
+ odbc_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
+ if (odbc_inst->db == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+
+ /* initialize DB connection list */
+ ISC_LIST_INIT(*odbc_inst->db);
+
+ /* create the appropriate number of database instances (DBI) */
+ /* append each new DBI to the end of the list */
+ for (i=0; i < dbcount; i++) {
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* how many queries were passed in from config file? */
+ switch(argc) {
+ case 5:
+ result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
+ NULL, argv[3], argv[4],
+ NULL, &db);
+ break;
+ case 6:
+ result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
+ argv[5], argv[3], argv[4],
+ NULL, &db);
+ break;
+ case 7:
+ result = build_sqldbinstance(ns_g_mctx, argv[6], NULL,
+ argv[5], argv[3], argv[4],
+ NULL, &db);
+ break;
+ case 8:
+ result = build_sqldbinstance(ns_g_mctx, argv[6],
+ argv[7], argv[5], argv[3],
+ argv[4], NULL, &db);
+ break;
+ default:
+ /* not really needed, should shut up compiler. */
+ result = ISC_R_FAILURE;
+ }
+
+ /* unsuccessful?, log err msg and cleanup. */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver could not create "
+ "database instance object.");
+ goto cleanup;
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* when multithreaded, build a list of DBI's */
+ ISC_LINK_INIT(db, link);
+ ISC_LIST_APPEND(*odbc_inst->db, db, link);
+
+#endif
+
+ result = odbc_connect(odbc_inst, (odbc_db_t **) &(db->dbconn));
+
+ if (result != ISC_R_SUCCESS) {
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /*
+ * if multi threaded, let user know which
+ * connection failed. user could be
+ * attempting to create 10 db connections and
+ * for some reason the db backend only allows
+ * 9.
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver failed to create database "
+ "connection number %u after 3 attempts",
+ i+1);
+#else
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Odbc driver failed to create database "
+ "connection after 3 attempts");
+#endif
+ goto cleanup;
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* set DB = null for next loop through. */
+ db = NULL;
+
+ } /* end for loop */
+
+#else
+ /* tell odbc_inst about the db connection we just created. */
+ odbc_inst->db = db;
+
+#endif
+
+ /* set dbdata to the odbc_instance we created. */
+ *dbdata = odbc_inst;
+
+ /* hey, we got through all of that ok, return success. */
+ return(ISC_R_SUCCESS);
+
+ cleanup:
+
+ destroy_odbc_instance(odbc_inst);
+
+ return result;
+}
+
+/*%
+ * destroy an instance of the driver. Remember, only 1 copy of the driver's
+ * code is ever loaded, the driver has to remember which context it's
+ * operating in. This is done via use of the dbdata argument.
+ * so we really only need to clean it up since we are not using driverarg.
+ */
+
+static void
+odbc_destroy(void *driverarg, void *dbdata)
+{
+ UNUSED(driverarg);
+
+ destroy_odbc_instance((odbc_instance_t *) dbdata);
+}
+
+
+/* pointers to all our runtime methods. */
+/* this is used during driver registration */
+/* i.e. in dlz_odbc_init below. */
+static dns_sdlzmethods_t dlz_odbc_methods = {
+ odbc_create,
+ odbc_destroy,
+ odbc_findzone,
+ odbc_lookup,
+ odbc_authority,
+ odbc_allnodes,
+ odbc_allowzonexfr
+};
+
+/*%
+ * Wrapper around dns_sdlzregister().
+ */
+isc_result_t
+dlz_odbc_init(void) {
+ isc_result_t result;
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Registering DLZ odbc driver.");
+
+ /*
+ * Driver is always threadsafe. When multithreaded all
+ * functions use multithreaded code. When not multithreaded,
+ * all functions can only be entered once, but only 1 thread
+ * of operation is available in Bind. So everything is still
+ * threadsafe.
+ */
+ result = dns_sdlzregister("odbc", &dlz_odbc_methods, NULL,
+ DNS_SDLZFLAG_RELATIVEOWNER |
+ DNS_SDLZFLAG_RELATIVERDATA |
+ DNS_SDLZFLAG_THREADSAFE,
+ ns_g_mctx, &dlz_odbc);
+ /* if we can't register the driver, there are big problems. */
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+
+ return result;
+}
+
+/*%
+ * Wrapper around dns_sdlzunregister().
+ */
+void
+dlz_odbc_clear(void) {
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Unregistering DLZ odbc driver.");
+
+ /* unregister the driver. */
+ if (dlz_odbc != NULL)
+ dns_sdlzunregister(&dlz_odbc);
+}
+
+#endif
diff --git a/contrib/dlz/drivers/dlz_postgres_driver.c b/contrib/dlz/drivers/dlz_postgres_driver.c
new file mode 100644
index 0000000..5cad59e
--- /dev/null
+++ b/contrib/dlz/drivers/dlz_postgres_driver.c
@@ -0,0 +1,1372 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef DLZ_POSTGRES
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <dns/log.h>
+#include <dns/sdlz.h>
+#include <dns/result.h>
+
+#include <isc/mem.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+
+#include <dlz/sdlz_helper.h>
+#include <dlz/dlz_postgres_driver.h>
+
+/* temporarily include time. */
+#include <time.h>
+
+#include <libpq-fe.h>
+
+static dns_sdlzimplementation_t *dlz_postgres = NULL;
+
+#define dbc_search_limit 30
+#define ALLNODES 1
+#define ALLOWXFR 2
+#define AUTHORITY 3
+#define FINDZONE 4
+#define LOOKUP 5
+
+/*
+ * Private methods
+ */
+
+/* ---------------
+ * Escaping arbitrary strings to get valid SQL strings/identifiers.
+ *
+ * Replaces "\\" with "\\\\" and "'" with "''".
+ * length is the length of the buffer pointed to by
+ * from. The buffer at to must be at least 2*length + 1 characters
+ * long. A terminating NUL character is written.
+ *
+ * NOTICE!!!
+ * This function was borrowed directly from PostgreSQL's libpq.
+ * The function was originally called PQescapeString and renamed
+ * to postgres_makesafe to avoid a naming collision.
+ * PQescapeString is a new function made available in Postgres 7.2.
+ * For some reason the function is not properly exported on Win32
+ * builds making the function unavailable on Windows. Also, since
+ * this function is new it would require building this driver with
+ * the libpq 7.2. By borrowing this function the Windows problem
+ * is solved, and the dependence on libpq 7.2 is removed. Libpq is
+ * still required of course, but an older version should work now too.
+ *
+ * The copyright statements from the original file containing this
+ * function are included below:
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ * ---------------
+ */
+
+static size_t
+postgres_makesafe(char *to, const char *from, size_t length)
+{
+ const char *source = from;
+ char *target = to;
+ unsigned int remaining = length;
+
+ while (remaining > 0)
+ {
+ switch (*source)
+ {
+ case '\\':
+ *target = '\\';
+ target++;
+ *target = '\\';
+ /* target and remaining are updated below. */
+ break;
+
+ case '\'':
+ *target = '\'';
+ target++;
+ *target = '\'';
+ /* target and remaining are updated below. */
+ break;
+
+ default:
+ *target = *source;
+ /* target and remaining are updated below. */
+ }
+ source++;
+ target++;
+ remaining--;
+ }
+
+ /* Write the terminating NUL character. */
+ *target = '\0';
+
+ return target - to;
+}
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+/*%
+ * Properly cleans up a list of database instances.
+ * This function is only used when the driver is compiled for
+ * multithreaded operation.
+ */
+static void
+postgres_destroy_dblist(db_list_t *dblist)
+{
+
+ dbinstance_t *ndbi = NULL;
+ dbinstance_t *dbi = NULL;
+
+ /* get the first DBI in the list */
+ ndbi = ISC_LIST_HEAD(*dblist);
+
+ /* loop through the list */
+ while (ndbi != NULL) {
+ dbi = ndbi;
+ /* get the next DBI in the list */
+ ndbi = ISC_LIST_NEXT(dbi, link);
+ /* release DB connection */
+ if (dbi->dbconn != NULL)
+ PQfinish((PGconn *) dbi->dbconn);
+ /* release all memory that comprised a DBI */
+ destroy_sqldbinstance(dbi);
+ }
+ /* release memory for the list structure */
+ isc_mem_put(ns_g_mctx, dblist, sizeof(db_list_t));
+}
+
+/*%
+ * Loops through the list of DB instances, attempting to lock
+ * on the mutex. If successful, the DBI is reserved for use
+ * and the thread can perform queries against the database.
+ * If the lock fails, the next one in the list is tried.
+ * looping continues until a lock is obtained, or until
+ * the list has been searched dbc_search_limit times.
+ * This function is only used when the driver is compiled for
+ * multithreaded operation.
+ */
+
+static dbinstance_t *
+postgres_find_avail_conn(db_list_t *dblist)
+{
+ dbinstance_t *dbi = NULL;
+ dbinstance_t *head;
+ int count = 0;
+
+ /* get top of list */
+ head = dbi = ISC_LIST_HEAD(*dblist);
+
+ /* loop through list */
+ while (count < dbc_search_limit) {
+ /* try to lock on the mutex */
+ if (isc_mutex_trylock(&dbi->instance_lock) == ISC_R_SUCCESS)
+ return dbi; /* success, return the DBI for use. */
+
+ /* not successful, keep trying */
+ dbi = ISC_LIST_NEXT(dbi, link);
+
+ /* check to see if we have gone to the top of the list. */
+ if (dbi == NULL) {
+ count++;
+ dbi = head;
+ }
+ }
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "Postgres driver unable to find available connection "
+ "after searching %d times",
+ count);
+ return NULL;
+}
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+/*%
+ * Allocates memory for a new string, and then constructs the new
+ * string by "escaping" the input string. The new string is
+ * safe to be used in queries. This is necessary because we cannot
+ * be sure of what types of strings are passed to us, and we don't
+ * want special characters in the string causing problems.
+ */
+
+static char *
+postgres_escape_string(const char *instr) {
+
+ char *outstr;
+ unsigned int len;
+
+ if (instr == NULL)
+ return NULL;
+
+ len = strlen(instr);
+
+ outstr = isc_mem_allocate(ns_g_mctx ,(2 * len * sizeof(char)) + 1);
+ if (outstr == NULL)
+ return NULL;
+
+ postgres_makesafe(outstr, instr, len);
+ /* PQescapeString(outstr, instr, len); */
+
+ return outstr;
+}
+
+/*%
+ * This function is the real core of the driver. Zone, record
+ * and client strings are passed in (or NULL is passed if the
+ * string is not available). The type of query we want to run
+ * is indicated by the query flag, and the dbdata object is passed
+ * passed in to. dbdata really holds either:
+ * 1) a list of database instances (in multithreaded mode) OR
+ * 2) a single database instance (in single threaded mode)
+ * The function will construct the query and obtain an available
+ * database instance (DBI). It will then run the query and hopefully
+ * obtain a result set. Postgres is nice, in that once the result
+ * set is returned, we can make the db connection available for another
+ * thread to use, while this thread continues on. So, the DBI is made
+ * available ASAP by unlocking the instance_lock after we have cleaned
+ * it up properly.
+ */
+static isc_result_t
+postgres_get_resultset(const char *zone, const char *record,
+ const char *client, unsigned int query,
+ void *dbdata, PGresult **rs)
+{
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+ char *querystring = NULL;
+ unsigned int i = 0;
+ unsigned int j = 0;
+
+ /* temporarily get a unique thread # */
+ unsigned int dlz_thread_num = 1+(int) (1000.0*rand()/(RAND_MAX+1.0));
+
+ REQUIRE(*rs == NULL);
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d Getting DBI", dlz_thread_num);
+#endif
+
+ /* get db instance / connection */
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* find an available DBI from the list */
+ dbi = postgres_find_avail_conn((db_list_t *) dbdata);
+
+#else /* ISC_PLATFORM_USETHREADS */
+
+ /*
+ * only 1 DBI - no need to lock instance lock either
+ * only 1 thread in the whole process, no possible contention.
+ */
+ dbi = (dbinstance_t *) dbdata;
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d Got DBI - checking query", dlz_thread_num);
+#endif
+
+ /* if DBI is null, can't do anything else */
+ if (dbi == NULL) {
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /* what type of query are we going to run? */
+ switch(query) {
+ case ALLNODES:
+ /*
+ * if the query was not passed in from the config file
+ * then we can't run it. return not_implemented, so
+ * it's like the code for that operation was never
+ * built into the driver.... AHHH flexibility!!!
+ */
+ if (dbi->allnodes_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ break;
+ case ALLOWXFR:
+ /* same as comments as ALLNODES */
+ if (dbi->allowxfr_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ break;
+ case AUTHORITY:
+ /* same as comments as ALLNODES */
+ if (dbi->authority_q == NULL) {
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup;
+ }
+ break;
+ case FINDZONE:
+ /* this is required. It's the whole point of DLZ! */
+ if (dbi->findzone_q == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "No query specified for findzone. "
+ "Findzone requires a query");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ break;
+ case LOOKUP:
+ /* this is required. It's also a major point of DLZ! */
+ if (dbi->lookup_q == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "No query specified for lookup. "
+ "Lookup requires a query");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ break;
+ default:
+ /*
+ * this should never happen. If it does, the code is
+ * screwed up!
+ */
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "Incorrect query flag passed to "
+ "postgres_get_resultset");
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d checked query", dlz_thread_num);
+#endif
+
+ /*
+ * was a zone string passed? If so, make it safe for use in
+ * queries.
+ */
+ if (zone != NULL) {
+ dbi->zone = postgres_escape_string(zone);
+ if (dbi->zone == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else { /* no string passed, set the string pointer to NULL */
+ dbi->zone = NULL;
+ }
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d did zone", dlz_thread_num);
+#endif
+
+ /*
+ * was a record string passed? If so, make it safe for use in
+ * queries.
+ */
+ if (record != NULL) {
+ dbi->record = postgres_escape_string(record);
+ if (dbi->record == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else { /* no string passed, set the string pointer to NULL */
+ dbi->record = NULL;
+ }
+
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d did record", dlz_thread_num);
+#endif
+
+ /*
+ * was a client string passed? If so, make it safe for use in
+ * queries.
+ */
+ if (client != NULL) {
+ dbi->client = postgres_escape_string(client);
+ if (dbi->client == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ } else { /* no string passed, set the string pointer to NULL */
+ dbi->client = NULL;
+ }
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d did client", dlz_thread_num);
+#endif
+
+ /*
+ * what type of query are we going to run?
+ * this time we build the actual query to run.
+ */
+ switch(query) {
+ case ALLNODES:
+ querystring = build_querystring(ns_g_mctx, dbi->allnodes_q);
+ break;
+ case ALLOWXFR:
+ querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q);
+ break;
+ case AUTHORITY:
+ querystring = build_querystring(ns_g_mctx, dbi->authority_q);
+ break;
+ case FINDZONE:
+ querystring = build_querystring(ns_g_mctx, dbi->findzone_q);
+ break;
+ case LOOKUP:
+ querystring = build_querystring(ns_g_mctx, dbi->lookup_q);
+ break;
+ default:
+ /*
+ * this should never happen. If it does, the code is
+ * screwed up!
+ */
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "Incorrect query flag passed to "
+ "postgres_get_resultset");
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d built query", dlz_thread_num);
+#endif
+
+ /* if the querystring is null, Bummer, outta RAM. UPGRADE TIME!!! */
+ if (querystring == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d query is '%s'", dlz_thread_num, querystring);
+#endif
+
+ /*
+ * output the full query string during debug so we can see
+ * what lame error the query has.
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "\nQuery String: %s\n", querystring);
+
+ /* attempt query up to 3 times. */
+ for (j=0; j < 3; j++) {
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d executing query for %d time",
+ dlz_thread_num, j);
+#endif
+ /* try to get result set */
+ *rs = PQexec((PGconn *)dbi->dbconn, querystring );
+ result = ISC_R_SUCCESS;
+ /*
+ * if result set is null, reset DB connection, max 3
+ * attempts.
+ */
+ for (i=0; *rs == NULL && i < 3; i++) {
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d resetting connection",
+ dlz_thread_num);
+#endif
+ result = ISC_R_FAILURE;
+ PQreset((PGconn *) dbi->dbconn);
+ /* connection ok, break inner loop */
+ if (PQstatus((PGconn *) dbi->dbconn) == CONNECTION_OK)
+ break;
+ }
+ /* result set ok, break outter loop */
+ if (PQresultStatus(*rs) == PGRES_TUPLES_OK) {
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d rs ok", dlz_thread_num);
+#endif
+ break;
+ } else {
+ /* we got a result set object, but it's not right. */
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d clearing rs", dlz_thread_num);
+#endif
+ PQclear(*rs); /* get rid of it */
+ /* in case this was the last attempt */
+ result = ISC_R_FAILURE;
+ }
+ }
+
+ cleanup:
+ /* it's always good to cleanup after yourself */
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d cleaning up", dlz_thread_num);
+#endif
+
+ /* if we couldn't even allocate DBI, just return NULL */
+ if (dbi == NULL)
+ return ISC_R_FAILURE;
+
+ /* free dbi->zone string */
+ if (dbi->zone != NULL)
+ isc_mem_free(ns_g_mctx, dbi->zone);
+
+ /* free dbi->record string */
+ if (dbi->record != NULL)
+ isc_mem_free(ns_g_mctx, dbi->record);
+
+ /* free dbi->client string */
+ if (dbi->client != NULL)
+ isc_mem_free(ns_g_mctx, dbi->client);
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d unlocking mutex", dlz_thread_num);
+#endif
+
+ /* release the lock so another thread can use this dbi */
+ isc_mutex_unlock(&dbi->instance_lock);
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* release query string */
+ if (querystring != NULL)
+ isc_mem_free(ns_g_mctx, querystring );
+
+#if 0
+ /* temporary logging message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "%d returning", dlz_thread_num);
+#endif
+
+ /* return result */
+ return result;
+}
+
+/*%
+ * The processing of result sets for lookup and authority are
+ * exactly the same. So that functionality has been moved
+ * into this function to minimize code.
+ */
+
+static isc_result_t
+postgres_process_rs(dns_sdlzlookup_t *lookup, PGresult *rs)
+{
+ isc_result_t result;
+ unsigned int i;
+ unsigned int rows;
+ unsigned int fields;
+ unsigned int j;
+ unsigned int len;
+ char *tmpString;
+ char *endp;
+ int ttl;
+
+ rows = PQntuples(rs); /* how many rows in result set */
+ fields = PQnfields(rs); /* how many columns in result set */
+ for (i=0; i < rows; i++) {
+ switch(fields) {
+ case 1:
+ /*
+ * one column in rs, it's the data field. use
+ * default type of A record, and default TTL
+ * of 86400
+ */
+ result = dns_sdlz_putrr(lookup, "a", 86400,
+ PQgetvalue(rs, i, 0));
+ break;
+ case 2:
+ /* two columns, data field, and data type.
+ * use default TTL of 86400.
+ */
+ result = dns_sdlz_putrr(lookup, PQgetvalue(rs, i, 0),
+ 86400, PQgetvalue(rs, i, 1));
+ break;
+ case 3:
+ /* three columns, all data no defaults.
+ * convert text to int, make sure it worked
+ * right.
+ */
+ ttl = strtol(PQgetvalue(rs, i, 0), &endp, 10);
+ if (*endp != '\0' || ttl < 0) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver ttl must be "
+ "a positive number");
+ }
+ result = dns_sdlz_putrr(lookup, PQgetvalue(rs, i, 1),
+ ttl, PQgetvalue(rs, i, 2));
+ break;
+ default:
+ /*
+ * more than 3 fields, concatenate the last
+ * ones together. figure out how long to make
+ * string
+ */
+ for (j=2, len=0; j < fields; j++) {
+ len += strlen(PQgetvalue(rs, i, j)) + 1;
+ }
+ /*
+ * allocate string memory, allow for NULL to
+ * term string
+ */
+ tmpString = isc_mem_allocate(ns_g_mctx, len + 1);
+ if (tmpString == NULL) {
+ /* major bummer, need more ram */
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver unable to "
+ "allocate memory for "
+ "temporary string");
+ PQclear(rs);
+ return (ISC_R_FAILURE); /* Yeah, I'd say! */
+ }
+ /* copy field to tmpString */
+ strcpy(tmpString, PQgetvalue(rs, i, 2));
+ /*
+ * concat the rest of fields together, space
+ * between each one.
+ */
+ for (j=3; j < fields; j++) {
+ strcat(tmpString, " ");
+ strcat(tmpString, PQgetvalue(rs, i, j));
+ }
+ /* convert text to int, make sure it worked right */
+ ttl = strtol(PQgetvalue(rs, i, 0), &endp, 10);
+ if (*endp != '\0' || ttl < 0) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver ttl must be "
+ "a postive number");
+ }
+ /* ok, now tell Bind about it. */
+ result = dns_sdlz_putrr(lookup, PQgetvalue(rs, i, 1),
+ ttl, tmpString);
+ /* done, get rid of this thing. */
+ isc_mem_free(ns_g_mctx, tmpString);
+ }
+ /* I sure hope we were successful */
+ if (result != ISC_R_SUCCESS) {
+ /* nope, get rid of the Result set, and log a msg */
+ PQclear(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "dns_sdlz_putrr returned error. "
+ "Error code was: %s",
+ isc_result_totext(result));
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ /* free result set memory */
+ PQclear(rs);
+
+ /* if we did return results, we are successful */
+ if (rows > 0)
+ return (ISC_R_SUCCESS);
+
+ /* empty result set, no data found */
+ return (ISC_R_NOTFOUND);
+}
+
+/*
+ * SDLZ interface methods
+ */
+
+/*% determine if the zone is supported by (in) the database */
+
+static isc_result_t
+postgres_findzone(void *driverarg, void *dbdata, const char *name)
+{
+ isc_result_t result;
+ PGresult *rs = NULL;
+ unsigned int rows;
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = postgres_get_resultset(name, NULL, NULL,
+ FINDZONE, dbdata, &rs);
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ if (rs != NULL)
+ PQclear(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver unable to return "
+ "result set for findzone query");
+ return (ISC_R_FAILURE);
+ }
+ /* count how many rows in result set */
+ rows = PQntuples(rs);
+ /* get rid of result set, we are done with it. */
+ PQclear(rs);
+
+ /* if we returned any rows, zone is supported. */
+ if (rows > 0)
+ return (ISC_R_SUCCESS);
+
+ /* no rows returned, zone is not supported. */
+ return (ISC_R_NOTFOUND);
+}
+
+/*% Determine if the client is allowed to perform a zone transfer */
+static isc_result_t
+postgres_allowzonexfr(void *driverarg, void *dbdata, const char *name,
+ const char *client)
+{
+ isc_result_t result;
+ PGresult *rs = NULL;
+ unsigned int rows;
+ UNUSED(driverarg);
+
+ /* first check if the zone is supported by the database. */
+ result = postgres_findzone(driverarg, dbdata, name);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_NOTFOUND);
+
+ /*
+ * if we get to this point we know the zone is supported by
+ * the database the only questions now are is the zone
+ * transfer is allowed for this client and did the config file
+ * have an allow zone xfr query.
+ *
+ * Run our query, and get a result set from the database.
+ */
+ result = postgres_get_resultset(name, NULL, client,
+ ALLOWXFR, dbdata, &rs);
+ /* if we get "not implemented", send it along. */
+ if (result == ISC_R_NOTIMPLEMENTED)
+ return result;
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ if (rs != NULL)
+ PQclear(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver unable to return "
+ "result set for allow xfr query");
+ return (ISC_R_FAILURE);
+ }
+ /* count how many rows in result set */
+ rows = PQntuples(rs);
+ /* get rid of result set, we are done with it. */
+ PQclear(rs);
+
+ /* if we returned any rows, zone xfr is allowed. */
+ if (rows > 0)
+ return (ISC_R_SUCCESS);
+
+ /* no rows returned, zone xfr not allowed */
+ return (ISC_R_NOPERM);
+}
+
+/*%
+ * If the client is allowed to perform a zone transfer, the next order of
+ * business is to get all the nodes in the zone, so bind can respond to the
+ * query.
+ */
+static isc_result_t
+postgres_allnodes(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzallnodes_t *allnodes)
+{
+ isc_result_t result;
+ PGresult *rs = NULL;
+ unsigned int i;
+ unsigned int rows;
+ unsigned int fields;
+ unsigned int j;
+ unsigned int len;
+ char *tmpString;
+ char *endp;
+ int ttl;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = postgres_get_resultset(zone, NULL, NULL,
+ ALLNODES, dbdata, &rs);
+ /* if we get "not implemented", send it along */
+ if (result == ISC_R_NOTIMPLEMENTED)
+ return result;
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ if (rs != NULL)
+ PQclear(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver unable to return "
+ "result set for all nodes query");
+ return (ISC_R_FAILURE);
+ }
+
+ rows = PQntuples(rs); /* how many rows in result set */
+ fields = PQnfields(rs); /* how many columns in result set */
+ for (i=0; i < rows; i++) {
+ if (fields < 4) { /* gotta have at least 4 columns */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver too few fields "
+ "returned by all nodes query");
+ }
+ /* convert text to int, make sure it worked right */
+ ttl = strtol(PQgetvalue(rs, i, 0), &endp, 10);
+ if (*endp != '\0' || ttl < 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver ttl must be "
+ "a postive number");
+ }
+ if (fields == 4) {
+ /* tell Bind about it. */
+ result = dns_sdlz_putnamedrr(allnodes,
+ PQgetvalue(rs, i, 2),
+ PQgetvalue(rs, i, 1),
+ ttl,
+ PQgetvalue(rs, i, 3));
+ } else {
+ /*
+ * more than 4 fields, concatonat the last
+ * ones together. figure out how long to make
+ * string
+ */
+ for (j=3, len=0; j < fields; j++) {
+ len += strlen(PQgetvalue(rs, i, j)) + 1;
+ }
+ /* allocate memory, allow for NULL to term string */
+ tmpString = isc_mem_allocate(ns_g_mctx, len + 1);
+ if (tmpString == NULL) { /* we need more ram. */
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver unable to "
+ "allocate memory for "
+ "temporary string");
+ PQclear(rs);
+ return (ISC_R_FAILURE);
+ }
+ /* copy this field to tmpString */
+ strcpy(tmpString, PQgetvalue(rs, i, 3));
+ /* concatonate the rest, with spaces between */
+ for (j=4; j < fields; j++) {
+ strcat(tmpString, " ");
+ strcat(tmpString, PQgetvalue(rs, i, j));
+ }
+ /* tell Bind about it. */
+ result = dns_sdlz_putnamedrr(allnodes,
+ PQgetvalue(rs, i, 2),
+ PQgetvalue(rs, i, 1),
+ ttl, tmpString);
+ isc_mem_free(ns_g_mctx, tmpString);
+ }
+ /* if we weren't successful, log err msg */
+ if (result != ISC_R_SUCCESS) {
+ PQclear(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "dns_sdlz_putnamedrr returned error. "
+ "Error code was: %s",
+ isc_result_totext(result));
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ /* free result set memory */
+ PQclear(rs);
+
+ /* if we did return results, we are successful */
+ if (rows > 0)
+ return (ISC_R_SUCCESS);
+
+ /* empty result set, no data found */
+ return (ISC_R_NOTFOUND);
+}
+
+/*%
+ * if the lookup function does not return SOA or NS records for the zone,
+ * use this function to get that information for Bind.
+ */
+
+static isc_result_t
+postgres_authority(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzlookup_t *lookup)
+{
+ isc_result_t result;
+ PGresult *rs = NULL;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = postgres_get_resultset(zone, NULL, NULL,
+ AUTHORITY, dbdata, &rs);
+ /* if we get "not implemented", send it along */
+ if (result == ISC_R_NOTIMPLEMENTED)
+ return result;
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ if (rs != NULL)
+ PQclear(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver unable to return "
+ "result set for authority query");
+ return (ISC_R_FAILURE);
+ }
+ /*
+ * lookup and authority result sets are processed in the same
+ * manner postgres_process_rs does the job for both
+ * functions.
+ */
+ return postgres_process_rs(lookup, rs);
+}
+
+/*% if zone is supported, lookup up a (or multiple) record(s) in it */
+static isc_result_t
+postgres_lookup(const char *zone, const char *name, void *driverarg,
+ void *dbdata, dns_sdlzlookup_t *lookup)
+{
+ isc_result_t result;
+ PGresult *rs = NULL;
+
+ UNUSED(driverarg);
+
+ /* run the query and get the result set from the database. */
+ result = postgres_get_resultset(zone, name, NULL, LOOKUP, dbdata, &rs);
+ /* if we didn't get a result set, log an err msg. */
+ if (result != ISC_R_SUCCESS) {
+ if (rs != NULL)
+ PQclear(rs);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver unable to "
+ "return result set for lookup query");
+ return (ISC_R_FAILURE);
+ }
+ /*
+ * lookup and authority result sets are processed in the same
+ * manner postgres_process_rs does the job for both functions.
+ */
+ return postgres_process_rs(lookup, rs);
+}
+
+/*%
+ * create an instance of the driver. Remember, only 1 copy of the driver's
+ * code is ever loaded, the driver has to remember which context it's
+ * operating in. This is done via use of the dbdata argument which is
+ * passed into all query functions.
+ */
+static isc_result_t
+postgres_create(const char *dlzname, unsigned int argc, char *argv[],
+ void *driverarg, void **dbdata)
+{
+ isc_result_t result;
+ dbinstance_t *dbi = NULL;
+ unsigned int j;
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /* if multi-threaded, we need a few extra variables. */
+ int dbcount;
+ db_list_t *dblist = NULL;
+ int i;
+ char *endp;
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ UNUSED(driverarg);
+ UNUSED(dlzname);
+
+/* seed random # generator */
+ srand( (unsigned)time( NULL ) );
+
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /* if debugging, let user know we are multithreaded. */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "Postgres driver running multithreaded");
+#else /* ISC_PLATFORM_USETHREADS */
+ /* if debugging, let user know we are single threaded. */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
+ "Postgres driver running single threaded");
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* verify we have at least 5 arg's passed to the driver */
+ if (argc < 5) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver requires at least "
+ "4 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* no more than 8 arg's should be passed to the driver */
+ if (argc > 8) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver cannot accept more than "
+ "7 command line args.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* multithreaded build can have multiple DB connections */
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* check how many db connections we should create */
+ dbcount = strtol(argv[1], &endp, 10);
+ if (*endp != '\0' || dbcount < 0) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver database connection count "
+ "must be positive.");
+ return (ISC_R_FAILURE);
+ }
+
+ /* allocate memory for database connection list */
+ dblist = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
+ if (dblist == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /* initialize DB connection list */
+ ISC_LIST_INIT(*dblist);
+
+ /*
+ * create the appropriate number of database instances (DBI)
+ * append each new DBI to the end of the list
+ */
+ for (i=0; i < dbcount; i++) {
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* how many queries were passed in from config file? */
+ switch(argc) {
+ case 5:
+ result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
+ NULL, argv[3], argv[4],
+ NULL, &dbi);
+ break;
+ case 6:
+ result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
+ argv[5], argv[3], argv[4],
+ NULL, &dbi);
+ break;
+ case 7:
+ result = build_sqldbinstance(ns_g_mctx, argv[6], NULL,
+ argv[5], argv[3], argv[4],
+ NULL, &dbi);
+ break;
+ case 8:
+ result = build_sqldbinstance(ns_g_mctx, argv[6],
+ argv[7], argv[5], argv[3],
+ argv[4], NULL, &dbi);
+ break;
+ default:
+ /* not really needed, should shut up compiler. */
+ result = ISC_R_FAILURE;
+ }
+
+
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Postgres driver created database "
+ "instance object.");
+ } else { /* unsuccessful?, log err msg and cleanup. */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver could not create "
+ "database instance object.");
+ goto cleanup;
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /* when multithreaded, build a list of DBI's */
+ ISC_LINK_INIT(dbi, link);
+ ISC_LIST_APPEND(*dblist, dbi, link);
+
+#endif
+
+ /* create and set db connection */
+ dbi->dbconn = PQconnectdb(argv[2]);
+ /*
+ * if db connection cannot be created, log err msg and
+ * cleanup.
+ */
+ if (dbi->dbconn == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver could not allocate "
+ "memory for database connection");
+ goto cleanup;
+ }
+
+ /* if we cannot connect the first time, try 3 more times. */
+ for (j = 0;
+ PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK &&
+ j < 3;
+ j++)
+ PQreset((PGconn *) dbi->dbconn);
+
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ /*
+ * if multi threaded, let user know which connection
+ * failed. user could be attempting to create 10 db
+ * connections and for some reason the db backend only
+ * allows 9
+ */
+ if (PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver failed to create "
+ "database connection number %u "
+ "after 4 attempts",
+ i + 1);
+ goto cleanup;
+ }
+
+ /* set DBI = null for next loop through. */
+ dbi = NULL;
+ } /* end for loop */
+
+ /* set dbdata to the list we created. */
+ *dbdata = dblist;
+
+#else /* ISC_PLATFORM_USETHREADS */
+ /* if single threaded, just let user know we couldn't connect. */
+ if (PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Postgres driver failed to create database "
+ "connection after 4 attempts");
+ goto cleanup;
+ }
+
+ /*
+ * single threaded build can only use 1 db connection, return
+ * it via dbdata
+ */
+ *dbdata = dbi;
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /* hey, we got through all of that ok, return success. */
+ return(ISC_R_SUCCESS);
+
+ cleanup:
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * if multithreaded, we could fail because only 1 connection
+ * couldn't be made. We should cleanup the other successful
+ * connections properly.
+ */
+ postgres_destroy_dblist(dblist);
+
+#else /* ISC_PLATFORM_USETHREADS */
+ if (dbi != NULL)
+ destroy_sqldbinstance(dbi);
+
+#endif /* ISC_PLATFORM_USETHREADS */
+ return(ISC_R_FAILURE);
+}
+
+/*%
+ * destroy an instance of the driver. Remember, only 1 copy of the driver's
+ * code is ever loaded, the driver has to remember which context it's
+ * operating in. This is done via use of the dbdata argument.
+ * so we really only need to clean it up since we are not using driverarg.
+ */
+static void
+postgres_destroy(void *driverarg, void *dbdata)
+{
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+ UNUSED(driverarg);
+ /* cleanup the list of DBI's */
+ postgres_destroy_dblist((db_list_t *) dbdata);
+
+#else /* ISC_PLATFORM_USETHREADS */
+
+ dbinstance_t *dbi;
+
+ UNUSED(driverarg);
+
+ dbi = (dbinstance_t *) dbdata;
+
+ /* release DB connection */
+ if (dbi->dbconn != NULL)
+ PQfinish((PGconn *) dbi->dbconn);
+
+ /* destroy single DB instance */
+ destroy_sqldbinstance(dbi);
+
+#endif /* ISC_PLATFORM_USETHREADS */
+}
+
+/* pointers to all our runtime methods. */
+/* this is used during driver registration */
+/* i.e. in dlz_postgres_init below. */
+static dns_sdlzmethods_t dlz_postgres_methods = {
+ postgres_create,
+ postgres_destroy,
+ postgres_findzone,
+ postgres_lookup,
+ postgres_authority,
+ postgres_allnodes,
+ postgres_allowzonexfr
+};
+
+/*%
+ * Wrapper around dns_sdlzregister().
+ */
+isc_result_t
+dlz_postgres_init(void) {
+ isc_result_t result;
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Registering DLZ postgres driver.");
+
+ /*
+ * Driver is always threadsafe. When multithreaded all
+ * functions use multithreaded code. When not multithreaded,
+ * all functions can only be entered once, but only 1 thread
+ * of operation is available in Bind. So everything is still
+ * threadsafe.
+ */
+ result = dns_sdlzregister("postgres", &dlz_postgres_methods, NULL,
+ DNS_SDLZFLAG_RELATIVEOWNER |
+ DNS_SDLZFLAG_RELATIVERDATA |
+ DNS_SDLZFLAG_THREADSAFE,
+ ns_g_mctx, &dlz_postgres);
+ /* if we can't register the driver, there are big problems. */
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+
+ return result;
+}
+
+/*%
+ * Wrapper around dns_sdlzunregister().
+ */
+void
+dlz_postgres_clear(void) {
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Unregistering DLZ postgres driver.");
+
+ /* unregister the driver. */
+ if (dlz_postgres != NULL)
+ dns_sdlzunregister(&dlz_postgres);
+}
+
+#endif
diff --git a/contrib/dlz/drivers/dlz_stub_driver.c b/contrib/dlz/drivers/dlz_stub_driver.c
new file mode 100644
index 0000000..f9a3bb8
--- /dev/null
+++ b/contrib/dlz/drivers/dlz_stub_driver.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef DLZ_STUB
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <dns/log.h>
+#include <dns/sdlz.h>
+#include <dns/result.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <named/globals.h>
+
+#include <dlz/dlz_stub_driver.h>
+
+static dns_sdlzimplementation_t *dlz_stub = NULL;
+
+typedef struct config_data {
+ char *myzone;
+ char *myname;
+ char *myip;
+ isc_mem_t *mctx;
+} config_data_t;
+
+/*
+ * SDLZ methods
+ */
+
+static isc_result_t
+stub_dlz_allnodes(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzallnodes_t *allnodes)
+{
+ config_data_t *cd;
+ isc_result_t result;
+
+ UNUSED(zone);
+ UNUSED(driverarg);
+
+ cd = (config_data_t *) dbdata;
+
+ result = dns_sdlz_putnamedrr(allnodes, cd->myname, "soa", 86400,
+ "web root.localhost. "
+ "0 28800 7200 604800 86400");
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+ result = dns_sdlz_putnamedrr(allnodes, "ns", "ns", 86400, cd->myname);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+ result = dns_sdlz_putnamedrr(allnodes, cd->myname, "a", 1, cd->myip);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+stub_dlz_allowzonexfr(void *driverarg, void *dbdata, const char *name,
+ const char *client)
+{
+ UNUSED(driverarg);
+ UNUSED(dbdata);
+ UNUSED(name);
+ UNUSED(client);
+ return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+stub_dlz_authority(const char *zone, void *driverarg, void *dbdata,
+ dns_sdlzlookup_t *lookup)
+{
+ isc_result_t result;
+ config_data_t *cd;
+
+ UNUSED(driverarg);
+
+ cd = (config_data_t *) dbdata;
+
+ if (strcmp(zone, cd->myzone) == 0) {
+ result = dns_sdlz_putsoa(lookup, cd->myname,
+ "root.localhost.", 0);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+
+ result = dns_sdlz_putrr(lookup, "ns", 86400, cd->myname);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+
+ return (ISC_R_SUCCESS);
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+stub_dlz_findzonedb(void *driverarg, void *dbdata, const char *name)
+{
+
+ config_data_t *cd;
+
+ UNUSED(driverarg);
+
+ cd = (config_data_t *) dbdata;
+
+ /* Write info message to log */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "dlz_stub findzone looking for '%s'", name);
+
+ if (strcmp(cd->myzone, name) == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+
+static isc_result_t
+stub_dlz_lookup(const char *zone, const char *name, void *driverarg,
+ void *dbdata, dns_sdlzlookup_t *lookup)
+{
+ isc_result_t result;
+ config_data_t *cd;
+
+ UNUSED(zone);
+ UNUSED(driverarg);
+
+ cd = (config_data_t *) dbdata;
+
+ if (strcmp(name, cd->myname) == 0) {
+ result = dns_sdlz_putrr(lookup, "a", 1, cd->myip);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+
+ return (ISC_R_SUCCESS);
+ }
+ return (ISC_R_FAILURE);
+
+}
+
+
+static isc_result_t
+stub_dlz_create(const char *dlzname, unsigned int argc, char *argv[],
+ void *driverarg, void **dbdata)
+{
+
+ config_data_t *cd;
+
+ UNUSED(driverarg);
+
+ if (argc < 4)
+ return (ISC_R_FAILURE);
+ /*
+ * Write info message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "Loading '%s' using DLZ_stub driver. "
+ "Zone: %s, Name: %s IP: %s",
+ dlzname, argv[1], argv[2], argv[3]);
+
+ cd = isc_mem_get(ns_g_mctx, sizeof(config_data_t));
+ if ((cd) == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ memset(cd, 0, sizeof(config_data_t));
+
+ cd->myzone = isc_mem_strdup(ns_g_mctx, argv[1]);
+ if (cd->myzone == NULL) {
+ isc_mem_put(ns_g_mctx, cd, sizeof(config_data_t));
+ return (ISC_R_NOMEMORY);
+ }
+
+ cd->myname = isc_mem_strdup(ns_g_mctx, argv[2]);
+ if (cd->myname == NULL) {
+ isc_mem_put(ns_g_mctx, cd, sizeof(config_data_t));
+ isc_mem_free(ns_g_mctx, cd->myzone);
+ return (ISC_R_NOMEMORY);
+ }
+
+ cd->myip = isc_mem_strdup(ns_g_mctx, argv[3]);
+ if (cd->myip == NULL) {
+ isc_mem_put(ns_g_mctx, cd, sizeof(config_data_t));
+ isc_mem_free(ns_g_mctx, cd->myname);
+ isc_mem_free(ns_g_mctx, cd->myzone);
+ return (ISC_R_NOMEMORY);
+ }
+
+ isc_mem_attach(ns_g_mctx, &cd->mctx);
+
+ *dbdata = cd;
+
+ return(ISC_R_SUCCESS);
+}
+
+static void
+stub_dlz_destroy(void *driverarg, void *dbdata)
+{
+ config_data_t *cd;
+ isc_mem_t *mctx;
+
+ UNUSED(driverarg);
+
+ cd = (config_data_t *) dbdata;
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Unloading DLZ_stub driver.");
+
+ isc_mem_free(ns_g_mctx, cd->myzone);
+ isc_mem_free(ns_g_mctx, cd->myname);
+ isc_mem_free(ns_g_mctx, cd->myip);
+ mctx = cd->mctx;
+ isc_mem_put(mctx, cd, sizeof(config_data_t));
+ isc_mem_detach(&mctx);
+}
+
+static dns_sdlzmethods_t dlz_stub_methods = {
+ stub_dlz_create,
+ stub_dlz_destroy,
+ stub_dlz_findzonedb,
+ stub_dlz_lookup,
+ stub_dlz_authority,
+ stub_dlz_allnodes,
+ stub_dlz_allowzonexfr
+};
+
+/*%
+ * Wrapper around dns_sdlzregister().
+ */
+isc_result_t
+dlz_stub_init(void) {
+ isc_result_t result;
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Registering DLZ_stub driver.");
+
+ result = dns_sdlzregister("dlz_stub", &dlz_stub_methods, NULL,
+ DNS_SDLZFLAG_RELATIVEOWNER |
+ DNS_SDLZFLAG_RELATIVERDATA,
+ ns_g_mctx, &dlz_stub);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_sdlzregister() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ }
+
+
+ return result;
+}
+
+/*
+ * Wrapper around dns_sdlzunregister().
+ */
+void
+dlz_stub_clear(void) {
+
+ /*
+ * Write debugging message to log
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Unregistering DLZ_stub driver.");
+
+ if (dlz_stub != NULL)
+ dns_sdlzunregister(&dlz_stub);
+}
+
+#endif
diff --git a/contrib/dlz/drivers/include/dlz/dlz_bdb_driver.h b/contrib/dlz/drivers/include/dlz/dlz_bdb_driver.h
new file mode 100644
index 0000000..1d706fc
--- /dev/null
+++ b/contrib/dlz/drivers/include/dlz/dlz_bdb_driver.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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 DLZ_BDB_DRIVER_H
+#define DLZ_BDB_DRIVER_H
+
+isc_result_t
+dlz_bdb_init(void);
+
+void
+dlz_bdb_clear(void);
+
+#endif
diff --git a/contrib/dlz/drivers/include/dlz/dlz_bdbhpt_driver.h b/contrib/dlz/drivers/include/dlz/dlz_bdbhpt_driver.h
new file mode 100644
index 0000000..0ccbc8d
--- /dev/null
+++ b/contrib/dlz/drivers/include/dlz/dlz_bdbhpt_driver.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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 DLZ_BDBHPT_DRIVER_H
+#define DLZ_BDBHPT_DRIVER_H
+
+isc_result_t
+dlz_bdbhpt_init(void);
+
+void
+dlz_bdbhpt_clear(void);
+
+#endif
diff --git a/contrib/dlz/drivers/include/dlz/dlz_drivers.h b/contrib/dlz/drivers/include/dlz/dlz_drivers.h
new file mode 100644
index 0000000..dce7cd2
--- /dev/null
+++ b/contrib/dlz/drivers/include/dlz/dlz_drivers.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND 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: dlz_drivers.h,v 1.2 2005/09/05 00:10:58 marka Exp $ */
+
+#ifndef DLZ_DRIVERS_H
+#define DLZ_DRIVERS_H 1
+
+/*! \file */
+
+isc_result_t
+dlz_drivers_init(void);
+
+void
+dlz_drivers_clear(void);
+
+#endif /* DLZ_DRIVERS_H */
diff --git a/contrib/dlz/drivers/include/dlz/dlz_filesystem_driver.h b/contrib/dlz/drivers/include/dlz/dlz_filesystem_driver.h
new file mode 100644
index 0000000..627427d
--- /dev/null
+++ b/contrib/dlz/drivers/include/dlz/dlz_filesystem_driver.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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 DLZ_FILESYSTEM_DRIVER_H
+#define DLZ_FILESYSTEM_DRIVER_H
+
+isc_result_t
+dlz_fs_init(void);
+
+void
+dlz_fs_clear(void);
+
+#endif
diff --git a/contrib/dlz/drivers/include/dlz/dlz_ldap_driver.h b/contrib/dlz/drivers/include/dlz/dlz_ldap_driver.h
new file mode 100644
index 0000000..51efbf4
--- /dev/null
+++ b/contrib/dlz/drivers/include/dlz/dlz_ldap_driver.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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 DLZ_LDAP_DRIVER_H
+#define DLZ_LDAP_DRIVER_H
+
+isc_result_t
+dlz_ldap_init(void);
+
+void
+dlz_ldap_clear(void);
+
+#endif
diff --git a/contrib/dlz/drivers/include/dlz/dlz_mysql_driver.h b/contrib/dlz/drivers/include/dlz/dlz_mysql_driver.h
new file mode 100644
index 0000000..b742838
--- /dev/null
+++ b/contrib/dlz/drivers/include/dlz/dlz_mysql_driver.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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 DLZ_MYSQL_DRIVER_H
+#define DLZ_MYSQL_DRIVER_H
+
+isc_result_t
+dlz_mysql_init(void);
+
+void
+dlz_mysql_clear(void);
+
+#endif
diff --git a/contrib/dlz/drivers/include/dlz/dlz_odbc_driver.h b/contrib/dlz/drivers/include/dlz/dlz_odbc_driver.h
new file mode 100644
index 0000000..5a072d8
--- /dev/null
+++ b/contrib/dlz/drivers/include/dlz/dlz_odbc_driver.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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 DLZ_ODBC_DRIVER_H
+#define DLZ_ODBC_DRIVER_H
+
+isc_result_t
+dlz_odbc_init(void);
+
+void
+dlz_odbc_clear(void);
+
+#endif
diff --git a/contrib/dlz/drivers/include/dlz/dlz_postgres_driver.h b/contrib/dlz/drivers/include/dlz/dlz_postgres_driver.h
new file mode 100644
index 0000000..3416dce
--- /dev/null
+++ b/contrib/dlz/drivers/include/dlz/dlz_postgres_driver.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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 DLZ_POSTGRES_DRIVER_H
+#define DLZ_POSTGRES_DRIVER_H
+
+isc_result_t
+dlz_postgres_init(void);
+
+void
+dlz_postgres_clear(void);
+
+#endif
diff --git a/contrib/dlz/drivers/include/dlz/dlz_stub_driver.h b/contrib/dlz/drivers/include/dlz/dlz_stub_driver.h
new file mode 100644
index 0000000..a517c69
--- /dev/null
+++ b/contrib/dlz/drivers/include/dlz/dlz_stub_driver.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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 DLZ_STUB_DRIVER_H
+#define DLZ_STUB_DRIVER_H
+
+isc_result_t
+dlz_stub_init(void);
+
+void
+dlz_stub_clear(void);
+
+#endif
diff --git a/contrib/dlz/drivers/include/dlz/sdlz_helper.h b/contrib/dlz/drivers/include/dlz/sdlz_helper.h
new file mode 100644
index 0000000..764a05a
--- /dev/null
+++ b/contrib/dlz/drivers/include/dlz/sdlz_helper.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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 SDLZHELPER_H
+#define SDLZHELPER_H
+
+/*
+ * Types
+ */
+#define SDLZH_REQUIRE_CLIENT 0x01
+#define SDLZH_REQUIRE_QUERY 0x02
+#define SDLZH_REQUIRE_RECORD 0x04
+#define SDLZH_REQUIRE_ZONE 0x08
+
+typedef struct query_segment query_segment_t;
+typedef ISC_LIST(query_segment_t) query_list_t;
+typedef struct dbinstance dbinstance_t;
+typedef ISC_LIST(dbinstance_t) db_list_t;
+typedef struct driverinstance driverinstance_t;
+
+/*%
+ * a query segment is all the text between our special tokens
+ * special tokens are %zone%, %record%, %client%
+ */
+struct query_segment {
+ void *sql;
+ unsigned int strlen;
+ isc_boolean_t direct;
+ ISC_LINK(query_segment_t) link;
+};
+
+/*%
+ * a database instance contains everything we need for running
+ * a query against the database. Using it each separate thread
+ * can dynamically construct a query and execute it against the
+ * database. The "instance_lock" and locking code in the driver's
+ * make sure no two threads try to use the same DBI at a time.
+ */
+struct dbinstance {
+ void *dbconn;
+ query_list_t *allnodes_q;
+ query_list_t *allowxfr_q;
+ query_list_t *authority_q;
+ query_list_t *findzone_q;
+ query_list_t *lookup_q;
+ query_list_t *countzone_q;
+ char *query_buf;
+ char *zone;
+ char *record;
+ char *client;
+ isc_mem_t *mctx;
+ isc_mutex_t instance_lock;
+ ISC_LINK(dbinstance_t) link;
+};
+
+/*
+ * Method declarations
+ */
+
+/* see the code in sdlz_helper.c for more information on these methods */
+
+char *
+sdlzh_build_querystring(isc_mem_t *mctx, query_list_t *querylist);
+
+isc_result_t
+sdlzh_build_sqldbinstance(isc_mem_t *mctx, const char *allnodes_str,
+ const char *allowxfr_str, const char *authority_str,
+ const char *findzone_str, const char *lookup_str,
+ const char *countzone_str, dbinstance_t **dbi);
+
+void
+sdlzh_destroy_sqldbinstance(dbinstance_t *dbi);
+
+char *
+sdlzh_get_parameter_value(isc_mem_t *mctx, const char *input, const char* key);
+
+/* Compatability with existing DLZ drivers */
+
+#define build_querystring sdlzh_build_querystring
+#define build_sqldbinstance sdlzh_build_sqldbinstance
+#define destroy_sqldbinstance sdlzh_destroy_sqldbinstance
+
+#define getParameterValue(x,y) sdlzh_get_parameter_value(ns_g_mctx, (x), (y))
+
+#endif /* SDLZHELPER_H */
diff --git a/contrib/dlz/drivers/rules.in b/contrib/dlz/drivers/rules.in
new file mode 100644
index 0000000..9caabcb
--- /dev/null
+++ b/contrib/dlz/drivers/rules.in
@@ -0,0 +1,47 @@
+# Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND 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: rules.in,v 1.2 2005/09/05 00:10:57 marka Exp $
+
+dlz_drivers.@O@: ${DLZ_DRIVER_DIR}/dlz_drivers.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_drivers.h
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_drivers.c
+
+sdlz_helper.@O@: ${DLZ_DRIVER_DIR}/sdlz_helper.c ${DLZ_DRIVER_DIR}/include/dlz/sdlz_helper.h
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/sdlz_helper.c
+
+
+dlz_bdb_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_bdb_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_bdb_driver.h
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_bdb_driver.c
+
+dlz_bdbhpt_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_bdbhpt_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_bdbhpt_driver.h
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_bdbhpt_driver.c
+
+dlz_filesystem_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_filesystem_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_filesystem_driver.h
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_filesystem_driver.c
+
+dlz_ldap_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_ldap_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_ldap_driver.h
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_ldap_driver.c
+
+dlz_mysql_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_mysql_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_mysql_driver.h
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_mysql_driver.c
+
+dlz_odbc_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_odbc_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_odbc_driver.h
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_odbc_driver.c
+
+dlz_postgres_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_postgres_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_postgres_driver.h
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_postgres_driver.c
+
+dlz_stub_driver.@O@: ${DLZ_DRIVER_DIR}/dlz_stub_driver.c ${DLZ_DRIVER_DIR}/include/dlz/dlz_stub_driver.h
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c ${DLZ_DRIVER_DIR}/dlz_stub_driver.c
+
diff --git a/contrib/dlz/drivers/sdlz_helper.c b/contrib/dlz/drivers/sdlz_helper.c
new file mode 100644
index 0000000..ea33db1
--- /dev/null
+++ b/contrib/dlz/drivers/sdlz_helper.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+ * USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef DLZ
+
+#include <config.h>
+
+#include <dns/log.h>
+#include <dns/result.h>
+
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dlz/sdlz_helper.h>
+
+/*
+ * sdlz helper methods
+ */
+
+/*%
+ * properly destroys a querylist by de-allocating the
+ * memory for each query segment, and then the list itself
+ */
+
+static void
+destroy_querylist(isc_mem_t *mctx, query_list_t **querylist)
+{
+ query_segment_t *tseg = NULL;
+ query_segment_t *nseg = NULL;
+
+ REQUIRE(mctx != NULL);
+
+ /* if query list is null, nothing to do */
+ if (*querylist == NULL)
+ return;
+
+ /* start at the top of the list */
+ nseg = ISC_LIST_HEAD(**querylist);
+ while (nseg != NULL) { /* loop, until end of list */
+ tseg = nseg;
+ /*
+ * free the query segment's text string but only if it
+ * was really a query segment, and not a pointer to
+ * %zone%, or %record%, or %client%
+ */
+ if (tseg->sql != NULL && tseg->direct == isc_boolean_true)
+ isc_mem_free(mctx, tseg->sql);
+ /* get the next query segment, before we destroy this one. */
+ nseg = ISC_LIST_NEXT(nseg, link);
+ /* deallocate this query segment. */
+ isc_mem_put(mctx, tseg, sizeof(query_segment_t));
+ }
+ /* deallocate the query segment list */
+ isc_mem_put(mctx, *querylist, sizeof(query_list_t));
+}
+
+/*% constructs a query list by parsing a string into query segments */
+static isc_result_t
+build_querylist(isc_mem_t *mctx, const char *query_str, char **zone,
+ char **record, char **client, query_list_t **querylist,
+ unsigned int flags)
+{
+ isc_result_t result;
+ isc_boolean_t foundzone = isc_boolean_false;
+ isc_boolean_t foundrecord = isc_boolean_false;
+ isc_boolean_t foundclient = isc_boolean_false;
+ char *temp_str = NULL;
+ char *right_str = NULL;
+ query_list_t *tql;
+ query_segment_t *tseg = NULL;
+
+ REQUIRE(querylist != NULL && *querylist == NULL);
+ REQUIRE(mctx != NULL);
+
+ /* if query string is null, or zero length */
+ if (query_str == NULL || strlen(query_str) < 1) {
+ if ((flags & SDLZH_REQUIRE_QUERY) == 0)
+ /* we don't need it were ok. */
+ return (ISC_R_SUCCESS);
+ else
+ /* we did need it, PROBLEM!!! */
+ return (ISC_R_FAILURE);
+ }
+
+ /* allocate memory for query list */
+ tql = isc_mem_get(mctx, sizeof(query_list_t));
+ /* couldn't allocate memory. Problem!! */
+ if (tql == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /* initialize the query segment list */
+ ISC_LIST_INIT(*tql);
+
+ /* make a copy of query_str so we can chop it up */
+ temp_str = right_str = isc_mem_strdup(mctx, query_str);
+ /* couldn't make a copy, problem!! */
+ if (right_str == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ /* loop through the string and chop it up */
+ while (right_str != NULL) {
+ /* allocate memory for tseg */
+ tseg = isc_mem_get(mctx, sizeof(query_segment_t));
+ if (tseg == NULL) { /* no memory, clean everything up. */
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ tseg->sql = NULL;
+ tseg->direct = isc_boolean_false;
+ /* initialize the query segment link */
+ ISC_LINK_INIT(tseg, link);
+ /* append the query segment to the list */
+ ISC_LIST_APPEND(*tql, tseg, link);
+
+ /*
+ * split string at the first "%". set query segment to
+ * left portion
+ */
+ tseg->sql = isc_mem_strdup(mctx,
+ isc_string_separate(&right_str,
+ "%"));
+ if (tseg->sql == NULL) {
+ /* no memory, clean everything up. */
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ /* tseg->sql points directly to a string. */
+ tseg->direct = isc_boolean_true;
+ tseg->strlen = strlen(tseg->sql);
+
+ /* check if we encountered "%zone%" token */
+ if (strcasecmp(tseg->sql, "zone") == 0) {
+ /*
+ * we don't really need, or want the "zone"
+ * text, so get rid of it.
+ */
+ isc_mem_free(mctx, tseg->sql);
+ /* set tseg->sql to in-direct zone string */
+ tseg->sql = (char**) zone;
+ tseg->strlen = 0;
+ /* tseg->sql points in-directly to a string */
+ tseg->direct = isc_boolean_false;
+ foundzone = isc_boolean_true;
+ /* check if we encountered "%record%" token */
+ } else if (strcasecmp(tseg->sql, "record") == 0) {
+ /*
+ * we don't really need, or want the "record"
+ * text, so get rid of it.
+ */
+ isc_mem_free(mctx, tseg->sql);
+ /* set tseg->sql to in-direct record string */
+ tseg->sql = (char**) record;
+ tseg->strlen = 0;
+ /* tseg->sql points in-directly poinsts to a string */
+ tseg->direct = isc_boolean_false;
+ foundrecord = isc_boolean_true;
+ /* check if we encountered "%client%" token */
+ } else if (strcasecmp(tseg->sql, "client") == 0) {
+ /*
+ * we don't really need, or want the "client"
+ * text, so get rid of it.
+ */
+ isc_mem_free(mctx, tseg->sql);
+ /* set tseg->sql to in-direct record string */
+ tseg->sql = (char**) client;
+ tseg->strlen = 0;
+ /* tseg->sql points in-directly poinsts to a string */
+ tseg->direct = isc_boolean_false;
+ foundclient = isc_boolean_true;
+ }
+ }
+
+ /* we don't need temp_str any more */
+ isc_mem_free(mctx, temp_str);
+ /*
+ * add checks later to verify zone and record are found if
+ * necessary.
+ */
+
+ /* if this query requires %client%, make sure we found it */
+ if (((flags & SDLZH_REQUIRE_CLIENT) != 0) && (!foundclient) ) {
+ /* Write error message to log */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Required token %%client%% not found.");
+ result = ISC_R_FAILURE;
+ goto flag_fail;
+ }
+
+ /* if this query requires %record%, make sure we found it */
+ if (((flags & SDLZH_REQUIRE_RECORD) != 0) && (!foundrecord) ) {
+ /* Write error message to log */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Required token %%record%% not found.");
+ result = ISC_R_FAILURE;
+ goto flag_fail;
+ }
+
+ /* if this query requires %zone%, make sure we found it */
+ if (((flags & SDLZH_REQUIRE_ZONE) != 0) && (!foundzone) ) {
+ /* Write error message to log */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Required token %%zone%% not found.");
+ result = ISC_R_FAILURE;
+ goto flag_fail;
+ }
+
+ /* pass back the query list */
+ *querylist = (query_list_t *) tql;
+
+ /* return success */
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ /* get rid of temp_str */
+ if (temp_str != NULL)
+ isc_mem_free(mctx, temp_str);
+
+ flag_fail:
+ /* get rid of what was build of the query list */
+ if (tql != NULL)
+ destroy_querylist(mctx, &tql);
+ return result;
+}
+
+/*%
+ * build a query string from query segments, and dynamic segments
+ * dynamic segments replace where the tokens %zone%, %record%, %client%
+ * used to be in our queries from named.conf
+ */
+char *
+sdlzh_build_querystring(isc_mem_t *mctx, query_list_t *querylist)
+{
+ query_segment_t *tseg = NULL;
+ unsigned int length = 0;
+ char *qs = NULL;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(querylist != NULL);
+
+ /* start at the top of the list */
+ tseg = ISC_LIST_HEAD(*querylist);
+ while (tseg != NULL) {
+ /*
+ * if this is a query segment, use the
+ * precalculated string length
+ */
+ if (tseg->direct == isc_boolean_true)
+ length += tseg->strlen;
+ else /* calculate string length for dynamic segments. */
+ length += strlen(* (char**) tseg->sql);
+ /* get the next segment */
+ tseg = ISC_LIST_NEXT(tseg, link);
+ }
+
+ /* allocate memory for the string */
+ qs = isc_mem_allocate(mctx, length + 1);
+ /* couldn't allocate memory, We need more ram! */
+ if (qs == NULL)
+ return NULL;
+
+ /* start at the top of the list again */
+ tseg = ISC_LIST_HEAD(*querylist);
+ /* copy the first item in the list to the query string */
+ if (tseg->direct == isc_boolean_true) /* query segment */
+ strcpy(qs, tseg->sql);
+ else
+ strcpy(qs, * (char**) tseg->sql); /* dynamic segment */
+
+ /* concatonate the rest of the segments */
+ while ((tseg = ISC_LIST_NEXT(tseg, link)) != NULL) {
+ if (tseg->direct == isc_boolean_true)
+ /* query segments */
+ strcat(qs, tseg->sql);
+ else
+ /* dynamic segments */
+ strcat(qs, * (char**) tseg->sql);
+ }
+
+ return qs;
+}
+
+/*% constructs a sql dbinstance (DBI) */
+isc_result_t
+sdlzh_build_sqldbinstance(isc_mem_t *mctx, const char *allnodes_str,
+ const char *allowxfr_str, const char *authority_str,
+ const char *findzone_str, const char *lookup_str,
+ const char *countzone_str, dbinstance_t **dbi)
+{
+
+ isc_result_t result;
+ dbinstance_t *db = NULL;
+
+ REQUIRE(dbi != NULL && *dbi == NULL);
+ REQUIRE(mctx != NULL);
+
+ /* allocate and zero memory for driver structure */
+ db = isc_mem_get(mctx, sizeof(dbinstance_t));
+ if (db == NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Could not allocate memory for "
+ "database instance object.");
+ return (ISC_R_NOMEMORY);
+ }
+ memset(db, 0, sizeof(dbinstance_t));
+ db->dbconn = NULL;
+ db->client = NULL;
+ db->record = NULL;
+ db->zone = NULL;
+ db->mctx = NULL;
+ db->query_buf = NULL;
+ db->allnodes_q = NULL;
+ db->allowxfr_q = NULL;
+ db->authority_q = NULL;
+ db->findzone_q = NULL;
+ db->countzone_q = NULL;
+ db->lookup_q = NULL;
+
+ /* attach to the memory context */
+ isc_mem_attach(mctx, &db->mctx);
+
+ /* initialize the reference count mutex */
+ result = isc_mutex_init(&db->instance_lock);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_mutex_init() failed: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ /* build the all nodes query list */
+ result = build_querylist(mctx, allnodes_str, &db->zone,
+ &db->record, &db->client,
+ &db->allnodes_q, SDLZH_REQUIRE_ZONE);
+ /* if unsuccessful, log err msg and cleanup */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Could not build all nodes query list");
+ goto cleanup;
+ }
+
+ /* build the allow zone transfer query list */
+ result = build_querylist(mctx, allowxfr_str, &db->zone,
+ &db->record, &db->client,
+ &db->allowxfr_q,
+ SDLZH_REQUIRE_ZONE | SDLZH_REQUIRE_CLIENT);
+ /* if unsuccessful, log err msg and cleanup */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Could not build allow xfr query list");
+ goto cleanup;
+ }
+
+ /* build the authority query, query list */
+ result = build_querylist(mctx, authority_str, &db->zone,
+ &db->record, &db->client,
+ &db->authority_q, SDLZH_REQUIRE_ZONE);
+ /* if unsuccessful, log err msg and cleanup */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Could not build authority query list");
+ goto cleanup;
+ }
+
+ /* build findzone query, query list */
+ result = build_querylist(mctx, findzone_str, &db->zone,
+ &db->record, &db->client,
+ &db->findzone_q, SDLZH_REQUIRE_ZONE);
+ /* if unsuccessful, log err msg and cleanup */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Could not build find zone query list");
+ goto cleanup;
+ }
+
+ /* build countzone query, query list */
+ result = build_querylist(mctx, countzone_str, &db->zone,
+ &db->record, &db->client,
+ &db->countzone_q, SDLZH_REQUIRE_ZONE);
+ /* if unsuccessful, log err msg and cleanup */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Could not build count zone query list");
+ goto cleanup;
+ }
+
+ /* build lookup query, query list */
+ result = build_querylist(mctx, lookup_str, &db->zone,
+ &db->record, &db->client,
+ &db->lookup_q, SDLZH_REQUIRE_RECORD);
+ /* if unsuccessful, log err msg and cleanup */
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "Could not build lookup query list");
+ goto cleanup;
+ }
+
+ /* pass back the db instance */
+ *dbi = (dbinstance_t *) db;
+
+ /* return success */
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ /* destroy whatever was build of the db instance */
+ destroy_sqldbinstance(db);
+ /* return failure */
+ return (ISC_R_FAILURE);
+}
+
+void
+sdlzh_destroy_sqldbinstance(dbinstance_t *dbi)
+{
+ isc_mem_t *mctx;
+
+ /* save mctx for later */
+ mctx = dbi->mctx;
+
+ /* destroy any query lists we created */
+ destroy_querylist(mctx, &dbi->allnodes_q);
+ destroy_querylist(mctx, &dbi->allowxfr_q);
+ destroy_querylist(mctx, &dbi->authority_q);
+ destroy_querylist(mctx, &dbi->findzone_q);
+ destroy_querylist(mctx, &dbi->countzone_q);
+ destroy_querylist(mctx, &dbi->lookup_q);
+
+ /* get rid of the mutex */
+ isc_mutex_destroy(&dbi->instance_lock);
+
+ /* return, and detach the memory */
+ isc_mem_put(mctx, dbi, sizeof(dbinstance_t));
+ isc_mem_detach(&mctx);
+}
+
+char *
+sdlzh_get_parameter_value(isc_mem_t *mctx, const char *input, const char* key)
+{
+ int keylen;
+ char *keystart;
+ char value[255];
+ int i;
+
+ if (key == NULL || input == NULL || strlen(input) < 1)
+ return NULL;
+
+ keylen = strlen(key);
+
+ if (keylen < 1)
+ return NULL;
+
+ keystart = strstr(input, key);
+
+ if (keystart == NULL)
+ return NULL;
+
+ REQUIRE(mctx != NULL);
+
+ for (i = 0; i < 255; i++) {
+ value[i] = keystart[keylen + i];
+ if (value[i] == ' ' || value[i] == '\0') {
+ value[i] = '\0';
+ break;
+ }
+ }
+
+ return isc_mem_strdup(mctx, value);
+}
+
+#endif
diff --git a/contrib/idn/idnkit-1.0-src/ChangeLog b/contrib/idn/idnkit-1.0-src/ChangeLog
new file mode 100644
index 0000000..085e3bd
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/ChangeLog
@@ -0,0 +1,856 @@
+2003-03-16
+ * idnkit 1.0 release.
+
+ * DISTFILES, README, README.ja, INSTALL, INSTALL.ja: delete BIND8,
+ Squid and libiconv patches.
+
+2003-03-13
+ * wsock/config/idnconf.tcl: change the version number to '1.0'.
+
+2003-03-12
+ * Makefile.in, lib/Makefile.in: Add 'make install-config' to
+ Makefile target.
+
+2003-03-11
+ * patch/bind9/bind-9.2.2-patch: created.
+
+2003-03-06
+ * lib/punycode.c: idn__punycode_encode() outputs an error message
+ if the input string is over PUNYCODE_MAXINPUT (the value is 3800).
+
+2003-03-05
+ * include/idn/api.h, include/idn/checker.h,
+ include/idn/nameprep.h, include/idn/res.h, include/idn/version.h,
+ lib/Makefile.in, lib/checker.c, lib/idn.conf.sample.in,
+ lib/mapper.c, lib/nameprep.c, lib/nameprepdata.c,
+ lib/normalizer.c, lib/tests/checker.tsy, lib/tests/mapper.tsy,
+ lib/tests/nameprep.tsy, lib/tests/normalizer.tsy,
+ man/idn.conf.5.in, tools/idnconv/idnconv.1, wsock/bin/idn.conf:
+ Add NAMEPREP version 'RFC3491', and remove 'nameprep-11'.
+
+2003-02-18
+ * lib/tests/api-init1.tsy, lib/tests/api-init2.tsy,
+ lib/tests/api-init3.tsy, lib/tests/api-init4-1.tsy,
+ lib/tests/api-init4-2.tsy, lib/tests/api-init4-3.tsy,
+ lib/tests/api-init5-1.tsy, lib/tests/api-init5-2.tsy,
+ lib/tests/api-init5-3.tsy, lib/tests/api.tsy, lib/tests/converter.tsy,
+ lib/tests/res.tsy, lib/tests/punycode.c: Change ACE prefix of Punycode
+ from `zq--' to `xn--'.
+
+2003-02-13
+ * lib/make.wnt: remove dependencies on obsolete files.
+
+ * INSTALL, INSTALL.ja, configure.in, aclocal.m4: Delete configure's
+ --with-punycode-prefix option.
+
+2003-02-05
+ * lib/res.c: improve performance when encoding/decoding
+ loooooooong domain names.
+
+2003-01-22
+ * lib/res.c: idn_res_encodename() and idn_res_decodename() in
+ libidnkit returns `idn_invalid_name' if local converter is not
+ available.
+
+2003-01-20
+ * lib/normalize.c, lib/unormalize.c, include/idn/unormalize.h,
+ lib/tests/normalizer.tsy: unicode-form-c or unicode-form-c/3.2.0 is
+ no longer supported.
+
+ * lib/mapselector.c, lib/tests/mapselector.tsy:
+ idn_mapselector_add() outputs an error message if invalid scheme
+ name or TLD is given.
+
+ * lib/checker.c, lib/normalizer.c, lib/mapselector.c, lib/res.c:
+ modify error messages.
+
+ * lib/result.c: modify an error message for `idn_invalid_length'.
+
+2003-01-16
+ * lib/checker.c, lib/idn.conf.sample.in, lib/mapper.c, lib/nameprep.c,
+ lib/normalizer.c, lib/unicode.c, lib/tests/checker.tsy,
+ lib/tests/mapper.tsy, lib/tests/nameprep.tsy, lib/tests/normalizer.tsy,
+ man/idn.conf.5.in, tools/idnconv/idnconv.1:
+ delete support for nameprep-03 and nameprep-09.
+
+ * lib/unicodedata_301.c, lib/unicodedata_310.c, DISTFILES:
+ unicodedata_301.c and unicodedata_310.c are removed.
+
+2003-01-14
+ * tools/idnconv/idnconv.c, tools/idnconv/util.c, tools/idnconv/util.h:
+ remove the restriction on the length of input lines. idnconv can
+ now handle very long lines.
+
+2003-01-10
+ * lib/converter.c: fix a bug in extending intermediate buffer
+ in converter_iconv_convtoucs4(), which causes incorrect
+ codeset conversion when the input string is very long.
+
+2002-12-06
+ * idnkit 1.0pr2 release (preview release).
+
+2002-12-03
+ * lib/mapper.c, lib/normalize.c: Don't check whether an input string
+ is STD3 ASCII label.
+ lib/res.c: Skip localmap if the string is STD3 ASCII label.
+
+2002-12-02
+ * lib/tests/iconvchk.c, lib/tests/Makefile.in: enable to check
+ whether codeset names "eucJP" and "SJIS" are available in iconv.
+
+2002-12-01
+ * tools/runidn/stub.c: use RTLD_NEXT for dlsym() if it is available.
+
+2002-11-29
+ * almost all files: change the license terms.
+
+2002-11-25
+ * lib/tests/codeset.h: define character encoding names here.
+ * lib/tests/api-init1.tsy, lib/tests/api-init2.tsy,
+ lib/tests/api-init3.tsy, lib/tests/api-init4-3.tsy,
+ lib/tests/api-init5-3.tsy, lib/tests/converter.tsy,
+ lib/tests/mapselector.tsy, lib/tests/resconf.tsy: include `codeset.h'.
+ lib/tests/api-init4-1.tsy, lib/tests/api-init4-2.tsy,
+ lib/tests/api-init5-1.tsy, lib/tests/api-init5-2.tsy,
+ lib/tests/mapselector.tsy, lib/tests/resconf.tsy:
+ Delete the unused cpp macro EUCJP_ENCODING_NAME.
+ * INSTALL, INSTALL.ja: describe `lib/tests/codeset.h'.
+
+ * lib/converter.c: Fix bugs in converter_uescape_convfromucs4()
+ and converter_uescape_convtoucs4() that libidnkit might crash
+ when `from' is very long.
+
+2002-11-15
+ * Makefile.in: `make distclean' also removes `libtool'.
+
+2002-10-25
+ * lib/resconf.c: enable the IDN_CONVERTER_RTCHECK flag when it
+ calls idn_converter_create().
+ * tools/idnconv/util.c: enable the IDN_CONVERTER_RTCHECK flag
+ when it calls idn_converter_setlocalconvertername() or
+ idn_converter_setidnconvertername().
+
+2002-09-20
+ * wsock/README.txt, wsock/README_j.txt: add description on
+ "Force local DLL reference" button.
+
+2002-09-19
+ * idnkit 1.0pr1 release (preview release).
+
+2002-09-13
+ * README, README.ja: update URIs.
+
+ * lib/Makefile.in, lib/tests/Makefile.in: generate libidntest and
+ libidntestlite for test programs.
+
+2002-09-09
+ * wsock/wsock11/dlldef.h, wsock/wsock11/dllfunc.c,
+ wsock/wsock11/dllload.c, wsock/wsock11/dllmain.c,
+ wsock/wsock20/dlldef.h, wsock/wsock20/dllfunc.c,
+ wsock/wsock20/dllload.c, wsock/wsock20/dllmain.c: take out
+ DLL load/unload from DllMain(). load/unload is delayed until
+ it is really necessary.
+ * wsock/common/checkdll.c, wsock/common/wrapcommon.h: move DLL
+ load/unload functions from wsock/{ws11,ws20}/dllmain.c.
+ * wsock/printf.c: make logging more effective.
+
+ * DISTFILES: remove wsock/common/dllmain.c, which is no longer used.
+
+2002-09-05
+ * lib/mapper.c: fix a bug that idn_mapper_add(ctx, "filemap") aborts.
+
+2002-09-04
+ * lib/nameprep.c: GCC says that a variable declared in
+ idn_nameprep_isvalidbidi() might be used uninitialized. Fixed.
+
+ * wsock/common/convert.c, wsock/common/printf.c,
+ wsock/common/wrapcommon.h: always reset log output callback procedure
+ before calling idnkit library functions.
+ * wsock/wsock11/dllmain.c, wsock/wsock20/dllmain.c: reset
+ log output callback before unloading.
+
+2002-09-03
+ * lib/tests/testygen, lib/tests/testsuite.c, lib/tests/testsuite.h:
+ add verbose and partial exec modes.
+
+2002-08-29
+ * idnkit 020829 snapshot release.
+
+2002-08-28
+ * lib/tests/testygen: fix generation of main(). It didn't destroy
+ a testsuite context.
+ * lib/tests/testsuite.c: fix a double free bug in
+ idn_testsuite_destroy().
+
+ * lib/filemapper.c: fix one memory leak in read_file().
+ * lib/filemapper.c: fix buffer expansion bug in ucsbuf_grow().
+ * lib/res.c: plug up memory leak in idn_res_decodename().
+
+ * lib/tests/setenv.c: fix memory leak bug.
+
+ * lib/filemapper.c, lib/ucsmap.c, lib/ucsset.c: fix misuse of
+ realloc().
+
+ * lib/converter.c: plug up memory leak in
+ converter_iconv_openfromucs4() and converter_iconv_opentoucs4().
+
+2002-08-27
+ * lib/tests/Makefile.in: support the case where the build directory
+ is different from the source directory.
+
+ * lib/tests/Makefile.in: perform tests for lite library only if
+ `--enable-liteonly' has been specified at configuration.
+
+ * lib/tests/setenv.c, lib/tests/setenv.h, lib/tests/Makefile.in,
+ configure.in: support systems which lack setenv() and/or unsetenv().
+
+ * configure.in, lib/Makefile.in, lib/idn.conf.sample, INSTALL,
+ INSTALL.ja: delete `--with-preference'.
+
+2002-08-26
+ * lib/tests/testygen: new option `-L', which suppresses `#line'
+ cpp lines on output.
+
+ * DISTFILES: Add files for tests.
+ * INSTALL, INSTALL.ja: add the `Test' section.
+
+ * lib/resconf.c: fix trace message of idn_resconf_create().
+
+ * win/README.WIN: update the contents.
+
+ * wsock/config/idnconf.tcl: do not display `force local DLL
+ reference' button on Windows 95 and NT, since it is meaningless
+ for these old OSes.
+
+2002-08-22
+ * lib/mapper.c, lib/normalizer.c: add the procedure for the case
+ that ctx->nschems is 0 to idn_mapper_map() and
+ idn_normalizer_normalize().
+
+ * lib/delimitermap.c: idn_delimitermap_add() and
+ idn_delimitermap_addall() reject a request to add an invalid
+ codepoint.
+
+2002-08-21
+ * lib/api.c: fix a bug that api_nameinit() didn't call
+ idn_resconf_initialize().
+ * lib/api.c: don't set the `ininitialized' flag if idn_nameinit()
+ returns with an error.
+ * lib/api.c, include/idn/api.h: add idn__setconffile().
+
+ * lib/mapselector.c: idn_mapselector_map() and idn_mapselector_map2()
+ now accept `tld' beginning with a dot.
+
+2002-08-20
+ * wsock/common/checkdll.c: back out 0812 change because the check
+ method doesn't seem to work correctly on WinMe.
+ * wsock/wsock11/dllload.c, wsock/wsock20/dllload.c: add some trace
+ statements.
+ * wsock/config/idnconf.tcl: do not install winsock2 wrapper on
+ Win98/Me.
+
+ * lib/tests/testsuite.c, lib/tests/testsuite.h, lib/tests/testygen:
+ exit the testcase if ASSERT fails.
+
+ * lib/tests/testsuite.c, lib/tests/testsuite.h:
+ replace ASSERT_PTRNOTNULL with ASSERT_PTR_NE.
+
+ * lib/tests/testutil.c, lib/testuil.h: new file.
+ It provides create_conf_file().
+
+2002-08-19
+ * lib/resconf.c: if application calls idn_resconf_create() before
+ idn_resconf_initialize(), idnkit returns `idn_failure'.
+
+2002-08-15
+ * lib/tests/testsuite.c, lib/tests/testsuite.h, lib/tests/testygen:
+ add two assertion macros: ASSERT_PTR and ASSERT_PTRNOTNULL.
+
+ * lib/converter.c: fix some warning messages.
+
+2002-08-14
+ * lib/resconf.c: fix a but that idnkit aborts if a line in config
+ file lacks an argument.
+
+ * wsock/common/hook.c, wsock/wsock11/dllfunc.c, wsock/wsock20/dllfunc.c
+ : make name resolver APIs return the domain name verbatim (instead
+ of returning error) when name decoding fails.
+
+2002-08-13
+ * lib/Makefile.in, lib/checker.c, lib/converter.c, lib/delimitermap.c,
+ lib/filechecker.c, lib/filemapper.c, lib/mapper.c, lib/mapselector.c,
+ lib/nameprep.c, lib/normalizer.c, lib/punycode.c, lib/race.c,
+ lib/resconf.c, lib/unormalize.c: delete main routines for test.
+
+ * lib/tests/: new directory.
+ * configure.in: Check for path of perl command.
+
+ * wsock/config/idnconf.tcl: correct OS version check routine.
+
+2002-08-12
+ * lib/make.wnt: change amcacez.* to punycode.*.
+ * wsock/common/encoding.c, wsock/common/dump.c, wsock/common/convert.c,
+ wsock/commn/hook.c, wsock/common/printf.c, wsock/common/wrapcommon.h,
+ wsock/wsock11/dllfunc.c, wsock/wsock11/dllload.c,
+ wsock/wsock20/dllfunc.c, wsock/wsock20/dllload.c: add extra argument
+ (specifying buffer length) to some interface functions, in order to
+ prevent possible buffer overflow.
+ * wsock/common/printf.c: increase message buffer size.
+ * wsock/wsock11/dllmain.c, wsock/wsock20/dllmain.c: call initialize
+ routine before first log output.
+ * wsock/common/checkdll.c: use light-weight DLL checking using
+ LoadLibraryEx.
+
+ * lib/res.c: fix bugs in idn_res_encodename(), idn_res_decodename()
+ and idn_res_decodename2(). They fell into infinite loops when
+ given `tolen' is 0.
+
+2002-08-08
+ * lib/resconf.c, lib/res.c: remove unused functions and variables.
+
+ * lib/Makefile.in tools/idnconv/Makefile.in,
+ tools/runidn/Makefile.in: add @CPPFLAGS@ to $(CFLAGS).
+
+ * lib/res.c: idn_res_decodename2() copies `from' to `to' and
+ returns immediately when the `actions' argument is 0.
+
+2002-08-07
+ * lib/resconf.c: fix a bug in parse_conf() that if `nameprep' or
+ `idn-encoding' directive is defined twice, default value is set
+ to the directive.
+ * lib/resconf.c: cosmetic changes.
+ delete parse_map(), parse_normalize(), parse_prohibit(),
+ parse_unassigned() and parse_bidi().
+
+ * lib/amcacez.c, include/idn/amcacez.h: renamed to lib/punycode.c
+ and include/idn/punycode.h.
+
+ * include/idn/converter.h, lib/converter.h: define
+ idn_converter_getrealname() externally instead of statically
+ defined get_realname().
+
+2002-08-06
+ * lib/resconf.c: arrange processes of obsolete commands in
+ idn_res_loadfile().
+
+ * INSTALL, INSTALL.ja, man/idn.conf.5.in, tools/idnconv/idnconv.1:
+ remove description of RACE and AMC-ACE-Z.
+
+ * lib/resconf.c: fix a bug in handling of local-converter.
+
+ * lib/converter.c: add initialization check in
+ idn_converter_aliasfile() and idn_converter_resetalias().
+
+ * lib/converter.c: free context memory at some right places in
+ idn_converter_create().
+
+2002-08-05
+ * configure.in, lib/Makefile.in, lib/aliaslist.sh: also add the
+ "UTF-8" entry if --with-utf8=NAME option of configure is specified,
+ and NAME is not "UTF-8".
+
+ * tools/idnconv/idnconv.c: call idn_converter_destroy() after
+ idn_resconf_getidnconverter() and idn_resconf_getlocalconverter()
+ in main().
+
+ * lib/res.c: fix a bug in idn_res_decodename2().
+ When the function called idn_res_decodename(), assertion check in
+ idn_res_decodename() may have failed.
+
+ * lib/res.c: call idn_delimitermap_destroy() after
+ idn_resconf_getdelimitermap() in idn_res_encodename() and
+ idn_res_decodename().
+
+2002-08-02
+ * lib/res.c: fix mismatched pointer type in idn_res_decodename2().
+ * lib/res.c: fix a bug in handling of `auxencoding', in
+ idn_res_decodename2().
+
+2002-08-01
+ * lib/resconf.c: fix two memory leaks in parse_conf().
+
+ * lib/aliaslist.c: fix an error of size measurement in
+ create_item().
+
+2002-07-31
+ * lib/converter.c: AMC-ACE-Z and RACE are now extra ACE.
+
+2002-07-30
+ * idnkit 020730 snapshot release.
+
+ * lib/resconf.c: fix a bug in idn_resconf_create() that it
+ misses initializing `ctx->bidi_checker'.
+
+2002-07-29
+ * tools/idnconv/idnconv.1: describe bidi character check.
+
+2002-07-24
+ * lib/resconf.c: force to add bidi checker at parsing nameprep
+ entry in config file.
+
+2002-07-19
+ * include/idn/checker.h, include/idn/nameprep.h,
+ include/idn/res.h, include/idn/resconf.h, man/idn.conf.5.in,
+ man/libidnkit.3.in, lib/checker.c, lib/nameprep.c, lib/res.c,
+ lib/resconf.c, tools/idnconv/idnconv.c: add bidirectional label
+ check routine.
+
+ * include/idn/api.h, include/idn/res.h, lib/api.c, lib/res.c,
+ tools/idnconv/idnconv.c, tools/idnconv/util.c,
+ tools/idnconv/util.h: change the type of action flag at conversion
+ functions and define it as ``idn_action_t''.
+
+2002-07-18
+ * wsock/config/idnconf.tcl: implement .exe.local file
+ creation/deletion feature.
+ * lib/make.wnt: update list of files according to the recent
+ changes of the library.
+
+2002-07-12
+ * include/idn/nameprpe.h: define idn_biditype_t.
+ * lib/nameprep_template.c, lib/nameprep.c: support for bidi type
+ check is added.
+
+2002-07-11
+ * idnkit 020711 snapshot release.
+
+2002-07-09
+ * man/Makefile.in, man/idn.conf.5.in: force to make and install
+ manpage of idnalias.conf (merely a copy of idn.conf's manpage).
+
+2002-07-08
+ * DISTFILES: `lib/dude.c' and `include/idn/dude.h' are removed.
+ * DISTFILES: `util/Makefile' is added.
+
+ * tools/idnconv/idnconv.c: fix typo in decode_file().
+
+ * tools/idnconv/idnconv.c: Support "-reverse -out ACE".
+
+ * lib/res.c: fix bugs in label_idndecode() and label_idnencode_ace().
+ If UCS4 to UTF-8 conversion is failed with idn_buffer_overflow,
+ we must extends the size of local buffer and try the conversion
+ again.
+
+2002-07-05
+ * tools/idnconv/idnconv.c: treat input as the string of the local
+ encoding specified by "-out" option at reverse conversion.
+
+ * include/idn/api.h, lib/api.c: add idn_decodename2() function.
+
+ * include/idn/res.h, lib/res.c: add idn_res_decodename2()
+ function.
+
+ * include/idn/res.h, lib/res.c: restore IDN_DELIMMAP flag.
+
+2002-07-02
+ * lib/unicodedata_320.c, lib/checker.c, lib/idn.conf.sample.in,
+ lib/mapper.c, lib/nameprep.c, lib/nameprepdata.c, lib/normalizer.c,
+ lib/unicode.c, unicodedata_320.c, include/idn/nameprep.c, DISTFILES,
+ man/idn.conf.5.in: Support NAMEPREP-11 which adopts Unicode-3.2.
+ Support for NAMEPREP-06, -08, -09 are removed.
+
+2002-07-01
+ * tools/idnconv/idnconv.1: added `-A' option.
+
+ * include/idn/res.h, lib/res.c: redefine IDN_ENCODE_QUERY,
+ IDN_DECODE_QUERY, IDN_ENCODE_STORED, IDN_DECODE_STORED, IDN_ENCODE_APP
+ and IDN_DECODE_APP.
+
+2002-06-26
+ * lib/resconf.c, include/idn/resconf.h: define
+ idn_resconf_getauxidnconverter(), idn_resconf_setauxidnconverter()
+ and idn_resconf_setauxidnconvertername().
+
+2002-06-20
+ * lib/res.c: use action flags at round trip check.
+
+2002-06-19
+ * include/idn/res.h, lib/res.c: remove IDN_UNASCHECK flag from
+ IDN_NAMEPREP.
+
+ * include/idn/res.h, lib/res.c: add IDN_ENCODE_QUERY,
+ IDN_DECODE_QUERY, IDN_ENCODE_STORED, and IDN_DECODE_STORED flags.
+
+ * include/idn/res.h, lib/res.c: IDN_ENCODE_APP and IDN_DECODE_APP
+ have same value as flags for conversion of the query string
+ (IDN_ENCODE_QUERY and IDN_DECODE_QUERY) now.
+
+2002-06-17
+ * include/idn/Makefile.in, lib/Makefile.in, lib/converter.c,
+ tools/runidn/Makefile.in, configure, INSTALL, INSTALL.ja:
+ delete DUDE support.
+ * include/idn/dude.h, lib/dude.c: deleted.
+
+ * README, README.ja: update URL of mdnkit FAQ.
+
+ * include/idn/res.h, lib/res.c, lib/idn.conf.sample.in,
+ lib/delimitermap.c, man/libidnkit.3.in: add default delimiters
+ defined in IDNA specification and always forced to do delimiter
+ mapping.
+
+ * lib/resconf.c, man/idn.conf.5.in: remove "delimiter-map" entry
+ support of configuration file.
+
+ * tools/idnconv/idnconv.c, tools/idnconv/idnconv.1: remove
+ "-delimiter-map" and "-d" options.
+
+2002-06-13
+ * wsock/common/encoding.c: fix registry key setting so that
+ it matches what documents say.
+
+2002-06-11
+ * include/idn/delimitermap.h: remove idn_delimitermap_fix()
+ declaration.
+
+2002-06-10
+ * wsock/wsock2/dllfunc.c: fix a bug which makes wrapping of
+ getaddrinfo()/getnameinfo() always fail.
+
+2002-06-05
+ * wsock/wsock2/dllfunc.c, wsock/wsock2/dllstub.c,
+ wsock/wsock2/ws2_32.def: add new APIs introduced by WinXP.
+
+2002-05-22
+ * tools/idnconv/util.c: reset alias information before loading
+ alias information file.
+
+2002-05-20
+ * idnkit 1.0rc1 release.
+
+ * include/idn/res.h: fix typo in a comment.
+
+2002-05-17
+ * include/idn/version.h: set IDNKIT_VERSION to "1.0rc1".
+
+2002-05-13
+ * tools/rpm/mdnkit.spec: renamed to idnkit.spec, and revised
+ for idnkit-1.0.
+
+2002-05-09
+ * tools/idnconv/idnconv.c: now `idnconv -r' can convert a file
+ from ACE to ACE.
+
+2002-05-08
+ * lib/idn.conf.sample.in: delete "encoding-alias-file" entry
+ because idnkit does not support it any longer.
+
+ * lib/nameprepdata.c lib/nameprep.c, lib/mapper.c, lib/normalizer.c,
+ lib/checker.c, lib/idn.conf.sample.in, man/idn.conf.5.in,
+ tools/idnconv/idnconv.1: support NAMEPREP-09.
+
+ * lib/mapper.c, lib/normalizer.c, lib/checker.c, lib/mapselector.c,
+ * lib/res.c, lib/race.c: spmplify local buffer managements.
+
+ * tools/idnconv/idnconv.c, tools/idnconv/util.c, tools/idnconv/util.h:
+ fix a bug that wrong local encoding is set to a resconf context.
+
+2002-05-07
+ * tools/idnconv/util.c: delete set_reverse_context().
+ * tools/idnconv/idnconv.c: fix a serious bug in -reverse conversion.
+
+2002-05-04
+ * include/idn/util.h, lib/converter.c, lib/resconf.c, lib/util.c:
+ simplify Windows registry retrieval function interface.
+ * wsock/common/convert.c, wsock/common/dump.c,
+ wsock/common/encoding.c, wsock/common/wrapcommon.h: fix type
+ conflicts.
+ * wsock/wsock11/dlldef.h, wsock/wsock11/dllmain.c,
+ wsock/wsock20/dlldef.h, wsock/wsock20/dllmain.c: fix typo.
+ * wsock/common/jpnicmdn.def, wsock/common/jpnicmdn.h,
+ wsock/config/mdnconf.tcl: removed.
+ * DISTFILES: add new files, remove obsolete files.
+
+2002-05-02
+ * tools/idnconv/util.c: create a new function set_reverse_context().
+ * tools/idnconv/idnconv.c: fix a bug in handing of reference count
+ of idn_resconf_t contexts.
+
+ * lib/amcacez.c, lib/race.c, lib/dude.c, lib/delimitermap.c,
+ lib/checker.c, lib/mapper.c, lib/mapselector.c, lib/converter.c,
+ lib/normalizer.c, lib/res.c, lib/ucs4.c, lib/debug.c,
+ include/idn/debug.h: output valuable trace logs for developpers.
+
+ * lib/res.c: fix double free bugs.
+
+ * lib/checker.c, include/idn/checker.h: for symbols of the checker
+ module, use `idn_' prefix instead of `idn__' by default.
+
+ * wsock/common/checkdll.c, wsock/common/convert.c,
+ wsock/common/dump.c, wsock/common/encoding.c, wsock/common/hook.c,
+ wsock/common/printf.c, wsock/common/make.wnt,
+ wsock/wsock11/dlldef.h, wsock/wsock11/dllfunc.c,
+ wsock/wsock11/dllload.c , wsock/wsock11/dllmain.c,
+ wsock/wsock11/dllstub.c, wsock/wsock11/make.wnt,
+ wsock/wsock20/dlldef.h, wsock/wsock20/dllfunc.c,
+ wsock/wsock20/dllload.c , wsock/wsock20/dllmain.c,
+ wsock/wsock20/dllstub.c, wsock/wsock20/make.wnt: adapt idnkit
+ interface, change name from `mDN Wrapper' to `idn wrapper'.
+ * wsock/common/wrapcommon.h: created.
+ * wsock/config/idnconf.tcl: created.
+
+2002-05-01
+ * include/idn/util.h, lib/converter.c, lib/resonf.c, lib/util.c:
+ Move alias information initialization scheme from the resconf
+ context initialization to the converter module initialization.
+
+ * tools/idnconv/idnconv.c: fix a bug in main().
+ Wrong localconverer/idnconverter may be set to resconf2.
+
+2002-04-30
+ * lib/res.c, tools/idnconv/idnconv.c: accept non-ace encoding as
+ idn-encoding and ace encoding as local-encoding at normal conversion.
+
+2002-04-23
+ * man/idn.conf.5.in: use the term "unassigned codepoint", not
+ "unassigned character".
+
+2002-04-19
+ * include/idn/api.h, include/idn/res.h:
+ delete cpp macros for backward compatibility, since they are defined
+ in include/mdn/api.h and include/mdn/res.h.
+
+ * include/idn/checker.h, include/idn/converter.h,
+ include/idn/delimitermap.h, include/idn/filechecker.h,
+ include/idn/filemapper.h, include/idn/mapper.h,
+ include/idn/mapselector.h, include/idn/nameprep.h,
+ include/idn/normalizer.h, include/idn/unormalize.h:
+ fix obsolete descriptions.
+
+2002-04-17
+ * idnkit 1.0beta2 release.
+
+2002-04-16
+ * configure.in: check AC_FIND_SYSTEM_SHOBJ(libnsl),
+ AC_CHECK_LIB(socket, socket) and AC_CHECK_LIB(nsl, inet_addr)
+ in case of --enable-runidn.
+
+2002-04-15
+ * tools/idnconv/idnconv.1: fix the "REVERSE CONVERSION MECHANISM"
+ section.
+
+2002-04-12
+ * lib/res.c, include/idn/res.h: rename `idn_res_actionstostring()'
+ to `idn__res_actionstostring()'.
+ * lib/mapper.c, lib/checker.c, lib/converter.c: output trace log
+ which shows scheme a name the module is going to perform.
+
+2002-04-10
+ * man/idn.conf.5.in: delete the "SETFILE SECTION".
+
+2002-04-09
+ * tools/runidn/resolver.c: call idn_nameinit() and then call
+ idn_encodename() or idn_decodename().
+
+2002-04-08
+ * include/idn/export.h: created.
+ * include/idn/Makefile.h, DISTFILES: add export.h.
+ * include/idn/api.h, include/idn/converter.h, include/idn/debug.h,
+ include/idn/delimitermap.h, include/idn/localencoding.h,
+ include/idn/log.h, include/idn/mapper.h, include/idn/mapselector.h,
+ include/idn/nameprep.h, include/idn/normalizer.h, include/idn/res.h,
+ include/idn/resconf.h, include/idn/result.h, include/idn/ucs4.h,
+ include/idn/ucsmap.h, include/idn/ucsset.h, include/idn/unormalize.h,
+ include/idn/utf8.h, include/idn/version.h: include export.h. mark
+ exportable functions with IDN_EXPORT macro.
+ * lib/make.wnt: modify to create DLLs.
+ * configure.in: add existance check for pwd.h.
+ * configure, include/config.h.in: rebuilt.
+ * lib/resconf.c, lib/localencoding.c: port to Win32.
+ * include/mdn/version.h: include <idn/version.h> for the declaration
+ of idn_version_getstring().
+ * tools/make.wnt, tools/idnconv/make.wnt: created.
+ * make.wnt: add tools subdirectory.
+ * DISTFILES: add tools/make.wnt and tools/idnconv/make.wnt.
+
+ * include/idn/mapselector.h, lib/mapselector.c:
+ add idn_mapselector_getnotld() and idn_mapselector_getdefaulttld().
+ Instead delete idn_mapselector_no_tld and idn_mapselector_default.
+
+ * lib/api.c, include/mdn/api.h: define mdn_nameinit(),
+ mdn_encodename() and mdn_decodename().
+
+ * DISTFILES: delete `patch/bind8/bind-8.2.3-patch' and
+ `tools/rpm/mdnsproxy.init'.
+
+ * include/idn/aliaslist.h, include/idn/converter.h,
+ lib/aliaslist.c, lib/converter.c: enable to add an alias
+ information item to either top or bottom of the alias information
+ list.
+
+2002-04-05
+ * include/idn/resconf.h, lib/resconf.c: add
+ idn_resconf_setdefaults().
+ * lib/resconf.c: call idn_converter_aliasfile() at parsing the
+ default alias information file automatically.
+ * include/idn/api.h, lib/api.c: modify api_nameinit() to enable to
+ choose initialization scheme.
+
+ * tools/idnconv/idnconv.c, tools/idnconv/idnconv.1: delete `-map',
+ `-normalize', `-prohibit' and `-unassigned' options.
+ * tools/idnconv/idnconv.c: use default configuration if `-noconf'
+ is specified.
+
+2002-04-04
+ * tools/idnconv/idnconv.1: fix obsolete description.
+ * tools/runidn/runidn.1: likewise.
+
+2002-04-02
+ * configure.in: add --enable-mdnkit-compat option.
+ * include/mdn/Makefile.in, include/mdn/api.h,
+ include/mdn/localencoding.h, include/mdn/log.h, include/mdn/res.h,
+ include/mdn/resconf.h, include/mdn/result.h, include/mdn/utf8.h,
+ include/mdn/version.h: re-added.
+ * include/Makefile.in: add `idn' to SUBDIRS.
+ * lib/Makefile.in, tools/idnconv/Makefile.in, tools/runidn/Makefile.in,
+ man/Makefile.in: support --enable-mdnkit-compat.
+ * lib/localencoding.c, lib/resconf.c: ditto.
+ * INSTALL: ditto.
+
+ * Makefile.in, include/Makefile.in, include/idn/Makefile.in,
+ include/mdn/Makefile, lib/Makefile.in, tools/Makefile.in,
+ tools/idnconv/Makefile.in, tools/runidn/Makefile.in,
+ man/Makefile.in, map/Makefile.in: support DESTDIR and distclean.
+
+2002-03-28
+ * include/idn/api.h: enclose the contents with `extern "C" {...}'
+ if C++ compiler is used.
+
+2002-03-27
+ * man/Makefile.in: generate and install idnrc.5.
+ * man/idn.conf.5.in: describe the user configuration file ~/.idnrc.
+
+ * tools/idnconv/idnconv.1: add missing description of -nolengthcheck,
+ -noasciicheck and -noroundtrip options.
+
+ * lib/checker.c, lib/mapper.c, lib/normalizer.c,
+ lib/idn.conf.sample.in, tools/idnconv/idnconv.1, man/idn.conf.5.in:
+ Add nameprep-08 support, and delete -05 and -07 instead.
+
+2002-03-26
+ * idnkit 1.0beta1 release.
+
+ * NEWS: add description about Major changes in mDNkit 2.3, 2.3.1,
+ 2.4.
+ * NEWS: add description about Major changes in idnkit
+ version1.0beta1.
+
+2002-03-25
+ * DISTFILES: add bind-8.3.1-patch and bind-9.2.0-patch.
+ delete bind-9.1.3-patch.
+
+2002-03-22
+ * lib/mapselector.c: fix a bug in handling of the special TLD `-'.
+
+2002-03-20
+ * lib/converter.c: fix a bug in idn_converter_convtoucs4().
+
+ * lib/res.c: fix a bug that IDN_LENCHECK overlook an empty label
+ generated by nameprep-map or localmap (e.g. "XXX.\u{200b}").
+ * lib/res.c: fix a bug that libidnkit aborts when it decodes "."
+
+ * lib/Makefile.in, tools/runidn/Makefile.in: change library
+ version.
+ * include/idn/version.h: set version `1.0beta1'.
+
+ * configure, configure.in: modify some error messages.
+
+2002-03-19
+ * man/idn.conf.5.in, lib/idn.conf.sample.in, tools/idnconv/idnconv.1:
+ delete DUDE from a list of supported encodings.
+
+ * lib/aliaslist.c, lib/debug.c, lib/strhash.c, lib/ucs4.c: they are
+ private modules.
+
+ * include/idn/resolver.h: moved to tools/runidn/resolver.h.
+
+ * tools/runidn/Makefile.in, tools/idnconv/Makefile.in:
+ insert `-I$(srcdir)' into INCS.
+
+2002-03-18
+ * aclocal.m4, configure, configure.in, include/config.h.in,
+ Makefile.in, map/Makefile.in, src/lib/idn.conf.sample.in,
+ tools/idnconv/selectiveencode.h: replace `MDN' with `IDN'.
+
+ * lib/aliaslist.c: change WARNING message into INFO message when
+ idn_aliaslist_aliasfile() finds an error in alias information
+ file.
+ * lib/resconf.c: change user configuration file name.
+ * lib/resconf.c: add procedure to check the existence of default
+ alias information file before letting converter parse the file.
+ * lib/resconf.c: call idn_converter_aliasfile() even when basic
+ configuration files are not found at all.
+
+ * tools/idnconv/idnconv.c: use hexadecimal numbers for values
+ associated with FLAGS_ macros.
+
+ * include/idn/result.h, lib/result.c: rename `idn_too_long' to
+ `idn_invalid_length'.
+ * lib/res.c: In IDN_LENCHECK, return `idn_invalid_length' for an
+ empty label, but return `idn_success'' for the "." domain name.
+
+ * lib/converter.c: DUDE is now extra ACE.
+
+ * lib/mapselector.c, include/idn/mapselector.h: change types of
+ `idn_mapselector_no_tld' and `idn_mapselector_default' from
+ (const unsigned long []) to (const unsigned long *).
+
+ * DISTFILES: syncronize current source structure.
+
+2002-03-14
+ * configure, configure.in, include/config.h.in: add
+ `--enable-runidn' option to configure script. Unless the value
+ for this option is set to `yes', runidn command will not be
+ complied and installed.
+
+2002-03-13
+ * man/libidnkit.3.in: describe new idnkit API.
+ * man/idn.conf.5.in: use the term `internationalized' rather than
+ `multilingual'.
+ * lib/Makefile.in: create idnalias.conf.sample correctly even if
+ the object directory is different from the source directory.
+
+2002-03-12
+ * configure, configure.in, lib/Makefile.in: add
+ `--enable-liteonly' option to configure script and change
+ description of lib/Makefile.in for designating compilation and
+ installation of libidnkitlite alone.
+
+2002-03-08
+ * mDNkit is now renamed to idnkit. Also files, directories,
+ commands and function names are renamed (e.g. mdnconv -> idnconv).
+
+2002-03-07
+ * include/mdn/nameprep.h, lib/nameprep.c, lib/resconf.c: enable
+ libmdn(lite) to run without configuration file and alias file, and
+ also enable to support user configuration file.
+
+2002-03-05
+ * include/mdn/aliaslist.h, lib/aliaslist.c: change year
+ description to `2002' in copyright notice.
+ * lib/aliaslist.c: fix the initialization scheme of structure's
+ members at creation of both list item and list itself.
+ * lib/aliaslist.c: fix the order of function free() call when
+ an error occurs at list item creation.
+ * make.wnt: remove descriptions related to mdnsproxy.
+
+2002-03-04
+ * include/mdn/aliaslist.h, include/mdn/amcacez.h, include/mdn/assert.h,
+ include/mdn/checker.h, include/mdn/converter.h, include/mdn/debug.h,
+ include/mdn/delimitermap.h, include/mdn/dude.h,
+ include/mdn/filechecker.h, include/mdn/filemapper.h,
+ include/mdn/localencoding.h, include/mdn/log.h, include/mdn/logmacro.h,
+ include/mdn/mapper.h, include/mdn/mapselector.h,
+ include/mdn/nameprep.h, include/mdn/normalizer.h, include/mdn/race.h,
+ include/mdn/res.h, include/mdn/resconf.h, include/mdn/resolver.h,
+ include/mdn/result.h, include/mdn/strhash.h, include/mdn/ucs4.h,
+ include/mdn/ucsmap.h, include/mdn/ucsset.h, include/mdn/unicode.h,
+ include/mdn/unormalize.h, include/mdn/utf8.h, include/mdn/util.h,
+ include/mdn/version.h: enclose the contents with `extern "C" {...}'
+ if C++ compiler is used.
+ * DISTFILES, Makefile.in, configure, configure.in:
+ remove descriptions related to mdnsproxy.
+
+2002-03-01
+ * include/mdn/result.h, lib/result.h: define new error code
+ `mdn_too_long'.
+ * lib/res.c: return `mdn_too_long' if MDN_LENCHECK is failed.
diff --git a/contrib/idn/idnkit-1.0-src/DISTFILES b/contrib/idn/idnkit-1.0-src/DISTFILES
new file mode 100644
index 0000000..f0bc02e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/DISTFILES
@@ -0,0 +1,191 @@
+# $Id: DISTFILES,v 1.1.1.1 2003/06/04 00:25:02 marka Exp $
+README
+README.ja
+INSTALL
+INSTALL.ja
+ChangeLog
+DISTFILES
+LICENSE.txt
+Makefile.in
+NEWS
+make.wnt
+acconfig.h
+aclocal.m4
+config.guess
+config.sub
+ltconfig
+ltmain.sh
+configure.in
+configure
+install-sh
+mkinstalldirs
+include/Makefile.in
+include/config.h.in
+include/config.h.win
+include/idn/Makefile.in
+include/idn/aliaslist.h
+include/idn/api.h
+include/idn/assert.h
+include/idn/checker.h
+include/idn/converter.h
+include/idn/debug.h
+include/idn/delimitermap.h
+include/idn/export.h
+include/idn/filechecker.h
+include/idn/filemapper.h
+include/idn/localencoding.h
+include/idn/log.h
+include/idn/logmacro.h
+include/idn/mapper.h
+include/idn/mapselector.h
+include/idn/nameprep.h
+include/idn/normalizer.h
+include/idn/punycode.h
+include/idn/race.h
+include/idn/res.h
+include/idn/resconf.h
+include/idn/result.h
+include/idn/strhash.h
+include/idn/ucs4.h
+include/idn/ucsmap.h
+include/idn/ucsset.h
+include/idn/unicode.h
+include/idn/unormalize.h
+include/idn/utf8.h
+include/idn/util.h
+include/idn/version.h
+include/mdn/Makefile.in
+include/mdn/api.h
+include/mdn/localencoding.h
+include/mdn/log.h
+include/mdn/res.h
+include/mdn/resconf.h
+include/mdn/result.h
+include/mdn/utf8.h
+include/mdn/version.h
+lib/Makefile.in
+lib/aliaslist.c
+lib/api.c
+lib/checker.c
+lib/converter.c
+lib/debug.c
+lib/delimitermap.c
+lib/filechecker.c
+lib/filemapper.c
+lib/localencoding.c
+lib/log.c
+lib/make.wnt
+lib/mapper.c
+lib/mapselector.c
+lib/nameprep.c
+lib/nameprep_template.c
+lib/nameprepdata.c
+lib/normalizer.c
+lib/punycode.c
+lib/race.c
+lib/res.c
+lib/resconf.c
+lib/result.c
+lib/strhash.c
+lib/ucs4.c
+lib/ucsmap.c
+lib/ucsset.c
+lib/unicode.c
+lib/unicode_template.c
+lib/unicodedata_320.c
+lib/unormalize.c
+lib/utf8.c
+lib/util.c
+lib/version.c
+lib/idn.conf.sample.in
+lib/aliaslist.sh
+lib/tests/Makefile.in
+lib/tests/api-init1.tsy
+lib/tests/api-init2.tsy
+lib/tests/api-init3.tsy
+lib/tests/api-init4-1.tsy
+lib/tests/api-init4-2.tsy
+lib/tests/api-init4-3.tsy
+lib/tests/api-init5-1.tsy
+lib/tests/api-init5-2.tsy
+lib/tests/api-init5-3.tsy
+lib/tests/api.tsy
+lib/tests/checker.tsy
+lib/tests/codeset.h
+lib/tests/converter.tsy
+lib/tests/delimitermap.tsy
+lib/tests/iconvchk.c
+lib/tests/mapper.tsy
+lib/tests/mapselector.tsy
+lib/tests/nameprep.tsy
+lib/tests/normalizer.tsy
+lib/tests/res.tsy
+lib/tests/resconf.tsy
+lib/tests/setenv.c
+lib/tests/setenv.h
+lib/tests/testsuite.c
+lib/tests/testsuite.h
+lib/tests/testutil.c
+lib/tests/testutil.h
+lib/tests/testygen
+lib/tests/ucs4.tsy
+lib/tests/utffilter
+tools/Makefile.in
+tools/idnconv/Makefile.in
+tools/idnconv/make.wnt
+tools/idnconv/idnconv.c
+tools/idnconv/selectiveencode.c
+tools/idnconv/selectiveencode.h
+tools/idnconv/util.c
+tools/idnconv/util.h
+tools/idnconv/idnconv.1
+tools/idnconv/idnslookup.in
+tools/make.wnt
+tools/rpm/idnkit.spec
+tools/runidn/Makefile.in
+tools/runidn/resolver.c
+tools/runidn/resolver.h
+tools/runidn/stub.c
+tools/runidn/stub.h
+tools/runidn/runidn.1
+tools/runidn/runidn.in
+man/Makefile.in
+man/libidnkit.3.in
+man/idn.conf.5.in
+patch/bind9/bind-9.2.1-patch
+patch/bind9/bind-9.2.2-patch
+win/README.WIN
+wsock/README.txt
+wsock/README_j.txt
+wsock/make.wnt
+wsock/common/checkdll.c
+wsock/common/convert.c
+wsock/common/dump.c
+wsock/common/encoding.c
+wsock/common/hook.c
+wsock/common/make.wnt
+wsock/common/printf.c
+wsock/common/wrapcommon.h
+wsock/config/make.wnt
+wsock/config/idnconf.tcl
+wsock/wsock11/dlldef.h
+wsock/wsock11/dllfunc.c
+wsock/wsock11/dllload.c
+wsock/wsock11/dllmain.c
+wsock/wsock11/dllstub.c
+wsock/wsock11/make.wnt
+wsock/wsock11/wsock32.def
+wsock/wsock20/dlldef.h
+wsock/wsock20/dllfunc.c
+wsock/wsock20/dllload.c
+wsock/wsock20/dllmain.c
+wsock/wsock20/dllstub.c
+wsock/wsock20/make.wnt
+wsock/wsock20/ws2_32.def
+util/Makefile
+util/SparseMap.pm
+util/UCD.pm
+util/generate_nameprep_data.pl
+util/generate_normalize_data.pl
+map/Makefile.in
+map/jp.map
diff --git a/contrib/idn/idnkit-1.0-src/INSTALL b/contrib/idn/idnkit-1.0-src/INSTALL
new file mode 100644
index 0000000..6257f65
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/INSTALL
@@ -0,0 +1,309 @@
+
+ idnkit
+ Compilation and Installation
+ Japan Network Information Center (JPNIC)
+
+
+This file explains how to compile and install the source package.
+These procedures take the following steps:
+
+ + Prerequisite: making iconv() available
+ + System Configuration: running `configure' script
+ + Compilation: running `make'
+ + Test: running `make test' (optional)
+ + Installation: running `make install'
+ + Site Configuration: tailoring `idn.conf'
+ + Configuration Check (optional)
+ + Clean up (optional)
+
+See also the following section if you'd like to apply patch and install
+BIND9.
+
+ + Applying patches
+
+0. Prerequisite
+
+If you want to install generic idnkit library with code conversion
+support, and also if your system's library does not have iconv()
+function, which is a general codeset conversion utility, install iconv
+as an external library. You also need external library if the
+system's implementation cannot handle UTF-8 encoding, or it doesn't
+support some encodings which your client applications uses.
+
+You can get a free version of iconv() implementation (under LGPL
+license, aka GNU libiconv) from:
+
+ ftp://ftp.gnu.org/gnu/libiconv/
+ and mirrors of that site.
+
+But if you don't want code conversion support and you want to install
+idnkitlite library without iconv support alone, you have not install
+external library. Instead, set `--enable-liteonly' value to "yes" at
+configure script execution.
+
+
+1. Running configure script
+
+Run `configure' script in the top directory. This checks various
+characteristics of your system and it will create Makefiles and
+config.h appropriate for your system.
+
+ % ./configure
+
+`configure' accepts many options. Here is a list of some important
+options.
+
+ --prefix=PREFIX
+ Specifies the prefix of install directories of idnkit. The
+ default is /usr/local.
+
+ --enable-runidn
+ Build `runidn' command. The default is "no".
+
+ You cannot set this option "yes" when `--enable-liteonly' is
+ also set "yes".
+
+ --with-libiconv=LIBICONV_PREFIX
+ If you have installed GNU libiconv and would like to link it
+ to idnkit, specify this option. The argument LIBICONV_PREFIX
+ is install prefix of GNU libiconv. If the argument is omitted,
+ PREFIX (derived from --prefix=PREFIX option) is assumed.
+
+ --with-libiconv is shorthand option for GNU libiconv.
+
+ --with-libiconv=/usr/local
+
+ This is equivalent to:
+
+ --with-iconv-include='-I/usr/local/include'
+ --with-iconv='-L/usr/local/lib -R/usr/local/lib -liconv'
+
+ If both the shorthand option (--with-libiconv) and longhand
+ options (--with-iconv-include and/or --with-iconv) are specified,
+ the longhand options have priority.
+
+ You cannot set this option when --enable-liteonly is set
+ "yes", because libidnkitlite library doesn't need iconv
+ support.
+
+ --with-iconv-include=ICONV_INCDIR
+ If the header file "iconv.h" resides in a directory where your
+ C compiler doesn't search by default, specify the directory as
+ DIR like this:
+
+ --with-iconv-include=/usr/local/include
+
+ You cannot set this option when `--enable-liteonly' is set
+ "yes", because libidnkitlite library doesn't need iconv
+ support.
+
+ --with-iconv=ICONV_LIB
+ If your libc doesn't contain iconv(), specify the library
+ that contains iconv(). For example, if iconv() is libiconv
+ in /usr/local/lib, you should specify:
+
+ --with-iconv="-L/usr/local/lib -liconv"
+
+ Note that if the library is a shared one, you might also want
+ to specify -R option, like:
+
+ --with-iconv="-L/usr/local/lib -R/usr/local/lib -liconv"
+
+ You cannot set this option when `--enable-liteonly' is set
+ "yes", because libidnkitlite library doesn't need iconv
+ support.
+
+ --with-iconv-sofile=SOFILE_PATH
+ The runidn command in this kit needs to know the pathname of
+ shared library file that contains iconv(), if iconv() is not
+ part of libc. idnkit tries to find out the pathname from the
+ informaiton provided by `--with-iconv' option described above.
+ But when it fails, you have to specify it with this option,
+ like:
+
+ --with-iconv-sofile=/usr/local/lib/libiconv.so.2.0
+
+ You cannot set this option when `--enable-liteonly' is set
+ "yes", because libidnkitlite library doesn't need iconv
+ support.
+
+ --with-utf8=UTF8_NAME
+ If your iconv() (precisely, iconv_open()) does not accept
+ "UTF-8" as the name of UTF-8 encoding, specify the name for
+ it. For example if your iconv() uses "utf8" instead, you
+ should specify:
+
+ --with-utf8=utf8
+
+
+2. Other configure options
+
+The configure script has many other options though they are not widely
+used:
+
+ --exec-prefix=EXEC_PREFIX
+ Specifies the prefix of install directories for machine-specific
+ files. The default is PREFIX (derived from `--prefix=PREFIX'
+ and its default is /usr/local).
+
+ --bindir=BINDIR
+ Specifies the install directory for idnconv and runidn.
+ The default is EXEC_PREFIX/bin.
+
+ --libdir=LIBDIR
+ Specifies the install directory for the libraries (libidnkit
+ and libidnkitlite). The default is EXEC_PREFIX/lib.
+
+ --includedir=INCDIR
+ Specifies the install directory for the header files of the
+ libraries. The default is PREFIX/include.
+
+ --sysconfdir=SYSCONFDIR
+ Specifies the install directory for sample configuration files
+ of the libraries. The default is PREFIX/etc.
+
+ --mandir=MANDIR
+ Specifies the base install directory for online manuals.
+ The default is PREFIX/man.
+
+ --datadir=DATADIR
+ Specifies the base install directory for machine independent
+ data files. The default is PREFIX/share. Some data files for
+ idnkit will be put under the DATADIR/idnkit directory.
+
+ --enable-debug
+ Enable debugging codes. The fault is "no".
+
+ --enable-shared
+ Build shared library. The fault is "yes".
+
+ --enable-static
+ Build static library. The fault is "yes".
+
+ --enable-liteonly
+ Build the `libidnlkitite' library only. Do not build the
+ `libidnkit' library, idnconv and runidn. The fault is "no".
+
+ If you want to set "yes" to this option, you cannot specify it
+ together with `--enable-runidn', `--with-libiconv',
+ `--with-iconv-include', `--with-iconv' or `--with-iconv-sofile'.
+
+To see the list of available options, you should run it with --help
+option.
+
+ % ./configure --help
+
+
+3. Compiling
+
+Run `make' for compilation.
+
+ % make
+
+
+4. Test
+
+Optionally, type `make test' to compile and run test programs.
+Note that Perl 5 is required for comipilation of the test programs.
+
+ % make test
+
+The test programs assume that iconv() on the system recognizes the
+encoding name "EUC-JP" as Japanese EUC, and "SJIS" as Japanese Shift
+JIS. If iconv() on the system doesn't support the encoding name,
+please edit `lib/tests/codeset.h' before `make test'.
+
+*Note*
+ If you use standard iconv which is attached as default on Solaris,
+ converter's test "idn_converter_convfromucs4()" may fail. But it's
+ not the problem because the result is derived from the difference of
+ specification of iconv. So please ignore it if you run the test on
+ Solaris.
+
+
+5. Installation
+
+Run `make install' to install binaries and manuals. Don't forget to
+become a super-user before the installation.
+
+ % su
+ # make install
+
+*Note*
+ If you have installed pre-release versions of idnkit (such as 1.0pr1),
+ idnkit-1.0 may not work correctly because of the old configuration
+ file 'idn.conf'. If this is the case, you should overwrite existing
+ configuration files with the new ones by executing the following command
+ after 'make install'.
+
+ # make install-config
+
+
+6. Configuration and usage
+
+Edit the `idn.conf' configuation file if you'd like to cosutomize
+conversion/normalization rules of idnkit. Please refer the manual
+for `idn.conf' for details. A sample configuration (`idn.conf.sample')
+is also provided for your convenience.
+
+The sample configuration file has also been installed as `idn.conf'
+if it has not exist on your system.
+
+Also online manuals for `idnconv' and `runidn' commands are available.
+Please refer them for the usage and configuration of these commands.
+
+ % man idn.conf
+ % man idnconv
+ % man runidn
+
+
+7. Check your configuration
+
+A simple shell script `idnslookup' is available in the directory
+`tools/idnconv', with which you can make queries for internationalized
+domain names. It may help you check your configuration.
+
+The usage of `idnslookup' is:
+
+ % tools/idnconv/idnslookup <domain-name> <dns-server>
+
+Suppose that <domain-name> is an internationalized domain name written
+in the local codeset (see ``LOCAL CODESET'' in the `idn.conf' man page
+for details), and <dns-server> is a hostname or IP address of DNS
+server.
+
+`idnslookup' inquires <idn-domain-name> from <dns-server>, using
+`idnconv' and `nslookup' commands. If something is wrong, you will
+see an error message output by `idnconv', `nslookup' or `idnslookup'
+itself.
+
+
+8. Clean up
+
+Run `make clean' to delete files generated by `make' and `make test'
+from the idnkit source directory. (Files installed by `make install'
+are not removed.)
+
+ % make clean
+
+Run `make distclean' instead to also delete files generated by
+`configure'.
+
+ % make distclean
+
+After `make distclean', you can run `configure' and compile idnkit for
+another system using the source directory.
+
+
+Appendix A. Applying patches
+
+This distribution also contains patches for BIND9.
+The top of these patch files describe how to apply the patch and
+(re)install.
+
+Note that on Solaris, "patch" command that comes with the system
+sometimes doesn't work correctly. You may want to install the GNU
+version of the command (http://www.gnu.org/software/patch/) and use
+it.
+
+; $Id: INSTALL,v 1.1.1.1 2003/06/04 00:24:59 marka Exp $
diff --git a/contrib/idn/idnkit-1.0-src/INSTALL.ja b/contrib/idn/idnkit-1.0-src/INSTALL.ja
new file mode 100644
index 0000000..66778b6
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/INSTALL.ja
@@ -0,0 +1,310 @@
+
+ idnkit
+ $B%3%s%Q%$%k$H%$%s%9%H!<%k$NJ}K!(B
+ ($B<R(B) $BF|K\%M%C%H%o!<%/%$%s%U%)%a!<%7%g%s%;%s%?!<(B (JPNIC)
+
+
+$BK\%Q%C%1!<%8$N%3%s%Q%$%k$*$h$S%$%s%9%H!<%k$O!"<!$N$h$&$J%9%F%C%W$G9T(B
+$B$$$^$9!#(B
+
+ + $BA0=`Hw(B: iconv() $B$,MxMQ$G$-$k$h$&$K$9$k(B
+ + $B%7%9%F%`@_Dj(B: `configure' $B%9%/%j%W%H$N<B9T(B
+ + $B%3%s%Q%$%k(B: `make' $B$N<B9T(B
+ + $B%F%9%H(B: `make test' $B$N<B9T(B ($B>JN,2D(B)
+ + $B%$%s%9%H!<%k(B: `make install' $B$N<B9T(B
+ + $B%5%$%HKh$N@_Dj(B: `idn.conf' $B$K$h$k@_Dj(B
+ + $B@_Dj$N3NG'(B ($B>JN,2D(B)
+ + $B8eJRIU$1(B ($B>JN,2D(B)
+
+BIND9 $B$K%Q%C%A$rEv$F$F%$%s%9%H!<%k$7$?$$>l9g$O!"<!$N9`$b;2>H$7$F2<$5$$!#(B
+
+ + $B%Q%C%A$NEv$FJ}(B
+
+0. $BA0=`Hw(B
+
+$B$b$7$"$J$?$,%3!<%IJQ495!G=$r%5%]!<%H$7$?DL>o$N(B idnkit $B%i%$%V%i%j$r%$%s%9(B
+$B%H!<%k$9$k$D$b$j$G$"$j!"$^$?$"$J$?$,;HMQ$7$F$$$k%7%9%F%`$N%i%$%V%i%j$K(B
+iconv() $B$,$J$$>l9g!"$"$k$$$O$"$C$F$b(B UTF-8 $B$r07$&$3$H$,$G$-$J$$>l9g$K$O(B
+$B$"$i$+$8$a(B iconv() $B$r%$%s%9%H!<%k$7$F$*$$$F$/$@$5$$!#(Biconv() $B$O!"Nc$($P(B
+GNU libiconv $B$H8F$P$l$k%U%j!<(B (LGPL) $B$N<BAu$,(B
+
+ ftp://ftp.gnu.org/gnu/libiconv/
+ $B$^$?$O$=$N%_%i!<%5%$%H(B
+
+$B$+$iF~<j2DG=$G$9!#(B
+
+$B$?$@$7!"%3!<%IJQ49$rI,MW$H$;$:!"(Blite $B%P!<%8%g%s$N%i%$%V%i%j$N$_$r%$%s%9(B
+$B%H!<%k$9$k$N$G$"$l$P!"(Biconv() $B$r4^$`%i%$%V%i%j$OI,MW$"$j$^$;$s!#$=$N>l9g!"(B
+configure $B%9%/%j%W%H$N<B9T;~$K(B `--enable-liteonly' $B%*%W%7%g%s$NCM$r(B
+"yes" $B$K%;%C%H$7$F$/$@$5$$!#(B
+
+
+1. configure $B%9%/%j%W%H$N<B9T(B
+
+$B%H%C%W%G%#%l%/%H%j$K$"$k(B configure $B%9%/%j%W%H$r<B9T$7$F$/$@$5$$!#(B
+
+ % ./configure
+
+configure $B%9%/%j%W%H$K$O!"?tB?$/$N%*%W%7%g%s$,MQ0U$5$l$F$$$^$9!#$=$N$&(B
+$B$A=EMW$H;W$o$l$k$b$N$O<!$NDL$j$G$9!#(B
+
+ --prefix=PREFIX
+ idnkit $B$r%$%s%9%H!<%k$9$k%G%#%l%/%H%j$N%Q%9$r;XDj$7$^$9!#%G%U%)(B
+ $B%k%H$O(B /usr/local $B$G$9!#(B
+
+ --enable-runidn
+ runidn $B%3%^%s%I$r:n@.$7$F!"%$%s%9%H!<%k$7$^$9!#%G%U%)%k%H$O(B "no"
+ ($B:n@.$7$J$$(B) $B$G$9!#(B
+
+ --with-libiconv=LIBICONV_PREFIX
+ $B%$%s%9%H!<%k:Q$_$N(B GNU libiconv $B$r(B idnkit $B$K%j%s%/$5$;$k>l9g$O!"(B
+ $B$3$N%*%W%7%g%s$r;XDj$7$F2<$5$$!#0z?t(B LIBICONV_PREFIX $B$K$O!"(BGNU
+ libiconv $B$,%$%s%9%H!<%k$5$l$F$$$k0LCV$r;XDj$7$^$9!#0z?t$r>JN,(B
+ $B$9$k$H!"(BPREFIX (PREFIX $B$NCM$O(B --prefix=PREFIX $B$+$iF3=P$5$l$^$9(B)
+ $B$r;XDj$7$?$b$N$H8+$J$5$l$^$9!#(B
+
+ --with-libiconv $B$O(B GNU libiconv $BMQ$NC;=L7A$N%*%W%7%g%s$G(B
+
+ --with-libiconv=/usr/local
+
+ $B$3$l$O<!$HEy2A$K$J$j$^$9!#(B
+
+ --with-iconv-include='-I/usr/local/include'
+ --with-iconv='-L/usr/local/lib -R/usr/local/lib -liconv'
+
+ $BC;=L7A$N%*%W%7%g%s(B (--with-libiconv) $B$HDL>oMQ$N%*%W%7%g%s(B
+ (--with-iconv-include, --with-iconv) $B$rN>J}$H$b;XDj$7$?>l9g$O!"(B
+ $BDL>oMQ$N%*%W%7%g%s$[$&$,M%@h$5$l$^$9!#(B
+
+ $B$3$N%*%W%7%g%s$O(B --enable-liteonly $B$r(B "yes" $B$K$7$?>l9g$O;XDj$9$k(B
+ $B$3$H$O$G$-$^$;$s!#$3$l$O!"(Blibidnkitlite $B%i%$%V%i%j$,(B iconv $B%5%]!<(B
+ $B%H$rI,MW$H$7$J$$$?$a$G$9!#(B
+
+ --with-iconv-include=ICONV_INCDIR
+ C $B%3%s%Q%$%i$,DL>o$G$O8!:w$7$J$$%G%#%l%/%H%j$K(B "iconv.h" $B$,CV(B
+ $B$+$l$F$$$k>l9g!"<!$N$h$&$K$7$F$=$N%G%#%l%/%H%j$r;XDj$7$^$9!#(B
+
+ --with-iconv-include=/usr/local/include
+
+ $B$3$N%*%W%7%g%s$O(B --enable-liteonly $B$r(B "yes" $B$K$7$?>l9g$O;XDj$9$k(B
+ $B$3$H$O$G$-$^$;$s!#$3$l$O!"(Blibidnkitlite $B%i%$%V%i%j$,(B iconv $B%5%]!<(B
+ $B%H$rI,MW$H$7$J$$$?$a$G$9!#(B
+
+ --with-iconv=ICONV_LIB
+ libc $B$K(B iconv $B$,F~$C$F$$$J$$>l9g(B ($B>e5-$N%Q%C%1!<%8$rF~$l$?(B
+ $B>l9g$J$I(B) $B$K!"(Biconv $B$N%i%$%V%i%j$r;XDj$7$^$9!#Nc$($P(B
+
+ --with-iconv="-L/usr/local/lib -liconv"
+
+ $B$N$h$&$K;XDj$7$^$9!#$b$7(B iconv $B$,6&M-%i%$%V%i%j$K$J$C$F$$$k(B
+ $B>l9g$K$O!"(B-R $B%*%W%7%g%s$b;XDj$7$F(B
+
+ --with-iconv="-L/usr/local/lib -R/usr/local/lib -liconv"
+
+ $B$H$9$kI,MW$,$"$k$+$b$7$l$^$;$s!#(B
+
+ $B$3$N%*%W%7%g%s$O(B --enable-liteonly $B$r(B "yes" $B$K$7$?>l9g$O;XDj$9$k(B
+ $B$3$H$O$G$-$^$;$s!#$3$l$O!"(Blibidnkitlite $B%i%$%V%i%j$,(B iconv $B%5%]!<(B
+ $B%H$rI,MW$H$7$J$$$?$a$G$9!#(B
+
+ --with-iconv-sofile=SOFILE_PATH
+ idnkit $B$K4^$^$l$F$$$k(B runidn $B%3%^%s%I$O!"(Biconv() $B$,(B libc $B$N0l(B
+ $BIt$H$7$FDs6!$5$l$J$$$H$-$K!"(Biconv() $B$r4^$`6&M-%i%$%V%i%j$X$N%Q(B
+ $B%9L>$rCN$kI,MW$,$"$j$^$9!#(Bidnkit $B$O!"(B--with-iconv $B%*%W%7%g%s$N(B
+ $B5-=R$r4p$K%Q%9L>$r8!:w$7$^$9$,!"$3$l$K<:GT$7$?$H$-$K!"0J2<$N$h(B
+ $B$&$K6&M-%i%$%V%i%j$r;XDj$9$k$3$H$,$G$-$^$9!#(B
+
+ --with-iconv-sofile=/usr/local/lib/libiconv.so.2.0
+
+ $B$3$N%*%W%7%g%s$O(B --enable-liteonly $B$r(B "yes" $B$K$7$?>l9g$O;XDj$9$k(B
+ $B$3$H$O$G$-$^$;$s!#$3$l$O!"(Blibidnkitlite $B%i%$%V%i%j$,(B iconv $B%5%]!<(B
+ $B%H$rI,MW$H$7$J$$$?$a$G$9!#(B
+
+ --with-utf8=UTF8_NAME
+ iconv $B$K(B utf-8 $B%(%s%3!<%G%#%s%0$r;XDj$9$k>l9g!"K\%i%$%V%i%j$O(B
+ $B%G%U%)%k%H$G$O(B "UTF-8" $B$H$$$&L>A0$r;XDj$7$^$9!#$b$7$"$J$?$N(B
+ $B%7%9%F%`$N(B iconv $B$,(B "UTF-8" $B$H$$$&L>A0$r<u$1IU$1$J$$>l9g$K$O!"(B
+ $BBe$j$NL>A0$r;XDj$7$^$9!#Nc$($P(B "UTF-8" $B$G$O$J$/(B "utf8" $B$N(B
+ $B>l9g$K$O<!$N$h$&$K;XDj$7$^$9!#(B
+
+ --with-utf8=utf8
+
+
+2. $B$=$NB>$N(B configure $B$N%*%W%7%g%s(B
+
+$B$=$l$[$I$h$/;H$&$o$1$G$O$"$j$^$;$s$,!"(Bconfigure $B$K$OA09`$N$b$N0J30$K(B
+$B$bMM!9$J%*%W%7%g%s$,MQ0U$5$l$F$$$^$9!#(B
+
+ --exec-prefix=EXEC_PREFIX
+ $B%^%7%s8GM-$N%U%!%$%k$r%$%s%9%H!<%k$9$k%G%#%l%/%H%j$N%Q%9$r;XDj(B
+ $B$7$^$9!#%G%U%)%k%H$O(B PREFIX (``--prefix=PREFIX'' $B$K$h$C$F;XDj(B
+ $B2DG=!"(BPREFIX $B$N%G%U%)%k%H$O(B /usr/local) $B$K$J$j$^$9!#(B
+
+ --bindir=BINDIR
+ idnconv $B$H(B runidn $B$r%$%s%9%H!<%k$9$k%G%#%l%/%H%j$r;XDj$7$^$9!#(B
+ $B%G%U%)%k%H$G$O(B EXEC_PREFIX/bin $B$G$9!#(B
+
+ --libdir=LIBDIR
+ $B%i%$%V%i%j(B (libidnkit $B$*$h$S(B libidnkitlite) $B$r%$%s%9%H!<%k$9$k(B
+ $B%G%#%l%/%H%j$r;XDj$7$^$9!#%G%U%)%k%H$G$O(B EXEC_PREFIX/lib $B$G$9!#(B
+
+ --includedir=INCDIR
+ $B%i%$%V%i%j$N%X%C%@%U%!%$%k$r%$%s%9%H!<%k$9$k%G%#%l%/%H%j$r;XDj(B
+ $B$7$^$9!#%G%U%)%k%H$G$O(B PREFIX/include $B$G$9!#(B
+
+ --sysconfdir=SYSCONFDIR
+ $B%i%$%V%i%j$N@_Dj%U%!%$%k$N%5%s%W%k$r%$%s%9%H!<%k$9$k%G%#%l%/%H(B
+ $B%j$r;XDj$7$^$9!#%G%U%)%k%H$G$O(B PREFIX/etc $B$G$9!#(B
+
+ --mandir=MANDIR
+ $B%*%s%i%$%s%^%K%e%"%k$N%$%s%9%H!<%k%G%#%l%/%H%j$r;XDj$7$^$9!#(B
+ $B%G%U%)%k%H$G$O(B PREFIX/man $B$G$9!#(B
+
+ --datadir=DATADIR
+ $B0[$J$k%^%7%s$G6&M-2DG=$J%U%!%$%k$r%$%s%9%H!<%k$9$k%G%#%l%/%H%j(B
+ $B$r;XDj$7$^$9!#%G%U%)%k%H$O(B PREFIX/share $B$G$9!#(BDATADIR/idnkit
+ $B$N2<$K!"(Bidnkit $B$G;HMQ$9$k4v$D$+$N%G!<%?%U%!%$%k$,%$%s%9%H!<%k(B
+ $B$5$l$^$9!#(B
+
+ --enable-debug
+ $B%G%P%C%0MQ$N%3!<%I$rM-8z$K$7$^$9!#%G%U%)%k%H$O(B "no" ($BL58z(B) $B$G$9!#(B
+
+ --enable-shared
+ $B6&M-%i%$%V%i%j$r:n@.$7$^$9!#%G%U%)%k%H$O(B "yes" ($B:n@.$9$k(B) $B$G$9!#(B
+
+ --enable-static
+ $B@EE*%i%$%V%i%j$r:n@.$7$^$9!#%G%U%)%k%H$O(B "yes" ($B:n@.$9$k(B) $B$G$9!#(B
+
+ --enable-liteonly
+ libidnkitlite $B%i%$%V%i%j$N$_$r:n@.$7$^$9!#(Blibidnkit $B%i%$%V%i%j!"(B
+ idnconv, runidn $B$O:n@.$7$^$;$s!#%G%U%)%k%H$O(B "no" ($B$=$l0J30$N(B
+ $B$b$N$b:n@.$9$k(B) $B$G$9!#(B
+
+ $B$3$N%*%W%7%g%s$NCM$r(B "yes" $B$K$9$k>l9g!"(B `--enable-runidn'
+ `--with-libiconv' `--with-iconv-include' `--with-iconv'
+ `--with-iconv-sofile' $B$OF1;~$K;XDj$9$k$3$H$O$G$-$^$;$s!#(B
+
+configure $B$K$OB>$K$bB?$/$N%*%W%7%g%s$,$"$j$^$9$,!";D$j$O0lHLE*$J%*%W%7%g(B
+$B%s$J$N$G@bL@$O>J$-$^$9!#(B
+
+ % ./configure --help
+
+$B$r<B9T$9$k$H%*%W%7%g%s$N0lMw$,I=<($5$l$^$9!#(B
+
+
+3. $B%3%s%Q%$%k(B
+
+configure $B$r<B9T$9$k$H(B Makefile $B$J$I$,@8@.$5$l$^$9$N$G!"B3$1$F(B make$B$r(B
+$B<B9T$7$F%3%s%Q%$%k$7$^$9!#(B
+
+ % make
+
+
+4. $B%F%9%H(B
+
+$B%F%9%H%W%m%0%i%`$r%3%s%Q%$%k$7!"<B9T$9$k$K$O(B `make test' $B$r<B9T$7$^$9(B
+($B>JN,$7$F$b9=$$$^$;$s(B)$B!#%F%9%H%W%m%0%i%`$N%3%s%Q%$%k$K$O!"(BPerl 5 $B$,I,(B
+$BMW$G$9!#(B
+
+ % make test
+
+$B$J$*!"(Biconv() $B$,(B "EUC-JP" $B$rF|K\8l(B EUC $B$N%(%s%3!<%G%#%s%0L>>N$H$7$FG'(B
+$B<1$7!"(B"SJIS" $B$rF|K\8l%7%U%H(B JIS $B$N%(%s%3!<%G%#%s%0L>>N$H$7$FG'<1$9$k$3(B
+$B$H$r!"%F%9%H%W%m%0%i%`$G$OA0Ds$H$7$F$$$^$9!#$b$7!"G'<1$7$J$$$h$&$G$"$l(B
+$B$P!"(B`make test' $B<B9TA0$K(B `lib/tests/codeset.h' $B$rJT=8$7$F2<$5$$!#(B
+
+*$BCm0U(B*
+ Solaris $B$K$*$$$F(B OS $BI8=`$N(B iconv $B$r;HMQ$7$F$$$k>l9g!"(Bconverter $B$N(B
+ idn_converter_convfromucs4() $B$N%F%9%H$,<:GT$9$k$3$H$,$"$j$^$9!#$3$l(B
+ $B$O(B iconv $B$N;EMM$N0c$$$K$h$k$b$N$J$N$G!">e5-4D6-$K$*$$$F%$%s%9%H!<%k(B
+ $B$r9T$C$F$$$k>l9g$OL5;k$7$F$/$@$5$$!#(B
+
+
+5. $B%$%s%9%H!<%k(B
+
+$B%9!<%Q%f!<%6$K$J$C$F%$%s%9%H!<%k$7$^$9!#(B
+
+ % su
+ # make install
+
+*$BCm0U(B*
+ idnkit $B$N(B 1.0 $B0JA0$N%P!<%8%g%s(B (1.0pr1 $B$J$I(B) $B$,$9$G$K%$%s%9%H!<%k$5(B
+ $B$l$F$$$k>l9g!"%$%s%9%H!<%k$5$l$?@_Dj%U%!%$%k(B 'idn.conf' $B$NFbMF$,8E$$(B
+ $B$?$a!"(Bidnkit-1.0$B$,@5$7$/F0:n$7$^$;$s!#$3$N$?$a!"(Bidnkit-1.0 $BMQ$N@_Dj(B
+ $B%U%!%$%k$r>e=q$-%$%s%9%H!<%k$9$kI,MW$,$"$j$^$9!#(Bmake install $B<B9T8e!"(B
+ $B0J2<$N%3%^%s%I$r<B9T$7$F$/$@$5$$!#(B
+
+ # make install-config
+
+
+6. $B@_Dj$H;HMQJ}K!(B
+
+idnkit $B$N@55,2=$*$h$SJQ495,B'$r%+%9%?%^%$%:$7$9$k$J$i!"@_Dj%U%!%$%k(B
+`idn.conf' $B$rJT=8$7$^$9!#$3$N@_Dj%U%!%$%k$N>\:Y$K$D$$$F$O(B idn.conf $B$N(B
+$B%*%s%i%$%s%^%K%e%"%k$r$4Mw$/$@$5$$!#$^$?@_DjNc$,=q$+$l$?%5%s%W%k%U%!%$(B
+$B%k(B (idn.conf.sample) $B$b%$%s%9%H!<%k$5$l$^$9$N$G$4MxMQ$/$@$5$$!#(B
+
+$B%7%9%F%`$K@_Dj%U%!%$%k$,B8:_$7$J$+$C$?>l9g!"$3$N%5%s%W%k$N@_Dj%U%!%$%k(B
+$B$O(B `idn.conf' $B$H$7$F$b%$%s%9%H!<%k$5$l$^$9!#(B
+
+$B$^$?!"(Bidnconv$B!"(Brunidn $B$H$$$C$?%D!<%k$N%*%s%i%$%s%^%K%e%"%k$bDs6!$5$l$F(B
+$B$$$^$9!#$3$l$i$N%3%^%s%I$N;H$$J}!"@_DjJ}K!$K4X$7$F$O$=$A$i$r;2>H$7$F$/(B
+$B$@$5$$!#(B
+
+ % man idn.conf
+ % man idnconv
+ % man runidn
+
+
+7. $B@_Dj$N3NG'(B
+
+`idnslookup' $B$H$$$&4JC1$J%7%'%k%9%/%j%W%H$,(B tools/idnconv $B%G%#%l%/%H%j(B
+$B$KMQ0U$5$l$F$$$^$9!#$3$N%9%/%j%W%H$r;H$&$H(B DNS $B%5!<%P$KBP$7$F9q:]2=%I(B
+$B%a%$%sL>$rLd$$9g$o$;$k$3$H$,$G$-$^$9!#@_Dj%U%!%$%k$N3NG'$KLrN)$D$+$bCN(B
+$B$l$^$;$s!#(B
+
+`idnslookup' $B$N;HMQJ}K!$O!"<!$NDL$j$G$9!#(B
+
+ % tools/idnconv/idnslookup <domain-name> <dns-server>
+
+$B$3$3$G(B <domain-name> $B$O%m!<%+%k%3!<%I%;%C%H(B ($B>\$7$/$O(B idn.conf $B$N%^%K%e(B
+$B%"%k$N(B ``LOCAL CODESET'' $B$r;2>H$N$3$H(B) $B$G=q$+$l$?9q:]2=%I%a%$%sL>$G!"(B
+<dns-server> $B$O(B DNS $B%5!<%P$N%[%9%HL>$b$7$/$O(B IP $B%"%I%l%9$G$9!#(B
+
+`idnslookup' $B$O(B `idnconv' $B$*$h$S(B `nslookup' $B%3%^%s%I$rMQ$$$F!"(B
+<dns-server> $B$KBP$7$F(B <domain-name> $B$r0z$-$K9T$-$^$9!#@_Dj$K2?$+4V0c$$(B
+$B$,$"$l$P!"(B`idnconv', `nslookup', $B$"$k$$$O(B `idnslookup' $B<+?H$K$h$k%(%i!<(B
+$B%a%C%;!<%8$,=PNO$5$l$^$9!#(B
+
+
+8. $B8eJRIU$1(B
+
+`make' $B$*$h$S(B `make test' $B$K$h$C$F@8@.$5$l$?%U%!%$%k$r(B idnkit $B$N%=!<(B
+$B%9%G%#%l%/%H%j$+$i:o=|$9$k$K$O!"(B`make clean' $B$r<B9T$7$F2<$5$$!#(B
+(`make install' $B$N:]$K%$%s%9%H!<%k$5$l$?%U%!%$%k$O!":o=|$5$l$^$;$s!#(B)
+
+ % make clean
+
+`configure' $B$G@8@.$5$l$?%U%!%$%k$b0l=o$K:o=|$9$k$J$i!"Be$o$j$K(B `make
+distclean' $B$r<B9T$7$^$9!#(B
+
+ % make distclean
+
+`make distclean' $B$r9T$($P!"$3$N%=!<%9%G%#%l%/%H%j$r;H$C$F!"A02s$H$OJL(B
+$B$N%7%9%F%`8~$1$K(B `configure' $B$*$h$S(B idnkit $B$N%3%s%Q%$%k$r9T$&$3$H$,$G(B
+$B$-$k$h$&$K$J$j$^$9!#(B
+
+
+$BIUO?(B A. $B%Q%C%A$NEv$FJ}(B
+
+$B$3$NG[I[%-%C%H$K$O!"(BBIND9 $B$KBP$9$k%Q%C%A$,4^$^$l$F$$$^$9!#(B
+$B%Q%C%A$NEv$FJ}$O!"%Q%C%A%U%!%$%k$N@hF,$K=q$+$l$F$$$^$9$N$G$=$A$i$r;2>H(B
+$B$7$F$/$@$5$$!#(B
+
+Solaris $B$G$O!"%7%9%F%`IUB0$N(B patch $B%3%^%s%I$,@5>o$KF0:n$7$J$$$3$H$,$"(B
+$B$j$^$9!#$=$N$h$&$J>l9g$K$O!"(BGNU $B%P!<%8%g%s$N(B patch
+(http://www.gnu.org/software/patch/) $B$r%$%s%9%H!<%k$7$F!"$3$l$r;HMQ$7(B
+$B$F$/$@$5$$!#(B
+
+
+; $Id: INSTALL.ja,v 1.1.1.1 2003/06/04 00:25:00 marka Exp $
diff --git a/contrib/idn/idnkit-1.0-src/LICENSE.txt b/contrib/idn/idnkit-1.0-src/LICENSE.txt
new file mode 100644
index 0000000..1f1e0a0
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/LICENSE.txt
@@ -0,0 +1,39 @@
+Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved.
+
+By using this file, you agree to the terms and conditions set forth bellow.
+
+ LICENSE TERMS AND CONDITIONS
+
+The following License Terms and Conditions apply, unless a different
+license is obtained from Japan Network Information Center ("JPNIC"),
+a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+Chiyoda-ku, Tokyo 101-0047, Japan.
+
+1. Use, Modification and Redistribution (including distribution of any
+ modified or derived work) in source and/or binary forms is permitted
+ under this License Terms and Conditions.
+
+2. Redistribution of source code must retain the copyright notices as they
+ appear in each source code file, this License Terms and Conditions.
+
+3. Redistribution in binary form must reproduce the Copyright Notice,
+ this License Terms and Conditions, in the documentation and/or other
+ materials provided with the distribution. For the purposes of binary
+ distribution the "Copyright Notice" refers to the following language:
+ "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+
+4. The name of JPNIC may not be used to endorse or promote products
+ derived from this Software without specific prior written approval of
+ JPNIC.
+
+5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
diff --git a/contrib/idn/idnkit-1.0-src/Makefile.in b/contrib/idn/idnkit-1.0-src/Makefile.in
new file mode 100644
index 0000000..cf6d8c8
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/Makefile.in
@@ -0,0 +1,79 @@
+# $Id: Makefile.in,v 1.1.1.1 2003/06/04 00:25:03 marka Exp $
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+PERL = perl
+MKTARPKG = ../util/mktarpkg
+SHELL = @SHELL@
+
+SUBDIRS = include lib man tools map
+
+all: force all-subdirs
+test check: force test-subdirs
+install: force install-subdirs
+clean: force clean-subdirs
+distclean: force distclean-localdir distclean-subdirs
+
+distclean-localdir:
+ rm -f config.status config.cache config.log libtool Makefile
+
+all-subdirs install-subdirs clean-subdirs distclean-subdirs test-subdirs:
+ @target=`echo $@ | sed 's/-subdirs$$//'`; \
+ for d in $(SUBDIRS); do \
+ (cd $$d; $(MAKE) DESTDIR=$(DESTDIR) $$target); \
+ done
+
+install-config:
+ (cd lib; $(MAKE) install-config);
+
+dist: force
+ @v=`sed -ne '/^# *define *IDNKIT_VERSION/s/^.*"\([^"]*\)".*$$/\1/p' \
+ $(srcdir)/include/idn/version.h`; \
+ echo generate idnkit-$$v-src.tar.gz; \
+ cd $(srcdir); \
+ $(PERL) $(MKTARPKG) --gzip=9 idnkit-$$v-src
+
+force:
diff --git a/contrib/idn/idnkit-1.0-src/NEWS b/contrib/idn/idnkit-1.0-src/NEWS
new file mode 100644
index 0000000..52943ae
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/NEWS
@@ -0,0 +1,186 @@
+; $Id: NEWS,v 1.1.1.1 2003/06/04 00:25:03 marka Exp $
+
+Major changes in idnkit version 1.0:
+
+* Change ACE prefix of Punycode from 'zq--' to 'xn--'. And delete
+ configure's --with-punycode-prefix option.
+
+* Add NAMEPREP version RFC3491. Other versions of NAMEPREP are
+ removed.
+
+* Enable idnconv to handle a input line as long as memory permitted
+ when encoding/decoding.
+
+* unicode-form-c and unicode-form-c/3.2.0 are not supported.
+
+* Unicode 3.0.1 and Unicode 3.1.0 are not supported.
+
+* Delete BIND8, Squid and GNU libiconv patches.
+
+Major changes in idnkit version 1.0-pr2:
+
+* The license of idnkit is changed to a less restrictive one. See
+ LICENSE.txt for the new license.
+
+* The local codeset name used in the test suite, which is hard-coded
+ in the previous version, can be specified by a separate header file.
+
+* IDN encoding and decoding now always check the validity of the
+ result by performing roundtrip conversion check.
+
+Major changes in idnkit version 1.0-pr1:
+
+* Some test cases are added to the testsuite.
+
+* The testsuite can run on OpenBSD.
+
+Major changes in idnkit version 020829:
+
+* Testsuit is added for the library behavior check.
+ Testsuit and testcases are in lib/tests. Read INSTALL (INSTALL.ja)
+ for details. Tests aim at api, checker, converter, delimitermap,
+ mapper, mapselecter, normalizer, res, resconf, and ucs4 at the
+ moment.
+
+* "amcacez" module is renamed to "punycode".
+
+* AMC-ACE-Z and RACE are now treated as extra ACE.
+
+* Add "--with-utf8=NAME" option to configure script.
+
+Major changes in idnkit version 020730:
+
+* Complete bidi check support for NAMEPREP draft -11.
+
+* Type definitions of action flags for conversion APIs are changed
+ from int to idn_action_t.
+
+* Add -nobidicheck option to idnconv command.
+
+Major changes in idnkit version 020711:
+
+* Default delimiters are added according to IDNA-10.
+
+* ``delimiter-map'' entry in config file is removed.
+
+* Add Unicode version 3.2 support.
+
+* Add preliminary support of NAMEPREP draft -11.
+ This version supports NAMEPREP draft -11 without bidirectional label
+ check.
+
+* Supported NAMEPREP versions are changed.
+ idnkit supports NAMEPREP draft version -03, -10, and -11. Others
+ are removed.
+
+* IDN encoding DUDE is removed.
+
+* New action flags are available for conversion APIs.
+ IDN_ENCODE_QUERY, IDN_DECODE_QUERY, IDN_ENCODE_STORED, and
+ IDN_DECODE_STORED are newly created according to IDNA specification.
+ See include/idn/res.h for precise description.
+
+* Action flags IDN_ENCODE_APP, IDN_DECODE_APP and IDN_NAMEPREP change
+ those behavior.
+ See include/idn/res.h for precise description.
+
+* New decode APIs are created.
+ idn_decodename2() and idn_res_decodename2() are defined to add
+ conversion process from "IDN string encoded in local encoding" to
+ UTF-8 before actual decode process of IDN.
+
+* idnconv with -reverse option treats input as IDN string(s) encoded
+ in local encoding specified by -out option.
+
+* idnconv recognizes `-A' option which is synonym for `-noasciicheck'.
+
+* (Windows) idn Wrapper can run on Windows XP.
+
+* BIND-8 patch for BIND-8.3.3 is available and other patches of BIND-8
+ are removed.
+
+Major changes in idnkit version 1.0-rc1:
+
+* NAMEPREP draft -09 is supported.
+
+* idnconv now accepts any encodings specified as argument for `-in'
+ or `-out' option. `-out' accepts non-ACE, and `-in' accepts ACE.
+
+* In configuration file, `encoding-alias-file' entry is not supported
+ any longer. It is simply ignored.
+
+Major changes in idnkit version 1.0-beta2:
+
+* Supported nameprep version is changed.
+ Now idnkit supports nameprep-03, nameprep-06, and nameprep-08.
+ Nameprep-05 and nameprep-07 are not supported any more.
+
+* Compatibility with mDNkit is added.
+ This feature provides applications formerly written using mDNkit
+ library with some source level compatibilities. If you want to use
+ this feature, set `--enable-mdnkit-compat' option at execution time
+ of configure script.
+
+* Now idnkit can set up easily without configuration file.
+ As this feature is added, initialization function and some behavior
+ of top level API are changed.
+
+* BIND-8 patch supports IDN conversion in itself.
+
+* (Windows) idnkit library looks for configuration files with registry
+ information.
+
+* (Windows) idnkit library returns "CP<code page number>" as local
+ encoding name when the environment variable "IDN_LOCAL_CODESET" is
+ not set.
+
+* (Windows) libidnkit/libidnkitlite are now installed as DLL.
+
+* (Windows) idnconv can be executed as a console application.
+
+Major changes in idnkit version 1.0-beta1:
+
+* mDNkit has been renamed idnkit.
+ This means all symbols with "mdn" are renamed with "idn". For
+ example, a function `mdn_encodename()' is now `idn_encodename()', an
+ environment variable "MDN_DISABLE" is "IDN_DISABLE", system
+ configuretion file is "idn.conf", `runmdn' command is `runidn', and
+ so forth.
+
+* Also, library name has been changed to "libidnkit(lite)".
+
+* `mdnsproxy' command has been removed.
+
+* `runidn' (formerly known as `runmdn') command is not installed by
+ default.
+ If you want to install it, set "yes" to `--enable-runidn' option
+ when you run configure script.
+
+* idnkitlite library only instalation is supported.
+ Set "yes" to `--enable-liteonly' option at execution of configure
+ script to use this feature.
+
+* BIND-9.1.3 patch has been removed.
+
+* User configuration file is supported.
+ idnkit now uses ".idnrc" in user's home directory for configuration
+ of whole scheme. If there is no user configuration file, then it
+ tries to load the system configuration file "idn.conf".
+
+* idnkit is now able to run without configuration file.
+ If there are no configuration files (both of user's and system's),
+ it sets normal configurations (the latest nameprep scheme it
+ supports and the IDN encoding "Punycode") automatically at runtime.
+
+* Encoding alias information file is supported. (by generic libidnkit)
+ Its name is "idnalias.conf" by default and it should be located in
+ same directory where the system configuration file is. Example
+ alias information file "idnalias.conf.sample" is installed
+ automatically.
+
+* APIs are renewed. See manpage.
+
+* Now idnkit has full support of IDNA-07.
+
+* Internal representation of domain name is changed to UCS4 in place
+ of UTF-8.
diff --git a/contrib/idn/idnkit-1.0-src/README b/contrib/idn/idnkit-1.0-src/README
new file mode 100644
index 0000000..5923b77
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/README
@@ -0,0 +1,159 @@
+
+ idnkit
+ -- internationalized domain name toolkit --
+ version 1.0
+ Japan Network Information Center (JPNIC)
+
+
+Table of contents of this file:
+
+ 1. Overview
+ 2. Directory structure of this distribution
+ 3. Supported systems
+ 4. Contact information
+
+See the file INSTALL for compilation and installation instructions.
+See the file NEWS for a list of major changes in the current release.
+
+
+1. Overview
+
+idnkit, which was originally known as mDNkit, is a toolkit for handling
+internationalized domain names. To handle such names, the following
+features are required:
+
+ + Encoding conversion
+ Multilingualized domain names have to be converted from
+ the encoding application uses (local encoding) to
+ the encoding used for name resolution (IDN encoding), and
+ vice versa. Since domain names in IDN encoding just look
+ like good old ASCII domain names, the encoding is also known
+ as ASCII-compatible encoding (ACE).
+
+ + NAMEPREP
+ Name preparation of domain names before converting to
+ IDN encoding. Basically this is a normalization process
+ of the domain names.
+
+These conversion/nameprep processes to domain names have to be
+performed before they are sent to DNS servers. And since the
+processed domain names (in IDN encoding) consist of only legal ASCII
+characters, no changes are required to DNS servers.
+
+idnkit provides several ways for adding these features.
+
+This kit consists of following components.
+
+ + library for handling internationalized domain names
+ (libidnkit, libidnkitlite)
+ Those libraries implement encoding conversion and nameprep.
+ They provide easy-to-use APIs for handling internationalized
+ domain name in your applications.
+
+ Both libraries provide almost the same API. The difference
+ between them is that libidnkit internally uses iconv() function
+ to provide encoding conversion from UTF-8 to the local encoding
+ (such as iso-8859-1, usually determined by the current locale),
+ and vise versa. The idnconv and runidn commands in this toolkit
+ use libidnkit.
+
+ libidnkitlite is lightweight version of libidnkit. It assumes
+ local encoding is UTF-8 so that it never uses iconv().
+
+ + codeset conversion utility (idnconv)
+ This command can convert internationalized domain name written
+ in local encoding (e.g. EUC-JP) to ACE or the opposite direction.
+ It can also convert named.conf and zone master files for BIND.
+
+ + command which adds IDN feature dynamically to unix applications
+ (runidn)
+ This command enables normal applications to handle
+ internationalized domain names by dynamically attaching special
+ library to them. See ``2. using runidn'' below.
+
+ Note that this command is not installed unless you specify the
+ `--enable-runidn' option to `configure'. See the file `INSTALL'
+ for more information about installation.
+
+ + patch for BIND9 that adds IDN capability
+ This patch adds IDN capability to BIND9. It adds encoding
+ conversion and nameprep features to `dig', `host' and
+ `nslookup'. With the patch, those commands become capable of
+ internationalized domain names.
+
+ + IDN wrapper for Windows applications
+ On windows, name resolving request is passed to WINSOCK DLL. So,
+ replacing WINSOCK DLL with multi-lingual domain name version
+ makes legacy windows applications compatible with IDN. This is
+ wrapper DLL for WINSOCK's name resolving functions. See
+ ``3. using IDN wrapper'' below.
+
+
+2. Directory structure of this distribution
+
+Below is a directory structure of this distribution with some
+important files and their brief description.
+
+ +README this file
+ +README.ja .. in Japanese
+ +INSTALL compilation and installation instructions.
+ +INSTALL.ja .. in Japanese
+ +DISTFILES list of files in this distribution
+ +NEWS what's new in this version
+ +ChangeLog list of changes
+ +Makefile.in toplevel makefile template
+ +configure a `configure' script
+ +include/
+ | +config.h.in template header file for configuration
+ | +idn/ header files for libidnkit and libindkitlite
+ | +mdn/ header files for backward compatibility
+ +lib/ source for libidnkit and libidnkitlite
+ +patch/
+ | +bind9/ BIND9 patch
+ +tools/
+ | +idnconv/ source for idnconv command
+ | +runidn/ source for runidn command
+ +util/ utilities
+ +wsock/ source for IDN wrapper
+
+
+3. Supported systems
+
+We've had successful builds on the following systems:
+
+ -------------------------------------------------------------------
+ OS iconv library configure options
+ ===================================================================
+ FreeBSD 4.7-RELEASE GNU libiconv --with-libiconv
+ for Intel 1.8
+ -------------------------------------------------------------------
+ Red Hat Linux 7.3 standard library none
+ for Intel (glibc)
+ -------------------------------------------------------------------
+ Solaris 9 standard library none
+ for Sparc (libc)
+ -------------------------------------------------------------------
+
+The latest information about supported/unsupported systems will be
+found at the mdnkit FAQ page linked from:
+
+ http://www.nic.ad.jp/en/idn/
+
+
+4. Contact information
+
+Please see
+
+ http://www.nic.ad.jp/en/idn/
+
+for the latest news about this kit.
+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,v 1.1.1.1 2003/06/04 00:24:58 marka Exp $
diff --git a/contrib/idn/idnkit-1.0-src/README.ja b/contrib/idn/idnkit-1.0-src/README.ja
new file mode 100644
index 0000000..c9394fc
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/README.ja
@@ -0,0 +1,151 @@
+
+ idnkit
+ -- $B9q:]2=%I%a%$%sL>%D!<%k%-%C%H(B --
+ $B%P!<%8%g%s(B 1.0
+ ($B<R(B) $BF|K\%M%C%H%o!<%/%$%s%U%)%a!<%7%g%s%;%s%?!<(B (JPNIC)
+
+
+$B$3$N%U%!%$%k$NL\<!(B:
+
+ 1. $B35MW(B
+ 2. $B%G%#%l%/%H%j9=@.(B
+ 3. $BK\%-%C%H$,BP1~$7$F$$$k%7%9%F%`(B
+ 4. $BK\%-%C%H$K4X$9$k:G?7>pJs!"Ld$$9g$o$;$K$D$$$F(B
+
+$B%3%s%Q%$%k$*$h$S%$%s%9%H!<%kJ}K!$K$D$$$F$O!"(BINSTALL.ja $B$H$$$&%U%!%$%k$r(B
+$B$4Mw2<$5$$!#$3$N%P!<%8%g%s$G$N<g$JJQ99E@$KIU$$$F$O!"(B($B1QJ8$G$9$,(B) NEWS
+$B$H$$$&%U%!%$%k$r$4Mw2<$5$$!#(B
+
+
+1. $B35MW(B
+
+idnkit ($B5l>N(B mDNkit) $B$H$O9q:]2=%I%a%$%sL>$r07$&$?$a$N%D!<%k%-%C%H$G$9!#(B
+$B9q:]2=%I%a%$%sL>$r07$&$?$a$K$O!"<!$N$h$&$J5!G=$,MW5a$5$l$^$9!#(B
+
+$B!&%(%s%3!<%G%#%s%0JQ49(B
+ $B9q:]2=%I%a%$%sL>$KBP$7$F!"$=$N%(%s%3!<%G%#%s%0$r%"%W%j%1!<%7%g%s$,;H(B
+ $BMQ$7$F$$$k$b$N(B ($B%m!<%+%k%(%s%3!<%G%#%s%0(B) $B$+$iL>A02r7h$KMQ$$$i$l$k$b(B
+ $B$N(B (IDN $B%(%s%3!<%G%#%s%0(B) $B$X$NJQ49!"$^$?$=$N5UJ}8~$NJQ49$r9T$$$^$9!#(B
+ $B%I%a%$%sL>$r(B IDN $B%(%s%3!<%G%#%s%0$K$7$?7k2L$O!"=>Mh$N%I%a%$%sL>$HF1(B
+ $B$8$/(B ASCII $BJ8;z$N$_$G9=@.$5$l$k$N$G!"(BIDN $B%(%s%3!<%G%#%s%0$O(BASCII $B8_(B
+ $B49%(%s%3!<%G%#%s%0(B (ACE) $B$H$b8F$P$l$^$9!#(B
+
+$B!&(BNAMEPREP
+ $B%I%a%$%sL>$r(B IDN $B%(%s%3!<%G%#%s%0$KJQ49$9$kA0$K!"L>A0$N@55,2=$r9T$$(B
+ $B$^$9!#$3$l$r(B NAMEPREP $B$H8F$S$^$9!#(B
+
+$B>e5-$N=hM}$O%I%a%$%sL>$r(B DNS $B%5!<%P$KAw$kA0$K<B9T$9$kI,MW$,$"$j$^$9!#(B
+$B=hM}:Q$N%I%a%$%sL>$O(B ASCII $BJ8;z$+$i9=@.$5$l!"=>Mh$N(B ASCII $B%I%a%$%sL>$H(B
+$B$7$F$b@5$7$$7A<0$K$J$C$F$$$k$N$G!"(BDNS $B%5!<%PB&$K$O$J$s$NJQ99$bI,MW$"$j(B
+$B$^$;$s!#(B
+
+$B$3$NG[I[%-%C%H$K$O<!$N$h$&$J$b$N$,4^$^$l$^$9!#(B
+
+$B!&9q:]2=%I%a%$%sL>$r=hM}$9$k$?$a$N%i%$%V%i%j(B (libidnkit, libidnkitlite)
+ $B$3$l$i$N%i%$%V%i%j$G$O!"%(%s%3!<%G%#%s%0JQ49$d(B NAMEPREP $B$N5!G=$r<B(B
+ $BAu$7$F$*$j!"%"%W%j%1!<%7%g%s$,9q:]2=%I%a%$%sL>$r4JC1$K07$($k$h$&$K(B
+ $B$9$k$?$a$N(B API $B$rHw$($F$$$^$9!#(B
+
+ $B$I$A$i$N%i%$%V%i%j$b$[$H$s$IF1$8(B API $B$rDs6!$7$^$9!#N><T$NAj0cE@$G$9(B
+ $B$,!"(Blibidnkit $B$N$[$&$O(B iconv() $B4X?t$r;H$C$F(B UTF-8 $B$H%m!<%+%k%(%s%3!<(B
+ $B%G%#%s%0(B (iso-8859-1 $B$J$I!"DL>o$O(B locale $B$+$i7hDj$5$l$^$9(B) $B$H$N4V$N(B
+ $BJQ495!G=$rDs6!$7$F$$$^$9!#K\%D!<%k%-%C%HIUB0$N(B idnconv $B$*$h$S(B runidn
+ $B$O(B libidnkit $B$r;HMQ$7$F$$$^$9!#(B
+
+ libidnkitlite $B$O(B libidnkit $B$N7ZNLHG$G$9!#%m!<%+%k%(%s%3!<%G%#%s%0$O(B
+ $B>o$K(B UTF-8 $B$@$H2>Dj$7$F$*$j!"(Biconv() $B$O;HMQ$7$^$;$s!#(B
+
+$B!&%3!<%I%;%C%H%3%s%P!<%?(B (idnconv)
+ $B%m!<%+%k%(%s%3!<%G%#%s%0(B ($B$?$H$($P(B EUC-JP) $B$G=q$+$l$?9q:]2=%I%a%$%s(B
+ $BL>$+$i(B ACE $B$X$NJQ49$d!"$=$N5UJQ49$r9T$($k%3%^%s%I$G$9!#(BBIND $BMQ$N(B
+ named.conf $B$d%>!<%s%^%9%?%U%!%$%k$rJQ49$9$k$3$H$b2DG=$G$9!#(B
+
+$B!&(BUNIX $B%"%W%j%1!<%7%g%s$K(B IDN $B5!G=$rF0E*$KDI2C$9$k%3%^%s%I(B (runidn)
+ UNIX $B$NDL>o$N%"%W%j%1!<%7%g%s$G9q:]2=%I%a%$%sL>$r<h$j07$&$?$a$K!"FC(B
+ $BJL$J%i%$%V%i%j$rF0E*$K%j%s%/$9$k$?$a$N%3%^%s%I$G$9!#>\$7$/$O!"8e=R$N(B
+ $B!V(B2. runidn $B$r;H$&!W$r8fMw$/$@$5$$!#(B
+
+ $B$J$*!"(Bconfigure $B<B9T;~$K(B `--enable-runidn' $B$r;XDj$7$J$$$H!"(Brunidn $B$O(B
+ $B%$%s%9%H!<%k$5$l$^$;$s!#%$%s%9%H!<%k$K4X$7$F!">\$7$/$O(B INSTALL.ja $B$H(B
+ $B$$$&%U%!%$%k$r$4Mw$/$@$5$$!#(B
+
+$B!&(BBIND9 $B$K(B IDN $B5!G=$rDI2C$9$k%Q%C%A(B
+ BIND $B$K(B IDN $B$N5!G=$rDI2C$9$k%Q%C%A$G$9!#(B`dig'$B!"(B`host'$B!"(B`nslookup' $B$K(B
+ $B%(%s%3!<%G%#%s%0JQ49$H(B NAMEPREP $B$N5!G=$rDI2C$7!"9q:]2=%I%a%$%sL>$,07(B
+ $B$($k$h$&$K$7$^$9!#(B
+
+$B!&(BWindows $B%"%W%j%1!<%7%g%sMQ$N(B IDN $B%i%C%Q!<(B
+ WINSOCK $B$NL>A02r7h5!G=$KBP$9$k%i%C%Q!<(B DLL $B$G$9!#(BWindows $B>e$G$O!"L>(B
+ $BA02r7h$NMW5a$O!"(BWINSOCK DLL $B$rDL$7$F9T$o$l$^$9!#$=$3$G!"$3$l$r9q:]2=(B
+ $B%I%a%$%sMQ$N(B WINSOCK DLL $B$KCV$-49$($k$3$H$G!"=>Mh$N(B Windows $B%"%W%j%1!<(B
+ $B%7%g%s$G$b(B IDN $B5!G=$r;HMQ$G$-$k$h$&$K$7$^$9!#>\$7$/$O!"8e=R$N(B
+ $B!V(B3. IDN $B%i%C%Q!<$r;H$&!W$r8fMw$/$@$5$$!#(B
+
+
+2. $B%G%#%l%/%H%j9=@.(B
+
+$BG[I[%-%C%H$N%G%#%l%/%H%j9=@.$H!"<gMW$J%U%!%$%k$r<($7$^$9!#(B
+
+ +README $B1Q8lHG$N(B README
+ +README.ja $B$3$N%U%!%$%k(B
+ +INSTALL $B1Q8lHG$N(B INSTALL
+ +INSTALL.ja $B%3%s%Q%$%k$H%$%s%9%H!<%kJ}K!(B
+ +DISTFILES $BG[I[$5$l$k%U%!%$%k0lMw(B
+ +NEWS $B<g$JJQ99(B
+ +ChangeLog $BJQ99>\:Y(B
+ +configure configure $B%9%/%j%W%H(B
+ +Makefile.in $B%H%C%W%l%Y%k$N(B Makefile $B$N%F%s%W%l!<%H(B
+ +include/
+ | +config.h.in config.h $B$N%F%s%W%l!<%H(B
+ | +idn/ libidnkit, libidnkitlite $B$N%X%C%@%U%!%$%k(B
+ | +mdn/ $B5l%P!<%8%g%s$H$N8_49MQ%X%C%@%U%!%$%k(B
+ +lib/ libidnkit, libidnkitlite $B$N%=!<%9(B
+ +patch/
+ | +bind9/ BIND9 $BMQ%Q%C%A(B
+ +tools/
+ | +idnconv/ idnconv $B%3%^%s%I$N%=!<%9(B
+ | +runidn/ runidn $B%3%^%s%I$N%=!<%9(B
+ +util/ $B%f!<%F%#%j%F%#(B
+ +wsock/ IDN $B%i%C%Q!<$N%=!<%9(B
+
+
+3. $BK\%-%C%H$,BP1~$7$F$$$k%7%9%F%`(B
+
+$B@5>o$K%$%s%9%H!<%k$G$-$k$3$H$,3NG'$G$-$F$$$k$N$O!"<!$N%7%9%F%`$G$9!#(B
+
+ ------------------------------------------------------------------
+ OS iconv configure $B$N%*%W%7%g%s(B
+ ==================================================================
+ FreeBSD 4.7-RELEASE GNU libiconv --with-libiconv
+ Intel 1.8
+ -------------------------------------------------------------------
+ Red Hat Linux 7.3 $BI8=`%i%$%V%i%j(B $B$J$7(B
+ Intel (glibc)
+ ------------------------------------------------------------------
+ Solaris 9 $BI8=`%i%$%V%i%j(B $B$J$7(B
+ Sparc (libc)
+ -------------------------------------------------------------------
+
+$BK\%-%C%H$,BP1~$7$F$$$k(B/$B$7$F$$$J$$%7%9%F%`$K4X$9$k:G?7$N>pJs$O!"<!$N$H(B
+$B$3$m$+$iC)$l$k(B mdnkit FAQ $B$N%Z!<%8$K5-$5$l$F$$$^$9!#(B
+
+ http://www.nic.ad.jp/ja/idn/
+
+
+4. $BK\%-%C%H$K4X$9$k:G?7>pJs!"Ld$$9g$o$;$K$D$$$F(B
+
+$BK\%-%C%H$K4X$9$k:G?7>pJs$K$D$$$F$O!"(B
+
+ http://www.nic.ad.jp/ja/idn/
+
+$B$r;2>H$7$F$/$@$5$$(B
+$BK\%-%C%H$K4X$9$k%P%0%l%]!<%H$*$h$S%3%a%s%H$O!"$=$l$>$l(B
+
+ mdnkit-bugs@nic.ad.jp
+$B$*$h$S(B
+ idn-cmt@nic.ad.jp
+
+$B$X$*4j$$$7$^$9!#(B
+
+
+; $Id: README.ja,v 1.1.1.1 2003/06/04 00:24:59 marka Exp $
diff --git a/contrib/idn/idnkit-1.0-src/acconfig.h b/contrib/idn/idnkit-1.0-src/acconfig.h
new file mode 100644
index 0000000..05d90a5
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/acconfig.h
@@ -0,0 +1,53 @@
+/* $Id: acconfig.h,v 1.1.1.1 2003/06/04 00:25:03 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+@TOP@
+
+/* Define as an appropriate type (ex. int) if your system doesn't have. */
+#undef BOOL
+
+@BOTTOM@
+/* Define as the pathname of the shared libc object if your system has one. */
+#undef SOPATH_LIBC
+
+/* Define as the pathname of the shared libnsl object if your system has one. */
+#undef SOPATH_LIBNSL
diff --git a/contrib/idn/idnkit-1.0-src/aclocal.m4 b/contrib/idn/idnkit-1.0-src/aclocal.m4
new file mode 100644
index 0000000..ffb130e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/aclocal.m4
@@ -0,0 +1,472 @@
+##
+## $Id: aclocal.m4,v 1.1.1.1 2003/06/04 00:25:05 marka Exp $
+##
+AC_DEFUN(AC_FIND_SYSTEM_SHOBJ,[
+AC_MSG_CHECKING(for $1 shared object)
+shobj_name=$1
+shobj_path=
+case "$host" in
+*-hpux*)
+ SOEXT=sl
+ ;;
+*)
+ SOEXT=so
+ ;;
+esac
+for shobj_libdir in /lib /usr/lib; do
+ if test -f $shobj_libdir/$shobj_name.$SOEXT; then
+ shobj_path=$shobj_libdir/$shobj_name.$SOEXT
+ else
+ shobj_path=`ls -r $shobj_libdir/$shobj_name.$SOEXT* 2>/dev/null | head -1`
+ if test "$shobj_path" != "" -a -f "$shobj_path"; then
+ :
+ else
+ shobj_path=
+ fi
+ fi
+ if test "$shobj_path" != ""; then
+ AC_MSG_RESULT($shobj_path)
+ shobj_pathsymbol=SOPATH_`echo $shobj_name | sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ AC_DEFINE_UNQUOTED($shobj_pathsymbol, "$shobj_path")
+ break
+ fi
+done
+if test "$shobj_path" = ""; then
+ AC_MSG_RESULT(no)
+fi
+])dnl
+
+## libtool.m4 - Configure libtool for the target system. -*-Shell-script-*-
+## Copyright (C) 1996-1999, 2000 Free Software Foundation, Inc.
+## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## As a special exception to the GNU General Public License, if you
+## distribute this file as part of a program that contains a
+## configuration script generated by Autoconf, you may include it under
+## the same distribution terms that you use for the rest of that program.
+
+# serial 40 AC_PROG_LIBTOOL
+AC_DEFUN(AC_PROG_LIBTOOL,
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+
+# Save cache, so that ltconfig can load it
+AC_CACHE_SAVE
+
+# Actually configure libtool. ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
+LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \
+DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \
+|| AC_MSG_ERROR([libtool configure failed])
+
+# Reload cache, that may have been modified by ltconfig
+AC_CACHE_LOAD
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+])
+
+AC_DEFUN(AC_LIBTOOL_SETUP,
+[AC_PREREQ(2.13)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_RANLIB])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+dnl
+
+case "$target" in
+NONE) lt_target="$host" ;;
+*) lt_target="$target" ;;
+esac
+
+# Check for any special flags to pass to ltconfig.
+libtool_flags="--cache-file=$cache_file"
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN],
+[libtool_flags="$libtool_flags --enable-dlopen"])
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+[libtool_flags="$libtool_flags --enable-win32-dll"])
+AC_ARG_ENABLE(libtool-lock,
+ [ --disable-libtool-lock avoid locking (might break parallel builds)])
+test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock"
+test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$lt_target" in
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case "`/usr/bin/file conftest.o`" in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])])
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw*)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+])
+esac
+])
+
+# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
+AC_DEFUN(AC_LIBTOOL_DLOPEN, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
+
+# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
+AC_DEFUN(AC_LIBTOOL_WIN32_DLL, [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
+
+# AC_ENABLE_SHARED - implement the --enable-shared flag
+# Usage: AC_ENABLE_SHARED[(DEFAULT)]
+# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+# `yes'.
+AC_DEFUN(AC_ENABLE_SHARED, [dnl
+define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(shared,
+changequote(<<, >>)dnl
+<< --enable-shared[=PKGS] build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac],
+enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
+])
+
+# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
+AC_DEFUN(AC_DISABLE_SHARED, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)])
+
+# AC_ENABLE_STATIC - implement the --enable-static flag
+# Usage: AC_ENABLE_STATIC[(DEFAULT)]
+# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+# `yes'.
+AC_DEFUN(AC_ENABLE_STATIC, [dnl
+define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(static,
+changequote(<<, >>)dnl
+<< --enable-static[=PKGS] build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac],
+enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
+])
+
+# AC_DISABLE_STATIC - set the default static flag to --disable-static
+AC_DEFUN(AC_DISABLE_STATIC, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)])
+
+
+# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
+# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
+# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to
+# `yes'.
+AC_DEFUN(AC_ENABLE_FAST_INSTALL, [dnl
+define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(fast-install,
+changequote(<<, >>)dnl
+<< --enable-fast-install[=PKGS] optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac],
+enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
+])
+
+# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install
+AC_DEFUN(AC_DISABLE_FAST_INSTALL, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)])
+
+# AC_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN(AC_PROG_LD,
+[AC_ARG_WITH(gnu-ld,
+[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by GCC])
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+changequote(,)dnl
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+changequote([,])dnl
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(ac_cv_path_LD,
+[if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ ac_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])
+
+AC_DEFUN(AC_PROG_LD_GNU,
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ ac_cv_prog_gnu_ld=yes
+else
+ ac_cv_prog_gnu_ld=no
+fi])
+])
+
+# AC_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN(AC_PROG_NM,
+[AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(ac_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ ac_cv_path_NM="$NM"
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -B"
+ break
+ elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -p"
+ break
+ else
+ ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi])
+NM="$ac_cv_path_NM"
+AC_MSG_RESULT([$NM])
+])
+
+# AC_CHECK_LIBM - check for math library
+AC_DEFUN(AC_CHECK_LIBM,
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case "$lt_target" in
+*-*-beos* | *-*-cygwin*)
+ # These system don't have libm
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+ AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, main, LIBM="-lm")
+ ;;
+esac
+])
+
+# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl convenience library and INCLTDL to the include flags for
+# the libltdl header and adds --enable-ltdl-convenience to the
+# configure arguments. Note that LIBLTDL and INCLTDL are not
+# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not
+# provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed
+# with '${top_builddir}/' and INCLTDL will be prefixed with
+# '${top_srcdir}/' (note the single quotes!). If your package is not
+# flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ case "$enable_ltdl_convenience" in
+ no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+ "") enable_ltdl_convenience=yes
+ ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+ esac
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+ INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+])
+
+# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl installable library and INCLTDL to the include flags for
+# the libltdl header and adds --enable-ltdl-install to the configure
+# arguments. Note that LIBLTDL and INCLTDL are not AC_SUBSTed, nor is
+# AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed
+# libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will
+# be prefixed with '${top_builddir}/' and INCLTDL will be prefixed
+# with '${top_srcdir}/' (note the single quotes!). If your package is
+# not flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ AC_CHECK_LIB(ltdl, main,
+ [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+ [if test x"$enable_ltdl_install" = xno; then
+ AC_MSG_WARN([libltdl not installed, but installation disabled])
+ else
+ enable_ltdl_install=yes
+ fi
+ ])
+ if test x"$enable_ltdl_install" = x"yes"; then
+ ac_configure_args="$ac_configure_args --enable-ltdl-install"
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+ INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ else
+ ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+ LIBLTDL="-lltdl"
+ INCLTDL=
+ fi
+])
+
+dnl old names
+AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl
+AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl
+AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl
+AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl
+AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl
+AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl
+AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl
+
+dnl This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])dnl
diff --git a/contrib/idn/idnkit-1.0-src/config.guess b/contrib/idn/idnkit-1.0-src/config.guess
new file mode 100755
index 0000000..dff9e48
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/config.guess
@@ -0,0 +1,1317 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+
+timestamp='2001-09-04'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# Please send patches to <config-patches@gnu.org>.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int dummy(){}" > $dummy.c ;
+ for c in cc gcc c89 ; do
+ ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+ if test $? = 0 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ rm -f $dummy.c $dummy.o $dummy.rel ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # Netbsd (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ # Determine the machine/vendor (is the vendor relevant).
+ case "${UNAME_MACHINE}" in
+ amiga) machine=m68k-unknown ;;
+ arm32) machine=arm-unknown ;;
+ atari*) machine=m68k-atari ;;
+ sun3*) machine=m68k-sun ;;
+ mac68k) machine=m68k-apple ;;
+ macppc) machine=powerpc-apple ;;
+ hp3[0-9][05]) machine=m68k-hp ;;
+ ibmrt|romp-ibm) machine=romp-ibm ;;
+ *) machine=${UNAME_MACHINE}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE}" in
+ i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ cat <<EOF >$dummy.s
+ .data
+\$Lformat:
+ .byte 37,100,45,37,120,10,0 # "%d-%x\n"
+
+ .text
+ .globl main
+ .align 4
+ .ent main
+main:
+ .frame \$30,16,\$26,0
+ ldgp \$29,0(\$27)
+ .prologue 1
+ .long 0x47e03d80 # implver \$0
+ lda \$2,-1
+ .long 0x47e20c21 # amask \$2,\$1
+ lda \$16,\$Lformat
+ mov \$0,\$17
+ not \$1,\$18
+ jsr \$26,printf
+ ldgp \$29,0(\$26)
+ mov 0,\$16
+ jsr \$26,exit
+ .end main
+EOF
+ eval $set_cc_for_build
+ $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ case `./$dummy` in
+ 0-0)
+ UNAME_MACHINE="alpha"
+ ;;
+ 1-0)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 1-1)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 1-101)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 2-303)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ 2-307)
+ UNAME_MACHINE="alphaev67"
+ ;;
+ 2-1307)
+ UNAME_MACHINE="alphaev68"
+ ;;
+ esac
+ fi
+ rm -f $dummy.s $dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ arc64:OpenBSD:*:*)
+ echo mips64el-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hkmips:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:NetBSD:*)
+ echo `uname -p`-unknown-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy \
+ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm -f $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ case "${HPUX_REV}" in
+ 11.[0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ esac ;;
+ esac
+ fi ;;
+ esac
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
+ if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+ rm -f $dummy.c $dummy
+ fi ;;
+ esac
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ hppa*:OpenBSD:*:*)
+ echo hppa-unknown-openbsd
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3D:*:*:*)
+ echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i386-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in
+ big) echo mips-unknown-linux-gnu && exit 0 ;;
+ little) echo mipsel-unknown-linux-gnu && exit 0 ;;
+ esac
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ ld_supported_targets=`cd /; ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ cat >$dummy.c <<EOF
+#include <features.h>
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+#ifdef __ELF__
+# ifdef __GLIBC__
+# if __GLIBC__ >= 2
+ printf ("%s-pc-linux-gnu\n", argv[1]);
+# else
+ printf ("%s-pc-linux-gnulibc1\n", argv[1]);
+# endif
+# else
+ printf ("%s-pc-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+ printf ("%s-pc-linux-gnuaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ echo `uname -p`-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ if test "${UNAME_MACHINE}" = "x86pc"; then
+ UNAME_MACHINE=pc
+ fi
+ echo `uname -p`-${UNAME_MACHINE}-nto-qnx
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-[KW]:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/contrib/idn/idnkit-1.0-src/config.sub b/contrib/idn/idnkit-1.0-src/config.sub
new file mode 100755
index 0000000..393f13d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/config.sub
@@ -0,0 +1,1411 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+
+timestamp='2001-09-07'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dsp16xx \
+ | fr30 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | m32r | m68000 | m68k | m88k | mcore \
+ | mips16 | mips64 | mips64el | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el | mips64vr4300 \
+ | mips64vr4300el | mips64vr5000 | mips64vr5000el \
+ | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
+ | mipsisa32 \
+ | mn10200 | mn10300 \
+ | ns16k | ns32k \
+ | openrisc \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | s390 | s390x \
+ | sh | sh[34] | sh[34]eb | shbe | shle \
+ | sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \
+ | stormy16 | strongarm \
+ | tahoe | thumb | tic80 | tron \
+ | v850 \
+ | we32k \
+ | x86 | xscale \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alphapca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armv*-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c54x-* \
+ | clipper-* | cray2-* | cydra-* \
+ | d10v-* | d30v-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | m32r-* \
+ | m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
+ | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
+ | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | s390-* | s390x-* \
+ | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclite-* \
+ | sparcv9-* | sparcv9b-* | stormy16-* | strongarm-* | sv1-* \
+ | t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
+ | v850-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xmp-* | xps100-* | xscale-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ [cjt]90)
+ basic_machine=${basic_machine}-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mipsel*-linux*)
+ basic_machine=mipsel-unknown
+ os=-linux-gnu
+ ;;
+ mips*-linux*)
+ basic_machine=mips-unknown
+ os=-linux-gnu
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2)
+ basic_machine=i686-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sparclite-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=t3e-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ windows32)
+ basic_machine=i386-pc
+ os=-windows32-msvcrt
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ mips)
+ if [ x$os = x-linux-gnu ]; then
+ basic_machine=mips-unknown
+ else
+ basic_machine=mips-mips
+ fi
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh3eb | sh4eb)
+ basic_machine=sh-unknown
+ ;;
+ sparc | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ c4x*)
+ basic_machine=c4x-none
+ os=-coff
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto*)
+ os=-nto-qnx
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/contrib/idn/idnkit-1.0-src/configure b/contrib/idn/idnkit-1.0-src/configure
new file mode 100755
index 0000000..1d22dac
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/configure
@@ -0,0 +1,3517 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-debug enable debug codes [default=no]"
+ac_help="$ac_help
+ --enable-mdnkit-compat enable mDNkit compatibility mode [default=no]"
+ac_help="$ac_help
+ --enable-extra-ace enable additional ACE converters. [default=no]"
+ac_help="$ac_help
+ --with-utf8=NAME codeset name for UTF-8 encoding [UTF-8]"
+ac_help="$ac_help
+ --enable-liteonly compile and install lite library only [default=no]"
+ac_help="$ac_help
+ --enable-runidn compile and install runidn [default=no]"
+ac_help="$ac_help
+ --with-libiconv=IPREFIX GNU libiconv are installed in IPREFIX [PREFIX]"
+ac_help="$ac_help
+ --with-iconv-include=DIR iconv include files are in DIR []"
+ac_help="$ac_help
+ --with-iconv=LIB special library for iconv []"
+ac_help="$ac_help
+ --with-iconv-sofile=PATH shared library file for libiconv []"
+ac_help="$ac_help
+ --enable-shared[=PKGS] build shared libraries [default=yes]"
+ac_help="$ac_help
+ --enable-static[=PKGS] build static libraries [default=yes]"
+ac_help="$ac_help
+ --enable-fast-install[=PKGS] optimize for fast installation [default=yes]"
+ac_help="$ac_help
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]"
+ac_help="$ac_help
+ --disable-libtool-lock avoid locking (might break parallel builds)"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=include/idn/converter.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:582: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+
+debug=no
+# Check whether --enable-debug or --disable-debug was given.
+if test "${enable_debug+set}" = set; then
+ enableval="$enable_debug"
+ debug=$enableval
+fi
+
+case "$debug" in
+yes)
+ CFLAGS="$CFLAGS -DDEBUG"
+ ;;
+esac
+
+mdnkit_compat=no
+COMPAT_TRUE="#"
+COMPAT_FALSE=
+# Check whether --enable-mdnkit-compat or --disable-mdnkit-compat was given.
+if test "${enable_mdnkit_compat+set}" = set; then
+ enableval="$enable_mdnkit_compat"
+ mdnkit_compat=$enableval
+fi
+
+case "$mdnkit_compat" in
+yes)
+ COMPAT_TRUE=
+ COMPAT_FALSE="#"
+ cat >> confdefs.h <<\EOF
+#define ENABLE_MDNKIT_COMPAT 1
+EOF
+
+ ;;
+no)
+ ;;
+*)
+ { echo "configure: error: You must specify yes or no to --enable-runidn option." 1>&2; exit 1; }
+ ;;
+esac
+
+
+
+extraace=no
+# Check whether --enable-extra-ace or --disable-extra-ace was given.
+if test "${enable_extra_ace+set}" = set; then
+ enableval="$enable_extra_ace"
+ extraace=$enableval
+fi
+
+case "$extraace" in
+no)
+ ;;
+yes)
+ cat >> confdefs.h <<\EOF
+#define IDN_EXTRA_ACE 1
+EOF
+
+ ;;
+*)
+ { echo "configure: error: You must specify yes or no to --enable-extra-ace option." 1>&2; exit 1; }
+ ;;
+esac
+
+UTF8_NAME=no
+# Check whether --with-utf8 or --without-utf8 was given.
+if test "${with_utf8+set}" = set; then
+ withval="$with_utf8"
+ UTF8_NAME=$withval
+fi
+
+case "$UTF8_NAME" in
+no)
+ UTF8_NAME=UTF-8
+ ;;
+yes)
+ { echo "configure: error: You must specify NAME to --with-utf8 option." 1>&2; exit 1; }
+ ;;
+*)
+ cat >> confdefs.h <<EOF
+#define IDN_UTF8_ENCODING_NAME "$UTF8_NAME"
+EOF
+
+ ;;
+esac
+
+
+liteonly=no
+LITEONLY_TRUE="#"
+LITEONLY_FALSE=
+# Check whether --enable-liteonly or --disable-liteonly was given.
+if test "${enable_liteonly+set}" = set; then
+ enableval="$enable_liteonly"
+ liteonly=$enableval
+fi
+
+case "$liteonly" in
+no)
+ ;;
+yes)
+ if test "$install_runidn" = yes ; then
+ { echo "configure: error: you can't set value \"yes\" to --enable-runidn and --enable-liteonly simultaneously, because runidn requires iconv support of generic libidnkit." 1>&2; exit 1; }
+ fi
+ LITEONLY_TRUE=
+ LITEONLY_FALSE="#"
+ ;;
+*)
+ { echo "configure: error: You must specify yes or no to --enable-liteonly option." 1>&2; exit 1; }
+ ;;
+esac
+
+
+
+install_runidn=no
+RUNIDN_TRUE="#"
+RUNIDN_FALSE=
+# Check whether --enable-runidn or --disable-runidn was given.
+if test "${enable_runidn+set}" = set; then
+ enableval="$enable_runidn"
+ install_runidn=$enableval
+fi
+
+case "$install_runidn" in
+no)
+ ;;
+yes)
+ if test "$liteonly" = yes ; then
+ { echo "configure: error: you can't set value \"yes\" to --enable-runidn and --enable-liteonly simultaneously, because runidn requires iconv support of generic libidnkit." 1>&2; exit 1; }
+ fi
+ RUNIDN_TRUE=
+ RUNIDN_FALSE="#"
+ ;;
+*)
+ { echo "configure: error: You must specify yes or no to --enable-runidn option." 1>&2; exit 1; }
+ ;;
+esac
+
+
+
+ICONVINC=
+ICONVLIB=
+
+libiconv=unspec
+# Check whether --with-libiconv or --without-libiconv was given.
+if test "${with_libiconv+set}" = set; then
+ withval="$with_libiconv"
+ libiconv=$withval
+fi
+
+case "$libiconv" in
+unspec)
+ ;;
+no)
+ ICONVINC=
+ ICONVLIB=
+ ;;
+yes)
+ if test "$liteonly" = yes ; then
+ { echo "configure: error: you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support." 1>&2; exit 1; }
+ fi
+ if test X$prefix = XNONE ; then
+ libiconv=$ac_default_prefix
+ else
+ libiconv=$prefix
+ fi
+ ICONVINC="-I$libiconv/include"
+ ICONVLIB="-L$libiconv/lib -R$libiconv/lib -liconv"
+ ;;
+*)
+ if test "$liteonly" = yes ; then
+ { echo "configure: error: you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support." 1>&2; exit 1; }
+ fi
+ ICONVINC="-I$libiconv/include"
+ ICONVLIB="-L$libiconv/lib -R$libiconv/lib -liconv"
+ ;;
+esac
+
+iconv_include=unspec
+# Check whether --with-iconv-include or --without-iconv-include was given.
+if test "${with_iconv_include+set}" = set; then
+ withval="$with_iconv_include"
+ iconv_include=$withval
+fi
+
+case "$iconv_include" in
+unspec)
+ ;;
+no)
+ ICONVINC=
+ ;;
+yes)
+ if test "$liteonly" = yes ; then
+ { echo "configure: error: you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support." 1>&2; exit 1; }
+ fi
+ echo "configure: warning: You must supply DIR to --with-iconv-include option.
+ Ignored." 1>&2
+ ICONVINC=
+ ;;
+*)
+ if test "$liteonly" = yes ; then
+ { echo "configure: error: you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support." 1>&2; exit 1; }
+ fi
+ ICONVINC="-I$iconv_include"
+ ;;
+esac
+
+if test "X$ICONVINC" != X ; then
+ iconv_include="`echo X$ICONVINC | sed -e 's/^X-I//'`"
+ if test ! -f "$iconv_include/iconv.h" ; then
+ { echo "configure: error: iconv.h doesn't exist in $iconv_include" 1>&2; exit 1; }
+ fi
+fi
+
+
+
+iconv=unspec
+# Check whether --with-iconv or --without-iconv was given.
+if test "${with_iconv+set}" = set; then
+ withval="$with_iconv"
+ iconv=$withval
+fi
+
+case "$iconv" in
+unspec)
+ ;;
+no)
+ ICONVLIB=
+ ;;
+yes)
+ if test "$liteonly" = yes ; then
+ { echo "configure: error: you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support." 1>&2; exit 1; }
+ fi
+ echo "configure: warning: You must supply LIB to --with-iconv option.
+ -liconv is assumed." 1>&2
+ ICONVLIB=-liconv
+ ;;
+*)
+ if test "$liteonly" = yes ; then
+ { echo "configure: error: you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support." 1>&2; exit 1; }
+ fi
+ ICONVLIB=$iconv
+ ;;
+esac
+
+
+# Check whether --with-iconv-sofile or --without-iconv-sofile was given.
+if test "${with_iconv_sofile+set}" = set; then
+ withval="$with_iconv_sofile"
+ iconv_file=$withval
+else
+ iconv_file=guess
+fi
+
+ICONVSOFILE=
+case "$iconv_file" in
+no)
+ ICONVSOFILE=none
+ ;;
+yes)
+ if test "$liteonly" = yes ; then
+ { echo "configure: error: you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support." 1>&2; exit 1; }
+ fi
+ { echo "configure: error: You must supply PATH to --with-iconv-sofile option." 1>&2; exit 1; }
+ ;;
+guess)
+ if test "$liteonly" != yes ; then
+ if test "$ICONVLIB" = ""; then
+ ICONVSOFILE=none
+ else
+ echo $ac_n "checking pathname of iconv shared library""... $ac_c" 1>&6
+echo "configure:870: checking pathname of iconv shared library" >&5
+ ic_libdir=
+ ic_libname=
+ case "$host" in
+ *-hpux*)
+ SO=sl
+ ;;
+ *)
+ SO=so
+ ;;
+ esac
+ for arg in $ICONVLIB; do
+ case "$arg" in
+ -L*) ic_libdir="$ic_libdir `echo $arg | sed s/-L//`" ;;
+ -l*) ic_libname=`echo $arg | sed s/-l//` ;;
+ /*.$SO*) ICONVSOFILE=$arg ;;
+ esac
+ done
+ if test "$ICONVSOFILE" = ""; then
+ if test "$ic_libname" = ""; then
+ echo "$ac_t""unknown" 1>&6
+ echo "configure: warning: use --with-iconv-sofile for specifying iconv shared library file" 1>&2
+ ICONVSOFILE=none
+ else
+ if test "$ic_libdir" = ""; then
+ # Standard (and semi-standard) library directories
+ ic_libdir="/lib /usr/lib /usr/local/lib"
+ fi
+ for dir in $ic_libdir; do
+ ICONVSOFILE=`ls -r $dir/lib$ic_libname.$SO* 2>/dev/null | head -1`
+ if test "$ICONVSOFILE" != ""; then
+ break
+ fi
+ done
+ if test "$ICONVSOFILE" != ""; then
+ echo "$ac_t""$ICONVSOFILE" 1>&6
+ else
+ echo "$ac_t""unknown" 1>&6
+ echo "configure: warning: use --with-iconv-sofile for specifying iconv shared library file" 1>&2
+ ICONVSOFILE=none
+ fi
+ fi
+ fi
+ fi
+ else
+ ICONVSOFILE=none
+ fi
+ ;;
+*)
+ if test "$liteonly" = yes ; then
+ { echo "configure: error: you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support." 1>&2; exit 1; }
+ fi
+ ICONVSOFILE=$iconv_file
+ ;;
+esac
+
+
+PRELOAD_VAR="LD_PRELOAD"
+PRELOAD_SEP=":"
+PRELOAD_LAST=""
+case "$host" in
+*-solaris*)
+ PRELOAD_SEP=" "
+ ;;
+*-linux*)
+ PRELOAD_SEP=" "
+ ;;
+*-osf*)
+ PRELOAD_VAR="_RLD_LIST"
+ PRELOAD_LAST=":DEFAULT"
+ ;;
+*-netbsd*)
+ if test -x /usr/bin/file -a -x /usr/bin/grep ; then
+ case "`/usr/bin/file /usr/bin/grep`" in
+ *ELF*)
+ PRELOAD_SEP=" "
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:959: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:989: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1040: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:1072: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 1083 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:1088: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:1114: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:1119: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1128: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1147: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1190: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+else
+ enable_shared=yes
+fi
+
+# Check whether --enable-static or --disable-static was given.
+if test "${enable_static+set}" = set; then
+ enableval="$enable_static"
+ p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+else
+ enable_static=yes
+fi
+
+# Check whether --enable-fast-install or --disable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then
+ enableval="$enable_fast_install"
+ p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+else
+ enable_fast_install=yes
+fi
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:1312: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1332: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then
+ withval="$with_gnu_ld"
+ test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
+echo "configure:1371: checking for ld used by GCC" >&5
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
+echo "configure:1395: checking for GNU ld" >&5
+else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+echo "configure:1398: checking for non-GNU ld" >&5
+fi
+if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ ac_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+ echo "$ac_t""$LD" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
+echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
+echo "configure:1433: checking if the linker ($LD) is GNU ld" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ ac_cv_prog_gnu_ld=yes
+else
+ ac_cv_prog_gnu_ld=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6
+
+
+echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
+echo "configure:1449: checking for BSD-compatible nm" >&5
+if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ ac_cv_path_NM="$NM"
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -B"
+ break
+ elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ ac_cv_path_NM="$ac_dir/nm -p"
+ break
+ else
+ ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi
+fi
+
+NM="$ac_cv_path_NM"
+echo "$ac_t""$NM" 1>&6
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:1485: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+ rm -f conftestdata
+ ac_cv_prog_LN_S="ln -s"
+else
+ ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+case "$target" in
+NONE) lt_target="$host" ;;
+*) lt_target="$target" ;;
+esac
+
+# Check for any special flags to pass to ltconfig.
+libtool_flags="--cache-file=$cache_file"
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+
+
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then
+ enableval="$enable_libtool_lock"
+ :
+fi
+
+test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock"
+test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$lt_target" in
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '#line 1534 "configure"' > conftest.$ac_ext
+ if { (eval echo configure:1535: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ case "`/usr/bin/file conftest.o`" in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
+echo "configure:1556: checking whether the C compiler needs -belf" >&5
+if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1561 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1568: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ lt_cv_cc_needs_belf=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ lt_cv_cc_needs_belf=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$lt_cv_cc_needs_belf" 1>&6
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+
+
+esac
+
+
+# Save cache, so that ltconfig can load it
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+
+# Actually configure libtool. ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
+LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \
+DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $lt_target \
+|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; }
+
+# Reload cache, that may have been modified by ltconfig
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+
+
+for ac_prog in perl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1675: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$PERL" in
+ /*)
+ ac_cv_path_PERL="$PERL" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_PERL="$PERL" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_PERL="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+PERL="$ac_cv_path_PERL"
+if test -n "$PERL"; then
+ echo "$ac_t""$PERL" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$PERL" && break
+done
+test -n "$PERL" || PERL="perl"
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1713: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1728 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1734: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1745 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1751: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 1762 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1768: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+for ac_hdr in unistd.h locale.h langinfo.h pwd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1796: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1801 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1806: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+if test "$install_runidn" = yes ; then
+ for ac_hdr in dlfcn.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1837: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1842 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1847: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+saved_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $ICONVINC"
+if test "$liteonly" != yes ; then
+ ac_safe=`echo "iconv.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for iconv.h""... $ac_c" 1>&6
+echo "configure:1880: checking for iconv.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1885 "configure"
+#include "confdefs.h"
+#include <iconv.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1890: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+{ echo "configure: error: iconv.h doesn't exist" 1>&2; exit 1; }
+fi
+
+fi
+CPPFLAGS=$saved_CPPFLAGS
+
+echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:1916: checking for uid_t in sys/types.h" >&5
+if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1921 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "uid_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_uid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_type_uid_t" 1>&6
+if test $ac_cv_type_uid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define uid_t int
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define gid_t int
+EOF
+
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1950: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1955 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1963: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1980 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1998 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2019 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:2030: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for BOOL""... $ac_c" 1>&6
+echo "configure:2054: checking for BOOL" >&5
+if eval "test \"`echo '$''{'ac_cv_type_BOOL'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2059 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])BOOL[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_BOOL=yes
+else
+ rm -rf conftest*
+ ac_cv_type_BOOL=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_BOOL" 1>&6
+if test $ac_cv_type_BOOL = no; then
+ cat >> confdefs.h <<\EOF
+#define BOOL int
+EOF
+
+fi
+
+
+if test "$install_runidn" = yes ; then
+ echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+echo "configure:2089: checking for socket in -lsocket" >&5
+ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2097 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:2108: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lsocket $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking for inet_addr in -lnsl""... $ac_c" 1>&6
+echo "configure:2136: checking for inet_addr in -lnsl" >&5
+ac_lib_var=`echo nsl'_'inet_addr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2144 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char inet_addr();
+
+int main() {
+inet_addr()
+; return 0; }
+EOF
+if { (eval echo configure:2155: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lnsl $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "configure:2183: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2191 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo configure:2202: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+ LIBS="-ldl $LIBS"
+ LIBDL="-ldl"
+ cat >> confdefs.h <<\EOF
+#define HAVE_LIBDL 1
+EOF
+
+
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+for ac_func in vsnprintf setvbuf setlocale nl_langinfo memmove bcopy setenv \
+ unsetenv
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2236: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2241 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2264: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+if test "$install_runidn" = yes ; then
+ for ac_func in gethostbyname gethostbyname2 gethostbyaddr
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2292: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2297 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ for ac_func in gethostbyname_r gethostbyname2_r gethostbyaddr_r
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2347: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2352 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2375: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+ find_gethost_r=yes
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ for ac_func in getipnodebyname getipnodebyaddr freehostent
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2402: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2407 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2430: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ for ac_func in getaddrinfo freeaddrinfo getnameinfo
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2457: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2462 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2485: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ for ac_func in dlopen dlsym
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2512: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2517 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2540: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+if test "$install_runidn" = yes ; then
+ echo $ac_n "checking flavor of gethostbyaddr""... $ac_c" 1>&6
+echo "configure:2568: checking flavor of gethostbyaddr" >&5
+if eval "test \"`echo '$''{'ac_cv_flavor_gethostbyaddr'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_flavor_gethostbyaddr=unknown
+ if test "$cross_compiling" = yes; then
+ ac_cv_flavor_gethostbyaddr=unknown
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2577 "configure"
+#include "confdefs.h"
+
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
+ return NULL;
+ }
+ int main() {
+ (void)gethostbyaddr(NULL, 0, 0);
+ return 0;
+ }
+
+EOF
+if { (eval echo configure:2593: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_flavor_gethostbyaddr=glibc2_2
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -fr conftest*
+fi
+
+ if test "$cross_compiling" = yes; then
+ ac_cv_flavor_gethostbyaddr=unknown
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2607 "configure"
+#include "confdefs.h"
+
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ struct hostent *gethostbyaddr(const char *addr, size_t len, int type) {
+ return NULL;
+ }
+ int main() {
+ (void)gethostbyaddr(NULL, 0, 0);
+ return 0;
+ }
+
+EOF
+if { (eval echo configure:2623: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_flavor_gethostbyaddr=glibc
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -fr conftest*
+fi
+
+ if test "$cross_compiling" = yes; then
+ ac_cv_flavor_gethostbyaddr=unknown
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2637 "configure"
+#include "confdefs.h"
+
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ struct hostent *gethostbyaddr(const char *addr, int len, int type) {
+ return NULL;
+ }
+ int main() {
+ (void)gethostbyaddr(NULL, 0, 0);
+ return 0;
+ }
+
+EOF
+if { (eval echo configure:2653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_flavor_gethostbyaddr=traditional
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -fr conftest*
+fi
+
+ if test "$ac_cv_func_gethostbyaddr" = no ; then
+ ac_cv_flavor_gethostbyaddr=none
+ fi
+fi
+
+echo "$ac_t""$ac_cv_flavor_gethostbyaddr" 1>&6
+
+ case "$ac_cv_flavor_gethostbyaddr" in
+ glibc2_2)
+ ac_cv_type_ghba_addr_t='const void *'
+ ac_cv_type_ghba_addrlen_t='socklen_t'
+ ;;
+ glibc)
+ ac_cv_type_ghba_addr_t='const char *'
+ ac_cv_type_ghba_addrlen_t='size_t'
+ ;;
+ traditional | none)
+ ac_cv_type_ghba_addr_t='const char *'
+ ac_cv_type_ghba_addrlen_t='int'
+ ;;
+ *)
+ { echo "configure: error: can't build runidn, since parameter type list of gethostbyaddr() is unknown to configure." 1>&2; exit 1; }
+ ;;
+ esac
+ cat >> confdefs.h <<EOF
+#define GHBA_ADDR_T $ac_cv_type_ghba_addr_t
+EOF
+
+ cat >> confdefs.h <<EOF
+#define GHBA_ADDRLEN_T $ac_cv_type_ghba_addrlen_t
+EOF
+
+
+ echo $ac_n "checking flavor of getnameinfo""... $ac_c" 1>&6
+echo "configure:2697: checking flavor of getnameinfo" >&5
+if eval "test \"`echo '$''{'ac_cv_flavor_getnameinfo'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_flavor_getnameinfo=unknown
+ if test "$cross_compiling" = yes; then
+ ac_cv_flavor_getnameinfo=unknown
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2706 "configure"
+#include "confdefs.h"
+
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
+ socklen_t hostlen, char *serv, socklen_t servlen,
+ unsigned int flags) {
+ return NULL;
+ }
+ int main() {
+ (void)getnameinfo(NULL, 0, NULL, 0, NULL, 0, 0);
+ return 0;
+ }
+
+EOF
+if { (eval echo configure:2724: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_flavor_getnameinfo=glibc2_2_2
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -fr conftest*
+fi
+
+ if test "$cross_compiling" = yes; then
+ ac_cv_flavor_getnameinfo=unknown
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2738 "configure"
+#include "confdefs.h"
+
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
+ socklen_t hostlen, char *serv, socklen_t servlen,
+ int flags) {
+ return NULL;
+ }
+ int main() {
+ (void)getnameinfo(NULL, 0, NULL, 0, NULL, 0, 0);
+ return 0;
+ }
+
+EOF
+if { (eval echo configure:2756: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_flavor_getnameinfo=rfc2553bis_03
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -fr conftest*
+fi
+
+ if test "$cross_compiling" = yes; then
+ ac_cv_flavor_getnameinfo=unknown
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2770 "configure"
+#include "confdefs.h"
+
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
+ size_t hostlen, char *serv, size_t servlen, int flags) {
+ return NULL;
+ }
+ int main() {
+ (void)getnameinfo(NULL, 0, NULL, 0, NULL, 0, 0);
+ return 0;
+ }
+
+EOF
+if { (eval echo configure:2787: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_flavor_getnameinfo=rfc2553
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -fr conftest*
+fi
+
+ if test "$cross_compiling" = yes; then
+ ac_cv_flavor_getnameinfo=unknown
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2801 "configure"
+#include "confdefs.h"
+
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
+ size_t hostlen, char *serv, size_t servlen, int flags) {
+ return NULL;
+ }
+ int main() {
+ (void)getnameinfo(NULL, 0, NULL, 0, NULL, 0, 0);
+ return 0;
+ }
+
+EOF
+if { (eval echo configure:2818: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_flavor_getnameinfo=rfc2133
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -fr conftest*
+fi
+
+ if test "$ac_cv_func_getnameinfo" = no ; then
+ ac_cv_flavor_getnameinfo=none
+ fi
+fi
+
+echo "$ac_t""$ac_cv_flavor_getnameinfo" 1>&6
+
+ case "$ac_cv_flavor_getnameinfo" in
+ glibc2_2_2)
+ ac_cv_type_gni_salen_t='socklen_t'
+ ac_cv_type_gni_hostlen_t='socklen_t'
+ ac_cv_type_gni_servlen_t='socklen_t'
+ ac_cv_type_gni_flags_t='unsigned int'
+ ;;
+ rfc2553bis_03)
+ ac_cv_type_gni_salen_t='socklen_t'
+ ac_cv_type_gni_hostlen_t='socklen_t'
+ ac_cv_type_gni_servlen_t='socklen_t'
+ ac_cv_type_gni_flags_t='int'
+ ;;
+ rfc2553)
+ ac_cv_type_gni_salen_t='socklen_t'
+ ac_cv_type_gni_hostlen_t='size_t'
+ ac_cv_type_gni_servlen_t='size_t'
+ ac_cv_type_gni_flags_t='int'
+ ;;
+ rfc2133 | none)
+ ac_cv_type_gni_salen_t='size_t'
+ ac_cv_type_gni_hostlen_t='size_t'
+ ac_cv_type_gni_servlen_t='size_t'
+ ac_cv_type_gni_flags_t='int'
+ ;;
+ *)
+ { echo "configure: error: can't build runidn, since parameter type list of getnameinfo() is unknown to configure." 1>&2; exit 1; }
+ esac
+ cat >> confdefs.h <<EOF
+#define GNI_SALEN_T $ac_cv_type_gni_salen_t
+EOF
+
+ cat >> confdefs.h <<EOF
+#define GNI_HOSTLEN_T $ac_cv_type_gni_hostlen_t
+EOF
+
+ cat >> confdefs.h <<EOF
+#define GNI_SERVLEN_T $ac_cv_type_gni_servlen_t
+EOF
+
+ cat >> confdefs.h <<EOF
+#define GNI_FLAGS_T $ac_cv_type_gni_flags_t
+EOF
+
+fi
+
+if test "$find_gethost_r" = yes; then
+ echo $ac_n "checking flavor of gethostbyname_r""... $ac_c" 1>&6
+echo "configure:2883: checking flavor of gethostbyname_r" >&5
+if eval "test \"`echo '$''{'ac_cv_flavor_gethost_r'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_flavor_gethost_r=sun
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2891 "configure"
+#include "confdefs.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+int main()
+{
+ int err = 0;
+ struct hostent hebuf, *hp;
+ char buf[10];
+ /* Try resolving a invalid name using glibc flavor. */
+ (void)gethostbyname_r("@#!", &hebuf, buf, sizeof(buf), &hp, &err);
+ if (err != 0)
+ return 0; /* glibc flavor */
+ else
+ return 1; /* Sun flavor */
+}
+
+EOF
+if { (eval echo configure:2913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_flavor_gethost_r=glibc
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_flavor_gethost_r=sun
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_flavor_gethost_r" 1>&6
+ if test "$ac_cv_flavor_gethost_r" = "glibc"; then
+ cat >> confdefs.h <<\EOF
+#define GETHOST_R_GLIBC_FLAVOR 1
+EOF
+
+ fi
+fi
+
+
+echo $ac_n "checking for libc shared object""... $ac_c" 1>&6
+echo "configure:2938: checking for libc shared object" >&5
+shobj_name=libc
+shobj_path=
+case "$host" in
+*-hpux*)
+ SOEXT=sl
+ ;;
+*)
+ SOEXT=so
+ ;;
+esac
+for shobj_libdir in /lib /usr/lib; do
+ if test -f $shobj_libdir/$shobj_name.$SOEXT; then
+ shobj_path=$shobj_libdir/$shobj_name.$SOEXT
+ else
+ shobj_path=`ls -r $shobj_libdir/$shobj_name.$SOEXT* 2>/dev/null | head -1`
+ if test "$shobj_path" != "" -a -f "$shobj_path"; then
+ :
+ else
+ shobj_path=
+ fi
+ fi
+ if test "$shobj_path" != ""; then
+ echo "$ac_t""$shobj_path" 1>&6
+ shobj_pathsymbol=SOPATH_`echo $shobj_name | sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $shobj_pathsymbol "$shobj_path"
+EOF
+
+ break
+ fi
+done
+if test "$shobj_path" = ""; then
+ echo "$ac_t""no" 1>&6
+fi
+
+if test "$install_runidn" = yes ; then
+
+echo $ac_n "checking for libnsl shared object""... $ac_c" 1>&6
+echo "configure:2977: checking for libnsl shared object" >&5
+shobj_name=libnsl
+shobj_path=
+case "$host" in
+*-hpux*)
+ SOEXT=sl
+ ;;
+*)
+ SOEXT=so
+ ;;
+esac
+for shobj_libdir in /lib /usr/lib; do
+ if test -f $shobj_libdir/$shobj_name.$SOEXT; then
+ shobj_path=$shobj_libdir/$shobj_name.$SOEXT
+ else
+ shobj_path=`ls -r $shobj_libdir/$shobj_name.$SOEXT* 2>/dev/null | head -1`
+ if test "$shobj_path" != "" -a -f "$shobj_path"; then
+ :
+ else
+ shobj_path=
+ fi
+ fi
+ if test "$shobj_path" != ""; then
+ echo "$ac_t""$shobj_path" 1>&6
+ shobj_pathsymbol=SOPATH_`echo $shobj_name | sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $shobj_pathsymbol "$shobj_path"
+EOF
+
+ break
+ fi
+done
+if test "$shobj_path" = ""; then
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+if test "$liteonly" != yes ; then
+ echo $ac_n "checking for iconv""... $ac_c" 1>&6
+echo "configure:3017: checking for iconv" >&5
+ saved_CPPFLAGS=$CPPFLAGS
+ saved_LIBS=$LIBS
+ CPPFLAGS="$CPPFLAGS $ICONVINC"
+ LIBS="$LIBS $ICONVLIB"
+ cat > conftest.$ac_ext <<EOF
+#line 3023 "configure"
+#include "confdefs.h"
+
+ #include <iconv.h>
+
+int main() {
+
+ iconv_t i;
+ i = iconv_open("ISO-8859-1", "UTF-8");
+
+; return 0; }
+EOF
+if { (eval echo configure:3035: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ iconv_try_link=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ iconv_try_link=no
+fi
+rm -f conftest*
+ LIBS=$saved_LIBS
+ CPPFLAGS=$saved_CPPFLAGS
+ echo "$ac_t""$iconv_try_link" 1>&6
+ if test "$iconv_try_link" = no ; then
+ { echo "configure: error: iconv function not available" 1>&2; exit 1; }
+ fi
+fi
+
+if test "$liteonly" != yes ; then
+ echo $ac_n "checking for codeset name $UTF8_NAME""... $ac_c" 1>&6
+echo "configure:3055: checking for codeset name $UTF8_NAME" >&5
+ saved_CPPFLAGS=$CPPFLAGS
+ saved_LIBS=$LIBS
+ CPPFLAGS="$CPPFLAGS $ICONVINC"
+ LIBS="$LIBS $ICONVLIB"
+ if test "$cross_compiling" = yes; then
+ utf8_name_valid=unknown
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3064 "configure"
+#include "confdefs.h"
+
+ #include <stddef.h>
+ #include <stdlib.h>
+ #include <iconv.h>
+ #define UTF8_NAME "$UTF8_NAME"
+ #define ICONV_FAIL ((iconv_t)(-1))
+ /* Check if the codeset name UTF8_NAME is valid by performing iconv_open(). */
+ int main() {
+ int i;
+ /* list of codeset names likely to exist */
+ static char *codeset[] = {
+ "ASCII", "ISO-8859-1", "ISO8859-1", "iso8859_1", "8859-1",
+ "Shift_JIS", "SJIS", "sjis", NULL,
+ };
+
+ /* First try null conversion. */
+ if (iconv_open(UTF8_NAME, UTF8_NAME) != ICONV_FAIL) return 0;
+
+ /* Unfortunately, above check fails on certain systems, such as Solaris. */
+ for (i = 0; codeset[i] != NULL; i++) {
+ if (iconv_open(UTF8_NAME, codeset[i]) != ICONV_FAIL) return 0;
+ }
+ return 1;
+ }
+
+EOF
+if { (eval echo configure:3092: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ utf8_name_valid=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ utf8_name_valid=no
+fi
+rm -fr conftest*
+fi
+
+ LIBS=$saved_LIBS
+ CPPFLAGS=$saved_CPPFLAGS
+ echo "$ac_t""$utf8_name_valid" 1>&6
+fi
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile
+ include/Makefile
+ include/idn/Makefile
+ include/mdn/Makefile
+ lib/Makefile
+ man/Makefile
+ tools/Makefile
+ tools/idnconv/Makefile
+ tools/runidn/Makefile
+ tools/runidn/runidn
+ map/Makefile
+ lib/tests/Makefile
+ include/config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@COMPAT_TRUE@%$COMPAT_TRUE%g
+s%@COMPAT_FALSE@%$COMPAT_FALSE%g
+s%@UTF8_NAME@%$UTF8_NAME%g
+s%@LITEONLY_TRUE@%$LITEONLY_TRUE%g
+s%@LITEONLY_FALSE@%$LITEONLY_FALSE%g
+s%@RUNIDN_TRUE@%$RUNIDN_TRUE%g
+s%@RUNIDN_FALSE@%$RUNIDN_FALSE%g
+s%@ICONVINC@%$ICONVINC%g
+s%@ICONVLIB@%$ICONVLIB%g
+s%@ICONVSOFILE@%$ICONVSOFILE%g
+s%@PRELOAD_VAR@%$PRELOAD_VAR%g
+s%@PRELOAD_SEP@%$PRELOAD_SEP%g
+s%@PRELOAD_LAST@%$PRELOAD_LAST%g
+s%@CC@%$CC%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@RANLIB@%$RANLIB%g
+s%@LN_S@%$LN_S%g
+s%@LIBTOOL@%$LIBTOOL%g
+s%@PERL@%$PERL%g
+s%@CPP@%$CPP%g
+s%@LIBDL@%$LIBDL%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile
+ include/Makefile
+ include/idn/Makefile
+ include/mdn/Makefile
+ lib/Makefile
+ man/Makefile
+ tools/Makefile
+ tools/idnconv/Makefile
+ tools/runidn/Makefile
+ tools/runidn/runidn
+ map/Makefile
+ lib/tests/Makefile
+"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="include/config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/contrib/idn/idnkit-1.0-src/configure.in b/contrib/idn/idnkit-1.0-src/configure.in
new file mode 100644
index 0000000..97a954e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/configure.in
@@ -0,0 +1,711 @@
+dnl $Id: configure.in,v 1.1.1.1 2003/06/04 00:25:25 marka Exp $
+dnl Process this file with autoconf to produce a configure script.
+dnl
+dnl Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+dnl
+dnl By using this file, you agree to the terms and conditions set forth bellow.
+dnl
+dnl LICENSE TERMS AND CONDITIONS
+dnl
+dnl The following License Terms and Conditions apply, unless a different
+dnl license is obtained from Japan Network Information Center ("JPNIC"),
+dnl a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+dnl Chiyoda-ku, Tokyo 101-0047, Japan.
+dnl
+dnl 1. Use, Modification and Redistribution (including distribution of any
+dnl modified or derived work) in source and/or binary forms is permitted
+dnl under this License Terms and Conditions.
+dnl
+dnl 2. Redistribution of source code must retain the copyright notices as they
+dnl appear in each source code file, this License Terms and Conditions.
+dnl
+dnl 3. Redistribution in binary form must reproduce the Copyright Notice,
+dnl this License Terms and Conditions, in the documentation and/or other
+dnl materials provided with the distribution. For the purposes of binary
+dnl distribution the "Copyright Notice" refers to the following language:
+dnl "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+dnl
+dnl 4. The name of JPNIC may not be used to endorse or promote products
+dnl derived from this Software without specific prior written approval of
+dnl JPNIC.
+dnl
+dnl 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+dnl PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+dnl FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+dnl CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+dnl SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+dnl BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+dnl WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+dnl OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+dnl ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+AC_INIT(include/idn/converter.h)
+
+AC_CANONICAL_HOST
+
+debug=no
+AC_ARG_ENABLE(debug,
+[ --enable-debug enable debug codes [default=no]],
+ debug=$enableval)
+case "$debug" in
+yes)
+ CFLAGS="$CFLAGS -DDEBUG"
+ ;;
+esac
+
+mdnkit_compat=no
+COMPAT_TRUE="#"
+COMPAT_FALSE=
+AC_ARG_ENABLE(mdnkit-compat,
+[ --enable-mdnkit-compat enable mDNkit compatibility mode [default=no]],
+ mdnkit_compat=$enableval)
+case "$mdnkit_compat" in
+yes)
+ COMPAT_TRUE=
+ COMPAT_FALSE="#"
+ AC_DEFINE(ENABLE_MDNKIT_COMPAT, 1,
+ [Define if --enable-mdnkit-compat is specified])
+ ;;
+no)
+ ;;
+*)
+ AC_MSG_ERROR([You must specify yes or no to --enable-runidn option.])
+ ;;
+esac
+AC_SUBST(COMPAT_TRUE)
+AC_SUBST(COMPAT_FALSE)
+
+extraace=no
+AC_ARG_ENABLE(extra-ace,
+[ --enable-extra-ace enable additional ACE converters. [default=no]],
+ extraace=$enableval)
+case "$extraace" in
+no)
+ ;;
+yes)
+ AC_DEFINE(IDN_EXTRA_ACE, 1,
+ [Define if you want additional ACE converters compiled in.])
+ ;;
+*)
+ AC_MSG_ERROR([You must specify yes or no to --enable-extra-ace option.])
+ ;;
+esac
+
+UTF8_NAME=no
+AC_ARG_WITH(utf8,
+[ --with-utf8=NAME codeset name for UTF-8 encoding [UTF-8]],
+ UTF8_NAME=$withval)
+case "$UTF8_NAME" in
+no)
+ UTF8_NAME=UTF-8
+ ;;
+yes)
+ AC_MSG_ERROR([You must specify NAME to --with-utf8 option.])
+ ;;
+*)
+ AC_DEFINE_UNQUOTED(IDN_UTF8_ENCODING_NAME, "$UTF8_NAME",
+ [Define if your iconv() does not accept "UTF-8" as the codeset name for utf-8.])
+ ;;
+esac
+AC_SUBST(UTF8_NAME)
+
+liteonly=no
+LITEONLY_TRUE="#"
+LITEONLY_FALSE=
+AC_ARG_ENABLE(liteonly,
+[ --enable-liteonly compile and install lite library only [default=no]],
+ liteonly=$enableval)
+case "$liteonly" in
+no)
+ ;;
+yes)
+ if test "$install_runidn" = yes ; then
+ AC_MSG_ERROR([you can't set value \"yes\" to --enable-runidn and --enable-liteonly simultaneously, because runidn requires iconv support of generic libidnkit.])
+ fi
+ LITEONLY_TRUE=
+ LITEONLY_FALSE="#"
+ ;;
+*)
+ AC_MSG_ERROR([You must specify yes or no to --enable-liteonly option.])
+ ;;
+esac
+AC_SUBST(LITEONLY_TRUE)
+AC_SUBST(LITEONLY_FALSE)
+
+install_runidn=no
+RUNIDN_TRUE="#"
+RUNIDN_FALSE=
+AC_ARG_ENABLE(runidn,
+[ --enable-runidn compile and install runidn [default=no]],
+ install_runidn=$enableval)
+case "$install_runidn" in
+no)
+ ;;
+yes)
+ if test "$liteonly" = yes ; then
+ AC_MSG_ERROR([you can't set value \"yes\" to --enable-runidn and --enable-liteonly simultaneously, because runidn requires iconv support of generic libidnkit.])
+ fi
+ RUNIDN_TRUE=
+ RUNIDN_FALSE="#"
+ ;;
+*)
+ AC_MSG_ERROR([You must specify yes or no to --enable-runidn option.])
+ ;;
+esac
+AC_SUBST(RUNIDN_TRUE)
+AC_SUBST(RUNIDN_FALSE)
+
+ICONVINC=
+ICONVLIB=
+
+libiconv=unspec
+AC_ARG_WITH(libiconv,
+[ --with-libiconv=IPREFIX GNU libiconv are installed in IPREFIX [PREFIX]],
+ libiconv=$withval)
+case "$libiconv" in
+unspec)
+ ;;
+no)
+ ICONVINC=
+ ICONVLIB=
+ ;;
+yes)
+ if test "$liteonly" = yes ; then
+ AC_MSG_ERROR([you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support.])
+ fi
+ if test X$prefix = XNONE ; then
+ libiconv=$ac_default_prefix
+ else
+ libiconv=$prefix
+ fi
+ ICONVINC="-I$libiconv/include"
+ ICONVLIB="-L$libiconv/lib -R$libiconv/lib -liconv"
+ ;;
+*)
+ if test "$liteonly" = yes ; then
+ AC_MSG_ERROR([you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support.])
+ fi
+ ICONVINC="-I$libiconv/include"
+ ICONVLIB="-L$libiconv/lib -R$libiconv/lib -liconv"
+ ;;
+esac
+
+iconv_include=unspec
+AC_ARG_WITH(iconv-include,
+[ --with-iconv-include=DIR iconv include files are in DIR []],
+ iconv_include=$withval)
+case "$iconv_include" in
+unspec)
+ ;;
+no)
+ ICONVINC=
+ ;;
+yes)
+ if test "$liteonly" = yes ; then
+ AC_MSG_ERROR([you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support.])
+ fi
+ AC_MSG_WARN([You must supply DIR to --with-iconv-include option.
+ Ignored.])
+ ICONVINC=
+ ;;
+*)
+ if test "$liteonly" = yes ; then
+ AC_MSG_ERROR([you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support.])
+ fi
+ ICONVINC="-I$iconv_include"
+ ;;
+esac
+
+if test "X$ICONVINC" != X ; then
+ iconv_include="`echo X$ICONVINC | sed -e 's/^X-I//'`"
+ if test ! -f "$iconv_include/iconv.h" ; then
+ AC_MSG_ERROR([iconv.h doesn't exist in $iconv_include])
+ fi
+fi
+
+AC_SUBST(ICONVINC)
+
+iconv=unspec
+AC_ARG_WITH(iconv,
+[ --with-iconv=LIB special library for iconv []],
+ iconv=$withval)
+case "$iconv" in
+unspec)
+ ;;
+no)
+ ICONVLIB=
+ ;;
+yes)
+ if test "$liteonly" = yes ; then
+ AC_MSG_ERROR([you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support.])
+ fi
+ AC_MSG_WARN([You must supply LIB to --with-iconv option.
+ -liconv is assumed.])
+ ICONVLIB=-liconv
+ ;;
+*)
+ if test "$liteonly" = yes ; then
+ AC_MSG_ERROR([you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support.])
+ fi
+ ICONVLIB=$iconv
+ ;;
+esac
+AC_SUBST(ICONVLIB)
+
+AC_ARG_WITH(iconv-sofile,
+[ --with-iconv-sofile=PATH shared library file for libiconv []],
+ iconv_file=$withval, iconv_file=guess)
+ICONVSOFILE=
+case "$iconv_file" in
+no)
+ ICONVSOFILE=none
+ ;;
+yes)
+ if test "$liteonly" = yes ; then
+ AC_MSG_ERROR([you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support.])
+ fi
+ AC_MSG_ERROR([You must supply PATH to --with-iconv-sofile option.])
+ ;;
+guess)
+ if test "$liteonly" != yes ; then
+ if test "$ICONVLIB" = ""; then
+ ICONVSOFILE=none
+ else
+ AC_MSG_CHECKING(pathname of iconv shared library)
+ ic_libdir=
+ ic_libname=
+ case "$host" in
+ *-hpux*)
+ SO=sl
+ ;;
+ *)
+ SO=so
+ ;;
+ esac
+ for arg in $ICONVLIB; do
+ case "$arg" in
+ -L*) ic_libdir="$ic_libdir `echo $arg | sed s/-L//`" ;;
+ -l*) ic_libname=`echo $arg | sed s/-l//` ;;
+ /*.$SO*) ICONVSOFILE=$arg ;;
+ esac
+ done
+ if test "$ICONVSOFILE" = ""; then
+ if test "$ic_libname" = ""; then
+ AC_MSG_RESULT(unknown)
+ AC_MSG_WARN([use --with-iconv-sofile for specifying iconv shared library file])
+ ICONVSOFILE=none
+ else
+ if test "$ic_libdir" = ""; then
+ # Standard (and semi-standard) library directories
+ ic_libdir="/lib /usr/lib /usr/local/lib"
+ fi
+ for dir in $ic_libdir; do
+ ICONVSOFILE=`ls -r $dir/lib$ic_libname.$SO* 2>/dev/null | head -1`
+ if test "$ICONVSOFILE" != ""; then
+ break
+ fi
+ done
+ if test "$ICONVSOFILE" != ""; then
+ AC_MSG_RESULT($ICONVSOFILE)
+ else
+ AC_MSG_RESULT(unknown)
+ AC_MSG_WARN([use --with-iconv-sofile for specifying iconv shared library file])
+ ICONVSOFILE=none
+ fi
+ fi
+ fi
+ fi
+ else
+ ICONVSOFILE=none
+ fi
+ ;;
+*)
+ if test "$liteonly" = yes ; then
+ AC_MSG_ERROR([you can't set iconv options at all when you set value \"yes\" to --enable-liteonly, because lite library does not have iconv support.])
+ fi
+ ICONVSOFILE=$iconv_file
+ ;;
+esac
+AC_SUBST(ICONVSOFILE)
+
+dnl Figure out preload stuff.
+PRELOAD_VAR="LD_PRELOAD"
+PRELOAD_SEP=":"
+PRELOAD_LAST=""
+case "$host" in
+*-solaris*)
+ PRELOAD_SEP=" "
+ ;;
+*-linux*)
+ PRELOAD_SEP=" "
+ ;;
+*-osf*)
+ PRELOAD_VAR="_RLD_LIST"
+ PRELOAD_LAST=":DEFAULT"
+ ;;
+*-netbsd*)
+ if test -x /usr/bin/file -a -x /usr/bin/grep ; then
+ case "`/usr/bin/file /usr/bin/grep`" in
+ *ELF*)
+ PRELOAD_SEP=" "
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+AC_SUBST(PRELOAD_VAR)
+AC_SUBST(PRELOAD_SEP)
+AC_SUBST(PRELOAD_LAST)
+
+dnl Checks for standard tools.
+AC_PROG_CC
+AC_PROG_INSTALL
+AM_PROG_LIBTOOL
+
+AC_PATH_PROGS(PERL, perl, perl)
+
+dnl Checks for header files.
+AC_CHECK_HEADERS(unistd.h locale.h langinfo.h pwd.h)
+if test "$install_runidn" = yes ; then
+ AC_CHECK_HEADERS(dlfcn.h)
+fi
+
+saved_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$CPPFLAGS $ICONVINC"
+if test "$liteonly" != yes ; then
+ AC_CHECK_HEADER(iconv.h, , [AC_MSG_ERROR([iconv.h doesn't exist])])
+fi
+CPPFLAGS=$saved_CPPFLAGS
+
+dnl Checks for data types.
+AC_TYPE_UID_T
+dnl for dnsproxy.
+AC_CHECK_TYPE(BOOL, int)
+
+dnl Checks for libraries.
+if test "$install_runidn" = yes ; then
+ AC_CHECK_LIB(socket, socket)
+ AC_CHECK_LIB(nsl, inet_addr)
+ AC_CHECK_LIB(dl, dlopen, [
+ LIBS="-ldl $LIBS"
+ LIBDL="-ldl"
+ AC_DEFINE(HAVE_LIBDL, 1, [Define if you have the dl library (-ldl).])
+ AC_SUBST(LIBDL)
+ ])
+fi
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS(vsnprintf setvbuf setlocale nl_langinfo memmove bcopy setenv \
+ unsetenv)
+if test "$install_runidn" = yes ; then
+ AC_CHECK_FUNCS(gethostbyname gethostbyname2 gethostbyaddr)
+ AC_CHECK_FUNCS(gethostbyname_r gethostbyname2_r gethostbyaddr_r, find_gethost_r=yes)
+ AC_CHECK_FUNCS(getipnodebyname getipnodebyaddr freehostent)
+ AC_CHECK_FUNCS(getaddrinfo freeaddrinfo getnameinfo)
+ AC_CHECK_FUNCS(dlopen dlsym)
+fi
+
+if test "$install_runidn" = yes ; then
+dnl Checks the flavor of gethostbyaddr* functions.
+ AC_CACHE_CHECK(flavor of gethostbyaddr, ac_cv_flavor_gethostbyaddr,
+ [ac_cv_flavor_gethostbyaddr=unknown
+ AC_TRY_RUN(
+ [
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) {
+ return NULL;
+ }
+ int main() {
+ (void)gethostbyaddr(NULL, 0, 0);
+ return 0;
+ }
+ ], ac_cv_flavor_gethostbyaddr=glibc2_2,,
+ ac_cv_flavor_gethostbyaddr=unknown)
+ AC_TRY_RUN(
+ [
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ struct hostent *gethostbyaddr(const char *addr, size_t len, int type) {
+ return NULL;
+ }
+ int main() {
+ (void)gethostbyaddr(NULL, 0, 0);
+ return 0;
+ }
+ ], ac_cv_flavor_gethostbyaddr=glibc,,
+ ac_cv_flavor_gethostbyaddr=unknown)
+ AC_TRY_RUN(
+ [
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ struct hostent *gethostbyaddr(const char *addr, int len, int type) {
+ return NULL;
+ }
+ int main() {
+ (void)gethostbyaddr(NULL, 0, 0);
+ return 0;
+ }
+ ], ac_cv_flavor_gethostbyaddr=traditional,,
+ ac_cv_flavor_gethostbyaddr=unknown)
+ if test "$ac_cv_func_gethostbyaddr" = no ; then
+ ac_cv_flavor_gethostbyaddr=none
+ fi])
+
+ case "$ac_cv_flavor_gethostbyaddr" in
+ glibc2_2)
+ ac_cv_type_ghba_addr_t='const void *'
+ ac_cv_type_ghba_addrlen_t='socklen_t'
+ ;;
+ glibc)
+ ac_cv_type_ghba_addr_t='const char *'
+ ac_cv_type_ghba_addrlen_t='size_t'
+ ;;
+ traditional | none)
+ ac_cv_type_ghba_addr_t='const char *'
+ ac_cv_type_ghba_addrlen_t='int'
+ ;;
+ *)
+ AC_MSG_ERROR([can't build runidn, since parameter type list of gethostbyaddr() is unknown to configure.])
+ ;;
+ esac
+ AC_DEFINE_UNQUOTED(GHBA_ADDR_T, $ac_cv_type_ghba_addr_t,
+ [Define as the type of the 1st argument of gethostbyaddr.])
+ AC_DEFINE_UNQUOTED(GHBA_ADDRLEN_T, $ac_cv_type_ghba_addrlen_t,
+ [Define as the type of the 2nd argument of gethostbyaddr.])
+
+dnl Checks the flavor of getnameinfo functions.
+ AC_CACHE_CHECK(flavor of getnameinfo, ac_cv_flavor_getnameinfo,
+ [ac_cv_flavor_getnameinfo=unknown
+ AC_TRY_RUN(
+ [
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
+ socklen_t hostlen, char *serv, socklen_t servlen,
+ unsigned int flags) {
+ return NULL;
+ }
+ int main() {
+ (void)getnameinfo(NULL, 0, NULL, 0, NULL, 0, 0);
+ return 0;
+ }
+ ], ac_cv_flavor_getnameinfo=glibc2_2_2,,
+ ac_cv_flavor_getnameinfo=unknown)
+ AC_TRY_RUN(
+ [
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
+ socklen_t hostlen, char *serv, socklen_t servlen,
+ int flags) {
+ return NULL;
+ }
+ int main() {
+ (void)getnameinfo(NULL, 0, NULL, 0, NULL, 0, 0);
+ return 0;
+ }
+ ], ac_cv_flavor_getnameinfo=rfc2553bis_03,,
+ ac_cv_flavor_getnameinfo=unknown)
+ AC_TRY_RUN(
+ [
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
+ size_t hostlen, char *serv, size_t servlen, int flags) {
+ return NULL;
+ }
+ int main() {
+ (void)getnameinfo(NULL, 0, NULL, 0, NULL, 0, 0);
+ return 0;
+ }
+ ], ac_cv_flavor_getnameinfo=rfc2553,,
+ ac_cv_flavor_getnameinfo=unknown)
+ AC_TRY_RUN(
+ [
+ #include <stddef.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h>
+ int getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
+ size_t hostlen, char *serv, size_t servlen, int flags) {
+ return NULL;
+ }
+ int main() {
+ (void)getnameinfo(NULL, 0, NULL, 0, NULL, 0, 0);
+ return 0;
+ }
+ ], ac_cv_flavor_getnameinfo=rfc2133,,
+ ac_cv_flavor_getnameinfo=unknown)
+ if test "$ac_cv_func_getnameinfo" = no ; then
+ ac_cv_flavor_getnameinfo=none
+ fi])
+
+ case "$ac_cv_flavor_getnameinfo" in
+ glibc2_2_2)
+ ac_cv_type_gni_salen_t='socklen_t'
+ ac_cv_type_gni_hostlen_t='socklen_t'
+ ac_cv_type_gni_servlen_t='socklen_t'
+ ac_cv_type_gni_flags_t='unsigned int'
+ ;;
+ rfc2553bis_03)
+ ac_cv_type_gni_salen_t='socklen_t'
+ ac_cv_type_gni_hostlen_t='socklen_t'
+ ac_cv_type_gni_servlen_t='socklen_t'
+ ac_cv_type_gni_flags_t='int'
+ ;;
+ rfc2553)
+ ac_cv_type_gni_salen_t='socklen_t'
+ ac_cv_type_gni_hostlen_t='size_t'
+ ac_cv_type_gni_servlen_t='size_t'
+ ac_cv_type_gni_flags_t='int'
+ ;;
+ rfc2133 | none)
+ ac_cv_type_gni_salen_t='size_t'
+ ac_cv_type_gni_hostlen_t='size_t'
+ ac_cv_type_gni_servlen_t='size_t'
+ ac_cv_type_gni_flags_t='int'
+ ;;
+ *)
+ AC_MSG_ERROR([can't build runidn, since parameter type list of getnameinfo() is unknown to configure.])
+ esac
+ AC_DEFINE_UNQUOTED(GNI_SALEN_T, $ac_cv_type_gni_salen_t,
+ [Define as the type of the 2nd argument of getnameinfo.])
+ AC_DEFINE_UNQUOTED(GNI_HOSTLEN_T, $ac_cv_type_gni_hostlen_t,
+ [Define as the type of the 4th argument of getnameinfo.])
+ AC_DEFINE_UNQUOTED(GNI_SERVLEN_T, $ac_cv_type_gni_servlen_t,
+ [Define as the type of the 6th argument of getnameinfo.])
+ AC_DEFINE_UNQUOTED(GNI_FLAGS_T, $ac_cv_type_gni_flags_t,
+ [Define as the type of the 7th argument of getnameinfo.])
+fi
+
+dnl resume here.
+dnl Checks the flavor of gethost*_r functions.
+if test "$find_gethost_r" = yes; then
+ AC_CACHE_CHECK(flavor of gethostbyname_r, ac_cv_flavor_gethost_r,
+ [AC_TRY_RUN(
+changequote(<<, >>)dnl
+<<
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+int main()
+{
+ int err = 0;
+ struct hostent hebuf, *hp;
+ char buf[10];
+ /* Try resolving a invalid name using glibc flavor. */
+ (void)gethostbyname_r("@#!", &hebuf, buf, sizeof(buf), &hp, &err);
+ if (err != 0)
+ return 0; /* glibc flavor */
+ else
+ return 1; /* Sun flavor */
+}
+>>,
+changequote([, ])dnl
+ ac_cv_flavor_gethost_r=glibc,
+ ac_cv_flavor_gethost_r=sun,
+ ac_cv_flavor_gethost_r=sun)])
+ if test "$ac_cv_flavor_gethost_r" = "glibc"; then
+ AC_DEFINE(GETHOST_R_GLIBC_FLAVOR, 1,
+ [Define if the prototype of gethost*_r is glibc flavor.])
+ fi
+fi
+
+dnl Find system shared object paths.
+AC_FIND_SYSTEM_SHOBJ(libc)
+if test "$install_runidn" = yes ; then
+ AC_FIND_SYSTEM_SHOBJ(libnsl)
+fi
+
+dnl Checks for iconv library.
+if test "$liteonly" != yes ; then
+ AC_MSG_CHECKING(for iconv)
+ saved_CPPFLAGS=$CPPFLAGS
+ saved_LIBS=$LIBS
+ CPPFLAGS="$CPPFLAGS $ICONVINC"
+ LIBS="$LIBS $ICONVLIB"
+ AC_TRY_LINK([
+ #include <iconv.h>
+ ], [
+ iconv_t i;
+ i = iconv_open("ISO-8859-1", "UTF-8");
+ ], [iconv_try_link=yes], [iconv_try_link=no])
+ LIBS=$saved_LIBS
+ CPPFLAGS=$saved_CPPFLAGS
+ AC_MSG_RESULT($iconv_try_link)
+ if test "$iconv_try_link" = no ; then
+ AC_MSG_ERROR(iconv function not available)
+ fi
+fi
+
+dnl Check for codeset name for UTF-8.
+if test "$liteonly" != yes ; then
+ AC_MSG_CHECKING([for codeset name $UTF8_NAME])
+ saved_CPPFLAGS=$CPPFLAGS
+ saved_LIBS=$LIBS
+ CPPFLAGS="$CPPFLAGS $ICONVINC"
+ LIBS="$LIBS $ICONVLIB"
+ AC_TRY_RUN([
+ #include <stddef.h>
+ #include <stdlib.h>
+ #include <iconv.h>
+ #define UTF8_NAME "$UTF8_NAME"
+ #define ICONV_FAIL ((iconv_t)(-1))
+ /* Check if the codeset name UTF8_NAME is valid by performing iconv_open(). */
+ int main() {
+ int i;
+ /* list of codeset names likely to exist */
+ static char *codeset[] = {
+ "ASCII", "ISO-8859-1", "ISO8859-1", "iso8859_1", "8859-1",
+ "Shift_JIS", "SJIS", "sjis", NULL,
+ };
+
+ /* First try null conversion. */
+ if (iconv_open(UTF8_NAME, UTF8_NAME) != ICONV_FAIL) return 0;
+
+ /* Unfortunately, above check fails on certain systems, such as Solaris. */
+ for (i = 0; codeset[i] != NULL; i++) {
+ if (iconv_open(UTF8_NAME, codeset[i]) != ICONV_FAIL) return 0;
+ }
+ return 1;
+ }
+ ], utf8_name_valid=yes, utf8_name_valid=no, utf8_name_valid=unknown)
+ LIBS=$saved_LIBS
+ CPPFLAGS=$saved_CPPFLAGS
+ AC_MSG_RESULT($utf8_name_valid)
+fi
+
+dnl Output.
+AC_CONFIG_HEADER(include/config.h)
+AC_OUTPUT(
+ Makefile
+ include/Makefile
+ include/idn/Makefile
+ include/mdn/Makefile
+ lib/Makefile
+ man/Makefile
+ tools/Makefile
+ tools/idnconv/Makefile
+ tools/runidn/Makefile
+ tools/runidn/runidn
+ map/Makefile
+ lib/tests/Makefile
+)
diff --git a/contrib/idn/idnkit-1.0-src/include/Makefile.in b/contrib/idn/idnkit-1.0-src/include/Makefile.in
new file mode 100644
index 0000000..cf931a3
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/Makefile.in
@@ -0,0 +1,65 @@
+# $Id: Makefile.in,v 1.1.1.1 2003/06/04 00:25:33 marka Exp $
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+SHELL = @SHELL@
+
+SUBDIRS = idn mdn
+
+all: all-subdirs
+install: install-subdirs
+clean: clean-subdirs
+distclean: distclean-localdir distclean-subdirs
+check test: test-subdirs
+
+all-subdirs install-subdirs clean-subdirs distclean-subdirs test-subdirs:
+ @target=`echo $@ | sed 's/-subdirs$$//'`; \
+ for d in $(SUBDIRS); do \
+ (cd $$d; $(MAKE) DESTDIR=$(DESTDIR) $$target); \
+ done
+
+distclean-localdir:
+ rm -f config.h Makefile
diff --git a/contrib/idn/idnkit-1.0-src/include/config.h.in b/contrib/idn/idnkit-1.0-src/include/config.h.in
new file mode 100644
index 0000000..304ec30
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/config.h.in
@@ -0,0 +1,181 @@
+/* include/config.h.in. Generated automatically from configure.in by autoheader. */
+/* $Id: config.h.in,v 1.1.1.1 2003/06/04 00:25:34 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define as an appropriate type (ex. int) if your system doesn't have. */
+#undef BOOL
+
+/* Define if you have the bcopy function. */
+#undef HAVE_BCOPY
+
+/* Define if you have the dlopen function. */
+#undef HAVE_DLOPEN
+
+/* Define if you have the dlsym function. */
+#undef HAVE_DLSYM
+
+/* Define if you have the freeaddrinfo function. */
+#undef HAVE_FREEADDRINFO
+
+/* Define if you have the freehostent function. */
+#undef HAVE_FREEHOSTENT
+
+/* Define if you have the getaddrinfo function. */
+#undef HAVE_GETADDRINFO
+
+/* Define if you have the gethostbyaddr function. */
+#undef HAVE_GETHOSTBYADDR
+
+/* Define if you have the gethostbyaddr_r function. */
+#undef HAVE_GETHOSTBYADDR_R
+
+/* Define if you have the gethostbyname function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define if you have the gethostbyname2 function. */
+#undef HAVE_GETHOSTBYNAME2
+
+/* Define if you have the gethostbyname2_r function. */
+#undef HAVE_GETHOSTBYNAME2_R
+
+/* Define if you have the gethostbyname_r function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define if you have the getipnodebyaddr function. */
+#undef HAVE_GETIPNODEBYADDR
+
+/* Define if you have the getipnodebyname function. */
+#undef HAVE_GETIPNODEBYNAME
+
+/* Define if you have the getnameinfo function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define if you have the memmove function. */
+#undef HAVE_MEMMOVE
+
+/* Define if you have the nl_langinfo function. */
+#undef HAVE_NL_LANGINFO
+
+/* Define if you have the setenv function. */
+#undef HAVE_SETENV
+
+/* Define if you have the setlocale function. */
+#undef HAVE_SETLOCALE
+
+/* Define if you have the setvbuf function. */
+#undef HAVE_SETVBUF
+
+/* Define if you have the unsetenv function. */
+#undef HAVE_UNSETENV
+
+/* Define if you have the vsnprintf function. */
+#undef HAVE_VSNPRINTF
+
+/* Define if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define if you have the <langinfo.h> header file. */
+#undef HAVE_LANGINFO_H
+
+/* Define if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
+/* Define if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the nsl library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define if you have the socket library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define if --enable-mdnkit-compat is specified */
+#undef ENABLE_MDNKIT_COMPAT
+
+/* Define if you want additional ACE converters compiled in. */
+#undef IDN_EXTRA_ACE
+
+/* Define if your iconv() does not accept UTF-8 as the codeset name for utf-8. */
+#undef IDN_UTF8_ENCODING_NAME
+
+/* Define if you have the dl library (-ldl). */
+#undef HAVE_LIBDL
+
+/* Define as the type of the 1st argument of gethostbyaddr. */
+#undef GHBA_ADDR_T
+
+/* Define as the type of the 2nd argument of gethostbyaddr. */
+#undef GHBA_ADDRLEN_T
+
+/* Define as the type of the 2nd argument of getnameinfo. */
+#undef GNI_SALEN_T
+
+/* Define as the type of the 4th argument of getnameinfo. */
+#undef GNI_HOSTLEN_T
+
+/* Define as the type of the 6th argument of getnameinfo. */
+#undef GNI_SERVLEN_T
+
+/* Define as the type of the 7th argument of getnameinfo. */
+#undef GNI_FLAGS_T
+
+/* Define if the prototype of gethost*_r is glibc flavor. */
+#undef GETHOST_R_GLIBC_FLAVOR
+
+/* Define as the pathname of the shared libc object if your system has one. */
+#undef SOPATH_LIBC
+
+/* Define as the pathname of the shared libnsl object if your system has one. */
+#undef SOPATH_LIBNSL
diff --git a/contrib/idn/idnkit-1.0-src/include/config.h.win b/contrib/idn/idnkit-1.0-src/include/config.h.win
new file mode 100644
index 0000000..3ed87df
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/config.h.win
@@ -0,0 +1,45 @@
+/* $Id: config.h.win,v 1.1.1.1 2003/06/04 00:25:34 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/* for enabling RACE */
+#define IDN_EXTRA_ACE
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/Makefile.in b/contrib/idn/idnkit-1.0-src/include/idn/Makefile.in
new file mode 100644
index 0000000..b99cf8c
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/Makefile.in
@@ -0,0 +1,103 @@
+# $Id: Makefile.in,v 1.1.1.1 2003/06/04 00:25:34 marka Exp $
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+includedir = @includedir@
+idnincludedir = $(includedir)/idn
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+SHELL = @SHELL@
+
+HDRS = \
+ api.h \
+ assert.h \
+ checker.h \
+ converter.h \
+ debug.h \
+ delimitermap.h \
+ export.h \
+ filechecker.h \
+ filemapper.h \
+ localencoding.h \
+ log.h \
+ logmacro.h \
+ mapper.h \
+ mapselector.h \
+ nameprep.h \
+ normalizer.h \
+ punycode.h \
+ race.h \
+ res.h \
+ resconf.h \
+ result.h \
+ strhash.h \
+ ucsmap.h \
+ ucsset.h \
+ unicode.h \
+ unormalize.h \
+ ucs4.h \
+ utf8.h \
+ util.h \
+ version.h
+
+all:
+
+install:
+ $(MKINSTALLDIRS) $(DESTDIR)$(idnincludedir)
+ for hdr in $(HDRS); do \
+ $(INSTALL_DATA) $(srcdir)/$$hdr $(DESTDIR)$(idnincludedir)/$$hdr; \
+ done
+
+clean:
+ rm -f *~
+
+distclean: clean
+ rm -f Makefile
+
+test check:
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/aliaslist.h b/contrib/idn/idnkit-1.0-src/include/idn/aliaslist.h
new file mode 100644
index 0000000..61c3fd5
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/aliaslist.h
@@ -0,0 +1,114 @@
+/* $Id: aliaslist.h,v 1.1.1.1 2003/06/04 00:25:34 marka Exp $ */
+/*
+ * Copyright (c) 2002 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_ALIASLIST_H
+#define IDN_ALIASLIST_H 1
+
+#include <idn/result.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct idn__aliaslist *idn__aliaslist_t;
+
+/*
+ * Create a list.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+extern idn_result_t
+idn__aliaslist_create(idn__aliaslist_t *listp);
+
+/*
+ * Delete a list created by 'idn__aliaslist_create'.
+ */
+extern void
+idn__aliaslist_destroy(idn__aliaslist_t list);
+
+/*
+ * Parse alias information file and set items to the list.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nofile -- no such file.
+ * idn_invalid_syntax -- file is malformed.
+ * idn_nomemory -- malloc failed.
+ */
+extern idn_result_t
+idn__aliaslist_aliasfile(idn__aliaslist_t list, const char *path);
+
+/*
+ * Add an item to the list.
+ *
+ * If top is 0, item is placed as the last item of the alias list.
+ * Otherwise, it is done as the first item.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+extern idn_result_t
+idn__aliaslist_additem(idn__aliaslist_t list,
+ const char *pattern, const char *encoding,
+ int first_item);
+
+/*
+ * Find the encoding name with the specified pattern by wildcard
+ * match.
+ *
+ * Returns:
+ * idn_success -- ok. found.
+ * idn_noentry -- not found.
+ */
+extern idn_result_t
+idn__aliaslist_find(idn__aliaslist_t list,
+ const char *pattern, char **encodingp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_ALIASLIST_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/api.h b/contrib/idn/idnkit-1.0-src/include/idn/api.h
new file mode 100644
index 0000000..ca529f3
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/api.h
@@ -0,0 +1,298 @@
+/* $Id: api.h,v 1.1.1.1 2003/06/04 00:25:35 marka Exp $ */
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_API_H
+#define IDN_API_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <idn/export.h>
+#include <idn/result.h>
+#include <idn/res.h>
+
+/*
+ * Application Programming Interface for Internationalized Domain Name
+ * Handling. This module provides high-level APIs for ordinary applications.
+ * Low-level APIs are also available. See "res.h" for details.
+ */
+
+/*
+ * Enable or disable IDN conversion scheme.
+ *
+ * If on_off is 0, IDN conversion scheme is disabled. Otherwise, IDN
+ * conversion is enabled even when IDN_DISABLE is defined.
+ */
+IDN_EXPORT void
+idn_enable(int on_off);
+
+/*
+ * Set configuration file name.
+ * This function is for private use only.
+ *
+ * When idn_nameinit(1) is called, this module loads `file'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ * idn_failure -- idn_nameinit() has already been
+ * called.
+ */
+extern idn_result_t
+idn__setconffile(const char *file);
+
+/*
+ * Initialize this module, and load configuration from the default
+ * configuration file (idn.conf).
+ *
+ * The initialization will be done only once when this function is
+ * called first, while either loading of the configuration file or
+ * setting the defaults behavior without the configuration file will
+ * be done every time it is called.
+ *
+ * If load_file is 0, this will set the defaults behavior without the
+ * configuration file. Otherwise, loading of the configuration file
+ * occurs.
+ *
+ * If 'idn_encodename' or 'idn_decodename' is called without calling
+ * this function, implicit initialization without the configuration
+ * file will be done prior to encoding/decoding process.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nofile -- cannot open the configuration file.
+ * idn_invalid_syntax -- syntax error found in the file.
+ * idn_invalid_name -- there are invalid names (encoding,
+ * normalization etc.).
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_nameinit(int load_file);
+
+/*
+ * Encode internationalized domain name.
+ *
+ * The encoding process consists of the following 7 steps.
+ *
+ * 1. Local encoding to UTF-8 conversion
+ * Converts a domain name written with local encoding (e.g. ISO-
+ * 8859-1) to UTF-8.
+ * 2. Delimiter mapping,
+ * Maps certain characters to period (U+002E, FULL STOP).
+ * 3. Local mapping
+ * Apply character mappings according with the TLD of the domain
+ * name.
+ * 4. NAMEPREP
+ * Perform NAME preparation described in RFC3491.
+ * This step consists of the following 4 steps:
+ * 4.1. Mapping
+ * 4.2. Normalization
+ * 4.3. Prohibited character check
+ * 4.4. Unassigned check
+ * 5. ASCII range character check
+ * Checks if the domain name contains non-LDH ASCII character (not
+ * alpha-numeric or hypen), or it begins or end with hypen.
+ * 6. UTF-8 to IDN encoding conversion.
+ * Converts the domain name from UTF-8 to ACE (e.g. Punycode).
+ * 7. Length check
+ * Checks the length of each label.
+ *
+ * 'actions' specifies actions and options of the encoding procedure.
+ * Its value is a bitwise-or of the following flags:
+ *
+ * IDN_LOCALCONV -- perform local encoding to UTF-8 conversion (step 1)
+ * IDN_DELIMMAP -- perform delimiter mapping (step 2)
+ * IDN_LOCALMAP -- perform local mapping (step 3)
+ * IDN_MAP -- perform mapping (step 4.1)
+ * IDN_NORMALIZE -- perform normalization (step 4.2)
+ * IDN_PROHCHECK -- perform prohibited character check (step 4.3)
+ * IDN_UNASCHECK -- perform unassigned codepoint check (step 4.4)
+ * IDN_ASCCHECK -- perform ASCII range character check (step 5)
+ * IDN_IDNCONV -- perform UTF-8 to IDN encoding conversion (step 6)
+ * IDN_LENCHECK -- perform length check (step 7)
+ *
+ * Also the following flags are provided for convinience:
+ *
+ * IDN_ENCODE_QUERY -- On libidnkit, perform step 1..7, except for step
+ * 4.4 and 5.
+ * On libidnkitlite, perform step 2..7, except for
+ * step 4.4 and 5.
+ * IDN_ENCODE_STORED -- On libidnkit, perform step 1..7, except for step
+ * 5.
+ * On libidnkitlite, perform step 2..7, except for
+ * step 5.
+ * IDN_ENCODE_APP -- Same as IDN_ENCODE_QUERY.
+ * IDN_NAMEPREP -- perform NAMEPREP (step 4) without unassigned
+ * codepoint check (step 4.4).
+ *
+ * The following flag does not corresponding to a particular action,
+ * but an option of conversion process:
+ *
+ * IDN_UNDOIFERR -- If any step fails, the original input name is
+ * returned.
+ *
+ * Note that if no flags are specified, 'idn_encodename' does nothing
+ * fancy, just copies the given name verbatim.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_action -- invalid action flag specified.
+ * idn_invalid_encoding -- the given string has invalid/illegal
+ * byte sequence.
+ * idn_invalid_length -- invalid length of a label.
+ * idn_prohibited -- prohibited/unassigned code point found.
+ * idn_buffer_overflow -- 'tolen' is too small.
+ * idn_nomemory -- malloc failed.
+ *
+ * Also, if this function is called without calling 'idn_nameinit',
+ * the following error codes might be returned.
+ * idn_nofile -- cannot open the configuration file.
+ * idn_invalid_syntax -- syntax error found in the file.
+ * idn_invalid_name -- there are invalid names (encoding,
+ * normalization etc.).
+ */
+IDN_EXPORT idn_result_t
+idn_encodename(idn_action_t actions, const char *from, char *to, size_t tolen);
+
+/*
+ * Decode internationalized domain name.
+ *
+ * The decoding process consists of the following 5 steps.
+ *
+ * 1. delimiter mapping
+ * Maps certain characters to period (U+002E, FULL STOP).
+ * 2. NAMEPREP
+ * Perform NAME preparation described in RFC3491.
+ * This step consists of the following 4 steps:
+ * 2.1. Mapping
+ * 2.2. Normalization
+ * 2.3. Prohibited character check
+ * 2.4. Unassigned check
+ * 3. IDN encoding to UTF-8 conversion.
+ * Converts the domain name from ACE (e.g. Punycode) to UCS4.
+ * 4. Perform round-trip check.
+ * Encode the result of step 3, and then compare it with the result
+ * of the step 2. If they are different, the check is failed.
+ * 5. Convert UTF-8 to local encoding.
+ * If a character in the domain name cannot be converted to local
+ * encoding, the conversion is failed.
+ *
+ * 'actions' specifies actions of the decoding procedure.
+ * Its value is a bitwise-or of the following flags:
+ *
+ * IDN_DELIMMAP -- perform delimiter mapping (step 1)
+ * IDN_MAP -- perform mapping (step 2.1)
+ * IDN_NORMALIZE -- perform normalization (step 2.2)
+ * IDN_PROHCHECK -- perform prohibited character check (step 2.3)
+ * IDN_UNASCHECK -- perform unassigned codepoint check (step 2.4)
+ * IDN_IDNCONV -- perform IDN encoding to UTF-8 conversion (step 3)
+ * IDN_RTCHECK -- perform round-trip check (step 4)
+ * IDN_ASCCHECK -- perform ASCII range character check while
+ * round-trip check (step 4.1)
+ * IDN_LOCALCONV -- perform UTF-8 to local encoding conversion (step 5)
+ *
+ * Also the following flags are provided for the convenience:
+ *
+ * IDN_DECODE_QUERY -- On libidnkit, perform step 1..5, except for step
+ * 2.4 and 4.1.
+ * On libidnkitlite, perform step 1..3, except for
+ * step 2.4 and 4.1.
+ * IDN_DECODE_STORED -- On libidnkit, perform step 1..5, except for step
+ * 4.1.
+ * On libidnkitlite, perform step 1..3, except for
+ * step 4.1.
+ * IDN_DECODE_APP -- Same as IDN_DECODE_QUERY.
+ * IDN_NAMEPREP -- perform NAMEPREP (step 2) without unassigned
+ * codepoint check (step 2.4).
+ *
+ * If any step fails, the original input name is returned.
+ * 'actions' specifies what actions to take when decoding, and is
+ * a bitwise-or of the following flags:
+ *
+ * Note that if no flags are specified, 'idn_decodename' does nothing
+ * but copying the given name verbatim.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_action -- invalid action flag specified.
+ * idn_invalid_encoding -- the given string has invalid/illegal
+ * byte sequence.
+ * idn_buffer_overflow -- 'tolen' is too small.
+ * idn_invalid_length -- length of a label is not 1..63 characters.
+ * idn_nomemory -- malloc failed.
+ *
+ * Also, if this function is called without calling 'idn_nameinit',
+ * the following error codes might be returned.
+ * idn_nofile -- cannot open the configuration file.
+ * idn_invalid_syntax -- syntax error found in the file.
+ * idn_invalid_name -- there are invalid names (encoding,
+ * normalization etc.).
+ */
+IDN_EXPORT idn_result_t
+idn_decodename(idn_action_t actions, const char *from, char *to, size_t tolen);
+
+/*
+ * Decode internationalized domain name with auxiliary encoding
+ * support.
+ *
+ * This is another API for IDN string decode. The difference between
+ * two is whether the encoding conversion from auxiliary encoding to
+ * UTF-8 occurs prior to the actual decode process (read description
+ * of idn_res_decodename() above) or not.
+ *
+ * If auxencoding is NULL, from is treated as UTF-8 encoded string.
+ *
+ * Other arguments serve exactly same role as those of
+ * idn_res_decodename().
+ */
+idn_result_t
+idn_decodename2(idn_action_t actions, const char *from, char *to, size_t tolen,
+ const char *auxencoding);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_API_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/assert.h b/contrib/idn/idnkit-1.0-src/include/idn/assert.h
new file mode 100644
index 0000000..12d4dac
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/assert.h
@@ -0,0 +1,61 @@
+/* $Id: assert.h,v 1.1.1.1 2003/06/04 00:25:35 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_ASSERT_H
+#define IDN_ASSERT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+
+#ifndef DEBUG
+#define NDEBUG
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+# endif /* IDN_ASSERT_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/checker.h b/contrib/idn/idnkit-1.0-src/include/idn/checker.h
new file mode 100644
index 0000000..02af31b
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/checker.h
@@ -0,0 +1,171 @@
+/* $Id: checker.h,v 1.1.1.1 2003/06/04 00:25:36 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_CHECKER_H
+#define IDN_CHECKER_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Character Checker.
+ *
+ * Perfom checking characters in the specified domain name.
+ */
+
+#include <idn/result.h>
+#include <idn/filechecker.h>
+#include <idn/nameprep.h>
+
+/*
+ * Schems name prefixes for the standard nameprep prohibit/unassigned
+ * checks.
+ *
+ * If you'd like to add the unassigned check scheme of "RFC3491"
+ * to a checker context, IDN_CHECKER_UNASSIGNED_PREFIX + "RFC3491"
+ * (i.e. "unassigned#RFC3491") is the scheme name passed to
+ * idn_checker_add().
+ */
+#define IDN_CHECKER_PROHIBIT_PREFIX "prohibit#"
+#define IDN_CHECKER_UNASSIGNED_PREFIX "unassigned#"
+#define IDN_CHECKER_BIDI_PREFIX "bidi#"
+
+/*
+ * Checker object type.
+ */
+typedef struct idn_checker *idn_checker_t;
+
+/*
+ * Initialize module. Must be called before any other calls of
+ * the functions of this module.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+extern idn_result_t
+idn_checker_initialize(void);
+
+/*
+ * Create a checker context.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+extern idn_result_t
+idn_checker_create(idn_checker_t *ctxp);
+
+/*
+ * Decrement reference count of the checker `ctx' created by
+ * 'idn_checker_create', if it is still refered by another object.
+ * Otherwise, release all the memory allocated to the checker.
+ */
+extern void
+idn_checker_destroy(idn_checker_t ctx);
+
+/*
+ * Increment reference count of the checker `ctx' created by
+ * 'idn_checker_create'.
+ */
+extern void
+idn_checker_incrref(idn_checker_t ctx);
+
+/*
+ * Add checking scheme `name' to the checker to `ctx'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_name -- the given name is not valid.
+ * idn_nomemory -- malloc failed.
+ */
+extern idn_result_t
+idn_checker_add(idn_checker_t ctx, const char *name);
+
+extern idn_result_t
+idn_checker_addall(idn_checker_t ctx, const char **names, int nnames);
+
+/*
+ * Check a domain name. All checking schemes regsitered in `ctx' are
+ * applied in the regisration order.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ * idn_buffer_overflow -- output buffer is too small.
+ */
+extern idn_result_t
+idn_checker_lookup(idn_checker_t ctx, const unsigned long *ucs4,
+ const unsigned long **found);
+
+/*
+ * Checking procedure type.
+ */
+typedef idn_result_t (*idn_checker_createproc_t)(const char *parameter,
+ void **ctxp);
+typedef void (*idn_checker_destroyproc_t)(void *ctx);
+typedef idn_result_t (*idn_checker_lookupproc_t)(void *ctx,
+ const unsigned long *ucs4,
+ const unsigned long **found);
+
+/*
+ * Register a new checking scheme.
+ *
+ * You can override the default normalization schemes, if you want.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+extern idn_result_t
+idn_checker_register(const char *prefix,
+ idn_checker_createproc_t create,
+ idn_checker_destroyproc_t destroy,
+ idn_checker_lookupproc_t lookup);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_CHECKER_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/converter.h b/contrib/idn/idnkit-1.0-src/include/idn/converter.h
new file mode 100644
index 0000000..03248f6
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/converter.h
@@ -0,0 +1,258 @@
+/* $Id: converter.h,v 1.1.1.1 2003/06/04 00:25:36 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_CONVERTER_H
+#define IDN_CONVERTER_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Codeset converter.
+ *
+ * This module provides conversions from some local codeset to UCS4
+ * and vice versa.
+ */
+
+#include <idn/export.h>
+#include <idn/result.h>
+
+/*
+ * Converter context type (opaque).
+ */
+typedef struct idn_converter *idn_converter_t;
+
+/*
+ * Conversion flags.
+ */
+#define IDN_CONVERTER_DELAYEDOPEN 1
+#define IDN_CONVERTER_RTCHECK 2
+
+/*
+ * Encoding types.
+ */
+#define IDN_NONACE 0
+#define IDN_ACE_STRICTCASE 1
+#define IDN_ACE_LOOSECASE 2
+
+/*
+ * Initialize module. Must be called before any other calls of
+ * the functions of this module.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_converter_initialize(void);
+
+/*
+ * Create a conversion context.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_name -- specified codeset is not supported.
+ * idn_nomemory -- malloc failed.
+ * idn_failure -- other failure (unknown cause).
+ */
+IDN_EXPORT idn_result_t
+idn_converter_create(const char *name, idn_converter_t *ctxp,
+ int flags);
+
+/*
+ * Decrement reference count of the converter `ctx' created by
+ * 'idn_converter_create', if it is still refered by another object.
+ * Otherwise, release all the memory allocated to the converter.
+ */
+IDN_EXPORT void
+idn_converter_destroy(idn_converter_t ctx);
+
+/*
+ * Increment reference count of the converter `ctx' created by
+ * 'idn_converter_create'.
+ */
+IDN_EXPORT void
+idn_converter_incrref(idn_converter_t ctx);
+
+/*
+ * Convert between local codeset and UCS4. Note that each conversion
+ * is started with initial state.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_buffer_overflow -- output buffer is too small.
+ * idn_invalid_encoding -- the input string has invalid/illegal
+ * byte sequence.
+ * idn_invalid_name -- codeset is not supported (this error
+ * should happen only if 'delayedopen'
+ * flag was set when idn_converter_create
+ * was called)
+ * idn_failure -- other failure.
+ */
+IDN_EXPORT idn_result_t
+idn_converter_convfromucs4(idn_converter_t ctx,
+ const unsigned long *from, char *to, size_t tolen);
+
+IDN_EXPORT idn_result_t
+idn_converter_convtoucs4(idn_converter_t ctx,
+ const char *from, unsigned long *to, size_t tolen);
+
+/*
+ * Get the name of local codeset. The returned name may be different from
+ * the one specified to idn_converter_create, if the specified one was an
+ * alias.
+ *
+ * Returns:
+ * the local codeset name.
+ */
+IDN_EXPORT char *
+idn_converter_localencoding(idn_converter_t ctx);
+
+/*
+ * Return the encoding type of this local encoding.
+ *
+ * Returns:
+ * IDN_NONACE -- encoding is not ACE.
+ * IDN_ACE_STRICTCASE -- encoding is ACE.
+ * decoder of this ACE preserve letter case.
+ * IDN_ACE_LOOSECASE -- encoding type is ACE.
+ * decoder cannot preserve letter case.
+ */
+IDN_EXPORT int
+idn_converter_encodingtype(idn_converter_t ctx);
+
+/*
+ * Return if this local encoding is ACE (Ascii Compatible Encoding).
+ *
+ * Returns:
+ * 1 -- yes, it is ACE.
+ * 0 -- no.
+ */
+IDN_EXPORT int
+idn_converter_isasciicompatible(idn_converter_t ctx);
+
+/*
+ * Register an alias for a codeset name.
+ *
+ * If first_item is 0, alias pattern is placed as the last item of the
+ * alias list. Otherwise, it is done as the first item.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_converter_addalias(const char *alias_name, const char *real_name,
+ int first_item);
+
+/*
+ * Register aliases defined by the specified file.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nofile -- no such file.
+ * idn_invalid_syntax -- file is malformed.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_converter_aliasfile(const char *path);
+
+/*
+ * Unregister all the aliases.
+ */
+IDN_EXPORT idn_result_t
+idn_converter_resetalias(void);
+
+/*
+ * resolve real encoding name from alias information.
+ */
+IDN_EXPORT const char *
+idn_converter_getrealname(const char *name);
+
+
+/*
+ * New converter registration.
+ */
+
+/*
+ * Conversion operation functions.
+ */
+typedef idn_result_t (*idn_converter_openproc_t)(idn_converter_t ctx,
+ void **privdata);
+typedef idn_result_t (*idn_converter_closeproc_t)(idn_converter_t ctx,
+ void *privdata);
+typedef idn_result_t
+ (*idn_converter_convfromucs4proc_t)(idn_converter_t ctx,
+ void *privdata,
+ const unsigned long *from,
+ char *to, size_t tolen);
+typedef idn_result_t
+ (*idn_converter_convtoucs4proc_t)(idn_converter_t ctx,
+ void *privdata,
+ const char *from,
+ unsigned long *to,
+ size_t tolen);
+
+/*
+ * Register a new converter.
+ * 'encoding_type' is a value which idn_converter_encodingtype() returns.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_converter_register(const char *name,
+ idn_converter_openproc_t openfromucs4,
+ idn_converter_openproc_t opentoucs4,
+ idn_converter_convfromucs4proc_t convfromucs4,
+ idn_converter_convtoucs4proc_t convtoucs4,
+ idn_converter_closeproc_t close,
+ int encoding_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_CONVERTER_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/debug.h b/contrib/idn/idnkit-1.0-src/include/idn/debug.h
new file mode 100644
index 0000000..35bb403
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/debug.h
@@ -0,0 +1,69 @@
+/* $Id: debug.h,v 1.1.1.1 2003/06/04 00:25:36 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_DEBUG_H
+#define IDN_DEBUG_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Debug utility
+ */
+
+#include <idn/export.h>
+
+IDN_EXPORT char *idn__debug_hexstring(const char *s, int maxbytes);
+IDN_EXPORT char *idn__debug_xstring(const char *s, int maxbytes);
+IDN_EXPORT char *idn__debug_ucs4xstring(const unsigned long *s, int maxbytes);
+IDN_EXPORT char *idn__debug_utf16xstring(const unsigned short *s,
+ int maxbytes);
+IDN_EXPORT char *idn__debug_hexdata(const char *s, int length, int maxbytes);
+IDN_EXPORT void idn__debug_hexdump(const char *s, int maxbytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_DEBUG_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/delimitermap.h b/contrib/idn/idnkit-1.0-src/include/idn/delimitermap.h
new file mode 100644
index 0000000..9a2381d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/delimitermap.h
@@ -0,0 +1,123 @@
+/* $Id: delimitermap.h,v 1.1.1.1 2003/06/04 00:25:37 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_DELIMITERMAP_H
+#define IDN_DELIMITERMAP_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Mapper.
+ *
+ * Perfom mapping local delimiters to `.'.
+ */
+
+#include <idn/export.h>
+#include <idn/result.h>
+
+/*
+ * Map object type.
+ */
+typedef struct idn_delimitermap *idn_delimitermap_t;
+
+/*
+ * Create a delimitermap context.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_delimitermap_create(idn_delimitermap_t *ctxp);
+
+/*
+ * Decrement reference count of the delimitermap `ctx' created by
+ * 'idn_delimitermap_create', if it is still refered by another object.
+ * Otherwise, release all the memory allocated to the delimitermap.
+ */
+IDN_EXPORT void
+idn_delimitermap_destroy(idn_delimitermap_t ctx);
+
+/*
+ * Increment reference count of the delimitermap `ctx' created by
+ * 'idn_delimitermap_create'.
+ */
+IDN_EXPORT void
+idn_delimitermap_incrref(idn_delimitermap_t ctx);
+
+/*
+ * Add a local delimiter.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ * idn_invalid_codepoint -- delimiter is not valid UCS4 character.
+ */
+IDN_EXPORT idn_result_t
+idn_delimitermap_add(idn_delimitermap_t ctx, unsigned long delimiter);
+
+IDN_EXPORT idn_result_t
+idn_delimitermap_addall(idn_delimitermap_t ctx, unsigned long *delimiters,
+ int ndelimiters);
+
+/*
+ * Map local delimiters in `from' to `.'.
+ *
+ * Note that if no delimiter is added to the context, the function copies
+ * the string.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_buffer_overflow -- output buffer is too small.
+ */
+IDN_EXPORT idn_result_t
+idn_delimitermap_map(idn_delimitermap_t ctx, const unsigned long *from,
+ unsigned long *to, size_t tolen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_DELIMITERMAP_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/export.h b/contrib/idn/idnkit-1.0-src/include/idn/export.h
new file mode 100644
index 0000000..cb9443c
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/export.h
@@ -0,0 +1,58 @@
+/* $Id: export.h,v 1.1.1.1 2003/06/04 00:25:37 marka Exp $ */
+/*
+ * Copyright (c) 2002 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_EXPORT_H
+#define IDN_EXPORT_H 1
+
+/*
+ * Macro for exporting functions.
+ *
+ * When creating a Windows DLL, define IDN_EXPORT something as
+ * "extern __declspec(dllexport)".
+ */
+
+#ifndef IDN_EXPORT
+#define IDN_EXPORT extern
+#endif
+
+# endif /* IDN_EXPORT_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/filechecker.h b/contrib/idn/idnkit-1.0-src/include/idn/filechecker.h
new file mode 100644
index 0000000..5904493
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/filechecker.h
@@ -0,0 +1,136 @@
+/* $Id: filechecker.h,v 1.1.1.1 2003/06/04 00:25:37 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_FILECHECKER_H
+#define IDN_FILECHECKER_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Character checker -- check if there are any characters specified
+ * by a file in the given string.
+ */
+
+#include <idn/result.h>
+
+/*
+ * Check object type.
+ */
+typedef struct idn__filechecker *idn__filechecker_t;
+
+/*
+ * Read the contents of the given file and create a context for
+ * checking.
+ *
+ * 'file' is the pathname of the file, which specifies the set of
+ * characters to be checked. The file is a simple text file, and
+ * each line must be of the form either
+ * <code_point>
+ * or
+ * <code_point>-<code_point>
+ * (or comment, see below) where <code_point> is a UCS code point
+ * represented as hexadecimal string with optional prefix `U+'
+ * (ex. `0041' or `U+FEDC').
+ *
+ * The former specifies just one character (a code point, to be precise),
+ * while the latter specified a range of characters. In the case of
+ * a character range, the first code point (before hyphen) must not be
+ * greater than the second code point (after hyphen).
+ *
+ * Lines starting with `#' are comments.
+ *
+ * If file is read with no errors, the created context is stored in
+ * '*ctxp', and 'idn_success' is returned. Otherwise, the contents
+ * of '*ctxp' is undefined.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nofile -- cannot open the specified file.
+ * idn_nomemory -- malloc failed.
+ * idn_invalid_syntax -- file format is not valid.
+ */
+extern idn_result_t
+idn__filechecker_create(const char *file, idn__filechecker_t *ctxp);
+
+/*
+ * Release memory for the specified context.
+ */
+extern void
+idn__filechecker_destroy(idn__filechecker_t ctx);
+
+/*
+ * See if the given string contains any specified characters.
+ *
+ * Check if there is any characters pecified by the context 'ctx' in
+ * the UCS4 string 'str'. If there are none, NULL is stored in '*found'.
+ * Otherwise, the pointer to the first occurence of such character is
+ * stored in '*found'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ */
+extern idn_result_t
+idn__filechecker_lookup(idn__filechecker_t ctx, const unsigned long *str,
+ const unsigned long **found);
+
+/*
+ * The following functions are for internal use.
+ * They are used for this module to be add to the checker module.
+ */
+extern idn_result_t
+idn__filechecker_createproc(const char *parameter, void **ctxp);
+
+extern void
+idn__filechecker_destroyproc(void *ctxp);
+
+extern idn_result_t
+idn__filechecker_lookupproc(void *ctx, const unsigned long *str,
+ const unsigned long **found);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_FILECHECKER_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/filemapper.h b/contrib/idn/idnkit-1.0-src/include/idn/filemapper.h
new file mode 100644
index 0000000..f1fbc18
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/filemapper.h
@@ -0,0 +1,137 @@
+/* $Id: filemapper.h,v 1.1.1.1 2003/06/04 00:25:38 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_FILEMAPPER_H
+#define IDN_FILEMAPPER_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Perform character mapping (substitution) according to a
+ * map file.
+ */
+
+#include <idn/result.h>
+
+/*
+ * Mapping object type.
+ */
+typedef struct idn__filemapper *idn__filemapper_t;
+
+/*
+ * Read the contents of the given map file and create a context for mapping.
+ *
+ * 'file' is the pathname of the file, which specifies the character
+ * mapping. The file is a simple text file, and each line specifies
+ * a mapping of a single character. The format of each line is
+ *
+ * <code_point>; [<code_point>..][;]
+ *
+ * where <code_point> is a UCS code point represented as a hexadecimal
+ * string with optional prefix `U+' (ex. `0041' or `U+FEDC').
+ * The code point before the first semicolon will be mapped to the
+ * sequence of code points separated by space characters after the
+ * first semicolon. The sequence may be empty, denoting wiping out
+ * the character.
+ *
+ * For example,
+ * U+0041; U+0061 -- maps 'A' to 'a'
+ * 20;; -- wipes out ' '
+ *
+ * Anything after the second semicolon is ignored. Also lines beginning
+ * with '#' are treated as comments.
+ *
+ * If there is no error, the created context is stored in '*ctxp'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nofile -- cannot open the specified file.
+ * idn_nomemory -- malloc failed.
+ * idn_invalid_syntax -- file format is not valid.
+ */
+extern idn_result_t
+idn__filemapper_create(const char *file, idn__filemapper_t *ctxp);
+
+/*
+ * Release memory for the given context.
+ */
+extern void
+idn__filemapper_destroy(idn__filemapper_t ctx);
+
+/*
+ * Perform character substitution.
+ *
+ * Each character in the string 'from' is examined and if it
+ * has a mapping, it is substituted to the corresponding
+ * character sequence. The substituted string is stored in 'to',
+ * whose length is specified by 'tolen'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_buffer_overflow -- result buffer is too small.
+ */
+extern idn_result_t
+idn__filemapper_map(idn__filemapper_t ctx, const unsigned long *from,
+ unsigned long *to, size_t tolen);
+
+/*
+ * The following functions are for internal use.
+ * They are used for this module to be add to the mapper module.
+ */
+extern idn_result_t
+idn__filemapper_createproc(const char *parameter, void **ctxp);
+
+extern void
+idn__filemapper_destroyproc(void *ctxp);
+
+extern idn_result_t
+idn__filemapper_mapproc(void *ctx, const unsigned long *from,
+ unsigned long *to, size_t tolen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_FILEMAPPER_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/localencoding.h b/contrib/idn/idnkit-1.0-src/include/idn/localencoding.h
new file mode 100644
index 0000000..86c2c32
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/localencoding.h
@@ -0,0 +1,79 @@
+/* $Id: localencoding.h,v 1.1.1.1 2003/06/04 00:25:38 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_LOCALENCODING_H
+#define IDN_LOCALENCODING_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Local codeset detection.
+ *
+ * Determine the local codeset (the codeset used by the current application),
+ * based on the locale information.
+ */
+
+#include <idn/export.h>
+
+#define IDN_LOCALCS_ENV "IDN_LOCAL_CODESET"
+
+/*
+ * Get the codeset name corresponding to the current locale,
+ * suitable for passing to 'idn_converter_create'.
+ *
+ * If the codeset cannot be determined, the locale name itself
+ * will be returned in the hope that codeset alias file translates it
+ * to the right name.
+ *
+ * If it cannot retrieve the current locale name, NULL will be
+ * returned.
+ */
+IDN_EXPORT const char *idn_localencoding_name(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_LOCALENCODING_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/log.h b/contrib/idn/idnkit-1.0-src/include/idn/log.h
new file mode 100644
index 0000000..c2d340c
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/log.h
@@ -0,0 +1,107 @@
+/* $Id: log.h,v 1.1.1.1 2003/06/04 00:25:38 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_LOG_H
+#define IDN_LOG_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * libidnkit logging facility.
+ */
+
+#include <idn/export.h>
+
+/*
+ * Log level definition.
+ */
+enum {
+ idn_log_level_fatal = 0,
+ idn_log_level_error = 1,
+ idn_log_level_warning = 2,
+ idn_log_level_info = 3,
+ idn_log_level_trace = 4,
+ idn_log_level_dump = 5
+};
+
+/*
+ * Log handler type.
+ */
+typedef void (*idn_log_proc_t)(int level, const char *msg);
+
+/*
+ * Log routines.
+ */
+IDN_EXPORT void idn_log_fatal(const char *fmt, ...);
+IDN_EXPORT void idn_log_error(const char *fmt, ...);
+IDN_EXPORT void idn_log_warning(const char *fmt, ...);
+IDN_EXPORT void idn_log_info(const char *fmt, ...);
+IDN_EXPORT void idn_log_trace(const char *fmt, ...);
+IDN_EXPORT void idn_log_dump(const char *fmt, ...);
+
+/*
+ * Set/get log level.
+ *
+ * If log level has not been explicitly defined by 'idn_log_setlevel',
+ * the default level is determined by the value of enrironment
+ * variable 'IDN_LOG_LEVEL'.
+ */
+IDN_EXPORT void idn_log_setlevel(int level);
+IDN_EXPORT int idn_log_getlevel(void);
+
+/*
+ * Set log handler.
+ *
+ * If no log handler is set, log goes to stderr by default.
+ * You can reset the handler to the default one by specifying
+ * NULL.
+ */
+IDN_EXPORT void idn_log_setproc(idn_log_proc_t proc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_LOG_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/logmacro.h b/contrib/idn/idnkit-1.0-src/include/idn/logmacro.h
new file mode 100644
index 0000000..bc55b6b
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/logmacro.h
@@ -0,0 +1,72 @@
+/* $Id: logmacro.h,v 1.1.1.1 2003/06/04 00:25:38 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_LOGMACRO_H
+#define IDN_LOGMACRO_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <idn/log.h>
+
+#define FATAL(x) idn_log_fatal x
+#define ERROR(x) idn_log_error x
+#define WARNING(x) idn_log_warning x
+#define INFO(x) LOG_AT_LEVEL(idn_log_level_info, idn_log_info, x)
+#define TRACE(x) LOG_AT_LEVEL(idn_log_level_trace, idn_log_trace, x)
+
+#ifdef DEBUG
+#define DUMP(x) LOG_AT_LEVEL(idn_log_level_dump, idn_log_dump, x)
+#else
+#define DUMP(x)
+#endif /* DEBUG */
+
+#define LOG_AT_LEVEL(lv, fun, x) do {if (LOGLEVEL >= (lv)) fun x; } while (0)
+#define LOGLEVEL idn_log_getlevel()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_LOGMACRO_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/mapper.h b/contrib/idn/idnkit-1.0-src/include/idn/mapper.h
new file mode 100644
index 0000000..a9c55c3
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/mapper.h
@@ -0,0 +1,159 @@
+/* $Id: mapper.h,v 1.1.1.1 2003/06/04 00:25:38 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_MAPPER_H
+#define IDN_MAPPER_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Mapper.
+ *
+ * Perfom mapping the specified domain name.
+ */
+
+#include <idn/export.h>
+#include <idn/result.h>
+#include <idn/filemapper.h>
+#include <idn/nameprep.h>
+
+/*
+ * Map object type.
+ */
+typedef struct idn_mapper *idn_mapper_t;
+
+/*
+ * Initialize module. Must be called before any other calls of
+ * the functions of this module.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_mapper_initialize(void);
+
+/*
+ * Create a mapper context.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_mapper_create(idn_mapper_t *ctxp);
+
+/*
+ * Decrement reference count of the mapper `ctx' created by
+ * 'idn_mapper_create', if it is still refered by another object.
+ * Otherwise, release all the memory allocated to the mapper.
+ */
+IDN_EXPORT void
+idn_mapper_destroy(idn_mapper_t ctx);
+
+/*
+ * Increment reference count of the mapper `ctx' created by
+ * 'idn_mapper_create'.
+ */
+IDN_EXPORT void
+idn_mapper_incrref(idn_mapper_t ctx);
+
+/*
+ * Add mapping scheme `name' to the mapper to `ctx'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_name -- the given name is not valid.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_mapper_add(idn_mapper_t ctx, const char *name);
+
+IDN_EXPORT idn_result_t
+idn_mapper_addall(idn_mapper_t ctx, const char **names, int nnames);
+
+/*
+ * Map an UCS4 string. All mapping schemes regsitered in `ctx'
+ * are applied in the regisration order.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ * idn_buffer_overflow -- output buffer is too small.
+ */
+IDN_EXPORT idn_result_t
+idn_mapper_map(idn_mapper_t ctx, const unsigned long *from,
+ unsigned long *to, size_t tolen);
+
+/*
+ * Mapping procedure type.
+ */
+typedef idn_result_t (*idn_mapper_createproc_t)(const char *parameter,
+ void **ctxp);
+typedef void (*idn_mapper_destroyproc_t)(void *ctxp);
+typedef idn_result_t (*idn_mapper_mapproc_t)(void *ctx,
+ const unsigned long *from,
+ unsigned long *, size_t);
+
+/*
+ * Register a new mapping scheme.
+ *
+ * You can override the default normalization schemes, if you want.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_mapper_register(const char *prefix,
+ idn_mapper_createproc_t create,
+ idn_mapper_destroyproc_t destroy,
+ idn_mapper_mapproc_t map);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_MAPPER_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/mapselector.h b/contrib/idn/idnkit-1.0-src/include/idn/mapselector.h
new file mode 100644
index 0000000..a17aea6
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/mapselector.h
@@ -0,0 +1,165 @@
+/* $Id: mapselector.h,v 1.1.1.1 2003/06/04 00:25:39 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_MAPSELECTOR_H
+#define IDN_MAPSELECTOR_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Map selector.
+ *
+ * Perfom mapping the specified domain name according with the TLD
+ * of the donmain name.
+ */
+
+#include <idn/export.h>
+#include <idn/result.h>
+#include <idn/mapper.h>
+
+/*
+ * Special TLDs for map selection.
+ */
+#define IDN_MAPSELECTOR_NOTLD "-"
+#define IDN_MAPSELECTOR_DEFAULTTLD "."
+
+IDN_EXPORT const unsigned long *
+idn_mapselector_getnotld(void);
+
+IDN_EXPORT const unsigned long *
+idn_mapselector_getdefaulttld(void);
+
+/*
+ * Mapselector object type.
+ */
+typedef struct idn_mapselector *idn_mapselector_t;
+
+/*
+ * Initialize module. Must be called before any other calls of
+ * the functions of this module.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_mapselector_initialize(void);
+
+/*
+ * Create a mapselector context.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_mapselector_create(idn_mapselector_t *ctxp);
+
+/*
+ * Decrement reference count of the mapselector `ctx' created by
+ * 'idn_mapselector_create', if it is still refered by another object.
+ * Otherwise, release all the memory allocated to the mapselector.
+ */
+IDN_EXPORT void
+idn_mapselector_destroy(idn_mapselector_t ctx);
+
+/*
+ * Increment reference count of the mapselector `ctx' created by
+ * 'idn_mapselector_create'.
+ */
+IDN_EXPORT void
+idn_mapselector_incrref(idn_mapselector_t ctx);
+
+/*
+ * Return the mapper for `tld' registered in `ctx', or return NULL if
+ * mapper for `tld' is not registered.
+ */
+IDN_EXPORT idn_mapper_t
+idn_mapselector_mapper(idn_mapselector_t ctx, const char *tld);
+
+/*
+ * Add mapping scheme `name' to the mapper for `tld' to the mapselector
+ * context `ctx'. If no mapper for `TLD' has not been registered, the
+ * function creates a new mapper for `tld', and then adds the given mapping
+ * scheme to the mapper. Otherwise, it adds the scheme to the mapper for
+ * TLD registered in `ctx'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_name -- the given tld or name is not valid.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_mapselector_add(idn_mapselector_t ctx, const char *tld, const char *name);
+
+IDN_EXPORT idn_result_t
+idn_mapselector_addall(idn_mapselector_t ctx, const char *tld,
+ const char **names, int nnames);
+
+/*
+ * Map an UCS4 string with the mapper for TLD of the domain name.
+ * If there is no mapper suitable for the domain name, the function
+ * simply copies the doman name.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ * idn_buffer_overflow -- output buffer is too small.
+ * idn_invalid_name -- the given tld is not valid.
+ */
+IDN_EXPORT idn_result_t
+idn_mapselector_map(idn_mapselector_t ctx, const unsigned long *from,
+ const char *tld, unsigned long *to, size_t tolen);
+
+IDN_EXPORT idn_result_t
+idn_mapselector_map2(idn_mapselector_t ctx, const unsigned long *from,
+ const unsigned long *tld, unsigned long *to,
+ size_t tolen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_MAPSELECTOR_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/nameprep.h b/contrib/idn/idnkit-1.0-src/include/idn/nameprep.h
new file mode 100644
index 0000000..af7d943
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/nameprep.h
@@ -0,0 +1,185 @@
+/* $Id: nameprep.h,v 1.1.1.1 2003/06/04 00:25:39 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_NAMEPREP_H
+#define IDN_NAMEPREP_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Perform NAMEPREP (mapping, prohibited/unassigned checking).
+ */
+
+#include <idn/export.h>
+#include <idn/result.h>
+
+/*
+ * BIDI type codes.
+ */
+typedef enum {
+ idn_biditype_r_al,
+ idn_biditype_l,
+ idn_biditype_others
+} idn_biditype_t;
+
+/*
+ * A Handle for nameprep operations.
+ */
+typedef struct idn_nameprep *idn_nameprep_t;
+
+
+/*
+ * The latest version of nameprep.
+ */
+#define IDN_NAMEPREP_CURRENT "RFC3491"
+
+/*
+ * Create a handle for nameprep operations.
+ * The handle is stored in '*handlep', which is used other functions
+ * in this module.
+ * The version of the NAMEPREP specification can be specified with
+ * 'version' parameter. If 'version' is NULL, the latest version
+ * is used.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_notfound -- specified version not found.
+ */
+IDN_EXPORT idn_result_t
+idn_nameprep_create(const char *version, idn_nameprep_t *handlep);
+
+/*
+ * Close a handle, which was created by 'idn_nameprep_create'.
+ */
+IDN_EXPORT void
+idn_nameprep_destroy(idn_nameprep_t handle);
+
+/*
+ * Perform character mapping on an UCS4 string specified by 'from', and
+ * store the result into 'to', whose length is specified by 'tolen'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_buffer_overflow -- result buffer is too small.
+ */
+IDN_EXPORT idn_result_t
+idn_nameprep_map(idn_nameprep_t handle, const unsigned long *from,
+ unsigned long *to, size_t tolen);
+
+/*
+ * Check if an UCS4 string 'str' contains any prohibited characters specified
+ * by the draft. If found, the pointer to the first such character is stored
+ * into '*found'. Otherwise '*found' will be NULL.
+ *
+ * Returns:
+ * idn_success -- check has been done properly. (But this
+ * does not mean that no prohibited character
+ * was found. Check '*found' to see the
+ * result.)
+ */
+IDN_EXPORT idn_result_t
+idn_nameprep_isprohibited(idn_nameprep_t handle, const unsigned long *str,
+ const unsigned long **found);
+
+/*
+ * Check if an UCS4 string 'str' contains any unassigned characters specified
+ * by the draft. If found, the pointer to the first such character is stored
+ * into '*found'. Otherwise '*found' will be NULL.
+ *
+ * Returns:
+ * idn_success -- check has been done properly. (But this
+ * does not mean that no unassinged character
+ * was found. Check '*found' to see the
+ * result.)
+ */
+IDN_EXPORT idn_result_t
+idn_nameprep_isunassigned(idn_nameprep_t handle, const unsigned long *str,
+ const unsigned long **found);
+
+/*
+ * Check if an UCS4 string 'str' is valid string specified by ``bidi check''
+ * of the draft. If it is not valid, the pointer to the first invalid
+ * character is stored into '*found'. Otherwise '*found' will be NULL.
+ *
+ * Returns:
+ * idn_success -- check has been done properly. (But this
+ * does not mean that the string was valid.
+ * Check '*found' to see the result.)
+ */
+IDN_EXPORT idn_result_t
+idn_nameprep_isvalidbidi(idn_nameprep_t handle, const unsigned long *str,
+ const unsigned long **found);
+
+/*
+ * The following functions are for internal use.
+ * They are used for this module to be add to the checker and mapper modules.
+ */
+IDN_EXPORT idn_result_t
+idn_nameprep_createproc(const char *parameter, void **handlep);
+
+IDN_EXPORT void
+idn_nameprep_destroyproc(void *handle);
+
+IDN_EXPORT idn_result_t
+idn_nameprep_mapproc(void *handle, const unsigned long *from,
+ unsigned long *to, size_t tolen);
+
+IDN_EXPORT idn_result_t
+idn_nameprep_prohibitproc(void *handle, const unsigned long *str,
+ const unsigned long **found);
+
+IDN_EXPORT idn_result_t
+idn_nameprep_unassignedproc(void *handle, const unsigned long *str,
+ const unsigned long **found);
+
+IDN_EXPORT idn_result_t
+idn_nameprep_bidiproc(void *handle, const unsigned long *str,
+ const unsigned long **found);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_NAMEPREP_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/normalizer.h b/contrib/idn/idnkit-1.0-src/include/idn/normalizer.h
new file mode 100644
index 0000000..e7e39b4
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/normalizer.h
@@ -0,0 +1,155 @@
+/* $Id: normalizer.h,v 1.1.1.1 2003/06/04 00:25:40 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_NORMALIZER_H
+#define IDN_NORMALIZER_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Domain name normalizer.
+ *
+ * Perform normalization on the specified strings. String must be
+ * in UCS4 encoding.
+ */
+
+#include <idn/export.h>
+#include <idn/result.h>
+
+/*
+ * Normalizer type (opaque).
+ */
+typedef struct idn_normalizer *idn_normalizer_t;
+
+/*
+ * Normalizer procedure type.
+ */
+typedef idn_result_t (*idn_normalizer_proc_t)(const unsigned long *from,
+ unsigned long *to, size_t tolen);
+
+/*
+ * Initialize this module.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_normalizer_initialize(void);
+
+/*
+ * Create a empty normalizer.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_normalizer_create(idn_normalizer_t *ctxp);
+
+/*
+ * Decrement reference count of the normalizer `ctx' created by
+ * 'idn_normalizer_create', if it is still refered by another object.
+ * Otherwise, release all the memory allocated to the normalizer.
+ */
+IDN_EXPORT void
+idn_normalizer_destroy(idn_normalizer_t ctx);
+
+/*
+ * Increment reference count of the normalizer `ctx' created by
+ * 'idn_normalizer_create'.
+ */
+IDN_EXPORT void
+idn_normalizer_incrref(idn_normalizer_t ctx);
+
+/*
+ * Add a normalization scheme to a normalizer.
+ *
+ * Multiple shemes can be added to a normalizer, and they will be
+ * applied in order.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_name -- unknown scheme was specified.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_normalizer_add(idn_normalizer_t ctx, const char *scheme_name);
+
+IDN_EXPORT idn_result_t
+idn_normalizer_addall(idn_normalizer_t ctx, const char **scheme_names,
+ int nschemes);
+
+/*
+ * Perform normalization(s) defined by a normalizer to the specified string,
+ * If the normalizer has two or more normalization schemes, they are
+ * applied in order.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_buffer_overflow -- output buffer is too small.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_normalizer_normalize(idn_normalizer_t ctx, const unsigned long *from,
+ unsigned long *to, size_t tolen);
+
+/*
+ * Register a new normalization scheme.
+ *
+ * You can override the default normalization schemes, if you want.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_normalizer_register(const char *scheme_name, idn_normalizer_proc_t proc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_NORMALIZER_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/punycode.h b/contrib/idn/idnkit-1.0-src/include/idn/punycode.h
new file mode 100644
index 0000000..5650a8e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/punycode.h
@@ -0,0 +1,70 @@
+/* $Id: punycode.h,v 1.1.1.1 2003/06/04 00:25:40 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_PUNYCODE_H
+#define IDN_PUNYCODE_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Punycode Converter.
+ */
+
+#include <idn/result.h>
+#include <idn/converter.h>
+
+extern idn_result_t
+idn__punycode_decode(idn_converter_t ctx, void *privdata,
+ const char *from, unsigned long *to, size_t tolen);
+
+extern idn_result_t
+idn__punycode_encode(idn_converter_t ctx, void *privdata,
+ const unsigned long *from, char *to, size_t tolen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_PUNYCODE_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/race.h b/contrib/idn/idnkit-1.0-src/include/idn/race.h
new file mode 100644
index 0000000..43a090b
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/race.h
@@ -0,0 +1,72 @@
+/* $Id: race.h,v 1.1.1.1 2003/06/04 00:25:40 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_RACE_H
+#define IDN_RACE_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * RACE Converter.
+ *
+ * See Internet Draft draft-ietf-idn-race-03.txt for details.
+ */
+
+#include <idn/result.h>
+#include <idn/converter.h>
+
+extern idn_result_t
+idn__race_encode(idn_converter_t ctx, void *privdata,
+ const unsigned long *from, char *to, size_t tolen);
+
+extern idn_result_t
+idn__race_decode(idn_converter_t ctx, void *privdata,
+ const char *from, unsigned long *to, size_t tolen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_RACE_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/res.h b/contrib/idn/idnkit-1.0-src/include/idn/res.h
new file mode 100644
index 0000000..ab7873d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/res.h
@@ -0,0 +1,309 @@
+/* $Id: res.h,v 1.1.1.1 2003/06/04 00:25:41 marka Exp $ */
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_RES_H
+#define IDN_RES_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Resolver library support.
+ *
+ * All the functions provided by this module requires IDN resolver
+ * configuration context of type 'idn_resconf_t' as an argument.
+ * This context holds information described in the configuration file
+ * (idn.conf). See idn_resconf module for details.
+ *
+ * All functions also accept NULL as the context, but since
+ * no conversion/normalization will be done in this case, it is
+ * pretty useless.
+ */
+
+#include <idn/export.h>
+#include <idn/resconf.h>
+#include <idn/result.h>
+
+typedef unsigned long idn_action_t;
+
+/*
+ * Actions
+ */
+#define IDN_LOCALCONV 0x00000001 /* Local encoding <-> UTF-8 conversion */
+#define IDN_DELIMMAP 0x00000002 /* Delimiter mapping */
+#define IDN_LOCALMAP 0x00000004 /* Local mapping */
+#define IDN_MAP 0x00000008 /* NAMEPREP map */
+#define IDN_NORMALIZE 0x00000010 /* NAMEPREP normalize */
+#define IDN_PROHCHECK 0x00000020 /* NAMEPREP prohibited character check */
+#define IDN_UNASCHECK 0x00000040 /* Unassigned code point check */
+#define IDN_BIDICHECK 0x00000080 /* bidirectional string check */
+#define IDN_ASCCHECK 0x00000100 /* Non-LDH ASCII check */
+#define IDN_IDNCONV 0x00000200 /* UTF-8 <-> IDN encoding conversion */
+#define IDN_LENCHECK 0x00000400 /* Label length check */
+#define IDN_RTCHECK 0x00000800 /* Round trip check */
+#define IDN_UNDOIFERR 0x00001000 /* Option: undo if error occurs */
+
+#define IDN_ENCODE_QUERY 0x00002000 /* Encode query string */
+#define IDN_DECODE_QUERY 0x00004000 /* Decode query string */
+
+#define IDN_ENCODE_APP \
+(IDN_ENCODE_QUERY | IDN_ASCCHECK) /* Standard encode */
+#define IDN_DECODE_APP \
+(IDN_DECODE_QUERY | IDN_ASCCHECK) /* Standard decode */
+
+#define IDN_ENCODE_STORED \
+(IDN_ENCODE_QUERY | IDN_ASCCHECK | IDN_UNASCHECK) /* Encode query string */
+#define IDN_DECODE_STORED \
+(IDN_DECODE_QUERY | IDN_ASCCHECK | IDN_UNASCHECK) /* Decode query string */
+
+
+#define IDN_NAMEPREP \
+(IDN_MAP | IDN_NORMALIZE | IDN_PROHCHECK | IDN_BIDICHECK)
+
+/*
+ * Enable or disable IDN conversion scheme.
+ *
+ * If on_off is 0, IDN conversion scheme is disabled. Otherwise, IDN
+ * conversion is enabled even when IDN_DISABLE is defined.
+ */
+IDN_EXPORT void
+idn_res_enable(int on_off);
+
+/*
+ * Encode internationalized domain name.
+ *
+ * The encoding process consists of the following 7 steps.
+ *
+ * 1. Local encoding to UTF-8 conversion
+ * Converts a domain name written with local encoding (e.g. ISO-
+ * 8859-1) to UTF-8.
+ * 2. Delimiter mapping,
+ * Maps certain characters to period (U+002E, FULL STOP).
+ * 3. Local mapping
+ * Apply character mappings according with the TLD of the domain
+ * name.
+ * 4. NAMEPREP
+ * Perform NAME preparation described in RFC3491.
+ * This step consists of the following 4 steps:
+ * 4.1. Mapping
+ * 4.2. Normalization
+ * 4.3. Prohibited character check
+ * 4.4. Unassigned check
+ * 5. ASCII range character check
+ * Checks if the domain name contains non-LDH ASCII character (not
+ * alpha-numeric or hypen), or it begins or end with hypen.
+ * 6. UTF-8 to IDN encoding conversion.
+ * Converts the domain name from UTF-8 to ACE (e.g. Punycode).
+ * 7. Length check
+ * Checks the length of each label.
+ *
+ * 'actions' specifies actions and options of the encoding procedure.
+ * Its value is a bitwise-or of the following flags:
+ *
+ * IDN_LOCALCONV -- perform local encoding to UTF-8 conversion (step 1)
+ * IDN_DELIMMAP -- perform delimiter mapping (step 2)
+ * IDN_LOCALMAP -- perform local mapping (step 3)
+ * IDN_MAP -- perform mapping (step 4.1)
+ * IDN_NORMALIZE -- perform normalization (step 4.2)
+ * IDN_PROHCHECK -- perform prohibited character check (step 4.3)
+ * IDN_UNASCHECK -- perform unassigned codepoint check (step 4.4)
+ * IDN_ASCCHECK -- perform ASCII range character check (step 5)
+ * IDN_IDNCONV -- perform UTF-8 to IDN encoding conversion (step 6)
+ * IDN_LENCHECK -- perform length check (step 7)
+ *
+ * Also the following flags are provided for convinience:
+ *
+ * IDN_ENCODE_QUERY -- On libidnkit, perform step 1..7, except for step
+ * 4.4 and 5.
+ * On libidnkitlite, perform step 2..7, except for
+ * step 4.4 and 5.
+ * IDN_ENCODE_STORED -- On libidnkit, perform step 1..7, except for step
+ * 5.
+ * On libidnkitlite, perform step 2..7, except for
+ * step 5.
+ * IDN_ENCODE_APP -- Same as IDN_ENCODE_QUERY.
+ * IDN_NAMEPREP -- perform NAMEPREP (step 4) without unassigned
+ * codepoint check (step 4.4).
+ *
+ * The following flag does not corresponding to a particular action,
+ * but an option of conversion process:
+ *
+ * IDN_UNDOIFERR -- If any step fails, the original input name is
+ * returned.
+ *
+ * Note that if no flags are specified, 'idn_encodename' does nothing
+ * fancy, just copies the given name verbatim.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_action -- invalid action flag specified.
+ * idn_invalid_encoding -- the given string has invalid/illegal
+ * byte sequence.
+ * idn_invalid_length -- invalid length of a label.
+ * idn_prohibited -- prohibited/unassigned code point found.
+ * idn_buffer_overflow -- 'tolen' is too small.
+ * idn_nomemory -- malloc failed.
+ *
+ * Also, if this function is called without calling 'idn_nameinit',
+ * the following error codes might be returned.
+ * idn_nofile -- cannot open the configuration file.
+ * idn_invalid_syntax -- syntax error found in the file.
+ * idn_invalid_name -- there are invalid names (encoding,
+ * normalization etc.).
+ */
+IDN_EXPORT idn_result_t
+idn_res_encodename(idn_resconf_t ctx, idn_action_t actions, const char *from,
+ char *to, size_t tolen);
+
+/*
+ * Decode internationalized domain name.
+ *
+ * The decoding process consists of the following 5 steps.
+ *
+ * 1. delimiter mapping
+ * Maps certain characters to period (U+002E, FULL STOP).
+ * 2. NAMEPREP
+ * Perform NAME preparation described in RFC3491.
+ * This step consists of the following 4 steps:
+ * 2.1. Mapping
+ * 2.2. Normalization
+ * 2.3. Prohibited character check
+ * 2.4. Unassigned check
+ * 3. IDN encoding to UTF-8 conversion.
+ * Converts the domain name from ACE (e.g. Punycode) to UCS4.
+ * 4. Perform round-trip check.
+ * Encode the result of step 3, and then compare it with the result
+ * of the step 2. If they are different, the check is failed.
+ * 5. Convert UTF-8 to local encoding.
+ * If a character in the domain name cannot be converted to local
+ * encoding, the conversion is failed.
+ *
+ * 'actions' specifies actions of the decoding procedure.
+ * Its value is a bitwise-or of the following flags:
+ *
+ * IDN_DELIMMAP -- perform delimiter mapping (step 1)
+ * IDN_MAP -- perform mapping (step 2.1)
+ * IDN_NORMALIZE -- perform normalization (step 2.2)
+ * IDN_PROHCHECK -- perform prohibited character check (step 2.3)
+ * IDN_UNASCHECK -- perform unassigned codepoint check (step 2.4)
+ * IDN_IDNCONV -- perform IDN encoding to UTF-8 conversion (step 3)
+ * IDN_RTCHECK -- perform round-trip check (step 4)
+ * IDN_ASCCHECK -- perform ASCII range character check while
+ * round-trip check (step 4.1)
+ * IDN_LOCALCONV -- perform UTF-8 to local encoding conversion (step 5)
+ *
+ * Also the following flags are provided for the convenience:
+ *
+ * IDN_DECODE_QUERY -- On libidnkit, perform step 1..5, except for step
+ * 2.4 and 4.1.
+ * On libidnkitlite, perform step 1..3, except for
+ * step 2.4 and 4.1.
+ * IDN_DECODE_STORED -- On libidnkit, perform step 1..5, except for step
+ * 4.1.
+ * On libidnkitlite, perform step 1..3, except for
+ * step 4.1.
+ * IDN_DECODE_APP -- Same as IDN_DECODE_QUERY.
+ * IDN_NAMEPREP -- perform NAMEPREP (step 2) without unassigned
+ * codepoint check (step 2.4).
+ *
+ * If any step fails, the original input name is returned.
+ * 'actions' specifies what actions to take when decoding, and is
+ * a bitwise-or of the following flags:
+ *
+ * Note that if no flags are specified, 'idn_decodename' does nothing
+ * but copying the given name verbatim.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_action -- invalid action flag specified.
+ * idn_invalid_encoding -- the given string has invalid/illegal
+ * byte sequence.
+ * idn_buffer_overflow -- 'tolen' is too small.
+ * idn_invalid_action -- length of a label is not 1..63 characters.
+ * idn_nomemory -- malloc failed.
+ *
+ * Also, if this function is called without calling 'idn_nameinit',
+ * the following error codes might be returned.
+ * idn_nofile -- cannot open the configuration file.
+ * idn_invalid_syntax -- syntax error found in the file.
+ * idn_invalid_name -- there are invalid names (encoding,
+ * normalization etc.).
+ */
+IDN_EXPORT idn_result_t
+idn_res_decodename(idn_resconf_t ctx, idn_action_t actions, const char *from,
+ char *to, size_t tolen);
+
+/*
+ * Decode internationalized domain name with auxiliary encoding
+ * support.
+ *
+ * This is another API for IDN string decode. The difference between
+ * two is whether the encoding conversion from auxiliary encoding to
+ * UTF-8 occurs prior to the actual decode process (read description
+ * of idn_res_decodename() above) or not.
+ *
+ * If auxencoding is NULL, from is treated as UTF-8 encoded string.
+ *
+ * Other arguments serve exactly same role as those of
+ * idn_res_decodename().
+ */
+idn_result_t
+idn_res_decodename2(idn_resconf_t ctx, idn_action_t actions, const char *from,
+ char *to, size_t tolen, const char *auxencoding);
+
+/*
+ * Convert `actions' to a string, and then return the string.
+ * This function is for internal use only.
+ *
+ * Note that this function returns a pointer to static buffer.
+ */
+extern const char *
+idn__res_actionstostring(idn_action_t actions);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_RES_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/resconf.h b/contrib/idn/idnkit-1.0-src/include/idn/resconf.h
new file mode 100644
index 0000000..1aed8bd
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/resconf.h
@@ -0,0 +1,323 @@
+/* $Id: resconf.h,v 1.1.1.1 2003/06/04 00:25:41 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_RESCONF_H
+#define IDN_RESCONF_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * IDN resolver configuration.
+ */
+
+#include <idn/export.h>
+#include <idn/result.h>
+#include <idn/converter.h>
+#include <idn/normalizer.h>
+#include <idn/checker.h>
+#include <idn/mapper.h>
+#include <idn/mapselector.h>
+#include <idn/delimitermap.h>
+
+/*
+ * Configuration type (opaque).
+ */
+typedef struct idn_resconf *idn_resconf_t;
+
+/*
+ * Initialize.
+ *
+ * Initialize this module and underlying ones. Must be called before
+ * any other functions of this module.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_resconf_initialize(void);
+
+/*
+ * Create a configuration context.
+ *
+ * Create an empty context and store it in '*ctxp'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_resconf_create(idn_resconf_t *ctxp);
+
+/*
+ * Destroy the configuration context.
+ *
+ * Destroy the configuration context created by 'idn_resconf_create',
+ * and release memory for it.
+ */
+IDN_EXPORT void
+idn_resconf_destroy(idn_resconf_t ctx);
+
+/*
+ * Increment reference count of the context created by 'idn_resconf_create'.
+ */
+IDN_EXPORT void
+idn_resconf_incrref(idn_resconf_t ctx);
+
+/*
+ * Set default configurations to resconf context.
+ *
+ * "default configurations" means current nameprep and IDN encoding
+ * which IDN standard document suggests.
+ *
+ * Warning: configurations set previously are removed.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_syntax -- syntax error found.
+ * idn_invalid_name -- invalid encoding/nomalization name is
+ * specified.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_resconf_setdefaults(idn_resconf_t ctx);
+
+/*
+ * Load configuration file.
+ *
+ * Parse a configuration file whose name is specified by 'file',
+ * store the result in 'ctx'. If 'file' is NULL, the default file is
+ * loaded.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nofile -- couldn't open specified file.
+ * idn_invalid_syntax -- syntax error found.
+ * idn_invalid_name -- invalid encoding/nomalization name is
+ * specified.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_resconf_loadfile(idn_resconf_t ctx, const char *file);
+
+/*
+ * Get the pathname of the default configuration file.
+ *
+ * Returns:
+ * the pathname of the default configuration file.
+ */
+IDN_EXPORT char *
+idn_resconf_defaultfile(void);
+
+/*
+ * Get an object of lower module that `ctx' holds.
+ */
+IDN_EXPORT idn_delimitermap_t
+idn_resconf_getdelimitermap(idn_resconf_t ctx);
+
+IDN_EXPORT idn_converter_t
+idn_resconf_getidnconverter(idn_resconf_t ctx);
+
+IDN_EXPORT idn_converter_t
+idn_resconf_getauxidnconverter(idn_resconf_t ctx);
+
+IDN_EXPORT idn_converter_t
+idn_resconf_getlocalconverter(idn_resconf_t ctx);
+
+IDN_EXPORT idn_mapselector_t
+idn_resconf_getlocalmapselector(idn_resconf_t ctx);
+
+IDN_EXPORT idn_mapper_t
+idn_resconf_getmapper(idn_resconf_t ctx);
+
+IDN_EXPORT idn_normalizer_t
+idn_resconf_getnormalizer(idn_resconf_t ctx);
+
+IDN_EXPORT idn_checker_t
+idn_resconf_getprohibitchecker(idn_resconf_t ctx);
+
+IDN_EXPORT idn_checker_t
+idn_resconf_getunassignedchecker(idn_resconf_t ctx);
+
+IDN_EXPORT idn_checker_t
+idn_resconf_getbidichecker(idn_resconf_t ctx);
+
+/*
+ * Set an object of lower module to `ctx'.
+ */
+IDN_EXPORT void
+idn_resconf_setdelimitermap(idn_resconf_t ctx,
+ idn_delimitermap_t delimiter_mapper);
+
+IDN_EXPORT void
+idn_resconf_setidnconverter(idn_resconf_t ctx,
+ idn_converter_t idn_coverter);
+
+IDN_EXPORT void
+idn_resconf_setauxidnconverter(idn_resconf_t ctx,
+ idn_converter_t aux_idn_coverter);
+
+IDN_EXPORT void
+idn_resconf_setlocalconverter(idn_resconf_t ctx,
+ idn_converter_t local_converter);
+
+IDN_EXPORT void
+idn_resconf_setlocalmapselector(idn_resconf_t ctx,
+ idn_mapselector_t map_selector);
+
+IDN_EXPORT void
+idn_resconf_setmapper(idn_resconf_t ctx, idn_mapper_t mapper);
+
+IDN_EXPORT void
+idn_resconf_setnormalizer(idn_resconf_t ctx, idn_normalizer_t normalizer);
+
+IDN_EXPORT void
+idn_resconf_setprohibitchecker(idn_resconf_t ctx,
+ idn_checker_t prohibit_checker);
+
+IDN_EXPORT void
+idn_resconf_setunassignedchecker(idn_resconf_t ctx,
+ idn_checker_t unassigned_checker);
+
+IDN_EXPORT void
+idn_resconf_setbidichecker(idn_resconf_t ctx,
+ idn_checker_t bidi_checker);
+
+/*
+ * Set name or add names to an object of lower module that `ctx' holds.
+ */
+IDN_EXPORT idn_result_t
+idn_resconf_setidnconvertername(idn_resconf_t ctx, const char *name,
+ int flags);
+
+IDN_EXPORT idn_result_t
+idn_resconf_setauxidnconvertername(idn_resconf_t ctx, const char *name,
+ int flags);
+
+IDN_EXPORT idn_result_t
+idn_resconf_addalldelimitermapucs(idn_resconf_t ctx, unsigned long *v, int nv);
+
+IDN_EXPORT idn_result_t
+idn_resconf_setlocalconvertername(idn_resconf_t ctx, const char *name,
+ int flags);
+
+IDN_EXPORT idn_result_t
+idn_resconf_addalllocalmapselectornames(idn_resconf_t ctx, const char *tld,
+ const char **names, int nnames);
+
+IDN_EXPORT idn_result_t
+idn_resconf_addallmappernames(idn_resconf_t ctx, const char **names,
+ int nnames);
+
+IDN_EXPORT idn_result_t
+idn_resconf_addallnormalizernames(idn_resconf_t ctx, const char **names,
+ int nnames);
+
+IDN_EXPORT idn_result_t
+idn_resconf_addallprohibitcheckernames(idn_resconf_t ctx, const char **names,
+ int nnames);
+
+IDN_EXPORT idn_result_t
+idn_resconf_addallunassignedcheckernames(idn_resconf_t ctx, const char **names,
+ int nnames);
+
+IDN_EXPORT idn_result_t
+idn_resconf_addallbidicheckernames(idn_resconf_t ctx, const char **names,
+ int nnames);
+
+IDN_EXPORT idn_result_t
+idn_resconf_setnameprepversion(idn_resconf_t ctx, const char *version);
+
+/*
+ * These macros are provided for backward compatibility to mDNkit 2.1
+ * and older.
+ */
+IDN_EXPORT void
+idn_resconf_setalternateconverter(idn_resconf_t ctx,
+ idn_converter_t alternate_converter);
+
+IDN_EXPORT idn_result_t
+idn_resconf_setalternateconvertername(idn_resconf_t ctx, const char *name,
+ int flags);
+
+IDN_EXPORT idn_converter_t
+idn_resconf_getalternateconverter(idn_resconf_t ctx);
+
+
+/*
+ * These macros are provided for backward compatibility to idnkit 1.x.
+ */
+#define idn_resconf_localconverter(ctx) \
+ idn_resconf_getlocalconverter(ctx)
+
+#define idn_resconf_idnconverter(ctx) \
+ idn_resconf_getidnconverter(ctx)
+
+#define idn_resconf_alternateconverter(ctx) \
+ idn_resconf_getalternateconverter(ctx)
+
+#define idn_resconf_normalizer(ctx) \
+ idn_resconf_getnormalizer(ctx)
+
+#define idn_resconf_mapper(ctx) \
+ idn_resconf_getmapper(ctx)
+
+#define idn_resconf_delimitermap(ctx) \
+ idn_resconf_getdelimitermap(ctx)
+
+#define idn_resconf_localmapselector(ctx) \
+ idn_resconf_getlocalmapselector(ctx)
+
+#define idn_resconf_prohibitchecker(ctx) \
+ idn_resconf_getprohibitchecker(ctx)
+
+#define idn_resconf_unassignedchecker(ctx) \
+ idn_resconf_getunassignedchecker(ctx)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_RESCONF_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/result.h b/contrib/idn/idnkit-1.0-src/include/idn/result.h
new file mode 100644
index 0000000..c044fcb
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/result.h
@@ -0,0 +1,86 @@
+/* $Id: result.h,v 1.1.1.1 2003/06/04 00:25:42 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_RESULT_H
+#define IDN_RESULT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <idn/export.h>
+
+/*
+ * libidnkit result code.
+ */
+typedef enum {
+ idn_success,
+ idn_notfound,
+ idn_invalid_encoding,
+ idn_invalid_syntax,
+ idn_invalid_name,
+ idn_invalid_message,
+ idn_invalid_action,
+ idn_invalid_codepoint,
+ idn_invalid_length,
+ idn_buffer_overflow,
+ idn_noentry,
+ idn_nomemory,
+ idn_nofile,
+ idn_nomapping,
+ idn_context_required,
+ idn_prohibited,
+ idn_failure /* !!This must be the last one!! */
+} idn_result_t;
+
+/*
+ * Get the string description of a result code.
+ */
+IDN_EXPORT char *
+idn_result_tostring(idn_result_t result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_RESULT_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/strhash.h b/contrib/idn/idnkit-1.0-src/include/idn/strhash.h
new file mode 100644
index 0000000..0a72a86
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/strhash.h
@@ -0,0 +1,123 @@
+/* $Id: strhash.h,v 1.1.1.1 2003/06/04 00:25:42 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_STRHASH_H
+#define IDN_STRHASH_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * String-keyed hash table
+ *
+ * Just a hash table. Nothing special. Number of hash buckets
+ * grows automatically.
+ */
+
+#include <idn/result.h>
+
+/*
+ * Hash table type, which is opaque.
+ */
+typedef struct idn__strhash *idn__strhash_t;
+
+/*
+ * Hash value free proc.
+ */
+typedef void (*idn__strhash_freeproc_t)(void *value);
+
+/*
+ * Create a hash table.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+extern idn_result_t
+idn__strhash_create(idn__strhash_t *hashp);
+
+/*
+ * Delete a hash table created by 'idn__strhash_create'.
+ * If 'proc' is not NULL, it is called for each value in the
+ * hash to release memory for them.
+ */
+extern void
+idn__strhash_destroy(idn__strhash_t hash, idn__strhash_freeproc_t proc);
+
+/*
+ * Register an item to the hash table. This function makes a
+ * private copy of the key string.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+extern idn_result_t
+idn__strhash_put(idn__strhash_t hash, const char *key, void *value);
+
+/*
+ * Find an item with the specified key.
+ *
+ * Returns:
+ * idn_success -- ok. found.
+ * idn_noentry -- not found.
+ */
+extern idn_result_t
+idn__strhash_get(idn__strhash_t hash, const char *key, void **valuep);
+
+/*
+ * Check if an item with the specified key exists.
+ *
+ * Returns:
+ * 1 -- yes.
+ * 0 -- no.
+ */
+extern int
+idn__strhash_exists(idn__strhash_t hash, const char *key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_STRHASH_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/ucs4.h b/contrib/idn/idnkit-1.0-src/include/idn/ucs4.h
new file mode 100644
index 0000000..ceb1f53
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/ucs4.h
@@ -0,0 +1,103 @@
+/* $Id: ucs4.h,v 1.1.1.1 2003/06/04 00:25:42 marka Exp $ */
+/*
+ * Copyright (c) 2002 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_UCS4_H
+#define IDN_UCS4_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * UCS4 encoded string facility.
+ */
+
+#include <idn/export.h>
+#include <idn/result.h>
+
+/*
+ * UCS4 to UTF-16 conversion and vice versa.
+ */
+IDN_EXPORT idn_result_t
+idn_ucs4_ucs4toutf16(const unsigned long *ucs4, unsigned short *utf16,
+ size_t tolen);
+
+IDN_EXPORT idn_result_t
+idn_ucs4_utf16toucs4(const unsigned short *utf16, unsigned long *ucs4,
+ size_t tolen);
+
+/*
+ * UCS4 to UTF-8 conversion and vice versa.
+ */
+IDN_EXPORT idn_result_t
+idn_ucs4_utf8toucs4(const char *utf8, unsigned long *ucs4, size_t tolen);
+
+IDN_EXPORT idn_result_t
+idn_ucs4_ucs4toutf8(const unsigned long *ucs4, char *utf8, size_t tolen);
+
+/*
+ * UCS4 version of string operation functions.
+ */
+IDN_EXPORT size_t
+idn_ucs4_strlen(const unsigned long *ucs4);
+
+IDN_EXPORT unsigned long *
+idn_ucs4_strcpy(unsigned long *to, const unsigned long *from);
+
+IDN_EXPORT unsigned long *
+idn_ucs4_strcat(unsigned long *to, const unsigned long *from);
+
+IDN_EXPORT int
+idn_ucs4_strcmp(const unsigned long *str1, const unsigned long *str2);
+
+IDN_EXPORT int
+idn_ucs4_strcasecmp(const unsigned long *str1, const unsigned long *str2);
+
+IDN_EXPORT unsigned long *
+idn_ucs4_strdup(const unsigned long *str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_UCS4_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/ucsmap.h b/contrib/idn/idnkit-1.0-src/include/idn/ucsmap.h
new file mode 100644
index 0000000..67af523
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/ucsmap.h
@@ -0,0 +1,131 @@
+/* $Id: ucsmap.h,v 1.1.1.1 2003/06/04 00:25:42 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_UCSMAP_H
+#define IDN_UCSMAP_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Perform UCS character mapping.
+ * This module support one-to-N mapping (N may be zero, one or more).
+ */
+
+#include <idn/export.h>
+#include <idn/result.h>
+
+/*
+ * Mapper type (opaque).
+ */
+typedef struct idn_ucsmap *idn_ucsmap_t;
+
+/*
+ * Create an empty mapping. The reference count is set to 1.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_ucsmap_create(idn_ucsmap_t *ctxp);
+
+/*
+ * Decrement the reference count of the given set, and if it reaches zero,
+ * release all the memory allocated for it.
+ */
+IDN_EXPORT void
+idn_ucsmap_destroy(idn_ucsmap_t ctx);
+
+/*
+ * Increment the reference count of the given set by one, so that
+ * the map can be shared.
+ */
+IDN_EXPORT void
+idn_ucsmap_incrref(idn_ucsmap_t ctx);
+
+/*
+ * Add a mapping.
+ * 'ucs' is the character to be mapped, 'map' points an array of mapped
+ * characters of length 'maplen'. 'map' may be NULL if 'maplen' is zero,
+ * meaning one-to-none mapping.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ * idn_failure -- already fixed by 'idn_ucsmap_fix',
+ * or too large maplen.
+ */
+IDN_EXPORT idn_result_t
+idn_ucsmap_add(idn_ucsmap_t ctx, unsigned long ucs, unsigned long *map,
+ size_t maplen);
+
+/*
+ * Perform internal arrangement of the map for lookup.
+ * Once it is fixed, 'idn_ucsmap_add' cannot be permitted to the map.
+ */
+IDN_EXPORT void
+idn_ucsmap_fix(idn_ucsmap_t ctx);
+
+/*
+ * Find the mapping for the given character.
+ * 'idn_ucsmap_fix' must be performed before calling this function.
+ * Find the mapping for 'v' and store the result to 'to'. The length
+ * of the mapped sequence is stored in '*maplenp'. 'tolen' specifies
+ * the length allocated for 'to'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomapping -- specified character has no mapping.
+ * idn_failure -- not fixed by 'idn_ucsmap_fix' yet.
+ */
+IDN_EXPORT idn_result_t
+idn_ucsmap_map(idn_ucsmap_t ctx, unsigned long v, unsigned long *to,
+ size_t tolen, size_t *maplenp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_UCSMAP_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/ucsset.h b/contrib/idn/idnkit-1.0-src/include/idn/ucsset.h
new file mode 100644
index 0000000..c50a4d0
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/ucsset.h
@@ -0,0 +1,145 @@
+/* $Id: ucsset.h,v 1.1.1.1 2003/06/04 00:25:43 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_UCSSET_H
+#define IDN_UCSSET_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * A 'set' of UCS codepoints.
+ */
+
+#include <idn/export.h>
+#include <idn/result.h>
+
+/*
+ * Type representing a set (opaque).
+ */
+typedef struct idn_ucsset *idn_ucsset_t;
+
+
+/*
+ * Create an empty set. The reference count is set to 1.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ */
+IDN_EXPORT idn_result_t
+idn_ucsset_create(idn_ucsset_t *ctxp);
+
+/*
+ * Decrement the reference count of the given set, and if it reaches zero,
+ * release all the memory allocated for it.
+ */
+IDN_EXPORT void
+idn_ucsset_destroy(idn_ucsset_t ctx);
+
+/*
+ * Increments the reference count by one.
+ */
+IDN_EXPORT void
+idn_ucsset_incrref(idn_ucsset_t ctx);
+
+/*
+ * Add a UCS code point to the set.
+ * The set must be in the building phase -- that is, before 'idn_ucsset_fix'
+ * is called for the set.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_code -- code point out of range.
+ * idn_nomemory -- malloc failed.
+ * idn_failure -- already fixed by 'idn_ucsset_fix'.
+ */
+IDN_EXPORT idn_result_t
+idn_ucsset_add(idn_ucsset_t ctx, unsigned long v);
+
+/*
+ * Add a range of code points (from 'from' to 'to', inclusive) to the set.
+ * 'from' must not be greater than 'to'.
+ * This function is similar to 'idn_ucsset_add' except that it accepts
+ * range of code points.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_code -- code point out of range, or the range
+ * specification is invalid.
+ * idn_nomemory -- malloc failed.
+ * idn_failure -- already fixed by 'idn_ucsset_fix'.
+ */
+IDN_EXPORT idn_result_t
+idn_ucsset_addrange(idn_ucsset_t ctx, unsigned long from, unsigned long to);
+
+/*
+ * Perform internal arrangement of the set for lookup.
+ * Before calling this function, a set is in 'building' phase, and code
+ * points can be added freely by 'idn_ucsset_add' or 'idn_ucsset_addrange'.
+ * But once it is fixed by this function, the set becomes immutable, and
+ * it shifts into 'lookup' phase.
+ */
+IDN_EXPORT void
+idn_ucsset_fix(idn_ucsset_t ctx);
+
+/*
+ * Find if the given code point is in the set.
+ * The set must be in the lookup phase -- in other words, 'idn_ucsset_fix'
+ * must be called for the set before calling this function.
+ * '*found' is set to 1 if the specified code point is in the set, 0 otherwise.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_invalid_code -- specified code point is out of range.
+ * idn_failure -- not fixed by 'idn_ucsset_fix' yet.
+ */
+IDN_EXPORT idn_result_t
+idn_ucsset_lookup(idn_ucsset_t ctx, unsigned long v, int *found);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_UCSSET_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/unicode.h b/contrib/idn/idnkit-1.0-src/include/idn/unicode.h
new file mode 100644
index 0000000..f9b5bb4
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/unicode.h
@@ -0,0 +1,164 @@
+/* $Id: unicode.h,v 1.1.1.1 2003/06/04 00:25:43 marka Exp $ */
+/*
+ * Copyright (c) 2000,2001 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_UNICODE_H
+#define IDN_UNICODE_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Unicode attributes retriever.
+ *
+ * All the information this module provides is based on UnicodeData.txt,
+ * CompositionExclusions-1.txt and SpecialCasing.txt, all of which can be
+ * obtained from unicode.org.
+ *
+ * Unicode characters are represented as 'unsigned long'.
+ */
+
+#include <idn/result.h>
+
+/*
+ * A Handle for Unicode versions.
+ */
+typedef struct idn__unicode_ops *idn__unicode_version_t;
+
+/*
+ * Context information for case conversion.
+ */
+typedef enum {
+ idn__unicode_context_unknown,
+ idn__unicode_context_final,
+ idn__unicode_context_nonfinal
+} idn__unicode_context_t;
+
+/*
+ * Create a handle for a specific Unicode version.
+ * The version number (such as "3.0.1") is specified by 'version' parameter.
+ * If it is NULL, the latest version is used.
+ * The handle is stored in '*versionp', which is used various functions
+ * in this and unormalize modules.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_notfound -- specified version not found.
+ */
+extern idn_result_t
+idn__unicode_create(const char *version, idn__unicode_version_t *versionp);
+
+/*
+ * Close a handle which was created by 'idn__unicode_create'.
+ */
+extern void
+idn__unicode_destroy(idn__unicode_version_t version);
+
+/*
+ * Get canonical class.
+ *
+ * For characters out of unicode range (i.e. above 0xffff), 0 will
+ * be returned.
+ */
+extern int
+idn__unicode_canonicalclass(idn__unicode_version_t version, unsigned long c);
+
+/*
+ * Decompose a character.
+ *
+ * Decompose character given by 'c', and put the result into 'v',
+ * which can hold 'vlen' characters. The number of decomposed characters
+ * will be stored in '*decomp_lenp'.
+ *
+ * If 'compat' is true, compatibility decomposition is performed.
+ * Otherwise canonical decomposition is done.
+ *
+ * Since decomposition is done recursively, no further decomposition
+ * will be needed.
+ *
+ * Returns:
+ * idn_success -- ok, decomposed.
+ * idn_notfound -- no decomposition possible.
+ * idn_buffer_overflow -- 'vlen' is too small.
+ */
+extern idn_result_t
+idn__unicode_decompose(idn__unicode_version_t version,
+ int compat, unsigned long *v, size_t vlen,
+ unsigned long c, int *decomp_lenp);
+
+/*
+ * Perform canonical composition.
+ *
+ * Do canonical composition to the character sequence 'c1' and 'c2', put the
+ * result into '*compp'.
+ *
+ * Since Unicode Nomalization Froms requires only canonical composition,
+ * compatibility composition is not supported.
+ *
+ * Returns:
+ * idn_success -- ok, composed.
+ * idn_notfound -- no composition possible.
+ */
+extern idn_result_t
+idn__unicode_compose(idn__unicode_version_t version,
+ unsigned long c1, unsigned long c2, unsigned long *compp);
+
+/*
+ * Returns if there may be a canonical composition sequence which starts
+ * with the given character.
+ *
+ * Returns:
+ * 1 -- there may be a composition sequence
+ * (maybe not).
+ * 0 -- no, there is definitely no such sequences.
+ */
+extern int
+idn__unicode_iscompositecandidate(idn__unicode_version_t version,
+ unsigned long c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_UNICODE_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/unormalize.h b/contrib/idn/idnkit-1.0-src/include/idn/unormalize.h
new file mode 100644
index 0000000..3d43270
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/unormalize.h
@@ -0,0 +1,86 @@
+/* $Id: unormalize.h,v 1.1.1.1 2003/06/04 00:25:44 marka Exp $ */
+/*
+ * Copyright (c) 2000,2001 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_UNORMALIZE_H
+#define IDN_UNORMALIZE_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Unicode Normalizations.
+ *
+ * Perform 4 normalizations defined by 'Unicode Normalization Forms'
+ * (http://www.unicode.org/unicode/reports/tr15)
+ *
+ * All of the functions use UCS4 encoding for input/output.
+ */
+
+#include <idn/result.h>
+#include <idn/unicode.h>
+
+/*
+ * Perform Unicode Normalication Form C and KC.
+ *
+ * They take NUL-terminated UCS4 encoded string 'from', perform
+ * the normalization specified by 'version', put the result
+ * (also a NUL-terminated UCS4 encoded string) to 'to', which must be
+ * able to hold at least 'tolen' bytes.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_nomemory -- malloc failed.
+ * idn_buffer_overflow -- 'tolen' is too small.
+ */
+extern idn_result_t
+idn__unormalize_formkc(idn__unicode_version_t version,
+ const unsigned long *from, unsigned long *to,
+ size_t tolen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_UNORMALIZE_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/utf8.h b/contrib/idn/idnkit-1.0-src/include/idn/utf8.h
new file mode 100644
index 0000000..ee5f589
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/utf8.h
@@ -0,0 +1,137 @@
+/* $Id: utf8.h,v 1.1.1.1 2003/06/04 00:25:44 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_UTF8_H
+#define IDN_UTF8_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * UTF-8 encoded string facility.
+ */
+
+#include <idn/export.h>
+
+/*
+ * Get the length of a character.
+ *
+ * Get the length (in bytes) of a character whose first byte is pointed
+ * by 's'. Since this function only looks one first byte to determine the
+ * length, it is possible some of the following bytes are invalid.
+ */
+IDN_EXPORT int
+idn_utf8_mblen(const char *s);
+
+/*
+ * Get one character.
+ *
+ * Get the first character of the string pointed by 's', and copy it
+ * to 'buf', whose length is 'len'. Returns the number of bytes copied,
+ * or zero if the encoding is invalid or len is too small.
+ *
+ * The area pointed by 'buf' must be large enough to store any UTF-8 encoded
+ * character.
+ *
+ * Note that the copied string is not NUL-terminated.
+ */
+IDN_EXPORT int
+idn_utf8_getmb(const char *s, size_t len, char *buf);
+
+/*
+ * Get one character in UCS-4.
+ *
+ * Similar to 'idn_utf8_getmb', except that the result is not in UTF-8
+ * encoding, but in UCS-4 format (plain 32bit integer value).
+ */
+IDN_EXPORT int
+idn_utf8_getwc(const char *s, size_t len, unsigned long *vp);
+
+/*
+ * Put one character.
+ *
+ * This function is an opposite of 'idn_utf8_getwc'. It takes a UCS-4
+ * value 'v', convert it to UTF-8 encoded sequence, and store it to 's',
+ * whose length is 'len'. It returns the number of bytes written, or
+ * zero 'v' is out of range or 'len' is too small.
+ */
+IDN_EXPORT int
+idn_utf8_putwc(char *s, size_t len, unsigned long v);
+
+/*
+ * Check the validity of UTF-8 encoded character.
+ *
+ * Check if the character pointed by 's' is a valid UTF-8 encoded
+ * character. Return the length of the character (in bytes) if it is valid,
+ * 0 otherwise.
+ */
+IDN_EXPORT int
+idn_utf8_isvalidchar(const char *s);
+
+/*
+ * Check the validity of UTF-8 encoded string.
+ *
+ * Check if the NUL-terminated string 's' is valid as a UTF-8 encoded
+ * string. Return 1 if it is valid, 0 otherwise.
+ */
+IDN_EXPORT int
+idn_utf8_isvalidstring(const char *s);
+
+/*
+ * Find first byte of a character.
+ *
+ * Find the first byte of a character 's' points to. 's' may point
+ * the 2nd or later byte of a character. 'known_top' is a pointer to
+ * a string which contains 's', and is known to be the first byte of
+ * a character. If it couldn't find the first byte between 'known_top'
+ * and 's', NULL will be returned.
+ */
+IDN_EXPORT char *
+idn_utf8_findfirstbyte(const char *s, const char *known_top);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_UTF8_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/util.h b/contrib/idn/idnkit-1.0-src/include/idn/util.h
new file mode 100644
index 0000000..cde34a6
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/util.h
@@ -0,0 +1,98 @@
+/* $Id: util.h,v 1.1.1.1 2003/06/04 00:25:44 marka Exp $ */
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_UTIL_H
+#define IDN_UTIL_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Utility functions.
+ */
+
+/*
+ * Check ACE prefix.
+ *
+ * These functions examine whether `str' begins with `prefix'.
+ * They disregard the case difference of ASCII letters ([A-Za-z]).
+ * They return 1 if `str' has the ACE prefix, 0 otherwise.
+ */
+extern int
+idn__util_asciihaveaceprefix(const char *str, const char *prefix);
+extern int
+idn__util_ucs4haveaceprefix(const unsigned long *str, const char *prefix);
+
+/*
+ * Check if all codepoints in the UCS4 string `str' are in the ASCII
+ * range (i.e. U+0000...U+007F).
+ *
+ * The function return 1 if it is, 0 otherwise.
+ */
+extern int
+idn__util_ucs4isasciirange(const unsigned long *str);
+
+/*
+ * Get registry information from the system. (Windows only)
+ */
+#ifdef WIN32
+/*
+ * registry top type.
+ */
+typedef enum {
+ idn__util_hkey_currentuser,
+ idn__util_hkey_localmachine
+} idn__util_hkey_t;
+
+extern int
+idn__util_getregistrystring(idn__util_hkey_t topkey, const char *name,
+ char *str, size_t length);
+#endif /* WIN32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_UTIL_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/idn/version.h b/contrib/idn/idnkit-1.0-src/include/idn/version.h
new file mode 100644
index 0000000..c483311
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/idn/version.h
@@ -0,0 +1,70 @@
+/* $Id: version.h,v 1.1.1.1 2003/06/04 00:25:44 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_VERSION_H
+#define IDN_VERSION_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <idn/export.h>
+
+/*
+ * Version number of this package.
+ */
+#define IDNKIT_VERSION "1.0"
+#define IDNKIT_MAJOR_VERSION 1
+#define IDNKIT_MINOR_VERSION 0
+
+/*
+ * Get the version of the library (libidnkit).
+ */
+IDN_EXPORT const char *
+idn_version_getstring(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_VERSION_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/mdn/Makefile.in b/contrib/idn/idnkit-1.0-src/include/mdn/Makefile.in
new file mode 100644
index 0000000..375db7e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/mdn/Makefile.in
@@ -0,0 +1,83 @@
+# $Id: Makefile.in,v 1.1.1.1 2003/06/04 00:25:45 marka Exp $
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+includedir = @includedir@
+mdnincludedir = $(includedir)/mdn
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+SHELL = @SHELL@
+
+HDRS = \
+ api.h \
+ log.h \
+ res.h \
+ resconf.h \
+ result.h \
+ utf8.h \
+ version.h
+
+all:
+
+@COMPAT_TRUE@install: all install-compat
+@COMPAT_FALSE@install:
+
+install-compat:
+ $(MKINSTALLDIRS) $(DESTDIR)$(mdnincludedir)
+ for hdr in $(HDRS); do \
+ $(INSTALL_DATA) $(srcdir)/$$hdr $(DESTDIR)$(mdnincludedir)/$$hdr; \
+ done
+
+clean:
+ rm -f *~
+
+distclean:
+ rm -f Makefile
+
+test check:
diff --git a/contrib/idn/idnkit-1.0-src/include/mdn/api.h b/contrib/idn/idnkit-1.0-src/include/mdn/api.h
new file mode 100644
index 0000000..5c8f7f3
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/mdn/api.h
@@ -0,0 +1,91 @@
+/* $Id: api.h,v 1.1.1.1 2003/06/04 00:25:45 marka Exp $ */
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef MDN_API_H
+#define MDN_API_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mdn/result.h>
+#include <mdn/res.h>
+#include <idn/api.h>
+
+#define mdn_enable idn_enable
+
+extern idn_result_t
+mdn_nameinit(void);
+
+extern idn_result_t
+mdn_encodename(int actions, const char *from, char *to, size_t tolen);
+
+extern idn_result_t
+mdn_decodename(int actions, const char *from, char *to, size_t tolen);
+
+#define mdn_localtoutf8(from, to, tolen) \
+ mdn_encodename(IDN_LOCALCONV, from, to, len)
+#define mdn_delimitermap(from, to, tolen) \
+ mdn_encodename(IDN_DELIMMAP, from, to, len)
+#define mdn_localmap(from, to, tolen) \
+ mdn_encodename(IDN_LOCALMAP, from, to, len)
+#define mdn_nameprep(from, to, tolen) \
+ mdn_encodename(IDN_NAMEPREP, from, to, len)
+#define mdn_utf8toidn(from, to, tolen) \
+ mdn_encodename(IDN_IDNCONV, from, to, len)
+#define mdn_idntoutf8(from, to, tolen) \
+ mdn_decodename(IDN_IDNCONV, from, to, tolen)
+#define mdn_utf8tolocal(from, to, tolen) \
+ mdn_decodename(IDN_LOCALCONV, from, to, tolen)
+
+#define mdn_localtoidn(from, to, tolen) \
+ mdn_encodename(IDN_ENCODE_APP, from, to, tolen)
+#define mdn_idntolocal(from, to, tolen) \
+ mdn_decodename(IDN_DECODE_APP, from, to, tolen)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MDN_API_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/mdn/localencoding.h b/contrib/idn/idnkit-1.0-src/include/mdn/localencoding.h
new file mode 100644
index 0000000..e1e86f7
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/mdn/localencoding.h
@@ -0,0 +1,49 @@
+/* $Id: localencoding.h,v 1.1.1.1 2003/06/04 00:25:45 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef MDN_LOCALENCODING_H
+#define MDN_LOCALENCODING_H 1
+
+#define MDN_LOCALCS_ENV "MDN_LOCAL_CODESET"
+
+#endif /* MDN_LOCALENCODING_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/mdn/log.h b/contrib/idn/idnkit-1.0-src/include/mdn/log.h
new file mode 100644
index 0000000..002c410
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/mdn/log.h
@@ -0,0 +1,92 @@
+/* $Id: log.h,v 1.1.1.1 2003/06/04 00:25:45 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef MDN_LOG_H
+#define MDN_LOG_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <idn/log.h>
+
+#define mdn_log_proc_t \
+ idn_log_proc_t
+
+#define mdn_log_level_fatal \
+ idn_log_level_fatal
+#define mdn_log_level_error \
+ idn_log_level_error
+#define mdn_log_level_warning \
+ idn_log_level_warning
+#define mdn_log_level_info \
+ idn_log_level_info
+#define mdn_log_level_trace \
+ idn_log_level_trace
+#define mdn_log_level_dump \
+ idn_log_level_dump
+
+#define mdn_log_fatal \
+ idn_log_fatal
+#define mdn_log_error \
+ idn_log_error
+#define mdn_log_warning \
+ idn_log_warning
+#define mdn_log_info \
+ idn_log_info
+#define mdn_log_trace \
+ idn_log_trace
+#define mdn_log_dump \
+ idn_log_dump
+#define mdn_log_setlevel \
+ idn_log_setlevel
+#define mdn_log_getlevel \
+ idn_log_getlevel
+#define mdn_log_setproc \
+ idn_log_setproc
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MDN_LOG_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/mdn/res.h b/contrib/idn/idnkit-1.0-src/include/mdn/res.h
new file mode 100644
index 0000000..a1c0c20
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/mdn/res.h
@@ -0,0 +1,121 @@
+/* $Id: res.h,v 1.1.1.1 2003/06/04 00:25:45 marka Exp $ */
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef MDN_RES_H
+#define MDN_RES_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mdn/resconf.h>
+#include <mdn/result.h>
+#include <idn/res.h>
+
+#define MDN_LOCALCONV \
+ IDN_LOCALCONV
+#define MDN_DELIMMAP \
+ IDN_DELIMMAP
+#define MDN_LOCALMAP \
+ IDN_LOCALMAP
+#define MDN_MAP \
+ IDN_MAP
+#define MDN_NORMALIZE \
+ IDN_NORMALIZE
+#define MDN_PROHCHECK \
+ IDN_PROHCHECK
+#define MDN_UNASCHECK \
+ IDN_UNASCHECK
+#define MDN_ASCCHECK \
+ IDN_ASCCHECK
+#define MDN_IDNCONV \
+ IDN_IDNCONV
+#define MDN_LENCHECK \
+ IDN_LENCHECK
+#define MDN_RTCHECK \
+ IDN_RTCHECK
+#define MDN_UNDOIFERR \
+ IDN_UNDOIFERR
+#define MDN_ENCODE_APP \
+ IDN_ENCODE_APP
+#define MDN_DECODE_APP \
+ IDN_DECODE_APP
+#define MDN_NAMEPREP \
+ IDN_NAMEPREP
+
+#define mdn_res_enable \
+ idn_res_enable
+#define mdn_res_encodename \
+ idn_res_encodename
+#define mdn_res_decodename \
+ idn_res_decodename
+#define mdn_res_actiontostring \
+ idn_res_actiontostring
+
+#define mdn_res_localtoutf8 \
+ idn_res_localtoutf8
+#define mdn_res_delimitermap \
+ idn_res_delimitermap
+#define mdn_res_localmap \
+ idn_res_localmap
+#define mdn_res_nameprep \
+ idn_res_nameprep
+#define mdn_res_utf8toidn \
+ idn_res_utf8toidn
+#define mdn_res_idntoutf8 \
+ idn_res_idntoutf8
+#define mdn_res_utf8tolocal \
+ idn_res_utf8tolocal
+#define mdn_res_nameprepcheck \
+ idn_res_nameprepcheck
+#define mdn_res_localtoidn \
+ idn_res_localtoidn
+#define mdn_res_idntolocal \
+ idn_res_idntolocal
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MDN_RES_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/mdn/resconf.h b/contrib/idn/idnkit-1.0-src/include/mdn/resconf.h
new file mode 100644
index 0000000..c98a8f5
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/mdn/resconf.h
@@ -0,0 +1,150 @@
+/* $Id: resconf.h,v 1.1.1.1 2003/06/04 00:25:46 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef MDN_RESCONF_H
+#define MDN_RESCONF_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mdn/result.h>
+#include <idn/resconf.h>
+
+#define mdn_resconf_t \
+ idn_resconf_t
+
+#define mdn_resconf_initialize \
+ idn_resconf_initialize
+#define mdn_resconf_create \
+ idn_resconf_create
+#define mdn_resconf_destroy \
+ idn_resconf_destroy
+
+#define mdn_resconf_incrref \
+ idn_resconf_incrref
+#define mdn_resconf_loadfile \
+ idn_resconf_loadfile
+#define mdn_resconf_defaultfile \
+ idn_resconf_defaultfile
+#define mdn_resconf_getdelimitermap \
+ idn_resconf_getdelimitermap
+#define mdn_resconf_getidnconverter \
+ idn_resconf_getidnconverter
+#define mdn_resconf_getlocalconverter \
+ idn_resconf_getlocalconverter
+#define mdn_resconf_getlocalmapselector \
+ idn_resconf_getlocalmapselector
+#define mdn_resconf_getmapper \
+ idn_resconf_getmapper
+#define mdn_resconf_getnormalizer \
+ idn_resconf_getnormalizer
+#define mdn_resconf_getprohibitchecker \
+ idn_resconf_getprohibitchecker
+#define mdn_resconf_getunassignedchecker \
+ idn_resconf_getunassignedchecker
+#define mdn_resconf_setdelimitermap \
+ idn_resconf_setdelimitermap
+#define mdn_resconf_setidnconverter \
+ idn_resconf_setidnconverter
+#define mdn_resconf_setlocalconverter \
+ idn_resconf_setlocalconverter
+#define mdn_resconf_setlocalmapselector \
+ idn_resconf_setlocalmapselector
+#define mdn_resconf_setmapper \
+ idn_resconf_setmapper
+#define mdn_resconf_setnormalizer \
+ idn_resconf_setnormalizer
+#define mdn_resconf_setprohibitchecker \
+ idn_resconf_setprohibitchecker
+#define mdn_resconf_setunassignedchecker \
+ idn_resconf_setunassignedchecker
+#define mdn_resconf_setidnconvertername \
+ idn_resconf_setidnconvertername
+#define mdn_resconf_addalldelimitermapucs \
+ idn_resconf_addalldelimitermapucs
+#define mdn_resconf_setlocalconvertername \
+ idn_resconf_setlocalconvertername
+#define mdn_resconf_addalllocalmapselectornames \
+ idn_resconf_addalllocalmapselectornames
+#define mdn_resconf_addallmappernames \
+ idn_resconf_addallmappernames
+#define mdn_resconf_addallnormalizernames \
+ idn_resconf_addallnormalizernames
+#define mdn_resconf_addallprohibitcheckernames \
+ idn_resconf_addallprohibitcheckernames
+#define mdn_resconf_addallunassignedcheckernames \
+ idn_resconf_addallunassignedcheckernames
+#define mdn_resconf_setnameprepversion \
+ idn_resconf_setnameprepversion
+#define mdn_resconf_setalternateconverter \
+ idn_resconf_setalternateconverter
+#define mdn_resconf_setalternateconvertername \
+ idn_resconf_setalternateconvertername
+#define mdn_resconf_getalternateconverter \
+ idn_resconf_getalternateconverter
+
+#define mdn_resconf_localconverter \
+ idn_resconf_localconverter
+#define mdn_resconf_idnconverter \
+ idn_resconf_idnconverter
+#define mdn_resconf_alternateconverter \
+ idn_resconf_alternateconverter
+#define mdn_resconf_normalizer \
+ idn_resconf_normalizer
+#define mdn_resconf_mapper \
+ idn_resconf_mapper
+#define mdn_resconf_delimitermap \
+ idn_resconf_delimitermap
+#define mdn_resconf_localmapselector \
+ idn_resconf_localmapselector
+#define mdn_resconf_prohibitchecker \
+ idn_resconf_prohibitchecker
+#define mdn_resconf_unassignedchecker \
+ idn_resconf_unassignedchecker
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MDN_RESCONF_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/mdn/result.h b/contrib/idn/idnkit-1.0-src/include/mdn/result.h
new file mode 100644
index 0000000..ac47ff7
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/mdn/result.h
@@ -0,0 +1,97 @@
+/* $Id: result.h,v 1.1.1.1 2003/06/04 00:25:46 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef MDN_RESULT_H
+#define MDN_RESULT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <idn/result.h>
+
+#define mdn_result_t \
+ idn_result_t
+
+#define mdn_success \
+ idn_success
+#define mdn_notfound \
+ idn_notfound
+#define mdn_invalid_encoding \
+ idn_invalid_encoding
+#define mdn_invalid_syntax \
+ idn_invalid_syntax
+#define mdn_invalid_name \
+ idn_invalid_name
+#define mdn_invalid_message \
+ idn_invalid_message
+#define mdn_invalid_action \
+ idn_invalid_action
+#define mdn_invalid_codepoint \
+ idn_invalid_codepoint
+#define mdn_invalid_length \
+ idn_invalid_length
+#define mdn_buffer_overflow \
+ idn_buffer_overflow
+#define mdn_noentry \
+ idn_noentry
+#define mdn_nomemory \
+ idn_nomemory
+#define mdn_nofile \
+ idn_nofile
+#define mdn_nomapping \
+ idn_nomapping
+#define mdn_context_required \
+ idn_context_required
+#define mdn_prohibited \
+ idn_prohibited
+#define mdn_failure \
+ idn_failure
+#define mdn_result_tostring \
+ idn_result_tostring
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MDN_RESULT_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/mdn/utf8.h b/contrib/idn/idnkit-1.0-src/include/mdn/utf8.h
new file mode 100644
index 0000000..7f5892d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/mdn/utf8.h
@@ -0,0 +1,70 @@
+/* $Id: utf8.h,v 1.1.1.1 2003/06/04 00:25:46 marka Exp $ */
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef MDN_UTF8_H
+#define MDN_UTF8_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define mdn_utf8_mblen \
+ idn_utf8_mblen
+#define mdn_utf8_getmb \
+ idn_utf8_getmb
+#define mdn_utf8_getwc \
+ idn_utf8_getwc
+#define mdn_utf8_putwc \
+ idn_utf8_putwc
+#define mdn_utf8_isvalidchar \
+ idn_utf8_isvalidchar
+#define mdn_utf8_isvalidstring \
+ idn_utf8_isvalidstring
+#define mdn_utf8_findfirstbyte \
+ idn_utf8_findfirstbyte
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MDN_UTF8_H */
diff --git a/contrib/idn/idnkit-1.0-src/include/mdn/version.h b/contrib/idn/idnkit-1.0-src/include/mdn/version.h
new file mode 100644
index 0000000..2ae4526
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/include/mdn/version.h
@@ -0,0 +1,66 @@
+/* $Id: version.h,v 1.1.1.1 2003/06/04 00:25:46 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef MDN_VERSION_H
+#define MDN_VERSION_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <idn/version.h>
+
+/*
+ * Version number of this package.
+ */
+#define MDNKIT_VERSION "idnkit " IDNKIT_VERSION
+#define MDNKIT_MAJOR_VERSION (IDNKIT_MAJOR_VERSION + 4)
+#define MDNKIT_MINOR_VERSION IDNKIT_MINOR_VERSION
+
+#define mdn_version_getstring idn_version_getstring
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MDN_VERSION_H */
diff --git a/contrib/idn/idnkit-1.0-src/install-sh b/contrib/idn/idnkit-1.0-src/install-sh
new file mode 100755
index 0000000..ebc6691
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/install-sh
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/contrib/idn/idnkit-1.0-src/lib/Makefile.in b/contrib/idn/idnkit-1.0-src/lib/Makefile.in
new file mode 100644
index 0000000..e768730
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/Makefile.in
@@ -0,0 +1,309 @@
+# $Id: Makefile.in,v 1.2 2004/07/20 07:13:39 marka Exp $
+# Copyright (c) 2000, 2002 Japan Network Information Center.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+build = @build@
+
+LIB_CURRENT = 1
+LIB_REVISION = 2
+LIB_AGE = 0
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .to
+
+top_builddir = ..
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+libdir = @libdir@
+sysconfdir = @sysconfdir@
+datadir = @datadir@
+mapdir = $(datadir)/idnkit
+utf8_name = @UTF8_NAME@
+
+SUBDIRS = tests
+
+SHELL = @SHELL@
+CC = @CC@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+LIBTOOL = @LIBTOOL@
+
+ICONVINC = @ICONVINC@
+ICONVLIB = @ICONVLIB@
+
+INCS = -I$(srcdir)/../include -I../include $(ICONVINC)
+DEFS = -DIDN_RESCONF_DIR="\"$(sysconfdir)\""
+
+CFLAGS = $(OPTS) $(INCS) $(DEFS) @CPPFLAGS@ @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+SRCS = \
+ aliaslist.c \
+ api.c \
+ checker.c \
+ converter.c \
+ debug.c \
+ delimitermap.c \
+ filechecker.c \
+ filemapper.c \
+ localencoding.c \
+ log.c \
+ mapper.c \
+ mapselector.c \
+ nameprep.c \
+ nameprep_template.c \
+ nameprepdata.c \
+ normalizer.c \
+ punycode.c \
+ race.c \
+ res.c \
+ resconf.c \
+ result.c \
+ strhash.c \
+ ucs4.c \
+ ucsmap.c \
+ ucsset.c \
+ unicode.c \
+ unicode_template.c \
+ unicodedata_320.c \
+ unormalize.c \
+ util.c \
+ utf8.c \
+ version.c
+
+OBJS = \
+ aliaslist.lo \
+ api.lo \
+ checker.lo \
+ converter.lo \
+ debug.lo \
+ delimitermap.lo \
+ filechecker.lo \
+ filemapper.lo \
+ localencoding.lo \
+ log.lo \
+ mapper.lo \
+ mapselector.lo \
+ nameprep.lo \
+ normalizer.lo \
+ punycode.lo \
+ race.lo \
+ res.lo \
+ resconf.lo \
+ result.lo \
+ strhash.lo \
+ ucs4.lo \
+ ucsmap.lo \
+ ucsset.lo \
+ unicode.lo \
+ unormalize.lo \
+ utf8.lo \
+ util.lo \
+ version.lo
+
+LIB = libidnkit
+TESTLIB = libidntest
+
+LITELIBCFLAGS = $(CFLAGS) -DWITHOUT_ICONV
+LITELIB_OBJS = \
+ apilite.lo \
+ converterlite.lo \
+ reslite.lo \
+ resconflite.lo \
+ aliaslist.lo \
+ checker.lo \
+ debug.lo \
+ delimitermap.lo \
+ filechecker.lo \
+ filemapper.lo \
+ log.lo \
+ mapper.lo \
+ mapselector.lo \
+ nameprep.lo \
+ normalizer.lo \
+ punycode.lo \
+ race.lo \
+ result.lo \
+ strhash.lo \
+ ucsmap.lo \
+ ucsset.lo \
+ unicode.lo \
+ unormalize.lo \
+ ucs4.lo \
+ utf8.lo \
+ util.lo \
+ version.lo
+
+LITELIB = libidnkitlite
+TESTLITELIB = libidntestlite
+
+SAMPLES = idn.conf.sample idnalias.conf.sample
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c $<
+
+.c.to:
+ $(CC) -o $@ -DTEST $(CFLAGS) $(LDFLAGS) -c $<
+
+all: all-localdir all-subdirs
+@LITEONLY_TRUE@all-localdir: $(LITELIB).la $(SAMPLES)
+@LITEONLY_FALSE@all-localdir: $(LIB).la $(LITELIB).la $(SAMPLES)
+
+$(LIB).la: $(OBJS)
+ $(LIBTOOL) --mode=link $(LD) $(LDFLAGS) -o $@ \
+ -version-info $(LIB_CURRENT):$(LIB_REVISION):$(LIB_AGE) \
+ -rpath $(libdir) $(OBJS)
+
+$(TESTLIB).la: $(OBJS)
+ $(LIBTOOL) --mode=link $(LD) $(LDFLAGS) -o $@ \
+ -version-info $(LIB_CURRENT):$(LIB_REVISION):$(LIB_AGE) \
+ -rpath $(libdir) $(OBJS)
+
+apilite.lo: api.c
+ $(LIBTOOL) --mode=compile $(CC) $(LITELIBCFLAGS) -o $@ \
+ -c $(srcdir)/api.c
+converterlite.lo: converter.c
+ $(LIBTOOL) --mode=compile $(CC) $(LITELIBCFLAGS) -o $@ \
+ -c $(srcdir)/converter.c
+reslite.lo: res.c
+ $(LIBTOOL) --mode=compile $(CC) $(LITELIBCFLAGS) -o $@ \
+ -c $(srcdir)/res.c
+resconflite.lo: resconf.c
+ $(LIBTOOL) --mode=compile $(CC) $(LITELIBCFLAGS) -o $@ \
+ -c $(srcdir)/resconf.c
+
+$(LITELIB).la: $(LITELIB_OBJS)
+ $(LIBTOOL) --mode=link $(LD) $(LDFLAGS) -o $@ \
+ -version-info $(LIB_CURRENT):$(LIB_REVISION):$(LIB_AGE) \
+ -rpath $(libdir) $(LITELIB_OBJS)
+
+$(TESTLITELIB).la: $(LITELIB_OBJS)
+ $(LIBTOOL) --mode=link $(LD) $(LDFLAGS) -o $@ \
+ -version-info $(LIB_CURRENT):$(LIB_REVISION):$(LIB_AGE) \
+ -rpath $(libdir) $(LITELIB_OBJS)
+
+idn.conf.sample: idn.conf.sample.in
+ sed -e 's%[@]mapdir[@]%$(mapdir)%' \
+ < $(srcdir)/idn.conf.sample.in > $@
+
+idnalias.conf.sample: Makefile
+ $(SHELL) $(srcdir)/aliaslist.sh $(build) $(utf8_name) > $@
+
+install: install-localdir install-subdirs
+@LITEONLY_TRUE@install-localdir: all install-common
+@LITEONLY_FALSE@install-localdir: all install-common install-nolite
+
+install-common:
+ $(MKINSTALLDIRS) $(DESTDIR)$(libdir)
+ $(LIBTOOL) $(INSTALL_DATA) $(LITELIB).la \
+ $(DESTDIR)$(libdir)/$(LITELIB).la
+ -[ -f $(DESTDIR)$(libdir)/$(LITELIB).a ] \
+ && $(RANLIB) $(DESTDIR)$(libdir)/$(LITELIB).a
+ $(MKINSTALLDIRS) $(DESTDIR)$(sysconfdir)
+ $(INSTALL_DATA) idn.conf.sample \
+ $(DESTDIR)$(sysconfdir)/idn.conf.sample
+ $(INSTALL_DATA) idnalias.conf.sample \
+ $(DESTDIR)$(sysconfdir)/idnalias.conf.sample
+ @if [ ! -f $(DESTDIR)$(sysconfdir)/idn.conf ]; then \
+ echo "** installing default idn.conf"; \
+ $(INSTALL_DATA) idn.conf.sample $(DESTDIR)$(sysconfdir)/idn.conf; \
+ fi
+ @if [ ! -f $(DESTDIR)$(sysconfdir)/idnalias.conf ]; then \
+ echo "** installing default idnalias.conf"; \
+ $(INSTALL_DATA) idnalias.conf.sample \
+ $(DESTDIR)$(sysconfdir)/idnalias.conf; \
+ fi
+
+install-nolite:
+ $(MKINSTALLDIRS) $(DESTDIR)$(libdir)
+ $(LIBTOOL) $(INSTALL_DATA) $(LIB).la \
+ $(DESTDIR)$(libdir)/$(LIB).la
+ -[ -f $(DESTDIR)$(libdir)/$(LIB).a ] \
+ && $(RANLIB) $(DESTDIR)$(libdir)/$(LIB).a
+
+install-config:
+ @if [ -f $(DESTDIR)$(sysconfdir)/idn.conf ]; then \
+ echo "** backing up old idn.conf as idn.conf.old"; \
+ mv -f $(DESTDIR)$(sysconfdir)/idn.conf \
+ $(DESTDIR)$(sysconfdir)/idn.conf.old; \
+ fi
+ @echo "** installing default idn.conf forcibly"
+ $(INSTALL_DATA) idn.conf.sample $(DESTDIR)$(sysconfdir)/idn.conf
+ @if [ -f $(DESTDIR)$(sysconfdir)/idnalias.conf ]; then \
+ echo "** backing up old idnalias.conf as idnalias.conf.old"; \
+ mv -f $(DESTDIR)$(sysconfdir)/idnalias.conf \
+ $(DESTDIR)$(sysconfdir)/idnalias.conf.old; \
+ fi
+ @echo "** installing default idnalias.conf forcibly"
+ $(INSTALL_DATA) idnalias.conf.sample \
+ $(DESTDIR)$(sysconfdir)/idnalias.conf
+
+clean: clean-localdir clean-subdirs
+clean-localdir: force
+ rm -f *.o *.lo *.la *.a core *.core *~
+ rm -f *.to *_test.c *_test
+ rm -f idn.conf.sample idnalias.conf.sample
+ rm -fr .libs/
+
+distclean: distclean-localdir distclean-subdirs
+distclean-localdir: force clean-localdir
+ rm -f Makefile
+
+test check: test-localdir test-subdirs
+
+@LITEONLY_TRUE@test-localdir: $(TESTLITELIB).la $(SAMPLES)
+@LITEONLY_FALSE@test-localdir: $(TESTLIB).la $(TESTLITELIB).la $(SAMPLES)
+
+all-subdirs install-subdirs clean-subdirs distclean-subdirs test-subdirs:
+ @target=`echo $@ | sed 's/-subdirs$$//'`; \
+ for d in $(SUBDIRS) ; do \
+ (cd $$d; $(MAKE) DESTDIR=$(DESTDIR) $$target); \
+ done
+
+force:
diff --git a/contrib/idn/idnkit-1.0-src/lib/aliaslist.c b/contrib/idn/idnkit-1.0-src/lib/aliaslist.c
new file mode 100644
index 0000000..2b5dca0
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/aliaslist.c
@@ -0,0 +1,355 @@
+#ifndef lint
+static char *rcsid = "$Id: aliaslist.c,v 1.1.1.1 2003/06/04 00:25:47 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <idn/aliaslist.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/result.h>
+
+struct aliasitem {
+ char *pattern; /* name pattern */
+ char *encoding; /* MIME-preferred charset name */
+ struct aliasitem *next;
+};
+typedef struct aliasitem *aliasitem_t;
+
+struct idn__aliaslist {
+ aliasitem_t first_item; /* first item of the list */
+};
+
+static idn_result_t
+additem_to_top(idn__aliaslist_t list,
+ const char *pattern, const char *encoding);
+
+static idn_result_t
+additem_to_bottom(idn__aliaslist_t list,
+ const char *pattern, const char *encoding);
+
+static int match(const char *pattern, const char *str);
+
+static idn_result_t create_item(const char *pattern, const char *encoding,
+ aliasitem_t *itemp);
+
+#ifdef DEBUG
+static void dump_list(idn__aliaslist_t list);
+#endif
+
+idn_result_t
+idn__aliaslist_create(idn__aliaslist_t *listp) {
+ static int size = sizeof(struct idn__aliaslist);
+
+ TRACE(("idn__aliaslist_create()\n"));
+
+ assert(listp != NULL);
+
+ if ((*listp = malloc(size)) == NULL) {
+ return (idn_nomemory);
+ }
+ (*listp)->first_item = NULL;
+
+ return (idn_success);
+}
+
+void
+idn__aliaslist_destroy(idn__aliaslist_t list) {
+ aliasitem_t current;
+ aliasitem_t next;
+
+ TRACE(("idn__aliaslist_destroy()\n"));
+
+ assert(list != NULL);
+
+ current = list->first_item;
+ while (current != NULL) {
+ if (current->pattern != NULL) {
+ free(current->pattern);
+ }
+ if (current->encoding != NULL) {
+ free(current->encoding);
+ }
+ next = current->next;
+ free(current);
+ current = next;
+ }
+ free(list);
+}
+
+idn_result_t
+idn__aliaslist_aliasfile(idn__aliaslist_t list, const char *path) {
+ FILE *fp;
+ int line_no;
+ idn_result_t r = idn_success;
+ char line[200], alias[200], real[200];
+
+ assert(path != NULL);
+
+ TRACE(("idn__aliaslist_aliasfile(path=%s)\n", path));
+
+ if ((fp = fopen(path, "r")) == NULL) {
+ return (idn_nofile);
+ }
+ for (line_no = 1; fgets(line, sizeof(line), fp) != NULL; line_no++) {
+ unsigned char *p = (unsigned char *)line;
+
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p == '#' || *p == '\n')
+ continue;
+ if (sscanf((char *)p, "%s %s", alias, real) == 2) {
+ r = additem_to_bottom(list, alias, real);
+ if (r != idn_success)
+ break;
+ } else {
+ INFO(("idn__aliaslist_aliasfile: file %s has "
+ "invalid contents at line %d\n",
+ path, line_no));
+ r = idn_invalid_syntax;
+ break;
+ }
+ }
+ fclose(fp);
+
+#ifdef DEBUG
+ dump_list(list);
+#endif
+
+ return (r);
+}
+
+idn_result_t
+idn__aliaslist_additem(idn__aliaslist_t list,
+ const char *pattern, const char *encoding,
+ int first_item) {
+ if (first_item) {
+ return additem_to_top(list, pattern, encoding);
+ } else {
+ return additem_to_bottom(list, pattern, encoding);
+ }
+}
+
+static idn_result_t
+additem_to_top(idn__aliaslist_t list,
+ const char *pattern, const char *encoding) {
+ aliasitem_t new_item;
+ idn_result_t r;
+
+ TRACE(("additem_to_top()\n"));
+
+ assert(list != NULL);
+ assert(pattern != NULL);
+ assert(encoding != NULL);
+
+ if ((r = create_item(pattern, encoding, &new_item))
+ != idn_success) {
+ WARNING(("additem_to_top: malloc failed\n"));
+ return (r);
+ }
+
+ new_item->next = list->first_item;
+ list->first_item = new_item;
+
+#ifdef DEBUG
+ dump_list(list);
+#endif
+
+ return (idn_success);
+}
+
+static idn_result_t
+additem_to_bottom(idn__aliaslist_t list,
+ const char *pattern, const char *encoding) {
+ aliasitem_t new_item;
+ idn_result_t r;
+
+ TRACE(("additem_to_bottom()\n"));
+
+ assert(list != NULL);
+ assert(pattern != NULL);
+ assert(encoding != NULL);
+
+ r = create_item(pattern, encoding, &new_item);
+ if (r != idn_success) {
+ WARNING(("additem_to_bottom: malloc failed\n"));
+ return r;
+ }
+
+ if (list->first_item == NULL) {
+ list->first_item = new_item;
+ } else {
+ aliasitem_t cur_item = list->first_item;
+ for (;;) {
+ if (cur_item->next == NULL) {
+ break;
+ }
+ cur_item = cur_item->next;
+ }
+ cur_item->next = new_item;
+ }
+
+ return (idn_success);
+}
+
+idn_result_t
+idn__aliaslist_find(idn__aliaslist_t list,
+ const char *pattern, char **encodingp) {
+ aliasitem_t current;
+
+ TRACE(("idn__aliaslist_find()\n"));
+
+ assert(list != NULL);
+ assert(pattern != NULL);
+
+#ifdef DEBUG
+ DUMP(("target pattern: %s\n", pattern));
+#endif
+ current = list->first_item;
+ while (current != NULL) {
+#ifdef DEBUG
+ DUMP(("current pattern: %s, encoding: %s\n",
+ current->pattern, current->encoding));
+#endif
+ if (match(current->pattern, pattern)) {
+ *encodingp = current->encoding;
+ return (idn_success);
+ }
+ current = current->next;
+ }
+
+ TRACE(("idn__aliaslist_find(): not found\n"));
+ *encodingp = (char *)pattern;
+ return (idn_notfound);
+}
+
+/*
+ * Wild card matching function that supports only '*'.
+ */
+static int
+match(const char *pattern, const char *str) {
+ for (;;) {
+ int c;
+
+ switch (c = *pattern++) {
+ case '\0':
+ return (*str == '\0');
+ case '*':
+ while (!match(pattern, str)) {
+ if (*str == '\0')
+ return (0);
+ str++;
+ }
+ return (1);
+ break;
+ default:
+ if (*str++ != c)
+ return (0);
+ break;
+ }
+ }
+}
+
+/*
+ * List item creation.
+ * pattern and encoding must not be NULL.
+ */
+static idn_result_t
+create_item(const char *pattern, const char *encoding,
+ aliasitem_t *itemp) {
+ static size_t size = sizeof(struct aliasitem);
+
+ assert(pattern != NULL);
+ assert(encoding != NULL);
+
+ if ((*itemp = malloc(size)) == NULL)
+ return (idn_nomemory);
+
+ if (((*itemp)->pattern = malloc(strlen(pattern) + 1)) == NULL) {
+ free(*itemp);
+ *itemp = NULL;
+ return (idn_nomemory);
+ }
+
+ if (((*itemp)->encoding = malloc(strlen(encoding) + 1)) == NULL) {
+ free((*itemp)->pattern);
+ free(*itemp);
+ *itemp = NULL;
+ return (idn_nomemory);
+ }
+
+ (void)strcpy((*itemp)->pattern, pattern);
+ (void)strcpy((*itemp)->encoding, encoding);
+ (*itemp)->next = NULL;
+
+ return (idn_success);
+}
+
+#ifdef DEBUG
+static void
+dump_list(idn__aliaslist_t list) {
+ aliasitem_t item;
+ int i;
+
+ TRACE(("dump_list()\n"));
+ if (list == NULL) {
+ TRACE(("list is NULL\n"));
+ return;
+ }
+ item = list->first_item;
+ i = 0;
+ while (item != NULL) {
+ DUMP(("%d: %s\t%s\n", i, item->pattern, item->encoding));
+ item = item->next;
+ i++;
+ }
+}
+#endif
diff --git a/contrib/idn/idnkit-1.0-src/lib/aliaslist.sh b/contrib/idn/idnkit-1.0-src/lib/aliaslist.sh
new file mode 100644
index 0000000..47c3d4f
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/aliaslist.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# aliaslist.sh -- Generate `idnalias.conf.sample' file.
+#
+
+cpu_company_system="$1"
+utf8_name="$2"
+
+cat <<EOF
+*.ISO_8859-1 ISO-8859-1
+*.ISO_8859-2 ISO-8859-1
+*.SJIS Shift_JIS
+*.Shift_JIS Shift_JIS
+ja_JP.EUC EUC-JP
+ko_KR.EUC EUC-KR
+*.big5 Big5
+*.Big5 Big5
+*.KOI8-R KOI8-R
+*.GB2312 GB2312
+ja EUC-JP
+EOF
+
+case "$cpu_company_system" in
+*-*-hpux*)
+ echo "japanese Shift_JIS"
+ ;;
+*)
+ echo "japanese EUC-JP"
+esac
+
+if [ "x$utf8_name" != xUTF-8 ] ; then
+ echo "UTF-8 $utf8_name"
+fi
+
+exit 0
diff --git a/contrib/idn/idnkit-1.0-src/lib/api.c b/contrib/idn/idnkit-1.0-src/lib/api.c
new file mode 100644
index 0000000..ab1b6e0
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/api.c
@@ -0,0 +1,257 @@
+#ifndef lint
+static char *rcsid = "$Id: api.c,v 1.1.1.1 2003/06/04 00:25:48 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/log.h>
+#include <idn/logmacro.h>
+#include <idn/resconf.h>
+#include <idn/api.h>
+#include <idn/debug.h>
+#include <idn/res.h>
+
+static int initialized;
+static idn_resconf_t default_conf;
+
+static char *conf_file;
+
+void
+idn_enable(int on_off) {
+ idn_res_enable(on_off);
+}
+
+idn_result_t
+idn__setconffile(const char *file) {
+ idn_result_t r;
+ char *s;
+
+ TRACE(("idn__setconffile(%s)\n", (file == NULL) ? "<null>" : file));
+
+ if (initialized) {
+ r = idn_failure;
+ goto ret;
+ }
+
+ if (file == NULL)
+ s = NULL;
+ else {
+ s = (char *)malloc(strlen(file) + 1);
+ if (s == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ strcpy(s, file);
+ }
+ free(conf_file);
+ conf_file = s;
+
+ r = idn_success;
+ret:
+ TRACE(("idn__setconffile(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_nameinit(int load_file) {
+ idn_result_t r;
+
+ TRACE(("idn_nameinit()\n"));
+
+ if (initialized) {
+ r = idn_success;
+ goto ret;
+ }
+
+ idn_resconf_initialize();
+
+ r = idn_resconf_create(&default_conf);
+ if (r != idn_success)
+ goto ret;
+
+ if (load_file)
+ r = idn_resconf_loadfile(default_conf, conf_file);
+ else
+ r = idn_resconf_setdefaults(default_conf);
+ if (r != idn_success)
+ goto ret;
+
+ initialized = 1;
+
+ret:
+ if (r != idn_success && default_conf != NULL) {
+ idn_resconf_destroy(default_conf);
+ default_conf = NULL;
+ }
+ TRACE(("idn_nameinit(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_encodename(idn_action_t actions, const char *from, char *to, size_t tolen) {
+ idn_result_t r;
+
+ assert(from != NULL && to != NULL);
+
+ TRACE(("idn_encodename(actions=%s, from=\"%s\")\n",
+ idn__res_actionstostring(actions),
+ idn__debug_xstring(from, 50)));
+
+ if (!initialized && ((r = idn_nameinit(0)) != idn_success))
+ goto ret;
+
+ r = idn_res_encodename(default_conf, actions, from, to, tolen);
+
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_encodename(): success (to=\"%s\")\n",
+ idn__debug_xstring(to, 50)));
+ } else {
+ TRACE(("idn_encodename(): %s\n", idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+idn_result_t
+idn_decodename(idn_action_t actions, const char *from, char *to, size_t tolen) {
+ idn_result_t r;
+
+ assert(from != NULL && to != NULL);
+
+ TRACE(("idn_decodename(actions=%s, from=\"%s\", tolen=%d)\n",
+ idn__res_actionstostring(actions),
+ idn__debug_xstring(from, 50), (int)tolen));
+
+ if (!initialized && ((r = idn_nameinit(0)) != idn_success))
+ goto ret;
+
+ r = idn_res_decodename(default_conf, actions, from, to, tolen);
+
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_decodename(): success (to=\"%s\")\n",
+ idn__debug_xstring(to, 50)));
+ } else {
+ TRACE(("idn_decodename(): %s\n", idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+idn_result_t
+idn_decodename2(idn_action_t actions, const char *from, char *to, size_t tolen,
+ const char *auxencoding) {
+ idn_result_t r;
+
+ assert(from != NULL && to != NULL);
+
+ TRACE(("idn_decodename2(actions=%s, from=\"%s\", tolen=%d)\n",
+ idn__res_actionstostring(actions),
+ idn__debug_xstring(from, 50), (int)tolen));
+
+ if (!initialized && ((r = idn_nameinit(0)) != idn_success))
+ goto ret;
+
+ r = idn_res_decodename2(default_conf, actions, from, to, tolen,
+ auxencoding);
+
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_decodename2(): success (to=\"%s\")\n",
+ idn__debug_xstring(to, 50)));
+ } else {
+ TRACE(("idn_decodename2(): %s\n", idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+/*
+ * These functions are for backward compatibility.
+ */
+#ifdef ENABLE_MDNKIT_COMPAT
+
+idn_result_t
+mdn_nameinit(void) {
+ return idn_nameinit(1);
+}
+
+idn_result_t
+mdn_encodename(int actions, const char *from, char *to, size_t tolen) {
+ idn_result_t r;
+
+ assert(from != NULL && to != NULL);
+
+ TRACE(("mdn_encodename(actions=%s, from=\"%s\")\n",
+ idn__res_actionstostring(actions),
+ idn__debug_xstring(from, 50)));
+
+ if (!initialized && ((r = idn_nameinit(1)) != idn_success))
+ return (r);
+
+ return (idn_res_encodename(default_conf, actions, from, to, tolen));
+}
+
+idn_result_t
+mdn_decodename(int actions, const char *from, char *to, size_t tolen) {
+ idn_result_t r;
+
+ assert(from != NULL && to != NULL);
+
+ TRACE(("idn_decodename(actions=%s, from=\"%s\", tolen=%d)\n",
+ idn__res_actionstostring(actions),
+ idn__debug_xstring(from, 50), (int)tolen));
+
+ if (!initialized && ((r = idn_nameinit(1)) != idn_success))
+ return (r);
+
+ return (idn_res_decodename(default_conf, actions, from, to, tolen));
+}
+
+#endif /* ENABLE_MDNKIT_COMPAT */
diff --git a/contrib/idn/idnkit-1.0-src/lib/checker.c b/contrib/idn/idnkit-1.0-src/lib/checker.c
new file mode 100644
index 0000000..c1e8fdf
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/checker.c
@@ -0,0 +1,446 @@
+#ifndef lint
+static char *rcsid = "$Id: checker.c,v 1.1.1.1 2003/06/04 00:25:49 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/checker.h>
+#include <idn/strhash.h>
+#include <idn/debug.h>
+
+/*
+ * Type for checking scheme.
+ */
+typedef struct {
+ char *prefix;
+ char *parameter;
+ idn_checker_createproc_t create;
+ idn_checker_destroyproc_t destroy;
+ idn_checker_lookupproc_t lookup;
+ void *context;
+} check_scheme_t;
+
+/*
+ * Standard checking schemes.
+ */
+static const check_scheme_t rfc3491_prohibit_scheme = {
+ "prohibit#RFC3491",
+ "RFC3491",
+ idn_nameprep_createproc,
+ idn_nameprep_destroyproc,
+ idn_nameprep_prohibitproc,
+ NULL,
+};
+
+static const check_scheme_t rfc3491_unasigned_scheme = {
+ "unassigned#RFC3491",
+ "RFC3491",
+ idn_nameprep_createproc,
+ idn_nameprep_destroyproc,
+ idn_nameprep_unassignedproc,
+ NULL,
+};
+
+static const check_scheme_t rfc3491_bidi_scheme = {
+ "bidi#RFC3491",
+ "RFC3491",
+ idn_nameprep_createproc,
+ idn_nameprep_destroyproc,
+ idn_nameprep_bidiproc,
+ NULL,
+};
+
+static const check_scheme_t filecheck_prohibit_scheme = {
+ "prohibit#fileset",
+ NULL,
+ idn__filechecker_createproc,
+ idn__filechecker_destroyproc,
+ idn__filechecker_lookupproc,
+ NULL,
+};
+
+static const check_scheme_t filecheck_unassigned_scheme = {
+ "unassigned#fileset",
+ NULL,
+ idn__filechecker_createproc,
+ idn__filechecker_destroyproc,
+ idn__filechecker_lookupproc,
+ NULL,
+};
+
+static const check_scheme_t *standard_check_schemes[] = {
+ &rfc3491_unasigned_scheme,
+ &rfc3491_prohibit_scheme,
+ &rfc3491_bidi_scheme,
+ &filecheck_prohibit_scheme,
+ &filecheck_unassigned_scheme,
+ NULL,
+};
+
+/*
+ * Hash table for checking schemes.
+ */
+static idn__strhash_t scheme_hash = NULL;
+
+/*
+ * Mapper object type.
+ */
+struct idn_checker {
+ int nschemes;
+ int scheme_size;
+ check_scheme_t *schemes;
+ int reference_count;
+};
+
+#define MAPPER_INITIAL_SCHEME_SIZE 1
+
+idn_result_t
+idn_checker_initialize(void) {
+ idn_result_t r;
+ check_scheme_t **scheme;
+
+ TRACE(("idn_checker_initialize()\n"));
+
+ if (scheme_hash != NULL) {
+ r = idn_success; /* already initialized */
+ goto ret;
+ }
+
+ r = idn__strhash_create(&scheme_hash);
+ if (r != idn_success) {
+ goto ret;
+ }
+
+ for (scheme = (check_scheme_t **)standard_check_schemes;
+ *scheme != NULL; scheme++) {
+ r = idn__strhash_put(scheme_hash, (*scheme)->prefix, *scheme);
+ if (r != idn_success)
+ goto ret;
+ }
+
+ r = idn_success;
+ret:
+ if (r != idn_success) {
+ if (scheme_hash != NULL) {
+ idn__strhash_destroy(scheme_hash, NULL);
+ scheme_hash = NULL;
+ }
+ }
+ TRACE(("idn_checker_initialize(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_checker_create(idn_checker_t *ctxp) {
+ idn_checker_t ctx = NULL;
+ idn_result_t r;
+
+ assert(scheme_hash != NULL);
+ assert(ctxp != NULL);
+
+ TRACE(("idn_checker_create()\n"));
+
+ ctx = (idn_checker_t) malloc(sizeof(struct idn_checker));
+ if (ctx == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ ctx->schemes = (check_scheme_t *) malloc(sizeof(check_scheme_t)
+ * MAPPER_INITIAL_SCHEME_SIZE);
+ if (ctx->schemes == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ ctx->nschemes = 0;
+ ctx->scheme_size = MAPPER_INITIAL_SCHEME_SIZE;
+ ctx->reference_count = 1;
+ *ctxp = ctx;
+ r = idn_success;
+ret:
+ if (r != idn_success) {
+ if (ctx != NULL)
+ free(ctx->schemes);
+ free(ctx);
+ }
+ TRACE(("idn_checker_create(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+void
+idn_checker_destroy(idn_checker_t ctx) {
+ int i;
+
+ assert(scheme_hash != NULL);
+ assert(ctx != NULL);
+
+ TRACE(("idn_checker_destroy()\n"));
+
+ ctx->reference_count--;
+ if (ctx->reference_count <= 0) {
+ TRACE(("idn_checker_destroy(): the object is destroyed\n"));
+ for (i = 0; i < ctx->nschemes; i++)
+ ctx->schemes[i].destroy(ctx->schemes[i].context);
+ free(ctx->schemes);
+ free(ctx);
+ } else {
+ TRACE(("idn_checker_destroy(): "
+ "update reference count (%d->%d)\n",
+ ctx->reference_count + 1, ctx->reference_count));
+ }
+}
+
+void
+idn_checker_incrref(idn_checker_t ctx) {
+ assert(ctx != NULL && scheme_hash != NULL);
+
+ TRACE(("idn_checker_incrref()\n"));
+ TRACE(("idn_checker_incrref: update reference count (%d->%d)\n",
+ ctx->reference_count, ctx->reference_count + 1));
+
+ ctx->reference_count++;
+}
+
+idn_result_t
+idn_checker_add(idn_checker_t ctx, const char *scheme_name) {
+ idn_result_t r;
+ check_scheme_t *scheme;
+ const char *scheme_prefix;
+ const char *scheme_parameter;
+ void *scheme_context = NULL;
+ char *buffer = NULL;
+
+ assert(scheme_hash != NULL);
+ assert(ctx != NULL);
+
+ TRACE(("idn_checker_add(scheme_name=%s)\n",
+ idn__debug_xstring(scheme_name, 50)));
+
+ /*
+ * Split `scheme_name' into `scheme_prefix' and `scheme_parameter'.
+ */
+ scheme_parameter = strchr(scheme_name, ':');
+ if (scheme_parameter == NULL) {
+ scheme_prefix = scheme_name;
+ scheme_parameter = NULL;
+ } else {
+ ptrdiff_t scheme_prefixlen;
+
+ scheme_prefixlen = scheme_parameter - scheme_name;
+ buffer = (char *) malloc(scheme_prefixlen + 1);
+ if (buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ memcpy(buffer, scheme_name, scheme_prefixlen);
+ *(buffer + scheme_prefixlen) = '\0';
+ scheme_prefix = buffer;
+ scheme_parameter++;
+ }
+
+ /*
+ * Find a scheme.
+ */
+ if (idn__strhash_get(scheme_hash, scheme_prefix, (void **)&scheme)
+ != idn_success) {
+ ERROR(("idn_checker_add(): invalid scheme \"%-.30s\"\n",
+ scheme_name));
+ r = idn_invalid_name;
+ goto ret;
+ }
+ if (scheme_parameter == NULL && scheme->parameter != NULL)
+ scheme_parameter = scheme->parameter;
+
+ /*
+ * Add the scheme.
+ */
+ assert(ctx->nschemes <= ctx->scheme_size);
+
+ if (ctx->nschemes == ctx->scheme_size) {
+ check_scheme_t *new_schemes;
+
+ new_schemes = (check_scheme_t *) realloc(ctx->schemes,
+ sizeof(check_scheme_t) * ctx->scheme_size * 2);
+ if (new_schemes == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ ctx->schemes = new_schemes;
+ ctx->scheme_size *= 2;
+ }
+
+ r = scheme->create(scheme_parameter, &scheme_context);
+ if (r != idn_success)
+ goto ret;
+
+ memcpy(ctx->schemes + ctx->nschemes, scheme, sizeof(check_scheme_t));
+ ctx->schemes[ctx->nschemes].context = scheme_context;
+ ctx->nschemes++;
+ r = idn_success;
+
+ret:
+ free(buffer);
+ if (r != idn_success)
+ free(scheme_context);
+ TRACE(("idn_checker_add(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_checker_addall(idn_checker_t ctx, const char **scheme_names,
+ int nschemes) {
+ idn_result_t r;
+ int i;
+
+ assert(scheme_hash != NULL);
+ assert(ctx != NULL && scheme_names != NULL);
+
+ TRACE(("idn_checker_addall(nschemes=%d)\n", nschemes));
+
+ for (i = 0; i < nschemes; i++) {
+ r = idn_checker_add(ctx, (const char *)*scheme_names);
+ if (r != idn_success)
+ goto ret;
+ scheme_names++;
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("idn_checker_addall(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_checker_lookup(idn_checker_t ctx, const unsigned long *ucs4,
+ const unsigned long **found) {
+ idn_result_t r;
+ int i;
+
+ assert(scheme_hash != NULL);
+ assert(ctx != NULL && ucs4 != NULL && found != NULL);
+
+ TRACE(("idn_checker_lookup(ucs4=\"%s\")\n",
+ idn__debug_ucs4xstring(ucs4, 50)));
+
+ /*
+ * Lookup.
+ */
+ *found = NULL;
+
+ for (i = 0; i < ctx->nschemes; i++) {
+ TRACE(("idn_checker_lookup(): lookup %s\n",
+ ctx->schemes[i].prefix));
+
+ r = (ctx->schemes[i].lookup)(ctx->schemes[i].context, ucs4,
+ found);
+ if (r != idn_success)
+ goto ret;
+ if (*found != NULL)
+ break;
+ }
+
+ r = idn_success;
+ret:
+ if (*found == NULL) {
+ TRACE(("idn_checker_lookup(): %s (not found)\n",
+ idn_result_tostring(r)));
+ } else {
+ TRACE(("idn_checker_lookup(): %s (found \\x%04lx)\n",
+ idn_result_tostring(r), **found));
+ }
+ return (r);
+}
+
+idn_result_t
+idn_checker_register(const char *prefix,
+ idn_checker_createproc_t create,
+ idn_checker_destroyproc_t destroy,
+ idn_checker_lookupproc_t lookup) {
+ idn_result_t r;
+ check_scheme_t *scheme = NULL;
+
+ assert(scheme_hash != NULL);
+ assert(prefix != NULL && create != NULL && destroy != NULL &&
+ lookup != NULL);
+
+ TRACE(("idn_checker_register(prefix=%s)\n", prefix));
+
+ scheme = (check_scheme_t *) malloc(sizeof(check_scheme_t));
+ if (scheme == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ scheme->prefix = (char *) malloc(strlen(prefix) + 1);
+ if (scheme->prefix == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ strcpy(scheme->prefix, prefix);
+ scheme->parameter = NULL;
+ scheme->create = create;
+ scheme->destroy = destroy;
+ scheme->lookup = lookup;
+
+ r = idn__strhash_put(scheme_hash, prefix, scheme);
+ret:
+ if (r != idn_success) {
+ if (scheme != NULL)
+ free(scheme->prefix);
+ free(scheme);
+ }
+ TRACE(("idn_checker_register(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/converter.c b/contrib/idn/idnkit-1.0-src/lib/converter.c
new file mode 100644
index 0000000..faed44f
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/converter.c
@@ -0,0 +1,1244 @@
+#ifndef lint
+static char *rcsid = "$Id: converter.c,v 1.1.1.1 2003/06/04 00:25:51 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#ifndef WITHOUT_ICONV
+#include <iconv.h>
+#endif
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/converter.h>
+#include <idn/aliaslist.h>
+#include <idn/strhash.h>
+#include <idn/debug.h>
+#include <idn/ucs4.h>
+#include <idn/punycode.h>
+#include <idn/race.h>
+#include <idn/util.h>
+
+#ifndef IDN_UTF8_ENCODING_NAME
+#define IDN_UTF8_ENCODING_NAME "UTF-8" /* by IANA */
+#endif
+#ifndef IDN_RACE_ENCODING_NAME
+#define IDN_RACE_ENCODING_NAME "RACE"
+#endif
+#ifndef IDN_AMCACEZ_ENCODING_NAME
+#define IDN_AMCACEZ_ENCODING_NAME "AMC-ACE-Z"
+#endif
+#ifndef IDN_PUNYCODE_ENCODING_NAME
+#define IDN_PUNYCODE_ENCODING_NAME "Punycode"
+#endif
+
+#define MAX_RECURSE 20
+
+#ifdef WIN32
+
+#define IDNKEY_IDNKIT "Software\\JPNIC\\IDN"
+#define IDNVAL_ALIASFILE "AliasFile"
+
+#else /* WIN32 */
+
+#ifndef IDN_RESCONF_DIR
+#define IDN_RESCONF_DIR "/etc"
+#endif
+#define IDN_ALIAS_FILE IDN_RESCONF_DIR "/idnalias.conf"
+
+#endif /* WIN32 */
+
+typedef struct {
+ idn_converter_openproc_t openfromucs4;
+ idn_converter_openproc_t opentoucs4;
+ idn_converter_convfromucs4proc_t convfromucs4;
+ idn_converter_convtoucs4proc_t convtoucs4;
+ idn_converter_closeproc_t close;
+ int encoding_type;
+} converter_ops_t;
+
+struct idn_converter {
+ char *local_encoding_name;
+ converter_ops_t *ops;
+ int flags;
+ int opened_convfromucs4;
+ int opened_convtoucs4;
+ int reference_count;
+ void *private_data;
+};
+
+static idn__strhash_t encoding_name_hash;
+static idn__aliaslist_t encoding_alias_list;
+
+static idn_result_t register_standard_encoding(void);
+static idn_result_t roundtrip_check(idn_converter_t ctx,
+ const unsigned long *from,
+ const char *to);
+
+static idn_result_t
+ converter_none_open(idn_converter_t ctx, void **privdata);
+static idn_result_t
+ converter_none_close(idn_converter_t ctx, void *privdata);
+static idn_result_t
+ converter_none_convfromucs4(idn_converter_t ctx,
+ void *privdata,
+ const unsigned long *from,
+ char *to, size_t tolen);
+static idn_result_t
+ converter_none_convtoucs4(idn_converter_t ctx,
+ void *privdata, const char *from,
+ unsigned long *to, size_t tolen);
+
+#ifndef WITHOUT_ICONV
+static idn_result_t
+ converter_iconv_openfromucs4(idn_converter_t ctx, void **privdata);
+static idn_result_t
+ converter_iconv_opentoucs4(idn_converter_t ctx, void **privdata);
+static idn_result_t
+ converter_iconv_close(idn_converter_t ctx, void *privdata);
+static idn_result_t
+ converter_iconv_convfromucs4(idn_converter_t ctx,
+ void *privdata,
+ const unsigned long *from,
+ char *to, size_t tolen);
+static idn_result_t
+ converter_iconv_convtoucs4(idn_converter_t ctx,
+ void *privdata,
+ const char *from,
+ unsigned long *to, size_t tolen);
+
+static idn_result_t
+iconv_initialize_privdata(void **privdata);
+static void
+iconv_finalize_privdata(void *privdata);
+
+static char * get_system_aliasfile(void);
+static int file_exist(const char *filename);
+
+#endif /* !WITHOUT_ICONV */
+
+#ifdef DEBUG
+static idn_result_t
+ converter_uescape_convfromucs4(idn_converter_t ctx,
+ void *privdata,
+ const unsigned long *from,
+ char *to, size_t tolen);
+static idn_result_t
+ converter_uescape_convtoucs4(idn_converter_t ctx,
+ void *privdata,
+ const char *from,
+ unsigned long *to,
+ size_t tolen);
+#endif /* DEBUG */
+
+static converter_ops_t none_converter_ops = {
+ converter_none_open,
+ converter_none_open,
+ converter_none_convfromucs4,
+ converter_none_convtoucs4,
+ converter_none_close,
+ IDN_NONACE,
+};
+
+#ifndef WITHOUT_ICONV
+static converter_ops_t iconv_converter_ops = {
+ converter_iconv_openfromucs4,
+ converter_iconv_opentoucs4,
+ converter_iconv_convfromucs4,
+ converter_iconv_convtoucs4,
+ converter_iconv_close,
+ IDN_NONACE,
+};
+#endif
+
+/*
+ * Initialize.
+ */
+
+idn_result_t
+idn_converter_initialize(void) {
+ idn_result_t r;
+ idn__strhash_t hash;
+ idn__aliaslist_t list;
+#ifndef WITHOUT_ICONV
+ const char *fname;
+#endif
+
+ TRACE(("idn_converter_initialize()\n"));
+
+ if (encoding_name_hash == NULL) {
+ if ((r = idn__strhash_create(&hash)) != idn_success)
+ goto ret;
+ encoding_name_hash = hash;
+ r = register_standard_encoding();
+ }
+ if (encoding_alias_list == NULL) {
+ if ((r = idn__aliaslist_create(&list)) != idn_success)
+ goto ret;
+ encoding_alias_list = list;
+#ifndef WITHOUT_ICONV
+ fname = get_system_aliasfile();
+ if (fname != NULL && file_exist(fname))
+ idn_converter_aliasfile(fname);
+#endif
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("idn_converter_initialize(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+#ifndef WITHOUT_ICONV
+static char *
+get_system_aliasfile() {
+#ifdef WIN32
+ static char alias_path[500]; /* a good longer than MAX_PATH */
+
+ if (idn__util_getregistrystring(idn__util_hkey_localmachine,
+ IDNVAL_ALIASFILE,
+ alias_path, sizeof(alias_path))) {
+ return (alias_path);
+ } else {
+ return (NULL);
+ }
+#else
+ return (IDN_ALIAS_FILE);
+#endif
+}
+
+static int
+file_exist(const char *filename) {
+ FILE *fp;
+
+ if ((fp = fopen(filename, "r")) == NULL)
+ return (0);
+ fclose(fp);
+ return (1);
+}
+#endif
+
+idn_result_t
+idn_converter_create(const char *name, idn_converter_t *ctxp, int flags) {
+ const char *realname;
+ idn_converter_t ctx;
+ idn_result_t r;
+ void *v;
+
+ assert(name != NULL && ctxp != NULL);
+
+ TRACE(("idn_converter_create(%s)\n", name));
+
+ realname = idn_converter_getrealname(name);
+#ifdef DEBUG
+ if (strcmp(name, realname) != 0) {
+ TRACE(("idn_converter_create: realname=%s\n", realname));
+ }
+#endif
+
+ *ctxp = NULL;
+
+ /* Allocate memory for a converter context and the name. */
+ ctx = malloc(sizeof(struct idn_converter) + strlen(realname) + 1);
+ if (ctx == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ ctx->local_encoding_name = (char *)(ctx + 1);
+ (void)strcpy(ctx->local_encoding_name, realname);
+ ctx->flags = flags;
+ ctx->reference_count = 1;
+ ctx->opened_convfromucs4 = 0;
+ ctx->opened_convtoucs4 = 0;
+ ctx->private_data = NULL;
+
+ assert(encoding_name_hash != NULL);
+
+ if (strcmp(realname, IDN_UTF8_ENCODING_NAME) == 0) {
+ /* No conversion needed */
+ ctx->ops = &none_converter_ops;
+ } else if ((r = idn__strhash_get(encoding_name_hash, realname, &v))
+ == idn_success) {
+ /* Special converter found */
+ ctx->ops = (converter_ops_t *)v;
+ } else {
+ /* General case */
+#ifdef WITHOUT_ICONV
+ free(ctx);
+ *ctxp = NULL;
+ r = idn_invalid_name;
+ goto ret;
+#else
+ ctx->ops = &iconv_converter_ops;
+#endif
+ }
+
+ if ((flags & IDN_CONVERTER_DELAYEDOPEN) == 0) {
+ r = (ctx->ops->openfromucs4)(ctx, &(ctx->private_data));
+ if (r != idn_success) {
+ WARNING(("idn_converter_create(): open failed "
+ "(ucs4->local)\n"));
+ free(ctx);
+ *ctxp = NULL;
+ goto ret;
+ }
+ ctx->opened_convfromucs4 = 1;
+
+ r = (*ctx->ops->opentoucs4)(ctx, &(ctx->private_data));
+ if (r != idn_success) {
+ WARNING(("idn_converter_create(): open failed "
+ "(local->ucs4)\n"));
+ free(ctx);
+ *ctxp = NULL;
+ goto ret;
+ }
+ ctx->opened_convtoucs4 = 1;
+ }
+
+ *ctxp = ctx;
+ r = idn_success;
+ret:
+ TRACE(("idn_converter_create(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+void
+idn_converter_destroy(idn_converter_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_converter_destroy(ctx=%s)\n", ctx->local_encoding_name));
+
+ ctx->reference_count--;
+ if (ctx->reference_count <= 0) {
+ TRACE(("idn_converter_destroy(): the object is destroyed\n"));
+ (void)(*ctx->ops->close)(ctx, ctx->private_data);
+ free(ctx);
+ } else {
+ TRACE(("idn_converter_destroy(): "
+ "update reference count (%d->%d)\n",
+ ctx->reference_count + 1, ctx->reference_count));
+ }
+}
+
+void
+idn_converter_incrref(idn_converter_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_converter_incrref(ctx=%s)\n", ctx->local_encoding_name));
+ TRACE(("idn_converter_incrref: update reference count (%d->%d)\n",
+ ctx->reference_count, ctx->reference_count + 1));
+
+ ctx->reference_count++;
+}
+
+char *
+idn_converter_localencoding(idn_converter_t ctx) {
+ assert(ctx != NULL);
+ TRACE(("idn_converter_localencoding(ctx=%s)\n",
+ ctx->local_encoding_name));
+ return (ctx->local_encoding_name);
+}
+
+int
+idn_converter_encodingtype(idn_converter_t ctx) {
+ int encoding_type;
+
+ assert(ctx != NULL);
+ TRACE(("idn_converter_encodingtype(ctx=%s)\n",
+ ctx->local_encoding_name));
+
+ encoding_type = ctx->ops->encoding_type;
+ TRACE(("idn_converter_encodingtype(): %d\n", encoding_type));
+ return (encoding_type);
+}
+
+int
+idn_converter_isasciicompatible(idn_converter_t ctx) {
+ int iscompat;
+
+ assert(ctx != NULL);
+ TRACE(("idn_converter_isasciicompatible(ctx=%s)\n",
+ ctx->local_encoding_name));
+
+ iscompat = (ctx->ops->encoding_type != IDN_NONACE);
+ TRACE(("idn_converter_isasciicompatible(): %d\n", iscompat));
+ return (iscompat);
+}
+
+idn_result_t
+idn_converter_convfromucs4(idn_converter_t ctx, const unsigned long *from,
+ char *to, size_t tolen) {
+ idn_result_t r;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_converter_convfromucs4(ctx=%s, from=\"%s\", tolen=%d)\n",
+ ctx->local_encoding_name, idn__debug_ucs4xstring(from, 50),
+ (int)tolen));
+
+ if (!ctx->opened_convfromucs4) {
+ r = (*ctx->ops->openfromucs4)(ctx, &(ctx->private_data));
+ if (r != idn_success)
+ goto ret;
+ ctx->opened_convfromucs4 = 1;
+ }
+
+ r = (*ctx->ops->convfromucs4)(ctx, ctx->private_data, from, to, tolen);
+ if (r != idn_success)
+ goto ret;
+ if ((ctx->flags & IDN_CONVERTER_RTCHECK) != 0) {
+ r = roundtrip_check(ctx, from, to);
+ if (r != idn_success)
+ goto ret;
+ }
+
+ r = idn_success;
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_converter_convfromucs4(): success (to=\"%s\")\n",
+ idn__debug_xstring(to, 50)));
+ } else {
+ TRACE(("idn_converter_convfromucs4(): %s\n",
+ idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+idn_result_t
+idn_converter_convtoucs4(idn_converter_t ctx, const char *from,
+ unsigned long *to, size_t tolen) {
+ idn_result_t r;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_converter_convtoucs4(ctx=%s, from=\"%s\", tolen=%d)\n",
+ ctx->local_encoding_name, idn__debug_xstring(from, 50),
+ (int)tolen));
+
+ if (!ctx->opened_convtoucs4) {
+ r = (*ctx->ops->opentoucs4)(ctx, &(ctx->private_data));
+ if (r != idn_success)
+ goto ret;
+ ctx->opened_convtoucs4 = 1;
+ }
+
+ r = (*ctx->ops->convtoucs4)(ctx, ctx->private_data, from, to, tolen);
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_converter_convtoucs4(): success (to=\"%s\")\n",
+ idn__debug_ucs4xstring(to, 50)));
+ } else {
+ TRACE(("idn_converter_convtoucs4(): %s\n",
+ idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+/*
+ * Encoding registration.
+ */
+
+idn_result_t
+idn_converter_register(const char *name,
+ idn_converter_openproc_t openfromucs4,
+ idn_converter_openproc_t opentoucs4,
+ idn_converter_convfromucs4proc_t convfromucs4,
+ idn_converter_convtoucs4proc_t convtoucs4,
+ idn_converter_closeproc_t close,
+ int encoding_type) {
+ converter_ops_t *ops;
+ idn_result_t r;
+
+ assert(name != NULL && convfromucs4 != NULL && convtoucs4 != NULL);
+
+ TRACE(("idn_converter_register(name=%s)\n", name));
+
+ if ((ops = malloc(sizeof(*ops))) == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ if (openfromucs4 == NULL)
+ openfromucs4 = converter_none_open;
+ if (opentoucs4 == NULL)
+ opentoucs4 = converter_none_open;
+ if (close == NULL)
+ close = converter_none_close;
+
+ ops->openfromucs4 = openfromucs4;
+ ops->opentoucs4 = opentoucs4;
+ ops->convfromucs4 = convfromucs4;
+ ops->convtoucs4 = convtoucs4;
+ ops->close = close;
+ ops->encoding_type = encoding_type;
+
+ r = idn__strhash_put(encoding_name_hash, name, ops);
+ if (r != idn_success) {
+ free(ops);
+ goto ret;
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("idn_converter_register(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+static idn_result_t
+register_standard_encoding(void) {
+ idn_result_t r;
+
+ r = idn_converter_register(IDN_PUNYCODE_ENCODING_NAME,
+ NULL,
+ NULL,
+ idn__punycode_encode,
+ idn__punycode_decode,
+ converter_none_close,
+ IDN_ACE_STRICTCASE);
+ if (r != idn_success)
+ return (r);
+
+#ifdef IDN_EXTRA_ACE
+ r = idn_converter_register(IDN_AMCACEZ_ENCODING_NAME,
+ NULL,
+ NULL,
+ idn__punycode_encode,
+ idn__punycode_decode,
+ converter_none_close,
+ IDN_ACE_STRICTCASE);
+ if (r != idn_success)
+ return (r);
+
+ r = idn_converter_register(IDN_RACE_ENCODING_NAME,
+ NULL,
+ NULL,
+ idn__race_encode,
+ idn__race_decode,
+ converter_none_close,
+ IDN_ACE_LOOSECASE);
+ if (r != idn_success)
+ return (r);
+#endif /* IDN_EXTRA_ACE */
+
+#ifdef DEBUG
+ /* This is convenient for debug. Not useful for other purposes. */
+ r = idn_converter_register("U-escape",
+ NULL,
+ NULL,
+ converter_uescape_convfromucs4,
+ converter_uescape_convtoucs4,
+ NULL,
+ IDN_NONACE);
+ if (r != idn_success)
+ return (r);
+#endif /* DEBUG */
+
+ return (r);
+}
+
+/*
+ * Encoding alias support.
+ */
+idn_result_t
+idn_converter_addalias(const char *alias_name, const char *real_name,
+ int first_item) {
+ idn_result_t r;
+
+ assert(alias_name != NULL && real_name != NULL);
+
+ TRACE(("idn_converter_addalias(alias_name=%s,real_name=%s)\n",
+ alias_name, real_name));
+
+ if (strlen(alias_name) == 0 || strlen(real_name) == 0) {
+ return idn_invalid_syntax;
+ }
+
+ if (strcmp(alias_name, real_name) == 0) {
+ r = idn_success;
+ goto ret;
+ }
+
+ if (encoding_alias_list == NULL) {
+ WARNING(("idn_converter_addalias(): the module is not "
+ "initialized\n"));
+ r = idn_failure;
+ goto ret;
+ }
+
+ r = idn__aliaslist_additem(encoding_alias_list, alias_name, real_name,
+ first_item);
+ret:
+ TRACE(("idn_converter_addalias(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_converter_aliasfile(const char *path) {
+ idn_result_t r;
+
+ assert(path != NULL);
+
+ TRACE(("idn_converter_aliasfile(path=%s)\n", path));
+
+ if (encoding_alias_list == NULL) {
+ WARNING(("idn_converter_aliasfile(): the module is not "
+ "initialized\n"));
+ return (idn_failure);
+ }
+
+ r = idn__aliaslist_aliasfile(encoding_alias_list, path);
+
+ TRACE(("idn_converter_aliasfile(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_converter_resetalias(void) {
+ idn__aliaslist_t list;
+ idn_result_t r;
+
+ TRACE(("idn_converter_resetalias()\n"));
+
+ if (encoding_alias_list == NULL) {
+ WARNING(("idn_converter_resetalias(): the module is not "
+ "initialized\n"));
+ return (idn_failure);
+ }
+
+ list = encoding_alias_list;
+ encoding_alias_list = NULL;
+ idn__aliaslist_destroy(list);
+ list = NULL;
+ r = idn__aliaslist_create(&list);
+ encoding_alias_list = list;
+
+ TRACE(("idn_converter_resetalias(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+const char *
+idn_converter_getrealname(const char *name) {
+ char *realname;
+ idn_result_t r;
+
+ TRACE(("idn_converter_getrealname()\n"));
+
+ assert(name != NULL);
+
+ if (encoding_alias_list == NULL) {
+ WARNING(("idn_converter_getrealname(): the module is not "
+ "initialized\n"));
+ return (name);
+ }
+
+ r = idn__aliaslist_find(encoding_alias_list, name, &realname);
+ if (r != idn_success) {
+ return (name);
+ }
+ return (realname);
+}
+
+/*
+ * Round trip check.
+ */
+
+static idn_result_t
+roundtrip_check(idn_converter_t ctx, const unsigned long *from, const char *to)
+{
+ /*
+ * One problem with iconv() convertion is that
+ * iconv() doesn't signal an error if the input
+ * string contains characters which are valid but
+ * do not have mapping to the output codeset.
+ * (the behavior of iconv() for that case is defined as
+ * `implementation dependent')
+ * One way to check this case is to perform round-trip
+ * conversion and see if it is same as the original string.
+ */
+ idn_result_t r;
+ unsigned long *back;
+ unsigned long backbuf[256];
+ size_t fromlen;
+ size_t backlen;
+
+ TRACE(("idn_converter_convert: round-trip checking (from=\"%s\")\n",
+ idn__debug_ucs4xstring(from, 50)));
+
+ /* Allocate enough buffer. */
+ fromlen = idn_ucs4_strlen(from) + 1;
+ if (fromlen * sizeof(*back) <= sizeof(backbuf)) {
+ backlen = sizeof(backbuf);
+ back = backbuf;
+ } else {
+ backlen = fromlen;
+ back = (unsigned long *)malloc(backlen * sizeof(*back));
+ if (back == NULL)
+ return (idn_nomemory);
+ }
+
+ /*
+ * Perform backward conversion.
+ */
+ r = idn_converter_convtoucs4(ctx, to, back, backlen);
+ switch (r) {
+ case idn_success:
+ if (memcmp(back, from, sizeof(*from) * fromlen) != 0)
+ r = idn_nomapping;
+ break;
+ case idn_invalid_encoding:
+ case idn_buffer_overflow:
+ r = idn_nomapping;
+ break;
+ default:
+ break;
+ }
+
+ if (back != backbuf)
+ free(back);
+
+ if (r != idn_success) {
+ TRACE(("round-trip check failed: %s\n",
+ idn_result_tostring(r)));
+ }
+
+ return (r);
+}
+
+/*
+ * Identity conversion (or, no conversion at all).
+ */
+
+static idn_result_t
+converter_none_open(idn_converter_t ctx, void **privdata) {
+ assert(ctx != NULL);
+
+ return (idn_success);
+}
+
+static idn_result_t
+converter_none_close(idn_converter_t ctx, void *privdata) {
+ assert(ctx != NULL);
+
+ return (idn_success);
+}
+
+static idn_result_t
+converter_none_convfromucs4(idn_converter_t ctx, void *privdata,
+ const unsigned long *from, char *to, size_t tolen) {
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ return idn_ucs4_ucs4toutf8(from, to, tolen);
+}
+
+static idn_result_t
+converter_none_convtoucs4(idn_converter_t ctx, void *privdata,
+ const char *from, unsigned long *to, size_t tolen) {
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ return idn_ucs4_utf8toucs4(from, to, tolen);
+}
+
+#ifndef WITHOUT_ICONV
+
+/*
+ * Conversion using iconv() interface.
+ */
+
+static idn_result_t
+converter_iconv_openfromucs4(idn_converter_t ctx, void **privdata) {
+ iconv_t *ictxp;
+ idn_result_t r;
+
+ assert(ctx != NULL);
+
+ r = iconv_initialize_privdata(privdata);
+ if (r != idn_success)
+ return (r);
+
+ ictxp = (iconv_t *)*privdata;
+ *ictxp = iconv_open(ctx->local_encoding_name, IDN_UTF8_ENCODING_NAME);
+ if (*ictxp == (iconv_t)(-1)) {
+ free(*privdata);
+ *privdata = NULL;
+ switch (errno) {
+ case ENOMEM:
+ return (idn_nomemory);
+ case EINVAL:
+ return (idn_invalid_name);
+ default:
+ WARNING(("iconv_open failed with errno %d\n", errno));
+ return (idn_failure);
+ }
+ }
+
+ return (idn_success);
+}
+
+static idn_result_t
+converter_iconv_opentoucs4(idn_converter_t ctx, void **privdata) {
+ iconv_t *ictxp;
+ idn_result_t r;
+
+ assert(ctx != NULL);
+
+ r = iconv_initialize_privdata(privdata);
+ if (r != idn_success)
+ return (r);
+
+ ictxp = (iconv_t *)*privdata + 1;
+ *ictxp = iconv_open(IDN_UTF8_ENCODING_NAME, ctx->local_encoding_name);
+ if (*ictxp == (iconv_t)(-1)) {
+ free(*privdata);
+ *privdata = NULL;
+ switch (errno) {
+ case ENOMEM:
+ return (idn_nomemory);
+ case EINVAL:
+ return (idn_invalid_name);
+ default:
+ WARNING(("iconv_open failed with errno %d\n", errno));
+ return (idn_failure);
+ }
+ }
+
+ return (idn_success);
+}
+
+static idn_result_t
+iconv_initialize_privdata(void **privdata) {
+ if (*privdata == NULL) {
+ *privdata = malloc(sizeof(iconv_t) * 2);
+ if (*privdata == NULL)
+ return (idn_nomemory);
+ *((iconv_t *)*privdata) = (iconv_t)(-1);
+ *((iconv_t *)*privdata + 1) = (iconv_t)(-1);
+ }
+
+ return (idn_success);
+}
+
+static void
+iconv_finalize_privdata(void *privdata) {
+ iconv_t *ictxp;
+
+ if (privdata != NULL) {
+ ictxp = (iconv_t *)privdata;
+ if (*ictxp != (iconv_t)(-1))
+ iconv_close(*ictxp);
+
+ ictxp++;
+ if (*ictxp != (iconv_t)(-1))
+ iconv_close(*ictxp);
+ free(privdata);
+ }
+}
+
+static idn_result_t
+converter_iconv_close(idn_converter_t ctx, void *privdata) {
+ assert(ctx != NULL);
+
+ iconv_finalize_privdata(privdata);
+
+ return (idn_success);
+}
+
+static idn_result_t
+converter_iconv_convfromucs4(idn_converter_t ctx, void *privdata,
+ const unsigned long *from, char *to,
+ size_t tolen) {
+ iconv_t ictx;
+ char *utf8 = NULL;
+ size_t utf8size = 256; /* large enough */
+ idn_result_t r;
+ size_t sz;
+ size_t inleft;
+ size_t outleft;
+ char *inbuf, *outbuf;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ if (tolen <= 0) {
+ r = idn_buffer_overflow; /* need space for NUL */
+ goto ret;
+ }
+
+ /*
+ * UCS4 -> UTF-8 conversion.
+ */
+ utf8 = (char *)malloc(utf8size);
+ if (utf8 == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+try_again:
+ r = idn_ucs4_ucs4toutf8(from, utf8, utf8size);
+ if (r == idn_buffer_overflow) {
+ char *new_utf8;
+
+ utf8size *= 2;
+ new_utf8 = (char *)realloc(utf8, utf8size);
+ if (new_utf8 == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ utf8 = new_utf8;
+ goto try_again;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+
+ ictx = ((iconv_t *)privdata)[0];
+
+ /*
+ * Reset internal state.
+ *
+ * The following code should work according to the SUSv2 spec,
+ * but causes segmentation fault with Solaris 2.6.
+ * So.. a work-around.
+ *
+ * (void)iconv(ictx, (const char **)NULL, (size_t *)NULL,
+ * (char **)NULL, (size_t *)NULL);
+ */
+ inleft = 0;
+ outbuf = NULL;
+ outleft = 0;
+ (void)iconv(ictx, (const char **)NULL, &inleft, &outbuf, &outleft);
+
+ inleft = strlen(utf8);
+ inbuf = utf8;
+ outleft = tolen - 1; /* reserve space for terminating NUL */
+ sz = iconv(ictx, (const char **)&inbuf, &inleft, &to, &outleft);
+
+ if (sz == (size_t)(-1) || inleft > 0) {
+ switch (errno) {
+ case EILSEQ:
+ case EINVAL:
+ /*
+ * We already checked the validity of the input
+ * string. So we assume a mapping error.
+ */
+ r = idn_nomapping;
+ goto ret;
+ case E2BIG:
+ r = idn_buffer_overflow;
+ goto ret;
+ default:
+ WARNING(("iconv failed with errno %d\n", errno));
+ r = idn_failure;
+ goto ret;
+ }
+ }
+
+ /*
+ * For UTF-8 -> local conversion, append a sequence of
+ * state reset.
+ */
+ inleft = 0;
+ sz = iconv(ictx, (const char **)NULL, &inleft, &to, &outleft);
+ if (sz == (size_t)(-1)) {
+ switch (errno) {
+ case EILSEQ:
+ case EINVAL:
+ r = idn_invalid_encoding;
+ goto ret;
+ case E2BIG:
+ r = idn_buffer_overflow;
+ goto ret;
+ default:
+ WARNING(("iconv failed with errno %d\n", errno));
+ r = idn_failure;
+ goto ret;
+ }
+ }
+ *to = '\0';
+ r = idn_success;
+
+ret:
+ free(utf8);
+ return (r);
+
+}
+
+static idn_result_t
+converter_iconv_convtoucs4(idn_converter_t ctx, void *privdata,
+ const char *from, unsigned long *to, size_t tolen) {
+ iconv_t ictx;
+ char *utf8 = NULL;
+ size_t utf8size = 256; /* large enough */
+ idn_result_t r;
+ size_t sz;
+ size_t inleft;
+ size_t outleft;
+ const char *from_ptr;
+ char *outbuf;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ if (tolen <= 0) {
+ r = idn_buffer_overflow; /* need space for NUL */
+ goto ret;
+ }
+ ictx = ((iconv_t *)privdata)[1];
+ utf8 = (char *)malloc(utf8size);
+ if (utf8 == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+try_again:
+ /*
+ * Reset internal state.
+ */
+ inleft = 0;
+ outbuf = NULL;
+ outleft = 0;
+ (void)iconv(ictx, (const char **)NULL, &inleft, &outbuf, &outleft);
+
+ from_ptr = from;
+ inleft = strlen(from);
+ outbuf = utf8;
+ outleft = utf8size - 1; /* reserve space for terminating NUL */
+ sz = iconv(ictx, (const char **)&from_ptr, &inleft, &outbuf, &outleft);
+
+ if (sz == (size_t)(-1) || inleft > 0) {
+ char *new_utf8;
+
+ switch (errno) {
+ case EILSEQ:
+ case EINVAL:
+ /*
+ * We assume all the characters in the local
+ * codeset are included in UCS. This means mapping
+ * error is not possible, so the input string must
+ * have some problem.
+ */
+ r = idn_invalid_encoding;
+ goto ret;
+ case E2BIG:
+ utf8size *= 2;
+ new_utf8 = (char *)realloc(utf8, utf8size);
+ if (new_utf8 == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ utf8 = new_utf8;
+ goto try_again;
+ default:
+ WARNING(("iconv failed with errno %d\n", errno));
+ r = idn_failure;
+ goto ret;
+ }
+ }
+ *outbuf = '\0';
+
+ /*
+ * UTF-8 -> UCS4 conversion.
+ */
+ r = idn_ucs4_utf8toucs4(utf8, to, tolen);
+
+ret:
+ free(utf8);
+ return (r);
+}
+
+#endif /* !WITHOUT_ICONV */
+
+#ifdef DEBUG
+/*
+ * Conversion to/from unicode escape string.
+ * Arbitrary UCS-4 character can be specified by a special sequence
+ * \u{XXXXXX}
+ * where XXXXX denotes any hexadecimal string up to FFFFFFFF.
+ * This is designed for debugging.
+ */
+
+static idn_result_t
+converter_uescape_convfromucs4(idn_converter_t ctx, void *privdata,
+ const unsigned long *from, char *to,
+ size_t tolen) {
+ idn_result_t r;
+ unsigned long v;
+
+ while (*from != '\0') {
+ v = *from++;
+
+ if (v <= 0x7f) {
+ if (tolen < 1) {
+ r = idn_buffer_overflow;
+ goto failure;
+ }
+ *to++ = v;
+ tolen--;
+ } else if (v <= 0xffffffff) {
+ char tmp[20];
+ int len;
+
+ (void)sprintf(tmp, "\\u{%lx}", v);
+ len = strlen(tmp);
+ if (tolen < len) {
+ r = idn_buffer_overflow;
+ goto failure;
+ }
+ (void)memcpy(to, tmp, len);
+ to += len;
+ tolen -= len;
+ } else {
+ r = idn_invalid_encoding;
+ goto failure;
+ }
+ }
+
+ if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto failure;
+ }
+ *to = '\0';
+
+ return (idn_success);
+
+failure:
+ if (r != idn_buffer_overflow) {
+ WARNING(("idn_uescape_convfromucs4(): %s\n",
+ idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+static idn_result_t
+converter_uescape_convtoucs4(idn_converter_t ctx, void *privdata,
+ const char *from, unsigned long *to, size_t tolen)
+{
+ idn_result_t r;
+ size_t fromlen = strlen(from);
+
+ while (*from != '\0') {
+ if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto failure;
+ }
+ if (strncmp(from, "\\u{", 3) == 0 ||
+ strncmp(from, "\\U{", 3) == 0) {
+ size_t ullen;
+ unsigned long v;
+ char *end;
+
+ v = strtoul(from + 3, &end, 16);
+ ullen = end - (from + 3);
+ if (*end == '}' && ullen > 1 && ullen < 8) {
+ *to = v;
+ from = end + 1;
+ fromlen -= ullen;
+ } else {
+ *to = '\\';
+ from++;
+ fromlen--;
+ }
+ } else {
+ int c = *(unsigned char *)from;
+ size_t width;
+ char buf[8];
+
+ if (c < 0x80)
+ width = 1;
+ else if (c < 0xc0)
+ width = 0;
+ else if (c < 0xe0)
+ width = 2;
+ else if (c < 0xf0)
+ width = 3;
+ else if (c < 0xf8)
+ width = 4;
+ else if (c < 0xfc)
+ width = 5;
+ else if (c < 0xfe)
+ width = 6;
+ else
+ width = 0;
+ if (width == 0 || width > fromlen) {
+ r = idn_invalid_encoding;
+ goto failure;
+ }
+
+ memcpy(buf, from, width);
+ buf[width] = '\0';
+ r = idn_ucs4_utf8toucs4(buf, to, tolen);
+ if (r != idn_success) {
+ r = idn_invalid_encoding;
+ goto failure;
+ }
+ from += width;
+ fromlen -= width;
+ }
+ to++;
+ tolen--;
+ }
+
+ if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto failure;
+ }
+ *to = '\0';
+
+ return (idn_success);
+
+failure:
+ if (r != idn_buffer_overflow) {
+ WARNING(("idn_uescape_convtoucs4(): %s\n",
+ idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+#endif
diff --git a/contrib/idn/idnkit-1.0-src/lib/debug.c b/contrib/idn/idnkit-1.0-src/lib/debug.c
new file mode 100644
index 0000000..07eba0a
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/debug.c
@@ -0,0 +1,267 @@
+#ifndef lint
+static char *rcsid = "$Id: debug.c,v 1.1.1.1 2003/06/04 00:25:51 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/debug.h>
+
+static char *hex = "0123456789abcdef";
+
+#define STRING_MAXBYTES 200
+#define STRING_NBUFS 4
+static char bufs[STRING_NBUFS][STRING_MAXBYTES + 16]; /* +16 for margin */
+static int bufno = 0;
+
+char *
+idn__debug_hexstring(const char *s, int maxbytes) {
+ char *buf = bufs[bufno];
+ char *p;
+ int i;
+
+ if (maxbytes > STRING_MAXBYTES)
+ maxbytes = STRING_MAXBYTES;
+
+ for (i = 0, p = buf; i < maxbytes; i += 3, s++) {
+ int c = *(unsigned char *)s;
+
+ if (c == '\0')
+ break;
+ *p++ = hex[c >> 4];
+ *p++ = hex[c & 15];
+ *p++ = ' ';
+ }
+
+ if (i >= maxbytes)
+ strcpy(p, "...");
+ else
+ *p = '\0';
+
+ bufno = (bufno + 1) % STRING_NBUFS;
+ return (buf);
+}
+
+char *
+idn__debug_xstring(const char *s, int maxbytes) {
+ char *buf = bufs[bufno];
+ char *p;
+ int i;
+
+ if (maxbytes > STRING_MAXBYTES)
+ maxbytes = STRING_MAXBYTES;
+
+ i = 0;
+ p = buf;
+ while (i < maxbytes) {
+ int c = *(unsigned char *)s;
+
+ if (c == '\0') {
+ break;
+ } else if (0x20 <= c && c <= 0x7e) {
+ *p++ = c;
+ i++;
+ } else {
+ *p++ = '\\';
+ *p++ = 'x';
+ *p++ = hex[c >> 4];
+ *p++ = hex[c & 15];
+ i += 4;
+ }
+ s++;
+ }
+
+ if (i >= maxbytes)
+ strcpy(p, "...");
+ else
+ *p = '\0';
+
+ bufno = (bufno + 1) % STRING_NBUFS;
+ return (buf);
+}
+
+char *
+idn__debug_ucs4xstring(const unsigned long *s, int maxbytes) {
+ char *buf = bufs[bufno];
+ char *p;
+ int i;
+
+ if (maxbytes > STRING_MAXBYTES)
+ maxbytes = STRING_MAXBYTES;
+
+ i = 0;
+ p = buf;
+ while (i < maxbytes) {
+ if (*s == '\0') {
+ break;
+ } else if (0x20 <= *s && *s <= 0x7e) {
+ *p++ = *s;
+ i++;
+ } else {
+ *p++ = '\\';
+ *p++ = 'x';
+ i += 2;
+ if (*s >= 0x1000000UL) {
+ *p++ = hex[(*s >> 28) & 0x0f];
+ *p++ = hex[(*s >> 24) & 0x0f];
+ i += 2;
+ }
+ if (*s >= 0x10000UL) {
+ *p++ = hex[(*s >> 20) & 0x0f];
+ *p++ = hex[(*s >> 16) & 0x0f];
+ i += 2;
+ }
+ if (*s >= 0x100UL) {
+ *p++ = hex[(*s >> 12) & 0x0f];
+ *p++ = hex[(*s >> 8) & 0x0f];
+ i += 2;
+ }
+ *p++ = hex[(*s >> 4) & 0x0f];
+ *p++ = hex[ *s & 0x0f];
+ i += 2;
+ }
+ s++;
+ }
+
+ if (i >= maxbytes)
+ strcpy(p, "...");
+ else
+ *p = '\0';
+
+ bufno = (bufno + 1) % STRING_NBUFS;
+ return (buf);
+}
+
+char *
+idn__debug_utf16xstring(const unsigned short *s, int maxbytes) {
+ char *buf = bufs[bufno];
+ char *p;
+ int i;
+
+ if (maxbytes > STRING_MAXBYTES)
+ maxbytes = STRING_MAXBYTES;
+
+ i = 0;
+ p = buf;
+ while (i < maxbytes) {
+ if (*s == '\0') {
+ break;
+ } else if (0x20 <= *s && *s <= 0x7e) {
+ *p++ = *s;
+ i++;
+ } else {
+ *p++ = '\\';
+ *p++ = 'x';
+ *p++ = hex[(*s >> 12) & 0x0f];
+ *p++ = hex[(*s >> 8) & 0x0f];
+ *p++ = hex[(*s >> 4) & 0x0f];
+ *p++ = hex[ *s & 0x0f];
+ i += 6;
+ }
+ s++;
+ }
+
+ if (i >= maxbytes)
+ strcpy(p, "...");
+ else
+ *p = '\0';
+
+ bufno = (bufno + 1) % STRING_NBUFS;
+ return (buf);
+}
+
+char *
+idn__debug_hexdata(const char *s, int length, int maxbytes) {
+ char *buf = bufs[bufno];
+ char *p;
+ int i;
+
+ if (maxbytes > STRING_MAXBYTES)
+ maxbytes = STRING_MAXBYTES;
+
+ i = 0;
+ p = buf;
+ while (length > 0 && i < maxbytes) {
+ int c = *(const unsigned char *)s;
+
+ *p++ = hex[c >> 4];
+ *p++ = hex[c & 15];
+ *p++ = ' ';
+ i += 3;
+ length--;
+ s++;
+ }
+
+ if (i >= maxbytes)
+ strcpy(p, "...");
+ else
+ *p = '\0';
+
+ bufno = (bufno + 1) % STRING_NBUFS;
+ return (buf);
+}
+
+void
+idn__debug_hexdump(const char *s, int length) {
+ int i;
+ const unsigned char *p = (const unsigned char *)s;
+
+ i = 0;
+ while (length-- > 0) {
+ if (i % 16 == 0) {
+ if (i > 0)
+ fprintf(stderr, "\n");
+ fprintf(stderr, "%4x:", i);
+ }
+ fprintf(stderr, " %02x", p[i]);
+ i++;
+ }
+ fprintf(stderr, "\n");
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/delimitermap.c b/contrib/idn/idnkit-1.0-src/lib/delimitermap.c
new file mode 100644
index 0000000..6f470a8
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/delimitermap.c
@@ -0,0 +1,268 @@
+#ifndef lint
+static char *rcsid = "$Id: delimitermap.c,v 1.1.1.1 2003/06/04 00:25:52 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/delimitermap.h>
+#include <idn/util.h>
+#include <idn/debug.h>
+#include <idn/ucs4.h>
+
+/*
+ * Mapper object type.
+ */
+struct idn_delimitermap {
+ int ndelimiters;
+ int delimiter_size;
+ unsigned long *delimiters;
+ int reference_count;
+};
+
+#define DELIMITERMAP_INITIAL_DELIMITER_SIZE 4
+#define UNICODE_MAX 0x10ffff
+#define IS_SURROGATE_HIGH(v) (0xd800 <= (v) && (v) <= 0xdbff)
+#define IS_SURROGATE_LOW(v) (0xdc00 <= (v) && (v) <= 0xdfff)
+
+idn_result_t
+idn_delimitermap_create(idn_delimitermap_t *ctxp) {
+ idn_delimitermap_t ctx = NULL;
+ idn_result_t r;
+
+ assert(ctxp != NULL);
+ TRACE(("idn_delimitermap_create()\n"));
+
+ ctx = (idn_delimitermap_t) malloc(sizeof(struct idn_delimitermap));
+ if (ctx == NULL) {
+ WARNING(("idn_mapper_create: malloc failed\n"));
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ ctx->delimiters = (unsigned long *) malloc(sizeof(unsigned long)
+ * DELIMITERMAP_INITIAL_DELIMITER_SIZE);
+ if (ctx->delimiters == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ ctx->ndelimiters = 0;
+ ctx->delimiter_size = DELIMITERMAP_INITIAL_DELIMITER_SIZE;
+ ctx->reference_count = 1;
+ *ctxp = ctx;
+ r = idn_success;
+
+ret:
+ if (r != idn_success)
+ free(ctx);
+ TRACE(("idn_delimitermap_create(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+void
+idn_delimitermap_destroy(idn_delimitermap_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_delimitermap_destroy()\n"));
+
+ ctx->reference_count--;
+ if (ctx->reference_count <= 0) {
+ TRACE(("idn_mapper_destroy(): the object is destroyed\n"));
+ free(ctx->delimiters);
+ free(ctx);
+ } else {
+ TRACE(("idn_delimitermap_destroy(): "
+ "update reference count (%d->%d)\n",
+ ctx->reference_count + 1, ctx->reference_count));
+ }
+}
+
+void
+idn_delimitermap_incrref(idn_delimitermap_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_delimitermap_incrref()\n"));
+ TRACE(("idn_delimitermap_incrref: update reference count (%d->%d)\n",
+ ctx->reference_count, ctx->reference_count + 1));
+
+ ctx->reference_count++;
+}
+
+idn_result_t
+idn_delimitermap_add(idn_delimitermap_t ctx, unsigned long delimiter) {
+ idn_result_t r;
+
+ assert(ctx != NULL && ctx->ndelimiters <= ctx->delimiter_size);
+ TRACE(("idn_delimitermap_add(delimiter=\\x%04lx)\n", delimiter));
+
+ if (delimiter == 0 || delimiter > UNICODE_MAX ||
+ IS_SURROGATE_HIGH(delimiter) || IS_SURROGATE_LOW(delimiter)) {
+ r = idn_invalid_codepoint;
+ goto ret;
+ }
+
+ if (ctx->ndelimiters == ctx->delimiter_size) {
+ unsigned long *new_delimiters;
+
+ new_delimiters = (unsigned long *) realloc(ctx->delimiters,
+ sizeof(unsigned long) * ctx->delimiter_size * 2);
+ if (new_delimiters == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ ctx->delimiters = new_delimiters;
+ ctx->delimiter_size *= 2;
+ }
+
+ ctx->delimiters[ctx->ndelimiters] = delimiter;
+ ctx->ndelimiters++;
+ r = idn_success;
+
+ret:
+ TRACE(("idn_delimitermap_add(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_delimitermap_addall(idn_delimitermap_t ctx, unsigned long *delimiters,
+ int ndelimiters) {
+ idn_result_t r;
+ int i;
+
+ assert(ctx != NULL && delimiters != NULL);
+
+ TRACE(("idn_delimitermap_addall(ndelimiters=%d)\n", ndelimiters));
+
+ for (i = 0; i < ndelimiters; i++) {
+ r = idn_delimitermap_add(ctx, *delimiters);
+ if (r != idn_success)
+ goto ret;
+ delimiters++;
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("idn_delimitermap_addall(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_delimitermap_map(idn_delimitermap_t ctx, const unsigned long *from,
+ unsigned long *to, size_t tolen) {
+
+ /* default delimiters (label separators) from IDNA specification */
+ static const unsigned long default_delimiters[] =
+ { 0x002e, /* full stop */
+ 0x3002, /* ideographic full stop */
+ 0xff0e, /* fullwidth full stop */
+ 0xff61, /* halfwidth ideographic full stop */
+ 0x0000 };
+
+ unsigned long *to_org = to;
+ idn_result_t r;
+ int i, j;
+ int found;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_delimitermap_map(from=\"%s\", tolen=%d)\n",
+ idn__debug_ucs4xstring(from, 50), (int)tolen));
+
+ /*
+ * Map.
+ */
+ while (*from != '\0') {
+ found = 0;
+ if (tolen < 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ for (j = 0; default_delimiters[j] != 0x0000; j++) {
+ if (default_delimiters[j] == *from) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ for (i = 0; i < ctx->ndelimiters; i++) {
+ if (ctx->delimiters[i] == *from) {
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (found)
+ *to = '.';
+ else
+ *to = *from;
+ from++;
+ to++;
+ tolen--;
+ }
+
+ if (tolen < 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *to = '\0';
+ r = idn_success;
+
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_delimitermap_map(): success (to=\"%s\")\n",
+ idn__debug_ucs4xstring(to_org, 50)));
+ } else {
+ TRACE(("idn_delimitermap_map(): %s\n",
+ idn_result_tostring(r)));
+ }
+ return (r);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/filechecker.c b/contrib/idn/idnkit-1.0-src/lib/filechecker.c
new file mode 100644
index 0000000..64330bb
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/filechecker.c
@@ -0,0 +1,261 @@
+#ifndef lint
+static char *rcsid = "$Id: filechecker.c,v 1.1.1.1 2003/06/04 00:25:52 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/log.h>
+#include <idn/logmacro.h>
+#include <idn/ucsset.h>
+#include <idn/filechecker.h>
+#include <idn/debug.h>
+
+#define SUPPORT_VERSIONING
+
+struct idn__filechecker {
+ idn_ucsset_t set;
+};
+
+static idn_result_t read_file(const char *file, FILE *fp,
+ idn_ucsset_t set);
+static int get_range(char *s, unsigned long *ucs1,
+ unsigned long *ucs2);
+static char *get_ucs(char *p, unsigned long *vp);
+
+
+idn_result_t
+idn__filechecker_create(const char *file, idn__filechecker_t *ctxp) {
+ FILE *fp;
+ idn__filechecker_t ctx;
+ idn_result_t r;
+
+ assert(file != NULL && ctxp != NULL);
+
+ TRACE(("idn__filechecker_create(file=\"%-.100s\")\n", file));
+
+ if ((fp = fopen(file, "r")) == NULL) {
+ WARNING(("idn__filechecker_create: cannot open %-.100s\n",
+ file));
+ return (idn_nofile);
+ }
+
+ if ((ctx = malloc(sizeof(struct idn__filechecker))) == NULL)
+ return (idn_nomemory);
+
+ if ((r = idn_ucsset_create(&ctx->set)) != idn_success) {
+ free(ctx);
+ return (r);
+ }
+
+ r = read_file(file, fp, ctx->set);
+ fclose(fp);
+
+ if (r == idn_success) {
+ idn_ucsset_fix(ctx->set);
+ *ctxp = ctx;
+ } else {
+ idn_ucsset_destroy(ctx->set);
+ free(ctx);
+ }
+ return (r);
+}
+
+void
+idn__filechecker_destroy(idn__filechecker_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn__filechecker_destroy()\n"));
+
+ idn_ucsset_destroy(ctx->set);
+ free(ctx);
+}
+
+idn_result_t
+idn__filechecker_lookup(idn__filechecker_t ctx, const unsigned long *str,
+ const unsigned long **found) {
+ idn_result_t r = idn_success;
+
+ assert(ctx != NULL && str != NULL);
+
+ TRACE(("idn__filechecker_lookup(str=\"%s\")\n",
+ idn__debug_ucs4xstring(str, 50)));
+
+ while (*str != '\0') {
+ int exists;
+
+ r = idn_ucsset_lookup(ctx->set, *str, &exists);
+
+ if (r != idn_success) {
+ return (r);
+ } else if (exists) {
+ /* Found. */
+ *found = str;
+ return (idn_success);
+ }
+ str++;
+ }
+ *found = NULL;
+ return (idn_success);
+}
+
+static idn_result_t
+read_file(const char *file, FILE *fp, idn_ucsset_t set) {
+ char line[256];
+ idn_result_t r;
+ int lineno = 0;
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ char *p = line;
+ unsigned long ucs1, ucs2;
+
+ lineno++;
+ while (isspace((unsigned char)*p))
+ p++;
+ if (*p == '\0' || *p == '#')
+ continue;
+
+#ifdef SUPPORT_VERSIONING
+ /* Skip version tag. */
+ if (lineno == 1 && strncmp("version=", line, 8) == 0)
+ continue;
+#endif
+ if (!get_range(p, &ucs1, &ucs2)) {
+ WARNING(("syntax error in file \"%-.100s\" line %d: "
+ "%-.100s", file, lineno, line));
+ return (idn_invalid_syntax);
+ }
+ if ((r = idn_ucsset_addrange(set, ucs1, ucs2)) != idn_success)
+ return (r);
+ }
+ return (idn_success);
+}
+
+static int
+get_range(char *s, unsigned long *ucs1, unsigned long *ucs2) {
+ if ((s = get_ucs(s, ucs1)) == NULL)
+ return (0);
+ *ucs2 = *ucs1;
+
+ switch (s[0]) {
+ case '\0':
+ case '\n':
+ case '#':
+ case ';':
+ return (1);
+ case '-':
+ break;
+ default:
+ return (0);
+ }
+
+ if ((s = get_ucs(s + 1, ucs2)) == NULL)
+ return (0);
+
+ if (*ucs1 > *ucs2) {
+ INFO(("idn__filechecker_create: invalid range spec "
+ "U+%X-U+%X\n", *ucs1, *ucs2));
+ return (0);
+ }
+
+ switch (s[0]) {
+ case '\0':
+ case '\n':
+ case '#':
+ case ';':
+ return (1);
+ default:
+ return (0);
+ }
+}
+
+
+static char *
+get_ucs(char *p, unsigned long *vp) {
+ char *end;
+
+ /* Skip leading space */
+ while (isspace((unsigned char)*p))
+ p++;
+
+ /* Skip optional 'U+' */
+ if (strncmp(p, "U+", 2) == 0)
+ p += 2;
+
+ *vp = strtoul(p, &end, 16);
+ if (end == p) {
+ INFO(("idn__filechecker_create: UCS code point expected\n"));
+ return (NULL);
+ }
+ p = end;
+
+ /* Skip trailing space */
+ while (isspace((unsigned char)*p))
+ p++;
+ return p;
+}
+
+idn_result_t
+idn__filechecker_createproc(const char *parameter, void **ctxp) {
+ return idn__filechecker_create(parameter, (idn__filechecker_t *)ctxp);
+}
+
+void
+idn__filechecker_destroyproc(void *ctxp) {
+ idn__filechecker_destroy((idn__filechecker_t)ctxp);
+}
+
+idn_result_t
+idn__filechecker_lookupproc(void *ctx, const unsigned long *str,
+ const unsigned long **found) {
+ return idn__filechecker_lookup((idn__filechecker_t)ctx, str, found);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/filemapper.c b/contrib/idn/idnkit-1.0-src/lib/filemapper.c
new file mode 100644
index 0000000..970b942
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/filemapper.c
@@ -0,0 +1,347 @@
+#ifndef lint
+static char *rcsid = "$Id: filemapper.c,v 1.1.1.1 2003/06/04 00:25:53 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/log.h>
+#include <idn/logmacro.h>
+#include <idn/debug.h>
+#include <idn/ucs4.h>
+#include <idn/ucsmap.h>
+#include <idn/filemapper.h>
+
+#define SUPPORT_VERSIONING
+
+#define UCSBUF_LOCAL_SIZE 20
+
+typedef struct ucsbuf {
+ unsigned long *ucs;
+ size_t size;
+ size_t len;
+ unsigned long local[UCSBUF_LOCAL_SIZE];
+} ucsbuf_t;
+
+struct idn__filemapper {
+ idn_ucsmap_t map;
+};
+
+static void ucsbuf_init(ucsbuf_t *b);
+static idn_result_t ucsbuf_grow(ucsbuf_t *b);
+static idn_result_t ucsbuf_append(ucsbuf_t *b, unsigned long v);
+static void ucsbuf_free(ucsbuf_t *b);
+static idn_result_t read_file(const char *file, FILE *fp,
+ idn_ucsmap_t map);
+static idn_result_t get_map(char *p, ucsbuf_t *b);
+static char *get_ucs(char *p, unsigned long *vp);
+
+
+idn_result_t
+idn__filemapper_create(const char *file, idn__filemapper_t *ctxp) {
+ FILE *fp;
+ idn__filemapper_t ctx;
+ idn_result_t r;
+
+ assert(file != NULL && ctxp != NULL);
+
+ TRACE(("idn__filemapper_create(file=\"%-.100s\")\n", file));
+
+ if ((fp = fopen(file, "r")) == NULL) {
+ WARNING(("idn__filemapper_create: cannot open %-.100s\n",
+ file));
+ return (idn_nofile);
+ }
+ if ((ctx = malloc(sizeof(struct idn__filemapper))) == NULL)
+ return (idn_nomemory);
+
+ if ((r = idn_ucsmap_create(&ctx->map)) != idn_success) {
+ free(ctx);
+ return (r);
+ }
+
+ r = read_file(file, fp, ctx->map);
+ fclose(fp);
+
+ if (r == idn_success) {
+ idn_ucsmap_fix(ctx->map);
+ *ctxp = ctx;
+ } else {
+ idn_ucsmap_destroy(ctx->map);
+ free(ctx);
+ }
+ return (r);
+}
+
+void
+idn__filemapper_destroy(idn__filemapper_t ctx) {
+
+ assert(ctx != NULL);
+
+ TRACE(("idn__filemapper_destroy()\n"));
+
+ idn_ucsmap_destroy(ctx->map);
+ free(ctx);
+}
+
+idn_result_t
+idn__filemapper_map(idn__filemapper_t ctx, const unsigned long *from,
+ unsigned long *to, size_t tolen)
+{
+ idn_result_t r = idn_success;
+ ucsbuf_t ub;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn__filemapper_map(from=\"%s\")\n",
+ idn__debug_ucs4xstring(from, 50)));
+
+ /* Initialize temporary buffer. */
+ ucsbuf_init(&ub);
+
+ while (*from != '\0') {
+ /* Try mapping. */
+ r = idn_ucsmap_map(ctx->map, *from, ub.ucs, ub.size, &ub.len);
+ switch (r) {
+ case idn_buffer_overflow:
+ /* Temporary buffer too small. Enlarge and retry. */
+ if ((r = ucsbuf_grow(&ub)) != idn_success)
+ break;
+ continue;
+ case idn_nomapping:
+ /* There is no mapping. */
+ r = idn_success;
+ /* fallthrough */
+ case idn_success:
+ if (tolen < ub.len) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ memcpy(to, ub.ucs, sizeof(*to) * ub.len);
+ to += ub.len;
+ tolen -= ub.len;
+ break;
+ default:
+ goto ret;
+ }
+ from++;
+ }
+
+ ret:
+ ucsbuf_free(&ub);
+
+ if (r == idn_success) {
+ /* Terminate with NUL. */
+ if (tolen == 0)
+ return (idn_buffer_overflow);
+ *to = '\0';
+ }
+
+ return (r);
+}
+
+static void
+ucsbuf_init(ucsbuf_t *b) {
+ b->ucs = b->local;
+ b->size = UCSBUF_LOCAL_SIZE;
+ b->len = 0;
+}
+
+static idn_result_t
+ucsbuf_grow(ucsbuf_t *b) {
+ unsigned long *newbuf;
+
+ b->size *= 2;
+ if (b->ucs == b->local) {
+ b->ucs = malloc(sizeof(unsigned long) * b->size);
+ if (b->ucs == NULL)
+ return (idn_nomemory);
+ memcpy(b->ucs, b->local, sizeof(b->local));
+ } else {
+ newbuf = realloc(b->ucs, sizeof(unsigned long) * b->size);
+ if (newbuf == NULL)
+ return (idn_nomemory);
+ b->ucs = newbuf;
+ }
+ return (idn_success);
+}
+
+static idn_result_t
+ucsbuf_append(ucsbuf_t *b, unsigned long v) {
+ idn_result_t r;
+
+ if (b->len + 1 > b->size) {
+ r = ucsbuf_grow(b);
+ if (r != idn_success)
+ return (r);
+ }
+ b->ucs[b->len++] = v;
+ return (idn_success);
+}
+
+static void
+ucsbuf_free(ucsbuf_t *b) {
+ if (b->ucs != b->local && b->ucs != NULL)
+ free(b->ucs);
+}
+
+static idn_result_t
+read_file(const char *file, FILE *fp, idn_ucsmap_t map) {
+ char line[1024];
+ ucsbuf_t ub;
+ idn_result_t r = idn_success;
+ int lineno = 0;
+
+ ucsbuf_init(&ub);
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ char *p = line;
+
+ lineno++;
+ while (isspace((unsigned char)*p))
+ p++;
+ if (*p == '\0' || *p == '#')
+ continue;
+#ifdef SUPPORT_VERSIONING
+ /* Skip version tag. */
+ if (lineno == 1 && strncmp("version=", line, 8) == 0)
+ continue;
+#endif
+ again:
+ ub.len = 0;
+ r = get_map(p, &ub);
+ switch (r) {
+ case idn_success:
+ r = idn_ucsmap_add(map, ub.ucs[0],
+ &ub.ucs[1], ub.len - 1);
+ break;
+ case idn_buffer_overflow:
+ if ((r = ucsbuf_grow(&ub)) != idn_success)
+ break;
+ goto again;
+ case idn_invalid_syntax:
+ WARNING(("syntax error in file \"%-.100s\" line %d: "
+ "%-.100s", file, lineno, line));
+ /* fall through */
+ default:
+ ucsbuf_free(&ub);
+ return (r);
+ }
+ }
+ ucsbuf_free(&ub);
+ return (r);
+}
+
+static idn_result_t
+get_map(char *p, ucsbuf_t *b) {
+ unsigned long v;
+ idn_result_t r = idn_success;
+
+ for (;;) {
+ if ((p = get_ucs(p, &v)) == NULL)
+ return (idn_invalid_syntax);
+ if ((r = ucsbuf_append(b, v)) != idn_success)
+ return (r);
+ if (b->len == 1) {
+ if (*p != ';')
+ return (idn_invalid_syntax);
+ p++;
+ while (isspace((unsigned char)*p))
+ p++;
+ }
+
+ if (*p == ';' || *p == '#' || *p == '\0')
+ return (r);
+ }
+ return (r);
+}
+
+static char *
+get_ucs(char *p, unsigned long *vp) {
+ char *end;
+
+ /* Skip leading space */
+ while (isspace((unsigned char)*p))
+ p++;
+
+ /* Skip optional 'U+' */
+ if (strncmp(p, "U+", 2) == 0)
+ p += 2;
+
+ *vp = strtoul(p, &end, 16);
+ if (end == p) {
+ INFO(("idn__filemapper_create: UCS code point expected\n"));
+ return (NULL);
+ }
+ p = end;
+
+ /* Skip trailing space */
+ while (isspace((unsigned char)*p))
+ p++;
+ return p;
+}
+
+idn_result_t
+idn__filemapper_createproc(const char *parameter, void **ctxp) {
+ return idn__filemapper_create(parameter, (idn__filemapper_t *)ctxp);
+}
+
+void
+idn__filemapper_destroyproc(void *ctxp) {
+ idn__filemapper_destroy((idn__filemapper_t)ctxp);
+}
+
+idn_result_t
+idn__filemapper_mapproc(void *ctx, const unsigned long *from,
+ unsigned long *to, size_t tolen) {
+ return idn__filemapper_map((idn__filemapper_t)ctx, from, to, tolen);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/idn.conf.sample.in b/contrib/idn/idnkit-1.0-src/lib/idn.conf.sample.in
new file mode 100644
index 0000000..ac771a8
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/idn.conf.sample.in
@@ -0,0 +1,61 @@
+# $Id: idn.conf.sample.in,v 1.1.1.1 2003/06/04 00:26:45 marka Exp $
+#
+# Sample file for idnkit configuration file (idn.conf).
+#
+
+#
+# `idn-encoding' entry specifies the encoding name used as the encoding
+# of multilingualized names by resolvers and DNS servers. Currently, the
+# following encodings are available:
+#
+# Punycode
+# UTF-8
+# <codeset names your iconv_open() accepts>
+#
+# If you enabled extra ace feature, following IDN encoding can be used.
+#
+# AMC-ACE-Z (old name of Punycode)
+# RACE
+#
+# syntax)
+# idn-encoding <encoding>
+#
+idn-encoding Punycode
+
+#
+# `nameprep' entry specifies the version of NAMEPREP.
+# idnkit currently supports the following version:
+#
+# RFC3491 -- name preparation scheme described in the
+# RFC3491
+#
+# syntax)
+# nameprep <nameprep version>
+#
+nameprep RFC3491
+
+#
+# `local-map' entry specifies TLD (top level domain) based local mapping
+# schemes, which is performed before NAMEPREP. Available schemes are:
+#
+# <nameprep version> -- nameprep version
+# filemap:<pathname> -- read mapping rules from a file
+#
+# syntax)
+# local-map <tld> <scheme> ...
+#
+# If the TLD of the domain name matches <tld>, local mapping specified
+# by <scheme> is performed on the name. Otherwise no mapping are
+# performed. Multiple schemes can be specified; they are applied in
+# turn.
+#
+# There are two special <tld>s for specifying a default mapping rule
+# and a mapping rule for local names (domain names containing no
+# dots). If <tld> is `.', its schemes are applied to domain names
+# whose TLD does not match any TLDs specified in local-map entries.
+# If <tld> is `-', its schemes are applied to domain names which
+# contain no dots.
+#
+#local-map - filemap:/some/where/local.map
+#local-map . filemap:/some/where/default.map
+local-map .jp filemap:@mapdir@/jp.map
diff --git a/contrib/idn/idnkit-1.0-src/lib/localencoding.c b/contrib/idn/idnkit-1.0-src/lib/localencoding.c
new file mode 100644
index 0000000..ae937ea
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/localencoding.c
@@ -0,0 +1,123 @@
+#ifndef lint
+static char *rcsid = "$Id: localencoding.c,v 1.1.1.1 2003/06/04 00:25:53 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#ifdef HAVE_LANGINFO_H
+#include <langinfo.h>
+#endif
+
+#include <idn/logmacro.h>
+#include <idn/localencoding.h>
+#include <idn/debug.h>
+
+#ifdef ENABLE_MDNKIT_COMPAT
+#include <mdn/localencoding.h>
+#endif
+
+const char *
+idn_localencoding_name(void) {
+ char *name;
+
+ TRACE(("idn_localencoding_name()\n"));
+
+ if ((name = getenv(IDN_LOCALCS_ENV)) != NULL) {
+ TRACE(("local encoding=\"%-.30s\"\n",
+ name == NULL ? "<null>" : name));
+ return (name);
+ }
+#ifdef ENABLE_MDNKIT_COMPAT
+ if ((name = getenv(MDN_LOCALCS_ENV)) != NULL) {
+ TRACE(("local encoding=\"%-.30s\"\n",
+ name == NULL ? "<null>" : name));
+ return (name);
+ }
+#endif
+
+#ifdef WIN32
+ {
+ static char cp_str[40]; /* enough */
+ (void)sprintf(cp_str, "CP%u", GetACP());
+ TRACE(("local encoding(codepage)=\"%-.30s\"\n", cp_str));
+ return (cp_str);
+ }
+#else /* WIN32 */
+#ifdef HAVE_LIBCHARSET
+ name = locale_charset();
+ TRACE(("local encoding=\"%-.30s\"\n",
+ name == NULL ? "<null>" : name));
+ return (name);
+#endif
+
+#if defined(HAVE_NL_LANGINFO) && defined(CODESET)
+ if ((name = nl_langinfo(CODESET)) != NULL) {
+ TRACE(("local encoding=\"%-.30s\"\n",
+ name == NULL ? "<null>" : name));
+ return (name);
+ }
+#endif
+ (void)(
+#ifdef HAVE_SETLOCALE
+ (name = setlocale(LC_CTYPE, NULL)) ||
+#endif
+ (name = getenv("LC_ALL")) ||
+ (name = getenv("LC_CTYPE")) ||
+ (name = getenv("LANG")));
+ TRACE(("local encoding=\"%-.30s\"\n", name == NULL ? "<null>" : name));
+ return (name);
+#endif /* WIN32 */
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/log.c b/contrib/idn/idnkit-1.0-src/lib/log.c
new file mode 100644
index 0000000..92ba9c9
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/log.c
@@ -0,0 +1,215 @@
+#ifndef lint
+static char *rcsid = "$Id: log.c,v 1.1.1.1 2003/06/04 00:25:53 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <idn/log.h>
+
+#define LOGLEVEL_ENV "IDN_LOG_LEVEL"
+
+#ifdef DEBUG
+#define DEFAULT_LOG_LEVEL idn_log_level_info
+#else
+#define DEFAULT_LOG_LEVEL idn_log_level_error
+#endif
+
+static int log_level = -1;
+static idn_log_proc_t log_proc;
+
+static void initialize(void);
+static void log(int level, const char *fmt, va_list args);
+static void log_to_stderr(int level, const char *buf);
+
+void
+idn_log_fatal(const char *fmt, ...) {
+ va_list args;
+
+ va_start(args, fmt);
+ log(idn_log_level_fatal, fmt, args);
+ va_end(args);
+ exit(1);
+}
+
+void
+idn_log_error(const char *fmt, ...) {
+ va_list args;
+
+ va_start(args, fmt);
+ log(idn_log_level_error, fmt, args);
+ va_end(args);
+}
+
+void
+idn_log_warning(const char *fmt, ...) {
+ va_list args;
+
+ va_start(args, fmt);
+ log(idn_log_level_warning, fmt, args);
+ va_end(args);
+}
+
+void
+idn_log_info(const char *fmt, ...) {
+ va_list args;
+
+ va_start(args, fmt);
+ log(idn_log_level_info, fmt, args);
+ va_end(args);
+}
+
+void
+idn_log_trace(const char *fmt, ...) {
+ va_list args;
+
+ va_start(args, fmt);
+ log(idn_log_level_trace, fmt, args);
+ va_end(args);
+}
+
+void
+idn_log_dump(const char *fmt, ...) {
+ va_list args;
+
+ va_start(args, fmt);
+ log(idn_log_level_dump, fmt, args);
+ va_end(args);
+}
+
+void
+idn_log_setlevel(int level) {
+ if (level >= 0)
+ log_level = level;
+}
+
+int
+idn_log_getlevel(void) {
+ if (log_level < 0)
+ initialize();
+ return log_level;
+}
+
+void
+idn_log_setproc(idn_log_proc_t proc) {
+ if (proc == NULL)
+ log_proc = log_to_stderr;
+ else
+ log_proc = proc;
+}
+
+static void
+initialize(void) {
+ char *s;
+
+ if (log_level < 0) {
+ if ((s = getenv(LOGLEVEL_ENV)) != NULL) {
+ int level = atoi(s);
+ if (level >= 0)
+ log_level = level;
+ }
+ if (log_level < 0)
+ log_level = DEFAULT_LOG_LEVEL;
+ }
+
+ if (log_proc == NULL)
+ log_proc = log_to_stderr;
+}
+
+static void
+log(int level, const char *fmt, va_list args) {
+ char buf[1024];
+
+ initialize();
+
+ if (log_level < level)
+ return;
+
+#if HAVE_VSNPRINTF
+ (void)vsnprintf(buf, sizeof(buf), fmt, args);
+#else
+ /* Let's hope 1024 is enough.. */
+ (void)vsprintf(buf, fmt, args);
+#endif
+ (*log_proc)(level, buf);
+}
+
+static void
+log_to_stderr(int level, const char *buf) {
+ char *title;
+ char tmp[20];
+
+ switch (level) {
+ case idn_log_level_fatal:
+ title = "FATAL";
+ break;
+ case idn_log_level_error:
+ title = "ERROR";
+ break;
+ case idn_log_level_warning:
+ title = "WARNING";
+ break;
+ case idn_log_level_info:
+ title = "INFO";
+ break;
+ case idn_log_level_trace:
+ title = "TRACE";
+ break;
+ case idn_log_level_dump:
+ title = "DUMP";
+ break;
+ default:
+ (void)sprintf(tmp, "LEVEL%d", level);
+ title = tmp;
+ break;
+ }
+ fprintf(stderr, "%u: [%s] %s", (unsigned int)getpid(), title, buf);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/make.wnt b/contrib/idn/idnkit-1.0-src/lib/make.wnt
new file mode 100644
index 0000000..9d80dcf
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/make.wnt
@@ -0,0 +1,279 @@
+# $Id: make.wnt,v 1.1.1.1 2003/06/04 00:25:54 marka Exp $
+# Makefile for MDN library, manually configured for WIN-NT (VC5.0)
+#
+# Copyright (c) 2000,2002 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+!include <ntwin32.mak>
+
+INCDIR = ..\include
+ICONVDIR = ..\win
+LIBS = $(ICONVDIR)\iconv.lib
+LIBS_LITE =
+SYSLIBS = $(conlibsdll)
+
+#
+# Files to build MDN library
+#
+
+HDRS_LITE = \
+ $(INCDIR)\config.h \
+ $(INCDIR)\idn\aliaslist.h \
+ $(INCDIR)\idn\api.h \
+ $(INCDIR)\idn\assert.h \
+ $(INCDIR)\idn\checker.h \
+ $(INCDIR)\idn\converter.h \
+ $(INCDIR)\idn\debug.h \
+ $(INCDIR)\idn\delimitermap.h \
+ $(INCDIR)\idn\export.h \
+ $(INCDIR)\idn\filechecker.h \
+ $(INCDIR)\idn\filemapper.h \
+ $(INCDIR)\idn\localencoding.h \
+ $(INCDIR)\idn\log.h \
+ $(INCDIR)\idn\logmacro.h \
+ $(INCDIR)\idn\mapper.h \
+ $(INCDIR)\idn\mapselector.h \
+ $(INCDIR)\idn\nameprep.h \
+ $(INCDIR)\idn\normalizer.h \
+ $(INCDIR)\idn\punycode.h \
+ $(INCDIR)\idn\race.h \
+ $(INCDIR)\idn\res.h \
+ $(INCDIR)\idn\resconf.h \
+ $(INCDIR)\idn\result.h \
+ $(INCDIR)\idn\strhash.h \
+ $(INCDIR)\idn\ucs4.h \
+ $(INCDIR)\idn\ucsmap.h \
+ $(INCDIR)\idn\ucsset.h \
+ $(INCDIR)\idn\unicode.h \
+ $(INCDIR)\idn\unormalize.h \
+ $(INCDIR)\idn\utf8.h \
+ $(INCDIR)\idn\util.h \
+ $(INCDIR)\idn\version.h
+
+HDRS = $(ICONVDIR)\iconv.h \
+ $(HDRS_LITE)
+
+SRCS = aliaslist.c api.c checker.c \
+ converter.c debug.c delimitermap.c \
+ filechecker.c filemapper.c \
+ localencoding.c log.c mapper.c \
+ mapselector.c nameprep.c nameprep_template.c \
+ nameprepdata.c normalizer.c punycode.c race.c \
+ res.c resconf.c result.c \
+ strhash.c ucs4.c ucsmap.c \
+ ucsset.c unicode.c unicode_template.c \
+ unicodedata_320.c unormalize.c \
+ utf8.c util.c version.c
+
+OBJS = aliaslist.obj api.obj checker.obj \
+ converter.obj debug.obj delimitermap.obj \
+ filechecker.obj filemapper.obj \
+ localencoding.obj log.obj mapper.obj \
+ mapselector.obj nameprep.obj \
+ normalizer.obj punycode.obj race.obj \
+ res.obj resconf.obj result.obj \
+ strhash.obj ucs4.obj ucsmap.obj \
+ ucsset.obj unicode.obj \
+ unormalize.obj \
+ utf8.obj util.obj version.obj
+
+OBJS_LITE = \
+ aliaslist_l.obj api_l.obj checker_l.obj \
+ converter_l.obj debug_l.obj delimitermap_l.obj \
+ filechecker_l.obj filemapper_l.obj \
+ localencoding_l.obj log_l.obj mapper_l.obj \
+ mapselector_l.obj nameprep_l.obj \
+ normalizer_l.obj punycode_l.obj race_l.obj \
+ res_l.obj resconf_l.obj result_l.obj \
+ strhash_l.obj ucs4_l.obj ucsmap_l.obj \
+ ucsset_l.obj unicode_l.obj \
+ unormalize_l.obj \
+ utf8_l.obj util_l.obj version_l.obj
+
+
+#DBG = -DDEBUG
+
+#
+# Target to build
+#
+
+TARGETS = idnkit.dll idnkitlite.dll
+
+all: $(TARGETS)
+
+idnkit.dll: $(OBJS)
+ -del idnkit.dll
+ $(link) /out:"idnkit.dll" /implib:"idnkit.lib" $(dlllflags) $(OBJS) $(LIBS) $(SYSLIBS)
+
+idnkitlite.dll: $(OBJS_LITE)
+ -del idnkitlite.dll
+ $(link) /out:"idnkitlite.dll" /implib:"idnkitlite.lib" $(dlllflags) $(OBJS_LITE) $(LIBS_LITE) $(SYSLIBS)
+
+install:
+
+clean:
+ -del *.obj
+ -del *.lib
+ -del *.dll
+ -del *.exp
+
+#
+# Dependencies
+#
+
+EXP = -DIDN_EXPORT="extern __declspec(dllexport)"
+CCARGS = $(cflags) $(cvarsdll) -I$(INCDIR) -I$(ICONVDIR) $(EXP) $(DBG)
+CCARGS_LITE = $(cflags) $(cvarsdll) -I$(INCDIR) -DWITHOUT_ICONV $(EXP) $(DBG)
+
+aliaslist.obj: aliaslist.c $(HDRS)
+ $(cc) $(CCARGS) /Foaliaslist.obj aliaslist.c
+api.obj: api.c $(HDRS)
+ $(cc) $(CCARGS) /Foapi.obj api.c
+checker.obj: checker.c $(HDRS)
+ $(cc) $(CCARGS) /Fochecker.obj checker.c
+converter.obj: converter.c $(HDRS)
+ $(cc) $(CCARGS) /Foconverter.obj converter.c
+debug.obj: debug.c $(HDRS)
+ $(cc) $(CCARGS) /Fodebug.obj debug.c
+delimitermap.obj: delimitermap.c $(HDRS)
+ $(cc) $(CCARGS) /Fodelimitermap.obj delimitermap.c
+filechecker.obj: filechecker.c $(HDRS)
+ $(cc) $(CCARGS) /Fofilechecker.obj filechecker.c
+filemapper.obj: filemapper.c $(HDRS)
+ $(cc) $(CCARGS) /Fofilemapper.obj filemapper.c
+localencoding.obj: localencoding.c $(HDRS)
+ $(cc) $(CCARGS) /Folocalencoding.obj localencoding.c
+log.obj: log.c $(HDRS)
+ $(cc) $(CCARGS) /Folog.obj log.c
+mapper.obj: mapper.c $(HDRS)
+ $(cc) $(CCARGS) /Fomapper.obj mapper.c
+mapselector.obj: mapselector.c $(HDRS)
+ $(cc) $(CCARGS) /Fomapselector.obj mapselector.c
+nameprep.obj: nameprep.c nameprepdata.c nameprep_template.c $(HDRS)
+ $(cc) $(CCARGS) /Fonameprep.obj nameprep.c
+normalizer.obj: normalizer.c $(HDRS)
+ $(cc) $(CCARGS) /Fonormalizer.obj normalizer.c
+punycode.obj: punycode.c $(HDRS)
+ $(cc) $(CCARGS) /Fopunycode.obj punycode.c
+race.obj: race.c $(HDRS)
+ $(cc) $(CCARGS) /Forace.obj race.c
+res.obj: res.c $(HDRS)
+ $(cc) $(CCARGS) /Fores.obj res.c
+resconf.obj: resconf.c $(HDRS)
+ $(cc) $(CCARGS) /Foresconf.obj resconf.c
+result.obj: result.c $(HDRS)
+ $(cc) $(CCARGS) /Foresult.obj result.c
+strhash.obj: strhash.c $(HDRS)
+ $(cc) $(CCARGS) /Fostrhash.obj strhash.c
+ucs4.obj: ucs4.c $(HDRS)
+ $(cc) $(CCARGS) /Foucs4.obj ucs4.c
+ucsmap.obj: ucsmap.c $(HDRS)
+ $(cc) $(CCARGS) /Foucsmap.obj ucsmap.c
+ucsset.obj: ucsset.c $(HDRS)
+ $(cc) $(CCARGS) /Foucsset.obj ucsset.c
+unicode.obj: unicode.c unicodedata_320.c unicode_template.c $(HDRS)
+ $(cc) $(CCARGS) /Founicode.obj unicode.c
+unormalize.obj: unormalize.c $(HDRS)
+ $(cc) $(CCARGS) /Founormalize.obj unormalize.c
+utf8.obj: utf8.c $(HDRS)
+ $(cc) $(CCARGS) /Foutf8.obj utf8.c
+util.obj: util.c $(HDRS)
+ $(cc) $(CCARGS) /Foutil.obj util.c
+version.obj: version.c $(HDRS)
+ $(cc) $(CCARGS) /Foversion.obj version.c
+
+aliaslist_l.obj: aliaslist.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foaliaslist_l.obj aliaslist.c
+api_l.obj: api.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foapi_l.obj api.c
+checker_l.obj: checker.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fochecker_l.obj checker.c
+converter_l.obj: converter.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foconverter_l.obj converter.c
+debug_l.obj: debug.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fodebug_l.obj debug.c
+delimitermap_l.obj: delimitermap.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fodelimitermap_l.obj delimitermap.c
+dude_l.obj: dude.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fodude_l.obj dude.c
+filechecker_l.obj: filechecker.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fofilechecker_l.obj filechecker.c
+filemapper_l.obj: filemapper.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fofilemapper_l.obj filemapper.c
+localencoding_l.obj: localencoding.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Folocalencoding_l.obj localencoding.c
+log_l.obj: log.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Folog_l.obj log.c
+mapper_l.obj: mapper.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fomapper_l.obj mapper.c
+mapselector_l.obj: mapselector.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fomapselector_l.obj mapselector.c
+nameprep_l.obj: nameprep.c nameprepdata.c nameprep_template.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fonameprep_l.obj nameprep.c
+normalizer_l.obj: normalizer.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fonormalizer_l.obj normalizer.c
+punycode_l.obj: punycode.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fopunycode_l.obj punycode.c
+race_l.obj: race.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Forace_l.obj race.c
+res_l.obj: res.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fores_l.obj res.c
+resconf_l.obj: resconf.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foresconf_l.obj resconf.c
+result_l.obj: result.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foresult_l.obj result.c
+strhash_l.obj: strhash.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Fostrhash_l.obj strhash.c
+ucs4_l.obj: ucs4.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foucs4_l.obj ucs4.c
+ucsmap_l.obj: ucsmap.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foucsmap_l.obj ucsmap.c
+ucsset_l.obj: ucsset.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foucsset_l.obj ucsset.c
+unicode_l.obj: unicode.c unicodedata_320.c unicode_template.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Founicode_l.obj unicode.c
+unormalize_l.obj: unormalize.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Founormalize_l.obj unormalize.c
+utf8_l.obj: utf8.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foutf8_l.obj utf8.c
+util_l.obj: util.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foutil_l.obj util.c
+version_l.obj: version.c $(HDRS_LITE)
+ $(cc) $(CCARGS_LITE) /Foversion_l.obj version.c
diff --git a/contrib/idn/idnkit-1.0-src/lib/mapper.c b/contrib/idn/idnkit-1.0-src/lib/mapper.c
new file mode 100644
index 0000000..008f027
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/mapper.c
@@ -0,0 +1,482 @@
+#ifndef lint
+static char *rcsid = "$Id: mapper.c,v 1.1.1.1 2003/06/04 00:25:55 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/mapper.h>
+#include <idn/strhash.h>
+#include <idn/debug.h>
+#include <idn/util.h>
+#include <idn/ucs4.h>
+
+/*
+ * Type for mapping scheme.
+ */
+typedef struct {
+ char *prefix;
+ char *parameter;
+ idn_mapper_createproc_t create;
+ idn_mapper_destroyproc_t destroy;
+ idn_mapper_mapproc_t map;
+ void *context;
+} map_scheme_t;
+
+/*
+ * Standard mapping schemes.
+ */
+static const map_scheme_t nameprep_scheme = {
+ "RFC3491",
+ NULL,
+ idn_nameprep_createproc,
+ idn_nameprep_destroyproc,
+ idn_nameprep_mapproc,
+ NULL,
+};
+
+static const map_scheme_t filemap_scheme = {
+ "filemap",
+ "",
+ idn__filemapper_createproc,
+ idn__filemapper_destroyproc,
+ idn__filemapper_mapproc,
+ NULL,
+};
+
+static const map_scheme_t *standard_map_schemes[] = {
+ &nameprep_scheme,
+ &filemap_scheme,
+ NULL,
+};
+
+/*
+ * Hash table for mapping schemes.
+ */
+static idn__strhash_t scheme_hash = NULL;
+
+/*
+ * Mapper object type.
+ */
+struct idn_mapper {
+ int nschemes;
+ int scheme_size;
+ map_scheme_t *schemes;
+ int reference_count;
+};
+
+#define MAPPER_INITIAL_SCHEME_SIZE 1
+
+idn_result_t
+idn_mapper_initialize(void) {
+ idn_result_t r;
+ map_scheme_t **scheme;
+
+ TRACE(("idn_mapper_initialize()\n"));
+
+ if (scheme_hash != NULL) {
+ r = idn_success; /* already initialized */
+ goto ret;
+ }
+
+ r = idn__strhash_create(&scheme_hash);
+ if (r != idn_success)
+ goto ret;
+
+ for (scheme = (map_scheme_t **)standard_map_schemes;
+ *scheme != NULL; scheme++) {
+ r = idn__strhash_put(scheme_hash, (*scheme)->prefix, *scheme);
+ if (r != idn_success)
+ goto ret;
+ }
+
+ r = idn_success;
+ret:
+ if (r != idn_success && scheme_hash != NULL) {
+ idn__strhash_destroy(scheme_hash, NULL);
+ scheme_hash = NULL;
+ }
+ TRACE(("idn_mapper_initialize(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_mapper_create(idn_mapper_t *ctxp) {
+ idn_mapper_t ctx = NULL;
+ idn_result_t r;
+
+ assert(scheme_hash != NULL);
+ assert(ctxp != NULL);
+
+ TRACE(("idn_mapper_create()\n"));
+
+ ctx = (idn_mapper_t) malloc(sizeof(struct idn_mapper));
+ if (ctx == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ ctx->schemes = (map_scheme_t *) malloc(sizeof(map_scheme_t)
+ * MAPPER_INITIAL_SCHEME_SIZE);
+ if (ctx->schemes == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ ctx->nschemes = 0;
+ ctx->scheme_size = MAPPER_INITIAL_SCHEME_SIZE;
+ ctx->reference_count = 1;
+ *ctxp = ctx;
+ r = idn_success;
+
+ret:
+ if (r != idn_success) {
+ if (ctx != NULL)
+ free(ctx->schemes);
+ free(ctx);
+ }
+ TRACE(("idn_mapper_create(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+void
+idn_mapper_destroy(idn_mapper_t ctx) {
+ int i;
+
+ assert(scheme_hash != NULL);
+ assert(ctx != NULL);
+
+ TRACE(("idn_mapper_destroy()\n"));
+
+ ctx->reference_count--;
+ if (ctx->reference_count <= 0) {
+ TRACE(("idn_mapper_destroy(): the object is destroyed\n"));
+ for (i = 0; i < ctx->nschemes; i++)
+ ctx->schemes[i].destroy(ctx->schemes[i].context);
+ free(ctx->schemes);
+ free(ctx);
+ } else {
+ TRACE(("idn_mapper_destroy(): "
+ "update reference count (%d->%d)\n",
+ ctx->reference_count + 1, ctx->reference_count));
+ }
+}
+
+void
+idn_mapper_incrref(idn_mapper_t ctx) {
+ assert(ctx != NULL && scheme_hash != NULL);
+
+ TRACE(("idn_mapper_incrref()\n"));
+ TRACE(("idn_mapper_incrref: update reference count (%d->%d)\n",
+ ctx->reference_count, ctx->reference_count + 1));
+
+ ctx->reference_count++;
+}
+
+idn_result_t
+idn_mapper_add(idn_mapper_t ctx, const char *scheme_name) {
+ idn_result_t r;
+ map_scheme_t *scheme;
+ const char *scheme_prefix;
+ const char *scheme_parameter;
+ void *scheme_context = NULL;
+ char static_buffer[128]; /* large enough */
+ char *buffer = static_buffer;
+
+ assert(scheme_hash != NULL);
+ assert(ctx != NULL);
+
+ TRACE(("idn_mapper_add(scheme_name=%s)\n",
+ idn__debug_xstring(scheme_name, 50)));
+
+ /*
+ * Split `scheme_name' into `scheme_prefix' and `scheme_parameter'.
+ */
+ scheme_parameter = strchr(scheme_name, ':');
+ if (scheme_parameter == NULL) {
+ scheme_prefix = scheme_name;
+ } else {
+ ptrdiff_t scheme_prefixlen;
+
+ scheme_prefixlen = scheme_parameter - scheme_name;
+ if (scheme_prefixlen + 1 > sizeof(static_buffer)) {
+ buffer = (char *) malloc(scheme_prefixlen + 1);
+ if (buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ }
+ memcpy(buffer, scheme_name, scheme_prefixlen);
+ *(buffer + scheme_prefixlen) = '\0';
+ scheme_prefix = buffer;
+ scheme_parameter++;
+ }
+
+ /*
+ * Find a scheme.
+ */
+ if (idn__strhash_get(scheme_hash, scheme_prefix, (void **)&scheme)
+ != idn_success) {
+ ERROR(("idn_mapper_add(): invalid scheme name \"%-.30s\"\n",
+ scheme_prefix));
+ r = idn_invalid_name;
+ goto ret;
+ }
+ if (scheme_parameter == NULL) {
+ if (scheme->parameter != NULL)
+ scheme_parameter = scheme->parameter;
+ else
+ scheme_parameter = scheme->prefix;
+ }
+
+ /*
+ * Add the scheme.
+ */
+ assert(ctx->nschemes <= ctx->scheme_size);
+
+ if (ctx->nschemes == ctx->scheme_size) {
+ map_scheme_t *new_schemes;
+
+ new_schemes = (map_scheme_t *) realloc(ctx->schemes,
+ sizeof(map_scheme_t) * ctx->scheme_size * 2);
+ if (new_schemes == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ ctx->schemes = new_schemes;
+ ctx->scheme_size *= 2;
+ }
+
+ r = scheme->create(scheme_parameter, &scheme_context);
+ if (r != idn_success)
+ goto ret;
+
+ memcpy(ctx->schemes + ctx->nschemes, scheme, sizeof(map_scheme_t));
+ ctx->schemes[ctx->nschemes].context = scheme_context;
+ ctx->nschemes++;
+ r = idn_success;
+ret:
+ if (r != idn_success)
+ free(scheme_context);
+ if (buffer != static_buffer)
+ free(buffer);
+ TRACE(("idn_mapper_add(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_mapper_addall(idn_mapper_t ctx, const char **scheme_names, int nschemes) {
+ idn_result_t r;
+ int i;
+
+ assert(scheme_hash != NULL);
+ assert(ctx != NULL && scheme_names != NULL);
+
+ TRACE(("idn_mapper_addall(nschemes=%d)\n", nschemes));
+
+ for (i = 0; i < nschemes; i++) {
+ r = idn_mapper_add(ctx, (const char *)*scheme_names);
+ if (r != idn_success)
+ goto ret;
+ scheme_names++;
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("idn_mapper_addall(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_mapper_map(idn_mapper_t ctx, const unsigned long *from,
+ unsigned long *to, size_t tolen) {
+ idn_result_t r;
+ unsigned long *src, *dst;
+ unsigned long *buffers[2] = {NULL, NULL};
+ size_t buflen[2] = {0, 0};
+ size_t dstlen;
+ int idx;
+ int i;
+
+ assert(scheme_hash != NULL);
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_mapper_map(from=\"%s\", tolen=%d)\n",
+ idn__debug_ucs4xstring(from, 50), (int)tolen));
+
+ if (ctx->nschemes <= 0) {
+ if (tolen < idn_ucs4_strlen(from) + 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ idn_ucs4_strcpy(to, from);
+ r = idn_success;
+ goto ret;
+ }
+
+ /*
+ * Map.
+ */
+ src = (void *)from;
+ dstlen = idn_ucs4_strlen(from) + 1;
+
+ i = 0;
+ while (i < ctx->nschemes) {
+ TRACE(("idn_mapper_map(): map %s\n", ctx->schemes[i].prefix));
+
+ /*
+ * Choose destination area to restore the result of a mapping.
+ */
+ if (i + 1 == ctx->nschemes) {
+ dst = to;
+ dstlen = tolen;
+
+ } else {
+ if (src == buffers[0])
+ idx = 1;
+ else
+ idx = 0;
+
+ if (buflen[idx] < dstlen) {
+ void *newbuf;
+
+ newbuf = realloc(buffers[idx],
+ sizeof(long) * dstlen);
+ if (newbuf == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ buffers[idx] = (unsigned long *)newbuf;
+ buflen[idx] = dstlen;
+ }
+
+ dst = buffers[idx];
+ dstlen = buflen[idx];
+ }
+
+ /*
+ * Perform i-th map scheme.
+ * If buffer size is not enough, we double it and try again.
+ */
+ r = (ctx->schemes[i].map)(ctx->schemes[i].context, src, dst,
+ dstlen);
+ if (r == idn_buffer_overflow && dst != to) {
+ dstlen *= 2;
+ continue;
+ }
+ if (r != idn_success)
+ goto ret;
+
+ src = dst;
+ i++;
+ }
+
+ r = idn_success;
+ret:
+ free(buffers[0]);
+ free(buffers[1]);
+ if (r == idn_success) {
+ TRACE(("idn_mapper_map(): success (to=\"%s\")\n",
+ idn__debug_ucs4xstring(to, 50)));
+ } else {
+ TRACE(("idn_mapper_map(): %s\n", idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+idn_result_t
+idn_mapper_register(const char *prefix,
+ idn_mapper_createproc_t create,
+ idn_mapper_destroyproc_t destroy,
+ idn_mapper_mapproc_t map) {
+ idn_result_t r;
+ map_scheme_t *scheme = NULL;
+
+ assert(scheme_hash != NULL);
+ assert(prefix != NULL && create != NULL && destroy != NULL &&
+ map != NULL);
+
+ TRACE(("idn_mapper_register(prefix=%s)\n", prefix));
+
+ scheme = (map_scheme_t *) malloc(sizeof(map_scheme_t));
+ if (scheme == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ scheme->prefix = (char *) malloc(strlen(prefix) + 1);
+ if (scheme->prefix == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ strcpy(scheme->prefix, prefix);
+ scheme->parameter = NULL;
+ scheme->create = create;
+ scheme->destroy = destroy;
+ scheme->map = map;
+
+ r = idn__strhash_put(scheme_hash, prefix, scheme);
+ if (r != idn_success)
+ goto ret;
+
+ r = idn_success;
+ret:
+ if (r != idn_success) {
+ if (scheme != NULL)
+ free(scheme->prefix);
+ free(scheme);
+ }
+
+ TRACE(("idn_mapper_register(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/mapselector.c b/contrib/idn/idnkit-1.0-src/lib/mapselector.c
new file mode 100644
index 0000000..0101b98
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/mapselector.c
@@ -0,0 +1,375 @@
+#ifndef lint
+static char *rcsid = "$Id: mapselector.c,v 1.1.1.1 2003/06/04 00:25:56 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/result.h>
+#include <idn/mapselector.h>
+#include <idn/strhash.h>
+#include <idn/debug.h>
+#include <idn/util.h>
+#include <idn/ucs4.h>
+
+struct idn_mapselector {
+ idn__strhash_t maphash;
+ int reference_count;
+};
+
+/*
+ * Maximum length of a top level domain name. (e.g. `com', `jp', ...)
+ */
+#define MAPSELECTOR_MAX_TLD_LENGTH 63
+
+static void string_ascii_tolower(char *string);
+
+
+const unsigned long *
+idn_mapselector_getnotld(void) {
+ static const unsigned long notld[] = {0x002d, 0x0000}; /* "-" */
+ return (notld);
+}
+
+const unsigned long *
+idn_mapselector_getdefaulttld(void) {
+ const static unsigned long defaulttld[] = {0x002e, 0x0000}; /* "." */
+ return (defaulttld);
+}
+
+idn_result_t
+idn_mapselector_initialize(void) {
+ idn_result_t r;
+
+ TRACE(("idn_mapselector_initialize()\n"));
+
+ r = idn_mapper_initialize();
+
+ TRACE(("idn_mapselector_initialize(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_mapselector_create(idn_mapselector_t *ctxp) {
+ idn_mapselector_t ctx = NULL;
+ idn_result_t r;
+
+ assert(ctxp != NULL);
+ TRACE(("idn_mapselector_create()\n"));
+
+ ctx = (idn_mapselector_t)malloc(sizeof(struct idn_mapselector));
+ if (ctx == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ ctx->maphash = NULL;
+ ctx->reference_count = 1;
+
+ r = idn__strhash_create(&(ctx->maphash));
+ if (r != idn_success)
+ goto ret;
+
+ *ctxp = ctx;
+ r = idn_success;
+
+ret:
+ if (r != idn_success) {
+ if (ctx != NULL)
+ free(ctx->maphash);
+ free(ctx);
+ }
+ TRACE(("idn_mapselector_create(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+void
+idn_mapselector_destroy(idn_mapselector_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_mapselector_destroy()\n"));
+
+ ctx->reference_count--;
+ if (ctx->reference_count <= 0) {
+ TRACE(("idn_mapselector_destroy(): "
+ "the object is destroyed\n"));
+ idn__strhash_destroy(ctx->maphash,
+ (idn__strhash_freeproc_t)&idn_mapper_destroy);
+ free(ctx);
+ } else {
+ TRACE(("idn_mapselector_destroy(): "
+ "update reference count (%d->%d)\n",
+ ctx->reference_count + 1, ctx->reference_count));
+ }
+}
+
+void
+idn_mapselector_incrref(idn_mapselector_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_mapselector_incrref()\n"));
+ TRACE(("idn_mapselector_incrref: update reference count (%d->%d)\n",
+ ctx->reference_count, ctx->reference_count + 1));
+
+ ctx->reference_count++;
+}
+
+idn_result_t
+idn_mapselector_add(idn_mapselector_t ctx, const char *tld, const char *name) {
+ idn_result_t r;
+ idn_mapper_t mapper;
+ char hash_key[MAPSELECTOR_MAX_TLD_LENGTH + 1];
+
+ assert(ctx != NULL && tld != NULL);
+
+ TRACE(("idn_mapselector_add(tld=%s, name=%s)\n", tld, name));
+
+ if (!(tld[0] == '.' && tld[1] == '\0')) {
+ if (tld[0] == '.')
+ tld++;
+ if (strchr(tld, '.') != NULL) {
+ ERROR(("idn_mapselector_add: "
+ "invalid TLD \"%-.100s\"\n", tld));
+ r = idn_invalid_name;
+ goto ret;
+ }
+ }
+ if (strlen(tld) > MAPSELECTOR_MAX_TLD_LENGTH) {
+ ERROR(("idn_mapselector_add: "
+ "too long TLD \"%-.100s\"\n", tld));
+ r = idn_invalid_name;
+ goto ret;
+ }
+ strcpy(hash_key, tld);
+ string_ascii_tolower(hash_key);
+
+ if (idn__strhash_get(ctx->maphash, hash_key, (void **)&mapper)
+ != idn_success) {
+ r = idn_mapper_create(&mapper);
+ if (r != idn_success)
+ goto ret;
+
+ r = idn__strhash_put(ctx->maphash, hash_key, mapper);
+ if (r != idn_success)
+ goto ret;
+ }
+
+ r = idn_mapper_add(mapper, name);
+ret:
+ TRACE(("idn_mapselector_add(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_mapselector_addall(idn_mapselector_t ctx, const char *tld,
+ const char **scheme_names, int nschemes) {
+ idn_result_t r;
+ int i;
+
+ assert(ctx != NULL && tld != NULL && scheme_names != NULL);
+
+ TRACE(("idn_mapselector_addall(tld=%s, nschemes=%d)\n",
+ tld, nschemes));
+
+ for (i = 0; i < nschemes; i++) {
+ r = idn_mapselector_add(ctx, tld, (const char *)*scheme_names);
+ if (r != idn_success)
+ goto ret;
+ scheme_names++;
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("idn_mapselector_addall(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_mapper_t
+idn_mapselector_mapper(idn_mapselector_t ctx, const char *tld) {
+ idn_result_t r;
+ idn_mapper_t mapper;
+ char hash_key[MAPSELECTOR_MAX_TLD_LENGTH + 1];
+
+ assert(ctx != NULL && tld != NULL);
+
+ TRACE(("idn_mapselector_mapper(tld=%s)\n", tld));
+
+ if (!(tld[0] == '.' && tld[1] == '\0')) {
+ if (tld[0] == '.')
+ tld++;
+ if (strchr(tld, '.') != NULL)
+ return (NULL);
+ }
+ if (strlen(tld) > MAPSELECTOR_MAX_TLD_LENGTH)
+ return (NULL);
+ strcpy(hash_key, tld);
+ string_ascii_tolower(hash_key);
+
+ mapper = NULL;
+ r = idn__strhash_get(ctx->maphash, hash_key, (void **)&mapper);
+ if (r != idn_success)
+ return (NULL);
+
+ idn_mapper_incrref(mapper);
+
+ return (mapper);
+}
+
+idn_result_t
+idn_mapselector_map(idn_mapselector_t ctx, const unsigned long *from,
+ const char *tld, unsigned long *to, size_t tolen) {
+ idn_result_t r;
+ idn_mapper_t mapper = NULL;
+ char hash_key[MAPSELECTOR_MAX_TLD_LENGTH + 1];
+ size_t fromlen;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_mapselector_map(from=\"%s\", tld=\"%s\", tolen=%d)\n",
+ idn__debug_ucs4xstring(from, 50), idn__debug_xstring(tld, 50),
+ (int)tolen));
+
+ if (!(tld[0] == '.' && tld[1] == '\0')) {
+ if (tld[0] == '.')
+ tld++;
+ if (strchr(tld, '.') != NULL) {
+ r = idn_invalid_name;
+ goto ret;
+ }
+ }
+ if (strlen(tld) > MAPSELECTOR_MAX_TLD_LENGTH) {
+ r = idn_invalid_name;
+ goto ret;
+ }
+ strcpy(hash_key, tld);
+ string_ascii_tolower(hash_key);
+
+ fromlen = idn_ucs4_strlen(from);
+
+ /*
+ * Get mapper for the TLD.
+ */
+ if (idn__strhash_get(ctx->maphash, hash_key, (void **)&mapper)
+ != idn_success) {
+ strcpy(hash_key, IDN_MAPSELECTOR_DEFAULTTLD);
+ idn__strhash_get(ctx->maphash, hash_key, (void **)&mapper);
+ }
+
+ /*
+ * Map.
+ * If default mapper has not been registered, copy the string.
+ */
+ if (mapper == NULL) {
+ TRACE(("idn_mapselector_map(): no mapper\n"));
+ if (fromlen + 1 > tolen) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ memcpy(to, from, (fromlen + 1) * sizeof(*from));
+ } else {
+ TRACE(("idn_mapselector_map(): tld=%s\n", tld));
+ r = idn_mapper_map(mapper, from, to, tolen);
+ if (r != idn_success)
+ goto ret;
+ }
+
+ r = idn_success;
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_mapselector_map(): succcess (to=\"%s\")\n",
+ idn__debug_ucs4xstring(to, 50)));
+ } else {
+ TRACE(("idn_mapselector_map(): %s\n", idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+idn_result_t
+idn_mapselector_map2(idn_mapselector_t ctx, const unsigned long *from,
+ const unsigned long *tld, unsigned long *to,
+ size_t tolen) {
+ char tld_utf8[MAPSELECTOR_MAX_TLD_LENGTH + 1];
+ idn_result_t r;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_mapselector_map2(from=\"%s\", tld=\"%s\")\n",
+ idn__debug_ucs4xstring(from, 50),
+ idn__debug_ucs4xstring(tld, 50)));
+
+ r = idn_ucs4_ucs4toutf8(tld, tld_utf8, sizeof(tld_utf8));
+ if (r == idn_buffer_overflow) {
+ r = idn_invalid_name;
+ goto ret;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+
+ r = idn_mapselector_map(ctx, from, tld_utf8, to, tolen);
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_mapselector_map2(): success (to=\"%s\")\n",
+ idn__debug_ucs4xstring(to, 50)));
+ } else {
+ TRACE(("idn_mapselector_map2(): %s\n", idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+static void
+string_ascii_tolower(char *string) {
+ unsigned char *p;
+
+ for (p = (unsigned char *) string; *p != '\0'; p++) {
+ if ('A' <= *p && *p <= 'Z')
+ *p = *p - 'A' + 'a';
+ }
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/nameprep.c b/contrib/idn/idnkit-1.0-src/lib/nameprep.c
new file mode 100644
index 0000000..bf08a0d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/nameprep.c
@@ -0,0 +1,357 @@
+#ifndef lint
+static char *rcsid = "$Id: nameprep.c,v 1.1.1.1 2003/06/04 00:25:56 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/log.h>
+#include <idn/logmacro.h>
+#include <idn/debug.h>
+#include <idn/nameprep.h>
+
+#define UCS_MAX 0x7fffffff
+#define UNICODE_MAX 0x10ffff
+
+
+/*
+ * Load NAMEPREP compiled tables.
+ */
+#include "nameprepdata.c"
+
+/*
+ * Define mapping/checking functions for each version of the draft.
+ */
+
+#define VERSION rfc3491
+#include "nameprep_template.c"
+#undef VERSION
+
+typedef const char *(*nameprep_mapproc)(unsigned long v);
+typedef int (*nameprep_checkproc)(unsigned long v);
+typedef idn_biditype_t (*nameprep_biditypeproc)(unsigned long v);
+
+static struct idn_nameprep {
+ char *version;
+ nameprep_mapproc map_proc;
+ nameprep_checkproc prohibited_proc;
+ nameprep_checkproc unassigned_proc;
+ nameprep_biditypeproc biditype_proc;
+} nameprep_versions[] = {
+#define MAKE_NAMEPREP_HANDLE(version, id) \
+ { version, \
+ compose_sym2(nameprep_map_, id), \
+ compose_sym2(nameprep_prohibited_, id), \
+ compose_sym2(nameprep_unassigned_, id), \
+ compose_sym2(nameprep_biditype_, id), }
+ MAKE_NAMEPREP_HANDLE("RFC3491", rfc3491),
+ { NULL, NULL, NULL },
+};
+
+static idn_result_t idn_nameprep_check(nameprep_checkproc proc,
+ const unsigned long *str,
+ const unsigned long **found);
+
+idn_result_t
+idn_nameprep_create(const char *version, idn_nameprep_t *handlep) {
+ idn_nameprep_t handle;
+
+ assert(handlep != NULL);
+
+ TRACE(("idn_nameprep_create(version=%-.50s)\n",
+ version == NULL ? "<NULL>" : version));
+
+ if (version == NULL)
+ version = IDN_NAMEPREP_CURRENT;
+
+ /*
+ * Lookup table for the specified version. Since the number of
+ * versions won't be large (I don't want see draft-23 or such :-),
+ * simple linear search is OK.
+ */
+ for (handle = nameprep_versions; handle->version != NULL; handle++) {
+ if (strcmp(handle->version, version) == 0) {
+ *handlep = handle;
+ return (idn_success);
+ }
+ }
+ return (idn_notfound);
+}
+
+void
+idn_nameprep_destroy(idn_nameprep_t handle) {
+ assert(handle != NULL);
+
+ TRACE(("idn_nameprep_destroy()\n"));
+
+ /* Nothing to do. */
+}
+
+idn_result_t
+idn_nameprep_map(idn_nameprep_t handle, const unsigned long *from,
+ unsigned long *to, size_t tolen) {
+ assert(handle != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_nameprep_map(ctx=%s, from=\"%s\")\n",
+ handle->version, idn__debug_ucs4xstring(from, 50)));
+
+ while (*from != '\0') {
+ unsigned long v = *from;
+ const char *mapped;
+
+ if (v > UCS_MAX) {
+ /* This cannot happen, but just in case.. */
+ return (idn_invalid_codepoint);
+ } else if (v > UNICODE_MAX) {
+ /* No mapping is possible. */
+ mapped = NULL;
+ } else {
+ /* Try mapping. */
+ mapped = (*handle->map_proc)(v);
+ }
+
+ if (mapped == NULL) {
+ /* No mapping. Just copy verbatim. */
+ if (tolen < 1)
+ return (idn_buffer_overflow);
+ *to++ = v;
+ tolen--;
+ } else {
+ const unsigned char *mappeddata;
+ size_t mappedlen;
+
+ mappeddata = (const unsigned char *)mapped + 1;
+ mappedlen = *mapped;
+
+ if (tolen < (mappedlen + 3) / 4)
+ return (idn_buffer_overflow);
+ tolen -= (mappedlen + 3) / 4;
+ while (mappedlen >= 4) {
+ *to = *mappeddata++;
+ *to |= *mappeddata++ << 8;
+ *to |= *mappeddata++ << 16;
+ *to |= *mappeddata++ << 24;
+ mappedlen -= 4;
+ to++;
+ }
+ if (mappedlen > 0) {
+ *to = *mappeddata++;
+ *to |= (mappedlen >= 2) ?
+ *mappeddata++ << 8: 0;
+ *to |= (mappedlen >= 3) ?
+ *mappeddata++ << 16: 0;
+ to++;
+ }
+ }
+ from++;
+ }
+ if (tolen == 0)
+ return (idn_buffer_overflow);
+ *to = '\0';
+ return (idn_success);
+}
+
+idn_result_t
+idn_nameprep_isprohibited(idn_nameprep_t handle, const unsigned long *str,
+ const unsigned long **found) {
+ assert(handle != NULL && str != NULL && found != NULL);
+
+ TRACE(("idn_nameprep_isprohibited(ctx=%s, str=\"%s\")\n",
+ handle->version, idn__debug_ucs4xstring(str, 50)));
+
+ return (idn_nameprep_check(handle->prohibited_proc, str, found));
+}
+
+idn_result_t
+idn_nameprep_isunassigned(idn_nameprep_t handle, const unsigned long *str,
+ const unsigned long **found) {
+ assert(handle != NULL && str != NULL && found != NULL);
+
+ TRACE(("idn_nameprep_isunassigned(handle->version, str=\"%s\")\n",
+ handle->version, idn__debug_ucs4xstring(str, 50)));
+
+ return (idn_nameprep_check(handle->unassigned_proc, str, found));
+}
+
+static idn_result_t
+idn_nameprep_check(nameprep_checkproc proc, const unsigned long *str,
+ const unsigned long **found) {
+ unsigned long v;
+
+ while (*str != '\0') {
+ v = *str;
+
+ if (v > UCS_MAX) {
+ /* This cannot happen, but just in case.. */
+ return (idn_invalid_codepoint);
+ } else if (v > UNICODE_MAX) {
+ /* It is invalid.. */
+ *found = str;
+ return (idn_success);
+ } else if ((*proc)(v)) {
+ *found = str;
+ return (idn_success);
+ }
+ str++;
+ }
+ *found = NULL;
+ return (idn_success);
+}
+
+idn_result_t
+idn_nameprep_isvalidbidi(idn_nameprep_t handle, const unsigned long *str,
+ const unsigned long **found) {
+ unsigned long v;
+ idn_biditype_t first_char;
+ idn_biditype_t last_char;
+ int found_r_al;
+
+ assert(handle != NULL && str != NULL && found != NULL);
+
+ TRACE(("idn_nameprep_isvalidbidi(ctx=%s, str=\"%s\")\n",
+ handle->version, idn__debug_ucs4xstring(str, 50)));
+
+ if (*str == '\0') {
+ *found = NULL;
+ return (idn_success);
+ }
+
+ /*
+ * check first character's type and initialize variables.
+ */
+ found_r_al = 0;
+ if (*str > UCS_MAX) {
+ /* This cannot happen, but just in case.. */
+ return (idn_invalid_codepoint);
+ } else if (*str > UNICODE_MAX) {
+ /* It is invalid.. */
+ *found = str;
+ return (idn_success);
+ }
+ first_char = last_char = (*(handle->biditype_proc))(*str);
+ if (first_char == idn_biditype_r_al) {
+ found_r_al = 1;
+ }
+ str++;
+
+ /*
+ * see whether string is valid or not.
+ */
+ while (*str != '\0') {
+ v = *str;
+
+ if (v > UCS_MAX) {
+ /* This cannot happen, but just in case.. */
+ return (idn_invalid_codepoint);
+ } else if (v > UNICODE_MAX) {
+ /* It is invalid.. */
+ *found = str;
+ return (idn_success);
+ } else {
+ last_char = (*(handle->biditype_proc))(v);
+ if (found_r_al && last_char == idn_biditype_l) {
+ *found = str;
+ return (idn_success);
+ }
+ if (first_char != idn_biditype_r_al && last_char == idn_biditype_r_al) {
+ *found = str;
+ return (idn_success);
+ }
+ if (last_char == idn_biditype_r_al) {
+ found_r_al = 1;
+ }
+ }
+ str++;
+ }
+
+ if (found_r_al) {
+ if (last_char != idn_biditype_r_al) {
+ *found = str - 1;
+ return (idn_success);
+ }
+ }
+
+ *found = NULL;
+ return (idn_success);
+}
+
+idn_result_t
+idn_nameprep_createproc(const char *parameter, void **handlep) {
+ return idn_nameprep_create(parameter, (idn_nameprep_t *)handlep);
+}
+
+void
+idn_nameprep_destroyproc(void *handle) {
+ idn_nameprep_destroy((idn_nameprep_t)handle);
+}
+
+idn_result_t
+idn_nameprep_mapproc(void *handle, const unsigned long *from,
+ unsigned long *to, size_t tolen) {
+ return idn_nameprep_map((idn_nameprep_t)handle, from, to, tolen);
+}
+
+idn_result_t
+idn_nameprep_prohibitproc(void *handle, const unsigned long *str,
+ const unsigned long **found) {
+ return idn_nameprep_isprohibited((idn_nameprep_t)handle, str, found);
+}
+
+idn_result_t
+idn_nameprep_unassignedproc(void *handle, const unsigned long *str,
+ const unsigned long **found) {
+ return idn_nameprep_isunassigned((idn_nameprep_t)handle, str, found);
+}
+
+idn_result_t
+idn_nameprep_bidiproc(void *handle, const unsigned long *str,
+ const unsigned long **found) {
+ return idn_nameprep_isvalidbidi((idn_nameprep_t)handle, str, found);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/nameprep_template.c b/contrib/idn/idnkit-1.0-src/lib/nameprep_template.c
new file mode 100644
index 0000000..4003b16
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/nameprep_template.c
@@ -0,0 +1,137 @@
+/* $Id: nameprep_template.c,v 1.1.1.1 2003/06/04 00:25:57 marka Exp $ */
+
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * Include this file once for each version of NAMEPREP.
+ * VERSION should be defined to appropriate value before inclusion.
+ */
+
+#ifndef NAMEPREP_TEMPLATE_INIT
+#define NAMEPREP_TEMPLATE_INIT
+
+/* Symbol composition. */
+#define compose_sym2(a, b) compose_sym2X(a, b)
+#define compose_sym2X(a, b) a ## b
+#define compose_sym3(a, b, c) compose_sym3X(a, b, c)
+#define compose_sym3X(a, b, c) a ## b ## c
+
+/* Index calculation for multi-level index tables. */
+#define IDX0(type, v) IDX_0(v, BITS1(type), BITS2(type))
+#define IDX1(type, v) IDX_1(v, BITS1(type), BITS2(type))
+#define IDX2(type, v) IDX_2(v, BITS1(type), BITS2(type))
+
+#define IDX_0(v, bits1, bits2) ((v) >> ((bits1) + (bits2)))
+#define IDX_1(v, bits1, bits2) (((v) >> (bits2)) & ((1 << (bits1)) - 1))
+#define IDX_2(v, bits1, bits2) ((v) & ((1 << (bits2)) - 1))
+
+#define BITS1(type) type ## _BITS_1
+#define BITS2(type) type ## _BITS_2
+
+#endif /* NAMEPREP_TEMPLATE_INIT */
+
+static const char *
+compose_sym2(nameprep_map_, VERSION) (unsigned long v) {
+ int idx0 = IDX0(MAP, v);
+ int idx1 = IDX1(MAP, v);
+ int idx2 = IDX2(MAP, v);
+ int offset;
+
+#define IMAP compose_sym3(nameprep_, VERSION, _map_imap)
+#define TABLE compose_sym3(nameprep_, VERSION, _map_table)
+#define DATA compose_sym3(nameprep_, VERSION, _map_data)
+ offset = TABLE[IMAP[IMAP[idx0] + idx1]].tbl[idx2];
+ if (offset == 0)
+ return (NULL); /* no mapping */
+ return (const char *)(DATA + offset);
+#undef IMAP
+#undef TABLE
+#undef DATA
+}
+
+static int
+compose_sym2(nameprep_prohibited_, VERSION) (unsigned long v) {
+ int idx0 = IDX0(PROH, v);
+ int idx1 = IDX1(PROH, v);
+ int idx2 = IDX2(PROH, v);
+ const unsigned char *bm;
+
+#define IMAP compose_sym3(nameprep_, VERSION, _prohibited_imap)
+#define BITMAP compose_sym3(nameprep_, VERSION, _prohibited_bitmap)
+ bm = BITMAP[IMAP[IMAP[idx0] + idx1]].bm;
+ return (bm[idx2 / 8] & (1 << (idx2 % 8)));
+#undef IMAP
+#undef BITMAP
+}
+
+static int
+compose_sym2(nameprep_unassigned_, VERSION) (unsigned long v) {
+ int idx0 = IDX0(UNAS, v);
+ int idx1 = IDX1(UNAS, v);
+ int idx2 = IDX2(UNAS, v);
+ const unsigned char *bm;
+
+#define IMAP compose_sym3(nameprep_, VERSION, _unassigned_imap)
+#define BITMAP compose_sym3(nameprep_, VERSION, _unassigned_bitmap)
+ bm = BITMAP[IMAP[IMAP[idx0] + idx1]].bm;
+ return (bm[idx2 / 8] & (1 << (idx2 % 8)));
+#undef IMAP
+#undef BITMAP
+}
+
+static idn_biditype_t
+compose_sym2(nameprep_biditype_, VERSION) (unsigned long v) {
+ int idx0 = IDX0(BIDI, v);
+ int idx1 = IDX1(BIDI, v);
+ int idx2 = IDX2(BIDI, v);
+ int offset;
+
+#define IMAP compose_sym3(nameprep_, VERSION, _bidi_imap)
+#define TABLE compose_sym3(nameprep_, VERSION, _bidi_table)
+#define DATA compose_sym3(nameprep_, VERSION, _bidi_data)
+ offset = TABLE[IMAP[IMAP[idx0] + idx1]].tbl[idx2];
+ return DATA[offset];
+#undef IMAP
+#undef TABLE
+#undef DATA
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/nameprepdata.c b/contrib/idn/idnkit-1.0-src/lib/nameprepdata.c
new file mode 100644
index 0000000..35adb05
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/nameprepdata.c
@@ -0,0 +1,2546 @@
+/* $Id: nameprepdata.c,v 1.1.1.1 2003/06/04 00:26:05 marka Exp $ */
+/* $-Id: generate_nameprep_data.pl,v 1.9 2002/11/29 09:08:13 ishisone Exp -$ */
+/*
+ * Do not edit this file!
+ * This file is generated from NAMEPREP specification.
+ */
+
+#define MAP_BITS_0 9
+#define MAP_BITS_1 7
+#define MAP_BITS_2 5
+
+#define PROH_BITS_0 7
+#define PROH_BITS_1 7
+#define PROH_BITS_2 7
+
+#define UNAS_BITS_0 7
+#define UNAS_BITS_1 7
+#define UNAS_BITS_2 7
+
+#define BIDI_BITS_0 9
+#define BIDI_BITS_1 7
+#define BIDI_BITS_2 5
+
+static const unsigned short nameprep_rfc3491_map_imap[] = {
+ 272, 400, 528, 656, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 912,
+ 1040, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 1168, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 0, 0, 1, 0, 0, 2, 3, 0,
+ 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 14, 15, 16, 17, 18, 19,
+ 20, 21, 0, 22, 23, 24, 25, 26,
+ 27, 28, 29, 0, 30, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 0, 0, 49, 0, 50, 0, 0,
+ 51, 52, 53, 54, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 55, 56, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 57, 58, 59, 60, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 61, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 63,
+ 0, 64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 65, 66, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 67, 68, 69,
+ 70, 80, 81, 73, 74, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const struct {
+ unsigned short tbl[32];
+} nameprep_rfc3491_map_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42,
+ 44, 46, 48, 50, 52, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77,
+ 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99,
+ 101, 0, 103, 105, 107, 109, 111, 113, 115, 117,
+ }},
+ {{
+ 123, 0, 126, 0, 129, 0, 132, 0, 135, 0, 138,
+ 0, 141, 0, 144, 0, 147, 0, 150, 0, 153, 0,
+ 156, 0, 159, 0, 162, 0, 165, 0, 168, 0,
+ }},
+ {{
+ 171, 0, 174, 0, 177, 0, 180, 0, 183, 0, 186,
+ 0, 189, 0, 192, 0, 195, 0, 202, 0, 205, 0,
+ 208, 0, 0, 211, 0, 214, 0, 217, 0, 220,
+ }},
+ {{
+ 0, 223, 0, 226, 0, 229, 0, 232, 0, 235, 241,
+ 0, 244, 0, 247, 0, 250, 0, 253, 0, 256, 0,
+ 259, 0, 262, 0, 265, 0, 268, 0, 271, 0,
+ }},
+ {{
+ 274, 0, 277, 0, 280, 0, 283, 0, 286, 0, 289,
+ 0, 292, 0, 295, 0, 298, 0, 301, 0, 304, 0,
+ 307, 0, 310, 312, 0, 315, 0, 318, 0, 38,
+ }},
+ {{
+ 0, 321, 324, 0, 327, 0, 330, 333, 0, 336, 339,
+ 342, 0, 0, 345, 348, 351, 354, 0, 357, 360, 0,
+ 363, 366, 369, 0, 0, 0, 372, 375, 0, 378,
+ }},
+ {{
+ 381, 0, 384, 0, 387, 0, 390, 393, 0, 396, 0,
+ 0, 399, 0, 402, 405, 0, 408, 411, 414, 0, 417,
+ 0, 420, 423, 0, 0, 0, 426, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 429, 429, 0, 432, 432, 0, 435,
+ 435, 0, 438, 0, 441, 0, 444, 0, 447, 0, 450,
+ 0, 453, 0, 456, 0, 459, 0, 0, 462, 0,
+ }},
+ {{
+ 465, 0, 468, 0, 471, 0, 474, 0, 477, 0, 480,
+ 0, 483, 0, 486, 0, 489, 496, 496, 0, 499, 0,
+ 502, 505, 508, 0, 511, 0, 514, 0, 517, 0,
+ }},
+ {{
+ 520, 0, 523, 0, 526, 0, 529, 0, 532, 0, 535,
+ 0, 538, 0, 541, 0, 544, 0, 547, 0, 550, 0,
+ 553, 0, 556, 0, 559, 0, 562, 0, 565, 0,
+ }},
+ {{
+ 568, 0, 571, 0, 574, 0, 577, 0, 580, 0, 583,
+ 0, 586, 0, 589, 0, 592, 0, 595, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 598, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 601, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 608, 0, 611, 614, 617,
+ 0, 620, 0, 623, 626, 629, 640, 643, 646, 649, 652,
+ 655, 658, 661, 598, 664, 667, 54, 670, 673, 676,
+ }},
+ {{
+ 679, 682, 0, 685, 688, 691, 694, 697, 700, 703, 706,
+ 709, 0, 0, 0, 0, 712, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 685, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 643, 661, 691, 623, 709, 694,
+ 679, 0, 723, 0, 726, 0, 729, 0, 732, 0,
+ }},
+ {{
+ 735, 0, 738, 0, 741, 0, 744, 0, 747, 0, 750,
+ 0, 753, 0, 756, 0, 664, 682, 685, 0, 661, 652,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 759, 762, 765, 768, 771, 774, 777, 780, 783, 786, 789,
+ 792, 795, 798, 801, 804, 807, 810, 813, 816, 819, 822,
+ 825, 828, 831, 834, 837, 840, 843, 846, 849, 852,
+ }},
+ {{
+ 855, 858, 861, 864, 867, 870, 873, 876, 879, 882, 885,
+ 888, 891, 894, 897, 900, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 903, 0, 906, 0, 909, 0, 912, 0, 915, 0, 918,
+ 0, 921, 0, 924, 0, 927, 0, 930, 0, 933, 0,
+ 936, 0, 939, 0, 942, 0, 945, 0, 948, 0,
+ }},
+ {{
+ 951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 954,
+ 0, 957, 0, 960, 0, 963, 0, 966, 0, 969, 0,
+ 972, 0, 975, 0, 978, 0, 981, 0, 984, 0,
+ }},
+ {{
+ 987, 0, 990, 0, 993, 0, 996, 0, 999, 0, 1002,
+ 0, 1005, 0, 1008, 0, 1011, 0, 1014, 0, 1017, 0,
+ 1020, 0, 1023, 0, 1026, 0, 1029, 0, 1032, 0,
+ }},
+ {{
+ 0, 1035, 0, 1038, 0, 1041, 0, 1044, 0, 1047, 0,
+ 1050, 0, 1053, 0, 0, 1056, 0, 1059, 0, 1062, 0,
+ 1065, 0, 1068, 0, 1071, 0, 1074, 0, 1077, 0,
+ }},
+ {{
+ 1080, 0, 1083, 0, 1086, 0, 1089, 0, 1092, 0, 1095,
+ 0, 1098, 0, 1101, 0, 1104, 0, 1107, 0, 1110, 0,
+ 0, 0, 1113, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1116, 0, 1119, 0, 1122, 0, 1125, 0, 1128, 0, 1131,
+ 0, 1134, 0, 1137, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1140, 1143, 1146, 1149, 1152,
+ 1155, 1158, 1161, 1164, 1167, 1170, 1173, 1176, 1179, 1182,
+ }},
+ {{
+ 1185, 1188, 1191, 1194, 1197, 1200, 1203, 1206, 1209, 1212, 1215,
+ 1218, 1221, 1224, 1227, 1230, 1233, 1236, 1239, 1242, 1245, 1248,
+ 1251, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 1254, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1261, 0, 1264, 0, 1267, 0, 1270, 0, 1273, 0, 1276,
+ 0, 1279, 0, 1282, 0, 1285, 0, 1288, 0, 1291, 0,
+ 1294, 0, 1297, 0, 1300, 0, 1303, 0, 1306, 0,
+ }},
+ {{
+ 1309, 0, 1312, 0, 1315, 0, 1318, 0, 1321, 0, 1324,
+ 0, 1327, 0, 1330, 0, 1333, 0, 1336, 0, 1339, 0,
+ 1342, 0, 1345, 0, 1348, 0, 1351, 0, 1354, 0,
+ }},
+ {{
+ 1357, 0, 1360, 0, 1363, 0, 1366, 0, 1369, 0, 1372,
+ 0, 1375, 0, 1378, 0, 1381, 0, 1384, 0, 1387, 0,
+ 1390, 0, 1393, 0, 1396, 0, 1399, 0, 1402, 0,
+ }},
+ {{
+ 1405, 0, 1408, 0, 1411, 0, 1414, 0, 1417, 0, 1420,
+ 0, 1423, 0, 1426, 0, 1429, 0, 1432, 0, 1435, 0,
+ 1438, 0, 1441, 0, 1444, 0, 1447, 0, 1450, 0,
+ }},
+ {{
+ 1453, 0, 1456, 0, 1459, 0, 1462, 0, 1465, 0, 1468,
+ 0, 1471, 0, 1474, 0, 1477, 0, 1480, 0, 1483, 0,
+ 1486, 1493, 1500, 1507, 1514, 1405, 0, 0, 0, 0,
+ }},
+ {{
+ 1521, 0, 1524, 0, 1527, 0, 1530, 0, 1533, 0, 1536,
+ 0, 1539, 0, 1542, 0, 1545, 0, 1548, 0, 1551, 0,
+ 1554, 0, 1557, 0, 1560, 0, 1563, 0, 1566, 0,
+ }},
+ {{
+ 1569, 0, 1572, 0, 1575, 0, 1578, 0, 1581, 0, 1584,
+ 0, 1587, 0, 1590, 0, 1593, 0, 1596, 0, 1599, 0,
+ 1602, 0, 1605, 0, 1608, 0, 1611, 0, 1614, 0,
+ }},
+ {{
+ 1617, 0, 1620, 0, 1623, 0, 1626, 0, 1629, 0, 1632,
+ 0, 1635, 0, 1638, 0, 1641, 0, 1644, 0, 1647, 0,
+ 1650, 0, 1653, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1656, 1659, 1662,
+ 1665, 1668, 1671, 1674, 1677, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1680, 1683, 1686, 1689, 1692, 1695, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1698, 1701, 1704,
+ 1707, 1710, 1713, 1716, 1719, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1722, 1725, 1728, 1731, 1734, 1737, 1740, 1743,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1746, 1749, 1752,
+ 1755, 1758, 1761, 0, 0, 1764, 0, 1771, 0, 1782, 0,
+ 1793, 0, 0, 1804, 0, 1807, 0, 1810, 0, 1813,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1816, 1819, 1822,
+ 1825, 1828, 1831, 1834, 1837, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1840, 1847, 1854, 1861, 1868, 1875, 1882, 1889, 1840, 1847, 1854,
+ 1861, 1868, 1875, 1882, 1889, 1896, 1903, 1910, 1917, 1924, 1931,
+ 1938, 1945, 1896, 1903, 1910, 1917, 1924, 1931, 1938, 1945,
+ }},
+ {{
+ 1952, 1959, 1966, 1973, 1980, 1987, 1994, 2001, 1952, 1959, 1966,
+ 1973, 1980, 1987, 1994, 2001, 0, 0, 2008, 2015, 2022, 0,
+ 2029, 2036, 2047, 2050, 2053, 2056, 2015, 0, 598, 0,
+ }},
+ {{
+ 0, 0, 2059, 2066, 2073, 0, 2080, 2087, 2098, 2101, 2104,
+ 2107, 2066, 0, 0, 0, 0, 0, 2110, 629, 0, 0,
+ 2121, 2128, 2139, 2142, 2145, 2148, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 2151, 712, 2162, 0, 2169, 2176, 2187, 2190, 2193,
+ 2196, 2199, 0, 0, 0, 0, 0, 2202, 2209, 2216, 0,
+ 2223, 2230, 2241, 2244, 2247, 2250, 2209, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 2253, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 6, 2259, 0, 0, 0, 351, 0, 2265, 0,
+ 16, 16, 16, 0, 0, 18, 18, 24, 0, 0, 28,
+ 2271, 0, 0, 32, 34, 36, 36, 36, 0, 0,
+ }},
+ {{
+ 2277, 2283, 2293, 0, 52, 0, 703, 0, 52, 0, 22,
+ 67, 4, 6, 0, 0, 10, 12, 0, 26, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 646, 679,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2299, 2302, 2305, 2308, 2311, 2314, 2317, 2320, 2323, 2326, 2329,
+ 2332, 2335, 2338, 2341, 2344, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2347, 2350, 2353, 2356, 2359, 2362, 2365, 2368, 2371, 2374,
+ }},
+ {{
+ 2377, 2380, 2383, 2386, 2389, 2392, 2395, 2398, 2401, 2404, 2407,
+ 2410, 2413, 2416, 2419, 2422, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2425, 0, 2435, 0, 2441,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2447, 2453, 2459, 2465, 2471, 2477, 2483, 2489, 0, 0, 2495,
+ 2501, 2507, 0, 0, 0, 2513, 2519, 2529, 2539, 2549, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2447, 2559,
+ 2569, 2579, 0, 0, 0, 0, 0, 0, 0, 2589, 2595,
+ 2601, 2607, 2613, 2607, 2619, 2625, 2631, 2637, 2643, 2637,
+ }},
+ {{
+ 2649, 2656, 0, 2663, 0, 0, 2669, 2683, 2693, 2699, 0,
+ 2705, 0, 2711, 2717, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2723, 0, 2729, 2739, 0, 2745, 2751, 0, 0,
+ }},
+ {{
+ 2757, 2763, 2769, 2775, 2785, 2795, 2795, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2801, 2808, 2815,
+ 2822, 2829, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ }},
+ {{
+ 0, 2836, 2839, 2842, 2845, 2848, 2851, 2854, 2857, 2860, 2863,
+ 2866, 2869, 2872, 2875, 2878, 2881, 2884, 2887, 2890, 2893, 2896,
+ 2899, 2902, 2905, 2908, 2911, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2914, 2918, 2922, 2926, 2930, 2934, 2938, 2942, 2946, 2950, 2954,
+ 2958, 2962, 2966, 2970, 2974, 2978, 2982, 2986, 2990, 2994, 2998,
+ 3002, 3006, 3010, 3014, 3018, 3022, 3026, 3030, 3034, 3038,
+ }},
+ {{
+ 3042, 3046, 3050, 3054, 3058, 3062, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22,
+ 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44,
+ 46, 48, 50, 52, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
+ }},
+ {{
+ 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46,
+ 48, 50, 52, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 6,
+ 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,
+ 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
+ }},
+ {{
+ 50, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 6, 8,
+ }},
+ {{
+ 0, 0, 14, 0, 0, 20, 22, 0, 0, 28, 30,
+ 32, 34, 0, 38, 40, 42, 44, 46, 48, 50, 52,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 4, 6, 8, 10, 12,
+ 14, 16, 18, 20, 22, 24, 26, 28, 30, 32,
+ }},
+ {{
+ 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 2, 4, 0, 8, 10, 12, 14,
+ 0, 0, 20, 22, 24, 26, 28, 30, 32, 34, 0,
+ 38, 40, 42, 44, 46, 48, 50, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 4, 0, 8, 10, 12, 14, 0,
+ }},
+ {{
+ 18, 20, 22, 24, 26, 0, 30, 0, 0, 0, 38,
+ 40, 42, 44, 46, 48, 50, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 24, 26, 28, 30, 32, 34, 36, 38, 40,
+ }},
+ {{
+ 42, 44, 46, 48, 50, 52, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 50, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 4, 6, 8,
+ }},
+ {{
+ 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 640, 643, 646,
+ 649, 652, 655, 658, 661, 598, 664, 667, 54, 670, 673,
+ 676, 679, 682, 661, 685, 688, 691, 694, 697, 700,
+ }},
+ {{
+ 703, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 685, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 640, 643, 646, 649, 652, 655, 658, 661, 598,
+ 664, 667, 54, 670, 673, 676, 679, 682, 661, 685, 688,
+ 691, 694, 697, 700, 703, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 685, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 640, 643, 646, 649,
+ }},
+ {{
+ 652, 655, 658, 661, 598, 664, 667, 54, 670, 673, 676,
+ 679, 682, 661, 685, 688, 691, 694, 697, 700, 703, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 685, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 640, 643, 646, 649, 652, 655, 658, 661, 598, 664,
+ }},
+ {{
+ 667, 54, 670, 673, 676, 679, 682, 661, 685, 688, 691,
+ 694, 697, 700, 703, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 685, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 640, 643, 646, 649, 652, 655,
+ 658, 661, 598, 664, 667, 54, 670, 673, 676, 679,
+ }},
+ {{
+ 682, 661, 685, 688, 691, 694, 697, 700, 703, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 685, 0, 0, 0, 0,
+ }},
+};
+
+static const unsigned char nameprep_rfc3491_map_data[] = {
+ 0, 0, 1, 97, 1, 98, 1, 99, 1, 100, 1, 101,
+ 1, 102, 1, 103, 1, 104, 1, 105, 1, 106, 1, 107,
+ 1, 108, 1, 109, 1, 110, 1, 111, 1, 112, 1, 113,
+ 1, 114, 1, 115, 1, 116, 1, 117, 1, 118, 1, 119,
+ 1, 120, 1, 121, 1, 122, 2, 188, 3, 1, 224, 1,
+ 225, 1, 226, 1, 227, 1, 228, 1, 229, 1, 230, 1,
+ 231, 1, 232, 1, 233, 1, 234, 1, 235, 1, 236, 1,
+ 237, 1, 238, 1, 239, 1, 240, 1, 241, 1, 242, 1,
+ 243, 1, 244, 1, 245, 1, 246, 1, 248, 1, 249, 1,
+ 250, 1, 251, 1, 252, 1, 253, 1, 254, 5, 115, 0,
+ 0, 0, 115, 2, 1, 1, 2, 3, 1, 2, 5, 1,
+ 2, 7, 1, 2, 9, 1, 2, 11, 1, 2, 13, 1,
+ 2, 15, 1, 2, 17, 1, 2, 19, 1, 2, 21, 1,
+ 2, 23, 1, 2, 25, 1, 2, 27, 1, 2, 29, 1,
+ 2, 31, 1, 2, 33, 1, 2, 35, 1, 2, 37, 1,
+ 2, 39, 1, 2, 41, 1, 2, 43, 1, 2, 45, 1,
+ 2, 47, 1, 6, 105, 0, 0, 0, 7, 3, 2, 51,
+ 1, 2, 53, 1, 2, 55, 1, 2, 58, 1, 2, 60,
+ 1, 2, 62, 1, 2, 64, 1, 2, 66, 1, 2, 68,
+ 1, 2, 70, 1, 2, 72, 1, 5, 188, 2, 0, 0,
+ 110, 2, 75, 1, 2, 77, 1, 2, 79, 1, 2, 81,
+ 1, 2, 83, 1, 2, 85, 1, 2, 87, 1, 2, 89,
+ 1, 2, 91, 1, 2, 93, 1, 2, 95, 1, 2, 97,
+ 1, 2, 99, 1, 2, 101, 1, 2, 103, 1, 2, 105,
+ 1, 2, 107, 1, 2, 109, 1, 2, 111, 1, 2, 113,
+ 1, 2, 115, 1, 2, 117, 1, 2, 119, 1, 1, 255,
+ 2, 122, 1, 2, 124, 1, 2, 126, 1, 2, 83, 2,
+ 2, 131, 1, 2, 133, 1, 2, 84, 2, 2, 136, 1,
+ 2, 86, 2, 2, 87, 2, 2, 140, 1, 2, 221, 1,
+ 2, 89, 2, 2, 91, 2, 2, 146, 1, 2, 96, 2,
+ 2, 99, 2, 2, 105, 2, 2, 104, 2, 2, 153, 1,
+ 2, 111, 2, 2, 114, 2, 2, 117, 2, 2, 161, 1,
+ 2, 163, 1, 2, 165, 1, 2, 128, 2, 2, 168, 1,
+ 2, 131, 2, 2, 173, 1, 2, 136, 2, 2, 176, 1,
+ 2, 138, 2, 2, 139, 2, 2, 180, 1, 2, 182, 1,
+ 2, 146, 2, 2, 185, 1, 2, 189, 1, 2, 198, 1,
+ 2, 201, 1, 2, 204, 1, 2, 206, 1, 2, 208, 1,
+ 2, 210, 1, 2, 212, 1, 2, 214, 1, 2, 216, 1,
+ 2, 218, 1, 2, 220, 1, 2, 223, 1, 2, 225, 1,
+ 2, 227, 1, 2, 229, 1, 2, 231, 1, 2, 233, 1,
+ 2, 235, 1, 2, 237, 1, 2, 239, 1, 6, 106, 0,
+ 0, 0, 12, 3, 2, 243, 1, 2, 245, 1, 2, 149,
+ 1, 2, 191, 1, 2, 249, 1, 2, 251, 1, 2, 253,
+ 1, 2, 255, 1, 2, 1, 2, 2, 3, 2, 2, 5,
+ 2, 2, 7, 2, 2, 9, 2, 2, 11, 2, 2, 13,
+ 2, 2, 15, 2, 2, 17, 2, 2, 19, 2, 2, 21,
+ 2, 2, 23, 2, 2, 25, 2, 2, 27, 2, 2, 29,
+ 2, 2, 31, 2, 2, 158, 1, 2, 35, 2, 2, 37,
+ 2, 2, 39, 2, 2, 41, 2, 2, 43, 2, 2, 45,
+ 2, 2, 47, 2, 2, 49, 2, 2, 51, 2, 2, 185,
+ 3, 6, 32, 0, 0, 0, 185, 3, 2, 172, 3, 2,
+ 173, 3, 2, 174, 3, 2, 175, 3, 2, 204, 3, 2,
+ 205, 3, 2, 206, 3, 10, 185, 3, 0, 0, 8, 3,
+ 0, 0, 1, 3, 2, 177, 3, 2, 178, 3, 2, 179,
+ 3, 2, 180, 3, 2, 181, 3, 2, 182, 3, 2, 183,
+ 3, 2, 184, 3, 2, 186, 3, 2, 187, 3, 2, 189,
+ 3, 2, 190, 3, 2, 191, 3, 2, 192, 3, 2, 193,
+ 3, 2, 195, 3, 2, 196, 3, 2, 197, 3, 2, 198,
+ 3, 2, 199, 3, 2, 200, 3, 2, 201, 3, 2, 202,
+ 3, 2, 203, 3, 10, 197, 3, 0, 0, 8, 3, 0,
+ 0, 1, 3, 2, 217, 3, 2, 219, 3, 2, 221, 3,
+ 2, 223, 3, 2, 225, 3, 2, 227, 3, 2, 229, 3,
+ 2, 231, 3, 2, 233, 3, 2, 235, 3, 2, 237, 3,
+ 2, 239, 3, 2, 80, 4, 2, 81, 4, 2, 82, 4,
+ 2, 83, 4, 2, 84, 4, 2, 85, 4, 2, 86, 4,
+ 2, 87, 4, 2, 88, 4, 2, 89, 4, 2, 90, 4,
+ 2, 91, 4, 2, 92, 4, 2, 93, 4, 2, 94, 4,
+ 2, 95, 4, 2, 48, 4, 2, 49, 4, 2, 50, 4,
+ 2, 51, 4, 2, 52, 4, 2, 53, 4, 2, 54, 4,
+ 2, 55, 4, 2, 56, 4, 2, 57, 4, 2, 58, 4,
+ 2, 59, 4, 2, 60, 4, 2, 61, 4, 2, 62, 4,
+ 2, 63, 4, 2, 64, 4, 2, 65, 4, 2, 66, 4,
+ 2, 67, 4, 2, 68, 4, 2, 69, 4, 2, 70, 4,
+ 2, 71, 4, 2, 72, 4, 2, 73, 4, 2, 74, 4,
+ 2, 75, 4, 2, 76, 4, 2, 77, 4, 2, 78, 4,
+ 2, 79, 4, 2, 97, 4, 2, 99, 4, 2, 101, 4,
+ 2, 103, 4, 2, 105, 4, 2, 107, 4, 2, 109, 4,
+ 2, 111, 4, 2, 113, 4, 2, 115, 4, 2, 117, 4,
+ 2, 119, 4, 2, 121, 4, 2, 123, 4, 2, 125, 4,
+ 2, 127, 4, 2, 129, 4, 2, 139, 4, 2, 141, 4,
+ 2, 143, 4, 2, 145, 4, 2, 147, 4, 2, 149, 4,
+ 2, 151, 4, 2, 153, 4, 2, 155, 4, 2, 157, 4,
+ 2, 159, 4, 2, 161, 4, 2, 163, 4, 2, 165, 4,
+ 2, 167, 4, 2, 169, 4, 2, 171, 4, 2, 173, 4,
+ 2, 175, 4, 2, 177, 4, 2, 179, 4, 2, 181, 4,
+ 2, 183, 4, 2, 185, 4, 2, 187, 4, 2, 189, 4,
+ 2, 191, 4, 2, 194, 4, 2, 196, 4, 2, 198, 4,
+ 2, 200, 4, 2, 202, 4, 2, 204, 4, 2, 206, 4,
+ 2, 209, 4, 2, 211, 4, 2, 213, 4, 2, 215, 4,
+ 2, 217, 4, 2, 219, 4, 2, 221, 4, 2, 223, 4,
+ 2, 225, 4, 2, 227, 4, 2, 229, 4, 2, 231, 4,
+ 2, 233, 4, 2, 235, 4, 2, 237, 4, 2, 239, 4,
+ 2, 241, 4, 2, 243, 4, 2, 245, 4, 2, 249, 4,
+ 2, 1, 5, 2, 3, 5, 2, 5, 5, 2, 7, 5,
+ 2, 9, 5, 2, 11, 5, 2, 13, 5, 2, 15, 5,
+ 2, 97, 5, 2, 98, 5, 2, 99, 5, 2, 100, 5,
+ 2, 101, 5, 2, 102, 5, 2, 103, 5, 2, 104, 5,
+ 2, 105, 5, 2, 106, 5, 2, 107, 5, 2, 108, 5,
+ 2, 109, 5, 2, 110, 5, 2, 111, 5, 2, 112, 5,
+ 2, 113, 5, 2, 114, 5, 2, 115, 5, 2, 116, 5,
+ 2, 117, 5, 2, 118, 5, 2, 119, 5, 2, 120, 5,
+ 2, 121, 5, 2, 122, 5, 2, 123, 5, 2, 124, 5,
+ 2, 125, 5, 2, 126, 5, 2, 127, 5, 2, 128, 5,
+ 2, 129, 5, 2, 130, 5, 2, 131, 5, 2, 132, 5,
+ 2, 133, 5, 2, 134, 5, 6, 101, 5, 0, 0, 130,
+ 5, 2, 1, 30, 2, 3, 30, 2, 5, 30, 2, 7,
+ 30, 2, 9, 30, 2, 11, 30, 2, 13, 30, 2, 15,
+ 30, 2, 17, 30, 2, 19, 30, 2, 21, 30, 2, 23,
+ 30, 2, 25, 30, 2, 27, 30, 2, 29, 30, 2, 31,
+ 30, 2, 33, 30, 2, 35, 30, 2, 37, 30, 2, 39,
+ 30, 2, 41, 30, 2, 43, 30, 2, 45, 30, 2, 47,
+ 30, 2, 49, 30, 2, 51, 30, 2, 53, 30, 2, 55,
+ 30, 2, 57, 30, 2, 59, 30, 2, 61, 30, 2, 63,
+ 30, 2, 65, 30, 2, 67, 30, 2, 69, 30, 2, 71,
+ 30, 2, 73, 30, 2, 75, 30, 2, 77, 30, 2, 79,
+ 30, 2, 81, 30, 2, 83, 30, 2, 85, 30, 2, 87,
+ 30, 2, 89, 30, 2, 91, 30, 2, 93, 30, 2, 95,
+ 30, 2, 97, 30, 2, 99, 30, 2, 101, 30, 2, 103,
+ 30, 2, 105, 30, 2, 107, 30, 2, 109, 30, 2, 111,
+ 30, 2, 113, 30, 2, 115, 30, 2, 117, 30, 2, 119,
+ 30, 2, 121, 30, 2, 123, 30, 2, 125, 30, 2, 127,
+ 30, 2, 129, 30, 2, 131, 30, 2, 133, 30, 2, 135,
+ 30, 2, 137, 30, 2, 139, 30, 2, 141, 30, 2, 143,
+ 30, 2, 145, 30, 2, 147, 30, 2, 149, 30, 6, 104,
+ 0, 0, 0, 49, 3, 6, 116, 0, 0, 0, 8, 3,
+ 6, 119, 0, 0, 0, 10, 3, 6, 121, 0, 0, 0,
+ 10, 3, 6, 97, 0, 0, 0, 190, 2, 2, 161, 30,
+ 2, 163, 30, 2, 165, 30, 2, 167, 30, 2, 169, 30,
+ 2, 171, 30, 2, 173, 30, 2, 175, 30, 2, 177, 30,
+ 2, 179, 30, 2, 181, 30, 2, 183, 30, 2, 185, 30,
+ 2, 187, 30, 2, 189, 30, 2, 191, 30, 2, 193, 30,
+ 2, 195, 30, 2, 197, 30, 2, 199, 30, 2, 201, 30,
+ 2, 203, 30, 2, 205, 30, 2, 207, 30, 2, 209, 30,
+ 2, 211, 30, 2, 213, 30, 2, 215, 30, 2, 217, 30,
+ 2, 219, 30, 2, 221, 30, 2, 223, 30, 2, 225, 30,
+ 2, 227, 30, 2, 229, 30, 2, 231, 30, 2, 233, 30,
+ 2, 235, 30, 2, 237, 30, 2, 239, 30, 2, 241, 30,
+ 2, 243, 30, 2, 245, 30, 2, 247, 30, 2, 249, 30,
+ 2, 0, 31, 2, 1, 31, 2, 2, 31, 2, 3, 31,
+ 2, 4, 31, 2, 5, 31, 2, 6, 31, 2, 7, 31,
+ 2, 16, 31, 2, 17, 31, 2, 18, 31, 2, 19, 31,
+ 2, 20, 31, 2, 21, 31, 2, 32, 31, 2, 33, 31,
+ 2, 34, 31, 2, 35, 31, 2, 36, 31, 2, 37, 31,
+ 2, 38, 31, 2, 39, 31, 2, 48, 31, 2, 49, 31,
+ 2, 50, 31, 2, 51, 31, 2, 52, 31, 2, 53, 31,
+ 2, 54, 31, 2, 55, 31, 2, 64, 31, 2, 65, 31,
+ 2, 66, 31, 2, 67, 31, 2, 68, 31, 2, 69, 31,
+ 6, 197, 3, 0, 0, 19, 3, 10, 197, 3, 0, 0,
+ 19, 3, 0, 0, 0, 3, 10, 197, 3, 0, 0, 19,
+ 3, 0, 0, 1, 3, 10, 197, 3, 0, 0, 19, 3,
+ 0, 0, 66, 3, 2, 81, 31, 2, 83, 31, 2, 85,
+ 31, 2, 87, 31, 2, 96, 31, 2, 97, 31, 2, 98,
+ 31, 2, 99, 31, 2, 100, 31, 2, 101, 31, 2, 102,
+ 31, 2, 103, 31, 6, 0, 31, 0, 0, 185, 3, 6,
+ 1, 31, 0, 0, 185, 3, 6, 2, 31, 0, 0, 185,
+ 3, 6, 3, 31, 0, 0, 185, 3, 6, 4, 31, 0,
+ 0, 185, 3, 6, 5, 31, 0, 0, 185, 3, 6, 6,
+ 31, 0, 0, 185, 3, 6, 7, 31, 0, 0, 185, 3,
+ 6, 32, 31, 0, 0, 185, 3, 6, 33, 31, 0, 0,
+ 185, 3, 6, 34, 31, 0, 0, 185, 3, 6, 35, 31,
+ 0, 0, 185, 3, 6, 36, 31, 0, 0, 185, 3, 6,
+ 37, 31, 0, 0, 185, 3, 6, 38, 31, 0, 0, 185,
+ 3, 6, 39, 31, 0, 0, 185, 3, 6, 96, 31, 0,
+ 0, 185, 3, 6, 97, 31, 0, 0, 185, 3, 6, 98,
+ 31, 0, 0, 185, 3, 6, 99, 31, 0, 0, 185, 3,
+ 6, 100, 31, 0, 0, 185, 3, 6, 101, 31, 0, 0,
+ 185, 3, 6, 102, 31, 0, 0, 185, 3, 6, 103, 31,
+ 0, 0, 185, 3, 6, 112, 31, 0, 0, 185, 3, 6,
+ 177, 3, 0, 0, 185, 3, 6, 172, 3, 0, 0, 185,
+ 3, 6, 177, 3, 0, 0, 66, 3, 10, 177, 3, 0,
+ 0, 66, 3, 0, 0, 185, 3, 2, 176, 31, 2, 177,
+ 31, 2, 112, 31, 2, 113, 31, 6, 116, 31, 0, 0,
+ 185, 3, 6, 183, 3, 0, 0, 185, 3, 6, 174, 3,
+ 0, 0, 185, 3, 6, 183, 3, 0, 0, 66, 3, 10,
+ 183, 3, 0, 0, 66, 3, 0, 0, 185, 3, 2, 114,
+ 31, 2, 115, 31, 2, 116, 31, 2, 117, 31, 10, 185,
+ 3, 0, 0, 8, 3, 0, 0, 0, 3, 6, 185, 3,
+ 0, 0, 66, 3, 10, 185, 3, 0, 0, 8, 3, 0,
+ 0, 66, 3, 2, 208, 31, 2, 209, 31, 2, 118, 31,
+ 2, 119, 31, 10, 197, 3, 0, 0, 8, 3, 0, 0,
+ 0, 3, 6, 193, 3, 0, 0, 19, 3, 6, 197, 3,
+ 0, 0, 66, 3, 10, 197, 3, 0, 0, 8, 3, 0,
+ 0, 66, 3, 2, 224, 31, 2, 225, 31, 2, 122, 31,
+ 2, 123, 31, 2, 229, 31, 6, 124, 31, 0, 0, 185,
+ 3, 6, 201, 3, 0, 0, 185, 3, 6, 206, 3, 0,
+ 0, 185, 3, 6, 201, 3, 0, 0, 66, 3, 10, 201,
+ 3, 0, 0, 66, 3, 0, 0, 185, 3, 2, 120, 31,
+ 2, 121, 31, 2, 124, 31, 2, 125, 31, 5, 114, 0,
+ 0, 0, 115, 5, 176, 0, 0, 0, 99, 5, 176, 0,
+ 0, 0, 102, 5, 110, 0, 0, 0, 111, 5, 115, 0,
+ 0, 0, 109, 9, 116, 0, 0, 0, 101, 0, 0, 0,
+ 108, 5, 116, 0, 0, 0, 109, 2, 112, 33, 2, 113,
+ 33, 2, 114, 33, 2, 115, 33, 2, 116, 33, 2, 117,
+ 33, 2, 118, 33, 2, 119, 33, 2, 120, 33, 2, 121,
+ 33, 2, 122, 33, 2, 123, 33, 2, 124, 33, 2, 125,
+ 33, 2, 126, 33, 2, 127, 33, 2, 208, 36, 2, 209,
+ 36, 2, 210, 36, 2, 211, 36, 2, 212, 36, 2, 213,
+ 36, 2, 214, 36, 2, 215, 36, 2, 216, 36, 2, 217,
+ 36, 2, 218, 36, 2, 219, 36, 2, 220, 36, 2, 221,
+ 36, 2, 222, 36, 2, 223, 36, 2, 224, 36, 2, 225,
+ 36, 2, 226, 36, 2, 227, 36, 2, 228, 36, 2, 229,
+ 36, 2, 230, 36, 2, 231, 36, 2, 232, 36, 2, 233,
+ 36, 9, 104, 0, 0, 0, 112, 0, 0, 0, 97, 5,
+ 97, 0, 0, 0, 117, 5, 111, 0, 0, 0, 118, 5,
+ 112, 0, 0, 0, 97, 5, 110, 0, 0, 0, 97, 5,
+ 188, 3, 0, 0, 97, 5, 109, 0, 0, 0, 97, 5,
+ 107, 0, 0, 0, 97, 5, 107, 0, 0, 0, 98, 5,
+ 109, 0, 0, 0, 98, 5, 103, 0, 0, 0, 98, 5,
+ 112, 0, 0, 0, 102, 5, 110, 0, 0, 0, 102, 5,
+ 188, 3, 0, 0, 102, 5, 104, 0, 0, 0, 122, 9,
+ 107, 0, 0, 0, 104, 0, 0, 0, 122, 9, 109, 0,
+ 0, 0, 104, 0, 0, 0, 122, 9, 103, 0, 0, 0,
+ 104, 0, 0, 0, 122, 9, 116, 0, 0, 0, 104, 0,
+ 0, 0, 122, 9, 107, 0, 0, 0, 112, 0, 0, 0,
+ 97, 9, 109, 0, 0, 0, 112, 0, 0, 0, 97, 9,
+ 103, 0, 0, 0, 112, 0, 0, 0, 97, 5, 112, 0,
+ 0, 0, 118, 5, 110, 0, 0, 0, 118, 5, 188, 3,
+ 0, 0, 118, 5, 109, 0, 0, 0, 118, 5, 107, 0,
+ 0, 0, 118, 5, 112, 0, 0, 0, 119, 5, 110, 0,
+ 0, 0, 119, 5, 188, 3, 0, 0, 119, 5, 109, 0,
+ 0, 0, 119, 5, 107, 0, 0, 0, 119, 6, 107, 0,
+ 0, 0, 201, 3, 6, 109, 0, 0, 0, 201, 3, 5,
+ 98, 0, 0, 0, 113, 13, 99, 0, 0, 0, 21, 34,
+ 0, 0, 107, 0, 0, 0, 103, 9, 99, 0, 0, 0,
+ 111, 0, 0, 0, 46, 5, 100, 0, 0, 0, 98, 5,
+ 103, 0, 0, 0, 121, 5, 104, 0, 0, 0, 112, 5,
+ 107, 0, 0, 0, 107, 5, 107, 0, 0, 0, 109, 5,
+ 112, 0, 0, 0, 104, 9, 112, 0, 0, 0, 112, 0,
+ 0, 0, 109, 5, 112, 0, 0, 0, 114, 5, 115, 0,
+ 0, 0, 118, 5, 119, 0, 0, 0, 98, 5, 102, 0,
+ 0, 0, 102, 5, 102, 0, 0, 0, 105, 5, 102, 0,
+ 0, 0, 108, 9, 102, 0, 0, 0, 102, 0, 0, 0,
+ 105, 9, 102, 0, 0, 0, 102, 0, 0, 0, 108, 5,
+ 115, 0, 0, 0, 116, 6, 116, 5, 0, 0, 118, 5,
+ 6, 116, 5, 0, 0, 101, 5, 6, 116, 5, 0, 0,
+ 107, 5, 6, 126, 5, 0, 0, 118, 5, 6, 116, 5,
+ 0, 0, 109, 5, 2, 65, 255, 2, 66, 255, 2, 67,
+ 255, 2, 68, 255, 2, 69, 255, 2, 70, 255, 2, 71,
+ 255, 2, 72, 255, 2, 73, 255, 2, 74, 255, 2, 75,
+ 255, 2, 76, 255, 2, 77, 255, 2, 78, 255, 2, 79,
+ 255, 2, 80, 255, 2, 81, 255, 2, 82, 255, 2, 83,
+ 255, 2, 84, 255, 2, 85, 255, 2, 86, 255, 2, 87,
+ 255, 2, 88, 255, 2, 89, 255, 2, 90, 255, 3, 40,
+ 4, 1, 3, 41, 4, 1, 3, 42, 4, 1, 3, 43,
+ 4, 1, 3, 44, 4, 1, 3, 45, 4, 1, 3, 46,
+ 4, 1, 3, 47, 4, 1, 3, 48, 4, 1, 3, 49,
+ 4, 1, 3, 50, 4, 1, 3, 51, 4, 1, 3, 52,
+ 4, 1, 3, 53, 4, 1, 3, 54, 4, 1, 3, 55,
+ 4, 1, 3, 56, 4, 1, 3, 57, 4, 1, 3, 58,
+ 4, 1, 3, 59, 4, 1, 3, 60, 4, 1, 3, 61,
+ 4, 1, 3, 62, 4, 1, 3, 63, 4, 1, 3, 64,
+ 4, 1, 3, 65, 4, 1, 3, 66, 4, 1, 3, 67,
+ 4, 1, 3, 68, 4, 1, 3, 69, 4, 1, 3, 70,
+ 4, 1, 3, 71, 4, 1, 3, 72, 4, 1, 3, 73,
+ 4, 1, 3, 74, 4, 1, 3, 75, 4, 1, 3, 76,
+ 4, 1, 3, 77, 4, 1,
+};
+
+static const unsigned short nameprep_rfc3491_prohibited_imap[] = {
+ 68, 196, 196, 324, 196, 196, 196, 452,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 708, 196, 196, 580, 836, 836, 836, 836,
+ 836, 836, 836, 836, 0, 1, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 3, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 5, 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 8, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 10,
+ 0, 0, 0, 11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 14, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9,
+};
+
+static const struct {
+ unsigned char bm[16];
+} nameprep_rfc3491_prohibited_bitmap[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 255,255,255,255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0,
+ }},
+ {{
+ 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 255,199, 0, 0, 0,255, 0, 0, 0, 0, 0,128, 14,252, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 15,
+ }},
+ {{
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 7,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,
+ }},
+ {{
+ 2, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+};
+
+static const unsigned short nameprep_rfc3491_unassigned_imap[] = {
+ 68, 196, 324, 452, 580, 708, 708, 836,
+ 964, 964, 1092, 1220, 708, 708, 708, 1348,
+ 708, 708, 708, 1348, 708, 708, 708, 1348,
+ 708, 708, 708, 1348, 708, 708, 708, 1348,
+ 708, 708, 708, 1348, 708, 708, 708, 1348,
+ 708, 708, 708, 1348, 708, 708, 708, 1348,
+ 708, 708, 708, 1348, 708, 708, 708, 1348,
+ 1476, 708, 708, 1348, 964, 964, 964, 964,
+ 964, 964, 964, 964, 0, 0, 0, 0,
+ 1, 2, 3, 4, 0, 5, 6, 7,
+ 8, 9, 10, 11, 12, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 0, 0, 0,
+ 36, 37, 38, 39, 40, 41, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 0, 42, 43, 44, 45, 46, 47, 48,
+ 0, 0, 0, 49, 50, 51, 0, 0,
+ 52, 53, 54, 55, 0, 0, 0, 0,
+ 0, 0, 12, 12, 12, 12, 12, 12,
+ 12, 56, 0, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 66,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 67, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 68, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 69, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 70, 12, 71, 72, 0, 0, 73, 74,
+ 75, 76, 35, 77, 12, 12, 12, 12,
+ 12, 12, 78, 12, 79, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 0, 80, 81, 82,
+ 12, 12, 12, 12, 83, 84, 85, 0,
+ 0, 86, 0, 87, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 88, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 89, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 0, 0, 0, 0,
+ 90, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 88, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 88, 91, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12,
+};
+
+static const struct {
+ unsigned char bm[16];
+} nameprep_rfc3491_unassigned_bitmap[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 2, 0,240,255,255,255, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0,128,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0,207,187,
+ }},
+ {{
+ 15, 40, 0, 0, 4, 0, 0, 0, 0,128, 0, 0, 0, 0,128,255,
+ }},
+ {{
+ 128, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0,192,252,
+ }},
+ {{
+ 0, 0,255,255,255,255, 1, 0, 0, 0,128, 1, 1, 0, 0, 0,
+ }},
+ {{
+ 0,249, 1, 0, 4, 0, 0, 4,224,255, 0, 0, 0,248,224,255,
+ }},
+ {{
+ 255,239,255,119, 1, 0, 0,248, 0, 0,192,255, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0,128,
+ }},
+ {{
+ 0, 64, 0, 0, 0,224, 0, 0, 0,248,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0,252,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 17, 0, 0, 0, 0, 0, 0, 12, 0,192,224, 0, 0, 0,254,255,
+ }},
+ {{
+ 17, 96, 6, 0, 0, 2, 58, 44, 96,198,127, 79, 48, 0, 0,248,
+ }},
+ {{
+ 27,120, 6, 0, 0, 2,146, 44,120,198,255,161, 63, 0,224,255,
+ }},
+ {{
+ 17, 80, 4, 0, 0, 2, 18, 12, 64,196,254,255, 62, 0,255,255,
+ }},
+ {{
+ 17, 96, 6, 0, 0, 2, 50, 12,112,198, 63, 79, 60, 0,254,255,
+ }},
+ {{
+ 19, 56,194, 41,231, 56, 64, 60, 56,194,127,255,127, 0,248,255,
+ }},
+ {{
+ 17, 32, 2, 0, 0, 2, 16, 60, 32,194,159,255, 60, 0,255,255,
+ }},
+ {{
+ 19, 32, 2, 0, 0, 2, 16, 60, 32,194,159,191, 60, 0,255,255,
+ }},
+ {{
+ 19, 32, 2, 0, 0, 2, 0, 60, 48,194,127,255, 60, 0,255,255,
+ }},
+ {{
+ 19, 0,128, 3, 0, 0, 4,208,128,123,160, 0,255,255,227,255,
+ }},
+ {{
+ 1, 0, 0, 0, 0, 0, 0,120, 0, 0, 0,240,255,255,255,255,
+ }},
+ {{
+ 105,218, 15, 1, 81, 19, 0,196,160,192, 0,204,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,248, 1, 0,
+ }},
+ {{
+ 0,240, 0, 1, 0, 0, 0, 32, 0, 96,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 4, 9, 56,252, 0, 0, 0,252,255,255,255,255,
+ }},
+ {{
+ 255,255,255,255, 0, 0, 0, 0,192,255, 0, 0, 0, 0, 0,246,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252,
+ }},
+ {{
+ 128, 0, 0, 0, 0, 0, 0, 0,128,194,128,194, 0, 0, 0, 0,
+ }},
+ {{
+ 128,194, 0, 0, 0,128,194,128,194,128,128, 0, 0,128, 0, 0,
+ }},
+ {{
+ 0,128,194,128, 0, 0, 0, 0,128, 0, 0,248, 1, 0, 0,224,
+ }},
+ {{
+ 255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,255,
+ }},
+ {{
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,255,
+ }},
+ {{
+ 0, 0, 0,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254,255,
+ }},
+ {{
+ 0, 32,224,255, 0, 0,128,255, 0, 0,240,255, 0, 32,242,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224, 0,252,255,255,
+ }},
+ {{
+ 0,128, 0,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0,252,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252,
+ }},
+ {{
+ 0, 0,192,192, 0, 0, 0, 0,192,192, 0, 85, 0, 0, 0,192,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 32, 0, 32, 0, 48, 16, 0, 0, 35,128,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,127,240, 3, 12, 0,
+ }},
+ {{
+ 0,128,255,255, 0, 0,252,255,255,255, 0, 0, 0,248,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 24, 0,240, 7, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 240,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,128,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0,128,255,255,255, 0,248,255,255, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,
+ }},
+ {{
+ 0, 0, 48, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,
+ }},
+ {{
+ 0,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 33, 12, 0, 0, 0, 1, 0, 0, 0, 80,184,128, 1, 0, 0, 0,
+ }},
+ {{
+ 0, 0,224, 0, 0, 0, 1,128,255,255, 0, 0, 0,240, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,255,255,255, 0,240,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0,128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 31, 0, 0, 0, 0,224, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0,128, 0, 0, 0, 0, 0,255,255,255,255,255,255,255, 0, 0,
+ }},
+ {{
+ 0, 0, 0,224, 0, 0, 0, 0,240,255, 1, 0, 0, 0, 0,112,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 0, 0, 0, 0, 0,128,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 7,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0, 0, 0,128,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0,192,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0,192,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0,224, 0, 0, 0, 0, 0, 0,128,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0,240,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0,248,255,255,
+ }},
+ {{
+ 128,255, 7, 31, 0, 0,128,160, 36, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0,252,255,255,255, 7, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 3, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0,224,
+ }},
+ {{
+ 0, 0,255,255,240,255, 0, 0,128, 1, 8, 0,128,240, 32, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,128, 3, 3, 3,227,128,128,255, 1,
+ }},
+ {{
+ 0, 0, 0,128,240,255, 0, 0, 0,248,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0,192, 0, 0, 0, 0,192,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,255,
+ }},
+ {{
+ 0, 0, 0, 0,128, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 32,155, 33, 0, 20, 18, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 64, 24, 32, 32, 0, 0, 0,132,160, 3, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 63,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0,192,255,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 253,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+};
+
+static const unsigned short nameprep_rfc3491_bidi_imap[] = {
+ 272, 400, 528, 656, 784, 912, 912, 912,
+ 912, 1040, 1168, 912, 912, 1296, 912, 1424,
+ 1552, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1808, 1680, 1680,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 1936, 1680, 1680, 1680, 1680, 2064,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 2192,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 2192,
+ 0, 0, 1, 1, 0, 2, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 5, 6, 4, 4, 7, 8, 9,
+ 0, 0, 0, 10, 11, 12, 13, 14,
+ 4, 4, 4, 4, 15, 4, 13, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 29, 30, 31,
+ 32, 33, 0, 0, 29, 34, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50,
+ 39, 51, 41, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 60,
+ 61, 64, 65, 60, 66, 67, 68, 69,
+ 20, 70, 71, 0, 72, 73, 74, 0,
+ 75, 76, 77, 78, 79, 80, 81, 0,
+ 4, 82, 83, 0, 0, 4, 84, 85,
+ 4, 4, 86, 4, 4, 87, 4, 88,
+ 89, 4, 90, 4, 91, 92, 93, 13,
+ 92, 4, 94, 95, 0, 4, 4, 96,
+ 20, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 97, 1, 4, 4, 98,
+ 99, 100, 101, 102, 4, 103, 104, 105,
+ 106, 4, 4, 83, 4, 107, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 108, 4, 4, 88,
+ 109, 4, 110, 111, 4, 112, 113, 114,
+ 115, 0, 0, 116, 0, 0, 0, 0,
+ 117, 118, 119, 4, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 121, 4, 122, 123, 0, 0, 0,
+ 0, 0, 0, 0, 124, 4, 4, 105,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 125, 126, 20, 4, 127, 20, 4, 128,
+ 129, 130, 4, 4, 13, 83, 0, 6,
+ 131, 4, 120, 132, 4, 98, 133, 134,
+ 4, 4, 4, 135, 4, 4, 111, 134,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 14, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 136, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 137, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 120, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 138, 4, 139, 0, 0, 0, 0,
+ 140, 141, 142, 29, 29, 143, 144, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 145, 146, 29, 147, 29, 148, 149,
+ 0, 0, 0, 150, 29, 29, 29, 151,
+ 0, 1, 1, 152, 4, 134, 153, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 134, 154, 139, 0, 0, 0, 0, 0,
+ 4, 155, 156, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 14,
+ 4, 157, 4, 158, 159, 160, 111, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 161, 4, 162, 163, 164, 4,
+ 165, 166, 167, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 168, 4, 4,
+ 4, 4, 4, 4, 4, 4, 105, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 97, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 111, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 111,
+};
+
+static const struct {
+ unsigned char tbl[32];
+} nameprep_rfc3491_bidi_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ }},
+ {{
+ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
+ }},
+ {{
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2,
+ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 2, 0, 2,
+ }},
+ {{
+ 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2,
+ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2,
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 0,
+ }},
+ {{
+ 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2,
+ 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 0, 2, 0, 2, 2,
+ }},
+ {{
+ 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2,
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2,
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
+ 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 0, 2, 0, 0, 2, 2, 0, 2, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 2, 2, 2, 0, 2, 0, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2,
+ 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2,
+ }},
+ {{
+ 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2,
+ 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0,
+ }},
+ {{
+ 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2,
+ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 0, 2, 0, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0,
+ }},
+ {{
+ 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2,
+ 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ }},
+ {{
+ 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 2, 2, 2, 0, 2, 2,
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 0, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0,
+ }},
+ {{
+ 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0,
+ 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2,
+ }},
+ {{
+ 0, 0, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 0, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2,
+ }},
+ {{
+ 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2,
+ 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+};
+
+static const unsigned char nameprep_rfc3491_bidi_data[] = {
+ idn_biditype_others,
+ idn_biditype_r_al,
+ idn_biditype_l,
+};
+
diff --git a/contrib/idn/idnkit-1.0-src/lib/normalizer.c b/contrib/idn/idnkit-1.0-src/lib/normalizer.c
new file mode 100644
index 0000000..604a1e5
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/normalizer.c
@@ -0,0 +1,439 @@
+#ifndef lint
+static char *rcsid = "$Id: normalizer.c,v 1.1.1.1 2003/06/04 00:26:05 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/result.h>
+#include <idn/normalizer.h>
+#include <idn/strhash.h>
+#include <idn/unormalize.h>
+#include <idn/unicode.h>
+#include <idn/ucs4.h>
+#include <idn/debug.h>
+#include <idn/util.h>
+
+#define MAX_LOCAL_SCHEME 3
+
+#define INITIALIZED (scheme_hash != NULL)
+
+typedef struct {
+ char *name;
+ idn_normalizer_proc_t proc;
+} normalize_scheme_t;
+
+struct idn_normalizer {
+ int nschemes;
+ int scheme_size;
+ normalize_scheme_t **schemes;
+ normalize_scheme_t *local_buf[MAX_LOCAL_SCHEME];
+ int reference_count;
+};
+
+static idn__strhash_t scheme_hash;
+
+static idn__unicode_version_t vcur = NULL;
+static idn__unicode_version_t v320 = NULL;
+#define INIT_VERSION(version, var) \
+ if (var == NULL) { \
+ idn_result_t r = idn__unicode_create(version, &var); \
+ if (r != idn_success) \
+ return (r); \
+ }
+
+static idn_result_t expand_schemes(idn_normalizer_t ctx);
+static idn_result_t register_standard_normalizers(void);
+static idn_result_t normalizer_formkc(const unsigned long *from,
+ unsigned long *to, size_t tolen);
+static idn_result_t normalizer_formkc_v320(const unsigned long *from,
+ unsigned long *to,
+ size_t tolen);
+
+static struct standard_normalizer {
+ char *name;
+ idn_normalizer_proc_t proc;
+} standard_normalizer[] = {
+ { "unicode-form-kc", normalizer_formkc },
+ { "unicode-form-kc/3.2.0", normalizer_formkc_v320 },
+ { "RFC3491", normalizer_formkc_v320 },
+ { NULL, NULL },
+};
+
+idn_result_t
+idn_normalizer_initialize(void) {
+ idn__strhash_t hash;
+ idn_result_t r;
+
+ TRACE(("idn_normalizer_initialize()\n"));
+
+ if (scheme_hash != NULL) {
+ r = idn_success; /* already initialized */
+ goto ret;
+ }
+
+ if ((r = idn__strhash_create(&hash)) != idn_success)
+ goto ret;
+ scheme_hash = hash;
+
+ /* Register standard normalizers */
+ r = register_standard_normalizers();
+ret:
+ TRACE(("idn_normalizer_initialize(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_normalizer_create(idn_normalizer_t *ctxp) {
+ idn_normalizer_t ctx;
+ idn_result_t r;
+
+ assert(ctxp != NULL);
+ TRACE(("idn_normalizer_create()\n"));
+
+ if ((ctx = malloc(sizeof(struct idn_normalizer))) == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ ctx->nschemes = 0;
+ ctx->scheme_size = MAX_LOCAL_SCHEME;
+ ctx->schemes = ctx->local_buf;
+ ctx->reference_count = 1;
+ *ctxp = ctx;
+
+ r = idn_success;
+ret:
+ TRACE(("idn_normalizer_create(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+void
+idn_normalizer_destroy(idn_normalizer_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_normalizer_destroy()\n"));
+
+ ctx->reference_count--;
+ if (ctx->reference_count <= 0) {
+ TRACE(("idn_normalizer_destroy(): the object is destroyed\n"));
+ if (ctx->schemes != ctx->local_buf)
+ free(ctx->schemes);
+ free(ctx);
+ } else {
+ TRACE(("idn_normalizer_destroy(): "
+ "update reference count (%d->%d)\n",
+ ctx->reference_count + 1, ctx->reference_count));
+ }
+}
+
+void
+idn_normalizer_incrref(idn_normalizer_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_normalizer_incrref()\n"));
+ TRACE(("idn_normalizer_incrref: update reference count (%d->%d)\n",
+ ctx->reference_count, ctx->reference_count + 1));
+
+ ctx->reference_count++;
+}
+
+idn_result_t
+idn_normalizer_add(idn_normalizer_t ctx, const char *scheme_name) {
+ idn_result_t r;
+ void *v;
+ normalize_scheme_t *scheme;
+
+ assert(ctx != NULL && scheme_name != NULL);
+
+ TRACE(("idn_normalizer_add(scheme_name=%s)\n", scheme_name));
+
+ assert(INITIALIZED);
+
+ if (idn__strhash_get(scheme_hash, scheme_name, &v) != idn_success) {
+ ERROR(("idn_normalizer_add(): invalid scheme \"%-.30s\"\n",
+ scheme_name));
+ r = idn_invalid_name;
+ goto ret;
+ }
+
+ scheme = v;
+
+ assert(ctx->nschemes <= ctx->scheme_size);
+
+ if (ctx->nschemes == ctx->scheme_size &&
+ (r = expand_schemes(ctx)) != idn_success) {
+ goto ret;
+ }
+
+ ctx->schemes[ctx->nschemes++] = scheme;
+ r = idn_success;
+ret:
+ TRACE(("idn_normalizer_add(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_normalizer_addall(idn_normalizer_t ctx, const char **scheme_names,
+ int nschemes) {
+ idn_result_t r;
+ int i;
+
+ assert(ctx != NULL && scheme_names != NULL);
+
+ TRACE(("idn_normalizer_addall(nschemes=%d)\n", nschemes));
+
+ for (i = 0; i < nschemes; i++) {
+ r = idn_normalizer_add(ctx, (const char *)*scheme_names);
+ if (r != idn_success)
+ goto ret;
+ scheme_names++;
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("idn_normalizer_addall(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_normalizer_normalize(idn_normalizer_t ctx, const unsigned long *from,
+ unsigned long *to, size_t tolen) {
+ idn_result_t r;
+ unsigned long *src, *dst;
+ unsigned long *buffers[2] = {NULL, NULL};
+ size_t buflen[2] = {0, 0};
+ size_t dstlen;
+ int idx;
+ int i;
+
+ assert(scheme_hash != NULL);
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_normalizer_normalize(from=\"%s\", tolen=%d)\n",
+ idn__debug_ucs4xstring(from, 50), (int)tolen));
+
+ if (ctx->nschemes <= 0) {
+ if (tolen < idn_ucs4_strlen(from) + 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ idn_ucs4_strcpy(to, from);
+ r = idn_success;
+ goto ret;
+ }
+
+ /*
+ * Normalize.
+ */
+ src = (void *)from;
+ dstlen = idn_ucs4_strlen(from) + 1;
+
+ i = 0;
+ while (i < ctx->nschemes) {
+ TRACE(("idn_normalizer_normalize(): normalize %s\n",
+ ctx->schemes[i]->name));
+
+ /*
+ * Choose destination area to restore the result of a mapping.
+ */
+ if (i + 1 == ctx->nschemes) {
+ dst = to;
+ dstlen = tolen;
+ } else {
+ if (src == buffers[0])
+ idx = 1;
+ else
+ idx = 0;
+
+ if (buflen[idx] < dstlen) {
+ void *newbuf;
+
+ newbuf = realloc(buffers[idx],
+ sizeof(long) * dstlen);
+ if (newbuf == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ buffers[idx] = (unsigned long *)newbuf;
+ buflen[idx] = dstlen;
+ }
+
+ dst = buffers[idx];
+ dstlen = buflen[idx];
+ }
+
+ /*
+ * Perform i-th normalization scheme.
+ * If buffer size is not enough, we double it and try again.
+ */
+ r = (ctx->schemes[i]->proc)(src, dst, dstlen);
+ if (r == idn_buffer_overflow && dst != to) {
+ dstlen *= 2;
+ continue;
+ }
+ if (r != idn_success)
+ goto ret;
+
+ src = dst;
+ i++;
+ }
+
+ r = idn_success;
+ret:
+ free(buffers[0]);
+ free(buffers[1]);
+ if (r == idn_success) {
+ TRACE(("idn_normalizer_normalize(): success (to=\"%s\")\n",
+ idn__debug_ucs4xstring(to, 50)));
+ } else {
+ TRACE(("idn_normalizer_normalize(): %s\n",
+ idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+idn_result_t
+idn_normalizer_register(const char *scheme_name, idn_normalizer_proc_t proc) {
+ idn_result_t r;
+ normalize_scheme_t *scheme;
+
+ assert(scheme_name != NULL && proc != NULL);
+
+ TRACE(("idn_normalizer_register(scheme_name=%s)\n", scheme_name));
+
+ assert(INITIALIZED);
+
+ scheme = malloc(sizeof(*scheme) + strlen(scheme_name) + 1);
+ if (scheme == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ scheme->name = (char *)(scheme + 1);
+ (void)strcpy(scheme->name, scheme_name);
+ scheme->proc = proc;
+
+ r = idn__strhash_put(scheme_hash, scheme_name, scheme);
+ if (r != idn_success)
+ goto ret;
+
+ r = idn_success;
+ret:
+ TRACE(("idn_normalizer_register(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+static idn_result_t
+expand_schemes(idn_normalizer_t ctx) {
+ normalize_scheme_t **new_schemes;
+ int new_size = ctx->scheme_size * 2;
+
+ if (ctx->schemes == ctx->local_buf) {
+ new_schemes = malloc(sizeof(normalize_scheme_t) * new_size);
+ } else {
+ new_schemes = realloc(ctx->schemes,
+ sizeof(normalize_scheme_t) * new_size);
+ }
+ if (new_schemes == NULL)
+ return (idn_nomemory);
+
+ if (ctx->schemes == ctx->local_buf)
+ memcpy(new_schemes, ctx->local_buf, sizeof(ctx->local_buf));
+
+ ctx->schemes = new_schemes;
+ ctx->scheme_size = new_size;
+
+ return (idn_success);
+}
+
+static idn_result_t
+register_standard_normalizers(void) {
+ int i;
+ int failed = 0;
+
+ for (i = 0; standard_normalizer[i].name != NULL; i++) {
+ idn_result_t r;
+ r = idn_normalizer_register(standard_normalizer[i].name,
+ standard_normalizer[i].proc);
+ if (r != idn_success) {
+ WARNING(("idn_normalizer_initialize(): "
+ "failed to register \"%-.100s\"\n",
+ standard_normalizer[i].name));
+ failed++;
+ }
+ }
+ if (failed > 0)
+ return (idn_failure);
+ else
+ return (idn_success);
+}
+
+/*
+ * Unicode Normalization Forms -- latest version
+ */
+
+static idn_result_t
+normalizer_formkc(const unsigned long *from, unsigned long *to, size_t tolen) {
+ INIT_VERSION(NULL, vcur);
+ return (idn__unormalize_formkc(vcur, from, to, tolen));
+}
+
+/*
+ * Unicode Normalization Forms -- version 3.2.0
+ */
+
+static idn_result_t
+normalizer_formkc_v320(const unsigned long *from, unsigned long *to,
+ size_t tolen) {
+ INIT_VERSION("3.2.0", v320);
+ return (idn__unormalize_formkc(v320, from, to, tolen));
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/punycode.c b/contrib/idn/idnkit-1.0-src/lib/punycode.c
new file mode 100644
index 0000000..d803af5
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/punycode.c
@@ -0,0 +1,434 @@
+#ifndef lint
+static char *rcsid = "$Id: punycode.c,v 1.1.1.1 2003/06/04 00:26:06 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/converter.h>
+#include <idn/ucs4.h>
+#include <idn/debug.h>
+#include <idn/punycode.h>
+#include <idn/util.h>
+
+/*
+ * Although draft-ietf-idn-punycode-00.txt doesn't specify the ACE
+ * signature, we have to choose one. In order to prevent the converted
+ * name from beginning with a hyphen, we should choose a prefix rather
+ * than a suffix.
+ */
+#ifndef IDN_PUNYCODE_PREFIX
+#define IDN_PUNYCODE_PREFIX "xn--"
+#endif
+
+#define INVALID_UCS 0x80000000
+#define MAX_UCS 0x10FFFF
+
+/*
+ * As the draft states, it is possible that `delta' may overflow during
+ * the encoding. The upper bound of 'delta' is:
+ * <# of chars. of input string> + <max. difference in code point> *
+ * <# of chars. of input string + 1>
+ * For this value not to be greater than 0xffffffff (since the calculation
+ * is done using unsigned long, which is at least 32bit long), the maxmum
+ * input string size is about 3850 characters, which is long enough for
+ * a domain label...
+ */
+#define PUNYCODE_MAXINPUT 3800
+
+/*
+ * Parameters.
+ */
+#define PUNYCODE_BASE 36
+#define PUNYCODE_TMIN 1
+#define PUNYCODE_TMAX 26
+#define PUNYCODE_SKEW 38
+#define PUNYCODE_DAMP 700
+#define PUNYCODE_INITIAL_BIAS 72
+#define PUNYCODE_INITIAL_N 0x80
+
+static int punycode_getwc(const char *s, size_t len,
+ int bias, unsigned long *vp);
+static int punycode_putwc(char *s, size_t len,
+ unsigned long delta, int bias);
+static int punycode_update_bias(unsigned long delta,
+ size_t npoints, int first);
+
+idn_result_t
+idn__punycode_decode(idn_converter_t ctx, void *privdata,
+ const char *from, unsigned long *to, size_t tolen) {
+ unsigned long *to_org = to;
+ unsigned long c, idx;
+ size_t prefixlen = strlen(IDN_PUNYCODE_PREFIX);
+ size_t fromlen;
+ size_t uidx, fidx, ucslen;
+ int first, bias;
+ idn_result_t r;
+
+ assert(ctx != NULL);
+
+ TRACE(("idn__punycode_decode(from=\"%s\", tolen=%d)\n",
+ idn__debug_xstring(from, 50), (int)tolen));
+
+ if (!idn__util_asciihaveaceprefix(from, IDN_PUNYCODE_PREFIX)) {
+ if (*from == '\0') {
+ r = idn_ucs4_utf8toucs4(from, to, tolen);
+ goto ret;
+ }
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+ from += prefixlen;
+ fromlen = strlen(from);
+
+ /*
+ * Find the last delimiter, and copy the characters
+ * before it verbatim.
+ */
+ ucslen = 0;
+ for (fidx = fromlen; fidx > 0; fidx--) {
+ if (from[fidx - 1] == '-') {
+ if (tolen < fidx) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ for (uidx = 0; uidx < fidx - 1; uidx++) {
+ to[uidx] = from[uidx];
+ }
+ ucslen = uidx;
+ break;
+ }
+ }
+
+ first = 1;
+ bias = PUNYCODE_INITIAL_BIAS;
+ c = PUNYCODE_INITIAL_N;
+ idx = 0;
+ while (fidx < fromlen) {
+ int len;
+ unsigned long delta;
+ int i;
+
+ len = punycode_getwc(from + fidx, fromlen - fidx, bias, &delta);
+ if (len == 0) {
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+ fidx += len;
+
+ bias = punycode_update_bias(delta, ucslen + 1, first);
+ first = 0;
+ idx += delta;
+ c += idx / (ucslen + 1);
+ uidx = idx % (ucslen + 1);
+
+ /* Insert 'c' at uidx. */
+ if (tolen-- <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ for (i = ucslen; i > uidx; i--)
+ to[i] = to[i - 1];
+ to[uidx] = c;
+
+ ucslen++;
+ idx = uidx + 1;
+ }
+
+ /* Terminate with NUL. */
+ if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ to[ucslen] = '\0';
+ r = idn_success;
+
+ret:
+ if (r == idn_success) {
+ TRACE(("idn__punycode_decode(): succcess (to=\"%s\")\n",
+ idn__debug_ucs4xstring(to_org, 50)));
+ } else {
+ TRACE(("idn__punycode_decode(): %s\n", idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+idn_result_t
+idn__punycode_encode(idn_converter_t ctx, void *privdata,
+ const unsigned long *from, char *to, size_t tolen) {
+ char *to_org = to;
+ unsigned long cur_code, next_code, delta;
+ size_t prefixlen = strlen(IDN_PUNYCODE_PREFIX);
+ size_t fromlen;
+ size_t ucsdone;
+ size_t toidx;
+ int uidx, bias, first;
+ idn_result_t r;
+
+ assert(ctx != NULL);
+
+ TRACE(("idn__punycode_encode(from=\"%s\", tolen=%d)\n",
+ idn__debug_ucs4xstring(from, 50), (int)tolen));
+
+ if (*from == '\0') {
+ r = idn_ucs4_ucs4toutf8(from, to, tolen);
+ goto ret;
+ } else if (idn__util_ucs4haveaceprefix(from, IDN_PUNYCODE_PREFIX)) {
+ r = idn_prohibited;
+ goto ret;
+ }
+
+ if (tolen < prefixlen) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ memcpy(to, IDN_PUNYCODE_PREFIX, prefixlen);
+ to += prefixlen;
+ tolen -= prefixlen;
+
+ fromlen = idn_ucs4_strlen(from);
+
+ /*
+ * If the input string is too long (actually too long to be sane),
+ * return failure in order to prevent possible overflow.
+ */
+ if (fromlen > PUNYCODE_MAXINPUT) {
+ ERROR(("idn__punycode_encode(): "
+ "the input string is too long to convert Punycode\n",
+ idn__debug_ucs4xstring(from, 50)));
+ r = idn_failure;
+ goto ret;
+ }
+
+ ucsdone = 0; /* number of characters processed */
+ toidx = 0;
+
+ /*
+ * First, pick up basic code points and copy them to 'to'.
+ */
+ for (uidx = 0; uidx < fromlen; uidx++) {
+ if (from[uidx] < 0x80) {
+ if (toidx >= tolen) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ to[toidx++] = from[uidx];
+ ucsdone++;
+ }
+ }
+
+ /*
+ * If there are any basic code points, output a delimiter
+ * (hyphen-minus).
+ */
+ if (toidx > 0) {
+ if (toidx >= tolen) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ to[toidx++] = '-';
+ to += toidx;
+ tolen -= toidx;
+ }
+
+ /*
+ * Then encode non-basic characters.
+ */
+ first = 1;
+ cur_code = PUNYCODE_INITIAL_N;
+ bias = PUNYCODE_INITIAL_BIAS;
+ delta = 0;
+ while (ucsdone < fromlen) {
+ int limit = -1, rest;
+
+ /*
+ * Find the smallest code point equal to or greater
+ * than 'cur_code'. Also remember the index of the
+ * last occurence of the code point.
+ */
+ for (next_code = MAX_UCS, uidx = fromlen - 1;
+ uidx >= 0; uidx--) {
+ if (from[uidx] >= cur_code && from[uidx] < next_code) {
+ next_code = from[uidx];
+ limit = uidx;
+ }
+ }
+ /* There must be such code point. */
+ assert(limit >= 0);
+
+ delta += (next_code - cur_code) * (ucsdone + 1);
+ cur_code = next_code;
+
+ /*
+ * Scan the input string again, and encode characters
+ * whose code point is 'cur_code'. Use 'limit' to avoid
+ * unnecessary scan.
+ */
+ for (uidx = 0, rest = ucsdone; uidx <= limit; uidx++) {
+ if (from[uidx] < cur_code) {
+ delta++;
+ rest--;
+ } else if (from[uidx] == cur_code) {
+ int sz = punycode_putwc(to, tolen, delta, bias);
+ if (sz == 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ to += sz;
+ tolen -= sz;
+ ucsdone++;
+ bias = punycode_update_bias(delta, ucsdone,
+ first);
+ delta = 0;
+ first = 0;
+ }
+ }
+ delta += rest + 1;
+ cur_code++;
+ }
+
+ /*
+ * Terminate with NUL.
+ */
+ if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *to = '\0';
+ r = idn_success;
+
+ret:
+ if (r == idn_success) {
+ TRACE(("idn__punycode_encode(): succcess (to=\"%s\")\n",
+ idn__debug_xstring(to_org, 50)));
+ } else {
+ TRACE(("idn__punycode_encode(): %s\n", idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+static int
+punycode_getwc(const char *s, size_t len, int bias, unsigned long *vp) {
+ size_t orglen = len;
+ unsigned long v = 0, w = 1;
+ int k;
+
+ for (k = PUNYCODE_BASE - bias; len > 0; k += PUNYCODE_BASE) {
+ int c = *s++;
+ int t = (k < PUNYCODE_TMIN) ? PUNYCODE_TMIN :
+ (k > PUNYCODE_TMAX) ? PUNYCODE_TMAX : k;
+
+ len--;
+ if ('a' <= c && c <= 'z')
+ c = c - 'a';
+ else if ('A' <= c && c <= 'Z')
+ c = c - 'A';
+ else if ('0' <= c && c <= '9')
+ c = c - '0' + 26;
+ else
+ c = -1;
+
+ if (c < 0)
+ return (0); /* invalid character */
+
+ v += c * w;
+
+ if (c < t) {
+ *vp = v;
+ return (orglen - len);
+ }
+
+ w *= (PUNYCODE_BASE - t);
+ }
+
+ return (0); /* final character missing */
+}
+
+static int
+punycode_putwc(char *s, size_t len, unsigned long delta, int bias) {
+ const char *punycode_base36 = "abcdefghijklmnopqrstuvwxyz0123456789";
+ int k;
+ char *sorg = s;
+
+ for (k = PUNYCODE_BASE - bias; 1; k += PUNYCODE_BASE) {
+ int t = (k < PUNYCODE_TMIN) ? PUNYCODE_TMIN :
+ (k > PUNYCODE_TMAX) ? PUNYCODE_TMAX : k;
+
+ if (delta < t)
+ break;
+ if (len < 1)
+ return (0);
+ *s++ = punycode_base36[t + ((delta - t) % (PUNYCODE_BASE - t))];
+ len--;
+ delta = (delta - t) / (PUNYCODE_BASE - t);
+ }
+ if (len < 1)
+ return (0);
+ *s++ = punycode_base36[delta];
+ return (s - sorg);
+}
+
+static int
+punycode_update_bias(unsigned long delta, size_t npoints, int first) {
+ int k = 0;
+
+ delta /= first ? PUNYCODE_DAMP : 2;
+ delta += delta / npoints;
+
+ while (delta > ((PUNYCODE_BASE - PUNYCODE_TMIN) * PUNYCODE_TMAX) / 2) {
+ delta /= PUNYCODE_BASE - PUNYCODE_TMIN;
+ k++;
+ }
+ return (PUNYCODE_BASE * k +
+ (((PUNYCODE_BASE - PUNYCODE_TMIN + 1) * delta) /
+ (delta + PUNYCODE_SKEW)));
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/race.c b/contrib/idn/idnkit-1.0-src/lib/race.c
new file mode 100644
index 0000000..1b44a98
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/race.c
@@ -0,0 +1,427 @@
+#ifndef lint
+static char *rcsid = "$Id: race.c,v 1.1.1.1 2003/06/04 00:26:07 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/converter.h>
+#include <idn/ucs4.h>
+#include <idn/debug.h>
+#include <idn/race.h>
+#include <idn/util.h>
+
+#ifndef IDN_RACE_PREFIX
+#define IDN_RACE_PREFIX "bq--"
+#endif
+#define RACE_2OCTET_MODE 0xd8
+#define RACE_ESCAPE 0xff
+#define RACE_ESCAPE_2ND 0x99
+
+#define RACE_BUF_SIZE 128 /* more than enough */
+
+/*
+ * Unicode surrogate pair.
+ */
+#define IS_SURROGATE_HIGH(v) (0xd800 <= (v) && (v) <= 0xdbff)
+#define IS_SURROGATE_LOW(v) (0xdc00 <= (v) && (v) <= 0xdfff)
+#define SURROGATE_HIGH(v) (SURROGATE_H_OFF + (((v) - 0x10000) >> 10))
+#define SURROGATE_LOW(v) (SURROGATE_L_OFF + ((v) & 0x3ff))
+#define SURROGATE_BASE 0x10000
+#define SURROGATE_H_OFF 0xd800
+#define SURROGATE_L_OFF 0xdc00
+#define COMBINE_SURROGATE(h, l) \
+ (SURROGATE_BASE + (((h)-SURROGATE_H_OFF)<<10) + ((l)-SURROGATE_L_OFF))
+
+/*
+ * Compression type.
+ */
+enum {
+ compress_one, /* all characters are in a single row */
+ compress_two, /* row 0 and another row */
+ compress_none /* nope */
+};
+
+static idn_result_t race_decode_decompress(const char *from,
+ unsigned short *buf,
+ size_t buflen);
+static idn_result_t race_compress_encode(const unsigned short *p,
+ int compress_mode,
+ char *to, size_t tolen);
+static int get_compress_mode(unsigned short *p);
+
+idn_result_t
+idn__race_decode(idn_converter_t ctx, void *privdata,
+ const char *from, unsigned long *to, size_t tolen) {
+ unsigned short *buf = NULL;
+ size_t prefixlen = strlen(IDN_RACE_PREFIX);
+ size_t fromlen;
+ size_t buflen;
+ idn_result_t r;
+
+ assert(ctx != NULL);
+
+ TRACE(("idn__race_decode(from=\"%s\", tolen=%d)\n",
+ idn__debug_xstring(from, 50), (int)tolen));
+
+ if (!idn__util_asciihaveaceprefix(from, IDN_RACE_PREFIX)) {
+ if (*from == '\0') {
+ r = idn_ucs4_utf8toucs4(from, to, tolen);
+ goto ret;
+ }
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+ from += prefixlen;
+ fromlen = strlen(from);
+
+ /*
+ * Allocate sufficient buffer.
+ */
+ buflen = fromlen + 1;
+ buf = malloc(sizeof(*buf) * buflen);
+ if (buf == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ /*
+ * Decode base32 and decompress.
+ */
+ r = race_decode_decompress(from, buf, buflen);
+ if (r != idn_success)
+ goto ret;
+
+ /*
+ * Now 'buf' points the decompressed string, which must contain
+ * UTF-16 characters.
+ */
+
+ /*
+ * Convert to UCS4.
+ */
+ r = idn_ucs4_utf16toucs4(buf, to, tolen);
+ if (r != idn_success)
+ goto ret;
+
+ret:
+ free(buf);
+ if (r == idn_success) {
+ TRACE(("idn__race_decode(): succcess (to=\"%s\")\n",
+ idn__debug_ucs4xstring(to, 50)));
+ } else {
+ TRACE(("idn__race_decode(): %s\n", idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+static idn_result_t
+race_decode_decompress(const char *from, unsigned short *buf, size_t buflen)
+{
+ unsigned short *p = buf;
+ unsigned int bitbuf = 0;
+ int bitlen = 0;
+ int i, j;
+ size_t len;
+
+ while (*from != '\0') {
+ int c = *from++;
+ int x;
+
+ if ('a' <= c && c <= 'z')
+ x = c - 'a';
+ else if ('A' <= c && c <= 'Z')
+ x = c - 'A';
+ else if ('2' <= c && c <= '7')
+ x = c - '2' + 26;
+ else
+ return (idn_invalid_encoding);
+
+ bitbuf = (bitbuf << 5) + x;
+ bitlen += 5;
+ if (bitlen >= 8) {
+ *p++ = (bitbuf >> (bitlen - 8)) & 0xff;
+ bitlen -= 8;
+ }
+ }
+ len = p - buf;
+
+ /*
+ * Now 'buf' holds the decoded string.
+ */
+
+ /*
+ * Decompress.
+ */
+ if (buf[0] == RACE_2OCTET_MODE) {
+ if ((len - 1) % 2 != 0)
+ return (idn_invalid_encoding);
+ for (i = 1, j = 0; i < len; i += 2, j++)
+ buf[j] = (buf[i] << 8) + buf[i + 1];
+ len = j;
+ } else {
+ unsigned short c = buf[0] << 8; /* higher octet */
+
+ for (i = 1, j = 0; i < len; j++) {
+ if (buf[i] == RACE_ESCAPE) {
+ if (i + 1 >= len)
+ return (idn_invalid_encoding);
+ else if (buf[i + 1] == RACE_ESCAPE_2ND)
+ buf[j] = c | 0xff;
+ else
+ buf[j] = buf[i + 1];
+ i += 2;
+
+ } else if (buf[i] == 0x99 && c == 0x00) {
+ /*
+ * The RACE specification says this is error.
+ */
+ return (idn_invalid_encoding);
+
+ } else {
+ buf[j] = c | buf[i++];
+ }
+ }
+ len = j;
+ }
+ buf[len] = '\0';
+
+ return (idn_success);
+}
+
+idn_result_t
+idn__race_encode(idn_converter_t ctx, void *privdata,
+ const unsigned long *from, char *to, size_t tolen) {
+ char *to_org = to;
+ unsigned short *p, *buf = NULL;
+ size_t prefixlen = strlen(IDN_RACE_PREFIX);
+ size_t buflen;
+ size_t fromlen;
+ idn_result_t r;
+ int compress_mode;
+
+ assert(ctx != NULL);
+
+ TRACE(("idn__race_encode(from=\"%s\", tolen=%d)\n",
+ idn__debug_ucs4xstring(from, 50), (int)tolen));
+
+ if (*from == '\0') {
+ r = idn_ucs4_ucs4toutf8(from, to, tolen);
+ goto ret;
+ } else if (idn__util_ucs4haveaceprefix(from, IDN_RACE_PREFIX)) {
+ r = idn_prohibited;
+ goto ret;
+ }
+
+ if (tolen < prefixlen) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ memcpy(to, IDN_RACE_PREFIX, prefixlen);
+ to += prefixlen;
+ tolen -= prefixlen;
+
+ fromlen = idn_ucs4_strlen(from);
+ buflen = fromlen * 2 + 2;
+
+ /*
+ * Convert to UTF-16.
+ * Preserve space for a character at the top of the buffer.
+ */
+ for (;;) {
+ unsigned short *new_buf;
+
+ new_buf = realloc(buf, sizeof(*buf) * buflen);
+ if (new_buf == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ buf = new_buf;
+
+ r = idn_ucs4_ucs4toutf16(from, buf + 1, buflen - 1);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+
+ buflen = fromlen * 2 + 2;
+ }
+ p = buf + 1;
+
+ /*
+ * Now 'p' contains UTF-16 encoded string.
+ */
+
+ /*
+ * Check U+0099.
+ * RACE doesn't permit U+0099 in an input string.
+ */
+ for (p = buf + 1; *p != '\0'; p++) {
+ if (*p == 0x0099) {
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+ }
+
+ /*
+ * Compress, encode in base-32 and output.
+ */
+ compress_mode = get_compress_mode(buf + 1);
+ r = race_compress_encode(buf, compress_mode, to, tolen);
+
+ret:
+ free(buf);
+ if (r == idn_success) {
+ TRACE(("idn__race_encode(): succcess (to=\"%s\")\n",
+ idn__debug_xstring(to_org, 50)));
+ } else {
+ TRACE(("idn__race_encode(): %s\n", idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+static idn_result_t
+race_compress_encode(const unsigned short *p, int compress_mode,
+ char *to, size_t tolen)
+{
+ unsigned long bitbuf = *p++; /* bit stream buffer */
+ int bitlen = 8; /* # of bits in 'bitbuf' */
+
+ while (*p != '\0' || bitlen > 0) {
+ unsigned int c = *p;
+
+ if (c == '\0') {
+ /* End of data. Flush. */
+ bitbuf <<= (5 - bitlen);
+ bitlen = 5;
+ } else if (compress_mode == compress_none) {
+ /* Push 16 bit data. */
+ bitbuf = (bitbuf << 16) | c;
+ bitlen += 16;
+ p++;
+ } else {/* compress_mode == compress_one/compress_two */
+ /* Push 8 or 16 bit data. */
+ if (compress_mode == compress_two &&
+ (c & 0xff00) == 0) {
+ /* Upper octet is zero (and not U1). */
+ bitbuf = (bitbuf << 16) | 0xff00 | c;
+ bitlen += 16;
+ } else if ((c & 0xff) == 0xff) {
+ /* Lower octet is 0xff. */
+ bitbuf = (bitbuf << 16) |
+ (RACE_ESCAPE << 8) | RACE_ESCAPE_2ND;
+ bitlen += 16;
+ } else {
+ /* Just output lower octet. */
+ bitbuf = (bitbuf << 8) | (c & 0xff);
+ bitlen += 8;
+ }
+ p++;
+ }
+
+ /*
+ * Output bits in 'bitbuf' in 5-bit unit.
+ */
+ while (bitlen >= 5) {
+ int x;
+
+ /* Get top 5 bits. */
+ x = (bitbuf >> (bitlen - 5)) & 0x1f;
+ bitlen -= 5;
+
+ /* Encode. */
+ if (x < 26)
+ x += 'a';
+ else
+ x = (x - 26) + '2';
+
+ if (tolen < 1)
+ return (idn_buffer_overflow);
+
+ *to++ = x;
+ tolen--;
+ }
+ }
+
+ if (tolen <= 0)
+ return (idn_buffer_overflow);
+
+ *to = '\0';
+ return (idn_success);
+}
+
+static int
+get_compress_mode(unsigned short *p) {
+ int zero = 0;
+ unsigned int upper = 0;
+ unsigned short *modepos = p - 1;
+
+ while (*p != '\0') {
+ unsigned int hi = *p++ & 0xff00;
+
+ if (hi == 0) {
+ zero++;
+ } else if (hi == upper) {
+ ;
+ } else if (upper == 0) {
+ upper = hi;
+ } else {
+ *modepos = RACE_2OCTET_MODE;
+ return (compress_none);
+ }
+ }
+ *modepos = upper >> 8;
+ if (upper > 0 && zero > 0)
+ return (compress_two);
+ else
+ return (compress_one);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/res.c b/contrib/idn/idnkit-1.0-src/lib/res.c
new file mode 100644
index 0000000..cefd0c3
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/res.c
@@ -0,0 +1,1726 @@
+#ifndef lint
+static char *rcsid = "$Id: res.c,v 1.1.1.1 2003/06/04 00:26:10 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/converter.h>
+#include <idn/normalizer.h>
+#include <idn/checker.h>
+#include <idn/mapper.h>
+#include <idn/mapselector.h>
+#include <idn/delimitermap.h>
+#include <idn/resconf.h>
+#include <idn/res.h>
+#include <idn/util.h>
+#include <idn/debug.h>
+#include <idn/ucs4.h>
+
+#ifndef IDN_UTF8_ENCODING_NAME
+#define IDN_UTF8_ENCODING_NAME "UTF-8" /* by IANA */
+#endif
+
+#ifndef WITHOUT_ICONV
+#define ENCODE_MASK \
+ (IDN_LOCALCONV | IDN_DELIMMAP | IDN_LOCALMAP | IDN_MAP | \
+ IDN_NORMALIZE | IDN_PROHCHECK | IDN_UNASCHECK | IDN_BIDICHECK | \
+ IDN_ASCCHECK | IDN_IDNCONV | IDN_LENCHECK | IDN_ENCODE_QUERY | \
+ IDN_UNDOIFERR)
+#define DECODE_MASK \
+ (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | IDN_PROHCHECK | \
+ IDN_UNASCHECK | IDN_BIDICHECK | IDN_IDNCONV | IDN_ASCCHECK | \
+ IDN_RTCHECK | IDN_LOCALCONV | IDN_DECODE_QUERY)
+#else
+#define ENCODE_MASK \
+ (IDN_DELIMMAP | IDN_LOCALMAP | IDN_MAP | IDN_NORMALIZE | \
+ IDN_PROHCHECK | IDN_UNASCHECK | IDN_BIDICHECK | IDN_ASCCHECK | \
+ IDN_IDNCONV | IDN_LENCHECK | IDN_ENCODE_QUERY | IDN_UNDOIFERR)
+#define DECODE_MASK \
+ (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | IDN_PROHCHECK | \
+ IDN_UNASCHECK | IDN_BIDICHECK | IDN_IDNCONV | IDN_ASCCHECK | \
+ IDN_RTCHECK | IDN_DECODE_QUERY)
+#endif
+
+#define MAX_LABEL_LENGTH 63
+
+/*
+ * label to convert.
+ */
+typedef struct labellist * labellist_t;
+struct labellist {
+ unsigned long *name;
+ size_t name_length;
+ unsigned long *undo_name;
+ labellist_t next;
+ labellist_t previous;
+ int dot_followed;
+};
+
+typedef idn_result_t (*res_insnproc_t)(idn_resconf_t ctx,
+ labellist_t label);
+
+static void idn_res_initialize(void);
+static idn_result_t copy_verbatim(const char *from, char *to,
+ size_t tolen);
+static idn_result_t labellist_create(const unsigned long *name,
+ labellist_t *labelp);
+static void labellist_destroy(labellist_t label);
+static idn_result_t labellist_setname(labellist_t label,
+ const unsigned long *name);
+static const unsigned long *
+ labellist_getname(labellist_t label);
+static const unsigned long *
+ labellist_gettldname(labellist_t label);
+static idn_result_t labellist_getnamelist(labellist_t label,
+ unsigned long *name,
+ size_t label_length);
+static void labellist_undo(labellist_t label);
+static labellist_t labellist_tail(labellist_t label);
+static labellist_t labellist_previous(labellist_t label);
+
+#ifndef WITHOUT_ICONV
+static idn_result_t label_localdecodecheck(idn_resconf_t ctx,
+ labellist_t label);
+#endif
+static idn_result_t label_idnencode_ace(idn_resconf_t ctx,
+ labellist_t label);
+static idn_result_t label_idndecode(idn_resconf_t ctx, labellist_t label);
+static idn_result_t label_localmap(idn_resconf_t ctx, labellist_t label);
+static idn_result_t label_map(idn_resconf_t ctx, labellist_t label);
+static idn_result_t label_normalize(idn_resconf_t ctx, labellist_t label);
+static idn_result_t label_prohcheck(idn_resconf_t ctx, labellist_t label);
+static idn_result_t label_unascheck(idn_resconf_t ctx, labellist_t label);
+static idn_result_t label_bidicheck(idn_resconf_t ctx, labellist_t label);
+static idn_result_t label_asccheck(idn_resconf_t ctx, labellist_t label);
+static idn_result_t label_lencheck_ace(idn_resconf_t ctx,
+ labellist_t label);
+static idn_result_t label_lencheck_nonace(idn_resconf_t ctx,
+ labellist_t label);
+static idn_result_t label_rtcheck(idn_resconf_t ctx, idn_action_t actions,
+ labellist_t label,
+ const unsigned long *original_name);
+
+static int initialized;
+static int enabled;
+
+void
+idn_res_enable(int on_off) {
+ if (!initialized) {
+ idn_res_initialize();
+ }
+
+ if (on_off == 0) {
+ enabled = 0;
+ } else {
+ enabled = 1;
+ }
+}
+
+static void
+idn_res_initialize(void) {
+ if (!initialized) {
+ char *value = getenv("IDN_DISABLE");
+
+ if (value == NULL) {
+ enabled = 1;
+ } else {
+ enabled = 0;
+ }
+ initialized = 1;
+ }
+}
+
+idn_result_t
+idn_res_encodename(idn_resconf_t ctx, idn_action_t actions, const char *from,
+ char *to, size_t tolen) {
+ idn_converter_t local_converter = NULL;
+ idn_converter_t idn_converter = NULL;
+ idn_delimitermap_t delimiter_mapper;
+ idn_result_t r;
+ labellist_t labels = NULL, l;
+ unsigned long *buffer = NULL;
+ size_t buffer_length;
+ int from_is_root;
+ int idn_is_ace;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_res_encodename(actions=%s, from=\"%s\", tolen=%d)\n",
+ idn__res_actionstostring(actions),
+ idn__debug_xstring(from, 50), (int)tolen));
+
+ if (actions & ~ENCODE_MASK) {
+ WARNING(("idn_res_encodename: invalid actions 0x%x\n",
+ actions));
+ r = idn_invalid_action;
+ goto ret;
+ }
+
+ if (!initialized)
+ idn_res_initialize();
+ if (!enabled || actions == 0) {
+ r = copy_verbatim(from, to, tolen);
+ goto ret;
+ } else if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+
+ if (actions & IDN_ENCODE_QUERY) {
+#ifndef WITHOUT_ICONV
+ actions |= (IDN_LOCALCONV | IDN_DELIMMAP | IDN_LOCALMAP | \
+ IDN_MAP | IDN_NORMALIZE | IDN_PROHCHECK | \
+ IDN_BIDICHECK | IDN_IDNCONV | IDN_LENCHECK);
+#else
+ actions |= (IDN_DELIMMAP | IDN_LOCALMAP | IDN_MAP | \
+ IDN_NORMALIZE | IDN_PROHCHECK | IDN_BIDICHECK | \
+ IDN_IDNCONV | IDN_LENCHECK);
+#endif
+ }
+
+ /*
+ * Convert `from' to UCS4.
+ */
+ local_converter = idn_resconf_getlocalconverter(ctx);
+#ifndef WITHOUT_ICONV
+ if (local_converter == NULL) {
+ r = idn_invalid_name;
+ goto ret;
+ }
+#endif
+
+ idn_converter = idn_resconf_getidnconverter(ctx);
+ if (idn_converter != NULL &&
+ idn_converter_isasciicompatible(idn_converter))
+ idn_is_ace = 1;
+ else
+ idn_is_ace = 0;
+
+ buffer_length = tolen * 2;
+
+ for (;;) {
+ void *new_buffer;
+
+ new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ buffer = (unsigned long *)new_buffer;
+
+ if (actions & IDN_LOCALCONV) {
+ r = idn_converter_convtoucs4(local_converter, from,
+ buffer, buffer_length);
+ } else {
+ r = idn_ucs4_utf8toucs4(from, buffer, buffer_length);
+ }
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+
+ buffer_length *= 2;
+ }
+
+ if (*buffer == '\0') {
+ if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *to = '\0';
+ r = idn_success;
+ goto ret;
+ }
+
+ /*
+ * Delimiter map.
+ */
+ if (actions & IDN_DELIMMAP) {
+ TRACE(("res delimitermap(name=\"%s\")\n",
+ idn__debug_ucs4xstring(buffer, 50)));
+
+ delimiter_mapper = idn_resconf_getdelimitermap(ctx);
+ if (delimiter_mapper != NULL) {
+ r = idn_delimitermap_map(delimiter_mapper, buffer,
+ buffer, buffer_length);
+ idn_delimitermap_destroy(delimiter_mapper);
+ if (r != idn_success)
+ goto ret;
+ }
+ TRACE(("res delimitermap(): success (name=\"%s\")\n",
+ idn__debug_ucs4xstring(buffer, 50)));
+ }
+
+ from_is_root = (buffer[0] == '.' && buffer[1] == '\0');
+
+ /*
+ * Split the name into a list of labels.
+ */
+ r = labellist_create(buffer, &labels);
+ if (r != idn_success)
+ goto ret;
+
+ /*
+ * Perform conversions and tests.
+ */
+ for (l = labellist_tail(labels); l != NULL;
+ l = labellist_previous(l)) {
+
+ if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
+ if (actions & IDN_LOCALMAP) {
+ r = label_localmap(ctx, l);
+ if (r != idn_success)
+ goto ret;
+ }
+ }
+
+ if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
+ if (actions & IDN_MAP) {
+ r = label_map(ctx, l);
+ if (r != idn_success)
+ goto ret;
+ }
+ if (actions & IDN_NORMALIZE) {
+ r = label_normalize(ctx, l);
+ if (r != idn_success)
+ goto ret;
+ }
+ if (actions & IDN_PROHCHECK) {
+ r = label_prohcheck(ctx, l);
+ if (r == idn_prohibited &&
+ (actions & IDN_UNDOIFERR)) {
+ labellist_undo(l);
+ continue;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ }
+ if (actions & IDN_UNASCHECK) {
+ r = label_unascheck(ctx, l);
+ if (r == idn_prohibited &&
+ (actions & IDN_UNDOIFERR)) {
+ labellist_undo(l);
+ continue;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ }
+ if (actions & IDN_BIDICHECK) {
+ r = label_bidicheck(ctx, l);
+ if (r == idn_prohibited &&
+ (actions & IDN_UNDOIFERR)) {
+ labellist_undo(l);
+ continue;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ }
+ }
+
+ if (actions & IDN_ASCCHECK) {
+ r = label_asccheck(ctx, l);
+ if (r == idn_prohibited && (actions & IDN_UNDOIFERR)) {
+ labellist_undo(l);
+ continue;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ }
+
+ if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
+ if ((actions & IDN_IDNCONV) && idn_is_ace) {
+ r = label_idnencode_ace(ctx, l);
+ if (r != idn_success)
+ goto ret;
+ }
+ }
+
+ if (!from_is_root && (actions & IDN_LENCHECK)) {
+ if (idn_is_ace)
+ r = label_lencheck_ace(ctx, l);
+ else
+ r = label_lencheck_nonace(ctx, l);
+ if (r == idn_invalid_length &&
+ (actions & IDN_UNDOIFERR)) {
+ labellist_undo(l);
+ continue;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ }
+ }
+
+ /*
+ * Concat a list of labels to a name.
+ */
+ for (;;) {
+ void *new_buffer;
+
+ new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ buffer = (unsigned long *)new_buffer;
+
+ r = labellist_getnamelist(labels, buffer, buffer_length);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+
+ buffer_length *= 2;
+ }
+
+ if ((actions & IDN_IDNCONV) && idn_converter != NULL && !idn_is_ace) {
+ r = idn_converter_convfromucs4(idn_converter, buffer, to,
+ tolen);
+ } else {
+ r = idn_ucs4_ucs4toutf8(buffer, to, tolen);
+ }
+
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_res_encodename(): success (to=\"%s\")\n",
+ idn__debug_xstring(to, 50)));
+ } else {
+ TRACE(("idn_res_encodename(): %s\n", idn_result_tostring(r)));
+ }
+ free(buffer);
+ if (local_converter != NULL)
+ idn_converter_destroy(local_converter);
+ if (idn_converter != NULL)
+ idn_converter_destroy(idn_converter);
+ if (labels != NULL)
+ labellist_destroy(labels);
+ return (r);
+}
+
+idn_result_t
+idn_res_decodename(idn_resconf_t ctx, idn_action_t actions, const char *from,
+ char *to, size_t tolen) {
+ idn_converter_t local_converter = NULL;
+ idn_converter_t idn_converter = NULL;
+ idn_delimitermap_t delimiter_mapper;
+ idn_result_t r;
+ labellist_t labels = NULL, l;
+ unsigned long *buffer = NULL;
+ unsigned long *saved_name = NULL;
+ size_t buffer_length;
+ int idn_is_ace;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_res_decodename(actions=%s, from=\"%s\", tolen=%d)\n",
+ idn__res_actionstostring(actions),
+ idn__debug_xstring(from, 50), (int)tolen));
+
+ if (actions & ~DECODE_MASK) {
+ WARNING(("idn_res_decodename: invalid actions 0x%x\n",
+ actions));
+ r = idn_invalid_action;
+ goto ret;
+ }
+
+ if (!initialized)
+ idn_res_initialize();
+ if (!enabled || actions == 0) {
+ r = copy_verbatim(from, to, tolen);
+ goto ret;
+ } else if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+
+ if (actions & IDN_DECODE_QUERY) {
+#ifndef WITHOUT_ICONV
+ actions |= (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | \
+ IDN_PROHCHECK | IDN_BIDICHECK | IDN_IDNCONV | \
+ IDN_RTCHECK | IDN_LOCALCONV);
+#else
+ actions |= (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | \
+ IDN_PROHCHECK | IDN_BIDICHECK | IDN_IDNCONV | \
+ IDN_RTCHECK);
+#endif
+ }
+
+ /*
+ * Convert `from' to UCS4.
+ */
+ local_converter = idn_resconf_getlocalconverter(ctx);
+#ifndef WITHOUT_ICONV
+ if (local_converter == NULL) {
+ r = idn_invalid_name;
+ goto ret;
+ }
+#endif
+
+ idn_converter = idn_resconf_getidnconverter(ctx);
+ if (idn_converter != NULL &&
+ idn_converter_isasciicompatible(idn_converter))
+ idn_is_ace = 1;
+ else
+ idn_is_ace = 0;
+
+ buffer_length = tolen * 2;
+
+ TRACE(("res idndecode(name=\"%s\")\n", idn__debug_xstring(from, 50)));
+
+ for (;;) {
+ void *new_buffer;
+
+ new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ buffer = (unsigned long *)new_buffer;
+
+ if ((actions & IDN_IDNCONV) &&
+ idn_converter != NULL && !idn_is_ace) {
+ r = idn_converter_convtoucs4(idn_converter, from,
+ buffer, buffer_length);
+ } else {
+ r = idn_ucs4_utf8toucs4(from, buffer, buffer_length);
+ }
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+
+ buffer_length *= 2;
+ }
+
+ if (*buffer == '\0') {
+ if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *to = '\0';
+ r = idn_success;
+ goto ret;
+ }
+
+ /*
+ * Delimiter map.
+ */
+ if (actions & IDN_DELIMMAP) {
+ TRACE(("res delimitermap(name=\"%s\")\n",
+ idn__debug_ucs4xstring(buffer, 50)));
+
+ delimiter_mapper = idn_resconf_getdelimitermap(ctx);
+ if (delimiter_mapper != NULL) {
+ r = idn_delimitermap_map(delimiter_mapper, buffer,
+ buffer, buffer_length);
+ idn_delimitermap_destroy(delimiter_mapper);
+ if (r != idn_success)
+ goto ret;
+ }
+ TRACE(("res delimitermap(): success (name=\"%s\")\n",
+ idn__debug_ucs4xstring(buffer, 50)));
+ }
+
+ /*
+ * Split the name into a list of labels.
+ */
+ r = labellist_create(buffer, &labels);
+ if (r != idn_success)
+ goto ret;
+
+ /*
+ * Perform conversions and tests.
+ */
+ for (l = labellist_tail(labels); l != NULL;
+ l = labellist_previous(l)) {
+
+ free(saved_name);
+ saved_name = NULL;
+
+ if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
+ if (actions & IDN_MAP) {
+ r = label_map(ctx, l);
+ if (r != idn_success)
+ goto ret;
+ }
+ if (actions & IDN_NORMALIZE) {
+ r = label_normalize(ctx, l);
+ if (r != idn_success)
+ goto ret;
+ }
+ if (actions & IDN_PROHCHECK) {
+ r = label_prohcheck(ctx, l);
+ if (r == idn_prohibited) {
+ labellist_undo(l);
+ continue;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ }
+ if (actions & IDN_UNASCHECK) {
+ r = label_unascheck(ctx, l);
+ if (r == idn_prohibited) {
+ labellist_undo(l);
+ continue;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ }
+ if (actions & IDN_BIDICHECK) {
+ r = label_bidicheck(ctx, l);
+ if (r == idn_prohibited) {
+ labellist_undo(l);
+ continue;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ }
+ }
+
+ if ((actions & IDN_IDNCONV) && idn_is_ace) {
+ saved_name = idn_ucs4_strdup(labellist_getname(l));
+ if (saved_name == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ r = label_idndecode(ctx, l);
+ if (r == idn_invalid_encoding) {
+ labellist_undo(l);
+ continue;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ }
+ if ((actions & IDN_RTCHECK) && saved_name != NULL) {
+ r = label_rtcheck(ctx, actions, l, saved_name);
+ if (r == idn_invalid_encoding) {
+ labellist_undo(l);
+ continue;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ }
+
+#ifndef WITHOUT_ICONV
+ if (actions & IDN_LOCALCONV) {
+ r = label_localdecodecheck(ctx, l);
+ if (r != idn_success)
+ goto ret;
+ }
+#endif
+ }
+
+ /*
+ * Concat a list of labels to a name.
+ */
+ for (;;) {
+ void *new_buffer;
+
+ new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ buffer = (unsigned long *)new_buffer;
+
+ r = labellist_getnamelist(labels, buffer, buffer_length);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+
+ buffer_length *= 2;
+ }
+
+ if (actions & IDN_LOCALCONV) {
+ r = idn_converter_convfromucs4(local_converter, buffer, to,
+ tolen);
+ } else {
+ r = idn_ucs4_ucs4toutf8(buffer, to, tolen);
+ }
+
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_res_decodename(): success (to=\"%s\")\n",
+ idn__debug_xstring(to, 50)));
+ } else {
+ TRACE(("idn_res_decodename(): %s\n", idn_result_tostring(r)));
+ }
+ free(saved_name);
+ free(buffer);
+ if (local_converter != NULL)
+ idn_converter_destroy(local_converter);
+ if (idn_converter != NULL)
+ idn_converter_destroy(idn_converter);
+ if (labels != NULL)
+ labellist_destroy(labels);
+ return (r);
+}
+
+idn_result_t
+idn_res_decodename2(idn_resconf_t ctx, idn_action_t actions, const char *from,
+ char *to, size_t tolen, const char *auxencoding) {
+#ifdef WITHOUT_ICONV
+ return idn_failure;
+
+#else /* WITHOUT_ICONV */
+ idn_result_t r;
+ idn_converter_t aux_converter = NULL;
+ unsigned long *buffer_ucs4 = NULL;
+ char *buffer_utf8 = NULL;
+ size_t buffer_length;
+
+ assert(ctx != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_res_decodename2(actions=%s, from=\"%s\", tolen=%d, "
+ "auxencoding=\"%s\")\n",
+ idn__res_actionstostring(actions),
+ idn__debug_xstring(from, 50), (int)tolen,
+ (auxencoding != NULL) ? auxencoding : "<null>"));
+
+ if (!initialized)
+ idn_res_initialize();
+ if (!enabled || actions == 0) {
+ r = copy_verbatim(from, to, tolen);
+ goto ret;
+ } else if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+
+ if (auxencoding == NULL ||
+ strcmp(auxencoding, IDN_UTF8_ENCODING_NAME) == 0 ||
+ strcmp(auxencoding, "UTF-8") == 0) {
+ return idn_res_decodename(ctx, actions, from, to, tolen);
+ }
+
+ /*
+ * Convert `from' to UCS4.
+ */
+ r = idn_resconf_setauxidnconvertername(ctx, auxencoding,
+ IDN_CONVERTER_DELAYEDOPEN);
+ if (r != idn_success) {
+ goto ret;
+ }
+
+ aux_converter = idn_resconf_getauxidnconverter(ctx);
+ if (aux_converter == NULL) {
+ r = idn_failure;
+ goto ret;
+ }
+
+ buffer_length = tolen * 2;
+ for (;;) {
+ void *new_buffer;
+
+ new_buffer = realloc(buffer_ucs4,
+ sizeof(*buffer_ucs4) * buffer_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ buffer_ucs4 = (unsigned long *)new_buffer;
+
+ r = idn_converter_convtoucs4(aux_converter, from,
+ buffer_ucs4,
+ buffer_length);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+
+ buffer_length *= 2;
+ }
+
+ if (*buffer_ucs4 == '\0') {
+ if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *to = '\0';
+ r = idn_success;
+ goto ret;
+ }
+
+ /*
+ * Convert `buffer_ucs4' to UTF-8.
+ */
+ buffer_length = tolen * 2;
+ for (;;) {
+ void *new_buffer;
+
+ new_buffer = realloc(buffer_utf8,
+ sizeof(*buffer_utf8) * buffer_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ buffer_utf8 = (char *)new_buffer;
+ r = idn_ucs4_ucs4toutf8(buffer_ucs4, buffer_utf8,
+ buffer_length);
+
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+
+ buffer_length *= 2;
+ }
+
+ if (*buffer_utf8 == '\0') {
+ if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *to = '\0';
+ r = idn_success;
+ goto ret;
+ }
+
+ r = idn_res_decodename(ctx, actions, buffer_utf8, to, tolen);
+
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_res_decodename2(): success (to=\"%s\")\n",
+ idn__debug_xstring(to, 50)));
+ } else {
+ TRACE(("idn_res_decodename2(): %s\n", idn_result_tostring(r)));
+ }
+ free(buffer_ucs4);
+ free(buffer_utf8);
+ if (aux_converter != NULL)
+ idn_converter_destroy(aux_converter);
+
+ return (r);
+
+#endif /* WITHOUT_ICONV */
+}
+
+static idn_result_t
+copy_verbatim(const char *from, char *to, size_t tolen) {
+ size_t fromlen = strlen(from);
+
+ if (fromlen + 1 > tolen)
+ return (idn_buffer_overflow);
+ (void)memcpy(to, from, fromlen + 1);
+ return (idn_success);
+}
+
+static idn_result_t
+labellist_create(const unsigned long *name, labellist_t *labelp) {
+ size_t length, malloc_length;
+ labellist_t head_label = NULL;
+ labellist_t tail_label = NULL;
+ labellist_t new_label = NULL;
+ const unsigned long *endp = NULL;
+ idn_result_t r;
+
+ while (*name != '\0') {
+ for (endp = name; *endp != '.' && *endp != '\0'; endp++)
+ ; /* nothing to be done */
+ length = (endp - name) + 1;
+ malloc_length = length + 15; /* add 15 for margin */
+
+ new_label = (labellist_t)
+ malloc(sizeof(struct labellist));
+ if (new_label == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ if (head_label == NULL)
+ head_label = new_label;
+
+ new_label->name = NULL;
+ new_label->undo_name = NULL;
+ new_label->name_length = malloc_length;
+ new_label->next = NULL;
+ new_label->previous = NULL;
+ new_label->dot_followed = (*endp == '.');
+
+ new_label->name = (unsigned long *)
+ malloc(sizeof(long) * malloc_length);
+ if (new_label->name == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ memcpy(new_label->name, name, sizeof(long) * length);
+ *(new_label->name + length - 1) = '\0';
+
+ new_label->undo_name = (unsigned long *)
+ malloc(sizeof(long) * malloc_length);
+ if (new_label->undo_name == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ memcpy(new_label->undo_name, name, sizeof(long) * length);
+ *(new_label->undo_name + length - 1) = '\0';
+
+ if (tail_label != NULL) {
+ tail_label->next = new_label;
+ new_label->previous = tail_label;
+ }
+ tail_label = new_label;
+
+ if (*endp == '.')
+ name = endp + 1;
+ else
+ name = endp;
+ }
+
+ *labelp = head_label;
+ r = idn_success;
+
+ret:
+ if (r != idn_success) {
+ if (new_label != NULL) {
+ free(new_label->name);
+ free(new_label->undo_name);
+ free(new_label);
+ }
+ if (head_label != NULL)
+ labellist_destroy(head_label);
+ }
+ return (r);
+}
+
+
+static void
+labellist_destroy(labellist_t label) {
+ labellist_t l, l_next;
+
+ for (l = label; l != NULL; l = l_next) {
+ l_next = l->next;
+ free(l->name);
+ free(l->undo_name);
+ free(l);
+ }
+}
+
+static idn_result_t
+labellist_setname(labellist_t label, const unsigned long *name) {
+ unsigned long *new_name;
+ size_t length, new_length;
+
+ length = idn_ucs4_strlen(name) + 1;
+ new_length = length + 15; /* add 15 for margin */
+
+ if (label->name_length < new_length) {
+ new_name = (unsigned long *)
+ realloc(label->name, sizeof(long) * new_length);
+ if (new_name == NULL)
+ return (idn_nomemory);
+ label->name = new_name;
+ label->name_length = new_length;
+ }
+ memcpy(label->name, name, sizeof(long) * length);
+
+ return (idn_success);
+}
+
+static const unsigned long *
+labellist_getname(labellist_t label) {
+ return (label->name);
+}
+
+static const unsigned long *
+labellist_gettldname(labellist_t label) {
+ labellist_t l;
+
+ if (label->previous == NULL && label->next == NULL &&
+ !label->dot_followed)
+ return (idn_mapselector_getnotld());
+
+ for (l = label; l->next != NULL; l = l->next)
+ ; /* nothing to be done */
+
+ return (l->name);
+}
+
+static idn_result_t
+labellist_getnamelist(labellist_t label, unsigned long *name,
+ size_t name_length) {
+ static const unsigned long dot_string[] = {0x002e, 0x0000}; /* "." */
+ size_t length;
+ labellist_t l;
+
+ for (l = label, length = 0; l != NULL; l = l->next)
+ length += idn_ucs4_strlen(l->name) + 1; /* name + `.' */
+ length++; /* for NUL */
+
+ if (name_length < length)
+ return (idn_buffer_overflow);
+
+ *name = '\0';
+ for (l = label; l != NULL; l = l->next) {
+ idn_ucs4_strcat(name, l->name);
+ name += idn_ucs4_strlen(name);
+ if (l->dot_followed)
+ idn_ucs4_strcat(name, dot_string);
+ }
+ return (idn_success);
+}
+
+static void
+labellist_undo(labellist_t label) {
+ size_t length;
+
+ length = idn_ucs4_strlen(label->undo_name) + 1;
+ memcpy(label->name, label->undo_name, sizeof(long) * length);
+}
+
+static labellist_t
+labellist_tail(labellist_t label) {
+ labellist_t l;
+
+ if (label == NULL)
+ return (NULL);
+ for (l = label; l->next != NULL; l = l->next)
+ ; /* nothing to be done */
+ return (l);
+}
+
+static labellist_t
+labellist_previous(labellist_t label) {
+ return (label->previous);
+}
+
+#ifndef WITHOUT_ICONV
+
+static idn_result_t
+label_localdecodecheck(idn_resconf_t ctx, labellist_t label) {
+ idn_converter_t local_converter = NULL;
+ const unsigned long *from;
+ char *to = NULL;
+ size_t to_length;
+ idn_result_t r;
+
+ from = labellist_getname(label);
+ to_length = idn_ucs4_strlen(from) + 1 + 15; /* 15 for margin */
+ TRACE(("res ucs4tolocal_check(label=\"%s\")\n",
+ idn__debug_ucs4xstring(from, 50)));
+
+ local_converter = idn_resconf_getlocalconverter(ctx);
+ if (local_converter == NULL) {
+ r = idn_success;
+ goto ret;
+ }
+
+ for (;;) {
+ char *new_buffer;
+
+ new_buffer = (char *)realloc(to, to_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ to = new_buffer;
+ r = idn_converter_convfromucs4(local_converter, from, to,
+ to_length);
+ if (r == idn_success)
+ break;
+ else if (r == idn_nomapping) {
+ r = label_idnencode_ace(ctx, label);
+ if (r != idn_success)
+ goto ret;
+ break;
+ } else if (r != idn_buffer_overflow) {
+ goto ret;
+ }
+ to_length *= 2;
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("res ucs4tolocal_check(): %s\n", idn_result_tostring(r)));
+ if (local_converter != NULL)
+ idn_converter_destroy(local_converter);
+ free(to);
+ return (r);
+}
+
+#endif /* !WITHOUT_ICONV */
+
+static idn_result_t
+label_idndecode(idn_resconf_t ctx, labellist_t label) {
+ idn_converter_t idn_converter = NULL;
+ const unsigned long *from;
+ char *ascii_from = NULL;
+ unsigned long *to = NULL;
+ size_t from_length, to_length;
+ idn_result_t r;
+
+ from = labellist_getname(label);
+ from_length = idn_ucs4_strlen(from) + 1;
+ TRACE(("res idntoucs4(label=\"%s\")\n",
+ idn__debug_ucs4xstring(from, 50)));
+
+ idn_converter = idn_resconf_getidnconverter(ctx);
+ if (idn_converter == NULL) {
+ r = idn_success;
+ goto ret;
+ }
+
+ for (;;) {
+ char *new_buffer;
+
+ new_buffer = (char *) realloc(ascii_from, from_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ ascii_from = new_buffer;
+ r = idn_ucs4_ucs4toutf8(from, ascii_from, from_length);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+ from_length *= 2;
+ }
+
+ to = NULL;
+ to_length = from_length;
+
+ for (;;) {
+ unsigned long *new_buffer;
+
+ new_buffer = (unsigned long *)
+ realloc(to, sizeof(long) * to_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ to = new_buffer;
+ r = idn_converter_convtoucs4(idn_converter, ascii_from, to,
+ to_length);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+ to_length *= 2;
+ }
+
+ r = labellist_setname(label, to);
+ret:
+ if (r == idn_success) {
+ TRACE(("res idntoucs4(): success (label=\"%s\")\n",
+ idn__debug_ucs4xstring(labellist_getname(label),
+ 50)));
+ } else {
+ TRACE(("res idntoucs4(): %s\n", idn_result_tostring(r)));
+ }
+ if (idn_converter != NULL)
+ idn_converter_destroy(idn_converter);
+ free(to);
+ free(ascii_from);
+ return (r);
+}
+
+static idn_result_t
+label_idnencode_ace(idn_resconf_t ctx, labellist_t label) {
+ idn_converter_t idn_converter = NULL;
+ const unsigned long *from;
+ char *ascii_to = NULL;
+ unsigned long *to = NULL;
+ size_t to_length;
+ idn_result_t r;
+
+ from = labellist_getname(label);
+ TRACE(("res ucs4toidn(label=\"%s\")\n",
+ idn__debug_ucs4xstring(from, 50)));
+
+ idn_converter = idn_resconf_getidnconverter(ctx);
+ if (idn_converter == NULL) {
+ r = idn_success;
+ goto ret;
+ }
+
+ ascii_to = NULL;
+ to_length = idn_ucs4_strlen(from) * 4 + 16; /* add mergin */
+
+ for (;;) {
+ char *new_buffer;
+
+ new_buffer = (char *) realloc(ascii_to, to_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ ascii_to = new_buffer;
+ r = idn_converter_convfromucs4(idn_converter, from, ascii_to,
+ to_length);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+ to_length *= 2;
+ }
+
+ for (;;) {
+ unsigned long *new_buffer;
+
+ new_buffer = (unsigned long *)
+ realloc(to, sizeof(long) * to_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ to = new_buffer;
+ r = idn_ucs4_utf8toucs4(ascii_to, to, to_length);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+ to_length *= 2;
+ }
+
+ if (r != idn_success)
+ goto ret;
+
+ r = labellist_setname(label, to);
+ret:
+ if (r == idn_success) {
+ TRACE(("res ucs4toidn(): success (label=\"%s\")\n",
+ idn__debug_ucs4xstring(labellist_getname(label),
+ 50)));
+ } else {
+ TRACE(("res ucs4toidn(): %s\n", idn_result_tostring(r)));
+ }
+ if (idn_converter != NULL)
+ idn_converter_destroy(idn_converter);
+ free(to);
+ free(ascii_to);
+ return (r);
+}
+
+static idn_result_t
+label_localmap(idn_resconf_t ctx, labellist_t label) {
+ const unsigned long *from;
+ const unsigned long *tld;
+ unsigned long *to = NULL;
+ size_t to_length;
+ idn_mapselector_t local_mapper;
+ idn_result_t r;
+
+ from = labellist_getname(label);
+ tld = labellist_gettldname(label);
+ TRACE(("res localmap(label=\"%s\", tld=\"%s\")\n",
+ idn__debug_ucs4xstring(from, 50),
+ idn__debug_ucs4xstring(tld, 50)));
+
+ local_mapper = idn_resconf_getlocalmapselector(ctx);
+ if (local_mapper == NULL) {
+ r = idn_success;
+ goto ret;
+ }
+
+ if (tld == from)
+ tld = idn_mapselector_getdefaulttld();
+ to_length = idn_ucs4_strlen(from) + 1 + 15; /* 15 for margin */
+
+ for (;;) {
+ unsigned long *new_buffer;
+
+ new_buffer = (unsigned long *)
+ realloc(to, sizeof(long) * to_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ to = new_buffer;
+ r = idn_mapselector_map2(local_mapper, from, tld, to,
+ to_length);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+ to_length *= 2;
+ }
+
+ r = labellist_setname(label, to);
+ret:
+ if (r == idn_success) {
+ TRACE(("res localmap(): success (label=\"%s\")\n",
+ idn__debug_ucs4xstring(labellist_getname(label),
+ 50)));
+ } else {
+ TRACE(("res localmap(): %s\n", idn_result_tostring(r)));
+ }
+ if (local_mapper != NULL)
+ idn_mapselector_destroy(local_mapper);
+ free(to);
+ return (r);
+}
+
+static idn_result_t
+label_map(idn_resconf_t ctx, labellist_t label) {
+ const unsigned long *from;
+ unsigned long *to = NULL;
+ size_t to_length;
+ idn_mapper_t mapper;
+ idn_result_t r;
+
+ from = labellist_getname(label);
+ TRACE(("res map(label=\"%s\")\n", idn__debug_ucs4xstring(from, 50)));
+
+ mapper = idn_resconf_getmapper(ctx);
+ if (mapper == NULL) {
+ r = idn_success;
+ goto ret;
+ }
+ to_length = idn_ucs4_strlen(from) + 1 + 15; /* 15 for margin */
+
+ for (;;) {
+ unsigned long *new_buffer;
+
+ new_buffer = (unsigned long *)
+ realloc(to, sizeof(long) * to_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ to = new_buffer;
+ r = idn_mapper_map(mapper, from, to, to_length);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+ to_length *= 2;
+ }
+
+ r = labellist_setname(label, to);
+ret:
+ if (r == idn_success) {
+ TRACE(("res map(): success (label=\"%s\")\n",
+ idn__debug_ucs4xstring(labellist_getname(label),
+ 50)));
+ } else {
+ TRACE(("res map(): %s\n", idn_result_tostring(r)));
+ }
+ if (mapper != NULL)
+ idn_mapper_destroy(mapper);
+ free(to);
+ return (r);
+}
+
+static idn_result_t
+label_normalize(idn_resconf_t ctx, labellist_t label) {
+ const unsigned long *from;
+ unsigned long *to = NULL;
+ size_t to_length;
+ idn_normalizer_t normalizer;
+ idn_result_t r;
+
+ from = labellist_getname(label);
+ TRACE(("res normalzie(label=\"%s\")\n",
+ idn__debug_ucs4xstring(from, 50)));
+
+ normalizer = idn_resconf_getnormalizer(ctx);
+ if (normalizer == NULL) {
+ r = idn_success;
+ goto ret;
+ }
+ to_length = idn_ucs4_strlen(from) + 1 + 15; /* 15 for margin */
+
+ for (;;) {
+ unsigned long *new_buffer;
+
+ new_buffer = (unsigned long *)
+ realloc(to, sizeof(long) * to_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ to = new_buffer;
+ r = idn_normalizer_normalize(normalizer, from, to, to_length);
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+ to_length *= 2;
+ }
+
+ r = labellist_setname(label, to);
+ret:
+ if (r == idn_success) {
+ TRACE(("res normalize(): success (label=\"%s\")\n",
+ idn__debug_ucs4xstring(labellist_getname(label),
+ 50)));
+ } else {
+ TRACE(("res normalize(): %s\n", idn_result_tostring(r)));
+ }
+ if (normalizer != NULL)
+ idn_normalizer_destroy(normalizer);
+ free(to);
+ return (r);
+}
+
+static idn_result_t
+label_prohcheck(idn_resconf_t ctx, labellist_t label) {
+ const unsigned long *name, *found;
+ idn_checker_t prohibit_checker;
+ idn_result_t r;
+
+ name = labellist_getname(label);
+ TRACE(("res prohcheck(label=\"%s\")\n",
+ idn__debug_ucs4xstring(name, 50)));
+
+ prohibit_checker = idn_resconf_getprohibitchecker(ctx);
+ if (prohibit_checker == NULL) {
+ r = idn_success;
+ goto ret;
+ }
+
+ r = idn_checker_lookup(prohibit_checker, name, &found);
+ idn_checker_destroy(prohibit_checker);
+ if (r == idn_success && found != NULL)
+ r = idn_prohibited;
+
+ret:
+ TRACE(("res prohcheck(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+static idn_result_t
+label_unascheck(idn_resconf_t ctx, labellist_t label) {
+ const unsigned long *name, *found;
+ idn_checker_t unassigned_checker;
+ idn_result_t r;
+
+ name = labellist_getname(label);
+ TRACE(("res unascheck(label=\"%s\")\n",
+ idn__debug_ucs4xstring(name, 50)));
+
+ unassigned_checker = idn_resconf_getunassignedchecker(ctx);
+ if (unassigned_checker == NULL) {
+ r = idn_success;
+ goto ret;
+ }
+
+ r = idn_checker_lookup(unassigned_checker, name, &found);
+ idn_checker_destroy(unassigned_checker);
+ if (r == idn_success && found != NULL)
+ r = idn_prohibited;
+
+ret:
+ TRACE(("res unascheck(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+static idn_result_t
+label_bidicheck(idn_resconf_t ctx, labellist_t label) {
+ const unsigned long *name, *found;
+ idn_checker_t bidi_checker;
+ idn_result_t r;
+
+ name = labellist_getname(label);
+ TRACE(("res bidicheck(label=\"%s\")\n",
+ idn__debug_ucs4xstring(name, 50)));
+
+ bidi_checker = idn_resconf_getbidichecker(ctx);
+ if (bidi_checker == NULL) {
+ r = idn_success;
+ goto ret;
+ }
+
+ r = idn_checker_lookup(bidi_checker, name, &found);
+ idn_checker_destroy(bidi_checker);
+ if (r == idn_success && found != NULL)
+ r = idn_prohibited;
+
+ret:
+ TRACE(("res bidicheck(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+static idn_result_t
+label_asccheck(idn_resconf_t ctx, labellist_t label) {
+ const unsigned long *name, *n;
+ idn_result_t r;
+
+ name = labellist_getname(label);
+ TRACE(("res asccheck(label=\"%s\")\n",
+ idn__debug_ucs4xstring(name, 50)));
+
+ if (*name == '-') {
+ r = idn_prohibited;
+ goto ret;
+ }
+
+ for (n = name; *n != '\0'; n++) {
+ if (*n <= '\177') {
+ if ((*n < '0' || *n > '9') &&
+ (*n < 'A' || *n > 'Z') &&
+ (*n < 'a' || *n > 'z') &&
+ *n != '-') {
+ r = idn_prohibited;
+ goto ret;
+ }
+ }
+ }
+
+ if (n > name && *(n - 1) == '-') {
+ r = idn_prohibited;
+ goto ret;
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("res asccheck(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+static idn_result_t
+label_lencheck_ace(idn_resconf_t ctx, labellist_t label) {
+ const unsigned long *name;
+ size_t name_length;
+ idn_result_t r;
+
+ name = labellist_getname(label);
+ name_length = idn_ucs4_strlen(name);
+ TRACE(("res lencheck(label=\"%s\")\n",
+ idn__debug_ucs4xstring(name, 50)));
+
+ if (name_length == 0 || name_length > MAX_LABEL_LENGTH) {
+ r = idn_invalid_length;
+ goto ret;
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("res lencheck(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+static idn_result_t
+label_lencheck_nonace(idn_resconf_t ctx, labellist_t label) {
+ idn_converter_t idn_converter;
+ const unsigned long *from;
+ size_t to_length;
+ idn_result_t r;
+ char *buffer = NULL;
+ size_t buffer_length;
+
+ from = labellist_getname(label);
+ TRACE(("res lencheck(label=\"%s\")\n",
+ idn__debug_ucs4xstring(from, 50)));
+
+ buffer_length = idn_ucs4_strlen(from) * 4 + 16; /* 16 for margin */
+ idn_converter = idn_resconf_getidnconverter(ctx);
+
+ for (;;) {
+ void *new_buffer;
+
+ new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
+ if (new_buffer == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+ buffer = (char *)new_buffer;
+
+ if (idn_converter != NULL) {
+ r = idn_converter_convfromucs4(idn_converter, from,
+ buffer, buffer_length);
+ } else {
+ r = idn_ucs4_ucs4toutf8(from, buffer, buffer_length);
+ }
+ if (r == idn_success)
+ break;
+ else if (r != idn_buffer_overflow)
+ goto ret;
+
+ buffer_length *= 2;
+ }
+
+ to_length = strlen(buffer);
+ if (to_length == 0 || to_length > MAX_LABEL_LENGTH) {
+ r = idn_invalid_length;
+ goto ret;
+ }
+
+ r = idn_success;
+ret:
+ TRACE(("res lencheck(): %s\n", idn_result_tostring(r)));
+ if (idn_converter != NULL)
+ idn_converter_destroy(idn_converter);
+ free(buffer);
+ return (r);
+}
+
+static idn_result_t
+label_rtcheck(idn_resconf_t ctx, idn_action_t actions, labellist_t label,
+ const unsigned long *original_name) {
+ labellist_t rt_label = NULL;
+ const unsigned long *rt_name;
+ const unsigned long *cur_name;
+ idn_result_t r;
+
+ cur_name = labellist_getname(label);
+ TRACE(("res rtcheck(label=\"%s\", org_label=\"%s\")\n",
+ idn__debug_ucs4xstring(cur_name, 50),
+ idn__debug_ucs4xstring(original_name, 50)));
+
+ r = labellist_create(cur_name, &rt_label);
+ if (r != idn_success)
+ goto ret;
+ if (rt_label == NULL) {
+ if (*original_name == '\0')
+ r = idn_success;
+ else
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+
+ if (!idn__util_ucs4isasciirange(labellist_getname(rt_label))) {
+ r = label_map(ctx, rt_label);
+ if (r != idn_success)
+ goto ret;
+ r = label_normalize(ctx, rt_label);
+ if (r != idn_success)
+ goto ret;
+ r = label_prohcheck(ctx, rt_label);
+ if (r != idn_success)
+ goto ret;
+ if (actions & IDN_UNASCHECK) {
+ r = label_unascheck(ctx, rt_label);
+ if (r != idn_success)
+ goto ret;
+ }
+ r = label_bidicheck(ctx, rt_label);
+ if (r != idn_success)
+ goto ret;
+ }
+
+ if (actions & IDN_ASCCHECK) {
+ r = label_asccheck(ctx, rt_label);
+ if (r != idn_success)
+ goto ret;
+ }
+ if (!idn__util_ucs4isasciirange(labellist_getname(rt_label))) {
+ r = label_idnencode_ace(ctx, rt_label);
+ if (r != idn_success)
+ goto ret;
+ }
+ r = label_lencheck_ace(ctx, rt_label);
+ if (r != idn_success)
+ goto ret;
+ rt_name = labellist_getname(rt_label);
+
+ if (idn_ucs4_strcasecmp(rt_name, original_name) != 0) {
+ TRACE(("res rtcheck(): round trip failed, org =\"%s\", rt=\"%s\"\n",
+ idn__debug_ucs4xstring(original_name, 50),
+ idn__debug_ucs4xstring(rt_name, 50)));
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+
+ r = idn_success;
+ret:
+ if (r != idn_nomemory && r != idn_success)
+ r = idn_invalid_encoding;
+ TRACE(("res rtcheck(): %s\n", idn_result_tostring(r)));
+ if (rt_label != NULL)
+ labellist_destroy(rt_label);
+ return (r);
+}
+
+const char *
+idn__res_actionstostring(idn_action_t actions) {
+ static char buf[100];
+
+ buf[0] = '\0';
+
+ if (actions == IDN_ENCODE_QUERY)
+ strcpy(buf, "encode-query");
+ else if (actions == IDN_DECODE_QUERY)
+ strcpy(buf, "decode-query");
+ else if (actions == IDN_ENCODE_APP)
+ strcpy(buf, "encode-app");
+ else if (actions == IDN_DECODE_APP)
+ strcpy(buf, "decode-app");
+ else if (actions == IDN_ENCODE_STORED)
+ strcpy(buf, "encode-stored");
+ else if (actions == IDN_DECODE_STORED)
+ strcpy(buf, "decode-stored");
+ else {
+ if (actions & IDN_LOCALCONV)
+ strcat(buf, "|localconv");
+ if (actions & IDN_DELIMMAP)
+ strcat(buf, "|delimmap");
+ if (actions & IDN_LOCALMAP)
+ strcat(buf, "|localmap");
+
+ if (actions & IDN_MAP)
+ strcat(buf, "|map");
+ if (actions & IDN_NORMALIZE)
+ strcat(buf, "|normalize");
+ if (actions & IDN_PROHCHECK)
+ strcat(buf, "|prohcheck");
+ if (actions & IDN_UNASCHECK)
+ strcat(buf, "|unascheck");
+ if (actions & IDN_BIDICHECK)
+ strcat(buf, "|bidicheck");
+
+ if (actions & IDN_IDNCONV)
+ strcat(buf, "|idnconv");
+ if (actions & IDN_ASCCHECK)
+ strcat(buf, "|asccheck");
+ if (actions & IDN_LENCHECK)
+ strcat(buf, "|lencheck");
+ if (actions & IDN_RTCHECK)
+ strcat(buf, "|rtcheck");
+ }
+
+ if (buf[0] == '|')
+ return (buf + 1);
+ else
+ return (buf);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/resconf.c b/contrib/idn/idnkit-1.0-src/lib/resconf.c
new file mode 100644
index 0000000..29bbeea
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/resconf.c
@@ -0,0 +1,1477 @@
+#ifndef lint
+static char *rcsid = "$Id: resconf.c,v 1.1.1.1 2003/06/04 00:26:12 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/converter.h>
+#include <idn/nameprep.h>
+#include <idn/normalizer.h>
+#include <idn/checker.h>
+#include <idn/mapper.h>
+#include <idn/mapselector.h>
+#include <idn/delimitermap.h>
+#include <idn/localencoding.h>
+#include <idn/resconf.h>
+#include <idn/debug.h>
+#include <idn/util.h>
+
+#ifdef WIN32
+#define MAX_PATH_SIZE 500 /* a good longer than MAX_PATH */
+#define IDNVAL_CONFFILE "ConfFile"
+#else /* WIN32 */
+
+#ifndef IDN_RESCONF_DIR
+#define IDN_RESCONF_DIR "/etc"
+#endif
+#define IDN_RESCONF_FILE IDN_RESCONF_DIR "/idn.conf"
+#define IDN_USER_RESCONF_FILE "/.idnrc"
+
+#endif /* WIN32 */
+
+#define MAX_CONF_LINE_LENGTH 255
+#define MAX_CONF_LINE_ARGS 63
+
+#define DEFAULT_CONF_NAMEPREP 0x0001
+#define DEFAULT_CONF_IDN_ENCODING 0x0010
+#define DEFAULT_CONF_ALL (DEFAULT_CONF_NAMEPREP | \
+ DEFAULT_CONF_IDN_ENCODING)
+
+#define IDN_ENCODING_CURRENT "Punycode"
+
+#ifdef ENABLE_MDNKIT_COMPAT
+#define MDN_RESCONF_FILE IDN_RESCONF_DIR "/mdn.conf"
+#endif
+
+struct idn_resconf {
+ int local_converter_is_static;
+ idn_converter_t local_converter;
+ idn_converter_t idn_converter;
+ idn_converter_t aux_idn_converter;
+ idn_normalizer_t normalizer;
+ idn_checker_t prohibit_checker;
+ idn_checker_t unassigned_checker;
+ idn_checker_t bidi_checker;
+ idn_mapper_t mapper;
+ idn_mapselector_t local_mapper;
+ idn_delimitermap_t delimiter_mapper;
+ int reference_count;
+};
+
+static int initialized;
+
+#ifndef WIN32
+static const char * userhomedir(void);
+#endif
+static idn_result_t open_userdefaultfile(FILE **fpp);
+static idn_result_t open_defaultfile(FILE **fpp);
+static idn_result_t parse_conf(idn_resconf_t ctx, FILE *fp);
+static idn_result_t parse_idn_encoding(idn_resconf_t ctx, char *args,
+ int lineno);
+static idn_result_t parse_local_map(idn_resconf_t ctx, char *args,
+ int lineno);
+static idn_result_t parse_nameprep(idn_resconf_t ctx, char *args,
+ int lineno);
+static int split_args(char *s, char **av, int max_ac);
+static void resetconf(idn_resconf_t ctx);
+#ifndef WITHOUT_ICONV
+static idn_result_t update_local_converter(idn_resconf_t ctx);
+#endif
+static idn_result_t setdefaults_body(idn_resconf_t ctx, int conf_mask);
+
+idn_result_t
+idn_resconf_initialize(void) {
+ idn_result_t r;
+
+ TRACE(("idn_resconf_initialize()\n"));
+
+ if (initialized) {
+ r = idn_success;
+ goto ret;
+ }
+
+ /*
+ * Initialize sub modules.
+ */
+ if ((r = idn_converter_initialize()) != idn_success)
+ goto ret;
+ if ((r = idn_normalizer_initialize()) != idn_success)
+ goto ret;
+ if ((r = idn_checker_initialize()) != idn_success)
+ goto ret;
+ if ((r = idn_mapselector_initialize()) != idn_success)
+ goto ret;
+ if ((r = idn_mapper_initialize()) != idn_success)
+ goto ret;
+
+ r = idn_success;
+ initialized = 1;
+ret:
+ TRACE(("idn_resconf_initialize(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+idn_result_t
+idn_resconf_create(idn_resconf_t *ctxp) {
+ idn_resconf_t ctx = NULL;
+ idn_result_t r;
+
+ assert(ctxp != NULL);
+
+ TRACE(("idn_resconf_create()\n"));
+
+ if (!initialized) {
+ r = idn_failure;
+ goto ret;
+ }
+ if ((ctx = malloc(sizeof(*ctx))) == NULL) {
+ r = idn_nomemory;
+ goto ret;
+ }
+
+ ctx->local_converter_is_static = 0;
+ ctx->local_converter = NULL;
+ ctx->idn_converter = NULL;
+ ctx->aux_idn_converter = NULL;
+ ctx->normalizer = NULL;
+ ctx->prohibit_checker = NULL;
+ ctx->unassigned_checker = NULL;
+ ctx->bidi_checker = NULL;
+ ctx->mapper = NULL;
+ ctx->local_mapper = NULL;
+ ctx->reference_count = 1;
+
+ r = idn_delimitermap_create(&ctx->delimiter_mapper);
+ if (r != idn_success)
+ goto ret;
+
+ *ctxp = ctx;
+ r = idn_success;
+ret:
+ TRACE(("idn_resconf_create(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+char *
+idn_resconf_defaultfile() {
+#ifdef WIN32
+ static char default_path[MAX_PATH_SIZE];
+
+ if (idn__util_getregistrystring(idn__util_hkey_localmachine,
+ IDNVAL_CONFFILE, default_path,
+ sizeof(default_path))) {
+ return (default_path);
+ } else {
+ return (NULL);
+ }
+#else
+ return (IDN_RESCONF_FILE);
+#endif
+}
+
+#ifndef WIN32
+static const char *
+userhomedir() {
+ uid_t uid;
+ struct passwd *pwd;
+
+ uid = getuid();
+ pwd = getpwuid(uid);
+ if (pwd == NULL) {
+ return (NULL);
+ }
+
+ return (pwd->pw_dir);
+}
+#endif
+
+static idn_result_t
+open_userdefaultfile(FILE **fpp) {
+#ifdef WIN32
+ char user_path[MAX_PATH_SIZE];
+
+ TRACE(("open_userdefaultfile()\n"));
+
+ if (idn__util_getregistrystring(idn__util_hkey_currentuser,
+ IDNVAL_CONFFILE, user_path,
+ sizeof(user_path)) == 0) {
+ return (idn_nofile);
+ }
+ *fpp = fopen(user_path, "r");
+ if (*fpp == NULL) {
+ return (idn_nofile);
+ }
+ return (idn_success);
+#else /* WIN32 */
+ const char *homedir;
+ char *file;
+ int len;
+
+ TRACE(("open_userdefaultfile()\n"));
+
+ homedir = userhomedir();
+ len = strlen(IDN_USER_RESCONF_FILE) + 1;
+ if (homedir != NULL) {
+ len += strlen(homedir);
+ } else {
+ return (idn_notfound);
+ }
+
+ file = (char *)malloc(sizeof(char) * len);
+ if (file == NULL) {
+ WARNING(("open_userdefaultfile(): malloc failed\n"));
+ return (idn_nomemory);
+ }
+
+ (void)strcpy(file, homedir);
+ strcat(file, IDN_USER_RESCONF_FILE);
+
+ *fpp = fopen(file, "r");
+ free(file);
+ if (*fpp == NULL) {
+ return (idn_nofile);
+ }
+
+ return (idn_success);
+#endif /* WIN32 */
+}
+
+static idn_result_t
+open_defaultfile(FILE **fpp) {
+ idn_result_t r;
+ const char *file;
+
+ r = open_userdefaultfile(fpp);
+ if (r == idn_nofile || r == idn_notfound) {
+ TRACE(("open_defaultfile: "
+ "cannot open user configuration file\n"));
+ file = idn_resconf_defaultfile();
+ *fpp = fopen(file, "r");
+#ifdef ENABLE_MDNKIT_COMPAT
+ if (*fpp == NULL)
+ *fpp = fopen(MDN_RESCONF_FILE, "r");
+#endif
+ if (*fpp == NULL) {
+ TRACE(("open_defaultfile: "
+ "cannot open system configuration file\n"));
+ return (idn_nofile);
+ }
+ } else if (r != idn_success) {
+ return (r);
+ }
+
+ return (idn_success);
+}
+
+idn_result_t
+idn_resconf_loadfile(idn_resconf_t ctx, const char *file) {
+ FILE *fp = NULL;
+ idn_result_t r;
+
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_loadfile(file=%s)\n",
+ file == NULL ? "<null>" : file));
+
+ resetconf(ctx);
+ r = idn_delimitermap_create(&ctx->delimiter_mapper);
+ if (r != idn_success) {
+ goto ret;
+ }
+
+ if (file == NULL) {
+ r = open_defaultfile(&fp);
+ if (r == idn_nofile || r == idn_notfound) {
+ r = setdefaults_body(ctx, 0);
+ goto ret;
+ } else if (r != idn_success) {
+ goto ret;
+ }
+ } else {
+ fp = fopen(file, "r");
+ if (fp == NULL) {
+ TRACE(("idn_resconf_loadfile: cannot open %-.40s\n",
+ file));
+ r = idn_nofile;
+ goto ret;
+ }
+ }
+
+ r = parse_conf(ctx, fp);
+ fclose(fp);
+
+ret:
+ TRACE(("idn_resconf_loadfile(): %s\n", idn_result_tostring(r)));
+ return (r);
+}
+
+void
+idn_resconf_destroy(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_destroy()\n"));
+
+ ctx->reference_count--;
+ if (ctx->reference_count <= 0) {
+ resetconf(ctx);
+ free(ctx);
+ TRACE(("idn_resconf_destroy: the object is destroyed\n"));
+ } else {
+ TRACE(("idn_resconf_destroy(): "
+ "update reference count (%d->%d)\n",
+ ctx->reference_count + 1, ctx->reference_count));
+ }
+}
+
+void
+idn_resconf_incrref(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_incrref()\n"));
+ TRACE(("idn_resconf_incrref: update reference count (%d->%d)\n",
+ ctx->reference_count, ctx->reference_count + 1));
+
+ ctx->reference_count++;
+}
+
+idn_converter_t
+idn_resconf_getalternateconverter(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getalternateconverter()\n"));
+
+ return (idn_resconf_getidnconverter(ctx));
+}
+
+idn_delimitermap_t
+idn_resconf_getdelimitermap(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getdelimitermap()\n"));
+
+ if (ctx->delimiter_mapper != NULL)
+ idn_delimitermap_incrref(ctx->delimiter_mapper);
+ return (ctx->delimiter_mapper);
+}
+
+idn_converter_t
+idn_resconf_getidnconverter(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getidnconverter()\n"));
+
+ if (ctx->idn_converter != NULL)
+ idn_converter_incrref(ctx->idn_converter);
+ return (ctx->idn_converter);
+}
+
+idn_converter_t
+idn_resconf_getauxidnconverter(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getauxidnconverter()\n"));
+
+ if (ctx->aux_idn_converter != NULL)
+ idn_converter_incrref(ctx->aux_idn_converter);
+ return (ctx->aux_idn_converter);
+}
+
+idn_converter_t
+idn_resconf_getlocalconverter(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getlocalconverter()\n"));
+
+#ifdef WITHOUT_ICONV
+ return NULL;
+
+#else /* WITHOUT_ICONV */
+ if (update_local_converter(ctx) != idn_success)
+ return (NULL);
+
+ idn_converter_incrref(ctx->local_converter);
+ return (ctx->local_converter);
+
+#endif /* WITHOUT_ICONV */
+}
+
+idn_mapselector_t
+idn_resconf_getlocalmapselector(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getlocalmapselector()\n"));
+
+ if (ctx->local_mapper != NULL)
+ idn_mapselector_incrref(ctx->local_mapper);
+ return (ctx->local_mapper);
+}
+
+idn_mapper_t
+idn_resconf_getmapper(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getmapper()\n"));
+
+ if (ctx->mapper != NULL)
+ idn_mapper_incrref(ctx->mapper);
+ return (ctx->mapper);
+}
+
+idn_normalizer_t
+idn_resconf_getnormalizer(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getnormalizer()\n"));
+
+ if (ctx->normalizer != NULL)
+ idn_normalizer_incrref(ctx->normalizer);
+ return (ctx->normalizer);
+}
+
+idn_checker_t
+idn_resconf_getprohibitchecker(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getprohibitchecker()\n"));
+
+ if (ctx->prohibit_checker != NULL)
+ idn_checker_incrref(ctx->prohibit_checker);
+ return (ctx->prohibit_checker);
+}
+
+idn_checker_t
+idn_resconf_getunassignedchecker(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getunassignedchecker()\n"));
+
+ if (ctx->unassigned_checker != NULL)
+ idn_checker_incrref(ctx->unassigned_checker);
+ return (ctx->unassigned_checker);
+}
+
+idn_checker_t
+idn_resconf_getbidichecker(idn_resconf_t ctx) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_getbidichecker()\n"));
+
+ if (ctx->bidi_checker != NULL)
+ idn_checker_incrref(ctx->bidi_checker);
+ return (ctx->bidi_checker);
+}
+
+void
+idn_resconf_setalternateconverter(idn_resconf_t ctx,
+ idn_converter_t alternate_converter) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setalternateconverter()\n"));
+}
+
+void
+idn_resconf_setdelimitermap(idn_resconf_t ctx,
+ idn_delimitermap_t delimiter_mapper) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setdelimitermap()\n"));
+
+ if (ctx->delimiter_mapper != NULL)
+ idn_delimitermap_destroy(ctx->delimiter_mapper);
+ ctx->delimiter_mapper = delimiter_mapper;
+ if (delimiter_mapper != NULL)
+ idn_delimitermap_incrref(ctx->delimiter_mapper);
+}
+
+void
+idn_resconf_setidnconverter(idn_resconf_t ctx,
+ idn_converter_t idn_converter) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setidnconverter()\n"));
+
+ if (ctx->idn_converter != NULL)
+ idn_converter_destroy(ctx->idn_converter);
+ ctx->idn_converter = idn_converter;
+ if (idn_converter != NULL)
+ idn_converter_incrref(ctx->idn_converter);
+}
+
+void
+idn_resconf_setauxidnconverter(idn_resconf_t ctx,
+ idn_converter_t aux_idn_converter) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setauxidnconverter()\n"));
+
+ if (ctx->aux_idn_converter != NULL)
+ idn_converter_destroy(ctx->aux_idn_converter);
+ ctx->aux_idn_converter = aux_idn_converter;
+ if (aux_idn_converter != NULL)
+ idn_converter_incrref(ctx->aux_idn_converter);
+}
+
+void
+idn_resconf_setlocalconverter(idn_resconf_t ctx,
+ idn_converter_t local_converter) {
+#ifndef WITHOUT_ICONV
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setlocalconverter()\n"));
+
+ if (ctx->local_converter != NULL) {
+ idn_converter_destroy(ctx->local_converter);
+ ctx->local_converter = NULL;
+ }
+
+ if (local_converter == NULL)
+ ctx->local_converter_is_static = 0;
+ else {
+ ctx->local_converter = local_converter;
+ idn_converter_incrref(local_converter);
+ ctx->local_converter_is_static = 1;
+ }
+#endif /* WITHOUT_ICONV */
+}
+
+void
+idn_resconf_setlocalmapselector(idn_resconf_t ctx,
+ idn_mapselector_t local_mapper) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setlocalmapselector()\n"));
+
+ if (ctx->local_mapper != NULL)
+ idn_mapselector_destroy(ctx->local_mapper);
+ ctx->local_mapper = local_mapper;
+ if (local_mapper != NULL)
+ idn_mapselector_incrref(ctx->local_mapper);
+}
+
+void
+idn_resconf_setmapper(idn_resconf_t ctx, idn_mapper_t mapper) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setmapper()\n"));
+
+ if (ctx->mapper != NULL)
+ idn_mapper_destroy(ctx->mapper);
+ ctx->mapper = mapper;
+ if (mapper != NULL)
+ idn_mapper_incrref(ctx->mapper);
+}
+
+void
+idn_resconf_setnormalizer(idn_resconf_t ctx, idn_normalizer_t normalizer) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setnormalizer()\n"));
+
+ if (ctx->normalizer != NULL)
+ idn_normalizer_destroy(ctx->normalizer);
+ ctx->normalizer = normalizer;
+ if (normalizer != NULL)
+ idn_normalizer_incrref(ctx->normalizer);
+}
+
+void
+idn_resconf_setprohibitchecker(idn_resconf_t ctx,
+ idn_checker_t prohibit_checker) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setprohibitchecker()\n"));
+
+ if (ctx->prohibit_checker != NULL)
+ idn_checker_destroy(ctx->prohibit_checker);
+ ctx->prohibit_checker = prohibit_checker;
+ if (prohibit_checker != NULL)
+ idn_checker_incrref(ctx->prohibit_checker);
+}
+
+void
+idn_resconf_setunassignedchecker(idn_resconf_t ctx,
+ idn_checker_t unassigned_checker) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setunassignedchecker()\n"));
+
+ if (ctx->unassigned_checker != NULL)
+ idn_checker_destroy(ctx->unassigned_checker);
+ ctx->unassigned_checker = unassigned_checker;
+ if (unassigned_checker != NULL)
+ idn_checker_incrref(ctx->unassigned_checker);
+}
+
+void
+idn_resconf_setbidichecker(idn_resconf_t ctx,
+ idn_checker_t bidi_checker) {
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setbidichecker()\n"));
+
+ if (ctx->bidi_checker != NULL)
+ idn_checker_destroy(ctx->bidi_checker);
+ ctx->bidi_checker = bidi_checker;
+ if (bidi_checker != NULL)
+ idn_checker_incrref(ctx->bidi_checker);
+}
+
+idn_result_t
+idn_resconf_setnameprepversion(idn_resconf_t ctx, const char *version)
+{
+ char prohibit_scheme_name[MAX_CONF_LINE_LENGTH + 1];
+ char unassigned_scheme_name[MAX_CONF_LINE_LENGTH + 1];
+ char bidi_scheme_name[MAX_CONF_LINE_LENGTH + 1];
+ idn_mapper_t mapper = NULL;
+ idn_normalizer_t normalizer = NULL;
+ idn_checker_t prohibit_checker = NULL;
+ idn_checker_t unassigned_checker = NULL;
+ idn_checker_t bidi_checker = NULL;
+ idn_result_t r;
+
+ assert(ctx != NULL && version != NULL);
+
+ TRACE(("idn_resconf_setnameprepversion()\n"));
+
+ /*
+ * Set canonical scheme names.
+ */
+ if (strlen(version) + strlen(IDN_CHECKER_PROHIBIT_PREFIX)
+ > MAX_CONF_LINE_LENGTH) {
+ r = idn_invalid_name;
+ goto failure;
+ }
+ sprintf(prohibit_scheme_name, "%s%s",
+ IDN_CHECKER_PROHIBIT_PREFIX, version);
+
+ if (strlen(version) + strlen(IDN_CHECKER_UNASSIGNED_PREFIX)
+ > MAX_CONF_LINE_LENGTH) {
+ r = idn_invalid_name;
+ goto failure;
+ }
+ sprintf(unassigned_scheme_name, "%s%s",
+ IDN_CHECKER_UNASSIGNED_PREFIX, version);
+
+ if (strlen(version) + strlen(IDN_CHECKER_BIDI_PREFIX)
+ > MAX_CONF_LINE_LENGTH) {
+ r = idn_invalid_name;
+ goto failure;
+ }
+ sprintf(bidi_scheme_name, "%s%s",
+ IDN_CHECKER_BIDI_PREFIX, version);
+
+ /*
+ * Create objects.
+ */
+ r = idn_mapper_create(&mapper);
+ if (r != idn_success)
+ goto failure;
+ r = idn_normalizer_create(&normalizer);
+ if (r != idn_success)
+ goto failure;
+ r = idn_checker_create(&prohibit_checker);
+ if (r != idn_success)
+ goto failure;
+ r = idn_checker_create(&unassigned_checker);
+ if (r != idn_success)
+ goto failure;
+ r = idn_checker_create(&bidi_checker);
+ if (r != idn_success)
+ goto failure;
+
+ r = idn_mapper_add(mapper, version);
+ if (r != idn_success)
+ goto failure;
+ r = idn_normalizer_add(normalizer, version);
+ if (r != idn_success)
+ goto failure;
+ r = idn_checker_add(prohibit_checker, prohibit_scheme_name);
+ if (r != idn_success)
+ goto failure;
+ r = idn_checker_add(unassigned_checker, unassigned_scheme_name);
+ if (r != idn_success)
+ goto failure;
+ r = idn_checker_add(bidi_checker, bidi_scheme_name);
+ if (r != idn_success)
+ goto failure;
+
+ /*
+ * Set the objects.
+ */
+ idn_resconf_setmapper(ctx, mapper);
+ idn_resconf_setnormalizer(ctx, normalizer);
+ idn_resconf_setprohibitchecker(ctx, prohibit_checker);
+ idn_resconf_setunassignedchecker(ctx, unassigned_checker);
+ idn_resconf_setbidichecker(ctx, bidi_checker);
+
+ /*
+ * Destroy the objects.
+ */
+ idn_mapper_destroy(mapper);
+ idn_normalizer_destroy(normalizer);
+ idn_checker_destroy(prohibit_checker);
+ idn_checker_destroy(unassigned_checker);
+ idn_checker_destroy(bidi_checker);
+
+ return (idn_success);
+
+failure:
+ if (mapper != NULL)
+ idn_mapper_destroy(mapper);
+ if (normalizer != NULL)
+ idn_normalizer_destroy(normalizer);
+ if (prohibit_checker != NULL)
+ idn_checker_destroy(prohibit_checker);
+ if (unassigned_checker != NULL)
+ idn_checker_destroy(unassigned_checker);
+ if (bidi_checker != NULL)
+ idn_checker_destroy(bidi_checker);
+
+ return (r);
+}
+
+idn_result_t
+idn_resconf_setalternateconvertername(idn_resconf_t ctx, const char *name,
+ int flags) {
+ assert(ctx != NULL && name != NULL);
+
+ TRACE(("idn_resconf_setalternateconvertername(name=%s, flags=%d)\n",
+ name, flags));
+
+ return (idn_success);
+}
+
+idn_result_t
+idn_resconf_setidnconvertername(idn_resconf_t ctx, const char *name,
+ int flags) {
+ idn_converter_t idn_converter;
+ idn_result_t r;
+
+ assert(ctx != NULL && name != NULL);
+
+ TRACE(("idn_resconf_setidnconvertername(name=%s, flags=%d)\n",
+ name, flags));
+
+ r = idn_converter_create(name, &idn_converter, flags);
+ if (r != idn_success)
+ return (r);
+
+ if (ctx->idn_converter != NULL)
+ idn_converter_destroy(ctx->idn_converter);
+ ctx->idn_converter = idn_converter;
+
+ return (idn_success);
+}
+
+idn_result_t
+idn_resconf_setauxidnconvertername(idn_resconf_t ctx, const char *name,
+ int flags) {
+ idn_converter_t aux_idn_converter;
+ const char *old_name;
+ idn_result_t r;
+
+ assert(ctx != NULL && name != NULL);
+
+ TRACE(("idn_resconf_setauxidnconvertername(name=%s, flags=%d)\n",
+ name, flags));
+
+ if (ctx->aux_idn_converter != NULL) {
+ old_name = idn_converter_localencoding(ctx->aux_idn_converter);
+ if (old_name != NULL && strcmp(old_name, name) == 0)
+ return (idn_success);
+ }
+
+ r = idn_converter_create(name, &aux_idn_converter, flags);
+ if (r != idn_success)
+ return (r);
+
+ if (ctx->aux_idn_converter != NULL)
+ idn_converter_destroy(ctx->aux_idn_converter);
+ ctx->aux_idn_converter = aux_idn_converter;
+
+ return (idn_success);
+}
+
+idn_result_t
+idn_resconf_setlocalconvertername(idn_resconf_t ctx, const char *name,
+ int flags) {
+#ifdef WITHOUT_ICONV
+ return idn_failure;
+
+#else /* WITHOUT_ICONV */
+ idn_converter_t local_converter;
+ idn_result_t r;
+
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setlocalconvertername(name=%s, flags=%d)\n",
+ name == NULL ? "<null>" : name, flags));
+
+ if (ctx->local_converter != NULL) {
+ idn_converter_destroy(ctx->local_converter);
+ ctx->local_converter = NULL;
+ }
+ ctx->local_converter_is_static = 0;
+
+ if (name != NULL) {
+ r = idn_converter_create(name, &local_converter, flags);
+ if (r != idn_success)
+ return (r);
+ ctx->local_converter = local_converter;
+ ctx->local_converter_is_static = 1;
+ }
+
+ return (idn_success);
+
+#endif /* WITHOUT_ICONV */
+}
+
+idn_result_t
+idn_resconf_addalldelimitermapucs(idn_resconf_t ctx, unsigned long *v,
+ int nv) {
+ idn_result_t r;
+
+ TRACE(("idn_resconf_addalldelimitermapucs(nv=%d)\n", nv));
+
+ if (ctx->delimiter_mapper == NULL) {
+ r = idn_delimitermap_create(&(ctx->delimiter_mapper));
+ if (r != idn_success)
+ return (r);
+ }
+
+ r = idn_delimitermap_addall(ctx->delimiter_mapper, v, nv);
+ return (r);
+}
+
+idn_result_t
+idn_resconf_addalllocalmapselectornames(idn_resconf_t ctx, const char *tld,
+ const char **names, int nnames) {
+ idn_result_t r;
+
+ assert(ctx != NULL && names != NULL && tld != NULL);
+
+ TRACE(("idn_resconf_addalllocalmapselectorname(tld=%s, nnames=%d)\n",
+ tld, nnames));
+
+ if (ctx->local_mapper == NULL) {
+ r = idn_mapselector_create(&(ctx->local_mapper));
+ if (r != idn_success)
+ return (r);
+ }
+
+ r = idn_mapselector_addall(ctx->local_mapper, tld, names, nnames);
+ return (r);
+}
+
+idn_result_t
+idn_resconf_addallmappernames(idn_resconf_t ctx, const char **names,
+ int nnames) {
+ idn_result_t r;
+
+ assert(ctx != NULL && names != NULL);
+
+ TRACE(("idn_resconf_addallmappername()\n"));
+
+ if (ctx->mapper == NULL) {
+ r = idn_mapper_create(&(ctx->mapper));
+ if (r != idn_success)
+ return (r);
+ }
+
+ r = idn_mapper_addall(ctx->mapper, names, nnames);
+ return (r);
+}
+
+idn_result_t
+idn_resconf_addallnormalizernames(idn_resconf_t ctx, const char **names,
+ int nnames) {
+ idn_result_t r;
+
+ assert(ctx != NULL && names != NULL);
+
+ TRACE(("idn_resconf_addallnormalizername(nnames=%d)\n", nnames));
+
+ if (ctx->normalizer == NULL) {
+ r = idn_normalizer_create(&(ctx->normalizer));
+ if (r != idn_success)
+ return (r);
+ }
+
+ r = idn_normalizer_addall(ctx->normalizer, names, nnames);
+ return (r);
+}
+
+idn_result_t
+idn_resconf_addallprohibitcheckernames(idn_resconf_t ctx, const char **names,
+ int nnames) {
+ char long_name[MAX_CONF_LINE_LENGTH + 1];
+ idn_result_t r;
+ int i;
+
+ assert(ctx != NULL && names != NULL);
+
+ TRACE(("idn_resconf_addallprohibitcheckername(nnames=%d)\n", nnames));
+
+ if (ctx->prohibit_checker == NULL) {
+ r = idn_checker_create(&(ctx->prohibit_checker));
+ if (r != idn_success)
+ return (r);
+ }
+
+ for (i = 0; i < nnames; i++, names++) {
+ if (strlen(*names) + strlen(IDN_CHECKER_PROHIBIT_PREFIX)
+ > MAX_CONF_LINE_LENGTH) {
+ return (idn_invalid_name);
+ }
+ strcpy(long_name, IDN_CHECKER_PROHIBIT_PREFIX);
+ strcat(long_name, *names);
+
+ r = idn_checker_add(ctx->prohibit_checker, long_name);
+ if (r != idn_success)
+ return (r);
+ }
+
+ return (idn_success);
+}
+
+idn_result_t
+idn_resconf_addallunassignedcheckernames(idn_resconf_t ctx, const char **names,
+ int nnames) {
+ char long_name[MAX_CONF_LINE_LENGTH + 1];
+ idn_result_t r;
+ int i;
+
+ assert(ctx != NULL && names != NULL);
+
+ TRACE(("idn_resconf_addallunassignedcheckername(nnames=%d)\n",
+ nnames));
+
+ if (ctx->unassigned_checker == NULL) {
+ r = idn_checker_create(&(ctx->unassigned_checker));
+ if (r != idn_success)
+ return (r);
+ }
+
+ for (i = 0; i < nnames; i++, names++) {
+ if (strlen(*names) + strlen(IDN_CHECKER_UNASSIGNED_PREFIX)
+ > MAX_CONF_LINE_LENGTH) {
+ return (idn_invalid_name);
+ }
+ strcpy(long_name, IDN_CHECKER_UNASSIGNED_PREFIX);
+ strcat(long_name, *names);
+
+ r = idn_checker_add(ctx->unassigned_checker, long_name);
+ if (r != idn_success)
+ return (r);
+ }
+
+ return (idn_success);
+}
+
+idn_result_t
+idn_resconf_addallbidicheckernames(idn_resconf_t ctx, const char **names,
+ int nnames) {
+ char long_name[MAX_CONF_LINE_LENGTH + 1];
+ idn_result_t r;
+ int i;
+
+ assert(ctx != NULL && names != NULL);
+
+ TRACE(("idn_resconf_addallbidicheckername(nnames=%d)\n", nnames));
+
+ if (ctx->bidi_checker == NULL) {
+ r = idn_checker_create(&(ctx->bidi_checker));
+ if (r != idn_success)
+ return (r);
+ }
+
+ for (i = 0; i < nnames; i++, names++) {
+ if (strlen(*names) + strlen(IDN_CHECKER_BIDI_PREFIX)
+ > MAX_CONF_LINE_LENGTH) {
+ return (idn_invalid_name);
+ }
+ strcpy(long_name, IDN_CHECKER_BIDI_PREFIX);
+ strcat(long_name, *names);
+
+ r = idn_checker_add(ctx->bidi_checker, long_name);
+ if (r != idn_success)
+ return (r);
+ }
+
+ return (idn_success);
+}
+
+static idn_result_t
+parse_conf(idn_resconf_t ctx, FILE *fp) {
+ char line[MAX_CONF_LINE_LENGTH + 1];
+ int lineno = 0;
+ char *argv[3];
+ int argc;
+ idn_result_t r;
+ int conf_mask = 0;
+
+ TRACE(("parse_conf()\n"));
+
+ /*
+ * Parse config file. parsing of 'idn-encoding' line is
+ * postponed because 'alias-file' line must be processed
+ * before them.
+ */
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ char *newline;
+
+ lineno++;
+ newline = strpbrk(line, "\r\n");
+ if (newline != NULL)
+ *newline = '\0';
+ else if (fgetc(fp) != EOF) {
+ ERROR(("libidnkit: too long line \"%-.30s\", "
+ "line %d\n", line, lineno));
+ return (idn_invalid_syntax);
+ }
+
+ argc = split_args(line, argv, 2);
+ if (argc == -1) {
+ ERROR(("libidnkit: syntax error, line %d\n", lineno));
+ return (idn_invalid_syntax);
+ } else if (argc == 0 || argv[0][0] == '#') {
+ continue;
+ } else if (argc == 1) {
+ ERROR(("libidnkit: syntax error, line %d\n", lineno));
+ return (idn_invalid_syntax);
+ }
+
+ if (strcmp(argv[0], "idn-encoding") == 0) {
+ if (conf_mask & DEFAULT_CONF_IDN_ENCODING) {
+ ERROR(("libidnkit: \"%s\" redefined, "
+ "line %d\n", argv[0], lineno));
+ r = idn_invalid_syntax;
+ } else {
+ conf_mask |= DEFAULT_CONF_IDN_ENCODING;
+ r = parse_idn_encoding(ctx, argv[1], lineno);
+ }
+ } else if (strcmp(argv[0], "local-map") == 0) {
+ r = parse_local_map(ctx, argv[1], lineno);
+
+ } else if (strcmp(argv[0], "nameprep") == 0) {
+ if (conf_mask & DEFAULT_CONF_NAMEPREP) {
+ ERROR(("libidnkit: \"%s\" redefined, "
+ "line %d\n", argv[0], lineno));
+ r = idn_invalid_syntax;
+ } else {
+ conf_mask |= DEFAULT_CONF_NAMEPREP;
+ r = parse_nameprep(ctx, argv[1], lineno);
+ }
+ } else if (strcmp(argv[0], "nameprep-map") == 0 ||
+ strcmp(argv[0], "nameprep-normalize") == 0 ||
+ strcmp(argv[0], "nameprep-prohibit") == 0 ||
+ strcmp(argv[0], "nameprep-unassigned") == 0 ||
+ strcmp(argv[0], "alias-file") == 0 ||
+ strcmp(argv[0], "encoding-alias-file") == 0 ||
+ strcmp(argv[0], "normalize") == 0 ||
+ strcmp(argv[0], "server-encoding") == 0 ||
+ strcmp(argv[0], "alternate-encoding") == 0 ||
+ strcmp(argv[0], "delimiter-map") == 0) {
+ WARNING(("libidnkit: obsolete command \"%s\", line %d "
+ "(ignored)\n", argv[0], lineno));
+ r = idn_success;
+ } else {
+ ERROR(("libidnkit: unknown command \"%-.30s\", "
+ "line %d\n", argv[0], lineno));
+ r = idn_invalid_syntax;
+ }
+ if (r != idn_success)
+ return (r);
+ }
+
+ lineno++;
+
+ if (conf_mask != DEFAULT_CONF_ALL) {
+ return setdefaults_body(ctx, conf_mask);
+ }
+
+ return (idn_success);
+}
+
+static idn_result_t
+parse_idn_encoding(idn_resconf_t ctx, char *args, int lineno) {
+ idn_result_t r;
+ char *argv[MAX_CONF_LINE_ARGS + 1];
+ int argc;
+
+ argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
+
+ if (argc != 1) {
+ ERROR(("libidnkit: wrong # of args for idn-encoding, "
+ "line %d\n", lineno));
+ return (idn_invalid_syntax);
+ }
+
+ r = idn_converter_create(argv[0], &ctx->idn_converter,
+ IDN_CONVERTER_DELAYEDOPEN |
+ IDN_CONVERTER_RTCHECK);
+ if (r != idn_success) {
+ ERROR(("libidnkit: cannot create idn converter, %s, "
+ "line %d\n", idn_result_tostring(r), lineno));
+ }
+
+ return (r);
+}
+
+static idn_result_t
+parse_local_map(idn_resconf_t ctx, char *args, int lineno) {
+ idn_result_t r;
+ char *argv[MAX_CONF_LINE_ARGS + 1];
+ int argc;
+ int i;
+
+ argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
+
+ if (argc < 2 || argc > MAX_CONF_LINE_ARGS) {
+ ERROR(("libidnkit: wrong # of args for local-map, line %d\n",
+ lineno));
+ return (idn_invalid_syntax);
+ }
+
+ if (ctx->local_mapper == NULL) {
+ r = idn_mapselector_create(&ctx->local_mapper);
+ if (r != idn_success) {
+ ERROR(("libidnkit: cannot create local mapper, %s, "
+ "line %d\n", idn_result_tostring(r), lineno));
+ return (r);
+ }
+ }
+
+ for (i = 1; i < argc; i++) {
+ r = idn_mapselector_add(ctx->local_mapper, argv[0], argv[i]);
+ if (r == idn_invalid_name) {
+ ERROR(("libidnkit: map scheme unavailable \"%-.30s\""
+ " or invalid TLD \"%-.30s\", line %d\n",
+ argv[i], argv[0], lineno));
+ return (r);
+ } else if (r != idn_success) {
+ return (r);
+ }
+ }
+
+ return (idn_success);
+}
+
+static idn_result_t
+parse_nameprep(idn_resconf_t ctx, char *args, int lineno) {
+ idn_result_t r;
+ char *argv[MAX_CONF_LINE_ARGS + 1];
+ char scheme_name[MAX_CONF_LINE_LENGTH + 1];
+ int argc;
+
+ argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);
+
+ if (argc != 1) {
+ ERROR(("libidnkit: wrong # of args for nameprep, line %d\n",
+ lineno));
+ return (idn_invalid_syntax);
+ }
+
+ /*
+ * Set mapper.
+ */
+ r = idn_mapper_create(&ctx->mapper);
+ if (r != idn_success) {
+ ERROR(("libidnkit: cannot create mapper, %s, line %d\n",
+ idn_result_tostring(r), lineno));
+ return (r);
+ }
+
+ r = idn_mapper_add(ctx->mapper, argv[0]);
+ if (r == idn_invalid_name) {
+ ERROR(("libidnkit: map scheme unavailable \"%-.30s\", "
+ "line %d\n", argv[0], lineno));
+ return (r);
+ } else if (r != idn_success) {
+ return (r);
+ }
+
+ /*
+ * Set normalizer.
+ */
+ r = idn_normalizer_create(&ctx->normalizer);
+ if (r != idn_success) {
+ ERROR(("libidnkit: cannot create normalizer, %s, line %d\n",
+ idn_result_tostring(r), lineno));
+ return (r);
+ }
+
+ r = idn_normalizer_add(ctx->normalizer, argv[0]);
+ if (r == idn_invalid_name) {
+ ERROR(("libidnkit: unknown normalization scheme \"%-.30s\", "
+ "line %d\n", argv[0], lineno));
+ return (r);
+ } else if (r != idn_success) {
+ return (r);
+ }
+
+ /*
+ * Set prohibit checker.
+ */
+ r = idn_checker_create(&ctx->prohibit_checker);
+ if (r != idn_success) {
+ ERROR(("libidnkit: cannot create prohibit checker, %s, "
+ "line %d\n", idn_result_tostring(r), lineno));
+ return (r);
+ }
+
+ sprintf(scheme_name, "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, argv[0]);
+ r = idn_checker_add(ctx->prohibit_checker, scheme_name);
+ if (r == idn_invalid_name) {
+ ERROR(("libidnkit: unknown prohibit scheme \"%-.30s\", "
+ "line %d\n", argv[0], lineno));
+ return (r);
+ } else if (r != idn_success) {
+ return (r);
+ }
+
+ /*
+ * Set unassigned checker.
+ */
+ r = idn_checker_create(&ctx->unassigned_checker);
+ if (r != idn_success) {
+ ERROR(("libidnkit: cannot create unassigned checker, %s, "
+ "line %d\n", idn_result_tostring(r), lineno));
+ return (r);
+ }
+
+ sprintf(scheme_name, "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, argv[0]);
+ r = idn_checker_add(ctx->unassigned_checker, scheme_name);
+ if (r == idn_invalid_name) {
+ ERROR(("libidnkit: unknown unassigned scheme \"%-.30s\", "
+ "line %d\n", argv[0], lineno));
+ return (r);
+ } else if (r != idn_success) {
+ return (r);
+ }
+
+ /*
+ * Set bidi checker.
+ */
+ r = idn_checker_create(&ctx->bidi_checker);
+ if (r != idn_success) {
+ ERROR(("libidnkit: cannot create bidi checker, %s, line %d\n",
+ idn_result_tostring(r), lineno));
+ return (r);
+ }
+
+ sprintf(scheme_name, "%s%s", IDN_CHECKER_BIDI_PREFIX, argv[0]);
+ r = idn_checker_add(ctx->bidi_checker, scheme_name);
+ if (r == idn_invalid_name) {
+ ERROR(("libidnkit: unknown bidi scheme \"%-.30s\", "
+ "line %d\n", argv[0], lineno));
+ return (r);
+ } else if (r != idn_success) {
+ return (r);
+ }
+
+ return (idn_success);
+}
+
+static int
+split_args(char *s, char **av, int max_ac) {
+ int ac;
+ int i;
+
+ for (ac = 0; *s != '\0' && ac < max_ac; ac++) {
+ if (ac > 0)
+ *s++ = '\0';
+ while (isspace((unsigned char)*s))
+ s++;
+ if (*s == '\0')
+ break;
+ if (*s == '"' || *s == '\'') {
+ int qc = *s++;
+ av[ac] = s;
+ while (*s != qc) {
+ if (*s == '\0')
+ return (-1);
+ s++;
+ }
+ } else {
+ av[ac] = s;
+ while (*s != '\0' && !isspace((unsigned char)*s))
+ s++;
+ }
+ }
+
+ for (i = ac; i < max_ac; i++)
+ av[i] = NULL;
+
+ return (ac);
+}
+
+static void
+resetconf(idn_resconf_t ctx) {
+#ifndef WITHOUT_ICONV
+ idn_resconf_setlocalconverter(ctx, NULL);
+#endif
+ idn_resconf_setidnconverter(ctx, NULL);
+ idn_resconf_setauxidnconverter(ctx, NULL);
+ idn_resconf_setdelimitermap(ctx, NULL);
+ idn_resconf_setlocalmapselector(ctx, NULL);
+ idn_resconf_setmapper(ctx, NULL);
+ idn_resconf_setnormalizer(ctx, NULL);
+ idn_resconf_setprohibitchecker(ctx, NULL);
+ idn_resconf_setunassignedchecker(ctx, NULL);
+ idn_resconf_setbidichecker(ctx, NULL);
+}
+
+#ifndef WITHOUT_ICONV
+static idn_result_t
+update_local_converter(idn_resconf_t ctx) {
+ idn_result_t r;
+ const char *old_encoding;
+ const char *new_encoding;
+
+ /*
+ * We don't update local converter, if the converter is set
+ * by idn_resconf_setlocalconverter() or
+ * idn_resconf_setlocalconvertername().
+ */
+ if (ctx->local_converter_is_static)
+ return (idn_success);
+
+ /*
+ * Update the local converter if the local encoding is changed.
+ */
+ old_encoding = (ctx->local_converter != NULL) ?
+ idn_converter_localencoding(ctx->local_converter) :
+ NULL;
+ new_encoding = idn_localencoding_name();
+ if (new_encoding == NULL) {
+ ERROR(("cannot determine local codeset name\n"));
+ return (idn_notfound);
+ }
+
+ if (old_encoding != NULL &&
+ new_encoding != NULL &&
+ strcmp(old_encoding, new_encoding) == 0) {
+ return (idn_success);
+ }
+
+ if (ctx->local_converter != NULL) {
+ idn_converter_destroy(ctx->local_converter);
+ ctx->local_converter = NULL;
+ }
+
+ r = idn_converter_create(new_encoding,
+ &ctx->local_converter,
+ IDN_CONVERTER_RTCHECK);
+ return (r);
+}
+#endif
+
+idn_result_t
+idn_resconf_setdefaults(idn_resconf_t ctx)
+{
+ idn_result_t r;
+
+ assert(ctx != NULL);
+
+ TRACE(("idn_resconf_setdefaults()\n"));
+
+ resetconf(ctx);
+ r = idn_delimitermap_create(&ctx->delimiter_mapper);
+ if (r != idn_success) {
+ ERROR(("libidnkit: cannot create delimiter mapper, %s\n",
+ idn_result_tostring(r)));
+ return (r);
+ }
+
+ return setdefaults_body(ctx, 0);
+}
+
+static idn_result_t
+setdefaults_body(idn_resconf_t ctx, int conf_mask) {
+ idn_result_t r;
+
+ TRACE(("setdefaults_body()\n"));
+ assert(ctx != NULL);
+
+ if (!(conf_mask & DEFAULT_CONF_NAMEPREP)) {
+ TRACE(("set default nameprep\n"));
+ r = idn_resconf_setnameprepversion(ctx, IDN_NAMEPREP_CURRENT);
+ if (r != idn_success) {
+ return (r);
+ }
+ }
+ if (!(conf_mask & DEFAULT_CONF_IDN_ENCODING)) {
+ TRACE(("set default idn encoding\n"));
+ r = idn_converter_create(IDN_ENCODING_CURRENT,
+ &ctx->idn_converter,
+ IDN_CONVERTER_DELAYEDOPEN |
+ IDN_CONVERTER_RTCHECK);
+ if (r != idn_success) {
+ ERROR(("libidnkit: cannot create idn converter, %s\n",
+ idn_result_tostring(r)));
+ return (r);
+ }
+ }
+
+ return (idn_success);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/result.c b/contrib/idn/idnkit-1.0-src/lib/result.c
new file mode 100644
index 0000000..c5745a2
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/result.c
@@ -0,0 +1,76 @@
+#ifndef lint
+static char *rcsid = "$Id: result.c,v 1.1.1.1 2003/06/04 00:26:12 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+#include <idn/result.h>
+
+static char *result_string[] = {
+ "success",
+ "not found",
+ "invalid encoding found",
+ "syntax error",
+ "invalid name",
+ "invalid message",
+ "invalid action",
+ "invalid code point",
+ "label length reduced to 0 or exceeded 63 bytes",
+ "buffer overflow",
+ "no such entry",
+ "out of memory",
+ "no such file",
+ "no mapping to output codeset",
+ "context information required",
+ "prohibited character found",
+ "generic failure",
+};
+
+char *
+idn_result_tostring(idn_result_t result) {
+ if (result < 0 || result > idn_failure)
+ return ("unknown result code");
+
+ return (result_string[result]);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/strhash.c b/contrib/idn/idnkit-1.0-src/lib/strhash.c
new file mode 100644
index 0000000..1d2d03a
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/strhash.c
@@ -0,0 +1,283 @@
+#ifndef lint
+static char *rcsid = "$Id: strhash.c,v 1.1.1.1 2003/06/04 00:26:13 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/result.h>
+#include <idn/strhash.h>
+
+/*
+ * Initially, the number of hash buckets is INITIAL_HASH_SIZE.
+ * As the more elements are put in the hash, the number of elements
+ * per bucket will exceed THRESHOLD eventually. When it happens,
+ * the number of buckets will be multiplied by FACTOR.
+ */
+#define INITIAL_HASH_SIZE 67
+#define FACTOR 7
+#define THRESHOLD 5
+
+#define HASH_MULT 31
+
+typedef struct strhash_entry {
+ struct strhash_entry *next;
+ unsigned long hash_value;
+ char *key;
+ void *value;
+} strhash_entry_t;
+
+struct idn__strhash {
+ int nbins;
+ int nelements;
+ strhash_entry_t **bins;
+};
+
+static unsigned long hash_value(const char *key);
+static strhash_entry_t *find_entry(strhash_entry_t *entry, const char *key,
+ unsigned long hash);
+static strhash_entry_t *new_entry(const char *key, void *value);
+static idn_result_t expand_bins(idn__strhash_t hash, int new_size);
+
+idn_result_t
+idn__strhash_create(idn__strhash_t *hashp) {
+ idn__strhash_t hash;
+ idn_result_t r;
+
+ TRACE(("idn__strhash_create()\n"));
+
+ assert(hashp != NULL);
+
+ *hashp = NULL;
+
+ if ((hash = malloc(sizeof(struct idn__strhash))) == NULL) {
+ WARNING(("idn__strhash_create: malloc failed (hash)\n"));
+ return (idn_nomemory);
+ }
+ hash->nbins = 0;
+ hash->nelements = 0;
+ hash->bins = NULL;
+ if ((r = expand_bins(hash, INITIAL_HASH_SIZE)) != idn_success) {
+ WARNING(("idn__strhash_create: malloc failed (bins)\n"));
+ free(hash);
+ return (r);
+ }
+
+ *hashp = hash;
+
+ return (idn_success);
+}
+
+void
+idn__strhash_destroy(idn__strhash_t hash, idn__strhash_freeproc_t proc) {
+ int i;
+
+ assert(hash != NULL && hash->bins != NULL);
+
+ for (i = 0; i < hash->nbins; i++) {
+ strhash_entry_t *bin = hash->bins[i];
+ strhash_entry_t *next;
+
+ while (bin != NULL) {
+ next = bin->next;
+ if (proc != NULL)
+ (*proc)(bin->value);
+ free(bin);
+ bin = next;
+ }
+ }
+ free(hash->bins);
+ free(hash);
+}
+
+idn_result_t
+idn__strhash_put(idn__strhash_t hash, const char *key, void *value) {
+ unsigned long h, h_index;
+ strhash_entry_t *entry;
+
+ assert(hash != NULL && key != NULL);
+
+ h = hash_value(key);
+ h_index = h % hash->nbins;
+
+ if ((entry = find_entry(hash->bins[h_index], key, h)) != NULL) {
+ /* Entry exists. Replace the value. */
+ entry->value = value;
+ } else {
+ /* Create new entry. */
+ if ((entry = new_entry(key, value)) == NULL) {
+ return (idn_nomemory);
+ }
+ /* Insert it to the list. */
+ entry->next = hash->bins[h_index];
+ hash->bins[h_index] = entry;
+ hash->nelements++;
+
+ if (hash->nelements > hash->nbins * THRESHOLD) {
+ idn_result_t r;
+ r = expand_bins(hash, hash->nbins * FACTOR);
+ if (r != idn_success) {
+ TRACE(("idn__strhash_put: hash table "
+ "expansion failed\n"));
+ }
+ }
+ }
+
+ return (idn_success);
+}
+
+idn_result_t
+idn__strhash_get(idn__strhash_t hash, const char *key, void **valuep) {
+ unsigned long h;
+ strhash_entry_t *entry;
+
+ assert(hash != NULL && key != NULL && valuep != NULL);
+
+ h = hash_value(key);
+ entry = find_entry(hash->bins[h % hash->nbins], key, h);
+ if (entry == NULL)
+ return (idn_noentry);
+
+ *valuep = entry->value;
+ return (idn_success);
+}
+
+int
+idn__strhash_exists(idn__strhash_t hash, const char *key) {
+ unsigned long h;
+
+ assert(hash != NULL && key != NULL);
+
+ h = hash_value(key);
+ return (find_entry(hash->bins[h % hash->nbins], key, h) != NULL);
+}
+
+static unsigned long
+hash_value(const char *key) {
+ unsigned long h = 0;
+ unsigned char *p = (unsigned char *)key;
+ int c;
+
+ while ((c = *p++) != '\0') {
+ h = h * HASH_MULT + c;
+ }
+ return (h);
+}
+
+static strhash_entry_t *
+find_entry(strhash_entry_t *entry, const char *key, unsigned long hash) {
+ assert(key != NULL);
+
+ while (entry != NULL) {
+ if (entry->hash_value == hash && strcmp(key, entry->key) == 0)
+ return (entry);
+ entry = entry->next;
+ }
+ return (NULL);
+}
+
+static strhash_entry_t *
+new_entry(const char *key, void *value) {
+ strhash_entry_t *entry;
+ int len;
+
+ assert(key != NULL);
+
+ len = strlen(key) + 1;
+ if ((entry = malloc(sizeof(strhash_entry_t) + len)) == NULL) {
+ return (NULL);
+ }
+ entry->next = NULL;
+ entry->hash_value = hash_value(key);
+ entry->key = (char *)(entry + 1);
+ (void)strcpy(entry->key, key);
+ entry->value = value;
+
+ return (entry);
+}
+
+static idn_result_t
+expand_bins(idn__strhash_t hash, int new_size) {
+ strhash_entry_t **old_bins, **new_bins;
+ int old_size;
+ int old_index, new_index;
+
+ new_bins = malloc(sizeof(strhash_entry_t *) * new_size);
+ if (new_bins == NULL)
+ return (idn_nomemory);
+
+ memset(new_bins, 0, sizeof(strhash_entry_t *) * new_size);
+
+ old_bins = hash->bins;
+ old_size = hash->nbins;
+ for (old_index = 0; old_index < old_size; old_index++) {
+ strhash_entry_t *entries = old_bins[old_index];
+
+ while (entries != NULL) {
+ strhash_entry_t *e = entries;
+
+ /* Remove the top element from the linked list. */
+ entries = entries->next;
+
+ /* ..and move to the new hash. */
+ new_index = e->hash_value % new_size;
+ e->next = new_bins[new_index];
+ new_bins[new_index] = e;
+ }
+ }
+
+ hash->nbins = new_size;
+ hash->bins = new_bins;
+
+ if (old_bins != NULL)
+ free(old_bins);
+
+ return (idn_success);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/Makefile.in b/contrib/idn/idnkit-1.0-src/lib/tests/Makefile.in
new file mode 100644
index 0000000..124ccec
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/Makefile.in
@@ -0,0 +1,304 @@
+# $Id: Makefile.in,v 1.2 2004/07/20 07:13:39 marka Exp $
+# Copyright (c) 2000, 2002 Japan Network Information Center.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+.SUFFIXES:
+.SUFFIXES: .tsy .c
+
+top_builddir = ../..
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+CC = @CC@
+SHELL = @SHELL@
+LIBTOOL = @LIBTOOL@
+
+ICONVINC = @ICONVINC@
+ICONVLIB = @ICONVLIB@
+IDNLIB = ../libidntest.la
+IDNLITELIB = ../libidntestlite.la
+
+INCS = -I. -I$(srcdir) -I$(srcdir)/../../include -I../../include $(ICONVINC)
+DEFS =
+
+CFLAGS = $(INCS) $(DEFS) @CPPFLAGS@ @CFLAGS@
+LDFLAGS = @LDFLAGS@
+TSYFLAGS =
+
+PERL = @PERL@
+
+COMMONSRCS = testsuite.c testutil.c setenv.c
+COMMONOBJS = testsuite.lo testutil.lo setenv.lo
+BUILTSRCS = api.c api-init1.c api-init2.c api-init3.c \
+ api-init4-1.c api-init4-2.c api-init4-3.c \
+ api-init5-1.c api-init5-2.c api-init5-3.c \
+ res.c resconf.c mapselector.c checker.c converter.c mapper.c \
+ normalizer.c delimitermap.c ucs4.c nameprep.c \
+ testconfig.h
+
+TESTS = api-test \
+ api-init1-test \
+ api-init2-test \
+ api-init3-test \
+ api-init4-1-test \
+ api-init4-2-test \
+ api-init4-3-test \
+ api-init5-1-test \
+ api-init5-2-test \
+ api-init5-3-test \
+ res-test \
+ resconf-test \
+ mapselector-test \
+ converter-test \
+ checker-test \
+ mapper-test \
+ normalizer-test \
+ delimitermap-test \
+ ucs4-test \
+ nameprep-test
+
+LITETESTS = apilite-test \
+ reslite-test \
+ resconflite-test \
+ converterlite-test
+
+.tsy.c:
+ rm -f $@ $@.tmp
+ $(PERL) $(srcdir)/testygen -o $@ $(TSYFLAGS) $<
+ $(PERL) $(srcdir)/utffilter $@ > $@.tmp
+ mv -f $@.tmp $@
+
+all:
+
+install:
+
+clean:
+ rm -f *.o *.lo *.tmp core *.core *~
+ rm -f $(TESTS) $(LITETESTS) $(BUILTSRCS)
+ rm -f test.conf testalias.conf test.map
+ rm -f iconvchk
+ rm -fr .libs/
+
+distclean: clean
+ rm -f Makefile
+
+@LITEONLY_TRUE@test check: test-lite
+@LITEONLY_FALSE@test check: test-nolite
+
+test-lite: $(LITETESTS)
+ @for i in $(LITETESTS); do \
+ echo "Run test program: $$i"; \
+ ./$$i; \
+ echo; \
+ done
+
+test-nolite: $(TESTS) $(LITETESTS) iconvchk
+ @./iconvchk
+ @for i in $(TESTS) $(LITETESTS); do \
+ echo "Run test program: $$i"; \
+ ./$$i; \
+ echo; \
+ done
+
+api-test: api.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ api.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+api.lo: api.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c api.c
+
+apilite-test: apilite.lo $(IDNLITELIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ apilite.lo $(COMMONOBJS) $(IDNLITELIB)
+apilite.lo: api.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -DWITHOUT_ICONV -o $@ \
+ -c api.c
+
+api-init1-test: api-init1.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ api-init1.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+api-init1.lo: api-init1.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c api-init1.c
+
+api-init2-test: api-init2.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ api-init2.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+api-init2.lo: api-init2.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c api-init2.c
+
+api-init3-test: api-init3.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ api-init3.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+api-init3.lo: api-init3.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c api-init3.c
+
+api-init4-1-test: api-init4-1.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ api-init4-1.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+api-init4-1.lo: api-init4-1.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c api-init4-1.c
+
+api-init4-2-test: api-init4-2.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ api-init4-2.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+api-init4-2.lo: api-init4-2.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c api-init4-2.c
+
+api-init4-3-test: api-init4-3.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ api-init4-3.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+api-init4-3.lo: api-init4-3.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c api-init4-3.c
+
+api-init5-1-test: api-init5-1.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ api-init5-1.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+api-init5-1.lo: api-init5-1.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c api-init5-1.c
+
+api-init5-2-test: api-init5-2.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ api-init5-2.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+api-init5-2.lo: api-init5-2.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c api-init5-2.c
+
+api-init5-3-test: api-init5-3.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ api-init5-3.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+api-init5-3.lo: api-init5-3.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c api-init5-3.c
+
+res-test: res.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ res.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+res.lo: res.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c res.c
+
+reslite-test: reslite.lo $(IDNLITELIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ reslite.lo $(COMMONOBJS) $(IDNLITELIB)
+reslite.lo: res.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -DWITHOUT_ICONV -o $@ \
+ -c res.c
+
+resconf-test: resconf.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ resconf.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+resconf.lo: resconf.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c resconf.c
+
+resconflite-test: resconflite.lo $(IDNLITELIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ resconflite.lo $(COMMONOBJS) $(IDNLITELIB)
+resconflite.lo: resconf.c testconfig.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -DWITHOUT_ICONV -o $@ \
+ -c resconf.c
+
+mapselector-test: mapselector.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ mapselector.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+mapselector.lo: mapselector.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c mapselector.c
+
+converter-test: converter.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ converter.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+converter.lo: converter.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c converter.c
+
+converterlite-test: converterlite.lo $(IDNLITELIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ converterlite.lo $(COMMONOBJS) $(IDNLITELIB)
+converterlite.lo: converter.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -DWITHOUT_ICONV -o $@ \
+ -c converter.c
+
+checker-test: checker.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ checker.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+checker.lo: checker.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c checker.c
+
+mapper-test: mapper.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ mapper.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+mapper.lo: mapper.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c mapper.c
+
+normalizer-test: normalizer.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ normalizer.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+normalizer.lo: normalizer.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c normalizer.c
+
+delimitermap-test: delimitermap.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ delimitermap.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+delimitermap.lo: delimitermap.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c delimitermap.c
+
+ucs4-test: ucs4.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ ucs4.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+ucs4.lo: ucs4.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c ucs4.c
+
+nameprep-test: nameprep.lo $(IDNLIB) $(COMMONOBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ nameprep.lo $(COMMONOBJS) $(IDNLIB) $(ICONVLIB)
+nameprep.lo: nameprep.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c nameprep.c
+
+testsuite.lo: testsuite.c testsuite.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -o $@ -c $(srcdir)/testsuite.c
+testutil.lo: testutil.c testutil.h
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -o $@ -c $(srcdir)/testutil.c
+setenv.lo: setenv.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -o $@ -c $(srcdir)/setenv.c
+
+testconfig.h: ../../include/config.h
+ rm -f testconfig.h
+ sed -n -e '/HAVE_SETENV/p' -e '/HAVE_UNSETENV/p' \
+ ../../include/config.h > testconfig.h
+
+iconvchk: iconvchk.c codeset.h
+ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@ \
+ $(srcdir)/iconvchk.c $(IDNLIB) $(ICONVLIB)
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/api-init1.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/api-init1.tsy
new file mode 100644
index 0000000..202db15
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/api-init1.tsy
@@ -0,0 +1,113 @@
+#ifndef lint
+static char *rcsid = "$Id: api-init1.tsy,v 1.1.1.1 2003/06/04 00:26:46 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <idn/api.h>
+#include <idn/log.h>
+
+#include "codeset.h"
+#include "setenv.h"
+#include "testutil.h"
+
+#ifndef EUCJP_ENCODING_NAME
+#define EUCJP_ENCODING_NAME "eucJP"
+#endif
+
+#define CONF_FILENAME "test.conf"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: init
+{
+ char to[256];
+ idn_result_t r;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding UTF-8",
+ NULL);
+}
+
+//# TEARDOWN
+// group: init
+{
+ remove(CONF_FILENAME);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: nameinit(0)
+// group: init
+{
+ r = idn__setconffile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_nameinit(0);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_encodename(IDN_ENCODE_APP, "<U+3042>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--l8j");
+
+ r = idn_decodename(IDN_DECODE_APP, "xn--l8j", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "<U+3042>");
+
+ r = idn_decodename2(IDN_DECODE_APP, "xn--l8j", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "<U+3042>");
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/api-init2.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/api-init2.tsy
new file mode 100644
index 0000000..e1561a4
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/api-init2.tsy
@@ -0,0 +1,113 @@
+#ifndef lint
+static char *rcsid = "$Id: api-init2.tsy,v 1.1.1.1 2003/06/04 00:26:47 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <idn/api.h>
+#include <idn/log.h>
+
+#include "codeset.h"
+#include "setenv.h"
+#include "testutil.h"
+
+#ifndef EUCJP_ENCODING_NAME
+#define EUCJP_ENCODING_NAME "eucJP"
+#endif
+
+#define CONF_FILENAME "test.conf"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: init
+{
+ char to[256];
+ idn_result_t r;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding UTF-8",
+ NULL);
+}
+
+//# TEARDOWN
+// group: init
+{
+ remove(CONF_FILENAME);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: nameinit(1)
+// group: init
+{
+ r = idn__setconffile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_nameinit(1);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_encodename(IDN_ENCODE_APP, "<U+3042>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "<U+3042>");
+
+ r = idn_decodename(IDN_DECODE_APP, "xn--l8j", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--l8j");
+
+ r = idn_decodename2(IDN_DECODE_APP, "xn--l8j", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--l8j");
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/api-init3.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/api-init3.tsy
new file mode 100644
index 0000000..9035cab
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/api-init3.tsy
@@ -0,0 +1,117 @@
+#ifndef lint
+static char *rcsid = "$Id: api-init3.tsy,v 1.1.1.1 2003/06/04 00:26:47 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <idn/api.h>
+#include <idn/log.h>
+
+#include "codeset.h"
+#include "setenv.h"
+#include "testutil.h"
+
+#ifndef EUCJP_ENCODING_NAME
+#define EUCJP_ENCODING_NAME "eucJP"
+#endif
+
+#define CONF_FILENAME "test.conf"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: init
+{
+ char to[256];
+ idn_result_t r;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding UTF-8",
+ NULL);
+}
+
+//# TEARDOWN
+// group: init
+{
+ remove(CONF_FILENAME);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call nameinit() twice
+// group: init
+{
+ r = idn__setconffile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_nameinit(1);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_nameinit(0);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_encodename(IDN_ENCODE_APP, "<U+3042>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "<U+3042>");
+
+ r = idn_decodename(IDN_DECODE_APP, "xn--l8j", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--l8j");
+
+ r = idn_decodename2(IDN_DECODE_APP, "xn--l8j", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--l8j");
+
+ remove(CONF_FILENAME);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/api-init4-1.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/api-init4-1.tsy
new file mode 100644
index 0000000..585b581
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/api-init4-1.tsy
@@ -0,0 +1,96 @@
+#ifndef lint
+static char *rcsid = "$Id: api-init4-1.tsy,v 1.1.1.1 2003/06/04 00:26:47 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <idn/api.h>
+#include <idn/log.h>
+
+#include "setenv.h"
+#include "testutil.h"
+
+#define CONF_FILENAME "test.conf"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: init
+{
+ char to[256];
+ idn_result_t r;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding UTF-8",
+ NULL);
+}
+
+//# TEARDOWN
+// group: init
+{
+ remove(CONF_FILENAME);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call encodename() without initialization
+// group: init
+{
+ r = idn__setconffile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_encodename(IDN_ENCODE_APP, "<U+3042>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--l8j");
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/api-init4-2.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/api-init4-2.tsy
new file mode 100644
index 0000000..fd0150b
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/api-init4-2.tsy
@@ -0,0 +1,96 @@
+#ifndef lint
+static char *rcsid = "$Id: api-init4-2.tsy,v 1.1.1.1 2003/06/04 00:26:47 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <idn/api.h>
+#include <idn/log.h>
+
+#include "setenv.h"
+#include "testutil.h"
+
+#define CONF_FILENAME "test.conf"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: init
+{
+ char to[256];
+ idn_result_t r;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding UTF-8",
+ NULL);
+}
+
+//# TEARDOWN
+// group: init
+{
+ remove(CONF_FILENAME);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call decodename() without initialization
+// group: init
+{
+ r = idn__setconffile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_decodename(IDN_DECODE_APP, "xn--l8j", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "<U+3042>");
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/api-init4-3.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/api-init4-3.tsy
new file mode 100644
index 0000000..7da74b9
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/api-init4-3.tsy
@@ -0,0 +1,102 @@
+#ifndef lint
+static char *rcsid = "$Id: api-init4-3.tsy,v 1.1.1.1 2003/06/04 00:26:47 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <idn/api.h>
+#include <idn/log.h>
+
+#include "codeset.h"
+#include "setenv.h"
+#include "testutil.h"
+
+#ifndef EUCJP_ENCODING_NAME
+#define EUCJP_ENCODING_NAME "eucJP"
+#endif
+
+#define CONF_FILENAME "test.conf"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: init
+{
+ char to[256];
+ idn_result_t r;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding UTF-8",
+ NULL);
+}
+
+//# TEARDOWN
+// group: init
+{
+ remove(CONF_FILENAME);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call decodename2() without initialization
+// group: init
+{
+ r = idn__setconffile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_decodename2(IDN_DECODE_APP, "xn--l8j", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "<U+3042>");
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/api-init5-1.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/api-init5-1.tsy
new file mode 100644
index 0000000..5669502
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/api-init5-1.tsy
@@ -0,0 +1,102 @@
+#ifndef lint
+static char *rcsid = "$Id: api-init5-1.tsy,v 1.1.1.1 2003/06/04 00:26:48 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <idn/api.h>
+#include <idn/log.h>
+
+#include "setenv.h"
+#include "testutil.h"
+
+#define CONF_FILENAME "test.conf"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: init
+{
+ char to[256];
+ idn_result_t r;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding UTF-8",
+ NULL);
+}
+
+//# TEARDOWN
+// group: init
+{
+ remove(CONF_FILENAME);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call encodename() and nameinit()
+// group: init
+{
+ r = idn__setconffile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_encodename(IDN_ENCODE_APP, "aaa", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_nameinit(1);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_encodename(IDN_ENCODE_APP, "<U+3042>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--l8j");
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/api-init5-2.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/api-init5-2.tsy
new file mode 100644
index 0000000..bf08862
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/api-init5-2.tsy
@@ -0,0 +1,102 @@
+#ifndef lint
+static char *rcsid = "$Id: api-init5-2.tsy,v 1.1.1.1 2003/06/04 00:26:48 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <idn/api.h>
+#include <idn/log.h>
+
+#include "setenv.h"
+#include "testutil.h"
+
+#define CONF_FILENAME "test.conf"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: init
+{
+ char to[256];
+ idn_result_t r;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding UTF-8",
+ NULL);
+}
+
+//# TEARDOWN
+// group: init
+{
+ remove(CONF_FILENAME);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call decodename() and nameinit()
+// group: init
+{
+ r = idn__setconffile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_decodename(IDN_DECODE_APP, "aaa", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_nameinit(1);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_decodename(IDN_DECODE_APP, "xn--l8j", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "<U+3042>");
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/api-init5-3.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/api-init5-3.tsy
new file mode 100644
index 0000000..fae1942
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/api-init5-3.tsy
@@ -0,0 +1,109 @@
+#ifndef lint
+static char *rcsid = "$Id: api-init5-3.tsy,v 1.1.1.1 2003/06/04 00:26:48 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <idn/api.h>
+#include <idn/log.h>
+
+#include "codeset.h"
+#include "setenv.h"
+#include "testutil.h"
+
+#ifndef EUCJP_ENCODING_NAME
+#define EUCJP_ENCODING_NAME "eucJP"
+#endif
+
+#define CONF_FILENAME "test.conf"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: init
+{
+ char to[256];
+ idn_result_t r;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding UTF-8",
+ NULL);
+}
+
+//# TEARDOWN
+// group: init
+{
+ remove(CONF_FILENAME);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call decodename2() and nameinit()
+// group: init
+{
+ r = idn__setconffile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_decodename2(IDN_DECODE_APP, "aaa", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_nameinit(1);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_decodename2(IDN_DECODE_APP, "xn--l8j", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "<U+3042>");
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/api.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/api.tsy
new file mode 100644
index 0000000..3ecfb20
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/api.tsy
@@ -0,0 +1,1009 @@
+#ifndef lint
+static char *rcsid = "$Id: api.tsy,v 1.1.1.1 2003/06/04 00:26:50 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <idn/api.h>
+#include <idn/log.h>
+
+#include "codeset.h"
+#include "setenv.h"
+
+#ifndef EUCJP_ENCODING_NAME
+#define EUCJP_ENCODING_NAME "eucJP"
+#endif
+
+/*
+ * U+304B: hiragana letter KA
+ * U+3099: combining katakana-hiragana voiced sound mark
+ *
+ * map("U+304B U+3099") -> "U+304C"
+ *
+ * U+304C: hiragana letter GA
+ */
+#define UTF8_NAME "A<U+304B><U+3099>"
+#define UTF8_REVNAME "a<U+304C>"
+
+/*
+ * A4AC: hiragana letter GA (in EUC-JP)
+ */
+#define EUCJP_NAME "\xa4\xac"
+#define EUCJP_REVNAME "\xa4\xac"
+
+/*
+ * Conversion result of "U+304B U+3099 A"
+ */
+#define PUNYCODE_NAME "xn--a-i8t"
+
+/*
+ * Conversion result of "A U+304B U+3099" (in EUC-JP).
+ */
+#define AUX_EUCJP_NAME "xn--a-i\xa3\xb8t"
+
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: generic-conversion
+//--
+// Initialize the `api' module.
+// Set local encoding to `UTF-8'.
+{
+ char to[256];
+ idn_result_t r;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+ idn_nameinit(0);
+}
+
+//# SETUP
+// group: quiet
+//--
+// Set log level to `fatal' to supress log messages.
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+//--
+// Restore log level.
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: basic conversion by encodename()
+// group: generic-conversion
+{
+ r = idn_encodename(IDN_ENCODE_APP, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: basic conversion by decodename()
+// group: generic-conversion
+{
+ r = idn_decodename(IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+}
+
+//# TESTCASE
+// title: basic conversion by decodename2()
+// group: generic-conversion
+{
+ r = idn_decodename2(IDN_DECODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+#ifdef WITHOUT_ICONV
+ ASSERT_RESULT(r, idn_failure);
+#else
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename2() with auxencoding=NULL
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to),
+ NULL);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+#endif
+}
+
+//# TESTCASE
+// title: call encodename() with actions=0
+// group: generic-conversion
+{
+ r = idn_encodename(0, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+}
+
+//# TESTCASE
+// title: call decodename() with actions=0
+// group: generic-conversion
+{
+ r = idn_decodename(0, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=0
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(0, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+#endif
+}
+
+//# TESTCASE
+// title: call encodename() with actions=rtcheck
+// group: generic-conversion quiet
+{
+ r = idn_encodename(IDN_RTCHECK, EUCJP_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call encodename() with actions=decode-query
+// group: generic-conversion quiet
+{
+ r = idn_encodename(IDN_DECODE_QUERY, EUCJP_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call encodename() with actions=decode-app
+// group: generic-conversion quiet
+{
+ r = idn_encodename(IDN_DECODE_APP, EUCJP_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call encodename() with actions=decode-stored
+// group: generic-conversion quiet
+{
+ r = idn_encodename(IDN_DECODE_STORED, EUCJP_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call encodename() with actions=(1<<31)
+// group: generic-conversion quiet
+{
+ r = idn_encodename(1 << 31, EUCJP_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename() with actions=localmap
+// group: generic-conversion quiet
+{
+ r = idn_decodename(IDN_LOCALMAP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=localmap
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(IDN_LOCALMAP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=lencheck
+// group: generic-conversion quiet
+{
+ r = idn_decodename(IDN_LENCHECK, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=lencheck
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(IDN_LENCHECK, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=encode-query
+// group: generic-conversion quiet
+{
+ r = idn_decodename(IDN_ENCODE_QUERY, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=encode-query
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(IDN_ENCODE_QUERY, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=encode-app
+// group: generic-conversion quiet
+{
+ r = idn_decodename(IDN_ENCODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=encode-app
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(IDN_ENCODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=encode-stored
+// group: generic-conversion quiet
+{
+ r = idn_decodename(IDN_ENCODE_STORED, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=encode-stored
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(IDN_ENCODE_STORED, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=(1<<31)
+// group: generic-conversion quiet
+{
+ r = idn_decodename(1 << 31, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=(1<<31)
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(1 << 31, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call encodename() with actions=localconv
+// group: generic-conversion quiet
+{
+#ifndef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_encodename(IDN_LOCALCONV, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=localconv
+// group: generic-conversion quiet
+{
+#ifndef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename(IDN_LOCALCONV, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=localconv
+// group: generic-conversion
+{
+#ifndef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(IDN_LOCALCONV, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_failure);
+#endif
+}
+
+//# TESTCASE
+// title: call enable(0) and then encodename()
+// group: generic-conversion
+{
+ idn_enable(0);
+ r = idn_encodename(IDN_ENCODE_APP, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+}
+
+//# TESTCASE
+// title: call decodename() when IDN_DISABLE is defined
+// group: generic-conversion
+{
+ idn_enable(0);
+ r = idn_decodename(IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: call decodename() when IDN_DISABLE is defined
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ idn_enable(0);
+ r = idn_decodename2(IDN_DECODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+#endif
+}
+
+//# TESTCASE
+// title: call enable(0) and then encodename()
+// group: generic-conversion
+{
+ idn_enable(0);
+ r = idn_encodename(IDN_ENCODE_APP, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+}
+
+//# TESTCASE
+// title: call enable(0) and then decodename()
+// group: generic-conversion
+{
+ idn_enable(0);
+ r = idn_decodename(IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: call enable(0) and then decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ idn_enable(0);
+ r = idn_decodename2(IDN_DECODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+#endif
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE and call encodename()
+// group: generic-conversion
+{
+ setenv("IDN_DISABLE", "1", 1);
+ r = idn_encodename(IDN_ENCODE_APP, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE and call decodename()
+// group: generic-conversion
+{
+ setenv("IDN_DISABLE", "1", 1);
+ r = idn_decodename(IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE and call decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ setenv("IDN_DISABLE", "1", 1);
+ r = idn_decodename2(IDN_DECODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+#endif
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE, and then call enable(1) and encodename()
+// group: generic-conversion
+{
+ setenv("IDN_DISABLE", "1", 1);
+ idn_enable(1);
+ r = idn_encodename(IDN_ENCODE_APP, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE, and then call enable(1) and decodename()
+// group: generic-conversion
+{
+ setenv("IDN_DISABLE", "1", 1);
+ idn_enable(1);
+ r = idn_decodename(IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE, and then call enable(1) and decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ setenv("IDN_DISABLE", "1", 1);
+ idn_enable(1);
+ r = idn_decodename2(IDN_DECODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+#endif
+}
+
+//# TESTCASE
+// title: overrun test for arg `to' of encodename()
+// group: generic-conversion
+{
+ /* Normal case */
+ r = idn_encodename(IDN_ENCODE_APP, UTF8_NAME, to,
+ strlen(PUNYCODE_NAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+
+ r = idn_encodename(IDN_ENCODE_APP, UTF8_NAME, to,
+ strlen(PUNYCODE_NAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* enable(0) case */
+ idn_enable(0);
+ r = idn_encodename(IDN_ENCODE_APP, UTF8_NAME, to,
+ strlen(UTF8_NAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+
+ r = idn_encodename(IDN_ENCODE_APP, UTF8_NAME, to,
+ strlen(UTF8_NAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* actions=0 case */
+ idn_enable(1);
+ r = idn_encodename(0, UTF8_NAME, to, strlen(UTF8_NAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+
+ r = idn_encodename(0, UTF8_NAME, to, strlen(UTF8_NAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: overrun test for arg `to' of decodename()
+// group: generic-conversion
+{
+ /* Normal case */
+ r = idn_decodename(IDN_DECODE_APP, PUNYCODE_NAME, to,
+ strlen(UTF8_REVNAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+
+ r = idn_decodename(IDN_DECODE_APP, PUNYCODE_NAME, to,
+ strlen(UTF8_REVNAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* idn_enable(0) case */
+ idn_enable(0);
+ r = idn_decodename(IDN_DECODE_APP, PUNYCODE_NAME, to,
+ strlen(PUNYCODE_NAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+
+ r = idn_decodename(IDN_DECODE_APP, PUNYCODE_NAME, to,
+ strlen(PUNYCODE_NAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* actions=0 case */
+ idn_enable(1);
+ r = idn_decodename(0, PUNYCODE_NAME, to, strlen(PUNYCODE_NAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+
+ r = idn_decodename(0, PUNYCODE_NAME, to, strlen(PUNYCODE_NAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: overrun test for arg `to' of decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* Normal case */
+ r = idn_decodename2(IDN_DECODE_APP, AUX_EUCJP_NAME, to,
+ strlen(UTF8_REVNAME) + 1, EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+
+ r = idn_decodename2(IDN_DECODE_APP, AUX_EUCJP_NAME, to,
+ strlen(UTF8_REVNAME), EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* idn_enable(0) case */
+ idn_enable(0);
+ r = idn_decodename2(IDN_DECODE_APP, AUX_EUCJP_NAME, to,
+ strlen(AUX_EUCJP_NAME) + 1, EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+
+ r = idn_decodename2(IDN_DECODE_APP, AUX_EUCJP_NAME, to,
+ strlen(AUX_EUCJP_NAME), EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* actions=0 case */
+ idn_enable(1);
+ r = idn_decodename2(0, AUX_EUCJP_NAME, to, strlen(AUX_EUCJP_NAME) + 1,
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+
+ r = idn_decodename2(0, AUX_EUCJP_NAME, to, strlen(AUX_EUCJP_NAME),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+#endif
+}
+
+//# TESTCASE
+// title: call encodename() with tolen=0
+// group: generic-conversion
+{
+ r = idn_encodename(IDN_ENCODE_APP, UTF8_NAME, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: call decodename() with tolen=0
+// group: generic-conversion
+{
+ r = idn_decodename(IDN_DECODE_APP, PUNYCODE_NAME, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: call decodename2() with tolen=0
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(IDN_DECODE_APP, AUX_EUCJP_NAME, to, 0,
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+#endif
+}
+
+//# TESTCASE
+// title: convert an empty string using encodename()
+// group: generic-conversion
+{
+ r = idn_encodename(IDN_ENCODE_APP, "", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "");
+}
+
+//# TESTCASE
+// title: convert an empty string using decodename()
+// group: generic-conversion
+{
+ r = idn_decodename(IDN_DECODE_APP, "", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "");
+}
+
+//# TESTCASE
+// title: convert an empty string using decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_decodename2(IDN_DECODE_APP, "", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "");
+#endif
+}
+
+//# TESTCASE
+// title: prohcheck by encodename()
+// group: generic-conversion
+{
+ /* U+1680: prohibited character */
+ r = idn_encodename(IDN_PROHCHECK, "<U+1680>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+}
+
+//# TESTCASE
+// title: unascheck by encodename()
+// group: generic-conversion
+{
+ /* U+0221: unassigned codepoint */
+ r = idn_encodename(IDN_UNASCHECK, "<U+0221>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+}
+
+//# TESTCASE
+// title: bidicheck by encodename()
+// group: generic-conversion
+{
+ /* U+05D0: bidirectional property is "R" */
+ /* `a': bidirectional property is "L" */
+ /* `0', `-': bidirectional property is "N" */
+ r = idn_encodename(IDN_BIDICHECK, "<U+05D0>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_encodename(IDN_BIDICHECK, "<U+05D0><U+05D0>",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_encodename(IDN_BIDICHECK, "<U+05D0><U+05D0>-a",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_encodename(IDN_BIDICHECK, "<U+05D0>-a-<U+05D0>",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_encodename(IDN_BIDICHECK, "a-<U+05D0><U+05D0>",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_encodename(IDN_BIDICHECK, "<U+05D0><U+05D0>-0",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_encodename(IDN_BIDICHECK, "<U+05D0>-0-<U+05D0>",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_encodename(IDN_BIDICHECK, "0-<U+05D0><U+05D0>",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+}
+
+//# TESTCASE
+// title: asccheck by encodename()
+// group: generic-conversion
+{
+ r = idn_encodename(IDN_ASCCHECK, "-name", to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_encodename(IDN_ASCCHECK, "name-", to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_encodename(IDN_ASCCHECK, "n ame", to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+}
+
+//# TESTCASE
+// title: lencheck by encodename()
+// group: generic-conversion
+{
+ r = idn_encodename(IDN_LENCHECK,
+ "123456789-123456789-123456789-123456789-"
+ "123456789-123456789-123", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_encodename(IDN_LENCHECK,
+ "123456789-123456789-123456789-123456789-"
+ "123456789-123456789-1234", to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_length);
+
+ r = idn_encodename(IDN_LENCHECK, "a..b", to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_length);
+}
+
+//# TESTCASE
+// title: rtcheck non-prohchecked label by decodename()
+// group: generic-conversion
+{
+ /* "xn--6ue" -> "U+1680" (prohibited character) */
+ r = idn_decodename(IDN_RTCHECK, "xn--6ue", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--6ue");
+}
+
+//# TESTCASE
+// title: rtcheck non-unaschecked label by decodename()
+// group: generic-conversion
+{
+ /* "xn--6la" -> "U+0221" (unassigned codepoint) */
+ r = idn_decodename(IDN_IDNCONV | IDN_RTCHECK | IDN_UNASCHECK,
+ "xn--6la", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--6la");
+}
+
+//# TESTCASE
+// title: rtcheck non-ascchecked label by decodename()
+// group: generic-conversion
+{
+ /* "xn----x7t" -> "- U+3042" */
+ r = idn_decodename(IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK,
+ "xn----x7t", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn----x7t");
+
+ /* "xn----w7t" -> "U+3042 -" */
+ r = idn_decodename(IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK,
+ "xn----w7t", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn----w7t");
+}
+
+//# TESTCASE
+// title: rtcheck non-lenchecked label by decodename()
+// group: generic-conversion
+{
+ /* `s1' has 63 characters */
+ const char *s1 =
+ "xn--l8jaa5522a8sj38bzugvvblo3y90fjzgvxlmxscifws3d43odzaq6aj340b";
+
+ const char *s1rev =
+ "<U+9752><U+68EE><U+5CA9><U+624B><U+5BAE><U+57CE><U+79CB><U+7530>"
+ "<U+5C71><U+5F62><U+798F><U+5CF6><U+6771><U+4EAC><U+795E><U+5948>"
+ "<U+5DDD><U+3042><U+3042><U+3042>";
+
+ /* `s2' has 64 characters */
+ const char *s2 =
+ "xn--a-w7ta6522a8sj38bzugvvblo3y90fjzgvxlmxscifws3d43odzaq6aj340b";
+
+ /* `s3' has an empty label */
+ const char *s3 = "a..b";
+
+ r = idn_decodename(IDN_IDNCONV | IDN_RTCHECK, s1, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s1rev);
+
+ r = idn_decodename(IDN_IDNCONV | IDN_RTCHECK, s2, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s2);
+
+ r = idn_decodename(IDN_IDNCONV | IDN_RTCHECK, s3, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s3);
+}
+
+//# TESTCASE
+// title: rtcheck non-prohchecked label by decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* "xn--6ue" -> "U+1680" (prohibited character) */
+ r = idn_decodename2(IDN_RTCHECK, "xn--6ue", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--6ue");
+#endif
+}
+
+//# TESTCASE
+// title: rtcheck non-unaschecked label by decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* "xn--6la" -> "U+0221" (unassigned codepoint) */
+ r = idn_decodename2(IDN_IDNCONV | IDN_RTCHECK | IDN_UNASCHECK,
+ "xn--6la", to, sizeof(to), EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--6la");
+#endif
+}
+
+//# TESTCASE
+// title: rtcheck non-ascchecked label by decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* "xn----x7t" -> "- U+3042" */
+ r = idn_decodename2(IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK,
+ "xn----x7t", to, sizeof(to), EUCJP_ENCODING_NAME);
+
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn----x7t");
+
+ /* "xn----w7t" -> "U+3042 -" */
+ r = idn_decodename2(IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK,
+ "xn----w7t", to, sizeof(to), EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn----w7t");
+#endif
+}
+
+//# TESTCASE
+// title: rtcheck non-lenchecked label by decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* `s1' has 63 characters */
+ const char *s1 =
+ "xn--l8jaa5522a8sj38bzugvvblo3y90fjzgvxlmxscifws3d43odzaq6aj340b";
+
+ const char *s1rev =
+ "<U+9752><U+68EE><U+5CA9><U+624B><U+5BAE><U+57CE><U+79CB><U+7530>"
+ "<U+5C71><U+5F62><U+798F><U+5CF6><U+6771><U+4EAC><U+795E><U+5948>"
+ "<U+5DDD><U+3042><U+3042><U+3042>";
+
+ /* `s2' has 64 characters */
+ const char *s2 =
+ "xn--a-w7ta6522a8sj38bzugvvblo3y90fjzgvxlmxscifws3d43odzaq6aj340b";
+
+ /* `s3' has an empty label */
+ const char *s3 = "a..b";
+
+ r = idn_decodename2(IDN_IDNCONV | IDN_RTCHECK, s1, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s1rev);
+
+ r = idn_decodename2(IDN_IDNCONV | IDN_RTCHECK, s2, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s2);
+
+ r = idn_decodename(IDN_IDNCONV | IDN_RTCHECK, s3, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s3);
+#endif
+}
+
+//# TESTCASE
+// title: pass broken string as `from' to encodename()
+// group: generic-conversion quiet
+{
+ /* "\xe3\x21" is not valid UTF-8 string */
+ r = idn_encodename(IDN_ENCODE_APP, "\xe3\x21", to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_encoding);
+}
+
+//# TESTCASE
+// title: pass broken string as `from' to decodename()
+// group: generic-conversion quiet
+{
+ /* "\xe3\x21" is not valid UTF-8 string */
+ r = idn_decodename(IDN_DECODE_APP, "\xe3\x21", to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_encoding);
+}
+
+//# TESTCASE
+// title: pass broken string as `from' to decodename2()
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* "\xa4\x21" is not valid EUC-JP string */
+ r = idn_decodename2(IDN_DECODE_APP, "\xa4\x21", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+#endif
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/checker.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/checker.tsy
new file mode 100644
index 0000000..54f8ea0
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/checker.tsy
@@ -0,0 +1,610 @@
+#ifndef lint
+static char *rcsid = "$Id: checker.tsy,v 1.1.1.1 2003/06/04 00:26:51 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <idn/checker.h>
+#include <idn/log.h>
+#include <idn/ucs4.h>
+#include "testutil.h"
+
+#define SIZEOFUCS4(x) (sizeof(x) / sizeof(unsigned long))
+
+#define UCS4_NAME_STR "U+304C" /* hiragana letter ga */
+#define UCS4_NAME 0x304C
+
+#define BUF_SIZE 128
+#define ARRAY_SIZE 9
+
+#define CONF_FILENAME "test.map"
+
+#define LINEBUF_SIZE 2001
+
+/*
+ * Sample strings for `from' argument of normalize(),
+ * and its expected outputs.
+ */
+const unsigned long from[4] = {
+ UCS4_NAME,
+ 0x00A0, /* no-break space: prohibited character */
+ 0x0221, /* unassigned character */
+ 0x0000
+};
+
+
+#define FROM_UCS4NAME_OFFSET 0
+#define FROM_PROH_OFFSET 1
+#define FROM_UNAS_OFFSET 2
+
+const unsigned long from2[4] = {
+ UCS4_NAME,
+ 0x0221, /* unassigned character */
+ 0x00A0, /* no-break space: prohibited character */
+ 0x0000
+};
+
+#define FROM2_UCS4NAME_OFFSET 0
+#define FROM2_PROH_OFFSET 2
+#define FROM2_UNAS_OFFSET 1
+
+static const unsigned long bidi_from[4] = {
+ 0x05BE, /* hebrew punctuation maqaf */
+ 0x0041, /* latin capital letter a */
+ 0xFEFC, /* arabic ligature lam with alef final form */
+ 0x0000
+};
+#define BIDIFROM_OFFSET 1
+
+idn_result_t
+test_createproc(const char *parameter, void **ctxp)
+{
+ return (idn_success);
+}
+
+void
+test_destroyproc(void *ctx)
+{
+}
+
+#define FOUNDPTR_OFFSET 2
+idn_result_t
+test_lookupproc(void *ctx, const unsigned long *ucs4,
+ const unsigned long **found)
+{
+ *found = ucs4 + FOUNDPTR_OFFSET;
+ return (idn_success);
+}
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: generic
+//--
+// Initialize the module and create context.
+{
+ idn_result_t r;
+ idn_checker_t ctx = NULL;
+ char name[BUF_SIZE];
+
+ r = idn_checker_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_checker_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: generic
+//--
+// Destroy context.
+{
+ if (ctx != NULL)
+ idn_checker_destroy(ctx);
+}
+
+//# SETUP
+// group: lookup
+//--
+// Initialize the module and create context.
+{
+ idn_result_t r;
+ idn_checker_t ctx = NULL;
+ char name[BUF_SIZE];
+ const unsigned long *ptr;
+
+ r = idn_checker_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_checker_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: lookup
+//--
+// Destroy context.
+{
+ if (ctx != NULL)
+ idn_checker_destroy(ctx);
+}
+
+//# SETUP
+// group: addall
+//--
+// Initialize the module and create context.
+{
+ idn_result_t r;
+ idn_checker_t ctx = NULL;
+ char *names[ARRAY_SIZE];
+ int i;
+ const unsigned long *ptr;
+
+ for (i = 0; i < ARRAY_SIZE; i++) {
+ names[i] = malloc(BUF_SIZE);
+ if (names[i] == NULL) {
+ ASSERT("malloc failed\n");
+ }
+ }
+
+ r = idn_checker_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_checker_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: addall
+//--
+// Destroy context and free some blocks.
+{
+ if (ctx != NULL)
+ idn_checker_destroy(ctx);
+ for (i = 0; i < ARRAY_SIZE; i++) {
+ free(names[i]);
+ }
+}
+
+//# SETUP
+// group: quiet
+//--
+// Set log level to `fatal' to supress log messages.
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+//--
+// Restore log level.
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: idn_checker_add() - boundary condition
+// group: generic quiet
+{
+ r = idn_checker_add(ctx, "");
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_checker_add() - builtin schemes, prohibit
+// group: generic quiet
+{
+ sprintf(name, "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+
+ sprintf(name, "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "nameprep-01");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_checker_add() - builtin schemes, unassigned
+// group: generic quiet
+{
+ sprintf(name, "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "RFC3491");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+
+ sprintf(name, "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "nameprep-01");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_checker_add() - builtin schemes, bidi
+// group: generic quiet
+{
+ sprintf(name, "%s%s", IDN_CHECKER_BIDI_PREFIX, "RFC3491");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+
+ sprintf(name, "%s%s", IDN_CHECKER_BIDI_PREFIX, "nameprep-01");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_checker_add() - file - boundary condition
+// group: generic quiet
+{
+ sprintf(name, "%sfileset:%s", IDN_CHECKER_UNASSIGNED_PREFIX, "");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_nofile);
+ sprintf(name, "%sfileset:%s", IDN_CHECKER_PROHIBIT_PREFIX, "");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_nofile);
+ sprintf(name, "%sfileset:%s", IDN_CHECKER_BIDI_PREFIX, "");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_checker_add() - file - long line
+// group: generic quiet
+{
+ char line[LINEBUF_SIZE];
+ const char *first_entry = "304C;";
+ const char *other_entry = " 304D";
+ int i;
+ int len;
+
+ memcpy(line, first_entry, strlen(first_entry));
+ len = strlen(other_entry);
+ for (i = len; i < LINEBUF_SIZE - len; i += len) {
+ memcpy(line + i, other_entry, len);
+ }
+ *(line + i) = '\0';
+
+ create_conf_file(CONF_FILENAME, 0, line, NULL);
+ sprintf(name, "%sfileset:%s", IDN_CHECKER_UNASSIGNED_PREFIX,
+ CONF_FILENAME);
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+ sprintf(name, "%sfileset:%s", IDN_CHECKER_PROHIBIT_PREFIX,
+ CONF_FILENAME);
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: idn_checker_add() - file, prohibit
+// group: lookup
+{
+ create_conf_file(CONF_FILENAME, 0,
+ UCS4_NAME_STR,
+ NULL);
+ sprintf(name, "%sfileset:%s", IDN_CHECKER_PROHIBIT_PREFIX,
+ CONF_FILENAME);
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from + FROM_UCS4NAME_OFFSET);
+ r = idn_checker_lookup(ctx, from2, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from2 + FROM2_UCS4NAME_OFFSET);
+}
+
+//# TESTCASE
+// title: idn_checker_add() - file, unassigned
+// group: lookup
+{
+ create_conf_file(CONF_FILENAME, 0,
+ UCS4_NAME_STR,
+ NULL);
+ sprintf(name, "%sfileset:%s", IDN_CHECKER_UNASSIGNED_PREFIX,
+ CONF_FILENAME);
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from + FROM_UCS4NAME_OFFSET);
+ r = idn_checker_lookup(ctx, from2, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from2 + FROM2_UCS4NAME_OFFSET);
+}
+
+//# TESTCASE
+// title: idn_checker_add() - file, bidi
+// group: lookup quiet
+{
+ create_conf_file(CONF_FILENAME, 0,
+ UCS4_NAME_STR,
+ NULL);
+ sprintf(name, "%sfileset:%s", IDN_CHECKER_BIDI_PREFIX,
+ CONF_FILENAME);
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_checker_addall() - boundary condition - scheme name
+// group: addall quiet
+{
+ sprintf(names[0], "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+ sprintf(names[1], "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "RFC3491");
+ sprintf(names[2], "%s%s", IDN_CHECKER_BIDI_PREFIX, "RFC3491");
+ sprintf(names[3], "%s%s", IDN_CHECKER_BIDI_PREFIX, "");
+ r = idn_checker_addall(ctx, (const char **)names, 4);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_checker_addall() - boundary condition - nschemes = 0
+// group: addall quiet
+{
+ sprintf(names[0], "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "nameprep-01");
+ sprintf(names[1], "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "nameprep-01");
+ sprintf(names[2], "%s%s", IDN_CHECKER_BIDI_PREFIX, "");
+ sprintf(names[3], "%s%s", IDN_CHECKER_BIDI_PREFIX, "nameprep-01");
+ r = idn_checker_addall(ctx, (const char **)names, 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, NULL);
+}
+
+//# TESTCASE
+// title: idn_checker_addall() - add a lot of schemes #1
+// group: addall
+{
+ sprintf(names[0], "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+ sprintf(names[1], "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "RFC3491");
+ sprintf(names[2], "%s%s", IDN_CHECKER_BIDI_PREFIX, "RFC3491");
+ sprintf(names[3], "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+ sprintf(names[4], "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "RFC3491");
+ sprintf(names[5], "%s%s", IDN_CHECKER_BIDI_PREFIX, "RFC3491");
+ sprintf(names[6], "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+ sprintf(names[7], "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "RFC3491");
+ sprintf(names[8], "%s%s", IDN_CHECKER_BIDI_PREFIX, "RFC3491");
+
+ r = idn_checker_addall(ctx, (const char **)names, 9);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from + FROM_PROH_OFFSET);
+
+ r = idn_checker_lookup(ctx, from2, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from2 + FROM2_PROH_OFFSET);
+
+ r = idn_checker_lookup(ctx, bidi_from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, bidi_from + BIDIFROM_OFFSET);
+}
+
+//# TESTCASE
+// title: idn_checker_addall() - add a lot of schemes #2
+// group: addall
+{
+ sprintf(names[0], "%s%s", IDN_CHECKER_BIDI_PREFIX, "RFC3491");
+ sprintf(names[1], "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "RFC3491");
+ sprintf(names[2], "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+ sprintf(names[3], "%s%s", IDN_CHECKER_BIDI_PREFIX, "RFC3491");
+ sprintf(names[4], "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "RFC3491");
+ sprintf(names[5], "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+ sprintf(names[6], "%s%s", IDN_CHECKER_BIDI_PREFIX, "RFC3491");
+ sprintf(names[7], "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "RFC3491");
+ sprintf(names[8], "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+
+ r = idn_checker_addall(ctx, (const char **)names, 9);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from + FROM_UNAS_OFFSET);
+
+ r = idn_checker_lookup(ctx, from2, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from2 + FROM2_UNAS_OFFSET);
+
+ r = idn_checker_lookup(ctx, bidi_from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, bidi_from + BIDIFROM_OFFSET);
+}
+
+//# TESTCASE
+// title: idn_checker_addall() - add same scheme repetedly
+// group: addall
+{
+ int i;
+
+ sprintf(names[0], "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+ for (i = 1; i < ARRAY_SIZE; i++) {
+ strcpy(names[i], names[0]);
+ }
+ r = idn_checker_addall(ctx, (const char **)names, ARRAY_SIZE);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from + FROM_PROH_OFFSET);
+
+ r = idn_checker_lookup(ctx, from2, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from2 + FROM2_PROH_OFFSET);
+}
+
+//# TESTCASE
+// title: idn_checker_lookup() - builtin schemes - RFC3491 prohibit
+// group: lookup
+{
+ sprintf(name, "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from + FROM_PROH_OFFSET);
+
+ r = idn_checker_lookup(ctx, from2, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from2 + FROM2_PROH_OFFSET);
+}
+
+//# TESTCASE
+// title: idn_checker_lookup() - builtin schemes - RFC3491 unassigned
+// group: lookup
+{
+ sprintf(name, "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "RFC3491");
+
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from + FROM_UNAS_OFFSET);
+
+ r = idn_checker_lookup(ctx, from2, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from2 + FROM2_UNAS_OFFSET);
+}
+
+//# TESTCASE
+// title: idn_checker_lookup() - builtin schemes - RFC3491 bidi
+// group: lookup
+{
+ sprintf(name, "%s%s", IDN_CHECKER_BIDI_PREFIX, "RFC3491");
+
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_checker_lookup(ctx, bidi_from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, bidi_from + BIDIFROM_OFFSET);
+
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, NULL);
+
+ r = idn_checker_lookup(ctx, from2, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, NULL);
+}
+
+//# TESTCASE
+// title: idn_checker_lookup() - context without procedure
+// group: lookup
+{
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, NULL);
+}
+
+//# TESTCASE
+// title: idn_checker_lookup() - string in ascii
+// group: lookup
+{
+ char *ascii_str = "test";
+ unsigned long ucs4_str[5];
+
+ r = idn_ucs4_utf8toucs4(ascii_str, ucs4_str, SIZEOFUCS4(ucs4_str));
+
+ sprintf(name, "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, "RFC3491");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+ sprintf(name, "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, "RFC3491");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+ sprintf(name, "%s%s", IDN_CHECKER_BIDI_PREFIX, "RFC3491");
+ r = idn_checker_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_checker_lookup(ctx, ucs4_str, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, NULL);
+}
+
+//# TESTCASE
+// title: idn_checker_destroy(), idn_checker_incrref()
+// group:
+{
+ idn_result_t r;
+ idn_checker_t ctx = NULL;
+
+ r = idn_checker_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_checker_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+ idn_checker_incrref(ctx);
+ idn_checker_destroy(ctx);
+ idn_checker_destroy(ctx);
+}
+
+//# TESTCASE
+// title: idn_checker_register()
+// group: generic
+{
+ const unsigned long *ptr = NULL;
+
+ r = idn_checker_register("test",
+ test_createproc,
+ test_destroyproc,
+ test_lookupproc);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_checker_add(ctx, "test");
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_checker_lookup(ctx, from, &ptr);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(ptr, from + FOUNDPTR_OFFSET);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/codeset.h b/contrib/idn/idnkit-1.0-src/lib/tests/codeset.h
new file mode 100644
index 0000000..735a023
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/codeset.h
@@ -0,0 +1,71 @@
+/* $Id: codeset.h,v 1.1.1.1 2003/06/04 00:26:51 marka Exp $ */
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef CODESET_H
+#define CODESET_H
+
+/*
+ * Character encoding name that iconv() recognizes as Japanese EUC.
+ *
+ * Please edit the cpp macro definition if iconv() on the system doesn't
+ * recognize "EUC-JP".
+ *
+ * NOTE:
+ * Konstantin Chuguev's iconv-2.0 doesn't accept "eucJP", but "euc-jp".
+ */
+#define EUCJP_ENCODING_NAME "eucJP"
+
+
+/*
+ * Character encoding name that iconv() recognizes as Japanese Shift JIS.
+ *
+ * Please edit the cpp macro definition if iconv() on the system doesn't
+ * recognize "SJIS".
+ *
+ * NOTE:
+ * Konstantin Chuguev's iconv-2.0 doesn't accept "SJIS", but "Shift_JIS".
+ */
+#define SJIS_ENCODING_NAME "SJIS"
+
+#endif /* CODESET_H */
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/converter.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/converter.tsy
new file mode 100644
index 0000000..94c865e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/converter.tsy
@@ -0,0 +1,822 @@
+#ifndef lint
+static char *rcsid = "$Id: converter.tsy,v 1.1.1.1 2003/06/04 00:26:53 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <idn/converter.h>
+#include <idn/log.h>
+
+#include "codeset.h"
+#include "testutil.h"
+
+
+#ifndef IDN_PUNYCODE_ENCODING_NAME
+#define IDN_PUNYCODE_ENCODING_NAME "Punycode"
+#endif
+
+#ifndef IDN_UTF8_ENCODING_NAME
+#define IDN_UTF8_ENCODING_NAME "UTF-8" /* by IANA */
+#endif
+
+#ifndef EUCJP_ENCODING_NAME
+#define EUCJP_ENCODING_NAME "eucJP"
+#endif
+
+#ifndef SJIS_ENCODING_NAME
+#define SJIS_ENCODING_NAME "SJIS"
+#endif
+
+#define CONF_FILENAME "testalias.conf"
+#define LINEBUF_SIZE 2001
+
+#define SIZEOFUCS4(x) (sizeof(x) / sizeof(unsigned long))
+
+/*
+ * U+1820: mongorian letter a
+ */
+#define UCS4_INVALID_NAME_FOR_EUCJP 0x1820
+
+/*
+ * A4AC: hiragana letter GA (in EUC-JP)
+ */
+#define EUCJP_NAME "\xa4\xac"
+#define EUCJP_NAME_SIZE 3
+
+/*
+ * U+304C: hiragana letter GA
+ */
+#define UCS4_NAME 0x304C
+
+/*
+ * Conversion result of "U+304C"
+ */
+#define PUNYCODE_NAME "xn--v8j"
+#define PUNYCODE_NAME_SIZE 8
+
+#define BUF_SIZE 128
+
+idn_result_t
+idn_test_encode(idn_converter_t ctx, void *privdata,
+ const unsigned long *from, char *to, size_t tolen)
+{
+ idn_result_t r;
+
+ if (tolen >= EUCJP_NAME_SIZE) {
+ strcpy(to, EUCJP_NAME);
+ r = idn_success;
+ } else {
+ r = idn_buffer_overflow;
+ }
+ return (r);
+
+}
+
+idn_result_t
+idn_test_decode(idn_converter_t ctx, void *privdata,
+ const char *from, unsigned long *to, size_t tolen)
+{
+ idn_result_t r;
+
+ if (tolen >= 2) {
+ to[0] = UCS4_NAME;
+ to[1] = 0x0000;
+ r = idn_success;
+ } else {
+ r = idn_buffer_overflow;
+ }
+ return (r);
+}
+
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: noinit
+//--
+// Do nothing
+{
+ idn_result_t r;
+}
+
+//# SETUP
+// group: generic
+//--
+// Initialize the module.
+{
+ idn_result_t r;
+ idn_converter_t ctx = NULL;
+ const char *name;
+
+ r = idn_converter_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_resetalias();
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# SETUP
+// group: localencoding
+//--
+// Initialize the module and load alias file.
+{
+ idn_result_t r;
+ idn_converter_t ctx = NULL;
+ const char *name;
+
+ r = idn_converter_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_resetalias();
+ ASSERT_RESULT(r, idn_success);
+ create_conf_file(CONF_FILENAME, 0,
+ "*.KOI8-R KOI8-R",
+ "*.ISO_8859-1 ISO-8859-1",
+ "*.ISO_8859-2 ISO-8859-1",
+ "*.UTF-8 UTF-8",
+ "ja_JP.EUC eucJP",
+ "japanese eucJP",
+ NULL);
+ r = idn_converter_aliasfile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: localencoding
+//--
+// reset alias information.
+{
+ idn_converter_resetalias();
+}
+
+//# SETUP
+// group: conversion
+//--
+// Initialize the module and create contexts.
+{
+ idn_result_t r;
+ idn_converter_t punycode_ctx = NULL;
+ idn_converter_t utf8_ctx = NULL;
+#ifndef WITHOUT_ICONV
+ idn_converter_t eucjp_ctx = NULL;
+#endif
+
+ r = idn_converter_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_create(IDN_PUNYCODE_ENCODING_NAME, &punycode_ctx,
+ 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_create(IDN_UTF8_ENCODING_NAME, &utf8_ctx,
+ IDN_CONVERTER_DELAYEDOPEN);
+ ASSERT_RESULT(r, idn_success);
+#ifndef WITHOUT_ICONV
+ r = idn_converter_create(EUCJP_ENCODING_NAME, &eucjp_ctx,
+ IDN_CONVERTER_DELAYEDOPEN);
+ ASSERT_RESULT(r, idn_success);
+#endif
+}
+
+//# TEARDOWN
+// group: conversion
+//--
+// Destroy contexts.
+{
+ if (punycode_ctx != NULL) {
+ idn_converter_destroy(punycode_ctx);
+ }
+ if (utf8_ctx != NULL) {
+ idn_converter_destroy(utf8_ctx);
+ }
+#ifndef WITHOUT_ICONV
+ if (eucjp_ctx != NULL) {
+ idn_converter_destroy(eucjp_ctx);
+ }
+#endif
+}
+
+//# SETUP
+// group: quiet
+//--
+// Set log level to `fatal' to supress log messages.
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+//--
+// Restore log level.
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: idn_converter_addalias() test - without initialization
+// group: noinit quiet
+{
+ r = idn_converter_addalias("a", "b", 0);
+ ASSERT_RESULT(r, idn_failure);
+}
+
+//# TESTCASE
+// title: idn_converter_aliasfile() - without initialization
+// group: noinit quiet
+{
+ r = idn_converter_aliasfile("a");
+ ASSERT_RESULT(r, idn_failure);
+}
+
+//# TESTCASE
+// title: idn_converter_resetalias() - without initialization
+// group: noinit quiet
+{
+ r = idn_converter_resetalias();
+ ASSERT_RESULT(r, idn_failure);
+}
+
+//# TESTCASE
+// title: idn_converter_getrealname() - without initialization
+// group: noinit quiet
+{
+ const char *name;
+
+ name = idn_converter_getrealname("test");
+ ASSERT_STRING(name, "test");
+}
+
+//# TESTCASE
+// title: idn_converter_create()
+// group: generic quiet
+{
+#ifdef WITHOUT_ICONV
+ r = idn_converter_addalias("*pc", "Punycode", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("*ej", EUCJP_ENCODING_NAME, 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("*sj", SJIS_ENCODING_NAME, 0);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_converter_create("abcsj", &ctx, 0);
+ ASSERT_RESULT(r, idn_invalid_name);
+
+ r = idn_converter_create("notresolved", &ctx, 0);
+ ASSERT_RESULT(r, idn_invalid_name);
+ r = idn_converter_create("notresolved", &ctx,
+ IDN_CONVERTER_DELAYEDOPEN);
+ ASSERT_RESULT(r, idn_invalid_name);
+#else
+ r = idn_converter_addalias("*pc", IDN_PUNYCODE_ENCODING_NAME, 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("*ej", EUCJP_ENCODING_NAME, 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("*sj", SJIS_ENCODING_NAME, 0);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_converter_create("abcsj", &ctx, 0);
+ ASSERT_RESULT(r, idn_success);
+ idn_converter_destroy(ctx);
+
+ r = idn_converter_create("notresolved", &ctx, 0);
+ ASSERT_RESULT(r, idn_invalid_name);
+ r = idn_converter_create("notresolved", &ctx,
+ IDN_CONVERTER_DELAYEDOPEN);
+ ASSERT_RESULT(r, idn_success);
+ {
+ unsigned long ucs4_to[BUF_SIZE];
+
+ r = idn_converter_convtoucs4(ctx, "a", ucs4_to, BUF_SIZE);
+ ASSERT_RESULT(r, idn_invalid_name);
+ idn_converter_destroy(ctx);
+ }
+#endif /* WITHOUT_ICONV */
+}
+
+//# TESTCASE
+// title: idn_converter_addalias() - #1
+// group: generic
+{
+ r = idn_converter_addalias("test", "result-a", 0);
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("test");
+ ASSERT_STRING(name, "result-a");
+}
+
+//# TESTCASE
+// title: idn_converter_addalias() - #2
+// group: generic
+{
+ r = idn_converter_addalias("test", "result-b", 1);
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("test");
+ ASSERT_STRING(name, "result-b");
+}
+
+//# TESTCASE
+// title: idn_converter_addalias() - #3
+// group: generic
+{
+ r = idn_converter_addalias("test", "result-a", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-b", 0);
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("test");
+ ASSERT_STRING(name, "result-a");
+}
+
+//# TESTCASE
+// title: idn_converter_addalias() - #4
+// group: generic
+{
+ r = idn_converter_addalias("test", "result-a", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-b", 1);
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("test");
+ ASSERT_STRING(name, "result-b");
+}
+
+//# TESTCASE
+// title: idn_converter_addalias() - #5
+// group: generic
+{
+ r = idn_converter_addalias("test", "result-a", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-b", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-c", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-d", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-e", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-f", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-g", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-h", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-i", 0);
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("test");
+ ASSERT_STRING(name, "result-a");
+}
+
+//# TESTCASE
+// title: idn_converter_addalias() - #6
+// group: generic
+{
+ r = idn_converter_addalias("test", "result-a", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-b", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-c", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-d", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-e", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-f", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-g", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-h", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-i", 1);
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("test");
+ ASSERT_STRING(name, "result-i");
+}
+
+//# TESTCASE
+// title: idn_converter_addalias() - null character
+// group: generic
+{
+ r = idn_converter_addalias("", "result", 0);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+ r = idn_converter_addalias("test", "", 0);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+ r = idn_converter_addalias("", "", 0);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: idn_converter_resetalias() - no alias added
+// group: generic
+{
+ r = idn_converter_resetalias();
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("test");
+ ASSERT_STRING(name, "test");
+
+}
+
+//# TESTCASE
+// title: idn_converter_resetalias() - one alias added
+// group: generic
+{
+ r = idn_converter_addalias("test", "result-a", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_resetalias();
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("test");
+ ASSERT_STRING(name, "test");
+
+}
+
+//# TESTCASE
+// title: idn_converter_resetalias() - many aliases added
+// group: generic
+{
+ r = idn_converter_addalias("test", "result-a", 1);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-b", 1);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-c", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-d", 1);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-e", 1);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-f", 1);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-g", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-h", 0);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_addalias("test", "result-i", 1);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_resetalias();
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("test");
+ ASSERT_STRING(name, "test");
+}
+
+//# TESTCASE
+// title: idn_converter_aliasfile() - boundary condition
+// group: generic quiet
+{
+ r = idn_converter_aliasfile("");
+ ASSERT_RESULT(r, idn_nofile);
+
+ r = idn_converter_aliasfile("idnalias-not-found.conf");
+ ASSERT_RESULT(r, idn_nofile);
+}
+
+//# TESTCASE
+// title: idn_converter_aliasfile() - long line
+// group: generic quiet
+{
+ char line[LINEBUF_SIZE];
+ const char *entry = "aaaaaaaaaa";
+ int i;
+ int len;
+
+ len = strlen(entry);
+ for (i = 0; i < LINEBUF_SIZE - len; i += len) {
+ memcpy(line + i, entry, len);
+ }
+ *(line + (LINEBUF_SIZE / 2)) = ' ';
+ *(line + i) = '\0';
+ create_conf_file(CONF_FILENAME, 0, line, NULL);
+ r = idn_converter_aliasfile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: idn_converter_aliasfile() - no new line at end of file
+// group: generic quiet
+{
+ create_conf_file(CONF_FILENAME, CONF_NO_EOF_NEWLINE,
+ "*.ISO_8859-1 ISO-8859-1",
+ "*.ISO_8859-2 ISO-8859-1",
+ "*.SJIS Shift_JIS",
+ "*.Shift_JIS Shift_JIS",
+ "ja_JP.EUC eucJP",
+ "japanese eucJP",
+ NULL);
+ r = idn_converter_aliasfile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("japanese");
+ ASSERT_STRING(name, "eucJP");
+
+}
+
+//# TESTCASE
+// title: idn_converter_aliasfile() - invalid entries
+// group: generic quiet
+{
+ create_conf_file(CONF_FILENAME, 0,
+ "*.ISO_8859-1 ISO-8859-1",
+ "*.ISO_8859-2 ISO-8859-1",
+ "*.SJIS",
+ "*.Shift_JIS",
+ "ja_JP.EUC eucJP",
+ "japanese eucJP",
+ NULL);
+ r = idn_converter_aliasfile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: idn_converter_aliasfile() - more then two items in one line
+// group: generic quiet
+{
+ create_conf_file(CONF_FILENAME, 0,
+ "*.ISO_8859-1 ISO-8859-1",
+ "*.ISO_8859-2 ISO-8859-1",
+ "*.SJIS Shift_JIS ko_KR.EUC",
+ "*.Shift_JIS Shift_JIS",
+ "*.big5 Big5 *.big5 *.big5",
+ "ja_JP.EUC eucJP",
+ "japanese eucJP",
+ NULL);
+ r = idn_converter_aliasfile(CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_getrealname("japanese");
+ ASSERT_STRING(name, "eucJP");
+}
+
+//# TESTCASE
+// title: idn_converter_localencoding() - #1
+// group: localencoding
+{
+ r = idn_converter_create("test.UTF-8", &ctx,
+ IDN_CONVERTER_DELAYEDOPEN);
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_localencoding(ctx);
+ ASSERT_STRING(name, "UTF-8");
+ idn_converter_destroy(ctx);
+}
+
+//# TESTCASE
+// title: idn_converter_localencoding() - #2
+// group: localencoding
+{
+ r = idn_converter_create("test.KOI8-R", &ctx,
+ IDN_CONVERTER_DELAYEDOPEN);
+#ifdef WITHOUT_ICONV
+ ASSERT_RESULT(r, idn_invalid_name);
+#else
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_localencoding(ctx);
+ ASSERT_STRING(name, "KOI8-R");
+ idn_converter_destroy(ctx);
+#endif
+}
+
+//# TESTCASE
+// title: idn_converter_localencoding() - #3
+// group: localencoding
+{
+ r = idn_converter_create("unresolvedname", &ctx,
+ IDN_CONVERTER_DELAYEDOPEN);
+#ifdef WITHOUT_ICONV
+ ASSERT_RESULT(r, idn_invalid_name);
+#else
+ ASSERT_RESULT(r, idn_success);
+ name = idn_converter_localencoding(ctx);
+ ASSERT_STRING(name, "unresolvedname");
+ idn_converter_destroy(ctx);
+#endif
+}
+
+//# TESTCASE
+// title: idn_converter_encodingtype()
+// group: conversion
+{
+ ASSERT_INT(idn_converter_encodingtype(punycode_ctx),
+ IDN_ACE_STRICTCASE);
+ ASSERT_INT(idn_converter_encodingtype(utf8_ctx),
+ IDN_NONACE);
+#ifndef WITHOUT_ICONV
+ ASSERT_INT(idn_converter_encodingtype(eucjp_ctx),
+ IDN_NONACE);
+#endif
+}
+
+//# TESTCASE
+// title: idn_converter_isasciicompatible()
+// group: conversion
+{
+ ASSERT_INT(idn_converter_isasciicompatible(punycode_ctx), 1);
+ ASSERT_INT(idn_converter_isasciicompatible(utf8_ctx), 0);
+#ifndef WITHOUT_ICONV
+ ASSERT_INT(idn_converter_isasciicompatible(eucjp_ctx), 0);
+#endif
+}
+
+//# TESTCASE
+// title: idn_converter_convfromucs4()
+// group: conversion quiet
+{
+ unsigned long from_nullchar = 0x0000;
+ unsigned long from[2] = { UCS4_NAME, 0x0000 };
+ char to[1];
+ char to_punycode[PUNYCODE_NAME_SIZE];
+#ifndef WITHOUT_ICONV
+ char to_eucjp[EUCJP_NAME_SIZE];
+#endif
+
+ r = idn_converter_convfromucs4(punycode_ctx, &from_nullchar, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_converter_convfromucs4(punycode_ctx, &from_nullchar, to, 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "");
+
+ r = idn_converter_convfromucs4(punycode_ctx, from, to_punycode, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_converter_convfromucs4(punycode_ctx, from, to_punycode,
+ PUNYCODE_NAME_SIZE - 1);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+ r = idn_converter_convfromucs4(punycode_ctx, from, to_punycode,
+ PUNYCODE_NAME_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to_punycode, PUNYCODE_NAME);
+
+#ifndef WITHOUT_ICONV
+ r = idn_converter_convfromucs4(eucjp_ctx, &from_nullchar, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_converter_convfromucs4(eucjp_ctx, &from_nullchar, to, 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "");
+
+ r = idn_converter_convfromucs4(eucjp_ctx, from, to_eucjp, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_converter_convfromucs4(eucjp_ctx, from, to_eucjp,
+ EUCJP_NAME_SIZE - 1);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_converter_convfromucs4(eucjp_ctx, from, to_eucjp,
+ EUCJP_NAME_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to_eucjp, EUCJP_NAME);
+
+ from[0] = 0x80000000;
+ r = idn_converter_convfromucs4(eucjp_ctx, from, to_eucjp,
+ EUCJP_NAME_SIZE);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ from[0] = UCS4_INVALID_NAME_FOR_EUCJP;
+ r = idn_converter_convfromucs4(eucjp_ctx, from, to_eucjp,
+ EUCJP_NAME_SIZE);
+ ASSERT_RESULT(r, idn_nomapping);
+#endif
+}
+
+//# TESTCASE
+// title: idn_converter_convtoucs4()
+// group: conversion
+{
+ unsigned long to_nullchar = 0x0000;
+ unsigned long to[1];
+ unsigned long punycode_to[2];
+#ifndef WITHOUT_ICONV
+ unsigned long eucjp_to[2];
+#endif
+ unsigned long ucs4_name[2] = { UCS4_NAME, 0x0000 };
+
+ r = idn_converter_convtoucs4(punycode_ctx, "", to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_converter_convtoucs4(punycode_ctx, "", to, 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, &to_nullchar);
+
+ r = idn_converter_convtoucs4(punycode_ctx, PUNYCODE_NAME,
+ punycode_to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_converter_convtoucs4(punycode_ctx, PUNYCODE_NAME,
+ punycode_to, 1);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+ r = idn_converter_convtoucs4(punycode_ctx, PUNYCODE_NAME, punycode_to,
+ 2);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING_THRU(punycode_to, ucs4_name);
+
+#ifndef WITHOUT_ICONV
+ r = idn_converter_convtoucs4(eucjp_ctx, "", to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_converter_convtoucs4(eucjp_ctx, "", to, 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, &to_nullchar);
+
+ r = idn_converter_convtoucs4(eucjp_ctx, EUCJP_NAME, eucjp_to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_converter_convtoucs4(eucjp_ctx, EUCJP_NAME, eucjp_to, 1);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_converter_convtoucs4(eucjp_ctx, EUCJP_NAME, eucjp_to, 2);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, &to_nullchar);
+
+ r = idn_converter_convtoucs4(eucjp_ctx, "\xFF\xFF", eucjp_to, 2);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+#endif
+}
+
+//# TESTCASE
+// title: idn_converter_destroy(), idn_converter_incrref()
+// group: generic
+{
+ idn_converter_t ctx2;
+
+ r = idn_converter_create(IDN_UTF8_ENCODING_NAME, &ctx, 0);
+ ASSERT_RESULT(r, idn_success);
+ idn_converter_destroy(ctx);
+
+ r = idn_converter_create(IDN_UTF8_ENCODING_NAME, &ctx2, 0);
+ ASSERT_RESULT(r, idn_success);
+ idn_converter_incrref(ctx2);
+ ASSERT_RESULT(r, idn_success);
+ idn_converter_destroy(ctx2);
+ idn_converter_destroy(ctx2);
+}
+
+//# TESTCASE
+// title: idn_converter_register()
+// group: generic
+{
+ char eucjp_to[3];
+ unsigned long ucs4_to[2];
+ unsigned long ucs4_name[2] = { UCS4_NAME, 0x0000 };
+
+ r = idn_converter_register("test",
+ NULL,
+ NULL,
+ idn_test_encode,
+ idn_test_decode,
+ NULL,
+ IDN_ACE_STRICTCASE);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_converter_create("test", &ctx, 0);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_converter_convfromucs4(ctx, ucs4_name, eucjp_to, sizeof(eucjp_to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(eucjp_to, EUCJP_NAME);
+
+ r = idn_converter_convtoucs4(ctx, "", ucs4_to, SIZEOFUCS4(ucs4_to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(ucs4_to, ucs4_name);
+
+ idn_converter_destroy(ctx);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/delimitermap.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/delimitermap.tsy
new file mode 100644
index 0000000..aeaa46c
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/delimitermap.tsy
@@ -0,0 +1,257 @@
+#ifndef lint
+static char *rcsid = "$Id: delimitermap.tsy,v 1.1.1.1 2003/06/04 00:26:53 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <idn/delimitermap.h>
+#include <idn/ucs4.h>
+#include <idn/log.h>
+#include "testutil.h"
+
+/*
+ * Codepoions to test the add() function.
+ */
+#define ADDITIONAL_DELIMITER0 0xe0
+#define ADDITIONAL_DELIMITER1 0xe1
+
+/*
+ * Sample string for `from' argument of map(),
+ * and its expected outputs.
+ */
+static const unsigned long from[] = {
+ 0x002e, /* full stop */
+ 0x3002, /* ideographic full stop */
+ 0xff0e, /* fullwidth full stop */
+ 0xff61, /* halfwidth ideographic full stop */
+ ADDITIONAL_DELIMITER0,
+ ADDITIONAL_DELIMITER1,
+ 0x0000
+};
+
+static const unsigned long expected_default[] = {
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ ADDITIONAL_DELIMITER0,
+ ADDITIONAL_DELIMITER1,
+ 0x0000
+};
+
+static const unsigned long expected_add[] = {
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ ADDITIONAL_DELIMITER1,
+ 0x0000
+};
+
+static const unsigned long expected_addall[] = {
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ 0x002e, /* full stop */
+ 0x0000
+};
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: generic-init
+{
+ idn_result_t r;
+ idn_delimitermap_t ctx;
+ unsigned long to[256];
+
+ r = idn_delimitermap_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: generic-init
+{
+ if (ctx != NULL)
+ idn_delimitermap_destroy(ctx);
+}
+
+//# SETUP
+// group: quiet
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call create()
+// group: generic-init
+{
+}
+
+//# TESTCASE
+// title: call map() without additional delimiters
+// group: generic-init
+{
+ r = idn_delimitermap_map(ctx, from, to, sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_default);
+}
+
+//# TESTCASE
+// title: call add() and map()
+// group: generic-init
+{
+ r = idn_delimitermap_add(ctx, ADDITIONAL_DELIMITER0);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_delimitermap_map(ctx, from, to, sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_add);
+}
+
+//# TESTCASE
+// title: call addall()
+// group: generic-init
+{
+ unsigned long delimiters[2];
+
+ delimiters[0] = ADDITIONAL_DELIMITER0;
+ delimiters[1] = ADDITIONAL_DELIMITER1;
+ r = idn_delimitermap_addall(ctx, delimiters, 2);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_delimitermap_map(ctx, from, to, sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_addall);
+}
+
+//# TESTCASE
+// title: call addall() with nnames=0
+// group: generic-init
+{
+ unsigned long delimiters[2];
+
+ r = idn_delimitermap_addall(ctx, delimiters, 0);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_delimitermap_map(ctx, from, to, sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_default);
+}
+
+//# TESTCASE
+// title: call add() with invalid codepoint
+// group: generic-init quiet
+{
+ r = idn_delimitermap_add(ctx, 0x0000); /* NUL */
+ ASSERT_RESULT(r, idn_invalid_codepoint);
+
+ r = idn_delimitermap_add(ctx, 0xd800); /* surrogate */
+ ASSERT_RESULT(r, idn_invalid_codepoint);
+
+ r = idn_delimitermap_add(ctx, 0x110000); /* out of range */
+ ASSERT_RESULT(r, idn_invalid_codepoint);
+}
+
+//# TESTCASE
+// title: call addall() with invalid codepoint
+// group: generic-init quiet
+{
+ unsigned long delimiters[1];
+
+ delimiters[0] = 0x0000; /* NUL */
+ r = idn_delimitermap_addall(ctx, delimiters, 1);
+ ASSERT_RESULT(r, idn_invalid_codepoint);
+
+ delimiters[0] = 0xd800; /* surrogate */
+ r = idn_delimitermap_addall(ctx, delimiters, 1);
+ ASSERT_RESULT(r, idn_invalid_codepoint);
+
+ delimiters[0] = 0x110000; /* out of range */
+ r = idn_delimitermap_addall(ctx, delimiters, 1);
+ ASSERT_RESULT(r, idn_invalid_codepoint);
+}
+
+//# TESTCASE
+// title: overrun test for arg `to' of map()
+// group: generic-init
+{
+ r = idn_delimitermap_map(ctx, from, to,
+ idn_ucs4_strlen(expected_default) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_default);
+ r = idn_delimitermap_map(ctx, from, to,
+ idn_ucs4_strlen(expected_default));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: call map() with tolen=0
+// group: generic-init
+{
+ r = idn_delimitermap_map(ctx, from, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/iconvchk.c b/contrib/idn/idnkit-1.0-src/lib/tests/iconvchk.c
new file mode 100644
index 0000000..895b197
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/iconvchk.c
@@ -0,0 +1,132 @@
+#ifndef lint
+static char *rcsid = "$Id: iconvchk.c,v 1.1.1.1 2003/06/04 00:26:54 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <idn/api.h>
+#include <idn/converter.h>
+#include <idn/result.h>
+
+#include "codeset.h"
+
+#define IDN_UTF8_ENCODING_NAME "UTF-8"
+
+void
+eucjp_check(void)
+{
+ idn_result_t r;
+ idn_converter_t eucjp_ctx = NULL;
+
+ r = idn_nameinit(0);
+ if (r != idn_success) {
+ fprintf(stderr, "idn_nameinit(): failed\n");
+ exit (1);
+ }
+
+ r = idn_converter_create(EUCJP_ENCODING_NAME, &eucjp_ctx, 0);
+
+ if (eucjp_ctx != NULL) {
+ idn_converter_destroy(eucjp_ctx);
+ }
+
+ if (r != idn_success) {
+ if (r == idn_invalid_name) {
+ fprintf(stderr, \
+ "\"%s\" is invalid codeset name, edit codeset.h\n", \
+ EUCJP_ENCODING_NAME);
+ exit (1);
+ } else {
+ fprintf(stderr, \
+ "idn_converter_create() failed with error \"%s\"\n", \
+ idn_result_tostring(r));
+ exit (1);
+ }
+ }
+}
+
+void
+sjis_check(void)
+{
+ idn_result_t r;
+ idn_converter_t sjis_ctx = NULL;
+
+ r = idn_nameinit(0);
+ if (r != idn_success) {
+ fprintf(stderr, "idn_nameinit(): failed\n");
+ exit (1);
+ }
+
+ r = idn_converter_create(SJIS_ENCODING_NAME, &sjis_ctx, 0);
+
+ if (sjis_ctx != NULL) {
+ idn_converter_destroy(sjis_ctx);
+ }
+
+ if (r != idn_success) {
+ if (r == idn_invalid_name) {
+ fprintf(stderr, \
+ "\"%s\" is invalid codeset name, edit codeset.h\n", \
+ SJIS_ENCODING_NAME);
+ exit (1);
+ } else {
+ fprintf(stderr, \
+ "idn_converter_create() failed with error \"%s\"\n", \
+ idn_result_tostring(r));
+ exit (1);
+ }
+ }
+}
+
+int
+main (int ac, char **av)
+{
+ eucjp_check();
+ sjis_check();
+
+ exit (0);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/mapper.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/mapper.tsy
new file mode 100644
index 0000000..5db6c65
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/mapper.tsy
@@ -0,0 +1,497 @@
+#ifndef lint
+static char *rcsid = "$Id: mapper.tsy,v 1.1.1.1 2003/06/04 00:26:54 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <idn/mapper.h>
+#include <idn/log.h>
+#include <idn/ucs4.h>
+#include "testutil.h"
+
+#define SIZEOFUCS4(x) (sizeof(x) / sizeof(unsigned long))
+
+#define UCS4_NAME_STR "U+304C" /* hiragana letter ga */
+#define UCS4_NAME 0x304C
+
+#define BUF_SIZE 128
+#define ARRAY_SIZE 9
+#define CONF_FILENAME "test.map"
+
+#define LINEBUF_SIZE 2001
+
+/*
+ * Sample string for `from' argument of map(),
+ * and its expected outputs.
+ */
+static const unsigned long from[] = {
+ 0x0041, /* latin capital letter a */
+ 0x0042, /* latin capital letter b */
+ UCS4_NAME,
+ 0x0000
+};
+
+static const unsigned long expected_default[] = {
+ 0x0061, /* latin small letter a */
+ 0x0062, /* latin small letter b */
+ UCS4_NAME,
+ 0x0000
+};
+
+idn_result_t
+test_create(const char *parameter, void **ctxp)
+{
+ return (idn_success);
+}
+
+void
+test_destroy(void *ctxp)
+{
+}
+
+idn_result_t
+test_map(void *ctx, const unsigned long *from, unsigned long *to,
+ size_t tolen)
+{
+ if (tolen > idn_ucs4_strlen(from)) {
+ idn_ucs4_strcpy(to, from);
+ } else {
+ return (idn_buffer_overflow);
+ }
+
+ return (idn_success);
+}
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: noinit
+//--
+// Do nothing
+{
+ idn_result_t r;
+ const char *name;
+}
+
+//# SETUP
+// group: generic
+//--
+// Initialize the module and create context.
+{
+ idn_result_t r;
+ idn_mapper_t ctx = NULL;
+
+ r = idn_mapper_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: generic
+//--
+// Destroy context.
+{
+ idn_mapper_destroy(ctx);
+}
+
+//# SETUP
+// group: addall
+//--
+// Initialize the module and create context.
+{
+ idn_result_t r;
+ idn_mapper_t ctx = NULL;
+ char *names[ARRAY_SIZE];
+ int i;
+ unsigned long to[4];
+
+ for (i = 0; i < ARRAY_SIZE; i++) {
+ names[i] = malloc(BUF_SIZE);
+ if (names[i] == NULL) {
+ ASSERT("malloc failed\n");
+ }
+ }
+
+ r = idn_mapper_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: addall
+//--
+// Destroy context and free some blocks.
+{
+ idn_mapper_destroy(ctx);
+ for (i = 0; i < ARRAY_SIZE; i++) {
+ free(names[i]);
+ }
+}
+
+//# SETUP
+// group: quiet
+//--
+// Set log level to `fatal' to supress log messages.
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+//--
+// Restore log level.
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: idn_mapper_add() - boundary condition
+// group: generic quiet
+{
+ r = idn_mapper_add(ctx, "");
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_mapper_add() - builtin schemes
+// group: generic quiet
+{
+ r = idn_mapper_add(ctx, "RFC3491");
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapper_add(ctx, "nameprep-01");
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_mapper_add() - boundary condition
+// group: generic quiet
+{
+ r = idn_mapper_add(ctx, "");
+ ASSERT_RESULT(r, idn_invalid_name);
+ r = idn_mapper_add(ctx, "filemap:");
+ ASSERT_RESULT(r, idn_nofile);
+ r = idn_mapper_add(ctx, "filemap:notfound.map");
+ ASSERT_RESULT(r, idn_nofile);
+}
+
+//# TESTCASE
+// title: idn_mapper_add() - file
+// group: generic quiet
+{
+ char name[BUF_SIZE];
+ unsigned long to[4];
+
+ create_conf_file(CONF_FILENAME, 0,
+ "0041; 0061;",
+ "0042; 0062;",
+ NULL);
+ sprintf(name, "filemap:%s", CONF_FILENAME);
+
+ r = idn_mapper_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_default);
+}
+
+//# TESTCASE
+// title: idn_mapper_add() - file - long line
+// group: generic quiet
+{
+ char line[LINEBUF_SIZE];
+ char name[BUF_SIZE];
+ const char *first_entry = "0041;";
+ const char *other_entry = " 0061";
+ int i;
+ int len;
+
+ memcpy(line, first_entry, strlen(first_entry));
+ len = strlen(other_entry);
+ for (i = len; i < LINEBUF_SIZE - len; i += len) {
+ memcpy(line + i, other_entry, len);
+ }
+ *(line + i) = '\0';
+
+ create_conf_file(CONF_FILENAME, 0, line, NULL);
+ sprintf(name, "filemap:%s", CONF_FILENAME);
+ r = idn_mapper_add(ctx, name);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: idn_mapper_add() - file - no new line at end of file
+// group: generic quiet
+{
+ char name[BUF_SIZE];
+ unsigned long to[4];
+
+ create_conf_file(CONF_FILENAME, CONF_NO_EOF_NEWLINE,
+ "0041; 0061;",
+ "0042; 0062;",
+ NULL);
+ sprintf(name, "filemap:%s", CONF_FILENAME);
+ r = idn_mapper_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_default);
+}
+
+//# TESTCASE
+// title: idn_mapper_add() - file - one item in one line #1
+// group: generic quiet
+{
+ char name[BUF_SIZE];
+ unsigned long to[3];
+ unsigned long expected[] = {
+ 0x0061,
+ UCS4_NAME,
+ 0x0000
+ };
+
+ create_conf_file(CONF_FILENAME, 0,
+ "0041; 0061;",
+ "0042;",
+ NULL);
+ sprintf(name, "filemap:%s", CONF_FILENAME);
+ r = idn_mapper_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected);
+}
+
+//# TESTCASE
+// title: idn_mapper_add() - file - one item in one line #2
+// group: generic quiet
+{
+ char name[BUF_SIZE];
+ unsigned long to[3];
+ unsigned long expected[] = {
+ 0x0061,
+ UCS4_NAME,
+ 0x0000
+ };
+
+ create_conf_file(CONF_FILENAME, 0,
+ "0041; 0061;",
+ "0042; ;",
+ NULL);
+ sprintf(name, "filemap:%s", CONF_FILENAME);
+ r = idn_mapper_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected);
+}
+
+//# TESTCASE
+// title: idn_mapper_add() - file - more then two items in one line #1
+// group: generic quiet
+{
+ char name[BUF_SIZE];
+ unsigned long to[4];
+
+ create_conf_file(CONF_FILENAME, 0,
+ "0041; 0061; 0062;",
+ "0042; 0062; 0063;",
+ NULL);
+ sprintf(name, "filemap:%s", CONF_FILENAME);
+ r = idn_mapper_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_default);
+}
+
+//# TESTCASE
+// title: idn_mapper_add() - file - more then two items in one line #2
+// group: generic quiet
+{
+ char name[BUF_SIZE];
+ unsigned long to[6];
+ unsigned long expected_to[] = {
+ 0x0061,
+ 0x0062,
+ 0x0062,
+ 0x0063,
+ UCS4_NAME,
+ 0x0000
+ };
+
+ create_conf_file(CONF_FILENAME, 0,
+ "0041; 0061 0062;",
+ "0042; 0062 0063;",
+ NULL);
+ sprintf(name, "filemap:%s", CONF_FILENAME);
+ r = idn_mapper_add(ctx, name);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_to);
+}
+
+//# TESTCASE
+// title: idn_mapper_add() - file - more then two items in one line #3
+// group: generic quiet
+{
+ char name[BUF_SIZE];
+ unsigned long to[3];
+
+ create_conf_file(CONF_FILENAME, 0,
+ "0041 0042; 0063;",
+ NULL);
+ sprintf(name, "filemap:%s", CONF_FILENAME);
+ r = idn_mapper_add(ctx, name);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: idn_mapper_addall() - add all builtin schemes
+// group: addall quiet
+{
+ strcpy(names[0], "RFC3491");
+ strcpy(names[1], "RFC3491");
+ strcpy(names[2], "RFC3491");
+ strcpy(names[3], "RFC3491");
+ strcpy(names[4], "RFC3491");
+ strcpy(names[5], "RFC3491");
+ strcpy(names[6], "RFC3491");
+ strcpy(names[7], "RFC3491");
+ strcpy(names[8], "RFC3491");
+
+ r = idn_mapper_addall(ctx, (const char **)names, 9);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_default);
+}
+
+//# TESTCASE
+// title: idn_mapper_addall() - add same scheme repetedly
+// group: addall quiet
+{
+ for (i = 0; i < ARRAY_SIZE; i++) {
+ strcpy(names[i], "RFC3491");
+ }
+ r = idn_mapper_addall(ctx, (const char **)names, 3);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_default);
+}
+
+//# TESTCASE
+// title: idn_mapper_map() - builtin schemes check - RFC3491
+// group: generic quiet
+{
+ unsigned long to[4];
+
+ r = idn_mapper_add(ctx, "RFC3491");
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, expected_default);
+}
+
+//# TESTCASE
+// title: idn_mapper_map() - context without procedure
+// group: generic
+{
+ unsigned long to[4];
+
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, from);
+}
+
+//# TESTCASE
+// title: idn_mapper_destroy(), idn_mapper_incrref()
+// group:
+{
+ idn_result_t r;
+ idn_mapper_t ctx = NULL;
+
+ r = idn_mapper_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+ idn_mapper_incrref(ctx);
+ idn_mapper_destroy(ctx);
+ idn_mapper_destroy(ctx);
+}
+
+//# TESTCASE
+// title: idn_mapper_register()
+// group: generic quiet
+{
+ unsigned long to[10];
+
+ r = idn_mapper_register("test", test_create, test_destroy, test_map);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_mapper_add(ctx, "test");
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapper_map(ctx, from, to, SIZEOFUCS4(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, from);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/mapselector.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/mapselector.tsy
new file mode 100644
index 0000000..1484f6c
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/mapselector.tsy
@@ -0,0 +1,592 @@
+#ifndef lint
+static char *rcsid = "$Id: mapselector.tsy,v 1.1.1.1 2003/06/04 00:26:55 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <idn/mapselector.h>
+#include <idn/ucs4.h>
+#include <idn/log.h>
+
+#include "testutil.h"
+
+#define CONF_FILENAME "test.conf"
+#define MAP_FILENAME "test.map"
+
+/*
+ * Sample TLDs.
+ */
+static const char *utf8_tlds_jp[] = {"jp", ".jp", "JP", ".JP"};
+static const char *utf8_tlds_tw[] = {"tw", ".tw", "TW", ".TW"};
+
+static const unsigned long ucs4_tlds_jp[][4] = {{'j', 'p', '\0', '\0'},
+ {'.', 'j', 'p', '\0'},
+ {'J', 'P', '\0', '\0'},
+ {'.', 'J', 'P', '\0'}};
+
+static const unsigned long ucs4_tlds_tw[][4] = {{'t', 'w', '\0', '\0'},
+ {'.', 't', 'w', '\0'},
+ {'T', 'W', '\0', '\0'},
+ {'.', 'T', 'W', '\0'}};
+
+/* How many elements in `utf8_tlds_{jp|tw}[]' and `ucs4_tlds_{jp|tw}[]'. */
+#define TLD_NVARIANTS 4
+
+/*
+ * Sample input string for mapping. (UCS4)
+ */
+static const unsigned long in_string[] = {0x00C0, 0x2212, 0};
+
+/*
+ * Sample mapping results of IN_STRING.
+ *
+ * OUT_STRING_FILEMAP is the result of file-mapping (U+2212 -> U+002D).
+ * OUT_STRING_NAMEPREP is the result of the latest nameprep
+ * OUT_STRING_BOTH is the result of both file-mapping and nameprep.
+ */
+static const unsigned long out_string_filemap[] = {0x00C0, 0x002D, 0};
+static const unsigned long out_string_nameprep[] = {0x00E0, 0x2212, 0};
+static const unsigned long out_string_both[] = {0x00E0, 0x002D, 0};
+
+#define MAP_FILENAME "test.map"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: generic-init
+{
+ idn_result_t r;
+ idn_mapselector_t ctxs[TLD_NVARIANTS];
+ unsigned long to[256];
+
+ {
+ int i;
+ for (i = 0; i < TLD_NVARIANTS; i++)
+ ctxs[i] = NULL;
+ }
+
+ r = idn_mapselector_initialize();
+ ASSERT_RESULT(r, idn_success);
+
+ {
+ int i;
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ r = idn_mapselector_create(&ctxs[i]);
+ ASSERT_RESULT(r, idn_success);
+ }
+ }
+}
+
+//# TEARDOWN
+// group: generic-init
+{
+ {
+ int i;
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ if (ctxs[i] != NULL)
+ idn_mapselector_destroy(ctxs[i]);
+ remove(CONF_FILENAME);
+ }
+ }
+}
+
+//# SETUP
+// group: quiet
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//# SETUP
+// group: generic-filemap
+{
+ create_conf_file(MAP_FILENAME, 0,
+ "U+2212; U+002D",
+ NULL);
+}
+
+//# TEARDOWN
+// group: generic-filemap
+{
+ remove(MAP_FILENAME);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call initialize() twice.
+//
+{
+ idn_result_t r;
+
+ r = idn_mapselector_initialize();
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapselector_initialize();
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: call create()
+{
+ idn_result_t r;
+ idn_mapselector_t ctx;
+
+ r = idn_mapselector_initialize();
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapselector_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+
+ idn_mapselector_destroy(ctx);
+}
+
+//# TESTCASE
+// title: call add(filemap) and map()
+// group: generic-init generic-filemap
+{
+ int i, j;
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ r = idn_mapselector_add(ctxs[i], utf8_tlds_jp[i],
+ "filemap:" MAP_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+ }
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ for (j = 0; j < TLD_NVARIANTS; j++) {
+ r = idn_mapselector_map(ctxs[i], in_string,
+ utf8_tlds_jp[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, out_string_filemap);
+
+ r = idn_mapselector_map(ctxs[i], in_string,
+ utf8_tlds_tw[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, in_string);
+ }
+ }
+}
+
+//# TESTCASE
+// title: call add(nameprep) and map()
+// group: generic-init generic-filemap
+{
+ int i, j;
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ r = idn_mapselector_add(ctxs[i], utf8_tlds_jp[i],
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+ }
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ for (j = 0; j < TLD_NVARIANTS; j++) {
+ r = idn_mapselector_map(ctxs[i], in_string,
+ utf8_tlds_jp[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, out_string_nameprep);
+
+ r = idn_mapselector_map(ctxs[i], in_string,
+ utf8_tlds_tw[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, in_string);
+ }
+ }
+}
+
+//# TESTCASE
+// title: call add(filemap) and map2()
+// group: generic-init generic-filemap
+{
+ int i, j;
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ r = idn_mapselector_add(ctxs[i], utf8_tlds_jp[i],
+ "filemap:" MAP_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+ }
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ for (j = 0; j < TLD_NVARIANTS; j++) {
+ r = idn_mapselector_map2(ctxs[i], in_string,
+ ucs4_tlds_jp[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, out_string_filemap);
+
+ r = idn_mapselector_map2(ctxs[i], in_string,
+ ucs4_tlds_tw[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, in_string);
+ }
+ }
+}
+
+//# TESTCASE
+// title: call add(nameprep) and map2()
+// group: generic-init generic-filemap
+{
+ int i, j;
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ r = idn_mapselector_add(ctxs[i], utf8_tlds_jp[i],
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+ }
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ for (j = 0; j < TLD_NVARIANTS; j++) {
+ r = idn_mapselector_map2(ctxs[i], in_string,
+ ucs4_tlds_jp[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, out_string_nameprep);
+
+ r = idn_mapselector_map2(ctxs[i], in_string,
+ ucs4_tlds_tw[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, in_string);
+ }
+ }
+}
+
+//# TESTCASE
+// title: call add(filemap) and map()
+// group: generic-init generic-filemap
+{
+ int i, j;
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ r = idn_mapselector_add(ctxs[i], utf8_tlds_jp[i],
+ "filemap:" MAP_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+ }
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ for (j = 0; j < TLD_NVARIANTS; j++) {
+ r = idn_mapselector_map(ctxs[i], in_string,
+ utf8_tlds_jp[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, out_string_filemap);
+
+ r = idn_mapselector_map(ctxs[i], in_string,
+ utf8_tlds_tw[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, in_string);
+ }
+ }
+}
+
+//# TESTCASE
+// title: call add(nameprep) and map()
+// group: generic-init generic-filemap
+{
+ int i, j;
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ r = idn_mapselector_add(ctxs[i], utf8_tlds_jp[i],
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+ }
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ for (j = 0; j < TLD_NVARIANTS; j++) {
+ r = idn_mapselector_map(ctxs[i], in_string,
+ utf8_tlds_jp[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, out_string_nameprep);
+
+ r = idn_mapselector_map(ctxs[i], in_string,
+ utf8_tlds_tw[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, in_string);
+ }
+ }
+}
+
+//# TESTCASE
+// title: call addall()
+// group: generic-init generic-filemap
+{
+ static const char *names[] = {
+ "filemap:" MAP_FILENAME,
+ IDN_NAMEPREP_CURRENT
+ };
+ int i, j;
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ r = idn_mapselector_addall(ctxs[i], utf8_tlds_jp[i], names,
+ sizeof(names) / sizeof(*names));
+ ASSERT_RESULT(r, idn_success);
+ }
+
+ for (i = 0; i < TLD_NVARIANTS; i++) {
+ for (j = 0; j < TLD_NVARIANTS; j++) {
+ r = idn_mapselector_map2(ctxs[i], in_string,
+ ucs4_tlds_jp[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, out_string_both);
+
+ r = idn_mapselector_map2(ctxs[i], in_string,
+ ucs4_tlds_tw[j], to,
+ sizeof(to) / sizeof(*to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, in_string);
+ }
+ }
+}
+
+//# TESTCASE
+// title: call addall() with nnames=0
+// group: generic-init
+{
+ static const char *names[] = {IDN_NAMEPREP_CURRENT};
+
+ r = idn_mapselector_addall(ctxs[0], ".", names, 0);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: call add() with empty tld
+// group: generic-init
+{
+ r = idn_mapselector_add(ctxs[0], "", IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: call addall() with empty tld
+// group: generic-init
+{
+ static const char *names[] = {IDN_NAMEPREP_CURRENT};
+
+ r = idn_mapselector_addall(ctxs[0], "", names, 1);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: call add() with too long tld
+// group: generic-init quiet
+{
+ r = idn_mapselector_add(ctxs[0],
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJK",
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapselector_add(ctxs[0],
+ "."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJK",
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapselector_add(ctxs[0],
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKL",
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_invalid_name);
+
+ r = idn_mapselector_add(ctxs[0],
+ "."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKL",
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: call addall() with too long tld
+// group: generic-init quiet
+{
+ static const char *names[] = {IDN_NAMEPREP_CURRENT};
+
+ r = idn_mapselector_addall(ctxs[0],
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJK",
+ names, 1);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapselector_addall(ctxs[0],
+ "."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJK",
+ names, 1);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapselector_addall(ctxs[0],
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKL",
+ names, 1);
+ ASSERT_RESULT(r, idn_invalid_name);
+
+ r = idn_mapselector_addall(ctxs[0],
+ "."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "ABCDEFGHIJKL",
+ names, 1);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: overrun test for arg `to' of map()
+// group: generic-init
+{
+ r = idn_mapselector_add(ctxs[0], utf8_tlds_jp[0],
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapselector_map(ctxs[0], in_string, utf8_tlds_jp[0], to,
+ idn_ucs4_strlen(out_string_nameprep) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, out_string_nameprep);
+
+ r = idn_mapselector_map(ctxs[0], in_string, utf8_tlds_tw[0], to,
+ idn_ucs4_strlen(in_string) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, in_string);
+
+ r = idn_mapselector_map(ctxs[0], in_string, utf8_tlds_jp[0], to,
+ idn_ucs4_strlen(out_string_nameprep));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_mapselector_map(ctxs[0], in_string, utf8_tlds_tw[0], to,
+ idn_ucs4_strlen(in_string));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: overrun test for arg `to' of map2()
+// group: generic-init
+{
+ r = idn_mapselector_add(ctxs[0], utf8_tlds_jp[0],
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapselector_map2(ctxs[0], in_string, ucs4_tlds_jp[0], to,
+ idn_ucs4_strlen(out_string_nameprep) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, out_string_nameprep);
+
+ r = idn_mapselector_map2(ctxs[0], in_string, ucs4_tlds_tw[0], to,
+ idn_ucs4_strlen(in_string) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, in_string);
+
+ r = idn_mapselector_map2(ctxs[0], in_string, ucs4_tlds_jp[0], to,
+ idn_ucs4_strlen(out_string_nameprep));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_mapselector_map2(ctxs[0], in_string, ucs4_tlds_tw[0], to,
+ idn_ucs4_strlen(in_string));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: call map() with tolen=0
+// group: generic-init
+{
+ r = idn_mapselector_add(ctxs[0], utf8_tlds_jp[0],
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapselector_map(ctxs[0], in_string, utf8_tlds_jp[0], to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_mapselector_map(ctxs[0], in_string, utf8_tlds_tw[0], to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: call map2() with tolen=0
+// group: generic-init
+{
+ r = idn_mapselector_add(ctxs[0], utf8_tlds_jp[0],
+ IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_mapselector_map2(ctxs[0], in_string, ucs4_tlds_jp[0], to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_mapselector_map2(ctxs[0], in_string, ucs4_tlds_tw[0], to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/nameprep.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/nameprep.tsy
new file mode 100644
index 0000000..bba49c7
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/nameprep.tsy
@@ -0,0 +1,340 @@
+#ifndef lint
+static char *rcsid = "$Id: nameprep.tsy,v 1.1.1.1 2003/06/04 00:26:56 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <idn/nameprep.h>
+#include <idn/log.h>
+#include "testutil.h"
+
+#define UCS4_NAME 0x304C /* hiragana letter ga */
+#define BUF_SIZE 4
+/*
+ * Sample string for `from' argument for map(),
+ * and its expected outputs.
+ */
+static const unsigned long map_from[] = {
+ 0x0041, /* latin capital letter a */
+ 0x0042, /* latin capital letter b */
+ UCS4_NAME,
+ 0x0000
+};
+
+static const unsigned long map_expected[] = {
+ 0x0061, /* latin small letter a */
+ 0x0062, /* latin small letter b */
+ UCS4_NAME,
+ 0x0000
+};
+
+/*
+ * Sample string for `from' argument for isprohibited().
+ */
+static const unsigned long check_from[4] = {
+ UCS4_NAME,
+ 0x00A0, /* no-break space: prohibited character */
+ 0x0221, /* unassigned character */
+ 0x0000
+};
+
+#define FROM_UCS4NAME_OFFSET 0
+#define FROM_PROH_OFFSET 1
+#define FROM_UNAS_OFFSET 2
+
+/*
+ * Sample string for `from' argument for isunassigned().
+ */
+static const unsigned long check_from2[4] = {
+ UCS4_NAME,
+ 0x0221, /* unassigned character */
+ 0x00A0, /* no-break space: prohibited character */
+ 0x0000
+};
+
+#define FROM2_UCS4NAME_OFFSET 0
+#define FROM2_PROH_OFFSET 2
+#define FROM2_UNAS_OFFSET 1
+
+/*
+ * Sample string for `from' argument for isvalidbidi().
+ * (It is not a valid bidi label.)
+ */
+static const unsigned long bidi_from[4] = {
+ 0x05BE, /* hebrew punctuation maqaf */
+ 0x0041, /* latin capital letter a */
+ 0xFEFC, /* arabic ligature lam with alef final form */
+ 0x0000
+};
+#define BIDIFROM_OFFSET 1
+
+/*
+ * Empty string.
+ */
+static const unsigned long ucs4_nullstr[] = {
+ 0x0000
+};
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: generic
+//--
+// Nothing happens.
+{
+ idn_result_t r;
+ idn_nameprep_t handle = NULL;
+
+}
+
+//# SETUP
+// group: check
+//--
+// Initialize the module and create contexts.
+{
+ idn_result_t r;
+ idn_nameprep_t handle11 = NULL;
+
+ r = idn_nameprep_create("RFC3491", &handle11);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: check
+//--
+// Destroy contexts.
+{
+ if (handle11 != NULL) {
+ idn_nameprep_destroy(handle11);
+ }
+}
+
+//# SETUP
+// group: quiet
+//--
+// Set log level to `fatal' to supress log messages.
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+//--
+// Restore log level.
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: idn_nameprep_create() - boundary condition
+// group: generic quiet
+{
+ r = idn_nameprep_create("", &handle);
+ ASSERT_RESULT(r, idn_notfound);
+}
+
+//# TESTCASE
+// title: idn_nameprep_create() - version is NULL (current nameprep)
+// group: generic quiet
+{
+ unsigned long to[BUF_SIZE];
+ const unsigned long *found;
+
+ r = idn_nameprep_create(NULL, &handle);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_nameprep_map(handle, map_from, to, BUF_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, map_expected);
+
+ r = idn_nameprep_isunassigned(handle, check_from, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, check_from + FROM_UNAS_OFFSET);
+
+ r = idn_nameprep_isprohibited(handle, check_from, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, check_from + FROM_PROH_OFFSET);
+
+ r = idn_nameprep_isvalidbidi(handle, bidi_from, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, bidi_from + BIDIFROM_OFFSET);
+
+ idn_nameprep_destroy(handle);
+}
+
+//# TESTCASE
+// title: idn_nameprep_create() - nameprep-01
+// group: generic quiet
+{
+ r = idn_nameprep_create("nameprep-01", &handle);
+ ASSERT_RESULT(r, idn_notfound);
+}
+
+//# TESTCASE
+// title: idn_nameprep_create() - RFC3491
+// group: generic
+{
+ r = idn_nameprep_create("RFC3491", &handle);
+ ASSERT_RESULT(r, idn_success);
+ idn_nameprep_destroy(handle);
+}
+
+//# TESTCASE
+// title: idn_nameprep_map() - boundary condition
+// group: check
+{
+ unsigned long to[BUF_SIZE];
+
+ r = idn_nameprep_map(handle11, ucs4_nullstr, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+ r = idn_nameprep_map(handle11, ucs4_nullstr, to, 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, ucs4_nullstr);
+}
+
+//# TESTCASE
+// title: idn_nameprep_map() - RFC3491
+// group: check
+{
+ unsigned long to[BUF_SIZE];
+
+ r = idn_nameprep_map(handle11, map_from, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+ r = idn_nameprep_map(handle11, map_from, to, BUF_SIZE - 1);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+ r = idn_nameprep_map(handle11, map_from, to, BUF_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, map_expected);
+}
+
+//# TESTCASE
+// title: idn_nameprep_isunassigned() - boundary condition
+// group: check
+{
+ const unsigned long *found;
+
+ r = idn_nameprep_isunassigned(handle11, ucs4_nullstr, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, NULL);
+}
+
+//# TESTCASE
+// title: idn_nameprep_isunassigned() - RFC3491
+// group: check
+{
+ const unsigned long *found;
+
+ r = idn_nameprep_isunassigned(handle11, check_from, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, check_from + FROM_UNAS_OFFSET);
+
+ r = idn_nameprep_isunassigned(handle11, check_from2, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, check_from2 + FROM2_UNAS_OFFSET);
+}
+
+//# TESTCASE
+// title: idn_nameprep_isprohibited() - boundary condition
+// group: check
+{
+ const unsigned long *found;
+
+ r = idn_nameprep_isprohibited(handle11, ucs4_nullstr, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, NULL);
+}
+
+//# TESTCASE
+// title: idn_nameprep_isprohibited() - RFC3491
+// group: check
+{
+ const unsigned long *found;
+
+ r = idn_nameprep_isprohibited(handle11, check_from, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, check_from + FROM_PROH_OFFSET);
+
+ r = idn_nameprep_isprohibited(handle11, check_from2, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, check_from2 + FROM2_PROH_OFFSET);
+}
+
+//# TESTCASE
+// title: idn_nameprep_isvalidbidi() - boundary condition
+// group: check
+{
+ const unsigned long *found;
+
+ r = idn_nameprep_isvalidbidi(handle11, ucs4_nullstr, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, NULL);
+}
+
+//# TESTCASE
+// title: idn_nameprep_isvalidbidi() - RFC3491
+// group: check
+{
+ const unsigned long *found;
+
+ r = idn_nameprep_isvalidbidi(handle11, bidi_from, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, bidi_from + BIDIFROM_OFFSET);
+
+ r = idn_nameprep_isvalidbidi(handle11, check_from2, &found);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_PTR(found, NULL);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/normalizer.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/normalizer.tsy
new file mode 100644
index 0000000..dc9906d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/normalizer.tsy
@@ -0,0 +1,346 @@
+#ifndef lint
+static char *rcsid = "$Id: normalizer.tsy,v 1.1.1.1 2003/06/04 00:26:57 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <idn/normalizer.h>
+#include <idn/log.h>
+#include <idn/ucs4.h>
+
+#define BUF_SIZE 64
+#define TOBUF_SIZE 4
+#define ARRAY_SIZE 20
+#define CONF_FILENAME "test.map"
+
+/*
+ * Sample string for `from' argument of normalize(),
+ * and its expected outputs.
+ */
+static const unsigned long from[4] = {
+ 0x304B, /* hiragana letter ka */
+ 0x3099, /* combining katakana-hiragana voiced sound mark */
+ 0x32D0, /* circled katakana a */
+ 0x0000
+};
+
+static const unsigned long normalized_kc_str[3] = {
+ 0x304C, /* hiragana letter ga */
+ 0x30A2, /* katakana letter a */
+ 0x0000
+};
+
+static const unsigned long normalized_c_str[3] = {
+ 0x304C, /* hiragana letter ga */
+ 0x32D0, /* circled katakana a */
+ 0x0000
+};
+
+idn_result_t
+test_proc(const unsigned long *from, unsigned long *to, size_t tolen)
+{
+ if (tolen > idn_ucs4_strlen(from)) {
+ idn_ucs4_strcpy(to, from);
+ } else {
+ return (idn_buffer_overflow);
+ }
+
+ return (idn_success);
+}
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: noinit
+//--
+// Do nothing
+{
+ idn_result_t r;
+ const char *name;
+}
+
+//# SETUP
+// group: generic
+//--
+// Initialize the module and create context.
+{
+ idn_result_t r;
+ idn_normalizer_t ctx = NULL;
+
+ r = idn_normalizer_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_normalizer_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: generic
+//--
+// Destroy context.
+{
+ idn_normalizer_destroy(ctx);
+}
+
+//# SETUP
+// group: addall
+//--
+// Initialize the module and create context.
+{
+ idn_result_t r;
+ idn_normalizer_t ctx = NULL;
+ char *names[ARRAY_SIZE];
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE; i++) {
+ names[i] = malloc(BUF_SIZE);
+ if (names[i] == NULL) {
+ ASSERT("malloc failed\n");
+ }
+ }
+
+ strcpy(names[0], "RFC3491");
+ strcpy(names[1], "unicode-form-kc");
+ strcpy(names[2], "unicode-form-kc/3.2.0");
+ strcpy(names[3], "RFC3491");
+ strcpy(names[4], "unicode-form-kc");
+ strcpy(names[5], "unicode-form-kc/3.2.0");
+ strcpy(names[6], "RFC3491");
+ strcpy(names[7], "unicode-form-kc");
+ strcpy(names[8], "unicode-form-kc/3.2.0");
+ strcpy(names[9], "RFC3491");
+ strcpy(names[10], "unicode-form-kc");
+ strcpy(names[11], "unicode-form-kc/3.2.0");
+ strcpy(names[12], "RFC3491");
+ strcpy(names[13], "unicode-form-kc");
+ strcpy(names[14], "unicode-form-kc/3.2.0");
+ strcpy(names[15], "RFC3491");
+ strcpy(names[16], "unicode-form-kc");
+ strcpy(names[17], "unicode-form-kc/3.2.0");
+ strcpy(names[18], "RFC3491");
+ strcpy(names[19], "unicode-form-kc");
+
+ r = idn_normalizer_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_normalizer_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: addall
+//--
+// Destroy context.
+{
+ idn_normalizer_destroy(ctx);
+ for (i = 0; i < ARRAY_SIZE; i++) {
+ free(names[i]);
+ }
+}
+
+//# SETUP
+// group: quiet
+//--
+// Set log level to `fatal' to supress log messages.
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+//--
+// Restore log level.
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: idn_normalizer_add() - boundary condition
+// group: generic quiet
+{
+ r = idn_normalizer_add(ctx, "");
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_normalizer_add() - builtin schemes
+// group: generic quiet
+{
+ r = idn_normalizer_add(ctx, "RFC3491");
+ ASSERT_RESULT(r, idn_success);
+ r = idn_normalizer_add(ctx, "unicode-form-kc");
+ ASSERT_RESULT(r, idn_success);
+ r = idn_normalizer_add(ctx, "unicode-form-kc/3.2.0");
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_normalizer_add(ctx, "nameprep-01");
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_normalizer_addall() - boundary condition
+// group: addall quiet
+{
+ strcpy(names[3], "");
+ r = idn_normalizer_addall(ctx, (const char **)names, ARRAY_SIZE);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: idn_normalizer_addall() - nschemes is 0
+// group: addall quiet
+{
+ r = idn_normalizer_addall(ctx, (const char **)names, 0);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: idn_normalizer_addall() - add a lot of schemes
+// group: addall quiet
+{
+ unsigned long to[TOBUF_SIZE];
+
+ r = idn_normalizer_addall(ctx, (const char **)names, ARRAY_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_normalizer_normalize(ctx, from, to, TOBUF_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, normalized_kc_str);
+}
+
+//# TESTCASE
+// title: idn_normalizer_addall() - add same scheme repetedly
+// group: addall quiet
+{
+ int i;
+ unsigned long to[TOBUF_SIZE];
+
+ for (i = 0; i < ARRAY_SIZE; i++) {
+ strcpy(names[i], "RFC3491");
+ }
+ r = idn_normalizer_addall(ctx, (const char **)names, ARRAY_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_normalizer_normalize(ctx, from, to, TOBUF_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, normalized_kc_str);
+}
+
+//# TESTCASE
+// title: idn_normalizer_normalize() - schemes check - RFC3491
+// group: generic quiet
+{
+ unsigned long to[TOBUF_SIZE];
+
+ r = idn_normalizer_add(ctx, "RFC3491");
+ ASSERT_RESULT(r, idn_success);
+ r = idn_normalizer_normalize(ctx, from, to, TOBUF_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, normalized_kc_str);
+}
+
+//# TESTCASE
+// title: idn_normalizer_normalize() - schemes check - unicode-form-kc/3.2.0
+// group: generic quiet
+{
+ unsigned long to[TOBUF_SIZE];
+
+ r = idn_normalizer_add(ctx, "unicode-form-kc/3.2.0");
+ ASSERT_RESULT(r, idn_success);
+ r = idn_normalizer_normalize(ctx, from, to, TOBUF_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, normalized_kc_str);
+}
+
+//# TESTCASE
+// title: idn_normalizer_normalize() - context without procedure
+// group: generic quiet
+{
+ unsigned long to[TOBUF_SIZE];
+
+ r = idn_normalizer_normalize(ctx, from, to, TOBUF_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, from);
+}
+
+//# TESTCASE
+// title: idn_normalizer_destroy(), idn_normalizer_incrref()
+// group:
+{
+ idn_result_t r;
+ idn_normalizer_t ctx = NULL;
+
+ r = idn_normalizer_initialize();
+ ASSERT_RESULT(r, idn_success);
+ r = idn_normalizer_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+ idn_normalizer_incrref(ctx);
+ idn_normalizer_destroy(ctx);
+ idn_normalizer_destroy(ctx);
+}
+
+//# TESTCASE
+// title: idn_normalizer_register()
+// group: generic quiet
+{
+ unsigned long to[TOBUF_SIZE];
+
+ r = idn_normalizer_register("test", test_proc);
+ ASSERT_RESULT(r, idn_success);
+ r = idn_normalizer_add(ctx, "test");
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_normalizer_normalize(ctx, from, to, TOBUF_SIZE);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, from);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/res.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/res.tsy
new file mode 100644
index 0000000..39c3895
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/res.tsy
@@ -0,0 +1,1026 @@
+#ifndef lint
+static char *rcsid = "$Id: res.tsy,v 1.1.1.1 2003/06/04 00:26:59 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <idn/res.h>
+#include <idn/log.h>
+
+#include "codeset.h"
+#include "setenv.h"
+
+#ifndef EUCJP_ENCODING_NAME
+#define EUCJP_ENCODING_NAME "eucJP"
+#endif
+
+/*
+ * U+304B: hiragana letter KA
+ * U+3099: combining katakana-hiragana voiced sound mark
+ *
+ * map("U+304B U+3099") -> "U+304C"
+ *
+ * U+304C: hiragana letter GA
+ */
+#define UTF8_NAME "A<U+304B><U+3099>"
+#define UTF8_REVNAME "a<U+304C>"
+
+/*
+ * A4AC: hiragana letter GA (in EUC-JP)
+ */
+#define EUCJP_NAME "\xa4\xac"
+#define EUCJP_REVNAME "\xa4\xac"
+
+/*
+ * Conversion result of "U+304B U+3099 A"
+ */
+#define PUNYCODE_NAME "xn--a-i8t"
+
+/*
+ * Conversion result of "A U+304B U+3099" (in EUC-JP).
+ */
+#define AUX_EUCJP_NAME "xn--a-i\xa3\xb8t"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: generic-conversion
+//--
+// Initialize the `resconf' context.
+// Set local encoding to `UTF-8'.
+{
+ char to[256];
+ idn_result_t r;
+ idn_resconf_t ctx;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+ unsetenv("IDN_DISABLE");
+
+ r = idn_resconf_initialize();
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_resconf_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_resconf_setdefaults(ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: generic-conversion
+{
+ idn_resconf_destroy(ctx);
+}
+
+//# SETUP
+// group: quiet
+//--
+// Set log level to `fatal' to supress log messages.
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+//--
+// Restore log level.
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: basic conversion by encodename()
+// group: generic-conversion
+{
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: basic conversion by decodename()
+// group: generic-conversion
+{
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+}
+
+//# TESTCASE
+// title: basic conversion by decodename2()
+// group: generic-conversion
+{
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+#ifdef WITHOUT_ICONV
+ ASSERT_RESULT(r, idn_failure);
+#else
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename2() with auxencoding=NULL
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to),
+ NULL);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+#endif
+}
+
+//# TESTCASE
+// title: call encodename() with actions=0
+// group: generic-conversion
+{
+ r = idn_res_encodename(ctx, 0, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+}
+
+//# TESTCASE
+// title: call decodename() with actions=0
+// group: generic-conversion
+{
+ r = idn_res_decodename(ctx, 0, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=0
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, 0, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+#endif
+}
+
+//# TESTCASE
+// title: call encodename() with actions=rtcheck
+// group: generic-conversion quiet
+{
+ r = idn_res_encodename(ctx, IDN_RTCHECK, EUCJP_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call encodename() with actions=decode-query
+// group: generic-conversion quiet
+{
+ r = idn_res_encodename(ctx, IDN_DECODE_QUERY, EUCJP_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call encodename() with actions=decode-app
+// group: generic-conversion quiet
+{
+ r = idn_res_encodename(ctx, IDN_DECODE_APP, EUCJP_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call encodename() with actions=decode-stored
+// group: generic-conversion quiet
+{
+ r = idn_res_encodename(ctx, IDN_DECODE_STORED, EUCJP_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call encodename() with actions=(1<<31)
+// group: generic-conversion quiet
+{
+ r = idn_res_encodename(ctx, 1 << 31, EUCJP_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename() with actions=localmap
+// group: generic-conversion quiet
+{
+ r = idn_res_decodename(ctx, IDN_LOCALMAP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=localmap
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, IDN_LOCALMAP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=lencheck
+// group: generic-conversion quiet
+{
+ r = idn_res_decodename(ctx, IDN_LENCHECK, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=lencheck
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, IDN_LENCHECK, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=encode-query
+// group: generic-conversion quiet
+{
+ r = idn_res_decodename(ctx, IDN_ENCODE_QUERY, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=encode-query
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, IDN_ENCODE_QUERY, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=encode-app
+// group: generic-conversion quiet
+{
+ r = idn_res_decodename(ctx, IDN_ENCODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=encode-app
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, IDN_ENCODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=encode-stored
+// group: generic-conversion quiet
+{
+ r = idn_res_decodename(ctx, IDN_ENCODE_STORED, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=encode-stored
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, IDN_ENCODE_STORED, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=(1<<31)
+// group: generic-conversion quiet
+{
+ r = idn_res_decodename(ctx, 1 << 31, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=(1<<31)
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, 1 << 31, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call encodename() with actions=localconv
+// group: generic-conversion quiet
+{
+#ifndef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_encodename(ctx, IDN_LOCALCONV, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename() with actions=localconv
+// group: generic-conversion quiet
+{
+#ifndef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename(ctx, IDN_LOCALCONV, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_action);
+#endif
+}
+
+//# TESTCASE
+// title: call decodename2() with actions=localconv
+// group: generic-conversion
+{
+#ifndef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, IDN_LOCALCONV, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_failure);
+#endif
+}
+
+//# TESTCASE
+// title: call enable(0) and then encodename()
+// group: generic-conversion
+{
+ idn_res_enable(0);
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+}
+
+//# TESTCASE
+// title: call decodename() when IDN_DISABLE is defined
+// group: generic-conversion
+{
+ idn_res_enable(0);
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: call decodename() when IDN_DISABLE is defined
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ idn_res_enable(0);
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+#endif
+}
+
+//# TESTCASE
+// title: call enable(0) and then encodename()
+// group: generic-conversion
+{
+ idn_res_enable(0);
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+}
+
+//# TESTCASE
+// title: call enable(0) and then decodename()
+// group: generic-conversion
+{
+ idn_res_enable(0);
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: call enable(0) and then decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ idn_res_enable(0);
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+#endif
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE and call encodename()
+// group: generic-conversion
+{
+ setenv("IDN_DISABLE", "1", 1);
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE and call decodename()
+// group: generic-conversion
+{
+ setenv("IDN_DISABLE", "1", 1);
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE and call decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ setenv("IDN_DISABLE", "1", 1);
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+#endif
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE, and then call enable(1) and encodename()
+// group: generic-conversion
+{
+ setenv("IDN_DISABLE", "1", 1);
+ idn_res_enable(1);
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, UTF8_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE, and then call enable(1) and decodename()
+// group: generic-conversion
+{
+ setenv("IDN_DISABLE", "1", 1);
+ idn_res_enable(1);
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+}
+
+//# TESTCASE
+// title: set IDN_DISABLE, and then call enable(1) and decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ setenv("IDN_DISABLE", "1", 1);
+ idn_res_enable(1);
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, AUX_EUCJP_NAME, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+#endif
+}
+
+//# TESTCASE
+// title: overrun test for arg `to' of encodename()
+// group: generic-conversion
+{
+ /* Normal case */
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, UTF8_NAME, to,
+ strlen(PUNYCODE_NAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, UTF8_NAME, to,
+ strlen(PUNYCODE_NAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* enable(0) case */
+ idn_res_enable(0);
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, UTF8_NAME, to,
+ strlen(UTF8_NAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, UTF8_NAME, to,
+ strlen(UTF8_NAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* actions=0 case */
+ idn_res_enable(1);
+ r = idn_res_encodename(ctx, 0, UTF8_NAME, to, strlen(UTF8_NAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_NAME);
+
+ r = idn_res_encodename(ctx, 0, UTF8_NAME, to, strlen(UTF8_NAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: overrun test for arg `to' of decodename()
+// group: generic-conversion
+{
+ /* Normal case */
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to,
+ strlen(UTF8_REVNAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to,
+ strlen(UTF8_REVNAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* idn_res_enable(0) case */
+ idn_res_enable(0);
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to,
+ strlen(PUNYCODE_NAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to,
+ strlen(PUNYCODE_NAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* actions=0 case */
+ idn_res_enable(1);
+ r = idn_res_decodename(ctx, 0, PUNYCODE_NAME, to,
+ strlen(PUNYCODE_NAME) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, PUNYCODE_NAME);
+
+ r = idn_res_decodename(ctx, 0, PUNYCODE_NAME, to,
+ strlen(PUNYCODE_NAME));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: overrun test for arg `to' of decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* Normal case */
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, AUX_EUCJP_NAME, to,
+ strlen(UTF8_REVNAME) + 1, EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, UTF8_REVNAME);
+
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, AUX_EUCJP_NAME, to,
+ strlen(UTF8_REVNAME), EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* idn_res_enable(0) case */
+ idn_res_enable(0);
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, AUX_EUCJP_NAME, to,
+ strlen(AUX_EUCJP_NAME) + 1, EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, AUX_EUCJP_NAME, to,
+ strlen(AUX_EUCJP_NAME), EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ /* actions=0 case */
+ idn_res_enable(1);
+ r = idn_res_decodename2(ctx, 0, AUX_EUCJP_NAME, to,
+ strlen(AUX_EUCJP_NAME) + 1, EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, AUX_EUCJP_NAME);
+
+ r = idn_res_decodename2(ctx, 0, AUX_EUCJP_NAME, to,
+ strlen(AUX_EUCJP_NAME), EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+#endif
+}
+
+//# TESTCASE
+// title: call encodename() with tolen=0
+// group: generic-conversion
+{
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, UTF8_NAME, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: call decodename() with tolen=0
+// group: generic-conversion
+{
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, PUNYCODE_NAME, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: call decodename2() with tolen=0
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, AUX_EUCJP_NAME, to, 0,
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+#endif
+}
+
+//# TESTCASE
+// title: convert an empty string using encodename()
+// group: generic-conversion
+{
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, "", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "");
+}
+
+//# TESTCASE
+// title: convert an empty string using decodename()
+// group: generic-conversion
+{
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, "", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "");
+}
+
+//# TESTCASE
+// title: convert an empty string using decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, "", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "");
+#endif
+}
+
+//# TESTCASE
+// title: prohcheck by encodename()
+// group: generic-conversion
+{
+ /* U+1680: prohibited character */
+ r = idn_res_encodename(ctx, IDN_PROHCHECK, "<U+1680>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+}
+
+//# TESTCASE
+// title: unascheck by encodename()
+// group: generic-conversion
+{
+ /* U+0221: unassigned codepoint */
+ r = idn_res_encodename(ctx, IDN_UNASCHECK, "<U+0221>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+}
+
+//# TESTCASE
+// title: bidicheck by encodename()
+// group: generic-conversion
+{
+ /* U+05D0: bidirectional property is "R" */
+ /* `a': bidirectional property is "L" */
+ /* `0', `-': bidirectional property is "N" */
+ r = idn_res_encodename(ctx, IDN_BIDICHECK, "<U+05D0>", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_res_encodename(ctx, IDN_BIDICHECK, "<U+05D0><U+05D0>",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_res_encodename(ctx, IDN_BIDICHECK, "<U+05D0><U+05D0>-a",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_res_encodename(ctx, IDN_BIDICHECK, "<U+05D0>-a-<U+05D0>",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_res_encodename(ctx, IDN_BIDICHECK, "a-<U+05D0><U+05D0>",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_res_encodename(ctx, IDN_BIDICHECK, "<U+05D0><U+05D0>-0",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_res_encodename(ctx, IDN_BIDICHECK, "<U+05D0>-0-<U+05D0>",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_res_encodename(ctx, IDN_BIDICHECK, "0-<U+05D0><U+05D0>",
+ to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+}
+
+//# TESTCASE
+// title: asccheck by encodename()
+// group: generic-conversion
+{
+ r = idn_res_encodename(ctx, IDN_ASCCHECK, "-name", to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_res_encodename(ctx, IDN_ASCCHECK, "name-", to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+
+ r = idn_res_encodename(ctx, IDN_ASCCHECK, "n ame", to, sizeof(to));
+ ASSERT_RESULT(r, idn_prohibited);
+}
+
+//# TESTCASE
+// title: lencheck by encodename()
+// group: generic-conversion
+{
+ r = idn_res_encodename(ctx, IDN_LENCHECK,
+ "123456789-123456789-123456789-123456789-"
+ "123456789-123456789-123", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_res_encodename(ctx, IDN_LENCHECK,
+ "123456789-123456789-123456789-123456789-"
+ "123456789-123456789-1234", to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_length);
+
+ r = idn_res_encodename(ctx, IDN_LENCHECK, "a..b", to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_length);
+}
+
+//# TESTCASE
+// title: rtcheck non-prohchecked label by decodename()
+// group: generic-conversion
+{
+ /* "xn--6ue" -> "U+1680" (prohibited character) */
+ r = idn_res_decodename(ctx, IDN_RTCHECK, "xn--6ue", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--6ue");
+}
+
+//# TESTCASE
+// title: rtcheck non-unaschecked label by decodename()
+// group: generic-conversion
+{
+ /* "xn--6la" -> "U+0221" (unassigned codepoint) */
+ r = idn_res_decodename(ctx, IDN_IDNCONV | IDN_RTCHECK | IDN_UNASCHECK,
+ "xn--6la", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--6la");
+}
+
+//# TESTCASE
+// title: rtcheck non-ascchecked label by decodename()
+// group: generic-conversion
+{
+ /* "xn----x7t" -> "- U+3042" */
+ r = idn_res_decodename(ctx, IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK,
+ "xn----x7t", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn----x7t");
+
+ /* "xn----w7t" -> "U+3042 -" */
+ r = idn_res_decodename(ctx, IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK,
+ "xn----w7t", to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn----w7t");
+}
+
+//# TESTCASE
+// title: rtcheck non-lenchecked label by decodename()
+// group: generic-conversion
+{
+ /* `s1' has 63 characters */
+ const char *s1 =
+ "xn--l8jaa5522a8sj38bzugvvblo3y90fjzgvxlmxscifws3d43odzaq6aj340b";
+
+ const char *s1rev =
+ "<U+9752><U+68EE><U+5CA9><U+624B><U+5BAE><U+57CE><U+79CB><U+7530>"
+ "<U+5C71><U+5F62><U+798F><U+5CF6><U+6771><U+4EAC><U+795E><U+5948>"
+ "<U+5DDD><U+3042><U+3042><U+3042>";
+
+ /* `s2' has 64 characters */
+ const char *s2 =
+ "xn--a-w7ta6522a8sj38bzugvvblo3y90fjzgvxlmxscifws3d43odzaq6aj340b";
+
+ /* `s3' has an empty label */
+ const char *s3 = "a..b";
+
+ r = idn_res_decodename(ctx, IDN_IDNCONV | IDN_RTCHECK, s1, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s1rev);
+
+ r = idn_res_decodename(ctx, IDN_IDNCONV | IDN_RTCHECK, s2, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s2);
+
+ r = idn_res_decodename(ctx, IDN_IDNCONV | IDN_RTCHECK, s3, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s3);
+}
+
+//# TESTCASE
+// title: rtcheck non-prohchecked label by decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* "xn--6ue" -> "U+1680" (prohibited character) */
+ r = idn_res_decodename2(ctx, IDN_RTCHECK, "xn--6ue", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--6ue");
+#endif
+}
+
+//# TESTCASE
+// title: rtcheck non-unaschecked label by decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* "xn--6la" -> "U+0221" (unassigned codepoint) */
+ r = idn_res_decodename2(ctx, IDN_IDNCONV | IDN_RTCHECK | IDN_UNASCHECK,
+ "xn--6la", to, sizeof(to), EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn--6la");
+#endif
+}
+
+//# TESTCASE
+// title: rtcheck non-ascchecked label by decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* "xn----x7t" -> "- U+3042" */
+ r = idn_res_decodename2(ctx, IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK,
+ "xn----x7t", to, sizeof(to), EUCJP_ENCODING_NAME);
+
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn----x7t");
+
+ /* "xn----w7t" -> "U+3042 -" */
+ r = idn_res_decodename2(ctx, IDN_IDNCONV | IDN_RTCHECK | IDN_ASCCHECK,
+ "xn----w7t", to, sizeof(to), EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "xn----w7t");
+#endif
+}
+
+//# TESTCASE
+// title: rtcheck non-lenchecked label by decodename2()
+// group: generic-conversion
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* `s1' has 63 characters */
+ const char *s1 =
+ "xn--l8jaa5522a8sj38bzugvvblo3y90fjzgvxlmxscifws3d43odzaq6aj340b";
+
+ const char *s1rev =
+ "<U+9752><U+68EE><U+5CA9><U+624B><U+5BAE><U+57CE><U+79CB><U+7530>"
+ "<U+5C71><U+5F62><U+798F><U+5CF6><U+6771><U+4EAC><U+795E><U+5948>"
+ "<U+5DDD><U+3042><U+3042><U+3042>";
+
+ /* `s2' has 64 characters */
+ const char *s2 =
+ "xn--a-w7ta6522a8sj38bzugvvblo3y90fjzgvxlmxscifws3d43odzaq6aj340b";
+
+ /* `s3' has an empty label */
+ const char *s3 = "a..b";
+
+ r = idn_res_decodename2(ctx, IDN_IDNCONV | IDN_RTCHECK, s1, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s1rev);
+
+ r = idn_res_decodename2(ctx, IDN_IDNCONV | IDN_RTCHECK, s2, to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s2);
+
+ r = idn_res_decodename(ctx, IDN_IDNCONV | IDN_RTCHECK, s3, to, sizeof(to));
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, s3);
+#endif
+}
+
+//# TESTCASE
+// title: pass broken string as `from' to encodename()
+// group: generic-conversion quiet
+{
+ /* "\xe3\x21" is not valid UTF-8 string */
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, "\xe3\x21", to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_encoding);
+}
+
+//# TESTCASE
+// title: pass broken string as `from' to decodename()
+// group: generic-conversion quiet
+{
+ /* "\xe3\x21" is not valid UTF-8 string */
+ r = idn_res_decodename(ctx, IDN_DECODE_APP, "\xe3\x21", to, sizeof(to));
+ ASSERT_RESULT(r, idn_invalid_encoding);
+}
+
+//# TESTCASE
+// title: pass broken string as `from' to decodename2()
+// group: generic-conversion quiet
+{
+#ifdef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ /* "\xa4\x21" is not valid EUC-JP string */
+ r = idn_res_decodename2(ctx, IDN_DECODE_APP, "\xa4\x21", to, sizeof(to),
+ EUCJP_ENCODING_NAME);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+#endif
+}
+
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/resconf.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/resconf.tsy
new file mode 100644
index 0000000..a4c2f35
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/resconf.tsy
@@ -0,0 +1,1026 @@
+#ifndef lint
+static char *rcsid = "$Id: resconf.tsy,v 1.1.1.1 2003/06/04 00:27:00 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <idn/resconf.h>
+#include <idn/converter.h>
+#include <idn/log.h>
+
+#include "setenv.h"
+#include "testutil.h"
+
+#define CONF_FILENAME "test.conf"
+#define MAP_FILENAME "test.map"
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: generic-init
+{
+ idn_result_t r;
+ idn_resconf_t ctx = NULL;
+
+ setenv("IDN_LOCAL_CODESET", "UTF-8", 1);
+
+ r = idn_resconf_initialize();
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_resconf_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: generic-init
+{
+ if (ctx != NULL)
+ idn_resconf_destroy(ctx);
+ remove(CONF_FILENAME);
+ remove(MAP_FILENAME);
+}
+
+//# SETUP
+// group: set-defaults
+{
+ r = idn_resconf_setdefaults(ctx);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TEARDOWN
+// group: set-defaults
+{
+}
+
+//# SETUP
+// group: quiet
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//# SETUP
+// group: delimitermap_ctx
+{
+ idn_delimitermap_t delimitermap_ctx1 = NULL;
+ idn_delimitermap_t delimitermap_ctx2 = NULL;
+}
+
+//# TEARDOWN
+// group: delimitermap_ctx
+{
+ if (delimitermap_ctx1 != NULL)
+ idn_delimitermap_destroy(delimitermap_ctx1);
+ if (delimitermap_ctx2 != NULL)
+ idn_delimitermap_destroy(delimitermap_ctx2);
+}
+
+//# SETUP
+// group: idnconverter_ctx
+{
+ idn_converter_t idnconverter_ctx1 = NULL;
+ idn_converter_t idnconverter_ctx2 = NULL;
+}
+
+//# TEARDOWN
+// group: idnconverter_ctx
+{
+ if (idnconverter_ctx1 != NULL)
+ idn_converter_destroy(idnconverter_ctx1);
+ if (idnconverter_ctx2 != NULL)
+ idn_converter_destroy(idnconverter_ctx2);
+}
+
+//# SETUP
+// group: localconverter_ctx
+{
+ idn_converter_t localconverter_ctx1 = NULL;
+ idn_converter_t localconverter_ctx2 = NULL;
+}
+
+//# TEARDOWN
+// group: localconverter_ctx
+{
+ if (localconverter_ctx1 != NULL)
+ idn_converter_destroy(localconverter_ctx1);
+ if (localconverter_ctx2 != NULL)
+ idn_converter_destroy(localconverter_ctx2);
+}
+
+//# SETUP
+// group: auxidnconverter_ctx
+{
+ idn_converter_t auxidnconverter_ctx1 = NULL;
+ idn_converter_t auxidnconverter_ctx2 = NULL;
+}
+
+//# TEARDOWN
+// group: auxidnconverter_ctx
+{
+ if (auxidnconverter_ctx1 != NULL)
+ idn_converter_destroy(auxidnconverter_ctx1);
+ if (auxidnconverter_ctx2 != NULL)
+ idn_converter_destroy(auxidnconverter_ctx2);
+}
+
+//# SETUP
+// group: mapselector_ctx
+{
+ idn_mapselector_t mapselector_ctx1 = NULL;
+ idn_mapselector_t mapselector_ctx2 = NULL;
+}
+
+//# TEARDOWN
+// group: mapselector_ctx
+{
+ if (mapselector_ctx1 != NULL)
+ idn_mapselector_destroy(mapselector_ctx1);
+ if (mapselector_ctx2 != NULL)
+ idn_mapselector_destroy(mapselector_ctx2);
+}
+
+//# SETUP
+// group: mapper_ctx
+{
+ idn_mapper_t mapper_ctx1 = NULL;
+ idn_mapper_t mapper_ctx2 = NULL;
+}
+
+//# TEARDOWN
+// group: mapper_ctx
+{
+ if (mapper_ctx1 != NULL)
+ idn_mapper_destroy(mapper_ctx1);
+ if (mapper_ctx2 != NULL)
+ idn_mapper_destroy(mapper_ctx2);
+}
+
+//# SETUP
+// group: normalizer_ctx
+{
+ idn_normalizer_t normalizer_ctx1 = NULL;
+ idn_normalizer_t normalizer_ctx2 = NULL;
+}
+
+//# TEARDOWN
+// group: normalizer_ctx
+{
+ if (normalizer_ctx1 != NULL)
+ idn_normalizer_destroy(normalizer_ctx1);
+ if (normalizer_ctx2 != NULL)
+ idn_normalizer_destroy(normalizer_ctx2);
+}
+
+//# SETUP
+// group: prohibitchecker_ctx
+{
+ idn_checker_t prohibitchecker_ctx1 = NULL;
+ idn_checker_t prohibitchecker_ctx2 = NULL;
+}
+
+//# TEARDOWN
+// group: prohibitchecker_ctx
+{
+ if (prohibitchecker_ctx1 != NULL)
+ idn_checker_destroy(prohibitchecker_ctx1);
+ if (prohibitchecker_ctx2 != NULL)
+ idn_checker_destroy(prohibitchecker_ctx2);
+}
+
+//# SETUP
+// group: unassignedchecker_ctx
+{
+ idn_checker_t unassignedchecker_ctx1 = NULL;
+ idn_checker_t unassignedchecker_ctx2 = NULL;
+}
+
+//# TEARDOWN
+// group: unassignedchecker_ctx
+{
+ if (unassignedchecker_ctx1 != NULL)
+ idn_checker_destroy(unassignedchecker_ctx1);
+ if (unassignedchecker_ctx2 != NULL)
+ idn_checker_destroy(unassignedchecker_ctx2);
+}
+
+//# SETUP
+// group: bidichecker_ctx
+{
+ idn_checker_t bidichecker_ctx1 = NULL;
+ idn_checker_t bidichecker_ctx2 = NULL;
+}
+
+//# TEARDOWN
+// group: bidichecker_ctx
+{
+ if (bidichecker_ctx1 != NULL)
+ idn_checker_destroy(bidichecker_ctx1);
+ if (bidichecker_ctx2 != NULL)
+ idn_checker_destroy(bidichecker_ctx2);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call create() without initialization.
+//--
+// This must be the first test case.
+{
+ idn_result_t r;
+ idn_resconf_t ctx = NULL;
+
+ r = idn_resconf_create(&ctx);
+ ASSERT_RESULT(r, idn_failure);
+
+ if (ctx != NULL)
+ idn_resconf_destroy(ctx);
+}
+
+//# TESTCASE
+// title: call initialize() twice.
+//
+{
+ idn_result_t r;
+
+ r = idn_resconf_initialize();
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_resconf_initialize();
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: call create()
+{
+ idn_result_t r;
+ idn_resconf_t ctx;
+
+ r = idn_resconf_initialize();
+ ASSERT_RESULT(r, idn_success);
+
+ r = idn_resconf_create(&ctx);
+ ASSERT_RESULT(r, idn_success);
+
+ if (ctx != NULL)
+ idn_resconf_destroy(ctx);
+}
+
+//# TESTCASE
+// title: load file (idn-encoding)
+// group: generic-init
+{
+ const char *idn_encoding;
+
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding Punycode",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: load file (nameprep)
+// group: generic-init
+{
+ const char *idn_encoding;
+
+ create_conf_file(CONF_FILENAME, 0,
+ "nameprep " IDN_NAMEPREP_CURRENT,
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: load file (idn-encoding & nameprep)
+// group: generic-init
+{
+ const char *idn_encoding;
+
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding Punycode",
+ "nameprep " IDN_NAMEPREP_CURRENT,
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: load file (empty)
+// group: generic-init
+{
+ const char *idn_encoding;
+
+ create_conf_file(CONF_FILENAME, 0,
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: load file (local-map filemap)
+// group: generic-init
+{
+ const char *idn_encoding;
+
+ create_conf_file(CONF_FILENAME, 0,
+ "local-map .jp filemap:" MAP_FILENAME,
+ NULL);
+ create_conf_file(MAP_FILENAME, 0,
+ "2212; FF0D",
+ NULL);
+
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: load file (local-map nameprep)
+// group: generic-init
+{
+ const char *idn_encoding;
+
+ create_conf_file(CONF_FILENAME, 0,
+ "local-map .jp " IDN_NAMEPREP_CURRENT,
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: set defaults
+// group: generic-init set-defaults
+{
+}
+
+//# TESTCASE
+// title: load file (no file)
+// group: generic-init
+{
+ r = idn_resconf_loadfile(ctx, "no-such-file");
+ ASSERT_RESULT(r, idn_nofile);
+}
+
+//# TESTCASE
+// title: load file (empty file name)
+// group: generic-init
+{
+ r = idn_resconf_loadfile(ctx, "");
+ ASSERT_RESULT(r, idn_nofile);
+}
+
+//# TESTCASE
+// title: load file (unknown command)
+// group: generic-init quiet
+{
+ create_conf_file(CONF_FILENAME, 0,
+ "unknown-command " IDN_NAMEPREP_CURRENT,
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: load file (no newline at the end of file)
+// group: generic-init quiet
+{
+ create_conf_file(CONF_FILENAME, CONF_NO_EOF_NEWLINE,
+ "nameprep " IDN_NAMEPREP_CURRENT,
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: load file (too long line)
+// group: generic-init quiet
+{
+ char arg[1024];
+ char *line;
+
+ /* arg = "local-map . ////..." */
+ memset(arg, '/', sizeof(arg));
+ arg[sizeof(arg) - 1] = '\0';
+ line = "local-map . ";
+ memcpy(arg, line, strlen(line));
+
+ create_conf_file(CONF_FILENAME, 0, arg, NULL);
+
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: load file (empty file)
+// group: generic-init
+{
+ create_conf_file(CONF_FILENAME, 0, "", NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: load file (invalid parameter for idn-encoding)
+// group: generic-init quiet
+{
+#ifndef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding invalid-encoding-name",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_name);
+#endif
+}
+
+//# TESTCASE
+// title: load file (define idn-encoding twice)
+// group: generic-init quiet
+{
+#ifndef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ create_conf_file(CONF_FILENAME, CONF_NO_EOF_NEWLINE,
+ "idn-encoding Punycode",
+ "idn-encoding Punycode",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+#endif
+}
+
+//# TESTCASE
+// title: load file (invalid parameter for nameprep)
+// group: generic-init quiet
+{
+ create_conf_file(CONF_FILENAME, 0,
+ "nameprep invalid-version",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: load file (define nameprep twice)
+// group: generic-init quiet
+{
+#ifndef WITHOUT_ICONV
+ SKIP_TESTCASE;
+#else
+ create_conf_file(CONF_FILENAME, CONF_NO_EOF_NEWLINE,
+ "nameprep " IDN_NAMEPREP_CURRENT,
+ "nameprep " IDN_NAMEPREP_CURRENT,
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+#endif
+}
+
+//# TESTCASE
+// title: load file (invalid parameter for local-map)
+// group: generic-init quiet
+{
+ create_conf_file(CONF_FILENAME, 0,
+ "local-map .jp :",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_name);
+
+ create_conf_file(CONF_FILENAME, 0,
+ "local-map .jp invalid:/dev/null",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_name);
+
+ create_conf_file(CONF_FILENAME, 0,
+ "local-map .jp filemap",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_nofile);
+
+ create_conf_file(CONF_FILENAME, 0,
+ "local-map .jp filemap:",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_nofile);
+
+ create_conf_file(CONF_FILENAME, 0,
+ "local-map .jp filemap:no-such-file",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_nofile);
+
+ create_conf_file(CONF_FILENAME, 0,
+ "local-map "
+ "abcdefghijklmnopqrstuvwxyz0123"
+ "abcdefghijklmnopqrstuvwxyz0123"
+ "4567 "
+ IDN_NAMEPREP_CURRENT,
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_name);
+}
+
+//# TESTCASE
+// title: load file (pass wrong number of parameters to idn-encoding)
+// group: generic-init quiet
+{
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding ",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+
+ create_conf_file(CONF_FILENAME, 0,
+ "idn-encoding Punycode ?",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: load file (pass wrong number of parameters to nameprep)
+// group: generic-init quiet
+{
+ create_conf_file(CONF_FILENAME, 0,
+ "nameprep ",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+
+ create_conf_file(CONF_FILENAME, 0,
+ "nameprep " IDN_NAMEPREP_CURRENT " ?",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: load file (pass wrong number of parameters to local-map)
+// group: generic-init quiet
+{
+ create_conf_file(CONF_FILENAME, 0,
+ "local-map ",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+
+ create_conf_file(CONF_FILENAME, 0,
+ "local-map .jp ",
+ NULL);
+ r = idn_resconf_loadfile(ctx, CONF_FILENAME);
+ ASSERT_RESULT(r, idn_invalid_syntax);
+}
+
+//# TESTCASE
+// title: getdelimitermap
+// group: generic-init set-defaults delimitermap_ctx
+{
+ delimitermap_ctx1 = idn_resconf_getdelimitermap(ctx);
+ ASSERT_PTR_NE(delimitermap_ctx1, NULL);
+}
+
+//# TESTCASE
+// title: setdelimitermap
+// group: generic-init set-defaults delimitermap_ctx
+{
+ r = idn_delimitermap_create(&delimitermap_ctx1);
+ ASSERT_RESULT(r, idn_success);
+
+ /* set delimitermap context. */
+ idn_resconf_setdelimitermap(ctx, delimitermap_ctx1);
+ delimitermap_ctx2 = idn_resconf_getdelimitermap(ctx);
+ ASSERT_PTR(delimitermap_ctx2, delimitermap_ctx1);
+ idn_delimitermap_destroy(delimitermap_ctx2);
+
+ /* set NULL as delimitermap context */
+ idn_resconf_setdelimitermap(ctx, NULL);
+ delimitermap_ctx2 = idn_resconf_getdelimitermap(ctx);
+ ASSERT_PTR(delimitermap_ctx2, NULL);
+}
+
+//# TESTCASE
+// title: addalldelimitermapucs
+// group: generic-init set-defaults
+{
+ static unsigned long v[] = {0x002C, 0x3001, 0xFF0C};
+ int nv = sizeof(v) / sizeof(*v);
+
+ r = idn_resconf_addalldelimitermapucs(ctx, v, nv);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: getidnconverter
+// group: generic-init set-defaults idnconverter_ctx
+{
+ idnconverter_ctx1 = idn_resconf_getidnconverter(ctx);
+ ASSERT_PTR_NE(idnconverter_ctx1, NULL);
+}
+
+//# TESTCASE
+// title: setidnconverter
+// group: generic-init set-defaults idnconverter_ctx
+{
+ r = idn_converter_create("Punycode", &idnconverter_ctx1, 0);
+ ASSERT_RESULT(r, idn_success);
+
+ /* set idnconverter context. */
+ idn_resconf_setidnconverter(ctx, idnconverter_ctx1);
+ idnconverter_ctx2 = idn_resconf_getidnconverter(ctx);
+ ASSERT_PTR(idnconverter_ctx2, idnconverter_ctx1);
+ idn_converter_destroy(idnconverter_ctx2);
+
+ /* set NULL as idnconverter context */
+ idn_resconf_setidnconverter(ctx, NULL);
+ idnconverter_ctx2 = idn_resconf_getidnconverter(ctx);
+ ASSERT_PTR(idnconverter_ctx2, NULL);
+}
+
+//# TESTCASE
+// title: getlocalconverter
+// group: generic-init set-defaults localconverter_ctx
+{
+ localconverter_ctx1 = idn_resconf_getlocalconverter(ctx);
+#ifdef WITHOUT_ICONV
+ ASSERT_PTR(localconverter_ctx1, NULL);
+#else
+ ASSERT_PTR_NE(localconverter_ctx1, NULL);
+#endif
+}
+
+//# TESTCASE
+// title: setlocalconverter
+// group: generic-init set-defaults localconverter_ctx
+{
+ r = idn_converter_create("UTF-8", &localconverter_ctx1, 0);
+ ASSERT_RESULT(r, idn_success);
+
+ /* set localconverter context. */
+ idn_resconf_setlocalconverter(ctx, localconverter_ctx1);
+ localconverter_ctx2 = idn_resconf_getlocalconverter(ctx);
+#ifdef WITHOUT_ICONV
+ ASSERT_PTR(localconverter_ctx2, NULL);
+#else
+ ASSERT_PTR(localconverter_ctx2, localconverter_ctx1);
+ idn_converter_destroy(localconverter_ctx2);
+#endif
+
+ /* set NULL as localconverter context */
+ idn_resconf_setlocalconverter(ctx, NULL);
+ localconverter_ctx2 = idn_resconf_getlocalconverter(ctx);
+#ifdef WITHOUT_ICONV
+ ASSERT_PTR(localconverter_ctx2, NULL);
+#else
+ ASSERT_PTR_NE(localconverter_ctx2, NULL);
+#endif
+}
+
+//# TESTCASE
+// title: getauxidnconverter
+// group: generic-init set-defaults auxidnconverter_ctx
+{
+ auxidnconverter_ctx1 = idn_resconf_getauxidnconverter(ctx);
+ ASSERT_PTR(auxidnconverter_ctx1, NULL);
+}
+
+//# TESTCASE
+// title: setauxidnconverter
+// group: generic-init set-defaults auxidnconverter_ctx
+{
+ r = idn_converter_create("Punycode", &auxidnconverter_ctx1, 0);
+ ASSERT_RESULT(r, idn_success);
+
+ /* set auxidnconverter context. */
+ idn_resconf_setauxidnconverter(ctx, auxidnconverter_ctx1);
+ auxidnconverter_ctx2 = idn_resconf_getauxidnconverter(ctx);
+ ASSERT_PTR(auxidnconverter_ctx2, auxidnconverter_ctx1);
+ idn_converter_destroy(auxidnconverter_ctx2);
+
+ /* set NULL as auxidnconverter context */
+ idn_resconf_setauxidnconverter(ctx, NULL);
+ auxidnconverter_ctx2 = idn_resconf_getauxidnconverter(ctx);
+ ASSERT_PTR(auxidnconverter_ctx2, NULL);
+}
+
+//# TESTCASE
+// title: getlocalmapselector
+// group: generic-init set-defaults mapselector_ctx
+{
+ mapselector_ctx1 = idn_resconf_getlocalmapselector(ctx);
+ ASSERT_PTR(mapselector_ctx1, NULL);
+}
+
+//# TESTCASE
+// title: setlocalmapselector
+// group: generic-init set-defaults mapselector_ctx
+{
+ r = idn_mapselector_create(&mapselector_ctx1);
+ ASSERT_RESULT(r, idn_success);
+
+ /* set localmapselector context. */
+ idn_resconf_setlocalmapselector(ctx, mapselector_ctx1);
+ mapselector_ctx2 = idn_resconf_getlocalmapselector(ctx);
+ ASSERT_PTR(mapselector_ctx2, mapselector_ctx1);
+ idn_mapselector_destroy(mapselector_ctx2);
+
+ /* set NULL as localmapselector context */
+ idn_resconf_setlocalmapselector(ctx, NULL);
+ mapselector_ctx2 = idn_resconf_getlocalmapselector(ctx);
+ ASSERT_PTR(mapselector_ctx2, NULL);
+}
+
+//# TESTCASE
+// title: addalllocalmapselectornames
+// group: generic-init set-defaults
+{
+ static const char *names[] = {
+ "filemap:" MAP_FILENAME,
+ "filemap:" MAP_FILENAME,
+ "filemap:" MAP_FILENAME
+ };
+ int nnames = sizeof(names) / sizeof(*names);
+
+ create_conf_file(MAP_FILENAME, 0,
+ "2212; FF0D",
+ NULL);
+ r = idn_resconf_addalllocalmapselectornames(ctx, ".jp", names, nnames);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: getmapper
+// group: generic-init set-defaults mapper_ctx
+{
+ mapper_ctx1 = idn_resconf_getmapper(ctx);
+ ASSERT_PTR_NE(mapper_ctx1, NULL);
+}
+
+//# TESTCASE
+// title: setmapper
+// group: generic-init set-defaults mapper_ctx
+{
+ r = idn_mapper_create(&mapper_ctx1);
+ ASSERT_RESULT(r, idn_success);
+
+ /* set mapper context. */
+ idn_resconf_setmapper(ctx, mapper_ctx1);
+ mapper_ctx2 = idn_resconf_getmapper(ctx);
+ ASSERT_PTR(mapper_ctx2, mapper_ctx1);
+ idn_mapper_destroy(mapper_ctx2);
+
+ /* set NULL as mapper context */
+ idn_resconf_setmapper(ctx, NULL);
+ mapper_ctx2 = idn_resconf_getmapper(ctx);
+ ASSERT_PTR(mapper_ctx2, NULL);
+}
+
+//# TESTCASE
+// title: addallmappernames
+// group: generic-init set-defaults
+{
+ static const char *names[] = {
+ IDN_NAMEPREP_CURRENT,
+ IDN_NAMEPREP_CURRENT,
+ IDN_NAMEPREP_CURRENT
+ };
+ int nnames = sizeof(names) / sizeof(*names);
+
+ r = idn_resconf_addallmappernames(ctx, names, nnames);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: getnormalizer
+// group: generic-init set-defaults normalizer_ctx
+{
+ normalizer_ctx1 = idn_resconf_getnormalizer(ctx);
+ ASSERT_PTR_NE(normalizer_ctx1, NULL);
+}
+
+//# TESTCASE
+// title: setnormalizer
+// group: generic-init set-defaults normalizer_ctx
+{
+ r = idn_normalizer_create(&normalizer_ctx1);
+ ASSERT_RESULT(r, idn_success);
+
+ /* set normalizer context. */
+ idn_resconf_setnormalizer(ctx, normalizer_ctx1);
+ normalizer_ctx2 = idn_resconf_getnormalizer(ctx);
+ ASSERT_PTR(normalizer_ctx2, normalizer_ctx1);
+ idn_normalizer_destroy(normalizer_ctx2);
+
+ /* set NULL as normalizer context */
+ idn_resconf_setnormalizer(ctx, NULL);
+ normalizer_ctx2 = idn_resconf_getnormalizer(ctx);
+ ASSERT_PTR(normalizer_ctx2, NULL);
+}
+
+//# TESTCASE
+// title: addallnormalizernames
+// group: generic-init set-defaults
+{
+ static const char *names[] = {
+ IDN_NAMEPREP_CURRENT,
+ IDN_NAMEPREP_CURRENT,
+ IDN_NAMEPREP_CURRENT
+ };
+ int nnames = sizeof(names) / sizeof(*names);
+
+ r = idn_resconf_addallnormalizernames(ctx, names, nnames);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: getprohibitchecker
+// group: generic-init set-defaults prohibitchecker_ctx
+{
+ prohibitchecker_ctx1 = idn_resconf_getprohibitchecker(ctx);
+ ASSERT_PTR_NE(prohibitchecker_ctx1, NULL);
+}
+
+//# TESTCASE
+// title: setprohibitchecker
+// group: generic-init set-defaults prohibitchecker_ctx
+{
+ r = idn_checker_create(&prohibitchecker_ctx1);
+ ASSERT_RESULT(r, idn_success);
+
+ /* set checker context. */
+ idn_resconf_setprohibitchecker(ctx, prohibitchecker_ctx1);
+ prohibitchecker_ctx2 = idn_resconf_getprohibitchecker(ctx);
+ ASSERT_PTR(prohibitchecker_ctx2, prohibitchecker_ctx1);
+ idn_checker_destroy(prohibitchecker_ctx2);
+
+ /* set NULL as checker context */
+ idn_resconf_setprohibitchecker(ctx, NULL);
+ prohibitchecker_ctx2 = idn_resconf_getprohibitchecker(ctx);
+ ASSERT_PTR(prohibitchecker_ctx2, NULL);
+}
+
+//# TESTCASE
+// title: addallprohibitcheckernames
+// group: generic-init set-defaults
+{
+ static const char *names[] = {
+ IDN_NAMEPREP_CURRENT,
+ IDN_NAMEPREP_CURRENT,
+ IDN_NAMEPREP_CURRENT
+ };
+ int nnames = sizeof(names) / sizeof(*names);
+
+ r = idn_resconf_addallprohibitcheckernames(ctx, names, nnames);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: getunassignedchecker
+// group: generic-init set-defaults unassignedchecker_ctx
+{
+ unassignedchecker_ctx1 = idn_resconf_getunassignedchecker(ctx);
+ ASSERT_PTR_NE(unassignedchecker_ctx1, NULL);
+}
+
+//# TESTCASE
+// title: setunassignedchecker
+// group: generic-init set-defaults unassignedchecker_ctx
+{
+ r = idn_checker_create(&unassignedchecker_ctx1);
+ ASSERT_RESULT(r, idn_success);
+
+ /* set checker context. */
+ idn_resconf_setunassignedchecker(ctx, unassignedchecker_ctx1);
+ unassignedchecker_ctx2 = idn_resconf_getunassignedchecker(ctx);
+ ASSERT_PTR(unassignedchecker_ctx2, unassignedchecker_ctx1);
+ idn_checker_destroy(unassignedchecker_ctx2);
+
+ /* set NULL as checker context */
+ idn_resconf_setunassignedchecker(ctx, NULL);
+ unassignedchecker_ctx2 = idn_resconf_getunassignedchecker(ctx);
+ ASSERT_PTR(unassignedchecker_ctx2, NULL);
+}
+
+//# TESTCASE
+// title: addallunassignedcheckernames
+// group: generic-init set-defaults
+{
+ static const char *names[] = {
+ IDN_NAMEPREP_CURRENT,
+ IDN_NAMEPREP_CURRENT,
+ IDN_NAMEPREP_CURRENT
+ };
+ int nnames = sizeof(names) / sizeof(*names);
+
+ r = idn_resconf_addallunassignedcheckernames(ctx, names, nnames);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: getbidichecker
+// group: generic-init set-defaults bidichecker_ctx
+{
+ bidichecker_ctx1 = idn_resconf_getbidichecker(ctx);
+ ASSERT_PTR_NE(bidichecker_ctx1, NULL);
+}
+
+//# TESTCASE
+// title: setbidichecker
+// group: generic-init set-defaults bidichecker_ctx
+{
+ r = idn_checker_create(&bidichecker_ctx1);
+ ASSERT_RESULT(r, idn_success);
+
+ /* set checker context. */
+ idn_resconf_setbidichecker(ctx, bidichecker_ctx1);
+ bidichecker_ctx2 = idn_resconf_getbidichecker(ctx);
+ ASSERT_PTR(bidichecker_ctx2, bidichecker_ctx1);
+ idn_checker_destroy(bidichecker_ctx2);
+
+ /* set NULL as checker context */
+ idn_resconf_setbidichecker(ctx, NULL);
+ bidichecker_ctx2 = idn_resconf_getbidichecker(ctx);
+ ASSERT_PTR(bidichecker_ctx2, NULL);
+}
+
+//# TESTCASE
+// title: addallbidicheckernames
+// group: generic-init set-defaults
+{
+ static const char *names[] = {
+ IDN_NAMEPREP_CURRENT,
+ IDN_NAMEPREP_CURRENT,
+ IDN_NAMEPREP_CURRENT
+ };
+ int nnames = sizeof(names) / sizeof(*names);
+
+ r = idn_resconf_addallbidicheckernames(ctx, names, nnames);
+ ASSERT_RESULT(r, idn_success);
+}
+
+//# TESTCASE
+// title: setnameprepversion
+// group: generic-init set-defaults
+{
+ idn_resconf_setnameprepversion(ctx, IDN_NAMEPREP_CURRENT);
+ ASSERT_RESULT(r, idn_success);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/setenv.c b/contrib/idn/idnkit-1.0-src/lib/tests/setenv.c
new file mode 100644
index 0000000..9c12bf1
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/setenv.c
@@ -0,0 +1,134 @@
+#ifndef lint
+static char *rcsid = "$Id: setenv.c,v 1.1.1.1 2003/06/04 00:27:01 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+/*
+ * We don't include <stdlib.h> here.
+ * Also <stdlib.h> may declare `environ' and its type might be different
+ * from ours.
+ */
+extern char **environ;
+
+typedef struct myenv myenv_t;
+
+struct myenv {
+ char *pointer;
+ myenv_t *next;
+ myenv_t *prev;
+};
+
+static myenv_t *myenvs = NULL;
+
+void
+myunsetenv(const char *name) {
+ char **e;
+ myenv_t *mye;
+ size_t namelen;
+ extern void free(void *);
+
+ namelen = strlen(name);
+ for (e = environ; *e != NULL; e++) {
+ if (strncmp(*e, name, namelen) == 0 && (*e)[namelen] == '=')
+ break;
+ }
+ if (*e == NULL)
+ return;
+
+ for (mye = myenvs; mye != NULL; mye = mye->next) {
+ if (mye->pointer == *e) {
+ if (mye->next != NULL)
+ mye->next->prev = mye->prev;
+ if (mye->prev != NULL)
+ mye->prev->next = mye->next;
+ if (mye->next == NULL && mye->prev == NULL)
+ myenvs = NULL;
+ free(mye);
+ free(*e);
+ break;
+ }
+ }
+
+ for ( ; *e != NULL; e++)
+ *e = *(e + 1);
+}
+
+#include <stdlib.h>
+
+int
+mysetenv(const char *name, const char *value, int overwrite) {
+ myenv_t *mye;
+ char *buffer;
+ int result;
+
+ if (getenv(name) != NULL && !overwrite)
+ return 0;
+
+ buffer = (char *) malloc(strlen(name) + strlen(value) + 2);
+ if (buffer == NULL)
+ return -1;
+ strcpy(buffer, name);
+ strcat(buffer, "=");
+ strcat(buffer, value);
+
+ myunsetenv(name);
+
+ mye = (myenv_t *) malloc(sizeof(myenv_t));
+ if (mye == NULL)
+ return -1;
+ mye->pointer = buffer;
+ mye->next = myenvs;
+ mye->prev = NULL;
+ if (myenvs != NULL)
+ myenvs->prev = mye;
+ myenvs = mye;
+
+ result = putenv(buffer);
+
+ return result;
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/setenv.h b/contrib/idn/idnkit-1.0-src/lib/tests/setenv.h
new file mode 100644
index 0000000..704c179
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/setenv.h
@@ -0,0 +1,61 @@
+/* $Id: setenv.h,v 1.1.1.1 2003/06/04 00:27:01 marka Exp $ */
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_SETENV_H
+#define IDN_SETENV_H
+
+#include "testconfig.h"
+
+#ifndef HAVE_SETENV
+#define unsetenv(a1) myunsetenv(a1)
+#endif
+
+#ifndef HAVE_SETENV
+#define setenv(a1, a2, a3) mysetenv(a1, a2, a3)
+#endif
+
+void myunsetenv(const char *name);
+int mysetenv(const char *name, const char *value, int overwrite);
+
+#endif /* IDN_SETENV_H */
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/testsuite.c b/contrib/idn/idnkit-1.0-src/lib/tests/testsuite.c
new file mode 100644
index 0000000..14b202f
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/testsuite.c
@@ -0,0 +1,578 @@
+#ifndef lint
+static char *rcsid = "$Id";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <idn/result.h>
+#include <idn/ucs4.h>
+#include <testsuite.h>
+
+typedef struct idn_testcase *idn_testcase_t;
+
+struct idn_testcase {
+ char *title;
+ idn_testsuite_testproc_t proc;
+};
+
+struct idn_testsuite {
+ idn_testcase_t testcases;
+ int ntestcases;
+ int testcase_size;
+
+ int npassed;
+ int nfailed;
+ int nskipped;
+ idn_testcase_t current_testcase;
+ idn_teststatus_t current_status;
+
+ idn_testsuite_msgproc_t msgproc;
+ int verbose;
+};
+
+#define INITIAL_TESTCASE_SIZE 16
+#define INITIAL_SETUP_SIZE 4
+#define INITIAL_TEARDOWN_SIZE 4
+
+static void run_internal(idn_testsuite_t ctx, char *titles[]);
+static char *make_hex_string(const char *string);
+static char *make_hex_ucs4string(const unsigned long *string);
+static void put_failure_message(idn_testsuite_t ctx, const char *msg,
+ const char *file, int lineno);
+static void idn_testsuite_msgtostderr(const char *msg);
+
+int
+idn_testsuite_create(idn_testsuite_t *ctxp) {
+ idn_testsuite_t ctx = NULL;
+
+ assert(ctxp != NULL);
+
+ ctx = (idn_testsuite_t) malloc(sizeof(struct idn_testsuite));
+ if (ctx == NULL)
+ goto error;
+
+ ctx->testcases = NULL;
+ ctx->ntestcases = 0;
+ ctx->testcase_size = 0;
+ ctx->npassed = 0;
+ ctx->nfailed = 0;
+ ctx->nskipped = 0;
+ ctx->current_testcase = NULL;
+ ctx->current_status = idn_teststatus_pass;
+ ctx->msgproc = NULL;
+ ctx->verbose = 0;
+
+ ctx->testcases = (idn_testcase_t) malloc(sizeof(struct idn_testcase)
+ * INITIAL_TESTCASE_SIZE);
+ if (ctx->testcases == NULL)
+ goto error;
+ ctx->testcase_size = INITIAL_TESTCASE_SIZE;
+
+ *ctxp = ctx;
+ return (1);
+
+error:
+ if (ctx != NULL)
+ free(ctx->testcases);
+ free(ctx);
+ return (0);
+}
+
+void
+idn_testsuite_destroy(idn_testsuite_t ctx) {
+ int i;
+
+ assert(ctx != NULL);
+
+ for (i = 0; i < ctx->ntestcases; i++)
+ free(ctx->testcases[i].title);
+
+ free(ctx->testcases);
+ free(ctx);
+}
+
+int
+idn_testsuite_addtestcase(idn_testsuite_t ctx, const char *title,
+ idn_testsuite_testproc_t proc) {
+ char *dup_title = NULL;
+ idn_testcase_t new_buffer = NULL;
+ idn_testcase_t new_testcase;
+ int new_size;
+
+ assert(ctx != NULL && title != NULL && proc != NULL);
+
+ dup_title = (char *)malloc(strlen(title) + 1);
+ if (dup_title == NULL)
+ goto error;
+ strcpy(dup_title, title);
+
+ if (ctx->ntestcases == ctx->testcase_size) {
+ new_size = ctx->testcase_size + INITIAL_TESTCASE_SIZE;
+ new_buffer = (idn_testcase_t)
+ realloc(ctx->testcases,
+ sizeof(struct idn_testcase) * new_size);
+ if (new_buffer == NULL)
+ goto error;
+ ctx->testcases = new_buffer;
+ ctx->testcase_size = new_size;
+ }
+
+ new_testcase = ctx->testcases + ctx->ntestcases;
+ new_testcase->title = dup_title;
+ new_testcase->proc = proc;
+ ctx->ntestcases++;
+ return (1);
+
+error:
+ free(dup_title);
+ free(new_buffer);
+ return (0);
+}
+
+int
+idn_testsuite_ntestcases(idn_testsuite_t ctx) {
+ assert(ctx != NULL);
+ return (ctx->ntestcases);
+}
+
+void
+idn_testsuite_setverbose(idn_testsuite_t ctx) {
+ assert(ctx != NULL);
+ ctx->verbose = 1;
+}
+
+void
+idn_testsuite_unsetverbose(idn_testsuite_t ctx) {
+ assert(ctx != NULL);
+ ctx->verbose = 0;
+}
+
+static void
+run_internal(idn_testsuite_t ctx, char *titles[]) {
+ int i, j;
+ int run_testcase;
+ const char *status;
+
+ assert(ctx != NULL);
+
+ ctx->npassed = 0;
+ ctx->nfailed = 0;
+ ctx->nskipped = 0;
+
+ for (i = 0; i < ctx->ntestcases; i++) {
+ ctx->current_testcase = ctx->testcases + i;
+ ctx->current_status = idn_teststatus_pass;
+
+ if (titles == NULL)
+ run_testcase = 1;
+ else {
+ run_testcase = 0;
+ for (j = 0; titles[j] != NULL; j++) {
+ if (strcmp(ctx->current_testcase->title,
+ titles[j]) == 0) {
+ run_testcase = 1;
+ break;
+ }
+ }
+ }
+
+ if (!run_testcase) {
+ ctx->nskipped++;
+ continue;
+ }
+ if (ctx->verbose) {
+ fprintf(stderr, "start testcase %d: %s\n", i + 1,
+ ctx->testcases[i].title);
+ }
+ (ctx->testcases[i].proc)(ctx);
+ status = idn_teststatus_tostring(ctx->current_status);
+ if (ctx->verbose) {
+ fprintf(stderr, "end testcase %d: %s\n", i + 1,
+ status);
+ }
+
+ switch (ctx->current_status) {
+ case idn_teststatus_pass:
+ ctx->npassed++;
+ break;
+ case idn_teststatus_fail:
+ ctx->nfailed++;
+ break;
+ case idn_teststatus_skip:
+ ctx->nskipped++;
+ break;
+ }
+ }
+}
+
+void
+idn_testsuite_runall(idn_testsuite_t ctx) {
+ assert(ctx != NULL);
+ run_internal(ctx, NULL);
+}
+
+void
+idn_testsuite_run(idn_testsuite_t ctx, char *titles[]) {
+ assert(ctx != NULL && titles != NULL);
+ run_internal(ctx, titles);
+}
+
+int
+idn_testsuite_npassed(idn_testsuite_t ctx) {
+ assert(ctx != NULL);
+ return (ctx->npassed);
+}
+
+int
+idn_testsuite_nfailed(idn_testsuite_t ctx) {
+ assert(ctx != NULL);
+ return (ctx->nfailed);
+}
+
+int
+idn_testsuite_nskipped(idn_testsuite_t ctx) {
+ assert(ctx != NULL);
+ return (ctx->nskipped);
+}
+
+idn_teststatus_t
+idn_testsuite_getstatus(idn_testsuite_t ctx) {
+ assert(ctx != NULL);
+ return (ctx->current_status);
+}
+
+void
+idn_testsuite_setstatus(idn_testsuite_t ctx, idn_teststatus_t status) {
+ assert(ctx != NULL);
+ assert(status == idn_teststatus_pass ||
+ status == idn_teststatus_fail ||
+ status == idn_teststatus_skip);
+
+ ctx->current_status = status;
+}
+
+const char *
+idn_teststatus_tostring(idn_teststatus_t status) {
+ assert(status == idn_teststatus_pass ||
+ status == idn_teststatus_fail ||
+ status == idn_teststatus_skip);
+
+ switch (status) {
+ case idn_teststatus_pass:
+ return "pass";
+ break;
+ case idn_teststatus_fail:
+ return "failed";
+ break;
+ case idn_teststatus_skip:
+ return "skipped";
+ break;
+ }
+
+ return "unknown";
+}
+
+void
+idn_testsuite_assert(idn_testsuite_t ctx, const char *msg,
+ const char *file, int lineno) {
+ assert(ctx != NULL && msg != NULL && file != NULL);
+
+ if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
+ return;
+ idn_testsuite_setstatus(ctx, idn_teststatus_fail);
+ put_failure_message(ctx, msg, file, lineno);
+}
+
+void
+idn_testsuite_assertint(idn_testsuite_t ctx, int gotten, int expected,
+ const char *file, int lineno) {
+ char msg[256]; /* large enough */
+
+ assert(ctx != NULL && file != NULL);
+
+ if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
+ return;
+ if (expected == gotten)
+ return;
+ idn_testsuite_setstatus(ctx, idn_teststatus_fail);
+
+ sprintf(msg, "`%d' expected, but got `%d'", expected, gotten);
+ put_failure_message(ctx, msg, file, lineno);
+}
+
+void
+idn_testsuite_assertstring(idn_testsuite_t ctx,
+ const char *gotten, const char *expected,
+ const char *file, int lineno) {
+ char *expected_hex = NULL;
+ char *gotten_hex = NULL;
+ char *msg;
+
+ assert(ctx != NULL && gotten != NULL && expected != NULL &&
+ file != NULL);
+
+ if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
+ return;
+ if (strcmp(expected, gotten) == 0)
+ return;
+ idn_testsuite_setstatus(ctx, idn_teststatus_fail);
+
+ msg = (char *)malloc(strlen(expected) * 4 + strlen(gotten) * 4 + 32);
+ expected_hex = make_hex_string(expected);
+ gotten_hex = make_hex_string(gotten);
+ if (msg == NULL || expected_hex == NULL || gotten_hex == NULL) {
+ msg = "";
+ } else {
+ sprintf(msg, "`%s' expected, but got `%s'",
+ expected_hex, gotten_hex);
+ }
+
+ put_failure_message(ctx, msg, file, lineno);
+
+ free(msg);
+ free(expected_hex);
+ free(gotten_hex);
+}
+
+void
+idn_testsuite_assertptr(idn_testsuite_t ctx, const void *gotten,
+ const void *expected, const char *file, int lineno) {
+ char *msg;
+
+ assert(ctx != NULL && file != NULL);
+
+ if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
+ return;
+ if (expected == gotten)
+ return;
+ idn_testsuite_setstatus(ctx, idn_teststatus_fail);
+
+ if (expected == NULL)
+ msg = "NULL expected, but got non-NULL";
+ else if (gotten == NULL)
+ msg = "non-NULL expected, but got NULL";
+ else
+ msg = "expected pointer != gotten pointer";
+ put_failure_message(ctx, msg, file, lineno);
+}
+
+void
+idn_testsuite_assertptrne(idn_testsuite_t ctx,
+ const void *gotten, const void *unexpected,
+ const char *file, int lineno) {
+ char *msg;
+
+ assert(ctx != NULL && file != NULL);
+
+ if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
+ return;
+ if (unexpected != gotten)
+ return;
+ idn_testsuite_setstatus(ctx, idn_teststatus_fail);
+
+ if (unexpected == NULL)
+ msg = "non-NULL unexpected, but got NULL";
+ else if (gotten == NULL)
+ msg = "non-NULL expected, but got NULL";
+ else
+ msg = "expected pointer == gotten pointer";
+ put_failure_message(ctx, msg, file, lineno);
+}
+
+void
+idn_testsuite_assertresult(idn_testsuite_t ctx,
+ idn_result_t gotten, idn_result_t expected,
+ const char *file, int lineno) {
+ char msg[256]; /* large enough */
+
+ assert(ctx != NULL && file != NULL);
+
+ if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
+ return;
+ if (expected == gotten)
+ return;
+ idn_testsuite_setstatus(ctx, idn_teststatus_fail);
+
+ sprintf(msg, "`%s' expected, but got `%s'",
+ idn_result_tostring(expected), idn_result_tostring(gotten));
+ put_failure_message(ctx, msg, file, lineno);
+}
+
+void
+idn_testsuite_assertucs4string(idn_testsuite_t ctx,
+ const unsigned long *gotten,
+ const unsigned long *expected,
+ const char *file, int lineno) {
+ char *expected_hex = NULL;
+ char *gotten_hex = NULL;
+ char *msg;
+
+ assert(ctx != NULL && gotten != NULL && expected != NULL &&
+ file != NULL);
+
+ if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
+ return;
+ if (idn_ucs4_strcmp(expected, gotten) == 0)
+ return;
+ idn_testsuite_setstatus(ctx, idn_teststatus_fail);
+
+ msg = (char *)malloc(idn_ucs4_strlen(expected) * 8 +
+ idn_ucs4_strlen(gotten) * 8 + 32);
+ expected_hex = make_hex_ucs4string(expected);
+ gotten_hex = make_hex_ucs4string(gotten);
+ if (msg == NULL || expected_hex == NULL || gotten_hex == NULL) {
+ msg = "";
+ } else {
+ sprintf(msg, "`%s' expected, but got `%s'",
+ expected_hex, gotten_hex);
+ }
+
+ put_failure_message(ctx, msg, file, lineno);
+
+ free(msg);
+ free(expected_hex);
+ free(gotten_hex);
+}
+
+static char *
+make_hex_string(const char *string) {
+ static const char hex[] = {"0123456789abcdef"};
+ char *hex_string;
+ const char *src;
+ char *dst;
+
+ hex_string = (char *)malloc((strlen(string)) * 4 + 1);
+ if (hex_string == NULL)
+ return NULL;
+
+ for (src = string, dst = hex_string; *src != '\0'; src++) {
+ if (0x20 <= *src && *src <= 0x7e && *src != '\\') {
+ *dst++ = *src;
+ } else {
+ *dst++ = '\\';
+ *dst++ = 'x';
+ *dst++ = hex[*(const unsigned char *)src >> 4];
+ *dst++ = hex[*src & 0x0f];
+ }
+ }
+ *dst = '\0';
+
+ return hex_string;
+}
+
+#define UCS4_MAX 0x10fffffUL
+
+static char *
+make_hex_ucs4string(const unsigned long *string) {
+ static const char hex[] = {"0123456789abcdef"};
+ char *hex_string;
+ const unsigned long *src;
+ char *dst;
+
+ hex_string = (char *)malloc((idn_ucs4_strlen(string)) * 8 + 1);
+ if (hex_string == NULL)
+ return NULL;
+
+ for (src = string, dst = hex_string; *src != '\0'; src++) {
+ if (0x20 <= *src && *src <= 0x7e && *src != '\\') {
+ *dst++ = *src;
+ } else if (*src <= UCS4_MAX) {
+ *dst++ = '\\';
+ *dst++ = 'u';
+ if (*src >= 0x100000) {
+ *dst++ = hex[(*src >> 20) & 0x0f];
+ }
+ if (*src >= 0x10000) {
+ *dst++ = hex[(*src >> 16) & 0x0f];
+ }
+ *dst++ = hex[(*src >> 12) & 0x0f];
+ *dst++ = hex[(*src >> 8) & 0x0f];
+ *dst++ = hex[(*src >> 4) & 0x0f];
+ *dst++ = hex[*src & 0x0f];
+ } else {
+ *dst++ = '\\';
+ *dst++ = 'u';
+ *dst++ = '?';
+ *dst++ = '?';
+ *dst++ = '?';
+ *dst++ = '?';
+ }
+ }
+ *dst = '\0';
+
+ return hex_string;
+}
+
+static void
+put_failure_message(idn_testsuite_t ctx, const char *msg, const char *file,
+ int lineno) {
+ idn_testsuite_msgproc_t proc;
+ char buffer[256];
+ const char *title;
+
+ proc = (ctx->msgproc == NULL) ?
+ idn_testsuite_msgtostderr : ctx->msgproc;
+ title = (ctx->current_testcase != NULL &&
+ ctx->current_testcase->title != NULL) ?
+ ctx->current_testcase->title : "anonymous";
+
+ sprintf(buffer, "%.100s: In test `%.100s':", file, title);
+ (*proc)(buffer);
+
+ sprintf(buffer, "%.100s:%d: failed (%.100s)", file, lineno, msg);
+ (*proc)(buffer);
+}
+
+
+static void
+idn_testsuite_msgtostderr(const char *msg) {
+ fputs(msg, stderr);
+ fputc('\n', stderr);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/testsuite.h b/contrib/idn/idnkit-1.0-src/lib/tests/testsuite.h
new file mode 100644
index 0000000..a5e4774
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/testsuite.h
@@ -0,0 +1,276 @@
+/* $Id: testsuite.h,v 1.1.1.1 2003/06/04 00:27:03 marka Exp $ */
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_TESTSUITE_H
+#define IDN_TESTSUITE_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Result codes for test case.
+ */
+typedef enum {
+ idn_teststatus_pass,
+ idn_teststatus_fail,
+ idn_teststatus_skip
+} idn_teststatus_t;
+
+/*
+ * Testsuite manager type (opaque).
+ */
+typedef struct idn_testsuite *idn_testsuite_t;
+
+/*
+ * Testcase function type.
+ */
+typedef void (*idn_testsuite_testproc_t)(idn_testsuite_t ctx);
+
+/*
+ * Message handler type.
+ */
+typedef void (*idn_testsuite_msgproc_t)(const char *msg);
+
+/*
+ * Create a testsuite manager context.
+ *
+ * Create an empty context and store it in '*ctxp'.
+ * Return 1 on success. Return 0 if memory is exhausted.
+ */
+extern int
+idn_testsuite_create(idn_testsuite_t *ctxp);
+
+/*
+ * Destory the testsuite manager context.
+ *
+ * Destroy the context created by idn_testsuite_create(), and release
+ * memory allocated to the context.
+ */
+extern void
+idn_testsuite_destroy(idn_testsuite_t ctx);
+
+/*
+ * Add a test case to the `group' test group.
+ * Return 1 on success. Return 0 if memory is exhausted.
+ */
+extern int
+idn_testsuite_addtestcase(idn_testsuite_t ctx, const char *title,
+ idn_testsuite_testproc_t proc);
+
+/*
+ * Return the number of test cases registered in the context.
+ */
+extern int
+idn_testsuite_ntestcases(idn_testsuite_t ctx);
+
+/*
+ * Run test cases registered in the context.
+ */
+extern void
+idn_testsuite_runall(idn_testsuite_t ctx);
+extern void
+idn_testsuite_run(idn_testsuite_t ctx, char *titles[]);
+
+/*
+ * Return the string description of `status'.
+ */
+extern const char *
+idn_teststatus_tostring(idn_teststatus_t status);
+
+/*
+ * Return the number of passed/failed/skipped test cases.
+ */
+extern int
+idn_testsuite_npassed(idn_testsuite_t ctx);
+extern int
+idn_testsuite_nfailed(idn_testsuite_t ctx);
+extern int
+idn_testsuite_nskipped(idn_testsuite_t ctx);
+
+/*
+ * Set/Get status of the test case running currently.
+ *
+ * These functions must be called by test case function.
+ */
+extern idn_teststatus_t
+idn_testsuite_getstatus(idn_testsuite_t ctx);
+extern void
+idn_testsuite_setstatus(idn_testsuite_t ctx, idn_teststatus_t status);
+
+/*
+ * Enable/Disable verbose mode.
+ */
+extern void
+idn_testsuite_setverbose(idn_testsuite_t ctx);
+extern void
+idn_testsuite_unsetverbose(idn_testsuite_t ctx);
+
+/*
+ * Generic assertion with message
+ */
+extern void
+idn_testsuite_assert(idn_testsuite_t ctx, const char *msg,
+ const char *file, int lineno);
+
+#define ASSERT_THRU(msg) \
+ idn_testsuite_assert(ctx__, msg, __FILE__, __LINE__)
+#define ASSERT(msg) \
+ do { \
+ ASSERT_THRU(msg); \
+ if (idn_testsuite_getstatus(ctx__) != idn_teststatus_pass) \
+ goto EXIT__; \
+ } while (0)
+
+/*
+ * Assertion function and macro to compare two `int' values.
+ * The assertion passes if `gotten' is equal to `expected'.
+ */
+extern void
+idn_testsuite_assertint(idn_testsuite_t ctx, int gotten, int expected,
+ const char *file, int lineno);
+
+#define ASSERT_INT(gotten, expected) \
+ do { \
+ idn_testsuite_assertint(ctx__, gotten, expected, __FILE__, __LINE__); \
+ if (idn_testsuite_getstatus(ctx__) != idn_teststatus_pass) \
+ goto EXIT__; \
+ } while (0)
+
+/*
+ * Assertion function and macro to compare two strings.
+ * The assertion passes if `gotten' is lexically equal to `expected'.
+ */
+extern void
+idn_testsuite_assertstring(idn_testsuite_t ctx, const char *gotten,
+ const char *expected, const char *file, int lineno);
+
+#define ASSERT_STRING(gotten, expected) \
+ do { \
+ idn_testsuite_assertstring(ctx__, gotten, expected, __FILE__, __LINE__); \
+ if (idn_testsuite_getstatus(ctx__) != idn_teststatus_pass) \
+ goto EXIT__; \
+ } while (0)
+
+/*
+ * Assertion function and macro to compare two pointers.
+ * The assertion passes if `gotten' is equal to `expected'.
+ */
+extern void
+idn_testsuite_assertptr(idn_testsuite_t ctx, const void *gotten,
+ const void *expected, const char *file, int lineno);
+
+#define ASSERT_PTR(gotten, expected) \
+ do { \
+ idn_testsuite_assertptr(ctx__, gotten, expected, __FILE__, __LINE__); \
+ if (idn_testsuite_getstatus(ctx__) != idn_teststatus_pass) \
+ goto EXIT__; \
+ } while (0)
+
+/*
+ * Assertion function and macro to compare two pointers.
+ * The assertion passes if `gotten' is NOT equal to `expected'.
+ */
+extern void
+idn_testsuite_assertptrne(idn_testsuite_t ctx,
+ const void *gotten, const void *unexpected,
+ const char *file, int lineno);
+
+#define ASSERT_PTR_NE(gotten, unexpected) \
+ do { \
+ idn_testsuite_assertptrne(ctx__, gotten, unexpected, __FILE__, __LINE__); \
+ if (idn_testsuite_getstatus(ctx__) != idn_teststatus_pass) \
+ goto EXIT__; \
+ } while (0)
+
+/*
+ * Assertion function and macro to compare two `idn_result_t' values.
+ * The assertion passes if `gotten' is equal to `expected'.
+ */
+extern void
+idn_testsuite_assertresult(idn_testsuite_t ctx,
+ idn_result_t gotten, idn_result_t expected,
+ const char *file, int lineno);
+
+#define ASSERT_RESULT(gotten, expected) \
+ do { \
+ idn_testsuite_assertresult(ctx__, gotten, expected, __FILE__, __LINE__); \
+ if (idn_testsuite_getstatus(ctx__) != idn_teststatus_pass) \
+ goto EXIT__; \
+ } while (0)
+
+/*
+ * Assertion function and macro to compare two UCS4 strings.
+ * The assertion passes if `gotten' is lexically equal to `expected'.
+ */
+extern void
+idn_testsuite_assertucs4string(idn_testsuite_t ctx,
+ const unsigned long *gotten,
+ const unsigned long *expected,
+ const char *file,
+ int lineno);
+
+#define ASSERT_UCS4STRING_THRU(gotten, expected) \
+ idn_testsuite_assertucs4string(ctx__, gotten, expected, __FILE__, __LINE__)
+#define ASSERT_UCS4STRING(gotten, expected) \
+ do { \
+ ASSERT_UCS4STRING_THRU(gotten, expected); \
+ if (idn_testsuite_getstatus(ctx__) != idn_teststatus_pass) \
+ goto EXIT__; \
+ } while (0)
+
+/*
+ * Shorthands.
+ */
+#define SKIP_TESTCASE \
+ do { \
+ idn_testsuite_setstatus(ctx__, idn_teststatus_skip); \
+ goto EXIT__; \
+ } while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* IDN_TESTSUITE_H */
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/testutil.c b/contrib/idn/idnkit-1.0-src/lib/tests/testutil.c
new file mode 100644
index 0000000..c1872fd
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/testutil.c
@@ -0,0 +1,83 @@
+#ifndef lint
+static char *rcsid = "$Id: testutil.c,v 1.1.1.1 2003/06/04 00:27:03 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "testutil.h"
+
+int
+create_conf_file(const char *filename, unsigned int flags, ...) {
+ FILE *file;
+ va_list ap;
+ const char *arg;
+ int arg_index;
+
+ file = fopen(filename, "w");
+ if (file == NULL) {
+ fprintf(stderr, "failed to create config file `%s'\n",
+ filename);
+ return 0;
+ }
+
+ arg_index = 0;
+ va_start(ap, flags);
+ for (;;) {
+ arg = va_arg(ap, const char *);
+ if (arg == NULL)
+ break;
+ if (arg_index++ > 0)
+ fputc('\n', file);
+ fputs(arg, file);
+ }
+ if (!(flags & CONF_NO_EOF_NEWLINE) && arg_index > 0)
+ fputc('\n', file);
+
+ fclose(file);
+ return 1;
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/testutil.h b/contrib/idn/idnkit-1.0-src/lib/tests/testutil.h
new file mode 100644
index 0000000..0e6405d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/testutil.h
@@ -0,0 +1,71 @@
+/* $Id: testutil.h,v 1.1.1.1 2003/06/04 00:27:03 marka Exp $ */
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_TESTUTIL_H
+#define IDN_TESTUTIL_H 1
+
+/*
+ * Option flags for create_conf_file().
+ *
+ * CONF_NO_EOF_NEWLINE -- Don't put newline character
+ * at the end of file.
+ */
+#define CONF_NO_EOF_NEWLINE 0x0001
+
+/*
+ * Create a configuration file.
+ *
+ * Write strings specified as variable length arguments (`...') to
+ * `filename'. Note that the arguments must be terminated with `NULL'.
+ *
+ * In the created config file, each string in the variable length
+ * arguments becomes a line. In other words, newline characters are
+ * added automatically.
+ *
+ * This function returns 1 upon success, 0 otherwise.
+ */
+int
+create_conf_file(const char *filename, unsigned int flags, ...);
+
+#endif /* IDN_TESTUTIL_H */
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/testygen b/contrib/idn/idnkit-1.0-src/lib/tests/testygen
new file mode 100755
index 0000000..5d2f9ca
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/testygen
@@ -0,0 +1,557 @@
+#! /usr/bin/perl -w
+#
+# Copyright (c) 2002 Japan Network Information Center.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+use FileHandle;
+use Getopt::Std;
+
+#
+# Parsing status.
+#
+my $STATUS_HEADER = 0;
+my $STATUS_HEADER_COMMENT = 1;
+my $STATUS_SEPARATOR = 2;
+my $STATUS_BODY = 3;
+my $STATUS_GLOBAL = 4;
+my $STATUS_GLOBAL_COMMENT = 5;
+my $STATUS_PREAMBLE = 6;
+
+my $LINENO_MARK = "<LINENO>";
+
+#
+# Create a new testsuite context.
+#
+sub new_testsuite {
+ return {'ntests' => 0,
+ 'setups' => {},
+ 'teardowns' => {},
+ 'tests' => [],
+ 'titles' => [],
+ 'preambles' => ''};
+}
+
+#
+# Read `$file' and put the result into `$testsutie'.
+#
+sub parse_file {
+ my ($testsuite, $file, $lineinfo) = @_;
+ my $parser = {'type' => '',
+ 'group' => '',
+ 'title' => '',
+ 'status' => $STATUS_PREAMBLE,
+ 'error' => '',
+ 'file' => $file,
+ 'lineno' => 0,
+ 'lineinfo' => $lineinfo};
+
+ my $handle = FileHandle->new($file, 'r');
+ if (!defined($handle)) {
+ die "failed to open the file, $!: $file\n";
+ }
+
+ my ($result, $line);
+ for (;;) {
+ $line = $handle->getline();
+ last if (!defined($line));
+
+ chomp($line);
+ $line .= "\n";
+ $parser->{lineno}++;
+ $result = parse_line($testsuite, $parser, $line);
+ if (!$result) {
+ die sprintf("%s, at line %d\n",
+ $parser->{error}, $parser->{lineno});
+ }
+ }
+
+ if ($parser->{status} != $STATUS_GLOBAL) {
+ die "unexpected EOF, at line $.\n";
+ }
+
+ $handle->close();
+}
+
+sub parse_line {
+ my ($testsuite, $parser, $line) = @_;
+ my $result = 1;
+
+ if ($parser->{status} == $STATUS_HEADER) {
+ if ($line =~ /^\/\/--/) {
+ $parser->{status} = $STATUS_HEADER_COMMENT;
+ } elsif ($line =~ /^\/\//) {
+ $result = parse_header($testsuite, $parser, $line);
+ } elsif ($line =~ /^\s*$/) {
+ $parser->{status} = $STATUS_SEPARATOR;
+ $result = parse_endheader($testsuite, $parser, $line);
+ } elsif ($line =~ /^\{\s*$/) {
+ $parser->{status} = $STATUS_BODY;
+ $result = parse_endheader($testsuite, $parser, $line)
+ && parse_startbody($testsuite, $parser, $line);
+ } else {
+ $parser->{error} = 'syntax error';
+ $result = 0;
+ }
+
+ } elsif ($parser->{status} == $STATUS_HEADER_COMMENT) {
+ if ($line =~ /^\/\//) {
+ # nothing to be done.
+ } elsif ($line =~ /^\s*$/) {
+ $parser->{status} = $STATUS_SEPARATOR;
+ $result = parse_endheader($testsuite, $parser, $line);
+ } elsif ($line =~ /^\{\s*$/) {
+ $parser->{status} = $STATUS_BODY;
+ $result = parse_endheader($testsuite, $parser, $line)
+ && parse_startbody($testsuite, $parser, $line);
+ } else {
+ $parser->{error} = 'syntax error';
+ $result = 0;
+ }
+
+ } elsif ($parser->{status} == $STATUS_SEPARATOR) {
+ if ($line =~ /^\s*$/) {
+ # nothing to be done.
+ } elsif ($line =~ /^\{\s*$/) {
+ $parser->{status} = $STATUS_BODY;
+ $result = parse_startbody($testsuite, $parser, $line);
+ } else {
+ $parser->{error} = 'syntax error';
+ $result = 0;
+ }
+
+ } elsif ($parser->{status} == $STATUS_BODY) {
+ if ($line =~ /^\}\s*$/) {
+ $parser->{status} = $STATUS_GLOBAL;
+ $result = parse_endbody($testsuite, $parser, $line);
+ } else {
+ $result = parse_body($testsuite, $parser, $line);
+ }
+
+ } elsif ($parser->{status} == $STATUS_GLOBAL) {
+ if ($line =~ /^\/\/\#/) {
+ $parser->{status} = $STATUS_HEADER;
+ $result = parse_startheader($testsuite, $parser, $line);
+ } elsif ($line =~ /^\/\/--/) {
+ $parser->{status} = $STATUS_GLOBAL_COMMENT;
+ } elsif ($line =~ /^\s*$/) {
+ # nothing to be done.
+ } else {
+ $parser->{error} = 'syntax error';
+ $result = 0;
+ }
+
+ } elsif ($parser->{status} == $STATUS_GLOBAL_COMMENT) {
+ if ($line =~ /^\/\//) {
+ # nothing to be done.
+ } elsif ($line =~ /^\s*$/) {
+ $parser->{status} = $STATUS_GLOBAL;
+ } else {
+ $parser->{error} = 'syntax error';
+ $result = 0;
+ }
+
+ } elsif ($parser->{status} == $STATUS_PREAMBLE) {
+ if ($line =~ /^\/\/\#/) {
+ $parser->{status} = $STATUS_HEADER;
+ $result = parse_startheader($testsuite, $parser, $line);
+ } elsif ($line =~ /^\/\/--/) {
+ $parser->{status} = $STATUS_GLOBAL_COMMENT;
+ } else {
+ $result = parse_preamble($testsuite, $parser, $line);
+ }
+
+ } else {
+ $parser->{error} = 'syntax error';
+ $result = 0;
+ }
+
+ return $result;
+}
+
+sub parse_startheader {
+ my ($testsuite, $parser, $line) = @_;
+
+ if ($line =~ /^\/\/\#\s*(SETUP|TEARDOWN|TESTCASE)\s*$/) {
+ $parser->{type} = $1;
+ $parser->{group} = '';
+ $parser->{title} = '';
+ } else {
+ $parser->{error} = 'invalid test-header format';
+ return 0;
+ }
+
+
+ return 1;
+}
+
+sub parse_header {
+ my ($testsuite, $parser, $line) = @_;
+
+ my $field = $line;
+ $field =~ s/^\/\/\s*//;
+ $field =~ s/^(\S+):\s*/$1:/;
+ $field =~ s/\s+$//;
+
+ return 1 if ($field eq '');
+
+ if ($field =~ /^group:(.*)$/) {
+ my $group = $1;
+
+ if ($parser->{group} ne '') {
+ $parser->{error} = "group defined twice in a header";
+ return 0;
+ }
+ if ($parser->{type} eq 'SETUP') {
+ if ($group !~ /^[0-9A-Za-z_\-]+$/) {
+ $parser->{error} = "invalid group name";
+ return 0;
+ }
+ if (defined($testsuite->{setups}->{$group})) {
+ $parser->{error} = sprintf("SETUP \`%s' redefined", $group);
+ return 0;
+ }
+ } elsif ($parser->{type} eq 'TEARDOWN') {
+ if ($group !~ /^[0-9A-Za-z_\-]+$/) {
+ $parser->{error} = "invalid group name";
+ return 0;
+ }
+ if (defined($testsuite->{teardowns}->{$group})) {
+ $parser->{error} = sprintf("TEARDOWN \`%s' redefined", $group);
+ return 0;
+ }
+ } else {
+ foreach my $i (split(/[ \t]+/, $group)) {
+ if ($i !~ /^[0-9A-Za-z_\-]+$/) {
+ $parser->{error} = "invalid group name \`$i'";
+ return 0;
+ }
+ if (!defined($testsuite->{setups}->{$i})
+ && !defined($testsuite->{teardowns}->{$i})) {
+ $parser->{error} = sprintf("group \'%s' not defined", $i);
+ return 0;
+ }
+ }
+ }
+ $parser->{group} = $group;
+
+ } elsif ($field =~ /^title:(.*)$/) {
+ my $title = $1;
+
+ if ($parser->{title} ne '') {
+ $parser->{error} = "title defined twice in a header";
+ return 0;
+ }
+ if ($title =~ /[\x00-\x1f\x7f-\xff\"\\]/ || $title eq '') {
+ $parser->{error} = "invalid title";
+ return 0;
+ }
+ if ($parser->{type} ne 'TESTCASE') {
+ $parser->{error} = sprintf("title for %s is not permitted",
+ $parser->{type});
+ return 0;
+ }
+ $parser->{title} = $title;
+
+ } else {
+ $parser->{error} = "invalid test-header field";
+ return 0;
+ }
+
+ return 1;
+}
+
+sub parse_endheader {
+ my ($testsuite, $parser, $line) = @_;
+
+ if ($parser->{type} ne 'TESTCASE' && $parser->{group} eq '') {
+ $parser->{error} = "missing \`group' in the header";
+ return 0;
+ }
+
+ if ($parser->{type} eq 'TESTCASE' && $parser->{title} eq '') {
+ $parser->{error} = "missing \`title' in the header";
+ return 0;
+ }
+
+ return 1;
+}
+
+sub parse_startbody {
+ my ($testsuite, $parser, $line) = @_;
+ my $group = $parser->{group};
+
+ if ($parser->{type} eq 'SETUP') {
+ if ($parser->{lineinfo}) {
+ $testsuite->{setups}->{$group} =
+ generate_line_info($parser->{lineno} + 1, $parser->{file});
+ }
+ } elsif ($parser->{type} eq 'TEARDOWN') {
+ if ($parser->{lineinfo}) {
+ $testsuite->{teardowns}->{$group} =
+ generate_line_info($parser->{lineno} + 1, $parser->{file});
+ }
+ } else {
+ $testsuite->{ntests}++;
+ push(@{$testsuite->{tests}}, '');
+ push(@{$testsuite->{titles}}, $parser->{title});
+
+ $testsuite->{tests}->[-1] .= "\n";
+ $testsuite->{tests}->[-1] .= "$LINENO_MARK\n";
+ $testsuite->{tests}->[-1] .=
+ sprintf("static void\ntestcase\%d(idn_testsuite_t ctx__) {\n",
+ $testsuite->{ntests});
+
+ my (@group_names) = split(/[ \t]+/, $group);
+ for (my $i = 0; $i < @group_names; $i++) {
+ if (defined($testsuite->{setups}->{$group_names[$i]})) {
+ $testsuite->{tests}->[-1] .= "\t\{\n";
+ $testsuite->{tests}->[-1] .= "#undef EXIT__\n";
+ $testsuite->{tests}->[-1] .= "#define EXIT__ exit${i}__\n";
+ $testsuite->{tests}->[-1] .=
+ $testsuite->{setups}->{$group_names[$i]};
+ }
+ }
+ $testsuite->{tests}->[-1] .= "$LINENO_MARK\n";
+ $testsuite->{tests}->[-1] .= "\t\{\n";
+ $testsuite->{tests}->[-1] .= "#undef EXIT__\n";
+ $testsuite->{tests}->[-1] .= "#define EXIT__ exit__\n";
+ if ($parser->{lineinfo}) {
+ $testsuite->{tests}->[-1] .=
+ generate_line_info($parser->{lineno} + 1, $parser->{file});
+ }
+ }
+
+ return 1;
+}
+
+sub parse_body {
+ my ($testsuite, $parser, $line) = @_;
+ my ($group) = $parser->{group};
+
+ if ($parser->{type} eq 'SETUP') {
+ $testsuite->{setups}->{$group} .= $line;
+ } elsif ($parser->{type} eq 'TEARDOWN') {
+ $testsuite->{teardowns}->{$group} .= $line;
+ } else {
+ $testsuite->{tests}->[-1] .= $line;
+ }
+
+ return 1;
+}
+
+sub parse_endbody {
+ my ($testsuite, $parser, $line) = @_;
+ my ($group) = $parser->{group};
+
+ if ($parser->{type} eq 'TESTCASE') {
+ $testsuite->{tests}->[-1] .= "$LINENO_MARK\n";
+ $testsuite->{tests}->[-1] .= "\t\}\n";
+ $testsuite->{tests}->[-1] .= " exit__:\n";
+ $testsuite->{tests}->[-1] .= "\t;\n";
+
+ my (@group_names) = split(/[ \t]+/, $group);
+ for (my $i = @group_names - 1; $i >= 0; $i--) {
+ $testsuite->{tests}->[-1] .= " exit${i}__:\n";
+ $testsuite->{tests}->[-1] .= "\t;\n";
+ if (defined($testsuite->{teardowns}->{$group_names[$i]})) {
+ $testsuite->{tests}->[-1] .=
+ $testsuite->{teardowns}->{$group_names[$i]};
+ }
+ $testsuite->{tests}->[-1] .= "$LINENO_MARK\n";
+ $testsuite->{tests}->[-1] .= "\t\}\n";
+ }
+
+ $testsuite->{tests}->[-1] .= "}\n";
+ }
+
+ return 1;
+}
+
+sub parse_preamble {
+ my ($testsuite, $parser, $line) = @_;
+
+ if ($parser->{lineinfo} && $parser->{lineno} == 1) {
+ $testsuite->{preambles} .= generate_line_info(1, $parser->{file});
+ }
+ $testsuite->{preambles} .= $line;
+ return 1;
+}
+
+sub generate_line_info {
+ my ($lineno, $file) = @_;
+ return "#line $lineno \"$file\"\n";
+}
+
+#
+# Output `$testsuite' as source codes of C.
+#
+sub output_tests {
+ my ($testsuite, $file, $lineinfo) = @_;
+
+ my $generator = {
+ 'file' => $file,
+ 'lineno' => 0
+ };
+
+ my $handle = FileHandle->new($file, 'w');
+ if (!defined($handle)) {
+ die "failed to open the file, $!: $file\n";
+ }
+
+ my $preamble_header =
+ "/* This file is automatically generated by testygen. */\n\n"
+ . "#define TESTYGEN 1\n"
+ . "\n";
+ output_lines($preamble_header, $generator, $handle, $lineinfo);
+
+ output_lines($testsuite->{preambles}, $generator, $handle, $lineinfo);
+
+ my $preamble_footer =
+ "\n"
+ . "$LINENO_MARK\n"
+ . "#include \"testsuite.h\"\n"
+ . "\n";
+ output_lines($preamble_footer, $generator, $handle, $lineinfo);
+
+
+ for (my $i = 0; $i < $testsuite->{ntests}; $i++) {
+ output_lines($testsuite->{tests}->[$i], $generator, $handle,
+ $lineinfo);
+ }
+
+ my $main_header =
+ "\n"
+ . "$LINENO_MARK\n"
+ . "int\n"
+ . "main(int argc, char *argv[]) {\n"
+ . "\tidn_testsuite_t ctx;\n"
+ . "\tconst char *title;\n"
+ . "\n"
+ . "\tidn_testsuite_create(&ctx);\n";
+ output_lines($main_header, $generator, $handle, $lineinfo);
+
+ for (my $i = 0; $i < $testsuite->{ntests}; $i++) {
+ my $title = $testsuite->{titles}->[$i];
+ my $proc = sprintf("testcase%d", $i + 1);
+ output_lines("\tidn_testsuite_addtestcase(ctx, \"$title\", $proc);\n",
+ $generator, $handle, $lineinfo);
+ }
+
+ my $main_footer =
+ "\n"
+ . "\tif (argc > 1 && strcmp(argv[1], \"-v\") == 0) {\n"
+ . "\t idn_testsuite_setverbose(ctx);\n"
+ . "\t argc--;\n"
+ . "\t argv++;\n"
+ . "\t}\n"
+ . "\tif (argc == 1)\n"
+ . "\t idn_testsuite_runall(ctx);\n"
+ . "\telse\n"
+ . "\t idn_testsuite_run(ctx, argv + 1);\n"
+ . "\n"
+ . "\tprintf(\"passed=%d, failed=%d, total=%d\\n\",\n"
+ . "\t idn_testsuite_npassed(ctx),\n"
+ . "\t idn_testsuite_nfailed(ctx),\n"
+ . "\t idn_testsuite_ntestcases(ctx) - idn_testsuite_nskipped(ctx));\n"
+ . "\n"
+ . "\tidn_testsuite_destroy(ctx);\n"
+ . "\treturn (0);\n"
+ . "\}\n";
+ output_lines($main_footer, $generator, $handle, $lineinfo);
+
+ $handle->close();
+}
+
+sub output_lines {
+ my ($lines, $generator, $handle, $lineinfo) = @_;
+ my ($line);
+
+ chomp($lines);
+ $lines .= "\n";
+
+ while ($lines ne '') {
+ $lines =~ s/^([^\n]*)\n//;
+ $line = $1;
+ $generator->{lineno}++;
+ if ($line eq $LINENO_MARK) {
+ if ($lineinfo) {
+ $handle->printf("#line %d \"%s\"\n", $generator->{lineno} + 1,
+ $generator->{file});
+ }
+ } else {
+ $handle->print("$line\n");
+ }
+ }
+}
+
+sub output_usage {
+ warn "$0: [-o output-file] input-file\n";
+}
+
+#
+# main.
+#
+my (%options);
+
+if (!getopts('Lo:', \%options)) {
+ output_usage;
+ exit(1);
+}
+if (@ARGV != 1) {
+ output_usage;
+ exit(1);
+}
+
+my ($in_file) = $ARGV[0];
+my ($out_file);
+if (!defined($options{o})) {
+ $out_file = $in_file;
+ $out_file .= '\.tsy' if ($out_file !~ /\.tsy$/);
+ $out_file =~ s/\.tsy$/\.c/;
+} else {
+ $out_file = $options{o};
+}
+
+my $testsuite = new_testsuite();
+parse_file($testsuite, $in_file, !$options{L});
+output_tests($testsuite, $out_file, !$options{L});
+
+exit(0);
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/ucs4.tsy b/contrib/idn/idnkit-1.0-src/lib/tests/ucs4.tsy
new file mode 100644
index 0000000..205edae
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/ucs4.tsy
@@ -0,0 +1,257 @@
+#ifndef lint
+static char *rcsid = "$Id: ucs4.tsy,v 1.1.1.1 2003/06/04 00:27:04 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <idn/ucs4.h>
+#include <idn/log.h>
+#include "testutil.h"
+
+/*
+ * Sample UTF8 and UCS4 strings.
+ */
+static const char *utf8_string =
+ "\x7f" /* 0x0000007f */
+ "\xdf\xbf" /* 0x000007ff */
+ "\xef\xbf\xbf" /* 0x0000ffff */
+ "\xf7\xbf\xbf\xbf" /* 0x001fffff */
+ "\xfb\xbf\xbf\xbf\xbf" /* 0x03ffffff */
+ "\xfd\xbf\xbf\xbf\xbf\xbf"; /* 0x7fffffff */
+
+static const unsigned long ucs4_string[] = {
+ 0x0000007f,
+ 0x000007ff,
+ 0x0000ffff,
+ 0x001fffff,
+ 0x03ffffff,
+ 0x7fffffff,
+ 0x00000000
+};
+
+//--------------------------------------------------------------------
+// Setups and Teardowns.
+//--------------------------------------------------------------------
+
+//# SETUP
+// group: utf8-init
+{
+ unsigned long to[256];
+ size_t tolen = 256;
+ idn_result_t r;
+}
+
+//# SETUP
+// group: ucs4-init
+{
+ char to[256];
+ size_t tolen = 256;
+ idn_result_t r;
+}
+
+//# SETUP
+// group: quiet
+{
+ int saved_log_level;
+
+ saved_log_level = idn_log_getlevel();
+ idn_log_setlevel(idn_log_level_fatal);
+}
+
+//# TEARDOWN
+// group: quiet
+{
+ idn_log_setlevel(saved_log_level);
+}
+
+//--------------------------------------------------------------------
+// Testcases.
+//--------------------------------------------------------------------
+
+//# TESTCASE
+// title: call utf8toucs4()
+// group: utf8-init
+{
+ r = idn_ucs4_utf8toucs4(utf8_string, to, tolen);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, ucs4_string);
+}
+
+//# TESTCASE
+// title: call ucs4toutf8()
+// group: ucs4-init
+{
+ r = idn_ucs4_ucs4toutf8(ucs4_string, to, tolen);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, utf8_string);
+}
+
+//# TESTCASE
+// title: call utf8toucs4() with empty from
+// group: utf8-init
+{
+ static unsigned long empty_ucs4_string[] = {0};
+
+ r = idn_ucs4_utf8toucs4("", to, tolen);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, empty_ucs4_string);
+}
+
+//# TESTCASE
+// title: call ucs4toutf8() with empty from
+// group: ucs4-init
+{
+ static unsigned long empty_ucs4_string[] = {0};
+
+ r = idn_ucs4_ucs4toutf8(empty_ucs4_string, to, tolen);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, "");
+}
+
+//# TESTCASE
+// title: call utf8toucs4() with broken string
+// group: utf8-init quiet
+{
+ /* "\xfe" as the 1st byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xfe\xbf\xbf\xbf\xbf\xbf\xbf", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* "\x7f" as the 2nd byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xdf\x7f", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* "\xc0" as the 2nd byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xdf\xc0", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* "\x7f" as the 3rd byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xef\xbf\x7f", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* "\xc0" as the 3rd byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xef\xbf\xc0", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* "\x7f" as the 4th byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xf7\xbf\xbf\x7f", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* "\xc0" as the 4th byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xf7\xbf\xbf\xc0", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* "\x7f" as the 5th byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xfb\xbf\xbf\xbf\x7f", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* "\xc0" as the 5th byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xfb\xbf\xbf\xbf\xc0", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* "\x7f" as the 6th byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xfd\xbf\xbf\xbf\xbf\x7f", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* "\xc0" as the 6th byte is out of range. */
+ r = idn_ucs4_utf8toucs4("\xfd\xbf\xbf\xbf\xbf\xc0", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* `from' contains surrogate pair */
+ r = idn_ucs4_utf8toucs4("\xed\xa0\x80\xed\xbf\xbf", to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+}
+
+//# TESTCASE
+// title: call ucs4toutf8() with broken string
+// group: ucs4-init quiet
+{
+ static unsigned long invalid_ucs4_string0[] = {0x80000000, 0};
+ static unsigned long invalid_ucs4_string1[] = {0xd800, 0xdfff, 0};
+
+ /* 0x80000000 is out of range */
+ r = idn_ucs4_ucs4toutf8(invalid_ucs4_string0, to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+
+ /* `from' contains surrogate pair */
+ r = idn_ucs4_ucs4toutf8(invalid_ucs4_string1, to, tolen);
+ ASSERT_RESULT(r, idn_invalid_encoding);
+}
+
+//# TESTCASE
+// title: buffer overrun test for utf8toucs4()
+// group: utf8-init
+{
+ r = idn_ucs4_utf8toucs4(utf8_string, to,
+ idn_ucs4_strlen(ucs4_string) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_UCS4STRING(to, ucs4_string);
+
+ r = idn_ucs4_utf8toucs4(utf8_string, to,
+ idn_ucs4_strlen(ucs4_string));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_ucs4_utf8toucs4(utf8_string, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
+//# TESTCASE
+// title: buffer overrun test for ucs4toutf8()
+// group: ucs4-init
+{
+ r = idn_ucs4_ucs4toutf8(ucs4_string, to, strlen(utf8_string) + 1);
+ ASSERT_RESULT(r, idn_success);
+ ASSERT_STRING(to, utf8_string);
+
+ r = idn_ucs4_ucs4toutf8(ucs4_string, to, strlen(utf8_string));
+ ASSERT_RESULT(r, idn_buffer_overflow);
+
+ r = idn_ucs4_ucs4toutf8(ucs4_string, to, 0);
+ ASSERT_RESULT(r, idn_buffer_overflow);
+}
+
diff --git a/contrib/idn/idnkit-1.0-src/lib/tests/utffilter b/contrib/idn/idnkit-1.0-src/lib/tests/utffilter
new file mode 100755
index 0000000..cebd4dc
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/tests/utffilter
@@ -0,0 +1,82 @@
+#! /usr/bin/perl -wp
+#
+# Copyright (c) 2002 Japan Network Information Center.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+
+sub to_utf8 ($) {
+ my ($utf32) = hex($_[0]);
+ my ($mask, $length);
+
+ if ($utf32 < 0x80) {
+ $mask = 0;
+ $length = 1;
+ } elsif ($utf32 < 0x800) {
+ $mask = 0xc0;
+ $length = 2;
+ } elsif ($utf32 < 0x10000) {
+ $mask = 0xe0;
+ $length = 3;
+ } elsif ($utf32 < 0x200000) {
+ $mask = 0xf0;
+ $length = 4;
+ } elsif ($utf32 < 0x4000000) {
+ $mask = 0xf8;
+ $length = 5;
+ } elsif ($utf32 < 0x80000000) {
+ $mask = 0xfc;
+ $length = 6;
+ } else {
+ return '';
+ }
+
+ my ($result, $offset);
+ $offset = 6 * ($length - 1);
+ $result .= sprintf('\\x%02x', ($utf32 >> $offset) | $mask);
+ while ($offset > 0) {
+ $offset -= 6;
+ $result .= sprintf('\\x%02x', (($utf32 >> $offset) & 0x3f) | 0x80);
+ }
+
+ return $result;
+}
+
+s/<U\+([0-9A-Fa-f]+)>/&to_utf8($1)/eg;
diff --git a/contrib/idn/idnkit-1.0-src/lib/ucs4.c b/contrib/idn/idnkit-1.0-src/lib/ucs4.c
new file mode 100644
index 0000000..a5f4e8c
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/ucs4.c
@@ -0,0 +1,461 @@
+#ifndef lint
+static char *rcsid = "$Id: ucs4.c,v 1.1.1.1 2003/06/04 00:26:14 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/assert.h>
+#include <idn/result.h>
+#include <idn/logmacro.h>
+#include <idn/util.h>
+#include <idn/ucs4.h>
+#include <idn/debug.h>
+
+/*
+ * Unicode surrogate pair.
+ */
+#define IS_SURROGATE_HIGH(v) (0xd800 <= (v) && (v) <= 0xdbff)
+#define IS_SURROGATE_LOW(v) (0xdc00 <= (v) && (v) <= 0xdfff)
+#define SURROGATE_HIGH(v) (SURROGATE_H_OFF + (((v) - 0x10000) >> 10))
+#define SURROGATE_LOW(v) (SURROGATE_L_OFF + ((v) & 0x3ff))
+#define SURROGATE_BASE 0x10000
+#define SURROGATE_H_OFF 0xd800
+#define SURROGATE_L_OFF 0xdc00
+#define COMBINE_SURROGATE(h, l) \
+ (SURROGATE_BASE + (((h)-SURROGATE_H_OFF)<<10) + ((l)-SURROGATE_L_OFF))
+
+/*
+ * ASCII ctype macros.
+ * Note that these macros evaluate the argument multiple times. Be careful.
+ */
+#define ASCII_TOUPPER(c) \
+ (('a' <= (c) && (c) <= 'z') ? ((c) - 'a' + 'A') : (c))
+#define ASCII_TOLOWER(c) \
+ (('A' <= (c) && (c) <= 'Z') ? ((c) - 'A' + 'a') : (c))
+
+idn_result_t
+idn_ucs4_ucs4toutf16(const unsigned long *ucs4, unsigned short *utf16,
+ size_t tolen) {
+ unsigned short *utf16p = utf16;
+ unsigned long v;
+ idn_result_t r;
+
+ TRACE(("idn_ucs4_ucs4toutf16(ucs4=\"%s\", tolen=%d)\n",
+ idn__debug_ucs4xstring(ucs4, 50), (int)tolen));
+
+ while (*ucs4 != '\0') {
+ v = *ucs4++;
+
+ if (IS_SURROGATE_LOW(v) || IS_SURROGATE_HIGH(v)) {
+ WARNING(("idn_ucs4_ucs4toutf16: UCS4 string contains "
+ "surrogate pair\n"));
+ r = idn_invalid_encoding;
+ goto ret;
+ } else if (v > 0xffff) {
+ /* Convert to surrogate pair */
+ if (v >= 0x110000) {
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+ if (tolen < 2) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *utf16p++ = SURROGATE_HIGH(v);
+ *utf16p++ = SURROGATE_LOW(v);
+ tolen -= 2;
+ } else {
+ if (tolen < 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *utf16p++ = v;
+ tolen--;
+ }
+ }
+
+ if (tolen < 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *utf16p = '\0';
+
+ r = idn_success;
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_ucs4_ucs4toutf16(): success (utf16=\"%s\")\n",
+ idn__debug_utf16xstring(utf16, 50)));
+ } else {
+ TRACE(("idn_ucs4_ucs4toutf16(): %s\n",
+ idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+idn_result_t
+idn_ucs4_utf16toucs4(const unsigned short *utf16, unsigned long *ucs4,
+ size_t tolen) {
+ unsigned long *ucs4p = ucs4;
+ unsigned short v0, v1;
+ idn_result_t r;
+
+ TRACE(("idn_ucs4_utf16toucs4(utf16=\"%s\", tolen=%d)\n",
+ idn__debug_utf16xstring(utf16, 50), (int)tolen));
+
+ while (*utf16 != '\0') {
+ v0 = *utf16;
+
+ if (tolen < 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+
+ if (IS_SURROGATE_HIGH(v0)) {
+ v1 = *(utf16 + 1);
+ if (!IS_SURROGATE_LOW(v1)) {
+ WARNING(("idn_ucs4_utf16toucs4: "
+ "corrupted surrogate pair\n"));
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+ *ucs4p++ = COMBINE_SURROGATE(v0, v1);
+ tolen--;
+ utf16 += 2;
+
+ } else {
+ *ucs4p++ = v0;
+ tolen--;
+ utf16++;
+
+ }
+ }
+
+ if (tolen < 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *ucs4p = '\0';
+
+ r = idn_success;
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_ucs4_utf16toucs4(): success (ucs4=\"%s\")\n",
+ idn__debug_ucs4xstring(ucs4, 50)));
+ } else {
+ TRACE(("idn_ucs4_utf16toucs4(): %s\n",
+ idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+idn_result_t
+idn_ucs4_utf8toucs4(const char *utf8, unsigned long *ucs4, size_t tolen) {
+ const unsigned char *utf8p = (const unsigned char *)utf8;
+ unsigned long *ucs4p = ucs4;
+ unsigned long v, min;
+ unsigned char c;
+ int width;
+ int i;
+ idn_result_t r;
+
+ TRACE(("idn_ucs4_utf8toucs4(utf8=\"%s\", tolen=%d)\n",
+ idn__debug_xstring(utf8, 50), (int)tolen));
+
+ while(*utf8p != '\0') {
+ c = *utf8p++;
+ if (c < 0x80) {
+ v = c;
+ min = 0;
+ width = 1;
+ } else if (c < 0xc0) {
+ WARNING(("idn_ucs4_utf8toucs4: invalid character\n"));
+ r = idn_invalid_encoding;
+ goto ret;
+ } else if (c < 0xe0) {
+ v = c & 0x1f;
+ min = 0x80;
+ width = 2;
+ } else if (c < 0xf0) {
+ v = c & 0x0f;
+ min = 0x800;
+ width = 3;
+ } else if (c < 0xf8) {
+ v = c & 0x07;
+ min = 0x10000;
+ width = 4;
+ } else if (c < 0xfc) {
+ v = c & 0x03;
+ min = 0x200000;
+ width = 5;
+ } else if (c < 0xfe) {
+ v = c & 0x01;
+ min = 0x4000000;
+ width = 6;
+ } else {
+ WARNING(("idn_ucs4_utf8toucs4: invalid character\n"));
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+
+ for (i = width - 1; i > 0; i--) {
+ c = *utf8p++;
+ if (c < 0x80 || 0xc0 <= c) {
+ WARNING(("idn_ucs4_utf8toucs4: "
+ "invalid character\n"));
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+ v = (v << 6) | (c & 0x3f);
+ }
+
+ if (v < min) {
+ WARNING(("idn_ucs4_utf8toucs4: invalid character\n"));
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+ if (IS_SURROGATE_LOW(v) || IS_SURROGATE_HIGH(v)) {
+ WARNING(("idn_ucs4_utf8toucs4: UTF-8 string contains "
+ "surrogate pair\n"));
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+ if (tolen < 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ tolen--;
+ *ucs4p++ = v;
+ }
+
+ if (tolen < 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *ucs4p = '\0';
+
+ r = idn_success;
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_ucs4_utf8toucs4(): success (ucs4=\"%s\")\n",
+ idn__debug_ucs4xstring(ucs4, 50)));
+ } else {
+ TRACE(("idn_ucs4_utf8toucs4(): %s\n",
+ idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+idn_result_t
+idn_ucs4_ucs4toutf8(const unsigned long *ucs4, char *utf8, size_t tolen) {
+ unsigned char *utf8p = (unsigned char *)utf8;
+ unsigned long v;
+ int width;
+ int mask;
+ int offset;
+ idn_result_t r;
+
+ TRACE(("idn_ucs4_ucs4toutf8(ucs4=\"%s\", tolen=%d)\n",
+ idn__debug_ucs4xstring(ucs4, 50), (int)tolen));
+
+ while (*ucs4 != '\0') {
+ v = *ucs4++;
+ if (IS_SURROGATE_LOW(v) || IS_SURROGATE_HIGH(v)) {
+ WARNING(("idn_ucs4_ucs4toutf8: UCS4 string contains "
+ "surrogate pair\n"));
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+ if (v < 0x80) {
+ mask = 0;
+ width = 1;
+ } else if (v < 0x800) {
+ mask = 0xc0;
+ width = 2;
+ } else if (v < 0x10000) {
+ mask = 0xe0;
+ width = 3;
+ } else if (v < 0x200000) {
+ mask = 0xf0;
+ width = 4;
+ } else if (v < 0x4000000) {
+ mask = 0xf8;
+ width = 5;
+ } else if (v < 0x80000000) {
+ mask = 0xfc;
+ width = 6;
+ } else {
+ WARNING(("idn_ucs4_ucs4toutf8: invalid character\n"));
+ r = idn_invalid_encoding;
+ goto ret;
+ }
+
+ if (tolen < width) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ offset = 6 * (width - 1);
+ *utf8p++ = (v >> offset) | mask;
+ mask = 0x80;
+ while (offset > 0) {
+ offset -= 6;
+ *utf8p++ = ((v >> offset) & 0x3f) | mask;
+ }
+ tolen -= width;
+ }
+
+ if (tolen < 1) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *utf8p = '\0';
+
+ r = idn_success;
+ret:
+ if (r == idn_success) {
+ TRACE(("idn_ucs4_ucs4toutf8(): success (utf8=\"%s\")\n",
+ idn__debug_xstring(utf8, 50)));
+ } else {
+ TRACE(("idn_ucs4_ucs4toutf8(): %s\n",
+ idn_result_tostring(r)));
+ }
+ return (r);
+}
+
+size_t
+idn_ucs4_strlen(const unsigned long *ucs4) {
+ size_t len;
+
+ for (len = 0; *ucs4 != '\0'; ucs4++, len++)
+ /* nothing to do */ ;
+
+ return (len);
+}
+
+unsigned long *
+idn_ucs4_strcpy(unsigned long *to, const unsigned long *from) {
+ unsigned long *result = to;
+
+ while (*from != '\0')
+ *to++ = *from++;
+ *to = '\0';
+
+ return (result);
+}
+
+unsigned long *
+idn_ucs4_strcat(unsigned long *to, const unsigned long *from) {
+ unsigned long *result = to;
+
+ while (*to != '\0')
+ to++;
+
+ while (*from != '\0')
+ *to++ = *from++;
+ *to = '\0';
+
+ return (result);
+}
+
+int
+idn_ucs4_strcmp(const unsigned long *str1, const unsigned long *str2) {
+ while (*str1 != '\0') {
+ if (*str1 > *str2)
+ return (1);
+ else if (*str1 < *str2)
+ return (-1);
+ str1++;
+ str2++;
+ }
+
+ if (*str1 > *str2)
+ return (1);
+ else if (*str1 < *str2)
+ return (-1);
+
+ return (0);
+}
+
+int
+idn_ucs4_strcasecmp(const unsigned long *str1, const unsigned long *str2) {
+ unsigned long c1, c2;
+
+ while (*str1 != '\0') {
+ c1 = ASCII_TOLOWER(*str1);
+ c2 = ASCII_TOLOWER(*str2);
+ if (c1 > c2)
+ return (1);
+ else if (c1 < c2)
+ return (-1);
+ str1++;
+ str2++;
+ }
+
+ c1 = ASCII_TOLOWER(*str1);
+ c2 = ASCII_TOLOWER(*str2);
+ if (c1 > c2)
+ return (1);
+ else if (c1 < c2)
+ return (-1);
+
+ return (0);
+}
+
+
+unsigned long *
+idn_ucs4_strdup(const unsigned long *str) {
+ size_t length = idn_ucs4_strlen(str);
+ unsigned long *dupstr;
+
+ dupstr = (unsigned long *)malloc(sizeof(*str) * (length + 1));
+ if (dupstr == NULL)
+ return NULL;
+ memcpy(dupstr, str, sizeof(*str) * (length + 1));
+
+ return dupstr;
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/ucsmap.c b/contrib/idn/idnkit-1.0-src/lib/ucsmap.c
new file mode 100644
index 0000000..633456d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/ucsmap.c
@@ -0,0 +1,380 @@
+#ifndef lint
+static char *rcsid = "$Id: ucsmap.c,v 1.1.1.1 2003/06/04 00:26:14 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/log.h>
+#include <idn/logmacro.h>
+#include <idn/ucsmap.h>
+
+#define INIT_SIZE 50
+#define DEFAULT_BUF_SIZE 500
+#define UCSMAP_HASH_SIZE 103
+#define MAX_MAPLEN 0xffff
+
+/*
+ * This module implements UCS 1-to-N mapping.
+ * To speed up mapping table lookup, a combination of hash and
+ * binary search is used.
+ */
+
+/*
+ * Mapping entry.
+ * Entries are sorted by its hash index and code point.
+ */
+typedef struct {
+ short hidx; /* hash index */
+ unsigned short len; /* length of mapped sequence */
+ unsigned long ucs; /* code point to be mapped */
+ unsigned long *map; /* mapped sequence of code points */
+} ucsmap_entry_t;
+
+/*
+ * Hash table entry.
+ * Since the entries pointed by ucsmap_hash_t.entry are sorted,
+ * binary search can be used.
+ */
+typedef struct {
+ ucsmap_entry_t *entry; /* sorted by code point */
+ int n; /* length of 'entry' */
+} ucsmap_hash_t;
+
+/*
+ * UCS character buffer for storing target character sequence.
+ */
+typedef struct ucsmap_buf {
+ struct ucsmap_buf *next;
+ unsigned long buf[1]; /* actually a variable length array */
+} ucsmap_buf_t;
+
+/*
+ * Mapping object.
+ */
+typedef struct idn_ucsmap {
+ ucsmap_hash_t hash[UCSMAP_HASH_SIZE];
+ ucsmap_entry_t *entries; /* array of entries */
+ size_t entry_size; /* allocated size */
+ size_t nentries; /* # of entries in use */
+ ucsmap_buf_t *mapdata; /* list of character buffers */
+ size_t mapdata_size; /* allocated size of current buffer */
+ size_t mapdata_used; /* # of chars in use */
+ int fixed; /* already fixed? */
+ int refcnt; /* reference count */
+} ucsmap_t;
+
+static int ucsmap_hash(unsigned long v);
+static unsigned long *save_mapped_sequence(idn_ucsmap_t ctx,
+ unsigned long *map,
+ size_t maplen);
+static void free_mapbuf(ucsmap_buf_t *buf);
+static int comp_entry(const void *v1, const void *v2);
+
+idn_result_t
+idn_ucsmap_create(idn_ucsmap_t *ctxp) {
+ idn_ucsmap_t ctx;
+
+ assert(ctxp != NULL);
+
+ TRACE(("idn_ucsmap_create()\n"));
+
+ if ((ctx = malloc(sizeof(*ctx))) == NULL) {
+ WARNING(("idn_ucsmap_create: malloc failed\n"));
+ return (idn_nomemory);
+ }
+
+ ctx->entry_size = 0;
+ ctx->nentries = 0;
+ ctx->entries = NULL;
+ ctx->mapdata = NULL;
+ ctx->mapdata_size = 0;
+ ctx->mapdata_used = 0;
+ ctx->fixed = 0;
+ ctx->refcnt = 1;
+ *ctxp = ctx;
+ return (idn_success);
+}
+
+void
+idn_ucsmap_destroy(idn_ucsmap_t ctx) {
+ assert(ctx != NULL && ctx->refcnt > 0);
+
+ TRACE(("idn_ucsmap_destroy()\n"));
+
+ if (--ctx->refcnt == 0) {
+ if (ctx->entries != NULL)
+ free(ctx->entries);
+ if (ctx->mapdata != NULL)
+ free_mapbuf(ctx->mapdata);
+ free(ctx);
+ }
+}
+
+void
+idn_ucsmap_incrref(idn_ucsmap_t ctx) {
+ assert(ctx != NULL && ctx->refcnt > 0);
+
+ ctx->refcnt++;
+}
+
+idn_result_t
+idn_ucsmap_add(idn_ucsmap_t ctx, unsigned long ucs,
+ unsigned long *map, size_t maplen)
+{
+ ucsmap_entry_t *e;
+ ucsmap_entry_t *newbuf;
+
+ assert(ctx != NULL && ctx->refcnt > 0);
+
+ TRACE(("idn_ucsmap_add(ucs=U+%lX, maplen=%u)\n", ucs, maplen));
+
+ /* Make sure it is not fixed yet. */
+ if (ctx->fixed) {
+ WARNING(("idn_ucsmap_add: attempt to add to fixed map\n"));
+ return (idn_failure);
+ }
+
+ if (maplen > MAX_MAPLEN) {
+ WARNING(("idn_ucsmap_add: maplen too large (> %d)\n",
+ MAX_MAPLEN));
+ return (idn_failure);
+ }
+
+ /* Append an entry. */
+ if (ctx->nentries >= ctx->entry_size) {
+ if (ctx->entry_size == 0)
+ ctx->entry_size = INIT_SIZE;
+ else
+ ctx->entry_size *= 2;
+ newbuf = realloc(ctx->entries, sizeof(*e) * ctx->entry_size);
+ if (newbuf == NULL)
+ return (idn_nomemory);
+ ctx->entries = newbuf;
+ }
+ e = &ctx->entries[ctx->nentries];
+ e->hidx = ucsmap_hash(ucs);
+ e->len = maplen;
+ e->ucs = ucs;
+ if (maplen > 0) {
+ /* Save mapped sequence in the buffer. */
+ e->map = save_mapped_sequence(ctx, map, maplen);
+ if (e->map == NULL)
+ return (idn_nomemory);
+ } else {
+ /*
+ * Zero 'maplen' is perfectly valid meaning one-to-zero
+ * mapping.
+ */
+ e->map = NULL;
+ }
+ ctx->nentries++;
+
+ return (idn_success);
+}
+
+void
+idn_ucsmap_fix(idn_ucsmap_t ctx) {
+ ucsmap_entry_t *e;
+ int last_hidx;
+ int i;
+
+ assert(ctx != NULL && ctx->refcnt > 0);
+
+ TRACE(("idn_ucsmap_fix()\n"));
+
+ if (ctx->fixed)
+ return;
+
+ ctx->fixed = 1;
+
+ /* Initialize hash. */
+ for (i = 0; i < UCSMAP_HASH_SIZE; i++) {
+ ctx->hash[i].entry = NULL;
+ ctx->hash[i].n = 0;
+ }
+
+ if (ctx->nentries == 0)
+ return;
+
+ /* Sort entries by the hash value and code point. */
+ qsort(ctx->entries, ctx->nentries, sizeof(ucsmap_entry_t), comp_entry);
+
+ /*
+ * Now the entries are sorted by their hash value, and
+ * sorted by its code point among the ones with the same hash value.
+ */
+
+ /* Build hash table. */
+ last_hidx = -1;
+ for (i = 0, e = ctx->entries; i < ctx->nentries; i++, e++) {
+ if (e->hidx != last_hidx) {
+ ctx->hash[e->hidx].entry = e;
+ last_hidx = e->hidx;
+ }
+ ctx->hash[last_hidx].n++;
+ }
+}
+
+idn_result_t
+idn_ucsmap_map(idn_ucsmap_t ctx, unsigned long v, unsigned long *to,
+ size_t tolen, size_t *maplenp) {
+ int hash;
+ ucsmap_entry_t *e;
+ int n;
+ int hi, lo, mid;
+
+ assert(ctx != NULL && ctx->refcnt > 0 && to != NULL &&
+ maplenp != NULL);
+
+ TRACE(("idn_ucsmap_map(v=U+%lX)\n", v));
+
+ if (!ctx->fixed) {
+ WARNING(("idn_ucsmap_map: not fixed yet\n"));
+ return (idn_failure);
+ }
+
+ /* First, look up hash table. */
+ hash = ucsmap_hash(v);
+ if ((n = ctx->hash[hash].n) == 0)
+ goto nomap;
+
+ /* Then do binary search. */
+ e = ctx->hash[hash].entry;
+ lo = 0;
+ hi = n - 1;
+ while (lo <= hi) {
+ mid = (lo + hi) / 2;
+ if (v < e[mid].ucs)
+ hi = mid - 1;
+ else if (v > e[mid].ucs)
+ lo = mid + 1;
+ else {
+ /* Found. */
+ if (tolen < e[mid].len)
+ return (idn_buffer_overflow);
+ memcpy(to, e[mid].map, sizeof(*to) * e[mid].len);
+ *maplenp = e[mid].len;
+ return (idn_success);
+ }
+ }
+
+ /*
+ * Not found. Put the original character to 'to'
+ * just for convenience.
+ */
+ nomap:
+ if (tolen < 1)
+ return (idn_buffer_overflow);
+ *to = v;
+ *maplenp = 1;
+ return (idn_nomapping);
+}
+
+static int
+ucsmap_hash(unsigned long v) {
+ return (v % UCSMAP_HASH_SIZE);
+}
+
+static unsigned long *
+save_mapped_sequence(idn_ucsmap_t ctx, unsigned long *map, size_t maplen) {
+ ucsmap_buf_t *buf;
+ unsigned long *p;
+ size_t allocsize;
+
+ /*
+ * If the current buffer (the first one in the ctx->mapdata list)
+ * has enough space, use it. Otherwise, allocate a new buffer and
+ * insert it at the beginning of the list.
+ */
+ if (ctx->mapdata_used + maplen > ctx->mapdata_size) {
+ if (maplen > DEFAULT_BUF_SIZE)
+ allocsize = maplen * 2;
+ else
+ allocsize = DEFAULT_BUF_SIZE;
+ buf = malloc(sizeof(ucsmap_hash_t) +
+ sizeof(unsigned long) * allocsize);
+ if (buf == NULL)
+ return (NULL);
+ buf->next = ctx->mapdata;
+ ctx->mapdata = buf;
+ ctx->mapdata_size = allocsize;
+ ctx->mapdata_used = 0;
+ }
+ p = ctx->mapdata->buf + ctx->mapdata_used;
+ memcpy(p, map, sizeof(unsigned long) * maplen);
+ ctx->mapdata_used += maplen;
+ return (p);
+}
+
+static void
+free_mapbuf(ucsmap_buf_t *buf) {
+ while (buf != NULL) {
+ ucsmap_buf_t *next = buf->next;
+ free(buf);
+ buf = next;
+ }
+}
+
+static int
+comp_entry(const void *v1, const void *v2) {
+ const ucsmap_entry_t *e1 = v1;
+ const ucsmap_entry_t *e2 = v2;
+
+ if (e1->hidx < e2->hidx)
+ return (-1);
+ else if (e1->hidx > e2->hidx)
+ return (1);
+ else if (e1->ucs < e2->ucs)
+ return (-1);
+ else if (e1->ucs > e2->ucs)
+ return (1);
+ else
+ return (0);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/ucsset.c b/contrib/idn/idnkit-1.0-src/lib/ucsset.c
new file mode 100644
index 0000000..76e2970
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/ucsset.c
@@ -0,0 +1,368 @@
+#ifndef lint
+static char *rcsid = "$Id: ucsset.c,v 1.1.1.1 2003/06/04 00:26:15 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/ucsset.h>
+
+#define UCS_MAX 0x80000000UL
+
+#define INIT_SIZE 50
+
+/*
+ * Code point range.
+ *
+ * The set of code points is represented by an array of code point ranges.
+ * In the building phase, specified ranges by 'idn_ucsset_add' or
+ * 'idn_ucsset_addrange' are simply appended to the array.
+ * And 'idn_ucsset_fix' sorts the array by the code point value, and also
+ * merges any intersecting ranges. Since the array is sorted, a binary
+ * search can be used for looking up.
+ */
+typedef struct {
+ unsigned long from;
+ unsigned long to;
+} range_t;
+
+/*
+ * Code point segment.
+ *
+ * To speed up searching further, the entire region of UCS-4 code points
+ * (U+0000 - U+7FFFFFFF) are divided into segments. For each segment,
+ * the first and last element of the range array corresponding to the
+ * segment are computed by 'idn_ucsset_fix'. This narrows down the
+ * (initial) search range.
+ */
+typedef struct {
+ int range_start; /* index of ucsset.ranges */
+ int range_end; /* ditto */
+} segment_t;
+
+/*
+ * Code point to segment index conversion.
+ *
+ * Below is the function that maps a code point to the corresponding segment.
+ * The mapping is non-uniform, so that BMP, the following 16 planes that
+ * comprise Unicode code points together with BMP, and other planes
+ * have different granularity.
+ */
+#define SEG_THLD1 0x10000 /* BMP */
+#define SEG_THLD2 0x110000 /* Unicode (BMP+16planes) */
+#define SEG_SFT1 10 /* BMP: 1K code points/segment */
+#define SEG_SFT2 14 /* following 16 planes: 16K cp/seg */
+#define SEG_SFT3 24 /* rest: 16M cp/seg */
+#define SEG_OFF1 (SEG_THLD1 >> SEG_SFT1)
+#define SEG_OFF2 (((SEG_THLD2 - SEG_THLD1) >> SEG_SFT2) + SEG_OFF1)
+#define SEG_INDEX(v) \
+ (((v) < SEG_THLD1) ? ((v) >> SEG_SFT1) : \
+ ((v) < SEG_THLD2) ? ((((v) - SEG_THLD1) >> SEG_SFT2) + SEG_OFF1) : \
+ ((((v) - SEG_THLD2) >> SEG_SFT3) + SEG_OFF2))
+#define SEG_LEN (SEG_INDEX(UCS_MAX - 1) + 1)
+
+/*
+ * Representation of set of UCS code points.
+ */
+typedef struct idn_ucsset {
+ segment_t segments[SEG_LEN];
+ int fixed;
+ int size; /* allocated size of 'ranges' */
+ int nranges; /* num of ranges */
+ range_t *ranges;
+ int refcnt; /* reference count */
+} ucsset;
+
+static idn_result_t addrange(idn_ucsset_t ctx, unsigned long from,
+ unsigned long to, char *func_name);
+static int comp_range(const void *v1, const void *v2);
+
+idn_result_t
+idn_ucsset_create(idn_ucsset_t *ctx) {
+ idn_ucsset_t bm;
+
+ assert(ctx != NULL);
+
+ TRACE(("idn_ucsset_create()\n"));
+
+ if ((bm = malloc(sizeof(ucsset))) == NULL) {
+ WARNING(("idn_ucsset_create: malloc failed\n"));
+ return idn_nomemory;
+ }
+ bm->size = bm->nranges = 0;
+ bm->ranges = NULL;
+ bm->fixed = 0;
+ bm->refcnt = 1;
+ *ctx = bm;
+ return (idn_success);
+}
+
+void
+idn_ucsset_destroy(idn_ucsset_t ctx) {
+ assert(ctx != NULL && ctx->refcnt > 0);
+
+ TRACE(("idn_ucsset_destroy()\n"));
+
+ if (--ctx->refcnt == 0) {
+ if (ctx->ranges != NULL)
+ free(ctx->ranges);
+ free(ctx);
+ }
+}
+
+void
+idn_ucsset_incrref(idn_ucsset_t ctx) {
+ assert(ctx != NULL && ctx->refcnt > 0);
+
+ TRACE(("idn_ucsset_incrref()\n"));
+
+ ctx->refcnt++;
+}
+
+idn_result_t
+idn_ucsset_add(idn_ucsset_t ctx, unsigned long v) {
+ assert(ctx != NULL && ctx->refcnt > 0);
+
+ TRACE(("idn_ucsset_add(v=U+%lX)\n", v));
+
+ return (addrange(ctx, v, v, "idn_ucsset_add"));
+}
+
+idn_result_t
+idn_ucsset_addrange(idn_ucsset_t ctx, unsigned long from,
+ unsigned long to)
+{
+ assert(ctx != NULL && ctx->refcnt > 0);
+
+ TRACE(("idn_ucsset_addrange(from=U+%lX, to=U+%lX)\n",
+ from, to));
+
+ return (addrange(ctx, from, to, "idn_ucsset_addrange"));
+}
+
+void
+idn_ucsset_fix(idn_ucsset_t ctx) {
+ int nranges;
+ range_t *ranges;
+ segment_t *segments;
+ int i, j;
+
+ assert(ctx != NULL && ctx->refcnt > 0);
+
+ TRACE(("idn_ucsset_fix()\n"));
+
+ nranges = ctx->nranges;
+ ranges = ctx->ranges;
+ segments = ctx->segments;
+
+ if (ctx->fixed)
+ return;
+
+ ctx->fixed = 1;
+
+ /* Initialize segment array */
+ for (i = 0; i < SEG_LEN; i++) {
+ segments[i].range_start = -1;
+ segments[i].range_end = -1;
+ }
+
+ /* If the set is empty, there's nothing to be done. */
+ if (nranges == 0)
+ return;
+
+ /* Sort ranges. */
+ qsort(ranges, nranges, sizeof(range_t), comp_range);
+
+ /* Merge overlapped/continuous ranges. */
+ for (i = 0, j = 1; j < nranges; j++) {
+ if (ranges[i].to + 1 >= ranges[j].from) {
+ /* can be merged */
+ if (ranges[i].to < ranges[j].to) {
+ ranges[i].to = ranges[j].to;
+ }
+ } else {
+ i++;
+ if (i < j)
+ ranges[i] = ranges[j];
+ }
+ }
+ /* 'i' points the last range in the array. */
+ ctx->nranges = nranges = ++i;
+
+ /* Create segment array. */
+ for (i = 0; i < nranges; i++) {
+ int fidx = SEG_INDEX(ranges[i].from);
+ int tidx = SEG_INDEX(ranges[i].to);
+
+ for (j = fidx; j <= tidx; j++) {
+ if (segments[j].range_start < 0)
+ segments[j].range_start = i;
+ segments[j].range_end = i;
+ }
+ }
+
+#if 0
+ /*
+ * Does the standard guarantee realloc() always succeeds
+ * when shrinking?
+ */
+ /* Shrink malloc'ed space if possible. */
+ ctx->ranges = realloc(ctx->ranges, ctx->nranges * sizeof(range_t));
+#endif
+}
+
+idn_result_t
+idn_ucsset_lookup(idn_ucsset_t ctx, unsigned long v, int *found) {
+ int idx;
+ segment_t *segments;
+
+ assert(ctx != NULL && ctx->refcnt > 0 && found != NULL);
+
+ TRACE(("idn_ucsset_lookup(v=U+%lX)\n", v));
+
+ /* Make sure it is fixed. */
+ if (!ctx->fixed) {
+ WARNING(("idn_ucsset_lookup: not fixed yet\n"));
+ return (idn_failure);
+ }
+
+ /* Check the given code point. */
+ if (v >= UCS_MAX)
+ return (idn_invalid_codepoint);
+
+ /* Get the segment 'v' belongs to. */
+ segments = ctx->segments;
+ idx = SEG_INDEX(v);
+
+ /* Do binary search. */
+ *found = 0;
+ if (segments[idx].range_start >= 0) {
+ int lo = segments[idx].range_start;
+ int hi = segments[idx].range_end;
+ range_t *ranges = ctx->ranges;
+
+ while (lo <= hi) {
+ int mid = (lo + hi) / 2;
+ if (v < ranges[mid].from) {
+ hi = mid - 1;
+ } else if (v > ranges[mid].to) {
+ lo = mid + 1;
+ } else {
+ *found = 1;
+ break;
+ }
+ }
+ }
+ return (idn_success);
+}
+
+static idn_result_t
+addrange(idn_ucsset_t ctx, unsigned long from, unsigned long to,
+ char *func_name)
+{
+ range_t *newbuf;
+
+ /* Check the given code points. */
+ if (from > UCS_MAX) {
+ WARNING(("%s: code point out of range (U+%lX)\n",
+ func_name, from));
+ return (idn_invalid_codepoint);
+ } else if (to > UCS_MAX) {
+ WARNING(("%s: code point out of range (U+%lX)\n",
+ func_name, to));
+ return (idn_invalid_codepoint);
+ } else if (from > to) {
+ WARNING(("%s: invalid range spec (U+%lX-U+%lX)\n",
+ func_name, from, to));
+ return (idn_invalid_codepoint);
+ }
+
+ /* Make sure it is not fixed yet. */
+ if (ctx->fixed) {
+ WARNING(("%s: attempt to add to already fixed object\n",
+ func_name));
+ return (idn_failure);
+ }
+
+ /* Append the specified range to the 'ranges' array. */
+ if (ctx->nranges >= ctx->size) {
+ /* Make it bigger. */
+ if (ctx->size == 0)
+ ctx->size = INIT_SIZE;
+ else
+ ctx->size *= 2;
+ newbuf = realloc(ctx->ranges, ctx->size * sizeof(range_t));
+ if (newbuf == NULL)
+ return (idn_nomemory);
+ ctx->ranges = newbuf;
+ }
+ ctx->ranges[ctx->nranges].from = from;
+ ctx->ranges[ctx->nranges].to = to;
+ ctx->nranges++;
+
+ return (idn_success);
+}
+
+static int
+comp_range(const void *v1, const void *v2) {
+ /*
+ * Range comparation function suitable for qsort().
+ */
+ const range_t *r1 = v1;
+ const range_t *r2 = v2;
+
+ if (r1->from < r2->from)
+ return (-1);
+ else if (r1->from > r2->from)
+ return (1);
+ else
+ return (0);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/unicode.c b/contrib/idn/idnkit-1.0-src/lib/unicode.c
new file mode 100644
index 0000000..b584b8f
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/unicode.c
@@ -0,0 +1,309 @@
+#ifndef lint
+static char *rcsid = "$Id: unicode.c,v 1.1.1.1 2003/06/04 00:26:16 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/logmacro.h>
+#include <idn/assert.h>
+#include <idn/unicode.h>
+
+#define UNICODE_CURRENT "3.2.0"
+
+#define UCS_MAX 0x10ffff
+#define END_BIT 0x80000000
+
+/*
+ * Some constants for Hangul decomposition/composition.
+ */
+#define SBase 0xac00
+#define LBase 0x1100
+#define VBase 0x1161
+#define TBase 0x11a7
+#define LCount 19
+#define VCount 21
+#define TCount 28
+#define SLast (SBase + LCount * VCount * TCount)
+
+/*
+ * Symbol composition macro.
+ */
+#define compose_sym(a, b) compose_symX(a, b)
+#define compose_symX(a, b) a ## b
+
+struct composition {
+ unsigned long c2; /* 2nd character */
+ unsigned long comp; /* composed character */
+};
+
+#include "unicodedata_320.c"
+#define VERSION v320
+#include "unicode_template.c"
+#undef VERSION
+
+typedef int (*unicode_canonclassproc)(unsigned long v);
+typedef int (*unicode_decomposeproc)(unsigned long c,
+ const unsigned long **seqp);
+typedef int (*unicode_composeproc)(unsigned long c,
+ const struct composition **compp);
+
+static struct idn__unicode_ops {
+ char *version;
+ unicode_canonclassproc canonclass_proc;
+ unicode_decomposeproc decompose_proc;
+ unicode_composeproc compose_proc;
+} unicode_versions[] = {
+#define MAKE_UNICODE_HANDLE(version, suffix) \
+ { version, \
+ compose_sym(canonclass_, suffix), \
+ compose_sym(decompose_, suffix), \
+ compose_sym(compose_, suffix) }
+ MAKE_UNICODE_HANDLE("3.2.0", v320),
+ { NULL },
+#undef MAKE_UNICODE_HANDLE
+};
+
+idn_result_t
+idn__unicode_create(const char *version,
+ idn__unicode_version_t *versionp) {
+ idn__unicode_version_t v;
+
+ assert(versionp != NULL);
+ TRACE(("idn__unicode_create(version=%-.50s)\n",
+ version == NULL ? "<NULL>" : version));
+
+ if (version == NULL)
+ version = UNICODE_CURRENT;
+
+ for (v = unicode_versions; v->version != NULL; v++) {
+ if (strcmp(v->version, version) == 0) {
+ *versionp = v;
+ return (idn_success);
+ }
+ }
+ return (idn_notfound);
+}
+
+void
+idn__unicode_destroy(idn__unicode_version_t version) {
+ assert(version != NULL);
+ TRACE(("idn__unicode_destroy()\n"));
+ /* Nothing to do */
+}
+
+int
+idn__unicode_canonicalclass(idn__unicode_version_t version, unsigned long c) {
+ if (c > UCS_MAX)
+ return (0);
+
+ return (*version->canonclass_proc)(c);
+}
+
+idn_result_t
+idn__unicode_decompose(idn__unicode_version_t version,
+ int compat, unsigned long *v, size_t vlen,
+ unsigned long c, int *decomp_lenp) {
+ unsigned long *vorg = v;
+ int seqidx;
+ const unsigned long *seq;
+
+ assert(v != NULL && vlen >= 0 && decomp_lenp != NULL);
+
+ if (c > UCS_MAX)
+ return (idn_notfound);
+
+ /*
+ * First, check for Hangul.
+ */
+ if (SBase <= c && c < SLast) {
+ int idx, t_offset, v_offset, l_offset;
+
+ idx = c - SBase;
+ t_offset = idx % TCount;
+ idx /= TCount;
+ v_offset = idx % VCount;
+ l_offset = idx / VCount;
+ if ((t_offset == 0 && vlen < 2) || (t_offset > 0 && vlen < 3))
+ return (idn_buffer_overflow);
+ *v++ = LBase + l_offset;
+ *v++ = VBase + v_offset;
+ if (t_offset > 0)
+ *v++ = TBase + t_offset;
+ *decomp_lenp = v - vorg;
+ return (idn_success);
+ }
+
+ /*
+ * Look up decomposition table. If no decomposition is defined
+ * or if it is a compatibility decomosition when canonical
+ * decomposition requested, return 'idn_notfound'.
+ */
+ seqidx = (*version->decompose_proc)(c, &seq);
+ if (seqidx == 0 || (compat == 0 && (seqidx & DECOMP_COMPAT) != 0))
+ return (idn_notfound);
+
+ /*
+ * Copy the decomposed sequence. The end of the sequence are
+ * marked with END_BIT.
+ */
+ do {
+ unsigned long c;
+ int dlen;
+ idn_result_t r;
+
+ c = *seq & ~END_BIT;
+
+ /* Decompose recursively. */
+ r = idn__unicode_decompose(version, compat, v, vlen, c, &dlen);
+ if (r == idn_success) {
+ v += dlen;
+ vlen -= dlen;
+ } else if (r == idn_notfound) {
+ if (vlen < 1)
+ return (idn_buffer_overflow);
+ *v++ = c;
+ vlen--;
+ } else {
+ return (r);
+ }
+
+ } while ((*seq++ & END_BIT) == 0);
+
+ *decomp_lenp = v - vorg;
+
+ return (idn_success);
+}
+
+int
+idn__unicode_iscompositecandidate(idn__unicode_version_t version,
+ unsigned long c) {
+ const struct composition *dummy;
+
+ if (c > UCS_MAX)
+ return (0);
+
+ /* Check for Hangul */
+ if ((LBase <= c && c < LBase + LCount) || (SBase <= c && c < SLast))
+ return (1);
+
+ /*
+ * Look up composition table. If there are no composition
+ * that begins with the given character, it is not a
+ * composition candidate.
+ */
+ if ((*version->compose_proc)(c, &dummy) == 0)
+ return (0);
+ else
+ return (1);
+}
+
+idn_result_t
+idn__unicode_compose(idn__unicode_version_t version, unsigned long c1,
+ unsigned long c2, unsigned long *compp) {
+ int n;
+ int lo, hi;
+ const struct composition *cseq;
+
+ assert(compp != NULL);
+
+ if (c1 > UCS_MAX || c2 > UCS_MAX)
+ return (idn_notfound);
+
+ /*
+ * Check for Hangul.
+ */
+ if (LBase <= c1 && c1 < LBase + LCount &&
+ VBase <= c2 && c2 < VBase + VCount) {
+ /*
+ * Hangul L and V.
+ */
+ *compp = SBase +
+ ((c1 - LBase) * VCount + (c2 - VBase)) * TCount;
+ return (idn_success);
+ } else if (SBase <= c1 && c1 < SLast &&
+ TBase <= c2 && c2 < TBase + TCount &&
+ (c1 - SBase) % TCount == 0) {
+ /*
+ * Hangul LV and T.
+ */
+ *compp = c1 + (c2 - TBase);
+ return (idn_success);
+ }
+
+ /*
+ * Look up composition table. If the result is 0, no composition
+ * is defined. Otherwise, upper 16bits of the result contains
+ * the number of composition that begins with 'c1', and the lower
+ * 16bits is the offset in 'compose_seq'.
+ */
+ if ((n = (*version->compose_proc)(c1, &cseq)) == 0)
+ return (idn_notfound);
+
+ /*
+ * The composite sequences are sorted by the 2nd character 'c2'.
+ * So we can use binary search.
+ */
+ lo = 0;
+ hi = n - 1;
+ while (lo <= hi) {
+ int mid = (lo + hi) / 2;
+
+ if (cseq[mid].c2 < c2) {
+ lo = mid + 1;
+ } else if (cseq[mid].c2 > c2) {
+ hi = mid - 1;
+ } else {
+ *compp = cseq[mid].comp;
+ return (idn_success);
+ }
+ }
+ return (idn_notfound);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/unicode_template.c b/contrib/idn/idnkit-1.0-src/lib/unicode_template.c
new file mode 100644
index 0000000..12ce571
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/unicode_template.c
@@ -0,0 +1,101 @@
+/* $Id: unicode_template.c,v 1.1.1.1 2003/06/04 00:26:16 marka Exp $ */
+
+/*
+ * Copyright (c) 2000,2001 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef UNICODE_TEMPLATE_INIT
+#define UNICODE_TEMPLATE_INIT
+
+/*
+ * Macro for multi-level index table.
+ */
+#define LOOKUPTBL(vprefix, mprefix, v) \
+ DMAP(vprefix)[\
+ IMAP(vprefix)[\
+ IMAP(vprefix)[IDX0(mprefix, v)] + IDX1(mprefix, v)\
+ ]\
+ ].tbl[IDX2(mprefix, v)]
+
+#define IDX0(mprefix, v) IDX_0(v, BITS1(mprefix), BITS2(mprefix))
+#define IDX1(mprefix, v) IDX_1(v, BITS1(mprefix), BITS2(mprefix))
+#define IDX2(mprefix, v) IDX_2(v, BITS1(mprefix), BITS2(mprefix))
+
+#define IDX_0(v, bits1, bits2) ((v) >> ((bits1) + (bits2)))
+#define IDX_1(v, bits1, bits2) (((v) >> (bits2)) & ((1 << (bits1)) - 1))
+#define IDX_2(v, bits1, bits2) ((v) & ((1 << (bits2)) - 1))
+
+#define BITS1(mprefix) mprefix ## _BITS_1
+#define BITS2(mprefix) mprefix ## _BITS_2
+
+#define IMAP(vprefix) concat4(VERSION, _, vprefix, _imap)
+#define DMAP(vprefix) concat4(VERSION, _, vprefix, _table)
+#define SEQ(vprefix) concat4(VERSION, _, vprefix, _seq)
+#define concat4(a,b,c,d) concat4X(a, b, c, d)
+#define concat4X(a,b,c,d) a ## b ## c ## d
+
+#endif /* UNICODE_TEMPLATE_INIT */
+
+static int
+compose_sym(canonclass_, VERSION) (unsigned long c) {
+ /* Look up canonicalclass table. */
+ return (LOOKUPTBL(canon_class, CANON_CLASS, c));
+}
+
+static int
+compose_sym(decompose_, VERSION) (unsigned long c, const unsigned long **seqp)
+{
+ /* Look up decomposition table. */
+ int seqidx = LOOKUPTBL(decompose, DECOMP, c);
+ *seqp = SEQ(decompose) + (seqidx & ~DECOMP_COMPAT);
+ return (seqidx);
+}
+
+static int
+compose_sym(compose_, VERSION) (unsigned long c,
+ const struct composition **compp)
+{
+ /* Look up composition table. */
+ int seqidx = LOOKUPTBL(compose, CANON_COMPOSE, c);
+ *compp = SEQ(compose) + (seqidx & 0xffff);
+ return (seqidx >> 16);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/unicodedata_320.c b/contrib/idn/idnkit-1.0-src/lib/unicodedata_320.c
new file mode 100644
index 0000000..64370e8
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/unicodedata_320.c
@@ -0,0 +1,7916 @@
+/* $Id: unicodedata_320.c,v 1.1.1.1 2003/06/04 00:26:43 marka Exp $ */
+/* $-Id: generate_normalize_data.pl,v 1.8 2001/10/31 08:51:30 m-kasahr Exp -$ */
+/*
+ * Do not edit this file!
+ * This file is generated from UnicodeData.txt, CompositionExclusions-1.txt,
+ * SpecialCasing.txt and CaseFolding.txt.
+ */
+
+
+/*
+ * Canonical Class
+ */
+
+#define CANON_CLASS_BITS_0 9
+#define CANON_CLASS_BITS_1 7
+#define CANON_CLASS_BITS_2 5
+
+static const unsigned short v320_canon_class_imap[] = {
+ 272, 400, 528, 656, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 912,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 1040, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 2, 3, 4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 6, 7, 8, 0,
+ 0, 0, 9, 10, 0, 0, 11, 12,
+ 13, 14, 15, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 16, 17, 0, 0, 16, 18, 0,
+ 0, 16, 18, 0, 0, 16, 18, 0,
+ 0, 16, 18, 0, 0, 0, 18, 0,
+ 0, 0, 19, 0, 0, 0, 18, 0,
+ 0, 0, 18, 0, 0, 0, 20, 0,
+ 0, 21, 22, 0, 0, 23, 24, 0,
+ 25, 26, 0, 27, 28, 0, 29, 0,
+ 0, 30, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 31, 31, 0, 0, 0, 0, 32, 0,
+ 0, 0, 0, 0, 0, 33, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 34, 35,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 36, 0, 0, 37, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 38, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 39, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 40, 41, 42, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const struct {
+ unsigned char tbl[32];
+} v320_canon_class_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
+ 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 232,
+ 220, 220, 220, 220, 232, 216, 220, 220, 220, 220,
+ }},
+ {{
+ 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220,
+ 220, 220, 220, 220, 220, 220, 220, 220, 220, 1, 1,
+ 1, 1, 1, 220, 220, 220, 220, 230, 230, 230,
+ }},
+ {{
+ 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230,
+ 230, 230, 220, 220, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 234, 234, 233, 230, 230, 230, 230, 230, 230, 230, 230,
+ 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 220, 230, 230, 230, 230,
+ 220, 230, 230, 230, 222, 220, 230, 230, 230, 230,
+ }},
+ {{
+ 230, 230, 0, 220, 220, 220, 220, 220, 230, 230, 220,
+ 230, 230, 222, 228, 230, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 0, 20, 21, 22, 0, 23,
+ }},
+ {{
+ 0, 24, 25, 0, 230, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 27, 28, 29, 30, 31, 32, 33, 34, 230, 230, 220,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 230, 230, 230, 230, 230, 230, 230, 0, 0, 230,
+ }},
+ {{
+ 230, 230, 230, 220, 230, 0, 0, 230, 230, 0, 220,
+ 230, 230, 220, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 230, 220, 230, 230, 220, 230,
+ 230, 220, 220, 220, 230, 220, 220, 230, 220, 230,
+ }},
+ {{
+ 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 9, 0, 0, 0, 230, 220, 230, 230, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84,
+ 91, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 103, 103, 9, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107,
+ 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 118, 118, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 122,
+ 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 220, 220, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220,
+ 0, 220, 0, 216, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 129, 130, 0, 132, 0,
+ 0, 0, 0, 0, 130, 130, 130, 130, 0, 0,
+ }},
+ {{
+ 130, 0, 230, 230, 9, 0, 230, 230, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 7, 0, 9, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 230, 230, 1, 1, 230, 230,
+ 230, 230, 1, 1, 1, 230, 230, 0, 0, 0,
+ }},
+ {{
+ 0, 230, 0, 0, 0, 1, 1, 230, 220, 230, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218,
+ 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 8, 8, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 26, 0,
+ }},
+ {{
+ 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 216, 216, 1, 1, 1, 0,
+ 0, 0, 226, 216, 216, 216, 216, 216, 0, 0, 0,
+ 0, 0, 0, 0, 0, 220, 220, 220, 220, 220,
+ }},
+ {{
+ 220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220,
+ 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230,
+ 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+};
+
+/*
+ * Canonical Composition
+ */
+
+#define CANON_COMPOSE_BITS_0 9
+#define CANON_COMPOSE_BITS_1 7
+#define CANON_COMPOSE_BITS_2 5
+
+static const unsigned short v320_compose_imap[] = {
+ 272, 400, 528, 656, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 0, 1, 2, 3, 0, 4, 5, 6,
+ 7, 0, 8, 9, 0, 10, 0, 11,
+ 0, 12, 0, 0, 13, 0, 0, 0,
+ 0, 0, 0, 0, 14, 15, 16, 0,
+ 17, 18, 19, 20, 0, 0, 21, 22,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 23, 24, 0, 0, 0, 25, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 0, 0, 0, 0, 27, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 28, 0, 29, 0, 30, 0,
+ 0, 0, 31, 0, 0, 32, 33, 0,
+ 0, 0, 34, 0, 0, 0, 35, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 36, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 37, 38, 39, 0, 40, 41, 0,
+ 42, 43, 44, 45, 0, 46, 47, 48,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 49, 0, 50, 0,
+ 51, 52, 53, 54, 55, 56, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 57, 58, 59, 60, 61, 62,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const struct {
+ unsigned long tbl[32];
+} v320_compose_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 65537, 65538, 65539, 0,
+ }},
+ {{
+ 0, 1048580, 196628, 327703, 393244, 1114146, 65587,
+ 458804, 458811, 983106, 65617, 327762, 393303, 196701,
+ 589920, 1048681, 131193, 0, 524411, 458883, 458890,
+ 1245329, 131236, 393382, 131244, 589998, 393399, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 1048765, 196813, 327888, 393429, 1114331, 65772,
+ 458989, 524532, 917756, 131338, 327948, 393489, 196887,
+ 590106, 1048867, 131379, 0, 524597, 459069, 524612,
+ 1245516, 131423, 459105, 131432, 655722, 393588, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 196986, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 262525, 0, 65921, 65922, 131459,
+ 65925, 0, 0, 262534, 0, 0, 0,
+ 0, 65930, 0, 0, 0, 0, 262539,
+ 197007, 65938, 0, 65939, 0, 0, 0,
+ 262548, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 262552, 0, 65948, 65949, 131486,
+ 65952, 0, 0, 262561, 0, 0, 0,
+ 0, 65957, 0, 0, 0, 0, 262566,
+ 197034, 65965, 0, 65966, 0, 0, 0,
+ 262575, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 262579, 262583, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 131515, 131517, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 131519, 131521,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 65987, 65988,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 65989, 65990, 0, 0, 0, 0, 0,
+ 0, 65991, 65992, 65993, 65994, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 65995,
+ }},
+ {{
+ 328140, 328145, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 328150, 328155, 0, 0, 0, 0,
+ 0, 0, 66016, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 66017, 66018, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 66019,
+ 66020, 66021, 66022, 0, 0, 0, 0,
+ 66023, 66024, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66025, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 459242, 0, 0, 0,
+ 262641, 0, 328181, 0, 459258, 0, 0,
+ 0, 0, 0, 262657,
+ }},
+ {{
+ 0, 66053, 0, 0, 0, 393734, 0,
+ 0, 0, 328204, 0, 0, 66065, 0,
+ 66066, 0, 0, 524819, 0, 0, 0,
+ 262683, 0, 393759, 0, 524837, 0, 0,
+ 0, 0, 0, 262701,
+ }},
+ {{
+ 0, 131633, 0, 0, 0, 524851, 0,
+ 0, 0, 393787, 197185, 197188, 0, 0,
+ 66119, 0, 0, 0, 131656, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 66122,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 131659, 0, 0, 66125, 0,
+ 197198, 131665, 66131, 262740, 0, 66136, 0,
+ 0, 0, 66137, 0,
+ }},
+ {{
+ 0, 0, 0, 262746, 0, 0, 0,
+ 66142, 0, 0, 0, 66143, 0, 66144,
+ 0, 0, 131681, 0, 0, 66147, 0,
+ 197220, 131687, 66153, 262762, 0, 66158, 0,
+ 0, 0, 66159, 0,
+ }},
+ {{
+ 0, 0, 0, 262768, 0, 0, 0,
+ 66164, 0, 0, 0, 66165, 0, 66166,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 66167, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 66168,
+ 66169, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 66170, 66171, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 66172, 66173, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 197246, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 66177, 0, 66178, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 66179, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66180, 0, 0,
+ 66181, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 66182, 0, 0, 0, 0, 0,
+ 0, 0, 66183, 0, 0, 66184, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 131721, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 197259, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66190, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 131727,
+ 66193, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 66194,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 66195,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 197268,
+ 0, 0, 0, 66199, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 131736,
+ 66202, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 197275, 0, 0,
+ 66206, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 66207, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 66208, 66209, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 66210, 66211,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 66212, 66213, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 131750, 131752, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 66218, 66219, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 66220, 66221,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 262830, 262834, 66230, 66231, 66232, 66233, 66234,
+ 66235, 262844, 262848, 66244, 66245, 66246, 66247,
+ 66248, 66249, 131786, 131788, 0, 0, 0,
+ 0, 0, 0, 131790, 131792, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 262866, 262870, 66266, 66267, 66268, 66269, 66270,
+ 66271, 262880, 262884, 66280, 66281, 66282, 66283,
+ 66284, 66285, 197358, 197361, 0, 0, 0,
+ 0, 0, 0, 197364, 197367, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 131834, 131836, 0, 0, 0, 0, 0,
+ 0, 131838, 131840, 0, 0, 0, 0,
+ 0, 0, 197378, 197381, 0, 0, 0,
+ 0, 0, 0, 0, 197384, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 262923, 262927, 66323, 66324, 66325, 66326, 66327,
+ 66328, 262937, 262941, 66337, 66338, 66339, 66340,
+ 66341, 66342, 66343, 0, 0, 0, 66344,
+ 0, 0, 0, 0, 0, 0, 0,
+ 66345, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 66346, 0, 0, 0, 0, 0,
+ 0, 0, 0, 197419,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 66350,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 66351, 0, 0, 0, 0, 0,
+ 0, 0, 197424, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 66355, 0, 66356, 0, 66357,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 66358, 0, 66359, 0, 66360,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 66361, 0, 0, 0,
+ 0, 66362, 0, 0, 66363, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 66364, 0, 66365, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 66366, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 66367, 0, 66368, 0,
+ 0, 66369, 0, 0, 0, 0, 66370,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 66371, 0, 0, 66372, 66373, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 66374, 66375, 0,
+ 0, 66376, 66377, 0, 0, 66378, 66379,
+ 66380, 66381, 0, 0,
+ }},
+ {{
+ 0, 0, 66382, 66383, 0, 0, 66384,
+ 66385, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 66386, 66387, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 66388, 0, 0, 0, 0,
+ 0, 66389, 66390, 0, 66391, 0, 0,
+ 0, 0, 0, 0, 66392, 66393, 66394,
+ 66395, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 66396,
+ 0, 0, 0, 0, 66397, 0, 66398,
+ 0, 66399, 0, 66400, 0, 66401, 0,
+ 66402, 0, 66403, 0, 66404, 0, 66405,
+ 0, 66406, 0, 66407,
+ }},
+ {{
+ 0, 66408, 0, 0, 66409, 0, 66410,
+ 0, 66411, 0, 0, 0, 0, 0,
+ 0, 131948, 0, 0, 131950, 0, 0,
+ 131952, 0, 0, 131954, 0, 0, 131956,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 66422, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 66423,
+ 0, 0, 0, 0, 66424, 0, 66425,
+ 0, 66426, 0, 66427, 0, 66428, 0,
+ 66429, 0, 66430, 0, 66431, 0, 66432,
+ 0, 66433, 0, 66434,
+ }},
+ {{
+ 0, 66435, 0, 0, 66436, 0, 66437,
+ 0, 66438, 0, 0, 0, 0, 0,
+ 0, 131975, 0, 0, 131977, 0, 0,
+ 131979, 0, 0, 131981, 0, 0, 131983,
+ 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 66449, 66450, 66451, 66452, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 66453, 0, 0,
+ }},
+};
+
+static const struct composition v320_compose_seq[] = {
+ { 0x00000000, 0x00000000 }, { 0x00000338, 0x0000226e },
+ { 0x00000338, 0x00002260 }, { 0x00000338, 0x0000226f },
+ { 0x00000300, 0x000000c0 }, { 0x00000301, 0x000000c1 },
+ { 0x00000302, 0x000000c2 }, { 0x00000303, 0x000000c3 },
+ { 0x00000304, 0x00000100 }, { 0x00000306, 0x00000102 },
+ { 0x00000307, 0x00000226 }, { 0x00000308, 0x000000c4 },
+ { 0x00000309, 0x00001ea2 }, { 0x0000030a, 0x000000c5 },
+ { 0x0000030c, 0x000001cd }, { 0x0000030f, 0x00000200 },
+ { 0x00000311, 0x00000202 }, { 0x00000323, 0x00001ea0 },
+ { 0x00000325, 0x00001e00 }, { 0x00000328, 0x00000104 },
+ { 0x00000307, 0x00001e02 }, { 0x00000323, 0x00001e04 },
+ { 0x00000331, 0x00001e06 }, { 0x00000301, 0x00000106 },
+ { 0x00000302, 0x00000108 }, { 0x00000307, 0x0000010a },
+ { 0x0000030c, 0x0000010c }, { 0x00000327, 0x000000c7 },
+ { 0x00000307, 0x00001e0a }, { 0x0000030c, 0x0000010e },
+ { 0x00000323, 0x00001e0c }, { 0x00000327, 0x00001e10 },
+ { 0x0000032d, 0x00001e12 }, { 0x00000331, 0x00001e0e },
+ { 0x00000300, 0x000000c8 }, { 0x00000301, 0x000000c9 },
+ { 0x00000302, 0x000000ca }, { 0x00000303, 0x00001ebc },
+ { 0x00000304, 0x00000112 }, { 0x00000306, 0x00000114 },
+ { 0x00000307, 0x00000116 }, { 0x00000308, 0x000000cb },
+ { 0x00000309, 0x00001eba }, { 0x0000030c, 0x0000011a },
+ { 0x0000030f, 0x00000204 }, { 0x00000311, 0x00000206 },
+ { 0x00000323, 0x00001eb8 }, { 0x00000327, 0x00000228 },
+ { 0x00000328, 0x00000118 }, { 0x0000032d, 0x00001e18 },
+ { 0x00000330, 0x00001e1a }, { 0x00000307, 0x00001e1e },
+ { 0x00000301, 0x000001f4 }, { 0x00000302, 0x0000011c },
+ { 0x00000304, 0x00001e20 }, { 0x00000306, 0x0000011e },
+ { 0x00000307, 0x00000120 }, { 0x0000030c, 0x000001e6 },
+ { 0x00000327, 0x00000122 }, { 0x00000302, 0x00000124 },
+ { 0x00000307, 0x00001e22 }, { 0x00000308, 0x00001e26 },
+ { 0x0000030c, 0x0000021e }, { 0x00000323, 0x00001e24 },
+ { 0x00000327, 0x00001e28 }, { 0x0000032e, 0x00001e2a },
+ { 0x00000300, 0x000000cc }, { 0x00000301, 0x000000cd },
+ { 0x00000302, 0x000000ce }, { 0x00000303, 0x00000128 },
+ { 0x00000304, 0x0000012a }, { 0x00000306, 0x0000012c },
+ { 0x00000307, 0x00000130 }, { 0x00000308, 0x000000cf },
+ { 0x00000309, 0x00001ec8 }, { 0x0000030c, 0x000001cf },
+ { 0x0000030f, 0x00000208 }, { 0x00000311, 0x0000020a },
+ { 0x00000323, 0x00001eca }, { 0x00000328, 0x0000012e },
+ { 0x00000330, 0x00001e2c }, { 0x00000302, 0x00000134 },
+ { 0x00000301, 0x00001e30 }, { 0x0000030c, 0x000001e8 },
+ { 0x00000323, 0x00001e32 }, { 0x00000327, 0x00000136 },
+ { 0x00000331, 0x00001e34 }, { 0x00000301, 0x00000139 },
+ { 0x0000030c, 0x0000013d }, { 0x00000323, 0x00001e36 },
+ { 0x00000327, 0x0000013b }, { 0x0000032d, 0x00001e3c },
+ { 0x00000331, 0x00001e3a }, { 0x00000301, 0x00001e3e },
+ { 0x00000307, 0x00001e40 }, { 0x00000323, 0x00001e42 },
+ { 0x00000300, 0x000001f8 }, { 0x00000301, 0x00000143 },
+ { 0x00000303, 0x000000d1 }, { 0x00000307, 0x00001e44 },
+ { 0x0000030c, 0x00000147 }, { 0x00000323, 0x00001e46 },
+ { 0x00000327, 0x00000145 }, { 0x0000032d, 0x00001e4a },
+ { 0x00000331, 0x00001e48 }, { 0x00000300, 0x000000d2 },
+ { 0x00000301, 0x000000d3 }, { 0x00000302, 0x000000d4 },
+ { 0x00000303, 0x000000d5 }, { 0x00000304, 0x0000014c },
+ { 0x00000306, 0x0000014e }, { 0x00000307, 0x0000022e },
+ { 0x00000308, 0x000000d6 }, { 0x00000309, 0x00001ece },
+ { 0x0000030b, 0x00000150 }, { 0x0000030c, 0x000001d1 },
+ { 0x0000030f, 0x0000020c }, { 0x00000311, 0x0000020e },
+ { 0x0000031b, 0x000001a0 }, { 0x00000323, 0x00001ecc },
+ { 0x00000328, 0x000001ea }, { 0x00000301, 0x00001e54 },
+ { 0x00000307, 0x00001e56 }, { 0x00000301, 0x00000154 },
+ { 0x00000307, 0x00001e58 }, { 0x0000030c, 0x00000158 },
+ { 0x0000030f, 0x00000210 }, { 0x00000311, 0x00000212 },
+ { 0x00000323, 0x00001e5a }, { 0x00000327, 0x00000156 },
+ { 0x00000331, 0x00001e5e }, { 0x00000301, 0x0000015a },
+ { 0x00000302, 0x0000015c }, { 0x00000307, 0x00001e60 },
+ { 0x0000030c, 0x00000160 }, { 0x00000323, 0x00001e62 },
+ { 0x00000326, 0x00000218 }, { 0x00000327, 0x0000015e },
+ { 0x00000307, 0x00001e6a }, { 0x0000030c, 0x00000164 },
+ { 0x00000323, 0x00001e6c }, { 0x00000326, 0x0000021a },
+ { 0x00000327, 0x00000162 }, { 0x0000032d, 0x00001e70 },
+ { 0x00000331, 0x00001e6e }, { 0x00000300, 0x000000d9 },
+ { 0x00000301, 0x000000da }, { 0x00000302, 0x000000db },
+ { 0x00000303, 0x00000168 }, { 0x00000304, 0x0000016a },
+ { 0x00000306, 0x0000016c }, { 0x00000308, 0x000000dc },
+ { 0x00000309, 0x00001ee6 }, { 0x0000030a, 0x0000016e },
+ { 0x0000030b, 0x00000170 }, { 0x0000030c, 0x000001d3 },
+ { 0x0000030f, 0x00000214 }, { 0x00000311, 0x00000216 },
+ { 0x0000031b, 0x000001af }, { 0x00000323, 0x00001ee4 },
+ { 0x00000324, 0x00001e72 }, { 0x00000328, 0x00000172 },
+ { 0x0000032d, 0x00001e76 }, { 0x00000330, 0x00001e74 },
+ { 0x00000303, 0x00001e7c }, { 0x00000323, 0x00001e7e },
+ { 0x00000300, 0x00001e80 }, { 0x00000301, 0x00001e82 },
+ { 0x00000302, 0x00000174 }, { 0x00000307, 0x00001e86 },
+ { 0x00000308, 0x00001e84 }, { 0x00000323, 0x00001e88 },
+ { 0x00000307, 0x00001e8a }, { 0x00000308, 0x00001e8c },
+ { 0x00000300, 0x00001ef2 }, { 0x00000301, 0x000000dd },
+ { 0x00000302, 0x00000176 }, { 0x00000303, 0x00001ef8 },
+ { 0x00000304, 0x00000232 }, { 0x00000307, 0x00001e8e },
+ { 0x00000308, 0x00000178 }, { 0x00000309, 0x00001ef6 },
+ { 0x00000323, 0x00001ef4 }, { 0x00000301, 0x00000179 },
+ { 0x00000302, 0x00001e90 }, { 0x00000307, 0x0000017b },
+ { 0x0000030c, 0x0000017d }, { 0x00000323, 0x00001e92 },
+ { 0x00000331, 0x00001e94 }, { 0x00000300, 0x000000e0 },
+ { 0x00000301, 0x000000e1 }, { 0x00000302, 0x000000e2 },
+ { 0x00000303, 0x000000e3 }, { 0x00000304, 0x00000101 },
+ { 0x00000306, 0x00000103 }, { 0x00000307, 0x00000227 },
+ { 0x00000308, 0x000000e4 }, { 0x00000309, 0x00001ea3 },
+ { 0x0000030a, 0x000000e5 }, { 0x0000030c, 0x000001ce },
+ { 0x0000030f, 0x00000201 }, { 0x00000311, 0x00000203 },
+ { 0x00000323, 0x00001ea1 }, { 0x00000325, 0x00001e01 },
+ { 0x00000328, 0x00000105 }, { 0x00000307, 0x00001e03 },
+ { 0x00000323, 0x00001e05 }, { 0x00000331, 0x00001e07 },
+ { 0x00000301, 0x00000107 }, { 0x00000302, 0x00000109 },
+ { 0x00000307, 0x0000010b }, { 0x0000030c, 0x0000010d },
+ { 0x00000327, 0x000000e7 }, { 0x00000307, 0x00001e0b },
+ { 0x0000030c, 0x0000010f }, { 0x00000323, 0x00001e0d },
+ { 0x00000327, 0x00001e11 }, { 0x0000032d, 0x00001e13 },
+ { 0x00000331, 0x00001e0f }, { 0x00000300, 0x000000e8 },
+ { 0x00000301, 0x000000e9 }, { 0x00000302, 0x000000ea },
+ { 0x00000303, 0x00001ebd }, { 0x00000304, 0x00000113 },
+ { 0x00000306, 0x00000115 }, { 0x00000307, 0x00000117 },
+ { 0x00000308, 0x000000eb }, { 0x00000309, 0x00001ebb },
+ { 0x0000030c, 0x0000011b }, { 0x0000030f, 0x00000205 },
+ { 0x00000311, 0x00000207 }, { 0x00000323, 0x00001eb9 },
+ { 0x00000327, 0x00000229 }, { 0x00000328, 0x00000119 },
+ { 0x0000032d, 0x00001e19 }, { 0x00000330, 0x00001e1b },
+ { 0x00000307, 0x00001e1f }, { 0x00000301, 0x000001f5 },
+ { 0x00000302, 0x0000011d }, { 0x00000304, 0x00001e21 },
+ { 0x00000306, 0x0000011f }, { 0x00000307, 0x00000121 },
+ { 0x0000030c, 0x000001e7 }, { 0x00000327, 0x00000123 },
+ { 0x00000302, 0x00000125 }, { 0x00000307, 0x00001e23 },
+ { 0x00000308, 0x00001e27 }, { 0x0000030c, 0x0000021f },
+ { 0x00000323, 0x00001e25 }, { 0x00000327, 0x00001e29 },
+ { 0x0000032e, 0x00001e2b }, { 0x00000331, 0x00001e96 },
+ { 0x00000300, 0x000000ec }, { 0x00000301, 0x000000ed },
+ { 0x00000302, 0x000000ee }, { 0x00000303, 0x00000129 },
+ { 0x00000304, 0x0000012b }, { 0x00000306, 0x0000012d },
+ { 0x00000308, 0x000000ef }, { 0x00000309, 0x00001ec9 },
+ { 0x0000030c, 0x000001d0 }, { 0x0000030f, 0x00000209 },
+ { 0x00000311, 0x0000020b }, { 0x00000323, 0x00001ecb },
+ { 0x00000328, 0x0000012f }, { 0x00000330, 0x00001e2d },
+ { 0x00000302, 0x00000135 }, { 0x0000030c, 0x000001f0 },
+ { 0x00000301, 0x00001e31 }, { 0x0000030c, 0x000001e9 },
+ { 0x00000323, 0x00001e33 }, { 0x00000327, 0x00000137 },
+ { 0x00000331, 0x00001e35 }, { 0x00000301, 0x0000013a },
+ { 0x0000030c, 0x0000013e }, { 0x00000323, 0x00001e37 },
+ { 0x00000327, 0x0000013c }, { 0x0000032d, 0x00001e3d },
+ { 0x00000331, 0x00001e3b }, { 0x00000301, 0x00001e3f },
+ { 0x00000307, 0x00001e41 }, { 0x00000323, 0x00001e43 },
+ { 0x00000300, 0x000001f9 }, { 0x00000301, 0x00000144 },
+ { 0x00000303, 0x000000f1 }, { 0x00000307, 0x00001e45 },
+ { 0x0000030c, 0x00000148 }, { 0x00000323, 0x00001e47 },
+ { 0x00000327, 0x00000146 }, { 0x0000032d, 0x00001e4b },
+ { 0x00000331, 0x00001e49 }, { 0x00000300, 0x000000f2 },
+ { 0x00000301, 0x000000f3 }, { 0x00000302, 0x000000f4 },
+ { 0x00000303, 0x000000f5 }, { 0x00000304, 0x0000014d },
+ { 0x00000306, 0x0000014f }, { 0x00000307, 0x0000022f },
+ { 0x00000308, 0x000000f6 }, { 0x00000309, 0x00001ecf },
+ { 0x0000030b, 0x00000151 }, { 0x0000030c, 0x000001d2 },
+ { 0x0000030f, 0x0000020d }, { 0x00000311, 0x0000020f },
+ { 0x0000031b, 0x000001a1 }, { 0x00000323, 0x00001ecd },
+ { 0x00000328, 0x000001eb }, { 0x00000301, 0x00001e55 },
+ { 0x00000307, 0x00001e57 }, { 0x00000301, 0x00000155 },
+ { 0x00000307, 0x00001e59 }, { 0x0000030c, 0x00000159 },
+ { 0x0000030f, 0x00000211 }, { 0x00000311, 0x00000213 },
+ { 0x00000323, 0x00001e5b }, { 0x00000327, 0x00000157 },
+ { 0x00000331, 0x00001e5f }, { 0x00000301, 0x0000015b },
+ { 0x00000302, 0x0000015d }, { 0x00000307, 0x00001e61 },
+ { 0x0000030c, 0x00000161 }, { 0x00000323, 0x00001e63 },
+ { 0x00000326, 0x00000219 }, { 0x00000327, 0x0000015f },
+ { 0x00000307, 0x00001e6b }, { 0x00000308, 0x00001e97 },
+ { 0x0000030c, 0x00000165 }, { 0x00000323, 0x00001e6d },
+ { 0x00000326, 0x0000021b }, { 0x00000327, 0x00000163 },
+ { 0x0000032d, 0x00001e71 }, { 0x00000331, 0x00001e6f },
+ { 0x00000300, 0x000000f9 }, { 0x00000301, 0x000000fa },
+ { 0x00000302, 0x000000fb }, { 0x00000303, 0x00000169 },
+ { 0x00000304, 0x0000016b }, { 0x00000306, 0x0000016d },
+ { 0x00000308, 0x000000fc }, { 0x00000309, 0x00001ee7 },
+ { 0x0000030a, 0x0000016f }, { 0x0000030b, 0x00000171 },
+ { 0x0000030c, 0x000001d4 }, { 0x0000030f, 0x00000215 },
+ { 0x00000311, 0x00000217 }, { 0x0000031b, 0x000001b0 },
+ { 0x00000323, 0x00001ee5 }, { 0x00000324, 0x00001e73 },
+ { 0x00000328, 0x00000173 }, { 0x0000032d, 0x00001e77 },
+ { 0x00000330, 0x00001e75 }, { 0x00000303, 0x00001e7d },
+ { 0x00000323, 0x00001e7f }, { 0x00000300, 0x00001e81 },
+ { 0x00000301, 0x00001e83 }, { 0x00000302, 0x00000175 },
+ { 0x00000307, 0x00001e87 }, { 0x00000308, 0x00001e85 },
+ { 0x0000030a, 0x00001e98 }, { 0x00000323, 0x00001e89 },
+ { 0x00000307, 0x00001e8b }, { 0x00000308, 0x00001e8d },
+ { 0x00000300, 0x00001ef3 }, { 0x00000301, 0x000000fd },
+ { 0x00000302, 0x00000177 }, { 0x00000303, 0x00001ef9 },
+ { 0x00000304, 0x00000233 }, { 0x00000307, 0x00001e8f },
+ { 0x00000308, 0x000000ff }, { 0x00000309, 0x00001ef7 },
+ { 0x0000030a, 0x00001e99 }, { 0x00000323, 0x00001ef5 },
+ { 0x00000301, 0x0000017a }, { 0x00000302, 0x00001e91 },
+ { 0x00000307, 0x0000017c }, { 0x0000030c, 0x0000017e },
+ { 0x00000323, 0x00001e93 }, { 0x00000331, 0x00001e95 },
+ { 0x00000300, 0x00001fed }, { 0x00000301, 0x00000385 },
+ { 0x00000342, 0x00001fc1 }, { 0x00000300, 0x00001ea6 },
+ { 0x00000301, 0x00001ea4 }, { 0x00000303, 0x00001eaa },
+ { 0x00000309, 0x00001ea8 }, { 0x00000304, 0x000001de },
+ { 0x00000301, 0x000001fa }, { 0x00000301, 0x000001fc },
+ { 0x00000304, 0x000001e2 }, { 0x00000301, 0x00001e08 },
+ { 0x00000300, 0x00001ec0 }, { 0x00000301, 0x00001ebe },
+ { 0x00000303, 0x00001ec4 }, { 0x00000309, 0x00001ec2 },
+ { 0x00000301, 0x00001e2e }, { 0x00000300, 0x00001ed2 },
+ { 0x00000301, 0x00001ed0 }, { 0x00000303, 0x00001ed6 },
+ { 0x00000309, 0x00001ed4 }, { 0x00000301, 0x00001e4c },
+ { 0x00000304, 0x0000022c }, { 0x00000308, 0x00001e4e },
+ { 0x00000304, 0x0000022a }, { 0x00000301, 0x000001fe },
+ { 0x00000300, 0x000001db }, { 0x00000301, 0x000001d7 },
+ { 0x00000304, 0x000001d5 }, { 0x0000030c, 0x000001d9 },
+ { 0x00000300, 0x00001ea7 }, { 0x00000301, 0x00001ea5 },
+ { 0x00000303, 0x00001eab }, { 0x00000309, 0x00001ea9 },
+ { 0x00000304, 0x000001df }, { 0x00000301, 0x000001fb },
+ { 0x00000301, 0x000001fd }, { 0x00000304, 0x000001e3 },
+ { 0x00000301, 0x00001e09 }, { 0x00000300, 0x00001ec1 },
+ { 0x00000301, 0x00001ebf }, { 0x00000303, 0x00001ec5 },
+ { 0x00000309, 0x00001ec3 }, { 0x00000301, 0x00001e2f },
+ { 0x00000300, 0x00001ed3 }, { 0x00000301, 0x00001ed1 },
+ { 0x00000303, 0x00001ed7 }, { 0x00000309, 0x00001ed5 },
+ { 0x00000301, 0x00001e4d }, { 0x00000304, 0x0000022d },
+ { 0x00000308, 0x00001e4f }, { 0x00000304, 0x0000022b },
+ { 0x00000301, 0x000001ff }, { 0x00000300, 0x000001dc },
+ { 0x00000301, 0x000001d8 }, { 0x00000304, 0x000001d6 },
+ { 0x0000030c, 0x000001da }, { 0x00000300, 0x00001eb0 },
+ { 0x00000301, 0x00001eae }, { 0x00000303, 0x00001eb4 },
+ { 0x00000309, 0x00001eb2 }, { 0x00000300, 0x00001eb1 },
+ { 0x00000301, 0x00001eaf }, { 0x00000303, 0x00001eb5 },
+ { 0x00000309, 0x00001eb3 }, { 0x00000300, 0x00001e14 },
+ { 0x00000301, 0x00001e16 }, { 0x00000300, 0x00001e15 },
+ { 0x00000301, 0x00001e17 }, { 0x00000300, 0x00001e50 },
+ { 0x00000301, 0x00001e52 }, { 0x00000300, 0x00001e51 },
+ { 0x00000301, 0x00001e53 }, { 0x00000307, 0x00001e64 },
+ { 0x00000307, 0x00001e65 }, { 0x00000307, 0x00001e66 },
+ { 0x00000307, 0x00001e67 }, { 0x00000301, 0x00001e78 },
+ { 0x00000301, 0x00001e79 }, { 0x00000308, 0x00001e7a },
+ { 0x00000308, 0x00001e7b }, { 0x00000307, 0x00001e9b },
+ { 0x00000300, 0x00001edc }, { 0x00000301, 0x00001eda },
+ { 0x00000303, 0x00001ee0 }, { 0x00000309, 0x00001ede },
+ { 0x00000323, 0x00001ee2 }, { 0x00000300, 0x00001edd },
+ { 0x00000301, 0x00001edb }, { 0x00000303, 0x00001ee1 },
+ { 0x00000309, 0x00001edf }, { 0x00000323, 0x00001ee3 },
+ { 0x00000300, 0x00001eea }, { 0x00000301, 0x00001ee8 },
+ { 0x00000303, 0x00001eee }, { 0x00000309, 0x00001eec },
+ { 0x00000323, 0x00001ef0 }, { 0x00000300, 0x00001eeb },
+ { 0x00000301, 0x00001ee9 }, { 0x00000303, 0x00001eef },
+ { 0x00000309, 0x00001eed }, { 0x00000323, 0x00001ef1 },
+ { 0x0000030c, 0x000001ee }, { 0x00000304, 0x000001ec },
+ { 0x00000304, 0x000001ed }, { 0x00000304, 0x000001e0 },
+ { 0x00000304, 0x000001e1 }, { 0x00000306, 0x00001e1c },
+ { 0x00000306, 0x00001e1d }, { 0x00000304, 0x00000230 },
+ { 0x00000304, 0x00000231 }, { 0x0000030c, 0x000001ef },
+ { 0x00000300, 0x00001fba }, { 0x00000301, 0x00000386 },
+ { 0x00000304, 0x00001fb9 }, { 0x00000306, 0x00001fb8 },
+ { 0x00000313, 0x00001f08 }, { 0x00000314, 0x00001f09 },
+ { 0x00000345, 0x00001fbc }, { 0x00000300, 0x00001fc8 },
+ { 0x00000301, 0x00000388 }, { 0x00000313, 0x00001f18 },
+ { 0x00000314, 0x00001f19 }, { 0x00000300, 0x00001fca },
+ { 0x00000301, 0x00000389 }, { 0x00000313, 0x00001f28 },
+ { 0x00000314, 0x00001f29 }, { 0x00000345, 0x00001fcc },
+ { 0x00000300, 0x00001fda }, { 0x00000301, 0x0000038a },
+ { 0x00000304, 0x00001fd9 }, { 0x00000306, 0x00001fd8 },
+ { 0x00000308, 0x000003aa }, { 0x00000313, 0x00001f38 },
+ { 0x00000314, 0x00001f39 }, { 0x00000300, 0x00001ff8 },
+ { 0x00000301, 0x0000038c }, { 0x00000313, 0x00001f48 },
+ { 0x00000314, 0x00001f49 }, { 0x00000314, 0x00001fec },
+ { 0x00000300, 0x00001fea }, { 0x00000301, 0x0000038e },
+ { 0x00000304, 0x00001fe9 }, { 0x00000306, 0x00001fe8 },
+ { 0x00000308, 0x000003ab }, { 0x00000314, 0x00001f59 },
+ { 0x00000300, 0x00001ffa }, { 0x00000301, 0x0000038f },
+ { 0x00000313, 0x00001f68 }, { 0x00000314, 0x00001f69 },
+ { 0x00000345, 0x00001ffc }, { 0x00000345, 0x00001fb4 },
+ { 0x00000345, 0x00001fc4 }, { 0x00000300, 0x00001f70 },
+ { 0x00000301, 0x000003ac }, { 0x00000304, 0x00001fb1 },
+ { 0x00000306, 0x00001fb0 }, { 0x00000313, 0x00001f00 },
+ { 0x00000314, 0x00001f01 }, { 0x00000342, 0x00001fb6 },
+ { 0x00000345, 0x00001fb3 }, { 0x00000300, 0x00001f72 },
+ { 0x00000301, 0x000003ad }, { 0x00000313, 0x00001f10 },
+ { 0x00000314, 0x00001f11 }, { 0x00000300, 0x00001f74 },
+ { 0x00000301, 0x000003ae }, { 0x00000313, 0x00001f20 },
+ { 0x00000314, 0x00001f21 }, { 0x00000342, 0x00001fc6 },
+ { 0x00000345, 0x00001fc3 }, { 0x00000300, 0x00001f76 },
+ { 0x00000301, 0x000003af }, { 0x00000304, 0x00001fd1 },
+ { 0x00000306, 0x00001fd0 }, { 0x00000308, 0x000003ca },
+ { 0x00000313, 0x00001f30 }, { 0x00000314, 0x00001f31 },
+ { 0x00000342, 0x00001fd6 }, { 0x00000300, 0x00001f78 },
+ { 0x00000301, 0x000003cc }, { 0x00000313, 0x00001f40 },
+ { 0x00000314, 0x00001f41 }, { 0x00000313, 0x00001fe4 },
+ { 0x00000314, 0x00001fe5 }, { 0x00000300, 0x00001f7a },
+ { 0x00000301, 0x000003cd }, { 0x00000304, 0x00001fe1 },
+ { 0x00000306, 0x00001fe0 }, { 0x00000308, 0x000003cb },
+ { 0x00000313, 0x00001f50 }, { 0x00000314, 0x00001f51 },
+ { 0x00000342, 0x00001fe6 }, { 0x00000300, 0x00001f7c },
+ { 0x00000301, 0x000003ce }, { 0x00000313, 0x00001f60 },
+ { 0x00000314, 0x00001f61 }, { 0x00000342, 0x00001ff6 },
+ { 0x00000345, 0x00001ff3 }, { 0x00000300, 0x00001fd2 },
+ { 0x00000301, 0x00000390 }, { 0x00000342, 0x00001fd7 },
+ { 0x00000300, 0x00001fe2 }, { 0x00000301, 0x000003b0 },
+ { 0x00000342, 0x00001fe7 }, { 0x00000345, 0x00001ff4 },
+ { 0x00000301, 0x000003d3 }, { 0x00000308, 0x000003d4 },
+ { 0x00000308, 0x00000407 }, { 0x00000306, 0x000004d0 },
+ { 0x00000308, 0x000004d2 }, { 0x00000301, 0x00000403 },
+ { 0x00000300, 0x00000400 }, { 0x00000306, 0x000004d6 },
+ { 0x00000308, 0x00000401 }, { 0x00000306, 0x000004c1 },
+ { 0x00000308, 0x000004dc }, { 0x00000308, 0x000004de },
+ { 0x00000300, 0x0000040d }, { 0x00000304, 0x000004e2 },
+ { 0x00000306, 0x00000419 }, { 0x00000308, 0x000004e4 },
+ { 0x00000301, 0x0000040c }, { 0x00000308, 0x000004e6 },
+ { 0x00000304, 0x000004ee }, { 0x00000306, 0x0000040e },
+ { 0x00000308, 0x000004f0 }, { 0x0000030b, 0x000004f2 },
+ { 0x00000308, 0x000004f4 }, { 0x00000308, 0x000004f8 },
+ { 0x00000308, 0x000004ec }, { 0x00000306, 0x000004d1 },
+ { 0x00000308, 0x000004d3 }, { 0x00000301, 0x00000453 },
+ { 0x00000300, 0x00000450 }, { 0x00000306, 0x000004d7 },
+ { 0x00000308, 0x00000451 }, { 0x00000306, 0x000004c2 },
+ { 0x00000308, 0x000004dd }, { 0x00000308, 0x000004df },
+ { 0x00000300, 0x0000045d }, { 0x00000304, 0x000004e3 },
+ { 0x00000306, 0x00000439 }, { 0x00000308, 0x000004e5 },
+ { 0x00000301, 0x0000045c }, { 0x00000308, 0x000004e7 },
+ { 0x00000304, 0x000004ef }, { 0x00000306, 0x0000045e },
+ { 0x00000308, 0x000004f1 }, { 0x0000030b, 0x000004f3 },
+ { 0x00000308, 0x000004f5 }, { 0x00000308, 0x000004f9 },
+ { 0x00000308, 0x000004ed }, { 0x00000308, 0x00000457 },
+ { 0x0000030f, 0x00000476 }, { 0x0000030f, 0x00000477 },
+ { 0x00000308, 0x000004da }, { 0x00000308, 0x000004db },
+ { 0x00000308, 0x000004ea }, { 0x00000308, 0x000004eb },
+ { 0x00000653, 0x00000622 }, { 0x00000654, 0x00000623 },
+ { 0x00000655, 0x00000625 }, { 0x00000654, 0x00000624 },
+ { 0x00000654, 0x00000626 }, { 0x00000654, 0x000006c2 },
+ { 0x00000654, 0x000006d3 }, { 0x00000654, 0x000006c0 },
+ { 0x0000093c, 0x00000929 }, { 0x0000093c, 0x00000931 },
+ { 0x0000093c, 0x00000934 }, { 0x000009be, 0x000009cb },
+ { 0x000009d7, 0x000009cc }, { 0x00000b3e, 0x00000b4b },
+ { 0x00000b56, 0x00000b48 }, { 0x00000b57, 0x00000b4c },
+ { 0x00000bd7, 0x00000b94 }, { 0x00000bbe, 0x00000bca },
+ { 0x00000bd7, 0x00000bcc }, { 0x00000bbe, 0x00000bcb },
+ { 0x00000c56, 0x00000c48 }, { 0x00000cd5, 0x00000cc0 },
+ { 0x00000cc2, 0x00000cca }, { 0x00000cd5, 0x00000cc7 },
+ { 0x00000cd6, 0x00000cc8 }, { 0x00000cd5, 0x00000ccb },
+ { 0x00000d3e, 0x00000d4a }, { 0x00000d57, 0x00000d4c },
+ { 0x00000d3e, 0x00000d4b }, { 0x00000dca, 0x00000dda },
+ { 0x00000dcf, 0x00000ddc }, { 0x00000ddf, 0x00000dde },
+ { 0x00000dca, 0x00000ddd }, { 0x0000102e, 0x00001026 },
+ { 0x00000304, 0x00001e38 }, { 0x00000304, 0x00001e39 },
+ { 0x00000304, 0x00001e5c }, { 0x00000304, 0x00001e5d },
+ { 0x00000307, 0x00001e68 }, { 0x00000307, 0x00001e69 },
+ { 0x00000302, 0x00001eac }, { 0x00000306, 0x00001eb6 },
+ { 0x00000302, 0x00001ead }, { 0x00000306, 0x00001eb7 },
+ { 0x00000302, 0x00001ec6 }, { 0x00000302, 0x00001ec7 },
+ { 0x00000302, 0x00001ed8 }, { 0x00000302, 0x00001ed9 },
+ { 0x00000300, 0x00001f02 }, { 0x00000301, 0x00001f04 },
+ { 0x00000342, 0x00001f06 }, { 0x00000345, 0x00001f80 },
+ { 0x00000300, 0x00001f03 }, { 0x00000301, 0x00001f05 },
+ { 0x00000342, 0x00001f07 }, { 0x00000345, 0x00001f81 },
+ { 0x00000345, 0x00001f82 }, { 0x00000345, 0x00001f83 },
+ { 0x00000345, 0x00001f84 }, { 0x00000345, 0x00001f85 },
+ { 0x00000345, 0x00001f86 }, { 0x00000345, 0x00001f87 },
+ { 0x00000300, 0x00001f0a }, { 0x00000301, 0x00001f0c },
+ { 0x00000342, 0x00001f0e }, { 0x00000345, 0x00001f88 },
+ { 0x00000300, 0x00001f0b }, { 0x00000301, 0x00001f0d },
+ { 0x00000342, 0x00001f0f }, { 0x00000345, 0x00001f89 },
+ { 0x00000345, 0x00001f8a }, { 0x00000345, 0x00001f8b },
+ { 0x00000345, 0x00001f8c }, { 0x00000345, 0x00001f8d },
+ { 0x00000345, 0x00001f8e }, { 0x00000345, 0x00001f8f },
+ { 0x00000300, 0x00001f12 }, { 0x00000301, 0x00001f14 },
+ { 0x00000300, 0x00001f13 }, { 0x00000301, 0x00001f15 },
+ { 0x00000300, 0x00001f1a }, { 0x00000301, 0x00001f1c },
+ { 0x00000300, 0x00001f1b }, { 0x00000301, 0x00001f1d },
+ { 0x00000300, 0x00001f22 }, { 0x00000301, 0x00001f24 },
+ { 0x00000342, 0x00001f26 }, { 0x00000345, 0x00001f90 },
+ { 0x00000300, 0x00001f23 }, { 0x00000301, 0x00001f25 },
+ { 0x00000342, 0x00001f27 }, { 0x00000345, 0x00001f91 },
+ { 0x00000345, 0x00001f92 }, { 0x00000345, 0x00001f93 },
+ { 0x00000345, 0x00001f94 }, { 0x00000345, 0x00001f95 },
+ { 0x00000345, 0x00001f96 }, { 0x00000345, 0x00001f97 },
+ { 0x00000300, 0x00001f2a }, { 0x00000301, 0x00001f2c },
+ { 0x00000342, 0x00001f2e }, { 0x00000345, 0x00001f98 },
+ { 0x00000300, 0x00001f2b }, { 0x00000301, 0x00001f2d },
+ { 0x00000342, 0x00001f2f }, { 0x00000345, 0x00001f99 },
+ { 0x00000345, 0x00001f9a }, { 0x00000345, 0x00001f9b },
+ { 0x00000345, 0x00001f9c }, { 0x00000345, 0x00001f9d },
+ { 0x00000345, 0x00001f9e }, { 0x00000345, 0x00001f9f },
+ { 0x00000300, 0x00001f32 }, { 0x00000301, 0x00001f34 },
+ { 0x00000342, 0x00001f36 }, { 0x00000300, 0x00001f33 },
+ { 0x00000301, 0x00001f35 }, { 0x00000342, 0x00001f37 },
+ { 0x00000300, 0x00001f3a }, { 0x00000301, 0x00001f3c },
+ { 0x00000342, 0x00001f3e }, { 0x00000300, 0x00001f3b },
+ { 0x00000301, 0x00001f3d }, { 0x00000342, 0x00001f3f },
+ { 0x00000300, 0x00001f42 }, { 0x00000301, 0x00001f44 },
+ { 0x00000300, 0x00001f43 }, { 0x00000301, 0x00001f45 },
+ { 0x00000300, 0x00001f4a }, { 0x00000301, 0x00001f4c },
+ { 0x00000300, 0x00001f4b }, { 0x00000301, 0x00001f4d },
+ { 0x00000300, 0x00001f52 }, { 0x00000301, 0x00001f54 },
+ { 0x00000342, 0x00001f56 }, { 0x00000300, 0x00001f53 },
+ { 0x00000301, 0x00001f55 }, { 0x00000342, 0x00001f57 },
+ { 0x00000300, 0x00001f5b }, { 0x00000301, 0x00001f5d },
+ { 0x00000342, 0x00001f5f }, { 0x00000300, 0x00001f62 },
+ { 0x00000301, 0x00001f64 }, { 0x00000342, 0x00001f66 },
+ { 0x00000345, 0x00001fa0 }, { 0x00000300, 0x00001f63 },
+ { 0x00000301, 0x00001f65 }, { 0x00000342, 0x00001f67 },
+ { 0x00000345, 0x00001fa1 }, { 0x00000345, 0x00001fa2 },
+ { 0x00000345, 0x00001fa3 }, { 0x00000345, 0x00001fa4 },
+ { 0x00000345, 0x00001fa5 }, { 0x00000345, 0x00001fa6 },
+ { 0x00000345, 0x00001fa7 }, { 0x00000300, 0x00001f6a },
+ { 0x00000301, 0x00001f6c }, { 0x00000342, 0x00001f6e },
+ { 0x00000345, 0x00001fa8 }, { 0x00000300, 0x00001f6b },
+ { 0x00000301, 0x00001f6d }, { 0x00000342, 0x00001f6f },
+ { 0x00000345, 0x00001fa9 }, { 0x00000345, 0x00001faa },
+ { 0x00000345, 0x00001fab }, { 0x00000345, 0x00001fac },
+ { 0x00000345, 0x00001fad }, { 0x00000345, 0x00001fae },
+ { 0x00000345, 0x00001faf }, { 0x00000345, 0x00001fb2 },
+ { 0x00000345, 0x00001fc2 }, { 0x00000345, 0x00001ff2 },
+ { 0x00000345, 0x00001fb7 }, { 0x00000300, 0x00001fcd },
+ { 0x00000301, 0x00001fce }, { 0x00000342, 0x00001fcf },
+ { 0x00000345, 0x00001fc7 }, { 0x00000345, 0x00001ff7 },
+ { 0x00000300, 0x00001fdd }, { 0x00000301, 0x00001fde },
+ { 0x00000342, 0x00001fdf }, { 0x00000338, 0x0000219a },
+ { 0x00000338, 0x0000219b }, { 0x00000338, 0x000021ae },
+ { 0x00000338, 0x000021cd }, { 0x00000338, 0x000021cf },
+ { 0x00000338, 0x000021ce }, { 0x00000338, 0x00002204 },
+ { 0x00000338, 0x00002209 }, { 0x00000338, 0x0000220c },
+ { 0x00000338, 0x00002224 }, { 0x00000338, 0x00002226 },
+ { 0x00000338, 0x00002241 }, { 0x00000338, 0x00002244 },
+ { 0x00000338, 0x00002247 }, { 0x00000338, 0x00002249 },
+ { 0x00000338, 0x0000226d }, { 0x00000338, 0x00002262 },
+ { 0x00000338, 0x00002270 }, { 0x00000338, 0x00002271 },
+ { 0x00000338, 0x00002274 }, { 0x00000338, 0x00002275 },
+ { 0x00000338, 0x00002278 }, { 0x00000338, 0x00002279 },
+ { 0x00000338, 0x00002280 }, { 0x00000338, 0x00002281 },
+ { 0x00000338, 0x000022e0 }, { 0x00000338, 0x000022e1 },
+ { 0x00000338, 0x00002284 }, { 0x00000338, 0x00002285 },
+ { 0x00000338, 0x00002288 }, { 0x00000338, 0x00002289 },
+ { 0x00000338, 0x000022e2 }, { 0x00000338, 0x000022e3 },
+ { 0x00000338, 0x000022ac }, { 0x00000338, 0x000022ad },
+ { 0x00000338, 0x000022ae }, { 0x00000338, 0x000022af },
+ { 0x00000338, 0x000022ea }, { 0x00000338, 0x000022eb },
+ { 0x00000338, 0x000022ec }, { 0x00000338, 0x000022ed },
+ { 0x00003099, 0x00003094 }, { 0x00003099, 0x0000304c },
+ { 0x00003099, 0x0000304e }, { 0x00003099, 0x00003050 },
+ { 0x00003099, 0x00003052 }, { 0x00003099, 0x00003054 },
+ { 0x00003099, 0x00003056 }, { 0x00003099, 0x00003058 },
+ { 0x00003099, 0x0000305a }, { 0x00003099, 0x0000305c },
+ { 0x00003099, 0x0000305e }, { 0x00003099, 0x00003060 },
+ { 0x00003099, 0x00003062 }, { 0x00003099, 0x00003065 },
+ { 0x00003099, 0x00003067 }, { 0x00003099, 0x00003069 },
+ { 0x00003099, 0x00003070 }, { 0x0000309a, 0x00003071 },
+ { 0x00003099, 0x00003073 }, { 0x0000309a, 0x00003074 },
+ { 0x00003099, 0x00003076 }, { 0x0000309a, 0x00003077 },
+ { 0x00003099, 0x00003079 }, { 0x0000309a, 0x0000307a },
+ { 0x00003099, 0x0000307c }, { 0x0000309a, 0x0000307d },
+ { 0x00003099, 0x0000309e }, { 0x00003099, 0x000030f4 },
+ { 0x00003099, 0x000030ac }, { 0x00003099, 0x000030ae },
+ { 0x00003099, 0x000030b0 }, { 0x00003099, 0x000030b2 },
+ { 0x00003099, 0x000030b4 }, { 0x00003099, 0x000030b6 },
+ { 0x00003099, 0x000030b8 }, { 0x00003099, 0x000030ba },
+ { 0x00003099, 0x000030bc }, { 0x00003099, 0x000030be },
+ { 0x00003099, 0x000030c0 }, { 0x00003099, 0x000030c2 },
+ { 0x00003099, 0x000030c5 }, { 0x00003099, 0x000030c7 },
+ { 0x00003099, 0x000030c9 }, { 0x00003099, 0x000030d0 },
+ { 0x0000309a, 0x000030d1 }, { 0x00003099, 0x000030d3 },
+ { 0x0000309a, 0x000030d4 }, { 0x00003099, 0x000030d6 },
+ { 0x0000309a, 0x000030d7 }, { 0x00003099, 0x000030d9 },
+ { 0x0000309a, 0x000030da }, { 0x00003099, 0x000030dc },
+ { 0x0000309a, 0x000030dd }, { 0x00003099, 0x000030f7 },
+ { 0x00003099, 0x000030f8 }, { 0x00003099, 0x000030f9 },
+ { 0x00003099, 0x000030fa }, { 0x00003099, 0x000030fe },
+};
+
+
+/*
+ * Canonical/Compatibility Decomposition
+ */
+
+#define DECOMP_BITS_0 9
+#define DECOMP_BITS_1 7
+#define DECOMP_BITS_2 5
+#define DECOMP_COMPAT 32768
+
+static const unsigned short v320_decompose_imap[] = {
+ 272, 400, 528, 656, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 912,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 1040, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 1168,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 0, 0, 0, 0, 0, 1, 2, 3,
+ 4, 5, 6, 7, 0, 8, 9, 10,
+ 11, 12, 0, 0, 0, 13, 14, 15,
+ 0, 0, 16, 17, 18, 19, 20, 21,
+ 22, 23, 24, 25, 0, 0, 26, 27,
+ 0, 0, 0, 0, 28, 0, 0, 0,
+ 0, 29, 0, 30, 0, 0, 31, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 32, 33, 0, 0, 0, 34, 0,
+ 0, 35, 36, 0, 0, 0, 0, 0,
+ 0, 0, 37, 0, 38, 0, 39, 0,
+ 0, 0, 40, 0, 0, 0, 41, 0,
+ 0, 0, 42, 0, 0, 0, 43, 0,
+ 0, 44, 0, 0, 0, 45, 46, 0,
+ 47, 0, 48, 49, 50, 51, 0, 0,
+ 0, 52, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 73, 74, 0, 0,
+ 75, 76, 77, 78, 79, 80, 81, 0,
+ 82, 83, 84, 85, 86, 87, 0, 88,
+ 0, 89, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 90, 91, 92, 93, 94,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 95, 0, 0, 96, 0, 0, 97, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 98, 0, 0, 99,
+ 100, 101, 102, 103, 104, 105, 106, 0,
+ 107, 108, 109, 110, 111, 112, 113, 114,
+ 0, 115, 116, 117, 118, 0, 0, 0,
+ 119, 120, 121, 122, 123, 124, 125, 126,
+ 127, 128, 129, 130, 131, 132, 133, 134,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 0, 0, 0, 0,
+ 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170,
+ 0, 171, 172, 173, 174, 175, 176, 177,
+ 178, 179, 180, 181, 182, 183, 184, 185,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 186, 187, 0, 188, 189, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 190, 191, 192, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 202, 203, 204, 205,
+ 206, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 220, 221,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 223, 224, 225, 226, 227, 228, 229,
+ 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const struct {
+ unsigned short tbl[32];
+} v320_decompose_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 32769, 0, 0, 0, 0, 0, 0, 0,
+ 32770, 0, 32772, 0, 0, 0, 0, 32773,
+ 0, 0, 32775, 32776, 32777, 32779, 0, 0,
+ 32780, 32782, 32783, 0, 32784, 32787, 32790, 0,
+ }},
+ {{
+ 25, 27, 29, 31, 33, 35, 0, 37,
+ 39, 41, 43, 45, 47, 49, 51, 53,
+ 0, 55, 57, 59, 61, 63, 65, 0,
+ 0, 67, 69, 71, 73, 75, 0, 0,
+ }},
+ {{
+ 77, 79, 81, 83, 85, 87, 0, 89,
+ 91, 93, 95, 97, 99, 101, 103, 105,
+ 0, 107, 109, 111, 113, 115, 117, 0,
+ 0, 119, 121, 123, 125, 127, 0, 129,
+ }},
+ {{
+ 131, 133, 135, 137, 139, 141, 143, 145,
+ 147, 149, 151, 153, 155, 157, 159, 161,
+ 0, 0, 163, 165, 167, 169, 171, 173,
+ 175, 177, 179, 181, 183, 185, 187, 189,
+ }},
+ {{
+ 191, 193, 195, 197, 199, 201, 0, 0,
+ 203, 205, 207, 209, 211, 213, 215, 217,
+ 219, 0, 32989, 32991, 225, 227, 229, 231,
+ 0, 233, 235, 237, 239, 241, 243, 33013,
+ }},
+ {{
+ 33015, 0, 0, 249, 251, 253, 255, 257,
+ 259, 33029, 0, 0, 263, 265, 267, 269,
+ 271, 273, 0, 0, 275, 277, 279, 281,
+ 283, 285, 287, 289, 291, 293, 295, 297,
+ }},
+ {{
+ 299, 301, 303, 305, 307, 309, 0, 0,
+ 311, 313, 315, 317, 319, 321, 323, 325,
+ 327, 329, 331, 333, 335, 337, 339, 341,
+ 343, 345, 347, 349, 351, 353, 355, 33125,
+ }},
+ {{
+ 358, 360, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 362,
+ 364, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 33134, 33136, 33138, 33140,
+ 33142, 33144, 33146, 33148, 33150, 384, 386, 388,
+ 390, 392, 394, 396, 398, 400, 402, 404,
+ 406, 408, 410, 412, 414, 0, 416, 418,
+ }},
+ {{
+ 420, 422, 424, 426, 0, 0, 428, 430,
+ 432, 434, 436, 438, 440, 442, 444, 446,
+ 448, 33218, 33220, 33222, 456, 458, 0, 0,
+ 460, 462, 464, 466, 468, 470, 472, 474,
+ }},
+ {{
+ 476, 478, 480, 482, 484, 486, 488, 490,
+ 492, 494, 496, 498, 500, 502, 504, 506,
+ 508, 510, 512, 514, 516, 518, 520, 522,
+ 524, 526, 528, 530, 0, 0, 532, 534,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 536, 538,
+ 540, 542, 544, 546, 548, 550, 552, 554,
+ 556, 558, 560, 562, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 33332, 33333, 33334, 33335, 33336, 33337, 33338, 33339,
+ 33340, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 33341, 33343, 33345, 33347, 33349, 33351, 0, 0,
+ }},
+ {{
+ 33353, 33354, 33355, 33356, 33357, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 590, 591, 0, 592, 593, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 595, 0, 0, 0,
+ 0, 0, 33364, 0, 0, 0, 598, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 33367, 601, 603, 605,
+ 606, 608, 610, 0, 612, 0, 614, 616,
+ 618, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 620, 622, 624, 626, 628, 630,
+ 632, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 634, 636, 638, 640, 642, 0,
+ 33412, 33413, 33414, 647, 649, 33419, 33420, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 33421, 33422, 33423, 0, 33424, 33425, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 658, 660, 0, 662, 0, 0, 0, 664,
+ 0, 0, 0, 0, 666, 668, 670, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 672, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 674, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 676, 678, 0, 680, 0, 0, 0, 682,
+ 0, 0, 0, 0, 684, 686, 688, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 690, 692,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 694, 696, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 698, 700, 702, 704, 0, 0, 706, 708,
+ 0, 0, 710, 712, 714, 716, 718, 720,
+ }},
+ {{
+ 0, 0, 722, 724, 726, 728, 730, 732,
+ 0, 0, 734, 736, 738, 740, 742, 744,
+ 746, 748, 750, 752, 754, 756, 0, 0,
+ 758, 760, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 33530,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 764, 766, 768, 770, 772, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 33542, 33544, 33546,
+ 33548, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 782, 0, 784, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 786, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 788, 0, 0, 0, 0, 0, 0,
+ 0, 790, 0, 0, 792, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 794, 796, 798, 800, 802, 804, 806, 808,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 810, 812, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 814, 816, 0, 818,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 820, 0, 0, 822, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 824, 826, 828, 0, 0, 830, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 832, 0, 0, 834, 836, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 838, 840, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 842, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 844, 846, 848, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 850, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 852, 0, 0, 0, 0, 0, 0, 854,
+ 856, 0, 858, 860, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 862, 864, 866, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 868, 0, 870, 872, 874, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 33644, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 33646, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 33648, 33650, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 33652, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 885, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 887, 0, 0,
+ 0, 0, 889, 0, 0, 0, 0, 891,
+ 0, 0, 0, 0, 893, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 895, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 897, 0, 899, 901, 33671,
+ 905, 33675, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 909, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 911, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 913, 0, 0,
+ }},
+ {{
+ 0, 0, 915, 0, 0, 0, 0, 917,
+ 0, 0, 0, 0, 919, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 921, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 923, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 925, 927, 929, 931, 933, 935, 937, 939,
+ 941, 943, 945, 947, 949, 951, 953, 955,
+ 957, 959, 961, 963, 965, 967, 969, 971,
+ 973, 975, 977, 979, 981, 983, 985, 987,
+ }},
+ {{
+ 989, 991, 993, 995, 997, 999, 1001, 1003,
+ 1005, 1007, 1009, 1011, 1013, 1015, 1017, 1019,
+ 1021, 1023, 1025, 1027, 1029, 1031, 1033, 1035,
+ 1037, 1039, 1041, 1043, 1045, 1047, 1049, 1051,
+ }},
+ {{
+ 1053, 1055, 1057, 1059, 1061, 1063, 1065, 1067,
+ 1069, 1071, 1073, 1075, 1077, 1079, 1081, 1083,
+ 1085, 1087, 1089, 1091, 1093, 1095, 1097, 1099,
+ 1101, 1103, 1105, 1107, 1109, 1111, 1113, 1115,
+ }},
+ {{
+ 1117, 1119, 1121, 1123, 1125, 1127, 1129, 1131,
+ 1133, 1135, 1137, 1139, 1141, 1143, 1145, 1147,
+ 1149, 1151, 1153, 1155, 1157, 1159, 1161, 1163,
+ 1165, 1167, 1169, 1171, 1173, 1175, 1177, 1179,
+ }},
+ {{
+ 1181, 1183, 1185, 1187, 1189, 1191, 1193, 1195,
+ 1197, 1199, 1201, 1203, 1205, 1207, 1209, 1211,
+ 1213, 1215, 1217, 1219, 1221, 1223, 1225, 1227,
+ 1229, 1231, 34001, 1235, 0, 0, 0, 0,
+ }},
+ {{
+ 1237, 1239, 1241, 1243, 1245, 1247, 1249, 1251,
+ 1253, 1255, 1257, 1259, 1261, 1263, 1265, 1267,
+ 1269, 1271, 1273, 1275, 1277, 1279, 1281, 1283,
+ 1285, 1287, 1289, 1291, 1293, 1295, 1297, 1299,
+ }},
+ {{
+ 1301, 1303, 1305, 1307, 1309, 1311, 1313, 1315,
+ 1317, 1319, 1321, 1323, 1325, 1327, 1329, 1331,
+ 1333, 1335, 1337, 1339, 1341, 1343, 1345, 1347,
+ 1349, 1351, 1353, 1355, 1357, 1359, 1361, 1363,
+ }},
+ {{
+ 1365, 1367, 1369, 1371, 1373, 1375, 1377, 1379,
+ 1381, 1383, 1385, 1387, 1389, 1391, 1393, 1395,
+ 1397, 1399, 1401, 1403, 1405, 1407, 1409, 1411,
+ 1413, 1415, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1417, 1419, 1421, 1423, 1425, 1427, 1429, 1431,
+ 1433, 1435, 1437, 1439, 1441, 1443, 1445, 1447,
+ 1449, 1451, 1453, 1455, 1457, 1459, 0, 0,
+ 1461, 1463, 1465, 1467, 1469, 1471, 0, 0,
+ }},
+ {{
+ 1473, 1475, 1477, 1479, 1481, 1483, 1485, 1487,
+ 1489, 1491, 1493, 1495, 1497, 1499, 1501, 1503,
+ 1505, 1507, 1509, 1511, 1513, 1515, 1517, 1519,
+ 1521, 1523, 1525, 1527, 1529, 1531, 1533, 1535,
+ }},
+ {{
+ 1537, 1539, 1541, 1543, 1545, 1547, 0, 0,
+ 1549, 1551, 1553, 1555, 1557, 1559, 0, 0,
+ 1561, 1563, 1565, 1567, 1569, 1571, 1573, 1575,
+ 0, 1577, 0, 1579, 0, 1581, 0, 1583,
+ }},
+ {{
+ 1585, 1587, 1589, 1591, 1593, 1595, 1597, 1599,
+ 1601, 1603, 1605, 1607, 1609, 1611, 1613, 1615,
+ 1617, 1619, 1620, 1622, 1623, 1625, 1626, 1628,
+ 1629, 1631, 1632, 1634, 1635, 1637, 0, 0,
+ }},
+ {{
+ 1638, 1640, 1642, 1644, 1646, 1648, 1650, 1652,
+ 1654, 1656, 1658, 1660, 1662, 1664, 1666, 1668,
+ 1670, 1672, 1674, 1676, 1678, 1680, 1682, 1684,
+ 1686, 1688, 1690, 1692, 1694, 1696, 1698, 1700,
+ }},
+ {{
+ 1702, 1704, 1706, 1708, 1710, 1712, 1714, 1716,
+ 1718, 1720, 1722, 1724, 1726, 1728, 1730, 1732,
+ 1734, 1736, 1738, 1740, 1742, 0, 1744, 1746,
+ 1748, 1750, 1752, 1754, 1755, 34525, 1759, 34528,
+ }},
+ {{
+ 34530, 1764, 1766, 1768, 1770, 0, 1772, 1774,
+ 1776, 1778, 1779, 1781, 1782, 1784, 1786, 1788,
+ 1790, 1792, 1794, 1796, 0, 0, 1797, 1799,
+ 1801, 1803, 1805, 1807, 0, 1808, 1810, 1812,
+ }},
+ {{
+ 1814, 1816, 1818, 1820, 1821, 1823, 1825, 1827,
+ 1829, 1831, 1833, 1835, 1836, 1838, 1840, 1841,
+ 0, 0, 1842, 1844, 1846, 0, 1848, 1850,
+ 1852, 1854, 1855, 1857, 1858, 1860, 34629, 0,
+ }},
+ {{
+ 1863, 1864, 34633, 34634, 34635, 34636, 34637, 34638,
+ 34639, 34640, 34641, 0, 0, 0, 0, 0,
+ 0, 34642, 0, 0, 0, 0, 0, 34643,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 34645, 34646, 34648, 0,
+ 0, 0, 0, 0, 0, 0, 0, 34651,
+ 0, 0, 0, 34652, 34654, 0, 34657, 34659,
+ 0, 0, 0, 0, 34662, 0, 34664, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 34666,
+ 34668, 34670, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 34672,
+ 0, 0, 0, 0, 0, 0, 0, 34676,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 34677, 34678, 0, 0, 34679, 34680, 34681, 34682,
+ 34683, 34684, 34685, 34686, 34687, 34688, 34689, 34690,
+ }},
+ {{
+ 34691, 34692, 34693, 34694, 34695, 34696, 34697, 34698,
+ 34699, 34700, 34701, 34702, 34703, 34704, 34705, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 34706, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 34708, 34711, 34714, 34715, 0, 34717, 34720, 34723,
+ 0, 34724, 34726, 34727, 34728, 34729, 34730, 34731,
+ 34732, 34733, 34734, 34735, 0, 34736, 34737, 0,
+ 0, 34739, 34740, 34741, 34742, 34743, 0, 0,
+ }},
+ {{
+ 34744, 34746, 34749, 0, 34751, 0, 1984, 0,
+ 34753, 0, 1986, 1987, 34756, 34757, 0, 34758,
+ 34759, 34760, 0, 34761, 34762, 34763, 34764, 34765,
+ 34766, 34767, 0, 0, 0, 34768, 34769, 34770,
+ }},
+ {{
+ 34771, 0, 0, 0, 0, 34772, 34773, 34774,
+ 34775, 34776, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 34777, 34780, 34783, 34786, 34789,
+ 34792, 34795, 34798, 34801, 34804, 34807, 34810, 34813,
+ }},
+ {{
+ 34815, 34816, 34818, 34821, 34823, 34824, 34826, 34829,
+ 34833, 34835, 34836, 34838, 34841, 34842, 34843, 34844,
+ 34845, 34846, 34848, 34851, 34853, 34854, 34856, 34859,
+ 34863, 34865, 34866, 34868, 34871, 34872, 34873, 34874,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2107, 2109, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2111, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2113, 2115, 2117,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 2119, 0, 0, 0,
+ 0, 2121, 0, 0, 2123, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 2125, 0, 2127, 0,
+ 0, 0, 0, 0, 34897, 34899, 0, 34902,
+ 34904, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2139, 0, 0, 2141, 0, 0, 2143,
+ 0, 2145, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2147, 0, 2149, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2151, 2153, 2155,
+ 2157, 2159, 0, 0, 2161, 2163, 0, 0,
+ 2165, 2167, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2169, 2171, 0, 0, 2173, 2175, 0, 0,
+ 2177, 2179, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2181, 2183, 2185, 2187,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2189, 2191, 2193, 2195, 0, 0, 0, 0,
+ 0, 0, 2197, 2199, 2201, 2203, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2205, 2206, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 34975, 34976, 34977, 34978, 34979, 34980, 34981, 34982,
+ 34983, 34984, 34986, 34988, 34990, 34992, 34994, 34996,
+ 34998, 35000, 35002, 35004, 35006, 35009, 35012, 35015,
+ 35018, 35021, 35024, 35027, 35030, 35033, 35037, 35041,
+ }},
+ {{
+ 35045, 35049, 35053, 35057, 35061, 35065, 35069, 35073,
+ 35077, 35079, 35081, 35083, 35085, 35087, 35089, 35091,
+ 35093, 35095, 35098, 35101, 35104, 35107, 35110, 35113,
+ 35116, 35119, 35122, 35125, 35128, 35131, 35134, 35137,
+ }},
+ {{
+ 35140, 35143, 35146, 35149, 35152, 35155, 35158, 35161,
+ 35164, 35167, 35170, 35173, 35176, 35179, 35182, 35185,
+ 35188, 35191, 35194, 35197, 35200, 35203, 35206, 35207,
+ 35208, 35209, 35210, 35211, 35212, 35213, 35214, 35215,
+ }},
+ {{
+ 35216, 35217, 35218, 35219, 35220, 35221, 35222, 35223,
+ 35224, 35225, 35226, 35227, 35228, 35229, 35230, 35231,
+ 35232, 35233, 35234, 35235, 35236, 35237, 35238, 35239,
+ 35240, 35241, 35242, 35243, 35244, 35245, 35246, 35247,
+ }},
+ {{
+ 35248, 35249, 35250, 35251, 35252, 35253, 35254, 35255,
+ 35256, 35257, 35258, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 35259, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 35263, 35266, 35268, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2503, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 35273,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 35274, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 35275, 35276, 35277, 35278, 35279, 35280, 35281, 35282,
+ 35283, 35284, 35285, 35286, 35287, 35288, 35289, 35290,
+ 35291, 35292, 35293, 35294, 35295, 35296, 35297, 35298,
+ 35299, 35300, 35301, 35302, 35303, 35304, 35305, 35306,
+ }},
+ {{
+ 35307, 35308, 35309, 35310, 35311, 35312, 35313, 35314,
+ 35315, 35316, 35317, 35318, 35319, 35320, 35321, 35322,
+ 35323, 35324, 35325, 35326, 35327, 35328, 35329, 35330,
+ 35331, 35332, 35333, 35334, 35335, 35336, 35337, 35338,
+ }},
+ {{
+ 35339, 35340, 35341, 35342, 35343, 35344, 35345, 35346,
+ 35347, 35348, 35349, 35350, 35351, 35352, 35353, 35354,
+ 35355, 35356, 35357, 35358, 35359, 35360, 35361, 35362,
+ 35363, 35364, 35365, 35366, 35367, 35368, 35369, 35370,
+ }},
+ {{
+ 35371, 35372, 35373, 35374, 35375, 35376, 35377, 35378,
+ 35379, 35380, 35381, 35382, 35383, 35384, 35385, 35386,
+ 35387, 35388, 35389, 35390, 35391, 35392, 35393, 35394,
+ 35395, 35396, 35397, 35398, 35399, 35400, 35401, 35402,
+ }},
+ {{
+ 35403, 35404, 35405, 35406, 35407, 35408, 35409, 35410,
+ 35411, 35412, 35413, 35414, 35415, 35416, 35417, 35418,
+ 35419, 35420, 35421, 35422, 35423, 35424, 35425, 35426,
+ 35427, 35428, 35429, 35430, 35431, 35432, 35433, 35434,
+ }},
+ {{
+ 35435, 35436, 35437, 35438, 35439, 35440, 35441, 35442,
+ 35443, 35444, 35445, 35446, 35447, 35448, 35449, 35450,
+ 35451, 35452, 35453, 35454, 35455, 35456, 35457, 35458,
+ 35459, 35460, 35461, 35462, 35463, 35464, 35465, 35466,
+ }},
+ {{
+ 35467, 35468, 35469, 35470, 35471, 35472, 35473, 35474,
+ 35475, 35476, 35477, 35478, 35479, 35480, 35481, 35482,
+ 35483, 35484, 35485, 35486, 35487, 35488, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 35489, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 35490, 0,
+ 35491, 35492, 35493, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2726, 0, 2728, 0,
+ 2730, 0, 2732, 0, 2734, 0, 2736, 0,
+ 2738, 0, 2740, 0, 2742, 0, 2744, 0,
+ }},
+ {{
+ 2746, 0, 2748, 0, 0, 2750, 0, 2752,
+ 0, 2754, 0, 0, 0, 0, 0, 0,
+ 2756, 2758, 0, 2760, 2762, 0, 2764, 2766,
+ 0, 2768, 2770, 0, 2772, 2774, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2776, 0, 0, 0,
+ 0, 0, 0, 35546, 35548, 0, 2782, 35552,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2786, 0, 2788, 0,
+ 2790, 0, 2792, 0, 2794, 0, 2796, 0,
+ 2798, 0, 2800, 0, 2802, 0, 2804, 0,
+ }},
+ {{
+ 2806, 0, 2808, 0, 0, 2810, 0, 2812,
+ 0, 2814, 0, 0, 0, 0, 0, 0,
+ 2816, 2818, 0, 2820, 2822, 0, 2824, 2826,
+ 0, 2828, 2830, 0, 2832, 2834, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2836, 0, 0, 2838,
+ 2840, 2842, 2844, 0, 0, 0, 2846, 35616,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 35618, 35619, 35620, 35621, 35622, 35623, 35624,
+ 35625, 35626, 35627, 35628, 35629, 35630, 35631, 35632,
+ }},
+ {{
+ 35633, 35634, 35635, 35636, 35637, 35638, 35639, 35640,
+ 35641, 35642, 35643, 35644, 35645, 35646, 35647, 35648,
+ 35649, 35650, 35651, 35652, 35653, 35654, 35655, 35656,
+ 35657, 35658, 35659, 35660, 35661, 35662, 35663, 35664,
+ }},
+ {{
+ 35665, 35666, 35667, 35668, 35669, 35670, 35671, 35672,
+ 35673, 35674, 35675, 35676, 35677, 35678, 35679, 35680,
+ 35681, 35682, 35683, 35684, 35685, 35686, 35687, 35688,
+ 35689, 35690, 35691, 35692, 35693, 35694, 35695, 35696,
+ }},
+ {{
+ 35697, 35698, 35699, 35700, 35701, 35702, 35703, 35704,
+ 35705, 35706, 35707, 35708, 35709, 35710, 35711, 0,
+ 0, 0, 35712, 35713, 35714, 35715, 35716, 35717,
+ 35718, 35719, 35720, 35721, 35722, 35723, 35724, 35725,
+ }},
+ {{
+ 35726, 35729, 35732, 35735, 35738, 35741, 35744, 35747,
+ 35750, 35753, 35756, 35759, 35762, 35765, 35768, 35772,
+ 35776, 35780, 35784, 35788, 35792, 35796, 35800, 35804,
+ 35808, 35812, 35816, 35820, 35824, 0, 0, 0,
+ }},
+ {{
+ 35828, 35831, 35834, 35837, 35840, 35843, 35846, 35849,
+ 35852, 35855, 35858, 35861, 35864, 35867, 35870, 35873,
+ 35876, 35879, 35882, 35885, 35888, 35891, 35894, 35897,
+ 35900, 35903, 35906, 35909, 35912, 35915, 35918, 35921,
+ }},
+ {{
+ 35924, 35927, 35930, 35933, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 35936, 35938, 35940, 35942, 35944, 35946, 35948,
+ 35950, 35952, 35954, 35956, 35958, 35960, 35962, 35964,
+ }},
+ {{
+ 35966, 35967, 35968, 35969, 35970, 35971, 35972, 35973,
+ 35974, 35975, 35976, 35977, 35978, 35979, 35980, 35982,
+ 35984, 35986, 35988, 35990, 35992, 35994, 35996, 35998,
+ 36000, 36002, 36004, 36006, 0, 0, 0, 0,
+ }},
+ {{
+ 36008, 36009, 36010, 36011, 36012, 36013, 36014, 36015,
+ 36016, 36017, 36018, 36019, 36020, 36021, 36022, 36023,
+ 36024, 36025, 36026, 36027, 36028, 36029, 36030, 36031,
+ 36032, 36033, 36034, 36035, 36036, 36037, 36038, 36039,
+ }},
+ {{
+ 36040, 36041, 36042, 36043, 36044, 36045, 36046, 36047,
+ 36048, 36049, 36050, 36051, 36052, 36053, 36054, 36055,
+ 36056, 36057, 36059, 36061, 36063, 36065, 36067, 36069,
+ 36071, 36073, 36075, 36077, 36079, 36081, 36083, 36085,
+ }},
+ {{
+ 36087, 36089, 36091, 36093, 36095, 36097, 36099, 36101,
+ 36103, 36105, 36108, 36111, 0, 0, 0, 0,
+ 36114, 36115, 36116, 36117, 36118, 36119, 36120, 36121,
+ 36122, 36123, 36124, 36125, 36126, 36127, 36128, 36129,
+ }},
+ {{
+ 36130, 36131, 36132, 36133, 36134, 36135, 36136, 36137,
+ 36138, 36139, 36140, 36141, 36142, 36143, 36144, 36145,
+ 36146, 36147, 36148, 36149, 36150, 36151, 36152, 36153,
+ 36154, 36155, 36156, 36157, 36158, 36159, 36160, 0,
+ }},
+ {{
+ 36161, 36165, 36169, 36173, 36176, 36180, 36183, 36186,
+ 36191, 36195, 36198, 36201, 36204, 36208, 36212, 36215,
+ 36218, 36220, 36223, 36227, 36231, 36233, 36238, 36244,
+ 36249, 36252, 36257, 36262, 36266, 36269, 36272, 36275,
+ }},
+ {{
+ 36279, 36284, 36288, 36291, 36294, 36297, 36299, 36301,
+ 36303, 36305, 36308, 36311, 36316, 36319, 36323, 36328,
+ 36331, 36333, 36335, 36340, 36344, 36349, 36352, 36357,
+ 36359, 36362, 36365, 36368, 36371, 36374, 36378, 36381,
+ }},
+ {{
+ 36383, 36386, 36389, 36392, 36396, 36399, 36402, 36405,
+ 36410, 36414, 36416, 36421, 36423, 36427, 36431, 36434,
+ 36437, 36440, 36444, 36446, 36449, 36453, 36455, 36460,
+ 36463, 36465, 36467, 36469, 36471, 36473, 36475, 36477,
+ }},
+ {{
+ 36479, 36481, 36483, 36486, 36489, 36492, 36495, 36498,
+ 36501, 36504, 36507, 36510, 36513, 36516, 36519, 36522,
+ 36525, 36528, 36531, 36533, 36535, 36538, 36540, 0,
+ 0, 0, 0, 36542, 36544, 36546, 36548, 36550,
+ }},
+ {{
+ 36554, 36556, 36558, 36560, 36562, 36564, 36566, 36568,
+ 36570, 36573, 36577, 36579, 36581, 36583, 36585, 36587,
+ 36589, 36591, 36594, 36597, 36600, 36603, 36605, 36607,
+ 36609, 36611, 36613, 36615, 36617, 36619, 36621, 36623,
+ }},
+ {{
+ 36626, 36629, 36631, 36634, 36637, 36640, 36642, 36645,
+ 36648, 36652, 36654, 36657, 36660, 36663, 36666, 36671,
+ 36677, 36679, 36681, 36683, 36685, 36687, 36689, 36691,
+ 36693, 36695, 36697, 36699, 36701, 36703, 36705, 36707,
+ }},
+ {{
+ 36709, 36711, 36713, 36717, 36719, 36721, 36723, 36727,
+ 36730, 36732, 36734, 36736, 36738, 36740, 36742, 36744,
+ 36746, 36748, 36750, 36753, 36755, 36757, 36760, 36763,
+ 36765, 36769, 36772, 36774, 36776, 36778, 0, 0,
+ }},
+ {{
+ 36780, 36782, 36784, 36786, 36788, 36790, 36792, 36794,
+ 36796, 36798, 36801, 36804, 36807, 36810, 36813, 36816,
+ 36819, 36822, 36825, 36828, 36831, 36834, 36837, 36840,
+ 36843, 36846, 36849, 36852, 36855, 36858, 36861, 0,
+ }},
+ {{
+ 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103,
+ 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111,
+ 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119,
+ 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127,
+ }},
+ {{
+ 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135,
+ 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143,
+ 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151,
+ 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159,
+ }},
+ {{
+ 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167,
+ 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175,
+ 4176, 4177, 4178, 4179, 4180, 4181, 4182, 4183,
+ 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191,
+ }},
+ {{
+ 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199,
+ 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207,
+ 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215,
+ 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223,
+ }},
+ {{
+ 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231,
+ 4232, 4233, 4234, 4235, 4236, 4237, 4238, 4239,
+ 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247,
+ 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255,
+ }},
+ {{
+ 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263,
+ 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271,
+ 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279,
+ 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287,
+ }},
+ {{
+ 4288, 4289, 4290, 4291, 4292, 4293, 4294, 4295,
+ 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303,
+ 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311,
+ 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319,
+ }},
+ {{
+ 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327,
+ 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335,
+ 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343,
+ 4344, 4345, 4346, 4347, 4348, 4349, 4350, 4351,
+ }},
+ {{
+ 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359,
+ 4360, 4361, 4362, 4363, 4364, 4365, 0, 0,
+ 4366, 0, 4367, 0, 0, 4368, 4369, 4370,
+ 4371, 4372, 4373, 4374, 4375, 4376, 4377, 0,
+ }},
+ {{
+ 4378, 0, 4379, 0, 0, 4380, 4381, 0,
+ 0, 0, 4382, 4383, 4384, 4385, 0, 0,
+ 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393,
+ 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401,
+ }},
+ {{
+ 4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409,
+ 4410, 4411, 4412, 4413, 4414, 4415, 4416, 4417,
+ 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425,
+ 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433,
+ }},
+ {{
+ 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441,
+ 4442, 4443, 4444, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 37213, 37215, 37217, 37219, 37222, 37225, 37227, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 37229, 37231, 37233, 37235, 37237,
+ 0, 0, 0, 0, 0, 4471, 0, 4473,
+ }},
+ {{
+ 37243, 37244, 37245, 37246, 37247, 37248, 37249, 37250,
+ 37251, 37252, 4485, 4487, 4489, 4491, 4493, 4495,
+ 4497, 4499, 4501, 4503, 4505, 4507, 4509, 0,
+ 4511, 4513, 4515, 4517, 4519, 0, 4521, 0,
+ }},
+ {{
+ 4523, 4525, 0, 4527, 4529, 0, 4531, 4533,
+ 4535, 4537, 4539, 4541, 4543, 4545, 4547, 37317,
+ 37319, 37320, 37321, 37322, 37323, 37324, 37325, 37326,
+ 37327, 37328, 37329, 37330, 37331, 37332, 37333, 37334,
+ }},
+ {{
+ 37335, 37336, 37337, 37338, 37339, 37340, 37341, 37342,
+ 37343, 37344, 37345, 37346, 37347, 37348, 37349, 37350,
+ 37351, 37352, 37353, 37354, 37355, 37356, 37357, 37358,
+ 37359, 37360, 37361, 37362, 37363, 37364, 37365, 37366,
+ }},
+ {{
+ 37367, 37368, 37369, 37370, 37371, 37372, 37373, 37374,
+ 37375, 37376, 37377, 37378, 37379, 37380, 37381, 37382,
+ 37383, 37384, 37385, 37386, 37387, 37388, 37389, 37390,
+ 37391, 37392, 37393, 37394, 37395, 37396, 37397, 37398,
+ }},
+ {{
+ 37399, 37400, 37401, 37402, 37403, 37404, 37405, 37406,
+ 37407, 37408, 37409, 37410, 37411, 37412, 37413, 37414,
+ 37415, 37416, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 37417, 37418, 37419, 37420, 37421,
+ 37422, 37423, 37424, 37425, 37426, 37427, 37428, 37429,
+ }},
+ {{
+ 37430, 37431, 37432, 37433, 37434, 37435, 37436, 37437,
+ 37438, 37439, 37440, 37442, 37444, 37446, 37448, 37450,
+ 37452, 37454, 37456, 37458, 37460, 37462, 37464, 37466,
+ 37468, 37470, 37472, 37474, 37476, 37477, 37478, 37479,
+ }},
+ {{
+ 37480, 37482, 37484, 37486, 37488, 37490, 37492, 37494,
+ 37496, 37498, 37500, 37502, 37504, 37506, 37508, 37510,
+ 37512, 37514, 37516, 37518, 37520, 37522, 37524, 37526,
+ 37528, 37530, 37532, 37534, 37536, 37538, 37540, 37542,
+ }},
+ {{
+ 37544, 37546, 37548, 37550, 37552, 37554, 37556, 37558,
+ 37560, 37562, 37564, 37566, 37568, 37570, 37572, 37574,
+ 37576, 37578, 37580, 37582, 37584, 37586, 37588, 37590,
+ 37592, 37594, 37596, 37598, 37600, 37602, 37604, 37606,
+ }},
+ {{
+ 37608, 37610, 37612, 37614, 37616, 37618, 37620, 37622,
+ 37624, 37626, 37628, 37630, 37632, 37634, 37636, 37638,
+ 37640, 37642, 37644, 37646, 37648, 37650, 37652, 37654,
+ 37656, 37658, 37660, 37662, 37664, 37666, 37668, 37671,
+ }},
+ {{
+ 37674, 37677, 37680, 37683, 37686, 37688, 37690, 37692,
+ 37694, 37696, 37698, 37700, 37702, 37704, 37706, 37708,
+ 37710, 37712, 37714, 37716, 37718, 37720, 37722, 37724,
+ 37726, 37728, 37730, 37732, 37734, 37736, 37738, 37740,
+ }},
+ {{
+ 37742, 37744, 37746, 37748, 37750, 37752, 37754, 37756,
+ 37758, 37760, 37762, 37764, 37766, 37768, 37770, 37772,
+ 37774, 37776, 37778, 37780, 37782, 37784, 37786, 37788,
+ 37790, 37792, 37794, 37796, 37798, 37800, 37802, 37804,
+ }},
+ {{
+ 37806, 37808, 37810, 37812, 37814, 37816, 37818, 37820,
+ 37822, 37824, 37826, 37828, 37830, 37832, 37834, 37836,
+ 37838, 37840, 37842, 37844, 37846, 37848, 37850, 37852,
+ 37854, 37856, 37858, 37860, 37862, 37864, 37866, 37868,
+ }},
+ {{
+ 37870, 37872, 37874, 37876, 37878, 37880, 37882, 37884,
+ 37886, 37888, 37890, 37892, 37894, 37896, 37898, 37900,
+ 37902, 37904, 37906, 37908, 37910, 37912, 37914, 37916,
+ 37918, 37920, 37922, 37924, 37926, 37928, 37930, 37932,
+ }},
+ {{
+ 37934, 37936, 37938, 37940, 37942, 37944, 37946, 37948,
+ 37950, 37952, 37954, 37956, 37958, 37960, 37962, 37964,
+ 37966, 37968, 37970, 37973, 37976, 37979, 37981, 37983,
+ 37985, 37987, 37989, 37991, 37993, 37995, 37997, 37999,
+ }},
+ {{
+ 38001, 38003, 38005, 38007, 38009, 38011, 38013, 38015,
+ 38017, 38019, 38021, 38023, 38025, 38027, 38029, 38031,
+ 38033, 38035, 38037, 38039, 38041, 38043, 38045, 38047,
+ 38049, 38051, 38053, 38055, 38057, 38059, 38061, 38063,
+ }},
+ {{
+ 38065, 38067, 38069, 38071, 38073, 38075, 38077, 38079,
+ 38081, 38083, 38085, 38087, 38089, 38091, 38093, 38095,
+ 38097, 38099, 38101, 38103, 38105, 38107, 38109, 38111,
+ 38113, 38115, 38117, 38119, 38121, 38123, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 38125, 38128, 38131, 38134, 38137, 38140, 38143, 38146,
+ 38149, 38152, 38155, 38158, 38161, 38164, 38167, 38170,
+ }},
+ {{
+ 38173, 38176, 38179, 38182, 38185, 38188, 38191, 38194,
+ 38197, 38200, 38203, 38206, 38209, 38212, 38215, 38218,
+ 38221, 38224, 38227, 38230, 38233, 38236, 38239, 38242,
+ 38245, 38248, 38251, 38254, 38257, 38260, 38263, 38266,
+ }},
+ {{
+ 38269, 38272, 38275, 38278, 38281, 38284, 38287, 38290,
+ 38293, 38296, 38299, 38302, 38305, 38308, 38311, 38314,
+ 0, 0, 38317, 38320, 38323, 38326, 38329, 38332,
+ 38335, 38338, 38341, 38344, 38347, 38350, 38353, 38356,
+ }},
+ {{
+ 38359, 38362, 38365, 38368, 38371, 38374, 38377, 38380,
+ 38383, 38386, 38389, 38392, 38395, 38398, 38401, 38404,
+ 38407, 38410, 38413, 38416, 38419, 38422, 38425, 38428,
+ 38431, 38434, 38437, 38440, 38443, 38446, 38449, 38452,
+ }},
+ {{
+ 38455, 38458, 38461, 38464, 38467, 38470, 38473, 38476,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 38479, 38482, 38485, 38489, 38493, 38497, 38501, 38505,
+ 38509, 38513, 38516, 38534, 38542, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 38546, 38547, 38548, 38549, 38550, 38551, 38552, 38553,
+ 38554, 38555, 38556, 38557, 38558, 38559, 38560, 38561,
+ }},
+ {{
+ 38562, 38563, 38564, 38565, 38566, 0, 0, 0,
+ 0, 38567, 38568, 38569, 38570, 38571, 38572, 38573,
+ 38574, 38575, 38576, 0, 38577, 38578, 38579, 38580,
+ 38581, 38582, 38583, 38584, 38585, 38586, 38587, 38588,
+ }},
+ {{
+ 38589, 38590, 38591, 38592, 38593, 38594, 38595, 0,
+ 38596, 38597, 38598, 38599, 0, 0, 0, 0,
+ 38600, 38602, 38604, 0, 38606, 0, 38608, 38610,
+ 38612, 38614, 38616, 38618, 38620, 38622, 38624, 38626,
+ }},
+ {{
+ 38628, 38629, 38630, 38631, 38632, 38633, 38634, 38635,
+ 38636, 38637, 38638, 38639, 38640, 38641, 38642, 38643,
+ 38644, 38645, 38646, 38647, 38648, 38649, 38650, 38651,
+ 38652, 38653, 38654, 38655, 38656, 38657, 38658, 38659,
+ }},
+ {{
+ 38660, 38661, 38662, 38663, 38664, 38665, 38666, 38667,
+ 38668, 38669, 38670, 38671, 38672, 38673, 38674, 38675,
+ 38676, 38677, 38678, 38679, 38680, 38681, 38682, 38683,
+ 38684, 38685, 38686, 38687, 38688, 38689, 38690, 38691,
+ }},
+ {{
+ 38692, 38693, 38694, 38695, 38696, 38697, 38698, 38699,
+ 38700, 38701, 38702, 38703, 38704, 38705, 38706, 38707,
+ 38708, 38709, 38710, 38711, 38712, 38713, 38714, 38715,
+ 38716, 38717, 38718, 38719, 38720, 38721, 38722, 38723,
+ }},
+ {{
+ 38724, 38725, 38726, 38727, 38728, 38729, 38730, 38731,
+ 38732, 38733, 38734, 38735, 38736, 38737, 38738, 38739,
+ 38740, 38741, 38742, 38743, 38744, 38745, 38747, 38749,
+ 38751, 38753, 38755, 38757, 38759, 0, 0, 0,
+ }},
+ {{
+ 0, 38761, 38762, 38763, 38764, 38765, 38766, 38767,
+ 38768, 38769, 38770, 38771, 38772, 38773, 38774, 38775,
+ 38776, 38777, 38778, 38779, 38780, 38781, 38782, 38783,
+ 38784, 38785, 38786, 38787, 38788, 38789, 38790, 38791,
+ }},
+ {{
+ 38792, 38793, 38794, 38795, 38796, 38797, 38798, 38799,
+ 38800, 38801, 38802, 38803, 38804, 38805, 38806, 38807,
+ 38808, 38809, 38810, 38811, 38812, 38813, 38814, 38815,
+ 38816, 38817, 38818, 38819, 38820, 38821, 38822, 38823,
+ }},
+ {{
+ 38824, 38825, 38826, 38827, 38828, 38829, 38830, 38831,
+ 38832, 38833, 38834, 38835, 38836, 38837, 38838, 38839,
+ 38840, 38841, 38842, 38843, 38844, 38845, 38846, 38847,
+ 38848, 38849, 38850, 38851, 38852, 38853, 38854, 38855,
+ }},
+ {{
+ 38856, 38857, 38858, 38859, 38860, 38861, 38862, 38863,
+ 38864, 38865, 38866, 38867, 38868, 38869, 38870, 38871,
+ 38872, 38873, 38874, 38875, 38876, 38877, 38878, 38879,
+ 38880, 38881, 38882, 38883, 38884, 38885, 38886, 38887,
+ }},
+ {{
+ 38888, 38889, 38890, 38891, 38892, 38893, 38894, 38895,
+ 38896, 38897, 38898, 38899, 38900, 38901, 38902, 38903,
+ 38904, 38905, 38906, 38907, 38908, 38909, 38910, 38911,
+ 38912, 38913, 38914, 38915, 38916, 38917, 38918, 38919,
+ }},
+ {{
+ 38920, 38921, 38922, 38923, 38924, 38925, 38926, 38927,
+ 38928, 38929, 38930, 38931, 38932, 38933, 38934, 38935,
+ 38936, 38937, 38938, 38939, 38940, 38941, 38942, 38943,
+ 38944, 38945, 38946, 38947, 38948, 38949, 38950, 0,
+ }},
+ {{
+ 0, 0, 38951, 38952, 38953, 38954, 38955, 38956,
+ 0, 0, 38957, 38958, 38959, 38960, 38961, 38962,
+ 0, 0, 38963, 38964, 38965, 38966, 38967, 38968,
+ 0, 0, 38969, 38970, 38971, 0, 0, 0,
+ }},
+ {{
+ 38972, 38973, 38974, 38975, 38976, 38977, 38978, 0,
+ 38979, 38980, 38981, 38982, 38983, 38984, 38985, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 6218, 6220,
+ }},
+ {{
+ 6222, 6224, 6226, 6228, 6230, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 6232, 6234, 6236, 6238, 6240,
+ }},
+ {{
+ 6242, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 39012, 39013, 39014, 39015, 39016, 39017, 39018, 39019,
+ 39020, 39021, 39022, 39023, 39024, 39025, 39026, 39027,
+ 39028, 39029, 39030, 39031, 39032, 39033, 39034, 39035,
+ 39036, 39037, 39038, 39039, 39040, 39041, 39042, 39043,
+ }},
+ {{
+ 39044, 39045, 39046, 39047, 39048, 39049, 39050, 39051,
+ 39052, 39053, 39054, 39055, 39056, 39057, 39058, 39059,
+ 39060, 39061, 39062, 39063, 39064, 39065, 39066, 39067,
+ 39068, 39069, 39070, 39071, 39072, 39073, 39074, 39075,
+ }},
+ {{
+ 39076, 39077, 39078, 39079, 39080, 39081, 39082, 39083,
+ 39084, 39085, 39086, 39087, 39088, 39089, 39090, 39091,
+ 39092, 39093, 39094, 39095, 39096, 0, 39097, 39098,
+ 39099, 39100, 39101, 39102, 39103, 39104, 39105, 39106,
+ }},
+ {{
+ 39107, 39108, 39109, 39110, 39111, 39112, 39113, 39114,
+ 39115, 39116, 39117, 39118, 39119, 39120, 39121, 39122,
+ 39123, 39124, 39125, 39126, 39127, 39128, 39129, 39130,
+ 39131, 39132, 39133, 39134, 39135, 39136, 39137, 39138,
+ }},
+ {{
+ 39139, 39140, 39141, 39142, 39143, 39144, 39145, 39146,
+ 39147, 39148, 39149, 39150, 39151, 39152, 39153, 39154,
+ 39155, 39156, 39157, 39158, 39159, 39160, 39161, 39162,
+ 39163, 39164, 39165, 39166, 39167, 0, 39168, 39169,
+ }},
+ {{
+ 0, 0, 39170, 0, 0, 39171, 39172, 0,
+ 0, 39173, 39174, 39175, 39176, 0, 39177, 39178,
+ 39179, 39180, 39181, 39182, 39183, 39184, 39185, 39186,
+ 39187, 39188, 0, 39189, 0, 39190, 39191, 39192,
+ }},
+ {{
+ 39193, 0, 39194, 39195, 0, 39196, 39197, 39198,
+ 39199, 39200, 39201, 39202, 39203, 39204, 39205, 39206,
+ 39207, 39208, 39209, 39210, 39211, 39212, 39213, 39214,
+ 39215, 39216, 39217, 39218, 39219, 39220, 39221, 39222,
+ }},
+ {{
+ 39223, 39224, 39225, 39226, 39227, 39228, 39229, 39230,
+ 39231, 39232, 39233, 39234, 39235, 39236, 39237, 39238,
+ 39239, 39240, 39241, 39242, 39243, 39244, 39245, 39246,
+ 39247, 39248, 39249, 39250, 39251, 39252, 39253, 39254,
+ }},
+ {{
+ 39255, 39256, 39257, 39258, 39259, 39260, 0, 39261,
+ 39262, 39263, 39264, 0, 0, 39265, 39266, 39267,
+ 39268, 39269, 39270, 39271, 39272, 0, 39273, 39274,
+ 39275, 39276, 39277, 39278, 39279, 0, 39280, 39281,
+ }},
+ {{
+ 39282, 39283, 39284, 39285, 39286, 39287, 39288, 39289,
+ 39290, 39291, 39292, 39293, 39294, 39295, 39296, 39297,
+ 39298, 39299, 39300, 39301, 39302, 39303, 39304, 39305,
+ 39306, 39307, 0, 39308, 39309, 39310, 39311, 0,
+ }},
+ {{
+ 39312, 39313, 39314, 39315, 39316, 0, 39317, 0,
+ 0, 0, 39318, 39319, 39320, 39321, 39322, 39323,
+ 39324, 0, 39325, 39326, 39327, 39328, 39329, 39330,
+ 39331, 39332, 39333, 39334, 39335, 39336, 39337, 39338,
+ }},
+ {{
+ 39339, 39340, 39341, 39342, 39343, 39344, 39345, 39346,
+ 39347, 39348, 39349, 39350, 39351, 39352, 39353, 39354,
+ 39355, 39356, 39357, 39358, 39359, 39360, 39361, 39362,
+ 39363, 39364, 39365, 39366, 39367, 39368, 39369, 39370,
+ }},
+ {{
+ 39371, 39372, 39373, 39374, 39375, 39376, 39377, 39378,
+ 39379, 39380, 39381, 39382, 39383, 39384, 39385, 39386,
+ 39387, 39388, 39389, 39390, 39391, 39392, 39393, 39394,
+ 39395, 39396, 39397, 39398, 39399, 39400, 39401, 39402,
+ }},
+ {{
+ 39403, 39404, 39405, 39406, 39407, 39408, 39409, 39410,
+ 39411, 39412, 39413, 39414, 39415, 39416, 39417, 39418,
+ 39419, 39420, 39421, 39422, 39423, 39424, 39425, 39426,
+ 39427, 39428, 39429, 39430, 39431, 39432, 39433, 39434,
+ }},
+ {{
+ 39435, 39436, 39437, 39438, 39439, 39440, 39441, 39442,
+ 39443, 39444, 39445, 39446, 39447, 39448, 39449, 39450,
+ 39451, 39452, 39453, 39454, 39455, 39456, 39457, 39458,
+ 39459, 39460, 39461, 39462, 39463, 39464, 39465, 39466,
+ }},
+ {{
+ 39467, 39468, 39469, 39470, 39471, 39472, 39473, 39474,
+ 39475, 39476, 39477, 39478, 39479, 39480, 39481, 39482,
+ 39483, 39484, 39485, 39486, 39487, 39488, 39489, 39490,
+ 39491, 39492, 39493, 39494, 39495, 39496, 39497, 39498,
+ }},
+ {{
+ 39499, 39500, 39501, 39502, 39503, 39504, 39505, 39506,
+ 39507, 39508, 39509, 39510, 39511, 39512, 39513, 39514,
+ 39515, 39516, 39517, 39518, 39519, 39520, 39521, 39522,
+ 39523, 39524, 39525, 39526, 39527, 39528, 39529, 39530,
+ }},
+ {{
+ 39531, 39532, 39533, 39534, 39535, 39536, 39537, 39538,
+ 39539, 39540, 39541, 39542, 39543, 39544, 39545, 39546,
+ 39547, 39548, 39549, 39550, 39551, 39552, 39553, 39554,
+ 39555, 39556, 39557, 39558, 39559, 39560, 39561, 39562,
+ }},
+ {{
+ 39563, 39564, 39565, 39566, 39567, 39568, 39569, 39570,
+ 39571, 39572, 39573, 39574, 39575, 39576, 39577, 39578,
+ 39579, 39580, 39581, 39582, 39583, 39584, 39585, 39586,
+ 39587, 39588, 39589, 39590, 39591, 39592, 39593, 39594,
+ }},
+ {{
+ 39595, 39596, 39597, 39598, 39599, 39600, 39601, 39602,
+ 39603, 39604, 39605, 39606, 39607, 39608, 39609, 39610,
+ 39611, 39612, 39613, 39614, 39615, 39616, 39617, 39618,
+ 39619, 39620, 39621, 39622, 39623, 39624, 39625, 39626,
+ }},
+ {{
+ 39627, 39628, 39629, 39630, 39631, 39632, 39633, 39634,
+ 39635, 39636, 39637, 39638, 39639, 39640, 39641, 39642,
+ 39643, 39644, 39645, 39646, 39647, 39648, 39649, 39650,
+ 39651, 39652, 39653, 39654, 39655, 39656, 39657, 39658,
+ }},
+ {{
+ 39659, 39660, 39661, 39662, 0, 0, 0, 0,
+ 39663, 39664, 39665, 39666, 39667, 39668, 39669, 39670,
+ 39671, 39672, 39673, 39674, 39675, 39676, 39677, 39678,
+ 39679, 39680, 39681, 39682, 39683, 39684, 39685, 39686,
+ }},
+ {{
+ 39687, 39688, 39689, 39690, 39691, 39692, 39693, 39694,
+ 39695, 39696, 39697, 39698, 39699, 39700, 39701, 39702,
+ 39703, 39704, 39705, 39706, 39707, 39708, 39709, 39710,
+ 39711, 39712, 39713, 39714, 39715, 39716, 39717, 39718,
+ }},
+ {{
+ 39719, 39720, 39721, 39722, 39723, 39724, 39725, 39726,
+ 39727, 39728, 39729, 39730, 39731, 39732, 39733, 39734,
+ 39735, 39736, 39737, 39738, 39739, 39740, 39741, 39742,
+ 39743, 39744, 39745, 39746, 39747, 39748, 39749, 39750,
+ }},
+ {{
+ 39751, 39752, 39753, 39754, 39755, 39756, 39757, 39758,
+ 39759, 39760, 39761, 39762, 39763, 39764, 39765, 39766,
+ 39767, 39768, 39769, 39770, 39771, 39772, 39773, 39774,
+ 39775, 39776, 39777, 39778, 39779, 39780, 39781, 39782,
+ }},
+ {{
+ 39783, 39784, 39785, 39786, 39787, 39788, 39789, 39790,
+ 39791, 39792, 39793, 39794, 39795, 39796, 39797, 39798,
+ 39799, 39800, 39801, 39802, 39803, 39804, 39805, 39806,
+ 39807, 39808, 39809, 39810, 39811, 39812, 39813, 39814,
+ }},
+ {{
+ 39815, 39816, 39817, 39818, 39819, 39820, 39821, 39822,
+ 39823, 39824, 39825, 39826, 39827, 39828, 39829, 39830,
+ 39831, 39832, 39833, 39834, 39835, 39836, 39837, 39838,
+ 39839, 39840, 39841, 39842, 39843, 39844, 39845, 39846,
+ }},
+ {{
+ 39847, 39848, 39849, 39850, 39851, 39852, 39853, 39854,
+ 39855, 39856, 39857, 39858, 39859, 39860, 39861, 39862,
+ 39863, 39864, 39865, 39866, 39867, 39868, 39869, 39870,
+ 39871, 39872, 39873, 39874, 39875, 39876, 39877, 39878,
+ }},
+ {{
+ 39879, 39880, 39881, 39882, 39883, 39884, 39885, 39886,
+ 39887, 39888, 39889, 39890, 39891, 39892, 39893, 39894,
+ 39895, 39896, 39897, 39898, 39899, 39900, 39901, 39902,
+ 39903, 39904, 39905, 39906, 39907, 39908, 39909, 39910,
+ }},
+ {{
+ 39911, 39912, 39913, 39914, 39915, 39916, 39917, 39918,
+ 39919, 39920, 39921, 39922, 39923, 39924, 39925, 39926,
+ 39927, 39928, 39929, 39930, 39931, 39932, 39933, 39934,
+ 39935, 39936, 39937, 39938, 39939, 39940, 39941, 39942,
+ }},
+ {{
+ 39943, 39944, 39945, 39946, 39947, 39948, 39949, 39950,
+ 39951, 39952, 0, 0, 0, 0, 39953, 39954,
+ 39955, 39956, 39957, 39958, 39959, 39960, 39961, 39962,
+ 39963, 39964, 39965, 39966, 39967, 39968, 39969, 39970,
+ }},
+ {{
+ 39971, 39972, 39973, 39974, 39975, 39976, 39977, 39978,
+ 39979, 39980, 39981, 39982, 39983, 39984, 39985, 39986,
+ 39987, 39988, 39989, 39990, 39991, 39992, 39993, 39994,
+ 39995, 39996, 39997, 39998, 39999, 40000, 40001, 40002,
+ }},
+ {{
+ 7235, 7236, 7237, 7238, 7239, 7240, 7241, 7242,
+ 7243, 7244, 7245, 7246, 7247, 7248, 7249, 7250,
+ 7251, 7252, 7253, 7254, 7255, 7256, 7257, 7258,
+ 7259, 7260, 7261, 7262, 7263, 7264, 7265, 7266,
+ }},
+ {{
+ 7267, 7268, 7269, 7270, 7271, 7272, 7273, 7274,
+ 7275, 7276, 7277, 7278, 7279, 7280, 7281, 7282,
+ 7283, 7284, 7285, 7286, 7287, 7288, 7289, 7290,
+ 7291, 7292, 7293, 7294, 7295, 7296, 7297, 7298,
+ }},
+ {{
+ 7299, 7300, 7301, 7302, 7303, 7304, 7305, 7306,
+ 7307, 7308, 7309, 7310, 7311, 7312, 7313, 7314,
+ 7315, 7316, 7317, 7318, 7319, 7320, 7321, 7322,
+ 7323, 7324, 7325, 7326, 7327, 7328, 7329, 7330,
+ }},
+ {{
+ 7331, 7332, 7333, 7334, 7335, 7336, 7337, 7338,
+ 7339, 7340, 7341, 7342, 7343, 7344, 7345, 7346,
+ 7347, 7348, 7349, 7350, 7351, 7352, 7353, 7354,
+ 7355, 7356, 7357, 7358, 7359, 7360, 7361, 7362,
+ }},
+ {{
+ 7363, 7364, 7365, 7366, 7367, 7368, 7369, 7370,
+ 7371, 7372, 7373, 7374, 7375, 7376, 7377, 7378,
+ 7379, 7380, 7381, 7382, 7383, 7384, 7385, 7386,
+ 7387, 7388, 7389, 7390, 7391, 7392, 7393, 7394,
+ }},
+ {{
+ 7395, 7396, 7397, 7398, 7399, 7400, 7401, 7402,
+ 7403, 7404, 7405, 7406, 7407, 7408, 7409, 7410,
+ 7411, 7412, 7413, 7414, 7415, 7416, 7417, 7418,
+ 7419, 7420, 7421, 7422, 7423, 7424, 7425, 7426,
+ }},
+ {{
+ 7427, 7428, 7429, 7430, 7431, 7432, 7433, 7434,
+ 7435, 7436, 7437, 7438, 7439, 7440, 7441, 7442,
+ 7443, 7444, 7445, 7446, 7447, 7448, 7449, 7450,
+ 7451, 7452, 7453, 7454, 7455, 7456, 7457, 7458,
+ }},
+ {{
+ 7459, 7460, 7461, 7462, 7463, 7464, 7465, 7466,
+ 7467, 7468, 7469, 7470, 7471, 7472, 7473, 7474,
+ 7475, 7476, 7477, 7478, 7479, 7480, 7481, 7482,
+ 7483, 7484, 7485, 7486, 7487, 7488, 7489, 7490,
+ }},
+ {{
+ 7491, 7492, 7493, 7494, 7495, 7496, 7497, 7498,
+ 7499, 7500, 7501, 7502, 7503, 7504, 7505, 7506,
+ 7507, 7508, 7509, 7510, 7511, 7512, 7513, 7514,
+ 7515, 7516, 7517, 7518, 7519, 7520, 7521, 7522,
+ }},
+ {{
+ 7523, 7524, 7525, 7526, 7527, 7528, 7529, 7530,
+ 7531, 7532, 7533, 7534, 7535, 7536, 7537, 7538,
+ 7539, 7540, 7541, 7542, 7543, 7544, 7545, 7546,
+ 7547, 7548, 7549, 7550, 7551, 7552, 7553, 7554,
+ }},
+ {{
+ 7555, 7556, 7557, 7558, 7559, 7560, 7561, 7562,
+ 7563, 7564, 7565, 7566, 7567, 7568, 7569, 7570,
+ 7571, 7572, 7573, 7574, 7575, 7576, 7577, 7578,
+ 7579, 7580, 7581, 7582, 7583, 7584, 7585, 7586,
+ }},
+ {{
+ 7587, 7588, 7589, 7590, 7591, 7592, 7593, 7594,
+ 7595, 7596, 7597, 7598, 7599, 7600, 7601, 7602,
+ 7603, 7604, 7605, 7606, 7607, 7608, 7609, 7610,
+ 7611, 7612, 7613, 7614, 7615, 7616, 7617, 7618,
+ }},
+ {{
+ 7619, 7620, 7621, 7622, 7623, 7624, 7625, 7626,
+ 7627, 7628, 7629, 7630, 7631, 7632, 7633, 7634,
+ 7635, 7636, 7637, 7638, 7639, 7640, 7641, 7642,
+ 7643, 7644, 7645, 7646, 7647, 7648, 7649, 7650,
+ }},
+ {{
+ 7651, 7652, 7653, 7654, 7655, 7656, 7657, 7658,
+ 7659, 7660, 7661, 7662, 7663, 7664, 7665, 7666,
+ 7667, 7668, 7669, 7670, 7671, 7672, 7673, 7674,
+ 7675, 7676, 7677, 7678, 7679, 7680, 7681, 7682,
+ }},
+ {{
+ 7683, 7684, 7685, 7686, 7687, 7688, 7689, 7690,
+ 7691, 7692, 7693, 7694, 7695, 7696, 7697, 7698,
+ 7699, 7700, 7701, 7702, 7703, 7704, 7705, 7706,
+ 7707, 7708, 7709, 7710, 7711, 7712, 7713, 7714,
+ }},
+ {{
+ 7715, 7716, 7717, 7718, 7719, 7720, 7721, 7722,
+ 7723, 7724, 7725, 7726, 7727, 7728, 7729, 7730,
+ 7731, 7732, 7733, 7734, 7735, 7736, 7737, 7738,
+ 7739, 7740, 7741, 7742, 7743, 7744, 7745, 7746,
+ }},
+ {{
+ 7747, 7748, 7749, 7750, 7751, 7752, 7753, 7754,
+ 7755, 7756, 7757, 7758, 7759, 7760, 7761, 7762,
+ 7763, 7764, 7765, 7766, 7767, 7768, 7769, 7770,
+ 7771, 7772, 7773, 7774, 7775, 7776, 0, 0,
+ }},
+};
+static const unsigned long v320_decompose_seq[] = {
+ 0x00000000, 0x80000020, 0x00000020, 0x80000308,
+ 0x80000061, 0x00000020, 0x80000304, 0x80000032,
+ 0x80000033, 0x00000020, 0x80000301, 0x800003bc,
+ 0x00000020, 0x80000327, 0x80000031, 0x8000006f,
+ 0x00000031, 0x00002044, 0x80000034, 0x00000031,
+ 0x00002044, 0x80000032, 0x00000033, 0x00002044,
+ 0x80000034, 0x00000041, 0x80000300, 0x00000041,
+ 0x80000301, 0x00000041, 0x80000302, 0x00000041,
+ 0x80000303, 0x00000041, 0x80000308, 0x00000041,
+ 0x8000030a, 0x00000043, 0x80000327, 0x00000045,
+ 0x80000300, 0x00000045, 0x80000301, 0x00000045,
+ 0x80000302, 0x00000045, 0x80000308, 0x00000049,
+ 0x80000300, 0x00000049, 0x80000301, 0x00000049,
+ 0x80000302, 0x00000049, 0x80000308, 0x0000004e,
+ 0x80000303, 0x0000004f, 0x80000300, 0x0000004f,
+ 0x80000301, 0x0000004f, 0x80000302, 0x0000004f,
+ 0x80000303, 0x0000004f, 0x80000308, 0x00000055,
+ 0x80000300, 0x00000055, 0x80000301, 0x00000055,
+ 0x80000302, 0x00000055, 0x80000308, 0x00000059,
+ 0x80000301, 0x00000061, 0x80000300, 0x00000061,
+ 0x80000301, 0x00000061, 0x80000302, 0x00000061,
+ 0x80000303, 0x00000061, 0x80000308, 0x00000061,
+ 0x8000030a, 0x00000063, 0x80000327, 0x00000065,
+ 0x80000300, 0x00000065, 0x80000301, 0x00000065,
+ 0x80000302, 0x00000065, 0x80000308, 0x00000069,
+ 0x80000300, 0x00000069, 0x80000301, 0x00000069,
+ 0x80000302, 0x00000069, 0x80000308, 0x0000006e,
+ 0x80000303, 0x0000006f, 0x80000300, 0x0000006f,
+ 0x80000301, 0x0000006f, 0x80000302, 0x0000006f,
+ 0x80000303, 0x0000006f, 0x80000308, 0x00000075,
+ 0x80000300, 0x00000075, 0x80000301, 0x00000075,
+ 0x80000302, 0x00000075, 0x80000308, 0x00000079,
+ 0x80000301, 0x00000079, 0x80000308, 0x00000041,
+ 0x80000304, 0x00000061, 0x80000304, 0x00000041,
+ 0x80000306, 0x00000061, 0x80000306, 0x00000041,
+ 0x80000328, 0x00000061, 0x80000328, 0x00000043,
+ 0x80000301, 0x00000063, 0x80000301, 0x00000043,
+ 0x80000302, 0x00000063, 0x80000302, 0x00000043,
+ 0x80000307, 0x00000063, 0x80000307, 0x00000043,
+ 0x8000030c, 0x00000063, 0x8000030c, 0x00000044,
+ 0x8000030c, 0x00000064, 0x8000030c, 0x00000045,
+ 0x80000304, 0x00000065, 0x80000304, 0x00000045,
+ 0x80000306, 0x00000065, 0x80000306, 0x00000045,
+ 0x80000307, 0x00000065, 0x80000307, 0x00000045,
+ 0x80000328, 0x00000065, 0x80000328, 0x00000045,
+ 0x8000030c, 0x00000065, 0x8000030c, 0x00000047,
+ 0x80000302, 0x00000067, 0x80000302, 0x00000047,
+ 0x80000306, 0x00000067, 0x80000306, 0x00000047,
+ 0x80000307, 0x00000067, 0x80000307, 0x00000047,
+ 0x80000327, 0x00000067, 0x80000327, 0x00000048,
+ 0x80000302, 0x00000068, 0x80000302, 0x00000049,
+ 0x80000303, 0x00000069, 0x80000303, 0x00000049,
+ 0x80000304, 0x00000069, 0x80000304, 0x00000049,
+ 0x80000306, 0x00000069, 0x80000306, 0x00000049,
+ 0x80000328, 0x00000069, 0x80000328, 0x00000049,
+ 0x80000307, 0x00000049, 0x8000004a, 0x00000069,
+ 0x8000006a, 0x0000004a, 0x80000302, 0x0000006a,
+ 0x80000302, 0x0000004b, 0x80000327, 0x0000006b,
+ 0x80000327, 0x0000004c, 0x80000301, 0x0000006c,
+ 0x80000301, 0x0000004c, 0x80000327, 0x0000006c,
+ 0x80000327, 0x0000004c, 0x8000030c, 0x0000006c,
+ 0x8000030c, 0x0000004c, 0x800000b7, 0x0000006c,
+ 0x800000b7, 0x0000004e, 0x80000301, 0x0000006e,
+ 0x80000301, 0x0000004e, 0x80000327, 0x0000006e,
+ 0x80000327, 0x0000004e, 0x8000030c, 0x0000006e,
+ 0x8000030c, 0x000002bc, 0x8000006e, 0x0000004f,
+ 0x80000304, 0x0000006f, 0x80000304, 0x0000004f,
+ 0x80000306, 0x0000006f, 0x80000306, 0x0000004f,
+ 0x8000030b, 0x0000006f, 0x8000030b, 0x00000052,
+ 0x80000301, 0x00000072, 0x80000301, 0x00000052,
+ 0x80000327, 0x00000072, 0x80000327, 0x00000052,
+ 0x8000030c, 0x00000072, 0x8000030c, 0x00000053,
+ 0x80000301, 0x00000073, 0x80000301, 0x00000053,
+ 0x80000302, 0x00000073, 0x80000302, 0x00000053,
+ 0x80000327, 0x00000073, 0x80000327, 0x00000053,
+ 0x8000030c, 0x00000073, 0x8000030c, 0x00000054,
+ 0x80000327, 0x00000074, 0x80000327, 0x00000054,
+ 0x8000030c, 0x00000074, 0x8000030c, 0x00000055,
+ 0x80000303, 0x00000075, 0x80000303, 0x00000055,
+ 0x80000304, 0x00000075, 0x80000304, 0x00000055,
+ 0x80000306, 0x00000075, 0x80000306, 0x00000055,
+ 0x8000030a, 0x00000075, 0x8000030a, 0x00000055,
+ 0x8000030b, 0x00000075, 0x8000030b, 0x00000055,
+ 0x80000328, 0x00000075, 0x80000328, 0x00000057,
+ 0x80000302, 0x00000077, 0x80000302, 0x00000059,
+ 0x80000302, 0x00000079, 0x80000302, 0x00000059,
+ 0x80000308, 0x0000005a, 0x80000301, 0x0000007a,
+ 0x80000301, 0x0000005a, 0x80000307, 0x0000007a,
+ 0x80000307, 0x0000005a, 0x8000030c, 0x0000007a,
+ 0x8000030c, 0x80000073, 0x0000004f, 0x8000031b,
+ 0x0000006f, 0x8000031b, 0x00000055, 0x8000031b,
+ 0x00000075, 0x8000031b, 0x00000044, 0x8000017d,
+ 0x00000044, 0x8000017e, 0x00000064, 0x8000017e,
+ 0x0000004c, 0x8000004a, 0x0000004c, 0x8000006a,
+ 0x0000006c, 0x8000006a, 0x0000004e, 0x8000004a,
+ 0x0000004e, 0x8000006a, 0x0000006e, 0x8000006a,
+ 0x00000041, 0x8000030c, 0x00000061, 0x8000030c,
+ 0x00000049, 0x8000030c, 0x00000069, 0x8000030c,
+ 0x0000004f, 0x8000030c, 0x0000006f, 0x8000030c,
+ 0x00000055, 0x8000030c, 0x00000075, 0x8000030c,
+ 0x000000dc, 0x80000304, 0x000000fc, 0x80000304,
+ 0x000000dc, 0x80000301, 0x000000fc, 0x80000301,
+ 0x000000dc, 0x8000030c, 0x000000fc, 0x8000030c,
+ 0x000000dc, 0x80000300, 0x000000fc, 0x80000300,
+ 0x000000c4, 0x80000304, 0x000000e4, 0x80000304,
+ 0x00000226, 0x80000304, 0x00000227, 0x80000304,
+ 0x000000c6, 0x80000304, 0x000000e6, 0x80000304,
+ 0x00000047, 0x8000030c, 0x00000067, 0x8000030c,
+ 0x0000004b, 0x8000030c, 0x0000006b, 0x8000030c,
+ 0x0000004f, 0x80000328, 0x0000006f, 0x80000328,
+ 0x000001ea, 0x80000304, 0x000001eb, 0x80000304,
+ 0x000001b7, 0x8000030c, 0x00000292, 0x8000030c,
+ 0x0000006a, 0x8000030c, 0x00000044, 0x8000005a,
+ 0x00000044, 0x8000007a, 0x00000064, 0x8000007a,
+ 0x00000047, 0x80000301, 0x00000067, 0x80000301,
+ 0x0000004e, 0x80000300, 0x0000006e, 0x80000300,
+ 0x000000c5, 0x80000301, 0x000000e5, 0x80000301,
+ 0x000000c6, 0x80000301, 0x000000e6, 0x80000301,
+ 0x000000d8, 0x80000301, 0x000000f8, 0x80000301,
+ 0x00000041, 0x8000030f, 0x00000061, 0x8000030f,
+ 0x00000041, 0x80000311, 0x00000061, 0x80000311,
+ 0x00000045, 0x8000030f, 0x00000065, 0x8000030f,
+ 0x00000045, 0x80000311, 0x00000065, 0x80000311,
+ 0x00000049, 0x8000030f, 0x00000069, 0x8000030f,
+ 0x00000049, 0x80000311, 0x00000069, 0x80000311,
+ 0x0000004f, 0x8000030f, 0x0000006f, 0x8000030f,
+ 0x0000004f, 0x80000311, 0x0000006f, 0x80000311,
+ 0x00000052, 0x8000030f, 0x00000072, 0x8000030f,
+ 0x00000052, 0x80000311, 0x00000072, 0x80000311,
+ 0x00000055, 0x8000030f, 0x00000075, 0x8000030f,
+ 0x00000055, 0x80000311, 0x00000075, 0x80000311,
+ 0x00000053, 0x80000326, 0x00000073, 0x80000326,
+ 0x00000054, 0x80000326, 0x00000074, 0x80000326,
+ 0x00000048, 0x8000030c, 0x00000068, 0x8000030c,
+ 0x00000041, 0x80000307, 0x00000061, 0x80000307,
+ 0x00000045, 0x80000327, 0x00000065, 0x80000327,
+ 0x000000d6, 0x80000304, 0x000000f6, 0x80000304,
+ 0x000000d5, 0x80000304, 0x000000f5, 0x80000304,
+ 0x0000004f, 0x80000307, 0x0000006f, 0x80000307,
+ 0x0000022e, 0x80000304, 0x0000022f, 0x80000304,
+ 0x00000059, 0x80000304, 0x00000079, 0x80000304,
+ 0x80000068, 0x80000266, 0x8000006a, 0x80000072,
+ 0x80000279, 0x8000027b, 0x80000281, 0x80000077,
+ 0x80000079, 0x00000020, 0x80000306, 0x00000020,
+ 0x80000307, 0x00000020, 0x8000030a, 0x00000020,
+ 0x80000328, 0x00000020, 0x80000303, 0x00000020,
+ 0x8000030b, 0x80000263, 0x8000006c, 0x80000073,
+ 0x80000078, 0x80000295, 0x80000300, 0x80000301,
+ 0x80000313, 0x00000308, 0x80000301, 0x800002b9,
+ 0x00000020, 0x80000345, 0x8000003b, 0x00000020,
+ 0x80000301, 0x000000a8, 0x80000301, 0x00000391,
+ 0x80000301, 0x800000b7, 0x00000395, 0x80000301,
+ 0x00000397, 0x80000301, 0x00000399, 0x80000301,
+ 0x0000039f, 0x80000301, 0x000003a5, 0x80000301,
+ 0x000003a9, 0x80000301, 0x000003ca, 0x80000301,
+ 0x00000399, 0x80000308, 0x000003a5, 0x80000308,
+ 0x000003b1, 0x80000301, 0x000003b5, 0x80000301,
+ 0x000003b7, 0x80000301, 0x000003b9, 0x80000301,
+ 0x000003cb, 0x80000301, 0x000003b9, 0x80000308,
+ 0x000003c5, 0x80000308, 0x000003bf, 0x80000301,
+ 0x000003c5, 0x80000301, 0x000003c9, 0x80000301,
+ 0x800003b2, 0x800003b8, 0x800003a5, 0x000003d2,
+ 0x80000301, 0x000003d2, 0x80000308, 0x800003c6,
+ 0x800003c0, 0x800003ba, 0x800003c1, 0x800003c2,
+ 0x80000398, 0x800003b5, 0x00000415, 0x80000300,
+ 0x00000415, 0x80000308, 0x00000413, 0x80000301,
+ 0x00000406, 0x80000308, 0x0000041a, 0x80000301,
+ 0x00000418, 0x80000300, 0x00000423, 0x80000306,
+ 0x00000418, 0x80000306, 0x00000438, 0x80000306,
+ 0x00000435, 0x80000300, 0x00000435, 0x80000308,
+ 0x00000433, 0x80000301, 0x00000456, 0x80000308,
+ 0x0000043a, 0x80000301, 0x00000438, 0x80000300,
+ 0x00000443, 0x80000306, 0x00000474, 0x8000030f,
+ 0x00000475, 0x8000030f, 0x00000416, 0x80000306,
+ 0x00000436, 0x80000306, 0x00000410, 0x80000306,
+ 0x00000430, 0x80000306, 0x00000410, 0x80000308,
+ 0x00000430, 0x80000308, 0x00000415, 0x80000306,
+ 0x00000435, 0x80000306, 0x000004d8, 0x80000308,
+ 0x000004d9, 0x80000308, 0x00000416, 0x80000308,
+ 0x00000436, 0x80000308, 0x00000417, 0x80000308,
+ 0x00000437, 0x80000308, 0x00000418, 0x80000304,
+ 0x00000438, 0x80000304, 0x00000418, 0x80000308,
+ 0x00000438, 0x80000308, 0x0000041e, 0x80000308,
+ 0x0000043e, 0x80000308, 0x000004e8, 0x80000308,
+ 0x000004e9, 0x80000308, 0x0000042d, 0x80000308,
+ 0x0000044d, 0x80000308, 0x00000423, 0x80000304,
+ 0x00000443, 0x80000304, 0x00000423, 0x80000308,
+ 0x00000443, 0x80000308, 0x00000423, 0x8000030b,
+ 0x00000443, 0x8000030b, 0x00000427, 0x80000308,
+ 0x00000447, 0x80000308, 0x0000042b, 0x80000308,
+ 0x0000044b, 0x80000308, 0x00000565, 0x80000582,
+ 0x00000627, 0x80000653, 0x00000627, 0x80000654,
+ 0x00000648, 0x80000654, 0x00000627, 0x80000655,
+ 0x0000064a, 0x80000654, 0x00000627, 0x80000674,
+ 0x00000648, 0x80000674, 0x000006c7, 0x80000674,
+ 0x0000064a, 0x80000674, 0x000006d5, 0x80000654,
+ 0x000006c1, 0x80000654, 0x000006d2, 0x80000654,
+ 0x00000928, 0x8000093c, 0x00000930, 0x8000093c,
+ 0x00000933, 0x8000093c, 0x00000915, 0x8000093c,
+ 0x00000916, 0x8000093c, 0x00000917, 0x8000093c,
+ 0x0000091c, 0x8000093c, 0x00000921, 0x8000093c,
+ 0x00000922, 0x8000093c, 0x0000092b, 0x8000093c,
+ 0x0000092f, 0x8000093c, 0x000009c7, 0x800009be,
+ 0x000009c7, 0x800009d7, 0x000009a1, 0x800009bc,
+ 0x000009a2, 0x800009bc, 0x000009af, 0x800009bc,
+ 0x00000a32, 0x80000a3c, 0x00000a38, 0x80000a3c,
+ 0x00000a16, 0x80000a3c, 0x00000a17, 0x80000a3c,
+ 0x00000a1c, 0x80000a3c, 0x00000a2b, 0x80000a3c,
+ 0x00000b47, 0x80000b56, 0x00000b47, 0x80000b3e,
+ 0x00000b47, 0x80000b57, 0x00000b21, 0x80000b3c,
+ 0x00000b22, 0x80000b3c, 0x00000b92, 0x80000bd7,
+ 0x00000bc6, 0x80000bbe, 0x00000bc7, 0x80000bbe,
+ 0x00000bc6, 0x80000bd7, 0x00000c46, 0x80000c56,
+ 0x00000cbf, 0x80000cd5, 0x00000cc6, 0x80000cd5,
+ 0x00000cc6, 0x80000cd6, 0x00000cc6, 0x80000cc2,
+ 0x00000cca, 0x80000cd5, 0x00000d46, 0x80000d3e,
+ 0x00000d47, 0x80000d3e, 0x00000d46, 0x80000d57,
+ 0x00000dd9, 0x80000dca, 0x00000dd9, 0x80000dcf,
+ 0x00000ddc, 0x80000dca, 0x00000dd9, 0x80000ddf,
+ 0x00000e4d, 0x80000e32, 0x00000ecd, 0x80000eb2,
+ 0x00000eab, 0x80000e99, 0x00000eab, 0x80000ea1,
+ 0x80000f0b, 0x00000f42, 0x80000fb7, 0x00000f4c,
+ 0x80000fb7, 0x00000f51, 0x80000fb7, 0x00000f56,
+ 0x80000fb7, 0x00000f5b, 0x80000fb7, 0x00000f40,
+ 0x80000fb5, 0x00000f71, 0x80000f72, 0x00000f71,
+ 0x80000f74, 0x00000fb2, 0x80000f80, 0x00000fb2,
+ 0x80000f81, 0x00000fb3, 0x80000f80, 0x00000fb3,
+ 0x80000f81, 0x00000f71, 0x80000f80, 0x00000f92,
+ 0x80000fb7, 0x00000f9c, 0x80000fb7, 0x00000fa1,
+ 0x80000fb7, 0x00000fa6, 0x80000fb7, 0x00000fab,
+ 0x80000fb7, 0x00000f90, 0x80000fb5, 0x00001025,
+ 0x8000102e, 0x00000041, 0x80000325, 0x00000061,
+ 0x80000325, 0x00000042, 0x80000307, 0x00000062,
+ 0x80000307, 0x00000042, 0x80000323, 0x00000062,
+ 0x80000323, 0x00000042, 0x80000331, 0x00000062,
+ 0x80000331, 0x000000c7, 0x80000301, 0x000000e7,
+ 0x80000301, 0x00000044, 0x80000307, 0x00000064,
+ 0x80000307, 0x00000044, 0x80000323, 0x00000064,
+ 0x80000323, 0x00000044, 0x80000331, 0x00000064,
+ 0x80000331, 0x00000044, 0x80000327, 0x00000064,
+ 0x80000327, 0x00000044, 0x8000032d, 0x00000064,
+ 0x8000032d, 0x00000112, 0x80000300, 0x00000113,
+ 0x80000300, 0x00000112, 0x80000301, 0x00000113,
+ 0x80000301, 0x00000045, 0x8000032d, 0x00000065,
+ 0x8000032d, 0x00000045, 0x80000330, 0x00000065,
+ 0x80000330, 0x00000228, 0x80000306, 0x00000229,
+ 0x80000306, 0x00000046, 0x80000307, 0x00000066,
+ 0x80000307, 0x00000047, 0x80000304, 0x00000067,
+ 0x80000304, 0x00000048, 0x80000307, 0x00000068,
+ 0x80000307, 0x00000048, 0x80000323, 0x00000068,
+ 0x80000323, 0x00000048, 0x80000308, 0x00000068,
+ 0x80000308, 0x00000048, 0x80000327, 0x00000068,
+ 0x80000327, 0x00000048, 0x8000032e, 0x00000068,
+ 0x8000032e, 0x00000049, 0x80000330, 0x00000069,
+ 0x80000330, 0x000000cf, 0x80000301, 0x000000ef,
+ 0x80000301, 0x0000004b, 0x80000301, 0x0000006b,
+ 0x80000301, 0x0000004b, 0x80000323, 0x0000006b,
+ 0x80000323, 0x0000004b, 0x80000331, 0x0000006b,
+ 0x80000331, 0x0000004c, 0x80000323, 0x0000006c,
+ 0x80000323, 0x00001e36, 0x80000304, 0x00001e37,
+ 0x80000304, 0x0000004c, 0x80000331, 0x0000006c,
+ 0x80000331, 0x0000004c, 0x8000032d, 0x0000006c,
+ 0x8000032d, 0x0000004d, 0x80000301, 0x0000006d,
+ 0x80000301, 0x0000004d, 0x80000307, 0x0000006d,
+ 0x80000307, 0x0000004d, 0x80000323, 0x0000006d,
+ 0x80000323, 0x0000004e, 0x80000307, 0x0000006e,
+ 0x80000307, 0x0000004e, 0x80000323, 0x0000006e,
+ 0x80000323, 0x0000004e, 0x80000331, 0x0000006e,
+ 0x80000331, 0x0000004e, 0x8000032d, 0x0000006e,
+ 0x8000032d, 0x000000d5, 0x80000301, 0x000000f5,
+ 0x80000301, 0x000000d5, 0x80000308, 0x000000f5,
+ 0x80000308, 0x0000014c, 0x80000300, 0x0000014d,
+ 0x80000300, 0x0000014c, 0x80000301, 0x0000014d,
+ 0x80000301, 0x00000050, 0x80000301, 0x00000070,
+ 0x80000301, 0x00000050, 0x80000307, 0x00000070,
+ 0x80000307, 0x00000052, 0x80000307, 0x00000072,
+ 0x80000307, 0x00000052, 0x80000323, 0x00000072,
+ 0x80000323, 0x00001e5a, 0x80000304, 0x00001e5b,
+ 0x80000304, 0x00000052, 0x80000331, 0x00000072,
+ 0x80000331, 0x00000053, 0x80000307, 0x00000073,
+ 0x80000307, 0x00000053, 0x80000323, 0x00000073,
+ 0x80000323, 0x0000015a, 0x80000307, 0x0000015b,
+ 0x80000307, 0x00000160, 0x80000307, 0x00000161,
+ 0x80000307, 0x00001e62, 0x80000307, 0x00001e63,
+ 0x80000307, 0x00000054, 0x80000307, 0x00000074,
+ 0x80000307, 0x00000054, 0x80000323, 0x00000074,
+ 0x80000323, 0x00000054, 0x80000331, 0x00000074,
+ 0x80000331, 0x00000054, 0x8000032d, 0x00000074,
+ 0x8000032d, 0x00000055, 0x80000324, 0x00000075,
+ 0x80000324, 0x00000055, 0x80000330, 0x00000075,
+ 0x80000330, 0x00000055, 0x8000032d, 0x00000075,
+ 0x8000032d, 0x00000168, 0x80000301, 0x00000169,
+ 0x80000301, 0x0000016a, 0x80000308, 0x0000016b,
+ 0x80000308, 0x00000056, 0x80000303, 0x00000076,
+ 0x80000303, 0x00000056, 0x80000323, 0x00000076,
+ 0x80000323, 0x00000057, 0x80000300, 0x00000077,
+ 0x80000300, 0x00000057, 0x80000301, 0x00000077,
+ 0x80000301, 0x00000057, 0x80000308, 0x00000077,
+ 0x80000308, 0x00000057, 0x80000307, 0x00000077,
+ 0x80000307, 0x00000057, 0x80000323, 0x00000077,
+ 0x80000323, 0x00000058, 0x80000307, 0x00000078,
+ 0x80000307, 0x00000058, 0x80000308, 0x00000078,
+ 0x80000308, 0x00000059, 0x80000307, 0x00000079,
+ 0x80000307, 0x0000005a, 0x80000302, 0x0000007a,
+ 0x80000302, 0x0000005a, 0x80000323, 0x0000007a,
+ 0x80000323, 0x0000005a, 0x80000331, 0x0000007a,
+ 0x80000331, 0x00000068, 0x80000331, 0x00000074,
+ 0x80000308, 0x00000077, 0x8000030a, 0x00000079,
+ 0x8000030a, 0x00000061, 0x800002be, 0x0000017f,
+ 0x80000307, 0x00000041, 0x80000323, 0x00000061,
+ 0x80000323, 0x00000041, 0x80000309, 0x00000061,
+ 0x80000309, 0x000000c2, 0x80000301, 0x000000e2,
+ 0x80000301, 0x000000c2, 0x80000300, 0x000000e2,
+ 0x80000300, 0x000000c2, 0x80000309, 0x000000e2,
+ 0x80000309, 0x000000c2, 0x80000303, 0x000000e2,
+ 0x80000303, 0x00001ea0, 0x80000302, 0x00001ea1,
+ 0x80000302, 0x00000102, 0x80000301, 0x00000103,
+ 0x80000301, 0x00000102, 0x80000300, 0x00000103,
+ 0x80000300, 0x00000102, 0x80000309, 0x00000103,
+ 0x80000309, 0x00000102, 0x80000303, 0x00000103,
+ 0x80000303, 0x00001ea0, 0x80000306, 0x00001ea1,
+ 0x80000306, 0x00000045, 0x80000323, 0x00000065,
+ 0x80000323, 0x00000045, 0x80000309, 0x00000065,
+ 0x80000309, 0x00000045, 0x80000303, 0x00000065,
+ 0x80000303, 0x000000ca, 0x80000301, 0x000000ea,
+ 0x80000301, 0x000000ca, 0x80000300, 0x000000ea,
+ 0x80000300, 0x000000ca, 0x80000309, 0x000000ea,
+ 0x80000309, 0x000000ca, 0x80000303, 0x000000ea,
+ 0x80000303, 0x00001eb8, 0x80000302, 0x00001eb9,
+ 0x80000302, 0x00000049, 0x80000309, 0x00000069,
+ 0x80000309, 0x00000049, 0x80000323, 0x00000069,
+ 0x80000323, 0x0000004f, 0x80000323, 0x0000006f,
+ 0x80000323, 0x0000004f, 0x80000309, 0x0000006f,
+ 0x80000309, 0x000000d4, 0x80000301, 0x000000f4,
+ 0x80000301, 0x000000d4, 0x80000300, 0x000000f4,
+ 0x80000300, 0x000000d4, 0x80000309, 0x000000f4,
+ 0x80000309, 0x000000d4, 0x80000303, 0x000000f4,
+ 0x80000303, 0x00001ecc, 0x80000302, 0x00001ecd,
+ 0x80000302, 0x000001a0, 0x80000301, 0x000001a1,
+ 0x80000301, 0x000001a0, 0x80000300, 0x000001a1,
+ 0x80000300, 0x000001a0, 0x80000309, 0x000001a1,
+ 0x80000309, 0x000001a0, 0x80000303, 0x000001a1,
+ 0x80000303, 0x000001a0, 0x80000323, 0x000001a1,
+ 0x80000323, 0x00000055, 0x80000323, 0x00000075,
+ 0x80000323, 0x00000055, 0x80000309, 0x00000075,
+ 0x80000309, 0x000001af, 0x80000301, 0x000001b0,
+ 0x80000301, 0x000001af, 0x80000300, 0x000001b0,
+ 0x80000300, 0x000001af, 0x80000309, 0x000001b0,
+ 0x80000309, 0x000001af, 0x80000303, 0x000001b0,
+ 0x80000303, 0x000001af, 0x80000323, 0x000001b0,
+ 0x80000323, 0x00000059, 0x80000300, 0x00000079,
+ 0x80000300, 0x00000059, 0x80000323, 0x00000079,
+ 0x80000323, 0x00000059, 0x80000309, 0x00000079,
+ 0x80000309, 0x00000059, 0x80000303, 0x00000079,
+ 0x80000303, 0x000003b1, 0x80000313, 0x000003b1,
+ 0x80000314, 0x00001f00, 0x80000300, 0x00001f01,
+ 0x80000300, 0x00001f00, 0x80000301, 0x00001f01,
+ 0x80000301, 0x00001f00, 0x80000342, 0x00001f01,
+ 0x80000342, 0x00000391, 0x80000313, 0x00000391,
+ 0x80000314, 0x00001f08, 0x80000300, 0x00001f09,
+ 0x80000300, 0x00001f08, 0x80000301, 0x00001f09,
+ 0x80000301, 0x00001f08, 0x80000342, 0x00001f09,
+ 0x80000342, 0x000003b5, 0x80000313, 0x000003b5,
+ 0x80000314, 0x00001f10, 0x80000300, 0x00001f11,
+ 0x80000300, 0x00001f10, 0x80000301, 0x00001f11,
+ 0x80000301, 0x00000395, 0x80000313, 0x00000395,
+ 0x80000314, 0x00001f18, 0x80000300, 0x00001f19,
+ 0x80000300, 0x00001f18, 0x80000301, 0x00001f19,
+ 0x80000301, 0x000003b7, 0x80000313, 0x000003b7,
+ 0x80000314, 0x00001f20, 0x80000300, 0x00001f21,
+ 0x80000300, 0x00001f20, 0x80000301, 0x00001f21,
+ 0x80000301, 0x00001f20, 0x80000342, 0x00001f21,
+ 0x80000342, 0x00000397, 0x80000313, 0x00000397,
+ 0x80000314, 0x00001f28, 0x80000300, 0x00001f29,
+ 0x80000300, 0x00001f28, 0x80000301, 0x00001f29,
+ 0x80000301, 0x00001f28, 0x80000342, 0x00001f29,
+ 0x80000342, 0x000003b9, 0x80000313, 0x000003b9,
+ 0x80000314, 0x00001f30, 0x80000300, 0x00001f31,
+ 0x80000300, 0x00001f30, 0x80000301, 0x00001f31,
+ 0x80000301, 0x00001f30, 0x80000342, 0x00001f31,
+ 0x80000342, 0x00000399, 0x80000313, 0x00000399,
+ 0x80000314, 0x00001f38, 0x80000300, 0x00001f39,
+ 0x80000300, 0x00001f38, 0x80000301, 0x00001f39,
+ 0x80000301, 0x00001f38, 0x80000342, 0x00001f39,
+ 0x80000342, 0x000003bf, 0x80000313, 0x000003bf,
+ 0x80000314, 0x00001f40, 0x80000300, 0x00001f41,
+ 0x80000300, 0x00001f40, 0x80000301, 0x00001f41,
+ 0x80000301, 0x0000039f, 0x80000313, 0x0000039f,
+ 0x80000314, 0x00001f48, 0x80000300, 0x00001f49,
+ 0x80000300, 0x00001f48, 0x80000301, 0x00001f49,
+ 0x80000301, 0x000003c5, 0x80000313, 0x000003c5,
+ 0x80000314, 0x00001f50, 0x80000300, 0x00001f51,
+ 0x80000300, 0x00001f50, 0x80000301, 0x00001f51,
+ 0x80000301, 0x00001f50, 0x80000342, 0x00001f51,
+ 0x80000342, 0x000003a5, 0x80000314, 0x00001f59,
+ 0x80000300, 0x00001f59, 0x80000301, 0x00001f59,
+ 0x80000342, 0x000003c9, 0x80000313, 0x000003c9,
+ 0x80000314, 0x00001f60, 0x80000300, 0x00001f61,
+ 0x80000300, 0x00001f60, 0x80000301, 0x00001f61,
+ 0x80000301, 0x00001f60, 0x80000342, 0x00001f61,
+ 0x80000342, 0x000003a9, 0x80000313, 0x000003a9,
+ 0x80000314, 0x00001f68, 0x80000300, 0x00001f69,
+ 0x80000300, 0x00001f68, 0x80000301, 0x00001f69,
+ 0x80000301, 0x00001f68, 0x80000342, 0x00001f69,
+ 0x80000342, 0x000003b1, 0x80000300, 0x800003ac,
+ 0x000003b5, 0x80000300, 0x800003ad, 0x000003b7,
+ 0x80000300, 0x800003ae, 0x000003b9, 0x80000300,
+ 0x800003af, 0x000003bf, 0x80000300, 0x800003cc,
+ 0x000003c5, 0x80000300, 0x800003cd, 0x000003c9,
+ 0x80000300, 0x800003ce, 0x00001f00, 0x80000345,
+ 0x00001f01, 0x80000345, 0x00001f02, 0x80000345,
+ 0x00001f03, 0x80000345, 0x00001f04, 0x80000345,
+ 0x00001f05, 0x80000345, 0x00001f06, 0x80000345,
+ 0x00001f07, 0x80000345, 0x00001f08, 0x80000345,
+ 0x00001f09, 0x80000345, 0x00001f0a, 0x80000345,
+ 0x00001f0b, 0x80000345, 0x00001f0c, 0x80000345,
+ 0x00001f0d, 0x80000345, 0x00001f0e, 0x80000345,
+ 0x00001f0f, 0x80000345, 0x00001f20, 0x80000345,
+ 0x00001f21, 0x80000345, 0x00001f22, 0x80000345,
+ 0x00001f23, 0x80000345, 0x00001f24, 0x80000345,
+ 0x00001f25, 0x80000345, 0x00001f26, 0x80000345,
+ 0x00001f27, 0x80000345, 0x00001f28, 0x80000345,
+ 0x00001f29, 0x80000345, 0x00001f2a, 0x80000345,
+ 0x00001f2b, 0x80000345, 0x00001f2c, 0x80000345,
+ 0x00001f2d, 0x80000345, 0x00001f2e, 0x80000345,
+ 0x00001f2f, 0x80000345, 0x00001f60, 0x80000345,
+ 0x00001f61, 0x80000345, 0x00001f62, 0x80000345,
+ 0x00001f63, 0x80000345, 0x00001f64, 0x80000345,
+ 0x00001f65, 0x80000345, 0x00001f66, 0x80000345,
+ 0x00001f67, 0x80000345, 0x00001f68, 0x80000345,
+ 0x00001f69, 0x80000345, 0x00001f6a, 0x80000345,
+ 0x00001f6b, 0x80000345, 0x00001f6c, 0x80000345,
+ 0x00001f6d, 0x80000345, 0x00001f6e, 0x80000345,
+ 0x00001f6f, 0x80000345, 0x000003b1, 0x80000306,
+ 0x000003b1, 0x80000304, 0x00001f70, 0x80000345,
+ 0x000003b1, 0x80000345, 0x000003ac, 0x80000345,
+ 0x000003b1, 0x80000342, 0x00001fb6, 0x80000345,
+ 0x00000391, 0x80000306, 0x00000391, 0x80000304,
+ 0x00000391, 0x80000300, 0x80000386, 0x00000391,
+ 0x80000345, 0x00000020, 0x80000313, 0x800003b9,
+ 0x00000020, 0x80000313, 0x00000020, 0x80000342,
+ 0x000000a8, 0x80000342, 0x00001f74, 0x80000345,
+ 0x000003b7, 0x80000345, 0x000003ae, 0x80000345,
+ 0x000003b7, 0x80000342, 0x00001fc6, 0x80000345,
+ 0x00000395, 0x80000300, 0x80000388, 0x00000397,
+ 0x80000300, 0x80000389, 0x00000397, 0x80000345,
+ 0x00001fbf, 0x80000300, 0x00001fbf, 0x80000301,
+ 0x00001fbf, 0x80000342, 0x000003b9, 0x80000306,
+ 0x000003b9, 0x80000304, 0x000003ca, 0x80000300,
+ 0x80000390, 0x000003b9, 0x80000342, 0x000003ca,
+ 0x80000342, 0x00000399, 0x80000306, 0x00000399,
+ 0x80000304, 0x00000399, 0x80000300, 0x8000038a,
+ 0x00001ffe, 0x80000300, 0x00001ffe, 0x80000301,
+ 0x00001ffe, 0x80000342, 0x000003c5, 0x80000306,
+ 0x000003c5, 0x80000304, 0x000003cb, 0x80000300,
+ 0x800003b0, 0x000003c1, 0x80000313, 0x000003c1,
+ 0x80000314, 0x000003c5, 0x80000342, 0x000003cb,
+ 0x80000342, 0x000003a5, 0x80000306, 0x000003a5,
+ 0x80000304, 0x000003a5, 0x80000300, 0x8000038e,
+ 0x000003a1, 0x80000314, 0x000000a8, 0x80000300,
+ 0x80000385, 0x80000060, 0x00001f7c, 0x80000345,
+ 0x000003c9, 0x80000345, 0x000003ce, 0x80000345,
+ 0x000003c9, 0x80000342, 0x00001ff6, 0x80000345,
+ 0x0000039f, 0x80000300, 0x8000038c, 0x000003a9,
+ 0x80000300, 0x8000038f, 0x000003a9, 0x80000345,
+ 0x800000b4, 0x00000020, 0x80000314, 0x80002002,
+ 0x80002003, 0x80000020, 0x80000020, 0x80000020,
+ 0x80000020, 0x80000020, 0x80000020, 0x80000020,
+ 0x80000020, 0x80000020, 0x80002010, 0x00000020,
+ 0x80000333, 0x8000002e, 0x0000002e, 0x8000002e,
+ 0x0000002e, 0x0000002e, 0x8000002e, 0x80000020,
+ 0x00002032, 0x80002032, 0x00002032, 0x00002032,
+ 0x80002032, 0x00002035, 0x80002035, 0x00002035,
+ 0x00002035, 0x80002035, 0x00000021, 0x80000021,
+ 0x00000020, 0x80000305, 0x0000003f, 0x8000003f,
+ 0x0000003f, 0x80000021, 0x00000021, 0x8000003f,
+ 0x00002032, 0x00002032, 0x00002032, 0x80002032,
+ 0x80000020, 0x80000030, 0x80000069, 0x80000034,
+ 0x80000035, 0x80000036, 0x80000037, 0x80000038,
+ 0x80000039, 0x8000002b, 0x80002212, 0x8000003d,
+ 0x80000028, 0x80000029, 0x8000006e, 0x80000030,
+ 0x80000031, 0x80000032, 0x80000033, 0x80000034,
+ 0x80000035, 0x80000036, 0x80000037, 0x80000038,
+ 0x80000039, 0x8000002b, 0x80002212, 0x8000003d,
+ 0x80000028, 0x80000029, 0x00000052, 0x80000073,
+ 0x00000061, 0x0000002f, 0x80000063, 0x00000061,
+ 0x0000002f, 0x80000073, 0x80000043, 0x000000b0,
+ 0x80000043, 0x00000063, 0x0000002f, 0x8000006f,
+ 0x00000063, 0x0000002f, 0x80000075, 0x80000190,
+ 0x000000b0, 0x80000046, 0x80000067, 0x80000048,
+ 0x80000048, 0x80000048, 0x80000068, 0x80000127,
+ 0x80000049, 0x80000049, 0x8000004c, 0x8000006c,
+ 0x8000004e, 0x0000004e, 0x8000006f, 0x80000050,
+ 0x80000051, 0x80000052, 0x80000052, 0x80000052,
+ 0x00000053, 0x8000004d, 0x00000054, 0x00000045,
+ 0x8000004c, 0x00000054, 0x8000004d, 0x8000005a,
+ 0x800003a9, 0x8000005a, 0x8000004b, 0x800000c5,
+ 0x80000042, 0x80000043, 0x80000065, 0x80000045,
+ 0x80000046, 0x8000004d, 0x8000006f, 0x800005d0,
+ 0x800005d1, 0x800005d2, 0x800005d3, 0x80000069,
+ 0x800003b3, 0x80000393, 0x800003a0, 0x80002211,
+ 0x80000044, 0x80000064, 0x80000065, 0x80000069,
+ 0x8000006a, 0x00000031, 0x00002044, 0x80000033,
+ 0x00000032, 0x00002044, 0x80000033, 0x00000031,
+ 0x00002044, 0x80000035, 0x00000032, 0x00002044,
+ 0x80000035, 0x00000033, 0x00002044, 0x80000035,
+ 0x00000034, 0x00002044, 0x80000035, 0x00000031,
+ 0x00002044, 0x80000036, 0x00000035, 0x00002044,
+ 0x80000036, 0x00000031, 0x00002044, 0x80000038,
+ 0x00000033, 0x00002044, 0x80000038, 0x00000035,
+ 0x00002044, 0x80000038, 0x00000037, 0x00002044,
+ 0x80000038, 0x00000031, 0x80002044, 0x80000049,
+ 0x00000049, 0x80000049, 0x00000049, 0x00000049,
+ 0x80000049, 0x00000049, 0x80000056, 0x80000056,
+ 0x00000056, 0x80000049, 0x00000056, 0x00000049,
+ 0x80000049, 0x00000056, 0x00000049, 0x00000049,
+ 0x80000049, 0x00000049, 0x80000058, 0x80000058,
+ 0x00000058, 0x80000049, 0x00000058, 0x00000049,
+ 0x80000049, 0x8000004c, 0x80000043, 0x80000044,
+ 0x8000004d, 0x80000069, 0x00000069, 0x80000069,
+ 0x00000069, 0x00000069, 0x80000069, 0x00000069,
+ 0x80000076, 0x80000076, 0x00000076, 0x80000069,
+ 0x00000076, 0x00000069, 0x80000069, 0x00000076,
+ 0x00000069, 0x00000069, 0x80000069, 0x00000069,
+ 0x80000078, 0x80000078, 0x00000078, 0x80000069,
+ 0x00000078, 0x00000069, 0x80000069, 0x8000006c,
+ 0x80000063, 0x80000064, 0x8000006d, 0x00002190,
+ 0x80000338, 0x00002192, 0x80000338, 0x00002194,
+ 0x80000338, 0x000021d0, 0x80000338, 0x000021d4,
+ 0x80000338, 0x000021d2, 0x80000338, 0x00002203,
+ 0x80000338, 0x00002208, 0x80000338, 0x0000220b,
+ 0x80000338, 0x00002223, 0x80000338, 0x00002225,
+ 0x80000338, 0x0000222b, 0x8000222b, 0x0000222b,
+ 0x0000222b, 0x8000222b, 0x0000222e, 0x8000222e,
+ 0x0000222e, 0x0000222e, 0x8000222e, 0x0000223c,
+ 0x80000338, 0x00002243, 0x80000338, 0x00002245,
+ 0x80000338, 0x00002248, 0x80000338, 0x0000003d,
+ 0x80000338, 0x00002261, 0x80000338, 0x0000224d,
+ 0x80000338, 0x0000003c, 0x80000338, 0x0000003e,
+ 0x80000338, 0x00002264, 0x80000338, 0x00002265,
+ 0x80000338, 0x00002272, 0x80000338, 0x00002273,
+ 0x80000338, 0x00002276, 0x80000338, 0x00002277,
+ 0x80000338, 0x0000227a, 0x80000338, 0x0000227b,
+ 0x80000338, 0x00002282, 0x80000338, 0x00002283,
+ 0x80000338, 0x00002286, 0x80000338, 0x00002287,
+ 0x80000338, 0x000022a2, 0x80000338, 0x000022a8,
+ 0x80000338, 0x000022a9, 0x80000338, 0x000022ab,
+ 0x80000338, 0x0000227c, 0x80000338, 0x0000227d,
+ 0x80000338, 0x00002291, 0x80000338, 0x00002292,
+ 0x80000338, 0x000022b2, 0x80000338, 0x000022b3,
+ 0x80000338, 0x000022b4, 0x80000338, 0x000022b5,
+ 0x80000338, 0x80003008, 0x80003009, 0x80000031,
+ 0x80000032, 0x80000033, 0x80000034, 0x80000035,
+ 0x80000036, 0x80000037, 0x80000038, 0x80000039,
+ 0x00000031, 0x80000030, 0x00000031, 0x80000031,
+ 0x00000031, 0x80000032, 0x00000031, 0x80000033,
+ 0x00000031, 0x80000034, 0x00000031, 0x80000035,
+ 0x00000031, 0x80000036, 0x00000031, 0x80000037,
+ 0x00000031, 0x80000038, 0x00000031, 0x80000039,
+ 0x00000032, 0x80000030, 0x00000028, 0x00000031,
+ 0x80000029, 0x00000028, 0x00000032, 0x80000029,
+ 0x00000028, 0x00000033, 0x80000029, 0x00000028,
+ 0x00000034, 0x80000029, 0x00000028, 0x00000035,
+ 0x80000029, 0x00000028, 0x00000036, 0x80000029,
+ 0x00000028, 0x00000037, 0x80000029, 0x00000028,
+ 0x00000038, 0x80000029, 0x00000028, 0x00000039,
+ 0x80000029, 0x00000028, 0x00000031, 0x00000030,
+ 0x80000029, 0x00000028, 0x00000031, 0x00000031,
+ 0x80000029, 0x00000028, 0x00000031, 0x00000032,
+ 0x80000029, 0x00000028, 0x00000031, 0x00000033,
+ 0x80000029, 0x00000028, 0x00000031, 0x00000034,
+ 0x80000029, 0x00000028, 0x00000031, 0x00000035,
+ 0x80000029, 0x00000028, 0x00000031, 0x00000036,
+ 0x80000029, 0x00000028, 0x00000031, 0x00000037,
+ 0x80000029, 0x00000028, 0x00000031, 0x00000038,
+ 0x80000029, 0x00000028, 0x00000031, 0x00000039,
+ 0x80000029, 0x00000028, 0x00000032, 0x00000030,
+ 0x80000029, 0x00000031, 0x8000002e, 0x00000032,
+ 0x8000002e, 0x00000033, 0x8000002e, 0x00000034,
+ 0x8000002e, 0x00000035, 0x8000002e, 0x00000036,
+ 0x8000002e, 0x00000037, 0x8000002e, 0x00000038,
+ 0x8000002e, 0x00000039, 0x8000002e, 0x00000031,
+ 0x00000030, 0x8000002e, 0x00000031, 0x00000031,
+ 0x8000002e, 0x00000031, 0x00000032, 0x8000002e,
+ 0x00000031, 0x00000033, 0x8000002e, 0x00000031,
+ 0x00000034, 0x8000002e, 0x00000031, 0x00000035,
+ 0x8000002e, 0x00000031, 0x00000036, 0x8000002e,
+ 0x00000031, 0x00000037, 0x8000002e, 0x00000031,
+ 0x00000038, 0x8000002e, 0x00000031, 0x00000039,
+ 0x8000002e, 0x00000032, 0x00000030, 0x8000002e,
+ 0x00000028, 0x00000061, 0x80000029, 0x00000028,
+ 0x00000062, 0x80000029, 0x00000028, 0x00000063,
+ 0x80000029, 0x00000028, 0x00000064, 0x80000029,
+ 0x00000028, 0x00000065, 0x80000029, 0x00000028,
+ 0x00000066, 0x80000029, 0x00000028, 0x00000067,
+ 0x80000029, 0x00000028, 0x00000068, 0x80000029,
+ 0x00000028, 0x00000069, 0x80000029, 0x00000028,
+ 0x0000006a, 0x80000029, 0x00000028, 0x0000006b,
+ 0x80000029, 0x00000028, 0x0000006c, 0x80000029,
+ 0x00000028, 0x0000006d, 0x80000029, 0x00000028,
+ 0x0000006e, 0x80000029, 0x00000028, 0x0000006f,
+ 0x80000029, 0x00000028, 0x00000070, 0x80000029,
+ 0x00000028, 0x00000071, 0x80000029, 0x00000028,
+ 0x00000072, 0x80000029, 0x00000028, 0x00000073,
+ 0x80000029, 0x00000028, 0x00000074, 0x80000029,
+ 0x00000028, 0x00000075, 0x80000029, 0x00000028,
+ 0x00000076, 0x80000029, 0x00000028, 0x00000077,
+ 0x80000029, 0x00000028, 0x00000078, 0x80000029,
+ 0x00000028, 0x00000079, 0x80000029, 0x00000028,
+ 0x0000007a, 0x80000029, 0x80000041, 0x80000042,
+ 0x80000043, 0x80000044, 0x80000045, 0x80000046,
+ 0x80000047, 0x80000048, 0x80000049, 0x8000004a,
+ 0x8000004b, 0x8000004c, 0x8000004d, 0x8000004e,
+ 0x8000004f, 0x80000050, 0x80000051, 0x80000052,
+ 0x80000053, 0x80000054, 0x80000055, 0x80000056,
+ 0x80000057, 0x80000058, 0x80000059, 0x8000005a,
+ 0x80000061, 0x80000062, 0x80000063, 0x80000064,
+ 0x80000065, 0x80000066, 0x80000067, 0x80000068,
+ 0x80000069, 0x8000006a, 0x8000006b, 0x8000006c,
+ 0x8000006d, 0x8000006e, 0x8000006f, 0x80000070,
+ 0x80000071, 0x80000072, 0x80000073, 0x80000074,
+ 0x80000075, 0x80000076, 0x80000077, 0x80000078,
+ 0x80000079, 0x8000007a, 0x80000030, 0x0000222b,
+ 0x0000222b, 0x0000222b, 0x8000222b, 0x0000003a,
+ 0x0000003a, 0x8000003d, 0x0000003d, 0x8000003d,
+ 0x0000003d, 0x0000003d, 0x8000003d, 0x00002add,
+ 0x80000338, 0x80006bcd, 0x80009f9f, 0x80004e00,
+ 0x80004e28, 0x80004e36, 0x80004e3f, 0x80004e59,
+ 0x80004e85, 0x80004e8c, 0x80004ea0, 0x80004eba,
+ 0x8000513f, 0x80005165, 0x8000516b, 0x80005182,
+ 0x80005196, 0x800051ab, 0x800051e0, 0x800051f5,
+ 0x80005200, 0x8000529b, 0x800052f9, 0x80005315,
+ 0x8000531a, 0x80005338, 0x80005341, 0x8000535c,
+ 0x80005369, 0x80005382, 0x800053b6, 0x800053c8,
+ 0x800053e3, 0x800056d7, 0x8000571f, 0x800058eb,
+ 0x80005902, 0x8000590a, 0x80005915, 0x80005927,
+ 0x80005973, 0x80005b50, 0x80005b80, 0x80005bf8,
+ 0x80005c0f, 0x80005c22, 0x80005c38, 0x80005c6e,
+ 0x80005c71, 0x80005ddb, 0x80005de5, 0x80005df1,
+ 0x80005dfe, 0x80005e72, 0x80005e7a, 0x80005e7f,
+ 0x80005ef4, 0x80005efe, 0x80005f0b, 0x80005f13,
+ 0x80005f50, 0x80005f61, 0x80005f73, 0x80005fc3,
+ 0x80006208, 0x80006236, 0x8000624b, 0x8000652f,
+ 0x80006534, 0x80006587, 0x80006597, 0x800065a4,
+ 0x800065b9, 0x800065e0, 0x800065e5, 0x800066f0,
+ 0x80006708, 0x80006728, 0x80006b20, 0x80006b62,
+ 0x80006b79, 0x80006bb3, 0x80006bcb, 0x80006bd4,
+ 0x80006bdb, 0x80006c0f, 0x80006c14, 0x80006c34,
+ 0x8000706b, 0x8000722a, 0x80007236, 0x8000723b,
+ 0x8000723f, 0x80007247, 0x80007259, 0x8000725b,
+ 0x800072ac, 0x80007384, 0x80007389, 0x800074dc,
+ 0x800074e6, 0x80007518, 0x8000751f, 0x80007528,
+ 0x80007530, 0x8000758b, 0x80007592, 0x80007676,
+ 0x8000767d, 0x800076ae, 0x800076bf, 0x800076ee,
+ 0x800077db, 0x800077e2, 0x800077f3, 0x8000793a,
+ 0x800079b8, 0x800079be, 0x80007a74, 0x80007acb,
+ 0x80007af9, 0x80007c73, 0x80007cf8, 0x80007f36,
+ 0x80007f51, 0x80007f8a, 0x80007fbd, 0x80008001,
+ 0x8000800c, 0x80008012, 0x80008033, 0x8000807f,
+ 0x80008089, 0x800081e3, 0x800081ea, 0x800081f3,
+ 0x800081fc, 0x8000820c, 0x8000821b, 0x8000821f,
+ 0x8000826e, 0x80008272, 0x80008278, 0x8000864d,
+ 0x8000866b, 0x80008840, 0x8000884c, 0x80008863,
+ 0x8000897e, 0x8000898b, 0x800089d2, 0x80008a00,
+ 0x80008c37, 0x80008c46, 0x80008c55, 0x80008c78,
+ 0x80008c9d, 0x80008d64, 0x80008d70, 0x80008db3,
+ 0x80008eab, 0x80008eca, 0x80008f9b, 0x80008fb0,
+ 0x80008fb5, 0x80009091, 0x80009149, 0x800091c6,
+ 0x800091cc, 0x800091d1, 0x80009577, 0x80009580,
+ 0x8000961c, 0x800096b6, 0x800096b9, 0x800096e8,
+ 0x80009751, 0x8000975e, 0x80009762, 0x80009769,
+ 0x800097cb, 0x800097ed, 0x800097f3, 0x80009801,
+ 0x800098a8, 0x800098db, 0x800098df, 0x80009996,
+ 0x80009999, 0x800099ac, 0x80009aa8, 0x80009ad8,
+ 0x80009adf, 0x80009b25, 0x80009b2f, 0x80009b32,
+ 0x80009b3c, 0x80009b5a, 0x80009ce5, 0x80009e75,
+ 0x80009e7f, 0x80009ea5, 0x80009ebb, 0x80009ec3,
+ 0x80009ecd, 0x80009ed1, 0x80009ef9, 0x80009efd,
+ 0x80009f0e, 0x80009f13, 0x80009f20, 0x80009f3b,
+ 0x80009f4a, 0x80009f52, 0x80009f8d, 0x80009f9c,
+ 0x80009fa0, 0x80000020, 0x80003012, 0x80005341,
+ 0x80005344, 0x80005345, 0x0000304b, 0x80003099,
+ 0x0000304d, 0x80003099, 0x0000304f, 0x80003099,
+ 0x00003051, 0x80003099, 0x00003053, 0x80003099,
+ 0x00003055, 0x80003099, 0x00003057, 0x80003099,
+ 0x00003059, 0x80003099, 0x0000305b, 0x80003099,
+ 0x0000305d, 0x80003099, 0x0000305f, 0x80003099,
+ 0x00003061, 0x80003099, 0x00003064, 0x80003099,
+ 0x00003066, 0x80003099, 0x00003068, 0x80003099,
+ 0x0000306f, 0x80003099, 0x0000306f, 0x8000309a,
+ 0x00003072, 0x80003099, 0x00003072, 0x8000309a,
+ 0x00003075, 0x80003099, 0x00003075, 0x8000309a,
+ 0x00003078, 0x80003099, 0x00003078, 0x8000309a,
+ 0x0000307b, 0x80003099, 0x0000307b, 0x8000309a,
+ 0x00003046, 0x80003099, 0x00000020, 0x80003099,
+ 0x00000020, 0x8000309a, 0x0000309d, 0x80003099,
+ 0x00003088, 0x8000308a, 0x000030ab, 0x80003099,
+ 0x000030ad, 0x80003099, 0x000030af, 0x80003099,
+ 0x000030b1, 0x80003099, 0x000030b3, 0x80003099,
+ 0x000030b5, 0x80003099, 0x000030b7, 0x80003099,
+ 0x000030b9, 0x80003099, 0x000030bb, 0x80003099,
+ 0x000030bd, 0x80003099, 0x000030bf, 0x80003099,
+ 0x000030c1, 0x80003099, 0x000030c4, 0x80003099,
+ 0x000030c6, 0x80003099, 0x000030c8, 0x80003099,
+ 0x000030cf, 0x80003099, 0x000030cf, 0x8000309a,
+ 0x000030d2, 0x80003099, 0x000030d2, 0x8000309a,
+ 0x000030d5, 0x80003099, 0x000030d5, 0x8000309a,
+ 0x000030d8, 0x80003099, 0x000030d8, 0x8000309a,
+ 0x000030db, 0x80003099, 0x000030db, 0x8000309a,
+ 0x000030a6, 0x80003099, 0x000030ef, 0x80003099,
+ 0x000030f0, 0x80003099, 0x000030f1, 0x80003099,
+ 0x000030f2, 0x80003099, 0x000030fd, 0x80003099,
+ 0x000030b3, 0x800030c8, 0x80001100, 0x80001101,
+ 0x800011aa, 0x80001102, 0x800011ac, 0x800011ad,
+ 0x80001103, 0x80001104, 0x80001105, 0x800011b0,
+ 0x800011b1, 0x800011b2, 0x800011b3, 0x800011b4,
+ 0x800011b5, 0x8000111a, 0x80001106, 0x80001107,
+ 0x80001108, 0x80001121, 0x80001109, 0x8000110a,
+ 0x8000110b, 0x8000110c, 0x8000110d, 0x8000110e,
+ 0x8000110f, 0x80001110, 0x80001111, 0x80001112,
+ 0x80001161, 0x80001162, 0x80001163, 0x80001164,
+ 0x80001165, 0x80001166, 0x80001167, 0x80001168,
+ 0x80001169, 0x8000116a, 0x8000116b, 0x8000116c,
+ 0x8000116d, 0x8000116e, 0x8000116f, 0x80001170,
+ 0x80001171, 0x80001172, 0x80001173, 0x80001174,
+ 0x80001175, 0x80001160, 0x80001114, 0x80001115,
+ 0x800011c7, 0x800011c8, 0x800011cc, 0x800011ce,
+ 0x800011d3, 0x800011d7, 0x800011d9, 0x8000111c,
+ 0x800011dd, 0x800011df, 0x8000111d, 0x8000111e,
+ 0x80001120, 0x80001122, 0x80001123, 0x80001127,
+ 0x80001129, 0x8000112b, 0x8000112c, 0x8000112d,
+ 0x8000112e, 0x8000112f, 0x80001132, 0x80001136,
+ 0x80001140, 0x80001147, 0x8000114c, 0x800011f1,
+ 0x800011f2, 0x80001157, 0x80001158, 0x80001159,
+ 0x80001184, 0x80001185, 0x80001188, 0x80001191,
+ 0x80001192, 0x80001194, 0x8000119e, 0x800011a1,
+ 0x80004e00, 0x80004e8c, 0x80004e09, 0x800056db,
+ 0x80004e0a, 0x80004e2d, 0x80004e0b, 0x80007532,
+ 0x80004e59, 0x80004e19, 0x80004e01, 0x80005929,
+ 0x80005730, 0x80004eba, 0x00000028, 0x00001100,
+ 0x80000029, 0x00000028, 0x00001102, 0x80000029,
+ 0x00000028, 0x00001103, 0x80000029, 0x00000028,
+ 0x00001105, 0x80000029, 0x00000028, 0x00001106,
+ 0x80000029, 0x00000028, 0x00001107, 0x80000029,
+ 0x00000028, 0x00001109, 0x80000029, 0x00000028,
+ 0x0000110b, 0x80000029, 0x00000028, 0x0000110c,
+ 0x80000029, 0x00000028, 0x0000110e, 0x80000029,
+ 0x00000028, 0x0000110f, 0x80000029, 0x00000028,
+ 0x00001110, 0x80000029, 0x00000028, 0x00001111,
+ 0x80000029, 0x00000028, 0x00001112, 0x80000029,
+ 0x00000028, 0x00001100, 0x00001161, 0x80000029,
+ 0x00000028, 0x00001102, 0x00001161, 0x80000029,
+ 0x00000028, 0x00001103, 0x00001161, 0x80000029,
+ 0x00000028, 0x00001105, 0x00001161, 0x80000029,
+ 0x00000028, 0x00001106, 0x00001161, 0x80000029,
+ 0x00000028, 0x00001107, 0x00001161, 0x80000029,
+ 0x00000028, 0x00001109, 0x00001161, 0x80000029,
+ 0x00000028, 0x0000110b, 0x00001161, 0x80000029,
+ 0x00000028, 0x0000110c, 0x00001161, 0x80000029,
+ 0x00000028, 0x0000110e, 0x00001161, 0x80000029,
+ 0x00000028, 0x0000110f, 0x00001161, 0x80000029,
+ 0x00000028, 0x00001110, 0x00001161, 0x80000029,
+ 0x00000028, 0x00001111, 0x00001161, 0x80000029,
+ 0x00000028, 0x00001112, 0x00001161, 0x80000029,
+ 0x00000028, 0x0000110c, 0x0000116e, 0x80000029,
+ 0x00000028, 0x00004e00, 0x80000029, 0x00000028,
+ 0x00004e8c, 0x80000029, 0x00000028, 0x00004e09,
+ 0x80000029, 0x00000028, 0x000056db, 0x80000029,
+ 0x00000028, 0x00004e94, 0x80000029, 0x00000028,
+ 0x0000516d, 0x80000029, 0x00000028, 0x00004e03,
+ 0x80000029, 0x00000028, 0x0000516b, 0x80000029,
+ 0x00000028, 0x00004e5d, 0x80000029, 0x00000028,
+ 0x00005341, 0x80000029, 0x00000028, 0x00006708,
+ 0x80000029, 0x00000028, 0x0000706b, 0x80000029,
+ 0x00000028, 0x00006c34, 0x80000029, 0x00000028,
+ 0x00006728, 0x80000029, 0x00000028, 0x000091d1,
+ 0x80000029, 0x00000028, 0x0000571f, 0x80000029,
+ 0x00000028, 0x000065e5, 0x80000029, 0x00000028,
+ 0x0000682a, 0x80000029, 0x00000028, 0x00006709,
+ 0x80000029, 0x00000028, 0x0000793e, 0x80000029,
+ 0x00000028, 0x0000540d, 0x80000029, 0x00000028,
+ 0x00007279, 0x80000029, 0x00000028, 0x00008ca1,
+ 0x80000029, 0x00000028, 0x0000795d, 0x80000029,
+ 0x00000028, 0x000052b4, 0x80000029, 0x00000028,
+ 0x00004ee3, 0x80000029, 0x00000028, 0x0000547c,
+ 0x80000029, 0x00000028, 0x00005b66, 0x80000029,
+ 0x00000028, 0x000076e3, 0x80000029, 0x00000028,
+ 0x00004f01, 0x80000029, 0x00000028, 0x00008cc7,
+ 0x80000029, 0x00000028, 0x00005354, 0x80000029,
+ 0x00000028, 0x0000796d, 0x80000029, 0x00000028,
+ 0x00004f11, 0x80000029, 0x00000028, 0x000081ea,
+ 0x80000029, 0x00000028, 0x000081f3, 0x80000029,
+ 0x00000032, 0x80000031, 0x00000032, 0x80000032,
+ 0x00000032, 0x80000033, 0x00000032, 0x80000034,
+ 0x00000032, 0x80000035, 0x00000032, 0x80000036,
+ 0x00000032, 0x80000037, 0x00000032, 0x80000038,
+ 0x00000032, 0x80000039, 0x00000033, 0x80000030,
+ 0x00000033, 0x80000031, 0x00000033, 0x80000032,
+ 0x00000033, 0x80000033, 0x00000033, 0x80000034,
+ 0x00000033, 0x80000035, 0x80001100, 0x80001102,
+ 0x80001103, 0x80001105, 0x80001106, 0x80001107,
+ 0x80001109, 0x8000110b, 0x8000110c, 0x8000110e,
+ 0x8000110f, 0x80001110, 0x80001111, 0x80001112,
+ 0x00001100, 0x80001161, 0x00001102, 0x80001161,
+ 0x00001103, 0x80001161, 0x00001105, 0x80001161,
+ 0x00001106, 0x80001161, 0x00001107, 0x80001161,
+ 0x00001109, 0x80001161, 0x0000110b, 0x80001161,
+ 0x0000110c, 0x80001161, 0x0000110e, 0x80001161,
+ 0x0000110f, 0x80001161, 0x00001110, 0x80001161,
+ 0x00001111, 0x80001161, 0x00001112, 0x80001161,
+ 0x80004e00, 0x80004e8c, 0x80004e09, 0x800056db,
+ 0x80004e94, 0x8000516d, 0x80004e03, 0x8000516b,
+ 0x80004e5d, 0x80005341, 0x80006708, 0x8000706b,
+ 0x80006c34, 0x80006728, 0x800091d1, 0x8000571f,
+ 0x800065e5, 0x8000682a, 0x80006709, 0x8000793e,
+ 0x8000540d, 0x80007279, 0x80008ca1, 0x8000795d,
+ 0x800052b4, 0x800079d8, 0x80007537, 0x80005973,
+ 0x80009069, 0x8000512a, 0x80005370, 0x80006ce8,
+ 0x80009805, 0x80004f11, 0x80005199, 0x80006b63,
+ 0x80004e0a, 0x80004e2d, 0x80004e0b, 0x80005de6,
+ 0x800053f3, 0x8000533b, 0x80005b97, 0x80005b66,
+ 0x800076e3, 0x80004f01, 0x80008cc7, 0x80005354,
+ 0x8000591c, 0x00000033, 0x80000036, 0x00000033,
+ 0x80000037, 0x00000033, 0x80000038, 0x00000033,
+ 0x80000039, 0x00000034, 0x80000030, 0x00000034,
+ 0x80000031, 0x00000034, 0x80000032, 0x00000034,
+ 0x80000033, 0x00000034, 0x80000034, 0x00000034,
+ 0x80000035, 0x00000034, 0x80000036, 0x00000034,
+ 0x80000037, 0x00000034, 0x80000038, 0x00000034,
+ 0x80000039, 0x00000035, 0x80000030, 0x00000031,
+ 0x80006708, 0x00000032, 0x80006708, 0x00000033,
+ 0x80006708, 0x00000034, 0x80006708, 0x00000035,
+ 0x80006708, 0x00000036, 0x80006708, 0x00000037,
+ 0x80006708, 0x00000038, 0x80006708, 0x00000039,
+ 0x80006708, 0x00000031, 0x00000030, 0x80006708,
+ 0x00000031, 0x00000031, 0x80006708, 0x00000031,
+ 0x00000032, 0x80006708, 0x800030a2, 0x800030a4,
+ 0x800030a6, 0x800030a8, 0x800030aa, 0x800030ab,
+ 0x800030ad, 0x800030af, 0x800030b1, 0x800030b3,
+ 0x800030b5, 0x800030b7, 0x800030b9, 0x800030bb,
+ 0x800030bd, 0x800030bf, 0x800030c1, 0x800030c4,
+ 0x800030c6, 0x800030c8, 0x800030ca, 0x800030cb,
+ 0x800030cc, 0x800030cd, 0x800030ce, 0x800030cf,
+ 0x800030d2, 0x800030d5, 0x800030d8, 0x800030db,
+ 0x800030de, 0x800030df, 0x800030e0, 0x800030e1,
+ 0x800030e2, 0x800030e4, 0x800030e6, 0x800030e8,
+ 0x800030e9, 0x800030ea, 0x800030eb, 0x800030ec,
+ 0x800030ed, 0x800030ef, 0x800030f0, 0x800030f1,
+ 0x800030f2, 0x000030a2, 0x000030d1, 0x000030fc,
+ 0x800030c8, 0x000030a2, 0x000030eb, 0x000030d5,
+ 0x800030a1, 0x000030a2, 0x000030f3, 0x000030da,
+ 0x800030a2, 0x000030a2, 0x000030fc, 0x800030eb,
+ 0x000030a4, 0x000030cb, 0x000030f3, 0x800030b0,
+ 0x000030a4, 0x000030f3, 0x800030c1, 0x000030a6,
+ 0x000030a9, 0x800030f3, 0x000030a8, 0x000030b9,
+ 0x000030af, 0x000030fc, 0x800030c9, 0x000030a8,
+ 0x000030fc, 0x000030ab, 0x800030fc, 0x000030aa,
+ 0x000030f3, 0x800030b9, 0x000030aa, 0x000030fc,
+ 0x800030e0, 0x000030ab, 0x000030a4, 0x800030ea,
+ 0x000030ab, 0x000030e9, 0x000030c3, 0x800030c8,
+ 0x000030ab, 0x000030ed, 0x000030ea, 0x800030fc,
+ 0x000030ac, 0x000030ed, 0x800030f3, 0x000030ac,
+ 0x000030f3, 0x800030de, 0x000030ae, 0x800030ac,
+ 0x000030ae, 0x000030cb, 0x800030fc, 0x000030ad,
+ 0x000030e5, 0x000030ea, 0x800030fc, 0x000030ae,
+ 0x000030eb, 0x000030c0, 0x800030fc, 0x000030ad,
+ 0x800030ed, 0x000030ad, 0x000030ed, 0x000030b0,
+ 0x000030e9, 0x800030e0, 0x000030ad, 0x000030ed,
+ 0x000030e1, 0x000030fc, 0x000030c8, 0x800030eb,
+ 0x000030ad, 0x000030ed, 0x000030ef, 0x000030c3,
+ 0x800030c8, 0x000030b0, 0x000030e9, 0x800030e0,
+ 0x000030b0, 0x000030e9, 0x000030e0, 0x000030c8,
+ 0x800030f3, 0x000030af, 0x000030eb, 0x000030bc,
+ 0x000030a4, 0x800030ed, 0x000030af, 0x000030ed,
+ 0x000030fc, 0x800030cd, 0x000030b1, 0x000030fc,
+ 0x800030b9, 0x000030b3, 0x000030eb, 0x800030ca,
+ 0x000030b3, 0x000030fc, 0x800030dd, 0x000030b5,
+ 0x000030a4, 0x000030af, 0x800030eb, 0x000030b5,
+ 0x000030f3, 0x000030c1, 0x000030fc, 0x800030e0,
+ 0x000030b7, 0x000030ea, 0x000030f3, 0x800030b0,
+ 0x000030bb, 0x000030f3, 0x800030c1, 0x000030bb,
+ 0x000030f3, 0x800030c8, 0x000030c0, 0x000030fc,
+ 0x800030b9, 0x000030c7, 0x800030b7, 0x000030c9,
+ 0x800030eb, 0x000030c8, 0x800030f3, 0x000030ca,
+ 0x800030ce, 0x000030ce, 0x000030c3, 0x800030c8,
+ 0x000030cf, 0x000030a4, 0x800030c4, 0x000030d1,
+ 0x000030fc, 0x000030bb, 0x000030f3, 0x800030c8,
+ 0x000030d1, 0x000030fc, 0x800030c4, 0x000030d0,
+ 0x000030fc, 0x000030ec, 0x800030eb, 0x000030d4,
+ 0x000030a2, 0x000030b9, 0x000030c8, 0x800030eb,
+ 0x000030d4, 0x000030af, 0x800030eb, 0x000030d4,
+ 0x800030b3, 0x000030d3, 0x800030eb, 0x000030d5,
+ 0x000030a1, 0x000030e9, 0x000030c3, 0x800030c9,
+ 0x000030d5, 0x000030a3, 0x000030fc, 0x800030c8,
+ 0x000030d6, 0x000030c3, 0x000030b7, 0x000030a7,
+ 0x800030eb, 0x000030d5, 0x000030e9, 0x800030f3,
+ 0x000030d8, 0x000030af, 0x000030bf, 0x000030fc,
+ 0x800030eb, 0x000030da, 0x800030bd, 0x000030da,
+ 0x000030cb, 0x800030d2, 0x000030d8, 0x000030eb,
+ 0x800030c4, 0x000030da, 0x000030f3, 0x800030b9,
+ 0x000030da, 0x000030fc, 0x800030b8, 0x000030d9,
+ 0x000030fc, 0x800030bf, 0x000030dd, 0x000030a4,
+ 0x000030f3, 0x800030c8, 0x000030dc, 0x000030eb,
+ 0x800030c8, 0x000030db, 0x800030f3, 0x000030dd,
+ 0x000030f3, 0x800030c9, 0x000030db, 0x000030fc,
+ 0x800030eb, 0x000030db, 0x000030fc, 0x800030f3,
+ 0x000030de, 0x000030a4, 0x000030af, 0x800030ed,
+ 0x000030de, 0x000030a4, 0x800030eb, 0x000030de,
+ 0x000030c3, 0x800030cf, 0x000030de, 0x000030eb,
+ 0x800030af, 0x000030de, 0x000030f3, 0x000030b7,
+ 0x000030e7, 0x800030f3, 0x000030df, 0x000030af,
+ 0x000030ed, 0x800030f3, 0x000030df, 0x800030ea,
+ 0x000030df, 0x000030ea, 0x000030d0, 0x000030fc,
+ 0x800030eb, 0x000030e1, 0x800030ac, 0x000030e1,
+ 0x000030ac, 0x000030c8, 0x800030f3, 0x000030e1,
+ 0x000030fc, 0x000030c8, 0x800030eb, 0x000030e4,
+ 0x000030fc, 0x800030c9, 0x000030e4, 0x000030fc,
+ 0x800030eb, 0x000030e6, 0x000030a2, 0x800030f3,
+ 0x000030ea, 0x000030c3, 0x000030c8, 0x800030eb,
+ 0x000030ea, 0x800030e9, 0x000030eb, 0x000030d4,
+ 0x800030fc, 0x000030eb, 0x000030fc, 0x000030d6,
+ 0x800030eb, 0x000030ec, 0x800030e0, 0x000030ec,
+ 0x000030f3, 0x000030c8, 0x000030b2, 0x800030f3,
+ 0x000030ef, 0x000030c3, 0x800030c8, 0x00000030,
+ 0x800070b9, 0x00000031, 0x800070b9, 0x00000032,
+ 0x800070b9, 0x00000033, 0x800070b9, 0x00000034,
+ 0x800070b9, 0x00000035, 0x800070b9, 0x00000036,
+ 0x800070b9, 0x00000037, 0x800070b9, 0x00000038,
+ 0x800070b9, 0x00000039, 0x800070b9, 0x00000031,
+ 0x00000030, 0x800070b9, 0x00000031, 0x00000031,
+ 0x800070b9, 0x00000031, 0x00000032, 0x800070b9,
+ 0x00000031, 0x00000033, 0x800070b9, 0x00000031,
+ 0x00000034, 0x800070b9, 0x00000031, 0x00000035,
+ 0x800070b9, 0x00000031, 0x00000036, 0x800070b9,
+ 0x00000031, 0x00000037, 0x800070b9, 0x00000031,
+ 0x00000038, 0x800070b9, 0x00000031, 0x00000039,
+ 0x800070b9, 0x00000032, 0x00000030, 0x800070b9,
+ 0x00000032, 0x00000031, 0x800070b9, 0x00000032,
+ 0x00000032, 0x800070b9, 0x00000032, 0x00000033,
+ 0x800070b9, 0x00000032, 0x00000034, 0x800070b9,
+ 0x00000068, 0x00000050, 0x80000061, 0x00000064,
+ 0x80000061, 0x00000041, 0x80000055, 0x00000062,
+ 0x00000061, 0x80000072, 0x0000006f, 0x80000056,
+ 0x00000070, 0x80000063, 0x00005e73, 0x80006210,
+ 0x0000662d, 0x8000548c, 0x00005927, 0x80006b63,
+ 0x0000660e, 0x80006cbb, 0x0000682a, 0x00005f0f,
+ 0x00004f1a, 0x8000793e, 0x00000070, 0x80000041,
+ 0x0000006e, 0x80000041, 0x000003bc, 0x80000041,
+ 0x0000006d, 0x80000041, 0x0000006b, 0x80000041,
+ 0x0000004b, 0x80000042, 0x0000004d, 0x80000042,
+ 0x00000047, 0x80000042, 0x00000063, 0x00000061,
+ 0x8000006c, 0x0000006b, 0x00000063, 0x00000061,
+ 0x8000006c, 0x00000070, 0x80000046, 0x0000006e,
+ 0x80000046, 0x000003bc, 0x80000046, 0x000003bc,
+ 0x80000067, 0x0000006d, 0x80000067, 0x0000006b,
+ 0x80000067, 0x00000048, 0x8000007a, 0x0000006b,
+ 0x00000048, 0x8000007a, 0x0000004d, 0x00000048,
+ 0x8000007a, 0x00000047, 0x00000048, 0x8000007a,
+ 0x00000054, 0x00000048, 0x8000007a, 0x000003bc,
+ 0x80002113, 0x0000006d, 0x80002113, 0x00000064,
+ 0x80002113, 0x0000006b, 0x80002113, 0x00000066,
+ 0x8000006d, 0x0000006e, 0x8000006d, 0x000003bc,
+ 0x8000006d, 0x0000006d, 0x8000006d, 0x00000063,
+ 0x8000006d, 0x0000006b, 0x8000006d, 0x0000006d,
+ 0x0000006d, 0x800000b2, 0x00000063, 0x0000006d,
+ 0x800000b2, 0x0000006d, 0x800000b2, 0x0000006b,
+ 0x0000006d, 0x800000b2, 0x0000006d, 0x0000006d,
+ 0x800000b3, 0x00000063, 0x0000006d, 0x800000b3,
+ 0x0000006d, 0x800000b3, 0x0000006b, 0x0000006d,
+ 0x800000b3, 0x0000006d, 0x00002215, 0x80000073,
+ 0x0000006d, 0x00002215, 0x00000073, 0x800000b2,
+ 0x00000050, 0x80000061, 0x0000006b, 0x00000050,
+ 0x80000061, 0x0000004d, 0x00000050, 0x80000061,
+ 0x00000047, 0x00000050, 0x80000061, 0x00000072,
+ 0x00000061, 0x80000064, 0x00000072, 0x00000061,
+ 0x00000064, 0x00002215, 0x80000073, 0x00000072,
+ 0x00000061, 0x00000064, 0x00002215, 0x00000073,
+ 0x800000b2, 0x00000070, 0x80000073, 0x0000006e,
+ 0x80000073, 0x000003bc, 0x80000073, 0x0000006d,
+ 0x80000073, 0x00000070, 0x80000056, 0x0000006e,
+ 0x80000056, 0x000003bc, 0x80000056, 0x0000006d,
+ 0x80000056, 0x0000006b, 0x80000056, 0x0000004d,
+ 0x80000056, 0x00000070, 0x80000057, 0x0000006e,
+ 0x80000057, 0x000003bc, 0x80000057, 0x0000006d,
+ 0x80000057, 0x0000006b, 0x80000057, 0x0000004d,
+ 0x80000057, 0x0000006b, 0x800003a9, 0x0000004d,
+ 0x800003a9, 0x00000061, 0x0000002e, 0x0000006d,
+ 0x8000002e, 0x00000042, 0x80000071, 0x00000063,
+ 0x80000063, 0x00000063, 0x80000064, 0x00000043,
+ 0x00002215, 0x0000006b, 0x80000067, 0x00000043,
+ 0x0000006f, 0x8000002e, 0x00000064, 0x80000042,
+ 0x00000047, 0x80000079, 0x00000068, 0x80000061,
+ 0x00000048, 0x80000050, 0x00000069, 0x8000006e,
+ 0x0000004b, 0x8000004b, 0x0000004b, 0x8000004d,
+ 0x0000006b, 0x80000074, 0x0000006c, 0x8000006d,
+ 0x0000006c, 0x8000006e, 0x0000006c, 0x0000006f,
+ 0x80000067, 0x0000006c, 0x80000078, 0x0000006d,
+ 0x80000062, 0x0000006d, 0x00000069, 0x8000006c,
+ 0x0000006d, 0x0000006f, 0x8000006c, 0x00000050,
+ 0x80000048, 0x00000070, 0x0000002e, 0x0000006d,
+ 0x8000002e, 0x00000050, 0x00000050, 0x8000004d,
+ 0x00000050, 0x80000052, 0x00000073, 0x80000072,
+ 0x00000053, 0x80000076, 0x00000057, 0x80000062,
+ 0x00000031, 0x800065e5, 0x00000032, 0x800065e5,
+ 0x00000033, 0x800065e5, 0x00000034, 0x800065e5,
+ 0x00000035, 0x800065e5, 0x00000036, 0x800065e5,
+ 0x00000037, 0x800065e5, 0x00000038, 0x800065e5,
+ 0x00000039, 0x800065e5, 0x00000031, 0x00000030,
+ 0x800065e5, 0x00000031, 0x00000031, 0x800065e5,
+ 0x00000031, 0x00000032, 0x800065e5, 0x00000031,
+ 0x00000033, 0x800065e5, 0x00000031, 0x00000034,
+ 0x800065e5, 0x00000031, 0x00000035, 0x800065e5,
+ 0x00000031, 0x00000036, 0x800065e5, 0x00000031,
+ 0x00000037, 0x800065e5, 0x00000031, 0x00000038,
+ 0x800065e5, 0x00000031, 0x00000039, 0x800065e5,
+ 0x00000032, 0x00000030, 0x800065e5, 0x00000032,
+ 0x00000031, 0x800065e5, 0x00000032, 0x00000032,
+ 0x800065e5, 0x00000032, 0x00000033, 0x800065e5,
+ 0x00000032, 0x00000034, 0x800065e5, 0x00000032,
+ 0x00000035, 0x800065e5, 0x00000032, 0x00000036,
+ 0x800065e5, 0x00000032, 0x00000037, 0x800065e5,
+ 0x00000032, 0x00000038, 0x800065e5, 0x00000032,
+ 0x00000039, 0x800065e5, 0x00000033, 0x00000030,
+ 0x800065e5, 0x00000033, 0x00000031, 0x800065e5,
+ 0x80008c48, 0x800066f4, 0x80008eca, 0x80008cc8,
+ 0x80006ed1, 0x80004e32, 0x800053e5, 0x80009f9c,
+ 0x80009f9c, 0x80005951, 0x800091d1, 0x80005587,
+ 0x80005948, 0x800061f6, 0x80007669, 0x80007f85,
+ 0x8000863f, 0x800087ba, 0x800088f8, 0x8000908f,
+ 0x80006a02, 0x80006d1b, 0x800070d9, 0x800073de,
+ 0x8000843d, 0x8000916a, 0x800099f1, 0x80004e82,
+ 0x80005375, 0x80006b04, 0x8000721b, 0x8000862d,
+ 0x80009e1e, 0x80005d50, 0x80006feb, 0x800085cd,
+ 0x80008964, 0x800062c9, 0x800081d8, 0x8000881f,
+ 0x80005eca, 0x80006717, 0x80006d6a, 0x800072fc,
+ 0x800090ce, 0x80004f86, 0x800051b7, 0x800052de,
+ 0x800064c4, 0x80006ad3, 0x80007210, 0x800076e7,
+ 0x80008001, 0x80008606, 0x8000865c, 0x80008def,
+ 0x80009732, 0x80009b6f, 0x80009dfa, 0x8000788c,
+ 0x8000797f, 0x80007da0, 0x800083c9, 0x80009304,
+ 0x80009e7f, 0x80008ad6, 0x800058df, 0x80005f04,
+ 0x80007c60, 0x8000807e, 0x80007262, 0x800078ca,
+ 0x80008cc2, 0x800096f7, 0x800058d8, 0x80005c62,
+ 0x80006a13, 0x80006dda, 0x80006f0f, 0x80007d2f,
+ 0x80007e37, 0x8000964b, 0x800052d2, 0x8000808b,
+ 0x800051dc, 0x800051cc, 0x80007a1c, 0x80007dbe,
+ 0x800083f1, 0x80009675, 0x80008b80, 0x800062cf,
+ 0x80006a02, 0x80008afe, 0x80004e39, 0x80005be7,
+ 0x80006012, 0x80007387, 0x80007570, 0x80005317,
+ 0x800078fb, 0x80004fbf, 0x80005fa9, 0x80004e0d,
+ 0x80006ccc, 0x80006578, 0x80007d22, 0x800053c3,
+ 0x8000585e, 0x80007701, 0x80008449, 0x80008aaa,
+ 0x80006bba, 0x80008fb0, 0x80006c88, 0x800062fe,
+ 0x800082e5, 0x800063a0, 0x80007565, 0x80004eae,
+ 0x80005169, 0x800051c9, 0x80006881, 0x80007ce7,
+ 0x8000826f, 0x80008ad2, 0x800091cf, 0x800052f5,
+ 0x80005442, 0x80005973, 0x80005eec, 0x800065c5,
+ 0x80006ffe, 0x8000792a, 0x800095ad, 0x80009a6a,
+ 0x80009e97, 0x80009ece, 0x8000529b, 0x800066c6,
+ 0x80006b77, 0x80008f62, 0x80005e74, 0x80006190,
+ 0x80006200, 0x8000649a, 0x80006f23, 0x80007149,
+ 0x80007489, 0x800079ca, 0x80007df4, 0x8000806f,
+ 0x80008f26, 0x800084ee, 0x80009023, 0x8000934a,
+ 0x80005217, 0x800052a3, 0x800054bd, 0x800070c8,
+ 0x800088c2, 0x80008aaa, 0x80005ec9, 0x80005ff5,
+ 0x8000637b, 0x80006bae, 0x80007c3e, 0x80007375,
+ 0x80004ee4, 0x800056f9, 0x80005be7, 0x80005dba,
+ 0x8000601c, 0x800073b2, 0x80007469, 0x80007f9a,
+ 0x80008046, 0x80009234, 0x800096f6, 0x80009748,
+ 0x80009818, 0x80004f8b, 0x800079ae, 0x800091b4,
+ 0x800096b8, 0x800060e1, 0x80004e86, 0x800050da,
+ 0x80005bee, 0x80005c3f, 0x80006599, 0x80006a02,
+ 0x800071ce, 0x80007642, 0x800084fc, 0x8000907c,
+ 0x80009f8d, 0x80006688, 0x8000962e, 0x80005289,
+ 0x8000677b, 0x800067f3, 0x80006d41, 0x80006e9c,
+ 0x80007409, 0x80007559, 0x8000786b, 0x80007d10,
+ 0x8000985e, 0x8000516d, 0x8000622e, 0x80009678,
+ 0x8000502b, 0x80005d19, 0x80006dea, 0x80008f2a,
+ 0x80005f8b, 0x80006144, 0x80006817, 0x80007387,
+ 0x80009686, 0x80005229, 0x8000540f, 0x80005c65,
+ 0x80006613, 0x8000674e, 0x800068a8, 0x80006ce5,
+ 0x80007406, 0x800075e2, 0x80007f79, 0x800088cf,
+ 0x800088e1, 0x800091cc, 0x800096e2, 0x8000533f,
+ 0x80006eba, 0x8000541d, 0x800071d0, 0x80007498,
+ 0x800085fa, 0x800096a3, 0x80009c57, 0x80009e9f,
+ 0x80006797, 0x80006dcb, 0x800081e8, 0x80007acb,
+ 0x80007b20, 0x80007c92, 0x800072c0, 0x80007099,
+ 0x80008b58, 0x80004ec0, 0x80008336, 0x8000523a,
+ 0x80005207, 0x80005ea6, 0x800062d3, 0x80007cd6,
+ 0x80005b85, 0x80006d1e, 0x800066b4, 0x80008f3b,
+ 0x8000884c, 0x8000964d, 0x8000898b, 0x80005ed3,
+ 0x80005140, 0x800055c0, 0x8000585a, 0x80006674,
+ 0x800051de, 0x8000732a, 0x800076ca, 0x8000793c,
+ 0x8000795e, 0x80007965, 0x8000798f, 0x80009756,
+ 0x80007cbe, 0x80007fbd, 0x80008612, 0x80008af8,
+ 0x80009038, 0x800090fd, 0x800098ef, 0x800098fc,
+ 0x80009928, 0x80009db4, 0x80004fae, 0x800050e7,
+ 0x8000514d, 0x800052c9, 0x800052e4, 0x80005351,
+ 0x8000559d, 0x80005606, 0x80005668, 0x80005840,
+ 0x800058a8, 0x80005c64, 0x80005c6e, 0x80006094,
+ 0x80006168, 0x8000618e, 0x800061f2, 0x8000654f,
+ 0x800065e2, 0x80006691, 0x80006885, 0x80006d77,
+ 0x80006e1a, 0x80006f22, 0x8000716e, 0x8000722b,
+ 0x80007422, 0x80007891, 0x8000793e, 0x80007949,
+ 0x80007948, 0x80007950, 0x80007956, 0x8000795d,
+ 0x8000798d, 0x8000798e, 0x80007a40, 0x80007a81,
+ 0x80007bc0, 0x80007df4, 0x80007e09, 0x80007e41,
+ 0x80007f72, 0x80008005, 0x800081ed, 0x80008279,
+ 0x80008279, 0x80008457, 0x80008910, 0x80008996,
+ 0x80008b01, 0x80008b39, 0x80008cd3, 0x80008d08,
+ 0x80008fb6, 0x80009038, 0x800096e3, 0x800097ff,
+ 0x8000983b, 0x00000066, 0x80000066, 0x00000066,
+ 0x80000069, 0x00000066, 0x8000006c, 0x00000066,
+ 0x00000066, 0x80000069, 0x00000066, 0x00000066,
+ 0x8000006c, 0x0000017f, 0x80000074, 0x00000073,
+ 0x80000074, 0x00000574, 0x80000576, 0x00000574,
+ 0x80000565, 0x00000574, 0x8000056b, 0x0000057e,
+ 0x80000576, 0x00000574, 0x8000056d, 0x000005d9,
+ 0x800005b4, 0x000005f2, 0x800005b7, 0x800005e2,
+ 0x800005d0, 0x800005d3, 0x800005d4, 0x800005db,
+ 0x800005dc, 0x800005dd, 0x800005e8, 0x800005ea,
+ 0x8000002b, 0x000005e9, 0x800005c1, 0x000005e9,
+ 0x800005c2, 0x0000fb49, 0x800005c1, 0x0000fb49,
+ 0x800005c2, 0x000005d0, 0x800005b7, 0x000005d0,
+ 0x800005b8, 0x000005d0, 0x800005bc, 0x000005d1,
+ 0x800005bc, 0x000005d2, 0x800005bc, 0x000005d3,
+ 0x800005bc, 0x000005d4, 0x800005bc, 0x000005d5,
+ 0x800005bc, 0x000005d6, 0x800005bc, 0x000005d8,
+ 0x800005bc, 0x000005d9, 0x800005bc, 0x000005da,
+ 0x800005bc, 0x000005db, 0x800005bc, 0x000005dc,
+ 0x800005bc, 0x000005de, 0x800005bc, 0x000005e0,
+ 0x800005bc, 0x000005e1, 0x800005bc, 0x000005e3,
+ 0x800005bc, 0x000005e4, 0x800005bc, 0x000005e6,
+ 0x800005bc, 0x000005e7, 0x800005bc, 0x000005e8,
+ 0x800005bc, 0x000005e9, 0x800005bc, 0x000005ea,
+ 0x800005bc, 0x000005d5, 0x800005b9, 0x000005d1,
+ 0x800005bf, 0x000005db, 0x800005bf, 0x000005e4,
+ 0x800005bf, 0x000005d0, 0x800005dc, 0x80000671,
+ 0x80000671, 0x8000067b, 0x8000067b, 0x8000067b,
+ 0x8000067b, 0x8000067e, 0x8000067e, 0x8000067e,
+ 0x8000067e, 0x80000680, 0x80000680, 0x80000680,
+ 0x80000680, 0x8000067a, 0x8000067a, 0x8000067a,
+ 0x8000067a, 0x8000067f, 0x8000067f, 0x8000067f,
+ 0x8000067f, 0x80000679, 0x80000679, 0x80000679,
+ 0x80000679, 0x800006a4, 0x800006a4, 0x800006a4,
+ 0x800006a4, 0x800006a6, 0x800006a6, 0x800006a6,
+ 0x800006a6, 0x80000684, 0x80000684, 0x80000684,
+ 0x80000684, 0x80000683, 0x80000683, 0x80000683,
+ 0x80000683, 0x80000686, 0x80000686, 0x80000686,
+ 0x80000686, 0x80000687, 0x80000687, 0x80000687,
+ 0x80000687, 0x8000068d, 0x8000068d, 0x8000068c,
+ 0x8000068c, 0x8000068e, 0x8000068e, 0x80000688,
+ 0x80000688, 0x80000698, 0x80000698, 0x80000691,
+ 0x80000691, 0x800006a9, 0x800006a9, 0x800006a9,
+ 0x800006a9, 0x800006af, 0x800006af, 0x800006af,
+ 0x800006af, 0x800006b3, 0x800006b3, 0x800006b3,
+ 0x800006b3, 0x800006b1, 0x800006b1, 0x800006b1,
+ 0x800006b1, 0x800006ba, 0x800006ba, 0x800006bb,
+ 0x800006bb, 0x800006bb, 0x800006bb, 0x800006c0,
+ 0x800006c0, 0x800006c1, 0x800006c1, 0x800006c1,
+ 0x800006c1, 0x800006be, 0x800006be, 0x800006be,
+ 0x800006be, 0x800006d2, 0x800006d2, 0x800006d3,
+ 0x800006d3, 0x800006ad, 0x800006ad, 0x800006ad,
+ 0x800006ad, 0x800006c7, 0x800006c7, 0x800006c6,
+ 0x800006c6, 0x800006c8, 0x800006c8, 0x80000677,
+ 0x800006cb, 0x800006cb, 0x800006c5, 0x800006c5,
+ 0x800006c9, 0x800006c9, 0x800006d0, 0x800006d0,
+ 0x800006d0, 0x800006d0, 0x80000649, 0x80000649,
+ 0x00000626, 0x80000627, 0x00000626, 0x80000627,
+ 0x00000626, 0x800006d5, 0x00000626, 0x800006d5,
+ 0x00000626, 0x80000648, 0x00000626, 0x80000648,
+ 0x00000626, 0x800006c7, 0x00000626, 0x800006c7,
+ 0x00000626, 0x800006c6, 0x00000626, 0x800006c6,
+ 0x00000626, 0x800006c8, 0x00000626, 0x800006c8,
+ 0x00000626, 0x800006d0, 0x00000626, 0x800006d0,
+ 0x00000626, 0x800006d0, 0x00000626, 0x80000649,
+ 0x00000626, 0x80000649, 0x00000626, 0x80000649,
+ 0x800006cc, 0x800006cc, 0x800006cc, 0x800006cc,
+ 0x00000626, 0x8000062c, 0x00000626, 0x8000062d,
+ 0x00000626, 0x80000645, 0x00000626, 0x80000649,
+ 0x00000626, 0x8000064a, 0x00000628, 0x8000062c,
+ 0x00000628, 0x8000062d, 0x00000628, 0x8000062e,
+ 0x00000628, 0x80000645, 0x00000628, 0x80000649,
+ 0x00000628, 0x8000064a, 0x0000062a, 0x8000062c,
+ 0x0000062a, 0x8000062d, 0x0000062a, 0x8000062e,
+ 0x0000062a, 0x80000645, 0x0000062a, 0x80000649,
+ 0x0000062a, 0x8000064a, 0x0000062b, 0x8000062c,
+ 0x0000062b, 0x80000645, 0x0000062b, 0x80000649,
+ 0x0000062b, 0x8000064a, 0x0000062c, 0x8000062d,
+ 0x0000062c, 0x80000645, 0x0000062d, 0x8000062c,
+ 0x0000062d, 0x80000645, 0x0000062e, 0x8000062c,
+ 0x0000062e, 0x8000062d, 0x0000062e, 0x80000645,
+ 0x00000633, 0x8000062c, 0x00000633, 0x8000062d,
+ 0x00000633, 0x8000062e, 0x00000633, 0x80000645,
+ 0x00000635, 0x8000062d, 0x00000635, 0x80000645,
+ 0x00000636, 0x8000062c, 0x00000636, 0x8000062d,
+ 0x00000636, 0x8000062e, 0x00000636, 0x80000645,
+ 0x00000637, 0x8000062d, 0x00000637, 0x80000645,
+ 0x00000638, 0x80000645, 0x00000639, 0x8000062c,
+ 0x00000639, 0x80000645, 0x0000063a, 0x8000062c,
+ 0x0000063a, 0x80000645, 0x00000641, 0x8000062c,
+ 0x00000641, 0x8000062d, 0x00000641, 0x8000062e,
+ 0x00000641, 0x80000645, 0x00000641, 0x80000649,
+ 0x00000641, 0x8000064a, 0x00000642, 0x8000062d,
+ 0x00000642, 0x80000645, 0x00000642, 0x80000649,
+ 0x00000642, 0x8000064a, 0x00000643, 0x80000627,
+ 0x00000643, 0x8000062c, 0x00000643, 0x8000062d,
+ 0x00000643, 0x8000062e, 0x00000643, 0x80000644,
+ 0x00000643, 0x80000645, 0x00000643, 0x80000649,
+ 0x00000643, 0x8000064a, 0x00000644, 0x8000062c,
+ 0x00000644, 0x8000062d, 0x00000644, 0x8000062e,
+ 0x00000644, 0x80000645, 0x00000644, 0x80000649,
+ 0x00000644, 0x8000064a, 0x00000645, 0x8000062c,
+ 0x00000645, 0x8000062d, 0x00000645, 0x8000062e,
+ 0x00000645, 0x80000645, 0x00000645, 0x80000649,
+ 0x00000645, 0x8000064a, 0x00000646, 0x8000062c,
+ 0x00000646, 0x8000062d, 0x00000646, 0x8000062e,
+ 0x00000646, 0x80000645, 0x00000646, 0x80000649,
+ 0x00000646, 0x8000064a, 0x00000647, 0x8000062c,
+ 0x00000647, 0x80000645, 0x00000647, 0x80000649,
+ 0x00000647, 0x8000064a, 0x0000064a, 0x8000062c,
+ 0x0000064a, 0x8000062d, 0x0000064a, 0x8000062e,
+ 0x0000064a, 0x80000645, 0x0000064a, 0x80000649,
+ 0x0000064a, 0x8000064a, 0x00000630, 0x80000670,
+ 0x00000631, 0x80000670, 0x00000649, 0x80000670,
+ 0x00000020, 0x0000064c, 0x80000651, 0x00000020,
+ 0x0000064d, 0x80000651, 0x00000020, 0x0000064e,
+ 0x80000651, 0x00000020, 0x0000064f, 0x80000651,
+ 0x00000020, 0x00000650, 0x80000651, 0x00000020,
+ 0x00000651, 0x80000670, 0x00000626, 0x80000631,
+ 0x00000626, 0x80000632, 0x00000626, 0x80000645,
+ 0x00000626, 0x80000646, 0x00000626, 0x80000649,
+ 0x00000626, 0x8000064a, 0x00000628, 0x80000631,
+ 0x00000628, 0x80000632, 0x00000628, 0x80000645,
+ 0x00000628, 0x80000646, 0x00000628, 0x80000649,
+ 0x00000628, 0x8000064a, 0x0000062a, 0x80000631,
+ 0x0000062a, 0x80000632, 0x0000062a, 0x80000645,
+ 0x0000062a, 0x80000646, 0x0000062a, 0x80000649,
+ 0x0000062a, 0x8000064a, 0x0000062b, 0x80000631,
+ 0x0000062b, 0x80000632, 0x0000062b, 0x80000645,
+ 0x0000062b, 0x80000646, 0x0000062b, 0x80000649,
+ 0x0000062b, 0x8000064a, 0x00000641, 0x80000649,
+ 0x00000641, 0x8000064a, 0x00000642, 0x80000649,
+ 0x00000642, 0x8000064a, 0x00000643, 0x80000627,
+ 0x00000643, 0x80000644, 0x00000643, 0x80000645,
+ 0x00000643, 0x80000649, 0x00000643, 0x8000064a,
+ 0x00000644, 0x80000645, 0x00000644, 0x80000649,
+ 0x00000644, 0x8000064a, 0x00000645, 0x80000627,
+ 0x00000645, 0x80000645, 0x00000646, 0x80000631,
+ 0x00000646, 0x80000632, 0x00000646, 0x80000645,
+ 0x00000646, 0x80000646, 0x00000646, 0x80000649,
+ 0x00000646, 0x8000064a, 0x00000649, 0x80000670,
+ 0x0000064a, 0x80000631, 0x0000064a, 0x80000632,
+ 0x0000064a, 0x80000645, 0x0000064a, 0x80000646,
+ 0x0000064a, 0x80000649, 0x0000064a, 0x8000064a,
+ 0x00000626, 0x8000062c, 0x00000626, 0x8000062d,
+ 0x00000626, 0x8000062e, 0x00000626, 0x80000645,
+ 0x00000626, 0x80000647, 0x00000628, 0x8000062c,
+ 0x00000628, 0x8000062d, 0x00000628, 0x8000062e,
+ 0x00000628, 0x80000645, 0x00000628, 0x80000647,
+ 0x0000062a, 0x8000062c, 0x0000062a, 0x8000062d,
+ 0x0000062a, 0x8000062e, 0x0000062a, 0x80000645,
+ 0x0000062a, 0x80000647, 0x0000062b, 0x80000645,
+ 0x0000062c, 0x8000062d, 0x0000062c, 0x80000645,
+ 0x0000062d, 0x8000062c, 0x0000062d, 0x80000645,
+ 0x0000062e, 0x8000062c, 0x0000062e, 0x80000645,
+ 0x00000633, 0x8000062c, 0x00000633, 0x8000062d,
+ 0x00000633, 0x8000062e, 0x00000633, 0x80000645,
+ 0x00000635, 0x8000062d, 0x00000635, 0x8000062e,
+ 0x00000635, 0x80000645, 0x00000636, 0x8000062c,
+ 0x00000636, 0x8000062d, 0x00000636, 0x8000062e,
+ 0x00000636, 0x80000645, 0x00000637, 0x8000062d,
+ 0x00000638, 0x80000645, 0x00000639, 0x8000062c,
+ 0x00000639, 0x80000645, 0x0000063a, 0x8000062c,
+ 0x0000063a, 0x80000645, 0x00000641, 0x8000062c,
+ 0x00000641, 0x8000062d, 0x00000641, 0x8000062e,
+ 0x00000641, 0x80000645, 0x00000642, 0x8000062d,
+ 0x00000642, 0x80000645, 0x00000643, 0x8000062c,
+ 0x00000643, 0x8000062d, 0x00000643, 0x8000062e,
+ 0x00000643, 0x80000644, 0x00000643, 0x80000645,
+ 0x00000644, 0x8000062c, 0x00000644, 0x8000062d,
+ 0x00000644, 0x8000062e, 0x00000644, 0x80000645,
+ 0x00000644, 0x80000647, 0x00000645, 0x8000062c,
+ 0x00000645, 0x8000062d, 0x00000645, 0x8000062e,
+ 0x00000645, 0x80000645, 0x00000646, 0x8000062c,
+ 0x00000646, 0x8000062d, 0x00000646, 0x8000062e,
+ 0x00000646, 0x80000645, 0x00000646, 0x80000647,
+ 0x00000647, 0x8000062c, 0x00000647, 0x80000645,
+ 0x00000647, 0x80000670, 0x0000064a, 0x8000062c,
+ 0x0000064a, 0x8000062d, 0x0000064a, 0x8000062e,
+ 0x0000064a, 0x80000645, 0x0000064a, 0x80000647,
+ 0x00000626, 0x80000645, 0x00000626, 0x80000647,
+ 0x00000628, 0x80000645, 0x00000628, 0x80000647,
+ 0x0000062a, 0x80000645, 0x0000062a, 0x80000647,
+ 0x0000062b, 0x80000645, 0x0000062b, 0x80000647,
+ 0x00000633, 0x80000645, 0x00000633, 0x80000647,
+ 0x00000634, 0x80000645, 0x00000634, 0x80000647,
+ 0x00000643, 0x80000644, 0x00000643, 0x80000645,
+ 0x00000644, 0x80000645, 0x00000646, 0x80000645,
+ 0x00000646, 0x80000647, 0x0000064a, 0x80000645,
+ 0x0000064a, 0x80000647, 0x00000640, 0x0000064e,
+ 0x80000651, 0x00000640, 0x0000064f, 0x80000651,
+ 0x00000640, 0x00000650, 0x80000651, 0x00000637,
+ 0x80000649, 0x00000637, 0x8000064a, 0x00000639,
+ 0x80000649, 0x00000639, 0x8000064a, 0x0000063a,
+ 0x80000649, 0x0000063a, 0x8000064a, 0x00000633,
+ 0x80000649, 0x00000633, 0x8000064a, 0x00000634,
+ 0x80000649, 0x00000634, 0x8000064a, 0x0000062d,
+ 0x80000649, 0x0000062d, 0x8000064a, 0x0000062c,
+ 0x80000649, 0x0000062c, 0x8000064a, 0x0000062e,
+ 0x80000649, 0x0000062e, 0x8000064a, 0x00000635,
+ 0x80000649, 0x00000635, 0x8000064a, 0x00000636,
+ 0x80000649, 0x00000636, 0x8000064a, 0x00000634,
+ 0x8000062c, 0x00000634, 0x8000062d, 0x00000634,
+ 0x8000062e, 0x00000634, 0x80000645, 0x00000634,
+ 0x80000631, 0x00000633, 0x80000631, 0x00000635,
+ 0x80000631, 0x00000636, 0x80000631, 0x00000637,
+ 0x80000649, 0x00000637, 0x8000064a, 0x00000639,
+ 0x80000649, 0x00000639, 0x8000064a, 0x0000063a,
+ 0x80000649, 0x0000063a, 0x8000064a, 0x00000633,
+ 0x80000649, 0x00000633, 0x8000064a, 0x00000634,
+ 0x80000649, 0x00000634, 0x8000064a, 0x0000062d,
+ 0x80000649, 0x0000062d, 0x8000064a, 0x0000062c,
+ 0x80000649, 0x0000062c, 0x8000064a, 0x0000062e,
+ 0x80000649, 0x0000062e, 0x8000064a, 0x00000635,
+ 0x80000649, 0x00000635, 0x8000064a, 0x00000636,
+ 0x80000649, 0x00000636, 0x8000064a, 0x00000634,
+ 0x8000062c, 0x00000634, 0x8000062d, 0x00000634,
+ 0x8000062e, 0x00000634, 0x80000645, 0x00000634,
+ 0x80000631, 0x00000633, 0x80000631, 0x00000635,
+ 0x80000631, 0x00000636, 0x80000631, 0x00000634,
+ 0x8000062c, 0x00000634, 0x8000062d, 0x00000634,
+ 0x8000062e, 0x00000634, 0x80000645, 0x00000633,
+ 0x80000647, 0x00000634, 0x80000647, 0x00000637,
+ 0x80000645, 0x00000633, 0x8000062c, 0x00000633,
+ 0x8000062d, 0x00000633, 0x8000062e, 0x00000634,
+ 0x8000062c, 0x00000634, 0x8000062d, 0x00000634,
+ 0x8000062e, 0x00000637, 0x80000645, 0x00000638,
+ 0x80000645, 0x00000627, 0x8000064b, 0x00000627,
+ 0x8000064b, 0x0000062a, 0x0000062c, 0x80000645,
+ 0x0000062a, 0x0000062d, 0x8000062c, 0x0000062a,
+ 0x0000062d, 0x8000062c, 0x0000062a, 0x0000062d,
+ 0x80000645, 0x0000062a, 0x0000062e, 0x80000645,
+ 0x0000062a, 0x00000645, 0x8000062c, 0x0000062a,
+ 0x00000645, 0x8000062d, 0x0000062a, 0x00000645,
+ 0x8000062e, 0x0000062c, 0x00000645, 0x8000062d,
+ 0x0000062c, 0x00000645, 0x8000062d, 0x0000062d,
+ 0x00000645, 0x8000064a, 0x0000062d, 0x00000645,
+ 0x80000649, 0x00000633, 0x0000062d, 0x8000062c,
+ 0x00000633, 0x0000062c, 0x8000062d, 0x00000633,
+ 0x0000062c, 0x80000649, 0x00000633, 0x00000645,
+ 0x8000062d, 0x00000633, 0x00000645, 0x8000062d,
+ 0x00000633, 0x00000645, 0x8000062c, 0x00000633,
+ 0x00000645, 0x80000645, 0x00000633, 0x00000645,
+ 0x80000645, 0x00000635, 0x0000062d, 0x8000062d,
+ 0x00000635, 0x0000062d, 0x8000062d, 0x00000635,
+ 0x00000645, 0x80000645, 0x00000634, 0x0000062d,
+ 0x80000645, 0x00000634, 0x0000062d, 0x80000645,
+ 0x00000634, 0x0000062c, 0x8000064a, 0x00000634,
+ 0x00000645, 0x8000062e, 0x00000634, 0x00000645,
+ 0x8000062e, 0x00000634, 0x00000645, 0x80000645,
+ 0x00000634, 0x00000645, 0x80000645, 0x00000636,
+ 0x0000062d, 0x80000649, 0x00000636, 0x0000062e,
+ 0x80000645, 0x00000636, 0x0000062e, 0x80000645,
+ 0x00000637, 0x00000645, 0x8000062d, 0x00000637,
+ 0x00000645, 0x8000062d, 0x00000637, 0x00000645,
+ 0x80000645, 0x00000637, 0x00000645, 0x8000064a,
+ 0x00000639, 0x0000062c, 0x80000645, 0x00000639,
+ 0x00000645, 0x80000645, 0x00000639, 0x00000645,
+ 0x80000645, 0x00000639, 0x00000645, 0x80000649,
+ 0x0000063a, 0x00000645, 0x80000645, 0x0000063a,
+ 0x00000645, 0x8000064a, 0x0000063a, 0x00000645,
+ 0x80000649, 0x00000641, 0x0000062e, 0x80000645,
+ 0x00000641, 0x0000062e, 0x80000645, 0x00000642,
+ 0x00000645, 0x8000062d, 0x00000642, 0x00000645,
+ 0x80000645, 0x00000644, 0x0000062d, 0x80000645,
+ 0x00000644, 0x0000062d, 0x8000064a, 0x00000644,
+ 0x0000062d, 0x80000649, 0x00000644, 0x0000062c,
+ 0x8000062c, 0x00000644, 0x0000062c, 0x8000062c,
+ 0x00000644, 0x0000062e, 0x80000645, 0x00000644,
+ 0x0000062e, 0x80000645, 0x00000644, 0x00000645,
+ 0x8000062d, 0x00000644, 0x00000645, 0x8000062d,
+ 0x00000645, 0x0000062d, 0x8000062c, 0x00000645,
+ 0x0000062d, 0x80000645, 0x00000645, 0x0000062d,
+ 0x8000064a, 0x00000645, 0x0000062c, 0x8000062d,
+ 0x00000645, 0x0000062c, 0x80000645, 0x00000645,
+ 0x0000062e, 0x8000062c, 0x00000645, 0x0000062e,
+ 0x80000645, 0x00000645, 0x0000062c, 0x8000062e,
+ 0x00000647, 0x00000645, 0x8000062c, 0x00000647,
+ 0x00000645, 0x80000645, 0x00000646, 0x0000062d,
+ 0x80000645, 0x00000646, 0x0000062d, 0x80000649,
+ 0x00000646, 0x0000062c, 0x80000645, 0x00000646,
+ 0x0000062c, 0x80000645, 0x00000646, 0x0000062c,
+ 0x80000649, 0x00000646, 0x00000645, 0x8000064a,
+ 0x00000646, 0x00000645, 0x80000649, 0x0000064a,
+ 0x00000645, 0x80000645, 0x0000064a, 0x00000645,
+ 0x80000645, 0x00000628, 0x0000062e, 0x8000064a,
+ 0x0000062a, 0x0000062c, 0x8000064a, 0x0000062a,
+ 0x0000062c, 0x80000649, 0x0000062a, 0x0000062e,
+ 0x8000064a, 0x0000062a, 0x0000062e, 0x80000649,
+ 0x0000062a, 0x00000645, 0x8000064a, 0x0000062a,
+ 0x00000645, 0x80000649, 0x0000062c, 0x00000645,
+ 0x8000064a, 0x0000062c, 0x0000062d, 0x80000649,
+ 0x0000062c, 0x00000645, 0x80000649, 0x00000633,
+ 0x0000062e, 0x80000649, 0x00000635, 0x0000062d,
+ 0x8000064a, 0x00000634, 0x0000062d, 0x8000064a,
+ 0x00000636, 0x0000062d, 0x8000064a, 0x00000644,
+ 0x0000062c, 0x8000064a, 0x00000644, 0x00000645,
+ 0x8000064a, 0x0000064a, 0x0000062d, 0x8000064a,
+ 0x0000064a, 0x0000062c, 0x8000064a, 0x0000064a,
+ 0x00000645, 0x8000064a, 0x00000645, 0x00000645,
+ 0x8000064a, 0x00000642, 0x00000645, 0x8000064a,
+ 0x00000646, 0x0000062d, 0x8000064a, 0x00000642,
+ 0x00000645, 0x8000062d, 0x00000644, 0x0000062d,
+ 0x80000645, 0x00000639, 0x00000645, 0x8000064a,
+ 0x00000643, 0x00000645, 0x8000064a, 0x00000646,
+ 0x0000062c, 0x8000062d, 0x00000645, 0x0000062e,
+ 0x8000064a, 0x00000644, 0x0000062c, 0x80000645,
+ 0x00000643, 0x00000645, 0x80000645, 0x00000644,
+ 0x0000062c, 0x80000645, 0x00000646, 0x0000062c,
+ 0x8000062d, 0x0000062c, 0x0000062d, 0x8000064a,
+ 0x0000062d, 0x0000062c, 0x8000064a, 0x00000645,
+ 0x0000062c, 0x8000064a, 0x00000641, 0x00000645,
+ 0x8000064a, 0x00000628, 0x0000062d, 0x8000064a,
+ 0x00000643, 0x00000645, 0x80000645, 0x00000639,
+ 0x0000062c, 0x80000645, 0x00000635, 0x00000645,
+ 0x80000645, 0x00000633, 0x0000062e, 0x8000064a,
+ 0x00000646, 0x0000062c, 0x8000064a, 0x00000635,
+ 0x00000644, 0x800006d2, 0x00000642, 0x00000644,
+ 0x800006d2, 0x00000627, 0x00000644, 0x00000644,
+ 0x80000647, 0x00000627, 0x00000643, 0x00000628,
+ 0x80000631, 0x00000645, 0x0000062d, 0x00000645,
+ 0x8000062f, 0x00000635, 0x00000644, 0x00000639,
+ 0x80000645, 0x00000631, 0x00000633, 0x00000648,
+ 0x80000644, 0x00000639, 0x00000644, 0x0000064a,
+ 0x80000647, 0x00000648, 0x00000633, 0x00000644,
+ 0x80000645, 0x00000635, 0x00000644, 0x80000649,
+ 0x00000635, 0x00000644, 0x00000649, 0x00000020,
+ 0x00000627, 0x00000644, 0x00000644, 0x00000647,
+ 0x00000020, 0x00000639, 0x00000644, 0x0000064a,
+ 0x00000647, 0x00000020, 0x00000648, 0x00000633,
+ 0x00000644, 0x80000645, 0x0000062c, 0x00000644,
+ 0x00000020, 0x0000062c, 0x00000644, 0x00000627,
+ 0x00000644, 0x80000647, 0x00000631, 0x000006cc,
+ 0x00000627, 0x80000644, 0x80002025, 0x80002014,
+ 0x80002013, 0x8000005f, 0x8000005f, 0x80000028,
+ 0x80000029, 0x8000007b, 0x8000007d, 0x80003014,
+ 0x80003015, 0x80003010, 0x80003011, 0x8000300a,
+ 0x8000300b, 0x80003008, 0x80003009, 0x8000300c,
+ 0x8000300d, 0x8000300e, 0x8000300f, 0x8000203e,
+ 0x8000203e, 0x8000203e, 0x8000203e, 0x8000005f,
+ 0x8000005f, 0x8000005f, 0x8000002c, 0x80003001,
+ 0x8000002e, 0x8000003b, 0x8000003a, 0x8000003f,
+ 0x80000021, 0x80002014, 0x80000028, 0x80000029,
+ 0x8000007b, 0x8000007d, 0x80003014, 0x80003015,
+ 0x80000023, 0x80000026, 0x8000002a, 0x8000002b,
+ 0x8000002d, 0x8000003c, 0x8000003e, 0x8000003d,
+ 0x8000005c, 0x80000024, 0x80000025, 0x80000040,
+ 0x00000020, 0x8000064b, 0x00000640, 0x8000064b,
+ 0x00000020, 0x8000064c, 0x00000020, 0x8000064d,
+ 0x00000020, 0x8000064e, 0x00000640, 0x8000064e,
+ 0x00000020, 0x8000064f, 0x00000640, 0x8000064f,
+ 0x00000020, 0x80000650, 0x00000640, 0x80000650,
+ 0x00000020, 0x80000651, 0x00000640, 0x80000651,
+ 0x00000020, 0x80000652, 0x00000640, 0x80000652,
+ 0x80000621, 0x80000622, 0x80000622, 0x80000623,
+ 0x80000623, 0x80000624, 0x80000624, 0x80000625,
+ 0x80000625, 0x80000626, 0x80000626, 0x80000626,
+ 0x80000626, 0x80000627, 0x80000627, 0x80000628,
+ 0x80000628, 0x80000628, 0x80000628, 0x80000629,
+ 0x80000629, 0x8000062a, 0x8000062a, 0x8000062a,
+ 0x8000062a, 0x8000062b, 0x8000062b, 0x8000062b,
+ 0x8000062b, 0x8000062c, 0x8000062c, 0x8000062c,
+ 0x8000062c, 0x8000062d, 0x8000062d, 0x8000062d,
+ 0x8000062d, 0x8000062e, 0x8000062e, 0x8000062e,
+ 0x8000062e, 0x8000062f, 0x8000062f, 0x80000630,
+ 0x80000630, 0x80000631, 0x80000631, 0x80000632,
+ 0x80000632, 0x80000633, 0x80000633, 0x80000633,
+ 0x80000633, 0x80000634, 0x80000634, 0x80000634,
+ 0x80000634, 0x80000635, 0x80000635, 0x80000635,
+ 0x80000635, 0x80000636, 0x80000636, 0x80000636,
+ 0x80000636, 0x80000637, 0x80000637, 0x80000637,
+ 0x80000637, 0x80000638, 0x80000638, 0x80000638,
+ 0x80000638, 0x80000639, 0x80000639, 0x80000639,
+ 0x80000639, 0x8000063a, 0x8000063a, 0x8000063a,
+ 0x8000063a, 0x80000641, 0x80000641, 0x80000641,
+ 0x80000641, 0x80000642, 0x80000642, 0x80000642,
+ 0x80000642, 0x80000643, 0x80000643, 0x80000643,
+ 0x80000643, 0x80000644, 0x80000644, 0x80000644,
+ 0x80000644, 0x80000645, 0x80000645, 0x80000645,
+ 0x80000645, 0x80000646, 0x80000646, 0x80000646,
+ 0x80000646, 0x80000647, 0x80000647, 0x80000647,
+ 0x80000647, 0x80000648, 0x80000648, 0x80000649,
+ 0x80000649, 0x8000064a, 0x8000064a, 0x8000064a,
+ 0x8000064a, 0x00000644, 0x80000622, 0x00000644,
+ 0x80000622, 0x00000644, 0x80000623, 0x00000644,
+ 0x80000623, 0x00000644, 0x80000625, 0x00000644,
+ 0x80000625, 0x00000644, 0x80000627, 0x00000644,
+ 0x80000627, 0x80000021, 0x80000022, 0x80000023,
+ 0x80000024, 0x80000025, 0x80000026, 0x80000027,
+ 0x80000028, 0x80000029, 0x8000002a, 0x8000002b,
+ 0x8000002c, 0x8000002d, 0x8000002e, 0x8000002f,
+ 0x80000030, 0x80000031, 0x80000032, 0x80000033,
+ 0x80000034, 0x80000035, 0x80000036, 0x80000037,
+ 0x80000038, 0x80000039, 0x8000003a, 0x8000003b,
+ 0x8000003c, 0x8000003d, 0x8000003e, 0x8000003f,
+ 0x80000040, 0x80000041, 0x80000042, 0x80000043,
+ 0x80000044, 0x80000045, 0x80000046, 0x80000047,
+ 0x80000048, 0x80000049, 0x8000004a, 0x8000004b,
+ 0x8000004c, 0x8000004d, 0x8000004e, 0x8000004f,
+ 0x80000050, 0x80000051, 0x80000052, 0x80000053,
+ 0x80000054, 0x80000055, 0x80000056, 0x80000057,
+ 0x80000058, 0x80000059, 0x8000005a, 0x8000005b,
+ 0x8000005c, 0x8000005d, 0x8000005e, 0x8000005f,
+ 0x80000060, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x8000007b,
+ 0x8000007c, 0x8000007d, 0x8000007e, 0x80002985,
+ 0x80002986, 0x80003002, 0x8000300c, 0x8000300d,
+ 0x80003001, 0x800030fb, 0x800030f2, 0x800030a1,
+ 0x800030a3, 0x800030a5, 0x800030a7, 0x800030a9,
+ 0x800030e3, 0x800030e5, 0x800030e7, 0x800030c3,
+ 0x800030fc, 0x800030a2, 0x800030a4, 0x800030a6,
+ 0x800030a8, 0x800030aa, 0x800030ab, 0x800030ad,
+ 0x800030af, 0x800030b1, 0x800030b3, 0x800030b5,
+ 0x800030b7, 0x800030b9, 0x800030bb, 0x800030bd,
+ 0x800030bf, 0x800030c1, 0x800030c4, 0x800030c6,
+ 0x800030c8, 0x800030ca, 0x800030cb, 0x800030cc,
+ 0x800030cd, 0x800030ce, 0x800030cf, 0x800030d2,
+ 0x800030d5, 0x800030d8, 0x800030db, 0x800030de,
+ 0x800030df, 0x800030e0, 0x800030e1, 0x800030e2,
+ 0x800030e4, 0x800030e6, 0x800030e8, 0x800030e9,
+ 0x800030ea, 0x800030eb, 0x800030ec, 0x800030ed,
+ 0x800030ef, 0x800030f3, 0x80003099, 0x8000309a,
+ 0x80003164, 0x80003131, 0x80003132, 0x80003133,
+ 0x80003134, 0x80003135, 0x80003136, 0x80003137,
+ 0x80003138, 0x80003139, 0x8000313a, 0x8000313b,
+ 0x8000313c, 0x8000313d, 0x8000313e, 0x8000313f,
+ 0x80003140, 0x80003141, 0x80003142, 0x80003143,
+ 0x80003144, 0x80003145, 0x80003146, 0x80003147,
+ 0x80003148, 0x80003149, 0x8000314a, 0x8000314b,
+ 0x8000314c, 0x8000314d, 0x8000314e, 0x8000314f,
+ 0x80003150, 0x80003151, 0x80003152, 0x80003153,
+ 0x80003154, 0x80003155, 0x80003156, 0x80003157,
+ 0x80003158, 0x80003159, 0x8000315a, 0x8000315b,
+ 0x8000315c, 0x8000315d, 0x8000315e, 0x8000315f,
+ 0x80003160, 0x80003161, 0x80003162, 0x80003163,
+ 0x800000a2, 0x800000a3, 0x800000ac, 0x800000af,
+ 0x800000a6, 0x800000a5, 0x800020a9, 0x80002502,
+ 0x80002190, 0x80002191, 0x80002192, 0x80002193,
+ 0x800025a0, 0x800025cb, 0x0001d157, 0x8001d165,
+ 0x0001d158, 0x8001d165, 0x0001d15f, 0x8001d16e,
+ 0x0001d15f, 0x8001d16f, 0x0001d15f, 0x8001d170,
+ 0x0001d15f, 0x8001d171, 0x0001d15f, 0x8001d172,
+ 0x0001d1b9, 0x8001d165, 0x0001d1ba, 0x8001d165,
+ 0x0001d1bb, 0x8001d16e, 0x0001d1bc, 0x8001d16e,
+ 0x0001d1bb, 0x8001d16f, 0x0001d1bc, 0x8001d16f,
+ 0x80000041, 0x80000042, 0x80000043, 0x80000044,
+ 0x80000045, 0x80000046, 0x80000047, 0x80000048,
+ 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c,
+ 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050,
+ 0x80000051, 0x80000052, 0x80000053, 0x80000054,
+ 0x80000055, 0x80000056, 0x80000057, 0x80000058,
+ 0x80000059, 0x8000005a, 0x80000061, 0x80000062,
+ 0x80000063, 0x80000064, 0x80000065, 0x80000066,
+ 0x80000067, 0x80000068, 0x80000069, 0x8000006a,
+ 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e,
+ 0x8000006f, 0x80000070, 0x80000071, 0x80000072,
+ 0x80000073, 0x80000074, 0x80000075, 0x80000076,
+ 0x80000077, 0x80000078, 0x80000079, 0x8000007a,
+ 0x80000041, 0x80000042, 0x80000043, 0x80000044,
+ 0x80000045, 0x80000046, 0x80000047, 0x80000048,
+ 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c,
+ 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050,
+ 0x80000051, 0x80000052, 0x80000053, 0x80000054,
+ 0x80000055, 0x80000056, 0x80000057, 0x80000058,
+ 0x80000059, 0x8000005a, 0x80000061, 0x80000062,
+ 0x80000063, 0x80000064, 0x80000065, 0x80000066,
+ 0x80000067, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000041,
+ 0x80000042, 0x80000043, 0x80000044, 0x80000045,
+ 0x80000046, 0x80000047, 0x80000048, 0x80000049,
+ 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d,
+ 0x8000004e, 0x8000004f, 0x80000050, 0x80000051,
+ 0x80000052, 0x80000053, 0x80000054, 0x80000055,
+ 0x80000056, 0x80000057, 0x80000058, 0x80000059,
+ 0x8000005a, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000041,
+ 0x80000043, 0x80000044, 0x80000047, 0x8000004a,
+ 0x8000004b, 0x8000004e, 0x8000004f, 0x80000050,
+ 0x80000051, 0x80000053, 0x80000054, 0x80000055,
+ 0x80000056, 0x80000057, 0x80000058, 0x80000059,
+ 0x8000005a, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000066, 0x80000068, 0x80000069,
+ 0x8000006a, 0x8000006b, 0x8000006d, 0x8000006e,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000041,
+ 0x80000042, 0x80000043, 0x80000044, 0x80000045,
+ 0x80000046, 0x80000047, 0x80000048, 0x80000049,
+ 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d,
+ 0x8000004e, 0x8000004f, 0x80000050, 0x80000051,
+ 0x80000052, 0x80000053, 0x80000054, 0x80000055,
+ 0x80000056, 0x80000057, 0x80000058, 0x80000059,
+ 0x8000005a, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000041,
+ 0x80000042, 0x80000044, 0x80000045, 0x80000046,
+ 0x80000047, 0x8000004a, 0x8000004b, 0x8000004c,
+ 0x8000004d, 0x8000004e, 0x8000004f, 0x80000050,
+ 0x80000051, 0x80000053, 0x80000054, 0x80000055,
+ 0x80000056, 0x80000057, 0x80000058, 0x80000059,
+ 0x80000061, 0x80000062, 0x80000063, 0x80000064,
+ 0x80000065, 0x80000066, 0x80000067, 0x80000068,
+ 0x80000069, 0x8000006a, 0x8000006b, 0x8000006c,
+ 0x8000006d, 0x8000006e, 0x8000006f, 0x80000070,
+ 0x80000071, 0x80000072, 0x80000073, 0x80000074,
+ 0x80000075, 0x80000076, 0x80000077, 0x80000078,
+ 0x80000079, 0x8000007a, 0x80000041, 0x80000042,
+ 0x80000044, 0x80000045, 0x80000046, 0x80000047,
+ 0x80000049, 0x8000004a, 0x8000004b, 0x8000004c,
+ 0x8000004d, 0x8000004f, 0x80000053, 0x80000054,
+ 0x80000055, 0x80000056, 0x80000057, 0x80000058,
+ 0x80000059, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000041,
+ 0x80000042, 0x80000043, 0x80000044, 0x80000045,
+ 0x80000046, 0x80000047, 0x80000048, 0x80000049,
+ 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d,
+ 0x8000004e, 0x8000004f, 0x80000050, 0x80000051,
+ 0x80000052, 0x80000053, 0x80000054, 0x80000055,
+ 0x80000056, 0x80000057, 0x80000058, 0x80000059,
+ 0x8000005a, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000041,
+ 0x80000042, 0x80000043, 0x80000044, 0x80000045,
+ 0x80000046, 0x80000047, 0x80000048, 0x80000049,
+ 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d,
+ 0x8000004e, 0x8000004f, 0x80000050, 0x80000051,
+ 0x80000052, 0x80000053, 0x80000054, 0x80000055,
+ 0x80000056, 0x80000057, 0x80000058, 0x80000059,
+ 0x8000005a, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000041,
+ 0x80000042, 0x80000043, 0x80000044, 0x80000045,
+ 0x80000046, 0x80000047, 0x80000048, 0x80000049,
+ 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d,
+ 0x8000004e, 0x8000004f, 0x80000050, 0x80000051,
+ 0x80000052, 0x80000053, 0x80000054, 0x80000055,
+ 0x80000056, 0x80000057, 0x80000058, 0x80000059,
+ 0x8000005a, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000041,
+ 0x80000042, 0x80000043, 0x80000044, 0x80000045,
+ 0x80000046, 0x80000047, 0x80000048, 0x80000049,
+ 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d,
+ 0x8000004e, 0x8000004f, 0x80000050, 0x80000051,
+ 0x80000052, 0x80000053, 0x80000054, 0x80000055,
+ 0x80000056, 0x80000057, 0x80000058, 0x80000059,
+ 0x8000005a, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000041,
+ 0x80000042, 0x80000043, 0x80000044, 0x80000045,
+ 0x80000046, 0x80000047, 0x80000048, 0x80000049,
+ 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d,
+ 0x8000004e, 0x8000004f, 0x80000050, 0x80000051,
+ 0x80000052, 0x80000053, 0x80000054, 0x80000055,
+ 0x80000056, 0x80000057, 0x80000058, 0x80000059,
+ 0x8000005a, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000041,
+ 0x80000042, 0x80000043, 0x80000044, 0x80000045,
+ 0x80000046, 0x80000047, 0x80000048, 0x80000049,
+ 0x8000004a, 0x8000004b, 0x8000004c, 0x8000004d,
+ 0x8000004e, 0x8000004f, 0x80000050, 0x80000051,
+ 0x80000052, 0x80000053, 0x80000054, 0x80000055,
+ 0x80000056, 0x80000057, 0x80000058, 0x80000059,
+ 0x8000005a, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x8000006a, 0x8000006b,
+ 0x8000006c, 0x8000006d, 0x8000006e, 0x8000006f,
+ 0x80000070, 0x80000071, 0x80000072, 0x80000073,
+ 0x80000074, 0x80000075, 0x80000076, 0x80000077,
+ 0x80000078, 0x80000079, 0x8000007a, 0x80000391,
+ 0x80000392, 0x80000393, 0x80000394, 0x80000395,
+ 0x80000396, 0x80000397, 0x80000398, 0x80000399,
+ 0x8000039a, 0x8000039b, 0x8000039c, 0x8000039d,
+ 0x8000039e, 0x8000039f, 0x800003a0, 0x800003a1,
+ 0x800003f4, 0x800003a3, 0x800003a4, 0x800003a5,
+ 0x800003a6, 0x800003a7, 0x800003a8, 0x800003a9,
+ 0x80002207, 0x800003b1, 0x800003b2, 0x800003b3,
+ 0x800003b4, 0x800003b5, 0x800003b6, 0x800003b7,
+ 0x800003b8, 0x800003b9, 0x800003ba, 0x800003bb,
+ 0x800003bc, 0x800003bd, 0x800003be, 0x800003bf,
+ 0x800003c0, 0x800003c1, 0x800003c2, 0x800003c3,
+ 0x800003c4, 0x800003c5, 0x800003c6, 0x800003c7,
+ 0x800003c8, 0x800003c9, 0x80002202, 0x800003f5,
+ 0x800003d1, 0x800003f0, 0x800003d5, 0x800003f1,
+ 0x800003d6, 0x80000391, 0x80000392, 0x80000393,
+ 0x80000394, 0x80000395, 0x80000396, 0x80000397,
+ 0x80000398, 0x80000399, 0x8000039a, 0x8000039b,
+ 0x8000039c, 0x8000039d, 0x8000039e, 0x8000039f,
+ 0x800003a0, 0x800003a1, 0x800003f4, 0x800003a3,
+ 0x800003a4, 0x800003a5, 0x800003a6, 0x800003a7,
+ 0x800003a8, 0x800003a9, 0x80002207, 0x800003b1,
+ 0x800003b2, 0x800003b3, 0x800003b4, 0x800003b5,
+ 0x800003b6, 0x800003b7, 0x800003b8, 0x800003b9,
+ 0x800003ba, 0x800003bb, 0x800003bc, 0x800003bd,
+ 0x800003be, 0x800003bf, 0x800003c0, 0x800003c1,
+ 0x800003c2, 0x800003c3, 0x800003c4, 0x800003c5,
+ 0x800003c6, 0x800003c7, 0x800003c8, 0x800003c9,
+ 0x80002202, 0x800003f5, 0x800003d1, 0x800003f0,
+ 0x800003d5, 0x800003f1, 0x800003d6, 0x80000391,
+ 0x80000392, 0x80000393, 0x80000394, 0x80000395,
+ 0x80000396, 0x80000397, 0x80000398, 0x80000399,
+ 0x8000039a, 0x8000039b, 0x8000039c, 0x8000039d,
+ 0x8000039e, 0x8000039f, 0x800003a0, 0x800003a1,
+ 0x800003f4, 0x800003a3, 0x800003a4, 0x800003a5,
+ 0x800003a6, 0x800003a7, 0x800003a8, 0x800003a9,
+ 0x80002207, 0x800003b1, 0x800003b2, 0x800003b3,
+ 0x800003b4, 0x800003b5, 0x800003b6, 0x800003b7,
+ 0x800003b8, 0x800003b9, 0x800003ba, 0x800003bb,
+ 0x800003bc, 0x800003bd, 0x800003be, 0x800003bf,
+ 0x800003c0, 0x800003c1, 0x800003c2, 0x800003c3,
+ 0x800003c4, 0x800003c5, 0x800003c6, 0x800003c7,
+ 0x800003c8, 0x800003c9, 0x80002202, 0x800003f5,
+ 0x800003d1, 0x800003f0, 0x800003d5, 0x800003f1,
+ 0x800003d6, 0x80000391, 0x80000392, 0x80000393,
+ 0x80000394, 0x80000395, 0x80000396, 0x80000397,
+ 0x80000398, 0x80000399, 0x8000039a, 0x8000039b,
+ 0x8000039c, 0x8000039d, 0x8000039e, 0x8000039f,
+ 0x800003a0, 0x800003a1, 0x800003f4, 0x800003a3,
+ 0x800003a4, 0x800003a5, 0x800003a6, 0x800003a7,
+ 0x800003a8, 0x800003a9, 0x80002207, 0x800003b1,
+ 0x800003b2, 0x800003b3, 0x800003b4, 0x800003b5,
+ 0x800003b6, 0x800003b7, 0x800003b8, 0x800003b9,
+ 0x800003ba, 0x800003bb, 0x800003bc, 0x800003bd,
+ 0x800003be, 0x800003bf, 0x800003c0, 0x800003c1,
+ 0x800003c2, 0x800003c3, 0x800003c4, 0x800003c5,
+ 0x800003c6, 0x800003c7, 0x800003c8, 0x800003c9,
+ 0x80002202, 0x800003f5, 0x800003d1, 0x800003f0,
+ 0x800003d5, 0x800003f1, 0x800003d6, 0x80000391,
+ 0x80000392, 0x80000393, 0x80000394, 0x80000395,
+ 0x80000396, 0x80000397, 0x80000398, 0x80000399,
+ 0x8000039a, 0x8000039b, 0x8000039c, 0x8000039d,
+ 0x8000039e, 0x8000039f, 0x800003a0, 0x800003a1,
+ 0x800003f4, 0x800003a3, 0x800003a4, 0x800003a5,
+ 0x800003a6, 0x800003a7, 0x800003a8, 0x800003a9,
+ 0x80002207, 0x800003b1, 0x800003b2, 0x800003b3,
+ 0x800003b4, 0x800003b5, 0x800003b6, 0x800003b7,
+ 0x800003b8, 0x800003b9, 0x800003ba, 0x800003bb,
+ 0x800003bc, 0x800003bd, 0x800003be, 0x800003bf,
+ 0x800003c0, 0x800003c1, 0x800003c2, 0x800003c3,
+ 0x800003c4, 0x800003c5, 0x800003c6, 0x800003c7,
+ 0x800003c8, 0x800003c9, 0x80002202, 0x800003f5,
+ 0x800003d1, 0x800003f0, 0x800003d5, 0x800003f1,
+ 0x800003d6, 0x80000030, 0x80000031, 0x80000032,
+ 0x80000033, 0x80000034, 0x80000035, 0x80000036,
+ 0x80000037, 0x80000038, 0x80000039, 0x80000030,
+ 0x80000031, 0x80000032, 0x80000033, 0x80000034,
+ 0x80000035, 0x80000036, 0x80000037, 0x80000038,
+ 0x80000039, 0x80000030, 0x80000031, 0x80000032,
+ 0x80000033, 0x80000034, 0x80000035, 0x80000036,
+ 0x80000037, 0x80000038, 0x80000039, 0x80000030,
+ 0x80000031, 0x80000032, 0x80000033, 0x80000034,
+ 0x80000035, 0x80000036, 0x80000037, 0x80000038,
+ 0x80000039, 0x80000030, 0x80000031, 0x80000032,
+ 0x80000033, 0x80000034, 0x80000035, 0x80000036,
+ 0x80000037, 0x80000038, 0x80000039, 0x80004e3d,
+ 0x80004e38, 0x80004e41, 0x80020122, 0x80004f60,
+ 0x80004fae, 0x80004fbb, 0x80005002, 0x8000507a,
+ 0x80005099, 0x800050e7, 0x800050cf, 0x8000349e,
+ 0x8002063a, 0x8000514d, 0x80005154, 0x80005164,
+ 0x80005177, 0x8002051c, 0x800034b9, 0x80005167,
+ 0x8000518d, 0x8002054b, 0x80005197, 0x800051a4,
+ 0x80004ecc, 0x800051ac, 0x800051b5, 0x800291df,
+ 0x800051f5, 0x80005203, 0x800034df, 0x8000523b,
+ 0x80005246, 0x80005272, 0x80005277, 0x80003515,
+ 0x800052c7, 0x800052c9, 0x800052e4, 0x800052fa,
+ 0x80005305, 0x80005306, 0x80005317, 0x80005349,
+ 0x80005351, 0x8000535a, 0x80005373, 0x8000537d,
+ 0x8000537f, 0x8000537f, 0x8000537f, 0x80020a2c,
+ 0x80007070, 0x800053ca, 0x800053df, 0x80020b63,
+ 0x800053eb, 0x800053f1, 0x80005406, 0x8000549e,
+ 0x80005438, 0x80005448, 0x80005468, 0x800054a2,
+ 0x800054f6, 0x80005510, 0x80005553, 0x80005563,
+ 0x80005584, 0x80005584, 0x80005599, 0x800055ab,
+ 0x800055b3, 0x800055c2, 0x80005716, 0x80005606,
+ 0x80005717, 0x80005651, 0x80005674, 0x80005207,
+ 0x800058ee, 0x800057ce, 0x800057f4, 0x8000580d,
+ 0x8000578b, 0x80005832, 0x80005831, 0x800058ac,
+ 0x800214e4, 0x800058f2, 0x800058f7, 0x80005906,
+ 0x8000591a, 0x80005922, 0x80005962, 0x800216a8,
+ 0x800216ea, 0x800059ec, 0x80005a1b, 0x80005a27,
+ 0x800059d8, 0x80005a66, 0x800036ee, 0x8002136a,
+ 0x80005b08, 0x80005b3e, 0x80005b3e, 0x800219c8,
+ 0x80005bc3, 0x80005bd8, 0x80005be7, 0x80005bf3,
+ 0x80021b18, 0x80005bff, 0x80005c06, 0x80005f33,
+ 0x80005c22, 0x80003781, 0x80005c60, 0x80005c6e,
+ 0x80005cc0, 0x80005c8d, 0x80021de4, 0x80005d43,
+ 0x80021de6, 0x80005d6e, 0x80005d6b, 0x80005d7c,
+ 0x80005de1, 0x80005de2, 0x8000382f, 0x80005dfd,
+ 0x80005e28, 0x80005e3d, 0x80005e69, 0x80003862,
+ 0x80022183, 0x8000387c, 0x80005eb0, 0x80005eb3,
+ 0x80005eb6, 0x80005eca, 0x8002a392, 0x80005efe,
+ 0x80022331, 0x80022331, 0x80008201, 0x80005f22,
+ 0x80005f22, 0x800038c7, 0x800232b8, 0x800261da,
+ 0x80005f62, 0x80005f6b, 0x800038e3, 0x80005f9a,
+ 0x80005fcd, 0x80005fd7, 0x80005ff9, 0x80006081,
+ 0x8000393a, 0x8000391c, 0x80006094, 0x800226d4,
+ 0x800060c7, 0x80006148, 0x8000614c, 0x8000614e,
+ 0x8000614c, 0x8000617a, 0x8000618e, 0x800061b2,
+ 0x800061a4, 0x800061af, 0x800061de, 0x800061f2,
+ 0x800061f6, 0x80006210, 0x8000621b, 0x8000625d,
+ 0x800062b1, 0x800062d4, 0x80006350, 0x80022b0c,
+ 0x8000633d, 0x800062fc, 0x80006368, 0x80006383,
+ 0x800063e4, 0x80022bf1, 0x80006422, 0x800063c5,
+ 0x800063a9, 0x80003a2e, 0x80006469, 0x8000647e,
+ 0x8000649d, 0x80006477, 0x80003a6c, 0x8000654f,
+ 0x8000656c, 0x8002300a, 0x800065e3, 0x800066f8,
+ 0x80006649, 0x80003b19, 0x80006691, 0x80003b08,
+ 0x80003ae4, 0x80005192, 0x80005195, 0x80006700,
+ 0x8000669c, 0x800080ad, 0x800043d9, 0x80006717,
+ 0x8000671b, 0x80006721, 0x8000675e, 0x80006753,
+ 0x800233c3, 0x80003b49, 0x800067fa, 0x80006785,
+ 0x80006852, 0x80006885, 0x8002346d, 0x8000688e,
+ 0x8000681f, 0x80006914, 0x80003b9d, 0x80006942,
+ 0x800069a3, 0x800069ea, 0x80006aa8, 0x800236a3,
+ 0x80006adb, 0x80003c18, 0x80006b21, 0x800238a7,
+ 0x80006b54, 0x80003c4e, 0x80006b72, 0x80006b9f,
+ 0x80006bba, 0x80006bbb, 0x80023a8d, 0x80021d0b,
+ 0x80023afa, 0x80006c4e, 0x80023cbc, 0x80006cbf,
+ 0x80006ccd, 0x80006c67, 0x80006d16, 0x80006d3e,
+ 0x80006d77, 0x80006d41, 0x80006d69, 0x80006d78,
+ 0x80006d85, 0x80023d1e, 0x80006d34, 0x80006e2f,
+ 0x80006e6e, 0x80003d33, 0x80006ecb, 0x80006ec7,
+ 0x80023ed1, 0x80006df9, 0x80006f6e, 0x80023f5e,
+ 0x80023f8e, 0x80006fc6, 0x80007039, 0x8000701e,
+ 0x8000701b, 0x80003d96, 0x8000704a, 0x8000707d,
+ 0x80007077, 0x800070ad, 0x80020525, 0x80007145,
+ 0x80024263, 0x8000719c, 0x800043ab, 0x80007228,
+ 0x80007235, 0x80007250, 0x80024608, 0x80007280,
+ 0x80007295, 0x80024735, 0x80024814, 0x8000737a,
+ 0x8000738b, 0x80003eac, 0x800073a5, 0x80003eb8,
+ 0x80003eb8, 0x80007447, 0x8000745c, 0x80007471,
+ 0x80007485, 0x800074ca, 0x80003f1b, 0x80007524,
+ 0x80024c36, 0x8000753e, 0x80024c92, 0x80007570,
+ 0x8002219f, 0x80007610, 0x80024fa1, 0x80024fb8,
+ 0x80025044, 0x80003ffc, 0x80004008, 0x800076f4,
+ 0x800250f3, 0x800250f2, 0x80025119, 0x80025133,
+ 0x8000771e, 0x8000771f, 0x8000771f, 0x8000774a,
+ 0x80004039, 0x8000778b, 0x80004046, 0x80004096,
+ 0x8002541d, 0x8000784e, 0x8000788c, 0x800078cc,
+ 0x800040e3, 0x80025626, 0x80007956, 0x8002569a,
+ 0x800256c5, 0x8000798f, 0x800079eb, 0x8000412f,
+ 0x80007a40, 0x80007a4a, 0x80007a4f, 0x8002597c,
+ 0x80025aa7, 0x80025aa7, 0x80007aae, 0x80004202,
+ 0x80025bab, 0x80007bc6, 0x80007bc9, 0x80004227,
+ 0x80025c80, 0x80007cd2, 0x800042a0, 0x80007ce8,
+ 0x80007ce3, 0x80007d00, 0x80025f86, 0x80007d63,
+ 0x80004301, 0x80007dc7, 0x80007e02, 0x80007e45,
+ 0x80004334, 0x80026228, 0x80026247, 0x80004359,
+ 0x800262d9, 0x80007f7a, 0x8002633e, 0x80007f95,
+ 0x80007ffa, 0x80008005, 0x800264da, 0x80026523,
+ 0x80008060, 0x800265a8, 0x80008070, 0x8002335f,
+ 0x800043d5, 0x800080b2, 0x80008103, 0x8000440b,
+ 0x8000813e, 0x80005ab5, 0x800267a7, 0x800267b5,
+ 0x80023393, 0x8002339c, 0x80008201, 0x80008204,
+ 0x80008f9e, 0x8000446b, 0x80008291, 0x8000828b,
+ 0x8000829d, 0x800052b3, 0x800082b1, 0x800082b3,
+ 0x800082bd, 0x800082e6, 0x80026b3c, 0x800082e5,
+ 0x8000831d, 0x80008363, 0x800083ad, 0x80008323,
+ 0x800083bd, 0x800083e7, 0x80008457, 0x80008353,
+ 0x800083ca, 0x800083cc, 0x800083dc, 0x80026c36,
+ 0x80026d6b, 0x80026cd5, 0x8000452b, 0x800084f1,
+ 0x800084f3, 0x80008516, 0x800273ca, 0x80008564,
+ 0x80026f2c, 0x8000455d, 0x80004561, 0x80026fb1,
+ 0x800270d2, 0x8000456b, 0x80008650, 0x8000865c,
+ 0x80008667, 0x80008669, 0x800086a9, 0x80008688,
+ 0x8000870e, 0x800086e2, 0x80008779, 0x80008728,
+ 0x8000876b, 0x80008786, 0x80004d57, 0x800087e1,
+ 0x80008801, 0x800045f9, 0x80008860, 0x80008863,
+ 0x80027667, 0x800088d7, 0x800088de, 0x80004635,
+ 0x800088fa, 0x800034bb, 0x800278ae, 0x80027966,
+ 0x800046be, 0x800046c7, 0x80008aa0, 0x80008aed,
+ 0x80008b8a, 0x80008c55, 0x80027ca8, 0x80008cab,
+ 0x80008cc1, 0x80008d1b, 0x80008d77, 0x80027f2f,
+ 0x80020804, 0x80008dcb, 0x80008dbc, 0x80008df0,
+ 0x800208de, 0x80008ed4, 0x80008f38, 0x800285d2,
+ 0x800285ed, 0x80009094, 0x800090f1, 0x80009111,
+ 0x8002872e, 0x8000911b, 0x80009238, 0x800092d7,
+ 0x800092d8, 0x8000927c, 0x800093f9, 0x80009415,
+ 0x80028bfa, 0x8000958b, 0x80004995, 0x800095b7,
+ 0x80028d77, 0x800049e6, 0x800096c3, 0x80005db2,
+ 0x80009723, 0x80029145, 0x8002921a, 0x80004a6e,
+ 0x80004a76, 0x800097e0, 0x8002940a, 0x80004ab2,
+ 0x80029496, 0x8000980b, 0x8000980b, 0x80009829,
+ 0x800295b6, 0x800098e2, 0x80004b33, 0x80009929,
+ 0x800099a7, 0x800099c2, 0x800099fe, 0x80004bce,
+ 0x80029b30, 0x80009b12, 0x80009c40, 0x80009cfd,
+ 0x80004cce, 0x80004ced, 0x80009d67, 0x8002a0ce,
+ 0x80004cf8, 0x8002a105, 0x8002a20e, 0x8002a291,
+ 0x80009ebb, 0x80004d56, 0x80009ef9, 0x80009efe,
+ 0x80009f05, 0x80009f0f, 0x80009f16, 0x80009f3b,
+ 0x8002a600,
+};
+
+
+/*
+ * Lowercase <-> Uppercase mapping
+ */
+
+/*
+ * Flags for special case mapping.
+ */
+#define CMF_FINAL 1
+#define CMF_NONFINAL 2
+#define CMF_LAST 16
+#define CMF_CTXDEP (CMF_FINAL|CMF_NONFINAL)
+
+#define CASEMAP_BITS_0 9
+#define CASEMAP_BITS_1 7
+#define CASEMAP_BITS_2 5
+
+static const unsigned short v320_toupper_imap[] = {
+ 272, 400, 528, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 784,
+ 912, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 0, 0, 0, 1, 0, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 0, 0, 0,
+ 0, 0, 18, 0, 19, 20, 21, 22,
+ 0, 23, 24, 25, 26, 27, 28, 29,
+ 30, 0, 0, 31, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 49, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 50, 51,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 52, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 53, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 54, 55, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const struct {
+ unsigned short tbl[32];
+} v320_toupper_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
+ 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41,
+ 43, 45, 47, 49, 51, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 55,
+ }},
+ {{
+ 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78,
+ 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100,
+ 102, 0, 104, 106, 108, 110, 112, 114, 116, 118,
+ }},
+ {{
+ 0, 120, 0, 122, 0, 124, 0, 126, 0, 128, 0,
+ 130, 0, 132, 0, 134, 0, 136, 0, 138, 0, 140,
+ 0, 142, 0, 144, 0, 146, 0, 148, 0, 150,
+ }},
+ {{
+ 0, 152, 0, 154, 0, 156, 0, 158, 0, 160, 0,
+ 162, 0, 164, 0, 166, 0, 168, 0, 170, 0, 172,
+ 0, 174, 0, 0, 176, 0, 178, 0, 180, 0,
+ }},
+ {{
+ 182, 0, 184, 0, 186, 0, 188, 0, 190, 192, 0,
+ 195, 0, 197, 0, 199, 0, 201, 0, 203, 0, 205,
+ 0, 207, 0, 209, 0, 211, 0, 213, 0, 215,
+ }},
+ {{
+ 0, 217, 0, 219, 0, 221, 0, 223, 0, 225, 0,
+ 227, 0, 229, 0, 231, 0, 233, 0, 235, 0, 237,
+ 0, 239, 0, 0, 241, 0, 243, 0, 245, 247,
+ }},
+ {{
+ 0, 0, 0, 249, 0, 251, 0, 0, 253, 0, 0,
+ 0, 255, 0, 0, 0, 0, 0, 257, 0, 0, 259,
+ 0, 0, 0, 261, 0, 0, 0, 0, 263, 0,
+ }},
+ {{
+ 0, 265, 0, 267, 0, 269, 0, 0, 271, 0, 0,
+ 0, 0, 273, 0, 0, 275, 0, 0, 0, 277, 0,
+ 279, 0, 0, 281, 0, 0, 0, 283, 0, 285,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 287, 289, 0, 291, 293, 0,
+ 295, 297, 0, 299, 0, 301, 0, 303, 0, 305, 0,
+ 307, 0, 309, 0, 311, 0, 313, 315, 0, 317,
+ }},
+ {{
+ 0, 319, 0, 321, 0, 323, 0, 325, 0, 327, 0,
+ 329, 0, 331, 0, 333, 335, 0, 338, 340, 0, 342,
+ 0, 0, 0, 344, 0, 346, 0, 348, 0, 350,
+ }},
+ {{
+ 0, 352, 0, 354, 0, 356, 0, 358, 0, 360, 0,
+ 362, 0, 364, 0, 366, 0, 368, 0, 370, 0, 372,
+ 0, 374, 0, 376, 0, 378, 0, 380, 0, 382,
+ }},
+ {{
+ 0, 0, 0, 384, 0, 386, 0, 388, 0, 390, 0,
+ 392, 0, 394, 0, 396, 0, 398, 0, 400, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 402, 404, 0,
+ 406, 408, 0, 410, 0, 412, 0, 0, 0, 0,
+ }},
+ {{
+ 414, 0, 0, 416, 0, 0, 0, 0, 418, 420, 0,
+ 0, 0, 0, 0, 422, 0, 0, 424, 0, 0, 426,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 428, 0, 0, 430, 0, 0, 0, 0, 432, 0, 434,
+ 436, 0, 0, 0, 0, 0, 0, 438, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 440, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 442, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 446, 448, 450, 452, 454, 458, 460, 462, 464, 466,
+ 468, 470, 472, 474, 476, 478, 480, 482, 484, 486,
+ }},
+ {{
+ 488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508,
+ 510, 512, 514, 516, 0, 518, 520, 0, 0, 0, 522,
+ 524, 0, 0, 526, 0, 528, 0, 530, 0, 532,
+ }},
+ {{
+ 0, 534, 0, 536, 0, 538, 0, 540, 0, 542, 0,
+ 544, 0, 546, 0, 548, 550, 552, 554, 0, 0, 556,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 558, 560, 562, 564, 566, 568,
+ 570, 572, 574, 576, 578, 580, 582, 584, 586, 588,
+ }},
+ {{
+ 590, 592, 594, 596, 598, 600, 602, 604, 606, 608, 610,
+ 612, 614, 616, 618, 620, 622, 624, 626, 628, 630, 632,
+ 634, 636, 638, 640, 642, 644, 646, 648, 650, 652,
+ }},
+ {{
+ 0, 654, 0, 656, 0, 658, 0, 660, 0, 662, 0,
+ 664, 0, 666, 0, 668, 0, 670, 0, 672, 0, 674,
+ 0, 676, 0, 678, 0, 680, 0, 682, 0, 684,
+ }},
+ {{
+ 0, 686, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 688, 0, 690, 0, 692, 0, 694, 0, 696, 0, 698,
+ 0, 700, 0, 702, 0, 704, 0, 706, 0, 708,
+ }},
+ {{
+ 0, 710, 0, 712, 0, 714, 0, 716, 0, 718, 0,
+ 720, 0, 722, 0, 724, 0, 726, 0, 728, 0, 730,
+ 0, 732, 0, 734, 0, 736, 0, 738, 0, 740,
+ }},
+ {{
+ 0, 0, 742, 0, 744, 0, 746, 0, 748, 0, 750,
+ 0, 752, 0, 754, 0, 0, 756, 0, 758, 0, 760,
+ 0, 762, 0, 764, 0, 766, 0, 768, 0, 770,
+ }},
+ {{
+ 0, 772, 0, 774, 0, 776, 0, 778, 0, 780, 0,
+ 782, 0, 784, 0, 786, 0, 788, 0, 790, 0, 792,
+ 0, 0, 0, 794, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 796, 0, 798, 0, 800, 0, 802, 0, 804, 0,
+ 806, 0, 808, 0, 810, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 812, 814, 816, 818, 820, 822, 824, 826, 828, 830,
+ 832, 834, 836, 838, 840, 842, 844, 846, 848, 850, 852,
+ 854, 856, 858, 860, 862, 864, 866, 868, 870, 872,
+ }},
+ {{
+ 874, 876, 878, 880, 882, 884, 886, 888, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 891, 0, 893, 0, 895, 0, 897, 0, 899, 0,
+ 901, 0, 903, 0, 905, 0, 907, 0, 909, 0, 911,
+ 0, 913, 0, 915, 0, 917, 0, 919, 0, 921,
+ }},
+ {{
+ 0, 923, 0, 925, 0, 927, 0, 929, 0, 931, 0,
+ 933, 0, 935, 0, 937, 0, 939, 0, 941, 0, 943,
+ 0, 945, 0, 947, 0, 949, 0, 951, 0, 953,
+ }},
+ {{
+ 0, 955, 0, 957, 0, 959, 0, 961, 0, 963, 0,
+ 965, 0, 967, 0, 969, 0, 971, 0, 973, 0, 975,
+ 0, 977, 0, 979, 0, 981, 0, 983, 0, 985,
+ }},
+ {{
+ 0, 987, 0, 989, 0, 991, 0, 993, 0, 995, 0,
+ 997, 0, 999, 0, 1001, 0, 1003, 0, 1005, 0, 1007,
+ 0, 1009, 0, 1011, 0, 1013, 0, 1015, 0, 1017,
+ }},
+ {{
+ 0, 1019, 0, 1021, 0, 1023, 0, 1025, 0, 1027, 0,
+ 1029, 0, 1031, 0, 1033, 0, 1035, 0, 1037, 0, 1039,
+ 1041, 1044, 1047, 1050, 1053, 1056, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 1058, 0, 1060, 0, 1062, 0, 1064, 0, 1066, 0,
+ 1068, 0, 1070, 0, 1072, 0, 1074, 0, 1076, 0, 1078,
+ 0, 1080, 0, 1082, 0, 1084, 0, 1086, 0, 1088,
+ }},
+ {{
+ 0, 1090, 0, 1092, 0, 1094, 0, 1096, 0, 1098, 0,
+ 1100, 0, 1102, 0, 1104, 0, 1106, 0, 1108, 0, 1110,
+ 0, 1112, 0, 1114, 0, 1116, 0, 1118, 0, 1120,
+ }},
+ {{
+ 0, 1122, 0, 1124, 0, 1126, 0, 1128, 0, 1130, 0,
+ 1132, 0, 1134, 0, 1136, 0, 1138, 0, 1140, 0, 1142,
+ 0, 1144, 0, 1146, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1148, 1150, 1152, 1154, 1156, 1158, 1160, 1162, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1164, 1166, 1168, 1170, 1172, 1174,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1176, 1178, 1180, 1182, 1184, 1186, 1188, 1190, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1192, 1194, 1196, 1198, 1200, 1202,
+ 1204, 1206, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1208, 1210, 1212, 1214, 1216, 1218, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1220, 1223, 1225, 1229, 1231, 1235,
+ 1237, 1241, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1243, 1245, 1247, 1249, 1251, 1253, 1255, 1257, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1259, 1261, 1263, 1265, 1267, 1269,
+ 1271, 1273, 1275, 1277, 1279, 1281, 1283, 1285, 0, 0,
+ }},
+ {{
+ 1287, 1292, 1297, 1302, 1307, 1312, 1317, 1322, 1327, 1330, 1333,
+ 1336, 1339, 1342, 1345, 1348, 1351, 1356, 1361, 1366, 1371, 1376,
+ 1381, 1386, 1391, 1394, 1397, 1400, 1403, 1406, 1409, 1412,
+ }},
+ {{
+ 1415, 1420, 1425, 1430, 1435, 1440, 1445, 1450, 1455, 1458, 1461,
+ 1464, 1467, 1470, 1473, 1476, 1479, 1481, 1483, 1486, 1491, 0,
+ 1494, 1497, 0, 0, 0, 0, 1501, 0, 1504, 0,
+ }},
+ {{
+ 0, 0, 1506, 1509, 1514, 0, 1517, 1520, 0, 0, 0,
+ 0, 1524, 0, 0, 0, 1527, 1529, 1531, 1535, 0, 0,
+ 1539, 1542, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1546, 1548, 1550, 1554, 1558, 1561, 1563, 1566, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1570, 1573, 1578, 0,
+ 1581, 1584, 0, 0, 0, 0, 1588, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1591, 1593, 1595, 1597, 1599, 1601,
+ 1603, 1605, 1607, 1609, 1611, 1613, 1615, 1617, 1619, 1621,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1623, 1625, 1627, 1629, 1631, 1633,
+ 1635, 1637, 1639, 1641, 1643, 1645, 1647, 1649, 1651, 1653,
+ }},
+ {{
+ 1655, 1657, 1659, 1661, 1663, 1665, 1667, 1669, 1671, 1673, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1675, 1678, 1681, 1684, 1688, 1692, 1695, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1698, 1701, 1704,
+ 1707, 1710, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 1713, 1715, 1717, 1719, 1721, 1723, 1725, 1727, 1729, 1731,
+ 1733, 1735, 1737, 1739, 1741, 1743, 1745, 1747, 1749, 1751, 1753,
+ 1755, 1757, 1759, 1761, 1763, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1765, 1767, 1769,
+ 1771, 1773, 1775, 1777, 1779, 1781, 1783, 1785, 1787, 1789, 1791,
+ 1793, 1795, 1797, 1799, 1801, 1803, 1805, 1807, 1809, 1811,
+ }},
+ {{
+ 1813, 1815, 1817, 1819, 1821, 1823, 1825, 1827, 1829, 1831, 1833,
+ 1835, 1837, 1839, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+};
+static const unsigned short v320_tolower_imap[] = {
+ 272, 400, 528, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 784,
+ 912, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 0, 0, 1, 0, 0, 0, 2, 0,
+ 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 13, 14, 15, 16,
+ 17, 18, 0, 19, 20, 21, 22, 23,
+ 24, 25, 26, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 43, 0, 44, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 45, 46, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 47, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 48, 49, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const struct {
+ unsigned short tbl[32];
+} v320_tolower_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19,
+ 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41,
+ 43, 45, 47, 49, 51, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73,
+ 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95,
+ 97, 0, 99, 101, 103, 105, 107, 109, 111, 0,
+ }},
+ {{
+ 113, 0, 115, 0, 117, 0, 119, 0, 121, 0, 123,
+ 0, 125, 0, 127, 0, 129, 0, 131, 0, 133, 0,
+ 135, 0, 137, 0, 139, 0, 141, 0, 143, 0,
+ }},
+ {{
+ 145, 0, 147, 0, 149, 0, 151, 0, 153, 0, 155,
+ 0, 157, 0, 159, 0, 161, 0, 165, 0, 167, 0,
+ 169, 0, 0, 171, 0, 173, 0, 175, 0, 177,
+ }},
+ {{
+ 0, 179, 0, 181, 0, 183, 0, 185, 0, 0, 187,
+ 0, 189, 0, 191, 0, 193, 0, 195, 0, 197, 0,
+ 199, 0, 201, 0, 203, 0, 205, 0, 207, 0,
+ }},
+ {{
+ 209, 0, 211, 0, 213, 0, 215, 0, 217, 0, 219,
+ 0, 221, 0, 223, 0, 225, 0, 227, 0, 229, 0,
+ 231, 0, 233, 235, 0, 237, 0, 239, 0, 0,
+ }},
+ {{
+ 0, 241, 243, 0, 245, 0, 247, 249, 0, 251, 253,
+ 255, 0, 0, 257, 259, 261, 263, 0, 265, 267, 0,
+ 269, 271, 273, 0, 0, 0, 275, 277, 0, 279,
+ }},
+ {{
+ 281, 0, 283, 0, 285, 0, 287, 289, 0, 291, 0,
+ 0, 293, 0, 295, 297, 0, 299, 301, 303, 0, 305,
+ 0, 307, 309, 0, 0, 0, 311, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 313, 315, 0, 317, 319, 0, 321,
+ 323, 0, 325, 0, 327, 0, 329, 0, 331, 0, 333,
+ 0, 335, 0, 337, 0, 339, 0, 0, 341, 0,
+ }},
+ {{
+ 343, 0, 345, 0, 347, 0, 349, 0, 351, 0, 353,
+ 0, 355, 0, 357, 0, 0, 359, 361, 0, 363, 0,
+ 365, 367, 369, 0, 371, 0, 373, 0, 375, 0,
+ }},
+ {{
+ 377, 0, 379, 0, 381, 0, 383, 0, 385, 0, 387,
+ 0, 389, 0, 391, 0, 393, 0, 395, 0, 397, 0,
+ 399, 0, 401, 0, 403, 0, 405, 0, 407, 0,
+ }},
+ {{
+ 409, 0, 411, 0, 413, 0, 415, 0, 417, 0, 419,
+ 0, 421, 0, 423, 0, 425, 0, 427, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 429, 0, 431, 433, 435,
+ 0, 437, 0, 439, 441, 0, 443, 445, 447, 449, 451,
+ 453, 455, 457, 459, 461, 463, 465, 467, 469, 471,
+ }},
+ {{
+ 473, 475, 0, 477, 479, 481, 483, 485, 487, 489, 491,
+ 493, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 495, 0, 497, 0, 499, 0, 501, 0,
+ }},
+ {{
+ 503, 0, 505, 0, 507, 0, 509, 0, 511, 0, 513,
+ 0, 515, 0, 517, 0, 0, 0, 0, 0, 519, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 521, 523, 525, 527, 529, 531, 533, 535, 537, 539, 541,
+ 543, 545, 547, 549, 551, 553, 555, 557, 559, 561, 563,
+ 565, 567, 569, 571, 573, 575, 577, 579, 581, 583,
+ }},
+ {{
+ 585, 587, 589, 591, 593, 595, 597, 599, 601, 603, 605,
+ 607, 609, 611, 613, 615, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 617, 0, 619, 0, 621, 0, 623, 0, 625, 0, 627,
+ 0, 629, 0, 631, 0, 633, 0, 635, 0, 637, 0,
+ 639, 0, 641, 0, 643, 0, 645, 0, 647, 0,
+ }},
+ {{
+ 649, 0, 0, 0, 0, 0, 0, 0, 0, 0, 651,
+ 0, 653, 0, 655, 0, 657, 0, 659, 0, 661, 0,
+ 663, 0, 665, 0, 667, 0, 669, 0, 671, 0,
+ }},
+ {{
+ 673, 0, 675, 0, 677, 0, 679, 0, 681, 0, 683,
+ 0, 685, 0, 687, 0, 689, 0, 691, 0, 693, 0,
+ 695, 0, 697, 0, 699, 0, 701, 0, 703, 0,
+ }},
+ {{
+ 0, 705, 0, 707, 0, 709, 0, 711, 0, 713, 0,
+ 715, 0, 717, 0, 0, 719, 0, 721, 0, 723, 0,
+ 725, 0, 727, 0, 729, 0, 731, 0, 733, 0,
+ }},
+ {{
+ 735, 0, 737, 0, 739, 0, 741, 0, 743, 0, 745,
+ 0, 747, 0, 749, 0, 751, 0, 753, 0, 755, 0,
+ 0, 0, 757, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 759, 0, 761, 0, 763, 0, 765, 0, 767, 0, 769,
+ 0, 771, 0, 773, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 775, 777, 779, 781, 783,
+ 785, 787, 789, 791, 793, 795, 797, 799, 801, 803,
+ }},
+ {{
+ 805, 807, 809, 811, 813, 815, 817, 819, 821, 823, 825,
+ 827, 829, 831, 833, 835, 837, 839, 841, 843, 845, 847,
+ 849, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 851, 0, 853, 0, 855, 0, 857, 0, 859, 0, 861,
+ 0, 863, 0, 865, 0, 867, 0, 869, 0, 871, 0,
+ 873, 0, 875, 0, 877, 0, 879, 0, 881, 0,
+ }},
+ {{
+ 883, 0, 885, 0, 887, 0, 889, 0, 891, 0, 893,
+ 0, 895, 0, 897, 0, 899, 0, 901, 0, 903, 0,
+ 905, 0, 907, 0, 909, 0, 911, 0, 913, 0,
+ }},
+ {{
+ 915, 0, 917, 0, 919, 0, 921, 0, 923, 0, 925,
+ 0, 927, 0, 929, 0, 931, 0, 933, 0, 935, 0,
+ 937, 0, 939, 0, 941, 0, 943, 0, 945, 0,
+ }},
+ {{
+ 947, 0, 949, 0, 951, 0, 953, 0, 955, 0, 957,
+ 0, 959, 0, 961, 0, 963, 0, 965, 0, 967, 0,
+ 969, 0, 971, 0, 973, 0, 975, 0, 977, 0,
+ }},
+ {{
+ 979, 0, 981, 0, 983, 0, 985, 0, 987, 0, 989,
+ 0, 991, 0, 993, 0, 995, 0, 997, 0, 999, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1001, 0, 1003, 0, 1005, 0, 1007, 0, 1009, 0, 1011,
+ 0, 1013, 0, 1015, 0, 1017, 0, 1019, 0, 1021, 0,
+ 1023, 0, 1025, 0, 1027, 0, 1029, 0, 1031, 0,
+ }},
+ {{
+ 1033, 0, 1035, 0, 1037, 0, 1039, 0, 1041, 0, 1043,
+ 0, 1045, 0, 1047, 0, 1049, 0, 1051, 0, 1053, 0,
+ 1055, 0, 1057, 0, 1059, 0, 1061, 0, 1063, 0,
+ }},
+ {{
+ 1065, 0, 1067, 0, 1069, 0, 1071, 0, 1073, 0, 1075,
+ 0, 1077, 0, 1079, 0, 1081, 0, 1083, 0, 1085, 0,
+ 1087, 0, 1089, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1091, 1093, 1095,
+ 1097, 1099, 1101, 1103, 1105, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1107, 1109, 1111, 1113, 1115, 1117, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1119, 1121, 1123,
+ 1125, 1127, 1129, 1131, 1133, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1135, 1137, 1139, 1141, 1143, 1145, 1147, 1149,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1151, 1153, 1155,
+ 1157, 1159, 1161, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1163, 0, 1165, 0, 1167, 0, 1169,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1171, 1173, 1175,
+ 1177, 1179, 1181, 1183, 1185, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1187, 1191, 1195,
+ 1199, 1203, 1207, 1211, 1215, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1219, 1223, 1227, 1231, 1235, 1239, 1243, 1247,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1251, 1255, 1259,
+ 1263, 1267, 1271, 1275, 1279, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1283, 1285, 1287, 1289, 1291, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1295, 1297, 1299,
+ 1301, 1303, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1307, 1309, 1311, 1313, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1315, 1317, 1319,
+ 1321, 1323, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1325, 1327, 1329, 1331, 1333, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 1337, 0, 0, 0, 1339,
+ 1341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1343, 1345, 1347, 1349, 1351, 1353, 1355, 1357, 1359, 1361, 1363,
+ 1365, 1367, 1369, 1371, 1373, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1375, 1377, 1379, 1381, 1383, 1385, 1387, 1389, 1391, 1393,
+ }},
+ {{
+ 1395, 1397, 1399, 1401, 1403, 1405, 1407, 1409, 1411, 1413, 1415,
+ 1417, 1419, 1421, 1423, 1425, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 1427, 1429, 1431, 1433, 1435, 1437, 1439, 1441, 1443, 1445,
+ 1447, 1449, 1451, 1453, 1455, 1457, 1459, 1461, 1463, 1465, 1467,
+ 1469, 1471, 1473, 1475, 1477, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1479, 1481, 1483, 1485, 1487, 1489, 1491, 1493, 1495, 1497, 1499,
+ 1501, 1503, 1505, 1507, 1509, 1511, 1513, 1515, 1517, 1519, 1521,
+ 1523, 1525, 1527, 1529, 1531, 1533, 1535, 1537, 1539, 1541,
+ }},
+ {{
+ 1543, 1545, 1547, 1549, 1551, 1553, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+};
+static const unsigned long v320_toupper_seq[] = {
+ 0x00000000, 0x00000010, 0x80000041, 0x00000010,
+ 0x80000042, 0x00000010, 0x80000043, 0x00000010,
+ 0x80000044, 0x00000010, 0x80000045, 0x00000010,
+ 0x80000046, 0x00000010, 0x80000047, 0x00000010,
+ 0x80000048, 0x00000010, 0x80000049, 0x00000010,
+ 0x8000004a, 0x00000010, 0x8000004b, 0x00000010,
+ 0x8000004c, 0x00000010, 0x8000004d, 0x00000010,
+ 0x8000004e, 0x00000010, 0x8000004f, 0x00000010,
+ 0x80000050, 0x00000010, 0x80000051, 0x00000010,
+ 0x80000052, 0x00000010, 0x80000053, 0x00000010,
+ 0x80000054, 0x00000010, 0x80000055, 0x00000010,
+ 0x80000056, 0x00000010, 0x80000057, 0x00000010,
+ 0x80000058, 0x00000010, 0x80000059, 0x00000010,
+ 0x8000005a, 0x00000010, 0x8000039c, 0x00000010,
+ 0x00000053, 0x80000053, 0x00000010, 0x800000c0,
+ 0x00000010, 0x800000c1, 0x00000010, 0x800000c2,
+ 0x00000010, 0x800000c3, 0x00000010, 0x800000c4,
+ 0x00000010, 0x800000c5, 0x00000010, 0x800000c6,
+ 0x00000010, 0x800000c7, 0x00000010, 0x800000c8,
+ 0x00000010, 0x800000c9, 0x00000010, 0x800000ca,
+ 0x00000010, 0x800000cb, 0x00000010, 0x800000cc,
+ 0x00000010, 0x800000cd, 0x00000010, 0x800000ce,
+ 0x00000010, 0x800000cf, 0x00000010, 0x800000d0,
+ 0x00000010, 0x800000d1, 0x00000010, 0x800000d2,
+ 0x00000010, 0x800000d3, 0x00000010, 0x800000d4,
+ 0x00000010, 0x800000d5, 0x00000010, 0x800000d6,
+ 0x00000010, 0x800000d8, 0x00000010, 0x800000d9,
+ 0x00000010, 0x800000da, 0x00000010, 0x800000db,
+ 0x00000010, 0x800000dc, 0x00000010, 0x800000dd,
+ 0x00000010, 0x800000de, 0x00000010, 0x80000178,
+ 0x00000010, 0x80000100, 0x00000010, 0x80000102,
+ 0x00000010, 0x80000104, 0x00000010, 0x80000106,
+ 0x00000010, 0x80000108, 0x00000010, 0x8000010a,
+ 0x00000010, 0x8000010c, 0x00000010, 0x8000010e,
+ 0x00000010, 0x80000110, 0x00000010, 0x80000112,
+ 0x00000010, 0x80000114, 0x00000010, 0x80000116,
+ 0x00000010, 0x80000118, 0x00000010, 0x8000011a,
+ 0x00000010, 0x8000011c, 0x00000010, 0x8000011e,
+ 0x00000010, 0x80000120, 0x00000010, 0x80000122,
+ 0x00000010, 0x80000124, 0x00000010, 0x80000126,
+ 0x00000010, 0x80000128, 0x00000010, 0x8000012a,
+ 0x00000010, 0x8000012c, 0x00000010, 0x8000012e,
+ 0x00000010, 0x80000049, 0x00000010, 0x80000132,
+ 0x00000010, 0x80000134, 0x00000010, 0x80000136,
+ 0x00000010, 0x80000139, 0x00000010, 0x8000013b,
+ 0x00000010, 0x8000013d, 0x00000010, 0x8000013f,
+ 0x00000010, 0x80000141, 0x00000010, 0x80000143,
+ 0x00000010, 0x80000145, 0x00000010, 0x80000147,
+ 0x00000010, 0x000002bc, 0x8000004e, 0x00000010,
+ 0x8000014a, 0x00000010, 0x8000014c, 0x00000010,
+ 0x8000014e, 0x00000010, 0x80000150, 0x00000010,
+ 0x80000152, 0x00000010, 0x80000154, 0x00000010,
+ 0x80000156, 0x00000010, 0x80000158, 0x00000010,
+ 0x8000015a, 0x00000010, 0x8000015c, 0x00000010,
+ 0x8000015e, 0x00000010, 0x80000160, 0x00000010,
+ 0x80000162, 0x00000010, 0x80000164, 0x00000010,
+ 0x80000166, 0x00000010, 0x80000168, 0x00000010,
+ 0x8000016a, 0x00000010, 0x8000016c, 0x00000010,
+ 0x8000016e, 0x00000010, 0x80000170, 0x00000010,
+ 0x80000172, 0x00000010, 0x80000174, 0x00000010,
+ 0x80000176, 0x00000010, 0x80000179, 0x00000010,
+ 0x8000017b, 0x00000010, 0x8000017d, 0x00000010,
+ 0x80000053, 0x00000010, 0x80000182, 0x00000010,
+ 0x80000184, 0x00000010, 0x80000187, 0x00000010,
+ 0x8000018b, 0x00000010, 0x80000191, 0x00000010,
+ 0x800001f6, 0x00000010, 0x80000198, 0x00000010,
+ 0x80000220, 0x00000010, 0x800001a0, 0x00000010,
+ 0x800001a2, 0x00000010, 0x800001a4, 0x00000010,
+ 0x800001a7, 0x00000010, 0x800001ac, 0x00000010,
+ 0x800001af, 0x00000010, 0x800001b3, 0x00000010,
+ 0x800001b5, 0x00000010, 0x800001b8, 0x00000010,
+ 0x800001bc, 0x00000010, 0x800001f7, 0x00000010,
+ 0x800001c4, 0x00000010, 0x800001c4, 0x00000010,
+ 0x800001c7, 0x00000010, 0x800001c7, 0x00000010,
+ 0x800001ca, 0x00000010, 0x800001ca, 0x00000010,
+ 0x800001cd, 0x00000010, 0x800001cf, 0x00000010,
+ 0x800001d1, 0x00000010, 0x800001d3, 0x00000010,
+ 0x800001d5, 0x00000010, 0x800001d7, 0x00000010,
+ 0x800001d9, 0x00000010, 0x800001db, 0x00000010,
+ 0x8000018e, 0x00000010, 0x800001de, 0x00000010,
+ 0x800001e0, 0x00000010, 0x800001e2, 0x00000010,
+ 0x800001e4, 0x00000010, 0x800001e6, 0x00000010,
+ 0x800001e8, 0x00000010, 0x800001ea, 0x00000010,
+ 0x800001ec, 0x00000010, 0x800001ee, 0x00000010,
+ 0x0000004a, 0x8000030c, 0x00000010, 0x800001f1,
+ 0x00000010, 0x800001f1, 0x00000010, 0x800001f4,
+ 0x00000010, 0x800001f8, 0x00000010, 0x800001fa,
+ 0x00000010, 0x800001fc, 0x00000010, 0x800001fe,
+ 0x00000010, 0x80000200, 0x00000010, 0x80000202,
+ 0x00000010, 0x80000204, 0x00000010, 0x80000206,
+ 0x00000010, 0x80000208, 0x00000010, 0x8000020a,
+ 0x00000010, 0x8000020c, 0x00000010, 0x8000020e,
+ 0x00000010, 0x80000210, 0x00000010, 0x80000212,
+ 0x00000010, 0x80000214, 0x00000010, 0x80000216,
+ 0x00000010, 0x80000218, 0x00000010, 0x8000021a,
+ 0x00000010, 0x8000021c, 0x00000010, 0x8000021e,
+ 0x00000010, 0x80000222, 0x00000010, 0x80000224,
+ 0x00000010, 0x80000226, 0x00000010, 0x80000228,
+ 0x00000010, 0x8000022a, 0x00000010, 0x8000022c,
+ 0x00000010, 0x8000022e, 0x00000010, 0x80000230,
+ 0x00000010, 0x80000232, 0x00000010, 0x80000181,
+ 0x00000010, 0x80000186, 0x00000010, 0x80000189,
+ 0x00000010, 0x8000018a, 0x00000010, 0x8000018f,
+ 0x00000010, 0x80000190, 0x00000010, 0x80000193,
+ 0x00000010, 0x80000194, 0x00000010, 0x80000197,
+ 0x00000010, 0x80000196, 0x00000010, 0x8000019c,
+ 0x00000010, 0x8000019d, 0x00000010, 0x8000019f,
+ 0x00000010, 0x800001a6, 0x00000010, 0x800001a9,
+ 0x00000010, 0x800001ae, 0x00000010, 0x800001b1,
+ 0x00000010, 0x800001b2, 0x00000010, 0x800001b7,
+ 0x00000010, 0x80000399, 0x00000010, 0x00000399,
+ 0x00000308, 0x80000301, 0x00000010, 0x80000386,
+ 0x00000010, 0x80000388, 0x00000010, 0x80000389,
+ 0x00000010, 0x8000038a, 0x00000010, 0x000003a5,
+ 0x00000308, 0x80000301, 0x00000010, 0x80000391,
+ 0x00000010, 0x80000392, 0x00000010, 0x80000393,
+ 0x00000010, 0x80000394, 0x00000010, 0x80000395,
+ 0x00000010, 0x80000396, 0x00000010, 0x80000397,
+ 0x00000010, 0x80000398, 0x00000010, 0x80000399,
+ 0x00000010, 0x8000039a, 0x00000010, 0x8000039b,
+ 0x00000010, 0x8000039c, 0x00000010, 0x8000039d,
+ 0x00000010, 0x8000039e, 0x00000010, 0x8000039f,
+ 0x00000010, 0x800003a0, 0x00000010, 0x800003a1,
+ 0x00000010, 0x800003a3, 0x00000010, 0x800003a3,
+ 0x00000010, 0x800003a4, 0x00000010, 0x800003a5,
+ 0x00000010, 0x800003a6, 0x00000010, 0x800003a7,
+ 0x00000010, 0x800003a8, 0x00000010, 0x800003a9,
+ 0x00000010, 0x800003aa, 0x00000010, 0x800003ab,
+ 0x00000010, 0x8000038c, 0x00000010, 0x8000038e,
+ 0x00000010, 0x8000038f, 0x00000010, 0x80000392,
+ 0x00000010, 0x80000398, 0x00000010, 0x800003a6,
+ 0x00000010, 0x800003a0, 0x00000010, 0x800003d8,
+ 0x00000010, 0x800003da, 0x00000010, 0x800003dc,
+ 0x00000010, 0x800003de, 0x00000010, 0x800003e0,
+ 0x00000010, 0x800003e2, 0x00000010, 0x800003e4,
+ 0x00000010, 0x800003e6, 0x00000010, 0x800003e8,
+ 0x00000010, 0x800003ea, 0x00000010, 0x800003ec,
+ 0x00000010, 0x800003ee, 0x00000010, 0x8000039a,
+ 0x00000010, 0x800003a1, 0x00000010, 0x800003a3,
+ 0x00000010, 0x80000395, 0x00000010, 0x80000410,
+ 0x00000010, 0x80000411, 0x00000010, 0x80000412,
+ 0x00000010, 0x80000413, 0x00000010, 0x80000414,
+ 0x00000010, 0x80000415, 0x00000010, 0x80000416,
+ 0x00000010, 0x80000417, 0x00000010, 0x80000418,
+ 0x00000010, 0x80000419, 0x00000010, 0x8000041a,
+ 0x00000010, 0x8000041b, 0x00000010, 0x8000041c,
+ 0x00000010, 0x8000041d, 0x00000010, 0x8000041e,
+ 0x00000010, 0x8000041f, 0x00000010, 0x80000420,
+ 0x00000010, 0x80000421, 0x00000010, 0x80000422,
+ 0x00000010, 0x80000423, 0x00000010, 0x80000424,
+ 0x00000010, 0x80000425, 0x00000010, 0x80000426,
+ 0x00000010, 0x80000427, 0x00000010, 0x80000428,
+ 0x00000010, 0x80000429, 0x00000010, 0x8000042a,
+ 0x00000010, 0x8000042b, 0x00000010, 0x8000042c,
+ 0x00000010, 0x8000042d, 0x00000010, 0x8000042e,
+ 0x00000010, 0x8000042f, 0x00000010, 0x80000400,
+ 0x00000010, 0x80000401, 0x00000010, 0x80000402,
+ 0x00000010, 0x80000403, 0x00000010, 0x80000404,
+ 0x00000010, 0x80000405, 0x00000010, 0x80000406,
+ 0x00000010, 0x80000407, 0x00000010, 0x80000408,
+ 0x00000010, 0x80000409, 0x00000010, 0x8000040a,
+ 0x00000010, 0x8000040b, 0x00000010, 0x8000040c,
+ 0x00000010, 0x8000040d, 0x00000010, 0x8000040e,
+ 0x00000010, 0x8000040f, 0x00000010, 0x80000460,
+ 0x00000010, 0x80000462, 0x00000010, 0x80000464,
+ 0x00000010, 0x80000466, 0x00000010, 0x80000468,
+ 0x00000010, 0x8000046a, 0x00000010, 0x8000046c,
+ 0x00000010, 0x8000046e, 0x00000010, 0x80000470,
+ 0x00000010, 0x80000472, 0x00000010, 0x80000474,
+ 0x00000010, 0x80000476, 0x00000010, 0x80000478,
+ 0x00000010, 0x8000047a, 0x00000010, 0x8000047c,
+ 0x00000010, 0x8000047e, 0x00000010, 0x80000480,
+ 0x00000010, 0x8000048a, 0x00000010, 0x8000048c,
+ 0x00000010, 0x8000048e, 0x00000010, 0x80000490,
+ 0x00000010, 0x80000492, 0x00000010, 0x80000494,
+ 0x00000010, 0x80000496, 0x00000010, 0x80000498,
+ 0x00000010, 0x8000049a, 0x00000010, 0x8000049c,
+ 0x00000010, 0x8000049e, 0x00000010, 0x800004a0,
+ 0x00000010, 0x800004a2, 0x00000010, 0x800004a4,
+ 0x00000010, 0x800004a6, 0x00000010, 0x800004a8,
+ 0x00000010, 0x800004aa, 0x00000010, 0x800004ac,
+ 0x00000010, 0x800004ae, 0x00000010, 0x800004b0,
+ 0x00000010, 0x800004b2, 0x00000010, 0x800004b4,
+ 0x00000010, 0x800004b6, 0x00000010, 0x800004b8,
+ 0x00000010, 0x800004ba, 0x00000010, 0x800004bc,
+ 0x00000010, 0x800004be, 0x00000010, 0x800004c1,
+ 0x00000010, 0x800004c3, 0x00000010, 0x800004c5,
+ 0x00000010, 0x800004c7, 0x00000010, 0x800004c9,
+ 0x00000010, 0x800004cb, 0x00000010, 0x800004cd,
+ 0x00000010, 0x800004d0, 0x00000010, 0x800004d2,
+ 0x00000010, 0x800004d4, 0x00000010, 0x800004d6,
+ 0x00000010, 0x800004d8, 0x00000010, 0x800004da,
+ 0x00000010, 0x800004dc, 0x00000010, 0x800004de,
+ 0x00000010, 0x800004e0, 0x00000010, 0x800004e2,
+ 0x00000010, 0x800004e4, 0x00000010, 0x800004e6,
+ 0x00000010, 0x800004e8, 0x00000010, 0x800004ea,
+ 0x00000010, 0x800004ec, 0x00000010, 0x800004ee,
+ 0x00000010, 0x800004f0, 0x00000010, 0x800004f2,
+ 0x00000010, 0x800004f4, 0x00000010, 0x800004f8,
+ 0x00000010, 0x80000500, 0x00000010, 0x80000502,
+ 0x00000010, 0x80000504, 0x00000010, 0x80000506,
+ 0x00000010, 0x80000508, 0x00000010, 0x8000050a,
+ 0x00000010, 0x8000050c, 0x00000010, 0x8000050e,
+ 0x00000010, 0x80000531, 0x00000010, 0x80000532,
+ 0x00000010, 0x80000533, 0x00000010, 0x80000534,
+ 0x00000010, 0x80000535, 0x00000010, 0x80000536,
+ 0x00000010, 0x80000537, 0x00000010, 0x80000538,
+ 0x00000010, 0x80000539, 0x00000010, 0x8000053a,
+ 0x00000010, 0x8000053b, 0x00000010, 0x8000053c,
+ 0x00000010, 0x8000053d, 0x00000010, 0x8000053e,
+ 0x00000010, 0x8000053f, 0x00000010, 0x80000540,
+ 0x00000010, 0x80000541, 0x00000010, 0x80000542,
+ 0x00000010, 0x80000543, 0x00000010, 0x80000544,
+ 0x00000010, 0x80000545, 0x00000010, 0x80000546,
+ 0x00000010, 0x80000547, 0x00000010, 0x80000548,
+ 0x00000010, 0x80000549, 0x00000010, 0x8000054a,
+ 0x00000010, 0x8000054b, 0x00000010, 0x8000054c,
+ 0x00000010, 0x8000054d, 0x00000010, 0x8000054e,
+ 0x00000010, 0x8000054f, 0x00000010, 0x80000550,
+ 0x00000010, 0x80000551, 0x00000010, 0x80000552,
+ 0x00000010, 0x80000553, 0x00000010, 0x80000554,
+ 0x00000010, 0x80000555, 0x00000010, 0x80000556,
+ 0x00000010, 0x00000535, 0x80000552, 0x00000010,
+ 0x80001e00, 0x00000010, 0x80001e02, 0x00000010,
+ 0x80001e04, 0x00000010, 0x80001e06, 0x00000010,
+ 0x80001e08, 0x00000010, 0x80001e0a, 0x00000010,
+ 0x80001e0c, 0x00000010, 0x80001e0e, 0x00000010,
+ 0x80001e10, 0x00000010, 0x80001e12, 0x00000010,
+ 0x80001e14, 0x00000010, 0x80001e16, 0x00000010,
+ 0x80001e18, 0x00000010, 0x80001e1a, 0x00000010,
+ 0x80001e1c, 0x00000010, 0x80001e1e, 0x00000010,
+ 0x80001e20, 0x00000010, 0x80001e22, 0x00000010,
+ 0x80001e24, 0x00000010, 0x80001e26, 0x00000010,
+ 0x80001e28, 0x00000010, 0x80001e2a, 0x00000010,
+ 0x80001e2c, 0x00000010, 0x80001e2e, 0x00000010,
+ 0x80001e30, 0x00000010, 0x80001e32, 0x00000010,
+ 0x80001e34, 0x00000010, 0x80001e36, 0x00000010,
+ 0x80001e38, 0x00000010, 0x80001e3a, 0x00000010,
+ 0x80001e3c, 0x00000010, 0x80001e3e, 0x00000010,
+ 0x80001e40, 0x00000010, 0x80001e42, 0x00000010,
+ 0x80001e44, 0x00000010, 0x80001e46, 0x00000010,
+ 0x80001e48, 0x00000010, 0x80001e4a, 0x00000010,
+ 0x80001e4c, 0x00000010, 0x80001e4e, 0x00000010,
+ 0x80001e50, 0x00000010, 0x80001e52, 0x00000010,
+ 0x80001e54, 0x00000010, 0x80001e56, 0x00000010,
+ 0x80001e58, 0x00000010, 0x80001e5a, 0x00000010,
+ 0x80001e5c, 0x00000010, 0x80001e5e, 0x00000010,
+ 0x80001e60, 0x00000010, 0x80001e62, 0x00000010,
+ 0x80001e64, 0x00000010, 0x80001e66, 0x00000010,
+ 0x80001e68, 0x00000010, 0x80001e6a, 0x00000010,
+ 0x80001e6c, 0x00000010, 0x80001e6e, 0x00000010,
+ 0x80001e70, 0x00000010, 0x80001e72, 0x00000010,
+ 0x80001e74, 0x00000010, 0x80001e76, 0x00000010,
+ 0x80001e78, 0x00000010, 0x80001e7a, 0x00000010,
+ 0x80001e7c, 0x00000010, 0x80001e7e, 0x00000010,
+ 0x80001e80, 0x00000010, 0x80001e82, 0x00000010,
+ 0x80001e84, 0x00000010, 0x80001e86, 0x00000010,
+ 0x80001e88, 0x00000010, 0x80001e8a, 0x00000010,
+ 0x80001e8c, 0x00000010, 0x80001e8e, 0x00000010,
+ 0x80001e90, 0x00000010, 0x80001e92, 0x00000010,
+ 0x80001e94, 0x00000010, 0x00000048, 0x80000331,
+ 0x00000010, 0x00000054, 0x80000308, 0x00000010,
+ 0x00000057, 0x8000030a, 0x00000010, 0x00000059,
+ 0x8000030a, 0x00000010, 0x00000041, 0x800002be,
+ 0x00000010, 0x80001e60, 0x00000010, 0x80001ea0,
+ 0x00000010, 0x80001ea2, 0x00000010, 0x80001ea4,
+ 0x00000010, 0x80001ea6, 0x00000010, 0x80001ea8,
+ 0x00000010, 0x80001eaa, 0x00000010, 0x80001eac,
+ 0x00000010, 0x80001eae, 0x00000010, 0x80001eb0,
+ 0x00000010, 0x80001eb2, 0x00000010, 0x80001eb4,
+ 0x00000010, 0x80001eb6, 0x00000010, 0x80001eb8,
+ 0x00000010, 0x80001eba, 0x00000010, 0x80001ebc,
+ 0x00000010, 0x80001ebe, 0x00000010, 0x80001ec0,
+ 0x00000010, 0x80001ec2, 0x00000010, 0x80001ec4,
+ 0x00000010, 0x80001ec6, 0x00000010, 0x80001ec8,
+ 0x00000010, 0x80001eca, 0x00000010, 0x80001ecc,
+ 0x00000010, 0x80001ece, 0x00000010, 0x80001ed0,
+ 0x00000010, 0x80001ed2, 0x00000010, 0x80001ed4,
+ 0x00000010, 0x80001ed6, 0x00000010, 0x80001ed8,
+ 0x00000010, 0x80001eda, 0x00000010, 0x80001edc,
+ 0x00000010, 0x80001ede, 0x00000010, 0x80001ee0,
+ 0x00000010, 0x80001ee2, 0x00000010, 0x80001ee4,
+ 0x00000010, 0x80001ee6, 0x00000010, 0x80001ee8,
+ 0x00000010, 0x80001eea, 0x00000010, 0x80001eec,
+ 0x00000010, 0x80001eee, 0x00000010, 0x80001ef0,
+ 0x00000010, 0x80001ef2, 0x00000010, 0x80001ef4,
+ 0x00000010, 0x80001ef6, 0x00000010, 0x80001ef8,
+ 0x00000010, 0x80001f08, 0x00000010, 0x80001f09,
+ 0x00000010, 0x80001f0a, 0x00000010, 0x80001f0b,
+ 0x00000010, 0x80001f0c, 0x00000010, 0x80001f0d,
+ 0x00000010, 0x80001f0e, 0x00000010, 0x80001f0f,
+ 0x00000010, 0x80001f18, 0x00000010, 0x80001f19,
+ 0x00000010, 0x80001f1a, 0x00000010, 0x80001f1b,
+ 0x00000010, 0x80001f1c, 0x00000010, 0x80001f1d,
+ 0x00000010, 0x80001f28, 0x00000010, 0x80001f29,
+ 0x00000010, 0x80001f2a, 0x00000010, 0x80001f2b,
+ 0x00000010, 0x80001f2c, 0x00000010, 0x80001f2d,
+ 0x00000010, 0x80001f2e, 0x00000010, 0x80001f2f,
+ 0x00000010, 0x80001f38, 0x00000010, 0x80001f39,
+ 0x00000010, 0x80001f3a, 0x00000010, 0x80001f3b,
+ 0x00000010, 0x80001f3c, 0x00000010, 0x80001f3d,
+ 0x00000010, 0x80001f3e, 0x00000010, 0x80001f3f,
+ 0x00000010, 0x80001f48, 0x00000010, 0x80001f49,
+ 0x00000010, 0x80001f4a, 0x00000010, 0x80001f4b,
+ 0x00000010, 0x80001f4c, 0x00000010, 0x80001f4d,
+ 0x00000010, 0x000003a5, 0x80000313, 0x00000010,
+ 0x80001f59, 0x00000010, 0x000003a5, 0x00000313,
+ 0x80000300, 0x00000010, 0x80001f5b, 0x00000010,
+ 0x000003a5, 0x00000313, 0x80000301, 0x00000010,
+ 0x80001f5d, 0x00000010, 0x000003a5, 0x00000313,
+ 0x80000342, 0x00000010, 0x80001f5f, 0x00000010,
+ 0x80001f68, 0x00000010, 0x80001f69, 0x00000010,
+ 0x80001f6a, 0x00000010, 0x80001f6b, 0x00000010,
+ 0x80001f6c, 0x00000010, 0x80001f6d, 0x00000010,
+ 0x80001f6e, 0x00000010, 0x80001f6f, 0x00000010,
+ 0x80001fba, 0x00000010, 0x80001fbb, 0x00000010,
+ 0x80001fc8, 0x00000010, 0x80001fc9, 0x00000010,
+ 0x80001fca, 0x00000010, 0x80001fcb, 0x00000010,
+ 0x80001fda, 0x00000010, 0x80001fdb, 0x00000010,
+ 0x80001ff8, 0x00000010, 0x80001ff9, 0x00000010,
+ 0x80001fea, 0x00000010, 0x80001feb, 0x00000010,
+ 0x80001ffa, 0x00000010, 0x80001ffb, 0x00000000,
+ 0x00001f08, 0x80000399, 0x00000010, 0x80001f88,
+ 0x00000000, 0x00001f09, 0x80000399, 0x00000010,
+ 0x80001f89, 0x00000000, 0x00001f0a, 0x80000399,
+ 0x00000010, 0x80001f8a, 0x00000000, 0x00001f0b,
+ 0x80000399, 0x00000010, 0x80001f8b, 0x00000000,
+ 0x00001f0c, 0x80000399, 0x00000010, 0x80001f8c,
+ 0x00000000, 0x00001f0d, 0x80000399, 0x00000010,
+ 0x80001f8d, 0x00000000, 0x00001f0e, 0x80000399,
+ 0x00000010, 0x80001f8e, 0x00000000, 0x00001f0f,
+ 0x80000399, 0x00000010, 0x80001f8f, 0x00000010,
+ 0x00001f08, 0x80000399, 0x00000010, 0x00001f09,
+ 0x80000399, 0x00000010, 0x00001f0a, 0x80000399,
+ 0x00000010, 0x00001f0b, 0x80000399, 0x00000010,
+ 0x00001f0c, 0x80000399, 0x00000010, 0x00001f0d,
+ 0x80000399, 0x00000010, 0x00001f0e, 0x80000399,
+ 0x00000010, 0x00001f0f, 0x80000399, 0x00000000,
+ 0x00001f28, 0x80000399, 0x00000010, 0x80001f98,
+ 0x00000000, 0x00001f29, 0x80000399, 0x00000010,
+ 0x80001f99, 0x00000000, 0x00001f2a, 0x80000399,
+ 0x00000010, 0x80001f9a, 0x00000000, 0x00001f2b,
+ 0x80000399, 0x00000010, 0x80001f9b, 0x00000000,
+ 0x00001f2c, 0x80000399, 0x00000010, 0x80001f9c,
+ 0x00000000, 0x00001f2d, 0x80000399, 0x00000010,
+ 0x80001f9d, 0x00000000, 0x00001f2e, 0x80000399,
+ 0x00000010, 0x80001f9e, 0x00000000, 0x00001f2f,
+ 0x80000399, 0x00000010, 0x80001f9f, 0x00000010,
+ 0x00001f28, 0x80000399, 0x00000010, 0x00001f29,
+ 0x80000399, 0x00000010, 0x00001f2a, 0x80000399,
+ 0x00000010, 0x00001f2b, 0x80000399, 0x00000010,
+ 0x00001f2c, 0x80000399, 0x00000010, 0x00001f2d,
+ 0x80000399, 0x00000010, 0x00001f2e, 0x80000399,
+ 0x00000010, 0x00001f2f, 0x80000399, 0x00000000,
+ 0x00001f68, 0x80000399, 0x00000010, 0x80001fa8,
+ 0x00000000, 0x00001f69, 0x80000399, 0x00000010,
+ 0x80001fa9, 0x00000000, 0x00001f6a, 0x80000399,
+ 0x00000010, 0x80001faa, 0x00000000, 0x00001f6b,
+ 0x80000399, 0x00000010, 0x80001fab, 0x00000000,
+ 0x00001f6c, 0x80000399, 0x00000010, 0x80001fac,
+ 0x00000000, 0x00001f6d, 0x80000399, 0x00000010,
+ 0x80001fad, 0x00000000, 0x00001f6e, 0x80000399,
+ 0x00000010, 0x80001fae, 0x00000000, 0x00001f6f,
+ 0x80000399, 0x00000010, 0x80001faf, 0x00000010,
+ 0x00001f68, 0x80000399, 0x00000010, 0x00001f69,
+ 0x80000399, 0x00000010, 0x00001f6a, 0x80000399,
+ 0x00000010, 0x00001f6b, 0x80000399, 0x00000010,
+ 0x00001f6c, 0x80000399, 0x00000010, 0x00001f6d,
+ 0x80000399, 0x00000010, 0x00001f6e, 0x80000399,
+ 0x00000010, 0x00001f6f, 0x80000399, 0x00000010,
+ 0x80001fb8, 0x00000010, 0x80001fb9, 0x00000010,
+ 0x00001fba, 0x80000399, 0x00000000, 0x00000391,
+ 0x80000399, 0x00000010, 0x80001fbc, 0x00000010,
+ 0x00000386, 0x80000399, 0x00000010, 0x00000391,
+ 0x80000342, 0x00000010, 0x00000391, 0x00000342,
+ 0x80000399, 0x00000010, 0x00000391, 0x80000399,
+ 0x00000010, 0x80000399, 0x00000010, 0x00001fca,
+ 0x80000399, 0x00000000, 0x00000397, 0x80000399,
+ 0x00000010, 0x80001fcc, 0x00000010, 0x00000389,
+ 0x80000399, 0x00000010, 0x00000397, 0x80000342,
+ 0x00000010, 0x00000397, 0x00000342, 0x80000399,
+ 0x00000010, 0x00000397, 0x80000399, 0x00000010,
+ 0x80001fd8, 0x00000010, 0x80001fd9, 0x00000010,
+ 0x00000399, 0x00000308, 0x80000300, 0x00000010,
+ 0x00000399, 0x00000308, 0x80000301, 0x00000010,
+ 0x00000399, 0x80000342, 0x00000010, 0x00000399,
+ 0x00000308, 0x80000342, 0x00000010, 0x80001fe8,
+ 0x00000010, 0x80001fe9, 0x00000010, 0x000003a5,
+ 0x00000308, 0x80000300, 0x00000010, 0x000003a5,
+ 0x00000308, 0x80000301, 0x00000010, 0x000003a1,
+ 0x80000313, 0x00000010, 0x80001fec, 0x00000010,
+ 0x000003a5, 0x80000342, 0x00000010, 0x000003a5,
+ 0x00000308, 0x80000342, 0x00000010, 0x00001ffa,
+ 0x80000399, 0x00000000, 0x000003a9, 0x80000399,
+ 0x00000010, 0x80001ffc, 0x00000010, 0x0000038f,
+ 0x80000399, 0x00000010, 0x000003a9, 0x80000342,
+ 0x00000010, 0x000003a9, 0x00000342, 0x80000399,
+ 0x00000010, 0x000003a9, 0x80000399, 0x00000010,
+ 0x80002160, 0x00000010, 0x80002161, 0x00000010,
+ 0x80002162, 0x00000010, 0x80002163, 0x00000010,
+ 0x80002164, 0x00000010, 0x80002165, 0x00000010,
+ 0x80002166, 0x00000010, 0x80002167, 0x00000010,
+ 0x80002168, 0x00000010, 0x80002169, 0x00000010,
+ 0x8000216a, 0x00000010, 0x8000216b, 0x00000010,
+ 0x8000216c, 0x00000010, 0x8000216d, 0x00000010,
+ 0x8000216e, 0x00000010, 0x8000216f, 0x00000010,
+ 0x800024b6, 0x00000010, 0x800024b7, 0x00000010,
+ 0x800024b8, 0x00000010, 0x800024b9, 0x00000010,
+ 0x800024ba, 0x00000010, 0x800024bb, 0x00000010,
+ 0x800024bc, 0x00000010, 0x800024bd, 0x00000010,
+ 0x800024be, 0x00000010, 0x800024bf, 0x00000010,
+ 0x800024c0, 0x00000010, 0x800024c1, 0x00000010,
+ 0x800024c2, 0x00000010, 0x800024c3, 0x00000010,
+ 0x800024c4, 0x00000010, 0x800024c5, 0x00000010,
+ 0x800024c6, 0x00000010, 0x800024c7, 0x00000010,
+ 0x800024c8, 0x00000010, 0x800024c9, 0x00000010,
+ 0x800024ca, 0x00000010, 0x800024cb, 0x00000010,
+ 0x800024cc, 0x00000010, 0x800024cd, 0x00000010,
+ 0x800024ce, 0x00000010, 0x800024cf, 0x00000010,
+ 0x00000046, 0x80000046, 0x00000010, 0x00000046,
+ 0x80000049, 0x00000010, 0x00000046, 0x8000004c,
+ 0x00000010, 0x00000046, 0x00000046, 0x80000049,
+ 0x00000010, 0x00000046, 0x00000046, 0x8000004c,
+ 0x00000010, 0x00000053, 0x80000054, 0x00000010,
+ 0x00000053, 0x80000054, 0x00000010, 0x00000544,
+ 0x80000546, 0x00000010, 0x00000544, 0x80000535,
+ 0x00000010, 0x00000544, 0x8000053b, 0x00000010,
+ 0x0000054e, 0x80000546, 0x00000010, 0x00000544,
+ 0x8000053d, 0x00000010, 0x8000ff21, 0x00000010,
+ 0x8000ff22, 0x00000010, 0x8000ff23, 0x00000010,
+ 0x8000ff24, 0x00000010, 0x8000ff25, 0x00000010,
+ 0x8000ff26, 0x00000010, 0x8000ff27, 0x00000010,
+ 0x8000ff28, 0x00000010, 0x8000ff29, 0x00000010,
+ 0x8000ff2a, 0x00000010, 0x8000ff2b, 0x00000010,
+ 0x8000ff2c, 0x00000010, 0x8000ff2d, 0x00000010,
+ 0x8000ff2e, 0x00000010, 0x8000ff2f, 0x00000010,
+ 0x8000ff30, 0x00000010, 0x8000ff31, 0x00000010,
+ 0x8000ff32, 0x00000010, 0x8000ff33, 0x00000010,
+ 0x8000ff34, 0x00000010, 0x8000ff35, 0x00000010,
+ 0x8000ff36, 0x00000010, 0x8000ff37, 0x00000010,
+ 0x8000ff38, 0x00000010, 0x8000ff39, 0x00000010,
+ 0x8000ff3a, 0x00000010, 0x80010400, 0x00000010,
+ 0x80010401, 0x00000010, 0x80010402, 0x00000010,
+ 0x80010403, 0x00000010, 0x80010404, 0x00000010,
+ 0x80010405, 0x00000010, 0x80010406, 0x00000010,
+ 0x80010407, 0x00000010, 0x80010408, 0x00000010,
+ 0x80010409, 0x00000010, 0x8001040a, 0x00000010,
+ 0x8001040b, 0x00000010, 0x8001040c, 0x00000010,
+ 0x8001040d, 0x00000010, 0x8001040e, 0x00000010,
+ 0x8001040f, 0x00000010, 0x80010410, 0x00000010,
+ 0x80010411, 0x00000010, 0x80010412, 0x00000010,
+ 0x80010413, 0x00000010, 0x80010414, 0x00000010,
+ 0x80010415, 0x00000010, 0x80010416, 0x00000010,
+ 0x80010417, 0x00000010, 0x80010418, 0x00000010,
+ 0x80010419, 0x00000010, 0x8001041a, 0x00000010,
+ 0x8001041b, 0x00000010, 0x8001041c, 0x00000010,
+ 0x8001041d, 0x00000010, 0x8001041e, 0x00000010,
+ 0x8001041f, 0x00000010, 0x80010420, 0x00000010,
+ 0x80010421, 0x00000010, 0x80010422, 0x00000010,
+ 0x80010423, 0x00000010, 0x80010424, 0x00000010,
+ 0x80010425,
+};
+
+static const unsigned long v320_tolower_seq[] = {
+ 0x00000000, 0x00000010, 0x80000061, 0x00000010,
+ 0x80000062, 0x00000010, 0x80000063, 0x00000010,
+ 0x80000064, 0x00000010, 0x80000065, 0x00000010,
+ 0x80000066, 0x00000010, 0x80000067, 0x00000010,
+ 0x80000068, 0x00000010, 0x80000069, 0x00000010,
+ 0x8000006a, 0x00000010, 0x8000006b, 0x00000010,
+ 0x8000006c, 0x00000010, 0x8000006d, 0x00000010,
+ 0x8000006e, 0x00000010, 0x8000006f, 0x00000010,
+ 0x80000070, 0x00000010, 0x80000071, 0x00000010,
+ 0x80000072, 0x00000010, 0x80000073, 0x00000010,
+ 0x80000074, 0x00000010, 0x80000075, 0x00000010,
+ 0x80000076, 0x00000010, 0x80000077, 0x00000010,
+ 0x80000078, 0x00000010, 0x80000079, 0x00000010,
+ 0x8000007a, 0x00000010, 0x800000e0, 0x00000010,
+ 0x800000e1, 0x00000010, 0x800000e2, 0x00000010,
+ 0x800000e3, 0x00000010, 0x800000e4, 0x00000010,
+ 0x800000e5, 0x00000010, 0x800000e6, 0x00000010,
+ 0x800000e7, 0x00000010, 0x800000e8, 0x00000010,
+ 0x800000e9, 0x00000010, 0x800000ea, 0x00000010,
+ 0x800000eb, 0x00000010, 0x800000ec, 0x00000010,
+ 0x800000ed, 0x00000010, 0x800000ee, 0x00000010,
+ 0x800000ef, 0x00000010, 0x800000f0, 0x00000010,
+ 0x800000f1, 0x00000010, 0x800000f2, 0x00000010,
+ 0x800000f3, 0x00000010, 0x800000f4, 0x00000010,
+ 0x800000f5, 0x00000010, 0x800000f6, 0x00000010,
+ 0x800000f8, 0x00000010, 0x800000f9, 0x00000010,
+ 0x800000fa, 0x00000010, 0x800000fb, 0x00000010,
+ 0x800000fc, 0x00000010, 0x800000fd, 0x00000010,
+ 0x800000fe, 0x00000010, 0x80000101, 0x00000010,
+ 0x80000103, 0x00000010, 0x80000105, 0x00000010,
+ 0x80000107, 0x00000010, 0x80000109, 0x00000010,
+ 0x8000010b, 0x00000010, 0x8000010d, 0x00000010,
+ 0x8000010f, 0x00000010, 0x80000111, 0x00000010,
+ 0x80000113, 0x00000010, 0x80000115, 0x00000010,
+ 0x80000117, 0x00000010, 0x80000119, 0x00000010,
+ 0x8000011b, 0x00000010, 0x8000011d, 0x00000010,
+ 0x8000011f, 0x00000010, 0x80000121, 0x00000010,
+ 0x80000123, 0x00000010, 0x80000125, 0x00000010,
+ 0x80000127, 0x00000010, 0x80000129, 0x00000010,
+ 0x8000012b, 0x00000010, 0x8000012d, 0x00000010,
+ 0x8000012f, 0x00000000, 0x80000069, 0x00000010,
+ 0x80000069, 0x00000010, 0x80000133, 0x00000010,
+ 0x80000135, 0x00000010, 0x80000137, 0x00000010,
+ 0x8000013a, 0x00000010, 0x8000013c, 0x00000010,
+ 0x8000013e, 0x00000010, 0x80000140, 0x00000010,
+ 0x80000142, 0x00000010, 0x80000144, 0x00000010,
+ 0x80000146, 0x00000010, 0x80000148, 0x00000010,
+ 0x8000014b, 0x00000010, 0x8000014d, 0x00000010,
+ 0x8000014f, 0x00000010, 0x80000151, 0x00000010,
+ 0x80000153, 0x00000010, 0x80000155, 0x00000010,
+ 0x80000157, 0x00000010, 0x80000159, 0x00000010,
+ 0x8000015b, 0x00000010, 0x8000015d, 0x00000010,
+ 0x8000015f, 0x00000010, 0x80000161, 0x00000010,
+ 0x80000163, 0x00000010, 0x80000165, 0x00000010,
+ 0x80000167, 0x00000010, 0x80000169, 0x00000010,
+ 0x8000016b, 0x00000010, 0x8000016d, 0x00000010,
+ 0x8000016f, 0x00000010, 0x80000171, 0x00000010,
+ 0x80000173, 0x00000010, 0x80000175, 0x00000010,
+ 0x80000177, 0x00000010, 0x800000ff, 0x00000010,
+ 0x8000017a, 0x00000010, 0x8000017c, 0x00000010,
+ 0x8000017e, 0x00000010, 0x80000253, 0x00000010,
+ 0x80000183, 0x00000010, 0x80000185, 0x00000010,
+ 0x80000254, 0x00000010, 0x80000188, 0x00000010,
+ 0x80000256, 0x00000010, 0x80000257, 0x00000010,
+ 0x8000018c, 0x00000010, 0x800001dd, 0x00000010,
+ 0x80000259, 0x00000010, 0x8000025b, 0x00000010,
+ 0x80000192, 0x00000010, 0x80000260, 0x00000010,
+ 0x80000263, 0x00000010, 0x80000269, 0x00000010,
+ 0x80000268, 0x00000010, 0x80000199, 0x00000010,
+ 0x8000026f, 0x00000010, 0x80000272, 0x00000010,
+ 0x80000275, 0x00000010, 0x800001a1, 0x00000010,
+ 0x800001a3, 0x00000010, 0x800001a5, 0x00000010,
+ 0x80000280, 0x00000010, 0x800001a8, 0x00000010,
+ 0x80000283, 0x00000010, 0x800001ad, 0x00000010,
+ 0x80000288, 0x00000010, 0x800001b0, 0x00000010,
+ 0x8000028a, 0x00000010, 0x8000028b, 0x00000010,
+ 0x800001b4, 0x00000010, 0x800001b6, 0x00000010,
+ 0x80000292, 0x00000010, 0x800001b9, 0x00000010,
+ 0x800001bd, 0x00000010, 0x800001c6, 0x00000010,
+ 0x800001c6, 0x00000010, 0x800001c9, 0x00000010,
+ 0x800001c9, 0x00000010, 0x800001cc, 0x00000010,
+ 0x800001cc, 0x00000010, 0x800001ce, 0x00000010,
+ 0x800001d0, 0x00000010, 0x800001d2, 0x00000010,
+ 0x800001d4, 0x00000010, 0x800001d6, 0x00000010,
+ 0x800001d8, 0x00000010, 0x800001da, 0x00000010,
+ 0x800001dc, 0x00000010, 0x800001df, 0x00000010,
+ 0x800001e1, 0x00000010, 0x800001e3, 0x00000010,
+ 0x800001e5, 0x00000010, 0x800001e7, 0x00000010,
+ 0x800001e9, 0x00000010, 0x800001eb, 0x00000010,
+ 0x800001ed, 0x00000010, 0x800001ef, 0x00000010,
+ 0x800001f3, 0x00000010, 0x800001f3, 0x00000010,
+ 0x800001f5, 0x00000010, 0x80000195, 0x00000010,
+ 0x800001bf, 0x00000010, 0x800001f9, 0x00000010,
+ 0x800001fb, 0x00000010, 0x800001fd, 0x00000010,
+ 0x800001ff, 0x00000010, 0x80000201, 0x00000010,
+ 0x80000203, 0x00000010, 0x80000205, 0x00000010,
+ 0x80000207, 0x00000010, 0x80000209, 0x00000010,
+ 0x8000020b, 0x00000010, 0x8000020d, 0x00000010,
+ 0x8000020f, 0x00000010, 0x80000211, 0x00000010,
+ 0x80000213, 0x00000010, 0x80000215, 0x00000010,
+ 0x80000217, 0x00000010, 0x80000219, 0x00000010,
+ 0x8000021b, 0x00000010, 0x8000021d, 0x00000010,
+ 0x8000021f, 0x00000010, 0x8000019e, 0x00000010,
+ 0x80000223, 0x00000010, 0x80000225, 0x00000010,
+ 0x80000227, 0x00000010, 0x80000229, 0x00000010,
+ 0x8000022b, 0x00000010, 0x8000022d, 0x00000010,
+ 0x8000022f, 0x00000010, 0x80000231, 0x00000010,
+ 0x80000233, 0x00000010, 0x800003ac, 0x00000010,
+ 0x800003ad, 0x00000010, 0x800003ae, 0x00000010,
+ 0x800003af, 0x00000010, 0x800003cc, 0x00000010,
+ 0x800003cd, 0x00000010, 0x800003ce, 0x00000010,
+ 0x800003b1, 0x00000010, 0x800003b2, 0x00000010,
+ 0x800003b3, 0x00000010, 0x800003b4, 0x00000010,
+ 0x800003b5, 0x00000010, 0x800003b6, 0x00000010,
+ 0x800003b7, 0x00000010, 0x800003b8, 0x00000010,
+ 0x800003b9, 0x00000010, 0x800003ba, 0x00000010,
+ 0x800003bb, 0x00000010, 0x800003bc, 0x00000010,
+ 0x800003bd, 0x00000010, 0x800003be, 0x00000010,
+ 0x800003bf, 0x00000010, 0x800003c0, 0x00000010,
+ 0x800003c1, 0x00000010, 0x800003c3, 0x00000010,
+ 0x800003c4, 0x00000010, 0x800003c5, 0x00000010,
+ 0x800003c6, 0x00000010, 0x800003c7, 0x00000010,
+ 0x800003c8, 0x00000010, 0x800003c9, 0x00000010,
+ 0x800003ca, 0x00000010, 0x800003cb, 0x00000010,
+ 0x800003d9, 0x00000010, 0x800003db, 0x00000010,
+ 0x800003dd, 0x00000010, 0x800003df, 0x00000010,
+ 0x800003e1, 0x00000010, 0x800003e3, 0x00000010,
+ 0x800003e5, 0x00000010, 0x800003e7, 0x00000010,
+ 0x800003e9, 0x00000010, 0x800003eb, 0x00000010,
+ 0x800003ed, 0x00000010, 0x800003ef, 0x00000010,
+ 0x800003b8, 0x00000010, 0x80000450, 0x00000010,
+ 0x80000451, 0x00000010, 0x80000452, 0x00000010,
+ 0x80000453, 0x00000010, 0x80000454, 0x00000010,
+ 0x80000455, 0x00000010, 0x80000456, 0x00000010,
+ 0x80000457, 0x00000010, 0x80000458, 0x00000010,
+ 0x80000459, 0x00000010, 0x8000045a, 0x00000010,
+ 0x8000045b, 0x00000010, 0x8000045c, 0x00000010,
+ 0x8000045d, 0x00000010, 0x8000045e, 0x00000010,
+ 0x8000045f, 0x00000010, 0x80000430, 0x00000010,
+ 0x80000431, 0x00000010, 0x80000432, 0x00000010,
+ 0x80000433, 0x00000010, 0x80000434, 0x00000010,
+ 0x80000435, 0x00000010, 0x80000436, 0x00000010,
+ 0x80000437, 0x00000010, 0x80000438, 0x00000010,
+ 0x80000439, 0x00000010, 0x8000043a, 0x00000010,
+ 0x8000043b, 0x00000010, 0x8000043c, 0x00000010,
+ 0x8000043d, 0x00000010, 0x8000043e, 0x00000010,
+ 0x8000043f, 0x00000010, 0x80000440, 0x00000010,
+ 0x80000441, 0x00000010, 0x80000442, 0x00000010,
+ 0x80000443, 0x00000010, 0x80000444, 0x00000010,
+ 0x80000445, 0x00000010, 0x80000446, 0x00000010,
+ 0x80000447, 0x00000010, 0x80000448, 0x00000010,
+ 0x80000449, 0x00000010, 0x8000044a, 0x00000010,
+ 0x8000044b, 0x00000010, 0x8000044c, 0x00000010,
+ 0x8000044d, 0x00000010, 0x8000044e, 0x00000010,
+ 0x8000044f, 0x00000010, 0x80000461, 0x00000010,
+ 0x80000463, 0x00000010, 0x80000465, 0x00000010,
+ 0x80000467, 0x00000010, 0x80000469, 0x00000010,
+ 0x8000046b, 0x00000010, 0x8000046d, 0x00000010,
+ 0x8000046f, 0x00000010, 0x80000471, 0x00000010,
+ 0x80000473, 0x00000010, 0x80000475, 0x00000010,
+ 0x80000477, 0x00000010, 0x80000479, 0x00000010,
+ 0x8000047b, 0x00000010, 0x8000047d, 0x00000010,
+ 0x8000047f, 0x00000010, 0x80000481, 0x00000010,
+ 0x8000048b, 0x00000010, 0x8000048d, 0x00000010,
+ 0x8000048f, 0x00000010, 0x80000491, 0x00000010,
+ 0x80000493, 0x00000010, 0x80000495, 0x00000010,
+ 0x80000497, 0x00000010, 0x80000499, 0x00000010,
+ 0x8000049b, 0x00000010, 0x8000049d, 0x00000010,
+ 0x8000049f, 0x00000010, 0x800004a1, 0x00000010,
+ 0x800004a3, 0x00000010, 0x800004a5, 0x00000010,
+ 0x800004a7, 0x00000010, 0x800004a9, 0x00000010,
+ 0x800004ab, 0x00000010, 0x800004ad, 0x00000010,
+ 0x800004af, 0x00000010, 0x800004b1, 0x00000010,
+ 0x800004b3, 0x00000010, 0x800004b5, 0x00000010,
+ 0x800004b7, 0x00000010, 0x800004b9, 0x00000010,
+ 0x800004bb, 0x00000010, 0x800004bd, 0x00000010,
+ 0x800004bf, 0x00000010, 0x800004c2, 0x00000010,
+ 0x800004c4, 0x00000010, 0x800004c6, 0x00000010,
+ 0x800004c8, 0x00000010, 0x800004ca, 0x00000010,
+ 0x800004cc, 0x00000010, 0x800004ce, 0x00000010,
+ 0x800004d1, 0x00000010, 0x800004d3, 0x00000010,
+ 0x800004d5, 0x00000010, 0x800004d7, 0x00000010,
+ 0x800004d9, 0x00000010, 0x800004db, 0x00000010,
+ 0x800004dd, 0x00000010, 0x800004df, 0x00000010,
+ 0x800004e1, 0x00000010, 0x800004e3, 0x00000010,
+ 0x800004e5, 0x00000010, 0x800004e7, 0x00000010,
+ 0x800004e9, 0x00000010, 0x800004eb, 0x00000010,
+ 0x800004ed, 0x00000010, 0x800004ef, 0x00000010,
+ 0x800004f1, 0x00000010, 0x800004f3, 0x00000010,
+ 0x800004f5, 0x00000010, 0x800004f9, 0x00000010,
+ 0x80000501, 0x00000010, 0x80000503, 0x00000010,
+ 0x80000505, 0x00000010, 0x80000507, 0x00000010,
+ 0x80000509, 0x00000010, 0x8000050b, 0x00000010,
+ 0x8000050d, 0x00000010, 0x8000050f, 0x00000010,
+ 0x80000561, 0x00000010, 0x80000562, 0x00000010,
+ 0x80000563, 0x00000010, 0x80000564, 0x00000010,
+ 0x80000565, 0x00000010, 0x80000566, 0x00000010,
+ 0x80000567, 0x00000010, 0x80000568, 0x00000010,
+ 0x80000569, 0x00000010, 0x8000056a, 0x00000010,
+ 0x8000056b, 0x00000010, 0x8000056c, 0x00000010,
+ 0x8000056d, 0x00000010, 0x8000056e, 0x00000010,
+ 0x8000056f, 0x00000010, 0x80000570, 0x00000010,
+ 0x80000571, 0x00000010, 0x80000572, 0x00000010,
+ 0x80000573, 0x00000010, 0x80000574, 0x00000010,
+ 0x80000575, 0x00000010, 0x80000576, 0x00000010,
+ 0x80000577, 0x00000010, 0x80000578, 0x00000010,
+ 0x80000579, 0x00000010, 0x8000057a, 0x00000010,
+ 0x8000057b, 0x00000010, 0x8000057c, 0x00000010,
+ 0x8000057d, 0x00000010, 0x8000057e, 0x00000010,
+ 0x8000057f, 0x00000010, 0x80000580, 0x00000010,
+ 0x80000581, 0x00000010, 0x80000582, 0x00000010,
+ 0x80000583, 0x00000010, 0x80000584, 0x00000010,
+ 0x80000585, 0x00000010, 0x80000586, 0x00000010,
+ 0x80001e01, 0x00000010, 0x80001e03, 0x00000010,
+ 0x80001e05, 0x00000010, 0x80001e07, 0x00000010,
+ 0x80001e09, 0x00000010, 0x80001e0b, 0x00000010,
+ 0x80001e0d, 0x00000010, 0x80001e0f, 0x00000010,
+ 0x80001e11, 0x00000010, 0x80001e13, 0x00000010,
+ 0x80001e15, 0x00000010, 0x80001e17, 0x00000010,
+ 0x80001e19, 0x00000010, 0x80001e1b, 0x00000010,
+ 0x80001e1d, 0x00000010, 0x80001e1f, 0x00000010,
+ 0x80001e21, 0x00000010, 0x80001e23, 0x00000010,
+ 0x80001e25, 0x00000010, 0x80001e27, 0x00000010,
+ 0x80001e29, 0x00000010, 0x80001e2b, 0x00000010,
+ 0x80001e2d, 0x00000010, 0x80001e2f, 0x00000010,
+ 0x80001e31, 0x00000010, 0x80001e33, 0x00000010,
+ 0x80001e35, 0x00000010, 0x80001e37, 0x00000010,
+ 0x80001e39, 0x00000010, 0x80001e3b, 0x00000010,
+ 0x80001e3d, 0x00000010, 0x80001e3f, 0x00000010,
+ 0x80001e41, 0x00000010, 0x80001e43, 0x00000010,
+ 0x80001e45, 0x00000010, 0x80001e47, 0x00000010,
+ 0x80001e49, 0x00000010, 0x80001e4b, 0x00000010,
+ 0x80001e4d, 0x00000010, 0x80001e4f, 0x00000010,
+ 0x80001e51, 0x00000010, 0x80001e53, 0x00000010,
+ 0x80001e55, 0x00000010, 0x80001e57, 0x00000010,
+ 0x80001e59, 0x00000010, 0x80001e5b, 0x00000010,
+ 0x80001e5d, 0x00000010, 0x80001e5f, 0x00000010,
+ 0x80001e61, 0x00000010, 0x80001e63, 0x00000010,
+ 0x80001e65, 0x00000010, 0x80001e67, 0x00000010,
+ 0x80001e69, 0x00000010, 0x80001e6b, 0x00000010,
+ 0x80001e6d, 0x00000010, 0x80001e6f, 0x00000010,
+ 0x80001e71, 0x00000010, 0x80001e73, 0x00000010,
+ 0x80001e75, 0x00000010, 0x80001e77, 0x00000010,
+ 0x80001e79, 0x00000010, 0x80001e7b, 0x00000010,
+ 0x80001e7d, 0x00000010, 0x80001e7f, 0x00000010,
+ 0x80001e81, 0x00000010, 0x80001e83, 0x00000010,
+ 0x80001e85, 0x00000010, 0x80001e87, 0x00000010,
+ 0x80001e89, 0x00000010, 0x80001e8b, 0x00000010,
+ 0x80001e8d, 0x00000010, 0x80001e8f, 0x00000010,
+ 0x80001e91, 0x00000010, 0x80001e93, 0x00000010,
+ 0x80001e95, 0x00000010, 0x80001ea1, 0x00000010,
+ 0x80001ea3, 0x00000010, 0x80001ea5, 0x00000010,
+ 0x80001ea7, 0x00000010, 0x80001ea9, 0x00000010,
+ 0x80001eab, 0x00000010, 0x80001ead, 0x00000010,
+ 0x80001eaf, 0x00000010, 0x80001eb1, 0x00000010,
+ 0x80001eb3, 0x00000010, 0x80001eb5, 0x00000010,
+ 0x80001eb7, 0x00000010, 0x80001eb9, 0x00000010,
+ 0x80001ebb, 0x00000010, 0x80001ebd, 0x00000010,
+ 0x80001ebf, 0x00000010, 0x80001ec1, 0x00000010,
+ 0x80001ec3, 0x00000010, 0x80001ec5, 0x00000010,
+ 0x80001ec7, 0x00000010, 0x80001ec9, 0x00000010,
+ 0x80001ecb, 0x00000010, 0x80001ecd, 0x00000010,
+ 0x80001ecf, 0x00000010, 0x80001ed1, 0x00000010,
+ 0x80001ed3, 0x00000010, 0x80001ed5, 0x00000010,
+ 0x80001ed7, 0x00000010, 0x80001ed9, 0x00000010,
+ 0x80001edb, 0x00000010, 0x80001edd, 0x00000010,
+ 0x80001edf, 0x00000010, 0x80001ee1, 0x00000010,
+ 0x80001ee3, 0x00000010, 0x80001ee5, 0x00000010,
+ 0x80001ee7, 0x00000010, 0x80001ee9, 0x00000010,
+ 0x80001eeb, 0x00000010, 0x80001eed, 0x00000010,
+ 0x80001eef, 0x00000010, 0x80001ef1, 0x00000010,
+ 0x80001ef3, 0x00000010, 0x80001ef5, 0x00000010,
+ 0x80001ef7, 0x00000010, 0x80001ef9, 0x00000010,
+ 0x80001f00, 0x00000010, 0x80001f01, 0x00000010,
+ 0x80001f02, 0x00000010, 0x80001f03, 0x00000010,
+ 0x80001f04, 0x00000010, 0x80001f05, 0x00000010,
+ 0x80001f06, 0x00000010, 0x80001f07, 0x00000010,
+ 0x80001f10, 0x00000010, 0x80001f11, 0x00000010,
+ 0x80001f12, 0x00000010, 0x80001f13, 0x00000010,
+ 0x80001f14, 0x00000010, 0x80001f15, 0x00000010,
+ 0x80001f20, 0x00000010, 0x80001f21, 0x00000010,
+ 0x80001f22, 0x00000010, 0x80001f23, 0x00000010,
+ 0x80001f24, 0x00000010, 0x80001f25, 0x00000010,
+ 0x80001f26, 0x00000010, 0x80001f27, 0x00000010,
+ 0x80001f30, 0x00000010, 0x80001f31, 0x00000010,
+ 0x80001f32, 0x00000010, 0x80001f33, 0x00000010,
+ 0x80001f34, 0x00000010, 0x80001f35, 0x00000010,
+ 0x80001f36, 0x00000010, 0x80001f37, 0x00000010,
+ 0x80001f40, 0x00000010, 0x80001f41, 0x00000010,
+ 0x80001f42, 0x00000010, 0x80001f43, 0x00000010,
+ 0x80001f44, 0x00000010, 0x80001f45, 0x00000010,
+ 0x80001f51, 0x00000010, 0x80001f53, 0x00000010,
+ 0x80001f55, 0x00000010, 0x80001f57, 0x00000010,
+ 0x80001f60, 0x00000010, 0x80001f61, 0x00000010,
+ 0x80001f62, 0x00000010, 0x80001f63, 0x00000010,
+ 0x80001f64, 0x00000010, 0x80001f65, 0x00000010,
+ 0x80001f66, 0x00000010, 0x80001f67, 0x00000000,
+ 0x80001f80, 0x00000010, 0x80001f80, 0x00000000,
+ 0x80001f81, 0x00000010, 0x80001f81, 0x00000000,
+ 0x80001f82, 0x00000010, 0x80001f82, 0x00000000,
+ 0x80001f83, 0x00000010, 0x80001f83, 0x00000000,
+ 0x80001f84, 0x00000010, 0x80001f84, 0x00000000,
+ 0x80001f85, 0x00000010, 0x80001f85, 0x00000000,
+ 0x80001f86, 0x00000010, 0x80001f86, 0x00000000,
+ 0x80001f87, 0x00000010, 0x80001f87, 0x00000000,
+ 0x80001f90, 0x00000010, 0x80001f90, 0x00000000,
+ 0x80001f91, 0x00000010, 0x80001f91, 0x00000000,
+ 0x80001f92, 0x00000010, 0x80001f92, 0x00000000,
+ 0x80001f93, 0x00000010, 0x80001f93, 0x00000000,
+ 0x80001f94, 0x00000010, 0x80001f94, 0x00000000,
+ 0x80001f95, 0x00000010, 0x80001f95, 0x00000000,
+ 0x80001f96, 0x00000010, 0x80001f96, 0x00000000,
+ 0x80001f97, 0x00000010, 0x80001f97, 0x00000000,
+ 0x80001fa0, 0x00000010, 0x80001fa0, 0x00000000,
+ 0x80001fa1, 0x00000010, 0x80001fa1, 0x00000000,
+ 0x80001fa2, 0x00000010, 0x80001fa2, 0x00000000,
+ 0x80001fa3, 0x00000010, 0x80001fa3, 0x00000000,
+ 0x80001fa4, 0x00000010, 0x80001fa4, 0x00000000,
+ 0x80001fa5, 0x00000010, 0x80001fa5, 0x00000000,
+ 0x80001fa6, 0x00000010, 0x80001fa6, 0x00000000,
+ 0x80001fa7, 0x00000010, 0x80001fa7, 0x00000010,
+ 0x80001fb0, 0x00000010, 0x80001fb1, 0x00000010,
+ 0x80001f70, 0x00000010, 0x80001f71, 0x00000000,
+ 0x80001fb3, 0x00000010, 0x80001fb3, 0x00000010,
+ 0x80001f72, 0x00000010, 0x80001f73, 0x00000010,
+ 0x80001f74, 0x00000010, 0x80001f75, 0x00000000,
+ 0x80001fc3, 0x00000010, 0x80001fc3, 0x00000010,
+ 0x80001fd0, 0x00000010, 0x80001fd1, 0x00000010,
+ 0x80001f76, 0x00000010, 0x80001f77, 0x00000010,
+ 0x80001fe0, 0x00000010, 0x80001fe1, 0x00000010,
+ 0x80001f7a, 0x00000010, 0x80001f7b, 0x00000010,
+ 0x80001fe5, 0x00000010, 0x80001f78, 0x00000010,
+ 0x80001f79, 0x00000010, 0x80001f7c, 0x00000010,
+ 0x80001f7d, 0x00000000, 0x80001ff3, 0x00000010,
+ 0x80001ff3, 0x00000010, 0x800003c9, 0x00000010,
+ 0x8000006b, 0x00000010, 0x800000e5, 0x00000010,
+ 0x80002170, 0x00000010, 0x80002171, 0x00000010,
+ 0x80002172, 0x00000010, 0x80002173, 0x00000010,
+ 0x80002174, 0x00000010, 0x80002175, 0x00000010,
+ 0x80002176, 0x00000010, 0x80002177, 0x00000010,
+ 0x80002178, 0x00000010, 0x80002179, 0x00000010,
+ 0x8000217a, 0x00000010, 0x8000217b, 0x00000010,
+ 0x8000217c, 0x00000010, 0x8000217d, 0x00000010,
+ 0x8000217e, 0x00000010, 0x8000217f, 0x00000010,
+ 0x800024d0, 0x00000010, 0x800024d1, 0x00000010,
+ 0x800024d2, 0x00000010, 0x800024d3, 0x00000010,
+ 0x800024d4, 0x00000010, 0x800024d5, 0x00000010,
+ 0x800024d6, 0x00000010, 0x800024d7, 0x00000010,
+ 0x800024d8, 0x00000010, 0x800024d9, 0x00000010,
+ 0x800024da, 0x00000010, 0x800024db, 0x00000010,
+ 0x800024dc, 0x00000010, 0x800024dd, 0x00000010,
+ 0x800024de, 0x00000010, 0x800024df, 0x00000010,
+ 0x800024e0, 0x00000010, 0x800024e1, 0x00000010,
+ 0x800024e2, 0x00000010, 0x800024e3, 0x00000010,
+ 0x800024e4, 0x00000010, 0x800024e5, 0x00000010,
+ 0x800024e6, 0x00000010, 0x800024e7, 0x00000010,
+ 0x800024e8, 0x00000010, 0x800024e9, 0x00000010,
+ 0x8000ff41, 0x00000010, 0x8000ff42, 0x00000010,
+ 0x8000ff43, 0x00000010, 0x8000ff44, 0x00000010,
+ 0x8000ff45, 0x00000010, 0x8000ff46, 0x00000010,
+ 0x8000ff47, 0x00000010, 0x8000ff48, 0x00000010,
+ 0x8000ff49, 0x00000010, 0x8000ff4a, 0x00000010,
+ 0x8000ff4b, 0x00000010, 0x8000ff4c, 0x00000010,
+ 0x8000ff4d, 0x00000010, 0x8000ff4e, 0x00000010,
+ 0x8000ff4f, 0x00000010, 0x8000ff50, 0x00000010,
+ 0x8000ff51, 0x00000010, 0x8000ff52, 0x00000010,
+ 0x8000ff53, 0x00000010, 0x8000ff54, 0x00000010,
+ 0x8000ff55, 0x00000010, 0x8000ff56, 0x00000010,
+ 0x8000ff57, 0x00000010, 0x8000ff58, 0x00000010,
+ 0x8000ff59, 0x00000010, 0x8000ff5a, 0x00000010,
+ 0x80010428, 0x00000010, 0x80010429, 0x00000010,
+ 0x8001042a, 0x00000010, 0x8001042b, 0x00000010,
+ 0x8001042c, 0x00000010, 0x8001042d, 0x00000010,
+ 0x8001042e, 0x00000010, 0x8001042f, 0x00000010,
+ 0x80010430, 0x00000010, 0x80010431, 0x00000010,
+ 0x80010432, 0x00000010, 0x80010433, 0x00000010,
+ 0x80010434, 0x00000010, 0x80010435, 0x00000010,
+ 0x80010436, 0x00000010, 0x80010437, 0x00000010,
+ 0x80010438, 0x00000010, 0x80010439, 0x00000010,
+ 0x8001043a, 0x00000010, 0x8001043b, 0x00000010,
+ 0x8001043c, 0x00000010, 0x8001043d, 0x00000010,
+ 0x8001043e, 0x00000010, 0x8001043f, 0x00000010,
+ 0x80010440, 0x00000010, 0x80010441, 0x00000010,
+ 0x80010442, 0x00000010, 0x80010443, 0x00000010,
+ 0x80010444, 0x00000010, 0x80010445, 0x00000010,
+ 0x80010446, 0x00000010, 0x80010447, 0x00000010,
+ 0x80010448, 0x00000010, 0x80010449, 0x00000010,
+ 0x8001044a, 0x00000010, 0x8001044b, 0x00000010,
+ 0x8001044c, 0x00000010, 0x8001044d,
+};
+
+
+/*
+ * Cased characters and non-spacing marks (for casemap context)
+ */
+
+#define CASEMAP_CTX_BITS_0 9
+#define CASEMAP_CTX_BITS_1 7
+#define CASEMAP_CTX_BITS_2 5
+
+#define CTX_CASED 1
+#define CTX_NSM 2
+
+static const unsigned short v320_casemap_ctx_imap[] = {
+ 272, 400, 528, 656, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 912,
+ 1040, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 1168, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 0, 0, 1, 1, 0, 2, 3, 3,
+ 4, 4, 4, 4, 4, 5, 6, 4,
+ 4, 7, 8, 4, 4, 9, 0, 0,
+ 10, 10, 11, 11, 12, 13, 14, 15,
+ 4, 4, 4, 4, 16, 4, 14, 17,
+ 18, 19, 20, 21, 22, 23, 24, 0,
+ 0, 0, 25, 26, 0, 0, 27, 28,
+ 29, 30, 31, 0, 0, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 33, 34, 35, 36, 37, 34, 38, 36,
+ 39, 34, 40, 41, 33, 34, 42, 0,
+ 37, 43, 44, 0, 39, 0, 45, 0,
+ 0, 46, 47, 0, 0, 48, 49, 0,
+ 0, 0, 50, 0, 0, 0, 51, 0,
+ 0, 52, 53, 0, 0, 54, 55, 0,
+ 56, 57, 0, 58, 59, 60, 61, 0,
+ 0, 62, 56, 0, 0, 4, 63, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 64, 64, 65, 65, 0, 66, 67, 0,
+ 68, 0, 0, 0, 0, 69, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 70, 4, 4, 71,
+ 72, 4, 73, 74, 4, 75, 76, 77,
+ 0, 0, 0, 78, 0, 0, 79, 80,
+ 81, 82, 83, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 84, 0, 0, 85, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 86, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 11, 87, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 88, 9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 89, 90, 91, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 92, 4, 93, 94, 95, 4,
+ 96, 97, 98, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 99, 100, 5,
+ 92, 92, 14, 14, 101, 101, 102, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const struct {
+ unsigned char tbl[32];
+} v320_casemap_ctx_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ }},
+ {{
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 0, 2, 2, 2, 2, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2,
+ }},
+ {{
+ 0, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0,
+ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2,
+ }},
+ {{
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,
+ 0, 2, 0, 0, 0, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0,
+ }},
+ {{
+ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1,
+ 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1,
+ 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
+ }},
+ {{
+ 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1,
+ }},
+ {{
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+};
+
+/*
+ * Case Folding
+ */
+
+#define CASE_FOLDING_BITS_0 9
+#define CASE_FOLDING_BITS_1 7
+#define CASE_FOLDING_BITS_2 5
+
+static const unsigned short v320_case_folding_imap[] = {
+ 272, 400, 528, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 784,
+ 912, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 656, 656, 656, 656, 656, 656, 656, 656,
+ 0, 0, 1, 0, 0, 2, 3, 0,
+ 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 14, 0, 15, 16, 17, 18,
+ 19, 20, 0, 21, 22, 23, 24, 25,
+ 26, 27, 28, 0, 29, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 46, 0, 47, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 48, 49, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 50, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 51, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 52, 53, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const struct {
+ unsigned short tbl[32];
+} v320_case_folding_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 0, 52, 53, 54, 55, 56, 57, 58, 59,
+ }},
+ {{
+ 61, 0, 62, 0, 63, 0, 64, 0, 65, 0, 66,
+ 0, 67, 0, 68, 0, 69, 0, 70, 0, 71, 0,
+ 72, 0, 73, 0, 74, 0, 75, 0, 76, 0,
+ }},
+ {{
+ 77, 0, 78, 0, 79, 0, 80, 0, 81, 0, 82,
+ 0, 83, 0, 84, 0, 87, 0, 88, 0, 89, 0,
+ 90, 0, 0, 91, 0, 92, 0, 93, 0, 94,
+ }},
+ {{
+ 0, 95, 0, 96, 0, 97, 0, 98, 0, 99, 101,
+ 0, 102, 0, 103, 0, 104, 0, 105, 0, 106, 0,
+ 107, 0, 108, 0, 109, 0, 110, 0, 111, 0,
+ }},
+ {{
+ 112, 0, 113, 0, 114, 0, 115, 0, 116, 0, 117,
+ 0, 118, 0, 119, 0, 120, 0, 121, 0, 122, 0,
+ 123, 0, 124, 125, 0, 126, 0, 127, 0, 128,
+ }},
+ {{
+ 0, 129, 130, 0, 131, 0, 132, 133, 0, 134, 135,
+ 136, 0, 0, 137, 138, 139, 140, 0, 141, 142, 0,
+ 143, 144, 145, 0, 0, 0, 146, 147, 0, 148,
+ }},
+ {{
+ 149, 0, 150, 0, 151, 0, 152, 153, 0, 154, 0,
+ 0, 155, 0, 156, 157, 0, 158, 159, 160, 0, 161,
+ 0, 162, 163, 0, 0, 0, 164, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 165, 166, 0, 167, 168, 0, 169,
+ 170, 0, 171, 0, 172, 0, 173, 0, 174, 0, 175,
+ 0, 176, 0, 177, 0, 178, 0, 0, 179, 0,
+ }},
+ {{
+ 180, 0, 181, 0, 182, 0, 183, 0, 184, 0, 185,
+ 0, 186, 0, 187, 0, 188, 190, 191, 0, 192, 0,
+ 193, 194, 195, 0, 196, 0, 197, 0, 198, 0,
+ }},
+ {{
+ 199, 0, 200, 0, 201, 0, 202, 0, 203, 0, 204,
+ 0, 205, 0, 206, 0, 207, 0, 208, 0, 209, 0,
+ 210, 0, 211, 0, 212, 0, 213, 0, 214, 0,
+ }},
+ {{
+ 215, 0, 216, 0, 217, 0, 218, 0, 219, 0, 220,
+ 0, 221, 0, 222, 0, 223, 0, 224, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 225, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 226, 0, 227, 228, 229,
+ 0, 230, 0, 231, 232, 233, 236, 237, 238, 239, 240,
+ 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
+ }},
+ {{
+ 251, 252, 0, 253, 254, 255, 256, 257, 258, 259, 260,
+ 261, 0, 0, 0, 0, 262, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 265, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 266, 267, 0, 0, 0, 268,
+ 269, 0, 270, 0, 271, 0, 272, 0, 273, 0,
+ }},
+ {{
+ 274, 0, 275, 0, 276, 0, 277, 0, 278, 0, 279,
+ 0, 280, 0, 281, 0, 282, 283, 284, 0, 285, 286,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+ 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
+ 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
+ }},
+ {{
+ 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329,
+ 330, 331, 332, 333, 334, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 335, 0, 336, 0, 337, 0, 338, 0, 339, 0, 340,
+ 0, 341, 0, 342, 0, 343, 0, 344, 0, 345, 0,
+ 346, 0, 347, 0, 348, 0, 349, 0, 350, 0,
+ }},
+ {{
+ 351, 0, 0, 0, 0, 0, 0, 0, 0, 0, 352,
+ 0, 353, 0, 354, 0, 355, 0, 356, 0, 357, 0,
+ 358, 0, 359, 0, 360, 0, 361, 0, 362, 0,
+ }},
+ {{
+ 363, 0, 364, 0, 365, 0, 366, 0, 367, 0, 368,
+ 0, 369, 0, 370, 0, 371, 0, 372, 0, 373, 0,
+ 374, 0, 375, 0, 376, 0, 377, 0, 378, 0,
+ }},
+ {{
+ 0, 379, 0, 380, 0, 381, 0, 382, 0, 383, 0,
+ 384, 0, 385, 0, 0, 386, 0, 387, 0, 388, 0,
+ 389, 0, 390, 0, 391, 0, 392, 0, 393, 0,
+ }},
+ {{
+ 394, 0, 395, 0, 396, 0, 397, 0, 398, 0, 399,
+ 0, 400, 0, 401, 0, 402, 0, 403, 0, 404, 0,
+ 0, 0, 405, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 406, 0, 407, 0, 408, 0, 409, 0, 410, 0, 411,
+ 0, 412, 0, 413, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 414, 415, 416, 417, 418,
+ 419, 420, 421, 422, 423, 424, 425, 426, 427, 428,
+ }},
+ {{
+ 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439,
+ 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450,
+ 451, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 452, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 454, 0, 455, 0, 456, 0, 457, 0, 458, 0, 459,
+ 0, 460, 0, 461, 0, 462, 0, 463, 0, 464, 0,
+ 465, 0, 466, 0, 467, 0, 468, 0, 469, 0,
+ }},
+ {{
+ 470, 0, 471, 0, 472, 0, 473, 0, 474, 0, 475,
+ 0, 476, 0, 477, 0, 478, 0, 479, 0, 480, 0,
+ 481, 0, 482, 0, 483, 0, 484, 0, 485, 0,
+ }},
+ {{
+ 486, 0, 487, 0, 488, 0, 489, 0, 490, 0, 491,
+ 0, 492, 0, 493, 0, 494, 0, 495, 0, 496, 0,
+ 497, 0, 498, 0, 499, 0, 500, 0, 501, 0,
+ }},
+ {{
+ 502, 0, 503, 0, 504, 0, 505, 0, 506, 0, 507,
+ 0, 508, 0, 509, 0, 510, 0, 511, 0, 512, 0,
+ 513, 0, 514, 0, 515, 0, 516, 0, 517, 0,
+ }},
+ {{
+ 518, 0, 519, 0, 520, 0, 521, 0, 522, 0, 523,
+ 0, 524, 0, 525, 0, 526, 0, 527, 0, 528, 0,
+ 529, 531, 533, 535, 537, 539, 0, 0, 0, 0,
+ }},
+ {{
+ 540, 0, 541, 0, 542, 0, 543, 0, 544, 0, 545,
+ 0, 546, 0, 547, 0, 548, 0, 549, 0, 550, 0,
+ 551, 0, 552, 0, 553, 0, 554, 0, 555, 0,
+ }},
+ {{
+ 556, 0, 557, 0, 558, 0, 559, 0, 560, 0, 561,
+ 0, 562, 0, 563, 0, 564, 0, 565, 0, 566, 0,
+ 567, 0, 568, 0, 569, 0, 570, 0, 571, 0,
+ }},
+ {{
+ 572, 0, 573, 0, 574, 0, 575, 0, 576, 0, 577,
+ 0, 578, 0, 579, 0, 580, 0, 581, 0, 582, 0,
+ 583, 0, 584, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 585, 586, 587,
+ 588, 589, 590, 591, 592, 0, 0, 0, 0, 0, 0,
+ 0, 0, 593, 594, 595, 596, 597, 598, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 599, 600, 601,
+ 602, 603, 604, 605, 606, 0, 0, 0, 0, 0, 0,
+ 0, 0, 607, 608, 609, 610, 611, 612, 613, 614,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 615, 616, 617,
+ 618, 619, 620, 0, 0, 621, 0, 623, 0, 626, 0,
+ 629, 0, 0, 632, 0, 633, 0, 634, 0, 635,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 636, 637, 638,
+ 639, 640, 641, 642, 643, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 644, 646, 648, 650, 652, 654, 656, 658, 662, 665, 668,
+ 671, 674, 677, 680, 683, 684, 686, 688, 690, 692, 694,
+ 696, 698, 702, 705, 708, 711, 714, 717, 720, 723,
+ }},
+ {{
+ 724, 726, 728, 730, 732, 734, 736, 738, 742, 745, 748,
+ 751, 754, 757, 760, 763, 0, 0, 764, 766, 768, 0,
+ 770, 772, 775, 776, 777, 778, 781, 0, 782, 0,
+ }},
+ {{
+ 0, 0, 783, 785, 787, 0, 789, 791, 794, 795, 796,
+ 797, 800, 0, 0, 0, 0, 0, 801, 804, 0, 0,
+ 807, 809, 812, 813, 814, 815, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 816, 819, 822, 0, 824, 826, 829, 830, 831,
+ 832, 833, 0, 0, 0, 0, 0, 834, 836, 838, 0,
+ 840, 842, 845, 846, 847, 848, 851, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 852, 0, 0, 0, 853,
+ 854, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865,
+ 866, 867, 868, 869, 870, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 871, 872, 873, 874, 875, 876, 877, 878, 879, 880,
+ }},
+ {{
+ 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891,
+ 892, 893, 894, 895, 896, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 897, 899, 901, 903, 906, 909, 911, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 913, 915, 917,
+ 919, 921, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932,
+ 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943,
+ 944, 945, 946, 947, 948, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959,
+ 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970,
+ 971, 972, 973, 974, 975, 976, 977, 978, 979, 980,
+ }},
+ {{
+ 981, 982, 983, 984, 985, 986, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+};
+static const unsigned long v320_case_folding_seq[] = {
+ 0x00000000, 0x80000061, 0x80000062, 0x80000063,
+ 0x80000064, 0x80000065, 0x80000066, 0x80000067,
+ 0x80000068, 0x80000069, 0x80000131, 0x8000006a,
+ 0x8000006b, 0x8000006c, 0x8000006d, 0x8000006e,
+ 0x8000006f, 0x80000070, 0x80000071, 0x80000072,
+ 0x80000073, 0x80000074, 0x80000075, 0x80000076,
+ 0x80000077, 0x80000078, 0x80000079, 0x8000007a,
+ 0x800003bc, 0x800000e0, 0x800000e1, 0x800000e2,
+ 0x800000e3, 0x800000e4, 0x800000e5, 0x800000e6,
+ 0x800000e7, 0x800000e8, 0x800000e9, 0x800000ea,
+ 0x800000eb, 0x800000ec, 0x800000ed, 0x800000ee,
+ 0x800000ef, 0x800000f0, 0x800000f1, 0x800000f2,
+ 0x800000f3, 0x800000f4, 0x800000f5, 0x800000f6,
+ 0x800000f8, 0x800000f9, 0x800000fa, 0x800000fb,
+ 0x800000fc, 0x800000fd, 0x800000fe, 0x00000073,
+ 0x80000073, 0x80000101, 0x80000103, 0x80000105,
+ 0x80000107, 0x80000109, 0x8000010b, 0x8000010d,
+ 0x8000010f, 0x80000111, 0x80000113, 0x80000115,
+ 0x80000117, 0x80000119, 0x8000011b, 0x8000011d,
+ 0x8000011f, 0x80000121, 0x80000123, 0x80000125,
+ 0x80000127, 0x80000129, 0x8000012b, 0x8000012d,
+ 0x8000012f, 0x00000069, 0x80000307, 0x80000069,
+ 0x80000133, 0x80000135, 0x80000137, 0x8000013a,
+ 0x8000013c, 0x8000013e, 0x80000140, 0x80000142,
+ 0x80000144, 0x80000146, 0x80000148, 0x000002bc,
+ 0x8000006e, 0x8000014b, 0x8000014d, 0x8000014f,
+ 0x80000151, 0x80000153, 0x80000155, 0x80000157,
+ 0x80000159, 0x8000015b, 0x8000015d, 0x8000015f,
+ 0x80000161, 0x80000163, 0x80000165, 0x80000167,
+ 0x80000169, 0x8000016b, 0x8000016d, 0x8000016f,
+ 0x80000171, 0x80000173, 0x80000175, 0x80000177,
+ 0x800000ff, 0x8000017a, 0x8000017c, 0x8000017e,
+ 0x80000073, 0x80000253, 0x80000183, 0x80000185,
+ 0x80000254, 0x80000188, 0x80000256, 0x80000257,
+ 0x8000018c, 0x800001dd, 0x80000259, 0x8000025b,
+ 0x80000192, 0x80000260, 0x80000263, 0x80000269,
+ 0x80000268, 0x80000199, 0x8000026f, 0x80000272,
+ 0x80000275, 0x800001a1, 0x800001a3, 0x800001a5,
+ 0x80000280, 0x800001a8, 0x80000283, 0x800001ad,
+ 0x80000288, 0x800001b0, 0x8000028a, 0x8000028b,
+ 0x800001b4, 0x800001b6, 0x80000292, 0x800001b9,
+ 0x800001bd, 0x800001c6, 0x800001c6, 0x800001c9,
+ 0x800001c9, 0x800001cc, 0x800001cc, 0x800001ce,
+ 0x800001d0, 0x800001d2, 0x800001d4, 0x800001d6,
+ 0x800001d8, 0x800001da, 0x800001dc, 0x800001df,
+ 0x800001e1, 0x800001e3, 0x800001e5, 0x800001e7,
+ 0x800001e9, 0x800001eb, 0x800001ed, 0x800001ef,
+ 0x0000006a, 0x8000030c, 0x800001f3, 0x800001f3,
+ 0x800001f5, 0x80000195, 0x800001bf, 0x800001f9,
+ 0x800001fb, 0x800001fd, 0x800001ff, 0x80000201,
+ 0x80000203, 0x80000205, 0x80000207, 0x80000209,
+ 0x8000020b, 0x8000020d, 0x8000020f, 0x80000211,
+ 0x80000213, 0x80000215, 0x80000217, 0x80000219,
+ 0x8000021b, 0x8000021d, 0x8000021f, 0x8000019e,
+ 0x80000223, 0x80000225, 0x80000227, 0x80000229,
+ 0x8000022b, 0x8000022d, 0x8000022f, 0x80000231,
+ 0x80000233, 0x800003b9, 0x800003ac, 0x800003ad,
+ 0x800003ae, 0x800003af, 0x800003cc, 0x800003cd,
+ 0x800003ce, 0x000003b9, 0x00000308, 0x80000301,
+ 0x800003b1, 0x800003b2, 0x800003b3, 0x800003b4,
+ 0x800003b5, 0x800003b6, 0x800003b7, 0x800003b8,
+ 0x800003b9, 0x800003ba, 0x800003bb, 0x800003bc,
+ 0x800003bd, 0x800003be, 0x800003bf, 0x800003c0,
+ 0x800003c1, 0x800003c3, 0x800003c4, 0x800003c5,
+ 0x800003c6, 0x800003c7, 0x800003c8, 0x800003c9,
+ 0x800003ca, 0x800003cb, 0x000003c5, 0x00000308,
+ 0x80000301, 0x800003c3, 0x800003b2, 0x800003b8,
+ 0x800003c6, 0x800003c0, 0x800003d9, 0x800003db,
+ 0x800003dd, 0x800003df, 0x800003e1, 0x800003e3,
+ 0x800003e5, 0x800003e7, 0x800003e9, 0x800003eb,
+ 0x800003ed, 0x800003ef, 0x800003ba, 0x800003c1,
+ 0x800003c3, 0x800003b8, 0x800003b5, 0x80000450,
+ 0x80000451, 0x80000452, 0x80000453, 0x80000454,
+ 0x80000455, 0x80000456, 0x80000457, 0x80000458,
+ 0x80000459, 0x8000045a, 0x8000045b, 0x8000045c,
+ 0x8000045d, 0x8000045e, 0x8000045f, 0x80000430,
+ 0x80000431, 0x80000432, 0x80000433, 0x80000434,
+ 0x80000435, 0x80000436, 0x80000437, 0x80000438,
+ 0x80000439, 0x8000043a, 0x8000043b, 0x8000043c,
+ 0x8000043d, 0x8000043e, 0x8000043f, 0x80000440,
+ 0x80000441, 0x80000442, 0x80000443, 0x80000444,
+ 0x80000445, 0x80000446, 0x80000447, 0x80000448,
+ 0x80000449, 0x8000044a, 0x8000044b, 0x8000044c,
+ 0x8000044d, 0x8000044e, 0x8000044f, 0x80000461,
+ 0x80000463, 0x80000465, 0x80000467, 0x80000469,
+ 0x8000046b, 0x8000046d, 0x8000046f, 0x80000471,
+ 0x80000473, 0x80000475, 0x80000477, 0x80000479,
+ 0x8000047b, 0x8000047d, 0x8000047f, 0x80000481,
+ 0x8000048b, 0x8000048d, 0x8000048f, 0x80000491,
+ 0x80000493, 0x80000495, 0x80000497, 0x80000499,
+ 0x8000049b, 0x8000049d, 0x8000049f, 0x800004a1,
+ 0x800004a3, 0x800004a5, 0x800004a7, 0x800004a9,
+ 0x800004ab, 0x800004ad, 0x800004af, 0x800004b1,
+ 0x800004b3, 0x800004b5, 0x800004b7, 0x800004b9,
+ 0x800004bb, 0x800004bd, 0x800004bf, 0x800004c2,
+ 0x800004c4, 0x800004c6, 0x800004c8, 0x800004ca,
+ 0x800004cc, 0x800004ce, 0x800004d1, 0x800004d3,
+ 0x800004d5, 0x800004d7, 0x800004d9, 0x800004db,
+ 0x800004dd, 0x800004df, 0x800004e1, 0x800004e3,
+ 0x800004e5, 0x800004e7, 0x800004e9, 0x800004eb,
+ 0x800004ed, 0x800004ef, 0x800004f1, 0x800004f3,
+ 0x800004f5, 0x800004f9, 0x80000501, 0x80000503,
+ 0x80000505, 0x80000507, 0x80000509, 0x8000050b,
+ 0x8000050d, 0x8000050f, 0x80000561, 0x80000562,
+ 0x80000563, 0x80000564, 0x80000565, 0x80000566,
+ 0x80000567, 0x80000568, 0x80000569, 0x8000056a,
+ 0x8000056b, 0x8000056c, 0x8000056d, 0x8000056e,
+ 0x8000056f, 0x80000570, 0x80000571, 0x80000572,
+ 0x80000573, 0x80000574, 0x80000575, 0x80000576,
+ 0x80000577, 0x80000578, 0x80000579, 0x8000057a,
+ 0x8000057b, 0x8000057c, 0x8000057d, 0x8000057e,
+ 0x8000057f, 0x80000580, 0x80000581, 0x80000582,
+ 0x80000583, 0x80000584, 0x80000585, 0x80000586,
+ 0x00000565, 0x80000582, 0x80001e01, 0x80001e03,
+ 0x80001e05, 0x80001e07, 0x80001e09, 0x80001e0b,
+ 0x80001e0d, 0x80001e0f, 0x80001e11, 0x80001e13,
+ 0x80001e15, 0x80001e17, 0x80001e19, 0x80001e1b,
+ 0x80001e1d, 0x80001e1f, 0x80001e21, 0x80001e23,
+ 0x80001e25, 0x80001e27, 0x80001e29, 0x80001e2b,
+ 0x80001e2d, 0x80001e2f, 0x80001e31, 0x80001e33,
+ 0x80001e35, 0x80001e37, 0x80001e39, 0x80001e3b,
+ 0x80001e3d, 0x80001e3f, 0x80001e41, 0x80001e43,
+ 0x80001e45, 0x80001e47, 0x80001e49, 0x80001e4b,
+ 0x80001e4d, 0x80001e4f, 0x80001e51, 0x80001e53,
+ 0x80001e55, 0x80001e57, 0x80001e59, 0x80001e5b,
+ 0x80001e5d, 0x80001e5f, 0x80001e61, 0x80001e63,
+ 0x80001e65, 0x80001e67, 0x80001e69, 0x80001e6b,
+ 0x80001e6d, 0x80001e6f, 0x80001e71, 0x80001e73,
+ 0x80001e75, 0x80001e77, 0x80001e79, 0x80001e7b,
+ 0x80001e7d, 0x80001e7f, 0x80001e81, 0x80001e83,
+ 0x80001e85, 0x80001e87, 0x80001e89, 0x80001e8b,
+ 0x80001e8d, 0x80001e8f, 0x80001e91, 0x80001e93,
+ 0x80001e95, 0x00000068, 0x80000331, 0x00000074,
+ 0x80000308, 0x00000077, 0x8000030a, 0x00000079,
+ 0x8000030a, 0x00000061, 0x800002be, 0x80001e61,
+ 0x80001ea1, 0x80001ea3, 0x80001ea5, 0x80001ea7,
+ 0x80001ea9, 0x80001eab, 0x80001ead, 0x80001eaf,
+ 0x80001eb1, 0x80001eb3, 0x80001eb5, 0x80001eb7,
+ 0x80001eb9, 0x80001ebb, 0x80001ebd, 0x80001ebf,
+ 0x80001ec1, 0x80001ec3, 0x80001ec5, 0x80001ec7,
+ 0x80001ec9, 0x80001ecb, 0x80001ecd, 0x80001ecf,
+ 0x80001ed1, 0x80001ed3, 0x80001ed5, 0x80001ed7,
+ 0x80001ed9, 0x80001edb, 0x80001edd, 0x80001edf,
+ 0x80001ee1, 0x80001ee3, 0x80001ee5, 0x80001ee7,
+ 0x80001ee9, 0x80001eeb, 0x80001eed, 0x80001eef,
+ 0x80001ef1, 0x80001ef3, 0x80001ef5, 0x80001ef7,
+ 0x80001ef9, 0x80001f00, 0x80001f01, 0x80001f02,
+ 0x80001f03, 0x80001f04, 0x80001f05, 0x80001f06,
+ 0x80001f07, 0x80001f10, 0x80001f11, 0x80001f12,
+ 0x80001f13, 0x80001f14, 0x80001f15, 0x80001f20,
+ 0x80001f21, 0x80001f22, 0x80001f23, 0x80001f24,
+ 0x80001f25, 0x80001f26, 0x80001f27, 0x80001f30,
+ 0x80001f31, 0x80001f32, 0x80001f33, 0x80001f34,
+ 0x80001f35, 0x80001f36, 0x80001f37, 0x80001f40,
+ 0x80001f41, 0x80001f42, 0x80001f43, 0x80001f44,
+ 0x80001f45, 0x000003c5, 0x80000313, 0x000003c5,
+ 0x00000313, 0x80000300, 0x000003c5, 0x00000313,
+ 0x80000301, 0x000003c5, 0x00000313, 0x80000342,
+ 0x80001f51, 0x80001f53, 0x80001f55, 0x80001f57,
+ 0x80001f60, 0x80001f61, 0x80001f62, 0x80001f63,
+ 0x80001f64, 0x80001f65, 0x80001f66, 0x80001f67,
+ 0x00001f00, 0x800003b9, 0x00001f01, 0x800003b9,
+ 0x00001f02, 0x800003b9, 0x00001f03, 0x800003b9,
+ 0x00001f04, 0x800003b9, 0x00001f05, 0x800003b9,
+ 0x00001f06, 0x800003b9, 0x00001f07, 0x800003b9,
+ 0x00001f00, 0x800003b9, 0x80001f80, 0x00001f01,
+ 0x800003b9, 0x80001f81, 0x00001f02, 0x800003b9,
+ 0x80001f82, 0x00001f03, 0x800003b9, 0x80001f83,
+ 0x00001f04, 0x800003b9, 0x80001f84, 0x00001f05,
+ 0x800003b9, 0x80001f85, 0x00001f06, 0x800003b9,
+ 0x80001f86, 0x00001f07, 0x800003b9, 0x80001f87,
+ 0x00001f20, 0x800003b9, 0x00001f21, 0x800003b9,
+ 0x00001f22, 0x800003b9, 0x00001f23, 0x800003b9,
+ 0x00001f24, 0x800003b9, 0x00001f25, 0x800003b9,
+ 0x00001f26, 0x800003b9, 0x00001f27, 0x800003b9,
+ 0x00001f20, 0x800003b9, 0x80001f90, 0x00001f21,
+ 0x800003b9, 0x80001f91, 0x00001f22, 0x800003b9,
+ 0x80001f92, 0x00001f23, 0x800003b9, 0x80001f93,
+ 0x00001f24, 0x800003b9, 0x80001f94, 0x00001f25,
+ 0x800003b9, 0x80001f95, 0x00001f26, 0x800003b9,
+ 0x80001f96, 0x00001f27, 0x800003b9, 0x80001f97,
+ 0x00001f60, 0x800003b9, 0x00001f61, 0x800003b9,
+ 0x00001f62, 0x800003b9, 0x00001f63, 0x800003b9,
+ 0x00001f64, 0x800003b9, 0x00001f65, 0x800003b9,
+ 0x00001f66, 0x800003b9, 0x00001f67, 0x800003b9,
+ 0x00001f60, 0x800003b9, 0x80001fa0, 0x00001f61,
+ 0x800003b9, 0x80001fa1, 0x00001f62, 0x800003b9,
+ 0x80001fa2, 0x00001f63, 0x800003b9, 0x80001fa3,
+ 0x00001f64, 0x800003b9, 0x80001fa4, 0x00001f65,
+ 0x800003b9, 0x80001fa5, 0x00001f66, 0x800003b9,
+ 0x80001fa6, 0x00001f67, 0x800003b9, 0x80001fa7,
+ 0x00001f70, 0x800003b9, 0x000003b1, 0x800003b9,
+ 0x000003ac, 0x800003b9, 0x000003b1, 0x80000342,
+ 0x000003b1, 0x00000342, 0x800003b9, 0x80001fb0,
+ 0x80001fb1, 0x80001f70, 0x80001f71, 0x000003b1,
+ 0x800003b9, 0x80001fb3, 0x800003b9, 0x00001f74,
+ 0x800003b9, 0x000003b7, 0x800003b9, 0x000003ae,
+ 0x800003b9, 0x000003b7, 0x80000342, 0x000003b7,
+ 0x00000342, 0x800003b9, 0x80001f72, 0x80001f73,
+ 0x80001f74, 0x80001f75, 0x000003b7, 0x800003b9,
+ 0x80001fc3, 0x000003b9, 0x00000308, 0x80000300,
+ 0x000003b9, 0x00000308, 0x80000301, 0x000003b9,
+ 0x80000342, 0x000003b9, 0x00000308, 0x80000342,
+ 0x80001fd0, 0x80001fd1, 0x80001f76, 0x80001f77,
+ 0x000003c5, 0x00000308, 0x80000300, 0x000003c5,
+ 0x00000308, 0x80000301, 0x000003c1, 0x80000313,
+ 0x000003c5, 0x80000342, 0x000003c5, 0x00000308,
+ 0x80000342, 0x80001fe0, 0x80001fe1, 0x80001f7a,
+ 0x80001f7b, 0x80001fe5, 0x00001f7c, 0x800003b9,
+ 0x000003c9, 0x800003b9, 0x000003ce, 0x800003b9,
+ 0x000003c9, 0x80000342, 0x000003c9, 0x00000342,
+ 0x800003b9, 0x80001f78, 0x80001f79, 0x80001f7c,
+ 0x80001f7d, 0x000003c9, 0x800003b9, 0x80001ff3,
+ 0x800003c9, 0x8000006b, 0x800000e5, 0x80002170,
+ 0x80002171, 0x80002172, 0x80002173, 0x80002174,
+ 0x80002175, 0x80002176, 0x80002177, 0x80002178,
+ 0x80002179, 0x8000217a, 0x8000217b, 0x8000217c,
+ 0x8000217d, 0x8000217e, 0x8000217f, 0x800024d0,
+ 0x800024d1, 0x800024d2, 0x800024d3, 0x800024d4,
+ 0x800024d5, 0x800024d6, 0x800024d7, 0x800024d8,
+ 0x800024d9, 0x800024da, 0x800024db, 0x800024dc,
+ 0x800024dd, 0x800024de, 0x800024df, 0x800024e0,
+ 0x800024e1, 0x800024e2, 0x800024e3, 0x800024e4,
+ 0x800024e5, 0x800024e6, 0x800024e7, 0x800024e8,
+ 0x800024e9, 0x00000066, 0x80000066, 0x00000066,
+ 0x80000069, 0x00000066, 0x8000006c, 0x00000066,
+ 0x00000066, 0x80000069, 0x00000066, 0x00000066,
+ 0x8000006c, 0x00000073, 0x80000074, 0x00000073,
+ 0x80000074, 0x00000574, 0x80000576, 0x00000574,
+ 0x80000565, 0x00000574, 0x8000056b, 0x0000057e,
+ 0x80000576, 0x00000574, 0x8000056d, 0x8000ff41,
+ 0x8000ff42, 0x8000ff43, 0x8000ff44, 0x8000ff45,
+ 0x8000ff46, 0x8000ff47, 0x8000ff48, 0x8000ff49,
+ 0x8000ff4a, 0x8000ff4b, 0x8000ff4c, 0x8000ff4d,
+ 0x8000ff4e, 0x8000ff4f, 0x8000ff50, 0x8000ff51,
+ 0x8000ff52, 0x8000ff53, 0x8000ff54, 0x8000ff55,
+ 0x8000ff56, 0x8000ff57, 0x8000ff58, 0x8000ff59,
+ 0x8000ff5a, 0x80010428, 0x80010429, 0x8001042a,
+ 0x8001042b, 0x8001042c, 0x8001042d, 0x8001042e,
+ 0x8001042f, 0x80010430, 0x80010431, 0x80010432,
+ 0x80010433, 0x80010434, 0x80010435, 0x80010436,
+ 0x80010437, 0x80010438, 0x80010439, 0x8001043a,
+ 0x8001043b, 0x8001043c, 0x8001043d, 0x8001043e,
+ 0x8001043f, 0x80010440, 0x80010441, 0x80010442,
+ 0x80010443, 0x80010444, 0x80010445, 0x80010446,
+ 0x80010447, 0x80010448, 0x80010449, 0x8001044a,
+ 0x8001044b, 0x8001044c, 0x8001044d,
+};
+
diff --git a/contrib/idn/idnkit-1.0-src/lib/unormalize.c b/contrib/idn/idnkit-1.0-src/lib/unormalize.c
new file mode 100644
index 0000000..f741724
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/unormalize.c
@@ -0,0 +1,413 @@
+#ifndef lint
+static char *rcsid = "$Id: unormalize.c,v 1.1.1.1 2003/06/04 00:26:43 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <idn/result.h>
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/ucs4.h>
+#include <idn/unicode.h>
+#include <idn/unormalize.h>
+#include <idn/debug.h>
+
+#if !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY)
+#define memmove(a,b,c) bcopy((char *)(b),(char *)(a),(int)(c))
+#endif
+
+#define WORKBUF_SIZE 128
+#define WORKBUF_SIZE_MAX 10000
+
+typedef struct {
+ idn__unicode_version_t version; /* Unicode version */
+ int cur; /* pointing now processing character */
+ int last; /* pointing just after the last character */
+ int size; /* size of UCS and CLASS array */
+ unsigned long *ucs4; /* UCS-4 characters */
+ int *class; /* and their canonical classes */
+ unsigned long ucs4_buf[WORKBUF_SIZE]; /* local buffer */
+ int class_buf[WORKBUF_SIZE]; /* ditto */
+} workbuf_t;
+
+static idn_result_t normalize(idn__unicode_version_t version,
+ int do_composition, int compat,
+ const unsigned long *from,
+ unsigned long *to, size_t tolen);
+static idn_result_t decompose(workbuf_t *wb, unsigned long c, int compat);
+static void get_class(workbuf_t *wb);
+static void reorder(workbuf_t *wb);
+static void compose(workbuf_t *wb);
+static idn_result_t flush_before_cur(workbuf_t *wb,
+ unsigned long **top, size_t *tolenp);
+static void workbuf_init(workbuf_t *wb);
+static void workbuf_free(workbuf_t *wb);
+static idn_result_t workbuf_extend(workbuf_t *wb);
+static idn_result_t workbuf_append(workbuf_t *wb, unsigned long c);
+static void workbuf_shift(workbuf_t *wb, int shift);
+static void workbuf_removevoid(workbuf_t *wb);
+
+idn_result_t
+idn__unormalize_formkc(idn__unicode_version_t version,
+ const unsigned long *from, unsigned long *to,
+ size_t tolen) {
+ assert(version != NULL && from != NULL && to != NULL && tolen >= 0);
+ TRACE(("idn__unormalize_formkc(from=\"%s\", tolen=%d)\n",
+ idn__debug_ucs4xstring(from, 50), tolen));
+ return (normalize(version, 1, 1, from, to, tolen));
+}
+
+static idn_result_t
+normalize(idn__unicode_version_t version, int do_composition, int compat,
+ const unsigned long *from, unsigned long *to, size_t tolen) {
+ workbuf_t wb;
+ idn_result_t r = idn_success;
+
+ /*
+ * Initialize working buffer.
+ */
+ workbuf_init(&wb);
+ wb.version = version;
+
+ while (*from != '\0') {
+ unsigned long c;
+
+ assert(wb.cur == wb.last);
+
+ /*
+ * Get one character from 'from'.
+ */
+ c = *from++;
+
+ /*
+ * Decompose it.
+ */
+ if ((r = decompose(&wb, c, compat)) != idn_success)
+ goto ret;
+
+ /*
+ * Get canonical class.
+ */
+ get_class(&wb);
+
+ /*
+ * Reorder & compose.
+ */
+ for (; wb.cur < wb.last; wb.cur++) {
+ if (wb.cur == 0) {
+ continue;
+ } else if (wb.class[wb.cur] > 0) {
+ /*
+ * This is not a starter. Try reordering.
+ * Note that characters up to it are
+ * already in canonical order.
+ */
+ reorder(&wb);
+ continue;
+ }
+
+ /*
+ * This is a starter character, and there are
+ * some characters before it. Those characters
+ * have been reordered properly, and
+ * ready for composition.
+ */
+ if (do_composition && wb.class[0] == 0)
+ compose(&wb);
+
+ /*
+ * If CUR points to a starter character,
+ * then process of characters before CUR are
+ * already finished, because any further
+ * reordering/composition for them are blocked
+ * by the starter CUR points.
+ */
+ if (wb.cur > 0 && wb.class[wb.cur] == 0) {
+ /* Flush everything before CUR. */
+ r = flush_before_cur(&wb, &to, &tolen);
+ if (r != idn_success)
+ goto ret;
+ }
+ }
+ }
+
+ if (r == idn_success) {
+ if (do_composition && wb.cur > 0 && wb.class[0] == 0) {
+ /*
+ * There is some characters left in WB.
+ * They are ordered, but not composed yet.
+ * Now CUR points just after the last character in WB,
+ * and since compose() tries to compose characters
+ * between top and CUR inclusive, we must make CUR
+ * one character back during compose().
+ */
+ wb.cur--;
+ compose(&wb);
+ wb.cur++;
+ }
+ /*
+ * Call this even when WB.CUR == 0, to make TO
+ * NUL-terminated.
+ */
+ r = flush_before_cur(&wb, &to, &tolen);
+ if (r != idn_success)
+ goto ret;
+ }
+
+ if (tolen <= 0) {
+ r = idn_buffer_overflow;
+ goto ret;
+ }
+ *to = '\0';
+
+ret:
+ workbuf_free(&wb);
+ return (r);
+}
+
+static idn_result_t
+decompose(workbuf_t *wb, unsigned long c, int compat) {
+ idn_result_t r;
+ int dec_len;
+
+again:
+ r = idn__unicode_decompose(wb->version, compat, wb->ucs4 + wb->last,
+ wb->size - wb->last, c, &dec_len);
+ switch (r) {
+ case idn_success:
+ wb->last += dec_len;
+ return (idn_success);
+ case idn_notfound:
+ return (workbuf_append(wb, c));
+ case idn_buffer_overflow:
+ if ((r = workbuf_extend(wb)) != idn_success)
+ return (r);
+ if (wb->size > WORKBUF_SIZE_MAX) {
+ WARNING(("idn__unormalize_form*: "
+ "working buffer too large\n"));
+ return (idn_nomemory);
+ }
+ goto again;
+ default:
+ return (r);
+ }
+ /* NOTREACHED */
+}
+
+static void
+get_class(workbuf_t *wb) {
+ int i;
+
+ for (i = wb->cur; i < wb->last; i++)
+ wb->class[i] = idn__unicode_canonicalclass(wb->version,
+ wb->ucs4[i]);
+}
+
+static void
+reorder(workbuf_t *wb) {
+ unsigned long c;
+ int i;
+ int class;
+
+ assert(wb != NULL);
+
+ i = wb->cur;
+ c = wb->ucs4[i];
+ class = wb->class[i];
+
+ while (i > 0 && wb->class[i - 1] > class) {
+ wb->ucs4[i] = wb->ucs4[i - 1];
+ wb->class[i] =wb->class[i - 1];
+ i--;
+ wb->ucs4[i] = c;
+ wb->class[i] = class;
+ }
+}
+
+static void
+compose(workbuf_t *wb) {
+ int cur;
+ unsigned long *ucs4;
+ int *class;
+ int last_class;
+ int nvoids;
+ int i;
+ idn__unicode_version_t ver;
+
+ assert(wb != NULL && wb->class[0] == 0);
+
+ cur = wb->cur;
+ ucs4 = wb->ucs4;
+ class = wb->class;
+ ver = wb->version;
+
+ /*
+ * If there are no decomposition sequence that begins with
+ * the top character, composition is impossible.
+ */
+ if (!idn__unicode_iscompositecandidate(ver, ucs4[0]))
+ return;
+
+ last_class = 0;
+ nvoids = 0;
+ for (i = 1; i <= cur; i++) {
+ unsigned long c;
+ int cl = class[i];
+
+ if ((last_class < cl || cl == 0) &&
+ idn__unicode_compose(ver, ucs4[0], ucs4[i],
+ &c) == idn_success) {
+ /*
+ * Replace the top character with the composed one.
+ */
+ ucs4[0] = c;
+ class[0] = idn__unicode_canonicalclass(ver, c);
+
+ class[i] = -1; /* void this character */
+ nvoids++;
+ } else {
+ last_class = cl;
+ }
+ }
+
+ /* Purge void characters, if any. */
+ if (nvoids > 0)
+ workbuf_removevoid(wb);
+}
+
+static idn_result_t
+flush_before_cur(workbuf_t *wb, unsigned long **top, size_t *tolenp) {
+ if (*tolenp < wb->cur)
+ return (idn_buffer_overflow);
+
+ memcpy(*top, wb->ucs4, sizeof(**top) * wb->cur);
+ *top += wb->cur;
+ *tolenp -= wb->cur;
+ workbuf_shift(wb, wb->cur);
+
+ return (idn_success);
+}
+
+static void
+workbuf_init(workbuf_t *wb) {
+ wb->cur = 0;
+ wb->last = 0;
+ wb->size = WORKBUF_SIZE;
+ wb->ucs4 = wb->ucs4_buf;
+ wb->class = wb->class_buf;
+}
+
+static void
+workbuf_free(workbuf_t *wb) {
+ if (wb->ucs4 != wb->ucs4_buf) {
+ free(wb->ucs4);
+ free(wb->class);
+ }
+}
+
+static idn_result_t
+workbuf_extend(workbuf_t *wb) {
+ int newsize = wb->size * 3;
+
+ if (wb->ucs4 == wb->ucs4_buf) {
+ wb->ucs4 = malloc(sizeof(wb->ucs4[0]) * newsize);
+ wb->class = malloc(sizeof(wb->class[0]) * newsize);
+ } else {
+ wb->ucs4 = realloc(wb->ucs4, sizeof(wb->ucs4[0]) * newsize);
+ wb->class = realloc(wb->class, sizeof(wb->class[0]) * newsize);
+ }
+ if (wb->ucs4 == NULL || wb->class == NULL)
+ return (idn_nomemory);
+ else
+ return (idn_success);
+}
+
+static idn_result_t
+workbuf_append(workbuf_t *wb, unsigned long c) {
+ idn_result_t r;
+
+ if (wb->last >= wb->size && (r = workbuf_extend(wb)) != idn_success)
+ return (r);
+ wb->ucs4[wb->last++] = c;
+ return (idn_success);
+}
+
+static void
+workbuf_shift(workbuf_t *wb, int shift) {
+ int nmove;
+
+ assert(wb != NULL && wb->cur >= shift);
+
+ nmove = wb->last - shift;
+ (void)memmove(&wb->ucs4[0], &wb->ucs4[shift],
+ nmove * sizeof(wb->ucs4[0]));
+ (void)memmove(&wb->class[0], &wb->class[shift],
+ nmove * sizeof(wb->class[0]));
+ wb->cur -= shift;
+ wb->last -= shift;
+}
+
+static void
+workbuf_removevoid(workbuf_t *wb) {
+ int i, j;
+ int last = wb->last;
+
+ for (i = j = 0; i < last; i++) {
+ if (wb->class[i] >= 0) {
+ if (j < i) {
+ wb->ucs4[j] = wb->ucs4[i];
+ wb->class[j] = wb->class[i];
+ }
+ j++;
+ }
+ }
+ wb->cur -= last - j;
+ wb->last = j;
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/utf8.c b/contrib/idn/idnkit-1.0-src/lib/utf8.c
new file mode 100644
index 0000000..7a9acd6
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/utf8.c
@@ -0,0 +1,276 @@
+#ifndef lint
+static char *rcsid = "$Id: utf8.c,v 1.1.1.1 2003/06/04 00:26:44 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/utf8.h>
+#include <idn/debug.h>
+
+#define UTF8_WIDTH(c) \
+ (((c) < 0x80) ? 1 : \
+ ((c) < 0xc0) ? 0 : \
+ ((c) < 0xe0) ? 2 : \
+ ((c) < 0xf0) ? 3 : \
+ ((c) < 0xf8) ? 4 : \
+ ((c) < 0xfc) ? 5 : \
+ ((c) < 0xfe) ? 6 : 0)
+
+#define VALID_CONT_BYTE(c) (0x80 <= (c) && (c) < 0xc0)
+
+int
+idn_utf8_mblen(const char *s) {
+ int c = *(unsigned char *)s;
+
+ assert(s != NULL);
+
+#if 0
+ TRACE(("idn_utf8_mblen(s=<%s>)\n", idn__debug_hexstring(s, 6)));
+#endif
+
+ return UTF8_WIDTH(c);
+}
+
+int
+idn_utf8_getmb(const char *s, size_t len, char *buf) {
+ /* buf must be at least 7-bytes long */
+ const unsigned char *p = (const unsigned char *)s;
+ unsigned char *q = (unsigned char *)buf;
+ int width = UTF8_WIDTH(*p);
+ int w;
+
+ assert(s != NULL);
+
+#if 0
+ TRACE(("idn_utf8_getmb(s=<%s>,len=%d)\n",
+ idn__debug_hexstring(s, 6), len));
+#endif
+
+ if (width == 0 || len < width)
+ return (0);
+
+ /* Copy the first byte. */
+ *q++ = *p++;
+
+ /* .. and the rest. */
+ w = width;
+ while (--w > 0) {
+ if (!VALID_CONT_BYTE(*p))
+ return (0);
+ *q++ = *p++;
+ }
+ return (width);
+}
+
+int
+idn_utf8_getwc(const char *s, size_t len, unsigned long *vp) {
+ unsigned long v;
+ unsigned long min;
+ const unsigned char *p = (const unsigned char *)s;
+ int c;
+ int width;
+ int rest;
+
+ assert(s != NULL);
+
+#if 0
+ TRACE(("idn_utf8_getwc(s=<%s>,len=%d)\n",
+ idn__debug_hexstring(s, 10), len));
+#endif
+
+ c = *p++;
+ width = UTF8_WIDTH(c);
+
+ switch (width) {
+ case 0:
+ return (0);
+ case 1:
+ v = c;
+ min = 0;
+ break;
+ case 2:
+ v = c & 0x1f;
+ min = 0x80;
+ break;
+ case 3:
+ v = c & 0xf;
+ min = 0x800;
+ break;
+ case 4:
+ v = c & 0x7;
+ min = 0x10000;
+ break;
+ case 5:
+ v = c & 3;
+ min = 0x200000;
+ break;
+ case 6:
+ v = c & 1;
+ min = 0x4000000;
+ break;
+ default:
+ FATAL(("idn_utf8_getint: internal error\n"));
+ return (0);
+ }
+
+ if (len < width)
+ return (0);
+
+ rest = width - 1;
+ while (rest-- > 0) {
+ if (!VALID_CONT_BYTE(*p))
+ return (0);
+ v = (v << 6) | (*p & 0x3f);
+ p++;
+ }
+
+ if (v < min)
+ return (0);
+
+ *vp = v;
+ return (width);
+}
+
+int
+idn_utf8_putwc(char *s, size_t len, unsigned long v) {
+ unsigned char *p = (unsigned char *)s;
+ int mask;
+ int off;
+ int l;
+
+ assert(s != NULL);
+
+#if 0
+ TRACE(("idn_utf8_putwc(v=%lx)\n", v));
+#endif
+
+ if (v < 0x80) {
+ mask = 0;
+ l = 1;
+ } else if (v < 0x800) {
+ mask = 0xc0;
+ l = 2;
+ } else if (v < 0x10000) {
+ mask = 0xe0;
+ l = 3;
+ } else if (v < 0x200000) {
+ mask = 0xf0;
+ l = 4;
+ } else if (v < 0x4000000) {
+ mask = 0xf8;
+ l = 5;
+ } else if (v < 0x80000000) {
+ mask = 0xfc;
+ l = 6;
+ } else {
+ return (0);
+ }
+
+ if (len < l)
+ return (0);
+
+ off = 6 * (l - 1);
+ *p++ = (v >> off) | mask;
+ mask = 0x80;
+ while (off > 0) {
+ off -= 6;
+ *p++ = ((v >> off) & 0x3f) | mask;
+ }
+ return l;
+}
+
+int
+idn_utf8_isvalidchar(const char *s) {
+ unsigned long dummy;
+
+ TRACE(("idn_utf8_isvalidchar(s=<%s>)\n",
+ idn__debug_hexstring(s, 6)));
+
+ return (idn_utf8_getwc(s, 6, &dummy) > 0);
+}
+
+int
+idn_utf8_isvalidstring(const char *s) {
+ unsigned long dummy;
+ int width;
+
+ assert(s != NULL);
+
+ TRACE(("idn_utf8_isvalidstring(s=<%s>)\n",
+ idn__debug_hexstring(s, 20)));
+
+ while (*s != '\0') {
+ width = idn_utf8_getwc(s, 6, &dummy);
+ if (width == 0)
+ return (0);
+ s += width;
+ }
+ return (1);
+}
+
+char *
+idn_utf8_findfirstbyte(const char *s, const char *known_top) {
+ const unsigned char *p = (const unsigned char *)s;
+ const unsigned char *t = (const unsigned char *)known_top;
+
+ assert(s != NULL && known_top != NULL && known_top <= s);
+
+ TRACE(("idn_utf8_findfirstbyte(s=<%s>)\n",
+ idn__debug_hexstring(s, 8)));
+
+ while (p >= t) {
+ if (!VALID_CONT_BYTE(*p))
+ break;
+ p--;
+ }
+ if (p < t || UTF8_WIDTH(*p) == 0)
+ return (NULL);
+
+ return ((char *)p);
+}
diff --git a/contrib/idn/idnkit-1.0-src/lib/util.c b/contrib/idn/idnkit-1.0-src/lib/util.c
new file mode 100644
index 0000000..a2d315a
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/util.c
@@ -0,0 +1,162 @@
+#ifndef lint
+static char *rcsid = "$Id: util.c,v 1.1.1.1 2003/06/04 00:26:45 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#ifdef WIN32
+#include <windows.h>
+#undef ERROR
+#endif
+
+#include <stddef.h>
+
+#include <idn/assert.h>
+#include <idn/result.h>
+#include <idn/logmacro.h>
+#include <idn/util.h>
+#include <idn/ucs4.h>
+
+#ifdef WIN32
+#define IDNKEY_IDNKIT "Software\\JPNIC\\IDN"
+#endif
+
+/*
+ * ASCII ctype macros.
+ * Note that these macros evaluate the argument multiple times. Be careful.
+ */
+#define ASCII_ISDIGIT(c) \
+ ('0' <= (c) && (c) <= '9')
+#define ASCII_ISUPPER(c) \
+ ('A' <= (c) && (c) <= 'Z')
+#define ASCII_ISLOWER(c) \
+ ('a' <= (c) && (c) <= 'z')
+#define ASCII_ISALPHA(c) \
+ (ASCII_ISUPPER(c) || ASCII_ISLOWER(c))
+#define ASCII_ISALNUM(c) \
+ (ASCII_ISDIGIT(c) || ASCII_ISUPPER(c) || ASCII_ISLOWER(c))
+
+#define ASCII_TOUPPER(c) \
+ (('a' <= (c) && (c) <= 'z') ? ((c) - 'a' + 'A') : (c))
+#define ASCII_TOLOWER(c) \
+ (('A' <= (c) && (c) <= 'Z') ? ((c) - 'A' + 'a') : (c))
+
+int
+idn__util_asciihaveaceprefix(const char *str, const char *prefix) {
+ assert(str != NULL && prefix != NULL);
+
+ while (*prefix != '\0') {
+ if (ASCII_TOLOWER(*str) != ASCII_TOLOWER(*prefix))
+ return 0;
+ str++;
+ prefix++;
+ }
+
+ return (1);
+}
+
+int
+idn__util_ucs4haveaceprefix(const unsigned long *str, const char *prefix) {
+ assert(str != NULL && prefix != NULL);
+
+ while (*prefix != '\0') {
+ if (ASCII_TOLOWER(*str) != ASCII_TOLOWER(*prefix))
+ return 0;
+ str++;
+ prefix++;
+ }
+
+ return (1);
+}
+
+int
+idn__util_ucs4isasciirange(const unsigned long *str) {
+ while (*str != '\0') {
+ if (*str > 0x7f)
+ return (0);
+ str++;
+ }
+
+ return (1);
+}
+
+#ifdef WIN32
+int
+idn__util_getregistrystring(idn__util_hkey_t topkey, const char *name,
+ char *str, size_t length)
+{
+ HKEY top;
+ LONG stat;
+ HKEY hk;
+ DWORD len, type;
+
+ assert((topkey == idn__util_hkey_currentuser ||
+ topkey == idn__util_hkey_localmachine) &&
+ name != NULL && str != NULL);
+
+ if (topkey == idn__util_hkey_currentuser) {
+ top= HKEY_CURRENT_USER;
+ } else { /* idn__util_hkey_localmachine */
+ top = HKEY_LOCAL_MACHINE;
+ }
+
+ stat = RegOpenKeyEx(top, IDNKEY_IDNKIT, 0, KEY_READ, &hk);
+ if (stat != ERROR_SUCCESS) {
+ return (0);
+ }
+
+ len = (DWORD)length;
+ stat = RegQueryValueEx(hk, (LPCTSTR)name, NULL,
+ &type, (LPBYTE)str, &len);
+ RegCloseKey(hk);
+
+ if (stat != ERROR_SUCCESS || type != REG_SZ) {
+ return (0);
+ }
+
+ return (1);
+}
+#endif /* WIN32 */
diff --git a/contrib/idn/idnkit-1.0-src/lib/version.c b/contrib/idn/idnkit-1.0-src/lib/version.c
new file mode 100644
index 0000000..31fdba7
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/lib/version.c
@@ -0,0 +1,54 @@
+#ifndef lint
+static char *rcsid = "$Id: version.c,v 1.1.1.1 2003/06/04 00:26:45 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <idn/version.h>
+
+const char *
+idn_version_getstring(void) {
+ return IDNKIT_VERSION;
+}
diff --git a/contrib/idn/idnkit-1.0-src/ltconfig b/contrib/idn/idnkit-1.0-src/ltconfig
new file mode 100755
index 0000000..c1cb8c0
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/ltconfig
@@ -0,0 +1,3114 @@
+#! /bin/sh
+
+# ltconfig - Create a system-specific libtool.
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A lot of this script is taken from autoconf-2.10.
+
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+echo=echo
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec "$SHELL" "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# Find the correct PATH separator. Usually this is `:', but
+# DJGPP uses `;' like DOS.
+if test "X${PATH_SEPARATOR+set}" != Xset; then
+ UNAME=${UNAME-`uname 2>/dev/null`}
+ case X$UNAME in
+ *-DOS) PATH_SEPARATOR=';' ;;
+ *) PATH_SEPARATOR=':' ;;
+ esac
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+if test "X${echo_test_string+set}" != Xset; then
+ # find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+ echo_test_string="`eval $cmd`" &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" != 'X\t' ||
+ test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for dir in $PATH /usr/ucb; do
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running ltconfig again with it.
+ ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}"
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"}
+ else
+ # Try using printf.
+ echo='printf "%s\n"'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL"
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
+ test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
+ echo="$CONFIG_SHELL $0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "$0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# The name of this program.
+progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'`
+
+# Constants:
+PROGRAM=ltconfig
+PACKAGE=libtool
+VERSION=1.3.5
+TIMESTAMP=" (1.385.2.206 2000/05/27 11:12:27)"
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+rm="rm -f"
+
+help="Try \`$progname --help' for more information."
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+enable_shared=yes
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+enable_static=yes
+enable_fast_install=yes
+enable_dlopen=unknown
+enable_win32_dll=no
+ltmain=
+silent=
+srcdir=
+ac_config_guess=
+ac_config_sub=
+host=
+nonopt=
+ofile="$default_ofile"
+verify_host=yes
+with_gcc=no
+with_gnu_ld=no
+need_locks=yes
+ac_ext=c
+objext=o
+libext=a
+exeext=
+cache_file=
+
+old_AR="$AR"
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+old_CPPFLAGS="$CPPFLAGS"
+old_LDFLAGS="$LDFLAGS"
+old_LD="$LD"
+old_LN_S="$LN_S"
+old_LIBS="$LIBS"
+old_NM="$NM"
+old_RANLIB="$RANLIB"
+old_DLLTOOL="$DLLTOOL"
+old_OBJDUMP="$OBJDUMP"
+old_AS="$AS"
+
+# Parse the command line options.
+args=
+prev=
+for option
+do
+ case "$option" in
+ -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ eval "$prev=\$option"
+ prev=
+ continue
+ fi
+
+ case "$option" in
+ --help) cat <<EOM
+Usage: $progname [OPTION]... [HOST [LTMAIN]]
+
+Generate a system-specific libtool script.
+
+ --debug enable verbose shell tracing
+ --disable-shared do not build shared libraries
+ --disable-static do not build static libraries
+ --disable-fast-install do not optimize for fast installation
+ --enable-dlopen enable dlopen support
+ --enable-win32-dll enable building dlls on win32 hosts
+ --help display this help and exit
+ --no-verify do not verify that HOST is a valid host type
+-o, --output=FILE specify the output file [default=$default_ofile]
+ --quiet same as \`--silent'
+ --silent do not print informational messages
+ --srcdir=DIR find \`config.guess' in DIR
+ --version output version information and exit
+ --with-gcc assume that the GNU C compiler will be used
+ --with-gnu-ld assume that the C compiler uses the GNU linker
+ --disable-lock disable file locking
+ --cache-file=FILE configure cache file
+
+LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program
+that provides basic libtool functionality.
+
+HOST is the canonical host system name [default=guessed].
+EOM
+ exit 0
+ ;;
+
+ --debug)
+ echo "$progname: enabling shell trace mode"
+ set -x
+ ;;
+
+ --disable-shared) enable_shared=no ;;
+
+ --disable-static) enable_static=no ;;
+
+ --disable-fast-install) enable_fast_install=no ;;
+
+ --enable-dlopen) enable_dlopen=yes ;;
+
+ --enable-win32-dll) enable_win32_dll=yes ;;
+
+ --quiet | --silent) silent=yes ;;
+
+ --srcdir) prev=srcdir ;;
+ --srcdir=*) srcdir="$optarg" ;;
+
+ --no-verify) verify_host=no ;;
+
+ --output | -o) prev=ofile ;;
+ --output=*) ofile="$optarg" ;;
+
+ --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;;
+
+ --with-gcc) with_gcc=yes ;;
+ --with-gnu-ld) with_gnu_ld=yes ;;
+
+ --disable-lock) need_locks=no ;;
+
+ --cache-file=*) cache_file="$optarg" ;;
+
+ -*)
+ echo "$progname: unrecognized option \`$option'" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ if test -z "$ltmain"; then
+ ltmain="$option"
+ elif test -z "$host"; then
+# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
+# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
+# echo "$progname: warning \`$option' is not a valid host type" 1>&2
+# fi
+ host="$option"
+ else
+ echo "$progname: too many arguments" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi ;;
+ esac
+done
+
+if test -z "$ltmain"; then
+ echo "$progname: you must specify a LTMAIN file" 1>&2
+ echo "$help" 1>&2
+ exit 1
+fi
+
+if test ! -f "$ltmain"; then
+ echo "$progname: \`$ltmain' does not exist" 1>&2
+ echo "$help" 1>&2
+ exit 1
+fi
+
+# Quote any args containing shell metacharacters.
+ltconfig_args=
+for arg
+do
+ case "$arg" in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ltconfig_args="$ltconfig_args '$arg'" ;;
+ *) ltconfig_args="$ltconfig_args $arg" ;;
+ esac
+done
+
+# A relevant subset of AC_INIT.
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 5 compiler messages saved in config.log
+# 6 checking for... messages and results
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>>./config.log
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi
+if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi
+
+if test -n "$cache_file" && test -r "$cache_file"; then
+ echo "loading cache $cache_file within ltconfig"
+ . $cache_file
+fi
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+if test -z "$srcdir"; then
+ # Assume the source directory is the same one as the path to LTMAIN.
+ srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'`
+ test "$srcdir" = "$ltmain" && srcdir=.
+fi
+
+trap "$rm conftest*; exit 1" 1 2 15
+if test "$verify_host" = yes; then
+ # Check for config.guess and config.sub.
+ ac_aux_dir=
+ for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/config.guess; then
+ ac_aux_dir=$ac_dir
+ break
+ fi
+ done
+ if test -z "$ac_aux_dir"; then
+ echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi
+ ac_config_guess=$ac_aux_dir/config.guess
+ ac_config_sub=$ac_aux_dir/config.sub
+
+ # Make sure we can run config.sub.
+ if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then :
+ else
+ echo "$progname: cannot run $ac_config_sub" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi
+
+ echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+ host_alias=$host
+ case "$host_alias" in
+ "")
+ if host_alias=`$SHELL $ac_config_guess`; then :
+ else
+ echo "$progname: cannot guess host type; you must specify one" 1>&2
+ echo "$help" 1>&2
+ exit 1
+ fi ;;
+ esac
+ host=`$SHELL $ac_config_sub $host_alias`
+ echo "$ac_t$host" 1>&6
+
+ # Make sure the host verified.
+ test -z "$host" && exit 1
+
+elif test -z "$host"; then
+ echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
+ echo "$help" 1>&2
+ exit 1
+else
+ host_alias=$host
+fi
+
+# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
+case "$host_os" in
+linux-gnu*) ;;
+linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
+esac
+
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+case "$host_os" in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR cru $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+# Set a sane default for `AR'.
+test -z "$AR" && AR=ar
+
+# Set a sane default for `OBJDUMP'.
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+# If RANLIB is not set, then run the test.
+if test "${RANLIB+set}" != "set"; then
+ result=no
+
+ echo $ac_n "checking for ranlib... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then
+ RANLIB="ranlib"
+ result="ranlib"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ echo "$ac_t$result" 1>&6
+fi
+
+if test -n "$RANLIB"; then
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+ old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+fi
+
+# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin.
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$AS" && AS=as
+
+# Check to see if we are using GCC.
+if test "$with_gcc" != yes || test -z "$CC"; then
+ # If CC is not set, then try to find GCC or a usable CC.
+ if test -z "$CC"; then
+ echo $ac_n "checking for gcc... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then
+ CC="gcc"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+
+ if test -n "$CC"; then
+ echo "$ac_t$CC" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+ fi
+
+ # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
+ if test -z "$CC"; then
+ echo $ac_n "checking for cc... $ac_c" 1>&6
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ cc_rejected=no
+ for dir in $PATH; do
+ test -z "$dir" && dir=.
+ if test -f $dir/cc || test -f $dir/cc$ac_exeext; then
+ if test "$dir/cc" = "/usr/ucb/cc"; then
+ cc_rejected=yes
+ continue
+ fi
+ CC="cc"
+ break
+ fi
+ done
+ IFS="$save_ifs"
+ if test $cc_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same name, so the bogon will be chosen
+ # first if we set CC to just the name; use the full file name.
+ shift
+ set dummy "$dir/cc" "$@"
+ shift
+ CC="$@"
+ fi
+ fi
+
+ if test -n "$CC"; then
+ echo "$ac_t$CC" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+
+ if test -z "$CC"; then
+ echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
+ exit 1
+ fi
+ fi
+
+ # Now see if the compiler is really GCC.
+ with_gcc=no
+ echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
+ echo "$progname:581: checking whether we are using GNU C" >&5
+
+ $rm conftest.c
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+ if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ with_gcc=yes
+ fi
+ $rm conftest.c
+ echo "$ac_t$with_gcc" 1>&6
+fi
+
+# Allow CC to be a program name with arguments.
+set dummy $CC
+compiler="$2"
+
+echo $ac_n "checking for object suffix... $ac_c" 1>&6
+$rm conftest*
+echo 'int i = 1;' > conftest.c
+echo "$progname:603: checking for object suffix" >& 5
+if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then
+ # Append any warnings to the config.log.
+ cat conftest.err 1>&5
+
+ for ac_file in conftest.*; do
+ case $ac_file in
+ *.c) ;;
+ *) objext=`echo $ac_file | sed -e s/conftest.//` ;;
+ esac
+ done
+else
+ cat conftest.err 1>&5
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+fi
+$rm conftest*
+echo "$ac_t$objext" 1>&6
+
+echo $ac_n "checking for executable suffix... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_exeext="no"
+ $rm conftest*
+ echo 'main () { return 0; }' > conftest.c
+ echo "$progname:629: checking for executable suffix" >& 5
+ if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then
+ # Append any warnings to the config.log.
+ cat conftest.err 1>&5
+
+ for ac_file in conftest.*; do
+ case $ac_file in
+ *.c | *.err | *.$objext ) ;;
+ *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;;
+ esac
+ done
+ else
+ cat conftest.err 1>&5
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ $rm conftest*
+fi
+if test "X$ac_cv_exeext" = Xno; then
+ exeext=""
+else
+ exeext="$ac_cv_exeext"
+fi
+echo "$ac_t$ac_cv_exeext" 1>&6
+
+echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
+pic_flag=
+special_shlib_compile_flags=
+wl=
+link_static_flag=
+no_builtin_flag=
+
+if test "$with_gcc" = yes; then
+ wl='-Wl,'
+ link_static_flag='-static'
+
+ case "$host_os" in
+ beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ aix*)
+ # Below there is a dirty hack to force normal static linking with -ldl
+ # The problem is because libdl dynamically linked with both libc and
+ # libC (AIX C++ library), which obviously doesn't included in libraries
+ # list by gcc. This cause undefined symbols with -static flags.
+ # This hack allows C programs to be linked with "-static -ldl", but
+ # we not sure about C++ programs.
+ link_static_flag="$link_static_flag ${wl}-lC"
+ ;;
+ cygwin* | mingw* | os2*)
+ # We can build DLLs from non-PIC.
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ pic_flag='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ pic_flag=-Kconform_pic
+ fi
+ ;;
+ *)
+ pic_flag='-fPIC'
+ ;;
+ esac
+else
+ # PORTME Check for PIC flags for the system compiler.
+ case "$host_os" in
+ aix3* | aix4*)
+ # All AIX code is PIC.
+ link_static_flag='-bnso -bI:/lib/syscalls.exp'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ # Is there a better link_static_flag that works with the bundled CC?
+ wl='-Wl,'
+ link_static_flag="${wl}-a ${wl}archive"
+ pic_flag='+Z'
+ ;;
+
+ irix5* | irix6*)
+ wl='-Wl,'
+ link_static_flag='-non_shared'
+ # PIC (with -KPIC) is the default.
+ ;;
+
+ cygwin* | mingw* | os2*)
+ # We can build DLLs from non-PIC.
+ ;;
+
+ osf3* | osf4* | osf5*)
+ # All OSF/1 code is PIC.
+ wl='-Wl,'
+ link_static_flag='-non_shared'
+ ;;
+
+ sco3.2v5*)
+ pic_flag='-Kpic'
+ link_static_flag='-dn'
+ special_shlib_compile_flags='-belf'
+ ;;
+
+ solaris*)
+ pic_flag='-KPIC'
+ link_static_flag='-Bstatic'
+ wl='-Wl,'
+ ;;
+
+ sunos4*)
+ pic_flag='-PIC'
+ link_static_flag='-Bstatic'
+ wl='-Qoption ld '
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ pic_flag='-KPIC'
+ link_static_flag='-Bstatic'
+ wl='-Wl,'
+ ;;
+
+ uts4*)
+ pic_flag='-pic'
+ link_static_flag='-Bstatic'
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ pic_flag='-Kconform_pic'
+ link_static_flag='-Bstatic'
+ fi
+ ;;
+ *)
+ can_build_shared=no
+ ;;
+ esac
+fi
+
+if test -n "$pic_flag"; then
+ echo "$ac_t$pic_flag" 1>&6
+
+ # Check to make sure the pic_flag actually works.
+ echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
+ $rm conftest*
+ echo "int some_variable = 0;" > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $pic_flag -DPIC"
+ echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5
+ if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
+ # Append any warnings to the config.log.
+ cat conftest.err 1>&5
+
+ case "$host_os" in
+ hpux9* | hpux10* | hpux11*)
+ # On HP-UX, both CC and GCC only warn that PIC is supported... then they
+ # create non-PIC objects. So, if there were any warnings, we assume that
+ # PIC is not supported.
+ if test -s conftest.err; then
+ echo "$ac_t"no 1>&6
+ can_build_shared=no
+ pic_flag=
+ else
+ echo "$ac_t"yes 1>&6
+ pic_flag=" $pic_flag"
+ fi
+ ;;
+ *)
+ echo "$ac_t"yes 1>&6
+ pic_flag=" $pic_flag"
+ ;;
+ esac
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ can_build_shared=no
+ pic_flag=
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+else
+ echo "$ac_t"none 1>&6
+fi
+
+# Check to see if options -o and -c are simultaneously supported by compiler
+echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6
+$rm -r conftest 2>/dev/null
+mkdir conftest
+cd conftest
+$rm conftest*
+echo "int some_variable = 0;" > conftest.c
+mkdir out
+# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
+# that will create temporary files in the current directory regardless of
+# the output directory. Thus, making CWD read-only will cause this test
+# to fail, enabling locking or at least warning the user not to do parallel
+# builds.
+chmod -w .
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -o out/conftest2.o"
+echo "$progname:829: checking if $compiler supports -c -o file.o" >&5
+if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then
+
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s out/conftest.err; then
+ echo "$ac_t"no 1>&6
+ compiler_c_o=no
+ else
+ echo "$ac_t"yes 1>&6
+ compiler_c_o=yes
+ fi
+else
+ # Append any errors to the config.log.
+ cat out/conftest.err 1>&5
+ compiler_c_o=no
+ echo "$ac_t"no 1>&6
+fi
+CFLAGS="$save_CFLAGS"
+chmod u+w .
+$rm conftest* out/*
+rmdir out
+cd ..
+rmdir conftest
+$rm -r conftest 2>/dev/null
+
+if test x"$compiler_c_o" = x"yes"; then
+ # Check to see if we can write to a .lo
+ echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6
+ $rm conftest*
+ echo "int some_variable = 0;" > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -c -o conftest.lo"
+ echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5
+if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then
+
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ echo "$ac_t"no 1>&6
+ compiler_o_lo=no
+ else
+ echo "$ac_t"yes 1>&6
+ compiler_o_lo=yes
+ fi
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ compiler_o_lo=no
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+else
+ compiler_o_lo=no
+fi
+
+# Check to see if we can do hard links to lock some files if needed
+hard_links="nottested"
+if test "$compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ echo "$ac_t$hard_links" 1>&6
+ $rm conftest*
+ if test "$hard_links" = no; then
+ echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+if test "$with_gcc" = yes; then
+ # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+ echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6
+ $rm conftest*
+ echo "int some_variable = 0;" > conftest.c
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c"
+ echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+ if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
+
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ echo "$ac_t"no 1>&6
+ compiler_rtti_exceptions=no
+ else
+ echo "$ac_t"yes 1>&6
+ compiler_rtti_exceptions=yes
+ fi
+ else
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ compiler_rtti_exceptions=no
+ echo "$ac_t"no 1>&6
+ fi
+ CFLAGS="$save_CFLAGS"
+ $rm conftest*
+
+ if test "$compiler_rtti_exceptions" = "yes"; then
+ no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
+ else
+ no_builtin_flag=' -fno-builtin'
+ fi
+
+fi
+
+# Check for any special shared library compilation flags.
+if test -n "$special_shlib_compile_flags"; then
+ echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
+ if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then :
+ else
+ echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
+ can_build_shared=no
+ fi
+fi
+
+echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
+$rm conftest*
+echo 'main(){return(0);}' > conftest.c
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS $link_static_flag"
+echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5
+if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ echo "$ac_t$link_static_flag" 1>&6
+else
+ echo "$ac_t"none 1>&6
+ link_static_flag=
+fi
+LDFLAGS="$save_LDFLAGS"
+$rm conftest*
+
+if test -z "$LN_S"; then
+ # Check to see if we can use ln -s, or we need hard links.
+ echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
+ $rm conftest.dat
+ if ln -s X conftest.dat 2>/dev/null; then
+ $rm conftest.dat
+ LN_S="ln -s"
+ else
+ LN_S=ln
+ fi
+ if test "$LN_S" = "ln -s"; then
+ echo "$ac_t"yes 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+fi
+
+# Make sure LD is an absolute path.
+if test -z "$LD"; then
+ ac_prog=ld
+ if test "$with_gcc" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
+ echo "$progname:991: checking for ld used by GCC" >&5
+ ac_prog=`($CC -print-prog-name=ld) 2>&5`
+ case "$ac_prog" in
+ # Accept absolute paths.
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we are not using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+ elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld... $ac_c" 1>&6
+ echo "$progname:1015: checking for GNU ld" >&5
+ else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+ echo "$progname:1018: checking for non-GNU ld" >&5
+ fi
+
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ fi
+
+ if test -n "$LD"; then
+ echo "$ac_t$LD" 1>&6
+ else
+ echo "$ac_t"no 1>&6
+ fi
+
+ if test -z "$LD"; then
+ echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
+ exit 1
+ fi
+fi
+
+# Check to see if it really is or is not GNU ld.
+echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
+# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+echo "$ac_t$with_gnu_ld" 1>&6
+
+# See if the linker supports building shared libraries.
+echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
+
+allow_undefined_flag=
+no_undefined_flag=
+need_lib_prefix=unknown
+need_version=unknown
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+archive_cmds=
+archive_expsym_cmds=
+old_archive_from_new_cmds=
+export_dynamic_flag_spec=
+whole_archive_flag_spec=
+thread_safe_flag_spec=
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+hardcode_shlibpath_var=unsupported
+runpath_var=
+always_export_symbols=no
+export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
+# include_expsyms should be a list of space-separated symbols to be *always*
+# included in the symbol list
+include_expsyms=
+# exclude_expsyms can be an egrep regular expression of symbols to exclude
+# it will be wrapped by ` (' and `)$', so one must not match beginning or
+# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+# as well as any symbol that contains `d'.
+exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
+# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+# platforms (ab)use it in PIC code, but their linkers get confused if
+# the symbol is explicitly referenced. Since portable code cannot
+# rely on this symbol name, it's probably fine to never include it in
+# preloaded symbol tables.
+
+case "$host_os" in
+cygwin* | mingw*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$with_gcc" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # See if GNU ld supports shared libraries.
+ case "$host_os" in
+ aix3* | aix4*)
+ # On AIX, the GNU linker is very broken
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can use
+ # them.
+ ld_shlibs=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw*)
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+
+ # Extract the symbol export list from an `--export-all' def file,
+ # then regenerate the def file from the symbol export list, so that
+ # the compiled dll only exports the symbol export list.
+ # Be careful not to strip the DATA tag left by newer dlltools.
+ export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
+ test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
+ $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~
+ sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $objdir/$soname-def > $export_symbols'
+
+ # If DATA tags from a recent dlltool are present, honour them!
+ archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~
+ _lt_hint=1;
+ cat $export_symbols | while read symbol; do
+ set dummy \$symbol;
+ case \$# in
+ 2) echo " \$2 @ \$_lt_hint ; " >> $objdir/$soname-def;;
+ *) echo " \$2 @ \$_lt_hint \$3 ; " >> $objdir/$soname-def;;
+ esac;
+ _lt_hint=`expr 1 + \$_lt_hint`;
+ done~
+ test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
+ test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
+ $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
+ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
+ $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
+ $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
+ $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts'
+
+ old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a'
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib'
+ # can we support soname and/or expsyms with a.out? -oliva
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris* | sysv5*)
+ if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = yes; then
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ case $host_os in
+ cygwin* | mingw*)
+ # dlltool doesn't understand --whole-archive et. al.
+ whole_archive_flag_spec=
+ ;;
+ *)
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ ;;
+ esac
+ fi
+else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case "$host_os" in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$with_gcc" = yes && test -z "$link_static_flag"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix4*)
+ hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib'
+ hardcode_libdir_separator=':'
+ if test "$with_gcc" = yes; then
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ hardcode_direct=yes
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ shared_flag='-shared'
+ else
+ shared_flag='${wl}-bM:SRE'
+ hardcode_direct=yes
+ fi
+ allow_undefined_flag=' ${wl}-berok'
+ archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
+ archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
+ case "$host_os" in aix4.[01]|aix4.[01].*)
+ # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
+ always_export_symbols=yes ;;
+ esac
+ ;;
+
+ amigaos*)
+ archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+
+ cygwin* | mingw*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_from_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib /OUT:$oldlib$oldobjs'
+ fix_srcfile_path='`cygpath -w $srcfile`'
+ ;;
+
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd*)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ case "$host_os" in
+ hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;;
+ *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;;
+ esac
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ hardcode_minus_L=yes # Not in the search PATH, but as the default
+ # location of the library.
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ irix5* | irix6*)
+ if test "$with_gcc" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+ else
+ archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF
+ fi
+ hardcode_libdir_flag_spec='${wl}-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ openbsd*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def'
+ old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$with_gcc" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # As osf3* with the addition of the -msym flag
+ if test "$with_gcc" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ rhapsody*)
+ archive_cmds='$CC -bundle -undefined suppress -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flags_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sco3.2v5*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z text'
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case "$host_os" in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $linkopts'
+ else
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ fi
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv5*)
+ no_undefined_flag=' -z text'
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
+ archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
+ hardcode_libdir_flag_spec=
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4.2uw2*)
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts'
+ hardcode_direct=yes
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=no
+ hardcode_runpath_var=yes
+ runpath_var=LD_RUN_PATH
+ ;;
+
+ unixware7*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+fi
+echo "$ac_t$ld_shlibs" 1>&6
+test "$ld_shlibs" = no && can_build_shared=no
+
+if test -z "$NM"; then
+ echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
+ case "$NM" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path.
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
+ for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ NM="$ac_dir/nm -B"
+ break
+ elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+ NM="$ac_dir/nm -p"
+ break
+ else
+ NM=${NM="$ac_dir/nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$NM" && NM=nm
+ ;;
+ esac
+ echo "$ac_t$NM" 1>&6
+fi
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
+
+# Define system-specific variables.
+case "$host_os" in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
+ ;;
+irix*)
+ symcode='[BCDEGRST]'
+ ;;
+solaris*)
+ symcode='[BDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
+ symcode='[ABCDGISTW]'
+fi
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Write the raw and C identifiers.
+ global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+ $rm conftest*
+ cat > conftest.c <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ echo "$progname:1653: checking if global_symbol_pipe works" >&5
+ if { (eval echo $progname:1654: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { echo "$progname:1657: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
+
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if egrep ' nm_test_var$' "$nlist" >/dev/null; then
+ if egrep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c'
+
+ cat <<EOF >> conftest.c
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{
+EOF
+ sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c
+ cat <<\EOF >> conftest.c
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$objext conftstm.$objext
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$objext"
+ CFLAGS="$CFLAGS$no_builtin_flag"
+ if { (eval echo $progname:1709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ pipe_works=yes
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ LIBS="$save_LIBS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.c >&5
+ fi
+ $rm conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ global_symbol_pipe=
+ fi
+done
+if test "$pipe_works" = yes; then
+ echo "${ac_t}ok" 1>&6
+else
+ echo "${ac_t}failed" 1>&6
+fi
+
+if test -z "$global_symbol_pipe"; then
+ global_symbol_to_cdecl=
+fi
+
+# Check hardcoding attributes.
+echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var"; then
+
+ # We can hardcode non-existant directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$hardcode_shlibpath_var" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+echo "$ac_t$hardcode_action" 1>&6
+
+
+reload_flag=
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
+# PORTME Some linkers may need a different reload flag.
+reload_flag='-r'
+echo "$ac_t$reload_flag" 1>&6
+test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+# PORTME Fill in your ld.so characteristics
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+file_magic_cmd=
+file_magic_test_file=
+deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [regex]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given egrep regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
+case "$host_os" in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}.so$major'
+ ;;
+
+aix4*)
+ version_type=linux
+ # AIX has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ # We preserve .a as extension for shared libraries though AIX4.2
+ # and later linker supports .so
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a'
+ shlibpath_var=LIBPATH
+ deplibs_check_method=pass_all
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}.so'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ deplibs_check_method=pass_all
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+bsdi4*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/shlib/libc.so
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ export_dynamic_flag_spec=-rdynamic
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw*)
+ version_type=windows
+ need_version=no
+ need_lib_prefix=no
+ if test "$with_gcc" = yes; then
+ library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a'
+ else
+ library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
+ fi
+ dynamic_linker='Win32 ld.exe'
+ deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ file_magic_cmd='${OBJDUMP} -f'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+ case "$version_type" in
+ freebsd-elf*)
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=`echo /usr/lib/libc.so*`
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ deplibs_check_method=unknown
+ library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case "$host_os" in
+ freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ *) # from 3.2 on
+ shlibpath_overrides_runpath=no
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ dynamic_linker="$host_os dld.sl"
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
+ soname_spec='${libname}${release}.sl$major'
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ case "$host_os" in
+ hpux10.20*)
+ # TODO: Does this work for hpux-11 too?
+ deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+irix5* | irix6*)
+ version_type=irix
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}.so.$major'
+ library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so'
+ case "$host_os" in
+ irix5*)
+ libsuff= shlibsuff=
+ # this will be overridden with pass_all, but let us keep it just in case
+ deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
+ ;;
+ *)
+ case "$LD" in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=`echo /lib${libsuff}/libc.so*`
+ deplibs_check_method='pass_all'
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux-gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ deplibs_check_method=pass_all
+
+ if test -f /lib/ld.so.1; then
+ dynamic_linker='GNU ld.so'
+ else
+ # Only the GNU ld.so supports shared libraries on MkLinux.
+ case "$host_cpu" in
+ powerpc*) dynamic_linker=no ;;
+ *) dynamic_linker='Linux ld.so' ;;
+ esac
+ fi
+ ;;
+
+netbsd*)
+ version_type=sunos
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
+ soname_spec='${libname}${release}.so$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+openbsd*)
+ version_type=sunos
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ need_version=no
+ fi
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+os2*)
+ libname_spec='$name'
+ need_lib_prefix=no
+ library_names_spec='$libname.dll $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_version=no
+ soname_spec='${libname}${release}.so'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ # this will be overridden with pass_all, but let us keep it just in case
+ deplibs_check_method='file_magic COFF format alpha shared library'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/shlib/libc.so
+ deplibs_check_method='pass_all'
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+rhapsody*)
+ version_type=sunos
+ library_names_spec='${libname}.so'
+ soname_spec='${libname}.so'
+ shlibpath_var=DYLD_LIBRARY_PATH
+ deplibs_check_method=pass_all
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='${libname}${release}.so$major'
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib"
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=/lib/libc.so
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case "$host_vendor" in
+ sequent)
+ file_magic_cmd='/bin/file'
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ ncr)
+ deplibs_check_method='pass_all'
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ file_magic_cmd=/usr/bin/file
+ file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ esac
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
+ soname_spec='${libname}${release}.so$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
+ soname_spec='$libname.so.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+echo "$ac_t$dynamic_linker" 1>&6
+test "$dynamic_linker" = no && can_build_shared=no
+
+# Report the final consequences.
+echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
+
+# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in
+# configure.in, otherwise build static only libraries.
+case "$host_os" in
+cygwin* | mingw* | os2*)
+ if test x$can_build_shared = xyes; then
+ test x$enable_win32_dll = xno && can_build_shared=no
+ echo "checking if package supports dlls... $can_build_shared" 1>&6
+ fi
+;;
+esac
+
+if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then
+ case "$deplibs_check_method" in
+ "file_magic "*)
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ egrep "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+fi
+
+echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4*)
+ test "$enable_shared" = yes && enable_static=no
+ ;;
+esac
+
+echo "$ac_t$enable_shared" 1>&6
+
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+
+echo "checking whether to build static libraries... $enable_static" 1>&6
+
+if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+echo $ac_n "checking for objdir... $ac_c" 1>&6
+rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+echo "$ac_t$objdir" 1>&6
+
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then
+ lt_cv_dlopen=no lt_cv_dlopen_libs=
+echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "$progname:2248: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2256 "ltconfig"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo $progname:2269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dlopen""... $ac_c" 1>&6
+echo "$progname:2288: checking for dlopen" >&5
+if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2293 "ltconfig"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_dlopen) || defined (__stub___dlopen)
+choke me
+#else
+dlopen();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo $progname:2318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_dlopen=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_dlopen=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="dlopen"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
+echo "$progname:2335: checking for dld_link in -ldld" >&5
+ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldld $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2343 "ltconfig"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link();
+
+int main() {
+dld_link()
+; return 0; }
+EOF
+if { (eval echo $progname:2356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load""... $ac_c" 1>&6
+echo "$progname:2375: checking for shl_load" >&5
+if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2380 "ltconfig"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_shl_load) || defined (__stub___shl_load)
+choke me
+#else
+shl_load();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo $progname:2405: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_shl_load=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_shl_load=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="shl_load"
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
+echo "$progname:2423: checking for shl_load in -ldld" >&5
+ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldld $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2431 "ltconfig"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load();
+
+int main() {
+shl_load()
+; return 0; }
+EOF
+if { (eval echo $progname:2445: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+fi
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ fi
+
+ case "$lt_cv_dlopen" in
+ dlopen)
+for ac_hdr in dlfcn.h; do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "$progname:2488: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2493 "ltconfig"
+#include <$ac_hdr>
+int fnord = 0;
+EOF
+ac_try="$ac_compile >/dev/null 2>conftest.out"
+{ (eval echo $progname:2498: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ if test "x$ac_cv_header_dlfcn_h" = xyes; then
+ CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+ fi
+ eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
+echo "$progname:2526: checking whether a program can dlopen itself" >&5
+if test "${lt_cv_dlopen_self+set}" = set; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ lt_cv_dlopen_self=cross
+ else
+ cat > conftest.c <<EOF
+#line 2534 "ltconfig"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LTDL_GLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LTDL_GLOBAL DL_GLOBAL
+# else
+# define LTDL_GLOBAL 0
+# endif
+#endif
+
+/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LTDL_LAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LTDL_LAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LTDL_LAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LTDL_LAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LTDL_LAZY_OR_NOW DL_NOW
+# else
+# define LTDL_LAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+fnord() { int i=42;}
+main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
+ if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
+ if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); }
+
+EOF
+if { (eval echo $progname:2580: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ lt_cv_dlopen_self=yes
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ lt_cv_dlopen_self=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self" 1>&6
+
+ if test "$lt_cv_dlopen_self" = yes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+ echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
+echo "$progname:2599: checking whether a statically linked program can dlopen itself" >&5
+if test "${lt_cv_dlopen_self_static+set}" = set; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ lt_cv_dlopen_self_static=cross
+ else
+ cat > conftest.c <<EOF
+#line 2607 "ltconfig"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LTDL_GLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LTDL_GLOBAL DL_GLOBAL
+# else
+# define LTDL_GLOBAL 0
+# endif
+#endif
+
+/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LTDL_LAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LTDL_LAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LTDL_LAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LTDL_LAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LTDL_LAZY_OR_NOW DL_NOW
+# else
+# define LTDL_LAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+fnord() { int i=42;}
+main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
+ if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
+ if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); }
+
+EOF
+if { (eval echo $progname:2653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ lt_cv_dlopen_self_static=yes
+else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ lt_cv_dlopen_self_static=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
+fi
+ ;;
+ esac
+
+ case "$lt_cv_dlopen_self" in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case "$lt_cv_dlopen_self_static" in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+# Copy echo and quote the copy, instead of the original, because it is
+# used later.
+ltecho="$echo"
+if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then
+ ltecho="$CONFIG_SHELL \$0 --fallback-echo"
+fi
+LTSHELL="$SHELL"
+
+LTCONFIG_VERSION="$VERSION"
+
+# Only quote variables if we're using ltmain.sh.
+case "$ltmain" in
+*.sh)
+ # Now quote all the things that may contain metacharacters.
+ for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \
+ old_LD old_LDFLAGS old_LIBS \
+ old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \
+ AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \
+ reload_flag reload_cmds wl \
+ pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
+ thread_safe_flag_spec whole_archive_flag_spec libname_spec \
+ library_names_spec soname_spec \
+ RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
+ old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \
+ file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \
+ finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
+ hardcode_libdir_flag_spec hardcode_libdir_separator \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
+
+ case "$var" in
+ reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case "$ltecho" in
+ *'\$0 --fallback-echo"')
+ ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
+ ;;
+ esac
+
+ trap "$rm \"$ofile\"; exit 1" 1 2 15
+ echo "creating $ofile"
+ $rm "$ofile"
+ cat <<EOF > "$ofile"
+#! $SHELL
+
+# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="sed -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+### BEGIN LIBTOOL CONFIG
+EOF
+ cfgfile="$ofile"
+ ;;
+
+*)
+ # Double-quote the variables that need it (for aesthetics).
+ for var in old_CC old_CFLAGS old_CPPFLAGS \
+ old_LD old_LDFLAGS old_LIBS \
+ old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do
+ eval "$var=\\\"\$var\\\""
+ done
+
+ # Just create a config file.
+ cfgfile="$ofile.cfg"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ echo "creating $cfgfile"
+ $rm "$cfgfile"
+ cat <<EOF > "$cfgfile"
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+EOF
+ ;;
+esac
+
+cat <<EOF >> "$cfgfile"
+# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\
+# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\
+# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\
+# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\
+# $0$ltconfig_args
+#
+# Compiler and other test output produced by $progname, useful for
+# debugging $progname, is in ./config.log if it exists.
+
+# The version of $progname that generated this script.
+LTCONFIG_VERSION=$LTCONFIG_VERSION
+
+# Shell to use when invoking shell scripts.
+SHELL=$LTSHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$ltecho
+
+# The archiver.
+AR=$AR
+
+# The default C compiler.
+CC=$CC
+
+# The linker used to build libraries.
+LD=$LD
+
+# Whether we need hard or soft links.
+LN_S=$LN_S
+
+# A BSD-compatible nm program.
+NM=$NM
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$reload_flag
+reload_cmds=$reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$wl
+
+# Object file suffix (normally "o").
+objext="$objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$pic_flag
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$compiler_c_o
+
+# Can we write directly to a .lo ?
+compiler_o_lo=$compiler_o_lo
+
+# Must we lock files when doing compilation ?
+need_locks=$need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$link_static_flag
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$no_builtin_flag
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$whole_archive_flag_spec
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$thread_safe_flag_spec
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$RANLIB
+old_archive_cmds=$old_archive_cmds
+old_postinstall_cmds=$old_postinstall_cmds
+old_postuninstall_cmds=$old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$old_archive_from_new_cmds
+
+# Commands used to build and install a shared archive.
+archive_cmds=$archive_cmds
+archive_expsym_cmds=$archive_expsym_cmds
+postinstall_cmds=$postinstall_cmds
+postuninstall_cmds=$postuninstall_cmds
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$allow_undefined_flag
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$no_undefined_flag
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$global_symbol_to_cdecl
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$hardcode_libdir_separator
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$fix_srcfile_path"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$include_expsyms
+
+EOF
+
+case "$ltmain" in
+*.sh)
+ echo '### END LIBTOOL CONFIG' >> "$ofile"
+ echo >> "$ofile"
+ case "$host_os" in
+ aix3*)
+ cat <<\EOF >> "$ofile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # Append the ltmain.sh script.
+ sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1)
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+
+ chmod +x "$ofile"
+ ;;
+
+*)
+ # Compile the libtool program.
+ echo "FIXME: would compile $ltmain"
+ ;;
+esac
+
+test -n "$cache_file" || exit 0
+
+# AC_CACHE_SAVE
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/contrib/idn/idnkit-1.0-src/ltmain.sh b/contrib/idn/idnkit-1.0-src/ltmain.sh
new file mode 100644
index 0000000..766732d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/ltmain.sh
@@ -0,0 +1,4024 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun ltconfig.
+#
+# Copyright (C) 1996-1999 Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$0" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit 0
+fi
+
+# The name of this program.
+progname=`$echo "$0" | sed 's%^.*/%%'`
+modename="$progname"
+
+# Constants.
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.3.5
+TIMESTAMP=" (1.385.2.206 2000/05/27 11:12:27)"
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+SP2NL='tr \040 \012'
+NL2SP='tr \015\012 \040\040'
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+ save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+ save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+if test "$LTCONFIG_VERSION" != "$VERSION"; then
+ echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ echo "$modename: not configured to build any kind of library" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+# Parse our command line options once, thoroughly.
+while test $# -gt 0
+do
+ arg="$1"
+ shift
+
+ case "$arg" in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ execute_dlfiles)
+ eval "$prev=\"\$$prev \$arg\""
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case "$arg" in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+ exit 0
+ ;;
+
+ --config)
+ sed -e '1,/^### BEGIN LIBTOOL CONFIG/d' -e '/^### END LIBTOOL CONFIG/,$d' $0
+ exit 0
+ ;;
+
+ --debug)
+ echo "$progname: enabling shell trace mode"
+ set -x
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ echo "enable shared libraries"
+ else
+ echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ echo "enable static libraries"
+ else
+ echo "disable static libraries"
+ fi
+ exit 0
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --quiet | --silent)
+ show=:
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+fi
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ case "$nonopt" in
+ *cc | *++ | gcc* | *-gcc*)
+ mode=link
+ for arg
+ do
+ case "$arg" in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case "$mode" in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ lastarg=
+ srcfile="$nonopt"
+ suppress_output=
+
+ user_target=no
+ for arg
+ do
+ # Accept any command-line options.
+ case "$arg" in
+ -o)
+ if test "$user_target" != "no"; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit 1
+ fi
+ user_target=next
+ ;;
+
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+ esac
+
+ case "$user_target" in
+ next)
+ # The next one is the -o target name
+ user_target=yes
+ continue
+ ;;
+ yes)
+ # We got the output file
+ user_target=set
+ libobj="$arg"
+ continue
+ ;;
+ esac
+
+ # Accept the current argument as the source file.
+ lastarg="$srcfile"
+ srcfile="$arg"
+
+ # Aesthetically quote the previous argument.
+
+ # Backslashify any backslashes, double quotes, and dollar signs.
+ # These are the only characters that are still specially
+ # interpreted inside of double-quoted scrings.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly in scan
+ # sets, so we specify it separately.
+ case "$lastarg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ # Add the previous argument to base_compile.
+ if test -z "$base_compile"; then
+ base_compile="$lastarg"
+ else
+ base_compile="$base_compile $lastarg"
+ fi
+ done
+
+ case "$user_target" in
+ set)
+ ;;
+ no)
+ # Get the name of the library object.
+ libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ *)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSfmso]'
+ case "$libobj" in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case "$libobj" in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $libobj"
+ else
+ removelist="$libobj"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit 1" 1 2 15
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\..*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit 1" 1 2 15
+ else
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until ln "$0" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+ echo $srcfile > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ # All platforms use -DPIC, to notify preprocessed assembler code.
+ command="$base_compile $srcfile $pic_flag -DPIC"
+ if test "$build_old_libs" = yes; then
+ lo_libobj="$libobj"
+ dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$libobj"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+ libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+
+ if test -d "$dir"; then
+ $show "$rm $libobj"
+ $run $rm $libobj
+ else
+ $show "$mkdir $dir"
+ $run $mkdir $dir
+ status=$?
+ if test $status -ne 0 && test ! -d $dir; then
+ exit $status
+ fi
+ fi
+ fi
+ if test "$compiler_o_lo" = yes; then
+ output_obj="$libobj"
+ command="$command -o $output_obj"
+ elif test "$compiler_c_o" = yes; then
+ output_obj="$obj"
+ command="$command -o $output_obj"
+ fi
+
+ $run $rm "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit 1
+ fi
+
+ if test "$need_locks" = warn &&
+ test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+ echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test x"$output_obj" != x"$libobj"; then
+ $show "$mv $output_obj $libobj"
+ if $run $mv $output_obj $libobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # If we have no pic_flag, then copy the object into place and finish.
+ if test -z "$pic_flag" && test "$build_old_libs" = yes; then
+ # Rename the .lo from within objdir to obj
+ if test -f $obj; then
+ $show $rm $obj
+ $run $rm $obj
+ fi
+
+ $show "$mv $libobj $obj"
+ if $run $mv $libobj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"`
+ libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
+ # Now arrange that obj and lo_libobj become the same file
+ $show "(cd $xdir && $LN_S $baseobj $libobj)"
+ if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then
+ exit 0
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Allow error messages only from the first compilation.
+ suppress_output=' >/dev/null 2>&1'
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ command="$base_compile $srcfile"
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ output_obj="$obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $run $rm "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit 1
+ fi
+
+ if test "$need_locks" = warn &&
+ test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then
+ echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit 1
+ fi
+
+ # Just move the object if needed
+ if test x"$output_obj" != x"$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we do not
+ # accidentally link it into a program.
+ if test "$build_libtool_libs" != yes; then
+ $show "echo timestamp > $libobj"
+ $run eval "echo timestamp > \$libobj" || exit $?
+ else
+ # Move the .lo from within objdir
+ $show "$mv $libobj $lo_libobj"
+ if $run $mv $libobj $lo_libobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+ fi
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $rm "$lockfile"
+ fi
+
+ exit 0
+ ;;
+
+ # libtool link mode
+ link)
+ modename="$modename: link"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invokation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+
+ # This is a source program that is used to create dlls on Windows
+ # Don't remove nor modify the starting and closing comments
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# # ifdef __CYGWIN32__
+# # define __CYGWIN__ __CYGWIN32__
+# # endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+# __hDllInstance_base = hInst;
+# return TRUE;
+# }
+# /* ltdll.c ends here */
+ # This is a source program that is used to create import libraries
+ # on Windows for dlls which lack them. Don't remove nor modify the
+ # starting and closing comments
+# /* impgen.c starts here */
+# /* Copyright (C) 1999 Free Software Foundation, Inc.
+#
+# This file is part of GNU libtool.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# */
+#
+# #include <stdio.h> /* for printf() */
+# #include <unistd.h> /* for open(), lseek(), read() */
+# #include <fcntl.h> /* for O_RDONLY, O_BINARY */
+# #include <string.h> /* for strdup() */
+#
+# static unsigned int
+# pe_get16 (fd, offset)
+# int fd;
+# int offset;
+# {
+# unsigned char b[2];
+# lseek (fd, offset, SEEK_SET);
+# read (fd, b, 2);
+# return b[0] + (b[1]<<8);
+# }
+#
+# static unsigned int
+# pe_get32 (fd, offset)
+# int fd;
+# int offset;
+# {
+# unsigned char b[4];
+# lseek (fd, offset, SEEK_SET);
+# read (fd, b, 4);
+# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# static unsigned int
+# pe_as32 (ptr)
+# void *ptr;
+# {
+# unsigned char *b = ptr;
+# return b[0] + (b[1]<<8) + (b[2]<<16) + (b[3]<<24);
+# }
+#
+# int
+# main (argc, argv)
+# int argc;
+# char *argv[];
+# {
+# int dll;
+# unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+# unsigned long export_rva, export_size, nsections, secptr, expptr;
+# unsigned long name_rvas, nexp;
+# unsigned char *expdata, *erva;
+# char *filename, *dll_name;
+#
+# filename = argv[1];
+#
+# dll = open(filename, O_RDONLY|O_BINARY);
+# if (!dll)
+# return 1;
+#
+# dll_name = filename;
+#
+# for (i=0; filename[i]; i++)
+# if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':')
+# dll_name = filename + i +1;
+#
+# pe_header_offset = pe_get32 (dll, 0x3c);
+# opthdr_ofs = pe_header_offset + 4 + 20;
+# num_entries = pe_get32 (dll, opthdr_ofs + 92);
+#
+# if (num_entries < 1) /* no exports */
+# return 1;
+#
+# export_rva = pe_get32 (dll, opthdr_ofs + 96);
+# export_size = pe_get32 (dll, opthdr_ofs + 100);
+# nsections = pe_get16 (dll, pe_header_offset + 4 +2);
+# secptr = (pe_header_offset + 4 + 20 +
+# pe_get16 (dll, pe_header_offset + 4 + 16));
+#
+# expptr = 0;
+# for (i = 0; i < nsections; i++)
+# {
+# char sname[8];
+# unsigned long secptr1 = secptr + 40 * i;
+# unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+# unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+# unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+# lseek(dll, secptr1, SEEK_SET);
+# read(dll, sname, 8);
+# if (vaddr <= export_rva && vaddr+vsize > export_rva)
+# {
+# expptr = fptr + (export_rva - vaddr);
+# if (export_rva + export_size > vaddr + vsize)
+# export_size = vsize - (export_rva - vaddr);
+# break;
+# }
+# }
+#
+# expdata = (unsigned char*)malloc(export_size);
+# lseek (dll, expptr, SEEK_SET);
+# read (dll, expdata, export_size);
+# erva = expdata - export_rva;
+#
+# nexp = pe_as32 (expdata+24);
+# name_rvas = pe_as32 (expdata+32);
+#
+# printf ("EXPORTS\n");
+# for (i = 0; i<nexp; i++)
+# {
+# unsigned long name_rva = pe_as32 (erva+name_rvas+i*4);
+# printf ("\t%s @ %ld ;\n", erva+name_rva, 1+ i);
+# }
+#
+# return 0;
+# }
+# /* impgen.c ends here */
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ compile_command="$nonopt"
+ finalize_command="$nonopt"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ linkopts=
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval lib_search_path=\`\$echo \"X \${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ lib_search_path=
+ fi
+ # now prepend the system-specific ones
+ eval lib_search_path=\"$sys_lib_search_path_spec\$lib_search_path\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ link_against_libtool_libs=
+ ltlibs=
+ module=no
+ objs=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case "$arg" in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static"; then
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ else
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ prefer_static_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test $# -gt 0; do
+ arg="$1"
+ shift
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case "$prev" in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case "$prev" in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case "$arg" in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit 1
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case "$arg" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit 1
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi
+
+ prevarg="$arg"
+
+ case "$arg" in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: not more than one -exported-symbols argument allowed"
+ exit 1
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ absdir="$dir"
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case " $deplibs " in
+ *" $arg "*) ;;
+ *) deplibs="$deplibs $arg";;
+ esac
+ case " $lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir";;
+ esac
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
+ case ":$dllsearchpath:" in
+ ::) dllsearchpath="$dllsearchdir";;
+ *":$dllsearchdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dllsearchdir";;
+ esac
+ ;;
+ esac
+ ;;
+
+ -l*)
+ if test "$arg" = "-lc"; then
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
+ # These systems don't actually have c library (as such)
+ continue
+ ;;
+ esac
+ elif test "$arg" = "-lm"; then
+ case "$host" in
+ *-*-cygwin* | *-*-beos*)
+ # These systems don't actually have math library (as such)
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit 1
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static)
+ # If we have no pic_flag, then this is the same as -all-static.
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.o | *.obj | *.a | *.lib)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A library object.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test "$build_libtool_libs" = yes && test "$dlopen" = yes; then
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"`
+ prev=
+ fi
+ libobjs="$libobjs $arg"
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ dlname=
+ libdir=
+ library_names=
+ old_library=
+
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $arg | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2
+ exit 1
+ fi
+
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variable installed.
+ installed=yes
+
+ # Read the .la file
+ # If there is no directory component, then add one.
+ case "$arg" in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Find the relevant object directory and library name.
+ name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'`
+
+ if test "X$installed" = Xyes; then
+ dir="$libdir"
+ else
+ dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$arg"; then
+ dir="$objdir"
+ else
+ dir="$dir/$objdir"
+ fi
+ fi
+
+ if test -n "$dependency_libs"; then
+ # Extract -R and -L from dependency_libs
+ temp_deplibs=
+ for deplib in $dependency_libs; do
+ case "$deplib" in
+ -R*) temp_xrpath=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ case " $rpath $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ -L*) case "$compile_command $temp_deplibs " in
+ *" $deplib "*) ;;
+ *) temp_deplibs="$temp_deplibs $deplib";;
+ esac
+ temp_dir=`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ case " $lib_search_path " in
+ *" $temp_dir "*) ;;
+ *) lib_search_path="$lib_search_path $temp_dir";;
+ esac
+ ;;
+ *) temp_deplibs="$temp_deplibs $deplib";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ if test -z "$libdir"; then
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $dir/$old_library"
+ old_convenience="$old_convenience $dir/$old_library"
+ deplibs="$deplibs$dependency_libs"
+ compile_command="$compile_command $dir/$old_library$dependency_libs"
+ finalize_command="$finalize_command $dir/$old_library$dependency_libs"
+ continue
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ if test -z "$dlname" || test "$dlopen" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking statically,
+ # we need to preload.
+ prev=dlprefiles
+ else
+ # We should not create a dependency on this library, but we
+ # may need any libraries it requires.
+ compile_command="$compile_command$dependency_libs"
+ finalize_command="$finalize_command$dependency_libs"
+ prev=
+ continue
+ fi
+ fi
+
+ # The library was specified with -dlpreopen.
+ if test "$prev" = dlprefiles; then
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ dlprefiles="$dlprefiles $dir/$old_library"
+ else
+ dlprefiles="$dlprefiles $dir/$linklib"
+ fi
+ prev=
+ fi
+
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ link_against_libtool_libs="$link_against_libtool_libs $arg"
+ if test -n "$shlibpath_var"; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ esac
+ fi
+
+ # We need an absolute path.
+ case "$dir" in
+ [\\/] | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+
+ # This is the magic to use -rpath.
+ # Skip directories that are in the system default run-time
+ # search path, unless they have been requested with -R.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+
+ lib_linked=yes
+ case "$hardcode_action" in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ compile_command="$compile_command $dir/$linklib"
+ deplibs="$deplibs $dir/$linklib"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2*)
+ dllsearchdir=`cd "$dir" && pwd || echo "$dir"`
+ if test -n "$dllsearchpath"; then
+ dllsearchpath="$dllsearchpath:$dllsearchdir"
+ else
+ dllsearchpath="$dllsearchdir"
+ fi
+ ;;
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case "$host" in
+ *-*-sunos*)
+ compile_shlibpath="$compile_shlibpath$dir:"
+ ;;
+ esac
+ case "$compile_command " in
+ *" -L$dir "*) ;;
+ *) compile_command="$compile_command -L$dir";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -L$dir -l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ case ":$compile_shlibpath:" in
+ *":$dir:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$dir:";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+
+ relink)
+ if test "$hardcode_direct" = yes; then
+ compile_command="$compile_command $absdir/$linklib"
+ deplibs="$deplibs $absdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ case "$compile_command " in
+ *" -L$absdir "*) ;;
+ *) compile_command="$compile_command -L$absdir";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -L$absdir -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case ":$compile_shlibpath:" in
+ *":$absdir:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$absdir:";;
+ esac
+ compile_command="$compile_command -l$name"
+ deplibs="$deplibs -l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+
+ *)
+ lib_linked=no
+ ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit 1
+ fi
+
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ finalize_command="$finalize_command $libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ case "$finalize_command " in
+ *" -L$libdir "*) ;;
+ *) finalize_command="$finalize_command -L$libdir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case ":$finalize_shlibpath:" in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ case "$finalize_command " in
+ *" -L$dir "*) ;;
+ *) finalize_command="$finalize_command -L$libdir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ fi
+ else
+ # Transform directly to old archives if we don't build new libraries.
+ if test -n "$pic_flag" && test -z "$old_library"; then
+ $echo "$modename: cannot find static library for \`$arg'" 1>&2
+ exit 1
+ fi
+
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_command="$compile_command $dir/$linklib"
+ finalize_command="$finalize_command $dir/$linklib"
+ else
+ case "$compile_command " in
+ *" -L$dir "*) ;;
+ *) compile_command="$compile_command -L$dir";;
+ esac
+ compile_command="$compile_command -l$name"
+ case "$finalize_command " in
+ *" -L$dir "*) ;;
+ *) finalize_command="$finalize_command -L$dir";;
+ esac
+ finalize_command="$finalize_command -l$name"
+ fi
+ fi
+
+ # Add in any libraries that this one depends upon.
+ compile_command="$compile_command$dependency_libs"
+ finalize_command="$finalize_command$dependency_libs"
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ case "$output" in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+
+ *.a | *.lib)
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link libtool libraries into archives" 1>&2
+ exit 1
+ fi
+
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ ;;
+
+ *.la)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case "$outputname" in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+
+ if test -n "$objs"; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1
+ exit 1
+ fi
+
+ # How the heck are we supposed to write a wrapper for a shared library?
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link shared libraries into libtool libraries" 1>&2
+ exit 1
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test $# -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ libext=al
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+ dependency_libs="$deplibs"
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ current="$2"
+ revision="$3"
+ age="$4"
+
+ # Check that each of the things are valid numbers.
+ case "$current" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$revision" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$age" in
+ 0 | [1-9] | [1-9][0-9]*) ;;
+ *)
+ $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test $age -gt $current; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit 1
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case "$version_type" in
+ none) ;;
+
+ irix)
+ major=`expr $current - $age + 1`
+ versuffix="$major.$revision"
+ verstring="sgi$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test $loop != 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="sgi$major.$iface:$verstring"
+ done
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test $loop != 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ windows)
+ # Like Linux, but with '-' rather than '.', since we only
+ # want one extension on Windows 95.
+ major=`expr $current - $age`
+ versuffix="-$major-$age-$revision"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ verstring="0.0"
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+
+ dependency_libs="$deplibs"
+ case "$host" in
+ *-*-cygwin* | *-*-mingw* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody*)
+ # rhapsody is a little odd...
+ deplibs="$deplibs -framework System"
+ ;;
+ *)
+ # Add libc to deplibs on all other systems.
+ deplibs="$deplibs -lc"
+ ;;
+ esac
+ fi
+
+ # Create the output directory, or remove our outputs if we need to.
+ if test -d $output_objdir; then
+ $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*"
+ $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*
+ else
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test $status -ne 0 && test ! -d $output_objdir; then
+ exit $status
+ fi
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ if test "$build_libtool_libs" = yes; then
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case "$deplibs_check_method" in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behaviour.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ $CC -o conftest conftest.c $deplibs
+ if test $? -eq 0 ; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occured in the first compile. Let's try to salvage the situation:
+ # Compile a seperate program for each library.
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ $rm conftest
+ $CC -o conftest conftest.c $i
+ # Did it work?
+ if test $? -eq 0 ; then
+ ldd_output=`ldd conftest`
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ droppeddeps=yes
+ echo
+ echo "*** Warning! Library $i is needed by this library but I was not able to"
+ echo "*** make it link in! You will probably need to install it or some"
+ echo "*** library that it depends on before this library will be fully"
+ echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"$2 \(.*\)\"`"
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | sed 's/.* -> //'`
+ case "$potliblink" in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | sed 10q \
+ | egrep "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ echo
+ echo "*** Warning: This library needs some functionality provided by $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' |
+ grep . >/dev/null; then
+ echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ echo
+ echo "*** Warning: libtool could not satisfy all declared inter-library"
+ echo "*** dependencies of module $libname. Therefore, libtool will create"
+ echo "*** a static module, that should work as long as the dlopening"
+ echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ echo "*** The inter-library dependencies that have been dropped here will be"
+ echo "*** automatically added whenever a program is linked with this library"
+ echo "*** or is declared to -dlopen it."
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ # Get the real and link names of the library.
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ lib="$output_objdir/$realname"
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Ensure that we have .o objects for linkers which dislike .lo
+ # (e.g. aix) in case we are running --disable-static
+ for obj in $libobjs; do
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
+ if test ! -f $xdir/$oldobj; then
+ $show "(cd $xdir && ${LN_S} $baseobj $oldobj)"
+ $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $?
+ fi
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ eval cmds=\"$export_symbols_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${outputname}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linkopts="$linkopts $flag"
+ fi
+
+ # Do each of the archive commands.
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval cmds=\"$archive_expsym_cmds\"
+ else
+ eval cmds=\"$archive_cmds\"
+ fi
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ *.lo | *.o | *.obj)
+ if test -n "$link_against_libtool_libs"; then
+ $echo "$modename: error: cannot link libtool libraries into objects" 1>&2
+ exit 1
+ fi
+
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case "$output" in
+ *.lo)
+ if test -n "$objs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit 1
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${obj}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ for xlib in $convenience; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs"
+
+ output="$obj"
+ eval cmds=\"$reload_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit 0
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ $show "echo timestamp > $libobj"
+ $run eval "echo timestamp > $libobj" || exit $?
+ exit 0
+ fi
+
+ if test -n "$pic_flag"; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ eval cmds=\"$reload_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ else
+ # Just create a symlink.
+ $show $rm $libobj
+ $run $rm $libobj
+ xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$libobj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'`
+ oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"`
+ $show "(cd $xdir && $LN_S $oldobj $baseobj)"
+ $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $?
+ fi
+
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit 0
+ ;;
+
+ # Anything else should be a program.
+ *)
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$compile_rpath " in
+ *" $libdir "*) ;;
+ *) compile_rpath="$compile_rpath $libdir" ;;
+ esac
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+
+ # Create the binary in the object directory, then wrap it.
+ if test ! -d $output_objdir; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test $status -ne 0 && test ! -d $output_objdir; then
+ exit $status
+ fi
+ fi
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case "$dlsyms" in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$output.exp"
+ $run $rm $export_symbols
+ $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ else
+ $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+ $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`echo "$arg" | sed -e 's%^.*/%%'`
+ $run eval 'echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ sed -n -e 's/^: \([^ ]*\) $/ {\"\1\", (lt_ptr_t) 0},/p' \
+ -e 's/^. \([^ ]*\) \([^ ]*\)$/ {"\2", (lt_ptr_t) \&\2},/p' \
+ < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr_t) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case "$host" in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";;
+ esac;;
+ *-*-hpux*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DPIC";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit 1
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+
+ if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case "$dir" in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $0 --fallback-echo"; then
+ case "$0" in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$0 --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`echo $output|sed 's,.exe$,,'` ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit 1" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ link_against_libtool_libs='$link_against_libtool_libs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ echo >> $output "\
+ program=lt-'$outputname'
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if (cd \"\$thisdir\" && eval \$relink_command); then :
+ else
+ $rm \"\$progdir/\$file\"
+ exit 1
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ echo >> $output "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ # win32 systems need to use the prog path for dll
+ # lookup to work
+ *-*-cygwin*)
+ $echo >> $output "\
+ exec \$progdir/\$program \${1+\"\$@\"}
+"
+ ;;
+
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2*)
+ $echo >> $output "\
+ exec \$progdir\\\\\$program \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $echo >> $output "\
+ # Export the path to the program.
+ PATH=\"\$progdir:\$PATH\"
+ export PATH
+
+ exec \$program \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+ exit 1
+ fi
+ else
+ # The program doesn't exist.
+ \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+ \$echo \"This script is just a wrapper for \$program.\" 1>&2
+ echo \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit 1
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit 0
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$objs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ $show "${rm}r $gentop"
+ $run ${rm}r "$gentop"
+ $show "mkdir $gentop"
+ $run mkdir "$gentop"
+ status=$?
+ if test $status -ne 0 && test ! -d "$gentop"; then
+ exit $status
+ fi
+ generated="$generated $gentop"
+
+ # Add in members from convenience archives.
+ for xlib in $addlibs; do
+ # Extract the objects.
+ case "$xlib" in
+ [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
+ *) xabs=`pwd`"/$xlib" ;;
+ esac
+ xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
+ xdir="$gentop/$xlib"
+
+ $show "${rm}r $xdir"
+ $run ${rm}r "$xdir"
+ $show "mkdir $xdir"
+ $run mkdir "$xdir"
+ status=$?
+ if test $status -ne 0 && test ! -d "$xdir"; then
+ exit $status
+ fi
+ $show "(cd $xdir && $AR x $xabs)"
+ $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
+
+ oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
+ done
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ eval cmds=\"$old_archive_from_new_cmds\"
+ else
+ # Ensure that we have .o objects in place in case we decided
+ # not to build a shared library, and have fallen back to building
+ # static libs even though --disable-static was passed!
+ for oldobj in $oldobjs; do
+ if test ! -f $oldobj; then
+ xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$oldobj"; then
+ xdir="."
+ else
+ xdir="$xdir"
+ fi
+ baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'`
+ obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"`
+ $show "(cd $xdir && ${LN_S} $obj $baseobj)"
+ $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $?
+ fi
+ done
+
+ eval cmds=\"$old_archive_cmds\"
+ fi
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case "$output" in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ if test -n "$xrpath"; then
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ done
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ fi
+ $rm $output
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$dlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'\
+"
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" || exit $?
+ ;;
+ esac
+ exit 0
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg="$nonopt"
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest="$arg"
+ continue
+ fi
+
+ case "$arg" in
+ -d) isdir=yes ;;
+ -f) prev="-f" ;;
+ -g) prev="-g" ;;
+ -m) prev="-m" ;;
+ -o) prev="-o" ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*) ;;
+
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest="$arg"
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case "$arg" in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test $# -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+ fi
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case "$file" in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case "$file" in
+ *.a | *.lib)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ library_names=
+ old_library=
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/"
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$realname $destdir/$realname"
+ $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $?
+
+ if test $# -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ for linkname
+ do
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ eval cmds=\"$postinstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case "$destfile" in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.o | *.obj)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit 0
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Do a test to see if this is really a libtool program.
+ if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ link_against_libtool_libs=
+ relink_command=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$link_against_libtool_libs"; then
+ $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2
+ exit 1
+ fi
+
+ finalize=yes
+ for lib in $link_against_libtool_libs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case "$lib" in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`"
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir="/tmp"
+ test -n "$TMPDIR" && tmpdir="$TMPDIR"
+ tmpdir="$tmpdir/libtool-$$"
+ if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then :
+ else
+ $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+ continue
+ fi
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ # Do each command in the postinstall commands.
+ eval cmds=\"$old_postinstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec $SHELL $0 --finish$current_libdirs
+ exit 1
+ fi
+
+ exit 0
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ eval cmds=\"$finish_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = : && exit 0
+
+ echo "----------------------------------------------------------------------"
+ echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ echo " $libdir"
+ done
+ echo
+ echo "If you ever happen to want to link against installed libraries"
+ echo "in a given directory, LIBDIR, you must either use libtool, and"
+ echo "specify the full pathname of the library, or use \`-LLIBDIR'"
+ echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ echo
+ echo "See any operating system documentation about shared libraries for"
+ echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ echo "----------------------------------------------------------------------"
+ exit 0
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit 1
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ dir=
+ case "$file" in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit 1
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case "$file" in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case "$file" in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved enviroment variables
+ if test "${save_LC_ALL+set}" = set; then
+ LC_ALL="$save_LC_ALL"; export LC_ALL
+ fi
+ if test "${save_LANG+set}" = set; then
+ LANG="$save_LANG"; export LANG
+ fi
+
+ # Now actually exec the command.
+ eval "exec \$cmd$args"
+
+ $echo "$modename: cannot exec \$cmd$args"
+ exit 1
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ fi
+ $echo "$cmd$args"
+ exit 0
+ fi
+ ;;
+
+ # libtool uninstall mode
+ uninstall)
+ modename="$modename: uninstall"
+ rm="$nonopt"
+ files=
+
+ for arg
+ do
+ case "$arg" in
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ fi
+
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ rmfiles="$file"
+
+ case "$name" in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $dir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library"
+
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ eval cmds=\"$postuninstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ eval cmds=\"$old_postuninstall_cmds\"
+ IFS="${IFS= }"; save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd"
+ done
+ IFS="$save_ifs"
+ fi
+
+ # FIXME: should reinstall the best remaining shared library.
+ fi
+ ;;
+
+ *.lo)
+ if test "$build_old_libs" = yes; then
+ oldobj=`$echo "X$name" | $Xsed -e "$lo2o"`
+ rmfiles="$rmfiles $dir/$oldobj"
+ fi
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+ ;;
+
+ *)
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles
+ ;;
+ esac
+ done
+ exit 0
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+ ;;
+ esac
+
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit 1
+fi # test -z "$show_help"
+
+# We need to display help for each of the modes.
+case "$mode" in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --version print version information
+
+MODE must be one of the following:
+
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE."
+ exit 0
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit 1
+ ;;
+esac
+
+echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit 0
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/contrib/idn/idnkit-1.0-src/make.wnt b/contrib/idn/idnkit-1.0-src/make.wnt
new file mode 100644
index 0000000..73316ca
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/make.wnt
@@ -0,0 +1,76 @@
+# $Id: make.wnt,v 1.1.1.1 2003/06/04 00:25:03 marka Exp $
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+all : force
+ copy include\config.h.win include\config.h
+ cd lib
+ $(MAKE) -f make.wnt
+ cd ..
+ cd tools
+ $(MAKE) -f make.wnt
+ cd ..
+ cd wsock
+ $(MAKE) -f make.wnt
+ cd ..
+
+install : all
+ cd lib
+ $(MAKE) -f make.wnt install
+ cd ..
+ cd tools
+ $(MAKE) -f make.wnt install
+ cd ..
+ cd wsock
+ $(MAKE) -f make.wnt install
+ cd ..
+
+clean : force
+ cd lib
+ $(MAKE) -f make.wnt clean
+ cd ..
+ cd tools
+ $(MAKE) -f make.wnt clean
+ cd ..
+ cd wsock
+ $(MAKE) -f make.wnt clean
+ cd ..
+
+force:
diff --git a/contrib/idn/idnkit-1.0-src/man/Makefile.in b/contrib/idn/idnkit-1.0-src/man/Makefile.in
new file mode 100644
index 0000000..a85a793
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/man/Makefile.in
@@ -0,0 +1,116 @@
+# $Id: Makefile.in,v 1.1.1.1 2003/06/04 00:27:14 marka Exp $
+#
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+top_builddir = ..
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+sysconfdir = @sysconfdir@
+mandir = @mandir@
+man3dir = $(mandir)/man3
+man5dir = $(mandir)/man5
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+SHELL = @SHELL@
+
+@LITEONLY_TRUE@all: libidnkitlite.3 idn.conf.5 idnrc.5 idnalias.conf.5
+@LITEONLY_FALSE@all: libidnkitlite.3 idn.conf.5 idnrc.5 idnalias.conf.5 libidnkit.3
+
+libidnkit.3: libidnkit.3.in
+ sed 's%[@]sysconfdir[@]%$(sysconfdir)%' < $(srcdir)/libidnkit.3.in > $@
+libidnkitlite.3: libidnkit.3.in
+ sed 's%[@]sysconfdir[@]%$(sysconfdir)%' < $(srcdir)/libidnkit.3.in > $@
+idn.conf.5: idn.conf.5.in
+ sed 's%[@]sysconfdir[@]%$(sysconfdir)%' < $(srcdir)/idn.conf.5.in > $@
+idnrc.5: idn.conf.5.in
+ sed 's%[@]sysconfdir[@]%$(sysconfdir)%' < $(srcdir)/idn.conf.5.in > $@
+idnalias.conf.5: idn.conf.5.in
+ sed 's%[@]sysconfdir[@]%$(sysconfdir)%' < $(srcdir)/idn.conf.5.in > $@
+
+@LITEONLY_TRUE@@COMPAT_TRUE@install: all install-common install-compat-common
+@LITEONLY_FALSE@@COMPAT_TRUE@install: all install-common install-nolite install-compat-common install-compat-nolite
+@LITEONLY_TRUE@@COMPAT_FALSE@install: all install-common
+@LITEONLY_FALSE@@COMPAT_FALSE@install: all install-common install-nolite
+
+install-common:
+ $(MKINSTALLDIRS) $(DESTDIR)$(man3dir)
+ $(INSTALL_DATA) libidnkitlite.3 $(DESTDIR)$(man3dir)/libidnkitlite.3
+ $(MKINSTALLDIRS) $(DESTDIR)$(man5dir)
+ $(INSTALL_DATA) idn.conf.5 $(DESTDIR)$(man5dir)/idn.conf.5
+ $(INSTALL_DATA) idnrc.5 $(DESTDIR)$(man5dir)/idnrc.5
+ $(INSTALL_DATA) idnalias.conf.5 $(DESTDIR)$(man5dir)/idnalias.conf.5
+
+install-nolite:
+ $(MKINSTALLDIRS) $(DESTDIR)$(man3dir)
+ $(INSTALL_DATA) libidnkit.3 $(DESTDIR)$(man3dir)/libidnkit.3
+
+install-compat-common:
+ src=$(DESTDIR)$(man3dir)/libidnkitlite.3; \
+ dst=$(DESTDIR)$(man3dir)/libmdnlite.3; \
+ rm -f $$dst; \
+ ln $$src $$dst || cp $$src $$dst
+ src=$(DESTDIR)$(man5dir)/idn.conf.5; \
+ dst=$(DESTDIR)$(man5dir)/mdn.conf.5; \
+ rm -f $$dst; \
+ ln $$src $$dst || cp $$src $$dst
+
+install-compat-nolite:
+ src=$(DESTDIR)$(man3dir)/libidnkit.3; \
+ dst=$(DESTDIR)$(man3dir)/libmdn.3; \
+ rm -f $$dst; \
+ ln $$src $$dst || cp $$src $$dst
+
+clean:
+ rm -f idn.conf.5 idnrc.5 idnalias.conf.5 libidnkit.3 libidnkitlite.3
+ rm -f *~
+
+distclean: clean
+ rm -f Makefile
+
+test check:
diff --git a/contrib/idn/idnkit-1.0-src/man/idn.conf.5.in b/contrib/idn/idnkit-1.0-src/man/idn.conf.5.in
new file mode 100644
index 0000000..cbc2248
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/man/idn.conf.5.in
@@ -0,0 +1,312 @@
+.\" $Id: idn.conf.5.in,v 1.1.1.1 2003/06/04 00:27:16 marka Exp $"
+.\"
+.\" Copyright (c) 2000,2001 Japan Network Information Center.
+.\" All rights reserved.
+.\"
+.\" By using this file, you agree to the terms and conditions set forth bellow.
+.\"
+.\" LICENSE TERMS AND CONDITIONS
+.\"
+.\" The following License Terms and Conditions apply, unless a different
+.\" license is obtained from Japan Network Information Center ("JPNIC"),
+.\" a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+.\" Chiyoda-ku, Tokyo 101-0047, Japan.
+.\"
+.\" 1. Use, Modification and Redistribution (including distribution of any
+.\" modified or derived work) in source and/or binary forms is permitted
+.\" under this License Terms and Conditions.
+.\"
+.\" 2. Redistribution of source code must retain the copyright notices as they
+.\" appear in each source code file, this License Terms and Conditions.
+.\"
+.\" 3. Redistribution in binary form must reproduce the Copyright Notice,
+.\" this License Terms and Conditions, in the documentation and/or other
+.\" materials provided with the distribution. For the purposes of binary
+.\" distribution the "Copyright Notice" refers to the following language:
+.\" "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+.\"
+.\" 4. The name of JPNIC may not be used to endorse or promote products
+.\" derived from this Software without specific prior written approval of
+.\" JPNIC.
+.\"
+.\" 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+.\" PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+.\"
+.TH idn.conf 5 "Mar 8, 2002"
+.\"
+.SH NAME
+idn.conf, .idnrc, idnalias.conf \- configuration files for idnkit library
+.\"
+.SH SYNOPSIS
+@sysconfdir@/idn.conf
+.br
+~/.idnrc
+.br
+@sysconfdir@/idnalias.conf
+.\"
+.SH DESCRIPTION
+\fBidn.conf\fR and \fB.idnrc\fR are configuration files for idnkit
+library which is a toolkit for handling internationalized domain names.
+.PP
+idnkit library tries to load the user's configuration file ~/.idnrc
+first, and then tries the system configutation file
+@sysconfdir@/idn.conf.
+Note that idnkit library loads either, not both.
+.PP
+To use internationalized domain names in DNS or other protocols, they
+must be converted to an appropriate format before further processing.
+In idnkit, this conversion process is comprised of the following tasks.
+.IP 1. 3
+Convert the given domain name in application's local codeset to Unicode,
+and vice versa.
+.IP 2. 3
+Map certain characters in the name to period character so that they are
+treated as the domain name
+delimiter (\fIdelimiter mapping\fR).
+.IP 3. 3
+Map certain characters in the name to other characters or chracter sequences,
+according to a mapping rule determined by its top level domain (TLD).
+.IP 4. 3
+Perform NAMEPREP, which is a starndard name preparation process for
+internationalized domain names. This process is composed of
+the tree steps called mapping, normalization, prohibited character
+checking and bidirectional string checking.
+.IP 5. 3
+Convert the nameprepped name to IDN encoding, which is the standard encoding
+for internationalized domain names (also known as ASCII-compatible encoding,
+ACE), and vice versa.
+.PP
+The configuration file specifies the parameters for these tasks, such as:
+.RS 2
+.IP \- 2
+the encoding of internationalized domain names (IDN encoding).
+.IP \- 2
+NAMEPREP schemes.
+.RE
+.\"
+.SH SYNTAX
+The configuration file is a simple text files, and each line in the file
+(other than comment lines, which begin with ``#'', and empty lines)
+forms an entry of the following format:
+.PP
+.RS 4
+.nf
+\fIkeyword\fP\ \fIvalue..\fP
+.fi
+.RE
+\."
+.SH "IDN-ENCODING ENTRY"
+IDN encoding entry specifies the encoding name (codeset name) which
+is used as the encoding of internationalized domain names.
+.PP
+The syntax of this entry is:
+.PP
+.RS 4
+.nf
+\f(CWidn-encoding \fP\fIencoding\fP
+.fi
+.RE
+.PP
+\fIencoding\fP is the encoding name to be used, and any of the following
+names can be specified.
+.RS 2
+.IP "\(bu" 2
+``Punycode''
+.IP "\(bu" 2
+``UTF-8''
+.IP "\(bu" 2
+Codeset names which iconv_open() library function accepts. Please
+consult iconv() documentation for the available codesets.
+.IP "\(bu" 2
+Any alias names for the above, defined by the alias file.
+(See section ``ENCODING-ALIAS-FILE'')
+.RE
+.PP
+The standard encoding was determined as Punycode.
+.\"
+.SH "NAMEPREP ENTRY"
+Nameprep entry specifies the version of NAMEPREP, which is a specification
+of ``canonicalization'' process of internationalized domain name before
+it is converted to the IDN encoding.
+.PP
+The syntax of this entry is:
+.PP
+.RS 4
+.nf
+\f(CWnameprep \fP\fIversion\fP
+.fi
+.RE
+.PP
+\fIversion\fR is the version name of NAMEPREP specification, and currently
+the following versions can be specified.
+.RS 2
+.IP "\(bu" 2
+``RFC3491''
+.br
+This version refers to RFC3491 ``rfc-3491.txt''.
+.RE
+.PP
+The NAMEPREP process consists of the following 4 subprocesses.
+.IP 1. 3
+mapping, which maps certain characters in a name to other characters,
+possibly none.
+.IP 2. 3
+normalization, which replaces character variants in a name to
+a unique one.
+.IP 3. 3
+prohibited character checking, which detects invalid characters in a name.
+.IP 4. 3
+unassigned codepoint checking, which also invalid codepoints in a name.
+.IP 5. 3
+bidirectional string checking, which detecs invalid string.
+.\"
+.SH "LOCAL-MAP ENTRY"
+This entry specifies localized mapping phase before NAMEPREP takes place.
+Different mapping rules can be specified for each TLD (top-level domain).
+For example, you can have one mapping for ``.tw'' domain, and another for
+``.jp'' domain.
+.PP
+The syntax of this entry is:
+.PP
+.RS 4
+.nf
+\f(CWlocal-map \fItld\f(CW \fIscheme\fR [\fIscheme\fR..]
+.fi
+.RE
+.PP
+\fItld\fR specifies the TLD to which the mapping rule is to be applied,
+and \fIscheme\fR specifies the mapping scheme, and currently available
+schemes are:
+.RS 2
+.TP 4
+\f(CWRFC3491\fP
+Specify mapping defined by RFC3491.
+.TP 4
+\f(CWfilemap:\fP\fIpathname\fP
+Specify mapping defined by the file \fIpathname\fP.
+See ``MAPFILE FORMAT'' for the format of this file.
+.RE
+.PP
+There are two special \fItld\fRs for specifying the mapping rule for
+local domain names (domain names without any dots in them), and the
+default mapping rule.
+If
+\fItld\fR is ``-'', it matches domain names which do not contain any
+dots.
+If \fItld\fR is ``.'', it matches any domain names which don't match
+to any other mapping rules specified by ``local-map'' entries.
+.\"
+.SH "MAPFILE FORMAT"
+A mapfile defines a set of character mapping rules. It can define
+unconditional one-character to N-character-sequence (N can be 0, 1 or more)
+mappings.
+.PP
+A mapfile is a simple text file, and each line specifies a single mapping.
+Each line is of the form:
+.PP
+.RS 4
+.nf
+\fIsrc-codepoint\fR\f(CW; \fImapped-codepoint-seq\fR\f(CW;\fR
+.fi
+.RE
+.PP
+\fIsrc-codepoint\fR indicates source character of the mapping, and must
+be a Unicode codepoint value in hexadecimal string.
+\fImapped-codepoint-seq\fR is a sequence of characters which is the
+outcome of the mapping, and must be a (possibly empty) list of Unicode
+codepoint values in hexadecimal string, separated by spaces.
+.PP
+Lines which begin with ``#'' are treated as comments and ignored.
+.PP
+A sample mapfile is shown below.
+.PP
+.RS 4
+.nf
+.ft CW
+# map "A" to "a"
+0041; 0061;
+# map "#" to nothing
+0023; ;
+# map "@" to "at"
+0040; 0061 0074;
+.ft R
+.fi
+.RE
+.\"
+.SH "LOCAL CODESET"
+\fBidn.conf\fR or \fB~/.idnrc\fR doesn't have an entry to specify the
+local codeset, since it is determined from the application's current
+locale information.
+So each application can use different local codeset.
+.PP
+Although idnkit tries hard to find out the local codeset, sometimes it
+fails. For example, there are applications which use non-ASCII codeset
+but work in C locale. In this case, you can specify the application's
+local codeset by an environment variable ``\fBIDN_LOCAL_CODESET\fR''.
+Just set the codeset name (or its alias name) to the variable, and
+idnkit will use the codeset as the local one, regardless of the locale
+setting.
+.\"
+.SH "ENCODING-ALIAS-FILE"
+Encoding alias file specifies codeset name aliases. It is located on
+@sysconfdir@/idnalias.conf and always loaded automatically as idn.conf
+and .idnrc. The aliases in this file can be used just as the real names.
+.PP
+The alias file is a simple text file, consisting of lines of the form:
+.PP
+.RS 4
+.nf
+\fIalias-name\fP\ \fIname\fP
+.fi
+.RE
+.PP
+\fIalias-name\fR is the alias name to be defined, and \fIname\fR is
+the real name or another alias name.
+.\"
+.SH "SAMPLE CONFIGURATION"
+The following shows a sample configuration file.
+.PP
+.RS 4
+.ft CW
+.nf
+#
+# a sample configuration.
+#
+
+# Use Punycode as the IDN encoding.
+idn-encoding Punycode
+
+# Use RFC3491 as NAMEPREP.
+nameprep RFC3491
+
+# Perform Japanese-specific mapping for .jp domain.
+# assuming /usr/local/lib/idnkit/jp-map contains the mapping.
+local-map .jp filemap:/usr/local/lib/idnkit/jp-map
+.fi
+.ft R
+.RE
+.\"
+.SH FILES
+.I @sysconfdir@/idn.conf
+.br
+.I ~/.idnrc
+.br
+.I @sysconfdir@/idnalias.conf
+.br
+.I @sysconfdir@/idn.conf.sample
+\- sample configuration with comments
+.br
+.I @sysconfdir@/idnalias.conf.sample
+\- sample alias file
+.\"
+.SH "SEE ALSO"
+iconv(3)
diff --git a/contrib/idn/idnkit-1.0-src/man/libidnkit.3.in b/contrib/idn/idnkit-1.0-src/man/libidnkit.3.in
new file mode 100644
index 0000000..12bca54
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/man/libidnkit.3.in
@@ -0,0 +1,480 @@
+.\" $Id: libidnkit.3.in,v 1.1.1.1 2003/06/04 00:27:15 marka Exp $
+.\"
+.\" Copyright (c) 2001,2002 Japan Network Information Center.
+.\" All rights reserved.
+.\"
+.\" By using this file, you agree to the terms and conditions set forth bellow.
+.\"
+.\" LICENSE TERMS AND CONDITIONS
+.\"
+.\" The following License Terms and Conditions apply, unless a different
+.\" license is obtained from Japan Network Information Center ("JPNIC"),
+.\" a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+.\" Chiyoda-ku, Tokyo 101-0047, Japan.
+.\"
+.\" 1. Use, Modification and Redistribution (including distribution of any
+.\" modified or derived work) in source and/or binary forms is permitted
+.\" under this License Terms and Conditions.
+.\"
+.\" 2. Redistribution of source code must retain the copyright notices as they
+.\" appear in each source code file, this License Terms and Conditions.
+.\"
+.\" 3. Redistribution in binary form must reproduce the Copyright Notice,
+.\" this License Terms and Conditions, in the documentation and/or other
+.\" materials provided with the distribution. For the purposes of binary
+.\" distribution the "Copyright Notice" refers to the following language:
+.\" "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+.\"
+.\" 4. The name of JPNIC may not be used to endorse or promote products
+.\" derived from this Software without specific prior written approval of
+.\" JPNIC.
+.\"
+.\" 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+.\" PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+.\"
+.TH libidnkit 3 "Mar 11, 2002"
+.\"
+.SH NAME
+libidnkit, libidnkitlite \- Internationalized Domain Name Handling Libraries
+.\"
+.SH SYNOPSIS
+.nf
+#include <idn/api.h>
+
+idn_result_t
+\fBidn_nameinit\fP(int\ load_file)
+
+idn_result_t
+\fBidn_encodename\fP(int\ actions,\ const\ char\ *from,\ char\ *to,\ size_t\ tolen)
+
+idn_result_t
+\fBidn_decodename\fP(int\ actions,\ const\ char\ *from,\ char\ *to,\ size_t\ tolen)
+
+idn_result_t
+\fBidn_decodename2\fP(int\ actions,\ const\ char\ *from,\ char\ *to,\ size_t\ tolen,
+ const\ char\ *auxencoding)
+
+idn_result_t
+\fBidn_enable\fP(int\ on_off)
+
+#include <idn/result.h>
+
+char *
+\fBidn_result_tostring\fP(idn_result_t\ result)
+
+.\"
+.SH OVERVIEW
+The
+\fBlibidnkit\fR and \fBlibidnkitlite\fR libraries support various
+manipulations of internationalized domain names, including:
+.RS 2
+.IP \- 2
+encoding convesion
+.IP \- 2
+name preparation
+.RE
+.PP
+They are designed according to IDNA framework where each application must
+do necessary preparations for the internationalized domain names before
+passing them to the resolver.
+.PP
+To help applications do the preparation, the libraries provide easy-to-use,
+high-level interface for the work.
+.PP
+Both libraries provide almost the same API.
+The difference between them is that \fBlibidnkit\fR internally uses
+\fIiconv\fR function to provide encoding conversion from UTF-8 to the
+local encoding
+(such as iso-8859-1, usually determined by the current locale), and vise
+versa.
+\fBlibidnkitlite\fR is lightweight version of libidnkit.
+It assumes local encoding is UTF-8 so that it never uses \fIiconv\fR.
+.PP
+This manual describes only a small subset of the API that the libraries
+provide, most important functions for application programmers.
+For other API, please refer to the idnkit's specification document
+(which is not yet available) or the header files typically found under
+`/usr/local/include/idn/' on your system.
+.\"
+.SH DESCRIPTION
+.PP
+The \fBidn_nameinit\fR function initializes the library.
+It also sets default configuration if \fIload_file\fR is 0, otherwise
+it tries to read a configuration file.
+If \fBidn_nameinit\fR is called more than once, the library initialization
+will take place only at the first call while the actual configuration
+procedure will occur at every call.
+.PP
+If there are no errors, \fBidn_nameinit\fR returns \fBidn_success\fR.
+Otherwise, the returned value indicates the cause of the error.
+See the section ``RETURN VALUES'' below for the error codes.
+.PP
+Usually you don't have to call this function explicitly because
+it is implicitly called when \fBidn_encodename\fR or \fBidn_decodename\fR
+is first called without prior calling of \fBidn_nameinit\fR.
+In such case, initialization without the configuration file
+takes place.
+.\"
+.PP
+\fBidn_encodename\fR function performs name preparation and encoding
+conversion on the internationalized domain name specified by \fIfrom\fR,
+and stores the result to \fIto\fR, whose length is specified by
+\fItolen\fR.
+\fIactions\fR is a bitwise-OR of the following macros, specifying which
+subprocesses in the encoding process are to be employed.
+.RS 2
+.nf
+.ft CW
+IDN_LOCALCONV Local encoding to UTF-8 conversion
+IDN_DELIMMAP Delimiter mapping
+IDN_LOCALMAP Local mapping
+IDN_NAMEPREP NAMEPREP mapping, normalization,
+ prohibited character check and bidirectional
+ string check
+IDN_UNASCHECK NAMEPREP unassigned codepoint check
+IDN_ASCCHECK ASCII range character check
+IDN_IDNCONV UTF-8 to IDN encoding conversion
+IDN_LENCHECK Label length check
+.ft R
+.fi
+.RE
+.PP
+Details of this encoding process can be found in the section ``NAME ENCODING''.
+.PP
+For convenience, also \fBIDN_ENCODE_QUERY\fR, \fBIDN_ENCODE_APP\fR
+and \fBIDN_ENCODE_STORED\fR macros are provided.
+\fBIDN_ENCODE_QUERY\fR is used to encode a ``query string''
+(see the IDNA specification).
+It is equal to
+.RS 4
+.nf
+.ft CW
+(IDN_LOCALCONV | IDN_DELIMMAP | IDN_LOCALMAP | IDN_NAMEPREP
+ | IDN_IDNCONV | IDN_LENCHECK)
+.ft R
+.fi
+.RE
+.PP
+if you are using \fBlibidnkit\fR, and equal to
+.RS 4
+.nf
+.ft CW
+(IDN_DELIMMAP | IDN_LOCALMAP | IDN_NAMEPREP | IDN_IDNCONV
+ | IDN_LENCHECK)
+.ft R
+.fi
+.RE
+.PP
+if you are using \fBlibidnkitlite\fR.
+.PP
+\fBIDN_ENCODE_APP\fR is used for ordinary application to encode a
+domain name.
+It performs \fBIDN_ASCCHECK\fR in addition with \fBIDN_ENCODE_QUERY\fR.
+\fBIDN_ENCODE_STORED\fR is used to encode a ``stored string''
+(see the IDNA specification).
+It performs \fBIDN_ENCODE_APP\fR plus \fBIDN_UNASCHECK\fR.
+.PP
+\fBidn_decodename\fR function performs the reverse of \fBidn_encodename\fR.
+It converts the internationalized domain name given by \fIfrom\fR,
+which is represented in a special encoding called ACE,
+to the application's local codeset and stores into \fIto\fR,
+whose length is specified by \fItolen\fR.
+As in \fBidn_encodename\fR, \fIactions\fR is a bitwise-OR of the following
+macros.
+.RS 2
+.nf
+.ft CW
+IDN_DELIMMAP Delimiter mapping
+IDN_NAMEPREP NAMEPREP mapping, normalization,
+ prohibited character check and bidirectional
+ string check
+IDN_UNASCHECK NAMEPREP unassigned codepoint check
+IDN_IDNCONV UTF-8 to IDN encoding conversion
+IDN_RTCHECK Round trip check
+IDN_ASCCHECK ASCII range character check
+IDN_LOCALCONV Local encoding to UTF-8 conversion
+.ft R
+.fi
+.RE
+.PP
+Details of this decoding process can be found in the section ``NAME DECODING''.
+.PP
+For convenience, also \fBIDN_DECODE_QUERY\fR, \fBIDN_DECODE_APP\fR
+and \fBIDN_DECODE_STORED\fR macros are provided.
+\fBIDN_DECODE_QUERY\fR is used to decode a ``qeury string''
+(see the IDNA specification).
+It is equal to
+.RS 4
+.nf
+.ft CW
+(IDN_DELIMMAP | IDN_NAMEPREP | IDN_IDNCONV | IDN_RTCHECK
+ | IDN_LOCALCONV)
+.ft R
+.fi
+.RE
+.PP
+if you are using \fBlibidnkit\fR, and equal to
+.RS 4
+.nf
+.ft CW
+(IDN_DELIMMAP | IDN_NAMEPREP | IDN_IDNCONV | IDN_RTCHECK)
+.ft R
+.fi
+.RE
+.PP
+if you are using \fBlibidnkitlite\fR.
+.PP
+\fBIDN_DECODE_APP\fR is used for ordinary application to decode a
+domain name.
+It performs \fBIDN_ASCCHECK\fR in addition with \fBIDN_DECODE_QUERY\fR.
+\fBIDN_DECODE_STORED\fR is used to decode a ``stored string''
+(see the IDNA specification).
+It performs \fBIDN_DECODE_APP\fR plus \fBIDN_UNASCHECK\fR.
+.PP
+\fBidn_decodename2\fR function provides the same functionality as
+\fBidn_decodename\fR except that character encoding of \fIfrom\fR is
+supposed to be \fIauxencoding\fR.
+If IDN encoding is Punycode and \fIauxencoding\fR is ISO 8859-2
+for example, it is assumed that the Punycode string stored in
+\fIfrom\fR is written in ISO 8859-2.
+.PP
+In the IDN decode procedure, \fBIDN_NAMEPREP\fR is done before
+\fBIDN_IDNCONV\fR, and some non-ASCII characters are converted to
+ASCII characters as the result of \fBIDN_NAMEPREP\fR.
+Therefore, ACE string given by \fBfrom\fR may contains those non-ASCII
+characters.
+That is the reason \fBdocode_name2\fR exists.
+.PP
+All of the functions above return error code of type \fBidn_result_t\fR.
+All codes other than \fBidn_success\fR indicates some kind of failure.
+\fBidn_result_tostring\fR function takes an error code \fIresult\fR
+and returns a pointer to the corresponding message string.
+.\"
+.SH "NAME ENCODING"
+Name encoding is a process that transforms the specified
+internationalized domain name to a certain string suitable for name
+resolution.
+For each label in a given domain name, the encoding processor performs:
+.\"
+.IP "(1) Convert to UTF-8 (IDN_LOCALCONV)"
+Convert the encoding of the given domain name from application's local
+encoding (e.g. ISO-8859-1) to UTF-8.
+Note that \fBlibidnkitlite\fR doesn't support this step.
+.\"
+.IP "(2) Delimiter mapping (IDN_DELIMMAP)"
+Map domain name delimiters to `.' (U+002E).
+The recoginzed delimiters are: U+3002 (ideographic full stop),
+U+FF0E (fullwidth full stop), U+FF61 (halfwidth ideographic full stop).
+.\"
+.IP "(3) Local mapping (IDN_LOCALMAP)"
+Apply character mapping whose rule is determined by the TLD of the name.
+.\"
+.IP "(4) NAMEPREP (IDN_NAMEPREP, IDN_UNASCHECK)"
+Perform name preparation (NAMEPREP), which is a standard process for
+name canonicalizaion of internationalized domain names.
+.br
+NAMEPREP consists of 5 steps:
+mapping, normalization, prohibited character check, bidirectional
+text check and unassigned codepoint check.
+The first four steps are done by IDN_NAMEPREP, and the last step is
+done by IDN_UNASCHECK.
+.\"
+.IP "(5) ASCII range character check (IDN_ASCCHECK)"
+Checks if the domain name contains non-LDH ASCII character (not
+alpha-numeric or hyphen), or it begins or end with hyphen.
+.\"
+.IP "(6) Convert to ACE (IDN_IDNCONV)"
+Convert the NAMEPREPed name to a special encoding designed for representing
+internationalized domain names.
+.br
+The encoding is also known as ACE (ASCII Compatible Encoding) since
+a string in the encoding is just like a traditional ASCII domain name
+consisting of only letters, numbers and hyphens.
+.\"
+.IP "(7) Label length check (IDN_LENCHECK)"
+For each label, check the number of characters in it.
+It must be in the range 1 to 63.
+.PP
+There are many configuration parameters for this process, such as the
+ACE or the local mapping rules. These parameters are read from the
+default idnkit's configuration file, \fBidn.conf\fR.
+See idn.conf(5) for details.
+.\"
+.SH "NAME DECODING"
+Name decoding is a reverse process of the name encoding.
+It transforms the specified
+internationalized domain name in a special encoding suitable for name
+resolution to the normal name string in the application's current codeset.
+However, name encoding and name decoding are not symmetric.
+.PP
+For each label in a given domain name, the decoding processor performs:
+.\"
+.IP "(1) Delimiter mapping (IDN_DELIMMAP)"
+Map domain name delimiters to `.' (U+002E).
+The recoginzed delimiters are: U+3002 (ideographic full stop),
+U+FF0E (fullwidth full stop), U+FF61 (halfwidth ideographic full stop).
+.\"
+.IP "(2) NAMEPREP (IDN_NAMEPREP, IDN_UNASCHECK)"
+Perform name preparation (NAMEPREP), which is a standard process for
+name canonicalizaion of internationalized domain names.
+.\"
+.IP "(3) Convert to UTF-8 (IDN_IDNCONV)"
+Convert the encoding of the given domain name from ACE to UTF-8.
+.\"
+.IP "(4) Round trip check (IDN_RTCHECK)"
+Encode the result of (3) using the ``NAME ENCODING'' scheme, and then
+compare it with the result of the step (2).
+If they are different, the check is failed.
+If IDN_UNASCHECK, IDN_ASCCHECK or both are specified, also they are
+done in the encoding processes.
+.\"
+.IP "(5) Convert to local encoding"
+Convert the result of (3) from UTF-8 to the application's local
+encoding (e.g. ISO-8859-1).
+Note that \fBlibidnkitlite\fR doesn't support this step.
+.PP
+If prohibited character check, unassigned codepoint check or
+bidirectional text check at step (2) is failed, or round trip check
+at step (4) is failed, the original input label is returned.
+.PP
+The configuration parameters for this process,
+are also read from the configuration file \fBidn.conf\fR.
+.\"
+.SH "IDN_DISABLE"
+If the \fBIDN_DISABLE\fR environ variable is defined at run-time,
+the libraries disable internationalized domain name support, by default.
+In this case, \fBidn_encodename\fR and \fBidn_decodename\fR don't
+encode/decode an input name, but instead they simply ouput a copy
+of the input name as the result of encoding/decoding.
+.PP
+If your application should always enable mulitilingual domain name
+support regardless of definition of \fBIDN_DISABLE\fR, call
+.RS 4
+.nf
+.ft CW
+idn_enable(1)
+.ft R
+.fi
+.RE
+.PP
+before performing encoding/decoding.
+.\"
+.SH "RETURN VALUES"
+Most of the API functions return values of type \fBidn_result_t\fR in
+order to indicate the status of the call.
+
+The following is a complete list of the status codes. Note that some
+of them are never returned by the functions described in this manual.
+.TP 15
+.SB idn_success
+Not an error. The call succeeded.
+.TP
+.SB idn_notfound
+Specified information does not exist.
+.TP
+.SB idn_invalid_encoding
+The encoding of the specified string is invalid.
+.TP
+.SB idn_invalid_syntax
+There is a syntax error in the configuration file.
+.TP
+.SB idn_invalid_name
+The specified name is not valid.
+.TP
+.SB idn_invalid_message
+The specified DNS message is not valid.
+.TP
+.SB idn_invalid_action
+The specified action contains invalid flags.
+.TP
+.SB idn_invalid_codepoint
+The specified Unicode code point value is not valid.
+.TP
+.SB idn_invalid_length
+The number of characters in an ACE label is not in the range 1 to 63.
+.TP
+.SB idn_buffer_overflow
+The specified buffer is too small to hold the result.
+.TP
+.SB idn_noentry
+The specified key does not exist in the hash table.
+.TP
+.SB idn_nomemory
+Memory allocation using malloc failed.
+.TP
+.SB idn_nofile
+The specified file could not be opened.
+.TP
+.SB idn_nomapping
+Some characters do not have the mapping to the target character set.
+.TP
+.SB idn_context_required
+Context information is required.
+.TP
+.SB idn_prohibited
+The specified string contains some prohibited characters.
+.TP
+.SB idn_failure
+Generic error which is not covered by the above codes.
+.\"
+.SH EXAMPLES
+To get the address of a internationalized domain name in the application's
+local codeset, use \fBidn_encodename\fR to convert the name to the format
+suitable for passing to resolver functions.
+.RS 4
+.nf
+.ft CW
+idn_result_t r;
+char ace_name[256];
+struct hostent *hp;
+
+\&...
+r = idn_encodename(IDN_ENCODE_APP, name, ace_name,
+ sizeof(ace_name));
+if (r != idn_success) {
+ fprintf(stderr, "idn_encodename failed: %s\en",
+ idn_result_tostring(r));
+ exit(1);
+}
+
+hp = gethostbyname(ace_name);
+\&...
+.ft R
+.fi
+.RE
+.PP
+To decode the internationalized domain name returned from a resolver function,
+use \fBidn_decodename\fR.
+.RS 4
+.nf
+.ft CW
+idn_result_t r;
+char local_name[256];
+struct hostent *hp;
+
+\&...
+hp = gethostbyname(name);
+r = idn_decodename(IDN_DECODE_APP, hp->h_name, local_name,
+ sizeof(local_name));
+if (r != idn_success) {
+ fprintf(stderr, "idn_decodename failed: %s\en",
+ idn_result_tostring(r));
+ exit(1);
+}
+printf("name: %s\en", local_name);
+\&...
+.ft R
+.fi
+.RE
+.\"
+.SH "SEE ALSO"
+idn.conf(5)
diff --git a/contrib/idn/idnkit-1.0-src/map/Makefile.in b/contrib/idn/idnkit-1.0-src/map/Makefile.in
new file mode 100644
index 0000000..5e52385
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/map/Makefile.in
@@ -0,0 +1,75 @@
+# $Id: Makefile.in,v 1.1.1.1 2003/06/04 00:27:55 marka Exp $
+#
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+top_builddir = ..
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+datadir = @datadir@
+mapdir = $(datadir)/idnkit
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+SHELL = @SHELL@
+
+MAPS = jp.map
+
+all:
+
+install:
+ $(MKINSTALLDIRS) $(DESTDIR)$(mapdir)
+ for map in $(MAPS); do \
+ $(INSTALL_DATA) $(srcdir)/$$map $(DESTDIR)$(mapdir)/$$map; \
+ done
+
+clean:
+ rm -f *~
+
+distclean: clean
+ rm -f Makefile
+
+test check:
diff --git a/contrib/idn/idnkit-1.0-src/map/jp.map b/contrib/idn/idnkit-1.0-src/map/jp.map
new file mode 100644
index 0000000..5deff1a
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/map/jp.map
@@ -0,0 +1,50 @@
+# $Id: jp.map,v 1.1.1.1 2003/06/04 00:27:55 marka Exp $
+# Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+#
+# Local map table for JP domain.
+#
+
+# version=1.0
+
+2212; FF0D
+309B; 3099
+309C; 309A
diff --git a/contrib/idn/idnkit-1.0-src/mkinstalldirs b/contrib/idn/idnkit-1.0-src/mkinstalldirs
new file mode 100755
index 0000000..946773d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.1.1.1 2003/06/04 00:25:33 marka Exp $
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/contrib/idn/idnkit-1.0-src/patch/bind9/bind-9.2.1-patch b/contrib/idn/idnkit-1.0-src/patch/bind9/bind-9.2.1-patch
new file mode 100644
index 0000000..7a8e3de
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/patch/bind9/bind-9.2.1-patch
@@ -0,0 +1,5900 @@
+IDN patch for bind-9.2.1
+========================
+
+
+This is a patch file for ISC BIND 9.2.1 to make it work with
+internationalized domain names. With this patch you'll get IDN-aware
+dig/host/nslookup.
+
+To apply this patch, you should go to the top directory of the BIND
+distribution (where you see `README' file), then invoke `patch'
+command like this:
+
+ % patch -p0 < this-file
+
+Then follow the instructions described in `README.idnkit' to compile
+and install.
+
+
+Index: README.idnkit
+diff -c /dev/null mdn/othersrc/bind9/README.idnkit:1.2
+*** README.idnkit Mon May 27 16:53:24 2002
+--- README.idnkit Tue Mar 26 16:35:05 2002
+***************
+*** 0 ****
+--- 1,113 ----
++
++ 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 exacutable 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 doens'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 argments, 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/jp/research/mdn/ 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 mdn-cmt@nic.ad.jp, respectively.
++
++
++ ; $Id: bind-9.2.1-patch,v 1.1.1.1 2003/06/04 00:27:30 marka Exp $
+Index: config.h.in
+diff -c mdn/othersrc/bind9/config.h.in:1.1.1.6 mdn/othersrc/bind9/config.h.in:1.12
+*** config.h.in Tue Nov 27 16:55:45 2001
+--- config.h.in Tue Mar 19 16:45:35 2002
+***************
+*** 141,146 ****
+--- 141,149 ----
+ /* define if you have strerror in the C library. */
+ #undef HAVE_STRERROR
+
++ /* Define if you have the setlocale function. */
++ #undef HAVE_SETLOCALE
++
+ /* Define if you have the <dlfcn.h> header file. */
+ #undef HAVE_DLFCN_H
+
+***************
+*** 150,155 ****
+--- 153,161 ----
+ /* Define if you have the <linux/capability.h> header file. */
+ #undef HAVE_LINUX_CAPABILITY_H
+
++ /* Define if you have the <locale.h> header file. */
++ #undef HAVE_LOCALE_H
++
+ /* Define if you have the <sys/prctl.h> header file. */
+ #undef HAVE_SYS_PRCTL_H
+
+***************
+*** 176,178 ****
+--- 182,188 ----
+
+ /* Define if you have the socket library (-lsocket). */
+ #undef HAVE_LIBSOCKET
++
++ /* define if idnkit support is to be included. */
++ #undef WITH_IDN
++
+Index: configure
+diff -c mdn/othersrc/bind9/configure:1.1.1.9 mdn/othersrc/bind9/configure:1.15
+*** configure Wed May 22 17:14:53 2002
+--- configure Mon May 27 12:10:14 2002
+***************
+*** 369,374 ****
+--- 369,382 ----
+ --with-kame[=PATH] use Kame IPv6 [default path /usr/local/v6]"
+ ac_help="$ac_help
+ --disable-linux-caps disable linux capabilities"
++ ac_help="$ac_help
++ --with-idn[=MPREFIX] enable IDN support using idnkit [default PREFIX]"
++ ac_help="$ac_help
++ --with-libiconv[=IPREFIX] GNU libiconv are in IPREFIX [default PREFIX]"
++ ac_help="$ac_help
++ --with-iconv[=LIBSPEC] specify iconv library [default -liconv]"
++ ac_help="$ac_help
++ --with-idnlib=ARG specify libidnkit"
+
+ # Initialize some variables set by options.
+ # The variables have the same names as the options, with
+***************
+*** 911,917 ****
+ fi
+
+ echo $ac_n "checking host system type""... $ac_c" 1>&6
+! echo "configure:915: checking host system type" >&5
+
+ host_alias=$host
+ case "$host_alias" in
+--- 919,925 ----
+ fi
+
+ echo $ac_n "checking host system type""... $ac_c" 1>&6
+! echo "configure:923: checking host system type" >&5
+
+ host_alias=$host
+ case "$host_alias" in
+***************
+*** 933,939 ****
+
+
+ echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+! echo "configure:937: checking whether ${MAKE-make} sets \${MAKE}" >&5
+ set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 941,947 ----
+
+
+ echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+! echo "configure:945: checking whether ${MAKE-make} sets \${MAKE}" >&5
+ set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 962,968 ****
+ # Extract the first word of "ranlib", so it can be a program name with args.
+ set dummy ranlib; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:966: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 970,976 ----
+ # Extract the first word of "ranlib", so it can be a program name with args.
+ set dummy ranlib; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:974: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 1001,1007 ****
+ # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+ # ./install, which can be erroneously created by make from ./install.sh.
+ echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+! echo "configure:1005: checking for a BSD compatible install" >&5
+ if test -z "$INSTALL"; then
+ if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 1009,1015 ----
+ # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+ # ./install, which can be erroneously created by make from ./install.sh.
+ echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+! echo "configure:1013: checking for a BSD compatible install" >&5
+ if test -z "$INSTALL"; then
+ if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 1062,1068 ****
+ # Extract the first word of "ar", so it can be a program name with args.
+ set dummy ar; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1066: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 1070,1076 ----
+ # Extract the first word of "ar", so it can be a program name with args.
+ set dummy ar; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1074: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 1121,1127 ****
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1125: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_ETAGS'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 1129,1135 ----
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1133: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_ETAGS'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 1163,1169 ****
+ #
+ if test "X$ETAGS" != "X"; then
+ echo $ac_n "checking for Exuberant Ctags etags""... $ac_c" 1>&6
+! echo "configure:1167: checking for Exuberant Ctags etags" >&5
+ if $ETAGS --version 2>&1 | grep 'Exuberant Ctags' >/dev/null 2>&1; then
+ echo "$ac_t""yes" 1>&6
+ ETAGS="$ETAGS -L"
+--- 1171,1177 ----
+ #
+ if test "X$ETAGS" != "X"; then
+ echo $ac_n "checking for Exuberant Ctags etags""... $ac_c" 1>&6
+! echo "configure:1175: checking for Exuberant Ctags etags" >&5
+ if $ETAGS --version 2>&1 | grep 'Exuberant Ctags' >/dev/null 2>&1; then
+ echo "$ac_t""yes" 1>&6
+ ETAGS="$ETAGS -L"
+***************
+*** 1181,1187 ****
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1185: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 1189,1195 ----
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1193: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 1328,1334 ****
+ # Extract the first word of "gcc", so it can be a program name with args.
+ set dummy gcc; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1332: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 1336,1342 ----
+ # Extract the first word of "gcc", so it can be a program name with args.
+ set dummy gcc; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1340: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 1358,1364 ****
+ # Extract the first word of "cc", so it can be a program name with args.
+ set dummy cc; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1362: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 1366,1372 ----
+ # Extract the first word of "cc", so it can be a program name with args.
+ set dummy cc; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1370: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 1409,1415 ****
+ # Extract the first word of "cl", so it can be a program name with args.
+ set dummy cl; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1413: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 1417,1423 ----
+ # Extract the first word of "cl", so it can be a program name with args.
+ set dummy cl; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:1421: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 1441,1447 ****
+ fi
+
+ echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+! echo "configure:1445: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ ac_ext=c
+ # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+--- 1449,1455 ----
+ fi
+
+ echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+! echo "configure:1453: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ ac_ext=c
+ # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+***************
+*** 1452,1463 ****
+
+ cat > conftest.$ac_ext << EOF
+
+! #line 1456 "configure"
+ #include "confdefs.h"
+
+ main(){return(0);}
+ EOF
+! if { (eval echo configure:1461: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+--- 1460,1471 ----
+
+ cat > conftest.$ac_ext << EOF
+
+! #line 1464 "configure"
+ #include "confdefs.h"
+
+ main(){return(0);}
+ EOF
+! if { (eval echo configure:1469: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+***************
+*** 1483,1494 ****
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+ fi
+ echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+! echo "configure:1487: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+ echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+ cross_compiling=$ac_cv_prog_cc_cross
+
+ echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+! echo "configure:1492: checking whether we are using GNU C" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 1491,1502 ----
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+ fi
+ echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+! echo "configure:1495: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+ echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+ cross_compiling=$ac_cv_prog_cc_cross
+
+ echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+! echo "configure:1500: checking whether we are using GNU C" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 1497,1503 ****
+ yes;
+ #endif
+ EOF
+! if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1501: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+ else
+ ac_cv_prog_gcc=no
+--- 1505,1511 ----
+ yes;
+ #endif
+ EOF
+! if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1509: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+ else
+ ac_cv_prog_gcc=no
+***************
+*** 1516,1522 ****
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+! echo "configure:1520: checking whether ${CC-cc} accepts -g" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 1524,1530 ----
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+! echo "configure:1528: checking whether ${CC-cc} accepts -g" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 1549,1555 ****
+
+
+ echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+! echo "configure:1553: checking how to run the C preprocessor" >&5
+ # On Suns, sometimes $CPP names a directory.
+ if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+--- 1557,1563 ----
+
+
+ echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+! echo "configure:1561: checking how to run the C preprocessor" >&5
+ # On Suns, sometimes $CPP names a directory.
+ if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+***************
+*** 1564,1576 ****
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+! #line 1568 "configure"
+ #include "confdefs.h"
+ #include <assert.h>
+ Syntax Error
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:1574: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ :
+--- 1572,1584 ----
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+! #line 1576 "configure"
+ #include "confdefs.h"
+ #include <assert.h>
+ Syntax Error
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:1582: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ :
+***************
+*** 1581,1593 ****
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+! #line 1585 "configure"
+ #include "confdefs.h"
+ #include <assert.h>
+ Syntax Error
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:1591: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ :
+--- 1589,1601 ----
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+! #line 1593 "configure"
+ #include "confdefs.h"
+ #include <assert.h>
+ Syntax Error
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:1599: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ :
+***************
+*** 1598,1610 ****
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+! #line 1602 "configure"
+ #include "confdefs.h"
+ #include <assert.h>
+ Syntax Error
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:1608: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ :
+--- 1606,1618 ----
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+! #line 1610 "configure"
+ #include "confdefs.h"
+ #include <assert.h>
+ Syntax Error
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:1616: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ :
+***************
+*** 1629,1640 ****
+ echo "$ac_t""$CPP" 1>&6
+
+ echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+! echo "configure:1633: checking for ANSI C header files" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1638 "configure"
+ #include "confdefs.h"
+ #include <stdlib.h>
+ #include <stdarg.h>
+--- 1637,1648 ----
+ echo "$ac_t""$CPP" 1>&6
+
+ echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+! echo "configure:1641: checking for ANSI C header files" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1646 "configure"
+ #include "confdefs.h"
+ #include <stdlib.h>
+ #include <stdarg.h>
+***************
+*** 1642,1648 ****
+ #include <float.h>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:1646: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+--- 1650,1656 ----
+ #include <float.h>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:1654: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+***************
+*** 1659,1665 ****
+ if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat > conftest.$ac_ext <<EOF
+! #line 1663 "configure"
+ #include "confdefs.h"
+ #include <string.h>
+ EOF
+--- 1667,1673 ----
+ if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat > conftest.$ac_ext <<EOF
+! #line 1671 "configure"
+ #include "confdefs.h"
+ #include <string.h>
+ EOF
+***************
+*** 1677,1683 ****
+ if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat > conftest.$ac_ext <<EOF
+! #line 1681 "configure"
+ #include "confdefs.h"
+ #include <stdlib.h>
+ EOF
+--- 1685,1691 ----
+ if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat > conftest.$ac_ext <<EOF
+! #line 1689 "configure"
+ #include "confdefs.h"
+ #include <stdlib.h>
+ EOF
+***************
+*** 1698,1704 ****
+ :
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1702 "configure"
+ #include "confdefs.h"
+ #include <ctype.h>
+ #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+--- 1706,1712 ----
+ :
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1710 "configure"
+ #include "confdefs.h"
+ #include <ctype.h>
+ #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+***************
+*** 1709,1715 ****
+ exit (0); }
+
+ EOF
+! if { (eval echo configure:1713: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ :
+ else
+--- 1717,1723 ----
+ exit (0); }
+
+ EOF
+! if { (eval echo configure:1721: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ :
+ else
+***************
+*** 1737,1753 ****
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+! echo "configure:1741: checking for $ac_hdr" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1746 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:1751: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+--- 1745,1761 ----
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+! echo "configure:1749: checking for $ac_hdr" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1754 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:1759: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+***************
+*** 1775,1786 ****
+
+
+ echo $ac_n "checking for working const""... $ac_c" 1>&6
+! echo "configure:1779: checking for working const" >&5
+ if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1784 "configure"
+ #include "confdefs.h"
+
+ int main() {
+--- 1783,1794 ----
+
+
+ echo $ac_n "checking for working const""... $ac_c" 1>&6
+! echo "configure:1787: checking for working const" >&5
+ if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1792 "configure"
+ #include "confdefs.h"
+
+ int main() {
+***************
+*** 1829,1835 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:1833: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+ else
+--- 1837,1843 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:1841: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+ else
+***************
+*** 1850,1870 ****
+ fi
+
+ echo $ac_n "checking for inline""... $ac_c" 1>&6
+! echo "configure:1854: checking for inline" >&5
+ if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ ac_cv_c_inline=no
+ for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+! #line 1861 "configure"
+ #include "confdefs.h"
+
+ int main() {
+ } $ac_kw foo() {
+ ; return 0; }
+ EOF
+! if { (eval echo configure:1868: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+ else
+--- 1858,1878 ----
+ fi
+
+ echo $ac_n "checking for inline""... $ac_c" 1>&6
+! echo "configure:1862: checking for inline" >&5
+ if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ ac_cv_c_inline=no
+ for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+! #line 1869 "configure"
+ #include "confdefs.h"
+
+ int main() {
+ } $ac_kw foo() {
+ ; return 0; }
+ EOF
+! if { (eval echo configure:1876: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+ else
+***************
+*** 1890,1901 ****
+ esac
+
+ echo $ac_n "checking for sysctlbyname""... $ac_c" 1>&6
+! echo "configure:1894: checking for sysctlbyname" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_sysctlbyname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1899 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char sysctlbyname(); below. */
+--- 1898,1909 ----
+ esac
+
+ echo $ac_n "checking for sysctlbyname""... $ac_c" 1>&6
+! echo "configure:1902: checking for sysctlbyname" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_sysctlbyname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1907 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char sysctlbyname(); below. */
+***************
+*** 1918,1924 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:1922: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_sysctlbyname=yes"
+ else
+--- 1926,1932 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:1930: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_sysctlbyname=yes"
+ else
+***************
+*** 1946,1954 ****
+ # is reported to not support "static inline" (RT #1212).
+ #
+ echo $ac_n "checking for static inline breakage""... $ac_c" 1>&6
+! echo "configure:1950: checking for static inline breakage" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 1952 "configure"
+ #include "confdefs.h"
+
+ int main() {
+--- 1954,1962 ----
+ # is reported to not support "static inline" (RT #1212).
+ #
+ echo $ac_n "checking for static inline breakage""... $ac_c" 1>&6
+! echo "configure:1958: checking for static inline breakage" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 1960 "configure"
+ #include "confdefs.h"
+
+ int main() {
+***************
+*** 1965,1971 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:1969: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ else
+--- 1973,1979 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:1977: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ else
+***************
+*** 1981,1992 ****
+ rm -f conftest*
+
+ echo $ac_n "checking for size_t""... $ac_c" 1>&6
+! echo "configure:1985: checking for size_t" >&5
+ if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1990 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #if STDC_HEADERS
+--- 1989,2000 ----
+ rm -f conftest*
+
+ echo $ac_n "checking for size_t""... $ac_c" 1>&6
+! echo "configure:1993: checking for size_t" >&5
+ if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 1998 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #if STDC_HEADERS
+***************
+*** 2014,2025 ****
+ fi
+
+ echo $ac_n "checking for ssize_t""... $ac_c" 1>&6
+! echo "configure:2018: checking for ssize_t" >&5
+ if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 2023 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #if STDC_HEADERS
+--- 2022,2033 ----
+ fi
+
+ echo $ac_n "checking for ssize_t""... $ac_c" 1>&6
+! echo "configure:2026: checking for ssize_t" >&5
+ if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 2031 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #if STDC_HEADERS
+***************
+*** 2047,2058 ****
+ fi
+
+ echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+! echo "configure:2051: checking whether time.h and sys/time.h may both be included" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 2056 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #include <sys/time.h>
+--- 2055,2066 ----
+ fi
+
+ echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+! echo "configure:2059: checking whether time.h and sys/time.h may both be included" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 2064 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #include <sys/time.h>
+***************
+*** 2061,2067 ****
+ struct tm *tp;
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2065: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+ else
+--- 2069,2075 ----
+ struct tm *tp;
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2073: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+ else
+***************
+*** 2082,2097 ****
+ fi
+
+ echo $ac_n "checking for long long""... $ac_c" 1>&6
+! echo "configure:2086: checking for long long" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 2088 "configure"
+ #include "confdefs.h"
+
+ int main() {
+ long long i = 0; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2095: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_HAVELONGLONG="#define ISC_PLATFORM_HAVELONGLONG 1"
+--- 2090,2105 ----
+ fi
+
+ echo $ac_n "checking for long long""... $ac_c" 1>&6
+! echo "configure:2094: checking for long long" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 2096 "configure"
+ #include "confdefs.h"
+
+ int main() {
+ long long i = 0; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2103: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_HAVELONGLONG="#define ISC_PLATFORM_HAVELONGLONG 1"
+***************
+*** 2111,2119 ****
+ case $ac_cv_header_unistd_h in
+ yes)
+ echo $ac_n "checking if unistd.h defines fd_set""... $ac_c" 1>&6
+! echo "configure:2115: checking if unistd.h defines fd_set" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 2117 "configure"
+ #include "confdefs.h"
+
+ #include <unistd.h>
+--- 2119,2127 ----
+ case $ac_cv_header_unistd_h in
+ yes)
+ echo $ac_n "checking if unistd.h defines fd_set""... $ac_c" 1>&6
+! echo "configure:2123: checking if unistd.h defines fd_set" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 2125 "configure"
+ #include "confdefs.h"
+
+ #include <unistd.h>
+***************
+*** 2121,2127 ****
+ fd_set read_set; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2125: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDSYSSELECTH="#undef ISC_PLATFORM_NEEDSYSSELECTH"
+--- 2129,2135 ----
+ fd_set read_set; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2133: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDSYSSELECTH="#undef ISC_PLATFORM_NEEDSYSSELECTH"
+***************
+*** 2163,2176 ****
+ # Find the machine's endian flavor.
+ #
+ echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
+! echo "configure:2167: checking whether byte ordering is bigendian" >&5
+ if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ ac_cv_c_bigendian=unknown
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat > conftest.$ac_ext <<EOF
+! #line 2174 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #include <sys/param.h>
+--- 2171,2184 ----
+ # Find the machine's endian flavor.
+ #
+ echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
+! echo "configure:2175: checking whether byte ordering is bigendian" >&5
+ if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ ac_cv_c_bigendian=unknown
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat > conftest.$ac_ext <<EOF
+! #line 2182 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #include <sys/param.h>
+***************
+*** 2181,2191 ****
+ #endif
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2185: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat > conftest.$ac_ext <<EOF
+! #line 2189 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #include <sys/param.h>
+--- 2189,2199 ----
+ #endif
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2193: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat > conftest.$ac_ext <<EOF
+! #line 2197 "configure"
+ #include "confdefs.h"
+ #include <sys/types.h>
+ #include <sys/param.h>
+***************
+*** 2196,2202 ****
+ #endif
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2200: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_bigendian=yes
+ else
+--- 2204,2210 ----
+ #endif
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2208: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_bigendian=yes
+ else
+***************
+*** 2216,2222 ****
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 2220 "configure"
+ #include "confdefs.h"
+ main () {
+ /* Are we little or big endian? From Harbison&Steele. */
+--- 2224,2230 ----
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 2228 "configure"
+ #include "confdefs.h"
+ main () {
+ /* Are we little or big endian? From Harbison&Steele. */
+***************
+*** 2229,2235 ****
+ exit (u.c[sizeof (long) - 1] == 1);
+ }
+ EOF
+! if { (eval echo configure:2233: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ ac_cv_c_bigendian=no
+ else
+--- 2237,2243 ----
+ exit (u.c[sizeof (long) - 1] == 1);
+ }
+ EOF
+! if { (eval echo configure:2241: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ ac_cv_c_bigendian=no
+ else
+***************
+*** 2257,2263 ****
+ # was --with-openssl specified?
+ #
+ echo $ac_n "checking for OpenSSL library""... $ac_c" 1>&6
+! echo "configure:2261: checking for OpenSSL library" >&5
+ # Check whether --with-openssl or --without-openssl was given.
+ if test "${with_openssl+set}" = set; then
+ withval="$with_openssl"
+--- 2265,2271 ----
+ # was --with-openssl specified?
+ #
+ echo $ac_n "checking for OpenSSL library""... $ac_c" 1>&6
+! echo "configure:2269: checking for OpenSSL library" >&5
+ # Check whether --with-openssl or --without-openssl was given.
+ if test "${with_openssl+set}" = set; then
+ withval="$with_openssl"
+***************
+*** 2298,2304 ****
+ echo "$ac_t""using openssl from $use_openssl/lib and $use_openssl/include" 1>&6
+
+ echo $ac_n "checking OpenSSL library version""... $ac_c" 1>&6
+! echo "configure:2302: checking OpenSSL library version" >&5
+ saved_cflags="$CFLAGS"
+ saved_libs="$LIBS"
+ CFLAGS="$CFLAGS $DST_OPENSSL_INC"
+--- 2306,2312 ----
+ echo "$ac_t""using openssl from $use_openssl/lib and $use_openssl/include" 1>&6
+
+ echo $ac_n "checking OpenSSL library version""... $ac_c" 1>&6
+! echo "configure:2310: checking OpenSSL library version" >&5
+ saved_cflags="$CFLAGS"
+ saved_libs="$LIBS"
+ CFLAGS="$CFLAGS $DST_OPENSSL_INC"
+***************
+*** 2307,2313 ****
+ echo "$ac_t""assuming target platform has compatible version" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 2311 "configure"
+ #include "confdefs.h"
+
+ #include <stdio.h>
+--- 2315,2321 ----
+ echo "$ac_t""assuming target platform has compatible version" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 2319 "configure"
+ #include "confdefs.h"
+
+ #include <stdio.h>
+***************
+*** 2322,2328 ****
+ }
+
+ EOF
+! if { (eval echo configure:2326: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""ok" 1>&6
+ else
+--- 2330,2336 ----
+ }
+
+ EOF
+! if { (eval echo configure:2334: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""ok" 1>&6
+ else
+***************
+*** 2387,2393 ****
+ # was --with-randomdev specified?
+ #
+ echo $ac_n "checking for random device""... $ac_c" 1>&6
+! echo "configure:2391: checking for random device" >&5
+ # Check whether --with-randomdev or --without-randomdev was given.
+ if test "${with_randomdev+set}" = set; then
+ withval="$with_randomdev"
+--- 2395,2401 ----
+ # was --with-randomdev specified?
+ #
+ echo $ac_n "checking for random device""... $ac_c" 1>&6
+! echo "configure:2399: checking for random device" >&5
+ # Check whether --with-randomdev or --without-randomdev was given.
+ if test "${with_randomdev+set}" = set; then
+ withval="$with_randomdev"
+***************
+*** 2411,2417 ****
+
+ ac_safe=`echo "$devrandom" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $devrandom""... $ac_c" 1>&6
+! echo "configure:2415: checking for $devrandom" >&5
+ if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 2419,2425 ----
+
+ ac_safe=`echo "$devrandom" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $devrandom""... $ac_c" 1>&6
+! echo "configure:2423: checking for $devrandom" >&5
+ if eval "test \"`echo '$''{'ac_cv_file_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 2463,2469 ****
+ #
+
+ echo $ac_n "checking whether to build with thread support""... $ac_c" 1>&6
+! echo "configure:2467: checking whether to build with thread support" >&5
+
+ case $host in
+ *-dec-osf*)
+--- 2471,2477 ----
+ #
+
+ echo $ac_n "checking whether to build with thread support""... $ac_c" 1>&6
+! echo "configure:2475: checking whether to build with thread support" >&5
+
+ case $host in
+ *-dec-osf*)
+***************
+*** 2551,2557 ****
+ # experiment with it.
+ CC="gcc"
+ echo $ac_n "checking which NetBSD thread library to use""... $ac_c" 1>&6
+! echo "configure:2555: checking which NetBSD thread library to use" >&5
+
+ # Check whether --with-ptl2 or --without-ptl2 was given.
+ if test "${with_ptl2+set}" = set; then
+--- 2559,2565 ----
+ # experiment with it.
+ CC="gcc"
+ echo $ac_n "checking which NetBSD thread library to use""... $ac_c" 1>&6
+! echo "configure:2563: checking which NetBSD thread library to use" >&5
+
+ # Check whether --with-ptl2 or --without-ptl2 was given.
+ if test "${with_ptl2+set}" = set; then
+***************
+*** 2590,2596 ****
+ ;;
+ *)
+ echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
+! echo "configure:2594: checking for pthread_create in -lpthread" >&5
+ ac_lib_var=`echo pthread'_'pthread_create | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 2598,2604 ----
+ ;;
+ *)
+ echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
+! echo "configure:2602: checking for pthread_create in -lpthread" >&5
+ ac_lib_var=`echo pthread'_'pthread_create | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 2598,2604 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2602 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 2606,2612 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2610 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 2609,2615 ****
+ pthread_create()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2613: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 2617,2623 ----
+ pthread_create()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2621: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 2635,2641 ****
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for __pthread_create in -lpthread""... $ac_c" 1>&6
+! echo "configure:2639: checking for __pthread_create in -lpthread" >&5
+ ac_lib_var=`echo pthread'_'__pthread_create | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 2643,2649 ----
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for __pthread_create in -lpthread""... $ac_c" 1>&6
+! echo "configure:2647: checking for __pthread_create in -lpthread" >&5
+ ac_lib_var=`echo pthread'_'__pthread_create | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 2643,2649 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2647 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 2651,2657 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2655 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 2654,2660 ****
+ __pthread_create()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 2662,2668 ----
+ __pthread_create()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2666: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 2680,2686 ****
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for __pthread_create_system in -lpthread""... $ac_c" 1>&6
+! echo "configure:2684: checking for __pthread_create_system in -lpthread" >&5
+ ac_lib_var=`echo pthread'_'__pthread_create_system | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 2688,2694 ----
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for __pthread_create_system in -lpthread""... $ac_c" 1>&6
+! echo "configure:2692: checking for __pthread_create_system in -lpthread" >&5
+ ac_lib_var=`echo pthread'_'__pthread_create_system | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 2688,2694 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2692 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 2696,2702 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2700 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 2699,2705 ****
+ __pthread_create_system()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2703: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 2707,2713 ----
+ __pthread_create_system()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2711: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 2725,2731 ****
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6
+! echo "configure:2729: checking for pthread_create in -lc_r" >&5
+ ac_lib_var=`echo c_r'_'pthread_create | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 2733,2739 ----
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for pthread_create in -lc_r""... $ac_c" 1>&6
+! echo "configure:2737: checking for pthread_create in -lc_r" >&5
+ ac_lib_var=`echo c_r'_'pthread_create | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 2733,2739 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lc_r $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2737 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 2741,2747 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lc_r $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2745 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 2744,2750 ****
+ pthread_create()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2748: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 2752,2758 ----
+ pthread_create()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2756: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 2770,2776 ****
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for pthread_create in -lc""... $ac_c" 1>&6
+! echo "configure:2774: checking for pthread_create in -lc" >&5
+ ac_lib_var=`echo c'_'pthread_create | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 2778,2784 ----
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for pthread_create in -lc""... $ac_c" 1>&6
+! echo "configure:2782: checking for pthread_create in -lc" >&5
+ ac_lib_var=`echo c'_'pthread_create | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 2778,2784 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lc $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2782 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 2786,2792 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lc $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2790 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 2789,2795 ****
+ pthread_create()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2793: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 2797,2803 ----
+ pthread_create()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2801: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 2835,2841 ****
+ # We'd like to use sigwait() too
+ #
+ echo $ac_n "checking for sigwait in -lc""... $ac_c" 1>&6
+! echo "configure:2839: checking for sigwait in -lc" >&5
+ ac_lib_var=`echo c'_'sigwait | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 2843,2849 ----
+ # We'd like to use sigwait() too
+ #
+ echo $ac_n "checking for sigwait in -lc""... $ac_c" 1>&6
+! echo "configure:2847: checking for sigwait in -lc" >&5
+ ac_lib_var=`echo c'_'sigwait | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 2843,2849 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lc $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2847 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 2851,2857 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lc $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2855 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 2854,2860 ****
+ sigwait()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2858: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 2862,2868 ----
+ sigwait()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2866: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 2876,2882 ****
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for sigwait in -lpthread""... $ac_c" 1>&6
+! echo "configure:2880: checking for sigwait in -lpthread" >&5
+ ac_lib_var=`echo pthread'_'sigwait | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 2884,2890 ----
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for sigwait in -lpthread""... $ac_c" 1>&6
+! echo "configure:2888: checking for sigwait in -lpthread" >&5
+ ac_lib_var=`echo pthread'_'sigwait | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 2884,2890 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2888 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 2892,2898 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2896 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 2895,2901 ****
+ sigwait()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2899: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 2903,2909 ----
+ sigwait()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2907: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 2917,2923 ****
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for _Psigwait in -lpthread""... $ac_c" 1>&6
+! echo "configure:2921: checking for _Psigwait in -lpthread" >&5
+ ac_lib_var=`echo pthread'_'_Psigwait | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 2925,2931 ----
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for _Psigwait in -lpthread""... $ac_c" 1>&6
+! echo "configure:2929: checking for _Psigwait in -lpthread" >&5
+ ac_lib_var=`echo pthread'_'_Psigwait | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 2925,2931 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2929 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 2933,2939 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 2937 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 2936,2942 ****
+ _Psigwait()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 2944,2950 ----
+ _Psigwait()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2948: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 2966,2977 ****
+
+
+ echo $ac_n "checking for pthread_attr_getstacksize""... $ac_c" 1>&6
+! echo "configure:2970: checking for pthread_attr_getstacksize" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_pthread_attr_getstacksize'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 2975 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char pthread_attr_getstacksize(); below. */
+--- 2974,2985 ----
+
+
+ echo $ac_n "checking for pthread_attr_getstacksize""... $ac_c" 1>&6
+! echo "configure:2978: checking for pthread_attr_getstacksize" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_pthread_attr_getstacksize'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 2983 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char pthread_attr_getstacksize(); below. */
+***************
+*** 2994,3000 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:2998: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_pthread_attr_getstacksize=yes"
+ else
+--- 3002,3008 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3006: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_pthread_attr_getstacksize=yes"
+ else
+***************
+*** 3026,3032 ****
+ #
+ *-freebsd*)
+ echo $ac_n "checking for sigwait in -lc_r""... $ac_c" 1>&6
+! echo "configure:3030: checking for sigwait in -lc_r" >&5
+ ac_lib_var=`echo c_r'_'sigwait | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 3034,3040 ----
+ #
+ *-freebsd*)
+ echo $ac_n "checking for sigwait in -lc_r""... $ac_c" 1>&6
+! echo "configure:3038: checking for sigwait in -lc_r" >&5
+ ac_lib_var=`echo c_r'_'sigwait | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 3034,3040 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lc_r $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 3038 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 3042,3048 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lc_r $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 3046 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 3045,3051 ****
+ sigwait()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3049: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 3053,3059 ----
+ sigwait()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3057: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 3100,3111 ****
+ EOF
+
+ echo $ac_n "checking for pthread_setconcurrency""... $ac_c" 1>&6
+! echo "configure:3104: checking for pthread_setconcurrency" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_pthread_setconcurrency'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3109 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char pthread_setconcurrency(); below. */
+--- 3108,3119 ----
+ EOF
+
+ echo $ac_n "checking for pthread_setconcurrency""... $ac_c" 1>&6
+! echo "configure:3112: checking for pthread_setconcurrency" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_pthread_setconcurrency'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3117 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char pthread_setconcurrency(); below. */
+***************
+*** 3128,3134 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3132: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_pthread_setconcurrency=yes"
+ else
+--- 3136,3142 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3140: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_pthread_setconcurrency=yes"
+ else
+***************
+*** 3166,3177 ****
+ # Look for sysconf to allow detection of the number of processors.
+ #
+ echo $ac_n "checking for sysconf""... $ac_c" 1>&6
+! echo "configure:3170: checking for sysconf" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_sysconf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3175 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char sysconf(); below. */
+--- 3174,3185 ----
+ # Look for sysconf to allow detection of the number of processors.
+ #
+ echo $ac_n "checking for sysconf""... $ac_c" 1>&6
+! echo "configure:3178: checking for sysconf" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_sysconf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3183 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char sysconf(); below. */
+***************
+*** 3194,3200 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3198: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_sysconf=yes"
+ else
+--- 3202,3208 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3206: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_sysconf=yes"
+ else
+***************
+*** 3275,3286 ****
+ # be defined.
+ #
+ echo $ac_n "checking for flockfile""... $ac_c" 1>&6
+! echo "configure:3279: checking for flockfile" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_flockfile'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3284 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char flockfile(); below. */
+--- 3283,3294 ----
+ # be defined.
+ #
+ echo $ac_n "checking for flockfile""... $ac_c" 1>&6
+! echo "configure:3287: checking for flockfile" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_flockfile'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3292 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char flockfile(); below. */
+***************
+*** 3303,3309 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3307: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_flockfile=yes"
+ else
+--- 3311,3317 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_flockfile=yes"
+ else
+***************
+*** 3326,3337 ****
+ fi
+
+ echo $ac_n "checking for getc_unlocked""... $ac_c" 1>&6
+! echo "configure:3330: checking for getc_unlocked" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_getc_unlocked'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3335 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getc_unlocked(); below. */
+--- 3334,3345 ----
+ fi
+
+ echo $ac_n "checking for getc_unlocked""... $ac_c" 1>&6
+! echo "configure:3338: checking for getc_unlocked" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_getc_unlocked'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3343 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getc_unlocked(); below. */
+***************
+*** 3354,3360 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3358: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_getc_unlocked=yes"
+ else
+--- 3362,3368 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3366: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_getc_unlocked=yes"
+ else
+***************
+*** 3381,3387 ****
+ # Indicate what the final decision was regarding threads.
+ #
+ echo $ac_n "checking whether to build with threads""... $ac_c" 1>&6
+! echo "configure:3385: checking whether to build with threads" >&5
+ if $use_threads; then
+ echo "$ac_t""yes" 1>&6
+ else
+--- 3389,3395 ----
+ # Indicate what the final decision was regarding threads.
+ #
+ echo $ac_n "checking whether to build with threads""... $ac_c" 1>&6
+! echo "configure:3393: checking whether to build with threads" >&5
+ if $use_threads; then
+ echo "$ac_t""yes" 1>&6
+ else
+***************
+*** 3457,3468 ****
+ # NLS
+ #
+ echo $ac_n "checking for catgets""... $ac_c" 1>&6
+! echo "configure:3461: checking for catgets" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_catgets'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3466 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char catgets(); below. */
+--- 3465,3476 ----
+ # NLS
+ #
+ echo $ac_n "checking for catgets""... $ac_c" 1>&6
+! echo "configure:3469: checking for catgets" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_catgets'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3474 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char catgets(); below. */
+***************
+*** 3485,3491 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3489: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_catgets=yes"
+ else
+--- 3493,3499 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_catgets=yes"
+ else
+***************
+*** 3523,3529 ****
+ ;;
+ *)
+ echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+! echo "configure:3527: checking for socket in -lsocket" >&5
+ ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 3531,3537 ----
+ ;;
+ *)
+ echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+! echo "configure:3535: checking for socket in -lsocket" >&5
+ ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 3531,3537 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lsocket $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 3535 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 3539,3545 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lsocket $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 3543 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 3542,3548 ****
+ socket()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3546: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 3550,3556 ----
+ socket()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3554: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 3570,3576 ****
+ fi
+
+ echo $ac_n "checking for inet_ntoa in -lnsl""... $ac_c" 1>&6
+! echo "configure:3574: checking for inet_ntoa in -lnsl" >&5
+ ac_lib_var=`echo nsl'_'inet_ntoa | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 3578,3584 ----
+ fi
+
+ echo $ac_n "checking for inet_ntoa in -lnsl""... $ac_c" 1>&6
+! echo "configure:3582: checking for inet_ntoa in -lnsl" >&5
+ ac_lib_var=`echo nsl'_'inet_ntoa | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 3578,3584 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lnsl $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 3582 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 3586,3592 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lnsl $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 3590 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 3589,3595 ****
+ inet_ntoa()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3593: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 3597,3603 ----
+ inet_ntoa()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3601: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 3623,3629 ****
+ # Purify support
+ #
+ echo $ac_n "checking whether to use purify""... $ac_c" 1>&6
+! echo "configure:3627: checking whether to use purify" >&5
+ # Check whether --with-purify or --without-purify was given.
+ if test "${with_purify+set}" = set; then
+ withval="$with_purify"
+--- 3631,3637 ----
+ # Purify support
+ #
+ echo $ac_n "checking whether to use purify""... $ac_c" 1>&6
+! echo "configure:3635: checking whether to use purify" >&5
+ # Check whether --with-purify or --without-purify was given.
+ if test "${with_purify+set}" = set; then
+ withval="$with_purify"
+***************
+*** 3640,3646 ****
+ # Extract the first word of "purify", so it can be a program name with args.
+ set dummy purify; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:3644: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_purify_path'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 3648,3654 ----
+ # Extract the first word of "purify", so it can be a program name with args.
+ set dummy purify; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:3652: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_purify_path'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 3717,3728 ****
+ case $use_libtool in
+ yes)
+ echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+! echo "configure:3721: checking for Cygwin environment" >&5
+ if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3726 "configure"
+ #include "confdefs.h"
+
+ int main() {
+--- 3725,3736 ----
+ case $use_libtool in
+ yes)
+ echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+! echo "configure:3729: checking for Cygwin environment" >&5
+ if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3734 "configure"
+ #include "confdefs.h"
+
+ int main() {
+***************
+*** 3733,3739 ****
+ return __CYGWIN__;
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3737: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_cygwin=yes
+ else
+--- 3741,3747 ----
+ return __CYGWIN__;
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3745: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_cygwin=yes
+ else
+***************
+*** 3750,3768 ****
+ CYGWIN=
+ test "$ac_cv_cygwin" = yes && CYGWIN=yes
+ echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+! echo "configure:3754: checking for mingw32 environment" >&5
+ if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3759 "configure"
+ #include "confdefs.h"
+
+ int main() {
+ return __MINGW32__;
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3766: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_mingw32=yes
+ else
+--- 3758,3776 ----
+ CYGWIN=
+ test "$ac_cv_cygwin" = yes && CYGWIN=yes
+ echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+! echo "configure:3762: checking for mingw32 environment" >&5
+ if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 3767 "configure"
+ #include "confdefs.h"
+
+ int main() {
+ return __MINGW32__;
+ ; return 0; }
+ EOF
+! if { (eval echo configure:3774: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_mingw32=yes
+ else
+***************
+*** 3848,3854 ****
+ fi
+
+ echo $ac_n "checking build system type""... $ac_c" 1>&6
+! echo "configure:3852: checking build system type" >&5
+
+ build_alias=$build
+ case "$build_alias" in
+--- 3856,3862 ----
+ fi
+
+ echo $ac_n "checking build system type""... $ac_c" 1>&6
+! echo "configure:3860: checking build system type" >&5
+
+ build_alias=$build
+ case "$build_alias" in
+***************
+*** 3877,3883 ****
+ if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
+! echo "configure:3881: checking for ld used by GCC" >&5
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+--- 3885,3891 ----
+ if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6
+! echo "configure:3889: checking for ld used by GCC" >&5
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+***************
+*** 3907,3916 ****
+ esac
+ elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
+! echo "configure:3911: checking for GNU ld" >&5
+ else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+! echo "configure:3914: checking for non-GNU ld" >&5
+ fi
+ if eval "test \"`echo '$''{'lt_cv_path_LD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 3915,3924 ----
+ esac
+ elif test "$with_gnu_ld" = yes; then
+ echo $ac_n "checking for GNU ld""... $ac_c" 1>&6
+! echo "configure:3919: checking for GNU ld" >&5
+ else
+ echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
+! echo "configure:3922: checking for non-GNU ld" >&5
+ fi
+ if eval "test \"`echo '$''{'lt_cv_path_LD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 3945,3951 ****
+ fi
+ test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
+ echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
+! echo "configure:3949: checking if the linker ($LD) is GNU ld" >&5
+ if eval "test \"`echo '$''{'lt_cv_prog_gnu_ld'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 3953,3959 ----
+ fi
+ test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; }
+ echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
+! echo "configure:3957: checking if the linker ($LD) is GNU ld" >&5
+ if eval "test \"`echo '$''{'lt_cv_prog_gnu_ld'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 3962,3968 ****
+
+
+ echo $ac_n "checking for $LD option to reload object files""... $ac_c" 1>&6
+! echo "configure:3966: checking for $LD option to reload object files" >&5
+ if eval "test \"`echo '$''{'lt_cv_ld_reload_flag'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 3970,3976 ----
+
+
+ echo $ac_n "checking for $LD option to reload object files""... $ac_c" 1>&6
+! echo "configure:3974: checking for $LD option to reload object files" >&5
+ if eval "test \"`echo '$''{'lt_cv_ld_reload_flag'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 3974,3980 ****
+ test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+ echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
+! echo "configure:3978: checking for BSD-compatible nm" >&5
+ if eval "test \"`echo '$''{'lt_cv_path_NM'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 3982,3988 ----
+ test -n "$reload_flag" && reload_flag=" $reload_flag"
+
+ echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6
+! echo "configure:3986: checking for BSD-compatible nm" >&5
+ if eval "test \"`echo '$''{'lt_cv_path_NM'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4012,4018 ****
+ echo "$ac_t""$NM" 1>&6
+
+ echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+! echo "configure:4016: checking whether ln -s works" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4020,4026 ----
+ echo "$ac_t""$NM" 1>&6
+
+ echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+! echo "configure:4024: checking whether ln -s works" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4033,4039 ****
+ fi
+
+ echo $ac_n "checking how to recognise dependant libraries""... $ac_c" 1>&6
+! echo "configure:4037: checking how to recognise dependant libraries" >&5
+ if eval "test \"`echo '$''{'lt_cv_deplibs_check_method'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4041,4047 ----
+ fi
+
+ echo $ac_n "checking how to recognise dependant libraries""... $ac_c" 1>&6
+! echo "configure:4045: checking how to recognise dependant libraries" >&5
+ if eval "test \"`echo '$''{'lt_cv_deplibs_check_method'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4206,4218 ****
+ deplibs_check_method=$lt_cv_deplibs_check_method
+
+ echo $ac_n "checking for object suffix""... $ac_c" 1>&6
+! echo "configure:4210: checking for object suffix" >&5
+ if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ rm -f conftest*
+ echo 'int i = 1;' > conftest.$ac_ext
+! if { (eval echo configure:4216: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ for ac_file in conftest.*; do
+ case $ac_file in
+ *.c) ;;
+--- 4214,4226 ----
+ deplibs_check_method=$lt_cv_deplibs_check_method
+
+ echo $ac_n "checking for object suffix""... $ac_c" 1>&6
+! echo "configure:4218: checking for object suffix" >&5
+ if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ rm -f conftest*
+ echo 'int i = 1;' > conftest.$ac_ext
+! if { (eval echo configure:4224: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ for ac_file in conftest.*; do
+ case $ac_file in
+ *.c) ;;
+***************
+*** 4232,4238 ****
+
+
+ echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+! echo "configure:4236: checking for executable suffix" >&5
+ if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4240,4246 ----
+
+
+ echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+! echo "configure:4244: checking for executable suffix" >&5
+ if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4242,4251 ****
+ rm -f conftest*
+ echo 'int main () { return 0; }' > conftest.$ac_ext
+ ac_cv_exeext=
+! if { (eval echo configure:4246: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ for file in conftest.*; do
+ case $file in
+! *.c | *.o | *.obj) ;;
+ *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+ esac
+ done
+--- 4250,4259 ----
+ rm -f conftest*
+ echo 'int main () { return 0; }' > conftest.$ac_ext
+ ac_cv_exeext=
+! if { (eval echo configure:4254: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ for file in conftest.*; do
+ case $file in
+! *.c | *.C | *.o | *.obj) ;;
+ *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+ esac
+ done
+***************
+*** 4273,4279 ****
+
+ # Check for command to grab the raw symbol name followed by C symbol from nm.
+ echo $ac_n "checking command to parse $NM output""... $ac_c" 1>&6
+! echo "configure:4277: checking command to parse $NM output" >&5
+ if eval "test \"`echo '$''{'lt_cv_sys_global_symbol_pipe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4281,4287 ----
+
+ # Check for command to grab the raw symbol name followed by C symbol from nm.
+ echo $ac_n "checking command to parse $NM output""... $ac_c" 1>&6
+! echo "configure:4285: checking command to parse $NM output" >&5
+ if eval "test \"`echo '$''{'lt_cv_sys_global_symbol_pipe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4349,4358 ****
+ int main(){nm_test_var='a';nm_test_func();return(0);}
+ EOF
+
+! if { (eval echo configure:4353: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+! if { (eval echo configure:4356: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5; } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+--- 4357,4366 ----
+ int main(){nm_test_var='a';nm_test_func();return(0);}
+ EOF
+
+! if { (eval echo configure:4361: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+! if { (eval echo configure:4364: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\") 1>&5; (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5; } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+***************
+*** 4403,4409 ****
+ save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$no_builtin_flag"
+! if { (eval echo configure:4407: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ pipe_works=yes
+ fi
+ LIBS="$save_LIBS"
+--- 4411,4417 ----
+ save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$no_builtin_flag"
+! if { (eval echo configure:4415: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ pipe_works=yes
+ fi
+ LIBS="$save_LIBS"
+***************
+*** 4449,4465 ****
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+! echo "configure:4453: checking for $ac_hdr" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 4458 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:4463: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+--- 4457,4473 ----
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+! echo "configure:4461: checking for $ac_hdr" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 4466 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:4471: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+***************
+*** 4494,4500 ****
+ file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ echo $ac_n "checking for ${ac_tool_prefix}file""... $ac_c" 1>&6
+! echo "configure:4498: checking for ${ac_tool_prefix}file" >&5
+ if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4502,4508 ----
+ file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ echo $ac_n "checking for ${ac_tool_prefix}file""... $ac_c" 1>&6
+! echo "configure:4506: checking for ${ac_tool_prefix}file" >&5
+ if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4556,4562 ****
+ if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ echo $ac_n "checking for file""... $ac_c" 1>&6
+! echo "configure:4560: checking for file" >&5
+ if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4564,4570 ----
+ if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ echo $ac_n "checking for file""... $ac_c" 1>&6
+! echo "configure:4568: checking for file" >&5
+ if eval "test \"`echo '$''{'lt_cv_path_MAGIC_CMD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4627,4633 ****
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:4631: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4635,4641 ----
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:4639: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4659,4665 ****
+ # Extract the first word of "ranlib", so it can be a program name with args.
+ set dummy ranlib; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:4663: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4667,4673 ----
+ # Extract the first word of "ranlib", so it can be a program name with args.
+ set dummy ranlib; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:4671: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4694,4700 ****
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}strip; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:4698: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4702,4708 ----
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+ set dummy ${ac_tool_prefix}strip; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:4706: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4726,4732 ****
+ # Extract the first word of "strip", so it can be a program name with args.
+ set dummy strip; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:4730: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4734,4740 ----
+ # Extract the first word of "strip", so it can be a program name with args.
+ set dummy strip; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:4738: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_prog_STRIP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4775,4782 ****
+ case $host in
+ *-*-irix6*)
+ # Find out which ABI we are using.
+! echo '#line 4779 "configure"' > conftest.$ac_ext
+! if { (eval echo configure:4780: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+--- 4783,4790 ----
+ case $host in
+ *-*-irix6*)
+ # Find out which ABI we are using.
+! echo '#line 4787 "configure"' > conftest.$ac_ext
+! if { (eval echo configure:4788: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+***************
+*** 4797,4803 ****
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
+! echo "configure:4801: checking whether the C compiler needs -belf" >&5
+ if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4805,4811 ----
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ echo $ac_n "checking whether the C compiler needs -belf""... $ac_c" 1>&6
+! echo "configure:4809: checking whether the C compiler needs -belf" >&5
+ if eval "test \"`echo '$''{'lt_cv_cc_needs_belf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 4810,4823 ****
+ cross_compiling=$ac_cv_prog_cc_cross
+
+ cat > conftest.$ac_ext <<EOF
+! #line 4814 "configure"
+ #include "confdefs.h"
+
+ int main() {
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:4821: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ lt_cv_cc_needs_belf=yes
+ else
+--- 4818,4831 ----
+ cross_compiling=$ac_cv_prog_cc_cross
+
+ cat > conftest.$ac_ext <<EOF
+! #line 4822 "configure"
+ #include "confdefs.h"
+
+ int main() {
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:4829: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ lt_cv_cc_needs_belf=yes
+ else
+***************
+*** 4932,4938 ****
+ ## FIXME: this should be a separate macro
+ ##
+ echo $ac_n "checking for objdir""... $ac_c" 1>&6
+! echo "configure:4936: checking for objdir" >&5
+ rm -f .libs 2>/dev/null
+ mkdir .libs 2>/dev/null
+ if test -d .libs; then
+--- 4940,4946 ----
+ ## FIXME: this should be a separate macro
+ ##
+ echo $ac_n "checking for objdir""... $ac_c" 1>&6
+! echo "configure:4944: checking for objdir" >&5
+ rm -f .libs 2>/dev/null
+ mkdir .libs 2>/dev/null
+ if test -d .libs; then
+***************
+*** 4963,4969 ****
+ # in isolation, and that seeing it set (from the cache) indicates that
+ # the associated values are set (in the cache) correctly too.
+ echo $ac_n "checking for $compiler option to produce PIC""... $ac_c" 1>&6
+! echo "configure:4967: checking for $compiler option to produce PIC" >&5
+ if eval "test \"`echo '$''{'lt_cv_prog_cc_pic'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 4971,4977 ----
+ # in isolation, and that seeing it set (from the cache) indicates that
+ # the associated values are set (in the cache) correctly too.
+ echo $ac_n "checking for $compiler option to produce PIC""... $ac_c" 1>&6
+! echo "configure:4975: checking for $compiler option to produce PIC" >&5
+ if eval "test \"`echo '$''{'lt_cv_prog_cc_pic'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 5115,5135 ****
+
+ # Check to make sure the pic_flag actually works.
+ echo $ac_n "checking if $compiler PIC flag $lt_cv_prog_cc_pic works""... $ac_c" 1>&6
+! echo "configure:5119: checking if $compiler PIC flag $lt_cv_prog_cc_pic works" >&5
+ if eval "test \"`echo '$''{'lt_cv_prog_cc_pic_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+ cat > conftest.$ac_ext <<EOF
+! #line 5126 "configure"
+ #include "confdefs.h"
+
+ int main() {
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:5133: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ case $host_os in
+ hpux9* | hpux10* | hpux11*)
+--- 5123,5143 ----
+
+ # Check to make sure the pic_flag actually works.
+ echo $ac_n "checking if $compiler PIC flag $lt_cv_prog_cc_pic works""... $ac_c" 1>&6
+! echo "configure:5127: checking if $compiler PIC flag $lt_cv_prog_cc_pic works" >&5
+ if eval "test \"`echo '$''{'lt_cv_prog_cc_pic_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $lt_cv_prog_cc_pic -DPIC"
+ cat > conftest.$ac_ext <<EOF
+! #line 5134 "configure"
+ #include "confdefs.h"
+
+ int main() {
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:5141: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ case $host_os in
+ hpux9* | hpux10* | hpux11*)
+***************
+*** 5185,5191 ****
+ ## FIXME: this should be a separate macro
+ ##
+ echo $ac_n "checking if $compiler static flag $lt_cv_prog_cc_static works""... $ac_c" 1>&6
+! echo "configure:5189: checking if $compiler static flag $lt_cv_prog_cc_static works" >&5
+ if eval "test \"`echo '$''{'lt_cv_prog_cc_static_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 5193,5199 ----
+ ## FIXME: this should be a separate macro
+ ##
+ echo $ac_n "checking if $compiler static flag $lt_cv_prog_cc_static works""... $ac_c" 1>&6
+! echo "configure:5197: checking if $compiler static flag $lt_cv_prog_cc_static works" >&5
+ if eval "test \"`echo '$''{'lt_cv_prog_cc_static_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 5193,5206 ****
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+ cat > conftest.$ac_ext <<EOF
+! #line 5197 "configure"
+ #include "confdefs.h"
+
+ int main() {
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:5204: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ lt_cv_prog_cc_static_works=yes
+ else
+--- 5201,5214 ----
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_cv_prog_cc_static"
+ cat > conftest.$ac_ext <<EOF
+! #line 5205 "configure"
+ #include "confdefs.h"
+
+ int main() {
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:5212: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ lt_cv_prog_cc_static_works=yes
+ else
+***************
+*** 5231,5237 ****
+ ##
+ # Check to see if options -o and -c are simultaneously supported by compiler
+ echo $ac_n "checking if $compiler supports -c -o file.$ac_objext""... $ac_c" 1>&6
+! echo "configure:5235: checking if $compiler supports -c -o file.$ac_objext" >&5
+ if eval "test \"`echo '$''{'lt_cv_compiler_c_o'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 5239,5245 ----
+ ##
+ # Check to see if options -o and -c are simultaneously supported by compiler
+ echo $ac_n "checking if $compiler supports -c -o file.$ac_objext""... $ac_c" 1>&6
+! echo "configure:5243: checking if $compiler supports -c -o file.$ac_objext" >&5
+ if eval "test \"`echo '$''{'lt_cv_compiler_c_o'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 5250,5256 ****
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+ compiler_c_o=no
+! if { (eval echo configure:5254: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s out/conftest.err; then
+--- 5258,5264 ----
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+ compiler_c_o=no
+! if { (eval echo configure:5262: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s out/conftest.err; then
+***************
+*** 5279,5285 ****
+ if test x"$compiler_c_o" = x"yes"; then
+ # Check to see if we can write to a .lo
+ echo $ac_n "checking if $compiler supports -c -o file.lo""... $ac_c" 1>&6
+! echo "configure:5283: checking if $compiler supports -c -o file.lo" >&5
+ if eval "test \"`echo '$''{'lt_cv_compiler_o_lo'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 5287,5293 ----
+ if test x"$compiler_c_o" = x"yes"; then
+ # Check to see if we can write to a .lo
+ echo $ac_n "checking if $compiler supports -c -o file.lo""... $ac_c" 1>&6
+! echo "configure:5291: checking if $compiler supports -c -o file.lo" >&5
+ if eval "test \"`echo '$''{'lt_cv_compiler_o_lo'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 5288,5301 ****
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -c -o conftest.lo"
+ cat > conftest.$ac_ext <<EOF
+! #line 5292 "configure"
+ #include "confdefs.h"
+
+ int main() {
+ int some_variable = 0;
+ ; return 0; }
+ EOF
+! if { (eval echo configure:5299: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+--- 5296,5309 ----
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -c -o conftest.lo"
+ cat > conftest.$ac_ext <<EOF
+! #line 5300 "configure"
+ #include "confdefs.h"
+
+ int main() {
+ int some_variable = 0;
+ ; return 0; }
+ EOF
+! if { (eval echo configure:5307: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+***************
+*** 5329,5335 ****
+ if test "$compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo $ac_n "checking if we can lock with hard links""... $ac_c" 1>&6
+! echo "configure:5333: checking if we can lock with hard links" >&5
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+--- 5337,5343 ----
+ if test "$compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ echo $ac_n "checking if we can lock with hard links""... $ac_c" 1>&6
+! echo "configure:5341: checking if we can lock with hard links" >&5
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+***************
+*** 5352,5371 ****
+ if test "$GCC" = yes; then
+ # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+ echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions""... $ac_c" 1>&6
+! echo "configure:5356: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
+ compiler_rtti_exceptions=no
+ cat > conftest.$ac_ext <<EOF
+! #line 5362 "configure"
+ #include "confdefs.h"
+
+ int main() {
+ int some_variable = 0;
+ ; return 0; }
+ EOF
+! if { (eval echo configure:5369: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+--- 5360,5379 ----
+ if test "$GCC" = yes; then
+ # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
+ echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions""... $ac_c" 1>&6
+! echo "configure:5364: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.$ac_ext"
+ compiler_rtti_exceptions=no
+ cat > conftest.$ac_ext <<EOF
+! #line 5370 "configure"
+ #include "confdefs.h"
+
+ int main() {
+ int some_variable = 0;
+ ; return 0; }
+ EOF
+! if { (eval echo configure:5377: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+***************
+*** 5396,5402 ****
+ ##
+ # See if the linker supports building shared libraries.
+ echo $ac_n "checking whether the linker ($LD) supports shared libraries""... $ac_c" 1>&6
+! echo "configure:5400: checking whether the linker ($LD) supports shared libraries" >&5
+
+ allow_undefined_flag=
+ no_undefined_flag=
+--- 5404,5410 ----
+ ##
+ # See if the linker supports building shared libraries.
+ echo $ac_n "checking whether the linker ($LD) supports shared libraries""... $ac_c" 1>&6
+! echo "configure:5408: checking whether the linker ($LD) supports shared libraries" >&5
+
+ allow_undefined_flag=
+ no_undefined_flag=
+***************
+*** 6016,6022 ****
+ ##
+ # Check hardcoding attributes.
+ echo $ac_n "checking how to hardcode library paths into programs""... $ac_c" 1>&6
+! echo "configure:6020: checking how to hardcode library paths into programs" >&5
+ hardcode_action=
+ if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var"; then
+--- 6024,6030 ----
+ ##
+ # Check hardcoding attributes.
+ echo $ac_n "checking how to hardcode library paths into programs""... $ac_c" 1>&6
+! echo "configure:6028: checking how to hardcode library paths into programs" >&5
+ hardcode_action=
+ if test -n "$hardcode_libdir_flag_spec" || \
+ test -n "$runpath_var"; then
+***************
+*** 6048,6054 ****
+ striplib=
+ old_striplib=
+ echo $ac_n "checking whether stripping libraries is possible""... $ac_c" 1>&6
+! echo "configure:6052: checking whether stripping libraries is possible" >&5
+ if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+--- 6056,6062 ----
+ striplib=
+ old_striplib=
+ echo $ac_n "checking whether stripping libraries is possible""... $ac_c" 1>&6
+! echo "configure:6060: checking whether stripping libraries is possible" >&5
+ if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+***************
+*** 6066,6072 ****
+ ##
+ # PORTME Fill in your ld.so characteristics
+ echo $ac_n "checking dynamic linker characteristics""... $ac_c" 1>&6
+! echo "configure:6070: checking dynamic linker characteristics" >&5
+ library_names_spec=
+ libname_spec='lib$name'
+ soname_spec=
+--- 6074,6080 ----
+ ##
+ # PORTME Fill in your ld.so characteristics
+ echo $ac_n "checking dynamic linker characteristics""... $ac_c" 1>&6
+! echo "configure:6078: checking dynamic linker characteristics" >&5
+ library_names_spec=
+ libname_spec='lib$name'
+ soname_spec=
+***************
+*** 6456,6462 ****
+ ##
+ # Report the final consequences.
+ echo $ac_n "checking if libtool supports shared libraries""... $ac_c" 1>&6
+! echo "configure:6460: checking if libtool supports shared libraries" >&5
+ echo "$ac_t""$can_build_shared" 1>&6
+ ##
+ ## END FIXME
+--- 6464,6470 ----
+ ##
+ # Report the final consequences.
+ echo $ac_n "checking if libtool supports shared libraries""... $ac_c" 1>&6
+! echo "configure:6468: checking if libtool supports shared libraries" >&5
+ echo "$ac_t""$can_build_shared" 1>&6
+ ##
+ ## END FIXME
+***************
+*** 6497,6503 ****
+
+ *)
+ echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+! echo "configure:6501: checking for dlopen in -ldl" >&5
+ ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 6505,6511 ----
+
+ *)
+ echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+! echo "configure:6509: checking for dlopen in -ldl" >&5
+ ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 6505,6511 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-ldl $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 6509 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 6513,6519 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-ldl $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 6517 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 6516,6522 ****
+ dlopen()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:6520: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 6524,6530 ----
+ dlopen()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:6528: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 6535,6546 ****
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for dlopen""... $ac_c" 1>&6
+! echo "configure:6539: checking for dlopen" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 6544 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen(); below. */
+--- 6543,6554 ----
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for dlopen""... $ac_c" 1>&6
+! echo "configure:6547: checking for dlopen" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 6552 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char dlopen(); below. */
+***************
+*** 6563,6569 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:6567: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_dlopen=yes"
+ else
+--- 6571,6577 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:6575: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_dlopen=yes"
+ else
+***************
+*** 6581,6592 ****
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for shl_load""... $ac_c" 1>&6
+! echo "configure:6585: checking for shl_load" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 6590 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load(); below. */
+--- 6589,6600 ----
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for shl_load""... $ac_c" 1>&6
+! echo "configure:6593: checking for shl_load" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 6598 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char shl_load(); below. */
+***************
+*** 6609,6615 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:6613: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_shl_load=yes"
+ else
+--- 6617,6623 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:6621: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_shl_load=yes"
+ else
+***************
+*** 6627,6633 ****
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for dlopen in -lsvld""... $ac_c" 1>&6
+! echo "configure:6631: checking for dlopen in -lsvld" >&5
+ ac_lib_var=`echo svld'_'dlopen | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 6635,6641 ----
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for dlopen in -lsvld""... $ac_c" 1>&6
+! echo "configure:6639: checking for dlopen in -lsvld" >&5
+ ac_lib_var=`echo svld'_'dlopen | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 6635,6641 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-lsvld $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 6639 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 6643,6649 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-lsvld $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 6647 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 6646,6652 ****
+ dlopen()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:6650: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 6654,6660 ----
+ dlopen()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:6658: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 6665,6671 ****
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
+! echo "configure:6669: checking for shl_load in -ldld" >&5
+ ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+--- 6673,6679 ----
+ else
+ echo "$ac_t""no" 1>&6
+ echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
+! echo "configure:6677: checking for shl_load in -ldld" >&5
+ ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
+ if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+***************
+*** 6673,6679 ****
+ ac_save_LIBS="$LIBS"
+ LIBS="-ldld $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 6677 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+--- 6681,6687 ----
+ ac_save_LIBS="$LIBS"
+ LIBS="-ldld $LIBS"
+ cat > conftest.$ac_ext <<EOF
+! #line 6685 "configure"
+ #include "confdefs.h"
+ /* Override any gcc2 internal prototype to avoid an error. */
+ /* We use char because int might match the return type of a gcc2
+***************
+*** 6684,6690 ****
+ shl_load()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:6688: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+--- 6692,6698 ----
+ shl_load()
+ ; return 0; }
+ EOF
+! if { (eval echo configure:6696: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+ else
+***************
+*** 6737,6743 ****
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
+! echo "configure:6741: checking whether a program can dlopen itself" >&5
+ if eval "test \"`echo '$''{'lt_cv_dlopen_self'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 6745,6751 ----
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
+! echo "configure:6749: checking whether a program can dlopen itself" >&5
+ if eval "test \"`echo '$''{'lt_cv_dlopen_self'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 6747,6753 ****
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+! #line 6751 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+--- 6755,6761 ----
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+! #line 6759 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+***************
+*** 6808,6814 ****
+ exit (status);
+ }
+ EOF
+! if { (eval echo configure:6812: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+--- 6816,6822 ----
+ exit (status);
+ }
+ EOF
+! if { (eval echo configure:6820: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+***************
+*** 6831,6837 ****
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+ echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
+! echo "configure:6835: checking whether a statically linked program can dlopen itself" >&5
+ if eval "test \"`echo '$''{'lt_cv_dlopen_self_static'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 6839,6845 ----
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+ echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
+! echo "configure:6843: checking whether a statically linked program can dlopen itself" >&5
+ if eval "test \"`echo '$''{'lt_cv_dlopen_self_static'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 6841,6847 ****
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+! #line 6845 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+--- 6849,6855 ----
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+! #line 6853 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+***************
+*** 6902,6908 ****
+ exit (status);
+ }
+ EOF
+! if { (eval echo configure:6906: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+--- 6910,6916 ----
+ exit (status);
+ }
+ EOF
+! if { (eval echo configure:6914: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+***************
+*** 6953,6966 ****
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo $ac_n "checking whether -lc should be explicitly linked in""... $ac_c" 1>&6
+! echo "configure:6957: checking whether -lc should be explicitly linked in" >&5
+ if eval "test \"`echo '$''{'lt_cv_archive_cmds_need_lc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ $rm conftest*
+ echo 'static int dummy;' > conftest.$ac_ext
+
+! if { (eval echo configure:6964: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+--- 6961,6974 ----
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ echo $ac_n "checking whether -lc should be explicitly linked in""... $ac_c" 1>&6
+! echo "configure:6965: checking whether -lc should be explicitly linked in" >&5
+ if eval "test \"`echo '$''{'lt_cv_archive_cmds_need_lc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ $rm conftest*
+ echo 'static int dummy;' > conftest.$ac_ext
+
+! if { (eval echo configure:6972: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+***************
+*** 6973,6979 ****
+ libname=conftest
+ save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+! if { (eval echo configure:6977: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\") 1>&5; (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5; }
+ then
+ lt_cv_archive_cmds_need_lc=no
+ else
+--- 6981,6987 ----
+ libname=conftest
+ save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+! if { (eval echo configure:6985: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\") 1>&5; (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5; }
+ then
+ lt_cv_archive_cmds_need_lc=no
+ else
+***************
+*** 7630,7638 ****
+ # the right suffix on the files.
+ #
+ echo $ac_n "checking for IPv6 structures""... $ac_c" 1>&6
+! echo "configure:7634: checking for IPv6 structures" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7636 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 7638,7646 ----
+ # the right suffix on the files.
+ #
+ echo $ac_n "checking for IPv6 structures""... $ac_c" 1>&6
+! echo "configure:7642: checking for IPv6 structures" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7644 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 7642,7648 ****
+ struct sockaddr_in6 sin6; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7646: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ found_ipv6=yes
+--- 7650,7656 ----
+ struct sockaddr_in6 sin6; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7654: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ found_ipv6=yes
+***************
+*** 7660,7666 ****
+ # This is done before other IPv6 linking tests to LIBS is properly set.
+ #
+ echo $ac_n "checking for Kame IPv6 support""... $ac_c" 1>&6
+! echo "configure:7664: checking for Kame IPv6 support" >&5
+ # Check whether --with-kame or --without-kame was given.
+ if test "${with_kame+set}" = set; then
+ withval="$with_kame"
+--- 7668,7674 ----
+ # This is done before other IPv6 linking tests to LIBS is properly set.
+ #
+ echo $ac_n "checking for Kame IPv6 support""... $ac_c" 1>&6
+! echo "configure:7672: checking for Kame IPv6 support" >&5
+ # Check whether --with-kame or --without-kame was given.
+ if test "${with_kame+set}" = set; then
+ withval="$with_kame"
+***************
+*** 7751,7759 ****
+ LWRES_PLATFORM_HAVEIPV6="#define LWRES_PLATFORM_HAVEIPV6 1"
+
+ echo $ac_n "checking for in6_addr""... $ac_c" 1>&6
+! echo "configure:7755: checking for in6_addr" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7757 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 7759,7767 ----
+ LWRES_PLATFORM_HAVEIPV6="#define LWRES_PLATFORM_HAVEIPV6 1"
+
+ echo $ac_n "checking for in6_addr""... $ac_c" 1>&6
+! echo "configure:7763: checking for in6_addr" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7765 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 7766,7772 ****
+ struct in6_addr in6; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7770: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_HAVEINADDR6="#undef ISC_PLATFORM_HAVEINADDR6"
+--- 7774,7780 ----
+ struct in6_addr in6; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7778: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_HAVEINADDR6="#undef ISC_PLATFORM_HAVEINADDR6"
+***************
+*** 7784,7792 ****
+ rm -f conftest*
+
+ echo $ac_n "checking for in6addr_any""... $ac_c" 1>&6
+! echo "configure:7788: checking for in6addr_any" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7790 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 7792,7800 ----
+ rm -f conftest*
+
+ echo $ac_n "checking for in6addr_any""... $ac_c" 1>&6
+! echo "configure:7796: checking for in6addr_any" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7798 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 7800,7806 ****
+ struct in6_addr in6; in6 = in6addr_any; return (in6.s6_addr[0]);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7804: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDIN6ADDRANY="#undef ISC_PLATFORM_NEEDIN6ADDRANY"
+--- 7808,7814 ----
+ struct in6_addr in6; in6 = in6addr_any; return (in6.s6_addr[0]);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7812: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDIN6ADDRANY="#undef ISC_PLATFORM_NEEDIN6ADDRANY"
+***************
+*** 7816,7824 ****
+ rm -f conftest*
+
+ echo $ac_n "checking for in6addr_loopback""... $ac_c" 1>&6
+! echo "configure:7820: checking for in6addr_loopback" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7822 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 7824,7832 ----
+ rm -f conftest*
+
+ echo $ac_n "checking for in6addr_loopback""... $ac_c" 1>&6
+! echo "configure:7828: checking for in6addr_loopback" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7830 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 7832,7838 ****
+ struct in6_addr in6; in6 = in6addr_loopback; return (in6.s6_addr[0]);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7836: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDIN6ADDRLOOPBACK="#undef ISC_PLATFORM_NEEDIN6ADDRLOOPBACK"
+--- 7840,7846 ----
+ struct in6_addr in6; in6 = in6addr_loopback; return (in6.s6_addr[0]);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDIN6ADDRLOOPBACK="#undef ISC_PLATFORM_NEEDIN6ADDRLOOPBACK"
+***************
+*** 7848,7856 ****
+ rm -f conftest*
+
+ echo $ac_n "checking for sin6_scope_id in struct sockaddr_in6""... $ac_c" 1>&6
+! echo "configure:7852: checking for sin6_scope_id in struct sockaddr_in6" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7854 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 7856,7864 ----
+ rm -f conftest*
+
+ echo $ac_n "checking for sin6_scope_id in struct sockaddr_in6""... $ac_c" 1>&6
+! echo "configure:7860: checking for sin6_scope_id in struct sockaddr_in6" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7862 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 7863,7869 ****
+ struct sockaddr_in6 xyzzy; xyzzy.sin6_scope_id = 0; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7867: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ result="#define LWRES_HAVE_SIN6_SCOPE_ID 1"
+--- 7871,7877 ----
+ struct sockaddr_in6 xyzzy; xyzzy.sin6_scope_id = 0; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7875: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ result="#define LWRES_HAVE_SIN6_SCOPE_ID 1"
+***************
+*** 7878,7886 ****
+ LWRES_HAVE_SIN6_SCOPE_ID="$result"
+
+ echo $ac_n "checking for in6_pktinfo""... $ac_c" 1>&6
+! echo "configure:7882: checking for in6_pktinfo" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7884 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 7886,7894 ----
+ LWRES_HAVE_SIN6_SCOPE_ID="$result"
+
+ echo $ac_n "checking for in6_pktinfo""... $ac_c" 1>&6
+! echo "configure:7890: checking for in6_pktinfo" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7892 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 7893,7899 ****
+ struct in6_pktinfo xyzzy; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7897: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_HAVEIN6PKTINFO="#define ISC_PLATFORM_HAVEIN6PKTINFO 1"
+--- 7901,7907 ----
+ struct in6_pktinfo xyzzy; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7905: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_HAVEIN6PKTINFO="#define ISC_PLATFORM_HAVEIN6PKTINFO 1"
+***************
+*** 7948,7956 ****
+ #
+
+ echo $ac_n "checking for inet_ntop""... $ac_c" 1>&6
+! echo "configure:7952: checking for inet_ntop" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7954 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 7956,7964 ----
+ #
+
+ echo $ac_n "checking for inet_ntop""... $ac_c" 1>&6
+! echo "configure:7960: checking for inet_ntop" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 7962 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 7960,7966 ****
+ inet_ntop(0, 0, 0, 0); return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7964: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDNTOP="#undef ISC_PLATFORM_NEEDNTOP"
+--- 7968,7974 ----
+ inet_ntop(0, 0, 0, 0); return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:7972: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDNTOP="#undef ISC_PLATFORM_NEEDNTOP"
+***************
+*** 7981,7993 ****
+ # zeros should also be rejected.
+
+ echo $ac_n "checking for inet_pton""... $ac_c" 1>&6
+! echo "configure:7985: checking for inet_pton" >&5
+ if test "$cross_compiling" = yes; then
+ echo "$ac_t""assuming target platform has working inet_pton" 1>&6
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 7991 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 7989,8001 ----
+ # zeros should also be rejected.
+
+ echo $ac_n "checking for inet_pton""... $ac_c" 1>&6
+! echo "configure:7993: checking for inet_pton" >&5
+ if test "$cross_compiling" = yes; then
+ echo "$ac_t""assuming target platform has working inet_pton" 1>&6
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 7999 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 7997,8003 ****
+ main() { char a[4]; return (inet_pton(AF_INET, "1.2.3", a) == 1 ? 1 :
+ inet_pton(AF_INET, "1.2.3.04", a) == 1 ? 1 : 0); }
+ EOF
+! if { (eval echo configure:8001: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"
+--- 8005,8011 ----
+ main() { char a[4]; return (inet_pton(AF_INET, "1.2.3", a) == 1 ? 1 :
+ inet_pton(AF_INET, "1.2.3.04", a) == 1 ? 1 : 0); }
+ EOF
+! if { (eval echo configure:8009: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDPTON="#undef ISC_PLATFORM_NEEDPTON"
+***************
+*** 8015,8023 ****
+
+
+ echo $ac_n "checking for inet_aton""... $ac_c" 1>&6
+! echo "configure:8019: checking for inet_aton" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8021 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 8023,8031 ----
+
+
+ echo $ac_n "checking for inet_aton""... $ac_c" 1>&6
+! echo "configure:8027: checking for inet_aton" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8029 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 8027,8033 ****
+ struct in_addr in; inet_aton(0, &in); return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8031: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDATON="#undef ISC_PLATFORM_NEEDATON"
+--- 8035,8041 ----
+ struct in_addr in; inet_aton(0, &in); return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8039: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDATON="#undef ISC_PLATFORM_NEEDATON"
+***************
+*** 8060,8068 ****
+ esac
+
+ echo $ac_n "checking for sa_len in struct sockaddr""... $ac_c" 1>&6
+! echo "configure:8064: checking for sa_len in struct sockaddr" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8066 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 8068,8076 ----
+ esac
+
+ echo $ac_n "checking for sa_len in struct sockaddr""... $ac_c" 1>&6
+! echo "configure:8072: checking for sa_len in struct sockaddr" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8074 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 8071,8077 ****
+ struct sockaddr sa; sa.sa_len = 0; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8075: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_HAVESALEN="#define ISC_PLATFORM_HAVESALEN 1"
+--- 8079,8085 ----
+ struct sockaddr sa; sa.sa_len = 0; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8083: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_HAVESALEN="#define ISC_PLATFORM_HAVESALEN 1"
+***************
+*** 8092,8100 ****
+ # Look for a 4.4BSD or 4.3BSD struct msghdr
+ #
+ echo $ac_n "checking for struct msghdr flavor""... $ac_c" 1>&6
+! echo "configure:8096: checking for struct msghdr flavor" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8098 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 8100,8108 ----
+ # Look for a 4.4BSD or 4.3BSD struct msghdr
+ #
+ echo $ac_n "checking for struct msghdr flavor""... $ac_c" 1>&6
+! echo "configure:8104: checking for struct msghdr flavor" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8106 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 8103,8109 ****
+ struct msghdr msg; msg.msg_flags = 0; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8107: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""4.4BSD" 1>&6
+ ISC_PLATFORM_MSGHDRFLAVOR="#define ISC_NET_BSD44MSGHDR 1"
+--- 8111,8117 ----
+ struct msghdr msg; msg.msg_flags = 0; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8115: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""4.4BSD" 1>&6
+ ISC_PLATFORM_MSGHDRFLAVOR="#define ISC_NET_BSD44MSGHDR 1"
+***************
+*** 8121,8129 ****
+ # Look for in_port_t.
+ #
+ echo $ac_n "checking for type in_port_t""... $ac_c" 1>&6
+! echo "configure:8125: checking for type in_port_t" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8127 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 8129,8137 ----
+ # Look for in_port_t.
+ #
+ echo $ac_n "checking for type in_port_t""... $ac_c" 1>&6
+! echo "configure:8133: checking for type in_port_t" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8135 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 8132,8138 ****
+ in_port_t port = 25; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8136: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDPORTT="#undef ISC_PLATFORM_NEEDPORTT"
+--- 8140,8146 ----
+ in_port_t port = 25; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8144: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_NEEDPORTT="#undef ISC_PLATFORM_NEEDPORTT"
+***************
+*** 8150,8158 ****
+ # Check for addrinfo
+ #
+ echo $ac_n "checking for struct addrinfo""... $ac_c" 1>&6
+! echo "configure:8154: checking for struct addrinfo" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8156 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+--- 8158,8166 ----
+ # Check for addrinfo
+ #
+ echo $ac_n "checking for struct addrinfo""... $ac_c" 1>&6
+! echo "configure:8162: checking for struct addrinfo" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8164 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+***************
+*** 8160,8166 ****
+ struct addrinfo a; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8164: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_NEEDADDRINFO="#undef ISC_LWRES_NEEDADDRINFO"
+--- 8168,8174 ----
+ struct addrinfo a; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8172: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_NEEDADDRINFO="#undef ISC_LWRES_NEEDADDRINFO"
+***************
+*** 8182,8190 ****
+ # Check for rrsetinfo
+ #
+ echo $ac_n "checking for struct rrsetinfo""... $ac_c" 1>&6
+! echo "configure:8186: checking for struct rrsetinfo" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8188 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+--- 8190,8198 ----
+ # Check for rrsetinfo
+ #
+ echo $ac_n "checking for struct rrsetinfo""... $ac_c" 1>&6
+! echo "configure:8194: checking for struct rrsetinfo" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8196 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+***************
+*** 8192,8198 ****
+ struct rrsetinfo r; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8196: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_NEEDRRSETINFO="#undef ISC_LWRES_NEEDRRSETINFO"
+--- 8200,8206 ----
+ struct rrsetinfo r; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8204: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_NEEDRRSETINFO="#undef ISC_LWRES_NEEDRRSETINFO"
+***************
+*** 8207,8215 ****
+
+
+ echo $ac_n "checking for int sethostent""... $ac_c" 1>&6
+! echo "configure:8211: checking for int sethostent" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8213 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+--- 8215,8223 ----
+
+
+ echo $ac_n "checking for int sethostent""... $ac_c" 1>&6
+! echo "configure:8219: checking for int sethostent" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8221 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+***************
+*** 8217,8223 ****
+ int i = sethostent(0); return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8221: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_SETHOSTENTINT="#define ISC_LWRES_SETHOSTENTINT 1"
+--- 8225,8231 ----
+ int i = sethostent(0); return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8229: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_SETHOSTENTINT="#define ISC_LWRES_SETHOSTENTINT 1"
+***************
+*** 8232,8240 ****
+
+
+ echo $ac_n "checking for int endhostent""... $ac_c" 1>&6
+! echo "configure:8236: checking for int endhostent" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8238 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+--- 8240,8248 ----
+
+
+ echo $ac_n "checking for int endhostent""... $ac_c" 1>&6
+! echo "configure:8244: checking for int endhostent" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8246 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+***************
+*** 8242,8248 ****
+ int i = endhostent(); return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8246: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_ENDHOSTENTINT="#define ISC_LWRES_ENDHOSTENTINT 1"
+--- 8250,8256 ----
+ int i = endhostent(); return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8254: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_ENDHOSTENTINT="#define ISC_LWRES_ENDHOSTENTINT 1"
+***************
+*** 8257,8265 ****
+
+
+ echo $ac_n "checking for getnetbyaddr(in_addr_t, ...)""... $ac_c" 1>&6
+! echo "configure:8261: checking for getnetbyaddr(in_addr_t, ...)" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8263 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+--- 8265,8273 ----
+
+
+ echo $ac_n "checking for getnetbyaddr(in_addr_t, ...)""... $ac_c" 1>&6
+! echo "configure:8269: checking for getnetbyaddr(in_addr_t, ...)" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8271 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+***************
+*** 8268,8274 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8272: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_GETNETBYADDRINADDR="#define ISC_LWRES_GETNETBYADDRINADDR 1"
+--- 8276,8282 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8280: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_GETNETBYADDRINADDR="#define ISC_LWRES_GETNETBYADDRINADDR 1"
+***************
+*** 8283,8291 ****
+
+
+ echo $ac_n "checking for int setnetent""... $ac_c" 1>&6
+! echo "configure:8287: checking for int setnetent" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8289 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+--- 8291,8299 ----
+
+
+ echo $ac_n "checking for int setnetent""... $ac_c" 1>&6
+! echo "configure:8295: checking for int setnetent" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8297 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+***************
+*** 8293,8299 ****
+ int i = setnetent(0); return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8297: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_SETNETENTINT="#define ISC_LWRES_SETNETENTINT 1"
+--- 8301,8307 ----
+ int i = setnetent(0); return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8305: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_SETNETENTINT="#define ISC_LWRES_SETNETENTINT 1"
+***************
+*** 8308,8316 ****
+
+
+ echo $ac_n "checking for int endnetent""... $ac_c" 1>&6
+! echo "configure:8312: checking for int endnetent" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8314 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+--- 8316,8324 ----
+
+
+ echo $ac_n "checking for int endnetent""... $ac_c" 1>&6
+! echo "configure:8320: checking for int endnetent" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8322 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+***************
+*** 8318,8324 ****
+ int i = endnetent(); return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8322: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_ENDNETENTINT="#define ISC_LWRES_ENDNETENTINT 1"
+--- 8326,8332 ----
+ int i = endnetent(); return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8330: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_ENDNETENTINT="#define ISC_LWRES_ENDNETENTINT 1"
+***************
+*** 8333,8341 ****
+
+
+ echo $ac_n "checking for gethostbyaddr(const void *, size_t, ...)""... $ac_c" 1>&6
+! echo "configure:8337: checking for gethostbyaddr(const void *, size_t, ...)" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8339 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+--- 8341,8349 ----
+
+
+ echo $ac_n "checking for gethostbyaddr(const void *, size_t, ...)""... $ac_c" 1>&6
+! echo "configure:8345: checking for gethostbyaddr(const void *, size_t, ...)" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8347 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+***************
+*** 8344,8350 ****
+ return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8348: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_GETHOSTBYADDRVOID="#define ISC_LWRES_GETHOSTBYADDRVOID 1"
+--- 8352,8358 ----
+ return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8356: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_GETHOSTBYADDRVOID="#define ISC_LWRES_GETHOSTBYADDRVOID 1"
+***************
+*** 8359,8367 ****
+
+
+ echo $ac_n "checking for h_errno in netdb.h""... $ac_c" 1>&6
+! echo "configure:8363: checking for h_errno in netdb.h" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8365 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+--- 8367,8375 ----
+
+
+ echo $ac_n "checking for h_errno in netdb.h""... $ac_c" 1>&6
+! echo "configure:8371: checking for h_errno in netdb.h" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8373 "configure"
+ #include "confdefs.h"
+
+ #include <netdb.h>
+***************
+*** 8369,8375 ****
+ h_errno = 1; return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8373: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_NEEDHERRNO="#undef ISC_LWRES_NEEDHERRNO"
+--- 8377,8383 ----
+ h_errno = 1; return(0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8381: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_LWRES_NEEDHERRNO="#undef ISC_LWRES_NEEDHERRNO"
+***************
+*** 8384,8395 ****
+
+
+ echo $ac_n "checking for getipnodebyname""... $ac_c" 1>&6
+! echo "configure:8388: checking for getipnodebyname" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_getipnodebyname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8393 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getipnodebyname(); below. */
+--- 8392,8403 ----
+
+
+ echo $ac_n "checking for getipnodebyname""... $ac_c" 1>&6
+! echo "configure:8396: checking for getipnodebyname" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_getipnodebyname'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8401 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getipnodebyname(); below. */
+***************
+*** 8412,8418 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8416: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_getipnodebyname=yes"
+ else
+--- 8420,8426 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8424: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_getipnodebyname=yes"
+ else
+***************
+*** 8433,8444 ****
+ fi
+
+ echo $ac_n "checking for getnameinfo""... $ac_c" 1>&6
+! echo "configure:8437: checking for getnameinfo" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_getnameinfo'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8442 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getnameinfo(); below. */
+--- 8441,8452 ----
+ fi
+
+ echo $ac_n "checking for getnameinfo""... $ac_c" 1>&6
+! echo "configure:8445: checking for getnameinfo" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_getnameinfo'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8450 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getnameinfo(); below. */
+***************
+*** 8461,8467 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8465: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_getnameinfo=yes"
+ else
+--- 8469,8475 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8473: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_getnameinfo=yes"
+ else
+***************
+*** 8482,8493 ****
+ fi
+
+ echo $ac_n "checking for getaddrinfo""... $ac_c" 1>&6
+! echo "configure:8486: checking for getaddrinfo" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_getaddrinfo'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8491 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getaddrinfo(); below. */
+--- 8490,8501 ----
+ fi
+
+ echo $ac_n "checking for getaddrinfo""... $ac_c" 1>&6
+! echo "configure:8494: checking for getaddrinfo" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_getaddrinfo'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8499 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getaddrinfo(); below. */
+***************
+*** 8510,8516 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8514: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_getaddrinfo=yes"
+ else
+--- 8518,8524 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8522: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_getaddrinfo=yes"
+ else
+***************
+*** 8535,8546 ****
+ fi
+
+ echo $ac_n "checking for gai_strerror""... $ac_c" 1>&6
+! echo "configure:8539: checking for gai_strerror" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_gai_strerror'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8544 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char gai_strerror(); below. */
+--- 8543,8554 ----
+ fi
+
+ echo $ac_n "checking for gai_strerror""... $ac_c" 1>&6
+! echo "configure:8547: checking for gai_strerror" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_gai_strerror'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8552 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char gai_strerror(); below. */
+***************
+*** 8563,8569 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8567: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_gai_strerror=yes"
+ else
+--- 8571,8577 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8575: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_gai_strerror=yes"
+ else
+***************
+*** 8593,8601 ****
+ # Look for a sysctl call to get the list of network interfaces.
+ #
+ echo $ac_n "checking for interface list sysctl""... $ac_c" 1>&6
+! echo "configure:8597: checking for interface list sysctl" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8599 "configure"
+ #include "confdefs.h"
+
+ #include <sys/param.h>
+--- 8601,8609 ----
+ # Look for a sysctl call to get the list of network interfaces.
+ #
+ echo $ac_n "checking for interface list sysctl""... $ac_c" 1>&6
+! echo "configure:8605: checking for interface list sysctl" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8607 "configure"
+ #include "confdefs.h"
+
+ #include <sys/param.h>
+***************
+*** 8632,8647 ****
+ # AC_CHECK_FUNC() incorrectly succeeds because it declares
+ # the function itself.
+ echo $ac_n "checking for correctly declared strsep()""... $ac_c" 1>&6
+! echo "configure:8636: checking for correctly declared strsep()" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8638 "configure"
+ #include "confdefs.h"
+ #include <string.h>
+ int main() {
+ char *sp; char *foo = strsep(&sp, ".");
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8645: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; ISC_PLATFORM_NEEDSTRSEP="#undef ISC_PLATFORM_NEEDSTRSEP"
+ else
+--- 8640,8655 ----
+ # AC_CHECK_FUNC() incorrectly succeeds because it declares
+ # the function itself.
+ echo $ac_n "checking for correctly declared strsep()""... $ac_c" 1>&6
+! echo "configure:8644: checking for correctly declared strsep()" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8646 "configure"
+ #include "confdefs.h"
+ #include <string.h>
+ int main() {
+ char *sp; char *foo = strsep(&sp, ".");
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; ISC_PLATFORM_NEEDSTRSEP="#undef ISC_PLATFORM_NEEDSTRSEP"
+ else
+***************
+*** 8653,8664 ****
+ rm -f conftest*
+
+ echo $ac_n "checking for vsnprintf""... $ac_c" 1>&6
+! echo "configure:8657: checking for vsnprintf" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_vsnprintf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8662 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vsnprintf(); below. */
+--- 8661,8672 ----
+ rm -f conftest*
+
+ echo $ac_n "checking for vsnprintf""... $ac_c" 1>&6
+! echo "configure:8665: checking for vsnprintf" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_vsnprintf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8670 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vsnprintf(); below. */
+***************
+*** 8681,8687 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8685: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_vsnprintf=yes"
+ else
+--- 8689,8695 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8693: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_vsnprintf=yes"
+ else
+***************
+*** 8706,8717 ****
+
+
+ echo $ac_n "checking for strerror""... $ac_c" 1>&6
+! echo "configure:8710: checking for strerror" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_strerror'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8715 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strerror(); below. */
+--- 8714,8725 ----
+
+
+ echo $ac_n "checking for strerror""... $ac_c" 1>&6
+! echo "configure:8718: checking for strerror" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_strerror'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8723 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char strerror(); below. */
+***************
+*** 8734,8740 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8738: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_strerror=yes"
+ else
+--- 8742,8748 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8746: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_strerror=yes"
+ else
+***************
+*** 8768,8784 ****
+ # but that's defined elsewhere since we don't use configure on Win32.
+ #
+ echo $ac_n "checking printf format modifier for 64-bit integers""... $ac_c" 1>&6
+! echo "configure:8772: checking printf format modifier for 64-bit integers" >&5
+ if test "$cross_compiling" = yes; then
+ echo "$ac_t""assuming target platform uses ll" 1>&6
+ ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "ll"'
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8778 "configure"
+ #include "confdefs.h"
+ main() { exit(!(sizeof(long long int) == sizeof(long int))); }
+ EOF
+! if { (eval echo configure:8782: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""l" 1>&6
+ ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "l"'
+--- 8776,8792 ----
+ # but that's defined elsewhere since we don't use configure on Win32.
+ #
+ echo $ac_n "checking printf format modifier for 64-bit integers""... $ac_c" 1>&6
+! echo "configure:8780: checking printf format modifier for 64-bit integers" >&5
+ if test "$cross_compiling" = yes; then
+ echo "$ac_t""assuming target platform uses ll" 1>&6
+ ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "ll"'
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8786 "configure"
+ #include "confdefs.h"
+ main() { exit(!(sizeof(long long int) == sizeof(long int))); }
+ EOF
+! if { (eval echo configure:8790: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""l" 1>&6
+ ISC_PLATFORM_QUADFORMAT='#define ISC_PLATFORM_QUADFORMAT "l"'
+***************
+*** 8798,8809 ****
+ # Security Stuff
+ #
+ echo $ac_n "checking for chroot""... $ac_c" 1>&6
+! echo "configure:8802: checking for chroot" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_chroot'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8807 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char chroot(); below. */
+--- 8806,8817 ----
+ # Security Stuff
+ #
+ echo $ac_n "checking for chroot""... $ac_c" 1>&6
+! echo "configure:8810: checking for chroot" >&5
+ if eval "test \"`echo '$''{'ac_cv_func_chroot'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8815 "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char chroot(); below. */
+***************
+*** 8826,8832 ****
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8830: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_chroot=yes"
+ else
+--- 8834,8840 ----
+
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8838: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_chroot=yes"
+ else
+***************
+*** 8860,8876 ****
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+! echo "configure:8864: checking for $ac_hdr" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8869 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:8874: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+--- 8868,8884 ----
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+! echo "configure:8872: checking for $ac_hdr" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8877 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:8882: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+***************
+*** 8904,8920 ****
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+! echo "configure:8908: checking for $ac_hdr" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8913 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:8918: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+--- 8912,8928 ----
+ do
+ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+! echo "configure:8916: checking for $ac_hdr" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8921 "configure"
+ #include "confdefs.h"
+ #include <$ac_hdr>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+! { (eval echo configure:8926: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+ if test -z "$ac_err"; then
+ rm -rf conftest*
+***************
+*** 8945,8953 ****
+ # BSD/OS, and perhaps some others, don't define rlim_t.
+ #
+ echo $ac_n "checking for type rlim_t""... $ac_c" 1>&6
+! echo "configure:8949: checking for type rlim_t" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8951 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 8953,8961 ----
+ # BSD/OS, and perhaps some others, don't define rlim_t.
+ #
+ echo $ac_n "checking for type rlim_t""... $ac_c" 1>&6
+! echo "configure:8957: checking for type rlim_t" >&5
+ cat > conftest.$ac_ext <<EOF
+! #line 8959 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 8957,8963 ****
+ rlim_t rl = 19671212; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8961: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE rlim_t"
+--- 8965,8971 ----
+ rlim_t rl = 19671212; return (0);
+ ; return 0; }
+ EOF
+! if { (eval echo configure:8969: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE rlim_t"
+***************
+*** 8968,8979 ****
+ echo "$ac_t""no" 1>&6
+
+ echo $ac_n "checking type of rlim_cur""... $ac_c" 1>&6
+! echo "configure:8972: checking type of rlim_cur" >&5
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: cannot determine type of rlim_cur when cross compiling - define rlim_t" 1>&2; exit 1; }
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8977 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 8976,8987 ----
+ echo "$ac_t""no" 1>&6
+
+ echo $ac_n "checking type of rlim_cur""... $ac_c" 1>&6
+! echo "configure:8980: checking type of rlim_cur" >&5
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: cannot determine type of rlim_cur when cross compiling - define rlim_t" 1>&2; exit 1; }
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8985 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 8981,8987 ****
+ #include <sys/resource.h>
+ main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(int)));}
+ EOF
+! if { (eval echo configure:8985: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""int" 1>&6
+ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE int"
+--- 8989,8995 ----
+ #include <sys/resource.h>
+ main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(int)));}
+ EOF
+! if { (eval echo configure:8993: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""int" 1>&6
+ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE int"
+***************
+*** 8994,9000 ****
+ { echo "configure: error: this cannot happen" 1>&2; exit 1; }
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 8998 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 9002,9008 ----
+ { echo "configure: error: this cannot happen" 1>&2; exit 1; }
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 9006 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 9002,9008 ****
+ #include <sys/resource.h>
+ main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(long int)));}
+ EOF
+! if { (eval echo configure:9006: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""long int" 1>&6
+ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long int"
+--- 9010,9016 ----
+ #include <sys/resource.h>
+ main() { struct rlimit r; exit(!(sizeof(r.rlim_cur) == sizeof(long int)));}
+ EOF
+! if { (eval echo configure:9014: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""long int" 1>&6
+ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long int"
+***************
+*** 9015,9021 ****
+ { echo "configure: error: this cannot happen" 1>&2; exit 1; }
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 9019 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+--- 9023,9029 ----
+ { echo "configure: error: this cannot happen" 1>&2; exit 1; }
+ else
+ cat > conftest.$ac_ext <<EOF
+! #line 9027 "configure"
+ #include "confdefs.h"
+
+ #include <sys/types.h>
+***************
+*** 9023,9029 ****
+ #include <sys/resource.h>
+ main() { struct rlimit r; exit((!sizeof(r.rlim_cur) == sizeof(long long int)));}
+ EOF
+! if { (eval echo configure:9027: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""long long int" 1>&6
+ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long long int"
+--- 9031,9037 ----
+ #include <sys/resource.h>
+ main() { struct rlimit r; exit((!sizeof(r.rlim_cur) == sizeof(long long int)));}
+ EOF
+! if { (eval echo configure:9035: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+ then
+ echo "$ac_t""long long int" 1>&6
+ ISC_PLATFORM_RLIMITTYPE="#define ISC_PLATFORM_RLIMITTYPE long long int"
+***************
+*** 9147,9153 ****
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:9151: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_OPENJADE'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 9155,9161 ----
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:9159: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_OPENJADE'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 9194,9200 ****
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:9198: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_JADETEX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 9202,9208 ----
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:9206: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_JADETEX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 9237,9243 ****
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:9241: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_PDFJADETEX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+--- 9245,9251 ----
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+ set dummy $ac_prog; ac_word=$2
+ echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+! echo "configure:9249: checking for $ac_word" >&5
+ if eval "test \"`echo '$''{'ac_cv_path_PDFJADETEX'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+ else
+***************
+*** 9293,9299 ****
+
+ SGMLCATALOG=""
+ echo $ac_n "checking for catalog""... $ac_c" 1>&6
+! echo "configure:9297: checking for catalog" >&5
+ for d in $sgmltrees
+ do
+ f=$d/catalog
+--- 9301,9307 ----
+
+ SGMLCATALOG=""
+ echo $ac_n "checking for catalog""... $ac_c" 1>&6
+! echo "configure:9305: checking for catalog" >&5
+ for d in $sgmltrees
+ do
+ f=$d/catalog
+***************
+*** 9335,9341 ****
+
+ HTMLSTYLE=""
+ echo $ac_n "checking for html/docbook.dsl""... $ac_c" 1>&6
+! echo "configure:9339: checking for html/docbook.dsl" >&5
+ for d in $stylepath
+ do
+ f=$d/html/docbook.dsl
+--- 9343,9349 ----
+
+ HTMLSTYLE=""
+ echo $ac_n "checking for html/docbook.dsl""... $ac_c" 1>&6
+! echo "configure:9347: checking for html/docbook.dsl" >&5
+ for d in $stylepath
+ do
+ f=$d/html/docbook.dsl
+***************
+*** 9356,9362 ****
+
+ PRINTSTYLE=""
+ echo $ac_n "checking for print/docbook.dsl""... $ac_c" 1>&6
+! echo "configure:9360: checking for print/docbook.dsl" >&5
+ for d in $stylepath
+ do
+ f=$d/print/docbook.dsl
+--- 9364,9370 ----
+
+ PRINTSTYLE=""
+ echo $ac_n "checking for print/docbook.dsl""... $ac_c" 1>&6
+! echo "configure:9368: checking for print/docbook.dsl" >&5
+ for d in $stylepath
+ do
+ f=$d/print/docbook.dsl
+***************
+*** 9382,9388 ****
+
+ XMLDCL=""
+ echo $ac_n "checking for docbook/dsssl/modular/dtds/decls/xml.dcl""... $ac_c" 1>&6
+! echo "configure:9386: checking for docbook/dsssl/modular/dtds/decls/xml.dcl" >&5
+ for d in $sgmltrees
+ do
+ f=$d/docbook/dsssl/modular/dtds/decls/xml.dcl
+--- 9390,9396 ----
+
+ XMLDCL=""
+ echo $ac_n "checking for docbook/dsssl/modular/dtds/decls/xml.dcl""... $ac_c" 1>&6
+! echo "configure:9394: checking for docbook/dsssl/modular/dtds/decls/xml.dcl" >&5
+ for d in $sgmltrees
+ do
+ f=$d/docbook/dsssl/modular/dtds/decls/xml.dcl
+***************
+*** 9408,9414 ****
+
+ DOCBOOK2MANSPEC=""
+ echo $ac_n "checking for docbook2X/docbook2man-spec.pl""... $ac_c" 1>&6
+! echo "configure:9412: checking for docbook2X/docbook2man-spec.pl" >&5
+ for d in $sgmltrees
+ do
+ f=$d/docbook2X/docbook2man-spec.pl
+--- 9416,9422 ----
+
+ DOCBOOK2MANSPEC=""
+ echo $ac_n "checking for docbook2X/docbook2man-spec.pl""... $ac_c" 1>&6
+! echo "configure:9420: checking for docbook2X/docbook2man-spec.pl" >&5
+ for d in $sgmltrees
+ do
+ f=$d/docbook2X/docbook2man-spec.pl
+***************
+*** 9428,9433 ****
+--- 9436,9631 ----
+
+
+ #
++ # IDN support
++ #
++ # Check whether --with-idn or --without-idn was given.
++ if test "${with_idn+set}" = set; then
++ withval="$with_idn"
++ use_idn="$withval"
++ else
++ use_idn="no"
++ fi
++
++ case "$use_idn" in
++ yes)
++ if test X$prefix = XNONE ; then
++ idn_path=/usr/local
++ else
++ idn_path=$prefix
++ fi
++ ;;
++ no)
++ ;;
++ *)
++ idn_path="$use_idn"
++ ;;
++ esac
++
++ iconvinc=
++ iconvlib=
++ # Check whether --with-libiconv or --without-libiconv was given.
++ if test "${with_libiconv+set}" = set; then
++ withval="$with_libiconv"
++ use_libiconv="$withval"
++ else
++ use_libiconv="no"
++ fi
++
++ case "$use_libiconv" in
++ yes)
++ if test X$prefix = XNONE ; then
++ iconvlib="-L/usr/local/lib -R/usr/local/lib -liconv"
++ else
++ iconvlib="-L$prefix/lib -R$prefix/lib -liconv"
++ fi
++ ;;
++ no)
++ iconvlib=
++ ;;
++ *)
++ iconvlib="-L$use_libiconv/lib -R$use_libiconv/lib -liconv"
++ ;;
++ esac
++
++ # Check whether --with-iconv or --without-iconv was given.
++ if test "${with_iconv+set}" = set; then
++ withval="$with_iconv"
++ iconvlib="$withval"
++ fi
++
++ case "$iconvlib" in
++ no)
++ iconvlib=
++ ;;
++ yes)
++ iconvlib=-liconv
++ ;;
++ esac
++
++ # Check whether --with-idnlib or --without-idnlib was given.
++ if test "${with_idnlib+set}" = set; then
++ withval="$with_idnlib"
++ idnlib="$withval"
++ else
++ idnlib="no"
++ fi
++
++ if test "$idnlib" = yes; then
++ { echo "configure: error: You must specify ARG for --with-idnlib." 1>&2; exit 1; }
++ fi
++
++ IDNLIBS=
++ if test "$use_idn" != no; then
++ cat >> confdefs.h <<\EOF
++ #define WITH_IDN 1
++ EOF
++
++ STD_CINCLUDES="$STD_CINCLUDES -I$idn_path/include"
++ if test "$idnlib" != no; then
++ IDNLIBS="$idnlib $iconvlib"
++ else
++ IDNLIBS="-L$idn_path/lib -lidnkit $iconvlib"
++ fi
++ fi
++
++
++ for ac_hdr in locale.h
++ do
++ ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
++ echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
++ echo "configure:9537: checking for $ac_hdr" >&5
++ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
++ echo $ac_n "(cached) $ac_c" 1>&6
++ else
++ cat > conftest.$ac_ext <<EOF
++ #line 9542 "configure"
++ #include "confdefs.h"
++ #include <$ac_hdr>
++ EOF
++ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
++ { (eval echo configure:9547: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
++ ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
++ if test -z "$ac_err"; then
++ rm -rf conftest*
++ eval "ac_cv_header_$ac_safe=yes"
++ else
++ echo "$ac_err" >&5
++ echo "configure: failed program was:" >&5
++ cat conftest.$ac_ext >&5
++ rm -rf conftest*
++ eval "ac_cv_header_$ac_safe=no"
++ fi
++ rm -f conftest*
++ fi
++ if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
++ echo "$ac_t""yes" 1>&6
++ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
++ cat >> confdefs.h <<EOF
++ #define $ac_tr_hdr 1
++ EOF
++
++ else
++ echo "$ac_t""no" 1>&6
++ fi
++ done
++
++ for ac_func in setlocale
++ do
++ echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
++ echo "configure:9576: checking for $ac_func" >&5
++ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
++ echo $ac_n "(cached) $ac_c" 1>&6
++ else
++ cat > conftest.$ac_ext <<EOF
++ #line 9581 "configure"
++ #include "confdefs.h"
++ /* System header to define __stub macros and hopefully few prototypes,
++ which can conflict with char $ac_func(); below. */
++ #include <assert.h>
++ /* Override any gcc2 internal prototype to avoid an error. */
++ /* We use char because int might match the return type of a gcc2
++ builtin and then its argument prototype would still apply. */
++ char $ac_func();
++
++ int main() {
++
++ /* The GNU C library defines this for functions which it implements
++ to always fail with ENOSYS. Some functions are actually named
++ something starting with __ and the normal name is an alias. */
++ #if defined (__stub_$ac_func) || defined (__stub___$ac_func)
++ choke me
++ #else
++ $ac_func();
++ #endif
++
++ ; return 0; }
++ EOF
++ if { (eval echo configure:9604: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
++ rm -rf conftest*
++ eval "ac_cv_func_$ac_func=yes"
++ else
++ echo "configure: failed program was:" >&5
++ cat conftest.$ac_ext >&5
++ rm -rf conftest*
++ eval "ac_cv_func_$ac_func=no"
++ fi
++ rm -f conftest*
++ fi
++
++ if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
++ echo "$ac_t""yes" 1>&6
++ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
++ cat >> confdefs.h <<EOF
++ #define $ac_tr_func 1
++ EOF
++
++ else
++ echo "$ac_t""no" 1>&6
++ fi
++ done
++
++
++ #
+ # Substitutions
+ #
+
+***************
+*** 9799,9804 ****
+--- 9997,10003 ----
+ s%@PRINTSTYLE@%$PRINTSTYLE%g
+ s%@XMLDCL@%$XMLDCL%g
+ s%@DOCBOOK2MANSPEC@%$DOCBOOK2MANSPEC%g
++ s%@IDNLIBS@%$IDNLIBS%g
+ s%@BIND9_TOP_BUILDDIR@%$BIND9_TOP_BUILDDIR%g
+ s%@BIND9_ISC_BUILDINCLUDE@%$BIND9_ISC_BUILDINCLUDE%g
+ s%@BIND9_ISCCC_BUILDINCLUDE@%$BIND9_ISCCC_BUILDINCLUDE%g
+***************
+*** 9828,9834 ****
+
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+! ac_max_sed_cmds=50 # Maximum number of lines to put in a sed script.
+ ac_file=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_cmds # Line after last line for current file.
+--- 10027,10033 ----
+
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+! ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ ac_file=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_cmds # Line after last line for current file.
+Index: configure.in
+diff -c mdn/othersrc/bind9/configure.in:1.1.1.9 mdn/othersrc/bind9/configure.in:1.15
+*** configure.in Wed May 22 17:14:53 2002
+--- configure.in Mon May 27 12:10:14 2002
+***************
+*** 1614,1619 ****
+--- 1614,1695 ----
+ NOM_PATH_FILE(DOCBOOK2MANSPEC, docbook2X/docbook2man-spec.pl, $sgmltrees)
+
+ #
++ # IDN support
++ #
++ AC_ARG_WITH(idn,
++ [ --with-idn[=MPREFIX] enable IDN support using idnkit [default PREFIX]],
++ use_idn="$withval", use_idn="no")
++ case "$use_idn" in
++ yes)
++ if test X$prefix = XNONE ; then
++ idn_path=/usr/local
++ else
++ idn_path=$prefix
++ fi
++ ;;
++ no)
++ ;;
++ *)
++ idn_path="$use_idn"
++ ;;
++ esac
++
++ iconvinc=
++ iconvlib=
++ AC_ARG_WITH(libiconv,
++ [ --with-libiconv[=IPREFIX] GNU libiconv are in IPREFIX [default PREFIX]],
++ use_libiconv="$withval", use_libiconv="no")
++ case "$use_libiconv" in
++ yes)
++ if test X$prefix = XNONE ; then
++ iconvlib="-L/usr/local/lib -R/usr/local/lib -liconv"
++ else
++ iconvlib="-L$prefix/lib -R$prefix/lib -liconv"
++ fi
++ ;;
++ no)
++ iconvlib=
++ ;;
++ *)
++ iconvlib="-L$use_libiconv/lib -R$use_libiconv/lib -liconv"
++ ;;
++ esac
++
++ AC_ARG_WITH(iconv,
++ [ --with-iconv[=LIBSPEC] specify iconv library [default -liconv]],
++ iconvlib="$withval")
++ case "$iconvlib" in
++ no)
++ iconvlib=
++ ;;
++ yes)
++ iconvlib=-liconv
++ ;;
++ esac
++
++ AC_ARG_WITH(idnlib,
++ [ --with-idnlib=ARG specify libidnkit],
++ idnlib="$withval", idnlib="no")
++ if test "$idnlib" = yes; then
++ AC_MSG_ERROR([You must specify ARG for --with-idnlib.])
++ fi
++
++ IDNLIBS=
++ if test "$use_idn" != no; then
++ AC_DEFINE(WITH_IDN, 1, [define if idnkit support is to be included.])
++ STD_CINCLUDES="$STD_CINCLUDES -I$idn_path/include"
++ if test "$idnlib" != no; then
++ IDNLIBS="$idnlib $iconvlib"
++ else
++ IDNLIBS="-L$idn_path/lib -lidnkit $iconvlib"
++ fi
++ fi
++ AC_SUBST(IDNLIBS)
++
++ AC_CHECK_HEADERS(locale.h)
++ AC_CHECK_FUNCS(setlocale)
++
++ #
+ # Substitutions
+ #
+ AC_SUBST(BIND9_TOP_BUILDDIR)
+Index: bin/dig/Makefile.in
+diff -c mdn/othersrc/bind9/bin/dig/Makefile.in:1.1.1.6 mdn/othersrc/bind9/bin/dig/Makefile.in:1.3
+*** bin/dig/Makefile.in Tue Nov 27 16:55:50 2001
+--- bin/dig/Makefile.in Tue Mar 19 16:45:35 2002
+***************
+*** 36,42 ****
+
+ DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+! LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+ SUBDIRS =
+
+--- 36,42 ----
+
+ DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+! LIBS = ${DNSLIBS} ${ISCLIBS} @IDNLIBS@ @LIBS@
+
+ SUBDIRS =
+
+Index: bin/dig/dig.1
+diff -c mdn/othersrc/bind9/bin/dig/dig.1:1.1.1.2 mdn/othersrc/bind9/bin/dig/dig.1:1.4
+*** bin/dig/dig.1 Wed May 22 17:14:53 2002
+--- bin/dig/dig.1 Mon May 27 12:10:14 2002
+***************
+*** 349,354 ****
+--- 349,365 ----
+ \fI+noqr\fR which means that \fBdig\fR
+ will not print the initial query when it looks up the NS records for
+ isc.org.
++ .SH "IDN SUPPORT"
++ .PP
++ If \fBdig\fR has been built with IDN (internationalized
++ domain name) support, it can accept and display non-ASCII domain names.
++ \fBdig\fR appropriately converts character encoding of
++ domain name before sending a request to DNS server or displaying a
++ reply from the server.
++ If you'd like to turn off the IDN support for some reason, defines
++ the \fBIDN_DISABLE\fR environment variable.
++ The IDN support is disabled if the the variable is set when
++ \fBdig\fR runs.
+ .SH "FILES"
+ .PP
+ \fI/etc/resolv.conf\fR
+Index: bin/dig/dig.docbook
+diff -c mdn/othersrc/bind9/bin/dig/dig.docbook:1.1.1.2 mdn/othersrc/bind9/bin/dig/dig.docbook:1.4
+*** bin/dig/dig.docbook Wed May 22 17:14:53 2002
+--- bin/dig/dig.docbook Mon May 27 12:10:15 2002
+***************
+*** 523,528 ****
+--- 523,543 ----
+ </refsect1>
+
+ <refsect1>
++ <title>IDN SUPPORT</title>
++ <para>
++ If <command>dig</command> has been built with IDN (internationalized
++ domain name) support, it can accept and display non-ASCII domain names.
++ <command>dig</command> appropriately converts character encoding of
++ domain name before sending a request to DNS server or displaying a
++ reply from the server.
++ If you'd like to turn off the IDN support for some reason, defines
++ the <envar>IDN_DISABLE</envar> environment variable.
++ The IDN support is disabled if the the variable is set when
++ <command>dig</command> runs.
++ </para>
++ </refsect1>
++
++ <refsect1>
+ <title>FILES</title>
+ <para>
+ <filename>/etc/resolv.conf</filename>
+Index: bin/dig/dighost.c
+diff -c mdn/othersrc/bind9/bin/dig/dighost.c:1.1.1.12 mdn/othersrc/bind9/bin/dig/dighost.c:1.32
+*** bin/dig/dighost.c Wed May 22 17:14:53 2002
+--- bin/dig/dighost.c Mon May 27 12:10:15 2002
+***************
+*** 32,37 ****
+--- 32,48 ----
+ #include <string.h>
+ #include <limits.h>
+
++ #ifdef HAVE_LOCALE_H
++ #include <locale.h>
++ #endif
++
++ #ifdef WITH_IDN
++ #include <idn/result.h>
++ #include <idn/log.h>
++ #include <idn/resconf.h>
++ #include <idn/api.h>
++ #endif
++
+ #include <dns/byaddr.h>
+ #include <dns/fixedname.h>
+ #include <dns/message.h>
+***************
+*** 130,135 ****
+--- 141,158 ----
+ isc_mutex_t lookup_lock;
+ dig_lookup_t *current_lookup = NULL;
+
++ #ifdef WITH_IDN
++ static void initialize_idn(void);
++ static isc_result_t output_filter(isc_buffer_t *buffer,
++ unsigned int used_org,
++ isc_boolean_t absolute);
++ static idn_result_t append_textname(char *name, const char *origin,
++ size_t namesize);
++ static void idn_check_result(idn_result_t r, const char *msg);
++
++ #define MAXDLEN 256
++ #endif
++
+ /*
+ * Apply and clear locks at the event level in global task.
+ * Can I get rid of these using shutdown events? XXX
+***************
+*** 648,653 ****
+--- 671,680 ----
+ ISC_LIST_APPEND(server_list, srv, link);
+ }
+
++ #ifdef WITH_IDN
++ initialize_idn();
++ #endif
++
+ if (keyfile[0] != 0)
+ setup_file_key();
+ else if (keysecret[0] != 0)
+***************
+*** 1168,1173 ****
+--- 1195,1208 ----
+ isc_buffer_t b;
+ dns_compress_t cctx;
+ char store[MXNAME];
++ #ifdef WITH_IDN
++ idn_result_t mr;
++ char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
++ #endif
++
++ #ifdef WITH_IDN
++ dns_name_settotextfilter(output_filter);
++ #endif
+
+ REQUIRE(lookup != NULL);
+ INSIST(!free_now);
+***************
+*** 1196,1201 ****
+--- 1231,1247 ----
+ isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
+ sizeof(lookup->onamespace));
+
++ #ifdef WITH_IDN
++ /*
++ * We cannot convert `textname' and `origin' separately.
++ * `textname' doesn't contain TLD, but local mapping needs
++ * TLD.
++ */
++ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
++ utf8_textname, sizeof(utf8_textname));
++ idn_check_result(mr, "convert textname to UTF-8");
++ #endif
++
+ /*
+ * If the name has too many dots, force the origin to be NULL
+ * (which produces an absolute lookup). Otherwise, take the origin
+***************
+*** 1204,1215 ****
+--- 1250,1290 ----
+ * is TRUE or we got a domain line in the resolv.conf file.
+ */
+ /* XXX New search here? */
++ #ifdef WITH_IDN
++ if ((count_dots(utf8_textname) >= ndots) || !usesearch)
++ lookup->origin = NULL; /* Force abs lookup */
++ else if (lookup->origin == NULL && lookup->new_search && usesearch) {
++ lookup->origin = ISC_LIST_HEAD(search_list);
++ }
++ #else
+ if ((count_dots(lookup->textname) >= ndots) || !usesearch)
+ lookup->origin = NULL; /* Force abs lookup */
+ else if (lookup->origin == NULL && lookup->new_search && usesearch) {
+ lookup->origin = ISC_LIST_HEAD(search_list);
+ }
++ #endif
++
++ #ifdef WITH_IDN
+ if (lookup->origin != NULL) {
++ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
++ lookup->origin->origin, utf8_origin,
++ sizeof(utf8_origin));
++ idn_check_result(mr, "convert origin to UTF-8");
++ mr = append_textname(utf8_textname, utf8_origin,
++ sizeof(utf8_textname));
++ idn_check_result(mr, "append origin to textname");
++ }
++ mr = idn_encodename(IDN_LOCALMAP | IDN_NAMEPREP | IDN_ASCCHECK |
++ IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
++ idn_textname, sizeof(idn_textname));
++ idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
++ #endif
++
++ #ifdef WITH_IDN
++ if (0) {
++ #else
++ if (lookup->origin != NULL) {
++ #endif
+ debug("trying origin %s", lookup->origin->origin);
+ result = dns_message_gettempname(lookup->sendmsg,
+ &lookup->oname);
+***************
+*** 1254,1259 ****
+--- 1329,1343 ----
+ if (lookup->trace && lookup->trace_root)
+ dns_name_clone(dns_rootname, lookup->name);
+ else {
++ #ifdef WITH_IDN
++ len = strlen(idn_textname);
++ isc_buffer_init(&b, idn_textname, len);
++ isc_buffer_add(&b, len);
++ result = dns_name_fromtext(lookup->name, &b,
++ dns_rootname,
++ ISC_FALSE,
++ &lookup->namebuf);
++ #else
+ len = strlen(lookup->textname);
+ isc_buffer_init(&b, lookup->textname, len);
+ isc_buffer_add(&b, len);
+***************
+*** 1261,1266 ****
+--- 1345,1351 ----
+ dns_rootname,
+ ISC_FALSE,
+ &lookup->namebuf);
++ #endif
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg,
+***************
+*** 2591,2593 ****
+--- 2676,2776 ----
+ if (mctx != NULL)
+ isc_mem_destroy(&mctx);
+ }
++
++ #ifdef WITH_IDN
++ static void
++ initialize_idn(void) {
++ idn_result_t r;
++
++ #ifdef HAVE_SETLOCALE
++ /* Set locale */
++ (void)setlocale(LC_ALL, "");
++ #endif
++ /* Create configuration context. */
++ r = idn_nameinit(1);
++ if (r != idn_success)
++ fatal("idn api initialization failed: %s",
++ idn_result_tostring(r));
++
++ /* Set domain name -> text post-conversion filter. */
++ dns_name_settotextfilter(output_filter);
++ }
++
++ static isc_result_t
++ output_filter(isc_buffer_t *buffer, unsigned int used_org,
++ isc_boolean_t absolute)
++ {
++ char tmp1[MAXDLEN], tmp2[MAXDLEN];
++ size_t fromlen, tolen;
++ isc_boolean_t end_with_dot;
++
++ /*
++ * Copy contents of 'buffer' to 'tmp1', supply trailing dot
++ * if 'absolute' is true, and terminate with NUL.
++ */
++ fromlen = isc_buffer_usedlength(buffer) - used_org;
++ if (fromlen >= MAXDLEN)
++ return (ISC_R_SUCCESS);
++ memcpy(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
++ end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
++ if (absolute && !end_with_dot) {
++ fromlen++;
++ if (fromlen >= MAXDLEN)
++ return (ISC_R_SUCCESS);
++ tmp1[fromlen - 1] = '.';
++ }
++ tmp1[fromlen] = '\0';
++
++ /*
++ * Convert contents of 'tmp1' to local encoding.
++ */
++ if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
++ return (ISC_R_SUCCESS);
++ strcpy(tmp1, tmp2);
++
++ /*
++ * Copy the converted contents in 'tmp1' back to 'buffer'.
++ * If we have appended trailing dot, remove it.
++ */
++ tolen = strlen(tmp1);
++ if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
++ tolen--;
++
++ if (isc_buffer_length(buffer) < used_org + tolen)
++ return (ISC_R_NOSPACE);
++
++ isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
++ memcpy(isc_buffer_used(buffer), tmp1, tolen);
++ isc_buffer_add(buffer, tolen);
++
++ return (ISC_R_SUCCESS);
++ }
++
++ static idn_result_t
++ append_textname(char *name, const char *origin, size_t namesize) {
++ size_t namelen = strlen(name);
++ size_t originlen = strlen(origin);
++
++ /* Already absolute? */
++ if (namelen > 0 && name[namelen - 1] == '.')
++ return idn_success;
++
++ /* Append dot and origin */
++
++ if (namelen + 1 + originlen >= namesize)
++ return idn_buffer_overflow;
++
++ name[namelen++] = '.';
++ (void)strcpy(name + namelen, origin);
++ return idn_success;
++ }
++
++ static void
++ idn_check_result(idn_result_t r, const char *msg) {
++ if (r != idn_success) {
++ exitcode = 1;
++ fatal("%s: %s", msg, idn_result_tostring(r));
++ }
++ }
++
++ #endif /* WITH_IDN */
+Index: bin/dig/host.1
+diff -c mdn/othersrc/bind9/bin/dig/host.1:1.1.1.1 mdn/othersrc/bind9/bin/dig/host.1:1.3
+*** bin/dig/host.1 Tue Nov 27 16:55:51 2001
+--- bin/dig/host.1 Tue Mar 19 16:45:36 2002
+***************
+*** 120,125 ****
+--- 120,136 ----
+ effectively wait forever for a reply. The time to wait for a response
+ will be set to the number of seconds given by the hardware's maximum
+ value for an integer quantity.
++ .SH "IDN SUPPORT"
++ .PP
++ If \fBhost\fR has been built with IDN (internationalized
++ domain name) support, it can accept and display non-ASCII domain names.
++ \fBhost\fR appropriately converts character encoding of
++ domain name before sending a request to DNS server or displaying a
++ reply from the server.
++ If you'd like to turn off the IDN support for some reason, defines
++ the \fBIDN_DISABLE\fR environment variable.
++ The IDN support is disabled if the the variable is set when
++ \fBhost\fR runs.
+ .SH "FILES"
+ .PP
+ \fI/etc/resolv.conf\fR
+Index: bin/dig/host.docbook
+diff -c mdn/othersrc/bind9/bin/dig/host.docbook:1.1.1.1 mdn/othersrc/bind9/bin/dig/host.docbook:1.3
+*** bin/dig/host.docbook Tue Nov 27 16:55:51 2001
+--- bin/dig/host.docbook Tue Mar 19 16:45:36 2002
+***************
+*** 181,186 ****
+--- 181,201 ----
+ </refsect1>
+
+ <refsect1>
++ <title>IDN SUPPORT</title>
++ <para>
++ If <command>host</command> has been built with IDN (internationalized
++ domain name) support, it can accept and display non-ASCII domain names.
++ <command>host</command> appropriately converts character encoding of
++ domain name before sending a request to DNS server or displaying a
++ reply from the server.
++ If you'd like to turn off the IDN support for some reason, defines
++ the <envar>IDN_DISABLE</envar> environment variable.
++ The IDN support is disabled if the the variable is set when
++ <command>host</command> runs.
++ </para>
++ </refsect1>
++
++ <refsect1>
+ <title>FILES</title>
+ <para>
+ <filename>/etc/resolv.conf</filename>
+Index: lib/dns/name.c
+diff -c mdn/othersrc/bind9/lib/dns/name.c:1.1.1.10 mdn/othersrc/bind9/lib/dns/name.c:1.14
+*** lib/dns/name.c Wed May 22 17:15:27 2002
+--- lib/dns/name.c Mon May 27 12:10:15 2002
+***************
+*** 194,199 ****
+--- 194,206 ----
+ /* XXXDCL make const? */
+ dns_name_t *dns_wildcardname = &wild;
+
++ #ifdef WITH_IDN
++ /*
++ * dns_name_t to text post-conversion procedure.
++ */
++ static dns_name_totextfilter_t totext_filter_proc = NULL;
++ #endif
++
+ static void
+ set_offsets(const dns_name_t *name, unsigned char *offsets,
+ dns_name_t *set_name);
+***************
+*** 1682,1687 ****
+--- 1689,1697 ----
+ unsigned int labels;
+ isc_boolean_t saw_root = ISC_FALSE;
+ char num[4];
++ #ifdef WITH_IDN
++ unsigned int oused = target->used;
++ #endif
+
+ /*
+ * This function assumes the name is in proper uncompressed
+***************
+*** 1859,1864 ****
+--- 1869,1878 ----
+
+ isc_buffer_add(target, tlen - trem);
+
++ #ifdef WITH_IDN
++ if (totext_filter_proc != NULL)
++ return ((*totext_filter_proc)(target, oused, saw_root));
++ #endif
+ return (ISC_R_SUCCESS);
+ }
+
+***************
+*** 3315,3317 ****
+--- 3329,3337 ----
+ return (ISC_R_SUCCESS);
+ }
+
++ #ifdef WITH_IDN
++ void
++ dns_name_settotextfilter(dns_name_totextfilter_t proc) {
++ totext_filter_proc = proc;
++ }
++ #endif
+Index: lib/dns/include/dns/name.h
+diff -c mdn/othersrc/bind9/lib/dns/include/dns/name.h:1.1.1.7 mdn/othersrc/bind9/lib/dns/include/dns/name.h:1.10
+*** lib/dns/include/dns/name.h Wed May 22 17:15:29 2002
+--- lib/dns/include/dns/name.h Mon May 27 12:10:15 2002
+***************
+*** 219,224 ****
+--- 219,235 ----
+ */
+ #define DNS_NAME_MAXWIRE 255
+
++ #ifdef WITH_IDN
++ /*
++ * Text output filter procedure.
++ * 'target' is the buffer to be converted. The region to be converted
++ * is from 'buffer'->base + 'used_org' to the end of the used region.
++ */
++ typedef isc_result_t (*dns_name_totextfilter_t)(isc_buffer_t *target,
++ unsigned int used_org,
++ isc_boolean_t absolute);
++ #endif
++
+ /***
+ *** Initialization
+ ***/
+***************
+*** 1244,1249 ****
+--- 1255,1268 ----
+ * 'size' > 0.
+ *
+ */
++
++ #ifdef WITH_IDN
++ void
++ dns_name_settotextfilter(dns_name_totextfilter_t proc);
++ /*
++ * Call 'proc' at the end of dns_name_totext.
++ */
++ #endif /* WITH_IDN */
+
+ #define DNS_NAME_FORMATSIZE (DNS_NAME_MAXTEXT + 1)
+ /*
diff --git a/contrib/idn/idnkit-1.0-src/patch/bind9/bind-9.2.2-patch b/contrib/idn/idnkit-1.0-src/patch/bind9/bind-9.2.2-patch
new file mode 100644
index 0000000..ccf4355
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/patch/bind9/bind-9.2.2-patch
@@ -0,0 +1,1169 @@
+IDN patch for bind-9.2.2
+========================
+
+
+This is a patch file for ISC BIND 9.2.2 to make it work with
+internationalized domain names. With this patch you'll get IDN-aware
+dig/host/nslookup.
+
+To apply this patch, you should go to the top directory of the BIND
+distribution (where you see `README' file), then invoke `patch'
+command like this:
+
+ % patch -p0 < this-file
+
+Then follow the instructions described in `README.idnkit' to compile
+and install.
+
+
+Index: README.idnkit
+diff -c /dev/null mdn/othersrc/bind9/README.idnkit:1.3
+*** README.idnkit Tue Mar 11 08:55:20 2003
+--- README.idnkit Mon Mar 10 09:47:41 2003
+***************
+*** 0 ****
+--- 1,113 ----
++
++ 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 exacutable 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 doens'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 argments, 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: bind-9.2.2-patch,v 1.1.1.1 2003/06/04 00:27:32 marka Exp $
+Index: config.h.in
+diff -c mdn/othersrc/bind9/config.h.in:1.1.1.6 mdn/othersrc/bind9/config.h.in:1.12
+*** config.h.in Tue Nov 27 16:55:45 2001
+--- config.h.in Tue Mar 19 16:45:35 2002
+***************
+*** 141,146 ****
+--- 141,149 ----
+ /* define if you have strerror in the C library. */
+ #undef HAVE_STRERROR
+
++ /* Define if you have the setlocale function. */
++ #undef HAVE_SETLOCALE
++
+ /* Define if you have the <dlfcn.h> header file. */
+ #undef HAVE_DLFCN_H
+
+***************
+*** 150,155 ****
+--- 153,161 ----
+ /* Define if you have the <linux/capability.h> header file. */
+ #undef HAVE_LINUX_CAPABILITY_H
+
++ /* Define if you have the <locale.h> header file. */
++ #undef HAVE_LOCALE_H
++
+ /* Define if you have the <sys/prctl.h> header file. */
+ #undef HAVE_SYS_PRCTL_H
+
+***************
+*** 176,178 ****
+--- 182,188 ----
+
+ /* Define if you have the socket library (-lsocket). */
+ #undef HAVE_LIBSOCKET
++
++ /* define if idnkit support is to be included. */
++ #undef WITH_IDN
++
+Index: configure
+diff -c mdn/othersrc/bind9/configure:1.1.1.10 mdn/othersrc/bind9/configure:1.16
+*** configure Wed Mar 5 17:14:55 2003
+--- configure Thu Mar 6 20:10:05 2003
+***************
+*** 1007,1012 ****
+--- 1007,1016 ----
+ --with-gnu-ld assume the C compiler uses GNU ld default=no
+ --with-pic try to use only PIC/non-PIC objects default=use both
+ --with-kame=PATH use Kame IPv6 default path /usr/local/v6
++ --with-idn=MPREFIX enable IDN support using idnkit default PREFIX
++ --with-libiconv=IPREFIX GNU libiconv are in IPREFIX default PREFIX
++ --with-iconv=LIBSPEC specify iconv library default -liconv
++ --with-idnlib=ARG specify libidnkit
+
+ Some influential environment variables:
+ CC C compiler command
+***************
+*** 7371,7377 ****
+ case $host in
+ *-*-irix6*)
+ # Find out which ABI we are using.
+! echo '#line 7374 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+--- 7375,7381 ----
+ case $host in
+ *-*-irix6*)
+ # Find out which ABI we are using.
+! echo '#line 7378 "configure"' > conftest.$ac_ext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+***************
+*** 7914,7920 ****
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+ compiler_c_o=no
+! if { (eval echo configure:7917: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s out/conftest.err; then
+--- 7918,7924 ----
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
+ compiler_c_o=no
+! if { (eval echo configure:7921: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s out/conftest.err; then
+***************
+*** 9599,9605 ****
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+! #line 9602 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+--- 9603,9609 ----
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+! #line 9606 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+***************
+*** 9697,9703 ****
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+! #line 9700 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+--- 9701,9707 ----
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+! #line 9704 "configure"
+ #include "confdefs.h"
+
+ #if HAVE_DLFCN_H
+***************
+*** 13265,13270 ****
+--- 13269,13580 ----
+
+
+ #
++ # IDN support
++ #
++
++ # Check whether --with-idn or --without-idn was given.
++ if test "${with_idn+set}" = set; then
++ withval="$with_idn"
++ use_idn="$withval"
++ else
++ use_idn="no"
++ fi;
++ case "$use_idn" in
++ yes)
++ if test X$prefix = XNONE ; then
++ idn_path=/usr/local
++ else
++ idn_path=$prefix
++ fi
++ ;;
++ no)
++ ;;
++ *)
++ idn_path="$use_idn"
++ ;;
++ esac
++
++ iconvinc=
++ iconvlib=
++
++ # Check whether --with-libiconv or --without-libiconv was given.
++ if test "${with_libiconv+set}" = set; then
++ withval="$with_libiconv"
++ use_libiconv="$withval"
++ else
++ use_libiconv="no"
++ fi;
++ case "$use_libiconv" in
++ yes)
++ if test X$prefix = XNONE ; then
++ iconvlib="-L/usr/local/lib -R/usr/local/lib -liconv"
++ else
++ iconvlib="-L$prefix/lib -R$prefix/lib -liconv"
++ fi
++ ;;
++ no)
++ iconvlib=
++ ;;
++ *)
++ iconvlib="-L$use_libiconv/lib -R$use_libiconv/lib -liconv"
++ ;;
++ esac
++
++
++ # Check whether --with-iconv or --without-iconv was given.
++ if test "${with_iconv+set}" = set; then
++ withval="$with_iconv"
++ iconvlib="$withval"
++ fi;
++ case "$iconvlib" in
++ no)
++ iconvlib=
++ ;;
++ yes)
++ iconvlib=-liconv
++ ;;
++ esac
++
++
++ # Check whether --with-idnlib or --without-idnlib was given.
++ if test "${with_idnlib+set}" = set; then
++ withval="$with_idnlib"
++ idnlib="$withval"
++ else
++ idnlib="no"
++ fi;
++ if test "$idnlib" = yes; then
++ { { echo "$as_me:$LINENO: error: You must specify ARG for --with-idnlib." >&5
++ echo "$as_me: error: You must specify ARG for --with-idnlib." >&2;}
++ { (exit 1); exit 1; }; }
++ fi
++
++ IDNLIBS=
++ if test "$use_idn" != no; then
++
++ cat >>confdefs.h <<\_ACEOF
++ #define WITH_IDN 1
++ _ACEOF
++
++ STD_CINCLUDES="$STD_CINCLUDES -I$idn_path/include"
++ if test "$idnlib" != no; then
++ IDNLIBS="$idnlib $iconvlib"
++ else
++ IDNLIBS="-L$idn_path/lib -lidnkit $iconvlib"
++ fi
++ fi
++
++
++
++ for ac_header in locale.h
++ do
++ as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
++ if eval "test \"\${$as_ac_Header+set}\" = set"; then
++ echo "$as_me:$LINENO: checking for $ac_header" >&5
++ echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
++ if eval "test \"\${$as_ac_Header+set}\" = set"; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++ fi
++ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
++ echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
++ else
++ # Is the header compilable?
++ echo "$as_me:$LINENO: checking $ac_header usability" >&5
++ echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
++ cat >conftest.$ac_ext <<_ACEOF
++ #line $LINENO "configure"
++ #include "confdefs.h"
++ $ac_includes_default
++ #include <$ac_header>
++ _ACEOF
++ rm -f conftest.$ac_objext
++ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
++ (eval $ac_compile) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest.$ac_objext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ ac_header_compiler=yes
++ else
++ echo "$as_me: failed program was:" >&5
++ cat conftest.$ac_ext >&5
++ ac_header_compiler=no
++ fi
++ rm -f conftest.$ac_objext conftest.$ac_ext
++ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
++ echo "${ECHO_T}$ac_header_compiler" >&6
++
++ # Is the header present?
++ echo "$as_me:$LINENO: checking $ac_header presence" >&5
++ echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
++ cat >conftest.$ac_ext <<_ACEOF
++ #line $LINENO "configure"
++ #include "confdefs.h"
++ #include <$ac_header>
++ _ACEOF
++ if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
++ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
++ ac_status=$?
++ egrep -v '^ *\+' conftest.er1 >conftest.err
++ rm -f conftest.er1
++ cat conftest.err >&5
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } >/dev/null; then
++ if test -s conftest.err; then
++ ac_cpp_err=$ac_c_preproc_warn_flag
++ else
++ ac_cpp_err=
++ fi
++ else
++ ac_cpp_err=yes
++ fi
++ if test -z "$ac_cpp_err"; then
++ ac_header_preproc=yes
++ else
++ echo "$as_me: failed program was:" >&5
++ cat conftest.$ac_ext >&5
++ ac_header_preproc=no
++ fi
++ rm -f conftest.err conftest.$ac_ext
++ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
++ echo "${ECHO_T}$ac_header_preproc" >&6
++
++ # So? What about this header?
++ case $ac_header_compiler:$ac_header_preproc in
++ yes:no )
++ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
++ echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
++ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
++ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
++ no:yes )
++ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
++ echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
++ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
++ echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
++ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
++ echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;};;
++ esac
++ echo "$as_me:$LINENO: checking for $ac_header" >&5
++ echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
++ if eval "test \"\${$as_ac_Header+set}\" = set"; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++ else
++ eval "$as_ac_Header=$ac_header_preproc"
++ fi
++ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
++ echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
++
++ fi
++ if test `eval echo '${'$as_ac_Header'}'` = yes; then
++ cat >>confdefs.h <<_ACEOF
++ #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
++ _ACEOF
++
++ fi
++
++ done
++
++
++ for ac_func in setlocale
++ do
++ as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
++ echo "$as_me:$LINENO: checking for $ac_func" >&5
++ echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
++ if eval "test \"\${$as_ac_var+set}\" = set"; then
++ echo $ECHO_N "(cached) $ECHO_C" >&6
++ else
++ cat >conftest.$ac_ext <<_ACEOF
++ #line $LINENO "configure"
++ #include "confdefs.h"
++ /* From autoconf 2.57 */
++ /* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
++ For example, HP-UX 11i <limits.h> declares gettimeofday. */
++ #define $ac_func innocuous_$ac_func
++
++ /* System header to define __stub macros and hopefully few prototypes,
++ which can conflict with char $ac_func (); below.
++ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
++ <limits.h> exists even on freestanding compilers. */
++
++ #ifdef __STDC__
++ # include <limits.h>
++ #else
++ # include <assert.h>
++ #endif
++
++ #undef $ac_func
++
++ /* Override any gcc2 internal prototype to avoid an error. */
++ #ifdef __cplusplus
++ extern "C"
++ {
++ #endif
++ /* We use char because int might match the return type of a gcc2
++ builtin and then its argument prototype would still apply. */
++ char $ac_func ();
++ /* The GNU C library defines this for functions which it implements
++ to always fail with ENOSYS. Some functions are actually named
++ something starting with __ and the normal name is an alias. */
++ #if defined (__stub_$ac_func) || defined (__stub___$ac_func)
++ choke me
++ #else
++ char (*f) () = $ac_func;
++ #endif
++ #ifdef __cplusplus
++ }
++ #endif
++
++ #ifdef F77_DUMMY_MAIN
++ # ifdef __cplusplus
++ extern "C"
++ # endif
++ int F77_DUMMY_MAIN() { return 1; }
++ #endif
++ int
++ main ()
++ {
++ return f != $ac_func;
++ ;
++ return 0;
++ }
++ _ACEOF
++ rm -f conftest.$ac_objext conftest$ac_exeext
++ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
++ (eval $ac_link) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); } &&
++ { ac_try='test -s conftest$ac_exeext'
++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ echo "$as_me:$LINENO: \$? = $ac_status" >&5
++ (exit $ac_status); }; }; then
++ eval "$as_ac_var=yes"
++ else
++ echo "$as_me: failed program was:" >&5
++ cat conftest.$ac_ext >&5
++ eval "$as_ac_var=no"
++ fi
++ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
++ fi
++ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
++ echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
++ if test `eval echo '${'$as_ac_var'}'` = yes; then
++ cat >>confdefs.h <<_ACEOF
++ #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
++ _ACEOF
++
++ fi
++ done
++
++
++ #
+ # Substitutions
+ #
+
+***************
+*** 14061,14066 ****
+--- 14371,14377 ----
+ s,@PRINTSTYLE@,$PRINTSTYLE,;t t
+ s,@XMLDCL@,$XMLDCL,;t t
+ s,@DOCBOOK2MANSPEC@,$DOCBOOK2MANSPEC,;t t
++ s,@IDNLIBS@,$IDNLIBS,;t t
+ s,@BIND9_TOP_BUILDDIR@,$BIND9_TOP_BUILDDIR,;t t
+ s,@BIND9_ISC_BUILDINCLUDE@,$BIND9_ISC_BUILDINCLUDE,;t t
+ s,@BIND9_ISCCC_BUILDINCLUDE@,$BIND9_ISCCC_BUILDINCLUDE,;t t
+Index: configure.in
+diff -c mdn/othersrc/bind9/configure.in:1.1.1.10 mdn/othersrc/bind9/configure.in:1.16
+*** configure.in Wed Mar 5 17:14:56 2003
+--- configure.in Wed Mar 5 17:37:08 2003
+***************
+*** 1681,1686 ****
+--- 1681,1762 ----
+ NOM_PATH_FILE(DOCBOOK2MANSPEC, docbook2X/docbook2man-spec.pl, $sgmltrees)
+
+ #
++ # IDN support
++ #
++ AC_ARG_WITH(idn,
++ [ --with-idn[=MPREFIX] enable IDN support using idnkit [default PREFIX]],
++ use_idn="$withval", use_idn="no")
++ case "$use_idn" in
++ yes)
++ if test X$prefix = XNONE ; then
++ idn_path=/usr/local
++ else
++ idn_path=$prefix
++ fi
++ ;;
++ no)
++ ;;
++ *)
++ idn_path="$use_idn"
++ ;;
++ esac
++
++ iconvinc=
++ iconvlib=
++ AC_ARG_WITH(libiconv,
++ [ --with-libiconv[=IPREFIX] GNU libiconv are in IPREFIX [default PREFIX]],
++ use_libiconv="$withval", use_libiconv="no")
++ case "$use_libiconv" in
++ yes)
++ if test X$prefix = XNONE ; then
++ iconvlib="-L/usr/local/lib -R/usr/local/lib -liconv"
++ else
++ iconvlib="-L$prefix/lib -R$prefix/lib -liconv"
++ fi
++ ;;
++ no)
++ iconvlib=
++ ;;
++ *)
++ iconvlib="-L$use_libiconv/lib -R$use_libiconv/lib -liconv"
++ ;;
++ esac
++
++ AC_ARG_WITH(iconv,
++ [ --with-iconv[=LIBSPEC] specify iconv library [default -liconv]],
++ iconvlib="$withval")
++ case "$iconvlib" in
++ no)
++ iconvlib=
++ ;;
++ yes)
++ iconvlib=-liconv
++ ;;
++ esac
++
++ AC_ARG_WITH(idnlib,
++ [ --with-idnlib=ARG specify libidnkit],
++ idnlib="$withval", idnlib="no")
++ if test "$idnlib" = yes; then
++ AC_MSG_ERROR([You must specify ARG for --with-idnlib.])
++ fi
++
++ IDNLIBS=
++ if test "$use_idn" != no; then
++ AC_DEFINE(WITH_IDN, 1, [define if idnkit support is to be included.])
++ STD_CINCLUDES="$STD_CINCLUDES -I$idn_path/include"
++ if test "$idnlib" != no; then
++ IDNLIBS="$idnlib $iconvlib"
++ else
++ IDNLIBS="-L$idn_path/lib -lidnkit $iconvlib"
++ fi
++ fi
++ AC_SUBST(IDNLIBS)
++
++ AC_CHECK_HEADERS(locale.h)
++ AC_CHECK_FUNCS(setlocale)
++
++ #
+ # Substitutions
+ #
+ AC_SUBST(BIND9_TOP_BUILDDIR)
+Index: bin/dig/Makefile.in
+diff -c mdn/othersrc/bind9/bin/dig/Makefile.in:1.1.1.6 mdn/othersrc/bind9/bin/dig/Makefile.in:1.3
+*** bin/dig/Makefile.in Tue Nov 27 16:55:50 2001
+--- bin/dig/Makefile.in Tue Mar 19 16:45:35 2002
+***************
+*** 36,42 ****
+
+ DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+! LIBS = ${DNSLIBS} ${ISCLIBS} @LIBS@
+
+ SUBDIRS =
+
+--- 36,42 ----
+
+ DEPLIBS = ${DNSDEPLIBS} ${ISCDEPLIBS}
+
+! LIBS = ${DNSLIBS} ${ISCLIBS} @IDNLIBS@ @LIBS@
+
+ SUBDIRS =
+
+Index: bin/dig/dig.1
+diff -c mdn/othersrc/bind9/bin/dig/dig.1:1.1.1.3 mdn/othersrc/bind9/bin/dig/dig.1:1.5
+*** bin/dig/dig.1 Wed Mar 5 17:14:57 2003
+--- bin/dig/dig.1 Wed Mar 5 17:42:53 2003
+***************
+*** 349,354 ****
+--- 349,365 ----
+ \fI+noqr\fR which means that \fBdig\fR
+ will not print the initial query when it looks up the NS records for
+ isc.org.
++ .SH "IDN SUPPORT"
++ .PP
++ If \fBdig\fR has been built with IDN (internationalized
++ domain name) support, it can accept and display non-ASCII domain names.
++ \fBdig\fR appropriately converts character encoding of
++ domain name before sending a request to DNS server or displaying a
++ reply from the server.
++ If you'd like to turn off the IDN support for some reason, defines
++ the \fBIDN_DISABLE\fR environment variable.
++ The IDN support is disabled if the the variable is set when
++ \fBdig\fR runs.
+ .SH "FILES"
+ .PP
+ \fI/etc/resolv.conf\fR
+Index: bin/dig/dig.docbook
+diff -c mdn/othersrc/bind9/bin/dig/dig.docbook:1.1.1.3 mdn/othersrc/bind9/bin/dig/dig.docbook:1.5
+*** bin/dig/dig.docbook Wed Mar 5 17:14:57 2003
+--- bin/dig/dig.docbook Wed Mar 5 17:42:53 2003
+***************
+*** 523,528 ****
+--- 523,543 ----
+ </refsect1>
+
+ <refsect1>
++ <title>IDN SUPPORT</title>
++ <para>
++ If <command>dig</command> has been built with IDN (internationalized
++ domain name) support, it can accept and display non-ASCII domain names.
++ <command>dig</command> appropriately converts character encoding of
++ domain name before sending a request to DNS server or displaying a
++ reply from the server.
++ If you'd like to turn off the IDN support for some reason, defines
++ the <envar>IDN_DISABLE</envar> environment variable.
++ The IDN support is disabled if the the variable is set when
++ <command>dig</command> runs.
++ </para>
++ </refsect1>
++
++ <refsect1>
+ <title>FILES</title>
+ <para>
+ <filename>/etc/resolv.conf</filename>
+Index: bin/dig/dighost.c
+diff -c mdn/othersrc/bind9/bin/dig/dighost.c:1.1.1.13 mdn/othersrc/bind9/bin/dig/dighost.c:1.33
+*** bin/dig/dighost.c Wed Mar 5 17:14:57 2003
+--- bin/dig/dighost.c Wed Mar 5 17:42:53 2003
+***************
+*** 32,37 ****
+--- 32,48 ----
+ #include <string.h>
+ #include <limits.h>
+
++ #ifdef HAVE_LOCALE_H
++ #include <locale.h>
++ #endif
++
++ #ifdef WITH_IDN
++ #include <idn/result.h>
++ #include <idn/log.h>
++ #include <idn/resconf.h>
++ #include <idn/api.h>
++ #endif
++
+ #include <dns/byaddr.h>
+ #include <dns/fixedname.h>
+ #include <dns/message.h>
+***************
+*** 130,135 ****
+--- 141,158 ----
+ isc_mutex_t lookup_lock;
+ dig_lookup_t *current_lookup = NULL;
+
++ #ifdef WITH_IDN
++ static void initialize_idn(void);
++ static isc_result_t output_filter(isc_buffer_t *buffer,
++ unsigned int used_org,
++ isc_boolean_t absolute);
++ static idn_result_t append_textname(char *name, const char *origin,
++ size_t namesize);
++ static void idn_check_result(idn_result_t r, const char *msg);
++
++ #define MAXDLEN 256
++ #endif
++
+ /*
+ * Apply and clear locks at the event level in global task.
+ * Can I get rid of these using shutdown events? XXX
+***************
+*** 648,653 ****
+--- 671,680 ----
+ ISC_LIST_APPEND(server_list, srv, link);
+ }
+
++ #ifdef WITH_IDN
++ initialize_idn();
++ #endif
++
+ if (keyfile[0] != 0)
+ setup_file_key();
+ else if (keysecret[0] != 0)
+***************
+*** 1168,1173 ****
+--- 1195,1208 ----
+ isc_buffer_t b;
+ dns_compress_t cctx;
+ char store[MXNAME];
++ #ifdef WITH_IDN
++ idn_result_t mr;
++ char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
++ #endif
++
++ #ifdef WITH_IDN
++ dns_name_settotextfilter(output_filter);
++ #endif
+
+ REQUIRE(lookup != NULL);
+ INSIST(!free_now);
+***************
+*** 1196,1201 ****
+--- 1231,1247 ----
+ isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
+ sizeof(lookup->onamespace));
+
++ #ifdef WITH_IDN
++ /*
++ * We cannot convert `textname' and `origin' separately.
++ * `textname' doesn't contain TLD, but local mapping needs
++ * TLD.
++ */
++ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
++ utf8_textname, sizeof(utf8_textname));
++ idn_check_result(mr, "convert textname to UTF-8");
++ #endif
++
+ /*
+ * If the name has too many dots, force the origin to be NULL
+ * (which produces an absolute lookup). Otherwise, take the origin
+***************
+*** 1204,1215 ****
+--- 1250,1290 ----
+ * is TRUE or we got a domain line in the resolv.conf file.
+ */
+ /* XXX New search here? */
++ #ifdef WITH_IDN
++ if ((count_dots(utf8_textname) >= ndots) || !usesearch)
++ lookup->origin = NULL; /* Force abs lookup */
++ else if (lookup->origin == NULL && lookup->new_search && usesearch) {
++ lookup->origin = ISC_LIST_HEAD(search_list);
++ }
++ #else
+ if ((count_dots(lookup->textname) >= ndots) || !usesearch)
+ lookup->origin = NULL; /* Force abs lookup */
+ else if (lookup->origin == NULL && lookup->new_search && usesearch) {
+ lookup->origin = ISC_LIST_HEAD(search_list);
+ }
++ #endif
++
++ #ifdef WITH_IDN
+ if (lookup->origin != NULL) {
++ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
++ lookup->origin->origin, utf8_origin,
++ sizeof(utf8_origin));
++ idn_check_result(mr, "convert origin to UTF-8");
++ mr = append_textname(utf8_textname, utf8_origin,
++ sizeof(utf8_textname));
++ idn_check_result(mr, "append origin to textname");
++ }
++ mr = idn_encodename(IDN_LOCALMAP | IDN_NAMEPREP | IDN_ASCCHECK |
++ IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
++ idn_textname, sizeof(idn_textname));
++ idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
++ #endif
++
++ #ifdef WITH_IDN
++ if (0) {
++ #else
++ if (lookup->origin != NULL) {
++ #endif
+ debug("trying origin %s", lookup->origin->origin);
+ result = dns_message_gettempname(lookup->sendmsg,
+ &lookup->oname);
+***************
+*** 1254,1259 ****
+--- 1329,1343 ----
+ if (lookup->trace && lookup->trace_root)
+ dns_name_clone(dns_rootname, lookup->name);
+ else {
++ #ifdef WITH_IDN
++ len = strlen(idn_textname);
++ isc_buffer_init(&b, idn_textname, len);
++ isc_buffer_add(&b, len);
++ result = dns_name_fromtext(lookup->name, &b,
++ dns_rootname,
++ ISC_FALSE,
++ &lookup->namebuf);
++ #else
+ len = strlen(lookup->textname);
+ isc_buffer_init(&b, lookup->textname, len);
+ isc_buffer_add(&b, len);
+***************
+*** 1261,1266 ****
+--- 1345,1351 ----
+ dns_rootname,
+ ISC_FALSE,
+ &lookup->namebuf);
++ #endif
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg,
+***************
+*** 2663,2665 ****
+--- 2748,2848 ----
+ if (mctx != NULL)
+ isc_mem_destroy(&mctx);
+ }
++
++ #ifdef WITH_IDN
++ static void
++ initialize_idn(void) {
++ idn_result_t r;
++
++ #ifdef HAVE_SETLOCALE
++ /* Set locale */
++ (void)setlocale(LC_ALL, "");
++ #endif
++ /* Create configuration context. */
++ r = idn_nameinit(1);
++ if (r != idn_success)
++ fatal("idn api initialization failed: %s",
++ idn_result_tostring(r));
++
++ /* Set domain name -> text post-conversion filter. */
++ dns_name_settotextfilter(output_filter);
++ }
++
++ static isc_result_t
++ output_filter(isc_buffer_t *buffer, unsigned int used_org,
++ isc_boolean_t absolute)
++ {
++ char tmp1[MAXDLEN], tmp2[MAXDLEN];
++ size_t fromlen, tolen;
++ isc_boolean_t end_with_dot;
++
++ /*
++ * Copy contents of 'buffer' to 'tmp1', supply trailing dot
++ * if 'absolute' is true, and terminate with NUL.
++ */
++ fromlen = isc_buffer_usedlength(buffer) - used_org;
++ if (fromlen >= MAXDLEN)
++ return (ISC_R_SUCCESS);
++ memcpy(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
++ end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_FALSE;
++ if (absolute && !end_with_dot) {
++ fromlen++;
++ if (fromlen >= MAXDLEN)
++ return (ISC_R_SUCCESS);
++ tmp1[fromlen - 1] = '.';
++ }
++ tmp1[fromlen] = '\0';
++
++ /*
++ * Convert contents of 'tmp1' to local encoding.
++ */
++ if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
++ return (ISC_R_SUCCESS);
++ strcpy(tmp1, tmp2);
++
++ /*
++ * Copy the converted contents in 'tmp1' back to 'buffer'.
++ * If we have appended trailing dot, remove it.
++ */
++ tolen = strlen(tmp1);
++ if (absolute && !end_with_dot && tmp1[tolen - 1] == '.')
++ tolen--;
++
++ if (isc_buffer_length(buffer) < used_org + tolen)
++ return (ISC_R_NOSPACE);
++
++ isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
++ memcpy(isc_buffer_used(buffer), tmp1, tolen);
++ isc_buffer_add(buffer, tolen);
++
++ return (ISC_R_SUCCESS);
++ }
++
++ static idn_result_t
++ append_textname(char *name, const char *origin, size_t namesize) {
++ size_t namelen = strlen(name);
++ size_t originlen = strlen(origin);
++
++ /* Already absolute? */
++ if (namelen > 0 && name[namelen - 1] == '.')
++ return idn_success;
++
++ /* Append dot and origin */
++
++ if (namelen + 1 + originlen >= namesize)
++ return idn_buffer_overflow;
++
++ name[namelen++] = '.';
++ (void)strcpy(name + namelen, origin);
++ return idn_success;
++ }
++
++ static void
++ idn_check_result(idn_result_t r, const char *msg) {
++ if (r != idn_success) {
++ exitcode = 1;
++ fatal("%s: %s", msg, idn_result_tostring(r));
++ }
++ }
++
++ #endif /* WITH_IDN */
+Index: bin/dig/host.1
+diff -c mdn/othersrc/bind9/bin/dig/host.1:1.1.1.2 mdn/othersrc/bind9/bin/dig/host.1:1.4
+*** bin/dig/host.1 Wed Mar 5 17:14:57 2003
+--- bin/dig/host.1 Wed Mar 5 17:42:53 2003
+***************
+*** 120,125 ****
+--- 120,136 ----
+ effectively wait forever for a reply. The time to wait for a response
+ will be set to the number of seconds given by the hardware's maximum
+ value for an integer quantity.
++ .SH "IDN SUPPORT"
++ .PP
++ If \fBhost\fR has been built with IDN (internationalized
++ domain name) support, it can accept and display non-ASCII domain names.
++ \fBhost\fR appropriately converts character encoding of
++ domain name before sending a request to DNS server or displaying a
++ reply from the server.
++ If you'd like to turn off the IDN support for some reason, defines
++ the \fBIDN_DISABLE\fR environment variable.
++ The IDN support is disabled if the the variable is set when
++ \fBhost\fR runs.
+ .SH "FILES"
+ .PP
+ \fI/etc/resolv.conf\fR
+Index: bin/dig/host.docbook
+diff -c mdn/othersrc/bind9/bin/dig/host.docbook:1.1.1.2 mdn/othersrc/bind9/bin/dig/host.docbook:1.4
+*** bin/dig/host.docbook Wed Mar 5 17:14:57 2003
+--- bin/dig/host.docbook Wed Mar 5 17:42:53 2003
+***************
+*** 181,186 ****
+--- 181,201 ----
+ </refsect1>
+
+ <refsect1>
++ <title>IDN SUPPORT</title>
++ <para>
++ If <command>host</command> has been built with IDN (internationalized
++ domain name) support, it can accept and display non-ASCII domain names.
++ <command>host</command> appropriately converts character encoding of
++ domain name before sending a request to DNS server or displaying a
++ reply from the server.
++ If you'd like to turn off the IDN support for some reason, defines
++ the <envar>IDN_DISABLE</envar> environment variable.
++ The IDN support is disabled if the the variable is set when
++ <command>host</command> runs.
++ </para>
++ </refsect1>
++
++ <refsect1>
+ <title>FILES</title>
+ <para>
+ <filename>/etc/resolv.conf</filename>
+Index: lib/dns/name.c
+diff -c mdn/othersrc/bind9/lib/dns/name.c:1.1.1.11 mdn/othersrc/bind9/lib/dns/name.c:1.15
+*** lib/dns/name.c Wed Mar 5 17:16:22 2003
+--- lib/dns/name.c Wed Mar 5 17:49:58 2003
+***************
+*** 194,199 ****
+--- 194,206 ----
+ /* XXXDCL make const? */
+ dns_name_t *dns_wildcardname = &wild;
+
++ #ifdef WITH_IDN
++ /*
++ * dns_name_t to text post-conversion procedure.
++ */
++ static dns_name_totextfilter_t totext_filter_proc = NULL;
++ #endif
++
+ static void
+ set_offsets(const dns_name_t *name, unsigned char *offsets,
+ dns_name_t *set_name);
+***************
+*** 1684,1689 ****
+--- 1691,1699 ----
+ unsigned int labels;
+ isc_boolean_t saw_root = ISC_FALSE;
+ char num[4];
++ #ifdef WITH_IDN
++ unsigned int oused = target->used;
++ #endif
+
+ /*
+ * This function assumes the name is in proper uncompressed
+***************
+*** 1861,1866 ****
+--- 1871,1880 ----
+
+ isc_buffer_add(target, tlen - trem);
+
++ #ifdef WITH_IDN
++ if (totext_filter_proc != NULL)
++ return ((*totext_filter_proc)(target, oused, saw_root));
++ #endif
+ return (ISC_R_SUCCESS);
+ }
+
+***************
+*** 3325,3327 ****
+--- 3339,3347 ----
+ return (ISC_R_SUCCESS);
+ }
+
++ #ifdef WITH_IDN
++ void
++ dns_name_settotextfilter(dns_name_totextfilter_t proc) {
++ totext_filter_proc = proc;
++ }
++ #endif
+Index: lib/dns/include/dns/name.h
+diff -c mdn/othersrc/bind9/lib/dns/include/dns/name.h:1.1.1.7 mdn/othersrc/bind9/lib/dns/include/dns/name.h:1.10
+*** lib/dns/include/dns/name.h Wed May 22 17:15:29 2002
+--- lib/dns/include/dns/name.h Mon May 27 12:10:15 2002
+***************
+*** 219,224 ****
+--- 219,235 ----
+ */
+ #define DNS_NAME_MAXWIRE 255
+
++ #ifdef WITH_IDN
++ /*
++ * Text output filter procedure.
++ * 'target' is the buffer to be converted. The region to be converted
++ * is from 'buffer'->base + 'used_org' to the end of the used region.
++ */
++ typedef isc_result_t (*dns_name_totextfilter_t)(isc_buffer_t *target,
++ unsigned int used_org,
++ isc_boolean_t absolute);
++ #endif
++
+ /***
+ *** Initialization
+ ***/
+***************
+*** 1244,1249 ****
+--- 1255,1268 ----
+ * 'size' > 0.
+ *
+ */
++
++ #ifdef WITH_IDN
++ void
++ dns_name_settotextfilter(dns_name_totextfilter_t proc);
++ /*
++ * Call 'proc' at the end of dns_name_totext.
++ */
++ #endif /* WITH_IDN */
+
+ #define DNS_NAME_FORMATSIZE (DNS_NAME_MAXTEXT + 1)
+ /*
diff --git a/contrib/idn/idnkit-1.0-src/tools/Makefile.in b/contrib/idn/idnkit-1.0-src/tools/Makefile.in
new file mode 100644
index 0000000..108bf24
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/Makefile.in
@@ -0,0 +1,65 @@
+# $Id: Makefile.in,v 1.1.1.1 2003/06/04 00:27:05 marka Exp $
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+SUBDIRS = idnconv runidn
+
+SHELL = @SHELL@
+
+all: all-subdirs
+install: install-subdirs
+clean: clean-subdirs
+distclean: distclean-localdir distclean-subdirs
+test check: test-subdirs
+
+all-subdirs install-subdirs clean-subdirs distclean-subdirs test-subdirs:
+ @target=`echo $@ | sed 's/-subdirs$$//'`; \
+ for d in $(SUBDIRS); do \
+ (cd $$d; $(MAKE) DESTDIR=$(DESTDIR) $$target); \
+ done
+
+distclean-localdir:
+ rm -f Makefile
diff --git a/contrib/idn/idnkit-1.0-src/tools/idnconv/Makefile.in b/contrib/idn/idnkit-1.0-src/tools/idnconv/Makefile.in
new file mode 100644
index 0000000..671c2c0
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/idnconv/Makefile.in
@@ -0,0 +1,116 @@
+# $Id: Makefile.in,v 1.1.1.1 2003/06/04 00:27:05 marka Exp $
+# Copyright (c) 2000, 2002 Japan Network Information Center.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+top_builddir = ../..
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+mandir = @mandir@
+man1dir = $(mandir)/man1
+
+CC = @CC@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+SHELL = @SHELL@
+LIBTOOL = @LIBTOOL@
+
+ICONVINC = @ICONVINC@
+ICONVLIB = @ICONVLIB@
+IDNLIB = ../../lib/libidnkit.la
+
+INCS = -I$(srcdir) -I$(srcdir)/../../include -I../../include $(ICONVINC)
+DEFS =
+
+CFLAGS = $(INCS) $(DEFS) @CPPFLAGS@ @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+SRCS = idnconv.c util.c selectiveencode.c
+OBJS = idnconv.o util.o selectiveencode.o
+
+@LITEONLY_TRUE@all:
+@LITEONLY_FALSE@all: idnconv idnslookup idnconv.1
+
+idnconv: $(OBJS) $(IDNLIB)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ \
+ $(OBJS) $(IDNLIB) $(ICONVLIB)
+
+idnslookup: $(srcdir)/idnslookup.in
+ sed -e 's%[@]bindir[@]%$(bindir)%' $(srcdir)/idnslookup.in > idnslookup
+ chmod 0755 idnslookup
+
+@LITEONLY_TRUE@install:
+@LITEONLY_FALSE@@COMPAT_TRUE@install: all install-nolite install-compat
+@LITEONLY_FALSE@@COMPAT_FALSE@install: all install-nolite
+
+install-nolite:
+ $(MKINSTALLDIRS) $(DESTDIR)$(bindir)
+ $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) idnconv \
+ $(DESTDIR)$(bindir)/idnconv
+ $(MKINSTALLDIRS) $(DESTDIR)$(man1dir)
+ $(INSTALL_DATA) $(srcdir)/idnconv.1 $(DESTDIR)$(man1dir)/idnconv.1
+
+install-compat:
+ src=$(DESTDIR)$(bindir)/idnconv; \
+ dst=$(DESTDIR)$(bindir)/mdnconv; \
+ rm -f $$dst; \
+ ln $$src $$dst || cp $$src $$dst
+ src=$(DESTDIR)$(man1dir)/idnconv.1; \
+ dst=$(DESTDIR)$(man1dir)/mdnconv.1; \
+ rm -f $$dst; \
+ ln $$src $$dst || cp $$src $$dst
+
+clean:
+ rm -f *.o idnconv idnslookup *.core core *~
+ rm -fr .libs/
+
+distclean: clean
+ rm -f Makefile
+
+test check:
diff --git a/contrib/idn/idnkit-1.0-src/tools/idnconv/idnconv.1 b/contrib/idn/idnkit-1.0-src/tools/idnconv/idnconv.1
new file mode 100644
index 0000000..5e7551e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/idnconv/idnconv.1
@@ -0,0 +1,373 @@
+.\" $Id: idnconv.1,v 1.1.1.1 2003/06/04 00:27:10 marka Exp $
+.\"
+.\" Copyright (c) 2000,2001,2002 Japan Network Information Center.
+.\" All rights reserved.
+.\"
+.\" By using this file, you agree to the terms and conditions set forth bellow.
+.\"
+.\" LICENSE TERMS AND CONDITIONS
+.\"
+.\" The following License Terms and Conditions apply, unless a different
+.\" license is obtained from Japan Network Information Center ("JPNIC"),
+.\" a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+.\" Chiyoda-ku, Tokyo 101-0047, Japan.
+.\"
+.\" 1. Use, Modification and Redistribution (including distribution of any
+.\" modified or derived work) in source and/or binary forms is permitted
+.\" under this License Terms and Conditions.
+.\"
+.\" 2. Redistribution of source code must retain the copyright notices as they
+.\" appear in each source code file, this License Terms and Conditions.
+.\"
+.\" 3. Redistribution in binary form must reproduce the Copyright Notice,
+.\" this License Terms and Conditions, in the documentation and/or other
+.\" materials provided with the distribution. For the purposes of binary
+.\" distribution the "Copyright Notice" refers to the following language:
+.\" "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+.\"
+.\" 4. The name of JPNIC may not be used to endorse or promote products
+.\" derived from this Software without specific prior written approval of
+.\" JPNIC.
+.\"
+.\" 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+.\" PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+.\"
+.TH IDNCONV 1 "Mar 3, 2001"
+.\"
+.SH NAME
+idnconv \- codeset converter for named.conf and zone master files
+.\"
+.SH SYNOPSIS
+\fBidnconv\fP [\fIoptions..\fP] [\fIfile\fP...]
+.\"
+.SH DESCRIPTION
+\fBidnconv\fR is a codeset converter for named configuration files
+and zone master files.
+\fBidnconv\fR performs codeset conversion specified either
+by the command-line arguments or by the configuration file,
+and writes the converted text to stdout.
+.PP
+If file name is specified, \fBidnconv\fR converts the contents of
+the file.
+Otherwise, \fBidnconv\fR converts \fIstdin\fR.
+.PP
+Since \fBidnconv\fR is specifically designed for converting
+internatinalized domain names, it may not be suitable as a general
+codeset converter.
+.\"
+.SH "OPERATION MODES"
+\fBidnconv\fR has two operation modes.
+.PP
+One is a mode to convert local-encoded domain names to IDN-encoded
+one. Usually this mode is used for preparing domain names to be
+listed in named configuration files or zone master files.
+In this mode, the following processes are performed in addition to
+the codeset (encoding) conversion.
+.RS 2
+.IP \- 2
+local mapping
+.IP \- 2
+standard domain name preperation (NAMEPREP)
+.RE
+.PP
+The other mode is a reverse conversion, from IDN-encoded domain name to
+local-encoded domain names.
+In this mode, local mapping and NAMEPREP are not performed since
+IDN-encoded names should already be normalized.
+Instead, a check is done in order to make sure the IDN-encoded domain name
+is properly NAMEPREP'ed. If it is not, the name will be output in
+IDN encoding, not in the local encoding.
+.\"
+.SH OPTIONS
+Normally \fBidnconv\fR reads system's default configuration file
+(idn.conf) and performs conversion or name preparation according to
+the parameters specified in the file.
+You can override the setting in the configuration file by various
+command line options below.
+.TP 4
+\fB\-in\fP \fIin-code\fP, \fB\-i\fP \fIin-code\fP
+Specify the codeset name of the input text.
+Any of the following codeset names can be specified.
+.RS 4
+.IP "\(bu" 2
+Any codeset names which \fIiconv_open()\fP library function accepts
+.IP "\(bu" 2
+\f(CWPunycode\fR
+.IP "\(bu" 2
+\f(CWUTF-8\fR
+.IP "\(bu" 2
+Any alias names for the above, defined by the codeset alias file.
+.RE
+.IP "" 4
+If this option is not specified, the default codeset is determined
+from the locale in normal conversion mode.
+In reverse conversion mode, the default codeset is the IDN encoding
+specified by the configuration file (``idn-encoding'' entry).
+.TP 4
+\fB\-out\fP \fIout-code\fP, \fB\-o\fP \fIout-code\fP
+Specify the codeset name of the output text. \fIout-code\fP can be any
+codeset name that can be specified for \fB\-in\fR option.
+.IP "" 4
+If this option is not specified, the default is the IDN encoding
+specified by the configuration file (``idn-encoding'' entry) in
+normal conversion mode.
+In reverse conversion mode, the default codeset is determined from
+the locale.
+.TP 4
+\fB\-conf\fP \fIpath\fP, \fB\-c\fP \fIpath\fP
+Specify the pathname of idnkit configuration file (``idn.conf'').
+If not specified, system's default file is used, unless \-noconf
+option is specified.
+.TP 4
+\fB\-noconf\fP, \fB\-C\fP
+Specify that no configuration file is to be used.
+.TP 4
+\fB\-reverse\fP, \fB\-r\fP
+Specify reverse conversion mode.
+.br
+If this option is not specified, the normal conversion mode is used.
+.TP 4
+\fB\-nameprep\fR \fIversion\fR, \fB\-n\fR \fIversion\fR
+Specify the version of NAMEPREP.
+The following is a list of currently available versions.
+.RS 4
+.IP \f(CWRFC3491\fR 4
+Perform NAMEPREP according to the RFC3491
+``rfc-3491.txt''.
+.RE
+.TP 4
+\fB\-nonameprep\fR, \fB\-N\fR
+Specify to skip NAMEPREP process (or NAMEPREP verification process
+in the reverse conversion mode).
+This option implies -nounassigncheck and -nobidicheck.
+.TP 4
+\fB\-localmap\fR \fImap\fR
+Specify the name of local mapping rule.
+Currently, following maps are available.
+.RS 4
+.IP \f(CWRFC3491\fR 4
+Use the list of mappings specified by RFC3491.
+.IP \f(CWfilemap:\fR\fIpath\fR 4
+Use list of mappings specified by mapfile \fIpath\fR.
+See idn.conf(5) for the format of a mapfile.
+.RE
+.IP "" 4
+This option can be specified more than once.
+In that case, each mapping will be performed in the order of the
+specification.
+.TP 4
+\fB\-nounassigncheck\fR, \fB\-U\fR
+Skip unassigned codepoint check.
+.TP 4
+\fB\-nobidicheck\fR, \fB\-B\fR
+Skip bidi character check.
+.TP 4
+\fB\-nolengthcheck\fR
+Do not check label length of normal conversion result.
+This option is only meaningful in the normal conversion mode.
+.TP 4
+\fB\-noasciicheck\fR, \fB\-A\fR
+Do not check ASCII range characters.
+This option is only meaningful in the normal conversion mode.
+.TP 4
+\fB\-noroundtripcheck\fR
+Do not perform round trip check.
+This option is only meaningful in the reverse conversion mode.
+.TP 4
+\fB\-delimiter\fR \fIcodepoint\fP
+Specify the character to be mapped to domain name delimiter (period).
+This option can be specified more than once in order to specify multiple
+characters.
+.br
+This option is only meaningful in the normal conversion mode.
+.TP 4
+\fB\-whole\fP, \fB\-w\fP
+Perform local mapping, nameprep and conversion to output codeset for the entire
+input text. If this option is not specified, only non-ASCII characters
+and their surrounding texts will be processed.
+See ``NORAML CONVERSION MECHANISM'' and ``REVERSE CONVERSION MECHANISM''
+for details.
+.TP 4
+\fB\-alias\fP \fIpath\fP, \fB\-a\fP \fIpath\fP
+Specify a codeset alias file. It is a simple text file, where
+each line has a pair of alias name and real name separated by one
+or more white spaces like below:
+.nf
+.ft CW
+
+ \fIalias-codeset-name\fP \fIreal-codeset-name\fP
+
+.ft R
+.fi
+Lines starting with ``#'' are treated as comments.
+.TP 4
+\fB\-flush\fP
+Force line-buffering mode.
+.TP 4
+\fB\-version\fP, \fB\-v\fP
+Print version information and quit.
+.\"
+.SH LOCAL CODESET
+idnconv guesses local codeset from locale and environment variables.
+See the ``LOCAL CODESET'' section in idn.conf(5) for more details.
+.\"
+.SH NORMAL CONVERSION MECHANISM
+\fBidnconv\fR performs conversion line by line.
+Here describes how \fBidnconv\fR does its job for each line.
+.\"
+.IP "1. read a line from input text" 4
+.IP "2. convert the line to UTF-8" 4
+\fBidnconv\fR converts the line from local encoding to UTF-8.
+.IP "3. find internationalized domain names" 4
+If the \-whole\ (or \-w) option is specified, the entire line is
+assumed as an internationalized domain name.
+Otherwise, \fBidnconv\fR recognizes any character sequences having
+the following properties in the line as internationalized domain names.
+.RS 4
+.IP "\(bu" 2
+containing at least one non-ASCII character, and
+.IP "\(bu" 2
+consisting of legal domain name characters (alphabets, digits, hypens),
+non-ASCII characters and period.
+.RE
+.IP "4. convert internationalized domain names to ACE" 4
+For each internationalized domain name found in the line,
+\fBidnconv\fR converts the name to ACE.
+The details about the conversion procedure is:
+.RS 4
+.IP "4.1. delimiter mapping" 4
+Substibute certain characters specified as domain name delimiter
+with period.
+.IP "4.2. local mapping" 4
+Perform local mapping.
+If the local mapping is specified by command line option \-localmap,
+the specified mapping rule is applied. Otherwise, find the mapping rule
+from the configuration file which matches to the TLD of the name,
+and perform mapping according to the matched rule.
+.br
+This step is skipped if the \-nolocalmap (or \-L) option is specified.
+.IP "4.3. NAMEPREP" 4
+Perform name preparation (NAMEPREP).
+Mapping, normalization, prohibited character checking, unassigned
+codepoint checking, bidirectional character checking are done in
+that order.
+If the prohibited character check, unassigned codepoint check, or
+bidi character check fails, the normal conversion procedure aborts.
+.br
+This step is skipped if the \-nonameprep (or \-N) option is specified.
+.IP "4.4. ASCII character checking" 4
+Checks ASCII range character in the domain name.
+the normal conversion procedure aborts, if the domain name has a label
+beginning or end with hyphen (U+002D) or it contains ASCII range character
+except for alphanumeric and hyphen,
+.br
+This step is skipped if the \-noasciicheck (or \-A) option is specified.
+.IP "4.5. ACE conversion" 4
+Convert the string to ACE.
+.IP "4.6. label length checking" 4
+The normal conversion procedure aborts, if the domain name has an empty
+label or too long label (64 characters or more).
+.br
+This step is skipped if the \-nolengthcheck option is specified.
+.RE
+.IP "5. output the result" 4
+.PP
+.\"
+.SH REVERSE CONVERSION MECHANISM
+This is like the normal conversion mechanism, but they are not symmetric.
+\fBidnconv\fR does its job for each line.
+.\"
+.IP "1. read a line from input text" 4
+.IP "2. convert the line to UTF-8" 4
+\fBidnconv\fR converts the line from local encoding to UTF-8.
+.IP "3. find internationalized domain names" 4
+If the \-whole\ (or \-w) option is specified, the entire line is
+assumed as an internationalized domain name.
+Otherwise, \fBidnconv\fR decodes any valid ASCII domain names
+including ACE names in the line.
+.IP "4. convert domain names to local encoding"
+Then, \fBidnconv\fR decodes the domain names.
+The decode procedure consists of the following steps.
+.RS 4
+.IP "4.1. Delimiter mapping" 4
+Substibute certain characters specified as domain name delimiter
+with period.
+.br
+.IP "4.2. NAMEPREP" 4
+Perform name preparation (NAMEPREP) for each label in the domain name.
+Mapping, normalization, prohibited character checking, unassigned
+codepoint checking, bidirectional character checking are done in
+that order.
+If the prohibited character check, unassigned codepoint check, or
+bidi character check fails, disqualified labels are restored to
+original input strings and further conversion on those labels are
+not performed.
+.br
+This step is skipped if the \-nonameprep (or \-N) option is specified.
+.IP "4.3. ACE conversion" 4
+Convert the string from ACE to UTF-8.
+.IP "4.4. Round trip checkning" 4
+For each label, perform the normal conversion and compare it with
+the result of the step 4.2.
+This check succeeds, if they are equivalent strings.
+In case of failure, disqualified labels are restored to original
+input strings and further conversion on those labels are not
+performed.
+.br
+This step is skipped if the \-noroundtripcheck option is specified.
+.IP "4.5. local encoding conversion" 4
+Convert the result of the step 4.3. from UTF-8 to local encoding.
+If a label in the domain name contains a character which cannot be
+represented in the local encoding, the label is restored to the
+original input string.
+.RE
+.IP "5. output the result" 4
+.PP
+.\"
+.SH FILE MANAGEMENT
+Maybe the best way to manage named.conf or zone master files that contains
+internationalized domain name is to keep them in your local codeset so that
+they can be edited with your favorite editor, and generate a version in
+the IDN encoding using \fBidnconv\fP.
+.PP
+`make' is a convenient tool for this purpose.
+Suppose the local codeset version has suffix `.lc', and its ACE version
+has suffix `.ace'. The following Makefile enables you to generate
+ACE version from local codeset version by just typing `make'.
+.RS 4
+.nf
+.ft CW
+
+\&.SUFFIXES: .lc .ace
+\&.lc.ace:
+ idnconv -in $(LOCALCODE) -out $(IDNCODE) \\
+ $(IDNCONVOPT) $< > $@
+
+LOCALCODE = EUC-JP
+IDNCODE = Punycode
+IDNCONVOPT =
+
+DESTFILES = db.zone1.ace db.zone2.ace
+
+all: $(DESTFILES)
+.ft
+.fi
+.RE
+.\"
+.SH SEE ALSO
+idn.conf(5),
+iconv(3)
+.\"
+.SH BUGS
+The automatic input-code selection depends on your system, and sometimes
+it cannot guess or guess wrong. It is better to explicitly specify it
+using \-in option.
diff --git a/contrib/idn/idnkit-1.0-src/tools/idnconv/idnconv.c b/contrib/idn/idnkit-1.0-src/tools/idnconv/idnconv.c
new file mode 100644
index 0000000..a10a738
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/idnconv/idnconv.c
@@ -0,0 +1,803 @@
+#ifndef lint
+static char *rcsid = "$Id: idnconv.c,v 1.1.1.1 2003/06/04 00:27:07 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * idnconv -- Codeset converter for named.conf and zone files
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#include <idn/result.h>
+#include <idn/converter.h>
+#include <idn/normalizer.h>
+#include <idn/utf8.h>
+#include <idn/resconf.h>
+#include <idn/res.h>
+#include <idn/util.h>
+#include <idn/version.h>
+
+#include "util.h"
+
+#define MAX_DELIMITER 10
+#define MAX_LOCALMAPPER 10
+#define MAX_MAPPER 10
+#define MAX_NORMALIZER 10
+#define MAX_CHEKER 10
+
+#define FLAG_REVERSE 0x0001
+#define FLAG_DELIMMAP 0x0002
+#define FLAG_LOCALMAP 0x0004
+#define FLAG_MAP 0x0008
+#define FLAG_NORMALIZE 0x0010
+#define FLAG_PROHIBITCHECK 0x0020
+#define FLAG_UNASSIGNCHECK 0x0040
+#define FLAG_BIDICHECK 0x0080
+#define FLAG_ASCIICHECK 0x0100
+#define FLAG_LENGTHCHECK 0x0200
+#define FLAG_ROUNDTRIPCHECK 0x0400
+#define FLAG_SELECTIVE 0x0800
+
+#define FLAG_NAMEPREP \
+ (FLAG_MAP|FLAG_NORMALIZE|FLAG_PROHIBITCHECK|FLAG_UNASSIGNCHECK|\
+ FLAG_BIDICHECK)
+
+#define DEFAULT_FLAGS \
+ (FLAG_LOCALMAP|FLAG_NAMEPREP|FLAG_ASCIICHECK|FLAG_LENGTHCHECK|\
+ FLAG_ROUNDTRIPCHECK|FLAG_SELECTIVE|FLAG_DELIMMAP)
+
+int line_number; /* current input file line number */
+static int flush_every_line = 0; /* pretty obvious */
+
+static int encode_file(idn_resconf_t conf1, idn_resconf_t conf2,
+ FILE *fp, int flags);
+static int decode_file(idn_resconf_t conf1, idn_resconf_t conf2,
+ FILE *fp, int flags);
+static int trim_newline(idnconv_strbuf_t *buf);
+static idn_result_t convert_line(idnconv_strbuf_t *from,
+ idnconv_strbuf_t *to,
+ idn_resconf_t conf,
+ idn_action_t actions, int flags);
+static void print_usage(char *cmd);
+static void print_version(void);
+static unsigned long get_ucs(const char *p);
+
+int
+main(int ac, char **av) {
+ char *cmd = *av;
+ char *cname;
+ unsigned long delimiters[MAX_DELIMITER];
+ char *localmappers[MAX_LOCALMAPPER];
+ char *nameprep_version = NULL;
+ int ndelimiters = 0;
+ int nlocalmappers = 0;
+ char *in_code = NULL;
+ char *out_code = NULL;
+ char *resconf_file = NULL;
+ int no_resconf = 0;
+ char *encoding_alias = NULL;
+ int flags = DEFAULT_FLAGS;
+ FILE *fp;
+ idn_result_t r;
+ idn_resconf_t resconf1, resconf2;
+ idn_converter_t conv;
+ int exit_value;
+
+#ifdef HAVE_SETLOCALE
+ (void)setlocale(LC_ALL, "");
+#endif
+
+ /*
+ * If the command name begins with 'r', reverse mode is assumed.
+ */
+ if ((cname = strrchr(cmd, '/')) != NULL)
+ cname++;
+ else
+ cname = cmd;
+ if (cname[0] == 'r')
+ flags |= FLAG_REVERSE;
+
+ ac--;
+ av++;
+ while (ac > 0 && **av == '-') {
+
+#define OPT_MATCH(opt) (strcmp(*av, opt) == 0)
+#define MUST_HAVE_ARG if (ac < 2) print_usage(cmd)
+#define APPEND_LIST(array, size, item, what) \
+ if (size >= (sizeof(array) / sizeof(array[0]))) { \
+ errormsg("too many " what "\n"); \
+ exit(1); \
+ } \
+ array[size++] = item; \
+ ac--; av++
+
+ if (OPT_MATCH("-in") || OPT_MATCH("-i")) {
+ MUST_HAVE_ARG;
+ in_code = av[1];
+ ac--;
+ av++;
+ } else if (OPT_MATCH("-out") || OPT_MATCH("-o")) {
+ MUST_HAVE_ARG;
+ out_code = av[1];
+ ac--;
+ av++;
+ } else if (OPT_MATCH("-conf") || OPT_MATCH("-c")) {
+ MUST_HAVE_ARG;
+ resconf_file = av[1];
+ ac--;
+ av++;
+ } else if (OPT_MATCH("-nameprep") || OPT_MATCH("-n")) {
+ MUST_HAVE_ARG;
+ nameprep_version = av[1];
+ ac--;
+ av++;
+ } else if (OPT_MATCH("-noconf") || OPT_MATCH("-C")) {
+ no_resconf = 1;
+ } else if (OPT_MATCH("-reverse") || OPT_MATCH("-r")) {
+ flags |= FLAG_REVERSE;
+ } else if (OPT_MATCH("-nolocalmap") || OPT_MATCH("-L")) {
+ flags &= ~FLAG_LOCALMAP;
+ } else if (OPT_MATCH("-nonameprep") || OPT_MATCH("-N")) {
+ flags &= ~FLAG_NAMEPREP;
+ } else if (OPT_MATCH("-unassigncheck") || OPT_MATCH("-u")) {
+ flags |= FLAG_UNASSIGNCHECK;
+ } else if (OPT_MATCH("-nounassigncheck") || OPT_MATCH("-U")) {
+ flags &= ~FLAG_UNASSIGNCHECK;
+ } else if (OPT_MATCH("-nobidicheck") || OPT_MATCH("-B")) {
+ flags &= ~FLAG_BIDICHECK;
+ } else if (OPT_MATCH("-noasciicheck") || OPT_MATCH("-A")) {
+ flags &= ~FLAG_ASCIICHECK;
+ } else if (OPT_MATCH("-nolengthcheck")) {
+ flags &= ~FLAG_LENGTHCHECK;
+ } else if (OPT_MATCH("-noroundtripcheck")) {
+ flags &= ~FLAG_ROUNDTRIPCHECK;
+ } else if (OPT_MATCH("-whole") || OPT_MATCH("-w")) {
+ flags &= ~FLAG_SELECTIVE;
+ } else if (OPT_MATCH("-localmap")) {
+ MUST_HAVE_ARG;
+ APPEND_LIST(localmappers, nlocalmappers, av[1],
+ "local maps");
+ } else if (OPT_MATCH("-delimiter")) {
+ unsigned long v;
+ MUST_HAVE_ARG;
+ v = get_ucs(av[1]);
+ APPEND_LIST(delimiters, ndelimiters, v,
+ "delimiter maps");
+ } else if (OPT_MATCH("-alias") || OPT_MATCH("-a")) {
+ MUST_HAVE_ARG;
+ encoding_alias = av[1];
+ ac--;
+ av++;
+ } else if (OPT_MATCH("-flush")) {
+ flush_every_line = 1;
+ } else if (OPT_MATCH("-version") || OPT_MATCH("-v")) {
+ print_version();
+ } else {
+ print_usage(cmd);
+ }
+#undef OPT_MATCH
+#undef MUST_HAVE_ARG
+#undef APPEND_LIST
+
+ ac--;
+ av++;
+ }
+
+ if (ac > 1)
+ print_usage(cmd);
+
+ /* Initialize. */
+ if ((r = idn_resconf_initialize()) != idn_success) {
+ errormsg("error initializing library\n");
+ return (1);
+ }
+
+ /*
+ * Create resource contexts.
+ * `resconf1' and `resconf2' are almost the same but local and
+ * IDN encodings are reversed.
+ */
+ resconf1 = NULL;
+ resconf2 = NULL;
+ if (idn_resconf_create(&resconf1) != idn_success ||
+ idn_resconf_create(&resconf2) != idn_success) {
+ errormsg("error initializing configuration contexts\n");
+ return (1);
+ }
+
+ /* Load configuration file. */
+ if (no_resconf) {
+ set_defaults(resconf1);
+ set_defaults(resconf2);
+ } else {
+ load_conf_file(resconf1, resconf_file);
+ load_conf_file(resconf2, resconf_file);
+ }
+
+ /* Set encoding alias file. */
+ if (encoding_alias != NULL)
+ set_encoding_alias(encoding_alias);
+
+ /* Set input codeset. */
+ if (flags & FLAG_REVERSE) {
+ if (in_code == NULL) {
+ conv = idn_resconf_getidnconverter(resconf1);
+ if (conv == NULL) {
+ errormsg("cannot get the IDN encoding.\n"
+ "please specify an appropriate one "
+ "with `-in' option.\n");
+ exit(1);
+ }
+ idn_resconf_setlocalconverter(resconf2, conv);
+ idn_converter_destroy(conv);
+ } else {
+ set_idncode(resconf1, in_code);
+ set_localcode(resconf2, in_code);
+ }
+ } else {
+ if (in_code == NULL) {
+ conv = idn_resconf_getlocalconverter(resconf1);
+ if (conv == NULL) {
+ errormsg("cannot get the local encoding.\n"
+ "please specify an appropriate one "
+ "with `-in' option.\n");
+ exit(1);
+ }
+ idn_resconf_setidnconverter(resconf2, conv);
+ idn_converter_destroy(conv);
+ } else {
+ set_localcode(resconf1, in_code);
+ set_idncode(resconf2, in_code);
+ }
+ }
+
+ /* Set output codeset. */
+ if (flags & FLAG_REVERSE) {
+ if (out_code == NULL) {
+ conv = idn_resconf_getlocalconverter(resconf1);
+ if (conv == NULL) {
+ errormsg("cannot get the local encoding.\n"
+ "please specify an appropriate one "
+ "with `-out' option.\n");
+ exit(1);
+ }
+ idn_resconf_setidnconverter(resconf2, conv);
+ idn_converter_destroy(conv);
+ } else {
+ set_localcode(resconf1, out_code);
+ set_idncode(resconf2, out_code);
+ }
+ } else {
+ if (out_code == NULL) {
+ conv = idn_resconf_getidnconverter(resconf1);
+ if (conv == NULL) {
+ errormsg("cannot get the IDN encoding.\n"
+ "please specify an appropriate one "
+ "with `-out' option.\n");
+ exit(1);
+ }
+ idn_resconf_setlocalconverter(resconf2, conv);
+ idn_converter_destroy(conv);
+ } else {
+ set_idncode(resconf1, out_code);
+ set_localcode(resconf2, out_code);
+ }
+ }
+
+ /* Set delimiter map(s). */
+ if (ndelimiters > 0) {
+ set_delimitermapper(resconf1, delimiters, ndelimiters);
+ set_delimitermapper(resconf2, delimiters, ndelimiters);
+ }
+
+ /* Set local map(s). */
+ if (nlocalmappers > 0) {
+ set_localmapper(resconf1, localmappers, nlocalmappers);
+ set_localmapper(resconf2, localmappers, nlocalmappers);
+ }
+
+ /* Set NAMEPREP version. */
+ if (nameprep_version != NULL) {
+ set_nameprep(resconf1, nameprep_version);
+ set_nameprep(resconf2, nameprep_version);
+ }
+
+ idn_res_enable(1);
+
+ /* Open input file. */
+ if (ac > 0) {
+ if ((fp = fopen(av[0], "r")) == NULL) {
+ errormsg("cannot open file %s: %s\n",
+ av[0], strerror(errno));
+ return (1);
+ }
+ } else {
+ fp = stdin;
+ }
+
+ /* Do the conversion. */
+ if (flags & FLAG_REVERSE)
+ exit_value = decode_file(resconf1, resconf2, fp, flags);
+ else
+ exit_value = encode_file(resconf1, resconf2, fp, flags);
+
+ idn_resconf_destroy(resconf1);
+ idn_resconf_destroy(resconf2);
+
+ return exit_value;
+}
+
+static int
+encode_file(idn_resconf_t conf1, idn_resconf_t conf2, FILE *fp, int flags) {
+ idn_result_t r;
+ idnconv_strbuf_t buf1, buf2;
+ idn_action_t actions1, actions2;
+ int nl_trimmed;
+ int local_ace_hack;
+ idn_converter_t conv;
+
+ /*
+ * See if the input codeset is an ACE.
+ */
+ conv = idn_resconf_getlocalconverter(conf1);
+ if (conv != NULL && idn_converter_isasciicompatible(conv) &&
+ (flags & FLAG_SELECTIVE))
+ local_ace_hack = 1;
+ else
+ local_ace_hack = 0;
+ if (conv != NULL)
+ idn_converter_destroy(conv);
+
+ if (local_ace_hack) {
+ actions1 = IDN_IDNCONV;
+ if (flags & FLAG_ROUNDTRIPCHECK)
+ actions1 |= IDN_RTCHECK;
+ } else {
+ actions1 = IDN_LOCALCONV;
+ }
+
+ actions2 = IDN_IDNCONV;
+ if (flags & FLAG_DELIMMAP)
+ actions2 |= IDN_DELIMMAP;
+ if (flags & FLAG_LOCALMAP)
+ actions2 |= IDN_LOCALMAP;
+ if (flags & FLAG_MAP)
+ actions2 |= IDN_MAP;
+ if (flags & FLAG_NORMALIZE)
+ actions2 |= IDN_NORMALIZE;
+ if (flags & FLAG_PROHIBITCHECK)
+ actions2 |= IDN_PROHCHECK;
+ if (flags & FLAG_UNASSIGNCHECK)
+ actions2 |= IDN_UNASCHECK;
+ if (flags & FLAG_BIDICHECK)
+ actions2 |= IDN_BIDICHECK;
+ if (flags & FLAG_ASCIICHECK)
+ actions2 |= IDN_ASCCHECK;
+ if (flags & FLAG_LENGTHCHECK)
+ actions2 |= IDN_LENCHECK;
+
+ strbuf_init(&buf1);
+ strbuf_init(&buf2);
+ line_number = 1;
+ while (strbuf_getline(&buf1, fp) != NULL) {
+ /*
+ * Trim newline at the end. This is needed for
+ * those ascii-comatible encodings such as UTF-5 or RACE
+ * not to try converting newlines, which will result
+ * in `invalid encoding' error.
+ */
+ nl_trimmed = trim_newline(&buf1);
+
+ /*
+ * Convert input line to UTF-8.
+ */
+ if (local_ace_hack)
+ r = convert_line(&buf1, &buf2, conf2, actions1,
+ FLAG_REVERSE|FLAG_SELECTIVE);
+ else
+ r = convert_line(&buf1, &buf2, conf1, actions1,
+ 0);
+
+ if (r != idn_success) {
+ errormsg("conversion failed at line %d: %s\n",
+ line_number,
+ idn_result_tostring(r));
+ goto error;
+ }
+ if (!idn_utf8_isvalidstring(strbuf_get(&buf2))) {
+ errormsg("conversion to utf-8 failed at line %d\n",
+ line_number);
+ goto error;
+ }
+
+ /*
+ * Perform local mapping and NAMEPREP, and convert to
+ * the output codeset.
+ */
+ r = convert_line(&buf2, &buf1, conf1, actions2,
+ flags & FLAG_SELECTIVE);
+
+ if (r != idn_success) {
+ errormsg("error in nameprep or output conversion "
+ "at line %d: %s\n",
+ line_number, idn_result_tostring(r));
+ goto error;
+ }
+
+ fputs(strbuf_get(&buf1), stdout);
+ if (nl_trimmed)
+ putc('\n', stdout);
+
+ if (flush_every_line)
+ fflush(stdout);
+
+ line_number++;
+ }
+
+ strbuf_reset(&buf1);
+ strbuf_reset(&buf2);
+ return (0);
+
+ error:
+ strbuf_reset(&buf1);
+ strbuf_reset(&buf2);
+ return (1);
+}
+
+static int
+decode_file(idn_resconf_t conf1, idn_resconf_t conf2, FILE *fp, int flags) {
+ idn_result_t r;
+ idnconv_strbuf_t buf1, buf2;
+ idn_action_t actions1, actions2;
+ int nl_trimmed;
+ int local_ace_hack, idn_ace_hack;
+ idn_converter_t conv;
+
+ /*
+ * See if the input codeset is an ACE.
+ */
+ conv = idn_resconf_getidnconverter(conf1);
+ if (conv != NULL && idn_converter_isasciicompatible(conv) &&
+ (flags & FLAG_SELECTIVE))
+ idn_ace_hack = 1;
+ else
+ idn_ace_hack = 0;
+ if (conv != NULL)
+ idn_converter_destroy(conv);
+
+ conv = idn_resconf_getlocalconverter(conf1);
+ if (conv != NULL && idn_converter_isasciicompatible(conv) &&
+ (flags & FLAG_SELECTIVE))
+ local_ace_hack = 1;
+ else
+ local_ace_hack = 0;
+ if (conv != NULL)
+ idn_converter_destroy(conv);
+
+ actions1 = IDN_IDNCONV;
+
+ if (local_ace_hack) {
+ actions2 = IDN_IDNCONV;
+ if (flags & FLAG_MAP)
+ actions2 |= IDN_MAP;
+ if (flags & FLAG_NORMALIZE)
+ actions2 |= IDN_NORMALIZE;
+ if (flags & FLAG_PROHIBITCHECK)
+ actions2 |= IDN_PROHCHECK;
+ if (flags & FLAG_UNASSIGNCHECK)
+ actions2 |= IDN_UNASCHECK;
+ if (flags & FLAG_BIDICHECK)
+ actions2 |= IDN_BIDICHECK;
+ if (flags & FLAG_ASCIICHECK)
+ actions2 |= IDN_ASCCHECK;
+ if (flags & FLAG_LENGTHCHECK)
+ actions2 |= IDN_LENCHECK;
+ } else {
+ actions2 = IDN_LOCALCONV;
+ }
+
+ if (flags & FLAG_DELIMMAP)
+ actions1 |= IDN_DELIMMAP;
+ if (flags & FLAG_MAP)
+ actions1 |= IDN_MAP;
+ if (flags & FLAG_NORMALIZE)
+ actions1 |= IDN_NORMALIZE;
+ if (flags & FLAG_NORMALIZE)
+ actions1 |= IDN_NORMALIZE;
+ if (flags & FLAG_PROHIBITCHECK)
+ actions1 |= IDN_PROHCHECK;
+ if (flags & FLAG_UNASSIGNCHECK)
+ actions1 |= IDN_UNASCHECK;
+ if (flags & FLAG_BIDICHECK)
+ actions1 |= IDN_BIDICHECK;
+ if (flags & FLAG_ASCIICHECK)
+ actions1 |= IDN_ASCCHECK;
+ if (flags & FLAG_ROUNDTRIPCHECK)
+ actions1 |= IDN_RTCHECK;
+
+ strbuf_init(&buf1);
+ strbuf_init(&buf2);
+ line_number = 1;
+ while (strbuf_getline(&buf1, fp) != NULL) {
+ /*
+ * Trim newline at the end. This is needed for
+ * those ascii-comatible encodings such as UTF-5 or RACE
+ * not to try converting newlines, which will result
+ * in `invalid encoding' error.
+ */
+ nl_trimmed = trim_newline(&buf1);
+
+ /*
+ * Treat input line as the string encoded in local
+ * encoding and convert it to UTF-8 encoded string.
+ */
+ if (local_ace_hack) {
+ if (strbuf_copy(&buf2, strbuf_get(&buf1)) == NULL)
+ r = idn_nomemory;
+ else
+ r = idn_success;
+ } else {
+ r = convert_line(&buf1, &buf2, conf1, IDN_LOCALCONV,
+ 0);
+ }
+ if (r != idn_success) {
+ errormsg("conversion failed at line %d: %s\n",
+ line_number, idn_result_tostring(r));
+ goto error;
+ }
+
+ /*
+ * Convert internationalized domain names in the line.
+ */
+ if (idn_ace_hack) {
+ r = convert_line(&buf2, &buf1, conf1, actions1,
+ FLAG_REVERSE|FLAG_SELECTIVE);
+ } else {
+ r = convert_line(&buf2, &buf1, conf1, actions1,
+ FLAG_REVERSE);
+ }
+ if (r != idn_success) {
+ errormsg("conversion failed at line %d: %s\n",
+ line_number,
+ idn_result_tostring(r));
+ goto error;
+ }
+ if (!idn_utf8_isvalidstring(strbuf_get(&buf1))) {
+ errormsg("conversion to utf-8 failed at line %d\n",
+ line_number);
+ goto error;
+ }
+
+ /*
+ * Perform round trip check and convert to the output
+ * codeset.
+ */
+ if (local_ace_hack) {
+ r = convert_line(&buf1, &buf2, conf2, actions2,
+ FLAG_SELECTIVE);
+ } else {
+ r = convert_line(&buf1, &buf2, conf1, actions2,
+ FLAG_REVERSE);
+ }
+
+ if (r != idn_success) {
+ errormsg("error in nameprep or output conversion "
+ "at line %d: %s\n",
+ line_number, idn_result_tostring(r));
+ goto error;
+ }
+
+ fputs(strbuf_get(&buf2), stdout);
+ if (nl_trimmed)
+ putc('\n', stdout);
+
+ if (flush_every_line)
+ fflush(stdout);
+
+ line_number++;
+ }
+ strbuf_reset(&buf1);
+ strbuf_reset(&buf2);
+ return (0);
+
+ error:
+ strbuf_reset(&buf1);
+ strbuf_reset(&buf2);
+ return (1);
+}
+
+static int
+trim_newline(idnconv_strbuf_t *buf) {
+ /*
+ * If the string in BUF ends with a newline, trim it and
+ * return 1. Otherwise, just return 0 without modifying BUF.
+ */
+ char *s = strbuf_get(buf);
+ size_t len = strlen(s);
+
+ if (s[len - 1] == '\n') {
+ s[len - 1] = '\0';
+ return (1);
+ }
+
+ return (0);
+}
+
+static idn_result_t
+convert_line(idnconv_strbuf_t *from, idnconv_strbuf_t *to,
+ idn_resconf_t conf, idn_action_t actions, int flags)
+{
+ idn_result_t r = idn_success;
+ char *from_str = strbuf_get(from);
+
+ for (;;) {
+ char *to_str = strbuf_get(to);
+ size_t to_size = strbuf_size(to);
+
+ switch (flags & (FLAG_REVERSE|FLAG_SELECTIVE)) {
+ case 0:
+ r = idn_res_encodename(conf, actions, from_str,
+ to_str, to_size);
+ break;
+ case FLAG_REVERSE:
+ r = idn_res_decodename(conf, actions, from_str,
+ to_str, to_size);
+ break;
+ case FLAG_SELECTIVE:
+ r = selective_encode(conf, actions, from_str,
+ to_str, to_size);
+ break;
+ case FLAG_REVERSE|FLAG_SELECTIVE:
+ r = selective_decode(conf, actions, from_str,
+ to_str, to_size);
+ break;
+ }
+ if (r == idn_buffer_overflow) {
+ /*
+ * Conversion is not successful because
+ * the size of the target buffer is not enough.
+ * Double the size and retry.
+ */
+ if (strbuf_double(to) == NULL) {
+ /* oops. allocation failed. */
+ return (idn_nomemory);
+ }
+ } else {
+ break;
+ }
+ }
+ return (r);
+}
+
+static char *options[] = {
+ "-in INPUT-CODESET : specifies input codeset name.",
+ "-i INPUT-CODESET : synonym for -in",
+ "-out OUTPUT-CODESET : specifies output codeset name.",
+ "-o OUTPUT-CODESET : synonym for -out",
+ "-conf CONF-FILE : specifies idnkit configuration file.",
+ "-c CONF-FILE : synonym for -conf",
+ "-noconf : do not load idnkit configuration file.",
+ "-C : synonym for -noconf",
+ "-reverse : specifies reverse conversion.",
+ " (i.e. IDN encoding to local encoding)",
+ "-r : synonym for -reverse",
+ "-nameprep VERSION : specifies version name of NAMEPREP.",
+ "-n VERSION : synonym for -nameprep",
+ "-nonameprep : do not perform NAMEPREP.",
+ "-N : synonym for -nonameprep",
+ "-localmap MAPPING : specifies local mapping.",
+ "-nolocalmap : do not perform local mapping.",
+ "-L : synonym for -nolocalmap",
+ "-nounassigncheck : do not perform unassigned codepoint check.",
+ "-U : synonym for -nounassigncheck",
+ "-nobidicheck : do not perform bidirectional text check.",
+ "-B : synonym for -nobidicheck",
+ "-nolengthcheck : do not check label length.",
+ "-noasciicheck : do not check ASCII range characters.",
+ "-A : synonym for -noasciicheck",
+ "-noroundtripcheck : do not perform round trip check.",
+ "-delimiter U+XXXX : specifies local delimiter code point.",
+ "-alias alias-file : specifies codeset alias file.",
+ "-a : synonym for -alias",
+ "-flush : line-buffering mode.",
+ "-whole : convert the whole region instead of",
+ " regions containing non-ascii characters.",
+ "-w : synonym for -whole",
+ "-version : print version number, then exit.",
+ "-v : synonym for -version",
+ "",
+ " The following options can be specified multiple times",
+ " -localmap, -delimiter",
+ NULL,
+};
+
+static void
+print_version() {
+ fprintf(stderr, "idnconv (idnkit) version: %s\n"
+ "library version: %s\n",
+ IDNKIT_VERSION,
+ idn_version_getstring());
+ exit(0);
+}
+
+static void
+print_usage(char *cmd) {
+ int i;
+
+ fprintf(stderr, "Usage: %s [options..] [file]\n", cmd);
+
+ for (i = 0; options[i] != NULL; i++)
+ fprintf(stderr, "\t%s\n", options[i]);
+
+ exit(1);
+}
+
+static unsigned long
+get_ucs(const char *p) {
+ unsigned long v;
+ char *end;
+
+ /* Skip optional 'U+' */
+ if (strncmp(p, "U+", 2) == 0)
+ p += 2;
+
+ v = strtoul(p, &end, 16);
+ if (*end != '\0') {
+ fprintf(stderr, "invalid UCS code point \"%s\"\n", p);
+ exit(1);
+ }
+
+ return v;
+}
diff --git a/contrib/idn/idnkit-1.0-src/tools/idnconv/idnslookup.in b/contrib/idn/idnkit-1.0-src/tools/idnconv/idnslookup.in
new file mode 100644
index 0000000..d380f1e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/idnconv/idnslookup.in
@@ -0,0 +1,116 @@
+#! /bin/sh
+# $Id: idnslookup.in,v 1.1.1.1 2003/06/04 00:27:10 marka Exp $
+#
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+USAGE="Usage: $0 domain-name DNS-server"
+
+#
+# Parse command line arguments.
+#
+if [ $# -lt 2 ] ; then
+ echo "$0: too few argument" 1>&2
+ echo $USAGE 1>&2
+ exit 1
+fi
+
+if [ $# -gt 2 ] ; then
+ echo "$0: too many argument" 1>&2
+ echo $USAGE 1>&2
+ exit 1
+fi
+
+case "$1" in
+-*) echo "$0: unknown option $1" 1>&2
+ echo $USAGE 1>&2
+ exit 1
+ ;;
+esac
+
+LOCAL_DOMAIN_NAME="$1"
+NAME_SERVER="$2"
+
+#
+# Append some directories to PATH.
+#
+[ -d /usr/sbin ] && PATH=$PATH:/usr/sbin
+[ -d /sbin ] && PATH=$PATH:/sbin
+
+#
+# Find `nslookup' command.
+#
+if [ x"$NSLOOKUP" = x ] ; then
+ for I in `echo $PATH | sed -e 's/:/ /g'` ; do
+ if [ -x $I/nslookup ] ; then
+ NSLOOKUP="$I/nslookup"
+ break
+ fi
+ done
+ if [ "$NSLOOKUP" = "" ] ; then
+ echo "$0: nslookup not found" 1>&2
+ exit 1
+ fi
+fi
+if [ ! -x "$NSLOOKUP" ] ; then
+ echo "$0: nslookup not found" 1>&2
+ exit 1
+fi
+
+#
+# Check if `idnconv' command exists.
+#
+IDNCONV=${IDNCONV-"@bindir@/idnconv"}
+if [ ! -x "$IDNCONV" ] ; then
+ echo "$0: idnconv not found" 1>&2
+ exit 1
+fi
+
+#
+# Convert domain name to IDN encoding.
+#
+IDN_DOMAIN_NAME="`echo $LOCAL_DOMAIN_NAME | $IDNCONV -w`" || exit 1
+
+#
+# Invoke nslookup.
+#
+$NSLOOKUP $IDN_DOMAIN_NAME $NAME_SERVER < /dev/null || exit 1
+
+exit 0
diff --git a/contrib/idn/idnkit-1.0-src/tools/idnconv/make.wnt b/contrib/idn/idnkit-1.0-src/tools/idnconv/make.wnt
new file mode 100644
index 0000000..97ce188
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/idnconv/make.wnt
@@ -0,0 +1,72 @@
+# $Id: make.wnt,v 1.1.1.1 2003/06/04 00:27:06 marka Exp $
+# Makefile for idnconv, manually configured for WIN-NT (VC5.0)
+#
+# Copyright (c) 2000,2002 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+!include <ntwin32.mak>
+
+INCDIR = ..\..\include
+ICONVDIR = ..\..\win
+IDNLIBDIR = ..\..\lib
+LIBS = $(IDNLIBDIR)\idnkit.lib $(ICONVDIR)\iconv.lib
+SYSLIBS = $(conlibsdll)
+
+SRCS = idnconv.c util.c selectiveencode.c
+OBJS = idnconv.obj util.obj selectiveencode.obj
+
+TARGET = idnconv.exe
+
+all: $(TARGET)
+
+idnconv.exe: $(OBJS) $(LIBS)
+ $(link) $(conflags) /out:idnconv.exe $(OBJS) $(LIBS) $(SYSLIBS)
+
+install:
+
+clean:
+ -del *.exe *.obj *.lib core *.core *~
+
+idnconv.obj: idnconv.c
+ $(cc) $(cflags) $(cvarsdll) -I$(INCDIR) $*.c
+util.obj: util.c
+ $(cc) $(cflags) $(cvarsdll) -I$(INCDIR) $*.c
+selectiveencode.obj: selectiveencode.c
+ $(cc) $(cflags) $(cvarsdll) -I$(INCDIR) $*.c
diff --git a/contrib/idn/idnkit-1.0-src/tools/idnconv/selectiveencode.c b/contrib/idn/idnkit-1.0-src/tools/idnconv/selectiveencode.c
new file mode 100644
index 0000000..ae509df
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/idnconv/selectiveencode.c
@@ -0,0 +1,127 @@
+#ifndef lint
+static char *rcsid = "$Id: selectiveencode.c,v 1.1.1.1 2003/06/04 00:27:07 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <idn/assert.h>
+#include <idn/logmacro.h>
+#include <idn/result.h>
+#include <idn/utf8.h>
+#include <idn/debug.h>
+
+#include "selectiveencode.h"
+
+static int is_domain_delimiter(char c);
+static char *find_nonascii(const char *s);
+
+idn_result_t
+idn_selectiveencode_findregion(const char *s,
+ char **startp, char **endp)
+{
+ char *non_ascii;
+ char *start, *end;
+
+ assert(s != NULL && startp != NULL && endp != NULL);
+
+ TRACE(("idn_selectiveencode_findregion(s=\"%s\")\n",
+ idn__debug_xstring(s, 20)));
+
+ /*
+ * Scan the specified string looking for non-ascii character.
+ */
+ if ((non_ascii = find_nonascii(s)) == NULL)
+ return (idn_notfound);
+
+ /*
+ * Non-ascii character found.
+ * Determine the region to encode.
+ */
+
+ /*
+ * First, we scan backwards to find the beginning of the region
+ * that should be converted.
+ */
+ start = non_ascii;
+ while (start > s) {
+ char *prev = idn_utf8_findfirstbyte(start - 1, s);
+ if (is_domain_delimiter(*prev))
+ break; /* Found */
+ start = prev;
+ }
+ *startp = start;
+
+ /*
+ * Next we scan forwards looking for the end of the region.
+ */
+ end = non_ascii + idn_utf8_mblen(non_ascii);
+ while (!is_domain_delimiter(*end))
+ end += idn_utf8_mblen(end);
+ *endp = end;
+
+ return (idn_success);
+}
+
+static int
+is_domain_delimiter(char c) {
+ return ((unsigned char)c < 0x80 &&
+ !('A' <= c && c <= 'Z') &&
+ !('a' <= c && c <= 'z') &&
+ !('0' <= c && c <= '9') &&
+ c != '-' && c != '.');
+}
+
+static char *
+find_nonascii(const char *s) {
+ while (*s != '\0' && (unsigned char)*s < 0x80)
+ s++;
+ if (*s == '\0')
+ return (NULL);
+ else
+ return ((char *)s);
+}
diff --git a/contrib/idn/idnkit-1.0-src/tools/idnconv/selectiveencode.h b/contrib/idn/idnkit-1.0-src/tools/idnconv/selectiveencode.h
new file mode 100644
index 0000000..ec4d8f6
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/idnconv/selectiveencode.h
@@ -0,0 +1,70 @@
+/* $Id: selectiveencode.h,v 1.1.1.1 2003/06/04 00:27:08 marka Exp $ */
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_SELECTIVENCODE_H
+#define IDN_SELECTIVENCODE_H 1
+
+/*
+ * Find where to convert.
+ *
+ * Find a substring for which IDN domain name codeset conversion is necessary.
+ */
+
+#include <idn/result.h>
+
+/*
+ * Scan the given string 's' (in UTF-8 encoding) looking for a substring
+ * made of
+ * + at least one non-ascii character and
+ * + zero or more legitimate domain-name characters (i.e. ascii alphabets,
+ * digits and hyphens) and periods.
+ *
+ * Returns:
+ * idn_success -- ok, found.
+ * idn_notfound -- not found.
+ */
+extern idn_result_t
+idn_selectiveencode_findregion(const char *s, char **startp, char **endp);
+
+#endif /* IDN_SELECTIVENCODE_H */
diff --git a/contrib/idn/idnkit-1.0-src/tools/idnconv/util.c b/contrib/idn/idnkit-1.0-src/tools/idnconv/util.c
new file mode 100644
index 0000000..35677e9
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/idnconv/util.c
@@ -0,0 +1,554 @@
+#ifndef lint
+static char *rcsid = "$Id: util.c,v 1.1.1.1 2003/06/04 00:27:08 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <idn/resconf.h>
+#include <idn/converter.h>
+#include <idn/res.h>
+#include <idn/utf8.h>
+
+#include "util.h"
+#include "selectiveencode.h"
+
+extern int line_number;
+
+idn_result_t
+selective_encode(idn_resconf_t conf, idn_action_t actions,
+ char *from, char *to, int tolen)
+{
+ for (;;) {
+ int len;
+ char *region_start, *region_end;
+ idn_result_t r;
+ char save;
+
+ /*
+ * Find the region that needs conversion.
+ */
+ r = idn_selectiveencode_findregion(from, &region_start,
+ &region_end);
+ if (r == idn_notfound) {
+ /*
+ * Not found. Just copy the whole thing.
+ */
+ if (tolen <= strlen(from))
+ return (idn_buffer_overflow);
+ (void)strcpy(to, from);
+ return (idn_success);
+ } else if (r != idn_success) {
+ /* This should not happen.. */
+ errormsg("internal error at line %d: %s\n",
+ line_number, idn_result_tostring(r));
+ return (r);
+ }
+
+ /*
+ * We have found a region to convert.
+ * First, copy the prefix part verbatim.
+ */
+ len = region_start - from;
+ if (tolen < len) {
+ errormsg("internal buffer overflow at line %d\n",
+ line_number);
+ return (idn_buffer_overflow);
+ }
+ (void)memcpy(to, from, len);
+ to += len;
+ tolen -= len;
+
+ /*
+ * Terminate the region with NUL.
+ */
+ save = *region_end;
+ *region_end = '\0';
+
+ /*
+ * Encode the region.
+ */
+ r = idn_res_encodename(conf, actions, region_start, to, tolen);
+
+ /*
+ * Restore character.
+ */
+ *region_end = save;
+
+ if (r != idn_success)
+ return (r);
+
+ len = strlen(to);
+ to += len;
+ tolen -= len;
+
+ from = region_end;
+ }
+}
+
+idn_result_t
+selective_decode(idn_resconf_t conf, idn_action_t actions,
+ char *from, char *to, int tolen)
+{
+ char *domain_name;
+ char *ignored_chunk;
+ char save;
+ int len;
+ idn_result_t r;
+
+ /*
+ * While `*from' points to a character in a string which may be
+ * a domain name, `domain_name' refers to the beginning of the
+ * domain name.
+ */
+ domain_name = NULL;
+
+ /*
+ * We ignore chunks matching to the regular expression:
+ * [\-\.][0-9A-Za-z\-\.]*
+ *
+ * While `*from' points to a character in such a chunk,
+ * `ignored_chunk' refers to the beginning of the chunk.
+ */
+ ignored_chunk = NULL;
+
+ for (;;) {
+ if (*from == '-') {
+ /*
+ * We don't recognize `.-' as a part of domain name.
+ */
+ if (domain_name != NULL) {
+ if (*(from - 1) == '.') {
+ ignored_chunk = domain_name;
+ domain_name = NULL;
+ }
+ } else if (ignored_chunk == NULL) {
+ ignored_chunk = from;
+ }
+
+ } else if (*from == '.') {
+ /*
+ * We don't recognize `-.' nor `..' as a part of
+ * domain name.
+ */
+ if (domain_name != NULL) {
+ if (*(from - 1) == '-' || *(from - 1) == '.') {
+ ignored_chunk = domain_name;
+ domain_name = NULL;
+ }
+ } else if (ignored_chunk == NULL) {
+ ignored_chunk = from;
+ }
+
+ } else if (('a' <= *from && *from <= 'z') ||
+ ('A' <= *from && *from <= 'Z') ||
+ ('0' <= *from && *from <= '9')) {
+ if (ignored_chunk == NULL && domain_name == NULL)
+ domain_name = from;
+
+ } else {
+ if (ignored_chunk != NULL) {
+ /*
+ * `from' reaches the end of the ignored chunk.
+ * Copy the chunk to `to'.
+ */
+ len = from - ignored_chunk;
+ if (tolen < len)
+ return (idn_buffer_overflow);
+ (void)memcpy(to, ignored_chunk, len);
+ to += len;
+ tolen -= len;
+
+ } else if (domain_name != NULL) {
+ /*
+ * `from' reaches the end of the domain name.
+ * Decode the domain name, and copy the result
+ * to `to'.
+ */
+ save = *from;
+ *from = '\0';
+ r = idn_res_decodename(conf, actions,
+ domain_name, to, tolen);
+ *from = save;
+
+ if (r == idn_success) {
+ len = strlen(to);
+ } else if (r == idn_invalid_encoding) {
+ len = from - domain_name;
+ if (tolen < len)
+ return (idn_buffer_overflow);
+ (void)memcpy(to, domain_name, len);
+ } else {
+ return (r);
+ }
+ to += len;
+ tolen -= len;
+ }
+
+ /*
+ * Copy a character `*from' to `to'.
+ */
+ if (tolen < 1)
+ return (idn_buffer_overflow);
+ *to = *from;
+ to++;
+ tolen--;
+
+ domain_name = NULL;
+ ignored_chunk = NULL;
+
+ if (*from == '\0')
+ break;
+ }
+
+ from++;
+ }
+
+ return (idn_success);
+}
+
+void
+set_defaults(idn_resconf_t conf) {
+ idn_result_t r;
+
+ if ((r = idn_resconf_setdefaults(conf)) != idn_success) {
+ errormsg("error setting default configuration: %s\n",
+ idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+load_conf_file(idn_resconf_t conf, const char *file) {
+ idn_result_t r;
+
+ if ((r = idn_resconf_loadfile(conf, file)) != idn_success) {
+ errormsg("error reading configuration file: %s\n",
+ idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+set_encoding_alias(const char *encoding_alias) {
+ idn_result_t r;
+
+ if ((r = idn_converter_resetalias()) != idn_success) {
+ errormsg("cannot reset alias information: %s\n",
+ idn_result_tostring(r));
+ exit(1);
+ }
+
+ if ((r = idn_converter_aliasfile(encoding_alias)) != idn_success) {
+ errormsg("cannot read alias file %s: %s\n",
+ encoding_alias, idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+set_localcode(idn_resconf_t conf, const char *code) {
+ idn_result_t r;
+
+ r = idn_resconf_setlocalconvertername(conf, code,
+ IDN_CONVERTER_RTCHECK);
+ if (r != idn_success) {
+ errormsg("cannot create converter for codeset %s: %s\n",
+ code, idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+set_idncode(idn_resconf_t conf, const char *code) {
+ idn_result_t r;
+
+ r = idn_resconf_setidnconvertername(conf, code,
+ IDN_CONVERTER_RTCHECK);
+ if (r != idn_success) {
+ errormsg("cannot create converter for codeset %s: %s\n",
+ code, idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+set_delimitermapper(idn_resconf_t conf, unsigned long *delimiters,
+ int ndelimiters) {
+ idn_result_t r;
+
+ r = idn_resconf_addalldelimitermapucs(conf, delimiters, ndelimiters);
+ if (r != idn_success) {
+ errormsg("cannot add delimiter: %s\n",
+ idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+set_localmapper(idn_resconf_t conf, char **mappers, int nmappers) {
+ idn_result_t r;
+
+ /* Add mapping. */
+ r = idn_resconf_addalllocalmapselectornames(conf,
+ IDN_MAPSELECTOR_DEFAULTTLD,
+ (const char **)mappers,
+ nmappers);
+ if (r != idn_success) {
+ errormsg("cannot add local map: %s\n",
+ idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+set_nameprep(idn_resconf_t conf, char *version) {
+ idn_result_t r;
+
+ r = idn_resconf_setnameprepversion(conf, version);
+ if (r != idn_success) {
+ errormsg("error setting nameprep %s: %s\n",
+ version, idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+set_mapper(idn_resconf_t conf, char **mappers, int nmappers) {
+ idn_result_t r;
+
+ /* Configure mapper. */
+ r = idn_resconf_addallmappernames(conf, (const char **)mappers,
+ nmappers);
+ if (r != idn_success) {
+ errormsg("cannot add nameprep map: %s\n",
+ idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+set_normalizer(idn_resconf_t conf, char **normalizers, int nnormalizer) {
+ idn_result_t r;
+
+ r = idn_resconf_addallnormalizernames(conf,
+ (const char **)normalizers,
+ nnormalizer);
+ if (r != idn_success) {
+ errormsg("cannot add normalizer: %s\n",
+ idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+set_prohibit_checkers(idn_resconf_t conf, char **prohibits, int nprohibits) {
+ idn_result_t r;
+
+ r = idn_resconf_addallprohibitcheckernames(conf,
+ (const char **)prohibits,
+ nprohibits);
+ if (r != idn_success) {
+ errormsg("cannot add prohibit checker: %s\n",
+ idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+set_unassigned_checkers(idn_resconf_t conf, char **unassigns, int nunassigns) {
+ idn_result_t r;
+
+ r = idn_resconf_addallunassignedcheckernames(conf,
+ (const char **)unassigns,
+ nunassigns);
+ if (r != idn_success) {
+ errormsg("cannot add unassigned checker: %s\n",
+ idn_result_tostring(r));
+ exit(1);
+ }
+}
+
+void
+errormsg(const char *fmt, ...) {
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+}
+
+
+/*
+ * Dynamic Stirng Buffer Utility
+ */
+
+void
+strbuf_init(idnconv_strbuf_t *buf) {
+ /*
+ * Initialize the given string buffer.
+ * Caller must allocate the structure (idnconv_strbuf_t)
+ * as an automatic variable or by malloc().
+ */
+ buf->str = buf->local_buf;
+ buf->str[0] = '\0';
+ buf->size = sizeof(buf->local_buf);
+}
+
+void
+strbuf_reset(idnconv_strbuf_t *buf) {
+ /*
+ * Reset the given string buffer.
+ * Free memory allocated by this utility, and
+ * re-initialize.
+ */
+ if (buf->str != NULL && buf->str != buf->local_buf) {
+ free(buf->str);
+ }
+ strbuf_init(buf);
+}
+
+char *
+strbuf_get(idnconv_strbuf_t *buf) {
+ /*
+ * Get the pointer of the buffer.
+ */
+ return (buf->str);
+}
+
+size_t
+strbuf_size(idnconv_strbuf_t *buf) {
+ /*
+ * Get the allocated size of the buffer.
+ */
+ return (buf->size);
+}
+
+char *
+strbuf_copy(idnconv_strbuf_t *buf, const char *str) {
+ /*
+ * Copy STR to BUF.
+ */
+ size_t len = strlen(str);
+
+ if (strbuf_alloc(buf, len + 1) == NULL)
+ return (NULL);
+ strcpy(buf->str, str);
+ return (buf->str);
+}
+
+char *
+strbuf_append(idnconv_strbuf_t *buf, const char *str) {
+ /*
+ * Append STR to the end of BUF.
+ */
+ size_t len1 = strlen(buf->str);
+ size_t len2 = strlen(str);
+ char *p;
+#define MARGIN 50
+
+ p = strbuf_alloc(buf, len1 + len2 + 1 + MARGIN);
+ if (p != NULL)
+ strcpy(buf->str + len1, str);
+ return (p);
+}
+
+char *
+strbuf_alloc(idnconv_strbuf_t *buf, size_t size) {
+ /*
+ * Reallocate the buffer of BUF if needed
+ * so that BUF can hold SIZE bytes of data at least.
+ */
+ char *p;
+
+ if (buf->size >= size)
+ return (buf->str);
+ if (buf->str == buf->local_buf) {
+ if ((p = malloc(size)) == NULL)
+ return (NULL);
+ memcpy(p, buf->local_buf, sizeof(buf->local_buf));
+ } else {
+ if ((p = realloc(buf->str, size)) == NULL)
+ return (NULL);
+ }
+ buf->str = p;
+ buf->size = size;
+ return (buf->str);
+}
+
+char *
+strbuf_double(idnconv_strbuf_t *buf) {
+ /*
+ * Double the size of the buffer of BUF.
+ */
+ return (strbuf_alloc(buf, buf->size * 2));
+}
+
+char *
+strbuf_getline(idnconv_strbuf_t *buf, FILE *fp) {
+ /*
+ * Read a line from FP.
+ */
+ char s[256];
+
+ buf->str[0] = '\0';
+ while (fgets(s, sizeof(s), fp) != NULL) {
+ if (strbuf_append(buf, s) == NULL)
+ return (NULL);
+ if (strlen(s) < sizeof(s) - 1 || s[sizeof(s) - 2] == '\n')
+ return (buf->str);
+ }
+ if (buf->str[0] != '\0')
+ return (buf->str);
+ return (NULL);
+}
diff --git a/contrib/idn/idnkit-1.0-src/tools/idnconv/util.h b/contrib/idn/idnkit-1.0-src/tools/idnconv/util.h
new file mode 100644
index 0000000..43c5b41
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/idnconv/util.h
@@ -0,0 +1,96 @@
+/* $Id: util.h,v 1.1.1.1 2003/06/04 00:27:09 marka Exp $ */
+/*
+ * Copyright (c) 2000,2001 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef IDN_IDNCONV_UTIL_H
+#define IDN_IDNCONV_UTIL_H 1
+
+#include <idn/res.h>
+
+#define IDNCONV_LOCALBUF_SIZE 512
+
+typedef struct {
+ char *str;
+ size_t size;
+ char local_buf[IDNCONV_LOCALBUF_SIZE];
+} idnconv_strbuf_t;
+
+extern idn_result_t selective_encode(idn_resconf_t conf,
+ idn_action_t actions, char *from,
+ char *to, int tolen);
+extern idn_result_t selective_decode(idn_resconf_t conf,
+ idn_action_t actions, char *from,
+ char *to, int tolen);
+extern void set_defaults(idn_resconf_t conf);
+extern void load_conf_file(idn_resconf_t conf, const char *file);
+extern void set_encoding_alias(const char *encoding_alias);
+extern void set_localcode(idn_resconf_t conf, const char *code);
+extern void set_idncode(idn_resconf_t conf, const char *code);
+extern void set_delimitermapper(idn_resconf_t conf,
+ unsigned long *delimiters,
+ int ndelimiters);
+extern void set_localmapper(idn_resconf_t conf,
+ char **mappers, int nmappers);
+extern void set_nameprep(idn_resconf_t conf, char *version);
+extern void set_mapper(idn_resconf_t conf,
+ char **mappers, int nmappers);
+extern void set_normalizer(idn_resconf_t conf,
+ char **normalizer, int nnormalizer);
+extern void set_prohibit_checkers(idn_resconf_t conf,
+ char **prohibits,
+ int nprohibits);
+extern void set_unassigned_checkers(idn_resconf_t conf,
+ char **unassigns,
+ int nunassigns);
+extern void errormsg(const char *fmt, ...);
+extern void strbuf_init(idnconv_strbuf_t *buf);
+extern void strbuf_reset(idnconv_strbuf_t *buf);
+extern char *strbuf_get(idnconv_strbuf_t *buf);
+extern size_t strbuf_size(idnconv_strbuf_t *buf);
+extern char *strbuf_copy(idnconv_strbuf_t *buf, const char *str);
+extern char *strbuf_append(idnconv_strbuf_t *buf, const char *str);
+extern char *strbuf_alloc(idnconv_strbuf_t *buf, size_t size);
+extern char *strbuf_double(idnconv_strbuf_t *buf);
+extern char *strbuf_getline(idnconv_strbuf_t *buf, FILE *fp);
+
+#endif /* IDN_IDNCONV_UTIL_H */
diff --git a/contrib/idn/idnkit-1.0-src/tools/make.wnt b/contrib/idn/idnkit-1.0-src/tools/make.wnt
new file mode 100644
index 0000000..60518f4
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/make.wnt
@@ -0,0 +1,57 @@
+# $Id: make.wnt,v 1.1.1.1 2003/06/04 00:27:05 marka Exp $
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+all : force
+ cd idnconv
+ $(MAKE) -f make.wnt
+ cd ..
+
+install : all
+ cd idnconv
+ $(MAKE) -f make.wnt install
+ cd ..
+
+clean : force
+ cd idnconv
+ $(MAKE) -f make.wnt clean
+ cd ..
+
+force:
diff --git a/contrib/idn/idnkit-1.0-src/tools/rpm/idnkit.spec b/contrib/idn/idnkit-1.0-src/tools/rpm/idnkit.spec
new file mode 100644
index 0000000..c740570
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/rpm/idnkit.spec
@@ -0,0 +1,142 @@
+%define prefix /usr
+%define sysconfdir /etc
+%define version 1.0
+
+# official/beta release:
+#define release 1
+#define distrel %{version}
+
+# release candidate:
+%define release rc1
+%define distrel %{version}-%{release}
+
+%define serial 2002051501
+
+%define name idnkit
+%define distsrc %{name}-%{distrel}-src
+
+Name: %{name}
+Version: %{version}
+Release: %{release}
+Copyright: distributable
+Group: System Environment
+Source: %{distsrc}.tar.gz
+BuildRoot: /var/tmp/%{name}-root
+Serial: %{serial}
+Summary: Internationalized Domain Name kit (idnkit/JPNIC)
+Vendor: JPNIC
+Packager: Japan Network Information Center
+
+%description
+idnkit is a kit for handling Internationalized Domain Name.
+
+%package devel
+Group: Development/Libraries
+Summary: The development files for idnkit
+
+%description devel
+The header files and libraries (libidnkit.a and libidnkitlite.a)
+to develop applications that use the libraries.
+
+%prep
+%setup -n %{distsrc}
+
+%build
+if [ -f /usr/lib/libiconv.a -o -f /usr/lib/libiconv.so ]
+then
+ if [ -f /lib/libc-2.0* ]
+ then
+ ICONV="--with-iconv=yes"
+ fi
+fi
+
+CFLAGS="$RPM_OPT_FLAGS" ./configure \
+ --prefix=%{prefix} --sysconfdir=%{sysconfdir} \
+ --enable-runidn \
+ $ICONV
+make
+
+%install
+rm -fr $RPM_BUILD_ROOT
+make DESTDIR=$RPM_BUILD_ROOT install
+mv $RPM_BUILD_ROOT/etc/idn.conf.sample $RPM_BUILD_ROOT/etc/idn.conf
+mv $RPM_BUILD_ROOT/etc/idnalias.conf.sample $RPM_BUILD_ROOT/etc/idnalias.conf
+
+# devel kit
+#install -c lib/libidnkit.a $RPM_BUILD_ROOT/usr/lib
+#cp -r include/idn $RPM_BUILD_ROOT/usr/include
+
+# docs
+mkdir rpm_docs
+(cp NEWS INSTALL INSTALL.ja DISTFILES README.ja README LICENSE.txt \
+ ChangeLog rpm_docs)
+cp -r patch rpm_docs
+
+%clean
+rm -fr $RPM_BUILD_ROOT
+
+%files
+%defattr(-, root, root)
+%{prefix}/bin/idnconv
+%{prefix}/bin/runidn
+%{prefix}/lib/libidnkit.so.*
+%{prefix}/lib/libidnkitlite.so.*
+%{prefix}/lib/libidnkitres.so.*
+%{prefix}/share/idnkit/*
+%config %{sysconfdir}/idn.conf
+%config %{sysconfdir}/idnalias.conf
+%attr(0644, root, root) %config(noreplace)
+%attr(0644, root, man) %{prefix}/man/man1/*
+%attr(0644, root, man) %{prefix}/man/man3/*
+%attr(0644, root, man) %{prefix}/man/man5/*
+%doc rpm_docs/*
+
+%files devel
+%defattr(-, root, root)
+%{prefix}/lib/libidnkit.a
+%{prefix}/lib/libidnkit.la
+%{prefix}/lib/libidnkit.so
+%{prefix}/lib/libidnkitlite.a
+%{prefix}/lib/libidnkitlite.la
+%{prefix}/lib/libidnkitlite.so
+%{prefix}/lib/libidnkitres.a
+%{prefix}/lib/libidnkitres.la
+%{prefix}/lib/libidnkitres.so
+%{prefix}/include/idn/*
+
+%changelog
+* Web May 15 2002 Motoyuki Kasahara <m-kasahr@sra.co.jp>
+- 1.0beta2, experimental.
+
+* Mon May 28 2001 MANABE Takashi <manabe@dsl.gr.jp>
+- include runmdn, libmdnresolv
+
+* Mon Apr 4 2001 Motoyuki Kasahara <m-kasahr@sra.co.jp>
+- 2.1 release
+
+* Mon Apr 4 2001 Motoyuki Kasahara <m-kasahr@sra.co.jp>
+- 2.0.1 release
+
+* Mon Apr 2 2001 MANABE Takashi <manabe@dsl.gr.jp>
+- 2.0 release
+
+* Fri Mar 3 2001 MANABE Takashi <manabe@dsl.gr.jp>
+- 1.3 release
+
+* Mon Dec 6 2000 MANABE Takashi <manabe@dsl.gr.jp>
+- add brace/lace functions to libmdnresolv(mdnkit-1.2-runmdn.patch)
+- include /var/dnsproxy
+- change files section for compressed man pages
+
+* Mon Nov 27 2000 Makoto Ishisone <ishisone@sra.co.jp>
+- 1.2 release
+
+* Thu Nov 2 2000 MANABE Takashi <manabe@dsl.gr.jp>
+- 1.1 release
+
+* Fri Oct 27 2000 MANABE Takashi <manabe@dsl.gr.jp>
+- dnsproxy.patch1
+- move libmdnresolv.{la,so} from mdnkit-devel to mdnkit package
+
+* Wed Oct 18 2000 MANABE Takashi <manabe@dsl.gr.jp>
+- 1.0 release
diff --git a/contrib/idn/idnkit-1.0-src/tools/runidn/Makefile.in b/contrib/idn/idnkit-1.0-src/tools/runidn/Makefile.in
new file mode 100644
index 0000000..c3098ff
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/runidn/Makefile.in
@@ -0,0 +1,167 @@
+# $Id: Makefile.in,v 1.1.1.1 2003/06/04 00:27:11 marka Exp $
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+LIB_CURRENT = 1
+LIB_REVISION = 1
+LIB_AGE = 0
+
+.SUFFIXES:
+.SUFFIXES: .c .lo
+
+top_builddir = ../..
+subdir = tools/runidn
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+libdir = @libdir@
+mandir = @mandir@
+man1dir = $(mandir)/man1
+
+CC = @CC@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+MKINSTALLDIRS = @top_srcdir@/mkinstalldirs
+SHELL = @SHELL@
+LIBTOOL = @LIBTOOL@
+
+ICONVINC = @ICONVINC@
+ICONVLIB = @ICONVLIB@
+
+INCS = -I$(srcdir) -I$(srcdir)/../../include -I../../include $(ICONVINC)
+DEFS =
+
+CFLAGS = $(INCS) $(DEFS) @CPPFLAGS@ @CFLAGS@
+LDFLAGS = @LDFLAGS@
+
+LIB = libidnkitres
+OBJS = rtresolver.lo stub.lo $(IDNOBJS)
+SCRIPT = runidn
+LIBDL = @LIBDL@
+
+IDNDIR = ../../lib
+IDNOBJS = \
+ $(IDNDIR)/aliaslist.lo \
+ $(IDNDIR)/api.lo \
+ $(IDNDIR)/checker.lo \
+ $(IDNDIR)/converter.lo \
+ $(IDNDIR)/debug.lo \
+ $(IDNDIR)/delimitermap.lo \
+ $(IDNDIR)/filechecker.lo \
+ $(IDNDIR)/filemapper.lo \
+ $(IDNDIR)/localencoding.lo \
+ $(IDNDIR)/log.lo \
+ $(IDNDIR)/mapper.lo \
+ $(IDNDIR)/mapselector.lo \
+ $(IDNDIR)/nameprep.lo \
+ $(IDNDIR)/normalizer.lo \
+ $(IDNDIR)/punycode.lo \
+ $(IDNDIR)/race.lo \
+ $(IDNDIR)/res.lo \
+ $(IDNDIR)/resconf.lo \
+ $(IDNDIR)/result.lo \
+ $(IDNDIR)/strhash.lo \
+ $(IDNDIR)/ucsmap.lo \
+ $(IDNDIR)/ucsset.lo \
+ $(IDNDIR)/unicode.lo \
+ $(IDNDIR)/unormalize.lo \
+ $(IDNDIR)/ucs4.lo \
+ $(IDNDIR)/utf8.lo \
+ $(IDNDIR)/util.lo \
+ $(IDNDIR)/version.lo
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c $<
+
+@RUNIDN_TRUE@all: $(LIB).la runidn
+@RUNIDN_FALSE@all:
+
+rtresolver.lo: $(srcdir)/resolver.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -DFOR_RUNIDN -o $@ \
+ -c $(srcdir)/resolver.c
+
+$(LIB).la: $(OBJS)
+ $(LIBTOOL) --mode=link $(LD) $(LDFLAGS) -o $@ \
+ -version-info $(LIB_CURRENT):$(LIB_REVISION):$(LIB_AGE) \
+ -module -rpath $(libdir) $(OBJS) $(LIBDL)
+
+runidn: $(srcdir)/runidn.in
+ cd $(top_builddir) && \
+ CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= CONFIG_LINKS= \
+ $(SHELL) ./config.status
+
+@RUNIDN_TRUE@@COMPAT_TRUE@install: all install-runidn install-compat
+@RUNIDN_TRUE@@COMPAT_FALSE@install: all install-runidn
+@RUNIDN_FALSE@install:
+
+install-runidn:
+ $(MKINSTALLDIRS) $(DESTDIR)$(libdir)
+ $(LIBTOOL) --mode=install $(INSTALL_DATA) $(LIB).la \
+ $(DESTDIR)$(libdir)/$(LIB).la
+ $(MKINSTALLDIRS) $(DESTDIR)$(bindir)
+ $(INSTALL_SCRIPT) $(SCRIPT) $(DESTDIR)$(bindir)
+ $(MKINSTALLDIRS) $(DESTDIR)$(man1dir)
+ $(INSTALL_DATA) $(srcdir)/runidn.1 $(DESTDIR)$(man1dir)/runidn.1
+
+install-compat:
+ src=$(DESTDIR)$(bindir)/runidn; \
+ dst=$(DESTDIR)$(bindir)/runmdn; \
+ rm -f $$dst; \
+ ln $$src $$dst || cp $$src $$dst
+ src=$(DESTDIR)$(man1dir)/runidn.1; \
+ dst=$(DESTDIR)$(man1dir)/runmdn.1; \
+ rm -f $$dst; \
+ ln $$src $$dst || cp $$src $$dst
+
+clean:
+ rm -f *.lo *.la *.o
+ rm -fr .libs/
+
+distclean: clean
+ rm -f runidn Makefile
+
+test check:
diff --git a/contrib/idn/idnkit-1.0-src/tools/runidn/resolver.c b/contrib/idn/idnkit-1.0-src/tools/runidn/resolver.c
new file mode 100644
index 0000000..129c704
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/runidn/resolver.c
@@ -0,0 +1,1056 @@
+#ifndef lint
+static char *rcsid = "$Id: resolver.c,v 1.1.1.1 2003/06/04 00:27:12 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <errno.h>
+
+#include <idn/api.h>
+#include <idn/log.h>
+#include <idn/logmacro.h>
+#include <idn/debug.h>
+
+#ifdef FOR_RUNIDN
+/*
+ * This file is specially compiled for runidn.
+ * runidn replaces existing resolver functions dynamically with ones
+ * with IDN processing (encoding conversion and normalization).
+ * So entry names must be same as the system's one.
+ */
+#include "stub.h"
+
+#define ENTRY(name) name
+#define REAL(name) idn_stub_ ## name
+#else
+/*
+ * For normal use. All the entry names are prefixed with "idn_resolver_".
+ * <idn/resolver.h> has bunch of #defines to substitute the standard
+ * name resolver functions with ones provided here.
+ */
+#include "resolver.h"
+#undef gethostbyname
+#undef gethostbyname2
+#undef gethostbyaddr
+#undef gethostbyname_r
+#undef gethostbyname2_r
+#undef gethostbyaddr_r
+#undef getipnodebyname
+#undef getipnodebyaddr
+#undef getaddrinfo
+#undef getnameinfo
+
+#define ENTRY(name) idn_resolver_ ## name
+#define REAL(name) name
+#endif
+
+#define IDN_NAME_SIZE 512
+
+#define IDN_HOSTBUF_SIZE 2048
+typedef union {
+ char *dummy_for_alignment;
+ char data[IDN_HOSTBUF_SIZE];
+} hostbuf_t;
+
+typedef struct obj_lock {
+ void *key;
+ struct obj_lock *next;
+} obj_lock_t;
+
+#define OBJLOCKHASH_SIZE 127
+static obj_lock_t *obj_lock_hash[OBJLOCKHASH_SIZE];
+
+/*
+ * This variable is to prevent IDN processing occuring more than once for
+ * a single name resolution. This will happen if some resolver function
+ * is implemented using another function (e.g. gethostbyname() implemented
+ * using gethostbyname2()).
+ * No, using the static variable is not a correct thing to do for a multi-
+ * threading environment, but I don't think of a better solution..
+ */
+static int idn_isprocessing = 0;
+
+static int obj_hash(void *key);
+static int obj_islocked(void *key);
+static void obj_lock(void *key);
+static void obj_unlock(void *key);
+static struct hostent *copy_decode_hostent_static(struct hostent *hp,
+ struct hostent *newhp,
+ char *buf, size_t buflen,
+ int *errp);
+static char *decode_name_dynamic(const char *name);
+static struct hostent *copy_decode_hostent_dynamic(struct hostent *hp,
+ int *errp);
+static void free_copied_hostent(struct hostent *hp);
+#ifdef HAVE_GETADDRINFO
+static struct addrinfo *copy_decode_addrinfo_dynamic(struct addrinfo *aip);
+#endif
+#ifdef HAVE_FREEADDRINFO
+static void free_copied_addrinfo(struct addrinfo *aip);
+#endif
+
+/*
+ * Object locking facility.
+ */
+
+static int
+obj_hash(void *key) {
+ /*
+ * Hash function for obj_*.
+ * 'key' is supposed to be an address.
+ */
+ unsigned long v = (unsigned long)key;
+
+ return ((v >> 3) % OBJLOCKHASH_SIZE);
+}
+
+static int
+obj_islocked(void *key)
+{
+ /*
+ * Check if the object specified by 'key' is locked.
+ * Return 1 if so, 0 otherwise.
+ */
+ int h = obj_hash(key);
+ obj_lock_t *olp = obj_lock_hash[h];
+
+ while (olp != NULL) {
+ if (olp->key == key)
+ return (1);
+ olp = olp->next;
+ }
+ return (0);
+}
+
+static void
+obj_lock(void *key)
+{
+ /*
+ * Lock an object specified by 'key'.
+ */
+ int h = obj_hash(key);
+ obj_lock_t *olp;
+
+ olp = malloc(sizeof(obj_lock_t));
+ if (olp != NULL) {
+ olp->key = key;
+ olp->next = obj_lock_hash[h];
+ obj_lock_hash[h] = olp;
+ }
+}
+
+static void
+obj_unlock(void *key)
+{
+ /*
+ * Unlock an object specified by 'key'.
+ */
+ int h = obj_hash(key);
+ obj_lock_t *olp, *olp0;
+
+ olp = obj_lock_hash[h];
+ olp0 = NULL;
+ while (olp != NULL) {
+ if (olp->key == key) {
+ if (olp0 == NULL)
+ obj_lock_hash[h] = olp->next;
+ else
+ olp0->next = olp->next;
+ free(olp);
+ return;
+ }
+ olp0 = olp;
+ olp = olp->next;
+ }
+}
+
+static struct hostent *
+copy_decode_hostent_static(struct hostent *hp, struct hostent *newhp,
+ char *buf, size_t buflen, int *errp)
+{
+ /*
+ * Copy "struct hostent" data referenced by 'hp' to 'newhp'.
+ * It's a deep-copy, meaning all the data referenced by 'hp' are
+ * also copied. They are copied into 'buf', whose length is 'buflen'.
+ * The domain names ('hp->h_name' and 'hp->h_aliases') are
+ * decoded from ACE to the local encoding before they are copied.
+ * If 'buf' is too small to hold all the data, NULL will be
+ * returned and '*errp' is set to NO_RECOVERY.
+ */
+ int naliases = 0;
+ int naddrs = 0;
+
+ if (hp == NULL)
+ return (NULL);
+
+ *newhp = *hp;
+
+ if (hp->h_aliases != NULL) {
+ /*
+ * Allocate aliase table in 'buf'.
+ */
+ size_t sz;
+
+ while (hp->h_aliases[naliases] != NULL)
+ naliases++;
+
+ newhp->h_aliases = (char **)buf;
+ sz = sizeof(char *) * (naliases + 1);
+
+ if (buflen < sz)
+ goto overflow;
+
+ buf += sz;
+ buflen -= sz;
+ }
+
+ if (hp->h_addr_list != NULL) {
+ /*
+ * Allocate address table in 'buf'.
+ */
+ size_t sz;
+ int i;
+
+ while (hp->h_addr_list[naddrs] != NULL)
+ naddrs++;
+
+ newhp->h_addr_list = (char **)buf;
+ sz = sizeof(char *) * (naddrs + 1);
+
+ if (buflen < sz)
+ goto overflow;
+
+ buf += sz;
+ buflen -= sz;
+
+ /*
+ * Copy the addresses.
+ */
+ sz = hp->h_length * naddrs;
+ if (buflen < sz)
+ goto overflow;
+
+ for (i = 0; i < naddrs; i++) {
+ newhp->h_addr_list[i] = buf;
+ memcpy(buf, hp->h_addr_list[i], hp->h_length);
+ buf += hp->h_length;
+ }
+ newhp->h_addr_list[naddrs] = NULL;
+
+ buf += sz;
+ buflen -= sz;
+ }
+
+ if (hp->h_name != NULL) {
+ /*
+ * Decode the name in h_name.
+ */
+ idn_result_t r;
+ size_t slen;
+
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_decodename(IDN_DECODE_APP, hp->h_name,
+ buf, buflen);
+ switch (r) {
+ case idn_success:
+ newhp->h_name = buf;
+ break;
+ default:
+ /* Copy hp->h_name verbatim. */
+ if (strlen(hp->h_name) + 1 <= buflen) {
+ newhp->h_name = buf;
+ strcpy(buf, hp->h_name);
+ break;
+ }
+ /* falllthrough */
+ case idn_buffer_overflow:
+ goto overflow;
+ }
+
+ slen = strlen(buf) + 1;
+ buf += slen;
+ buflen -= slen;
+ }
+
+ if (hp->h_aliases != NULL) {
+ /*
+ * Decode the names in h_aliases.
+ */
+ char **aliases = hp->h_aliases;
+ char **newaliases = newhp->h_aliases;
+ int i;
+
+ for (i = 0; i < naliases; i++) {
+ idn_result_t r;
+ size_t slen;
+
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_decodename(IDN_DECODE_APP, aliases[i],
+ buf, buflen);
+
+ switch (r) {
+ case idn_success:
+ newaliases[i] = buf;
+ break;
+ default:
+ /* Copy hp->h_name verbatim. */
+ if (strlen(aliases[i]) + 1 <= buflen) {
+ newaliases[i] = buf;
+ strcpy(buf, aliases[i]);
+ break;
+ }
+ /* falllthrough */
+ case idn_buffer_overflow:
+ goto overflow;
+ }
+
+ slen = strlen(buf) + 1;
+ buf += slen;
+ buflen -= slen;
+ }
+ newaliases[naliases] = NULL;
+ }
+
+ return (newhp);
+
+ overflow:
+ *errp = NO_RECOVERY;
+ return (NULL);
+}
+
+static char *
+decode_name_dynamic(const char *name) {
+ idn_result_t r;
+ char buf[IDN_NAME_SIZE];
+ char *s;
+
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_decodename(IDN_DECODE_APP, name, buf, sizeof(buf));
+ if (r == idn_success) {
+ name = buf;
+ }
+ s = malloc(strlen(name) + 1);
+ if (s == NULL)
+ return (NULL);
+ else
+ return (strcpy(s, name));
+}
+
+static struct hostent *
+copy_decode_hostent_dynamic(struct hostent *hp, int *errp) {
+ /*
+ * Make a deep-copy of the data referenced by 'hp', and return
+ * a pointer to the copied data.
+ * All the data are dynamically allocated using malloc().
+ * The domain names ('hp->h_name' and 'hp->h_aliases') are
+ * decoded from ACE to the local encoding before they are copied.
+ * If malloc() fails, NULL will be returned and '*errp' is set to
+ * NO_RECOVERY.
+ */
+ struct hostent *newhp;
+ char **pp;
+ size_t alloc_size;
+ int naliases = 0;
+ int naddrs = 0;
+ int i;
+
+ if (hp == NULL)
+ return (NULL);
+
+ if (hp->h_aliases != NULL) {
+ while (hp->h_aliases[naliases] != NULL)
+ naliases++;
+ }
+
+ if (hp->h_addr_list != NULL) {
+ while (hp->h_addr_list[naddrs] != NULL)
+ naddrs++;
+ }
+
+ alloc_size = sizeof(struct hostent) +
+ sizeof(char *) * (naliases + 1) +
+ sizeof(char *) * (naddrs + 1) +
+ hp->h_length * naddrs;
+
+ if ((newhp = malloc(alloc_size)) == NULL) {
+ return (hp);
+ }
+
+ memset(newhp, 0, alloc_size);
+
+ pp = (char **)(newhp + 1);
+
+ if (hp->h_name != NULL) {
+ newhp->h_name = decode_name_dynamic(hp->h_name);
+ if (newhp->h_name == NULL)
+ goto alloc_fail;
+ }
+
+ newhp->h_addrtype = hp->h_addrtype;
+ newhp->h_length = hp->h_length;
+
+ if (hp->h_aliases != NULL) {
+ newhp->h_aliases = pp;
+ for (i = 0; i < naliases; i++) {
+ newhp->h_aliases[i] =
+ decode_name_dynamic(hp->h_aliases[i]);
+ if (newhp->h_aliases[i] == NULL)
+ goto alloc_fail;
+ }
+ newhp->h_aliases[naliases] = NULL;
+ pp += naliases + 1;
+ }
+
+ if (hp->h_addr_list != NULL) {
+ char *p;
+
+ newhp->h_addr_list = pp;
+ pp += naddrs + 1;
+ p = (char *)pp;
+
+ for (i = 0; i < naddrs; i++) {
+ newhp->h_addr_list[i] = p;
+ memcpy(p, hp->h_addr_list[i], hp->h_length);
+ p += hp->h_length;
+ }
+ newhp->h_addr_list[naddrs] = NULL;
+ }
+
+ return (newhp);
+
+ alloc_fail:
+ free_copied_hostent(hp);
+ *errp = NO_RECOVERY;
+ return (NULL);
+}
+
+static void
+free_copied_hostent(struct hostent *hp) {
+ /*
+ * Free all the memory allocated by copy_decode_hostent_dynamic().
+ */
+ if (hp->h_name != NULL)
+ free(hp->h_name);
+ if (hp->h_aliases != NULL) {
+ char **pp = hp->h_aliases;
+ while (*pp != NULL)
+ free(*pp++);
+ }
+ free(hp);
+}
+
+#ifdef HAVE_GETNAMEINFO
+static struct addrinfo *
+copy_decode_addrinfo_dynamic(struct addrinfo *aip) {
+ struct addrinfo *newaip;
+
+ if (aip == NULL)
+ return (NULL);
+
+ newaip = malloc(sizeof(struct addrinfo) + aip->ai_addrlen);
+ if (newaip == NULL)
+ return (NULL);
+
+ *newaip = *aip;
+ newaip->ai_addr = (struct sockaddr *)(newaip + 1);
+ memcpy(newaip->ai_addr, aip->ai_addr, aip->ai_addrlen);
+
+ if (newaip->ai_canonname != NULL)
+ newaip->ai_canonname = decode_name_dynamic(aip->ai_canonname);
+
+ newaip->ai_next = copy_decode_addrinfo_dynamic(aip->ai_next);
+ return (newaip);
+}
+#endif
+
+#ifdef HAVE_FREEADDRINFO
+static void
+free_copied_addrinfo(struct addrinfo *aip) {
+ while (aip != NULL) {
+ struct addrinfo *next = aip->ai_next;
+
+ if (aip->ai_canonname != NULL)
+ free(aip->ai_canonname);
+ free(aip);
+ aip = next;
+ }
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYNAME
+struct hostent *
+ENTRY(gethostbyname)(const char *name) {
+ static hostbuf_t buf;
+ static struct hostent he;
+ idn_result_t r;
+ struct hostent *hp;
+
+ if (idn_isprocessing)
+ return (REAL(gethostbyname)(name));
+
+ TRACE(("gethostbyname(name=%s)\n", idn__debug_xstring(name, 60)));
+
+ idn_isprocessing = 1;
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_encodename(IDN_ENCODE_APP, name, buf.data, sizeof(buf));
+ if (r == idn_success)
+ name = buf.data;
+
+ hp = copy_decode_hostent_static(REAL(gethostbyname)(name),
+ &he, buf.data, sizeof(buf),
+ &h_errno);
+ idn_isprocessing = 0;
+ return (hp);
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYNAME2
+struct hostent *
+ENTRY(gethostbyname2)(const char *name, int af) {
+ static hostbuf_t buf;
+ static struct hostent he;
+ idn_result_t r;
+ struct hostent *hp;
+
+ if (idn_isprocessing)
+ return (REAL(gethostbyname2)(name, af));
+
+ TRACE(("gethostbyname2(name=%s)\n", idn__debug_xstring(name, 60), af));
+
+ idn_isprocessing = 1;
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_encodename(IDN_ENCODE_APP, name, buf.data, sizeof(buf));
+ if (r == idn_success)
+ name = buf.data;
+
+ hp = copy_decode_hostent_static(REAL(gethostbyname2)(name, af),
+ &he, buf.data, sizeof(buf),
+ &h_errno);
+ idn_isprocessing = 0;
+ return (hp);
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYADDR
+struct hostent *
+ENTRY(gethostbyaddr)(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type) {
+ static hostbuf_t buf;
+ static struct hostent he;
+ struct hostent *hp;
+
+ if (idn_isprocessing)
+ return (REAL(gethostbyaddr)(addr, len, type));
+
+ TRACE(("gethostbyaddr()\n"));
+
+ idn_isprocessing = 1;
+ hp = copy_decode_hostent_static(REAL(gethostbyaddr)(addr, len, type),
+ &he, buf.data, sizeof(buf),
+ &h_errno);
+ idn_isprocessing = 0;
+ return (hp);
+}
+#endif
+
+#ifdef GETHOST_R_GLIBC_FLAVOR
+
+#ifdef HAVE_GETHOSTBYNAME_R
+int
+ENTRY(gethostbyname_r)(const char *name, struct hostent *result,
+ char *buffer, size_t buflen,
+ struct hostent **rp, int *errp)
+{
+ char namebuf[IDN_NAME_SIZE];
+ char *data;
+ size_t datalen;
+ idn_result_t r;
+ struct hostent he;
+ hostbuf_t buf;
+ int n;
+
+ if (idn_isprocessing)
+ return (REAL(gethostbyname_r)(name, result, buffer,
+ buflen, rp, errp));
+
+ TRACE(("gethostbyname_r(name=%s,buflen=%d)\n",
+ idn__debug_xstring(name, 60), buflen));
+
+ if (buflen <= sizeof(buf)) {
+ data = buf.data;
+ datalen = sizeof(buf);
+ } else {
+ data = malloc(buflen);
+ datalen = buflen;
+ if (data == NULL) {
+ *errp = NO_RECOVERY;
+ return (ENOMEM);
+ }
+ }
+
+ idn_isprocessing = 1;
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_encodename(IDN_ENCODE_APP, name, namebuf, sizeof(namebuf));
+ if (r == idn_success)
+ name = namebuf;
+
+ *errp = 0;
+ n = REAL(gethostbyname_r)(name, &he, data, datalen, rp, errp);
+
+ if (n == 0 && *rp != NULL)
+ *rp = copy_decode_hostent_static(*rp, result, buffer, buflen,
+ errp);
+ idn_isprocessing = 0;
+
+ if (data != buf.data)
+ free(data);
+
+ if (*errp != 0)
+ n = EINVAL; /* XXX */
+
+ return (n);
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYNAME2_R
+int
+ENTRY(gethostbyname2_r)(const char *name, int af, struct hostent *result,
+ char *buffer, size_t buflen,
+ struct hostent **rp, int *errp)
+{
+ char namebuf[IDN_NAME_SIZE];
+ char *data;
+ size_t datalen;
+ idn_result_t r;
+ struct hostent he;
+ hostbuf_t buf;
+ int n;
+
+ if (idn_isprocessing)
+ return (REAL(gethostbyname2_r)(name, af, result, buffer,
+ buflen, rp, errp));
+
+ TRACE(("gethostbyname2_r(name=%s,buflen=%d)\n",
+ idn__debug_xstring(name, 60), buflen));
+
+ if (buflen <= sizeof(buf)) {
+ data = buf.data;
+ datalen = sizeof(buf);
+ } else {
+ data = malloc(buflen);
+ datalen = buflen;
+ if (data == NULL) {
+ *errp = NO_RECOVERY;
+ return (ENOMEM);
+ }
+ }
+
+ idn_isprocessing = 1;
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_encodename(IDN_ENCODE_APP, name, namebuf, sizeof(namebuf));
+ if (r == idn_success)
+ name = namebuf;
+
+ n = REAL(gethostbyname2_r)(name, af, &he, data, datalen, rp, errp);
+
+ if (n == 0 && *rp != NULL)
+ *rp = copy_decode_hostent_static(*rp, result, buffer, buflen,
+ errp);
+ idn_isprocessing = 0;
+
+ if (data != buf.data)
+ free(data);
+
+ if (*errp != 0)
+ n = EINVAL; /* XXX */
+
+ return (n);
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYADDR_R
+int
+ENTRY(gethostbyaddr_r)(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type,
+ struct hostent *result,
+ char *buffer, size_t buflen,
+ struct hostent **rp, int *errp)
+{
+ char *data;
+ size_t datalen;
+ struct hostent he;
+ hostbuf_t buf;
+ int n;
+
+ if (idn_isprocessing) {
+ return (REAL(gethostbyaddr_r)(addr, len, type, result,
+ buffer, buflen, rp, errp));
+ }
+
+ TRACE(("gethostbyaddr_r(buflen=%d)\n", buflen));
+
+ if (buflen <= sizeof(buf)) {
+ data = buf.data;
+ datalen = sizeof(buf);
+ } else {
+ data = malloc(buflen);
+ datalen = buflen;
+ if (data == NULL) {
+ *errp = NO_RECOVERY;
+ return (ENOMEM);
+ }
+ }
+
+ idn_isprocessing = 1;
+ n = REAL(gethostbyaddr_r)(addr, len, type, &he,
+ data, datalen, rp, errp);
+
+ if (n == 0 && *rp != NULL)
+ *rp = copy_decode_hostent_static(*rp, result, buffer, buflen,
+ errp);
+ idn_isprocessing = 0;
+
+ if (data != buf.data)
+ free(data);
+
+ if (*errp != 0)
+ n = EINVAL; /* XXX */
+
+ return (0);
+}
+#endif
+
+#else /* GETHOST_R_GLIBC_FLAVOR */
+
+#ifdef HAVE_GETHOSTBYNAME_R
+struct hostent *
+ENTRY(gethostbyname_r)(const char *name, struct hostent *result,
+ char *buffer, int buflen, int *errp)
+{
+ char namebuf[IDN_NAME_SIZE];
+ char *data;
+ size_t datalen;
+ idn_result_t r;
+ struct hostent *hp, he;
+ hostbuf_t buf;
+
+ if (idn_isprocessing)
+ return (REAL(gethostbyname_r)(name, result, buffer,
+ buflen, errp));
+
+ TRACE(("gethostbyname_r(name=%s,buflen=%d)\n",
+ idn__debug_xstring(name, 60), buflen));
+
+ if (buflen <= sizeof(buf)) {
+ data = buf.data;
+ datalen = sizeof(buf);
+ } else {
+ data = malloc(buflen);
+ datalen = buflen;
+ if (data == NULL) {
+ *errp = NO_RECOVERY;
+ return (NULL);
+ }
+ }
+
+ idn_isprocessing = 1;
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_encodename(IDN_ENCODE_APP, name, namebuf, sizeof(namebuf));
+ if (r == idn_success)
+ name = namebuf;
+
+ hp = REAL(gethostbyname_r)(name, &he, data, datalen, errp);
+
+ if (hp != NULL)
+ hp = copy_decode_hostent_static(hp, result, buffer, buflen,
+ errp);
+ idn_isprocessing = 0;
+
+ if (data != buf.data)
+ free(data);
+
+ return (hp);
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYADDR_R
+struct hostent *
+ENTRY(gethostbyaddr_r)(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type,
+ struct hostent *result,
+ char *buffer, int buflen, int *errp)
+{
+ char *data;
+ size_t datalen;
+ struct hostent *hp, he;
+ hostbuf_t buf;
+
+ if (idn_isprocessing) {
+ return (REAL(gethostbyaddr_r)(addr, len, type, result,
+ buffer, buflen, errp));
+ }
+
+ TRACE(("gethostbyaddr_r(buflen=%d)\n", buflen));
+
+ if (buflen <= sizeof(buf)) {
+ data = buf.data;
+ datalen = sizeof(buf);
+ } else {
+ data = malloc(buflen);
+ datalen = buflen;
+ if (data == NULL) {
+ *errp = NO_RECOVERY;
+ return (NULL);
+ }
+ }
+
+ idn_isprocessing = 1;
+ hp = REAL(gethostbyaddr_r)(addr, len, type, &he, data, datalen, errp);
+
+ if (hp != NULL)
+ hp = copy_decode_hostent_static(hp, result, buffer, buflen,
+ errp);
+ idn_isprocessing = 0;
+
+ if (data != buf.data)
+ free(data);
+
+ return (hp);
+}
+#endif
+
+#endif /* GETHOST_R_GLIBC_FLAVOR */
+
+#ifdef HAVE_GETIPNODEBYNAME
+struct hostent *
+ENTRY(getipnodebyname)(const char *name, int af, int flags, int *errp) {
+ char namebuf[IDN_NAME_SIZE];
+ idn_result_t r;
+ struct hostent *hp;
+
+ if (idn_isprocessing)
+ return (REAL(getipnodebyname)(name, af, flags, errp));
+
+ TRACE(("getipnodebyname(name=%s)\n", idn__debug_xstring(name, 60), af));
+
+ idn_isprocessing = 1;
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_encodename(IDN_ENCODE_APP, name, namebuf, sizeof(namebuf));
+ if (r == idn_success)
+ name = namebuf;
+
+ hp = REAL(getipnodebyname)(name, af, flags, errp);
+ if (hp != NULL) {
+ struct hostent *newhp = copy_decode_hostent_dynamic(hp, errp);
+ if (newhp != hp) {
+ REAL(freehostent)(hp);
+ obj_lock(newhp);
+ hp = newhp;
+ }
+ }
+ idn_isprocessing = 0;
+ return (hp);
+}
+#endif
+
+#ifdef HAVE_GETIPNODEBYADDR
+struct hostent *
+ENTRY(getipnodebyaddr)(const void *src, size_t len, int af, int *errp) {
+ struct hostent *hp;
+
+ if (idn_isprocessing)
+ return (REAL(getipnodebyaddr)(src, len, af, errp));
+
+ TRACE(("getipnodebyaddr()\n"));
+
+ idn_isprocessing = 1;
+ hp = REAL(getipnodebyaddr)(src, len, af, errp);
+ if (hp != NULL) {
+ struct hostent *newhp = copy_decode_hostent_dynamic(hp, errp);
+ if (newhp != hp) {
+ REAL(freehostent)(hp);
+ obj_lock(newhp);
+ hp = newhp;
+ }
+ }
+ idn_isprocessing = 0;
+ return (hp);
+}
+#endif
+
+#ifdef HAVE_FREEHOSTENT
+void
+ENTRY(freehostent)(struct hostent *hp) {
+ TRACE(("freehostent(hp=%p)\n", (void *)hp));
+
+ if (obj_islocked(hp)) {
+ /*
+ * We allocated the data.
+ */
+ obj_unlock(hp);
+ free_copied_hostent(hp);
+ } else {
+ /*
+ * It was allocated the original getipnodeby*().
+ */
+ REAL(freehostent)(hp);
+ }
+}
+#endif
+
+#ifdef HAVE_GETADDRINFO
+int
+ENTRY(getaddrinfo)(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ char namebuf[IDN_NAME_SIZE];
+ idn_result_t r;
+ struct addrinfo *aip;
+ int err;
+
+ if (nodename == NULL || idn_isprocessing)
+ return (REAL(getaddrinfo)(nodename, servname, hints, res));
+
+ TRACE(("getaddrinfo(nodename=%s)\n", idn__debug_xstring(nodename, 60)));
+
+ idn_isprocessing = 1;
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_encodename(IDN_ENCODE_APP, nodename,
+ namebuf, sizeof(namebuf));
+ if (r == idn_success)
+ nodename = namebuf;
+
+ err = REAL(getaddrinfo)(nodename, servname, hints, &aip);
+ if (err == 0 && aip != NULL) {
+ *res = copy_decode_addrinfo_dynamic(aip);
+ if (*res == NULL)
+ err = EAI_FAIL;
+ else
+ obj_lock(*res);
+ if (aip != NULL)
+ REAL(freeaddrinfo)(aip);
+ }
+ idn_isprocessing = 0;
+ return (err);
+}
+#endif
+
+#ifdef HAVE_FREEADDRINFO
+void
+ENTRY(freeaddrinfo)(struct addrinfo *aip) {
+ TRACE(("freeaddrinfo(aip=%p)\n", (void *)aip));
+
+ if (obj_islocked(aip)) {
+ /*
+ * We allocated the data.
+ */
+ obj_unlock(aip);
+ free_copied_addrinfo(aip);
+ } else {
+ /*
+ * It was allocated the original getaddrinfo().
+ */
+ REAL(freeaddrinfo)(aip);
+ }
+}
+#endif
+
+#ifdef HAVE_GETNAMEINFO
+int
+ENTRY(getnameinfo)(const struct sockaddr *sa, GNI_SALEN_T salen,
+ char *host, GNI_HOSTLEN_T hostlen, char *serv,
+ GNI_SERVLEN_T servlen, GNI_FLAGS_T flags)
+{
+ char name[IDN_NAME_SIZE];
+ size_t namelen = sizeof(name);
+ int code;
+ idn_result_t r;
+
+ if (host == NULL || hostlen == 0 || idn_isprocessing) {
+ return (REAL(getnameinfo)(sa, salen, host, hostlen,
+ serv, servlen, flags));
+ }
+
+ TRACE(("getnameinfo(hostlen=%u)\n", hostlen));
+
+ idn_isprocessing = 1;
+ code = REAL(getnameinfo)(sa, salen, name, namelen,
+ serv, servlen, flags);
+ if (code == 0 && name[0] != '\0') {
+ idn_enable(1);
+ idn_nameinit(1);
+ r = idn_decodename(IDN_DECODE_APP, name, host, hostlen);
+ switch (r) {
+ case idn_success:
+ code = 0;
+ break;
+ case idn_buffer_overflow:
+ case idn_nomemory:
+ code = EAI_MEMORY;
+ break;
+ default:
+ code = EAI_FAIL;
+ break;
+ }
+ }
+ idn_isprocessing = 0;
+ return (code);
+}
+#endif
diff --git a/contrib/idn/idnkit-1.0-src/tools/runidn/resolver.h b/contrib/idn/idnkit-1.0-src/tools/runidn/resolver.h
new file mode 100644
index 0000000..e3fc35e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/runidn/resolver.h
@@ -0,0 +1,70 @@
+/* $Id: resolver.h,v 1.1.1.1 2003/06/04 00:27:13 marka Exp $ */
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef RESOLVER_H
+#define RESOLVER_H 1
+
+#undef gethostbyname
+#define gethostbyname idn_resolver_gethostbyname
+#undef gethostbyname2
+#define gethostbyname2 idn_resolver_gethostbyname2
+#undef gethostbyname_r
+#define gethostbyname_r idn_resolver_gethostbyname_r
+#undef gethostbyaddr
+#define gethostbyaddr idn_resolver_gethostbyaddr
+#undef gethostbyaddr
+#define gethostbyaddr_r idn_resolver_gethostbyaddr_r
+#undef getipnodebyname
+#define getipnodebyname idn_resolver_getipnodebyname
+#undef getipnodebyaddr
+#define getipnodebyaddr idn_resolver_getipnodebyaddr
+#undef freehostent
+#define freehostent idn_resolver_freehostent
+#undef getaddrinfo
+#define getaddrinfo idn_resolver_getaddrinfo
+#undef freeaddrinfo
+#define freeaddrinfo idn_resolver_freeaddrinfo
+#undef getnameinfo
+#define getnameinfo idn_resolver_getnameinfo
+
+#endif /* RESOLVER_H */
diff --git a/contrib/idn/idnkit-1.0-src/tools/runidn/runidn.1 b/contrib/idn/idnkit-1.0-src/tools/runidn/runidn.1
new file mode 100644
index 0000000..a8b1270
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/runidn/runidn.1
@@ -0,0 +1,151 @@
+.\" $Id: runidn.1,v 1.1.1.1 2003/06/04 00:27:14 marka Exp $
+.\"
+.\" Copyright (c) 2000,2001 Japan Network Information Center.
+.\" All rights reserved.
+.\"
+.\" By using this file, you agree to the terms and conditions set forth bellow.
+.\"
+.\" LICENSE TERMS AND CONDITIONS
+.\"
+.\" The following License Terms and Conditions apply, unless a different
+.\" license is obtained from Japan Network Information Center ("JPNIC"),
+.\" a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+.\" Chiyoda-ku, Tokyo 101-0047, Japan.
+.\"
+.\" 1. Use, Modification and Redistribution (including distribution of any
+.\" modified or derived work) in source and/or binary forms is permitted
+.\" under this License Terms and Conditions.
+.\"
+.\" 2. Redistribution of source code must retain the copyright notices as they
+.\" appear in each source code file, this License Terms and Conditions.
+.\"
+.\" 3. Redistribution in binary form must reproduce the Copyright Notice,
+.\" this License Terms and Conditions, in the documentation and/or other
+.\" materials provided with the distribution. For the purposes of binary
+.\" distribution the "Copyright Notice" refers to the following language:
+.\" "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+.\"
+.\" 4. The name of JPNIC may not be used to endorse or promote products
+.\" derived from this Software without specific prior written approval of
+.\" JPNIC.
+.\"
+.\" 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+.\" PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+.\"
+.TH RUNIDN 1 "April 6, 2001"
+.\"
+.SH NAME
+runidn \- A script to allow applications to use internationalized domain names.
+.\"
+.SH SYNOPSIS
+\fBrunidn\fP [\fB-e\fP \fIlocal-codeset\fP] \fIprogram-name\fP [\fIargs..\fP]
+.\"
+.SH DESCRIPTION
+\fBrunidn\fP enables applications to use internationalized domain names
+without recompilation.
+Just add ``runidn'' before the application-name, and the application
+can handle non-ASCII domain names. For example, you can do:
+.PP
+.RS 4
+.nf
+\f(CW% runidn telnet \fInon-ASCII-hostname\fR
+.fi
+.RE
+.PP
+Before using runidn, you should set up properties related to
+internationalized DNS by configuring idnkit's configuration file
+\fBidn.conf\fP.
+See idn.conf(5) which describes the configuration.
+.\"
+.SH OPTION
+The following option is available:
+.TP 4
+\fB\-e\fP \fIlocal-codeset\fP
+Specify the application's local codeset.
+If the option is not specified, \fBrunidn\fR guesses the codeset
+from the current locale.
+See the ``NOTE'' section for more details about local codeset.
+.\"
+.SH IMPLEMENTATION
+\fBrunidn\fR is a small shell script that sets up an environment variable
+called ``LD_PRELOAD'', so that an application dynamically links a shared
+library ``libidnkitres'' before any other shared libraries.
+.PP
+The library ``libidnkitres'' provides a special version of resolver
+functions which implement features for handling internationalized
+domain names.
+\fBrunidn\fR replaces the following functions with the special version:
+.PP
+.RS 4
+.nf
+.ft CW
+gethostbyname
+gethostbyname2
+gethostbyaddr
+gethostbyname_r
+gethostbyname2_r
+gethostbyaddr_r
+getipnodebyname
+getipnodebyaddr
+freehostent
+getaddrinfo
+freeaddrinfo
+getnameinfo
+.ft R
+.fi
+.RE
+.PP
+By overriding them in the standard libraries with the special version
+provided by ``libidnkitres'',
+\fBrunidn\fR enables applications to use internationalized domain names.
+.RS 4
+.IP \(bu 2
+These API functions accept non-ASCII domain names encoded
+in the local codeset that the application is using.
+Also the result from these APIs may contain non-ASCII domain names.
+.IP \(bu 2
+The normalization and codeset conversion between application's local
+codeset and the codeset used in DNS protocol data are handled
+automatically, so users/applications need not worry about them.
+.RE
+.PP
+Properties of internationalized DNS (such as the normalization or
+the codeset used on DNS protocol data) can be configured with the
+idnkit's configuration file (\fBidn.conf\fR).
+See idn.conf(5) for details.
+.\"
+.SH NOTE
+Unless \fB\-e\fP option is specified, \fBrunidn\fR tries to guess
+the application's local codeset from the application's current locale.
+However, sometimes it cannot guess the codeset correctly, for example
+if the application does not set the locale appropriately by calling
+`setlocale()'.
+In that case, you can explicitly specify the local codeset by setting an
+environment variable ``IDN_LOCAL_CODESET''.
+See the section ``LOCAL CODESET'' in idn.conf(5) for details.
+.PP
+The idea of using ``LD_PRELOAD'' to replace some functions in the standard
+library was taken from ``runsocks'' script distributed as part of SOCKS5
+reference implementation.
+.SH BUGS
+There are many cases where \fBrunidn\fR does not work.
+.PP
+Your system must support ``LD_PRELOAD'' mechanism in the first place.
+.PP
+Due to security reasons, ``LD_PRELOAD'' mechanism is disabled for
+setuid programs in any sane systems.
+So \fBrunidn\fR does not work for setuid programs such as ping or rsh.
+.PP
+If your application uses a function other than the ones runidn supports for
+name resolution, you lose.
+.SH "SEE ALSO"
+idn.conf(5), runsocks(1)
diff --git a/contrib/idn/idnkit-1.0-src/tools/runidn/runidn.in b/contrib/idn/idnkit-1.0-src/tools/runidn/runidn.in
new file mode 100644
index 0000000..6437658
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/runidn/runidn.in
@@ -0,0 +1,109 @@
+#! /bin/sh
+# $Id: runidn.in,v 1.1.1.1 2003/06/04 00:27:14 marka Exp $
+#
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+# Parse command line options.
+usage="Usage: `basename $0` [-e local-encoding] command [argument..]"
+while test $# -gt 0; do
+ case "$1" in
+ -e)
+ if test $# -le 1; then
+ echo $usage 1>&2
+ exit 1
+ fi
+ IDN_LOCAL_CODESET="$2"
+ export IDN_LOCAL_CODESET
+ shift
+ ;;
+ -)
+ break
+ ;;
+ -*)
+ echo $usage 1>&2
+ exit 1
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+if test $# -eq 0; then
+ echo $usage 1>&2
+ exit 1
+fi
+
+# Load library info.
+preload=
+iconv_file=@ICONVSOFILE@
+if test "$iconv_file" != none; then
+ preload="$iconv_file@PRELOAD_SEP@"
+fi
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=`echo @libdir@`
+if test ! -f $libdir/libidnkitres.la; then
+ cat <<EOF 1>&2
+Have you installed idnkit? I cannot find libidnkitres.la.
+EOF
+ exit 1
+fi
+eval `grep '^dlname' $libdir/libidnkitres.la`
+if test "$dlname" = ""; then
+ cat <<EOF 1>&2
+Sorry, runidn won't work because libidnkitres is not dynamically loadable.
+EOF
+ exit 1
+fi
+preload=$preload$libdir/$dlname
+
+# Set @PRELOAD_VAR@.
+if [ X$@PRELOAD_VAR@ = X ]; then
+ @PRELOAD_VAR@="$preload@PRELOAD_LAST@"
+else
+ @PRELOAD_VAR@="$preload@PRELOAD_SEP@$@PRELOAD_VAR@@PRELOAD_LAST@"
+fi
+export @PRELOAD_VAR@
+
+# Shoot.
+exec "$@"
diff --git a/contrib/idn/idnkit-1.0-src/tools/runidn/stub.c b/contrib/idn/idnkit-1.0-src/tools/runidn/stub.c
new file mode 100644
index 0000000..0ec1685
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/runidn/stub.c
@@ -0,0 +1,387 @@
+#ifndef lint
+static char *rcsid = "$Id: stub.c,v 1.1.1.1 2003/06/04 00:27:13 marka Exp $";
+#endif
+
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <config.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <errno.h>
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <idn/logmacro.h>
+#include <idn/debug.h>
+
+#include "stub.h"
+
+#ifndef RTLD_NEXT
+typedef struct {
+ const char *name;
+ void *handle;
+} shared_obj_t;
+
+static shared_obj_t shobj[] = {
+#ifdef SOPATH_LIBC
+ { SOPATH_LIBC },
+#endif
+#ifdef SOPATH_LIBNSL
+ { SOPATH_LIBNSL },
+#endif
+ { NULL },
+};
+#endif
+
+static void *shared_obj_findsym(void *handle, const char *name);
+static void *shared_obj_findsymx(void *handle, const char *name);
+static void *get_func_addr(const char *name);
+
+#ifndef RTLD_NEXT
+static void *
+shared_obj_open(const char *path) {
+#ifdef HAVE_DLOPEN
+ return (dlopen(path, RTLD_LAZY));
+#endif
+ FATAL(("stub: no way to load shared object file\n"));
+ return (NULL);
+}
+#endif
+
+static void *
+shared_obj_findsym(void *handle, const char *name) {
+ char namebuf[100];
+ void *addr;
+ static int need_leading_underscore = -1;
+
+ /* Prepend underscore. */
+ namebuf[0] = '_';
+ (void)strcpy(namebuf + 1, name);
+ name = namebuf;
+
+ if (need_leading_underscore < 0) {
+ /* First try without one. */
+ if ((addr = shared_obj_findsymx(handle, name + 1)) != NULL) {
+ need_leading_underscore = 0;
+ return (addr);
+ }
+ /* Then try with one. */
+ if ((addr = shared_obj_findsymx(handle, name)) != NULL) {
+ need_leading_underscore = 1;
+ return (addr);
+ }
+ } else if (need_leading_underscore) {
+ return (shared_obj_findsymx(handle, name));
+ } else {
+ return (shared_obj_findsymx(handle, name + 1));
+ }
+ return (NULL);
+}
+
+static void *
+shared_obj_findsymx(void *handle, const char *name) {
+#ifdef HAVE_DLSYM
+ return (dlsym(handle, name));
+#endif
+ /* logging */
+ FATAL(("stub: no way to get symbol address\n"));
+ return (NULL);
+}
+
+static void *
+get_func_addr(const char *name) {
+#ifdef RTLD_NEXT
+ void *addr = shared_obj_findsym(RTLD_NEXT, name);
+
+ if (addr != NULL) {
+ TRACE(("stub: %s found in the subsequent objects\n", name));
+ return (addr);
+ }
+#else
+ int i;
+
+ for (i = 0; shobj[i].name != NULL; i++) {
+ if (shobj[i].handle == NULL) {
+ TRACE(("stub: loading %s\n", shobj[i].name));
+ shobj[i].handle = shared_obj_open(shobj[i].name);
+ }
+ if (shobj[i].handle != NULL) {
+ void *addr = shared_obj_findsym(shobj[i].handle, name);
+ if (addr != NULL) {
+ TRACE(("stub: %s found in %s\n",
+ name, shobj[i].name));
+ return (addr);
+ }
+ }
+ }
+#endif
+ TRACE(("stub: %s not found\n", name));
+ return (NULL);
+}
+
+#ifdef HAVE_GETHOSTBYNAME
+struct hostent *
+idn_stub_gethostbyname(const char *name) {
+ static struct hostent *(*fp)(const char *name);
+
+ if (fp == NULL)
+ fp = get_func_addr("gethostbyname");
+ if (fp != NULL)
+ return ((*fp)(name));
+ return (NULL);
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYNAME2
+struct hostent *
+idn_stub_gethostbyname2(const char *name, int af) {
+ static struct hostent *(*fp)(const char *name, int af);
+
+ if (fp == NULL)
+ fp = get_func_addr("gethostbyname2");
+ if (fp != NULL)
+ return ((*fp)(name, af));
+ return (NULL);
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYADDR
+struct hostent *
+idn_stub_gethostbyaddr(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type) {
+ static struct hostent *(*fp)(GHBA_ADDR_T name,
+ GHBA_ADDRLEN_T len, int type);
+
+ if (fp == NULL)
+ fp = get_func_addr("gethostbyaddr");
+ if (fp != NULL)
+ return ((*fp)(addr, len, type));
+ return (NULL);
+}
+#endif
+
+#ifdef GETHOST_R_GLIBC_FLAVOR
+
+#ifdef HAVE_GETHOSTBYNAME_R
+int
+idn_stub_gethostbyname_r(const char *name, struct hostent *result,
+ char *buffer, size_t buflen,
+ struct hostent **rp, int *errp)
+{
+ static int (*fp)(const char *name, struct hostent *result,
+ char *buffer, size_t buflen,
+ struct hostent **rp, int *errp);
+
+ if (fp == NULL)
+ fp = get_func_addr("gethostbyname_r");
+ if (fp != NULL)
+ return ((*fp)(name, result, buffer, buflen, rp, errp));
+ return (ENOENT); /* ??? */
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYNAME2_R
+int
+idn_stub_gethostbyname2_r(const char *name, int af, struct hostent *result,
+ char *buffer, size_t buflen,
+ struct hostent **rp, int *errp)
+{
+ static int (*fp)(const char *name, int af, struct hostent *result,
+ char *buffer, size_t buflen,
+ struct hostent **rp, int *errp);
+
+ if (fp == NULL)
+ fp = get_func_addr("gethostbyname2_r");
+ if (fp != NULL)
+ return ((*fp)(name, af, result, buffer, buflen, rp, errp));
+ return (ENOENT); /* ??? */
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYADDR_R
+int
+idn_stub_gethostbyaddr_r(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type,
+ struct hostent *result, char *buffer,
+ size_t buflen, struct hostent **rp, int *errp)
+{
+ static int (*fp)(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type,
+ struct hostent *result, char *buffer,
+ size_t buflen, struct hostent **rp, int *errp);
+
+ if (fp == NULL)
+ fp = get_func_addr("gethostbyaddr_r");
+ if (fp != NULL)
+ return ((*fp)(addr, len, type, result,
+ buffer, buflen, rp, errp));
+ return (ENOENT); /* ??? */
+}
+#endif
+
+#else /* GETHOST_R_GLIBC_FLAVOR */
+
+#ifdef HAVE_GETHOSTBYNAME_R
+struct hostent *
+idn_stub_gethostbyname_r(const char *name, struct hostent *result,
+ char *buffer, int buflen, int *errp)
+{
+ static struct hostent *(*fp)(const char *name, struct hostent *result,
+ char *buffer, int buflen, int *errp);
+
+ if (fp == NULL)
+ fp = get_func_addr("gethostbyname_r");
+ if (fp != NULL)
+ return ((*fp)(name, result, buffer, buflen, errp));
+ return (NULL);
+}
+#endif
+
+#ifdef HAVE_GETHOSTBYADDR_R
+struct hostent *
+idn_stub_gethostbyaddr_r(GHBA_ADDR_T addr, int len, int type,
+ struct hostent *result, char *buffer,
+ int buflen, int *errp)
+{
+ static struct hostent *(*fp)(GHBA_ADDR_T addr, int len, int type,
+ struct hostent *result, char *buffer,
+ int buflen, int *errp);
+
+ if (fp == NULL)
+ fp = get_func_addr("gethostbyaddr_r");
+ if (fp != NULL)
+ return ((*fp)(addr, len, type, result, buffer, buflen, errp));
+ return (NULL);
+}
+#endif
+
+#endif /* GETHOST_R_GLIBC_FLAVOR */
+
+#ifdef HAVE_GETIPNODEBYNAME
+struct hostent *
+idn_stub_getipnodebyname(const char *name, int af, int flags, int *errp) {
+ static struct hostent *(*fp)(const char *name, int af, int flags,
+ int *errp);
+
+ if (fp == NULL)
+ fp = get_func_addr("getipnodebyname");
+ if (fp != NULL)
+ return ((*fp)(name, af, flags, errp));
+ return (NULL);
+}
+#endif
+
+#ifdef HAVE_GETIPNODEBYADDR
+struct hostent *
+idn_stub_getipnodebyaddr(const void *src, size_t len, int af, int *errp) {
+ static struct hostent *(*fp)(const void *src, size_t len, int af,
+ int *errp);
+
+ if (fp == NULL)
+ fp = get_func_addr("getipnodebyaddr");
+ if (fp != NULL)
+ return ((*fp)(src, len, af, errp));
+ return (NULL);
+}
+#endif
+
+#ifdef HAVE_FREEHOSTENT
+void
+idn_stub_freehostent(struct hostent *hp) {
+ static void (*fp)(struct hostent *hp);
+
+ if (fp == NULL)
+ fp = get_func_addr("freehostent");
+ if (fp != NULL)
+ (*fp)(hp);
+}
+#endif
+
+#ifdef HAVE_GETADDRINFO
+int
+idn_stub_getaddrinfo(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ static int (*fp)(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res);
+
+ if (fp == NULL)
+ fp = get_func_addr("getaddrinfo");
+ if (fp != NULL)
+ return ((*fp)(nodename, servname, hints, res));
+ return (EAI_FAIL);
+}
+#endif
+
+#ifdef HAVE_FREEADDRINFO
+void
+idn_stub_freeaddrinfo(struct addrinfo *aip) {
+ static void (*fp)(struct addrinfo *aip);
+
+ if (fp == NULL)
+ fp = get_func_addr("freeaddrinfo");
+ if (fp != NULL)
+ (*fp)(aip);
+}
+#endif
+
+#ifdef HAVE_GETNAMEINFO
+int
+idn_stub_getnameinfo(const struct sockaddr *sa, GNI_SALEN_T salen,
+ char *host, GNI_HOSTLEN_T hostlen,
+ char *serv, GNI_SERVLEN_T servlen, GNI_FLAGS_T flags) {
+ static int (*fp)(const struct sockaddr *sa, GNI_SALEN_T salen,
+ char *host, GNI_HOSTLEN_T hostlen,
+ char *serv, GNI_SERVLEN_T servlen,
+ GNI_FLAGS_T flags);
+
+ if (fp == NULL)
+ fp = get_func_addr("getnameinfo");
+ if (fp != NULL)
+ return ((*fp)(sa, salen, host, hostlen, serv, servlen, flags));
+ return (EAI_FAIL);
+}
+#endif
diff --git a/contrib/idn/idnkit-1.0-src/tools/runidn/stub.h b/contrib/idn/idnkit-1.0-src/tools/runidn/stub.h
new file mode 100644
index 0000000..48167ed
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/tools/runidn/stub.h
@@ -0,0 +1,94 @@
+/* $Id: stub.h,v 1.1.1.1 2003/06/04 00:27:13 marka Exp $ */
+
+#ifndef STUB_H
+#define STUB_H
+
+#ifdef HAVE_GETHOSTBYNAME
+extern struct hostent *
+idn_stub_gethostbyname(const char *name);
+#endif
+
+#ifdef GETHOST_R_GLIBC_FLAVOR
+#ifdef HAVE_GETHOSTBYNAME_R
+extern int
+idn_stub_gethostbyname_r(const char *name, struct hostent *result,
+ char *buffer, size_t buflen,
+ struct hostent **rp, int *errp);
+#endif
+#else /* GETHOST_R_GLIBC_FLAVOR */
+#ifdef HAVE_GETHOSTBYNAME_R
+extern struct hostent *
+idn_stub_gethostbyname_r(const char *name, struct hostent *result,
+ char *buffer, int buflen, int *errp);
+#endif
+#endif /* GETHOST_R_GLIBC_FLAVOR */
+
+#ifdef HAVE_GETHOSTBYNAME2
+extern struct hostent *
+idn_stub_gethostbyname2(const char *name, int af);
+#endif
+
+#ifdef GETHOST_R_GLIBC_FLAVOR
+#ifdef HAVE_GETHOSTBYNAME2_R
+extern int
+idn_stub_gethostbyname2_r(const char *name, int af, struct hostent *result,
+ char *buffer, size_t buflen,
+ struct hostent **rp, int *errp);
+#endif
+#endif /* GETHOST_R_GLIBC_FLAVOR */
+
+#ifdef HAVE_GETHOSTBYADDR
+extern struct hostent *
+idn_stub_gethostbyaddr(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type);
+#endif
+
+#ifdef GETHOST_R_GLIBC_FLAVOR
+#ifdef HAVE_GETHOSTBYADDR_R
+extern int
+idn_stub_gethostbyaddr_r(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type,
+ struct hostent *result, char *buffer,
+ size_t buflen, struct hostent **rp, int *errp);
+#endif
+#else /* GETHOST_R_GLIBC_FLAVOR */
+#ifdef HAVE_GETHOSTBYADDR_R
+extern struct hostent *
+idn_stub_gethostbyaddr_r(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type,
+ struct hostent *result, char *buffer,
+ int buflen, int *errp);
+#endif
+#endif /* GETHOST_R_GLIBC_FLAVOR */
+
+#ifdef HAVE_GETIPNODEBYNAME
+extern struct hostent *
+idn_stub_getipnodebyname(const char *name, int af, int flags, int *errp);
+#endif
+
+#ifdef HAVE_GETIPNODEBYADDR
+extern struct hostent *
+idn_stub_getipnodebyaddr(const void *src, size_t len, int af, int *errp);
+#endif
+
+#ifdef HAVE_FREEHOSTENT
+extern void
+idn_stub_freehostent(struct hostent *hp);
+#endif
+
+#ifdef HAVE_GETADDRINFO
+extern int
+idn_stub_getaddrinfo(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res);
+#endif
+
+#ifdef HAVE_FREEADDRINFO
+extern void
+idn_stub_freeaddrinfo(struct addrinfo *aip);
+#endif
+
+#ifdef HAVE_GETNAMEINFO
+extern int
+idn_stub_getnameinfo(const struct sockaddr *sa, GNI_SALEN_T salen,
+ char *host, GNI_HOSTLEN_T hostlen, char *serv,
+ GNI_SERVLEN_T servlen, GNI_FLAGS_T flags);
+#endif
+
+#endif /* STUB_H */
diff --git a/contrib/idn/idnkit-1.0-src/util/Makefile b/contrib/idn/idnkit-1.0-src/util/Makefile
new file mode 100644
index 0000000..2f49ddd
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/util/Makefile
@@ -0,0 +1,43 @@
+# $Id: Makefile,v 1.1.1.1 2003/06/04 00:27:52 marka Exp $
+
+PERL = /usr/local/bin/perl -w
+
+V301_NORM_DIR = data/unicode-3.0.0
+V310_NORM_DIR = data/unicode-3.1.0
+V320_NORM_DIR = data/unicode-3.2.0
+NORM_GENERATOR = ./generate_normalize_data.pl
+
+NAMEPREP_DIR = data/nameprep
+NAMEPREP_FILES = \
+ $(NAMEPREP_DIR)/nameprep.rfc3491.map \
+ $(NAMEPREP_DIR)/nameprep.rfc3491.prohibited \
+ $(NAMEPREP_DIR)/nameprep.rfc3491.unassigned \
+ $(NAMEPREP_DIR)/nameprep.rfc3491.bidi
+NAMEPREP_GENERATOR = ./generate_nameprep_data.pl
+NAMEPREP_VERSIONS = rfc3491
+
+all: normalize nameprep
+
+normalize: ../lib/unicodedata_320.c
+
+nameprep: ../lib/nameprepdata.c
+
+../lib/unicodedata_301.c: $(NORM_GENERATOR)
+ -rm -f $@.tmp
+ $(PERL) $(NORM_GENERATOR) -prefix v301_ -dir $(V301_NORM_DIR) \
+ > $@.tmp && mv $@.tmp $@
+
+../lib/unicodedata_310.c: $(NORM_GENERATOR)
+ -rm -f $@.tmp
+ $(PERL) $(NORM_GENERATOR) -prefix v310_ -dir $(V310_NORM_DIR) \
+ > $@.tmp && mv $@.tmp $@
+
+../lib/unicodedata_320.c: $(NORM_GENERATOR)
+ -rm -f $@.tmp
+ $(PERL) $(NORM_GENERATOR) -prefix v320_ -dir $(V320_NORM_DIR) \
+ > $@.tmp && mv $@.tmp $@
+
+../lib/nameprepdata.c: $(NAMEPREP_GENERATOR) $(NAMEPREP_FILES)
+ -rm -f $@.tmp
+ $(PERL) $(NAMEPREP_GENERATOR) -dir $(NAMEPREP_DIR) \
+ $(NAMEPREP_VERSIONS) > $@.tmp && mv $@.tmp $@
diff --git a/contrib/idn/idnkit-1.0-src/util/SparseMap.pm b/contrib/idn/idnkit-1.0-src/util/SparseMap.pm
new file mode 100644
index 0000000..834c795
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/util/SparseMap.pm
@@ -0,0 +1,575 @@
+# $Id: SparseMap.pm,v 1.1.1.1 2003/06/04 00:27:53 marka Exp $
+#
+# Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+
+package SparseMap;
+
+use strict;
+use Carp;
+
+my $debug = 0;
+
+sub new {
+ # common options are:
+ # BITS => [8, 7, 6], # 3-level map, 2nd level bits=7, 3rd = 6.
+ # MAX => 0x110000 # actually, max + 1.
+ my $class = shift;
+ my $self = {@_};
+
+ croak "BITS unspecified" unless exists $self->{BITS};
+ croak "BITS is not an array reference"
+ unless ref($self->{BITS}) eq 'ARRAY';
+ croak "MAX unspecified" unless exists $self->{MAX};
+
+ $self->{MAXLV} = @{$self->{BITS}} - 1;
+ $self->{FIXED} = 0;
+
+ my $lv0size = (indices($self, $self->{MAX} - 1))[0] + 1;
+
+ my @map = (undef) x $lv0size;
+ $self->{MAP} = \@map;
+
+ bless $self, $class;
+}
+
+sub add1 {
+ my ($self, $n, $val) = @_;
+
+ croak "Already fixed" if $self->{FIXED};
+ carp("data ($n) out of range"), return if $n >= $self->{MAX};
+
+ my @index = $self->indices($n);
+ my $r = $self->{MAP};
+ my $maxlv = $self->{MAXLV};
+ my $idx;
+ my $lv;
+
+ for ($lv = 0; $lv < $maxlv - 1; $lv++) {
+ $idx = $index[$lv];
+ $r->[$idx] = $self->create_imap($lv + 1, undef)
+ unless defined $r->[$idx];
+ $r = $r->[$idx];
+ }
+ $idx = $index[$lv];
+ $r->[$idx] = $self->create_dmap() unless defined $r->[$idx];
+ $self->add_to_dmap($r->[$idx], $index[$maxlv], $val);
+}
+
+sub fix {
+ my $self = shift;
+ my $map = $self->{MAP};
+ my $maxlv = $self->{MAXLV};
+ my @tmp;
+ my @zero;
+
+ carp "Already fixed" if $self->{FIXED};
+ $self->collapse_tree();
+ $self->fill_default();
+ $self->{FIXED} = 1;
+}
+
+sub indices {
+ my $self = shift;
+ my $v = shift;
+ my @bits = @{$self->{BITS}};
+ my @idx;
+
+ print "indices($v,", join(',', @bits), ") = " if $debug;
+ for (my $i = @bits - 1; $i >= 0; $i--) {
+ my $bit = $bits[$i];
+ unshift @idx, $v & ((1 << $bit) - 1);
+ $v = $v >> $bit;
+ }
+ print "(", join(',', @idx), ")\n" if $debug;
+ @idx;
+}
+
+sub get {
+ my $self = shift;
+ my $v = shift;
+ my $map = $self->{MAP};
+ my @index = $self->indices($v);
+
+ croak "Not yet fixed" unless $self->{FIXED};
+
+ my $lastidx = pop @index;
+ foreach my $idx (@index) {
+ return $map->{DEFAULT} unless defined $map->[$idx];
+ $map = $map->[$idx];
+ }
+ $map->[$lastidx];
+}
+
+sub indirectmap {
+ my $self = shift;
+
+ croak "Not yet fixed" unless $self->{FIXED};
+
+ my @maps = $self->collect_maps();
+ my $maxlv = $self->{MAXLV};
+ my @bits = @{$self->{BITS}};
+
+ my @indirect = ();
+ for (my $lv = 0; $lv < $maxlv; $lv++) {
+ my $offset;
+ my $chunksz;
+ my $mapsz = @{$maps[$lv]->[0]};
+ if ($lv < $maxlv - 1) {
+ # indirect map
+ $offset = @indirect + @{$maps[$lv]} * @{$maps[$lv]->[0]};
+ $chunksz = (1 << $bits[$lv + 1]);
+ } else {
+ # direct map
+ $offset = 0;
+ $chunksz = 1;
+ }
+ my $nextmaps = $maps[$lv + 1];
+ foreach my $mapref (@{$maps[$lv]}) {
+ croak "mapsize inconsistent ", scalar(@$mapref),
+ " should be ", $mapsz, " (lv $lv)\n" if @$mapref != $mapsz;
+ foreach my $m (@$mapref) {
+ my $idx;
+ for ($idx = 0; $idx < @$nextmaps; $idx++) {
+ last if $nextmaps->[$idx] == $m;
+ }
+ croak "internal error: map corrupted" if $idx >= @$nextmaps;
+ push @indirect, $offset + $chunksz * $idx;
+ }
+ }
+ }
+ @indirect;
+}
+
+sub cprog_imap {
+ my $self = shift;
+ my %opt = @_;
+ my $name = $opt{NAME} || 'map';
+ my @indirect = $self->indirectmap();
+ my $prog;
+ my $i;
+ my ($idtype, $idcol, $idwid);
+
+ my $max = 0;
+ $max < $_ and $max = $_ foreach @indirect;
+
+ if ($max < 256) {
+ $idtype = 'char';
+ $idcol = 8;
+ $idwid = 3;
+ } elsif ($max < 65536) {
+ $idtype = 'short';
+ $idcol = 8;
+ $idwid = 5;
+ } else {
+ $idtype = 'long';
+ $idcol = 4;
+ $idwid = 10;
+ }
+ $prog = "static const unsigned $idtype ${name}_imap[] = {\n";
+ $i = 0;
+ foreach my $v (@indirect) {
+ if ($i % $idcol == 0) {
+ $prog .= "\n" if $i != 0;
+ $prog .= "\t";
+ }
+ $prog .= sprintf "%${idwid}d, ", $v;
+ $i++;
+ }
+ $prog .= "\n};\n";
+ $prog;
+}
+
+sub cprog {
+ my $self = shift;
+ $self->cprog_imap(@_) . "\n" . $self->cprog_dmap(@_);
+}
+
+sub stat {
+ my $self = shift;
+ my @maps = $self->collect_maps();
+ my $elsize = $self->{ELSIZE};
+ my $i;
+ my $total = 0;
+ my @lines;
+
+ for ($i = 0; $i < $self->{MAXLV}; $i++) {
+ my $nmaps = @{$maps[$i]};
+ my $mapsz = @{$maps[$i]->[0]};
+ push @lines, "level $i: $nmaps maps (size $mapsz) ";
+ push @lines, "[", $nmaps * $mapsz * $elsize, "]" if $elsize;
+ push @lines, "\n";
+ }
+ my $ndmaps = @{$maps[$i]};
+ push @lines, "level $i: $ndmaps dmaps";
+ my $r = $maps[$i]->[0];
+ if (ref($r) eq 'ARRAY') {
+ push @lines, " (size ", scalar(@$r), ")";
+ }
+ push @lines, "\n";
+ join '', @lines;
+}
+
+sub collapse_tree {
+ my $self = shift;
+ my @tmp;
+
+ $self->_collapse_tree_rec($self->{MAP}, 0, \@tmp);
+}
+
+sub _collapse_tree_rec {
+ my ($self, $r, $lv, $refs) = @_;
+ my $ref = $refs->[$lv];
+ my $maxlv = $self->{MAXLV};
+ my $found;
+
+ return $r unless defined $r;
+
+ $ref = $refs->[$lv] = [] unless defined $ref;
+
+ if ($lv == $maxlv) {
+ $found = $self->find_dmap($ref, $r);
+ } else {
+ for (my $i = 0; $i < @$r; $i++) {
+ $r->[$i] = $self->_collapse_tree_rec($r->[$i], $lv + 1, $refs);
+ }
+ $found = $self->find_imap($ref, $r);
+ }
+ unless ($found) {
+ $found = $r;
+ push @$ref, $found;
+ }
+ return $found;
+}
+
+sub fill_default {
+ my $self = shift;
+ my $maxlv = $self->{MAXLV};
+ my $bits = $self->{BITS};
+ my @zeros;
+
+ $zeros[$maxlv] = $self->create_dmap();
+ for (my $lv = $maxlv - 1; $lv >= 0; $lv--) {
+ my $r = $zeros[$lv + 1];
+ $zeros[$lv] = $self->create_imap($lv, $r);
+ }
+ _fill_default_rec($self->{MAP}, 0, $maxlv, \@zeros);
+}
+
+sub _fill_default_rec {
+ my ($r, $lv, $maxlv, $zeros) = @_;
+
+ return if $lv == $maxlv;
+ for (my $i = 0; $i < @$r; $i++) {
+ if (defined($r->[$i])) {
+ _fill_default_rec($r->[$i], $lv + 1, $maxlv, $zeros);
+ } else {
+ $r->[$i] = $zeros->[$lv + 1];
+ }
+ }
+}
+
+sub create_imap {
+ my ($self, $lv, $v) = @_;
+ my @map;
+ @map = ($v) x (1 << $self->{BITS}->[$lv]);
+ \@map;
+}
+
+sub find_imap {
+ my ($self, $maps, $map) = @_;
+ my $i;
+
+ foreach my $el (@$maps) {
+ next unless @$el == @$map;
+ for ($i = 0; $i < @$el; $i++) {
+ last unless ($el->[$i] || 0) == ($map->[$i] || 0);
+ }
+ return $el if $i >= @$el;
+ }
+ undef;
+}
+
+sub collect_maps {
+ my $self = shift;
+ my @maps;
+ _collect_maps_rec($self->{MAP}, 0, $self->{MAXLV}, \@maps);
+ @maps;
+}
+
+sub _collect_maps_rec {
+ my ($r, $lv, $maxlv, $maps) = @_;
+ my $mapref = $maps->[$lv];
+
+ return unless defined $r;
+ foreach my $ref (@{$mapref}) {
+ return if $ref == $r;
+ }
+ push @{$maps->[$lv]}, $r;
+ if ($lv < $maxlv) {
+ _collect_maps_rec($_, $lv + 1, $maxlv, $maps) foreach @{$r};
+ }
+}
+
+sub add {confess "Subclass responsibility";}
+sub create_dmap {confess "Subclass responsibility";}
+sub add_to_dmap {confess "Subclass responsibility";}
+sub find_dmap {confess "Subclass responsibility";}
+sub cprog_dmap {confess "Subclass responsibility";}
+
+1;
+
+package SparseMap::Bit;
+
+use strict;
+use vars qw(@ISA);
+use Carp;
+#use SparseMap;
+
+@ISA = qw(SparseMap);
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ $self->{DEFAULT} = 0;
+ bless $self, $class;
+}
+
+sub add {
+ my $self = shift;
+
+ $self->add1($_, undef) foreach @_;
+}
+
+sub create_dmap {
+ my $self = shift;
+ my $bmbits = $self->{BITS}->[-1];
+
+ my $s = "\0" x (1 << ($bmbits - 3));
+ \$s;
+}
+
+sub add_to_dmap {
+ my ($self, $map, $idx, $val) = @_;
+ vec($$map, $idx, 1) = 1;
+}
+
+sub find_dmap {
+ my ($self, $ref, $r) = @_;
+ foreach my $map (@$ref) {
+ return $map if $$map eq $$r;
+ }
+ return undef;
+}
+
+sub cprog_dmap {
+ my $self = shift;
+ my %opt = @_;
+ my $name = $opt{NAME} || 'map';
+ my @maps = $self->collect_maps();
+ my @bitmap = @{$maps[-1]};
+ my $prog;
+ my $bmsize = 1 << ($self->{BITS}->[-1] - 3);
+
+ $prog = <<"END";
+static const struct {
+ unsigned char bm[$bmsize];
+} ${name}_bitmap[] = {
+END
+
+ foreach my $bm (@bitmap) {
+ my $i = 0;
+ $prog .= "\t{{\n";
+ foreach my $v (unpack 'C*', $$bm) {
+ if ($i % 16 == 0) {
+ $prog .= "\n" if $i != 0;
+ $prog .= "\t";
+ }
+ $prog .= sprintf "%3d,", $v;
+ $i++;
+ }
+ $prog .= "\n\t}},\n";
+ }
+ $prog .= "};\n";
+ $prog;
+}
+
+1;
+
+package SparseMap::Int;
+
+use strict;
+use vars qw(@ISA);
+use Carp;
+#use SparseMap;
+
+@ISA = qw(SparseMap);
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ $self->{DEFAULT} = 0 unless exists $self->{DEFAULT};
+ bless $self, $class;
+}
+
+sub add {
+ my $self = shift;
+ while (@_ > 0) {
+ my $n = shift;
+ my $val = shift;
+ $self->add1($n, $val);
+ }
+}
+
+sub create_dmap {
+ my $self = shift;
+ my $tblbits = $self->{BITS}->[-1];
+ my $default = $self->{DEFAULT};
+
+ my @tbl = ($default) x (1 << $tblbits);
+ \@tbl;
+}
+
+sub add_to_dmap {
+ my ($self, $map, $idx, $val) = @_;
+ $map->[$idx] = $val;
+}
+
+sub find_dmap {
+ my ($self, $ref, $r) = @_;
+ foreach my $map (@$ref) {
+ if (@$map == @$r) {
+ my $i;
+ for ($i = 0; $i < @$map; $i++) {
+ last if $map->[$i] != $r->[$i];
+ }
+ return $map if $i == @$map;
+ }
+ }
+ return undef;
+}
+
+sub cprog_dmap {
+ my $self = shift;
+ my %opt = @_;
+ my $name = $opt{NAME} || 'map';
+ my @maps = $self->collect_maps();
+ my @table = @{$maps[-1]};
+ my $prog;
+ my $i;
+ my ($idtype, $idcol, $idwid);
+ my $tblsize = 1 << $self->{BITS}->[-1];
+
+ my ($min, $max);
+ foreach my $a (@table) {
+ foreach my $v (@$a) {
+ $min = $v if !defined($min) or $min > $v;
+ $max = $v if !defined($max) or $max < $v;
+ }
+ }
+ if (exists $opt{MAPTYPE}) {
+ $idtype = $opt{MAPTYPE};
+ } else {
+ my $u = $min < 0 ? '' : 'unsigned ';
+ my $absmax = abs($max);
+ $absmax = abs($min) if abs($min) > $absmax;
+
+ if ($absmax < 256) {
+ $idtype = "${u}char";
+ } elsif ($absmax < 65536) {
+ $idtype = "${u}short";
+ } else {
+ $idtype = "${u}long";
+ }
+ }
+
+ $idwid = decimalwidth($max);
+ $idwid = decimalwidth($min) if decimalwidth($min) > $idwid;
+
+ $prog = <<"END";
+static const struct {
+ $idtype tbl[$tblsize];
+} ${name}_table[] = {
+END
+
+ foreach my $a (@table) {
+ my $i = 0;
+ my $col = 0;
+ $prog .= "\t{{\n\t";
+ foreach my $v (@$a) {
+ my $s = sprintf "%${idwid}d, ", $v;
+ $col += length($s);
+ if ($col > 70) {
+ $prog .= "\n\t";
+ $col = length($s);
+ }
+ $prog .= $s;
+ }
+ $prog .= "\n\t}},\n";
+ }
+ $prog .= "};\n";
+ $prog;
+}
+
+sub decimalwidth {
+ my $n = shift;
+ my $neg = 0;
+ my $w;
+
+ if ($n < 0) {
+ $neg = 1;
+ $n = -$n;
+ }
+ if ($n < 100) {
+ $w = 2;
+ } elsif ($n < 10000) {
+ $w = 4;
+ } elsif ($n < 1000000) {
+ $w = 6;
+ } elsif ($n < 100000000) {
+ $w = 8;
+ } else {
+ $w = 10;
+ }
+ $w + $neg;
+}
+
+1;
diff --git a/contrib/idn/idnkit-1.0-src/util/UCD.pm b/contrib/idn/idnkit-1.0-src/util/UCD.pm
new file mode 100644
index 0000000..19629e6
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/util/UCD.pm
@@ -0,0 +1,194 @@
+# $Id: UCD.pm,v 1.1.1.1 2003/06/04 00:27:53 marka Exp $
+#
+# Copyright (c) 2000,2001 Japan Network Information Center.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+
+package UCD;
+
+#
+# UCD.pm -- parser for Unicode Character Database files.
+#
+# This file is an aggregation of the following modules, each of which
+# provides a parser for a specific data file of UCD.
+# UCD::UnicodeData -- for UnicodeData.txt
+# UCD::CaseFolding -- for CaseFolding.txt
+# UCD::SpecialCasing -- for SpecialCasing.txt
+# UCD::CompositionExclusions -- for CompositionExclusions-1.txt
+#
+# Each module provides two subroutines:
+#
+# $line = getline(\*HANDLE);
+# reads next non-comment line from HANDLE, and returns it.
+# undef will be returned upon EOF.
+#
+# %fields = parse($line);
+# parses a line and extract fields, and returns a list of
+# field name and its value, suitable for assignment to a hash.
+#
+
+package UCD::UnicodeData;
+
+use strict;
+use Carp;
+
+sub getline {
+ my $fh = shift;
+ my $s = <$fh>;
+ $s =~ s/\r?\n$// if $s;
+ $s;
+}
+
+sub parseline {
+ my $s = shift;
+
+ my @f = split /;/, $s, -1;
+ return (CODE => hex($f[0]),
+ NAME => $f[1],
+ CATEGORY => $f[2],
+ CLASS => $f[3]+0,
+ BIDI => $f[4],
+ DECOMP => dcmap($f[5]),
+ DECIMAL => dvalue($f[6]),
+ DIGIT => dvalue($f[7]),
+ NUMERIC => dvalue($f[8]),
+ MIRRORED => $f[9] eq 'Y',
+ NAME10 => $f[10],
+ COMMENT => $f[11],
+ UPPER => ucode($f[12]),
+ LOWER => ucode($f[13]),
+ TITLE => ucode($f[14]));
+}
+
+sub dcmap {
+ my $v = shift;
+ return undef if $v eq '';
+ $v =~ /^(?:(<[^>]+>)\s*)?(\S.*)/
+ or croak "invalid decomposition mapping \"$v\"";
+ my $tag = $1 || '';
+ [$tag, map {hex($_)} split(' ', $2)];
+}
+
+sub ucode {
+ my $v = shift;
+ return undef if $v eq '';
+ hex($v);
+}
+
+sub dvalue {
+ my $v = shift;
+ return undef if $v eq '';
+ $v;
+}
+
+package UCD::CaseFolding;
+
+use strict;
+
+sub getline {
+ my $fh = shift;
+ while (defined(my $s = <$fh>)) {
+ next if $s =~ /^\#/;
+ next if $s =~ /^\s*$/;
+ $s =~ s/\r?\n$//;
+ return $s;
+ }
+ undef;
+}
+
+sub parseline {
+ my $s = shift;
+ my @f = split /;\s*/, $s, -1;
+ return (CODE => hex($f[0]),
+ TYPE => $f[1],
+ MAP => [map(hex, split ' ', $f[2])],
+ );
+}
+
+package UCD::SpecialCasing;
+
+use strict;
+
+sub getline {
+ my $fh = shift;
+ while (defined(my $s = <$fh>)) {
+ next if $s =~ /^\#/;
+ next if $s =~ /^\s*$/;
+ $s =~ s/\r?\n$//;
+ return $s;
+ }
+ undef;
+}
+
+sub parseline {
+ my $s = shift;
+
+ my @f = split /;\s*/, $s, -1;
+ my $cond = (@f > 5) ? $f[4] : undef;
+ return (CODE => hex($f[0]),
+ LOWER => [map(hex, split ' ', $f[1])],
+ TITLE => [map(hex, split ' ', $f[2])],
+ UPPER => [map(hex, split ' ', $f[3])],
+ CONDITION => $cond);
+}
+
+package UCD::CompositionExclusions;
+
+use strict;
+
+sub getline {
+ my $fh = shift;
+ while (defined(my $s = <$fh>)) {
+ next if $s =~ /^\#/;
+ next if $s =~ /^\s*$/;
+ $s =~ s/\r?\n$//;
+ return $s;
+ }
+ undef;
+}
+
+sub parseline {
+ my $s = shift;
+ m/^[0-9A-Fa-f]+/;
+ return (CODE => hex($&));
+}
+
+1;
diff --git a/contrib/idn/idnkit-1.0-src/util/generate_nameprep_data.pl b/contrib/idn/idnkit-1.0-src/util/generate_nameprep_data.pl
new file mode 100755
index 0000000..31dd18b
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/util/generate_nameprep_data.pl
@@ -0,0 +1,405 @@
+#! /usr/local/bin/perl -w
+# $Id: generate_nameprep_data.pl,v 1.1.1.1 2003/06/04 00:27:54 marka Exp $
+#
+# Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+
+use v5.6.0; # for pack('U')
+use bytes;
+
+use lib qw(.);
+
+use SparseMap;
+use Getopt::Long;
+
+(my $myid = '$Id: generate_nameprep_data.pl,v 1.1.1.1 2003/06/04 00:27:54 marka Exp $') =~ s/\$([^\$]+)\$/\$-$1-\$/;
+
+my @map_bits = (9, 7, 5);
+my @proh_bits = (7, 7, 7);
+my @unas_bits = (7, 7, 7);
+my @bidi_bits = (9, 7, 5);
+
+my @bidi_types = ('OTHERS', 'R_AL', 'L');
+
+my $dir = '.';
+my @versions = ();
+
+GetOptions('dir=s', \$dir) or die usage();
+@versions = @ARGV;
+
+print_header();
+
+bits_definition("MAP", @map_bits);
+bits_definition("PROH", @proh_bits);
+bits_definition("UNAS", @unas_bits);
+bits_definition("BIDI", @bidi_bits);
+
+generate_data($_) foreach @ARGV;
+
+sub usage {
+ die "Usage: $0 [-dir dir] version..\n";
+}
+
+sub generate_data {
+ my $version = shift;
+ generate_mapdata($version, "$dir/nameprep.$version.map");
+ generate_prohibiteddata($version, "$dir/nameprep.$version.prohibited");
+ generate_unassigneddata($version, "$dir/nameprep.$version.unassigned");
+ generate_bididata($version, "$dir/nameprep.$version.bidi");
+}
+
+#
+# Generate mapping data.
+#
+sub generate_mapdata {
+ my $version = shift;
+ my $file = shift;
+
+ my $map = SparseMap::Int->new(BITS => [@map_bits],
+ MAX => 0x110000,
+ MAPALL => 1,
+ DEFAULT => 0);
+ open FILE, $file or die "cannot open $file: $!\n";
+
+ my $mapbuf = "\0"; # dummy
+ my %maphash = ();
+ while (<FILE>) {
+ if ($. == 1 and /^%\s*SAME-AS\s+(\S+)/) {
+ my $same_as = $1;
+ if (grep {$_ eq $same_as} @versions > 0) {
+ generate_map_ref($version, $same_as);
+ close FILE;
+ return;
+ }
+ next;
+ }
+ next if /^\#/;
+ next if /^\s*$/;
+ register_map($map, \$mapbuf, \%maphash, $_);
+ }
+ close FILE;
+ generate_map($version, $map, \$mapbuf);
+}
+
+#
+# Generate prohibited character data.
+#
+sub generate_prohibiteddata {
+ my $version = shift;
+ my $file = shift;
+
+ my $proh = SparseMap::Bit->new(BITS => [@proh_bits],
+ MAX => 0x110000);
+ open FILE, $file or die "cannot open $file: $!\n";
+ while (<FILE>) {
+ if ($. == 1 and /^%\s*SAME-AS\s+(\S+)/) {
+ my $same_as = $1;
+ if (grep {$_ eq $same_as} @versions > 0) {
+ generate_prohibited_ref($version, $same_as);
+ close FILE;
+ return;
+ }
+ next;
+ }
+ next if /^\#/;
+ next if /^\s*$/;
+ register_prohibited($proh, $_);
+ }
+ close FILE;
+ generate_prohibited($version, $proh);
+}
+
+#
+# Generate unassigned codepoint data.
+#
+sub generate_unassigneddata {
+ my $version = shift;
+ my $file = shift;
+
+ my $unas = SparseMap::Bit->new(BITS => [@unas_bits],
+ MAX => 0x110000);
+ open FILE, $file or die "cannot open $file: $!\n";
+ while (<FILE>) {
+ if ($. == 1 and /^%\s*SAME-AS\s+(\S+)/) {
+ my $same_as = $1;
+ if (grep {$_ eq $same_as} @versions > 0) {
+ generate_unassigned_ref($version, $same_as);
+ close FILE;
+ return;
+ }
+ next;
+ }
+ next if /^\#/;
+ next if /^\s*$/;
+ register_unassigned($unas, $_);
+ }
+ close FILE;
+ generate_unassigned($version, $unas);
+}
+
+#
+# Generate data of bidi "R" or "AL" characters.
+#
+sub generate_bididata {
+ my $version = shift;
+ my $file = shift;
+
+ my $bidi = SparseMap::Int->new(BITS => [@bidi_bits],
+ MAX => 0x110000);
+ open FILE, $file or die "cannot open $file: $!\n";
+
+ my $type = 0;
+ while (<FILE>) {
+ if ($. == 1 and /^%\s*SAME-AS\s+(\S+)/) {
+ my $same_as = $1;
+ if (grep {$_ eq $same_as} @versions > 0) {
+ generate_unassigned_ref($version, $same_as);
+ close FILE;
+ return;
+ }
+ next;
+ }
+ if (/^%\s*BIDI_TYPE\s+(\S+)$/) {
+ my $i = 0;
+ for ($i = 0; $i < @bidi_types; $i++) {
+ if ($1 eq $bidi_types[$i]) {
+ $type = $i;
+ last;
+ }
+ }
+ die "unrecognized line: $_" if ($i >= @bidi_types);
+ next;
+ }
+ next if /^\#/;
+ next if /^\s*$/;
+ register_bidi($bidi, $type, $_);
+ }
+ close FILE;
+
+ generate_bidi($version, $bidi);
+}
+
+sub print_header {
+ print <<"END";
+/* \$Id\$ */
+/* $myid */
+/*
+ * Do not edit this file!
+ * This file is generated from NAMEPREP specification.
+ */
+
+END
+}
+
+sub bits_definition {
+ my $name = shift;
+ my @bits = @_;
+ my $i = 0;
+
+ foreach my $n (@bits) {
+ print "#define ${name}_BITS_$i\t$n\n";
+ $i++;
+ }
+ print "\n";
+}
+
+sub register_map {
+ my ($map, $bufref, $hashref, $line) = @_;
+
+ my ($from, $to) = split /;/, $line;
+ my @fcode = map {hex($_)} split ' ', $from;
+ my @tcode = map {hex($_)} split ' ', $to;
+
+ my $ucs4 = pack('V*', @tcode);
+ $ucs4 =~ s/\000+$//;
+
+ my $offset;
+ if (exists $hashref->{$ucs4}) {
+ $offset = $hashref->{$ucs4};
+ } else {
+ $offset = length $$bufref;
+ $$bufref .= pack('C', length($ucs4)) . $ucs4;
+ $hashref->{$ucs4} = $offset;
+ }
+
+ die "unrecognized line: $line" if @fcode != 1;
+ $map->add($fcode[0], $offset);
+}
+
+sub generate_map {
+ my ($version, $map, $bufref) = @_;
+
+ $map->fix();
+
+ print $map->cprog(NAME => "nameprep_${version}_map");
+ print "\nstatic const unsigned char nameprep_${version}_map_data[] = \{\n";
+ print_uchararray($$bufref);
+ print "};\n\n";
+}
+
+sub generate_map_ref {
+ my ($version, $refversion) = @_;
+ print <<"END";
+#define nameprep_${version}_map_imap nameprep_${refversion}_map_imap
+#define nameprep_${version}_map_table nameprep_${refversion}_map_table
+#define nameprep_${version}_map_data nameprep_${refversion}_map_data
+
+END
+}
+
+sub print_uchararray {
+ my @chars = unpack 'C*', $_[0];
+ my $i = 0;
+ foreach my $v (@chars) {
+ if ($i % 12 == 0) {
+ print "\n" if $i != 0;
+ print "\t";
+ }
+ printf "%3d, ", $v;
+ $i++;
+ }
+ print "\n";
+}
+
+sub register_prohibited {
+ my $proh = shift;
+ register_bitmap($proh, @_);
+}
+
+sub register_unassigned {
+ my $unas = shift;
+ register_bitmap($unas, @_);
+}
+
+sub register_bidi {
+ my $bidi = shift;
+ my $type = shift;
+ register_intmap($bidi, $type, @_);
+}
+
+sub generate_prohibited {
+ my ($version, $proh) = @_;
+ generate_bitmap($proh, "nameprep_${version}_prohibited");
+ print "\n";
+}
+
+sub generate_prohibited_ref {
+ my ($version, $refversion) = @_;
+ print <<"END";
+#define nameprep_${version}_prohibited_imap nameprep_${refversion}_prohibited_imap
+#define nameprep_${version}_prohibited_bitmap nameprep_${refversion}_prohibited_bitmap
+
+END
+}
+
+sub generate_unassigned {
+ my ($version, $unas) = @_;
+ generate_bitmap($unas, "nameprep_${version}_unassigned");
+ print "\n";
+}
+
+sub generate_unassigned_ref {
+ my ($version, $refversion) = @_;
+ print <<"END";
+#define nameprep_${version}_unassigned_imap nameprep_${refversion}_unassigned_imap
+#define nameprep_${version}_unassigned_bitmap nameprep_${refversion}_unassigned_bitmap
+
+END
+}
+
+sub generate_bidi {
+ my ($version, $bidi) = @_;
+
+ $bidi->fix();
+
+ print $bidi->cprog(NAME => "nameprep_${version}_bidi");
+ print "\n";
+ print "static const unsigned char nameprep_${version}_bidi_data[] = \{\n";
+
+ foreach my $type (@bidi_types) {
+ printf "\tidn_biditype_%s, \n", lc($type);
+ }
+ print "};\n\n";
+}
+
+sub generate_bidi_ref {
+ my ($version, $refversion) = @_;
+ print <<"END";
+#define nameprep_${version}_bidi_imap nameprep_${refversion}_bidi_imap
+#define nameprep_${version}_bidi_table nameprep_${refversion}_bidi_table
+
+END
+}
+
+sub register_bitmap {
+ my $map = shift;
+ my $line = shift;
+
+ /^([0-9A-Fa-f]+)(?:-([0-9A-Fa-f]+))?/ or die "unrecognized line: $line";
+ my $start = hex($1);
+ my $end = defined($2) ? hex($2) : undef;
+ if (defined $end) {
+ $map->add($start .. $end);
+ } else {
+ $map->add($start);
+ }
+}
+
+sub register_intmap {
+ my $map = shift;
+ my $value = shift;
+ my $line = shift;
+
+ /^([0-9A-Fa-f]+)(?:-([0-9A-Fa-f]+))?/ or die "unrecognized line: $line";
+ my $start = hex($1);
+ my $end = defined($2) ? hex($2) : $start;
+ for (my $i = $start; $i <= $end; $i++) {
+ $map->add($i, $value);
+ }
+}
+
+sub generate_bitmap {
+ my $map = shift;
+ my $name = shift;
+ $map->fix();
+ #$map->stat();
+ print $map->cprog(NAME => $name);
+}
diff --git a/contrib/idn/idnkit-1.0-src/util/generate_normalize_data.pl b/contrib/idn/idnkit-1.0-src/util/generate_normalize_data.pl
new file mode 100755
index 0000000..fe81648
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/util/generate_normalize_data.pl
@@ -0,0 +1,586 @@
+#! /usr/local/bin/perl -w
+# $Id: generate_normalize_data.pl,v 1.1.1.1 2003/06/04 00:27:55 marka Exp $
+#
+# Copyright (c) 2000,2001 Japan Network Information Center.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#
+
+#
+# Generate lib/unicodedata.c from UnicodeData.txt,
+# CompositionExclusions-1.txt, SpecialCasing.txt and CaseFolding.txt,
+# all of them available from ftp://ftp.unicode.org/Public/UNIDATA/.
+#
+
+use strict;
+use lib qw(.);
+
+use Getopt::Long;
+use UCD;
+use SparseMap;
+
+use constant UCS_MAX => 0x110000;
+use constant END_BIT => 0x80000000;
+
+my $DECOMP_COMPAT_BIT = 0x8000;
+
+my $CASEMAP_FINAL_BIT = 0x1;
+my $CASEMAP_NONFINAL_BIT = 0x2;
+my $CASEMAP_LAST_BIT = 0x10;
+
+my $LETTER_BIT = 1;
+my $NSPMARK_BIT = 2;
+
+(my $myid = '$Id: generate_normalize_data.pl,v 1.1.1.1 2003/06/04 00:27:55 marka Exp $') =~ s/\$([^\$]+)\$/\$-$1-\$/;
+
+my @default_bits = (9, 7, 5);
+#my @default_bits = (7, 7, 7);
+my @canon_class_bits = @default_bits;
+my @decomp_bits = @default_bits;
+my @comp_bits = @default_bits;
+my @folding_bits = @default_bits;
+my @casemap_bits = @default_bits;
+my @casemap_ctx_bits = @default_bits;
+
+my $prefix = '';
+my $dir = '.';
+my $unicodedatafile = 'UnicodeData.txt';
+my $exclusionfile = 'CompositionExclusions.txt';
+my $specialcasefile = 'SpecialCasing.txt';
+my $casefoldingfile = 'CaseFolding.txt';
+my $verbose;
+
+GetOptions('dir|d=s' => \$dir,
+ 'unicodedata|u=s' => \$unicodedatafile,
+ 'exclude|e=s' => \$exclusionfile,
+ 'specialcase|s=s' => \$specialcasefile,
+ 'casefold|c=s' => \$casefoldingfile,
+ 'prefix|p=s' => \$prefix,
+ 'verbose|v' => \$verbose,
+) or usage();
+
+foreach my $r (\$unicodedatafile, \$exclusionfile,
+ \$specialcasefile, \$casefoldingfile) {
+ $$r = "$dir/$$r" unless $$r =~ m|^/|;
+}
+
+my %exclusions;
+my %lower_special;
+my %upper_special;
+
+my @decomp_data;
+my @comp_data;
+my @toupper_data;
+my @tolower_data;
+my @folding_data;
+
+#
+# Create Mapping/Bitmap objects.
+#
+
+# canonical class
+my $canon_class = SparseMap::Int->new(BITS => [@canon_class_bits],
+ MAX => UCS_MAX,
+ MAPALL => 1,
+ DEFAULT => 0);
+
+# canonical/compatibility decomposition
+my $decomp = SparseMap::Int->new(BITS => [@decomp_bits],
+ MAX => UCS_MAX,
+ MAPALL => 1,
+ DEFAULT => 0);
+
+# canonical composition
+my $comp = SparseMap::Int->new(BITS => [@comp_bits],
+ MAX => UCS_MAX,
+ MAPALL => 1,
+ DEFAULT => 0);
+
+# uppercase/lowercase
+my $upper = SparseMap::Int->new(BITS => [@casemap_bits],
+ MAX => UCS_MAX,
+ MAPALL => 1,
+ DEFAULT => 0);
+my $lower = SparseMap::Int->new(BITS => [@casemap_bits],
+ MAX => UCS_MAX,
+ MAPALL => 1,
+ DEFAULT => 0);
+
+# final/nonfinal context
+my $casemap_ctx = SparseMap::Int->new(BITS => [@casemap_ctx_bits],
+ MAX => UCS_MAX,
+ MAPALL => 1,
+ DEFAULT => 0);
+
+# casefolding
+my $folding = SparseMap::Int->new(BITS => [@folding_bits],
+ MAX => UCS_MAX,
+ MAPALL => 1,
+ DEFAULT => 0);
+
+#
+# Read datafiles.
+#
+
+read_exclusion_file();
+read_specialcasing_file();
+read_unicodedata_file();
+read_casefolding_file();
+
+print_header();
+print_canon_class();
+print_composition();
+print_decomposition();
+print_casemap();
+print_casemap_context();
+print_casefolding();
+
+exit;
+
+sub usage {
+ print STDERR <<"END";
+Usage: $0 [options..]
+ options:
+ -d DIR directory where Unicode Character Data files resides [./]
+ -u FILE name of the UnicodeData file [UnicodeData.txt]
+ -e FILE name of the CompositionExclusion file [CompositionExclusions-1.txt]
+ -s FILE name of the SpecialCasing file [SpecialCasing.txt]
+ -c FILE name of the CaseFolding file [CaseFolding.txt]
+END
+ exit 1;
+}
+
+#
+# read_exclusion_file -- read CompositionExclusions-1.txt.
+#
+sub read_exclusion_file {
+ open EXCLUDE, $exclusionfile or die "cannot open $exclusionfile: $!\n";
+ while ($_ = UCD::CompositionExclusions::getline(\*EXCLUDE)) {
+ my %data = UCD::CompositionExclusions::parseline($_);
+ $exclusions{$data{CODE}} = 1;
+ }
+ close EXCLUDE;
+}
+
+#
+# read_specialcasing_file -- read SpecialCasing.txt
+#
+sub read_specialcasing_file {
+ open SPCASE, $specialcasefile or die "cannot open $specialcasefile: $!\n";
+ while ($_ = UCD::SpecialCasing::getline(\*SPCASE)) {
+ my %data = UCD::SpecialCasing::parseline($_);
+ my $code = $data{CODE};
+ my $lower = $data{LOWER};
+ my $upper = $data{UPPER};
+ my $cond = $data{CONDITION} || '';
+
+ next unless $cond eq '' or $cond =~ /^(NON_)?FINAL/;
+
+ if (defined $cond && (@$lower > 1 || $lower->[0] != $code)
+ or @$lower > 1 or $lower->[0] != $code) {
+ $lower_special{$code} = [$lower, $cond];
+ }
+ if (defined $cond && (@$upper > 1 || $upper->[0] != $code)
+ or @$upper > 1 or $upper->[0] != $code) {
+ $upper_special{$code} = [$upper, $cond];
+ }
+ }
+ close SPCASE;
+}
+
+#
+# read_unicodedata_file -- read UnicodeData.txt
+#
+sub read_unicodedata_file {
+ open UCD, $unicodedatafile or die "cannot open $unicodedatafile: $!\n";
+
+ @decomp_data = (0);
+ @toupper_data = (0);
+ @tolower_data = (0);
+
+ my @comp_cand; # canonical composition candidates
+ my %nonstarter;
+
+ while ($_ = UCD::UnicodeData::getline(\*UCD)) {
+ my %data = UCD::UnicodeData::parseline($_);
+ my $code = $data{CODE};
+
+ # combining class
+ if ($data{CLASS} > 0) {
+ $nonstarter{$code} = 1;
+ $canon_class->add($code, $data{CLASS});
+ }
+
+ # uppercasing
+ if (exists $upper_special{$code} or defined $data{UPPER}) {
+ my $offset = @toupper_data;
+ my @casedata;
+
+ $upper->add($code, $offset);
+ if (exists $upper_special{$code}) {
+ push @casedata, $upper_special{$code};
+ }
+ if (defined $data{UPPER}) {
+ push @casedata, $data{UPPER};
+ }
+ push @toupper_data, casemap_data(@casedata);
+ }
+
+ # lowercasing
+ if (exists $lower_special{$code} or defined $data{LOWER}) {
+ my $offset = @tolower_data;
+ my @casedata;
+
+ $lower->add($code, $offset);
+ if (exists $lower_special{$code}) {
+ push @casedata, $lower_special{$code};
+ }
+ if (defined $data{LOWER}) {
+ push @casedata, $data{LOWER};
+ }
+ push @tolower_data, casemap_data(@casedata);
+ }
+
+ # composition/decomposition
+ if ($data{DECOMP}) {
+ my ($tag, @decomp) = @{$data{DECOMP}};
+ my $offset = @decomp_data;
+
+ # composition
+ if ($tag eq '' and @decomp > 1 and not exists $exclusions{$code}) {
+ # canonical composition candidate
+ push @comp_cand, [$code, @decomp];
+ }
+
+ # decomposition
+ if ($tag ne '') {
+ # compatibility decomposition
+ $offset |= $DECOMP_COMPAT_BIT;
+ }
+ $decomp->add($code, $offset);
+ push @decomp_data, @decomp;
+ $decomp_data[-1] |= END_BIT;
+
+ }
+
+ # final/nonfinal context
+ if ($data{CATEGORY} =~ /L[ult]/) {
+ $casemap_ctx->add($code, $LETTER_BIT);
+ } elsif ($data{CATEGORY} eq 'Mn') {
+ $casemap_ctx->add($code, $NSPMARK_BIT);
+ }
+ }
+ close UCD;
+
+ # Eliminate composition candidates whose decomposition starts with
+ # a non-starter.
+ @comp_cand = grep {not exists $nonstarter{$_->[1]}} @comp_cand;
+
+ @comp_data = ([0, 0, 0]);
+ my $last_code = -1;
+ my $last_offset = @comp_data;
+ for my $r (sort {$a->[1] <=> $b->[1] || $a->[2] <=> $b->[2]} @comp_cand) {
+ if ($r->[1] != $last_code) {
+ $comp->add($last_code,
+ ($last_offset | ((@comp_data - $last_offset)<<16)))
+ unless $last_code == -1;
+ $last_code = $r->[1];
+ $last_offset = @comp_data;
+ }
+ push @comp_data, $r;
+ }
+ $comp->add($last_code,
+ ($last_offset | ((@comp_data - $last_offset)<<16)));
+}
+
+sub casemap_data {
+ my @data = @_;
+ my @result = ();
+ while (@data > 0) {
+ my $r = shift @data;
+ my $flag = 0;
+ if (ref $r) {
+ if ($r->[1] eq 'FINAL') {
+ $flag |= $CASEMAP_FINAL_BIT;
+ } elsif ($r->[1] eq 'NON_FINAL') {
+ $flag |= $CASEMAP_NONFINAL_BIT;
+ } elsif ($r->[1] ne '') {
+ die "unknown condition \"", $r->[1], "\"\n";
+ }
+ }
+ $flag |= $CASEMAP_LAST_BIT if @data == 0;
+ push @result, $flag;
+ push @result, (ref $r) ? @{$r->[0]} : $r;
+ $result[-1] |= END_BIT;
+ }
+ @result;
+}
+
+#
+# read_casefolding_file -- read CaseFolding.txt
+#
+sub read_casefolding_file {
+ open FOLD, $casefoldingfile or die "cannto open $casefoldingfile: $!\n";
+
+ # dummy.
+ @folding_data = (0);
+
+ while ($_ = UCD::CaseFolding::getline(\*FOLD)) {
+ my %data = UCD::CaseFolding::parseline($_);
+
+ $folding->add($data{CODE}, scalar(@folding_data));
+ push @folding_data, @{$data{MAP}};
+ $folding_data[-1] |= END_BIT;
+ }
+ close FOLD;
+}
+
+sub print_header {
+ print <<"END";
+/* \$Id\$ */
+/* $myid */
+/*
+ * Do not edit this file!
+ * This file is generated from UnicodeData.txt, CompositionExclusions-1.txt,
+ * SpecialCasing.txt and CaseFolding.txt.
+ */
+
+END
+}
+
+#
+# print_canon_class -- generate data for canonical class
+#
+sub print_canon_class {
+ $canon_class->fix();
+ print STDERR "** cannon_class\n", $canon_class->stat() if $verbose;
+
+ print <<"END";
+
+/*
+ * Canonical Class
+ */
+
+END
+ print_bits("CANON_CLASS", @canon_class_bits);
+ print "\n";
+ print $canon_class->cprog(NAME => "${prefix}canon_class");
+}
+
+#
+# print_composition -- generate data for canonical composition
+#
+sub print_composition {
+ $comp->fix();
+ print STDERR "** composition\n", $comp->stat() if $verbose;
+
+ print <<"END";
+
+/*
+ * Canonical Composition
+ */
+
+END
+ print_bits("CANON_COMPOSE", @comp_bits);
+ print "\n";
+ print $comp->cprog(NAME => "${prefix}compose");
+ print <<"END";
+
+static const struct composition ${prefix}compose_seq[] = {
+END
+ my $i = 0;
+ foreach my $r (@comp_data) {
+ if ($i % 2 == 0) {
+ print "\n" if $i != 0;
+ print "\t";
+ }
+ printf "{ 0x%08x, 0x%08x }, ", $r->[2], $r->[0];
+ $i++;
+ }
+ print "\n};\n\n";
+}
+
+#
+# print_decomposition -- generate data for canonical/compatibility
+# decomposition
+#
+sub print_decomposition {
+ $decomp->fix();
+ print STDERR "** decomposition\n", $decomp->stat() if $verbose;
+
+ print <<"END";
+
+/*
+ * Canonical/Compatibility Decomposition
+ */
+
+END
+ print_bits("DECOMP", @decomp_bits);
+ print "#define DECOMP_COMPAT\t$DECOMP_COMPAT_BIT\n\n";
+
+ print $decomp->cprog(NAME => "${prefix}decompose");
+
+ print "static const unsigned long ${prefix}decompose_seq[] = {\n";
+ print_ulseq(@decomp_data);
+ print "};\n\n";
+}
+
+#
+# print_casemap -- generate data for case mapping
+#
+sub print_casemap {
+ $upper->fix();
+ $lower->fix();
+ print STDERR "** upper mapping\n", $upper->stat() if $verbose;
+ print STDERR "** lower mapping\n", $lower->stat() if $verbose;
+
+ print <<"END";
+
+/*
+ * Lowercase <-> Uppercase mapping
+ */
+
+/*
+ * Flags for special case mapping.
+ */
+#define CMF_FINAL $CASEMAP_FINAL_BIT
+#define CMF_NONFINAL $CASEMAP_NONFINAL_BIT
+#define CMF_LAST $CASEMAP_LAST_BIT
+#define CMF_CTXDEP (CMF_FINAL|CMF_NONFINAL)
+
+END
+ print_bits("CASEMAP", @casemap_bits);
+ print "\n";
+ print $upper->cprog(NAME => "${prefix}toupper");
+ print $lower->cprog(NAME => "${prefix}tolower");
+
+ print "static const unsigned long ${prefix}toupper_seq[] = {\n";
+ print_ulseq(@toupper_data);
+ print "};\n\n";
+
+ print "static const unsigned long ${prefix}tolower_seq[] = {\n";
+ print_ulseq(@tolower_data);
+ print "};\n\n";
+}
+
+#
+# print_casefolding -- generate data for case folding
+#
+sub print_casefolding {
+ $folding->fix();
+ print STDERR "** case folding\n", $folding->stat() if $verbose;
+
+ print <<"END";
+
+/*
+ * Case Folding
+ */
+
+END
+ print_bits("CASE_FOLDING", @folding_bits);
+ print "\n";
+ print $folding->cprog(NAME => "${prefix}case_folding");
+
+ print "static const unsigned long ${prefix}case_folding_seq[] = {\n";
+ print_ulseq(@folding_data);
+ print "};\n\n";
+}
+
+#
+# print_casemap_context -- gerarate data for determining context
+# (final/non-final)
+#
+sub print_casemap_context {
+ $casemap_ctx->fix();
+ print STDERR "** casemap context\n", $casemap_ctx->stat() if $verbose;
+
+ print <<"END";
+
+/*
+ * Cased characters and non-spacing marks (for casemap context)
+ */
+
+END
+
+ print_bits("CASEMAP_CTX", @casemap_ctx_bits);
+ print <<"END";
+
+#define CTX_CASED $LETTER_BIT
+#define CTX_NSM $NSPMARK_BIT
+
+END
+ print $casemap_ctx->cprog(NAME => "${prefix}casemap_ctx");
+}
+
+sub sprint_composition_hash {
+ my $i = 0;
+ my $s = '';
+ foreach my $r (@_) {
+ if ($i % 2 == 0) {
+ $s .= "\n" if $i != 0;
+ $s .= "\t";
+ }
+ $s .= sprintf "{0x%04x, 0x%04x, 0x%04x}, ", @{$r};
+ $i++;
+ }
+ $s;
+}
+
+sub print_bits {
+ my $prefix = shift;
+ my $i = 0;
+ foreach my $bit (@_) {
+ print "#define ${prefix}_BITS_$i\t$bit\n";
+ $i++;
+ }
+}
+
+sub print_ulseq {
+ my $i = 0;
+ foreach my $v (@_) {
+ if ($i % 4 == 0) {
+ print "\n" if $i != 0;
+ print "\t";
+ }
+ printf "0x%08x, ", $v;
+ $i++;
+ }
+ print "\n";
+}
diff --git a/contrib/idn/idnkit-1.0-src/win/README.WIN b/contrib/idn/idnkit-1.0-src/win/README.WIN
new file mode 100644
index 0000000..8e47f85
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/win/README.WIN
@@ -0,0 +1,17 @@
+To build idnkit for Windows, follow the instruction below.
+
+To build Windows version, you need `iconv' library. A LGPL
+implemenation is available from the following place.
+
+ http://www.gnu.org/software/libiconv/
+
+Follow the instructions described in README.woe32 file which can be
+found in the distribution, and you'll get a DLL vesion of `libiconv'.
+Copy the DLL (iconv.dll), the header (iconv.h) and the import library
+(iconv.lib) here.
+
+Then go to the top directory and run the following command.
+
+ nmake -f make.wnt
+
+; $Id: README.WIN,v 1.1.1.1 2003/06/04 00:27:32 marka Exp $
diff --git a/contrib/idn/idnkit-1.0-src/wsock/README.txt b/contrib/idn/idnkit-1.0-src/wsock/README.txt
new file mode 100644
index 0000000..e7723b4
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/README.txt
@@ -0,0 +1,665 @@
+
+ idn wrapper - Client Side IDN Conversion Software for Windows
+
+ Copyright (c) 2000,2001,2002 Japan Network Information Center.
+ All rights reserved.
+
+ *** NOTICE ******************************************************
+ If you have installed mDN Wrapper (former version of idn wrapper)
+ on your system, you should unwrap all the programs before
+ installing idn wrapper.
+ *****************************************************************
+
+
+1. Introduction
+
+ For supporting internationalized domain names, each client
+ application should convert domain names (their encodings) to that
+ DNS server accepts. This requires applications to handle
+ internationalized domain names in its core, and it is the vendor's
+ responsibility to make their programs IDN-compatible.
+
+ Although there are ongoing efforts in IETF to standardize IDN
+ framework (architecture, encoding etc.) and several RFCs are
+ expected to be published soon as the result, not many applications
+ support IDN to this date.
+
+ So, there are needs for some helper application which makes legacy
+ applications IDN-aware. `runidn' in idnkit is one of such
+ solutions for Unix-like operating systems, and this software, `idn
+ wrapper' is the one for Windows.
+
+ On windows, name resolving request is passed to WINSOCK DLL. idn
+ wrapper replaces WINSOCK DLL with the one that can handle IDN,
+ which makes legacy windows applications compatible with IDN.
+
+2. Architecture
+
+2.1. Wrapper DLL
+
+ Wrapper DLL resides between application and original DLL. It
+ intercept application's calls to original DLL, and preforms some
+ additional processing on those calls.
+
+ +------------+ Call +------------+ Call +------------+
+ | |------->| |------->| |
+ |Application | |Wrapper DLL | |Original DLL|
+ | |<-------| |<-------| |
+ +------------+ Return +------------+ Return +------------+
+ additional
+ processing
+ here
+
+ DLL call from apllication is passed to wrapper DLL. Wrapper DLL
+ then performs some additional processing on that call, and then
+ calls original DLL. Also, result from original DLL will once passed
+ to wrapper DLL and wrapper does additional process on that result,
+ and finally result will passed to the application.
+
+ idn wrapper provides wrapper DLLs for WINSOCK,
+
+ WSOCK32.DLL WINSOCK V1.1
+ WS2_32.DLL WINSOCK V2.0
+
+ to resolve multi-lingual domain names.
+
+2.2. Wrapping APIs
+
+ idn wrapper performs additional processing on name resolving APIs in
+ WINSOCK, listed below.
+
+ both WINSOCK 1.1, WINSOCK 2.0
+
+ gethostbyaddr
+ gethostbyname
+ WSAAsyncGetHostByAddr
+ WSAAsyncGetHostByName
+
+ only in WINSOCK 2.0
+
+ getaddrinfo
+ freeaddrinfo
+ getnameinfo
+ WSALookupServiceBeginA
+ WSALookupServiceNextA
+ WSALookupServiceEnd
+
+ Some applications do not use these APIs to resolve domain names.
+ `nslookup' is one of those programs. `nslookup' builds and parse DNS
+ messages internally and does not use WINSOCK's name resolver APIs.
+ idn wrapper cannot make those programs IDN-aware.
+
+ NOTE:
+ WINSOCK 2.0 also contains WIDE-CHARACTER based name resolution
+ APIs,
+
+ WSALookupServiceBeginW
+ WSALookupServiceNextW
+
+ idn wrapper does not wrap these APIs. These APIs are used in
+ Microsoft's own internationalization framework. It is dangerous
+ to convert to another internationalization framework.
+
+2.3. Other APIs in WINSOCK
+
+ For other APIs in WINSOCK, idn wrapper does nothing, only calls
+ original DLL's entries.
+
+ idn wrapper copies original WINSOCK DLLs with renaming
+ as below, and forward requests to them.
+
+ wsock32.dll -> wsock32o.dll
+ ws2_32.dll -> ws2_32o.dll
+
+ Wrappper DLL will be installed with original DLL names. So after
+ installation of idn wrapper, WINSOCK DLLs should be
+
+ wsock32.dll idn wrapper for WINSOCK V1.1
+ ws2_32.dll idn wrapper for WINSOCK V2.0
+ wsock32o.dll Original WINSOCK V1.1 DLL
+ ws2_32o.dll Original WINSOCK V2.0 DLL
+
+2.4. Asynchronous API
+
+ Domain name conversion take place on
+
+ request to DNS
+
+ convert from local encoding to DNS compatible encoding
+
+ response from DNS
+
+ convert from DNS encoding to local encoding
+
+ For synchronous APIs, local to DNS conversion is done before calling
+ original API, and after return from original API, name should be
+ converted from DNS encoding to local encoding.
+
+ But WINSOCK having some asynchronous APIs, such as
+
+ WSAAsyncGetHostByAddr
+ WSAAsyncGetHostByName
+
+ In these APIs, completion is notified with windows message. To
+ perform DNS to local conversion, wrapper should hook target window
+ procedure to capture those completion messages.
+
+ So, if asynchronous API was called, idn wrapper set hook to target
+ window procedure (passed with API parameter). If hook found
+ notify message (also given with API parameter), then convert
+ resulting name (in DNS encoding) to local encoding.
+
+2.5. Installing Wrapper DLLs
+
+ WINSOCK DLLs are placed at Windows's system directory. To wrap
+ WINSOCK DLLs, one could do following sequence at system directory.
+
+ + Rename Original WINSOCK DLLs
+
+ ren wsock32.dll wsock32o.dll
+ ren ws2_32.dll ws2_32o.dll
+
+ + Install (copy in) Wrapper DLLs
+
+ copy somewhere\wsock32.dll wsock32.dll
+ copy somewhere\ws2_32.dll ws2_32.dll
+ copy another DLLs also
+
+ However, replacing DLLs in Window's system directory is very
+ dangerous:
+
+ a) If you re-install idn wrapper again, original WINSOCK DLLs
+ may be lost.
+
+ b) Some application or service pack will replace WINSOCK DLLs. It
+ may corrupt WINSOCK environment.
+
+ If these happen, at least networking does not work, and worse,
+ Windows never startup again.
+
+ So, idn wrapper usually does not wrap in the system directory, but wrap in
+ each indivisual application's directory.
+
+ In Windows, DLL will be searched in the following places:
+
+ Application's Load Directory
+ %SystemRoot%\System32
+ %SystemRoot%
+ Directories in PATH
+
+ and loaded & linked first found one. So if installed wrapper DLLs is
+ found on application's load directory, the application's call to
+ WINSOCK will wrapped.
+
+ But some applications or DLLs are binded to specific DLL, they do
+ not rely on above DLL's search path. For those applcaitons or DLLs,
+ idn wrapper (in standard installation) cannot wrap them.
+
+ NOTE: Netscape is one of those program. It cannot be wrapped if
+ installed to applications directory. Also WINSOCK DLLs are
+ also binded to related DLLs in system directory. On the
+ other hand, Internet Explore or Window Media Player relys on
+ standard DLL search path, and well wrapped with idn wrapper.
+
+2.6. At which point conversion applied
+
+ If windows supporting WINSOCK 2.0, there are DLLs one for 1.1 and
+ another for 2.0, and call to WINSOCK 1.1 will redirected to 2.0 DLL.
+
+ +------------+ Call +------------+ Call +------------+
+ | |------->| |------->| |
+ |Application | |WINSOCK 1.1 | |WINSOCK 2.0 |
+ | |<-------| |<-------| |
+ +------------+ Return +------------+ Return +------------+
+
+ In this case, calls to 1.1 and 2.0 are both passed to 2.0 DLL. So
+ conversion will done in WINSOCK 2.0 DLL side.
+
+ If windows only supports WINSOCK 1.1, there's 1.1 DLL only.
+
+ +------------+ Call +------------+
+ | |------->| |
+ |Application | |WINSOCK 1.1 |
+ | |<-------| |
+ +------------+ Return +------------+
+
+ In this case, conversion must done in 1.1 DLL.
+
+ If idn wrapper was installed on system directory, DLLs will work as
+ described above. But if wrapper was installed on application's
+ directory, call/return sequence changes. Original WINSOCK 1.1 DLL
+ in windows seems binded to specific WINSOCK 2.0 DLL, placed at
+ window's system diretory. So call from WINSOCK 1.1 to WINSOCK 2.0
+ will passed to original DLL (in system directory) and never passed
+ to wrapper DLL in application's directory. So in this case, both
+ 1.1 and 2.0 DLLs should coonvert domain name encodings.
+
+ These DLL binding is not documented. It may be change on OS
+ versions or DLL versions. So, mDn wrapper determines place of
+ conversion on registry value. With this registry value, idn
+ wrappper absolb OS/DLL variations.
+
+ Registry values for idn wrapper will placed under
+
+ HKEY_LOCAL_MACHINE\SOFTWARE\JPNIC\IDN
+ HKEY_CURRENT_USER\SOFTWARE\JPNIC\IDN
+
+ Place of conversion is determined with registry value "Where",
+
+ Registry Value "Where" REG_DWORD
+
+ 0 both on WINSOCK 1.1 and WINSOCK 2.0
+ 1 if WINSOCK 2.0 exist, only in WINSOCK 2.0
+ otherwise, convert on WINSOCK 1.1
+ 2 only in WINSOCK 1.1
+ 3 only in WINSOCK 2.0
+
+ If you install idn wrapper into application's directory, use "0".
+ If you install idn wrapper into system directory, use "1". If there
+ are no "Where" value, idn wrapper uses "0" as default, it is suited
+ to installation into application's directory (default installation).
+
+2.7. Converting From/To
+
+ Wrapper DLL convert resolving domain name encoded with local code to
+ DNS server's encoding. Also, wrapper DLL convert resulting name (
+ encoded with DNS's encoding) back to local encoding.
+
+ There are several proposals for DNS encodings to handle multi-lingual
+ domain names. Wrapper DLL should be configured to convert to one of
+ those encodings. This DNS side encoding will specified with
+ registry. When installing idn wrapper, this registry will set to
+ some (yet undefined) DNS encoding.
+
+ Registry values for idn wrapper will placed under
+
+ HKEY_LOCAL_MACHINE\SOFTWARE\JPNIC\IDN
+ HKEY_CURRENT_USER\SOFTWARE\JPNIC\IDN
+
+ DNS encoding name will given with registry value (REG_SZ) of "Encoding",
+ this name must be one of encoding names which 'libmdn' recognize.
+
+ Registry Value "Encoding" REG_SZ
+
+ Encoding name of DNS server accepts.
+
+ Local encodings (Windows Apllication Encodings) is generally
+ acquired from process's code page. 'iconv' library, used for idn
+ wrapper, generally accepts MS's codepage names.
+
+ Some windows apllication encode domain name with some specific multi-
+ lingual encoding. For example, if you configured IE to use UTF-8,
+ then domain names are encoded with UTF-8. UTF-8 is one of proposed
+ DNS encoding, but DNS server may expect another encoding.
+
+ For those cases, idn wrapper accept program specific encoding as
+ local encoding. These program specific local encoding should be
+ marked in registry.
+
+ Program specific registry setting will placed under
+
+ HKEY_LOCAL_MACHINE\SOFTWARE\JPNIC\IDN\PerProg
+ HKEY_CURRENT_USER\SOFTWARE\JPNIC\IDN\PerProg
+
+ using program name (executable file name) as key. For example,
+ setting specific to Internet Explore, it executable name is
+ "IEXPLORE", will plcaed at
+
+ HKEY_LOCAL_MACHINE\SOFTWARE\JPNIC\IDN\PerProg\IEXPLORE
+
+ Local encoding name will specified with registry value (REG_SZ) of
+ "Encoding". This name must be one of encoding names which '
+ recognize.libmdn'
+
+ Registry Value "Encoding" REG_SZ
+
+ Encoding name of application program encodes, if it is not
+ system's default encoding.
+
+3. Setup and Configuration
+
+ idn wrapper wraps WINSOCK DLL by placing wrapper (fake) DLLs in
+ the application's directory. For the installation, idn wrapper
+ comes with a setup program and a configuration program.
+
+ NOTE: You can also install idn wrapper DLLs in the Windows
+ system directory. But this installation is very dangerous
+ and may cause severe problems in your system.
+ You should try it at your own risk.
+
+3.1. Setup Program
+
+ To install idn wrapper, run "setup.exe". Setup program will do:
+
+ Installing Files
+
+ Copy idn wrapper files (DLL, Program EXE, etc) into diretory
+
+ "\Program Files\JPNIC\idn wrapper"
+
+ This directory may be changed on setup sequence.
+
+ Setting registry entries
+
+ Setup program will create keys and values under registry:
+
+ "HKEY_LOCAL_MACHINES\Software\JPNIC\IDN"
+
+ InstallDir REG_SZ "<installation directory>"
+ Pathname of the idn wrapper's installation directory.
+ The installer makes copies of the original WINSOCK DLLs
+ in that directory, which is referenced by the idn wrapper's
+ fake DLLs.
+
+ ConfFile REG_SZ "<installation directory>\idn.conf"
+ Name of the idnkit's configuration file, which defines
+ various parameter regarding multilingual domain name
+ handling. See the contents of the file for details.
+ This value can be changed with the Configuration Program
+ or the registry editor.
+
+ LogFile REG_SZ "<installation directory>\idn_wrapper.log"
+ Name of the idn wrapper's log file.
+ This value can be changed with the Configuration Program
+ or the registry editor.
+
+ LogLevel DWORD -1
+ Logging level. Default is -1, which indicates no logging
+ is made. This value can be changed with the Configuration
+ Program or the registry editor.
+
+ PerProg KEY
+
+ Under this key, idn wrapper set program specific values. idn
+ wrapper uses program's executable name as key, and put
+ values under that key.
+
+ PerProg\<progname>\Where REG_DWORD Encoding Position
+ PerProg\>progname>\Encoding REG_SZ Local Encoding Name
+
+ Configuration program set local encpoding name. "Where"
+ value is usually not required in standard installation. If
+ you installed idn wrapper in system directory, chanage
+ "Where" values to fit your environment.
+
+ Creating ICON
+
+ Setup program will create program icon for idn wrapper's
+ configuration program, and put it into "Start Menu". You can
+ start configuration program with it.
+
+3.2. Configuration Program
+
+ Configuration program is a tool for wrap specific program, or unwrap
+ programs. If you start "Configuration Program", you'll get window
+ like this.
+
+ +---+-------------------------------------------------+---+---+---+
+ | | idn wrapper - Configuration | _ | O | X |
+ +---+-------------------------------------------------+---+---+---+
+ | idn wrapper Configuration Program version X.X |
+ +-----------------------------------------------------------------+
+ | Wrapped Program +---------+ |
+ | +---------------------------------------------+---+ | Wrap.. | |
+ | | | A | +---------+ |
+ | | +---+ +---------+ |
+ | | | | | Unwrap..| |
+ | | | | +---------+ |
+ | | | | +---------+ |
+ | | | | |UnwrapAll| |
+ | | | | +---------+ |
+ | | | | +---------+ |
+ | | | | |RewrapAll| |
+ | | | | +---------+ |
+ | | | | +---------+ |
+ | | | | | Log.. | |
+ | | | | +---------+ |
+ | | | | +---------+ |
+ | | +---+ |Advanced.| |
+ | | | V | +---------+ |
+ | +---+-------------------------------------+---+---+ +---------+ |
+ | | < | | > | | Exit | |
+ | +---+-------------------------------------+---+ +---------+ |
+ +-----------------------------------------------------------------+
+
+ Listbox contains list of current wrapped programs. Initially it is
+ empty.
+
+ To wrap a program, press button "wrap". You'll get following dialog.
+
+ +---+-------------------------------------------------+---+---+---+
+ | | idn wrapper - Wrap Executable | _ | O | X |
+ +---+-------------------------------------------------+---+---+---+
+ | +----------------------------------------+ +--------+ |
+ | Program: | | |Browse..| |
+ | +----------------------------------------+ +--------+ |
+ | +----------+ |
+ | Encoding: | | o Default o UTF-8 |
+ | +----------+ |
+ | [] Force local DLL reference |
+ +-----------------------------------------------------------------+
+ | +--------+ +--------+ |
+ | | Wrap | | Cancel | |
+ | +--------+ +--------+ |
+ +-----------------------------------------------------------------+
+
+ First, enter program (executable name with full path) or browse
+ wrapping exectable from file browser. Then set local encoding of
+ that program. Usually use "Default" as local encoding. If target
+ program uses internationalized encoding, then specify "UFT-8".
+
+ The "Force local DLL reference" button controls the DLL search
+ order of the program to be wrapped (Windows95 does not have this
+ capability, hence this button does not appear). If it is checked,
+ DLLs in the local directory (the directory which the executable
+ file is in) are always preferred, even if the executable specifies
+ otherwise. If you have problem with wrapping, checking this
+ button may solve the problem, but it is also possible that it
+ causes other problem.
+
+ Finally, put "wrap" button to wrap specified program with given
+ encoding. Wrapped program will be listed in listbox of the first
+ window.
+
+ When you install a new version of idn wrapper, you have to re-wrap
+ your programs in order to update DLLs used for wrapping. "Rewrap
+ all" button is provided for this purpose. Just press the button,
+ and all the currently wrapped programs will be re-wrapped.
+
+ To unwrap a program, press button "unwrap". You'll get following
+ confirmating dialog.
+
+ +---+-------------------------------------------------+---+---+---+
+ | | idn wrapper - Unwrap Executable | _ | O | X |
+ +---+-------------------------------------------------+---+---+---+
+ | +---------------------------------------------------+ |
+ | Program: | | |
+ | +---------------------------------------------------+ |
+ +-----------------------------------------------------------------+
+ | +--------+ +--------+ |
+ | | Unwrap | | Cancel | |
+ | +--------+ +--------+ |
+ +-----------------------------------------------------------------+
+
+ If you unwrap a program, the program will be vanished from listbox
+ of the first window.
+
+ Also "Unwrap all" button is provided to unwrap all the programs
+ that are currently wrapped.
+
+ To configure logging, press button "log". You'll get the following
+ dialog.
+
+ +---+-------------------------------------------------+---+---+---+
+ | | idn wrapper - Log Configuration | _ | O | X |
+ +---+-------------------------------------------------+---+---+---+
+ | Log Level: o None o Fatal o Error o Warning o Info o Trace |
+ | |
+ | +------------------------------------+ +---------+ |
+ | Log File:| | | Browse..| |
+ | +------------------------------------+ +---------+ |
+ | +------+ +--------+ |
+ |Log Operation: | View | | Delete | |
+ | +------+ +--------+ |
+ +-----------------------------------------------------------------+
+ | +--------+ +--------+ |
+ | | OK | | Cancel | |
+ | +--------+ +--------+ |
+ +-----------------------------------------------------------------+
+
+ Logging level can be selected from the followings.
+ None no logging at all
+ Fatal only records fatal errors
+ Error also records non-fatal errors
+ Warning also records warning mssages
+ Info also records informational messages
+ Trace also records trace information
+ Note that these levels are for log output from IDN library (idnkit.dll).
+ idn wrapper itself supports only off (None) and on (the rest).
+
+ Pathname of the log file can also be specified with this dialog.
+
+ You can view the current log file contents by pressing "View" button,
+ or delete it by "Delete" button.
+
+ Note that log level and log file configuration doesn't affect already
+ running processes.
+
+ Press "advanced" button to invoke the advanced configuration dialog.
+ This dialog is for advanced users and enables customization for
+ some basic parameters which normal users need not change, since
+ appropriate defaults are provided.
+
+ +---+-------------------------------------------------+---+---+---+
+ | | idn wrapper - Advanced Configuration | _ | O | X |
+ +---+-------------------------------------------------+---+---+---+
+ | IDN Wrapping Mode |
+ | o Wrap both WINSOCK 1.1 and WINSOCK 2.0 |
+ | o Wrap only WINSOCK 1.1 |
+ | o Wrap only WINSOCK 2.0 |
+ | o Wrap only WINSOCK 2.0 if it exists. |
+ | Otherwise wrap only WINSOCK 1.1 |
+ +-----------------------------------------------------------------+
+ | IDN Configuration |
+ | +--------------------------------+ +----------+ |
+ | Config File: | | | Browse.. | |
+ | +--------------------------------+ +----------+ |
+ | +------+ |
+ | | Edit | |
+ | +------+ |
+ +-----------------------------------------------------------------+
+ | +--------+ +--------+ |
+ | | OK | | Cancel | |
+ | +--------+ +--------+ |
+ +-----------------------------------------------------------------+
+
+ With the dialog users can do the following configuration.
+
+ Wrapping Mode
+ Customize wrapping mode. Normally the default item should be
+ appropriate. Changing it to other item may help when you
+ have problems.
+
+ IDN Configuration
+ Set the configuration file for multilingual domain name handling.
+ By pressing "Edit" button, you can edit then contents of the file.
+
+4. Limitations
+
+4.1. DLL Versions
+
+ Wrapper DLL is tightly coupled with specific DLL version, because
+ it must export all the entries including un-documented ones.
+ If WINSOCK DLL version changed, idn wrapper may not work correctly.
+
+ Current idn wrapper is tested on
+
+ Win2000 (WINSOCK 1.1 + 2.0)
+ WinME (WINSOCK 1.1 + 2.0)
+
+ But there are no assuarance for future versions of Windows.
+
+4.2. DNS, WINS, LMHOSTS
+
+ There are three name resolving methods in windows, DNS, WINS and
+ LMHOSTS. Using idn wrapper, domain name conversion will performed
+ on all of thoses methods. It may cause some trouble if windows
+ using WINS or LMHOSTS. We recommend use DNS oly if you want to use
+ idn wrapper.
+
+4.3. Converting Names other than Domain Name
+
+ In WINSOCK 2.0, there are generic name resolution APIs are
+ introduced.
+
+ WSALookupServiceBeginA
+ WSALookupServiceNextA
+ WSALookupServiceEnd
+
+ They are use mainly domain name conversion now, but not limited to
+ resolving domain name. idn wrapper hooks this API and convert
+ given name anyway. This causes some trouble if conversion name is
+ not domain name.
+
+4.4. Applications don't use these APIa
+
+ Some applications don't use these APIs to resolving domain names.
+ For example, 'nslookup' issue DNS request locally. For these
+ applications, idn wrapper does not work.
+
+4.5. Applications bound to specific WINSOCK DLL
+
+ Some applications are bound to specific DLL, not relying on
+ standard DLL search path. Netscape Communicator seems to be one of
+ such programs. idn wrapper in standard installation cannot wrap
+ such programs.
+
+ If you want to wrap those programs, you may use installation into
+ system directory. But this installation is very dangerous, for
+ it is possible that your system cannot boot again.
+
+5. Registry Setting - Summary
+
+5.1. Priority of Setting
+
+ Settings of idn wrapper is placed on registry
+
+ Software\JPNIC\IDN
+
+ under HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER. idn wrapper first
+ read HKEY_LOCAL_MACHINE, and if HKEY_CURRENT_USER exist, overwrite
+ with this one. Usually set HKEY_LOCAL_MACHINE only. But if you
+ need per user setting, then set HKEY_CURRENT_USER.
+
+ Note that the configuration program reads/writes only
+ HKEY_LOCAL_MACHINE.
+
+5.2. Registry Key
+
+ There's common settings and per program settings.
+
+_Common Settings
+
+ Software\JPNIC\IDN\InstallDir Installation directory
+ Software\JPNIC\IDN\Where Where to convert encoding
+ 0: both WINSOCK 1.1 and WINSOCK 2.0
+ 1: if WINSOCK 2.0 exist, convert at 2.0 DLL
+ if WINSOCK 1.1 only, convert at 1.1 DLL
+ 2: only in WINSOCK1.1
+ 3: only in WINSOCK2.0
+ Software\JPNIC\IDN\ConfFile idnkit Configuration File
+ Software\JPNIC\IDN\LogFile Log File
+ Software\JPNIC\IDN\LogLevel Log Level
+
+_Per Program Settings
+
+ Converting position and program's local encoding may be set per
+ program bases.
+
+ Software\JPNIC\IDN\PerProg\<name>\Where
+ Software\JPNIC\IDN\PerProg\<name>\Encoding
+
+ If not specified, the following values are assumed.
+
+ Where 0 (both 1.1 DLL and 2.0 DLL)
+ Encoding [process's code page]
diff --git a/contrib/idn/idnkit-1.0-src/wsock/README_j.txt b/contrib/idn/idnkit-1.0-src/wsock/README_j.txt
new file mode 100644
index 0000000..354f46c
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/README_j.txt
@@ -0,0 +1,717 @@
+
+ idn wrapper - Windows ‚É‚¨‚¯‚éƒNƒ‰ƒCƒAƒ“ƒg‘¤‚Å‚Ì IDN •ÏŠ·ƒ\ƒtƒgƒEƒFƒA
+
+ Copyright (c) 2000,2001,2002 Japan Network Information Center.
+ All rights reserved.
+
+ *** ’ˆÓ **********************************************************
+ ‚à‚µ‚à‚·‚Å‚É mDN Wrapper (idn wrapper ‚Ì‘Og) ‚ªƒCƒ“ƒXƒg[ƒ‹‚³‚ê‚Ä
+ ‚¢‚éƒ}ƒVƒ“‚É idn wrapper ‚ðƒCƒ“ƒXƒg[ƒ‹‚·‚éꇂɂÍAƒCƒ“ƒXƒg[ƒ‹‘O
+ ‚ÉAƒ‰ƒbƒv‚³‚ê‚Ä‚¢‚é‚·‚ׂẴvƒƒOƒ‰ƒ€‚ðƒAƒ“ƒ‰ƒbƒv‚µ‚Ä‚­‚¾‚³‚¢B
+ *******************************************************************
+
+
+1. ‚Í‚¶‚ß‚É
+
+ Windows ‚Å‘Û‰»ƒhƒƒCƒ“–¼‚ðˆµ‚¦‚é‚悤‚É‚·‚邽‚ß‚É‚ÍAWindows ã‚Ì
+ ƒNƒ‰ƒCƒAƒ“ƒgƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚É‚¨‚¢‚ÄA‰ðŒˆ‚µ‚悤‚Æ‚·‚é–¼‘O‚̃Gƒ“ƒR[
+ ƒfƒBƒ“ƒO‚ðADNS ƒT[ƒo‚ªŽó•t‚¯‚éŒ`Ž®‚Ì‚à‚Ì‚É•ÏŠ·‚·‚é•K—v‚ª‚ ‚è‚Ü‚·B
+ ‚±‚ê‚ÍAWindows ã‚̃AƒvƒŠƒP[ƒVƒ‡ƒ“‚ªA‚«‚¿‚ñ‚Æ‘Û‰»ƒhƒƒCƒ“–¼‚ð
+ ˆµ‚¦‚é‚悤‚É‚È‚Á‚Ä‚¢‚È‚¯‚ê‚΂Ȃç‚È‚¢A‚Æ‚¢‚¤‚±‚Æ‚Å‚ ‚èA–{—ˆ‚Í‚»‚ê
+ ‚¼‚ê‚̃vƒƒOƒ‰ƒ€‚Ì쬎҂ªs‚È‚¤‚ׂ«‚±‚Æ‚Å‚·B
+
+ Œ»Ý IETF ‚É‚Ä‘Û‰»ƒhƒƒCƒ“–¼‚̃tƒŒ[ƒ€ƒ[ƒN‚ð•W€‰»‚·‚é“w—Í‚ª‘±
+ ‚¯‚ç‚ê‚Ä‚¨‚èA‚»‚ÌŒ‹‰Ê‚Æ‚µ‚Ĉê˜A‚Ì RFC ‚ª‚à‚¤‚·‚®”­s‚³‚ê‚邱‚Æ‚É
+ ‚È‚Á‚Ä‚¢‚Ü‚·‚ªA‚»‚ê‚Å‚à‘Û‰»ƒhƒƒCƒ“–¼‚ɑΉž‚µ‚½ƒAƒvƒŠƒP[ƒVƒ‡ƒ“
+ ‚Í‚Ü‚¾‚Ü‚¾­‚È‚¢‚Ì‚ªŒ»ó‚Å‚·B
+
+ ‚»‚±‚ÅAŠù‘¶‚̃AƒvƒŠƒP[ƒVƒ‡ƒ“‚ð‘Û‰»ƒhƒƒCƒ“–¼‚ɑΉž‚³‚¹‚邽‚ß‚Ì
+ ƒwƒ‹ƒp[ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚ª•K—v‚É‚È‚è‚Ü‚·Bidnkit ‚ÉŠÜ‚Ü‚ê‚é runidn
+ ƒRƒ}ƒ“ƒh‚Í Unix Œn‚Ì OS ‚ł̈ê‚‚̉ðŒˆô‚Å‚·‚µAWindows ‚ɑ΂·‚é‰ð
+ Œˆô‚Æ‚µ‚Ä‚Í‚±‚±‚Åà–¾‚·‚é idn wrapper ‚ª‚ ‚è‚Ü‚·B
+
+ Windows ‚É‚¨‚¢‚ÄA‘½‚­‚Ìê‡AƒhƒƒCƒ“–¼‰ðŒˆ‚Ì—v‹‚ÍWINSOCK DLL ‚É
+ “n‚³‚ê‚Ü‚·B‚»‚±‚ÅAWINSOCK DLL ‚ð‘Û‰»ƒhƒƒCƒ“–¼‘Ήž‚Ì‚à‚Ì‚É’u‚«
+ Š·‚¦‚Ä‚â‚ê‚ÎAŠù‘¶‚̃vƒƒOƒ‰ƒ€‚©‚ç‚Å‚à‘Û‰»ƒhƒƒCƒ“–¼‚ðŽg‚¤‚±‚Æ‚ª
+ ‚Å‚«‚é‚悤‚É‚È‚è‚Ü‚·B
+
+2. ŽÀŒ»•û–@
+
+2.1. ƒ‰ƒbƒp[DLL
+
+ ƒ‰ƒbƒp[DLL ‚ÍAƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚ÆŒ³‚ÌDLL ‚Æ‚ÌŠÔ‚ÉŠ„‚èž‚ñ‚ÅAƒAƒvƒŠ
+ ƒP[ƒVƒ‡ƒ“‚©‚ç‚ÌDLL ‚̌ĂÑo‚µ‚ð‰¡Žæ‚肵‚ÄA–{—ˆ‚ÌDLL ‚Ƃ͈قȂÁ‚½ˆ
+ —‚ð‚³‚¹‚é‚à‚Ì‚Å‚·B
+
+ +------------+ Call +------------+ Call +------------+
+ | |------->| |------->| |
+ |Application | |Wrapper DLL | |Original DLL|
+ | |<-------| |<-------| |
+ +------------+ Return +------------+ Return +------------+
+ additional
+ processing
+ here
+
+ ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚©‚ç‚ÌDLL ‚̌ĂÑo‚µ‚̓‰ƒbƒp[ DLL‚É“n‚³‚ê‚Ü‚·Bƒ‰ƒb
+ ƒp[ DLL‚Í‚»‚±‚ÅA•t‰Á“I‚Ȉ—‚ðs‚È‚Á‚ÄAŒ³‚ÌDLL ‚̃Gƒ“ƒgƒŠ‚ðŒÄ‚Ño
+ ‚µ‚Ü‚·B‚Ü‚½AŒ³‚ÌDLL ‚̈—Œ‹‰Ê‚͈ê’Uƒ‰ƒbƒp[ DLL‚É•Ô‚³‚êA‚±‚±‚Å‚à
+ •t‰Á“I‚Ȉ—‚ðs‚È‚Á‚ÄAÅI“I‚ÈŒ‹‰Ê‚ªƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚É•Ô‚³‚ê‚邱‚Æ
+ ‚É‚È‚è‚Ü‚·B
+
+ idn wrapper ‚Å‚ÍAWINSOCK DLL‚Ì
+
+ WSOCK32.DLL WINSOCK V1.1
+ WS2_32.DLL WINSOCK V2.0
+
+ ‚ɑ΂·‚郉ƒbƒp[DLL ‚ð’ñ‹Ÿ‚µ‚ÄA‘Û‰»ƒhƒƒCƒ“–¼‚Ì–¼‘O‰ðŒˆ‚ª‚Å‚«‚é‚æ
+ ‚¤‚É‚µ‚Ü‚·B16ƒrƒbƒg”Å‚ÌWINSOCK (WINSOCK.DLL) ‚Í‘ÎÛŠO‚Å‚·B
+
+2.2. ˆ—‘ÎÛ‚ÌAPI
+
+ idn wrapper ‚ÍWINSOCK ‚Ì–¼‘O‰ðŒˆ‚ÉŠÖ˜A‚µ‚½API ‚ɂ‚¢‚Ä‚Ì‚Ý•t‰Á“I‚Ȉ
+ —‚ðs‚È‚¢‚Ü‚·Bˆ—‚Ì‘ÎÛ‚Æ‚È‚éWINSOCK API‚͈ȉº‚Ì‚à‚Ì‚Å‚·B
+
+ WINSOCK 1.1, WINSOCK 2.0 ‚Ì—¼•û‚É‚ ‚é‚à‚Ì
+
+ gethostbyaddr
+ gethostbyname
+ WSAAsyncGetHostByAddr
+ WSAAsyncGetHostByName
+
+ WINSOCK 2.0 ‚¾‚¯‚É‚ ‚é‚à‚Ì
+
+ WSALookupServiceBeginA
+ WSALookupServiceNextA
+ WSALookupServiceEnd
+
+ ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚É‚æ‚Á‚Ä‚ÍA‚±‚ê‚ç‚ÌAPI ‚ðŽg‚í‚È‚¢‚Å“ÆŽ©‚ɃhƒƒCƒ“–¼
+ ‚Ì‰ðŒˆ‚ðs‚È‚¤‚à‚Ì‚à‚ ‚è‚Ü‚·B—Ⴆ‚ÎAnslookup‚ÍA‚±‚ê‚ç‚ÌAPI ‚ðŽg‚í
+ ‚È‚¢‚ÅA“à•”‚Å“ÆŽ©‚ÉDNS ƒŠƒNƒGƒXƒg‚̶¬A‰ðŽß‚ðs‚È‚Á‚Ä‚¢‚Ü‚·B“–‘R
+ ‚Ì‚±‚Æ‚È‚ª‚çA‚±‚ê‚ç‚̃AƒvƒŠƒP[ƒVƒ‡ƒ“‚ɂ‚¢‚Ä‚ÍAidn wrapper ‚Å‚Í‘½
+ Œ¾Œê‰»‘Ήž‚³‚¹‚邱‚Æ‚Í‚Å‚«‚Ü‚¹‚ñB
+
+ ’FWINSOCK 2.0 ‚É‚ÍAWIDE CHARACTER ƒx[ƒX‚Ì–¼‘O‰ðŒˆ‚ÌAPI ‚Æ‚µ‚Ä
+
+ WSALookupServiceBeginW
+ WSALookupServiceNextW
+
+ ‚à‚ ‚è‚Ü‚·‚ªA‚±‚ê‚ç‚ɂ‚¢‚Ă̓‰ƒbƒv‚µ‚Ü‚¹‚ñB‚±‚ê‚ç‚ÌAPI ‚̓}
+ ƒCƒNƒƒ\ƒtƒgŽd—l‚É‚æ‚é‘Û‰»‚ɑΉž‚µ‚½‚à‚Ì‚Å‚·‚©‚çA‚»‚̃tƒŒ[
+ ƒ€ƒ[ƒNã‚ÅŽg‚¤‚ׂ«‚à‚Ì‚Å‚·B‚±‚ê‚ç‚ɂ‚¢‚Ä‚Í‘¼‚Ì‘½Œ¾Œê‰»ƒtƒŒ[
+ ƒ€ƒ[ƒN‚É•ÏŠ·‚µ‚Ä‚µ‚Ü‚¤‚̂͊댯‚Å‚Í‚È‚¢‚Æ”»’f‚µ‚Ü‚µ‚½B
+
+2.3. ˆ—‘ÎÛŠO‚ÌAPI
+
+ ã‹LˆÈŠO‚ÌWINSOCK API ‚ɂ‚¢‚Ä‚ÍAidn wrapper ‚Í‚È‚É‚à‚µ‚È‚¢‚ÅAŒ³‚Ì
+ WINSOCK API ‚ðŒÄ‚Ño‚µ‚Ü‚·B
+
+ idn wrapper ‚Å‚ÍAŒ³‚ÌWINSOCK DLL ‚𖼑O‚ð•Ï‚¦‚ăRƒs[‚µA‚»‚ê‚ð
+ ŒÄ‚Ño‚·‚悤‚Éì‚ç‚ê‚Ä‚¢‚Ü‚·B
+
+ wsock32.dll -> wsock32o.dll
+ ws2_32.dll -> ws2_32o.dll
+
+ ƒ‰ƒbƒp[DLL ‚ÍŒ³‚ÌWINSOCK DLL ‚Æ“¯‚¶–¼‘O‚Å쬂³‚ê‚Ü‚·B]‚Á‚Äidn
+ wrapper ‚ªƒCƒ“ƒXƒg[ƒ‹‚³‚ꂽó‘Ô‚Å‚ÍA
+
+ wsock32.dll idn wrapper for WINSOCK V1.1
+ ws2_32.dll idn wrapper for WINSOCK V2.0
+ wsock32o.dll Original WINSOCK V1.1 DLL
+ ws2_32o.dll Original WINSOCK V2.0 DLL
+
+ ‚Æ‚È‚è‚Ü‚·B
+
+2.4. ”ñ“¯Šú API
+
+ ƒhƒƒCƒ“–¼‚Ì•ÏŠ·‚ÍAˆÈ‰º‚̃^ƒCƒ~ƒ“ƒO‚Ås‚È‚í‚ê‚é•K—v‚ª‚ ‚è‚Ü‚·B
+
+ DNS ‚ւ̃ŠƒNƒGƒXƒgŽž
+
+ ƒ[ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“ƒO -> DNS ƒGƒ“ƒR[ƒfƒBƒ“ƒO
+
+ DNS ‚©‚ç‚̉ž“šŽóMŽž
+
+ DNS ƒGƒ“ƒR[ƒfƒBƒ“ƒO -> ƒ[ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“ƒO
+
+ “¯ŠúAPI ‚É‚¨‚¢‚Ä‚ÍAƒ[ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚©‚çDNS ƒGƒ“ƒR[ƒfƒBƒ“ƒO
+ ‚Ö‚Ì•ÏŠ·‚ÍAŒ³‚ÌAPI ‚ðŒÄ‚Ño‚·‘O‚És‚í‚êADNS ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚©‚çƒ[
+ ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚Ö‚Ì•ÏŠ·‚ÍAŒ³‚ÌAPI ‚©‚ç•œ‹A‚µ‚Ä‚«‚½‚Æ‚±‚ë‚Ås‚È
+ ‚í‚ê‚Ü‚·B
+
+ ‚µ‚©‚µAWINSOCK ‚̈ȉº‚ÌAPI ‚Í”ñ“¯ŠúAPI ‚ÅADNS ‚©‚ç‚̉ž“šŽóM‘O‚É•œ
+ ‹A‚µ‚Ä‚µ‚Ü‚¢‚Ü‚·B
+
+ WSAAsyncGetHostByAddr
+ WSAAsyncGetHostByName
+
+ ‚±‚ê‚ç‚ÌAPI ‚É‚¨‚¢‚Ä‚ÍA–¼‘O‰ðŒˆ‚ÌŠ®—¹‚ÍAWindows ‚ւ̃ƒbƒZ[ƒW‚É‚æ‚Á
+ ‚Ä’Ê’m‚³‚ê‚Ü‚·B‚±‚Ì‚½‚ßADNS ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚©‚çƒ[ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“
+ ƒO‚Ö‚Ì•ÏŠ·‚ðs‚È‚¤‚É‚ÍAƒ‰ƒbƒp[‚Í’Ê’mæ‚̃EƒBƒ“ƒhƒEƒvƒƒVƒWƒƒ‚̃ƒb
+ ƒZ[ƒWƒLƒ…[‚ðƒtƒbƒN‚µ‚ÄA‚±‚ÌŠ®—¹ƒƒbƒZ[ƒW‚ð•ßŠl‚·‚é•K—v‚ª‚ ‚è‚Ü‚·B
+
+ ‚»‚±‚ÅA”ñ“¯ŠúAPI ‚ªŒÄ‚Ño‚³‚ꂽꇂɂÍAidn wrapper ‚ÍA’Ê’mæ‚̃EƒBƒ“
+ ƒhƒEƒvƒƒVƒWƒƒi‚±‚ê‚ÍAPI ‚̃pƒ‰ƒƒ^‚ÅŽwŽ¦‚³‚ê‚Ü‚·j‚ɃtƒbƒN‚ðݒ肵
+ ‚Ü‚·BƒtƒbƒN‚ªŠ®—¹ƒƒbƒZ[ƒWi‚±‚ê‚àAPI ‚̃pƒ‰ƒƒ^‚ÅŽwŽ¦‚³‚ê‚Ü‚·j‚ð
+ ŒŸo‚µ‚½‚È‚çAƒtƒbƒN‚ÍŒ‹‰Ê‚ÌŠi”[—̈æi‚±‚ê‚àAPI ‚̃pƒ‰ƒƒ^‚ÅŽwŽ¦‚³‚ê
+ ‚Ä‚¢‚Ü‚·j‚̃hƒƒCƒ“–¼‚ðADNS ‘¤‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO‚©‚çƒ[ƒJƒ‹ƒGƒ“ƒR[
+ ƒfƒBƒ“ƒO‚É•ÏŠ·‚·‚é‚à‚Ì‚Æ‚µ‚Ü‚·B
+
+2.5. Wrapper DLL ‚̃Cƒ“ƒXƒg[ƒ‹
+
+ WINSOCK DLL ‚ÍWindows ‚̃VƒXƒeƒ€ƒfƒBƒŒƒNƒgƒŠ‚É’u‚©‚ê‚Ä‚¢‚Ü‚·B
+ WINSOCK ‚ðŠmŽÀ‚Ƀ‰ƒbƒv‚·‚é‚É‚ÍAƒVƒXƒeƒ€ƒfƒBƒŒƒNƒgƒŠ‚É‚¨‚¢‚Ä
+
+ ƒIƒŠƒWƒiƒ‹WINSOCK DLL ‚Ì–¼‘O‚Ì•ÏX
+
+ ren wsock32.dll wsock32o.dll
+ ren ws2_32.dll ws2_32o.dll
+
+ ƒ‰ƒbƒp[DLL ‚Ì“±“ü
+
+ copy somewhere\wsock32.dll wsock32.dll
+ copy somewhere\ws2_32.dll ws2_32.dll
+ copy another DLLs also
+
+ ‚ðs‚È‚¤•K—v‚ª‚ ‚è‚Ü‚·B
+
+ ‚µ‚©‚µAƒVƒXƒeƒ€ƒfƒBƒŒƒNƒgƒŠ‚Å‚±‚̂悤‚ÈDLL ‚Ì’u‚«Š·‚¦‚ðs‚È‚¤‚Ì‚Í‘å
+ •ÏŠëŒ¯‚È‘€ì‚É‚È‚è‚Ü‚·B
+
+ a) DLL ‚ð“ü‚ê‘Ö‚¦‚½ó‘Ô‚ÅA‚à‚¤‚¢‚¿‚Ç“¯‚¶‘€ì‚ðs‚È‚¤‚ÆAƒIƒŠƒWƒiƒ‹
+ ‚ÌWINSOCK DLL ‚ªŽ¸‚í‚ê‚Ä‚µ‚Ü‚¤‚±‚Æ‚É‚È‚è‚Ü‚·B
+
+ b) ƒT[ƒrƒXƒpƒbƒN‚âƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚È‚Ç‚ÅAWINSOCK DLL ‚ðÄ“±“ü‚·‚é
+ ‚à‚Ì‚ª‚ ‚è‚Ü‚·‚ªA‚±‚ê‚É‚æ‚Á‚Ä‚àWINSOCK ‚ª—˜—p•s”\‚ɂȂ邱‚Æ‚ª‚ 
+ ‚è‚Ü‚·B
+
+ ‚±‚̂悤‚Èó‘Ô‚É‚È‚é‚ÆAƒlƒbƒgƒ[ƒN‹@”\‚ª‘S‚­Žg‚¦‚È‚­‚È‚Á‚½‚èAň«
+ ‚ÍWindows ‚Ì‹N“®‚·‚ço—ˆ‚È‚­‚È‚é‰Â”\«‚ª‚ ‚è‚Ü‚·B
+
+ ‚»‚±‚ÅAidn wrapper ‚Å‚ÍAã‚̂悤‚ȃVƒXƒeƒ€ƒŒƒxƒ‹‚̃‰ƒbƒv‚Å‚Í‚È‚­A
+ ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚ɑ΂·‚郉ƒbƒv‚ðŠî–{‹@”\‚Æ‚µ‚Ä’ñ‹Ÿ‚·‚é‚à‚Ì‚Æ‚µ‚Ü‚·B
+
+ Windows ‚É‚¨‚¢‚ÄADLL ‚ÍAŠî–{“I‚É‚Í
+
+ ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚̃[ƒhƒfƒBƒŒƒNƒgƒŠ
+ %SystemRoot%\System32
+ %SystemRoot%
+ PATH ‚ÅŽwŽ¦‚³‚ê‚éƒfƒBƒŒƒNƒgƒŠ
+
+ ‚̇˜‚ÅŒŸõ‚³‚ê‚ÄAʼn‚ÉŒ©‚‚©‚Á‚½‚à‚Ì‚ªƒ[ƒh‚³‚ê‚Ü‚·B‚Å‚·‚©‚çA
+ ˆê”Ê“I‚É‚ÍADLL ‚ðƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚̃[ƒhƒfƒBƒŒƒNƒgƒŠ‚ɃCƒ“ƒXƒg[ƒ‹
+ ‚·‚ê‚ÎA‚»‚̃AƒvƒŠƒP[ƒVƒ‡ƒ“‚©‚ç‚ÌWINSOCK ‚̌ĂÑo‚µ‚ðƒ‰ƒbƒv‚·‚邱‚Æ
+ ‚ª‚Å‚«‚Ü‚·B
+
+ ‚½‚¾‚µA‚¢‚­‚‚©‚̃AƒvƒŠƒP[ƒVƒ‡ƒ“ADLL ‚Å‚ÍAŒŸõƒpƒX‚ðŒo—R‚¹‚¸‚É“Á
+ ’è‚ÌDLL ‚ðƒŠƒ“ƒN‚·‚é‚悤‚É‚È‚Á‚Ä‚¢‚é‚à‚Ì‚ª‚ ‚è‚Ü‚·B‚±‚̂悤‚È\¬‚Ì
+ ƒAƒvƒŠƒP[ƒVƒ‡ƒ“ADLL ‚ªŽg‚í‚ê‚½ê‡‚É‚Í idn wrapper‚ł͑Έ‚·‚邱‚Æ
+ ‚Í‚Å‚«‚Ü‚¹‚ñB
+
+ ’FNetscape‚Í“Á’èDLL ‚ɃoƒCƒ“ƒh‚³‚ê‚Ä‚¢‚é‚悤‚ÅAƒAƒvƒŠƒP[ƒVƒ‡ƒ“ƒfƒB
+ ƒŒƒNƒgƒŠ‚ւ̃Cƒ“ƒXƒg[ƒ‹‚ł̓‰ƒbƒv‚Å‚«‚Ü‚¹‚ñBWINSOCK DLL Ž©‘Ì‚à
+ ƒVƒXƒeƒ€ƒfƒBƒŒƒNƒgƒŠ‚ÌŠÖ˜ADLL ‚ɃoƒCƒ“ƒh‚³‚ê‚Ä‚¢‚é‚悤‚Å‚·Bˆê•ûA
+ Internet Explore‚âWindows Media Player‚Í•W€‚̃T[ƒ`ƒpƒX‚É]‚Á‚Ä
+ ‚¢‚é‚Ì‚ÅAƒ‰ƒbƒv‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B
+
+2.6. ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚Ì•ÏŠ·ˆÊ’u
+
+ WINSOCK 2.0 ‚ðƒTƒ|[ƒg‚µ‚Ä‚¢‚éWindows ‚É‚ÍAWINSOCK ‚Ì1.1 ‚Æ2.0 ‚Ì‚»
+ ‚ꂼ‚ê‚ɑΉž‚·‚éDLL ‚ª‚ ‚èAWINSOCK 1.1 ‚ÌAPI ‚̌ĂÑo‚µ‚Í2.0 ‚Ì“¯‚¶
+ ƒGƒ“ƒgƒŠ‚ɃŠƒ_ƒCƒŒƒNƒg‚³‚ê‚é‚悤‚É‚È‚Á‚Ä‚¢‚Ü‚·B
+
+ +------------+ Call +------------+ Call +------------+
+ | |------->| |------->| |
+ |Application | |WINSOCK 1.1 | |WINSOCK 2.0 |
+ | |<-------| |<-------| |
+ +------------+ Return +------------+ Return +------------+
+
+ ‚±‚ÌꇂɂÍ1.1 ‚ɑ΂·‚éŒÄ‚Ño‚µ‚à2.0 ‚ɑ΂·‚éŒÄ‚Ño‚µ‚àA‚Æ‚à‚ÉV2.0
+ —p‚ÌDLL ‚É“n‚³‚ê‚é‚Ì‚ÅA2.0—p‚̃‰ƒbƒp[DLL ‘¤‚¾‚¯‚ŃGƒ“ƒR[ƒfƒBƒ“ƒO‚Ì
+ •ÏŠ·‚ðs‚È‚¤‚悤‚É‚·‚é‚ׂ«‚Å‚µ‚傤B
+
+ ˆê•ûAWINSOCK 1.1 ‚µ‚©ƒTƒ|[ƒg‚µ‚Ä‚¢‚È‚¢ê‡(Win95)‚É‚ÍA1.1 ‚ɑΉž‚µ
+ ‚½DLL ‚µ‚©‚ ‚è‚Ü‚¹‚ñB
+
+ +------------+ Call +------------+
+ | |------->| |
+ |Application | |WINSOCK 1.1 |
+ | |<-------| |
+ +------------+ Return +------------+
+
+ ‚±‚Ìꇂɂ͕K‘R“I‚É1.1 —p‚̃‰ƒbƒp[DLL ‚ŃGƒ“ƒR[ƒfƒBƒ“ƒO‚ð•ÏŠ·‚µ‚È
+ ‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñB
+
+ idn Wrapepr ‚ªwindows ‚̃VƒXƒeƒ€ƒfƒBƒŒƒNƒgƒŠ‚ɃCƒ“ƒXƒg[ƒ‹‚³‚ꂽê‡
+ ‚É‚ÍAã‚Ì’Ê‚è‚É“®ì‚·‚é‚Ì‚ÅA
+
+ WINSOCK 2.0 ‚ ‚è 2.0 ƒ‰ƒbƒp[‚Å•ÏŠ·
+ WINSOCK 1.1 ‚Ì‚Ý 1.1 ƒ‰ƒbƒp[‚Å•ÏŠ·
+
+ ‚·‚é•K—v‚ª‚ ‚è‚Ü‚·B
+
+ ‚µ‚©‚µAƒAƒvƒŠƒP[ƒVƒ‡ƒ“ƒfƒBƒŒƒNƒgƒŠ‚ɃCƒ“ƒXƒg[ƒ‹‚³‚ꂽꇂɂ͓®ì
+ ‚ª•Ï‚í‚Á‚Ä‚«‚Ü‚·BWindows •t‘®‚Ì WINSOCK 1.1 DLL‚ÍAƒVƒXƒeƒ€ƒfƒBƒŒƒN
+ ƒgƒŠ‚ÌWINSOCK 2.0 ‚ɃoƒCƒ“ƒh‚³‚ê‚Ä‚¢‚邽‚ßAƒAƒvƒŠƒP[ƒVƒ‡ƒ“ƒfƒBƒŒƒN
+ ƒgƒŠ‘¤‚ÌWINSOCK 2.0 ƒ‰ƒbƒp[DLL ‚ɂ̓Šƒ_ƒCƒŒƒNƒg‚³‚ê‚Ä‚«‚Ü‚¹‚ñB‚±‚Ì
+ ‚½‚ßAƒAƒvƒŠƒP[ƒVƒ‡ƒ“ƒfƒBƒŒƒNƒgƒŠ‚ւ̃Cƒ“ƒXƒg[ƒ‹‚É‚¨‚¢‚Ä‚ÍA1.1DLLA
+ 2.0DLL‚Ì—¼•û‚ŃGƒ“ƒR[ƒfƒBƒ“ƒO‚ð•ÏŠ·‚·‚é•K—v‚ª‚ ‚è‚Ü‚·B
+
+ ‚±‚̂悤‚ÈDLL ŠÔ‚̃oƒCƒ“ƒfƒBƒ“ƒO‚̓hƒLƒ…ƒƒ“ƒg‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ‚Ì‚ÅAŠÂ
+ ‹«Aƒo[ƒWƒ‡ƒ“‚É‚æ‚Á‚Ă͈قȂÁ‚½“®ì‚ð‚·‚é‚©‚à’m‚ê‚Ü‚¹‚ñB‚»‚±‚Åidn
+ wrapper ‚Å‚ÍAƒŒƒWƒXƒgƒŠ’l‚É‚æ‚Á‚ÄAƒ‰ƒbƒp[DLL ‚Ì‚Ç‚±‚Å•ÏŠ·‚ðs‚È‚¤
+ ‚©‚ðŒˆ’è‚·‚é‚悤‚É‚µ‚ÄAƒCƒ“ƒXƒg[ƒ‹æ‚É‚æ‚é·ˆÙA‚ ‚é‚¢‚̓o[ƒWƒ‡ƒ“
+ ‚É‚æ‚é·ˆÙ‚ð‹zŽû‚·‚é‚悤‚É‚µ‚Ü‚·B
+
+ idn wrapper —p‚̃ŒƒWƒXƒgƒŠÝ’è‚Í
+
+ HKEY_LOCAL_MACHINE\SOFTWARE\JPNIC\IDN
+ HKEY_CURRENT_USER\SOFTWARE\JPNIC\IDN
+
+ ˆÈ‰º‚É”z’u‚³‚ê‚Ü‚·BƒGƒ“ƒR[ƒfƒBƒ“ƒO•ÏŠ·‚ðs‚È‚¤ˆÊ’u‚ɂ‚¢‚Ä‚ÍA‚±‚Ì
+ ’¼‰º‚̃ŒƒWƒXƒgƒŠ’l WhereiREG_DWORDj ‚É‚æ‚Á‚ÄŒˆ’肵‚Ü‚·B—LŒø‚È’l‚ÍA
+
+ ƒŒƒWƒXƒgƒŠ Where (REG_DWORD)
+
+ 0 WINSOCK 1.1AWINSOCK 2.0 ‚Ì—¼•û‚Å•ÏŠ·‚·‚é
+ 1 WINSOCK 2.0 ‚ª‚ ‚ê‚ÎAWINSOCK 2.0‚¾‚¯‚Å•ÏŠ·‚·‚é
+ WINSOCK 1.1 ‚¾‚¯‚Ìê‡‚É‚Í WINSOCK 1.1 ‚Å•ÏŠ·‚·‚é
+ 2 WINSOCK 1.1 ‚¾‚¯‚Å•ÏŠ·‚·‚é
+ 3 WINSOCK 2.0 ‚¾‚¯‚Å•ÏŠ·‚·‚é
+
+ ‚Ì‚S’Ê‚è‚Å‚·BƒAƒvƒŠƒP[ƒVƒ‡ƒ“ƒfƒBƒŒƒNƒgƒŠ‚ɃCƒ“ƒXƒg[ƒ‹‚·‚éꇂɂÍ
+ u‚Ov‚ðAƒVƒXƒeƒ€ƒfƒBƒŒƒNƒgƒŠ‚ɃCƒ“ƒXƒg[ƒ‹‚·‚éꇂɂÍu‚Pv‚ðÝ’è
+ ‚·‚é•K—v‚ª‚ ‚è‚Ü‚·BƒŒƒWƒXƒgƒŠ’l‚ª‘¶Ý‚µ‚È‚¢ê‡‚É‚Íu‚Ov‚ð‘z’肵‚Ü
+ ‚·B‚±‚ê‚̓AƒvƒŠƒP[ƒVƒ‡ƒ“ƒfƒBƒŒƒNƒgƒŠ‚ւ̃Cƒ“ƒXƒg[ƒ‹‚ð•W€‚Æ‚µ‚½‚à
+ ‚Ì‚Å‚·B
+
+2.7. •ÏŠ·Œ³/æ‚̃Gƒ“ƒNƒR[ƒfƒBƒ“ƒO
+
+ ƒ‰ƒbƒp[DLL ‚Å‚ÍA‰ðŒˆ‚µ‚悤‚Æ‚·‚éƒhƒƒCƒ“–¼‚ðAƒ}ƒVƒ“‚̃[ƒJƒ‹ƒGƒ“
+ ƒR[ƒfƒBƒ“ƒO‚©‚çDNS ƒT[ƒo‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO‚É•ÏŠ·‚µA‚Ü‚½ADNS ‚ª•Ô
+ ‚µ‚Ä‚«‚½ƒhƒƒCƒ“–¼(DNS ƒT[ƒo‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO)‚ðƒ}ƒVƒ“‚̃[ƒJƒ‹ƒGƒ“
+ ƒR[ƒfƒBƒ“ƒO‚É–ß‚µ‚Ü‚·B
+
+ Œ»ÝADNS ‘¤‚Ì‘Û‰»ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚ɂ‚¢‚Ä‚ÍA‚¢‚­‚‚à‚Ì•ûŽ®‚ª’ñ
+ ˆÄ‚³‚ê‚Ä‚¢‚Ü‚·Bƒ‰ƒbƒp[DLL ‚Í‚»‚ê‚ç‚ÌDNS ‘¤ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚Ì‚Ç‚ê‚©
+ ‚ЂƂ‚ɕϊ·‚·‚é‚悤‚É\¬‚³‚ê‚Ü‚·B‚±‚ÌDNS ‘¤ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚̓ŒƒW
+ ƒXƒgƒŠ‚ÅŽwŽ¦‚³‚ê‚Ü‚·B‚±‚̃ŒƒWƒXƒgƒŠ‚É‚ÍAidn wrapper ‚̃Cƒ“ƒXƒg[ƒ‹
+ Žž‚ÉiŒ»Žž“_‚Å‚Í–¢’è‚ÌjƒfƒtƒHƒ‹ƒgƒGƒ“ƒR[ƒfƒBƒ“ƒO‚ªÝ’肳‚ê‚Ü‚·B“–
+ ‘RA‚±‚̃ŒƒWƒXƒgƒŠ‚ÍAŒã‚Å‘¼‚Ì‚à‚Ì‚É•ÏX‚·‚邱‚Æ‚à‚Å‚«‚Ü‚·B
+
+ idn wrapper —p‚̃ŒƒWƒXƒgƒŠÝ’è‚Í
+
+ HKEY_LOCAL_MACHINE\SOFTWARE\JPNIC\IDN
+ HKEY_CURRENT_USER\SOFTWARE\JPNIC\IDN
+
+ ˆÈ‰º‚É”z’u‚³‚ê‚Ü‚·BDNS ‘¤‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO‚̓ŒƒWƒXƒgƒŠ’l Encoding
+ iREG_SZj‚ÅŽwŽ¦‚³‚ê‚Ü‚·B‚±‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO–¼‚ÍAlibmdn‚Å”FŽ¯‚³‚ê
+ ‚é‚à‚Ì‚Å‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñB
+
+ ƒŒƒWƒXƒgƒŠ Encoding (REG_SZ)
+ DNS ƒT[ƒo‘¤‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO–¼‚ðݒ肵‚Ü‚·
+
+ ˆê•ûAƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚ªŽg—p‚µ‚Ä‚¢‚éƒ[ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚ÍA’Êí
+ ‚̓vƒƒZƒX‚̃R[ƒhƒy[ƒW‚©‚ç‹‚ß‚Ü‚·Bƒ‰ƒbƒp[DLL ‚ªŽg—p‚·‚é 'iconv'
+ ƒ‰ƒCƒuƒ‰ƒŠ‚ÍAwindows ‚̃R[ƒhƒy[ƒW–¼‚ðƒGƒ“ƒR[ƒfƒBƒ“ƒO–¼‚Æ‚µ‚ÄŽó•t
+ ‚¯‚邱‚Æ‚ª‚Å‚«‚é‚Ì‚ÅAƒR[ƒhƒy[ƒW–¼‚ð‚»‚Ì‚Ü‚Üƒ[ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“
+ ƒO–¼‚Æ‚µ‚ÄŽg—p‚µ‚Ü‚·B
+
+ ‚µ‚©‚µAƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚É‚æ‚Á‚Ä‚ÍA“Á’è‚Ì‘Û‰»ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚Å
+ ƒhƒƒCƒ“–¼‚ðƒGƒ“ƒR[ƒfƒBƒ“ƒO‚µ‚Ä‚µ‚Ü‚¤‚à‚Ì‚à‚ ‚è‚Ü‚·B—Ⴆ‚ÎAIE‚Å‚Í
+ ƒhƒƒCƒ“–¼‚ðUTF-8 ‚Å•\‹L‚·‚é‚悤‚ÉŽwŽ¦‚·‚邱‚Æ‚ª‚Å‚«‚é‚悤‚É‚È‚Á‚Ä‚¢
+ ‚Ü‚·BUTF-8 ‚É‚æ‚éƒGƒ“ƒR[ƒfƒBƒ“ƒO‚ÍA’ñˆÄ‚³‚ê‚Ä‚¢‚é‘Û‰»•ûŽ®‚Ì‚Ð
+ ‚Ƃ‚ł·‚ªA‘Û‰»‚³‚ꂽDNS ƒT[ƒo‚Í‘¼‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO‚µ‚©Žó•t‚¯
+ ‚È‚¢‚©‚à’m‚ê‚Ü‚¹‚ñB
+
+ ‚±‚̂悤‚È󋵂ɑΈ‚·‚邽‚ßAidn ƒ‰ƒbƒp[‚ÍAƒ[ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“
+ ƒO‚Æ‚µ‚ăvƒƒOƒ‰ƒ€“Á—L‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO‚àŽó•t‚¯‚邱‚Æ‚ª‚Å‚«‚é‚悤‚É
+ ‚µ‚Ü‚·B‚±‚̂悤‚ȃvƒƒOƒ‰ƒ€“Á—L‚̃[ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚̓ŒƒWƒXƒg
+ ƒŠ‹LÚ‚³‚ê‚é‚à‚Ì‚Æ‚µ‚Ü‚·B
+
+ idn wrapper —p‚̃vƒƒOƒ‰ƒ€“Á—L‚̃ŒƒWƒXƒgƒŠÝ’è‚Í
+
+ HKEY_LOCAL_MACHINE\SOFTWARE\JPNIC\IDN\PerProg
+ HKEY_CURRENT_USER\SOFTWARE\JPNIC\IDN\PerProg
+
+ ˆÈ‰º‚ÉAƒvƒƒOƒ‰ƒ€–¼iŽÀsƒ‚ƒWƒ…[ƒ‹ƒtƒ@ƒCƒ‹–¼j‚ðƒL[‚Æ‚µ‚Ä”z’u‚³‚ê
+ ‚Ü‚·B—Ⴆ‚ÎAInternet Explore ‚ÌꇂɂÍAŽÀsƒ‚ƒWƒ…[ƒ‹–¼‚Ì
+ IEXPLORE‚ðƒL[‚Æ‚µ‚Ä
+
+ HKEY_LOCAL_MACHINE\SOFTWARE\JPNIC\IDN\PerProg\IEXPLORE
+
+ ˆÈ‰º‚É’u‚©‚ê‚Ü‚·Bƒ[ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“ƒO–¼‚ÍAƒŒƒWƒXƒgƒŠ’l
+ Encoding iREG_SZj‚ÅŽwŽ¦‚µ‚Ü‚·B‚±‚ê‚àlibmdn‚Å”FŽ¯‚³‚ê‚é‚à‚Ì‚Å‚È‚¯‚ê
+ ‚΂Ȃè‚Ü‚¹‚ñB
+
+ ƒŒƒWƒXƒgƒŠ Encoding (REG_SZ)
+
+ ƒAƒvƒŠƒP[ƒVƒ‡ƒ“ƒvƒƒOƒ‰ƒ€“Á—L‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO–¼iƒfƒtƒHƒ‹
+ ƒg‚̃Gƒ“ƒR[ƒfƒBƒ“ƒOˆÈŠO‚ð•K—v‚Æ‚·‚éê‡j‚ðŽw’肵‚Ü‚·B
+
+3.ƒZƒbƒgƒAƒbƒv‚ƃRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“
+
+ idn wrapper ‚ÍAŠî–{ƒCƒ“ƒXƒgƒŒ[ƒVƒ‡ƒ“‚Æ‚µ‚ÄAƒAƒvƒŠƒP[ƒVƒ‡ƒ“ƒfƒBƒŒ
+ ƒNƒgƒŠ‚ÅWINSOCK ‚ðƒ‰ƒbƒv‚µ‚Ü‚·B‚±‚ê‚ɇ‚킹‚ÄAƒZƒbƒgƒAƒbƒvƒvƒƒOƒ‰
+ ƒ€‚ƃRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒvƒƒOƒ‰ƒ€‚Æ‚ð’ñ‹Ÿ‚µ‚Ü‚·B
+
+ ’FƒVƒXƒeƒ€ƒfƒBƒŒƒNƒgƒŠ‚ł̃‰ƒbƒv‚à‰Â”\‚Å‚·‚ªA‚±‚ê‚͊댯‚ÈÝ’è‚Å‚·
+ ‚Ì‚ÅA•W€ƒCƒ“ƒXƒgƒŒ[ƒVƒ‡ƒ“‚Æ‚µ‚Ä‚Í’ñ‹Ÿ‚µ‚Ü‚¹‚ñBƒVƒXƒeƒ€ƒfƒBƒŒ
+ ƒNƒgƒŠ‚ւ̃Cƒ“ƒXƒg[ƒ‹‚ðs‚È‚¤ê‡‚É‚ÍAŽ©ŒÈÓ”C‚Å‚â‚Á‚Ä‚­‚¾‚³‚¢B
+
+3.1.ƒZƒbƒgƒAƒbƒvƒvƒƒOƒ‰ƒ€
+
+ idn wrapper ‚ðƒCƒ“ƒXƒg[ƒ‹‚·‚é‚É‚Í"setup.exe" ‚ðŽÀs‚µ‚Ü‚·BƒZƒbƒgƒAƒb
+ ƒvƒvƒƒOƒ‰ƒ€‚͈ȉº‚̈—‚ðŽÀs‚µ‚Ü‚·B
+
+ ƒtƒ@ƒCƒ‹‚̃Cƒ“ƒXƒg[ƒ‹
+
+ ƒfƒBƒŒƒNƒgƒŠu\Program Files\JPNIC\idn wrapperv i ƒZƒbƒgƒAƒbƒv
+ Žž“_‚Å•ÏX‰Â”\jˆÈ‰º‚ÉAidn wrapper ‚ð\¬‚·‚éƒtƒ@ƒCƒ‹‚ðƒRƒs[‚µ
+ ‚Ü‚·B
+
+ ƒŒƒWƒXƒgƒŠ‚ÌÝ’è
+
+ HKEY_LOCAL_MACHINE\Software\JPNIC\IDN ˆÈ‰º‚É•K—v‚ȃŒƒWƒXƒgƒŠƒL[A
+ ƒŒƒWƒXƒgƒŠ’l‚ðì¬Aݒ肵‚Ü‚·B
+
+ InstallDir REG_SZ "<ƒCƒ“ƒXƒg[ƒ‹ƒfƒBƒŒƒNƒgƒŠ>"
+ idn wrapper ‚̃Cƒ“ƒXƒg[ƒ‹ƒfƒBƒŒƒNƒgƒŠ‚̃pƒX–¼‚Å‚·BƒZƒbƒg
+ ƒAƒbƒvƒvƒƒOƒ‰ƒ€‚Í‚±‚̃fƒBƒŒƒNƒgƒŠ‚ɃIƒŠƒWƒiƒ‹‚ÌWINSOCK
+ DLL ‚̃Rƒs[‚ð쬂µ‚Ü‚·Bidn wrapper ‚̃‰ƒbƒp[ DLL ‚ÍŽÀ
+ sŽž‚É‚±‚Ì DLL ‚ðŽQÆ‚µ‚Ü‚·B
+
+ ConfFile REG_SZ "<ƒCƒ“ƒXƒg[ƒ‹ƒfƒBƒŒƒNƒgƒŠ>\idn.conf"
+ idn wrapper ‚ª‘Û‰»ƒhƒƒCƒ“–¼‚Ì•ÏŠ·ˆ—‚ÉŽg—p‚µ‚Ä‚¢‚é
+ idnkit ‚̃Rƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒtƒ@ƒCƒ‹‚Ì–¼‘O‚Å‚·B‚±‚̃tƒ@
+ ƒCƒ‹‚Í‘Û‰»ƒhƒƒCƒ“–¼‚̈—‚É•K—v‚ÈŠeŽí‚̃pƒ‰ƒ[ƒ^‚ðÝ’è
+ ‚·‚邽‚ß‚Ì‚à‚Ì‚Å‚·BÚ‚µ‚­‚̓tƒ@ƒCƒ‹‚Ì“à—e‚ð‚²——‚­‚¾‚³‚¢B
+ ‚±‚Ì’l‚ÍŒãq‚·‚éƒRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒvƒƒOƒ‰ƒ€‚Å•ÏX‚·‚é
+ ‚±‚Æ‚ª‚Å‚«‚Ü‚·B
+
+ LogFile REG_SZ "<ƒCƒ“ƒXƒg[ƒ‹ƒfƒBƒŒƒNƒgƒŠ>\idn_wrapper.log"
+ idn wrapper ‚̃ƒOƒtƒ@ƒCƒ‹‚Ì–¼‘O‚Å‚·B‚±‚Ì’l‚àƒRƒ“ƒtƒBƒMƒ…
+ ƒŒ[ƒVƒ‡ƒ“ƒvƒƒOƒ‰ƒ€‚Å•ÏX‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B
+
+ LogLevel DWORD -1
+ ƒƒOƒŒƒxƒ‹‚ÌŽw’è‚Å‚·BƒfƒtƒHƒ‹ƒg‚Í -1 ‚ÅA‚±‚ê‚Í‘S‚­ƒƒO‚ð
+ o—Í‚µ‚È‚¢‚Æ‚¢‚¤ˆÓ–¡‚Å‚·B‚±‚Ì’l‚àƒRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒv
+ ƒƒOƒ‰ƒ€‚Å•ÏX‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B
+
+ PerProg ƒL[
+
+ ƒvƒƒOƒ‰ƒ€–ˆ‚ÌÝ’è’l‚ðŠi”[‚·‚邽‚߂̃L[‚Å‚·B‚±‚̉º‚ÉAƒvƒ
+ ƒOƒ‰ƒ€‚ÌŽÀsƒ‚ƒWƒ…[ƒ‹–¼‚ðƒL[‚Æ‚µ‚ăvƒƒOƒ‰ƒ€ŒÂ•Ê‚Ìݒ肪‹L
+ ˜^‚³‚ê‚Ü‚·Bݒ肳‚ê‚éî•ñ‚͈ȉº‚Ì“ñ‚‚ł·B
+
+ PerProg\<progname>\Where REG_DWORD •ÏŠ·ˆÊ’u
+ PerProg\<progname>\Encoding REG_SZ ƒGƒ“ƒR[ƒfƒBƒ“ƒO–¼
+
+ ƒGƒ“ƒR[ƒfƒBƒ“ƒO–¼‚Í’ÊíƒRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒvƒƒOƒ‰ƒ€‚É‚æ‚Á
+ ‚Äݒ肳‚ê‚Ü‚·B•ÏŠ·ˆÊ’u‚ÍA•W€ƒCƒ“ƒXƒg[ƒ‹‚Å‚Í•s—v‚Å‚·BƒV
+ ƒXƒeƒ€ƒfƒBƒŒƒNƒgƒŠ‚ւ̃Cƒ“ƒXƒg[ƒ‹‚ðs‚È‚Á‚½ê‡‚É‚ÍAƒŒƒWƒX
+ ƒgƒŠƒGƒfƒBƒ^‚Ŋ‹«‚ɇ‚킹‚ÄÝ’è‚·‚é•K—v‚ª‚ ‚è‚Ü‚·B
+
+ ƒAƒCƒRƒ“‚Ìì¬
+
+ ƒRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒvƒƒOƒ‰ƒ€‚̃AƒCƒRƒ“‚ð쬂µAƒXƒ^[ƒgƒƒjƒ…[
+ ‚É“o˜^‚µ‚Ü‚·B‚±‚ê‚É‚æ‚Á‚ăRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒvƒƒOƒ‰ƒ€‚ð‹N“®
+ ‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B
+
+ ƒAƒ“ƒCƒ“ƒXƒg[ƒ‹‚·‚é‚É‚ÍAƒRƒ“ƒgƒ[ƒ‹ƒpƒlƒ‹‚ÌuƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚Ì’Ç
+ ‰Á‚Æíœv‚ÅAuidn wrapperv ‚ð‘I‘ð‚µ‚Äíœiu’ljÁ‚Æíœvƒ{ƒ^ƒ“j
+ ‚µ‚Ü‚·B
+
+3.2.ƒRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒvƒƒOƒ‰ƒ€
+
+ ƒRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒvƒƒOƒ‰ƒ€‚ÍAƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚ð“Á’肵‚ă‰ƒbƒv
+ ‚µ‚½‚èAƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚̃‰ƒbƒv‚ð‰ðœ‚·‚邽‚߂̃c[ƒ‹‚Å‚·B
+
+ ‹N“®‚·‚é‚ƈȉº‚̂悤‚ȉæ–Ê‚ª•\Ž¦‚³‚ê‚Ü‚·B
+
+ „¡„Ÿ„¦„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¦„Ÿ„¦„Ÿ„¦„Ÿ„¢
+ „ @„ idn wrapper - Configuration „ Q„  „ ~„ 
+ „¥„Ÿ„¨„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¨„Ÿ„¨„Ÿ„¨„Ÿ„§
+ „  idn wrapper Configuration Program version X.X „ 
+ „¥„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„§
+ „  Wrapped Program „¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „ „¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¦„Ÿ„¢„  Wrap.. „ „ 
+ „ „  „ È„ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „ „  „¥„Ÿ„§„¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „ „  „  „ „  Unwrap.. „ „ 
+ „ „  „  „ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „ „  „  „ „¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „ „  „  „ „ UnwrapAll.„ „ 
+ „ „  „  „ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „ „  „  „ „¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „ „  „  „ „ RewrapAll.„ „ 
+ „ „  „  „ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „ „  „  „ „¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „ „  „  „ „  Log.. „ „ 
+ „ „  „  „ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „ „  „  „ „¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „ „  „¥„Ÿ„§„ Advanced..„ „ 
+ „ „  „ É„ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „ „¥„Ÿ„¦„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¦„Ÿ„©„Ÿ„£„¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „ „ q„  „ r„  „  Exit „ „ 
+ „ „¤„Ÿ„¨„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¨„Ÿ„£ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£
+
+ ƒŠƒXƒgƒ{ƒbƒNƒX‚É‚ÍA‚»‚ÌŽž“_‚щƒbƒv‚³‚ê‚Ä‚¢‚éƒvƒƒOƒ‰ƒ€‚ª•\Ž¦‚³‚ê‚Ü
+ ‚·Bʼn‚ÉŽÀs‚µ‚½ê‡‚É‚Í‹ó‚É‚È‚Á‚Ä‚¢‚Ü‚·B
+
+ ƒvƒƒOƒ‰ƒ€‚ðƒ‰ƒbƒv‚·‚é‚É‚ÍA"wrap"ƒ{ƒ^ƒ“‚ð‰Ÿ‚µ‚Ü‚·B"wrap"ƒ{ƒ^ƒ“‚ð‰Ÿ
+ ‚·‚ƈȉº‚̂悤‚ȃ_ƒCƒAƒƒO‚ª•\Ž¦‚³‚ê‚Ü‚·B
+
+ „¡„Ÿ„¦„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¦„Ÿ„¦„Ÿ„¦„Ÿ„¢
+ „ @„ idn wrapper - Wrap Executable „ Q„  „ ~„ 
+ „¥„Ÿ„¨„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¨„Ÿ„¨„Ÿ„¨„Ÿ„§
+ „  „¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „  Program: „  „ „ Browse..„ „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„¤„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „  „¡„Ÿ„Ÿ„Ÿ„¢ „ 
+ „ Encoding: „  „  ›Default ›UTF-8 „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„£ „ 
+ „    Force local DLL reference „ 
+ „¥„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„§
+ „  „¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „  „  wrap „ „  cancel „ „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„Ÿ„£„¤„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£
+
+ ʼn‚ÉAƒ‰ƒbƒv‚·‚éƒvƒƒOƒ‰ƒ€‚ÌŽÀsƒtƒ@ƒCƒ‹–¼‚ðݒ肵‚Ü‚·B’¼Ú“ü—Í
+ ‚·‚é‚©Aƒuƒ‰ƒEƒYƒ{ƒ^ƒ“‚Ńtƒ@ƒCƒ‹‚ð’T‚µ‚Ä‚­‚¾‚³‚¢BŽŸ‚É‚»‚̃vƒƒOƒ‰
+ ƒ€‚̃[ƒJƒ‹ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚ðŽw’肵‚Ü‚·B’Êí‚ÍuDefaultv ‚Å‚©‚Ü
+ ‚¢‚Ü‚¹‚ñBƒvƒƒOƒ‰ƒ€‚ª‘Û‰»ƒGƒ“ƒR[ƒfƒBƒ“ƒO‚É]‚Á‚Ä‚¢‚éꇂɂ̂Ý
+ uUTF-8v ‚ðŽwŽ¦‚µ‚Ü‚·B
+
+ uForce local DLL referencevƒ{ƒ^ƒ“‚É‚æ‚èAƒ‰ƒbƒv‚·‚éƒvƒƒOƒ‰ƒ€‚Ì
+ DLL ‚Ì’Tõ‡˜‚ð•ÏX‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚· (‚½‚¾‚µ Windows95 ‚É‚Í‚±‚Ì
+ ‹@”\‚ª‚È‚¢‚½‚ßA‚±‚̃{ƒ^ƒ“‚à•\Ž¦‚³‚ê‚Ü‚¹‚ñ)B‚±‚̃{ƒ^ƒ“‚ðƒ`ƒFƒbƒN
+ ‚·‚é‚ÆA‚½‚Æ‚¦ƒvƒƒOƒ‰ƒ€‚ª•Ê‚ÌêŠ‚Ì DLL ‚ðŽw’肵‚Ä‚¢‚Ä‚àAí‚ÉŽÀ
+ sƒtƒ@ƒCƒ‹‚ª‚ ‚éƒfƒBƒŒƒNƒgƒŠ‚Ì DLL ‚ª—D悳‚ê‚é‚悤‚É‚È‚è‚Ü‚·B‚à
+ ‚µƒvƒƒOƒ‰ƒ€‚ª‚¤‚Ü‚­ƒ‰ƒbƒv‚Å‚«‚È‚¢ê‡‚É‚ÍA‚±‚̃{ƒ^ƒ“‚ðƒ`ƒFƒbƒN‚·
+ ‚é‚Æ‚¤‚Ü‚­‚¢‚­‚©‚à‚µ‚ê‚Ü‚¹‚ñB‚½‚¾‚µ“¯Žž‚É‘¼‚Ì–â‘肪”­¶‚·‚é‰Â”\«
+ ‚à‚ ‚è‚Ü‚·B
+
+ ÅŒã‚Éuwrapvƒ{ƒ^ƒ“‚ð‰Ÿ‚¹‚ÎAƒvƒƒOƒ‰ƒ€‚ªAŽw’肳‚ꂽƒGƒ“ƒR[ƒfƒB
+ ƒ“ƒO‚щƒbƒv‚³‚ê‚Ü‚·Bƒ‰ƒbƒv‚³‚ꂽƒvƒƒOƒ‰ƒ€‚ÍAʼn‚̃EƒBƒ“ƒhƒE‚Ì
+ ƒŠƒXƒgƒ{ƒbƒNƒX‚É”½‰f‚³‚ê‚Ü‚·B
+
+ idn wrapper ‚ðƒo[ƒWƒ‡ƒ“ƒAƒbƒv‚µ‚½ê‡‚É‚ÍAƒ‰ƒbƒv—p‚Ì DLL ‚ðƒAƒbƒv
+ ƒf[ƒg‚·‚邽‚ß‚ÉAƒvƒƒOƒ‰ƒ€‚ðă‰ƒbƒv‚·‚é•K—v‚ª‚ ‚è‚Ü‚·B‚±‚Ì‚½‚ß‚ÉA
+ Œ»Ýƒ‰ƒbƒv‚³‚ê‚Ä‚¢‚éƒvƒƒOƒ‰ƒ€‚ɑ΂µ‚ÄÄ“xƒ‰ƒbƒv‚ðs‚¤‚½‚ß‚Ìurewrap
+ allvƒ{ƒ^ƒ“‚ª—pˆÓ‚³‚ê‚Ä‚¢‚Ü‚·B
+
+ ƒvƒƒOƒ‰ƒ€‚ɑ΂·‚郉ƒbƒv‚ð‰ðœ‚·‚é‚É‚ÍAƒŠƒXƒgƒ{ƒbƒNƒX‚ʼn𜂷‚éƒvƒ
+ ƒOƒ‰ƒ€‚ð‘I‘ð‚µ‚ÄAuunwrapvƒ{ƒ^ƒ“‚ð‰Ÿ‚µ‚Ü‚·BˆÈ‰º‚ÌŠm”F—p‚̃_ƒCƒAƒ
+ ƒO‚ª•\Ž¦‚³‚ê‚Ü‚·‚Ì‚ÅAŠÔˆá‚¢‚ª‚È‚¯‚ê‚Îuunwrapvƒ{ƒ^ƒ“‚ð‰Ÿ‚µ‚Ä‚­‚¾‚³
+ ‚¢B
+
+ „¡„Ÿ„¦„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¦„Ÿ„¦„Ÿ„¦„Ÿ„¢
+ „ @„ idn wrapper - Unwrap Executable „ Q„  „ ~„ 
+ „¥„Ÿ„¨„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¨„Ÿ„¨„Ÿ„¨„Ÿ„§
+ „  „¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „ Program: „  „ „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „¥„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„§
+ „  „¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „  „  Unwrap „ „  Cancel „ „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„Ÿ„£„¤„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£
+
+ ƒ‰ƒbƒv‚ª‰ðœ‚³‚ê‚é‚ÆA‚»‚̃vƒƒOƒ‰ƒ€‚Íʼn‚̃EƒBƒ“ƒhƒE‚̃ŠƒXƒgƒ{ƒbƒN
+ ƒX‚©‚ç‚à휂³‚ê‚Ü‚·B
+
+ ƒvƒƒOƒ‰ƒ€‚ɑ΂µ‚ÄŒ»Ýݒ肳‚ê‚Ä‚¢‚郉ƒbƒv‚ð‚·‚×‚Ä‰ðœ‚·‚邽‚ß‚Ì
+ uunwrap allvƒ{ƒ^ƒ“‚à—pˆÓ‚³‚ê‚Ä‚¢‚Ü‚·B
+
+ ƒƒO‚ÌÝ’è‚ðs‚¤‚É‚ÍA"log" ƒ{ƒ^ƒ“‚ð‰Ÿ‚µ‚Ü‚·BŽŸ‚̂悤‚ȃ_ƒCƒAƒƒO‚ª
+ •\Ž¦‚³‚ê‚Ü‚·B
+
+ „¡„Ÿ„¦„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¦„Ÿ„¦„Ÿ„¦„Ÿ„¢
+ „ @„ idn wrapper - Log Configuration „ Q„  „ ~„ 
+ „¥„Ÿ„¨„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¨„Ÿ„¨„Ÿ„¨„Ÿ„§
+ „  Log Level: ›None ›Fatal ›Error ›Warning ›Info ›Trace „ 
+ „  „¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „  Log File:„  „ „ Browse..„ „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„¤„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „  „¡„Ÿ„Ÿ„Ÿ„¢ „¡„Ÿ„Ÿ„Ÿ„¢ „ 
+ „ Log Operation:„  View „  „ Delete„  „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„£ „¤„Ÿ„Ÿ„Ÿ„£ „ 
+ „¥„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„§
+ „  „¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „  „  OK „ „  Cancel „ „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„Ÿ„£„¤„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£
+
+ ƒƒOƒŒƒxƒ‹‚ÍŽŸ‚Ì’†‚©‚ç‘I‘ð‚·‚é‚±‚Æ‚ª‚Å‚«‚Ü‚·B
+ None ƒƒO‚ðo—Í‚µ‚È‚¢
+ Fatal ’v–½“IƒGƒ‰[‚Ì‚Ý‹L˜^‚·‚é
+ Error ’v–½“I‚Å‚È‚¢ƒGƒ‰[‚à‹L˜^‚·‚é
+ Warning ŒxƒƒbƒZ[ƒW‚à‹L˜^‚·‚é
+ Info ‚»‚Ì‘¼‚Ìî•ñ‚à‹L˜^‚·‚é
+ Trace ƒgƒŒ[ƒXo—Í‚à‹L˜^‚·‚é
+ ‚±‚±‚É‚ ‚°‚½ƒƒOƒŒƒxƒ‹‚ÌÝ’è‚ÍAIDN ƒ‰ƒCƒuƒ‰ƒŠ (idnkit.dll) ‚ªo—Í‚·‚é
+ ƒƒO‚ɑ΂µ‚Ä‚Ì‚Ý—LŒø‚Å‚·Bidn wrapper Ž©g‚ªo—Í‚·‚郃O‚Í ON/OFF
+ ‚µ‚©‚Å‚«‚Ü‚¹‚ñBNone ‚ðŽw’è‚·‚é‚Æ OFF ‚ÉA‚»‚êˆÈŠO‚̃Œƒxƒ‹‚ðŽw’è‚·‚é‚Æ
+ ON ‚É‚È‚è‚Ü‚·B
+
+ ‚±‚̃_ƒCƒAƒƒO‚ð—p‚¢‚ÄAƒƒOƒtƒ@ƒCƒ‹‚̃pƒX–¼‚ðŽw’è‚·‚邱‚Æ‚à‚Å‚«‚Ü‚·B
+
+ ‚Ü‚½AƒƒOƒtƒ@ƒCƒ‹‚Ì“à—e‚ð•\Ž¦‚³‚¹‚½‚èAƒƒOƒtƒ@ƒCƒ‹‚ð휂·‚邱‚Æ‚à
+ ‰Â”\‚Å‚·B
+
+ ƒƒOƒŒƒxƒ‹‚⃃Oƒtƒ@ƒCƒ‹‚ÌÝ’è‚ÍAݒ莞‚É‚·‚Å‚É“®ì‚µ‚Ä‚¢‚éƒvƒƒZƒX
+ ‚ɂ͉e‹¿‚ð—^‚¦‚È‚¢‚±‚Æ‚É‹C‚ð‚‚¯‚Ä‚­‚¾‚³‚¢B
+
+ "advanced" ƒ{ƒ^ƒ“‚ð‰Ÿ‚·‚Æuadvanced configurationv—p‚̃_ƒCƒAƒƒO
+ ‚ª•\Ž¦‚³‚ê‚Ü‚·B‚±‚̃_ƒCƒAƒƒO‚Í㋉ƒ†[ƒU‚Ì‚½‚ß‚Ì‚à‚Ì‚ÅA“K؂ȃf
+ ƒtƒHƒ‹ƒg‚ªÝ’肳‚ê‚Ä‚¢‚邽‚ß‚É’Ê탆[ƒU‚ª•ÏX‚·‚é•K—v‚Ì‚È‚¢‚悤‚È
+ Šî–{“I‚ȃpƒ‰ƒ[ƒ^‚ð•ÏX‚·‚邱‚Æ‚ª‚Å‚«‚Ü‚·B
+
+ „¡„Ÿ„¦„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¦„Ÿ„¦„Ÿ„¦„Ÿ„¢
+ „ @„ idn wrapper - Advanced Configuration „ Q„  „ ~„ 
+ „¥„Ÿ„¨„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¨„Ÿ„¨„Ÿ„¨„Ÿ„§
+ „  IDN Wrapping Mode „ 
+ „  ›Wrap both WINSOCK 1.1 and WINSOCK 2.0 „ 
+ „  ›Wrap only WINSOCK 1.1 „ 
+ „  ›Wrap only WINSOCK 2.0 „ 
+ „  ›Wrap only WINSOCK 2.0 if it exists. „ 
+ „  Otherwise wrap only WINSOCK 1.1 „ 
+ „¥„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„§
+ „  IDN Configuration „ 
+ „  „¡„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„¢„¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „  Log File:„  „ „ Browse..„ „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£„¤„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „  „¡„Ÿ„Ÿ„Ÿ„¢ „ 
+ „  „  Edit „  „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„£ „ 
+ „¥„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„§
+ „  „¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„¡„Ÿ„Ÿ„Ÿ„Ÿ„¢„ 
+ „  „  OK „ „  Cancel „ „ 
+ „  „¤„Ÿ„Ÿ„Ÿ„Ÿ„£„¤„Ÿ„Ÿ„Ÿ„Ÿ„£„ 
+ „¤„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„Ÿ„£
+
+ ‚±‚̃_ƒCƒAƒƒO‚ðŽg—p‚µ‚ÄAŽŸ‚Ì3Ží—Þ‚ÌÝ’è‚ðs‚¤‚±‚Æ‚ª‚Å‚«‚Ü‚·B
+
+ Wrapping Mode
+ ƒ‰ƒbƒv•û–@‚ðݒ肵‚Ü‚·B’Êí‚̓fƒtƒHƒ‹ƒg‚Åݒ肳‚ê‚Ä‚¢‚逖ڂð
+ ‘I‘ð‚µ‚Ä‚¨‚¯‚΂悢‚Í‚¸‚Å‚·‚ªA–â‘肪‹N‚Á‚½‚Æ‚«‚É‚Í•Ê‚Ì€–Ú‚É‚·
+ ‚é‚Æ“®‚­‚悤‚É‚È‚é‚©‚à‚µ‚ê‚Ü‚¹‚ñB
+
+ IDN Configuration
+ ƒRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒtƒ@ƒCƒ‹–¼‚ðŽw’肵‚Ü‚·B‚Ü‚½ "Edit" ƒ{ƒ^
+ ƒ“‚ð‰Ÿ‚·‚±‚Æ‚É‚æ‚èAƒtƒ@ƒCƒ‹‚Ì“à—e‚ð•ÒW‚·‚邱‚Æ‚à‰Â”\‚Å‚·B
+
+4. §ŒÀŽ–€
+
+4.1. DLL ƒo[ƒWƒ‡ƒ“
+
+ ƒ‰ƒbƒp[DLL ‚ÍAŒ³‚ÌWINSOCK ‚ÌDLL ‚̃o[ƒWƒ‡ƒ“‚É‹­‚­ˆË‘¶‚µ‚Ü‚·B‚±‚ê
+ ‚ÍA”ñŒöŠJ‚̃Gƒ“ƒgƒŠ‚àŠÜ‚ß‚Ä‚·‚ׂẴGƒ“ƒgƒŠ‚ð’ñ‹Ÿ‚·‚é•K—v‚ª‚ ‚邽‚ß
+ ‚Å‚·B‚±‚Ì‚½‚ßWINSOCK DLL ‚̃o[ƒWƒ‡ƒ“‚ª•Ï‚í‚é‚ÆAidn wrapper ‚ª“®ì
+ ‚µ‚È‚­‚È‚é‰Â”\«‚ª‚ ‚è‚Ü‚·B
+
+ ¡‰ñ쬂³‚ꂽidn wrapper ‚ÍA
+
+ Win2000 (WINSOCK 1.1 + 2.0)
+ WinME (WINSOCK 1.1 + 2.0)
+
+ ‚Å“®ì‚ðŠm”F‚µ‚Ä‚¢‚Ü‚·B‚½‚¾A«—ˆ‚ɂ킽‚Á‚Ä“®ì‚·‚é•ÛØ‚Í‚ ‚è‚Ü‚¹‚ñB
+
+4.2. DNS, WINS, LMHOSTS
+
+ Windows ‚Å‚ÍADNS ‚¾‚¯‚Å‚Í‚È‚­AWINS‚âLMHOSTS ‚É‚æ‚Á‚Ä‚àƒhƒƒCƒ“–¼A
+ ƒzƒXƒg–¼‚Ì‰ðŒˆ‚ªs‚È‚í‚ê‚Ü‚·Bidn wrapper ‚ðŽg‚Á‚½ê‡‚É‚ÍAƒhƒƒCƒ“
+ –¼‚Ì•ÏŠ·‚ªA‚±‚ê‚ç‚Ì•ûŽ®‚ւ̃fƒBƒXƒpƒbƒ`‚ðs‚È‚¤êŠ‚æ‚è‚àãˆÊ‘w‚Ås
+ ‚È‚í‚ê‚é‚Ì‚ÅA‚±‚ê‚ç‚Ì‚·‚ׂĂ̕ûŽ®‚ɂ‚¢‚ÄAƒhƒƒCƒ“–¼AƒzƒXƒg–¼‚Ì•Ï
+ Š·‚ªs‚È‚í‚ê‚邱‚Æ‚É‚È‚è‚Ü‚·B‚±‚Ì‚½‚ßAWindows ‚ªAWINS‚âLMHOSTS ‚ð
+ Žg‚Á‚Ä‚¢‚éꇂɂÍA—\Šú‚µ‚È‚¢–â‘肪”­¶‚·‚é‰Â”\«‚ª‚ ‚è‚Ü‚·B‚±‚ê‚É
+ ‚‚¢‚Ä‚ÍAidn wrapper ‚ðŽg‚¤ê‡‚É‚ÍA–¼‘O‰ðŒˆ‚ÉDNS ‚¾‚¯‚ðŽg—p‚·‚邱
+ ‚Æ‚ð‚¨Š©‚ß‚µ‚Ü‚·B
+
+3.3. ƒhƒƒCƒ“–¼ˆÈŠO‚Ì–¼‘O‚̉ðŒˆ
+
+ WINSOCK 2.0 ‚Ì–¼‘O‰ðŒˆAPI
+
+ WSALookupServiceBeginA
+ WSALookupServiceNextA
+ WSALookupServiceEnd
+
+ ‚ÍAƒhƒƒCƒ“–¼ˆÈŠO‚Å‚àŽg—p‚Å‚«‚éA”Ä—p‚Ì–¼‘O‰ðŒˆ—p‚ÌAPI ‚Æ‚µ‚Ä’è‹`‚³
+ ‚ê‚Ä‚¢‚Ü‚·BŒ»Žž“_‚Å‚ÍA‚±‚ê‚ç‚Í‚à‚Á‚Ï‚çƒhƒƒCƒ“–¼‚Ì‰ðŒˆ‚ÅŽg—p‚³‚ê‚Ä
+ ‚¢‚Ü‚·‚ªA‘¼‚Ì–¼‘O(—Ⴆ‚΃T[ƒrƒX–¼)‚Ì‰ðŒˆ‚É‚àŽg—p‚Å‚«‚邱‚Æ‚É‚È‚Á‚Ä
+ ‚¢‚Ü‚·B
+
+ idn wrapper ‚ÍA–¼‘O‚Ì‘ÎÛ‚Ì”@‰½‚É‚©‚©‚í‚炸A–¼‘O‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO
+ ‚ð•ÏŠ·‚µ‚Ä‚µ‚Ü‚¤‚Ì‚ÅA‚±‚ê‚ç‚ÌAPI ‚ªAƒhƒƒCƒ“–¼ˆÈŠO‚Ì‰ðŒˆ‚ÉŽg‚í‚ê‚Ä
+ ‚¢‚éꇂɂÍA–â‘è‚ðˆø‚«‹N‚±‚·‰Â”\«‚ª‚ ‚è‚Ü‚·B
+
+4.4. –¼‘O‰ðŒˆAPI ‚ðŽg‚í‚È‚¢ƒvƒƒOƒ‰ƒ€
+
+ ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚É‚æ‚Á‚Ä‚ÍAƒhƒƒCƒ“–¼‚Ì‰ðŒˆ‚É‚±‚ê‚ç‚ÌAPI ‚ðŽg—p‚µ‚È
+ ‚¢‚à‚Ì‚à‚ ‚è‚Ü‚·B—Ⴆ‚ÎA'nslookup'‚ÍA‚±‚ê‚ç‚ÌAPI ‚ðŽg—p‚µ‚È‚¢‚ÅA
+ ’¼ÚDNS ƒT[ƒo‚Æ’ÊM‚µ‚Ä‚µ‚Ü‚¢‚Ü‚·B‚±‚̂悤‚ȃAƒvƒŠƒP[ƒVƒ‡ƒ“‚ɂ‚¢
+ ‚Ä‚ÍAidn wrapper ‚Í–ð‚É—§‚¿‚Ü‚¹‚ñB
+
+4.5. “Á’èWINSOCK DLL ‚ɃoƒCƒ“ƒh‚³‚ꂽƒAƒvƒŠƒP[ƒVƒ‡ƒ“
+
+ ƒAƒvƒŠƒP[ƒVƒ‡ƒ“‚É‚æ‚Á‚Ä‚ÍA•W€‚ÌDLL ƒT[ƒ`ƒpƒX‚É]‚í‚È‚¢‚ÅA“Á’è‚Ì
+ ƒpƒX‚ÌDLL ‚ɃoƒCƒ“ƒh‚³‚ê‚Ä‚¢‚é‚à‚Ì‚ª‚ ‚è‚Ü‚·B‚æ‚­Žg‚í‚ê‚éƒvƒƒOƒ‰ƒ€
+ ‚Ì’†‚Å‚ÍANetscape Communicator ‚ª‚»‚¤‚È‚Á‚Ä‚¢‚Ü‚·B‚±‚̂悤‚ȃvƒƒO
+ ƒ‰ƒ€‚ɂ‚¢‚Ä‚ÍA•W€‚̃Cƒ“ƒXƒg[ƒ‹^ƒRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“‚ł̓‰ƒbƒv
+ ‚·‚邱‚Æ‚Í‚Å‚«‚Ü‚¹‚ñB
+
+ ‚±‚̂悤‚ȃvƒƒOƒ‰ƒ€‚ɂ‚¢‚ÄA‚Ç‚¤‚µ‚Ä‚àƒ‰ƒbƒv‚·‚é•K—v‚ª‚ ‚é‚È‚çAƒV
+ ƒXƒeƒ€ƒfƒBƒŒƒNƒgƒŠ‚ւ̃Cƒ“ƒXƒg[ƒ‹‚ðs‚È‚¤‚±‚Æ‚ª‚Å‚«‚Ü‚·B‚½‚¾‚µA‚±
+ ‚̃Cƒ“ƒXƒg[ƒ‹‚Í‘å•ÏŠëŒ¯‚ÅAꇂɂæ‚Á‚Ă̓VƒXƒeƒ€‚ðÄ‹N“®•s”\‚É‚µ‚Ä
+ ‚µ‚Ü‚¤‰Â”\«‚à‚ ‚è‚Ü‚·B
+
+5. ƒŒƒWƒXƒgƒŠÝ’è - ‚Ü‚Æ‚ß
+
+5.1. ƒŒƒWƒXƒgƒŠ‚Ì—D懈Ê
+
+ idn wrapper ‚ÌÝ’èî•ñ‚ÍAHKEY_LOCAL_MACHINEAHKEY_CURRENT_USER‚Ì
+
+ Software\JPNIC\IDN
+
+ ˆÈ‰º‚ÉŠi”[‚³‚ê‚Ü‚·Bidn wrapper‚Íʼn‚ÉHKEY_LOCAL_MACHINE‚ÌÝ’è‚ð“Ç
+ ‚Ýž‚ÝAHKEY_CURRENT_USER‘¤‚É‚àݒ肪‚ ‚ê‚ÎA‚±‚ê‚Åã‘‚«‚µ‚Ü‚·B’Ê
+ í‚ÍAHKEY_LOCAL_MACHINE ‘¤‚¾‚¯‚ðݒ肵‚Ü‚·Bƒ†[ƒUŒÂ•Ê‚ɈقȂÁ‚½Ý
+ ’è‚ðŽg‚¢‚½‚¢ê‡‚Ì‚ÝAHKEY_CURRENT_USER‚ðÝ’è‚·‚é‚悤‚É‚µ‚Ä‚­‚¾‚³‚¢B
+
+ ‚È‚¨AƒRƒ“ƒtƒBƒMƒ…ƒŒ[ƒVƒ‡ƒ“ƒvƒƒOƒ‰ƒ€‚Í HKEY_LOCAL_MACHINE ‚ÌÝ’è
+ ‚¾‚¯‚ð“Ç‚Ý‘‚«‚·‚é‚悤‚É‚È‚Á‚Ä‚¢‚Ü‚·B
+
+4.2. ƒŒƒWƒXƒgƒŠƒL[
+
+ ‘S‘Ì‚Ì‹¤’Ê‚ÌÝ’è‚ÆAƒvƒƒOƒ‰ƒ€ŒÂ•ÊÝ’è‚Æ‚ª‚ ‚è‚Ü‚·B
+
+Q‹¤’Ê’è‹`
+
+ Software\JPNIC\IDN\InstallDir ƒCƒ“ƒXƒg[ƒ‹ƒfƒBƒŒƒNƒgƒŠ
+ Software\JPNIC\IDN\Where •ÏŠ·ˆÊ’u
+ 0:WINSOCK1.1 WINSOCK2.0‚Ì—¼•û‚Å
+ 1:WINSOCK2.0 ‚ª‚ ‚ê‚΂»‚¿‚ç‚Å
+ 2:WINSOCK1.1 ‚¾‚¯‚Å
+ 3:WINSOCK2.0 ‚¾‚¯‚Å
+ Software\JPNIC\IDN\ConfFile idnkit ‚ÌÝ’èƒtƒ@ƒCƒ‹
+ Software\JPNIC\IDN\LogLevel ƒƒOƒŒƒxƒ‹
+ Software\JPNIC\IDN\LogFile ƒƒOƒtƒ@ƒCƒ‹
+
+QƒvƒƒOƒ‰ƒ€ŒÂ•ÊÝ’è
+
+ •ÏŠ·ˆÊ’uA‚¨‚æ‚уvƒƒOƒ‰ƒ€‘¤‚̃Gƒ“ƒR[ƒfƒBƒ“ƒO‚̓vƒƒOƒ‰ƒ€–ˆ‚É“Á’è‚·
+ ‚邱‚Æ‚à‚Å‚«‚Ü‚·B‚±‚ê‚ç‚ÍAˆÈ‰º‚̃L[ƒnƒCƒu‚̉º‚ÉAƒvƒƒOƒ‰ƒ€–¼‚ðƒL[
+ ‚Æ‚·‚é’l‚Åݒ肵‚Ü‚·B
+
+ Software\JPNIC\IDN\PerProg\<name>\Where
+ Software\JPNIC\IDN\PerProg\<name>\Encoding
+
+ Žw’肳‚ê‚Ä‚¢‚È‚¢ê‡‚É‚ÍA
+
+ Where 0 1.1A2.0 ‚Ì—¼•û‚Å•ÏŠ·
+ Encoding ƒvƒƒZƒX‚̃R[ƒhƒy[ƒW
+
+ ‚Æ‚Ý‚È‚µ‚Ü‚·B
+
diff --git a/contrib/idn/idnkit-1.0-src/wsock/common/checkdll.c b/contrib/idn/idnkit-1.0-src/wsock/common/checkdll.c
new file mode 100644
index 0000000..a620cc9
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/common/checkdll.c
@@ -0,0 +1,242 @@
+/*
+ * checkdll.c - Winsock DLL/IDN processing status
+ */
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "wrapcommon.h"
+
+static int winsock_idx; /* index of winsock_info[] */
+
+static struct winsock_type {
+ char *version; /* winsock version */
+ char *name; /* wrapper DLL name */
+ char *original_name; /* original DLL name */
+} winsock_info[] = {
+#define IDN_IDX_WS11 0
+ { "1.1", "WSOCK32", "WSOCK32O" },
+#define IDN_IDX_WS20 1
+ { "2.0", "WS2_32", "WS2_32O" },
+ { NULL, NULL, NULL },
+};
+
+static HINSTANCE load_original_dll(void);
+static BOOL check_idn_processing(void);
+static BOOL check_dll(const char *name);
+
+BOOL
+idnWinsockVersion(const char *version) {
+ int i;
+ for (i = 0; winsock_info[i].version != NULL; i++) {
+ if (strcmp(winsock_info[i].version, version) == 0) {
+ winsock_idx = i;
+ idnLogPrintf(idn_log_level_trace,
+ "idnWinsockVersion: version %s\n",
+ version);
+ return (TRUE);
+ }
+ }
+ idnLogPrintf(idn_log_level_fatal,
+ "idnWinsockVersion: unknown winsock version %s\n",
+ version);
+ return (FALSE);
+}
+
+HINSTANCE
+idnWinsockHandle(void) {
+ static HINSTANCE dll_handle = NULL;
+ static int initialized = 0;
+
+ if (!initialized) {
+ /* Get the handle of the original winsock DLL */
+ idnLogPrintf(idn_log_level_trace,
+ "idnWinsockHandle: loading original DLL..\n");
+ dll_handle = load_original_dll();
+ }
+ initialized = 1;
+ return (dll_handle);
+}
+
+idn_resconf_t
+idnGetContext(void) {
+ static int initialized = 0;
+ static idn_resconf_t ctx = NULL;
+
+ if (!initialized) {
+ /*
+ * Check whether IDN processing should be done
+ * in this wrapper DLL.
+ */
+ idnLogPrintf(idn_log_level_trace,
+ "idnGetContext: checking IDN status..\n");
+ if (check_idn_processing()) {
+ /* Initialize idnkit */
+ ctx = idnConvInit();
+ idnLogPrintf(idn_log_level_info,
+ "Processing context: %08x\n", ctx);
+ } else {
+ idnLogPrintf(idn_log_level_info,
+ "NOT process IDN here\n");
+ ctx = NULL;
+ }
+ initialized = 1;
+ }
+
+ return (ctx);
+}
+
+static HINSTANCE
+load_original_dll(void) {
+ /*
+ * Load Original DLL
+ */
+ char dllpath[MAX_PATH];
+ const char *dll_name = winsock_info[winsock_idx].original_name;
+ HINSTANCE handle;
+
+ /*
+ * Get idn wrapper's install directory, where the copies of
+ * the original winsock DLLs are saved.
+ */
+ dllpath[0] = '\0';
+ if (idnGetInstallDir(dllpath, sizeof(dllpath)) != TRUE) {
+ idnLogPrintf(idn_log_level_fatal,
+ "idnWinsockHandle: cannot find idn wrapper's "
+ "install directory\n");
+ abort();
+ return (NULL); /* for lint */
+ }
+ /* Strip the trailing backslash. */
+ if (dllpath[0] != '\0' &&
+ dllpath[strlen(dllpath) - 1] == '\\') {
+ dllpath[strlen(dllpath) - 1] = '\0';
+ }
+ /* Is the pathname is insanely long? */
+ if (strlen(dllpath) + strlen(dll_name) + 1 + 4 >= sizeof(dllpath)) {
+ idnLogPrintf(idn_log_level_fatal,
+ "idnWinsockHandle: idn wrapper's install path is "
+ "too long to be true\n");
+ abort();
+ return (NULL); /* for lint */
+ }
+ /* Append the DLL name to form a full pathname of the DLL. */
+ strcat(dllpath, "\\");
+ strcat(dllpath, dll_name);
+ strcat(dllpath, ".DLL");
+
+ idnLogPrintf(idn_log_level_trace,
+ "idnWinsockHandle: loading original winsock DLL (%s)\n",
+ dllpath);
+ if ((handle = LoadLibrary(dllpath)) == NULL) {
+ idnLogPrintf(idn_log_level_fatal,
+ "idnWinsockHandle: no DLL %-.100s\n", dllpath);
+ abort();
+ return (NULL); /* font lint */
+ }
+ return (handle);
+}
+
+static BOOL
+check_idn_processing(void) {
+ int where = idnEncodeWhere();
+ BOOL here = FALSE;
+
+ idnLogPrintf(idn_log_level_trace,
+ "idnGetContext: Winsock%s, where=%d\n",
+ winsock_info[winsock_idx].version, where);
+
+ switch (winsock_idx) {
+ case IDN_IDX_WS11:
+ switch (where) {
+ case IDN_ENCODE_ALWAYS:
+ case IDN_ENCODE_ONLY11:
+ return (TRUE);
+ case IDN_ENCODE_CHECK:
+ if (!check_dll(winsock_info[winsock_idx].name)) {
+ return (TRUE);
+ }
+ break;
+ }
+ break;
+ case IDN_IDX_WS20:
+ switch (where) {
+ case IDN_ENCODE_ALWAYS:
+ case IDN_ENCODE_ONLY20:
+ case IDN_ENCODE_CHECK:
+ return (TRUE);
+ break;
+ }
+ break;
+ }
+ return (FALSE);
+}
+
+static BOOL
+check_dll(const char *name) {
+ HINSTANCE hdll = NULL;
+
+#if 1
+ hdll = LoadLibrary(name);
+#else
+ /*
+ * Just check the existence of the named DLL, without taking
+ * the trouble of calling DllMain.
+ */
+ hdll = LoadLibraryEx(name, NULL, LOAD_LIBRARY_AS_DATAFILE);
+#endif
+ if (hdll == NULL) {
+ idnLogPrintf(idn_log_level_trace,
+ "idnGetContext: DLL %s does not exist\n");
+ return (FALSE);
+ } else {
+ idnLogPrintf(idn_log_level_trace,
+ "idnGetContext: DLL %s exists\n");
+ FreeLibrary(hdll);
+ return (TRUE);
+ }
+}
diff --git a/contrib/idn/idnkit-1.0-src/wsock/common/convert.c b/contrib/idn/idnkit-1.0-src/wsock/common/convert.c
new file mode 100644
index 0000000..b2c202e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/common/convert.c
@@ -0,0 +1,180 @@
+/*
+ * convert.c - convert domain name
+ */
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wrapcommon.h"
+
+/*
+ * prepare/dispose conversion context
+ */
+
+void
+idnConvDone(idn_resconf_t ctx)
+{
+ if (ctx != NULL) {
+ idnLogReset();
+ idn_resconf_destroy(ctx);
+ }
+}
+
+idn_resconf_t
+idnConvInit(void)
+{
+ char encoding[256];
+ idn_resconf_t ctx;
+ idn_result_t r;
+
+ idnLogReset();
+
+ idnLogPrintf(idn_log_level_info, "idnkit version: %-.20s\n",
+ idn_version_getstring());
+
+ /*
+ * Initialize.
+ */
+ if ((r = idn_resconf_initialize()) != idn_success) {
+ idnPrintf("idnConvInit: cannot initialize idn library: %s\n",
+ idn_result_tostring(r));
+ return NULL;
+ }
+ if ((r = idn_resconf_create(&ctx)) != idn_success) {
+ idnPrintf("idnConvInit: cannot create context: %s\n",
+ idn_result_tostring(r));
+ return NULL;
+ }
+ /*
+ * load configuration file.
+ */
+ if ((r = idn_resconf_loadfile(ctx, NULL)) != idn_success) {
+ idnPrintf("idnConvInit: cannot read configuration file: %s\n",
+ idn_result_tostring(r));
+ if ((r = idn_resconf_setdefaults(ctx)) != idn_success) {
+ idnPrintf("idnConvInit: setting default configuration"
+ " failed: %s\n",
+ idn_result_tostring(r));
+ idnConvDone(ctx);
+ return (NULL);
+ }
+ idnPrintf("idnConvInit: using default configuration\n");
+ }
+ /*
+ * Set local codeset.
+ */
+ if (idnGetPrgEncoding(encoding, sizeof(encoding)) == TRUE) {
+ idnPrintf("Encoding PRG <%-.100s>\n", encoding);
+ r = idn_resconf_setlocalconvertername(ctx, encoding,
+ IDN_CONVERTER_RTCHECK);
+ if (r != idn_success) {
+ idnPrintf("idnConvInit: invalid local codeset "
+ "\"%-.100s\": %s\n",
+ encoding, idn_result_tostring(r));
+ idnConvDone(ctx);
+ return NULL;
+ }
+ }
+ return ctx;
+}
+
+/*
+ * idnConvReq - convert domain name in a DNS request
+ *
+ * convert local encoding to DNS encoding
+ */
+
+BOOL
+idnConvReq(idn_resconf_t ctx, const char FAR *from, char FAR *to, size_t tolen)
+{
+ idn_result_t r;
+
+ idnLogReset();
+
+ idnLogPrintf(idn_log_level_trace, "idnConvReq(from=%-.100s)\n", from);
+ if (ctx == NULL) {
+ idnLogPrintf(idn_log_level_trace, "idnConvReq: ctx is NULL\n");
+ if (strlen(from) >= tolen)
+ return FALSE;
+ strcpy(to, from);
+ return TRUE;
+ }
+
+ r = idn_res_encodename(ctx, IDN_ENCODE_APP, from, to, tolen);
+
+ if (r == idn_success) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/*
+ * idnConvRsp - convert domain name in a DNS response
+ *
+ * convert DNS encoding to local encoding
+ */
+
+BOOL
+idnConvRsp(idn_resconf_t ctx, const char FAR *from, char FAR *to, size_t tolen)
+{
+ idnLogReset();
+
+ idnLogPrintf(idn_log_level_trace, "idnConvRsp(from=%-.100s)\n", from);
+ if (ctx == NULL) {
+ if (strlen(from) >= tolen)
+ return FALSE;
+ strcpy(to, from);
+ return TRUE;
+ } else if (idn_res_decodename(ctx, IDN_DECODE_APP,
+ from, to, tolen) == idn_success) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
diff --git a/contrib/idn/idnkit-1.0-src/wsock/common/dump.c b/contrib/idn/idnkit-1.0-src/wsock/common/dump.c
new file mode 100644
index 0000000..1f16bd5
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/common/dump.c
@@ -0,0 +1,118 @@
+/*
+ * dump.c - dump data
+ */
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wrapcommon.h"
+
+char *
+dumpAddr(const char FAR *addr, int len, char *buff, size_t size) {
+ int i;
+ char *p;
+
+ buff[0] = '\0';
+ for (i = 0, p = buff; i < len; i++) {
+ char digits[8];
+
+ sprintf(digits, "%d", (addr[i] & 0xff));
+ if (i + 1 < len) {
+ strcat(digits, ".");
+ }
+ if (strlen(digits) >= size) {
+ break;
+ }
+ strcpy(p, digits);
+ p += strlen(digits);
+ size -= strlen(digits);
+ }
+ return (buff);
+}
+
+char *
+dumpHost(const struct hostent FAR *hp, char *buff, size_t size) {
+ char *p = buff;
+
+ p[0] = '\0';
+ if (strlen(hp->h_name) + 1 < size) {
+ sprintf(p, "%s ", hp->h_name);
+ p += strlen(p);
+ size -= strlen(p);
+ }
+ dumpAddr(hp->h_addr_list[0], hp->h_length, p, size);
+ return (buff);
+}
+
+char *
+dumpName(const char *name, char *buff, size_t size) {
+ const char *sp;
+ char *dp;
+
+ for (sp = name, dp = buff; *sp != '\0'; sp++) {
+ if (*sp >= 0x21 && *sp <= 0x7e) {
+ if (size < 2) {
+ break;
+ }
+ *dp++ = *sp;
+ size--;
+ } else {
+ if (size < 5) {
+ break;
+ }
+ dp[0] = '\\';
+ dp[1] = 'x';
+ sprintf(dp + 2, "%02x", *sp & 0xff);
+ dp += 4;
+ size -= 4;
+ }
+ }
+ *dp = '\0';
+
+ return (buff);
+}
+
diff --git a/contrib/idn/idnkit-1.0-src/wsock/common/encoding.c b/contrib/idn/idnkit-1.0-src/wsock/common/encoding.c
new file mode 100644
index 0000000..f8ad9e7
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/common/encoding.c
@@ -0,0 +1,271 @@
+/*
+ * encoding.c - get DNS/Local encodings
+ *
+ * Software\JPNIC\IDN\Where
+ * \LogFile
+ * \LogLevel
+ * \InstallDir
+ * \PerProg\<name>\Where
+ * \PerProg\<name>\Encoding
+ */
+
+/*
+ * Copyright (c) 2000,2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "wrapcommon.h"
+
+#define IDN_GLOBAL 1
+#define IDN_PERPROG 2
+#define IDN_CURUSER 4
+
+/*
+ * Registry of Encodings
+ */
+
+#define IDNKEY_WRAPPER "Software\\JPNIC\\IDN"
+#define IDNKEY_PERPROG "Software\\JPNIC\\IDN\\PerProg"
+#define IDNVAL_WHERE "Where"
+#define IDNVAL_ENCODE "Encoding"
+#define IDNVAL_LOGLVL "LogLevel"
+#define IDNVAL_LOGFILE "LogFile"
+#define IDNVAL_INSDIR "InstallDir"
+
+static int GetRegistry(HKEY top, const char *key, const char *name,
+ DWORD type, void *param, DWORD length);
+static char *GetPerProgKey(char *buf, size_t len);
+static int GetFromRegistry(const char *name, int where, DWORD type,
+ void *param, DWORD length);
+static int GetIntFromRegistry(const char *name, int defvalue, int where);
+static BOOL GetStringFromRegistry(const char *name, char *result,
+ size_t length, int where);
+
+static int
+GetRegistry(HKEY top, const char *key, const char *name, DWORD type,
+ void *param, DWORD length)
+{
+ LONG stat;
+ HKEY hk;
+ DWORD realtype;
+
+ stat = RegOpenKeyEx(top, key, 0, KEY_READ, &hk);
+ if (stat != ERROR_SUCCESS) {
+ return 0;
+ }
+
+ stat = RegQueryValueEx(hk, (LPCTSTR)name, NULL,
+ &realtype, (LPBYTE)param, &length);
+
+ RegCloseKey(hk);
+
+ if (stat != ERROR_SUCCESS || realtype != type)
+ return 0;
+
+ return 1;
+}
+
+static char *
+GetPerProgKey(char *buf, size_t len)
+{
+ char exename[256];
+ char prgname[256];
+ char *p, *last;
+
+ GetModuleFileName(NULL, exename, 256);
+
+ for (p = exename, last = NULL; *p != '\0'; p++) {
+ if (*p == '/' || *p == '\\') {
+ last = p;
+ }
+ }
+ strcpy(prgname, (last == NULL) ? exename : (last + 1));
+ if ((p = strrchr(prgname, '.')) != NULL) {
+ *p = '\0';
+ }
+
+ if (strlen(IDNKEY_PERPROG) + 1 + strlen(prgname) >= len) {
+ return (NULL);
+ }
+ sprintf(buf, "%s\\%s", IDNKEY_PERPROG, prgname);
+ return buf;
+}
+
+static int
+GetFromRegistry(const char *name, int where, DWORD type,
+ void *param, DWORD length)
+{
+ if (where & IDN_PERPROG) {
+ /*
+ * First, try program specific setting.
+ */
+ char keyname[256];
+
+ /*
+ * Try HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE.
+ */
+ if (GetPerProgKey(keyname, sizeof(keyname)) != NULL) {
+ if (((where & IDN_CURUSER) &&
+ GetRegistry(HKEY_CURRENT_USER, keyname, name,
+ type, param, length)) ||
+ GetRegistry(HKEY_LOCAL_MACHINE, keyname, name,
+ type, param, length)) {
+ return (1);
+ }
+ }
+ }
+
+ if (where & IDN_GLOBAL) {
+ /*
+ * Try global setting.
+ */
+ if (((where & IDN_CURUSER) &&
+ GetRegistry(HKEY_CURRENT_USER, IDNKEY_WRAPPER, name,
+ type, param, length)) ||
+ GetRegistry(HKEY_LOCAL_MACHINE, IDNKEY_WRAPPER, name,
+ type, param, length)) {
+ return (1);
+ }
+ }
+
+ /*
+ * Not found.
+ */
+ return (0);
+}
+
+static int
+GetIntFromRegistry(const char *name, int defvalue, int where)
+{
+ DWORD param;
+
+ if (GetFromRegistry(name, where, REG_DWORD, &param, sizeof(param))) {
+ return ((int)param);
+ }
+ return (defvalue);
+}
+
+static BOOL
+GetStringFromRegistry(const char *name, char *result, size_t length, int where)
+{
+ if (GetFromRegistry(name, where, REG_SZ, result, (DWORD)length)) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * idnEncodeWhere - which module should convert domain name
+ */
+int
+idnEncodeWhere(void)
+{
+ int v = GetIntFromRegistry(IDNVAL_WHERE, IDN_ENCODE_ALWAYS,
+ IDN_GLOBAL|IDN_PERPROG|IDN_CURUSER);
+
+ idnLogPrintf(idn_log_level_trace, "idnEncodeWhere: %d\n", v);
+ return (v);
+}
+
+/*
+ * idnGetLogFile - refer to log file
+ */
+BOOL
+idnGetLogFile(char *file, size_t len)
+{
+ BOOL v = GetStringFromRegistry(IDNVAL_LOGFILE, file, len,
+ IDN_GLOBAL|IDN_CURUSER);
+
+ idnLogPrintf(idn_log_level_trace, "idnGetLogFile: %-.100s\n",
+ (v == TRUE) ? file : "<none>");
+ return (v);
+}
+
+/*
+ * idnGetPrgEncoding - refer to Program's Local Encoding
+ *
+ * use program name as registry key
+ */
+BOOL
+idnGetPrgEncoding(char *enc, size_t len)
+{
+ if (GetStringFromRegistry(IDNVAL_ENCODE, enc, len,
+ IDN_PERPROG|IDN_CURUSER) != TRUE ||
+ enc[0] == '\0') {
+ sprintf(enc, "CP%d", GetACP());
+ }
+ idnLogPrintf(idn_log_level_trace,
+ "idnGetPrgEncoding: %-.30s\n", enc);
+ return (TRUE);
+}
+
+/*
+ * idnGetLogLevel
+ */
+int
+idnGetLogLevel(void)
+{
+ int v = GetIntFromRegistry(IDNVAL_LOGLVL, 0,
+ IDN_GLOBAL|IDN_CURUSER);
+
+ idnLogPrintf(idn_log_level_trace, "idnGetLogLevel: %d\n", v);
+ return (v);
+}
+
+/*
+ * idnGetInstallDir - get idn wrapper install directory
+ */
+BOOL
+idnGetInstallDir(char *dir, size_t len)
+{
+ /* No need to look at HKEY_CURRENT_USER */
+ BOOL v = GetStringFromRegistry(IDNVAL_INSDIR, dir, len, IDN_GLOBAL);
+
+ idnLogPrintf(idn_log_level_trace, "idnGetInstallDir: %-.100s\n",
+ (v == TRUE) ? dir : "<none>");
+ return (v);
+}
diff --git a/contrib/idn/idnkit-1.0-src/wsock/common/hook.c b/contrib/idn/idnkit-1.0-src/wsock/common/hook.c
new file mode 100644
index 0000000..b520f10
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/common/hook.c
@@ -0,0 +1,224 @@
+/*
+ * hook.c - Hooking Asynchronous Completion
+ */
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "wrapcommon.h"
+
+/*
+ * Hook Managements
+ */
+
+static HHOOK hookHandle = NULL ;
+
+typedef struct _HOOK *HOOKPTR;
+
+typedef struct _HOOK {
+ HOOKPTR prev;
+ HOOKPTR next;
+ idn_resconf_t ctx;
+ HWND hWnd;
+ u_int wMsg;
+ char FAR *pBuf;
+} HOOKREC;
+
+static HOOKREC hookList = { 0 } ;
+
+static void
+hookListInit(void) {
+ if (hookList.prev == NULL || hookList.next == NULL) {
+ hookList.prev = &hookList;
+ hookList.next = &hookList;
+ }
+}
+
+static HOOKPTR
+hookListSearch(HWND hWnd, u_int wMsg) {
+ HOOKPTR hp;
+
+ for (hp = hookList.next ; hp != &hookList ; hp = hp->next) {
+ if (hp->hWnd == hWnd && hp->wMsg == wMsg) {
+ return (hp);
+ }
+ }
+ return (NULL);
+}
+
+static BOOL
+hookListAppend(HWND hWnd, u_int wMsg, char FAR *buf, idn_resconf_t ctx) {
+ HOOKPTR hp, prev, next;
+
+ if ((hp = (HOOKPTR)malloc(sizeof(HOOKREC))) == NULL) {
+ idnPrintf("cannot create hook record\n");
+ return (FALSE);
+ }
+ memset(hp, 0, sizeof(*hp));
+
+ hp->ctx = ctx;
+ hp->hWnd = hWnd;
+ hp->wMsg = wMsg;
+ hp->pBuf = buf;
+
+ prev = hookList.prev;
+ next = prev->next;
+ prev->next = hp;
+ next->prev = hp;
+ hp->next = next;
+ hp->prev = prev;
+
+ return (TRUE);
+}
+
+static void
+hookListDelete(HOOKPTR hp)
+{
+ HOOKPTR prev, next;
+
+ prev = hp->prev;
+ next = hp->next;
+ prev->next = next;
+ next->prev = prev;
+
+ free(hp);
+}
+
+static void
+hookListDone(void)
+{
+ HOOKPTR hp;
+
+ while ((hp = hookList.next) != &hookList) {
+ hookListDelete(hp);
+ }
+}
+
+/*
+ * idnHookInit - initialize Hook Management
+ */
+void
+idnHookInit(void) {
+ hookListInit();
+}
+
+/*
+ * idnHookDone - finalize Hook Management
+ */
+void
+idnHookDone(void) {
+ if (hookHandle != NULL) {
+ UnhookWindowsHookEx(hookHandle);
+ hookHandle = NULL;
+ }
+ hookListDone();
+}
+
+/*
+ * hookProc - hookprocedure, used as WH_GETMESSAGE hook
+ */
+LRESULT CALLBACK
+hookProc(int nCode, WPARAM wParam, LPARAM lParam) {
+ MSG *pMsg;
+ HOOKPTR pHook;
+ struct hostent *pHost;
+ char nbuff[256];
+ char hbuff[256];
+
+ if (nCode < 0) {
+ return (CallNextHookEx(hookHandle, nCode, wParam, lParam));
+ } else if (nCode != HC_ACTION) {
+ return (0);
+ }
+ if ((pMsg = (MSG *)lParam) == NULL) {
+ return (0);
+ }
+ if ((pHook = hookListSearch(pMsg->hwnd, pMsg->message)) == NULL) {
+ return (0);
+ }
+
+ /*
+ * Convert the Host Name
+ */
+ pHost = (struct hostent *)pHook->pBuf;
+ idnPrintf("AsyncComplete Resulting <%s>\n",
+ dumpName(pHost->h_name, hbuff, sizeof(hbuff)));
+ if (idnConvRsp(pHook->ctx, pHost->h_name,
+ nbuff, sizeof(nbuff)) == TRUE) {
+ idnPrintf("AsyncComplete Converted <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ strcpy(pHost->h_name, nbuff);
+ }
+
+ /*
+ * Delete target
+ */
+ hookListDelete(pHook);
+
+ return (0);
+}
+
+/*
+ * idnHook - hook async. completion message
+ */
+BOOL
+idnHook(HWND hWnd, u_int wMsg, char FAR *buf, idn_resconf_t ctx)
+{
+ if (hookHandle == NULL) {
+ hookHandle = SetWindowsHookEx(WH_GETMESSAGE, hookProc,
+ NULL, GetCurrentThreadId());
+ }
+ if (hookHandle == NULL) {
+ idnPrintf("idnHook: cannot set hook\n");
+ return (FALSE);
+ }
+ if (hookListAppend(hWnd, wMsg, buf, ctx) != TRUE) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
diff --git a/contrib/idn/idnkit-1.0-src/wsock/common/make.wnt b/contrib/idn/idnkit-1.0-src/wsock/common/make.wnt
new file mode 100644
index 0000000..4dde4dd
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/common/make.wnt
@@ -0,0 +1,102 @@
+#
+# Makefile for WinSock Wrapper (common part)
+#
+
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+!include <win32.mak>
+
+SYSLIBS = $(libcdll) kernel32.lib advapi32.lib user32.lib
+
+#
+# Files to use
+#
+
+HDRS = wrapcommon.h
+SRCS = printf.c dump.c checkdll.c encoding.c convert.c hook.c
+OBJS = printf.obj dump.obj checkdll.obj encoding.obj convert.obj hook.obj
+LIBS = ..\..\lib\idnkit.lib ..\..\win\iconv.lib
+
+cflags = $(cflags) -I..\..\include
+
+#
+# Targets to Build
+#
+
+TARGETS = wrapcommon.lib
+
+all : $(TARGETS)
+
+wrapcommon.lib : $(OBJS)
+ -del wrapcommon.lib
+ lib /out:wrapcommon.lib $(OBJS)
+
+install :
+
+clean : force
+ -del *.obj
+ -del *.lib
+ -del *.exp
+
+#
+# Dependencies
+#
+
+printf.obj : printf.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+dump.obj : dump.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+checkdll.obj : checkdll.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+encoding.obj : encoding.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+convert.obj : convert.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+hook.obj : hook.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+force :
+
diff --git a/contrib/idn/idnkit-1.0-src/wsock/common/printf.c b/contrib/idn/idnkit-1.0-src/wsock/common/printf.c
new file mode 100644
index 0000000..7d6d2e4
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/common/printf.c
@@ -0,0 +1,138 @@
+/*
+ * printf.c - printf like debug print function
+ */
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+
+#include "wrapcommon.h"
+
+/*
+ * Debug Tracer for DLL
+ */
+
+static char logfile_name[256];
+static int log_level = -1;
+static char log_header[30];
+
+void
+idnPrintf(char *fmt, ...) {
+ va_list arg_ptr;
+ FILE *fp;
+ char msg[512];
+
+ if (log_level < 0 || logfile_name[0] == '\0')
+ return;
+
+ va_start(arg_ptr, fmt);
+ vsprintf(msg, fmt, arg_ptr);
+ va_end(arg_ptr);
+
+ if ((fp = fopen(logfile_name, "a")) != NULL) {
+ fputs(log_header, fp);
+ fputs(msg, fp);
+ fclose(fp);
+ }
+}
+
+void
+idnLogPrintf(int level, char *fmt, ...) {
+ va_list arg_ptr;
+ FILE *fp;
+ char msg[512];
+
+ if (level > log_level || logfile_name[0] == '\0')
+ return;
+
+ va_start(arg_ptr, fmt);
+ vsprintf(msg, fmt, arg_ptr);
+ va_end(arg_ptr);
+
+ if ((fp = fopen(logfile_name, "a")) != NULL) {
+ fputs(log_header, fp);
+ fputs(msg, fp);
+ fclose(fp);
+ }
+}
+
+static void
+log_proc(int level, const char *msg) {
+ FILE *fp;
+
+ if (log_level < 0 || logfile_name[0] == '\0')
+ return;
+
+ if ((fp = fopen(logfile_name, "a")) != NULL) {
+ fputs(msg, fp);
+ fclose(fp);
+ }
+}
+
+void
+idnLogInit(const char *title) {
+ log_level = idnGetLogLevel();
+ /* If log file is not stored in the registry, don't do logging. */
+ if (idnGetLogFile(logfile_name, sizeof(logfile_name)) == FALSE) {
+ log_level = -1;
+ }
+ sprintf(log_header, "%08x %-.16s: ", getpid(), title);
+ idn_log_setproc(log_proc);
+ idn_log_setlevel(log_level < 0 ? 0 : log_level);
+}
+
+void
+idnLogReset(void) {
+ idn_log_setproc(log_proc);
+}
+
+void
+idnLogFinish(void) {
+ idn_log_setproc(NULL);
+ /* idn_log_setlevel(0); */
+}
diff --git a/contrib/idn/idnkit-1.0-src/wsock/common/wrapcommon.h b/contrib/idn/idnkit-1.0-src/wsock/common/wrapcommon.h
new file mode 100644
index 0000000..c186a33
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/common/wrapcommon.h
@@ -0,0 +1,109 @@
+/*
+ * wrapcommon.h
+ */
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _WRAPCOMMON_H
+#define _WRAPCOMMON_H
+
+#include <idn/res.h>
+#include <idn/log.h>
+#include <idn/version.h>
+
+#define WRAPPER_EXPORT extern __declspec(dllexport)
+
+extern void idnPrintf(char *fmt, ...);
+extern void idnLogPrintf(int level, char *fmt, ...);
+extern void idnLogInit(const char *title);
+extern void idnLogReset(void);
+extern void idnLogFinish(void);
+
+extern char *dumpAddr(const char FAR *addr, int len, char *buff, size_t size);
+extern char *dumpHost(const struct hostent FAR *hp, char *buff, size_t size);
+extern char *dumpName(const char *name, char *buff, size_t size);
+
+extern int idnEncodeWhere(void);
+
+#define IDN_ENCODE_ALWAYS 0
+#define IDN_ENCODE_CHECK 1
+#define IDN_ENCODE_ONLY11 2
+#define IDN_ENCODE_ONLY20 3
+
+extern BOOL idnGetPrgEncoding(char *enc, size_t len);
+extern BOOL idnGetLogFile(char *file, size_t len);
+
+extern int idnGetLogLevel(void); /* 0 : fatal */
+ /* 1 : error */
+ /* 2 : warning */
+ /* 3 : info */
+ /* 4 : trace */
+ /* 5 : dump */
+extern int idnGetInstallDir(char *dir, size_t len);
+
+extern idn_resconf_t idnConvInit(void);
+extern void idnConvDone(idn_resconf_t ctx);
+
+extern BOOL idnWinsockVersion(const char *version);
+extern HINSTANCE idnWinsockHandle(void);
+extern idn_resconf_t idnGetContext(void);
+
+/*
+ * Converting Request/Response
+ */
+
+extern BOOL idnConvReq(idn_resconf_t ctx, const char FAR *from,
+ char FAR *to, size_t tolen);
+extern BOOL idnConvRsp(idn_resconf_t ctx, const char FAR *from,
+ char FAR *to, size_t tolen);
+
+/*
+ * Hook for Asynchronouse Query
+ */
+
+extern void idnHookInit(void);
+extern void idnHookDone(void);
+extern BOOL idnHook(HWND hWnd, u_int wMsg, char FAR *buf, idn_resconf_t ctx);
+
+#endif /* _WRAPCOMMON_H */
diff --git a/contrib/idn/idnkit-1.0-src/wsock/config/idnconf.tcl b/contrib/idn/idnkit-1.0-src/wsock/config/idnconf.tcl
new file mode 100644
index 0000000..d73bb77
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/config/idnconf.tcl
@@ -0,0 +1,1123 @@
+# $Id: idnconf.tcl,v 1.1.1.1 2003/06/04 00:27:42 marka Exp $
+#
+# idnconf.tcl - configure idn wrapper
+#
+
+#############################################################################
+# Copyright (c) 2000,2002 Japan Network Information Center.
+# All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+#############################################################################
+
+global configFile configBack
+global registryKey registryEnc registryDef
+global filesCpy filesRen filesDel
+
+# idnkit version
+set version "1.0"
+
+set configFile "idnconf.lst" ;# list of wrapped program
+set configBack "idnconf.bak" ;# backup of previous data
+
+set serverKey "HKEY_LOCAL_MACHINE\\Software\\JPNIC\\IDN"
+set serverLogLevel LogLevel
+set serverLogLevelDef -1
+set serverLogLevelNone -1
+set serverLogFile LogFile
+set serverLogFileDef {C:\idn_wrapper.log}
+set serverConfFile ConfFile
+
+set perprogKey "HKEY_LOCAL_MACHINE\\Software\\JPNIC\\IDN\\PerProg\\"
+set perprogEnc Encoding
+set perprogDef Default
+
+set logFileNameDef idn_wrapper.log
+set confFileNameDef idn.conf
+
+set filesCpy11 { "wsock32.dll" }
+set filesCpy20 { "wsock32.dll" "ws2_32.dll" }
+set filesDel11 { "wsock32.dll" }
+set filesDel20 { "wsock32.dll" "ws2_32.dll" }
+
+set local_dll 0
+
+########################################################################
+#
+# OS version check
+#
+
+proc get_os_version {} {
+ global os_version tcl_platform
+
+ if {[llength [info globals os_version]] > 0} {
+ return $os_version
+ }
+
+ switch -- $tcl_platform(os) {
+ "Windows 95" {
+ switch -- $tcl_platform(osVersion) {
+ 4.0 {
+ set os_version {Windows 95}
+ }
+ 4.10 {
+ set os_version {Windows 98}
+ }
+ 4.90 {
+ set os_version {Windows Me}
+ }
+ }
+ }
+ "Windows NT" {
+ switch -- $tcl_platform(osVersion) {
+ 3.51 -
+ 4.0 {
+ set os_version {Windows NT}
+ }
+ 5.0 {
+ set os_version {Windows 2000}
+ }
+ default {
+ # XP or .NET
+ set os_version {Windows XP}
+ }
+ }
+ }
+ "Win32s" {
+ error "idn wrapper does not support Windows 3.1"
+ }
+ default {
+ set os_version "Unknown"
+ }
+ }
+ set os_version
+}
+
+proc support_dll_redirection {} {
+ global dll_redirection
+
+ if {[llength [info globals dll_redirection]] > 0} {
+ return $dll_redirection
+ }
+
+ switch -- [get_os_version] {
+ {Windows 95} -
+ {Windows NT} {
+ # cannot force local DLL reference by .local file.
+ set dll_redirection 0
+ }
+ default {
+ set dll_redirection 1
+ }
+ }
+ set dll_redirection
+}
+
+########################################################################
+#
+# handling pathname
+#
+
+proc getExeName { prg } {
+ set elem [file split $prg]
+ set leng [expr {[llength $elem] - 1}]
+ set name [lindex $elem $leng]
+ set exe [file rootname $name]
+ return $exe
+}
+
+proc getDirName { prg } {
+ file dirname $prg
+}
+
+proc getSystemDir {} {
+ global env
+ switch -- [get_os_version] {
+ "Windows 95" -
+ "Windows 98" -
+ "Windows Me" {
+ set sysDir $env(windir)/system
+ }
+ default {
+ set sysDir $env(SystemRoot)/system32
+ }
+ }
+ return $sysDir
+}
+
+########################################################################
+#
+# loadList / saveList
+#
+# loadList - load list of wrapped executables from $configFile
+# saveList - save list of wrapped executables into $configFile
+#
+
+proc loadList {} {
+
+ global configFile configBack
+
+ if { [file exists $configFile] } {
+ file copy -force $configFile $configBack
+ }
+
+ set aList {}
+ set fd [open $configFile {CREAT RDONLY}]
+ while { ! [eof $fd]} {
+ set line [gets $fd]
+ if { [string length $line] > 0} {
+ lappend aList "$line"
+ }
+ }
+ close $fd
+ return $aList
+}
+
+proc saveList { aList } {
+ global configFile
+ file delete -force $configFile
+ set fd [open $configFile {CREAT WRONLY}]
+ foreach e $aList {
+ puts $fd $e
+ }
+ close $fd
+}
+
+########################################################################
+#
+# putList / getList - set/get list to/from listbox
+#
+
+proc putList { lb aList } {
+ foreach e $aList {
+ $lb insert end $e
+ }
+}
+
+proc getList { lb } {
+ $lb get 0 end
+}
+
+########################################################################
+#
+# checkList / appendList / deleteList - check / append / delete program from/to listbox
+#
+
+proc checkList { lb prg } {
+ set cnt 0
+ set lst [getList $lb]
+
+ foreach n $lst {
+ if { [string compare $prg $n] == 0 } {
+ incr cnt
+ }
+ }
+ return $cnt
+}
+
+proc appendList { lb prg } {
+
+ if { [checkList $lb $prg] == 0 } {
+ $lb insert end $prg
+ }
+}
+
+proc deleteList { lb prg } {
+ set cnt 0
+ set lst [getList $lb]
+
+ foreach n $lst {
+ if { [string compare $n $prg] == 0 } {
+ $lb delete $cnt
+ }
+ incr cnt
+ }
+}
+
+########################################################################
+#
+# registry operations
+#
+
+proc regGetEncode { prg } {
+
+ global perprogKey perprogEnc perprogDef
+
+ if { [string compare $prg "" ] == 0 } {
+ return $perprogDef
+ }
+
+ if {![isWindows]} {
+ return $perprogDef
+ }
+ package require registry 1.0
+
+ set name [getExeName $prg]
+ set key $perprogKey$name
+
+ if { [catch {set enc [registry get $key $perprogEnc]} err] } {
+ return $perprogDef
+ }
+ if { [string compare $enc ""] == 0 } {
+ return $perprogDef
+ }
+ return $enc
+}
+
+proc regSetEncode { prg enc } {
+
+ global perprogKey perprogEnc perprogDef
+
+ if {![isWindows]} {
+ return 1
+ }
+
+ package require registry 1.0
+
+ set name [getExeName $prg]
+ set key $perprogKey$name
+
+ if { [string compare $enc $perprogDef] == 0 } {
+ set enc ""
+ }
+ if { [catch {registry set $key $perprogEnc $enc sz} ] } {
+ return 2
+ }
+ return 0
+}
+
+proc regGetLogLevel {} {
+ global serverKey serverLogLevel serverLogLevelDef
+ regGetValue $serverKey $serverLogLevel $serverLogLevelDef
+}
+
+proc regSetLogLevel {level} {
+ global serverKey serverLogLevel
+ regSetValue $serverKey $serverLogLevel $level dword
+}
+
+proc regGetLogFile {} {
+ global serverKey serverLogFile serverLogFileDef
+ set file [regGetValue $serverKey $serverLogFile $serverLogFileDef]
+ if {[catch {file attributes $file -longname} lfile]} {
+ # Maybe $file doesn't exist (yet). Get the longname of
+ # directory portion.
+ set dir [file dirname $file]
+ if {[catch {file attributes $dir -longname} ldir]} {
+ set ldir $dir
+ }
+ set lfile [file join $ldir [file tail $file]]
+ }
+ file nativename $lfile
+}
+
+proc regSetLogFile {file} {
+ global serverKey serverLogFile
+ regSetValue $serverKey $serverLogFile [file nativename $file]
+}
+
+proc regGetConfFile {} {
+ global serverKey serverConfFile
+ set file [regGetValue $serverKey $serverConfFile {}]
+ if {[string compare $file {}] == 0} {
+ return {}
+ }
+ if {[catch {file attributes $file -longname} lfile]} {
+ # Maybe $file doesn't exist (yet). Get the longname of
+ # directory portion.
+ set dir [file dirname $file]
+ if {[catch {file attributes $dir -longname} ldir]} {
+ set ldir $dir
+ }
+ set lfile [file join $ldir [file tail $file]]
+ }
+ file nativename $lfile
+}
+
+proc regSetConfFile {file} {
+ global serverKey serverConfFile
+ regSetValue $serverKey $serverConfFile [file nativename $file]
+}
+
+proc regGetWhere {} {
+ global serverKey
+ regGetValue $serverKey Where 0
+}
+
+proc regSetWhere {where} {
+ global serverKey
+ regSetValue $serverKey Where $where dword
+}
+
+proc regGetValue {key name default} {
+ if {![isWindows]} {
+ puts "--regGetValue $key $name"
+ return $default
+ }
+ package require registry 1.0
+
+ if {[catch {registry get $key $name} value]} {
+ return $default
+ }
+ if {[string compare $value {}] == 0} {
+ return $default
+ }
+ return $value
+}
+
+proc regSetValue {key name value {type sz}} {
+ if {![isWindows]} {
+ puts "--regSetValue $key $name $value"
+ return 1
+ }
+
+ package require registry 1.0
+
+ if {[catch {registry set $key $name $value $type}]} {
+ return 2
+ }
+ return 0
+}
+
+########################################################################
+#
+# install / uninstall DLL s
+#
+
+proc fileInstall { prg } {
+
+ global env
+ global filesCpy11 filesCpy20
+
+ if {![isWindows]} {
+ return 1
+ }
+
+ switch -- [get_os_version] {
+ "Windows 95" -
+ "Windows 98" -
+ "Windows Me" {
+ set winDir $env(windir)
+ set sysDir $winDir/system
+ set filesCpy $filesCpy11
+ }
+ default {
+ set winDir $env(SystemRoot)
+ set sysDir $winDir/system32
+ set filesCpy $filesCpy20
+ }
+ }
+
+ set toDir [getDirName $prg ]
+
+ foreach n $filesCpy {
+ file copy -force $n $toDir
+ }
+ return 0
+}
+
+proc fileRemove { prg } {
+
+ global filesDel11 filesDel20
+
+ if {![isWindows]} {
+ return 1
+ }
+
+ switch -- [get_os_version] {
+ "Windows 95" {
+ set filesDel $filesDel11
+ }
+ "Windows 98" -
+ "Windows Me" {
+ set filesDel $filesDel20
+ }
+ default {
+ set filesDel $filesDel20
+ }
+ }
+
+ set fromDir [getDirName $prg ]
+
+ foreach n $filesDel {
+ file delete -force $fromDir/$n
+ }
+ return 0
+}
+
+########################################################################
+#
+# Wrap/Unwrap program
+#
+
+proc execWrap { pw lb dlg prg enc } {
+
+ set prgName [$prg get]
+ set encName [$enc get]
+
+ # Make sure the program name is not empty
+ if {[string compare $prgName {}] == 0} {
+ confErrorDialog $dlg "Program must be specified.\nClick \"Browse..\" button for browsing."
+ return
+ }
+
+ # It is dangerous to wrap programs in the system directory.
+ set prgdir [file nativename [getDirName $prgName]]
+ set sysdir [file nativename [getSystemDir]]
+ if {[string compare -nocase $prgdir $sysdir] == 0} {
+ tk_messageBox -icon error -type ok -title "Directory Error" \
+ -parent $dlg \
+ -message "Cannot wrap applications in the system directory.\nPlease copy the EXE file to elsewhere and wrap the copied one."
+ destroy $dlg
+ return 1
+ }
+
+ # Okay, copy the wrapper DLLs.
+ if { [fileInstall $prgName] } {
+ tk_messageBox -icon warning -type ok \
+ -title "Warning" \
+ -message "Cannot install DLLs" \
+ -parent $dlg
+ destroy $dlg
+ return 1
+ }
+ if { [regSetEncode $prgName $encName] } {
+ tk_messageBox -icon warning -type ok \
+ -title "Warning" \
+ -message "Cannot set encoding" \
+ -parent $dlg
+ fileRemove $prgName
+ destroy $dlg
+ return 2
+ }
+
+ # if local flag is on, create $prgName.local.
+ global local_dll
+ if {$local_dll} {
+ create_dot_local $prgName $dlg
+ } else {
+ remove_dot_local $prgName $dlg
+ }
+
+ if { [checkList $lb $prgName] == 0 } {
+ appendList $lb $prgName
+ }
+ saveList [getList $lb]
+ destroy $dlg
+}
+
+proc execUnwrap { pw lb dlg prg } {
+
+ set prgName [$prg get]
+
+ if {[support_dll_redirection] && [file exists $prgName.local]} {
+ set ans [tk_messageBox -icon question -type yesno \
+ -title "Confirmation" \
+ -message "Also remove $prgName.local file?" \
+ -parent $dlg]
+ if {[string compare $ans yes] == 0} {
+ remove_dot_local $prgName $dlg
+ }
+ }
+
+ if { [checkList $lb $prgName] == 1 } {
+ fileRemove $prgName
+ }
+ deleteList $lb $prgName
+ saveList [getList $lb]
+ destroy $dlg
+}
+
+proc create_dot_local {path {parent .}} {
+ set dotlocal $path.local
+ if {[file exists $dotlocal]} {
+ return 0
+ }
+ if {[catch {open $dotlocal w} fh]} {
+ tk_messageBox -icon warning -type ok -title "Warning" \
+ -message "Cannot create $dotlocal" -parent $parent
+ return -1
+ }
+ close $fh
+ return 0
+}
+
+proc remove_dot_local {path {parent .}} {
+ set dotlocal $path.local
+ if {[file exists $dotlocal] && [catch {file delete $dotlocal}]} {
+ tk_messageBox -icon warning -type ok -title "Warning" \
+ -message "Cannot remove $dotlocal" -parent $parent
+ return -1
+ }
+ return 0
+}
+
+########################################################################
+#
+# dialog for Wrap / Unwrap
+#
+
+proc syncEncode { v i op } {
+ global prgName encName
+ set enc [regGetEncode $prgName]
+ if { [string compare $encName $enc] != 0 } {
+ set encName $enc
+ }
+}
+
+proc confBrowse { p ePrg eEnc } {
+
+ set types {
+ { "Executable" .exe }
+ }
+
+ set file [tk_getOpenFile -filetypes $types -parent $p ]
+
+ if { [string compare $file ""] == 0 } {
+ return
+ }
+ set enc [regGetEncode $file]
+ $ePrg delete 0 end
+ $ePrg insert 0 $file
+}
+
+proc confWrap { pw lb } {
+
+ global prgName encName local_dll
+
+ set idx [$lb curselection]
+ if { [llength $idx] == 1 } {
+ set prg [$lb get $idx]
+ set local_dll [file exists $prg.local]
+ } else {
+ set prg ""
+ }
+
+ set top .wrap
+ toplevel $top
+ grab $top
+ wm title $top "idn wrapper - Wrap Executable"
+
+ frame $top.f1 -bd 1 -relief raised
+ frame $top.f2 -bd 1 -relief raised
+ pack $top.f1 -side top -fill x -expand on
+ pack $top.f2 -side top -fill x -expand on
+
+ frame $top.f1.f
+ pack $top.f1.f -fill both -expand on -padx 4 -pady 4
+
+ set w $top.f1.f
+ label $w.prgtitle -text "Program:"
+ label $w.enctitle -text "Encoding:"
+
+ entry $w.prgname -relief sunken -width 56 -textvariable prgName
+ entry $w.encname -relief sunken -width 8 -textvariable encName
+ set w_prgname $w.prgname
+ set w_encname $w.encname
+ button $w.browse -text "Browse.." \
+ -command [list confBrowse $w $w_prgname $w_encname]
+
+ frame $w.rbf
+ radiobutton $w.rbf.encdef -text "Default" -variable encName \
+ -value "Default"
+ radiobutton $w.rbf.encutf -text "UTF-8" -variable encName \
+ -value "UTF-8"
+ pack $w.rbf.encdef $w.rbf.encutf -side left -padx 4
+
+ grid $w.prgtitle -row 0 -column 0 -sticky e
+ grid $w.enctitle -row 1 -column 0 -sticky e
+ grid $w.prgname -row 0 -column 1 -sticky we -pady 4 -padx 2 -columnspan 2
+ grid $w.browse -row 0 -column 3 -sticky w -pady 4 -padx 4
+ grid $w.encname -row 1 -column 1 -sticky we -pady 4 -padx 2
+ grid $w.rbf -row 1 -column 2 -sticky w -padx 2
+ if {[support_dll_redirection]} {
+ checkbutton $w.local -text "Force local DLL reference" \
+ -variable local_dll
+ grid $w.local -row 2 -column 1 -sticky w -padx 4 -pady 4
+ }
+ grid columnconfig $w 1 -weight 1 -minsize 20
+ grid columnconfig $w 2 -weight 2 -minsize 20
+
+ trace variable prgName w syncEncode
+
+ $w.prgname delete 0 end
+ $w.prgname insert 0 $prg
+
+ focus $w.prgname
+
+ set w $top.f2
+ button $w.wrap -text "Wrap" \
+ -command [list execWrap $pw $lb $top $w_prgname $w_encname]
+ button $w.cancel -text "Cancel" \
+ -command [list destroy $top]
+ pack $w.cancel -side right -fill y -padx 12 -pady 4
+ pack $w.wrap -side right -fill y -padx 12 -pady 4
+
+ tkwait window $top
+}
+
+proc confUnwrap { pw lb } {
+
+ set idx [$lb curselection]
+ if { [llength $idx] != 1 } {
+ tk_messageBox -icon warning -type ok \
+ -title "Warning" \
+ -message "first, select unwrapping executable" \
+ -parent $pw
+ return 0
+ }
+ set prg [$lb get $idx]
+ if { [string length $prg] == 0 } {
+ tk_messageBox -icon warning -type ok \
+ -title "Warning" \
+ -message "first, select unwrapping executable" \
+ -parent $pw
+ return 0
+ }
+
+ set top .unwrap
+ toplevel $top
+ grab $top
+ wm title $top "idn wrapper - Unwrap Executable"
+
+ frame $top.f1 -bd 1 -relief raised
+ frame $top.f2 -bd 1 -relief raised
+ pack $top.f2 -side bottom -fill x
+ pack $top.f1 -side bottom -fill x -expand on
+
+ frame $top.f1.f
+ pack $top.f1.f -padx 4 -pady 4 -fill both -expand on
+ set w $top.f1.f
+ label $w.prgtitle -text "Program:"
+ entry $w.prgname -relief sunken -width 56 -textvariable prgName
+ $w.prgname delete 0 end
+ $w.prgname insert 0 $prg
+
+ set w_prgname $w.prgname
+
+ grid $w.prgtitle -row 0 -column 0 -sticky w
+ grid $w.prgname -row 0 -column 1 -sticky we -pady 4
+ grid columnconfig $w 1 -weight 1 -minsize 20
+
+ set w $top.f2
+ button $w.wrap -text "Unwrap" \
+ -command [list execUnwrap $pw $lb $top $w_prgname]
+ button $w.cancel -text "Cancel" \
+ -command [list destroy $top]
+
+ pack $w.cancel -side right -padx 12 -pady 6
+ pack $w.wrap -side right -padx 12 -pady 6
+
+ focus $w.wrap
+ tkwait window $top
+}
+
+proc unwrapAll {pw lb} {
+ set ans [tk_messageBox -type yesno -default no -icon question \
+ -parent $pw -title {idn wrapper Configuration} \
+ -message {Really unwrap all programs?}]
+ if {[string compare $ans yes] != 0} {
+ return
+ }
+
+ foreach prog [$lb get 0 end] {
+ fileRemove $prog
+ }
+
+ if {[support_dll_redirection]} {
+ set delete_type yes
+ foreach prog [$lb get 0 end] {
+ if {![file exists $prog.local]} continue
+ switch -- $delete_type {
+ yes -
+ no {
+ set delete_type [dotLocalDialog $prog $delete_type]
+ }
+ }
+ switch -- $delete_type {
+ yes -
+ yesall {
+ remove_dot_local $prog $pw
+ }
+ }
+ }
+ }
+
+ $lb delete 0 end
+ saveList {}
+}
+
+proc rewrapAll {pw lb} {
+ set ans [tk_messageBox -type yesno -default yes -icon question \
+ -parent $pw -title {idn wrapper Configuration} \
+ -message {Really rewrap all programs?}]
+ if {[string compare $ans yes] != 0} {
+ return
+ }
+ foreach prog [$lb get 0 end] {
+ fileInstall $prog
+ }
+}
+
+proc confLog {pw} {
+ global _logLevel _logFile
+
+ set top .log
+ catch {destroy $top}
+ toplevel $top
+ wm title $top "idn wrapper - Log Configuration"
+ # wm transient $top $pw
+
+ set _logLevel [regGetLogLevel]
+ set _logFile [regGetLogFile]
+
+ frame $top.f1 -bd 1 -relief raised
+ frame $top.f2 -bd 1 -relief raised
+ pack $top.f2 -side bottom -fill x
+ pack $top.f1 -side top -fill both -expand on
+
+ set w $top.f1
+ label $w.lv_l -text "Log Level:"
+ frame $w.lv_v
+ global serverLogLevelNone
+ set i 0
+ foreach {lvl text} [list $serverLogLevelNone None \
+ 0 Fatal 1 Error 2 Warning 3 Info 4 Trace] {
+ radiobutton $w.lv_v.btn$i -text $text -value $lvl -variable _logLevel
+ pack $w.lv_v.btn$i -side left -padx 3
+ incr i
+ }
+ label $w.ld_l -text "Log File:"
+ frame $w.ld_v
+ entry $w.ld_v.e -width 40 -textvariable _logFile
+ focus $w.ld_v.e
+ button $w.ld_v.b -text "Browse.." -command [list selectLog $top $w.ld_v.e]
+ pack $w.ld_v.b -side right -fill y -padx 6
+ pack $w.ld_v.e -side left -fill both -expand yes
+ #label $w.lo_l -text "Log Operation:"
+ frame $w.lo_v
+ button $w.lo_v.show -text "View" -command [list showLog $top]
+ button $w.lo_v.delete -text "Delete" -command [list deleteLog $top]
+ pack $w.lo_v.show $w.lo_v.delete -side left -padx 4
+
+ grid $w.lv_l -row 0 -column 0 -sticky e -padx 4
+ grid $w.ld_l -row 1 -column 0 -sticky e -padx 4
+ #grid $w.lo_l -row 2 -column 0 -sticky e -padx 4
+ grid $w.lv_v -row 0 -column 1 -sticky w -padx 4 -pady 4
+ grid $w.ld_v -row 1 -column 1 -sticky we -padx 4 -pady 4
+ grid $w.lo_v -row 2 -column 1 -sticky w -padx 4 -pady 4
+
+ set w $top.f2
+ button $w.ok -text "OK" -command [list configureLog $top]
+ button $w.cancel -text "Cancel" -command [list destroy $top]
+ pack $w.cancel -side right -padx 12 -pady 6
+ pack $w.ok -side right -padx 12 -pady 6
+}
+
+proc configureLog {top} {
+ global _logLevel _logFile
+
+ if {$_logLevel != [regGetLogLevel] ||
+ [string compare $_logFile [regGetLogFile]] != 0} {
+ set dir [file dirname $_logFile]
+ if {[string compare $dir {}]} {
+ if {![file exists $dir]} {
+ confErrorDialog $top "Directory $dir doesn't exist"
+ return
+ } elseif {![file isdirectory $dir]} {
+ confErrorDialog $top "$dir is not a directory"
+ return
+ }
+ }
+ regSetLogLevel $_logLevel
+ regSetLogFile $_logFile
+ tk_messageBox -type ok -default ok -icon info -parent $top \
+ -title "idn wrapper Configuration" \
+ -message "Changing log level or file does not affect already running processes."
+ }
+ destroy $top
+}
+
+proc selectLog {top e} {
+ global logFileNameDef
+ set file [tk_getSaveFile -title {idn wrapper Logfile Selection} \
+ -defaultextension .log \
+ -filetypes {{{Log Files} .log} {{All Files} *}} \
+ -initialfile $logFileNameDef \
+ -parent $top]
+ if {[string compare $file {}]} {
+ $e delete 0 end
+ $e insert insert $file
+ }
+}
+
+proc showLog {top} {
+ global _logFile
+ if {[catch {exec notepad.exe $_logFile &} r]} {
+ confErrorDialog $top "Cannot execute notepad"
+ }
+}
+
+proc deleteLog {top} {
+ global _logFile
+ set ans [tk_messageBox -type yesno -default no -icon question \
+ -parent $top -title "idn wrapper Configuration" \
+ -message "Really delete $_logFile?"]
+ if {[string compare $ans yes] == 0} {
+ file delete $_logFile
+ }
+}
+
+########################################################################
+#
+# dialog for .local deletion
+#
+
+proc dotLocalDialog {path {default yes}} {
+ set parent .
+ set dlg .dotlocaldlg
+ catch {destroy $dlg}
+ toplevel $dlg
+
+ wm iconname $dlg Dialog
+ wm title $dlg Confirmation
+ wm transient $dlg $parent
+ wm protocol $dlg WM_DELETE_WINDOW {}
+
+ frame $dlg.f1 -bd 1 -relief raised
+ frame $dlg.f2 -bd 1 -relief raised
+ pack $dlg.f1 -side top -fill x -expand on -ipadx 2m -ipady 4m
+ pack $dlg.f2 -side top -fill x -ipadx 2m
+
+ label $dlg.f1.bm -bitmap question -bd 0
+ label $dlg.f1.msg -text "Remove $path.local?" -wraplength 10c
+ pack $dlg.f1.bm -side left -padx 3m -pady 2m
+ pack $dlg.f1.msg -side left -padx 2m -pady 2m
+
+ global dotlocal_selection
+ foreach {btn lbl} {yes Yes no No yesall {Yes to All} noall {No to All}} {
+ set bw $dlg.f2.btn$btn
+ button $bw -text $lbl -default normal \
+ -command [list set dotlocal_selection $btn]
+ if {[string compare $default $btn] == 0} {
+ $bw configure -default active
+ focus $bw
+ }
+ bind $bw <Return> {%W flash; %W invoke}
+ pack $bw -side left -padx 3m -pady 2m
+ }
+
+ grab $dlg
+ ::tk::PlaceWindow $dlg widget $parent
+
+ vwait dotlocal_selection
+ destroy $dlg
+ return $dotlocal_selection
+}
+
+########################################################################
+#
+# dialog for advanced configuration
+#
+
+proc advancedConf {pw} {
+ set top .adv
+ catch {destroy $top}
+ toplevel $top
+ wm title $top "idn wrapper - Advanced Configuration"
+
+ global _mdnOperation _confFile
+ set _mdnOperation [regGetWhere]
+ set _confFile [regGetConfFile]
+
+ foreach f {f1 f2 f3} {
+ frame $top.$f -bd 1 -relief raised
+ pack $top.$f -side top -fill x
+ }
+
+ set f $top.f1
+ label $f.lbl -text {IDN Wrapping Mode}
+ set w $f.f
+ frame $w
+ foreach {rb val txt} [list \
+ rb1 0 {Wrap both WINSOCK 1.1 and WINSOCK 2.0} \
+ rb2 2 {Wrap only WINSOCK 1.1} \
+ rb3 3 {Wrap only WINSOCK 2.0} \
+ rb4 1 "Wrap only WINSOCK2.0 if it exists.\nOtherwise wrap only WINSOCK1.1"] {
+ radiobutton $w.$rb -text $txt -variable _mdnOperation -value $val \
+ -anchor w -justify left
+ pack $w.$rb -side top -fill x -pady 1
+ }
+ pack $f.lbl -side top -fill x -pady 4
+ pack $w -side top -fill both -padx 20 -pady 10
+
+ set f $top.f2
+ label $f.lbl -text {IDN Configuration}
+ pack $f.lbl -side top -fill x -pady 6
+
+ set w $f.f
+ frame $w
+ pack $w -side top -fill both -padx 10 -pady 6
+ label $w.l1 -text {Config File:}
+ #label $w.l2 -text {Config Operation:}
+ entry $w.e -width 40 -textvariable _confFile
+ focus $w.e
+ button $w.br -text "Browse.." -command [list selectConf $top $w.e]
+ button $w.b -text Edit -command [list editConf $top]
+ grid $w.l1 -row 0 -column 0 -sticky e -padx 4
+ #grid $w.l2 -row 1 -column 0 -sticky e -padx 4
+ grid $w.e -row 0 -column 1 -sticky we -padx 4 -pady 4
+ grid $w.b -row 1 -column 1 -sticky w -padx 4 -pady 4
+ grid $w.br -row 0 -column 2 -sticky w -padx 4 -pady 4
+
+ set w $top.f3
+ button $w.ok -text "OK" -command [list advConf $top]
+ button $w.cancel -text "Cancel" -command [list destroy $top]
+ pack $w.cancel -side right -padx 12 -pady 8
+ pack $w.ok -side right -padx 12 -pady 8
+}
+
+proc editConf {top} {
+ global _confFile
+ if {[catch {exec notepad.exe $_confFile &} r]} {
+ confErrorDialog $top "Cannot execute notepad"
+ }
+}
+
+proc selectConf {top e} {
+ global confFileNameDef
+ set file [tk_getOpenFile -title {idn wrapper Config File Selection} \
+ -defaultextension .conf \
+ -filetypes {{{Config Files} .conf} {{All Files} *}} \
+ -initialfile $confFileNameDef \
+ -parent $top]
+ if {[string compare $file {}]} {
+ $e delete 0 end
+ $e insert insert $file
+ }
+}
+
+proc advConf {top} {
+ global _mdnOperation _confFile
+ regSetWhere $_mdnOperation
+ regSetConfFile $_confFile
+ destroy $top
+}
+
+########################################################################
+#
+# utility
+#
+
+proc confErrorDialog {top message} {
+ tk_messageBox -default ok -icon error -parent $top -type ok \
+ -title {idn wrapper Configuration Error} -message $message
+}
+
+proc isWindows {} {
+ global tcl_platform
+ expr {[string compare $tcl_platform(platform) "windows"] == 0}
+}
+
+########################################################################
+#
+# config program start here
+#
+
+wm title . "idn wrapper - Configuration"
+wm iconname . "idn wrapper - Configuration"
+
+
+label .title -bd 1 -relief raised -pady 5 \
+ -text "idn wrapper Configuration Program version $version"
+
+frame .left -bd 1 -relief raised
+frame .right -bd 1 -relief raised
+
+frame .lst
+label .lst.title -text "Wrapped Programs" -pady 3
+listbox .lst.list -width 64 -height 16 -setgrid 1 \
+ -xscrollcommand ".lst.xscroll set" \
+ -yscrollcommand ".lst.yscroll set"
+scrollbar .lst.yscroll -orient vertical -command ".lst.list yview"
+scrollbar .lst.xscroll -orient horizontal -command ".lst.list xview"
+grid .lst.title -row 0 -column 0 -columnspan 2 -sticky news
+grid .lst.list -row 1 -column 0 -sticky news
+grid .lst.xscroll -row 2 -column 0 -sticky news
+grid .lst.yscroll -row 1 -column 1 -sticky news
+grid rowconfig .lst 1 -weight 1
+grid columnconfig .lst 0 -weight 1
+
+frame .btn
+button .btn.wrap -text "Wrap.." -command [list confWrap . .lst.list]
+button .btn.unwrap -text "Unwrap.." -command [list confUnwrap . .lst.list]
+button .btn.unwrapall -text "Unwrap All" -command [list unwrapAll . .lst.list]
+button .btn.rewrapall -text "Rewrap All" -command [list rewrapAll . .lst.list]
+frame .btn.spacing1 -width 1 -height 12 -bd 0
+button .btn.log -text "Log.." -command [list confLog .]
+frame .btn.spacing2 -width 1 -height 12 -bd 0
+button .btn.adv -text "Advanced.." -command [list advancedConf .]
+button .btn.exit -text Exit -command exit
+pack .btn.wrap -side top -fill x -pady 4
+pack .btn.unwrap -side top -fill x -pady 4
+pack .btn.unwrapall -side top -fill x -pady 4
+pack .btn.rewrapall -side top -fill x -pady 4
+pack .btn.spacing1 -side top
+pack .btn.log -side top -fill x -pady 4
+pack .btn.spacing2 -side top
+pack .btn.adv -side top -fill x -pady 4
+pack .btn.exit -side bottom -fill x -pady 4
+
+pack .lst -in .left -padx 4 -pady 4 -fill both -expand on
+pack .btn -in .right -padx 6 -pady 4 -fill both -expand on
+
+pack .title -side top -fill x
+pack .right -side right -fill y
+pack .left -side left -fill y -expand on
+
+#
+# then set current list into listbox
+#
+
+set theList [loadList]
+#saveList $theList
+putList .lst.list $theList
+
+#
+########################################################################
diff --git a/contrib/idn/idnkit-1.0-src/wsock/config/make.wnt b/contrib/idn/idnkit-1.0-src/wsock/config/make.wnt
new file mode 100644
index 0000000..1099fbe
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/config/make.wnt
@@ -0,0 +1,58 @@
+#
+# Makefile for building mDNS Wrapper Configuration Tool
+#
+
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+TARGETS = idnconf.exe
+
+all : $(TARGETS)
+
+idnconf.exe : idnconf.tcl
+ freewrap idnconf.tcl
+
+install : $(TARGETS)
+ copy idnconf.exe ..\bin
+
+clean : force
+ -del idnconf.exe
+
+force :
diff --git a/contrib/idn/idnkit-1.0-src/wsock/make.wnt b/contrib/idn/idnkit-1.0-src/wsock/make.wnt
new file mode 100644
index 0000000..3c45432
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/make.wnt
@@ -0,0 +1,97 @@
+#
+# Top Level Makefile for building WINSOCK idn wrapper
+#
+
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+all : force
+ cd common
+ $(MAKE) -f make.wnt all
+ cd ..
+ cd wsock11
+ $(MAKE) -f make.wnt all
+ cd ..
+ cd wsock20
+ $(MAKE) -f make.wnt all
+ cd ..
+ cd config
+ $(MAKE) -f make.wnt all
+ cd ..
+
+install : force
+ copy ..\win\iconv.dll bin
+ copy ..\lib\idnkit.dll bin
+ copy ..\lib\idnkitlite.dll bin
+ copy ..\map\jp.map bin
+ cd common
+ $(MAKE) -f make.wnt install
+ cd ..
+ cd wsock11
+ $(MAKE) -f make.wnt install
+ cd ..
+ cd wsock20
+ $(MAKE) -f make.wnt install
+ cd ..
+ cd config
+ $(MAKE) -f make.wnt install
+ cd ..
+
+setup : force
+ cd bin
+ iscc idn_wrapper.iss
+ cd ..
+
+clean : force
+ cd common
+ $(MAKE) -f make.wnt clean
+ cd ..
+ cd wsock11
+ $(MAKE) -f make.wnt clean
+ cd ..
+ cd wsock20
+ $(MAKE) -f make.wnt clean
+ cd ..
+ cd config
+ $(MAKE) -f make.wnt clean
+ cd ..
+
+force :
+
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock11/dlldef.h b/contrib/idn/idnkit-1.0-src/wsock/wsock11/dlldef.h
new file mode 100644
index 0000000..569a264
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock11/dlldef.h
@@ -0,0 +1,86 @@
+/*
+ * dlldef.h
+ */
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _DLLDEF_H
+#define _DLLDEF_H
+
+#include "../common/wrapcommon.h"
+
+/*
+ * Execution Tracing
+ */
+
+extern int procPid;
+
+#ifdef DEBUG
+#define TRACE idnPrintf
+#define FATAL idnPrintf
+#else
+#define TRACE
+#define FATAL idnPrintf
+#endif
+
+/*
+ * Stub functions for calling original version.
+ */
+extern int PASCAL
+_org_gethostname(char FAR * name, int namelen);
+
+extern struct hostent FAR * PASCAL
+_org_gethostbyname(const char FAR * name);
+
+extern struct hostent FAR * PASCAL
+_org_gethostbyaddr(const char FAR * addr, int len, int type);
+
+extern HANDLE PASCAL
+_org_WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char FAR * name,
+ char FAR * buf, int buflen);
+extern HANDLE PASCAL
+_org_WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char FAR * addr,
+ int len, int type, char FAR * buf, int buflen);
+
+
+#endif /* _DLLDEF_H */
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllfunc.c b/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllfunc.c
new file mode 100644
index 0000000..4b709f6
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllfunc.c
@@ -0,0 +1,212 @@
+/*
+ * dllfunc.c - wrapper functions
+ */
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+
+#include "dlldef.h"
+
+WRAPPER_EXPORT int PASCAL FAR
+gethostname(char FAR * name, int namelen) {
+ int ret;
+
+ TRACE("ENTER gethostname\n");
+ ret = _org_gethostname(name, namelen);
+ TRACE("LEAVE gethostname %d <%-.100s>\n", ret, name);
+
+ return (ret);
+}
+
+WRAPPER_EXPORT struct hostent FAR * PASCAL FAR
+gethostbyname(const char FAR * name) {
+ struct hostent FAR *ret;
+ char nbuff[256];
+ char hbuff[256];
+ BOOL stat;
+ idn_resconf_t encodeCtx;
+
+ TRACE("ENTER gethostbyname <%-.100s>\n",
+ (name != NULL ? name : "NULL"));
+
+ encodeCtx = idnGetContext();
+
+ if (encodeCtx == NULL) {
+ TRACE("gethostbyname: not encode here\n");
+ ret = _org_gethostbyname(name);
+ } else if (name == NULL) {
+ TRACE("gethostbyname: name is NULL\n");
+ ret = _org_gethostbyname(name);
+ } else {
+ stat = idnConvReq(encodeCtx, name, nbuff, sizeof(nbuff));
+ if (stat == FALSE) {
+ TRACE("idnConvReq failed\n");
+ ret = NULL;
+ } else {
+ TRACE("Converted Name <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ ret = _org_gethostbyname(nbuff);
+ }
+ }
+
+ if (ret != NULL && encodeCtx != NULL) {
+ TRACE("Resulting Name <%s>\n",
+ dumpName(ret->h_name, hbuff, sizeof(hbuff)));
+ stat = idnConvRsp(encodeCtx, ret->h_name, nbuff,
+ sizeof(nbuff));
+ if (stat == FALSE) {
+ TRACE("Decoding failed - return the name verbatim\n");
+ } else {
+ TRACE("Converted Back <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ strcpy(ret->h_name, nbuff);
+ }
+ }
+
+ if (ret == NULL) {
+ TRACE("LEAVE gethostbyname NULL\n");
+ } else {
+ TRACE("LEAVE gethostbyname <%s>\n",
+ dumpHost(ret, hbuff, sizeof(hbuff)));
+ }
+ return (ret);
+}
+
+WRAPPER_EXPORT struct hostent FAR * PASCAL FAR
+gethostbyaddr(const char FAR * addr, int len, int type) {
+ struct hostent FAR *ret;
+ char nbuff[256];
+ char abuff[256];
+ char hbuff[256];
+ BOOL stat;
+ idn_resconf_t encodeCtx;
+
+ TRACE("ENTER gethostbyaddr <%s>\n",
+ dumpAddr(addr, len, abuff, sizeof(abuff)));
+
+ encodeCtx = idnGetContext();
+
+ ret = _org_gethostbyaddr(addr, len, type);
+
+ if (ret != NULL && encodeCtx != NULL) {
+ TRACE("Resulting Name <%s>\n",
+ dumpName(ret->h_name, hbuff, sizeof(hbuff)));
+ stat = idnConvRsp(encodeCtx, ret->h_name,
+ nbuff, sizeof(nbuff));
+ if (stat == FALSE) {
+ TRACE("Decoding failed - return the name verbatim\n");
+ } else {
+ TRACE("Converted Back <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ strcpy(ret->h_name, nbuff);
+ }
+ }
+
+ if (ret == NULL) {
+ TRACE("LEAVE gethostbyaddr NULL\n") ;
+ } else {
+ TRACE("LEAVE gethostbyaddr <%s>\n",
+ dumpHost(ret, hbuff, sizeof(hbuff)));
+ }
+ return (ret);
+}
+
+WRAPPER_EXPORT HANDLE PASCAL FAR
+WSAAsyncGetHostByName(HWND hWnd, u_int wMsg,
+ const char FAR * name, char FAR * buf, int buflen)
+{
+ HANDLE ret;
+ char nbuff[256];
+ char hbuff[256];
+ idn_resconf_t encodeCtx;
+
+ TRACE("ENTER WSAAsyncGetHostByName <%-.100s>\n", name);
+
+ encodeCtx = idnGetContext();
+
+ if (encodeCtx == NULL || name == NULL) {
+ ret = _org_WSAAsyncGetHostByName(hWnd, wMsg, name,
+ buf, buflen);
+ } else {
+ idnHook(hWnd, wMsg, buf, encodeCtx);
+ idnConvReq(encodeCtx, name, nbuff, sizeof(nbuff));
+ TRACE("Converted Name <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ ret = _org_WSAAsyncGetHostByName(hWnd, wMsg, nbuff,
+ buf, buflen);
+ }
+
+ TRACE("LEAVE WSAAsyncGetHostByName HANDLE %08x\n", ret);
+
+ return (ret);
+}
+
+WRAPPER_EXPORT HANDLE PASCAL FAR
+WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char FAR * addr,
+ int len, int type, char FAR * buf, int buflen)
+{
+ HANDLE ret;
+ char abuff[256];
+ idn_resconf_t encodeCtx;
+
+ encodeCtx = idnGetContext();
+
+ if (encodeCtx != NULL) {
+ idnHook(hWnd, wMsg, buf, encodeCtx);
+ }
+
+ TRACE("ENTER WSAAsyncGetHostByAddr <%s>\n",
+ dumpAddr(addr, len, abuff, sizeof(abuff)));
+ ret = _org_WSAAsyncGetHostByAddr(hWnd, wMsg, addr, len, type,
+ buf, buflen);
+ TRACE("LEAVE WSAAsyncGetHostByAddr HANDLE %08x\n", ret);
+
+ return (ret);
+}
+
+
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllload.c b/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllload.c
new file mode 100644
index 0000000..68c2a7e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllload.c
@@ -0,0 +1,63 @@
+/*
+ * dllload.c - load original entries
+ */
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <winsock.h>
+#include <nspapi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+
+#include "dlldef.h"
+
+/*
+ * Manages original DLL
+ */
+
+#define DLLHANDLE idnWinsockHandle()
+
+#include "dllstub.c"
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllmain.c b/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllmain.c
new file mode 100644
index 0000000..177f722
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllmain.c
@@ -0,0 +1,96 @@
+/*
+ * dllmain.c - entry for DLL
+ */
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+
+#include "dlldef.h"
+
+/*
+ * Control Variables
+ */
+
+int procPid = 0;
+
+static char procExe[256];
+
+/*
+ * DLL Entry
+ */
+
+BOOL APIENTRY
+DllMain(HMODULE hmod, DWORD reason, LPVOID *resv) {
+ switch (reason) {
+
+ case DLL_PROCESS_ATTACH:
+ procPid = getpid();
+ GetModuleFileName(NULL, procExe, 256);
+
+ idnLogInit("ws11");
+ idnHookInit();
+
+ TRACE("Attached to Process <%s>\n", procExe);
+ return (idnWinsockVersion("1.1"));
+
+ case DLL_PROCESS_DETACH:
+ idnConvDone(idnGetContext());
+ idnHookDone();
+ TRACE("Detached from Process\n");
+ idnLogFinish();
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ break;
+ }
+
+ return (TRUE);
+}
+
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllstub.c b/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllstub.c
new file mode 100644
index 0000000..534abc4
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock11/dllstub.c
@@ -0,0 +1,1541 @@
+/* $Id: dllstub.c,v 1.1.1.1 2003/06/04 00:27:45 marka Exp $ */
+
+SOCKET PASCAL
+accept(SOCKET a0, struct sockaddr* a1, int* a2)
+{
+ static SOCKET (PASCAL *fp)(SOCKET a0, struct sockaddr* a1, int* a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub accept() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "accept")) == NULL) {
+ FATAL("cannot find entry accept (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+bind(SOCKET a0, const struct sockaddr* a1, int a2)
+{
+ static int (PASCAL *fp)(SOCKET a0, const struct sockaddr* a1, int a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub bind() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "bind")) == NULL) {
+ FATAL("cannot find entry bind (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+closesocket(SOCKET a0)
+{
+ static int (PASCAL *fp)(SOCKET a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub closesocket() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "closesocket")) == NULL) {
+ FATAL("cannot find entry closesocket (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+connect(SOCKET a0, const struct sockaddr* a1, int a2)
+{
+ static int (PASCAL *fp)(SOCKET a0, const struct sockaddr* a1, int a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub connect() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "connect")) == NULL) {
+ FATAL("cannot find entry connect (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+getpeername(SOCKET a0, struct sockaddr* a1, int* a2)
+{
+ static int (PASCAL *fp)(SOCKET a0, struct sockaddr* a1, int* a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getpeername() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getpeername")) == NULL) {
+ FATAL("cannot find entry getpeername (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+getsockname(SOCKET a0, struct sockaddr* a1, int* a2)
+{
+ static int (PASCAL *fp)(SOCKET a0, struct sockaddr* a1, int* a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getsockname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getsockname")) == NULL) {
+ FATAL("cannot find entry getsockname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+getsockopt(SOCKET a0, int a1, int a2, char* a3, int* a4)
+{
+ static int (PASCAL *fp)(SOCKET a0, int a1, int a2, char* a3, int* a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getsockopt() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getsockopt")) == NULL) {
+ FATAL("cannot find entry getsockopt (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+u_long PASCAL
+htonl(u_long a0)
+{
+ static u_long (PASCAL *fp)(u_long a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub htonl() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "htonl")) == NULL) {
+ FATAL("cannot find entry htonl (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+u_short PASCAL
+htons(u_short a0)
+{
+ static u_short (PASCAL *fp)(u_short a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub htons() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "htons")) == NULL) {
+ FATAL("cannot find entry htons (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+unsigned long PASCAL
+inet_addr(const char* a0)
+{
+ static unsigned long (PASCAL *fp)(const char* a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub inet_addr() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "inet_addr")) == NULL) {
+ FATAL("cannot find entry inet_addr (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+ char * PASCAL
+inet_ntoa(struct in_addr a0)
+{
+ static char * (PASCAL *fp)(struct in_addr a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub inet_ntoa() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "inet_ntoa")) == NULL) {
+ FATAL("cannot find entry inet_ntoa (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+ioctlsocket(SOCKET a0, long a1, u_long * a2)
+{
+ static int (PASCAL *fp)(SOCKET a0, long a1, u_long * a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub ioctlsocket() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "ioctlsocket")) == NULL) {
+ FATAL("cannot find entry ioctlsocket (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+listen(SOCKET a0, int a1)
+{
+ static int (PASCAL *fp)(SOCKET a0, int a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub listen() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "listen")) == NULL) {
+ FATAL("cannot find entry listen (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+u_long PASCAL
+ntohl(u_long a0)
+{
+ static u_long (PASCAL *fp)(u_long a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub ntohl() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "ntohl")) == NULL) {
+ FATAL("cannot find entry ntohl (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+u_short PASCAL
+ntohs(u_short a0)
+{
+ static u_short (PASCAL *fp)(u_short a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub ntohs() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "ntohs")) == NULL) {
+ FATAL("cannot find entry ntohs (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+recv(SOCKET a0, char* a1, int a2, int a3)
+{
+ static int (PASCAL *fp)(SOCKET a0, char* a1, int a2, int a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub recv() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "recv")) == NULL) {
+ FATAL("cannot find entry recv (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+int PASCAL
+recvfrom(SOCKET a0, char* a1, int a2, int a3, struct sockaddr* a4, int* a5)
+{
+ static int (PASCAL *fp)(SOCKET a0, char* a1, int a2, int a3, struct sockaddr* a4, int* a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub recvfrom() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "recvfrom")) == NULL) {
+ FATAL("cannot find entry recvfrom (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+int PASCAL
+select(int a0, fd_set* a1, fd_set* a2, fd_set* a3, const struct timeval* a4)
+{
+ static int (PASCAL *fp)(int a0, fd_set* a1, fd_set* a2, fd_set* a3, const struct timeval* a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub select() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "select")) == NULL) {
+ FATAL("cannot find entry select (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+int PASCAL
+send(SOCKET a0, const char* a1, int a2, int a3)
+{
+ static int (PASCAL *fp)(SOCKET a0, const char* a1, int a2, int a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub send() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "send")) == NULL) {
+ FATAL("cannot find entry send (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+int PASCAL
+sendto(SOCKET a0, const char* a1, int a2, int a3, const struct sockaddr* a4, int a5)
+{
+ static int (PASCAL *fp)(SOCKET a0, const char* a1, int a2, int a3, const struct sockaddr* a4, int a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub sendto() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "sendto")) == NULL) {
+ FATAL("cannot find entry sendto (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+int PASCAL
+setsockopt(SOCKET a0, int a1, int a2, const char* a3, int a4)
+{
+ static int (PASCAL *fp)(SOCKET a0, int a1, int a2, const char* a3, int a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub setsockopt() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "setsockopt")) == NULL) {
+ FATAL("cannot find entry setsockopt (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+int PASCAL
+shutdown(SOCKET a0, int a1)
+{
+ static int (PASCAL *fp)(SOCKET a0, int a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub shutdown() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "shutdown")) == NULL) {
+ FATAL("cannot find entry shutdown (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+SOCKET PASCAL
+socket(int a0, int a1, int a2)
+{
+ static SOCKET (PASCAL *fp)(int a0, int a1, int a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub socket() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "socket")) == NULL) {
+ FATAL("cannot find entry socket (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+MigrateWinsockConfiguration(int a0, int a1, int a2)
+{
+ static int (PASCAL *fp)(int a0, int a1, int a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub MigrateWinsockConfiguration() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "MigrateWinsockConfiguration")) == NULL) {
+ FATAL("cannot find entry MigrateWinsockConfiguration (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+ struct hostent * PASCAL
+_org_gethostbyaddr(const char* a0, int a1, int a2)
+{
+ static struct hostent * (PASCAL *fp)(const char* a0, int a1, int a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_gethostbyaddr() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "gethostbyaddr")) == NULL) {
+ FATAL("cannot find entry gethostbyaddr (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+ struct hostent * PASCAL
+_org_gethostbyname(const char* a0)
+{
+ static struct hostent * (PASCAL *fp)(const char* a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_gethostbyname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "gethostbyname")) == NULL) {
+ FATAL("cannot find entry gethostbyname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+ struct protoent * PASCAL
+getprotobyname(const char* a0)
+{
+ static struct protoent * (PASCAL *fp)(const char* a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getprotobyname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getprotobyname")) == NULL) {
+ FATAL("cannot find entry getprotobyname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+ struct protoent * PASCAL
+getprotobynumber(int a0)
+{
+ static struct protoent * (PASCAL *fp)(int a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getprotobynumber() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getprotobynumber")) == NULL) {
+ FATAL("cannot find entry getprotobynumber (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+ struct servent * PASCAL
+getservbyname(const char* a0, const char* a1)
+{
+ static struct servent * (PASCAL *fp)(const char* a0, const char* a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getservbyname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getservbyname")) == NULL) {
+ FATAL("cannot find entry getservbyname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+ struct servent * PASCAL
+getservbyport(int a0, const char* a1)
+{
+ static struct servent * (PASCAL *fp)(int a0, const char* a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getservbyport() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getservbyport")) == NULL) {
+ FATAL("cannot find entry getservbyport (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int PASCAL
+_org_gethostname(char* a0, int a1)
+{
+ static int (PASCAL *fp)(char* a0, int a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_gethostname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "gethostname")) == NULL) {
+ FATAL("cannot find entry gethostname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int PASCAL
+WSAAsyncSelect(SOCKET a0, HWND a1, u_int a2, long a3)
+{
+ static int (PASCAL *fp)(SOCKET a0, HWND a1, u_int a2, long a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAsyncSelect() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncSelect")) == NULL) {
+ FATAL("cannot find entry WSAAsyncSelect (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+HANDLE PASCAL
+_org_WSAAsyncGetHostByAddr(HWND a0, u_int a1, const char* a2, int a3, int a4, char* a5, int a6)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, const char* a2, int a3, int a4, char* a5, int a6);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_WSAAsyncGetHostByAddr() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetHostByAddr")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetHostByAddr (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6);
+}
+
+HANDLE PASCAL
+_org_WSAAsyncGetHostByName(HWND a0, u_int a1, const char* a2, char* a3, int a4)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, const char* a2, char* a3, int a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_WSAAsyncGetHostByName() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetHostByName")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetHostByName (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+HANDLE PASCAL
+WSAAsyncGetProtoByNumber(HWND a0, u_int a1, int a2, char* a3, int a4)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, int a2, char* a3, int a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAsyncGetProtoByNumber() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetProtoByNumber")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetProtoByNumber (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+HANDLE PASCAL
+WSAAsyncGetProtoByName(HWND a0, u_int a1, const char* a2, char* a3, int a4)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, const char* a2, char* a3, int a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAsyncGetProtoByName() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetProtoByName")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetProtoByName (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+HANDLE PASCAL
+WSAAsyncGetServByPort(HWND a0, u_int a1, int a2, const char* a3, char* a4, int a5)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, int a2, const char* a3, char* a4, int a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAsyncGetServByPort() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetServByPort")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetServByPort (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+HANDLE PASCAL
+WSAAsyncGetServByName(HWND a0, u_int a1, const char* a2, const char* a3, char* a4, int a5)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, const char* a2, const char* a3, char* a4, int a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAsyncGetServByName() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetServByName")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetServByName (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+int PASCAL
+WSACancelAsyncRequest(HANDLE a0)
+{
+ static int (PASCAL *fp)(HANDLE a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSACancelAsyncRequest() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSACancelAsyncRequest")) == NULL) {
+ FATAL("cannot find entry WSACancelAsyncRequest (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+FARPROC PASCAL
+WSASetBlockingHook(FARPROC a0)
+{
+ static FARPROC (PASCAL *fp)(FARPROC a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASetBlockingHook() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASetBlockingHook")) == NULL) {
+ FATAL("cannot find entry WSASetBlockingHook (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+WSAUnhookBlockingHook(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAUnhookBlockingHook() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAUnhookBlockingHook")) == NULL) {
+ FATAL("cannot find entry WSAUnhookBlockingHook (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+int PASCAL
+WSAGetLastError(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAGetLastError() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAGetLastError")) == NULL) {
+ FATAL("cannot find entry WSAGetLastError (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+void PASCAL
+WSASetLastError(int a0)
+{
+ static void (PASCAL *fp)(int a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASetLastError() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASetLastError")) == NULL) {
+ FATAL("cannot find entry WSASetLastError (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ (*fp)(a0);
+}
+
+int PASCAL
+WSACancelBlockingCall(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSACancelBlockingCall() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSACancelBlockingCall")) == NULL) {
+ FATAL("cannot find entry WSACancelBlockingCall (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+BOOL PASCAL
+WSAIsBlocking(void)
+{
+ static BOOL (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAIsBlocking() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAIsBlocking")) == NULL) {
+ FATAL("cannot find entry WSAIsBlocking (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+int PASCAL
+WSAStartup(WORD a0, LPWSADATA a1)
+{
+ static int (PASCAL *fp)(WORD a0, LPWSADATA a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAStartup() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAStartup")) == NULL) {
+ FATAL("cannot find entry WSAStartup (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int PASCAL
+WSACleanup(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSACleanup() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSACleanup")) == NULL) {
+ FATAL("cannot find entry WSACleanup (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+int PASCAL
+__WSAFDIsSet(SOCKET a0, fd_set* a1)
+{
+ static int (PASCAL *fp)(SOCKET a0, fd_set* a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub __WSAFDIsSet() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "__WSAFDIsSet")) == NULL) {
+ FATAL("cannot find entry __WSAFDIsSet (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int PASCAL
+WEP(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WEP() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WEP")) == NULL) {
+ FATAL("cannot find entry WEP (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+int PASCAL
+WSApSetPostRoutine(int a0)
+{
+ static int (PASCAL *fp)(int a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSApSetPostRoutine() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSApSetPostRoutine")) == NULL) {
+ FATAL("cannot find entry WSApSetPostRoutine (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+WsControl(int a0, int a1, int a2, int a3, int a4, int a5)
+{
+ static int (PASCAL *fp)(int a0, int a1, int a2, int a3, int a4, int a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WsControl() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WsControl")) == NULL) {
+ FATAL("cannot find entry WsControl (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+int PASCAL
+closesockinfo(int a0)
+{
+ static int (PASCAL *fp)(int a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub closesockinfo() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "closesockinfo")) == NULL) {
+ FATAL("cannot find entry closesockinfo (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+Arecv(int a0, int a1, int a2, int a3)
+{
+ static int (PASCAL *fp)(int a0, int a1, int a2, int a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub Arecv() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "Arecv")) == NULL) {
+ FATAL("cannot find entry Arecv (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+int PASCAL
+Asend(int a0, int a1, int a2, int a3)
+{
+ static int (PASCAL *fp)(int a0, int a1, int a2, int a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub Asend() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "Asend")) == NULL) {
+ FATAL("cannot find entry Asend (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+int PASCAL
+WSHEnumProtocols(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSHEnumProtocols() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSHEnumProtocols")) == NULL) {
+ FATAL("cannot find entry WSHEnumProtocols (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+int PASCAL
+inet_network(int a0)
+{
+ static int (PASCAL *fp)(int a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub inet_network() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "inet_network")) == NULL) {
+ FATAL("cannot find entry inet_network (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+getnetbyname(int a0)
+{
+ static int (PASCAL *fp)(int a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getnetbyname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getnetbyname")) == NULL) {
+ FATAL("cannot find entry getnetbyname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+rcmd(int a0, int a1, int a2, int a3, int a4, int a5)
+{
+ static int (PASCAL *fp)(int a0, int a1, int a2, int a3, int a4, int a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub rcmd() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "rcmd")) == NULL) {
+ FATAL("cannot find entry rcmd (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+int PASCAL
+rexec(int a0, int a1, int a2, int a3, int a4, int a5)
+{
+ static int (PASCAL *fp)(int a0, int a1, int a2, int a3, int a4, int a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub rexec() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "rexec")) == NULL) {
+ FATAL("cannot find entry rexec (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+int PASCAL
+rresvport(int a0)
+{
+ static int (PASCAL *fp)(int a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub rresvport() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "rresvport")) == NULL) {
+ FATAL("cannot find entry rresvport (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+sethostname(int a0, int a1)
+{
+ static int (PASCAL *fp)(int a0, int a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub sethostname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "sethostname")) == NULL) {
+ FATAL("cannot find entry sethostname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int PASCAL
+dn_expand(int a0, int a1, int a2, int a3, int a4)
+{
+ static int (PASCAL *fp)(int a0, int a1, int a2, int a3, int a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub dn_expand() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "dn_expand")) == NULL) {
+ FATAL("cannot find entry dn_expand (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+int PASCAL
+WSARecvEx(SOCKET a0, char* a1, int a2, int* a3)
+{
+ static int (PASCAL *fp)(SOCKET a0, char* a1, int a2, int* a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSARecvEx() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSARecvEx")) == NULL) {
+ FATAL("cannot find entry WSARecvEx (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+int PASCAL
+s_perror(int a0, int a1)
+{
+ static int (PASCAL *fp)(int a0, int a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub s_perror() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "s_perror")) == NULL) {
+ FATAL("cannot find entry s_perror (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+INT PASCAL
+GetAddressByNameA(DWORD a0, LPGUID a1, LPSTR a2, LPINT a3, DWORD a4, LPSERVICE_ASYNC_INFO a5, LPVOID a6, LPDWORD a7, LPSTR a8, LPDWORD a9)
+{
+ static INT (PASCAL *fp)(DWORD a0, LPGUID a1, LPSTR a2, LPINT a3, DWORD a4, LPSERVICE_ASYNC_INFO a5, LPVOID a6, LPDWORD a7, LPSTR a8, LPDWORD a9);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub GetAddressByNameA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "GetAddressByNameA")) == NULL) {
+ FATAL("cannot find entry GetAddressByNameA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+}
+
+INT PASCAL
+GetAddressByNameW(DWORD a0, LPGUID a1, LPWSTR a2, LPINT a3, DWORD a4, LPSERVICE_ASYNC_INFO a5, LPVOID a6, LPDWORD a7, LPWSTR a8, LPDWORD a9)
+{
+ static INT (PASCAL *fp)(DWORD a0, LPGUID a1, LPWSTR a2, LPINT a3, DWORD a4, LPSERVICE_ASYNC_INFO a5, LPVOID a6, LPDWORD a7, LPWSTR a8, LPDWORD a9);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub GetAddressByNameW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "GetAddressByNameW")) == NULL) {
+ FATAL("cannot find entry GetAddressByNameW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+}
+
+INT PASCAL
+EnumProtocolsA(LPINT a0, LPVOID a1, LPDWORD a2)
+{
+ static INT (PASCAL *fp)(LPINT a0, LPVOID a1, LPDWORD a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub EnumProtocolsA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "EnumProtocolsA")) == NULL) {
+ FATAL("cannot find entry EnumProtocolsA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT PASCAL
+EnumProtocolsW(LPINT a0, LPVOID a1, LPDWORD a2)
+{
+ static INT (PASCAL *fp)(LPINT a0, LPVOID a1, LPDWORD a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub EnumProtocolsW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "EnumProtocolsW")) == NULL) {
+ FATAL("cannot find entry EnumProtocolsW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT PASCAL
+GetTypeByNameA(LPSTR a0, LPGUID a1)
+{
+ static INT (PASCAL *fp)(LPSTR a0, LPGUID a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub GetTypeByNameA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "GetTypeByNameA")) == NULL) {
+ FATAL("cannot find entry GetTypeByNameA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+INT PASCAL
+GetTypeByNameW(LPWSTR a0, LPGUID a1)
+{
+ static INT (PASCAL *fp)(LPWSTR a0, LPGUID a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub GetTypeByNameW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "GetTypeByNameW")) == NULL) {
+ FATAL("cannot find entry GetTypeByNameW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+INT PASCAL
+GetNameByTypeA(LPGUID a0, LPSTR a1, DWORD a2)
+{
+ static INT (PASCAL *fp)(LPGUID a0, LPSTR a1, DWORD a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub GetNameByTypeA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "GetNameByTypeA")) == NULL) {
+ FATAL("cannot find entry GetNameByTypeA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT PASCAL
+GetNameByTypeW(LPGUID a0, LPWSTR a1, DWORD a2)
+{
+ static INT (PASCAL *fp)(LPGUID a0, LPWSTR a1, DWORD a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub GetNameByTypeW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "GetNameByTypeW")) == NULL) {
+ FATAL("cannot find entry GetNameByTypeW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT PASCAL
+SetServiceA(DWORD a0, DWORD a1, DWORD a2, LPSERVICE_INFOA a3, LPSERVICE_ASYNC_INFO a4, LPDWORD a5)
+{
+ static INT (PASCAL *fp)(DWORD a0, DWORD a1, DWORD a2, LPSERVICE_INFOA a3, LPSERVICE_ASYNC_INFO a4, LPDWORD a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub SetServiceA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "SetServiceA")) == NULL) {
+ FATAL("cannot find entry SetServiceA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+INT PASCAL
+SetServiceW(DWORD a0, DWORD a1, DWORD a2, LPSERVICE_INFOW a3, LPSERVICE_ASYNC_INFO a4, LPDWORD a5)
+{
+ static INT (PASCAL *fp)(DWORD a0, DWORD a1, DWORD a2, LPSERVICE_INFOW a3, LPSERVICE_ASYNC_INFO a4, LPDWORD a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub SetServiceW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "SetServiceW")) == NULL) {
+ FATAL("cannot find entry SetServiceW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+INT PASCAL
+GetServiceA(DWORD a0, LPGUID a1, LPSTR a2, DWORD a3, LPVOID a4, LPDWORD a5, LPSERVICE_ASYNC_INFO a6)
+{
+ static INT (PASCAL *fp)(DWORD a0, LPGUID a1, LPSTR a2, DWORD a3, LPVOID a4, LPDWORD a5, LPSERVICE_ASYNC_INFO a6);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub GetServiceA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "GetServiceA")) == NULL) {
+ FATAL("cannot find entry GetServiceA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6);
+}
+
+INT PASCAL
+GetServiceW(DWORD a0, LPGUID a1, LPWSTR a2, DWORD a3, LPVOID a4, LPDWORD a5, LPSERVICE_ASYNC_INFO a6)
+{
+ static INT (PASCAL *fp)(DWORD a0, LPGUID a1, LPWSTR a2, DWORD a3, LPVOID a4, LPDWORD a5, LPSERVICE_ASYNC_INFO a6);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub GetServiceW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "GetServiceW")) == NULL) {
+ FATAL("cannot find entry GetServiceW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6);
+}
+
+int PASCAL
+NPLoadNameSpaces(int a0, int a1, int a2)
+{
+ static int (PASCAL *fp)(int a0, int a1, int a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub NPLoadNameSpaces() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "NPLoadNameSpaces")) == NULL) {
+ FATAL("cannot find entry NPLoadNameSpaces (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+NSPStartup(int a0, int a1)
+{
+ static int (PASCAL *fp)(int a0, int a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub NSPStartup() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "NSPStartup")) == NULL) {
+ FATAL("cannot find entry NSPStartup (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+BOOL PASCAL
+TransmitFile(SOCKET a0, HANDLE a1, DWORD a2, DWORD a3, LPOVERLAPPED a4, LPTRANSMIT_FILE_BUFFERS a5, DWORD a6)
+{
+ static BOOL (PASCAL *fp)(SOCKET a0, HANDLE a1, DWORD a2, DWORD a3, LPOVERLAPPED a4, LPTRANSMIT_FILE_BUFFERS a5, DWORD a6);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub TransmitFile() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "TransmitFile")) == NULL) {
+ FATAL("cannot find entry TransmitFile (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6);
+}
+
+BOOL PASCAL
+AcceptEx(SOCKET a0, SOCKET a1, PVOID a2, DWORD a3, DWORD a4, DWORD a5, LPDWORD a6, LPOVERLAPPED a7)
+{
+ static BOOL (PASCAL *fp)(SOCKET a0, SOCKET a1, PVOID a2, DWORD a3, DWORD a4, DWORD a5, LPDWORD a6, LPOVERLAPPED a7);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub AcceptEx() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "AcceptEx")) == NULL) {
+ FATAL("cannot find entry AcceptEx (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6, a7);
+}
+
+VOID PASCAL
+GetAcceptExSockaddrs(PVOID a0, DWORD a1, DWORD a2, DWORD a3, struct sockaddr** a4, LPINT a5, struct sockaddr** a6, LPINT a7)
+{
+ static VOID (PASCAL *fp)(PVOID a0, DWORD a1, DWORD a2, DWORD a3, struct sockaddr** a4, LPINT a5, struct sockaddr** a6, LPINT a7);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub GetAcceptExSockaddrs() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "GetAcceptExSockaddrs")) == NULL) {
+ FATAL("cannot find entry GetAcceptExSockaddrs (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ (*fp)(a0, a1, a2, a3, a4, a5, a6, a7);
+}
+
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock11/make.wnt b/contrib/idn/idnkit-1.0-src/wsock/wsock11/make.wnt
new file mode 100644
index 0000000..5543a6d
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock11/make.wnt
@@ -0,0 +1,98 @@
+#
+# Makefile for WinSock Wrapper (for WinSock 1.1)
+#
+
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+!include <win32.mak>
+
+SYSLIBS = $(libcdll) kernel32.lib advapi32.lib user32.lib
+
+#
+# Files to use
+#
+
+HDRS = dlldef.h ..\common\wrapcommon.h
+SRCS = dllmain.c dllload.c dllfunc.c dllstub.c
+OBJS = dllmain.obj dllload.obj dllfunc.obj
+LIBS = ..\common\wrapcommon.lib ..\..\lib\idnkit.lib ..\..\win\iconv.lib
+
+cflags = $(cflags) -I..\..\include
+
+#
+# Targets to Build
+#
+
+TARGETS = wsock32.dll
+
+all : $(TARGETS)
+
+wsock32.dll : wsock32.def $(OBJS) $(LIBS)
+ $(link) $(dlllflags) /OUT:wsock32.dll /DEF:wsock32.def $(OBJS) $(LIBS) $(SYSLIBS)
+
+install : $(TARGETS)
+ copy wsock32.dll ..\bin
+
+clean : force
+ -del *.obj
+ -del *.lib
+ -del *.dll
+ -del *.exp
+
+#
+# Dependencies
+#
+
+dllmain.obj : dllmain.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+dllload.obj : dllload.c dllstub.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+
+dllfunc.obj : dllfunc.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+wsock32o.lib : wsock32o.def
+ LIB /DEF:wsock32o.def /MACHINE:IX86
+
+force :
+
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock11/wsock32.def b/contrib/idn/idnkit-1.0-src/wsock/wsock11/wsock32.def
new file mode 100644
index 0000000..5501d26
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock11/wsock32.def
@@ -0,0 +1,87 @@
+;
+; Library Defition for idn wrapper's wrapper DLL
+;
+LIBRARY wsock32
+DESCRIPTION "JPNIC idn wrapper DLL for WSOCK32"
+EXPORTS
+ accept @1
+ bind @2
+ closesocket @3
+ connect @4
+ getpeername @5
+ getsockname @6
+ getsockopt @7
+ htonl @8
+ htons @9
+ inet_addr @10
+ inet_ntoa @11
+ ioctlsocket @12
+ listen @13
+ ntohl @14
+ ntohs @15
+ recv @16
+ recvfrom @17
+ select @18
+ send @19
+ sendto @20
+ setsockopt @21
+ shutdown @22
+ socket @23
+ MigrateWinsockConfiguration @24
+ gethostbyaddr @51
+ gethostbyname @52
+ getprotobyname @53
+ getprotobynumber @54
+ getservbyname @55
+ getservbyport @56
+ gethostname @57
+ WSAAsyncSelect @101
+ WSAAsyncGetHostByAddr @102
+ WSAAsyncGetHostByName @103
+ WSAAsyncGetProtoByNumber @104
+ WSAAsyncGetProtoByName @105
+ WSAAsyncGetServByPort @106
+ WSAAsyncGetServByName @107
+ WSACancelAsyncRequest @108
+ WSASetBlockingHook @109
+ WSAUnhookBlockingHook @110
+ WSAGetLastError @111
+ WSASetLastError @112
+ WSACancelBlockingCall @113
+ WSAIsBlocking @114
+ WSAStartup @115
+ WSACleanup @116
+ __WSAFDIsSet @151
+ WEP @500
+ WSApSetPostRoutine @1000
+ WsControl @1001
+ closesockinfo @1002
+ Arecv @1003
+ Asend @1004
+ WSHEnumProtocols @1005
+ inet_network @1100
+ getnetbyname @1101
+ rcmd @1102
+ rexec @1103
+ rresvport @1104
+ sethostname @1105
+ dn_expand @1106
+ WSARecvEx @1107
+ s_perror @1108
+ GetAddressByNameA @1109
+ GetAddressByNameW @1110
+ EnumProtocolsA @1111
+ EnumProtocolsW @1112
+ GetTypeByNameA @1113
+ GetTypeByNameW @1114
+ GetNameByTypeA @1115
+ GetNameByTypeW @1116
+ SetServiceA @1117
+ SetServiceW @1118
+ GetServiceA @1119
+ GetServiceW @1120
+ NPLoadNameSpaces @1130
+ NSPStartup @1131
+ TransmitFile @1140
+ AcceptEx @1141
+ GetAcceptExSockaddrs @1142
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock20/dlldef.h b/contrib/idn/idnkit-1.0-src/wsock/wsock20/dlldef.h
new file mode 100644
index 0000000..52a2567
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock20/dlldef.h
@@ -0,0 +1,123 @@
+/*
+ * dlldef.h
+ */
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _DLLDEF_H
+#define _DLLDEF_H
+
+#include "../common/wrapcommon.h"
+
+/*
+ * Execution Tracing
+ */
+
+extern int procPid;
+
+#ifdef DEBUG
+#define TRACE idnPrintf
+#define FATAL idnPrintf
+#else
+#define TRACE
+#define FATAL idnPrintf
+#endif
+
+/*
+ * entry points to wrap
+ */
+
+extern int WSAAPI
+_org_gethostname(char FAR * name, int namelen);
+
+extern struct hostent FAR * WSAAPI
+_org_gethostbyaddr(const char FAR * addr, int len, int type);
+
+extern struct hostent FAR * WSAAPI
+_org_gethostbyname(const char FAR * name);
+
+extern HANDLE WSAAPI
+_org_WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, const char FAR * name,
+ char FAR * buf,int buflen);
+
+extern HANDLE WSAAPI
+_org_WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char FAR * addr,
+ int len, int type, char FAR * buf, int buflen);
+
+extern INT WSAAPI
+_org_WSALookupServiceBeginA(LPWSAQUERYSETA lpqsRestrictions,
+ DWORD dwControlFlags,
+ LPHANDLE lphLookup);
+
+extern INT WSAAPI
+_org_WSALookupServiceBeginW(LPWSAQUERYSETW lpqsRestrictions,
+ DWORD dwControlFlags,
+ LPHANDLE lphLookup);
+
+extern INT WSAAPI
+_org_WSALookupServiceNextA(HANDLE hLookup,
+ DWORD dwControlFlags,
+ LPDWORD lpdwBufferLength,
+ LPWSAQUERYSETA lpqsResults);
+
+extern INT WSAAPI
+_org_WSALookupServiceNextW(HANDLE hLookup,
+ DWORD dwControlFlags,
+ LPDWORD lpdwBufferLength,
+ LPWSAQUERYSETW lpqsResults);
+
+extern INT WSAAPI
+_org_WSALookupServiceEnd(HANDLE hLookup);
+
+extern int WSAAPI
+_org_getaddrinfo(const char *nodename, const char *servname,
+ LPVOID hints, LPVOID res);
+
+extern void WSAAPI
+_org_freeaddrinfo(LPVOID aip);
+
+extern int WSAAPI
+_org_getnameinfo(LPVOID sa, DWORD salen, char* host, DWORD hostlen,
+ char* serv, DWORD servlen, int flags);
+
+#endif /* _DLLDEF_H */
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllfunc.c b/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllfunc.c
new file mode 100644
index 0000000..cec2d06
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllfunc.c
@@ -0,0 +1,592 @@
+/*
+ * dllfunc.c - wrapper functions
+ */
+
+/*
+ * Copyright (c) 2000,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <svcguid.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+
+#include "dlldef.h"
+
+#ifndef EAI_MEMORY
+#define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
+#endif
+#ifndef EAI_FAIL
+#define EAI_FAIL WSANO_RECOVERY
+#endif
+
+static GUID guid_habn = SVCID_INET_HOSTADDRBYNAME;
+static GUID guid_habis = SVCID_INET_HOSTADDRBYINETSTRING;
+
+#define SVCID_IS_HABN(p) (memcmp(p, &guid_habn, sizeof(GUID)) == 0)
+#define SVCID_IS_HABIS(p) (memcmp(p, &guid_habis, sizeof(GUID)) == 0)
+
+/*
+ * Rename addrinfo to my_addrinfo for avoiding possible name conflict.
+ */
+struct my_addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ char *ai_canonname;
+ struct sockaddr *ai_addr;
+ struct my_addrinfo *ai_next;
+};
+
+typedef struct obj_lock {
+ void *key;
+ struct obj_lock *next;
+} obj_lock_t;
+
+#define OBJLOCKHASH_SIZE 127
+static obj_lock_t *obj_lock_hash[OBJLOCKHASH_SIZE];
+
+static int obj_hash(void *key);
+static int obj_islocked(void *key);
+static void obj_lock(void *key);
+static void obj_unlock(void *key);
+static char *decode_name_dynamic(const char *name, idn_resconf_t idnctx);
+static struct my_addrinfo
+ *copy_decode_addrinfo_dynamic(struct my_addrinfo *aip,
+ idn_resconf_t idnctx);
+static void free_copied_addrinfo(struct my_addrinfo *aip);
+
+WRAPPER_EXPORT int WSAAPI
+gethostname(char FAR * name, int namelen) {
+ int ret;
+
+ TRACE("ENTER gethostname\n");
+ ret = _org_gethostname(name, namelen);
+ TRACE("LEAVE gethostname %d <%-.100s>\n", ret, name);
+
+ return (ret);
+}
+
+WRAPPER_EXPORT struct hostent FAR * WSAAPI
+gethostbyname(const char FAR * name) {
+ struct hostent FAR *ret;
+ char nbuff[256];
+ char hbuff[256];
+ BOOL stat;
+ idn_resconf_t encodeCtx;
+
+ TRACE("ENTER gethostbyname <%-.100s>\n",
+ (name != NULL ? name : "NULL"));
+
+ encodeCtx = idnGetContext();
+
+ if (encodeCtx == NULL || name == NULL) {
+ ret = _org_gethostbyname(name);
+ } else {
+ stat = idnConvReq(encodeCtx, name, nbuff, sizeof(nbuff));
+ if (stat == FALSE) {
+ TRACE("idnConvReq failed\n");
+ ret = NULL;
+ } else {
+ TRACE("Converted Name <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ ret = _org_gethostbyname(nbuff);
+ }
+ }
+
+ if (ret != NULL && encodeCtx != NULL) {
+ TRACE("Resulting Name <%s>\n",
+ dumpName(ret->h_name, hbuff, sizeof(hbuff)));
+ stat = idnConvRsp(encodeCtx, ret->h_name,
+ nbuff, sizeof(nbuff));
+ if (stat == FALSE) {
+ TRACE("Decoding failed - return the name verbatim\n");
+ } else {
+ TRACE("Converted Back <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ strcpy(ret->h_name, nbuff);
+ }
+ }
+
+ if (ret == NULL) {
+ TRACE("LEAVE gethostbyname NULL\n");
+ } else {
+ TRACE("LEAVE gethostbyname <%s>\n",
+ dumpHost(ret, hbuff, sizeof(hbuff)));
+ }
+ return (ret);
+}
+
+WRAPPER_EXPORT struct hostent FAR * WSAAPI
+gethostbyaddr(const char FAR * addr, int len, int type) {
+ struct hostent FAR *ret;
+ char nbuff[256];
+ char abuff[256];
+ char hbuff[256];
+ BOOL stat;
+ idn_resconf_t encodeCtx;
+
+ TRACE("ENTER gethostbyaddr <%s>\n",
+ dumpAddr(addr, len, abuff, sizeof(abuff)));
+
+ encodeCtx = idnGetContext();
+
+ ret = _org_gethostbyaddr(addr, len, type);
+
+ if (ret != NULL && encodeCtx != NULL) {
+ TRACE("Resulting Name <%s>\n",
+ dumpName(ret->h_name, hbuff, sizeof(hbuff)));
+ stat = idnConvRsp(encodeCtx, ret->h_name,
+ nbuff, sizeof(nbuff));
+ if (stat == FALSE) {
+ TRACE("Decoding failed - return the name verbatim\n");
+ } else {
+ TRACE("Converted Back <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ strcpy(ret->h_name, nbuff);
+ }
+ }
+
+ if (ret == NULL) {
+ TRACE("LEAVE gethostbyaddr NULL\n");
+ } else {
+ TRACE("LEAVE gethostbyaddr <%s>\n",
+ dumpHost(ret, hbuff, sizeof(hbuff)));
+ }
+ return (ret);
+}
+
+WRAPPER_EXPORT HANDLE WSAAPI
+WSAAsyncGetHostByName(HWND hWnd, u_int wMsg,
+ const char FAR * name, char FAR * buf, int buflen)
+{
+ HANDLE ret;
+ char nbuff[256];
+ char hbuff[256];
+ idn_resconf_t encodeCtx;
+
+ TRACE("ENTER WSAAsyncGetHostByName <%-.100s>\n", name);
+
+ encodeCtx = idnGetContext();
+
+ if (encodeCtx == NULL || name == NULL) {
+ ret = _org_WSAAsyncGetHostByName(hWnd, wMsg,
+ name, buf, buflen);
+ } else {
+ idnHook(hWnd, wMsg, buf, encodeCtx);
+ idnConvReq(encodeCtx, name, nbuff, sizeof(nbuff));
+ TRACE("Converted Name <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ ret = _org_WSAAsyncGetHostByName(hWnd, wMsg, nbuff,
+ buf, buflen);
+ }
+
+ TRACE("LEAVE WSAAsyncGetHostByName HANDLE %08x\n", ret);
+
+ return (ret);
+}
+
+WRAPPER_EXPORT HANDLE WSAAPI
+WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, const char FAR * addr,
+ int len, int type, char FAR * buf, int buflen)
+{
+ HANDLE ret;
+ char abuff[256];
+ idn_resconf_t encodeCtx;
+
+ encodeCtx = idnGetContext();
+
+ if (encodeCtx != NULL) {
+ idnHook(hWnd, wMsg, buf, encodeCtx);
+ }
+
+ TRACE("ENTER WSAAsyncGetHostByAddr <%s>\n",
+ dumpAddr(addr, len, abuff, sizeof(abuff)));
+ ret = _org_WSAAsyncGetHostByAddr(hWnd, wMsg, addr, len, type,
+ buf, buflen);
+ TRACE("LEAVE WSAAsyncGetHostByAddr HANDLE %08x\n", ret);
+
+ return (ret);
+}
+
+WRAPPER_EXPORT INT WSAAPI
+WSALookupServiceBeginA(LPWSAQUERYSETA lpqsRestrictions,
+ DWORD dwControlFlags, LPHANDLE lphLookup)
+{
+ INT ret;
+ char nbuff[256];
+ char hbuff[256];
+ LPSTR name = lpqsRestrictions->lpszServiceInstanceName;
+ LPGUID class = lpqsRestrictions->lpServiceClassId;
+ idn_resconf_t encodeCtx;
+
+ TRACE("ENTER WSALookupServiceBeginA <%-.100s>\n",
+ name == NULL ? "<NULL>" : name);
+
+ encodeCtx = idnGetContext();
+
+ if (name != NULL && encodeCtx != NULL && SVCID_IS_HABN(class) == 0) {
+ idnConvReq(encodeCtx, name, nbuff, sizeof(nbuff));
+ TRACE("Converted Name <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ /* strcpy(lpqsRestrictions->lpszQueryString, nbuff); */
+ lpqsRestrictions->lpszServiceInstanceName = nbuff;
+ }
+ ret = _org_WSALookupServiceBeginA(lpqsRestrictions,
+ dwControlFlags, lphLookup);
+ TRACE("LEAVE WSALookupServiceBeginA %d\n", ret);
+
+ return (ret);
+}
+
+WRAPPER_EXPORT INT WSAAPI
+WSALookupServiceNextA(HANDLE hLookup, DWORD dwControlFlags,
+ LPDWORD lpdwBufferLength, LPWSAQUERYSETA lpqsResults)
+{
+ INT ret;
+ char nbuff[256];
+ char hbuff[256];
+ LPGUID class;
+ idn_resconf_t encodeCtx;
+
+ TRACE("ENTER WSALookupServiceNextA\n");
+
+ encodeCtx = idnGetContext();
+
+ ret = _org_WSALookupServiceNextA(hLookup, dwControlFlags,
+ lpdwBufferLength, lpqsResults);
+ class = lpqsResults->lpServiceClassId;
+
+ if (ret == 0 &&
+ encodeCtx != NULL &&
+ (dwControlFlags & LUP_RETURN_NAME) &&
+ (SVCID_IS_HABN(class) || SVCID_IS_HABIS(class))) {
+ TRACE("Resulting Name <%s>\n",
+ dumpName(lpqsResults->lpszServiceInstanceName,
+ hbuff, sizeof(hbuff)));
+ if (idnConvRsp(encodeCtx,
+ lpqsResults->lpszServiceInstanceName,
+ nbuff, sizeof(nbuff)) == FALSE) {
+ TRACE("Decoding failed - return the name verbatim\n");
+ } else {
+ TRACE("Converted Back <%s>\n",
+ dumpName(nbuff, hbuff, sizeof(hbuff)));
+ strcpy(lpqsResults->lpszServiceInstanceName, nbuff);
+ }
+ }
+ TRACE("LEAVE WSALookupServiceNextA %d <%s>\n", ret, nbuff);
+
+ return (ret);
+}
+
+WRAPPER_EXPORT INT WSAAPI
+WSALookupServiceBeginW(LPWSAQUERYSETW lpqsRestrictions,
+ DWORD dwControlFlags, LPHANDLE lphLookup)
+{
+ INT ret;
+
+ TRACE("ENTER WSALookupServiceBeginW\n");
+ ret = _org_WSALookupServiceBeginW(lpqsRestrictions,
+ dwControlFlags,lphLookup);
+ TRACE("LEAVE WSALookupServiceBeginW %d\n", ret);
+
+ return (ret);
+}
+
+WRAPPER_EXPORT INT WSAAPI
+WSALookupServiceNextW(HANDLE hLookup, DWORD dwControlFlags,
+ LPDWORD lpdwBufferLength, LPWSAQUERYSETW lpqsResults)
+{
+ INT ret;
+
+ TRACE("ENTER WSALookupServiceNextW\n");
+ ret = _org_WSALookupServiceNextW(hLookup, dwControlFlags,
+ lpdwBufferLength, lpqsResults);
+ TRACE("LEAVE WSALookupServiceNextW %d\n", ret);
+
+ return (ret);
+}
+
+WRAPPER_EXPORT INT WSAAPI
+WSALookupServiceEnd(HANDLE hLookup) {
+ INT ret;
+
+ TRACE("ENTER WSALookupServiceEnd\n");
+ ret = _org_WSALookupServiceEnd(hLookup);
+ TRACE("LEAVE WSALookupServiceEnd %d\n", ret);
+
+ return (ret);
+}
+
+static int
+obj_hash(void *key) {
+ /*
+ * Hash function for obj_*.
+ * 'key' is supposed to be an address.
+ */
+ unsigned long v = (unsigned long)key;
+
+ return ((v >> 3) % OBJLOCKHASH_SIZE);
+}
+
+static int
+obj_islocked(void *key)
+{
+ /*
+ * Check if the object specified by 'key' is locked.
+ * Return 1 if so, 0 otherwise.
+ */
+ int h = obj_hash(key);
+ obj_lock_t *olp = obj_lock_hash[h];
+
+ while (olp != NULL) {
+ if (olp->key == key)
+ return (1);
+ olp = olp->next;
+ }
+ return (0);
+}
+
+static void
+obj_lock(void *key)
+{
+ /*
+ * Lock an object specified by 'key'.
+ */
+ int h = obj_hash(key);
+ obj_lock_t *olp;
+
+ olp = malloc(sizeof(obj_lock_t));
+ if (olp != NULL) {
+ olp->key = key;
+ olp->next = obj_lock_hash[h];
+ obj_lock_hash[h] = olp;
+ }
+}
+
+static void
+obj_unlock(void *key)
+{
+ /*
+ * Unlock an object specified by 'key'.
+ */
+ int h = obj_hash(key);
+ obj_lock_t *olp, *olp0;
+
+ olp = obj_lock_hash[h];
+ olp0 = NULL;
+ while (olp != NULL) {
+ if (olp->key == key) {
+ if (olp0 == NULL)
+ obj_lock_hash[h] = olp->next;
+ else
+ olp0->next = olp->next;
+ free(olp);
+ return;
+ }
+ olp0 = olp;
+ olp = olp->next;
+ }
+}
+
+static char *
+decode_name_dynamic(const char *name, idn_resconf_t idnctx) {
+ BOOL stat;
+ char buf[256], tmp[256];
+ char *s;
+
+ if (idnConvRsp(idnctx, name, buf, sizeof(buf)) == TRUE) {
+ TRACE("Converted Back <%s>\n",
+ dumpName(buf, tmp, sizeof(tmp)));
+ name = buf;
+ } else {
+ TRACE("Decoding failed - return the name verbatim\n");
+ }
+ s = malloc(strlen(name) + 1);
+ if (s == NULL)
+ return (NULL);
+ else
+ return (strcpy(s, name));
+}
+
+static struct my_addrinfo *
+copy_decode_addrinfo_dynamic(struct my_addrinfo *aip, idn_resconf_t idnctx)
+{
+ struct my_addrinfo *newaip;
+
+ if (aip == NULL)
+ return (NULL);
+
+ newaip = malloc(sizeof(struct my_addrinfo) + aip->ai_addrlen);
+ if (newaip == NULL)
+ return (NULL);
+
+ *newaip = *aip;
+ newaip->ai_addr = (struct sockaddr *)(newaip + 1);
+ memcpy(newaip->ai_addr, aip->ai_addr, aip->ai_addrlen);
+
+ if (newaip->ai_canonname != NULL)
+ newaip->ai_canonname = decode_name_dynamic(aip->ai_canonname,
+ idnctx);
+
+ newaip->ai_next = copy_decode_addrinfo_dynamic(aip->ai_next, idnctx);
+ return (newaip);
+}
+
+static void
+free_copied_addrinfo(struct my_addrinfo *aip) {
+ while (aip != NULL) {
+ struct my_addrinfo *next = aip->ai_next;
+
+ if (aip->ai_canonname != NULL)
+ free(aip->ai_canonname);
+ free(aip);
+ aip = next;
+ }
+}
+
+WRAPPER_EXPORT int WSAAPI
+getaddrinfo(const char *nodename, const char *servname,
+ const struct my_addrinfo *hints, struct my_addrinfo **res)
+{
+ char namebuf[256];
+ BOOL stat;
+ struct my_addrinfo *aip;
+ int err;
+ idn_resconf_t encodeCtx;
+
+ TRACE("ENTER getaddrinfo <%-.100s>\n", nodename ? nodename : "NULL");
+
+ encodeCtx = idnGetContext();
+
+ if (nodename == NULL || encodeCtx == NULL) {
+ TRACE("conversion unnecessary\n");
+ err = _org_getaddrinfo(nodename, servname, hints, res);
+ } else {
+ stat = idnConvReq(encodeCtx, nodename,
+ namebuf, sizeof(namebuf));
+ if (stat == TRUE) {
+ nodename = namebuf;
+ TRACE("Converted Name <%-.100s>\n", namebuf);
+ }
+
+ err = _org_getaddrinfo(nodename, servname, hints, &aip);
+ if (err == 0 && aip != NULL) {
+ *res = copy_decode_addrinfo_dynamic(aip, encodeCtx);
+ if (*res == NULL)
+ err = EAI_FAIL;
+ else
+ obj_lock(*res);
+ if (aip != NULL)
+ _org_freeaddrinfo(aip);
+ }
+ }
+
+ TRACE("LEAVE getaddrinfo %d\n", err);
+ return (err);
+}
+
+WRAPPER_EXPORT void WSAAPI
+freeaddrinfo(struct my_addrinfo *aip) {
+ TRACE("ENTER freeaddrinfo aip=%p\n", (void *)aip);
+
+ if (obj_islocked(aip)) {
+ /*
+ * We allocated the data.
+ */
+ obj_unlock(aip);
+ free_copied_addrinfo(aip);
+ } else {
+ /*
+ * It was allocated the original getaddrinfo().
+ */
+ TRACE("Not allocated by the wrapper\n");
+ _org_freeaddrinfo(aip);
+ }
+ TRACE("LEAVE freeaddrinfo\n");
+}
+
+WRAPPER_EXPORT int WSAAPI
+getnameinfo(const struct sockaddr *sa, DWORD salen,
+ char *host, DWORD hostlen, char *serv,
+ DWORD servlen, int flags)
+{
+ char name[256];
+ size_t namelen = sizeof(name);
+ int code;
+ BOOL stat;
+ idn_resconf_t encodeCtx;
+
+ TRACE("ENTER getnameinfo\n");
+
+ encodeCtx = idnGetContext();
+
+ if (host == NULL || hostlen == 0 || encodeCtx == NULL) {
+ TRACE("conversion unnecessary\n");
+ code = _org_getnameinfo(sa, salen, host, hostlen,
+ serv, servlen, flags);
+ } else {
+ code = _org_getnameinfo(sa, salen, name, namelen,
+ serv, servlen, flags);
+ if (code == 0 && name[0] != '\0') {
+ stat = idnConvRsp(encodeCtx, name, host, hostlen);
+ if (stat == FALSE) {
+ TRACE("Decoding failed - return the name verbatim\n");
+ if (strlen(name) >= hostlen) {
+ code = EAI_FAIL;
+ } else {
+ strcpy(host, name);
+ }
+ } else {
+ TRACE("Converted Back <%s>\n",
+ dumpName(host, name, sizeof(name)));
+ }
+ }
+ }
+
+ TRACE("LEAVE getnameinfo %d\n", code);
+ return (code);
+}
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllload.c b/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllload.c
new file mode 100644
index 0000000..0f1257e
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllload.c
@@ -0,0 +1,62 @@
+/*
+ * dllload.c - load original entries
+ */
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <winsock2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+
+#include "dlldef.h"
+
+/*
+ * Manages original DLL
+ */
+
+#define DLLHANDLE idnWinsockHandle()
+
+#include "dllstub.c"
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllmain.c b/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllmain.c
new file mode 100644
index 0000000..c6609bc
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllmain.c
@@ -0,0 +1,94 @@
+/*
+ * dllmain.c - entry for DLL
+ */
+
+/*
+ * Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <process.h>
+
+#include "dlldef.h"
+
+/*
+ * Control Variables
+ */
+
+int procPid = 0;
+
+static char procExe[256];
+
+/*
+ * DLL Entry
+ */
+
+BOOL APIENTRY
+DllMain(HMODULE hmod, DWORD reason, LPVOID *resv) {
+ switch (reason) {
+ case DLL_PROCESS_ATTACH:
+ procPid = getpid();
+ GetModuleFileName(NULL, procExe, 256);
+
+ idnLogInit("ws20");
+ idnHookInit();
+
+ TRACE("Attached to Process <%s>\n", procExe);
+ return (idnWinsockVersion("2.0"));
+
+ case DLL_PROCESS_DETACH:
+ idnConvDone(idnGetContext());
+ idnHookDone();
+ TRACE("Detached from Process\n");
+ idnLogFinish();
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+ case DLL_THREAD_DETACH:
+ break;
+ }
+
+ return (TRUE);
+}
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllstub.c b/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllstub.c
new file mode 100644
index 0000000..afc4537
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock20/dllstub.c
@@ -0,0 +1,2168 @@
+/* $Id: dllstub.c,v 1.1.1.1 2003/06/04 00:27:51 marka Exp $ */
+
+SOCKET PASCAL
+accept(SOCKET a0, struct sockaddr* a1, int* a2)
+{
+ static SOCKET (PASCAL *fp)(SOCKET a0, struct sockaddr* a1, int* a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub accept() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "accept")) == NULL) {
+ FATAL("cannot find entry accept (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+bind(SOCKET a0, const struct sockaddr* a1, int a2)
+{
+ static int (PASCAL *fp)(SOCKET a0, const struct sockaddr* a1, int a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub bind() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "bind")) == NULL) {
+ FATAL("cannot find entry bind (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+closesocket(SOCKET a0)
+{
+ static int (PASCAL *fp)(SOCKET a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub closesocket() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "closesocket")) == NULL) {
+ FATAL("cannot find entry closesocket (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+connect(SOCKET a0, const struct sockaddr* a1, int a2)
+{
+ static int (PASCAL *fp)(SOCKET a0, const struct sockaddr* a1, int a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub connect() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "connect")) == NULL) {
+ FATAL("cannot find entry connect (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+getpeername(SOCKET a0, struct sockaddr* a1, int* a2)
+{
+ static int (PASCAL *fp)(SOCKET a0, struct sockaddr* a1, int* a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getpeername() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getpeername")) == NULL) {
+ FATAL("cannot find entry getpeername (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+getsockname(SOCKET a0, struct sockaddr* a1, int* a2)
+{
+ static int (PASCAL *fp)(SOCKET a0, struct sockaddr* a1, int* a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getsockname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getsockname")) == NULL) {
+ FATAL("cannot find entry getsockname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+getsockopt(SOCKET a0, int a1, int a2, char* a3, int* a4)
+{
+ static int (PASCAL *fp)(SOCKET a0, int a1, int a2, char* a3, int* a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getsockopt() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getsockopt")) == NULL) {
+ FATAL("cannot find entry getsockopt (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+u_long PASCAL
+htonl(u_long a0)
+{
+ static u_long (PASCAL *fp)(u_long a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub htonl() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "htonl")) == NULL) {
+ FATAL("cannot find entry htonl (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+u_short PASCAL
+htons(u_short a0)
+{
+ static u_short (PASCAL *fp)(u_short a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub htons() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "htons")) == NULL) {
+ FATAL("cannot find entry htons (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+ioctlsocket(SOCKET a0, long a1, u_long * a2)
+{
+ static int (PASCAL *fp)(SOCKET a0, long a1, u_long * a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub ioctlsocket() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "ioctlsocket")) == NULL) {
+ FATAL("cannot find entry ioctlsocket (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+unsigned long PASCAL
+inet_addr(const char* a0)
+{
+ static unsigned long (PASCAL *fp)(const char* a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub inet_addr() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "inet_addr")) == NULL) {
+ FATAL("cannot find entry inet_addr (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+ char * PASCAL
+inet_ntoa(struct in_addr a0)
+{
+ static char * (PASCAL *fp)(struct in_addr a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub inet_ntoa() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "inet_ntoa")) == NULL) {
+ FATAL("cannot find entry inet_ntoa (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+listen(SOCKET a0, int a1)
+{
+ static int (PASCAL *fp)(SOCKET a0, int a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub listen() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "listen")) == NULL) {
+ FATAL("cannot find entry listen (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+u_long PASCAL
+ntohl(u_long a0)
+{
+ static u_long (PASCAL *fp)(u_long a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub ntohl() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "ntohl")) == NULL) {
+ FATAL("cannot find entry ntohl (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+u_short PASCAL
+ntohs(u_short a0)
+{
+ static u_short (PASCAL *fp)(u_short a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub ntohs() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "ntohs")) == NULL) {
+ FATAL("cannot find entry ntohs (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+recv(SOCKET a0, char* a1, int a2, int a3)
+{
+ static int (PASCAL *fp)(SOCKET a0, char* a1, int a2, int a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub recv() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "recv")) == NULL) {
+ FATAL("cannot find entry recv (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+int PASCAL
+recvfrom(SOCKET a0, char* a1, int a2, int a3, struct sockaddr* a4, int* a5)
+{
+ static int (PASCAL *fp)(SOCKET a0, char* a1, int a2, int a3, struct sockaddr* a4, int* a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub recvfrom() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "recvfrom")) == NULL) {
+ FATAL("cannot find entry recvfrom (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+int PASCAL
+select(int a0, fd_set* a1, fd_set* a2, fd_set* a3, const struct timeval* a4)
+{
+ static int (PASCAL *fp)(int a0, fd_set* a1, fd_set* a2, fd_set* a3, const struct timeval* a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub select() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "select")) == NULL) {
+ FATAL("cannot find entry select (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+int PASCAL
+send(SOCKET a0, const char* a1, int a2, int a3)
+{
+ static int (PASCAL *fp)(SOCKET a0, const char* a1, int a2, int a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub send() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "send")) == NULL) {
+ FATAL("cannot find entry send (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+int PASCAL
+sendto(SOCKET a0, const char* a1, int a2, int a3, const struct sockaddr* a4, int a5)
+{
+ static int (PASCAL *fp)(SOCKET a0, const char* a1, int a2, int a3, const struct sockaddr* a4, int a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub sendto() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "sendto")) == NULL) {
+ FATAL("cannot find entry sendto (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+int PASCAL
+setsockopt(SOCKET a0, int a1, int a2, const char* a3, int a4)
+{
+ static int (PASCAL *fp)(SOCKET a0, int a1, int a2, const char* a3, int a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub setsockopt() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "setsockopt")) == NULL) {
+ FATAL("cannot find entry setsockopt (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+int PASCAL
+shutdown(SOCKET a0, int a1)
+{
+ static int (PASCAL *fp)(SOCKET a0, int a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub shutdown() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "shutdown")) == NULL) {
+ FATAL("cannot find entry shutdown (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+SOCKET PASCAL
+socket(int a0, int a1, int a2)
+{
+ static SOCKET (PASCAL *fp)(int a0, int a1, int a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub socket() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "socket")) == NULL) {
+ FATAL("cannot find entry socket (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int PASCAL
+WSApSetPostRoutine(int a0)
+{
+ static int (PASCAL *fp)(int a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSApSetPostRoutine() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSApSetPostRoutine")) == NULL) {
+ FATAL("cannot find entry WSApSetPostRoutine (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+WSAEVENT WSAAPI
+WPUCompleteOverlappedRequest(SOCKET a0, LPWSAOVERLAPPED a1, DWORD a2, DWORD a3, LPINT a4)
+{
+ static WSAEVENT (WSAAPI *fp)(SOCKET a0, LPWSAOVERLAPPED a1, DWORD a2, DWORD a3, LPINT a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WPUCompleteOverlappedRequest() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WPUCompleteOverlappedRequest")) == NULL) {
+ FATAL("cannot find entry WPUCompleteOverlappedRequest (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+SOCKET WINAPI
+WSAAccept(SOCKET a0, struct sockaddr * a1, LPINT a2, LPCONDITIONPROC a3, DWORD a4)
+{
+ static SOCKET (WINAPI *fp)(SOCKET a0, struct sockaddr * a1, LPINT a2, LPCONDITIONPROC a3, DWORD a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAccept() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAccept")) == NULL) {
+ FATAL("cannot find entry WSAAccept (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+INT WINAPI
+WSAAddressToStringA(LPSOCKADDR a0, DWORD a1, LPWSAPROTOCOL_INFOA a2, LPSTR a3, LPDWORD a4)
+{
+ static INT (WINAPI *fp)(LPSOCKADDR a0, DWORD a1, LPWSAPROTOCOL_INFOA a2, LPSTR a3, LPDWORD a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAddressToStringA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAddressToStringA")) == NULL) {
+ FATAL("cannot find entry WSAAddressToStringA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+INT WINAPI
+WSAAddressToStringW(LPSOCKADDR a0, DWORD a1, LPWSAPROTOCOL_INFOW a2, LPWSTR a3, LPDWORD a4)
+{
+ static INT (WINAPI *fp)(LPSOCKADDR a0, DWORD a1, LPWSAPROTOCOL_INFOW a2, LPWSTR a3, LPDWORD a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAddressToStringW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAddressToStringW")) == NULL) {
+ FATAL("cannot find entry WSAAddressToStringW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+BOOL WINAPI
+WSACloseEvent(WSAEVENT a0)
+{
+ static BOOL (WINAPI *fp)(WSAEVENT a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSACloseEvent() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSACloseEvent")) == NULL) {
+ FATAL("cannot find entry WSACloseEvent (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int WINAPI
+WSAConnect(SOCKET a0, const struct sockaddr * a1, int a2, LPWSABUF a3, LPWSABUF a4, LPQOS a5, LPQOS a6)
+{
+ static int (WINAPI *fp)(SOCKET a0, const struct sockaddr * a1, int a2, LPWSABUF a3, LPWSABUF a4, LPQOS a5, LPQOS a6);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAConnect() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAConnect")) == NULL) {
+ FATAL("cannot find entry WSAConnect (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6);
+}
+
+WSAEVENT WINAPI
+WSACreateEvent(void)
+{
+ static WSAEVENT (WINAPI *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSACreateEvent() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSACreateEvent")) == NULL) {
+ FATAL("cannot find entry WSACreateEvent (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+int WINAPI
+WSADuplicateSocketA(SOCKET a0, DWORD a1, LPWSAPROTOCOL_INFOA a2)
+{
+ static int (WINAPI *fp)(SOCKET a0, DWORD a1, LPWSAPROTOCOL_INFOA a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSADuplicateSocketA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSADuplicateSocketA")) == NULL) {
+ FATAL("cannot find entry WSADuplicateSocketA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int WINAPI
+WSADuplicateSocketW(SOCKET a0, DWORD a1, LPWSAPROTOCOL_INFOW a2)
+{
+ static int (WINAPI *fp)(SOCKET a0, DWORD a1, LPWSAPROTOCOL_INFOW a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSADuplicateSocketW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSADuplicateSocketW")) == NULL) {
+ FATAL("cannot find entry WSADuplicateSocketW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT WINAPI
+WSAEnumNameSpaceProvidersA(LPDWORD a0, LPWSANAMESPACE_INFOA a1)
+{
+ static INT (WINAPI *fp)(LPDWORD a0, LPWSANAMESPACE_INFOA a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAEnumNameSpaceProvidersA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAEnumNameSpaceProvidersA")) == NULL) {
+ FATAL("cannot find entry WSAEnumNameSpaceProvidersA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+INT WINAPI
+WSAEnumNameSpaceProvidersW(LPDWORD a0, LPWSANAMESPACE_INFOW a1)
+{
+ static INT (WINAPI *fp)(LPDWORD a0, LPWSANAMESPACE_INFOW a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAEnumNameSpaceProvidersW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAEnumNameSpaceProvidersW")) == NULL) {
+ FATAL("cannot find entry WSAEnumNameSpaceProvidersW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int WINAPI
+WSAEnumNetworkEvents(SOCKET a0, WSAEVENT a1, LPWSANETWORKEVENTS a2)
+{
+ static int (WINAPI *fp)(SOCKET a0, WSAEVENT a1, LPWSANETWORKEVENTS a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAEnumNetworkEvents() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAEnumNetworkEvents")) == NULL) {
+ FATAL("cannot find entry WSAEnumNetworkEvents (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int WINAPI
+WSAEnumProtocolsA(LPINT a0, LPWSAPROTOCOL_INFOA a1, LPDWORD a2)
+{
+ static int (WINAPI *fp)(LPINT a0, LPWSAPROTOCOL_INFOA a1, LPDWORD a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAEnumProtocolsA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAEnumProtocolsA")) == NULL) {
+ FATAL("cannot find entry WSAEnumProtocolsA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int WINAPI
+WSAEnumProtocolsW(LPINT a0, LPWSAPROTOCOL_INFOW a1, LPDWORD a2)
+{
+ static int (WINAPI *fp)(LPINT a0, LPWSAPROTOCOL_INFOW a1, LPDWORD a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAEnumProtocolsW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAEnumProtocolsW")) == NULL) {
+ FATAL("cannot find entry WSAEnumProtocolsW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int WINAPI
+WSAEventSelect(SOCKET a0, WSAEVENT a1, long a2)
+{
+ static int (WINAPI *fp)(SOCKET a0, WSAEVENT a1, long a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAEventSelect() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAEventSelect")) == NULL) {
+ FATAL("cannot find entry WSAEventSelect (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+BOOL WINAPI
+WSAGetOverlappedResult(SOCKET a0, LPWSAOVERLAPPED a1, LPDWORD a2, BOOL a3, LPDWORD a4)
+{
+ static BOOL (WINAPI *fp)(SOCKET a0, LPWSAOVERLAPPED a1, LPDWORD a2, BOOL a3, LPDWORD a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAGetOverlappedResult() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAGetOverlappedResult")) == NULL) {
+ FATAL("cannot find entry WSAGetOverlappedResult (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+BOOL WINAPI
+WSAGetQOSByName(SOCKET a0, LPWSABUF a1, LPQOS a2)
+{
+ static BOOL (WINAPI *fp)(SOCKET a0, LPWSABUF a1, LPQOS a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAGetQOSByName() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAGetQOSByName")) == NULL) {
+ FATAL("cannot find entry WSAGetQOSByName (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT WINAPI
+WSAGetServiceClassInfoA(LPGUID a0, LPGUID a1, LPDWORD a2, LPWSASERVICECLASSINFOA a3)
+{
+ static INT (WINAPI *fp)(LPGUID a0, LPGUID a1, LPDWORD a2, LPWSASERVICECLASSINFOA a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAGetServiceClassInfoA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAGetServiceClassInfoA")) == NULL) {
+ FATAL("cannot find entry WSAGetServiceClassInfoA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+INT WINAPI
+WSAGetServiceClassInfoW(LPGUID a0, LPGUID a1, LPDWORD a2, LPWSASERVICECLASSINFOW a3)
+{
+ static INT (WINAPI *fp)(LPGUID a0, LPGUID a1, LPDWORD a2, LPWSASERVICECLASSINFOW a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAGetServiceClassInfoW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAGetServiceClassInfoW")) == NULL) {
+ FATAL("cannot find entry WSAGetServiceClassInfoW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+INT WINAPI
+WSAGetServiceClassNameByClassIdA(LPGUID a0, LPSTR a1, LPDWORD a2)
+{
+ static INT (WINAPI *fp)(LPGUID a0, LPSTR a1, LPDWORD a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAGetServiceClassNameByClassIdA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAGetServiceClassNameByClassIdA")) == NULL) {
+ FATAL("cannot find entry WSAGetServiceClassNameByClassIdA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT WINAPI
+WSAGetServiceClassNameByClassIdW(LPGUID a0, LPWSTR a1, LPDWORD a2)
+{
+ static INT (WINAPI *fp)(LPGUID a0, LPWSTR a1, LPDWORD a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAGetServiceClassNameByClassIdW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAGetServiceClassNameByClassIdW")) == NULL) {
+ FATAL("cannot find entry WSAGetServiceClassNameByClassIdW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int WINAPI
+WSAHtonl(SOCKET a0, unsigned long a1, unsigned long * a2)
+{
+ static int (WINAPI *fp)(SOCKET a0, unsigned long a1, unsigned long * a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAHtonl() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAHtonl")) == NULL) {
+ FATAL("cannot find entry WSAHtonl (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int WINAPI
+WSAHtons(SOCKET a0, unsigned short a1, unsigned short * a2)
+{
+ static int (WINAPI *fp)(SOCKET a0, unsigned short a1, unsigned short * a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAHtons() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAHtons")) == NULL) {
+ FATAL("cannot find entry WSAHtons (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT WINAPI
+WSAInstallServiceClassA(LPWSASERVICECLASSINFOA a0)
+{
+ static INT (WINAPI *fp)(LPWSASERVICECLASSINFOA a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAInstallServiceClassA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAInstallServiceClassA")) == NULL) {
+ FATAL("cannot find entry WSAInstallServiceClassA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+INT WINAPI
+WSAInstallServiceClassW(LPWSASERVICECLASSINFOW a0)
+{
+ static INT (WINAPI *fp)(LPWSASERVICECLASSINFOW a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAInstallServiceClassW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAInstallServiceClassW")) == NULL) {
+ FATAL("cannot find entry WSAInstallServiceClassW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int WINAPI
+WSAIoctl(SOCKET a0, DWORD a1, LPVOID a2, DWORD a3, LPVOID a4, DWORD a5, LPDWORD a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8)
+{
+ static int (WINAPI *fp)(SOCKET a0, DWORD a1, LPVOID a2, DWORD a3, LPVOID a4, DWORD a5, LPDWORD a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAIoctl() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAIoctl")) == NULL) {
+ FATAL("cannot find entry WSAIoctl (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+}
+
+ struct hostent * PASCAL
+_org_gethostbyaddr(const char* a0, int a1, int a2)
+{
+ static struct hostent * (PASCAL *fp)(const char* a0, int a1, int a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_gethostbyaddr() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "gethostbyaddr")) == NULL) {
+ FATAL("cannot find entry gethostbyaddr (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+ struct hostent * PASCAL
+_org_gethostbyname(const char* a0)
+{
+ static struct hostent * (PASCAL *fp)(const char* a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_gethostbyname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "gethostbyname")) == NULL) {
+ FATAL("cannot find entry gethostbyname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+ struct protoent * PASCAL
+getprotobyname(const char* a0)
+{
+ static struct protoent * (PASCAL *fp)(const char* a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getprotobyname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getprotobyname")) == NULL) {
+ FATAL("cannot find entry getprotobyname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+ struct protoent * PASCAL
+getprotobynumber(int a0)
+{
+ static struct protoent * (PASCAL *fp)(int a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getprotobynumber() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getprotobynumber")) == NULL) {
+ FATAL("cannot find entry getprotobynumber (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+ struct servent * PASCAL
+getservbyname(const char* a0, const char* a1)
+{
+ static struct servent * (PASCAL *fp)(const char* a0, const char* a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getservbyname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getservbyname")) == NULL) {
+ FATAL("cannot find entry getservbyname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+ struct servent * PASCAL
+getservbyport(int a0, const char* a1)
+{
+ static struct servent * (PASCAL *fp)(int a0, const char* a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub getservbyport() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getservbyport")) == NULL) {
+ FATAL("cannot find entry getservbyport (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int PASCAL
+_org_gethostname(char* a0, int a1)
+{
+ static int (PASCAL *fp)(char* a0, int a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_gethostname() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "gethostname")) == NULL) {
+ FATAL("cannot find entry gethostname (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+SOCKET WINAPI
+WSAJoinLeaf(SOCKET a0, const struct sockaddr * a1, int a2, LPWSABUF a3, LPWSABUF a4, LPQOS a5, LPQOS a6, DWORD a7)
+{
+ static SOCKET (WINAPI *fp)(SOCKET a0, const struct sockaddr * a1, int a2, LPWSABUF a3, LPWSABUF a4, LPQOS a5, LPQOS a6, DWORD a7);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAJoinLeaf() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAJoinLeaf")) == NULL) {
+ FATAL("cannot find entry WSAJoinLeaf (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6, a7);
+}
+
+INT WINAPI
+_org_WSALookupServiceBeginA(LPWSAQUERYSETA a0, DWORD a1, LPHANDLE a2)
+{
+ static INT (WINAPI *fp)(LPWSAQUERYSETA a0, DWORD a1, LPHANDLE a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_WSALookupServiceBeginA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSALookupServiceBeginA")) == NULL) {
+ FATAL("cannot find entry WSALookupServiceBeginA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT WINAPI
+_org_WSALookupServiceBeginW(LPWSAQUERYSETW a0, DWORD a1, LPHANDLE a2)
+{
+ static INT (WINAPI *fp)(LPWSAQUERYSETW a0, DWORD a1, LPHANDLE a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_WSALookupServiceBeginW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSALookupServiceBeginW")) == NULL) {
+ FATAL("cannot find entry WSALookupServiceBeginW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT WINAPI
+_org_WSALookupServiceEnd(HANDLE a0)
+{
+ static INT (WINAPI *fp)(HANDLE a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_WSALookupServiceEnd() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSALookupServiceEnd")) == NULL) {
+ FATAL("cannot find entry WSALookupServiceEnd (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+INT WINAPI
+_org_WSALookupServiceNextA(HANDLE a0, DWORD a1, LPDWORD a2, LPWSAQUERYSETA a3)
+{
+ static INT (WINAPI *fp)(HANDLE a0, DWORD a1, LPDWORD a2, LPWSAQUERYSETA a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_WSALookupServiceNextA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSALookupServiceNextA")) == NULL) {
+ FATAL("cannot find entry WSALookupServiceNextA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+INT WINAPI
+_org_WSALookupServiceNextW(HANDLE a0, DWORD a1, LPDWORD a2, LPWSAQUERYSETW a3)
+{
+ static INT (WINAPI *fp)(HANDLE a0, DWORD a1, LPDWORD a2, LPWSAQUERYSETW a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_WSALookupServiceNextW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSALookupServiceNextW")) == NULL) {
+ FATAL("cannot find entry WSALookupServiceNextW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+int WINAPI
+WSANtohl(SOCKET a0, unsigned long a1, unsigned long * a2)
+{
+ static int (WINAPI *fp)(SOCKET a0, unsigned long a1, unsigned long * a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSANtohl() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSANtohl")) == NULL) {
+ FATAL("cannot find entry WSANtohl (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int WINAPI
+WSANtohs(SOCKET a0, unsigned short a1, unsigned short * a2)
+{
+ static int (WINAPI *fp)(SOCKET a0, unsigned short a1, unsigned short * a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSANtohs() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSANtohs")) == NULL) {
+ FATAL("cannot find entry WSANtohs (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int WSAAPI
+WSAProviderConfigChange(LPHANDLE a0, LPWSAOVERLAPPED a1, LPWSAOVERLAPPED_COMPLETION_ROUTINE a2)
+{
+ static int (WSAAPI *fp)(LPHANDLE a0, LPWSAOVERLAPPED a1, LPWSAOVERLAPPED_COMPLETION_ROUTINE a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAProviderConfigChange() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAProviderConfigChange")) == NULL) {
+ FATAL("cannot find entry WSAProviderConfigChange (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+int WINAPI
+WSARecv(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, LPWSAOVERLAPPED a5, LPWSAOVERLAPPED_COMPLETION_ROUTINE a6)
+{
+ static int (WINAPI *fp)(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, LPWSAOVERLAPPED a5, LPWSAOVERLAPPED_COMPLETION_ROUTINE a6);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSARecv() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSARecv")) == NULL) {
+ FATAL("cannot find entry WSARecv (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6);
+}
+
+int WINAPI
+WSARecvDisconnect(SOCKET a0, LPWSABUF a1)
+{
+ static int (WINAPI *fp)(SOCKET a0, LPWSABUF a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSARecvDisconnect() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSARecvDisconnect")) == NULL) {
+ FATAL("cannot find entry WSARecvDisconnect (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int WINAPI
+WSARecvFrom(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, struct sockaddr * a5, LPINT a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8)
+{
+ static int (WINAPI *fp)(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, LPDWORD a4, struct sockaddr * a5, LPINT a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSARecvFrom() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSARecvFrom")) == NULL) {
+ FATAL("cannot find entry WSARecvFrom (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+}
+
+INT WINAPI
+WSARemoveServiceClass(LPGUID a0)
+{
+ static INT (WINAPI *fp)(LPGUID a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSARemoveServiceClass() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSARemoveServiceClass")) == NULL) {
+ FATAL("cannot find entry WSARemoveServiceClass (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+BOOL WINAPI
+WSAResetEvent(WSAEVENT a0)
+{
+ static BOOL (WINAPI *fp)(WSAEVENT a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAResetEvent() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAResetEvent")) == NULL) {
+ FATAL("cannot find entry WSAResetEvent (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int WINAPI
+WSASend(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, DWORD a4, LPWSAOVERLAPPED a5, LPWSAOVERLAPPED_COMPLETION_ROUTINE a6)
+{
+ static int (WINAPI *fp)(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, DWORD a4, LPWSAOVERLAPPED a5, LPWSAOVERLAPPED_COMPLETION_ROUTINE a6);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASend() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASend")) == NULL) {
+ FATAL("cannot find entry WSASend (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6);
+}
+
+int WINAPI
+WSASendDisconnect(SOCKET a0, LPWSABUF a1)
+{
+ static int (WINAPI *fp)(SOCKET a0, LPWSABUF a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASendDisconnect() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASendDisconnect")) == NULL) {
+ FATAL("cannot find entry WSASendDisconnect (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int WINAPI
+WSASendTo(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, DWORD a4, const struct sockaddr * a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8)
+{
+ static int (WINAPI *fp)(SOCKET a0, LPWSABUF a1, DWORD a2, LPDWORD a3, DWORD a4, const struct sockaddr * a5, int a6, LPWSAOVERLAPPED a7, LPWSAOVERLAPPED_COMPLETION_ROUTINE a8);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASendTo() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASendTo")) == NULL) {
+ FATAL("cannot find entry WSASendTo (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6, a7, a8);
+}
+
+BOOL WINAPI
+WSASetEvent(WSAEVENT a0)
+{
+ static BOOL (WINAPI *fp)(WSAEVENT a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASetEvent() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASetEvent")) == NULL) {
+ FATAL("cannot find entry WSASetEvent (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+INT WSAAPI
+WSASetServiceA(LPWSAQUERYSETA a0, WSAESETSERVICEOP a1, DWORD a2)
+{
+ static INT (WSAAPI *fp)(LPWSAQUERYSETA a0, WSAESETSERVICEOP a1, DWORD a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASetServiceA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASetServiceA")) == NULL) {
+ FATAL("cannot find entry WSASetServiceA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+INT WINAPI
+WSASetServiceW(LPWSAQUERYSETW a0, WSAESETSERVICEOP a1, DWORD a2)
+{
+ static INT (WINAPI *fp)(LPWSAQUERYSETW a0, WSAESETSERVICEOP a1, DWORD a2);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASetServiceW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASetServiceW")) == NULL) {
+ FATAL("cannot find entry WSASetServiceW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2);
+}
+
+SOCKET WINAPI
+WSASocketA(int a0, int a1, int a2, LPWSAPROTOCOL_INFOA a3, GROUP a4, DWORD a5)
+{
+ static SOCKET (WINAPI *fp)(int a0, int a1, int a2, LPWSAPROTOCOL_INFOA a3, GROUP a4, DWORD a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASocketA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASocketA")) == NULL) {
+ FATAL("cannot find entry WSASocketA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+SOCKET WINAPI
+WSASocketW(int a0, int a1, int a2, LPWSAPROTOCOL_INFOW a3, GROUP a4, DWORD a5)
+{
+ static SOCKET (WINAPI *fp)(int a0, int a1, int a2, LPWSAPROTOCOL_INFOW a3, GROUP a4, DWORD a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASocketW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASocketW")) == NULL) {
+ FATAL("cannot find entry WSASocketW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+INT WINAPI
+WSAStringToAddressA(LPSTR a0, INT a1, LPWSAPROTOCOL_INFOA a2, LPSOCKADDR a3, LPINT a4)
+{
+ static INT (WINAPI *fp)(LPSTR a0, INT a1, LPWSAPROTOCOL_INFOA a2, LPSOCKADDR a3, LPINT a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAStringToAddressA() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAStringToAddressA")) == NULL) {
+ FATAL("cannot find entry WSAStringToAddressA (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+INT WINAPI
+WSAStringToAddressW(LPWSTR a0, INT a1, LPWSAPROTOCOL_INFOW a2, LPSOCKADDR a3, LPINT a4)
+{
+ static INT (WINAPI *fp)(LPWSTR a0, INT a1, LPWSAPROTOCOL_INFOW a2, LPSOCKADDR a3, LPINT a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAStringToAddressW() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAStringToAddressW")) == NULL) {
+ FATAL("cannot find entry WSAStringToAddressW (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+DWORD WINAPI
+WSAWaitForMultipleEvents(DWORD a0, const WSAEVENT * a1, BOOL a2, DWORD a3, BOOL a4)
+{
+ static DWORD (WINAPI *fp)(DWORD a0, const WSAEVENT * a1, BOOL a2, DWORD a3, BOOL a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAWaitForMultipleEvents() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAWaitForMultipleEvents")) == NULL) {
+ FATAL("cannot find entry WSAWaitForMultipleEvents (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+int WINAPI
+WSCDeinstallProvider(LPGUID a0, LPINT a1)
+{
+ static int (WINAPI *fp)(LPGUID a0, LPINT a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSCDeinstallProvider() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSCDeinstallProvider")) == NULL) {
+ FATAL("cannot find entry WSCDeinstallProvider (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int WINAPI
+WSCEnableNSProvider(LPGUID a0, BOOL a1)
+{
+ static int (WINAPI *fp)(LPGUID a0, BOOL a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSCEnableNSProvider() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSCEnableNSProvider")) == NULL) {
+ FATAL("cannot find entry WSCEnableNSProvider (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int WINAPI
+WSCEnumProtocols(LPINT a0, LPWSAPROTOCOL_INFOW a1, LPDWORD a2, LPINT a3)
+{
+ static int (WINAPI *fp)(LPINT a0, LPWSAPROTOCOL_INFOW a1, LPDWORD a2, LPINT a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSCEnumProtocols() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSCEnumProtocols")) == NULL) {
+ FATAL("cannot find entry WSCEnumProtocols (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+int WINAPI
+WSCGetProviderPath(LPGUID a0, LPWSTR a1, LPINT a2, LPINT a3)
+{
+ static int (WINAPI *fp)(LPGUID a0, LPWSTR a1, LPINT a2, LPINT a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSCGetProviderPath() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSCGetProviderPath")) == NULL) {
+ FATAL("cannot find entry WSCGetProviderPath (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+int WINAPI
+WSCInstallNameSpace(LPWSTR a0, LPWSTR a1, DWORD a2, DWORD a3, LPGUID a4)
+{
+ static int (WINAPI *fp)(LPWSTR a0, LPWSTR a1, DWORD a2, DWORD a3, LPGUID a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSCInstallNameSpace() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSCInstallNameSpace")) == NULL) {
+ FATAL("cannot find entry WSCInstallNameSpace (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+int WINAPI
+WSCInstallProvider(const LPGUID a0, const LPWSTR a1, const LPWSAPROTOCOL_INFOW a2, DWORD a3, LPINT a4)
+{
+ static int (WINAPI *fp)(const LPGUID a0, const LPWSTR a1, const LPWSAPROTOCOL_INFOW a2, DWORD a3, LPINT a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSCInstallProvider() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSCInstallProvider")) == NULL) {
+ FATAL("cannot find entry WSCInstallProvider (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+int WINAPI
+WSCUnInstallNameSpace(LPGUID a0)
+{
+ static int (WINAPI *fp)(LPGUID a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSCUnInstallNameSpace() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSCUnInstallNameSpace")) == NULL) {
+ FATAL("cannot find entry WSCUnInstallNameSpace (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+WSAAsyncSelect(SOCKET a0, HWND a1, u_int a2, long a3)
+{
+ static int (PASCAL *fp)(SOCKET a0, HWND a1, u_int a2, long a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAsyncSelect() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncSelect")) == NULL) {
+ FATAL("cannot find entry WSAAsyncSelect (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+HANDLE PASCAL
+_org_WSAAsyncGetHostByAddr(HWND a0, u_int a1, const char* a2, int a3, int a4, char* a5, int a6)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, const char* a2, int a3, int a4, char* a5, int a6);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_WSAAsyncGetHostByAddr() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetHostByAddr")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetHostByAddr (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6);
+}
+
+HANDLE PASCAL
+_org_WSAAsyncGetHostByName(HWND a0, u_int a1, const char* a2, char* a3, int a4)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, const char* a2, char* a3, int a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_WSAAsyncGetHostByName() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetHostByName")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetHostByName (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+HANDLE PASCAL
+WSAAsyncGetProtoByNumber(HWND a0, u_int a1, int a2, char* a3, int a4)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, int a2, char* a3, int a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAsyncGetProtoByNumber() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetProtoByNumber")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetProtoByNumber (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+HANDLE PASCAL
+WSAAsyncGetProtoByName(HWND a0, u_int a1, const char* a2, char* a3, int a4)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, const char* a2, char* a3, int a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAsyncGetProtoByName() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetProtoByName")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetProtoByName (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+HANDLE PASCAL
+WSAAsyncGetServByPort(HWND a0, u_int a1, int a2, const char* a3, char* a4, int a5)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, int a2, const char* a3, char* a4, int a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAsyncGetServByPort() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetServByPort")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetServByPort (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+HANDLE PASCAL
+WSAAsyncGetServByName(HWND a0, u_int a1, const char* a2, const char* a3, char* a4, int a5)
+{
+ static HANDLE (PASCAL *fp)(HWND a0, u_int a1, const char* a2, const char* a3, char* a4, int a5);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAAsyncGetServByName() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAAsyncGetServByName")) == NULL) {
+ FATAL("cannot find entry WSAAsyncGetServByName (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5);
+}
+
+int PASCAL
+WSACancelAsyncRequest(HANDLE a0)
+{
+ static int (PASCAL *fp)(HANDLE a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSACancelAsyncRequest() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSACancelAsyncRequest")) == NULL) {
+ FATAL("cannot find entry WSACancelAsyncRequest (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+FARPROC PASCAL
+WSASetBlockingHook(FARPROC a0)
+{
+ static FARPROC (PASCAL *fp)(FARPROC a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASetBlockingHook() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASetBlockingHook")) == NULL) {
+ FATAL("cannot find entry WSASetBlockingHook (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0);
+}
+
+int PASCAL
+WSAUnhookBlockingHook(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAUnhookBlockingHook() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAUnhookBlockingHook")) == NULL) {
+ FATAL("cannot find entry WSAUnhookBlockingHook (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+int PASCAL
+WSAGetLastError(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAGetLastError() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAGetLastError")) == NULL) {
+ FATAL("cannot find entry WSAGetLastError (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+void PASCAL
+WSASetLastError(int a0)
+{
+ static void (PASCAL *fp)(int a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSASetLastError() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSASetLastError")) == NULL) {
+ FATAL("cannot find entry WSASetLastError (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ (*fp)(a0);
+}
+
+int PASCAL
+WSACancelBlockingCall(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSACancelBlockingCall() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSACancelBlockingCall")) == NULL) {
+ FATAL("cannot find entry WSACancelBlockingCall (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+BOOL PASCAL
+WSAIsBlocking(void)
+{
+ static BOOL (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAIsBlocking() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAIsBlocking")) == NULL) {
+ FATAL("cannot find entry WSAIsBlocking (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+int PASCAL
+WSAStartup(WORD a0, LPWSADATA a1)
+{
+ static int (PASCAL *fp)(WORD a0, LPWSADATA a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSAStartup() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSAStartup")) == NULL) {
+ FATAL("cannot find entry WSAStartup (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int PASCAL
+WSACleanup(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSACleanup() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSACleanup")) == NULL) {
+ FATAL("cannot find entry WSACleanup (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+int PASCAL
+__WSAFDIsSet(SOCKET a0, fd_set* a1)
+{
+ static int (PASCAL *fp)(SOCKET a0, fd_set* a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub __WSAFDIsSet() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "__WSAFDIsSet")) == NULL) {
+ FATAL("cannot find entry __WSAFDIsSet (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int PASCAL
+WEP(void)
+{
+ static int (PASCAL *fp)(void);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WEP() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WEP")) == NULL) {
+ FATAL("cannot find entry WEP (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)();
+}
+
+int PASCAL
+WSCWriteNameSpaceOrder(int a0, int a1)
+{
+ static int (PASCAL *fp)(int a0, int a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSCWriteNameSpaceOrder() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSCWriteNameSpaceOrder")) == NULL) {
+ FATAL("cannot find entry WSCWriteNameSpaceOrder (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int PASCAL
+WSCWriteProviderOrder(LPDWORD a0, DWORD a1)
+{
+ static int (PASCAL *fp)(LPDWORD a0, DWORD a1);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSCWriteProviderOrder() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSCWriteProviderOrder")) == NULL) {
+ FATAL("cannot find entry WSCWriteProviderOrder (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1);
+}
+
+int PASCAL
+WSANSPIoctl(HANDLE a0, DWORD a1, LPVOID a2, DWORD a3, LPVOID a4, DWORD a5, LPDWORD a6, LPVOID a7)
+{
+ static int (PASCAL *fp)(HANDLE a0, DWORD a1, LPVOID a2, DWORD a3, LPVOID a4, DWORD a5, LPDWORD a6, LPVOID a7);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSANSPIoctl() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSANSPIoctl")) == NULL) {
+ FATAL("cannot find entry WSANSPIoctl (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6, a7);
+}
+
+int PASCAL
+WSCUpdateProvider(LPGUID a0, const WCHAR FAR* a1, const LPVOID a2, DWORD a3, LPINT a4)
+{
+ static int (PASCAL *fp)(LPGUID a0, const WCHAR FAR* a1, const LPVOID a2, DWORD a3, LPINT a4);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub WSCUpdateProvider() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "WSCUpdateProvider")) == NULL) {
+ FATAL("cannot find entry WSCUpdateProvider (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4);
+}
+
+int PASCAL
+_org_getaddrinfo(const char* a0, const char* a1, LPVOID a2, LPVOID a3)
+{
+ static int (PASCAL *fp)(const char* a0, const char* a1, LPVOID a2, LPVOID a3);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_getaddrinfo() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getaddrinfo")) == NULL) {
+ FATAL("cannot find entry getaddrinfo (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3);
+}
+
+void PASCAL
+_org_freeaddrinfo(LPVOID a0)
+{
+ static void (PASCAL *fp)(LPVOID a0);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_freeaddrinfo() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "freeaddrinfo")) == NULL) {
+ FATAL("cannot find entry freeaddrinfo (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ (*fp)(a0);
+}
+
+int PASCAL
+_org_getnameinfo(LPVOID a0, DWORD a1, char* a2, DWORD a3, char* a4, DWORD a5, int a6)
+{
+ static int (PASCAL *fp)(LPVOID a0, DWORD a1, char* a2, DWORD a3, char* a4, DWORD a5, int a6);
+
+#ifdef DEBUG_STUB
+ idnLogPrintf(idn_log_level_trace, "stub _org_getnameinfo() called\n");
+#endif
+ if (fp == NULL) {
+ void *p;
+ if ((p = GetProcAddress(DLLHANDLE, "getnameinfo")) == NULL) {
+ FATAL("cannot find entry getnameinfo (%d)\n", GetLastError());
+ abort();
+ }
+ fp = p;
+ }
+ return (*fp)(a0, a1, a2, a3, a4, a5, a6);
+}
+
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock20/make.wnt b/contrib/idn/idnkit-1.0-src/wsock/wsock20/make.wnt
new file mode 100644
index 0000000..b5283aa
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock20/make.wnt
@@ -0,0 +1,97 @@
+#
+# Makefile for WinSock Wrapper (for WinSock 2.0)
+#
+
+# Copyright (c) 2000 Japan Network Information Center. All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set forth bellow.
+#
+# LICENSE TERMS AND CONDITIONS
+#
+# The following License Terms and Conditions apply, unless a different
+# license is obtained from Japan Network Information Center ("JPNIC"),
+# a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+# Chiyoda-ku, Tokyo 101-0047, Japan.
+#
+# 1. Use, Modification and Redistribution (including distribution of any
+# modified or derived work) in source and/or binary forms is permitted
+# under this License Terms and Conditions.
+#
+# 2. Redistribution of source code must retain the copyright notices as they
+# appear in each source code file, this License Terms and Conditions.
+#
+# 3. Redistribution in binary form must reproduce the Copyright Notice,
+# this License Terms and Conditions, in the documentation and/or other
+# materials provided with the distribution. For the purposes of binary
+# distribution the "Copyright Notice" refers to the following language:
+# "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+#
+# 4. The name of JPNIC may not be used to endorse or promote products
+# derived from this Software without specific prior written approval of
+# JPNIC.
+#
+# 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+!include <win32.mak>
+
+SYSLIBS = $(libcdll) kernel32.lib advapi32.lib user32.lib
+
+#
+# Files to use
+#
+
+HDRS = dlldef.h ..\common\wrapcommon.h
+SRCS = dllmain.c dllload.obj dllfunc.c dllstub.c
+OBJS = dllmain.obj dllload.obj dllfunc.obj
+LIBS = ..\common\wrapcommon.lib ..\..\lib\idnkit.lib ..\..\win\iconv.lib
+
+cflags = $(cflags) -I..\..\include
+
+#
+# Targets to Build
+#
+
+TARGETS = ws2_32.dll
+
+all : $(TARGETS)
+
+ws2_32.dll : ws2_32.def $(OBJS) $(LIBS)
+ $(link) $(dlllflags) /OUT:ws2_32.dll /DEF:ws2_32.def $(OBJS) $(LIBS) $(SYSLIBS)
+
+install : $(TARGETS)
+ copy ws2_32.dll ..\bin
+
+clean : force
+ -del *.obj
+ -del *.lib
+ -del *.dll
+ -del *.exp
+
+#
+# Dependencies
+#
+
+dllmain.obj : dllmain.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+dllload.obj : dllload.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+dllfunc.obj : dllfunc.c dllstub.c $(HDRS)
+ $(cc) $(cflags) $(cvarsdll) -DDEBUG $*.c
+
+ws2_32o.lib : ws2_32o.def
+ LIB /DEF:ws2_32o.def /MACHINE:IX86
+
+force:
+
diff --git a/contrib/idn/idnkit-1.0-src/wsock/wsock20/ws2_32.def b/contrib/idn/idnkit-1.0-src/wsock/wsock20/ws2_32.def
new file mode 100644
index 0000000..ba9a44c
--- /dev/null
+++ b/contrib/idn/idnkit-1.0-src/wsock/wsock20/ws2_32.def
@@ -0,0 +1,120 @@
+;
+; Library Defition for idn wrapper's wrapper DLL
+;
+LIBRARY ws2_32
+DESCRIPTION "JPNIC idn warpper DLL for WS2_32"
+EXPORTS
+ accept @1
+ bind @2
+ closesocket @3
+ connect @4
+ getpeername @5
+ getsockname @6
+ getsockopt @7
+ htonl @8
+ htons @9
+ ioctlsocket @10
+ inet_addr @11
+ inet_ntoa @12
+ listen @13
+ ntohl @14
+ ntohs @15
+ recv @16
+ recvfrom @17
+ select @18
+ send @19
+ sendto @20
+ setsockopt @21
+ shutdown @22
+ socket @23
+ WSApSetPostRoutine @24
+ WPUCompleteOverlappedRequest @25
+ WSAAccept @26
+ WSAAddressToStringA @27
+ WSAAddressToStringW @28
+ WSACloseEvent @29
+ WSAConnect @30
+ WSACreateEvent @31
+ WSADuplicateSocketA @32
+ WSADuplicateSocketW @33
+ WSAEnumNameSpaceProvidersA @34
+ WSAEnumNameSpaceProvidersW @35
+ WSAEnumNetworkEvents @36
+ WSAEnumProtocolsA @37
+ WSAEnumProtocolsW @38
+ WSAEventSelect @39
+ WSAGetOverlappedResult @40
+ WSAGetQOSByName @41
+ WSAGetServiceClassInfoA @42
+ WSAGetServiceClassInfoW @43
+ WSAGetServiceClassNameByClassIdA @44
+ WSAGetServiceClassNameByClassIdW @45
+ WSAHtonl @46
+ WSAHtons @47
+ WSAInstallServiceClassA @48
+ WSAInstallServiceClassW @49
+ WSAIoctl @50
+ gethostbyaddr @51
+ gethostbyname @52
+ getprotobyname @53
+ getprotobynumber @54
+ getservbyname @55
+ getservbyport @56
+ gethostname @57
+ WSAJoinLeaf @58
+ WSALookupServiceBeginA @59
+ WSALookupServiceBeginW @60
+ WSALookupServiceEnd @61
+ WSALookupServiceNextA @62
+ WSALookupServiceNextW @63
+ WSANtohl @64
+ WSANtohs @65
+ WSAProviderConfigChange @66
+ WSARecv @67
+ WSARecvDisconnect @68
+ WSARecvFrom @69
+ WSARemoveServiceClass @70
+ WSAResetEvent @71
+ WSASend @72
+ WSASendDisconnect @73
+ WSASendTo @74
+ WSASetEvent @75
+ WSASetServiceA @76
+ WSASetServiceW @77
+ WSASocketA @78
+ WSASocketW @79
+ WSAStringToAddressA @80
+ WSAStringToAddressW @81
+ WSAWaitForMultipleEvents @82
+ WSCDeinstallProvider @83
+ WSCEnableNSProvider @84
+ WSCEnumProtocols @85
+ WSCGetProviderPath @86
+ WSCInstallNameSpace @87
+ WSCInstallProvider @88
+ WSCUnInstallNameSpace @89
+ WSCWriteNameSpaceOrder @90
+ WSCWriteProviderOrder @91
+ freeaddrinfo @94
+ getaddrinfo @95
+ getnameinfo @96
+ WSAAsyncSelect @101
+ WSAAsyncGetHostByAddr @102
+ WSAAsyncGetHostByName @103
+ WSAAsyncGetProtoByNumber @104
+ WSAAsyncGetProtoByName @105
+ WSAAsyncGetServByPort @106
+ WSAAsyncGetServByName @107
+ WSACancelAsyncRequest @108
+ WSASetBlockingHook @109
+ WSAUnhookBlockingHook @110
+ WSAGetLastError @111
+ WSASetLastError @112
+ WSACancelBlockingCall @113
+ WSAIsBlocking @114
+ WSAStartup @115
+ WSACleanup @116
+ __WSAFDIsSet @151
+ WEP @500
+ WSANSPIoctl @600
+ WSCUpdateProvider @601
diff --git a/contrib/linux/coredump-patch b/contrib/linux/coredump-patch
new file mode 100644
index 0000000..d179290
--- /dev/null
+++ b/contrib/linux/coredump-patch
@@ -0,0 +1,12 @@
+--- binfmt_elf.c.old Mon Dec 11 10:49:57 2000
++++ binfmt_elf.c Wed Nov 1 13:05:23 2000
+@@ -1091,7 +1091,8 @@
+
+ if (!current->dumpable ||
+ limit < ELF_EXEC_PAGESIZE ||
+- atomic_read(&current->mm->count) != 1)
++/* atomic_read(&current->mm->count) != 1) */
++ test_and_set_bit(31, &current->mm->def_flags) != 0)
+ return 0;
+ current->dumpable = 0;
+
diff --git a/contrib/named-bootconf/named-bootconf.sh b/contrib/named-bootconf/named-bootconf.sh
new file mode 100644
index 0000000..029e35b
--- /dev/null
+++ b/contrib/named-bootconf/named-bootconf.sh
@@ -0,0 +1,314 @@
+#!/bin/sh
+#
+# Portions Copyright (C) 2004, 2006, 2007 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
+# 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-bootconf.sh,v 1.12 2007/06/19 23:47:07 tbox Exp $
+
+# $NetBSD: named-bootconf.sh,v 1.5 1998/12/15 01:00:53 tron Exp $
+#
+# Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by Matthias Scheler.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the NetBSD
+# Foundation, Inc. and its contributors.
+# 4. Neither the name of The NetBSD Foundation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+if [ ${OPTIONFILE-X} = X ]; then
+ WORKDIR=/tmp/`date +%s`.$$
+ ( umask 077 ; mkdir $WORKDIR ) || {
+ echo "unable to create work directory '$WORKDIR'" >&2
+ exit 1
+ }
+ OPTIONFILE=$WORKDIR/options
+ ZONEFILE=$WORKDIR/zones
+ COMMENTFILE=$WORKDIR/comments
+ export OPTIONFILE ZONEFILE COMMENTFILE
+ touch $OPTIONFILE $ZONEFILE $COMMENTFILE
+ DUMP=1
+else
+ DUMP=0
+fi
+
+while read CMD ARGS; do
+ class=
+ CMD=`echo "${CMD}" | tr '[A-Z]' '[a-z]'`
+ case $CMD in
+ \; )
+ echo \# $ARGS >>$COMMENTFILE
+ ;;
+ cache )
+ set - X $ARGS
+ shift
+ if [ $# -eq 2 ]; then
+ (echo ""
+ cat $COMMENTFILE
+ echo "zone \"$1\" {"
+ echo " type hint;"
+ echo " file \"$2\";"
+ echo "};") >>$ZONEFILE
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+ fi
+ ;;
+ directory )
+ set - X $ARGS
+ shift
+ if [ $# -eq 1 ]; then
+ (cat $COMMENTFILE
+ echo " directory \"$1\";") >>$OPTIONFILE
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+
+ DIRECTORY=$1
+ export DIRECTORY
+ fi
+ ;;
+ forwarders )
+ (cat $COMMENTFILE
+ echo " forwarders {"
+ for ARG in $ARGS; do
+ echo " $ARG;"
+ done
+ echo " };") >>$OPTIONFILE
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+ ;;
+ include )
+ if [ "$ARGS" != "" ]; then
+ (cd ${DIRECTORY-.}; cat $ARGS) | $0
+ fi
+ ;;
+ limit )
+ ARGS=`echo "${ARGS}" | tr '[A-Z]' '[a-z]'`
+ set - X $ARGS
+ shift
+ if [ $# -eq 2 ]; then
+ cat $COMMENTFILE >>$OPTIONFILE
+ case $1 in
+ datasize | files | transfers-in | transfers-per-ns )
+ echo " $1 $2;" >>$OPTIONFILE
+ ;;
+ esac
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+ fi
+ ;;
+ options )
+ ARGS=`echo "${ARGS}" | tr '[A-Z]' '[a-z]'`
+ cat $COMMENTFILE >>$OPTIONFILE
+ for ARG in $ARGS; do
+ case $ARG in
+ fake-iquery )
+ echo " fake-iquery yes;" >>$OPTIONFILE
+ ;;
+ forward-only )
+ echo " forward only;" >>$OPTIONFILE
+ ;;
+ no-fetch-glue )
+ echo " fetch-glue no;" >>$OPTIONFILE
+ ;;
+ no-recursion )
+ echo " recursion no;" >>$OPTIONFILE
+ ;;
+ esac
+ done
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+ ;;
+ primary|primary/* )
+ case $CMD in
+ primary/chaos )
+ class="chaos "
+ ;;
+ primary/hs )
+ class="hesiod "
+ ;;
+ esac
+ set - X $ARGS
+ shift
+ if [ $# -eq 2 ]; then
+ (echo ""
+ cat $COMMENTFILE
+ echo "zone \"$1\" ${class}{"
+ echo " type master;"
+ echo " file \"$2\";"
+ echo "};") >>$ZONEFILE
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+ fi
+ ;;
+ secondary|secondary/* )
+ case $CMD in
+ secondary/chaos )
+ class="chaos "
+ ;;
+ secondary/hs )
+ class="hesiod "
+ ;;
+ esac
+ set - X $ARGS
+ shift
+ if [ $# -gt 2 ]; then
+ ZONE=$1
+ shift
+ PRIMARIES=$1
+ while [ $# -gt 2 ]; do
+ shift
+ PRIMARIES="$PRIMARIES $1"
+ done
+ (echo ""
+ cat $COMMENTFILE
+ echo "zone \"$ZONE\" ${class}{"
+ echo " type slave;"
+ echo " file \"$2\";"
+ echo " masters {"
+ for PRIMARY in $PRIMARIES; do
+ echo " $PRIMARY;"
+ done
+ echo " };"
+ echo "};") >>$ZONEFILE
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+ fi
+ ;;
+ stub|stub/* )
+ case $CMD in
+ stub/chaos )
+ class="chaos "
+ ;;
+ stub/hs )
+ class="hesiod "
+ ;;
+ esac
+ set - X $ARGS
+ shift
+ if [ $# -gt 2 ]; then
+ ZONE=$1
+ shift
+ PRIMARIES=$1
+ while [ $# -gt 2 ]; do
+ shift
+ PRIMARIES="$PRIMARIES $1"
+ done
+ (echo ""
+ cat $COMMENTFILE
+ echo "zone \"$ZONE\" ${class}{"
+ echo " type stub;"
+ echo " file \"$2\";"
+ echo " masters {"
+ for PRIMARY in $PRIMARIES; do
+ echo " $PRIMARY;"
+ done
+ echo " };"
+ echo "};") >>$ZONEFILE
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+ fi
+ ;;
+ slave )
+ cat $COMMENTFILE >>$OPTIONFILE
+ echo " forward only;" >>$OPTIONFILE
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+ ;;
+ sortlist )
+ (cat $COMMENTFILE
+ echo " topology {"
+ for ARG in $ARGS; do
+ case $ARG in
+ *.0.0.0 )
+ echo " $ARG/8;"
+ ;;
+ *.0.0 )
+ echo " $ARG/16;"
+ ;;
+ *.0 )
+ echo " $ARG/24;"
+ ;;
+ * )
+ echo " $ARG;"
+ ;;
+ esac
+ done
+ echo " };") >>$OPTIONFILE
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+ ;;
+ tcplist | xfrnets )
+ (cat $COMMENTFILE
+ echo " allow-transfer {"
+ for ARG in $ARGS; do
+ case $ARG in
+ *.0.0.0 )
+ echo " $ARG/8;"
+ ;;
+ *.0.0 )
+ echo " $ARG/16;"
+ ;;
+ *.0 )
+ echo " $ARG/24;"
+ ;;
+ * )
+ echo " $ARG;"
+ ;;
+ esac
+ done
+ echo " };") >>$OPTIONFILE
+ rm -f $COMMENTFILE
+ touch $COMMENTFILE
+ ;;
+ esac
+done
+
+if [ $DUMP -eq 1 ]; then
+ echo ""
+ echo "options {"
+ cat $OPTIONFILE
+ echo "};"
+ cat $ZONEFILE $COMMENTFILE
+
+ rm -f $OPTIONFILE $ZONEFILE $COMMENTFILE
+ rmdir $WORKDIR
+fi
+
+exit 0
diff --git a/contrib/nanny/nanny.pl b/contrib/nanny/nanny.pl
new file mode 100644
index 0000000..16ecf1f
--- /dev/null
+++ b/contrib/nanny/nanny.pl
@@ -0,0 +1,55 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2004, 2007 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: nanny.pl,v 1.11 2007/06/19 23:47:07 tbox Exp $
+
+# A simple nanny to make sure named stays running.
+
+$pid_file_location = '/var/run/named.pid';
+$nameserver_location = 'localhost';
+$dig_program = 'dig';
+$named_program = 'named';
+
+fork() && exit();
+
+for (;;) {
+ $pid = 0;
+ open(FILE, $pid_file_location) || goto restart;
+ $pid = <FILE>;
+ close(FILE);
+ chomp($pid);
+
+ $res = kill 0, $pid;
+
+ goto restart if ($res == 0);
+
+ $dig_command =
+ "$dig_program +short . \@$nameserver_location > /dev/null";
+ $return = system($dig_command);
+ goto restart if ($return == 9);
+
+ sleep 30;
+ next;
+
+ restart:
+ if ($pid != 0) {
+ kill 15, $pid;
+ sleep 30;
+ }
+ system ($named_program);
+ sleep 120;
+}
diff --git a/contrib/nslint-2.1a3/CHANGES b/contrib/nslint-2.1a3/CHANGES
new file mode 100644
index 0000000..c425e01
--- /dev/null
+++ b/contrib/nslint-2.1a3/CHANGES
@@ -0,0 +1,191 @@
+@(#) $Id: CHANGES,v 1.1 2001/12/21 04:12:02 marka Exp $ (LBL)
+
+v2.1 Wed Aug 22 18:30:35 PDT 2001
+
+- Handle "srv" records.
+
+- Fix some ttl parsing problems.
+
+- Add "ignore" option
+
+v2.0.2 Tue Mar 20 17:49:13 PST 2001
+
+- Allow missing trailing dot in certain special cases.
+
+- Include zone names when checking NS records.
+
+- Document nslint.conf network keyword.
+
+v2.0.1 Tue Dec 14 11:24:31 PST 1999
+
+- Handle $ttl.
+
+- Fix some minor portability/compiler problems for OSF 4.
+
+- Correctly detect mx records that point to themselves but not a
+ real "a" record.
+
+- Fix file descriptor leak in doconf(). Thanks to Paul McIlfatrick
+ (paul.mcilfatrick@bt.com)
+
+v2.0 Wed Dec 9 16:48:54 PST 1998
+
+- Add support for BIND 8 named.conf file.
+
+- Support protocols in addition to tcp and udp for WKS records.
+ Resulted from a bug report from Petter Reinholdtsen (pere@td.org.uit.no)
+
+- Support dotted serial numbers in SOA records. Resulted from a
+ bug report from Frank Ederveen (frank@our.domaintje.com)
+
+- Ignore unknown statements and options in named.boot and named.conf
+ (instead of issuing warnings).
+
+- Handle '#' and C style named.conf comments.
+
+- Handle optional "in" in named.conf zone statements. Reported by
+ DJ Coster (djc@discoverbrokerage.com)
+
+- Add support for include directives in named.boot and named.conf.
+
+- Redo differing ttls check and do mx records in addition to a
+ records. Change place where soa values gets zeroed so they don't
+ get clobbered when we use includes.
+
+- Allow "@" abbr. for ptr, mx, cname and ns records.
+
+- Detect cname referenced by another cname or mx record.
+
+- Handle chaos records (to some minor extent).
+
+v1.7 Tue Jul 22 14:26:21 PDT 1997
+
+- Report differing ttls in A records. Check SOA records.
+
+- Detect hosts with more than one ip address on a subnet.
+
+v1.6.1 Sat Jun 7 03:12:01 PDT 1997
+
+- Fix "unknown service" printf format.
+
+- Fix off-by-one error in the ptr parsing code. Thanks to Andreas
+ Lamprecht (andreas.lamprecht@siemens.at)
+
+- Fix broken $origin code.
+
+v1.6 Mon Apr 7 19:09:52 PDT 1997
+
+- Add support for classless delegation.
+
+- Fix some case sensitive bugs.
+
+- Report domain names outside the current zone.
+
+- Fixed off-by-one bug that broke single character hostnames.
+
+- Increase size of hash table.
+
+- Make tcp and udp service name tables dynamic.
+
+- Improved error message for garbage in /etc/services.
+
+v1.5.1 Thu Jul 18 21:44:44 PDT 1996
+
+- Use $CC when checking gcc version. Thanks to Carl Lindberg
+ (carl_lindberg@blacksmith.com)
+
+- Raise size of hash table to 65K.
+
+v1.5 Fri Jul 12 18:58:47 PDT 1996
+
+- Detect extra octets and other garbage in PTR records.
+
+- Handle multi-line WKS records.
+
+- Allow multple WKS records (since we can have udp and tcp).
+
+- Convert to autoconf.
+
+- Declare optarg, optind and opterr extern. Thanks to Howard Moftich
+ (howardm@lsil.com).
+
+- BS/DOS does not have malloc.h. Thanks to Jordan Hayes
+ (jordan@thinkbank.com).
+
+- Correctly handle named.boot comments with leading whitespace.
+
+- Handle fully specified in-addr.arpa records. Resulted from a bug
+ report from Joe Kelly (joe@gol.com).
+
+- Fix endian problems. Thanks to Carl Lindberg (carl_lindberg@blacksmith.com).
+
+- Fixed some mixed case problems.
+
+- Update man page to describe how nslint.boot works.
+
+v1.4 Sat Jun 3 23:38:14 PDT 1995
+
+- Allow TXT records to exist with no other records.
+
+- Full system prototypes.
+
+- Complain about extra arguments.
+
+- Detect MX record chains.
+
+- Handle single line SOA records correctly. Thanks to Edward J. O'Brien
+ (ejobrie@sam.wal-mart.com)
+
+v1.3 Wed Mar 8 17:27:20 PST 1995
+
+- Add "allowdupa" record type for use with nslint.boot. This allows ip
+ addresses to have multiple A records.
+
+- Fixed bug that caused dangling cname references to not be reported
+ properly. Thanks to Edward J. O'Brien (ejobrie@sam.wal-mart.com).
+
+v1.2 Thu Sep 1 15:55:38 PDT 1994
+
+- Allow hostnames with a leading numeric as per rfc1123. Thanks to Bill
+ Gianopoulos (wag@sccux1.msd.ray.com).
+
+- Remove (undocumented) -u flag and allow uppercase.
+
+- Support TXT records. Thanks to Paul Pomes (paul@uxc.cso.uiuc.edu).
+
+- Support RP records.
+
+- Ignore new bind keywords.
+
+- Fix bug where we could exit with a zero status even though errors had
+ been detected
+
+- Complain about hosts that have smtp/tcp WKS entries but no MX records.
+
+- Add -B flag to handle PTR records that point outside the domains
+ listed in named.boot.
+
+v1.1 Sun May 22 20:43:03 PDT 1994
+
+- Allow ns records with no a records (the preferred way to go).
+
+- Fix typos in the sawstr array.
+
+- Use string.h instead of strings.h and add rindex(), index() and
+ bzero() macros for SYSV compatibility. Thanks to Bill King
+ (wrk@cle.ab.com).
+
+- Handle $origin directives. Thanks to Bill Gianopoulos
+ (wag@sccux1.msd.ray.com).
+
+- Fix add_domain() to work for the root. Thanks to Bill Gianopoulos.
+
+- Handle quotes in hinfo records. Thanks to Bill Gianopoulos.
+
+- Fix endian problems in parseinaddr() and parseptr().
+
+- Check non in-addr.arpa names for cname conflicts.
+
+v1.0 Thu Apr 21 11:02:59 PDT 1994
+
+- Initial release.
diff --git a/contrib/nslint-2.1a3/FILES b/contrib/nslint-2.1a3/FILES
new file mode 100644
index 0000000..ddb8d44
--- /dev/null
+++ b/contrib/nslint-2.1a3/FILES
@@ -0,0 +1,24 @@
+CHANGES
+FILES
+INSTALL
+Makefile.in
+README
+VERSION
+aclocal.m4
+config.guess
+config.sub
+configure
+configure.in
+install-sh
+lbl/gnuc.h
+lbl/os-irix5.h
+lbl/os-osf3.h
+lbl/os-solaris2.h
+lbl/os-sunos4.h
+lbl/os-ultrix4.h
+mkdep
+nslint.8
+nslint.c
+savestr.c
+savestr.h
+strerror.c
diff --git a/contrib/nslint-2.1a3/INSTALL b/contrib/nslint-2.1a3/INSTALL
new file mode 100644
index 0000000..c92bfbe
--- /dev/null
+++ b/contrib/nslint-2.1a3/INSTALL
@@ -0,0 +1,42 @@
+@(#) $Header: /proj/cvs/prod/bind9/contrib/nslint-2.1a3/INSTALL,v 1.1 2001/12/21 04:12:02 marka Exp $ (LBL)
+
+You will need an ANSI C compiler to build nslint. The configure
+script will abort if your compiler is not ANSI compliant. If this
+happens, use the GNU C compiler, available via anonymous ftp:
+
+ ftp://prep.ai.mit.edu/pub/gnu/gcc.tar.gz
+
+If necessary, edit the BINDEST and MANDEST paths in Makefile.in
+and run ./configure (a shell script). "configure" will determine
+your system attributes and generate an appropriate Makefile from
+Makefile.in. Now build nslint by running "make".
+
+If everything builds ok, su and type "make install" (and optionally
+"make install-man). This will install nslint and its manual entry.
+
+If your system is not one which we have tested nslint on, you may
+have to modify the configure script and Makefile.in. Please send
+us patches for any modifications you need to make.
+
+FILES
+-----
+CHANGES - description of differences between releases
+FILES - list of files exported as part of the distribution
+INSTALL - this file
+Makefile.in - compilation rules (input to the configure script)
+README - description of distribution
+VERSION - version of this release
+aclocal.m4 - autoconf macros
+config.guess - autoconf support
+config.sub - autoconf support
+configure - configure script (run this first)
+configure.in - configure script source
+install-sh - BSD style install script
+lbl/gnuc.h - gcc macros and defines
+lbl/os-*.h - os dependent defines and prototypes
+mkdep - construct Makefile dependency list
+nslint.8 - manual entry
+nslint.c - main program
+savestr.c - strdup() replacement
+savestr.h - savestr prototypes
+strerror.c - missing routine
diff --git a/contrib/nslint-2.1a3/Makefile.in b/contrib/nslint-2.1a3/Makefile.in
new file mode 100644
index 0000000..60ed017
--- /dev/null
+++ b/contrib/nslint-2.1a3/Makefile.in
@@ -0,0 +1,122 @@
+# Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997, 2000
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that: (1) source code distributions
+# retain the above copyright notice and this paragraph in its entirety, (2)
+# distributions including binary code include the above copyright notice and
+# this paragraph in its entirety in the documentation or other materials
+# provided with the distribution, and (3) all advertising materials mentioning
+# features or use of this software display the following acknowledgement:
+# ``This product includes software developed by the University of California,
+# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+# the University nor the names of its contributors may be used to endorse
+# or promote products derived from this software without specific prior
+# written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+#
+# @(#) $Id: Makefile.in,v 1.2 2004/07/20 07:13:40 marka Exp $ (LBL)
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+# Pathname of directory to install the binary
+BINDEST = @bindir@
+# Pathname of directory to install the man page
+MANDEST = @mandir@
+
+# VPATH
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+#
+# You shouldn't need to edit anything below here.
+#
+
+PROG = nslint
+CC = @CC@
+CCOPT = @V_CCOPT@
+INCLS = @V_INCLS@
+DEFS = @DEFS@
+
+# Standard CFLAGS
+CFLAGS = $(CCOPT) $(DEFS) $(INCLS)
+
+# Standard LIBS
+LIBS = @LIBS@
+
+INSTALL = @INSTALL@
+
+# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
+# Also, gcc does not remove the .o before forking 'as', which can be a
+# problem if you don't own the file but can write to the directory.
+.c.o:
+ @rm -f $@
+ $(CC) $(CFLAGS) -c $(srcdir)/$*.c
+
+CSRC = nslint.c savestr.c
+GENSRC = version.c
+
+SRC = $(CSRC) $(GENSRC)
+
+# We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
+# hack the extra indirection
+OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) @LIBOBJS@
+
+TAGHDR = \
+ /usr/include/sys/types.h \
+ /usr/include/netinet/in.h
+
+TAGFILES = $(SRC) $(TAGHDR)
+
+CLEANFILES = $(PROG) $(OBJ) $(GENSRC)
+
+$(PROG): $(OBJ)
+ @rm -f $@
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
+
+version.o: version.c
+version.c: $(srcdir)/VERSION
+ @rm -f $@
+ sed -e 's/.*/char version[] = "&";/' $(srcdir)/VERSION > $@
+
+install: force
+ $(INSTALL) -m 555 -o bin -g bin $(PROG) $(DESTDIR)$(BINDEST)/$(PROG)
+
+install-man: force
+ $(INSTALL) -m 444 -o bin -g bin $(srcdir)/$(PROG).8 \
+ $(DESTDIR)$(MANDEST)/man8/$(PROG).8
+
+clean: force
+ rm -f $(CLEANFILES)
+
+distclean: force
+ rm -f $(CLEANFILES) Makefile config.cache config.log config.status \
+ gnuc.h os-proto.h
+
+tags: $(TAGFILES)
+ ctags -wtd $(TAGFILES)
+
+tar: force
+ @cwd=`pwd` ; name=$(PROG)-`cat VERSION` ; \
+ list="" ; tar="tar chf" ; temp="$$name.tar.gz" ; \
+ for i in `cat FILES` ; do list="$$list $$name/$$i" ; done; \
+ echo \
+ "rm -f $$name; ln -s . $$name" ; \
+ rm -f $$name; ln -s . $$name ; \
+ echo \
+ "$$tar - [lots of files] | gzip > $$temp" ; \
+ $$tar - $$list | gzip > $$temp ; \
+ echo \
+ "rm -f $$name" ; \
+ rm -f $$name
+
+force: /tmp
+depend: $(GENSRC) force
+ ./mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC)
diff --git a/contrib/nslint-2.1a3/README b/contrib/nslint-2.1a3/README
new file mode 100644
index 0000000..39f0202
--- /dev/null
+++ b/contrib/nslint-2.1a3/README
@@ -0,0 +1,14 @@
+@(#) $Id: README,v 1.1 2001/12/21 04:12:02 marka Exp $ (LBL)
+
+NSLINT 2.0
+Lawrence Berkeley National Laboratory
+Network Research Group
+nslint@ee.lbl.gov
+ftp://ftp.ee.lbl.gov/nslint.tar.gz
+
+This directory contains source code for nslint, a lint program for dns
+files.
+
+Please send bugs and comments to nslint@ee.lbl.gov.
+
+ - Craig Leres
diff --git a/contrib/nslint-2.1a3/VERSION b/contrib/nslint-2.1a3/VERSION
new file mode 100644
index 0000000..375279c
--- /dev/null
+++ b/contrib/nslint-2.1a3/VERSION
@@ -0,0 +1 @@
+2.1a3
diff --git a/contrib/nslint-2.1a3/aclocal.m4 b/contrib/nslint-2.1a3/aclocal.m4
new file mode 100644
index 0000000..9f1d33f
--- /dev/null
+++ b/contrib/nslint-2.1a3/aclocal.m4
@@ -0,0 +1,765 @@
+dnl @(#) $Header: /proj/cvs/prod/bind9/contrib/nslint-2.1a3/aclocal.m4,v 1.1 2001/12/21 04:12:03 marka Exp $ (LBL)
+dnl
+dnl Copyright (c) 1995, 1996, 1997, 1998, 1999
+dnl The Regents of the University of California. All rights reserved.
+dnl
+dnl Redistribution and use in source and binary forms, with or without
+dnl modification, are permitted provided that: (1) source code distributions
+dnl retain the above copyright notice and this paragraph in its entirety, (2)
+dnl distributions including binary code include the above copyright notice and
+dnl this paragraph in its entirety in the documentation or other materials
+dnl provided with the distribution, and (3) all advertising materials mentioning
+dnl features or use of this software display the following acknowledgement:
+dnl ``This product includes software developed by the University of California,
+dnl Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+dnl the University nor the names of its contributors may be used to endorse
+dnl or promote products derived from this software without specific prior
+dnl written permission.
+dnl THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+dnl WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+dnl MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+dnl
+dnl LBL autoconf macros
+dnl
+
+dnl
+dnl Determine which compiler we're using (cc or gcc)
+dnl If using gcc, determine the version number
+dnl If using cc, require that it support ansi prototypes
+dnl If using gcc, use -O2 (otherwise use -O)
+dnl If using cc, explicitly specify /usr/local/include
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_C_INIT(copt, incls)
+dnl
+dnl results:
+dnl
+dnl $1 (copt set)
+dnl $2 (incls set)
+dnl CC
+dnl LDFLAGS
+dnl LBL_CFLAGS
+dnl
+AC_DEFUN(AC_LBL_C_INIT,
+ [AC_PREREQ(2.12)
+ AC_BEFORE([$0], [AC_PROG_CC])
+ AC_BEFORE([$0], [AC_LBL_FIXINCLUDES])
+ AC_BEFORE([$0], [AC_LBL_DEVEL])
+ AC_ARG_WITH(gcc, [ --without-gcc don't use gcc])
+ $1="-O"
+ $2=""
+ if test "${srcdir}" != "." ; then
+ $2="-I\$\(srcdir\)"
+ fi
+ if test "${CFLAGS+set}" = set; then
+ LBL_CFLAGS="$CFLAGS"
+ fi
+ if test -z "$CC" ; then
+ case "$target_os" in
+
+ bsdi*)
+ AC_CHECK_PROG(SHLICC2, shlicc2, yes, no)
+ if test $SHLICC2 = yes ; then
+ CC=shlicc2
+ export CC
+ fi
+ ;;
+ esac
+ fi
+ if test -z "$CC" -a "$with_gcc" = no ; then
+ CC=cc
+ export CC
+ fi
+ AC_PROG_CC
+ if test "$GCC" != yes ; then
+ AC_MSG_CHECKING(that $CC handles ansi prototypes)
+ AC_CACHE_VAL(ac_cv_lbl_cc_ansi_prototypes,
+ AC_TRY_COMPILE(
+ [#include <sys/types.h>],
+ [int frob(int, char *)],
+ ac_cv_lbl_cc_ansi_prototypes=yes,
+ ac_cv_lbl_cc_ansi_prototypes=no))
+ AC_MSG_RESULT($ac_cv_lbl_cc_ansi_prototypes)
+ if test $ac_cv_lbl_cc_ansi_prototypes = no ; then
+ case "$target_os" in
+
+ hpux*)
+ AC_MSG_CHECKING(for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE))
+ savedcflags="$CFLAGS"
+ CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS"
+ AC_CACHE_VAL(ac_cv_lbl_cc_hpux_cc_aa,
+ AC_TRY_COMPILE(
+ [#include <sys/types.h>],
+ [int frob(int, char *)],
+ ac_cv_lbl_cc_hpux_cc_aa=yes,
+ ac_cv_lbl_cc_hpux_cc_aa=no))
+ AC_MSG_RESULT($ac_cv_lbl_cc_hpux_cc_aa)
+ if test $ac_cv_lbl_cc_hpux_cc_aa = no ; then
+ AC_MSG_ERROR(see the INSTALL doc for more info)
+ fi
+ CFLAGS="$savedcflags"
+ $1="-Aa $$1"
+ AC_DEFINE(_HPUX_SOURCE)
+ ;;
+
+ *)
+ AC_MSG_ERROR(see the INSTALL doc for more info)
+ ;;
+ esac
+ fi
+ $2="$$2 -I/usr/local/include"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+ case "$target_os" in
+
+ irix*)
+ $1="$$1 -xansi -signed -g3"
+ ;;
+
+ osf*)
+ $1="$$1 -std1 -g3"
+ ;;
+
+ ultrix*)
+ AC_MSG_CHECKING(that Ultrix $CC hacks const in prototypes)
+ AC_CACHE_VAL(ac_cv_lbl_cc_const_proto,
+ AC_TRY_COMPILE(
+ [#include <sys/types.h>],
+ [struct a { int b; };
+ void c(const struct a *)],
+ ac_cv_lbl_cc_const_proto=yes,
+ ac_cv_lbl_cc_const_proto=no))
+ AC_MSG_RESULT($ac_cv_lbl_cc_const_proto)
+ if test $ac_cv_lbl_cc_const_proto = no ; then
+ AC_DEFINE(const,)
+ fi
+ ;;
+ esac
+ fi
+])
+
+dnl
+dnl Use pfopen.c if available and pfopen() not in standard libraries
+dnl Require libpcap
+dnl Look for libpcap in ..
+dnl Use the installed libpcap if there is no local version
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_LIBPCAP(pcapdep, incls)
+dnl
+dnl results:
+dnl
+dnl $1 (pcapdep set)
+dnl $2 (incls appended)
+dnl LIBS
+dnl LDFLAGS
+dnl LBL_LIBS
+dnl
+AC_DEFUN(AC_LBL_LIBPCAP,
+ [AC_REQUIRE([AC_LBL_LIBRARY_NET])
+ dnl
+ dnl save a copy before locating libpcap.a
+ dnl
+ LBL_LIBS="$LIBS"
+ pfopen=/usr/examples/packetfilter/pfopen.c
+ if test -f $pfopen ; then
+ AC_CHECK_FUNCS(pfopen)
+ if test $ac_cv_func_pfopen = "no" ; then
+ AC_MSG_RESULT(Using $pfopen)
+ LIBS="$LIBS $pfopen"
+ fi
+ fi
+ AC_MSG_CHECKING(for local pcap library)
+ libpcap=FAIL
+ lastdir=FAIL
+ places=`ls .. | sed -e 's,/$,,' -e 's,^,../,' | \
+ egrep '/libpcap-[[0-9]]*\.[[0-9]]*(\.[[0-9]]*)?([[ab]][[0-9]]*)?$'`
+ for dir in $places ../libpcap libpcap ; do
+ basedir=`echo $dir | sed -e 's/[[ab]][[0-9]]*$//'`
+ if test $lastdir = $basedir ; then
+ dnl skip alphas when an actual release is present
+ continue;
+ fi
+ lastdir=$dir
+ if test -r $dir/pcap.c ; then
+ libpcap=$dir/libpcap.a
+ d=$dir
+ dnl continue and select the last one that exists
+ fi
+ done
+ if test "x$libpcap" = xFAIL ; then
+ AC_MSG_RESULT(not found)
+ unset ac_cv_lbl_lib_pcap_pcap_open_live_
+ AC_LBL_CHECK_LIB(pcap, pcap_open_live, libpcap="-lpcap")
+ if test "x$libpcap" = xFAIL ; then
+ unset ac_cv_lbl_lib_pcap_pcap_open_live_
+ CFLAGS="$CFLAGS -I/usr/local/include"
+ LIBS="$LIBS -L/usr/local/lib"
+ AC_LBL_CHECK_LIB(pcap, pcap_open_live, libpcap="-lpcap")
+ if test "x$libpcap" = xFAIL ; then
+ AC_MSG_ERROR(see the INSTALL doc for more info)
+ fi
+ $2="$$2 -I/usr/local/include"
+ fi
+ LIBS="$LIBS -lpcap"
+ else
+ $1=$libpcap
+ $2="-I$d $$2"
+ AC_MSG_RESULT($libpcap)
+ fi
+ if test "x$libpcap" != "x-lpcap" ; then
+ LIBS="$libpcap $LIBS"
+ fi
+ case "$target_os" in
+
+ aix*)
+ pseexe="/lib/pse.exp"
+ AC_MSG_CHECKING(for $pseexe)
+ if test -f $pseexe ; then
+ AC_MSG_RESULT(yes)
+ LIBS="$LIBS -I:$pseexe"
+ fi
+ ;;
+ esac])
+
+dnl
+dnl Define RETSIGTYPE and RETSIGVAL
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_TYPE_SIGNAL
+dnl
+dnl results:
+dnl
+dnl RETSIGTYPE (defined)
+dnl RETSIGVAL (defined)
+dnl
+AC_DEFUN(AC_LBL_TYPE_SIGNAL,
+ [AC_BEFORE([$0], [AC_LBL_LIBPCAP])
+ AC_TYPE_SIGNAL
+ if test "$ac_cv_type_signal" = void ; then
+ AC_DEFINE(RETSIGVAL,)
+ else
+ AC_DEFINE(RETSIGVAL,(0))
+ fi
+ case "$target_os" in
+
+ irix*)
+ AC_DEFINE(_BSD_SIGNALS)
+ ;;
+
+ *)
+ dnl prefer sigset() to sigaction()
+ AC_CHECK_FUNCS(sigset)
+ if test $ac_cv_func_sigset = yes ; then
+ AC_DEFINE(signal,sigset)
+ else
+ AC_CHECK_FUNCS(sigaction)
+ fi
+ ;;
+ esac])
+
+dnl
+dnl If using gcc, make sure we have ANSI ioctl definitions
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_FIXINCLUDES
+dnl
+AC_DEFUN(AC_LBL_FIXINCLUDES,
+ [if test "$GCC" = yes ; then
+ AC_MSG_CHECKING(for ANSI ioctl definitions)
+ AC_CACHE_VAL(ac_cv_lbl_gcc_fixincludes,
+ AC_TRY_COMPILE(
+ [/*
+ * This generates a "duplicate case value" when fixincludes
+ * has not be run.
+ */
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/ioctl.h>
+# ifdef HAVE_SYS_IOCCOM_H
+# include <sys/ioccom.h>
+# endif],
+ [switch (0) {
+ case _IO('A', 1):;
+ case _IO('B', 1):;
+ }],
+ ac_cv_lbl_gcc_fixincludes=yes,
+ ac_cv_lbl_gcc_fixincludes=no))
+ AC_MSG_RESULT($ac_cv_lbl_gcc_fixincludes)
+ if test $ac_cv_lbl_gcc_fixincludes = no ; then
+ # Don't cache failure
+ unset ac_cv_lbl_gcc_fixincludes
+ AC_MSG_ERROR(see the INSTALL for more info)
+ fi
+ fi])
+
+dnl
+dnl Check for flex, default to lex
+dnl Require flex 2.4 or higher
+dnl Check for bison, default to yacc
+dnl Default to lex/yacc if both flex and bison are not available
+dnl Define the yy prefix string if using flex and bison
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_LEX_AND_YACC(lex, yacc, yyprefix)
+dnl
+dnl results:
+dnl
+dnl $1 (lex set)
+dnl $2 (yacc appended)
+dnl $3 (optional flex and bison -P prefix)
+dnl
+AC_DEFUN(AC_LBL_LEX_AND_YACC,
+ [AC_ARG_WITH(flex, [ --without-flex don't use flex])
+ AC_ARG_WITH(bison, [ --without-bison don't use bison])
+ if test "$with_flex" = no ; then
+ $1=lex
+ else
+ AC_CHECK_PROGS($1, flex, lex)
+ fi
+ if test "$$1" = flex ; then
+ # The -V flag was added in 2.4
+ AC_MSG_CHECKING(for flex 2.4 or higher)
+ AC_CACHE_VAL(ac_cv_lbl_flex_v24,
+ if flex -V >/dev/null 2>&1; then
+ ac_cv_lbl_flex_v24=yes
+ else
+ ac_cv_lbl_flex_v24=no
+ fi)
+ AC_MSG_RESULT($ac_cv_lbl_flex_v24)
+ if test $ac_cv_lbl_flex_v24 = no ; then
+ s="2.4 or higher required"
+ AC_MSG_WARN(ignoring obsolete flex executable ($s))
+ $1=lex
+ fi
+ fi
+ if test "$with_bison" = no ; then
+ $2=yacc
+ else
+ AC_CHECK_PROGS($2, bison, yacc)
+ fi
+ if test "$$2" = bison ; then
+ $2="$$2 -y"
+ fi
+ if test "$$1" != lex -a "$$2" = yacc -o "$$1" = lex -a "$$2" != yacc ; then
+ AC_MSG_WARN(don't have both flex and bison; reverting to lex/yacc)
+ $1=lex
+ $2=yacc
+ fi
+ if test "$$1" = flex -a -n "$3" ; then
+ $1="$$1 -P$3"
+ $2="$$2 -p $3"
+ fi])
+
+dnl
+dnl Checks to see if union wait is used with WEXITSTATUS()
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_UNION_WAIT
+dnl
+dnl results:
+dnl
+dnl DECLWAITSTATUS (defined)
+dnl
+AC_DEFUN(AC_LBL_UNION_WAIT,
+ [AC_MSG_CHECKING(if union wait is used)
+ AC_CACHE_VAL(ac_cv_lbl_union_wait,
+ AC_TRY_COMPILE([
+# include <sys/types.h>
+# include <sys/wait.h>],
+ [int status;
+ u_int i = WEXITSTATUS(status);
+ u_int j = waitpid(0, &status, 0);],
+ ac_cv_lbl_union_wait=no,
+ ac_cv_lbl_union_wait=yes))
+ AC_MSG_RESULT($ac_cv_lbl_union_wait)
+ if test $ac_cv_lbl_union_wait = yes ; then
+ AC_DEFINE(DECLWAITSTATUS,union wait)
+ else
+ AC_DEFINE(DECLWAITSTATUS,int)
+ fi])
+
+dnl
+dnl Checks to see if the sockaddr struct has the 4.4 BSD sa_len member
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_SOCKADDR_SA_LEN
+dnl
+dnl results:
+dnl
+dnl HAVE_SOCKADDR_SA_LEN (defined)
+dnl
+AC_DEFUN(AC_LBL_SOCKADDR_SA_LEN,
+ [AC_MSG_CHECKING(if sockaddr struct has sa_len member)
+ AC_CACHE_VAL(ac_cv_lbl_sockaddr_has_sa_len,
+ AC_TRY_COMPILE([
+# include <sys/types.h>
+# include <sys/socket.h>],
+ [u_int i = sizeof(((struct sockaddr *)0)->sa_len)],
+ ac_cv_lbl_sockaddr_has_sa_len=yes,
+ ac_cv_lbl_sockaddr_has_sa_len=no))
+ AC_MSG_RESULT($ac_cv_lbl_sockaddr_has_sa_len)
+ if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then
+ AC_DEFINE(HAVE_SOCKADDR_SA_LEN)
+ fi])
+
+dnl
+dnl Checks to see if the IFF_LOOPBACK exists as a define or enum
+dnl
+dnl (stupidly some versions of linux use an enum...)
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_IFF_LOOPBACK
+dnl
+dnl results:
+dnl
+dnl HAVE_IFF_LOOPBACK (defined)
+dnl
+AC_DEFUN(AC_LBL_IFF_LOOPBACK,
+ [AC_MSG_CHECKING(for IFF_LOOPBACK define/enum)
+ AC_CACHE_VAL(ac_cv_lbl_have_iff_loopback,
+ AC_TRY_COMPILE([
+# include <sys/param.h>
+# include <sys/file.h>
+# include <sys/ioctl.h>
+# include <sys/socket.h>
+# ifdef HAVE_SYS_SOCKIO_H
+# include <sys/sockio.h>
+# endif
+# include <sys/time.h>
+# include <net/if.h>
+# include <netinet/in.h>],
+ [int i = IFF_LOOPBACK],
+ ac_cv_lbl_have_iff_loopback=yes,
+ ac_cv_lbl_have_iff_loopback=no))
+ AC_MSG_RESULT($ac_cv_lbl_have_iff_loopback)
+ if test $ac_cv_lbl_have_iff_loopback = yes ; then
+ AC_DEFINE(HAVE_IFF_LOOPBACK)
+ fi])
+
+dnl
+dnl Checks to see if -R is used
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_HAVE_RUN_PATH
+dnl
+dnl results:
+dnl
+dnl ac_cv_lbl_have_run_path (yes or no)
+dnl
+AC_DEFUN(AC_LBL_HAVE_RUN_PATH,
+ [AC_MSG_CHECKING(for ${CC-cc} -R)
+ AC_CACHE_VAL(ac_cv_lbl_have_run_path,
+ [echo 'main(){}' > conftest.c
+ ${CC-cc} -o conftest conftest.c -R/a1/b2/c3 >conftest.out 2>&1
+ if test ! -s conftest.out ; then
+ ac_cv_lbl_have_run_path=yes
+ else
+ ac_cv_lbl_have_run_path=no
+ fi
+ rm -f conftest*])
+ AC_MSG_RESULT($ac_cv_lbl_have_run_path)
+ ])
+
+dnl
+dnl Due to the stupid way it's implemented, AC_CHECK_TYPE is nearly useless.
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_CHECK_TYPE
+dnl
+dnl results:
+dnl
+dnl int32_t (defined)
+dnl u_int32_t (defined)
+dnl
+AC_DEFUN(AC_LBL_CHECK_TYPE,
+ [AC_MSG_CHECKING(for $1 using $CC)
+ AC_CACHE_VAL(ac_cv_lbl_have_$1,
+ AC_TRY_COMPILE([
+# include "confdefs.h"
+# include <sys/types.h>
+# if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+# endif],
+ [$1 i],
+ ac_cv_lbl_have_$1=yes,
+ ac_cv_lbl_have_$1=no))
+ AC_MSG_RESULT($ac_cv_lbl_have_$1)
+ if test $ac_cv_lbl_have_$1 = no ; then
+ AC_DEFINE($1, $2)
+ fi])
+
+dnl
+dnl Checks to see if unaligned memory accesses fail
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_UNALIGNED_ACCESS
+dnl
+dnl results:
+dnl
+dnl LBL_ALIGN (DEFINED)
+dnl
+AC_DEFUN(AC_LBL_UNALIGNED_ACCESS,
+ [AC_MSG_CHECKING(if unaligned accesses fail)
+ AC_CACHE_VAL(ac_cv_lbl_unaligned_fail,
+ [case "$target_cpu" in
+
+ alpha|hp*|mips|sparc)
+ ac_cv_lbl_unaligned_fail=yes
+ ;;
+
+ *)
+ cat >conftest.c <<EOF
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <stdio.h>
+ unsigned char a[[5]] = { 1, 2, 3, 4, 5 };
+ main() {
+ unsigned int i;
+ pid_t pid;
+ int status;
+ /* avoid "core dumped" message */
+ pid = fork();
+ if (pid < 0)
+ exit(2);
+ if (pid > 0) {
+ /* parent */
+ pid = waitpid(pid, &status, 0);
+ if (pid < 0)
+ exit(3);
+ exit(!WIFEXITED(status));
+ }
+ /* child */
+ i = *(unsigned int *)&a[[1]];
+ printf("%d\n", i);
+ exit(0);
+ }
+EOF
+ ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \
+ conftest.c $LIBS >/dev/null 2>&1
+ if test ! -x conftest ; then
+ dnl failed to compile for some reason
+ ac_cv_lbl_unaligned_fail=yes
+ else
+ ./conftest >conftest.out
+ if test ! -s conftest.out ; then
+ ac_cv_lbl_unaligned_fail=yes
+ else
+ ac_cv_lbl_unaligned_fail=no
+ fi
+ fi
+ rm -f conftest* core core.conftest
+ ;;
+ esac])
+ AC_MSG_RESULT($ac_cv_lbl_unaligned_fail)
+ if test $ac_cv_lbl_unaligned_fail = yes ; then
+ AC_DEFINE(LBL_ALIGN)
+ fi])
+
+dnl
+dnl add all warning option to CFLAGS
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_CHECK_WALL(copt)
+dnl
+dnl results:
+dnl
+dnl $1 (copt appended)
+dnl ac_cv_lbl_gcc_vers
+dnl
+AC_DEFUN(AC_LBL_CHECK_WALL,
+ [ if test "$GCC" = yes ; then
+ if test "$SHLICC2" = yes ; then
+ ac_cv_lbl_gcc_vers=2
+ $1="`echo $$1 | sed -e 's/-O/-O2/'`"
+ else
+ AC_MSG_CHECKING(gcc version)
+ AC_CACHE_VAL(ac_cv_lbl_gcc_vers,
+ ac_cv_lbl_gcc_vers=`$CC --version 2>&1 | \
+ sed -e 's/\..*//'`)
+ AC_MSG_RESULT($ac_cv_lbl_gcc_vers)
+ if test $ac_cv_lbl_gcc_vers -gt 1 ; then
+ $1="`echo $$1 | sed -e 's/-O/-O2/'`"
+ fi
+ fi
+ if test "${LBL_CFLAGS+set}" != set; then
+ if test "$ac_cv_prog_cc_g" = yes ; then
+ $1="-g $$1"
+ fi
+ $1="$$1 -Wall"
+ if test $ac_cv_lbl_gcc_vers -gt 1 ; then
+ $1="$$1 -Wmissing-prototypes -Wstrict-prototypes"
+ fi
+ fi
+ else
+ case "$target_os" in
+
+ irix6*)
+ $1="$$1 -fullwarn -n32"
+ ;;
+
+ *)
+ ;;
+ esac
+ fi])
+
+dnl
+dnl If using gcc and the file .devel exists:
+dnl Compile with -g (if supported) and -Wall
+dnl If using gcc 2, do extra prototype checking
+dnl If an os prototype include exists, symlink os-proto.h to it
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_DEVEL(copt)
+dnl
+dnl results:
+dnl
+dnl $1 (copt appended)
+dnl HAVE_OS_PROTO_H (defined)
+dnl os-proto.h (symlinked)
+dnl
+AC_DEFUN(AC_LBL_DEVEL,
+ [rm -f os-proto.h
+ if test "${LBL_CFLAGS+set}" = set; then
+ $1="$$1 ${LBL_CFLAGS}"
+ fi
+ if test -f .devel ; then
+ AC_LBL_CHECK_WALL($1)
+ os=`echo $target_os | sed -e 's/\([[0-9]][[0-9]]*\)[[^0-9]].*$/\1/'`
+ name="lbl/os-$os.h"
+ if test -f $name ; then
+ ln -s $name os-proto.h
+ AC_DEFINE(HAVE_OS_PROTO_H)
+ else
+ AC_MSG_WARN(can't find $name)
+ fi
+ fi])
+
+dnl
+dnl Improved version of AC_CHECK_LIB
+dnl
+dnl Thanks to John Hawkinson (jhawk@mit.edu)
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_CHECK_LIB(LIBRARY, FUNCTION [, ACTION-IF-FOUND [,
+dnl ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]])
+dnl
+dnl results:
+dnl
+dnl LIBS
+dnl
+
+define(AC_LBL_CHECK_LIB,
+[AC_MSG_CHECKING([for $2 in -l$1])
+dnl Use a cache variable name containing both the library and function name,
+dnl because the test really is for library $1 defining function $2, not
+dnl just for library $1. Separate tests with the same $1 and different $2's
+dnl may have different results.
+ac_lib_var=`echo $1['_']$2['_']$5 | sed 'y%./+- %__p__%'`
+AC_CACHE_VAL(ac_cv_lbl_lib_$ac_lib_var,
+[ac_save_LIBS="$LIBS"
+LIBS="-l$1 $5 $LIBS"
+AC_TRY_LINK(dnl
+ifelse([$2], [main], , dnl Avoid conflicting decl of main.
+[/* Override any gcc2 internal prototype to avoid an error. */
+]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus
+extern "C"
+#endif
+])dnl
+[/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $2();
+]),
+ [$2()],
+ eval "ac_cv_lbl_lib_$ac_lib_var=yes",
+ eval "ac_cv_lbl_lib_$ac_lib_var=no")
+LIBS="$ac_save_LIBS"
+])dnl
+if eval "test \"`echo '$ac_cv_lbl_lib_'$ac_lib_var`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$3], ,
+[changequote(, )dnl
+ ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+changequote([, ])dnl
+ AC_DEFINE_UNQUOTED($ac_tr_lib)
+ LIBS="-l$1 $LIBS"
+], [$3])
+else
+ AC_MSG_RESULT(no)
+ifelse([$4], , , [$4
+])dnl
+fi
+])
+
+dnl
+dnl AC_LBL_LIBRARY_NET
+dnl
+dnl This test is for network applications that need socket() and
+dnl gethostbyname() -ish functions. Under Solaris, those applications
+dnl need to link with "-lsocket -lnsl". Under IRIX, they need to link
+dnl with "-lnsl" but should *not* link with "-lsocket" because
+dnl libsocket.a breaks a number of things (for instance:
+dnl gethostbyname() under IRIX 5.2, and snoop sockets under most
+dnl versions of IRIX).
+dnl
+dnl Unfortunately, many application developers are not aware of this,
+dnl and mistakenly write tests that cause -lsocket to be used under
+dnl IRIX. It is also easy to write tests that cause -lnsl to be used
+dnl under operating systems where neither are necessary (or useful),
+dnl such as SunOS 4.1.4, which uses -lnsl for TLI.
+dnl
+dnl This test exists so that every application developer does not test
+dnl this in a different, and subtly broken fashion.
+
+dnl It has been argued that this test should be broken up into two
+dnl seperate tests, one for the resolver libraries, and one for the
+dnl libraries necessary for using Sockets API. Unfortunately, the two
+dnl are carefully intertwined and allowing the autoconf user to use
+dnl them independantly potentially results in unfortunate ordering
+dnl dependancies -- as such, such component macros would have to
+dnl carefully use indirection and be aware if the other components were
+dnl executed. Since other autoconf macros do not go to this trouble,
+dnl and almost no applications use sockets without the resolver, this
+dnl complexity has not been implemented.
+dnl
+dnl The check for libresolv is in case you are attempting to link
+dnl statically and happen to have a libresolv.a lying around (and no
+dnl libnsl.a).
+dnl
+AC_DEFUN(AC_LBL_LIBRARY_NET, [
+ # Most operating systems have gethostbyname() in the default searched
+ # libraries (i.e. libc):
+ AC_CHECK_FUNC(gethostbyname, ,
+ # Some OSes (eg. Solaris) place it in libnsl:
+ AC_LBL_CHECK_LIB(nsl, gethostbyname, ,
+ # Some strange OSes (SINIX) have it in libsocket:
+ AC_LBL_CHECK_LIB(socket, gethostbyname, ,
+ # Unfortunately libsocket sometimes depends on libnsl.
+ # AC_CHECK_LIB's API is essentially broken so the
+ # following ugliness is necessary:
+ AC_LBL_CHECK_LIB(socket, gethostbyname,
+ LIBS="-lsocket -lnsl $LIBS",
+ AC_CHECK_LIB(resolv, gethostbyname),
+ -lnsl))))
+ AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket, ,
+ AC_LBL_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", ,
+ -lnsl)))
+ # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+ AC_CHECK_LIB(str, putmsg)
+ ])
diff --git a/contrib/nslint-2.1a3/config.guess b/contrib/nslint-2.1a3/config.guess
new file mode 100644
index 0000000..e9e4455
--- /dev/null
+++ b/contrib/nslint-2.1a3/config.guess
@@ -0,0 +1,693 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ alpha:OSF1:*:*)
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-cbm-sysv4
+ exit 0;;
+ amiga:NetBSD:*:*)
+ echo m68k-cbm-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-cbm-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:OpenBSD:*:*)
+ echo m68k-atari-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:OpenBSD:*:*)
+ echo m68k-sun-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-apple-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ sed 's/^ //' << EOF >dummy.c
+ int main (argc, argv) int argc; char **argv; {
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy \
+ && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i?86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ sed 's/^ //' << EOF >dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:4)
+ if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=4.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[3478]??:HP-UX:*:*)
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
+ 9000/8?? ) HP_ARCH=hppa1.0 ;;
+ esac
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ sed 's/^ //' << EOF >dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i?86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ F300:UNIX_System_V:*:*)
+ FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ F301:UNIX_System_V:*:*)
+ echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+ exit 0 ;;
+ hp3[0-9][05]:NetBSD:*:*)
+ echo m68k-hp-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp3[0-9][05]:OpenBSD:*:*)
+ echo m68k-hp-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:BSD/386:*:* | *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:NetBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo i386-pc-cygwin32
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin32
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us.
+ ld_help_string=`ld --help 2>&1`
+ if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i.86"; then
+ echo "${UNAME_MACHINE}-pc-linux-gnu" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86linux"; then
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86coff"; then
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
+ echo "${UNAME_MACHINE}-unknown-linux-gnu" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
+ echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf32ppc"; then
+ echo "powerpc-unknown-linux-gnu" ; exit 0
+ elif test "${UNAME_MACHINE}" = "alpha" ; then
+ echo alpha-unknown-linux-gnu ; exit 0
+ elif test "${UNAME_MACHINE}" = "sparc" ; then
+ echo sparc-unknown-linux-gnu ; exit 0
+ else
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or one that does not give us
+ # useful --help. Gcc wants to distinguish between linux-gnuoldld and linux-gnuaout.
+ test ! -d /usr/lib/ldscripts/. \
+ && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+ # Determine whether the default compiler is a.out or elf
+ cat >dummy.c <<EOF
+main(argc, argv)
+int argc;
+char *argv[];
+{
+#ifdef __ELF__
+ printf ("%s-pc-linux-gnu\n", argv[1]);
+#else
+ printf ("%s-pc-linux-gnuaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ fi ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+ i?86:DYNIX/ptx:4*:*)
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ i?86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i?86:LynxOS:2.*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+ printf ("vax-dec-bsd\n"); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/contrib/nslint-2.1a3/config.sub b/contrib/nslint-2.1a3/config.sub
new file mode 100644
index 0000000..0432524
--- /dev/null
+++ b/contrib/nslint-2.1a3/config.sub
@@ -0,0 +1,927 @@
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+# Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+if [ x$1 = x ]
+then
+ echo Configuration name missing. 1>&2
+ echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+ echo "or $0 ALIAS" 1>&2
+ echo where ALIAS is a recognized configuration type. 1>&2
+ exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+ *local*)
+ echo $1
+ exit 0
+ ;;
+ *)
+ ;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ linux-gnu*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple)
+ os=
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ tahoe | i860 | m68k | m68000 | m88k | ns32k | arm \
+ | arme[lb] | pyramid \
+ | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
+ | alpha | we32k | ns16k | clipper | i370 | sh \
+ | powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \
+ | pdp11 | mips64el | mips64orion | mips64orionel \
+ | sparc | sparclet | sparclite | sparc64)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i[3456]86)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
+ | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
+ | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
+ | hppa-* | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
+ | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
+ | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
+ | mips64el-* | mips64orion-* | mips64orionel-* | f301-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-cbm
+ ;;
+ amigados)
+ basic_machine=m68k-cbm
+ os=-amigados
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-cbm
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ [ctj]90-cray)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i[3456]86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i[3456]86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i[3456]86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i[3456]86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5)
+ basic_machine=i586-intel
+ ;;
+ pentiumpro | p6)
+ basic_machine=i686-intel
+ ;;
+ pentium-* | p5-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ k5)
+ # We don't have specific support for AMD's K5 yet, so just call it a Pentium
+ basic_machine=i586-amd
+ ;;
+ nexen)
+ # We don't have specific support for Nexgen yet, so just call it a Pentium
+ basic_machine=i586-nexgen
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=rs6000-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ mips)
+ basic_machine=mips-mips
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sparc)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -unixware* | svr4*)
+ os=-sysv4
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigados* | -msdos* | -newsos* | -unicos* | -aof* | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -linux-gnu* | -uxpv*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigados
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f301-fujitsu)
+ os=-uxpv
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
diff --git a/contrib/nslint-2.1a3/configure b/contrib/nslint-2.1a3/configure
new file mode 100644
index 0000000..db5c53e
--- /dev/null
+++ b/contrib/nslint-2.1a3/configure
@@ -0,0 +1,1905 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --without-gcc don't use gcc"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=nslint.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:575: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:596: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:614: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+umask 002
+
+if test -z "$PWD" ; then
+ PWD=`pwd`
+fi
+
+
+
+
+
+ # Check whether --with-gcc or --without-gcc was given.
+if test "${with_gcc+set}" = set; then
+ withval="$with_gcc"
+ :
+fi
+
+ V_CCOPT="-O"
+ V_INCLS=""
+ if test "${srcdir}" != "." ; then
+ V_INCLS="-I\$\(srcdir\)"
+ fi
+ if test "${CFLAGS+set}" = set; then
+ LBL_CFLAGS="$CFLAGS"
+ fi
+ if test -z "$CC" ; then
+ case "$target_os" in
+
+ bsdi*)
+ # Extract the first word of "shlicc2", so it can be a program name with args.
+set dummy shlicc2; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:668: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_SHLICC2'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$SHLICC2"; then
+ ac_cv_prog_SHLICC2="$SHLICC2" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_SHLICC2="yes"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_SHLICC2" && ac_cv_prog_SHLICC2="no"
+fi
+fi
+SHLICC2="$ac_cv_prog_SHLICC2"
+if test -n "$SHLICC2"; then
+ echo "$ac_t""$SHLICC2" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test $SHLICC2 = yes ; then
+ CC=shlicc2
+ export CC
+ fi
+ ;;
+ esac
+ fi
+ if test -z "$CC" -a "$with_gcc" = no ; then
+ CC=cc
+ export CC
+ fi
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:709: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:739: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:790: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:822: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 833 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:838: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:864: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:869: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:878: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:897: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+ if test "$GCC" != yes ; then
+ echo $ac_n "checking that $CC handles ansi prototypes""... $ac_c" 1>&6
+echo "configure:930: checking that $CC handles ansi prototypes" >&5
+ if eval "test \"`echo '$''{'ac_cv_lbl_cc_ansi_prototypes'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 935 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() {
+int frob(int, char *)
+; return 0; }
+EOF
+if { (eval echo configure:942: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_lbl_cc_ansi_prototypes=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_lbl_cc_ansi_prototypes=no
+fi
+rm -f conftest*
+fi
+
+ echo "$ac_t""$ac_cv_lbl_cc_ansi_prototypes" 1>&6
+ if test $ac_cv_lbl_cc_ansi_prototypes = no ; then
+ case "$target_os" in
+
+ hpux*)
+ echo $ac_n "checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)""... $ac_c" 1>&6
+echo "configure:960: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5
+ savedcflags="$CFLAGS"
+ CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS"
+ if eval "test \"`echo '$''{'ac_cv_lbl_cc_hpux_cc_aa'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 967 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() {
+int frob(int, char *)
+; return 0; }
+EOF
+if { (eval echo configure:974: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_lbl_cc_hpux_cc_aa=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_lbl_cc_hpux_cc_aa=no
+fi
+rm -f conftest*
+fi
+
+ echo "$ac_t""$ac_cv_lbl_cc_hpux_cc_aa" 1>&6
+ if test $ac_cv_lbl_cc_hpux_cc_aa = no ; then
+ { echo "configure: error: see the INSTALL doc for more info" 1>&2; exit 1; }
+ fi
+ CFLAGS="$savedcflags"
+ V_CCOPT="-Aa $V_CCOPT"
+ cat >> confdefs.h <<\EOF
+#define _HPUX_SOURCE 1
+EOF
+
+ ;;
+
+ *)
+ { echo "configure: error: see the INSTALL doc for more info" 1>&2; exit 1; }
+ ;;
+ esac
+ fi
+ V_INCLS="$V_INCLS -I/usr/local/include"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+ case "$target_os" in
+
+ irix*)
+ V_CCOPT="$V_CCOPT -xansi -signed -g3"
+ ;;
+
+ osf*)
+ V_CCOPT="$V_CCOPT -std1 -g3"
+ ;;
+
+ ultrix*)
+ echo $ac_n "checking that Ultrix $CC hacks const in prototypes""... $ac_c" 1>&6
+echo "configure:1018: checking that Ultrix $CC hacks const in prototypes" >&5
+ if eval "test \"`echo '$''{'ac_cv_lbl_cc_const_proto'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1023 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+int main() {
+struct a { int b; };
+ void c(const struct a *)
+; return 0; }
+EOF
+if { (eval echo configure:1031: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_lbl_cc_const_proto=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_lbl_cc_const_proto=no
+fi
+rm -f conftest*
+fi
+
+ echo "$ac_t""$ac_cv_lbl_cc_const_proto" 1>&6
+ if test $ac_cv_lbl_cc_const_proto = no ; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+ fi
+ ;;
+ esac
+ fi
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1056: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1071 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1077: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1088 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1094: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 1105 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1111: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+for ac_hdr in fcntl.h malloc.h memory.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1139: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1144 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1149: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+for ac_func in strerror
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1179: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1184 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1207: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}"
+fi
+done
+
+
+echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6
+echo "configure:1234: checking for main in -lnsl" >&5
+ac_lib_var=`echo nsl'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1242 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:1249: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lnsl $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for main in -lsocket""... $ac_c" 1>&6
+echo "configure:1277: checking for main in -lsocket" >&5
+ac_lib_var=`echo socket'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1285 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:1292: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lsocket $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1321: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1326 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1334: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1351 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1369 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1390 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1401: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for int32_t""... $ac_c" 1>&6
+echo "configure:1425: checking for int32_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_int32_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1430 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])int32_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_int32_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_int32_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_int32_t" 1>&6
+if test $ac_cv_type_int32_t = no; then
+ cat >> confdefs.h <<\EOF
+#define int32_t int
+EOF
+
+fi
+
+echo $ac_n "checking for u_int32_t""... $ac_c" 1>&6
+echo "configure:1458: checking for u_int32_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_u_int32_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1463 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])u_int32_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_u_int32_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_u_int32_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_u_int32_t" 1>&6
+if test $ac_cv_type_u_int32_t = no; then
+ cat >> confdefs.h <<\EOF
+#define u_int32_t u_int
+EOF
+
+fi
+
+
+rm -f os-proto.h
+ if test "${LBL_CFLAGS+set}" = set; then
+ V_CCOPT="$V_CCOPT ${LBL_CFLAGS}"
+ fi
+ if test -f .devel ; then
+ if test "$GCC" = yes ; then
+ if test "$SHLICC2" = yes ; then
+ ac_cv_lbl_gcc_vers=2
+ V_CCOPT="`echo $V_CCOPT | sed -e 's/-O/-O2/'`"
+ else
+ echo $ac_n "checking gcc version""... $ac_c" 1>&6
+echo "configure:1502: checking gcc version" >&5
+ if eval "test \"`echo '$''{'ac_cv_lbl_gcc_vers'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_lbl_gcc_vers=`$CC --version 2>&1 | \
+ sed -e 's/\..*//'`
+fi
+
+ echo "$ac_t""$ac_cv_lbl_gcc_vers" 1>&6
+ if test $ac_cv_lbl_gcc_vers -gt 1 ; then
+ V_CCOPT="`echo $V_CCOPT | sed -e 's/-O/-O2/'`"
+ fi
+ fi
+ if test "${LBL_CFLAGS+set}" != set; then
+ if test "$ac_cv_prog_cc_g" = yes ; then
+ V_CCOPT="-g $V_CCOPT"
+ fi
+ V_CCOPT="$V_CCOPT -Wall"
+ if test $ac_cv_lbl_gcc_vers -gt 1 ; then
+ V_CCOPT="$V_CCOPT -Wmissing-prototypes -Wstrict-prototypes"
+ fi
+ fi
+ else
+ case "$target_os" in
+
+ irix6*)
+ V_CCOPT="$V_CCOPT -fullwarn -n32"
+ ;;
+
+ *)
+ ;;
+ esac
+ fi
+ os=`echo $target_os | sed -e 's/\([0-9][0-9]*\)[^0-9].*$/\1/'`
+ name="lbl/os-$os.h"
+ if test -f $name ; then
+ ln -s $name os-proto.h
+ cat >> confdefs.h <<\EOF
+#define HAVE_OS_PROTO_H 1
+EOF
+
+ else
+ echo "configure: warning: can't find $name" 1>&2
+ fi
+ fi
+
+if test -r lbl/gnuc.h ; then
+ rm -f gnuc.h
+ ln -s lbl/gnuc.h gnuc.h
+fi
+
+
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:1568: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@SHLICC2@%$SHLICC2%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@LIBOBJS@%$LIBOBJS%g
+s%@V_CCOPT@%$V_CCOPT%g
+s%@V_INCLS@%$V_INCLS%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
+if test -f .devel ; then
+ make depend
+fi
+exit 0
diff --git a/contrib/nslint-2.1a3/configure.in b/contrib/nslint-2.1a3/configure.in
new file mode 100644
index 0000000..5ba1e87
--- /dev/null
+++ b/contrib/nslint-2.1a3/configure.in
@@ -0,0 +1,47 @@
+dnl @(#) $Header: /proj/cvs/prod/bind9/contrib/nslint-2.1a3/configure.in,v 1.1 2001/12/21 04:12:03 marka Exp $ (LBL)
+dnl
+dnl Copyright (c) 1995, 1996, 1997
+dnl The Regents of the University of California. All rights reserved.
+dnl
+dnl Process this file with autoconf to produce a configure script.
+dnl
+
+AC_INIT(nslint.c)
+
+AC_CANONICAL_SYSTEM
+
+umask 002
+
+if test -z "$PWD" ; then
+ PWD=`pwd`
+fi
+
+AC_LBL_C_INIT(V_CCOPT, V_INCLS)
+
+AC_CHECK_HEADERS(fcntl.h malloc.h memory.h)
+
+AC_REPLACE_FUNCS(strerror)
+AC_CHECK_LIB(nsl, main)
+AC_CHECK_LIB(socket, main)
+
+AC_CHECK_TYPE(int32_t, int)
+AC_CHECK_TYPE(u_int32_t, u_int)
+
+AC_LBL_DEVEL(V_CCOPT)
+
+if test -r lbl/gnuc.h ; then
+ rm -f gnuc.h
+ ln -s lbl/gnuc.h gnuc.h
+fi
+
+AC_SUBST(V_CCOPT)
+AC_SUBST(V_INCLS)
+
+AC_PROG_INSTALL
+
+AC_OUTPUT(Makefile)
+
+if test -f .devel ; then
+ make depend
+fi
+exit 0
diff --git a/contrib/nslint-2.1a3/install-sh b/contrib/nslint-2.1a3/install-sh
new file mode 100644
index 0000000..ebc6691
--- /dev/null
+++ b/contrib/nslint-2.1a3/install-sh
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/contrib/nslint-2.1a3/lbl/gnuc.h b/contrib/nslint-2.1a3/lbl/gnuc.h
new file mode 100644
index 0000000..7330227
--- /dev/null
+++ b/contrib/nslint-2.1a3/lbl/gnuc.h
@@ -0,0 +1,43 @@
+/* @(#) $Header: /proj/cvs/prod/bind9/contrib/nslint-2.1a3/lbl/gnuc.h,v 1.1 2001/12/21 04:12:05 marka Exp $ (LBL) */
+
+/* Define __P() macro, if necessary */
+#ifndef __P
+#if __STDC__
+#define __P(protos) protos
+#else
+#define __P(protos) ()
+#endif
+#endif
+
+/* inline foo */
+#ifdef __GNUC__
+#define inline __inline
+#else
+#define inline
+#endif
+
+/*
+ * Handle new and old "dead" routine prototypes
+ *
+ * For example:
+ *
+ * __dead void foo(void) __attribute__((volatile));
+ *
+ */
+#ifdef __GNUC__
+#ifndef __dead
+#define __dead volatile
+#endif
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
+#ifndef __attribute__
+#define __attribute__(args)
+#endif
+#endif
+#else
+#ifndef __dead
+#define __dead
+#endif
+#ifndef __attribute__
+#define __attribute__(args)
+#endif
+#endif
diff --git a/contrib/nslint-2.1a3/lbl/os-irix5.h b/contrib/nslint-2.1a3/lbl/os-irix5.h
new file mode 100644
index 0000000..71fdc7e
--- /dev/null
+++ b/contrib/nslint-2.1a3/lbl/os-irix5.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /proj/cvs/prod/bind9/contrib/nslint-2.1a3/lbl/os-irix5.h,v 1.1 2001/12/21 04:12:05 marka Exp $ (LBL)
+ */
+
+/* Prototypes missing in IRIX 5 */
+#ifdef __STDC__
+struct ether_addr;
+#endif
+int ether_hostton(char *, struct ether_addr *);
+char *ether_ntoa(struct ether_addr *);
+#ifdef __STDC__
+struct utmp;
+#endif
+void login(struct utmp *);
+int setenv(const char *, const char *, int);
+int sigblock(int);
+int sigsetmask(int);
+int snprintf(char *, size_t, const char *, ...);
+time_t time(time_t *);
diff --git a/contrib/nslint-2.1a3/lbl/os-osf3.h b/contrib/nslint-2.1a3/lbl/os-osf3.h
new file mode 100644
index 0000000..f0e549e
--- /dev/null
+++ b/contrib/nslint-2.1a3/lbl/os-osf3.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /proj/cvs/prod/bind9/contrib/nslint-2.1a3/lbl/os-osf3.h,v 1.1 2001/12/21 04:12:05 marka Exp $ (LBL)
+ */
+
+/* Prototypes missing in osf3 */
+int flock(int, int);
+int ioctl(int, int, caddr_t);
+int iruserok(u_int, int, char *, char *);
+int pfopen(char *, int);
+int rcmd(char **, u_short, const char *, const char *, const char *, int *);
+int rresvport(int *);
+int snprintf(char *, size_t, const char *, ...);
+void sync(void);
diff --git a/contrib/nslint-2.1a3/lbl/os-solaris2.h b/contrib/nslint-2.1a3/lbl/os-solaris2.h
new file mode 100644
index 0000000..ba91e71
--- /dev/null
+++ b/contrib/nslint-2.1a3/lbl/os-solaris2.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Id: os-solaris2.h,v 1.1 2001/12/21 04:12:05 marka Exp $ (LBL)
+ */
+
+/* Prototypes missing in SunOS 5 */
+int daemon(int, int);
+int dn_expand(const u_char *, const u_char *, const u_char *, char *, int);
+int dn_skipname(const u_char *, const u_char *);
+int flock(int, int);
+int getdtablesize(void);
+int gethostname(char *, int);
+int getpagesize(void);
+char *getusershell(void);
+char *getwd(char *);
+int iruserok(u_int, int, char *, char *);
+#ifdef __STDC__
+struct utmp;
+void login(struct utmp *);
+#endif
+int logout(const char *);
+int res_query(const char *, int, int, u_char *, int);
+int setenv(const char *, const char *, int);
+#if defined(_STDIO_H) && defined(HAVE_SETLINEBUF)
+int setlinebuf(FILE *);
+#endif
+int sigblock(int);
+int sigsetmask(int);
+char *strerror(int);
+int snprintf(char *, size_t, const char *, ...);
+int strcasecmp(const char *, const char *);
+void unsetenv(const char *);
diff --git a/contrib/nslint-2.1a3/lbl/os-sunos4.h b/contrib/nslint-2.1a3/lbl/os-sunos4.h
new file mode 100644
index 0000000..157ab67
--- /dev/null
+++ b/contrib/nslint-2.1a3/lbl/os-sunos4.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 1989, 1990, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /proj/cvs/prod/bind9/contrib/nslint-2.1a3/lbl/os-sunos4.h,v 1.1 2001/12/21 04:12:05 marka Exp $ (LBL)
+ */
+
+/* Prototypes missing in SunOS 4 */
+#ifdef FILE
+int _filbuf(FILE *);
+int _flsbuf(u_char, FILE *);
+int fclose(FILE *);
+int fflush(FILE *);
+int fgetc(FILE *);
+int fprintf(FILE *, const char *, ...);
+int fputc(int, FILE *);
+int fputs(const char *, FILE *);
+u_int fread(void *, u_int, u_int, FILE *);
+int fseek(FILE *, long, int);
+u_int fwrite(const void *, u_int, u_int, FILE *);
+int pclose(FILE *);
+void rewind(FILE *);
+void setbuf(FILE *, char *);
+int setlinebuf(FILE *);
+int ungetc(int, FILE *);
+int vfprintf(FILE *, const char *, ...);
+int vprintf(const char *, ...);
+#endif
+
+#if __GNUC__ <= 1
+int read(int, char *, u_int);
+int write(int, char *, u_int);
+#endif
+
+long a64l(const char *);
+#ifdef __STDC__
+struct sockaddr;
+#endif
+int accept(int, struct sockaddr *, int *);
+int bind(int, struct sockaddr *, int);
+int bcmp(const void *, const void *, u_int);
+void bcopy(const void *, void *, u_int);
+void bzero(void *, int);
+int chroot(const char *);
+int close(int);
+void closelog(void);
+int connect(int, struct sockaddr *, int);
+char *crypt(const char *, const char *);
+int daemon(int, int);
+int fchmod(int, int);
+int fchown(int, int, int);
+void endgrent(void);
+void endpwent(void);
+void endservent(void);
+#ifdef __STDC__
+struct ether_addr;
+#endif
+struct ether_addr *ether_aton(const char *);
+int flock(int, int);
+#ifdef __STDC__
+struct stat;
+#endif
+int fstat(int, struct stat *);
+#ifdef __STDC__
+struct statfs;
+#endif
+int fstatfs(int, struct statfs *);
+int fsync(int);
+#ifdef __STDC__
+struct timeb;
+#endif
+int ftime(struct timeb *);
+int ftruncate(int, off_t);
+int getdtablesize(void);
+long gethostid(void);
+int gethostname(char *, int);
+int getopt(int, char * const *, const char *);
+int getpagesize(void);
+char *getpass(char *);
+int getpeername(int, struct sockaddr *, int *);
+int getpriority(int, int);
+#ifdef __STDC__
+struct rlimit;
+#endif
+int getrlimit(int, struct rlimit *);
+int getsockname(int, struct sockaddr *, int *);
+int getsockopt(int, int, int, char *, int *);
+#ifdef __STDC__
+struct timeval;
+struct timezone;
+#endif
+int gettimeofday(struct timeval *, struct timezone *);
+char *getusershell(void);
+char *getwd(char *);
+int initgroups(const char *, int);
+int ioctl(int, int, caddr_t);
+int iruserok(u_long, int, char *, char *);
+int isatty(int);
+int killpg(int, int);
+int listen(int, int);
+#ifdef __STDC__
+struct utmp;
+#endif
+void login(struct utmp *);
+int logout(const char *);
+off_t lseek(int, off_t, int);
+int lstat(const char *, struct stat *);
+int mkstemp(char *);
+char *mktemp(char *);
+int munmap(caddr_t, int);
+void openlog(const char *, int, int);
+void perror(const char *);
+int printf(const char *, ...);
+int puts(const char *);
+long random(void);
+int readlink(const char *, char *, int);
+#ifdef __STDC__
+struct iovec;
+#endif
+int readv(int, struct iovec *, int);
+int recv(int, char *, u_int, int);
+int recvfrom(int, char *, u_int, int, struct sockaddr *, int *);
+int rename(const char *, const char *);
+int rcmd(char **, u_short, char *, char *, char *, int *);
+int rresvport(int *);
+int send(int, char *, u_int, int);
+int sendto(int, char *, u_int, int, struct sockaddr *, int);
+int setenv(const char *, const char *, int);
+int seteuid(int);
+int setpriority(int, int, int);
+int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+int setpgrp(int, int);
+void setpwent(void);
+int setrlimit(int, struct rlimit *);
+void setservent(int);
+int setsockopt(int, int, int, char *, int);
+int shutdown(int, int);
+int sigblock(int);
+void (*signal (int, void (*) (int))) (int);
+int sigpause(int);
+int sigsetmask(int);
+#ifdef __STDC__
+struct sigvec;
+#endif
+int sigvec(int, struct sigvec *, struct sigvec*);
+int snprintf(char *, size_t, const char *, ...);
+int socket(int, int, int);
+int socketpair(int, int, int, int *);
+int symlink(const char *, const char *);
+void srandom(int);
+int sscanf(char *, const char *, ...);
+int stat(const char *, struct stat *);
+int statfs(char *, struct statfs *);
+char *strerror(int);
+int strcasecmp(const char *, const char *);
+#ifdef __STDC__
+struct tm;
+#endif
+int strftime(char *, int, char *, struct tm *);
+int strncasecmp(const char *, const char *, int);
+long strtol(const char *, char **, int);
+void sync(void);
+void syslog(int, const char *, ...);
+int system(const char *);
+long tell(int);
+time_t time(time_t *);
+char *timezone(int, int);
+int tolower(int);
+int toupper(int);
+int truncate(char *, off_t);
+void unsetenv(const char *);
+int vfork(void);
+int vsprintf(char *, const char *, ...);
+int writev(int, struct iovec *, int);
+#ifdef __STDC__
+struct rusage;
+#endif
+int utimes(const char *, struct timeval *);
+#if __GNUC__ <= 1
+int wait(int *);
+pid_t wait3(int *, int, struct rusage *);
+#endif
+
+/* Ugly signal hacking */
+#ifdef SIG_ERR
+#undef SIG_ERR
+#define SIG_ERR (void (*)(int))-1
+#undef SIG_DFL
+#define SIG_DFL (void (*)(int))0
+#undef SIG_IGN
+#define SIG_IGN (void (*)(int))1
+
+#ifdef KERNEL
+#undef SIG_CATCH
+#define SIG_CATCH (void (*)(int))2
+#endif
+#undef SIG_HOLD
+#define SIG_HOLD (void (*)(int))3
+#endif
diff --git a/contrib/nslint-2.1a3/lbl/os-ultrix4.h b/contrib/nslint-2.1a3/lbl/os-ultrix4.h
new file mode 100644
index 0000000..f8cedf4
--- /dev/null
+++ b/contrib/nslint-2.1a3/lbl/os-ultrix4.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /proj/cvs/prod/bind9/contrib/nslint-2.1a3/lbl/os-ultrix4.h,v 1.1 2001/12/21 04:12:05 marka Exp $ (LBL)
+ */
+
+/* Prototypes missing in Ultrix 4 */
+int bcmp(const char *, const char *, u_int);
+void bcopy(const void *, void *, u_int);
+void bzero(void *, u_int);
+void endservent(void);
+int getopt(int, char * const *, const char *);
+#ifdef __STDC__
+struct timeval;
+struct timezone;
+#endif
+int gettimeofday(struct timeval *, struct timezone *);
+int ioctl(int, int, caddr_t);
+int pfopen(char *, int);
+int setlinebuf(FILE *);
+int socket(int, int, int);
+int strcasecmp(const char *, const char *);
diff --git a/contrib/nslint-2.1a3/mkdep b/contrib/nslint-2.1a3/mkdep
new file mode 100644
index 0000000..2a9c221
--- /dev/null
+++ b/contrib/nslint-2.1a3/mkdep
@@ -0,0 +1,109 @@
+#!/bin/sh -
+#
+# Copyright (c) 1994, 1996
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted
+# provided that this notice is preserved and that due credit is given
+# to the University of California at Berkeley. The name of the University
+# may not be used to endorse or promote products derived from this
+# software without specific prior written permission. This software
+# is provided ``as is'' without express or implied warranty.
+#
+# @(#)mkdep.sh 5.11 (Berkeley) 5/5/88
+#
+
+PATH=/bin:/usr/bin:/usr/ucb:/usr/local:/usr/local/bin
+export PATH
+
+MAKE=Makefile # default makefile name is "Makefile"
+CC=cc # default C compiler is "cc"
+
+while :
+ do case "$1" in
+ # -c allows you to specify the C compiler
+ -c)
+ CC=$2
+ shift; shift ;;
+
+ # -f allows you to select a makefile name
+ -f)
+ MAKE=$2
+ shift; shift ;;
+
+ # the -p flag produces "program: program.c" style dependencies
+ # so .o's don't get produced
+ -p)
+ SED='s;\.o;;'
+ shift ;;
+ *)
+ break ;;
+ esac
+done
+
+if [ $# = 0 ] ; then
+ echo 'usage: mkdep [-p] [-c cc] [-f makefile] [flags] file ...'
+ exit 1
+fi
+
+if [ ! -w $MAKE ]; then
+ echo "mkdep: no writeable file \"$MAKE\""
+ exit 1
+fi
+
+TMP=/tmp/mkdep$$
+
+trap 'rm -f $TMP ; exit 1' 1 2 3 13 15
+
+cp $MAKE ${MAKE}.bak
+
+sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP
+
+cat << _EOF_ >> $TMP
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+_EOF_
+
+# If your compiler doesn't have -M, add it. If you can't, the next two
+# lines will try and replace the "cc -M". The real problem is that this
+# hack can't deal with anything that requires a search path, and doesn't
+# even try for anything using bracket (<>) syntax.
+#
+# egrep '^#include[ ]*".*"' /dev/null $* |
+# sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
+
+# XXX this doesn't work with things like "-DDECLWAITSTATUS=union\ wait"
+$CC -M $* |
+sed "
+ s; \./; ;g
+ $SED" |
+awk '{
+ if ($1 != prev) {
+ if (rec != "")
+ print rec;
+ rec = $0;
+ prev = $1;
+ }
+ else {
+ if (length(rec $2) > 78) {
+ print rec;
+ rec = $0;
+ }
+ else
+ rec = rec " " $2
+ }
+}
+END {
+ print rec
+}' >> $TMP
+
+cat << _EOF_ >> $TMP
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
+_EOF_
+
+# copy to preserve permissions
+cp $TMP $MAKE
+rm -f ${MAKE}.bak $TMP
+exit 0
diff --git a/contrib/nslint-2.1a3/nslint.8 b/contrib/nslint-2.1a3/nslint.8
new file mode 100644
index 0000000..98c1ebe
--- /dev/null
+++ b/contrib/nslint-2.1a3/nslint.8
@@ -0,0 +1,451 @@
+.\" @(#) $Id: nslint.8,v 1.1 2001/12/21 04:12:03 marka Exp $ (LBL)
+.\"
+.\" Copyright (c) 1994, 1996, 1997, 1999, 2001
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH nslint 8 "20 March 2001"
+.UC 4
+.SH NAME
+nslint - perform consistency checks on dns files
+.SH SYNOPSIS
+.B nslint
+[
+.B -d
+] [
+.B -b
+.I named.boot
+] [
+.B -B
+.I nslint.boot
+]
+.br
+.B nslint
+[
+.B -d
+] [
+.B -c
+.I named.conf
+] [
+.B -C
+.I nslint.conf
+]
+.SH DESCRIPTION
+.B Nslint
+reads the nameserver configuration files and performs a number of
+consistency checks on the dns records. If any problems are discovered,
+error messages are displayed on
+.I stderr
+and
+.B nslint
+exits with a non-zero status.
+.LP
+Here is a short list of errors
+.B nslint
+detects:
+.IP
+Records that are malformed.
+.IP
+Names that contain dots but are missing a trailing dot.
+.IP
+.B PTR
+records with names that are missing a trailing dot.
+.IP
+Names that contain illegal characters (rfc1034).
+.IP
+.B A
+records
+without matching
+.B PTR
+records
+.IP
+.B PTR
+records
+without matching
+.B A
+records
+.IP
+Names with more than one address on the same subnet.
+.IP
+Addresses in use by more than one name.
+.IP
+Names with
+.B CNAME
+and other records (rfc1033).
+.IP
+Unknown service and/or protocol keywords in
+.B WKS
+records.
+.IP
+Missing quotes.
+.LP
+.SH OPTIONS
+.TP
+.B -b
+Specify an alternate
+.I named.boot
+file. The default is
+.IR /etc/named.boot .
+.TP
+.TP
+.B -c
+Specify an alternate
+.I named.conf
+file. The default is
+.IR /etc/named.conf .
+.TP
+.B -B
+Specify an alternate
+.I nslint.boot
+file. The default is
+.I nslint.boot
+in the last
+.B directory
+line processed in
+.I named.boot
+(or the current working directory).
+This file is processed like a second
+.IR named.boot .
+The most common use is to tell
+.B nslint
+about
+.B A
+records that match
+.B PTR
+records that point outside the domains listed in
+.IR named.boot .
+.TP
+.B -C
+Specify an alternate
+.I nslint.conf
+file. The default is
+.I nslint.conf
+in the last
+.B directory
+line processed in
+.I named.conf
+(or the current working directory).
+This file is processed like a second
+.IR named.conf .
+.TP
+.B -d
+Raise the debugging level. Debugging information is
+displayed on
+.IR stdout .
+.LP
+.B Nslint
+knows how to read old style
+.I named.boot
+and BIND 8's new
+.I named.conf
+files. If both files exist,
+.B nslint
+will prefer
+.I named.conf
+(on the theory that you forgot to delete
+.I named.boot
+when you upgraded to BIND 8).
+.LP
+.SH "ADVANCED CONFIGURATION"
+There are some cases where it is necessary to use the
+advanced configuration features of
+.BR nslint .
+Advanced configuration is done with the
+.I nslint.boot
+file.
+.LP
+The most common is when a site has a demilitarized zone (DMZ).
+The problem here is that the DMZ network will have
+.B PTR
+records for hosts outside its domain. For example lets say
+we have
+.I 128.0.rev
+with:
+.LP
+.RS
+.nf
+.sp .5
+1.1 604800 in ptr gateway.lbl.gov.
+2.1 604800 in ptr gateway.es.net.
+.sp .5
+.fi
+.RE
+.LP
+Obviously we will define an
+.B A
+record for
+.I gateway.lbl.gov
+pointing to
+.I 128.0.1.1
+but we will get errors because there is no
+.B A
+record defined for
+.IR gateway.es.net .
+The solution is to create a
+.I nslint.boot
+file (in the same directory as the other dns files)
+with:
+.LP
+.RS
+.nf
+.sp .5
+primary es.net nslint.es.net
+.sp .5
+.fi
+.RE
+.LP
+And then create the file
+.I nslint.es.net
+with:
+.LP
+.RS
+.nf
+.sp .5
+gateway 1 in a 128.0.1.2
+.sp .5
+.fi
+.RE
+.LP
+Another problem occurs when there is a
+.B CNAME
+that points to a host outside the local domains. Let's say we have
+.I info.lbl.gov
+pointing to
+.IR larry.es.net :
+.LP
+.RS
+.nf
+.sp .5
+info 604800 in cname larry.es.net.
+.sp .5
+.fi
+.RE
+.LP
+In this case we would need:
+.LP
+.RS
+.nf
+.sp .5
+primary es.net nslint.es.net
+.sp .5
+.fi
+.RE
+.LP
+in
+.I nslint.boot
+and:
+.LP
+.RS
+.nf
+.sp .5
+larry 1 in txt "place holder"
+.sp .5
+.fi
+.RE
+.LP
+.IR nslint.es.net .
+.LP
+One last problem
+when a pseudo host is setup to allow two more
+more actual hosts provide a service. For, let's say that
+.I lbl.gov
+contains:
+.LP
+.RS
+.nf
+.sp .5
+server 604800 in a 128.0.6.6
+server 604800 in a 128.0.6.94
+;
+tom 604800 in a 128.0.6.6
+tom 604800 in mx 0 lbl.gov.
+;
+jerry 604800 in a 128.0.6.94
+jerry 604800 in mx 0 lbl.gov.
+.sp .5
+.fi
+.RE
+.LP
+In this case
+.B nslint
+would complain about missing
+.B PTR
+records and ip addresses in use by more than one host.
+To suppress these warnings, add you would the lines:
+.LP
+.RS
+.nf
+.sp .5
+primary lbl.gov nslint.lbl.gov
+primary 0.128.in-addr.arpa nslint.128.0.rev
+.sp .5
+.fi
+.RE
+.LP
+to
+.I nslint.boot
+and create
+.I nslint.lbl.gov
+with:
+.LP
+.RS
+.nf
+.sp .5
+server 1 in allowdupa 128.0.6.6
+server 1 in allowdupa 128.0.6.94
+.sp .5
+.fi
+.RE
+.LP
+and create
+.I nslint.128.0.rev
+with:
+.LP
+.RS
+.nf
+.sp .5
+6.6 604800 in ptr server.lbl.gov.
+94.6 604800 in ptr server.lbl.gov.
+.sp .5
+.fi
+.RE
+.LP
+In this example, the
+.B allowdupa
+keyword tells
+.B nslint
+that it's ok for
+.I 128.0.6.6
+and
+.I 128.0.6.94
+to be shared by
+.IR server.lbl.gov ,
+.IR tom.lbl.gov ,
+and
+.IR jerry.lbl.gov .
+.LP
+One last
+.B nslint
+feature helps detect hosts that have mistakenly had two ip addresses
+assigned on the same subnet. This can happen when two different
+people request an ip address for the same hostname or when someone
+forgets an address has been assigned and requests a new number.
+.LP
+To detect such
+.B A
+records, add a
+.B nslint
+section to your
+.I nslint.conf
+containing something similar to:
+.LP
+.RS
+.nf
+.sp .5
+nslint {
+.RS
+network "128.0.6/22";
+network "128.0.6 255.255.252.0";
+.RE
+};
+.sp .5
+.fi
+.RE
+.LP
+The two network lines in this example are equivalent ways of saying the same
+thing; that subnet
+.I 128.0.6
+has a 22 bit wide subnet mask.
+.LP
+If you are using
+.IR nslint.boot ,
+the syntax would be:
+.LP
+.RS
+.nf
+.sp .5
+network 128.0.6/22
+network 128.0.6 255.255.252.0
+.sp .5
+.fi
+.RE
+.LP
+Again this shows two ways of saying the same thing.
+.LP
+Using information from the above
+.B network
+statement,
+.B nslint
+would would flag the following
+.B A
+records as being in error:
+.LP
+.RS
+.nf
+.sp .5
+server 1 in a 128.0.6.48
+server 1 in a 128.0.7.16
+.sp .5
+.fi
+.RE
+.LP
+Note that if you specify any
+.B network
+lines in your
+.I nslint.conf
+or
+.I nslint.boot
+files,
+.B nslint
+requires you to include lines for all networks;
+otherwise you might forget to add
+.B network
+lines for new networks.
+.LP
+.SH FILES
+.na
+.nh
+.nf
+/etc/named.boot - default named configuration file
+nslint.boot - default nslint configuration file
+.ad
+.hy
+.fi
+.LP
+.SH "SEE ALSO"
+.na
+.nh
+.IR named (8),
+rfc1033,
+rfc1034
+.ad
+.hy
+.SH AUTHOR
+Craig Leres of the
+Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
+.LP
+The current version is available via anonymous ftp:
+.LP
+.RS
+.I ftp://ftp.ee.lbl.gov/nslint.tar.gz
+.RE
+.SH BUGS
+Please send bug reports to nslint@ee.lbl.gov.
+.LP
+Not everyone is guaranteed to agree with all the checks done.
diff --git a/contrib/nslint-2.1a3/nslint.c b/contrib/nslint-2.1a3/nslint.c
new file mode 100644
index 0000000..8ce9505
--- /dev/null
+++ b/contrib/nslint-2.1a3/nslint.c
@@ -0,0 +1,2382 @@
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef lint
+static const char copyright[] =
+ "@(#) Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001\n\
+The Regents of the University of California. All rights reserved.\n";
+static const char rcsid[] =
+ "@(#) $Id: nslint.c,v 1.1 2001/12/21 04:12:04 marka Exp $ (LBL)";
+#endif
+/*
+ * nslint - perform consistency checks on dns files
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "savestr.h"
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#define NSLINTBOOT "nslint.boot" /* default nslint.boot file */
+#define NSLINTCONF "nslint.conf" /* default nslint.conf file */
+
+/* item struct */
+struct item {
+ char *host; /* pointer to hostname */
+ u_int32_t addr; /* ip address */
+ u_int ttl; /* ttl of A records */
+ int records; /* resource records seen */
+ int flags; /* flags word */
+};
+
+/* Resource records seen */
+#define REC_A 0x0001
+#define REC_PTR 0x0002
+#define REC_WKS 0x0004
+#define REC_HINFO 0x0008
+#define REC_MX 0x0010
+#define REC_CNAME 0x0020
+#define REC_NS 0x0040
+#define REC_SOA 0x0080
+#define REC_RP 0x0100
+#define REC_TXT 0x0200
+#define REC_SRV 0x0400
+
+/* These aren't real records */
+#define REC_OTHER 0x0800
+#define REC_REF 0x1000
+#define REC_UNKNOWN 0x2000
+
+/* Test for records we want to map to REC_OTHER */
+#define MASK_TEST_REC (REC_WKS | REC_HINFO | \
+ REC_MX | REC_SOA | REC_RP | REC_TXT | REC_SRV | REC_UNKNOWN)
+
+/* Mask away records we don't care about in the final processing to REC_OTHER */
+#define MASK_CHECK_REC \
+ (REC_A | REC_PTR | REC_CNAME | REC_REF | REC_OTHER)
+
+/* Test for records we want to check for duplicate name detection */
+#define MASK_TEST_DUP \
+ (REC_A | REC_HINFO)
+
+/* Flags */
+#define FLG_SELFMX 0x001 /* mx record refers to self */
+#define FLG_MXREF 0x002 /* this record referred to by a mx record */
+#define FLG_SMTPWKS 0x004 /* saw wks with smtp/tcp */
+#define FLG_ALLOWDUPA 0x008 /* allow duplicate a records */
+
+/* Test for smtp problems */
+#define MASK_TEST_SMTP \
+ (FLG_SELFMX | FLG_SMTPWKS)
+
+
+#define ITEMSIZE (1 << 17) /* power of two */
+#define ITEMHASH(str, h, p) \
+ for (p = str, h = 0; *p != '.' && *p != '\0';) h = (h << 5) - h + *p++
+
+struct item items[ITEMSIZE];
+int itemcnt; /* count of items */
+
+/* Hostname string storage */
+#define STRSIZE 8192; /* size to malloc when more space is needed */
+char *strptr; /* pointer to string pool */
+int strsize; /* size of space left in pool */
+
+int debug;
+int errors;
+char *bootfile = "/etc/named.boot";
+char *conffile = "/etc/named.conf";
+char *nslintboot;
+char *nslintconf;
+char *prog;
+char *cwd = ".";
+
+char **protoserv; /* valid protocol/service names */
+int protoserv_init;
+int protoserv_last;
+int protoserv_len;
+
+static char inaddr[] = ".in-addr.arpa.";
+
+/* SOA record */
+#define SOA_SERIAL 0
+#define SOA_REFRESH 1
+#define SOA_RETRY 2
+#define SOA_EXPIRE 3
+#define SOA_MINIMUM 4
+
+static u_int soaval[5];
+static int nsoaval;
+#define NSOAVAL (sizeof(soaval) / sizeof(soaval[0]))
+
+/* Forwards */
+static inline void add_domain(char *, const char *);
+int checkdots(const char *);
+void checkdups(struct item *, int);
+int checkserv(const char *, char **p);
+int checkwks(FILE *, char *, int *, char **);
+int cmpaddr(const void *, const void *);
+int cmphost(const void *, const void *);
+int doboot(const char *, int);
+int doconf(const char *, int);
+void initprotoserv(void);
+char *intoa(u_int32_t);
+int main(int, char **);
+int nslint(void);
+int parseinaddr(const char *, u_int32_t *, u_int32_t *);
+int parsenetwork(const char *, char **);
+u_int32_t parseptr(const char *, u_int32_t, u_int32_t, char **);
+char *parsequoted(char *);
+int parsesoa(const char *, char **);
+void process(const char *, const char *, const char *);
+int rfc1034host(const char *, int);
+int updateitem(const char *, u_int32_t, int, u_int, int);
+__dead void usage(void) __attribute__((volatile));
+
+extern char *optarg;
+extern int optind, opterr;
+
+/* add domain if necessary */
+static inline void
+add_domain(register char *name, register const char *domain)
+{
+ register char *cp;
+
+ /* Kill trailing white space and convert to lowercase */
+ for (cp = name; *cp != '\0' && !isspace(*cp); ++cp)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+ *cp-- = '\0';
+ /* If necessary, append domain */
+ if (cp >= name && *cp++ != '.') {
+ if (*domain != '.')
+ *cp++ = '.';
+ (void)strcpy(cp, domain);
+ }
+ /* XXX should we insure a trailing dot? */
+}
+
+int
+main(int argc, char **argv)
+{
+ register char *cp;
+ register int op, status, i, donamedboot, donamedconf;
+
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ prog = cp + 1;
+ else
+ prog = argv[0];
+
+ donamedboot = 0;
+ donamedconf = 0;
+ while ((op = getopt(argc, argv, "b:c:B:C:d")) != -1)
+ switch (op) {
+
+ case 'b':
+ bootfile = optarg;
+ ++donamedboot;
+ break;
+
+ case 'c':
+ conffile = optarg;
+ ++donamedconf;
+ break;
+
+ case 'B':
+ nslintboot = optarg;
+ ++donamedboot;
+ break;
+
+ case 'C':
+ nslintconf = optarg;
+ ++donamedconf;
+ break;
+
+ case 'd':
+ ++debug;
+ break;
+
+ default:
+ usage();
+ }
+ if (optind != argc || (donamedboot && donamedconf))
+ usage();
+
+ if (donamedboot)
+ status = doboot(bootfile, 1);
+ else if (donamedconf)
+ status = doconf(conffile, 1);
+ else {
+ status = doconf(conffile, 0);
+ if (status < 0) {
+ status = doboot(bootfile, 1);
+ ++donamedboot;
+ } else
+ ++donamedconf;
+ }
+
+ if (donamedboot) {
+ if (nslintboot != NULL)
+ status |= doboot(nslintboot, 1);
+ else if ((i = doboot(NSLINTBOOT, 0)) > 0)
+ status |= i;
+ } else {
+ if (nslintconf != NULL)
+ status |= doconf(nslintconf, 1);
+ else if ((i = doconf(NSLINTCONF, 0)) > 0)
+ status |= i;
+ }
+ status |= nslint();
+ exit (status);
+}
+
+struct netlist {
+ u_int32_t net;
+ u_int32_t mask;
+};
+
+static struct netlist *netlist;
+static u_int netlistsize; /* size of array */
+static u_int netlistcnt; /* next free element */
+
+static u_int32_t
+findmask(u_int32_t addr)
+{
+ register int i;
+
+ for (i = 0; i < netlistcnt; ++i)
+ if ((addr & netlist[i].mask) == netlist[i].net)
+ return (netlist[i].mask);
+ return (0);
+}
+
+int
+parsenetwork(register const char *cp, register char **errstrp)
+{
+ register int i, w;
+ register u_int32_t net, mask;
+ register u_int32_t o;
+ register int shift;
+ static char errstr[132];
+
+ while (isspace(*cp))
+ ++cp;
+ net = 0;
+ mask = 0;
+ shift = 24;
+ while (isdigit(*cp) && shift >= 0) {
+ o = 0;
+ do {
+ o = o * 10 + (*cp++ - '0');
+ } while (isdigit(*cp));
+ net |= o << shift;
+ shift -= 8;
+ if (*cp != '.')
+ break;
+ ++cp;
+ }
+
+
+ if (isspace(*cp)) {
+ ++cp;
+ while (isspace(*cp))
+ ++cp;
+ mask = htonl(inet_addr(cp));
+ if ((int)mask == -1) {
+ *errstrp = errstr;
+ (void)sprintf(errstr, "bad mask \"%s\"", cp);
+ return (0);
+ }
+ i = 0;
+ while (isdigit(*cp))
+ ++cp;
+ for (i = 0; i < 3 && *cp == '.'; ++i) {
+ ++cp;
+ while (isdigit(*cp))
+ ++cp;
+ }
+ if (i != 3) {
+ *errstrp = "wrong number of dots in mask";
+ return (0);
+ }
+ } else if (*cp == '/') {
+ ++cp;
+ w = atoi(cp);
+ do {
+ ++cp;
+ } while (isdigit(*cp));
+ if (w < 1 || w > 32) {
+ *errstrp = "bad mask width";
+ return (0);
+ }
+ mask = 0xffffffff << (32 - w);
+ } else {
+ *errstrp = "garbage after net";
+ return (0);
+ }
+
+ while (isspace(*cp))
+ ++cp;
+
+ if (*cp != '\0') {
+ *errstrp = "trailing garbage";
+ return (0);
+ }
+
+ /* Finaly sanity checks */
+ if ((net & ~ mask) != 0) {
+ *errstrp = errstr;
+ (void)sprintf(errstr, "host bits set in net \"%s\"",
+ intoa(net));
+ return (0);
+ }
+
+ /* Make sure there's room */
+ if (netlistsize <= netlistcnt) {
+ if (netlistsize == 0) {
+ netlistsize = 32;
+ netlist = (struct netlist *)
+ malloc(netlistsize * sizeof(*netlist));
+ } else {
+ netlistsize <<= 1;
+ netlist = (struct netlist *)
+ realloc(netlist, netlistsize * sizeof(*netlist));
+ }
+ if (netlist == NULL) {
+ fprintf(stderr, "%s: nslint: malloc/realloc: %s\n",
+ prog, strerror(errno));
+ exit(1);
+ }
+ }
+
+ /* Add to list */
+ netlist[netlistcnt].net = net;
+ netlist[netlistcnt].mask = mask;
+ ++netlistcnt;
+
+ return (1);
+}
+
+int
+doboot(register const char *file, register int mustexist)
+{
+ register int n;
+ register char *cp, *cp2;
+ register FILE *f;
+ char *errstr;
+ char buf[1024], name[128];
+
+ errno = 0;
+ f = fopen(file, "r");
+ if (f == NULL) {
+ /* Not an error if it doesn't exist */
+ if (!mustexist && errno == ENOENT) {
+ if (debug > 1)
+ printf(
+ "%s: doit: %s doesn't exist (ignoring)\n",
+ prog, file);
+ return (-1);
+ }
+ fprintf(stderr, "%s: %s: %s\n", prog, file, strerror(errno));
+ exit(1);
+ }
+ if (debug > 1)
+ printf("%s: doit: opened %s\n", prog, file);
+
+ n = 0;
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ ++n;
+
+ /* Skip comments */
+ if (buf[0] == ';')
+ continue;
+ cp = strchr(buf, ';');
+ if (cp)
+ *cp = '\0';
+ cp = buf + strlen(buf) - 1;
+ if (cp >= buf && *cp == '\n')
+ *cp = '\0';
+ cp = buf;
+
+ /* Eat leading whitespace */
+ while (isspace(*cp))
+ ++cp;
+
+ /* Skip blank lines */
+ if (*cp == '\n' || *cp == '\0')
+ continue;
+
+ /* Get name */
+ cp2 = cp;
+ while (!isspace(*cp) && *cp != '\0')
+ ++cp;
+ *cp++ = '\0';
+
+ /* Find next keyword */
+ while (isspace(*cp))
+ ++cp;
+ if (strcasecmp(cp2, "directory") == 0) {
+ /* Terminate directory */
+ cp2 = cp;
+ while (!isspace(*cp) && *cp != '\0')
+ ++cp;
+ *cp = '\0';
+ if (chdir(cp2) < 0) {
+ ++errors;
+ fprintf(stderr, "%s: can't chdir %s: %s\n",
+ prog, cp2, strerror(errno));
+ exit(1);
+ }
+ cwd = savestr(cp2);
+ continue;
+ }
+ if (strcasecmp(cp2, "primary") == 0) {
+ /* Extract domain, converting to lowercase */
+ for (cp2 = name; !isspace(*cp) && *cp != '\0'; ++cp)
+ if (isupper(*cp))
+ *cp2++ = tolower(*cp);
+ else
+ *cp2++ = *cp;
+ /* Insure trailing dot */
+ if (cp2 > name && cp2[-1] != '.')
+ *cp2++ = '.';
+ *cp2 = '\0';
+
+ /* Find file */
+ while (isspace(*cp))
+ ++cp;
+
+ /* Terminate directory */
+ cp2 = cp;
+ while (!isspace(*cp) && *cp != '\0')
+ ++cp;
+ *cp = '\0';
+
+ /* Process it! (zone is the same as the domain) */
+ nsoaval = -1;
+ memset(soaval, 0, sizeof(soaval));
+ process(cp2, name, name);
+ continue;
+ }
+ if (strcasecmp(cp2, "network") == 0) {
+ if (!parsenetwork(cp, &errstr)) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d: bad network: %s\n",
+ prog, file, n, errstr);
+ }
+ continue;
+ }
+ if (strcasecmp(cp2, "include") == 0) {
+ /* Terminate include file */
+ cp2 = cp;
+ while (!isspace(*cp) && *cp != '\0')
+ ++cp;
+ *cp = '\0';
+ errors += doboot(cp2, 1);
+ continue;
+ }
+ /* Eat any other options */
+ }
+ (void)fclose(f);
+
+ return (errors != 0);
+}
+
+int
+doconf(register const char *file, register int mustexist)
+{
+ register int n, fd, cc, i, depth;
+ register char *cp, *cp2, *buf;
+ register char *name, *zonename, *filename, *typename;
+ register int namelen, zonenamelen, filenamelen, typenamelen;
+ char *errstr;
+ struct stat sbuf;
+ char zone[128], includefile[256];
+
+ errno = 0;
+ fd = open(file, O_RDONLY, 0);
+ if (fd < 0) {
+ /* Not an error if it doesn't exist */
+ if (!mustexist && errno == ENOENT) {
+ if (debug > 1)
+ printf(
+ "%s: doconf: %s doesn't exist (ignoring)\n",
+ prog, file);
+ return (-1);
+ }
+ fprintf(stderr, "%s: %s: %s\n", prog, file, strerror(errno));
+ exit(1);
+ }
+ if (debug > 1)
+ printf("%s: doconf: opened %s\n", prog, file);
+
+ if (fstat(fd, &sbuf) < 0) {
+ fprintf(stderr, "%s: fstat(%s) %s\n",
+ prog, file, strerror(errno));
+ exit(1);
+ }
+ buf = (char *)malloc(sbuf.st_size + 1);
+ if (buf == NULL) {
+ fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
+ exit(1);
+ }
+
+ /* Slurp entire config file */
+ n = sbuf.st_size;
+ cp = buf;
+ do {
+ cc = read(fd, cp, n);
+ if (cc < 0) {
+ fprintf(stderr, "%s: read(%s) %s\n",
+ prog, file, strerror(errno));
+ exit(1);
+ }
+ cp += cc;
+ n -= cc;
+ } while (cc != 0 && cc < n);
+ buf[cc] = '\0';
+
+#define EATWHITESPACE \
+ while (isspace(*cp)) { \
+ if (*cp == '\n') \
+ ++n; \
+ ++cp; \
+ }
+
+/* Handle both to-end-of-line and C style comments */
+#define EATCOMMENTS \
+ { \
+ int sawcomment; \
+ do { \
+ EATWHITESPACE \
+ sawcomment = 0; \
+ if (*cp == '#') { \
+ sawcomment = 1; \
+ ++cp; \
+ while (*cp != '\n' && *cp != '\0') \
+ ++cp; \
+ } \
+ else if (strncmp(cp, "//", 2) == 0) { \
+ sawcomment = 1; \
+ cp += 2; \
+ while (*cp != '\n' && *cp != '\0') \
+ ++cp; \
+ } \
+ else if (strncmp(cp, "/*", 2) == 0) { \
+ sawcomment = 1; \
+ for (cp += 2; *cp != '\0'; ++cp) { \
+ if (*cp == '\n') \
+ ++n; \
+ else if (strncmp(cp, "*/", 2) == 0) { \
+ cp += 2; \
+ break; \
+ } \
+ } \
+ } \
+ } while (sawcomment); \
+ }
+
+#define GETNAME(name, len) \
+ { \
+ (name) = cp; \
+ (len) = 0; \
+ while (!isspace(*cp) && *cp != ';' && *cp != '\0') { \
+ ++(len); \
+ ++cp; \
+ } \
+ }
+
+#define GETQUOTEDNAME(name, len) \
+ { \
+ if (*cp != '"') { \
+ ++errors; \
+ fprintf(stderr, "%s: %s:%d missing left quote\n", \
+ prog, file, n); \
+ } else \
+ ++cp; \
+ (name) = cp; \
+ (len) = 0; \
+ while (*cp != '"' && *cp != '\n' && *cp != '\0') { \
+ ++(len); \
+ ++cp; \
+ } \
+ if (*cp != '"') { \
+ ++errors; \
+ fprintf(stderr, "%s: %s:%d missing right quote\n", \
+ prog, file, n); \
+ } else \
+ ++cp; \
+ }
+
+/* Eat everything to the next semicolon, perhaps eating matching qbraces */
+#define EATSEMICOLON \
+ { \
+ register int depth = 0; \
+ while (*cp != '\0') { \
+ EATCOMMENTS \
+ if (*cp == ';') { \
+ ++cp; \
+ if (depth == 0) \
+ break; \
+ continue; \
+ } \
+ if (*cp == '{') { \
+ ++depth; \
+ ++cp; \
+ continue; \
+ } \
+ if (*cp == '}') { \
+ --depth; \
+ ++cp; \
+ continue; \
+ } \
+ ++cp; \
+ } \
+ }
+
+ n = 1;
+ zone[0] = '\0';
+ cp = buf;
+ while (*cp != '\0') {
+ EATCOMMENTS
+ if (*cp == '\0')
+ break;
+ GETNAME(name, namelen)
+ if (namelen == 0) {
+ ++errors;
+ fprintf(stderr, "%s: %s:%d garbage char '%c' (1)\n",
+ prog, file, n, *cp);
+ ++cp;
+ continue;
+ }
+ EATCOMMENTS
+ if (strncasecmp(name, "options", namelen) == 0) {
+ EATCOMMENTS
+ if (*cp != '{') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d missing left qbrace in options\n",
+ prog, file, n);
+ } else
+ ++cp;
+ EATCOMMENTS
+ while (*cp != '}' && *cp != '\0') {
+ EATCOMMENTS
+ GETNAME(name, namelen)
+ if (namelen == 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d garbage char '%c' (2)\n",
+ prog, file, n, *cp);
+ ++cp;
+ break;
+ }
+
+ /* If not the "directory" option, just eat it */
+ if (strncasecmp(name, "directory",
+ namelen) == 0) {
+ EATCOMMENTS
+ GETQUOTEDNAME(cp2, i)
+ cp2[i] = '\0';
+ if (chdir(cp2) < 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:.%d can't chdir %s: %s\n",
+ prog, file, n, cp2,
+ strerror(errno));
+ exit(1);
+ }
+ cwd = savestr(cp2);
+ }
+ EATSEMICOLON
+ EATCOMMENTS
+ }
+ ++cp;
+ EATCOMMENTS
+ if (*cp != ';') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d missing options semi\n",
+ prog, file, n);
+ } else
+ ++cp;
+ continue;
+ }
+ if (strncasecmp(name, "zone", namelen) == 0) {
+ EATCOMMENTS
+ GETQUOTEDNAME(zonename, zonenamelen)
+ typename = NULL;
+ filename = NULL;
+ typenamelen = 0;
+ filenamelen = 0;
+ EATCOMMENTS
+ if (strncasecmp(cp, "in", 2) == 0) {
+ cp += 2;
+ EATWHITESPACE
+ } else if (strncasecmp(cp, "chaos", 5) == 0) {
+ cp += 5;
+ EATWHITESPACE
+ }
+ if (*cp != '{') { /* } */
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d missing left qbrace in zone\n",
+ prog, file, n);
+ continue;
+ }
+ depth = 0;
+ EATCOMMENTS
+ while (*cp != '\0') {
+ if (*cp == '{') {
+ ++cp;
+ ++depth;
+ } else if (*cp == '}') {
+ if (--depth <= 1)
+ break;
+ ++cp;
+ }
+ EATCOMMENTS
+ GETNAME(name, namelen)
+ if (namelen == 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d garbage char '%c' (3)\n",
+ prog, file, n, *cp);
+ ++cp;
+ break;
+ }
+ if (strncasecmp(name, "type",
+ namelen) == 0) {
+ EATCOMMENTS
+ GETNAME(typename, typenamelen)
+ if (namelen == 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d garbage char '%c' (4)\n",
+ prog, file, n, *cp);
+ ++cp;
+ break;
+ }
+ } else if (strncasecmp(name, "file",
+ namelen) == 0) {
+ EATCOMMENTS
+ GETQUOTEDNAME(filename, filenamelen)
+ }
+ /* Just ignore keywords we don't understand */
+ EATSEMICOLON
+ EATCOMMENTS
+ }
+ /* { */
+ if (*cp != '}') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d missing zone right qbrace\n",
+ prog, file, n);
+ } else
+ ++cp;
+ if (*cp != ';') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d missing zone semi\n",
+ prog, file, n);
+ } else
+ ++cp;
+ EATCOMMENTS
+ /* If we got something interesting, process it */
+ if (typenamelen == 0) {
+ ++errors;
+ fprintf(stderr, "%s: missing zone type!\n",
+ prog);
+ continue;
+ }
+ if (strncasecmp(typename, "master", typenamelen) == 0) {
+ if (filenamelen == 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: missing zone filename!\n",
+ prog);
+ continue;
+ }
+ strncpy(zone, zonename, zonenamelen);
+ zone[zonenamelen] = '\0';
+ for (cp2 = zone; *cp2 != '\0'; ++cp2)
+ if (isupper(*cp2))
+ *cp2 = tolower(*cp2);
+ /* Insure trailing dot */
+ if (cp2 > zone && cp2[-1] != '.') {
+ *cp2++ = '.';
+ *cp2 = '\0';
+ }
+ filename[filenamelen] = '\0';
+ nsoaval = -1;
+ memset(soaval, 0, sizeof(soaval));
+ process(filename, zone, zone);
+ }
+ continue;
+ }
+ if (strncasecmp(name, "nslint", namelen) == 0) {
+ EATCOMMENTS
+ if (*cp != '{') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d missing left qbrace in nslint\n",
+ prog, file, n);
+ } else
+ ++cp;
+ ++cp;
+ EATCOMMENTS
+ while (*cp != '}' && *cp != '\0') {
+ EATCOMMENTS
+ GETNAME(name, namelen)
+ if (strncasecmp(name, "network",
+ namelen) == 0) {
+ EATCOMMENTS
+ GETQUOTEDNAME(cp2, i)
+
+
+ cp2[i] = '\0';
+ if (!parsenetwork(cp2, &errstr)) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s:%d: bad network: %s\n",
+ prog, file, n, errstr);
+ }
+ } else {
+ ++errors;
+ fprintf(stderr,
+ "%s: unknown nslint \"%.*s\"\n",
+ prog, namelen, name);
+ }
+ EATSEMICOLON
+ EATCOMMENTS
+ }
+ ++cp;
+ EATCOMMENTS
+ if (*cp != ';') {
+ ++errors;
+ fprintf(stderr, "missing options semi\n");
+ } else
+ ++cp;
+ continue;
+ }
+ if (strncasecmp(name, "include", namelen) == 0) {
+ EATCOMMENTS
+ GETQUOTEDNAME(filename, filenamelen)
+ strncpy(includefile, filename, filenamelen);
+ includefile[filenamelen] = '\0';
+ errors += doconf(includefile, 1);
+ EATSEMICOLON
+ continue;
+ }
+
+ /* Skip over statements we don't understand */
+ EATSEMICOLON
+ }
+
+ free(buf);
+ close(fd);
+ return (errors != 0);
+}
+
+/* Return true when done */
+int
+parsesoa(register const char *cp, register char **errstrp)
+{
+ register char ch, *garbage;
+ static char errstr[132];
+
+ /* Eat leading whitespace */
+ while (isspace(*cp))
+ ++cp;
+
+ /* Find opening paren */
+ if (nsoaval < 0) {
+ cp = strchr(cp, '(');
+ if (cp == NULL)
+ return (0);
+ ++cp;
+ while (isspace(*cp))
+ ++cp;
+ nsoaval = 0;
+ }
+
+ /* Grab any numbers we find */
+ garbage = "leading garbage";
+ while (isdigit(*cp) && nsoaval < NSOAVAL) {
+ soaval[nsoaval] = atoi(cp);
+ do {
+ ++cp;
+ } while (isdigit(*cp));
+ if (nsoaval == SOA_SERIAL && *cp == '.' && isdigit(cp[1])) {
+ do {
+ ++cp;
+ } while (isdigit(*cp));
+ } else {
+ ch = *cp;
+ if (isupper(ch))
+ ch = tolower(ch);
+ switch (ch) {
+
+ case 'w':
+ soaval[nsoaval] *= 7;
+ /* fall through */
+
+ case 'd':
+ soaval[nsoaval] *= 24;
+ /* fall through */
+
+ case 'h':
+ soaval[nsoaval] *= 60;
+ /* fall through */
+
+ case 'm':
+ soaval[nsoaval] *= 60;
+ /* fall through */
+
+ case 's':
+ ++cp;
+ break;
+
+ default:
+ ; /* none */
+ }
+ }
+ while (isspace(*cp))
+ ++cp;
+ garbage = "trailing garbage";
+ ++nsoaval;
+ }
+
+ /* If we're done, do some sanity checks */
+ if (nsoaval >= NSOAVAL && *cp == ')') {
+ ++cp;
+ if (*cp != '\0')
+ *errstrp = garbage;
+ else if (soaval[SOA_EXPIRE] <
+ soaval[SOA_REFRESH] + 10 * soaval[SOA_RETRY]) {
+ (void)sprintf(errstr,
+ "expire less than refresh + 10 * retry (%u < %u + 10 * %u)",
+ soaval[SOA_EXPIRE],
+ soaval[SOA_REFRESH],
+ soaval[SOA_RETRY]);
+ *errstrp = errstr;
+ } else if (soaval[SOA_REFRESH] < 2 * soaval[SOA_RETRY]) {
+ (void)sprintf(errstr,
+ "refresh less than 2 * retry (%u < 2 * %u)",
+ soaval[SOA_REFRESH],
+ soaval[SOA_RETRY]);
+ *errstrp = errstr;
+ }
+ return (1);
+ }
+
+ if (*cp != '\0') {
+ *errstrp = garbage;
+ return (1);
+ }
+
+ return (0);
+}
+
+void
+process(register const char *file, register const char *domain,
+ register const char *zone)
+{
+ register FILE *f;
+ register char ch, *cp, *cp2, *cp3, *rtype;
+ register const char *ccp;
+ register int n, sawsoa, flags, i;
+ register u_int ttl;
+ register u_int32_t addr;
+ u_int32_t net, mask;
+ int smtp;
+ char buf[1024], name[128], lastname[128], odomain[128];
+ char *errstr;
+ char *dotfmt = "%s: %s/%s:%d \"%s\" target missing trailing dot: %s\n";
+
+ f = fopen(file, "r");
+ if (f == NULL) {
+ fprintf(stderr, "%s: %s/%s: %s\n",
+ prog, cwd, file, strerror(errno));
+ ++errors;
+ return;
+ }
+ if (debug > 1)
+ printf("%s: process: opened %s/%s\n", prog, cwd, file);
+
+ /* Are we doing an in-addr.arpa domain? */
+ n = 0;
+ net = 0;
+ mask = 0;
+ ccp = domain + strlen(domain) - sizeof(inaddr) + 1;
+ if (ccp >= domain && strcasecmp(ccp, inaddr) == 0 &&
+ !parseinaddr(domain, &net, &mask)) {
+ ++errors;
+ fprintf(stderr, "%s: %s/%s:%d bad in-addr.arpa domain\n",
+ prog, cwd, file, n);
+ return;
+ }
+
+ lastname[0] = '\0';
+ sawsoa = 0;
+ while (fgets(buf, sizeof(buf), f) != NULL) {
+ ++n;
+ cp = buf;
+ while (*cp != '\0') {
+ /* Handle quoted strings (but don't report errors) */
+ if (*cp == '"') {
+ ++cp;
+ while (*cp != '"' && *cp != '\n' && *cp != '\0')
+ ++cp;
+ continue;
+ }
+ if (*cp == '\n' || *cp == ';')
+ break;
+ ++cp;
+ }
+ *cp-- = '\0';
+
+ /* Nuke trailing white space */
+ while (cp >= buf && isspace(*cp))
+ *cp-- = '\0';
+
+ cp = buf;
+ if (*cp == '\0')
+ continue;
+
+ /* Handle multi-line soa records */
+ if (sawsoa) {
+ errstr = NULL;
+ if (parsesoa(cp, &errstr))
+ sawsoa = 0;
+ if (errstr != NULL) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d bad \"soa\" record (%s)\n",
+ prog, cwd, file, n, errstr);
+ }
+ continue;
+ }
+ if (debug > 3)
+ printf(">%s<\n", cp);
+
+ /* Look for name */
+ if (isspace(*cp)) {
+ /* Same name as last record */
+ if (lastname[0] == '\0') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d no default name\n",
+ prog, cwd, file, n);
+ continue;
+ }
+ (void)strcpy(name, lastname);
+ } else {
+ /* Extract name, converting to lowercase */
+ for (cp2 = name; !isspace(*cp) && *cp != '\0'; ++cp)
+ if (isupper(*cp))
+ *cp2++ = tolower(*cp);
+ else
+ *cp2++ = *cp;
+ *cp2 = '\0';
+
+ /* Check for domain shorthand */
+ if (name[0] == '@' && name[1] == '\0')
+ (void)strcpy(name, domain);
+ }
+
+ /* Find next token */
+ while (isspace(*cp))
+ ++cp;
+
+ /* Handle includes (gag) */
+ if (name[0] == '$' && strcasecmp(name, "$include") == 0) {
+ /* Extract filename */
+ cp2 = name;
+ while (!isspace(*cp) && *cp != '\0')
+ *cp2++ = *cp++;
+ *cp2 = '\0';
+
+ /* Look for optional domain */
+ while (isspace(*cp))
+ ++cp;
+ if (*cp == '\0')
+ process(name, domain, zone);
+ else {
+ cp2 = cp;
+ /* Convert optional domain to lowercase */
+ for (; !isspace(*cp) && *cp != '\0'; ++cp)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+ *cp = '\0';
+ process(name, cp2, cp2);
+ }
+ continue;
+ }
+
+ /* Handle $origin */
+ if (name[0] == '$' && strcasecmp(name, "$origin") == 0) {
+ /* Extract domain, converting to lowercase */
+ for (cp2 = odomain; !isspace(*cp) && *cp != '\0'; ++cp)
+ if (isupper(*cp))
+ *cp2++ = tolower(*cp);
+ else
+ *cp2++ = *cp;
+ *cp2 = '\0';
+ domain = odomain;
+ lastname[0] = '\0';
+
+ /* Are we doing an in-addr.arpa domain? */
+ net = 0;
+ mask = 0;
+ ccp = domain + strlen(domain) - (sizeof(inaddr) - 1);
+ if (ccp >= domain && strcasecmp(ccp, inaddr) == 0 &&
+ !parseinaddr(domain, &net, &mask)) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d bad in-addr.arpa domain\n",
+ prog, cwd, file, n);
+ return;
+ }
+ continue;
+ }
+
+ /* Handle ttl */
+ if (name[0] == '$' && strcasecmp(name, "$ttl") == 0) {
+ cp2 = cp;
+ while (isdigit(*cp))
+ ++cp;
+ ch = *cp;
+ if (isupper(ch))
+ ch = tolower(ch);
+ if (strchr("wdhms", ch) != NULL)
+ ++cp;
+ while (isspace(*cp))
+ ++cp;
+ if (*cp != '\0') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d bad $ttl \"%s\"\n",
+ prog, cwd, file, n, cp2);
+ }
+ (void)strcpy(name, lastname);
+ continue;
+ }
+
+ /* Parse ttl or use default */
+ if (isdigit(*cp)) {
+ ttl = atoi(cp);
+ do {
+ ++cp;
+ } while (isdigit(*cp));
+
+ ch = *cp;
+ if (isupper(ch))
+ ch = tolower(ch);
+ switch (ch) {
+
+ case 'w':
+ ttl *= 7;
+ /* fall through */
+
+ case 'd':
+ ttl *= 24;
+ /* fall through */
+
+ case 'h':
+ ttl *= 60;
+ /* fall through */
+
+ case 'm':
+ ttl *= 60;
+ /* fall through */
+
+ case 's':
+ ++cp;
+ break;
+
+ default:
+ ; /* none */
+ }
+
+
+ if (!isspace(*cp)) {
+ ++errors;
+ fprintf(stderr, "%s: %s/%s:%d bad ttl\n",
+ prog, cwd, file, n);
+ continue;
+ }
+
+ /* Find next token */
+ ++cp;
+ while (isspace(*cp))
+ ++cp;
+ } else
+ ttl = soaval[SOA_MINIMUM];
+
+ /* Eat optional "in" */
+ if ((cp[0] == 'i' || cp[0] == 'I') &&
+ (cp[1] == 'n' || cp[1] == 'N') && isspace(cp[2])) {
+ /* Find next token */
+ cp += 3;
+ while (isspace(*cp))
+ ++cp;
+ } else if ((cp[0] == 'c' || cp[0] == 'C') &&
+ isspace(cp[5]) && strncasecmp(cp, "chaos", 5) == 0) {
+ /* Find next token */
+ cp += 5;
+ while (isspace(*cp))
+ ++cp;
+ }
+
+ /* Find end of record type, converting to lowercase */
+ rtype = cp;
+ for (rtype = cp; !isspace(*cp) && *cp != '\0'; ++cp)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+ *cp++ = '\0';
+
+ /* Find "the rest" */
+ while (isspace(*cp))
+ ++cp;
+
+ /* Check for non-ptr names with dots but no trailing dot */
+ if (!isdigit(*name) &&
+ checkdots(name) && strcmp(domain, ".") != 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"%s\" name missing trailing dot: %s\n",
+ prog, cwd, file, n, rtype, name);
+ }
+
+ /* Check for FQDNs outside the zone */
+ cp2 = name + strlen(name) - 1;
+ if (cp2 >= name && *cp2 == '.' && strchr(name, '.') != NULL) {
+ cp2 = name + strlen(name) - strlen(zone);
+ if (cp2 >= name && strcasecmp(cp2, zone) != 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"%s\" outside zone %s\n",
+ prog, cwd, file, n, name, zone);
+ }
+ }
+
+#define CHECK4(p, a, b, c, d) \
+ (p[0] == (a) && p[1] == (b) && p[2] == (c) && p[3] == (d) && p[4] == '\0')
+#define CHECK3(p, a, b, c) \
+ (p[0] == (a) && p[1] == (b) && p[2] == (c) && p[3] == '\0')
+#define CHECK2(p, a, b) \
+ (p[0] == (a) && p[1] == (b) && p[2] == '\0')
+#define CHECKDOT(p) \
+ (p[0] == '.' && p[1] == '\0')
+
+ if (rtype[0] == 'a' && rtype[1] == '\0') {
+ /* Handle "a" record */
+ add_domain(name, domain);
+ addr = htonl(inet_addr(cp));
+ if ((int)addr == -1) {
+ ++errors;
+ cp2 = cp + strlen(cp) - 1;
+ if (cp2 >= cp && *cp2 == '\n')
+ *cp2 = '\0';
+ fprintf(stderr,
+ "%s: %s/%s:%d bad \"a\" record ip addr \"%s\"\n",
+ prog, cwd, file, n, cp);
+ continue;
+ }
+ errors += updateitem(name, addr, REC_A, ttl, 0);
+ } else if (CHECK4(rtype, 'a', 'a', 'a', 'a')) {
+ /* Just eat for now */
+ continue;
+ } else if (CHECK3(rtype, 'p', 't', 'r')) {
+ /* Handle "ptr" record */
+ add_domain(name, domain);
+ if (strcmp(cp, "@") == 0)
+ (void)strcpy(cp, zone);
+ if (checkdots(cp)) {
+ ++errors;
+ fprintf(stderr, dotfmt,
+ prog, cwd, file, n, rtype, cp);
+ }
+ add_domain(cp, domain);
+ errstr = NULL;
+ addr = parseptr(name, net, mask, &errstr);
+ if (errstr != NULL) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d bad \"ptr\" record (%s) ip addr \"%s\"\n",
+ prog, cwd, file, n, errstr, name);
+ continue;
+ }
+ errors += updateitem(cp, addr, REC_PTR, 0, 0);
+ } else if (CHECK3(rtype, 's', 'o', 'a')) {
+ /* Handle "soa" record */
+ if (!CHECKDOT(name)) {
+ add_domain(name, domain);
+ errors += updateitem(name, 0, REC_SOA, 0, 0);
+ }
+ errstr = NULL;
+ if (!parsesoa(cp, &errstr))
+ ++sawsoa;
+ if (errstr != NULL) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d bad \"soa\" record (%s)\n",
+ prog, cwd, file, n, errstr);
+ continue;
+ }
+ } else if (CHECK3(rtype, 'w', 'k', 's')) {
+ /* Handle "wks" record */
+ addr = htonl(inet_addr(cp));
+ if ((int)addr == -1) {
+ ++errors;
+ cp2 = cp;
+ while (!isspace(*cp2) && *cp2 != '\0')
+ ++cp2;
+ *cp2 = '\0';
+ fprintf(stderr,
+ "%s: %s/%s:%d bad \"wks\" record ip addr \"%s\"\n",
+ prog, cwd, file, n, cp);
+ continue;
+ }
+ /* Step over ip address */
+ while (*cp == '.' || isdigit(*cp))
+ ++cp;
+ while (isspace(*cp))
+ *cp++ = '\0';
+ /* Make sure services are legit */
+ errstr = NULL;
+ n += checkwks(f, cp, &smtp, &errstr);
+ if (errstr != NULL) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d bad \"wks\" record (%s)\n",
+ prog, cwd, file, n, errstr);
+ continue;
+ }
+ add_domain(name, domain);
+ errors += updateitem(name, addr, REC_WKS,
+ 0, smtp ? FLG_SMTPWKS : 0);
+ /* XXX check to see if ip address records exists? */
+ } else if (rtype[0] == 'h' && strcmp(rtype, "hinfo") == 0) {
+ /* Handle "hinfo" record */
+ add_domain(name, domain);
+ errors += updateitem(name, 0, REC_HINFO, 0, 0);
+ cp2 = cp;
+ cp = parsequoted(cp);
+ if (cp == NULL) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"hinfo\" missing quote: %s\n",
+ prog, cwd, file, n, cp2);
+ continue;
+ }
+ if (!isspace(*cp)) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"hinfo\" missing white space: %s\n",
+ prog, cwd, file, n, cp2);
+ continue;
+ }
+ ++cp;
+ while (isspace(*cp))
+ ++cp;
+ if (*cp == '\0') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"hinfo\" missing keyword: %s\n",
+ prog, cwd, file, n, cp2);
+ continue;
+ }
+ cp = parsequoted(cp);
+ if (cp == NULL) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"hinfo\" missing quote: %s\n",
+ prog, cwd, file, n, cp2);
+ continue;
+ }
+ if (*cp != '\0') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"hinfo\" garbage after keywords: %s\n",
+ prog, cwd, file, n, cp2);
+ continue;
+ }
+ } else if (CHECK2(rtype, 'm', 'x')) {
+ /* Handle "mx" record */
+ add_domain(name, domain);
+ errors += updateitem(name, 0, REC_MX, ttl, 0);
+
+ /* Look for priority */
+ if (!isdigit(*cp)) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d bad \"mx\" priority: %s\n",
+ prog, cwd, file, n, cp);
+ }
+
+ /* Skip over priority */
+ ++cp;
+ while (isdigit(*cp))
+ ++cp;
+ while (isspace(*cp))
+ ++cp;
+ if (*cp == '\0') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d missing \"mx\" hostname\n",
+ prog, cwd, file, n);
+ }
+ if (strcmp(cp, "@") == 0)
+ (void)strcpy(cp, zone);
+ if (checkdots(cp)) {
+ ++errors;
+ fprintf(stderr, dotfmt,
+ prog, cwd, file, n, rtype, cp);
+ }
+
+ /* Check to see if mx host exists */
+ add_domain(cp, domain);
+ flags = FLG_MXREF;
+ if (*name == *cp && strcmp(name, cp) == 0)
+ flags |= FLG_SELFMX;
+ errors += updateitem(cp, 0, REC_REF, 0, flags);
+ } else if (rtype[0] == 'c' && strcmp(rtype, "cname") == 0) {
+ /* Handle "cname" record */
+ add_domain(name, domain);
+ errors += updateitem(name, 0, REC_CNAME, 0, 0);
+ if (checkdots(cp)) {
+ ++errors;
+ fprintf(stderr, dotfmt,
+ prog, cwd, file, n, rtype, cp);
+ }
+
+ /* Make sure cname points somewhere */
+ if (strcmp(cp, "@") == 0)
+ (void)strcpy(cp, zone);
+ add_domain(cp, domain);
+ errors += updateitem(cp, 0, REC_REF, 0, 0);
+ } else if (CHECK3(rtype, 's', 'r', 'v')) {
+ /* Handle "srv" record */
+ add_domain(name, domain);
+ errors += updateitem(name, 0, REC_SRV, 0, 0);
+ cp2 = cp;
+
+ /* Skip over three values */
+ for (i = 0; i < 3; ++i) {
+ if (!isdigit(*cp)) {
+ ++errors;
+ fprintf(stderr, "%s: %s/%s:%d"
+ " bad \"srv\" value: %s\n",
+ prog, cwd, file, n, cp);
+ }
+
+ /* Skip over value */
+ ++cp;
+ while (isdigit(*cp))
+ ++cp;
+ while (isspace(*cp))
+ ++cp;
+ }
+
+ /* Check to see if mx host exists */
+ add_domain(cp, domain);
+ errors += updateitem(cp, 0, REC_REF, 0, 0);
+ } else if (CHECK3(rtype, 't', 'x', 't')) {
+ /* Handle "txt" record */
+ add_domain(name, domain);
+ errors += updateitem(name, 0, REC_TXT, 0, 0);
+ cp2 = cp;
+ cp = parsequoted(cp);
+ if (cp == NULL) {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"txt\" missing quote: %s\n",
+ prog, cwd, file, n, cp2);
+ continue;
+ }
+ while (isspace(*cp))
+ ++cp;
+ if (*cp != '\0') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"txt\" garbage after text: %s\n",
+ prog, cwd, file, n, cp2);
+ continue;
+ }
+ } else if (CHECK2(rtype, 'n', 's')) {
+ /* Handle "ns" record */
+ errors += updateitem(zone, 0, REC_NS, 0, 0);
+ if (strcmp(cp, "@") == 0)
+ (void)strcpy(cp, zone);
+ if (checkdots(cp)) {
+ ++errors;
+ fprintf(stderr, dotfmt,
+ prog, cwd, file, n, rtype, cp);
+ }
+ add_domain(cp, domain);
+ errors += updateitem(cp, 0, REC_REF, 0, 0);
+ } else if (CHECK2(rtype, 'r', 'p')) {
+ /* Handle "rp" record */
+ add_domain(name, domain);
+ errors += updateitem(name, 0, REC_RP, 0, 0);
+ cp2 = cp;
+
+ /* Step over mailbox name */
+ /* XXX could add_domain() and check further */
+ while (!isspace(*cp) && *cp != '\0')
+ ++cp;
+ if (*cp == '\0') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"rp\" missing text name: %s\n",
+ prog, cwd, file, n, cp2);
+ continue;
+ }
+ ++cp;
+ cp3 = cp;
+
+ /* Step over text name */
+ while (!isspace(*cp) && *cp != '\0')
+ ++cp;
+
+ if (*cp != '\0') {
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d \"rp\" garbage after text name: %s\n",
+ prog, cwd, file, n, cp2);
+ continue;
+ }
+
+ /* Make sure text name points somewhere (if not ".") */
+ if (!CHECKDOT(cp3)) {
+ add_domain(cp3, domain);
+ errors += updateitem(cp3, 0, REC_REF, 0, 0);
+ }
+ } else if (rtype[0] == 'a' && strcmp(rtype, "allowdupa") == 0) {
+ /* Handle "allow duplicate a" record */
+ add_domain(name, domain);
+ addr = htonl(inet_addr(cp));
+ if ((int)addr == -1) {
+ ++errors;
+ cp2 = cp + strlen(cp) - 1;
+ if (cp2 >= cp && *cp2 == '\n')
+ *cp2 = '\0';
+ fprintf(stderr,
+ "%s: %s/%s:%d bad \"allowdupa\" record ip addr \"%s\"\n",
+ prog, cwd, file, n, cp);
+ continue;
+ }
+ errors += updateitem(name, addr, 0, 0, FLG_ALLOWDUPA);
+ } else {
+ /* Unknown record type */
+ ++errors;
+ fprintf(stderr,
+ "%s: %s/%s:%d unknown record type \"%s\"\n",
+ prog, cwd, file, n, rtype);
+ add_domain(name, domain);
+ errors += updateitem(name, 0, REC_UNKNOWN, 0, 0);
+ }
+ (void)strcpy(lastname, name);
+ }
+ (void)fclose(f);
+ return;
+}
+
+/* Records we use to detect duplicates */
+static struct duprec {
+ int record;
+ char *name;
+} duprec[] = {
+ { REC_A, "a" },
+ { REC_HINFO, "hinfo" },
+ { 0, NULL },
+};
+
+void
+checkdups(register struct item *ip, register int records)
+{
+ register struct duprec *dp;
+
+ records &= (ip->records & MASK_TEST_DUP);
+ if (records == 0)
+ return;
+ for (dp = duprec; dp->name != NULL; ++dp)
+ if ((records & dp->record) != 0) {
+ ++errors;
+ fprintf(stderr, "%s: multiple \"%s\" records for %s\n",
+ prog, dp->name, ip->host);
+ records &= ~dp->record;
+ }
+ if (records != 0)
+ fprintf(stderr, "%s: checkdups: records not zero (%d)\n",
+ prog, records);
+}
+
+int
+updateitem(register const char *host, register u_int32_t addr,
+ register int records, register u_int ttl, register int flags)
+{
+ register const char *ccp;
+ register int n, errs;
+ register u_int i;
+ register struct item *ip;
+ int foundsome;
+
+ n = 0;
+ foundsome = 0;
+ errs = 0;
+ ITEMHASH(host, i, ccp);
+ ip = &items[i & (ITEMSIZE - 1)];
+ while (n < ITEMSIZE && ip->host) {
+ if ((addr == 0 || addr == ip->addr || ip->addr == 0) &&
+ *host == *ip->host && strcmp(host, ip->host) == 0) {
+ ++foundsome;
+ if (ip->addr == 0)
+ ip->addr = addr;
+ if ((records & MASK_TEST_DUP) != 0)
+ checkdups(ip, records);
+ ip->records |= records;
+ /* Only check differing ttl's for A and MX records */
+ if (ip->ttl == 0)
+ ip->ttl = ttl;
+ else if (ttl != 0 && ip->ttl != ttl) {
+ fprintf(stderr,
+ "%s: differing ttls for %s (%u != %u)\n",
+ prog, ip->host, ttl, ip->ttl);
+ ++errs;
+ }
+ ip->flags |= flags;
+ /* Not done if we wildcard matched the name */
+ if (addr)
+ return (errs);
+ }
+ ++n;
+ ++ip;
+ if (ip >= &items[ITEMSIZE])
+ ip = items;
+ }
+
+ if (n >= ITEMSIZE) {
+ fprintf(stderr, "%s: out of item slots (max %d)\n",
+ prog, ITEMSIZE);
+ exit(1);
+ }
+
+ /* Done if we were wildcarding the name (and found entries for it) */
+ if (addr == 0 && foundsome)
+ return (errs);
+
+ /* Didn't find it, make new entry */
+ ++itemcnt;
+ if (ip->host) {
+ fprintf(stderr, "%s: reusing bucket!\n", prog);
+ exit(1);
+ }
+ ip->addr = addr;
+ ip->host = savestr(host);
+ if ((records & MASK_TEST_DUP) != 0)
+ checkdups(ip, records);
+ ip->records |= records;
+ if (ttl != 0)
+ ip->ttl = ttl;
+ ip->flags |= flags;
+ return (errs);
+}
+
+static const char *microlist[] = {
+ "_tcp",
+ "_udp",
+ "_msdcs",
+ "_sites",
+ NULL
+};
+
+int
+rfc1034host(register const char *host, register int recs)
+{
+ register const char *cp, **p;
+ register int underok;
+
+ underok = 0;
+ for (p = microlist; *p != NULL ;++p)
+ if ((cp = strstr(host, *p)) != NULL &&
+ cp > host &&
+ cp[-1] == '.' &&
+ cp[strlen(*p)] == '.') {
+ ++underok;
+ break;
+ }
+
+ cp = host;
+ if (!(isalpha(*cp) || isdigit(*cp) || (*cp == '_' && underok))) {
+ fprintf(stderr,
+ "%s: illegal hostname \"%s\" (starts with non-alpha/numeric)\n",
+ prog, host);
+ return (1);
+ }
+ for (++cp; *cp != '.' && *cp != '\0'; ++cp)
+ if (!(isalpha(*cp) || isdigit(*cp) || *cp == '-' ||
+ (*cp == '/' && (recs & REC_SOA) != 0))) {
+ fprintf(stderr,
+ "%s: illegal hostname \"%s\" ('%c' illegal character)\n",
+ prog, host, *cp);
+ return (1);
+ }
+ if (--cp >= host && *cp == '-') {
+ fprintf(stderr, "%s: illegal hostname \"%s\" (ends with '-')\n",
+ prog, host);
+ return (1);
+ }
+ return (0);
+}
+
+int
+nslint(void)
+{
+ register int n, records, flags;
+ register struct item *ip, *lastaip, **ipp, **itemlist;
+ register u_int32_t addr, lastaddr, mask;
+
+ itemlist = (struct item **)calloc(itemcnt, sizeof(*ipp));
+ if (itemlist == NULL) {
+ fprintf(stderr, "%s: nslint: calloc: %s\n",
+ prog, strerror(errno));
+ exit(1);
+ }
+ ipp = itemlist;
+ for (n = 0, ip = items; n < ITEMSIZE; ++n, ++ip) {
+ if (ip->host == NULL)
+ continue;
+
+ /* Save entries with addresses for later check */
+ if (ip->addr != 0)
+ *ipp++ = ip;
+
+ if (debug > 1) {
+ if (debug > 2)
+ printf("%d\t", n);
+ printf("%s\t%s\t0x%x\t0x%x\n",
+ ip->host, intoa(ip->addr), ip->records, ip->flags);
+ }
+
+ /* Check for illegal hostnames (rfc1034) */
+ if (rfc1034host(ip->host, ip->records))
+ ++errors;
+
+ /* Check for missing ptr records (ok if also an ns record) */
+ records = ip->records & MASK_CHECK_REC;
+ if ((ip->records & MASK_TEST_REC) != 0)
+ records |= REC_OTHER;
+ switch (records) {
+
+ case REC_A | REC_OTHER | REC_PTR | REC_REF:
+ case REC_A | REC_OTHER | REC_PTR:
+ case REC_A | REC_PTR | REC_REF:
+ case REC_A | REC_PTR:
+ case REC_CNAME:
+ /* These are O.K. */
+ break;
+
+ case REC_CNAME | REC_REF:
+ ++errors;
+ fprintf(stderr, "%s: \"cname\" referenced by other"
+ " \"cname\" or \"mx\": %s\n", prog, ip->host);
+ break;
+
+ case REC_OTHER | REC_REF:
+ case REC_OTHER:
+ /*
+ * This is only an error if there is an address
+ * associated with the hostname; this means
+ * there was a wks entry with bogus address.
+ * Otherwise, we have an mx or hinfo.
+ */
+ if (ip->addr != 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: \"wks\" without \"a\" and \"ptr\": %s -> %s\n",
+ prog, ip->host, intoa(ip->addr));
+ }
+ break;
+
+ case REC_REF:
+ ++errors;
+ fprintf(stderr,
+ "%s: name referenced without other records: %s\n",
+ prog, ip->host);
+ break;
+
+ case REC_A | REC_OTHER | REC_REF:
+ case REC_A | REC_OTHER:
+ case REC_A | REC_REF:
+ case REC_A:
+ ++errors;
+ fprintf(stderr, "%s: missing \"ptr\": %s -> %s\n",
+ prog, ip->host, intoa(ip->addr));
+ break;
+
+ case REC_OTHER | REC_PTR | REC_REF:
+ case REC_OTHER | REC_PTR:
+ case REC_PTR | REC_REF:
+ case REC_PTR:
+ ++errors;
+ fprintf(stderr, "%s: missing \"a\": %s -> %s\n",
+ prog, ip->host, intoa(ip->addr));
+ break;
+
+ case REC_A | REC_CNAME | REC_OTHER | REC_PTR | REC_REF:
+ case REC_A | REC_CNAME | REC_OTHER | REC_PTR:
+ case REC_A | REC_CNAME | REC_OTHER | REC_REF:
+ case REC_A | REC_CNAME | REC_OTHER:
+ case REC_A | REC_CNAME | REC_PTR | REC_REF:
+ case REC_A | REC_CNAME | REC_PTR:
+ case REC_A | REC_CNAME | REC_REF:
+ case REC_A | REC_CNAME:
+ case REC_CNAME | REC_OTHER | REC_PTR | REC_REF:
+ case REC_CNAME | REC_OTHER | REC_PTR:
+ case REC_CNAME | REC_OTHER | REC_REF:
+ case REC_CNAME | REC_OTHER:
+ case REC_CNAME | REC_PTR | REC_REF:
+ case REC_CNAME | REC_PTR:
+ ++errors;
+ fprintf(stderr, "%s: \"cname\" %s has other records\n",
+ prog, ip->host);
+ break;
+
+ case 0:
+ /* Second level test */
+ if ((ip->records & ~(REC_NS | REC_TXT)) == 0)
+ break;
+ /* Fall through... */
+
+ default:
+ ++errors;
+ fprintf(stderr,
+ "%s: records == 0x%x: can't happen (%s 0x%x)\n",
+ prog, records, ip->host, ip->records);
+ break;
+ }
+
+ /* Check for smtp problems */
+ flags = ip->flags & MASK_TEST_SMTP;
+
+ if ((flags & FLG_SELFMX) != 0 && (ip->records & REC_A) == 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: self \"mx\" for %s missing \"a\" record\n",
+ prog, ip->host);
+ }
+
+ switch (flags) {
+
+ case 0:
+ case FLG_SELFMX | FLG_SMTPWKS:
+ /* These are O.K. */
+ break;
+
+ case FLG_SELFMX:
+ if ((ip->records & REC_WKS) != 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: smtp/tcp missing from \"wks\": %s\n",
+ prog, ip->host);
+ }
+ break;
+
+ case FLG_SMTPWKS:
+ ++errors;
+ fprintf(stderr,
+ "%s: saw smtp/tcp without self \"mx\": %s\n",
+ prog, ip->host);
+ break;
+
+ default:
+ ++errors;
+ fprintf(stderr,
+ "%s: flags == 0x%x: can't happen (%s)\n",
+ prog, flags, ip->host);
+ }
+
+ /* Check for chained MX records */
+ if ((ip->flags & (FLG_SELFMX | FLG_MXREF)) == FLG_MXREF &&
+ (ip->records & REC_MX) != 0) {
+ ++errors;
+ fprintf(stderr, "%s: \"mx\" referenced by other"
+ " \"mx\" record: %s\n", prog, ip->host);
+ }
+ }
+
+ /* Check for doubly booked addresses */
+ n = ipp - itemlist;
+ qsort(itemlist, n, sizeof(itemlist[0]), cmpaddr);
+ lastaddr = 0;
+ ip = NULL;
+ for (ipp = itemlist; n > 0; ++ipp, --n) {
+ addr = (*ipp)->addr;
+ if (lastaddr == addr &&
+ ((*ipp)->flags & FLG_ALLOWDUPA) == 0 &&
+ (ip->flags & FLG_ALLOWDUPA) == 0) {
+ ++errors;
+ fprintf(stderr, "%s: %s in use by %s and %s\n",
+ prog, intoa(addr), (*ipp)->host, ip->host);
+ }
+ lastaddr = addr;
+ ip = *ipp;
+ }
+
+ /* Check for hosts with multiple addresses on the same subnet */
+ n = ipp - itemlist;
+ qsort(itemlist, n, sizeof(itemlist[0]), cmphost);
+ if (netlistcnt > 0) {
+ n = ipp - itemlist;
+ lastaip = NULL;
+ for (ipp = itemlist; n > 0; ++ipp, --n) {
+ ip = *ipp;
+ if ((ip->records & REC_A) == 0 ||
+ (ip->flags & FLG_ALLOWDUPA) != 0)
+ continue;
+ if (lastaip != NULL &&
+ strcasecmp(ip->host, lastaip->host) == 0) {
+ mask = findmask(ip->addr);
+ if (mask == 0) {
+ ++errors;
+ fprintf(stderr,
+ "%s: can't find mask for %s (%s)\n",
+ prog, ip->host, intoa(ip->addr));
+ } else if ((lastaip->addr & mask) ==
+ (ip->addr & mask) ) {
+ ++errors;
+ fprintf(stderr,
+ "%s: multiple \"a\" records for %s on subnet %s",
+ prog, ip->host,
+ intoa(ip->addr & mask));
+ fprintf(stderr, "\n\t(%s",
+ intoa(lastaip->addr));
+ fprintf(stderr, " and %s)\n",
+ intoa(ip->addr));
+ }
+ }
+ lastaip = ip;
+ }
+ }
+
+ if (debug)
+ printf("%s: %d/%d items used, %d error%s\n", prog, itemcnt,
+ ITEMSIZE, errors, errors == 1 ? "" : "s");
+ return (errors != 0);
+}
+
+/* Similar to inet_ntoa() */
+char *
+intoa(u_int32_t addr)
+{
+ register char *cp;
+ register u_int byte;
+ register int n;
+ static char buf[sizeof(".xxx.xxx.xxx.xxx")];
+
+ cp = &buf[sizeof buf];
+ *--cp = '\0';
+
+ n = 4;
+ do {
+ byte = addr & 0xff;
+ *--cp = byte % 10 + '0';
+ byte /= 10;
+ if (byte > 0) {
+ *--cp = byte % 10 + '0';
+ byte /= 10;
+ if (byte > 0)
+ *--cp = byte + '0';
+ }
+ *--cp = '.';
+ addr >>= 8;
+ } while (--n > 0);
+
+ return cp + 1;
+}
+
+int
+parseinaddr(register const char *cp, register u_int32_t *netp,
+ register u_int32_t *maskp)
+{
+ register int i, bits;
+ register u_int32_t o, net, mask;
+
+ if (!isdigit(*cp))
+ return (0);
+ net = 0;
+ mask = 0xff000000;
+ bits = 0;
+ o = 0;
+ do {
+ o = o * 10 + (*cp++ - '0');
+ } while (isdigit(*cp));
+ net = o << 24;
+
+ /* Check for classless delegation mask width */
+ if (*cp == '/') {
+ ++cp;
+ o = 0;
+ do {
+ o = o * 10 + (*cp++ - '0');
+ } while (isdigit(*cp));
+ bits = o;
+ if (bits <= 0 || bits > 32)
+ return (0);
+ }
+
+ if (*cp == '.' && isdigit(cp[1])) {
+ ++cp;
+ o = 0;
+ do {
+ o = o * 10 + (*cp++ - '0');
+ } while (isdigit(*cp));
+ net = (net >> 8) | (o << 24);
+ mask = 0xffff0000;
+ if (*cp == '.' && isdigit(cp[1])) {
+ ++cp;
+ o = 0;
+ do {
+ o = o * 10 + (*cp++ - '0');
+ } while (isdigit(*cp));
+ net = (net >> 8) | (o << 24);
+ mask = 0xffffff00;
+ if (*cp == '.' && isdigit(cp[1])) {
+ ++cp;
+ o = 0;
+ do {
+ o = o * 10 + (*cp++ - '0');
+ } while (isdigit(*cp));
+ net = (net >> 8) | (o << 24);
+ mask = 0xffffffff;
+ }
+ }
+ }
+ if (strcasecmp(cp, inaddr) != 0)
+ return (0);
+
+ /* Classless delegation */
+ /* XXX check that calculated mask isn't smaller than octet mask? */
+ if (bits != 0)
+ for (mask = 0, i = 31; bits > 0; --i, --bits)
+ mask |= (1 << i);
+
+ *netp = net;
+ *maskp = mask;
+ return (1);
+}
+
+u_int32_t
+parseptr(register const char *cp, u_int32_t net, u_int32_t mask,
+ register char **errstrp)
+{
+ register u_int32_t o, addr;
+ register int shift;
+
+ addr = 0;
+ shift = 0;
+ while (isdigit(*cp) && shift < 32) {
+ o = 0;
+ do {
+ o = o * 10 + (*cp++ - '0');
+ } while (isdigit(*cp));
+ addr |= o << shift;
+ shift += 8;
+ if (*cp != '.') {
+ if (*cp == '\0')
+ break;
+ *errstrp = "missing dot";
+ return (0);
+ }
+ ++cp;
+ }
+
+ if (shift > 32) {
+ *errstrp = "more than 4 octets";
+ return (0);
+ }
+
+ if (shift == 32 && strcasecmp(cp, inaddr + 1) == 0)
+ return (addr);
+
+#ifdef notdef
+ if (*cp != '\0') {
+ *errstrp = "trailing junk";
+ return (0);
+ }
+#endif
+#ifdef notdef
+ if ((~mask & net) != 0) {
+ *errstrp = "too many octets for net";
+ return (0);
+ }
+#endif
+ return (net | addr);
+}
+
+int
+checkwks(register FILE *f, register char *proto, register int *smtpp,
+ register char **errstrp)
+{
+ register int n, sawparen;
+ register char *cp, *serv, **p;
+ static char errstr[132];
+ char buf[1024];
+ char psbuf[512];
+
+ if (!protoserv_init) {
+ initprotoserv();
+ ++protoserv_init;
+ }
+
+ /* Line count */
+ n = 0;
+
+ /* Terminate protocol */
+ cp = proto;
+ while (!isspace(*cp) && *cp != '\0')
+ ++cp;
+ if (*cp != '\0')
+ *cp++ = '\0';
+
+ /* Find services */
+ *smtpp = 0;
+ sawparen = 0;
+ if (*cp == '(') {
+ ++sawparen;
+ ++cp;
+ while (isspace(*cp))
+ ++cp;
+ }
+ for (;;) {
+ if (*cp == '\0') {
+ if (!sawparen)
+ break;
+ if (fgets(buf, sizeof(buf), f) == NULL) {
+ *errstrp = "mismatched parens";
+ return (n);
+ }
+ ++n;
+ cp = buf;
+ while (isspace(*cp))
+ ++cp;
+ }
+ /* Find end of service, converting to lowercase */
+ for (serv = cp; !isspace(*cp) && *cp != '\0'; ++cp)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+ if (*cp != '\0')
+ *cp++ = '\0';
+ if (sawparen && *cp == ')') {
+ /* XXX should check for trailing junk */
+ break;
+ }
+
+ (void)sprintf(psbuf, "%s/%s", serv, proto);
+
+ if (*serv == 's' && strcmp(psbuf, "tcp/smtp") == 0)
+ ++*smtpp;
+
+ for (p = protoserv; *p != NULL; ++p)
+ if (*psbuf == **p && strcmp(psbuf, *p) == 0) {
+ break;
+ }
+ if (*p == NULL) {
+ sprintf(errstr, "%s unknown", psbuf);
+ *errstrp = errstr;
+ break;
+ }
+ }
+
+ return (n);
+}
+
+int
+checkserv(register const char *serv, register char **p)
+{
+ for (; *p != NULL; ++p)
+ if (*serv == **p && strcmp(serv, *p) == 0)
+ return (1);
+ return (0);
+}
+
+void
+initprotoserv(void)
+{
+ register char *cp;
+ register struct servent *sp;
+ char psbuf[512];
+
+ protoserv_len = 256;
+ protoserv = (char **)malloc(protoserv_len * sizeof(*protoserv));
+ if (protoserv == NULL) {
+ fprintf(stderr, "%s: nslint: malloc: %s\n",
+ prog, strerror(errno));
+ exit(1);
+ }
+
+ while ((sp = getservent()) != NULL) {
+ (void)sprintf(psbuf, "%s/%s", sp->s_name, sp->s_proto);
+
+ /* Convert to lowercase */
+ for (cp = psbuf; *cp != '\0'; ++cp)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+
+ if (protoserv_last + 1 >= protoserv_len) {
+ protoserv_len <<= 1;
+ protoserv = realloc(protoserv,
+ protoserv_len * sizeof(*protoserv));
+ if (protoserv == NULL) {
+ fprintf(stderr, "%s: nslint: realloc: %s\n",
+ prog, strerror(errno));
+ exit(1);
+ }
+ }
+ protoserv[protoserv_last] = savestr(psbuf);
+ ++protoserv_last;
+ }
+ protoserv[protoserv_last] = NULL;
+}
+
+/*
+ * Returns true if name contains a dot but not a trailing dot.
+ * Special case: allow a single dot if the second part is not one
+ * of the 3 or 4 letter top level domains or is any 2 letter TLD
+ */
+int
+checkdots(register const char *name)
+{
+ register const char *cp, *cp2;
+
+ if ((cp = strchr(name, '.')) == NULL)
+ return (0);
+ cp2 = name + strlen(name) - 1;
+ if (cp2 >= name && *cp2 == '.')
+ return (0);
+
+ /* Return true of more than one dot*/
+ ++cp;
+ if (strchr(cp, '.') != NULL)
+ return (1);
+
+ if (strlen(cp) == 2 ||
+ strcasecmp(cp, "gov") == 0 ||
+ strcasecmp(cp, "edu") == 0 ||
+ strcasecmp(cp, "com") == 0 ||
+ strcasecmp(cp, "net") == 0 ||
+ strcasecmp(cp, "org") == 0 ||
+ strcasecmp(cp, "mil") == 0 ||
+ strcasecmp(cp, "int") == 0 ||
+ strcasecmp(cp, "nato") == 0 ||
+ strcasecmp(cp, "arpa") == 0)
+ return (1);
+ return (0);
+}
+
+int
+cmpaddr(register const void *ip1, register const void *ip2)
+{
+ register u_int32_t a1, a2;
+
+ a1 = (*(struct item **)ip1)->addr;
+ a2 = (*(struct item **)ip2)->addr;
+
+ if (a1 < a2)
+ return (-1);
+ else if (a1 > a2)
+ return (1);
+ else
+ return (0);
+}
+
+int
+cmphost(register const void *ip1, register const void *ip2)
+{
+ register const char *s1, *s2;
+
+ s1 = (*(struct item **)ip1)->host;
+ s2 = (*(struct item **)ip2)->host;
+
+ return (strcasecmp(s1, s2));
+}
+
+/* Returns a pointer after the next token or quoted string, else NULL */
+char *
+parsequoted(register char *cp)
+{
+
+ if (*cp == '"') {
+ ++cp;
+ while (*cp != '"' && *cp != '\0')
+ ++cp;
+ if (*cp != '"')
+ return (NULL);
+ ++cp;
+ } else {
+ while (!isspace(*cp) && *cp != '\0')
+ ++cp;
+ }
+ return (cp);
+}
+
+__dead void
+usage(void)
+{
+ extern char version[];
+
+ fprintf(stderr, "Version %s\n", version);
+ fprintf(stderr, "usage: %s [-d] [-b named.boot] [-B nslint.boot]\n",
+ prog);
+ fprintf(stderr, " %s [-d] [-c named.conf] [-C nslint.conf]\n",
+ prog);
+ exit(1);
+}
diff --git a/contrib/nslint-2.1a3/savestr.c b/contrib/nslint-2.1a3/savestr.c
new file mode 100644
index 0000000..49b1a3b
--- /dev/null
+++ b/contrib/nslint-2.1a3/savestr.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "@(#) $Header: /proj/cvs/prod/bind9/contrib/nslint-2.1a3/savestr.c,v 1.1 2001/12/21 04:12:04 marka Exp $ (LBL)";
+#endif
+
+#include <sys/types.h>
+
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "savestr.h"
+
+/* A replacement for strdup() that cuts down on malloc() overhead */
+char *
+savestr(register const char *str)
+{
+ register u_int size;
+ register char *p;
+ static char *strptr = NULL;
+ static u_int strsize = 0;
+
+ size = strlen(str) + 1;
+ if (size > strsize) {
+ strsize = 1024;
+ if (strsize < size)
+ strsize = size;
+ strptr = (char *)malloc(strsize);
+ if (strptr == NULL) {
+ fprintf(stderr, "savestr: malloc\n");
+ exit(1);
+ }
+ }
+ (void)strcpy(strptr, str);
+ p = strptr;
+ strptr += size;
+ strsize -= size;
+ return (p);
+}
diff --git a/contrib/nslint-2.1a3/savestr.h b/contrib/nslint-2.1a3/savestr.h
new file mode 100644
index 0000000..020f698
--- /dev/null
+++ b/contrib/nslint-2.1a3/savestr.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * @(#) $Header: /proj/cvs/prod/bind9/contrib/nslint-2.1a3/savestr.h,v 1.1 2001/12/21 04:12:05 marka Exp $ (LBL)
+ */
+
+extern char *savestr(const char *);
diff --git a/contrib/nslint-2.1a3/strerror.c b/contrib/nslint-2.1a3/strerror.c
new file mode 100644
index 0000000..d330a65
--- /dev/null
+++ b/contrib/nslint-2.1a3/strerror.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <string.h>
+
+#include "gnuc.h"
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+char *
+strerror(num)
+ int num;
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+#define UPREFIX "Unknown error: "
+ static char ebuf[40] = UPREFIX; /* 64-bit number + slop */
+ register unsigned int errnum;
+ register char *p, *t;
+ char tmp[40];
+
+ errnum = num; /* convert to unsigned */
+ if (errnum < sys_nerr)
+ return(sys_errlist[errnum]);
+
+ /* Do this by hand, so we don't include stdio(3). */
+ t = tmp;
+ do {
+ *t++ = "0123456789"[errnum % 10];
+ } while (errnum /= 10);
+ for (p = ebuf + sizeof(UPREFIX) - 1;;) {
+ *p++ = *--t;
+ if (t <= tmp)
+ break;
+ }
+ *p = '\0';
+ return(ebuf);
+}
diff --git a/contrib/pkcs11-keygen/PEM_write_pubkey.c b/contrib/pkcs11-keygen/PEM_write_pubkey.c
new file mode 100644
index 0000000..65def63
--- /dev/null
+++ b/contrib/pkcs11-keygen/PEM_write_pubkey.c
@@ -0,0 +1,124 @@
+/* OpenSSL tool
+ *
+ * usage: PEM_write_pubkey -e engine -p pin -k keyname -f filename
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <openssl/engine.h>
+#include <openssl/conf.h>
+#include <unistd.h>
+#include <errno.h>
+
+extern int PEM_write_PUBKEY(FILE *fp, EVP_PKEY *x);
+
+int
+main(int argc, char *argv[])
+{
+ ENGINE *e;
+ EVP_PKEY *pub_key;
+ FILE *fp;
+ char *engine = NULL;
+ char *pin = NULL;
+ char *keyname = NULL;
+ char *filename = NULL;
+ int c, errflg = 0;
+ extern char *optarg;
+ extern int optopt;
+
+ while ((c = getopt(argc, argv, ":e:p:k:f:")) != -1) {
+ switch (c) {
+ case 'e':
+ engine = optarg;
+ break;
+ case 'p':
+ pin = optarg;
+ break;
+ case 'k':
+ keyname = optarg;
+ break;
+ case 'f':
+ filename = optarg;
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n", optopt);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n", optopt);
+ errflg++;
+ }
+ }
+ if ((errflg) || (!engine) || (!filename) || (!keyname)) {
+ fprintf(stderr,
+ "usage: PEM_write_pubkey -e engine [-p pin] "
+ "-k keyname -f filename\n");
+ exit(1);
+ }
+
+ /* Load the config file */
+ OPENSSL_config(NULL);
+
+ /* Register engine */
+ e = ENGINE_by_id(engine);
+ if (!e) {
+ /* the engine isn't available */
+ printf("The engine isn't available\n");
+ ERR_print_errors_fp(stderr);
+ exit(1);
+ }
+
+ /* Send PIN to engine */
+ if (pin && !ENGINE_ctrl_cmd_string(e, "PIN", pin, 0)){
+ printf("Error sending PIN to engine\n");
+ ERR_print_errors_fp(stderr);
+ ENGINE_free(e);
+ exit(1);
+ }
+
+ if (!ENGINE_init(e)) {
+ /* the engine couldn't initialise, release 'e' */
+ printf("The engine couldn't initialise\n");
+ ERR_print_errors_fp(stderr);
+ ENGINE_free(e);
+ exit(1);
+ }
+
+ if (!ENGINE_register_RSA(e)){
+ /* This should only happen when 'e' can't initialise, but the previous
+ * statement suggests it did. */
+ printf("This should not happen\n");
+ ERR_print_errors_fp(stderr);
+ exit(1);
+ }
+
+ /* Load public key */
+ pub_key = ENGINE_load_public_key(e, keyname, NULL, NULL);
+ if (pub_key == NULL) {
+ /* No public key */
+ printf("Error loading public key\n");
+ ERR_print_errors_fp(stderr);
+ ENGINE_free(e);
+ exit(1);
+ }
+
+ /* write public key to file in PEM format */
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ printf("Error opening output file.\n");
+ ENGINE_free(e);
+ exit(1);
+ }
+
+ if (!PEM_write_PUBKEY(fp, pub_key)) {
+ /* Error writing public key */
+ printf("Error writing public key");
+ ERR_print_errors_fp(stderr);
+ ENGINE_free(e);
+ exit(1);
+ }
+
+ fclose(fp);
+ exit(0);
+}
diff --git a/contrib/pkcs11-keygen/README b/contrib/pkcs11-keygen/README
new file mode 100644
index 0000000..4104e17
--- /dev/null
+++ b/contrib/pkcs11-keygen/README
@@ -0,0 +1,18 @@
+This is a set of utilities that when used together create rsa keys in
+a PKCS11 keystore. The keys will have a label of "zone,zsk|ksk,xxx" and
+an id of the keytag in hex.
+
+Run genkey.sh to generate a new key and call the other programs in turn.
+Run writekey.sh to load key to the key store from Kxxx.{key,private}.
+
+genkey[.c] uses PKCS11 calls to generate keys.
+PEM_write_pubkey[.c] uses OpenSSL to write a public key from the key store
+ into a file in PEM format.
+keyconv.pl uses Net::DNS::SEC to calculate the key tag and to write out
+ a DNSKEY RR into a file.
+set_key_id[.c] uses PKCS11 to set to the key id == keytag in the key store.
+readkey[.c] and writekey[.c] extracts and loads a key from/to the key store.
+keydump.pl uses Net::DNS::SEC to get the key from a Kxxx.private file and
+ write it into a file in PEM format.
+
+listobjs and destroyobjs browse the key store, prints or destroys objects.
diff --git a/contrib/pkcs11-keygen/destroyobj.c b/contrib/pkcs11-keygen/destroyobj.c
new file mode 100644
index 0000000..9c714d8
--- /dev/null
+++ b/contrib/pkcs11-keygen/destroyobj.c
@@ -0,0 +1,183 @@
+/* destroyobj [-s $slot] [-i $id | -l $label] [-p $pin] */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef OPENCRYPTOKI
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
+#else
+#include <opencryptoki/pkcs11.h>
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_UTF8CHAR *pin = NULL;
+ CK_BYTE attr_id[2];
+ CK_OBJECT_HANDLE akey[50];
+ char *label = NULL;
+ int error = 0;
+ int id = 0, i = 0;
+ int c, errflg = 0;
+ CK_ULONG ulObjectCount;
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_ID, &attr_id, sizeof(attr_id)}
+ };
+ extern char *optarg;
+ extern int optopt;
+
+ while ((c = getopt(argc, argv, ":s:i:l:p:")) != -1) {
+ switch (c) {
+ case 's':
+ slot = atoi(optarg);
+ break;
+ case 'i':
+ id = atoi(optarg);
+ id &= 0xffff;
+ break;
+ case 'l':
+ label = optarg;
+ break;
+ case 'p':
+ pin = (CK_UTF8CHAR *)optarg;
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n", optopt);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n", optopt);
+ errflg++;
+ }
+ }
+ if (errflg || ((!id) && (!label))) {
+ fprintf(stderr,
+ "usage: destroykey [-s slot] [-i id | -l label] [-p pin]\n");
+ exit(1);
+ }
+ if (id) {
+ printf("id %i\n", id);
+ attr_id[0] = (id >> 8) & 0xff;
+ attr_id[1] = id & 0xff;
+ } else if (label) {
+ printf("label %s\n", label);
+ search_template[0].type = CKA_LABEL;
+ search_template[0].pValue = label;
+ search_template[0].ulValueLen = strlen(label);
+ }
+
+ /* Initialize the CRYPTOKI library */
+ rv = C_Initialize(NULL_PTR);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_Initialize: Error = 0x%.8X\n", rv);
+ exit(1);
+ }
+
+ /* Open a session on the slot found */
+ rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_OpenSession: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_program;
+ }
+
+ /* Login to the Token (Keystore) */
+ if (!pin)
+#ifndef OPENCRYPTOKI
+ pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
+#else
+ pin = (CK_UTF8CHAR *)getpass("Enter Pin: ");
+#endif
+ rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin));
+ memset(pin, 0, strlen((char *)pin));
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_Login: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ rv = C_FindObjectsInit(hSession, search_template,
+ ((id != 0) || (label != NULL)) ? 1 : 0);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ rv = C_FindObjects(hSession, akey, 50, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+
+ for (i = 0; i < ulObjectCount; i++) {
+ CK_OBJECT_CLASS oclass = 0;
+ CK_BYTE labelbuf[64 + 1];
+ CK_BYTE idbuf[64];
+ CK_ATTRIBUTE attr_template[] = {
+ {CKA_CLASS, &oclass, sizeof(oclass)},
+ {CKA_LABEL, labelbuf, sizeof(labelbuf) - 1},
+ {CKA_ID, idbuf, sizeof(idbuf)}
+ };
+ int j, len;
+
+ memset(labelbuf, 0, sizeof(labelbuf));
+ memset(idbuf, 0, sizeof(idbuf));
+
+ rv = C_GetAttributeValue(hSession, akey[i], attr_template, 3);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GetAttributeValue[%d]: rv = 0x%.8X\n", i, rv);
+ error = 1;
+ goto exit_search;
+ }
+ len = attr_template[2].ulValueLen;
+ printf("object[%d]: class %d label '%s' id[%u] ",
+ i, oclass, labelbuf, attr_template[2].ulValueLen);
+ if (len > 4)
+ len = 4;
+ for (j = 0; j < len; j++)
+ printf("%02x", idbuf[j]);
+ if (attr_template[2].ulValueLen > len)
+ printf("...\n");
+ else
+ printf("\n");
+ }
+
+ /* give a chance to kill this */
+ printf("sleeping 5 seconds...\n");
+ sleep(5);
+
+ for (i = 0; i < ulObjectCount; i++) {
+ rv = C_DestroyObject(hSession, akey[i]);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_DestroyObject[%d]: rv = 0x%.8X\n", i, rv);
+ error = 1;
+ }
+ }
+
+ exit_search:
+ rv = C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8X\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ (void) C_CloseSession(hSession);
+
+ exit_program:
+ (void) C_Finalize(NULL_PTR);
+
+ exit(error);
+}
diff --git a/contrib/pkcs11-keygen/genkey.c b/contrib/pkcs11-keygen/genkey.c
new file mode 100644
index 0000000..fc70391
--- /dev/null
+++ b/contrib/pkcs11-keygen/genkey.c
@@ -0,0 +1,206 @@
+/* genkey - pkcs11 rsa key generator
+ *
+ * create RSASHA1 key in the keystore of an SCA6000
+ * The calculation of key tag is left to the script
+ * that converts the key into a DNSKEY RR and inserts
+ * it into a zone file.
+ *
+ * usage:
+ * genkey [-P] [-s slot] -b keysize -l label [-p pin]
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef OPENCRYPTOKI
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
+#else
+#include <opencryptoki/pkcs11.h>
+#endif
+
+/* Define static key template values */
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[])
+{
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_MECHANISM genmech;
+ CK_SESSION_HANDLE hSession;
+ CK_UTF8CHAR *pin = NULL;
+ CK_ULONG modulusbits = 0;
+ CK_CHAR *label = NULL;
+ CK_OBJECT_HANDLE privatekey, publickey;
+ CK_BYTE public_exponent[3];
+ int error = 0;
+ int i = 0;
+ int c, errflg = 0;
+ int hide = 1;
+ CK_ULONG ulObjectCount;
+ /* Set search template */
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_LABEL, NULL_PTR, 0}
+ };
+ CK_ATTRIBUTE publickey_template[] = {
+ {CKA_LABEL, NULL_PTR, 0},
+ {CKA_VERIFY, &truevalue, sizeof (truevalue)},
+ {CKA_TOKEN, &truevalue, sizeof (truevalue)},
+ {CKA_MODULUS_BITS, &modulusbits, sizeof (modulusbits)},
+ {CKA_PUBLIC_EXPONENT, &public_exponent, sizeof (public_exponent)}
+ };
+ CK_ATTRIBUTE privatekey_template[] = {
+ {CKA_LABEL, NULL_PTR, 0},
+ {CKA_SIGN, &truevalue, sizeof (truevalue)},
+ {CKA_TOKEN, &truevalue, sizeof (truevalue)},
+ {CKA_PRIVATE, &truevalue, sizeof (truevalue)},
+ {CKA_SENSITIVE, &truevalue, sizeof (truevalue)},
+ {CKA_EXTRACTABLE, &falsevalue, sizeof (falsevalue)}
+ };
+ extern char *optarg;
+ extern int optopt;
+
+ while ((c = getopt(argc, argv, ":Ps:b:i:l:p:")) != -1) {
+ switch (c) {
+ case 'P':
+ hide = 0;
+ break;
+ case 's':
+ slot = atoi(optarg);
+ break;
+ case 'b':
+ modulusbits = atoi(optarg);
+ break;
+ case 'l':
+ label = (CK_CHAR *)optarg;
+ break;
+ case 'p':
+ pin = (CK_UTF8CHAR *)optarg;
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n", optopt);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n", optopt);
+ errflg++;
+ }
+ }
+ if ((errflg) || (!modulusbits) || (!label)) {
+ fprintf(stderr,
+ "usage: genkey [-P] [-s slot] -b keysize -l label [-p pin]\n");
+ exit(2);
+ }
+
+ search_template[0].pValue = label;
+ search_template[0].ulValueLen = strlen((char *)label);
+ publickey_template[0].pValue = label;
+ publickey_template[0].ulValueLen = strlen((char *)label);
+ privatekey_template[0].pValue = label;
+ privatekey_template[0].ulValueLen = strlen((char *)label);
+
+ /* Set public exponent to 65537 */
+ public_exponent[0] = 0x01;
+ public_exponent[1] = 0x00;
+ public_exponent[2] = 0x01;
+
+ /* Set up mechanism for generating key pair */
+ genmech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
+ genmech.pParameter = NULL_PTR;
+ genmech.ulParameterLen = 0;
+
+ /* Initialize the CRYPTOKI library */
+ rv = C_Initialize(NULL_PTR);
+
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_Initialize: Error = 0x%.8X\n", rv);
+ exit(1);
+ }
+
+ /* Open a session on the slot found */
+ rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_OpenSession: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_program;
+ }
+
+ /* Login to the Token (Keystore) */
+ if (!pin)
+#ifndef OPENCRYPTOKI
+ pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
+#else
+ pin = (CK_UTF8CHAR *)getpass("Enter Pin: ");
+#endif
+ rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin));
+ memset(pin, 0, strlen((char *)pin));
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_Login: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ /* check if a key with the same id already exists */
+ rv = C_FindObjectsInit(hSession, search_template, 1);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+ rv = C_FindObjects(hSession, &privatekey, 1, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+ if (ulObjectCount != 0) {
+ fprintf(stderr, "Key already exists.\n");
+ error = 1;
+ goto exit_search;
+ }
+
+ /* Set attributes if the key is not to be hidden */
+ if (!hide) {
+ privatekey_template[4].pValue = &falsevalue;
+ privatekey_template[5].pValue = &truevalue;
+ }
+
+ /* Generate Key pair for signing/verifying */
+ rv = C_GenerateKeyPair(hSession, &genmech, publickey_template,
+ (sizeof (publickey_template) /
+ sizeof (CK_ATTRIBUTE)),
+ privatekey_template,
+ (sizeof (privatekey_template) /
+ sizeof (CK_ATTRIBUTE)),
+ &publickey, &privatekey);
+
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GenerateKeyPair: Error = 0x%.8X\n", rv);
+ error = 1;
+ }
+
+ exit_search:
+ rv = C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8X\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ (void) C_CloseSession(hSession);
+
+ exit_program:
+ (void) C_Finalize(NULL_PTR);
+
+ exit(error);
+}
diff --git a/contrib/pkcs11-keygen/genkey.sh b/contrib/pkcs11-keygen/genkey.sh
new file mode 100755
index 0000000..f5bf146
--- /dev/null
+++ b/contrib/pkcs11-keygen/genkey.sh
@@ -0,0 +1,55 @@
+#!/usr/bin/bash
+
+usage="Usage: $0 -z zone -x ext -p pin -b bits -e engine [-f] -k key_path"
+tmp_file=/tmp/cur_key.$$
+while getopts ":z:x:p:t:k:b:e:f" opt; do
+ case $opt in
+ z ) zone=$OPTARG ;;
+ x ) ext=$OPTARG ;;
+ p ) pin=$OPTARG ;;
+ t ) id=$OPTARG ;;
+ f ) flag="ksk" ;;
+ e ) engine=$OPTARG ;;
+ b ) bits=$OPTARG ;;
+ k ) key_path=$OPTARG ;;
+ \? ) echo $usage
+ exit 1 ;;
+ esac
+done
+shift $(($OPTIND -1))
+
+if [ ! "$zone" -o ! "$ext" -o ! "$pin" -o ! "$engine" -o ! "$bits" -o ! "$key_path" ] ; then
+ echo $usage
+ exit 1
+fi
+
+if [ "$flag" ] ; then
+ label="$zone,$flag,$ext"
+else
+ label="$zone,zsk,$ext"
+fi
+
+# for testing
+mypath=.
+
+echo "Generating key"
+$mypath/genkey -b $bits -l $label -p $pin
+if [ $? -ne 0 ] ; then exit 1 ; fi
+
+echo "Exporting public key"
+$mypath/PEM_write_pubkey -e $engine -p $pin -k pkcs11:$label -f $tmp_file
+if [ $? -ne 0 ] ; then exit 1 ; fi
+
+echo "Generating DNSKEY RR"
+if [ "$flag" ] ; then
+ keytag=`$mypath/keyconv.pl -a 5 -k -e $engine -l $label -p $key_path -i $tmp_file $zone`
+else
+ keytag=`$mypath/keyconv.pl -a 5 -e $engine -l $label -p $key_path -i $tmp_file $zone`
+fi
+
+if [ ! $keytag ] ; then rm $tmp_file; exit 1 ; fi
+
+echo "Set key id"
+$mypath/set_key_id -l $label -n $keytag -p $pin
+
+rm $tmp_file
diff --git a/contrib/pkcs11-keygen/keyconv.pl b/contrib/pkcs11-keygen/keyconv.pl
new file mode 100755
index 0000000..c68124c
--- /dev/null
+++ b/contrib/pkcs11-keygen/keyconv.pl
@@ -0,0 +1,61 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Crypt::OpenSSL::RSA;
+use Getopt::Std;
+use MIME::Base64;
+use Net::DNS;
+use Net::DNS::SEC;
+
+my %option;
+getopts('a:e:i:l:p:hk',\%option);
+
+die "usage: keyconv.pl [-a alg] [-k (to indicate KSK)] -e engine -l label [-p (path to store key)] -i filename domainname\n" if $option{h} || (not defined $option{i}) || (not defined $option{e}) || (not defined $option{l});
+
+# The default path is local.
+$option{p} || ($option{p}="./");
+
+# The default algorithm is 5.
+$option{a} || ($option{a}=5);
+
+$option{k} || ($option{k}=0);
+
+# The algorithm is either 5 or 133.
+$option{a}==5 || $option{a}==133 || die "algorithm must be 5 or 133\n";
+
+# standard flags (value is 256) plus optionally the KSK flag.
+my $flags=(256 + $option{k});
+
+open(PFILE, $option{i});
+ my @fc = <PFILE>;
+close(PFILE);
+
+my $rsa = Crypt::OpenSSL::RSA->new_public_key(join "", @fc);
+
+my ($m,$e)= $rsa->get_key_parameters;
+
+(my $l=pack("Cn",0,length($e->to_bin))) =~ s/^\000{2}//;
+
+my $rrkey=$l.$e->to_bin.$m->to_bin;
+my $keystr = $ARGV[0]. ". IN DNSKEY $flags 3 $option{a} ".encode_base64($rrkey,"");
+my $keyrr = Net::DNS::RR->new($keystr);
+
+open(PFILE, "> $option{p}/K".$ARGV[0].".+".sprintf("%03d",$option{a})."+".$keyrr->keytag.".key");
+print PFILE $ARGV[0], ". IN DNSKEY $flags 3 $option{a} ",encode_base64($rrkey,"")."\n";
+close(PFILE);
+
+open(PFILE, "> $option{p}/K".$ARGV[0].".+".sprintf("%03d",$option{a})."+".$keyrr->keytag.".private");
+print PFILE "Private-key-format: v1.2\n";
+print PFILE "Algorithm: ", $option{a}, " (RSASHA1)\n";
+print PFILE "Modulus: ".encode_base64($m->to_bin,"")."\n";
+print PFILE "PublicExponent: ".encode_base64($e->to_bin,"")."\n";
+my $engine="";
+$engine=encode_base64($option{e}."\0","");
+print PFILE "Engine: ", $engine, "\n";
+my $label="";
+$option{k}==0 && ($label=encode_base64($option{e}.":".$option{l}."\0",""));
+$option{k}!=0 && ($label=encode_base64($option{e}.":".$option{l}."\0",""));
+print PFILE "Label: ", $label, "\n";
+close(PFILE);
+
+print $keyrr->keytag;
diff --git a/contrib/pkcs11-keygen/keydump.pl b/contrib/pkcs11-keygen/keydump.pl
new file mode 100755
index 0000000..acbb00c
--- /dev/null
+++ b/contrib/pkcs11-keygen/keydump.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl -w
+
+use strict;
+use Getopt::Std;
+use Crypt::OpenSSL::RSA;
+use Net::DNS::SEC;
+
+my %option;
+getopts('k:p:o:h',\%option);
+
+$option{h} || (not defined $option{k}) || (not defined $option{p}) || (not defined $option{o}) && die "usage: keydump.pl -k Kxxx.key -p Kxxx.priv -o pem\n";
+
+my $rsa = Net::DNS::SEC::Private->new($option{p});
+
+open(PFILE, "> $option{o}");
+print PFILE $rsa->dump_rsa_private_der;
+close(PFILE);
+
+open(KFILE, "< $option{k}");
+my @fc = <KFILE>;
+close(KFILE);
+
+my $keyrr = Net::DNS::RR->new(join "", @fc);
+
+print $keyrr->flags;
+
diff --git a/contrib/pkcs11-keygen/listobjs.c b/contrib/pkcs11-keygen/listobjs.c
new file mode 100644
index 0000000..68e22ec
--- /dev/null
+++ b/contrib/pkcs11-keygen/listobjs.c
@@ -0,0 +1,197 @@
+/* listobjs [-P] [-s slot] [-i $id | -l $label] [-p $pin] */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef OPENCRYPTOKI
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
+#else
+#include <opencryptoki/pkcs11.h>
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_UTF8CHAR *pin = NULL;
+ CK_BYTE attr_id[2];
+ CK_OBJECT_HANDLE akey[50];
+ char *label = NULL;
+ int error = 0, public = 0, all = 0;
+ int i = 0, id = 0;
+ int c, errflg = 0;
+ CK_ULONG ulObjectCount;
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_ID, &attr_id, sizeof(attr_id)}
+ };
+ extern char *optarg;
+ extern int optopt;
+
+ while ((c = getopt(argc, argv, ":s:i:l:p:P")) != -1) {
+ switch (c) {
+ case 'P':
+ public = 1;
+ break;
+ case 's':
+ slot = atoi(optarg);
+ break;
+ case 'i':
+ id = atoi(optarg);
+ id &= 0xffff;
+ break;
+ case 'l':
+ label = optarg;
+ break;
+ case 'p':
+ pin = (CK_UTF8CHAR *)optarg;
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n", optopt);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n", optopt);
+ errflg++;
+ }
+ }
+ if (errflg) {
+ fprintf(stderr,
+ "usage: listobjs [-P] [-s slot] [-p pin] -i id | $label\n");
+ exit(1);
+ }
+ if ((!id) && (!label))
+ all = 1;
+ if (slot)
+ printf("slot %d\n", slot);
+ if (id) {
+ printf("id %i\n", id);
+ attr_id[0] = (id >> 8) & 0xff;
+ attr_id[1] = id & 0xff;
+ } else if (label) {
+ printf("label %s\n", label);
+ search_template[0].type = CKA_LABEL;
+ search_template[0].pValue = label;
+ search_template[0].ulValueLen = strlen(label);
+ }
+
+ /* Initialize the CRYPTOKI library */
+ rv = C_Initialize(NULL_PTR);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_Initialize: Error = 0x%.8X\n", rv);
+ exit(1);
+ }
+
+ /* Open a session on the slot found */
+ rv = C_OpenSession(slot, CKF_SERIAL_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_OpenSession: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_program;
+ }
+
+ /* Login to the Token (Keystore) */
+ if (!public) {
+ if (!pin)
+#ifndef OPENCRYPTOKI
+ pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
+#else
+ pin = (CK_UTF8CHAR *)getpass("Enter Pin: ");
+#endif
+ rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin));
+ memset(pin, 0, strlen((char *)pin));
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_Login: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+ }
+
+ rv = C_FindObjectsInit(hSession, search_template, all ? 0 : 1);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ ulObjectCount = 1;
+ while (ulObjectCount) {
+ rv = C_FindObjects(hSession, akey, 50, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+
+ for (i = 0; i < ulObjectCount; i++) {
+ CK_OBJECT_CLASS oclass = 0;
+ CK_BYTE labelbuf[64 + 1];
+ CK_BYTE idbuf[64];
+ CK_ATTRIBUTE attr_template[] = {
+ {CKA_CLASS, &oclass, sizeof(oclass)},
+ {CKA_LABEL, labelbuf, sizeof(labelbuf) - 1},
+ {CKA_ID, idbuf, sizeof(idbuf)}
+ };
+ int j, len;
+
+ memset(labelbuf, 0, sizeof(labelbuf));
+ memset(idbuf, 0, sizeof(idbuf));
+
+ rv = C_GetAttributeValue(hSession, akey[i], attr_template, 3);
+ if (rv != CKR_OK) {
+ fprintf(stderr,
+ "C_GetAttributeValue[%d]: rv = 0x%.8X\n", i, rv);
+ if (rv = CKR_BUFFER_TOO_SMALL)
+ fprintf(stderr, "%d too small: %u %u %u\n", i,
+ attr_template[0].ulValueLen,
+ attr_template[1].ulValueLen,
+ attr_template[2].ulValueLen);
+ error = 1;
+ continue;
+ }
+
+ len = attr_template[2].ulValueLen;
+ printf("object[%d]: handle %u class %d label[%u] '%s' id[%u] ",
+ i, akey[i], oclass,
+ attr_template[1].ulValueLen, labelbuf,
+ attr_template[2].ulValueLen);
+ if (len == 2) {
+ id = (idbuf[0] << 8) & 0xff00;
+ id |= idbuf[1] & 0xff;
+ printf("%i\n", id);
+ } else {
+ if (len > 8)
+ len = 8;
+ for (j = 0; j < len; j++)
+ printf("%02x", idbuf[j]);
+ if (attr_template[2].ulValueLen > len)
+ printf("...\n");
+ else
+ printf("\n");
+ }
+ }
+ }
+
+ exit_search:
+ rv = C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8X\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ (void) C_CloseSession(hSession);
+
+ exit_program:
+ (void) C_Finalize(NULL_PTR);
+
+ exit(error);
+}
diff --git a/contrib/pkcs11-keygen/openssl-0.9.8g-patch b/contrib/pkcs11-keygen/openssl-0.9.8g-patch
new file mode 100644
index 0000000..6d93c68
--- /dev/null
+++ b/contrib/pkcs11-keygen/openssl-0.9.8g-patch
@@ -0,0 +1,8715 @@
+diff -r -u -N openssl-0.9.8g/Configure openssl/Configure
+--- openssl-0.9.8g/Configure 2007-09-16 14:24:17.000000000 +0200
++++ openssl/Configure 2007-10-25 01:27:08.000000000 +0200
+@@ -10,7 +10,7 @@
+
+ # see INSTALL for instructions.
+
+-my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
++my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n";
+
+ # Options:
+ #
+@@ -19,6 +19,9 @@
+ # --prefix prefix for the OpenSSL include, lib and bin directories
+ # (Default: the OPENSSLDIR directory)
+ #
++# --pk11_libname PKCS#11 library name.
++# (Default: none)
++#
+ # --install_prefix Additional prefix for package builders (empty by
+ # default). This needn't be set in advance, you can
+ # just as well use "make INSTALL_PREFIX=/whatever install".
+@@ -560,6 +563,8 @@
+ my $idx_ranlib = $idx++;
+ my $idx_arflags = $idx++;
+
++my $pk11_libname="";
++
+ my $prefix="";
+ my $openssldir="";
+ my $exe_ext="";
+@@ -738,6 +743,10 @@
+ {
+ $flags.=$_." ";
+ }
++ elsif (/^--pk11-libname=(.*)$/)
++ {
++ $pk11_libname=$1;
++ }
+ elsif (/^--prefix=(.*)$/)
+ {
+ $prefix=$1;
+@@ -861,6 +870,13 @@
+ exit 0;
+ }
+
++if (! $pk11_libname)
++ {
++ print STDERR "You must set --pk11-libname for PKCS#11 library.\n";
++ print STDERR "See README.pkcs11 for more information.\n";
++ exit 1;
++ }
++
+ if ($target =~ m/^CygWin32(-.*)$/) {
+ $target = "Cygwin".$1;
+ }
+@@ -986,6 +1002,8 @@
+ if ($flags ne "") { $cflags="$flags$cflags"; }
+ else { $no_user_cflags=1; }
+
++$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags";
++
+ # Kerberos settings. The flavor must be provided from outside, either through
+ # the script "config" or manually.
+ if (!$no_krb5)
+@@ -1319,6 +1337,7 @@
+ s/^VERSION=.*/VERSION=$version/;
+ s/^MAJOR=.*/MAJOR=$major/;
+ s/^MINOR=.*/MINOR=$minor/;
++ s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/;
+ s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/;
+ s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/;
+ s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/;
+diff -r -u -N openssl-0.9.8g/crypto/engine/cryptoki.h openssl/crypto/engine/cryptoki.h
+--- openssl-0.9.8g/crypto/engine/cryptoki.h 1970-01-01 01:00:00.000000000 +0100
++++ openssl/crypto/engine/cryptoki.h 2007-10-25 01:27:09.000000000 +0200
+@@ -0,0 +1,103 @@
++/*
++ * CDDL HEADER START
++ *
++ * The contents of this file are subject to the terms of the
++ * Common Development and Distribution License, Version 1.0 only
++ * (the "License"). You may not use this file except in compliance
++ * with the License.
++ *
++ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
++ * or http://www.opensolaris.org/os/licensing.
++ * See the License for the specific language governing permissions
++ * and limitations under the License.
++ *
++ * When distributing Covered Code, include this CDDL HEADER in each
++ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
++ * If applicable, add the following below this CDDL HEADER, with the
++ * fields enclosed by brackets "[]" replaced with your own identifying
++ * information: Portions Copyright [yyyy] [name of copyright owner]
++ *
++ * CDDL HEADER END
++ */
++/*
++ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#ifndef _CRYPTOKI_H
++#define _CRYPTOKI_H
++
++#pragma ident "@(#)cryptoki.h 1.2 05/06/08 SMI"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef CK_PTR
++#define CK_PTR *
++#endif
++
++#ifndef CK_DEFINE_FUNCTION
++#define CK_DEFINE_FUNCTION(returnType, name) returnType name
++#endif
++
++#ifndef CK_DECLARE_FUNCTION
++#define CK_DECLARE_FUNCTION(returnType, name) returnType name
++#endif
++
++#ifndef CK_DECLARE_FUNCTION_POINTER
++#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
++#endif
++
++#ifndef CK_CALLBACK_FUNCTION
++#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
++#endif
++
++#ifndef NULL_PTR
++#include <unistd.h> /* For NULL */
++#define NULL_PTR NULL
++#endif
++
++/*
++ * pkcs11t.h defines TRUE and FALSE in a way that upsets lint
++ */
++#ifndef CK_DISABLE_TRUE_FALSE
++#define CK_DISABLE_TRUE_FALSE
++#ifndef TRUE
++#define TRUE 1
++#endif /* TRUE */
++#ifndef FALSE
++#define FALSE 0
++#endif /* FALSE */
++#endif /* CK_DISABLE_TRUE_FALSE */
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++#include "pkcs11.h"
++
++/* Solaris specific functions */
++
++#include <stdlib.h>
++
++/*
++ * SUNW_C_GetMechSession will initialize the framework and do all
++ * the necessary PKCS#11 calls to create a session capable of
++ * providing operations on the requested mechanism
++ */
++CK_RV SUNW_C_GetMechSession(CK_MECHANISM_TYPE mech,
++ CK_SESSION_HANDLE_PTR hSession);
++
++/*
++ * SUNW_C_KeyToObject will create a secret key object for the given
++ * mechanism from the rawkey data.
++ */
++CK_RV SUNW_C_KeyToObject(CK_SESSION_HANDLE hSession,
++ CK_MECHANISM_TYPE mech, const void *rawkey, size_t rawkey_len,
++ CK_OBJECT_HANDLE_PTR obj);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _CRYPTOKI_H */
+diff -r -u -N openssl-0.9.8g/crypto/engine/eng_all.c openssl/crypto/engine/eng_all.c
+--- openssl-0.9.8g/crypto/engine/eng_all.c 2007-01-04 23:55:25.000000000 +0100
++++ openssl/crypto/engine/eng_all.c 2007-10-25 01:27:09.000000000 +0200
+@@ -107,6 +107,9 @@
+ #if defined(__OpenBSD__) || defined(__FreeBSD__)
+ ENGINE_load_cryptodev();
+ #endif
++#ifndef OPENSSL_NO_HW_PKCS11
++ ENGINE_load_pk11();
++#endif
+ #endif
+ }
+
+diff -r -u -N openssl-0.9.8g/crypto/engine/engine.h openssl/crypto/engine/engine.h
+--- openssl-0.9.8g/crypto/engine/engine.h 2005-11-06 18:48:59.000000000 +0100
++++ openssl/crypto/engine/engine.h 2007-10-25 01:27:09.000000000 +0200
+@@ -332,6 +332,7 @@
+ void ENGINE_load_ubsec(void);
+ #endif
+ void ENGINE_load_cryptodev(void);
++void ENGINE_load_pk11(void);
+ void ENGINE_load_padlock(void);
+ void ENGINE_load_builtin_engines(void);
+
+diff -r -u -N openssl-0.9.8g/crypto/engine/hw_pk11.c openssl/crypto/engine/hw_pk11.c
+--- openssl-0.9.8g/crypto/engine/hw_pk11.c 1970-01-01 01:00:00.000000000 +0100
++++ openssl/crypto/engine/hw_pk11.c 2007-10-29 23:31:11.000000000 +0100
+@@ -0,0 +1,2153 @@
++/*
++ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++
++#pragma ident "@(#)hw_pk11.c 1.12 07/07/05 SMI"
++
++/* crypto/engine/hw_pk11.c */
++/* This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/* ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <assert.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++#include <unistd.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/md5.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++#include <cryptlib.h>
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++
++#undef DEBUG_SLOT_SELECTION
++
++#include "cryptoki.h"
++#include "pkcs11.h"
++#include "hw_pk11_err.c"
++
++
++/* The head of the free PK11 session list */
++static struct PK11_SESSION_st *free_session = NULL;
++
++/* Create all secret key objects in a global session so that they are available
++ * to use for other sessions. These other sessions may be opened or closed
++ * without losing the secret key objects */
++static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE;
++
++/* ENGINE level stuff */
++static int pk11_init(ENGINE *e);
++static int pk11_library_init(ENGINE *e);
++static int pk11_finish(ENGINE *e);
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
++static int pk11_destroy(ENGINE *e);
++
++/* RAND stuff */
++static void pk11_rand_seed(const void *buf, int num);
++static void pk11_rand_add(const void *buf, int num, double add_entropy);
++static void pk11_rand_cleanup(void);
++static int pk11_rand_bytes(unsigned char *buf, int num);
++static int pk11_rand_status(void);
++
++/* These functions are also used in other files */
++PK11_SESSION *pk11_get_session();
++void pk11_return_session(PK11_SESSION *sp);
++int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_dsa_key_objects(PK11_SESSION *session);
++int pk11_destroy_dh_key_objects(PK11_SESSION *session);
++
++/* Local helper functions */
++static int pk11_free_all_sessions();
++static int pk11_setup_session(PK11_SESSION *sp);
++static int pk11_destroy_cipher_key_objects(PK11_SESSION *session);
++static int pk11_destroy_object(CK_SESSION_HANDLE session,
++ CK_OBJECT_HANDLE oh);
++static const char *get_PK11_LIBNAME(void);
++static void free_PK11_LIBNAME(void);
++static long set_PK11_LIBNAME(const char *name);
++
++/* Symmetric cipher and digest support functions */
++static int cipher_nid_to_pk11(int nid);
++static int pk11_usable_ciphers(const int **nids);
++static int pk11_usable_digests(const int **nids);
++static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
++ const unsigned char *iv, int enc);
++static int pk11_cipher_final(PK11_SESSION *sp);
++static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, unsigned int inl);
++static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx);
++static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
++ const int **nids, int nid);
++static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest,
++ const int **nids, int nid);
++static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx,
++ const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp);
++static void check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key);
++static int md_nid_to_pk11(int nid);
++static int pk11_digest_init(EVP_MD_CTX *ctx);
++static int pk11_digest_update(EVP_MD_CTX *ctx,const void *data,
++ size_t count);
++static int pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md);
++static int pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from);
++static int pk11_digest_cleanup(EVP_MD_CTX *ctx);
++
++static int pk11_choose_slot();
++static int pk11_count_symmetric_cipher(int slot_id, CK_MECHANISM_TYPE mech,
++ int *current_slot_n_cipher, int *local_cipher_nids, int id);
++static int pk11_count_digest(int slot_id, CK_MECHANISM_TYPE mech,
++ int *current_slot_n_digest, int *local_digest_nids, int id);
++
++/* Index for the supported ciphers */
++#define PK11_DES_CBC 0
++#define PK11_DES3_CBC 1
++#define PK11_AES_CBC 2
++#define PK11_RC4 3
++
++/* Index for the supported digests */
++#define PK11_MD5 0
++#define PK11_SHA1 1
++
++#define PK11_CIPHER_MAX 4 /* Max num of ciphers supported */
++#define PK11_DIGEST_MAX 2 /* Max num of digests supported */
++
++#define PK11_KEY_LEN_MAX 24
++
++static int cipher_nids[PK11_CIPHER_MAX];
++static int digest_nids[PK11_DIGEST_MAX];
++static int cipher_count = 0;
++static int digest_count = 0;
++static CK_BBOOL pk11_have_rsa = CK_FALSE;
++static CK_BBOOL pk11_have_dsa = CK_FALSE;
++static CK_BBOOL pk11_have_dh = CK_FALSE;
++static CK_BBOOL pk11_have_random = CK_FALSE;
++
++typedef struct PK11_CIPHER_st
++ {
++ int id;
++ int nid;
++ int ivmax;
++ int key_len;
++ CK_KEY_TYPE key_type;
++ CK_MECHANISM_TYPE mech_type;
++ } PK11_CIPHER;
++
++static PK11_CIPHER ciphers[] =
++ {
++ {PK11_DES_CBC, NID_des_cbc, 8, 8, CKK_DES, CKM_DES_CBC, },
++ {PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, CKK_DES3, CKM_DES3_CBC, },
++ {PK11_AES_CBC, NID_aes_128_cbc, 16, 16, CKK_AES, CKM_AES_CBC, },
++ {PK11_RC4, NID_rc4, 0, 16, CKK_RC4, CKM_RC4, },
++ };
++
++typedef struct PK11_DIGEST_st
++ {
++ int id;
++ int nid;
++ CK_MECHANISM_TYPE mech_type;
++ } PK11_DIGEST;
++
++static PK11_DIGEST digests[] =
++ {
++ {PK11_MD5, NID_md5, CKM_MD5, },
++ {PK11_SHA1, NID_sha1, CKM_SHA_1, },
++ {0, NID_undef, 0xFFFF, },
++ };
++
++/* Structure to be used for the cipher_data/md_data in
++ * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same
++ * pk11 session in multiple cipher_update calls
++ */
++typedef struct PK11_CIPHER_STATE_st
++ {
++ PK11_SESSION *sp;
++ } PK11_CIPHER_STATE;
++
++
++/* libcrypto EVP stuff - this is how we get wired to EVP so the engine
++ * gets called when libcrypto requests a cipher NID.
++ * Note how the PK11_CIPHER_STATE is used here.
++ */
++
++/* DES CBC EVP */
++static const EVP_CIPHER pk11_des_cbc =
++ {
++ NID_des_cbc,
++ 8, 8, 8,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof(PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++/* 3DES CBC EVP */
++static const EVP_CIPHER pk11_3des_cbc =
++ {
++ NID_des_ede3_cbc,
++ 8, 24, 8,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof(PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_aes_cbc =
++ {
++ NID_aes_128_cbc,
++ 16, 16, 16,
++ EVP_CIPH_CBC_MODE,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof(PK11_CIPHER_STATE),
++ EVP_CIPHER_set_asn1_iv,
++ EVP_CIPHER_get_asn1_iv,
++ NULL
++ };
++
++static const EVP_CIPHER pk11_rc4 =
++ {
++ NID_rc4,
++ 1,16,0,
++ EVP_CIPH_VARIABLE_LENGTH,
++ pk11_cipher_init,
++ pk11_cipher_do_cipher,
++ pk11_cipher_cleanup,
++ sizeof(PK11_CIPHER_STATE),
++ NULL,
++ NULL,
++ NULL
++ };
++
++static const EVP_MD pk11_md5 =
++ {
++ NID_md5,
++ NID_md5WithRSAEncryption,
++ MD5_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ MD5_CBLOCK,
++ sizeof(PK11_CIPHER_STATE),
++ };
++
++static const EVP_MD pk11_sha1 =
++ {
++ NID_sha1,
++ NID_sha1WithRSAEncryption,
++ SHA_DIGEST_LENGTH,
++ 0,
++ pk11_digest_init,
++ pk11_digest_update,
++ pk11_digest_final,
++ pk11_digest_copy,
++ pk11_digest_cleanup,
++ EVP_PKEY_RSA_method,
++ SHA_CBLOCK,
++ sizeof(PK11_CIPHER_STATE),
++ };
++
++/* Initialization function. Sets up various pk11 library components.
++ */
++/* The definitions for control commands specific to this engine
++ */
++#define PK11_CMD_SO_PATH ENGINE_CMD_BASE
++#define PK11_CMD_PIN (ENGINE_CMD_BASE+1)
++#define PK11_CMD_SLOT (ENGINE_CMD_BASE+2)
++static const ENGINE_CMD_DEFN pk11_cmd_defns[] =
++ {
++ {
++ PK11_CMD_SO_PATH,
++ "SO_PATH",
++ "Specifies the path to the 'pkcs#11' shared library",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_PIN,
++ "PIN",
++ "Specifies the pin code",
++ ENGINE_CMD_FLAG_STRING
++ },
++ {
++ PK11_CMD_SLOT,
++ "SLOT",
++ "Specifies the slot (default is auto select)",
++ ENGINE_CMD_FLAG_NUMERIC,
++ },
++ {0, NULL, NULL, 0}
++ };
++
++
++static RAND_METHOD pk11_random =
++ {
++ pk11_rand_seed,
++ pk11_rand_bytes,
++ pk11_rand_cleanup,
++ pk11_rand_add,
++ pk11_rand_bytes,
++ pk11_rand_status
++ };
++
++
++/* Constants used when creating the ENGINE
++ */
++static const char *engine_pk11_id = "pkcs11";
++static const char *engine_pk11_name = "PKCS #11 engine support";
++
++CK_FUNCTION_LIST_PTR pFuncList = NULL;
++static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList";
++
++/* Cryptoki library
++ */
++static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION;
++
++static CK_BBOOL true = TRUE;
++static CK_BBOOL false = FALSE;
++static CK_SLOT_ID SLOTID = 0;
++static int pk11_auto_slot = 1;
++char *pk11_pin;
++static int pk11_library_initialized = 0;
++
++static DSO *pk11_dso = NULL;
++
++/*
++ * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support.
++ */
++static int bind_pk11(ENGINE *e)
++ {
++ const RSA_METHOD *rsa = NULL;
++ RSA_METHOD *pk11_rsa = PK11_RSA();
++
++ if (!pk11_library_initialized)
++ pk11_library_init(e);
++
++ if(!ENGINE_set_id(e, engine_pk11_id) ||
++ !ENGINE_set_name(e, engine_pk11_name) ||
++ !ENGINE_set_ciphers(e, pk11_engine_ciphers) ||
++ !ENGINE_set_digests(e, pk11_engine_digests))
++ return 0;
++#ifndef OPENSSL_NO_RSA
++ if(pk11_have_rsa == CK_TRUE)
++ {
++ if(!ENGINE_set_RSA(e, PK11_RSA()) ||
++ !ENGINE_set_load_privkey_function(e, pk11_load_privkey) ||
++ !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey))
++ return 0;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered RSA\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif
++#ifndef OPENSSL_NO_DSA
++ if(pk11_have_dsa == CK_TRUE)
++ {
++ if (!ENGINE_set_DSA(e, PK11_DSA()))
++ return 0;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered DSA\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif
++#ifndef OPENSSL_NO_DH
++ if(pk11_have_dh == CK_TRUE)
++ {
++ if (!ENGINE_set_DH(e, PK11_DH()))
++ return 0;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered DH\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++#endif
++ if(pk11_have_random)
++ {
++ if(!ENGINE_set_RAND(e, &pk11_random))
++ return 0;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered random\n");
++#endif /* DEBUG_SLOT_SELECTION */
++ }
++ if(!ENGINE_set_init_function(e, pk11_init) ||
++ !ENGINE_set_destroy_function(e, pk11_destroy) ||
++ !ENGINE_set_finish_function(e, pk11_finish) ||
++ !ENGINE_set_ctrl_function(e, pk11_ctrl) ||
++ !ENGINE_set_cmd_defns(e, pk11_cmd_defns))
++ return 0;
++
++/* Apache calls OpenSSL function RSA_blinding_on() once during startup
++ * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp
++ * here, we wire it back to the OpenSSL software implementation.
++ * Since it is used only once, performance is not a concern. */
++#ifndef OPENSSL_NO_RSA
++ rsa = RSA_PKCS1_SSLeay();
++ pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp;
++ pk11_rsa->bn_mod_exp = rsa->bn_mod_exp;
++#endif
++
++ /* Ensure the pk11 error handling is set up */
++ ERR_load_pk11_strings();
++
++ return 1;
++ }
++
++/* Dynamic engine support is disabled at a higher level for Solaris
++ */
++#ifdef ENGINE_DYNAMIC_SUPPORT
++static int bind_helper(ENGINE *e, const char *id)
++ {
++ if (id && (strcmp(id, engine_pk11_id) != 0))
++ return 0;
++
++ if (!bind_pk11(e))
++ return 0;
++
++ return 1;
++ }
++
++IMPLEMENT_DYNAMIC_CHECK_FN()
++IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
++
++#else
++static ENGINE *engine_pk11(void)
++ {
++ ENGINE *ret = ENGINE_new();
++
++ if (!ret)
++ return NULL;
++
++ if (!bind_pk11(ret))
++ {
++ ENGINE_free(ret);
++ return NULL;
++ }
++
++ return ret;
++ }
++
++void ENGINE_load_pk11(void)
++ {
++ ENGINE *e_pk11 = NULL;
++
++ /* Do not use dynamic PKCS#11 library on Solaris due to
++ * security reasons. We will link it in statically
++ */
++ /* Attempt to load PKCS#11 library
++ */
++ if (!pk11_dso)
++ pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0);
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE);
++ return;
++ }
++
++ e_pk11 = engine_pk11();
++ if (!e_pk11)
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ return;
++ }
++
++ /* At this point, the pk11 shared library is either dynamically
++ * loaded or statically linked in. So, initialize the pk11
++ * library before calling ENGINE_set_default since the latter
++ * needs cipher and digest algorithm information
++ */
++ if (!pk11_library_init(e_pk11))
++ {
++ DSO_free(pk11_dso);
++ pk11_dso = NULL;
++ ENGINE_free(e_pk11);
++ return;
++ }
++
++ ENGINE_add(e_pk11);
++
++ ENGINE_free(e_pk11);
++ ERR_clear_error();
++ }
++#endif
++
++/* These are the static string constants for the DSO file name and
++ * the function symbol names to bind to.
++ */
++static const char *PK11_LIBNAME = NULL;
++
++static const char *get_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ return PK11_LIBNAME;
++
++ return def_PK11_LIBNAME;
++ }
++
++static void free_PK11_LIBNAME(void)
++ {
++ if (PK11_LIBNAME)
++ OPENSSL_free((void*)PK11_LIBNAME);
++
++ PK11_LIBNAME = NULL;
++ }
++
++static long set_PK11_LIBNAME(const char *name)
++ {
++ free_PK11_LIBNAME();
++
++ return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
++ }
++
++/* Initialization function for the pk11 engine */
++static int pk11_init(ENGINE *e)
++{
++ return pk11_library_init(e);
++}
++
++/* Initialization function. Sets up various pk11 library components.
++ * It selects a slot based on predefined critiera. In the process, it also
++ * count how many ciphers and digests to support. Since the cipher and
++ * digest information is needed when setting default engine, this function
++ * needs to be called before calling ENGINE_set_default.
++ */
++static int pk11_library_init(ENGINE *e)
++ {
++ CK_C_GetFunctionList p;
++ CK_RV rv = CKR_OK;
++ CK_INFO info;
++ CK_ULONG ul_state_len;
++ char tmp_buf[20];
++
++ if (pk11_library_initialized)
++ return 1;
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the C_GetFunctionList function from the loaded library
++ */
++ p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso,
++ PK11_GET_FUNCTION_LIST);
++ if ( !p )
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++
++ /* get the full function list from the loaded library
++ */
++ rv = p(&pFuncList);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_Initialize(NULL_PTR);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetInfo(&info);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_GETINFO);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (pk11_choose_slot() == 0)
++ goto err;
++
++ if (global_session == CK_INVALID_HANDLE)
++ {
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_LIBRARY_INIT, PK11_R_OPENSESSION);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ }
++
++ /* Disable digest if C_GetOperationState is not supported since
++ * this function is required by OpenSSL digest copy function */
++ if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len)
++ == CKR_FUNCTION_NOT_SUPPORTED)
++ digest_count = 0;
++
++ pk11_library_initialized = 1;
++ return 1;
++
++err:
++
++ return 0;
++ }
++
++/* Destructor (complements the "ENGINE_pk11()" constructor)
++ */
++static int pk11_destroy(ENGINE *e)
++ {
++ free_PK11_LIBNAME();
++ ERR_unload_pk11_strings();
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++ return 1;
++ }
++
++/* Termination function to clean up the session, the token, and
++ * the pk11 library.
++ */
++static int pk11_finish(ENGINE *e)
++ {
++
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (pk11_dso == NULL)
++ {
++ PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED);
++ goto err;
++ }
++
++ assert(pFuncList != NULL);
++
++ if (pk11_free_all_sessions() == 0)
++ goto err;
++
++ pFuncList->C_CloseSession(global_session);
++
++ /* Since we are part of a library (libcrypto.so), calling this
++ * function may have side-effects.
++ pFuncList->C_Finalize(NULL);
++ */
++
++ if (!DSO_free(pk11_dso))
++ {
++ PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE);
++ goto err;
++ }
++ pk11_dso = NULL;
++ pFuncList = NULL;
++ pk11_library_initialized = 0;
++
++ return 1;
++
++err:
++ return 0;
++ }
++
++/* Standard engine interface function to set the dynamic library path */
++static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
++ {
++ int initialized = ((pk11_dso == NULL) ? 0 : 1);
++
++ switch(cmd)
++ {
++ case PK11_CMD_SO_PATH:
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return 0;
++ }
++
++ if (initialized)
++ {
++ PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED);
++ return 0;
++ }
++
++ return set_PK11_LIBNAME((const char*)p);
++ case PK11_CMD_PIN:
++ if (pk11_pin) {
++ memset(pk11_pin, 0, strlen(pk11_pin));
++ OPENSSL_free((void*)pk11_pin);
++ }
++ pk11_pin = NULL;
++
++ if (p == NULL)
++ {
++ PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER);
++ return 0;
++ }
++
++ pk11_pin = BUF_strdup(p);
++ if (pk11_pin == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_MALLOC_FAILURE);
++ return 0;
++ }
++ return 1;
++ case PK11_CMD_SLOT:
++ SLOTID = (CK_SLOT_ID)i;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: slot set\n");
++#endif
++ return 1;
++ default:
++ break;
++ }
++
++ PK11err(PK11_F_CTRL,PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED);
++
++ return 0;
++ }
++
++
++/* Required function by the engine random interface. It does nothing here
++ */
++static void pk11_rand_cleanup(void)
++ {
++ return;
++ }
++
++static void pk11_rand_add(const void *buf, int num, double add)
++ {
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session()) == NULL)
++ return;
++
++ /* Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since
++ * the calling functions do not care anyway
++ */
++ pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num);
++ pk11_return_session(sp);
++
++ return;
++ }
++
++static void pk11_rand_seed(const void *buf, int num)
++ {
++ pk11_rand_add(buf, num, 0);
++ }
++
++static int pk11_rand_bytes(unsigned char *buf, int num)
++ {
++ CK_RV rv;
++ PK11_SESSION *sp;
++
++ if ((sp = pk11_get_session()) == NULL)
++ return 0;
++
++ rv = pFuncList->C_GenerateRandom(sp->session, buf, num);
++ if (rv != CKR_OK)
++ {
++ char tmp_buf[20];
++ PK11err(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return 0;
++ }
++
++ pk11_return_session(sp);
++ return 1;
++ }
++
++
++/* Required function by the engine random interface. It does nothing here
++ */
++static int pk11_rand_status(void)
++ {
++ return 1;
++ }
++
++
++PK11_SESSION *pk11_get_session()
++ {
++ PK11_SESSION *sp, *sp1;
++ CK_RV rv;
++ char tmp_buf[20];
++
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++ if ((sp = free_session) == NULL)
++ {
++ if ((sp = OPENSSL_malloc(sizeof(PK11_SESSION))) == NULL)
++ {
++ PK11err(PK11_F_GET_SESSION,
++ PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ memset(sp, 0, sizeof(PK11_SESSION));
++ }
++ else
++ {
++ free_session = sp->next;
++ }
++
++ if (sp->pid != 0 && sp->pid != getpid())
++ {
++ /* We are a new process and thus need to free any inherated
++ * PK11_SESSION objects.
++ */
++ while ((sp1 = free_session) != NULL)
++ {
++ free_session = sp1->next;
++ OPENSSL_free(sp1);
++ }
++
++ /* Initialize the process */
++ rv = pFuncList->C_Initialize(NULL_PTR);
++ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED))
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_INITIALIZE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /* Choose slot here since the slot table is different on
++ * this process.
++ */
++ if (pk11_choose_slot() == 0)
++ goto err;
++
++ /* Open the global_session for the new process */
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &global_session);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_SESSION, PK11_R_OPENSESSION);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ OPENSSL_free(sp);
++ sp = NULL;
++ goto err;
++ }
++
++ /* It is an inherited session and needs re-initialization.
++ */
++ if (pk11_setup_session(sp) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ }
++ }
++ else if (sp->pid == 0)
++ {
++ /* It is a new session and needs initialization.
++ */
++ if (pk11_setup_session(sp) == 0)
++ {
++ OPENSSL_free(sp);
++ sp = NULL;
++ }
++ }
++
++err:
++ if (sp)
++ sp->next = NULL;
++
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++
++ return sp;
++ }
++
++
++void pk11_return_session(PK11_SESSION *sp)
++ {
++ if (sp == NULL || sp->pid != getpid())
++ return;
++
++
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++
++ sp->next = free_session;
++ free_session = sp;
++
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++ }
++
++
++/* Destroy all objects. This function is called when the engine is finished
++ */
++static int pk11_free_all_sessions()
++ {
++ CK_RV rv;
++ PK11_SESSION *sp = NULL;
++ pid_t mypid = getpid();
++ int ret = 0;
++
++ pk11_destroy_rsa_key_objects(NULL);
++ pk11_destroy_dsa_key_objects(NULL);
++ pk11_destroy_dh_key_objects(NULL);
++ pk11_destroy_cipher_key_objects(NULL);
++
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++ while ((sp = free_session) != NULL)
++ {
++ if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid)
++ {
++ rv = pFuncList->C_CloseSession(sp->session);
++ if (rv != CKR_OK)
++ {
++ char tmp_buf[20];
++ PK11err(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_CLOSESESSION);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ }
++ }
++ if (sp->session_cipher != CK_INVALID_HANDLE && sp->pid == mypid)
++ {
++ rv = pFuncList->C_CloseSession(sp->session_cipher);
++ if (rv != CKR_OK)
++ {
++ char tmp_buf[20];
++ PK11err(PK11_F_FREE_ALL_SESSIONS,
++ PK11_R_CLOSESESSION);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ }
++ }
++ free_session = sp->next;
++ OPENSSL_free(sp);
++ }
++ ret = 1;
++err:
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++
++ return ret;
++ }
++
++
++static int pk11_setup_session(PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ sp->session = CK_INVALID_HANDLE;
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ if (rv == CKR_CRYPTOKI_NOT_INITIALIZED)
++ {
++ /*
++ * We are probably a child process so force the
++ * reinitialize of the session
++ */
++ pk11_library_initialized = 0;
++ (void) pk11_library_init(NULL);
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session);
++ }
++ if (rv != CKR_OK)
++ {
++ char tmp_buf[20];
++ PK11err(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ return 0;
++ }
++
++ sp->session_cipher = CK_INVALID_HANDLE;
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session_cipher);
++ if (rv != CKR_OK)
++ {
++ char tmp_buf[20];
++
++ (void) pFuncList->C_CloseSession(sp->session);
++ sp->session = CK_INVALID_HANDLE;
++
++ PK11err(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ return 0;
++ }
++
++ sp->pid = getpid();
++ sp->rsa_pub_key = CK_INVALID_HANDLE;
++ sp->rsa_priv_key = CK_INVALID_HANDLE;
++ sp->dsa_pub_key = CK_INVALID_HANDLE;
++ sp->dsa_priv_key = CK_INVALID_HANDLE;
++ sp->dh_key = CK_INVALID_HANDLE;
++ sp->cipher_key = CK_INVALID_HANDLE;
++ sp->rsa = NULL;
++ sp->dsa = NULL;
++ sp->dh = NULL;
++ sp->encrypt = -1;
++
++ return 1;
++ }
++
++int pk11_destroy_rsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 0;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++ if (session)
++ local_free_session = session;
++ else
++ local_free_session = free_session;
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ if (sp->rsa_pub_key != CK_INVALID_HANDLE)
++ {
++ if (pk11_destroy_object(sp->session,
++ sp->rsa_pub_key) == 0)
++ goto err;
++ sp->rsa_pub_key = CK_INVALID_HANDLE;
++ }
++
++ if (sp->rsa_priv_key != CK_INVALID_HANDLE)
++ {
++ if ((sp->rsa->flags & RSA_FLAG_EXT_PKEY) == 0 &&
++ pk11_destroy_object(sp->session,
++ sp->rsa_priv_key) == 0)
++ goto err;
++ sp->rsa_priv_key = CK_INVALID_HANDLE;
++ }
++
++ sp->rsa = NULL;
++ }
++ ret = 1;
++err:
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++
++ return ret;
++ }
++
++int pk11_destroy_dsa_key_objects(PK11_SESSION *session)
++ {
++ int ret = 0;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++ if (session)
++ local_free_session = session;
++ else
++ local_free_session = free_session;
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ if (sp->dsa_pub_key != CK_INVALID_HANDLE)
++ {
++ if (pk11_destroy_object(sp->session,
++ sp->dsa_pub_key) == 0)
++ goto err;
++ sp->dsa_pub_key = CK_INVALID_HANDLE;
++ }
++
++ if (sp->dsa_priv_key != CK_INVALID_HANDLE)
++ {
++ if (pk11_destroy_object(sp->session,
++ sp->dsa_priv_key) == 0)
++ goto err;
++ sp->dsa_priv_key = CK_INVALID_HANDLE;
++ }
++
++ sp->dsa = NULL;
++ }
++ ret = 1;
++err:
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++
++ return ret;
++ }
++
++int pk11_destroy_dh_key_objects(PK11_SESSION *session)
++ {
++ int ret = 0;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++ if (session)
++ local_free_session = session;
++ else
++ local_free_session = free_session;
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ if (sp->dh_key != CK_INVALID_HANDLE)
++ {
++ if (pk11_destroy_object(sp->session,
++ sp->dh_key) == 0)
++ goto err;
++ sp->dh_key = CK_INVALID_HANDLE;
++ }
++
++ sp->dh = NULL;
++ }
++ ret = 1;
++err:
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++
++ return ret;
++ }
++
++static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh)
++ {
++ CK_RV rv;
++ rv = pFuncList->C_DestroyObject(session, oh);
++ if (rv != CKR_OK)
++ {
++ char tmp_buf[20];
++ PK11err(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X",
++ tmp_buf);
++ return 0;
++ }
++
++ return 1;
++ }
++
++
++/* Symmetric ciphers and digests support functions
++ */
++
++static int
++cipher_nid_to_pk11(int nid)
++ {
++ int i;
++
++ for (i = 0; i < PK11_CIPHER_MAX; i++)
++ if (ciphers[i].nid == nid)
++ return (ciphers[i].id);
++ return (-1);
++ }
++
++static int
++pk11_usable_ciphers(const int **nids)
++ {
++ if (cipher_count > 0)
++ *nids = cipher_nids;
++ else
++ *nids = NULL;
++ return (cipher_count);
++ }
++
++static int
++pk11_usable_digests(const int **nids)
++ {
++ if (digest_count > 0)
++ *nids = digest_nids;
++ else
++ *nids = NULL;
++ return (digest_count);
++ }
++
++static int
++pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
++ const unsigned char *iv, int enc)
++ {
++ CK_RV rv;
++ CK_MECHANISM mech;
++ int index;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data;
++ PK11_SESSION *sp;
++ PK11_CIPHER *pcp;
++ char tmp_buf[20];
++
++ state->sp = NULL;
++
++ index = cipher_nid_to_pk11(ctx->cipher->nid);
++ if (index < 0 || index >= PK11_CIPHER_MAX)
++ return 0;
++
++ pcp = &ciphers[index];
++ if (ctx->cipher->iv_len > pcp->ivmax || ctx->key_len != pcp->key_len)
++ return 0;
++
++ if ((sp = pk11_get_session()) == NULL)
++ return 0;
++
++ /* if applicable, the mechanism parameter is used for IV */
++ mech.mechanism = pcp->mech_type;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ /* The key object is destroyed here if it is not the current key
++ */
++ check_new_cipher_key(sp, key);
++
++ /* If the key is the same and the encryption is also the same,
++ * then just reuse it
++ */
++ if (sp->cipher_key != CK_INVALID_HANDLE && sp->encrypt == ctx->encrypt)
++ {
++ state->sp = sp;
++ return 1;
++ }
++
++ /* Check if the key has been invalidated. If so, a new key object
++ * needs to be created.
++ */
++ if (sp->cipher_key == CK_INVALID_HANDLE)
++ {
++ sp->cipher_key = pk11_get_cipher_key(
++ ctx, key, pcp->key_type, sp);
++ }
++
++ if (sp->encrypt != ctx->encrypt && sp->encrypt != -1)
++ {
++ /* The previous encryption/decryption
++ * is different. Need to terminate the previous
++ * active encryption/decryption here
++ */
++ if (!pk11_cipher_final(sp))
++ {
++ pk11_return_session(sp);
++ return 0;
++ }
++ }
++
++ if (sp->cipher_key == CK_INVALID_HANDLE)
++ {
++ pk11_return_session(sp);
++ return 0;
++ }
++
++ if (ctx->cipher->iv_len > 0)
++ {
++ mech.pParameter = (void *) ctx->iv;
++ mech.ulParameterLen = ctx->cipher->iv_len;
++ }
++
++ /* If we get here, the encryption needs to be reinitialized */
++ if (ctx->encrypt)
++ {
++ rv = pFuncList->C_EncryptInit(sp->session_cipher, &mech,
++ sp->cipher_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_CIPHER_INIT, PK11_R_ENCRYPTINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return 0;
++ }
++ }
++ else
++ {
++ rv = pFuncList->C_DecryptInit(sp->session_cipher, &mech,
++ sp->cipher_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_CIPHER_INIT, PK11_R_DECRYPTINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return 0;
++ }
++ }
++
++ sp->encrypt = ctx->encrypt;
++ state->sp = sp;
++
++ return 1;
++ }
++
++/* When reusing the same key in an encryption/decryption session for a
++ * decryption/encryption session, we need to close the active session
++ * and recreate a new one. Note that the key is in the global session so
++ * that it needs not be recreated.
++ *
++ * It is more appropriate to use C_En/DecryptFinish here. At the time of this
++ * development, these two functions in the PKCS#11 libraries used return
++ * unexpected errors when passing in 0 length output. It may be a good
++ * idea to try them again if performance is a problem here and fix
++ * C_En/DecryptFinial if there are bugs there causing the problem.
++ */
++static int
++pk11_cipher_final(PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ char tmp_buf[20];
++
++ rv = pFuncList->C_CloseSession(sp->session_cipher);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ return 0;
++ }
++
++ rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION,
++ NULL_PTR, NULL_PTR, &sp->session_cipher);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ return 0;
++ }
++
++ return 1;
++ }
++
++/* An engine interface function. The calling function allocates sufficient
++ * memory for the output buffer "out" to hold the results */
++static int
++pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
++ const unsigned char *in, unsigned int inl)
++ {
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data;
++ PK11_SESSION *sp;
++ CK_RV rv;
++ unsigned long outl = inl;
++ char tmp_buf[20];
++
++ if (state == NULL || state->sp == NULL)
++ return 0;
++
++ sp = (PK11_SESSION *) state->sp;
++
++ if (!inl)
++ return 1;
++
++ /* RC4 is the only stream cipher we support */
++ if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0)
++ return 0;
++
++ if (ctx->encrypt)
++ {
++ rv = pFuncList->C_EncryptUpdate(sp->session_cipher,
++ (unsigned char *)in, inl, out, &outl);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_CIPHER_DO_CIPHER,
++ PK11_R_ENCRYPTUPDATE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ return 0;
++ }
++ }
++ else
++ {
++ rv = pFuncList->C_DecryptUpdate(sp->session_cipher,
++ (unsigned char *)in, inl, out, &outl);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_CIPHER_DO_CIPHER,
++ PK11_R_DECRYPTUPDATE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ return 0;
++ }
++ }
++
++ /* for DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always
++ * the same size of input
++ * The application has guaranteed to call the block ciphers with
++ * correctly aligned buffers.
++ */
++ if (inl != outl)
++ return 0;
++
++ return 1;
++ }
++
++/* Return the session to the pool. The C_EncryptFinal and C_DecryptFinal are
++ * not used. Once a secret key is initialized, it is used until destroyed.
++ */
++static int
++pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx)
++ {
++ PK11_CIPHER_STATE *state = ctx->cipher_data;
++
++ if (state != NULL && state->sp != NULL)
++ {
++ pk11_return_session(state->sp);
++ state->sp = NULL;
++ }
++
++ return 1;
++ }
++
++/* Registered by the ENGINE when used to find out how to deal with
++ * a particular NID in the ENGINE. This says what we'll do at the
++ * top level - note, that list is restricted by what we answer with
++ */
++static int
++pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
++ const int **nids, int nid)
++ {
++ if (!cipher)
++ return (pk11_usable_ciphers(nids));
++
++ switch (nid)
++ {
++ case NID_des_ede3_cbc:
++ *cipher = &pk11_3des_cbc;
++ break;
++ case NID_des_cbc:
++ *cipher = &pk11_des_cbc;
++ break;
++ case NID_aes_128_cbc:
++ *cipher = &pk11_aes_cbc;
++ break;
++ case NID_rc4:
++ *cipher = &pk11_rc4;
++ break;
++ default:
++ *cipher = NULL;
++ break;
++ }
++ return (*cipher != NULL);
++ }
++
++static int
++pk11_engine_digests(ENGINE *e, const EVP_MD **digest,
++ const int **nids, int nid)
++ {
++ if (!digest)
++ return (pk11_usable_digests(nids));
++
++ switch (nid)
++ {
++ case NID_md5:
++ *digest = &pk11_md5;
++ break;
++ case NID_sha1:
++ *digest = &pk11_sha1;
++ break;
++ default:
++ *digest = NULL;
++ break;
++ }
++ return (*digest != NULL);
++ }
++
++
++/* Create a secret key object in a PKCS#11 session
++ */
++static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx,
++ const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY;
++ CK_ULONG ul_key_attr_count = 6;
++ char tmp_buf[20];
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof(CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof(CK_KEY_TYPE)},
++ {CKA_TOKEN, &false, sizeof(false)},
++ {CKA_ENCRYPT, &true, sizeof(true)},
++ {CKA_DECRYPT, &true, sizeof(true)},
++ {CKA_VALUE, (void*) NULL, 0},
++ };
++
++ /* Create secret key object in global_session. All other sessions
++ * can use the key handles. Here is why:
++ * OpenSSL will call EncryptInit and EncryptUpdate using a secret key.
++ * It may then call DecryptInit and DecryptUpdate using the same key.
++ * To use the same key object, we need to call EncryptFinal with
++ * a 0 length message. Currently, this does not work for 3DES
++ * mechanism. To get around this problem, we close the session and
++ * then create a new session to use the same key object. When a session
++ * is closed, all the object handles will be invalid. Thus, create key
++ * objects in a global session, an individual session may be closed to
++ * terminate the active operation.
++ */
++ CK_SESSION_HANDLE session = global_session;
++ a_key_template[0].pValue = &obj_key;
++ a_key_template[1].pValue = &key_type;
++ a_key_template[5].pValue = (void *) key;
++ a_key_template[5].ulValueLen = (unsigned long) ctx->key_len;
++
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ /* Save the key information used in this session.
++ * The max can be saved is PK11_KEY_LEN_MAX.
++ */
++ sp->key_len = ctx->key_len > PK11_KEY_LEN_MAX ?
++ PK11_KEY_LEN_MAX : ctx->key_len;
++ memcpy(sp->key, key, sp->key_len);
++err:
++
++ return h_key;
++ }
++
++static int
++md_nid_to_pk11(int nid)
++ {
++ int i;
++
++ for (i = 0; i < PK11_DIGEST_MAX; i++)
++ if (digests[i].nid == nid)
++ return (digests[i].id);
++ return (-1);
++ }
++
++static int
++pk11_digest_init(EVP_MD_CTX *ctx)
++ {
++ CK_RV rv;
++ CK_MECHANISM mech;
++ int index;
++ PK11_SESSION *sp;
++ PK11_DIGEST *pdp;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++
++ state->sp = NULL;
++
++ index = md_nid_to_pk11(ctx->digest->type);
++ if (index < 0 || index >= PK11_DIGEST_MAX)
++ return 0;
++
++ pdp = &digests[index];
++ if ((sp = pk11_get_session()) == NULL)
++ return 0;
++
++ /* at present, no parameter is needed for supported digests */
++ mech.mechanism = pdp->mech_type;
++ mech.pParameter = NULL;
++ mech.ulParameterLen = 0;
++
++ rv = pFuncList->C_DigestInit(sp->session, &mech);
++
++ if (rv != CKR_OK)
++ {
++ char tmp_buf[20];
++ PK11err(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return 0;
++ }
++
++ state->sp = sp;
++
++ return 1;
++ }
++
++static int
++pk11_digest_update(EVP_MD_CTX *ctx,const void *data,size_t count)
++ {
++ CK_RV rv;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++
++ /* 0 length message will cause a failure in C_DigestFinal */
++ if (count == 0)
++ return 1;
++
++ if (state == NULL || state->sp == NULL)
++ return 0;
++
++ rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data,
++ count);
++
++ if (rv != CKR_OK)
++ {
++ char tmp_buf[20];
++ PK11err(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(state->sp);
++ state->sp = NULL;
++ return 0;
++ }
++
++ return 1;
++ }
++
++static int
++pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md)
++ {
++ CK_RV rv;
++ unsigned long len;
++ PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data;
++ len = ctx->digest->md_size;
++
++ if (state == NULL || state->sp == NULL)
++ return 0;
++
++ rv = pFuncList->C_DigestFinal(state->sp->session, md, &len);
++
++ if (rv != CKR_OK)
++ {
++ char tmp_buf[20];
++ PK11err(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(state->sp);
++ state->sp = NULL;
++ return 0;
++ }
++
++ if (ctx->digest->md_size != len)
++ return 0;
++
++ /* Final is called and digest is returned, so return the session
++ * to the pool
++ */
++ pk11_return_session(state->sp);
++ state->sp = NULL;
++
++ return 1;
++ }
++
++static int
++pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
++ {
++ CK_RV rv;
++ int ret = 0;
++ PK11_CIPHER_STATE *state, *state_to;
++ CK_BYTE_PTR pstate = NULL;
++ CK_ULONG ul_state_len;
++ char tmp_buf[20];
++
++ /* The copy-from state */
++ state = (PK11_CIPHER_STATE *) from->md_data;
++ if (state == NULL || state->sp == NULL)
++ goto err;
++
++ /* Initialize the copy-to state */
++ if (!pk11_digest_init(to))
++ goto err;
++ state_to = (PK11_CIPHER_STATE *) to->md_data;
++
++ /* Get the size of the operation state of the copy-from session */
++ rv = pFuncList->C_GetOperationState(state->sp->session, NULL,
++ &ul_state_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ if (ul_state_len == 0)
++ {
++ goto err;
++ }
++
++ pstate = OPENSSL_malloc(ul_state_len);
++ if (pstate == NULL)
++ {
++ RSAerr(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* Get the operation state of the copy-from session */
++ rv = pFuncList->C_GetOperationState(state->sp->session, pstate,
++ &ul_state_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ /* Set the operation state of the copy-to session */
++ rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate,
++ ul_state_len, 0, 0);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DIGEST_COPY, PK11_R_SET_OPERATION_STATE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ ret = 1;
++err:
++ if (pstate != NULL)
++ OPENSSL_free(pstate);
++
++ return ret;
++ }
++
++/* Return any pending session state to the pool */
++static int
++pk11_digest_cleanup(EVP_MD_CTX *ctx)
++ {
++ PK11_CIPHER_STATE *state = ctx->md_data;
++ unsigned char buf[EVP_MAX_MD_SIZE];
++
++ if (state != NULL && state->sp != NULL)
++ {
++ /*
++ * If state->sp is not NULL then pk11_digest_final() has not
++ * been called yet. We must call it now to free any memory
++ * that might have been allocated in the token when
++ * pk11_digest_init() was called.
++ */
++ pk11_digest_final(ctx,buf);
++ pk11_return_session(state->sp);
++ state->sp = NULL;
++ }
++
++ return 1;
++ }
++
++/* Check if the new key is the same as the key object in the session.
++ * If the key is the same, no need to create a new key object. Otherwise,
++ * the old key object needs to be destroyed and a new one will be created
++ */
++static void check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key)
++ {
++ if (memcmp(sp->key, key, sp->key_len) != 0)
++ pk11_destroy_cipher_key_objects(sp);
++ }
++
++/* Destroy one or more secret key objects.
++ */
++static int pk11_destroy_cipher_key_objects(PK11_SESSION *session)
++ {
++ int ret = 0;
++ PK11_SESSION *sp = NULL;
++ PK11_SESSION *local_free_session;
++
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++ if (session)
++ local_free_session = session;
++ else
++ local_free_session = free_session;
++ while ((sp = local_free_session) != NULL)
++ {
++ local_free_session = sp->next;
++
++ if (sp->cipher_key != CK_INVALID_HANDLE)
++ {
++ /* The secret key object is created in the
++ * global_session. See pk11_get_cipher_key
++ */
++ if (pk11_destroy_object(global_session,
++ sp->cipher_key) == 0)
++ goto err;
++ sp->cipher_key = CK_INVALID_HANDLE;
++ }
++ }
++ ret = 1;
++err:
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++
++ return ret;
++ }
++
++
++/*
++ * Required mechanisms
++ *
++ * CKM_RSA_X_509
++ * CKM_RSA_PKCS
++ * CKM_DSA
++ *
++ * As long as these required mechanisms are met, it will return success.
++ * Otherwise, it will return failure and the engine initialization will fail.
++ * The application will then decide whether to use another engine or
++ * no engine.
++ *
++ * Symmetric ciphers optionally supported
++ *
++ * CKM_DES3_CBC
++ * CKM_DES_CBC
++ * CKM_AES_CBC
++ * CKM_RC4
++ *
++ * Digests optionally supported
++ *
++ * CKM_MD5
++ * CKM_SHA_1
++ */
++
++static int
++pk11_choose_slot()
++ {
++ CK_SLOT_ID_PTR pSlotList = NULL_PTR;
++ CK_ULONG ulSlotCount = 0;
++ CK_MECHANISM_INFO mech_info;
++ CK_TOKEN_INFO token_info;
++ int i;
++ CK_RV rv;
++ CK_SLOT_ID best_slot_sofar;
++ CK_BBOOL found_candidate_slot = CK_FALSE;
++ int slot_n_cipher = 0;
++ int slot_n_digest = 0;
++ CK_SLOT_ID current_slot = 0;
++ int current_slot_n_cipher = 0;
++ int current_slot_n_digest = 0;
++
++ int local_cipher_nids[PK11_CIPHER_MAX];
++ int local_digest_nids[PK11_DIGEST_MAX];
++ char tmp_buf[20];
++ int retval = 0;
++
++ if (!pk11_auto_slot)
++ return 1;
++
++ /* Get slot list for memory alloction */
++ rv = pFuncList->C_GetSlotList(0, NULL_PTR, &ulSlotCount);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ return retval;
++ }
++
++ if (ulSlotCount == 0)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST);
++ return retval;
++ }
++
++ pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID));
++
++ if (pSlotList == NULL)
++ {
++ RSAerr(PK11_F_CHOOSE_SLOT,PK11_R_MALLOC_FAILURE);
++ return retval;
++ }
++
++ /* Get the slot list for processing */
++ rv = pFuncList->C_GetSlotList(0, pSlotList, &ulSlotCount);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ OPENSSL_free(pSlotList);
++ return retval;
++ }
++
++ for (i = 0; i < ulSlotCount; i++)
++ {
++ CK_BBOOL slot_has_rsa = CK_FALSE;
++ CK_BBOOL slot_has_dsa = CK_FALSE;
++ CK_BBOOL slot_has_dh = CK_FALSE;
++ current_slot = pSlotList[i];
++ current_slot_n_cipher = 0;
++ current_slot_n_digest = 0;
++ memset(local_cipher_nids, 0, sizeof(local_cipher_nids));
++ memset(local_digest_nids, 0, sizeof(local_digest_nids));
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: checking slot: %d\n",
++ current_slot);
++#endif
++ /* Check if slot has random support. */
++ rv = pFuncList->C_GetTokenInfo(current_slot, &token_info);
++ if (rv != CKR_OK)
++ continue;
++
++ if (token_info.flags & CKF_RNG)
++ pk11_have_random = CK_TRUE;
++
++ /*
++ * Check if this slot is capable of signing and
++ * verifying with CKM_RSA_PKCS.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS,
++ &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY)))
++ {
++ /*
++ * Check if this slot is capable of encryption,
++ * decryption, sign, and verify with CKM_RSA_X_509.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_RSA_X_509, &mech_info);
++
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY) &&
++ (mech_info.flags & CKF_ENCRYPT) &&
++ (mech_info.flags & CKF_VERIFY_RECOVER) &&
++ (mech_info.flags & CKF_DECRYPT)))
++ slot_has_rsa = CK_TRUE;
++ }
++
++ /*
++ * Check if this slot is capable of signing and
++ * verifying with CKM_DSA.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA,
++ &mech_info);
++ if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) &&
++ (mech_info.flags & CKF_VERIFY)))
++ slot_has_dsa = CK_TRUE;
++
++ /*
++ * Check if this slot is capable of DH key generataion and
++ * derivation.
++ */
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info);
++
++ if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR))
++ {
++ rv = pFuncList->C_GetMechanismInfo(current_slot,
++ CKM_DH_PKCS_DERIVE, &mech_info);
++ if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE))
++ slot_has_dh = CK_TRUE;
++ }
++
++ if (!found_candidate_slot &&
++ (slot_has_rsa || slot_has_dsa || slot_has_dh))
++ {
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "OPENSSL_PKCS#11_ENGINE: potential slot: %d\n",
++ current_slot);
++#endif
++ best_slot_sofar = current_slot;
++ pk11_have_rsa = slot_has_rsa;
++ pk11_have_dsa = slot_has_dsa;
++ pk11_have_dh = slot_has_dh;
++ found_candidate_slot = CK_TRUE;
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "OPENSSL_PKCS#11_ENGINE: best so far slot: %d\n",
++ best_slot_sofar);
++#endif
++ }
++
++ /* Count symmetric cipher support. */
++ if (!pk11_count_symmetric_cipher(current_slot, CKM_DES_CBC,
++ &current_slot_n_cipher, local_cipher_nids,
++ PK11_DES_CBC))
++ continue;
++ if (!pk11_count_symmetric_cipher(current_slot, CKM_DES3_CBC,
++ &current_slot_n_cipher, local_cipher_nids,
++ PK11_DES3_CBC))
++ continue;
++ if (!pk11_count_symmetric_cipher(current_slot, CKM_AES_CBC,
++ &current_slot_n_cipher, local_cipher_nids,
++ PK11_AES_CBC))
++ continue;
++ if (!pk11_count_symmetric_cipher(current_slot, CKM_RC4,
++ &current_slot_n_cipher, local_cipher_nids,
++ PK11_RC4))
++ continue;
++
++ /* Count digest support */
++ if (!pk11_count_digest(current_slot, CKM_MD5,
++ &current_slot_n_digest, local_digest_nids,
++ PK11_MD5))
++ continue;
++ if (!pk11_count_digest(current_slot, CKM_SHA_1,
++ &current_slot_n_digest, local_digest_nids,
++ PK11_SHA1))
++ continue;
++
++ /*
++ * If the current slot supports more ciphers/digests than
++ * the previous best one we change the current best to this one.
++ * otherwise leave it where it is.
++ */
++ if (((current_slot_n_cipher > slot_n_cipher) &&
++ (current_slot_n_digest > slot_n_digest)) &&
++ ((slot_has_rsa == pk11_have_rsa) &&
++ (slot_has_dsa == pk11_have_dsa) &&
++ (slot_has_dh == pk11_have_dh)))
++ {
++ best_slot_sofar = current_slot;
++ slot_n_cipher = current_slot_n_cipher;
++ slot_n_digest = current_slot_n_digest;
++
++ memcpy(cipher_nids, local_cipher_nids,
++ sizeof(local_cipher_nids));
++ memcpy(digest_nids, local_digest_nids,
++ sizeof(local_digest_nids));
++ }
++
++ }
++
++ if (found_candidate_slot)
++ {
++ cipher_count = slot_n_cipher;
++ digest_count = slot_n_digest;
++ SLOTID = best_slot_sofar;
++ retval = 1;
++ }
++ else
++ {
++ cipher_count = 0;
++ digest_count = 0;
++ }
++
++#ifdef DEBUG_SLOT_SELECTION
++ fprintf(stderr,
++ "OPENSSL_PKCS#11_ENGINE: choose slot: %d\n", SLOTID);
++ fprintf(stderr,
++ "OPENSSL_PKCS#11_ENGINE: pk11_have_rsa %d\n", pk11_have_rsa);
++ fprintf(stderr,
++ "OPENSSL_PKCS#11_ENGINE: pk11_have_dsa %d\n", pk11_have_dsa);
++ fprintf(stderr,
++ "OPENSSL_PKCS#11_ENGINE: pk11_have_dh %d\n", pk11_have_dh);
++ fprintf(stderr,
++ "OPENSSL_PKCS#11_ENGINE: pk11_have_random %d\n", pk11_have_random);
++#endif /* DEBUG_SLOT_SELECTION */
++
++ if (pSlotList)
++ OPENSSL_free(pSlotList);
++
++ return retval;
++ }
++
++static int pk11_count_symmetric_cipher(int slot_id, CK_MECHANISM_TYPE mech,
++ int *current_slot_n_cipher, int *local_cipher_nids, int id)
++ {
++ CK_MECHANISM_INFO mech_info;
++ CK_RV rv;
++
++ rv = pFuncList->C_GetMechanismInfo(slot_id, mech, &mech_info);
++
++ if (rv != CKR_OK)
++ return 0;
++
++ if ((mech_info.flags & CKF_ENCRYPT) &&
++ (mech_info.flags & CKF_DECRYPT))
++ {
++ local_cipher_nids[(*current_slot_n_cipher)++] = ciphers[id].nid;
++ }
++
++ return 1;
++ }
++
++
++static int pk11_count_digest(int slot_id, CK_MECHANISM_TYPE mech,
++ int *current_slot_n_digest, int *local_digest_nids, int id)
++ {
++ CK_MECHANISM_INFO mech_info;
++ CK_RV rv;
++
++ rv = pFuncList->C_GetMechanismInfo(slot_id, mech, &mech_info);
++
++ if (rv != CKR_OK)
++ return 0;
++
++ if (mech_info.flags & CKF_DIGEST)
++ {
++ local_digest_nids[(*current_slot_n_digest)++] = digests[id].nid;
++ }
++
++ return 1;
++ }
++
++
++#endif
++#endif
++
+diff -r -u -N openssl-0.9.8g/crypto/engine/hw_pk11_err.c openssl/crypto/engine/hw_pk11_err.c
+--- openssl-0.9.8g/crypto/engine/hw_pk11_err.c 1970-01-01 01:00:00.000000000 +0100
++++ openssl/crypto/engine/hw_pk11_err.c 2007-10-25 01:27:09.000000000 +0200
+@@ -0,0 +1,233 @@
++/*
++ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++#pragma ident "@(#)hw_pk11_err.c 1.2 04/06/22 SMI"
++
++/* crypto/engine/hw_pk11_err.c */
++/* This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/* ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <openssl/err.h>
++#include "hw_pk11_err.h"
++
++/* BEGIN ERROR CODES */
++#ifndef OPENSSL_NO_ERR
++static ERR_STRING_DATA pk11_str_functs[]=
++{
++ {ERR_PACK(0,PK11_F_INIT,0), "PK11_INIT"},
++ {ERR_PACK(0,PK11_F_FINISH,0), "PK11_FINISH"},
++ {ERR_PACK(0,PK11_F_DESTROY,0), "PK11_DESTROY"},
++ {ERR_PACK(0,PK11_F_CTRL,0), "PK11_CTRL"},
++ {ERR_PACK(0,PK11_F_RSA_INIT,0), "PK11_RSA_INIT"},
++ {ERR_PACK(0,PK11_F_RSA_FINISH,0), "PK11_RSA_FINISH"},
++ {ERR_PACK(0,PK11_F_GET_PUB_RSA_KEY,0), "PK11_GET_PUB_RSA_KEY"},
++ {ERR_PACK(0,PK11_F_GET_PRIV_RSA_KEY,0), "PK11_GET_PRIV_RSA_KEY"},
++ {ERR_PACK(0,PK11_F_RSA_GEN_KEY,0), "PK11_RSA_GEN_KEY"},
++ {ERR_PACK(0,PK11_F_RSA_PUB_ENC,0), "PK11_RSA_PUB_ENC"},
++ {ERR_PACK(0,PK11_F_RSA_PRIV_ENC,0), "PK11_RSA_PRIV_ENC"},
++ {ERR_PACK(0,PK11_F_RSA_PUB_DEC,0), "PK11_RSA_PUB_DEC"},
++ {ERR_PACK(0,PK11_F_RSA_PRIV_DEC,0), "PK11_RSA_PRIV_DEC"},
++ {ERR_PACK(0,PK11_F_RSA_SIGN,0), "PK11_RSA_SIGN"},
++ {ERR_PACK(0,PK11_F_RSA_VERIFY,0), "PK11_RSA_VERIFY"},
++ {ERR_PACK(0,PK11_F_RAND_ADD,0), "PK11_RAND_ADD"},
++ {ERR_PACK(0,PK11_F_RAND_BYTES,0), "PK11_RAND_BYTES"},
++ {ERR_PACK(0,PK11_F_GET_SESSION,0), "PK11_GET_SESSION"},
++ {ERR_PACK(0,PK11_F_FREE_SESSION,0), "PK11_FREE_SESSION"},
++ {ERR_PACK(0,PK11_F_LOAD_PUBKEY,0), "PK11_LOAD_PUBKEY"},
++ {ERR_PACK(0,PK11_F_LOAD_PRIVKEY,0), "PK11_LOAD_PRIV_KEY"},
++ {ERR_PACK(0,PK11_F_RSA_PUB_ENC_LOW,0), "PK11_RSA_PUB_ENC_LOW"},
++ {ERR_PACK(0,PK11_F_RSA_PRIV_ENC_LOW,0), "PK11_RSA_PRIV_ENC_LOW"},
++ {ERR_PACK(0,PK11_F_RSA_PUB_DEC_LOW,0), "PK11_RSA_PUB_DEC_LOW"},
++ {ERR_PACK(0,PK11_F_RSA_PRIV_DEC_LOW,0), "PK11_RSA_PRIV_DEC_LOW"},
++ {ERR_PACK(0,PK11_F_DSA_SIGN,0), "PK11_DSA_SIGN"},
++ {ERR_PACK(0,PK11_F_DSA_VERIFY,0), "PK11_DSA_VERIFY"},
++ {ERR_PACK(0,PK11_F_DSA_INIT,0), "PK11_DSA_INIT"},
++ {ERR_PACK(0,PK11_F_DSA_FINISH,0), "PK11_DSA_FINISH"},
++ {ERR_PACK(0,PK11_F_GET_PUB_DSA_KEY,0), "PK11_GET_PUB_DSA_KEY"},
++ {ERR_PACK(0,PK11_F_GET_PRIV_DSA_KEY,0), "PK11_GET_PRIV_DSA_KEY"},
++ {ERR_PACK(0,PK11_F_DH_INIT,0), "PK11_DH_INIT"},
++ {ERR_PACK(0,PK11_F_DH_FINISH,0), "PK11_DH_FINISH"},
++ {ERR_PACK(0,PK11_F_MOD_EXP_DH,0), "PK11_MOD_EXP_DH"},
++ {ERR_PACK(0,PK11_F_GET_DH_KEY,0), "PK11_GET_DH_KEY"},
++ {ERR_PACK(0,PK11_F_FREE_ALL_SESSIONS,0),"PK11_FREE_ALL_SESSIONS"},
++ {ERR_PACK(0,PK11_F_SETUP_SESSION,0), "PK11_SETUP_SESSION"},
++ {ERR_PACK(0,PK11_F_DESTROY_OBJECT,0), "PK11_DESTROY_OBJECT"},
++ {ERR_PACK(0,PK11_F_CIPHER_INIT,0), "PK11_CIPHER_INIT"},
++ {ERR_PACK(0,PK11_F_CIPHER_DO_CIPHER,0), "PK11_CIPHER_DO_CIPHER"},
++ {ERR_PACK(0,PK11_F_GET_CIPHER_KEY,0), "PK11_GET_CIPHER_KEY"},
++ {ERR_PACK(0,PK11_F_DIGEST_INIT,0), "PK11_DIGEST_INIT"},
++ {ERR_PACK(0,PK11_F_DIGEST_UPDATE,0), "PK11_DIGEST_UPDATE"},
++ {ERR_PACK(0,PK11_F_DIGEST_FINAL,0), "PK11_DIGEST_FINAL"},
++ {ERR_PACK(0,PK11_F_CHOOSE_SLOT,0), "PK11_CHOOSE_SLOT"},
++ {ERR_PACK(0,PK11_F_CIPHER_FINAL,0), "PK11_CIPHER_FINAL"},
++ {ERR_PACK(0,PK11_F_LIBRARY_INIT,0), "PK11_LIBRARY_INIT"},
++ {ERR_PACK(0,PK11_F_LOAD,0), "ENGINE_LOAD_PK11"},
++ {ERR_PACK(0,PK11_F_DH_GEN_KEY,0), "PK11_DH_GEN_KEY"},
++ {ERR_PACK(0,PK11_F_DH_COMP_KEY,0), "PK11_DH_COMP_KEY"},
++ {ERR_PACK(0,PK11_F_DIGEST_COPY,0), "PK11_DIGEST_COPY"},
++ {0,NULL}
++};
++
++static ERR_STRING_DATA pk11_str_reasons[]=
++{
++ {PK11_R_ALREADY_LOADED ,"PKCS#11 DSO already loaded"},
++ {PK11_R_DSO_FAILURE ,"unable to load PKCS#11 DSO"},
++ {PK11_R_NOT_LOADED ,"PKCS#11 DSO not loaded"},
++ {PK11_R_PASSED_NULL_PARAMETER ,"null parameter passed"},
++ {PK11_R_COMMAND_NOT_IMPLEMENTED ,"command not implemented"},
++ {PK11_R_INITIALIZE ,"C_Initialize failed"},
++ {PK11_R_FINALIZE ,"C_Finalize failed"},
++ {PK11_R_GETINFO ,"C_GetInfo faile"},
++ {PK11_R_GETSLOTLIST ,"C_GetSlotList failed"},
++ {PK11_R_NO_MODULUS_OR_NO_EXPONENT ,"no modulus or no exponent"},
++ {PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID ,"attr sensitive or invalid"},
++ {PK11_R_GETATTRIBUTVALUE ,"C_GetAttributeValue failed"},
++ {PK11_R_NO_MODULUS ,"no modulus"},
++ {PK11_R_NO_EXPONENT ,"no exponent"},
++ {PK11_R_FINDOBJECTSINIT ,"C_FindObjectsInit failed"},
++ {PK11_R_FINDOBJECTS ,"C_FindObjects failed"},
++ {PK11_R_FINDOBJECTSFINAL ,"C_FindObjectsFinal failed"},
++ {PK11_R_CREATEOBJECT ,"C_CreateObject failed"},
++ {PK11_R_DESTROYOBJECT ,"C_DestroyObject failed"},
++ {PK11_R_OPENSESSION ,"C_OpenSession failed"},
++ {PK11_R_CLOSESESSION ,"C_CloseSession failed"},
++ {PK11_R_ENCRYPTINIT ,"C_EncryptInit failed"},
++ {PK11_R_ENCRYPT ,"C_Encrypt failed"},
++ {PK11_R_SIGNINIT ,"C_SignInit failed"},
++ {PK11_R_SIGN ,"C_Sign failed"},
++ {PK11_R_DECRYPTINIT ,"C_DecryptInit failed"},
++ {PK11_R_DECRYPT ,"C_Decrypt failed"},
++ {PK11_R_VERIFYINIT ,"C_VerifyRecover failed"},
++ {PK11_R_VERIFY ,"C_Verify failed "},
++ {PK11_R_VERIFYRECOVERINIT ,"C_VerifyRecoverInit failed"},
++ {PK11_R_VERIFYRECOVER ,"C_VerifyRecover failed"},
++ {PK11_R_GEN_KEY ,"C_GenerateKeyPair failed"},
++ {PK11_R_SEEDRANDOM ,"C_SeedRandom failed"},
++ {PK11_R_GENERATERANDOM ,"C_GenerateRandom failed"},
++ {PK11_R_INVALID_MESSAGE_LENGTH ,"invalid message length"},
++ {PK11_R_UNKNOWN_ALGORITHM_TYPE ,"unknown algorithm type"},
++ {PK11_R_UNKNOWN_ASN1_OBJECT_ID ,"unknown asn1 onject id"},
++ {PK11_R_UNKNOWN_PADDING_TYPE ,"unknown padding type"},
++ {PK11_R_PADDING_CHECK_FAILED ,"padding check failed"},
++ {PK11_R_DIGEST_TOO_BIG ,"digest too big"},
++ {PK11_R_MALLOC_FAILURE ,"malloc failure"},
++ {PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED ,"ctl command not implemented"},
++ {PK11_R_DATA_GREATER_THAN_MOD_LEN ,"data is bigger than mod"},
++ {PK11_R_DATA_TOO_LARGE_FOR_MODULUS ,"data is too larger for mod"},
++ {PK11_R_MISSING_KEY_COMPONENT ,"a dsa component is missing"},
++ {PK11_R_INVALID_SIGNATURE_LENGTH ,"invalid signature length"},
++ {PK11_R_INVALID_DSA_SIGNATURE_R ,"missing r in dsa verify"},
++ {PK11_R_INVALID_DSA_SIGNATURE_S ,"missing s in dsa verify"},
++ {PK11_R_INCONSISTENT_KEY ,"inconsistent key type"},
++ {PK11_R_ENCRYPTUPDATE ,"C_EncryptUpdate failed"},
++ {PK11_R_DECRYPTUPDATE ,"C_DecryptUpdate failed"},
++ {PK11_R_DIGESTINIT ,"C_DigestInit failed"},
++ {PK11_R_DIGESTUPDATE ,"C_DigestUpdate failed"},
++ {PK11_R_DIGESTFINAL ,"C_DigestFinal failed"},
++ {PK11_R_ENCRYPTFINAL ,"C_EncryptFinal failed"},
++ {PK11_R_DECRYPTFINAL ,"C_DecryptFinal failed"},
++ {PK11_R_NO_PRNG_SUPPORT ,"Slot does not support PRNG"},
++ {PK11_R_GETTOKENINFO ,"C_GetTokenInfo failed"},
++ {PK11_R_DERIVEKEY ,"C_DeriveKey failed"},
++ {PK11_R_GET_OPERATION_STATE ,"C_GetOperationState failed"},
++ {PK11_R_SET_OPERATION_STATE ,"C_SetOperationState failed"},
++ {0,NULL}
++};
++
++#endif
++
++static int pk11_lib_error_code=0;
++static int pk11_error_init=1;
++
++static void ERR_load_pk11_strings(void)
++{
++ if (pk11_lib_error_code == 0)
++ pk11_lib_error_code = ERR_get_next_error_library();
++
++ if (pk11_error_init)
++ {
++ pk11_error_init=0;
++#ifndef OPENSSL_NO_ERR
++ ERR_load_strings(pk11_lib_error_code,pk11_str_functs);
++ ERR_load_strings(pk11_lib_error_code,pk11_str_reasons);
++#endif
++ }
++}
++
++static void ERR_unload_pk11_strings(void)
++{
++ if (pk11_error_init == 0)
++ {
++#ifndef OPENSSL_NO_ERR
++ ERR_unload_strings(pk11_lib_error_code,pk11_str_functs);
++ ERR_unload_strings(pk11_lib_error_code,pk11_str_reasons);
++#endif
++ pk11_error_init = 1;
++ }
++}
++
++static void ERR_pk11_error(int function, int reason, char *file, int line)
++{
++ if (pk11_lib_error_code == 0)
++ pk11_lib_error_code=ERR_get_next_error_library();
++ ERR_PUT_error(pk11_lib_error_code,function,reason,file,line);
++}
+diff -r -u -N openssl-0.9.8g/crypto/engine/hw_pk11_err.h openssl/crypto/engine/hw_pk11_err.h
+--- openssl-0.9.8g/crypto/engine/hw_pk11_err.h 1970-01-01 01:00:00.000000000 +0100
++++ openssl/crypto/engine/hw_pk11_err.h 2008-01-31 16:14:07.000000000 +0100
+@@ -0,0 +1,247 @@
++/*
++ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++#pragma ident "@(#)hw_pk11_err.h 1.2 04/06/22 SMI"
++
++/* crypto/engine/hw_pk11_err.h */
++/* This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/* ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#ifndef HW_PK11_ERR_H
++#define HW_PK11_ERR_H
++
++/* CRYPTO_LOCK_RSA is defined in OpenSSL for RSA method. Since this pk11
++ * engine replaces RSA method, we may reuse this lock here.
++ */
++#define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_RSA
++
++static void ERR_load_pk11_strings(void);
++static void ERR_pk11_error(int function, int reason, char *file, int line);
++#define PK11err(f,r) ERR_pk11_error((f),(r),__FILE__,__LINE__)
++
++/* Error codes for the PK11 functions. */
++
++/* Function codes. */
++
++#define PK11_F_INIT 100
++#define PK11_F_FINISH 101
++#define PK11_F_DESTROY 102
++#define PK11_F_CTRL 103
++#define PK11_F_RSA_INIT 104
++#define PK11_F_RSA_FINISH 105
++#define PK11_F_GET_PUB_RSA_KEY 106
++#define PK11_F_GET_PRIV_RSA_KEY 107
++#define PK11_F_RSA_GEN_KEY 108
++#define PK11_F_RSA_PUB_ENC 109
++#define PK11_F_RSA_PRIV_ENC 110
++#define PK11_F_RSA_PUB_DEC 111
++#define PK11_F_RSA_PRIV_DEC 112
++#define PK11_F_RSA_SIGN 113
++#define PK11_F_RSA_VERIFY 114
++#define PK11_F_RAND_ADD 115
++#define PK11_F_RAND_BYTES 116
++#define PK11_F_GET_SESSION 117
++#define PK11_F_FREE_SESSION 118
++#define PK11_F_LOAD_PUBKEY 119
++#define PK11_F_LOAD_PRIVKEY 120
++#define PK11_F_RSA_PUB_ENC_LOW 121
++#define PK11_F_RSA_PRIV_ENC_LOW 122
++#define PK11_F_RSA_PUB_DEC_LOW 123
++#define PK11_F_RSA_PRIV_DEC_LOW 124
++#define PK11_F_DSA_SIGN 125
++#define PK11_F_DSA_VERIFY 126
++#define PK11_F_DSA_INIT 127
++#define PK11_F_DSA_FINISH 128
++#define PK11_F_GET_PUB_DSA_KEY 129
++#define PK11_F_GET_PRIV_DSA_KEY 130
++#define PK11_F_DH_INIT 131
++#define PK11_F_DH_FINISH 132
++#define PK11_F_MOD_EXP_DH 133
++#define PK11_F_GET_DH_KEY 134
++#define PK11_F_FREE_ALL_SESSIONS 135
++#define PK11_F_SETUP_SESSION 136
++#define PK11_F_DESTROY_OBJECT 137
++#define PK11_F_CIPHER_INIT 138
++#define PK11_F_CIPHER_DO_CIPHER 139
++#define PK11_F_GET_CIPHER_KEY 140
++#define PK11_F_DIGEST_INIT 141
++#define PK11_F_DIGEST_UPDATE 142
++#define PK11_F_DIGEST_FINAL 143
++#define PK11_F_CHOOSE_SLOT 144
++#define PK11_F_CIPHER_FINAL 145
++#define PK11_F_LIBRARY_INIT 146
++#define PK11_F_LOAD 147
++#define PK11_F_DH_GEN_KEY 148
++#define PK11_F_DH_COMP_KEY 149
++#define PK11_F_DIGEST_COPY 150
++
++/* Reason codes. */
++#define PK11_R_ALREADY_LOADED 100
++#define PK11_R_DSO_FAILURE 101
++#define PK11_R_NOT_LOADED 102
++#define PK11_R_PASSED_NULL_PARAMETER 103
++#define PK11_R_COMMAND_NOT_IMPLEMENTED 104
++#define PK11_R_INITIALIZE 105
++#define PK11_R_FINALIZE 106
++#define PK11_R_GETINFO 107
++#define PK11_R_GETSLOTLIST 108
++#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109
++#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110
++#define PK11_R_GETATTRIBUTVALUE 111
++#define PK11_R_NO_MODULUS 112
++#define PK11_R_NO_EXPONENT 113
++#define PK11_R_FINDOBJECTSINIT 114
++#define PK11_R_FINDOBJECTS 115
++#define PK11_R_FINDOBJECTSFINAL 116
++#define PK11_R_CREATEOBJECT 118
++#define PK11_R_DESTROYOBJECT 119
++#define PK11_R_OPENSESSION 120
++#define PK11_R_CLOSESESSION 121
++#define PK11_R_ENCRYPTINIT 122
++#define PK11_R_ENCRYPT 123
++#define PK11_R_SIGNINIT 124
++#define PK11_R_SIGN 125
++#define PK11_R_DECRYPTINIT 126
++#define PK11_R_DECRYPT 127
++#define PK11_R_VERIFYINIT 128
++#define PK11_R_VERIFY 129
++#define PK11_R_VERIFYRECOVERINIT 130
++#define PK11_R_VERIFYRECOVER 131
++#define PK11_R_GEN_KEY 132
++#define PK11_R_SEEDRANDOM 133
++#define PK11_R_GENERATERANDOM 134
++#define PK11_R_INVALID_MESSAGE_LENGTH 135
++#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136
++#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137
++#define PK11_R_UNKNOWN_PADDING_TYPE 138
++#define PK11_R_PADDING_CHECK_FAILED 139
++#define PK11_R_DIGEST_TOO_BIG 140
++#define PK11_R_MALLOC_FAILURE 141
++#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142
++#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143
++#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144
++#define PK11_R_MISSING_KEY_COMPONENT 145
++#define PK11_R_INVALID_SIGNATURE_LENGTH 146
++#define PK11_R_INVALID_DSA_SIGNATURE_R 147
++#define PK11_R_INVALID_DSA_SIGNATURE_S 148
++#define PK11_R_INCONSISTENT_KEY 149
++#define PK11_R_ENCRYPTUPDATE 150
++#define PK11_R_DECRYPTUPDATE 151
++#define PK11_R_DIGESTINIT 152
++#define PK11_R_DIGESTUPDATE 153
++#define PK11_R_DIGESTFINAL 154
++#define PK11_R_ENCRYPTFINAL 155
++#define PK11_R_DECRYPTFINAL 156
++#define PK11_R_NO_PRNG_SUPPORT 157
++#define PK11_R_GETTOKENINFO 158
++#define PK11_R_DERIVEKEY 159
++#define PK11_R_GET_OPERATION_STATE 160
++#define PK11_R_SET_OPERATION_STATE 161
++#define PK11_R_INVALID_PIN 162
++#define PK11_R_TOO_MANY_OBJECTS 163
++#define PK11_R_OBJECT_NOT_FOUND 164
++
++/* This structure encapsulates all reusable information for a PKCS#11
++ * session. A list of this object is created on behalf of the
++ * calling application using an on-demand method. When a new request
++ * comes in, an object will be taken from the list (if there is one)
++ * or a new one is created to handle the request. Note that not all
++ * fields are used for every application. For example, an RSA-only
++ * application only uses the RSA related fields */
++typedef struct PK11_SESSION_st
++ {
++ struct PK11_SESSION_st *next;
++ CK_SESSION_HANDLE session; /* PK11 session handle */
++ CK_SESSION_HANDLE session_cipher; /* PK11 sess handle for ciph */
++ pid_t pid; /* Current process ID */
++ CK_OBJECT_HANDLE rsa_pub_key; /* RSA key handle in the sess */
++ CK_OBJECT_HANDLE rsa_priv_key; /* RSA private key handle */
++ CK_OBJECT_HANDLE dsa_pub_key; /* DSA pub key handle */
++ CK_OBJECT_HANDLE dsa_priv_key; /* DSA priv key handle */
++ CK_OBJECT_HANDLE dh_key; /* RSA pub key handle for DH */
++ CK_OBJECT_HANDLE cipher_key; /* Cipher key handle */
++ RSA *rsa; /* Address of the RSA struct */
++ void *dsa; /* Address of the DSA structure */
++ void *dh; /* Address of the DH */
++ unsigned char key[24];/* Save the private key here */
++ int key_len;/* Saved private key length */
++ int encrypt;/* 1/0 for encrypt/decrypt */
++ } PK11_SESSION;
++
++extern PK11_SESSION *pk11_get_session();
++extern void pk11_return_session(PK11_SESSION *sp);
++
++extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session);
++extern int pk11_destroy_dh_key_objects(PK11_SESSION *session);
++
++extern RSA_METHOD *PK11_RSA(void);
++extern DSA_METHOD *PK11_DSA(void);
++extern DH_METHOD *PK11_DH(void);
++
++extern EVP_PKEY *pk11_load_privkey(ENGINE*, const char* pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++extern EVP_PKEY *pk11_load_pubkey(ENGINE*, const char* pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++
++extern CK_FUNCTION_LIST_PTR pFuncList;
++
++#endif /* HW_PK11_ERR_H */
+diff -r -u -N openssl-0.9.8g/crypto/engine/hw_pk11_pub.c openssl/crypto/engine/hw_pk11_pub.c
+--- openssl-0.9.8g/crypto/engine/hw_pk11_pub.c 1970-01-01 01:00:00.000000000 +0100
++++ openssl/crypto/engine/hw_pk11_pub.c 2008-03-17 15:15:49.000000000 +0100
+@@ -0,0 +1,2616 @@
++/*
++ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
++ * Use is subject to license terms.
++ */
++#pragma ident "@(#)hw_pk11_pub.c 1.4 07/05/10 SMI"
++
++/* crypto/engine/hw_pk11_pub.c */
++/* This product includes software developed by the OpenSSL Project for
++ * use in the OpenSSL Toolkit (http://www.openssl.org/).
++ *
++ * This project also referenced hw_pkcs11-0.9.7b.patch written by
++ * Afchine Madjlessi.
++ */
++/* ====================================================================
++ * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ * notice, this list of conditions and the following disclaimer.
++ *
++ * 2. Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in
++ * the documentation and/or other materials provided with the
++ * distribution.
++ *
++ * 3. All advertising materials mentioning features or use of this
++ * software must display the following acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
++ *
++ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
++ * endorse or promote products derived from this software without
++ * prior written permission. For written permission, please contact
++ * licensing@OpenSSL.org.
++ *
++ * 5. Products derived from this software may not be called "OpenSSL"
++ * nor may "OpenSSL" appear in their names without prior written
++ * permission of the OpenSSL Project.
++ *
++ * 6. Redistributions of any form whatsoever must retain the following
++ * acknowledgment:
++ * "This product includes software developed by the OpenSSL Project
++ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
++ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
++ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++ * OF THE POSSIBILITY OF SUCH DAMAGE.
++ * ====================================================================
++ *
++ * This product includes cryptographic software written by Eric Young
++ * (eay@cryptsoft.com). This product includes software written by Tim
++ * Hudson (tjh@cryptsoft.com).
++ *
++ */
++
++#include <stdio.h>
++#include <assert.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++#include <unistd.h>
++
++#include <openssl/e_os2.h>
++#include <openssl/engine.h>
++#include <openssl/dso.h>
++#include <openssl/err.h>
++#include <openssl/bn.h>
++#include <openssl/pem.h>
++#include <openssl/rsa.h>
++#include <openssl/rand.h>
++#include <openssl/objects.h>
++#include <openssl/x509.h>
++#include <cryptlib.h>
++
++#ifndef OPENSSL_NO_HW
++#ifndef OPENSSL_NO_HW_PK11
++
++#include "cryptoki.h"
++#include "pkcs11.h"
++#include "hw_pk11_err.c"
++
++#ifndef OPENSSL_NO_RSA
++/* RSA stuff */
++static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding);
++static int pk11_RSA_init(RSA *rsa);
++static int pk11_RSA_finish(RSA *rsa);
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
++static int pk11_RSA_verify(int dtype, const unsigned char *m,
++ unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa);
++EVP_PKEY *pk11_load_privkey(ENGINE*, const char* pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++EVP_PKEY *pk11_load_pubkey(ENGINE*, const char* pubkey_file,
++ UI_METHOD *ui_method, void *callback_data);
++
++static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa);
++
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, PK11_SESSION *sp);
++static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa,
++ PK11_SESSION *sp);
++#endif
++
++/* DSA stuff */
++#ifndef OPENSSL_NO_DSA
++static int pk11_DSA_init(DSA *dsa);
++static int pk11_DSA_finish(DSA *dsa);
++static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen,
++ DSA *dsa);
++static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len,
++ DSA_SIG *sig, DSA *dsa);
++
++static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa,
++ PK11_SESSION *sp);
++static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa,
++ PK11_SESSION *sp);
++#endif
++
++/* DH stuff */
++#ifndef OPENSSL_NO_DH
++static int pk11_DH_init(DH *dh);
++static int pk11_DH_finish(DH *dh);
++static int pk11_DH_generate_key(DH *dh);
++static int pk11_DH_compute_key(unsigned char *key,
++ const BIGNUM *pub_key,DH *dh);
++
++static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, PK11_SESSION *sp);
++#endif
++
++static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue,
++ CK_ULONG *ulValueLen);
++static void check_new_rsa_key(PK11_SESSION *sp, void *rsa);
++static void check_new_dsa_key(PK11_SESSION *sp, void *dsa);
++static void check_new_dh_key(PK11_SESSION *sp, void *dh);
++static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn);
++
++
++#ifndef OPENSSL_NO_RSA
++/* Our internal RSA_METHOD that we provide pointers to */
++static RSA_METHOD pk11_rsa =
++ {
++ "PKCS#11 RSA method",
++ pk11_RSA_public_encrypt, /* rsa_pub_encrypt */
++ pk11_RSA_public_decrypt, /* rsa_pub_decrypt */
++ pk11_RSA_private_encrypt, /* rsa_priv_encrypt */
++ pk11_RSA_private_decrypt, /* rsa_priv_decrypt */
++ NULL, /* rsa_mod_exp */
++ NULL, /* bn_mod_exp */
++ pk11_RSA_init, /* init */
++ pk11_RSA_finish, /* finish */
++ RSA_FLAG_SIGN_VER, /* flags */
++ NULL, /* app_data */
++ pk11_RSA_sign, /* rsa_sign */
++ pk11_RSA_verify/*,*/ /* rsa_verify */
++ };
++
++RSA_METHOD *PK11_RSA(void)
++ {
++ return(&pk11_rsa);
++ }
++#endif
++
++#ifndef OPENSSL_NO_DSA
++/* Our internal DSA_METHOD that we provide pointers to */
++static DSA_METHOD pk11_dsa =
++ {
++ "PKCS#11 DSA method",
++ pk11_dsa_do_sign, /* dsa_do_sign */
++ NULL, /* dsa_sign_setup */
++ pk11_dsa_do_verify, /* dsa_do_verify */
++ NULL, /* dsa_mod_exp */
++ NULL, /* bn_mod_exp */
++ pk11_DSA_init, /* init */
++ pk11_DSA_finish, /* finish */
++ 0, /* flags */
++ NULL /* app_data */
++ };
++
++DSA_METHOD *PK11_DSA(void)
++ {
++ return(&pk11_dsa);
++ }
++
++#endif
++
++
++#ifndef OPENSSL_NO_DH
++/* Our internal DH_METHOD that we provide pointers to */
++static DH_METHOD pk11_dh =
++ {
++ "PKCS#11 DH method",
++ pk11_DH_generate_key, /* generate_key */
++ pk11_DH_compute_key, /* compute_key */
++ NULL, /* bn_mod_exp */
++ pk11_DH_init, /* init */
++ pk11_DH_finish, /* finish */
++ 0, /* flags */
++ NULL /* app_data */
++ };
++
++DH_METHOD *PK11_DH(void)
++ {
++ return(&pk11_dh);
++ }
++#endif
++
++/* Size of an SSL signature: MD5+SHA1
++ */
++#define SSL_SIG_LENGTH 36
++
++/* Lengths of DSA data and signature
++ */
++#define DSA_DATA_LEN 20
++#define DSA_SIGNATURE_LEN 40
++
++static CK_BBOOL true = TRUE;
++static CK_BBOOL false = FALSE;
++
++#ifndef OPENSSL_NO_RSA
++
++/* Similiar to Openssl to take advantage of the paddings. The goal is to
++ * support all paddings in this engine although PK11 library does not
++ * support all the paddings used in OpenSSL.
++ * The input errors should have been checked in the padding functions
++ */
++static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ int i,num=0,r= -1;
++ unsigned char *buf=NULL;
++
++ num=BN_num_bytes(rsa->n);
++ if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PUB_ENC,PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen);
++ break;
++#ifndef OPENSSL_NO_SHA
++ case RSA_PKCS1_OAEP_PADDING:
++ i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0);
++ break;
++#endif
++ case RSA_SSLV23_PADDING:
++ i=RSA_padding_add_SSLv23(buf,num,from,flen);
++ break;
++ case RSA_NO_PADDING:
++ i=RSA_padding_add_none(buf,num,from,flen);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PUB_ENC,PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (i <= 0) goto err;
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_public_encrypt_low(num, buf, to, rsa);
++err:
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf,num);
++ OPENSSL_free(buf);
++ }
++ return(r);
++ }
++
++
++/* Similar to Openssl to take advantage of the paddings. The input errors
++ * should be catched in the padding functions
++ */
++static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ int i,num=0,r= -1;
++ unsigned char *buf=NULL;
++
++ num=BN_num_bytes(rsa->n);
++ if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PRIV_ENC,PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ i=RSA_padding_add_PKCS1_type_1(buf,num,from,flen);
++ break;
++ case RSA_NO_PADDING:
++ i=RSA_padding_add_none(buf,num,from,flen);
++ break;
++ case RSA_SSLV23_PADDING:
++ default:
++ RSAerr(PK11_F_RSA_PRIV_ENC,PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (i <= 0) goto err;
++
++ /* PK11 functions are called here */
++ r=pk11_RSA_private_encrypt_low(num, buf, to, rsa);
++err:
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf,num);
++ OPENSSL_free(buf);
++ }
++ return(r);
++ }
++
++/* Similar to Openssl. Input errors are also checked here
++ */
++static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ BIGNUM f;
++ int j,num=0,r= -1;
++ unsigned char *p;
++ unsigned char *buf=NULL;
++
++ BN_init(&f);
++
++ num=BN_num_bytes(rsa->n);
++
++ if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* This check was for equality but PGP does evil things
++ * and chops off the top '0' bytes */
++ if (flen > num)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,
++ PK11_R_DATA_GREATER_THAN_MOD_LEN);
++ goto err;
++ }
++
++ /* make data into a big number */
++ if (BN_bin2bn(from,(int)flen,&f) == NULL) goto err;
++
++ if (BN_ucmp(&f, rsa->n) >= 0)
++ {
++ RSAerr(PK11_F_RSA_PRIV_DEC,
++ PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
++ goto err;
++ }
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa);
++
++ /* PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
++ * Needs to skip these 0's paddings here */
++ for (j = 0; j < r; j++)
++ if (buf[j] != 0)
++ break;
++
++ p = buf + j;
++ j = r - j; /* j is only used with no-padding mode */
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ r=RSA_padding_check_PKCS1_type_2(to,num,p,j,num);
++ break;
++#ifndef OPENSSL_NO_SHA
++ case RSA_PKCS1_OAEP_PADDING:
++ r=RSA_padding_check_PKCS1_OAEP(to,num,p,j,num,NULL,0);
++ break;
++#endif
++ case RSA_SSLV23_PADDING:
++ r=RSA_padding_check_SSLv23(to,num,p,j,num);
++ break;
++ case RSA_NO_PADDING:
++ r=RSA_padding_check_none(to,num,p,j,num);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PRIV_DEC,PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (r < 0)
++ RSAerr(PK11_F_RSA_PRIV_DEC,PK11_R_PADDING_CHECK_FAILED);
++
++err:
++ BN_clear_free(&f);
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf,num);
++ OPENSSL_free(buf);
++ }
++ return(r);
++ }
++
++/* Similar to Openssl. Input errors are also checked here
++ */
++static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
++ unsigned char *to, RSA *rsa, int padding)
++ {
++ BIGNUM f;
++ int i,num=0,r= -1;
++ unsigned char *p;
++ unsigned char *buf=NULL;
++
++ BN_init(&f);
++ num=BN_num_bytes(rsa->n);
++ buf=(unsigned char *)OPENSSL_malloc(num);
++ if (buf == NULL)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC,PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ /* This check was for equality but PGP does evil things
++ * and chops off the top '0' bytes */
++ if (flen > num)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC,PK11_R_DATA_GREATER_THAN_MOD_LEN);
++ goto err;
++ }
++
++ if (BN_bin2bn(from,flen,&f) == NULL) goto err;
++
++ if (BN_ucmp(&f, rsa->n) >= 0)
++ {
++ RSAerr(PK11_F_RSA_PUB_DEC,
++ PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
++ goto err;
++ }
++
++ /* PK11 functions are called here */
++ r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa);
++
++ /* PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
++ * Needs to skip these 0's here */
++ for (i = 0; i < r; i++)
++ if (buf[i] != 0)
++ break;
++
++ p = buf + i;
++ i = r - i; /* i is only used with no-padding mode */
++
++ switch (padding)
++ {
++ case RSA_PKCS1_PADDING:
++ r=RSA_padding_check_PKCS1_type_1(to,num,p,i,num);
++ break;
++ case RSA_NO_PADDING:
++ r=RSA_padding_check_none(to,num,p,i,num);
++ break;
++ default:
++ RSAerr(PK11_F_RSA_PUB_DEC,PK11_R_UNKNOWN_PADDING_TYPE);
++ goto err;
++ }
++ if (r < 0)
++ RSAerr(PK11_F_RSA_PUB_DEC,PK11_R_PADDING_CHECK_FAILED);
++
++err:
++ BN_clear_free(&f);
++ if (buf != NULL)
++ {
++ OPENSSL_cleanse(buf,num);
++ OPENSSL_free(buf);
++ }
++ return(r);
++ }
++
++/* This function implements RSA public encryption using C_EncryptInit and
++ * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_public_encrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_encrypted=flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++ char tmp_buf[20];
++
++ if ((sp = pk11_get_session()) == NULL)
++ return -1;
++
++ check_new_rsa_key(sp, (void *) rsa);
++
++ h_pub_key = sp->rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->rsa_pub_key =
++ pk11_get_public_rsa_key(rsa, sp);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_EncryptInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_PUB_ENC_LOW,
++ PK11_R_ENCRYPTINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return -1;
++ }
++
++ rv = pFuncList->C_Encrypt(sp->session,
++ (unsigned char *)from, flen, to, &bytes_encrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_PUB_ENC_LOW, PK11_R_ENCRYPT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return -1;
++ }
++ retval = bytes_encrypted;
++ }
++
++ pk11_return_session(sp);
++ return retval;
++ }
++
++
++/* This function implements RSA private encryption using C_SignInit and
++ * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_private_encrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG ul_sig_len=flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key= CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++ char tmp_buf[20];
++
++ if ((sp = pk11_get_session()) == NULL)
++ return -1;
++
++ check_new_rsa_key(sp, (void *) rsa);
++
++ h_priv_key = sp->rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->rsa_priv_key =
++ pk11_get_private_rsa_key(rsa, sp);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech,
++ h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGNINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return -1;
++ }
++
++ rv = pFuncList->C_Sign(sp->session,
++ (unsigned char *)from, flen, to, &ul_sig_len);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return -1;
++ }
++
++ retval = ul_sig_len;
++ }
++
++ pk11_return_session(sp);
++ return retval;
++ }
++
++
++/* This function implements RSA private decryption using C_DecryptInit and
++ * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_private_decrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_decrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp;
++ char tmp_buf[20];
++
++ if ((sp = pk11_get_session()) == NULL)
++ return -1;
++
++ check_new_rsa_key(sp, (void *) rsa);
++
++ h_priv_key = sp->rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->rsa_priv_key =
++ pk11_get_private_rsa_key(rsa, sp);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DecryptInit(sp->session, p_mech,
++ h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_PRIV_DEC_LOW,
++ PK11_R_DECRYPTINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return -1;
++ }
++
++ rv = pFuncList->C_Decrypt(sp->session,
++ (unsigned char *)from, flen, to, &bytes_decrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_PRIV_DEC_LOW, PK11_R_DECRYPT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return -1;
++ }
++ retval = bytes_decrypted;
++ }
++
++ pk11_return_session(sp);
++ return retval;
++ }
++
++
++/* This function implements RSA public decryption using C_VerifyRecoverInit
++ * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here.
++ * The calling function allocated sufficient memory in "to" to store results.
++ */
++static int pk11_RSA_public_decrypt_low(int flen,
++ const unsigned char *from, unsigned char *to, RSA *rsa)
++ {
++ CK_ULONG bytes_decrypted = flen;
++ int retval = -1;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ PK11_SESSION *sp;
++ char tmp_buf[20];
++
++ if ((sp = pk11_get_session()) == NULL)
++ return -1;
++
++ check_new_rsa_key(sp, (void *) rsa);
++
++ h_pub_key = sp->rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->rsa_pub_key =
++ pk11_get_public_rsa_key(rsa, sp);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyRecoverInit(sp->session,
++ p_mech, h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_PUB_DEC_LOW,
++ PK11_R_VERIFYRECOVERINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return -1;
++ }
++
++ rv = pFuncList->C_VerifyRecover(sp->session,
++ (unsigned char *)from, flen, to, &bytes_decrypted);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_PUB_DEC_LOW,
++ PK11_R_VERIFYRECOVER);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ pk11_return_session(sp);
++ return -1;
++ }
++ retval = bytes_decrypted;
++ }
++
++ pk11_return_session(sp);
++ return retval;
++ }
++
++
++static int pk11_RSA_init(RSA *rsa)
++ {
++ /* This flag in the RSA_METHOD enables the new rsa_sign,
++ * rsa_verify functions. See rsa.h for details. */
++ rsa->flags |= RSA_FLAG_SIGN_VER;
++
++ return 1;
++ }
++
++
++static int pk11_RSA_finish(RSA *rsa)
++ {
++ if (rsa->_method_mod_n != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_n);
++ if (rsa->_method_mod_p != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_p);
++ if (rsa->_method_mod_q != NULL)
++ BN_MONT_CTX_free(rsa->_method_mod_q);
++
++ return pk11_destroy_rsa_key_objects(NULL);
++ }
++
++
++/* Standard engine interface function. Majority codes here are from
++ * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11.
++ * See more details in rsa/rsa_sign.c */
++static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
++ unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i,j;
++ unsigned char *p,*s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_priv_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++ char tmp_buf[20];
++ unsigned long ulsiglen;
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor= &algor;
++ sig.algor->algorithm=OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_SIGN,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type=V_ASN1_NULL;
++ parameter.value.ptr=NULL;
++ sig.algor->parameter= &parameter;
++
++ sig.digest= &digest;
++ sig.digest->data=(unsigned char *)m;
++ sig.digest->length=m_len;
++
++ i=i2d_X509_SIG(&sig,NULL);
++ }
++
++ j=RSA_size(rsa);
++ if ((i-RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s=(unsigned char *)OPENSSL_malloc((unsigned int)j+1);
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p=s;
++ i2d_X509_SIG(&sig,&p);
++ }
++
++ if ((sp = pk11_get_session()) == NULL)
++ goto err;
++
++ check_new_rsa_key(sp, (void *) rsa);
++
++ h_priv_key = sp->rsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->rsa_priv_key =
++ pk11_get_private_rsa_key((RSA *)rsa, sp);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_SIGNINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ ulsiglen = j;
++ rv = pFuncList->C_Sign(sp->session, s, i, sigret,
++ (CK_ULONG_PTR) &ulsiglen);
++ *siglen = ulsiglen;
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_SIGN, PK11_R_SIGN);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if (type != NID_md5_sha1)
++ {
++ memset(s,0,(unsigned int)j+1);
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp);
++ return ret;
++ }
++
++static int pk11_RSA_verify(int type, const unsigned char *m,
++ unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
++ const RSA *rsa)
++ {
++ X509_SIG sig;
++ ASN1_TYPE parameter;
++ int i,j;
++ unsigned char *p,*s = NULL;
++ X509_ALGOR algor;
++ ASN1_OCTET_STRING digest;
++ CK_RV rv;
++ CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
++ CK_MECHANISM *p_mech = &mech_rsa;
++ CK_OBJECT_HANDLE h_pub_key;
++ PK11_SESSION *sp = NULL;
++ int ret = 0;
++ char tmp_buf[20];
++
++ /* Encode the digest */
++ /* Special case: SSL signature, just check the length */
++ if (type == NID_md5_sha1)
++ {
++ if (m_len != SSL_SIG_LENGTH)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_INVALID_MESSAGE_LENGTH);
++ goto err;
++ }
++ i = SSL_SIG_LENGTH;
++ s = (unsigned char *)m;
++ }
++ else
++ {
++ sig.algor= &algor;
++ sig.algor->algorithm=OBJ_nid2obj(type);
++ if (sig.algor->algorithm == NULL)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_UNKNOWN_ALGORITHM_TYPE);
++ goto err;
++ }
++ if (sig.algor->algorithm->length == 0)
++ {
++ PK11err(PK11_F_RSA_VERIFY,
++ PK11_R_UNKNOWN_ASN1_OBJECT_ID);
++ goto err;
++ }
++ parameter.type=V_ASN1_NULL;
++ parameter.value.ptr=NULL;
++ sig.algor->parameter= &parameter;
++ sig.digest= &digest;
++ sig.digest->data=(unsigned char *)m;
++ sig.digest->length=m_len;
++ i=i2d_X509_SIG(&sig,NULL);
++ }
++
++ j=RSA_size(rsa);
++ if ((i-RSA_PKCS1_PADDING) > j)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG);
++ goto err;
++ }
++
++ if (type != NID_md5_sha1)
++ {
++ s=(unsigned char *)OPENSSL_malloc((unsigned int)j+1);
++ if (s == NULL)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ p=s;
++ i2d_X509_SIG(&sig,&p);
++ }
++
++ if ((sp = pk11_get_session()) == NULL)
++ goto err;
++
++ check_new_rsa_key(sp, (void *) rsa);
++
++ h_pub_key = sp->rsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->rsa_pub_key =
++ pk11_get_public_rsa_key((RSA *)rsa, sp);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ rv = pFuncList->C_Verify(sp->session, s, i, sigbuf,
++ (CK_ULONG)siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_RSA_VERIFY, PK11_R_VERIFY);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ ret = 1;
++ }
++
++err:
++ if (type != NID_md5_sha1)
++ {
++ memset(s,0,(unsigned int)siglen);
++ OPENSSL_free(s);
++ }
++
++ pk11_return_session(sp);
++ return ret;
++ }
++
++static int hndidx_rsa = -1;
++
++struct key_info {
++ CK_OBJECT_HANDLE handle;
++ CK_SESSION_HANDLE session;
++};
++
++/* Destroy the object when the last reference to it has gone.
++ */
++static void hndidx_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
++ int ind, long argl, void *argp)
++{
++ struct key_info *key_info = item;
++ CK_RV rv;
++ char tmp_buf[20];
++
++ if (key_info != NULL)
++ {
++ rv = pFuncList->C_DestroyObject(key_info->session,
++ key_info->handle);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ }
++ free(item);
++ }
++}
++
++EVP_PKEY *pk11_load_privkey(ENGINE* e, const char* privkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey=NULL;
++ FILE *privkey;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++ RSA *rsa;
++ PK11_SESSION *sp;
++ /* everything else below needed for key by reference extension */
++ char tmp_buf[20];
++ CK_RV rv;
++ CK_ULONG objcnt = 0;
++ CK_BBOOL is_token = TRUE;
++ CK_BYTE attr_data[2][1024];
++ CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++ struct key_info *key_info = NULL;
++ extern char *pk11_pin;
++
++ /* we look for private keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /* these attributes are needed to initialize OpenSSL RSA structure */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], 1024}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], 1024}, /* e */
++ };
++
++ if ((sp = pk11_get_session()) == NULL)
++ return NULL;
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(privkey_file, "pkcs11:") == privkey_file)
++ {
++ search_templ[2].pValue = strstr(privkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++ if (pk11_pin == NULL)
++#ifndef OPENCRYPTOKI
++ pk11_pin = getpassphrase("Enter PIN: ");
++#else
++ pk11_pin = getpass("Enter PIN: ");
++#endif
++ if ((rv = pFuncList->C_Login(sp->session, CKU_USER, (CK_UTF8CHAR*)pk11_pin,
++ strlen(pk11_pin))) != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN)
++ {
++ fprintf(stderr, "C_Login -> %lx\n", rv);
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_INVALID_PIN);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++ if ((rv = pFuncList->C_FindObjectsInit(sp->session,
++ search_templ, 3)) != CKR_OK)
++ {
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_FINDOBJECTSINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(sp->session, &ks_key, 1, &objcnt);
++ if (rv != CKR_OK)
++ {
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_FINDOBJECTS);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (objcnt > 1)
++ {
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_TOO_MANY_OBJECTS);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lu", objcnt);
++ ERR_add_error_data(2,
++ "PK11 too many objects:", tmp_buf);
++ goto err;
++ }
++
++ if (objcnt != 1)
++ {
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_OBJECT_NOT_FOUND);
++ ERR_add_error_data(1, "PK11 object not found");
++ goto err;
++ }
++
++ (void) pFuncList->C_FindObjectsFinal(sp->session);
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++
++ if (hndidx_rsa == -1)
++ hndidx_rsa = RSA_get_ex_new_index(0,
++ "pkcs11 RSA HSM key handle",
++ NULL, NULL, hndidx_free);
++
++ key_info = malloc(sizeof(struct key_info));
++ if (key_info == NULL)
++ goto err;
++
++ pkey = EVP_PKEY_new();
++ if (pkey == NULL)
++ goto err;
++
++ rsa = RSA_new();
++ if (rsa == NULL) {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ goto err;
++ }
++ EVP_PKEY_set1_RSA(pkey, rsa);
++
++ if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 2)) != CKR_OK)
++ {
++ PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_GETATTRIBUTVALUE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->meth = &pk11_rsa;
++ rsa->engine = e;
++ rsa->references = 2;
++ rsa->flags = RSA_FLAG_SIGN_VER | RSA_FLAG_EXT_PKEY;
++ key_info->handle = ks_key;
++ key_info->session = sp->session;
++ RSA_set_ex_data(rsa, hndidx_rsa, key_info);
++ key_info = NULL;
++ sp->rsa = rsa;
++ sp->rsa_priv_key = ks_key;
++
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++#ifdef OPENCRYPTOKI
++ /* openCryptoki bug workaround */
++ if (get_templ[1].ulValueLen == 0) {
++ get_templ[1].ulValueLen = 1;
++ attr_data[1][0] = 3;
++ }
++#endif
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++ }
++ else if ((privkey=fopen(privkey_file,"r")) != NULL)
++ {
++ pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL);
++ fclose(privkey);
++ if (pkey)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++
++ if (rsa)
++ {
++ check_new_rsa_key(sp, (void *) rsa);
++
++ h_priv_key = pk11_get_private_rsa_key(rsa,
++ sp);
++ if (h_priv_key == CK_INVALID_HANDLE)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ }
++ else
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ }
++ }
++
++err:
++ if (key_info != NULL)
++ free(key_info);
++ pk11_return_session(sp);
++ return(pkey);
++ }
++
++EVP_PKEY *pk11_load_pubkey(ENGINE* e, const char* pubkey_file,
++ UI_METHOD *ui_method, void *callback_data)
++ {
++ EVP_PKEY *pkey=NULL;
++ FILE *pubkey;
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ RSA *rsa;
++ PK11_SESSION *sp;
++ /* everything else below needed for key by reference extension */
++ char tmp_buf[20];
++ CK_RV rv;
++ CK_ULONG objcnt = 0;
++ CK_BBOOL is_token = TRUE;
++ CK_BYTE attr_data[2][1024];
++ CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */
++ extern char *pk11_pin;
++
++ /* we look for private keys only */
++ CK_ATTRIBUTE search_templ[] =
++ {
++ {CKA_TOKEN, &is_token, sizeof(is_token)},
++ {CKA_CLASS, &key_class, sizeof(key_class)},
++ {CKA_LABEL, NULL, 0}
++ };
++
++ /* these attributes are needed to initialize OpenSSL RSA structure */
++ CK_ATTRIBUTE get_templ[] =
++ {
++ {CKA_MODULUS, (void *)attr_data[0], 1024}, /* n */
++ {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], 1024}, /* e */
++ };
++
++ if ((sp = pk11_get_session()) == NULL)
++ return NULL;
++
++ /*
++ * Use simple scheme "pkcs11:<KEY_LABEL>" for now.
++ */
++ if (strstr(pubkey_file, "pkcs11:") == pubkey_file)
++ {
++ search_templ[2].pValue = strstr(pubkey_file, ":") + 1;
++ search_templ[2].ulValueLen = strlen(search_templ[2].pValue);
++
++#define ALLWAYS_LOGIN
++#ifdef ALLWAYS_LOGIN
++ if (pk11_pin == NULL)
++#ifndef OPENCRYPTOKI
++ pk11_pin = getpassphrase("Enter PIN: ");
++#else
++ pk11_pin = getpass("Enter PIN: ");
++#endif
++ if ((rv = pFuncList->C_Login(sp->session, CKU_USER, (CK_UTF8CHAR*)pk11_pin,
++ strlen(pk11_pin))) != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN)
++ {
++ fprintf(stderr, "C_Login -> %lx\n", rv);
++ PK11err(PK11_F_LOAD_PUBKEY, PK11_R_INVALID_PIN);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++#endif
++
++ CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE);
++ if (pFuncList->C_FindObjectsInit(sp->session, search_templ, 3) != CKR_OK)
++ {
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++ PK11err(PK11_F_LOAD_PUBKEY, PK11_R_FINDOBJECTSINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ rv = pFuncList->C_FindObjects(sp->session, &ks_key, 1, &objcnt);
++ if (rv != CKR_OK)
++ {
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++ PK11err(PK11_F_LOAD_PUBKEY, PK11_R_FINDOBJECTS);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (objcnt > 1)
++ {
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++ PK11err(PK11_F_LOAD_PUBKEY, PK11_R_TOO_MANY_OBJECTS);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lu", objcnt);
++ ERR_add_error_data(2,
++ "PK11 too many objects:", tmp_buf);
++ goto err;
++ }
++
++ if (objcnt != 1)
++ {
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++ PK11err(PK11_F_LOAD_PUBKEY, PK11_R_OBJECT_NOT_FOUND);
++ ERR_add_error_data(1, "PK11 object not found");
++ goto err;
++ }
++
++ (void) pFuncList->C_FindObjectsFinal(sp->session);
++ CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE);
++
++ sp->rsa_pub_key = ks_key;
++ pkey = malloc(sizeof(EVP_PKEY));
++ bzero(pkey, sizeof(EVP_PKEY));
++ pkey->type = EVP_PKEY_RSA;
++ pkey->references = 1;
++
++ rsa = pkey->pkey.rsa = sp->rsa = malloc(sizeof(RSA));
++ bzero(rsa, sizeof(RSA));
++
++ if (pFuncList->C_GetAttributeValue(sp->session, ks_key,
++ get_templ, 3) != CKR_OK)
++ {
++ PK11err(PK11_F_LOAD_PUBKEY, PK11_R_GETATTRIBUTVALUE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ /*
++ * Now we have to initialize an OpenSSL RSA structure,
++ * everything else is 0 or NULL.
++ */
++ rsa->meth = &pk11_rsa;
++ rsa->engine = e;
++ rsa->references = 2;
++ rsa->flags = RSA_FLAG_SIGN_VER;
++
++ attr_to_BN(&get_templ[0], attr_data[0], &rsa->n);
++ attr_to_BN(&get_templ[1], attr_data[1], &rsa->e);
++ }
++ else if ((pubkey=fopen(pubkey_file,"r")) != NULL)
++ {
++ pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
++ fclose(pubkey);
++ if (pkey)
++ {
++ rsa = EVP_PKEY_get1_RSA(pkey);
++ if (rsa)
++ {
++ check_new_rsa_key(sp, (void *) rsa);
++
++ h_pub_key = pk11_get_public_rsa_key(rsa, sp);
++ if (h_pub_key == CK_INVALID_HANDLE)
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ }
++ else
++ {
++ EVP_PKEY_free(pkey);
++ pkey = NULL;
++ }
++ }
++ }
++
++err:
++ pk11_return_session(sp);
++ return(pkey);
++ }
++
++/* Create a public key object in a session from a given rsa structure.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 7;
++ char tmp_buf[20];
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof(CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof(CK_KEY_TYPE)},
++ {CKA_TOKEN, &false, sizeof(true)},
++ {CKA_ENCRYPT, &true, sizeof(true)},
++ {CKA_VERIFY_RECOVER, &true, sizeof(true)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}
++ };
++
++ int i;
++ CK_SESSION_HANDLE session = sp->session;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ a_key_template[5].ulValueLen = BN_num_bytes(rsa->n);
++ a_key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[5].ulValueLen);
++ if (a_key_template[5].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ BN_bn2bin(rsa->n, a_key_template[5].pValue);
++
++ a_key_template[6].ulValueLen = BN_num_bytes(rsa->e);
++ a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)a_key_template[6].ulValueLen);
++ if (a_key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ BN_bn2bin(rsa->e, a_key_template[6].pValue);
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_FINDOBJECTSINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_FINDOBJECTS);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_FINDOBJECTSFINAL);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PUB_RSA_KEY,
++ PK11_R_CREATEOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ }
++
++ sp->rsa = rsa;
++
++ err:
++ for (i = 5; i <= 6; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return h_key;
++
++ }
++
++/* Create a private key object in the session from a given rsa structure
++ */
++static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ int i;
++ CK_ULONG found;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE k_type = CKK_RSA;
++ CK_ULONG ul_key_attr_count = 14;
++ char tmp_buf[20];
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys
++ */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof(CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof(CK_KEY_TYPE)},
++ {CKA_TOKEN, &false, sizeof(true)},
++ {CKA_SENSITIVE, &false, sizeof(true)},
++ {CKA_DECRYPT, &true, sizeof(true)},
++ {CKA_SIGN, &true, sizeof(true)},
++ {CKA_MODULUS, (void *)NULL, 0},
++ {CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
++ {CKA_PRIME_1, (void *)NULL, 0},
++ {CKA_PRIME_2, (void *)NULL, 0},
++ {CKA_EXPONENT_1, (void *)NULL, 0},
++ {CKA_EXPONENT_2, (void *)NULL, 0},
++ {CKA_COEFFICIENT, (void *)NULL, 0}
++ };
++ CK_SESSION_HANDLE session = sp->session;
++
++ if ((rsa->flags & RSA_FLAG_EXT_PKEY) != 0) {
++ sp->rsa = rsa;
++ return (*(CK_OBJECT_HANDLE_PTR)RSA_get_ex_data(rsa, hndidx_rsa));
++ }
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template */
++ if (init_template_value(rsa->n, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(rsa->e, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(rsa->d, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0 ||
++ init_template_value(rsa->p, &a_key_template[9].pValue,
++ &a_key_template[9].ulValueLen) == 0 ||
++ init_template_value(rsa->q, &a_key_template[10].pValue,
++ &a_key_template[10].ulValueLen) == 0 ||
++ init_template_value(rsa->dmp1, &a_key_template[11].pValue,
++ &a_key_template[11].ulValueLen) == 0 ||
++ init_template_value(rsa->dmq1, &a_key_template[12].pValue,
++ &a_key_template[12].ulValueLen) == 0 ||
++ init_template_value(rsa->iqmp, &a_key_template[13].pValue,
++ &a_key_template[13].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_FINDOBJECTSINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_FINDOBJECTS);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_FINDOBJECTSFINAL);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PRIV_RSA_KEY,
++ PK11_R_CREATEOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ }
++
++ sp->rsa = rsa;
++
++ err:
++ /* 6 to 13 entries in the key template are key components
++ * They need to be freed apon exit or error.
++ */
++ for (i = 6; i <= 13; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return h_key;
++ }
++
++#endif
++
++
++#ifndef OPENSSL_NO_DSA
++/* The DSA function implementation
++ */
++static int pk11_DSA_init(DSA *dsa)
++ {
++ return 1;
++ }
++
++
++static int pk11_DSA_finish(DSA *dsa)
++ {
++ return pk11_destroy_dsa_key_objects(NULL);
++ }
++
++
++static DSA_SIG *
++pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
++ {
++ BIGNUM *r = NULL, *s = NULL;
++ int i;
++ DSA_SIG *dsa_sig = NULL;
++
++ CK_RV rv;
++ CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
++ CK_MECHANISM *p_mech = &Mechanism_dsa;
++ CK_OBJECT_HANDLE h_priv_key;
++
++ /* The signature is the concatenation of r and s,
++ * each is 20 bytes long
++ */
++ unsigned char sigret[DSA_SIGNATURE_LEN];
++ unsigned long siglen = DSA_SIGNATURE_LEN;
++ unsigned int siglen2 = DSA_SIGNATURE_LEN / 2;
++
++ PK11_SESSION *sp = NULL;
++ char tmp_buf[20];
++
++ if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT);
++ goto ret;
++ }
++
++ i=BN_num_bytes(dsa->q); /* should be 20 */
++ if (dlen > i)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH);
++ goto ret;
++ }
++
++ if ((sp = pk11_get_session()) == NULL)
++ goto ret;
++
++ check_new_dsa_key(sp, (void *) dsa);
++
++ h_priv_key = sp->dsa_priv_key;
++ if (h_priv_key == CK_INVALID_HANDLE)
++ h_priv_key = sp->dsa_priv_key =
++ pk11_get_private_dsa_key((DSA *)dsa, sp);
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_SIGNINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto ret;
++ }
++
++ memset(sigret, 0, siglen);
++ rv = pFuncList->C_Sign(sp->session,
++ (unsigned char*) dgst, dlen, sigret,
++ (CK_ULONG_PTR) &siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_SIGN);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto ret;
++ }
++ }
++
++
++ if ((s = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if ((r = BN_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ if ((dsa_sig = DSA_SIG_new()) == NULL)
++ {
++ PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
++ goto ret;
++ }
++
++ BN_bin2bn(sigret, siglen2, r);
++ BN_bin2bn(&sigret[siglen2], siglen2, s);
++
++ dsa_sig->r = r;
++ dsa_sig->s = s;
++
++ret:
++ if (dsa_sig == NULL)
++ {
++ if (r != NULL)
++ BN_free(r);
++ if (s != NULL)
++ BN_free(s);
++ }
++
++ pk11_return_session(sp);
++ return (dsa_sig);
++ }
++
++static int
++pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig,
++ DSA *dsa)
++ {
++ int i;
++ CK_RV rv;
++ int retval = 0;
++ CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
++ CK_MECHANISM *p_mech = &Mechanism_dsa;
++ CK_OBJECT_HANDLE h_pub_key;
++
++ unsigned char sigbuf[DSA_SIGNATURE_LEN];
++ unsigned long siglen = DSA_SIGNATURE_LEN;
++ unsigned long siglen2 = DSA_SIGNATURE_LEN/2;
++
++ PK11_SESSION *sp = NULL;
++ char tmp_buf[20];
++
++ if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_DSA_SIGNATURE_R);
++ goto ret;
++ }
++
++ if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_DSA_SIGNATURE_S);
++ goto ret;
++ }
++
++ i = BN_num_bytes(dsa->q); /* should be 20 */
++
++ if (dlen > i)
++ {
++ PK11err(PK11_F_DSA_VERIFY,
++ PK11_R_INVALID_SIGNATURE_LENGTH);
++ goto ret;
++ }
++
++ if ((sp = pk11_get_session()) == NULL)
++ goto ret;
++
++ check_new_dsa_key(sp, (void *) dsa);
++
++ h_pub_key = sp->dsa_pub_key;
++ if (h_pub_key == CK_INVALID_HANDLE)
++ h_pub_key = sp->dsa_pub_key =
++ pk11_get_public_dsa_key((DSA *)dsa, sp);
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_VerifyInit(sp->session, p_mech,
++ h_pub_key);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto ret;
++ }
++
++ memset(sigbuf, 0, siglen);
++ BN_bn2bin(sig->r, sigbuf);
++ BN_bn2bin(sig->s, &sigbuf[siglen2]);
++
++ rv = pFuncList->C_Verify(sp->session,
++ (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DSA_VERIFY, PK11_R_VERIFY);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto ret;
++ }
++ }
++
++ retval = 1;
++ret:
++
++ pk11_return_session(sp);
++ return retval;
++ }
++
++
++/* Create a public key object in a session from a given dsa structure.
++ */
++static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_ULONG found;
++ CK_KEY_TYPE k_type = CKK_DSA;
++ CK_ULONG ul_key_attr_count = 8;
++ int i;
++ char tmp_buf[20];
++
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof(CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof(CK_KEY_TYPE)},
++ {CKA_TOKEN, &false, sizeof(true)},
++ {CKA_VERIFY, &true, sizeof(true)},
++ {CKA_PRIME, (void *)NULL, 0}, /* p */
++ {CKA_SUBPRIME, (void *)NULL, 0}, /* q */
++ {CKA_BASE, (void *)NULL, 0}, /* g */
++ {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */
++ };
++ CK_SESSION_HANDLE session = sp->session;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ if (init_template_value(dsa->p, &a_key_template[4].pValue,
++ &a_key_template[4].ulValueLen) == 0 ||
++ init_template_value(dsa->q, &a_key_template[5].pValue,
++ &a_key_template[5].ulValueLen) == 0 ||
++ init_template_value(dsa->g, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(dsa->pub_key, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_FINDOBJECTSINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_FINDOBJECTS);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_FINDOBJECTSFINAL);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PUB_DSA_KEY,
++ PK11_R_CREATEOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ }
++
++ sp->dsa = dsa;
++
++ err:
++ for (i = 4; i <= 7; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return h_key;
++
++ }
++
++/* Create a private key object in the session from a given dsa structure
++ */
++static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
++ int i;
++ char tmp_buf[20];
++ CK_ULONG found;
++ CK_KEY_TYPE k_type = CKK_DSA;
++ CK_ULONG ul_key_attr_count = 9;
++
++ /* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys
++ */
++ CK_ATTRIBUTE a_key_template[] =
++ {
++ {CKA_CLASS, (void *) NULL, sizeof(CK_OBJECT_CLASS)},
++ {CKA_KEY_TYPE, (void *) NULL, sizeof(CK_KEY_TYPE)},
++ {CKA_TOKEN, &false, sizeof(true)},
++ {CKA_SENSITIVE, &false, sizeof(true)},
++ {CKA_SIGN, &true, sizeof(true)},
++ {CKA_PRIME, (void *)NULL, 0}, /* p */
++ {CKA_SUBPRIME, (void *)NULL, 0}, /* q */
++ {CKA_BASE, (void *)NULL, 0}, /* g */
++ {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */
++ };
++ CK_SESSION_HANDLE session = sp->session;
++
++ a_key_template[0].pValue = &o_key;
++ a_key_template[1].pValue = &k_type;
++
++ /* Put the private key components into the template
++ */
++ if (init_template_value(dsa->p, &a_key_template[5].pValue,
++ &a_key_template[5].ulValueLen) == 0 ||
++ init_template_value(dsa->q, &a_key_template[6].pValue,
++ &a_key_template[6].ulValueLen) == 0 ||
++ init_template_value(dsa->g, &a_key_template[7].pValue,
++ &a_key_template[7].ulValueLen) == 0 ||
++ init_template_value(dsa->priv_key, &a_key_template[8].pValue,
++ &a_key_template[8].ulValueLen) == 0)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsInit(session, a_key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_FINDOBJECTSINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_FINDOBJECTS);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_FINDOBJECTSFINAL);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ a_key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_PRIV_DSA_KEY,
++ PK11_R_CREATEOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ }
++
++ sp->dsa = dsa;
++
++err:
++ /* 5 to 8 entries in the key template are key components
++ * They need to be freed apon exit or error.
++ */
++ for (i = 5; i <= 8; i++)
++ {
++ if (a_key_template[i].pValue != NULL)
++ {
++ memset(a_key_template[i].pValue, 0,
++ a_key_template[i].ulValueLen);
++ OPENSSL_free(a_key_template[i].pValue);
++ a_key_template[i].pValue = NULL;
++ }
++ }
++
++ return h_key;
++
++ }
++#endif
++
++
++#ifndef OPENSSL_NO_DH
++
++/* The DH function implementation
++ */
++static int pk11_DH_init(DH *dh)
++ {
++ return 1;
++ }
++
++
++static int pk11_DH_finish(DH *dh)
++ {
++ return pk11_destroy_dh_key_objects(NULL);
++ }
++
++static int pk11_DH_generate_key(DH *dh)
++ {
++ CK_ULONG i;
++ CK_RV rv, rv1;
++ int ret = 0;
++ PK11_SESSION *sp = NULL;
++ char tmp_buf[20];
++ CK_BYTE_PTR reuse_mem;
++
++ CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0};
++ CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
++
++ CK_ULONG ul_pub_key_attr_count = 3;
++ CK_ATTRIBUTE pub_key_template[] =
++ {
++ {CKA_PRIVATE, &false, sizeof(false)},
++ {CKA_PRIME, (void *)NULL, 0},
++ {CKA_BASE, (void *)NULL, 0}
++ };
++
++ CK_ULONG ul_priv_key_attr_count = 3;
++ CK_ATTRIBUTE priv_key_template[] =
++ {
++ {CKA_PRIVATE, &false, sizeof(false)},
++ {CKA_SENSITIVE, &false, sizeof(false)},
++ {CKA_DERIVE, &true, sizeof(true)}
++ };
++
++ CK_ULONG pub_key_attr_result_count = 1;
++ CK_ATTRIBUTE pub_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ CK_ULONG priv_key_attr_result_count = 1;
++ CK_ATTRIBUTE priv_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ pub_key_template[1].ulValueLen = BN_num_bytes(dh->p);
++ if (pub_key_template[1].ulValueLen > 0)
++ {
++ pub_key_template[1].pValue =
++ OPENSSL_malloc(pub_key_template[1].ulValueLen);
++ if (pub_key_template[1].pValue == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ i = BN_bn2bin(dh->p, pub_key_template[1].pValue);
++ }
++ else
++ goto err;
++
++ pub_key_template[2].ulValueLen = BN_num_bytes(dh->g);
++ if (pub_key_template[2].ulValueLen > 0)
++ {
++ pub_key_template[2].pValue =
++ OPENSSL_malloc(pub_key_template[2].ulValueLen);
++ if (pub_key_template[2].pValue == NULL)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ i = BN_bn2bin(dh->g, pub_key_template[2].pValue);
++ }
++ else
++ goto err;
++
++ if ((sp = pk11_get_session()) == NULL)
++ goto err;
++
++ rv = pFuncList->C_GenerateKeyPair(sp->session,
++ &mechanism,
++ pub_key_template,
++ ul_pub_key_attr_count,
++ priv_key_template,
++ ul_priv_key_attr_count,
++ &h_pub_key,
++ &h_priv_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ /* Reuse the larger memory allocated. We know the larger memory
++ * is sufficient for reuse */
++ if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen)
++ reuse_mem = pub_key_template[1].pValue;
++ else
++ reuse_mem = pub_key_template[2].pValue;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
++ pub_key_result, pub_key_attr_result_count);
++ rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK || rv1 != CKR_OK)
++ {
++ rv = (rv != CKR_OK) ? rv : rv1;
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 ||
++ ((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE);
++ goto err;
++ }
++
++ /* Reuse the memory allocated */
++ pub_key_result[0].pValue = reuse_mem;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
++ pub_key_result, pub_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (pub_key_result[0].type == CKA_VALUE)
++ {
++ if (dh->pub_key == NULL)
++ dh->pub_key = BN_new();
++ dh->pub_key = BN_bin2bn(pub_key_result[0].pValue,
++ pub_key_result[0].ulValueLen, dh->pub_key);
++ }
++
++ /* Reuse the memory allocated */
++ priv_key_result[0].pValue = reuse_mem;
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (priv_key_result[0].type == CKA_VALUE)
++ {
++ if (dh->priv_key == NULL)
++ dh->priv_key = BN_new();
++ dh->priv_key = BN_bin2bn(priv_key_result[0].pValue,
++ priv_key_result[0].ulValueLen, dh->priv_key);
++ }
++
++ ret = 1;
++
++err:
++
++ if (h_pub_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_pub_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_DESTROYOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ }
++ }
++
++ if (h_priv_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_priv_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DH_GEN_KEY, PK11_R_DESTROYOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ }
++ }
++
++ for (i = 1; i <= 2; i++)
++ {
++ if (pub_key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(pub_key_template[i].pValue);
++ pub_key_template[i].pValue = NULL;
++ }
++ }
++
++ pk11_return_session(sp);
++ return ret;
++ }
++
++static int pk11_DH_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh)
++ {
++ int i;
++ CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0};
++ CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
++ CK_KEY_TYPE key_type = CKK_GENERIC_SECRET;
++ CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++
++ CK_ULONG ul_priv_key_attr_count = 2;
++ CK_ATTRIBUTE priv_key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof(key_class)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof(key_type)},
++ };
++
++ CK_ULONG priv_key_attr_result_count = 1;
++ CK_ATTRIBUTE priv_key_result[] =
++ {
++ {CKA_VALUE, (void *)NULL, 0}
++ };
++
++ CK_RV rv;
++ int ret = 0;
++ PK11_SESSION *sp = NULL;
++ char tmp_buf[20];
++
++ priv_key_template[0].pValue = &key_class;
++ priv_key_template[1].pValue = &key_type;
++
++ if ((sp = pk11_get_session()) == NULL)
++ goto err;
++
++ mechanism.ulParameterLen = BN_num_bytes(pub_key);
++ mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen);
++ if (mechanism.pParameter == NULL)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++ BN_bn2bin(pub_key, mechanism.pParameter);
++
++ check_new_dh_key(sp, dh);
++
++ h_key = sp->dh_key;
++ if (h_key == CK_INVALID_HANDLE)
++ h_key = sp->dh_key = pk11_get_dh_key((DH*) dh, sp);
++
++ if (h_key == CK_INVALID_HANDLE)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT);
++ goto err;
++ }
++
++ rv = pFuncList->C_DeriveKey(sp->session,
++ &mechanism,
++ h_key,
++ priv_key_template,
++ ul_priv_key_attr_count,
++ &h_derived_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE);
++ goto err;
++ }
++ priv_key_result[0].pValue =
++ OPENSSL_malloc(priv_key_result[0].ulValueLen);
++ if (!priv_key_result[0].pValue)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
++ priv_key_result, priv_key_attr_result_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ /* OpenSSL allocates the output buffer 'key' which is the same
++ * length of the public key. It is long enough for the derived key */
++ if (priv_key_result[0].type == CKA_VALUE)
++ {
++ /* CKM_DH_PKCS_DERIVE mechanism is not supposed to strip
++ * leading zeros from a computed shared secret. However,
++ * OpenSSL always did it so we must do the same here. The
++ * vagueness of the spec regarding leading zero bytes was
++ * finally cleared with TLS 1.1 (RFC 4346) saying that leading
++ * zeros are stripped before the computed data is used as the
++ * pre-master secret.
++ */
++ for (i = 0; i < priv_key_result[0].ulValueLen; ++i)
++ {
++ if (((char *) priv_key_result[0].pValue)[i] != 0)
++ break;
++ }
++
++ memcpy(key, ((char *) priv_key_result[0].pValue) + i,
++ priv_key_result[0].ulValueLen - i);
++ ret = priv_key_result[0].ulValueLen - i;
++ }
++
++err:
++
++ if (h_derived_key != CK_INVALID_HANDLE)
++ {
++ rv = pFuncList->C_DestroyObject(sp->session, h_derived_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_DH_COMP_KEY, PK11_R_DESTROYOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ }
++ }
++ if (priv_key_result[0].pValue)
++ {
++ OPENSSL_free(priv_key_result[0].pValue);
++ priv_key_result[0].pValue = NULL;
++ }
++
++ if (mechanism.pParameter)
++ {
++ OPENSSL_free(mechanism.pParameter);
++ mechanism.pParameter = NULL;
++ }
++
++ pk11_return_session(sp);
++ return ret;
++ }
++
++
++static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, PK11_SESSION *sp)
++ {
++ CK_RV rv;
++ CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
++ CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
++ CK_KEY_TYPE key_type = CKK_DH;
++ CK_ULONG found;
++ int i;
++ char tmp_buf[20];
++
++ CK_ULONG ul_key_attr_count = 7;
++ CK_ATTRIBUTE key_template[] =
++ {
++ {CKA_CLASS, (void*) NULL, sizeof(class)},
++ {CKA_KEY_TYPE, (void*) NULL, sizeof(key_type)},
++ {CKA_DERIVE, &true, sizeof(true)},
++ {CKA_PRIVATE, &false, sizeof(false)},
++ {CKA_PRIME, (void *) NULL, 0},
++ {CKA_BASE, (void *) NULL, 0},
++ {CKA_VALUE, (void *) NULL, 0},
++ };
++
++ CK_SESSION_HANDLE session = sp->session;
++
++ key_template[0].pValue = &class;
++ key_template[1].pValue = &key_type;
++
++ key_template[4].ulValueLen = BN_num_bytes(dh->p);
++ key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[4].ulValueLen);
++ if (key_template[4].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ BN_bn2bin(dh->p, key_template[4].pValue);
++
++ key_template[5].ulValueLen = BN_num_bytes(dh->g);
++ key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[5].ulValueLen);
++ if (key_template[5].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ BN_bn2bin(dh->g, key_template[5].pValue);
++
++ key_template[6].ulValueLen = BN_num_bytes(dh->priv_key);
++ key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
++ (size_t)key_template[6].ulValueLen);
++ if (key_template[6].pValue == NULL)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
++ goto err;
++ }
++
++ BN_bn2bin(dh->priv_key, key_template[6].pValue);
++
++ rv = pFuncList->C_FindObjectsInit(session, key_template,
++ ul_key_attr_count);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ rv = pFuncList->C_FindObjectsFinal(session);
++
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++
++ if (found == 0)
++ {
++ rv = pFuncList->C_CreateObject(session,
++ key_template, ul_key_attr_count, &h_key);
++ if (rv != CKR_OK)
++ {
++ PK11err(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT);
++ snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv);
++ ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf);
++ goto err;
++ }
++ }
++
++ sp->dh = dh;
++
++ err:
++ for (i = 4; i <= 6; i++)
++ {
++ if (key_template[i].pValue != NULL)
++ {
++ OPENSSL_free(key_template[i].pValue);
++ key_template[i].pValue = NULL;
++ }
++ }
++
++ return h_key;
++ }
++
++#endif
++
++/* Local function to simplify key template population
++ * Return 0 -- error, 1 -- no error
++ */
++static int init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value,
++ CK_ULONG *ul_value_len)
++ {
++ CK_ULONG len = BN_num_bytes(bn);
++ if (len == 0)
++ return 1;
++
++ *ul_value_len = len;
++ *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t) *ul_value_len);
++ if (*p_value == NULL)
++ return 0;
++
++ BN_bn2bin(bn, *p_value);
++
++ return 1;
++ }
++
++static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn)
++ {
++ if (attr->ulValueLen > 0)
++ {
++ *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL);
++ }
++ }
++
++static void check_new_rsa_key(PK11_SESSION *sp, void *rsa)
++ {
++ if (sp->rsa != rsa)
++ pk11_destroy_rsa_key_objects(sp);
++ }
++
++static void check_new_dsa_key(PK11_SESSION *sp, void *dsa)
++ {
++ if (sp->dsa != dsa)
++ pk11_destroy_dsa_key_objects(sp);
++ }
++
++static void check_new_dh_key(PK11_SESSION *sp, void *dh)
++ {
++ if (sp->dh != dh)
++ pk11_destroy_dh_key_objects(sp);
++ }
++
++
++#endif
++#endif
+diff -r -u -N openssl-0.9.8g/crypto/engine/Makefile openssl/crypto/engine/Makefile
+--- openssl-0.9.8g/crypto/engine/Makefile 2005-07-16 13:13:05.000000000 +0200
++++ openssl/crypto/engine/Makefile 2007-10-25 01:27:09.000000000 +0200
+@@ -21,12 +21,14 @@
+ eng_table.c eng_pkey.c eng_fat.c eng_all.c \
+ tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \
+ tb_cipher.c tb_digest.c \
+- eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c eng_padlock.c
++ eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c eng_padlock.c \
++ hw_pk11.c hw_pk11_pub.c
+ LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \
+ eng_table.o eng_pkey.o eng_fat.o eng_all.o \
+ tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \
+ tb_cipher.o tb_digest.o \
+- eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o eng_padlock.o
++ eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o eng_padlock.o \
++ hw_pk11.o hw_pk11_pub.o
+
+ SRC= $(LIBSRC)
+
+@@ -212,6 +214,54 @@
+ eng_table.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
+ eng_table.o: ../../include/openssl/symhacks.h ../cryptlib.h eng_int.h
+ eng_table.o: eng_table.c
++hw_pk11.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
++hw_pk11.o: ../../include/openssl/engine.h ../../include/openssl/ossl_typ.h
++hw_pk11.o: ../../include/openssl/bn.h ../../include/openssl/rsa.h
++hw_pk11.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
++hw_pk11.o: ../../include/openssl/crypto.h ../../include/openssl/stack.h
++hw_pk11.o: ../../include/openssl/safestack.h ../../include/openssl/opensslv.h
++hw_pk11.o: ../../include/openssl/symhacks.h ../../include/openssl/dsa.h
++hw_pk11.o: ../../include/openssl/dh.h ../../include/openssl/rand.h
++hw_pk11.o: ../../include/openssl/ui.h ../../include/openssl/err.h
++hw_pk11.o: ../../include/openssl/lhash.h ../../include/openssl/dso.h
++hw_pk11.o: ../../include/openssl/pem.h ../../include/openssl/evp.h
++hw_pk11.o: ../../include/openssl/md2.h ../../include/openssl/md4.h
++hw_pk11.o: ../../include/openssl/md5.h ../../include/openssl/sha.h
++hw_pk11.o: ../../include/openssl/ripemd.h ../../include/openssl/des.h
++hw_pk11.o: ../../include/openssl/des_old.h ../../include/openssl/ui_compat.h
++hw_pk11.o: ../../include/openssl/rc4.h ../../include/openssl/rc2.h
++hw_pk11.o: ../../crypto/rc5/rc5.h ../../include/openssl/blowfish.h
++hw_pk11.o: ../../include/openssl/cast.h ../../include/openssl/idea.h
++hw_pk11.o: ../../crypto/mdc2/mdc2.h ../../include/openssl/aes.h
++hw_pk11.o: ../../include/openssl/objects.h ../../include/openssl/obj_mac.h
++hw_pk11.o: ../../include/openssl/x509.h ../../include/openssl/buffer.h
++hw_pk11.o: ../../include/openssl/x509_vfy.h ../../include/openssl/pkcs7.h
++hw_pk11.o: ../../include/openssl/pem2.h ../cryptlib.h
++hw_pk11.o: ../../e_os.h hw_pk11_err.c hw_pk11_err.h hw_pk11.c
++hw_pk11_pub.o: ../../include/openssl/e_os2.h ../../include/openssl/opensslconf.h
++hw_pk11_pub.o: ../../include/openssl/engine.h ../../include/openssl/ossl_typ.h
++hw_pk11_pub.o: ../../include/openssl/bn.h ../../include/openssl/rsa.h
++hw_pk11_pub.o: ../../include/openssl/asn1.h ../../include/openssl/bio.h
++hw_pk11_pub.o: ../../include/openssl/crypto.h ../../include/openssl/stack.h
++hw_pk11_pub.o: ../../include/openssl/safestack.h ../../include/openssl/opensslv.h
++hw_pk11_pub.o: ../../include/openssl/symhacks.h ../../include/openssl/dsa.h
++hw_pk11_pub.o: ../../include/openssl/dh.h ../../include/openssl/rand.h
++hw_pk11_pub.o: ../../include/openssl/ui.h ../../include/openssl/err.h
++hw_pk11_pub.o: ../../include/openssl/lhash.h ../../include/openssl/dso.h
++hw_pk11_pub.o: ../../include/openssl/pem.h ../../include/openssl/evp.h
++hw_pk11_pub.o: ../../include/openssl/md2.h ../../include/openssl/md4.h
++hw_pk11_pub.o: ../../include/openssl/md5.h ../../include/openssl/sha.h
++hw_pk11_pub.o: ../../include/openssl/ripemd.h ../../include/openssl/des.h
++hw_pk11_pub.o: ../../include/openssl/des_old.h ../../include/openssl/ui_compat.h
++hw_pk11_pub.o: ../../include/openssl/rc4.h ../../include/openssl/rc2.h
++hw_pk11_pub.o: ../../crypto/rc5/rc5.h ../../include/openssl/blowfish.h
++hw_pk11_pub.o: ../../include/openssl/cast.h ../../include/openssl/idea.h
++hw_pk11_pub.o: ../../crypto/mdc2/mdc2.h ../../include/openssl/aes.h
++hw_pk11_pub.o: ../../include/openssl/objects.h ../../include/openssl/obj_mac.h
++hw_pk11_pub.o: ../../include/openssl/x509.h ../../include/openssl/buffer.h
++hw_pk11_pub.o: ../../include/openssl/x509_vfy.h ../../include/openssl/pkcs7.h
++hw_pk11_pub.o: ../../include/openssl/pem2.h ../cryptlib.h
++hw_pk11_pub.o: ../../e_os.h hw_pk11_err.c hw_pk11_err.h hw_pk11_pub.c
+ tb_cipher.o: ../../e_os.h ../../include/openssl/bio.h
+ tb_cipher.o: ../../include/openssl/buffer.h ../../include/openssl/crypto.h
+ tb_cipher.o: ../../include/openssl/e_os2.h ../../include/openssl/engine.h
+diff -r -u -N openssl-0.9.8g/crypto/engine/pkcs11f.h openssl/crypto/engine/pkcs11f.h
+--- openssl-0.9.8g/crypto/engine/pkcs11f.h 1970-01-01 01:00:00.000000000 +0100
++++ openssl/crypto/engine/pkcs11f.h 2007-10-25 01:27:09.000000000 +0200
+@@ -0,0 +1,912 @@
++/* pkcs11f.h include file for PKCS #11. */
++/* $Revision: 1.2 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* This header file contains pretty much everything about all the */
++/* Cryptoki function prototypes. Because this information is */
++/* used for more than just declaring function prototypes, the */
++/* order of the functions appearing herein is important, and */
++/* should not be altered. */
++
++/* General-purpose */
++
++/* C_Initialize initializes the Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Initialize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pInitArgs /* if this is not NULL_PTR, it gets
++ * cast to CK_C_INITIALIZE_ARGS_PTR
++ * and dereferenced */
++);
++#endif
++
++
++/* C_Finalize indicates that an application is done with the
++ * Cryptoki library. */
++CK_PKCS11_FUNCTION_INFO(C_Finalize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_VOID_PTR pReserved /* reserved. Should be NULL_PTR */
++);
++#endif
++
++
++/* C_GetInfo returns general information about Cryptoki. */
++CK_PKCS11_FUNCTION_INFO(C_GetInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_INFO_PTR pInfo /* location that receives information */
++);
++#endif
++
++
++/* C_GetFunctionList returns the function list. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FUNCTION_LIST_PTR_PTR ppFunctionList /* receives pointer to
++ * function list */
++);
++#endif
++
++
++
++/* Slot and token management */
++
++/* C_GetSlotList obtains a list of slots in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_BBOOL tokenPresent, /* only slots with tokens? */
++ CK_SLOT_ID_PTR pSlotList, /* receives array of slot IDs */
++ CK_ULONG_PTR pulCount /* receives number of slots */
++);
++#endif
++
++
++/* C_GetSlotInfo obtains information about a particular slot in
++ * the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the ID of the slot */
++ CK_SLOT_INFO_PTR pInfo /* receives the slot information */
++);
++#endif
++
++
++/* C_GetTokenInfo obtains information about a particular token
++ * in the system. */
++CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_TOKEN_INFO_PTR pInfo /* receives the token information */
++);
++#endif
++
++
++/* C_GetMechanismList obtains a list of mechanism types
++ * supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of token's slot */
++ CK_MECHANISM_TYPE_PTR pMechanismList, /* gets mech. array */
++ CK_ULONG_PTR pulCount /* gets # of mechs. */
++);
++#endif
++
++
++/* C_GetMechanismInfo obtains information about a particular
++ * mechanism possibly supported by a token. */
++CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_MECHANISM_TYPE type, /* type of mechanism */
++ CK_MECHANISM_INFO_PTR pInfo /* receives mechanism info */
++);
++#endif
++
++
++/* C_InitToken initializes a token. */
++CK_PKCS11_FUNCTION_INFO(C_InitToken)
++#ifdef CK_NEED_ARG_LIST
++/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
++(
++ CK_SLOT_ID slotID, /* ID of the token's slot */
++ CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */
++ CK_ULONG ulPinLen, /* length in bytes of the PIN */
++ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */
++);
++#endif
++
++
++/* C_InitPIN initializes the normal user's PIN. */
++CK_PKCS11_FUNCTION_INFO(C_InitPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */
++ CK_ULONG ulPinLen /* length in bytes of the PIN */
++);
++#endif
++
++
++/* C_SetPIN modifies the PIN of the user who is logged in. */
++CK_PKCS11_FUNCTION_INFO(C_SetPIN)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_UTF8CHAR_PTR pOldPin, /* the old PIN */
++ CK_ULONG ulOldLen, /* length of the old PIN */
++ CK_UTF8CHAR_PTR pNewPin, /* the new PIN */
++ CK_ULONG ulNewLen /* length of the new PIN */
++);
++#endif
++
++
++
++/* Session management */
++
++/* C_OpenSession opens a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_OpenSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID, /* the slot's ID */
++ CK_FLAGS flags, /* from CK_SESSION_INFO */
++ CK_VOID_PTR pApplication, /* passed to callback */
++ CK_NOTIFY Notify, /* callback function */
++ CK_SESSION_HANDLE_PTR phSession /* gets session handle */
++);
++#endif
++
++
++/* C_CloseSession closes a session between an application and a
++ * token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseSession)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CloseAllSessions closes all sessions with a token. */
++CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SLOT_ID slotID /* the token's slot */
++);
++#endif
++
++
++/* C_GetSessionInfo obtains information about the session. */
++CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_SESSION_INFO_PTR pInfo /* receives session info */
++);
++#endif
++
++
++/* C_GetOperationState obtains the state of the cryptographic operation
++ * in a session. */
++CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* gets state */
++ CK_ULONG_PTR pulOperationStateLen /* gets state length */
++);
++#endif
++
++
++/* C_SetOperationState restores the state of the cryptographic
++ * operation in a session. */
++CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pOperationState, /* holds state */
++ CK_ULONG ulOperationStateLen, /* holds state length */
++ CK_OBJECT_HANDLE hEncryptionKey, /* en/decryption key */
++ CK_OBJECT_HANDLE hAuthenticationKey /* sign/verify key */
++);
++#endif
++
++
++/* C_Login logs a user into a token. */
++CK_PKCS11_FUNCTION_INFO(C_Login)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_USER_TYPE userType, /* the user type */
++ CK_UTF8CHAR_PTR pPin, /* the user's PIN */
++ CK_ULONG ulPinLen /* the length of the PIN */
++);
++#endif
++
++
++/* C_Logout logs a user out from a token. */
++CK_PKCS11_FUNCTION_INFO(C_Logout)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Object management */
++
++/* C_CreateObject creates a new object. */
++CK_PKCS11_FUNCTION_INFO(C_CreateObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* the object's template */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phObject /* gets new object's handle. */
++);
++#endif
++
++
++/* C_CopyObject copies an object, creating a new object for the
++ * copy. */
++CK_PKCS11_FUNCTION_INFO(C_CopyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new object */
++ CK_ULONG ulCount, /* attributes in template */
++ CK_OBJECT_HANDLE_PTR phNewObject /* receives handle of copy */
++);
++#endif
++
++
++/* C_DestroyObject destroys an object. */
++CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject /* the object's handle */
++);
++#endif
++
++
++/* C_GetObjectSize gets the size of an object in bytes. */
++CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ULONG_PTR pulSize /* receives size of object */
++);
++#endif
++
++
++/* C_GetAttributeValue obtains the value of one or more object
++ * attributes. */
++CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs; gets vals */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_SetAttributeValue modifies the value of one or more object
++ * attributes */
++CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hObject, /* the object's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* specifies attrs and values */
++ CK_ULONG ulCount /* attributes in template */
++);
++#endif
++
++
++/* C_FindObjectsInit initializes a search for token and session
++ * objects that match a template. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_ATTRIBUTE_PTR pTemplate, /* attribute values to match */
++ CK_ULONG ulCount /* attrs in search template */
++);
++#endif
++
++
++/* C_FindObjects continues a search for token and session
++ * objects that match a template, obtaining additional object
++ * handles. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjects)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_OBJECT_HANDLE_PTR phObject, /* gets obj. handles */
++ CK_ULONG ulMaxObjectCount, /* max handles to get */
++ CK_ULONG_PTR pulObjectCount /* actual # returned */
++);
++#endif
++
++
++/* C_FindObjectsFinal finishes a search for token and session
++ * objects. */
++CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Encryption and decryption */
++
++/* C_EncryptInit initializes an encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the encryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of encryption key */
++);
++#endif
++
++
++/* C_Encrypt encrypts single-part data. */
++CK_PKCS11_FUNCTION_INFO(C_Encrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pData, /* the plaintext data */
++ CK_ULONG ulDataLen, /* bytes of plaintext */
++ CK_BYTE_PTR pEncryptedData, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedDataLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptUpdate continues a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext data len */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text size */
++);
++#endif
++
++
++/* C_EncryptFinal finishes a multiple-part encryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session handle */
++ CK_BYTE_PTR pLastEncryptedPart, /* last c-text */
++ CK_ULONG_PTR pulLastEncryptedPartLen /* gets last size */
++);
++#endif
++
++
++/* C_DecryptInit initializes a decryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the decryption mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of decryption key */
++);
++#endif
++
++
++/* C_Decrypt decrypts encrypted data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Decrypt)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedData, /* ciphertext */
++ CK_ULONG ulEncryptedDataLen, /* ciphertext length */
++ CK_BYTE_PTR pData, /* gets plaintext */
++ CK_ULONG_PTR pulDataLen /* gets p-text size */
++);
++#endif
++
++
++/* C_DecryptUpdate continues a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* encrypted data */
++ CK_ULONG ulEncryptedPartLen, /* input length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* p-text size */
++);
++#endif
++
++
++/* C_DecryptFinal finishes a multiple-part decryption
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pLastPart, /* gets plaintext */
++ CK_ULONG_PTR pulLastPartLen /* p-text size */
++);
++#endif
++
++
++
++/* Message digesting */
++
++/* C_DigestInit initializes a message-digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism /* the digesting mechanism */
++);
++#endif
++
++
++/* C_Digest digests data in a single part. */
++CK_PKCS11_FUNCTION_INFO(C_Digest)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* data to be digested */
++ CK_ULONG ulDataLen, /* bytes of data to digest */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets digest length */
++);
++#endif
++
++
++/* C_DigestUpdate continues a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* data to be digested */
++ CK_ULONG ulPartLen /* bytes of data to be digested */
++);
++#endif
++
++
++/* C_DigestKey continues a multi-part message-digesting
++ * operation, by digesting the value of a secret key as part of
++ * the data already digested. */
++CK_PKCS11_FUNCTION_INFO(C_DigestKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_OBJECT_HANDLE hKey /* secret key to digest */
++);
++#endif
++
++
++/* C_DigestFinal finishes a multiple-part message-digesting
++ * operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pDigest, /* gets the message digest */
++ CK_ULONG_PTR pulDigestLen /* gets byte count of digest */
++);
++#endif
++
++
++
++/* Signing and MACing */
++
++/* C_SignInit initializes a signature (private key encryption)
++ * operation, where the signature is (will be) an appendix to
++ * the data, and plaintext cannot be recovered from the
++ *signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of signature key */
++);
++#endif
++
++
++/* C_Sign signs (encrypts with private key) data in a single
++ * part, where the signature is (will be) an appendix to the
++ * data, and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Sign)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignUpdate continues a multiple-part signature operation,
++ * where the signature is (will be) an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* the data to sign */
++ CK_ULONG ulPartLen /* count of bytes to sign */
++);
++#endif
++
++
++/* C_SignFinal finishes a multiple-part signature operation,
++ * returning the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++/* C_SignRecoverInit initializes a signature operation, where
++ * the data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the signature mechanism */
++ CK_OBJECT_HANDLE hKey /* handle of the signature key */
++);
++#endif
++
++
++/* C_SignRecover signs data in a single operation, where the
++ * data can be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_SignRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* the data to sign */
++ CK_ULONG ulDataLen, /* count of bytes to sign */
++ CK_BYTE_PTR pSignature, /* gets the signature */
++ CK_ULONG_PTR pulSignatureLen /* gets signature length */
++);
++#endif
++
++
++
++/* Verifying signatures and MACs */
++
++/* C_VerifyInit initializes a verification operation, where the
++ * signature is an appendix to the data, and plaintext cannot
++ * cannot be recovered from the signature (e.g. DSA). */
++CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_Verify verifies a signature in a single-part operation,
++ * where the signature is an appendix to the data, and plaintext
++ * cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_Verify)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pData, /* signed data */
++ CK_ULONG ulDataLen, /* length of signed data */
++ CK_BYTE_PTR pSignature, /* signature */
++ CK_ULONG ulSignatureLen /* signature length*/
++);
++#endif
++
++
++/* C_VerifyUpdate continues a multiple-part verification
++ * operation, where the signature is an appendix to the data,
++ * and plaintext cannot be recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pPart, /* signed data */
++ CK_ULONG ulPartLen /* length of signed data */
++);
++#endif
++
++
++/* C_VerifyFinal finishes a multiple-part verification
++ * operation, checking the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen /* signature length */
++);
++#endif
++
++
++/* C_VerifyRecoverInit initializes a signature verification
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the verification mechanism */
++ CK_OBJECT_HANDLE hKey /* verification key */
++);
++#endif
++
++
++/* C_VerifyRecover verifies a signature in a single-part
++ * operation, where the data is recovered from the signature. */
++CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSignature, /* signature to verify */
++ CK_ULONG ulSignatureLen, /* signature length */
++ CK_BYTE_PTR pData, /* gets signed data */
++ CK_ULONG_PTR pulDataLen /* gets signed data len */
++);
++#endif
++
++
++
++/* Dual-function cryptographic operations */
++
++/* C_DigestEncryptUpdate continues a multiple-part digesting
++ * and encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptDigestUpdate continues a multiple-part decryption and
++ * digesting operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets plaintext len */
++);
++#endif
++
++
++/* C_SignEncryptUpdate continues a multiple-part signing and
++ * encryption operation. */
++CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pPart, /* the plaintext data */
++ CK_ULONG ulPartLen, /* plaintext length */
++ CK_BYTE_PTR pEncryptedPart, /* gets ciphertext */
++ CK_ULONG_PTR pulEncryptedPartLen /* gets c-text length */
++);
++#endif
++
++
++/* C_DecryptVerifyUpdate continues a multiple-part decryption and
++ * verify operation. */
++CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_BYTE_PTR pEncryptedPart, /* ciphertext */
++ CK_ULONG ulEncryptedPartLen, /* ciphertext length */
++ CK_BYTE_PTR pPart, /* gets plaintext */
++ CK_ULONG_PTR pulPartLen /* gets p-text length */
++);
++#endif
++
++
++
++/* Key management */
++
++/* C_GenerateKey generates a secret key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key generation mech. */
++ CK_ATTRIBUTE_PTR pTemplate, /* template for new key */
++ CK_ULONG ulCount, /* # of attrs in template */
++ CK_OBJECT_HANDLE_PTR phKey /* gets handle of new key */
++);
++#endif
++
++
++/* C_GenerateKeyPair generates a public-key/private-key pair,
++ * creating new key objects. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session
++ * handle */
++ CK_MECHANISM_PTR pMechanism, /* key-gen
++ * mech. */
++ CK_ATTRIBUTE_PTR pPublicKeyTemplate, /* template
++ * for pub.
++ * key */
++ CK_ULONG ulPublicKeyAttributeCount, /* # pub.
++ * attrs. */
++ CK_ATTRIBUTE_PTR pPrivateKeyTemplate, /* template
++ * for priv.
++ * key */
++ CK_ULONG ulPrivateKeyAttributeCount, /* # priv.
++ * attrs. */
++ CK_OBJECT_HANDLE_PTR phPublicKey, /* gets pub.
++ * key
++ * handle */
++ CK_OBJECT_HANDLE_PTR phPrivateKey /* gets
++ * priv. key
++ * handle */
++);
++#endif
++
++
++/* C_WrapKey wraps (i.e., encrypts) a key. */
++CK_PKCS11_FUNCTION_INFO(C_WrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_MECHANISM_PTR pMechanism, /* the wrapping mechanism */
++ CK_OBJECT_HANDLE hWrappingKey, /* wrapping key */
++ CK_OBJECT_HANDLE hKey, /* key to be wrapped */
++ CK_BYTE_PTR pWrappedKey, /* gets wrapped key */
++ CK_ULONG_PTR pulWrappedKeyLen /* gets wrapped key size */
++);
++#endif
++
++
++/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
++ * key object. */
++CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* unwrapping mech. */
++ CK_OBJECT_HANDLE hUnwrappingKey, /* unwrapping key */
++ CK_BYTE_PTR pWrappedKey, /* the wrapped key */
++ CK_ULONG ulWrappedKeyLen, /* wrapped key len */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++/* C_DeriveKey derives a key from a base key, creating a new key
++ * object. */
++CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* session's handle */
++ CK_MECHANISM_PTR pMechanism, /* key deriv. mech. */
++ CK_OBJECT_HANDLE hBaseKey, /* base key */
++ CK_ATTRIBUTE_PTR pTemplate, /* new key template */
++ CK_ULONG ulAttributeCount, /* template length */
++ CK_OBJECT_HANDLE_PTR phKey /* gets new handle */
++);
++#endif
++
++
++
++/* Random number generation */
++
++/* C_SeedRandom mixes additional seed material into the token's
++ * random number generator. */
++CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR pSeed, /* the seed material */
++ CK_ULONG ulSeedLen /* length of seed material */
++);
++#endif
++
++
++/* C_GenerateRandom generates random data. */
++CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_BYTE_PTR RandomData, /* receives the random data */
++ CK_ULONG ulRandomLen /* # of bytes to generate */
++);
++#endif
++
++
++
++/* Parallel function management */
++
++/* C_GetFunctionStatus is a legacy function; it obtains an
++ * updated status of a function running in parallel with an
++ * application. */
++CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++/* C_CancelFunction is a legacy function; it cancels a function
++ * running in parallel. */
++CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_SESSION_HANDLE hSession /* the session's handle */
++);
++#endif
++
++
++
++/* Functions added in for Cryptoki Version 2.01 or later */
++
++/* C_WaitForSlotEvent waits for a slot event (token insertion,
++ * removal, etc.) to occur. */
++CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
++#ifdef CK_NEED_ARG_LIST
++(
++ CK_FLAGS flags, /* blocking/nonblocking flag */
++ CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
++ CK_VOID_PTR pRserved /* reserved. Should be NULL_PTR */
++);
++#endif
+diff -r -u -N openssl-0.9.8g/crypto/engine/pkcs11.h openssl/crypto/engine/pkcs11.h
+--- openssl-0.9.8g/crypto/engine/pkcs11.h 1970-01-01 01:00:00.000000000 +0100
++++ openssl/crypto/engine/pkcs11.h 2007-10-25 01:27:09.000000000 +0200
+@@ -0,0 +1,299 @@
++/* pkcs11.h include file for PKCS #11. */
++/* $Revision: 1.2 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++#ifndef _PKCS11_H_
++#define _PKCS11_H_ 1
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* Before including this file (pkcs11.h) (or pkcs11t.h by
++ * itself), 6 platform-specific macros must be defined. These
++ * macros are described below, and typical definitions for them
++ * are also given. Be advised that these definitions can depend
++ * on both the platform and the compiler used (and possibly also
++ * on whether a Cryptoki library is linked statically or
++ * dynamically).
++ *
++ * In addition to defining these 6 macros, the packing convention
++ * for Cryptoki structures should be set. The Cryptoki
++ * convention on packing is that structures should be 1-byte
++ * aligned.
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, this might be done by using the following
++ * preprocessor directive before including pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(push, cryptoki, 1)
++ *
++ * and using the following preprocessor directive after including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(pop, cryptoki)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, this might be done by using
++ * the following preprocessor directive before including
++ * pkcs11.h or pkcs11t.h:
++ *
++ * #pragma pack(1)
++ *
++ * In a UNIX environment, you're on your own for this. You might
++ * not need to do (or be able to do!) anything.
++ *
++ *
++ * Now for the macros:
++ *
++ *
++ * 1. CK_PTR: The indirection string for making a pointer to an
++ * object. It can be used like this:
++ *
++ * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to produce
++ * Win32 stuff, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to produce Win16 stuff, it might be defined by:
++ *
++ * #define CK_PTR far *
++ *
++ * In a typical UNIX environment, it might be defined by:
++ *
++ * #define CK_PTR *
++ *
++ *
++ * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
++ * an exportable Cryptoki library function definition out of a
++ * return type and a function name. It should be used in the
++ * following fashion to define the exposed Cryptoki functions in
++ * a Cryptoki library:
++ *
++ * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * )
++ * {
++ * ...
++ * }
++ *
++ * If you're using Microsoft Developer Studio 5.0 to define a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllexport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to define a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DEFINE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
++ * an importable Cryptoki library function declaration out of a
++ * return type and a function name. It should be used in the
++ * following fashion:
++ *
++ * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
++ * CK_VOID_PTR pReserved
++ * );
++ *
++ * If you're using Microsoft Developer Studio 5.0 to declare a
++ * function in a Win32 Cryptoki .dll, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __declspec(dllimport) name
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to declare a function in a Win16 Cryptoki .dll, it
++ * might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType __export _far _pascal name
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION(returnType, name) \
++ * returnType name
++ *
++ *
++ * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
++ * which makes a Cryptoki API function pointer declaration or
++ * function pointer type declaration out of a return type and a
++ * function name. It should be used in the following fashion:
++ *
++ * // Define funcPtr to be a pointer to a Cryptoki API function
++ * // taking arguments args and returning CK_RV.
++ * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
++ *
++ * or
++ *
++ * // Define funcPtrType to be the type of a pointer to a
++ * // Cryptoki API function taking arguments args and returning
++ * // CK_RV, and then define funcPtr to be a variable of type
++ * // funcPtrType.
++ * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
++ * funcPtrType funcPtr;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to access
++ * functions in a Win32 Cryptoki .dll, in might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __declspec(dllimport) (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to access functions in a Win16 Cryptoki .dll, it might
++ * be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType __export _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
++ * a function pointer type for an application callback out of
++ * a return type for the callback and a name for the callback.
++ * It should be used in the following fashion:
++ *
++ * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
++ *
++ * to declare a function pointer, myCallback, to a callback
++ * which takes arguments args and returns a CK_RV. It can also
++ * be used like this:
++ *
++ * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
++ * myCallbackType myCallback;
++ *
++ * If you're using Microsoft Developer Studio 5.0 to do Win32
++ * Cryptoki development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ * If you're using an earlier version of Microsoft Developer
++ * Studio to do Win16 development, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType _far _pascal (* name)
++ *
++ * In a UNIX environment, it might be defined by:
++ *
++ * #define CK_CALLBACK_FUNCTION(returnType, name) \
++ * returnType (* name)
++ *
++ *
++ * 6. NULL_PTR: This macro is the value of a NULL pointer.
++ *
++ * In any ANSI/ISO C environment (and in many others as well),
++ * this should best be defined by
++ *
++ * #ifndef NULL_PTR
++ * #define NULL_PTR 0
++ * #endif
++ */
++
++
++/* All the various Cryptoki types and #define'd values are in the
++ * file pkcs11t.h. */
++#include "pkcs11t.h"
++
++#define __PASTE(x,y) x##y
++
++
++/* ==============================================================
++ * Define the "extern" form of all the entry points.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ extern CK_DECLARE_FUNCTION(CK_RV, name)
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define the typedef form of all the entry points. That is, for
++ * each Cryptoki function C_XXX, define a type CK_C_XXX which is
++ * a pointer to that kind of function.
++ * ==============================================================
++ */
++
++#define CK_NEED_ARG_LIST 1
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
++
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++#undef CK_NEED_ARG_LIST
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++/* ==============================================================
++ * Define structed vector of entry points. A CK_FUNCTION_LIST
++ * contains a CK_VERSION indicating a library's Cryptoki version
++ * and then a whole slew of function pointers to the routines in
++ * the library. This type was declared, but not defined, in
++ * pkcs11t.h.
++ * ==============================================================
++ */
++
++#define CK_PKCS11_FUNCTION_INFO(name) \
++ __PASTE(CK_,name) name;
++
++struct CK_FUNCTION_LIST {
++
++ CK_VERSION version; /* Cryptoki version */
++
++/* Pile all the function pointers into the CK_FUNCTION_LIST. */
++/* pkcs11f.h has all the information about the Cryptoki
++ * function prototypes. */
++#include "pkcs11f.h"
++
++};
++
++#undef CK_PKCS11_FUNCTION_INFO
++
++
++#undef __PASTE
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+diff -r -u -N openssl-0.9.8g/crypto/engine/pkcs11t.h openssl/crypto/engine/pkcs11t.h
+--- openssl-0.9.8g/crypto/engine/pkcs11t.h 1970-01-01 01:00:00.000000000 +0100
++++ openssl/crypto/engine/pkcs11t.h 2007-10-25 01:27:09.000000000 +0200
+@@ -0,0 +1,1685 @@
++/* pkcs11t.h include file for PKCS #11. */
++/* $Revision: 1.2 $ */
++
++/* License to copy and use this software is granted provided that it is
++ * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++ * (Cryptoki)" in all material mentioning or referencing this software.
++
++ * License is also granted to make and use derivative works provided that
++ * such works are identified as "derived from the RSA Security Inc. PKCS #11
++ * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
++ * referencing the derived work.
++
++ * RSA Security Inc. makes no representations concerning either the
++ * merchantability of this software or the suitability of this software for
++ * any particular purpose. It is provided "as is" without express or implied
++ * warranty of any kind.
++ */
++
++/* See top of pkcs11.h for information about the macros that
++ * must be defined and the structure-packing conventions that
++ * must be set before including this file. */
++
++#ifndef _PKCS11T_H_
++#define _PKCS11T_H_ 1
++
++#define CK_TRUE 1
++#define CK_FALSE 0
++
++#ifndef CK_DISABLE_TRUE_FALSE
++#ifndef FALSE
++#define FALSE CK_FALSE
++#endif
++
++#ifndef TRUE
++#define TRUE CK_TRUE
++#endif
++#endif
++
++/* an unsigned 8-bit value */
++typedef unsigned char CK_BYTE;
++
++/* an unsigned 8-bit character */
++typedef CK_BYTE CK_CHAR;
++
++/* an 8-bit UTF-8 character */
++typedef CK_BYTE CK_UTF8CHAR;
++
++/* a BYTE-sized Boolean flag */
++typedef CK_BYTE CK_BBOOL;
++
++/* an unsigned value, at least 32 bits long */
++typedef unsigned long int CK_ULONG;
++
++/* a signed value, the same size as a CK_ULONG */
++/* CK_LONG is new for v2.0 */
++typedef long int CK_LONG;
++
++/* at least 32 bits; each bit is a Boolean flag */
++typedef CK_ULONG CK_FLAGS;
++
++
++/* some special values for certain CK_ULONG variables */
++#define CK_UNAVAILABLE_INFORMATION (~0UL)
++#define CK_EFFECTIVELY_INFINITE 0
++
++
++typedef CK_BYTE CK_PTR CK_BYTE_PTR;
++typedef CK_CHAR CK_PTR CK_CHAR_PTR;
++typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR;
++typedef CK_ULONG CK_PTR CK_ULONG_PTR;
++typedef void CK_PTR CK_VOID_PTR;
++
++/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
++typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
++
++
++/* The following value is always invalid if used as a session */
++/* handle or object handle */
++#define CK_INVALID_HANDLE 0
++
++
++typedef struct CK_VERSION {
++ CK_BYTE major; /* integer portion of version number */
++ CK_BYTE minor; /* 1/100ths portion of version number */
++} CK_VERSION;
++
++typedef CK_VERSION CK_PTR CK_VERSION_PTR;
++
++
++typedef struct CK_INFO {
++ /* manufacturerID and libraryDecription have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_VERSION cryptokiVersion; /* Cryptoki interface ver */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags; /* must be zero */
++
++ /* libraryDescription and libraryVersion are new for v2.0 */
++ CK_UTF8CHAR libraryDescription[32]; /* blank padded */
++ CK_VERSION libraryVersion; /* version of library */
++} CK_INFO;
++
++typedef CK_INFO CK_PTR CK_INFO_PTR;
++
++
++/* CK_NOTIFICATION enumerates the types of notifications that
++ * Cryptoki provides to an application */
++/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_NOTIFICATION;
++#define CKN_SURRENDER 0
++
++
++typedef CK_ULONG CK_SLOT_ID;
++
++typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
++
++
++/* CK_SLOT_INFO provides information about a slot */
++typedef struct CK_SLOT_INFO {
++ /* slotDescription and manufacturerID have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR slotDescription[64]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_FLAGS flags;
++
++ /* hardwareVersion and firmwareVersion are new for v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++} CK_SLOT_INFO;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_TOKEN_PRESENT 0x00000001 /* a token is there */
++#define CKF_REMOVABLE_DEVICE 0x00000002 /* removable devices*/
++#define CKF_HW_SLOT 0x00000004 /* hardware slot */
++
++typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
++
++
++/* CK_TOKEN_INFO provides information about a token */
++typedef struct CK_TOKEN_INFO {
++ /* label, manufacturerID, and model have been changed from
++ * CK_CHAR to CK_UTF8CHAR for v2.10 */
++ CK_UTF8CHAR label[32]; /* blank padded */
++ CK_UTF8CHAR manufacturerID[32]; /* blank padded */
++ CK_UTF8CHAR model[16]; /* blank padded */
++ CK_CHAR serialNumber[16]; /* blank padded */
++ CK_FLAGS flags; /* see below */
++
++ /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
++ * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
++ * changed from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulMaxSessionCount; /* max open sessions */
++ CK_ULONG ulSessionCount; /* sess. now open */
++ CK_ULONG ulMaxRwSessionCount; /* max R/W sessions */
++ CK_ULONG ulRwSessionCount; /* R/W sess. now open */
++ CK_ULONG ulMaxPinLen; /* in bytes */
++ CK_ULONG ulMinPinLen; /* in bytes */
++ CK_ULONG ulTotalPublicMemory; /* in bytes */
++ CK_ULONG ulFreePublicMemory; /* in bytes */
++ CK_ULONG ulTotalPrivateMemory; /* in bytes */
++ CK_ULONG ulFreePrivateMemory; /* in bytes */
++
++ /* hardwareVersion, firmwareVersion, and time are new for
++ * v2.0 */
++ CK_VERSION hardwareVersion; /* version of hardware */
++ CK_VERSION firmwareVersion; /* version of firmware */
++ CK_CHAR utcTime[16]; /* time */
++} CK_TOKEN_INFO;
++
++/* The flags parameter is defined as follows:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RNG 0x00000001 /* has random #
++ * generator */
++#define CKF_WRITE_PROTECTED 0x00000002 /* token is
++ * write-
++ * protected */
++#define CKF_LOGIN_REQUIRED 0x00000004 /* user must
++ * login */
++#define CKF_USER_PIN_INITIALIZED 0x00000008 /* normal user's
++ * PIN is set */
++
++/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0. If it is set,
++ * that means that *every* time the state of cryptographic
++ * operations of a session is successfully saved, all keys
++ * needed to continue those operations are stored in the state */
++#define CKF_RESTORE_KEY_NOT_NEEDED 0x00000020
++
++/* CKF_CLOCK_ON_TOKEN is new for v2.0. If it is set, that means
++ * that the token has some sort of clock. The time on that
++ * clock is returned in the token info structure */
++#define CKF_CLOCK_ON_TOKEN 0x00000040
++
++/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0. If it is
++ * set, that means that there is some way for the user to login
++ * without sending a PIN through the Cryptoki library itself */
++#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
++
++/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0. If it is true,
++ * that means that a single session with the token can perform
++ * dual simultaneous cryptographic operations (digest and
++ * encrypt; decrypt and digest; sign and encrypt; and decrypt
++ * and sign) */
++#define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200
++
++/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
++ * token has been initialized using C_InitializeToken or an
++ * equivalent mechanism outside the scope of PKCS #11.
++ * Calling C_InitializeToken when this flag is set will cause
++ * the token to be reinitialized. */
++#define CKF_TOKEN_INITIALIZED 0x00000400
++
++/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
++ * true, the token supports secondary authentication for
++ * private key objects. This flag is deprecated in v2.11 and
++ onwards. */
++#define CKF_SECONDARY_AUTHENTICATION 0x00000800
++
++/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect user login PIN has been entered at least once
++ * since the last successful authentication. */
++#define CKF_USER_PIN_COUNT_LOW 0x00010000
++
++/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect user PIN will it to become locked. */
++#define CKF_USER_PIN_FINAL_TRY 0x00020000
++
++/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
++ * user PIN has been locked. User login to the token is not
++ * possible. */
++#define CKF_USER_PIN_LOCKED 0x00040000
++
++/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the user PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000
++
++/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
++ * incorrect SO login PIN has been entered at least once since
++ * the last successful authentication. */
++#define CKF_SO_PIN_COUNT_LOW 0x00100000
++
++/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
++ * supplying an incorrect SO PIN will it to become locked. */
++#define CKF_SO_PIN_FINAL_TRY 0x00200000
++
++/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
++ * PIN has been locked. SO login to the token is not possible.
++ */
++#define CKF_SO_PIN_LOCKED 0x00400000
++
++/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
++ * the SO PIN value is the default value set by token
++ * initialization or manufacturing, or the PIN has been
++ * expired by the card. */
++#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000
++
++typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
++
++
++/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
++ * identifies a session */
++typedef CK_ULONG CK_SESSION_HANDLE;
++
++typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
++
++
++/* CK_USER_TYPE enumerates the types of Cryptoki users */
++/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_USER_TYPE;
++/* Security Officer */
++#define CKU_SO 0
++/* Normal user */
++#define CKU_USER 1
++/* Context specific (added in v2.20) */
++#define CKU_CONTEXT_SPECIFIC 2
++
++/* CK_STATE enumerates the session states */
++/* CK_STATE has been changed from an enum to a CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_STATE;
++#define CKS_RO_PUBLIC_SESSION 0
++#define CKS_RO_USER_FUNCTIONS 1
++#define CKS_RW_PUBLIC_SESSION 2
++#define CKS_RW_USER_FUNCTIONS 3
++#define CKS_RW_SO_FUNCTIONS 4
++
++
++/* CK_SESSION_INFO provides information about a session */
++typedef struct CK_SESSION_INFO {
++ CK_SLOT_ID slotID;
++ CK_STATE state;
++ CK_FLAGS flags; /* see below */
++
++ /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulDeviceError; /* device-dependent error code */
++} CK_SESSION_INFO;
++
++/* The flags are defined in the following table:
++ * Bit Flag Mask Meaning
++ */
++#define CKF_RW_SESSION 0x00000002 /* session is r/w */
++#define CKF_SERIAL_SESSION 0x00000004 /* no parallel */
++
++typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
++
++
++/* CK_OBJECT_HANDLE is a token-specific identifier for an
++ * object */
++typedef CK_ULONG CK_OBJECT_HANDLE;
++
++typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
++
++
++/* CK_OBJECT_CLASS is a value that identifies the classes (or
++ * types) of objects that Cryptoki recognizes. It is defined
++ * as follows: */
++/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_OBJECT_CLASS;
++
++/* The following classes of objects are defined: */
++/* CKO_HW_FEATURE is new for v2.10 */
++/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
++/* CKO_MECHANISM is new for v2.20 */
++#define CKO_DATA 0x00000000
++#define CKO_CERTIFICATE 0x00000001
++#define CKO_PUBLIC_KEY 0x00000002
++#define CKO_PRIVATE_KEY 0x00000003
++#define CKO_SECRET_KEY 0x00000004
++#define CKO_HW_FEATURE 0x00000005
++#define CKO_DOMAIN_PARAMETERS 0x00000006
++#define CKO_MECHANISM 0x00000007
++#define CKO_VENDOR_DEFINED 0x80000000
++
++typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
++
++/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
++ * value that identifies the hardware feature type of an object
++ * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
++typedef CK_ULONG CK_HW_FEATURE_TYPE;
++
++/* The following hardware feature types are defined */
++/* CKH_USER_INTERFACE is new for v2.20 */
++#define CKH_MONOTONIC_COUNTER 0x00000001
++#define CKH_CLOCK 0x00000002
++#define CKH_USER_INTERFACE 0x00000003
++#define CKH_VENDOR_DEFINED 0x80000000
++
++/* CK_KEY_TYPE is a value that identifies a key type */
++/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_KEY_TYPE;
++
++/* the following key types are defined: */
++#define CKK_RSA 0x00000000
++#define CKK_DSA 0x00000001
++#define CKK_DH 0x00000002
++
++/* CKK_ECDSA and CKK_KEA are new for v2.0 */
++/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
++#define CKK_ECDSA 0x00000003
++#define CKK_EC 0x00000003
++#define CKK_X9_42_DH 0x00000004
++#define CKK_KEA 0x00000005
++
++#define CKK_GENERIC_SECRET 0x00000010
++#define CKK_RC2 0x00000011
++#define CKK_RC4 0x00000012
++#define CKK_DES 0x00000013
++#define CKK_DES2 0x00000014
++#define CKK_DES3 0x00000015
++
++/* all these key types are new for v2.0 */
++#define CKK_CAST 0x00000016
++#define CKK_CAST3 0x00000017
++/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
++#define CKK_CAST5 0x00000018
++#define CKK_CAST128 0x00000018
++#define CKK_RC5 0x00000019
++#define CKK_IDEA 0x0000001A
++#define CKK_SKIPJACK 0x0000001B
++#define CKK_BATON 0x0000001C
++#define CKK_JUNIPER 0x0000001D
++#define CKK_CDMF 0x0000001E
++#define CKK_AES 0x0000001F
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKK_BLOWFISH 0x00000020
++#define CKK_TWOFISH 0x00000021
++
++#define CKK_VENDOR_DEFINED 0x80000000
++
++
++/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
++ * type */
++/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
++ * for v2.0 */
++typedef CK_ULONG CK_CERTIFICATE_TYPE;
++
++/* The following certificate types are defined: */
++/* CKC_X_509_ATTR_CERT is new for v2.10 */
++/* CKC_WTLS is new for v2.20 */
++#define CKC_X_509 0x00000000
++#define CKC_X_509_ATTR_CERT 0x00000001
++#define CKC_WTLS 0x00000002
++#define CKC_VENDOR_DEFINED 0x80000000
++
++
++/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
++ * type */
++/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_ATTRIBUTE_TYPE;
++
++/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
++ consists of an array of values. */
++#define CKF_ARRAY_ATTRIBUTE 0x40000000
++
++/* The following attribute types are defined: */
++#define CKA_CLASS 0x00000000
++#define CKA_TOKEN 0x00000001
++#define CKA_PRIVATE 0x00000002
++#define CKA_LABEL 0x00000003
++#define CKA_APPLICATION 0x00000010
++#define CKA_VALUE 0x00000011
++
++/* CKA_OBJECT_ID is new for v2.10 */
++#define CKA_OBJECT_ID 0x00000012
++
++#define CKA_CERTIFICATE_TYPE 0x00000080
++#define CKA_ISSUER 0x00000081
++#define CKA_SERIAL_NUMBER 0x00000082
++
++/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
++ * for v2.10 */
++#define CKA_AC_ISSUER 0x00000083
++#define CKA_OWNER 0x00000084
++#define CKA_ATTR_TYPES 0x00000085
++
++/* CKA_TRUSTED is new for v2.11 */
++#define CKA_TRUSTED 0x00000086
++
++/* CKA_CERTIFICATE_CATEGORY ...
++ * CKA_CHECK_VALUE are new for v2.20 */
++#define CKA_CERTIFICATE_CATEGORY 0x00000087
++#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088
++#define CKA_URL 0x00000089
++#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A
++#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B
++#define CKA_CHECK_VALUE 0x00000090
++
++#define CKA_KEY_TYPE 0x00000100
++#define CKA_SUBJECT 0x00000101
++#define CKA_ID 0x00000102
++#define CKA_SENSITIVE 0x00000103
++#define CKA_ENCRYPT 0x00000104
++#define CKA_DECRYPT 0x00000105
++#define CKA_WRAP 0x00000106
++#define CKA_UNWRAP 0x00000107
++#define CKA_SIGN 0x00000108
++#define CKA_SIGN_RECOVER 0x00000109
++#define CKA_VERIFY 0x0000010A
++#define CKA_VERIFY_RECOVER 0x0000010B
++#define CKA_DERIVE 0x0000010C
++#define CKA_START_DATE 0x00000110
++#define CKA_END_DATE 0x00000111
++#define CKA_MODULUS 0x00000120
++#define CKA_MODULUS_BITS 0x00000121
++#define CKA_PUBLIC_EXPONENT 0x00000122
++#define CKA_PRIVATE_EXPONENT 0x00000123
++#define CKA_PRIME_1 0x00000124
++#define CKA_PRIME_2 0x00000125
++#define CKA_EXPONENT_1 0x00000126
++#define CKA_EXPONENT_2 0x00000127
++#define CKA_COEFFICIENT 0x00000128
++#define CKA_PRIME 0x00000130
++#define CKA_SUBPRIME 0x00000131
++#define CKA_BASE 0x00000132
++
++/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
++#define CKA_PRIME_BITS 0x00000133
++#define CKA_SUBPRIME_BITS 0x00000134
++#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS
++/* (To retain backwards-compatibility) */
++
++#define CKA_VALUE_BITS 0x00000160
++#define CKA_VALUE_LEN 0x00000161
++
++/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
++ * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
++ * and CKA_EC_POINT are new for v2.0 */
++#define CKA_EXTRACTABLE 0x00000162
++#define CKA_LOCAL 0x00000163
++#define CKA_NEVER_EXTRACTABLE 0x00000164
++#define CKA_ALWAYS_SENSITIVE 0x00000165
++
++/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
++#define CKA_KEY_GEN_MECHANISM 0x00000166
++
++#define CKA_MODIFIABLE 0x00000170
++
++/* CKA_ECDSA_PARAMS is deprecated in v2.11,
++ * CKA_EC_PARAMS is preferred. */
++#define CKA_ECDSA_PARAMS 0x00000180
++#define CKA_EC_PARAMS 0x00000180
++
++#define CKA_EC_POINT 0x00000181
++
++/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
++ * are new for v2.10. Deprecated in v2.11 and onwards. */
++#define CKA_SECONDARY_AUTH 0x00000200
++#define CKA_AUTH_PIN_FLAGS 0x00000201
++
++/* CKA_ALWAYS_AUTHENTICATE ...
++ * CKA_UNWRAP_TEMPLATE are new for v2.20 */
++#define CKA_ALWAYS_AUTHENTICATE 0x00000202
++
++#define CKA_WRAP_WITH_TRUSTED 0x00000210
++#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211)
++#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212)
++
++/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
++ * are new for v2.10 */
++#define CKA_HW_FEATURE_TYPE 0x00000300
++#define CKA_RESET_ON_INIT 0x00000301
++#define CKA_HAS_RESET 0x00000302
++
++/* The following attributes are new for v2.20 */
++#define CKA_PIXEL_X 0x00000400
++#define CKA_PIXEL_Y 0x00000401
++#define CKA_RESOLUTION 0x00000402
++#define CKA_CHAR_ROWS 0x00000403
++#define CKA_CHAR_COLUMNS 0x00000404
++#define CKA_COLOR 0x00000405
++#define CKA_BITS_PER_PIXEL 0x00000406
++#define CKA_CHAR_SETS 0x00000480
++#define CKA_ENCODING_METHODS 0x00000481
++#define CKA_MIME_TYPES 0x00000482
++#define CKA_MECHANISM_TYPE 0x00000500
++#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501
++#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502
++#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503
++#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
++
++#define CKA_VENDOR_DEFINED 0x80000000
++
++
++/* CK_ATTRIBUTE is a structure that includes the type, length
++ * and value of an attribute */
++typedef struct CK_ATTRIBUTE {
++ CK_ATTRIBUTE_TYPE type;
++ CK_VOID_PTR pValue;
++
++ /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
++ CK_ULONG ulValueLen; /* in bytes */
++} CK_ATTRIBUTE;
++
++typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
++
++
++/* CK_DATE is a structure that defines a date */
++typedef struct CK_DATE{
++ CK_CHAR year[4]; /* the year ("1900" - "9999") */
++ CK_CHAR month[2]; /* the month ("01" - "12") */
++ CK_CHAR day[2]; /* the day ("01" - "31") */
++} CK_DATE;
++
++
++/* CK_MECHANISM_TYPE is a value that identifies a mechanism
++ * type */
++/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++typedef CK_ULONG CK_MECHANISM_TYPE;
++
++/* the following mechanism types are defined: */
++#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000
++#define CKM_RSA_PKCS 0x00000001
++#define CKM_RSA_9796 0x00000002
++#define CKM_RSA_X_509 0x00000003
++
++/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
++ * are new for v2.0. They are mechanisms which hash and sign */
++#define CKM_MD2_RSA_PKCS 0x00000004
++#define CKM_MD5_RSA_PKCS 0x00000005
++#define CKM_SHA1_RSA_PKCS 0x00000006
++
++/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
++ * CKM_RSA_PKCS_OAEP are new for v2.10 */
++#define CKM_RIPEMD128_RSA_PKCS 0x00000007
++#define CKM_RIPEMD160_RSA_PKCS 0x00000008
++#define CKM_RSA_PKCS_OAEP 0x00000009
++
++/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
++ * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
++#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A
++#define CKM_RSA_X9_31 0x0000000B
++#define CKM_SHA1_RSA_X9_31 0x0000000C
++#define CKM_RSA_PKCS_PSS 0x0000000D
++#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E
++
++#define CKM_DSA_KEY_PAIR_GEN 0x00000010
++#define CKM_DSA 0x00000011
++#define CKM_DSA_SHA1 0x00000012
++#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020
++#define CKM_DH_PKCS_DERIVE 0x00000021
++
++/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
++ * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
++ * v2.11 */
++#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030
++#define CKM_X9_42_DH_DERIVE 0x00000031
++#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032
++#define CKM_X9_42_MQV_DERIVE 0x00000033
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_RSA_PKCS 0x00000040
++#define CKM_SHA384_RSA_PKCS 0x00000041
++#define CKM_SHA512_RSA_PKCS 0x00000042
++#define CKM_SHA256_RSA_PKCS_PSS 0x00000043
++#define CKM_SHA384_RSA_PKCS_PSS 0x00000044
++#define CKM_SHA512_RSA_PKCS_PSS 0x00000045
++
++#define CKM_RC2_KEY_GEN 0x00000100
++#define CKM_RC2_ECB 0x00000101
++#define CKM_RC2_CBC 0x00000102
++#define CKM_RC2_MAC 0x00000103
++
++/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
++#define CKM_RC2_MAC_GENERAL 0x00000104
++#define CKM_RC2_CBC_PAD 0x00000105
++
++#define CKM_RC4_KEY_GEN 0x00000110
++#define CKM_RC4 0x00000111
++#define CKM_DES_KEY_GEN 0x00000120
++#define CKM_DES_ECB 0x00000121
++#define CKM_DES_CBC 0x00000122
++#define CKM_DES_MAC 0x00000123
++
++/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
++#define CKM_DES_MAC_GENERAL 0x00000124
++#define CKM_DES_CBC_PAD 0x00000125
++
++#define CKM_DES2_KEY_GEN 0x00000130
++#define CKM_DES3_KEY_GEN 0x00000131
++#define CKM_DES3_ECB 0x00000132
++#define CKM_DES3_CBC 0x00000133
++#define CKM_DES3_MAC 0x00000134
++
++/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
++ * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
++ * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
++#define CKM_DES3_MAC_GENERAL 0x00000135
++#define CKM_DES3_CBC_PAD 0x00000136
++#define CKM_CDMF_KEY_GEN 0x00000140
++#define CKM_CDMF_ECB 0x00000141
++#define CKM_CDMF_CBC 0x00000142
++#define CKM_CDMF_MAC 0x00000143
++#define CKM_CDMF_MAC_GENERAL 0x00000144
++#define CKM_CDMF_CBC_PAD 0x00000145
++
++/* the following four DES mechanisms are new for v2.20 */
++#define CKM_DES_OFB64 0x00000150
++#define CKM_DES_OFB8 0x00000151
++#define CKM_DES_CFB64 0x00000152
++#define CKM_DES_CFB8 0x00000153
++
++#define CKM_MD2 0x00000200
++
++/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD2_HMAC 0x00000201
++#define CKM_MD2_HMAC_GENERAL 0x00000202
++
++#define CKM_MD5 0x00000210
++
++/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
++#define CKM_MD5_HMAC 0x00000211
++#define CKM_MD5_HMAC_GENERAL 0x00000212
++
++#define CKM_SHA_1 0x00000220
++
++/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
++#define CKM_SHA_1_HMAC 0x00000221
++#define CKM_SHA_1_HMAC_GENERAL 0x00000222
++
++/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
++ * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
++ * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
++#define CKM_RIPEMD128 0x00000230
++#define CKM_RIPEMD128_HMAC 0x00000231
++#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232
++#define CKM_RIPEMD160 0x00000240
++#define CKM_RIPEMD160_HMAC 0x00000241
++#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256 0x00000250
++#define CKM_SHA256_HMAC 0x00000251
++#define CKM_SHA256_HMAC_GENERAL 0x00000252
++#define CKM_SHA384 0x00000260
++#define CKM_SHA384_HMAC 0x00000261
++#define CKM_SHA384_HMAC_GENERAL 0x00000262
++#define CKM_SHA512 0x00000270
++#define CKM_SHA512_HMAC 0x00000271
++#define CKM_SHA512_HMAC_GENERAL 0x00000272
++
++/* All of the following mechanisms are new for v2.0 */
++/* Note that CAST128 and CAST5 are the same algorithm */
++#define CKM_CAST_KEY_GEN 0x00000300
++#define CKM_CAST_ECB 0x00000301
++#define CKM_CAST_CBC 0x00000302
++#define CKM_CAST_MAC 0x00000303
++#define CKM_CAST_MAC_GENERAL 0x00000304
++#define CKM_CAST_CBC_PAD 0x00000305
++#define CKM_CAST3_KEY_GEN 0x00000310
++#define CKM_CAST3_ECB 0x00000311
++#define CKM_CAST3_CBC 0x00000312
++#define CKM_CAST3_MAC 0x00000313
++#define CKM_CAST3_MAC_GENERAL 0x00000314
++#define CKM_CAST3_CBC_PAD 0x00000315
++#define CKM_CAST5_KEY_GEN 0x00000320
++#define CKM_CAST128_KEY_GEN 0x00000320
++#define CKM_CAST5_ECB 0x00000321
++#define CKM_CAST128_ECB 0x00000321
++#define CKM_CAST5_CBC 0x00000322
++#define CKM_CAST128_CBC 0x00000322
++#define CKM_CAST5_MAC 0x00000323
++#define CKM_CAST128_MAC 0x00000323
++#define CKM_CAST5_MAC_GENERAL 0x00000324
++#define CKM_CAST128_MAC_GENERAL 0x00000324
++#define CKM_CAST5_CBC_PAD 0x00000325
++#define CKM_CAST128_CBC_PAD 0x00000325
++#define CKM_RC5_KEY_GEN 0x00000330
++#define CKM_RC5_ECB 0x00000331
++#define CKM_RC5_CBC 0x00000332
++#define CKM_RC5_MAC 0x00000333
++#define CKM_RC5_MAC_GENERAL 0x00000334
++#define CKM_RC5_CBC_PAD 0x00000335
++#define CKM_IDEA_KEY_GEN 0x00000340
++#define CKM_IDEA_ECB 0x00000341
++#define CKM_IDEA_CBC 0x00000342
++#define CKM_IDEA_MAC 0x00000343
++#define CKM_IDEA_MAC_GENERAL 0x00000344
++#define CKM_IDEA_CBC_PAD 0x00000345
++#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350
++#define CKM_CONCATENATE_BASE_AND_KEY 0x00000360
++#define CKM_CONCATENATE_BASE_AND_DATA 0x00000362
++#define CKM_CONCATENATE_DATA_AND_BASE 0x00000363
++#define CKM_XOR_BASE_AND_DATA 0x00000364
++#define CKM_EXTRACT_KEY_FROM_KEY 0x00000365
++#define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370
++#define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371
++#define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372
++
++/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
++ * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
++ * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
++#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373
++#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374
++#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375
++#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376
++#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377
++
++/* CKM_TLS_PRF is new for v2.20 */
++#define CKM_TLS_PRF 0x00000378
++
++#define CKM_SSL3_MD5_MAC 0x00000380
++#define CKM_SSL3_SHA1_MAC 0x00000381
++#define CKM_MD5_KEY_DERIVATION 0x00000390
++#define CKM_MD2_KEY_DERIVATION 0x00000391
++#define CKM_SHA1_KEY_DERIVATION 0x00000392
++
++/* CKM_SHA256/384/512 are new for v2.20 */
++#define CKM_SHA256_KEY_DERIVATION 0x00000393
++#define CKM_SHA384_KEY_DERIVATION 0x00000394
++#define CKM_SHA512_KEY_DERIVATION 0x00000395
++
++#define CKM_PBE_MD2_DES_CBC 0x000003A0
++#define CKM_PBE_MD5_DES_CBC 0x000003A1
++#define CKM_PBE_MD5_CAST_CBC 0x000003A2
++#define CKM_PBE_MD5_CAST3_CBC 0x000003A3
++#define CKM_PBE_MD5_CAST5_CBC 0x000003A4
++#define CKM_PBE_MD5_CAST128_CBC 0x000003A4
++#define CKM_PBE_SHA1_CAST5_CBC 0x000003A5
++#define CKM_PBE_SHA1_CAST128_CBC 0x000003A5
++#define CKM_PBE_SHA1_RC4_128 0x000003A6
++#define CKM_PBE_SHA1_RC4_40 0x000003A7
++#define CKM_PBE_SHA1_DES3_EDE_CBC 0x000003A8
++#define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9
++#define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA
++#define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB
++
++/* CKM_PKCS5_PBKD2 is new for v2.10 */
++#define CKM_PKCS5_PBKD2 0x000003B0
++
++#define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0
++
++/* WTLS mechanisms are new for v2.20 */
++#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0
++#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1
++#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2
++#define CKM_WTLS_PRF 0x000003D3
++#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4
++#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5
++
++#define CKM_KEY_WRAP_LYNKS 0x00000400
++#define CKM_KEY_WRAP_SET_OAEP 0x00000401
++
++/* CKM_CMS_SIG is new for v2.20 */
++#define CKM_CMS_SIG 0x00000500
++
++/* Fortezza mechanisms */
++#define CKM_SKIPJACK_KEY_GEN 0x00001000
++#define CKM_SKIPJACK_ECB64 0x00001001
++#define CKM_SKIPJACK_CBC64 0x00001002
++#define CKM_SKIPJACK_OFB64 0x00001003
++#define CKM_SKIPJACK_CFB64 0x00001004
++#define CKM_SKIPJACK_CFB32 0x00001005
++#define CKM_SKIPJACK_CFB16 0x00001006
++#define CKM_SKIPJACK_CFB8 0x00001007
++#define CKM_SKIPJACK_WRAP 0x00001008
++#define CKM_SKIPJACK_PRIVATE_WRAP 0x00001009
++#define CKM_SKIPJACK_RELAYX 0x0000100a
++#define CKM_KEA_KEY_PAIR_GEN 0x00001010
++#define CKM_KEA_KEY_DERIVE 0x00001011
++#define CKM_FORTEZZA_TIMESTAMP 0x00001020
++#define CKM_BATON_KEY_GEN 0x00001030
++#define CKM_BATON_ECB128 0x00001031
++#define CKM_BATON_ECB96 0x00001032
++#define CKM_BATON_CBC128 0x00001033
++#define CKM_BATON_COUNTER 0x00001034
++#define CKM_BATON_SHUFFLE 0x00001035
++#define CKM_BATON_WRAP 0x00001036
++
++/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
++ * CKM_EC_KEY_PAIR_GEN is preferred */
++#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040
++#define CKM_EC_KEY_PAIR_GEN 0x00001040
++
++#define CKM_ECDSA 0x00001041
++#define CKM_ECDSA_SHA1 0x00001042
++
++/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
++ * are new for v2.11 */
++#define CKM_ECDH1_DERIVE 0x00001050
++#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051
++#define CKM_ECMQV_DERIVE 0x00001052
++
++#define CKM_JUNIPER_KEY_GEN 0x00001060
++#define CKM_JUNIPER_ECB128 0x00001061
++#define CKM_JUNIPER_CBC128 0x00001062
++#define CKM_JUNIPER_COUNTER 0x00001063
++#define CKM_JUNIPER_SHUFFLE 0x00001064
++#define CKM_JUNIPER_WRAP 0x00001065
++#define CKM_FASTHASH 0x00001070
++
++/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
++ * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
++ * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
++ * new for v2.11 */
++#define CKM_AES_KEY_GEN 0x00001080
++#define CKM_AES_ECB 0x00001081
++#define CKM_AES_CBC 0x00001082
++#define CKM_AES_MAC 0x00001083
++#define CKM_AES_MAC_GENERAL 0x00001084
++#define CKM_AES_CBC_PAD 0x00001085
++
++/* BlowFish and TwoFish are new for v2.20 */
++#define CKM_BLOWFISH_KEY_GEN 0x00001090
++#define CKM_BLOWFISH_CBC 0x00001091
++#define CKM_TWOFISH_KEY_GEN 0x00001092
++#define CKM_TWOFISH_CBC 0x00001093
++
++
++/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
++#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100
++#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101
++#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102
++#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103
++#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104
++#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105
++
++#define CKM_DSA_PARAMETER_GEN 0x00002000
++#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001
++#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002
++
++#define CKM_VENDOR_DEFINED 0x80000000
++
++typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
++
++
++/* CK_MECHANISM is a structure that specifies a particular
++ * mechanism */
++typedef struct CK_MECHANISM {
++ CK_MECHANISM_TYPE mechanism;
++ CK_VOID_PTR pParameter;
++
++ /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulParameterLen; /* in bytes */
++} CK_MECHANISM;
++
++typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
++
++
++/* CK_MECHANISM_INFO provides information about a particular
++ * mechanism */
++typedef struct CK_MECHANISM_INFO {
++ CK_ULONG ulMinKeySize;
++ CK_ULONG ulMaxKeySize;
++ CK_FLAGS flags;
++} CK_MECHANISM_INFO;
++
++/* The flags are defined as follows:
++ * Bit Flag Mask Meaning */
++#define CKF_HW 0x00000001 /* performed by HW */
++
++/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
++ * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
++ * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
++ * and CKF_DERIVE are new for v2.0. They specify whether or not
++ * a mechanism can be used for a particular task */
++#define CKF_ENCRYPT 0x00000100
++#define CKF_DECRYPT 0x00000200
++#define CKF_DIGEST 0x00000400
++#define CKF_SIGN 0x00000800
++#define CKF_SIGN_RECOVER 0x00001000
++#define CKF_VERIFY 0x00002000
++#define CKF_VERIFY_RECOVER 0x00004000
++#define CKF_GENERATE 0x00008000
++#define CKF_GENERATE_KEY_PAIR 0x00010000
++#define CKF_WRAP 0x00020000
++#define CKF_UNWRAP 0x00040000
++#define CKF_DERIVE 0x00080000
++
++/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
++ * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
++ * describe a token's EC capabilities not available in mechanism
++ * information. */
++#define CKF_EC_F_P 0x00100000
++#define CKF_EC_F_2M 0x00200000
++#define CKF_EC_ECPARAMETERS 0x00400000
++#define CKF_EC_NAMEDCURVE 0x00800000
++#define CKF_EC_UNCOMPRESS 0x01000000
++#define CKF_EC_COMPRESS 0x02000000
++
++#define CKF_EXTENSION 0x80000000 /* FALSE for this version */
++
++typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
++
++
++/* CK_RV is a value that identifies the return value of a
++ * Cryptoki function */
++/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
++typedef CK_ULONG CK_RV;
++
++#define CKR_OK 0x00000000
++#define CKR_CANCEL 0x00000001
++#define CKR_HOST_MEMORY 0x00000002
++#define CKR_SLOT_ID_INVALID 0x00000003
++
++/* CKR_FLAGS_INVALID was removed for v2.0 */
++
++/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
++#define CKR_GENERAL_ERROR 0x00000005
++#define CKR_FUNCTION_FAILED 0x00000006
++
++/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
++ * and CKR_CANT_LOCK are new for v2.01 */
++#define CKR_ARGUMENTS_BAD 0x00000007
++#define CKR_NO_EVENT 0x00000008
++#define CKR_NEED_TO_CREATE_THREADS 0x00000009
++#define CKR_CANT_LOCK 0x0000000A
++
++#define CKR_ATTRIBUTE_READ_ONLY 0x00000010
++#define CKR_ATTRIBUTE_SENSITIVE 0x00000011
++#define CKR_ATTRIBUTE_TYPE_INVALID 0x00000012
++#define CKR_ATTRIBUTE_VALUE_INVALID 0x00000013
++#define CKR_DATA_INVALID 0x00000020
++#define CKR_DATA_LEN_RANGE 0x00000021
++#define CKR_DEVICE_ERROR 0x00000030
++#define CKR_DEVICE_MEMORY 0x00000031
++#define CKR_DEVICE_REMOVED 0x00000032
++#define CKR_ENCRYPTED_DATA_INVALID 0x00000040
++#define CKR_ENCRYPTED_DATA_LEN_RANGE 0x00000041
++#define CKR_FUNCTION_CANCELED 0x00000050
++#define CKR_FUNCTION_NOT_PARALLEL 0x00000051
++
++/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
++#define CKR_FUNCTION_NOT_SUPPORTED 0x00000054
++
++#define CKR_KEY_HANDLE_INVALID 0x00000060
++
++/* CKR_KEY_SENSITIVE was removed for v2.0 */
++
++#define CKR_KEY_SIZE_RANGE 0x00000062
++#define CKR_KEY_TYPE_INCONSISTENT 0x00000063
++
++/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
++ * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
++ * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
++ * v2.0 */
++#define CKR_KEY_NOT_NEEDED 0x00000064
++#define CKR_KEY_CHANGED 0x00000065
++#define CKR_KEY_NEEDED 0x00000066
++#define CKR_KEY_INDIGESTIBLE 0x00000067
++#define CKR_KEY_FUNCTION_NOT_PERMITTED 0x00000068
++#define CKR_KEY_NOT_WRAPPABLE 0x00000069
++#define CKR_KEY_UNEXTRACTABLE 0x0000006A
++
++#define CKR_MECHANISM_INVALID 0x00000070
++#define CKR_MECHANISM_PARAM_INVALID 0x00000071
++
++/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
++ * were removed for v2.0 */
++#define CKR_OBJECT_HANDLE_INVALID 0x00000082
++#define CKR_OPERATION_ACTIVE 0x00000090
++#define CKR_OPERATION_NOT_INITIALIZED 0x00000091
++#define CKR_PIN_INCORRECT 0x000000A0
++#define CKR_PIN_INVALID 0x000000A1
++#define CKR_PIN_LEN_RANGE 0x000000A2
++
++/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
++#define CKR_PIN_EXPIRED 0x000000A3
++#define CKR_PIN_LOCKED 0x000000A4
++
++#define CKR_SESSION_CLOSED 0x000000B0
++#define CKR_SESSION_COUNT 0x000000B1
++#define CKR_SESSION_HANDLE_INVALID 0x000000B3
++#define CKR_SESSION_PARALLEL_NOT_SUPPORTED 0x000000B4
++#define CKR_SESSION_READ_ONLY 0x000000B5
++#define CKR_SESSION_EXISTS 0x000000B6
++
++/* CKR_SESSION_READ_ONLY_EXISTS and
++ * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
++#define CKR_SESSION_READ_ONLY_EXISTS 0x000000B7
++#define CKR_SESSION_READ_WRITE_SO_EXISTS 0x000000B8
++
++#define CKR_SIGNATURE_INVALID 0x000000C0
++#define CKR_SIGNATURE_LEN_RANGE 0x000000C1
++#define CKR_TEMPLATE_INCOMPLETE 0x000000D0
++#define CKR_TEMPLATE_INCONSISTENT 0x000000D1
++#define CKR_TOKEN_NOT_PRESENT 0x000000E0
++#define CKR_TOKEN_NOT_RECOGNIZED 0x000000E1
++#define CKR_TOKEN_WRITE_PROTECTED 0x000000E2
++#define CKR_UNWRAPPING_KEY_HANDLE_INVALID 0x000000F0
++#define CKR_UNWRAPPING_KEY_SIZE_RANGE 0x000000F1
++#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x000000F2
++#define CKR_USER_ALREADY_LOGGED_IN 0x00000100
++#define CKR_USER_NOT_LOGGED_IN 0x00000101
++#define CKR_USER_PIN_NOT_INITIALIZED 0x00000102
++#define CKR_USER_TYPE_INVALID 0x00000103
++
++/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
++ * are new to v2.01 */
++#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000104
++#define CKR_USER_TOO_MANY_TYPES 0x00000105
++
++#define CKR_WRAPPED_KEY_INVALID 0x00000110
++#define CKR_WRAPPED_KEY_LEN_RANGE 0x00000112
++#define CKR_WRAPPING_KEY_HANDLE_INVALID 0x00000113
++#define CKR_WRAPPING_KEY_SIZE_RANGE 0x00000114
++#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115
++#define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120
++
++/* These are new to v2.0 */
++#define CKR_RANDOM_NO_RNG 0x00000121
++
++/* These are new to v2.11 */
++#define CKR_DOMAIN_PARAMS_INVALID 0x00000130
++
++/* These are new to v2.0 */
++#define CKR_BUFFER_TOO_SMALL 0x00000150
++#define CKR_SAVED_STATE_INVALID 0x00000160
++#define CKR_INFORMATION_SENSITIVE 0x00000170
++#define CKR_STATE_UNSAVEABLE 0x00000180
++
++/* These are new to v2.01 */
++#define CKR_CRYPTOKI_NOT_INITIALIZED 0x00000190
++#define CKR_CRYPTOKI_ALREADY_INITIALIZED 0x00000191
++#define CKR_MUTEX_BAD 0x000001A0
++#define CKR_MUTEX_NOT_LOCKED 0x000001A1
++
++/* This is new to v2.20 */
++#define CKR_FUNCTION_REJECTED 0x00000200
++
++#define CKR_VENDOR_DEFINED 0x80000000
++
++
++/* CK_NOTIFY is an application callback that processes events */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
++ CK_SESSION_HANDLE hSession, /* the session's handle */
++ CK_NOTIFICATION event,
++ CK_VOID_PTR pApplication /* passed to C_OpenSession */
++);
++
++
++/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
++ * version and pointers of appropriate types to all the
++ * Cryptoki functions */
++/* CK_FUNCTION_LIST is new for v2.0 */
++typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
++
++typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
++
++typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
++
++
++/* CK_CREATEMUTEX is an application callback for creating a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
++ CK_VOID_PTR_PTR ppMutex /* location to receive ptr to mutex */
++);
++
++
++/* CK_DESTROYMUTEX is an application callback for destroying a
++ * mutex object */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_LOCKMUTEX is an application callback for locking a mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_UNLOCKMUTEX is an application callback for unlocking a
++ * mutex */
++typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
++ CK_VOID_PTR pMutex /* pointer to mutex */
++);
++
++
++/* CK_C_INITIALIZE_ARGS provides the optional arguments to
++ * C_Initialize */
++typedef struct CK_C_INITIALIZE_ARGS {
++ CK_CREATEMUTEX CreateMutex;
++ CK_DESTROYMUTEX DestroyMutex;
++ CK_LOCKMUTEX LockMutex;
++ CK_UNLOCKMUTEX UnlockMutex;
++ CK_FLAGS flags;
++ CK_VOID_PTR pReserved;
++} CK_C_INITIALIZE_ARGS;
++
++/* flags: bit flags that provide capabilities of the slot
++ * Bit Flag Mask Meaning
++ */
++#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
++#define CKF_OS_LOCKING_OK 0x00000002
++
++typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
++
++
++/* additional flags for parameters to functions */
++
++/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
++#define CKF_DONT_BLOCK 1
++
++/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message
++ * Generation Function (MGF) applied to a message block when
++ * formatting a message block for the PKCS #1 OAEP encryption
++ * scheme. */
++typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
++
++typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
++
++/* The following MGFs are defined */
++/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
++ * are new for v2.20 */
++#define CKG_MGF1_SHA1 0x00000001
++#define CKG_MGF1_SHA256 0x00000002
++#define CKG_MGF1_SHA384 0x00000003
++#define CKG_MGF1_SHA512 0x00000004
++
++/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
++ * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source
++ * of the encoding parameter when formatting a message block
++ * for the PKCS #1 OAEP encryption scheme. */
++typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
++
++typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
++
++/* The following encoding parameter sources are defined */
++#define CKZ_DATA_SPECIFIED 0x00000001
++
++/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
++ * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_OAEP mechanism. */
++typedef struct CK_RSA_PKCS_OAEP_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
++ CK_VOID_PTR pSourceData;
++ CK_ULONG ulSourceDataLen;
++} CK_RSA_PKCS_OAEP_PARAMS;
++
++typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
++
++/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
++ * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
++ * CKM_RSA_PKCS_PSS mechanism(s). */
++typedef struct CK_RSA_PKCS_PSS_PARAMS {
++ CK_MECHANISM_TYPE hashAlg;
++ CK_RSA_PKCS_MGF_TYPE mgf;
++ CK_ULONG sLen;
++} CK_RSA_PKCS_PSS_PARAMS;
++
++typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
++
++/* CK_EC_KDF_TYPE is new for v2.11. */
++typedef CK_ULONG CK_EC_KDF_TYPE;
++
++/* The following EC Key Derivation Functions are defined */
++#define CKD_NULL 0x00000001
++#define CKD_SHA1_KDF 0x00000002
++
++/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
++ * where each party contributes one key pair.
++ */
++typedef struct CK_ECDH1_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_ECDH1_DERIVE_PARAMS;
++
++typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
++
++
++/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
++ * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
++typedef struct CK_ECDH2_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_ECDH2_DERIVE_PARAMS;
++
++typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_ECMQV_DERIVE_PARAMS {
++ CK_EC_KDF_TYPE kdf;
++ CK_ULONG ulSharedDataLen;
++ CK_BYTE_PTR pSharedData;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_ECMQV_DERIVE_PARAMS;
++
++typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
++
++/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
++ * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
++typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
++typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
++
++/* The following X9.42 DH key derivation functions are defined
++ (besides CKD_NULL already defined : */
++#define CKD_SHA1_KDF_ASN1 0x00000003
++#define CKD_SHA1_KDF_CONCATENATE 0x00000004
++
++/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
++ * contributes one key pair */
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_X9_42_DH1_DERIVE_PARAMS;
++
++typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
++
++/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
++ * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
++ * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
++ * mechanisms, where each party contributes two key pairs */
++typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++} CK_X9_42_DH2_DERIVE_PARAMS;
++
++typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
++
++typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
++ CK_X9_42_DH_KDF_TYPE kdf;
++ CK_ULONG ulOtherInfoLen;
++ CK_BYTE_PTR pOtherInfo;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPrivateDataLen;
++ CK_OBJECT_HANDLE hPrivateData;
++ CK_ULONG ulPublicDataLen2;
++ CK_BYTE_PTR pPublicData2;
++ CK_OBJECT_HANDLE publicKey;
++} CK_X9_42_MQV_DERIVE_PARAMS;
++
++typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
++
++/* CK_KEA_DERIVE_PARAMS provides the parameters to the
++ * CKM_KEA_DERIVE mechanism */
++/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
++typedef struct CK_KEA_DERIVE_PARAMS {
++ CK_BBOOL isSender;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pRandomB;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++} CK_KEA_DERIVE_PARAMS;
++
++typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
++
++
++/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
++ * CKM_RC2_MAC mechanisms. An instance of CK_RC2_PARAMS just
++ * holds the effective keysize */
++typedef CK_ULONG CK_RC2_PARAMS;
++
++typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
++
++
++/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
++ * mechanism */
++typedef struct CK_RC2_CBC_PARAMS {
++ /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
++ * v2.0 */
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++
++ CK_BYTE iv[8]; /* IV for CBC mode */
++} CK_RC2_CBC_PARAMS;
++
++typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
++
++
++/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC2_MAC_GENERAL mechanism */
++/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC2_MAC_GENERAL_PARAMS {
++ CK_ULONG ulEffectiveBits; /* effective bits (1-1024) */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC2_MAC_GENERAL_PARAMS;
++
++typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC2_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
++ * CKM_RC5_MAC mechanisms */
++/* CK_RC5_PARAMS is new for v2.0 */
++typedef struct CK_RC5_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++} CK_RC5_PARAMS;
++
++typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
++
++
++/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
++ * mechanism */
++/* CK_RC5_CBC_PARAMS is new for v2.0 */
++typedef struct CK_RC5_CBC_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_BYTE_PTR pIv; /* pointer to IV */
++ CK_ULONG ulIvLen; /* length of IV in bytes */
++} CK_RC5_CBC_PARAMS;
++
++typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
++
++
++/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
++ * CKM_RC5_MAC_GENERAL mechanism */
++/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef struct CK_RC5_MAC_GENERAL_PARAMS {
++ CK_ULONG ulWordsize; /* wordsize in bits */
++ CK_ULONG ulRounds; /* number of rounds */
++ CK_ULONG ulMacLength; /* Length of MAC in bytes */
++} CK_RC5_MAC_GENERAL_PARAMS;
++
++typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
++ CK_RC5_MAC_GENERAL_PARAMS_PTR;
++
++
++/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
++ * ciphers' MAC_GENERAL mechanisms. Its value is the length of
++ * the MAC */
++/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_MAC_GENERAL_PARAMS;
++
++typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
++
++/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
++typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[8];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
++ CK_BYTE iv[16];
++ CK_BYTE_PTR pData;
++ CK_ULONG length;
++} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
++
++typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
++
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
++/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pPassword;
++ CK_ULONG ulPublicDataLen;
++ CK_BYTE_PTR pPublicData;
++ CK_ULONG ulPAndGLen;
++ CK_ULONG ulQLen;
++ CK_ULONG ulRandomLen;
++ CK_BYTE_PTR pRandomA;
++ CK_BYTE_PTR pPrimeP;
++ CK_BYTE_PTR pBaseG;
++ CK_BYTE_PTR pSubprimeQ;
++} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
++
++typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
++ CK_SKIPJACK_PRIVATE_WRAP_PTR;
++
++
++/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
++ * CKM_SKIPJACK_RELAYX mechanism */
++/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
++typedef struct CK_SKIPJACK_RELAYX_PARAMS {
++ CK_ULONG ulOldWrappedXLen;
++ CK_BYTE_PTR pOldWrappedX;
++ CK_ULONG ulOldPasswordLen;
++ CK_BYTE_PTR pOldPassword;
++ CK_ULONG ulOldPublicDataLen;
++ CK_BYTE_PTR pOldPublicData;
++ CK_ULONG ulOldRandomLen;
++ CK_BYTE_PTR pOldRandomA;
++ CK_ULONG ulNewPasswordLen;
++ CK_BYTE_PTR pNewPassword;
++ CK_ULONG ulNewPublicDataLen;
++ CK_BYTE_PTR pNewPublicData;
++ CK_ULONG ulNewRandomLen;
++ CK_BYTE_PTR pNewRandomA;
++} CK_SKIPJACK_RELAYX_PARAMS;
++
++typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
++ CK_SKIPJACK_RELAYX_PARAMS_PTR;
++
++
++typedef struct CK_PBE_PARAMS {
++ CK_BYTE_PTR pInitVector;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG ulPasswordLen;
++ CK_BYTE_PTR pSalt;
++ CK_ULONG ulSaltLen;
++ CK_ULONG ulIteration;
++} CK_PBE_PARAMS;
++
++typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
++
++
++/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
++ * CKM_KEY_WRAP_SET_OAEP mechanism */
++/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
++typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
++ CK_BYTE bBC; /* block contents byte */
++ CK_BYTE_PTR pX; /* extra data */
++ CK_ULONG ulXLen; /* length of extra data in bytes */
++} CK_KEY_WRAP_SET_OAEP_PARAMS;
++
++typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
++ CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_SSL3_RANDOM_DATA;
++
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_VERSION_PTR pVersion;
++} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
++
++typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hClientMacSecret;
++ CK_OBJECT_HANDLE hServerMacSecret;
++ CK_OBJECT_HANDLE hClientKey;
++ CK_OBJECT_HANDLE hServerKey;
++ CK_BYTE_PTR pIVClient;
++ CK_BYTE_PTR pIVServer;
++} CK_SSL3_KEY_MAT_OUT;
++
++typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
++
++
++typedef struct CK_SSL3_KEY_MAT_PARAMS {
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_BBOOL bIsExport;
++ CK_SSL3_RANDOM_DATA RandomInfo;
++ CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_SSL3_KEY_MAT_PARAMS;
++
++typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
++
++/* CK_TLS_PRF_PARAMS is new for version 2.20 */
++typedef struct CK_TLS_PRF_PARAMS {
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_TLS_PRF_PARAMS;
++
++typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
++
++/* WTLS is new for version 2.20 */
++typedef struct CK_WTLS_RANDOM_DATA {
++ CK_BYTE_PTR pClientRandom;
++ CK_ULONG ulClientRandomLen;
++ CK_BYTE_PTR pServerRandom;
++ CK_ULONG ulServerRandomLen;
++} CK_WTLS_RANDOM_DATA;
++
++typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
++
++typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_BYTE_PTR pVersion;
++} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
++
++typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
++ CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
++
++typedef struct CK_WTLS_PRF_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_BYTE_PTR pSeed;
++ CK_ULONG ulSeedLen;
++ CK_BYTE_PTR pLabel;
++ CK_ULONG ulLabelLen;
++ CK_BYTE_PTR pOutput;
++ CK_ULONG_PTR pulOutputLen;
++} CK_WTLS_PRF_PARAMS;
++
++typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_OUT {
++ CK_OBJECT_HANDLE hMacSecret;
++ CK_OBJECT_HANDLE hKey;
++ CK_BYTE_PTR pIV;
++} CK_WTLS_KEY_MAT_OUT;
++
++typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
++
++typedef struct CK_WTLS_KEY_MAT_PARAMS {
++ CK_MECHANISM_TYPE DigestMechanism;
++ CK_ULONG ulMacSizeInBits;
++ CK_ULONG ulKeySizeInBits;
++ CK_ULONG ulIVSizeInBits;
++ CK_ULONG ulSequenceNumber;
++ CK_BBOOL bIsExport;
++ CK_WTLS_RANDOM_DATA RandomInfo;
++ CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
++} CK_WTLS_KEY_MAT_PARAMS;
++
++typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
++
++/* CMS is new for version 2.20 */
++typedef struct CK_CMS_SIG_PARAMS {
++ CK_OBJECT_HANDLE certificateHandle;
++ CK_MECHANISM_PTR pSigningMechanism;
++ CK_MECHANISM_PTR pDigestMechanism;
++ CK_UTF8CHAR_PTR pContentType;
++ CK_BYTE_PTR pRequestedAttributes;
++ CK_ULONG ulRequestedAttributesLen;
++ CK_BYTE_PTR pRequiredAttributes;
++ CK_ULONG ulRequiredAttributesLen;
++} CK_CMS_SIG_PARAMS;
++
++typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
++
++typedef struct CK_KEY_DERIVATION_STRING_DATA {
++ CK_BYTE_PTR pData;
++ CK_ULONG ulLen;
++} CK_KEY_DERIVATION_STRING_DATA;
++
++typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
++ CK_KEY_DERIVATION_STRING_DATA_PTR;
++
++
++/* The CK_EXTRACT_PARAMS is used for the
++ * CKM_EXTRACT_KEY_FROM_KEY mechanism. It specifies which bit
++ * of the base key should be used as the first bit of the
++ * derived key */
++/* CK_EXTRACT_PARAMS is new for v2.0 */
++typedef CK_ULONG CK_EXTRACT_PARAMS;
++
++typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
++
++/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
++ * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
++ * indicate the Pseudo-Random Function (PRF) used to generate
++ * key bits using PKCS #5 PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
++
++typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
++
++/* The following PRFs are defined in PKCS #5 v2.0. */
++#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
++
++
++/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
++ * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
++ * source of the salt value when deriving a key using PKCS #5
++ * PBKDF2. */
++typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
++
++typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
++
++/* The following salt value sources are defined in PKCS #5 v2.0. */
++#define CKZ_SALT_SPECIFIED 0x00000001
++
++/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
++ * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
++ * parameters to the CKM_PKCS5_PBKD2 mechanism. */
++typedef struct CK_PKCS5_PBKD2_PARAMS {
++ CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource;
++ CK_VOID_PTR pSaltSourceData;
++ CK_ULONG ulSaltSourceDataLen;
++ CK_ULONG iterations;
++ CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
++ CK_VOID_PTR pPrfData;
++ CK_ULONG ulPrfDataLen;
++ CK_UTF8CHAR_PTR pPassword;
++ CK_ULONG_PTR ulPasswordLen;
++} CK_PKCS5_PBKD2_PARAMS;
++
++typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
++
++#endif
+diff -r -u -N openssl-0.9.8g/demos/easy_tls/cacerts.pem openssl/demos/easy_tls/cacerts.pem
+--- openssl-0.9.8g/demos/easy_tls/cacerts.pem 2001-09-17 21:06:57.000000000 +0200
++++ openssl/demos/easy_tls/cacerts.pem 2007-10-25 01:27:09.000000000 +0200
+@@ -1,4 +1,4 @@
+-$Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
++$Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
+
+ issuer= /C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test PCA (1024 bit)
+ subject=/C=AU/ST=Queensland/O=CryptSoft Pty Ltd/CN=Test CA (1024 bit)
+diff -r -u -N openssl-0.9.8g/demos/easy_tls/cert.pem openssl/demos/easy_tls/cert.pem
+--- openssl-0.9.8g/demos/easy_tls/cert.pem 2001-09-17 21:06:57.000000000 +0200
++++ openssl/demos/easy_tls/cert.pem 2007-10-25 01:27:09.000000000 +0200
+@@ -1,4 +1,4 @@
+-$Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
++$Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
+
+ Example certificate and key.
+
+diff -r -u -N openssl-0.9.8g/demos/easy_tls/easy-tls.c openssl/demos/easy_tls/easy-tls.c
+--- openssl-0.9.8g/demos/easy_tls/easy-tls.c 2002-03-05 10:07:16.000000000 +0100
++++ openssl/demos/easy_tls/easy-tls.c 2007-10-25 01:27:09.000000000 +0200
+@@ -1,7 +1,7 @@
+ /* -*- Mode: C; c-file-style: "bsd" -*- */
+ /*
+ * easy-tls.c -- generic TLS proxy.
+- * $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
++ * $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
+ */
+ /*
+ (c) Copyright 1999 Bodo Moeller. All rights reserved.
+@@ -73,7 +73,7 @@
+ */
+
+ static char const rcsid[] =
+-"$Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $";
++"$Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $";
+
+ #include <assert.h>
+ #include <errno.h>
+diff -r -u -N openssl-0.9.8g/demos/easy_tls/easy-tls.h openssl/demos/easy_tls/easy-tls.h
+--- openssl-0.9.8g/demos/easy_tls/easy-tls.h 2001-09-17 21:06:59.000000000 +0200
++++ openssl/demos/easy_tls/easy-tls.h 2007-10-25 01:27:09.000000000 +0200
+@@ -1,7 +1,7 @@
+ /* -*- Mode: C; c-file-style: "bsd" -*- */
+ /*
+ * easy-tls.h -- generic TLS proxy.
+- * $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
++ * $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
+ */
+ /*
+ * (c) Copyright 1999 Bodo Moeller. All rights reserved.
+diff -r -u -N openssl-0.9.8g/demos/easy_tls/Makefile openssl/demos/easy_tls/Makefile
+--- openssl-0.9.8g/demos/easy_tls/Makefile 2001-09-18 11:15:40.000000000 +0200
++++ openssl/demos/easy_tls/Makefile 2007-10-25 01:27:09.000000000 +0200
+@@ -1,5 +1,5 @@
+ # Makefile for easy-tls example application (rudimentary client and server)
+-# $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
++# $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
+
+ SOLARIS_CFLAGS=-Wall -pedantic -g -O2
+ SOLARIS_LIBS=-lxnet
+diff -r -u -N openssl-0.9.8g/demos/easy_tls/test.c openssl/demos/easy_tls/test.c
+--- openssl-0.9.8g/demos/easy_tls/test.c 2001-09-17 21:06:59.000000000 +0200
++++ openssl/demos/easy_tls/test.c 2007-10-25 01:27:09.000000000 +0200
+@@ -1,5 +1,5 @@
+ /* test.c */
+-/* $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $ */
++/* $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $ */
+
+ #define L_PORT 9999
+ #define C_PORT 443
+diff -r -u -N openssl-0.9.8g/demos/easy_tls/test.h openssl/demos/easy_tls/test.h
+--- openssl-0.9.8g/demos/easy_tls/test.h 2001-09-17 21:07:00.000000000 +0200
++++ openssl/demos/easy_tls/test.h 2007-10-25 01:27:09.000000000 +0200
+@@ -1,5 +1,5 @@
+ /* test.h */
+-/* $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $ */
++/* $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $ */
+
+
+ void test_process_init(int fd, int client_p, void *apparg);
+diff -r -u -N openssl-0.9.8g/engines/vendor_defns/hwcryptohook.h openssl/engines/vendor_defns/hwcryptohook.h
+--- openssl-0.9.8g/engines/vendor_defns/hwcryptohook.h 2002-10-11 19:10:59.000000000 +0200
++++ openssl/engines/vendor_defns/hwcryptohook.h 2007-10-25 01:27:09.000000000 +0200
+@@ -65,7 +65,7 @@
+ * please contact nCipher.
+ *
+ *
+- * $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
++ * $Id: openssl-0.9.8g-patch,v 1.2 2008/03/31 14:42:50 fdupont Exp $
+ */
+
+ #ifndef HWCRYPTOHOOK_H
+diff -r -u -N openssl-0.9.8g/Makefile.org openssl/Makefile.org
+--- openssl-0.9.8g/Makefile.org 2007-04-24 01:49:54.000000000 +0200
++++ openssl/Makefile.org 2007-10-25 01:27:08.000000000 +0200
+@@ -26,6 +26,9 @@
+ INSTALL_PREFIX=
+ INSTALLTOP=/usr/local/ssl
+
++# You must set this through --pk11-libname configure option.
++PK11_LIB_LOCATION=
++
+ # Do not edit this manually. Use Configure --openssldir=DIR do change this!
+ OPENSSLDIR=/usr/local/ssl
+
+diff -r -u -N openssl-0.9.8g/README.pkcs11 openssl/README.pkcs11
+--- openssl-0.9.8g/README.pkcs11 1970-01-01 01:00:00.000000000 +0100
++++ openssl/README.pkcs11 2008-01-31 15:24:32.000000000 +0100
+@@ -0,0 +1,153 @@
++PKCS#11 engine support for OpenSSL 0.9.8g
++=========================================
++
++[Nov 21, 2007]
++
++This patch containing code available in OpenSolaris adds support for PKCS#11
++engine into OpenSSL and implements PKCS#11 v2.20. It is to be applied against
++OpenSSL 0.9.8g. Your system must provide PKCS#11 backend otherwise the patch
++is useless.
++
++Patch can be applied like this:
++
++ tar xfzv openssl-0.9.8g.tar.gz
++ cd openssl-0.9.8g
++ patch -p1 < ../pkcs11_engine-0.9.8g.patch.2007-11-21
++
++It is designed to support pure acceleration for RSA, DSA, DH and all the
++symetric ciphers and message digest algorithms that PKCS#11 and OpenSSL share
++except for missing support for patented algorithms MDC2, RC3, RC5 and IDEA.
++
++It also contains experimental code for accessing RSA keys stored in pkcs#11 key
++stores by reference. See below for more information.
++
++You must provide the location of PKCS#11 library in your system to the
++configure script, eg. if you use libraries from openCryptoki project on Linux
++AMD64 box, run configure like this:
++
++ ./config --pk11-libname=/usr/lib64/pkcs11/PKCS11_API.so
++
++To check whether newly built openssl really supports PKCS#11 it's enough to
++run "apps/openssl engine" and look for "(pkcs11) PKCS #11 engine support" in
++the output.
++
++This patch was tested on Solaris against PKCS#11 engine available from Solaris
++Cryptographic Framework (Solaris 10 and OpenSolaris) and also on Linux using
++PKCS#11 libraries from openCryptoki project (see openCryptoki website
++http://sourceforge.net/projects/opencryptoki for more information). Some Linux
++distributions even ship those libraries with the system. The patch should work
++on any system that is supported by OpenSSL itself and has functional PKCS#11
++library.
++
++The patch contains "RSA Security Inc. PKCS #11 Cryptographic Token Interface
++(Cryptoki)" - files cryptoki.h, pkcs11.h, pkcs11f.h and pkcs11t.h which are
++copyrighted by RSA Security Inc., see pkcs11.h for more information.
++
++Other added/modified code in this patch is copyrighted by Sun Microsystems,
++Inc. and is released under the OpenSSL license (see LICENSE file for more
++information).
++
++Revisions of patch for 0.9.8 branch
++===================================
++
++2007-11-21
++- update for 0.9.8g version
++- fixes in the draft code for "6607670 teach pkcs#11 engine how to use keys
++ be reference" so that it doesn't coredump when the referenced key is not
++ present
++
++2007-10-15
++- update for 0.9.8f version
++- update for "6607670 teach pkcs#11 engine how to use keys be reference"
++
++2007-10-02
++- draft for "6607670 teach pkcs#11 engine how to use keys be reference"
++- draft for "6607307 pkcs#11 engine can't read RSA private keys"
++
++2007-09-26
++- 6375348 Using pkcs11 as the SSLCryptoDevice with Apache/OpenSSL causes
++ significant performance drop
++- 6573196 memory is leaked when OpenSSL is used with PKCS#11 engine
++
++2007-05-25
++- 6558630 race in OpenSSL pkcs11 engine when using symetric block ciphers
++
++2007-05-19
++- initial patch for 0.9.8e using latest OpenSolaris code
++
++Notes
++=====
++
++This patch version contains not very well tested code for referencing RSA keys
++in keystores by labels. That code might and might not end up in OpenSolaris
++code base in the future. If you use this particular functionality with this
++patch I would be very grateful to get any feedback from you (please see my
++contact in the bottom).
++
++Issues
++------
++- can't reference public keys inside of certificates using certificate label
++- can't reference symetric keys
++- simple references in form of "pkcs11:LABEL" only are supported now. This is
++ supposed to be changed according to discussion on pkcs11 mailing list; comma
++ separated list of attributes is planned to be used.
++- getpassphrase(3c) is used for entering the PIN. This should be changed to a
++ more general approach; to check if the process has allocated tty and use
++ other means of entering the PIN if not.
++
++Usage
++-----
++See examples below using Solaris's pktool(1):
++
++# list private keys (note "mycert" label. Basically, we can't generate a
++# pub/priv key pair with pktool(1) without creating a certificate. This should
++# be changed in the future).
++$ pktool list objtype=private
++Enter PIN for Sun Software PKCS#11 softtoken :
++Found 1 keys.
++Key #1 - RSA private key: mycert
++
++# this file is going to be signed
++$ cat test
++hello
++
++# sign it, note "pkcs11:mycert" private key's label
++$ openssl rsautl -inkey pkcs11:mycert -out test2 -in test -sign -keyform e -engine pkcs11
++engine "pkcs11" set.
++Enter PIN:
++
++# export the certificate out of the keyring
++$ pktool export keystore=pkcs11 label=mycert outfile=mycert.cert outformat=pem
++Warning: file "mycert.cert" exists, will be overwritten.
++Continue with export? y
++
++# verify using OpenSSL without pkcs#11 engine and with the certificate in the
++# file. This is proof of concept that a file signed with key by reference is
++# successfully verified when stock OpenSSL is used (I didn't have public key
++# in the keystore, only the certificate. There is no way to reference a public
++# key inside of the certificate).
++$ openssl rsautl -verify -inkey mycert.cert -certin -in test2
++hello
++
++API
++---
++You can use ENGINE_load_public_key() and ENGINE_load_private_key() functions
++only. The 2nd parameter of those calls is the one to use for "pkcs11:LABEL"
++filename overloading. If used that way, both functions will look for the key
++in the available keystores. Only one such key must be present. The private key
++is never extracted from the keystore. See OpenSSL's engine(3) or header file
++openssl/engine.h for more information.
++
++Note that those functions return a pointer to EVP_PKEY structure that contains
++all necessary information for accesing the key by label then. The pointer can be
++used in other functions that work with RSA keys - X509_sign() for example. See
++source code in apps/ subdirectory for reference.
++
++Feedback
++========
++
++Please send feedback to security-discuss@opensolaris.org. The patch was
++created by Jan.Pechanec@Sun.COM from code available in OpenSolaris.
++
++Latest version should be always available on http://blogs.sun.com/janp.
++
diff --git a/contrib/pkcs11-keygen/readkey.c b/contrib/pkcs11-keygen/readkey.c
new file mode 100644
index 0000000..869717c
--- /dev/null
+++ b/contrib/pkcs11-keygen/readkey.c
@@ -0,0 +1,230 @@
+/* readkey [-s $slot] -l $label [-p $pin] -f $filename */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef OPENCRYPTOKI
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
+#else
+#include <opencryptoki/pkcs11.h>
+#endif
+#include <openssl/conf.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+
+static CK_BBOOL truevalue = TRUE;
+
+int
+main(int argc, char *argv[])
+{
+ RSA *rsa = NULL;
+ FILE *fp;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_UTF8CHAR *pin = NULL;
+ char *label;
+ CK_OBJECT_HANDLE key = CK_INVALID_HANDLE;
+ CK_OBJECT_CLASS kclass = CKO_PRIVATE_KEY;
+ char *filename;
+ int error = 0;
+ int i = 0;
+ int c, errflg = 0;
+ CK_ULONG ulObjectCount;
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_LABEL, NULL, 0},
+ {CKA_TOKEN, &truevalue, sizeof (truevalue)},
+ {CKA_CLASS, &kclass, sizeof (kclass)}
+ };
+ CK_BYTE id[32];
+ CK_BYTE data[8][1024];
+ CK_ATTRIBUTE attr_template[] = {
+ {CKA_ID, &id, sizeof (id)},
+ {CKA_MODULUS, (void *)data[0], 1024}, /* n */
+ {CKA_PUBLIC_EXPONENT, (void *)data[1], 1024}, /* e */
+ {CKA_PRIVATE_EXPONENT, (void *)data[2], 1024}, /* d */
+ {CKA_PRIME_1, (void *)data[3], 1024}, /* p */
+ {CKA_PRIME_2, (void *)data[4], 1024}, /* q */
+ {CKA_EXPONENT_1, (void *)data[5], 1024}, /* dmp1 */
+ {CKA_EXPONENT_2, (void *)data[6], 1024}, /* dmq1 */
+ {CKA_COEFFICIENT, (void *)data[7], 1024} /* iqmp */
+ };
+ extern char *optarg;
+ extern int optopt;
+
+ while ((c = getopt(argc, argv, ":s:l:p:f:")) != -1) {
+ switch (c) {
+ case 's':
+ slot = atoi(optarg);
+ break;
+ case 'l':
+ label = optarg;
+ break;
+ case 'p':
+ pin = (CK_UTF8CHAR *)optarg;
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n", optopt);
+ errflg++;
+ break;
+ case 'f':
+ filename = optarg;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n", optopt);
+ errflg++;
+ }
+ }
+ if ((errflg) || (!label) || (!filename)) {
+ fprintf(stderr,
+ "usage: readkey [-s slot] -l label [-p pin] -f filename\n");
+ exit(1);
+ }
+ if (slot)
+ printf("slot %d\n", slot);
+
+ /* Initialize OpenSSL library */
+ OPENSSL_config(NULL);
+ rsa = RSA_new();
+ if (!rsa) {
+ fprintf(stderr, "RSA_new failed\n");
+ ERR_print_errors_fp(stderr);
+ exit(1);
+ }
+
+ /* Initialize the CRYPTOKI library */
+ rv = C_Initialize(NULL_PTR);
+ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
+ fprintf(stderr, "C_Initialize: Error = 0x%.8X\n", rv);
+ exit(1);
+ }
+
+ /* Open a session on the slot found */
+ rv = C_OpenSession(slot, CKF_SERIAL_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_OpenSession: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_program;
+ }
+
+ /* Login to the Token (Keystore) */
+ if (!pin)
+#ifndef OPENCRYPTOKI
+ pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
+#else
+ pin = (CK_UTF8CHAR *)getpass("Enter Pin: ");
+#endif
+ rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin));
+ memset(pin, 0, strlen((char *)pin));
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_Login: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ /* Set search template. */
+ if (strstr(label, "pkcs11:") == label)
+ label = strstr(label, ":") + 1;
+ search_template[0].pValue = label;
+ search_template[0].ulValueLen = strlen(label);
+
+ rv = C_FindObjectsInit(hSession, search_template, 3);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ rv = C_FindObjects(hSession, &key, 1, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+ if (ulObjectCount == 0) {
+ fprintf(stderr, "C_FindObjects: can't find the key\n");
+ error = 1;
+ goto exit_search;
+ }
+
+ rv = C_GetAttributeValue(hSession, key, attr_template, 9);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_GetAttributeValue: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+
+ printf("ID[%u]=", attr_template[0].ulValueLen);
+ for (i = 0; i < attr_template[0].ulValueLen; i++)
+ printf("%02x", id[i]);
+ printf("\n");
+
+ if (attr_template[1].ulValueLen > 0)
+ rsa->n = BN_bin2bn(data[0], attr_template[1].ulValueLen, NULL);
+ if (attr_template[2].ulValueLen > 0)
+ rsa->e = BN_bin2bn(data[1], attr_template[2].ulValueLen, NULL);
+ if (attr_template[3].ulValueLen > 0)
+ rsa->d = BN_bin2bn(data[2], attr_template[3].ulValueLen, NULL);
+ if (attr_template[4].ulValueLen > 0)
+ rsa->p = BN_bin2bn(data[3], attr_template[4].ulValueLen, NULL);
+ if (attr_template[5].ulValueLen > 0)
+ rsa->q = BN_bin2bn(data[4], attr_template[5].ulValueLen, NULL);
+ if (attr_template[6].ulValueLen > 0)
+ rsa->dmp1 = BN_bin2bn(data[5], attr_template[6].ulValueLen, NULL);
+ if (attr_template[7].ulValueLen > 0)
+ rsa->dmq1 = BN_bin2bn(data[6], attr_template[7].ulValueLen, NULL);
+ if (attr_template[8].ulValueLen > 0)
+ rsa->iqmp = BN_bin2bn(data[7], attr_template[8].ulValueLen, NULL);
+
+ rv = C_FindObjects(hSession, &key, 1, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+ if (ulObjectCount != 0) {
+ fprintf(stderr, "C_FindObjects: found extra keys?\n");
+ error = 1;
+ goto exit_search;
+ }
+
+ printf("RSA=");
+ RSA_print_fp(stdout, rsa, 4);
+
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ printf("Error opening output file.\n");
+ error = 1;
+ goto exit_search;
+ }
+
+ if (!PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL)) {
+ printf("Error writing output file.\n");
+ ERR_print_errors_fp(stderr);
+ error = 1;
+ goto exit_search;
+ }
+
+ exit_search:
+ rv = C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8X\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ (void) C_CloseSession(hSession);
+
+ exit_program:
+ (void) C_Finalize(NULL_PTR);
+
+ exit(error);
+}
diff --git a/contrib/pkcs11-keygen/set_key_id.c b/contrib/pkcs11-keygen/set_key_id.c
new file mode 100644
index 0000000..5c3a3c4
--- /dev/null
+++ b/contrib/pkcs11-keygen/set_key_id.c
@@ -0,0 +1,159 @@
+/* set_key_id [-s slot] [-p $pin] -n $keytag {-i $id | -l $label} */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef OPENCRYPTOKI
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
+#else
+#include <opencryptoki/pkcs11.h>
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_UTF8CHAR *pin = NULL;
+ CK_BYTE old_id[2], new_id[2];
+ CK_OBJECT_HANDLE akey;
+ int error = 0;
+ int i = 0;
+ int c, errflg = 0;
+ char *label = NULL;
+ CK_ULONG ulObjectCount;
+ int oid = 0, nid = 0;
+ CK_ATTRIBUTE search_template[] = {
+ {CKA_ID, &old_id, sizeof(old_id)}
+ };
+ extern char *optarg;
+ extern int optopt;
+
+ while ((c = getopt(argc, argv, ":s:i:n:l:p:")) != -1) {
+ switch (c) {
+ case 's':
+ slot = atoi(optarg);
+ break;
+ case 'i':
+ oid = atoi(optarg);
+ oid &= 0xffff;
+ old_id[0] = (oid >> 8) & 0xff;
+ old_id[1] = oid & 0xff;
+ break;
+ case 'n':
+ nid = atoi(optarg);
+ nid &= 0xffff;
+ new_id[0] = (nid >> 8) & 0xff;
+ new_id[1] = nid & 0xff;
+ break;
+ case 'l':
+ label = optarg;
+ break;
+ case 'p':
+ pin = (CK_UTF8CHAR *)optarg;
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n", optopt);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n", optopt);
+ errflg++;
+ }
+ }
+ if ((errflg) || (!nid) || ((!oid) && (!label))) {
+ fprintf(stderr,
+ "usage: set_key_id [-s slot] [-p pin] -n new_id "
+ "{ -i old_id | -l label }\n");
+ exit(1);
+ }
+ if (!label)
+ printf("old %i new %i\n", oid, nid);
+ else {
+ printf("label %s new %i\n", label, nid);
+ search_template[0].type = CKA_LABEL;
+ search_template[0].pValue = label;
+ search_template[0].ulValueLen = strlen(label);
+ }
+
+ /* Initialize the CRYPTOKI library */
+ rv = C_Initialize(NULL_PTR);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_Initialize: Error = 0x%.8X\n", rv);
+ exit(1);
+ }
+
+ /* Open a session on the slot found */
+ rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_OpenSession: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_program;
+ }
+
+ /* Login to the Token (Keystore) */
+ if (!pin)
+#ifndef OPENCRYPTOKI
+ pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
+#else
+ pin = (CK_UTF8CHAR *)getpass("Enter Pin: ");
+#endif
+ rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin));
+ memset(pin, 0, strlen((char *)pin));
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_Login: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ rv = C_FindObjectsInit(hSession, search_template, 1);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ ulObjectCount = 1;
+ while(ulObjectCount) {
+ rv = C_FindObjects(hSession, &akey, 1, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_search;
+ } else if (ulObjectCount) {
+ /* Set update template. */
+ CK_ATTRIBUTE new_template[] = {
+ {CKA_ID, &new_id, sizeof(new_id)}
+ };
+
+ rv = C_SetAttributeValue(hSession, akey, new_template, 1);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_SetAttributeValue: rv = 0x%.8X\n", rv);
+ error = 1;
+ }
+ }
+ }
+
+ exit_search:
+ rv = C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8X\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ (void) C_CloseSession(hSession);
+
+ exit_program:
+ (void) C_Finalize(NULL_PTR);
+
+ exit(error);
+}
diff --git a/contrib/pkcs11-keygen/writekey.c b/contrib/pkcs11-keygen/writekey.c
new file mode 100644
index 0000000..3d1ba99
--- /dev/null
+++ b/contrib/pkcs11-keygen/writekey.c
@@ -0,0 +1,360 @@
+/* writekey [-s $slot] [-p $pin] -l $label -i $id -f $filename */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#ifndef OPENCRYPTOKI
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
+#else
+#include <opencryptoki/pkcs11.h>
+#endif
+#include <openssl/conf.h>
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+
+/* Define static key template values */
+static CK_BBOOL truevalue = TRUE;
+static CK_BBOOL falsevalue = FALSE;
+
+int
+main(int argc, char *argv[])
+{
+ ENGINE *e;
+ RSA *rsa = NULL;
+ FILE *fp;
+ CK_RV rv;
+ CK_SLOT_ID slot = 0;
+ CK_SESSION_HANDLE hSession;
+ CK_UTF8CHAR *pin = NULL;
+ CK_BYTE new_id[2];
+ CK_OBJECT_HANDLE key = CK_INVALID_HANDLE;
+ CK_OBJECT_CLASS kclass;
+ CK_KEY_TYPE ktype = CKK_RSA;
+ CK_ATTRIBUTE template[50];
+ CK_ULONG template_size;
+ CK_BYTE data[8][1024];
+ CK_ULONG ulObjectCount;
+ char *label = NULL, *filename = NULL;
+ int id = 0;
+ int error = 0;
+ int c, errflg = 0;
+ extern char *optarg;
+ extern int optopt;
+
+ while ((c = getopt(argc, argv, ":s:l:i:p:f:")) != -1) {
+ switch (c) {
+ case 's':
+ slot = atoi(optarg);
+ break;
+ case 'l':
+ label = optarg;
+ break;
+ case 'i':
+ id = atoi(optarg);
+ id &= 0xffff;
+ break;
+ case 'p':
+ pin = (CK_UTF8CHAR *)optarg;
+ break;
+ case 'f':
+ filename = optarg;
+ break;
+ case ':':
+ fprintf(stderr, "Option -%c requires an operand\n", optopt);
+ errflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "Unrecognised option: -%c\n", optopt);
+ errflg++;
+ }
+ }
+ if ((errflg) || (!label) || (!id) || (!filename)) {
+ fprintf(stderr,
+ "usage: writekey [-s slot] [-p pin] -l label -i id "
+ "-f filename\n");
+ exit(2);
+ }
+
+ /* Load the config file */
+ OPENSSL_config(NULL);
+
+ /* Register engine */
+ e = ENGINE_by_id("pkcs11");
+ if (!e) {
+ /* the engine isn't available */
+ printf("The engine isn't available\n");
+ ERR_print_errors_fp(stderr);
+ exit(1);
+ }
+
+ if (!ENGINE_init(e)) {
+ /* the engine couldn't initialise, release 'e' */
+ printf("The engine couldn't initialise\n");
+ ERR_print_errors_fp(stderr);
+ ENGINE_free(e);
+ exit(1);
+ }
+
+ /* Read the key */
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ printf("Error opening input file.\n");
+ ENGINE_free(e);
+ exit(1);
+ }
+
+ rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
+ (void) fclose(fp);
+ if (rsa == NULL) {
+ printf("Error reading input file.\n");
+ ERR_print_errors_fp(stderr);
+ ENGINE_free(e);
+ exit(1);
+ }
+
+ /* Initialize the CRYPTOKI library */
+ rv = C_Initialize(NULL_PTR);
+ if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
+ fprintf(stderr, "C_Initialize: Error = 0x%.8X\n", rv);
+ ENGINE_free(e);
+ exit(1);
+ }
+
+ /* Open a session on the slot found */
+ rv = C_OpenSession(slot, CKF_RW_SESSION+CKF_SERIAL_SESSION,
+ NULL_PTR, NULL_PTR, &hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_OpenSession: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_program;
+ }
+
+ /* Login to the Token (Keystore) */
+ if (!pin)
+#ifndef OPENCRYPTOKI
+ pin = (CK_UTF8CHAR *)getpassphrase("Enter Pin: ");
+#else
+ pin = (CK_UTF8CHAR *)getpass("Enter Pin: ");
+#endif
+ rv = C_Login(hSession, CKU_USER, pin, strlen((char *)pin));
+ memset(pin, 0, strlen((char *)pin));
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_Login: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+
+ /* fill the search template */
+ if (strstr(label, "pkcs11:") == label)
+ label = strstr(label, ":") + 1;
+ kclass = CKO_PRIVATE_KEY;
+ template[0].type = CKA_TOKEN;
+ template[0].pValue = &truevalue;
+ template[0].ulValueLen = sizeof (truevalue);
+ template[1].type = CKA_CLASS;
+ template[1].pValue = &kclass;
+ template[1].ulValueLen = sizeof (kclass);
+ template[2].type = CKA_LABEL;
+ template[2].pValue = label;
+ template[2].ulValueLen = strlen(label);
+
+ /* check if a key with the same label already exists */
+ rv = C_FindObjectsInit(hSession, template, 3);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsInit: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_session;
+ }
+ rv = C_FindObjects(hSession, &key, 1, &ulObjectCount);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjects: Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+ if (ulObjectCount != 0) {
+ fprintf(stderr, "Key already exists.\n");
+ error = 1;
+ goto exit_search;
+ }
+
+ /* fill attributes for the public key */
+ new_id[0] = (id >> 8) & 0xff;
+ new_id[1] = id & 0xff;
+ kclass = CKO_PUBLIC_KEY;
+ if (BN_num_bytes(rsa->n) > 1024) {
+ fprintf(stderr, "RSA modulus too large\n");
+ error = 1;
+ goto exit_search;
+ }
+ BN_bn2bin(rsa->n, data[0]);
+ if (BN_num_bytes(rsa->e) > 1024) {
+ fprintf(stderr, "RSA public exponent too large\n");
+ error = 1;
+ goto exit_search;
+ }
+ BN_bn2bin(rsa->e, data[1]);
+ if (BN_num_bytes(rsa->d) > 1024) {
+ fprintf(stderr, "RSA private exponent too large\n");
+ error = 1;
+ goto exit_search;
+ }
+ BN_bn2bin(rsa->d, data[2]);
+ if (BN_num_bytes(rsa->p) > 1024) {
+ fprintf(stderr, "RSA prime 1 too large\n");
+ error = 1;
+ goto exit_search;
+ }
+ BN_bn2bin(rsa->p, data[3]);
+ if (BN_num_bytes(rsa->q) > 1024) {
+ fprintf(stderr, "RSA prime 2 too large\n");
+ error = 1;
+ goto exit_search;
+ }
+ BN_bn2bin(rsa->q, data[4]);
+ if (BN_num_bytes(rsa->dmp1) > 1024) {
+ fprintf(stderr, "RSA exponent 1 too large\n");
+ error = 1;
+ goto exit_search;
+ }
+ BN_bn2bin(rsa->dmp1, data[5]);
+ if (BN_num_bytes(rsa->dmq1) > 1024) {
+ fprintf(stderr, "RSA exponent 2 too large\n");
+ error = 1;
+ goto exit_search;
+ }
+ BN_bn2bin(rsa->dmq1, data[6]);
+ if (BN_num_bytes(rsa->iqmp) > 1024) {
+ fprintf(stderr, "RSA coefficient too large\n");
+ error = 1;
+ goto exit_search;
+ }
+ BN_bn2bin(rsa->iqmp, data[7]);
+
+ template[0].type = CKA_TOKEN;
+ template[0].pValue = &truevalue;
+ template[0].ulValueLen = sizeof (truevalue);
+ template[1].type = CKA_CLASS;
+ template[1].pValue = &kclass;
+ template[1].ulValueLen = sizeof (kclass);
+ template[2].type = CKA_LABEL;
+ template[2].pValue = label;
+ template[2].ulValueLen = strlen(label);
+ template[3].type = CKA_ID;
+ template[3].pValue = new_id;
+ template[3].ulValueLen = sizeof (new_id);
+ template[4].type = CKA_KEY_TYPE;
+ template[4].pValue = &ktype;
+ template[4].ulValueLen = sizeof (ktype);
+ template[5].type = CKA_ENCRYPT;
+ template[5].pValue = &truevalue;
+ template[5].ulValueLen = sizeof (truevalue);
+ template[6].type = CKA_VERIFY;
+ template[6].pValue = &truevalue;
+ template[6].ulValueLen = sizeof (truevalue);
+ template[7].type = CKA_VERIFY_RECOVER;
+ template[7].pValue = &truevalue;
+ template[7].ulValueLen = sizeof (truevalue);
+ template[8].type = CKA_MODULUS;
+ template[8].pValue = data[0];
+ template[8].ulValueLen = BN_num_bytes(rsa->n);
+ template[9].type = CKA_PUBLIC_EXPONENT;
+ template[9].pValue = data[1];
+ template[9].ulValueLen = BN_num_bytes(rsa->e);
+
+ rv = C_CreateObject(hSession, template, 10, &key);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_CreateObject (pub): Error = 0x%.8X\n", rv);
+ error = 1;
+ goto exit_search;
+ }
+
+ /* fill attributes for the private key */
+ kclass = CKO_PRIVATE_KEY;
+ template[0].type = CKA_TOKEN;
+ template[0].pValue = &truevalue;
+ template[0].ulValueLen = sizeof (truevalue);
+ template[1].type = CKA_CLASS;
+ template[1].pValue = &kclass;
+ template[1].ulValueLen = sizeof (kclass);
+ template[2].type = CKA_LABEL;
+ template[2].pValue = label;
+ template[2].ulValueLen = strlen(label);
+ template[3].type = CKA_ID;
+ template[3].pValue = new_id;
+ template[3].ulValueLen = sizeof (new_id);
+ template[4].type = CKA_KEY_TYPE;
+ template[4].pValue = &ktype;
+ template[4].ulValueLen = sizeof (ktype);
+ template[5].type = CKA_SENSITIVE;
+ template[5].pValue = &falsevalue;
+ template[5].ulValueLen = sizeof (falsevalue);
+ template[6].type = CKA_EXTRACTABLE;
+ template[6].pValue = &truevalue;
+ template[6].ulValueLen = sizeof (truevalue);
+ template[7].type = CKA_DECRYPT;
+ template[7].pValue = &truevalue;
+ template[7].ulValueLen = sizeof (truevalue);
+ template[8].type = CKA_SIGN;
+ template[8].pValue = &truevalue;
+ template[8].ulValueLen = sizeof (truevalue);
+ template[9].type = CKA_SIGN_RECOVER;
+ template[9].pValue = &truevalue;
+ template[9].ulValueLen = sizeof (truevalue);
+ template[10].type = CKA_MODULUS;
+ template[10].pValue = data[0];
+ template[10].ulValueLen = BN_num_bytes(rsa->n);
+ template[11].type = CKA_PUBLIC_EXPONENT;
+ template[11].pValue = data[1];
+ template[11].ulValueLen = BN_num_bytes(rsa->e);
+ template[12].type = CKA_PRIVATE_EXPONENT;
+ template[12].pValue = data[2];
+ template[12].ulValueLen = BN_num_bytes(rsa->d);
+ template[13].type = CKA_PRIME_1;
+ template[13].pValue = data[3];
+ template[13].ulValueLen = BN_num_bytes(rsa->p);
+ template[14].type = CKA_PRIME_2;
+ template[14].pValue = data[4];
+ template[14].ulValueLen = BN_num_bytes(rsa->q);
+ template[15].type = CKA_EXPONENT_1;
+ template[15].pValue = data[5];
+ template[15].ulValueLen = BN_num_bytes(rsa->dmp1);
+ template[16].type = CKA_EXPONENT_2;
+ template[16].pValue = data[6];
+ template[16].ulValueLen = BN_num_bytes(rsa->dmq1);
+ template[17].type = CKA_COEFFICIENT;
+ template[17].pValue = data[7];
+ template[17].ulValueLen = BN_num_bytes(rsa->iqmp);
+
+ rv = C_CreateObject(hSession, template, 18, &key);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_CreateObject (priv): Error = 0x%.8X\n", rv);
+ (void) C_DestroyObject(hSession, key);
+ error = 1;
+ goto exit_search;
+ }
+
+ exit_search:
+ rv = C_FindObjectsFinal(hSession);
+ if (rv != CKR_OK) {
+ fprintf(stderr, "C_FindObjectsFinal: Error = 0x%.8X\n", rv);
+ error = 1;
+ }
+
+ exit_session:
+ (void) C_CloseSession(hSession);
+
+ exit_program:
+ (void) C_Finalize(NULL_PTR);
+ ENGINE_free(e);
+ ENGINE_cleanup();
+
+ exit(error);
+}
diff --git a/contrib/pkcs11-keygen/writekey.sh b/contrib/pkcs11-keygen/writekey.sh
new file mode 100755
index 0000000..9b235d0
--- /dev/null
+++ b/contrib/pkcs11-keygen/writekey.sh
@@ -0,0 +1,73 @@
+#!/bin/bash --debug
+
+usage="Usage: $0 -x ext -p pin -f keyrootname"
+tmp_file=/tmp/cur_pem.$$
+while getopts ":x:p:f:" opt; do
+ case $opt in
+ x ) ext=$OPTARG ;;
+ p ) pin=$OPTARG ;;
+ f ) root=$OPTARG ;;
+ \? ) echo $usage
+ exit 1 ;;
+ esac
+done
+shift $(($OPTIND -1))
+
+if [ ! "$ext" -o ! "$pin" -o ! "$root" ] ; then
+ echo $usage
+ exit 1
+fi
+
+keyfile=${root}.key
+privfile=${root}.private
+file=`basename $root | sed 's/^K//'`
+zone=`echo $file | awk -F+ '{ print $1 }' | sed 's/\.$//'`
+algo=`echo $file | awk -F+ '{ print $2 }'`
+tag=`echo $file | awk -F+ '{ print $3 }'`
+
+# debug
+echo 'zone: ' $zone
+echo 'algo: ' $algo
+echo 'tag: ' $tag
+
+if [ ! -r "$keyfile" ] ; then
+ echo "can't read " $keyfile
+ exit 1
+fi
+if [ ! -r "$privfile" ] ; then
+ echo "can't read " $privfile
+ exit 1
+fi
+
+if [ "$algo" != "005" ] ; then
+ echo 'algorithm must be 005'
+ exit 1
+fi
+
+# for testing
+mypath=.
+
+echo 'Reading key files'
+flag=`$mypath/keydump.pl -k $keyfile -p $privfile -o $tmp_file`
+
+if [ "$flag" = "256" ] ; then
+ label=$zone,zsk,$ext
+elif [ "$flag" = "257" ] ; then
+ label=$zone,ksk,$ext
+else
+ echo 'flag must be 256 or 257'
+ rm $tmp_file
+ exit 1
+fi
+
+echo "Label will be '"$label"'"
+$mypath/writekey -p $pin -l $label -i $tag -f $tmp_file
+
+rm $tmp_file
+
+echo 'Now you can add at the end of ' $privfile
+/usr/bin/perl <<EOF
+use MIME::Base64;
+print "Engine: ", encode_base64("pkcs11\0",""), "\n";
+print "Label: ", encode_base64("pkcs11:"."$label"."\0",""), "\n";
+EOF
diff --git a/contrib/query-loc-0.4.0/ADDRESSES b/contrib/query-loc-0.4.0/ADDRESSES
new file mode 100644
index 0000000..49fb7d8
--- /dev/null
+++ b/contrib/query-loc-0.4.0/ADDRESSES
@@ -0,0 +1,16 @@
+The following machines, at least today seem to have LOC
+records:
+
+147.210.73.0/24 (note the two /25 have different LOC, inherited differently)
+130.104.3.*
+Melanie.Tolna.Net
+204.92.254.*
+alink.net
+caida.org
+ckdhr.com
+distributed.net (rc5stats.distributed.net)
+nikhef.nl
+yahoo.com
+nic.af
+
+$Id: ADDRESSES,v 1.1 2008/02/15 01:47:15 marka Exp $
diff --git a/contrib/query-loc-0.4.0/ALGO b/contrib/query-loc-0.4.0/ALGO
new file mode 100644
index 0000000..4695dc1
--- /dev/null
+++ b/contrib/query-loc-0.4.0/ALGO
@@ -0,0 +1,48 @@
+Just for info, can be out of date.
+
+
+RFC 1876, 5.2, specially 5.2.3
+
+Important points:
+
+- LOC RRs are always attached to a *name*.
+- we can have two (or more) RRs for one address, one more specific than the other
+
+main
+ if (host is a name)
+ getLOCbyname
+ else # host is an IP address
+ gethostbyaddr
+ if (name)
+ getLOCbyname
+ # If there is none, do not search. We assume the above was sufficient # (But check 5.2.2)
+ else
+ getLOCbyaddress
+
+getLOCbyname (host)
+ get LOC for host
+ if (it exists)
+ OK
+ else
+ get all A records of the name
+ foreach A record
+ getLOCbyaddress
+ OK at the first one found
+ # we assume they are consistent
+ END
+
+getLOCbyaddress (address)
+ # May receive a mask. Otherwise, deduce it from the class
+ makeNetAddress
+ getLOCbynetwork
+
+getLOCbynetwork
+ get PTR and A for it
+ if (exist)
+ getLOCbyname
+ ******* DIFFICULT : we have to manage a stack. See the code
+ makeNetAddress (level--)
+ getLOCbynetwork
+ else
+ END
+
diff --git a/contrib/query-loc-0.4.0/INSTALL b/contrib/query-loc-0.4.0/INSTALL
new file mode 100644
index 0000000..97e740b
--- /dev/null
+++ b/contrib/query-loc-0.4.0/INSTALL
@@ -0,0 +1,9 @@
+Type './configure', then 'make' and (as root if necessary) 'make
+install'.
+
+It requires a recent libresolv, with loc_ntoa, but use an alternative
+which I provide, if not found.
+
+Tested on Linux (i386 and Alpha), Solaris (Sparc) and Digital Unix (Alpha).
+
+$Id: INSTALL,v 1.1 2008/02/15 01:47:15 marka Exp $
diff --git a/contrib/query-loc-0.4.0/Makefile.in b/contrib/query-loc-0.4.0/Makefile.in
new file mode 100644
index 0000000..eefa2ac
--- /dev/null
+++ b/contrib/query-loc-0.4.0/Makefile.in
@@ -0,0 +1,42 @@
+# $Id: Makefile.in,v 1.1 2008/02/15 01:47:15 marka Exp $
+CC=@CC@
+CFLAGS=@CFLAGS@
+LIBS=@LIBS@
+DESTDIR=@prefix@
+BINDIR=@prefix@/bin
+MANDIR=@prefix@/share/man/man1
+DISTRIB= README INSTALL ALGO USAGE ADDRESSES Makefile.in configure configure.in config.h.in install-sh loc.h loc.c query-loc.c loc_ntoa.c query-loc.1 reconf
+OBJS=query-loc.o loc.o @LOC_NTOA@
+VERSION=`grep VERSION loc.h | cut -d ' ' -f 3 | sed s/\"//g`
+
+all: query-loc
+
+query-loc: $(OBJS)
+ $(CC) -o $@ $(OBJS) $(LIBS)
+
+%.o: %.c loc.h
+ $(CC) $(CFLAGS) -c $<
+
+clean:
+ rm -f *.o query-loc *~
+
+distclean: clean
+ rm -f config.h config.cache config.log config.status Makefile
+
+dist: distrib
+
+distrib: clean
+ ./reconf
+ @(echo Query-Loc is version ${VERSION}; \
+ mkdir query-loc-${VERSION}; \
+ cp $(DISTRIB) query-loc-${VERSION};\
+ tar cvf query-loc-${VERSION}.tar query-loc-${VERSION}; \
+ rm -rf query-loc-${VERSION}; \
+ gzip -v -9 -f query-loc-${VERSION}.tar);
+
+install:
+ @INSTALL@ -m 0755 query-loc $(BINDIR)
+ if [ ! -d $(MANDIR) ]; then \
+ mkdir $(MANDIR); \
+ fi
+ @INSTALL@ -m 0644 query-loc.1 $(MANDIR)
diff --git a/contrib/query-loc-0.4.0/README b/contrib/query-loc-0.4.0/README
new file mode 100644
index 0000000..250b378
--- /dev/null
+++ b/contrib/query-loc-0.4.0/README
@@ -0,0 +1,21 @@
+ query-loc: a program to retrieve and display the location
+ information in the DNS.
+
+ It uses the algorithms described in
+ RFC 1876 (and RFC 1101 to get the network names).
+ You can find examples of networks wchich implement this scheme
+ in the ADDRESSES file.
+
+ It is under the General Public Licence (GPL, which
+ you can fetch from <http://www.gnu.org/copyleft/gpl.html>.
+
+ Copyright Stéphane Bortzmeyer <bortzmeyer@sources.org>, 1998-2007.
+
+ Thanks to Paul Vixie for the RFC and its encouragements. Thanks
+ to Björn Augustsson for the xtraceroute program
+ <http://www.dtek.chalmers.se/~d3august/xt/>. Thanks to Roland
+ Dirlewanger for extensive patching.
+
+$Id: README,v 1.1 2008/02/15 01:47:15 marka Exp $
+
+
diff --git a/contrib/query-loc-0.4.0/USAGE b/contrib/query-loc-0.4.0/USAGE
new file mode 100644
index 0000000..d3ee4c0
--- /dev/null
+++ b/contrib/query-loc-0.4.0/USAGE
@@ -0,0 +1,7 @@
+query-loc [-v] [-d nnn] host-name-or-address
+
+Examples of hosts with LOCation info (quite uncommon, if you know more,
+please tell me):
+
+See the ADDRESSES file
+
diff --git a/contrib/query-loc-0.4.0/config.h.in b/contrib/query-loc-0.4.0/config.h.in
new file mode 100644
index 0000000..d436639
--- /dev/null
+++ b/contrib/query-loc-0.4.0/config.h.in
@@ -0,0 +1,69 @@
+/* config.h.in. Generated from configure.in by autoheader. */
+/* $Id: config.h.in,v 1.1 2008/02/15 01:47:15 marka Exp $ */
+
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of a `char', as computed by sizeof. */
+#undef SIZEOF_CHAR
+
+/* The size of a `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of a `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of a `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Is there a loc_ntoa on this system? */
+#undef HAVE_LOC_NTOA
diff --git a/contrib/query-loc-0.4.0/configure b/contrib/query-loc-0.4.0/configure
new file mode 100755
index 0000000..d77cf76
--- /dev/null
+++ b/contrib/query-loc-0.4.0/configure
@@ -0,0 +1,6436 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="query-loc.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CPP EGREP LOC_NTOA LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_option in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_$ac_feature='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_$ac_package='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
+ else
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+ fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd "$ac_popdir"
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CC" && break
+done
+
+ CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std1 is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std1. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test "$GCC" = "yes"; then
+ CFLAGS="${CFLAGS} -Wall"
+fi
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f $ac_dir/shtool; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+ ./ | .// | /cC/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+done
+
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL=$ac_install_sh
+ fi
+fi
+echo "$as_me:$LINENO: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+
+
+echo "$as_me:$LINENO: checking for res_query in -lresolv" >&5
+echo $ECHO_N "checking for res_query in -lresolv... $ECHO_C" >&6
+if test "${ac_cv_lib_resolv_res_query+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lresolv $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char res_query ();
+int
+main ()
+{
+res_query ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_resolv_res_query=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_resolv_res_query=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_res_query" >&5
+echo "${ECHO_T}$ac_cv_lib_resolv_res_query" >&6
+if test $ac_cv_lib_resolv_res_query = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBRESOLV 1
+_ACEOF
+
+ LIBS="-lresolv $LIBS"
+
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+ ac_config_headers="$ac_config_headers config.h"
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+if test "${ac_cv_header_resolv_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for resolv.h" >&5
+echo $ECHO_N "checking for resolv.h... $ECHO_C" >&6
+if test "${ac_cv_header_resolv_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_resolv_h" >&5
+echo "${ECHO_T}$ac_cv_header_resolv_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking resolv.h usability" >&5
+echo $ECHO_N "checking resolv.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <resolv.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking resolv.h presence" >&5
+echo $ECHO_N "checking resolv.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <resolv.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: resolv.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: resolv.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: resolv.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: resolv.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: resolv.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: resolv.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: resolv.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: resolv.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: resolv.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: resolv.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: resolv.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: resolv.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: resolv.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: resolv.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: resolv.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: resolv.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for resolv.h" >&5
+echo $ECHO_N "checking for resolv.h... $ECHO_C" >&6
+if test "${ac_cv_header_resolv_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_resolv_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_resolv_h" >&5
+echo "${ECHO_T}$ac_cv_header_resolv_h" >&6
+
+fi
+if test $ac_cv_header_resolv_h = yes; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: \"No headers for name service applications\"" >&5
+echo "$as_me: error: \"No headers for name service applications\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+if test "${ac_cv_header_arpa_nameser_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for arpa/nameser.h" >&5
+echo $ECHO_N "checking for arpa/nameser.h... $ECHO_C" >&6
+if test "${ac_cv_header_arpa_nameser_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_arpa_nameser_h" >&5
+echo "${ECHO_T}$ac_cv_header_arpa_nameser_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking arpa/nameser.h usability" >&5
+echo $ECHO_N "checking arpa/nameser.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <arpa/nameser.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking arpa/nameser.h presence" >&5
+echo $ECHO_N "checking arpa/nameser.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <arpa/nameser.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: arpa/nameser.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: arpa/nameser.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: arpa/nameser.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: arpa/nameser.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: arpa/nameser.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: arpa/nameser.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: arpa/nameser.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: arpa/nameser.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: arpa/nameser.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: arpa/nameser.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: arpa/nameser.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: arpa/nameser.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: arpa/nameser.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: arpa/nameser.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: arpa/nameser.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: arpa/nameser.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for arpa/nameser.h" >&5
+echo $ECHO_N "checking for arpa/nameser.h... $ECHO_C" >&6
+if test "${ac_cv_header_arpa_nameser_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_arpa_nameser_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_arpa_nameser_h" >&5
+echo "${ECHO_T}$ac_cv_header_arpa_nameser_h" >&6
+
+fi
+if test $ac_cv_header_arpa_nameser_h = yes; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: \"No headers for name service applications\"" >&5
+echo "$as_me: error: \"No headers for name service applications\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+if test "${ac_cv_header_sys_time_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for sys/time.h" >&5
+echo $ECHO_N "checking for sys/time.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_time_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_time_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_time_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking sys/time.h usability" >&5
+echo $ECHO_N "checking sys/time.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <sys/time.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking sys/time.h presence" >&5
+echo $ECHO_N "checking sys/time.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/time.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: sys/time.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: sys/time.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/time.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: sys/time.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: sys/time.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: sys/time.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/time.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: sys/time.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/time.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: sys/time.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/time.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: sys/time.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/time.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: sys/time.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: sys/time.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: sys/time.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for sys/time.h" >&5
+echo $ECHO_N "checking for sys/time.h... $ECHO_C" >&6
+if test "${ac_cv_header_sys_time_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_sys_time_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_time_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_time_h" >&6
+
+fi
+if test $ac_cv_header_sys_time_h = yes; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: \"Mandatory header missing on your system\"" >&5
+echo "$as_me: error: \"Mandatory header missing on your system\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+if test "${ac_cv_header_unistd_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for unistd.h" >&5
+echo $ECHO_N "checking for unistd.h... $ECHO_C" >&6
+if test "${ac_cv_header_unistd_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_unistd_h" >&5
+echo "${ECHO_T}$ac_cv_header_unistd_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking unistd.h usability" >&5
+echo $ECHO_N "checking unistd.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <unistd.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking unistd.h presence" >&5
+echo $ECHO_N "checking unistd.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <unistd.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: unistd.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: unistd.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: unistd.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: unistd.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: unistd.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: unistd.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: unistd.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: unistd.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: unistd.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: unistd.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: unistd.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: unistd.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: unistd.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: unistd.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: unistd.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: unistd.h: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists. ##
+## ------------------------------------------ ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for unistd.h" >&5
+echo $ECHO_N "checking for unistd.h... $ECHO_C" >&6
+if test "${ac_cv_header_unistd_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_unistd_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_unistd_h" >&5
+echo "${ECHO_T}$ac_cv_header_unistd_h" >&6
+
+fi
+if test $ac_cv_header_unistd_h = yes; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: \"Mandatory header missing on your system\"" >&5
+echo "$as_me: error: \"Mandatory header missing on your system\"" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+echo "$as_me:$LINENO: checking if libnsl is mandatory" >&5
+echo $ECHO_N "checking if libnsl is mandatory... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <netinet/in.h>
+ #include <arpa/nameser.h>
+ #include <resolv.h>
+ union
+ {
+ HEADER hdr;
+ u_char buf[4096]; /* With RFC 2671, otherwise 512 is enough */
+ }
+ response;
+ char *domain;
+ int requested_type;
+int
+main ()
+{
+res_query(domain,
+ C_IN,
+ requested_type,
+ (u_char *) & response,
+ sizeof (response))
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; LIBS="${LIBS} -lnsl"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+echo "$as_me:$LINENO: checking loc_ntoa" >&5
+echo $ECHO_N "checking loc_ntoa... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <resolv.h>
+int
+main ()
+{
+ u_char *cp; char *result; loc_ntoa(cp, result)
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; cat >>confdefs.h <<\_ACEOF
+#define HAVE_LOC_NTOA 1
+_ACEOF
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ echo "$as_me:$LINENO: result: no, using the alternative" >&5
+echo "${ECHO_T}no, using the alternative" >&6; LOC_NTOA=loc_ntoa.o
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset x;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *ccp;
+ char **p;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ ccp = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++ccp;
+ p = (char**) ccp;
+ ccp = (char const *const *) p;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ }
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for long" >&5
+echo $ECHO_N "checking for long... $ECHO_C" >&6
+if test "${ac_cv_type_long+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((long *) 0)
+ return 0;
+if (sizeof (long))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_long=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_long=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_long" >&5
+echo "${ECHO_T}$ac_cv_type_long" >&6
+
+echo "$as_me:$LINENO: checking size of long" >&5
+echo $ECHO_N "checking size of long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$ac_cv_type_long" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (long))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_long=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5
+echo "$as_me: error: internal error: not reached in cross-compile" >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (long)); }
+unsigned long ulongval () { return (long) (sizeof (long)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (long))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (long))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (long))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_long=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (long), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_long=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for int" >&5
+echo $ECHO_N "checking for int... $ECHO_C" >&6
+if test "${ac_cv_type_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((int *) 0)
+ return 0;
+if (sizeof (int))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_int=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_int=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5
+echo "${ECHO_T}$ac_cv_type_int" >&6
+
+echo "$as_me:$LINENO: checking size of int" >&5
+echo $ECHO_N "checking size of int... $ECHO_C" >&6
+if test "${ac_cv_sizeof_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$ac_cv_type_int" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (int))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_int=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5
+echo "$as_me: error: internal error: not reached in cross-compile" >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (int)); }
+unsigned long ulongval () { return (long) (sizeof (int)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (int))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (int))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (int))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_int=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (int), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_int=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_int" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for short" >&5
+echo $ECHO_N "checking for short... $ECHO_C" >&6
+if test "${ac_cv_type_short+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((short *) 0)
+ return 0;
+if (sizeof (short))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_short=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_short=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_short" >&5
+echo "${ECHO_T}$ac_cv_type_short" >&6
+
+echo "$as_me:$LINENO: checking size of short" >&5
+echo $ECHO_N "checking size of short... $ECHO_C" >&6
+if test "${ac_cv_sizeof_short+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$ac_cv_type_short" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (short))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (short))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (short))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (short))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (short))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_short=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (short), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (short), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5
+echo "$as_me: error: internal error: not reached in cross-compile" >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (short)); }
+unsigned long ulongval () { return (long) (sizeof (short)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (short))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (short))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (short))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_short=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (short), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (short), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_short=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_short" >&5
+echo "${ECHO_T}$ac_cv_sizeof_short" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for char" >&5
+echo $ECHO_N "checking for char... $ECHO_C" >&6
+if test "${ac_cv_type_char+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((char *) 0)
+ return 0;
+if (sizeof (char))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_char=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_char=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_char" >&5
+echo "${ECHO_T}$ac_cv_type_char" >&6
+
+echo "$as_me:$LINENO: checking size of char" >&5
+echo $ECHO_N "checking size of char... $ECHO_C" >&6
+if test "${ac_cv_sizeof_char+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$ac_cv_type_char" = yes; then
+ # The cast to unsigned long works around a bug in the HP C Compiler
+ # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+ # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+ # This bug is HP SR number 8606223364.
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (char))) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (char))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr $ac_mid + 1`
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (char))) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (char))) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_lo=$ac_mid; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_hi=`expr '(' $ac_mid ')' - 1`
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ ac_mid=`expr 2 '*' $ac_mid`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo= ac_hi=
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(((long) (sizeof (char))) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_hi=$ac_mid
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_lo=`expr '(' $ac_mid ')' + 1`
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in
+?*) ac_cv_sizeof_char=$ac_lo;;
+'') { { echo "$as_me:$LINENO: error: cannot compute sizeof (char), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (char), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; } ;;
+esac
+else
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: internal error: not reached in cross-compile" >&5
+echo "$as_me: error: internal error: not reached in cross-compile" >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+long longval () { return (long) (sizeof (char)); }
+unsigned long ulongval () { return (long) (sizeof (char)); }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ exit (1);
+ if (((long) (sizeof (char))) < 0)
+ {
+ long i = longval ();
+ if (i != ((long) (sizeof (char))))
+ exit (1);
+ fprintf (f, "%ld\n", i);
+ }
+ else
+ {
+ unsigned long i = ulongval ();
+ if (i != ((long) (sizeof (char))))
+ exit (1);
+ fprintf (f, "%lu\n", i);
+ }
+ exit (ferror (f) || fclose (f) != 0);
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_char=`cat conftest.val`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: cannot compute sizeof (char), 77
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute sizeof (char), 77
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+rm -f conftest.val
+else
+ ac_cv_sizeof_char=0
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_char" >&5
+echo "${ECHO_T}$ac_cv_sizeof_char" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_CHAR $ac_cv_sizeof_char
+_ACEOF
+
+
+
+ ac_config_files="$ac_config_files Makefile"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+ if test -w $cache_file; then
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@LOC_NTOA@,$LOC_NTOA,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
+ esac
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ # Do quote $f, to prevent DOS paths from being IFS'd.
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+ # Remove the trailing spaces.
+ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h. The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status. Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless. Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo ' :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+ # Write a limited-size here document to $tmp/defines.sed.
+ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#define' lines.
+ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/defines.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo ' fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+ # Write a limited-size here document to $tmp/undefs.sed.
+ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#undef'
+ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+ rm -f conftest.undefs
+ mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ echo "/* Generated by configure. */" >$tmp/config.h
+ else
+ echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
+ fi
+ cat $tmp/in >>$tmp/config.h
+ rm -f $tmp/in
+ if test x"$ac_file" != x-; then
+ if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ rm -f $ac_file
+ mv $tmp/config.h $ac_file
+ fi
+ else
+ cat $tmp/config.h
+ rm -f $tmp/config.h
+ fi
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+
+
diff --git a/contrib/query-loc-0.4.0/configure.in b/contrib/query-loc-0.4.0/configure.in
new file mode 100644
index 0000000..2530fb0
--- /dev/null
+++ b/contrib/query-loc-0.4.0/configure.in
@@ -0,0 +1,65 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_RELEASE("$Id: configure.in,v 1.1 2008/02/15 01:47:15 marka Exp $")
+AC_INIT(query-loc.c)
+
+dnl Checks for programs.
+AC_PROG_CC
+if test "$GCC" = "yes"; then
+ CFLAGS="${CFLAGS} -Wall"
+fi
+AC_PROG_INSTALL
+
+dnl Checks for libraries.
+AC_CHECK_LIB(resolv, res_query)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CONFIG_HEADER(config.h)
+AC_CHECK_HEADER(resolv.h, , AC_MSG_ERROR("No headers for name service applications"))
+AC_CHECK_HEADER(arpa/nameser.h, , AC_MSG_ERROR("No headers for name service applications"))
+AC_CHECK_HEADER(sys/time.h, , AC_MSG_ERROR("Mandatory header missing on your system"))
+AC_CHECK_HEADER(unistd.h, , AC_MSG_ERROR("Mandatory header missing on your system"))
+
+
+dnl This one is only useful for Solaris?
+AC_MSG_CHECKING(if libnsl is mandatory)
+AC_TRY_LINK([#include <sys/types.h>
+ #include <netinet/in.h>
+ #include <arpa/nameser.h>
+ #include <resolv.h>
+ union
+ {
+ HEADER hdr;
+ u_char buf[4096]; /* With RFC 2671, otherwise 512 is enough */
+ }
+ response;
+ char *domain;
+ int requested_type; ],
+ [res_query(domain,
+ C_IN,
+ requested_type,
+ (u_char *) & response,
+ sizeof (response)) ], dnl
+ [AC_MSG_RESULT(no)], dnl
+ [AC_MSG_RESULT(yes); LIBS="${LIBS} -lnsl"])
+
+dnl Check for the loc_ntoa macro/function
+AC_MSG_CHECKING(loc_ntoa)
+AC_TRY_LINK([#include <resolv.h>], dnl
+ [u_char *cp; char *result; loc_ntoa(cp, result)], dnl
+ [AC_MSG_RESULT(yes); AC_DEFINE(HAVE_LOC_NTOA)], dnl
+ [AC_MSG_RESULT([no, using the alternative]); LOC_NTOA=loc_ntoa.o])
+AC_SUBST(LOC_NTOA)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(char)
+
+dnl Misc.
+AC_OUTPUT(Makefile)
+
+
+
diff --git a/contrib/query-loc-0.4.0/install-sh b/contrib/query-loc-0.4.0/install-sh
new file mode 100755
index 0000000..1a83534
--- /dev/null
+++ b/contrib/query-loc-0.4.0/install-sh
@@ -0,0 +1,323 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2005-02-02.21
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+chmodcmd="$chmodprog 0755"
+chowncmd=
+chgrpcmd=
+stripcmd=
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=
+dst=
+dir_arg=
+dstarg=
+no_target_directory=
+
+usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+-c (ignored)
+-d create directories instead of installing files.
+-g GROUP $chgrpprog installed files to GROUP.
+-m MODE $chmodprog installed files to MODE.
+-o USER $chownprog installed files to USER.
+-s $stripprog installed files.
+-t DIRECTORY install into DIRECTORY.
+-T report an error if DSTFILE is a directory.
+--help display this help and exit.
+--version display version info and exit.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
+"
+
+while test -n "$1"; do
+ case $1 in
+ -c) shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd=$stripprog
+ shift
+ continue;;
+
+ -t) dstarg=$2
+ shift
+ shift
+ continue;;
+
+ -T) no_target_directory=true
+ shift
+ continue;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ *) # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ test -n "$dir_arg$dstarg" && break
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dstarg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dstarg"
+ shift # fnord
+ fi
+ shift # arg
+ dstarg=$arg
+ done
+ break;;
+ esac
+done
+
+if test -z "$1"; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src ;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ src=
+
+ if test -d "$dst"; then
+ mkdircmd=:
+ chmodcmd=
+ else
+ mkdircmd=$mkdirprog
+ fi
+ else
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dstarg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dstarg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst ;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dstarg: Is a directory" >&2
+ exit 1
+ fi
+ dst=$dst/`basename "$src"`
+ fi
+ fi
+
+ # This sed command emulates the dirname command.
+ dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
+
+ # Make sure that the destination directory exists.
+
+ # Skip lots of stat calls in the usual case.
+ if test ! -d "$dstdir"; then
+ defaultIFS='
+ '
+ IFS="${IFS-$defaultIFS}"
+
+ oIFS=$IFS
+ # Some sh's can't handle IFS=/ for some reason.
+ IFS='%'
+ set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
+ shift
+ IFS=$oIFS
+
+ pathcomp=
+
+ while test $# -ne 0 ; do
+ pathcomp=$pathcomp$1
+ shift
+ if test ! -d "$pathcomp"; then
+ $mkdirprog "$pathcomp"
+ # mkdir can fail with a `File exist' error in case several
+ # install-sh are creating the directory concurrently. This
+ # is OK.
+ test -d "$pathcomp" || exit
+ fi
+ pathcomp=$pathcomp/
+ done
+ fi
+
+ if test -n "$dir_arg"; then
+ $doit $mkdircmd "$dst" \
+ && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
+ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
+ && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
+ && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
+
+ else
+ dstfile=`basename "$dst"`
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+ trap '(exit $?); exit' 1 2 13 15
+
+ # Copy the file name to the temp name.
+ $doit $cpprog "$src" "$dsttmp" &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
+ && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
+ && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
+ && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
+
+ # Now rename the file to the real destination.
+ { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
+ || {
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ if test -f "$dstdir/$dstfile"; then
+ $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
+ || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
+ || {
+ echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
+ (exit 1); exit 1
+ }
+ else
+ :
+ fi
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
+ }
+ }
+ fi || { (exit 1); exit 1; }
+done
+
+# The final little trick to "correctly" pass the exit status to the exit trap.
+{
+ (exit 0); exit 0
+}
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/contrib/query-loc-0.4.0/loc.c b/contrib/query-loc-0.4.0/loc.c
new file mode 100644
index 0000000..57e3737
--- /dev/null
+++ b/contrib/query-loc-0.4.0/loc.c
@@ -0,0 +1,590 @@
+#include "loc.h"
+
+/* $Id: loc.c,v 1.1 2008/02/15 01:47:15 marka Exp $ */
+
+/* Global variables */
+
+short rr_errno;
+
+/*
+ Prints the actual usage
+ */
+void
+usage ()
+{
+ (void) fprintf (stderr,
+ "Usage: %s: [-v] [-d nnn] hostname\n", progname);
+ exit (2);
+}
+
+/*
+ Panics
+ */
+void
+panic (message)
+ char *message;
+{
+ (void) fprintf (stderr,
+ "%s: %s\n", progname, message);
+ exit (2);
+}
+
+/*
+ ** IN_ADDR_ARPA -- Convert dotted quad string to reverse in-addr.arpa
+ ** ------------------------------------------------------------------
+ **
+ ** Returns:
+ ** Pointer to appropriate reverse in-addr.arpa name
+ ** with trailing dot to force absolute domain name.
+ ** NULL in case of invalid dotted quad input string.
+ */
+
+#ifndef ARPA_ROOT
+#define ARPA_ROOT "in-addr.arpa"
+#endif
+
+char *
+in_addr_arpa (dottedquad)
+ char *dottedquad; /* input string with dotted quad */
+{
+ static char addrbuf[4 * 4 + sizeof (ARPA_ROOT) + 2];
+ unsigned int a[4];
+ register int n;
+
+ n = sscanf (dottedquad, "%u.%u.%u.%u", &a[0], &a[1], &a[2], &a[3]);
+ switch (n)
+ {
+ case 4:
+ (void) sprintf (addrbuf, "%u.%u.%u.%u.%s.",
+ a[3] & 0xff, a[2] & 0xff, a[1] & 0xff, a[0] & 0xff, ARPA_ROOT);
+ break;
+
+ case 3:
+ (void) sprintf (addrbuf, "%u.%u.%u.%s.",
+ a[2] & 0xff, a[1] & 0xff, a[0] & 0xff, ARPA_ROOT);
+ break;
+
+ case 2:
+ (void) sprintf (addrbuf, "%u.%u.%s.",
+ a[1] & 0xff, a[0] & 0xff, ARPA_ROOT);
+ break;
+
+ case 1:
+ (void) sprintf (addrbuf, "%u.%s.",
+ a[0] & 0xff, ARPA_ROOT);
+ break;
+
+ default:
+ return (NULL);
+ }
+
+ while (--n >= 0)
+ if (a[n] > 255)
+ return (NULL);
+
+ return (addrbuf);
+}
+
+/*
+ Returns a human-readable version of the LOC information or
+ NULL if it failed. Argument is a name (of a network or a machine)
+ and a boolean telling is it is a network name or a machine name.
+ */
+char *
+getlocbyname (name, is_network)
+ const char *name;
+ short is_network;
+{
+ char *result;
+ struct list_in_addr *list, *p;
+ result = findRR (name, T_LOC);
+ if (result != NULL)
+ {
+ if (debug >= 2)
+ printf ("LOC record found for the name %s\n", name);
+ return result;
+ }
+ else
+ {
+ if (!is_network)
+ {
+ list = findA (name);
+ if (debug >= 2)
+ printf ("No LOC record found for the name %s, trying addresses\n", name);
+ if (list != NULL)
+ {
+ for (p = list; p != NULL; p = p->next)
+ {
+ if (debug >= 2)
+ printf ("Trying address %s\n", inet_ntoa (p->addr));
+ result = getlocbyaddr (p->addr, NULL);
+ if (result != NULL)
+ return result;
+ }
+ return NULL;
+ }
+ else
+ {
+ if (debug >= 2)
+ printf (" No A record found for %s\n", name);
+ return NULL;
+ }
+ }
+ else
+ {
+ if (debug >= 2)
+ printf ("No LOC record found for the network name %s\n", name);
+ return NULL;
+ }
+ }
+}
+
+/*
+ Returns a human-readable version of the LOC information or
+ NULL if it failed. Argument is an IP address.
+ */
+char *
+getlocbyaddr (addr, mask)
+ const struct in_addr addr;
+ const struct in_addr *mask;
+{
+ struct in_addr netaddr;
+ u_int32_t a;
+ struct in_addr themask;
+ char *text_addr, *text_mask;
+
+ if (mask == NULL)
+ {
+ themask.s_addr = (u_int32_t) 0;
+ }
+ else
+ {
+ themask = *mask;
+ }
+
+ text_addr = (char *) malloc (256);
+ text_mask = (char *) malloc (256);
+ strcpy (text_addr, inet_ntoa (addr));
+ strcpy (text_mask, inet_ntoa (themask));
+
+ if (debug >= 2)
+ printf ("Testing address %s/%s\n", text_addr, text_mask);
+ if (mask == NULL)
+ {
+ a = ntohl (addr.s_addr);
+ if (IN_CLASSA (a))
+ {
+ netaddr.s_addr = htonl (a & IN_CLASSA_NET);
+ themask.s_addr = htonl(IN_CLASSA_NET);
+ }
+ else if (IN_CLASSB (a))
+ {
+ netaddr.s_addr = htonl (a & IN_CLASSB_NET);
+ themask.s_addr = htonl(IN_CLASSB_NET);
+ }
+ else if (IN_CLASSC (a))
+ {
+ netaddr.s_addr = htonl (a & IN_CLASSC_NET);
+ themask.s_addr = htonl(IN_CLASSC_NET);
+ }
+ else
+ {
+ /* Error */
+ return NULL;
+ }
+ return getlocbynet (in_addr_arpa (inet_ntoa (netaddr)), addr, &themask);
+ }
+ else
+ {
+ netaddr.s_addr = addr.s_addr & themask.s_addr;
+ return getlocbynet (in_addr_arpa (inet_ntoa (netaddr)), addr, mask);
+ }
+}
+
+/*
+ Returns a human-readable LOC.
+ Argument is a network name in the 0.z.y.x.in-addr.arpa format
+ and the original address
+ */
+char *
+getlocbynet (name, addr, mask)
+ char *name;
+ struct in_addr addr;
+ struct in_addr *mask;
+{
+ char *network;
+ char *result;
+ struct list_in_addr *list;
+ struct in_addr newmask;
+ u_int32_t a;
+ char newname[4 * 4 + sizeof (ARPA_ROOT) + 2];
+
+ if (debug >= 2)
+ printf ("Testing network %s with mask %s\n", name, inet_ntoa(*mask));
+
+ /* Check if this network has an A RR */
+ list = findA (name);
+ if (list != NULL)
+ {
+ /* Yes, it does. This A record will be used as the
+ * new mask for recursion if it is longer than
+ * the actual mask. */
+ if (mask != NULL && mask->s_addr < list->addr.s_addr)
+ {
+ /* compute the new arguments for recursion
+ * - compute the new network by applying the new mask
+ * to the address and get the in_addr_arpa representation
+ * of it.
+ * - the address remains unchanged
+ * - the new mask is the one given in the A record
+ */
+ a = ntohl(addr.s_addr); /* start from host address */
+ a &= ntohl(list->addr.s_addr); /* apply new mask */
+ newname[sizeof newname - 1] = 0;
+ strncpy(
+ newname,
+ in_addr_arpa(inet_ntoa(inet_makeaddr(a, 0))),
+ sizeof newname);
+ newmask = inet_makeaddr(ntohl(list->addr.s_addr), 0);
+ result = getlocbynet (newname, addr, &newmask);
+ if (result != NULL)
+ {
+ return result;
+ }
+ }
+ /* couldn't find a LOC. Fall through and try with name */
+ }
+
+ /* Check if this network has a name */
+ network = findRR (name, T_PTR);
+ if (network == NULL)
+ {
+ if (debug >= 2)
+ printf ("No name for network %s\n", name);
+ return NULL;
+ }
+ else
+ {
+ return getlocbyname (network, TRUE);
+ }
+}
+
+/*
+ The code for these two functions is stolen from the examples in Liu and Albitz
+ book "DNS and BIND" (O'Reilly).
+ */
+
+/****************************************************************
+ * skipName -- This routine skips over a domain name. If the *
+ * domain name expansion fails, it crashes. *
+ * dn_skipname() is probably not on your manual *
+ * page; it is similar to dn_expand() except that it just *
+ * skips over the name. dn_skipname() is in res_comp.c if *
+ * you need to find it. *
+ ****************************************************************/
+int
+skipName (cp, endOfMsg)
+ u_char *cp;
+ u_char *endOfMsg;
+{
+ int n;
+
+ if ((n = dn_skipname (cp, endOfMsg)) < 0)
+ {
+ panic ("dn_skipname failed\n");
+ }
+ return (n);
+}
+
+/****************************************************************
+ * skipToData -- This routine advances the cp pointer to the *
+ * start of the resource record data portion. On the way, *
+ * it fills in the type, class, ttl, and data length *
+ ****************************************************************/
+int
+skipToData (cp, type, class, ttl, dlen, endOfMsg)
+ u_char *cp;
+ u_short *type;
+ u_short *class;
+ u_int32_t *ttl;
+ u_short *dlen;
+ u_char *endOfMsg;
+{
+ u_char *tmp_cp = cp; /* temporary version of cp */
+
+ /* Skip the domain name; it matches the name we looked up */
+ tmp_cp += skipName (tmp_cp, endOfMsg);
+
+ /*
+ * Grab the type, class, and ttl. GETSHORT and GETLONG
+ * are macros defined in arpa/nameser.h.
+ */
+ GETSHORT (*type, tmp_cp);
+ GETSHORT (*class, tmp_cp);
+ GETLONG (*ttl, tmp_cp);
+ GETSHORT (*dlen, tmp_cp);
+
+ return (tmp_cp - cp);
+}
+
+
+/*
+ Returns a human-readable version of a DNS RR (resource record)
+ associated with the name 'domain'.
+ If it does not find, ir returns NULL and sets rr_errno to explain why.
+
+ The code for this function is stolen from the examples in Liu and Albitz
+ book "DNS and BIND" (O'Reilly).
+ */
+char *
+findRR (domain, requested_type)
+ char *domain;
+ int requested_type;
+{
+ char *result, *message;
+
+ union
+ {
+ HEADER hdr; /* defined in resolv.h */
+ u_char buf[PACKETSZ]; /* defined in arpa/nameser.h */
+ }
+ response; /* response buffers */
+short found = 0;
+int responseLen; /* buffer length */
+
+ u_char *cp; /* character pointer to parse DNS packet */
+ u_char *endOfMsg; /* need to know the end of the message */
+ u_short class; /* classes defined in arpa/nameser.h */
+ u_short type; /* types defined in arpa/nameser.h */
+ u_int32_t ttl; /* resource record time to live */
+ u_short dlen; /* size of resource record data */
+
+ int i, count, dup; /* misc variables */
+
+ char *ptrList[1];
+ int ptrNum = 0;
+ struct in_addr addr;
+
+ result = (char *) malloc (256);
+ message = (char *) malloc (256);
+ /*
+ * Look up the records for the given domain name.
+ * We expect the domain to be a fully qualified name, so
+ * we use res_query(). If we wanted the resolver search
+ * algorithm, we would have used res_search() instead.
+ */
+ if ((responseLen =
+ res_query (domain, /* the domain we care about */
+ C_IN, /* Internet class records */
+ requested_type, /* Look up name server records */
+ (u_char *) & response, /*response buffer */
+ sizeof (response))) /*buffer size */
+ < 0)
+ { /*If negative */
+ rr_errno = h_errno;
+ return NULL;
+ }
+
+ /*
+ * Keep track of the end of the message so we don't
+ * pass it while parsing the response. responseLen is
+ * the value returned by res_query.
+ */
+ endOfMsg = response.buf + responseLen;
+
+ /*
+ * Set a pointer to the start of the question section,
+ * which begins immediately AFTER the header.
+ */
+ cp = response.buf + sizeof (HEADER);
+
+ /*
+ * Skip over the whole question section. The question
+ * section is comprised of a name, a type, and a class.
+ * QFIXEDSZ (defined in arpa/nameser.h) is the size of
+ * the type and class portions, which is fixed. Therefore,
+ * we can skip the question section by skipping the
+ * name (at the beginning) and then advancing QFIXEDSZ.
+ * After this calculation, cp points to the start of the
+ * answer section, which is a list of NS records.
+ */
+ cp += skipName (cp, endOfMsg) + QFIXEDSZ;
+
+ count = ntohs (response.hdr.ancount) +
+ ntohs (response.hdr.nscount);
+ while ((--count >= 0) /* still more records */
+ && (cp < endOfMsg))
+ { /* still inside the packet */
+
+
+ /* Skip to the data portion of the resource record */
+ cp += skipToData (cp, &type, &class, &ttl, &dlen, endOfMsg);
+
+ if (type == requested_type)
+ {
+ switch (requested_type)
+ {
+ case (T_LOC):
+ loc_ntoa (cp, result);
+ return result;
+ break;
+ case (T_PTR):
+ ptrList[ptrNum] = (char *) malloc (MAXDNAME);
+ if (ptrList[ptrNum] == NULL)
+ {
+ panic ("Malloc failed");
+ }
+
+ if (dn_expand (response.buf, /* Start of the packet */
+ endOfMsg, /* End of the packet */
+ cp, /* Position in the packet */
+ (char *) ptrList[ptrNum], /* Result */
+ MAXDNAME) /* size of ptrList buffer */
+ < 0)
+ { /* Negative: error */
+ panic ("dn_expand failed");
+ }
+
+ /*
+ * Check the name we've just unpacked and add it to
+ * the list if it is not a duplicate.
+ * If it is a duplicate, just ignore it.
+ */
+ for (i = 0, dup = 0; (i < ptrNum) && !dup; i++)
+ dup = !strcasecmp (ptrList[i], ptrList[ptrNum]);
+ if (dup)
+ free (ptrList[ptrNum]);
+ else
+ ptrNum++;
+ strcpy (result, ptrList[0]);
+ return result;
+ break;
+ case (T_A):
+ bcopy ((char *) cp, (char *) &addr, INADDRSZ);
+ strcat (result, " ");
+ strcat (result, inet_ntoa (addr));
+ found = 1;
+ break;
+ default:
+ sprintf (message, "Unexpected type %u", requested_type);
+ panic (message);
+ }
+ }
+
+ /* Advance the pointer over the resource record data */
+ cp += dlen;
+
+ } /* end of while */
+ if (found)
+ return result;
+else
+return NULL;
+}
+
+struct list_in_addr *
+findA (domain)
+ char *domain;
+{
+
+ struct list_in_addr *result, *end;
+
+ union
+ {
+ HEADER hdr; /* defined in resolv.h */
+ u_char buf[PACKETSZ]; /* defined in arpa/nameser.h */
+ }
+ response; /* response buffers */
+ int responseLen; /* buffer length */
+
+ u_char *cp; /* character pointer to parse DNS packet */
+ u_char *endOfMsg; /* need to know the end of the message */
+ u_short class; /* classes defined in arpa/nameser.h */
+ u_short type; /* types defined in arpa/nameser.h */
+ u_int32_t ttl; /* resource record time to live */
+ u_short dlen; /* size of resource record data */
+
+ int count; /* misc variables */
+
+ struct in_addr addr;
+
+ end = NULL;
+ result = NULL;
+
+ /*
+ * Look up the records for the given domain name.
+ * We expect the domain to be a fully qualified name, so
+ * we use res_query(). If we wanted the resolver search
+ * algorithm, we would have used res_search() instead.
+ */
+ if ((responseLen =
+ res_query (domain, /* the domain we care about */
+ C_IN, /* Internet class records */
+ T_A,
+ (u_char *) & response, /*response buffer */
+ sizeof (response))) /*buffer size */
+ < 0)
+ { /*If negative */
+ rr_errno = h_errno;
+ return NULL;
+ }
+
+ /*
+ * Keep track of the end of the message so we don't
+ * pass it while parsing the response. responseLen is
+ * the value returned by res_query.
+ */
+ endOfMsg = response.buf + responseLen;
+
+ /*
+ * Set a pointer to the start of the question section,
+ * which begins immediately AFTER the header.
+ */
+ cp = response.buf + sizeof (HEADER);
+
+ /*
+ * Skip over the whole question section. The question
+ * section is comprised of a name, a type, and a class.
+ * QFIXEDSZ (defined in arpa/nameser.h) is the size of
+ * the type and class portions, which is fixed. Therefore,
+ * we can skip the question section by skipping the
+ * name (at the beginning) and then advancing QFIXEDSZ.
+ * After this calculation, cp points to the start of the
+ * answer section, which is a list of NS records.
+ */
+ cp += skipName (cp, endOfMsg) + QFIXEDSZ;
+
+ count = ntohs (response.hdr.ancount) +
+ ntohs (response.hdr.nscount);
+ while ((--count >= 0) /* still more records */
+ && (cp < endOfMsg))
+ { /* still inside the packet */
+
+
+ /* Skip to the data portion of the resource record */
+ cp += skipToData (cp, &type, &class, &ttl, &dlen, endOfMsg);
+
+ if (type == T_A)
+ {
+ bcopy ((char *) cp, (char *) &addr, INADDRSZ);
+ if (end == NULL)
+ {
+ result = (void *) malloc (sizeof (struct list_in_addr));
+ result->addr = addr;
+ result->next = NULL;
+ end = result;
+ }
+ else
+ {
+ end->next = (void *) malloc (sizeof (struct list_in_addr));
+ end = end->next;
+ end->addr = addr;
+ end->next = NULL;
+ }
+ }
+
+ /* Advance the pointer over the resource record data */
+ cp += dlen;
+
+ } /* end of while */
+ return result;
+}
diff --git a/contrib/query-loc-0.4.0/loc.h b/contrib/query-loc-0.4.0/loc.h
new file mode 100644
index 0000000..c9b74db
--- /dev/null
+++ b/contrib/query-loc-0.4.0/loc.h
@@ -0,0 +1,78 @@
+/* $Id: loc.h,v 1.1 2008/02/15 01:47:15 marka Exp $ */
+
+#define VERSION "0.4.0"
+
+#include "config.h"
+
+/* Probably too many inclusions but this is to keep 'gcc -Wall' happy... */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#if SIZEOF_LONG == 4
+#define u_int32_t unsigned long
+#ifndef int32_t
+#define int32_t long
+#endif
+#else
+#define u_int32_t unsigned int
+#ifndef int32_t
+#define int32_t int
+#endif
+#endif
+
+#if SIZEOF_CHAR == 1
+#define u_int8_t unsigned char
+#ifndef int8_t
+#define int8_t char
+#endif
+#else
+#if SIZEOF_SHORT == 1
+#define u_int8_t unsigned short
+#ifndef int8_t
+#define int8_t short
+#endif
+#else
+#error "No suitable native type for storing bytes"
+#endif
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE (in_addr_t)-1
+#endif
+
+struct list_in_addr
+ {
+ struct in_addr addr;
+ void *next;
+ };
+
+void usage ();
+void panic ();
+
+char *getlocbyname ();
+char *getlocbyaddr ();
+char *getlocbynet ();
+char *findRR ();
+struct list_in_addr *findA ();
+
+extern char *progname;
+extern short debug;
diff --git a/contrib/query-loc-0.4.0/loc_ntoa.c b/contrib/query-loc-0.4.0/loc_ntoa.c
new file mode 100644
index 0000000..21eada3
--- /dev/null
+++ b/contrib/query-loc-0.4.0/loc_ntoa.c
@@ -0,0 +1,248 @@
+/* Stolen from BIND */
+
+/*
+ * Copyright (c) 1985
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "loc.h"
+
+const char *precsize_ntoa();
+
+/* takes an on-the-wire LOC RR and formats it in a human readable format. */
+const char *
+loc_ntoa(binary, ascii)
+ const u_char *binary;
+ char *ascii;
+{
+ static char *error = "?";
+ static char tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+ const u_char *cp = binary;
+
+ int latdeg, latmin, latsec, latsecfrac;
+ int longdeg, longmin, longsec, longsecfrac;
+ char northsouth, eastwest;
+ int altmeters, altfrac, altsign;
+
+ const u_int32_t referencealt = 100000 * 100;
+
+ int32_t latval, longval, altval;
+ u_int32_t templ;
+ u_int8_t sizeval, hpval, vpval, versionval;
+
+ char *sizestr, *hpstr, *vpstr;
+
+ versionval = *cp++;
+
+ if (ascii == NULL)
+ ascii = tmpbuf;
+
+ if (versionval) {
+ (void) sprintf(ascii, "; error: unknown LOC RR version");
+ return (ascii);
+ }
+
+ sizeval = *cp++;
+
+ hpval = *cp++;
+ vpval = *cp++;
+
+ GETLONG(templ, cp);
+ latval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ longval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ if (templ < referencealt) { /* below WGS 84 spheroid */
+ altval = referencealt - templ;
+ altsign = -1;
+ } else {
+ altval = templ - referencealt;
+ altsign = 1;
+ }
+
+ if (latval < 0) {
+ northsouth = 'S';
+ latval = -latval;
+ } else
+ northsouth = 'N';
+
+ latsecfrac = latval % 1000;
+ latval = latval / 1000;
+ latsec = latval % 60;
+ latval = latval / 60;
+ latmin = latval % 60;
+ latval = latval / 60;
+ latdeg = latval;
+
+ if (longval < 0) {
+ eastwest = 'W';
+ longval = -longval;
+ } else
+ eastwest = 'E';
+
+ longsecfrac = longval % 1000;
+ longval = longval / 1000;
+ longsec = longval % 60;
+ longval = longval / 60;
+ longmin = longval % 60;
+ longval = longval / 60;
+ longdeg = longval;
+
+ altfrac = altval % 100;
+ altmeters = (altval / 100) * altsign;
+
+ if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
+ sizestr = error;
+ if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
+ hpstr = error;
+ if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
+ vpstr = error;
+
+ sprintf(ascii,
+ "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
+ latdeg, latmin, latsec, latsecfrac, northsouth,
+ longdeg, longmin, longsec, longsecfrac, eastwest,
+ altmeters, altfrac, sizestr, hpstr, vpstr);
+
+ if (sizestr != error)
+ free(sizestr);
+ if (hpstr != error)
+ free(hpstr);
+ if (vpstr != error)
+ free(vpstr);
+
+ return (ascii);
+}
+
+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+ 1000000,10000000,100000000,1000000000};
+
+/* takes an XeY precision/size value, returns a string representation. */
+const char *
+precsize_ntoa(prec)
+ u_int8_t prec;
+{
+ static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */
+ unsigned long val;
+ int mantissa, exponent;
+
+ mantissa = (int)((prec >> 4) & 0x0f) % 10;
+ exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+ val = mantissa * poweroften[exponent];
+
+ (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
+ return (retbuf);
+}
+
diff --git a/contrib/query-loc-0.4.0/query-loc.1 b/contrib/query-loc-0.4.0/query-loc.1
new file mode 100644
index 0000000..df55b4d
--- /dev/null
+++ b/contrib/query-loc-0.4.0/query-loc.1
@@ -0,0 +1,55 @@
+.\" Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH QUERY-LOC 1 "January 11, 2005"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+query-loc \- to retrieve and display the location information in the DNS
+.SH SYNOPSIS
+.B query-loc
+.RI [-v] [-d nnn] " host"
+.SH DESCRIPTION
+This manual page documents briefly the
+.B query-loc
+command.
+.PP
+.\" TeX users may be more comfortable with the \fB<whatever>\fP and
+.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" respectively.
+\fBquery-loc\fP is a program to retrieve and display the location
+information in the DNS.
+
+It uses the algorithms described in
+RFC 1876 (and RFC 1101 to get the network names).
+You can find examples of networks wchich implement this scheme
+in the ADDRESSES file.
+
+.SH OPTIONS
+.TP
+.B \-v
+Verbose mode.
+.TP
+.B \-d nnn
+Debug mode. Displays the RFC's algorithm
+
+.SH BUGS
+
+Very few hosts have location information.
+
+.SH AUTHOR
+This manual page was written by Stephane Bortzmeyer
+<bortzmeyer@debian.org>.
+
+.\" $Id: query-loc.1,v 1.1 2008/02/15 01:47:15 marka Exp $
diff --git a/contrib/query-loc-0.4.0/query-loc.c b/contrib/query-loc-0.4.0/query-loc.c
new file mode 100644
index 0000000..2492d5b
--- /dev/null
+++ b/contrib/query-loc-0.4.0/query-loc.c
@@ -0,0 +1,98 @@
+#include "loc.h"
+
+/* $Id: query-loc.c,v 1.1 2008/02/15 01:47:15 marka Exp $ */
+
+/* Global variables */
+char *progname;
+short debug;
+
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern char *optarg;
+ extern int optind;
+
+ short verbose = FALSE;
+ char *host;
+
+ char ch;
+
+ char *loc = NULL;
+ struct in_addr addr;
+ struct hostent *hp;
+
+ progname = argv[0];
+ while ((ch = getopt (argc, argv, "vd:")) != EOF)
+ {
+ switch (ch)
+ {
+ case 'v':
+ verbose = TRUE;
+ break;
+ case 'd':
+ debug = atoi (optarg);
+ if (debug <= 0)
+ {
+ (void) fprintf (stderr,
+ "%s: illegal debug value.\n", progname);
+ exit (2);
+ }
+ break;
+ default:
+ usage ();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc != 1)
+ {
+ usage ();
+ }
+ if (verbose || debug)
+ {
+ printf ("\nThis is %s, version %s.\n\n", progname, VERSION);
+ }
+ host = argv[0];
+ (void) res_init ();
+
+ if ((addr.s_addr = inet_addr (host)) == INADDR_NONE)
+ {
+ if (debug >= 1)
+ printf ("%s is a name\n", host);
+ loc = getlocbyname (host, FALSE);
+ }
+ else
+ {
+ if (debug >= 1)
+ printf ("%s is an IP address ", host);
+ hp = (struct hostent *) gethostbyaddr
+ ((char *) &addr, sizeof (addr), AF_INET);
+ if (hp)
+ {
+ if (debug >= 1)
+ printf ("and %s is its official name\n",
+ hp->h_name);
+ loc = getlocbyname (hp->h_name, FALSE);
+ }
+ else
+ {
+ if (debug >= 1)
+ printf ("which has no name\n");
+ loc = getlocbyaddr (addr, NULL);
+ }
+ }
+ if (loc == NULL)
+ {
+ printf ("No LOCation found for %s\n", host);
+ exit (1);
+ }
+ else
+ {
+ if (verbose || debug)
+ printf ("LOCation for %s is ", host);
+ printf ("%s\n", loc);
+ exit (0);
+ }
+}
diff --git a/contrib/query-loc-0.4.0/reconf b/contrib/query-loc-0.4.0/reconf
new file mode 100755
index 0000000..c1cf732
--- /dev/null
+++ b/contrib/query-loc-0.4.0/reconf
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# $Id: reconf,v 1.1 2008/02/15 01:47:15 marka Exp $
+
+autoreconf
+# We do not use automake but we need its install-sh file. We do not
+# care about the exit code.
+automake --add-missing || true
diff --git a/contrib/queryperf/Makefile.in b/contrib/queryperf/Makefile.in
new file mode 100644
index 0000000..6e16cad
--- /dev/null
+++ b/contrib/queryperf/Makefile.in
@@ -0,0 +1,28 @@
+# Copyright (C) 2000, 2001 Nominum, Inc. All Rights Reserved.
+
+CC = @CC@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+DEFS = @DEFS@
+
+queryperf: queryperf.o $(LIBOBJS)
+ $(CC) $(CFLAGS) $(DEFS) $(LDFLAGS) queryperf.o $(LIBOBJS) $(LIBS) -lm -o queryperf
+
+queryperf.o: queryperf.c
+ $(CC) $(CFLAGS) $(DEFS) -c queryperf.c
+
+# under missing subdir
+getaddrinfo.o: ./missing/getaddrinfo.c
+ $(CC) $(CFLAGS) -c ./missing/$*.c
+
+getnameinfo.o: ./missing/getnameinfo.c
+ $(CC) $(CFLAGS) -c ./missing/$*.c
+
+clean:
+ rm -f *.o queryperf
+
+distclean: clean
+ rm -f config.log
+ rm -f config.cache
+ rm -f config.status
+ rm -f Makefile
diff --git a/contrib/queryperf/README b/contrib/queryperf/README
new file mode 100644
index 0000000..a1e0c62
--- /dev/null
+++ b/contrib/queryperf/README
@@ -0,0 +1,82 @@
+
+$Id: README,v 1.1.1.1 2001/07/12 02:02:09 gson Exp $
+
+This is queryperf, a DNS server query performance testing tool.
+
+It is primarily intended for measuring the performance of
+authoritative DNS servers, but it has also been used for measuring
+caching server performance. This document describes the use of
+queryperf for authoritative server performance testing.
+
+
+Building
+
+To build queryperf, just do
+
+ sh configure
+ make
+
+
+The test environment
+
+It is recommended that you run queryperf and the name server under
+test on separate machines, so that the CPU usage of queryperf itself
+does not slow down the name server. The two machines should be
+connected with a fast network, preferably a dedicated 100baseT
+segment. Testing through a router or firewall is not advisable.
+
+
+Configuring the server
+
+The name server under test should be set up as an authoritative
+server, serving one or more zones similar in size and number to
+what the server is expected to serve in production.
+
+Be sure to turn off recursion in the server's configuration
+(in BIND 8/9, specify "recursion no;" in the options block).
+In BIND 8, you should also specify "fetch-glue no;"; otherwise
+the server may attempt to retrieve glue information from the
+Internet during the test, slowing it down by an unpredictable
+factor.
+
+
+Constructing the input file
+
+You need to construct a queryperf input file containing a large and
+realistic set of queries, on the order of ten thousand to a million.
+The input file contains one line per query, consisting of a domain
+name and an RR type name separated by a space. The class of the
+query is implicitly IN.
+
+When measuring the performance serving non-terminal zones such as the
+root zone or TLDs, note that such servers spend most of their time
+providing referral responses, not authoritative answers. Therefore, a
+realistic input file might consist mostly of queries for type A for
+names *below*, not at, the delegations present in the zone. For
+example, when testing the performance of a server configured to be
+authoritative for the top-level domain "fi.", which contains
+delegations for domains like "helsinki.fi" and "turku.fi", the input
+file could contain lines like
+
+ www.turku.fi A
+ www.helsinki.fi A
+
+where the "www" prefix ensures that the server will respond with a
+referral. Ideally, a realistic proportion of queries for nonexistent
+domains should be mixed in with those for existing ones, and the lines
+of the input file should be in a random order.
+
+
+Running the tests
+
+Queryperf is run specifying the input file using the "-d" option, as
+in
+
+ queryperf -d input_file -s server
+
+The output of queryperf is mostly self-explanatory. Pay attention to
+the number of dropped packets reported - when running the test over a
+local Ethernet connection, it should be zero. If one or more packets
+has been dropped, there may be a problem with the network connection.
+In that case, the results should be considered suspect and the test
+repeated.
diff --git a/contrib/queryperf/config.h.in b/contrib/queryperf/config.h.in
new file mode 100644
index 0000000..744afdd
--- /dev/null
+++ b/contrib/queryperf/config.h.in
@@ -0,0 +1,37 @@
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `gethostbyname2' function. */
+#undef HAVE_GETHOSTBYNAME2
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define to 1 if `struct sockaddr' has element `sa_len'. */
+#undef HAVE_SA_LEN
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to `int' if `socklen_t' does not exist. */
+#undef socklen_t
diff --git a/contrib/queryperf/configure b/contrib/queryperf/configure
new file mode 100755
index 0000000..9cd2a99
--- /dev/null
+++ b/contrib/queryperf/configure
@@ -0,0 +1,4365 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.61.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+ if (eval ":") 2>/dev/null; then
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+
+ if test $as_have_required = yes && (eval ":
+(as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=\$LINENO
+ as_lineno_2=\$LINENO
+ test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+ test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+ :
+else
+ as_candidate_shells=
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ case $as_dir in
+ /*)
+ for as_base in sh bash ksh sh5; do
+ as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+ done;;
+ esac
+done
+IFS=$as_save_IFS
+
+
+ for as_shell in $as_candidate_shells $SHELL; do
+ # Try only shells that exist, to save several forks.
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+ CONFIG_SHELL=$as_shell
+ as_have_required=yes
+ if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+ (exit $1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+ break
+fi
+
+fi
+
+ done
+
+ if test "x$CONFIG_SHELL" != x; then
+ for as_var in BASH_ENV ENV
+ do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ done
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+ if test $as_have_required = no; then
+ echo This script requires a shell more modern than all the
+ echo shells that I found on your system. Please install a
+ echo modern shell, or manually run the script under such a
+ echo shell if you do have one.
+ { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+ (exit \$1)
+}
+as_func_success () {
+ as_func_return 0
+}
+as_func_failure () {
+ as_func_return 1
+}
+as_func_ret_success () {
+ return 0
+}
+as_func_ret_failure () {
+ return 1
+}
+
+exitcode=0
+if as_func_success; then
+ :
+else
+ exitcode=1
+ echo as_func_success failed.
+fi
+
+if as_func_failure; then
+ exitcode=1
+ echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+ :
+else
+ exitcode=1
+ echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+ exitcode=1
+ echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+ :
+else
+ exitcode=1
+ echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+ echo No shell found that supports shell functions.
+ echo Please tell autoconf@gnu.org about your system,
+ echo including any error possibly output before this
+ echo message
+}
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="queryperf.c"
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+LIBOBJS
+LTLIBOBJS'
+ac_subst_files=''
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'`
+ eval enable_$ac_feature=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/[-.]/_/g'`
+ eval with_$ac_package=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute directory names.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ { echo "$as_me: error: Working directory cannot be determined" >&2
+ { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ { echo "$as_me: error: pwd does not report name of working directory" >&2
+ { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$0" ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+ { (exit 1); exit 1; }; }
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" || continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.61
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+ set x "$ac_default_prefix/share/config.site" \
+ "$ac_default_prefix/etc/config.site"
+fi
+shift
+for ac_site_file
+do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO: checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler --version >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -v >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compiler -V >&5") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort. b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions. Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+
+{ echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
+if test -z "$ac_file"; then
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+{ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ CFLAGS=""
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_prog_cc_c89=$ac_arg
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+ xno)
+ { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+{ echo "$as_me:$LINENO: checking for library containing res_mkquery" >&5
+echo $ECHO_N "checking for library containing res_mkquery... $ECHO_C" >&6; }
+if test "${ac_cv_search_res_mkquery+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char res_mkquery ();
+int
+main ()
+{
+return res_mkquery ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' resolv bind; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search_res_mkquery=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search_res_mkquery+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_res_mkquery+set}" = set; then
+ :
+else
+ ac_cv_search_res_mkquery=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_res_mkquery" >&5
+echo "${ECHO_T}$ac_cv_search_res_mkquery" >&6; }
+ac_res=$ac_cv_search_res_mkquery
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ echo "$as_me:$LINENO: checking for library containing __res_mkquery" >&5
+echo $ECHO_N "checking for library containing __res_mkquery... $ECHO_C" >&6; }
+if test "${ac_cv_search___res_mkquery+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char __res_mkquery ();
+int
+main ()
+{
+return __res_mkquery ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' resolv bind; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_search___res_mkquery=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext
+ if test "${ac_cv_search___res_mkquery+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search___res_mkquery+set}" = set; then
+ :
+else
+ ac_cv_search___res_mkquery=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search___res_mkquery" >&5
+echo "${ECHO_T}$ac_cv_search___res_mkquery" >&6; }
+ac_res=$ac_cv_search___res_mkquery
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for socket in -lsocket" >&5
+echo $ECHO_N "checking for socket in -lsocket... $ECHO_C" >&6; }
+if test "${ac_cv_lib_socket_socket+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_socket_socket=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_socket_socket=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_socket" >&6; }
+if test $ac_cv_lib_socket_socket = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
+
+ LIBS="-lsocket $LIBS"
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for inet_ntoa in -lnsl" >&5
+echo $ECHO_N "checking for inet_ntoa in -lnsl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_nsl_inet_ntoa+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnsl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inet_ntoa ();
+int
+main ()
+{
+return inet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_nsl_inet_ntoa=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_nsl_inet_ntoa=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_inet_ntoa" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_inet_ntoa" >&6; }
+if test $ac_cv_lib_nsl_inet_ntoa = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNSL 1
+_ACEOF
+
+ LIBS="-lnsl $LIBS"
+
+fi
+
+
+for ac_func in gethostbyname2
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+{ echo "$as_me:$LINENO: checking for getaddrinfo" >&5
+echo $ECHO_N "checking for getaddrinfo... $ECHO_C" >&6; }
+if test "${ac_cv_func_getaddrinfo+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getaddrinfo to an innocuous variant, in case <limits.h> declares getaddrinfo.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getaddrinfo innocuous_getaddrinfo
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getaddrinfo (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getaddrinfo
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getaddrinfo ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_getaddrinfo || defined __stub___getaddrinfo
+choke me
+#endif
+
+int
+main ()
+{
+return getaddrinfo ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_getaddrinfo=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_getaddrinfo=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_getaddrinfo" >&5
+echo "${ECHO_T}$ac_cv_func_getaddrinfo" >&6; }
+if test $ac_cv_func_getaddrinfo = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETADDRINFO 1
+_ACEOF
+
+else
+ case " $LIBOBJS " in
+ *" getaddrinfo.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS getaddrinfo.$ac_objext"
+ ;;
+esac
+
+fi
+
+{ echo "$as_me:$LINENO: checking for getnameinfo" >&5
+echo $ECHO_N "checking for getnameinfo... $ECHO_C" >&6; }
+if test "${ac_cv_func_getnameinfo+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define getnameinfo to an innocuous variant, in case <limits.h> declares getnameinfo.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getnameinfo innocuous_getnameinfo
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getnameinfo (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getnameinfo
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getnameinfo ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_getnameinfo || defined __stub___getnameinfo
+choke me
+#endif
+
+int
+main ()
+{
+return getnameinfo ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_getnameinfo=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_func_getnameinfo=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_getnameinfo" >&5
+echo "${ECHO_T}$ac_cv_func_getnameinfo" >&6; }
+if test $ac_cv_func_getnameinfo = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETNAMEINFO 1
+_ACEOF
+
+else
+ case " $LIBOBJS " in
+ *" getnameinfo.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS getnameinfo.$ac_objext"
+ ;;
+esac
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for socklen_t" >&5
+echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6; }
+if test "${ac_cv_type_socklen_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/socket.h>
+int
+main ()
+{
+socklen_t len = 42; return len;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_type_socklen_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_type_socklen_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5
+echo "${ECHO_T}$ac_cv_type_socklen_t" >&6; }
+ if test $ac_cv_type_socklen_t != yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define socklen_t int
+_ACEOF
+
+ fi
+
+{ echo "$as_me:$LINENO: checking for sa_len" >&5
+echo $ECHO_N "checking for sa_len... $ECHO_C" >&6; }
+if test "${ac_cv_sa_len+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/socket.h>
+int
+main ()
+{
+struct sockaddr sa; sa.sa_len = 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sa_len=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_sa_len=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sa_len" >&5
+echo "${ECHO_T}$ac_cv_sa_len" >&6; }
+ if test $ac_cv_sa_len = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SA_LEN 1
+_ACEOF
+
+ fi
+
+
+ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ *) $as_unset $ac_var ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ test "x$cache_file" != "x/dev/null" &&
+ { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
+ cat confcache >$cache_file
+ else
+ { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in
+ *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line after each line using $LINENO; the second 'sed'
+ # does the real work. The second script uses 'N' to pair each
+ # line-number line with the line containing $LINENO, and appends
+ # trailing '-' during substitution so that $LINENO is not a special
+ # case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # scripts with optimization help from Paolo Bonzini. Blame Lee
+ # E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+ case `echo 'x\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ *) ECHO_C='\c';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir
+fi
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -p'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -p'
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+ as_test_x='test -x'
+else
+ if ls -dL / >/dev/null 2>&1; then
+ as_ls_L_option=L
+ else
+ as_ls_L_option=
+ fi
+ as_test_x='
+ eval sh -c '\''
+ if test -d "$1"; then
+ test -d "$1/.";
+ else
+ case $1 in
+ -*)set "./$1";;
+ esac;
+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+ ???[sx]*):;;*)false;;esac;fi
+ '\'' sh
+ '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.61. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.61,
+ with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2006 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ echo "$ac_cs_version"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ { echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ CONFIG_SHELL=$SHELL
+ export CONFIG_SHELL
+ exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp=
+ trap 'exit_status=$?
+ { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+#
+# Set up the sed scripts for CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 46; then
+ break
+ elif $ac_last_try; then
+ { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+ { (exit 1); exit 1; }; }
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+ ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+ ac_eof=`expr $ac_eof + 1`
+fi
+
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
+_ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[ ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in :F $CONFIG_FILES :H $CONFIG_HEADERS
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+ { (exit 1); exit 1; }; };;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+ ac_file_inputs="$ac_file_inputs $ac_f"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input="Generated from "`IFS=:
+ echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ fi
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$tmp/stdin";;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { as_dir="$ac_dir"
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
+ { (exit 1); exit 1; }; }; }
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+ { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined." >&2;}
+
+ rm -f "$tmp/stdin"
+ case $ac_file in
+ -) cat "$tmp/out"; rm -f "$tmp/out";;
+ *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+ esac
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+_ACEOF
+
+# Transform confdefs.h into a sed script `conftest.defines', that
+# substitutes the proper values into config.h.in to produce config.h.
+rm -f conftest.defines conftest.tail
+# First, append a space to every undef/define line, to ease matching.
+echo 's/$/ /' >conftest.defines
+# Then, protect against being on the right side of a sed subst, or in
+# an unquoted here document, in config.status. If some macros were
+# called several times there might be several #defines for the same
+# symbol, which is useless. But do not sort them, since the last
+# AC_DEFINE must be honored.
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
+# NAME is the cpp macro being defined, VALUE is the value it is being given.
+# PARAMS is the parameter list in the macro definition--in most cases, it's
+# just an empty string.
+ac_dA='s,^\\([ #]*\\)[^ ]*\\([ ]*'
+ac_dB='\\)[ (].*,\\1define\\2'
+ac_dC=' '
+ac_dD=' ,'
+
+uniq confdefs.h |
+ sed -n '
+ t rset
+ :rset
+ s/^[ ]*#[ ]*define[ ][ ]*//
+ t ok
+ d
+ :ok
+ s/[\\&,]/\\&/g
+ s/^\('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
+ s/^\('"$ac_word_re"'\)[ ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
+ ' >>conftest.defines
+
+# Remove the space that was appended to ease matching.
+# Then replace #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+# (The regexp can be short, since the line contains either #define or #undef.)
+echo 's/ $//
+s,^[ #]*u.*,/* & */,' >>conftest.defines
+
+# Break up conftest.defines:
+ac_max_sed_lines=50
+
+# First sed command is: sed -f defines.sed $ac_file_inputs >"$tmp/out1"
+# Second one is: sed -f defines.sed "$tmp/out1" >"$tmp/out2"
+# Third one will be: sed -f defines.sed "$tmp/out2" >"$tmp/out1"
+# et cetera.
+ac_in='$ac_file_inputs'
+ac_out='"$tmp/out1"'
+ac_nxt='"$tmp/out2"'
+
+while :
+do
+ # Write a here document:
+ cat >>$CONFIG_STATUS <<_ACEOF
+ # First, check the format of the line:
+ cat >"\$tmp/defines.sed" <<\\CEOF
+/^[ ]*#[ ]*undef[ ][ ]*$ac_word_re[ ]*\$/b def
+/^[ ]*#[ ]*define[ ][ ]*$ac_word_re[( ]/b def
+b
+:def
+_ACEOF
+ sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
+ ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
+ sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
+ grep . conftest.tail >/dev/null || break
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines conftest.tail
+
+echo "ac_result=$ac_in" >>$CONFIG_STATUS
+cat >>$CONFIG_STATUS <<\_ACEOF
+ if test x"$ac_file" != x-; then
+ echo "/* $configure_input */" >"$tmp/config.h"
+ cat "$ac_result" >>"$tmp/config.h"
+ if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f $ac_file
+ mv "$tmp/config.h" $ac_file
+ fi
+ else
+ echo "/* $configure_input */"
+ cat "$ac_result"
+ fi
+ rm -f "$tmp/out12"
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/contrib/queryperf/configure.in b/contrib/queryperf/configure.in
new file mode 100644
index 0000000..2f0f7af
--- /dev/null
+++ b/contrib/queryperf/configure.in
@@ -0,0 +1,70 @@
+#
+# Copyright (C) 2000, 2001 Nominum, Inc.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+AC_INIT(queryperf.c)
+
+AC_PREREQ(2.13)
+
+AC_PROG_CC
+
+AC_DEFUN(AC_TYPE_SOCKLEN_T,
+[AC_CACHE_CHECK([for socklen_t], ac_cv_type_socklen_t,
+[
+ AC_TRY_COMPILE(
+ [#include <sys/types.h>
+ #include <sys/socket.h>],
+ [socklen_t len = 42; return len;],
+ ac_cv_type_socklen_t=yes,
+ ac_cv_type_socklen_t=no)
+])
+ if test $ac_cv_type_socklen_t != yes; then
+ AC_DEFINE(socklen_t, int, [Define to `int' if `socklen_t' does not exist.])
+ fi
+])
+
+AC_DEFUN(AC_SA_LEN,
+[AC_CACHE_CHECK([for sa_len], ac_cv_sa_len,
+[
+ AC_TRY_COMPILE(
+ [#include <sys/types.h>
+ #include <sys/socket.h>],
+ [struct sockaddr sa; sa.sa_len = 0;],
+ ac_cv_sa_len=yes,
+ ac_cv_sa_len=no)
+])
+ if test $ac_cv_sa_len = yes; then
+ AC_DEFINE(HAVE_SA_LEN, 1, [Define to 1 if `struct sockaddr' has element `sa_len'.])
+ fi
+])
+
+AC_CONFIG_HEADERS(config.h)
+AC_SEARCH_LIBS(res_mkquery, resolv bind)
+AC_SEARCH_LIBS(__res_mkquery, resolv bind)
+AC_CHECK_LIB(socket, socket)
+AC_CHECK_LIB(nsl, inet_ntoa)
+AC_CHECK_FUNCS(gethostbyname2)
+AC_CHECK_FUNC(getaddrinfo,
+ AC_DEFINE(HAVE_GETADDRINFO, 1, [Define to 1 if you have the `getaddrinfo' function.]),
+ [AC_LIBOBJ(getaddrinfo)])
+AC_CHECK_FUNC(getnameinfo,
+ AC_DEFINE(HAVE_GETNAMEINFO, 1, [Define to 1 if you have the `getnameinfo' function.]),
+ [AC_LIBOBJ(getnameinfo)])
+
+AC_TYPE_SOCKLEN_T
+AC_SA_LEN
+
+AC_OUTPUT(Makefile)
diff --git a/contrib/queryperf/input/sample.0 b/contrib/queryperf/input/sample.0
new file mode 100644
index 0000000..024d8a0
--- /dev/null
+++ b/contrib/queryperf/input/sample.0
@@ -0,0 +1,6 @@
+; This is a comment
+#server ns.sector93.ie
+#port 53
+#maxwait 5
+meow.com MX
+1.0.0.10.in-addr.arpa PTR
diff --git a/contrib/queryperf/input/sample.1 b/contrib/queryperf/input/sample.1
new file mode 100644
index 0000000..e2911a5
--- /dev/null
+++ b/contrib/queryperf/input/sample.1
@@ -0,0 +1,13 @@
+; Sample input data file
+
+;#server ns.sector93.ie
+;#port 53
+;#maxwait 10
+
+1-host.com ANY
+1-linknet.com A
+1.0-127.35.195.200.in-addr.arpa PTR
+1.0-63.236.210.200.in-addr.arpa PTR
+1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.int PTR
+1.0.0.0.in-addr.arpa PTR
+1.0.0.10.in-addr.arpa PTR
diff --git a/contrib/queryperf/missing/addrinfo.h b/contrib/queryperf/missing/addrinfo.h
new file mode 100644
index 0000000..54a5e85
--- /dev/null
+++ b/contrib/queryperf/missing/addrinfo.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef HAVE_GETADDRINFO
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+#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_MAX 14
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#define AI_PASSIVE 0x00000001 /* get address to use bind() */
+#define AI_CANONNAME 0x00000002 /* fill ai_canonname */
+#define AI_NUMERICHOST 0x00000004 /* prevent name resolution */
+/* valid flags for addrinfo */
+#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
+
+#define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
+#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
+#define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */
+#define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */
+/* special recommended flags for getipnodebyname */
+#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
+
+/*
+ * Constants for getnameinfo()
+ */
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+
+/*
+ * Flag values for getnameinfo()
+ */
+#define NI_NOFQDN 0x00000001
+#define NI_NUMERICHOST 0x00000002
+#define NI_NAMEREQD 0x00000004
+#define NI_NUMERICSERV 0x00000008
+#define NI_DGRAM 0x00000010
+
+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 */
+};
+
+struct sockaddr_storage {
+ u_char __ss_len;
+ u_char __ss_family;
+ u_char fill[126];
+};
+
+extern void freehostent(struct hostent *);
+extern char *gai_strerror(int);
+#endif
diff --git a/contrib/queryperf/missing/getaddrinfo.c b/contrib/queryperf/missing/getaddrinfo.c
new file mode 100644
index 0000000..69eb748
--- /dev/null
+++ b/contrib/queryperf/missing/getaddrinfo.c
@@ -0,0 +1,632 @@
+/*
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include "addrinfo.h"
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO 0
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in6_addrany[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const char in_loopback[] = { 127, 0, 0, 1 };
+static const char in6_loopback[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+};
+
+struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
+};
+
+static struct afd {
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+ const char *a_addrany;
+ const char *a_loopback;
+} afdl [] = {
+#ifdef INET6
+#define N_INET6 0
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr),
+ in6_addrany, in6_loopback},
+#define N_INET 1
+#else
+#define N_INET 0
+#endif
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr),
+ in_addrany, in_loopback},
+ {0, 0, 0, 0, NULL, NULL},
+};
+
+#ifdef INET6
+#define PTON_MAX 16
+#else
+#define PTON_MAX 4
+#endif
+
+
+static int get_name(const char *, struct afd *,
+ struct addrinfo **, char *, struct addrinfo *,
+ int);
+static int get_addr(const char *, int, struct addrinfo **,
+ struct addrinfo *, int);
+static int get_addr0(const char *, int, struct addrinfo **,
+ struct addrinfo *, int);
+static int str_isnumber(const char *);
+
+static char *ai_errlist[] = {
+ "Success",
+ "Address family for hostname not supported", /* EAI_ADDRFAMILY */
+ "Temporary failure in name resolution", /* EAI_AGAIN */
+ "Invalid value for ai_flags", /* EAI_BADFLAGS */
+ "Non-recoverable failure in name resolution", /* EAI_FAIL */
+ "ai_family not supported", /* EAI_FAMILY */
+ "Memory allocation failure", /* EAI_MEMORY */
+ "No address associated with hostname", /* EAI_NODATA */
+ "hostname nor servname provided, or not known",/* EAI_NONAME */
+ "servname not supported for ai_socktype", /* EAI_SERVICE */
+ "ai_socktype not supported", /* EAI_SOCKTYPE */
+ "System error returned in errno", /* EAI_SYSTEM */
+ "Invalid value for hints", /* EAI_BADHINTS */
+ "Resolved protocol is unknown", /* EAI_PROTOCOL */
+ "Unknown error", /* EAI_MAX */
+};
+
+#define GET_CANONNAME(ai, str) \
+if (pai->ai_flags & AI_CANONNAME) {\
+ if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
+ strcpy((ai)->ai_canonname, (str));\
+ } else {\
+ error = EAI_MEMORY;\
+ goto free;\
+ }\
+}
+
+#ifdef HAVE_SA_LEN
+#define SET_AILEN(ai,l) (ai)->ai_addr->sa_len = (ai)->ai_addrlen = (l)
+#else
+#define SET_AILEN(ai,l) (ai)->ai_addrlen = (l)
+#endif
+
+#define GET_AI(ai, afd, addr, port) {\
+ char *p;\
+ if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
+ ((afd)->a_socklen)))\
+ == NULL) {\
+ error = EAI_MEMORY;\
+ goto free;\
+ }\
+ memcpy(ai, pai, sizeof(struct addrinfo));\
+ (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
+ memset((ai)->ai_addr, 0, (afd)->a_socklen);\
+ SET_AILEN((ai), (afd)->a_socklen);\
+ (ai)->ai_addr->sa_family = (ai)->ai_family = (afd)->a_af;\
+ ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
+ p = (char *)((ai)->ai_addr);\
+ memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
+}
+
+#define ERR(err) { error = (err); goto bad; }
+
+char *
+gai_strerror(ecode)
+ int ecode;
+{
+ if (ecode < 0 || ecode > EAI_MAX)
+ ecode = EAI_MAX;
+ return ai_errlist[ecode];
+}
+
+void
+freeaddrinfo(ai)
+ struct addrinfo *ai;
+{
+ struct addrinfo *next;
+
+ do {
+ next = ai->ai_next;
+ if (ai->ai_canonname)
+ free(ai->ai_canonname);
+ /* no need to free(ai->ai_addr) */
+ free(ai);
+ } while ((ai = next) != NULL);
+}
+
+static int
+str_isnumber(p)
+ const char *p;
+{
+ char *q = (char *)p;
+ while (*q) {
+ if (! isdigit(*q))
+ return NO;
+ q++;
+ }
+ return YES;
+}
+
+int
+getaddrinfo(hostname, servname, hints, res)
+ const char *hostname, *servname;
+ const struct addrinfo *hints;
+ struct addrinfo **res;
+{
+ struct addrinfo sentinel;
+ struct addrinfo *top = NULL;
+ struct addrinfo *cur;
+ int i, error = 0;
+ char pton[PTON_MAX];
+ struct addrinfo ai;
+ struct addrinfo *pai;
+ u_short port;
+
+ /* initialize file static vars */
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+ pai = &ai;
+ pai->ai_flags = 0;
+ pai->ai_family = PF_UNSPEC;
+ pai->ai_socktype = ANY;
+ pai->ai_protocol = ANY;
+ pai->ai_addrlen = 0;
+ pai->ai_canonname = NULL;
+ pai->ai_addr = NULL;
+ pai->ai_next = NULL;
+ port = ANY;
+
+ if (hostname == NULL && servname == NULL)
+ return EAI_NONAME;
+ if (hints) {
+ /* error check for hints */
+ if (hints->ai_addrlen || hints->ai_canonname ||
+ hints->ai_addr || hints->ai_next)
+ ERR(EAI_BADHINTS); /* xxx */
+ if (hints->ai_flags & ~AI_MASK)
+ ERR(EAI_BADFLAGS);
+ switch (hints->ai_family) {
+ case PF_UNSPEC:
+ case PF_INET:
+#ifdef INET6
+ case PF_INET6:
+#endif
+ break;
+ default:
+ ERR(EAI_FAMILY);
+ }
+ memcpy(pai, hints, sizeof(*pai));
+ switch (pai->ai_socktype) {
+ case ANY:
+ switch (pai->ai_protocol) {
+ case ANY:
+ break;
+ case IPPROTO_UDP:
+ pai->ai_socktype = SOCK_DGRAM;
+ break;
+ case IPPROTO_TCP:
+ pai->ai_socktype = SOCK_STREAM;
+ break;
+ default:
+ pai->ai_socktype = SOCK_RAW;
+ break;
+ }
+ break;
+ case SOCK_RAW:
+ break;
+ case SOCK_DGRAM:
+ if (pai->ai_protocol != IPPROTO_UDP &&
+ pai->ai_protocol != ANY)
+ ERR(EAI_BADHINTS); /*xxx*/
+ pai->ai_protocol = IPPROTO_UDP;
+ break;
+ case SOCK_STREAM:
+ if (pai->ai_protocol != IPPROTO_TCP &&
+ pai->ai_protocol != ANY)
+ ERR(EAI_BADHINTS); /*xxx*/
+ pai->ai_protocol = IPPROTO_TCP;
+ break;
+ default:
+ ERR(EAI_SOCKTYPE);
+ break;
+ }
+ }
+
+ /*
+ * service port
+ */
+ if (servname) {
+ if (str_isnumber(servname)) {
+ if (pai->ai_socktype == ANY) {
+ /* caller accept *ANY* socktype */
+ pai->ai_socktype = SOCK_DGRAM;
+ pai->ai_protocol = IPPROTO_UDP;
+ }
+ port = htons(atoi(servname));
+ } else {
+ struct servent *sp;
+ char *proto;
+
+ proto = NULL;
+ switch (pai->ai_socktype) {
+ case ANY:
+ proto = NULL;
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ default:
+ fprintf(stderr, "panic!\n");
+ break;
+ }
+ if ((sp = getservbyname(servname, proto)) == NULL)
+ ERR(EAI_SERVICE);
+ port = sp->s_port;
+ if (pai->ai_socktype == ANY) {
+ if (strcmp(sp->s_proto, "udp") == 0) {
+ pai->ai_socktype = SOCK_DGRAM;
+ pai->ai_protocol = IPPROTO_UDP;
+ } else if (strcmp(sp->s_proto, "tcp") == 0) {
+ pai->ai_socktype = SOCK_STREAM;
+ pai->ai_protocol = IPPROTO_TCP;
+ } else
+ ERR(EAI_PROTOCOL); /*xxx*/
+ }
+ }
+ }
+
+ /*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+ if (hostname == NULL) {
+ struct afd *afd;
+ int s;
+
+ for (afd = &afdl[0]; afd->a_af; afd++) {
+ if (!(pai->ai_family == PF_UNSPEC
+ || pai->ai_family == afd->a_af)) {
+ continue;
+ }
+
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ s = socket(afd->a_af, SOCK_DGRAM, 0);
+ if (s < 0)
+ continue;
+ close(s);
+
+ if (pai->ai_flags & AI_PASSIVE) {
+ GET_AI(cur->ai_next, afd, afd->a_addrany, port);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "anyaddr");
+ */
+ } else {
+ GET_AI(cur->ai_next, afd, afd->a_loopback,
+ port);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "localhost");
+ */
+ }
+ cur = cur->ai_next;
+ }
+ top = sentinel.ai_next;
+ if (top)
+ goto good;
+ else
+ ERR(EAI_FAMILY);
+ }
+
+ /* hostname as numeric name */
+ for (i = 0; afdl[i].a_af; i++) {
+ if (inet_pton(afdl[i].a_af, hostname, pton) == 1) {
+ u_long v4a;
+ u_char pfx;
+
+ switch (afdl[i].a_af) {
+ case AF_INET:
+ v4a = ntohl(((struct in_addr *)pton)->s_addr);
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ pai->ai_flags &= ~AI_CANONNAME;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ pai->ai_flags &= ~AI_CANONNAME;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ pfx = ((struct in6_addr *)pton)->s6_addr[0];
+ if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+ pai->ai_flags &= ~AI_CANONNAME;
+ break;
+#endif
+ }
+
+ if (pai->ai_family == afdl[i].a_af ||
+ pai->ai_family == PF_UNSPEC) {
+ if (! (pai->ai_flags & AI_CANONNAME)) {
+ GET_AI(top, &afdl[i], pton, port);
+ goto good;
+ }
+ /*
+ * if AI_CANONNAME and if reverse lookup
+ * fail, return ai anyway to pacify
+ * calling application.
+ *
+ * XXX getaddrinfo() is a name->address
+ * translation function, and it looks strange
+ * that we do addr->name translation here.
+ */
+ get_name(pton, &afdl[i], &top, pton, pai, port);
+ goto good;
+ } else
+ ERR(EAI_FAMILY); /*xxx*/
+ }
+ }
+
+ if (pai->ai_flags & AI_NUMERICHOST)
+ ERR(EAI_NONAME);
+
+ /* hostname as alphabetical name */
+ error = get_addr(hostname, pai->ai_family, &top, pai, port);
+ if (error == 0) {
+ if (top) {
+ good:
+ *res = top;
+ return SUCCESS;
+ } else
+ error = EAI_FAIL;
+ }
+ free:
+ if (top)
+ freeaddrinfo(top);
+ bad:
+ *res = NULL;
+ return error;
+}
+
+static int
+get_name(addr, afd, res, numaddr, pai, port0)
+ const char *addr;
+ struct afd *afd;
+ struct addrinfo **res;
+ char *numaddr;
+ struct addrinfo *pai;
+ int port0;
+{
+ u_short port = port0 & 0xffff;
+ struct hostent *hp;
+ struct addrinfo *cur;
+ int error = 0;
+ hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+ if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+ GET_AI(cur, afd, hp->h_addr_list[0], port);
+ GET_CANONNAME(cur, hp->h_name);
+ } else
+ GET_AI(cur, afd, numaddr, port);
+
+ *res = cur;
+ return SUCCESS;
+ free:
+ if (cur)
+ freeaddrinfo(cur);
+
+ /* bad: */
+ *res = NULL;
+ return error;
+}
+
+static int
+get_addr(hostname, af, res0, pai, port0)
+ const char *hostname;
+ int af;
+ struct addrinfo **res0;
+ struct addrinfo *pai;
+ int port0;
+{
+ int i, error, ekeep;
+ struct addrinfo *cur;
+ struct addrinfo **res;
+ int retry;
+ int s;
+
+ res = res0;
+ ekeep = 0;
+ error = 0;
+ for (i = 0; afdl[i].a_af; i++) {
+ retry = 0;
+ if (af == AF_UNSPEC) {
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ s = socket(afdl[i].a_af, SOCK_DGRAM, 0);
+ if (s < 0)
+ continue;
+ close(s);
+ } else {
+ if (af != afdl[i].a_af)
+ continue;
+ }
+ /* It is WRONG, we need getipnodebyname(). */
+again:
+ error = get_addr0(hostname, afdl[i].a_af, res, pai, port0);
+ switch (error) {
+ case EAI_AGAIN:
+ if (++retry < 3)
+ goto again;
+ /* FALL THROUGH*/
+ default:
+ if (ekeep == 0)
+ ekeep = error;
+ break;
+ }
+ if (*res) {
+ /* make chain of addrs */
+ for (cur = *res;
+ cur && cur->ai_next;
+ cur = cur->ai_next)
+ ;
+ if (!cur)
+ return EAI_FAIL;
+ res = &cur->ai_next;
+ }
+ }
+
+ /* if we got something, it's okay */
+ if (*res0)
+ return 0;
+
+ return error ? error : ekeep;
+}
+
+static int
+get_addr0(hostname, af, res, pai, port0)
+ const char *hostname;
+ int af;
+ struct addrinfo **res;
+ struct addrinfo *pai;
+ int port0;
+{
+ u_short port = port0 & 0xffff;
+ struct addrinfo sentinel;
+ struct hostent *hp;
+ struct addrinfo *top, *cur;
+ struct afd *afd;
+ int i, error = 0, h_error;
+ char *ap;
+
+ top = NULL;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+#ifdef HAVE_GETHOSTBYNAME2
+ if (af == AF_UNSPEC) {
+ error = EAI_FAIL;
+ goto bad;
+ }
+ hp = gethostbyname2(hostname, af);
+#else
+ if (af != AF_UNSPEC && af != AF_INET) {
+ error = EAI_FAIL;
+ goto bad;
+ }
+ hp = gethostbyname(hostname);
+#endif
+ h_error = h_errno;
+
+ if (hp == NULL) {
+ switch (h_error) {
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ error = EAI_NODATA;
+ break;
+ case TRY_AGAIN:
+ error = EAI_AGAIN;
+ break;
+ case NO_RECOVERY:
+ case NETDB_INTERNAL:
+ default:
+ error = EAI_FAIL;
+ break;
+ }
+ goto bad;
+ }
+
+ if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
+ (hp->h_addr_list[0] == NULL))
+ ERR(EAI_FAIL);
+
+ for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
+ switch (af) {
+#ifdef INET6
+ case AF_INET6:
+ afd = &afdl[N_INET6];
+ break;
+#endif
+#ifndef INET6
+ default: /* AF_UNSPEC */
+#endif
+ case AF_INET:
+ afd = &afdl[N_INET];
+ break;
+#ifdef INET6
+ default: /* AF_UNSPEC */
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
+ ap += sizeof(struct in6_addr) -
+ sizeof(struct in_addr);
+ afd = &afdl[N_INET];
+ } else
+ afd = &afdl[N_INET6];
+ break;
+#endif
+ }
+ GET_AI(cur->ai_next, afd, ap, port);
+ if (cur == &sentinel) {
+ top = cur->ai_next;
+ GET_CANONNAME(top, hp->h_name);
+ }
+ cur = cur->ai_next;
+ }
+ *res = top;
+ return SUCCESS;
+ free:
+ if (top)
+ freeaddrinfo(top);
+ bad:
+ *res = NULL;
+ return error;
+}
diff --git a/contrib/queryperf/missing/getnameinfo.c b/contrib/queryperf/missing/getnameinfo.c
new file mode 100644
index 0000000..6b1cbe1
--- /dev/null
+++ b/contrib/queryperf/missing/getnameinfo.c
@@ -0,0 +1,226 @@
+/*
+ * 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.
+ */
+
+/*
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked
+ * - Return values. There seems to be no standard for return value (RFC2553)
+ * but INRIA implementation returns EAI_xxx defined for getaddrinfo().
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stddef.h>
+
+#include "addrinfo.h"
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO 0
+
+static struct afd {
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+} afdl [] = {
+#ifdef INET6
+ {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr)},
+#endif
+ {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr)},
+ {0, 0, 0},
+};
+
+struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
+};
+
+#define ENI_NOSOCKET 0
+#define ENI_NOSERVNAME 1
+#define ENI_NOHOSTNAME 2
+#define ENI_MEMORY 3
+#define ENI_SYSTEM 4
+#define ENI_FAMILY 5
+#define ENI_SALEN 6
+
+int
+getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
+ const struct sockaddr *sa;
+ size_t salen;
+ char *host;
+ size_t hostlen;
+ char *serv;
+ size_t servlen;
+ int flags;
+{
+ struct afd *afd;
+ struct servent *sp;
+ struct hostent *hp;
+ u_short port;
+ int family, len, i;
+ char *addr, *p;
+ u_long v4a;
+ int h_error;
+ char numserv[512];
+ char numaddr[512];
+
+ if (sa == NULL)
+ return ENI_NOSOCKET;
+
+#ifdef HAVE_SA_LEN
+ len = sa->sa_len;
+ if (len != salen) return ENI_SALEN;
+#else
+ len = salen;
+#endif
+
+ family = sa->sa_family;
+ for (i = 0; afdl[i].a_af; i++)
+ if (afdl[i].a_af == family) {
+ afd = &afdl[i];
+ goto found;
+ }
+ return ENI_FAMILY;
+
+ found:
+ if (len != afd->a_socklen) return ENI_SALEN;
+
+ port = ((struct sockinet *)sa)->si_port; /* network byte order */
+ addr = (char *)sa + afd->a_off;
+
+ if (serv == NULL || servlen == 0) {
+ /* what we should do? */
+ } else if (flags & NI_NUMERICSERV) {
+ snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
+ if (strlen(numserv) > servlen)
+ return ENI_MEMORY;
+ strcpy(serv, numserv);
+ } else {
+ sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
+ if (sp) {
+ if (strlen(sp->s_name) > servlen)
+ return ENI_MEMORY;
+ strcpy(serv, sp->s_name);
+ } else
+ return ENI_NOSERVNAME;
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ v4a = ntohl(((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;
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *)sa;
+ switch (sin6->sin6_addr.s6_addr[0]) {
+ case 0x00:
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+ ;
+ else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
+ ;
+ else
+ flags |= NI_NUMERICHOST;
+ break;
+ default:
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
+ flags |= NI_NUMERICHOST;
+ else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
+ flags |= NI_NUMERICHOST;
+ break;
+ }
+ }
+ break;
+#endif
+ }
+ if (host == NULL || hostlen == 0) {
+ /* what should we do? */
+ } else if (flags & NI_NUMERICHOST) {
+ /* NUMERICHOST and NAMEREQD conflicts with each other */
+ if (flags & NI_NAMEREQD)
+ return ENI_NOHOSTNAME;
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_SYSTEM;
+ if (strlen(numaddr) > hostlen)
+ return ENI_MEMORY;
+ strcpy(host, numaddr);
+ } else {
+#ifdef USE_GETIPNODEBY
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+#else
+ hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+ h_error = h_errno;
+#endif
+
+ if (hp) {
+ if (flags & NI_NOFQDN) {
+ p = strchr(hp->h_name, '.');
+ if (p) *p = '\0';
+ }
+ if (strlen(hp->h_name) > hostlen) {
+#ifdef USE_GETIPNODEBY
+ freehostent(hp);
+#endif
+ return ENI_MEMORY;
+ }
+ strcpy(host, hp->h_name);
+#ifdef USE_GETIPNODEBY
+ freehostent(hp);
+#endif
+ } else {
+ if (flags & NI_NAMEREQD)
+ return ENI_NOHOSTNAME;
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_NOHOSTNAME;
+ if (strlen(numaddr) > hostlen)
+ return ENI_MEMORY;
+ strcpy(host, numaddr);
+ }
+ }
+ return SUCCESS;
+}
diff --git a/contrib/queryperf/queryperf.c b/contrib/queryperf/queryperf.c
new file mode 100644
index 0000000..d15b7c4
--- /dev/null
+++ b/contrib/queryperf/queryperf.c
@@ -0,0 +1,2113 @@
+/*
+ * Copyright (C) 2000, 2001 Nominum, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/***
+ *** DNS Query Performance Testing Tool (queryperf.c)
+ ***
+ *** Version $Id: queryperf.c,v 1.12 2007/09/05 07:36:04 marka Exp $
+ ***
+ *** Stephen Jacob <sj@nominum.com>
+ ***/
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <math.h>
+#include <errno.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#ifndef HAVE_GETADDRINFO
+#include "missing/addrinfo.h"
+#endif
+#endif
+
+/*
+ * Configuration defaults
+ */
+
+#define DEF_MAX_QUERIES_OUTSTANDING 20
+#define DEF_QUERY_TIMEOUT 5 /* in seconds */
+#define DEF_SERVER_TO_QUERY "127.0.0.1"
+#define DEF_SERVER_PORT "53"
+#define DEF_BUFFER_SIZE 32 /* in k */
+
+#define DEF_RTTARRAY_SIZE 50000
+#define DEF_RTTARRAY_UNIT 100 /* in usec */
+
+/*
+ * Other constants / definitions
+ */
+
+#define COMMENT_CHAR ';'
+#define CONFIG_CHAR '#'
+#define MAX_PORT 65535
+#define MAX_INPUT_LEN 512
+#define MAX_DOMAIN_LEN 255
+#define MAX_BUFFER_LEN 8192 /* in bytes */
+#define HARD_TIMEOUT_EXTRA 5 /* in seconds */
+#define RESPONSE_BLOCKING_WAIT_TIME 0.1 /* in seconds */
+#define EDNSLEN 11
+
+#define FALSE 0
+#define TRUE 1
+
+#define WHITESPACE " \t\n"
+
+enum directives_enum { V_SERVER, V_PORT, V_MAXQUERIES, V_MAXWAIT };
+#define DIRECTIVES { "server", "port", "maxqueries", "maxwait" }
+#define DIR_VALUES { V_SERVER, V_PORT, V_MAXQUERIES, V_MAXWAIT }
+
+#define QTYPE_STRINGS { \
+ "A", "NS", "MD", "MF", "CNAME", "SOA", "MB", "MG", \
+ "MR", "NULL", "WKS", "PTR", "HINFO", "MINFO", "MX", "TXT", \
+ "AAAA", "SRV", "NAPTR", "A6", "AXFR", "MAILB", "MAILA", "*", "ANY" \
+}
+
+#define QTYPE_CODES { \
+ 1, 2, 3, 4, 5, 6, 7, 8, \
+ 9, 10, 11, 12, 13, 14, 15, 16, \
+ 28, 33, 35, 38, 252, 253, 254, 255, 255 \
+}
+
+#define RCODE_STRINGS { \
+ "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", \
+ "NOTIMP", "REFUSED", "YXDOMAIN", "YXRRSET", \
+ "NXRRSET", "NOTAUTH", "NOTZONE", "rcode11", \
+ "rcode12", "rcode13", "rcode14", "rcode15" \
+}
+
+/*
+ * Data type definitions
+ */
+
+#define QUERY_STATUS_MAGIC 0x51535441U /* QSTA */
+#define VALID_QUERY_STATUS(q) ((q) != NULL && \
+ (q)->magic == QUERY_STATUS_MAGIC)
+
+struct query_status {
+ unsigned int magic;
+ int in_use;
+ unsigned short int id;
+ struct timeval sent_timestamp;
+ char *desc;
+};
+
+/*
+ * Configuration options (global)
+ */
+
+unsigned int max_queries_outstanding; /* init 0 */
+unsigned int query_timeout = DEF_QUERY_TIMEOUT;
+int ignore_config_changes = FALSE;
+unsigned int socket_bufsize = DEF_BUFFER_SIZE;
+
+int family = AF_UNSPEC;
+int use_stdin = TRUE;
+char *datafile_name; /* init NULL */
+
+char *server_to_query; /* init NULL */
+char *server_port; /* init NULL */
+struct addrinfo *server_ai; /* init NULL */
+
+int run_only_once = FALSE;
+int use_timelimit = FALSE;
+unsigned int run_timelimit; /* init 0 */
+unsigned int print_interval; /* init 0 */
+
+unsigned int target_qps; /* init 0 */
+
+int serverset = FALSE, portset = FALSE;
+int queriesset = FALSE, timeoutset = FALSE;
+int edns = FALSE, dnssec = FALSE;
+int countrcodes = FALSE;
+int rcodecounts[16] = {0};
+
+int verbose = FALSE;
+
+/*
+ * Other global stuff
+ */
+
+int setup_phase = TRUE;
+
+FILE *datafile_ptr; /* init NULL */
+unsigned int runs_through_file; /* init 0 */
+
+unsigned int num_queries_sent; /* init 0 */
+unsigned int num_queries_sent_interval;
+unsigned int num_queries_outstanding; /* init 0 */
+unsigned int num_queries_timed_out; /* init 0 */
+unsigned int num_queries_possiblydelayed; /* init 0 */
+unsigned int num_queries_timed_out_interval;
+unsigned int num_queries_possiblydelayed_interval;
+
+struct timeval time_of_program_start;
+struct timeval time_of_first_query;
+double time_of_first_query_sec;
+struct timeval time_of_first_query_interval;
+struct timeval time_of_end_of_run;
+struct timeval time_of_stop_sending;
+
+struct timeval time_of_queryset_start;
+double query_interval;
+struct timeval time_of_next_queryset;
+
+double rtt_max = -1;
+double rtt_max_interval = -1;
+double rtt_min = -1;
+double rtt_min_interval = -1;
+double rtt_total;
+double rtt_total_interval;
+int rttarray_size = DEF_RTTARRAY_SIZE;
+int rttarray_unit = DEF_RTTARRAY_UNIT;
+unsigned int *rttarray = NULL;
+unsigned int *rttarray_interval = NULL;
+unsigned int rtt_overflows;
+unsigned int rtt_overflows_interval;
+char *rtt_histogram_file = NULL;
+
+struct query_status *status; /* init NULL */
+unsigned int query_status_allocated; /* init 0 */
+
+int query_socket = -1;
+int socket4 = -1, socket6 = -1;
+
+static char *rcode_strings[] = RCODE_STRINGS;
+
+/*
+ * get_uint16:
+ * Get an unsigned short integer from a buffer (in network order)
+ */
+static unsigned short
+get_uint16(unsigned char *buf) {
+ unsigned short ret;
+
+ ret = buf[0] * 256 + buf[1];
+
+ return (ret);
+}
+
+/*
+ * show_startup_info:
+ * Show name/version
+ */
+void
+show_startup_info(void) {
+ printf("\n"
+"DNS Query Performance Testing Tool\n"
+"Version: $Id: queryperf.c,v 1.12 2007/09/05 07:36:04 marka Exp $\n"
+"\n");
+}
+
+/*
+ * show_usage:
+ * Print out usage/syntax information
+ */
+void
+show_usage(void) {
+ fprintf(stderr,
+"\n"
+"Usage: queryperf [-d datafile] [-s server_addr] [-p port] [-q num_queries]\n"
+" [-b bufsize] [-t timeout] [-n] [-l limit] [-f family] [-1]\n"
+" [-i interval] [-r arraysize] [-u unit] [-H histfile]\n"
+" [-T qps] [-e] [-D] [-c] [-v] [-h]\n"
+" -d specifies the input data file (default: stdin)\n"
+" -s sets the server to query (default: %s)\n"
+" -p sets the port on which to query the server (default: %s)\n"
+" -q specifies the maximum number of queries outstanding (default: %d)\n"
+" -t specifies the timeout for query completion in seconds (default: %d)\n"
+" -n causes configuration changes to be ignored\n"
+" -l specifies how a limit for how long to run tests in seconds (no default)\n"
+" -1 run through input only once (default: multiple iff limit given)\n"
+" -b set input/output buffer size in kilobytes (default: %d k)\n"
+" -i specifies interval of intermediate outputs in seconds (default: 0=none)\n"
+" -f specify address family of DNS transport, inet or inet6 (default: any)\n"
+" -r set RTT statistics array size (default: %d)\n"
+" -u set RTT statistics time unit in usec (default: %d)\n"
+" -H specifies RTT histogram data file (default: none)\n"
+" -T specify the target qps (default: 0=unspecified)\n"
+" -e enable EDNS 0\n"
+" -D set the DNSSEC OK bit (implies EDNS)\n"
+" -c print the number of packets with each rcode\n"
+" -v verbose: report the RCODE of each response on stdout\n"
+" -h print this usage\n"
+"\n",
+ DEF_SERVER_TO_QUERY, DEF_SERVER_PORT,
+ DEF_MAX_QUERIES_OUTSTANDING, DEF_QUERY_TIMEOUT,
+ DEF_BUFFER_SIZE, DEF_RTTARRAY_SIZE, DEF_RTTARRAY_UNIT);
+}
+
+/*
+ * set_datafile:
+ * Set the datafile to read
+ *
+ * Return -1 on failure
+ * Return a non-negative integer otherwise
+ */
+int
+set_datafile(char *new_file) {
+ char *dfname_tmp;
+
+ if ((new_file == NULL) || (new_file[0] == '\0')) {
+ fprintf(stderr, "Error: null datafile name\n");
+ return (-1);
+ }
+
+ if ((dfname_tmp = malloc(strlen(new_file) + 1)) == NULL) {
+ fprintf(stderr, "Error allocating memory for datafile name: "
+ "%s\n", new_file);
+ return (-1);
+ }
+
+ free(datafile_name);
+ datafile_name = dfname_tmp;
+
+ strcpy(datafile_name, new_file);
+ use_stdin = FALSE;
+
+ return (0);
+}
+
+/*
+ * set_input_stdin:
+ * Set the input to be stdin (instead of a datafile)
+ */
+void
+set_input_stdin(void) {
+ use_stdin = TRUE;
+ free(datafile_name);
+ datafile_name = NULL;
+}
+
+/*
+ * set_server:
+ * Set the server to be queried
+ *
+ * Return -1 on failure
+ * Return a non-negative integer otherwise
+ */
+int
+set_server(char *new_name) {
+ static struct hostent *server_he;
+
+ /* If no change in server name, don't do anything... */
+ if ((server_to_query != NULL) && (new_name != NULL))
+ if (strcmp(new_name, server_to_query) == 0)
+ return (0);
+
+ if ((new_name == NULL) || (new_name[0] == '\0')) {
+ fprintf(stderr, "Error: null server name\n");
+ return (-1);
+ }
+
+ free(server_to_query);
+ server_to_query = NULL;
+
+ if ((server_to_query = malloc(strlen(new_name) + 1)) == NULL) {
+ fprintf(stderr, "Error allocating memory for server name: "
+ "%s\n", new_name);
+ return (-1);
+ }
+
+ strcpy(server_to_query, new_name);
+
+ return (0);
+}
+
+/*
+ * set_server_port:
+ * Set the port on which to contact the server
+ *
+ * Return -1 if port is invalid
+ * Return a non-negative integer otherwise
+ */
+int
+set_server_port(char *new_port) {
+ unsigned int uint_val;
+
+ if ((is_uint(new_port, &uint_val)) != TRUE)
+ return (-1);
+
+ if (uint_val && uint_val > MAX_PORT)
+ return (-1);
+ else {
+ if (server_port != NULL && new_port != NULL &&
+ strcmp(server_port, new_port) == 0)
+ return (0);
+
+ free(server_port);
+ server_port = NULL;
+
+ if ((server_port = malloc(strlen(new_port) + 1)) == NULL) {
+ fprintf(stderr,
+ "Error allocating memory for server port: "
+ "%s\n", new_port);
+ return (-1);
+ }
+
+ strcpy(server_port, new_port);
+
+ return (0);
+ }
+}
+
+int
+set_server_sa(void) {
+ struct addrinfo hints, *res;
+ static struct protoent *proto;
+ int error;
+
+ if (proto == NULL && (proto = getprotobyname("udp")) == NULL) {
+ fprintf(stderr, "Error: getprotobyname call failed");
+ return (-1);
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = proto->p_proto;
+ if ((error = getaddrinfo(server_to_query, server_port,
+ &hints, &res)) != 0) {
+ fprintf(stderr, "Error: getaddrinfo(%s, %s) failed\n",
+ server_to_query, server_port);
+ return (-1);
+ }
+
+ /* replace the server's addrinfo */
+ if (server_ai != NULL)
+ freeaddrinfo(server_ai);
+ server_ai = res;
+ return (0);
+}
+
+/*
+ * is_digit:
+ * Tests if a character is a digit
+ *
+ * Return TRUE if it is
+ * Return FALSE if it is not
+ */
+int
+is_digit(char d) {
+ if (d < '0' || d > '9')
+ return (FALSE);
+ else
+ return (TRUE);
+}
+
+/*
+ * is_uint:
+ * Tests if a string, test_int, is a valid unsigned integer
+ *
+ * Sets *result to be the unsigned integer if it is valid
+ *
+ * Return TRUE if it is
+ * Return FALSE if it is not
+ */
+int
+is_uint(char *test_int, unsigned int *result) {
+ unsigned long int value;
+ char *end;
+
+ if (test_int == NULL)
+ return (FALSE);
+
+ if (is_digit(test_int[0]) == FALSE)
+ return (FALSE);
+
+ value = strtoul(test_int, &end, 10);
+
+ if ((errno == ERANGE) || (*end != '\0') || (value > UINT_MAX))
+ return (FALSE);
+
+ *result = (unsigned int)value;
+ return (TRUE);
+}
+
+/*
+ * set_max_queries:
+ * Set the maximum number of outstanding queries
+ *
+ * Returns -1 on failure
+ * Returns a non-negative integer otherwise
+ */
+int
+set_max_queries(unsigned int new_max) {
+ static unsigned int size_qs = sizeof(struct query_status);
+ struct query_status *temp_stat;
+ unsigned int count;
+
+ if (new_max < 0) {
+ fprintf(stderr, "Unable to change max outstanding queries: "
+ "must be positive and non-zero: %u\n", new_max);
+ return (-1);
+ }
+
+ if (new_max > query_status_allocated) {
+ temp_stat = realloc(status, new_max * size_qs);
+
+ if (temp_stat == NULL) {
+ fprintf(stderr, "Error resizing query_status\n");
+ return (-1);
+ } else {
+ status = temp_stat;
+
+ /*
+ * Be careful to only initialise between above
+ * the previously allocated space. Note that the
+ * allocation may be larger than the current
+ * max_queries_outstanding. We don't want to
+ * "forget" any outstanding queries! We might
+ * still have some above the bounds of the max.
+ */
+ count = query_status_allocated;
+ for (; count < new_max; count++) {
+ status[count].in_use = FALSE;
+ status[count].magic = QUERY_STATUS_MAGIC;
+ status[count].desc = NULL;
+ }
+
+ query_status_allocated = new_max;
+ }
+ }
+
+ max_queries_outstanding = new_max;
+
+ return (0);
+}
+
+/*
+ * parse_args:
+ * Parse program arguments and set configuration options
+ *
+ * Return -1 on failure
+ * Return a non-negative integer otherwise
+ */
+int
+parse_args(int argc, char **argv) {
+ int c;
+ unsigned int uint_arg_val;
+
+ while ((c = getopt(argc, argv,
+ "f:q:t:i:nd:s:p:1l:b:eDcvr:T::u:H:h")) != -1) {
+ switch (c) {
+ case 'f':
+ if (strcmp(optarg, "inet") == 0)
+ family = AF_INET;
+#ifdef AF_INET6
+ else if (strcmp(optarg, "inet6") == 0)
+ family = AF_INET6;
+#endif
+ else if (strcmp(optarg, "any") == 0)
+ family = AF_UNSPEC;
+ else {
+ fprintf(stderr, "Invalid address family: %s\n",
+ optarg);
+ return (-1);
+ }
+ break;
+ case 'q':
+ if (is_uint(optarg, &uint_arg_val) == TRUE) {
+ set_max_queries(uint_arg_val);
+ queriesset = TRUE;
+ } else {
+ fprintf(stderr, "Option requires a positive "
+ "integer value: -%c %s\n",
+ c, optarg);
+ return (-1);
+ }
+ break;
+
+ case 't':
+ if (is_uint(optarg, &uint_arg_val) == TRUE) {
+ query_timeout = uint_arg_val;
+ timeoutset = TRUE;
+ } else {
+ fprintf(stderr, "Option requires a positive "
+ "integer value: -%c %s\n",
+ c, optarg);
+ return (-1);
+ }
+ break;
+
+ case 'n':
+ ignore_config_changes = TRUE;
+ break;
+
+ case 'd':
+ if (set_datafile(optarg) == -1) {
+ fprintf(stderr, "Error setting datafile "
+ "name: %s\n", optarg);
+ return (-1);
+ }
+ break;
+
+ case 's':
+ if (set_server(optarg) == -1) {
+ fprintf(stderr, "Error setting server "
+ "name: %s\n", optarg);
+ return (-1);
+ }
+ serverset = TRUE;
+ break;
+
+ case 'p':
+ if (is_uint(optarg, &uint_arg_val) == TRUE &&
+ uint_arg_val < MAX_PORT)
+ {
+ set_server_port(optarg);
+ portset = TRUE;
+ } else {
+ fprintf(stderr, "Option requires a positive "
+ "integer between 0 and %d: -%c %s\n",
+ MAX_PORT - 1, c, optarg);
+ return (-1);
+ }
+ break;
+
+ case '1':
+ run_only_once = TRUE;
+ break;
+
+ case 'l':
+ if (is_uint(optarg, &uint_arg_val) == TRUE) {
+ use_timelimit = TRUE;
+ run_timelimit = uint_arg_val;
+ } else {
+ fprintf(stderr, "Option requires a positive "
+ "integer: -%c %s\n",
+ c, optarg);
+ return (-1);
+ }
+ break;
+
+ case 'b':
+ if (is_uint(optarg, &uint_arg_val) == TRUE) {
+ socket_bufsize = uint_arg_val;
+ } else {
+ fprintf(stderr, "Option requires a positive "
+ "integer: -%c %s\n",
+ c, optarg);
+ return (-1);
+ }
+ break;
+ case 'e':
+ edns = TRUE;
+ break;
+ case 'D':
+ dnssec = TRUE;
+ edns = TRUE;
+ break;
+ case 'c':
+ countrcodes = TRUE;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'i':
+ if (is_uint(optarg, &uint_arg_val) == TRUE)
+ print_interval = uint_arg_val;
+ else {
+ fprintf(stderr, "Invalid interval: %s\n",
+ optarg);
+ return (-1);
+ }
+ break;
+ case 'r':
+ if (is_uint(optarg, &uint_arg_val) == TRUE)
+ rttarray_size = uint_arg_val;
+ else {
+ fprintf(stderr, "Invalid RTT array size: %s\n",
+ optarg);
+ return (-1);
+ }
+ break;
+ case 'u':
+ if (is_uint(optarg, &uint_arg_val) == TRUE)
+ rttarray_unit = uint_arg_val;
+ else {
+ fprintf(stderr, "Invalid RTT unit: %s\n",
+ optarg);
+ return (-1);
+ }
+ break;
+ case 'H':
+ rtt_histogram_file = optarg;
+ break;
+ case 'T':
+ if (is_uint(optarg, &uint_arg_val) == TRUE)
+ target_qps = uint_arg_val;
+ else {
+ fprintf(stderr, "Invalid target qps: %s\n",
+ optarg);
+ return (-1);
+ }
+ break;
+ case 'h':
+ return (-1);
+ default:
+ fprintf(stderr, "Invalid option: -%c\n", optopt);
+ return (-1);
+ }
+ }
+
+ if (run_only_once == FALSE && use_timelimit == FALSE)
+ run_only_once = TRUE;
+
+ return (0);
+}
+
+/*
+ * open_datafile:
+ * Open the data file ready for reading
+ *
+ * Return -1 on failure
+ * Return non-negative integer on success
+ */
+int
+open_datafile(void) {
+ if (use_stdin == TRUE) {
+ datafile_ptr = stdin;
+ return (0);
+ } else {
+ if ((datafile_ptr = fopen(datafile_name, "r")) == NULL) {
+ fprintf(stderr, "Error: unable to open datafile: %s\n",
+ datafile_name);
+ return (-1);
+ } else
+ return (0);
+ }
+}
+
+/*
+ * close_datafile:
+ * Close the data file if any is open
+ *
+ * Return -1 on failure
+ * Return non-negative integer on success, including if not needed
+ */
+int
+close_datafile(void) {
+ if ((use_stdin == FALSE) && (datafile_ptr != NULL)) {
+ if (fclose(datafile_ptr) != 0) {
+ fprintf(stderr, "Error: unable to close datafile\n");
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * open_socket:
+ * Open a socket for the queries. When we have an active socket already,
+ * close it and open a new one.
+ *
+ * Return -1 on failure
+ * Return the socket identifier
+ */
+int
+open_socket(void) {
+ int sock;
+ int ret;
+ int bufsize;
+ struct addrinfo hints, *res;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = server_ai->ai_family;
+ hints.ai_socktype = server_ai->ai_socktype;
+ hints.ai_protocol = server_ai->ai_protocol;
+ hints.ai_flags = AI_PASSIVE;
+
+ if ((ret = getaddrinfo(NULL, "0", &hints, &res)) != 0) {
+ fprintf(stderr,
+ "Error: getaddrinfo for bind socket failed: %s\n",
+ gai_strerror(ret));
+ return (-1);
+ }
+
+ if ((sock = socket(res->ai_family, SOCK_DGRAM,
+ res->ai_protocol)) == -1) {
+ fprintf(stderr, "Error: socket call failed");
+ goto fail;
+ }
+
+#if defined(AF_INET6) && defined(IPV6_V6ONLY)
+ if (res->ai_family == AF_INET6) {
+ int on = 1;
+
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ &on, sizeof(on)) == -1) {
+ fprintf(stderr,
+ "Warning: setsockopt(IPV6_V6ONLY) failed\n");
+ }
+ }
+#endif
+
+ if (bind(sock, res->ai_addr, res->ai_addrlen) == -1)
+ fprintf(stderr, "Error: bind call failed");
+
+ freeaddrinfo(res);
+
+ bufsize = 1024 * socket_bufsize;
+
+ ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+ (char *) &bufsize, sizeof(bufsize));
+ if (ret < 0)
+ fprintf(stderr, "Warning: setsockbuf(SO_RCVBUF) failed\n");
+
+ ret = setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
+ (char *) &bufsize, sizeof(bufsize));
+ if (ret < 0)
+ fprintf(stderr, "Warning: setsockbuf(SO_SNDBUF) failed\n");
+
+ return (sock);
+
+ fail:
+ if (res)
+ freeaddrinfo(res);
+ return (-1);
+}
+
+/*
+ * close_socket:
+ * Close the query socket(s)
+ *
+ * Return -1 on failure
+ * Return a non-negative integer otherwise
+ */
+int
+close_socket(void) {
+ if (socket4 != -1) {
+ if (close(socket4) != 0) {
+ fprintf(stderr,
+ "Error: unable to close IPv4 socket\n");
+ return (-1);
+ }
+ }
+
+ if (socket6 != -1) {
+ if (close(socket6) != 0) {
+ fprintf(stderr,
+ "Error: unable to close IPv6 socket\n");
+ return (-1);
+ }
+ }
+
+ query_socket = -1;
+
+ return (0);
+}
+
+/*
+ * change_socket:
+ * Choose an appropriate socket according to the address family of the
+ * current server. Open a new socket if necessary.
+ *
+ * Return -1 on failure
+ * Return the socket identifier
+ */
+int
+change_socket(void) {
+ int s, *sockp;
+
+ switch (server_ai->ai_family) {
+ case AF_INET:
+ sockp = &socket4;
+ break;
+#ifdef AF_INET6
+ case AF_INET6:
+ sockp = &socket6;
+ break;
+#endif
+ default:
+ fprintf(stderr, "unexpected address family: %d\n",
+ server_ai->ai_family);
+ exit(1);
+ }
+
+ if (*sockp == -1) {
+ if ((s = open_socket()) == -1)
+ return (-1);
+ *sockp = s;
+ }
+
+ return (*sockp);
+}
+
+/*
+ * reset_rttarray:
+ * (re)allocate RTT array and zero-clear the whole buffer.
+ * if array is being used, it is freed.
+ * Returns -1 on failure
+ * Returns a non-negative integer otherwise
+ */
+int
+reset_rttarray(int size) {
+ if (rttarray != NULL)
+ free(rttarray);
+ if (rttarray_interval != NULL)
+ free(rttarray_interval);
+
+ rttarray = NULL;
+ rttarray_interval = NULL;
+ rtt_max = -1;
+ rtt_min = -1;
+
+ if (size > 0) {
+ rttarray = malloc(size * sizeof(rttarray[0]));
+ if (rttarray == NULL) {
+ fprintf(stderr,
+ "Error: allocating memory for RTT array\n");
+ return (-1);
+ }
+ memset(rttarray, 0, size * sizeof(rttarray[0]));
+
+ rttarray_interval = malloc(size *
+ sizeof(rttarray_interval[0]));
+ if (rttarray_interval == NULL) {
+ fprintf(stderr,
+ "Error: allocating memory for RTT array\n");
+ return (-1);
+ }
+
+ memset(rttarray_interval, 0,
+ size * sizeof(rttarray_interval[0]));
+ }
+
+ return (0);
+}
+
+/*
+ * set_query_interval:
+ * set the interval of consecutive queries if the target qps are specified.
+ * Returns -1 on failure
+ * Returns a non-negative integer otherwise
+ */
+int
+set_query_interval(unsigned int qps) {
+ if (qps == 0)
+ return (0);
+
+ query_interval = (1.0 / (double)qps);
+
+ return (0);
+}
+
+/*
+ * setup:
+ * Set configuration options from command line arguments
+ * Open datafile ready for reading
+ *
+ * Return -1 on failure
+ * Return non-negative integer on success
+ */
+int
+setup(int argc, char **argv) {
+ set_input_stdin();
+
+ if (set_max_queries(DEF_MAX_QUERIES_OUTSTANDING) == -1) {
+ fprintf(stderr, "%s: Unable to set default max outstanding "
+ "queries\n", argv[0]);
+ return (-1);
+ }
+
+ if (set_server(DEF_SERVER_TO_QUERY) == -1) {
+ fprintf(stderr, "%s: Error setting default server name\n",
+ argv[0]);
+ return (-1);
+ }
+
+ if (set_server_port(DEF_SERVER_PORT) == -1) {
+ fprintf(stderr, "%s: Error setting default server port\n",
+ argv[0]);
+ return (-1);
+ }
+
+ if (parse_args(argc, argv) == -1) {
+ show_usage();
+ return (-1);
+ }
+
+ if (open_datafile() == -1)
+ return (-1);
+
+ if (set_server_sa() == -1)
+ return (-1);
+
+ if ((query_socket = change_socket()) == -1)
+ return (-1);
+
+ if (reset_rttarray(rttarray_size) == -1)
+ return (-1);
+
+ if (set_query_interval(target_qps) == -1)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * set_timenow:
+ * Set a timeval struct to indicate the current time
+ */
+void
+set_timenow(struct timeval *tv) {
+ if (gettimeofday(tv, NULL) == -1) {
+ fprintf(stderr, "Error in gettimeofday(). Using inaccurate "
+ "time() instead\n");
+ tv->tv_sec = time(NULL);
+ tv->tv_usec = 0;
+ }
+}
+
+/*
+ * addtv:
+ * add tv1 and tv2, store the result in tv_result.
+ */
+void
+addtv(struct timeval *tv1, struct timeval *tv2, struct timeval *tv_result) {
+ tv_result->tv_sec = tv1->tv_sec + tv2->tv_sec;
+ tv_result->tv_usec = tv1->tv_usec + tv2->tv_usec;
+ if (tv_result->tv_usec > 1000000) {
+ tv_result->tv_sec++;
+ tv_result->tv_usec -= 1000000;
+ }
+}
+
+/*
+ * difftv:
+ * Find the difference in seconds between two timeval structs.
+ *
+ * Return the difference between tv1 and tv2 in seconds in a double.
+ */
+double
+difftv(struct timeval tv1, struct timeval tv2) {
+ long diff_sec, diff_usec;
+ double diff;
+
+ diff_sec = tv1.tv_sec - tv2.tv_sec;
+ diff_usec = tv1.tv_usec - tv2.tv_usec;
+
+ diff = (double)diff_sec + ((double)diff_usec / 1000000.0);
+
+ return (diff);
+}
+
+/*
+ * timelimit_reached:
+ * Have we reached the time limit (if any)?
+ *
+ * Returns FALSE if there is no time limit or if we have not reached it
+ * Returns TRUE otherwise
+ */
+int
+timelimit_reached(void) {
+ struct timeval time_now;
+
+ set_timenow(&time_now);
+
+ if (use_timelimit == FALSE)
+ return (FALSE);
+
+ if (setup_phase == TRUE) {
+ if (difftv(time_now, time_of_program_start)
+ < (double)(run_timelimit + HARD_TIMEOUT_EXTRA))
+ return (FALSE);
+ else
+ return (TRUE);
+ } else {
+ if (difftv(time_now, time_of_first_query)
+ < (double)run_timelimit)
+ return (FALSE);
+ else
+ return (TRUE);
+ }
+}
+
+/*
+ * keep_sending:
+ * Should we keep sending queries or stop here?
+ *
+ * Return TRUE if we should keep on sending queries
+ * Return FALSE if we should stop
+ *
+ * Side effects:
+ * Rewinds the input and clears reached_end_input if we have reached the
+ * end of the input, but we are meant to run through it multiple times
+ * and have not hit the time limit yet (if any is set).
+ */
+int
+keep_sending(int *reached_end_input) {
+ static int stop = FALSE;
+
+ if (stop == TRUE)
+ return (FALSE);
+
+ if ((*reached_end_input == FALSE) && (timelimit_reached() == FALSE))
+ return (TRUE);
+ else if ((*reached_end_input == TRUE) && (run_only_once == FALSE)
+ && (timelimit_reached() == FALSE)) {
+ rewind(datafile_ptr);
+ *reached_end_input = FALSE;
+ runs_through_file++;
+ return (TRUE);
+ } else {
+ if (*reached_end_input == TRUE)
+ runs_through_file++;
+ set_timenow(&time_of_stop_sending);
+ stop = TRUE;
+ return (FALSE);
+ }
+}
+
+/*
+ * queries_outstanding:
+ * How many queries are outstanding?
+ *
+ * Returns the number of outstanding queries
+ */
+unsigned int
+queries_outstanding(void) {
+ return (num_queries_outstanding);
+}
+
+/*
+ * next_input_line:
+ * Get the next non-comment line from the input file
+ *
+ * Put text in line, up to max of n chars. Skip comment lines.
+ * Skip empty lines.
+ *
+ * Return line length on success
+ * Return 0 if cannot read a non-comment line (EOF or error)
+ */
+int
+next_input_line(char *line, int n) {
+ char *result;
+
+ do {
+ result = fgets(line, n, datafile_ptr);
+ } while ((result != NULL) &&
+ ((line[0] == COMMENT_CHAR) || (line[0] == '\n')));
+
+ if (result == NULL)
+ return (0);
+ else
+ return (strlen(line));
+}
+
+/*
+ * identify_directive:
+ * Gives us a numerical value equivelant for a directive string
+ *
+ * Returns the value for the directive
+ * Returns -1 if not a valid directive
+ */
+int
+identify_directive(char *dir) {
+ static char *directives[] = DIRECTIVES;
+ static int dir_values[] = DIR_VALUES;
+ unsigned int index, num_directives;
+
+ num_directives = sizeof(directives) / sizeof(directives[0]);
+
+ if (num_directives > (sizeof(dir_values) / sizeof(int)))
+ num_directives = sizeof(dir_values) / sizeof(int);
+
+ for (index = 0; index < num_directives; index++) {
+ if (strcmp(dir, directives[index]) == 0)
+ return (dir_values[index]);
+ }
+
+ return (-1);
+}
+
+/*
+ * update_config:
+ * Update configuration options from a line from the input file
+ */
+void
+update_config(char *config_change_desc) {
+ char *directive, *config_value, *trailing_garbage;
+ char conf_copy[MAX_INPUT_LEN + 1];
+ unsigned int uint_val;
+ int directive_number;
+ int check;
+ int old_af;
+
+ if (ignore_config_changes == TRUE) {
+ fprintf(stderr, "Ignoring configuration change: %s",
+ config_change_desc);
+ return;
+ }
+
+ strcpy(conf_copy, config_change_desc);
+
+ ++config_change_desc;
+
+ if (*config_change_desc == '\0') {
+ fprintf(stderr, "Invalid config: No directive present: %s\n",
+ conf_copy);
+ return;
+ }
+
+ if (index(WHITESPACE, *config_change_desc) != NULL) {
+ fprintf(stderr, "Invalid config: Space before directive or "
+ "no directive present: %s\n", conf_copy);
+ return;
+ }
+
+ directive = strtok(config_change_desc, WHITESPACE);
+ config_value = strtok(NULL, WHITESPACE);
+ trailing_garbage = strtok(NULL, WHITESPACE);
+
+ if ((directive_number = identify_directive(directive)) == -1) {
+ fprintf(stderr, "Invalid config: Bad directive: %s\n",
+ conf_copy);
+ return;
+ }
+
+ if (config_value == NULL) {
+ fprintf(stderr, "Invalid config: No value present: %s\n",
+ conf_copy);
+ return;
+ }
+
+ if (trailing_garbage != NULL) {
+ fprintf(stderr, "Config warning: "
+ "trailing garbage: %s\n", conf_copy);
+ }
+
+ switch(directive_number) {
+
+ case V_SERVER:
+ if (serverset && (setup_phase == TRUE)) {
+ fprintf(stderr, "Config change overridden by command "
+ "line: %s\n", directive);
+ return;
+ }
+
+ if (set_server(config_value) == -1) {
+ fprintf(stderr, "Set server error: unable to change "
+ "the server name to '%s'\n", config_value);
+ return;
+ }
+
+ old_af = server_ai->ai_family;
+ if (set_server_sa() == -1) {
+ fprintf(stderr, "Set server error: unable to resolve "
+ "a new server '%s'\n",
+ config_value);
+ return;
+ }
+ if (old_af != server_ai->ai_family) {
+ if ((query_socket = change_socket()) == -1) {
+ /* XXX: this is fatal */
+ fprintf(stderr, "Set server error: "
+ "unable to open a new socket "
+ "for '%s'\n", config_value);
+ exit(1);
+ }
+ }
+
+ break;
+
+ case V_PORT:
+ if (portset && (setup_phase == TRUE)) {
+ fprintf(stderr, "Config change overridden by command "
+ "line: %s\n", directive);
+ return;
+ }
+
+ check = is_uint(config_value, &uint_val);
+
+ if ((check == TRUE) && (uint_val > 0)) {
+ if (set_server_port(config_value) == -1) {
+ fprintf(stderr, "Invalid config: Bad value for"
+ " %s: %s\n", directive, config_value);
+ } else {
+ if (set_server_sa() == -1) {
+ fprintf(stderr,
+ "Failed to set a new port\n");
+ return;
+ }
+ }
+ } else
+ fprintf(stderr, "Invalid config: Bad value for "
+ "%s: %s\n", directive, config_value);
+ break;
+
+ case V_MAXQUERIES:
+ if (queriesset && (setup_phase == TRUE)) {
+ fprintf(stderr, "Config change overridden by command "
+ "line: %s\n", directive);
+ return;
+ }
+
+ check = is_uint(config_value, &uint_val);
+
+ if ((check == TRUE) && (uint_val > 0)) {
+ set_max_queries(uint_val);
+ } else
+ fprintf(stderr, "Invalid config: Bad value for "
+ "%s: %s\n", directive, config_value);
+ break;
+
+ case V_MAXWAIT:
+ if (timeoutset && (setup_phase == TRUE)) {
+ fprintf(stderr, "Config change overridden by command "
+ "line: %s\n", directive);
+ return;
+ }
+
+ check = is_uint(config_value, &uint_val);
+
+ if ((check == TRUE) && (uint_val > 0)) {
+ query_timeout = uint_val;
+ } else
+ fprintf(stderr, "Invalid config: Bad value for "
+ "%s: %s\n", directive, config_value);
+ break;
+
+ default:
+ fprintf(stderr, "Invalid config: Bad directive: %s\n",
+ directive);
+ break;
+ }
+}
+
+/*
+ * parse_query:
+ * Parse a query line from the input file
+ *
+ * Set qname to be the domain to query (up to a max of qnlen chars)
+ * Set qtype to be the type of the query
+ *
+ * Return -1 on failure
+ * Return a non-negative integer otherwise
+ */
+int
+parse_query(char *input, char *qname, int qnlen, int *qtype) {
+ static char *qtype_strings[] = QTYPE_STRINGS;
+ static int qtype_codes[] = QTYPE_CODES;
+ int num_types, index;
+ int found = FALSE;
+ char incopy[MAX_INPUT_LEN + 1];
+ char *domain_str, *type_str;
+
+ num_types = sizeof(qtype_strings) / sizeof(qtype_strings[0]);
+ if (num_types > (sizeof(qtype_codes) / sizeof(int)))
+ num_types = sizeof(qtype_codes) / sizeof(int);
+
+ strcpy(incopy, input);
+
+ domain_str = strtok(incopy, WHITESPACE);
+ type_str = strtok(NULL, WHITESPACE);
+
+ if ((domain_str == NULL) || (type_str == NULL)) {
+ fprintf(stderr, "Invalid query input format: %s\n", input);
+ return (-1);
+ }
+
+ if (strlen(domain_str) > qnlen) {
+ fprintf(stderr, "Query domain too long: %s\n", domain_str);
+ return (-1);
+ }
+
+ for (index = 0; (index < num_types) && (found == FALSE); index++) {
+ if (strcasecmp(type_str, qtype_strings[index]) == 0) {
+ *qtype = qtype_codes[index];
+ found = TRUE;
+ }
+ }
+
+ if (found == FALSE) {
+ fprintf(stderr, "Query type not understood: %s\n", type_str);
+ return (-1);
+ }
+
+ strcpy(qname, domain_str);
+
+ return (0);
+}
+
+/*
+ * dispatch_query:
+ * Send the query packet for the entry
+ *
+ * Return -1 on failure
+ * Return a non-negative integer otherwise
+ */
+int
+dispatch_query(unsigned short int id, char *dom, int qt) {
+ static u_char packet_buffer[PACKETSZ + 1];
+ static socklen_t sockaddrlen = sizeof(struct sockaddr);
+ int buffer_len = PACKETSZ;
+ int bytes_sent;
+ unsigned short int net_id = htons(id);
+ char *id_ptr = (char *)&net_id;
+
+ buffer_len = res_mkquery(QUERY, dom, C_IN, qt, NULL, 0,
+ NULL, packet_buffer, PACKETSZ);
+ if (buffer_len == -1) {
+ fprintf(stderr, "Failed to create query packet: %s %d\n",
+ dom, qt);
+ return (-1);
+ }
+ if (edns) {
+ unsigned char *p;
+ if (buffer_len + EDNSLEN >= PACKETSZ) {
+ fprintf(stderr, "Failed to add OPT to query packet\n");
+ return (-1);
+ }
+ packet_buffer[11] = 1;
+ p = &packet_buffer[buffer_len];
+ *p++ = 0; /* root name */
+ *p++ = 0;
+ *p++ = 41; /* OPT */
+ *p++ = 16;
+ *p++ = 0; /* UDP payload size (4K) */
+ *p++ = 0; /* extended rcode */
+ *p++ = 0; /* version */
+ if (dnssec)
+ *p++ = 0x80; /* upper flag bits - DO set */
+ else
+ *p++ = 0; /* upper flag bits */
+ *p++ = 0; /* lower flag bit */
+ *p++ = 0;
+ *p++ = 0; /* rdlen == 0 */
+ buffer_len += EDNSLEN;
+ }
+
+ packet_buffer[0] = id_ptr[0];
+ packet_buffer[1] = id_ptr[1];
+
+ bytes_sent = sendto(query_socket, packet_buffer, buffer_len, 0,
+ server_ai->ai_addr, server_ai->ai_addrlen);
+ if (bytes_sent == -1) {
+ fprintf(stderr, "Failed to send query packet: %s %d\n",
+ dom, qt);
+ return (-1);
+ }
+
+ if (bytes_sent != buffer_len)
+ fprintf(stderr, "Warning: incomplete packet sent: %s %d\n",
+ dom, qt);
+
+ return (0);
+}
+
+/*
+ * send_query:
+ * Send a query based on a line of input
+ */
+void
+send_query(char *query_desc) {
+ static unsigned short int use_query_id = 0;
+ static int qname_len = MAX_DOMAIN_LEN;
+ static char domain[MAX_DOMAIN_LEN + 1];
+ char serveraddr[NI_MAXHOST];
+ int query_type;
+ unsigned int count;
+
+ use_query_id++;
+
+ if (parse_query(query_desc, domain, qname_len, &query_type) == -1) {
+ fprintf(stderr, "Error parsing query: %s\n", query_desc);
+ return;
+ }
+
+ if (dispatch_query(use_query_id, domain, query_type) == -1) {
+ char *addrstr;
+
+ if (getnameinfo(server_ai->ai_addr, server_ai->ai_addrlen,
+ serveraddr, sizeof(serveraddr), NULL, 0,
+ NI_NUMERICHOST) == 0) {
+ addrstr = serveraddr;
+ } else
+ addrstr = "???"; /* XXX: this should not happen */
+ fprintf(stderr, "Error sending query to %s: %s\n",
+ addrstr, query_desc);
+ return;
+ }
+
+ if (setup_phase == TRUE) {
+ set_timenow(&time_of_first_query);
+ time_of_first_query_sec = (double)time_of_first_query.tv_sec +
+ ((double)time_of_first_query.tv_usec / 1000000.0);
+ setup_phase = FALSE;
+ if (getnameinfo(server_ai->ai_addr, server_ai->ai_addrlen,
+ serveraddr, sizeof(serveraddr), NULL, 0,
+ NI_NUMERICHOST) != 0) {
+ fprintf(stderr, "Error printing server address\n");
+ return;
+ }
+ printf("[Status] Sending queries (beginning with %s)\n",
+ serveraddr);
+ }
+
+ /* Find the first slot in status[] that is not in use */
+ for (count = 0; (status[count].in_use == TRUE)
+ && (count < max_queries_outstanding); count++);
+
+ if (status[count].in_use == TRUE) {
+ fprintf(stderr, "Unexpected error: We have run out of "
+ "status[] space!\n");
+ return;
+ }
+
+ /* Register the query in status[] */
+ status[count].in_use = TRUE;
+ status[count].id = use_query_id;
+ if (verbose)
+ status[count].desc = strdup(query_desc);
+ set_timenow(&status[count].sent_timestamp);
+
+ if (num_queries_sent_interval == 0)
+ set_timenow(&time_of_first_query_interval);
+
+ num_queries_sent++;
+ num_queries_sent_interval++;
+ num_queries_outstanding++;
+}
+
+void
+register_rtt(struct timeval *timestamp) {
+ int i;
+ int oldquery = FALSE;
+ struct timeval now;
+ double rtt;
+
+ set_timenow(&now);
+ rtt = difftv(now, *timestamp);
+
+ if (difftv(*timestamp, time_of_first_query_interval) < 0)
+ oldquery = TRUE;
+
+ if (rtt_max < 0 || rtt_max < rtt)
+ rtt_max = rtt;
+
+ if (rtt_min < 0 || rtt_min > rtt)
+ rtt_min = rtt;
+
+ rtt_total += rtt;
+
+ if (!oldquery) {
+ if (rtt_max_interval < 0 || rtt_max_interval < rtt)
+ rtt_max_interval = rtt;
+
+ if (rtt_min_interval < 0 || rtt_min_interval > rtt)
+ rtt_min_interval = rtt;
+
+ rtt_total_interval += rtt;
+ }
+
+ if (rttarray == NULL)
+ return;
+
+ i = (int)(rtt * (1000000.0 / rttarray_unit));
+ if (i < rttarray_size) {
+ rttarray[i]++;
+ if (!oldquery)
+ rttarray_interval[i]++;
+ } else {
+ fprintf(stderr, "Warning: RTT is out of range: %.6lf\n",
+ rtt);
+ rtt_overflows++;
+ if (!oldquery)
+ rtt_overflows_interval++;
+ }
+}
+
+/*
+ * register_response:
+ * Register receipt of a query
+ *
+ * Removes (sets in_use = FALSE) the record for the given query id in
+ * status[] if any exists.
+ */
+void
+register_response(unsigned short int id, unsigned int rcode) {
+ unsigned int ct = 0;
+ int found = FALSE;
+ struct timeval now;
+ double rtt;
+
+ for (; (ct < query_status_allocated) && (found == FALSE); ct++) {
+ if ((status[ct].in_use == TRUE) && (status[ct].id == id)) {
+ status[ct].in_use = FALSE;
+ num_queries_outstanding--;
+ found = TRUE;
+
+ register_rtt(&status[ct].sent_timestamp);
+
+ if (status[ct].desc) {
+ printf("> %s %s\n", rcode_strings[rcode],
+ status[ct].desc);
+ free(status[ct].desc);
+ }
+ if (countrcodes)
+ rcodecounts[rcode]++;
+ }
+ }
+
+ if (found == FALSE) {
+ if (target_qps > 0) {
+ num_queries_possiblydelayed++;
+ num_queries_possiblydelayed_interval++;
+ } else {
+ fprintf(stderr, "Warning: Received a response with an "
+ "unexpected (maybe timed out) id: %u\n", id);
+ }
+ }
+}
+
+/*
+ * process_single_response:
+ * Receive from the given socket & process an invididual response packet.
+ * Remove it from the list of open queries (status[]) and decrement the
+ * number of outstanding queries if it matches an open query.
+ */
+void
+process_single_response(int sockfd) {
+ struct sockaddr_storage from_addr_ss;
+ struct sockaddr *from_addr;
+ static unsigned char in_buf[MAX_BUFFER_LEN];
+ int numbytes, addr_len, resp_id;
+ int flags;
+
+ memset(&from_addr_ss, 0, sizeof(from_addr_ss));
+ from_addr = (struct sockaddr *)&from_addr_ss;
+ addr_len = sizeof(from_addr_ss);
+
+ if ((numbytes = recvfrom(sockfd, in_buf, MAX_BUFFER_LEN,
+ 0, from_addr, &addr_len)) == -1) {
+ fprintf(stderr, "Error receiving datagram\n");
+ return;
+ }
+
+ resp_id = get_uint16(in_buf);
+ flags = get_uint16(in_buf + 2);
+
+ register_response(resp_id, flags & 0xF);
+}
+
+/*
+ * data_available:
+ * Is there data available on the given file descriptor?
+ *
+ * Return TRUE if there is
+ * Return FALSE otherwise
+ */
+int
+data_available(double wait) {
+ fd_set read_fds;
+ struct timeval tv;
+ int retval;
+ int available = FALSE;
+ int maxfd = -1;
+
+ /* Set list of file descriptors */
+ FD_ZERO(&read_fds);
+ if (socket4 != -1) {
+ FD_SET(socket4, &read_fds);
+ maxfd = socket4;
+ }
+ if (socket6 != -1) {
+ FD_SET(socket6, &read_fds);
+ if (maxfd == -1 || maxfd < socket6)
+ maxfd = socket6;
+ }
+
+ if ((wait > 0.0) && (wait < (double)LONG_MAX)) {
+ tv.tv_sec = (long)floor(wait);
+ tv.tv_usec = (long)(1000000.0 * (wait - floor(wait)));
+ } else {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
+
+ retval = select(maxfd + 1, &read_fds, NULL, NULL, &tv);
+
+ if (socket4 != -1 && FD_ISSET(socket4, &read_fds)) {
+ available = TRUE;
+ process_single_response(socket4);
+ }
+ if (socket6 != -1 && FD_ISSET(socket6, &read_fds)) {
+ available = TRUE;
+ process_single_response(socket6);
+ }
+
+ return (available);
+}
+
+/*
+ * process_responses:
+ * Go through any/all received responses and remove them from the list of
+ * open queries (set in_use = FALSE for their entry in status[]), also
+ * decrementing the number of outstanding queries.
+ */
+void
+process_responses(int adjust_rate) {
+ double wait;
+ struct timeval now, waituntil;
+ double first_packet_wait = RESPONSE_BLOCKING_WAIT_TIME;
+ unsigned int outstanding = queries_outstanding();
+
+ if (adjust_rate == TRUE) {
+ double u;
+
+ u = time_of_first_query_sec +
+ query_interval * num_queries_sent;
+ waituntil.tv_sec = (long)floor(u);
+ waituntil.tv_usec = (long)(1000000.0 * (u - waituntil.tv_sec));
+
+ /*
+ * Wait until a response arrives or the specified limit is
+ * reached.
+ */
+ while (1) {
+ set_timenow(&now);
+ wait = difftv(waituntil, now);
+ if (wait <= 0)
+ wait = 0.0;
+ if (data_available(wait) != TRUE)
+ break;
+
+ /*
+ * We have reached the limit. Read as many responses
+ * as possible without waiting, and exit.
+ */
+ if (wait == 0) {
+ while (data_available(0.0) == TRUE)
+ ;
+ break;
+ }
+ }
+ } else {
+ /*
+ * Don't block waiting for packets at all if we aren't
+ * looking for any responses or if we are now able to send new
+ * queries.
+ */
+ if ((outstanding == 0) ||
+ (outstanding < max_queries_outstanding)) {
+ first_packet_wait = 0.0;
+ }
+
+ if (data_available(first_packet_wait) == TRUE) {
+ while (data_available(0.0) == TRUE)
+ ;
+ }
+ }
+}
+
+/*
+ * retire_old_queries:
+ * Go through the list of open queries (status[]) and remove any queries
+ * (i.e. set in_use = FALSE) which are older than the timeout, decrementing
+ * the number of queries outstanding for each one removed.
+ */
+void
+retire_old_queries(int sending) {
+ unsigned int count = 0;
+ struct timeval curr_time;
+ double timeout = query_timeout;
+ int timeout_reduced = FALSE;
+
+ /*
+ * If we have target qps and would not be able to send any packets
+ * due to buffer full, check whether we are behind the schedule.
+ * If we are, purge some queries more aggressively.
+ */
+ if (target_qps > 0 && sending == TRUE && count == 0 &&
+ queries_outstanding() == max_queries_outstanding) {
+ struct timeval next, now;
+ double n;
+
+ n = time_of_first_query_sec +
+ query_interval * num_queries_sent;
+ next.tv_sec = (long)floor(n);
+ next.tv_usec = (long)(1000000.0 * (n - next.tv_sec));
+
+ set_timenow(&now);
+ if (difftv(next, now) <= 0) {
+ timeout_reduced = TRUE;
+ timeout = 0.001; /* XXX: ad-hoc value */
+ }
+ }
+
+ set_timenow(&curr_time);
+
+ for (; count < query_status_allocated; count++) {
+
+ if ((status[count].in_use == TRUE)
+ && (difftv(curr_time, status[count].sent_timestamp)
+ >= (double)timeout)) {
+
+ status[count].in_use = FALSE;
+ num_queries_outstanding--;
+ num_queries_timed_out++;
+ num_queries_timed_out_interval++;
+
+ if (timeout_reduced == FALSE) {
+ if (status[count].desc) {
+ printf("> T %s\n", status[count].desc);
+ free(status[count].desc);
+ } else {
+ printf("[Timeout] Query timed out: "
+ "msg id %u\n",
+ status[count].id);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * print_histogram
+ * Print RTT histogram to the specified file in the gnuplot format
+ */
+void
+print_histogram(unsigned int total) {
+ int i;
+ double ratio;
+ FILE *fp;
+
+ if (rtt_histogram_file == NULL || rttarray == NULL)
+ return;
+
+ fp = fopen((const char *)rtt_histogram_file, "w+");
+ if (fp == NULL) {
+ fprintf(stderr, "Error opening RTT histogram file: %s\n",
+ rtt_histogram_file);
+ return;
+ }
+
+ for (i = 0; i < rttarray_size; i++) {
+ ratio = ((double)rttarray[i] / (double)total) * 100;
+ fprintf(fp, "%.6lf %.3lf\n",
+ (double)(i * rttarray_unit) +
+ (double)rttarray_unit / 2,
+ ratio);
+ }
+
+ (void)fclose(fp);
+}
+
+/*
+ * print_statistics:
+ * Print out statistics based on the results of the test
+ */
+void
+print_statistics(int intermediate, unsigned int sent, unsigned int timed_out,
+ unsigned int possibly_delayed,
+ struct timeval *first_query,
+ struct timeval *program_start,
+ struct timeval *end_perf, struct timeval *end_query,
+ double rmax, double rmin, double rtotal,
+ unsigned int roverflows, unsigned int *rarray)
+{
+ unsigned int num_queries_completed;
+ double per_lost, per_completed, per_lost2, per_completed2;
+ double run_time, queries_per_sec, queries_per_sec2;
+ double queries_per_sec_total;
+ double rtt_average, rtt_stddev;
+ struct timeval start_time;
+
+ num_queries_completed = sent - timed_out;
+
+ if (num_queries_completed == 0) {
+ per_lost = 0.0;
+ per_completed = 0.0;
+
+ per_lost2 = 0.0;
+ per_completed2 = 0.0;
+ } else {
+ per_lost = (100.0 * (double)timed_out) / (double)sent;
+ per_completed = 100.0 - per_lost;
+
+ per_lost2 = (100.0 * (double)(timed_out - possibly_delayed))
+ / (double)sent;
+ per_completed2 = 100 - per_lost2;
+ }
+
+ if (sent == 0) {
+ start_time.tv_sec = program_start->tv_sec;
+ start_time.tv_usec = program_start->tv_usec;
+ run_time = 0.0;
+ queries_per_sec = 0.0;
+ queries_per_sec2 = 0.0;
+ queries_per_sec_total = 0.0;
+ } else {
+ start_time.tv_sec = first_query->tv_sec;
+ start_time.tv_usec = first_query->tv_usec;
+ run_time = difftv(*end_perf, *first_query);
+ queries_per_sec = (double)num_queries_completed / run_time;
+ queries_per_sec2 = (double)(num_queries_completed +
+ possibly_delayed) / run_time;
+
+ queries_per_sec_total = (double)sent /
+ difftv(*end_query, *first_query);
+ }
+
+ if (num_queries_completed > 0) {
+ int i;
+ double sum = 0;
+
+ rtt_average = rtt_total / (double)num_queries_completed;
+ for (i = 0; i < rttarray_size; i++) {
+ if (rarray[i] != 0) {
+ double mean, diff;
+
+ mean = (double)(i * rttarray_unit) +
+ (double)rttarray_unit / 2;
+ diff = rtt_average - (mean / 1000000.0);
+ sum += (diff * diff) * rarray[i];
+ }
+ }
+ rtt_stddev = sqrt(sum / (double)num_queries_completed);
+ } else {
+ rtt_average = 0.0;
+ rtt_stddev = 0.0;
+ }
+
+ printf("\n");
+
+ printf("%sStatistics:\n", intermediate ? "Intermediate " : "");
+
+ printf("\n");
+
+ if (!intermediate) {
+ printf(" Parse input file: %s\n",
+ ((run_only_once == TRUE) ? "once" : "multiple times"));
+ if (use_timelimit)
+ printf(" Run time limit: %u seconds\n",
+ run_timelimit);
+ if (run_only_once == FALSE)
+ printf(" Ran through file: %u times\n",
+ runs_through_file);
+ else
+ printf(" Ended due to: reaching %s\n",
+ ((runs_through_file == 0) ? "time limit"
+ : "end of file"));
+
+ printf("\n");
+ }
+
+ printf(" Queries sent: %u queries\n", sent);
+ printf(" Queries completed: %u queries\n", num_queries_completed);
+ printf(" Queries lost: %u queries\n", timed_out);
+ printf(" Queries delayed(?): %u queries\n", possibly_delayed);
+
+ printf("\n");
+
+ printf(" RTT max: %3.6lf sec\n", rmax);
+ printf(" RTT min: %3.6lf sec\n", rmin);
+ printf(" RTT average: %3.6lf sec\n", rtt_average);
+ printf(" RTT std deviation: %3.6lf sec\n", rtt_stddev);
+ printf(" RTT out of range: %u queries\n", roverflows);
+
+ if (!intermediate) /* XXX should we print this case also? */
+ print_histogram(num_queries_completed);
+
+ printf("\n");
+
+ if (countrcodes) {
+ unsigned int i;
+
+ for (i = 0; i < 16; i++) {
+ if (rcodecounts[i] == 0)
+ continue;
+ printf(" Returned %8s: %u queries\n",
+ rcode_strings[i], rcodecounts[i]);
+ }
+ printf("\n");
+ }
+
+ printf(" Percentage completed: %6.2lf%%\n", per_completed);
+ if (possibly_delayed > 0)
+ printf(" (w/ delayed qrys): %6.2lf%%\n", per_completed2);
+ printf(" Percentage lost: %6.2lf%%\n", per_lost);
+ if (possibly_delayed > 0)
+ printf(" (w/o delayed qrys): %6.2lf%%\n", per_lost2);
+
+ printf("\n");
+
+ printf(" Started at: %s",
+ ctime((const time_t *)&start_time.tv_sec));
+ printf(" Finished at: %s",
+ ctime((const time_t *)&end_perf->tv_sec));
+ printf(" Ran for: %.6lf seconds\n", run_time);
+
+ printf("\n");
+
+ printf(" Queries per second: %.6lf qps\n", queries_per_sec);
+ if (possibly_delayed > 0) {
+ printf(" (w/ delayed qrys): %.6lf qps\n",
+ queries_per_sec2);
+ }
+ if (target_qps > 0) {
+ printf(" Total QPS/target: %.6lf/%d qps\n",
+ queries_per_sec_total, target_qps);
+ }
+
+ printf("\n");
+}
+
+void
+print_interval_statistics() {
+ struct timeval time_now;
+
+ if (use_timelimit == FALSE)
+ return;
+
+ if (setup_phase == TRUE)
+ return;
+
+ if (print_interval == 0)
+ return;
+
+ if (timelimit_reached() == TRUE)
+ return;
+
+ set_timenow(&time_now);
+ if (difftv(time_now, time_of_first_query_interval)
+ <= (double)print_interval)
+ return;
+
+ /* Don't count currently outstanding queries */
+ num_queries_sent_interval -= queries_outstanding();
+ print_statistics(TRUE, num_queries_sent_interval,
+ num_queries_timed_out_interval,
+ num_queries_possiblydelayed_interval,
+ &time_of_first_query_interval,
+ &time_of_first_query_interval, &time_now, &time_now,
+ rtt_max_interval, rtt_min_interval,
+ rtt_total_interval, rtt_overflows_interval,
+ rttarray_interval);
+
+ /* Reset intermediate counters */
+ num_queries_sent_interval = 0;
+ num_queries_timed_out_interval = 0;
+ num_queries_possiblydelayed_interval = 0;
+ rtt_max_interval = -1;
+ rtt_min_interval = -1;
+ rtt_total_interval = 0.0;
+ rtt_overflows_interval = 0;
+ if (rttarray_interval != NULL) {
+ memset(rttarray_interval, 0,
+ sizeof(rttarray_interval[0]) * rttarray_size);
+ }
+}
+
+/*
+ * queryperf Program Mainline
+ */
+int
+main(int argc, char **argv) {
+ int adjust_rate;
+ int sending = FALSE;
+ int got_eof = FALSE;
+ int input_length = MAX_INPUT_LEN;
+ char input_line[MAX_INPUT_LEN + 1];
+
+ set_timenow(&time_of_program_start);
+ time_of_first_query.tv_sec = 0;
+ time_of_first_query.tv_usec = 0;
+ time_of_first_query_interval.tv_sec = 0;
+ time_of_first_query_interval.tv_usec = 0;
+ time_of_end_of_run.tv_sec = 0;
+ time_of_end_of_run.tv_usec = 0;
+
+ input_line[0] = '\0';
+
+ show_startup_info();
+
+ if (setup(argc, argv) == -1)
+ return (-1);
+
+ printf("[Status] Processing input data\n");
+
+ while ((sending = keep_sending(&got_eof)) == TRUE ||
+ queries_outstanding() > 0) {
+ print_interval_statistics();
+ adjust_rate = FALSE;
+
+ while ((sending = keep_sending(&got_eof)) == TRUE &&
+ queries_outstanding() < max_queries_outstanding) {
+ int len = next_input_line(input_line, input_length);
+ if (len == 0) {
+ got_eof = TRUE;
+ } else {
+ /* Zap the trailing newline */
+ if (input_line[len - 1] == '\n')
+ input_line[len - 1] = '\0';
+
+ /*
+ * TODO: Should test if we got a whole line
+ * and flush to the next \n in input if not
+ * here... Add this later. Only do the next
+ * few lines if we got a whole line, else
+ * print a warning. Alternative: Make the
+ * max line size really big. BAD! :)
+ */
+
+ if (input_line[0] == CONFIG_CHAR)
+ update_config(input_line);
+ else {
+ send_query(input_line);
+ if (target_qps > 0 &&
+ (num_queries_sent %
+ max_queries_outstanding) == 0) {
+ adjust_rate = TRUE;
+ }
+ }
+ }
+ }
+
+ process_responses(adjust_rate);
+ retire_old_queries(sending);
+ }
+
+ set_timenow(&time_of_end_of_run);
+
+ printf("[Status] Testing complete\n");
+
+ close_socket();
+ close_datafile();
+
+ print_statistics(FALSE, num_queries_sent, num_queries_timed_out,
+ num_queries_possiblydelayed,
+ &time_of_first_query, &time_of_program_start,
+ &time_of_end_of_run, &time_of_stop_sending,
+ rtt_max, rtt_min, rtt_total, rtt_overflows, rttarray);
+
+ return (0);
+}
diff --git a/contrib/queryperf/utils/gen-data-queryperf.py b/contrib/queryperf/utils/gen-data-queryperf.py
new file mode 100644
index 0000000..52074b7
--- /dev/null
+++ b/contrib/queryperf/utils/gen-data-queryperf.py
@@ -0,0 +1,113 @@
+#!/usr/bin/python
+
+#
+# $Id: gen-data-queryperf.py,v 1.2 2008/06/13 18:17:08 jinmei Exp $
+#
+# Contributed by Stephane Bortzmeyer <bortzmeyer@nic.fr>
+#
+# "A small tool which may be useful with contrib/queryperf. This script
+# can generate files of queries, both with random names (to test the
+# behaviour with NXdomain) and with domains from a real zone file."
+#
+
+import sys
+import getopt
+import random
+import re
+
+ldh = []
+# Letters
+for i in range(97, 122):
+ ldh.append(chr(i))
+# Digits
+for i in range(48, 57):
+ ldh.append(chr(i))
+# Hyphen
+ldh.append('-')
+
+maxsize=10
+tld='org'
+num=4
+percent_random = 0.3
+gen = None
+zone_file = None
+domains = {}
+domain_ns = r'^([a-z0-9-\.]+)((\s+\d+)?(\s+IN)?|(\s+IN)(\s+\d+)?)\s+NS'
+domain_ns_re = re.compile(domain_ns, re.IGNORECASE)
+
+def remove_tld(label, tld):
+ if label.endswith('.' + tld + '.'):
+ return label[0:-(1+ len(tld) + 1)]
+ else:
+ return label
+
+def gen_random_label():
+ label = ""
+ for i in range(gen.randint(1, maxsize)):
+ label = label + gen.choice(ldh)
+ return label
+
+def make_domain(label):
+ return "www." + label + "." + tld + " A"
+
+def usage():
+ sys.stdout.write("Usage: " + sys.argv[0] + " [-n number] " + \
+ "[-p percent-random] [-t TLD]\n")
+ sys.stdout.write(" [-m MAXSIZE] [-f zone-file]\n")
+
+try:
+ optlist, args = getopt.getopt(sys.argv[1:], "hp:f:n:t:m:",
+ ["help", "percentrandom=", "zonefile=",
+ "number=", "tld=",
+ "maxsize="])
+ for option, value in optlist:
+ if option == "--help" or option == "-h":
+ usage()
+ sys.exit(0)
+ elif option == "--number" or option == "-n":
+ num = int(value)
+ elif option == "--maxsize" or option == "-m":
+ maxsize = int(value)
+ elif option == "--percentrandom" or option == "-p":
+ percent_random = float(value)
+ elif option == "--tld" or option == "-t":
+ tld = str(value)
+ elif option == "--zonefile" or option == "-f":
+ zone_file = str(value)
+ else:
+ error("Unknown option " + option)
+except getopt.error, reason:
+ sys.stderr.write(sys.argv[0] + ": " + str(reason) + "\n")
+ usage()
+ sys.exit(1)
+
+if len(args) <> 0:
+ usage()
+ sys.exit(1)
+
+gen = random.Random()
+if zone_file:
+ file = open(zone_file)
+ line = file.readline()
+ while line:
+ domain_line = domain_ns_re.match(line)
+ if domain_line:
+ print domain_line.group(1)
+ domain = remove_tld(domain_line.group(1), tld)
+ domains[domain] = 1
+ line = file.readline()
+ file.close()
+if zone_file:
+ domains = domains.keys()
+ if len(domains) == 0:
+ sys.stderr.write("No domains found in '%s'\n" % zone_file)
+ sys.exit(1)
+for i in range(num):
+ if zone_file:
+ if gen.random() < percent_random:
+ sys.stdout.write(make_domain(gen_random_label()))
+ else:
+ sys.stdout.write(make_domain(gen.choice(domains)))
+ else:
+ sys.stdout.write(make_domain(gen_random_label()))
+ sys.stdout.write("\n")
diff --git a/contrib/sdb/bdb/README b/contrib/sdb/bdb/README
new file mode 100644
index 0000000..d2acf4e
--- /dev/null
+++ b/contrib/sdb/bdb/README
@@ -0,0 +1,37 @@
+(Message trash:37216)
+
+Date: Wed, 15 May 2002 20:44:45 +0100
+To: <bind-workers@isc.org>
+From: Nuno Miguel Rodrigues <nmr@co.sapo.pt>
+Subject: Berkeley DB BIND9 SDB
+
+Replied: Thu, 16 May 2002 11:47:35 +1000
+Replied: Nuno Miguel Rodrigues <nmr@co.sapo.pt>
+Return-Path: <bind-workers-bounce@isc.org>
+X-X-Sender: <nmr@angelina.sl.pt>
+MIME-Version: 1.0
+X-ecartis-version: Ecartis v1.0.0
+Sender: bind-workers-bounce@isc.org
+Errors-To: bind-workers-bounce@isc.org
+X-original-sender: nmr@co.sapo.pt
+Precedence: bulk
+X-list: bind-workers
+Status:
+
+
+
+Hello all,
+
+I'm making available a BIND9 SDB using Berkeley DB 4.0.
+
+You can get it at http://www.dhis.org/~nmr/bind9_berkeleydb_sdb-1.0.tar
+
+Thanks,
+
+
+--
+Nuno M. Rodrigues <nmr@co.sapo.pt>
+
+
+
+
diff --git a/contrib/sdb/bdb/bdb.c b/contrib/sdb/bdb/bdb.c
new file mode 100644
index 0000000..10f5811
--- /dev/null
+++ b/contrib/sdb/bdb/bdb.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2002 Nuno M. Rodrigues.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NUNO M. RODRIGUES
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bdb.c,v 1.1 2002/05/16 04:25:22 marka Exp $ */
+
+/*
+ * BIND 9.1.x simple database driver
+ * implementation, using Berkeley DB.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <isc/file.h>
+#include <isc/log.h>
+#include <isc/lib.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/msgcat.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/sdb.h>
+#include <dns/log.h>
+#include <dns/lib.h>
+#include <dns/ttl.h>
+
+#include <named/bdb.h>
+#include <named/globals.h>
+#include <named/config.h>
+
+#include <db.h>
+
+#define DRIVERNAME "bdb"
+
+static dns_sdbimplementation_t *bdb_imp;
+
+static isc_result_t
+bdb_create(const char *zone, int argc, char **argv,
+ void *unused, void **dbdata)
+{
+ int ret;
+
+ UNUSED(zone);
+ UNUSED(unused);
+
+ if (argc < 1)
+ return ISC_R_FAILURE; /* database path must be given */
+
+ if (db_create((DB **)dbdata, NULL, 0) != 0) {
+ /*
+ * XXX Should use dns_msgcat et al
+ * but seems to be unavailable.
+ */
+ isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_SDB, ISC_LOG_CRITICAL, isc_msgcat,
+ ISC_MSGSET_GENERAL, ISC_MSG_FATALERROR,
+ "db_create");
+ return ISC_R_FAILURE;
+ }
+
+ if (isc_file_exists(*argv) != ISC_TRUE) {
+ isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_SDB, ISC_LOG_CRITICAL, isc_msgcat,
+ ISC_MSGSET_GENERAL, ISC_MSG_FATALERROR,
+ "isc_file_exists: %s", *argv);
+ return ISC_R_FAILURE;
+ }
+
+ if ((ret = (*(DB **)dbdata)->open(*(DB **)dbdata, *argv, NULL, DB_HASH,
+ DB_RDONLY, 0)) != 0) {
+ isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_SDB, ISC_LOG_CRITICAL,
+ isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FATALERROR, "DB->open: %s",
+ db_strerror(ret));
+ return ISC_R_FAILURE;
+ }
+ return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+bdb_lookup(const char *zone, const char *name, void *dbdata,
+ dns_sdblookup_t *l)
+{
+ int ret;
+ char *type, *rdata;
+ dns_ttl_t ttl;
+ isc_consttextregion_t ttltext;
+ DBC *c;
+ DBT key, data;
+
+ UNUSED(zone);
+
+ if ((ret = ((DB *)dbdata)->cursor((DB *)dbdata, NULL, &c, 0)) != 0) {
+ isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "DB->cursor: %s",
+ db_strerror(ret));
+ return ISC_R_FAILURE;
+ }
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+
+ (const char *)key.data = name;
+ key.size = strlen(name);
+
+ ret = c->c_get(c, &key, &data, DB_SET);
+ while (ret == 0) {
+ ((char *)key.data)[key.size] = 0;
+ ((char *)data.data)[data.size] = 0;
+ ttltext.base = strtok((char *)data.data, " ");
+ ttltext.length = strlen(ttltext.base);
+ dns_ttl_fromtext((isc_textregion_t *)&ttltext, &ttl);
+ type = strtok(NULL, " ");
+ rdata = type + strlen(type) + 1;
+
+ if (dns_sdb_putrr(l, type, ttl, rdata) != ISC_R_SUCCESS) {
+ isc_log_iwrite(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "dns_sdb_putrr");
+ return ISC_R_FAILURE;
+ }
+ ret = c->c_get(c, &key, &data, DB_NEXT_DUP);
+ }
+
+ c->c_close(c);
+ return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+bdb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *n)
+{
+ int ret;
+ char *type, *rdata;
+ dns_ttl_t ttl;
+ isc_consttextregion_t ttltext;
+ DBC *c;
+ DBT key, data;
+
+ UNUSED(zone);
+
+ if ((ret = ((DB *)dbdata)->cursor((DB *)dbdata, NULL, &c, 0)) != 0) {
+ isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "DB->cursor: %s",
+ db_strerror(ret));
+ return ISC_R_FAILURE;
+ }
+
+ memset(&key, 0, sizeof(DBT));
+ memset(&data, 0, sizeof(DBT));
+
+ while (c->c_get(c, &key, &data, DB_NEXT) == 0) {
+ ((char *)key.data)[key.size] = 0;
+ ((char *)data.data)[data.size] = 0;
+ ttltext.base = strtok((char *)data.data, " ");
+ ttltext.length = strlen(ttltext.base);
+ dns_ttl_fromtext((isc_textregion_t *)&ttltext, &ttl);
+ type = strtok(NULL, " ");
+ rdata = type + strlen(type) + 1;
+
+ if (dns_sdb_putnamedrr(n, key.data, type, ttl, rdata) !=
+ ISC_R_SUCCESS) {
+ isc_log_iwrite(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "dns_sdb_putnamedrr");
+ return ISC_R_FAILURE;
+ }
+
+ }
+
+ c->c_close(c);
+ return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+bdb_destroy(const char *zone, void *unused, void **dbdata)
+{
+
+ UNUSED(zone);
+ UNUSED(unused);
+
+ (*(DB **)dbdata)->close(*(DB **)dbdata, 0);
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t
+bdb_init(void)
+{
+ static dns_sdbmethods_t bdb_methods = {
+ bdb_lookup,
+ NULL,
+ bdb_allnodes,
+ bdb_create,
+ bdb_destroy
+ };
+
+ return dns_sdb_register(DRIVERNAME, &bdb_methods, NULL, 0, ns_g_mctx,
+ &bdb_imp);
+}
+
+void
+bdb_clear(void)
+{
+
+ if (bdb_imp != NULL)
+ dns_sdb_unregister(&bdb_imp);
+}
diff --git a/contrib/sdb/bdb/bdb.h b/contrib/sdb/bdb/bdb.h
new file mode 100644
index 0000000..7ab56b4
--- /dev/null
+++ b/contrib/sdb/bdb/bdb.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2002 Nuno M. Rodrigues.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NUNO M. RODRIGUES
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: bdb.h,v 1.1 2002/05/16 04:25:22 marka Exp $ */
+
+#ifndef BDB_H
+#define BDB_H 1
+
+#include <isc/types.h>
+
+/*
+ * Prototypes.
+ */
+isc_result_t bdb_init(void);
+void bdb_clear(void);
+
+#endif /* BDB_H */
diff --git a/contrib/sdb/bdb/zone2bdb.c b/contrib/sdb/bdb/zone2bdb.c
new file mode 100644
index 0000000..36326af
--- /dev/null
+++ b/contrib/sdb/bdb/zone2bdb.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2002 Nuno M. Rodrigues.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NUNO M. RODRIGUES
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: zone2bdb.c,v 1.2 2008/09/24 02:46:21 marka Exp $ */
+
+#include <stdio.h>
+
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/ttl.h>
+#include <dns/types.h>
+
+#include <db.h>
+
+#define MAX_RDATATEXT 63 + 4 + 65535 + 2 /* ttl + type + rdata + sep */
+
+/*
+ * Returns a valid 'DB' handle.
+ *
+ * Requires:
+ * 'file' is a valid non-existant path.
+ */
+DB *
+bdb_init(const char *file)
+{
+ DB *db;
+
+ REQUIRE(db_create(&db, NULL, 0) == 0);
+ REQUIRE(db->set_flags(db, DB_DUP) == 0);
+ REQUIRE(db->open(db, file, NULL, DB_HASH, DB_CREATE | DB_EXCL, 0) == 0);
+
+ return db;
+}
+
+/*
+ * Puts resource record data on 'db'.
+ */
+isc_result_t
+bdb_putrdata(DB *db, dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
+{
+ static DBT key, data;
+ isc_buffer_t keybuf, databuf;
+ char nametext[DNS_NAME_MAXTEXT];
+ char rdatatext[MAX_RDATATEXT];
+
+ isc_buffer_init(&keybuf, nametext, DNS_NAME_MAXTEXT);
+
+ dns_name_totext(name, ISC_TRUE, &keybuf);
+
+ key.data = isc_buffer_base(&keybuf);
+ key.size = isc_buffer_usedlength(&keybuf);
+
+ isc_buffer_init(&databuf, rdatatext, MAX_RDATATEXT);
+
+ dns_ttl_totext(ttl, ISC_FALSE, &databuf);
+ *(char *)isc_buffer_used(&databuf) = ' ';
+ isc_buffer_add(&databuf, 1);
+
+ dns_rdatatype_totext(rdata->type, &databuf); /* XXX private data */
+ *(char *)isc_buffer_used(&databuf) = ' ';
+ isc_buffer_add(&databuf, 1);
+
+ dns_rdata_totext(rdata, NULL, &databuf);
+
+ data.data = isc_buffer_base(&databuf);
+ data.size = isc_buffer_usedlength(&databuf);
+
+ REQUIRE(db->put(db, NULL, &key, &data, 0) == 0);
+
+ return ISC_R_SUCCESS;
+}
+
+isc_result_t
+bdb_destroy(DB *db)
+{
+
+ return (db->close(db, 0) == 0) ? ISC_R_SUCCESS : ISC_R_FAILURE;
+}
+
+void
+usage(const char *prog)
+{
+
+ fprintf(stderr, "Usage: %s <origin> <zonefile> <db>\n", prog);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ isc_mem_t *mctx = NULL;
+ isc_buffer_t b;
+ int n;
+ dns_fixedname_t origin, name;
+ dns_db_t *db = NULL;
+ dns_dbiterator_t *dbiter = NULL;
+ isc_result_t res;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdatasetiter_t *rdatasetiter = NULL;
+ dns_rdata_t rdata;
+ DB *bdb;
+
+ if (argc != 4) usage(*argv);
+
+ REQUIRE(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+
+ n = strlen(argv[1]);
+ isc_buffer_init(&b, argv[1], n);
+ isc_buffer_add(&b, n);
+
+ dns_fixedname_init(&origin);
+
+ REQUIRE(dns_name_fromtext(dns_fixedname_name(&origin), &b, dns_rootname,
+ ISC_FALSE, NULL) == ISC_R_SUCCESS);
+ REQUIRE(dns_db_create(mctx, "rbt", dns_fixedname_name(&origin),
+ dns_dbtype_zone, dns_rdataclass_in, 0, NULL,
+ &db) == ISC_R_SUCCESS);
+
+ REQUIRE(dns_db_load(db, argv[2]) == ISC_R_SUCCESS);
+
+ REQUIRE(dns_db_createiterator(db, 0, &dbiter) == ISC_R_SUCCESS);
+
+ dns_rdataset_init(&rdataset);
+ dns_rdata_init(&rdata);
+ dns_fixedname_init(&name);
+ bdb = bdb_init(argv[3]);
+
+ for (res = dns_dbiterator_first(dbiter); res == ISC_R_SUCCESS;
+ res = dns_dbiterator_next(dbiter)) {
+ dns_dbiterator_current(dbiter, &node, dns_fixedname_name(&name));
+ REQUIRE(dns_db_allrdatasets(db, node, NULL, 0, &rdatasetiter)
+ == ISC_R_SUCCESS);
+
+ for (res = dns_rdatasetiter_first(rdatasetiter);
+ res == ISC_R_SUCCESS;
+ res = dns_rdatasetiter_next(rdatasetiter)) {
+ dns_rdatasetiter_current(rdatasetiter, &rdataset);
+
+ res = dns_rdataset_first(&rdataset);
+ while (res == ISC_R_SUCCESS) {
+ dns_rdataset_current(&rdataset, &rdata);
+ REQUIRE(bdb_putrdata(bdb,
+ dns_fixedname_name(&name),
+ rdataset.ttl, &rdata)
+ == ISC_R_SUCCESS);
+
+ dns_rdata_reset(&rdata);
+ res = dns_rdataset_next(&rdataset);
+ }
+
+ dns_rdataset_disassociate(&rdataset);
+ }
+ dns_rdatasetiter_destroy(&rdatasetiter);
+ dns_db_detachnode(db, &node);
+ }
+ dns_dbiterator_destroy(&dbiter);
+
+ REQUIRE(bdb_destroy(bdb) == ISC_R_SUCCESS);
+
+ return 0;
+}
diff --git a/contrib/sdb/dir/dirdb.c b/contrib/sdb/dir/dirdb.c
new file mode 100644
index 0000000..ca82cf8
--- /dev/null
+++ b/contrib/sdb/dir/dirdb.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2004, 2007 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: dirdb.c,v 1.12 2007/06/19 23:47:07 tbox Exp $ */
+
+/*
+ * A simple database driver that returns basic information about
+ * files and directories in the Unix file system as DNS data.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/sdb.h>
+
+#include <named/globals.h>
+
+#include "dirdb.h"
+
+static dns_sdbimplementation_t *dirdb = NULL;
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) return (result); \
+ } while (0)
+
+#define CHECKN(op) \
+ do { n = (op); \
+ if (n < 0) return (ISC_R_FAILURE); \
+ } while (0)
+
+
+/*
+ * This database operates on relative names.
+ *
+ * Any name will be interpreted as a pathname offset from the directory
+ * specified in the configuration file.
+ */
+static isc_result_t
+dirdb_lookup(const char *zone, const char *name, void *dbdata,
+ dns_sdblookup_t *lookup)
+{
+ char filename[255];
+ char filename2[255];
+ char buf[1024];
+ struct stat statbuf;
+ isc_result_t result;
+ int n;
+
+ UNUSED(zone);
+ UNUSED(dbdata);
+
+ if (strcmp(name, "@") == 0)
+ snprintf(filename, sizeof(filename), "%s", (char *)dbdata);
+ else
+ snprintf(filename, sizeof(filename), "%s/%s",
+ (char *)dbdata, name);
+ CHECKN(lstat(filename, &statbuf));
+
+ if (S_ISDIR(statbuf.st_mode))
+ CHECK(dns_sdb_putrr(lookup, "txt", 3600, "dir"));
+ else if (S_ISCHR(statbuf.st_mode) || S_ISBLK(statbuf.st_mode)) {
+ CHECKN(snprintf(buf, sizeof(buf),
+ "\"%sdev\" \"major %d\" \"minor %d\"",
+ S_ISCHR(statbuf.st_mode) ? "chr" : "blk",
+ major(statbuf.st_rdev),
+ minor(statbuf.st_rdev)));
+ CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
+ } else if (S_ISFIFO(statbuf.st_mode))
+ CHECK(dns_sdb_putrr(lookup, "txt", 3600, "pipe"));
+ else if (S_ISSOCK(statbuf.st_mode))
+ CHECK(dns_sdb_putrr(lookup, "txt", 3600, "socket"));
+ else if (S_ISLNK(statbuf.st_mode)) {
+ CHECKN(readlink(filename, filename2, sizeof(filename2) - 1));
+ buf[n] = 0;
+ CHECKN(snprintf(buf, sizeof(buf), "\"symlink\" \"%s\"",
+ filename2));
+ CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
+ } else if (!S_ISREG(statbuf.st_mode))
+ CHECK(dns_sdb_putrr(lookup, "txt", 3600, "unknown"));
+ else {
+ CHECKN(snprintf(buf, sizeof(buf), "\"file\" \"size = %u\"",
+ (unsigned int)statbuf.st_size));
+ CHECK(dns_sdb_putrr(lookup, "txt", 3600, buf));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * lookup () does not return SOA or NS records, so authority() must be defined.
+ */
+static isc_result_t
+dirdb_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
+ isc_result_t result;
+
+ UNUSED(zone);
+ UNUSED(dbdata);
+
+ result = dns_sdb_putsoa(lookup, "ns", "hostmaster", 0);
+ INSIST(result == ISC_R_SUCCESS);
+ result = dns_sdb_putrr(lookup, "ns", 86400, "ns1");
+ INSIST(result == ISC_R_SUCCESS);
+ result = dns_sdb_putrr(lookup, "ns", 86400, "ns2");
+ INSIST(result == ISC_R_SUCCESS);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Each database stores the top-level directory as the dbdata opaque
+ * object. The create() function allocates it. argv[0] holds the top
+ * level directory.
+ */
+static isc_result_t
+dirdb_create(const char *zone, int argc, char **argv,
+ void *driverdata, void **dbdata)
+{
+ UNUSED(zone);
+ UNUSED(driverdata);
+
+ if (argc < 1)
+ return (ISC_R_FAILURE);
+ *dbdata = isc_mem_strdup((isc_mem_t *)driverdata, argv[0]);
+ if (*dbdata == NULL)
+ return (ISC_R_NOMEMORY);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * The destroy() function frees the memory allocated by create().
+ */
+static void
+dirdb_destroy(const char *zone, void *driverdata, void **dbdata) {
+ UNUSED(zone);
+ UNUSED(driverdata);
+ isc_mem_free((isc_mem_t *)driverdata, *dbdata);
+}
+
+/*
+ * This zone does not support zone transfer, so allnodes() is NULL.
+ */
+static dns_sdbmethods_t dirdb_methods = {
+ dirdb_lookup,
+ dirdb_authority,
+ NULL, /* allnodes */
+ dirdb_create,
+ dirdb_destroy
+};
+
+/*
+ * Wrapper around dns_sdb_register(). Note that the first ns_g_mctx is
+ * being passed as the "driverdata" parameter, so that will it will be
+ * passed to create() and destroy().
+ */
+isc_result_t
+dirdb_init(void) {
+ unsigned int flags;
+ flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA |
+ DNS_SDBFLAG_THREADSAFE;
+ return (dns_sdb_register("dir", &dirdb_methods, ns_g_mctx, flags,
+ ns_g_mctx, &dirdb));
+}
+
+/*
+ * Wrapper around dns_sdb_unregister().
+ */
+void
+dirdb_clear(void) {
+ if (dirdb != NULL)
+ dns_sdb_unregister(&dirdb);
+}
diff --git a/contrib/sdb/dir/dirdb.h b/contrib/sdb/dir/dirdb.h
new file mode 100644
index 0000000..0deea13
--- /dev/null
+++ b/contrib/sdb/dir/dirdb.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004, 2007 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: dirdb.h,v 1.5 2007/06/19 23:47:07 tbox Exp $ */
+
+#include <isc/types.h>
+
+isc_result_t dirdb_init(void);
+
+void dirdb_clear(void);
+
diff --git a/contrib/sdb/ldap/INSTALL.ldap b/contrib/sdb/ldap/INSTALL.ldap
new file mode 100644
index 0000000..9151129
--- /dev/null
+++ b/contrib/sdb/ldap/INSTALL.ldap
@@ -0,0 +1,83 @@
+This is the INSTALL file for 1.0-beta. See
+http://www.venaas.no/ldap/bind-sdb/ for updates or other information.
+
+BUILDING
+
+You need the source for BIND 9.1.0 or newer (for zone transfers you
+will need at least 9.1.1rc3 due to a bug). Basically you need to follow
+the instructions in doc/misc/sdb, if my instructions don't make sense,
+please have a look at those as well.
+
+Copy ldapdb.c to bin/named and ldapdb.h to bin/named/include in the
+source tree.
+
+Next alter bin/named/Makefile.in. Add ldapdb.@O@ to DBDRIVER_OBJS and
+ldapdb.c to DBDRIVER_SRCS. You also need to add something like
+-I/usr/local/include to DBDRIVER_INCLUDES and
+-L/usr/local/lib -lldap -llber -lresolv to DBDRIVER_LIBS
+depending on what LDAP library you have and where you installed it.
+
+Finally you need to edit bin/named/main.c. Below where it says
+"#include "xxdb.h"", add the line "#include <ldapdb.h>". Below where
+it says "xxdb_init();" add the line "ldapdb_init();", and finally
+below where it says "xxdb_clear();", add "ldapdb_clear();".
+
+Now you should hopefully be able to build as usual; first configure
+and then make. If you get an error message about ldap_memfree() not
+being defined, you're probably using an LDAP library with the
+interface defined in RFC 1823. To build, uncomment the "#define
+LDAPDB_RFC1823API" line near the top of ldapdb.c.
+
+Also, if you're using an LDAPv2 only server, you need to change
+the line "#define LDAPDB_LDAP_VERSION 3" in ldapdb.c. Simply
+replace 3 with 2. Instead of editing the file, you may define
+LDAPDB_LDAP_VERSION yourself.
+
+If you want to use TLS, you need to uncommed the #define LDAPDB_TLS"
+line near the top of ldapdb.c.
+
+CONFIGURING
+
+Before you do any configuring of LDAP stuff, please try to configure
+and start bind as usual to see if things work.
+
+To do anything useful, you need to store a zone in some LDAP server.
+You must use a schema called dNSZone. Note that it relies on some
+attribute definitions in the Cosine schema, so that must be included
+as well. The Cosine schema probably comes with your LDAP server. You
+can find dNSZone and further details on how to store the data in your
+LDAP server at http://www.venaas.no/ldap/bind-sdb/
+
+To make BIND use a zone stored in LDAP, you will have to put something
+like this in named.conf:
+
+zone "venaas.com" {
+ type master;
+ database "ldap ldap://158.38.160.245/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no 172800";
+};
+
+When doing lookups BIND will do a sub-tree search below the base in the
+URL. The number 172800 is the TTL which will be used for all entries that
+haven't got the dNSTTL attribute. It is also possible to add a filter to
+the URL, say "ldap://host/base???(o=internal)".
+
+Version 1.0 also has support for simple LDAP bind, that is, binding to
+LDAP using plain text authentication. The bind dn and password is coded
+into the URL as extensions, according to RFC 2255. If you want simple
+bind with say dn "cn=Manager,dc=venaas,dc=no" and password "secret", the
+URL will be something like this:
+
+ldap://158.38.160.245/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no????!bindname=cn=Manager%2cdc=venaas%2cdc=no,!x-bindpw=secret
+
+This URL may also include a filter part if you need it. Note that in
+the bind dn, "," is hex-escaped as "%2c". This is necessary since ","
+is the separator between the extension elements. The "!" in front of
+"bindname" and "x-bindpw" can be omitted if you prefer. "x-bindpw" is
+not standardized, but it's used by several other LDAP applications. See
+RFC 2255 for details.
+
+Finally, if you enabled TLS when compiling, you can also use TLS if
+you like. To do this you use the extension "x-tls", e.g.
+ldap://158.38.160.245/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no????!bindname=cn=Manager%2cdc=venaas%2cdc=no,!x-bindpw=secret,x-tls
+
+Stig Venaas <venaas@uninett.no> 2004-08-15
diff --git a/contrib/sdb/ldap/README.ldap b/contrib/sdb/ldap/README.ldap
new file mode 100644
index 0000000..b4ea18a
--- /dev/null
+++ b/contrib/sdb/ldap/README.ldap
@@ -0,0 +1,48 @@
+This is an attempt at an LDAP back-end for BIND 9 using the new simplified
+database interface "sdb". This is release 1.0-beta and should be pretty
+stable. Note that since version 0.4 a new schema is used. It is not
+backwards compatible with versions before 0.4.
+
+1.0-beta fixes a large memory leak. An extension x-tls for enabling TLS
+has been added.
+
+1.0-alpha uses LDAPv3 by default and also supports LDAP simple bind. That
+is, one can use plain text password for authentication. The bind dn and
+password is coded into the URL using extensions bindname and x-bindpw
+per RFC 2255.
+
+In 0.9 the code has been cleaned up a bit and should be slightly faster
+than previous versions. It also fixes an error with zone transfers (AXFR)
+and entries with multiple relativeDomainName values. The problem was
+that it would only use the first value in the result. There's no need
+to upgrade unless you use such entries.
+
+0.8 uses asynchronous LDAP search which should give better performance.
+Thanks to Ashley Burston for providing patch. Another new feature is
+allowing filters in URLs. The syntax is as in RFC 2255. Few people will
+need this, but if you have say an internal and external version of the
+same zone, you could stick say o=internal and o=external into different
+entries, and specify for instance ldap://host/base???(o=internal)
+Some error logging has also been added.
+
+0.7 allows space and other characters to be used in URLs by use of %-quoting.
+For instance space can be written as %20. It also fixes a problem with some
+servers and/or APIs that do not preserve attribute casing.
+
+0.6 fixes some memory leaks present in older versions unless compiled with
+the RFC 1823 API.
+
+The big changes in 0.5 are thread support and improved connection handling.
+Multiple threads can now access the back-end simultaneously, and rather than
+having one connection per zone, there is now one connection per thread per
+LDAP server. This should help people with multiple CPUs and people with a
+huge number of zones. One final change is support for literal IPv6 addresses
+in LDAP URLs. At least OpenLDAP 2 has IPv6 support, so if you use OpenLDAP 2
+libraries and server, you got all you need.
+
+If you have bug reports, fixes, comments, questions or whatever, please
+contact me. See also http://www.venaas.no/ldap/bind-sdb/ for information.
+
+See INSTALL for how to build, install and use.
+
+Stig Venaas <venaas@uninett.no> 2004-08-15
diff --git a/contrib/sdb/ldap/README.zone2ldap b/contrib/sdb/ldap/README.zone2ldap
new file mode 100644
index 0000000..edb367b
--- /dev/null
+++ b/contrib/sdb/ldap/README.zone2ldap
@@ -0,0 +1,17 @@
+INSTALLATION
+
+To Compile zone2ldap from contrib/sdb directory:
+
+ gcc -g `../../isc-config.sh --cflags isc dns` -c zone2ldap.c
+ gcc -g -o zone2ldap zone2ldap.o `isc-config.sh --libs isc dns` -lldap -llber -lresolv
+
+USAGE:
+
+See zone2ldap.1
+
+BUGS:
+
+Jeff McNeil <jeff@snapcase.g-rock.net>
+
+
+
diff --git a/contrib/sdb/ldap/ldapdb.c b/contrib/sdb/ldap/ldapdb.c
new file mode 100644
index 0000000..ed124c0
--- /dev/null
+++ b/contrib/sdb/ldap/ldapdb.c
@@ -0,0 +1,667 @@
+/*
+ * ldapdb.c version 1.0-beta
+ *
+ * Copyright (C) 2002, 2004 Stig Venaas
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * Contributors: Jeremy C. McDermond
+ */
+
+/*
+ * If you want to use TLS, uncomment the define below
+ */
+/* #define LDAPDB_TLS */
+
+/*
+ * If you are using an old LDAP API uncomment the define below. Only do this
+ * if you know what you're doing or get compilation errors on ldap_memfree().
+ * This also forces LDAPv2.
+ */
+/* #define LDAPDB_RFC1823API */
+
+/* Using LDAPv3 by default, change this if you want v2 */
+#ifndef LDAPDB_LDAP_VERSION
+#define LDAPDB_LDAP_VERSION 3
+#endif
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+#include <isc/thread.h>
+
+#include <dns/sdb.h>
+
+#include <named/globals.h>
+#include <named/log.h>
+
+#include <ldap.h>
+#include "ldapdb.h"
+
+/*
+ * A simple database driver for LDAP
+ */
+
+/* enough for name with 8 labels of max length */
+#define MAXNAMELEN 519
+
+static dns_sdbimplementation_t *ldapdb = NULL;
+
+struct ldapdb_data {
+ char *hostport;
+ char *hostname;
+ int portno;
+ char *base;
+ int defaultttl;
+ char *filterall;
+ int filteralllen;
+ char *filterone;
+ int filteronelen;
+ char *filtername;
+ char *bindname;
+ char *bindpw;
+#ifdef LDAPDB_TLS
+ int tls;
+#endif
+};
+
+/* used by ldapdb_getconn */
+
+struct ldapdb_entry {
+ void *index;
+ size_t size;
+ void *data;
+ struct ldapdb_entry *next;
+};
+
+static struct ldapdb_entry *ldapdb_find(struct ldapdb_entry *stack,
+ const void *index, size_t size) {
+ while (stack != NULL) {
+ if (stack->size == size && !memcmp(stack->index, index, size))
+ return stack;
+ stack = stack->next;
+ }
+ return NULL;
+}
+
+static void ldapdb_insert(struct ldapdb_entry **stack,
+ struct ldapdb_entry *item) {
+ item->next = *stack;
+ *stack = item;
+}
+
+static void ldapdb_lock(int what) {
+ static isc_mutex_t lock;
+
+ switch (what) {
+ case 0:
+ isc_mutex_init(&lock);
+ break;
+ case 1:
+ LOCK(&lock);
+ break;
+ case -1:
+ UNLOCK(&lock);
+ break;
+ }
+}
+
+/* data == NULL means cleanup */
+static LDAP **
+ldapdb_getconn(struct ldapdb_data *data)
+{
+ static struct ldapdb_entry *allthreadsdata = NULL;
+ struct ldapdb_entry *threaddata, *conndata;
+ unsigned long threadid;
+
+ if (data == NULL) {
+ /* cleanup */
+ /* lock out other threads */
+ ldapdb_lock(1);
+ while (allthreadsdata != NULL) {
+ threaddata = allthreadsdata;
+ free(threaddata->index);
+ while (threaddata->data != NULL) {
+ conndata = threaddata->data;
+ free(conndata->index);
+ if (conndata->data != NULL)
+ ldap_unbind((LDAP *)conndata->data);
+ threaddata->data = conndata->next;
+ free(conndata);
+ }
+ allthreadsdata = threaddata->next;
+ free(threaddata);
+ }
+ ldapdb_lock(-1);
+ return (NULL);
+ }
+
+ /* look for connection data for current thread */
+ threadid = isc_thread_self();
+ threaddata = ldapdb_find(allthreadsdata, &threadid, sizeof(threadid));
+ if (threaddata == NULL) {
+ /* no data for this thread, create empty connection list */
+ threaddata = malloc(sizeof(*threaddata));
+ if (threaddata == NULL)
+ return (NULL);
+ threaddata->index = malloc(sizeof(threadid));
+ if (threaddata->index == NULL) {
+ free(threaddata);
+ return (NULL);
+ }
+ *(unsigned long *)threaddata->index = threadid;
+ threaddata->size = sizeof(threadid);
+ threaddata->data = NULL;
+
+ /* need to lock out other threads here */
+ ldapdb_lock(1);
+ ldapdb_insert(&allthreadsdata, threaddata);
+ ldapdb_lock(-1);
+ }
+
+ /* threaddata points at the connection list for current thread */
+ /* look for existing connection to our server */
+ conndata = ldapdb_find((struct ldapdb_entry *)threaddata->data,
+ data->hostport, strlen(data->hostport));
+ if (conndata == NULL) {
+ /* no connection data structure for this server, create one */
+ conndata = malloc(sizeof(*conndata));
+ if (conndata == NULL)
+ return (NULL);
+ conndata->index = data->hostport;
+ conndata->size = strlen(data->hostport);
+ conndata->data = NULL;
+ ldapdb_insert((struct ldapdb_entry **)&threaddata->data,
+ conndata);
+ }
+
+ return (LDAP **)&conndata->data;
+}
+
+static void
+ldapdb_bind(struct ldapdb_data *data, LDAP **ldp)
+{
+#ifndef LDAPDB_RFC1823API
+ const int ver = LDAPDB_LDAP_VERSION;
+#endif
+
+ if (*ldp != NULL)
+ ldap_unbind(*ldp);
+ *ldp = ldap_open(data->hostname, data->portno);
+ if (*ldp == NULL)
+ return;
+
+#ifndef LDAPDB_RFC1823API
+ ldap_set_option(*ldp, LDAP_OPT_PROTOCOL_VERSION, &ver);
+#endif
+
+#ifdef LDAPDB_TLS
+ if (data->tls) {
+ ldap_start_tls_s(*ldp, NULL, NULL);
+ }
+#endif
+
+ if (ldap_simple_bind_s(*ldp, data->bindname, data->bindpw) != LDAP_SUCCESS) {
+ ldap_unbind(*ldp);
+ *ldp = NULL;
+ }
+}
+
+static isc_result_t
+ldapdb_search(const char *zone, const char *name, void *dbdata, void *retdata)
+{
+ struct ldapdb_data *data = dbdata;
+ isc_result_t result = ISC_R_NOTFOUND;
+ LDAP **ldp;
+ LDAPMessage *res, *e;
+ char *fltr, *a, **vals = NULL, **names = NULL;
+ char type[64];
+#ifdef LDAPDB_RFC1823API
+ void *ptr;
+#else
+ BerElement *ptr;
+#endif
+ int i, j, errno, msgid;
+
+ ldp = ldapdb_getconn(data);
+ if (ldp == NULL)
+ return (ISC_R_FAILURE);
+ if (*ldp == NULL) {
+ ldapdb_bind(data, ldp);
+ if (*ldp == NULL) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "LDAP sdb zone '%s': bind failed", zone);
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ if (name == NULL) {
+ fltr = data->filterall;
+ } else {
+ if (strlen(name) > MAXNAMELEN) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "LDAP sdb zone '%s': name %s too long", zone, name);
+ return (ISC_R_FAILURE);
+ }
+ sprintf(data->filtername, "%s))", name);
+ fltr = data->filterone;
+ }
+
+ msgid = ldap_search(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0);
+ if (msgid == -1) {
+ ldapdb_bind(data, ldp);
+ if (*ldp != NULL)
+ msgid = ldap_search(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0);
+ }
+
+ if (*ldp == NULL || msgid == -1) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "LDAP sdb zone '%s': search failed, filter %s", zone, fltr);
+ return (ISC_R_FAILURE);
+ }
+
+ /* Get the records one by one as they arrive and return them to bind */
+ while ((errno = ldap_result(*ldp, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) {
+ LDAP *ld = *ldp;
+ int ttl = data->defaultttl;
+
+ /* not supporting continuation references at present */
+ if (errno != LDAP_RES_SEARCH_ENTRY) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "LDAP sdb zone '%s': ldap_result returned %d", zone, errno);
+ ldap_msgfree(res);
+ return (ISC_R_FAILURE);
+ }
+
+ /* only one entry per result message */
+ e = ldap_first_entry(ld, res);
+ if (e == NULL) {
+ ldap_msgfree(res);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "LDAP sdb zone '%s': ldap_first_entry failed", zone);
+ return (ISC_R_FAILURE);
+ }
+
+ if (name == NULL) {
+ names = ldap_get_values(ld, e, "relativeDomainName");
+ if (names == NULL)
+ continue;
+ }
+
+ vals = ldap_get_values(ld, e, "dNSTTL");
+ if (vals != NULL) {
+ ttl = atoi(vals[0]);
+ ldap_value_free(vals);
+ }
+
+ for (a = ldap_first_attribute(ld, e, &ptr); a != NULL; a = ldap_next_attribute(ld, e, ptr)) {
+ char *s;
+
+ for (s = a; *s; s++)
+ *s = toupper(*s);
+ s = strstr(a, "RECORD");
+ if ((s == NULL) || (s == a) || (s - a >= (signed int)sizeof(type))) {
+#ifndef LDAPDB_RFC1823API
+ ldap_memfree(a);
+#endif
+ continue;
+ }
+
+ strncpy(type, a, s - a);
+ type[s - a] = '\0';
+ vals = ldap_get_values(ld, e, a);
+ if (vals != NULL) {
+ for (i = 0; vals[i] != NULL; i++) {
+ if (name != NULL) {
+ result = dns_sdb_putrr(retdata, type, ttl, vals[i]);
+ } else {
+ for (j = 0; names[j] != NULL; j++) {
+ result = dns_sdb_putnamedrr(retdata, names[j], type, ttl, vals[i]);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ }
+; if (result != ISC_R_SUCCESS) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "LDAP sdb zone '%s': dns_sdb_put... failed for %s", zone, vals[i]);
+ ldap_value_free(vals);
+#ifndef LDAPDB_RFC1823API
+ ldap_memfree(a);
+ if (ptr != NULL)
+ ber_free(ptr, 0);
+#endif
+ if (name == NULL)
+ ldap_value_free(names);
+ ldap_msgfree(res);
+ return (ISC_R_FAILURE);
+ }
+ }
+ ldap_value_free(vals);
+ }
+#ifndef LDAPDB_RFC1823API
+ ldap_memfree(a);
+#endif
+ }
+#ifndef LDAPDB_RFC1823API
+ if (ptr != NULL)
+ ber_free(ptr, 0);
+#endif
+ if (name == NULL)
+ ldap_value_free(names);
+
+ /* free this result */
+ ldap_msgfree(res);
+ }
+
+ /* free final result */
+ ldap_msgfree(res);
+ return (result);
+}
+
+
+/* callback routines */
+static isc_result_t
+ldapdb_lookup(const char *zone, const char *name, void *dbdata,
+ dns_sdblookup_t *lookup)
+{
+ return ldapdb_search(zone, name, dbdata, lookup);
+}
+
+static isc_result_t
+ldapdb_allnodes(const char *zone, void *dbdata,
+ dns_sdballnodes_t *allnodes)
+{
+ return ldapdb_search(zone, NULL, dbdata, allnodes);
+}
+
+static char *
+unhex(char *in)
+{
+ static const char hexdigits[] = "0123456789abcdef";
+ char *p, *s = in;
+ int d1, d2;
+
+ while ((s = strchr(s, '%'))) {
+ if (!(s[1] && s[2]))
+ return NULL;
+ if ((p = strchr(hexdigits, tolower(s[1]))) == NULL)
+ return NULL;
+ d1 = p - hexdigits;
+ if ((p = strchr(hexdigits, tolower(s[2]))) == NULL)
+ return NULL;
+ d2 = p - hexdigits;
+ *s++ = d1 << 4 | d2;
+ memmove(s, s + 2, strlen(s) - 1);
+ }
+ return in;
+}
+
+/* returns 0 for ok, -1 for bad syntax, -2 for unknown critical extension */
+static int
+parseextensions(char *extensions, struct ldapdb_data *data)
+{
+ char *s, *next, *name, *value;
+ int critical;
+
+ while (extensions != NULL) {
+ s = strchr(extensions, ',');
+ if (s != NULL) {
+ *s++ = '\0';
+ next = s;
+ } else {
+ next = NULL;
+ }
+
+ if (*extensions != '\0') {
+ s = strchr(extensions, '=');
+ if (s != NULL) {
+ *s++ = '\0';
+ value = *s != '\0' ? s : NULL;
+ } else {
+ value = NULL;
+ }
+ name = extensions;
+
+ critical = *name == '!';
+ if (critical) {
+ name++;
+ }
+ if (*name == '\0') {
+ return -1;
+ }
+
+ if (!strcasecmp(name, "bindname")) {
+ data->bindname = value;
+ } else if (!strcasecmp(name, "x-bindpw")) {
+ data->bindpw = value;
+#ifdef LDAPDB_TLS
+ } else if (!strcasecmp(name, "x-tls")) {
+ data->tls = value == NULL || !strcasecmp(value, "true");
+#endif
+ } else if (critical) {
+ return -2;
+ }
+ }
+ extensions = next;
+ }
+ return 0;
+}
+
+static void
+free_data(struct ldapdb_data *data)
+{
+ if (data->hostport != NULL)
+ isc_mem_free(ns_g_mctx, data->hostport);
+ if (data->hostname != NULL)
+ isc_mem_free(ns_g_mctx, data->hostname);
+ if (data->filterall != NULL)
+ isc_mem_put(ns_g_mctx, data->filterall, data->filteralllen);
+ if (data->filterone != NULL)
+ isc_mem_put(ns_g_mctx, data->filterone, data->filteronelen);
+ isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data));
+}
+
+
+static isc_result_t
+ldapdb_create(const char *zone, int argc, char **argv,
+ void *driverdata, void **dbdata)
+{
+ struct ldapdb_data *data;
+ char *s, *filter = NULL, *extensions = NULL;
+ int defaultttl;
+
+ UNUSED(driverdata);
+
+ /* we assume that only one thread will call create at a time */
+ /* want to do this only once for all instances */
+
+ if ((argc < 2)
+ || (argv[0] != strstr( argv[0], "ldap://"))
+ || ((defaultttl = atoi(argv[1])) < 1))
+ return (ISC_R_FAILURE);
+ data = isc_mem_get(ns_g_mctx, sizeof(struct ldapdb_data));
+ if (data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(data, 0, sizeof(struct ldapdb_data));
+ data->hostport = isc_mem_strdup(ns_g_mctx, argv[0] + strlen("ldap://"));
+ if (data->hostport == NULL) {
+ free_data(data);
+ return (ISC_R_NOMEMORY);
+ }
+
+ data->defaultttl = defaultttl;
+
+ s = strchr(data->hostport, '/');
+ if (s != NULL) {
+ *s++ = '\0';
+ data->base = s;
+ /* attrs, scope, filter etc? */
+ s = strchr(s, '?');
+ if (s != NULL) {
+ *s++ = '\0';
+ /* ignore attributes */
+ s = strchr(s, '?');
+ if (s != NULL) {
+ *s++ = '\0';
+ /* ignore scope */
+ s = strchr(s, '?');
+ if (s != NULL) {
+ *s++ = '\0';
+ /* filter */
+ filter = s;
+ s = strchr(s, '?');
+ if (s != NULL) {
+ *s++ = '\0';
+ /* extensions */
+ extensions = s;
+ s = strchr(s, '?');
+ if (s != NULL) {
+ *s++ = '\0';
+ }
+ if (*extensions == '\0') {
+ extensions = NULL;
+ }
+ }
+ if (*filter == '\0') {
+ filter = NULL;
+ }
+ }
+ }
+ }
+ if (*data->base == '\0') {
+ data->base = NULL;
+ }
+ }
+
+ /* parse extensions */
+ if (extensions != NULL) {
+ int err;
+
+ err = parseextensions(extensions, data);
+ if (err < 0) {
+ /* err should be -1 or -2 */
+ free_data(data);
+ if (err == -1) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "LDAP sdb zone '%s': URL: extension syntax error", zone);
+ } else if (err == -2) {
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "LDAP sdb zone '%s': URL: unknown critical extension", zone);
+ }
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ if ((data->base != NULL && unhex(data->base) == NULL) ||
+ (filter != NULL && unhex(filter) == NULL) ||
+ (data->bindname != NULL && unhex(data->bindname) == NULL) ||
+ (data->bindpw != NULL && unhex(data->bindpw) == NULL)) {
+ free_data(data);
+ isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+ "LDAP sdb zone '%s': URL: bad hex values", zone);
+ return (ISC_R_FAILURE);
+ }
+
+ /* compute filterall and filterone once and for all */
+ if (filter == NULL) {
+ data->filteralllen = strlen(zone) + strlen("(zoneName=)") + 1;
+ data->filteronelen = strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1;
+ } else {
+ data->filteralllen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=))") + 1;
+ data->filteronelen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1;
+ }
+
+ data->filterall = isc_mem_get(ns_g_mctx, data->filteralllen);
+ if (data->filterall == NULL) {
+ free_data(data);
+ return (ISC_R_NOMEMORY);
+ }
+ data->filterone = isc_mem_get(ns_g_mctx, data->filteronelen);
+ if (data->filterone == NULL) {
+ free_data(data);
+ return (ISC_R_NOMEMORY);
+ }
+
+ if (filter == NULL) {
+ sprintf(data->filterall, "(zoneName=%s)", zone);
+ sprintf(data->filterone, "(&(zoneName=%s)(relativeDomainName=", zone);
+ } else {
+ sprintf(data->filterall, "(&%s(zoneName=%s))", filter, zone);
+ sprintf(data->filterone, "(&%s(zoneName=%s)(relativeDomainName=", filter, zone);
+ }
+ data->filtername = data->filterone + strlen(data->filterone);
+
+ /* support URLs with literal IPv6 addresses */
+ data->hostname = isc_mem_strdup(ns_g_mctx, data->hostport + (*data->hostport == '[' ? 1 : 0));
+ if (data->hostname == NULL) {
+ free_data(data);
+ return (ISC_R_NOMEMORY);
+ }
+
+ if (*data->hostport == '[' &&
+ (s = strchr(data->hostname, ']')) != NULL )
+ *s++ = '\0';
+ else
+ s = data->hostname;
+ s = strchr(s, ':');
+ if (s != NULL) {
+ *s++ = '\0';
+ data->portno = atoi(s);
+ } else
+ data->portno = LDAP_PORT;
+
+ *dbdata = data;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+ldapdb_destroy(const char *zone, void *driverdata, void **dbdata) {
+ struct ldapdb_data *data = *dbdata;
+
+ UNUSED(zone);
+ UNUSED(driverdata);
+
+ free_data(data);
+}
+
+static dns_sdbmethods_t ldapdb_methods = {
+ ldapdb_lookup,
+ NULL, /* authority */
+ ldapdb_allnodes,
+ ldapdb_create,
+ ldapdb_destroy
+};
+
+/* Wrapper around dns_sdb_register() */
+isc_result_t
+ldapdb_init(void) {
+ unsigned int flags =
+ DNS_SDBFLAG_RELATIVEOWNER |
+ DNS_SDBFLAG_RELATIVERDATA |
+ DNS_SDBFLAG_THREADSAFE;
+
+ ldapdb_lock(0);
+ return (dns_sdb_register("ldap", &ldapdb_methods, NULL, flags,
+ ns_g_mctx, &ldapdb));
+}
+
+/* Wrapper around dns_sdb_unregister() */
+void
+ldapdb_clear(void) {
+ if (ldapdb != NULL) {
+ /* clean up thread data */
+ ldapdb_getconn(NULL);
+ dns_sdb_unregister(&ldapdb);
+ }
+}
diff --git a/contrib/sdb/ldap/ldapdb.h b/contrib/sdb/ldap/ldapdb.h
new file mode 100644
index 0000000..a08eb20
--- /dev/null
+++ b/contrib/sdb/ldap/ldapdb.h
@@ -0,0 +1,6 @@
+#include <isc/types.h>
+
+isc_result_t ldapdb_init(void);
+
+void ldapdb_clear(void);
+
diff --git a/contrib/sdb/ldap/zone2ldap.1 b/contrib/sdb/ldap/zone2ldap.1
new file mode 100644
index 0000000..781114b
--- /dev/null
+++ b/contrib/sdb/ldap/zone2ldap.1
@@ -0,0 +1,64 @@
+.TH zone2ldap 1 "8 March 2001"
+.SH NAME
+zone2ldap /- Load BIND 9 Zone files into LDAP Directory
+.SH SYNOPSIS
+zone2ldap [-D Bind DN] [-w Bind Password] [-b Base DN] [-z Zone] [-f Zone File ] [-h Ldap Host] [-cd] [-v]
+.SH DESCRIPTION
+zone2ldap will parse a complete BIND 9 format DNS zone file, and load
+the contents into an LDAP directory, for use with the LDAP sdb back-end.
+
+If the zone already exists, zone2ldap will exit succesfully. If the zone does not exists, or
+partially exists, zone2ldap will attempt to add all/missing zone data.
+
+.SS Options
+.TP
+-b
+LDAP Base DN. LDAP systems require a "base dn", which is generally considered the LDAP Directory root.
+If the zone you are loading is different from the base, then you will need to tell zone2ldap what your LDAP
+base is.
+.TP
+-v
+Print version information, and immediatly exit.
+.TP
+-f
+Zone file. Bind 9.1 compatible zone file, from which zone information will be read.
+.TP
+-d
+Dump debug information to standard out.
+.TP
+-w
+LDAP Bind password, corresponding the the value of "-b".
+.TP
+-h
+LDAP Directory host. This is the hostname of the LDAP system you wish to store zone information on.
+An LDAP server should be listening on port 389 of the target system. This may be ommited, and will default
+to "localhost".
+.TP
+-c
+This will create the zone portion of the DN you are importing. For instance, if you are creating a domain.com zone,
+zone2ldap should first create "dc=domain,dc=com". This is useful if you are creating multiple domains.
+.TP
+-z
+This is the name of the zone specified in the SOA record.
+.SH EXAMPLES
+Following are brief examples of how to import a zone file into your LDAP DIT.
+.SS Loading zone domain.com, with an LDAP Base DN of dc=domain,dc=com
+zone2ldap -D dc=root -w secret -h localhost -z domain.com -f domain.com.zone
+
+This will add Resource Records into an ALREADY EXISTING dc=domain,dc=com. The final SOA DN in this case, will be
+dc=@,dc=domain,dc=com
+
+.SS Loading customer.com, if your LDAP Base DN is dc=provider,dc=net.
+zone2ldap -D dc=root -w secret -h localhost -z customer.com -b dc=provider,dc=net -f customer.com.zone -c
+
+This will create dc=customer,dc=com under dc=provider,dc=net, and add all necessary Resource Records. The final
+root DN to the SOA will be dc=@,dc=customer,dc=com,dc=provider,dc=net.
+
+.SH "SEE ALSO"
+named(8) ldap(3)
+http://www.venaas.no/ldap/bind-sdb/
+.SH "BUGS"
+Send all bug reports to Jeff McNeil <jeff@snapcase.g-rock.net>
+.SH AUTHOR
+Jeff McNeil <jeff@snapcase.g-rock.net>
+
diff --git a/contrib/sdb/ldap/zone2ldap.c b/contrib/sdb/ldap/zone2ldap.c
new file mode 100644
index 0000000..c2820fd
--- /dev/null
+++ b/contrib/sdb/ldap/zone2ldap.c
@@ -0,0 +1,734 @@
+/*
+ * Copyright (C) 2001 Jeff McNeil <jeff@snapcase.g-rock.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * Change Log
+ *
+ * Tue May 1 19:19:54 EDT 2001 - Jeff McNeil
+ * Update to objectClass code, and add_to_rr_list function
+ * (I need to rename that) to support the dNSZone schema,
+ * ditched dNSDomain2 schema support. Version 0.3-ALPHA
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+#include <dns/rdatatype.h>
+
+#include <ldap.h>
+
+#define DNS_OBJECT 6
+#define DNS_TOP 2
+
+#define VERSION "0.4-ALPHA"
+
+#define NO_SPEC 0
+#define WI_SPEC 1
+
+/* Global Zone Pointer */
+char *gbl_zone = NULL;
+
+typedef struct LDAP_INFO
+{
+ char *dn;
+ LDAPMod **attrs;
+ struct LDAP_INFO *next;
+ int attrcnt;
+}
+ldap_info;
+
+/* usage Info */
+void usage ();
+
+/* Add to the ldap dit */
+void add_ldap_values (ldap_info * ldinfo);
+
+/* Init an ldap connection */
+void init_ldap_conn ();
+
+/* Ldap error checking */
+void ldap_result_check (char *msg, char *dn, int err);
+
+/* Put a hostname into a char ** array */
+char **hostname_to_dn_list (char *hostname, char *zone, unsigned int flags);
+
+/* Find out how many items are in a char ** array */
+int get_attr_list_size (char **tmp);
+
+/* Get a DN */
+char *build_dn_from_dc_list (char **dc_list, unsigned int ttl, int flag);
+
+/* Add to RR list */
+void add_to_rr_list (char *dn, char *name, char *type, char *data,
+ unsigned int ttl, unsigned int flags);
+
+/* Error checking */
+void isc_result_check (isc_result_t res, char *errorstr);
+
+/* Generate LDIF Format files */
+void generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata,
+ unsigned int ttl);
+
+/* head pointer to the list */
+ldap_info *ldap_info_base = NULL;
+
+char *argzone, *ldapbase, *binddn, *bindpw = NULL;
+char *ldapsystem = "localhost";
+static char *objectClasses[] =
+ { "top", "dNSZone", NULL };
+static char *topObjectClasses[] = { "top", NULL };
+LDAP *conn;
+unsigned int debug = 0;
+
+#ifdef DEBUG
+debug = 1;
+#endif
+
+int
+main (int *argc, char **argv)
+{
+ isc_mem_t *mctx = NULL;
+ isc_entropy_t *ectx = NULL;
+ isc_result_t result;
+ char *basedn;
+ ldap_info *tmp;
+ LDAPMod *base_attrs[2];
+ LDAPMod base;
+ isc_buffer_t buff;
+ char *zonefile;
+ char fullbasedn[1024];
+ char *ctmp;
+ dns_fixedname_t fixedzone, fixedname;
+ dns_rdataset_t rdataset;
+ char **dc_list;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatasetiter_t *riter;
+ dns_name_t *zone, *name;
+ dns_db_t *db = NULL;
+ dns_dbiterator_t *dbit = NULL;
+ dns_dbnode_t *node;
+ extern char *optarg;
+ extern int optind, opterr, optopt;
+ int create_base = 0;
+ int topt;
+
+ if ((int) argc < 2)
+ {
+ usage ();
+ exit (-1);
+ }
+
+ while ((topt = getopt ((int) argc, argv, "D:w:b:z:f:h:?dcv")) != -1)
+ {
+ switch (topt)
+ {
+ case 'v':
+ printf("%s\n", VERSION);
+ exit(0);
+ case 'c':
+ create_base++;
+ break;
+ case 'd':
+ debug++;
+ break;
+ case 'D':
+ binddn = strdup (optarg);
+ break;
+ case 'w':
+ bindpw = strdup (optarg);
+ break;
+ case 'b':
+ ldapbase = strdup (optarg);
+ break;
+ case 'z':
+ argzone = strdup (optarg);
+ // We wipe argzone all to hell when we parse it for the DN */
+ gbl_zone = strdup(argzone);
+ break;
+ case 'f':
+ zonefile = strdup (optarg);
+ break;
+ case 'h':
+ ldapsystem = strdup (optarg);
+ break;
+ case '?':
+ default:
+ usage ();
+ exit (0);
+ }
+ }
+
+ if ((argzone == NULL) || (zonefile == NULL))
+ {
+ usage ();
+ exit (-1);
+ }
+
+ if (debug)
+ printf ("Initializing ISC Routines, parsing zone file\n");
+
+ result = isc_mem_create (0, 0, &mctx);
+ isc_result_check (result, "isc_mem_create");
+
+ result = isc_entropy_create(mctx, &ectx);
+ isc_result_check (result, "isc_entropy_create");
+
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ isc_result_check (result, "isc_hash_create");
+
+ isc_buffer_init (&buff, argzone, strlen (argzone));
+ isc_buffer_add (&buff, strlen (argzone));
+ dns_fixedname_init (&fixedzone);
+ zone = dns_fixedname_name (&fixedzone);
+ result = dns_name_fromtext (zone, &buff, dns_rootname, ISC_FALSE, NULL);
+ isc_result_check (result, "dns_name_fromtext");
+
+ result = dns_db_create (mctx, "rbt", zone, dns_dbtype_zone,
+ dns_rdataclass_in, 0, NULL, &db);
+ isc_result_check (result, "dns_db_create");
+
+ result = dns_db_load (db, zonefile);
+ isc_result_check (result, "Check Zone Syntax: dns_db_load");
+
+ result = dns_db_createiterator (db, 0, &dbit);
+ isc_result_check (result, "dns_db_createiterator");
+
+ result = dns_dbiterator_first (dbit);
+ isc_result_check (result, "dns_dbiterator_first");
+
+ dns_fixedname_init (&fixedname);
+ name = dns_fixedname_name (&fixedname);
+ dns_rdataset_init (&rdataset);
+ dns_rdata_init (&rdata);
+
+ while (result == ISC_R_SUCCESS)
+ {
+ node = NULL;
+ result = dns_dbiterator_current (dbit, &node, name);
+
+ if (result == ISC_R_NOMORE)
+ break;
+
+ isc_result_check (result, "dns_dbiterator_current");
+
+ riter = NULL;
+ result = dns_db_allrdatasets (db, node, NULL, 0, &riter);
+ isc_result_check (result, "dns_db_allrdatasets");
+
+ result = dns_rdatasetiter_first (riter);
+ //isc_result_check(result, "dns_rdatasetiter_first");
+
+ while (result == ISC_R_SUCCESS)
+ {
+ dns_rdatasetiter_current (riter, &rdataset);
+ result = dns_rdataset_first (&rdataset);
+ isc_result_check (result, "dns_rdatasetiter_current");
+
+ while (result == ISC_R_SUCCESS)
+ {
+ dns_rdataset_current (&rdataset, &rdata);
+ generate_ldap (name, &rdata, rdataset.ttl);
+ dns_rdata_reset (&rdata);
+ result = dns_rdataset_next (&rdataset);
+ }
+ dns_rdataset_disassociate (&rdataset);
+ result = dns_rdatasetiter_next (riter);
+
+ }
+ dns_rdatasetiter_destroy (&riter);
+ result = dns_dbiterator_next (dbit);
+
+ }
+
+ /* Initialize the LDAP Connection */
+ if (debug)
+ printf ("Initializing LDAP Connection to %s as %s\n", ldapsystem, binddn);
+
+ init_ldap_conn ();
+
+ if (create_base)
+ {
+ if (debug)
+ printf ("Creating base zone DN %s\n", argzone);
+
+ dc_list = hostname_to_dn_list (argzone, argzone, DNS_TOP);
+ basedn = build_dn_from_dc_list (dc_list, 0, NO_SPEC);
+
+ for (ctmp = &basedn[strlen (basedn)]; ctmp >= &basedn[0]; ctmp--)
+ {
+ if ((*ctmp == ',') || (ctmp == &basedn[0]))
+ {
+ base.mod_op = LDAP_MOD_ADD;
+ base.mod_type = "objectClass";
+ base.mod_values = topObjectClasses;
+ base_attrs[0] = &base;
+ base_attrs[1] = NULL;
+
+ if (ldapbase)
+ {
+ if (ctmp != &basedn[0])
+ sprintf (fullbasedn, "%s,%s", ctmp + 1, ldapbase);
+ else
+ sprintf (fullbasedn, "%s,%s", ctmp, ldapbase);
+
+ }
+ else
+ {
+ if (ctmp != &basedn[0])
+ sprintf (fullbasedn, "%s", ctmp + 1);
+ else
+ sprintf (fullbasedn, "%s", ctmp);
+ }
+ result = ldap_add_s (conn, fullbasedn, base_attrs);
+ ldap_result_check ("intial ldap_add_s", fullbasedn, result);
+ }
+
+ }
+ }
+ else
+ {
+ if (debug)
+ printf ("Skipping zone base dn creation for %s\n", argzone);
+ }
+
+ for (tmp = ldap_info_base; tmp != NULL; tmp = tmp->next)
+ {
+
+ if (debug)
+ printf ("Adding DN: %s\n", tmp->dn);
+
+ add_ldap_values (tmp);
+ }
+
+ if (debug)
+ printf("Operation Complete.\n");
+
+ /* Cleanup */
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return 0;
+}
+
+
+/* Check the status of an isc_result_t after any isc routines.
+ * I should probably rename this function, as not to cause any
+ * confusion with the isc* routines. Will exit on error. */
+void
+isc_result_check (isc_result_t res, char *errorstr)
+{
+ if (res != ISC_R_SUCCESS)
+ {
+ fprintf (stderr, " %s: %s\n", errorstr, isc_result_totext (res));
+ exit (-1);
+ }
+}
+
+
+/* Takes DNS information, in bind data structure format, and adds textual
+ * zone information to the LDAP run queue. */
+void
+generate_ldap (dns_name_t * dnsname, dns_rdata_t * rdata, unsigned int ttl)
+{
+ unsigned char name[DNS_NAME_MAXTEXT + 1];
+ unsigned int len;
+ unsigned char type[20];
+ unsigned char data[2048];
+ char **dc_list;
+ char *dn;
+
+ isc_buffer_t buff;
+ isc_result_t result;
+
+ isc_buffer_init (&buff, name, sizeof (name));
+ result = dns_name_totext (dnsname, ISC_TRUE, &buff);
+ isc_result_check (result, "dns_name_totext");
+ name[isc_buffer_usedlength (&buff)] = 0;
+
+ isc_buffer_init (&buff, type, sizeof (type));
+ result = dns_rdatatype_totext (rdata->type, &buff);
+ isc_result_check (result, "dns_rdatatype_totext");
+ type[isc_buffer_usedlength (&buff)] = 0;
+
+ isc_buffer_init (&buff, data, sizeof (data));
+ result = dns_rdata_totext (rdata, NULL, &buff);
+ isc_result_check (result, "dns_rdata_totext");
+ data[isc_buffer_usedlength (&buff)] = 0;
+
+ dc_list = hostname_to_dn_list (name, argzone, DNS_OBJECT);
+ len = (get_attr_list_size (dc_list) - 2);
+ dn = build_dn_from_dc_list (dc_list, ttl, WI_SPEC);
+
+ if (debug)
+ printf ("Adding %s (%s %s) to run queue list.\n", dn, type, data);
+
+ add_to_rr_list (dn, dc_list[len], type, data, ttl, DNS_OBJECT);
+}
+
+
+/* Locate an item in the Run queue linked list, by DN. Used by functions
+ * which add items to the run queue.
+ */
+ldap_info *
+locate_by_dn (char *dn)
+{
+ ldap_info *tmp;
+ for (tmp = ldap_info_base; tmp != (ldap_info *) NULL; tmp = tmp->next)
+ {
+ if (!strncmp (tmp->dn, dn, strlen (dn)))
+ return tmp;
+ }
+ return (ldap_info *) NULL;
+}
+
+
+
+/* Take textual zone data, and add to the LDAP Run queue. This works like so:
+ * If locate_by_dn does not return, alloc a new ldap_info structure, and then
+ * calloc a LDAPMod array, fill in the default "everyone needs this" information,
+ * including object classes and dc's. If it locate_by_dn does return, then we'll
+ * realloc for more LDAPMod structs, and appened the new data. If an LDAPMod exists
+ * for the parameter we're adding, then we'll realloc the mod_values array, and
+ * add the new value to the existing LDAPMod. Finnaly, it assures linkage exists
+ * within the Run queue linked ilst*/
+
+void
+add_to_rr_list (char *dn, char *name, char *type,
+ char *data, unsigned int ttl, unsigned int flags)
+{
+ int i;
+ int x;
+ ldap_info *tmp;
+ int attrlist;
+ char ldap_type_buffer[128];
+ char charttl[64];
+
+
+ if ((tmp = locate_by_dn (dn)) == NULL)
+ {
+
+ /* There wasn't one already there, so we need to allocate a new one,
+ * and stick it on the list */
+
+ tmp = (ldap_info *) malloc (sizeof (ldap_info));
+ if (tmp == (ldap_info *) NULL)
+ {
+ fprintf (stderr, "malloc: %s\n", strerror (errno));
+ ldap_unbind_s (conn);
+ exit (-1);
+ }
+
+ tmp->dn = strdup (dn);
+ tmp->attrs = (LDAPMod **) calloc (sizeof (LDAPMod *), flags);
+ if (tmp->attrs == (LDAPMod **) NULL)
+ {
+ fprintf (stderr, "calloc: %s\n", strerror (errno));
+ ldap_unbind_s (conn);
+ exit (-1);
+ }
+
+ for (i = 0; i < flags; i++)
+ {
+ tmp->attrs[i] = (LDAPMod *) malloc (sizeof (LDAPMod));
+ if (tmp->attrs[i] == (LDAPMod *) NULL)
+ {
+ fprintf (stderr, "malloc: %s\n", strerror (errno));
+ exit (-1);
+ }
+ }
+ tmp->attrs[0]->mod_op = LDAP_MOD_ADD;
+ tmp->attrs[0]->mod_type = "objectClass";
+
+ if (flags == DNS_OBJECT)
+ tmp->attrs[0]->mod_values = objectClasses;
+ else
+ {
+ tmp->attrs[0]->mod_values = topObjectClasses;
+ tmp->attrs[1] = NULL;
+ tmp->attrcnt = 2;
+ tmp->next = ldap_info_base;
+ ldap_info_base = tmp;
+ return;
+ }
+
+ tmp->attrs[1]->mod_op = LDAP_MOD_ADD;
+ tmp->attrs[1]->mod_type = "relativeDomainName";
+ tmp->attrs[1]->mod_values = (char **) calloc (sizeof (char *), 2);
+
+ if (tmp->attrs[1]->mod_values == (char **)NULL)
+ exit(-1);
+
+ tmp->attrs[1]->mod_values[0] = strdup (name);
+ tmp->attrs[1]->mod_values[2] = NULL;
+
+ sprintf (ldap_type_buffer, "%sRecord", type);
+
+ tmp->attrs[2]->mod_op = LDAP_MOD_ADD;
+ tmp->attrs[2]->mod_type = strdup (ldap_type_buffer);
+ tmp->attrs[2]->mod_values = (char **) calloc (sizeof (char *), 2);
+
+ if (tmp->attrs[2]->mod_values == (char **)NULL)
+ exit(-1);
+
+ tmp->attrs[2]->mod_values[0] = strdup (data);
+ tmp->attrs[2]->mod_values[1] = NULL;
+
+ tmp->attrs[3]->mod_op = LDAP_MOD_ADD;
+ tmp->attrs[3]->mod_type = "dNSTTL";
+ tmp->attrs[3]->mod_values = (char **) calloc (sizeof (char *), 2);
+
+ if (tmp->attrs[3]->mod_values == (char **)NULL)
+ exit(-1);
+
+ sprintf (charttl, "%d", ttl);
+ tmp->attrs[3]->mod_values[0] = strdup (charttl);
+ tmp->attrs[3]->mod_values[1] = NULL;
+
+ tmp->attrs[4]->mod_op = LDAP_MOD_ADD;
+ tmp->attrs[4]->mod_type = "zoneName";
+ tmp->attrs[4]->mod_values = (char **)calloc(sizeof(char *), 2);
+ tmp->attrs[4]->mod_values[0] = gbl_zone;
+ tmp->attrs[4]->mod_values[1] = NULL;
+
+ tmp->attrs[5] = NULL;
+ tmp->attrcnt = flags;
+ tmp->next = ldap_info_base;
+ ldap_info_base = tmp;
+ }
+ else
+ {
+
+ for (i = 0; tmp->attrs[i] != NULL; i++)
+ {
+ sprintf (ldap_type_buffer, "%sRecord", type);
+ if (!strncmp
+ (ldap_type_buffer, tmp->attrs[i]->mod_type,
+ strlen (tmp->attrs[i]->mod_type)))
+ {
+ attrlist = get_attr_list_size (tmp->attrs[i]->mod_values);
+ tmp->attrs[i]->mod_values =
+ (char **) realloc (tmp->attrs[i]->mod_values,
+ sizeof (char *) * (attrlist + 1));
+
+ if (tmp->attrs[i]->mod_values == (char **) NULL)
+ {
+ fprintf (stderr, "realloc: %s\n", strerror (errno));
+ ldap_unbind_s (conn);
+ exit (-1);
+ }
+ for (x = 0; tmp->attrs[i]->mod_values[x] != NULL; x++);
+
+ tmp->attrs[i]->mod_values[x] = strdup (data);
+ tmp->attrs[i]->mod_values[x + 1] = NULL;
+ return;
+ }
+ }
+ tmp->attrs =
+ (LDAPMod **) realloc (tmp->attrs,
+ sizeof (LDAPMod) * ++(tmp->attrcnt));
+ if (tmp->attrs == NULL)
+ {
+ fprintf (stderr, "realloc: %s\n", strerror (errno));
+ ldap_unbind_s (conn);
+ exit (-1);
+ }
+
+ for (x = 0; tmp->attrs[x] != NULL; x++);
+ tmp->attrs[x] = (LDAPMod *) malloc (sizeof (LDAPMod));
+ tmp->attrs[x]->mod_op = LDAP_MOD_ADD;
+ tmp->attrs[x]->mod_type = strdup (ldap_type_buffer);
+ tmp->attrs[x]->mod_values = (char **) calloc (sizeof (char *), 2);
+ tmp->attrs[x]->mod_values[0] = strdup (data);
+ tmp->attrs[x]->mod_values[1] = NULL;
+ tmp->attrs[x + 1] = NULL;
+ }
+}
+
+/* Size of a mod_values list, plus the terminating NULL field. */
+int
+get_attr_list_size (char **tmp)
+{
+ int i = 0;
+ char **ftmp = tmp;
+ while (*ftmp != NULL)
+ {
+ i++;
+ ftmp++;
+ }
+ return ++i;
+}
+
+
+/* take a hostname, and split it into a char ** of the dc parts,
+ * example, we have www.domain.com, this function will return:
+ * array[0] = com, array[1] = domain, array[2] = www. */
+
+char **
+hostname_to_dn_list (char *hostname, char *zone, unsigned int flags)
+{
+ char *tmp;
+ static char *dn_buffer[64];
+ int i = 0;
+ char *zname;
+ char *hnamebuff;
+
+ zname = strdup (hostname);
+
+ if (flags == DNS_OBJECT)
+ {
+
+ if (strlen (zname) != strlen (zone))
+ {
+ tmp = &zname[strlen (zname) - strlen (zone)];
+ *--tmp = '\0';
+ hnamebuff = strdup (zname);
+ zname = ++tmp;
+ }
+ else
+ hnamebuff = "@";
+ }
+ else
+ {
+ zname = zone;
+ hnamebuff = NULL;
+ }
+
+ for (tmp = strrchr (zname, '.'); tmp != (char *) 0;
+ tmp = strrchr (zname, '.'))
+ {
+ *tmp++ = '\0';
+ dn_buffer[i++] = tmp;
+ }
+ dn_buffer[i++] = zname;
+ dn_buffer[i++] = hnamebuff;
+ dn_buffer[i] = NULL;
+
+ return dn_buffer;
+}
+
+
+/* build an sdb compatible LDAP DN from a "dc_list" (char **).
+ * will append dNSTTL information to each RR Record, with the
+ * exception of "@"/SOA. */
+
+char *
+build_dn_from_dc_list (char **dc_list, unsigned int ttl, int flag)
+{
+ int size;
+ int x;
+ static char dn[1024];
+ char tmp[128];
+
+ bzero (tmp, sizeof (tmp));
+ bzero (dn, sizeof (dn));
+ size = get_attr_list_size (dc_list);
+ for (x = size - 2; x > 0; x--)
+ {
+ if (flag == WI_SPEC)
+ {
+ if (x == (size - 2) && (strncmp (dc_list[x], "@", 1) == 0) && (ttl))
+ sprintf (tmp, "relativeDomainName=%s + dNSTTL=%d,", dc_list[x], ttl);
+ else if (x == (size - 2))
+ sprintf(tmp, "relativeDomainName=%s,",dc_list[x]);
+ else
+ sprintf(tmp,"dc=%s,", dc_list[x]);
+ }
+ else
+ {
+ sprintf(tmp, "dc=%s,", dc_list[x]);
+ }
+
+
+ strncat (dn, tmp, sizeof (dn) - strlen (dn));
+ }
+
+ sprintf (tmp, "dc=%s", dc_list[0]);
+ strncat (dn, tmp, sizeof (dn) - strlen (dn));
+
+ fflush(NULL);
+ return dn;
+}
+
+
+/* Initialize LDAP Conn */
+void
+init_ldap_conn ()
+{
+ int result;
+ conn = ldap_open (ldapsystem, LDAP_PORT);
+ if (conn == NULL)
+ {
+ fprintf (stderr, "Error opening Ldap connection: %s\n",
+ strerror (errno));
+ exit (-1);
+ }
+
+ result = ldap_simple_bind_s (conn, binddn, bindpw);
+ ldap_result_check ("ldap_simple_bind_s", "LDAP Bind", result);
+}
+
+/* Like isc_result_check, only for LDAP */
+void
+ldap_result_check (char *msg, char *dn, int err)
+{
+ if ((err != LDAP_SUCCESS) && (err != LDAP_ALREADY_EXISTS))
+ {
+ fprintf(stderr, "Error while adding %s (%s):\n",
+ dn, msg);
+ ldap_perror (conn, dn);
+ ldap_unbind_s (conn);
+ exit (-1);
+ }
+}
+
+
+
+/* For running the ldap_info run queue. */
+void
+add_ldap_values (ldap_info * ldinfo)
+{
+ int result;
+ char dnbuffer[1024];
+
+
+ if (ldapbase != NULL)
+ sprintf (dnbuffer, "%s,%s", ldinfo->dn, ldapbase);
+ else
+ sprintf (dnbuffer, "%s", ldinfo->dn);
+
+ result = ldap_add_s (conn, dnbuffer, ldinfo->attrs);
+ ldap_result_check ("ldap_add_s", dnbuffer, result);
+}
+
+
+
+
+/* name says it all */
+void
+usage ()
+{
+ fprintf (stderr,
+ "zone2ldap -D [BIND DN] -w [BIND PASSWORD] -b [BASE DN] -z [ZONE] -f [ZONE FILE] -h [LDAP HOST]
+ [-c Create LDAP Base structure][-d Debug Output (lots !)] \n ");}
diff --git a/contrib/sdb/pgsql/pgsqldb.c b/contrib/sdb/pgsql/pgsqldb.c
new file mode 100644
index 0000000..ca3bfbf
--- /dev/null
+++ b/contrib/sdb/pgsql/pgsqldb.c
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2004, 2007 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: pgsqldb.c,v 1.15 2007/06/19 23:47:07 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <pgsql/libpq-fe.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/sdb.h>
+#include <dns/result.h>
+
+#include <named/globals.h>
+
+#include "pgsqldb.h"
+
+/*
+ * A simple database driver that interfaces to a PostgreSQL database. This
+ * is not complete, and not designed for general use. It opens one
+ * connection to the database per zone, which is inefficient. It also may
+ * not handle quoting correctly.
+ *
+ * The table must contain the fields "name", "rdtype", and "rdata", and
+ * is expected to contain a properly constructed zone. The program "zonetodb"
+ * creates such a table.
+ */
+
+static dns_sdbimplementation_t *pgsqldb = NULL;
+
+struct dbinfo {
+ PGconn *conn;
+ char *database;
+ char *table;
+ char *host;
+ char *user;
+ char *passwd;
+};
+
+static void
+pgsqldb_destroy(const char *zone, void *driverdata, void **dbdata);
+
+/*
+ * Canonicalize a string before writing it to the database.
+ * "dest" must be an array of at least size 2*strlen(source) + 1.
+ */
+static void
+quotestring(const char *source, char *dest) {
+ while (*source != 0) {
+ if (*source == '\'')
+ *dest++ = '\'';
+ /* SQL doesn't treat \ as special, but PostgreSQL does */
+ else if (*source == '\\')
+ *dest++ = '\\';
+ *dest++ = *source++;
+ }
+ *dest++ = 0;
+}
+
+/*
+ * Connect to the database.
+ */
+static isc_result_t
+db_connect(struct dbinfo *dbi) {
+ dbi->conn = PQsetdbLogin(dbi->host, NULL, NULL, NULL, dbi->database,
+ dbi->user, dbi->passwd);
+
+ if (PQstatus(dbi->conn) == CONNECTION_OK)
+ return (ISC_R_SUCCESS);
+ else
+ return (ISC_R_FAILURE);
+}
+
+/*
+ * Check to see if the connection is still valid. If not, attempt to
+ * reconnect.
+ */
+static isc_result_t
+maybe_reconnect(struct dbinfo *dbi) {
+ if (PQstatus(dbi->conn) == CONNECTION_OK)
+ return (ISC_R_SUCCESS);
+
+ return (db_connect(dbi));
+}
+
+/*
+ * This database operates on absolute names.
+ *
+ * Queries are converted into SQL queries and issued synchronously. Errors
+ * are handled really badly.
+ */
+static isc_result_t
+pgsqldb_lookup(const char *zone, const char *name, void *dbdata,
+ dns_sdblookup_t *lookup)
+{
+ isc_result_t result;
+ struct dbinfo *dbi = dbdata;
+ PGresult *res;
+ char str[1500];
+ char *canonname;
+ int i;
+
+ UNUSED(zone);
+
+ canonname = isc_mem_get(ns_g_mctx, strlen(name) * 2 + 1);
+ if (canonname == NULL)
+ return (ISC_R_NOMEMORY);
+ quotestring(name, canonname);
+ snprintf(str, sizeof(str),
+ "SELECT TTL,RDTYPE,RDATA FROM \"%s\" WHERE "
+ "lower(NAME) = lower('%s')", dbi->table, canonname);
+ isc_mem_put(ns_g_mctx, canonname, strlen(name) * 2 + 1);
+
+ result = maybe_reconnect(dbi);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ res = PQexec(dbi->conn, str);
+ if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
+ PQclear(res);
+ return (ISC_R_FAILURE);
+ }
+ if (PQntuples(res) == 0) {
+ PQclear(res);
+ return (ISC_R_NOTFOUND);
+ }
+
+ for (i = 0; i < PQntuples(res); i++) {
+ char *ttlstr = PQgetvalue(res, i, 0);
+ char *type = PQgetvalue(res, i, 1);
+ char *data = PQgetvalue(res, i, 2);
+ dns_ttl_t ttl;
+ char *endp;
+ ttl = strtol(ttlstr, &endp, 10);
+ if (*endp != '\0') {
+ PQclear(res);
+ return (DNS_R_BADTTL);
+ }
+ result = dns_sdb_putrr(lookup, type, ttl, data);
+ if (result != ISC_R_SUCCESS) {
+ PQclear(res);
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ PQclear(res);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Issue an SQL query to return all nodes in the database and fill the
+ * allnodes structure.
+ */
+static isc_result_t
+pgsqldb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *allnodes) {
+ struct dbinfo *dbi = dbdata;
+ PGresult *res;
+ isc_result_t result;
+ char str[1500];
+ int i;
+
+ UNUSED(zone);
+
+ snprintf(str, sizeof(str),
+ "SELECT TTL,NAME,RDTYPE,RDATA FROM \"%s\" ORDER BY NAME",
+ dbi->table);
+
+ result = maybe_reconnect(dbi);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ res = PQexec(dbi->conn, str);
+ if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ) {
+ PQclear(res);
+ return (ISC_R_FAILURE);
+ }
+ if (PQntuples(res) == 0) {
+ PQclear(res);
+ return (ISC_R_NOTFOUND);
+ }
+
+ for (i = 0; i < PQntuples(res); i++) {
+ char *ttlstr = PQgetvalue(res, i, 0);
+ char *name = PQgetvalue(res, i, 1);
+ char *type = PQgetvalue(res, i, 2);
+ char *data = PQgetvalue(res, i, 3);
+ dns_ttl_t ttl;
+ char *endp;
+ ttl = strtol(ttlstr, &endp, 10);
+ if (*endp != '\0') {
+ PQclear(res);
+ return (DNS_R_BADTTL);
+ }
+ result = dns_sdb_putnamedrr(allnodes, name, type, ttl, data);
+ if (result != ISC_R_SUCCESS) {
+ PQclear(res);
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ PQclear(res);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Create a connection to the database and save any necessary information
+ * in dbdata.
+ *
+ * argv[0] is the name of the database
+ * argv[1] is the name of the table
+ * argv[2] (if present) is the name of the host to connect to
+ * argv[3] (if present) is the name of the user to connect as
+ * argv[4] (if present) is the name of the password to connect with
+ */
+static isc_result_t
+pgsqldb_create(const char *zone, int argc, char **argv,
+ void *driverdata, void **dbdata)
+{
+ struct dbinfo *dbi;
+ isc_result_t result;
+
+ UNUSED(zone);
+ UNUSED(driverdata);
+
+ if (argc < 2)
+ return (ISC_R_FAILURE);
+
+ dbi = isc_mem_get(ns_g_mctx, sizeof(struct dbinfo));
+ if (dbi == NULL)
+ return (ISC_R_NOMEMORY);
+ dbi->conn = NULL;
+ dbi->database = NULL;
+ dbi->table = NULL;
+ dbi->host = NULL;
+ dbi->user = NULL;
+ dbi->passwd = NULL;
+
+#define STRDUP_OR_FAIL(target, source) \
+ do { \
+ target = isc_mem_strdup(ns_g_mctx, source); \
+ if (target == NULL) { \
+ result = ISC_R_NOMEMORY; \
+ goto cleanup; \
+ } \
+ } while (0);
+
+ STRDUP_OR_FAIL(dbi->database, argv[0]);
+ STRDUP_OR_FAIL(dbi->table, argv[1]);
+ if (argc > 2)
+ STRDUP_OR_FAIL(dbi->host, argv[2]);
+ if (argc > 3)
+ STRDUP_OR_FAIL(dbi->user, argv[3]);
+ if (argc > 4)
+ STRDUP_OR_FAIL(dbi->passwd, argv[4]);
+
+ result = db_connect(dbi);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ *dbdata = dbi;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ pgsqldb_destroy(zone, driverdata, (void **)&dbi);
+ return (result);
+}
+
+/*
+ * Close the connection to the database.
+ */
+static void
+pgsqldb_destroy(const char *zone, void *driverdata, void **dbdata) {
+ struct dbinfo *dbi = *dbdata;
+
+ UNUSED(zone);
+ UNUSED(driverdata);
+
+ if (dbi->conn != NULL)
+ PQfinish(dbi->conn);
+ if (dbi->database != NULL)
+ isc_mem_free(ns_g_mctx, dbi->database);
+ if (dbi->table != NULL)
+ isc_mem_free(ns_g_mctx, dbi->table);
+ if (dbi->host != NULL)
+ isc_mem_free(ns_g_mctx, dbi->host);
+ if (dbi->user != NULL)
+ isc_mem_free(ns_g_mctx, dbi->user);
+ if (dbi->passwd != NULL)
+ isc_mem_free(ns_g_mctx, dbi->passwd);
+ if (dbi->database != NULL)
+ isc_mem_free(ns_g_mctx, dbi->database);
+ isc_mem_put(ns_g_mctx, dbi, sizeof(struct dbinfo));
+}
+
+/*
+ * Since the SQL database corresponds to a zone, the authority data should
+ * be returned by the lookup() function. Therefore the authority() function
+ * is NULL.
+ */
+static dns_sdbmethods_t pgsqldb_methods = {
+ pgsqldb_lookup,
+ NULL, /* authority */
+ pgsqldb_allnodes,
+ pgsqldb_create,
+ pgsqldb_destroy
+};
+
+/*
+ * Wrapper around dns_sdb_register().
+ */
+isc_result_t
+pgsqldb_init(void) {
+ unsigned int flags;
+ flags = 0;
+ return (dns_sdb_register("pgsql", &pgsqldb_methods, NULL, flags,
+ ns_g_mctx, &pgsqldb));
+}
+
+/*
+ * Wrapper around dns_sdb_unregister().
+ */
+void
+pgsqldb_clear(void) {
+ if (pgsqldb != NULL)
+ dns_sdb_unregister(&pgsqldb);
+}
diff --git a/contrib/sdb/pgsql/pgsqldb.h b/contrib/sdb/pgsql/pgsqldb.h
new file mode 100644
index 0000000..20dc742
--- /dev/null
+++ b/contrib/sdb/pgsql/pgsqldb.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004, 2007 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: pgsqldb.h,v 1.5 2007/06/19 23:47:08 tbox Exp $ */
+
+#include <isc/types.h>
+
+isc_result_t pgsqldb_init(void);
+
+void pgsqldb_clear(void);
+
diff --git a/contrib/sdb/pgsql/zonetodb.c b/contrib/sdb/pgsql/zonetodb.c
new file mode 100644
index 0000000..ba93027
--- /dev/null
+++ b/contrib/sdb/pgsql/zonetodb.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: zonetodb.c,v 1.20 2008/09/25 04:02:38 tbox Exp $ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+
+#include <pgsql/libpq-fe.h>
+
+/*
+ * Generate a PostgreSQL table from a zone.
+ *
+ * This is compiled this with something like the following (assuming bind9 has
+ * been installed):
+ *
+ * gcc -g `isc-config.sh --cflags isc dns` -c zonetodb.c
+ * gcc -g -o zonetodb zonetodb.o `isc-config.sh --libs isc dns` -lpq
+ */
+
+PGconn *conn = NULL;
+char *dbname, *dbtable;
+char str[10240];
+
+void
+closeandexit(int status) {
+ if (conn != NULL)
+ PQfinish(conn);
+ exit(status);
+}
+
+void
+check_result(isc_result_t result, const char *message) {
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "%s: %s\n", message,
+ isc_result_totext(result));
+ closeandexit(1);
+ }
+}
+
+/*
+ * Canonicalize a string before writing it to the database.
+ * "dest" must be an array of at least size 2*strlen(source) + 1.
+ */
+static void
+quotestring(const char *source, char *dest) {
+ while (*source != 0) {
+ if (*source == '\'')
+ *dest++ = '\'';
+ else if (*source == '\\')
+ *dest++ = '\\';
+ *dest++ = *source++;
+ }
+ *dest++ = 0;
+}
+
+void
+addrdata(dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
+ unsigned char namearray[DNS_NAME_MAXTEXT + 1];
+ unsigned char canonnamearray[2 * DNS_NAME_MAXTEXT + 1];
+ unsigned char typearray[20];
+ unsigned char canontypearray[40];
+ unsigned char dataarray[2048];
+ unsigned char canondataarray[4096];
+ isc_buffer_t b;
+ isc_result_t result;
+ PGresult *res;
+
+ isc_buffer_init(&b, namearray, sizeof(namearray) - 1);
+ result = dns_name_totext(name, ISC_TRUE, &b);
+ check_result(result, "dns_name_totext");
+ namearray[isc_buffer_usedlength(&b)] = 0;
+ quotestring(namearray, canonnamearray);
+
+ isc_buffer_init(&b, typearray, sizeof(typearray) - 1);
+ result = dns_rdatatype_totext(rdata->type, &b);
+ check_result(result, "dns_rdatatype_totext");
+ typearray[isc_buffer_usedlength(&b)] = 0;
+ quotestring(typearray, canontypearray);
+
+ isc_buffer_init(&b, dataarray, sizeof(dataarray) - 1);
+ result = dns_rdata_totext(rdata, NULL, &b);
+ check_result(result, "dns_rdata_totext");
+ dataarray[isc_buffer_usedlength(&b)] = 0;
+ quotestring(dataarray, canondataarray);
+
+ snprintf(str, sizeof(str),
+ "INSERT INTO %s (NAME, TTL, RDTYPE, RDATA)"
+ " VALUES ('%s', %d, '%s', '%s')",
+ dbtable, canonnamearray, ttl, canontypearray, canondataarray);
+ printf("%s\n", str);
+ res = PQexec(conn, str);
+ if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
+ fprintf(stderr, "INSERT INTO command failed: %s\n",
+ PQresultErrorMessage(res));
+ PQclear(res);
+ closeandexit(1);
+ }
+ PQclear(res);
+}
+
+int
+main(int argc, char **argv) {
+ char *porigin, *zonefile;
+ dns_fixedname_t forigin, fname;
+ dns_name_t *origin, *name;
+ dns_db_t *db = NULL;
+ dns_dbiterator_t *dbiter;
+ dns_dbnode_t *node;
+ dns_rdatasetiter_t *rdsiter;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_mem_t *mctx = NULL;
+ isc_entropy_t *ectx = NULL;
+ isc_buffer_t b;
+ isc_result_t result;
+ PGresult *res;
+
+ if (argc != 5) {
+ printf("usage: %s origin file dbname dbtable\n", argv[0]);
+ printf("Note that dbname must be an existing database.\n");
+ exit(1);
+ }
+
+ porigin = argv[1];
+ zonefile = argv[2];
+ dbname = argv[3];
+ dbtable = argv[4];
+
+ dns_result_register();
+
+ mctx = NULL;
+ result = isc_mem_create(0, 0, &mctx);
+ check_result(result, "isc_mem_create");
+
+ result = isc_entropy_create(mctx, &ectx);
+ result_check (result, "isc_entropy_create");
+
+ result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ check_result (result, "isc_hash_create");
+
+ isc_buffer_init(&b, porigin, strlen(porigin));
+ isc_buffer_add(&b, strlen(porigin));
+ dns_fixedname_init(&forigin);
+ origin = dns_fixedname_name(&forigin);
+ result = dns_name_fromtext(origin, &b, dns_rootname, ISC_FALSE, NULL);
+ check_result(result, "dns_name_fromtext");
+
+ db = NULL;
+ result = dns_db_create(mctx, "rbt", origin, dns_dbtype_zone,
+ dns_rdataclass_in, 0, NULL, &db);
+ check_result(result, "dns_db_create");
+
+ result = dns_db_load(db, zonefile);
+ if (result == DNS_R_SEENINCLUDE)
+ result = ISC_R_SUCCESS;
+ check_result(result, "dns_db_load");
+
+ printf("Connecting to '%s'\n", dbname);
+ conn = PQsetdb(NULL, NULL, NULL, NULL, dbname);
+ if (PQstatus(conn) == CONNECTION_BAD) {
+ fprintf(stderr, "Connection to database '%s' failed: %s\n",
+ dbname, PQerrorMessage(conn));
+ closeandexit(1);
+ }
+
+ snprintf(str, sizeof(str),
+ "DROP TABLE %s", dbtable);
+ printf("%s\n", str);
+ res = PQexec(conn, str);
+ if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
+ fprintf(stderr, "DROP TABLE command failed: %s\n",
+ PQresultErrorMessage(res));
+ PQclear(res);
+
+ snprintf(str, sizeof(str), "BEGIN");
+ printf("%s\n", str);
+ res = PQexec(conn, str);
+ if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
+ fprintf(stderr, "BEGIN command failed: %s\n",
+ PQresultErrorMessage(res));
+ PQclear(res);
+ closeandexit(1);
+ }
+ PQclear(res);
+
+ snprintf(str, sizeof(str),
+ "CREATE TABLE %s "
+ "(NAME TEXT, TTL INTEGER, RDTYPE TEXT, RDATA TEXT)",
+ dbtable);
+ printf("%s\n", str);
+ res = PQexec(conn, str);
+ if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
+ fprintf(stderr, "CREATE TABLE command failed: %s\n",
+ PQresultErrorMessage(res));
+ PQclear(res);
+ closeandexit(1);
+ }
+ PQclear(res);
+
+ dbiter = NULL;
+ result = dns_db_createiterator(db, 0, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first");
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_rdataset_init(&rdataset);
+ dns_rdata_init(&rdata);
+
+ while (result == ISC_R_SUCCESS) {
+ node = NULL;
+ result = dns_dbiterator_current(dbiter, &node, name);
+ if (result == ISC_R_NOMORE)
+ break;
+ check_result(result, "dns_dbiterator_current");
+
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, NULL, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets");
+
+ result = dns_rdatasetiter_first(rdsiter);
+
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ result = dns_rdataset_first(&rdataset);
+ check_result(result, "dns_rdataset_first");
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&rdataset, &rdata);
+ addrdata(name, rdataset.ttl, &rdata);
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&rdataset);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+ dns_db_detachnode(db, &node);
+ result = dns_dbiterator_next(dbiter);
+ }
+
+ snprintf(str, sizeof(str), "COMMIT TRANSACTION");
+ printf("%s\n", str);
+ res = PQexec(conn, str);
+ if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {
+ fprintf(stderr, "COMMIT command failed: %s\n",
+ PQresultErrorMessage(res));
+ PQclear(res);
+ closeandexit(1);
+ }
+ PQclear(res);
+ dns_dbiterator_destroy(&dbiter);
+ dns_db_detach(&db);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ closeandexit(0);
+ exit(0);
+}
diff --git a/contrib/sdb/sqlite/README.sdb_sqlite b/contrib/sdb/sqlite/README.sdb_sqlite
new file mode 100644
index 0000000..36128e1
--- /dev/null
+++ b/contrib/sdb/sqlite/README.sdb_sqlite
@@ -0,0 +1,67 @@
+ SQLite BIND SDB driver
+
+The SQLite BIND SDB "driver" is intended as an alternative both to the
+pgsqldb and dirdb drivers, for situations that would like the management
+simplicity and convenience of single filesystem files, with the additional
+capability of SQL databases. It is also intended as an alternative to
+the standard dynamic DNS update capability in bind, which effectively
+requires use of DNSSEC keys for authorization and is limited to 'nsupdate'
+for updates. An sqlite database, by contrast, uses and requires only
+normal filesystem permissions, and may be updated however a typical SQLite
+database might be updated, e.g., via a web service with an SQLite backend.
+
+This driver is not considered suitable for very high volume public
+nameserver use, while likely useful for smaller private nameserver
+applications, whether or not in a production environment. It should
+generally be suitable wherever SQLite is preferable over larger database
+engines, and not suitable where SQLite is not preferable.
+
+Usage:
+
+o Use the named_sdb process ( put ENABLE_SDB=yes in /etc/sysconfig/named )
+
+o Edit your named.conf to contain a database zone, eg.:
+
+zone "mydomain.net." IN {
+ type master;
+ database "sqlite /etc/named.d/mydomain.db mydomain";
+ # ^- DB file ^-Table
+};
+
+o Create the database zone table
+ The table must contain the columns "name", "rdtype", and "rdata", and
+ is expected to contain a properly constructed zone. The program
+ "zone2sqlite" creates such a table.
+
+ zone2sqlite usage:
+
+ zone2sqlite origin zonefile dbfile dbtable
+
+ where
+ origin : zone origin, eg "mydomain.net."
+ zonefile : master zone database file, eg. mydomain.net.zone
+ dbfile : name of SQLite database file
+ dbtable : name of table in database
+
+---
+# mydomain.net.zone:
+$TTL 1H
+@ SOA localhost. root.localhost. ( 1
+ 3H
+ 1H
+ 1W
+ 1H )
+ NS localhost.
+host1 A 192.168.2.1
+host2 A 192.168.2.2
+host3 A 192.168.2.3
+host4 A 192.168.2.4
+host5 A 192.168.2.5
+host6 A 192.168.2.6
+host7 A 192.168.2.7
+---
+
+# zone2sqlite mydomain.net. mydomain.net.zone mydomain.net.db mydomain
+
+will create/update the 'mydomain' table in database file 'mydomain.net.db'.
+
diff --git a/contrib/sdb/sqlite/sqlitedb.c b/contrib/sdb/sqlite/sqlitedb.c
new file mode 100644
index 0000000..c9d0096
--- /dev/null
+++ b/contrib/sdb/sqlite/sqlitedb.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2007 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: sqlitedb.c,v 1.1 2007/03/05 05:30:22 marka Exp $ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sqlite3.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/sdb.h>
+#include <dns/result.h>
+
+#include <named/globals.h>
+
+#include "sqlitedb.h"
+
+/*
+ * A simple database driver that interfaces to a SQLite database.
+ *
+ * The table must contain the fields "name", "rdtype", and "rdata", and
+ * is expected to contain a properly constructed zone. The program "zonetodb"
+ * creates such a table.
+ */
+
+static dns_sdbimplementation_t *sqlitedb = NULL;
+
+typedef struct _dbinfo {
+ sqlite3 *db;
+ char *filename;
+ char *table;
+} dbinfo_t;
+
+
+static isc_result_t
+db_connect(dbinfo_t *dbi)
+{
+ if (sqlite3_open(dbi->filename, &dbi->db) == SQLITE_OK) {
+ return (ISC_R_SUCCESS);
+ } else {
+ /* a connection is returned even if the open fails */
+ sqlite3_close(dbi->db);
+ dbi->db = NULL;
+ return (ISC_R_FAILURE);
+ }
+}
+
+
+typedef struct _lookup_parm_t {
+ int i;
+ dns_sdblookup_t *lookup;
+ isc_result_t result;
+} lookup_parm_t;
+
+
+static int
+sqlitedb_lookup_cb(void *p, int cc, char **cv, char **cn)
+{
+ lookup_parm_t *parm = p;
+ dns_ttl_t ttl;
+ char *endp;
+
+ /* FIXME - check these(num/names); I'm assuming a mapping for now */
+ char *ttlstr = cv[0];
+ char *type = cv[1];
+ char *data = cv[2];
+
+ UNUSED(cc);
+ UNUSED(cn);
+
+ ttl = strtol(ttlstr, &endp, 10);
+ if (*endp) {
+ parm->result = DNS_R_BADTTL;
+ return 1;
+ }
+
+ parm->result = dns_sdb_putrr(parm->lookup, type, ttl, data);
+
+ if (parm->result != ISC_R_SUCCESS)
+ return 1;
+
+ (parm->i)++;
+
+ return 0;
+}
+
+
+static isc_result_t
+sqlitedb_lookup(const char *zone,
+ const char *name, void *dbdata,
+ dns_sdblookup_t *lookup)
+/*
+ * synchronous absolute name lookup
+ */
+{
+ dbinfo_t *dbi = (dbinfo_t *) dbdata;
+ char *sql;
+ lookup_parm_t parm = { 0, lookup, ISC_R_SUCCESS };
+ char *errmsg = NULL;
+ int result;
+
+ UNUSED(zone);
+
+ sql = sqlite3_mprintf(
+ "SELECT TTL,RDTYPE,RDATA FROM \"%q\" WHERE "
+ "lower(NAME) = lower('%q')",
+ dbi->table, name);
+
+ result = sqlite3_exec(dbi->db, sql,
+ &sqlitedb_lookup_cb, &parm,
+ &errmsg);
+ sqlite3_free(sql);
+
+ if (result != SQLITE_OK)
+ return (ISC_R_FAILURE);
+ if (parm.i == 0)
+ return (ISC_R_NOTFOUND);
+
+ return (ISC_R_SUCCESS);
+}
+
+
+typedef struct _allnodes_parm_t {
+ int i;
+ dns_sdballnodes_t *allnodes;
+ isc_result_t result;
+} allnodes_parm_t;
+
+
+static int
+sqlitedb_allnodes_cb(void *p, int cc, char **cv, char **cn)
+{
+ allnodes_parm_t *parm = p;
+ dns_ttl_t ttl;
+ char *endp;
+
+ /* FIXME - check these(num/names); I'm assuming a mapping for now */
+ char *ttlstr = cv[0];
+ char *name = cv[1];
+ char *type = cv[2];
+ char *data = cv[3];
+
+ UNUSED(cc);
+ UNUSED(cn);
+
+ ttl = strtol(ttlstr, &endp, 10);
+ if (*endp) {
+ parm->result = DNS_R_BADTTL;
+ return 1;
+ }
+
+ parm->result = dns_sdb_putnamedrr(parm->allnodes, name, type, ttl, data);
+
+ if (parm->result != ISC_R_SUCCESS)
+ return 1;
+
+ (parm->i)++;
+
+ return 0;
+}
+
+
+static isc_result_t
+sqlitedb_allnodes(const char *zone,
+ void *dbdata,
+ dns_sdballnodes_t *allnodes)
+{
+ dbinfo_t *dbi = (dbinfo_t *) dbdata;
+ char *sql;
+ allnodes_parm_t parm = { 0, allnodes, ISC_R_SUCCESS };
+ char *errmsg = NULL;
+ int result;
+
+ UNUSED(zone);
+
+ sql = sqlite3_mprintf(
+ "SELECT TTL,NAME,RDTYPE,RDATA FROM \"%q\" ORDER BY NAME",
+ dbi->table);
+
+ result = sqlite3_exec(dbi->db, sql,
+ &sqlitedb_allnodes_cb, &parm,
+ &errmsg);
+ sqlite3_free(sql);
+
+ if (result != SQLITE_OK)
+ return (ISC_R_FAILURE);
+ if (parm.i == 0)
+ return (ISC_R_NOTFOUND);
+
+ return (ISC_R_SUCCESS);
+}
+
+
+static void
+sqlitedb_destroy(const char *zone, void *driverdata, void **dbdata)
+{
+ dbinfo_t *dbi = *dbdata;
+
+ UNUSED(zone);
+ UNUSED(driverdata);
+
+ if (dbi->db != NULL)
+ sqlite3_close(dbi->db);
+ if (dbi->table != NULL)
+ isc_mem_free(ns_g_mctx, dbi->table);
+ if (dbi->filename != NULL)
+ isc_mem_free(ns_g_mctx, dbi->filename);
+
+ isc_mem_put(ns_g_mctx, dbi, sizeof(dbinfo_t));
+}
+
+
+#define STRDUP_OR_FAIL(target, source) \
+ do { \
+ target = isc_mem_strdup(ns_g_mctx, source); \
+ if (target == NULL) { \
+ result = ISC_R_NOMEMORY; \
+ goto cleanup; \
+ } \
+ } while (0);
+
+/*
+ * Create a connection to the database and save any necessary information
+ * in dbdata.
+ *
+ * argv[0] is the name of the database file
+ * argv[1] is the name of the table
+ */
+static isc_result_t
+sqlitedb_create(const char *zone,
+ int argc, char **argv,
+ void *driverdata, void **dbdata)
+{
+ dbinfo_t *dbi;
+ isc_result_t result;
+
+ UNUSED(zone);
+ UNUSED(driverdata);
+
+ if (argc < 2)
+ return (ISC_R_FAILURE);
+
+ dbi = isc_mem_get(ns_g_mctx, sizeof(dbinfo_t));
+ if (dbi == NULL)
+ return (ISC_R_NOMEMORY);
+ dbi->db = NULL;
+ dbi->filename = NULL;
+ dbi->table = NULL;
+
+ STRDUP_OR_FAIL(dbi->filename, argv[0]);
+ STRDUP_OR_FAIL(dbi->table, argv[1]);
+
+ result = db_connect(dbi);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ *dbdata = dbi;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ sqlitedb_destroy(zone, driverdata, (void **)&dbi);
+ return (result);
+}
+
+
+/*
+ * Since the SQL database corresponds to a zone, the authority data should
+ * be returned by the lookup() function. Therefore the authority() function
+ * is NULL.
+ */
+static dns_sdbmethods_t sqlitedb_methods = {
+ sqlitedb_lookup,
+ NULL, /* authority */
+ sqlitedb_allnodes,
+ sqlitedb_create,
+ sqlitedb_destroy
+};
+
+
+/*
+ * Wrapper around dns_sdb_register().
+ */
+isc_result_t
+sqlitedb_init(void)
+{
+ unsigned int flags;
+ flags = 0;
+ return (dns_sdb_register("sqlite", &sqlitedb_methods, NULL, flags,
+ ns_g_mctx, &sqlitedb));
+}
+
+
+/*
+ * Wrapper around dns_sdb_unregister().
+ */
+void
+sqlitedb_clear(void)
+{
+ if (sqlitedb != NULL)
+ dns_sdb_unregister(&sqlitedb);
+}
diff --git a/contrib/sdb/sqlite/sqlitedb.h b/contrib/sdb/sqlite/sqlitedb.h
new file mode 100644
index 0000000..5d22d0e
--- /dev/null
+++ b/contrib/sdb/sqlite/sqlitedb.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2000-2002 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: sqlitedb.h,v 1.1 2007/03/05 05:30:22 marka Exp $ */
+
+#include <isc/types.h>
+
+isc_result_t sqlitedb_init(void);
+
+void sqlitedb_clear(void);
+
diff --git a/contrib/sdb/sqlite/zone2sqlite.c b/contrib/sdb/sqlite/zone2sqlite.c
new file mode 100644
index 0000000..abaf52b
--- /dev/null
+++ b/contrib/sdb/sqlite/zone2sqlite.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2007 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: zone2sqlite.c,v 1.2 2008/09/24 02:46:21 marka Exp $ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+
+#include <sqlite3.h>
+
+#ifndef UNUSED
+#define UNUSED(x) (x) = (x)
+#endif
+
+/*
+ * Generate an SQLite table from a zone.
+ */
+
+typedef struct _dbinfo {
+ sqlite3 *db;
+ char *filename;
+ char *table;
+} dbinfo_t;
+
+dbinfo_t dbi = { NULL, NULL, NULL };
+
+
+static void
+closeandexit(int status)
+{
+ if (dbi.db) {
+ sqlite3_close(dbi.db);
+ dbi.db = NULL;
+ }
+ exit(status);
+}
+
+static void
+check_result(isc_result_t result, const char *message)
+{
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "%s: %s\n", message,
+ isc_result_totext(result));
+ closeandexit(1);
+ }
+}
+
+static isc_result_t
+db_connect(dbinfo_t *dbi)
+{
+ if (sqlite3_open(dbi->filename, &dbi->db) == SQLITE_OK) {
+ return (ISC_R_SUCCESS);
+ } else {
+ /* a connection is returned even if the open fails */
+ sqlite3_close(dbi->db);
+ dbi->db = NULL;
+ return (ISC_R_FAILURE);
+ }
+}
+
+static int
+add_rdata_cb(void *parm, int cc, char **cv, char **cn)
+{
+ UNUSED(parm);
+ UNUSED(cc);
+ UNUSED(cv);
+ UNUSED(cn);
+
+ return 0;
+}
+
+
+static void
+addrdata(dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
+{
+ unsigned char namearray[DNS_NAME_MAXTEXT + 1];
+ unsigned char typearray[20];
+ unsigned char dataarray[2048];
+ isc_buffer_t b;
+ isc_result_t result;
+ char *sql;
+ char *errmsg = NULL;
+ int res;
+
+ isc_buffer_init(&b, namearray, sizeof(namearray) - 1);
+ result = dns_name_totext(name, ISC_TRUE, &b);
+ check_result(result, "dns_name_totext");
+ namearray[isc_buffer_usedlength(&b)] = 0;
+
+ isc_buffer_init(&b, typearray, sizeof(typearray) - 1);
+ result = dns_rdatatype_totext(rdata->type, &b);
+ check_result(result, "dns_rdatatype_totext");
+ typearray[isc_buffer_usedlength(&b)] = 0;
+
+ isc_buffer_init(&b, dataarray, sizeof(dataarray) - 1);
+ result = dns_rdata_totext(rdata, NULL, &b);
+ check_result(result, "dns_rdata_totext");
+ dataarray[isc_buffer_usedlength(&b)] = 0;
+
+ sql = sqlite3_mprintf(
+ "INSERT INTO %q (NAME, TTL, RDTYPE, RDATA)"
+ " VALUES ('%q', %d, '%q', '%q') ",
+ dbi.table,
+ namearray, ttl, typearray, dataarray);
+ printf("%s\n", sql);
+ res = sqlite3_exec(dbi.db, sql, add_rdata_cb, NULL, &errmsg);
+ sqlite3_free(sql);
+
+ if (result != SQLITE_OK) {
+ fprintf(stderr, "INSERT failed: %s\n", errmsg);
+ closeandexit(1);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *sql;
+ int res;
+ char *errmsg = NULL;
+ char *porigin, *zonefile;
+ dns_fixedname_t forigin, fname;
+ dns_name_t *origin, *name;
+ dns_db_t *db = NULL;
+ dns_dbiterator_t *dbiter;
+ dns_dbnode_t *node;
+ dns_rdatasetiter_t *rdsiter;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_mem_t *mctx = NULL;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ if (argc != 5) {
+ printf("usage: %s <zone> <zonefile> <dbfile> <dbtable>\n", argv[0]);
+ exit(1);
+ }
+
+ porigin = argv[1];
+ zonefile = argv[2];
+
+ dbi.filename = argv[3];
+ dbi.table = argv[4];
+
+ dns_result_register();
+
+ mctx = NULL;
+ result = isc_mem_create(0, 0, &mctx);
+ check_result(result, "isc_mem_create");
+
+ isc_buffer_init(&b, porigin, strlen(porigin));
+ isc_buffer_add(&b, strlen(porigin));
+ dns_fixedname_init(&forigin);
+ origin = dns_fixedname_name(&forigin);
+ result = dns_name_fromtext(origin, &b, dns_rootname, ISC_FALSE, NULL);
+ check_result(result, "dns_name_fromtext");
+
+ db = NULL;
+ result = dns_db_create(mctx, "rbt", origin, dns_dbtype_zone,
+ dns_rdataclass_in, 0, NULL, &db);
+ check_result(result, "dns_db_create");
+
+ result = dns_db_load(db, zonefile);
+ if (result == DNS_R_SEENINCLUDE)
+ result = ISC_R_SUCCESS;
+ check_result(result, "dns_db_load");
+
+ printf("Connecting to '%s'\n", dbi.filename);
+
+ if ((result = db_connect(&dbi)) != ISC_R_SUCCESS) {
+ fprintf(stderr, "Connection to database '%s' failed\n",
+ dbi.filename);
+ closeandexit(1);
+ }
+
+ sql = sqlite3_mprintf("DROP TABLE %q ", dbi.table);
+ printf("%s\n", sql);
+ res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
+ sqlite3_free(sql);
+#if 0
+ if (res != SQLITE_OK) {
+ fprintf(stderr, "DROP TABLE %s failed: %s\n",
+ dbi.table, errmsg);
+ }
+#endif
+
+#if 0
+ sql = sqlite3_mprintf(sql, "BEGIN TRANSACTION");
+ printf("%s\n", sql);
+ res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
+ sqlite3_free(sql);
+ if (res != SQLITE_OK) {
+ fprintf(stderr, "BEGIN TRANSACTION failed: %s\n", errmsg);
+ closeandexit(1);
+ }
+#endif
+
+ sql = sqlite3_mprintf(
+ "CREATE TABLE %q "
+ "(NAME TEXT, TTL INTEGER, RDTYPE TEXT, RDATA TEXT) ",
+ dbi.table);
+ printf("%s\n", sql);
+ res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
+ sqlite3_free(sql);
+ if (res != SQLITE_OK) {
+ fprintf(stderr, "CREATE TABLE %s failed: %s\n",
+ dbi.table, errmsg);
+ closeandexit(1);
+ }
+
+ dbiter = NULL;
+ result = dns_db_createiterator(db, 0, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ result = dns_dbiterator_first(dbiter);
+ check_result(result, "dns_dbiterator_first");
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_rdataset_init(&rdataset);
+ dns_rdata_init(&rdata);
+
+ while (result == ISC_R_SUCCESS) {
+ node = NULL;
+ result = dns_dbiterator_current(dbiter, &node, name);
+ if (result == ISC_R_NOMORE)
+ break;
+ check_result(result, "dns_dbiterator_current");
+
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, NULL, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets");
+
+ result = dns_rdatasetiter_first(rdsiter);
+
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ result = dns_rdataset_first(&rdataset);
+ check_result(result, "dns_rdataset_first");
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&rdataset, &rdata);
+ addrdata(name, rdataset.ttl, &rdata);
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&rdataset);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+ dns_rdatasetiter_destroy(&rdsiter);
+ dns_db_detachnode(db, &node);
+ result = dns_dbiterator_next(dbiter);
+ }
+
+#if 0
+ sql = sqlite3_mprintf(sql, "COMMIT TRANSACTION ");
+ printf("%s\n", sql);
+ res = sqlite3_exec(dbi.db, sql, NULL, NULL, &errmsg);
+ sqlite3_free(sql);
+ if (res != SQLITE_OK) {
+ fprintf(stderr, "COMMIT TRANSACTION failed: %s\n", errmsg);
+ closeandexit(1);
+ }
+#endif
+
+ dns_dbiterator_destroy(&dbiter);
+ dns_db_detach(&db);
+ isc_mem_destroy(&mctx);
+
+ closeandexit(0);
+
+ exit(0);
+}
diff --git a/contrib/sdb/tcl/lookup.tcl b/contrib/sdb/tcl/lookup.tcl
new file mode 100644
index 0000000..83a8e2a
--- /dev/null
+++ b/contrib/sdb/tcl/lookup.tcl
@@ -0,0 +1,51 @@
+# Copyright (C) 2004, 2007 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: lookup.tcl,v 1.10 2007/06/19 23:47:08 tbox Exp $
+
+#
+# Sample lookup procedure for tcldb
+#
+# This lookup procedure defines zones with identical SOA, NS, and MX
+# records at the apex and a single A record that varies from zone to
+# zone at the name "www".
+#
+# Something like this could be used by a web hosting company to serve
+# a number of domains without needing to create a separate master file
+# for each domain. Instead, all per-zone data (in this case, a single
+# IP address) specified in the named.conf file like this:
+#
+# zone "a.com." { type master; database "tcl 10.0.0.42"; };
+# zone "b.com." { type master; database "tcl 10.0.0.99"; };
+#
+# Since the tcldb driver doesn't support zone transfers, there should
+# be at least two identically configured master servers. In the
+# example below, they are assumed to be called ns1.isp.nil and
+# ns2.isp.nil.
+#
+
+proc lookup {zone name} {
+ global dbargs
+ switch -- $name {
+ @ { return [list \
+ {SOA 86400 "ns1.isp.nil. hostmaster.isp.nil. \
+ 1 3600 1800 1814400 3600"} \
+ {NS 86400 "ns1.isp.nil."} \
+ {NS 86400 "ns2.isp.nil."} \
+ {MX 86400 "10 mail.isp.nil."} ] }
+ www { return [list [list A 3600 $dbargs($zone)] ] }
+ }
+ return NXDOMAIN
+}
diff --git a/contrib/sdb/tcl/tcldb.c b/contrib/sdb/tcl/tcldb.c
new file mode 100644
index 0000000..de6f4c5
--- /dev/null
+++ b/contrib/sdb/tcl/tcldb.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2004, 2007 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: tcldb.c,v 1.10 2007/06/19 23:47:10 tbox Exp $ */
+
+/*
+ * A simple database driver that calls a Tcl procedure to define
+ * the contents of the DNS namespace. The procedure is loaded
+ * from the file lookup.tcl; look at the comments there for
+ * more information.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/log.h>
+#include <dns/sdb.h>
+
+#include <named/globals.h>
+
+#include <tcl.h>
+
+#include <tcldb.h>
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) return (result); \
+ } while (0)
+
+typedef struct tcldb_driver {
+ isc_mem_t *mctx;
+ Tcl_Interp *interp;
+} tcldb_driver_t;
+
+static tcldb_driver_t *the_driver = NULL;
+
+static dns_sdbimplementation_t *tcldb = NULL;
+
+static isc_result_t
+tcldb_driver_create(isc_mem_t *mctx, tcldb_driver_t **driverp) {
+ int tclres;
+ isc_result_t result = ISC_R_SUCCESS;
+ tcldb_driver_t *driver = isc_mem_get(mctx, sizeof(tcldb_driver_t));
+ if (driver == NULL)
+ return (ISC_R_NOMEMORY);
+ driver->mctx = mctx;
+ driver->interp = Tcl_CreateInterp();
+
+ tclres = Tcl_EvalFile(driver->interp, (char *) "lookup.tcl");
+ if (tclres != TCL_OK) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
+ "initializing tcldb: "
+ "loading 'lookup.tcl' failed: %s",
+ driver->interp->result);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ *driverp = driver;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_mem_put(mctx, driver, sizeof(tcldb_driver_t));
+ return (result);
+
+}
+
+static void
+tcldb_driver_destroy(tcldb_driver_t **driverp) {
+ tcldb_driver_t *driver = *driverp;
+ Tcl_DeleteInterp(driver->interp);
+ isc_mem_put(driver->mctx, driver, sizeof(tcldb_driver_t));
+}
+
+/*
+ * Perform a lookup, by invoking the Tcl procedure "lookup".
+ */
+static isc_result_t
+tcldb_lookup(const char *zone, const char *name, void *dbdata,
+ dns_sdblookup_t *lookup)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ int tclres;
+ int rrc; /* RR count */
+ char **rrv; /* RR vector */
+ int i;
+ char *cmdv[3];
+ char *cmd;
+
+ tcldb_driver_t *driver = (tcldb_driver_t *) dbdata;
+
+ cmdv[0] = "lookup";
+ cmdv[1] = zone;
+ cmdv[2] = name;
+ cmd = Tcl_Merge(3, cmdv);
+ tclres = Tcl_Eval(driver->interp, cmd);
+ Tcl_Free(cmd);
+
+ if (tclres != TCL_OK) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
+ "zone '%s': tcl lookup function failed: %s",
+ zone, driver->interp->result);
+ return (ISC_R_FAILURE);
+ }
+
+ if (strcmp(driver->interp->result, "NXDOMAIN") == 0) {
+ result = ISC_R_NOTFOUND;
+ goto fail;
+ }
+
+ tclres = Tcl_SplitList(driver->interp, driver->interp->result,
+ &rrc, &rrv);
+ if (tclres != TCL_OK)
+ goto malformed;
+
+ for (i = 0; i < rrc; i++) {
+ isc_result_t tmpres;
+ int fieldc; /* Field count */
+ char **fieldv; /* Field vector */
+ tclres = Tcl_SplitList(driver->interp, rrv[i],
+ &fieldc, &fieldv);
+ if (tclres != TCL_OK) {
+ tmpres = ISC_R_FAILURE;
+ goto failrr;
+ }
+ if (fieldc != 3)
+ goto malformed;
+ tmpres = dns_sdb_putrr(lookup, fieldv[0], atoi(fieldv[1]),
+ fieldv[2]);
+ Tcl_Free((char *) fieldv);
+ failrr:
+ if (tmpres != ISC_R_SUCCESS)
+ result = tmpres;
+ }
+ Tcl_Free((char *) rrv);
+ if (result == ISC_R_SUCCESS)
+ return (result);
+
+ malformed:
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
+ "zone '%s': "
+ "malformed return value from tcl lookup function: %s",
+ zone, driver->interp->result);
+ result = ISC_R_FAILURE;
+ fail:
+ return (result);
+}
+
+/*
+ * Set up per-zone state. In our case, the database arguments of the
+ * zone are collected into a Tcl list and assigned to an element of
+ * the global array "dbargs".
+ */
+static isc_result_t
+tcldb_create(const char *zone, int argc, char **argv,
+ void *driverdata, void **dbdata)
+{
+ tcldb_driver_t *driver = (tcldb_driver_t *) driverdata;
+
+ char *list = Tcl_Merge(argc, argv);
+
+ Tcl_SetVar2(driver->interp, (char *) "dbargs", (char *) zone, list, 0);
+
+ Tcl_Free(list);
+
+ *dbdata = driverdata;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This driver does not support zone transfer, so allnodes() is NULL.
+ */
+static dns_sdbmethods_t tcldb_methods = {
+ tcldb_lookup,
+ NULL, /* authority */
+ NULL, /* allnodes */
+ tcldb_create,
+ NULL /* destroy */
+};
+
+/*
+ * Initialize the tcldb driver.
+ */
+isc_result_t
+tcldb_init(void) {
+ isc_result_t result;
+ int flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA;
+
+ result = tcldb_driver_create(ns_g_mctx, &the_driver);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ return (dns_sdb_register("tcl", &tcldb_methods, the_driver, flags,
+ ns_g_mctx, &tcldb));
+}
+
+/*
+ * Wrapper around dns_sdb_unregister().
+ */
+void
+tcldb_clear(void) {
+ if (tcldb != NULL)
+ dns_sdb_unregister(&tcldb);
+ if (the_driver != NULL)
+ tcldb_driver_destroy(&the_driver);
+}
diff --git a/contrib/sdb/tcl/tcldb.h b/contrib/sdb/tcl/tcldb.h
new file mode 100644
index 0000000..f31639b
--- /dev/null
+++ b/contrib/sdb/tcl/tcldb.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004, 2007 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: tcldb.h,v 1.7 2007/06/19 23:47:10 tbox Exp $ */
+
+#include <isc/types.h>
+
+isc_result_t tcldb_init(void);
+
+void tcldb_clear(void);
+
diff --git a/contrib/sdb/time/timedb.c b/contrib/sdb/time/timedb.c
new file mode 100644
index 0000000..f6ddaa4
--- /dev/null
+++ b/contrib/sdb/time/timedb.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2004, 2007 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: timedb.c,v 1.10 2007/06/19 23:47:10 tbox Exp $ */
+
+/*
+ * A simple database driver that enables the server to return the
+ * current time in a DNS record.
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include <dns/sdb.h>
+
+#include <named/globals.h>
+
+#include "timedb.h"
+
+static dns_sdbimplementation_t *timedb = NULL;
+
+/*
+ * This database operates on relative names.
+ *
+ * "time" and "@" return the time in a TXT record.
+ * "clock" is a CNAME to "time"
+ * "current" is a DNAME to "@" (try time.current.time)
+ */
+static isc_result_t
+timedb_lookup(const char *zone, const char *name, void *dbdata,
+ dns_sdblookup_t *lookup)
+{
+ isc_result_t result;
+
+ UNUSED(zone);
+ UNUSED(dbdata);
+
+ if (strcmp(name, "@") == 0 || strcmp(name, "time") == 0) {
+ time_t now = time(NULL);
+ char buf[100];
+ int n;
+
+ /*
+ * Call ctime to create the string, put it in quotes, and
+ * remove the trailing newline.
+ */
+ n = snprintf(buf, sizeof(buf), "\"%s", ctime(&now));
+ if (n < 0)
+ return (ISC_R_FAILURE);
+ buf[n - 1] = '\"';
+ result = dns_sdb_putrr(lookup, "txt", 1, buf);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+ } else if (strcmp(name, "clock") == 0) {
+ result = dns_sdb_putrr(lookup, "cname", 1, "time");
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+ } else if (strcmp(name, "current") == 0) {
+ result = dns_sdb_putrr(lookup, "dname", 1, "@");
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+ } else
+ return (ISC_R_NOTFOUND);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * lookup() does not return SOA or NS records, so authority() must be defined.
+ */
+static isc_result_t
+timedb_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
+ isc_result_t result;
+
+ UNUSED(zone);
+ UNUSED(dbdata);
+
+ result = dns_sdb_putsoa(lookup, "localhost.", "root.localhost.", 0);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+
+ result = dns_sdb_putrr(lookup, "ns", 86400, "ns1.localdomain.");
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+ result = dns_sdb_putrr(lookup, "ns", 86400, "ns2.localdomain.");
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This zone does not support zone transfer, so allnodes() is NULL. There
+ * is no database specific data, so create() and destroy() are NULL.
+ */
+static dns_sdbmethods_t timedb_methods = {
+ timedb_lookup,
+ timedb_authority,
+ NULL, /* allnodes */
+ NULL, /* create */
+ NULL /* destroy */
+};
+
+/*
+ * Wrapper around dns_sdb_register().
+ */
+isc_result_t
+timedb_init(void) {
+ unsigned int flags;
+ flags = DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA;
+ return (dns_sdb_register("time", &timedb_methods, NULL, flags,
+ ns_g_mctx, &timedb));
+}
+
+/*
+ * Wrapper around dns_sdb_unregister().
+ */
+void
+timedb_clear(void) {
+ if (timedb != NULL)
+ dns_sdb_unregister(&timedb);
+}
diff --git a/contrib/sdb/time/timedb.h b/contrib/sdb/time/timedb.h
new file mode 100644
index 0000000..ca8688a
--- /dev/null
+++ b/contrib/sdb/time/timedb.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004, 2007 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: timedb.h,v 1.5 2007/06/19 23:47:13 tbox Exp $ */
+
+#include <isc/types.h>
+
+isc_result_t timedb_init(void);
+
+void timedb_clear(void);
+
diff --git a/contrib/zkt/CHANGELOG b/contrib/zkt/CHANGELOG
new file mode 100644
index 0000000..40fb02e
--- /dev/null
+++ b/contrib/zkt/CHANGELOG
@@ -0,0 +1,446 @@
+zkt 0.97 --
+
+* bug LG_* logging level wasn't mapped to syslog level in lg_mesg().
+ gettock() in ncparse.c did not recognize C single line comments "//"
+ (Thanks to Frank Behrens for finding this out)
+
+* misc dist_and_reload () now calls the "Distribute_Cmd" twice:
+ First with argument "distribute" for signed zone file distribution,
+ second with argument "reload" to initiate a reload.
+ Again see example/flat/dist.sh for an example script.
+
+* bug full KSK rollover will (mostly) also work for dynamic zones
+ This is a hack and requires further investigation. Currently
+ it will not work if someone is using non standard zone file
+ names.
+
+* misc default ZSK lifetime set to 3 month
+
+* misc get_mtime() renamed to file_mtime()
+
+* func is_exec_ok() added and called in dist_and_reload ()
+
+* func New parameter "Distribute_Cmd" added for specifing a user
+ defined distribution (and reload) command (See example/flat/dist.sh).
+
+* misc Changed wording to be a bit more consistent to
+ draft-gudmundsson-life-of-dnskey-00.txt
+ - State of published key will be print as "pub" instead of "pre"
+ by dnssec-zkt.
+ - Option --pre-publish of dnssec-zkt changed to --published.
+ - Changed wording in all comments and log message from "pre-publish"
+ to "published".
+
+* func Highly experimental code to do a full automatic ksk rollover
+ in hierachical mode.
+ ksk_rollover() added in rollover.c; parameter change for ksk_status()
+
+* misc Changed name of "dnssec-soaserial" to "zkt-soaserial"
+
+* bug Fixed verbose logging error if -N or -D option was used
+
+* func Some LG_INFO messages added about key status change
+
+* func Remove of function to register a new ksk (zktr.[ch])
+
+* misc Changed licence from GNU GPLv2 to BSD licence
+
+* bug Fixed bug in logging of ZSK rollover
+
+* misc Changed tar file to zipped one and archive the files with
+ toplevel directory
+
+* bug Fixed use of uninitialized vars in zconf.c (line)
+
+* port Preparation for use of autoconf
+ - config.h renamed to config_zkt.h and change of include directives
+ - conditional include of config.h
+ - ./configure script is able to determine BIND utility path
+ (BIND_UTIL_PATH) and version (BIND_VERSION)
+ - compile time options are settable via configure script (--enable-xxx)
+ - For now, the configure script is not able to set the install dir.
+
+* bug ksk rollover phase2 did not trigger resigning of parent
+ (the parent file was copied to the parent directory only
+ after child zone resigning)
+
+* bug fixed bad notice message in zskstatus ()
+
+* func dnssec-zkt -Z print out syslog facility & level with
+ upper case letter and without quotation marks
+
+* func Syslog facility DAEMON added
+
+zkt 0.96 -- 19. June 2008
+
+* func Config file option "SIG_Parameter" added.
+
+* func Function verbmesg() added and used for verbose logging
+ to stdout and/or to syslog resp. file.
+ Config file parameter VerboseLog added to config file.
+
+* bug Option -O wasn't recognized by dnssec-signer
+
+* func Better support of initial setup of dynamic signed
+ zones (just create an empty "zone.db.dsigned" file
+ and run dnssec-signer with option -d).
+
+* func Improved error logging; incr_soa() errors are written
+ as clear text message instead of error number
+
+* func elog_mesg() function replaced by a more general
+ logging mechanism.
+ ErrorLog config parameter replaced by LogFile,
+ LogLevel and SyslogFacility, SyslogLevel parameter
+
+* func New function filesize() added
+
+* func dki_prt_trustedkey print out old key id if key
+ is revoked
+
+* func dki_new() writes gentime (GMT) and proposed key
+ lifetime (days) as comment into the *.key file
+
+* bug Doing some housekeeping
+
+zkt 0.95 -- 19. April 2008
+
+* misc This is not a public released version of zkt.
+
+* func All config file option are now settable via
+ commandline option -O (--option or --config-option)
+
+* misc Function fatal() now has an exit code of 127.
+ This is neccessary because values from 1 to 64 are
+ reflecting the number of errors occured.
+
+* func Errorlog functionality added
+ All dnssec-signer errors will be logged in the file
+ specified by the Errorlog config file parameter or
+ specified by the command line option -L (--errorlog).
+ If a directory is given, then the logging will occur
+ in a file within this directory which is named
+ like "zkt-<current-date>.log".
+ The dnssec-signer command has an exit code of 0 if
+ no error occured, an exit code of 127 on fatal errors,
+ an exit code from 1 to 63 reflecting the number of errors
+ occured, or an exit code of 64 if more than 63 errors
+ occured.
+
+* func dnssec-signer: Introducing long options
+
+* bug New skript added to example/views directory to
+ read in the right config file
+
+* func New option -f (--lifetime) and -F (--setlifetime)
+ added to dnssec-zkt.
+
+* func New option -e (--expire) added to dnssec-zkt.
+ (Seems to be that the dnssec-zkt command is a little
+ bit overloaded with options.)
+
+* func dki.c and zkt.c supports storage of key lifetime,
+ generation time and expiration time as a comment in the
+ .key file. With this, it's possible to change the default
+ lifetime without any impact on already used keys.
+
+zkt 0.94 -- 6. Dec 2007
+
+* bug Case mismatch of zone name and key file name prevent
+ dki_read() from reading the key.
+ Thanks to Alan Clegg for finding this out.
+ Added some additional error processing and convert
+ zone name to lower case.
+
+* misc Builtin default for KSK_randfile changed
+ from NULL to "/dev/urandom".
+
+* bug dnssec-signer has to use private keys for signing
+ even if the revoke bit is set.
+ To achieve this the file pattern K*.private is added
+ to the dnssec-signzone run.
+
+* bug Uninitialized variable "len" in sign_zone().
+
+* func Default config file is settable via environment
+ variable ZKT_CONFFILE
+
+* func Support of views added
+ Link dnssec-zkt to dnssec-zkt-<view> and
+ dnssec-signer to dnssec-signer-<view>.
+ Option -V and --view added to dnssec-zkt.
+ Option -V added to dnssec-signer.
+ View support added to parse_namedconf().
+
+zkt 0.93 -- 1. Nov 2007
+
+* func The ksk registration mechanism is disabled by
+ default (see REG_URL in config.h).
+
+* func Basic support for revoke flag added (RFC5011).
+ Semantic of option -R of dnssec-zkt changed.
+
+* func Undocumented option -S changed to lower case.
+ Pre-pulished KSK will be shown as "standby" key.
+ New Option -S (standby) for pre-publish KSK.
+
+* func New command dnssec-soaserial added.
+
+* bug dnssec-signer do not print the incremented serial
+ number anymore.
+ time2str() fixed bug in time format (HAS_STRFTIME=0).
+
+* port New build dependencies "solaris", "macos" and "help"
+ added to Makefile.
+
+zkt 0.92 -- 1. Oct 2007
+
+* func Parameter "Serialformat" in dnssec.conf added .
+ Now it is possible to use the unixtime format for
+ the SOA serial number. If you use BIND 9.4 or
+ greater in conjunction with this, than there is no
+ need for the special SOA serial formating in
+ the zonefile. (Thanks to Jakob Schlyter for the
+ -N option of dnssec-signzone and the suggestion to
+ add the unixtime support to zkt)
+
+* func Option --ksk-roll-stat added.
+
+* port Added macro HAS_GETOPT_LONG to support OS with
+ lack of getopt_long() (e.g. solaris).
+ Options -[01239] added.
+
+* misc Unused macro HAS_ULONG removed from config.h.
+ Deklaration of unsigned types moved from dki.h to
+ config.h (so it will be available in _all_ source
+ files). Thanks to Mans Nilsson.
+ Unused macro isblank() (ncparse.c) removed.
+
+* bug In dosigning(): freeze the dynamic zone _before_ copying
+ the zone file.
+
+zkt 0.91 -- 1. Apr 2007
+
+* doc --ksk-rollover option added to usage().
+
+* func some experimental code for dynamic zones added.
+ new functions added: copyzonefile(), dyn_update_freeze().
+ New option "-d" added.
+
+zkt 0.90 -- 6. Dec 2006
+
+* func CHECK_RESIGN interval added to config.h.
+ This is the dnssec-signer calling interval (at least 1 day or 86400 sec).
+
+* func new function dki_destroy() added; semantic of dk_remove()
+ changed to rename the key files instead of physical deletion.
+
+* doc Setup of new example directory (flat and hierarchical).
+
+* doc dnssec-zkt man page updated.
+ Added some comments in misc.c
+
+* misc function strtaint() renamed to str_untaint(),
+ dki_keycmp() renamed to dki_tagcmp().
+
+* func New parameter key_ttl added to dnssec.conf.
+ New func dki_prt_dnskeyttl () added.
+ Now dnskey.db is written with key_ttl value.
+
+* func dnssec-signer: In hierarchical mode sign_zone() copies the
+ parent-file (if such a file exist) instead of the
+ keyset-file to the parent directory.
+
+* func dnssec-zkt: Option --ksk-roll-phase[123] and function
+ ksk_rollover() added.
+
+* misc zconf: default values for sigvalidity, resign_int etc. changed,
+ new dnssec.conf example file created.
+
+* func dnssec-zkt: Long option support added.
+
+zkt 0.83 -- 11. Sep 2006
+
+* bug dosigning(): Fixed bug in the bug fixing of printing undefined
+ serial number if incr_serial() failed. (Thanks to Randy McCasskill).
+
+zkt 0.82 -- 8. Sep 2006
+
+* bug Use option -e for dnssec-keygen calls in dki_new(), because
+ an RSA exponent of 3 is vulnerable.
+
+* bug dosigning(): Fixed bug in printing undefined serial
+ number if incr_serial() failed.
+
+ an RSA exponent of 3 is vulnerable.
+
+* bug dosigning(): Fixed bug in printing undefined serial
+ number if incr_serial() failed.
+
+zkt 0.81 -- 13. July 2006
+
+* bug The function ceatekey() won't work with USE_TREE.
+ Size of MAX_DNAME increased.
+
+zkt 0.8 -- 09. July 2006
+
+* func Now a hierarchical directory structure with subdomains stored in
+ subfolders of the parent domain are allowed. Added copyfile(),
+ cmpfile() and new_keysetfiles() for that.
+
+* func Config parameter added to choose if the domain name is
+ right or left justified listed by dnssec-zkt (printkeyinfo).
+
+* func New class of key added ("sep"). A SEP key is a (public) key file
+ without the private counterpart. So we could use the key solely
+ as an secure entry point. (dki.h, dki_read).
+
+zkt 0.70 -- 15. Sep 2005
+
+* func Experimental code added to use a binary search tree instead of a
+ single linked list. This is mainly for performance improvement for large
+ sites. If you don't want to use it, set USE_TREE in config.h to zero.
+ In the first step only dnssec-zkt use the new data structure.
+ The tree is build over the domain names and each node is the starting point
+ of a linked list of keys.
+ As a result, it's not possible anymore to search on key tags only. You have
+ to specify the domain name plus the tag. :-(
+
+* func Function parseurl added.
+
+* func Experimental code to register a new ksk. Currently it's more like
+ a key announcement because of the lack of identification and
+ authentication.
+
+zkt 0.65 -- 22. Aug 2005
+
+* misc Rewrite of the domaincmp() function. Now it's round about 2 times faster.
+ After some additional changes and the compiler option -O3 the dnssec-zkt
+ on the ~ 12000 zones requires only a minute
+ $ time dnssec-zkt -z -r sec > /dev/null
+ real 0m58.287s
+ user 0m54.610s
+ sys 0m3.680s
+
+* func A keyset directory is introduced (experimental)
+ The parameter -d is added to the call of the dnssec-signzone command
+ if the config option KeySetDir is set.
+ As a result, all dsset-, keyset- and dlvset- files are stored in one directory.
+ The advantage is, that the chain of trust of all local subzone is build
+ automatically (This is the reason why we sort the zones with the child zones
+ first).
+ The disadvantage is that we store many files in single directory (3 files
+ per zone).
+
+zkt 0.64 -- 1. Aug 2005
+
+* bug The code for option -Z of dnssec-zkt should be executed before we read the
+ complete directory tree. This is usefull if we have a very deep directory
+ structure and the recursive flag is switched on.
+
+* func SIG_Pseudorand parameter added.
+
+* func ([KZ]SK)|(SIG)_randfile parameter added.
+
+* func measure the time used for signing of each zone.
+
+* bug function logflush() added to misc.c and called by dosigning().
+
+* misc some perfomance test made:
+ - Directory structure "sec/<firstletter>/domain" with round about 12200 domains
+ - One of the domain is a big one (~ 820000 RRs), the others are mostly very small ones
+ - We use a dsa with 704 bits as ksk and a rsamd5 with 512 bits as zsk on each domain.
+ - All test made on Sun Fire V440 with 4 CPU and 4x2GB main memory
+
+ # sequential signing of all zones
+ $ time dnssec-signer -v -v -f -D sec
+ real 434m (~ 7h 14min)
+ user 188
+ sys 175
+
+ # with option -p and -r /dev/urandom
+ $ time dnssec-signer -v -v -f -D sec > log
+ real 96m28.306s
+ user 290m41.980s
+ sys 6m13.790s
+
+ # one process for each firstletter subdirectory
+ $ time par_signer.sh
+ real 394m12.334s
+ user 295m58.390s
+ sys 786m42.479s
+
+ # with option -p and -r /dev/urandom
+ $ time par_signer.sh
+ real 78m49.323s
+ user 284m58.350s
+ sys 5m39.340s
+
+
+ $ time dnssec-zkt -z -r sec > /dev/null
+ real 2m5.722s
+ user 2m0.060s
+ sys 0m4.510s
+
+
+ # signing the big (820000 RR) domain only
+ $ time dnssec-signer -v -v -f -D sec/b/big-domain
+ real 196m23.165 (~ 3h 16min)
+ user 176m57.610
+ sys 167m27.570
+
+ # with option -p and -r /dev/urandom
+ $ time dnssec-signer -v -v -f -D sec/b/big-domain
+ real 49m53.152
+ user 173m59.520
+ sys 1m40.150
+
+zkt 0.63 -- 14. June 2005
+
+* bug allow TTL value in keyfiles (see TTL_IN_KEYFILES_ALLOWED
+ in dki_readfile()).
+
+* misc function strchop() added to misc.c.
+
+zkt 0.62 -- 13. May 2005
+
+* func dnssec-signer: Option -o added.
+ Now it works a little bit more like dnssec-signzone.
+
+* func strlist.c: prepstrlist and unprepstrlist functions get a
+ second parameter for the delimiter.
+
+* bug fixed some typos and inaccurate usage of symbolic constants.
+ Doing some housekeeping.
+
+zkt 0.61 -- 3. May 2005
+
+* bug local config file will not be mentioned if -N switch is used.
+
+zkt 0.6 -- 1. May 2005
+
+* doc dnssec-signer: man page added.
+
+* func dnssec-signer: Print out a warning message if ksk lifetime is exceeded.
+
+* func dnssec-signer: Remaining arguments will be interpreted as zone names
+ (in_strarr () added).
+
+* func dnssec-signer: Option -D added.
+
+
+zkt 0.51 -- 8. April 2005
+
+* func dnssec-signer: Option -N added.
+
+* func dnssec-signer: change of keystatus from pre-published to active
+ resets timestamp of key, thus age of active key counts 0.
+
+* bug prepstrlist: resulting string was not terminated with '\0'.
+
+* bug dnssec-signer: do signing if there are additional keys, or the
+ status of any key is changed (function check_keytimestamp).
+
+* func dnssec-zkt: -l <list> option added.
+
+* func dnssec-zkt: -p flag defaults to on in key creation mode (-C).
diff --git a/contrib/zkt/LICENSE b/contrib/zkt/LICENSE
new file mode 100644
index 0000000..1af01c7
--- /dev/null
+++ b/contrib/zkt/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2005 - 2008, Holger Zuleger HZnet. All rights reserved.
+
+This software is open source.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/contrib/zkt/Makefile.in b/contrib/zkt/Makefile.in
new file mode 100644
index 0000000..197fd14
--- /dev/null
+++ b/contrib/zkt/Makefile.in
@@ -0,0 +1,151 @@
+#################################################################
+#
+# @(#) Makefile for dnssec zone key tool (c) Mar 2005 hoz
+#
+#################################################################
+
+INSTALL_DIR ?= $$HOME/bin
+
+CC ?= @CC@
+
+PROFILE = # -pg
+OPTIM = # -O3 -DNDEBUG
+
+#CFLAGS ?= @CFLAGS@ @DEFS@ -I@top_srcdir@
+CFLAGS += -g @DEFS@ -I@top_srcdir@
+CFLAGS += -Wall #-DDBG
+CFLAGS += -Wmissing-prototypes
+CFLAGS += $(PROFILE) $(OPTIM)
+LDFLAGS += $(PROFILE)
+
+PROJECT = @PACKAGE_TARNAME@
+VERSION = @PACKAGE_VERSION@
+
+HEADER = dki.h misc.h domaincmp.h zconf.h config_zkt.h \
+ config.h.in strlist.h zone.h zkt.h debug.h \
+ ncparse.h log.h rollover.h
+SRC_ALL = dki.c misc.c domaincmp.c zconf.c log.c
+OBJ_ALL = $(SRC_ALL:.c=.o)
+
+SRC_SIG = dnssec-signer.c zone.c ncparse.c rollover.c
+OBJ_SIG = $(SRC_SIG:.c=.o)
+MAN_SIG = dnssec-signer.8
+PROG_SIG= dnssec-signer
+
+SRC_ZKT = dnssec-zkt.c strlist.c zkt.c
+OBJ_ZKT = $(SRC_ZKT:.c=.o)
+MAN_ZKT = dnssec-zkt.8
+PROG_ZKT= dnssec-zkt
+
+SRC_SER = zkt-soaserial.c
+OBJ_SER = $(SRC_SER:.c=.o)
+#MAN_SER = zkt-soaserial.8
+PROG_SER= zkt-soaserial
+
+MAN = $(MAN_ZKT) $(MAN_SIG) #$(MAN_SER)
+OTHER = README README.logging TODO LICENSE CHANGELOG tags Makefile.in \
+ configure examples
+SAVE = $(HEADER) $(SRC_ALL) $(SRC_SIG) $(SRC_ZKT) $(SRC_SER) $(MAN) $(OTHER)
+MNTSAVE = $(SAVE) configure.ac config.h.in doc
+
+
+all: $(PROG_ZKT) $(PROG_SIG) $(PROG_SER)
+
+macos: ## for MAC OS
+macos:
+ $(MAKE) CFLAGS="$(CFLAGS) -D HAS_UTYPES=0" all
+
+solaris: ## for solaris
+solaris:
+ @$(MAKE) CFLAGS="$(CFLAGS) -D HAVE_GETOPT_LONG=0" all
+
+linux: ## for linux (default)
+linux:
+ @$(MAKE) all
+
+$(PROG_SIG): $(OBJ_SIG) $(OBJ_ALL) Makefile
+ $(CC) $(LDFLAGS) $(OBJ_SIG) $(OBJ_ALL) -o $(PROG_SIG)
+
+$(PROG_ZKT): $(OBJ_ZKT) $(OBJ_ALL) Makefile
+ $(CC) $(LDFLAGS) $(OBJ_ZKT) $(OBJ_ALL) -o $(PROG_ZKT)
+
+$(PROG_SER): $(OBJ_SER) Makefile
+ $(CC) $(LDFLAGS) $(OBJ_SER) -o $(PROG_SER)
+
+install: ## install binaries in INSTALL_DIR
+install: $(PROG_ZKT) $(PROG_SIG) $(PROG_SER)
+ cp $(PROG_ZKT) $(PROG_SIG) $(PROG_SER) $(INSTALL_DIR)
+
+tags: ## create tags file
+tags: $(SRC_ALL) $(SRC_SIG) $(SRC_ZKT) $(SRC_SER)
+ ctags $(SRC_ALL) $(SRC_SIG) $(SRC_ZKT) $(SRC_SER)
+
+clean: ## remove objectfiles and binaries
+clean:
+ rm -f $(OBJ_SIG) $(OBJ_ZKT) $(OBJ_SER) $(OBJ_ALL)
+
+dist: ## create tar file for distribution
+dist: $(PROJECT)-$(VERSION).tar.gz
+tar: ## create tar file for distribution
+tar: $(PROJECT)-$(VERSION).tar.gz
+
+maintain: ## create configure script
+maintain: configure
+
+mainttar: ## create tar file for maintenance
+mainttar: $(PROJECT)-maint-$(VERSION).tar.gz
+
+configure: configure.ac
+ autoconf && autoheader
+
+man: $(MAN_ZKT).html $(MAN_ZKT).pdf $(MAN_SIG).html $(MAN_SIG).pdf
+
+$(MAN_ZKT).html: $(MAN_ZKT)
+ groff -Thtml -man -mhtml $(MAN_ZKT) > $(MAN_ZKT).html
+$(MAN_ZKT).pdf: $(MAN_ZKT)
+ groff -Tps -man $(MAN_ZKT) | ps2pdf - $(MAN_ZKT).pdf
+$(MAN_SIG).html: $(MAN_SIG)
+ groff -Thtml -man -mhtml $(MAN_SIG) > $(MAN_SIG).html
+$(MAN_SIG).pdf: $(MAN_SIG)
+ groff -Tps -man $(MAN_SIG) | ps2pdf - $(MAN_SIG).pdf
+
+
+$(PROJECT)-$(VERSION).tar.gz: $(SAVE)
+ rm -f examples/hierarchical/log/zkt-*
+ ( \
+ distfiles=`ls -d $(SAVE) | sed 's|^|$(PROJECT)-$(VERSION)/|'` ;\
+ cd .. && tar czvf $(PROJECT)-$(VERSION)/$(PROJECT)-$(VERSION).tar.gz $$distfiles ;\
+ )
+
+$(PROJECT)-maint-$(VERSION).tar.gz: $(MNTSAVE)
+ ( \
+ distfiles=`ls -d $(SAVE) | sed 's|^|$(PROJECT)-$(VERSION)/|'` ;\
+ cd .. && tar czvf $(PROJECT)-$(VERSION)/$(PROJECT)-maint-$(VERSION).tar.gz $$distfiles ;\
+ )
+
+depend:
+ $(CC) -MM $(SRC_SIG) $(SRC_ZKT) $(SRC_SER) $(SRC_ALL)
+
+help:
+ @grep "^.*:[ ]*##" Makefile
+
+## all dependicies
+#:r !make depend
+#gcc -MM dnssec-signer.c zone.c ncparse.c rollover.c dnssec-zkt.c strlist.c zkt.c zkt-soaserial.c dki.c misc.c domaincmp.c zconf.c log.c
+dnssec-signer.o: dnssec-signer.c config_zkt.h zconf.h debug.h misc.h \
+ ncparse.h zone.h dki.h rollover.h log.h
+zone.o: zone.c config_zkt.h debug.h domaincmp.h misc.h zconf.h dki.h \
+ zone.h
+ncparse.o: ncparse.c debug.h misc.h zconf.h log.h ncparse.h
+rollover.o: rollover.c config_zkt.h zconf.h debug.h misc.h zone.h dki.h \
+ log.h rollover.h
+dnssec-zkt.o: dnssec-zkt.c config_zkt.h debug.h misc.h zconf.h strlist.h \
+ dki.h zkt.h
+strlist.o: strlist.c strlist.h
+zkt.o: zkt.c config_zkt.h dki.h misc.h zconf.h strlist.h zkt.h
+zkt-soaserial.o: zkt-soaserial.c config_zkt.h
+dki.o: dki.c config_zkt.h debug.h domaincmp.h misc.h zconf.h dki.h
+misc.o: misc.c config_zkt.h zconf.h log.h debug.h misc.h
+domaincmp.o: domaincmp.c domaincmp.h
+zconf.o: zconf.c config_zkt.h debug.h misc.h zconf.h dki.h
+log.o: log.c config_zkt.h misc.h zconf.h debug.h log.h
diff --git a/contrib/zkt/README b/contrib/zkt/README
new file mode 100644
index 0000000..0798932
--- /dev/null
+++ b/contrib/zkt/README
@@ -0,0 +1,44 @@
+#
+# README dnssec zone key tool
+#
+# (c) March 2005 - Aug 2008 by Holger Zuleger hznet
+# (c) for domaincmp Aug 2005 by Karle Boss & H. Zuleger (kaho)
+# (c) for zconf.c by Jeroen Masar & Holger Zuleger
+#
+
+For more information about the DNSSEC Zone Key Tool please
+have a look at "http://www.hznet.de/dns/zkt/"
+
+You can also subscribe to the zkt-users@sourceforge.net mailing list
+on the following website: https://lists.sourceforge.net/lists/listinfo/zkt-users
+
+The complete software stands under BSD licence (see LICENCE file)
+
+To build the software:
+a) Get the current version of zkt
+ $ wget http://www.hznet.de/dns/zkt/zkt-0.97.tar.gz
+
+b) Unpack
+ $ tar xzvf zkt-0.97.tar.gz
+
+c) Change to dir
+ $ cd zkt-0.97
+
+d) Run configure script
+ $ ./configure
+
+e) (optional) Edit config_zkt.h
+
+f) Compile
+ $ make
+ For MAC users: # this should not needed anymore
+ $ make macos
+ For Solaris: # this should not needed anymore
+ $ make solaris
+
+g) Install
+ $ make install # this will copy the binarys to $HOME/bin
+
+h) (optional) Install and modify the default dnssec.conf file
+ $ ./dnssec-zkt -c "" -Z > /var/named/dnssec.conf
+ $ vi /var/named/dnssec.conf
diff --git a/contrib/zkt/README.logging b/contrib/zkt/README.logging
new file mode 100644
index 0000000..f0f3f90
--- /dev/null
+++ b/contrib/zkt/README.logging
@@ -0,0 +1,99 @@
+#
+# README.logging
+#
+# Introduction into the new logging feature
+# available since v0.96
+#
+
+In previous version of dnssec-signer every message was written
+to the default stdout and stderr channels, and the logging itself
+was handled by a redirection of those chanels to the logger command
+or to a file.
+
+Now, since version v0.96, the dnssec-signer command is able to log all
+messages by itself. File and SYSLOG logging is supported.
+
+To enable the logging into a file channel, you have to specify
+the file or directory name via the commandline option -L (--logfile)
+or via the config file parameter "LogFile".
+ LogFile: ""|"<file>"|"<directory>" (default is "")
+If a file is specified, than each run of dnssec-signer will append the
+messages to tat file. If a directory is specified, than a file with a
+name of zkt-<ISOdate&timeUTC>.log" will be created on each dnssec-signer run.
+
+Logging into the syslog channel could be enabled via the config file
+parameter "SyslogFacility".
+ SyslogFacility: NONE|USER|DAEMON|LOCAL0|..|LOCAL7 (default is USER)
+
+For both channels, the log level could be independently set to one
+of six log levels:
+ LG_FATAL, LG_ERROR, LG_WARNING
+ LB_NOTICE, LG_INFO, LG_DEBUG
+
+The loglevel is settable via the config file parameter :
+ SyslogLevel: FATAL|ERROR|WARNING|NOTICE|INFO|DEBUG
+ (default is ERROR)
+and
+ LogLevel: FATAL|ERROR|WARNING|NOTICE|INFO|DEBUG
+ (default is NOTICE)
+
+All the log parameters are settable on the commandline via the generic
+option -O "optstring" (--config-option="opt").
+
+A verbose message output to stdout could be achieved by the commandline
+option -v (or -v -v).
+If you want to log the same messages with loglevel LG_DEBUG to a file or
+to syslog, you could enable this by setting the config file option
+"VerboseLog" to a value of 1 or 2.
+
+Current logging messages:
+ LG_FATAL: Not all of the fatal errors are logged
+ (e.g.: config file or command line option fatal errors are
+ not logged)
+ LG_ERROR: All error messages will be logged
+ LG_WARNING: KSK lifetime expiration
+ LG_NOTICE:
+ Start and stop of dnssec-signer
+ Re-signing events
+ Key rollover events
+ Zone reload resp. freeze/thaw of dynamic zone
+ LG_INFO: Currently none
+ planned:
+ Mesages for key generation and key status change
+ (e.g.: pre-publish -> activate; revoked -> removed etc.)
+ LG_DEBUG: all "verbose" (-v) and "very verbose" (-v -v) messages
+
+Some recomended and useful logging settings
+
+- The default setting
+ LogFile: ""
+ SyslogFacility: USER
+ SyslogLevel: NOTICE
+ VerboseLog: 0
+
+- Setting as in version v0.95
+ LogFile: "zkt-error.log" # or a directory for seperate logfiles
+ LogLevel: ERROR
+ SyslogFacility: NONE
+ VerboseLog: 0
+
+- Setting as in previous versions
+ LogFile: ""
+ SyslogFacility: NONE
+ VerboseLog: 0
+
+- Recommended setting for normal usage
+ LogFile: "zkt.log" # or a directory for seperate logfiles
+ LogLevel: ERROR
+ SyslogFacility: USER
+ SyslogLevel: NOTICE
+ VerboseLog: 0
+
+- Recommended setting for debugging
+ LogFile: "zkt.log" # or a directory for seperate logfiles
+ LogLevel: DEBUG
+ SyslogFacility: USER
+ SyslogLevel: NOTICE
+ VerboseLog: 2
+
+-
diff --git a/contrib/zkt/TODO b/contrib/zkt/TODO
new file mode 100644
index 0000000..fc53210
--- /dev/null
+++ b/contrib/zkt/TODO
@@ -0,0 +1,37 @@
+TODO list as of zkt-0.97
+
+general:
+ Renaming of the tools to zkt-* ?
+
+dnssec-zkt:
+ feat option to specify the key age as remaining lifetime
+ (Option -i inverse age ?) As of v0.95 the key lifetime
+ is stored at the key itself, so this could be possibly
+ implemented without big effort(?).
+
+dnssec-signer:
+ bug Distribute_Cmd will not work properly on dynamic zones
+
+ bug Automatic KSK rollover of dynamic zones will only work if the parent
+ uses the standard name for the signed zonefile (zonefile.db.signed).
+
+ bug Phase3 of manual ksk rollover do not trigger a resigning of the zone
+ (Key removal is not recognized by dosigning () function )
+
+ bug There is no online checking of the key material by design.
+ So the signer command checks the status of the key as they
+ are represented in the file system and not in the zone.
+ The dnssec maintainer is responsible for the lifeliness of the
+ data in the hosted domain.
+ In other words: It's highly recommended to use the
+ option -r when you use dnssec-signer on a production zone.
+ Then the time of propagation is (more or less) equal to the timestamp
+ of the zone.db.signed file.
+
+ bug The max_TTL and Key_TTL parameter should be set to the value found
+ in the zone. A mechanism for setting up a dnssec.conf file for the
+ zone specific TTL values is needed.
+
+dki:
+ feat Use dynamic memory for dname in dki_t
+
diff --git a/contrib/zkt/config.h.in b/contrib/zkt/config.h.in
new file mode 100644
index 0000000..fa6ef0f
--- /dev/null
+++ b/contrib/zkt/config.h.in
@@ -0,0 +1,217 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Path to BIND utilities */
+#undef BIND_UTIL_PATH
+
+/* BIND version as integer number without dots */
+#undef BIND_VERSION
+
+/* Define to 1 if the `closedir' function returns void instead of `int'. */
+#undef CLOSEDIR_VOID
+
+/* set path of config file (defaults to /var/named) */
+#undef CONFIG_PATH
+
+/* Define to 1 if you have the `alarm' function. */
+#undef HAVE_ALARM
+
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
+
+/* Define to 1 if you have the `getopt_long' function. */
+#undef HAVE_GETOPT_LONG
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the `setenv' function. */
+#undef HAVE_SETENV
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+ zero-length file name argument. */
+#undef HAVE_STAT_EMPTY_STRING_BUG
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the `strftime' function. */
+#undef HAVE_STRFTIME
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#undef HAVE_STRNCASECMP
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+ */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the `tzset' function. */
+#undef HAVE_TZSET
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `utime' function. */
+#undef HAVE_UTIME
+
+/* Define to 1 if you have the <utime.h> header file. */
+#undef HAVE_UTIME_H
+
+/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */
+#undef HAVE_UTIME_NULL
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* log with level */
+#undef LOG_WITH_LEVEL
+
+/* log with progname */
+#undef LOG_WITH_PROGNAME
+
+/* log with timestamp */
+#undef LOG_WITH_TIMESTAMP
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+ slash. */
+#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* print age of year */
+#undef PRINT_AGE_OF_YEAR
+
+/* print out timezone */
+#undef PRINT_TIMEZONE
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* TTL in keyfiles allowed */
+#undef TTL_IN_KEYFILE_ALLOWED
+
+/* Use TREE data structure for dnssec-zkt */
+#undef USE_TREE
+
+/* ZKT version string */
+#undef ZKT_VERSION
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `unsigned char' if <sys/types.h> does not define. */
+#undef uchar
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef uint
+
+/* Define to `unsigned long' if <sys/types.h> does not define. */
+#undef ulong
+
+/* Define to `unsigned short' if <sys/types.h> does not define. */
+#undef ushort
diff --git a/contrib/zkt/config_zkt.h b/contrib/zkt/config_zkt.h
new file mode 100644
index 0000000..4c04844
--- /dev/null
+++ b/contrib/zkt/config_zkt.h
@@ -0,0 +1,121 @@
+/*****************************************************************
+**
+** @(#) config_zkt.h -- config options for ZKT
+**
+** Copyright (c) Aug 2005, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+#ifndef CONFIG_ZKT_H
+# define CONFIG_ZKT_H
+
+#ifndef HAS_TIMEGM
+# define HAS_TIMEGM 1
+#endif
+
+#ifndef HAS_UTYPES
+# define HAS_UTYPES 1
+#endif
+
+#ifndef LOG_FNAMETMPL
+# define LOG_FNAMETMPL "/zkt-%04d-%02d-%02dT%02d%02d%02dZ.log"
+#endif
+
+/* don't change anything below this */
+/* the values here are determined or settable via the ./configure script */
+
+#ifndef HAVE_GETOPT_LONG
+# define HAVE_GETOPT_LONG 1
+#endif
+
+#ifndef HAVE_STRFTIME
+# define HAVE_STRFTIME 1
+#endif
+
+#ifndef TTL_IN_KEYFILE_ALLOWED
+# define TTL_IN_KEYFILE_ALLOWED 1
+#endif
+
+#ifndef PRINT_TIMEZONE
+# define PRINT_TIMEZONE 0
+#endif
+
+#ifndef PRINT_AGE_WITH_YEAR
+# define PRINT_AGE_WITH_YEAR 0
+#endif
+
+#ifndef LOG_WITH_PROGNAME
+# define LOG_WITH_PROGNAME 0
+#endif
+
+#ifndef LOG_WITH_TIMESTAMP
+# define LOG_WITH_TIMESTAMP 1
+#endif
+
+#ifndef LOG_WITH_LEVEL
+# define LOG_WITH_LEVEL 1
+#endif
+
+#ifndef CONFIG_PATH
+# define CONFIG_PATH "/var/named/"
+#endif
+
+/* tree usage is setable by configure script parameter */
+#ifndef USE_TREE
+# define USE_TREE 1
+#endif
+
+/* BIND version and utility path will be set by ./configure script */
+#ifndef BIND_VERSION
+# define BIND_VERSION 942
+#endif
+
+#ifndef BIND_UTIL_PATH
+# define BIND_UTIL_PATH "/usr/local/sbin/"
+#endif
+
+#ifndef ZKT_VERSION
+# if defined(USE_TREE) && USE_TREE
+# define ZKT_VERSION "vT0.97 (c) Feb 2005 - Aug 2008 Holger Zuleger hznet.de"
+# else
+# define ZKT_VERSION "v0.97 (c) Feb 2005 - Aug 2008 Holger Zuleger hznet.de"
+# endif
+#endif
+
+
+#if !defined(HAS_UTYPES) || !HAS_UTYPES
+typedef unsigned long ulong;
+typedef unsigned int uint;
+typedef unsigned short ushort;
+typedef unsigned char uchar;
+#endif
+
+#endif
diff --git a/contrib/zkt/configure b/contrib/zkt/configure
new file mode 100755
index 0000000..178398f
--- /dev/null
+++ b/contrib/zkt/configure
@@ -0,0 +1,6838 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.59 for ZKT 0.97.
+#
+# Report bugs to <Holger Zuleger hznet.de>.
+#
+# Copyright (C) 2003 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME='ZKT'
+PACKAGE_TARNAME='zkt'
+PACKAGE_VERSION='0.97'
+PACKAGE_STRING='ZKT 0.97'
+PACKAGE_BUGREPORT='Holger Zuleger hznet.de'
+
+ac_unique_file="dnssec-zkt.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT SIGNZONE_PROG CPP EGREP LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_option in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_$ac_feature='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_$ac_package='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
+ else
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+ fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures ZKT 0.97 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of ZKT 0.97:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-print-timezone print out timezone
+ --enable-print-age print age of year
+ --enable-log-progname log with progname
+ --disable-log-timestamp do not log with timestamp
+ --disable-log-level do not log with level
+ --disable-ttl-in-keyfiles
+ do not allow TTL values in keyfiles
+ --enable-configpath=PATH
+ set path of config file (defaults to /var/named)
+ --disable-tree use single linked list instead of binary tree data
+ structure for dnssec-zkt
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <Holger Zuleger hznet.de>.
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+ZKT configure 0.97
+generated by GNU Autoconf 2.59
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by ZKT $as_me 0.97, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+### Files to test to check if src dir contains the package
+
+ ac_config_headers="$ac_config_headers config.h"
+
+
+
+### Checks for programs.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CC" && break
+done
+
+ CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std1 is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std1. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ '' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+### find out the path to BIND utils and version
+# Extract the first word of "dnssec-signzone", so it can be a program name with args.
+set dummy dnssec-signzone; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_SIGNZONE_PROG+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case $SIGNZONE_PROG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_SIGNZONE_PROG="$SIGNZONE_PROG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_SIGNZONE_PROG="$as_dir/$ac_word$ac_exec_ext"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+ ;;
+esac
+fi
+SIGNZONE_PROG=$ac_cv_path_SIGNZONE_PROG
+
+if test -n "$SIGNZONE_PROG"; then
+ echo "$as_me:$LINENO: result: $SIGNZONE_PROG" >&5
+echo "${ECHO_T}$SIGNZONE_PROG" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+bind_util_path=`dirname $SIGNZONE_PROG`
+if test -z "$SIGNZONE_PROG" ; then
+ { { echo "$as_me:$LINENO: error: *** 'BIND dnssec-signzone dnssec-keygen' missing, please install or fix your \$PATH ***" >&5
+echo "$as_me: error: *** 'BIND dnssec-signzone dnssec-keygen' missing, please install or fix your \$PATH ***" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+# define BIND_UTIL_PATH in config.h.in
+
+cat >>confdefs.h <<_ACEOF
+#define BIND_UTIL_PATH "$bind_util_path/"
+_ACEOF
+
+# define BIND_VERSION in config.h.in
+bind_version=`$SIGNZONE_PROG 2>&1 | grep Version: | tr -dc 0-9`
+
+cat >>confdefs.h <<_ACEOF
+#define BIND_VERSION $bind_version
+_ACEOF
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+echo "$as_me:$LINENO: checking for uint" >&5
+echo $ECHO_N "checking for uint... $ECHO_C" >&6
+if test "${ac_cv_type_uint+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((uint *) 0)
+ return 0;
+if (sizeof (uint))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_uint=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_uint=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_uint" >&5
+echo "${ECHO_T}$ac_cv_type_uint" >&6
+if test $ac_cv_type_uint = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define uint unsigned int
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for ulong" >&5
+echo $ECHO_N "checking for ulong... $ECHO_C" >&6
+if test "${ac_cv_type_ulong+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((ulong *) 0)
+ return 0;
+if (sizeof (ulong))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_ulong=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_ulong=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_ulong" >&5
+echo "${ECHO_T}$ac_cv_type_ulong" >&6
+if test $ac_cv_type_ulong = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ulong unsigned long
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for ushort" >&5
+echo $ECHO_N "checking for ushort... $ECHO_C" >&6
+if test "${ac_cv_type_ushort+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((ushort *) 0)
+ return 0;
+if (sizeof (ushort))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_ushort=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_ushort=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_ushort" >&5
+echo "${ECHO_T}$ac_cv_type_ushort" >&6
+if test $ac_cv_type_ushort = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ushort unsigned short
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for uchar" >&5
+echo $ECHO_N "checking for uchar... $ECHO_C" >&6
+if test "${ac_cv_type_uchar+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((uchar *) 0)
+ return 0;
+if (sizeof (uchar))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_uchar=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_uchar=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_uchar" >&5
+echo "${ECHO_T}$ac_cv_type_uchar" >&6
+if test $ac_cv_type_uchar = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define uchar unsigned char
+_ACEOF
+
+fi
+
+
+### define configure arguments
+# Check whether --enable-printtimezone or --disable-printtimezone was given.
+if test "${enable_printtimezone+set}" = set; then
+ enableval="$enable_printtimezone"
+ printtimezone=$enableval
+fi;
+printtimezone=0
+test "$printtimezone" = yes && printtimezone=1
+
+cat >>confdefs.h <<_ACEOF
+#define PRINT_TIMEZONE $printtimezone
+_ACEOF
+
+
+# Check whether --enable-printyear or --disable-printyear was given.
+if test "${enable_printyear+set}" = set; then
+ enableval="$enable_printyear"
+ printyear=$enableval
+fi;
+printyear=0
+test "$printyear" = yes && printyear=1
+
+cat >>confdefs.h <<_ACEOF
+#define PRINT_AGE_OF_YEAR $printyear
+_ACEOF
+
+
+# Check whether --enable-logprogname or --disable-logprogname was given.
+if test "${enable_logprogname+set}" = set; then
+ enableval="$enable_logprogname"
+ logprogname=$enableval
+fi;
+logprogname=0
+test "$logprogname" = yes && logprogname=1
+
+cat >>confdefs.h <<_ACEOF
+#define LOG_WITH_PROGNAME $logprogname
+_ACEOF
+
+
+# Check whether --enable-logtimestamp or --disable-logtimestamp was given.
+if test "${enable_logtimestamp+set}" = set; then
+ enableval="$enable_logtimestamp"
+ logtimestamp=$enableval
+fi;
+logtimestamp=1
+test "$logtimestamp" = no && logtimestamp=0
+
+cat >>confdefs.h <<_ACEOF
+#define LOG_WITH_TIMESTAMP $logtimestamp
+_ACEOF
+
+
+# Check whether --enable-loglevel or --disable-loglevel was given.
+if test "${enable_loglevel+set}" = set; then
+ enableval="$enable_loglevel"
+ loglevel=$enableval
+fi;
+loglevel=1
+test "$loglevel" = no && loglevel=0
+
+cat >>confdefs.h <<_ACEOF
+#define LOG_WITH_LEVEL $loglevel
+_ACEOF
+
+
+# Check whether --enable-ttl_in_keyfile or --disable-ttl_in_keyfile was given.
+if test "${enable_ttl_in_keyfile+set}" = set; then
+ enableval="$enable_ttl_in_keyfile"
+ ttl_in_keyfile=$enableval
+fi;
+ttl_in_keyfile=1
+test "$ttl_in_keyfile" = no && ttl_in_keyfile=0
+
+cat >>confdefs.h <<_ACEOF
+#define TTL_IN_KEYFILE_ALLOWED $ttl_in_keyfile
+_ACEOF
+
+
+configpath="/var/named"
+# Check whether --enable-configpath or --disable-configpath was given.
+if test "${enable_configpath+set}" = set; then
+ enableval="$enable_configpath"
+ configpath=$enableval
+fi;
+case "$configpath" in
+yes)
+ configpath="/var/named"
+ ;;
+no)
+ configpath=""
+ ;;
+*)
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define CONFIG_PATH "$configpath/"
+_ACEOF
+
+
+usetree=1
+t="T"
+# Check whether --enable-tree or --disable-tree was given.
+if test "${enable_tree+set}" = set; then
+ enableval="$enable_tree"
+ usetree=$enableval
+fi;
+if test "$usetree" = no
+then
+ usetree=0
+ t=""
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define USE_TREE $usetree
+_ACEOF
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define ZKT_VERSION "v$t$PACKAGE_VERSION (c) Feb 2005 - Aug 2008 Holger Zuleger hznet.de"
+_ACEOF
+
+
+### Checks for libraries.
+
+
+### Checks for header files.
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+ as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <$ac_hdr>
+
+int
+main ()
+{
+if ((DIR *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+_ACEOF
+
+ac_header_dirent=$ac_hdr; break
+fi
+
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+ echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir ();
+int
+main ()
+{
+opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_opendir="none required"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+ for ac_lib in dir; do
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir ();
+int
+main ()
+{
+opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_opendir="-l$ac_lib"
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+ test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+else
+ echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir ();
+int
+main ()
+{
+opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_opendir="none required"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+ for ac_lib in x; do
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir ();
+int
+main ()
+{
+opendir ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_opendir="-l$ac_lib"
+break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+ test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
+
+fi
+
+fi
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in fcntl.h netdb.h stdlib.h getopt.h string.h strings.h sys/socket.h sys/time.h sys/types.h syslog.h unistd.h utime.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## -------------------------------------- ##
+## Report this to Holger Zuleger hznet.de ##
+## -------------------------------------- ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+### Checks for typedefs, structures, and compiler characteristics.
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset x;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *ccp;
+ char **p;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ ccp = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++ccp;
+ p = (char**) ccp;
+ ccp = (char const *const *) p;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ }
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+ return 0;
+if (sizeof (size_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_type_size_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_size_t=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6
+if test "${ac_cv_header_time+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_time=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_time=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6
+if test $ac_cv_header_time = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6
+if test "${ac_cv_struct_tm+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm *tp; tp->tm_sec;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_struct_tm=time.h
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_struct_tm=sys/time.h
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5
+echo "${ECHO_T}$ac_cv_struct_tm" >&6
+if test $ac_cv_struct_tm = sys/time.h; then
+
+cat >>confdefs.h <<\_ACEOF
+#define TM_IN_SYS_TIME 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for uid_t in sys/types.h" >&5
+echo $ECHO_N "checking for uid_t in sys/types.h... $ECHO_C" >&6
+if test "${ac_cv_type_uid_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "uid_t" >/dev/null 2>&1; then
+ ac_cv_type_uid_t=yes
+else
+ ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_uid_t" >&5
+echo "${ECHO_T}$ac_cv_type_uid_t" >&6
+if test $ac_cv_type_uid_t = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define uid_t int
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define gid_t int
+_ACEOF
+
+fi
+
+
+
+### Checks for library functions.
+echo "$as_me:$LINENO: checking whether closedir returns void" >&5
+echo $ECHO_N "checking whether closedir returns void... $ECHO_C" >&6
+if test "${ac_cv_func_closedir_void+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_closedir_void=yes
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header_dirent>
+#ifndef __cplusplus
+int closedir ();
+#endif
+
+int
+main ()
+{
+exit (closedir (opendir (".")) != 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_closedir_void=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_closedir_void=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_closedir_void" >&5
+echo "${ECHO_T}$ac_cv_func_closedir_void" >&6
+if test $ac_cv_func_closedir_void = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define CLOSEDIR_VOID 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for error_at_line" >&5
+echo $ECHO_N "checking for error_at_line... $ECHO_C" >&6
+if test "${ac_cv_lib_error_at_line+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+error_at_line (0, 0, "", 0, "");
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_error_at_line=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_error_at_line=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_error_at_line" >&5
+echo "${ECHO_T}$ac_cv_lib_error_at_line" >&6
+if test $ac_cv_lib_error_at_line = no; then
+ case $LIBOBJS in
+ "error.$ac_objext" | \
+ *" error.$ac_objext" | \
+ "error.$ac_objext "* | \
+ *" error.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS error.$ac_objext" ;;
+esac
+
+fi
+
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## -------------------------------------- ##
+## Report this to Holger Zuleger hznet.de ##
+## -------------------------------------- ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+echo "$as_me:$LINENO: checking for GNU libc compatible malloc" >&5
+echo $ECHO_N "checking for GNU libc compatible malloc... $ECHO_C" >&6
+if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_malloc_0_nonnull=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#if STDC_HEADERS || HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+exit (malloc (0) ? 0 : 1);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_malloc_0_nonnull=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_malloc_0_nonnull=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_malloc_0_nonnull" >&5
+echo "${ECHO_T}$ac_cv_func_malloc_0_nonnull" >&6
+if test $ac_cv_func_malloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 1
+_ACEOF
+
+else
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 0
+_ACEOF
+
+ case $LIBOBJS in
+ "malloc.$ac_objext" | \
+ *" malloc.$ac_objext" | \
+ "malloc.$ac_objext "* | \
+ *" malloc.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;;
+esac
+
+
+cat >>confdefs.h <<\_ACEOF
+#define malloc rpl_malloc
+_ACEOF
+
+fi
+
+
+
+
+
+
+for ac_header in stdlib.h sys/time.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ (
+ cat <<\_ASBOX
+## -------------------------------------- ##
+## Report this to Holger Zuleger hznet.de ##
+## -------------------------------------- ##
+_ASBOX
+ ) |
+ sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in alarm
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+echo "$as_me:$LINENO: checking for working mktime" >&5
+echo $ECHO_N "checking for working mktime... $ECHO_C" >&6
+if test "${ac_cv_func_working_mktime+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_working_mktime=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Test program from Paul Eggert and Tony Leneis. */
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if !HAVE_ALARM
+# define alarm(X) /* empty */
+#endif
+
+/* Work around redefinition to rpl_putenv by other config tests. */
+#undef putenv
+
+static time_t time_t_max;
+static time_t time_t_min;
+
+/* Values we'll use to set the TZ environment variable. */
+static char *tz_strings[] = {
+ (char *) 0, "TZ=GMT0", "TZ=JST-9",
+ "TZ=EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00"
+};
+#define N_STRINGS (sizeof (tz_strings) / sizeof (tz_strings[0]))
+
+/* Fail if mktime fails to convert a date in the spring-forward gap.
+ Based on a problem report from Andreas Jaeger. */
+static void
+spring_forward_gap ()
+{
+ /* glibc (up to about 1998-10-07) failed this test. */
+ struct tm tm;
+
+ /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0"
+ instead of "TZ=America/Vancouver" in order to detect the bug even
+ on systems that don't support the Olson extension, or don't have the
+ full zoneinfo tables installed. */
+ putenv ("TZ=PST8PDT,M4.1.0,M10.5.0");
+
+ tm.tm_year = 98;
+ tm.tm_mon = 3;
+ tm.tm_mday = 5;
+ tm.tm_hour = 2;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_isdst = -1;
+ if (mktime (&tm) == (time_t)-1)
+ exit (1);
+}
+
+static void
+mktime_test1 (now)
+ time_t now;
+{
+ struct tm *lt;
+ if ((lt = localtime (&now)) && mktime (lt) != now)
+ exit (1);
+}
+
+static void
+mktime_test (now)
+ time_t now;
+{
+ mktime_test1 (now);
+ mktime_test1 ((time_t) (time_t_max - now));
+ mktime_test1 ((time_t) (time_t_min + now));
+}
+
+static void
+irix_6_4_bug ()
+{
+ /* Based on code from Ariel Faigon. */
+ struct tm tm;
+ tm.tm_year = 96;
+ tm.tm_mon = 3;
+ tm.tm_mday = 0;
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_isdst = -1;
+ mktime (&tm);
+ if (tm.tm_mon != 2 || tm.tm_mday != 31)
+ exit (1);
+}
+
+static void
+bigtime_test (j)
+ int j;
+{
+ struct tm tm;
+ time_t now;
+ tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j;
+ now = mktime (&tm);
+ if (now != (time_t) -1)
+ {
+ struct tm *lt = localtime (&now);
+ if (! (lt
+ && lt->tm_year == tm.tm_year
+ && lt->tm_mon == tm.tm_mon
+ && lt->tm_mday == tm.tm_mday
+ && lt->tm_hour == tm.tm_hour
+ && lt->tm_min == tm.tm_min
+ && lt->tm_sec == tm.tm_sec
+ && lt->tm_yday == tm.tm_yday
+ && lt->tm_wday == tm.tm_wday
+ && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst)
+ == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst))))
+ exit (1);
+ }
+}
+
+int
+main ()
+{
+ time_t t, delta;
+ int i, j;
+
+ /* This test makes some buggy mktime implementations loop.
+ Give up after 60 seconds; a mktime slower than that
+ isn't worth using anyway. */
+ alarm (60);
+
+ for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2)
+ continue;
+ time_t_max--;
+ if ((time_t) -1 < 0)
+ for (time_t_min = -1; (time_t) (time_t_min * 2) < 0; time_t_min *= 2)
+ continue;
+ delta = time_t_max / 997; /* a suitable prime number */
+ for (i = 0; i < N_STRINGS; i++)
+ {
+ if (tz_strings[i])
+ putenv (tz_strings[i]);
+
+ for (t = 0; t <= time_t_max - delta; t += delta)
+ mktime_test (t);
+ mktime_test ((time_t) 1);
+ mktime_test ((time_t) (60 * 60));
+ mktime_test ((time_t) (60 * 60 * 24));
+
+ for (j = 1; 0 < j; j *= 2)
+ bigtime_test (j);
+ bigtime_test (j - 1);
+ }
+ irix_6_4_bug ();
+ spring_forward_gap ();
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_working_mktime=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_working_mktime=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_working_mktime" >&5
+echo "${ECHO_T}$ac_cv_func_working_mktime" >&6
+if test $ac_cv_func_working_mktime = no; then
+ case $LIBOBJS in
+ "mktime.$ac_objext" | \
+ *" mktime.$ac_objext" | \
+ "mktime.$ac_objext "* | \
+ *" mktime.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS mktime.$ac_objext" ;;
+esac
+
+fi
+
+echo "$as_me:$LINENO: checking whether lstat dereferences a symlink specified with a trailing slash" >&5
+echo $ECHO_N "checking whether lstat dereferences a symlink specified with a trailing slash... $ECHO_C" >&6
+if test "${ac_cv_func_lstat_dereferences_slashed_symlink+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ rm -f conftest.sym conftest.file
+echo >conftest.file
+if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+ /* Linux will dereference the symlink and fail.
+ That is better in the sense that it means we will not
+ have to compile and use the lstat wrapper. */
+ exit (lstat ("conftest.sym/", &sbuf) ? 0 : 1);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_lstat_dereferences_slashed_symlink=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+else
+ # If the `ln -s' command failed, then we probably don't even
+ # have an lstat function.
+ ac_cv_func_lstat_dereferences_slashed_symlink=no
+fi
+rm -f conftest.sym conftest.file
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5
+echo "${ECHO_T}$ac_cv_func_lstat_dereferences_slashed_symlink" >&6
+
+test $ac_cv_func_lstat_dereferences_slashed_symlink = yes &&
+
+cat >>confdefs.h <<_ACEOF
+#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1
+_ACEOF
+
+
+if test $ac_cv_func_lstat_dereferences_slashed_symlink = no; then
+ case $LIBOBJS in
+ "lstat.$ac_objext" | \
+ *" lstat.$ac_objext" | \
+ "lstat.$ac_objext "* | \
+ *" lstat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS lstat.$ac_objext" ;;
+esac
+
+fi
+
+echo "$as_me:$LINENO: checking whether stat accepts an empty string" >&5
+echo $ECHO_N "checking whether stat accepts an empty string... $ECHO_C" >&6
+if test "${ac_cv_func_stat_empty_string_bug+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_stat_empty_string_bug=yes
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat sbuf;
+ exit (stat ("", &sbuf) ? 1 : 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_stat_empty_string_bug=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_stat_empty_string_bug=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_stat_empty_string_bug" >&5
+echo "${ECHO_T}$ac_cv_func_stat_empty_string_bug" >&6
+if test $ac_cv_func_stat_empty_string_bug = yes; then
+ case $LIBOBJS in
+ "stat.$ac_objext" | \
+ *" stat.$ac_objext" | \
+ "stat.$ac_objext "* | \
+ *" stat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS stat.$ac_objext" ;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STAT_EMPTY_STRING_BUG 1
+_ACEOF
+
+fi
+
+
+for ac_func in strftime
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+ # strftime is in -lintl on SCO UNIX.
+echo "$as_me:$LINENO: checking for strftime in -lintl" >&5
+echo $ECHO_N "checking for strftime in -lintl... $ECHO_C" >&6
+if test "${ac_cv_lib_intl_strftime+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lintl $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strftime ();
+int
+main ()
+{
+strftime ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_intl_strftime=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_intl_strftime=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_intl_strftime" >&5
+echo "${ECHO_T}$ac_cv_lib_intl_strftime" >&6
+if test $ac_cv_lib_intl_strftime = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRFTIME 1
+_ACEOF
+
+LIBS="-lintl $LIBS"
+fi
+
+fi
+done
+
+echo "$as_me:$LINENO: checking whether utime accepts a null argument" >&5
+echo $ECHO_N "checking whether utime accepts a null argument... $ECHO_C" >&6
+if test "${ac_cv_func_utime_null+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ rm -f conftest.data; >conftest.data
+# Sequent interprets utime(file, 0) to mean use start of epoch. Wrong.
+if test "$cross_compiling" = yes; then
+ ac_cv_func_utime_null=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+struct stat s, t;
+ exit (!(stat ("conftest.data", &s) == 0
+ && utime ("conftest.data", (long *)0) == 0
+ && stat ("conftest.data", &t) == 0
+ && t.st_mtime >= s.st_mtime
+ && t.st_mtime - s.st_mtime < 120));
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_utime_null=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_utime_null=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core *.core
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_utime_null" >&5
+echo "${ECHO_T}$ac_cv_func_utime_null" >&6
+if test $ac_cv_func_utime_null = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_UTIME_NULL 1
+_ACEOF
+
+fi
+rm -f conftest.data
+
+
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+echo "$as_me:$LINENO: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6
+if test "${ac_cv_func__doprnt+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define _doprnt to an innocuous variant, in case <limits.h> declares _doprnt.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define _doprnt innocuous__doprnt
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char _doprnt (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef _doprnt
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _doprnt ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub__doprnt) || defined (__stub____doprnt)
+choke me
+#else
+char (*f) () = _doprnt;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != _doprnt;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func__doprnt=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func__doprnt=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6
+if test $ac_cv_func__doprnt = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DOPRNT 1
+_ACEOF
+
+fi
+
+fi
+done
+
+
+# 2008-07-04 getopt_long added
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in getopt_long gettimeofday memset setenv socket strcasecmp strchr strdup strerror strncasecmp strrchr tzset utime
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+ ac_config_files="$ac_config_files Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+ if test -w $cache_file; then
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by ZKT $as_me 0.97, which was
+generated by GNU Autoconf 2.59. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+ZKT config.status 0.97
+configured by $0, generated by GNU Autoconf 2.59,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2003 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@SIGNZONE_PROG@,$SIGNZONE_PROG,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+ case "$ac_dir" in
+ .) ac_abs_builddir=`pwd`;;
+ [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+ *) ac_abs_builddir=`pwd`/"$ac_dir";;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+ case ${ac_top_builddir}. in
+ .) ac_abs_top_builddir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+ *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+ case $ac_srcdir in
+ .) ac_abs_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+ *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+ esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+ case $ac_top_srcdir in
+ .) ac_abs_top_srcdir=$ac_abs_builddir;;
+ [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+ *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+ esac;;
+esac
+
+
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ # Do quote $f, to prevent DOS paths from being IFS'd.
+ echo "$f";;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo "$f"
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo "$srcdir/$f"
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+ # Remove the trailing spaces.
+ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h. The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status. Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless. Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo ' :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+ # Write a limited-size here document to $tmp/defines.sed.
+ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#define' lines.
+ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/defines.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo ' fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+ # Write a limited-size here document to $tmp/undefs.sed.
+ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#undef'
+ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+ rm -f conftest.undefs
+ mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ echo "/* Generated by configure. */" >$tmp/config.h
+ else
+ echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
+ fi
+ cat $tmp/in >>$tmp/config.h
+ rm -f $tmp/in
+ if test x"$ac_file" != x-; then
+ if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ rm -f $ac_file
+ mv $tmp/config.h $ac_file
+ fi
+ else
+ cat $tmp/config.h
+ rm -f $tmp/config.h
+ fi
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
diff --git a/contrib/zkt/debug.h b/contrib/zkt/debug.h
new file mode 100644
index 0000000..e0c47dc
--- /dev/null
+++ b/contrib/zkt/debug.h
@@ -0,0 +1,66 @@
+/*****************************************************************
+**
+** @(#) debug.h -- macros for debug messages
+**
+** compile with cc -DDBG to activate
+**
+** Copyright (c) Jan 2005, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+#ifndef DEBUG_H
+# define DEBUG_H
+
+# ifdef DBG
+# define dbg_line() fprintf (stderr, "DBG: %s(%d) reached\n", __FILE__, __LINE__)
+# define dbg_msg(msg) fprintf (stderr, "DBG: %s(%d) %s\n", __FILE__, __LINE__, msg)
+# define dbg_val0(text) fprintf (stderr, "DBG: %s(%d) %s", __FILE__, __LINE__, text)
+# define dbg_val1(fmt, var) dbg_val (fmt, var)
+# define dbg_val(fmt, var) fprintf (stderr, "DBG: %s(%d) " fmt, __FILE__, __LINE__, var)
+# define dbg_val2(fmt, v1, v2) fprintf (stderr, "DBG: %s(%d) " fmt, __FILE__, __LINE__, v1, v2)
+# define dbg_val3(fmt, v1, v2, v3) fprintf (stderr, "DBG: %s(%d) " fmt, __FILE__, __LINE__, v1, v2, v3)
+# define dbg_val4(fmt, v1, v2, v3, v4) fprintf (stderr, "DBG: %s(%d) " fmt, __FILE__, __LINE__, v1, v2, v3, v4)
+# define dbg_val5(fmt, v1, v2, v3, v4, v5) fprintf (stderr, "DBG: %s(%d) " fmt, __FILE__, __LINE__, v1, v2, v3, v4, v5)
+# define dbg_val6(fmt, v1, v2, v3, v4, v5, v6) fprintf (stderr, "DBG: %s(%d) " fmt, __FILE__, __LINE__, v1, v2, v3, v4, v5, v6)
+# else
+# define dbg_line()
+# define dbg_msg(msg)
+# define dbg_val0(text)
+# define dbg_val1(fmt, var)
+# define dbg_val(fmt, str)
+# define dbg_val2(fmt, v1, v2)
+# define dbg_val3(fmt, v1, v2, v3)
+# define dbg_val4(fmt, v1, v2, v3, v4)
+# define dbg_val5(fmt, v1, v2, v3, v4, v5)
+# define dbg_val6(fmt, v1, v2, v3, v4, v5, v6)
+# endif
+
+#endif
diff --git a/contrib/zkt/dki.c b/contrib/zkt/dki.c
new file mode 100644
index 0000000..81498ae
--- /dev/null
+++ b/contrib/zkt/dki.c
@@ -0,0 +1,1185 @@
+/*****************************************************************
+**
+** @(#) dki.c (c) Jan 2005 Holger Zuleger hznet.de
+**
+** A library for managing BIND dnssec key files.
+**
+** Copyright (c) Jan 2005, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+**
+*****************************************************************/
+
+# include <stdio.h>
+# include <string.h>
+# include <ctype.h> /* tolower(), ... */
+# include <unistd.h> /* link(), unlink(), ... */
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/stat.h>
+# include <dirent.h>
+# include <assert.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+# include "debug.h"
+# include "domaincmp.h"
+# include "misc.h"
+# include "zconf.h"
+#define extern
+# include "dki.h"
+#undef extern
+
+/*****************************************************************
+** private (static) function declaration and definition
+*****************************************************************/
+static char dki_estr[255+1];
+
+static dki_t *dki_alloc ()
+{
+ dki_estr[0] = '\0';
+ dki_t *dkp = malloc (sizeof (dki_t));
+
+ if ( (dkp = malloc (sizeof (dki_t))) )
+ {
+ memset (dkp, 0, sizeof (dki_t));
+ return dkp;
+ }
+
+ snprintf (dki_estr, sizeof (dki_estr),
+ "dki_alloc: Out of memory");
+ return NULL;
+}
+
+static int dki_readfile (FILE *fp, dki_t *dkp)
+{
+ int algo, flags, type;
+ int c;
+ char *p;
+ char buf[4095+1];
+ char tag[25+1];
+ char val[14+1]; /* e.g. "YYYYMMDDhhmmss" | "60d" */
+
+ assert (dkp != NULL);
+ assert (fp != NULL);
+
+ while ( (c = getc (fp)) == ';' ) /* line start with comment ? */
+ {
+ tag[0] = val[0] = '\0';
+ if ( (c = getc (fp)) == '%' ) /* special comment? */
+ {
+ while ( (c = getc (fp)) == ' ' || c == '\t' )
+ ;
+ ungetc (c, fp);
+ /* then try to read in the creation, expire and lifetime */
+ if ( fscanf (fp, "%25[a-zA-Z]=%14s", tag, val) == 2 )
+ {
+ dbg_val2 ("dki_readfile: tag=%s val=%s \n", tag, val);
+ switch ( tolower (tag[0]) )
+ {
+ case 'g': dkp->gentime = timestr2time (val); break;
+ case 'e': dkp->exptime = timestr2time (val); break;
+ case 'l': dkp->lifetime = atoi (val) * DAYSEC; break;
+ }
+ }
+ }
+ else
+ ungetc (c, fp);
+ while ( (c = getc (fp)) != EOF && c != '\n' ) /* eat up rest of the line */
+ ;
+ }
+ ungetc (c, fp); /* push back last char */
+
+ if ( fscanf (fp, "%4095s", buf) != 1 ) /* read label */
+ return -1;
+
+ if ( strcmp (buf, dkp->name) != 0 )
+ return -2;
+
+#if defined(TTL_IN_KEYFILE_ALLOWED) && TTL_IN_KEYFILE_ALLOWED
+ /* skip optional TTL value */
+ while ( (c = getc (fp)) != EOF && isspace (c) ) /* skip spaces */
+ ;
+ if ( isdigit (c) ) /* skip ttl */
+ fscanf (fp, "%*d");
+ else
+ ungetc (c, fp); /* oops, no ttl */
+#endif
+
+ if ( (c = fscanf (fp, " IN DNSKEY %d %d %d", &flags, &type, &algo)) != 3 &&
+ (c = fscanf (fp, "KEY %d %d %d", &flags, &type, &algo)) != 3 )
+ return -3;
+ if ( type != 3 || algo != dkp->algo )
+ return -4; /* no DNSKEY or algorithm mismatch */
+ if ( ((flags >> 8) & 0xFF) != 01 )
+ return -5; /* no ZONE key */
+ dkp->flags = flags;
+
+ if ( fgets (buf, sizeof buf, fp) == NULL || buf[0] == '\0' )
+ return -6;
+ p = buf + strlen (buf);
+ *--p = '\0'; /* delete trailing \n */
+ /* delete leading ws */
+ for ( p = buf; *p && isspace (*p); p++ )
+ ;
+
+ dkp->pubkey = strdup (p);
+
+ return 0;
+}
+
+static int dki_writeinfo (const dki_t *dkp, const char *path)
+{
+ FILE *fp;
+
+ assert (dkp != NULL);
+ assert (path != NULL && path[0] != '\0');
+
+ if ( (fp = fopen (path, "w")) == NULL )
+ return 0;
+ dbg_val1 ("dki_writeinfo %s\n", path);
+ if ( dki_prt_dnskey_raw (dkp, fp) == 0 )
+ return 0;
+ fclose (fp);
+ touch (path, dkp->time); /* restore time of key file */
+
+ return 1;
+}
+
+static int dki_setstat (dki_t *dkp, int status, int preserve_time);
+
+/*****************************************************************
+** public function definition
+*****************************************************************/
+
+/*****************************************************************
+** dki_free ()
+*****************************************************************/
+void dki_free (dki_t *dkp)
+{
+ assert (dkp != NULL);
+
+ if ( dkp->pubkey )
+ free (dkp->pubkey);
+ free (dkp);
+}
+
+/*****************************************************************
+** dki_freelist ()
+*****************************************************************/
+void dki_freelist (dki_t **listp)
+{
+ dki_t *curr;
+ dki_t *next;
+
+ assert (listp != NULL);
+
+ curr = *listp;
+ while ( curr )
+ {
+ next = curr->next;
+ dki_free (curr);
+ curr = next;
+ }
+ if ( *listp )
+ *listp = NULL;
+}
+
+#if defined(USE_TREE) && USE_TREE
+/*****************************************************************
+** dki_tfree ()
+*****************************************************************/
+void dki_tfree (dki_t **tree)
+{
+ assert (tree != NULL);
+ // TODO: tdestroy is a GNU extension
+ // tdestroy (*tree, dki_free);
+}
+#endif
+
+/*****************************************************************
+** dki_new ()
+** create new keyfile
+** allocate memory for new dki key and init with keyfile
+*****************************************************************/
+dki_t *dki_new (const char *dir, const char *name, int ksk, int algo, int bitsize, const char *rfile, int lf_days)
+{
+ char cmdline[511+1];
+ char fname[254+1];
+ char randfile[254+1];
+ FILE *fp;
+ int len;
+ char *flag = "";
+ char *expflag = "";
+ dki_t *new;
+
+ if ( ksk )
+ flag = "-f KSK";
+
+ randfile[0] = '\0';
+ if ( rfile && *rfile )
+ snprintf (randfile, sizeof (randfile), "-r %.250s ", rfile);
+
+ if ( algo == DK_ALGO_RSA || algo == DK_ALGO_RSASHA1 )
+ expflag = "-e ";
+
+ if ( dir && *dir )
+ snprintf (cmdline, sizeof (cmdline), "cd %s ; %s %s%s-n ZONE -a %s -b %d %s %s",
+ dir, KEYGENCMD, randfile, expflag, dki_algo2str(algo), bitsize, flag, name);
+ else
+ snprintf (cmdline, sizeof (cmdline), "%s %s%s-n ZONE -a %s -b %d %s %s",
+ KEYGENCMD, randfile, expflag, dki_algo2str(algo), bitsize, flag, name);
+
+ dbg_msg (cmdline);
+
+ if ( (fp = popen (cmdline, "r")) == NULL || fgets (fname, sizeof fname, fp) == NULL )
+ return NULL;
+ pclose (fp);
+
+ len = strlen (fname) - 1;
+ if ( len >= 0 && fname[len] == '\n' )
+ fname[len] = '\0';
+
+ new = dki_read (dir, fname);
+ if ( new )
+ dki_setlifetime (new, lf_days); /* sets gentime + proposed lifetime */
+
+ return new;
+}
+
+/*****************************************************************
+** dki_read ()
+** read key from file 'filename' (independed of the extension)
+*****************************************************************/
+dki_t *dki_read (const char *dirname, const char *filename)
+{
+ dki_t *dkp;
+ FILE *fp;
+ struct stat st;
+ int len;
+ int err;
+ char fname[MAX_FNAMESIZE+1];
+ char path[MAX_PATHSIZE+1];
+
+ dki_estr[0] = '\0';
+ if ( (dkp = dki_alloc ()) == NULL )
+ return (NULL);
+
+ len = sizeof (fname) - 1;
+ fname[len] = '\0';
+ strncpy (fname, filename, len);
+
+ len = strlen (fname); /* delete extension */
+ if ( len > 4 && strcmp (&fname[len - 4], DKI_KEY_FILEEXT) == 0 )
+ fname[len - 4] = '\0';
+ else if ( len > 10 && strcmp (&fname[len - 10], DKI_PUB_FILEEXT) == 0 )
+ fname[len - 10] = '\0';
+ else if ( len > 8 && strcmp (&fname[len - 8], DKI_ACT_FILEEXT) == 0 )
+ fname[len - 8] = '\0';
+ else if ( len > 12 && strcmp (&fname[len - 12], DKI_DEP_FILEEXT) == 0 )
+ fname[len - 12] = '\0';
+ dbg_line ();
+
+ assert (strlen (dirname)+1 < sizeof (dkp->dname));
+ strcpy (dkp->dname, dirname);
+
+ assert (strlen (fname)+1 < sizeof (dkp->fname));
+ strcpy (dkp->fname, fname);
+ dbg_line ();
+ if ( sscanf (fname, "K%254[^+]+%hd+%d", dkp->name, &dkp->algo, &dkp->tag) != 3 )
+ {
+ snprintf (dki_estr, sizeof (dki_estr),
+ "dki_read: Filename don't match expected format (%s)", fname);
+ return (NULL);
+ }
+
+ pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
+ dbg_val ("dki_read: path \"%s\"\n", path);
+ if ( (fp = fopen (path, "r")) == NULL )
+ {
+ snprintf (dki_estr, sizeof (dki_estr),
+ "dki_read: Can\'t open file \"%s\" for reading", path);
+ return (NULL);
+ }
+
+ dbg_line ();
+ if ( (err = dki_readfile (fp, dkp)) != 0 )
+ {
+ dbg_line ();
+ snprintf (dki_estr, sizeof (dki_estr),
+ "dki_read: Can\'t read key from file %s (errno %d)", path, err);
+ fclose (fp);
+ return (NULL);
+ }
+
+ dbg_line ();
+ if ( fstat (fileno(fp), &st) )
+ {
+ snprintf (dki_estr, sizeof (dki_estr),
+ "dki_read: Can\'t stat file %s", fname);
+ return (NULL);
+ }
+ dkp->time = st.st_mtime;
+
+ dbg_line ();
+ pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_ACT_FILEEXT);
+ if ( fileexist (path) )
+ {
+ if ( dki_isrevoked (dkp) )
+ dkp->status = DKI_REV;
+ else
+ dkp->status = DKI_ACT;
+ }
+ else
+ {
+ pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_PUB_FILEEXT);
+ if ( fileexist (path) )
+ dkp->status = DKI_PUB;
+ else
+ {
+ pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_DEP_FILEEXT);
+ if ( fileexist (path) )
+ dkp->status = DKI_DEP;
+ else
+ dkp->status = DKI_SEP;
+ }
+ }
+
+ dbg_line ();
+ fclose (fp);
+
+ dbg_line ();
+ return dkp;
+}
+
+/*****************************************************************
+** dki_readdir ()
+** read key files from directory 'dir' and, if recursive is
+** true, from all directorys below that.
+*****************************************************************/
+int dki_readdir (const char *dir, dki_t **listp, int recursive)
+{
+ dki_t *dkp;
+ DIR *dirp;
+ struct dirent *dentp;
+ char path[MAX_PATHSIZE+1];
+
+ dbg_val ("directory: opendir(%s)\n", dir);
+ if ( (dirp = opendir (dir)) == NULL )
+ return 0;
+
+ while ( (dentp = readdir (dirp)) != NULL )
+ {
+ if ( is_dotfile (dentp->d_name) )
+ continue;
+
+ dbg_val ("directory: check %s\n", dentp->d_name);
+ pathname (path, sizeof (path), dir, dentp->d_name, NULL);
+ if ( is_directory (path) && recursive )
+ {
+ dbg_val ("directory: recursive %s\n", path);
+ dki_readdir (path, listp, recursive);
+ }
+ else if ( is_keyfilename (dentp->d_name) )
+ if ( (dkp = dki_read (dir, dentp->d_name)) )
+ dki_add (listp, dkp);
+ }
+ closedir (dirp);
+ return 1;
+}
+
+/*****************************************************************
+** dki_setstatus_preservetime ()
+** set status of key and change extension to
+** ".published", ".private" or ".depreciated"
+*****************************************************************/
+int dki_setstatus_preservetime (dki_t *dkp, int status)
+{
+ return dki_setstat (dkp, status, 1);
+}
+
+/*****************************************************************
+** dki_setstatus ()
+** set status of key and change extension to
+** ".published", ".private" or ".depreciated"
+*****************************************************************/
+int dki_setstatus (dki_t *dkp, int status)
+{
+ return dki_setstat (dkp, status, 0);
+}
+
+/*****************************************************************
+** dki_setstat ()
+** low level function of dki_setstatus and dki_setstatus_preservetime
+*****************************************************************/
+static int dki_setstat (dki_t *dkp, int status, int preserve_time)
+{
+ char frompath[MAX_PATHSIZE+1];
+ char topath[MAX_PATHSIZE+1];
+ time_t totime;
+ time_t currtime;
+
+ if ( dkp == NULL )
+ return 0;
+
+ currtime = time (NULL);
+ status = tolower (status);
+ switch ( dkp->status ) /* look at old status */
+ {
+ case 'r':
+ if ( status == 'r' )
+ return 1;
+ break;
+ case 'a':
+ if ( status == 'a' )
+ return 1;
+ pathname (frompath, sizeof (frompath), dkp->dname, dkp->fname, DKI_ACT_FILEEXT);
+ break;
+ case 'd':
+ if ( status == 'd' )
+ return 1;
+ pathname (frompath, sizeof (frompath), dkp->dname, dkp->fname, DKI_DEP_FILEEXT);
+ break;
+ case 'p': /* or 's' */
+ if ( status == 'p' || status == 's' )
+ return 1;
+ pathname (frompath, sizeof (frompath), dkp->dname, dkp->fname, DKI_PUB_FILEEXT);
+ break;
+ default:
+ /* TODO: set error code */
+ return 0;
+ }
+
+ dbg_val ("dki_setstat: \"%s\"\n", frompath);
+ dbg_val ("dki_setstat: to status \"%c\"\n", status);
+
+ /* a state change could result in different things: */
+ /* 1) write a new keyfile when the REVOKE bit is set or unset */
+ if ( status == 'r' || (status == 'a' && dki_isrevoked (dkp)) )
+ {
+ pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
+
+ if ( status == 'r' )
+ dki_setflag (dkp, DK_FLAG_REVOKE); /* set REVOKE bit */
+ else
+ dki_unsetflag (dkp, DK_FLAG_REVOKE); /* clear REVOKE bit */
+
+
+ dki_writeinfo (dkp, topath); /* ..and write it to the key file */
+
+ if ( !preserve_time )
+ touch (topath, time (NULL));
+
+ return 0;
+ }
+
+
+ /* 2) change the filename of the private key in all other cases */
+ totime = 0L;
+ if ( preserve_time )
+ totime = file_mtime (frompath); /* get original timestamp */
+ topath[0] = '\0';
+ switch ( status )
+ {
+ case 'a':
+ pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_ACT_FILEEXT);
+ break;
+ case 'd':
+ pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_DEP_FILEEXT);
+ break;
+ case 's': /* standby means a "published KSK" */
+ if ( !dki_isksk (dkp) )
+ return 2;
+ status = 'p';
+ /* fall through */
+ case 'p':
+ pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_PUB_FILEEXT);
+ break;
+ }
+
+ if ( topath[0] )
+ {
+ dbg_val ("dki_setstat: to \"%s\"\n", topath);
+ if ( link (frompath, topath) == 0 )
+ unlink (frompath);
+ dkp->status = status;
+ if ( !totime )
+ totime = time (NULL); /* set .key file to current time */
+ pathname (topath, sizeof (topath), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
+ touch (topath, totime); /* store/restore time of status change */
+ }
+
+ return 0;
+}
+
+/*****************************************************************
+** dki_remove ()
+** rename files associated with key, so that the keys are not
+** recognized by the zkt tools e.g.
+** Kdo.ma.in.+001+12345.key ==> kdo.ma.in.+001+12345.key
+** (second one starts with a lower case 'k')
+*****************************************************************/
+dki_t *dki_remove (dki_t *dkp)
+{
+ char path[MAX_PATHSIZE+1];
+ char newpath[MAX_PATHSIZE+1];
+ char newfile[MAX_FNAMESIZE+1];
+ dki_t *next;
+ const char **pext;
+ static const char *ext[] = {
+ DKI_KEY_FILEEXT, DKI_PUB_FILEEXT,
+ DKI_ACT_FILEEXT, DKI_DEP_FILEEXT,
+ NULL
+ };
+
+ if ( dkp == NULL )
+ return NULL;
+
+ strncpy (newfile, dkp->fname, sizeof (newfile));
+ *newfile = tolower (*newfile);
+ for ( pext = ext; *pext; pext++ )
+ {
+ pathname (path, sizeof (path), dkp->dname, dkp->fname, *pext);
+ if ( fileexist (path) )
+ {
+ pathname (newpath, sizeof (newpath), dkp->dname, newfile, *pext);
+
+ dbg_val2 ("dki_remove: %s ==> %s \n", path, newpath);
+ rename (path, newpath);
+ }
+ }
+ next = dkp->next;
+ dki_free (dkp);
+
+ return next;
+}
+
+/*****************************************************************
+** dki_destroy ()
+** delete files associated with key and free allocated memory
+*****************************************************************/
+dki_t *dki_destroy (dki_t *dkp)
+{
+ char path[MAX_PATHSIZE+1];
+ dki_t *next;
+ const char **pext;
+ static const char *ext[] = {
+ DKI_KEY_FILEEXT, DKI_PUB_FILEEXT,
+ DKI_ACT_FILEEXT, DKI_DEP_FILEEXT,
+ NULL
+ };
+
+ if ( dkp == NULL )
+ return NULL;
+
+ for ( pext = ext; *pext; pext++ )
+ {
+ pathname (path, sizeof (path), dkp->dname, dkp->fname, *pext);
+ if ( fileexist (path) )
+ {
+ dbg_val ("dki_remove: %s \n", path);
+ unlink (path);
+ }
+ }
+ next = dkp->next;
+ dki_free (dkp);
+
+ return next;
+}
+
+/*****************************************************************
+** dki_algo2str ()
+** return a string describing the key algorithm
+*****************************************************************/
+char *dki_algo2str (int algo)
+{
+ switch ( algo )
+ {
+ case DK_ALGO_RSA: return ("RSAMD5");
+ case DK_ALGO_DH: return ("DH");
+ case DK_ALGO_DSA: return ("DSA");
+ case DK_ALGO_EC: return ("EC");
+ case DK_ALGO_RSASHA1: return ("RSASHA1");
+ }
+ return ("unknown");
+}
+
+/*****************************************************************
+** dki_geterrstr ()
+** return error string
+*****************************************************************/
+const char *dki_geterrstr ()
+{
+ return dki_estr;
+}
+
+/*****************************************************************
+** dki_prt_dnskey ()
+*****************************************************************/
+int dki_prt_dnskey (const dki_t *dkp, FILE *fp)
+{
+ return dki_prt_dnskeyttl (dkp, fp, 0);
+}
+
+/*****************************************************************
+** dki_prt_dnskeyttl ()
+*****************************************************************/
+int dki_prt_dnskeyttl (const dki_t *dkp, FILE *fp, int ttl)
+{
+ char *p;
+
+ dki_estr[0] = '\0';
+ if ( dkp == NULL )
+ return 0;
+
+ fprintf (fp, "%s ", dkp->name);
+ if ( ttl > 0 )
+ fprintf (fp, "%d ", ttl);
+ fprintf (fp, "IN DNSKEY ");
+ fprintf (fp, "%d 3 %d (", dkp->flags, dkp->algo);
+ fprintf (fp, "\n\t\t\t");
+ for ( p = dkp->pubkey; *p ; p++ )
+ if ( *p == ' ' )
+ fprintf (fp, "\n\t\t\t");
+ else
+ putc (*p, fp);
+ fprintf (fp, "\n\t\t");
+ if ( dki_isrevoked (dkp) )
+ fprintf (fp, ") ; key id = %u (original key id = %u)", (dkp->tag + 128) % 65535, dkp->tag);
+ else
+ fprintf (fp, ") ; key id = %u", dkp->tag);
+ fprintf (fp, "\n");
+
+ return 1;
+}
+
+/*****************************************************************
+** dki_prt_dnskey_raw ()
+*****************************************************************/
+int dki_prt_dnskey_raw (const dki_t *dkp, FILE *fp)
+{
+ int days;
+
+ dki_estr[0] = '\0';
+ if ( dkp == NULL )
+ return 0;
+
+ if ( dkp->gentime )
+ fprintf (fp, ";%%\tgenerationtime=%s\n", time2isostr (dkp->gentime, 's'));
+ if ( (days = dki_lifetimedays (dkp)) )
+ fprintf (fp, ";%%\tlifetime=%dd\n", days);
+ if ( dkp->exptime )
+ fprintf (fp, ";%%\texpirationtime=%s\n", time2isostr (dkp->exptime, 's'));
+
+ fprintf (fp, "%s ", dkp->name);
+#if 0
+ if ( ttl > 0 )
+ fprintf (fp, "%d ", ttl);
+#endif
+ fprintf (fp, "IN DNSKEY ");
+ fprintf (fp, "%d 3 %d ", dkp->flags, dkp->algo);
+ fprintf (fp, "%s\n", dkp->pubkey);
+
+ return 1;
+}
+
+/*****************************************************************
+** dki_prt_comment ()
+*****************************************************************/
+int dki_prt_comment (const dki_t *dkp, FILE *fp)
+{
+ int len = 0;
+
+ dki_estr[0] = '\0';
+ if ( dkp == NULL )
+ return len;
+ len += fprintf (fp, "; %s ", dkp->name);
+ len += fprintf (fp, "tag=%u ", dkp->tag);
+ len += fprintf (fp, "algo=%s ", dki_algo2str(dkp->algo));
+ len += fprintf (fp, "generated %s\n", time2str (dkp->time, 's'));
+
+ return len;
+}
+
+/*****************************************************************
+** dki_prt_trustedkey ()
+*****************************************************************/
+int dki_prt_trustedkey (const dki_t *dkp, FILE *fp)
+{
+ char *p;
+ int spaces;
+ int len = 0;
+
+ dki_estr[0] = '\0';
+ if ( dkp == NULL )
+ return len;
+ len += fprintf (fp, "\"%s\" ", dkp->name);
+ spaces = 22 - (strlen (dkp->name) + 3);
+ len += fprintf (fp, "%*s", spaces > 0 ? spaces : 0 , " ");
+ len += fprintf (fp, "%d 3 %d ", dkp->flags, dkp->algo);
+ if ( spaces < 0 )
+ len += fprintf (fp, "\n\t\t\t%7s", " ");
+ len += fprintf (fp, "\"");
+ for ( p = dkp->pubkey; *p ; p++ )
+ if ( *p == ' ' )
+ len += fprintf (fp, "\n\t\t\t\t");
+ else
+ putc (*p, fp), len += 1;
+
+ if ( dki_isrevoked (dkp) )
+ len += fprintf (fp, "\" ; # key id = %u (original key id = %u)\n\n", (dkp->tag + 128) % 65535, dkp->tag);
+ else
+ len += fprintf (fp, "\" ; # key id = %u\n\n", dkp->tag);
+ return len;
+}
+
+
+/*****************************************************************
+** dki_cmp () return <0 | 0 | >0
+*****************************************************************/
+int dki_cmp (const dki_t *a, const dki_t *b)
+{
+ int res;
+
+ dki_estr[0] = '\0';
+ if ( a == NULL ) return -1;
+ if ( b == NULL ) return 1;
+
+ /* sort by domain name, */
+ if ( (res = domaincmp (a->name, b->name)) != 0 )
+ return res;
+
+ /* then by key type, */
+ if ( (res = dki_isksk (b) - dki_isksk (a)) != 0 )
+ return res;
+
+ /* and last by creation time, */
+ return (ulong)a->time - (ulong)b->time;
+}
+
+#if defined(USE_TREE) && USE_TREE
+/*****************************************************************
+** dki_allcmp () return <0 | 0 | >0
+*****************************************************************/
+int dki_allcmp (const dki_t *a, const dki_t *b)
+{
+ int res;
+
+ dki_estr[0] = '\0';
+ if ( a == NULL ) return -1;
+ if ( b == NULL ) return 1;
+
+// fprintf (stderr, "dki_allcmp %s, %s)\n", a->name, b->name);
+ /* sort by domain name, */
+ if ( (res = domaincmp (a->name, b->name)) != 0 )
+ return res;
+
+ /* then by key type, */
+ if ( (res = dki_isksk (b) - dki_isksk (a)) != 0 )
+ return res;
+
+ /* creation time, */
+ if ( (res = (ulong)a->time - (ulong)b->time) != 0 )
+ return res;
+
+ /* and last by tag */
+ return a->tag - b->tag;
+}
+
+/*****************************************************************
+** dki_namecmp () return <0 | 0 | >0
+*****************************************************************/
+int dki_namecmp (const dki_t *a, const dki_t *b)
+{
+ dki_estr[0] = '\0';
+ if ( a == NULL ) return -1;
+ if ( b == NULL ) return 1;
+
+ return domaincmp (a->name, b->name);
+}
+/*****************************************************************
+** dki_tagcmp () return <0 | 0 | >0
+*****************************************************************/
+int dki_tagcmp (const dki_t *a, const dki_t *b)
+{
+ dki_estr[0] = '\0';
+ if ( a == NULL ) return -1;
+ if ( b == NULL ) return 1;
+
+ return a->tag - b->tag;
+}
+#endif
+
+/*****************************************************************
+** dki_timecmp ()
+*****************************************************************/
+int dki_timecmp (const dki_t *a, const dki_t *b)
+{
+ dki_estr[0] = '\0';
+ if ( a == NULL ) return -1;
+ if ( b == NULL ) return 1;
+
+ return ((ulong)a->time - (ulong)b->time);
+}
+
+/*****************************************************************
+** dki_time () return the timestamp of the key
+*****************************************************************/
+time_t dki_time (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+ return (dkp->time);
+}
+
+/*****************************************************************
+** dki_exptime () return the expiration timestamp of the key
+*****************************************************************/
+time_t dki_exptime (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+ return (dkp->exptime);
+}
+
+/*****************************************************************
+** dki_lifetime (dkp) return the lifetime of the key in sec!
+*****************************************************************/
+time_t dki_lifetime (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+ return (dkp->lifetime);
+}
+
+/*****************************************************************
+** dki_lifetimedays (dkp) return the lifetime of the key in days!
+*****************************************************************/
+ushort dki_lifetimedays (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+ return (dkp->lifetime / DAYSEC);
+}
+
+/*****************************************************************
+** dki_gentime (dkp) return the generation timestamp of the key
+*****************************************************************/
+time_t dki_gentime (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+ return (dkp->gentime > 0L ? dkp->gentime: dkp->time);
+}
+
+/*****************************************************************
+** dki_setlifetime (dkp, int days)
+** set the lifetime in days (and also the gentime if not set)
+** return the old lifetime of the key in days!
+*****************************************************************/
+ushort dki_setlifetime (dki_t *dkp, int days)
+{
+ ulong lifetsec;
+ char path[MAX_PATHSIZE+1];
+
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+
+ lifetsec = dkp->lifetime; /* old lifetime */
+ dkp->lifetime = days * DAYSEC; /* set new lifetime */
+
+ dbg_val1 ("dki_setlifetime (%d)\n", days);
+ if ( lifetsec == 0 ) /* initial setup (old lifetime was zero)? */
+ dkp->gentime = dkp->time;
+
+ pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
+ dki_writeinfo (dkp, path);
+
+ return (lifetsec / DAYSEC);
+}
+
+/*****************************************************************
+** dki_setexptime (dkp, time_t sec)
+** set the expiration time of the key in seconds since the epoch
+** return the old exptime
+*****************************************************************/
+time_t dki_setexptime (dki_t *dkp, time_t sec)
+{
+ char path[MAX_PATHSIZE+1];
+ time_t oldexptime;
+
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+
+ dbg_val1 ("dki_setexptime (%ld)\n", sec);
+ oldexptime = dkp->exptime;
+ dkp->exptime = sec;
+
+ pathname (path, sizeof (path), dkp->dname, dkp->fname, DKI_KEY_FILEEXT);
+ dki_writeinfo (dkp, path);
+
+#if 0 /* not necessary ? */
+ touch (path, time (NULL));
+#endif
+ return (oldexptime);
+}
+
+/*****************************************************************
+** dki_age () return age of key in seconds since 'curr'
+*****************************************************************/
+int dki_age (const dki_t *dkp, time_t curr)
+{
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+ return ((ulong)curr - (ulong)dkp->time);
+}
+
+/*****************************************************************
+** dki_getflag () return the flags field of a key
+*****************************************************************/
+dk_flag_t dki_getflag (const dki_t *dkp, time_t curr)
+{
+ dki_estr[0] = '\0';
+ return dkp->flags;
+}
+
+/*****************************************************************
+** dki_setflag () set a flag of a key
+*****************************************************************/
+dk_flag_t dki_setflag (dki_t *dkp, dk_flag_t flag)
+{
+ dki_estr[0] = '\0';
+ return dkp->flags |= (ushort)flag;
+}
+
+/*****************************************************************
+** dki_unsetflag () unset a flag of a key
+*****************************************************************/
+dk_flag_t dki_unsetflag (dki_t *dkp, dk_flag_t flag)
+{
+ dki_estr[0] = '\0';
+ return dkp->flags &= ~((ushort)flag);
+}
+
+/*****************************************************************
+** dki_isksk ()
+*****************************************************************/
+int dki_isksk (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+ return (dkp->flags & DK_FLAG_KSK) == DK_FLAG_KSK;
+}
+
+/*****************************************************************
+** dki_isrevoked ()
+*****************************************************************/
+int dki_isrevoked (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+ return (dkp->flags & DK_FLAG_REVOKE) == DK_FLAG_REVOKE;
+}
+
+/*****************************************************************
+** dki_isdepreciated ()
+*****************************************************************/
+int dki_isdepreciated (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ return dki_status (dkp) == DKI_DEPRECIATED;
+}
+
+/*****************************************************************
+** dki_isactive ()
+*****************************************************************/
+int dki_isactive (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ return dki_status (dkp) == DKI_ACTIVE;
+}
+
+/*****************************************************************
+** dki_ispublished ()
+*****************************************************************/
+int dki_ispublished (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ return dki_status (dkp) == DKI_PUBLISHED;
+}
+
+
+/*****************************************************************
+** dki_status () return key status
+*****************************************************************/
+dk_status_t dki_status (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+ return (dkp->status);
+}
+
+/*****************************************************************
+** dki_statusstr () return key status as string
+*****************************************************************/
+const char *dki_statusstr (const dki_t *dkp)
+{
+ dki_estr[0] = '\0';
+ assert (dkp != NULL);
+ switch ( dkp->status )
+ {
+ case DKI_ACT: return "active";
+ case DKI_PUB: if ( dki_isksk (dkp) )
+ return "standby";
+ else
+ return "published";
+ case DKI_DEP: return "depreciated";
+ case DKI_REV: return "revoked";
+ case DKI_SEP: return "sep";
+ }
+ return "unknown";
+}
+
+/*****************************************************************
+** dki_add () add a key to the given list
+*****************************************************************/
+dki_t *dki_add (dki_t **list, dki_t *new)
+{
+ dki_t *curr;
+ dki_t *last;
+
+ dki_estr[0] = '\0';
+ if ( list == NULL )
+ return NULL;
+ if ( new == NULL )
+ return *list;
+
+ last = curr = *list;
+ while ( curr && dki_cmp (curr, new) < 0 )
+ {
+ last = curr;
+ curr = curr->next;
+ }
+
+ if ( curr == *list ) /* add node at start of list */
+ *list = new;
+ else /* add node at end or between two nodes */
+ last->next = new;
+ new->next = curr;
+
+ return *list;
+}
+
+/*****************************************************************
+** dki_search () search a key with the given tag, or the first
+** occurence of a key with the given name
+*****************************************************************/
+const dki_t *dki_search (const dki_t *list, int tag, const char *name)
+{
+ const dki_t *curr;
+
+ dki_estr[0] = '\0';
+ curr = list;
+ if ( tag )
+ while ( curr && (tag != curr->tag ||
+ (name && *name && strcmp (name, curr->name) != 0)) )
+ curr = curr->next;
+ else if ( name && *name )
+ while ( curr && strcmp (name, curr->name) != 0 )
+ curr = curr->next;
+ else
+ curr = NULL;
+
+ return curr;
+}
+
+#if defined(USE_TREE) && USE_TREE
+/*****************************************************************
+** dki_tadd () add a key to the given tree
+*****************************************************************/
+dki_t *dki_tadd (dki_t **tree, dki_t *new)
+{
+ dki_t **p;
+
+ dki_estr[0] = '\0';
+ p = tsearch (new, tree, dki_namecmp);
+ if ( *p == new )
+ dbg_val ("dki_tadd: New entry %s added\n", new->name);
+ else
+ {
+ dbg_val ("dki_tadd: New key added to %s\n", new->name);
+ dki_add (p, new);
+ }
+
+ return *p;
+}
+
+/*****************************************************************
+** dki_tsearch () search a key with the given tag, or the first
+** occurence of a key with the given name
+*****************************************************************/
+const dki_t *dki_tsearch (const dki_t *tree, int tag, const char *name)
+{
+ dki_t search;
+ dki_t **p;
+
+ dki_estr[0] = '\0';
+ search.tag = tag;
+ snprintf (search.name, sizeof (search.name), "%s", name);
+ p = tfind (&search, &tree, dki_namecmp);
+ if ( p == NULL )
+ return NULL;
+
+ return dki_search (*p, tag, name);
+}
+#endif
+
+/*****************************************************************
+** dki_find () find the n'th ksk or zsk key with given status
+*****************************************************************/
+const dki_t *dki_find (const dki_t *list, int ksk, int status, int no)
+{
+ const dki_t *dkp;
+ const dki_t *last;
+
+ dki_estr[0] = '\0';
+ last = NULL;
+ for ( dkp = list; no > 0 && dkp; dkp = dkp->next )
+ if ( dki_isksk (dkp) == ksk && dki_status (dkp) == status )
+ {
+ no--;
+ last = dkp;
+ }
+
+ return last;
+}
diff --git a/contrib/zkt/dki.h b/contrib/zkt/dki.h
new file mode 100644
index 0000000..548ce68
--- /dev/null
+++ b/contrib/zkt/dki.h
@@ -0,0 +1,185 @@
+/*****************************************************************
+**
+** @(#) dki.h -- Header file for DNSsec Key info/manipulation
+**
+** Copyright (c) July 2004 - Jan 2005, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+#ifndef DKI_H
+# define DKI_H
+
+# ifndef TYPES_H
+# include <sys/types.h>
+# include <stdio.h>
+# include <time.h>
+# endif
+
+# define MAX_LABELSIZE (255)
+# define MAX_FNAMESIZE (1+255+2+3+1+5+1+11)
+ /* Kdomain.+ALG+KEYID.type */
+ /* domain == FQDN (max 255) */
+ /* ALG == 3; KEYID == 5 chars */
+ /* type == key||published|private|depreciated == 11 chars */
+//# define MAX_DNAMESIZE (254)
+# define MAX_DNAMESIZE (1023)
+ /* /path/name / filename */
+# define MAX_PATHSIZE (MAX_DNAMESIZE + 1 + MAX_FNAMESIZE)
+
+/* algorithm types */
+# define DK_ALGO_RSA 1 /* RFC2537 */
+# define DK_ALGO_DH 2 /* RFC2539 */
+# define DK_ALGO_DSA 3 /* RFC2536 (mandatory) */
+# define DK_ALGO_EC 4 /* */
+# define DK_ALGO_RSASHA1 5 /* RFC3110 */
+
+/* protocol types */
+# define DK_PROTO_DNS 3
+
+/* flag bits */
+typedef enum { /* 11 1111 */
+ /* 0123 4567 8901 2345 */
+ DK_FLAG_KSK= 01, /* 0000 0000 0000 0001 Bit 15 RFC4034/RFC3757 */
+ DK_FLAG_REVOKE= 0200, /* 0000 0000 1000 0000 Bit 8 RFC5011 */
+ DK_FLAG_ZONE= 0400, /* 0000 0001 0000 0000 Bit 7 RFC4034 */
+} dk_flag_t;
+
+/* status types */
+typedef enum {
+ DKI_SEP= 'e',
+ DKI_SECUREENTRYPOINT= 'e',
+ DKI_PUB= 'p',
+ DKI_PUBLISHED= 'p',
+ DKI_ACT= 'a',
+ DKI_ACTIVE= 'a',
+ DKI_DEP= 'd',
+ DKI_DEPRECIATED= 'd',
+ DKI_REV= 'r',
+ DKI_REVOKED= 'r',
+} dk_status_t;
+
+# define DKI_KEY_FILEEXT ".key"
+# define DKI_PUB_FILEEXT ".published"
+# define DKI_ACT_FILEEXT ".private"
+# define DKI_DEP_FILEEXT ".depreciated"
+
+# define DKI_KSK 1
+# define DKI_ZSK 0
+
+typedef struct dki {
+ char dname[MAX_DNAMESIZE+1]; /* directory */
+ char fname[MAX_FNAMESIZE+1]; /* file name without extension */
+ char name[MAX_LABELSIZE+1]; /* domain name or label */
+ ushort algo; /* key algorithm */
+ ushort proto; /* must be 3 (DNSSEC) */
+ dk_flag_t flags; /* ZONE, optional SEP or REVOKE flag */
+ time_t time; /* key file time */
+ time_t gentime; /* key generation time (will be set on key generation and never changed) */
+ time_t exptime; /* time the key was expired (0L if not) */
+ ulong lifetime; /* proposed key life time at time of generation */
+ uint tag; /* key id */
+ dk_status_t status; /* key exist (".key") and name of private */
+ /* key file is ".published", ".private" */
+ /* or ".depreciated" */
+ char *pubkey; /* base64 public key */
+ struct dki *next; /* ptr to next entry in list */
+} dki_t;
+
+#if defined(USE_TREE) && USE_TREE
+/*
+ * Instead of including <search.h>, which contains horrible false function
+ * declarations, we declared it for our usage (Yes, these functions return
+ * the adress of a pointer variable)
+ */
+typedef enum
+{
+ /* we change the naming to the new, and more predictive one, used by Knuth */
+ PREORDER, /* preorder, */
+ INORDER, /* postorder, */
+ POSTORDER, /* endorder, */
+ LEAF /* leaf */
+}
+VISIT;
+
+dki_t **tsearch (const dki_t *dkp, dki_t **tree, int(*compar)(const dki_t *, const dki_t *));
+dki_t **tfind (const dki_t *dkp, const dki_t **tree, int(*compar)(const dki_t *, const dki_t *));
+dki_t **tdelete (const dki_t *dkp, dki_t **tree, int(*compar)(const dki_t *, const dki_t *));
+void twalk (const dki_t *root, void (*action)(const dki_t **nodep, VISIT which, int depth));
+
+extern void dki_tfree (dki_t **tree);
+extern dki_t *dki_tadd (dki_t **tree, dki_t *new);
+extern int dki_tagcmp (const dki_t *a, const dki_t *b);
+extern int dki_namecmp (const dki_t *a, const dki_t *b);
+extern int dki_allcmp (const dki_t *a, const dki_t *b);
+#endif
+
+extern dki_t *dki_read (const char *dir, const char *fname);
+extern int dki_readdir (const char *dir, dki_t **listp, int recursive);
+extern int dki_prt_trustedkey (const dki_t *dkp, FILE *fp);
+extern int dki_prt_dnskey (const dki_t *dkp, FILE *fp);
+extern int dki_prt_dnskeyttl (const dki_t *dkp, FILE *fp, int ttl);
+extern int dki_prt_dnskey_raw (const dki_t *dkp, FILE *fp);
+extern int dki_prt_comment (const dki_t *dkp, FILE *fp);
+extern int dki_cmp (const dki_t *a, const dki_t *b);
+extern int dki_timecmp (const dki_t *a, const dki_t *b);
+extern int dki_age (const dki_t *dkp, time_t curr);
+extern dk_flag_t dki_getflag (const dki_t *dkp, time_t curr);
+extern dk_flag_t dki_setflag (dki_t *dkp, dk_flag_t flag);
+extern dk_flag_t dki_unsetflag (dki_t *dkp, dk_flag_t flag);
+extern dk_status_t dki_status (const dki_t *dkp);
+extern const char *dki_statusstr (const dki_t *dkp);
+extern int dki_isksk (const dki_t *dkp);
+extern int dki_isdepreciated (const dki_t *dkp);
+extern int dki_isrevoked (const dki_t *dkp);
+extern int dki_isactive (const dki_t *dkp);
+extern int dki_ispublished (const dki_t *dkp);
+extern time_t dki_time (const dki_t *dkp);
+extern time_t dki_exptime (const dki_t *dkp);
+extern time_t dki_gentime (const dki_t *dkp);
+extern time_t dki_lifetime (const dki_t *dkp);
+extern ushort dki_lifetimedays (const dki_t *dkp);
+extern ushort dki_setlifetime (dki_t *dkp, int days);
+extern time_t dki_setexptime (dki_t *dkp, time_t sec);
+extern dki_t *dki_new (const char *dir, const char *name, int ksk, int algo, int bitsize, const char *rfile, int lf_days);
+extern dki_t *dki_remove (dki_t *dkp);
+extern dki_t *dki_destroy (dki_t *dkp);
+extern int dki_setstatus (dki_t *dkp, int status);
+extern int dki_setstatus_preservetime (dki_t *dkp, int status);
+extern dki_t *dki_add (dki_t **dkp, dki_t *new);
+extern const dki_t *dki_tsearch (const dki_t *tree, int tag, const char *name);
+extern const dki_t *dki_search (const dki_t *list, int tag, const char *name);
+extern const dki_t *dki_find (const dki_t *list, int ksk, int status, int first);
+extern void dki_free (dki_t *dkp);
+extern void dki_freelist (dki_t **listp);
+extern char *dki_algo2str (int algo);
+extern const char *dki_geterrstr (void);
+
+#endif
diff --git a/contrib/zkt/dnssec-signer.8 b/contrib/zkt/dnssec-signer.8
new file mode 100644
index 0000000..07c3c6c
--- /dev/null
+++ b/contrib/zkt/dnssec-signer.8
@@ -0,0 +1,436 @@
+.TH dnssec-signer 8 "June 27, 2008" "ZKT 0.96" ""
+\" turn off hyphenation
+.\" if n .nh
+.nh
+.SH NAME
+dnssec-signer \(em Secure DNS zone signing tool
+
+.SH SYNOPSYS
+.na
+.B dnssec-signer
+.RB [ \-L|--logfile
+.IR "file" ]
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-fhnr ]
+.RB [ \-v
+.RB [ \-v ]]
+.B \-N
+.I "named.conf"
+.RI [ zone
+.RI "" ... ]
+.br
+.B dnssec-signer
+.RB [ \-L|--logfile
+.IR "file" ]
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-fhnr ]
+.RB [ \-v
+.RB [ \-v ]]
+.RB [ \-D
+.IR "directory" ]
+.RI [ zone
+.RI "" ... ]
+.br
+.B dnssec-signer
+.RB [ \-L|--logfile
+.IR "file" ]
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-fhnr ]
+.RB [ \-v
+.RB [ \-v ]]
+.B \-o
+.IR "origin"
+.RI [ zonefile ]
+
+.SH DESCRIPTION
+The
+.I dnssec-signer
+command is a wrapper around
+.I dnssec-signzone(8)
+and
+.I dnssec-keygen(8)
+to sign a zone and manage the necessary zone keys.
+It's able to increment the serial number before signing the zone
+and can trigger
+.I named(8)
+to reload the signed zone file.
+The command controls several secure zones and, if started in regular
+intervals via
+.IR cron(8) ,
+can do all that stuff automatically.
+.PP
+In the most useful usage scenario the command will be called with option
+.B \-N
+to read the secure zones out of the given
+.I named.conf
+file.
+If you have a configuration file with views, you have to use option
+-V viewname or --view viewname to specify the name of the view.
+Alternatively you could link the executable file to a second name like
+.I dnssec-signer-viewname
+and use that command to specify the name of the view.
+All master zone statements will be scanned for filenames
+ending with ".signed".
+These zones will be checked if the necessary zone- and key signing keys
+are existent and fresh enough to be used in the signing process.
+If some out-dated keys where found, new keying material will be generated via
+the
+.I dnssec-keygen(8)
+command and the old ones will be marked as depreciated.
+So the command do anything needed for a zone key rollover as defined by [2].
+.PP
+If the resigning interval is reached or any new key must be announced,
+the serial number of the zone will be incremented and the
+.I dnssec-signzone(8)
+command will be evoked to sign the zone.
+After that, if the option
+.B \-r
+is given, the
+.I rndc(8)
+command will be called to reload the zone on the
+nameserver.
+.PP
+In the second form of the command it's possible to specify a directory
+tree with the option
+.B \-D
+.IR dir .
+Every secure zone found in a subdirectory below
+.I dir
+will be signed.
+However, it's also possible to reduce the signing to those
+zones given as arguments.
+In directory mode the pre-requisite is, that the directory name is
+exactly (including the trailing dot) the same as the zone name.
+.PP
+In the last form of the command, the functionality is more or less the same
+as the
+.I dnssec-signzone (8)
+command.
+The parameter specify the zone file name and the option
+.B \-o
+takes the name of the zone.
+.PP
+If neither
+.B \-N
+nor
+.B \-D
+nor
+.B \-o
+is given, then the default directory specified in the
+.I dnssec.conf
+file by the parameter
+.I zonedir
+will be used as the top level directory.
+
+.SH OPTIONS
+.TP
+.BI \-L " file|dir" ", \-\-logfile=" file|dir
+Specify the name of a log file or a directory where
+logfiles are created with a name like
+.fam C
+.\"# define LOG_FNAMETMPL "/zkt-%04d-%02d-%02dT%02d%02d%02dZ.log"
+.RI zkt- YYYY-MM-DD T hhmmss Z.log .
+.fam T
+.\" \&.
+If the argument is not an absolute path name and a zone directory
+is specified in the config file, this will prepend the given name.
+This option is also settable in the dnssec.conf file via the parameter
+.BI LogFile .
+.br
+The default is no file logging, but error logging to syslog with facility
+.BI USER
+at level
+.BI ERROR
+is enabled by default.
+These parameters are settable via the config file parameter
+.BI "SyslogFacility:" ,
+.BI "SyslogLevel:" ,
+.BI "LogFile:"
+and
+.BI "Loglevel" .
+.br
+There is an additional parameter
+.BI VerboseLog:
+which specifies the verbosity (0|1|2) of messages that will be logged
+with level
+.BI DEBUG
+to file and syslog.
+
+.TP
+.BI \-V " view" ", \-\-view=" view
+Try to read the default configuration out of a file named
+.I dnssec-<view>.conf .
+Instead of specifying the \-V or --view option every time,
+it's also possible to create a hard or softlink to the
+executable file with an additional name like
+.I dnssec-zkt-<view> .
+.TP
+.BI \-c " file" ", \-\-config=" file
+Read configuration values out of the specified file.
+Otherwise the default config file is read or build-in defaults
+will be used.
+.TP
+.BI \-O " optstr" ", \-\-config-option=" optstr
+Set any config file option via the commandline.
+Several config file options could be specified at the argument string
+but have to be delimited by semicolon (or newline).
+.TP
+.BR \-f ", " \-\-force
+Force a resigning of the zone, regardless if the resigning interval
+is reached, or any new keys must be announced.
+.TP
+.BR \-n ", " \-\-noexec
+Don't execute the
+.I dnssec-signzone(8)
+command.
+Currently this option is of very limited usage.
+.TP
+.BR \-r ", " \-\-reload
+Reload the zone via
+.I rndc(8)
+after successful signing.
+In a production environment it's recommended to use this option
+to be sure that a freshly signed zone will be immediately propagated.
+However, that's only feasable if the named runs on the signing
+machine, which is not recommended.
+Otherwise the signed zonefile must be copied to the production
+server before reloading the zone.
+If this is the case, the parameter
+.I propagation
+in the
+.I dnssec.conf
+file must be set to a reasonable value.
+.TP
+.BR \-v ", " \-\-verbose
+Verbose mode (recommended).
+A second
+.B \-v
+will be a little more verbose.
+.TP
+.BR \-h ", " \-\-help
+Print out the online help.
+
+.SH SAMPLE USAGE
+.TP
+.fam C
+.B "dnssec-signer \-N /var/named/named.conf \-r \-v \-v
+.fam T
+Sign all secure zones found in the named.conf file and, if necessary,
+trigger a reload of the zone.
+Print some explanatory remarks on stdout.
+.TP
+.fam C
+.B "dnssec-signer \-D zonedir/example.net. \-f \-v \-v
+.fam T
+Force the signing of the zone found in the directory
+.I zonedir/example.net .
+Do not reload the zone.
+.TP
+.fam C
+.B "dnssec-signer \-D zonedir \-f \-v \-v example.net.
+.fam T
+Same as above.
+.TP
+.fam C
+.B "dnssec-signer \-f \-v \-v example.net.
+.fam T
+Same as above if the
+.I dnssec.conf
+file contains the path of the parent directory of the
+.I example.net
+zone.
+.TP
+.fam C
+.B "dnssec-signer \-f \-v \-v \-o example.net. zone.db
+.fam T
+Same as above if we are in the directory containing the
+.I example.net
+files.
+.TP
+.fam C
+.B "dnssec-signer \-\-config-option='ResignInterval 1d; Sigvalidity 28h; \e
+.B ZSK_lifetime 2d;' \-v \-v \-o example.net. zone.db
+.fam T
+.br
+Sign the example.net zone but overwrite some config file values with the parameters
+given on the commandline.
+
+.SH Zone setup and initial preparation
+.TP
+Create a separate directory for every secure zone.
+.br
+This is useful because there are many additional files needed to
+secure a zone.
+Besides the zone file
+.RI ( zone.db ),
+there is a signed zone file
+.RI ( zone.db.signed),
+a minimum of four files containing the keying material,
+a file called
+.I dnskey.db
+with the current used keys,
+and the
+.I dsset-
+and
+.IR keyset- files
+created by the
+.I dnssec-signzone(8)
+command.
+So in summary there is a minimum of nine files used per secure zone.
+For every additional key there are two extra files and
+every delegated subzone creates also two or three files.
+.TP
+Name the directory just like the zone.
+.br
+That's only needed if you want to use the dnssec-signer command in
+directory mode
+.RB ( \-D ).
+Then the name of the zone will be parsed out of the directory name.
+.TP
+Change the name of the zone file to \fIzone.db\fP
+Otherwise you have to set the name via the
+.I dnssec.conf
+parameter
+.IR zonefile ,
+or you have to use the option
+.B \-o
+to name the zone and specify the zone file as argument.
+.TP
+Add the name of the signed zonefile to the \fInamed.conf\fP file
+The filename is the name of the zone file with the
+extension
+.IR .signed .
+Create an empty file with the name
+.IB zonefile .signed
+in the zone directory.
+.TP
+Include the keyfile in the zone.
+The name of the keyfile is settable by the
+.I dnssec.conf
+parameter
+.I keyfile .
+The default is
+.I dnskey.db .
+.br
+.if t \{\
+.nf
+.fam C
+ ...
+ IN NS ns1.example.net.
+ IN NS ns2.example.net.
+$INCLUDE dnskey.db
+ ...
+.fi
+.fam T
+.\}
+.TP
+Control the format of the SOA-Record
+For automatic incrementation of the serial number, the SOA-Record
+must be formated, so that the serial number is on a single line and
+left justified in a field of at least 10 spaces!
+.if t \{\
+.fam C
+.fi 0
+@ IN SOA ns1.example.net. hostmaster.example.net. (
+ 60 ; Serial
+ 43200 ; Refresh
+ 1800 ; Retry
+ 2W ; Expire
+ 7200 ); Minimum
+.fi
+.fam T
+.\}
+If you use a BIND Verison of 9.4 or greater and
+use the unixtime format for the serial number (See parameter
+Serialformat in
+.IR dnssec.conf )
+than this is not necessary.
+.TP
+Try to sign the zone
+If the current working directory is the directory of the zone
+.IR example.net ,
+use the command
+.fam C
+.nf
+.sp 0.5
+ $ dnssec-signer \-D .. \-v \-v example.net
+ $ dnssec-signer \-o example.net.
+.sp 0.5
+.fi
+.fam T
+to create the initial keying material and a signed zone file.
+Then try to load the file on the name server.
+
+.SH ENVIRONMENT VARIABLES
+.TP
+ZKT_CONFFILE
+Specifies the name of the default global configuration files.
+
+.SH FILES
+.TP
+.I /var/named/dnssec.conf
+Built-in default global configuration file.
+The name of the default global config file is settable via
+the environment variable ZKT_CONFFILE.
+Use
+.I dnssec-zkt(8)
+with option
+.B \-Z
+to create an initial config file.
+.TP
+.I /var/named/dnssec-<view>.conf
+View specific global configuration file.
+.TP
+.I ./dnssec.conf
+Local configuration file.
+.TP
+.I dnskey.db
+The file contains the currently used key and zone signing keys.
+It will be created by
+.IR dnsssec-signer(8) .
+The name of the file is settable via the dnssec configuration
+file (parameter
+.IR keyfile ).
+.TP
+.I zone.db
+This is the zone file.
+The name of the file is settable via the dnssec configuration
+file (parameter
+.IR zonefile ).
+
+.SH BUGS
+.PP
+The zone name given as an argument must be ending with a dot.
+.PP
+The named.conf parser is a little bit rudimental and not
+very well tested.
+
+.SH AUTHOR
+Holger Zuleger
+
+.SH COPYRIGHT
+Copyright (c) 2005 \- 2008 by Holger Zuleger.
+Licensed under the GPL 2. There is NO warranty; not even for MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.
+.\"--------------------------------------------------
+.SH SEE ALSO
+dnssec-keygen(8), dnssec-signzone(8), rndc(8), named.conf(5), dnssec-zkt(8)
+.br
+RFC4033, RFC4034, RFC4035
+.br
+[1] DNSSEC HOWTO Tutorial by Olaf Kolkman, RIPE NCC
+.br
+(http://www.nlnetlabs.nl/dnssec_howto/)
+.br
+[2] RFC4641 "DNSSEC Operational Practices" by Miek Gieben and Olaf Kolkman
+.br
+(http://www.ietf.org/rfc/rfc4641.txt)
diff --git a/contrib/zkt/dnssec-signer.c b/contrib/zkt/dnssec-signer.c
new file mode 100644
index 0000000..5b2b8f6
--- /dev/null
+++ b/contrib/zkt/dnssec-signer.c
@@ -0,0 +1,1002 @@
+/*****************************************************************
+**
+** @(#) dnssec-signer.c (c) Jan 2005 Holger Zuleger hznet.de
+**
+** A wrapper around the BIND dnssec-signzone command which is able
+** to resign a zone if neccessary and doing a zone or key signing key rollover.
+**
+** Copyright (c) 2005 - 2008, Holger Zuleger HZnet. All rights reserved.
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+# include <assert.h>
+# include <dirent.h>
+# include <errno.h>
+# include <unistd.h>
+# include <ctype.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
+# include <getopt.h>
+#endif
+# include "zconf.h"
+# include "debug.h"
+# include "misc.h"
+# include "ncparse.h"
+# include "zone.h"
+# include "dki.h"
+# include "rollover.h"
+# include "log.h"
+
+#if defined(BIND_VERSION) && BIND_VERSION >= 940
+# define short_options "c:L:V:D:N:o:O:dfHhnrv"
+#else
+# define short_options "c:L:V:D:N:o:O:fHhnrv"
+#endif
+#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
+static struct option long_options[] = {
+ {"reload", no_argument, NULL, 'r'},
+ {"force", no_argument, NULL, 'f'},
+ {"noexec", no_argument, NULL, 'n'},
+ {"verbose", no_argument, NULL, 'v'},
+ {"directory", no_argument, NULL, 'd'},
+ {"config", required_argument, NULL, 'c'},
+ {"option", required_argument, NULL, 'O'},
+ {"config-option", required_argument, NULL, 'O'},
+ {"logfile", required_argument, NULL, 'L' },
+ {"view", required_argument, NULL, 'V' },
+ {"directory", required_argument, NULL, 'D'},
+ {"named-conf", required_argument, NULL, 'N'},
+ {"origin", required_argument, NULL, 'o'},
+#if defined(BIND_VERSION) && BIND_VERSION >= 940
+ {"dynamic", no_argument, NULL, 'd' },
+#endif
+ {"help", no_argument, NULL, 'h'},
+ {0, 0, 0, 0}
+};
+#endif
+
+
+/** function declaration **/
+static void usage (char *mesg, zconf_t *conf);
+static int add2zonelist (const char *dir, const char *view, const char *zone, const char *file);
+static int parsedir (const char *dir, zone_t **zp, const zconf_t *conf);
+static int dosigning (zone_t *zonelist, zone_t *zp);
+static int check_keydb_timestamp (dki_t *keylist, time_t reftime);
+static int new_keysetfiles (const char *dir, time_t zone_signing_time);
+static int writekeyfile (const char *fname, const dki_t *list, int key_ttl);
+static int sign_zone (const char *dir, const char *domain, const char *file, const zconf_t *conf);
+static int dyn_update_freeze (const char *domain, const zconf_t *z, int freeze);
+static int reload_zone (const char *domain, const zconf_t *z);
+static int dist_and_reload (const zone_t *zp);
+static void register_key (dki_t *listp, const zconf_t *z);
+static void copy_keyset (const char *dir, const char *domain, const zconf_t *conf);
+
+/** global command line options **/
+extern int optopt;
+extern int opterr;
+extern int optind;
+extern char *optarg;
+const char *progname;
+const char *viewname = NULL;
+const char *logfile = NULL;
+const char *origin = NULL;
+const char *namedconf = NULL;
+const char *dirname = NULL;
+static int verbose = 0;
+static int force = 0;
+static int reloadflag = 0;
+static int noexec = 0;
+static int dynamic_zone = 0; /* dynamic zone ? */
+static zone_t *zonelist = NULL; /* must be static global because add2zonelist use it */
+static zconf_t *config;
+
+int main (int argc, char *const argv[])
+{
+ int c;
+ int errcnt;
+ int opt_index;
+ char errstr[255+1];
+ char *p;
+ const char *defconfname;
+ zone_t *zp;
+
+ progname = *argv;
+ if ( (p = strrchr (progname, '/')) )
+ progname = ++p;
+ viewname = getnameappendix (progname, "dnssec-signer");
+
+ defconfname = getdefconfname (viewname);
+ config = loadconfig ("", (zconf_t *)NULL); /* load built in config */
+ if ( fileexist (defconfname) ) /* load default config file */
+ config = loadconfig (defconfname, config);
+ if ( config == NULL )
+ fatal ("Couldn't load config: Out of memory\n");
+
+ zonelist = NULL;
+ opterr = 0;
+#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
+ while ( (c = getopt_long (argc, argv, short_options, long_options, &opt_index)) != -1 )
+#else
+ while ( (c = getopt (argc, argv, short_options)) != -1 )
+#endif
+ {
+ switch ( c )
+ {
+ case 'V': /* view name */
+ viewname = optarg;
+ defconfname = getdefconfname (viewname);
+ if ( fileexist (defconfname) ) /* load default config file */
+ config = loadconfig (defconfname, config);
+ if ( config == NULL )
+ fatal ("Out of memory\n");
+ break;
+ case 'c': /* load config from file */
+ config = loadconfig (optarg, config);
+ if ( config == NULL )
+ fatal ("Out of memory\n");
+ break;
+ case 'O': /* load config option from commandline */
+ config = loadconfig_fromstr (optarg, config);
+ if ( config == NULL )
+ fatal ("Out of memory\n");
+ break;
+ case 'o':
+ origin = optarg;
+ break;
+ case 'N':
+ namedconf = optarg;
+ break;
+ case 'D':
+ dirname = optarg;
+ break;
+ case 'L': /* error log file|directory */
+ logfile = optarg;
+ break;
+ case 'f':
+ force++;
+ break;
+ case 'H':
+ case 'h':
+ usage (NULL, config);
+ break;
+#if defined(BIND_VERSION) && BIND_VERSION >= 940
+ case 'd':
+ dynamic_zone = 1;
+ /* dynamic zone requires a name server reload... */
+ reloadflag = 0; /* ...but "rndc thaw" reloads the zone anyway */
+ break;
+#endif
+ case 'n':
+ noexec = 1;
+ break;
+ case 'r':
+ reloadflag = 1;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case '?':
+ if ( isprint (optopt) )
+ snprintf (errstr, sizeof(errstr),
+ "Unknown option \"-%c\".\n", optopt);
+ else
+ snprintf (errstr, sizeof (errstr),
+ "Unknown option char \\x%x.\n", optopt);
+ usage (errstr, config);
+ break;
+ default:
+ abort();
+ }
+ }
+ dbg_line();
+
+ /* store some of the commandline parameter in the config structure */
+ setconfigpar (config, "--view", viewname);
+ setconfigpar (config, "-v", &verbose);
+ if ( logfile == NULL )
+ logfile = config->logfile;
+
+ if ( lg_open (progname, config->syslogfacility, config->sysloglevel, config->zonedir, logfile, config->loglevel) < -1 )
+ fatal ("Couldn't open logfile %s in dir %s\n", logfile, config->zonedir);
+
+#if defined(DBG) && DBG
+ for ( zp = zonelist; zp; zp = zp->next )
+ zone_print ("in main: ", zp);
+#endif
+ lg_args (LG_NOTICE, argc, argv);
+
+ if ( origin ) /* option -o ? */
+ {
+ if ( (argc - optind) <= 0 ) /* no arguments left ? */
+ zone_readdir (".", origin, NULL, &zonelist, config, dynamic_zone);
+ else
+ zone_readdir (".", origin, argv[optind], &zonelist, config, dynamic_zone);
+
+ /* anyway, "delete" all (remaining) arguments */
+ optind = argc;
+
+ /* complain if nothing could read in */
+ if ( zonelist == NULL )
+ {
+ lg_mesg (LG_FATAL, "\"%s\": couldn't read", origin);
+ fatal ("Couldn't read zone \"%s\"\n", origin);
+ }
+ }
+ if ( namedconf ) /* option -N ? */
+ {
+ char dir[255+1];
+
+ memset (dir, '\0', sizeof (dir));
+ if ( config->zonedir )
+ strncpy (dir, config->zonedir, sizeof(dir));
+ if ( !parse_namedconf (namedconf, dir, sizeof (dir), add2zonelist) )
+ fatal ("Can't read file %s as namedconf file\n", namedconf);
+ if ( zonelist == NULL )
+ fatal ("No signed zone found in file %s\n", namedconf);
+ }
+ if ( dirname ) /* option -D ? */
+ {
+ if ( !parsedir (dirname, &zonelist, config) )
+ fatal ("Can't read directory tree %s\n", dirname);
+ if ( zonelist == NULL )
+ fatal ("No signed zone found in directory tree %s\n", dirname);
+ }
+
+ /* none of the above: read current directory tree */
+ if ( zonelist == NULL )
+ parsedir (config->zonedir, &zonelist, config);
+
+ for ( zp = zonelist; zp; zp = zp->next )
+ if ( in_strarr (zp->zone, &argv[optind], argc - optind) )
+ {
+ dosigning (zonelist, zp);
+ verbmesg (1, zp->conf, "\n");
+ }
+
+ zone_freelist (&zonelist);
+
+ errcnt = lg_geterrcnt ();
+ lg_mesg (LG_NOTICE, "end of run: %d error%s occured", errcnt, errcnt == 1 ? "" : "s");
+ lg_close ();
+
+ return errcnt < 64 ? errcnt : 64;
+}
+
+# define sopt_usage(mesg, value) fprintf (stderr, mesg, value)
+#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
+# define lopt_usage(mesg, value) fprintf (stderr, mesg, value)
+# define loptstr(lstr, sstr) lstr
+#else
+# define lopt_usage(mesg, value)
+# define loptstr(lstr, sstr) sstr
+#endif
+static void usage (char *mesg, zconf_t *conf)
+{
+ fprintf (stderr, "%s version %s\n", progname, ZKT_VERSION);
+ fprintf (stderr, "\n");
+
+ fprintf (stderr, "usage: %s [-c file] [-O optstr] ", progname);
+ fprintf (stderr, "[-D directorytree] ");
+ fprintf (stderr, "[-fhnr] [-v [-v]] [zone ...]\n");
+
+ fprintf (stderr, "usage: %s [-c file] [-O optstr] ", progname);
+ fprintf (stderr, "-N named.conf ");
+ fprintf (stderr, "[-fhnr] [-v [-v]] [zone ...]\n");
+
+ fprintf (stderr, "usage: %s [-c file] [-O optstr] ", progname);
+ fprintf (stderr, "-o origin ");
+ fprintf (stderr, "[-fhnr] [-v [-v]] [zonefile.signed]\n");
+
+ fprintf (stderr, "\t-c file%s", loptstr (", --config=file\n", ""));
+ fprintf (stderr, "\t\t read config from <file> instead of %s\n", CONFIG_FILE);
+ fprintf (stderr, "\t-O optstr%s", loptstr (", --config-option=\"optstr\"\n", ""));
+ fprintf (stderr, "\t\t set config options on the commandline\n");
+ fprintf (stderr, "\t-L file|dir%s", loptstr (", --logfile=file|dir\n", ""));
+ fprintf (stderr, "\t\t specify file or directory for the log output\n");
+ fprintf (stderr, "\t-D dir%s", loptstr (", --directory=dir\n", ""));
+ fprintf (stderr, "\t\t parse the given directory tree for a list of secure zones \n");
+ fprintf (stderr, "\t-N file%s", loptstr (", --named-conf=file\n", ""));
+ fprintf (stderr, "\t\t get the list of secure zones out of the named like config file \n");
+ fprintf (stderr, "\t-o zone%s", loptstr (", --origin=zone", ""));
+ fprintf (stderr, "\tspecify the name of the zone \n");
+ fprintf (stderr, "\t\t The file to sign should be given as an argument (default is \"%s.signed\")\n", conf->zonefile);
+ fprintf (stderr, "\t-h%s\t print this help\n", loptstr (", --help", "\t"));
+ fprintf (stderr, "\t-f%s\t force re-signing\n", loptstr (", --force", "\t"));
+ fprintf (stderr, "\t-n%s\t no execution of external signing command\n", loptstr (", --noexec", "\t"));
+ // fprintf (stderr, "\t-r%s\t reload zone via <rndc reload zone> (or via the external distribution command)\n", loptstr (", --reload", "\t"));
+ fprintf (stderr, "\t-r%s\t reload zone via %s\n", loptstr (", --reload", "\t"), conf->dist_cmd ? conf->dist_cmd: "rndc");
+ fprintf (stderr, "\t-v%s\t be verbose (use twice to be very verbose)\n", loptstr (", --verbose", "\t"));
+
+ fprintf (stderr, "\t[zone]\t sign only those zones given as argument\n");
+
+ fprintf (stderr, "\n");
+ fprintf (stderr, "\tif neither -D nor -N nor -o is given, the directory tree specified\n");
+ fprintf (stderr, "\tin the dnssec config file (\"%s\") will be parsed\n", conf->zonedir);
+
+ if ( mesg && *mesg )
+ fprintf (stderr, "%s\n", mesg);
+ exit (127);
+}
+
+/** fill zonelist with infos coming out of named.conf **/
+static int add2zonelist (const char *dir, const char *view, const char *zone, const char *file)
+{
+#ifdef DBG
+ fprintf (stderr, "printzone ");
+ fprintf (stderr, "view \"%s\" " , view);
+ fprintf (stderr, "zone \"%s\" " , zone);
+ fprintf (stderr, "file ");
+ if ( dir && *dir )
+ fprintf (stderr, "%s/", dir);
+ fprintf (stderr, "%s", file);
+ fprintf (stderr, "\n");
+#endif
+ dbg_line ();
+ if ( view[0] != '\0' ) /* view found in named.conf */
+ {
+ if ( viewname == NULL || viewname[0] == '\0' ) /* viewname wasn't set on startup ? */
+ {
+ dbg_line ();
+ error ("zone \"%s\" in view \"%s\" found in name server config, but no matching view was set on startup\n", zone, view);
+ lg_mesg (LG_ERROR, "\"%s\" in view \"%s\" found in name server config, but no matching view was set on startup", zone, view);
+ return 0;
+ }
+ dbg_line ();
+ if ( strcmp (viewname, view) != 0 ) /* zone is _not_ in current view */
+ return 0;
+ }
+ return zone_readdir (dir, zone, file, &zonelist, config, dynamic_zone);
+}
+
+static int parsedir (const char *dir, zone_t **zp, const zconf_t *conf)
+{
+ DIR *dirp;
+ struct dirent *dentp;
+ char path[MAX_PATHSIZE+1];
+
+ dbg_val ("parsedir: (%s)\n", dir);
+ if ( !is_directory (dir) )
+ return 0;
+
+ dbg_line ();
+ zone_readdir (dir, NULL, NULL, zp, conf, dynamic_zone);
+
+ dbg_val ("parsedir: opendir(%s)\n", dir);
+ if ( (dirp = opendir (dir)) == NULL )
+ return 0;
+
+ while ( (dentp = readdir (dirp)) != NULL )
+ {
+ if ( is_dotfile (dentp->d_name) )
+ continue;
+
+ pathname (path, sizeof (path), dir, dentp->d_name, NULL);
+ if ( !is_directory (path) )
+ continue;
+
+ dbg_val ("parsedir: recursive %s\n", path);
+ parsedir (path, zp, conf);
+ }
+ closedir (dirp);
+ return 1;
+}
+
+static int dosigning (zone_t *zonelist, zone_t *zp)
+{
+ char path[MAX_PATHSIZE+1];
+ int err;
+ int newkey;
+ int newkeysetfile;
+ int use_unixtime;
+ time_t currtime;
+ time_t zfile_time;
+ time_t zfilesig_time;
+ char mesg[255+1];
+
+ verbmesg (1, zp->conf, "parsing zone \"%s\" in dir \"%s\"\n", zp->zone, zp->dir);
+
+ pathname (path, sizeof (path), zp->dir, zp->sfile, NULL);
+ dbg_val("parsezonedir fileexist (%s)\n", path);
+ if ( !fileexist (path) )
+ {
+ error ("Not a secure zone directory (%s)!\n", zp->dir);
+ lg_mesg (LG_ERROR, "\"%s\": not a secure zone directory (%s)!", zp->zone, zp->dir);
+ return 1;
+ }
+ zfilesig_time = file_mtime (path);
+
+ pathname (path, sizeof (path), zp->dir, zp->file, NULL);
+ dbg_val("parsezonedir fileexist (%s)\n", path);
+ if ( !fileexist (path) )
+ {
+ error ("No zone file found (%s)!\n", path);
+ lg_mesg (LG_ERROR, "\"%s\": no zone file found (%s)!", zp->zone, path);
+ return 2;
+ }
+
+ zfile_time = file_mtime (path);
+ currtime = time (NULL);
+
+ /* check rfc5011 key signing keys, create new one if neccessary */
+ dbg_msg("parsezonedir check rfc 5011 ksk ");
+ newkey = ksk5011status (&zp->keys, zp->dir, zp->zone, zp->conf);
+ if ( (newkey & 02) != 02 ) /* not a rfc 5011 zone ? */
+ {
+ verbmesg (2, zp->conf, "\t\t->not a rfc5011 zone, looking for a regular ksk rollover\n");
+ /* check key signing keys, create new one if neccessary */
+ dbg_msg("parsezonedir check ksk ");
+ newkey |= kskstatus (zonelist, zp);
+ }
+ else
+ newkey &= ~02; /* reset bit 2 */
+
+ /* check age of zone keys, probably retire (depreciate) or remove old keys */
+ dbg_msg("parsezonedir check zsk ");
+ newkey += zskstatus (&zp->keys, zp->dir, zp->zone, zp->conf);
+
+ /* check age of "dnskey.db" file against age of keyfiles */
+ pathname (path, sizeof (path), zp->dir, zp->conf->keyfile, NULL);
+ dbg_val("parsezonedir check_keydb_timestamp (%s)\n", path);
+ if ( !newkey )
+ newkey = check_keydb_timestamp (zp->keys, file_mtime (path));
+
+ /* if we work in subdir mode, check if there is a new keyset- file */
+ newkeysetfile = 0;
+ if ( !newkey && zp->conf->keysetdir && strcmp (zp->conf->keysetdir, "..") == 0 )
+ newkeysetfile = new_keysetfiles (zp->dir, zfilesig_time);
+
+ /**
+ ** Check if it is time to do a re-sign. This is the case if
+ ** a) the command line flag -f is set, or
+ ** b) new keys are generated, or
+ ** c) we found a new KSK of a delegated domain, or
+ ** d) the "dnskey.db" file is newer than "zone.db"
+ ** e) the "zone.db" is newer than "zone.db.signed" or
+ ** f) "zone.db.signed" is older than the re-sign interval
+ **/
+ mesg[0] = '\0';
+ if ( force )
+ snprintf (mesg, sizeof(mesg), "Option -f");
+ else if ( newkey )
+ snprintf (mesg, sizeof(mesg), "New zone key");
+ else if ( newkeysetfile )
+ snprintf (mesg, sizeof(mesg), "Modified KSK in delegated domain");
+ else if ( file_mtime (path) > zfilesig_time )
+ snprintf (mesg, sizeof(mesg), "Modified keys");
+ else if ( zfile_time > zfilesig_time )
+ snprintf (mesg, sizeof(mesg), "Zone file edited");
+ else if ( (currtime - zfilesig_time) > zp->conf->resign - (OFFSET) )
+ snprintf (mesg, sizeof(mesg), "re-signing interval (%s) reached",
+ str_delspace (age2str (zp->conf->resign)));
+ else if ( dynamic_zone )
+ snprintf (mesg, sizeof(mesg), "dynamic zone");
+
+ if ( *mesg )
+ verbmesg (1, zp->conf, "\tRe-signing necessary: %s\n", mesg);
+ else
+ verbmesg (1, zp->conf, "\tRe-signing not necessary!\n");
+
+ if ( *mesg )
+ lg_mesg (LG_NOTICE, "\"%s\": re-signing triggered: %s", zp->zone, mesg);
+
+ dbg_line ();
+ if ( !(force || newkey || newkeysetfile || zfile_time > zfilesig_time ||
+ file_mtime (path) > zfilesig_time ||
+ (currtime - zfilesig_time) > zp->conf->resign - (OFFSET) || dynamic_zone) )
+ {
+ verbmesg (2, zp->conf, "\tCheck if there is a parent file to copy\n");
+ if ( zp->conf->keysetdir && strcmp (zp->conf->keysetdir, "..") == 0 )
+ copy_keyset (zp->dir, zp->zone, zp->conf); /* copy the parent- file if it exist */
+ return 0; /* nothing to do */
+ }
+
+ /* let's start signing the zone */
+ dbg_line ();
+
+ /* create new "dnskey.db" file */
+ pathname (path, sizeof (path), zp->dir, zp->conf->keyfile, NULL);
+ verbmesg (1, zp->conf, "\tWriting key file \"%s\"\n", path);
+ if ( !writekeyfile (path, zp->keys, zp->conf->key_ttl) )
+ {
+ error ("Can't create keyfile %s \n", path);
+ lg_mesg (LG_ERROR, "\"%s\": can't create keyfile %s", zp->zone , path);
+ }
+
+ err = 1;
+ use_unixtime = ( zp->conf->serialform == Unixtime );
+ dbg_val1 ("Use unixtime = %d\n", use_unixtime);
+#if defined(BIND_VERSION) && BIND_VERSION >= 940
+ if ( !dynamic_zone && !use_unixtime ) /* increment serial no in static zone files */
+#else
+ if ( !dynamic_zone ) /* increment serial no in static zone files */
+#endif
+ {
+ pathname (path, sizeof (path), zp->dir, zp->file, NULL);
+ err = 0;
+ if ( noexec == 0 )
+ {
+ if ( (err = inc_serial (path, use_unixtime)) < 0 )
+ {
+ error ("could not increment serialno of domain %s in file %s: %s!\n",
+ zp->zone, path, inc_errstr (err));
+ lg_mesg (LG_ERROR,
+ "zone \"%s\": couldn't increment serialno in file %s: %s",
+ zp->zone, path, inc_errstr (err));
+ }
+ else
+ verbmesg (1, zp->conf, "\tIncrementing serial number in file \"%s\"\n", path);
+ }
+ else
+ verbmesg (1, zp->conf, "\tIncrementing serial number in file \"%s\"\n", path);
+ }
+
+ /* at last, sign the zone file */
+ if ( err > 0 )
+ {
+ time_t timer;
+
+ verbmesg (1, zp->conf, "\tSigning zone \"%s\"\n", zp->zone);
+ logflush ();
+
+ /* dynamic zones uses incremental signing, so we have to */
+ /* prepare the old (signed) file as new input file */
+ if ( dynamic_zone )
+ {
+ char zfile[MAX_PATHSIZE+1];
+
+ dyn_update_freeze (zp->zone, zp->conf, 1); /* freeze dynamic zone ! */
+
+ pathname (zfile, sizeof (zfile), zp->dir, zp->file, NULL);
+ pathname (path, sizeof (path), zp->dir, zp->sfile, NULL);
+ if ( filesize (path) == 0L ) /* initial signing request */
+ {
+ verbmesg (1, zp->conf, "\tDynamic Zone signing: Initial signing request: Add DNSKEYs to zonefile\n");
+ copyfile (zfile, path, zp->conf->keyfile);
+ }
+ verbmesg (1, zp->conf, "\tDynamic Zone signing: copy old signed zone file %s to new input file %s\n",
+ path, zfile);
+ if ( newkey ) /* if we have new keys, they should be added to the zone file */
+ copyzonefile (path, zfile, zp->conf->keyfile);
+ else /* else we can do a simple file copy */
+ copyfile (path, zfile, NULL);
+ }
+
+ timer = start_timer ();
+ if ( (err = sign_zone (zp->dir, zp->zone, zp->file, zp->conf)) < 0 )
+ {
+ error ("Signing of zone %s failed (%d)!\n", zp->zone, err);
+ lg_mesg (LG_ERROR, "\"%s\": signing failed!", zp->zone);
+ }
+ timer = stop_timer (timer);
+
+ if ( dynamic_zone )
+ dyn_update_freeze (zp->zone, zp->conf, 0); /* thaw dynamic zone file */
+
+ {
+ const char *tstr = str_delspace (age2str (timer));
+
+ if ( !tstr || *tstr == '\0' )
+ tstr = "0s";
+ verbmesg (1, zp->conf, "\tSigning completed after %s.\n", tstr);
+ }
+ }
+
+ copy_keyset (zp->dir, zp->zone, zp->conf);
+
+ if ( err >= 0 && reloadflag )
+ {
+ if ( zp->conf->dist_cmd )
+ dist_and_reload (zp);
+ else
+ reload_zone (zp->zone, zp->conf);
+
+ register_key (zp->keys, zp->conf);
+ }
+
+ return err;
+}
+
+static void register_key (dki_t *list, const zconf_t *z)
+{
+ dki_t *dkp;
+ time_t currtime;
+ time_t age;
+
+ assert ( list != NULL );
+ assert ( z != NULL );
+
+ currtime = time (NULL);
+ for ( dkp = list; dkp && dki_isksk (dkp); dkp = dkp->next )
+ {
+ age = dki_age (dkp, currtime);
+#if 0
+ /* announce "new" and active key signing keys */
+ if ( REG_URL && *REG_URL && dki_status (dkp) == DKI_ACT && age <= z->resign * 4 )
+ {
+ if ( verbose )
+ logmesg ("\tRegister new KSK with tag %d for domain %s\n",
+ dkp->tag, dkp->name);
+ }
+#endif
+ }
+}
+
+/*
+ * This function is not working with symbolic links to keyset- files,
+ * because file_mtime() returns the mtime of the underlying file, and *not*
+ * that of the symlink file.
+ * This is bad, because the keyset-file will be newly generated by dnssec-signzone
+ * on every re-signing call.
+ * Instead, in the case of a hierarchical directory structure, we copy the file
+ * (and so we change the timestamp) only if it was modified after the last
+ * generation (checked with cmpfile(), see func sign_zone()).
+ */
+# define KEYSET_FILE_PFX "keyset-"
+static int new_keysetfiles (const char *dir, time_t zone_signing_time)
+{
+ DIR *dirp;
+ struct dirent *dentp;
+ char path[MAX_PATHSIZE+1];
+ int newkeysetfile;
+
+ if ( (dirp = opendir (dir)) == NULL )
+ return 0;
+
+ newkeysetfile = 0;
+ dbg_val2 ("new_keysetfile (%s, %s)\n", dir, time2str (zone_signing_time, 's'));
+ while ( !newkeysetfile && (dentp = readdir (dirp)) != NULL )
+ {
+ if ( strncmp (dentp->d_name, KEYSET_FILE_PFX, strlen (KEYSET_FILE_PFX)) != 0 )
+ continue;
+
+ pathname (path, sizeof (path), dir, dentp->d_name, NULL);
+ dbg_val2 ("newkeysetfile timestamp of %s = %s\n", path, time2str (file_mtime(path), 's'));
+ if ( file_mtime (path) > zone_signing_time )
+ newkeysetfile = 1;
+ }
+ closedir (dirp);
+
+ return newkeysetfile;
+}
+
+static int check_keydb_timestamp (dki_t *keylist, time_t reftime)
+{
+ dki_t *key;
+
+ assert ( keylist != NULL );
+ if ( reftime == 0 )
+ return 1;
+
+ for ( key = keylist; key; key = key->next )
+ if ( dki_time (key) > reftime )
+ return 1;
+
+ return 0;
+}
+
+static int writekeyfile (const char *fname, const dki_t *list, int key_ttl)
+{
+ FILE *fp;
+ const dki_t *dkp;
+ time_t curr = time (NULL);
+ int ksk;
+
+ if ( (fp = fopen (fname, "w")) == NULL )
+ return 0;
+ fprintf (fp, ";\n");
+ fprintf (fp, ";\t!!! Don\'t edit this file by hand.\n");
+ fprintf (fp, ";\t!!! It will be generated by %s.\n", progname);
+ fprintf (fp, ";\n");
+ fprintf (fp, ";\t Last generation time %s\n", time2str (curr, 's'));
+ fprintf (fp, ";\n");
+
+ fprintf (fp, "\n");
+ fprintf (fp, "; *** List of Key Signing Keys ***\n");
+ ksk = 1;
+ for ( dkp = list; dkp; dkp = dkp->next )
+ {
+ if ( ksk && !dki_isksk (dkp) )
+ {
+ fprintf (fp, "; *** List of Zone Signing Keys ***\n");
+ ksk = 0;
+ }
+ dki_prt_comment (dkp, fp);
+ dki_prt_dnskeyttl (dkp, fp, key_ttl);
+ putc ('\n', fp);
+ }
+
+ fclose (fp);
+ return 1;
+}
+
+static int sign_zone (const char *dir, const char *domain, const char *file, const zconf_t *conf)
+{
+ char cmd[1023+1];
+ char str[1023+1];
+ char rparam[254+1];
+ char keysetdir[254+1];
+ const char *gends;
+ const char *pseudo;
+ const char *param;
+ int len;
+ FILE *fp;
+
+ assert (conf != NULL);
+ assert (domain != NULL);
+
+ len = 0;
+ str[0] = '\0';
+ if ( conf->lookaside && conf->lookaside[0] )
+ len = snprintf (str, sizeof (str), "-l %.250s", conf->lookaside);
+
+ dbg_line();
+#if defined(BIND_VERSION) && BIND_VERSION >= 940
+ if ( !dynamic_zone && conf->serialform == Unixtime )
+ snprintf (str+len, sizeof (str) - len, " -N unixtime");
+#endif
+
+ gends = "";
+ if ( conf->sig_gends )
+ gends = "-g ";
+
+ pseudo = "";
+ if ( conf->sig_pseudo )
+ pseudo = "-p ";
+
+ param = "";
+ if ( conf->sig_param && conf->sig_param[0] )
+ param = conf->sig_param;
+
+ dbg_line();
+ rparam[0] = '\0';
+ if ( conf->sig_random && conf->sig_random[0] )
+ snprintf (rparam, sizeof (rparam), "-r %.250s ", conf->sig_random);
+
+ dbg_line();
+ keysetdir[0] = '\0';
+ if ( conf->keysetdir && conf->keysetdir[0] && strcmp (conf->keysetdir, "..") != 0 )
+ snprintf (keysetdir, sizeof (keysetdir), "-d %.250s ", conf->keysetdir);
+
+ if ( dir == NULL || *dir == '\0' )
+ dir = ".";
+
+ dbg_line();
+#if defined(BIND_VERSION) && BIND_VERSION >= 940
+ if ( dynamic_zone )
+ snprintf (cmd, sizeof (cmd), "cd %s; %s %s %s%s%s%s-o %s -e +%d %s -N increment -f %s.dsigned %s K*.private",
+ dir, SIGNCMD, param, gends, pseudo, rparam, keysetdir, domain, conf->sigvalidity, str, file, file);
+ else
+#endif
+ snprintf (cmd, sizeof (cmd), "cd %s; %s %s %s%s%s%s-o %s -e +%d %s %s K*.private",
+ dir, SIGNCMD, param, gends, pseudo, rparam, keysetdir, domain, conf->sigvalidity, str, file);
+ verbmesg (2, conf, "\t Run cmd \"%s\"\n", cmd);
+ *str = '\0';
+ if ( noexec == 0 )
+ {
+ if ( (fp = popen (cmd, "r")) == NULL || fgets (str, sizeof str, fp) == NULL )
+ return -1;
+ pclose (fp);
+ }
+
+ dbg_line();
+ verbmesg (2, conf, "\t Cmd dnssec-signzone return: \"%s\"\n", str_chop (str, '\n'));
+
+ return 0;
+}
+
+static void copy_keyset (const char *dir, const char *domain, const zconf_t *conf)
+{
+ char fromfile[1024];
+ char tofile[1024];
+ int ret;
+
+ /* propagate "keyset"-file to parent dir */
+ if ( conf->keysetdir && strcmp (conf->keysetdir, "..") == 0 )
+ {
+ /* check if special parent-file exist (ksk rollover) */
+ snprintf (fromfile, sizeof (fromfile), "%s/parent-%s", dir, domain);
+ if ( !fileexist (fromfile) ) /* use "normal" keyset-file */
+ snprintf (fromfile, sizeof (fromfile), "%s/keyset-%s", dir, domain);
+
+ /* verbmesg (2, conf, "\t check \"%s\" against parent dir\n", fromfile); */
+ snprintf (tofile, sizeof (tofile), "%s/../keyset-%s", dir, domain);
+ if ( cmpfile (fromfile, tofile) != 0 )
+ {
+ verbmesg (2, conf, "\t copy \"%s\" to parent dir\n", fromfile);
+ if ( (ret = copyfile (fromfile, tofile, NULL)) != 0 )
+ {
+ error ("Couldn't copy \"%s\" to parent dir (%d:%s)\n",
+ fromfile, ret, strerror(errno));
+ lg_mesg (LG_ERROR, "\%s\": can't copy \"%s\" to parent dir (%d:%s)",
+ domain, fromfile, ret, strerror(errno));
+ }
+ }
+ }
+}
+
+static int dyn_update_freeze (const char *domain, const zconf_t *z, int freeze)
+{
+ char cmdline[254+1];
+ char str[254+1];
+ char *action;
+ FILE *fp;
+
+ assert (z != NULL);
+ if ( freeze )
+ action = "freeze";
+ else
+ action = "thaw";
+
+ if ( z->view )
+ snprintf (str, sizeof (str), "\"%s\" in view \"%s\"", domain, z->view);
+ else
+ snprintf (str, sizeof (str), "\"%s\"", domain);
+
+ lg_mesg (LG_NOTICE, "%s: %s dynamic zone", str, action);
+ verbmesg (1, z, "\t%s dynamic zone %s\n", action, str);
+
+ if ( z->view )
+ snprintf (cmdline, sizeof (cmdline), "%s %s %s IN %s", RELOADCMD, action, domain, z->view);
+ else
+ snprintf (cmdline, sizeof (cmdline), "%s %s %s", RELOADCMD, action, domain);
+
+ verbmesg (2, z, "\t Run cmd \"%s\"\n", cmdline);
+ *str = '\0';
+ if ( noexec == 0 )
+ {
+ if ( (fp = popen (cmdline, "r")) == NULL || fgets (str, sizeof str, fp) == NULL )
+ return -1;
+ pclose (fp);
+ }
+
+ verbmesg (2, z, "\t rndc %s return: \"%s\"\n", action, str_chop (str, '\n'));
+
+ return 0;
+}
+
+/*****************************************************************
+** distribute and reload a zone via "distribute_command"
+*****************************************************************/
+static int dist_and_reload (const zone_t *zp)
+{
+ char path[MAX_PATHSIZE+1];
+ char cmdline[254+1];
+ char zone[254+1];
+ char str[254+1];
+ FILE *fp;
+
+ assert (zp != NULL);
+ assert (zp->conf->dist_cmd != NULL);
+
+ if ( !is_exec_ok (zp->conf->dist_cmd) )
+ {
+ char *mesg;
+
+ if ( getuid () == 0 )
+ mesg = "\tDistribution command %s not run as root\n";
+ else
+ mesg = "\tDistribution command %s not run due to strange file mode settings\n";
+
+ verbmesg (1, zp->conf, mesg, zp->conf->dist_cmd);
+ lg_mesg (LG_ERROR, "exec of distribution command %s disabled due to security reasons", zp->conf->dist_cmd);
+
+ return -1;
+ }
+
+ if ( zp->conf->view )
+ snprintf (zone, sizeof (zone), "\"%s\" in view \"%s\"", zp->zone, zp->conf->view);
+ else
+ snprintf (zone, sizeof (zone), "\"%s\"", zp->zone);
+
+
+ pathname (path, sizeof (path), zp->dir, zp->sfile, NULL);
+
+ lg_mesg (LG_NOTICE, "%s: distribution triggered", zone);
+ verbmesg (1, zp->conf, "\tDistribute zone %s\n", zone);
+ if ( zp->conf->view )
+ snprintf (cmdline, sizeof (cmdline), "%s distribute %s %s %s", zp->conf->dist_cmd, zp->zone, path, zp->conf->view);
+ else
+ snprintf (cmdline, sizeof (cmdline), "%s distribute %s %s", zp->conf->dist_cmd, zp->zone, path);
+
+ *str = '\0';
+ if ( noexec == 0 )
+ {
+ verbmesg (2, zp->conf, "\t Run cmd \"%s\"\n", cmdline);
+ if ( (fp = popen (cmdline, "r")) == NULL || fgets (str, sizeof str, fp) == NULL )
+ return -2;
+ pclose (fp);
+ verbmesg (2, zp->conf, "\t %s distribute return: \"%s\"\n", zp->conf->dist_cmd, str_chop (str, '\n'));
+ }
+
+
+ lg_mesg (LG_NOTICE, "%s: reload triggered", zone);
+ verbmesg (1, zp->conf, "\tReload zone %s\n", zone);
+ if ( zp->conf->view )
+ snprintf (cmdline, sizeof (cmdline), "%s reload %s %s %s", zp->conf->dist_cmd, zp->zone, path, zp->conf->view);
+ else
+ snprintf (cmdline, sizeof (cmdline), "%s reload %s %s", zp->conf->dist_cmd, zp->zone, path);
+
+ *str = '\0';
+ if ( noexec == 0 )
+ {
+ verbmesg (2, zp->conf, "\t Run cmd \"%s\"\n", cmdline);
+ if ( (fp = popen (cmdline, "r")) == NULL || fgets (str, sizeof str, fp) == NULL )
+ return -2;
+ pclose (fp);
+ verbmesg (2, zp->conf, "\t %s reload return: \"%s\"\n", zp->conf->dist_cmd, str_chop (str, '\n'));
+ }
+
+ return 0;
+}
+
+/*****************************************************************
+** reload a zone via "rndc"
+*****************************************************************/
+static int reload_zone (const char *domain, const zconf_t *z)
+{
+ char cmdline[254+1];
+ char str[254+1];
+ FILE *fp;
+
+ assert (z != NULL);
+ // fprintf (stderr, "reload_zone %d :%s: :%s:\n", z->verbosity, domain, z->view);
+ if ( z->view )
+ snprintf (str, sizeof (str), "\"%s\" in view \"%s\"", domain, z->view);
+ else
+ snprintf (str, sizeof (str), "\"%s\"", domain);
+
+ lg_mesg (LG_NOTICE, "%s: reload triggered", str);
+ verbmesg (1, z, "\tReload zone %s\n", str);
+
+ if ( z->view )
+ snprintf (cmdline, sizeof (cmdline), "%s reload %s IN %s", RELOADCMD, domain, z->view);
+ else
+ snprintf (cmdline, sizeof (cmdline), "%s reload %s", RELOADCMD, domain);
+
+ *str = '\0';
+ if ( noexec == 0 )
+ {
+ verbmesg (2, z, "\t Run cmd \"%s\"\n", cmdline);
+ if ( (fp = popen (cmdline, "r")) == NULL || fgets (str, sizeof str, fp) == NULL )
+ return -1;
+ pclose (fp);
+ verbmesg (2, z, "\t rndc reload return: \"%s\"\n", str_chop (str, '\n'));
+ }
+
+ return 0;
+}
diff --git a/contrib/zkt/dnssec-zkt.8 b/contrib/zkt/dnssec-zkt.8
new file mode 100644
index 0000000..b53f8bb
--- /dev/null
+++ b/contrib/zkt/dnssec-zkt.8
@@ -0,0 +1,481 @@
+.TH dnssec-zkt 8 "July 27, 2008" "ZKT 0.97" ""
+\" turn off hyphenation
+.\" if n .nh
+.nh
+.SH NAME
+dnssec-zkt \(em Secure DNS zone key tool
+
+.SH SYNOPSYS
+.na
+.B dnssec-zkt
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-l
+.IR "list" ]
+.RB [ \-adefhkLrptz ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+
+.B dnssec-zkt
+.BR \-C <label>
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-krpz ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+.br
+.B dnssec-zkt
+.BR \-\-create= <label>
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-krpz ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+
+.B dnssec-zkt
+.BR \- { P | A | D | R } <keytag>
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-r ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+.br
+.B dnssec-zkt
+.BR \-\-published= <keytag>
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-r ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+.br
+.B dnssec-zkt
+.BR \-\-active= <keytag>
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-r ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+.br
+.B dnssec-zkt
+.BR \-\-depreciate= <keytag>
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-r ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+.br
+.B dnssec-zkt
+.BR \-\-rename= <keytag>
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-r ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+
+.B dnssec-zkt
+.BR \-\-destroy= <keytag>
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-r ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+
+.B dnssec-zkt
+.B \-T
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-l
+.IR "list" ]
+.RB [ \-hr ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+.br
+.B dnssec-zkt
+.B \-\-list-trustedkeys
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-l
+.IR "list" ]
+.RB [ \-hr ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+
+.B dnssec-zkt
+.B \-K
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-l
+.IR "list" ]
+.RB [ \-hkzr ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+.br
+.B dnssec-zkt
+.B \-\-list-dnskeys
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.RB [ \-l
+.IR "list" ]
+.RB [ \-hkzr ]
+.RI [{ keyfile | dir }
+.RI "" ... ]
+
+.B dnssec-zkt
+.B \-Z
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.br
+.B dnssec-zkt
+.B \-\-zone-config
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+
+.B dnssec-zkt
+.B \-9 | \-\-ksk-rollover
+.br
+.B dnssec-zkt
+.B \-1 | \-\-ksk-roll-phase1
+.I "do.ma.in."
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.br
+.B dnssec-zkt
+.B \-2 | \-\-ksk-roll-phase2
+.I "do.ma.in."
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.br
+.B dnssec-zkt
+.B \-3 | \-\-ksk-roll-phase3
+.I do.ma.in.
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.br
+.B dnssec-zkt
+.B \-0 | \-\-ksk-roll-stat
+.I do.ma.in.
+.RB [ \-V|--view
+.IR "view" ]
+.RB [ \-c
+.IR "file" ]
+.br
+.ad
+
+.SH DESCRIPTION
+The
+.I dnssec-zkt
+command is a wrapper around
+.I dnssec-keygen(8)
+to assist in dnssec zone key management.
+.PP
+In the common usage the command prints out information about
+all dnssec (zone) keys found in the given (or predefined default) directory.
+It's also possible to specify keyfiles (K*.key) as arguments.
+With option
+.B \-r
+subdirectories will be searched recursively, and all dnssec keys found
+will be listed sorted by domain name, key type and generation time.
+In that mode the use of the
+.B \-p
+option may be helpful to find the location of the keyfile in the directory tree.
+.PP
+Other forms of the command print out keys in a format suitable for
+a trusted-key section or as a DNSKEY resource record.
+.PP
+The command is also useful in dns key management.
+It allows key livetime monitoring and status change.
+
+.SH GENERAL OPTIONS
+.TP
+.BI \-V " view" ", \-\-view=" view
+Try to read the default configuration out of a file named
+.I dnssec-<view>.conf .
+Instead of specifying the \-V or --view option every time,
+it's also possible to create a hard or softlink to the
+executable file to give it an additional name like
+.I dnssec-zkt-<view> .
+.TP
+.BI \-c " file" ", \-\-config=" file
+Read default values from the specified config file.
+Otherwise the default config file is read or build in defaults
+will be used.
+.TP
+.BI \-O " optstr" ", \-\-config-option=" optstr
+Set any config file option via the commandline.
+Several config file options could be specified at the argument string
+but have to be delimited by semicolon (or newline).
+.TP
+.BI \-l " list"
+Print out information solely about domains given in the comma or space separated
+list.
+Take care of, that every domain name has a trailing dot.
+.TP
+.BR \-d ", " \-\-directory
+Skip directory arguments.
+This will be useful in combination with wildcard arguments
+to prevent dnsssec-zkt to list all keys found in subdirectories.
+For example "dnssec-zkt -d *" will print out a list of all keys only found in
+the current directory.
+Maybe it's easier to use "dnssec-zkt ." instead (without -r set).
+The option works similar to the \-d option of
+.IR ls(1) .
+.TP
+.BR \-L ", " \-\-left-justify
+Print out the domain name left justified.
+.TP
+.BR \-k ", " \-\-ksk
+Select and print key signing keys only (default depends on command mode).
+.TP
+.BR \-z ", " \-\-zsk
+Select and print zone signing keys only (default depends on command mode).
+.TP
+.BR \-r ", " \-\-recursive
+Recursive mode (default is off).
+.br
+Also settable in the dnssec.conf file (Parameter: Recursive).
+.TP
+.BR \-p ", " \-\-path
+Print pathname in listing mode.
+In -C mode, don't create the new key in the same directory as (already existing)
+keys with the same label.
+.TP
+.BR \-a ", " \-\-age
+Print age of key in weeks, days, hours, minutes and seconds (default is off).
+.br
+Also settable in the dnssec.conf file (Parameter: PrintAge).
+.TP
+.BR \-f ", " \-\-lifetime
+Print the key lifetime.
+.TP
+.BR \-F ", " \-\-setlifetime
+Set the key lifetime of all the selected keys.
+Use option -k, -z, -l or the file and dir argument for key selection.
+.TP
+.BR \-e ", " \-\-exptime
+Print the key expiration time.
+.TP
+.BR \-t ", " \-\-time
+Print the key generation time (default is on).
+.br
+Also settable in the dnssec.conf file (Parameter: PrintTime).
+.TP
+.B \-h
+No header or trusted-key section header and trailer in -T mode
+.PP
+
+.SH COMMAND OPTIONS
+.TP
+.BR \-H ", " \-\-help
+Print out the online help.
+.TP
+.BR \-T ", " \-\-list-trustedkeys
+List all key signing keys as a
+.I named.conf
+trusted-key section.
+Use
+.B \-h
+to supress the section header/trailer.
+.TP
+.BR \-K ", " \-\-list-dnskeys
+List the public part of all the keys in DNSKEY resource record format.
+Use
+.B \-h
+to suppress comment lines.
+.TP
+.BI \-C " zone" ", \-\-create=" zone
+Create a new zone signing key for the given zone.
+Add option
+.B \-k
+to create a key signing key.
+The key algorithm and key length will be examined from built-in default values
+or from the parameter settings in the
+.I dnssec.conf
+file.
+.br
+The keyfile will be created in the current directory if
+the
+.B \-p
+option is specified.
+.TP
+.BI \-R " keyid" ", \-\-revoke=" keyid
+Revoke the key signing key with the given keyid.
+A revoked key has bit 8 in the flags filed set (see RFC5011).
+The keyid is the numeric keytag with an optionally added zone name separated by a colon.
+.TP
+.BI \-\-rename=" keyid
+Rename the key files of the key with the given keyid
+(Look at key file names starting with an lower 'k').
+The keyid is the numeric keytag with an optionally added zone name separated by a colon.
+.TP
+.BI \-\-destroy= keyid
+Deletes the key with the given keyid.
+The keyid is the numeric keytag with an optionally added zone name separated by a colon.
+Beware that this deletes both private and public keyfiles, thus the key is
+unrecoverable lost.
+.TP
+.BI \-P|A|D " keyid," " \-\-published=" keyid, " \-\-active=" keyid, " \-\-depreciated=" keyid
+Change the status of the given dnssec key to
+published
+.RB ( \-P ),
+active
+.RB ( \-A )
+or depreciated
+.RB ( \-D ).
+The
+.I keyid
+is the numeric keytag with an optionally added zone name separated by a colon.
+Setting the status to "published" or "depreciate" will change the filename
+of the private key file to ".published" or ".depreciated" respectivly.
+This prevents the usage of the key as a signing key by the use of
+.IR dnssec-signzone(8) .
+The time of status change will be stored in the 'mtime' field of the corresponding
+".key" file.
+Key activation via option
+.B \-A
+will restore the original timestamp and file name (".private").
+.TP
+.BR \-Z ", " \-\-zone-config
+Write all config parameters to stdout.
+The output is suitable as a template for the
+.I dnssec.conf
+file, so the easiest way to create a
+.I dnssec.conf
+file is to redirect the standard output of the above command.
+Pay attention not to overwrite an existing file.
+.TP
+.BI \-\-ksk-roll-phase[123] " do.ma.in."
+Initiate a key signing key rollover of the specified domain.
+This feature is currently in experimental status and is mainly for the use
+in an hierachical environment.
+Use --ksk-rollover for a little more detailed description.
+
+
+.SH SAMPLE USAGE
+.TP
+.fam C
+.B "dnssec-zkt \-r .
+.fam T
+Print out a list of all zone keys found below the current directory.
+.TP
+.fam C
+.B "dnssec-zkt \-Z \-c """"
+.fam T
+Print out the compiled in default parameters.
+.TP
+.fam C
+.B "dnssec-zkt \-C example.net \-k \-r ./zonedir
+.fam T
+Create a new key signing key for the zone "example.net".
+Store the key in the same directory below "zonedir" where the other
+"example.net" keys live.
+.TP
+.fam C
+.B "dnssec-zkt \-T ./zonedir/example.net
+.fam T
+Print out a trusted-key section containing the key signing keys of "example.net".
+.TP
+.fam C
+.B "dnssec-zkt \-D 123245 \-r .
+.fam T
+Depreciate the key with tag "12345" below the current directory,
+.TP
+.fam C
+.B "dnssec-zkt --view intern
+Print out a list of all zone keys found below the directory where all
+the zones of view intern live.
+There should be a seperate dnssec config file
+.I dnssec-intern.conf
+with a directory option to take affect of this.
+.TP
+.fam C
+.B "dnssec-zkt-intern
+.fam T
+Same as above.
+The binary file
+.I dnssec-zkt
+have linked to
+.I dnssec-zkt-intern .
+
+.SH ENVIRONMENT VARIABLES
+.TP
+ZKT_CONFFILE
+Specifies the name of the default global configuration files.
+
+.SH FILES
+.TP
+.I /var/named/dnssec.conf
+Built-in default global configuration file.
+The name of the default global config file is settable via
+the environment variable ZKT_CONFFILE.
+.TP
+.I /var/named/dnssec-<view>.conf
+View specific global configuration file.
+.TP
+.I ./dnssec.conf
+Local configuration file (only used in
+.B \-C
+mode).
+
+.SH BUGS
+.PP
+Some of the general options will not be meaningful in all of the command modes.
+.br
+The option
+.B \-l
+and the ksk rollover options
+insist on domain names ending with a dot.
+.PP
+
+.SH AUTHOR
+Holger Zuleger
+
+.SH COPYRIGHT
+Copyright (c) 2005 \- 2007 by Holger Zuleger.
+Licensed under the GPL 2. There is NO warranty; not even for MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.
+.\"--------------------------------------------------
+.SH SEE ALSO
+dnssec-keygen(8), dnssec-signzone(8), rndc(8), named.conf(5), dnssec-signer(8),
+.br
+RFC4641
+"DNSSEC Operational Practices" by Miek Gieben and Olaf Kolkman,
+.br
+DNSSEC HOWTO Tutorial by Olaf Kolkman, RIPE NCC
+.br
+(http://www.nlnetlabs.nl/dnssec_howto/)
diff --git a/contrib/zkt/dnssec-zkt.c b/contrib/zkt/dnssec-zkt.c
new file mode 100644
index 0000000..803cbc3
--- /dev/null
+++ b/contrib/zkt/dnssec-zkt.c
@@ -0,0 +1,823 @@
+/*****************************************************************
+**
+** @(#) dnssec-zkt.c (c) Jan 2005 Holger Zuleger hznet.de
+**
+** Secure DNS zone key tool
+** A wrapper command around the BIND dnssec-keygen utility
+**
+** Copyright (c) 2005 - 2008, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+
+# include <stdio.h>
+# include <stdlib.h> /* abort(), exit(), ... */
+# include <string.h>
+# include <dirent.h>
+# include <assert.h>
+# include <unistd.h>
+# include <ctype.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
+# include <getopt.h>
+#endif
+
+# include "debug.h"
+# include "misc.h"
+# include "strlist.h"
+# include "zconf.h"
+# include "dki.h"
+# include "zkt.h"
+
+extern int optopt;
+extern int opterr;
+extern int optind;
+extern char *optarg;
+const char *progname;
+
+char *labellist = NULL;
+
+int headerflag = 1;
+int ageflag = 0;
+int lifetime = 0;
+int lifetimeflag = 0;
+int timeflag = 1;
+int exptimeflag = 0;
+int pathflag = 0;
+int kskflag = 1;
+int zskflag = 1;
+int ljustflag = 0;
+
+static int dirflag = 0;
+static int recflag = RECURSIVE;
+static int trustedkeyflag = 0;
+static char *kskdomain = "";
+static const char *view = "";
+
+# define short_options ":0:1:2:3:9A:C:D:P:S:R:HKTs:ZV:afF:c:O:dhkLl:prtez"
+#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
+static struct option long_options[] = {
+ {"ksk-rollover", no_argument, NULL, '9'},
+ {"ksk-status", required_argument, NULL, '0'},
+ {"ksk-roll-status", required_argument, NULL, '0'},
+ {"ksk-newkey", required_argument, NULL, '1'},
+ {"ksk-publish", required_argument, NULL, '2'},
+ {"ksk-delkey", required_argument, NULL, '3'},
+ {"ksk-roll-phase1", required_argument, NULL, '1'},
+ {"ksk-roll-phase2", required_argument, NULL, '2'},
+ {"ksk-roll-phase3", required_argument, NULL, '3'},
+ {"list-dnskeys", no_argument, NULL, 'K'},
+ {"list-trustedkeys", no_argument, NULL, 'T'},
+ {"ksk", no_argument, NULL, 'k'},
+ {"zsk", no_argument, NULL, 'z'},
+ {"age", no_argument, NULL, 'a'},
+ {"lifetime", no_argument, NULL, 'f'},
+ {"time", no_argument, NULL, 't'},
+ {"expire", no_argument, NULL, 'e'},
+ {"recursive", no_argument, NULL, 'r'},
+ {"zone-config", no_argument, NULL, 'Z'},
+ {"leftjust", no_argument, NULL, 'L'},
+ {"path", no_argument, NULL, 'p'},
+ {"nohead", no_argument, NULL, 'h'},
+ {"directory", no_argument, NULL, 'd'},
+ {"config", required_argument, NULL, 'c'},
+ {"option", required_argument, NULL, 'O'},
+ {"config-option", required_argument, NULL, 'O'},
+ {"published", required_argument, NULL, 'P'},
+ {"standby", required_argument, NULL, 'S'},
+ {"active", required_argument, NULL, 'A'},
+ {"depreciated", required_argument, NULL, 'D'},
+ {"create", required_argument, NULL, 'C'},
+ {"revoke", required_argument, NULL, 'R'},
+ {"remove", required_argument, NULL, 19 },
+ {"destroy", required_argument, NULL, 20 },
+ {"setlifetime", required_argument, NULL, 'F' },
+ {"view", required_argument, NULL, 'V' },
+ {"help", no_argument, NULL, 'H'},
+ {0, 0, 0, 0}
+};
+#endif
+
+static int parsedirectory (const char *dir, dki_t **listp);
+static void parsefile (const char *file, dki_t **listp);
+static void createkey (const char *keyname, const dki_t *list, const zconf_t *conf);
+static void ksk_roll (const char *keyname, int phase, const dki_t *list, const zconf_t *conf);
+static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp);
+static void usage (char *mesg, zconf_t *cp);
+static const char *parsetag (const char *str, int *tagp);
+
+static void setglobalflags (zconf_t *config)
+{
+ recflag = config->recursive;
+ ageflag = config->printage;
+ timeflag = config->printtime;
+ ljustflag = config->ljust;
+}
+
+int main (int argc, char *argv[])
+{
+ dki_t *data = NULL;
+ dki_t *dkp;
+ int c;
+ int opt_index;
+ int action;
+ const char *file;
+ const char *defconfname = NULL;
+ char *p;
+ char str[254+1];
+ const char *keyname = NULL;
+ int searchtag;
+ zconf_t *config;
+
+ progname = *argv;
+ if ( (p = strrchr (progname, '/')) )
+ progname = ++p;
+ view = getnameappendix (progname, "dnssec-zkt");
+
+ defconfname = getdefconfname (view);
+ config = loadconfig ("", (zconf_t *)NULL); /* load built in config */
+ if ( fileexist (defconfname) ) /* load default config file */
+ config = loadconfig (defconfname, config);
+ if ( config == NULL )
+ fatal ("Out of memory\n");
+ setglobalflags (config);
+
+ opterr = 0;
+ opt_index = 0;
+ action = 0;
+#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
+ while ( (c = getopt_long (argc, argv, short_options, long_options, &opt_index)) != -1 )
+#else
+ while ( (c = getopt (argc, argv, short_options)) != -1 )
+#endif
+ {
+ switch ( c )
+ {
+ case '9': /* ksk rollover help */
+ ksk_roll ("help", c - '0', NULL, NULL);
+ exit (1);
+ case '1': /* ksk rollover: create new key */
+ case '2': /* ksk rollover: publish DS */
+ case '3': /* ksk rollover: delete old key */
+ case '0': /* ksk rollover: show current status */
+ action = c;
+ if ( !optarg )
+ usage ("ksk rollover requires an domain argument", config);
+ kskdomain = str_tolowerdup (optarg);
+ break;
+ case 'T':
+ trustedkeyflag = 1;
+ zskflag = pathflag = 0;
+ /* fall through */
+ case 'H':
+ case 'K':
+ case 'Z':
+ action = c;
+ break;
+ case 'C':
+ pathflag = !pathflag;
+ /* fall through */
+ case 'P':
+ case 'S':
+ case 'A':
+ case 'D':
+ case 'R':
+ case 's':
+ case 19:
+ case 20:
+ if ( (keyname = parsetag (optarg, &searchtag)) != NULL )
+ {
+ int len = strlen (keyname);
+ if ( len > 0 && keyname[len-1] != '.' )
+ {
+ snprintf (str, sizeof(str), "%s.", keyname);
+ keyname = str;
+ }
+ }
+ keyname = str_tolowerdup (keyname);
+ action = c;
+ break;
+ case 'a': /* age */
+ ageflag = !ageflag;
+ break;
+ case 'f': /* key lifetime */
+ lifetimeflag = !lifetimeflag;
+ break;
+ case 'F': /* set key lifetime */
+ lifetime = atoi (optarg);
+ lifetimeflag = 1; /* set some flags for more informative output */
+ exptimeflag = 1;
+ timeflag = 1;
+ action = c;
+ break;
+ case 'V': /* view name */
+ view = optarg;
+ defconfname = getdefconfname (view);
+ if ( fileexist (defconfname) ) /* load default config file */
+ config = loadconfig (defconfname, config);
+ if ( config == NULL )
+ fatal ("Out of memory\n");
+ setglobalflags (config);
+ break;
+ case 'c':
+ config = loadconfig (optarg, config);
+ setglobalflags (config);
+ checkconfig (config);
+ break;
+ case 'O': /* read option from commandline */
+ config = loadconfig_fromstr (optarg, config);
+ setglobalflags (config);
+ checkconfig (config);
+ break;
+ case 'd': /* ignore directory arg */
+ dirflag = 1;
+ break;
+ case 'h': /* print no headline */
+ headerflag = 0;
+ break;
+ case 'k': /* ksk only */
+ zskflag = 0;
+ break;
+ case 'L': /* ljust */
+ ljustflag = !ljustflag;
+ break;
+ case 'l': /* label list */
+ labellist = prepstrlist (optarg, LISTDELIM);
+ if ( labellist == NULL )
+ fatal ("Out of memory\n");
+ break;
+ case 'p': /* print path */
+ pathflag = 1;
+ break;
+ case 'r': /* switch recursive flag */
+ recflag = !recflag;
+ break;
+ case 't': /* time */
+ timeflag = !timeflag;
+ break;
+ case 'e': /* expire time */
+ exptimeflag = !exptimeflag;
+ break;
+ case 'z': /* zsk only */
+ kskflag = 0;
+ break;
+ case ':':
+ snprintf (str, sizeof(str), "option \"-%c\" requires an argument.\n",
+ optopt);
+ usage (str, config);
+ break;
+ case '?':
+ if ( isprint (optopt) )
+ snprintf (str, sizeof(str), "Unknown option \"-%c\".\n",
+ optopt);
+ else
+ snprintf (str, sizeof (str), "Unknown option char \\x%x.\n",
+ optopt);
+ usage (str, config);
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /* it's better to do this before we read the whole directory tree */
+ if ( action == 'Z' )
+ {
+ printconfig ("stdout", config);
+ return 0;
+ }
+
+ if ( kskflag == 0 && zskflag == 0 )
+ kskflag = zskflag = 1;
+
+ c = optind;
+ do {
+ if ( c >= argc ) /* no args left */
+ file = config->zonedir; /* use default directory */
+ else
+ file = argv[c++];
+
+ if ( is_directory (file) )
+ parsedirectory (file, &data);
+ else
+ parsefile (file, &data);
+
+ } while ( c < argc ); /* for all arguments */
+
+ switch ( action )
+ {
+ case 'H':
+ usage ("", config);
+ case 'C':
+ createkey (keyname, data, config);
+ break;
+ case 'P':
+ case 'S':
+ case 'A':
+ case 'D':
+ if ( (dkp = (dki_t*)zkt_search (data, searchtag, keyname)) == NULL )
+ fatal ("Key with tag %u not found\n", searchtag);
+ else if ( dkp == (void *) 01 )
+ fatal ("Key with tag %u found multiple times\n", searchtag);
+ if ( (c = dki_setstatus_preservetime (dkp, action)) != 0 )
+ fatal ("Couldn't change status of key %u: %d\n", searchtag, c);
+ break;
+ case 19: /* remove (rename) key file */
+ if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
+ fatal ("Key with tag %u not found\n", searchtag);
+ else if ( dkp == (void *) 01 )
+ fatal ("Key with tag %u found multiple times\n", searchtag);
+ dki_remove (dkp);
+ break;
+ case 20: /* destroy the key (remove the files!) */
+ if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
+ fatal ("Key with tag %u not found\n", searchtag);
+ else if ( dkp == (void *) 01 )
+ fatal ("Key with tag %u found multiple times\n", searchtag);
+ dki_destroy (dkp);
+ break;
+ case 'R':
+ if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
+ fatal ("Key with tag %u not found\n", searchtag);
+ else if ( dkp == (void *) 01 )
+ fatal ("Key with tag %u found multiple times\n", searchtag);
+ if ( (c = dki_setstatus (dkp, action)) != 0 )
+ fatal ("Couldn't change status of key %u: %d\n", searchtag, c);
+ break;
+ case 's':
+ if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
+ fatal ("Key with tag %u not found\n", searchtag);
+ else if ( dkp == (void *) 01 )
+ fatal ("Key with tag %u found multiple times\n", searchtag);
+ dki_prt_dnskey (dkp, stdout);
+ break;
+ case 'K':
+ zkt_list_dnskeys (data);
+ break;
+ case 'T':
+ zkt_list_trustedkeys (data);
+ break;
+ case '1': /* ksk rollover new key */
+ case '2': /* ksk rollover publish DS */
+ case '3': /* ksk rollover delete old key */
+ case '0': /* ksk rollover status */
+ ksk_roll (kskdomain, action - '0', data, config);
+ break;
+ case 'F':
+ zkt_setkeylifetime (data);
+ /* fall through */
+ default:
+ zkt_list_keys (data);
+ }
+
+ return 0;
+}
+
+# define sopt_usage(mesg, value) fprintf (stderr, mesg, value)
+#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
+# define lopt_usage(mesg, value) fprintf (stderr, mesg, value)
+# define loptstr(lstr, sstr) lstr
+#else
+# define lopt_usage(mesg, value)
+# define loptstr(lstr, sstr) sstr
+#endif
+static void usage (char *mesg, zconf_t *cp)
+{
+ fprintf (stderr, "Secure DNS Zone Key Tool %s\n", ZKT_VERSION);
+ fprintf (stderr, "\n");
+ fprintf (stderr, "Show zone config parameter as %s file\n", LOCALCONF_FILE);
+ sopt_usage ("\tusage: %s -Z\n", progname);
+ lopt_usage ("\tusage: %s --zone-config\n", progname);
+ fprintf (stderr, "\n");
+ fprintf (stderr, "List keys in current or given directory (-r for recursive mode)\n");
+ sopt_usage ("\tusage: %s [-dhatkzpr] [-c config] [file|dir ...]\n", progname);
+ fprintf (stderr, "\n");
+ fprintf (stderr, "List public part of keys in DNSKEY RR format\n");
+ sopt_usage ("\tusage: %s -K [-dhkzr] [-c config] [file|dir ...]\n", progname);
+ lopt_usage ("\tusage: %s --list-dnskeys [-dhkzr] [-c config] [file|dir ...]\n", progname);
+ fprintf (stderr, "\n");
+ fprintf (stderr, "List keys (output is suitable for trusted-keys section)\n");
+ sopt_usage ("\tusage: %s -T [-dhzr] [-c config] [file|dir ...]\n", progname);
+ lopt_usage ("\tusage: %s --list-trustedkeys [-dhzr] [-c config] [file|dir ...]\n", progname);
+ fprintf (stderr, "\n");
+ fprintf (stderr, "Create a new key \n");
+ sopt_usage ("\tusage: %s -C <name> [-k] [-dpr] [-c config] [dir ...]\n", progname);
+ lopt_usage ("\tusage: %s --create=<name> [-k] [-dpr] [-c config] [dir ...]\n", progname);
+ fprintf (stderr, "\t\tKSK (use -k): %s %d bits\n", dki_algo2str (cp->k_algo), cp->k_bits);
+ fprintf (stderr, "\t\tZSK (default): %s %d bits\n", dki_algo2str (cp->z_algo), cp->z_bits);
+ fprintf (stderr, "\n");
+ fprintf (stderr, "Change key status of specified key to published, active or depreciated\n");
+ fprintf (stderr, "\t(<keyspec> := tag | tag:name) \n");
+ sopt_usage ("\tusage: %s -P|-A|-D <keyspec> [-dr] [-c config] [dir ...]\n", progname);
+ lopt_usage ("\tusage: %s --published=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
+ lopt_usage ("\tusage: %s --active=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
+ lopt_usage ("\tusage: %s --depreciated=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
+ fprintf (stderr, "\n");
+ fprintf (stderr, "Revoke specified key (<keyspec> := tag | tag:name) \n");
+ sopt_usage ("\tusage: %s -R <keyspec> [-dr] [-c config] [dir ...]\n", progname);
+ lopt_usage ("\tusage: %s --revoke=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
+ fprintf (stderr, "\n");
+ fprintf (stderr, "Remove (rename) or destroy (delete) specified key (<keyspec> := tag | tag:name) \n");
+ lopt_usage ("\tusage: %s --remove=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
+ lopt_usage ("\tusage: %s --destroy=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
+ fprintf (stderr, "\n");
+ fprintf (stderr, "Initiate a semi-automated KSK rollover");
+ fprintf (stderr, "('%s -9%s' prints out a short description)\n", progname, loptstr ("|--ksk-rollover", ""));
+ sopt_usage ("\tusage: %s {-1} do.ma.in.\n", progname);
+ lopt_usage ("\tusage: %s {--ksk-roll-phase1|--ksk-newkey} do.ma.in.\n", progname);
+ sopt_usage ("\tusage: %s {-2} do.ma.in.\n", progname);
+ lopt_usage ("\tusage: %s {--ksk-roll-phase2|--ksk-publish} do.ma.in.\n", progname);
+ sopt_usage ("\tusage: %s {-3} do.ma.in.\n", progname);
+ lopt_usage ("\tusage: %s {--ksk-roll-phase3|--ksk-delkey} do.ma.in.\n", progname);
+ sopt_usage ("\tusage: %s {-0} do.ma.in.\n", progname);
+ lopt_usage ("\tusage: %s {--ksk-roll-status|--ksk-status} do.ma.in.\n", progname);
+ fprintf (stderr, "\n");
+
+ fprintf (stderr, "\n");
+ fprintf (stderr, "General options \n");
+ fprintf (stderr, "\t-c file%s", loptstr (", --config=file\n", ""));
+ fprintf (stderr, "\t\t read config from <file> instead of %s\n", CONFIG_FILE);
+ fprintf (stderr, "\t-O optstr%s", loptstr (", --config-option=\"optstr\"\n", ""));
+ fprintf (stderr, "\t\t read config options from commandline\n");
+ fprintf (stderr, "\t-h%s\t no headline or trusted-key section header/trailer in -T mode\n", loptstr (", --nohead", "\t"));
+ fprintf (stderr, "\t-d%s\t skip directory arguments\n", loptstr (", --directory", "\t"));
+ fprintf (stderr, "\t-L%s\t print the domain name left justified (default: %s)\n", loptstr (", --leftjust", "\t"), ljustflag ? "on": "off");
+ fprintf (stderr, "\t-l list\t\t print out only zone keys out of the given domain list\n");
+ fprintf (stderr, "\t-p%s\t show path of keyfile / create key in current directory\n", loptstr (", --path", "\t"));
+ fprintf (stderr, "\t-r%s\t recursive mode on/off (default: %s)\n", loptstr(", --recursive", "\t"), recflag ? "on": "off");
+ fprintf (stderr, "\t-a%s\t print age of key (default: %s)\n", loptstr (", --age", "\t"), ageflag ? "on": "off");
+ fprintf (stderr, "\t-t%s\t print key generation time (default: %s)\n", loptstr (", --time", "\t"),
+ timeflag ? "on": "off");
+ fprintf (stderr, "\t-e%s\t print key expiration time\n", loptstr (", --expire", "\t"));
+ fprintf (stderr, "\t-f%s\t print key lifetime\n", loptstr (", --lifetime", "\t"));
+ fprintf (stderr, "\t-F days%s=days\t set key lifetime\n", loptstr (", --setlifetime", "\t"));
+ fprintf (stderr, "\t-k%s\t key signing keys only\n", loptstr (", --ksk", "\t"));
+ fprintf (stderr, "\t-z%s\t zone signing keys only\n", loptstr (", --zsk", "\t"));
+ if ( mesg && *mesg )
+ fprintf (stderr, "%s\n", mesg);
+ exit (1);
+}
+
+static void createkey (const char *keyname, const dki_t *list, const zconf_t *conf)
+{
+ const char *dir = "";
+ dki_t *dkp;
+
+ if ( keyname == NULL || *keyname == '\0' )
+ fatal ("Create key: no keyname!");
+
+ dbg_val2 ("createkey: keyname %s, pathflag = %d\n", keyname, pathflag);
+ /* search for already existent key to get the directory name */
+ if ( pathflag && (dkp = (dki_t *)zkt_search (list, 0, keyname)) != NULL )
+ {
+ char path[MAX_PATHSIZE+1];
+ zconf_t localconf;
+
+ dir = dkp->dname;
+ pathname (path, sizeof (path), dir, LOCALCONF_FILE, NULL);
+ if ( fileexist (path) ) /* load local config file */
+ {
+ dbg_val ("Load local config file \"%s\"\n", path);
+ memcpy (&localconf, conf, sizeof (zconf_t));
+ conf = loadconfig (path, &localconf);
+ }
+ }
+
+ if ( zskflag )
+ dkp = dki_new (dir, keyname, DKI_ZSK, conf->z_algo, conf->z_bits, conf->z_random, conf->z_life / DAYSEC);
+ else
+ dkp = dki_new (dir, keyname, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
+ if ( dkp == NULL )
+ fatal ("Can't create key %s: %s!\n", keyname, dki_geterrstr ());
+
+ /* create a new key always in state published, which means "standby" for ksk */
+ dki_setstatus (dkp, DKI_PUB);
+}
+
+static int get_parent_phase (const char *file)
+{
+ FILE *fp;
+ int phase;
+
+ if ( (fp = fopen (file, "r")) == NULL )
+ return -1;
+
+ phase = 0;
+ if ( fscanf (fp, "; KSK rollover phase%d", &phase) != 1 )
+ phase = 0;
+
+ fclose (fp);
+ return phase;
+}
+
+static void ksk_roll (const char *keyname, int phase, const dki_t *list, const zconf_t *conf)
+{
+ char path[MAX_PATHSIZE+1];
+ zconf_t localconf;
+ const char *dir;
+ dki_t *keylist;
+ dki_t *dkp;
+ dki_t *standby;
+ int parent_exist;
+ int parent_age;
+ int parent_phase;
+ int parent_propagation;
+ int key_ttl;
+ int ksk;
+
+ if ( phase == 9 ) /* usage */
+ {
+ fprintf (stderr, "A KSK rollover requires three consecutive steps:\n");
+ fprintf (stderr, "\n");
+ fprintf (stderr, "-1%s", loptstr ("|--ksk-roll-phase1 (--ksk-newkey)\n", ""));
+ fprintf (stderr, "\t Create a new KSK.\n");
+ fprintf (stderr, "\t This step also creates a parent-<domain> file which contains only\n");
+ fprintf (stderr, "\t the _old_ key. This file will be copied in hierarchical mode\n");
+ fprintf (stderr, "\t by dnssec-signer to the parent directory as keyset-<domain> file.\n");
+ fprintf (stderr, "\t Wait until the new keyset is propagated, before going to the next step.\n");
+ fprintf (stderr, "\n");
+ fprintf (stderr, "-2%s", loptstr ("|--ksk-roll-phase2 (--ksk-publish)\n", ""));
+ fprintf (stderr, "\t This step creates a parent-<domain> file with the _new_ key only.\n");
+ fprintf (stderr, "\t Please send this file immediately to the parent (In hierarchical\n");
+ fprintf (stderr, "\t mode this will be done automatically by the dnssec-signer command).\n");
+ fprintf (stderr, "\t Then wait until the new DS is generated by the parent and propagated\n");
+ fprintf (stderr, "\t to all the parent name server, plus the old DS TTL before going to step three.\n");
+ fprintf (stderr, "\n");
+ fprintf (stderr, "-3%s", loptstr ("|--ksk-roll-phase3 (--ksk-delkey)\n", ""));
+ fprintf (stderr, "\t Remove (rename) the old KSK and the parent-<domain> file.\n");
+ fprintf (stderr, "\t You have to manually delete the old KSK (look at file names beginning\n");
+ fprintf (stderr, "\t with an lower 'k').\n");
+ fprintf (stderr, "\n");
+ fprintf (stderr, "-0%s", loptstr ("|--ksk-roll-stat (--ksk-status)\n", ""));
+ fprintf (stderr, "\t Show the current KSK rollover state of a domain.\n");
+
+ fprintf (stderr, "\n");
+
+ return;
+ }
+
+ if ( keyname == NULL || *keyname == '\0' )
+ fatal ("ksk rollover: no domain!");
+
+ dbg_val2 ("ksk_roll: keyname %s, phase = %d\n", keyname, phase);
+
+ /* search for already existent key to get the directory name */
+ if ( (keylist = (dki_t *)zkt_search (list, 0, keyname)) == NULL )
+ fatal ("ksk rollover: domain %s not found!\n", keyname);
+ dkp = keylist;
+
+ /* try to read local config file */
+ dir = dkp->dname;
+ pathname (path, sizeof (path), dir, LOCALCONF_FILE, NULL);
+ if ( fileexist (path) ) /* load local config file */
+ {
+ dbg_val ("Load local config file \"%s\"\n", path);
+ memcpy (&localconf, conf, sizeof (zconf_t));
+ conf = loadconfig (path, &localconf);
+ }
+ key_ttl = conf->key_ttl;
+
+ /* check if parent-file already exist */
+ pathname (path, sizeof (path), dir, "parent-", keyname);
+ parent_phase = parent_age = 0;
+ if ( (parent_exist = fileexist (path)) != 0 )
+ {
+ parent_phase = get_parent_phase (path);
+ parent_age = file_age (path);
+ }
+ // parent_propagation = 2 * DAYSEC;
+ parent_propagation = 5 * MINSEC;
+
+ ksk = 0; /* count active(!) key signing keys */
+ standby = NULL; /* find standby key if available */
+ for ( dkp = keylist; dkp; dkp = dkp->next )
+ if ( dki_isksk (dkp) )
+ {
+ if ( dki_status (dkp) == DKI_ACT )
+ ksk++;
+ else if ( dki_status (dkp) == DKI_PUB )
+ standby = dkp;
+ }
+
+ switch ( phase )
+ {
+ case 0: /* print status (debug) */
+ fprintf (stdout, "ksk_rollover:\n");
+ fprintf (stdout, "\t domain = %s\n", keyname);
+ fprintf (stdout, "\t phase = %d\n", parent_phase);
+ fprintf (stdout, "\t parent_file %s %s\n", path, parent_exist ? "exist": "not exist");
+ if ( parent_exist )
+ fprintf (stdout, "\t age of parent_file %d %s\n", parent_age, str_delspace (age2str (parent_age)));
+ fprintf (stdout, "\t # of active key signing keys %d\n", ksk);
+ fprintf (stdout, "\t parent_propagation %d %s\n", parent_propagation, str_delspace (age2str (parent_propagation)));
+ fprintf (stdout, "\t keys ttl %d %s\n", key_ttl, age2str (key_ttl));
+
+ for ( dkp = keylist; dkp; dkp = dkp->next )
+ {
+ /* TODO: Nur zum testen */
+ dki_prt_dnskey (dkp, stdout);
+ }
+ break;
+ case 1:
+ if ( parent_exist || ksk > 1 )
+ fatal ("Can\'t create new ksk because there is already an ksk rollover in progress\n");
+
+ fprintf (stdout, "create new ksk \n");
+ dkp = dki_new (dir, keyname, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
+ if ( dkp == NULL )
+ fatal ("Can't create key %s: %s!\n", keyname, dki_geterrstr ());
+ if ( standby )
+ {
+ dki_setstatus (standby, DKI_ACT); /* activate standby key */
+ dki_setstatus (dkp, DKI_PUB); /* new key will be the new standby */
+ }
+
+ // dkp = keylist; /* use old key to create the parent file */
+ if ( (dkp = (dki_t *)dki_find (keylist, 1, 'a', 1)) == NULL ) /* find the oldest active ksk to create the parent file */
+ fatal ("ksk_rollover phase1: Couldn't find the old active key\n");
+ if ( !create_parent_file (path, phase, key_ttl, dkp) )
+ fatal ("Couldn't create parentfile %s\n", path);
+ break;
+
+ case 2:
+ if ( ksk < 2 )
+ fatal ("Can\'t publish new key because no one exist\n");
+ if ( !parent_exist )
+ fatal ("More than one KSK but no parent file found!\n");
+ if ( parent_phase != 1 )
+ fatal ("Parent file exists but is in wrong state (phase = %d)\n", parent_phase);
+ if ( parent_age < conf->proptime + key_ttl )
+ fatal ("ksk_rollover (phase2): you have to wait for the propagation of the new KSK (at least %dsec or %s)\n",
+ conf->proptime + key_ttl - parent_age,
+ str_delspace (age2str (conf->proptime + key_ttl - parent_age)));
+
+ fprintf (stdout, "save new ksk in parent file\n");
+ dkp = keylist->next; /* set dkp to new ksk */
+ if ( !create_parent_file (path, phase, key_ttl, dkp) )
+ fatal ("Couldn't create parentfile %s\n", path);
+ break;
+ case 3:
+ if ( !parent_exist || ksk < 2 )
+ fatal ("ksk-delkey only allowed after ksk-publish\n");
+ if ( parent_phase != 2 )
+ fatal ("Parent file exists but is in wrong state (phase = %d)\n", parent_phase);
+ if ( parent_age < parent_propagation + key_ttl )
+ fatal ("ksk_rollover (phase3): you have to wait for DS propagation (at least %dsec or %s)\n",
+ parent_propagation + key_ttl - parent_age,
+ str_delspace (age2str (parent_propagation + key_ttl - parent_age)));
+ /* remove the parentfile */
+ fprintf (stdout, "remove parentfile \n");
+ unlink (path);
+ /* remove or rename the old key */
+ fprintf (stdout, "old ksk renamed \n");
+ dkp = keylist; /* set dkp to old ksk */
+ dki_remove (dkp);
+ break;
+ default: assert (phase == 1 || phase == 2 || phase == 3);
+ }
+}
+
+/*****************************************************************
+** create_parent_file ()
+*****************************************************************/
+static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp)
+{
+ FILE *fp;
+
+ assert ( fname != NULL );
+
+ if ( dkp == NULL || (phase != 1 && phase != 2) )
+ return 0;
+
+ if ( (fp = fopen (fname, "w")) == NULL )
+ fatal ("can\'t create new parentfile \"%s\"\n", fname);
+
+ if ( phase == 1 )
+ fprintf (fp, "; KSK rollover phase1 (old key)\n");
+ else
+ fprintf (fp, "; KSK rollover phase2 (new key)\n");
+
+ dki_prt_dnskeyttl (dkp, fp, ttl);
+ fclose (fp);
+
+ return phase;
+}
+
+static int parsedirectory (const char *dir, dki_t **listp)
+{
+ dki_t *dkp;
+ DIR *dirp;
+ struct dirent *dentp;
+ char path[MAX_PATHSIZE+1];
+
+ if ( dirflag )
+ return 0;
+
+ dbg_val ("directory: opendir(%s)\n", dir);
+ if ( (dirp = opendir (dir)) == NULL )
+ return 0;
+
+ while ( (dentp = readdir (dirp)) != NULL )
+ {
+ if ( is_dotfile (dentp->d_name) )
+ continue;
+
+ dbg_val ("directory: check %s\n", dentp->d_name);
+ pathname (path, sizeof (path), dir, dentp->d_name, NULL);
+ if ( is_directory (path) && recflag )
+ {
+ dbg_val ("directory: recursive %s\n", path);
+ parsedirectory (path, listp);
+ }
+ else if ( is_keyfilename (dentp->d_name) )
+ if ( (dkp = dki_read (dir, dentp->d_name)) )
+ {
+ // fprintf (stderr, "parsedir: tssearch (%d %s)\n", dkp, dkp->name);
+#if defined (USE_TREE) && USE_TREE
+ dki_tadd (listp, dkp);
+#else
+ dki_add (listp, dkp);
+#endif
+ }
+ }
+ closedir (dirp);
+ return 1;
+}
+
+static void parsefile (const char *file, dki_t **listp)
+{
+ char path[MAX_PATHSIZE+1];
+ dki_t *dkp;
+
+ /* file arg contains path ? ... */
+ file = splitpath (path, sizeof (path), file); /* ... then split of */
+
+ if ( is_keyfilename (file) ) /* plain file name looks like DNS key file ? */
+ {
+ if ( (dkp = dki_read (path, file)) ) /* read DNS key file ... */
+#if defined (USE_TREE) && USE_TREE
+ dki_tadd (listp, dkp); /* ... and add to tree */
+#else
+ dki_add (listp, dkp); /* ... and add to list */
+#endif
+ else
+ error ("error parsing %s: (%s)\n", file, dki_geterrstr());
+ }
+}
+
+static const char *parsetag (const char *str, int *tagp)
+{
+ const char *p;
+
+ *tagp = 0;
+ while ( isspace (*str) ) /* skip leading ws */
+ str++;
+
+ p = str;
+ if ( isdigit (*p) ) /* keytag starts with digit */
+ {
+ sscanf (p, "%u", tagp); /* read keytag as number */
+ do /* eat up to the end of the number */
+ p++;
+ while ( isdigit (*p) );
+
+ if ( *p == ':' ) /* label follows ? */
+ return p+1; /* return that */
+ if ( *p == '\0' )
+ return NULL; /* no label */
+ }
+ return str; /* return as label string if not a numeric keytag */
+}
+
diff --git a/contrib/zkt/domaincmp.c b/contrib/zkt/domaincmp.c
new file mode 100644
index 0000000..7d2486f
--- /dev/null
+++ b/contrib/zkt/domaincmp.c
@@ -0,0 +1,190 @@
+/*****************************************************************
+**
+** @(#) domaincmp.c -- compare two domain names
+**
+** Copyright (c) Aug 2005, Karle Boss, Holger Zuleger (kaho).
+** All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Karle Boss or Holger Zuleger (kaho) nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+# include <stdio.h>
+# include <string.h>
+# include <assert.h>
+# include <ctype.h>
+#define extern
+# include "domaincmp.h"
+#undef extern
+
+
+#define goto_labelstart(str, p) while ( (p) > (str) && *((p)-1) != '.' ) \
+ (p)--
+
+/*****************************************************************
+** int domaincmp (a, b)
+** compare a and b as fqdns.
+** return <0 | 0 | >0 as in strcmp
+** A subdomain is less than the corresponding parent domain,
+** thus domaincmp ("z.example.net", "example.net") return < 0 !!
+*****************************************************************/
+int domaincmp (const char *a, const char *b)
+{
+ register const char *pa;
+ register const char *pb;
+
+ if ( a == NULL ) return -1;
+ if ( b == NULL ) return 1;
+
+ if ( *a == '.' ) /* skip a leading dot */
+ a++;
+ if ( *b == '.' ) /* same at the other string */
+ b++;
+
+ /* let pa and pb point to the last non dot char */
+ pa = a + strlen (a);
+ do
+ pa--;
+ while ( pa > a && *pa == '.' );
+
+ pb = b + strlen (b);
+ do
+ pb--;
+ while ( pb > b && *pb == '.' );
+
+ /* cmp both domains starting at the end */
+ while ( *pa == *pb && pa > a && pb > b )
+ pa--, pb--;
+
+ if ( *pa != *pb ) /* both domains are different ? */
+ {
+ if ( *pa == '.' )
+ pa++; /* set to beginning of next label */
+ else
+ goto_labelstart (a, pa); /* find begin of current label */
+ if ( *pb == '.' )
+ pb++; /* set to beginning of next label */
+ else
+ goto_labelstart (b, pb); /* find begin of current label */
+ }
+ else /* maybe one of them has a subdomain */
+ {
+ if ( pa > a )
+ if ( pa[-1] == '.' )
+ return -1;
+ else
+ goto_labelstart (a, pa);
+ else if ( pb > b )
+ if ( pb[-1] == '.' )
+ return 1;
+ else
+ goto_labelstart (b, pb);
+ else
+ return 0; /* both are at the beginning, so they are equal */
+ }
+
+ /* both domains are definitly unequal */
+ while ( *pa == *pb ) /* so we have to look at the point where they differ */
+ pa++, pb++;
+
+ return *pa - *pb;
+}
+
+#ifdef DOMAINCMP_TEST
+static struct {
+ char *a;
+ char *b;
+ int res;
+} ex[] = {
+ { ".", ".", 0 },
+ { "test", "", 1 },
+ { "", "test2", -1 },
+ { "", "", 0 },
+ { "de", "de", 0 },
+ { ".de", "de", 0 },
+ { "de.", "de.", 0 },
+ { ".de", ".de", 0 },
+ { ".de.", ".de.", 0 },
+ { ".de", "zde", -1 },
+ { ".de", "ade", 1 },
+ { "zde", ".de", 1 },
+ { "ade", ".de", -1 },
+ { "a.de", ".de", -1 },
+ { ".de", "a.de", 1 },
+ { "a.de", "b.de", -1 },
+ { "a.de.", "b.de", -1 },
+ { "a.de", "b.de.", -1 },
+ { "a.de", "a.de.", 0 },
+ { "aa.de", "b.de", -1 },
+ { "ba.de", "b.de", 1 },
+ { "a.de", "a.dk", -1 },
+ { "anna.example.de", "anna.example.de", 0 },
+ { "anna.example.de", "annamirl.example.de", -1 },
+ { "anna.example.de", "ann.example.de", 1 },
+ { "example.de.", "xy.example.de.", 1 },
+ { "example.de.", "ab.example.de.", 1 },
+ { "example.de", "ab.example.de", 1 },
+ { "ab.example.de", "example.de", -1 },
+ { "ab.mast.de", "axt.de", 1 },
+ { "ab.mast.de", "obt.de", -1 },
+ { "abc.example.de.", "xy.example.de.", -1 },
+ { NULL, NULL, 0 }
+};
+
+const char *progname;
+main (int argc, char *argv[])
+{
+
+ int expect;
+ int res;
+ int c;
+ int i;
+
+ progname = *argv;
+
+ for ( i = 0; ex[i].a; i++ )
+ {
+ expect = ex[i].res;
+ if ( expect < 0 )
+ c = '<';
+ else if ( expect > 0 )
+ c = '>';
+ else
+ c = '=';
+ printf ("%-20s %-20s ==> %c 0 ", ex[i].a, ex[i].b, c);
+ fflush (stdout);
+ res = domaincmp (ex[i].a, ex[i].b);
+ printf ("%3d ", res);
+ if ( res < 0 && expect < 0 || res > 0 && expect > 0 || res == 0 && expect == 0 )
+ puts ("ok");
+ else
+ puts ("not ok");
+ }
+}
+#endif
diff --git a/contrib/zkt/domaincmp.h b/contrib/zkt/domaincmp.h
new file mode 100644
index 0000000..7051f54
--- /dev/null
+++ b/contrib/zkt/domaincmp.h
@@ -0,0 +1,40 @@
+/*****************************************************************
+**
+** @(#) domaincmp.h -- compare two domain names
+**
+** Copyright (c) Aug 2005, Karle Boss (kaho). All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+#ifndef DOMAINCMP_H
+# define DOMAINCMP_H
+extern int domaincmp (const char *a, const char *b);
+#endif
diff --git a/contrib/zkt/examples/dnskey.db b/contrib/zkt/examples/dnskey.db
new file mode 100644
index 0000000..2822e6a
--- /dev/null
+++ b/contrib/zkt/examples/dnskey.db
@@ -0,0 +1,24 @@
+;
+; !!! Don't edit this file by hand.
+; !!! It will be generated by dnssec-signer.
+;
+; Last generation time Jun 24 2008 09:58:34
+;
+
+; *** List of Key Signing Keys ***
+; example.net. tag=31674 algo=RSASHA1 generated Jun 24 2008 09:58:34
+example.net. 14400 IN DNSKEY 257 3 5 (
+ BQEAAAABC23icFZAD3DFBLoEw7DWKl8Hig7azmEbpXHYyAV98l+QQaTA
+ b98Ob3YbrVJ9IU8E0KBFb5iYpHobxowPsI8FjUH2oL/7PfhtN1E3NlL6
+ Uhbo8Umf6H0UULEsUTlTT8dnX+ikjAr8bN71YJP7BXlszezsFHuMEspN
+ dOPyMr93230+R2KTEzC2H4CQzSRIr5xXSIq8kkrJ3miGjTyj5awvXfJ+
+ eQ==
+ ) ; key id = 31674
+
+; *** List of Zone Signing Keys ***
+; example.net. tag=33755 algo=RSASHA1 generated Jun 24 2008 09:58:34
+example.net. 14400 IN DNSKEY 256 3 5 (
+ BQEAAAABzN8pvZb5GSy8AozXt4L8HK/x59TQjh9IaZS+mIyyuHDX2iaF
+ UigOqHixIJtDLD1r/MfelgJ/Mh6+vCu+XmMQuw==
+ ) ; key id = 33755
+
diff --git a/contrib/zkt/examples/dnssec-signer.sh b/contrib/zkt/examples/dnssec-signer.sh
new file mode 100755
index 0000000..ee4bfc0
--- /dev/null
+++ b/contrib/zkt/examples/dnssec-signer.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# Shell script to start the dnssec-signer
+# command out of the example directory
+#
+
+if test ! -f dnssec.conf
+then
+ echo Please start this skript out of the flat or hierarchical sub directory
+ exit 1
+fi
+ZKT_CONFFILE=`pwd`/dnssec.conf ../../dnssec-signer "$@"
diff --git a/contrib/zkt/examples/dnssec-zkt.sh b/contrib/zkt/examples/dnssec-zkt.sh
new file mode 100755
index 0000000..f3976ce
--- /dev/null
+++ b/contrib/zkt/examples/dnssec-zkt.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#
+# Shell script to start the dnssec-zkt command
+# out of the example directory
+#
+
+if test ! -f dnssec.conf
+then
+ echo Please start this skript out of the flat or hierarchical sub directory
+ exit 1
+fi
+ZKT_CONFFILE=`pwd`/dnssec.conf ../../dnssec-zkt "$@"
diff --git a/contrib/zkt/examples/flat/dist.sh b/contrib/zkt/examples/flat/dist.sh
new file mode 100755
index 0000000..c112f55
--- /dev/null
+++ b/contrib/zkt/examples/flat/dist.sh
@@ -0,0 +1,70 @@
+#################################################################
+#
+# @(#) dist.sh -- distribute and reload command for dnssec-signer
+#
+# (c) Jul 2008 Holger Zuleger hznet.de
+#
+# This shell script will be run by dnssec-signer as a distribution
+# and reload command if:
+#
+# a) the dnssec.conf file parameter Distribute_Cmd: points
+# to this file
+# and
+# b) the user running the dnssec-signer command is not
+# root (uid==0)
+# and
+# c) the owner of this shell script is the same as the
+# running user and the access rights don't allow writing
+# for anyone except the owner
+# or
+# d) the group of this shell script is the same as the
+# running user and the access rights don't allow writing
+# for anyone except the group
+#
+#################################################################
+
+# set path to rndc and scp
+PATH="/bin:/usr/bin:/usr/local/sbin"
+
+# remote server and directory
+server=localhost # fqdn of remote name server
+dir=/var/named # zone directory on remote name server
+
+progname=$0
+usage()
+{
+ echo "usage: $progname distribute|reload <domain> <path_to_zonefile> [<viewname>]" 1>&2
+ test $# -gt 0 && echo $* 1>&2
+ exit 1
+}
+
+if test $# -lt 3
+then
+ usage
+fi
+action="$1"
+domain="$2"
+zonefile="$3"
+view=""
+test $# -gt 3 && view="$4"
+
+case $action in
+distribute)
+ if test -n "$view"
+ then
+ echo "scp $zonefile $server:$dir/$view/$domain/"
+ : scp $zonefile $server:$dir/$view/$domain/
+ else
+ echo "scp $zonefile $server:$dir/$domain/"
+ : scp $zonefile $server:$dir/$domain/
+ fi
+ ;;
+reload)
+ echo "rndc $action $zone $view"
+ : rndc $action $zone $view
+ ;;
+*)
+ usage "illegal action $action"
+ ;;
+esac
+
diff --git a/contrib/zkt/examples/flat/dnssec.conf b/contrib/zkt/examples/flat/dnssec.conf
new file mode 100644
index 0000000..2bd9c58
--- /dev/null
+++ b/contrib/zkt/examples/flat/dnssec.conf
@@ -0,0 +1,41 @@
+#
+# @(#) dnssec.conf vT0.96 (c) Feb 2005 - May 2008 Holger Zuleger hznet.de
+#
+
+# dnssec-zkt options
+Zonedir: "."
+Recursive: True
+PrintTime: False
+PrintAge: True
+LeftJustify: False
+
+# zone specific values
+ResignInterval: 2d # (172800 seconds)
+Sigvalidity: 6d # (518400 seconds)
+Max_TTL: 8h # (28800 seconds)
+Propagation: 5m # (300 seconds)
+KEY_TTL: 1h # (3600 seconds)
+Serialformat: incremental
+
+# signing key parameters
+KSK_lifetime: 60d # (5184000 seconds)
+KSK_algo: RSASHA1 # (Algorithm ID 5)
+KSK_bits: 1300
+KSK_randfile: "/dev/urandom"
+ZSK_lifetime: 2w # (1209600 seconds)
+ZSK_algo: RSASHA1 # (Algorithm ID 5)
+ZSK_bits: 512
+ZSK_randfile: "/dev/urandom"
+
+# dnssec-signer options
+LogFile: "zkt.log"
+LogLevel: debug
+SyslogFacility: USER
+SyslogLevel: notice
+VerboseLog: 2
+Keyfile: "dnskey.db"
+Zonefile: "zone.db"
+KeySetDir: "../keysets"
+DLV_Domain: ""
+Sig_Pseudorand: True
+Distribute_Cmd: "./dist.sh"
diff --git a/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+003+42138.key b/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+003+42138.key
new file mode 100644
index 0000000..6a64c44
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+003+42138.key
@@ -0,0 +1,3 @@
+;% generationtime=20080609224426
+;% lifetime=60d
+dyn.example.net. IN DNSKEY 257 3 3 CNtFdVrUUJ9MPDyzGoPm+tSKUgnX4bble5+VNGd4RjwWpEDj8RhEAhQ7 LybJzr0wtHXT2Q/KS55xARkUtcH2TVO/ayMupa30pM38rd8uF38sm+AB KLEvCbPjaLZyW+s10di8nLp1aAxKFFfAEfXkIhl3Wm5g9CvjrMlrxAOf Ny/jtz4v+asIr6/d992V80G9wMKMvTMQoCr4Sp9s2JubW79i4RBVWgHH JMmtyqq+SqEkPhZvsTuo2sXgIH9vRS3XgfkGtw/KyTUM29bhZ2eB+Ldq +bggp1gbBDiSsxZPjxciizI/mCzXWbq8BdfZ6LsddMjAolJwCtaPCD4e 4infmw+YSxjGau+YGgI0Cc0uItzQmNNpSoejM3IWGV+SN/YuPJIzw8wi xDfO6kCNiPsW45Fvq31148cAvUvwiqYPQ3fONeOTdQjsJWLLdLTApVEH 10kjAGfa30Tm92lQhhG5ovWrWCMbFlw4Lbvlon+X2snWPNut0a1Pz4Wd clDcmNU8dxi1lFvGbcJ0E4qBoJVBIzDh4HX1
diff --git a/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+003+42138.private b/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+003+42138.private
new file mode 100644
index 0000000..4f7ec3d
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+003+42138.private
@@ -0,0 +1,7 @@
+Private-key-format: v1.2
+Algorithm: 3 (DSA)
+Prime(p): 4bble5+VNGd4RjwWpEDj8RhEAhQ7LybJzr0wtHXT2Q/KS55xARkUtcH2TVO/ayMupa30pM38rd8uF38sm+ABKLEvCbPjaLZyW+s10di8nLp1aAxKFFfAEfXkIhl3Wm5g9CvjrMlrxAOfNy/jtz4v+asIr6/d992V80G9wMKMvTM=
+Subprime(q): 20V1WtRQn0w8PLMag+b61IpSCdc=
+Base(g): EKAq+EqfbNibm1u/YuEQVVoBxyTJrcqqvkqhJD4Wb7E7qNrF4CB/b0Ut14H5BrcPysk1DNvW4Wdngfi3avm4IKdYGwQ4krMWT48XIosyP5gs11m6vAXX2ei7HXTIwKJScArWjwg+HuIp35sPmEsYxmrvmBoCNAnNLiLc0JjTaUo=
+Private_value(x): xY/GSk3U4oHIsvUiAs/9/n+6ttk=
+Public_value(y): h6MzchYZX5I39i48kjPDzCLEN87qQI2I+xbjkW+rfXXjxwC9S/CKpg9Dd84145N1COwlYst0tMClUQfXSSMAZ9rfROb3aVCGEbmi9atYIxsWXDgtu+Wif5faydY8263RrU/PhZ1yUNyY1Tx3GLWUW8ZtwnQTioGglUEjMOHgdfU=
diff --git a/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+005+01355.key b/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+005+01355.key
new file mode 100644
index 0000000..d129398
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+005+01355.key
@@ -0,0 +1,3 @@
+;% generationtime=20080609224426
+;% lifetime=14d
+dyn.example.net. IN DNSKEY 256 3 5 BQEAAAAB1hmOomNafbJ3H76e8V4qmFvlFWQuIkM+jbh+s79ZpErpCR7w BS5TswdoTeglX9UjP0D6hLmHfTcsdHQLLeMidQ==
diff --git a/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+005+01355.private b/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+005+01355.private
new file mode 100644
index 0000000..3692946
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./Kdyn.example.net.+005+01355.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: 1hmOomNafbJ3H76e8V4qmFvlFWQuIkM+jbh+s79ZpErpCR7wBS5TswdoTeglX9UjP0D6hLmHfTcsdHQLLeMidQ==
+PublicExponent: AQAAAAE=
+PrivateExponent: dAiTob6wk4h5l6frfh49NAzd3RBsVRxqqCsMao52fJvlK06wmOb9PkqOaEMTDroJEGgN6zD/sWcGPK7nYwDMHQ==
+Prime1: 731n5xPK9UQqQsQtattcC4MxtL6+OP1CyLy8e2tsd/8=
+Prime2: 5NwPUBy32o2zzpw4TDH3omB6yk0fmFItJx4ek3RaBYs=
+Exponent1: jzq6en2c8SwS5uQwY3/vFY549HMSTxP58kyS/GJ9hqE=
+Exponent2: y52KLCquniy3EwUypKRkPZPftjBoqZkXeQLXSk4b850=
+Coefficient: vHnxG4D4n+IKETXrutOFT+iREDDcfj6GpYubIP/goZc=
diff --git a/contrib/zkt/examples/flat/dyn.example.net./dnskey.db b/contrib/zkt/examples/flat/dyn.example.net./dnskey.db
new file mode 100644
index 0000000..e0f978e
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./dnskey.db
@@ -0,0 +1,29 @@
+;
+; !!! Don't edit this file by hand.
+; !!! It will be generated by dnssec-signer.
+;
+; Last generation time Jun 12 2008 18:28:38
+;
+
+; *** List of Key Signing Keys ***
+; dyn.example.net. tag=42138 algo=DSA generated Jun 10 2008 00:44:26
+dyn.example.net. 14400 IN DNSKEY 257 3 3 (
+ CNtFdVrUUJ9MPDyzGoPm+tSKUgnX4bble5+VNGd4RjwWpEDj8RhEAhQ7
+ LybJzr0wtHXT2Q/KS55xARkUtcH2TVO/ayMupa30pM38rd8uF38sm+AB
+ KLEvCbPjaLZyW+s10di8nLp1aAxKFFfAEfXkIhl3Wm5g9CvjrMlrxAOf
+ Ny/jtz4v+asIr6/d992V80G9wMKMvTMQoCr4Sp9s2JubW79i4RBVWgHH
+ JMmtyqq+SqEkPhZvsTuo2sXgIH9vRS3XgfkGtw/KyTUM29bhZ2eB+Ldq
+ +bggp1gbBDiSsxZPjxciizI/mCzXWbq8BdfZ6LsddMjAolJwCtaPCD4e
+ 4infmw+YSxjGau+YGgI0Cc0uItzQmNNpSoejM3IWGV+SN/YuPJIzw8wi
+ xDfO6kCNiPsW45Fvq31148cAvUvwiqYPQ3fONeOTdQjsJWLLdLTApVEH
+ 10kjAGfa30Tm92lQhhG5ovWrWCMbFlw4Lbvlon+X2snWPNut0a1Pz4Wd
+ clDcmNU8dxi1lFvGbcJ0E4qBoJVBIzDh4HX1
+ ) ; key id = 42138
+
+; *** List of Zone Signing Keys ***
+; dyn.example.net. tag=1355 algo=RSASHA1 generated Jun 10 2008 00:44:26
+dyn.example.net. 14400 IN DNSKEY 256 3 5 (
+ BQEAAAAB1hmOomNafbJ3H76e8V4qmFvlFWQuIkM+jbh+s79ZpErpCR7w
+ BS5TswdoTeglX9UjP0D6hLmHfTcsdHQLLeMidQ==
+ ) ; key id = 1355
+
diff --git a/contrib/zkt/examples/flat/dyn.example.net./dnssec.conf b/contrib/zkt/examples/flat/dyn.example.net./dnssec.conf
new file mode 100644
index 0000000..0998fda
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./dnssec.conf
@@ -0,0 +1,5 @@
+# signing key parameters
+KSK_lifetime: 60d # (5184000 seconds)
+KSK_algo: DSA
+KSK_bits: 1024
+KSK_randfile: "/dev/urandom"
diff --git a/contrib/zkt/examples/flat/dyn.example.net./dsset-dyn.example.net. b/contrib/zkt/examples/flat/dyn.example.net./dsset-dyn.example.net.
new file mode 100644
index 0000000..f94666a
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./dsset-dyn.example.net.
@@ -0,0 +1,2 @@
+dyn.example.net. IN DS 42138 3 1 0F49FCDB683D1903F69B6779DB55CA3472974879
+dyn.example.net. IN DS 42138 3 2 94AC94BFE3AFA17F7485F5F741274074FF2E26A360D776D8884F2689 CCED34C6
diff --git a/contrib/zkt/examples/flat/dyn.example.net./keyset-dyn.example.net. b/contrib/zkt/examples/flat/dyn.example.net./keyset-dyn.example.net.
new file mode 100644
index 0000000..002217b
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./keyset-dyn.example.net.
@@ -0,0 +1,18 @@
+$ORIGIN .
+dyn.example.net 7200 IN DNSKEY 257 3 3 (
+ CNtFdVrUUJ9MPDyzGoPm+tSKUgnX4bble5+V
+ NGd4RjwWpEDj8RhEAhQ7LybJzr0wtHXT2Q/K
+ S55xARkUtcH2TVO/ayMupa30pM38rd8uF38s
+ m+ABKLEvCbPjaLZyW+s10di8nLp1aAxKFFfA
+ EfXkIhl3Wm5g9CvjrMlrxAOfNy/jtz4v+asI
+ r6/d992V80G9wMKMvTMQoCr4Sp9s2JubW79i
+ 4RBVWgHHJMmtyqq+SqEkPhZvsTuo2sXgIH9v
+ RS3XgfkGtw/KyTUM29bhZ2eB+Ldq+bggp1gb
+ BDiSsxZPjxciizI/mCzXWbq8BdfZ6LsddMjA
+ olJwCtaPCD4e4infmw+YSxjGau+YGgI0Cc0u
+ ItzQmNNpSoejM3IWGV+SN/YuPJIzw8wixDfO
+ 6kCNiPsW45Fvq31148cAvUvwiqYPQ3fONeOT
+ dQjsJWLLdLTApVEH10kjAGfa30Tm92lQhhG5
+ ovWrWCMbFlw4Lbvlon+X2snWPNut0a1Pz4Wd
+ clDcmNU8dxi1lFvGbcJ0E4qBoJVBIzDh4HX1
+ ) ; key id = 42138
diff --git a/contrib/zkt/examples/flat/dyn.example.net./zone.db b/contrib/zkt/examples/flat/dyn.example.net./zone.db
new file mode 100644
index 0000000..ee557b8
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./zone.db
@@ -0,0 +1,136 @@
+; File written on Thu Jun 12 18:28:34 2008
+; dnssec_signzone version 9.5.0
+dyn.example.net. 7200 IN SOA ns1.example.net. hostmaster.example.net. (
+ 7 ; serial
+ 43200 ; refresh (12 hours)
+ 1800 ; retry (30 minutes)
+ 1209600 ; expire (2 weeks)
+ 7200 ; minimum (2 hours)
+ )
+ 7200 RRSIG SOA 5 3 7200 20080622152834 (
+ 20080612152834 1355 dyn.example.net.
+ h8oKA1I7aC378Cll7LdhM2XZzrtsoxOdPaas
+ SMAd5Ok2zobl8i4nTpxUzmJE27U+yEeOJkf+
+ SXgsy934gAaYLw== )
+ 7200 NS ns1.example.net.
+ 7200 NS ns2.example.net.
+ 7200 RRSIG NS 5 3 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ xuEEg3kN7hAVIwdQ8l8lmeEzNhrtz5Ow1PQK
+ Sm3KTIxXI8RLcqZgc4pMlCWq+gWwxekvxJwz
+ lU0C+J4VPkA8pA== )
+ 7200 NSEC localhost.dyn.example.net. NS SOA RRSIG NSEC DNSKEY
+ 7200 RRSIG NSEC 5 3 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ XFDBfmcN874qUtNsGwD9Ir0QAzjYMw3BI40I
+ HFEOkTBJouhQ8RBpR6YqgWpkLqg1khvES5DH
+ +6XuqA8u/xPmbw== )
+ 3600 DNSKEY 256 3 5 (
+ BQEAAAAB1hmOomNafbJ3H76e8V4qmFvlFWQu
+ IkM+jbh+s79ZpErpCR7wBS5TswdoTeglX9Uj
+ P0D6hLmHfTcsdHQLLeMidQ==
+ ) ; key id = 1355
+ 3600 DNSKEY 257 3 3 (
+ CNtFdVrUUJ9MPDyzGoPm+tSKUgnX4bble5+V
+ NGd4RjwWpEDj8RhEAhQ7LybJzr0wtHXT2Q/K
+ S55xARkUtcH2TVO/ayMupa30pM38rd8uF38s
+ m+ABKLEvCbPjaLZyW+s10di8nLp1aAxKFFfA
+ EfXkIhl3Wm5g9CvjrMlrxAOfNy/jtz4v+asI
+ r6/d992V80G9wMKMvTMQoCr4Sp9s2JubW79i
+ 4RBVWgHHJMmtyqq+SqEkPhZvsTuo2sXgIH9v
+ RS3XgfkGtw/KyTUM29bhZ2eB+Ldq+bggp1gb
+ BDiSsxZPjxciizI/mCzXWbq8BdfZ6LsddMjA
+ olJwCtaPCD4e4infmw+YSxjGau+YGgI0Cc0u
+ ItzQmNNpSoejM3IWGV+SN/YuPJIzw8wixDfO
+ 6kCNiPsW45Fvq31148cAvUvwiqYPQ3fONeOT
+ dQjsJWLLdLTApVEH10kjAGfa30Tm92lQhhG5
+ ovWrWCMbFlw4Lbvlon+X2snWPNut0a1Pz4Wd
+ clDcmNU8dxi1lFvGbcJ0E4qBoJVBIzDh4HX1
+ ) ; key id = 42138
+ 3600 RRSIG DNSKEY 3 3 3600 20080615214426 (
+ 20080609214426 42138 dyn.example.net.
+ CIIuZ4cbwEWxoPGO6KDcLRO4Z3y0i2VhXy+5
+ 1X+nmHSkpcKJrUty/wY= )
+ 3600 RRSIG DNSKEY 5 3 3600 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ xGL6ZjA7v2RjPj7BnYjCvsgMRm/Z94j4c5K4
+ 7twJsUZ0AO/mURIpdbCigDfFJuK2fy/8X4Vi
+ 9K8P4EgCcj52Jw== )
+localhost.dyn.example.net. 7200 IN A 127.0.0.1
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ s+RvcycC8aAYgRcR5qBdVXhpRxBMTFS5Q0Pk
+ FN7OAdfmJ/3nV7+ehu0eOZ2ZjO2Pm4ZFcSM1
+ Sm1ttNxSTe2M8A== )
+ 7200 NSEC ns1.dyn.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ ZhXlmS/WJPbIiXwLKzNFOxw7RU3owfTA8vEM
+ +/SDZO/7+aVSj5IgbsUs3qLAuFrMN8BFEAWt
+ AqArf+M3STbO9g== )
+ns1.dyn.example.net. 7200 IN A 1.0.0.5
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ gPY1vUcxdWRJ1YbFMg/8rgoPZwta6rFrxQZl
+ KbyBNctNmlbXxeynP6j3qjwq9dydzbNt+sjO
+ TdWtXSZIlU2JKQ== )
+ 7200 AAAA 2001:db8::53
+ 7200 RRSIG AAAA 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ Y/PZmvaKPq4CqDvdG7eA2sxlnCPeNKHkZOB4
+ eDvK1x+q/WfTs3BDd3+g4zlG5nMC+NRSlXeO
+ Q4Pxd2rI9ud1hA== )
+ 7200 NSEC ns2.dyn.example.net. A AAAA RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ pLgxecgjqGdhVmCcUl59FljWsnC4bjkslUdt
+ 0etzeGD1SNGUqhFcW10EgZE4Y9pXwvLvw68R
+ sj80tqtN0NHi/Q== )
+ns2.dyn.example.net. 7200 IN A 1.2.0.6
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ pHtJzfj0HU/AkLE70xT0UG8M/Gvvsia61TnC
+ UrxR/61uQk1X4Vy2+oPA14Yb2QJ7ZHG5D1cn
+ LrVtjyQbfimbOA== )
+ 7200 NSEC x.dyn.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ vjPL9Mb6oUyg9y8m+BpVpTRpac9+WJxu8FHd
+ Xv4xk67NN+L+Zpukm0D8LSOrk4hZk0X5JkLD
+ Pz/gpH280yQJFA== )
+x.dyn.example.net. 7200 IN A 1.2.3.4
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ tFyv0gmTKt8/IXdH9VA1H1ymBQ8EIviN2xbC
+ P8vzWZbay3Az2GPObYmaHKb1dm+Sq1dQUJsb
+ jn6fdB+T2Zs9Pw== )
+ 7200 NSEC y.dyn.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ bWhiuA+4V86k/bfw7XQ7qDHwxTwbTyN+2gu5
+ MeYQA/WeHdb+3QUOYr6aERRJlbD4q431d4f7
+ 0sIwBMHOsDjTSA== )
+y.dyn.example.net. 7200 IN A 1.2.3.5
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ KQbZCcMcXWwGUyHyubt0VRhrpgiOel/0rQpF
+ 18PyCNIAUIdRra1+Tj12ZaCBT2x5fu+/rtki
+ qA5CzWo8HIPwmA== )
+ 7200 NSEC z.dyn.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ e/zPTQ1WxvSJymZ/QSyPYFRYpc8gScTbwfXY
+ mSyhQGyn1FjfLodAvyicNYbKF/oxR7IaXKLn
+ lO6C9gQ+Iu9wyw== )
+z.dyn.example.net. 7200 IN A 1.2.3.6
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ hv9KA2BS+b97KSebN4h/nrP8cU4FUASHdsZj
+ E2GMTf1aV3gpUyPf8LizKhLbUo/LF0bO3CpJ
+ rWBT4VggwE8blQ== )
+ 7200 NSEC dyn.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ r8f5dzQcdnn8gvr0jiExt/n4IUCVKID9Nahx
+ XMDPLrA7ZH7omol+hKz6wlumYmjphlP2mHUU
+ TNZYnWKCkD3hAQ== )
diff --git a/contrib/zkt/examples/flat/dyn.example.net./zone.db.dsigned b/contrib/zkt/examples/flat/dyn.example.net./zone.db.dsigned
new file mode 100644
index 0000000..9e4c5c8
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./zone.db.dsigned
@@ -0,0 +1,136 @@
+; File written on Thu Jun 12 18:28:39 2008
+; dnssec_signzone version 9.5.0
+dyn.example.net. 7200 IN SOA ns1.example.net. hostmaster.example.net. (
+ 8 ; serial
+ 43200 ; refresh (12 hours)
+ 1800 ; retry (30 minutes)
+ 1209600 ; expire (2 weeks)
+ 7200 ; minimum (2 hours)
+ )
+ 7200 RRSIG SOA 5 3 7200 20080622152838 (
+ 20080612152838 1355 dyn.example.net.
+ GXyAKsmJ3D+pFic86kQxw+ASoAeGwuGj2rY+
+ fby0HR5ud3i/Iq857ZlluDbQbg1EKZuar0l5
+ e7HwrB59bxKAuw== )
+ 7200 NS ns1.example.net.
+ 7200 NS ns2.example.net.
+ 7200 RRSIG NS 5 3 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ xuEEg3kN7hAVIwdQ8l8lmeEzNhrtz5Ow1PQK
+ Sm3KTIxXI8RLcqZgc4pMlCWq+gWwxekvxJwz
+ lU0C+J4VPkA8pA== )
+ 7200 NSEC localhost.dyn.example.net. NS SOA RRSIG NSEC DNSKEY
+ 7200 RRSIG NSEC 5 3 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ XFDBfmcN874qUtNsGwD9Ir0QAzjYMw3BI40I
+ HFEOkTBJouhQ8RBpR6YqgWpkLqg1khvES5DH
+ +6XuqA8u/xPmbw== )
+ 3600 DNSKEY 256 3 5 (
+ BQEAAAAB1hmOomNafbJ3H76e8V4qmFvlFWQu
+ IkM+jbh+s79ZpErpCR7wBS5TswdoTeglX9Uj
+ P0D6hLmHfTcsdHQLLeMidQ==
+ ) ; key id = 1355
+ 3600 DNSKEY 257 3 3 (
+ CNtFdVrUUJ9MPDyzGoPm+tSKUgnX4bble5+V
+ NGd4RjwWpEDj8RhEAhQ7LybJzr0wtHXT2Q/K
+ S55xARkUtcH2TVO/ayMupa30pM38rd8uF38s
+ m+ABKLEvCbPjaLZyW+s10di8nLp1aAxKFFfA
+ EfXkIhl3Wm5g9CvjrMlrxAOfNy/jtz4v+asI
+ r6/d992V80G9wMKMvTMQoCr4Sp9s2JubW79i
+ 4RBVWgHHJMmtyqq+SqEkPhZvsTuo2sXgIH9v
+ RS3XgfkGtw/KyTUM29bhZ2eB+Ldq+bggp1gb
+ BDiSsxZPjxciizI/mCzXWbq8BdfZ6LsddMjA
+ olJwCtaPCD4e4infmw+YSxjGau+YGgI0Cc0u
+ ItzQmNNpSoejM3IWGV+SN/YuPJIzw8wixDfO
+ 6kCNiPsW45Fvq31148cAvUvwiqYPQ3fONeOT
+ dQjsJWLLdLTApVEH10kjAGfa30Tm92lQhhG5
+ ovWrWCMbFlw4Lbvlon+X2snWPNut0a1Pz4Wd
+ clDcmNU8dxi1lFvGbcJ0E4qBoJVBIzDh4HX1
+ ) ; key id = 42138
+ 3600 RRSIG DNSKEY 3 3 3600 20080615214426 (
+ 20080609214426 42138 dyn.example.net.
+ CIIuZ4cbwEWxoPGO6KDcLRO4Z3y0i2VhXy+5
+ 1X+nmHSkpcKJrUty/wY= )
+ 3600 RRSIG DNSKEY 5 3 3600 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ xGL6ZjA7v2RjPj7BnYjCvsgMRm/Z94j4c5K4
+ 7twJsUZ0AO/mURIpdbCigDfFJuK2fy/8X4Vi
+ 9K8P4EgCcj52Jw== )
+localhost.dyn.example.net. 7200 IN A 127.0.0.1
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ s+RvcycC8aAYgRcR5qBdVXhpRxBMTFS5Q0Pk
+ FN7OAdfmJ/3nV7+ehu0eOZ2ZjO2Pm4ZFcSM1
+ Sm1ttNxSTe2M8A== )
+ 7200 NSEC ns1.dyn.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ ZhXlmS/WJPbIiXwLKzNFOxw7RU3owfTA8vEM
+ +/SDZO/7+aVSj5IgbsUs3qLAuFrMN8BFEAWt
+ AqArf+M3STbO9g== )
+ns1.dyn.example.net. 7200 IN A 1.0.0.5
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ gPY1vUcxdWRJ1YbFMg/8rgoPZwta6rFrxQZl
+ KbyBNctNmlbXxeynP6j3qjwq9dydzbNt+sjO
+ TdWtXSZIlU2JKQ== )
+ 7200 AAAA 2001:db8::53
+ 7200 RRSIG AAAA 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ Y/PZmvaKPq4CqDvdG7eA2sxlnCPeNKHkZOB4
+ eDvK1x+q/WfTs3BDd3+g4zlG5nMC+NRSlXeO
+ Q4Pxd2rI9ud1hA== )
+ 7200 NSEC ns2.dyn.example.net. A AAAA RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ pLgxecgjqGdhVmCcUl59FljWsnC4bjkslUdt
+ 0etzeGD1SNGUqhFcW10EgZE4Y9pXwvLvw68R
+ sj80tqtN0NHi/Q== )
+ns2.dyn.example.net. 7200 IN A 1.2.0.6
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ pHtJzfj0HU/AkLE70xT0UG8M/Gvvsia61TnC
+ UrxR/61uQk1X4Vy2+oPA14Yb2QJ7ZHG5D1cn
+ LrVtjyQbfimbOA== )
+ 7200 NSEC x.dyn.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ vjPL9Mb6oUyg9y8m+BpVpTRpac9+WJxu8FHd
+ Xv4xk67NN+L+Zpukm0D8LSOrk4hZk0X5JkLD
+ Pz/gpH280yQJFA== )
+x.dyn.example.net. 7200 IN A 1.2.3.4
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ tFyv0gmTKt8/IXdH9VA1H1ymBQ8EIviN2xbC
+ P8vzWZbay3Az2GPObYmaHKb1dm+Sq1dQUJsb
+ jn6fdB+T2Zs9Pw== )
+ 7200 NSEC y.dyn.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ bWhiuA+4V86k/bfw7XQ7qDHwxTwbTyN+2gu5
+ MeYQA/WeHdb+3QUOYr6aERRJlbD4q431d4f7
+ 0sIwBMHOsDjTSA== )
+y.dyn.example.net. 7200 IN A 1.2.3.5
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ KQbZCcMcXWwGUyHyubt0VRhrpgiOel/0rQpF
+ 18PyCNIAUIdRra1+Tj12ZaCBT2x5fu+/rtki
+ qA5CzWo8HIPwmA== )
+ 7200 NSEC z.dyn.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ e/zPTQ1WxvSJymZ/QSyPYFRYpc8gScTbwfXY
+ mSyhQGyn1FjfLodAvyicNYbKF/oxR7IaXKLn
+ lO6C9gQ+Iu9wyw== )
+z.dyn.example.net. 7200 IN A 1.2.3.6
+ 7200 RRSIG A 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ hv9KA2BS+b97KSebN4h/nrP8cU4FUASHdsZj
+ E2GMTf1aV3gpUyPf8LizKhLbUo/LF0bO3CpJ
+ rWBT4VggwE8blQ== )
+ 7200 NSEC dyn.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 4 7200 20080615214426 (
+ 20080609214426 1355 dyn.example.net.
+ r8f5dzQcdnn8gvr0jiExt/n4IUCVKID9Nahx
+ XMDPLrA7ZH7omol+hKz6wlumYmjphlP2mHUU
+ TNZYnWKCkD3hAQ== )
diff --git a/contrib/zkt/examples/flat/dyn.example.net./zone.org b/contrib/zkt/examples/flat/dyn.example.net./zone.org
new file mode 100644
index 0000000..c536fc8
--- /dev/null
+++ b/contrib/zkt/examples/flat/dyn.example.net./zone.org
@@ -0,0 +1,30 @@
+;-----------------------------------------------------------------
+;
+; @(#) dyn.example.net/zone.org
+;
+;-----------------------------------------------------------------
+
+$TTL 7200
+
+@ IN SOA ns1.example.net. hostmaster.example.net. (
+ 1 ; Serial
+ 43200 ; Refresh
+ 1800 ; Retry
+ 2W ; Expire
+ 7200 ) ; Minimum
+
+ IN NS ns1.example.net.
+ IN NS ns2.example.net.
+
+ns1 IN A 1.0.0.5
+ IN AAAA 2001:db8::53
+ns2 IN A 1.2.0.6
+
+localhost IN A 127.0.0.1
+
+x IN A 1.2.3.4
+y IN A 1.2.3.5
+z IN A 1.2.3.6
+
+$INCLUDE dnskey.db
+
diff --git a/contrib/zkt/examples/flat/example.net./Kexample.net.+005+01764.key b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+01764.key
new file mode 100644
index 0000000..bd273d3
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+01764.key
@@ -0,0 +1,3 @@
+;% generationtime=20080506212634
+;% lifetime=60d
+example.net. IN DNSKEY 257 3 5 BQEAAAABDUi2uSUlDjESbnrnY5wd8+pXxhYVY4wCi2UVjhcehvIb2bF8 VJH2Q9/0ubQR1vQ2VJhsGUj3A7bdTfbMETPxKkZaDpc9lCYrm0z5HDrs lyx4bSb4JX/iCyhgYZXrTVb9WyLXjUtmDUktDjZgsyVshFHVJShBUSj+ YpnfQkndGViDAbJRycXDYEF1hCNmTK3KsR1JS9dXMKI3WidH+B9rLlBU 8w==
diff --git a/contrib/zkt/examples/flat/example.net./Kexample.net.+005+01764.published b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+01764.published
new file mode 100644
index 0000000..42b8b80
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+01764.published
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: DUi2uSUlDjESbnrnY5wd8+pXxhYVY4wCi2UVjhcehvIb2bF8VJH2Q9/0ubQR1vQ2VJhsGUj3A7bdTfbMETPxKkZaDpc9lCYrm0z5HDrslyx4bSb4JX/iCyhgYZXrTVb9WyLXjUtmDUktDjZgsyVshFHVJShBUSj+YpnfQkndGViDAbJRycXDYEF1hCNmTK3KsR1JS9dXMKI3WidH+B9rLlBU8w==
+PublicExponent: AQAAAAE=
+PrivateExponent: AzPR74ljfqsl7qB92XeCowR3igYQrN59a2Z8VGB1PegjagkBltDzudzYyDKpvqdigjeFLL54f1MN5JCPo4J2Q6Ij49LAQ5GsXiEd/FWlwR+UztOcW/uZ3W6DNIwuMbSY7ruZmpv/zVPpyeY1PVXgCsJlX2Zj/Wt8QHASHp5rUugGQSPQfVSQ/mBdDXMZw2tEb3b10quziCmKuHegopRYeuNXwQ==
+Prime1: A+5jXfxmP0Mfnjr4m8BPrPkDyokgFXZB3dXibxeZqp4ypcwpXeO0xTf1FjSZeIOi2RJOzpym914IYa3wPx4zbxmsGeozr1hTIWE+6Xuz0qjE0w==
+Prime2: A2EOffOaSvEoTUf/0dF8Z9/dYxIrE9HBbXRjgrlPc+WoG57lCkjxe/KO5Eclg9o5nrTFcsxpsjrdxOAcIcyTIHsXW8YgxDAb1mFJ0V6tBsabYQ==
+Exponent1: vmRAN3zHGTV28Oj4gslB/xA58sDyieCkDrpGaGChsPo7yUPOEeZQ8ep/FDnQoZLhLCn6XkKcN4D99Yo3JxVECBJOHZp8HrFsfF9BzpXk2yH9
+Exponent2: Aj8x3YdZJ0/KzwX2m6G2qZ5WktmkDITa+XHxvSashqlBm2niBCRFN5kNQNhkIO5ZAFWKEPuHSB5BZWTzgj8jeB8mRoYtbPlJom4KbNtCiZ6BYQ==
+Coefficient: A87WfUPUBfYDuSAu6kcHLAyr0OnqoXnMeXSgyq28CJXdh3Vg39Al8me07wWeRDjMzfpZGdKEhxyvVIS8WhY3du0FYoGI5YhJMqaYq3XjwLfpsQ==
diff --git a/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41151.key b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41151.key
new file mode 100644
index 0000000..d72baa9
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41151.key
@@ -0,0 +1,3 @@
+;% generationtime=20080420205422
+;% lifetime=60d
+example.net. IN DNSKEY 257 3 5 BQEAAAABDAnSCbSyScZdP2M6OQTbTGvZRD5avmDYgAwXv0EsnNautYn7 kzDGwY3oVTXWDTdII+syK0pt0unjUn2ActoXtyFzIk61VRKDroANM9/W O0PO/y50vNIGMJUL1TiMR6jCp23eSxQ39/1A+BeiU+fMjoJK0/Yc7hbM HWwD8myU0IEX8R2iVUTXNPNbmUV2M836Eu5SRLIVTc7P4vjKT1YYVnoQ qw==
diff --git a/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41151.private b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41151.private
new file mode 100644
index 0000000..554cd12
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41151.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: DAnSCbSyScZdP2M6OQTbTGvZRD5avmDYgAwXv0EsnNautYn7kzDGwY3oVTXWDTdII+syK0pt0unjUn2ActoXtyFzIk61VRKDroANM9/WO0PO/y50vNIGMJUL1TiMR6jCp23eSxQ39/1A+BeiU+fMjoJK0/Yc7hbMHWwD8myU0IEX8R2iVUTXNPNbmUV2M836Eu5SRLIVTc7P4vjKT1YYVnoQqw==
+PublicExponent: AQAAAAE=
+PrivateExponent: CJPcx+j7bWxMzKCl395v2PxQRYc/YurHU25oJL9i+B/bkxC8sRzSrTe4rRW61vhtAE3R6+CGz1336igirbEWKjHbPyBg42QHu2OCHWcKv4jq8k9yvtYGb9rKVvSUj4HAfZolr130loWW+CNp5soQQcJG0qxP+YkdI/Z+GDQ9kDbn80+r3wtCtVzjhoq0RoUSH3UnKUbs+DvacQmvepMLcM3PgQ==
+Prime1: A413lN4gpI+7Imn2Krm4CGyRCBoNwFa2PSr1ZQN195W5enKVZAkKg+49G7hoduMgjW2RAzwoJp0/4cGPx5nugSv93QT/mTMhYupL9KdGKcYUIQ==
+Prime2: A2N7TbYY1Q67CsoqHPvogKEP0XtlN421eF+88Yu/YnAZ3Ikd1nMad7rO1bVWptabsNuw0JFkpOmrS3u/GvaWmKCNGBlGjF/XlKr8Bh63V/zLSw==
+Exponent1: Aa0C6ssN8NTZIKsoGJEJLVbb9uB48nXtaMq2FxFARogrnmY0Gi/n8AWFc+ulPvAzJhhrjWF3VW38GcuPe3Ss8l3fpAbAexEnrJHOXxKLlOgmwQ==
+Exponent2: j78LKeDXSgTL5WmsffdJHSRe32GfaX6SgTF0BKzKVRuNIiOf7vHjzkDn4gdcTsMLTSNVp/Zj4vkWMkfJNq+AqosHpBFvhmd+boUG4Xde4jSp
+Coefficient: A1RWhKCgowdNAWs9OF3Q5CBBzC2Fq6O0CspJJD3cmNTEQVbxEbzSWyW7S1NsBgp+6de/HQ72IFtEAL9ChSy6pXWx27PGK6wE89rGbfaJ9Y2gzQ==
diff --git a/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41300.key b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41300.key
new file mode 100644
index 0000000..235a5df
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41300.key
@@ -0,0 +1,3 @@
+;% generationtime=20080721221039
+;% lifetime=14d
+example.net. IN DNSKEY 256 3 5 BQEAAAABz+XkYpKYKuMPi7jA8Y/qfzDuGKdGVadO1kBAK6UnrK+WbxP3 LjoOtWm13QuS8fHsuZipXs2ouT2S9dhdEArKfw==
diff --git a/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41300.private b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41300.private
new file mode 100644
index 0000000..b5041c0
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./Kexample.net.+005+41300.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: z+XkYpKYKuMPi7jA8Y/qfzDuGKdGVadO1kBAK6UnrK+WbxP3LjoOtWm13QuS8fHsuZipXs2ouT2S9dhdEArKfw==
+PublicExponent: AQAAAAE=
+PrivateExponent: MF8+pDySZKCy1bZvgH9me1xf6cMd7V7FYgIWqRTSGuGpRWdtnIoltaBWjj2UlCshJYiwT0Y5g3obAsorqBC3wQ==
+Prime1: 6M83fhmfDJmatbG+texk1m/E7Aj8yOTLommXQYC/18M=
+Prime2: 5JtrNfEt434OYY/aIFo+LpKQ4YHmni1IODDoP9sHkpU=
+Exponent1: nCZRKBmE9YucwPIw6E1yLiAJ87fqm9IGNLez0kmtV+0=
+Exponent2: 4rEtpIoEBRymA2/iJbg+UmyCd1MKp5Mx4WhFTv1KOS0=
+Coefficient: v0eWAC3cl0XllkeNGaq5thp02OnHsxVU8Xwtss3dCMw=
diff --git a/contrib/zkt/examples/flat/example.net./dnskey.db b/contrib/zkt/examples/flat/example.net./dnskey.db
new file mode 100644
index 0000000..6bd2ba0
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./dnskey.db
@@ -0,0 +1,33 @@
+;
+; !!! Don't edit this file by hand.
+; !!! It will be generated by dnssec-signer.
+;
+; Last generation time Jul 31 2008 00:25:53
+;
+
+; *** List of Key Signing Keys ***
+; example.net. tag=1764 algo=RSASHA1 generated Jun 19 2008 00:32:22
+example.net. 3600 IN DNSKEY 257 3 5 (
+ BQEAAAABDUi2uSUlDjESbnrnY5wd8+pXxhYVY4wCi2UVjhcehvIb2bF8
+ VJH2Q9/0ubQR1vQ2VJhsGUj3A7bdTfbMETPxKkZaDpc9lCYrm0z5HDrs
+ lyx4bSb4JX/iCyhgYZXrTVb9WyLXjUtmDUktDjZgsyVshFHVJShBUSj+
+ YpnfQkndGViDAbJRycXDYEF1hCNmTK3KsR1JS9dXMKI3WidH+B9rLlBU
+ 8w==
+ ) ; key id = 1764
+
+; example.net. tag=41151 algo=RSASHA1 generated Jun 19 2008 00:32:22
+example.net. 3600 IN DNSKEY 257 3 5 (
+ BQEAAAABDAnSCbSyScZdP2M6OQTbTGvZRD5avmDYgAwXv0EsnNautYn7
+ kzDGwY3oVTXWDTdII+syK0pt0unjUn2ActoXtyFzIk61VRKDroANM9/W
+ O0PO/y50vNIGMJUL1TiMR6jCp23eSxQ39/1A+BeiU+fMjoJK0/Yc7hbM
+ HWwD8myU0IEX8R2iVUTXNPNbmUV2M836Eu5SRLIVTc7P4vjKT1YYVnoQ
+ qw==
+ ) ; key id = 41151
+
+; *** List of Zone Signing Keys ***
+; example.net. tag=41300 algo=RSASHA1 generated Jul 24 2008 00:13:57
+example.net. 3600 IN DNSKEY 256 3 5 (
+ BQEAAAABz+XkYpKYKuMPi7jA8Y/qfzDuGKdGVadO1kBAK6UnrK+WbxP3
+ LjoOtWm13QuS8fHsuZipXs2ouT2S9dhdEArKfw==
+ ) ; key id = 41300
+
diff --git a/contrib/zkt/examples/flat/example.net./dsset-example.net. b/contrib/zkt/examples/flat/example.net./dsset-example.net.
new file mode 100644
index 0000000..d4a01ed
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./dsset-example.net.
@@ -0,0 +1,4 @@
+example.net. IN DS 1764 5 1 A6F060DDE8DE45CA7FD1C21E2F39C477F214795F
+example.net. IN DS 1764 5 2 B7109245C60ACEDD1630E145477FDF574D5BD9CABE530AAC6D7192DB 7FBFAA3F
+example.net. IN DS 41151 5 1 BBB692EA07571E412F9385A618C1CAD9BFC1469A
+example.net. IN DS 41151 5 2 4D22B44C3DC09BD9EEADFFB917EFCE8E45F22E89FF0C096CD14F4405 CA1CAE3F
diff --git a/contrib/zkt/examples/flat/example.net./kexample.net.+005+14829.key b/contrib/zkt/examples/flat/example.net./kexample.net.+005+14829.key
new file mode 100644
index 0000000..fdf427b
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./kexample.net.+005+14829.key
@@ -0,0 +1,4 @@
+;% generationtime=20080415164557
+;% lifetime=20d
+;% expirationtime=20080506212633
+example.net. IN DNSKEY 385 3 5 BQEAAAABCrDt76ODmeteohszxggclH3vAXO/NXOnXjOzIivP5LaUL4/U uAtafg5JXypl/nCUVap9FG0K1ebCCBCMJaPCoi7pIgD5EgFzHPnxZo2w GvtmWYwK3MaBP4U8YzwpVbGpJIBAW+IZyM89LD6b2cvkJL5YEviPNfMp rMTLo7BOMVjMBpG2IuULOHq7dzyIe/ym/RXKuuYc5AVtHCBBfGKU/Wzn 0Q==
diff --git a/contrib/zkt/examples/flat/example.net./kexample.net.+005+14829.private b/contrib/zkt/examples/flat/example.net./kexample.net.+005+14829.private
new file mode 100644
index 0000000..1018561
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./kexample.net.+005+14829.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: CrDt76ODmeteohszxggclH3vAXO/NXOnXjOzIivP5LaUL4/UuAtafg5JXypl/nCUVap9FG0K1ebCCBCMJaPCoi7pIgD5EgFzHPnxZo2wGvtmWYwK3MaBP4U8YzwpVbGpJIBAW+IZyM89LD6b2cvkJL5YEviPNfMprMTLo7BOMVjMBpG2IuULOHq7dzyIe/ym/RXKuuYc5AVtHCBBfGKU/Wzn0Q==
+PublicExponent: AQAAAAE=
+PrivateExponent: CWC6hC61oQC954Dcu2Z0NNmLk6Wnr33yh7VCuT7kh5fSOgA6Fm0qQgH+nvW2sv9fpy8JB4WBaa/CnysKkLwjDBFcWkrMw7wDR0KAiixe8bjXCZUy95x2t3B/o23jQtS/ejJgaSSOJFioRcPoT5sv9mm6QCe3ir3g9+3n4COrzf0DY1oGfDLzuhrYDT/AM5MuEjSamlblTPHHsKlI3UCl+AHDLQ==
+Prime1: A3ZcDeyxt/SDgmgg4Yk7v66MbFU4GWreYp4/MYhEDsE4jA0cqEY28cAoN8FyPCB1H1t10IVqOs7/LSKrWdXMUKUv57DPMHJp539Wx2HYLmVIfw==
+Prime2: AxZ8J01/Sbij24nloiVsDJdjFTAVApr4S6n/QRdBkWumQTLexnQ1ErcTEVc3Fn0po04ZToIO5JNINrWNdAuNiaHYLuiD4pkkHuSAmTajbVsnrw==
+Exponent1: Iw7WPWd3zZeJ/b3zQcQtSosUXUWFy430aEsQWimMnibFm+qOVpsjhRkTHW/yZp227Y4sVb/ZhzCZWFGr6qWe0sdHIv5Yx6SkvIxv4rUiHdOL
+Exponent2: AhiPWhKq+Iyy/HRZuWpIAalUZ7yE7FeHWFQYQLocatTCnY91VsgNxRLXRwcci6mflhIVoLBDHJal7x4SCRq0Xbze5PeMlMUhsDQdCT+QYTgCRw==
+Coefficient: Auw2b1lPzp3gWxpnDNZWeuiwGcWTd9fNfN/4kBrCbulFngYTNVBpqathFqdwtojYXHfM2HZDKHqmZVZgON+FfxvauGvTDWO6MTBxUleeBlLmcg==
diff --git a/contrib/zkt/examples/flat/example.net./keyset-example.net. b/contrib/zkt/examples/flat/example.net./keyset-example.net.
new file mode 100644
index 0000000..c832578
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./keyset-example.net.
@@ -0,0 +1,19 @@
+$ORIGIN .
+example.net 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABDAnSCbSyScZdP2M6OQTbTGvZRD5a
+ vmDYgAwXv0EsnNautYn7kzDGwY3oVTXWDTdI
+ I+syK0pt0unjUn2ActoXtyFzIk61VRKDroAN
+ M9/WO0PO/y50vNIGMJUL1TiMR6jCp23eSxQ3
+ 9/1A+BeiU+fMjoJK0/Yc7hbMHWwD8myU0IEX
+ 8R2iVUTXNPNbmUV2M836Eu5SRLIVTc7P4vjK
+ T1YYVnoQqw==
+ ) ; key id = 41151
+ 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABDUi2uSUlDjESbnrnY5wd8+pXxhYV
+ Y4wCi2UVjhcehvIb2bF8VJH2Q9/0ubQR1vQ2
+ VJhsGUj3A7bdTfbMETPxKkZaDpc9lCYrm0z5
+ HDrslyx4bSb4JX/iCyhgYZXrTVb9WyLXjUtm
+ DUktDjZgsyVshFHVJShBUSj+YpnfQkndGViD
+ AbJRycXDYEF1hCNmTK3KsR1JS9dXMKI3WidH
+ +B9rLlBU8w==
+ ) ; key id = 1764
diff --git a/contrib/zkt/examples/flat/example.net./zone.db b/contrib/zkt/examples/flat/example.net./zone.db
new file mode 100644
index 0000000..42ad067
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./zone.db
@@ -0,0 +1,43 @@
+;-----------------------------------------------------------------
+;
+; @(#) example.net/zone.db
+;
+;-----------------------------------------------------------------
+
+$TTL 7200
+
+; Be sure that the serial number below is left
+; justified in a field of at least 10 chars!!
+; 0123456789;
+; It's also possible to use the date form e.g. 2005040101
+@ IN SOA ns1.example.net. hostmaster.example.net. (
+ 306 ; Serial
+ 43200 ; Refresh
+ 1800 ; Retry
+ 2W ; Expire
+ 7200 ) ; Minimum
+
+ IN NS ns1.example.net.
+ IN NS ns2.example.net.
+
+ns1 IN A 1.0.0.5
+ IN AAAA 2001:db8::53
+ns2 IN A 1.2.0.6
+
+localhost IN A 127.0.0.1
+
+a IN A 1.2.3.1
+b IN MX 10 a
+;c IN A 1.2.3.2
+d IN A 1.2.3.3
+ IN AAAA 2001:0db8::3
+
+; Delegation to secure zone; The DS resource record will
+; be added by dnssec-signzone automatically if the
+; keyset-sub.example.net file is present (run dnssec-signzone
+; with option -g or use the dnssec-signer tool) ;-)
+sub IN NS ns1.example.net.
+
+; this file will have all the zone keys
+$INCLUDE dnskey.db
+
diff --git a/contrib/zkt/examples/flat/example.net./zone.db.signed b/contrib/zkt/examples/flat/example.net./zone.db.signed
new file mode 100644
index 0000000..b10d122
--- /dev/null
+++ b/contrib/zkt/examples/flat/example.net./zone.db.signed
@@ -0,0 +1,166 @@
+; File written on Thu Jul 31 00:25:53 2008
+; dnssec_signzone version 9.5.1b1
+example.net. 7200 IN SOA ns1.example.net. hostmaster.example.net. (
+ 306 ; serial
+ 43200 ; refresh (12 hours)
+ 1800 ; retry (30 minutes)
+ 1209600 ; expire (2 weeks)
+ 7200 ; minimum (2 hours)
+ )
+ 7200 RRSIG SOA 5 2 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ eRpET793mGv1lKjHoaL/woHNxqFx8mFg1LlT
+ x3ISMuUH7BJCHI4urjNMIJCOKwTeDsstlmvt
+ llflqikDp8uLmQ== )
+ 7200 NS ns1.example.net.
+ 7200 NS ns2.example.net.
+ 7200 RRSIG NS 5 2 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ t7lt/MCYy2plJXQXeZFapUjzkhtYi0NIa4/i
+ sJInZYv78nT2981zrlYCX5UKswGy6VAchtgu
+ WDdVL5V3nirNiA== )
+ 7200 NSEC a.example.net. NS SOA RRSIG NSEC DNSKEY
+ 7200 RRSIG NSEC 5 2 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ TNq3FKjB7brjHQDD1vReNNddof1UmsAOdioU
+ vL1alQJa1zXVpL9Yl2NUbtuV3kKVpxxLAZM4
+ 8fjJ1uPzW3KVJQ== )
+ 3600 DNSKEY 256 3 5 (
+ BQEAAAABz+XkYpKYKuMPi7jA8Y/qfzDuGKdG
+ VadO1kBAK6UnrK+WbxP3LjoOtWm13QuS8fHs
+ uZipXs2ouT2S9dhdEArKfw==
+ ) ; key id = 41300
+ 3600 DNSKEY 257 3 5 (
+ BQEAAAABDAnSCbSyScZdP2M6OQTbTGvZRD5a
+ vmDYgAwXv0EsnNautYn7kzDGwY3oVTXWDTdI
+ I+syK0pt0unjUn2ActoXtyFzIk61VRKDroAN
+ M9/WO0PO/y50vNIGMJUL1TiMR6jCp23eSxQ3
+ 9/1A+BeiU+fMjoJK0/Yc7hbMHWwD8myU0IEX
+ 8R2iVUTXNPNbmUV2M836Eu5SRLIVTc7P4vjK
+ T1YYVnoQqw==
+ ) ; key id = 41151
+ 3600 DNSKEY 257 3 5 (
+ BQEAAAABDUi2uSUlDjESbnrnY5wd8+pXxhYV
+ Y4wCi2UVjhcehvIb2bF8VJH2Q9/0ubQR1vQ2
+ VJhsGUj3A7bdTfbMETPxKkZaDpc9lCYrm0z5
+ HDrslyx4bSb4JX/iCyhgYZXrTVb9WyLXjUtm
+ DUktDjZgsyVshFHVJShBUSj+YpnfQkndGViD
+ AbJRycXDYEF1hCNmTK3KsR1JS9dXMKI3WidH
+ +B9rLlBU8w==
+ ) ; key id = 1764
+ 3600 RRSIG DNSKEY 5 2 3600 20080805212553 (
+ 20080730212553 41151 example.net.
+ AoLzL97D0rw8R5leKTNH7XuKyLPUdmX2nmfb
+ Q9RV9mV1mcM7cV37C8nNp1xNqY91frjCiUtd
+ PjFa95U2B1ZVU6j2CgWzPLRidRTU/aKJy2MZ
+ dwkAx4P6MGXemCwi5xGY1JLP3WTtdW1ERBjE
+ tgOT8mOOA8pDk+1S2zUAGbT4WGLx09hf16n+
+ b9YR+mNVyEyJ8qJGvWm6U8niyhHOZWFj6QkL
+ Tw== )
+ 3600 RRSIG DNSKEY 5 2 3600 20080805212553 (
+ 20080730212553 41300 example.net.
+ up151hyvd84qGvWxziVwgzuLHvZ9os27gqSU
+ hMeplk+Q2coXShZ219zSQKfZHRYRQF0Hujwi
+ FSHnJW5dlBhMow== )
+a.example.net. 7200 IN A 1.2.3.1
+ 7200 RRSIG A 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ EOJulnvULgDyx+WXIPkkoAcBot3lKKIHplAM
+ aa2K3QIXak75/IxCh+K/yUpqgsbeU0wHJakd
+ vo0cFjkPvCCrHA== )
+ 7200 NSEC b.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ Vb+ZkjqQ+TzXmhsVEE1490F6O3Mww5z0GiO/
+ 1CtMb+qfUNS0RavmHVnm5rBYs3WyQmG04vQr
+ 2MS4wJguPpznEg== )
+b.example.net. 7200 IN MX 10 a.example.net.
+ 7200 RRSIG MX 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ RG6GDR1HAKQeG6TaWbIlp97FYZSp8Xf7ySxi
+ Q+OJaPw209RmlNFySWt/HQ6XiwPQ3OJUU9KJ
+ V1VbEaZnFVXu2Q== )
+ 7200 NSEC d.example.net. MX RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ MxxrqKlQWoN1PgC6g/VkzTQYRFZpeJfjtm9L
+ jbnNPVNUJoRFA2knURkrTB4nmQc6k9bms9Na
+ G1yt/jdFB699yg== )
+d.example.net. 7200 IN A 1.2.3.3
+ 7200 RRSIG A 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ LHAxOSR8B+5D4nPxGn3zr4w8E+sSffCRbiqS
+ 8Giafiugn+FKRRO+QrCBytSF/YBmwfuz7uQF
+ Xqk7op11oye7fA== )
+ 7200 AAAA 2001:db8::3
+ 7200 RRSIG AAAA 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ VkBfSCLQGwOsCdzJTCgNenXpIHQ1OfOHhqib
+ 2UHf/kPtCRxONFQUcKfTC10XSbnOJ7oWcyVC
+ sJOAIxxNQOefZg== )
+ 7200 NSEC localhost.example.net. A AAAA RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ e9HXw+0oV/wa8dobs1lstE68JgCzdlmnGUAh
+ /0878kn5nyoLBaFEW3u6LU1E1YY277Ox2jZD
+ X51lgVvrlOsMaw== )
+localhost.example.net. 7200 IN A 127.0.0.1
+ 7200 RRSIG A 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ cx0NJFy0/RjCjhlU1X3S0na2q9hMyHmvFLhv
+ zLk+LqSaK1rHW4GNCCsGlNxQIb9uJjQJuUq1
+ U9ZdHxUEqeRRtQ== )
+ 7200 NSEC ns1.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ nDPwYL/05NLxkY4iuyzH8ASiBq8FcY0uNQAg
+ F+bjdtm1xt1uyqTROl5JQ1P3SUb/EuoxCMII
+ hS9tIVb0spHDuQ== )
+ns1.example.net. 7200 IN A 1.0.0.5
+ 7200 RRSIG A 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ swMfIxbBfSCr4ACCa3dJ8d0gtoHD7Z0L0sTp
+ TFEZ9miQFFN9zxKHGRpk6fBjkiMI3bSAMbtM
+ bBUOTYWJIMT50g== )
+ 7200 AAAA 2001:db8::53
+ 7200 RRSIG AAAA 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ w+weJuOzg5fQ15RGdNQ/7Gf4DxkcKq4Drx0l
+ CZ16TKV3/fR8ROCzIP9HulPsNJtEFK+J+CbM
+ 5P5ZMXieZrh+xQ== )
+ 7200 NSEC ns2.example.net. A AAAA RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ xe9q0umSSgBNQ5H0yLSQ9tONsw2hORQpxMGT
+ rrfxEcPm86SLMM40dithZQeajNucRlmuadKX
+ HREpYT/DVVBT0A== )
+ns2.example.net. 7200 IN A 1.2.0.6
+ 7200 RRSIG A 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ gOU5QjhdfwBBNHi5uQOs53GoxU7eiSt9I/yk
+ 06EzlFU2gJ+1cmhYKqrSZM7XC7/c5I61AZDS
+ 2LaOiuqMIPm8Hw== )
+ 7200 NSEC sub.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ dT90BIfl/AJ6gVSbrU0TiOacE5ZffS4N4B5+
+ HQzwNup6HfL7ZwBEO/vhKJjSgwd+Oetfc76+
+ /l+dJFZ8FtdZTA== )
+sub.example.net. 7200 IN NS ns1.example.net.
+ 7200 DS 54876 5 1 (
+ CAB6127E303A8A8D7D5A29AE05DB60F4C506
+ 0B10 )
+ 7200 DS 54876 5 2 (
+ 7C8CAF1844479F3600213173BB5D1E2A4414
+ 3D63B6E0B3E10D8C5310ADF84D30 )
+ 7200 RRSIG DS 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ DjNb5DNaKyPMWJgfiLxXbw/BhuxxKd58tHv+
+ TQqrp6STx8jZRWNsigEh4QTyx8lyYcAPaYEt
+ X6JnkVWr89s82A== )
+ 7200 NSEC example.net. NS DS RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080805212553 (
+ 20080730212553 41300 example.net.
+ kDm+cYjtem6aZSTTsLdSQZnJJVfASXdIsrom
+ fViO1QIHNSZodbtWT9cqMvhMhmQ1rO5GVRGg
+ KaG0bEo8TpOAUw== )
diff --git a/contrib/zkt/examples/flat/keysets/dlvset-sub.example.net. b/contrib/zkt/examples/flat/keysets/dlvset-sub.example.net.
new file mode 100644
index 0000000..8e00719
--- /dev/null
+++ b/contrib/zkt/examples/flat/keysets/dlvset-sub.example.net.
@@ -0,0 +1,2 @@
+sub.example.net.dlv.trusted-keys.de. IN DLV 54876 5 1 CAB6127E303A8A8D7D5A29AE05DB60F4C5060B10
+sub.example.net.dlv.trusted-keys.de. IN DLV 54876 5 2 7C8CAF1844479F3600213173BB5D1E2A44143D63B6E0B3E10D8C5310 ADF84D30
diff --git a/contrib/zkt/examples/flat/keysets/dsset-dyn.example.net. b/contrib/zkt/examples/flat/keysets/dsset-dyn.example.net.
new file mode 100644
index 0000000..f94666a
--- /dev/null
+++ b/contrib/zkt/examples/flat/keysets/dsset-dyn.example.net.
@@ -0,0 +1,2 @@
+dyn.example.net. IN DS 42138 3 1 0F49FCDB683D1903F69B6779DB55CA3472974879
+dyn.example.net. IN DS 42138 3 2 94AC94BFE3AFA17F7485F5F741274074FF2E26A360D776D8884F2689 CCED34C6
diff --git a/contrib/zkt/examples/flat/keysets/dsset-example.net. b/contrib/zkt/examples/flat/keysets/dsset-example.net.
new file mode 100644
index 0000000..d4a01ed
--- /dev/null
+++ b/contrib/zkt/examples/flat/keysets/dsset-example.net.
@@ -0,0 +1,4 @@
+example.net. IN DS 1764 5 1 A6F060DDE8DE45CA7FD1C21E2F39C477F214795F
+example.net. IN DS 1764 5 2 B7109245C60ACEDD1630E145477FDF574D5BD9CABE530AAC6D7192DB 7FBFAA3F
+example.net. IN DS 41151 5 1 BBB692EA07571E412F9385A618C1CAD9BFC1469A
+example.net. IN DS 41151 5 2 4D22B44C3DC09BD9EEADFFB917EFCE8E45F22E89FF0C096CD14F4405 CA1CAE3F
diff --git a/contrib/zkt/examples/flat/keysets/dsset-sub.example.net. b/contrib/zkt/examples/flat/keysets/dsset-sub.example.net.
new file mode 100644
index 0000000..9bed62a
--- /dev/null
+++ b/contrib/zkt/examples/flat/keysets/dsset-sub.example.net.
@@ -0,0 +1,2 @@
+sub.example.net. IN DS 54876 5 1 CAB6127E303A8A8D7D5A29AE05DB60F4C5060B10
+sub.example.net. IN DS 54876 5 2 7C8CAF1844479F3600213173BB5D1E2A44143D63B6E0B3E10D8C5310 ADF84D30
diff --git a/contrib/zkt/examples/flat/keysets/keyset-dyn.example.net. b/contrib/zkt/examples/flat/keysets/keyset-dyn.example.net.
new file mode 100644
index 0000000..002217b
--- /dev/null
+++ b/contrib/zkt/examples/flat/keysets/keyset-dyn.example.net.
@@ -0,0 +1,18 @@
+$ORIGIN .
+dyn.example.net 7200 IN DNSKEY 257 3 3 (
+ CNtFdVrUUJ9MPDyzGoPm+tSKUgnX4bble5+V
+ NGd4RjwWpEDj8RhEAhQ7LybJzr0wtHXT2Q/K
+ S55xARkUtcH2TVO/ayMupa30pM38rd8uF38s
+ m+ABKLEvCbPjaLZyW+s10di8nLp1aAxKFFfA
+ EfXkIhl3Wm5g9CvjrMlrxAOfNy/jtz4v+asI
+ r6/d992V80G9wMKMvTMQoCr4Sp9s2JubW79i
+ 4RBVWgHHJMmtyqq+SqEkPhZvsTuo2sXgIH9v
+ RS3XgfkGtw/KyTUM29bhZ2eB+Ldq+bggp1gb
+ BDiSsxZPjxciizI/mCzXWbq8BdfZ6LsddMjA
+ olJwCtaPCD4e4infmw+YSxjGau+YGgI0Cc0u
+ ItzQmNNpSoejM3IWGV+SN/YuPJIzw8wixDfO
+ 6kCNiPsW45Fvq31148cAvUvwiqYPQ3fONeOT
+ dQjsJWLLdLTApVEH10kjAGfa30Tm92lQhhG5
+ ovWrWCMbFlw4Lbvlon+X2snWPNut0a1Pz4Wd
+ clDcmNU8dxi1lFvGbcJ0E4qBoJVBIzDh4HX1
+ ) ; key id = 42138
diff --git a/contrib/zkt/examples/flat/keysets/keyset-example.net. b/contrib/zkt/examples/flat/keysets/keyset-example.net.
new file mode 100644
index 0000000..c832578
--- /dev/null
+++ b/contrib/zkt/examples/flat/keysets/keyset-example.net.
@@ -0,0 +1,19 @@
+$ORIGIN .
+example.net 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABDAnSCbSyScZdP2M6OQTbTGvZRD5a
+ vmDYgAwXv0EsnNautYn7kzDGwY3oVTXWDTdI
+ I+syK0pt0unjUn2ActoXtyFzIk61VRKDroAN
+ M9/WO0PO/y50vNIGMJUL1TiMR6jCp23eSxQ3
+ 9/1A+BeiU+fMjoJK0/Yc7hbMHWwD8myU0IEX
+ 8R2iVUTXNPNbmUV2M836Eu5SRLIVTc7P4vjK
+ T1YYVnoQqw==
+ ) ; key id = 41151
+ 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABDUi2uSUlDjESbnrnY5wd8+pXxhYV
+ Y4wCi2UVjhcehvIb2bF8VJH2Q9/0ubQR1vQ2
+ VJhsGUj3A7bdTfbMETPxKkZaDpc9lCYrm0z5
+ HDrslyx4bSb4JX/iCyhgYZXrTVb9WyLXjUtm
+ DUktDjZgsyVshFHVJShBUSj+YpnfQkndGViD
+ AbJRycXDYEF1hCNmTK3KsR1JS9dXMKI3WidH
+ +B9rLlBU8w==
+ ) ; key id = 1764
diff --git a/contrib/zkt/examples/flat/keysets/keyset-sub.example.net. b/contrib/zkt/examples/flat/keysets/keyset-sub.example.net.
new file mode 100644
index 0000000..77aacd6
--- /dev/null
+++ b/contrib/zkt/examples/flat/keysets/keyset-sub.example.net.
@@ -0,0 +1,8 @@
+$ORIGIN .
+sub.example.net 7200 IN DNSKEY 257 3 5 (
+ AQOjGNN0/hLA20+W2qo0sktVActYKf1Opnx+
+ bmkWSrsmJHMBHlT8hL507pGTmDoyH0Ae9+3M
+ ZSTBL1S+HhA12B0htiTp8IbtN/gZOBbwD36c
+ BpPe72uDQoUy/TdSn1HLtoqUSMTB+saqCTZW
+ CfIEqcbHRn0T6PhgqLyCvLzbZ/avYw==
+ ) ; key id = 54876
diff --git a/contrib/zkt/examples/flat/named.conf b/contrib/zkt/examples/flat/named.conf
new file mode 100644
index 0000000..0e8551c
--- /dev/null
+++ b/contrib/zkt/examples/flat/named.conf
@@ -0,0 +1,99 @@
+/*****************************************************************
+**
+** #(@) named.conf (c) 6. May 2004 (hoz)
+**
+*****************************************************************/
+
+/*****************************************************************
+** logging options
+*****************************************************************/
+logging {
+ channel "named-log" {
+ file "/var/log/named" versions 3 size 2m;
+ print-time yes;
+ print-category yes;
+ print-severity yes;
+ severity info;
+ };
+ channel "resolver-log" {
+ file "/var/log/named";
+ print-time yes;
+ print-category yes;
+ print-severity yes;
+ severity debug 1;
+ };
+ channel "dnssec-log" {
+# file "/var/log/named-dnssec" ;
+ file "/var/log/named" ;
+ print-time yes;
+ print-category yes;
+ print-severity yes;
+ severity debug 3;
+ };
+ category "dnssec" { "dnssec-log"; };
+ category "default" { "named-log"; };
+ category "resolver" { "resolver-log"; };
+ category "client" { "resolver-log"; };
+ category "queries" { "resolver-log"; };
+};
+
+/*****************************************************************
+** name server options
+*****************************************************************/
+options {
+ directory ".";
+
+ dump-file "/var/log/named_dump.db";
+ statistics-file "/var/log/named.stats";
+
+ listen-on-v6 { any; };
+
+ query-source address * port 53;
+ transfer-source * port 53;
+ notify-source * port 53;
+
+ recursion yes;
+ dnssec-enable yes;
+ edns-udp-size 4096;
+
+# dnssec-lookaside "." trust-anchor "trusted-keys.de.";
+
+ querylog yes;
+
+};
+
+/*****************************************************************
+** include shared secrets...
+*****************************************************************/
+/** for control sessions ... **/
+controls {
+ inet 127.0.0.1
+ allow { localhost; };
+ inet ::1
+ allow { localhost; };
+};
+
+/*****************************************************************
+** ... and trusted_keys
+*****************************************************************/
+# include "trusted-keys.conf" ;
+
+/*****************************************************************
+** root server hints and required 127 stuff
+*****************************************************************/
+zone "." in {
+ type hint;
+ file "root.hint";
+};
+
+zone "localhost" in {
+ type master;
+ file "localhost.zone";
+};
+
+zone "0.0.127.in-addr.ARPA" in {
+ type master;
+ file "127.0.0.zone";
+};
+
+include "zone.conf";
diff --git a/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+04254.key b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+04254.key
new file mode 100644
index 0000000..a255a7b
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+04254.key
@@ -0,0 +1,3 @@
+;% generationtime=20080725213107
+;% lifetime=3d
+sub.example.net. IN DNSKEY 256 3 1 BQEAAAAB4Z/siqZTvCFKzaOrB8+HHTlR9is+/+/Sem6gxhZt/vpWkNMy aSpAT8LjR7nNHr9vNYsJ2KCQtY2dUFjT5BCeqQ==
diff --git a/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+04254.private b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+04254.private
new file mode 100644
index 0000000..e636e05
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+04254.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 1 (RSA)
+Modulus: 4Z/siqZTvCFKzaOrB8+HHTlR9is+/+/Sem6gxhZt/vpWkNMyaSpAT8LjR7nNHr9vNYsJ2KCQtY2dUFjT5BCeqQ==
+PublicExponent: AQAAAAE=
+PrivateExponent: fcaPYDDCumWIaPKV7FY0JB/PofSCo8amWw5u+eXFxh149WE5PeXYOOS2+x41keA5Z1PhYme4Ma5rcCMRN7n+sQ==
+Prime1: /RbDZdmt2zlsChJiLR+Brweas6L1jnzUsJFm78HlSnM=
+Prime2: 5DhKYbovzYbkIFhp1b9lt22+ymAU8LOGvFXdfb1y33M=
+Exponent1: yw61YMxuJGzEAgxVmlAm6oEH0WaaJ5T1PvZGut1xCU0=
+Exponent2: wYNtwOUtI0UQWQF1ZCBiVsquBIkPvI5eR2GQypHaK08=
+Coefficient: NqkVvrZjnJ/jVWDEykJ2XYuslJOIJPi1+7+sTUyBhPU=
diff --git a/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+56744.key b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+56744.key
new file mode 100644
index 0000000..4e7c3e5
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+56744.key
@@ -0,0 +1,3 @@
+;% generationtime=20080730222553
+;% lifetime=3d
+sub.example.net. IN DNSKEY 256 3 1 BQEAAAABxZS/DJA1BUdYVj5cOmMMnA5W/SHlkb4sEZkca3uIqV4gTzgv guftN+M1ZgwyPwarn7DQR1Eb92uW3ALxwN2o6w==
diff --git a/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+56744.published b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+56744.published
new file mode 100644
index 0000000..2a3ae65
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+001+56744.published
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 1 (RSA)
+Modulus: xZS/DJA1BUdYVj5cOmMMnA5W/SHlkb4sEZkca3uIqV4gTzgvguftN+M1ZgwyPwarn7DQR1Eb92uW3ALxwN2o6w==
+PublicExponent: AQAAAAE=
+PrivateExponent: aSglUr7DxsGNZMOhyoyN6W0xGps+JGfI3ErXbewlvflVSFSHrA19x0OafvR6eFzqmzKKGIyZBJkYT5NHqKIG6Q==
+Prime1: 4yqINEZm3xDdHGyv31umolirJtS4X2teORhzWDE/r6U=
+Prime2: 3qjiidKP41FSrOsXXgkj3XBi+OAH0cpVBZxCuP+ykU8=
+Exponent1: p8nyeR3ldgpw7A6tebr6okucM6324S5LPOWlC8ygxp0=
+Exponent2: a1qTrKaBO6pN7UI/mHimSYLoevjQBWeX8jB0tmG0NIc=
+Coefficient: NB2eeh6Z+a9qMf1w5UY2z9ME+ZyYtvRbYZSkedB4Q4Y=
diff --git a/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+005+54876.key b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+005+54876.key
new file mode 100644
index 0000000..21098f8
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+005+54876.key
@@ -0,0 +1 @@
+sub.example.net. IN DNSKEY 257 3 5 AQOjGNN0/hLA20+W2qo0sktVActYKf1Opnx+bmkWSrsmJHMBHlT8hL50 7pGTmDoyH0Ae9+3MZSTBL1S+HhA12B0htiTp8IbtN/gZOBbwD36cBpPe 72uDQoUy/TdSn1HLtoqUSMTB+saqCTZWCfIEqcbHRn0T6PhgqLyCvLzb Z/avYw==
diff --git a/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+005+54876.private b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+005+54876.private
new file mode 100644
index 0000000..ad5b363
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./Ksub.example.net.+005+54876.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: oxjTdP4SwNtPltqqNLJLVQHLWCn9TqZ8fm5pFkq7JiRzAR5U/IS+dO6Rk5g6Mh9AHvftzGUkwS9Uvh4QNdgdIbYk6fCG7Tf4GTgW8A9+nAaT3u9rg0KFMv03Up9Ry7aKlEjEwfrGqgk2VgnyBKnGx0Z9E+j4YKi8gry822f2r2M=
+PublicExponent: Aw==
+PrivateExponent: bLs3o1QMgJI1DzxxeHbc41aHkBv+NG79qZ7wuYcnbsL3VhQ4qFh++J8Lt7rRdr+AFKVJMu4YgMo4fr61eTq+FWije4t8PrILH6qzNdwCqOLsQYyKRUODTPsE+2BU6TZVBsBOBPlpJP9hTBj1DCoUTE6y8Evkkmf4C4Y6U7frF/s=
+Prime1: 1t2pJC/eQzdhrLR4qHlaaT6vPmBC+7eNPg8zjdZDA03TKMd/V4kw6XtB6QYQZRi/CXg7JjoLr3dpUgyMY0l8tw==
+Prime2: wlIHexyw6bAIC1WmnQFESPLNXjvYYYiyRqCmAPwq4b02/4g7LR/BoKkh+3xiBY+VxvhwUOd5XVEIIVjRcMyOtQ==
+Exponent1: jz5wwsqULM+WcyL7GvuRm38ffurXUnpeKV93s+QsrN6MxdpU5QYgm6eBRgQK7hB/W6V8xCaydPpGNrMIQjD9zw==
+Exponent2: gYwE/L3LRnVasjkZvgDYMKHePtKQQQXMLxXEAKgcln4kqlrSHhUrwHDBUlLsA7UOhKWgNe+mPjYFa5CLoIhfIw==
+Coefficient: DWng17udd0Q2STNt5gshQ6PjNQxEQmQMnCwltkosf8rJhl/rQuYULz0elnWhADcMBDYw7Y6Kb7xjpL4FdR0YnA==
diff --git a/contrib/zkt/examples/flat/sub.example.net./dlvset-sub.example.net. b/contrib/zkt/examples/flat/sub.example.net./dlvset-sub.example.net.
new file mode 100644
index 0000000..8e00719
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./dlvset-sub.example.net.
@@ -0,0 +1,2 @@
+sub.example.net.dlv.trusted-keys.de. IN DLV 54876 5 1 CAB6127E303A8A8D7D5A29AE05DB60F4C5060B10
+sub.example.net.dlv.trusted-keys.de. IN DLV 54876 5 2 7C8CAF1844479F3600213173BB5D1E2A44143D63B6E0B3E10D8C5310 ADF84D30
diff --git a/contrib/zkt/examples/flat/sub.example.net./dnskey.db b/contrib/zkt/examples/flat/sub.example.net./dnskey.db
new file mode 100644
index 0000000..396e7d3
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./dnskey.db
@@ -0,0 +1,29 @@
+;
+; !!! Don't edit this file by hand.
+; !!! It will be generated by dnssec-signer.
+;
+; Last generation time Jul 31 2008 13:19:17
+;
+
+; *** List of Key Signing Keys ***
+; sub.example.net. tag=54876 algo=RSASHA1 generated Jun 19 2008 00:32:22
+sub.example.net. 3600 IN DNSKEY 257 3 5 (
+ AQOjGNN0/hLA20+W2qo0sktVActYKf1Opnx+bmkWSrsmJHMBHlT8hL50
+ 7pGTmDoyH0Ae9+3MZSTBL1S+HhA12B0htiTp8IbtN/gZOBbwD36cBpPe
+ 72uDQoUy/TdSn1HLtoqUSMTB+saqCTZWCfIEqcbHRn0T6PhgqLyCvLzb
+ Z/avYw==
+ ) ; key id = 54876
+
+; *** List of Zone Signing Keys ***
+; sub.example.net. tag=4254 algo=RSAMD5 generated Jul 31 2008 00:25:52
+sub.example.net. 3600 IN DNSKEY 256 3 1 (
+ BQEAAAAB4Z/siqZTvCFKzaOrB8+HHTlR9is+/+/Sem6gxhZt/vpWkNMy
+ aSpAT8LjR7nNHr9vNYsJ2KCQtY2dUFjT5BCeqQ==
+ ) ; key id = 4254
+
+; sub.example.net. tag=56744 algo=RSAMD5 generated Jul 31 2008 00:25:53
+sub.example.net. 3600 IN DNSKEY 256 3 1 (
+ BQEAAAABxZS/DJA1BUdYVj5cOmMMnA5W/SHlkb4sEZkca3uIqV4gTzgv
+ guftN+M1ZgwyPwarn7DQR1Eb92uW3ALxwN2o6w==
+ ) ; key id = 56744
+
diff --git a/contrib/zkt/examples/flat/sub.example.net./dnssec.conf b/contrib/zkt/examples/flat/sub.example.net./dnssec.conf
new file mode 100644
index 0000000..4a045ad
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./dnssec.conf
@@ -0,0 +1,14 @@
+
+resigninterval 1d
+sigvalidity 2d
+max_ttl 90s
+
+Serialformat: unixtime
+ksk_algo RSASHA1
+ksk_bits 1024
+
+zsk_lifetime 3d
+zsk_algo RSAMD5
+zsk_bits 512
+
+dlv_domain "dlv.trusted-keys.de"
diff --git a/contrib/zkt/examples/flat/sub.example.net./zone.db b/contrib/zkt/examples/flat/sub.example.net./zone.db
new file mode 100644
index 0000000..c9ec01e
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./zone.db
@@ -0,0 +1,25 @@
+;-----------------------------------------------------------------
+;
+; @(#) sec.example.net/zone.db
+;
+;-----------------------------------------------------------------
+
+$TTL 7200
+
+@ IN SOA ns1.example.net. hostmaster.example.net. (
+ 0 ; Serial
+ 86400 ; Refresh (RIPE recommendation if NOTIFY is used)
+ 1800 ; Retry
+ 2W ; Expire
+ 7200 ) ; Minimum
+
+
+ IN NS ns1.example.net.
+
+$INCLUDE dnskey.db
+
+localhost IN A 127.0.0.1
+
+a IN A 1.2.3.4
+b IN A 1.2.3.5
+c IN A 1.2.3.6
diff --git a/contrib/zkt/examples/flat/sub.example.net./zone.db.signed b/contrib/zkt/examples/flat/sub.example.net./zone.db.signed
new file mode 100644
index 0000000..0560d2b
--- /dev/null
+++ b/contrib/zkt/examples/flat/sub.example.net./zone.db.signed
@@ -0,0 +1,103 @@
+; File written on Thu Jul 31 13:19:17 2008
+; dnssec_signzone version 9.5.1b1
+sub.example.net. 7200 IN SOA ns1.example.net. hostmaster.example.net. (
+ 1217503157 ; serial
+ 86400 ; refresh (1 day)
+ 1800 ; retry (30 minutes)
+ 1209600 ; expire (2 weeks)
+ 7200 ; minimum (2 hours)
+ )
+ 7200 RRSIG SOA 1 3 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ pAevIprv5lPMcSSR4l0cGzaYTY2pG3HsT6z9
+ RkSwssWSyyMxRqgYCuR2gErA1THGJNPlT8Qa
+ 9bvrMVOXpd0Q1g== )
+ 7200 NS ns1.example.net.
+ 7200 RRSIG NS 1 3 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ zB0f/bN5fvezT404pT+ArKVIW2QHKzTC2osb
+ k2sUpJiuhKtdJBx1kfBNmyaIuFaZsLtWacJn
+ 1S/A2bV4S3No7Q== )
+ 7200 NSEC a.sub.example.net. NS SOA RRSIG NSEC DNSKEY
+ 7200 RRSIG NSEC 1 3 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ ElgI6LCNWdDWM3OKh4vNDN9EiSns1bpnmOPK
+ TmAPb/tStfHfmNOuwBleW6irtDexizZcZFl8
+ feRHQBEYFpgvhA== )
+ 3600 DNSKEY 256 3 1 (
+ BQEAAAABxZS/DJA1BUdYVj5cOmMMnA5W/SHl
+ kb4sEZkca3uIqV4gTzgvguftN+M1ZgwyPwar
+ n7DQR1Eb92uW3ALxwN2o6w==
+ ) ; key id = 56744
+ 3600 DNSKEY 256 3 1 (
+ BQEAAAAB4Z/siqZTvCFKzaOrB8+HHTlR9is+
+ /+/Sem6gxhZt/vpWkNMyaSpAT8LjR7nNHr9v
+ NYsJ2KCQtY2dUFjT5BCeqQ==
+ ) ; key id = 4254
+ 3600 DNSKEY 257 3 5 (
+ AQOjGNN0/hLA20+W2qo0sktVActYKf1Opnx+
+ bmkWSrsmJHMBHlT8hL507pGTmDoyH0Ae9+3M
+ ZSTBL1S+HhA12B0htiTp8IbtN/gZOBbwD36c
+ BpPe72uDQoUy/TdSn1HLtoqUSMTB+saqCTZW
+ CfIEqcbHRn0T6PhgqLyCvLzbZ/avYw==
+ ) ; key id = 54876
+ 3600 RRSIG DNSKEY 1 3 3600 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ ASLViHuAWYqnzkZ4i6eywTuKvHyk93xsQBba
+ 4VjRCKc93KzvkWUA6SgOcwGvuRuAGCGb60VT
+ UW2clZMFj/Fy6g== )
+ 3600 RRSIG DNSKEY 5 3 3600 20080802101917 (
+ 20080731101917 54876 sub.example.net.
+ B2w2YAkeV2vx159FnG+B/H36Vnx8L1WwHt3E
+ 0YV1yYj2s5ZV6B6Gq34Ahm6y+zs7TsVxeYpO
+ OCoYCck/D+ehpuHOzZRR7xS2Rz/xLIvfASAK
+ 7NT/aIOlNPWH6I1J3ZAwhfAwF680KEFHPksv
+ oFMHe/OpIq7x/a4NdMn3yIWbFtg= )
+a.sub.example.net. 7200 IN A 1.2.3.4
+ 7200 RRSIG A 1 4 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ 1bTDrFSMIV8H8HTfEFQiG7dqYGr3a8UvK5fQ
+ owoh0VJuG4+DCUZU8edUSwnzMW8Yza4Ev0j+
+ M4ESPnoKxli7YQ== )
+ 7200 NSEC b.sub.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 1 4 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ nmJGbJWWaChlNmTTk5TgWEYRETeSJFiCoYHv
+ USKfEwLn13LfKk/lRZJarWIkDh7mxoismPOt
+ 2ODgeGLhUTap7A== )
+b.sub.example.net. 7200 IN A 1.2.3.5
+ 7200 RRSIG A 1 4 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ ojTCQ+aB8WClC7ncJsVGaN5RY6lczR7/Q0uz
+ bydmXQBjGUdF/GsuJvhR26mVbPzJNmF7uDNN
+ S0Et3ivWZSAVOg== )
+ 7200 NSEC c.sub.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 1 4 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ a6adIifDPjibbLme8dVzcKymxSARsIs2pz7B
+ jHXl0NCH9tmPBc/cBnjHxnSaes3QVDeok04k
+ +SzjVQtJfxUDsA== )
+c.sub.example.net. 7200 IN A 1.2.3.6
+ 7200 RRSIG A 1 4 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ ZeYTG7C6eEXhcHaBS4oIcwWGA5NayJs9aqhb
+ eWLRoZ75LxgIxhMQYU6A22PQf+zIWLADd0ID
+ z5HLpC+KbfpJxw== )
+ 7200 NSEC localhost.sub.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 1 4 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ IypmujoPBPhfEJqJdst5ZBazYfrr5l8nzrIh
+ a6xQYUDcw8aI96rVxn0pjeeiGBHuge2HbAAh
+ 4AnYjZlHjfe+MA== )
+localhost.sub.example.net. 7200 IN A 127.0.0.1
+ 7200 RRSIG A 1 4 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ o8kEv5q2Xus/jL8w8gB/M3VSvz7eTP67u38T
+ X+JO2yRn7W8gIxPo46yYfgr3qB7WXYD8jB8Y
+ vw4b+pdoWMi0+g== )
+ 7200 NSEC sub.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 1 4 7200 20080802101917 (
+ 20080731101917 4254 sub.example.net.
+ XbQQpoL8oV9kgpIKHyX2KoCmtMm2Wub1lVu9
+ PP0RM4QO5bpWls0ify3KgNiAg0g6qV86UQIr
+ SgFnqsd6YTxxpw== )
diff --git a/contrib/zkt/examples/flat/zkt.log b/contrib/zkt/examples/flat/zkt.log
new file mode 100644
index 0000000..9276f94
--- /dev/null
+++ b/contrib/zkt/examples/flat/zkt.log
@@ -0,0 +1,2501 @@
+2008-06-10 00:36:45.086: warning: zone "sub.example.net.": lifetime of key signing key 54876 exceeded
+2008-06-10 00:37:09.073: warning: zone "sub.example.net.": lifetime of key signing key 54876 exceeded
+2008-06-10 00:37:09.074: error: zone "example.net.": couldn't increment serialno in file ./example.net./zone.db: not enough space left for serialno
+2008-06-10 00:37:24.586: warning: zone "sub.example.net.": lifetime of key signing key 54876 exceeded
+2008-06-10 00:37:24.588: error: zone "example.net.": couldn't increment serialno in file ./example.net./zone.db: not enough space left for serialno
+2008-06-10 00:38:02.499: warning: zone "sub.example.net.": lifetime of key signing key 54876 exceeded
+2008-06-10 00:38:14.016: warning: zone "sub.example.net.": lifetime of key signing key 54876 exceeded
+2008-06-10 00:38:14.018: error: zone "example.net.": couldn't increment serialno in file ./example.net./zone.db: couldn't find serialnumber in zone file
+2008-06-10 00:38:40.235: warning: zone "sub.example.net.": lifetime of key signing key 54876 exceeded
+2008-06-10 00:38:40.236: error: zone "example.net.": couldn't increment serialno in file ./example.net./zone.db: unexpected end of file
+2008-06-10 00:38:49.975: warning: zone "sub.example.net.": lifetime of key signing key 54876 exceeded
+2008-06-11 13:47:16.909: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded ()
+2008-06-11 13:51:06.959: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded -16781202()
+2008-06-11 13:54:29.680: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded (27w5d5h30m5s)
+2008-06-11 13:56:36.990: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w5d5h32m12s
+2008-06-11 22:39:48.053: notice: running as ../../dnssec-signer -v -v
+2008-06-11 22:39:48.056: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w5d14h15m24s
+2008-06-11 22:39:48.056: notice: "sub.example.net.": lifetime of zone signing key 44833 exceeded since 2h30m54s: ZSK rollover done
+2008-06-11 22:39:48.143: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-06-11 22:39:48.617: notice: end of run: 0 errors occured
+2008-06-11 22:41:14.103: notice: running as ../../dnssec-signer -v -v
+2008-06-11 22:41:14.106: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w5d14h16m50s
+2008-06-11 22:41:14.106: notice: end of run: 0 errors occured
+2008-06-11 22:48:18.445: notice: running as ../../dnssec-signer -v -v
+2008-06-11 22:48:18.448: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w5d14h23m54s
+2008-06-11 22:48:18.448: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-06-11 22:48:19.087: notice: end of run: 0 errors occured
+2008-06-11 22:56:53.295: notice: running as ../../dnssec-signer -v -v
+2008-06-11 22:56:53.297: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w5d14h32m29s
+2008-06-11 22:56:53.297: notice: end of run: 0 errors occured
+2008-06-11 23:01:41.451: notice: running as ../../dnssec-signer -v -v
+2008-06-11 23:01:41.454: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w5d14h37m17s
+2008-06-11 23:01:41.454: notice: end of run: 0 errors occured
+2008-06-11 23:04:25.909: notice: running as ../../dnssec-signer -c dnssec.conf -v -v
+2008-06-11 23:04:25.911: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w5d14h40m1s
+2008-06-11 23:04:25.911: notice: end of run: 0 errors occured
+2008-06-12 13:06:54.007: notice: running as ../../dnssec-signer -v -v
+2008-06-12 13:06:54.055: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d4h42m30s
+2008-06-12 13:06:54.056: notice: end of run: 0 errors occured
+2008-06-12 13:07:45.126: notice: running as ../../dnssec-signer -v -v
+2008-06-12 13:07:45.129: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+
+2008-06-12 13:07:45.129: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d4h43m21s
+2008-06-12 13:07:45.130: debug: parsing zone "example.net." in dir "./example.net."
+
+2008-06-12 13:07:45.130: notice: end of run: 0 errors occured
+2008-06-12 13:22:02.251: notice: running as ../../dnssec-signer -v -v
+2008-06-12 13:22:02.253: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+
+2008-06-12 13:22:02.253: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d4h57m38s
+2008-06-12 13:22:02.253: debug: parsing zone "example.net." in dir "./example.net."
+
+2008-06-12 13:22:02.253: notice: end of run: 0 errors occured
+2008-06-12 13:24:37.956: notice: running as ../../dnssec-signer -v -v
+2008-06-12 13:24:37.958: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 13:24:37.958: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d5h13s
+2008-06-12 13:24:37.958: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 13:24:37.958: notice: end of run: 0 errors occured
+2008-06-12 13:25:32.993: notice: running as ../../dnssec-signer --config-option verboselog: 0; -v -v
+2008-06-12 13:25:32.997: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d5h1m8s
+2008-06-12 13:25:32.997: notice: end of run: 0 errors occured
+2008-06-12 13:26:49.861: notice: running as ../../dnssec-signer -O verboselog: 0; -v -v
+2008-06-12 13:26:49.864: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d5h2m25s
+2008-06-12 13:26:49.864: notice: end of run: 0 errors occured
+2008-06-12 16:28:01.977: notice: running as ../../dnssec-signer --config-option verboselog: 0; -v -v
+2008-06-12 16:28:01.979: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h3m37s
+2008-06-12 16:28:01.979: notice: end of run: 0 errors occured
+2008-06-12 16:28:13.626: notice: running as ../../dnssec-signer --config-option verboselog: 0; -v
+2008-06-12 16:28:13.629: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h3m49s
+2008-06-12 16:28:13.630: notice: end of run: 0 errors occured
+2008-06-12 16:28:30.318: notice: running as ../../dnssec-signer --config-option verboselog: 0; -v -v
+2008-06-12 16:28:30.320: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h4m6s
+2008-06-12 16:28:30.320: notice: end of run: 0 errors occured
+2008-06-12 16:34:06.968: notice: running as ../../dnssec-signer -v -v
+2008-06-12 16:34:06.971: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 16:34:06.971: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h9m42s
+2008-06-12 16:34:06.972: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 16:34:06.972: notice: end of run: 0 errors occured
+2008-06-12 16:34:15.816: notice: running as ../../dnssec-signer
+2008-06-12 16:34:15.818: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 16:34:15.818: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h9m51s
+2008-06-12 16:34:15.818: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 16:34:15.818: notice: end of run: 0 errors occured
+2008-06-12 16:35:27.777: notice: running as ../../dnssec-signer --config-option verboselog: 0; -v -v
+2008-06-12 16:35:27.780: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h11m3s
+2008-06-12 16:35:27.780: notice: end of run: 0 errors occured
+2008-06-12 16:44:56.266: notice: running as ../../dnssec-signer -v -v
+2008-06-12 16:44:56.269: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 16:44:56.269: debug: ->ksk5011status returns 0
+2008-06-12 16:44:56.269: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h20m32s
+2008-06-12 16:44:56.269: debug: Re-signing not necessary!
+2008-06-12 16:44:56.269: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 16:44:56.269: debug: ->ksk5011status returns 2
+2008-06-12 16:44:56.269: debug: Re-signing not necessary!
+2008-06-12 16:44:56.270: notice: end of run: 0 errors occured
+2008-06-12 16:49:23.380: notice: running as ../../dnssec-signer -v -v
+2008-06-12 16:49:23.385: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 16:49:23.385: debug: ->ksk5011status returns 0
+2008-06-12 16:49:23.386: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h24m59s
+2008-06-12 16:49:23.386: debug: Re-signing not necessary!
+2008-06-12 16:49:23.386: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 16:49:23.386: debug: ->ksk5011status returns 2
+2008-06-12 16:49:23.386: debug: Re-signing not necessary!
+2008-06-12 16:49:23.386: notice: end of run: 0 errors occured
+2008-06-12 16:49:28.284: notice: running as ../../dnssec-signer -r -v -v
+2008-06-12 16:49:28.288: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 16:49:28.288: debug: ->ksk5011status returns 0
+2008-06-12 16:49:28.288: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h25m4s
+2008-06-12 16:49:28.288: debug: Re-signing not necessary!
+2008-06-12 16:49:28.288: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 16:49:28.288: debug: ->ksk5011status returns 2
+2008-06-12 16:49:28.288: debug: Re-signing not necessary!
+2008-06-12 16:49:28.288: notice: end of run: 0 errors occured
+2008-06-12 16:49:32.079: notice: running as ../../dnssec-signer -f -v -v
+2008-06-12 16:49:32.081: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 16:49:32.081: debug: ->ksk5011status returns 0
+2008-06-12 16:49:32.081: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h25m8s
+2008-06-12 16:49:32.082: debug: Re-signing necessary: Option -f
+2008-06-12 16:49:32.082: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-06-12 16:49:32.082: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-06-12 16:49:32.082: debug: Signing zone "sub.example.net."
+2008-06-12 16:49:32.082: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o sub.example.net. -e +172800 -g -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-06-12 16:49:32.222: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 16:49:32.222: debug: Signing completed after 0s.
+2008-06-12 16:49:32.222: debug:
+2008-06-12 16:49:32.222: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 16:49:32.222: debug: ->ksk5011status returns 2
+2008-06-12 16:49:32.223: debug: Re-signing necessary: Option -f
+2008-06-12 16:49:32.223: notice: "example.net.": re-signing triggered: Option -f
+2008-06-12 16:49:32.223: debug: Writing key file "./example.net./dnskey.db"
+2008-06-12 16:49:32.223: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-06-12 16:49:32.223: debug: Signing zone "example.net."
+2008-06-12 16:49:32.223: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o example.net. -e +518400 -g zone.db K*.private"
+2008-06-12 16:49:32.335: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 16:49:32.335: debug: Signing completed after 0s.
+2008-06-12 16:49:32.335: debug:
+2008-06-12 16:49:32.335: notice: end of run: 0 errors occured
+2008-06-12 17:02:15.076: notice: running as ../../dnssec-signer -f -v -v
+2008-06-12 17:02:15.078: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 17:02:15.078: debug: Check RFC5011 status
+2008-06-12 17:02:15.078: debug: ->ksk5011status returns 0
+2008-06-12 17:02:15.078: debug: Check ksk status
+2008-06-12 17:02:15.078: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d8h37m51s
+2008-06-12 17:02:15.078: debug: Re-signing necessary: Option -f
+2008-06-12 17:02:15.078: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-06-12 17:02:15.078: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-06-12 17:02:15.079: debug: Signing zone "sub.example.net."
+2008-06-12 17:02:15.079: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o sub.example.net. -e +172800 -g -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-06-12 17:02:15.254: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 17:02:15.254: debug: Signing completed after 0s.
+2008-06-12 17:02:15.254: debug:
+2008-06-12 17:02:15.254: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 17:02:15.255: debug: Check RFC5011 status
+2008-06-12 17:02:15.255: debug: ->ksk5011status returns 2
+2008-06-12 17:02:15.255: debug: Re-signing necessary: Option -f
+2008-06-12 17:02:15.255: notice: "example.net.": re-signing triggered: Option -f
+2008-06-12 17:02:15.255: debug: Writing key file "./example.net./dnskey.db"
+2008-06-12 17:02:15.255: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-06-12 17:02:15.255: debug: Signing zone "example.net."
+2008-06-12 17:02:15.255: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o example.net. -e +518400 -g zone.db K*.private"
+2008-06-12 17:02:15.368: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 17:02:15.368: debug: Signing completed after 0s.
+2008-06-12 17:02:15.368: debug:
+2008-06-12 17:02:15.368: notice: end of run: 0 errors occured
+2008-06-12 17:43:50.388: notice: running as ../../dnssec-signer -f -f
+2008-06-12 17:43:50.390: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 17:43:50.390: debug: Check RFC5011 status
+2008-06-12 17:43:50.390: debug: ->ksk5011status returns 0
+2008-06-12 17:43:50.390: debug: Check ksk status
+2008-06-12 17:43:50.390: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d9h19m26s
+2008-06-12 17:43:50.390: debug: Re-signing necessary: Option -f
+2008-06-12 17:43:50.390: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-06-12 17:43:50.390: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-06-12 17:43:50.390: debug: Signing zone "sub.example.net."
+2008-06-12 17:43:50.390: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o sub.example.net. -e +172800 -g -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-06-12 17:43:50.533: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 17:43:50.533: debug: Signing completed after 0s.
+2008-06-12 17:43:50.533: debug:
+2008-06-12 17:43:50.533: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 17:43:50.533: debug: Check RFC5011 status
+2008-06-12 17:43:50.533: debug: ->ksk5011status returns 2
+2008-06-12 17:43:50.533: debug: Re-signing necessary: Option -f
+2008-06-12 17:43:50.533: notice: "example.net.": re-signing triggered: Option -f
+2008-06-12 17:43:50.533: debug: Writing key file "./example.net./dnskey.db"
+2008-06-12 17:43:50.534: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-06-12 17:43:50.534: debug: Signing zone "example.net."
+2008-06-12 17:43:50.534: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o example.net. -e +518400 -g zone.db K*.private"
+2008-06-12 17:43:50.645: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 17:43:50.645: debug: Signing completed after 0s.
+2008-06-12 17:43:50.645: debug:
+2008-06-12 17:43:50.645: notice: end of run: 0 errors occured
+2008-06-12 17:49:43.188: notice: running as ../../dnssec-signer -O verboselog: 2 -v -v
+2008-06-12 17:49:43.190: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 17:49:43.190: debug: Check RFC5011 status
+2008-06-12 17:49:43.190: debug: ->ksk5011status returns 0
+2008-06-12 17:49:43.190: debug: Check ksk status
+2008-06-12 17:49:43.190: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d9h25m19s
+2008-06-12 17:49:43.190: debug: Re-signing not necessary!
+2008-06-12 17:49:43.190: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 17:49:43.190: debug: Check RFC5011 status
+2008-06-12 17:49:43.190: debug: ->ksk5011status returns 2
+2008-06-12 17:49:43.190: debug: Re-signing not necessary!
+2008-06-12 17:49:43.190: notice: end of run: 0 errors occured
+2008-06-12 17:50:09.325: notice: running as ../../dnssec-signer -v -v
+2008-06-12 17:50:09.327: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 17:50:09.327: debug: Check RFC5011 status
+2008-06-12 17:50:09.327: debug: ->ksk5011status returns 0
+2008-06-12 17:50:09.327: debug: Check ksk status
+2008-06-12 17:50:09.327: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d9h25m45s
+2008-06-12 17:50:09.327: debug: Re-signing not necessary!
+2008-06-12 17:50:09.327: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 17:50:09.327: debug: Check RFC5011 status
+2008-06-12 17:50:09.327: debug: ->ksk5011status returns 2
+2008-06-12 17:50:09.327: debug: Re-signing not necessary!
+2008-06-12 17:50:09.327: notice: end of run: 0 errors occured
+2008-06-12 17:52:29.309: notice: running as ../../dnssec-signer -v -v
+2008-06-12 17:52:29.311: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 17:52:29.312: debug: Check RFC5011 status
+2008-06-12 17:52:29.312: debug: ->ksk5011status returns 0
+2008-06-12 17:52:29.312: debug: Check ksk status
+2008-06-12 17:52:29.312: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d9h28m5s
+2008-06-12 17:52:29.312: debug: Re-signing not necessary!
+2008-06-12 17:52:29.312: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 17:52:29.313: debug: Check RFC5011 status
+2008-06-12 17:52:29.313: debug: ->ksk5011status returns 2
+2008-06-12 17:52:29.313: debug: Re-signing not necessary!
+2008-06-12 17:52:29.313: notice: end of run: 0 errors occured
+2008-06-12 18:24:57.405: notice: running as ../../dnssec-signer -v -v
+2008-06-12 18:24:57.409: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-12 18:24:57.409: debug: Check RFC5011 status
+2008-06-12 18:24:57.409: debug: ->ksk5011status returns 0
+2008-06-12 18:24:57.409: debug: Check ksk status
+2008-06-12 18:24:57.409: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 27w6d10h33s
+2008-06-12 18:24:57.409: debug: Re-signing not necessary!
+2008-06-12 18:24:57.409: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-12 18:24:57.409: debug: Check RFC5011 status
+2008-06-12 18:24:57.409: debug: ->ksk5011status returns 2
+2008-06-12 18:24:57.410: debug: Re-signing not necessary!
+2008-06-12 18:24:57.410: notice: end of run: 0 errors occured
+2008-06-16 23:12:32.309: notice:
+2008-06-16 23:12:32.309: notice: running as ../../dnssec-signer -v -v
+2008-06-16 23:12:32.654: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-16 23:12:32.654: debug: Check RFC5011 status
+2008-06-16 23:12:32.654: debug: ->ksk5011status returns 0
+2008-06-16 23:12:32.654: debug: Check ksk status
+2008-06-16 23:12:32.654: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 28w3d14h48m8s
+2008-06-16 23:12:32.654: debug: Lifetime(259200 +/-150 sec) of active key 44833 exceeded (433964 sec)
+2008-06-16 23:12:32.654: debug: ->depreciate it
+2008-06-16 23:12:32.654: debug: ->activate pre-publish key 55267
+2008-06-16 23:12:32.654: notice: "sub.example.net.": lifetime of zone signing key 55267 exceeded since 2d32m44s: ZSK rollover done
+2008-06-16 23:12:32.654: debug: New pre-publish key needed
+2008-06-16 23:12:32.790: debug: ->creating new pre-publish key 56149
+2008-06-16 23:12:32.791: debug: Re-signing necessary: New zone key
+2008-06-16 23:12:32.791: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-06-16 23:12:32.791: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-06-16 23:12:32.792: debug: Signing zone "sub.example.net."
+2008-06-16 23:12:32.792: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o sub.example.net. -e +172800 -g -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-06-16 23:12:33.022: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-16 23:12:33.022: debug: Signing completed after 1s.
+2008-06-16 23:12:33.022: debug:
+2008-06-16 23:12:33.023: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-16 23:12:33.023: debug: Check RFC5011 status
+2008-06-16 23:12:33.023: debug: ->ksk5011status returns 2
+2008-06-16 23:12:33.023: debug: Re-signing necessary: re-signing interval (2d) reached
+2008-06-16 23:12:33.023: notice: "example.net.": re-signing triggered: re-signing interval (2d) reached
+2008-06-16 23:12:33.023: debug: Writing key file "./example.net./dnskey.db"
+2008-06-16 23:12:33.024: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-06-16 23:12:33.024: debug: Signing zone "example.net."
+2008-06-16 23:12:33.024: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o example.net. -e +518400 -g zone.db K*.private"
+2008-06-16 23:12:33.169: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-16 23:12:33.170: debug: Signing completed after 0s.
+2008-06-16 23:12:33.170: debug:
+2008-06-16 23:12:33.170: notice: end of run: 0 errors occured
+2008-06-16 23:13:24.119: notice: ===> running as ../../dnssec-signer -v -v <===
+2008-06-16 23:13:24.121: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-16 23:13:24.121: debug: Check RFC5011 status
+2008-06-16 23:13:24.121: debug: ->ksk5011status returns 0
+2008-06-16 23:13:24.121: debug: Check ksk status
+2008-06-16 23:13:24.121: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 28w3d14h49m
+2008-06-16 23:13:24.121: debug: Re-signing not necessary!
+2008-06-16 23:13:24.121: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-16 23:13:24.121: debug: Check RFC5011 status
+2008-06-16 23:13:24.121: debug: ->ksk5011status returns 2
+2008-06-16 23:13:24.121: debug: Re-signing not necessary!
+2008-06-16 23:13:24.121: notice: end of run: 0 errors occured
+2008-06-16 23:13:56.970: notice: =====> running as ../../dnssec-signer -v -v <=====
+2008-06-16 23:13:56.972: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-16 23:13:56.972: debug: Check RFC5011 status
+2008-06-16 23:13:56.972: debug: ->ksk5011status returns 0
+2008-06-16 23:13:56.972: debug: Check ksk status
+2008-06-16 23:13:56.973: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 28w3d14h49m32s
+2008-06-16 23:13:56.973: debug: Re-signing not necessary!
+2008-06-16 23:13:56.973: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-16 23:13:56.973: debug: Check RFC5011 status
+2008-06-16 23:13:56.973: debug: ->ksk5011status returns 2
+2008-06-16 23:13:56.973: debug: Re-signing not necessary!
+2008-06-16 23:13:56.973: notice: end of run: 0 errors occured
+2008-06-16 23:15:16.980: notice: ------------------------------------------------------------
+2008-06-16 23:15:16.982: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-16 23:15:16.982: debug: Check RFC5011 status
+2008-06-16 23:15:16.982: debug: ->ksk5011status returns 0
+2008-06-16 23:15:16.982: debug: Check ksk status
+2008-06-16 23:15:16.982: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 28w3d14h50m52s
+2008-06-16 23:15:16.982: debug: Re-signing not necessary!
+2008-06-16 23:15:16.982: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-16 23:15:16.982: debug: Check RFC5011 status
+2008-06-16 23:15:16.982: debug: ->ksk5011status returns 2
+2008-06-16 23:15:16.982: debug: Re-signing not necessary!
+2008-06-16 23:15:16.983: notice: end of run: 0 errors occured
+2008-06-16 23:18:48.101: notice: ------------------------------------------------------------
+2008-06-16 23:18:48.101: notice: running as ../../dnssec-signer -v -v
+2008-06-16 23:18:48.103: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-16 23:18:48.103: debug: Check RFC5011 status
+2008-06-16 23:18:48.103: debug: ->ksk5011status returns 0
+2008-06-16 23:18:48.103: debug: Check ksk status
+2008-06-16 23:18:48.103: warning: "sub.example.net.": lifetime of key signing key 54876 exceeded since 28w3d14h54m24s
+2008-06-16 23:18:48.103: debug: Re-signing not necessary!
+2008-06-16 23:18:48.103: debug:
+2008-06-16 23:18:48.103: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-16 23:18:48.104: debug: Check RFC5011 status
+2008-06-16 23:18:48.104: debug: ->ksk5011status returns 2
+2008-06-16 23:18:48.104: debug: Re-signing not necessary!
+2008-06-16 23:18:48.104: debug:
+2008-06-16 23:18:48.104: notice: end of run: 0 errors occured
+2008-06-24 14:55:16.347: notice: ------------------------------------------------------------
+2008-06-24 14:55:16.347: notice: running ../../dnssec-signer -v -v
+2008-06-24 14:55:16.349: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-24 14:55:16.349: debug: Check RFC5011 status
+2008-06-24 14:55:16.349: debug: ->ksk5011status returns 0
+2008-06-24 14:55:16.349: debug: Check ksk status
+2008-06-24 14:55:16.349: debug: Lifetime(390 sec) of depreciated key 44833 exceeded (483774 sec)
+2008-06-24 14:55:16.350: debug: ->remove it
+2008-06-24 14:55:16.350: debug: Lifetime(259200 +/-150 sec) of active key 55267 exceeded (483774 sec)
+2008-06-24 14:55:16.350: debug: ->depreciate it
+2008-06-24 14:55:16.350: debug: ->activate pre-publish key 56149
+2008-06-24 14:55:16.350: notice: "sub.example.net.": lifetime of zone signing key 55267 exceeded: ZSK rollover done
+2008-06-24 14:55:16.350: notice: "sub.example.net.": lifetime of zone signing key 56149 exceeded since 2d14h22m54s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-24 14:55:16.350: debug: New pre-publish key needed
+2008-06-24 14:55:16.532: debug: ->creating new pre-publish key 2338
+2008-06-24 14:55:16.532: debug: Re-signing necessary: New zone key
+2008-06-24 14:55:16.533: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-06-24 14:55:16.533: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-06-24 14:55:16.533: debug: Signing zone "sub.example.net."
+2008-06-24 14:55:16.533: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o sub.example.net. -e +172800 -g -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-06-24 14:55:16.776: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-24 14:55:16.776: debug: Signing completed after 0s.
+2008-06-24 14:55:16.776: debug:
+2008-06-24 14:55:16.776: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-24 14:55:16.776: debug: Check RFC5011 status
+2008-06-24 14:55:16.776: debug: ->ksk5011status returns 2
+2008-06-24 14:55:16.776: debug: Re-signing necessary: re-signing interval (2d) reached
+2008-06-24 14:55:16.776: notice: "example.net.": re-signing triggered: re-signing interval (2d) reached
+2008-06-24 14:55:16.776: debug: Writing key file "./example.net./dnskey.db"
+2008-06-24 14:55:16.777: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-06-24 14:55:16.777: debug: Signing zone "example.net."
+2008-06-24 14:55:16.777: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o example.net. -e +518400 -g zone.db K*.private"
+2008-06-24 14:55:16.922: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-24 14:55:16.922: debug: Signing completed after 0s.
+2008-06-24 14:55:16.922: debug:
+2008-06-24 14:55:16.922: notice: end of run: 0 errors occured
+2008-06-24 14:57:56.093: notice: ------------------------------------------------------------
+2008-06-24 14:57:56.094: notice: running ../../dnssec-signer -v -v
+2008-06-24 14:57:56.096: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-24 14:57:56.096: debug: Check RFC5011 status
+2008-06-24 14:57:56.096: debug: ->ksk5011status returns 0
+2008-06-24 14:57:56.096: debug: Check ksk status
+2008-06-24 14:57:56.097: debug: Re-signing not necessary!
+2008-06-24 14:57:56.097: debug:
+2008-06-24 14:57:56.097: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-24 14:57:56.097: debug: Check RFC5011 status
+2008-06-24 14:57:56.097: debug: ->ksk5011status returns 2
+2008-06-24 14:57:56.097: debug: Re-signing not necessary!
+2008-06-24 14:57:56.097: debug:
+2008-06-24 14:57:56.098: notice: end of run: 0 errors occured
+2008-06-24 23:26:12.632: notice: ------------------------------------------------------------
+2008-06-24 23:26:12.632: notice: running ../../dnssec-signer -v -v
+2008-06-24 23:26:12.648: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-06-24 23:26:12.648: debug: Check RFC5011 status
+2008-06-24 23:26:12.648: debug: ->ksk5011status returns 0
+2008-06-24 23:26:12.648: debug: Check ksk status
+2008-06-24 23:26:12.648: debug: Lifetime(390 sec) of depreciated key 55267 exceeded (30656 sec)
+2008-06-24 23:26:12.648: debug: ->remove it
+2008-06-24 23:26:12.648: debug: Re-signing necessary: New zone key
+2008-06-24 23:26:12.649: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-06-24 23:26:12.649: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-06-24 23:26:12.655: debug: Signing zone "sub.example.net."
+2008-06-24 23:26:12.655: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -p -d ../keysets -o sub.example.net. -e +172800 -g -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-06-24 23:26:13.030: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-24 23:26:13.030: debug: Signing completed after 1s.
+2008-06-24 23:26:13.030: debug:
+2008-06-24 23:26:13.030: debug: parsing zone "example.net." in dir "./example.net."
+2008-06-24 23:26:13.030: debug: Check RFC5011 status
+2008-06-24 23:26:13.030: debug: ->ksk5011status returns 2
+2008-06-24 23:26:13.030: debug: Re-signing not necessary!
+2008-06-24 23:26:13.030: debug:
+2008-06-24 23:26:13.030: notice: end of run: 0 errors occured
+2008-07-08 00:53:55.013: notice: ------------------------------------------------------------
+2008-07-08 00:53:55.013: notice: running ../../dnssec-signer -v -v
+2008-07-08 00:53:55.015: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-08 00:53:55.015: debug: Check RFC5011 status
+2008-07-08 00:53:55.015: debug: ->ksk5011status returns 0
+2008-07-08 00:53:55.015: debug: Check KSK status
+2008-07-08 00:53:55.015: debug: Check ZSK status
+2008-07-08 00:53:55.015: debug: Lifetime(259200 +/-150 sec) of active key 56149 exceeded (1159119 sec)
+2008-07-08 00:53:55.015: debug: ->depreciate it
+2008-07-08 00:53:55.015: debug: ->activate pre-publish key 2338
+2008-07-08 00:53:55.018: notice: "sub.example.net.": lifetime of zone signing key 56149 exceeded: ZSK rollover done
+2008-07-08 00:53:55.018: debug: New pre-publish key needed
+2008-07-08 00:53:55.547: debug: ->creating new pre-publish key 9198
+2008-07-08 00:53:55.547: info: "sub.example.net.": new pre-publish key 9198 created
+2008-07-08 00:53:55.547: debug: Re-signing necessary: New zone key
+2008-07-08 00:53:55.548: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-07-08 00:53:55.548: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-08 00:53:55.578: debug: Signing zone "sub.example.net."
+2008-07-08 00:53:55.578: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-08 00:53:55.708: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-08 00:53:55.708: debug: Signing completed after 0s.
+2008-07-08 00:53:55.708: debug:
+2008-07-08 00:53:55.708: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-08 00:53:55.708: debug: Check RFC5011 status
+2008-07-08 00:53:55.708: debug: ->ksk5011status returns 2
+2008-07-08 00:53:55.708: debug: Check ZSK status
+2008-07-08 00:53:55.708: debug: Lifetime(1209600 +/-150 sec) of active key 14939 exceeded (1642893 sec)
+2008-07-08 00:53:55.708: debug: ->waiting for pre-publish key
+2008-07-08 00:53:55.708: notice: "example.net.": lifetime of zone signing key 14939 exceeded since 5d21m33s: ZSK rollover deferred: waiting for pre-publish key
+2008-07-08 00:53:55.708: debug: New pre-publish key needed
+2008-07-08 00:53:55.747: debug: ->creating new pre-publish key 16682
+2008-07-08 00:53:55.747: info: "example.net.": new pre-publish key 16682 created
+2008-07-08 00:53:55.747: debug: Re-signing necessary: New zone key
+2008-07-08 00:53:55.747: notice: "example.net.": re-signing triggered: New zone key
+2008-07-08 00:53:55.747: debug: Writing key file "./example.net./dnskey.db"
+2008-07-08 00:53:55.748: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-08 00:53:55.748: debug: Signing zone "example.net."
+2008-07-08 00:53:55.748: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-08 00:53:55.899: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-08 00:53:55.899: debug: Signing completed after 0s.
+2008-07-08 00:53:55.899: debug:
+2008-07-08 00:53:55.899: notice: end of run: 0 errors occured
+2008-07-08 00:53:57.597: notice: ------------------------------------------------------------
+2008-07-08 00:53:57.597: notice: running ../../dnssec-signer -v -v
+2008-07-08 00:53:57.599: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-08 00:53:57.599: debug: Check RFC5011 status
+2008-07-08 00:53:57.599: debug: ->ksk5011status returns 0
+2008-07-08 00:53:57.599: debug: Check KSK status
+2008-07-08 00:53:57.599: debug: Check ZSK status
+2008-07-08 00:53:57.599: debug: Re-signing not necessary!
+2008-07-08 00:53:57.599: debug: Check if there is a parent file to copy
+2008-07-08 00:53:57.599: debug:
+2008-07-08 00:53:57.599: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-08 00:53:57.599: debug: Check RFC5011 status
+2008-07-08 00:53:57.599: debug: ->ksk5011status returns 2
+2008-07-08 00:53:57.599: debug: Check ZSK status
+2008-07-08 00:53:57.599: debug: Lifetime(1209600 +/-150 sec) of active key 14939 exceeded (1642895 sec)
+2008-07-08 00:53:57.599: debug: ->waiting for pre-publish key
+2008-07-08 00:53:57.600: notice: "example.net.": lifetime of zone signing key 14939 exceeded since 5d21m35s: ZSK rollover deferred: waiting for pre-publish key
+2008-07-08 00:53:57.600: debug: Re-signing not necessary!
+2008-07-08 00:53:57.600: debug: Check if there is a parent file to copy
+2008-07-08 00:53:57.600: debug:
+2008-07-08 00:53:57.600: notice: end of run: 0 errors occured
+2008-07-08 20:28:20.476: notice: ------------------------------------------------------------
+2008-07-08 20:28:20.476: notice: running ../../dnssec-signer -v -v -N named.conf
+2008-07-08 20:28:20.476: debug: parsing zone "sub.example.net." in dir "././sub.example.net."
+2008-07-08 20:28:20.476: debug: Check RFC5011 status
+2008-07-08 20:28:20.476: debug: ->ksk5011status returns 0
+2008-07-08 20:28:20.476: debug: Check KSK status
+2008-07-08 20:28:20.476: debug: Check ZSK status
+2008-07-08 20:28:20.476: debug: Lifetime(390 sec) of depreciated key 56149 exceeded (70465 sec)
+2008-07-08 20:28:20.476: info: "sub.example.net.": removed old ZSK 56149
+
+2008-07-08 20:28:20.656: debug: ->remove it
+2008-07-08 20:28:20.656: debug: Re-signing necessary: New zone key
+2008-07-08 20:28:20.656: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-07-08 20:28:20.656: debug: Writing key file "././sub.example.net./dnskey.db"
+2008-07-08 20:28:20.656: debug: Signing zone "sub.example.net."
+2008-07-08 20:28:20.656: debug: Run cmd "cd ././sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-08 20:28:20.990: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-08 20:28:20.990: debug: Signing completed after 0s.
+2008-07-08 20:28:20.990: debug:
+2008-07-08 20:28:20.990: debug: parsing zone "example.net." in dir "././example.net."
+2008-07-08 20:28:20.990: debug: Check RFC5011 status
+2008-07-08 20:28:20.990: debug: ->ksk5011status returns 2
+2008-07-08 20:28:20.990: debug: Check ZSK status
+2008-07-08 20:28:20.990: debug: Lifetime(1209600 +/-150 sec) of active key 14939 exceeded (1713358 sec)
+2008-07-08 20:28:20.990: debug: ->depreciate it
+2008-07-08 20:28:20.990: debug: ->activate pre-publish key 16682
+2008-07-08 20:28:20.990: notice: "example.net.": lifetime of zone signing key 14939 exceeded: ZSK rollover done
+2008-07-08 20:28:20.990: debug: Re-signing necessary: New zone key
+2008-07-08 20:28:20.990: notice: "example.net.": re-signing triggered: New zone key
+2008-07-08 20:28:20.990: debug: Writing key file "././example.net./dnskey.db"
+2008-07-08 20:28:20.991: debug: Incrementing serial number in file "././example.net./zone.db"
+2008-07-08 20:28:20.991: debug: Signing zone "example.net."
+2008-07-08 20:28:20.991: debug: Run cmd "cd ././example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-08 20:28:21.112: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-08 20:28:21.112: debug: Signing completed after 1s.
+2008-07-08 20:28:21.112: debug:
+2008-07-08 20:28:21.113: notice: end of run: 0 errors occured
+2008-07-08 20:32:23.121: notice: ------------------------------------------------------------
+2008-07-08 20:32:23.121: notice: running ../../dnssec-signer -v -v
+2008-07-08 20:32:23.123: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-08 20:32:23.123: debug: Check RFC5011 status
+2008-07-08 20:32:23.124: debug: ->ksk5011status returns 0
+2008-07-08 20:32:23.124: debug: Check KSK status
+2008-07-08 20:32:23.124: debug: Check ZSK status
+2008-07-08 20:32:23.124: debug: Re-signing not necessary!
+2008-07-08 20:32:23.124: debug: Check if there is a parent file to copy
+2008-07-08 20:32:23.124: debug:
+2008-07-08 20:32:23.124: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-08 20:32:23.124: debug: Check RFC5011 status
+2008-07-08 20:32:23.124: debug: ->ksk5011status returns 2
+2008-07-08 20:32:23.124: debug: Check ZSK status
+2008-07-08 20:32:23.124: debug: Re-signing not necessary!
+2008-07-08 20:32:23.124: debug: Check if there is a parent file to copy
+2008-07-08 20:32:23.124: debug:
+2008-07-08 20:32:23.124: notice: end of run: 0 errors occured
+2008-07-08 20:32:30.246: notice: ------------------------------------------------------------
+2008-07-08 20:32:30.246: notice: running ../../dnssec-signer -v -v -N named.conf
+2008-07-08 20:32:30.246: debug: parsing zone "sub.example.net." in dir "././sub.example.net."
+2008-07-08 20:32:30.246: debug: Check RFC5011 status
+2008-07-08 20:32:30.246: debug: ->ksk5011status returns 0
+2008-07-08 20:32:30.246: debug: Check KSK status
+2008-07-08 20:32:30.246: debug: Check ZSK status
+2008-07-08 20:32:30.246: debug: Re-signing not necessary!
+2008-07-08 20:32:30.246: debug: Check if there is a parent file to copy
+2008-07-08 20:32:30.246: debug:
+2008-07-08 20:32:30.246: debug: parsing zone "example.net." in dir "././example.net."
+2008-07-08 20:32:30.246: debug: Check RFC5011 status
+2008-07-08 20:32:30.246: debug: ->ksk5011status returns 2
+2008-07-08 20:32:30.247: debug: Check ZSK status
+2008-07-08 20:32:30.247: debug: Re-signing not necessary!
+2008-07-08 20:32:30.247: debug: Check if there is a parent file to copy
+2008-07-08 20:32:30.247: debug:
+2008-07-08 20:32:30.247: notice: end of run: 0 errors occured
+2008-07-08 20:35:51.512: notice: ------------------------------------------------------------
+2008-07-08 20:35:51.512: notice: running ../../dnssec-signer -v -v -N named.conf
+2008-07-08 20:35:51.512: debug: parsing zone "sub.example.net." in dir "././sub.example.net."
+2008-07-08 20:35:51.512: debug: Check RFC5011 status
+2008-07-08 20:35:51.512: debug: ->ksk5011status returns 0
+2008-07-08 20:35:51.513: debug: Check KSK status
+2008-07-08 20:35:51.513: debug: Check ZSK status
+2008-07-08 20:35:51.513: debug: Re-signing not necessary!
+2008-07-08 20:35:51.513: debug: Check if there is a parent file to copy
+2008-07-08 20:35:51.513: debug:
+2008-07-08 20:35:51.513: debug: parsing zone "example.net." in dir "././example.net."
+2008-07-08 20:35:51.513: debug: Check RFC5011 status
+2008-07-08 20:35:51.513: debug: ->ksk5011status returns 2
+2008-07-08 20:35:51.513: debug: Check ZSK status
+2008-07-08 20:35:51.513: debug: Re-signing not necessary!
+2008-07-08 20:35:51.513: debug: Check if there is a parent file to copy
+2008-07-08 20:35:51.513: debug:
+2008-07-08 20:35:51.513: notice: end of run: 0 errors occured
+2008-07-08 20:37:16.569: notice: ------------------------------------------------------------
+2008-07-08 20:37:16.569: notice: running ../../dnssec-signer -v -v -N named.conf
+2008-07-08 20:37:16.569: debug: parsing zone "sub.example.net." in dir "././sub.example.net."
+2008-07-08 20:37:16.569: debug: Check RFC5011 status
+2008-07-08 20:37:16.569: debug: ->ksk5011status returns 0
+2008-07-08 20:37:16.570: debug: Check KSK status
+2008-07-08 20:37:16.570: debug: Check ZSK status
+2008-07-08 20:37:16.570: debug: Re-signing not necessary!
+2008-07-08 20:37:16.570: debug: Check if there is a parent file to copy
+2008-07-08 20:37:16.570: debug:
+2008-07-08 20:37:16.570: debug: parsing zone "example.net." in dir "././example.net."
+2008-07-08 20:37:16.570: debug: Check RFC5011 status
+2008-07-08 20:37:16.570: debug: ->ksk5011status returns 2
+2008-07-08 20:37:16.570: debug: Check ZSK status
+2008-07-08 20:37:16.570: debug: Re-signing not necessary!
+2008-07-08 20:37:16.570: debug: Check if there is a parent file to copy
+2008-07-08 20:37:16.570: debug:
+2008-07-08 20:37:16.570: notice: end of run: 0 errors occured
+2008-07-08 20:37:29.134: notice: ------------------------------------------------------------
+2008-07-08 20:37:29.134: notice: running ../../dnssec-signer -v -v
+2008-07-08 20:37:29.137: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-08 20:37:29.137: debug: Check RFC5011 status
+2008-07-08 20:37:29.137: debug: ->ksk5011status returns 0
+2008-07-08 20:37:29.137: debug: Check KSK status
+2008-07-08 20:37:29.137: debug: Check ZSK status
+2008-07-08 20:37:29.137: debug: Re-signing not necessary!
+2008-07-08 20:37:29.138: debug: Check if there is a parent file to copy
+2008-07-08 20:37:29.138: debug:
+2008-07-08 20:37:29.138: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-08 20:37:29.138: debug: Check RFC5011 status
+2008-07-08 20:37:29.138: debug: ->ksk5011status returns 2
+2008-07-08 20:37:29.138: debug: Check ZSK status
+2008-07-08 20:37:29.138: debug: Re-signing not necessary!
+2008-07-08 20:37:29.139: debug: Check if there is a parent file to copy
+2008-07-08 20:37:29.139: debug:
+2008-07-08 20:37:29.139: notice: end of run: 0 errors occured
+2008-07-08 20:39:39.895: notice: ------------------------------------------------------------
+2008-07-08 20:39:39.895: notice: running ../../dnssec-signer -N named.conf -v -v
+2008-07-08 20:39:39.895: debug: parsing zone "sub.example.net." in dir "././sub.example.net."
+2008-07-08 20:39:39.895: debug: Check RFC5011 status
+2008-07-08 20:39:39.895: debug: ->ksk5011status returns 0
+2008-07-08 20:39:39.895: debug: Check KSK status
+2008-07-08 20:39:39.895: debug: Check ZSK status
+2008-07-08 20:39:39.895: debug: Re-signing not necessary!
+2008-07-08 20:39:39.895: debug: Check if there is a parent file to copy
+2008-07-08 20:39:39.895: debug:
+2008-07-08 20:39:39.895: debug: parsing zone "example.net." in dir "././example.net."
+2008-07-08 20:39:39.895: debug: Check RFC5011 status
+2008-07-08 20:39:39.895: debug: ->ksk5011status returns 2
+2008-07-08 20:39:39.895: debug: Check ZSK status
+2008-07-08 20:39:39.895: debug: Re-signing not necessary!
+2008-07-08 20:39:39.895: debug: Check if there is a parent file to copy
+2008-07-08 20:39:39.895: debug:
+2008-07-08 20:39:39.895: notice: end of run: 0 errors occured
+2008-07-08 20:42:54.377: notice: ------------------------------------------------------------
+2008-07-08 20:42:54.377: notice: running ../../dnssec-signer -v -v -D .
+2008-07-08 20:42:54.377: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-08 20:42:54.377: debug: Check RFC5011 status
+2008-07-08 20:42:54.377: debug: ->ksk5011status returns 0
+2008-07-08 20:42:54.377: debug: Check KSK status
+2008-07-08 20:42:54.377: debug: Check ZSK status
+2008-07-08 20:42:54.377: debug: Re-signing not necessary!
+2008-07-08 20:42:54.377: debug: Check if there is a parent file to copy
+2008-07-08 20:42:54.377: debug:
+2008-07-08 20:42:54.377: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-08 20:42:54.378: debug: Check RFC5011 status
+2008-07-08 20:42:54.378: debug: ->ksk5011status returns 2
+2008-07-08 20:42:54.378: debug: Check ZSK status
+2008-07-08 20:42:54.378: debug: Re-signing not necessary!
+2008-07-08 20:42:54.378: debug: Check if there is a parent file to copy
+2008-07-08 20:42:54.378: debug:
+2008-07-08 20:42:54.378: notice: end of run: 0 errors occured
+2008-07-08 20:53:40.414: notice: ------------------------------------------------------------
+2008-07-08 20:53:40.414: notice: running ../../dnssec-signer -v -v -D .
+2008-07-08 20:53:40.417: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-08 20:53:40.417: debug: Check RFC5011 status
+2008-07-08 20:53:40.417: debug: ->ksk5011status returns 0
+2008-07-08 20:53:40.417: debug: Check KSK status
+2008-07-08 20:53:40.417: debug: Check ZSK status
+2008-07-08 20:53:40.417: debug: Re-signing not necessary!
+2008-07-08 20:53:40.417: debug: Check if there is a parent file to copy
+2008-07-08 20:53:40.417: debug:
+2008-07-08 20:53:40.417: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-08 20:53:40.417: debug: Check RFC5011 status
+2008-07-08 20:53:40.417: debug: ->ksk5011status returns 2
+2008-07-08 20:53:40.417: debug: Check ZSK status
+2008-07-08 20:53:40.417: debug: Re-signing not necessary!
+2008-07-08 20:53:40.418: debug: Check if there is a parent file to copy
+2008-07-08 20:53:40.418: debug:
+2008-07-08 20:53:40.418: notice: end of run: 0 errors occured
+2008-07-08 20:53:49.488: notice: ------------------------------------------------------------
+2008-07-08 20:53:49.488: notice: running ../../dnssec-signer -v -v -N named.conf
+2008-07-08 20:53:49.490: debug: parsing zone "sub.example.net." in dir "././sub.example.net."
+2008-07-08 20:53:49.490: debug: Check RFC5011 status
+2008-07-08 20:53:49.490: debug: ->ksk5011status returns 0
+2008-07-08 20:53:49.491: debug: Check KSK status
+2008-07-08 20:53:49.491: debug: Check ZSK status
+2008-07-08 20:53:49.491: debug: Re-signing not necessary!
+2008-07-08 20:53:49.491: debug: Check if there is a parent file to copy
+2008-07-08 20:53:49.491: debug:
+2008-07-08 20:53:49.491: debug: parsing zone "example.net." in dir "././example.net."
+2008-07-08 20:53:49.492: debug: Check RFC5011 status
+2008-07-08 20:53:49.492: debug: ->ksk5011status returns 2
+2008-07-08 20:53:49.492: debug: Check ZSK status
+2008-07-08 20:53:49.492: debug: Re-signing not necessary!
+2008-07-08 20:53:49.492: debug: Check if there is a parent file to copy
+2008-07-08 20:53:49.492: debug:
+2008-07-08 20:53:49.492: notice: end of run: 0 errors occured
+2008-07-09 00:42:08.103: notice: ------------------------------------------------------------
+2008-07-09 00:42:08.103: notice: running ../../dnssec-signer -v -v
+2008-07-09 00:42:08.106: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-09 00:42:08.106: debug: Check RFC5011 status
+2008-07-09 00:42:08.106: debug: ->ksk5011status returns 0
+2008-07-09 00:42:08.106: debug: Check KSK status
+2008-07-09 00:42:08.106: debug: ksk_rollover
+2008-07-09 00:42:08.106: debug: Check ZSK status
+2008-07-09 00:42:08.106: debug: Re-signing not necessary!
+2008-07-09 00:42:08.106: debug: Check if there is a parent file to copy
+2008-07-09 00:42:08.106: debug:
+2008-07-09 00:42:08.106: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-09 00:42:08.106: debug: Check RFC5011 status
+2008-07-09 00:42:08.106: debug: ->ksk5011status returns 2
+2008-07-09 00:42:08.106: debug: Check ZSK status
+2008-07-09 00:42:08.106: debug: Re-signing not necessary!
+2008-07-09 00:42:08.106: debug: Check if there is a parent file to copy
+2008-07-09 00:42:08.106: debug:
+2008-07-09 00:42:08.106: notice: end of run: 0 errors occured
+2008-07-09 00:45:19.663: notice: ------------------------------------------------------------
+2008-07-09 00:45:19.663: notice: running ../../dnssec-signer -v -v
+2008-07-09 00:45:19.665: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-09 00:45:19.665: debug: Check RFC5011 status
+2008-07-09 00:45:19.665: debug: ->ksk5011status returns 0
+2008-07-09 00:45:19.665: debug: Check KSK status
+2008-07-09 00:45:19.665: debug: Check ZSK status
+2008-07-09 00:45:19.665: debug: Re-signing not necessary!
+2008-07-09 00:45:19.665: debug: Check if there is a parent file to copy
+2008-07-09 00:45:19.665: debug:
+2008-07-09 00:45:19.665: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-09 00:45:19.665: debug: Check RFC5011 status
+2008-07-09 00:45:19.665: debug: ->ksk5011status returns 2
+2008-07-09 00:45:19.665: debug: Check ZSK status
+2008-07-09 00:45:19.665: debug: Re-signing not necessary!
+2008-07-09 00:45:19.665: debug: Check if there is a parent file to copy
+2008-07-09 00:45:19.665: debug:
+2008-07-09 00:45:19.665: notice: end of run: 0 errors occured
+2008-07-09 23:46:12.682: notice: ------------------------------------------------------------
+2008-07-09 23:46:12.682: notice: running ../../dnssec-signer -v -v -D /home/hoz/named/dnssec-signer/zkt-0.97/examples/flat/
+2008-07-09 23:46:12.702: debug: parsing zone "sub.example.net." in dir "/home/hoz/named/dnssec-signer/zkt-0.97/examples/flat/sub.example.net."
+2008-07-09 23:46:12.702: debug: Check RFC5011 status
+2008-07-09 23:46:12.702: debug: ->ksk5011status returns 0
+2008-07-09 23:46:12.702: debug: Check KSK status
+2008-07-09 23:46:12.702: debug: Check ZSK status
+2008-07-09 23:46:12.702: debug: Re-signing necessary: re-signing interval (1d) reached
+2008-07-09 23:46:12.702: notice: "sub.example.net.": re-signing triggered: re-signing interval (1d) reached
+2008-07-09 23:46:12.702: debug: Writing key file "/home/hoz/named/dnssec-signer/zkt-0.97/examples/flat/sub.example.net./dnskey.db"
+2008-07-09 23:46:12.702: debug: Signing zone "sub.example.net."
+2008-07-09 23:46:12.702: debug: Run cmd "cd /home/hoz/named/dnssec-signer/zkt-0.97/examples/flat/sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-09 23:46:13.222: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-09 23:46:13.222: debug: Signing completed after 1s.
+2008-07-09 23:46:13.222: debug:
+2008-07-09 23:46:13.222: debug: parsing zone "example.net." in dir "/home/hoz/named/dnssec-signer/zkt-0.97/examples/flat/example.net."
+2008-07-09 23:46:13.222: debug: Check RFC5011 status
+2008-07-09 23:46:13.222: debug: ->ksk5011status returns 2
+2008-07-09 23:46:13.222: debug: Check ZSK status
+2008-07-09 23:46:13.222: debug: Lifetime(29100 sec) of depreciated key 14939 exceeded (98273 sec)
+2008-07-09 23:46:13.222: info: "example.net.": removed old ZSK 14939
+
+2008-07-09 23:46:13.222: debug: ->remove it
+2008-07-09 23:46:13.222: debug: Re-signing necessary: New zone key
+2008-07-09 23:46:13.222: notice: "example.net.": re-signing triggered: New zone key
+2008-07-09 23:46:13.222: debug: Writing key file "/home/hoz/named/dnssec-signer/zkt-0.97/examples/flat/example.net./dnskey.db"
+2008-07-09 23:46:13.223: debug: Incrementing serial number in file "/home/hoz/named/dnssec-signer/zkt-0.97/examples/flat/example.net./zone.db"
+2008-07-09 23:46:13.223: debug: Signing zone "example.net."
+2008-07-09 23:46:13.223: debug: Run cmd "cd /home/hoz/named/dnssec-signer/zkt-0.97/examples/flat/example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-09 23:46:13.374: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-09 23:46:13.374: debug: Signing completed after 0s.
+2008-07-09 23:46:13.374: debug:
+2008-07-09 23:46:13.374: notice: end of run: 0 errors occured
+2008-07-15 00:21:04.641: notice: ------------------------------------------------------------
+2008-07-15 00:21:04.641: notice: running ../../dnssec-signer -r -v -v
+2008-07-15 00:21:05.071: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-15 00:21:05.071: debug: Check RFC5011 status
+2008-07-15 00:21:05.071: debug: ->ksk5011status returns 0
+2008-07-15 00:21:05.071: debug: Check KSK status
+2008-07-15 00:21:05.071: debug: Check ZSK status
+2008-07-15 00:21:05.071: debug: Lifetime(259200 +/-150 sec) of active key 2338 exceeded (602830 sec)
+2008-07-15 00:21:05.071: debug: ->depreciate it
+2008-07-15 00:21:05.072: debug: ->activate published key 9198
+2008-07-15 00:21:05.072: notice: "sub.example.net.": lifetime of zone signing key 2338 exceeded: ZSK rollover done
+2008-07-15 00:21:05.072: debug: New published key needed
+2008-07-15 00:21:05.128: debug: ->creating new published key 8397
+2008-07-15 00:21:05.128: info: "sub.example.net.": new published key 8397 created
+2008-07-15 00:21:05.128: debug: Re-signing necessary: New zone key
+2008-07-15 00:21:05.128: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-07-15 00:21:05.129: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-15 00:21:05.129: debug: Signing zone "sub.example.net."
+2008-07-15 00:21:05.129: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-15 00:21:05.274: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:21:05.274: debug: Signing completed after 0s.
+2008-07-15 00:21:05.274: notice: "sub.example.net.": distribution triggered
+2008-07-15 00:21:05.275: debug: Distribute zone "sub.example.net."
+2008-07-15 00:21:05.275: debug: Run cmd "./dist.sh reload sub.example.net."
+2008-07-15 00:21:05.279: debug:
+2008-07-15 00:21:05.279: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-15 00:21:05.279: debug: Check RFC5011 status
+2008-07-15 00:21:05.279: debug: ->ksk5011status returns 2
+2008-07-15 00:21:05.279: debug: Check ZSK status
+2008-07-15 00:21:05.279: debug: Re-signing necessary: re-signing interval (2d) reached
+2008-07-15 00:21:05.279: notice: "example.net.": re-signing triggered: re-signing interval (2d) reached
+2008-07-15 00:21:05.279: debug: Writing key file "./example.net./dnskey.db"
+2008-07-15 00:21:05.280: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-15 00:21:05.280: debug: Signing zone "example.net."
+2008-07-15 00:21:05.280: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-15 00:21:05.418: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:21:05.419: debug: Signing completed after 0s.
+2008-07-15 00:21:05.419: notice: "example.net.": distribution triggered
+2008-07-15 00:21:05.419: debug: Distribute zone "example.net."
+2008-07-15 00:21:05.419: debug: Run cmd "./dist.sh reload example.net."
+2008-07-15 00:21:05.423: debug:
+2008-07-15 00:21:05.423: notice: end of run: 0 errors occured
+2008-07-15 00:21:18.128: notice: ------------------------------------------------------------
+2008-07-15 00:21:18.128: notice: running ../../dnssec-signer -r -v -v
+2008-07-15 00:21:18.130: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-15 00:21:18.130: debug: Check RFC5011 status
+2008-07-15 00:21:18.130: debug: ->ksk5011status returns 0
+2008-07-15 00:21:18.130: debug: Check KSK status
+2008-07-15 00:21:18.130: debug: Check ZSK status
+2008-07-15 00:21:18.130: debug: Re-signing not necessary!
+2008-07-15 00:21:18.130: debug: Check if there is a parent file to copy
+2008-07-15 00:21:18.130: debug:
+2008-07-15 00:21:18.130: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-15 00:21:18.131: debug: Check RFC5011 status
+2008-07-15 00:21:18.131: debug: ->ksk5011status returns 2
+2008-07-15 00:21:18.131: debug: Check ZSK status
+2008-07-15 00:21:18.131: debug: Re-signing not necessary!
+2008-07-15 00:21:18.131: debug: Check if there is a parent file to copy
+2008-07-15 00:21:18.131: debug:
+2008-07-15 00:21:18.131: notice: end of run: 0 errors occured
+2008-07-15 00:21:26.360: notice: ------------------------------------------------------------
+2008-07-15 00:21:26.360: notice: running ../../dnssec-signer -f -r -v -v
+2008-07-15 00:21:26.362: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-15 00:21:26.362: debug: Check RFC5011 status
+2008-07-15 00:21:26.362: debug: ->ksk5011status returns 0
+2008-07-15 00:21:26.362: debug: Check KSK status
+2008-07-15 00:21:26.362: debug: Check ZSK status
+2008-07-15 00:21:26.362: debug: Re-signing necessary: Option -f
+2008-07-15 00:21:26.362: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-15 00:21:26.362: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-15 00:21:26.363: debug: Signing zone "sub.example.net."
+2008-07-15 00:21:26.363: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-15 00:21:26.978: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:21:26.978: debug: Signing completed after 0s.
+2008-07-15 00:21:26.978: notice: "sub.example.net.": distribution triggered
+2008-07-15 00:21:26.978: debug: Distribute zone "sub.example.net."
+2008-07-15 00:21:26.978: debug: Run cmd "./dist.sh reload sub.example.net."
+2008-07-15 00:21:26.983: debug:
+2008-07-15 00:21:26.983: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-15 00:21:26.983: debug: Check RFC5011 status
+2008-07-15 00:21:26.983: debug: ->ksk5011status returns 2
+2008-07-15 00:21:26.983: debug: Check ZSK status
+2008-07-15 00:21:26.983: debug: Re-signing necessary: Option -f
+2008-07-15 00:21:26.983: notice: "example.net.": re-signing triggered: Option -f
+2008-07-15 00:21:26.983: debug: Writing key file "./example.net./dnskey.db"
+2008-07-15 00:21:26.983: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-15 00:21:26.983: debug: Signing zone "example.net."
+2008-07-15 00:21:26.983: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-15 00:21:27.122: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:21:27.122: debug: Signing completed after 1s.
+2008-07-15 00:21:27.122: notice: "example.net.": distribution triggered
+2008-07-15 00:21:27.122: debug: Distribute zone "example.net."
+2008-07-15 00:21:27.122: debug: Run cmd "./dist.sh reload example.net."
+2008-07-15 00:21:27.127: debug:
+2008-07-15 00:21:27.127: notice: end of run: 0 errors occured
+2008-07-15 00:21:52.947: notice: ------------------------------------------------------------
+2008-07-15 00:21:52.947: notice: running ../../dnssec-signer -f -r -v -v
+2008-07-15 00:21:52.951: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-15 00:21:52.951: debug: Check RFC5011 status
+2008-07-15 00:21:52.951: debug: ->ksk5011status returns 0
+2008-07-15 00:21:52.951: debug: Check KSK status
+2008-07-15 00:21:52.951: debug: Check ZSK status
+2008-07-15 00:21:52.951: debug: Re-signing necessary: Option -f
+2008-07-15 00:21:52.951: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-15 00:21:52.951: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-15 00:21:52.952: debug: Signing zone "sub.example.net."
+2008-07-15 00:21:52.952: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-15 00:21:53.119: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:21:53.119: debug: Signing completed after 1s.
+2008-07-15 00:21:53.120: notice: "sub.example.net.": distribution triggered
+2008-07-15 00:21:53.120: debug: Distribute zone "sub.example.net."
+2008-07-15 00:21:53.120: debug: Run cmd "./dist.sh reload sub.example.net."
+2008-07-15 00:21:53.126: debug:
+2008-07-15 00:21:53.126: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-15 00:21:53.126: debug: Check RFC5011 status
+2008-07-15 00:21:53.126: debug: ->ksk5011status returns 2
+2008-07-15 00:21:53.126: debug: Check ZSK status
+2008-07-15 00:21:53.126: debug: Re-signing necessary: Option -f
+2008-07-15 00:21:53.126: notice: "example.net.": re-signing triggered: Option -f
+2008-07-15 00:21:53.126: debug: Writing key file "./example.net./dnskey.db"
+2008-07-15 00:21:53.126: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-15 00:21:53.126: debug: Signing zone "example.net."
+2008-07-15 00:21:53.126: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-15 00:21:53.262: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:21:53.262: debug: Signing completed after 0s.
+2008-07-15 00:21:53.262: notice: "example.net.": distribution triggered
+2008-07-15 00:21:53.262: debug: Distribute zone "example.net."
+2008-07-15 00:21:53.262: debug: Run cmd "./dist.sh reload example.net."
+2008-07-15 00:21:53.268: debug:
+2008-07-15 00:21:53.268: notice: end of run: 0 errors occured
+2008-07-15 00:23:40.781: notice: ------------------------------------------------------------
+2008-07-15 00:23:40.781: notice: running ../../dnssec-signer -f -r -v -v
+2008-07-15 00:23:40.783: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-15 00:23:40.783: debug: Check RFC5011 status
+2008-07-15 00:23:40.783: debug: ->ksk5011status returns 0
+2008-07-15 00:23:40.783: debug: Check KSK status
+2008-07-15 00:23:40.783: debug: Check ZSK status
+2008-07-15 00:23:40.783: debug: Re-signing necessary: Option -f
+2008-07-15 00:23:40.783: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-15 00:23:40.783: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-15 00:23:40.786: debug: Signing zone "sub.example.net."
+2008-07-15 00:23:40.786: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-15 00:23:41.281: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:23:41.281: debug: Signing completed after 1s.
+2008-07-15 00:23:41.281: notice: "sub.example.net.": distribution triggered
+2008-07-15 00:23:41.281: debug: Distribute zone "sub.example.net."
+2008-07-15 00:23:41.281: debug: Run cmd "./dist.sh reload sub.example.net."
+2008-07-15 00:23:41.287: debug:
+2008-07-15 00:23:41.287: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-15 00:23:41.287: debug: Check RFC5011 status
+2008-07-15 00:23:41.287: debug: ->ksk5011status returns 2
+2008-07-15 00:23:41.287: debug: Check ZSK status
+2008-07-15 00:23:41.287: debug: Re-signing necessary: Option -f
+2008-07-15 00:23:41.287: notice: "example.net.": re-signing triggered: Option -f
+2008-07-15 00:23:41.288: debug: Writing key file "./example.net./dnskey.db"
+2008-07-15 00:23:41.288: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-15 00:23:41.288: debug: Signing zone "example.net."
+2008-07-15 00:23:41.289: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-15 00:23:41.561: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:23:41.561: debug: Signing completed after 0s.
+2008-07-15 00:23:41.561: notice: "example.net.": distribution triggered
+2008-07-15 00:23:41.561: debug: Distribute zone "example.net."
+2008-07-15 00:23:41.561: debug: Run cmd "./dist.sh reload example.net."
+2008-07-15 00:23:41.566: debug:
+2008-07-15 00:23:41.567: notice: end of run: 0 errors occured
+2008-07-15 00:31:10.917: notice: ------------------------------------------------------------
+2008-07-15 00:31:10.917: notice: running ../../dnssec-signer -f -r -v -v
+2008-07-15 00:31:10.923: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-15 00:31:10.923: debug: Check RFC5011 status
+2008-07-15 00:31:10.923: debug: ->ksk5011status returns 0
+2008-07-15 00:31:10.923: debug: Check KSK status
+2008-07-15 00:31:10.923: debug: Check ZSK status
+2008-07-15 00:31:10.923: debug: Lifetime(390 sec) of depreciated key 2338 exceeded (605 sec)
+2008-07-15 00:31:10.923: info: "sub.example.net.": removed old ZSK 2338
+
+2008-07-15 00:31:10.924: debug: ->remove it
+2008-07-15 00:31:10.924: debug: Re-signing necessary: Option -f
+2008-07-15 00:31:10.924: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-15 00:31:10.924: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-15 00:31:11.347: debug: Signing zone "sub.example.net."
+2008-07-15 00:31:11.347: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-15 00:31:11.571: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:31:11.571: debug: Signing completed after 0s.
+2008-07-15 00:31:11.571: notice: "sub.example.net.": distribution triggered
+2008-07-15 00:31:11.571: debug: Distribute zone "sub.example.net."
+2008-07-15 00:31:11.571: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-15 00:31:11.579: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed :/sub.example.net."
+2008-07-15 00:31:11.579: debug:
+2008-07-15 00:31:11.580: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-15 00:31:11.580: debug: Check RFC5011 status
+2008-07-15 00:31:11.580: debug: ->ksk5011status returns 2
+2008-07-15 00:31:11.580: debug: Check ZSK status
+2008-07-15 00:31:11.580: debug: Re-signing necessary: Option -f
+2008-07-15 00:31:11.580: notice: "example.net.": re-signing triggered: Option -f
+2008-07-15 00:31:11.580: debug: Writing key file "./example.net./dnskey.db"
+2008-07-15 00:31:11.581: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-15 00:31:11.581: debug: Signing zone "example.net."
+2008-07-15 00:31:11.581: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-15 00:31:11.698: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:31:11.698: debug: Signing completed after 0s.
+2008-07-15 00:31:11.698: notice: "example.net.": distribution triggered
+2008-07-15 00:31:11.698: debug: Distribute zone "example.net."
+2008-07-15 00:31:11.698: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-15 00:31:11.704: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed :/example.net."
+2008-07-15 00:31:11.704: debug:
+2008-07-15 00:31:11.704: notice: end of run: 0 errors occured
+2008-07-15 00:32:00.676: notice: ------------------------------------------------------------
+2008-07-15 00:32:00.676: notice: running ../../dnssec-signer -f -r -v -v
+2008-07-15 00:32:00.678: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-15 00:32:00.678: debug: Check RFC5011 status
+2008-07-15 00:32:00.678: debug: ->ksk5011status returns 0
+2008-07-15 00:32:00.678: debug: Check KSK status
+2008-07-15 00:32:00.678: debug: Check ZSK status
+2008-07-15 00:32:00.678: debug: Re-signing necessary: Option -f
+2008-07-15 00:32:00.678: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-15 00:32:00.678: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-15 00:32:00.679: debug: Signing zone "sub.example.net."
+2008-07-15 00:32:00.679: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-15 00:32:01.282: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:32:01.282: debug: Signing completed after 1s.
+2008-07-15 00:32:01.282: notice: "sub.example.net.": distribution triggered
+2008-07-15 00:32:01.282: debug: Distribute zone "sub.example.net."
+2008-07-15 00:32:01.282: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-15 00:32:01.289: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/sub.example.net."
+2008-07-15 00:32:01.289: debug:
+2008-07-15 00:32:01.289: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-15 00:32:01.289: debug: Check RFC5011 status
+2008-07-15 00:32:01.289: debug: ->ksk5011status returns 2
+2008-07-15 00:32:01.289: debug: Check ZSK status
+2008-07-15 00:32:01.290: debug: Re-signing necessary: Option -f
+2008-07-15 00:32:01.290: notice: "example.net.": re-signing triggered: Option -f
+2008-07-15 00:32:01.290: debug: Writing key file "./example.net./dnskey.db"
+2008-07-15 00:32:01.291: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-15 00:32:01.291: debug: Signing zone "example.net."
+2008-07-15 00:32:01.291: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-15 00:32:01.405: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:32:01.405: debug: Signing completed after 0s.
+2008-07-15 00:32:01.406: notice: "example.net.": distribution triggered
+2008-07-15 00:32:01.406: debug: Distribute zone "example.net."
+2008-07-15 00:32:01.406: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-15 00:32:01.412: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/example.net."
+2008-07-15 00:32:01.412: debug:
+2008-07-15 00:32:01.412: notice: end of run: 0 errors occured
+2008-07-15 00:33:00.866: notice: ------------------------------------------------------------
+2008-07-15 00:33:00.867: notice: running ../../dnssec-signer -f -r -v -v
+2008-07-15 00:33:00.869: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-15 00:33:00.869: debug: Check RFC5011 status
+2008-07-15 00:33:00.869: debug: ->ksk5011status returns 0
+2008-07-15 00:33:00.869: debug: Check KSK status
+2008-07-15 00:33:00.869: debug: Check ZSK status
+2008-07-15 00:33:00.869: debug: Re-signing necessary: Option -f
+2008-07-15 00:33:00.870: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-15 00:33:00.870: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-15 00:33:00.870: debug: Signing zone "sub.example.net."
+2008-07-15 00:33:00.870: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-15 00:33:01.531: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:33:01.531: debug: Signing completed after 1s.
+2008-07-15 00:33:01.531: notice: "sub.example.net.": distribution triggered
+2008-07-15 00:33:01.531: debug: Distribute zone "sub.example.net."
+2008-07-15 00:33:01.531: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-15 00:33:01.537: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net."
+2008-07-15 00:33:01.537: debug:
+2008-07-15 00:33:01.537: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-15 00:33:01.538: debug: Check RFC5011 status
+2008-07-15 00:33:01.538: debug: ->ksk5011status returns 2
+2008-07-15 00:33:01.538: debug: Check ZSK status
+2008-07-15 00:33:01.538: debug: Re-signing necessary: Option -f
+2008-07-15 00:33:01.538: notice: "example.net.": re-signing triggered: Option -f
+2008-07-15 00:33:01.538: debug: Writing key file "./example.net./dnskey.db"
+2008-07-15 00:33:01.539: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-15 00:33:01.539: debug: Signing zone "example.net."
+2008-07-15 00:33:01.539: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-15 00:33:01.655: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:33:01.655: debug: Signing completed after 0s.
+2008-07-15 00:33:01.655: notice: "example.net.": distribution triggered
+2008-07-15 00:33:01.655: debug: Distribute zone "example.net."
+2008-07-15 00:33:01.656: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-15 00:33:01.661: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net."
+2008-07-15 00:33:01.662: debug:
+2008-07-15 00:33:01.662: notice: end of run: 0 errors occured
+2008-07-15 00:34:09.259: notice: ------------------------------------------------------------
+2008-07-15 00:34:09.259: notice: running ../../dnssec-signer -f -r -v -v
+2008-07-15 00:34:09.261: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-15 00:34:09.261: debug: Check RFC5011 status
+2008-07-15 00:34:09.261: debug: ->ksk5011status returns 0
+2008-07-15 00:34:09.261: debug: Check KSK status
+2008-07-15 00:34:09.261: debug: Check ZSK status
+2008-07-15 00:34:09.261: debug: Re-signing necessary: Option -f
+2008-07-15 00:34:09.261: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-15 00:34:09.261: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-15 00:34:09.261: debug: Signing zone "sub.example.net."
+2008-07-15 00:34:09.261: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-15 00:34:10.245: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:34:10.245: debug: Signing completed after 1s.
+2008-07-15 00:34:10.245: notice: "sub.example.net.": distribution triggered
+2008-07-15 00:34:10.245: debug: Distribute zone "sub.example.net."
+2008-07-15 00:34:10.245: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-15 00:34:10.251: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-15 00:34:10.252: debug:
+2008-07-15 00:34:10.252: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-15 00:34:10.252: debug: Check RFC5011 status
+2008-07-15 00:34:10.252: debug: ->ksk5011status returns 2
+2008-07-15 00:34:10.252: debug: Check ZSK status
+2008-07-15 00:34:10.252: debug: Re-signing necessary: Option -f
+2008-07-15 00:34:10.252: notice: "example.net.": re-signing triggered: Option -f
+2008-07-15 00:34:10.252: debug: Writing key file "./example.net./dnskey.db"
+2008-07-15 00:34:10.252: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-15 00:34:10.252: debug: Signing zone "example.net."
+2008-07-15 00:34:10.252: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-15 00:34:10.369: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-15 00:34:10.369: debug: Signing completed after 0s.
+2008-07-15 00:34:10.369: notice: "example.net.": distribution triggered
+2008-07-15 00:34:10.369: debug: Distribute zone "example.net."
+2008-07-15 00:34:10.369: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-15 00:34:10.375: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-15 00:34:10.375: debug:
+2008-07-15 00:34:10.375: notice: end of run: 0 errors occured
+2008-07-18 00:38:52.860: notice: ------------------------------------------------------------
+2008-07-18 00:38:52.860: notice: running ../../dnssec-signer -v -v
+2008-07-18 00:38:52.862: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-18 00:38:52.862: debug: Check RFC5011 status
+2008-07-18 00:38:52.862: debug: ->ksk5011status returns 0
+2008-07-18 00:38:52.862: debug: Check KSK status
+2008-07-18 00:38:52.862: debug: Check ZSK status
+2008-07-18 00:38:52.862: debug: Lifetime(259200 +/-150 sec) of active key 9198 exceeded (260267 sec)
+2008-07-18 00:38:52.862: debug: ->depreciate it
+2008-07-18 00:38:52.862: debug: ->activate published key 8397
+2008-07-18 00:38:52.862: notice: "sub.example.net.": lifetime of zone signing key 9198 exceeded: ZSK rollover done
+2008-07-18 00:38:52.862: debug: New published key needed
+2008-07-18 00:38:53.418: debug: ->creating new published key 31081
+2008-07-18 00:38:53.418: info: "sub.example.net.": new key 31081 generated for publishing
+2008-07-18 00:38:53.418: debug: Re-signing necessary: New zone key
+2008-07-18 00:38:53.418: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-07-18 00:38:53.418: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-18 00:38:53.419: debug: Signing zone "sub.example.net."
+2008-07-18 00:38:53.419: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-18 00:38:53.556: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-18 00:38:53.556: debug: Signing completed after 0s.
+2008-07-18 00:38:53.556: debug:
+2008-07-18 00:38:53.556: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-18 00:38:53.557: debug: Check RFC5011 status
+2008-07-18 00:38:53.557: debug: ->ksk5011status returns 2
+2008-07-18 00:38:53.557: debug: Check ZSK status
+2008-07-18 00:38:53.557: debug: Re-signing necessary: re-signing interval (2d) reached
+2008-07-18 00:38:53.557: notice: "example.net.": re-signing triggered: re-signing interval (2d) reached
+2008-07-18 00:38:53.557: debug: Writing key file "./example.net./dnskey.db"
+2008-07-18 00:38:53.558: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-18 00:38:53.558: debug: Signing zone "example.net."
+2008-07-18 00:38:53.559: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-18 00:38:53.715: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-18 00:38:53.715: debug: Signing completed after 0s.
+2008-07-18 00:38:53.715: debug:
+2008-07-18 00:38:53.716: notice: end of run: 0 errors occured
+2008-07-18 00:39:29.824: notice: ------------------------------------------------------------
+2008-07-18 00:39:29.824: notice: running ../../dnssec-signer -r -v -v
+2008-07-18 00:39:29.827: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-18 00:39:29.827: debug: Check RFC5011 status
+2008-07-18 00:39:29.827: debug: ->ksk5011status returns 0
+2008-07-18 00:39:29.827: debug: Check KSK status
+2008-07-18 00:39:29.827: debug: Check ZSK status
+2008-07-18 00:39:29.827: debug: Re-signing not necessary!
+2008-07-18 00:39:29.827: debug: Check if there is a parent file to copy
+2008-07-18 00:39:29.827: debug:
+2008-07-18 00:39:29.827: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-18 00:39:29.827: debug: Check RFC5011 status
+2008-07-18 00:39:29.827: debug: ->ksk5011status returns 2
+2008-07-18 00:39:29.827: debug: Check ZSK status
+2008-07-18 00:39:29.827: debug: Re-signing not necessary!
+2008-07-18 00:39:29.827: debug: Check if there is a parent file to copy
+2008-07-18 00:39:29.827: debug:
+2008-07-18 00:39:29.828: notice: end of run: 0 errors occured
+2008-07-18 00:39:36.641: notice: ------------------------------------------------------------
+2008-07-18 00:39:36.641: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-18 00:39:36.644: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-18 00:39:36.644: debug: Check RFC5011 status
+2008-07-18 00:39:36.644: debug: ->ksk5011status returns 0
+2008-07-18 00:39:36.644: debug: Check KSK status
+2008-07-18 00:39:36.644: debug: Check ZSK status
+2008-07-18 00:39:36.644: debug: Re-signing necessary: Option -f
+2008-07-18 00:39:36.644: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-18 00:39:36.644: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-18 00:39:36.644: debug: Signing zone "sub.example.net."
+2008-07-18 00:39:36.644: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-18 00:39:37.144: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-18 00:39:37.144: debug: Signing completed after 1s.
+2008-07-18 00:39:37.144: notice: "sub.example.net.": distribution triggered
+2008-07-18 00:39:37.144: debug: Distribute zone "sub.example.net."
+2008-07-18 00:39:37.144: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-18 00:39:37.151: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-18 00:39:37.151: debug:
+2008-07-18 00:39:37.151: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-18 00:39:37.151: debug: Check RFC5011 status
+2008-07-18 00:39:37.151: debug: ->ksk5011status returns 2
+2008-07-18 00:39:37.151: debug: Check ZSK status
+2008-07-18 00:39:37.151: debug: Re-signing necessary: Option -f
+2008-07-18 00:39:37.151: notice: "example.net.": re-signing triggered: Option -f
+2008-07-18 00:39:37.151: debug: Writing key file "./example.net./dnskey.db"
+2008-07-18 00:39:37.152: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-18 00:39:37.152: debug: Signing zone "example.net."
+2008-07-18 00:39:37.152: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-18 00:39:37.313: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-18 00:39:37.313: debug: Signing completed after 0s.
+2008-07-18 00:39:37.313: notice: "example.net.": distribution triggered
+2008-07-18 00:39:37.313: debug: Distribute zone "example.net."
+2008-07-18 00:39:37.313: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-18 00:39:37.319: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-18 00:39:37.319: debug:
+2008-07-18 00:39:37.319: notice: end of run: 0 errors occured
+2008-07-18 00:42:39.912: notice: ------------------------------------------------------------
+2008-07-18 00:42:39.912: notice: running ../../dnssec-signer -v -v
+2008-07-18 00:42:39.914: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-18 00:42:39.914: debug: Check RFC5011 status
+2008-07-18 00:42:39.914: debug: ->ksk5011status returns 0
+2008-07-18 00:42:39.914: debug: Check KSK status
+2008-07-18 00:42:39.914: debug: Check ZSK status
+2008-07-18 00:42:39.914: debug: Re-signing not necessary!
+2008-07-18 00:42:39.914: debug: Check if there is a parent file to copy
+2008-07-18 00:42:39.914: debug:
+2008-07-18 00:42:39.914: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-18 00:42:39.914: debug: Check RFC5011 status
+2008-07-18 00:42:39.914: debug: ->ksk5011status returns 2
+2008-07-18 00:42:39.914: debug: Check ZSK status
+2008-07-18 00:42:39.914: debug: Re-signing not necessary!
+2008-07-18 00:42:39.914: debug: Check if there is a parent file to copy
+2008-07-18 00:42:39.914: debug:
+2008-07-18 00:42:39.914: notice: end of run: 0 errors occured
+2008-07-22 00:10:38.346: notice: ------------------------------------------------------------
+2008-07-22 00:10:38.346: notice: running ../../dnssec-signer -v -v
+2008-07-22 00:10:38.349: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:10:38.349: debug: Check RFC5011 status
+2008-07-22 00:10:38.349: debug: ->ksk5011status returns 0
+2008-07-22 00:10:38.349: debug: Check KSK status
+2008-07-22 00:10:38.349: debug: Check ZSK status
+2008-07-22 00:10:38.349: debug: Lifetime(390 sec) of depreciated key 9198 exceeded (343906 sec)
+2008-07-22 00:10:38.349: info: "sub.example.net.": removed old ZSK 9198
+
+2008-07-22 00:10:38.349: debug: ->remove it
+2008-07-22 00:10:38.349: debug: Lifetime(259200 +/-150 sec) of active key 8397 exceeded (343906 sec)
+2008-07-22 00:10:38.349: debug: ->depreciate it
+2008-07-22 00:10:38.349: debug: ->activate published key 31081
+2008-07-22 00:10:38.349: notice: "sub.example.net.": lifetime of zone signing key 8397 exceeded: ZSK rollover done
+2008-07-22 00:10:38.349: debug: New published key needed
+2008-07-22 00:10:38.870: debug: ->creating new published key 3615
+2008-07-22 00:10:38.870: info: "sub.example.net.": new key 3615 generated for publishing
+2008-07-22 00:10:38.870: debug: Re-signing necessary: New zone key
+2008-07-22 00:10:38.870: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-07-22 00:10:38.870: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:10:38.871: debug: Signing zone "sub.example.net."
+2008-07-22 00:10:38.871: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:10:39.208: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:10:39.208: debug: Signing completed after 1s.
+2008-07-22 00:10:39.208: debug:
+2008-07-22 00:10:39.208: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:10:39.208: debug: Check RFC5011 status
+2008-07-22 00:10:39.208: debug: ->ksk5011status returns 2
+2008-07-22 00:10:39.208: debug: Check ZSK status
+2008-07-22 00:10:39.208: debug: New published key needed
+2008-07-22 00:10:39.255: debug: ->creating new published key 41300
+2008-07-22 00:10:39.255: info: "example.net.": new key 41300 generated for publishing
+2008-07-22 00:10:39.255: debug: Re-signing necessary: New zone key
+2008-07-22 00:10:39.255: notice: "example.net.": re-signing triggered: New zone key
+2008-07-22 00:10:39.255: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:10:39.256: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:10:39.256: debug: Signing zone "example.net."
+2008-07-22 00:10:39.256: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:10:39.414: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:10:39.414: debug: Signing completed after 0s.
+2008-07-22 00:10:39.414: debug:
+2008-07-22 00:10:39.414: notice: end of run: 0 errors occured
+2008-07-22 00:16:04.680: notice: ------------------------------------------------------------
+2008-07-22 00:16:04.680: notice: running ../../dnssec-signer -v -v
+2008-07-22 00:16:04.682: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:16:04.682: debug: Check RFC5011 status
+2008-07-22 00:16:04.682: debug: ->ksk5011status returns 0
+2008-07-22 00:16:04.683: debug: Check KSK status
+2008-07-22 00:16:04.683: debug: Check ZSK status
+2008-07-22 00:16:04.683: debug: Re-signing not necessary!
+2008-07-22 00:16:04.683: debug: Check if there is a parent file to copy
+2008-07-22 00:16:04.683: debug:
+2008-07-22 00:16:04.683: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:16:04.683: debug: Check RFC5011 status
+2008-07-22 00:16:04.683: debug: ->ksk5011status returns 2
+2008-07-22 00:16:04.684: debug: Check ZSK status
+2008-07-22 00:16:04.684: debug: Re-signing not necessary!
+2008-07-22 00:16:04.684: debug: Check if there is a parent file to copy
+2008-07-22 00:16:04.684: debug:
+2008-07-22 00:16:04.684: notice: end of run: 0 errors occured
+2008-07-22 00:16:09.309: notice: ------------------------------------------------------------
+2008-07-22 00:16:09.309: notice: running ../../dnssec-signer -r -v -v
+2008-07-22 00:16:09.311: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:16:09.311: debug: Check RFC5011 status
+2008-07-22 00:16:09.311: debug: ->ksk5011status returns 0
+2008-07-22 00:16:09.312: debug: Check KSK status
+2008-07-22 00:16:09.312: debug: Check ZSK status
+2008-07-22 00:16:09.312: debug: Re-signing not necessary!
+2008-07-22 00:16:09.312: debug: Check if there is a parent file to copy
+2008-07-22 00:16:09.312: debug:
+2008-07-22 00:16:09.312: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:16:09.312: debug: Check RFC5011 status
+2008-07-22 00:16:09.312: debug: ->ksk5011status returns 2
+2008-07-22 00:16:09.313: debug: Check ZSK status
+2008-07-22 00:16:09.313: debug: Re-signing not necessary!
+2008-07-22 00:16:09.313: debug: Check if there is a parent file to copy
+2008-07-22 00:16:09.313: debug:
+2008-07-22 00:16:09.313: notice: end of run: 0 errors occured
+2008-07-22 00:16:13.285: notice: ------------------------------------------------------------
+2008-07-22 00:16:13.285: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 00:16:13.287: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:16:13.287: debug: Check RFC5011 status
+2008-07-22 00:16:13.287: debug: ->ksk5011status returns 0
+2008-07-22 00:16:13.287: debug: Check KSK status
+2008-07-22 00:16:13.287: debug: Check ZSK status
+2008-07-22 00:16:13.287: debug: Re-signing necessary: Option -f
+2008-07-22 00:16:13.287: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 00:16:13.287: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:16:13.287: debug: Signing zone "sub.example.net."
+2008-07-22 00:16:13.287: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:16:13.822: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:16:13.822: debug: Signing completed after 0s.
+2008-07-22 00:16:13.822: notice: "sub.example.net.": distribution triggered
+2008-07-22 00:16:13.822: debug: Distribute zone "sub.example.net."
+2008-07-22 00:16:13.822: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-22 00:16:13.828: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-22 00:16:13.828: debug:
+2008-07-22 00:16:13.829: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:16:13.829: debug: Check RFC5011 status
+2008-07-22 00:16:13.829: debug: ->ksk5011status returns 2
+2008-07-22 00:16:13.829: debug: Check ZSK status
+2008-07-22 00:16:13.829: debug: Re-signing necessary: Option -f
+2008-07-22 00:16:13.829: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 00:16:13.829: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:16:13.830: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:16:13.830: debug: Signing zone "example.net."
+2008-07-22 00:16:13.830: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:16:13.976: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:16:13.976: debug: Signing completed after 0s.
+2008-07-22 00:16:13.977: notice: "example.net.": distribution triggered
+2008-07-22 00:16:13.977: debug: Distribute zone "example.net."
+2008-07-22 00:16:13.977: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-22 00:16:13.983: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-22 00:16:13.983: debug:
+2008-07-22 00:16:13.983: notice: end of run: 0 errors occured
+2008-07-22 00:20:56.119: notice: ------------------------------------------------------------
+2008-07-22 00:20:56.119: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 00:20:56.121: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:20:56.121: debug: Check RFC5011 status
+2008-07-22 00:20:56.121: debug: ->ksk5011status returns 0
+2008-07-22 00:20:56.121: debug: Check KSK status
+2008-07-22 00:20:56.121: debug: Check ZSK status
+2008-07-22 00:20:56.121: debug: Lifetime(390 sec) of depreciated key 8397 exceeded (618 sec)
+2008-07-22 00:20:56.121: info: "sub.example.net.": removed old ZSK 8397
+
+2008-07-22 00:20:56.122: debug: ->remove it
+2008-07-22 00:20:56.122: debug: Re-signing necessary: Option -f
+2008-07-22 00:20:56.122: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 00:20:56.122: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:20:56.122: debug: Signing zone "sub.example.net."
+2008-07-22 00:20:56.122: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:20:56.627: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:20:56.627: debug: Signing completed after 0s.
+2008-07-22 00:20:56.627: notice: "sub.example.net.": distribution triggered
+2008-07-22 00:20:56.627: debug: Distribute zone "sub.example.net."
+2008-07-22 00:20:56.627: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-22 00:20:56.634: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-22 00:20:56.635: debug:
+2008-07-22 00:20:56.635: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:20:56.635: debug: Check RFC5011 status
+2008-07-22 00:20:56.635: debug: ->ksk5011status returns 2
+2008-07-22 00:20:56.635: debug: Check ZSK status
+2008-07-22 00:20:56.635: debug: Re-signing necessary: Option -f
+2008-07-22 00:20:56.635: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 00:20:56.635: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:20:56.636: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:20:56.636: debug: Signing zone "example.net."
+2008-07-22 00:20:56.637: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:20:56.760: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:20:56.760: debug: Signing completed after 0s.
+2008-07-22 00:20:56.760: notice: "example.net.": distribution triggered
+2008-07-22 00:20:56.760: debug: Distribute zone "example.net."
+2008-07-22 00:20:56.760: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-22 00:20:56.768: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-22 00:20:56.769: debug:
+2008-07-22 00:20:56.769: notice: end of run: 0 errors occured
+2008-07-22 00:23:51.528: notice: ------------------------------------------------------------
+2008-07-22 00:23:51.528: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 00:23:51.530: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:23:51.530: debug: Check RFC5011 status
+2008-07-22 00:23:51.530: debug: ->ksk5011status returns 0
+2008-07-22 00:23:51.531: debug: Check KSK status
+2008-07-22 00:23:51.531: debug: Check ZSK status
+2008-07-22 00:23:51.531: debug: Re-signing necessary: Option -f
+2008-07-22 00:23:51.531: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 00:23:51.531: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:23:51.531: debug: Signing zone "sub.example.net."
+2008-07-22 00:23:51.532: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:23:52.042: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:23:52.042: debug: Signing completed after 1s.
+2008-07-22 00:23:52.042: notice: "sub.example.net.": distribution triggered
+2008-07-22 00:23:52.042: debug: Distribute zone "sub.example.net."
+2008-07-22 00:23:52.043: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-22 00:23:52.049: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-22 00:23:52.049: debug:
+2008-07-22 00:23:52.049: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:23:52.049: debug: Check RFC5011 status
+2008-07-22 00:23:52.049: debug: ->ksk5011status returns 2
+2008-07-22 00:23:52.049: debug: Check ZSK status
+2008-07-22 00:23:52.049: debug: Re-signing necessary: Option -f
+2008-07-22 00:23:52.049: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 00:23:52.049: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:23:52.050: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:23:52.050: debug: Signing zone "example.net."
+2008-07-22 00:23:52.050: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:23:52.176: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:23:52.176: debug: Signing completed after 0s.
+2008-07-22 00:23:52.176: notice: "example.net.": distribution triggered
+2008-07-22 00:23:52.176: debug: Distribute zone "example.net."
+2008-07-22 00:23:52.176: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-22 00:23:52.185: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-22 00:23:52.185: debug:
+2008-07-22 00:23:52.185: notice: end of run: 0 errors occured
+2008-07-22 00:24:09.609: notice: ------------------------------------------------------------
+2008-07-22 00:24:09.609: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 00:24:09.614: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:24:09.614: debug: Check RFC5011 status
+2008-07-22 00:24:09.614: debug: ->ksk5011status returns 0
+2008-07-22 00:24:09.614: debug: Check KSK status
+2008-07-22 00:24:09.614: debug: Check ZSK status
+2008-07-22 00:24:09.614: debug: Re-signing necessary: Option -f
+2008-07-22 00:24:09.614: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 00:24:09.614: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:24:09.614: debug: Signing zone "sub.example.net."
+2008-07-22 00:24:09.614: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:24:10.692: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:24:10.692: debug: Signing completed after 1s.
+2008-07-22 00:24:10.692: notice: "sub.example.net.": distribution triggered
+2008-07-22 00:24:10.692: debug: Distribute zone "sub.example.net."
+2008-07-22 00:24:10.692: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-22 00:24:10.698: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-22 00:24:10.698: debug:
+2008-07-22 00:24:10.698: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:24:10.698: debug: Check RFC5011 status
+2008-07-22 00:24:10.698: debug: ->ksk5011status returns 2
+2008-07-22 00:24:10.698: debug: Check ZSK status
+2008-07-22 00:24:10.698: debug: Re-signing necessary: Option -f
+2008-07-22 00:24:10.698: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 00:24:10.698: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:24:10.699: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:24:10.699: debug: Signing zone "example.net."
+2008-07-22 00:24:10.699: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:24:10.883: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:24:10.883: debug: Signing completed after 0s.
+2008-07-22 00:24:10.883: notice: "example.net.": distribution triggered
+2008-07-22 00:24:10.883: debug: Distribute zone "example.net."
+2008-07-22 00:24:10.883: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-22 00:24:10.889: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-22 00:24:10.889: debug:
+2008-07-22 00:24:10.889: notice: end of run: 0 errors occured
+2008-07-22 00:28:44.300: notice: ------------------------------------------------------------
+2008-07-22 00:28:44.300: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 00:28:44.302: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:28:44.302: debug: Check RFC5011 status
+2008-07-22 00:28:44.302: debug: ->ksk5011status returns 0
+2008-07-22 00:28:44.302: debug: Check KSK status
+2008-07-22 00:28:44.302: debug: Check ZSK status
+2008-07-22 00:28:44.302: debug: Re-signing necessary: Option -f
+2008-07-22 00:28:44.302: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 00:28:44.302: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:28:44.306: debug: Signing zone "sub.example.net."
+2008-07-22 00:28:44.306: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:28:44.898: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:28:44.898: debug: Signing completed after 0s.
+2008-07-22 00:28:44.898: notice: "sub.example.net.": distribution triggered
+2008-07-22 00:28:44.899: debug: Distribute zone "sub.example.net."
+2008-07-22 00:28:44.899: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-22 00:28:44.904: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-22 00:28:44.905: debug:
+2008-07-22 00:28:44.905: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:28:44.905: debug: Check RFC5011 status
+2008-07-22 00:28:44.905: debug: ->ksk5011status returns 2
+2008-07-22 00:28:44.905: debug: Check ZSK status
+2008-07-22 00:28:44.905: debug: Re-signing necessary: Option -f
+2008-07-22 00:28:44.905: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 00:28:44.905: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:28:44.906: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:28:44.906: debug: Signing zone "example.net."
+2008-07-22 00:28:44.907: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:28:45.039: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:28:45.039: debug: Signing completed after 1s.
+2008-07-22 00:28:45.039: notice: "example.net.": distribution triggered
+2008-07-22 00:28:45.039: debug: Distribute zone "example.net."
+2008-07-22 00:28:45.040: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-22 00:28:45.046: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-22 00:28:45.046: debug:
+2008-07-22 00:28:45.046: notice: end of run: 0 errors occured
+2008-07-22 00:39:15.968: notice: ------------------------------------------------------------
+2008-07-22 00:39:15.968: notice: running ../../dnssec-signer -r -v -v
+2008-07-22 00:39:16.005: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:39:16.006: debug: Check RFC5011 status
+2008-07-22 00:39:16.006: debug: ->ksk5011status returns 0
+2008-07-22 00:39:16.006: debug: Check KSK status
+2008-07-22 00:39:16.006: debug: Check ZSK status
+2008-07-22 00:39:16.006: debug: Re-signing not necessary!
+2008-07-22 00:39:16.006: debug: Check if there is a parent file to copy
+2008-07-22 00:39:16.006: debug:
+2008-07-22 00:39:16.006: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:39:16.006: debug: Check RFC5011 status
+2008-07-22 00:39:16.006: debug: ->ksk5011status returns 2
+2008-07-22 00:39:16.007: debug: Check ZSK status
+2008-07-22 00:39:16.007: debug: Re-signing not necessary!
+2008-07-22 00:39:16.007: debug: Check if there is a parent file to copy
+2008-07-22 00:39:16.007: debug:
+2008-07-22 00:39:16.007: notice: end of run: 0 errors occured
+2008-07-22 00:39:31.578: notice: ------------------------------------------------------------
+2008-07-22 00:39:31.578: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 00:39:31.580: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:39:31.580: debug: Check RFC5011 status
+2008-07-22 00:39:31.580: debug: ->ksk5011status returns 0
+2008-07-22 00:39:31.580: debug: Check KSK status
+2008-07-22 00:39:31.581: debug: Check ZSK status
+2008-07-22 00:39:31.581: debug: Re-signing necessary: Option -f
+2008-07-22 00:39:31.581: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 00:39:31.581: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:39:31.581: debug: Signing zone "sub.example.net."
+2008-07-22 00:39:31.582: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:39:32.216: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:39:32.216: debug: Signing completed after 1s.
+2008-07-22 00:39:32.216: notice: "sub.example.net.": distribution triggered
+2008-07-22 00:39:32.216: debug: Distribute zone "sub.example.net."
+2008-07-22 00:39:32.217: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-22 00:39:32.223: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-22 00:39:32.223: debug:
+2008-07-22 00:39:32.223: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:39:32.223: debug: Check RFC5011 status
+2008-07-22 00:39:32.223: debug: ->ksk5011status returns 2
+2008-07-22 00:39:32.223: debug: Check ZSK status
+2008-07-22 00:39:32.223: debug: Re-signing necessary: Option -f
+2008-07-22 00:39:32.223: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 00:39:32.223: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:39:32.224: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:39:32.224: debug: Signing zone "example.net."
+2008-07-22 00:39:32.225: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:39:32.360: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:39:32.361: debug: Signing completed after 0s.
+2008-07-22 00:39:32.361: notice: "example.net.": distribution triggered
+2008-07-22 00:39:32.361: debug: Distribute zone "example.net."
+2008-07-22 00:39:32.361: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-22 00:39:32.367: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-22 00:39:32.367: debug:
+2008-07-22 00:39:32.367: notice: end of run: 0 errors occured
+2008-07-22 00:41:53.710: notice: ------------------------------------------------------------
+2008-07-22 00:41:53.710: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 00:41:53.712: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:41:53.712: debug: Check RFC5011 status
+2008-07-22 00:41:53.712: debug: ->ksk5011status returns 0
+2008-07-22 00:41:53.712: debug: Check KSK status
+2008-07-22 00:41:53.712: debug: Check ZSK status
+2008-07-22 00:41:53.712: debug: Re-signing necessary: Option -f
+2008-07-22 00:41:53.712: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 00:41:53.712: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:41:53.712: debug: Signing zone "sub.example.net."
+2008-07-22 00:41:53.713: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:41:53.866: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:41:53.866: debug: Signing completed after 0s.
+2008-07-22 00:41:53.866: notice: "sub.example.net.": distribution triggered
+2008-07-22 00:41:53.866: debug: Distribute zone "sub.example.net."
+2008-07-22 00:41:53.867: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-22 00:41:53.873: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-22 00:41:53.873: debug:
+2008-07-22 00:41:53.873: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:41:53.873: debug: Check RFC5011 status
+2008-07-22 00:41:53.873: debug: ->ksk5011status returns 2
+2008-07-22 00:41:53.873: debug: Check ZSK status
+2008-07-22 00:41:53.873: debug: Re-signing necessary: Option -f
+2008-07-22 00:41:53.873: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 00:41:53.873: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:41:53.873: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:41:53.873: debug: Signing zone "example.net."
+2008-07-22 00:41:53.873: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:41:53.989: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:41:53.989: debug: Signing completed after 0s.
+2008-07-22 00:41:53.989: notice: "example.net.": distribution triggered
+2008-07-22 00:41:53.989: debug: Distribute zone "example.net."
+2008-07-22 00:41:53.989: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-22 00:41:53.995: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-22 00:41:53.995: debug:
+2008-07-22 00:41:53.995: notice: end of run: 0 errors occured
+2008-07-22 00:45:46.509: notice: ------------------------------------------------------------
+2008-07-22 00:45:46.509: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 00:45:46.511: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:45:46.512: debug: Check RFC5011 status
+2008-07-22 00:45:46.512: debug: ->ksk5011status returns 0
+2008-07-22 00:45:46.512: debug: Check KSK status
+2008-07-22 00:45:46.512: debug: Check ZSK status
+2008-07-22 00:45:46.512: debug: Re-signing necessary: Option -f
+2008-07-22 00:45:46.512: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 00:45:46.512: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:45:46.513: debug: Signing zone "sub.example.net."
+2008-07-22 00:45:46.513: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:45:46.734: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:45:46.734: debug: Signing completed after 0s.
+2008-07-22 00:45:46.734: notice: "sub.example.net.": distribution triggered
+2008-07-22 00:45:46.734: debug: Distribute zone "sub.example.net."
+2008-07-22 00:45:46.734: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-22 00:45:46.740: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-22 00:45:46.740: debug:
+2008-07-22 00:45:46.740: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:45:46.740: debug: Check RFC5011 status
+2008-07-22 00:45:46.741: debug: ->ksk5011status returns 2
+2008-07-22 00:45:46.741: debug: Check ZSK status
+2008-07-22 00:45:46.741: debug: Re-signing necessary: Option -f
+2008-07-22 00:45:46.741: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 00:45:46.741: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:45:46.742: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:45:46.742: debug: Signing zone "example.net."
+2008-07-22 00:45:46.742: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:45:47.013: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:45:47.013: debug: Signing completed after 1s.
+2008-07-22 00:45:47.013: notice: "example.net.": distribution triggered
+2008-07-22 00:45:47.013: debug: Distribute zone "example.net."
+2008-07-22 00:45:47.013: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-22 00:45:47.019: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-22 00:45:47.019: debug:
+2008-07-22 00:45:47.019: notice: end of run: 0 errors occured
+2008-07-22 00:48:02.761: notice: ------------------------------------------------------------
+2008-07-22 00:48:02.761: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 00:48:02.763: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:48:02.763: debug: Check RFC5011 status
+2008-07-22 00:48:02.763: debug: ->ksk5011status returns 0
+2008-07-22 00:48:02.763: debug: Check KSK status
+2008-07-22 00:48:02.763: debug: Check ZSK status
+2008-07-22 00:48:02.763: debug: Re-signing necessary: Option -f
+2008-07-22 00:48:02.763: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 00:48:02.763: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:48:02.763: debug: Signing zone "sub.example.net."
+2008-07-22 00:48:02.763: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:48:02.907: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:48:02.907: debug: Signing completed after 0s.
+2008-07-22 00:48:02.907: notice: "sub.example.net.": distribution triggered
+2008-07-22 00:48:02.907: debug: Distribute zone "sub.example.net."
+2008-07-22 00:48:02.907: debug:
+2008-07-22 00:48:02.907: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:48:02.907: debug: Check RFC5011 status
+2008-07-22 00:48:02.907: debug: ->ksk5011status returns 2
+2008-07-22 00:48:02.907: debug: Check ZSK status
+2008-07-22 00:48:02.907: debug: Re-signing necessary: Option -f
+2008-07-22 00:48:02.907: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 00:48:02.907: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:48:02.908: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:48:02.908: debug: Signing zone "example.net."
+2008-07-22 00:48:02.908: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:48:03.029: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:48:03.029: debug: Signing completed after 1s.
+2008-07-22 00:48:03.029: notice: "example.net.": distribution triggered
+2008-07-22 00:48:03.029: debug: Distribute zone "example.net."
+2008-07-22 00:48:03.029: debug:
+2008-07-22 00:48:03.029: notice: end of run: 0 errors occured
+2008-07-22 00:48:56.098: notice: ------------------------------------------------------------
+2008-07-22 00:48:56.098: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 00:48:56.100: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 00:48:56.101: debug: Check RFC5011 status
+2008-07-22 00:48:56.101: debug: ->ksk5011status returns 0
+2008-07-22 00:48:56.101: debug: Check KSK status
+2008-07-22 00:48:56.101: debug: Check ZSK status
+2008-07-22 00:48:56.101: debug: Re-signing necessary: Option -f
+2008-07-22 00:48:56.101: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 00:48:56.101: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 00:48:56.102: debug: Signing zone "sub.example.net."
+2008-07-22 00:48:56.102: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 00:48:56.244: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:48:56.244: debug: Signing completed after 0s.
+2008-07-22 00:48:56.244: notice: "sub.example.net.": distribution triggered
+2008-07-22 00:48:56.244: debug: Distribute zone "sub.example.net."
+2008-07-22 00:48:56.245: debug:
+2008-07-22 00:48:56.245: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 00:48:56.245: debug: Check RFC5011 status
+2008-07-22 00:48:56.245: debug: ->ksk5011status returns 2
+2008-07-22 00:48:56.245: debug: Check ZSK status
+2008-07-22 00:48:56.245: debug: Re-signing necessary: Option -f
+2008-07-22 00:48:56.245: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 00:48:56.246: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 00:48:56.246: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 00:48:56.246: debug: Signing zone "example.net."
+2008-07-22 00:48:56.247: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 00:48:56.367: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 00:48:56.367: debug: Signing completed after 0s.
+2008-07-22 00:48:56.367: notice: "example.net.": distribution triggered
+2008-07-22 00:48:56.367: debug: Distribute zone "example.net."
+2008-07-22 00:48:56.367: debug:
+2008-07-22 00:48:56.367: notice: end of run: 0 errors occured
+2008-07-22 08:07:30.993: notice: ------------------------------------------------------------
+2008-07-22 08:07:30.993: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 08:07:30.995: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 08:07:30.995: debug: Check RFC5011 status
+2008-07-22 08:07:30.995: debug: ->ksk5011status returns 0
+2008-07-22 08:07:30.995: debug: Check KSK status
+2008-07-22 08:07:30.995: debug: Check ZSK status
+2008-07-22 08:07:30.995: debug: Re-signing necessary: Option -f
+2008-07-22 08:07:30.996: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 08:07:30.996: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 08:07:30.996: debug: Signing zone "sub.example.net."
+2008-07-22 08:07:30.996: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 08:07:31.454: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 08:07:31.454: debug: Signing completed after 1s.
+2008-07-22 08:07:31.454: notice: "sub.example.net.": distribution triggered
+2008-07-22 08:07:31.454: debug: Distribute zone "sub.example.net."
+2008-07-22 08:07:31.454: debug:
+2008-07-22 08:07:31.454: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 08:07:31.454: debug: Check RFC5011 status
+2008-07-22 08:07:31.454: debug: ->ksk5011status returns 2
+2008-07-22 08:07:31.454: debug: Check ZSK status
+2008-07-22 08:07:31.454: debug: Re-signing necessary: Option -f
+2008-07-22 08:07:31.454: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 08:07:31.454: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 08:07:31.454: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 08:07:31.454: debug: Signing zone "example.net."
+2008-07-22 08:07:31.455: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 08:07:31.588: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 08:07:31.589: debug: Signing completed after 0s.
+2008-07-22 08:07:31.589: notice: "example.net.": distribution triggered
+2008-07-22 08:07:31.589: debug: Distribute zone "example.net."
+2008-07-22 08:07:31.589: debug:
+2008-07-22 08:07:31.589: notice: end of run: 0 errors occured
+2008-07-22 08:08:09.237: notice: ------------------------------------------------------------
+2008-07-22 08:08:09.237: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 08:08:09.239: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 08:08:09.239: debug: Check RFC5011 status
+2008-07-22 08:08:09.239: debug: ->ksk5011status returns 0
+2008-07-22 08:08:09.239: debug: Check KSK status
+2008-07-22 08:08:09.239: debug: Check ZSK status
+2008-07-22 08:08:09.239: debug: Re-signing necessary: Option -f
+2008-07-22 08:08:09.239: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 08:08:09.239: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 08:08:09.240: debug: Signing zone "sub.example.net."
+2008-07-22 08:08:09.240: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 08:08:09.506: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 08:08:09.507: debug: Signing completed after 0s.
+2008-07-22 08:08:09.507: notice: "sub.example.net.": distribution triggered
+2008-07-22 08:08:09.507: debug: Distribute zone "sub.example.net."
+2008-07-22 08:10:10.328: notice: ------------------------------------------------------------
+2008-07-22 08:10:10.328: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 08:10:10.330: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 08:10:10.330: debug: Check RFC5011 status
+2008-07-22 08:10:10.330: debug: ->ksk5011status returns 0
+2008-07-22 08:10:10.330: debug: Check KSK status
+2008-07-22 08:10:10.330: debug: Check ZSK status
+2008-07-22 08:10:10.330: debug: Re-signing necessary: Option -f
+2008-07-22 08:10:10.330: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 08:10:10.330: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 08:10:10.331: debug: Signing zone "sub.example.net."
+2008-07-22 08:10:10.331: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 08:10:10.950: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 08:10:10.950: debug: Signing completed after 0s.
+2008-07-22 08:10:10.950: notice: "sub.example.net.": distribution triggered
+2008-07-22 08:10:10.950: debug: Distribute zone "sub.example.net."
+2008-07-22 08:11:17.247: notice: ------------------------------------------------------------
+2008-07-22 08:11:17.247: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-22 08:11:17.249: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-22 08:11:17.250: debug: Check RFC5011 status
+2008-07-22 08:11:17.250: debug: ->ksk5011status returns 0
+2008-07-22 08:11:17.250: debug: Check KSK status
+2008-07-22 08:11:17.250: debug: Check ZSK status
+2008-07-22 08:11:17.250: debug: Re-signing necessary: Option -f
+2008-07-22 08:11:17.250: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-22 08:11:17.250: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-22 08:11:17.251: debug: Signing zone "sub.example.net."
+2008-07-22 08:11:17.251: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-22 08:11:17.883: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 08:11:17.883: debug: Signing completed after 0s.
+2008-07-22 08:11:17.883: notice: "sub.example.net.": distribution triggered
+2008-07-22 08:11:17.883: debug: Distribute zone "sub.example.net."
+2008-07-22 08:11:17.883: debug:
+2008-07-22 08:11:17.883: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-22 08:11:17.884: debug: Check RFC5011 status
+2008-07-22 08:11:17.884: debug: ->ksk5011status returns 2
+2008-07-22 08:11:17.884: debug: Check ZSK status
+2008-07-22 08:11:17.884: debug: Re-signing necessary: Option -f
+2008-07-22 08:11:17.884: notice: "example.net.": re-signing triggered: Option -f
+2008-07-22 08:11:17.884: debug: Writing key file "./example.net./dnskey.db"
+2008-07-22 08:11:17.884: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-22 08:11:17.884: debug: Signing zone "example.net."
+2008-07-22 08:11:17.884: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-22 08:11:18.005: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-22 08:11:18.005: debug: Signing completed after 1s.
+2008-07-22 08:11:18.006: notice: "example.net.": distribution triggered
+2008-07-22 08:11:18.006: debug: Distribute zone "example.net."
+2008-07-22 08:11:18.006: debug:
+2008-07-22 08:11:18.006: notice: end of run: 0 errors occured
+2008-07-24 00:13:56.493: notice: ------------------------------------------------------------
+2008-07-24 00:13:56.493: notice: running ../../dnssec-signer -v -v
+2008-07-24 00:13:56.495: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 00:13:56.495: debug: Check RFC5011 status
+2008-07-24 00:13:56.495: debug: ->ksk5011status returns 0
+2008-07-24 00:13:56.495: debug: Check KSK status
+2008-07-24 00:13:56.495: debug: Check ZSK status
+2008-07-24 00:13:56.495: debug: Re-signing necessary: re-signing interval (1d) reached
+2008-07-24 00:13:56.495: notice: "sub.example.net.": re-signing triggered: re-signing interval (1d) reached
+2008-07-24 00:13:56.495: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 00:13:56.495: debug: Signing zone "sub.example.net."
+2008-07-24 00:13:56.495: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 00:13:57.439: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:13:57.439: debug: Signing completed after 1s.
+2008-07-24 00:13:57.439: debug:
+2008-07-24 00:13:57.439: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 00:13:57.439: debug: Check RFC5011 status
+2008-07-24 00:13:57.439: debug: ->ksk5011status returns 2
+2008-07-24 00:13:57.439: debug: Check ZSK status
+2008-07-24 00:13:57.440: debug: Lifetime(1209600 +/-150 sec) of active key 16682 exceeded (1309537 sec)
+2008-07-24 00:13:57.440: debug: ->depreciate it
+2008-07-24 00:13:57.440: debug: ->activate published key 41300
+2008-07-24 00:13:57.440: notice: "example.net.": lifetime of zone signing key 16682 exceeded: ZSK rollover done
+2008-07-24 00:13:57.440: debug: Re-signing necessary: New zone key
+2008-07-24 00:13:57.440: notice: "example.net.": re-signing triggered: New zone key
+2008-07-24 00:13:57.441: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 00:13:57.441: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 00:13:57.441: debug: Signing zone "example.net."
+2008-07-24 00:13:57.442: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 00:13:57.562: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:13:57.562: debug: Signing completed after 0s.
+2008-07-24 00:13:57.562: debug:
+2008-07-24 00:13:57.562: notice: end of run: 0 errors occured
+2008-07-24 00:14:08.862: notice: ------------------------------------------------------------
+2008-07-24 00:14:08.862: notice: running ../../dnssec-signer -r -v -v
+2008-07-24 00:14:08.864: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 00:14:08.864: debug: Check RFC5011 status
+2008-07-24 00:14:08.864: debug: ->ksk5011status returns 0
+2008-07-24 00:14:08.864: debug: Check KSK status
+2008-07-24 00:14:08.864: debug: Check ZSK status
+2008-07-24 00:14:08.864: debug: Re-signing not necessary!
+2008-07-24 00:14:08.864: debug: Check if there is a parent file to copy
+2008-07-24 00:14:08.864: debug:
+2008-07-24 00:14:08.864: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 00:14:08.864: debug: Check RFC5011 status
+2008-07-24 00:14:08.864: debug: ->ksk5011status returns 2
+2008-07-24 00:14:08.864: debug: Check ZSK status
+2008-07-24 00:14:08.864: debug: Re-signing not necessary!
+2008-07-24 00:14:08.864: debug: Check if there is a parent file to copy
+2008-07-24 00:14:08.864: debug:
+2008-07-24 00:14:08.864: notice: end of run: 0 errors occured
+2008-07-24 00:14:12.963: notice: ------------------------------------------------------------
+2008-07-24 00:14:12.963: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-24 00:14:12.965: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 00:14:12.965: debug: Check RFC5011 status
+2008-07-24 00:14:12.965: debug: ->ksk5011status returns 0
+2008-07-24 00:14:12.965: debug: Check KSK status
+2008-07-24 00:14:12.965: debug: Check ZSK status
+2008-07-24 00:14:12.965: debug: Re-signing necessary: Option -f
+2008-07-24 00:14:12.965: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 00:14:12.966: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 00:14:12.966: debug: Signing zone "sub.example.net."
+2008-07-24 00:14:12.966: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 00:14:13.488: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:14:13.488: debug: Signing completed after 1s.
+2008-07-24 00:14:13.488: error: exec of distribution command Ìö÷¿ forbidden due to strange file mode settings
+2008-07-24 00:14:13.488: debug:
+2008-07-24 00:14:13.488: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 00:14:13.488: debug: Check RFC5011 status
+2008-07-24 00:14:13.488: debug: ->ksk5011status returns 2
+2008-07-24 00:14:13.488: debug: Check ZSK status
+2008-07-24 00:14:13.488: debug: Re-signing necessary: Option -f
+2008-07-24 00:14:13.488: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 00:14:13.488: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 00:14:13.489: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 00:14:13.489: debug: Signing zone "example.net."
+2008-07-24 00:14:13.489: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 00:14:13.601: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:14:13.601: debug: Signing completed after 0s.
+2008-07-24 00:14:13.601: error: exec of distribution command Ìö÷¿ forbidden due to strange file mode settings
+2008-07-24 00:14:13.602: debug:
+2008-07-24 00:14:13.602: notice: end of run: 2 errors occured
+2008-07-24 00:15:38.304: notice: ------------------------------------------------------------
+2008-07-24 00:15:38.304: notice: running ../../dnssec-signer -f -v -v
+2008-07-24 00:15:38.306: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 00:15:38.306: debug: Check RFC5011 status
+2008-07-24 00:15:38.307: debug: ->ksk5011status returns 0
+2008-07-24 00:15:38.307: debug: Check KSK status
+2008-07-24 00:15:38.307: debug: Check ZSK status
+2008-07-24 00:15:38.307: debug: Re-signing necessary: Option -f
+2008-07-24 00:15:38.307: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 00:15:38.307: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 00:15:38.308: debug: Signing zone "sub.example.net."
+2008-07-24 00:15:38.308: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 00:15:39.280: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:15:39.280: debug: Signing completed after 1s.
+2008-07-24 00:15:39.281: debug:
+2008-07-24 00:15:39.281: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 00:15:39.281: debug: Check RFC5011 status
+2008-07-24 00:15:39.281: debug: ->ksk5011status returns 2
+2008-07-24 00:15:39.281: debug: Check ZSK status
+2008-07-24 00:15:39.281: debug: Re-signing necessary: Option -f
+2008-07-24 00:15:39.281: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 00:15:39.281: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 00:15:39.282: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 00:15:39.282: debug: Signing zone "example.net."
+2008-07-24 00:15:39.282: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 00:15:39.402: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:15:39.402: debug: Signing completed after 0s.
+2008-07-24 00:15:39.403: debug:
+2008-07-24 00:15:39.403: notice: end of run: 0 errors occured
+2008-07-24 00:18:59.568: notice: ------------------------------------------------------------
+2008-07-24 00:18:59.568: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-24 00:18:59.570: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 00:18:59.573: debug: Check RFC5011 status
+2008-07-24 00:18:59.573: debug: ->ksk5011status returns 0
+2008-07-24 00:18:59.573: debug: Check KSK status
+2008-07-24 00:18:59.573: debug: Check ZSK status
+2008-07-24 00:18:59.573: debug: Re-signing necessary: Option -f
+2008-07-24 00:18:59.573: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 00:18:59.573: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 00:18:59.573: debug: Signing zone "sub.example.net."
+2008-07-24 00:18:59.573: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 00:19:00.167: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:19:00.167: debug: Signing completed after 1s.
+2008-07-24 00:19:00.168: error: exec of distribution command ./dist.sh forbidden due to strange file mode settings
+2008-07-24 00:19:00.168: debug:
+2008-07-24 00:19:00.168: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 00:19:00.168: debug: Check RFC5011 status
+2008-07-24 00:19:00.168: debug: ->ksk5011status returns 2
+2008-07-24 00:19:00.168: debug: Check ZSK status
+2008-07-24 00:19:00.168: debug: Re-signing necessary: Option -f
+2008-07-24 00:19:00.168: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 00:19:00.168: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 00:19:00.169: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 00:19:00.169: debug: Signing zone "example.net."
+2008-07-24 00:19:00.169: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 00:19:00.280: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:19:00.280: debug: Signing completed after 0s.
+2008-07-24 00:19:00.280: error: exec of distribution command ./dist.sh forbidden due to strange file mode settings
+2008-07-24 00:19:00.280: debug:
+2008-07-24 00:19:00.280: notice: end of run: 2 errors occured
+2008-07-24 00:22:24.567: notice: ------------------------------------------------------------
+2008-07-24 00:22:24.567: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-24 00:22:24.569: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 00:22:24.569: debug: Check RFC5011 status
+2008-07-24 00:22:24.569: debug: ->ksk5011status returns 0
+2008-07-24 00:22:24.569: debug: Check KSK status
+2008-07-24 00:22:24.570: debug: Check ZSK status
+2008-07-24 00:22:24.570: debug: Re-signing necessary: Option -f
+2008-07-24 00:22:24.570: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 00:22:24.570: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 00:22:24.570: debug: Signing zone "sub.example.net."
+2008-07-24 00:22:24.571: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 00:22:25.147: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:22:25.148: debug: Signing completed after 1s.
+2008-07-24 00:22:25.148: error: exec of distribution command ./dist.sh forbidden due to strange file mode settings
+2008-07-24 00:22:25.148: debug: not running distribution command ./dist.sh because of strange file mode settings
+2008-07-24 00:22:25.148: debug:
+2008-07-24 00:22:25.148: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 00:22:25.148: debug: Check RFC5011 status
+2008-07-24 00:22:25.148: debug: ->ksk5011status returns 2
+2008-07-24 00:22:25.148: debug: Check ZSK status
+2008-07-24 00:22:25.149: debug: Re-signing necessary: Option -f
+2008-07-24 00:22:25.149: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 00:22:25.149: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 00:22:25.150: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 00:22:25.150: debug: Signing zone "example.net."
+2008-07-24 00:22:25.150: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 00:22:25.271: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:22:25.271: debug: Signing completed after 0s.
+2008-07-24 00:22:25.271: error: exec of distribution command ./dist.sh forbidden due to strange file mode settings
+2008-07-24 00:22:25.271: debug: not running distribution command ./dist.sh because of strange file mode settings
+2008-07-24 00:22:25.271: debug:
+2008-07-24 00:22:25.271: notice: end of run: 2 errors occured
+2008-07-24 00:23:08.907: notice: ------------------------------------------------------------
+2008-07-24 00:23:08.907: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-24 00:23:08.909: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 00:23:08.909: debug: Check RFC5011 status
+2008-07-24 00:23:08.909: debug: ->ksk5011status returns 0
+2008-07-24 00:23:08.909: debug: Check KSK status
+2008-07-24 00:23:08.909: debug: Check ZSK status
+2008-07-24 00:23:08.909: debug: Re-signing necessary: Option -f
+2008-07-24 00:23:08.909: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 00:23:08.909: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 00:23:08.910: debug: Signing zone "sub.example.net."
+2008-07-24 00:23:08.910: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 00:23:09.510: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:23:09.510: debug: Signing completed after 1s.
+2008-07-24 00:23:09.511: notice: "sub.example.net.": distribution triggered
+2008-07-24 00:23:09.511: debug: Distribute zone "sub.example.net."
+2008-07-24 00:23:09.511: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 00:23:09.517: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-24 00:23:09.517: debug:
+2008-07-24 00:23:09.517: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 00:23:09.517: debug: Check RFC5011 status
+2008-07-24 00:23:09.517: debug: ->ksk5011status returns 2
+2008-07-24 00:23:09.517: debug: Check ZSK status
+2008-07-24 00:23:09.517: debug: Re-signing necessary: Option -f
+2008-07-24 00:23:09.517: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 00:23:09.517: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 00:23:09.518: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 00:23:09.518: debug: Signing zone "example.net."
+2008-07-24 00:23:09.518: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 00:23:09.633: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:23:09.633: debug: Signing completed after 0s.
+2008-07-24 00:23:09.634: notice: "example.net.": distribution triggered
+2008-07-24 00:23:09.634: debug: Distribute zone "example.net."
+2008-07-24 00:23:09.634: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-24 00:23:09.640: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-24 00:23:09.640: debug:
+2008-07-24 00:23:09.640: notice: end of run: 0 errors occured
+2008-07-24 00:33:30.818: notice: ------------------------------------------------------------
+2008-07-24 00:33:30.818: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-24 00:33:30.820: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 00:33:30.820: debug: Check RFC5011 status
+2008-07-24 00:33:30.821: debug: ->ksk5011status returns 0
+2008-07-24 00:33:30.821: debug: Check KSK status
+2008-07-24 00:33:30.821: debug: Check ZSK status
+2008-07-24 00:33:30.821: debug: Re-signing necessary: Option -f
+2008-07-24 00:33:30.821: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 00:33:30.821: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 00:33:30.822: debug: Signing zone "sub.example.net."
+2008-07-24 00:33:30.822: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 00:33:31.320: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:33:31.320: debug: Signing completed after 1s.
+2008-07-24 00:33:31.320: error: exec of distribution command ./dist.sh forbidden due to running as root
+2008-07-24 00:33:31.320: debug: Not running distribution command ./dist.sh as root
+2008-07-24 00:33:31.320: debug:
+2008-07-24 00:33:31.320: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 00:33:31.320: debug: Check RFC5011 status
+2008-07-24 00:33:31.320: debug: ->ksk5011status returns 2
+2008-07-24 00:33:31.320: debug: Check ZSK status
+2008-07-24 00:33:31.320: debug: Re-signing necessary: Option -f
+2008-07-24 00:33:31.320: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 00:33:31.320: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 00:33:31.321: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 00:33:31.321: debug: Signing zone "example.net."
+2008-07-24 00:33:31.321: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 00:33:31.443: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 00:33:31.443: debug: Signing completed after 0s.
+2008-07-24 00:33:31.443: error: exec of distribution command ./dist.sh forbidden due to running as root
+2008-07-24 00:33:31.443: debug: Not running distribution command ./dist.sh as root
+2008-07-24 00:33:31.443: debug:
+2008-07-24 00:33:31.443: notice: end of run: 2 errors occured
+2008-07-24 23:21:55.189: notice: ------------------------------------------------------------
+2008-07-24 23:21:55.189: notice: running ../../dnssec-signer -r -v -v
+2008-07-24 23:21:55.196: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:21:55.196: debug: Check RFC5011 status
+2008-07-24 23:21:55.196: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:21:55.196: debug: Check KSK status
+2008-07-24 23:21:55.196: debug: Check ZSK status
+2008-07-24 23:21:55.196: debug: Re-signing not necessary!
+2008-07-24 23:21:55.196: debug: Check if there is a parent file to copy
+2008-07-24 23:21:55.196: debug:
+2008-07-24 23:21:55.196: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:21:55.196: debug: Check RFC5011 status
+2008-07-24 23:21:55.196: debug: Check ZSK status
+2008-07-24 23:21:55.196: debug: Lifetime(29100 sec) of depreciated key 16682 exceeded (83278 sec)
+2008-07-24 23:21:55.196: info: "example.net.": old ZSK 16682 removed
+2008-07-24 23:21:55.196: debug: ->remove it
+2008-07-24 23:21:55.196: debug: Re-signing necessary: New zone key
+2008-07-24 23:21:55.197: notice: "example.net.": re-signing triggered: New zone key
+2008-07-24 23:21:55.197: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 23:21:55.197: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 23:21:55.197: debug: Signing zone "example.net."
+2008-07-24 23:21:55.197: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 23:21:55.873: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:21:55.873: debug: Signing completed after 0s.
+2008-07-24 23:21:55.873: debug: Distribution command ./dist.sh not run as root
+2008-07-24 23:21:55.873: error: exec of distribution command ./dist.sh suppressed because of security reasons
+2008-07-24 23:21:55.873: debug:
+2008-07-24 23:21:55.874: notice: end of run: 1 error occured
+2008-07-24 23:23:06.278: notice: ------------------------------------------------------------
+2008-07-24 23:23:06.278: notice: running ../../dnssec-signer -r -v -v
+2008-07-24 23:23:06.279: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:23:06.280: debug: Check RFC5011 status
+2008-07-24 23:23:06.280: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:23:06.280: debug: Check KSK status
+2008-07-24 23:23:06.280: debug: Check ZSK status
+2008-07-24 23:23:06.280: debug: Re-signing not necessary!
+2008-07-24 23:23:06.280: debug: Check if there is a parent file to copy
+2008-07-24 23:23:06.280: debug:
+2008-07-24 23:23:06.280: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:23:06.280: debug: Check RFC5011 status
+2008-07-24 23:23:06.280: debug: Check ZSK status
+2008-07-24 23:23:06.280: debug: Re-signing not necessary!
+2008-07-24 23:23:06.280: debug: Check if there is a parent file to copy
+2008-07-24 23:23:06.280: debug:
+2008-07-24 23:23:06.280: notice: end of run: 0 errors occured
+2008-07-24 23:25:21.930: notice: ------------------------------------------------------------
+2008-07-24 23:25:21.930: notice: running ../../dnssec-signer -r -v -v
+2008-07-24 23:25:21.932: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:25:21.932: debug: Check RFC5011 status
+2008-07-24 23:25:21.932: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:25:21.932: debug: Check KSK status
+2008-07-24 23:25:21.932: debug: Check ZSK status
+2008-07-24 23:25:21.932: debug: Re-signing not necessary!
+2008-07-24 23:25:21.932: debug: Check if there is a parent file to copy
+2008-07-24 23:25:21.932: debug:
+2008-07-24 23:25:21.932: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:25:21.932: debug: Check RFC5011 status
+2008-07-24 23:25:21.932: debug: Check ZSK status
+2008-07-24 23:25:21.932: debug: Re-signing not necessary!
+2008-07-24 23:25:21.932: debug: Check if there is a parent file to copy
+2008-07-24 23:25:21.932: debug:
+2008-07-24 23:25:21.932: notice: end of run: 0 errors occured
+2008-07-24 23:25:39.009: notice: ------------------------------------------------------------
+2008-07-24 23:25:39.009: notice: running ../../dnssec-signer -f -r -v -v
+2008-07-24 23:25:39.011: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:25:39.011: debug: Check RFC5011 status
+2008-07-24 23:25:39.011: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:25:39.011: debug: Check KSK status
+2008-07-24 23:25:39.011: debug: Check ZSK status
+2008-07-24 23:25:39.011: debug: Re-signing necessary: Option -f
+2008-07-24 23:25:39.011: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 23:25:39.011: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 23:25:39.011: debug: Signing zone "sub.example.net."
+2008-07-24 23:25:39.012: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 23:25:39.591: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:25:39.591: debug: Signing completed after 0s.
+2008-07-24 23:25:39.591: debug: Distribution command ./dist.sh not run as root
+2008-07-24 23:25:39.591: error: exec of distribution command ./dist.sh suppressed because of security reasons
+2008-07-24 23:25:39.592: debug:
+2008-07-24 23:25:39.592: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:25:39.592: debug: Check RFC5011 status
+2008-07-24 23:25:39.592: debug: Check ZSK status
+2008-07-24 23:25:39.592: debug: Re-signing necessary: Option -f
+2008-07-24 23:25:39.592: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 23:25:39.592: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 23:25:39.592: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 23:25:39.592: debug: Signing zone "example.net."
+2008-07-24 23:25:39.592: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 23:25:39.703: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:25:39.703: debug: Signing completed after 0s.
+2008-07-24 23:25:39.703: debug: Distribution command ./dist.sh not run as root
+2008-07-24 23:25:39.703: error: exec of distribution command ./dist.sh suppressed because of security reasons
+2008-07-24 23:25:39.703: debug:
+2008-07-24 23:25:39.703: notice: end of run: 2 errors occured
+2008-07-24 23:28:16.436: notice: ------------------------------------------------------------
+2008-07-24 23:28:16.436: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-24 23:28:16.438: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:28:16.438: debug: Check RFC5011 status
+2008-07-24 23:28:16.438: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:28:16.438: debug: Check KSK status
+2008-07-24 23:28:16.438: debug: Check ZSK status
+2008-07-24 23:28:16.438: debug: Re-signing necessary: Option -f
+2008-07-24 23:28:16.438: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 23:28:16.438: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 23:28:16.438: debug: Signing zone "sub.example.net."
+2008-07-24 23:28:16.439: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 23:28:17.008: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:28:17.008: debug: Signing completed after 1s.
+2008-07-24 23:28:17.009: notice: "sub.example.net.": distribution triggered
+2008-07-24 23:28:17.009: debug: Distribute zone "sub.example.net."
+2008-07-24 23:28:17.009: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:28:17.015: debug: ./dist.sh reload return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-24 23:28:17.015: debug:
+2008-07-24 23:28:17.015: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:28:17.015: debug: Check RFC5011 status
+2008-07-24 23:28:17.015: debug: Check ZSK status
+2008-07-24 23:28:17.015: debug: Re-signing necessary: Option -f
+2008-07-24 23:28:17.015: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 23:28:17.015: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 23:28:17.016: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 23:28:17.016: debug: Signing zone "example.net."
+2008-07-24 23:28:17.016: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 23:28:17.132: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:28:17.132: debug: Signing completed after 0s.
+2008-07-24 23:28:17.132: notice: "example.net.": distribution triggered
+2008-07-24 23:28:17.132: debug: Distribute zone "example.net."
+2008-07-24 23:28:17.132: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-24 23:28:17.138: debug: ./dist.sh reload return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-24 23:28:17.138: debug:
+2008-07-24 23:28:17.138: notice: end of run: 0 errors occured
+2008-07-24 23:31:17.354: notice: ------------------------------------------------------------
+2008-07-24 23:31:17.354: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-24 23:31:17.364: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:31:17.364: debug: Check RFC5011 status
+2008-07-24 23:31:17.364: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:31:17.364: debug: Check KSK status
+2008-07-24 23:31:17.364: debug: Check ZSK status
+2008-07-24 23:31:17.364: debug: Re-signing necessary: Option -f
+2008-07-24 23:31:17.364: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 23:31:17.364: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 23:31:17.364: debug: Signing zone "sub.example.net."
+2008-07-24 23:31:17.364: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 23:31:18.032: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:31:18.032: debug: Signing completed after 1s.
+2008-07-24 23:31:18.032: notice: "sub.example.net.": distribution triggered
+2008-07-24 23:31:18.032: debug: Distribute zone "sub.example.net."
+2008-07-24 23:31:18.032: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:31:18.039: debug: ./dist.sh reload return: "rndc reload "
+2008-07-24 23:31:18.039: debug:
+2008-07-24 23:31:18.039: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:31:18.039: debug: Check RFC5011 status
+2008-07-24 23:31:18.039: debug: Check ZSK status
+2008-07-24 23:31:18.039: debug: Re-signing necessary: Option -f
+2008-07-24 23:31:18.039: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 23:31:18.039: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 23:31:18.040: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 23:31:18.040: debug: Signing zone "example.net."
+2008-07-24 23:31:18.040: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 23:31:18.155: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:31:18.155: debug: Signing completed after 0s.
+2008-07-24 23:31:18.155: notice: "example.net.": distribution triggered
+2008-07-24 23:31:18.155: debug: Distribute zone "example.net."
+2008-07-24 23:31:18.155: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-24 23:31:18.161: debug: ./dist.sh reload return: "rndc reload "
+2008-07-24 23:31:18.161: debug:
+2008-07-24 23:31:18.162: notice: end of run: 0 errors occured
+2008-07-24 23:31:28.467: notice: ------------------------------------------------------------
+2008-07-24 23:31:28.467: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-24 23:31:28.470: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:31:28.470: debug: Check RFC5011 status
+2008-07-24 23:31:28.470: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:31:28.470: debug: Check KSK status
+2008-07-24 23:31:28.470: debug: Check ZSK status
+2008-07-24 23:31:28.470: debug: Re-signing necessary: Option -f
+2008-07-24 23:31:28.470: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 23:31:28.470: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 23:31:28.471: debug: Signing zone "sub.example.net."
+2008-07-24 23:31:28.471: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 23:31:29.058: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:31:29.059: debug: Signing completed after 1s.
+2008-07-24 23:31:29.059: notice: "sub.example.net.": distribution triggered
+2008-07-24 23:31:29.059: debug: Distribute zone "sub.example.net."
+2008-07-24 23:31:29.059: debug: Run cmd "./dist.sh distribute sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:31:29.066: debug: ./dist.sh distribute return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-24 23:31:29.066: notice: scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./: distribution triggered
+2008-07-24 23:31:29.066: debug: Distribute zone scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./
+2008-07-24 23:31:29.066: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:31:29.072: debug: ./dist.sh reload return: "rndc reload "
+2008-07-24 23:31:29.072: debug:
+2008-07-24 23:31:29.073: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:31:29.073: debug: Check RFC5011 status
+2008-07-24 23:31:29.073: debug: Check ZSK status
+2008-07-24 23:31:29.073: debug: Re-signing necessary: Option -f
+2008-07-24 23:31:29.073: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 23:31:29.073: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 23:31:29.074: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 23:31:29.074: debug: Signing zone "example.net."
+2008-07-24 23:31:29.075: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 23:31:29.204: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:31:29.204: debug: Signing completed after 0s.
+2008-07-24 23:31:29.204: notice: "example.net.": distribution triggered
+2008-07-24 23:31:29.204: debug: Distribute zone "example.net."
+2008-07-24 23:31:29.205: debug: Run cmd "./dist.sh distribute example.net. ./example.net./zone.db.signed"
+2008-07-24 23:31:29.211: debug: ./dist.sh distribute return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-24 23:31:29.211: notice: scp ./example.net./zone.db.signed localhost:/var/named/example.net./: distribution triggered
+2008-07-24 23:31:29.211: debug: Distribute zone scp ./example.net./zone.db.signed localhost:/var/named/example.net./
+2008-07-24 23:31:29.211: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-24 23:31:29.217: debug: ./dist.sh reload return: "rndc reload "
+2008-07-24 23:31:29.217: debug:
+2008-07-24 23:31:29.217: notice: end of run: 0 errors occured
+2008-07-24 23:35:48.844: notice: ------------------------------------------------------------
+2008-07-24 23:35:48.844: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-24 23:35:48.846: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:35:48.846: debug: Check RFC5011 status
+2008-07-24 23:35:48.846: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:35:48.846: debug: Check KSK status
+2008-07-24 23:35:48.846: debug: Check ZSK status
+2008-07-24 23:35:48.846: debug: Re-signing necessary: Option -f
+2008-07-24 23:35:48.846: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 23:35:48.846: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 23:35:48.846: debug: Signing zone "sub.example.net."
+2008-07-24 23:35:48.846: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 23:35:49.455: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:35:49.455: debug: Signing completed after 1s.
+2008-07-24 23:35:49.455: notice: "sub.example.net.": distribution triggered
+2008-07-24 23:35:49.455: debug: Distribute zone "sub.example.net."
+2008-07-24 23:35:49.455: debug: Run cmd "./dist.sh distribute sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:35:49.462: notice: "sub.example.net.": distribution triggered
+2008-07-24 23:35:49.462: debug: Distribute zone "sub.example.net."
+2008-07-24 23:35:49.462: debug: ./dist.sh distribute return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-24 23:35:49.462: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:35:49.468: notice: "sub.example.net.": reload triggered
+2008-07-24 23:35:49.468: debug: Reload zone "sub.example.net."
+2008-07-24 23:35:49.468: debug: ./dist.sh reload return: "rndc reload "
+2008-07-24 23:35:49.468: debug:
+2008-07-24 23:35:49.468: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:35:49.468: debug: Check RFC5011 status
+2008-07-24 23:35:49.469: debug: Check ZSK status
+2008-07-24 23:35:49.469: debug: Re-signing necessary: Option -f
+2008-07-24 23:35:49.469: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 23:35:49.469: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 23:35:49.470: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 23:35:49.470: debug: Signing zone "example.net."
+2008-07-24 23:35:49.470: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 23:35:49.600: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:35:49.600: debug: Signing completed after 0s.
+2008-07-24 23:35:49.600: notice: "example.net.": distribution triggered
+2008-07-24 23:35:49.600: debug: Distribute zone "example.net."
+2008-07-24 23:35:49.600: debug: Run cmd "./dist.sh distribute example.net. ./example.net./zone.db.signed"
+2008-07-24 23:35:49.606: notice: "example.net.": distribution triggered
+2008-07-24 23:35:49.606: debug: Distribute zone "example.net."
+2008-07-24 23:35:49.606: debug: ./dist.sh distribute return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-24 23:35:49.606: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-24 23:35:49.613: notice: "example.net.": reload triggered
+2008-07-24 23:35:49.613: debug: Reload zone "example.net."
+2008-07-24 23:35:49.613: debug: ./dist.sh reload return: "rndc reload "
+2008-07-24 23:35:49.613: debug:
+2008-07-24 23:35:49.613: notice: end of run: 0 errors occured
+2008-07-24 23:37:41.081: notice: ------------------------------------------------------------
+2008-07-24 23:37:41.081: notice: running ../../dnssec-signer -r -f -v -v
+2008-07-24 23:37:41.083: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:37:41.083: debug: Check RFC5011 status
+2008-07-24 23:37:41.083: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:37:41.083: debug: Check KSK status
+2008-07-24 23:37:41.083: debug: Check ZSK status
+2008-07-24 23:37:41.083: debug: Re-signing necessary: Option -f
+2008-07-24 23:37:41.083: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 23:37:41.083: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 23:37:41.084: debug: Signing zone "sub.example.net."
+2008-07-24 23:37:41.084: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 23:37:41.688: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:37:41.688: debug: Signing completed after 0s.
+2008-07-24 23:37:41.689: notice: "sub.example.net.": distribution triggered
+2008-07-24 23:37:41.689: debug: Distribute zone "sub.example.net."
+2008-07-24 23:37:41.689: debug: Run cmd "./dist.sh distribute sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:37:41.695: debug: ./dist.sh distribute return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-24 23:37:41.695: notice: "sub.example.net.": reload triggered
+2008-07-24 23:37:41.695: debug: Reload zone "sub.example.net."
+2008-07-24 23:37:41.695: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:37:41.701: debug: ./dist.sh reload return: "rndc reload "
+2008-07-24 23:37:41.701: debug:
+2008-07-24 23:37:41.701: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:37:41.701: debug: Check RFC5011 status
+2008-07-24 23:37:41.701: debug: Check ZSK status
+2008-07-24 23:37:41.701: debug: Re-signing necessary: Option -f
+2008-07-24 23:37:41.701: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 23:37:41.701: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 23:37:41.702: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 23:37:41.702: debug: Signing zone "example.net."
+2008-07-24 23:37:41.702: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 23:37:41.823: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:37:41.824: debug: Signing completed after 0s.
+2008-07-24 23:37:41.824: notice: "example.net.": distribution triggered
+2008-07-24 23:37:41.824: debug: Distribute zone "example.net."
+2008-07-24 23:37:41.824: debug: Run cmd "./dist.sh distribute example.net. ./example.net./zone.db.signed"
+2008-07-24 23:37:41.830: debug: ./dist.sh distribute return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-24 23:37:41.831: notice: "example.net.": reload triggered
+2008-07-24 23:37:41.831: debug: Reload zone "example.net."
+2008-07-24 23:37:41.831: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-24 23:37:41.837: debug: ./dist.sh reload return: "rndc reload "
+2008-07-24 23:37:41.837: debug:
+2008-07-24 23:37:41.837: notice: end of run: 0 errors occured
+2008-07-24 23:37:51.742: notice: ------------------------------------------------------------
+2008-07-24 23:37:51.742: notice: running ../../dnssec-signer -r -f -v
+2008-07-24 23:37:51.744: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:37:51.744: debug: Check RFC5011 status
+2008-07-24 23:37:51.744: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:37:51.744: debug: Check KSK status
+2008-07-24 23:37:51.744: debug: Check ZSK status
+2008-07-24 23:37:51.744: debug: Re-signing necessary: Option -f
+2008-07-24 23:37:51.744: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 23:37:51.744: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 23:37:51.745: debug: Signing zone "sub.example.net."
+2008-07-24 23:37:51.745: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 23:37:52.263: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:37:52.264: debug: Signing completed after 1s.
+2008-07-24 23:37:52.264: notice: "sub.example.net.": distribution triggered
+2008-07-24 23:37:52.264: debug: Distribute zone "sub.example.net."
+2008-07-24 23:37:52.264: debug: Run cmd "./dist.sh distribute sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:37:52.270: debug: ./dist.sh distribute return: "scp ./sub.example.net./zone.db.signed localhost:/var/named/sub.example.net./"
+2008-07-24 23:37:52.271: notice: "sub.example.net.": reload triggered
+2008-07-24 23:37:52.271: debug: Reload zone "sub.example.net."
+2008-07-24 23:37:52.271: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:37:52.276: debug: ./dist.sh reload return: "rndc reload "
+2008-07-24 23:37:52.277: debug:
+2008-07-24 23:37:52.277: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:37:52.277: debug: Check RFC5011 status
+2008-07-24 23:37:52.277: debug: Check ZSK status
+2008-07-24 23:37:52.277: debug: Re-signing necessary: Option -f
+2008-07-24 23:37:52.277: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 23:37:52.277: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 23:37:52.277: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 23:37:52.277: debug: Signing zone "example.net."
+2008-07-24 23:37:52.277: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-24 23:37:52.397: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-24 23:37:52.398: debug: Signing completed after 0s.
+2008-07-24 23:37:52.398: notice: "example.net.": distribution triggered
+2008-07-24 23:37:52.398: debug: Distribute zone "example.net."
+2008-07-24 23:37:52.398: debug: Run cmd "./dist.sh distribute example.net. ./example.net./zone.db.signed"
+2008-07-24 23:37:52.404: debug: ./dist.sh distribute return: "scp ./example.net./zone.db.signed localhost:/var/named/example.net./"
+2008-07-24 23:37:52.404: notice: "example.net.": reload triggered
+2008-07-24 23:37:52.404: debug: Reload zone "example.net."
+2008-07-24 23:37:52.404: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-24 23:37:52.410: debug: ./dist.sh reload return: "rndc reload "
+2008-07-24 23:37:52.410: debug:
+2008-07-24 23:37:52.410: notice: end of run: 0 errors occured
+2008-07-24 23:44:51.717: notice: ------------------------------------------------------------
+2008-07-24 23:44:51.717: notice: running ../../dnssec-signer -n -r -f -v
+2008-07-24 23:44:51.719: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:44:51.719: debug: Check RFC5011 status
+2008-07-24 23:44:51.719: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:44:51.719: debug: Check KSK status
+2008-07-24 23:44:51.720: debug: Check ZSK status
+2008-07-24 23:44:51.720: debug: Re-signing necessary: Option -f
+2008-07-24 23:44:51.720: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 23:44:51.720: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 23:44:51.720: debug: Signing zone "sub.example.net."
+2008-07-24 23:44:51.720: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 23:44:51.720: debug: Cmd dnssec-signzone return: ""
+2008-07-24 23:44:51.720: debug: Signing completed after 0s.
+2008-07-24 23:44:51.721: notice: "sub.example.net.": distribution triggered
+2008-07-24 23:44:51.721: debug: Distribute zone "sub.example.net."
+2008-07-24 23:44:51.721: debug: Run cmd "./dist.sh distribute sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:44:51.721: debug: ./dist.sh distribute return: ""
+2008-07-24 23:44:51.721: notice: "sub.example.net.": reload triggered
+2008-07-24 23:44:51.721: debug: Reload zone "sub.example.net."
+2008-07-24 23:44:51.721: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:44:51.721: debug: ./dist.sh reload return: ""
+2008-07-24 23:44:51.721: debug:
+2008-07-24 23:44:51.721: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:44:51.721: debug: Check RFC5011 status
+2008-07-24 23:44:51.721: debug: Check ZSK status
+2008-07-24 23:44:51.721: debug: Re-signing necessary: Option -f
+2008-07-24 23:44:51.722: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 23:44:51.722: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 23:44:51.722: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 23:44:51.722: notice: "example.net.": distribution triggered
+2008-07-24 23:44:51.722: debug: Distribute zone "example.net."
+2008-07-24 23:44:51.722: debug: Run cmd "./dist.sh distribute example.net. ./example.net./zone.db.signed"
+2008-07-24 23:44:51.722: debug: ./dist.sh distribute return: ""
+2008-07-24 23:44:51.722: notice: "example.net.": reload triggered
+2008-07-24 23:44:51.722: debug: Reload zone "example.net."
+2008-07-24 23:44:51.722: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-24 23:44:51.722: debug: ./dist.sh reload return: ""
+2008-07-24 23:44:51.723: debug:
+2008-07-24 23:44:51.723: notice: end of run: 0 errors occured
+2008-07-24 23:44:57.039: notice: ------------------------------------------------------------
+2008-07-24 23:44:57.040: notice: running ../../dnssec-signer -n -r -f -v -v
+2008-07-24 23:44:57.042: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-24 23:44:57.042: debug: Check RFC5011 status
+2008-07-24 23:44:57.042: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-24 23:44:57.042: debug: Check KSK status
+2008-07-24 23:44:57.042: debug: Check ZSK status
+2008-07-24 23:44:57.042: debug: Re-signing necessary: Option -f
+2008-07-24 23:44:57.042: notice: "sub.example.net.": re-signing triggered: Option -f
+2008-07-24 23:44:57.042: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-24 23:44:57.042: debug: Signing zone "sub.example.net."
+2008-07-24 23:44:57.042: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-24 23:44:57.042: debug: Cmd dnssec-signzone return: ""
+2008-07-24 23:44:57.042: debug: Signing completed after 0s.
+2008-07-24 23:44:57.042: notice: "sub.example.net.": distribution triggered
+2008-07-24 23:44:57.042: debug: Distribute zone "sub.example.net."
+2008-07-24 23:44:57.042: debug: Run cmd "./dist.sh distribute sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:44:57.042: debug: ./dist.sh distribute return: ""
+2008-07-24 23:44:57.043: notice: "sub.example.net.": reload triggered
+2008-07-24 23:44:57.043: debug: Reload zone "sub.example.net."
+2008-07-24 23:44:57.043: debug: Run cmd "./dist.sh reload sub.example.net. ./sub.example.net./zone.db.signed"
+2008-07-24 23:44:57.043: debug: ./dist.sh reload return: ""
+2008-07-24 23:44:57.043: debug:
+2008-07-24 23:44:57.043: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-24 23:44:57.043: debug: Check RFC5011 status
+2008-07-24 23:44:57.043: debug: Check ZSK status
+2008-07-24 23:44:57.043: debug: Re-signing necessary: Option -f
+2008-07-24 23:44:57.043: notice: "example.net.": re-signing triggered: Option -f
+2008-07-24 23:44:57.043: debug: Writing key file "./example.net./dnskey.db"
+2008-07-24 23:44:57.043: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-24 23:44:57.043: notice: "example.net.": distribution triggered
+2008-07-24 23:44:57.043: debug: Distribute zone "example.net."
+2008-07-24 23:44:57.043: debug: Run cmd "./dist.sh distribute example.net. ./example.net./zone.db.signed"
+2008-07-24 23:44:57.043: debug: ./dist.sh distribute return: ""
+2008-07-24 23:44:57.043: notice: "example.net.": reload triggered
+2008-07-24 23:44:57.043: debug: Reload zone "example.net."
+2008-07-24 23:44:57.043: debug: Run cmd "./dist.sh reload example.net. ./example.net./zone.db.signed"
+2008-07-24 23:44:57.043: debug: ./dist.sh reload return: ""
+2008-07-24 23:44:57.043: debug:
+2008-07-24 23:44:57.043: notice: end of run: 0 errors occured
+2008-07-25 23:31:07.235: notice: ------------------------------------------------------------
+2008-07-25 23:31:07.236: notice: running ../../dnssec-signer -v -v
+2008-07-25 23:31:07.238: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-25 23:31:07.238: debug: Check RFC5011 status
+2008-07-25 23:31:07.238: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-25 23:31:07.238: debug: Check KSK status
+2008-07-25 23:31:07.238: debug: Check ZSK status
+2008-07-25 23:31:07.238: debug: Lifetime(259200 +/-150 sec) of active key 31081 exceeded (343229 sec)
+2008-07-25 23:31:07.239: debug: ->depreciate it
+2008-07-25 23:31:07.239: debug: ->activate published key 3615
+2008-07-25 23:31:07.239: notice: "sub.example.net.": lifetime of zone signing key 31081 exceeded: ZSK rollover done
+2008-07-25 23:31:07.239: debug: New published key needed
+2008-07-25 23:31:07.397: debug: ->creating new published key 4254
+2008-07-25 23:31:07.397: info: "sub.example.net.": new key 4254 generated for publishing
+2008-07-25 23:31:07.397: debug: Re-signing necessary: New zone key
+2008-07-25 23:31:07.397: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-07-25 23:31:07.398: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-25 23:31:07.398: debug: Signing zone "sub.example.net."
+2008-07-25 23:31:07.398: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-25 23:31:07.639: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-25 23:31:07.639: debug: Signing completed after 0s.
+2008-07-25 23:31:07.639: debug:
+2008-07-25 23:31:07.639: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-25 23:31:07.639: debug: Check RFC5011 status
+2008-07-25 23:31:07.639: debug: Check ZSK status
+2008-07-25 23:31:07.639: debug: Re-signing necessary: Modified keys
+2008-07-25 23:31:07.639: notice: "example.net.": re-signing triggered: Modified keys
+2008-07-25 23:31:07.639: debug: Writing key file "./example.net./dnskey.db"
+2008-07-25 23:31:07.640: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-25 23:31:07.640: debug: Signing zone "example.net."
+2008-07-25 23:31:07.640: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-25 23:31:07.783: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-25 23:31:07.783: debug: Signing completed after 0s.
+2008-07-25 23:31:07.783: debug:
+2008-07-25 23:31:07.783: notice: end of run: 0 errors occured
+2008-07-25 23:32:27.052: notice: ------------------------------------------------------------
+2008-07-25 23:32:27.052: notice: running ../../dnssec-signer -v -v
+2008-07-25 23:32:27.054: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-25 23:32:27.054: debug: Check RFC5011 status
+2008-07-25 23:32:27.054: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-25 23:32:27.054: debug: Check KSK status
+2008-07-25 23:32:27.054: debug: Check ZSK status
+2008-07-25 23:32:27.054: debug: Re-signing not necessary!
+2008-07-25 23:32:27.054: debug: Check if there is a parent file to copy
+2008-07-25 23:32:27.054: debug:
+2008-07-25 23:32:27.054: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-25 23:32:27.054: debug: Check RFC5011 status
+2008-07-25 23:32:27.054: debug: Check ZSK status
+2008-07-25 23:32:27.054: debug: Re-signing not necessary!
+2008-07-25 23:32:27.054: debug: Check if there is a parent file to copy
+2008-07-25 23:32:27.057: debug:
+2008-07-25 23:32:27.057: notice: end of run: 0 errors occured
+2008-07-31 00:25:52.601: notice: ------------------------------------------------------------
+2008-07-31 00:25:52.601: notice: running ../../dnssec-signer -v -v
+2008-07-31 00:25:52.604: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-31 00:25:52.604: debug: Check RFC5011 status
+2008-07-31 00:25:52.604: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-31 00:25:52.604: debug: Check KSK status
+2008-07-31 00:25:52.604: debug: Check ZSK status
+2008-07-31 00:25:52.604: debug: Lifetime(390 sec) of depreciated key 31081 exceeded (435285 sec)
+2008-07-31 00:25:52.604: info: "sub.example.net.": old ZSK 31081 removed
+2008-07-31 00:25:52.605: debug: ->remove it
+2008-07-31 00:25:52.605: debug: Lifetime(259200 +/-150 sec) of active key 3615 exceeded (435285 sec)
+2008-07-31 00:25:52.605: debug: ->depreciate it
+2008-07-31 00:25:52.605: debug: ->activate published key 4254
+2008-07-31 00:25:52.605: notice: "sub.example.net.": lifetime of zone signing key 3615 exceeded: ZSK rollover done
+2008-07-31 00:25:52.605: debug: New key for publishing needed
+2008-07-31 00:25:53.128: debug: ->creating new key 56744
+2008-07-31 00:25:53.128: info: "sub.example.net.": new key 56744 generated for publishing
+2008-07-31 00:25:53.128: debug: Re-signing necessary: New zone key
+2008-07-31 00:25:53.128: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-07-31 00:25:53.128: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-31 00:25:53.128: debug: Signing zone "sub.example.net."
+2008-07-31 00:25:53.128: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-31 00:25:53.332: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-31 00:25:53.332: debug: Signing completed after 0s.
+2008-07-31 00:25:53.332: debug:
+2008-07-31 00:25:53.332: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-31 00:25:53.332: debug: Check RFC5011 status
+2008-07-31 00:25:53.332: debug: Check ZSK status
+2008-07-31 00:25:53.332: debug: Re-signing necessary: re-signing interval (2d) reached
+2008-07-31 00:25:53.332: notice: "example.net.": re-signing triggered: re-signing interval (2d) reached
+2008-07-31 00:25:53.332: debug: Writing key file "./example.net./dnskey.db"
+2008-07-31 00:25:53.333: debug: Incrementing serial number in file "./example.net./zone.db"
+2008-07-31 00:25:53.333: debug: Signing zone "example.net."
+2008-07-31 00:25:53.333: debug: Run cmd "cd ./example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o example.net. -e +518400 zone.db K*.private"
+2008-07-31 00:25:53.477: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-31 00:25:53.477: debug: Signing completed after 0s.
+2008-07-31 00:25:53.477: debug:
+2008-07-31 00:25:53.477: notice: end of run: 0 errors occured
+2008-07-31 13:19:17.447: notice: ------------------------------------------------------------
+2008-07-31 13:19:17.447: notice: running ../../dnssec-signer -v -v
+2008-07-31 13:19:17.449: debug: parsing zone "sub.example.net." in dir "./sub.example.net."
+2008-07-31 13:19:17.449: debug: Check RFC5011 status
+2008-07-31 13:19:17.450: debug: ->not a rfc5011 zone, looking for a regular ksk rollover
+2008-07-31 13:19:17.450: debug: Check KSK status
+2008-07-31 13:19:17.450: debug: Check ZSK status
+2008-07-31 13:19:17.450: debug: Lifetime(390 sec) of depreciated key 3615 exceeded (46405 sec)
+2008-07-31 13:19:17.450: info: "sub.example.net.": old ZSK 3615 removed
+2008-07-31 13:19:17.450: debug: ->remove it
+2008-07-31 13:19:17.450: debug: Re-signing necessary: New zone key
+2008-07-31 13:19:17.451: notice: "sub.example.net.": re-signing triggered: New zone key
+2008-07-31 13:19:17.451: debug: Writing key file "./sub.example.net./dnskey.db"
+2008-07-31 13:19:17.451: debug: Signing zone "sub.example.net."
+2008-07-31 13:19:17.451: debug: Run cmd "cd ./sub.example.net.; /usr/local/sbin/dnssec-signzone -g -p -d ../keysets -o sub.example.net. -e +172800 -l dlv.trusted-keys.de -N unixtime zone.db K*.private"
+2008-07-31 13:19:17.943: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-07-31 13:19:17.944: debug: Signing completed after 0s.
+2008-07-31 13:19:17.944: debug:
+2008-07-31 13:19:17.944: debug: parsing zone "example.net." in dir "./example.net."
+2008-07-31 13:19:17.944: debug: Check RFC5011 status
+2008-07-31 13:19:17.944: debug: Check ZSK status
+2008-07-31 13:19:17.944: debug: Re-signing not necessary!
+2008-07-31 13:19:17.944: debug: Check if there is a parent file to copy
+2008-07-31 13:19:17.944: debug:
+2008-07-31 13:19:17.945: notice: end of run: 0 errors occured
diff --git a/contrib/zkt/examples/flat/zone.conf b/contrib/zkt/examples/flat/zone.conf
new file mode 100644
index 0000000..0ccc7f6
--- /dev/null
+++ b/contrib/zkt/examples/flat/zone.conf
@@ -0,0 +1,10 @@
+
+zone "example.NET." in {
+ type master;
+ file "example.net./zone.db.signed";
+};
+
+zone "sub.example.NET." in {
+ type master;
+ file "sub.example.net./zone.db.signed";
+};
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+11867.key b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+11867.key
new file mode 100644
index 0000000..a824208
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+11867.key
@@ -0,0 +1,3 @@
+;% generationtime=20080717083652
+;% lifetime=28d
+example.de. IN DNSKEY 256 3 5 BQEAAAAByN2rMrazHwh+sNOv8cBef3HUotAQTS9QW4Y5NjNuyYNraJBA OqV8KSaGQqIhkh0ZD0oIm2h0JowdyERZVj6ZZQ==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+11867.published b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+11867.published
new file mode 100644
index 0000000..8703816
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+11867.published
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: yN2rMrazHwh+sNOv8cBef3HUotAQTS9QW4Y5NjNuyYNraJBAOqV8KSaGQqIhkh0ZD0oIm2h0JowdyERZVj6ZZQ==
+PublicExponent: AQAAAAE=
+PrivateExponent: PUJ1+zrJn3r8Z+GcNmxwyHaNeLivsjSiSoGZu2FnlJHgHV3Kq5ZL+d5jeGpbPyW6Bc5z+NpkqGPuz/DG9C6OhQ==
+Prime1: 8NWUn++L7p45k/tgcIoVKWe9Jgwtn4m8K8PkNQG1H4s=
+Prime2: 1YPE6Nw/KsuDHPkM6NAqtnMWugaG9kDq348eSTkhSM8=
+Exponent1: tF/x51phYle6xgqBLw3ixmkQJCSpCa3F51pb/zGieV0=
+Exponent2: PeU/PmlccGmtux9ZC9rEdu/xmMERXZri3QdBtCzYDLs=
+Coefficient: gMF5l8BpGn2VBO7XqZNTJWOkx1lBOytfBc4y6yh+Cn8=
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+17439.key b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+17439.key
new file mode 100644
index 0000000..1986117
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+17439.key
@@ -0,0 +1,4 @@
+;% generationtime=20080506225722
+;% lifetime=20d
+;% expirationtime=20080711220959
+example.de. IN DNSKEY 385 3 5 BQEAAAABCyg92L7v21N3lc/gR07/2iLmvt6dUn1KKauLvmkRuT040XT+ Rd3Iq20iq6BqVPsPS+hCOTRA3xikTIn5YzmPLPutIRtjIodHhsrML4D9 Pp1dzgEDKWLam96v+E7KC0GGH/BI6/WelqeqjS5BjI4Gjv4roaTyDCi6 3oXwcMFDVwrSjws4A/5AGANka41Aky+UCGse6+64YmNP/QkSXDAeBZqw rw==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+17439.private b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+17439.private
new file mode 100644
index 0000000..62b7ca4
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+17439.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: Cyg92L7v21N3lc/gR07/2iLmvt6dUn1KKauLvmkRuT040XT+Rd3Iq20iq6BqVPsPS+hCOTRA3xikTIn5YzmPLPutIRtjIodHhsrML4D9Pp1dzgEDKWLam96v+E7KC0GGH/BI6/WelqeqjS5BjI4Gjv4roaTyDCi63oXwcMFDVwrSjws4A/5AGANka41Aky+UCGse6+64YmNP/QkSXDAeBZqwrw==
+PublicExponent: AQAAAAE=
+PrivateExponent: CGYBtGSIMmSFoqnh6yYuoYlvTP2O7vkBdRrfkN43NwdlQVhco+wQO55QxCZNhCcbp2xau9IdejetNH0pQ3Zfg2Vllx78F8VMTMqkgw2HudWS/RahkMg+Hq6DBUaX/LYt90ToGyy5+FmyBm4fOV8FxJVrmTFMw4m7ULp3FgRcxmzS5zNjKYP2LKU/pYz0wFpyAr88DGNjChgwvRN/GE4obsoJgQ==
+Prime1: A18v8idXV3o9tpIzalTEpOeDX7OxKumhUsoDpPhOJf7XqHLS6hYoYwFbRObF23Zi/3kHiAoGffR1Dkd+ji3xZhFOSEcUDuikQ2jdzdY8NxbzQQ==
+Prime2: A08XMjIEpsViYvYB+ChuYxPbq7Z/eHtT/r5f8zS+nuEUwYAlKeq/i+U5sIydC1txv5XQuRPqpjtlZTClJ85BpS0GnSspG5PcY3OMwkA2smLX7w==
+Exponent1: AcLu8YM68M8LtP7Dr7vYI+vJK6RK5SN/mAnz4ALt53igCUB/iVrfvBWCHp7hEgkRZUQQoItbT9C6YXrC3G9DW+IldSP8vrtqYva4YDBD2X1LAQ==
+Exponent2: JdJVp3CAJPPcx0KiKDS8gHDiu22CBV2w1cycnXgwFmJl4aQkbTA7/xlgl15r3lByacAc19JreArqgCQRQV3bS7NG2PiQmzO26XkwCq+Kj7OJ
+Coefficient: i6sKgv2zpCvdY9fChryaf5nZyb4nFd2dG/vnjQScBz8YVw4LnfL/XqKIego0Ez6/KlL4AnvkcafzogJ+MtmBB7V4RXEyObcbR6M/MLGMhpL8
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+35672.key b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+35672.key
new file mode 100644
index 0000000..4836d51
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+35672.key
@@ -0,0 +1,3 @@
+;% generationtime=20080608210458
+;% lifetime=28d
+example.de. IN DNSKEY 256 3 5 BQEAAAABnRJdmY7dzRKi93pVkLToV5FK4Ffm8YnY0c6IHKcAmb5t8FLv pNijniIclCPXTpfio+HNa59a4UA8jTdJb+kT0w==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+35672.private b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+35672.private
new file mode 100644
index 0000000..3b1b32e
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+35672.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: nRJdmY7dzRKi93pVkLToV5FK4Ffm8YnY0c6IHKcAmb5t8FLvpNijniIclCPXTpfio+HNa59a4UA8jTdJb+kT0w==
+PublicExponent: AQAAAAE=
+PrivateExponent: I2jMbjLfEzJ4iZHvXDTRZKM2/SXOLH9dTWkzH8zfbW+jzsKObfnt7/yJYaIHv0gQOvOAfQ46RutqryjQpLPtoQ==
+Prime1: 0TgZK52tc+JlhyG5229kjntpXP0enYcMqROdLM9lSoM=
+Prime2: wDFNEVHv0GDU7L7ZLPIuRewnHg9SHgSnQ+kOWDhZEHE=
+Exponent1: aVdC0HyDAG7bvUkwx468HhrL/00lGXQYvnxoKqV3/dU=
+Exponent2: quQ/NY7YkT3jYi649bQ9hsWDkaAoBf1FrIVPcf3FSXE=
+Coefficient: Td8UjaaoC44Qt0jCQ4uULI1YUQRNdPYH3024NghryrE=
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+41145.key b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+41145.key
new file mode 100644
index 0000000..3a636d4
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+41145.key
@@ -0,0 +1,3 @@
+;% generationtime=20080608210458
+;% lifetime=20d
+example.de. IN DNSKEY 257 3 5 BQEAAAABDrm5aXRPuZOmwT4nINnY2qXyXWLtutggFAJgBW5Ua7uzAR+7 r/DcOE7IfjnT5FQhbYXIuKy61uOEqPu1TYvDsGb1pseKSB4J0jmXDU9N tu9TDp6X6ZXE11+cFdATa4TPnsAUMSxVkLZanrbyACmcNr1gjT3dz6qI VBVPb5OnUldndbgtlOX3wcE0aR/MIsIjz1UQl/QoxbVclZVOUNdJQGb9 zQ==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+41145.private b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+41145.private
new file mode 100644
index 0000000..b0466be
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+41145.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: Drm5aXRPuZOmwT4nINnY2qXyXWLtutggFAJgBW5Ua7uzAR+7r/DcOE7IfjnT5FQhbYXIuKy61uOEqPu1TYvDsGb1pseKSB4J0jmXDU9Ntu9TDp6X6ZXE11+cFdATa4TPnsAUMSxVkLZanrbyACmcNr1gjT3dz6qIVBVPb5OnUldndbgtlOX3wcE0aR/MIsIjz1UQl/QoxbVclZVOUNdJQGb9zQ==
+PublicExponent: AQAAAAE=
+PrivateExponent: AQM2fRAmc6coPLeTHAK1DCHOYCRPSjsHYXoOzwMzzdIpHschjfxka35UdNSGKYpqM9E+VTZmV96w9ZZK5recxYak/6F72ZYTIYtsWYqCkej18nzhpnlt4nASnRt0nsS9UVVwc1Y7QxqRtSVXEcgcbiW3lr0jq+PSBf/HjY9qOHV4ExXlz7KPYOWbJa1YLFnvGlMd/W7hmQvXNEfTvOwjKURV4Q==
+Prime1: A/0Yax4evJzC7VSw0Swt0KNM7gtIJ9nwzDCrTymulzKhu6Wgeu0veU9OAGDhv0Yfmn0kr1JLITpMu4uo3a5jfLb18yZEAyPphejZBA+wPIll+Q==
+Prime2: A7EcplBfPWZmeCeL6UnFz4h45nxi3jRfQT00k34Nu5aFt5v+ngExbatcoOMnEKZSq2SQKDQRTp6XBOiwPNB9mVaLmzl9k9tyX6JvkCBEDrM7dQ==
+Exponent1: AjoJbjmJarH7I4Zj5UPc9r0I5NtVgrAx4ZltcqPN07/1cBS2QAnZuMSLUvv8pkK+Lng9Wdy9c2FL0XjWY5Q+ORYj4ONGl9OWpi2zKqpTw4WgOQ==
+Exponent2: AZfFGuYsztbn6tHFUIdIeXfaFTYyVbSfCEUp2Uv8N75QMyyuT4dzAlkU2cfSg3oAefrlCKWqXtLv9XlOJ1hTeXZOz8jyYAyhvGWGoHmSbeaNKQ==
+Coefficient: AX6DKJRk0GXwCnkpfbn91myfZ2wgsUTXKjqasdlTqm3JL9Rtpq8J2MWPhexcSSz8DNa5LQlGduE1nh4eqqntnSNckD6CeImMdWgTNbQS3zV8Bw==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+59244.key b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+59244.key
new file mode 100644
index 0000000..35d4c6a
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+59244.key
@@ -0,0 +1,3 @@
+;% generationtime=20080711221000
+;% lifetime=20d
+example.de. IN DNSKEY 257 3 5 BQEAAAABDfaBERX9p+FUi1OXYVig7zLCQFZoRYpwDDuLzBcC7k+G1+wW dftyA1vBm5HMpyq0OifT0Hsez4+H+0CIWHZP8oPCYfKrq+wM2EgMzDDO Yv+O1TQU4i3G+iONxB1RAwH/J2lA+U0zCbrdf0KLq/enNquchhPw4gCX 0RB9HC+TkpoPf2u7aKFcjlpw4C4uhDl1s6FpfdXe6NQWW6c+ONUcLAEt +w==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+59244.published b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+59244.published
new file mode 100644
index 0000000..b7f28db
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./Kexample.de.+005+59244.published
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: DfaBERX9p+FUi1OXYVig7zLCQFZoRYpwDDuLzBcC7k+G1+wWdftyA1vBm5HMpyq0OifT0Hsez4+H+0CIWHZP8oPCYfKrq+wM2EgMzDDOYv+O1TQU4i3G+iONxB1RAwH/J2lA+U0zCbrdf0KLq/enNquchhPw4gCX0RB9HC+TkpoPf2u7aKFcjlpw4C4uhDl1s6FpfdXe6NQWW6c+ONUcLAEt+w==
+PublicExponent: AQAAAAE=
+PrivateExponent: /MDd0rAZf9mm/3cDi6TjTqeegMmnidhKYIzxyz1+quzwOA16L3jLf3ucWjz/BlEiOYh1CZbAroGRYqBAskys8u7FDinOQEP5cEn5NUyL5z0WebSCO+qnaqaQSokRs0oUx3+e9tJc9GhhmZIVNXQe4mYxfeYCl6KZS9CXe22y31PkvJ+SQIBh/I+SQnM4rbW012rKroAxdHfTvmalofx+Qb1h
+Prime1: A/5Pkk5UAGvEa06GrEcATMOjsxZ0BbgalPuJKLLTFzvtYhdlJY738oY0QfsHba9hEC+iiSwfjWYyNlH/7bcVqSFtbLJiJ0aUfvObj75qw4HjXQ==
+Prime2: A38aQzy3UrARKcwUqCiQrSOTM5P7xIDfbruW7ywmaWA1lXCvP3EJAal6MYs0pG2vx1cxVTIPva3Se26NkGaBqZw+RgHxmRmfgxvSoCfWXGZZNw==
+Exponent1: OvPYJBkVUbncb0mBtTe5uwa9RgGlCgW4ges93zf3UQuHGvAesUFNnMh6y9zi4vgyVNbz2KOSnA91onc9l42b6NwqRNbExGhDsMc8NQi16vnF
+Exponent2: AkkCNzHuGv3HaQ4MpRT/PLPA2UONseMBvJHWlgK+aO2xb6/7I09sPqKnJ4f6Bj5jL8efNZYHWsaN4l335V9lc5791opU+07LHHpULn2qVRpJYw==
+Coefficient: An94juF2F5cDtoMC6gwI5iaWDH/qxkeuZ62fnMFoMY18XO0/clTVfdW7XvXCOn1DQyDLDOYpxR5MfeDKkbxtGGYKABWBOWlyaS1A5D5wTQRJzw==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./dnskey.db b/contrib/zkt/examples/hierarchical/de./example.de./dnskey.db
new file mode 100644
index 0000000..bd106bd
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./dnskey.db
@@ -0,0 +1,48 @@
+;
+; !!! Don't edit this file by hand.
+; !!! It will be generated by dnssec-signer.
+;
+; Last generation time Jul 29 2008 12:44:06
+;
+
+; *** List of Key Signing Keys ***
+; example.de. tag=17439 algo=RSASHA1 generated Jun 19 2008 00:32:22
+example.de. 3600 IN DNSKEY 385 3 5 (
+ BQEAAAABCyg92L7v21N3lc/gR07/2iLmvt6dUn1KKauLvmkRuT040XT+
+ Rd3Iq20iq6BqVPsPS+hCOTRA3xikTIn5YzmPLPutIRtjIodHhsrML4D9
+ Pp1dzgEDKWLam96v+E7KC0GGH/BI6/WelqeqjS5BjI4Gjv4roaTyDCi6
+ 3oXwcMFDVwrSjws4A/5AGANka41Aky+UCGse6+64YmNP/QkSXDAeBZqw
+ rw==
+ ) ; key id = 17567 (original key id = 17439)
+
+; example.de. tag=41145 algo=RSASHA1 generated Jul 12 2008 00:10:00
+example.de. 3600 IN DNSKEY 257 3 5 (
+ BQEAAAABDrm5aXRPuZOmwT4nINnY2qXyXWLtutggFAJgBW5Ua7uzAR+7
+ r/DcOE7IfjnT5FQhbYXIuKy61uOEqPu1TYvDsGb1pseKSB4J0jmXDU9N
+ tu9TDp6X6ZXE11+cFdATa4TPnsAUMSxVkLZanrbyACmcNr1gjT3dz6qI
+ VBVPb5OnUldndbgtlOX3wcE0aR/MIsIjz1UQl/QoxbVclZVOUNdJQGb9
+ zQ==
+ ) ; key id = 41145
+
+; example.de. tag=59244 algo=RSASHA1 generated Jul 12 2008 00:10:00
+example.de. 3600 IN DNSKEY 257 3 5 (
+ BQEAAAABDfaBERX9p+FUi1OXYVig7zLCQFZoRYpwDDuLzBcC7k+G1+wW
+ dftyA1vBm5HMpyq0OifT0Hsez4+H+0CIWHZP8oPCYfKrq+wM2EgMzDDO
+ Yv+O1TQU4i3G+iONxB1RAwH/J2lA+U0zCbrdf0KLq/enNquchhPw4gCX
+ 0RB9HC+TkpoPf2u7aKFcjlpw4C4uhDl1s6FpfdXe6NQWW6c+ONUcLAEt
+ +w==
+ ) ; key id = 59244
+
+; *** List of Zone Signing Keys ***
+; example.de. tag=35672 algo=RSASHA1 generated Jul 17 2008 10:36:52
+example.de. 3600 IN DNSKEY 256 3 5 (
+ BQEAAAABnRJdmY7dzRKi93pVkLToV5FK4Ffm8YnY0c6IHKcAmb5t8FLv
+ pNijniIclCPXTpfio+HNa59a4UA8jTdJb+kT0w==
+ ) ; key id = 35672
+
+; example.de. tag=11867 algo=RSASHA1 generated Jul 17 2008 10:36:52
+example.de. 3600 IN DNSKEY 256 3 5 (
+ BQEAAAAByN2rMrazHwh+sNOv8cBef3HUotAQTS9QW4Y5NjNuyYNraJBA
+ OqV8KSaGQqIhkh0ZD0oIm2h0JowdyERZVj6ZZQ==
+ ) ; key id = 11867
+
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./dsset-example.de. b/contrib/zkt/examples/hierarchical/de./example.de./dsset-example.de.
new file mode 100644
index 0000000..a2cb04a
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./dsset-example.de.
@@ -0,0 +1,6 @@
+example.de. IN DS 17567 5 1 D2AE03CF2A76AA0A28AE8593B3D96E497C6508E5
+example.de. IN DS 17567 5 2 A9F2D82927721257F7C4325B402F664BBFE58780A786BB7B7188A0DB FD5D7008
+example.de. IN DS 41145 5 1 8F18A5F2A59AEF518DBA5A0CD0F0E259DD0F8C05
+example.de. IN DS 41145 5 2 BA5A78FB98E5A38554B4D73B32F15C4794AEE9E25934B3696B999451 A534102A
+example.de. IN DS 59244 5 1 56F34A865AFA3A183D3C008490B94CB1D238BB9A
+example.de. IN DS 59244 5 2 08C1BFC17C4634BE4A03A297D65E44CC8EB375B4027534541B7E0596 5E985313
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./keyset-example.de. b/contrib/zkt/examples/hierarchical/de./example.de./keyset-example.de.
new file mode 100644
index 0000000..2b40c68
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./keyset-example.de.
@@ -0,0 +1,28 @@
+$ORIGIN .
+example.de 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABDfaBERX9p+FUi1OXYVig7zLCQFZo
+ RYpwDDuLzBcC7k+G1+wWdftyA1vBm5HMpyq0
+ OifT0Hsez4+H+0CIWHZP8oPCYfKrq+wM2EgM
+ zDDOYv+O1TQU4i3G+iONxB1RAwH/J2lA+U0z
+ Cbrdf0KLq/enNquchhPw4gCX0RB9HC+TkpoP
+ f2u7aKFcjlpw4C4uhDl1s6FpfdXe6NQWW6c+
+ ONUcLAEt+w==
+ ) ; key id = 59244
+ 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABDrm5aXRPuZOmwT4nINnY2qXyXWLt
+ utggFAJgBW5Ua7uzAR+7r/DcOE7IfjnT5FQh
+ bYXIuKy61uOEqPu1TYvDsGb1pseKSB4J0jmX
+ DU9Ntu9TDp6X6ZXE11+cFdATa4TPnsAUMSxV
+ kLZanrbyACmcNr1gjT3dz6qIVBVPb5OnUldn
+ dbgtlOX3wcE0aR/MIsIjz1UQl/QoxbVclZVO
+ UNdJQGb9zQ==
+ ) ; key id = 41145
+ 7200 IN DNSKEY 385 3 5 (
+ BQEAAAABCyg92L7v21N3lc/gR07/2iLmvt6d
+ Un1KKauLvmkRuT040XT+Rd3Iq20iq6BqVPsP
+ S+hCOTRA3xikTIn5YzmPLPutIRtjIodHhsrM
+ L4D9Pp1dzgEDKWLam96v+E7KC0GGH/BI6/We
+ lqeqjS5BjI4Gjv4roaTyDCi63oXwcMFDVwrS
+ jws4A/5AGANka41Aky+UCGse6+64YmNP/QkS
+ XDAeBZqwrw==
+ ) ; key id = 17567
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./keyset-sub.example.de. b/contrib/zkt/examples/hierarchical/de./example.de./keyset-sub.example.de.
new file mode 100644
index 0000000..04ed33a
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./keyset-sub.example.de.
@@ -0,0 +1,8 @@
+$ORIGIN .
+sub.example.de 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABpL4/T8z6mCbTm46Y9+KJOgCAk+dG
+ HBoyg75N1f0lwYSZOLyyyOLWwDxlsfkb5Wwv
+ Z1ZG6NFmg/3o5N3Zd7TEkkvHZafRMrzHFicd
+ IMSvjmOWVBR0GsEb+reREu5X0sdZbqOuxT6C
+ kKoTXRpRZgU9ouus6W5bSWQAfdQIegTBBKk=
+ ) ; key id = 40998
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+19793.key b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+19793.key
new file mode 100644
index 0000000..6b6aca1
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+19793.key
@@ -0,0 +1,3 @@
+;% generationtime=20080729104405
+;% lifetime=2d
+sub.example.de. IN DNSKEY 256 3 1 BQEAAAABny2+yO3erGn/4hCJyG031zbeZa91KPPsQRfqgx3eNgyaQjfD 7NTKuAfJjbSTbHnvXF008duYET+UU9+hS01RIw==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+19793.private b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+19793.private
new file mode 100644
index 0000000..2377635
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+19793.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 1 (RSA)
+Modulus: ny2+yO3erGn/4hCJyG031zbeZa91KPPsQRfqgx3eNgyaQjfD7NTKuAfJjbSTbHnvXF008duYET+UU9+hS01RIw==
+PublicExponent: AQAAAAE=
+PrivateExponent: njIKbIVXtg54r7CRULxKaNXpW0BUus3VYh/JBkMgd+runwCUtXUccG14jHrZ/H2M6Yx46EIYxebzoi0rStisAQ==
+Prime1: zsU5EgehqDuowoV/yRkMTDa/b3unK6hUy4AnqCpumtE=
+Prime2: xRPHnd4KuW4H4SueCLf3oduoTfOp6pl6cKdJyjooQbM=
+Exponent1: WbbHa11huZfttfhiiocYX0zKzy+2hTHb8vXBJ27mIcE=
+Exponent2: JrXRbJt0aQuZ7PEcBuYpcLp0d4WZFD0htANku1j9xHc=
+Coefficient: y0cK7SB3Usly0yku3wY50DpxX0k+qPu8HztqHeGCXpg=
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+51977.depreciated b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+51977.depreciated
new file mode 100644
index 0000000..934f630
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+51977.depreciated
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 1 (RSA)
+Modulus: rPRVqWxFqCoVRrtQ8XYrbeogdBKBvEus359hPgFqYdGHvR1Kkyl8EhioksP/Tze5cGBHTSFCjIh+lGMPEssJCQ==
+PublicExponent: AQAAAAE=
+PrivateExponent: OGFXm5oxuztSyLrcmyhrWs14NTOKh745RZMjIUVyoem0SLRjkJWdqGlPnMsR+lmyVieKx6OhFTOZnbjRaeu2AQ==
+Prime1: 1epbg5Yr1USYkwGu9zV7AXpB74Wfu7I3WDzPabBFQ+k=
+Prime2: zvsD4Q/+PCmzXiRwsSlwZwtwpcSump1fuIve+REOCCE=
+Exponent1: kMpHQJed0XNHcNZ2hcEZ1/yG3Ex4MZbdJ9DsK2Rgosk=
+Exponent2: LEK4vqbV5lWlccULSqR0puA/1lFWmvRbS0yu7qp4OGE=
+Coefficient: gXEyODoVUSbHQP2mar5cwP3BDdi1LwDYVvdvKYEPIrw=
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+51977.key b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+51977.key
new file mode 100644
index 0000000..2c662a9
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+51977.key
@@ -0,0 +1,3 @@
+;% generationtime=20080726213646
+;% lifetime=2d
+sub.example.de. IN DNSKEY 256 3 1 BQEAAAABrPRVqWxFqCoVRrtQ8XYrbeogdBKBvEus359hPgFqYdGHvR1K kyl8EhioksP/Tze5cGBHTSFCjIh+lGMPEssJCQ==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+55699.key b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+55699.key
new file mode 100644
index 0000000..3a0fcec
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+55699.key
@@ -0,0 +1,3 @@
+;% generationtime=20080731111645
+;% lifetime=2d
+sub.example.de. IN DNSKEY 256 3 1 BQEAAAABwutYROLC3W5wyq8jZEN7Fjgn2bLMoUAVJoteHeTZgfc11ekm /T+TEsR0L1Eazfc/MP+8X0OzdEl97NGOPtmT9w==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+55699.published b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+55699.published
new file mode 100644
index 0000000..b45db1f
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+001+55699.published
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 1 (RSA)
+Modulus: wutYROLC3W5wyq8jZEN7Fjgn2bLMoUAVJoteHeTZgfc11ekm/T+TEsR0L1Eazfc/MP+8X0OzdEl97NGOPtmT9w==
+PublicExponent: AQAAAAE=
+PrivateExponent: f7ufWzg6L93T6LUD9P4Enjv0YvfQoIAJwO3OLdaMTuvz7ehqy+FWuAzy4fQwBxr768pDWv/EZqpqPuDIifUCUQ==
+Prime1: 50l7b5UFq5ejhH7Y/ZTA03M0JMZiIQDrpJdWL89sn6M=
+Prime2: 178TrVx2Of4cF18K9sbgdrbQCL82IotrErwo5YAsb50=
+Exponent1: Gs/D3DZdG7gy9INcfyIBH8pOHkcITjxJQbEJotYtp48=
+Exponent2: xVkRB61kvgdvwcowk4UnL6FqBPi5p9Jk1AlNteSksMU=
+Coefficient: Z9dHWKQ4b7QgZt5kzJNs4gW4iZPvD2pdm31V0jEbPoA=
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+005+40998.key b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+005+40998.key
new file mode 100644
index 0000000..9c7c36c
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+005+40998.key
@@ -0,0 +1,3 @@
+;% generationtime=20080726221746
+;% lifetime=5d
+sub.example.de. IN DNSKEY 257 3 5 BQEAAAABpL4/T8z6mCbTm46Y9+KJOgCAk+dGHBoyg75N1f0lwYSZOLyy yOLWwDxlsfkb5WwvZ1ZG6NFmg/3o5N3Zd7TEkkvHZafRMrzHFicdIMSv jmOWVBR0GsEb+reREu5X0sdZbqOuxT6CkKoTXRpRZgU9ouus6W5bSWQA fdQIegTBBKk=
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+005+40998.private b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+005+40998.private
new file mode 100644
index 0000000..3e39f5a
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./Ksub.example.de.+005+40998.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: pL4/T8z6mCbTm46Y9+KJOgCAk+dGHBoyg75N1f0lwYSZOLyyyOLWwDxlsfkb5WwvZ1ZG6NFmg/3o5N3Zd7TEkkvHZafRMrzHFicdIMSvjmOWVBR0GsEb+reREu5X0sdZbqOuxT6CkKoTXRpRZgU9ouus6W5bSWQAfdQIegTBBKk=
+PublicExponent: AQAAAAE=
+PrivateExponent: CrFKdhkCOgyF27Jc4GPfo7A6v2q0OgRE2nBdkw7XFUEADEHSVLA6XYUm3AZmAOWxTmrGU8EK+76hfC22DjA6O0BljTNdxLB5cGRL2Dxey603jCIEVt/ahIqyb2STr0pWYEVc3qAKJL93iP4v5r7fJt157sJhQF8F5Zpqj24QvmE=
+Prime1: 1EpVvo011F2qgjesKSKplhqtvbmRPjTuhijb7531zIbxDzBF+lXCDyjt3Y/LrWS240t74vbZpo9FUZIETIf/FQ==
+Prime2: xqm8Bk18u2WJZ9uUr+/MMPKfh6OgAFqtBwFi81FFJ62kHGL9i8AcychE9tD5IRu74KLCGW+Vk87lyLOF3WU0RQ==
+Exponent1: JmLNa+QmMjHVDmAM833bF024/+NIyZgfNSDLnGXxTqYZ3PK/llLHIwBChLMKAQgFvt5PP0id1Nkc9N16xjkuFQ==
+Exponent2: rZW7rMmQxQQRHD8TKQTAhCX+31n8jnq7gW9dyVpjY85GDuQe6+3rox6xvsMfUzEOgXk1lgnm46FAIHOH6DhMuQ==
+Coefficient: MPoirwMUkLzLWeynO1Izy+lff70hnDnOcZEckS+Sy1TlUkk22uHBF4uNLkgoF26XqeKzK9pG1rCGfccfWTCayQ==
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dlvset-sub.example.de. b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dlvset-sub.example.de.
new file mode 100644
index 0000000..c392b9a
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dlvset-sub.example.de.
@@ -0,0 +1,2 @@
+sub.example.de.dlv.trusted-keys.net. IN DLV 40998 5 1 1414E9C46F367D787EEF2EC91E1FC66DD087AEAE
+sub.example.de.dlv.trusted-keys.net. IN DLV 40998 5 2 6FE53984AB75C31A06778E9944F8CDB4790527D36BBD08CC1E90DA7A E32EEE5F
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dnskey.db b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dnskey.db
new file mode 100644
index 0000000..e922c18
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dnskey.db
@@ -0,0 +1,35 @@
+;
+; !!! Don't edit this file by hand.
+; !!! It will be generated by dnssec-signer.
+;
+; Last generation time Jul 31 2008 13:16:45
+;
+
+; *** List of Key Signing Keys ***
+; sub.example.de. tag=40998 algo=RSASHA1 generated Jul 27 2008 00:17:46
+sub.example.de. 3600 IN DNSKEY 257 3 5 (
+ BQEAAAABpL4/T8z6mCbTm46Y9+KJOgCAk+dGHBoyg75N1f0lwYSZOLyy
+ yOLWwDxlsfkb5WwvZ1ZG6NFmg/3o5N3Zd7TEkkvHZafRMrzHFicdIMSv
+ jmOWVBR0GsEb+reREu5X0sdZbqOuxT6CkKoTXRpRZgU9ouus6W5bSWQA
+ fdQIegTBBKk=
+ ) ; key id = 40998
+
+; *** List of Zone Signing Keys ***
+; sub.example.de. tag=51977 algo=RSAMD5 generated Jul 29 2008 12:44:04
+sub.example.de. 3600 IN DNSKEY 256 3 1 (
+ BQEAAAABrPRVqWxFqCoVRrtQ8XYrbeogdBKBvEus359hPgFqYdGHvR1K
+ kyl8EhioksP/Tze5cGBHTSFCjIh+lGMPEssJCQ==
+ ) ; key id = 51977
+
+; sub.example.de. tag=19793 algo=RSAMD5 generated Jul 29 2008 12:44:05
+sub.example.de. 3600 IN DNSKEY 256 3 1 (
+ BQEAAAABny2+yO3erGn/4hCJyG031zbeZa91KPPsQRfqgx3eNgyaQjfD
+ 7NTKuAfJjbSTbHnvXF008duYET+UU9+hS01RIw==
+ ) ; key id = 19793
+
+; sub.example.de. tag=55699 algo=RSAMD5 generated Jul 31 2008 13:16:45
+sub.example.de. 3600 IN DNSKEY 256 3 1 (
+ BQEAAAABwutYROLC3W5wyq8jZEN7Fjgn2bLMoUAVJoteHeTZgfc11ekm
+ /T+TEsR0L1Eazfc/MP+8X0OzdEl97NGOPtmT9w==
+ ) ; key id = 55699
+
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dnssec.conf b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dnssec.conf
new file mode 100644
index 0000000..d7d33ca
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dnssec.conf
@@ -0,0 +1,17 @@
+##
+## dnssec-zkt v0.4 (c) Jan 2005 hoz <at> hznet <dot> de ##
+##
+
+resigninterval 36h
+sigvalidity 2d
+max_ttl 90s
+
+ksk_lifetime 5d
+ksk_algo RSASHA1
+ksk_bits 1024
+
+zsk_lifetime 2d
+zsk_algo RSAMD5
+zsk_bits 512
+
+dlv_domain "dlv.trusted-keys.net"
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dsset-sub.example.de. b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dsset-sub.example.de.
new file mode 100644
index 0000000..b8ec77b
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./dsset-sub.example.de.
@@ -0,0 +1,2 @@
+sub.example.de. IN DS 40998 5 1 1414E9C46F367D787EEF2EC91E1FC66DD087AEAE
+sub.example.de. IN DS 40998 5 2 6FE53984AB75C31A06778E9944F8CDB4790527D36BBD08CC1E90DA7A E32EEE5F
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./keyset-sub.example.de. b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./keyset-sub.example.de.
new file mode 100644
index 0000000..04ed33a
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./keyset-sub.example.de.
@@ -0,0 +1,8 @@
+$ORIGIN .
+sub.example.de 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABpL4/T8z6mCbTm46Y9+KJOgCAk+dG
+ HBoyg75N1f0lwYSZOLyyyOLWwDxlsfkb5Wwv
+ Z1ZG6NFmg/3o5N3Zd7TEkkvHZafRMrzHFicd
+ IMSvjmOWVBR0GsEb+reREu5X0sdZbqOuxT6C
+ kKoTXRpRZgU9ouus6W5bSWQAfdQIegTBBKk=
+ ) ; key id = 40998
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./zone.db b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./zone.db
new file mode 100644
index 0000000..05489a4
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./zone.db
@@ -0,0 +1,25 @@
+;-----------------------------------------------------------------
+;
+; @(#) sub.example.de/zone.db
+;
+;-----------------------------------------------------------------
+
+$TTL 7200
+
+@ IN SOA ns1.example.de. hostmaster.example.de. (
+ 2008073101; Serial (up to 10 digits)
+ 86400 ; Refresh (RIPE recommendation if NOTIFY is used)
+ 1800 ; Retry
+ 2W ; Expire
+ 7200 ) ; Minimum
+
+
+ IN NS ns1.example.de.
+
+$INCLUDE dnskey.db
+
+localhost IN A 127.0.0.1
+
+a IN A 1.2.3.4
+b IN A 1.2.3.5
+c IN A 1.2.3.6
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./zone.db.signed b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./zone.db.signed
new file mode 100644
index 0000000..d607de5
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./sub.example.de./zone.db.signed
@@ -0,0 +1,108 @@
+; File written on Thu Jul 31 13:16:45 2008
+; dnssec_signzone version 9.5.1b1
+sub.example.de. 7200 IN SOA ns1.example.de. hostmaster.example.de. (
+ 2008073101 ; serial
+ 86400 ; refresh (1 day)
+ 1800 ; retry (30 minutes)
+ 1209600 ; expire (2 weeks)
+ 7200 ; minimum (2 hours)
+ )
+ 7200 RRSIG SOA 1 3 7200 20080802100259 (
+ 20080731101645 19793 sub.example.de.
+ d/lRqmf+AWENEHoKbG+ABspEFH0UEHsyue0o
+ DPPUzkAw/gZcHcwoCuf4AsbUYHz1HKyHjeUz
+ g2+AsH8mPZKGvg== )
+ 7200 NS ns1.example.de.
+ 7200 RRSIG NS 1 3 7200 20080802095409 (
+ 20080731101645 19793 sub.example.de.
+ VoXeajFhxMQjwVXspcxBN/lfM1R6hc1fIVdV
+ HjWlw0RSeCL7fBOY54HOIWcu6jHegMrjuB9y
+ KTOgEwv3r8kOiw== )
+ 7200 NSEC a.sub.example.de. NS SOA RRSIG NSEC DNSKEY
+ 7200 RRSIG NSEC 1 3 7200 20080802095639 (
+ 20080731101645 19793 sub.example.de.
+ cmhtmISCv2bbpBkgwyMuKNnlrNsJ3GViYUxT
+ lhQ8ASHjNH74mIuenBIGy+w3RxyDzoMk1w6Y
+ J0qpEvDF3FNvRQ== )
+ 3600 DNSKEY 256 3 1 (
+ BQEAAAABny2+yO3erGn/4hCJyG031zbeZa91
+ KPPsQRfqgx3eNgyaQjfD7NTKuAfJjbSTbHnv
+ XF008duYET+UU9+hS01RIw==
+ ) ; key id = 19793
+ 3600 DNSKEY 256 3 1 (
+ BQEAAAABrPRVqWxFqCoVRrtQ8XYrbeogdBKB
+ vEus359hPgFqYdGHvR1Kkyl8EhioksP/Tze5
+ cGBHTSFCjIh+lGMPEssJCQ==
+ ) ; key id = 51977
+ 3600 DNSKEY 256 3 1 (
+ BQEAAAABwutYROLC3W5wyq8jZEN7Fjgn2bLM
+ oUAVJoteHeTZgfc11ekm/T+TEsR0L1Eazfc/
+ MP+8X0OzdEl97NGOPtmT9w==
+ ) ; key id = 55699
+ 3600 DNSKEY 257 3 5 (
+ BQEAAAABpL4/T8z6mCbTm46Y9+KJOgCAk+dG
+ HBoyg75N1f0lwYSZOLyyyOLWwDxlsfkb5Wwv
+ Z1ZG6NFmg/3o5N3Zd7TEkkvHZafRMrzHFicd
+ IMSvjmOWVBR0GsEb+reREu5X0sdZbqOuxT6C
+ kKoTXRpRZgU9ouus6W5bSWQAfdQIegTBBKk=
+ ) ; key id = 40998
+ 3600 RRSIG DNSKEY 1 3 3600 20080802100935 (
+ 20080731101645 19793 sub.example.de.
+ WU1UIuqpuCLRe/46p4u2eqEvKrfsBvKpzKmx
+ TLG2AX+AOxWhRH5CqZ1zDiKUd+Xu6ekGxB/g
+ ZOu0rsPqvux2PA== )
+ 3600 RRSIG DNSKEY 5 3 3600 20080802100334 (
+ 20080731101645 40998 sub.example.de.
+ WW23Oq06HTSt5R/4Ds/nOl1n0Egsbf4bztB8
+ MZQAv6khorlDzmy3B4WPG1f79yuc26Zb6/Z9
+ QxNH0s68kp3X/eBR7FTEfHehsKaoRtaxldhz
+ V0VjOKI2iu4mhA6n/P0bAEhfxFxxde5tymP/
+ Od6//GN4UmNi9LCwWtLbGnF4Gpc= )
+a.sub.example.de. 7200 IN A 1.2.3.4
+ 7200 RRSIG A 1 4 7200 20080802095159 (
+ 20080731101645 19793 sub.example.de.
+ LxVthdAkEiBec6khr63+rufhSwtByBNvff8e
+ HEG/m+yusTBVqVoUp987aabxqaeW5v6f4GaB
+ 4iK4mspVH4Md7A== )
+ 7200 NSEC b.sub.example.de. A RRSIG NSEC
+ 7200 RRSIG NSEC 1 4 7200 20080802100843 (
+ 20080731101645 19793 sub.example.de.
+ HEqR2LChtQD2AeGCBhCsCemP3kjwAGi3RIXu
+ UpklHVo44Yu+JINnO/jxZ61CtlvBaZ25dpjt
+ 4ldl+d6z3bs4pQ== )
+b.sub.example.de. 7200 IN A 1.2.3.5
+ 7200 RRSIG A 1 4 7200 20080802095415 (
+ 20080731101645 19793 sub.example.de.
+ eLTaD1maS++Py3rybVftMtz0V8QnJenAH6tQ
+ PIcoZElIaLt8DGfwJYPmIPJlhwNlyqJH7d2A
+ SDEWBEFsFCnMkg== )
+ 7200 NSEC c.sub.example.de. A RRSIG NSEC
+ 7200 RRSIG NSEC 1 4 7200 20080802094836 (
+ 20080731101645 19793 sub.example.de.
+ nHvo1ValqHljlwCiPI51hdl0lnd5WiDIHbo7
+ MMxxZrYLNAP9ECK5DCzht9UrEGgIpI/MAvsU
+ 7S7eIlt0jBSehg== )
+c.sub.example.de. 7200 IN A 1.2.3.6
+ 7200 RRSIG A 1 4 7200 20080802095037 (
+ 20080731101645 19793 sub.example.de.
+ eVluthAz6YLAJWSaroRGuf5IsjhHoLz60Ot9
+ 1KTnw9zAFU16H6vuQ/TIH7ZzHOT0CgdwawF5
+ V0L4MAkK76H00w== )
+ 7200 NSEC localhost.sub.example.de. A RRSIG NSEC
+ 7200 RRSIG NSEC 1 4 7200 20080802100135 (
+ 20080731101645 19793 sub.example.de.
+ KRTIiVJPkQayfB8k6sIWyZPm6fqQAZbs8BQ4
+ jz/EGrHj3oFPRULUpLMKUdLFAp0kU0qRqCwl
+ Ull//CFV9J272A== )
+localhost.sub.example.de. 7200 IN A 127.0.0.1
+ 7200 RRSIG A 1 4 7200 20080802095833 (
+ 20080731101645 19793 sub.example.de.
+ fXGLRIRCvK/Q9D+dQTia3HUe1xlVBwBL1vcY
+ wRWdvNQgXQnOkpGtcb9fjKXkPz34SirmyESh
+ 8kYWUvV1kghBzA== )
+ 7200 NSEC sub.example.de. A RRSIG NSEC
+ 7200 RRSIG NSEC 1 4 7200 20080802101452 (
+ 20080731101645 19793 sub.example.de.
+ EqI9jcbxtroVBCVrCLWezzcxNvwm2xl/1nCt
+ 6Nogs3WvBPpMExUX2tWvpJMV14vpFSW2qWQK
+ UoFq9NHsH2WSDw== )
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./zone.db b/contrib/zkt/examples/hierarchical/de./example.de./zone.db
new file mode 100644
index 0000000..c485181
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./zone.db
@@ -0,0 +1,37 @@
+;-----------------------------------------------------------------
+;
+; @(#) example.de/zone.db
+;
+;-----------------------------------------------------------------
+
+$TTL 7200
+
+; Be sure that the serial number below is left
+; justified in a field of at least 10 chars!!
+; 0123456789;
+; It's also possible to use the date form e.g. 2005040101
+@ IN SOA ns1.example.de. hostmaster.example.de. (
+ 258 ; Serial
+ 43200 ; Refresh
+ 1800 ; Retry
+ 2W ; Expire
+ 7200 ) ; Minimum
+
+ IN NS ns1.example.de.
+ IN NS ns2.example.de.
+
+ns1 IN A 1.0.0.5
+ IN AAAA 2001:db8::53
+ns2 IN A 1.2.0.6
+
+localhost IN A 127.0.0.1
+
+; Delegation to secure zone; The DS resource record will
+; be added by dnssec-signzone automatically if the
+; keyset-sub.example.de file is present (run dnssec-signzone
+; with option -g or use the dnssec-signer tool) ;-)
+sub IN NS ns1.example.de.
+
+; this file will have all the zone keys
+$INCLUDE dnskey.db
+
diff --git a/contrib/zkt/examples/hierarchical/de./example.de./zone.db.signed b/contrib/zkt/examples/hierarchical/de./example.de./zone.db.signed
new file mode 100644
index 0000000..4b9b3dc
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./example.de./zone.db.signed
@@ -0,0 +1,147 @@
+; File written on Tue Jul 29 12:44:06 2008
+; dnssec_signzone version 9.5.1b1
+example.de. 7200 IN SOA ns1.example.de. hostmaster.example.de. (
+ 258 ; serial
+ 43200 ; refresh (12 hours)
+ 1800 ; retry (30 minutes)
+ 1209600 ; expire (2 weeks)
+ 7200 ; minimum (2 hours)
+ )
+ 7200 RRSIG SOA 5 2 7200 20080808092956 (
+ 20080729094406 35672 example.de.
+ UufM9vATUwvqXJjvgt9WGAytmMhd7Pz/3DK0
+ 6a9uReXHcU4NcO0BhTP9chwXAQC5pI2ucRxs
+ /4p/Vc/L91wUMA== )
+ 7200 NS ns1.example.de.
+ 7200 NS ns2.example.de.
+ 7200 RRSIG NS 5 2 7200 20080808091515 (
+ 20080729094406 35672 example.de.
+ hpHATL81t7GASSKPPBuheQqBqXU688itETkN
+ QYfy/OwcE/7g+LvS1oHEBRds6neRkXxUpDa1
+ hsdbbCDo6UuHSg== )
+ 7200 NSEC localhost.example.de. NS SOA RRSIG NSEC DNSKEY
+ 7200 RRSIG NSEC 5 2 7200 20080808092007 (
+ 20080729094406 35672 example.de.
+ aN9cYobVe+qJ5Gw0GPMQI3V7vPQaF7cBuX6T
+ +yWZ/TAHhKcJYqbwOQH2XQar2s+JwckEMSdI
+ HFPySUOtQaNNxA== )
+ 3600 DNSKEY 256 3 5 (
+ BQEAAAABnRJdmY7dzRKi93pVkLToV5FK4Ffm
+ 8YnY0c6IHKcAmb5t8FLvpNijniIclCPXTpfi
+ o+HNa59a4UA8jTdJb+kT0w==
+ ) ; key id = 35672
+ 3600 DNSKEY 256 3 5 (
+ BQEAAAAByN2rMrazHwh+sNOv8cBef3HUotAQ
+ TS9QW4Y5NjNuyYNraJBAOqV8KSaGQqIhkh0Z
+ D0oIm2h0JowdyERZVj6ZZQ==
+ ) ; key id = 11867
+ 3600 DNSKEY 257 3 5 (
+ BQEAAAABDfaBERX9p+FUi1OXYVig7zLCQFZo
+ RYpwDDuLzBcC7k+G1+wWdftyA1vBm5HMpyq0
+ OifT0Hsez4+H+0CIWHZP8oPCYfKrq+wM2EgM
+ zDDOYv+O1TQU4i3G+iONxB1RAwH/J2lA+U0z
+ Cbrdf0KLq/enNquchhPw4gCX0RB9HC+TkpoP
+ f2u7aKFcjlpw4C4uhDl1s6FpfdXe6NQWW6c+
+ ONUcLAEt+w==
+ ) ; key id = 59244
+ 3600 DNSKEY 257 3 5 (
+ BQEAAAABDrm5aXRPuZOmwT4nINnY2qXyXWLt
+ utggFAJgBW5Ua7uzAR+7r/DcOE7IfjnT5FQh
+ bYXIuKy61uOEqPu1TYvDsGb1pseKSB4J0jmX
+ DU9Ntu9TDp6X6ZXE11+cFdATa4TPnsAUMSxV
+ kLZanrbyACmcNr1gjT3dz6qIVBVPb5OnUldn
+ dbgtlOX3wcE0aR/MIsIjz1UQl/QoxbVclZVO
+ UNdJQGb9zQ==
+ ) ; key id = 41145
+ 3600 DNSKEY 385 3 5 (
+ BQEAAAABCyg92L7v21N3lc/gR07/2iLmvt6d
+ Un1KKauLvmkRuT040XT+Rd3Iq20iq6BqVPsP
+ S+hCOTRA3xikTIn5YzmPLPutIRtjIodHhsrM
+ L4D9Pp1dzgEDKWLam96v+E7KC0GGH/BI6/We
+ lqeqjS5BjI4Gjv4roaTyDCi63oXwcMFDVwrS
+ jws4A/5AGANka41Aky+UCGse6+64YmNP/QkS
+ XDAeBZqwrw==
+ ) ; key id = 17567
+ 3600 RRSIG DNSKEY 5 2 3600 20080808092214 (
+ 20080729094406 41145 example.de.
+ BMVp5vW7MgvrhoGfqQhdwGg1mBHNw4xnI+YX
+ XMYqOAMMRmFg7G6Vn+UcFmUoL1AdUKIdXPp7
+ t30UREHQspELWmnLVdJ36HRmzk1eNgwLFuUM
+ l+Lr+KeoufJ2QlF4TWeItozv0pgmkxaOr0Im
+ fzRmWKs84rwautwY+R/b5wrCMfZt96/JPGA0
+ 4JWDls1wJ7iR0LtiJxe7mvtNRZ5krPFKXBRz
+ nA== )
+ 3600 RRSIG DNSKEY 5 2 3600 20080808092411 (
+ 20080729094406 17567 example.de.
+ BmHQcJsmGmt7HZHqWPAHQuelDrWXASUy7tgc
+ W4RVIed4voZiHyvxfTPR3cldIWpdP2RqxMm8
+ Dj5hlYRqnVt3phSSnwpczcPkfQD4meTqK0DJ
+ kpX/mBCMHedfvATKf82A9wri13/Zi97N6sTK
+ 4VZZIWaUH/YDYyMwxgK70+jU0m2N8Iebm3s6
+ RshTMxAZjiSH29mgow/HSHtf+cnaTUGAr83P
+ ug== )
+ 3600 RRSIG DNSKEY 5 2 3600 20080808093317 (
+ 20080729094406 35672 example.de.
+ Q5UnfDMbzApCl/wOy9IDna25UVvjKhuV/dos
+ hFKPUArM4wDx9kJU5tc1Eatwh4MAXPM81kNW
+ 6DbiKMXJpO7biQ== )
+localhost.example.de. 7200 IN A 127.0.0.1
+ 7200 RRSIG A 5 3 7200 20080808092724 (
+ 20080729094406 35672 example.de.
+ JW8ScAtavvTR0fHI/ZDZTgARHSXM/QcLT+w6
+ dl6kaeR/9JqxTKpKnH6mtYYdfqom4siJnZCI
+ D66sltGHW/er+Q== )
+ 7200 NSEC ns1.example.de. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080808094047 (
+ 20080729094406 35672 example.de.
+ XsTqHahVRcPPyrdffkdyBj0BFlTx2vkmfrvY
+ IIQcaNiUxrgZfyDBQ1GZbL4tDGK/ujValdz9
+ s2s+6ISxxobC3A== )
+ns1.example.de. 7200 IN A 1.0.0.5
+ 7200 RRSIG A 5 3 7200 20080808091743 (
+ 20080729094406 35672 example.de.
+ ljYOmOC9r3RlsohXrHt40sIQuF98JSkRSFHb
+ xKlcToqEVSgxAKkMlwPKBQPaHtRdQhIVkxly
+ OpCYxAQSguB/MA== )
+ 7200 AAAA 2001:db8::53
+ 7200 RRSIG AAAA 5 3 7200 20080808094144 (
+ 20080729094406 35672 example.de.
+ nNchBWvoPtgRNxaz9bmFwvv/KtgloYq1SGti
+ 59yQFFm6ixY0p0l0d+U5nnwgI1iS5h0JGYqI
+ 0mOu0mNbxtt9gQ== )
+ 7200 NSEC ns2.example.de. A AAAA RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080808092537 (
+ 20080729094406 35672 example.de.
+ MgnxPyKHMqQXnmfjh5ffr0FRvgRyl7D56phx
+ xKzTquSXDECP5ORpDxvybixbvHvM8R59LjYH
+ 1OZ3fi+/kWVAJg== )
+ns2.example.de. 7200 IN A 1.2.0.6
+ 7200 RRSIG A 5 3 7200 20080808091624 (
+ 20080729094406 35672 example.de.
+ MkrwvOLYJQvoNFNeqtLOOmDnVFY0n7qdTOUL
+ Ia2stlfOn7r/7f4lKQTE5UMM+SBN2iizV4qc
+ SFFUxREAI5UGkQ== )
+ 7200 NSEC sub.example.de. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080808094337 (
+ 20080729094406 35672 example.de.
+ QE8DYRraVloZVQi2RTpYwxEY1P0u3ovHgC58
+ AR1NiLtbQ0YCsPJZeIhVSXbdd8qLZzb5gsJ2
+ 9AU6m1TfAa5WSw== )
+sub.example.de. 7200 IN NS ns1.example.de.
+ 7200 DS 40998 5 1 (
+ 1414E9C46F367D787EEF2EC91E1FC66DD087
+ AEAE )
+ 7200 DS 40998 5 2 (
+ 6FE53984AB75C31A06778E9944F8CDB47905
+ 27D36BBD08CC1E90DA7AE32EEE5F )
+ 7200 RRSIG DS 5 3 7200 20080808092142 (
+ 20080729094406 35672 example.de.
+ cdyXeVNOD5TBuab8JFkwcf4GiS2n9F4tgct/
+ ZedULbikEqO0CyJddPW3wSsNAZeP2tgXJNI8
+ H6SutDh0IiR5MA== )
+ 7200 NSEC example.de. NS DS RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080808091754 (
+ 20080729094406 35672 example.de.
+ jkvn4NznbaH8S5PeWkPf/cHaq19kNav8Y78E
+ 3GVQHD3ApcDAMs8gImjRrJMT1lqSB7yCu/5f
+ k3CPfTs/+p/8Og== )
diff --git a/contrib/zkt/examples/hierarchical/de./keyset-example.de. b/contrib/zkt/examples/hierarchical/de./keyset-example.de.
new file mode 100644
index 0000000..2b40c68
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/de./keyset-example.de.
@@ -0,0 +1,28 @@
+$ORIGIN .
+example.de 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABDfaBERX9p+FUi1OXYVig7zLCQFZo
+ RYpwDDuLzBcC7k+G1+wWdftyA1vBm5HMpyq0
+ OifT0Hsez4+H+0CIWHZP8oPCYfKrq+wM2EgM
+ zDDOYv+O1TQU4i3G+iONxB1RAwH/J2lA+U0z
+ Cbrdf0KLq/enNquchhPw4gCX0RB9HC+TkpoP
+ f2u7aKFcjlpw4C4uhDl1s6FpfdXe6NQWW6c+
+ ONUcLAEt+w==
+ ) ; key id = 59244
+ 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABDrm5aXRPuZOmwT4nINnY2qXyXWLt
+ utggFAJgBW5Ua7uzAR+7r/DcOE7IfjnT5FQh
+ bYXIuKy61uOEqPu1TYvDsGb1pseKSB4J0jmX
+ DU9Ntu9TDp6X6ZXE11+cFdATa4TPnsAUMSxV
+ kLZanrbyACmcNr1gjT3dz6qIVBVPb5OnUldn
+ dbgtlOX3wcE0aR/MIsIjz1UQl/QoxbVclZVO
+ UNdJQGb9zQ==
+ ) ; key id = 41145
+ 7200 IN DNSKEY 385 3 5 (
+ BQEAAAABCyg92L7v21N3lc/gR07/2iLmvt6d
+ Un1KKauLvmkRuT040XT+Rd3Iq20iq6BqVPsP
+ S+hCOTRA3xikTIn5YzmPLPutIRtjIodHhsrM
+ L4D9Pp1dzgEDKWLam96v+E7KC0GGH/BI6/We
+ lqeqjS5BjI4Gjv4roaTyDCi63oXwcMFDVwrS
+ jws4A/5AGANka41Aky+UCGse6+64YmNP/QkS
+ XDAeBZqwrw==
+ ) ; key id = 17567
diff --git a/contrib/zkt/examples/hierarchical/dnssec.conf b/contrib/zkt/examples/hierarchical/dnssec.conf
new file mode 100644
index 0000000..12da654
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/dnssec.conf
@@ -0,0 +1,40 @@
+#
+# @(#) dnssec.conf vT0.96 (c) Feb 2005 - May 2008 Holger Zuleger hznet.de
+#
+
+# dnssec-zkt options
+Zonedir: "."
+Recursive: True
+PrintTime: False
+PrintAge: True
+LeftJustify: False
+
+# zone specific values
+ResignInterval: 1w # (604800 seconds)
+Sigvalidity: 10d # (864000 seconds)
+Max_TTL: 6h # (21600 seconds)
+Propagation: 5m # (300 seconds)
+KEY_TTL: 1h # (3600 seconds)
+Serialformat: incremental
+
+# signing key parameters
+KSK_lifetime: 20d # (1728000 seconds)
+KSK_algo: RSASHA1 # (Algorithm ID 5)
+KSK_bits: 1300
+KSK_randfile: "/dev/urandom"
+ZSK_lifetime: 4w # (2419200 seconds)
+ZSK_algo: RSASHA1 # (Algorithm ID 5)
+ZSK_bits: 512
+ZSK_randfile: "/dev/urandom"
+
+# dnssec-signer options
+LogFile: "log"
+LogLevel: "info"
+SyslogFacility: "user"
+SyslogLevel: "notice"
+Keyfile: "dnskey.db"
+Zonefile: "zone.db"
+KeySetDir: ".."
+DLV_Domain: ""
+Sig_Pseudorand: True
+Sig_Parameter: "-j 1800"
diff --git a/contrib/zkt/examples/hierarchical/named.conf b/contrib/zkt/examples/hierarchical/named.conf
new file mode 100644
index 0000000..8bd3f9d
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/named.conf
@@ -0,0 +1,102 @@
+/*****************************************************************
+**
+** #(@) named.conf (c) 6. May 2004 (hoz)
+**
+*****************************************************************/
+
+/*****************************************************************
+** logging options
+*****************************************************************/
+logging {
+ channel "named-log" {
+ file "/var/log/named" versions 3 size 2m;
+ print-time yes;
+ print-category yes;
+ print-severity yes;
+ severity info;
+ };
+ channel "resolver-log" {
+ file "/var/log/named";
+ print-time yes;
+ print-category yes;
+ print-severity yes;
+ severity debug 1;
+ };
+ channel "dnssec-log" {
+# file "/var/log/named-dnssec" ;
+ file "/var/log/named" ;
+ print-time yes;
+ print-category yes;
+ print-severity yes;
+ severity debug 3;
+ };
+ category "dnssec" { "dnssec-log"; };
+ category "default" { "named-log"; };
+ category "resolver" { "resolver-log"; };
+ category "client" { "resolver-log"; };
+ category "queries" { "resolver-log"; };
+};
+
+/*****************************************************************
+** name server options
+*****************************************************************/
+options {
+ directory ".";
+
+ dump-file "/var/log/named_dump.db";
+ statistics-file "/var/log/named.stats";
+
+ listen-on-v6 { any; };
+
+ query-source address * port 53;
+ transfer-source * port 53;
+ notify-source * port 53;
+
+ recursion yes;
+ dnssec-enable yes;
+ edns-udp-size 4096;
+
+# dnssec-lookaside "." trust-anchor "trusted-keys.de.";
+
+ querylog yes;
+
+};
+
+/*****************************************************************
+** include shared secrets...
+*****************************************************************/
+/** for control sessions ... **/
+# include "rndc.key";
+controls {
+ inet 127.0.0.1
+ allow { localhost; }
+ keys { "rndc-key"; };
+ inet ::1
+ allow { localhost; }
+ keys { "rndc-key"; };
+};
+
+/*****************************************************************
+** ... and trusted_keys
+*****************************************************************/
+# include "trusted-keys.conf" ;
+
+/*****************************************************************
+** root server hints and required 127 stuff
+*****************************************************************/
+zone "." in {
+ type hint;
+ file "root.hint";
+};
+
+zone "localhost" in {
+ type master;
+ file "localhost.zone";
+};
+
+zone "0.0.127.in-addr.arpa" in {
+ type master;
+ file "127.0.0.zone";
+};
+
+include "zone.conf";
diff --git a/contrib/zkt/examples/hierarchical/zone.conf b/contrib/zkt/examples/hierarchical/zone.conf
new file mode 100644
index 0000000..6944d5a
--- /dev/null
+++ b/contrib/zkt/examples/hierarchical/zone.conf
@@ -0,0 +1,10 @@
+
+zone "example.de." in {
+ type master;
+ file "de./example.de./zone.db.signed";
+};
+
+zone "sub.example.de." in {
+ type master;
+ file "de./example.de./sub.example.de./zone.db.signed";
+};
diff --git a/contrib/zkt/examples/views/dnssec-extern.conf b/contrib/zkt/examples/views/dnssec-extern.conf
new file mode 100644
index 0000000..728dcc9
--- /dev/null
+++ b/contrib/zkt/examples/views/dnssec-extern.conf
@@ -0,0 +1,39 @@
+#
+# @(#) dnssec.conf vT0.96 (c) Feb 2005 - May 2008 Holger Zuleger hznet.de
+#
+
+# dnssec-zkt options
+Zonedir: "extern"
+Recursive: True
+PrintTime: False
+PrintAge: True
+LeftJustify: False
+
+# zone specific values
+ResignInterval: 1w # (604800 seconds)
+Sigvalidity: 10d # (864000 seconds)
+Max_TTL: 8h # (28800 seconds)
+Propagation: 5m # (300 seconds)
+KEY_TTL: 1h # (3600 seconds)
+Serialformat: unixtime
+
+# signing key parameters
+KSK_lifetime: 1y # (31536000 seconds)
+KSK_algo: RSASHA1 # (Algorithm ID 5)
+KSK_bits: 1300
+KSK_randfile: "/dev/urandom"
+ZSK_lifetime: 30d # (2592000 seconds)
+ZSK_algo: RSASHA1 # (Algorithm ID 5)
+ZSK_bits: 512
+ZSK_randfile: "/dev/urandom"
+
+# dnssec-signer options
+LogFile: "zkt-ext.log"
+LogLevel: "debug"
+SyslogFacility: "none"
+SyslogLevel: "notice"
+VerboseLog: 2
+Keyfile: "dnskey.db"
+Zonefile: "zone.db"
+DLV_Domain: ""
+Sig_Pseudorand: True
diff --git a/contrib/zkt/examples/views/dnssec-intern.conf b/contrib/zkt/examples/views/dnssec-intern.conf
new file mode 100644
index 0000000..d49fc94
--- /dev/null
+++ b/contrib/zkt/examples/views/dnssec-intern.conf
@@ -0,0 +1,39 @@
+#
+# @(#) dnssec.conf vT0.96 (c) Feb 2005 - May 2008 Holger Zuleger hznet.de
+#
+
+# dnssec-zkt options
+Zonedir: "intern"
+Recursive: True
+PrintTime: False
+PrintAge: True
+LeftJustify: False
+
+# zone specific values
+ResignInterval: 5h # (18000 seconds)
+Sigvalidity: 1d # (86400 seconds)
+Max_TTL: 30m # (1800 seconds)
+Propagation: 1m # (60 seconds)
+KEY_TTL: 30m # (1800 seconds)
+Serialformat: unixtime
+
+# signing key parameters
+KSK_lifetime: 1y # (31536000 seconds)
+KSK_algo: RSASHA1 # (Algorithm ID 5)
+KSK_bits: 1300
+KSK_randfile: "/dev/urandom"
+ZSK_lifetime: 30d # (2592000 seconds)
+ZSK_algo: RSASHA1 # (Algorithm ID 5)
+ZSK_bits: 512
+ZSK_randfile: "/dev/urandom"
+
+# dnssec-signer options
+LogFile: "zkt-int.log"
+LogLevel: "debug"
+SyslogFacility: "none"
+SyslogLevel: "notice"
+VerboseLog: 2
+Keyfile: "dnskey.db"
+Zonefile: "zone.db"
+DLV_Domain: ""
+Sig_Pseudorand: True
diff --git a/contrib/zkt/examples/views/dnssec-signer-extern b/contrib/zkt/examples/views/dnssec-signer-extern
new file mode 100755
index 0000000..910e82a
--- /dev/null
+++ b/contrib/zkt/examples/views/dnssec-signer-extern
@@ -0,0 +1,7 @@
+#!/bin/sh
+#
+# Shell script to start the dnssec-signer
+# command out of the view directory
+#
+
+ZKT_CONFFILE=`pwd`/dnssec.conf ../../dnssec-signer -V extern "$@"
diff --git a/contrib/zkt/examples/views/dnssec-signer-intern b/contrib/zkt/examples/views/dnssec-signer-intern
new file mode 100755
index 0000000..915ed15
--- /dev/null
+++ b/contrib/zkt/examples/views/dnssec-signer-intern
@@ -0,0 +1,7 @@
+#!/bin/sh
+#
+# Shell script to start the dnssec-signer
+# command out of the view directory
+#
+
+ZKT_CONFFILE=`pwd`/dnssec.conf ../../dnssec-signer -V intern "$@"
diff --git a/contrib/zkt/examples/views/dnssec-zkt-extern b/contrib/zkt/examples/views/dnssec-zkt-extern
new file mode 100755
index 0000000..129b4e1
--- /dev/null
+++ b/contrib/zkt/examples/views/dnssec-zkt-extern
@@ -0,0 +1,7 @@
+#!/bin/sh
+#
+# Shell script to start the dnssec-zkt command
+# out of the view directory
+#
+
+ZKT_CONFFILE=`pwd`/dnssec.conf ../../dnssec-zkt --view extern "$@"
diff --git a/contrib/zkt/examples/views/dnssec-zkt-intern b/contrib/zkt/examples/views/dnssec-zkt-intern
new file mode 100755
index 0000000..1836840
--- /dev/null
+++ b/contrib/zkt/examples/views/dnssec-zkt-intern
@@ -0,0 +1,7 @@
+#!/bin/sh
+#
+# Shell script to start the dnssec-zkt command
+# out of the view directory
+#
+
+ZKT_CONFFILE=`pwd`/dnssec.conf ../../dnssec-zkt --view intern "$@"
diff --git a/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+10367.key b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+10367.key
new file mode 100644
index 0000000..54ba934
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+10367.key
@@ -0,0 +1,3 @@
+;% generationtime=20080609231143
+;% lifetime=30d
+example.net. IN DNSKEY 256 3 5 BQEAAAAB3U9DMT6BkywYADO+5p0lG4VFLLzNvJUMaOc++HqN2N1sKSX4 ZTf2V5gtamPZ/1kMrg8gYImKCl6n3K37EjXYBw==
diff --git a/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+10367.published b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+10367.published
new file mode 100644
index 0000000..7240075
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+10367.published
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: 3U9DMT6BkywYADO+5p0lG4VFLLzNvJUMaOc++HqN2N1sKSX4ZTf2V5gtamPZ/1kMrg8gYImKCl6n3K37EjXYBw==
+PublicExponent: AQAAAAE=
+PrivateExponent: Q3TKb2j5AMk4wn9q5vvgtEy7o1VAhCvv/Nw3QRpXi7xGeHb7WJHj2ia2I44vQQk9fB+Kck1M8KNRMgYt0d0xCQ==
+Prime1: 7l4yn7VYrTSOaZu+lubsFvE+JB7asyYyymAEQeod2p0=
+Prime2: 7a4LEAmrtZTI/PHjdk/Ij/hbpDmtOe1H0lnWTVG+GfM=
+Exponent1: DTpyBBW39+d9b8LqCo7hJf5KQ3oVw9tdnUuHNstGZd0=
+Exponent2: b+aBbhRPr/a9ZCNM2JTjZJrrSebtMQCy1GcE33o64HM=
+Coefficient: UdvxnKd2GL6In82yHG40rU35WTZ2SUYQ+1mfz3DQqnE=
diff --git a/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+23553.key b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+23553.key
new file mode 100644
index 0000000..ec11dcb
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+23553.key
@@ -0,0 +1 @@
+example.net. IN DNSKEY 257 3 5 BQEAAAABDEEycfY6uqWNTpQO8ygi9xms6NOFYGhCjijN109fVGJ4KDnI ZtLhoFrOKru9rZn+pyqurlyZG4vESg0BMty6xljVDlr/TegDYFTN19mQ uwvlasJhZPv9pjROPqQGnqLaw3O4OKCY9HgTTPdXK1hQ4Mg2rNU4SM2T u5ki91f5AQqiXF8KYMics0mwVvpj5C2YTDvE9SafLrce68JM6DaiC6E1 sQ==
diff --git a/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+23553.private b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+23553.private
new file mode 100644
index 0000000..ea29447
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+23553.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: DEEycfY6uqWNTpQO8ygi9xms6NOFYGhCjijN109fVGJ4KDnIZtLhoFrOKru9rZn+pyqurlyZG4vESg0BMty6xljVDlr/TegDYFTN19mQuwvlasJhZPv9pjROPqQGnqLaw3O4OKCY9HgTTPdXK1hQ4Mg2rNU4SM2Tu5ki91f5AQqiXF8KYMics0mwVvpj5C2YTDvE9SafLrce68JM6DaiC6E1sQ==
+PublicExponent: AQAAAAE=
+PrivateExponent: A3ZXTF8afjlxddgO/sDxotc0XLBMa3sNrXhCpdFzeDV1HszZbz1lP8rrZjA1wQgSo56DjiGRKTsHjAAm4xN1lGYKBZuVF4U3uiWie2PhJStt7kckNduKOfV9Nofow5Jh8I2lXKqcOJ8Qd+EJYIsajdBoGQ72PGGfDaHphbN/mW13n59PlilMF4RRRybcMA6jTAOfvIcv5Mes3+ADh0TktHdHQQ==
+Prime1: A+SKyrgtNzGVpAXPQysMQ9O/10B/+nhy6//1F5Epxihyuln+d2euh+TjVneojx4D2JUflDUSD5BQAdflDb+KiBXdQjBEmqfWwY+INwSQzv4M5Q==
+Prime2: AyXovkiIs7ywIRS6FfRolMMUeh3yeYNtCVAvLB6EC2MiNCzfkDOFB7rpmUkZR8HYUWuz1hQfR781RDO81Sp3RIpSyL7SwOqkpMZyaSgK/GKE3Q==
+Exponent1: D1vC405mkcUVfno92EuBXomRiOG7VeSyjwofgCpa0JKR6J2BThdCGrcVbq68ucIddn+cbkD8JsZB3k4aeDYFxm6d1En1Z2C1cVHrzCFi2zFV
+Exponent2: N+iliM1Qp3spcsR06kXImb/N4FosHrZkXtcbRIMWhV8NBcyqLDIfGlNluaiztv4rf6Kn2UyVeiGC822nqZHcW5PiXJnBEWs9AC4Di1QzZh0h
+Coefficient: AtZ4sYqGgyB5kfdcQBBlIkPbsRRNKrUVAsZkjabdZTQa+ox6tYnlVjh7BgPMHJlj/Z4VTRJ5rfAUPnB4ZwO/r1eAJLd+vxjJb9M7DaGMc+RqQA==
diff --git a/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+35744.key b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+35744.key
new file mode 100644
index 0000000..1809a93
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+35744.key
@@ -0,0 +1,4 @@
+;% generationtime=20071217224527
+;% lifetime=30
+;% expiretime=20080116224527
+example.net. IN DNSKEY 256 3 5 BQEAAAABsQvn4MXvSlbajLPMJdGnczsX/Zw5yYSeERYtaO2Wxi+kHz6w iAyKkbBYFUGtmbPJ6JFt+4f9KnNPi1txiBg76Q==
diff --git a/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+35744.private b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+35744.private
new file mode 100644
index 0000000..ca789eb
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./Kexample.net.+005+35744.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: sQvn4MXvSlbajLPMJdGnczsX/Zw5yYSeERYtaO2Wxi+kHz6wiAyKkbBYFUGtmbPJ6JFt+4f9KnNPi1txiBg76Q==
+PublicExponent: AQAAAAE=
+PrivateExponent: fZs/S7/pOPP1C9Jjdb7KhnbfiLfCIXdc7d8LDWmm7d9rL2kZK77WMp+o5WRQhoIDDQPAdv+phoIdFEIiXKLN8Q==
+Prime1: 6NEgG3Z86nn9fNjG+3E9OqF/7oaCvrVnb1XogalZgr0=
+Prime2: wq0aosO1mWXo38HuxO5JiR2mX/9LWjxxqwK6I9gnJp0=
+Exponent1: ZvI2y//PImr1OqeVLoWfFHop2iorgT4+SYiz1Gw9FME=
+Exponent2: TBUeoolmnFcOfWO6T1v0S6za7LEib2H1Pgt95UvDA40=
+Coefficient: eHmKka0EVRfjDfEpcwRp5nZ36ZHfLxuKF5tGQ1YclBI=
diff --git a/contrib/zkt/examples/views/extern/example.net./dnskey.db b/contrib/zkt/examples/views/extern/example.net./dnskey.db
new file mode 100644
index 0000000..d46eff9
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./dnskey.db
@@ -0,0 +1,30 @@
+;
+; !!! Don't edit this file by hand.
+; !!! It will be generated by dnssec-signer.
+;
+; Last generation time Jun 12 2008 17:56:05
+;
+
+; *** List of Key Signing Keys ***
+; example.net. tag=23553 algo=RSASHA1 generated Nov 20 2007 12:49:04
+example.net. 3600 IN DNSKEY 257 3 5 (
+ BQEAAAABDEEycfY6uqWNTpQO8ygi9xms6NOFYGhCjijN109fVGJ4KDnI
+ ZtLhoFrOKru9rZn+pyqurlyZG4vESg0BMty6xljVDlr/TegDYFTN19mQ
+ uwvlasJhZPv9pjROPqQGnqLaw3O4OKCY9HgTTPdXK1hQ4Mg2rNU4SM2T
+ u5ki91f5AQqiXF8KYMics0mwVvpj5C2YTDvE9SafLrce68JM6DaiC6E1
+ sQ==
+ ) ; key id = 23553
+
+; *** List of Zone Signing Keys ***
+; example.net. tag=35744 algo=RSASHA1 generated Jun 10 2008 01:11:43
+example.net. 3600 IN DNSKEY 256 3 5 (
+ BQEAAAABsQvn4MXvSlbajLPMJdGnczsX/Zw5yYSeERYtaO2Wxi+kHz6w
+ iAyKkbBYFUGtmbPJ6JFt+4f9KnNPi1txiBg76Q==
+ ) ; key id = 35744
+
+; example.net. tag=10367 algo=RSASHA1 generated Jun 10 2008 01:11:43
+example.net. 3600 IN DNSKEY 256 3 5 (
+ BQEAAAAB3U9DMT6BkywYADO+5p0lG4VFLLzNvJUMaOc++HqN2N1sKSX4
+ ZTf2V5gtamPZ/1kMrg8gYImKCl6n3K37EjXYBw==
+ ) ; key id = 10367
+
diff --git a/contrib/zkt/examples/views/extern/example.net./dsset-example.net. b/contrib/zkt/examples/views/extern/example.net./dsset-example.net.
new file mode 100644
index 0000000..cbcd3d0
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./dsset-example.net.
@@ -0,0 +1,2 @@
+example.net. IN DS 23553 5 1 A1A6D06CB84D619730F605AEF2A6DD4148DD9D5B
+example.net. IN DS 23553 5 2 B0DCAB8A32C230495CEC1FD61CEC03849450909CA6636FD9BC53D1B3 3B4F3A2D
diff --git a/contrib/zkt/examples/views/extern/example.net./keyset-example.net. b/contrib/zkt/examples/views/extern/example.net./keyset-example.net.
new file mode 100644
index 0000000..b845245
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./keyset-example.net.
@@ -0,0 +1,10 @@
+$ORIGIN .
+example.net 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABDEEycfY6uqWNTpQO8ygi9xms6NOF
+ YGhCjijN109fVGJ4KDnIZtLhoFrOKru9rZn+
+ pyqurlyZG4vESg0BMty6xljVDlr/TegDYFTN
+ 19mQuwvlasJhZPv9pjROPqQGnqLaw3O4OKCY
+ 9HgTTPdXK1hQ4Mg2rNU4SM2Tu5ki91f5AQqi
+ XF8KYMics0mwVvpj5C2YTDvE9SafLrce68JM
+ 6DaiC6E1sQ==
+ ) ; key id = 23553
diff --git a/contrib/zkt/examples/views/extern/example.net./zone.db b/contrib/zkt/examples/views/extern/example.net./zone.db
new file mode 100644
index 0000000..4c72928
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./zone.db
@@ -0,0 +1,33 @@
+;-----------------------------------------------------------------
+;
+; @(#) extern/example.net/zone.db
+;
+;-----------------------------------------------------------------
+
+$TTL 7200
+
+@ IN SOA ns1.example.net. hostmaster.example.net. (
+ 0 ; Serial
+ 43200 ; Refresh
+ 1800 ; Retry
+ 2W ; Expire
+ 7200 ) ; Minimum
+
+ IN NS ns1.example.net.
+ IN NS ns2.example.net.
+
+ns1 IN A 1.0.0.5
+ IN AAAA 2001:db8::53
+ns2 IN A 1.2.0.6
+
+localhost IN A 127.0.0.1
+
+; Delegation to secure zone; The DS resource record will
+; be added by dnssec-signzone automatically if the
+; keyset-sub.example.net file is present (run dnssec-signzone
+; with option -g or use the dnssec-signer tool) ;-)
+sub IN NS ns1.example.net.
+
+; this file will have all the zone keys
+$INCLUDE dnskey.db
+
diff --git a/contrib/zkt/examples/views/extern/example.net./zone.db.signed b/contrib/zkt/examples/views/extern/example.net./zone.db.signed
new file mode 100644
index 0000000..c0e2801
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/example.net./zone.db.signed
@@ -0,0 +1,109 @@
+; File written on Thu Jun 12 17:56:06 2008
+; dnssec_signzone version 9.5.0
+example.net. 7200 IN SOA ns1.example.net. hostmaster.example.net. (
+ 1213286165 ; serial
+ 43200 ; refresh (12 hours)
+ 1800 ; retry (30 minutes)
+ 1209600 ; expire (2 weeks)
+ 7200 ; minimum (2 hours)
+ )
+ 7200 RRSIG SOA 5 2 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ iSF46kemTmJ62ipRyAzcVF0zlND4ZXdMSzAg
+ wGLfXN1xlgt0IwB8ypP1OjDyUx+YwBpbMlJt
+ tFsswvYaZtP11Q== )
+ 7200 NS ns1.example.net.
+ 7200 NS ns2.example.net.
+ 7200 RRSIG NS 5 2 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ fmC9BXzFcy6TRXixIHk51TYTetGd69YcRguc
+ VlqTalvPJTJ99nKkRS5HdP2CZPJqv9bHOmSO
+ yQibjS4TA5Pr3g== )
+ 7200 NSEC localhost.example.net. NS SOA RRSIG NSEC DNSKEY
+ 7200 RRSIG NSEC 5 2 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ kimcFA1awlsIou/66y2XLByBWKc2e7Wm8vis
+ Pz/i0NS4NFoe+oSKIeIjUorWOSf5AkpxxntV
+ 91i/sxof6bc61w== )
+ 3600 DNSKEY 256 3 5 (
+ BQEAAAABsQvn4MXvSlbajLPMJdGnczsX/Zw5
+ yYSeERYtaO2Wxi+kHz6wiAyKkbBYFUGtmbPJ
+ 6JFt+4f9KnNPi1txiBg76Q==
+ ) ; key id = 35744
+ 3600 DNSKEY 256 3 5 (
+ BQEAAAAB3U9DMT6BkywYADO+5p0lG4VFLLzN
+ vJUMaOc++HqN2N1sKSX4ZTf2V5gtamPZ/1kM
+ rg8gYImKCl6n3K37EjXYBw==
+ ) ; key id = 10367
+ 3600 DNSKEY 257 3 5 (
+ BQEAAAABDEEycfY6uqWNTpQO8ygi9xms6NOF
+ YGhCjijN109fVGJ4KDnIZtLhoFrOKru9rZn+
+ pyqurlyZG4vESg0BMty6xljVDlr/TegDYFTN
+ 19mQuwvlasJhZPv9pjROPqQGnqLaw3O4OKCY
+ 9HgTTPdXK1hQ4Mg2rNU4SM2Tu5ki91f5AQqi
+ XF8KYMics0mwVvpj5C2YTDvE9SafLrce68JM
+ 6DaiC6E1sQ==
+ ) ; key id = 23553
+ 3600 RRSIG DNSKEY 5 2 3600 20080622145605 (
+ 20080612145605 23553 example.net.
+ Bfg8AMvj3OmC7E5aMCfotsdL4eJ+hPqtH30E
+ +aGEJojZNgfhnSKZrolMJa5fij4oZ+Fp8U+a
+ V73egxkrYI+NnddGRVium+vT6NDVknYl6hx0
+ kgKmZ8oYMulF8CCmTaw6WXswIX0j/7e17Qtw
+ ZjbkWZagIXWotE5t0qel3doAQ37ZUaKMMAoc
+ SRgJ8s+w7OZ86f1kWyGNdhYeF8yY3AraSx7h
+ fg== )
+ 3600 RRSIG DNSKEY 5 2 3600 20080622145605 (
+ 20080612145605 35744 example.net.
+ SrsmKW7eB+zWA+8j2DvlDktthDusinJP4QKV
+ ihsJN1Gq8fTcHsFX2+3EJLyGZfhKyW7Q5Z1W
+ dIM4sjx78Zjh5Q== )
+localhost.example.net. 7200 IN A 127.0.0.1
+ 7200 RRSIG A 5 3 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ DUWSV0Wj/h1U4idKUoDLB+NXgj8M9et1E8BP
+ X0lhAu4CMrPhsiFU1NN+N3bhC16u7S+xxeEI
+ N/c7vC223ejn8A== )
+ 7200 NSEC ns1.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ qQ7FB0+O9Ve88VblRspGAm28JXurNAQ23HX9
+ rkmbFLL/Z7Xp7xO2899oJZrgHl3CWLcKRBV+
+ P50QYwYXET3byw== )
+ns1.example.net. 7200 IN A 1.0.0.5
+ 7200 RRSIG A 5 3 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ qv8y5gEQg/5BpSTMoZvwW6AAzMIxT34ds4VK
+ QQ9ScfVYOwtKigsaFmr8Zs97R946rl5vh/cs
+ w8uw5x6/1ECflg== )
+ 7200 AAAA 2001:db8::53
+ 7200 RRSIG AAAA 5 3 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ T5MtLR9ZY0e6PKk+nU9cjRpSAWaccH2bGjzI
+ aYEvKRFcLQ0QPDww8gBZNimYL+BYfCSysyXz
+ LNjR7KqYQxrXmg== )
+ 7200 NSEC ns2.example.net. A AAAA RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ IlRZWwLVtf7oalaLBCMbqH4pxgqCJ7f0wQzO
+ ftS2jhMGVez+q7SgO8Vpw5f+vhNiSWe6noiN
+ ogRV1rxohxDyCw== )
+ns2.example.net. 7200 IN A 1.2.0.6
+ 7200 RRSIG A 5 3 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ NR3Nkw9U12uZcZs8ChTY+u3a0QisLV/5okqR
+ Cy1Jpg8YkEzBJ0nEdxoGX6WUtnb0u5Kjxea1
+ iTZYEXffLBchmw== )
+ 7200 NSEC sub.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ eM1ckSfeiEg6pV8JxJEEkDeDo04i1iblO6a1
+ pWydc4IGMH0vaCuGHvLlfCmSOZK7TWMFSLJN
+ SqabEFO1114AyQ== )
+sub.example.net. 7200 IN NS ns1.example.net.
+ 7200 NSEC example.net. NS RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080622145605 (
+ 20080612145605 35744 example.net.
+ nwfqNjzYHKtWWsJgoiM9ZQFY9UKHMS6pkyNB
+ ISgm6pTLeG9QXuwf9vTrtfvhPYAp5DRz96AT
+ db/3/DXIwUnMnA== )
diff --git a/contrib/zkt/examples/views/extern/zkt-ext.log b/contrib/zkt/examples/views/extern/zkt-ext.log
new file mode 100644
index 0000000..04fa4fb
--- /dev/null
+++ b/contrib/zkt/examples/views/extern/zkt-ext.log
@@ -0,0 +1,28 @@
+2008-06-12 17:59:04.194: notice: running as ../../dnssec-signer -V extern -v -v
+2008-06-12 17:59:04.195: debug: parsing zone "example.net." in dir "extern/example.net."
+2008-06-12 17:59:04.196: debug: Check RFC5011 status
+2008-06-12 17:59:04.196: debug: ->ksk5011status returns 0
+2008-06-12 17:59:04.196: debug: Check ksk status
+2008-06-12 17:59:04.196: debug: Re-signing not necessary!
+2008-06-12 17:59:04.196: notice: end of run: 0 errors occured
+2008-06-12 17:59:17.435: notice: running as ../../dnssec-signer -V extern -v -v
+2008-06-12 17:59:17.436: debug: parsing zone "example.net." in dir "extern/example.net."
+2008-06-12 17:59:17.436: debug: Check RFC5011 status
+2008-06-12 17:59:17.436: debug: ->ksk5011status returns 0
+2008-06-12 17:59:17.436: debug: Check ksk status
+2008-06-12 17:59:17.436: debug: Re-signing not necessary!
+2008-06-12 17:59:17.436: notice: end of run: 0 errors occured
+2008-06-12 18:00:07.818: notice: running as ../../dnssec-signer -V extern -v -v
+2008-06-12 18:00:07.819: debug: parsing zone "example.net." in dir "extern/example.net."
+2008-06-12 18:00:07.819: debug: Check RFC5011 status
+2008-06-12 18:00:07.819: debug: ->ksk5011status returns 0
+2008-06-12 18:00:07.819: debug: Check ksk status
+2008-06-12 18:00:07.819: debug: Re-signing not necessary!
+2008-06-12 18:00:07.819: notice: end of run: 0 errors occured
+2008-06-12 18:00:39.019: notice: running as ../../dnssec-signer -V extern -v -v
+2008-06-12 18:00:39.020: debug: parsing zone "example.net." in dir "extern/example.net."
+2008-06-12 18:00:39.020: debug: Check RFC5011 status
+2008-06-12 18:00:39.020: debug: ->ksk5011status returns 0
+2008-06-12 18:00:39.020: debug: Check ksk status
+2008-06-12 18:00:39.020: debug: Re-signing not necessary!
+2008-06-12 18:00:39.020: notice: end of run: 0 errors occured
diff --git a/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+00126.key b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+00126.key
new file mode 100644
index 0000000..316e4cf
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+00126.key
@@ -0,0 +1 @@
+example.net. IN DNSKEY 257 3 5 BQEAAAABC+JLXRgWPqqGe0cta8CR95tz7PkkgRDlXyxESD+XkpVDkJ3W ey/1Lh7083Ve1WmIuUAo3N4d7HjLgrFVZxiumGGRz/aV3s01OFFS5JqI wF9BTNrNPGLPzzbBaQMHErO88HIbbg4sot7e6bSrtpAEf23MhZ3qZJC9 +nN+DknmsgTE6EpK6ZyUrZc64/0K68EWhtk1gf95NQEzTD4QgrOD6IYq Lw==
diff --git a/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+00126.private b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+00126.private
new file mode 100644
index 0000000..96e1ff6
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+00126.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: C+JLXRgWPqqGe0cta8CR95tz7PkkgRDlXyxESD+XkpVDkJ3Wey/1Lh7083Ve1WmIuUAo3N4d7HjLgrFVZxiumGGRz/aV3s01OFFS5JqIwF9BTNrNPGLPzzbBaQMHErO88HIbbg4sot7e6bSrtpAEf23MhZ3qZJC9+nN+DknmsgTE6EpK6ZyUrZc64/0K68EWhtk1gf95NQEzTD4QgrOD6IYqLw==
+PublicExponent: AQAAAAE=
+PrivateExponent: CF6/bss8OtQFdcjO6kJh9EamPFXAsaXFCdcYpHF55CU4H3jBuu7teLFEanvgm6M+wROYF0Yohiyb2aeSBdGLRIfTC9l3xfHD+XixuZVoNk6DqR1/8Wlxwu/a/hW9dq7pUXqDfTbzdZKR6SVRPa4MAdQ0p8aSF4S926NRqZC6E/anqhqNPSlBpxTs3TrRk+wY6u8wMXxPGNjJYoID8Y0Qau/H6Q==
+Prime1: A50B7etEtQCDudL8+KBxU1/2sVT3ORMfoZPsOe+ZLFrwcOO9Iyrr6saymuD4QvcIHECdLUM5rsT1JBo87wgvVysibco7oVLxlIfsTcbM70l2Kw==
+Prime2: A0n3+qM3ng3WAFzlpYRNUZpH/CW1pMq3nOHjx2olWwDxDZ4tAsUPKuW9n3kVZAR+4FkeUKn2ePR7xRtO3AzvA6QmZuZN6EHuLPlSKRufzeZ+DQ==
+Exponent1: Hk5KY5PiXs6pf8T8rSvVs6PJqDX491R01ZDdAIDYjmhIUHKWQ2STAlPEpSAGXi+oqOo4dD1eJWgw36hT0JakjXU4aIvPoSdmVPMs8aod0NUh
+Exponent2: AXKBZ5sYApCCj/0fGBTkmU6Zc89/ddQNrFm2lVLrwSTILHQWm/aXDvI+5icpF5kdrukVcNHUeCz1R/RTgeV4N9/qvr5YzbPWieqDNvpG1RcNRQ==
+Coefficient: BZxK+fKwUNWoJ5huBqLsi8UMWgrCMqAfXvge4+Y4n4IL0VCU1UUEXZQEEeiATh0g52CuetOMej6FZ4QKbNryWg036ZKl81ataMGtDX/i/yZG
diff --git a/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+05972.key b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+05972.key
new file mode 100644
index 0000000..8be3973
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+05972.key
@@ -0,0 +1 @@
+example.net. IN DNSKEY 256 3 5 BQEAAAABsMIdQ+yt52Q/OR1s+QPj7SuBydYb11l0HC5kGIDp+JPQIQHx pyCWa/LaLgcvK3IA1HR8YaO3QXB2LAHEz5B/CQ==
diff --git a/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+05972.private b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+05972.private
new file mode 100644
index 0000000..b519641
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+05972.private
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: sMIdQ+yt52Q/OR1s+QPj7SuBydYb11l0HC5kGIDp+JPQIQHxpyCWa/LaLgcvK3IA1HR8YaO3QXB2LAHEz5B/CQ==
+PublicExponent: AQAAAAE=
+PrivateExponent: fpWuYAOXJWdjMrZnI91hTi1wwuje4sKjDu8xvfnKvqKhr61QxK1gR9TB3mc2FM+Awivphb3xfi8+y2cacq9iUQ==
+Prime1: 6DE1tFJXGIm2SW3fSwQymX7Zcw8VSIMWiHQPCqX1FA0=
+Prime2: wuHS7u0I9aYOFkDAndfEVyDi8vOh96CcY/BuSvEZ6+0=
+Exponent1: sn7RttKPap3cgw2sddmgwcuVSaEpwOswF/O42Ou3fMk=
+Exponent2: LoJ305VksT7SWWR6bM5OybcdTm39PTZM0g3V2hOceK0=
+Coefficient: SwRF9S9ICVeyeYw3djxbg7kUZjz5AkbHIgz9VeX4mzM=
diff --git a/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+23375.key b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+23375.key
new file mode 100644
index 0000000..160110e
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+23375.key
@@ -0,0 +1,3 @@
+;% generationtime=20080612154545
+;% lifetime=30d
+example.net. IN DNSKEY 256 3 5 BQEAAAABzbx90CiFrOSh0/BkiRQYRC4rHL0QQv96Qwy5/zuOa/3Zy9Lc TpbE13DtEAqOfVGSQ79S4WgKalFJxq6lSk0xrw==
diff --git a/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+23375.published b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+23375.published
new file mode 100644
index 0000000..60e4316
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./Kexample.net.+005+23375.published
@@ -0,0 +1,10 @@
+Private-key-format: v1.2
+Algorithm: 5 (RSASHA1)
+Modulus: zbx90CiFrOSh0/BkiRQYRC4rHL0QQv96Qwy5/zuOa/3Zy9LcTpbE13DtEAqOfVGSQ79S4WgKalFJxq6lSk0xrw==
+PublicExponent: AQAAAAE=
+PrivateExponent: XZK4eHRUrFka7O0Q/RBuBG3iW8KFng5em4FnjCSBQpwSAvFzTBebqwfNSOcgqKihz8VzvKHxEd6BxVZRGI2dgQ==
+Prime1: 8Jji5R57Y4ROxrO5EuEFjxL723VQ/Ym+4KYG+tM3bP8=
+Prime2: 2uhGRdJU3UJvnPwx0gJGio6KmRBC6CmDqTMORhYrS1E=
+Exponent1: cqVno4KLgMmKN5VPWaYA+pB5e55r6UEIaxqj6WMXATs=
+Exponent2: EqSKzb/r02jmNCTv5aX7wHl+57LYR40rJvzgVTfh/tE=
+Coefficient: 37ywfYlNFmtR/jZwoZBHNdIEy+C+jIeJ+fEepesSpoI=
diff --git a/contrib/zkt/examples/views/intern/example.net./dnskey.db b/contrib/zkt/examples/views/intern/example.net./dnskey.db
new file mode 100644
index 0000000..9e2c47f
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./dnskey.db
@@ -0,0 +1,30 @@
+;
+; !!! Don't edit this file by hand.
+; !!! It will be generated by dnssec-signer.
+;
+; Last generation time Jun 12 2008 18:13:43
+;
+
+; *** List of Key Signing Keys ***
+; example.net. tag=126 algo=RSASHA1 generated Nov 20 2007 12:44:27
+example.net. 1800 IN DNSKEY 257 3 5 (
+ BQEAAAABC+JLXRgWPqqGe0cta8CR95tz7PkkgRDlXyxESD+XkpVDkJ3W
+ ey/1Lh7083Ve1WmIuUAo3N4d7HjLgrFVZxiumGGRz/aV3s01OFFS5JqI
+ wF9BTNrNPGLPzzbBaQMHErO88HIbbg4sot7e6bSrtpAEf23MhZ3qZJC9
+ +nN+DknmsgTE6EpK6ZyUrZc64/0K68EWhtk1gf95NQEzTD4QgrOD6IYq
+ Lw==
+ ) ; key id = 126
+
+; *** List of Zone Signing Keys ***
+; example.net. tag=5972 algo=RSASHA1 generated Nov 20 2007 12:44:27
+example.net. 1800 IN DNSKEY 256 3 5 (
+ BQEAAAABsMIdQ+yt52Q/OR1s+QPj7SuBydYb11l0HC5kGIDp+JPQIQHx
+ pyCWa/LaLgcvK3IA1HR8YaO3QXB2LAHEz5B/CQ==
+ ) ; key id = 5972
+
+; example.net. tag=23375 algo=RSASHA1 generated Jun 12 2008 17:45:45
+example.net. 1800 IN DNSKEY 256 3 5 (
+ BQEAAAABzbx90CiFrOSh0/BkiRQYRC4rHL0QQv96Qwy5/zuOa/3Zy9Lc
+ TpbE13DtEAqOfVGSQ79S4WgKalFJxq6lSk0xrw==
+ ) ; key id = 23375
+
diff --git a/contrib/zkt/examples/views/intern/example.net./dsset-example.net. b/contrib/zkt/examples/views/intern/example.net./dsset-example.net.
new file mode 100644
index 0000000..b61c1b6
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./dsset-example.net.
@@ -0,0 +1,2 @@
+example.net. IN DS 126 5 1 D32161DCFCA120944CB9C0394CBED1389FDB72CA
+example.net. IN DS 126 5 2 351C6807B25E47223D7A6AA222291E8D7D7DDDA61D64CE839F937F22 47481FC9
diff --git a/contrib/zkt/examples/views/intern/example.net./keyset-example.net. b/contrib/zkt/examples/views/intern/example.net./keyset-example.net.
new file mode 100644
index 0000000..0aa2c7d
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./keyset-example.net.
@@ -0,0 +1,10 @@
+$ORIGIN .
+example.net 7200 IN DNSKEY 257 3 5 (
+ BQEAAAABC+JLXRgWPqqGe0cta8CR95tz7Pkk
+ gRDlXyxESD+XkpVDkJ3Wey/1Lh7083Ve1WmI
+ uUAo3N4d7HjLgrFVZxiumGGRz/aV3s01OFFS
+ 5JqIwF9BTNrNPGLPzzbBaQMHErO88HIbbg4s
+ ot7e6bSrtpAEf23MhZ3qZJC9+nN+DknmsgTE
+ 6EpK6ZyUrZc64/0K68EWhtk1gf95NQEzTD4Q
+ grOD6IYqLw==
+ ) ; key id = 126
diff --git a/contrib/zkt/examples/views/intern/example.net./zone.db b/contrib/zkt/examples/views/intern/example.net./zone.db
new file mode 100644
index 0000000..d3e90f7
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./zone.db
@@ -0,0 +1,33 @@
+;-----------------------------------------------------------------
+;
+; @(#) intern/example.net/zone.db
+;
+;-----------------------------------------------------------------
+
+$TTL 7200
+
+@ IN SOA ns1.example.net. hostmaster.example.net. (
+ 0 ; Serial
+ 43200 ; Refresh
+ 1800 ; Retry
+ 2W ; Expire
+ 7200 ) ; Minimum
+
+ IN NS ns1.example.net.
+ IN NS ns2.example.net.
+
+ns1 IN A 192.168.1.53
+ IN AAAA fd12:063c:cdbb::53
+ns2 IN A 10.1.2.3
+
+localhost IN A 127.0.0.1
+
+; Delegation to secure zone; The DS resource record will
+; be added by dnssec-signzone automatically if the
+; keyset-sub.example.net file is present (run dnssec-signzone
+; with option -g or use the dnssec-signer tool) ;-)
+sub IN NS ns1.example.net.
+
+; this file will have all the zone keys
+$INCLUDE dnskey.db
+
diff --git a/contrib/zkt/examples/views/intern/example.net./zone.db.signed b/contrib/zkt/examples/views/intern/example.net./zone.db.signed
new file mode 100644
index 0000000..88a42c6
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/example.net./zone.db.signed
@@ -0,0 +1,109 @@
+; File written on Thu Jun 12 18:13:43 2008
+; dnssec_signzone version 9.5.0
+example.net. 7200 IN SOA ns1.example.net. hostmaster.example.net. (
+ 1213287223 ; serial
+ 43200 ; refresh (12 hours)
+ 1800 ; retry (30 minutes)
+ 1209600 ; expire (2 weeks)
+ 7200 ; minimum (2 hours)
+ )
+ 7200 RRSIG SOA 5 2 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ Pc3wGwZm0n5gMs9lSHUiRG4EIpalC+UUJPwy
+ 2LwHbyFkzCdGQz2RDJeL6mRKS4Z+gmt3oNUV
+ aV3H0KfNq6ITLg== )
+ 7200 NS ns1.example.net.
+ 7200 NS ns2.example.net.
+ 7200 RRSIG NS 5 2 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ dUy23xqHx9shvAc20zW9uBOt8TnrI5ot31vS
+ Gas9s5ksxGZuQIIdpdYvbFtufp9jLfAQG98L
+ a6rQDFcnJ8xzng== )
+ 7200 NSEC localhost.example.net. NS SOA RRSIG NSEC DNSKEY
+ 7200 RRSIG NSEC 5 2 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ gWt7VDw60E1q7qS4+pkor6RR2Dfc1sshGHia
+ UEJBt9F4PiHux3ICJbyWQ2USBLJMzO+uR8GH
+ kt2inbyQytbPDQ== )
+ 1800 DNSKEY 256 3 5 (
+ BQEAAAABsMIdQ+yt52Q/OR1s+QPj7SuBydYb
+ 11l0HC5kGIDp+JPQIQHxpyCWa/LaLgcvK3IA
+ 1HR8YaO3QXB2LAHEz5B/CQ==
+ ) ; key id = 5972
+ 1800 DNSKEY 256 3 5 (
+ BQEAAAABzbx90CiFrOSh0/BkiRQYRC4rHL0Q
+ Qv96Qwy5/zuOa/3Zy9LcTpbE13DtEAqOfVGS
+ Q79S4WgKalFJxq6lSk0xrw==
+ ) ; key id = 23375
+ 1800 DNSKEY 257 3 5 (
+ BQEAAAABC+JLXRgWPqqGe0cta8CR95tz7Pkk
+ gRDlXyxESD+XkpVDkJ3Wey/1Lh7083Ve1WmI
+ uUAo3N4d7HjLgrFVZxiumGGRz/aV3s01OFFS
+ 5JqIwF9BTNrNPGLPzzbBaQMHErO88HIbbg4s
+ ot7e6bSrtpAEf23MhZ3qZJC9+nN+DknmsgTE
+ 6EpK6ZyUrZc64/0K68EWhtk1gf95NQEzTD4Q
+ grOD6IYqLw==
+ ) ; key id = 126
+ 1800 RRSIG DNSKEY 5 2 1800 20080613151343 (
+ 20080612151343 126 example.net.
+ CPj9rEcjTazkLm5yNpC4PatufPvKQdCkaIj9
+ EKFgYUpPftfvhP1MzKcHnKraVq8jU995e1vU
+ WZ3ac9M4KRynUoYYj4/nMFwWQu/xC9yaUjj0
+ XodXMEMlSjjN5BE/2Og3xzKJ9grim7riKClH
+ fixhNn6WGUXWT7TV1GKNnB7Ix/ZVCpzU4QAz
+ qr28rqTYvbmoowGXPf6OgafFdRQ6rdTRTzvK
+ xA== )
+ 1800 RRSIG DNSKEY 5 2 1800 20080613151343 (
+ 20080612151343 5972 example.net.
+ dOdjm4GD0nzgoMgRYl8HiEqi4nxP/ocB7n/N
+ WRKdU4Tuk7OYacr2Bd+tVa2bKLJZ9JmMQR8v
+ VDkzRjT4eONxuA== )
+localhost.example.net. 7200 IN A 127.0.0.1
+ 7200 RRSIG A 5 3 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ KRpkDBsuqC+WHv++YBsxW1rhkALl/LWyI24E
+ qJJevkm0+5tCmHgHa9WovZwDDMEn/tzxOaqi
+ rk8Mnbf6cYxSlw== )
+ 7200 NSEC ns1.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ GdpOVVyqa1nTaGFuN4ohqxnYs5yG+vGK9gK0
+ Tt4aenChFAmcuIvhX7ZcdejXM8x+imttnKCp
+ Smho3kSGf9gQRQ== )
+ns1.example.net. 7200 IN A 192.168.1.53
+ 7200 RRSIG A 5 3 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ P4vZDd3DBZIEwk9mQWoR1qjqyFTNOvsp+yOt
+ z2OvdAjSnlVnYHC0lM0LY24RVTQlQPLRq75F
+ joAIP/0wvXihsA== )
+ 7200 AAAA fd12:63c:cdbb::53
+ 7200 RRSIG AAAA 5 3 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ V04kA3VrzhcNfwCEXBpgKyu+eRFYGCIrXuty
+ XiRCHV2DCOlr9EBKGdXzpR8kUnpRZI2BuP17
+ 2a3emgs9BHJJ6A== )
+ 7200 NSEC ns2.example.net. A AAAA RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ Y0DaMxmczQLNCtzKO/MA7Nvt4Rh3MdnEvcPJ
+ 48blsqd3UWGlRcHD/yx1NFV2JxBFSNTsAkBs
+ JFhw+nVeZJdHJA== )
+ns2.example.net. 7200 IN A 10.1.2.3
+ 7200 RRSIG A 5 3 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ GsvMGEozNeTjBPOuYM3thOZsQ+pPv7/8zQlj
+ FPnivBwkvkgrk+IyJxoh9xyTnVxd93mPY0Rv
+ Xsp5ITBTILSM6Q== )
+ 7200 NSEC sub.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ LYIa+Hhk4l6KnbT/QKS0Zqkfy8Ywpz8J9RLh
+ 9VqzxFcdXrJswV4o/5fbZCT33sBqzebggBVR
+ LYF/o0HVi5uzJA== )
+sub.example.net. 7200 IN NS ns1.example.net.
+ 7200 NSEC example.net. NS RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080613151343 (
+ 20080612151343 5972 example.net.
+ nkGsdegvupGxCOpr/8K6kY/0iZH1ZC8y5HwQ
+ 8Z3/aD0wJxaVK9iMjZ+jbIbQHg3Es5V0UYFR
+ RPdjTNk7YEC0Mg== )
diff --git a/contrib/zkt/examples/views/intern/zkt-int.log b/contrib/zkt/examples/views/intern/zkt-int.log
new file mode 100644
index 0000000..0729139
--- /dev/null
+++ b/contrib/zkt/examples/views/intern/zkt-int.log
@@ -0,0 +1,169 @@
+2008-06-12 18:02:13.593: notice: running as ../../dnssec-signer -V intern -v -v
+2008-06-12 18:02:13.594: debug: parsing zone "example.net." in dir "intern/example.net."
+2008-06-12 18:02:13.594: debug: Check RFC5011 status
+2008-06-12 18:02:13.595: debug: ->ksk5011status returns 0
+2008-06-12 18:02:13.595: debug: Check ksk status
+2008-06-12 18:02:13.595: debug: Lifetime(2592000 +/-150 sec) of active key 5972 exceeded (17727466 sec)
+2008-06-12 18:02:13.595: debug: ->waiting for pre-publish key
+2008-06-12 18:02:13.595: notice: "example.net.": lifetime of zone signing key 5972 exceeded since 25w4h17m46s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-12 18:02:13.595: debug: Re-signing necessary: Modified keys
+2008-06-12 18:02:13.595: notice: "example.net.": re-signing triggered: Modified keys
+2008-06-12 18:02:13.595: debug: Writing key file "intern/example.net./dnskey.db"
+2008-06-12 18:02:13.596: debug: Signing zone "example.net."
+2008-06-12 18:02:13.596: debug: Run cmd "cd intern/example.net.; /usr/local/sbin/dnssec-signzone -p -o example.net. -e +86400 -g -N unixtime zone.db K*.private"
+2008-06-12 18:02:13.705: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 18:02:13.705: debug: Signing completed after 0s.
+2008-06-12 18:02:13.705: debug:
+2008-06-12 18:02:13.705: notice: end of run: 0 errors occured
+2008-06-12 18:03:13.208: notice: running as ../../dnssec-signer -V intern -r -v -v
+2008-06-12 18:03:13.209: debug: parsing zone "example.net." in dir "intern/example.net."
+2008-06-12 18:03:13.209: debug: Check RFC5011 status
+2008-06-12 18:03:13.209: debug: ->ksk5011status returns 0
+2008-06-12 18:03:13.209: debug: Check ksk status
+2008-06-12 18:03:13.209: debug: Lifetime(2592000 +/-150 sec) of active key 5972 exceeded (17727526 sec)
+2008-06-12 18:03:13.209: debug: ->waiting for pre-publish key
+2008-06-12 18:03:13.209: notice: "example.net.": lifetime of zone signing key 5972 exceeded since 25w4h18m46s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-12 18:03:13.209: debug: Re-signing not necessary!
+2008-06-12 18:03:13.209: notice: end of run: 0 errors occured
+2008-06-12 18:03:19.287: notice: running as ../../dnssec-signer -V intern -r -v -v
+2008-06-12 18:03:19.288: debug: parsing zone "example.net." in dir "intern/example.net."
+2008-06-12 18:03:19.288: debug: Check RFC5011 status
+2008-06-12 18:03:19.289: debug: ->ksk5011status returns 0
+2008-06-12 18:03:19.289: debug: Check ksk status
+2008-06-12 18:03:19.289: debug: Lifetime(2592000 +/-150 sec) of active key 5972 exceeded (17727532 sec)
+2008-06-12 18:03:19.289: debug: ->waiting for pre-publish key
+2008-06-12 18:03:19.289: notice: "example.net.": lifetime of zone signing key 5972 exceeded since 25w4h18m52s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-12 18:03:19.289: debug: Re-signing not necessary!
+2008-06-12 18:03:19.289: notice: end of run: 0 errors occured
+2008-06-12 18:03:23.617: notice: running as ../../dnssec-signer -V intern -f -r -v -v
+2008-06-12 18:03:23.618: debug: parsing zone "example.net." in dir "intern/example.net."
+2008-06-12 18:03:23.618: debug: Check RFC5011 status
+2008-06-12 18:03:23.618: debug: ->ksk5011status returns 0
+2008-06-12 18:03:23.618: debug: Check ksk status
+2008-06-12 18:03:23.618: debug: Lifetime(2592000 +/-150 sec) of active key 5972 exceeded (17727536 sec)
+2008-06-12 18:03:23.618: debug: ->waiting for pre-publish key
+2008-06-12 18:03:23.618: notice: "example.net.": lifetime of zone signing key 5972 exceeded since 25w4h18m56s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-12 18:03:23.618: debug: Re-signing necessary: Option -f
+2008-06-12 18:03:23.618: notice: "example.net.": re-signing triggered: Option -f
+2008-06-12 18:03:23.618: debug: Writing key file "intern/example.net./dnskey.db"
+2008-06-12 18:03:23.619: debug: Signing zone "example.net."
+2008-06-12 18:03:23.619: debug: Run cmd "cd intern/example.net.; /usr/local/sbin/dnssec-signzone -p -o example.net. -e +86400 -g -N unixtime zone.db K*.private"
+2008-06-12 18:03:23.719: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 18:03:23.719: debug: Signing completed after 0s.
+2008-06-12 18:03:23.720: notice: ""example.net." in view "intern"": reload triggered
+2008-06-12 18:03:23.772: debug:
+2008-06-12 18:03:23.772: notice: end of run: 0 errors occured
+2008-06-12 18:05:39.532: notice: running as ../../dnssec-signer -V intern -f -r -v -v
+2008-06-12 18:05:39.533: debug: parsing zone "example.net." in dir "intern/example.net."
+2008-06-12 18:05:39.533: debug: Check RFC5011 status
+2008-06-12 18:05:39.533: debug: ->ksk5011status returns 0
+2008-06-12 18:05:39.533: debug: Check ksk status
+2008-06-12 18:05:39.533: debug: Lifetime(2592000 +/-150 sec) of active key 5972 exceeded (17727672 sec)
+2008-06-12 18:05:39.533: debug: ->waiting for pre-publish key
+2008-06-12 18:05:39.533: notice: "example.net.": lifetime of zone signing key 5972 exceeded since 25w4h21m12s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-12 18:05:39.533: debug: Re-signing necessary: Option -f
+2008-06-12 18:05:39.533: notice: "example.net.": re-signing triggered: Option -f
+2008-06-12 18:05:39.533: debug: Writing key file "intern/example.net./dnskey.db"
+2008-06-12 18:05:39.534: debug: Signing zone "example.net."
+2008-06-12 18:05:39.534: debug: Run cmd "cd intern/example.net.; /usr/local/sbin/dnssec-signzone -p -o example.net. -e +86400 -g -N unixtime zone.db K*.private"
+2008-06-12 18:05:39.629: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 18:05:39.630: debug: Signing completed after 0s.
+2008-06-12 18:05:39.630: notice: ""example.net."": reload triggered
+2008-06-12 18:05:39.640: debug:
+2008-06-12 18:05:39.640: notice: end of run: 0 errors occured
+2008-06-12 18:07:47.753: notice: running as ../../dnssec-signer -V intern -f -r -v -v
+2008-06-12 18:07:47.754: debug: parsing zone "example.net." in dir "intern/example.net."
+2008-06-12 18:07:47.754: debug: Check RFC5011 status
+2008-06-12 18:07:47.754: debug: ->ksk5011status returns 0
+2008-06-12 18:07:47.754: debug: Check ksk status
+2008-06-12 18:07:47.754: debug: Lifetime(2592000 +/-150 sec) of active key 5972 exceeded (17727800 sec)
+2008-06-12 18:07:47.754: debug: ->waiting for pre-publish key
+2008-06-12 18:07:47.754: notice: "example.net.": lifetime of zone signing key 5972 exceeded since 25w4h23m20s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-12 18:07:47.754: debug: Re-signing necessary: Option -f
+2008-06-12 18:07:47.754: notice: "example.net.": re-signing triggered: Option -f
+2008-06-12 18:07:47.754: debug: Writing key file "intern/example.net./dnskey.db"
+2008-06-12 18:07:47.754: debug: Signing zone "example.net."
+2008-06-12 18:07:47.754: debug: Run cmd "cd intern/example.net.; /usr/local/sbin/dnssec-signzone -p -o example.net. -e +86400 -g -N unixtime zone.db K*.private"
+2008-06-12 18:07:47.856: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 18:07:47.856: debug: Signing completed after 0s.
+2008-06-12 18:07:47.856: notice: ""example.net."": reload triggered
+2008-06-12 18:07:47.866: debug:
+2008-06-12 18:07:47.867: notice: end of run: 0 errors occured
+2008-06-12 18:10:57.978: notice: running as ../../dnssec-signer -V intern -f -r -v -v
+2008-06-12 18:10:57.978: debug: parsing zone "example.net." in dir "intern/example.net."
+2008-06-12 18:10:57.978: debug: Check RFC5011 status
+2008-06-12 18:10:57.978: debug: ->ksk5011status returns 0
+2008-06-12 18:10:57.978: debug: Check ksk status
+2008-06-12 18:10:57.978: debug: Lifetime(2592000 +/-150 sec) of active key 5972 exceeded (17727990 sec)
+2008-06-12 18:10:57.978: debug: ->waiting for pre-publish key
+2008-06-12 18:10:57.978: notice: "example.net.": lifetime of zone signing key 5972 exceeded since 25w4h26m30s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-12 18:10:57.978: debug: Re-signing necessary: Option -f
+2008-06-12 18:10:57.978: notice: "example.net.": re-signing triggered: Option -f
+2008-06-12 18:10:57.978: debug: Writing key file "intern/example.net./dnskey.db"
+2008-06-12 18:10:57.979: debug: Signing zone "example.net."
+2008-06-12 18:10:57.979: debug: Run cmd "cd intern/example.net.; /usr/local/sbin/dnssec-signzone -p -o example.net. -e +86400 -g -N unixtime zone.db K*.private"
+2008-06-12 18:10:58.081: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 18:10:58.081: debug: Signing completed after 1s.
+2008-06-12 18:10:58.081: notice: ""example.net." in view "intern"": reload triggered
+2008-06-12 18:10:58.093: debug:
+2008-06-12 18:10:58.093: notice: end of run: 0 errors occured
+2008-06-12 18:13:29.511: notice: running as ../../dnssec-signer -V intern -f -r -v -v
+2008-06-12 18:13:29.512: debug: parsing zone "example.net." in dir "intern/example.net."
+2008-06-12 18:13:29.512: debug: Check RFC5011 status
+2008-06-12 18:13:29.512: debug: ->ksk5011status returns 0
+2008-06-12 18:13:29.512: debug: Check ksk status
+2008-06-12 18:13:29.512: debug: Lifetime(2592000 +/-150 sec) of active key 5972 exceeded (17728142 sec)
+2008-06-12 18:13:29.512: debug: ->waiting for pre-publish key
+2008-06-12 18:13:29.512: notice: "example.net.": lifetime of zone signing key 5972 exceeded since 25w4h29m2s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-12 18:13:29.512: debug: Re-signing necessary: Option -f
+2008-06-12 18:13:29.512: notice: "example.net.": re-signing triggered: Option -f
+2008-06-12 18:13:29.512: debug: Writing key file "intern/example.net./dnskey.db"
+2008-06-12 18:13:29.513: debug: Signing zone "example.net."
+2008-06-12 18:13:29.513: debug: Run cmd "cd intern/example.net.; /usr/local/sbin/dnssec-signzone -p -o example.net. -e +86400 -g -N unixtime zone.db K*.private"
+2008-06-12 18:13:29.612: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 18:13:29.612: debug: Signing completed after 0s.
+2008-06-12 18:13:29.612: notice: ""example.net." in view "intern"": reload triggered
+2008-06-12 18:13:29.612: debug: Reload zone "example.net." in view "intern"
+2008-06-12 18:13:29.612: debug: Run cmd "/usr/local/sbin/rndc reload example.net. IN intern"
+2008-06-12 18:13:29.623: debug:
+2008-06-12 18:13:29.623: notice: end of run: 0 errors occured
+2008-06-12 18:13:38.707: notice: running as ../../dnssec-signer -V intern -f -r -v
+2008-06-12 18:13:38.708: debug: parsing zone "example.net." in dir "intern/example.net."
+2008-06-12 18:13:38.709: debug: Check RFC5011 status
+2008-06-12 18:13:38.709: debug: ->ksk5011status returns 0
+2008-06-12 18:13:38.709: debug: Check ksk status
+2008-06-12 18:13:38.709: debug: Lifetime(2592000 +/-150 sec) of active key 5972 exceeded (17728151 sec)
+2008-06-12 18:13:38.709: debug: ->waiting for pre-publish key
+2008-06-12 18:13:38.709: notice: "example.net.": lifetime of zone signing key 5972 exceeded since 25w4h29m11s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-12 18:13:38.709: debug: Re-signing necessary: Option -f
+2008-06-12 18:13:38.709: notice: "example.net.": re-signing triggered: Option -f
+2008-06-12 18:13:38.709: debug: Writing key file "intern/example.net./dnskey.db"
+2008-06-12 18:13:38.710: debug: Signing zone "example.net."
+2008-06-12 18:13:38.710: debug: Run cmd "cd intern/example.net.; /usr/local/sbin/dnssec-signzone -p -o example.net. -e +86400 -g -N unixtime zone.db K*.private"
+2008-06-12 18:13:39.163: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 18:13:39.163: debug: Signing completed after 1s.
+2008-06-12 18:13:39.163: notice: ""example.net." in view "intern"": reload triggered
+2008-06-12 18:13:39.163: debug: Reload zone "example.net." in view "intern"
+2008-06-12 18:13:39.163: debug: Run cmd "/usr/local/sbin/rndc reload example.net. IN intern"
+2008-06-12 18:13:39.174: debug:
+2008-06-12 18:13:39.174: notice: end of run: 0 errors occured
+2008-06-12 18:13:43.163: notice: running as ../../dnssec-signer -V intern -f -r -v -v
+2008-06-12 18:13:43.164: debug: parsing zone "example.net." in dir "intern/example.net."
+2008-06-12 18:13:43.164: debug: Check RFC5011 status
+2008-06-12 18:13:43.164: debug: ->ksk5011status returns 0
+2008-06-12 18:13:43.164: debug: Check ksk status
+2008-06-12 18:13:43.164: debug: Lifetime(2592000 +/-150 sec) of active key 5972 exceeded (17728156 sec)
+2008-06-12 18:13:43.164: debug: ->waiting for pre-publish key
+2008-06-12 18:13:43.164: notice: "example.net.": lifetime of zone signing key 5972 exceeded since 25w4h29m16s: ZSK rollover deferred: waiting for pre-publish key
+2008-06-12 18:13:43.164: debug: Re-signing necessary: Option -f
+2008-06-12 18:13:43.164: notice: "example.net.": re-signing triggered: Option -f
+2008-06-12 18:13:43.164: debug: Writing key file "intern/example.net./dnskey.db"
+2008-06-12 18:13:43.164: debug: Signing zone "example.net."
+2008-06-12 18:13:43.164: debug: Run cmd "cd intern/example.net.; /usr/local/sbin/dnssec-signzone -p -o example.net. -e +86400 -g -N unixtime zone.db K*.private"
+2008-06-12 18:13:43.262: debug: Cmd dnssec-signzone return: "zone.db.signed"
+2008-06-12 18:13:43.262: debug: Signing completed after 0s.
+2008-06-12 18:13:43.262: notice: ""example.net." in view "intern"": reload triggered
+2008-06-12 18:13:43.262: debug: Reload zone "example.net." in view "intern"
+2008-06-12 18:13:43.262: debug: Run cmd "/usr/local/sbin/rndc reload example.net. IN intern"
+2008-06-12 18:13:43.273: debug:
+2008-06-12 18:13:43.273: notice: end of run: 0 errors occured
diff --git a/contrib/zkt/examples/views/named.conf b/contrib/zkt/examples/views/named.conf
new file mode 100644
index 0000000..1ec3d13
--- /dev/null
+++ b/contrib/zkt/examples/views/named.conf
@@ -0,0 +1,97 @@
+/*****************************************************************
+**
+** #(@) named.conf (c) 6. May 2004 (hoz)
+*****************************************************************/
+
+/*****************************************************************
+** logging options
+*****************************************************************/
+logging {
+ channel "named-log" {
+ file "named.log";
+ print-time yes;
+ print-category yes;
+ print-severity yes;
+ severity info;
+ };
+ category "dnssec" { "named-log"; };
+ category "edns-disabled" { "named-log"; };
+ category "default" { "named-log"; };
+};
+
+/*****************************************************************
+** name server options
+*****************************************************************/
+options {
+ directory ".";
+
+ pid-file "named.pid";
+ listen-on-v6 port 1053 { any; };
+ listen-on port 1053 { any; };
+
+ empty-zones-enable no;
+
+ port 1053;
+ query-source address * port 1053;
+ query-source-v6 address * port 1053;
+ transfer-source * port 53;
+ transfer-source-v6 * port 53;
+ use-alt-transfer-source no;
+ notify-source * port 53;
+ notify-source-v6 * port 53;
+
+ recursion yes;
+ dnssec-enable yes;
+ dnssec-validation yes; /* required by BIND 9.4.0 */
+ dnssec-accept-expired false; /* added since BIND 9.5.0 */
+ edns-udp-size 1460; /* (M4) */
+ max-udp-size 1460; /* (M5) */
+
+ # allow-query { localhost; }; /* default in 9.4.0 */
+ # allow-query-cache { localhost; }; /* default in 9.4.0 */
+
+ dnssec-must-be-secure "." no;
+
+ querylog yes;
+
+ stats-server 127.0.0.1 port 8881; /* added since BIND 9.5.0 */
+};
+
+/*****************************************************************
+** view intern
+*****************************************************************/
+view "intern" {
+ match-clients { 127.0.0.1; ::1; };
+ recursion yes;
+ zone "." in {
+ type hint;
+ file "root.hint";
+ };
+
+ zone "0.0.127.in-addr.arpa" in {
+ type master;
+ file "127.0.0.zone";
+ };
+
+ zone "example.net" in {
+ type master;
+ file "intern/example.net./zone.db.signed";
+ };
+};
+
+/*****************************************************************
+** view extern
+*****************************************************************/
+view "extern" {
+ match-clients { any; };
+ recursion no;
+ zone "." in {
+ type hint;
+ file "root.hint";
+ };
+
+ zone "example.net" in {
+ type master;
+ file "extern/example.net./zone.db.signed";
+ };
+};
diff --git a/contrib/zkt/examples/views/named.log b/contrib/zkt/examples/views/named.log
new file mode 100644
index 0000000..15d5f7b
--- /dev/null
+++ b/contrib/zkt/examples/views/named.log
@@ -0,0 +1,17 @@
+20-Nov-2007 17:12:58.092 general: critical: couldn't open pid file '/var/run/named.pid': Permission denied
+20-Nov-2007 17:12:58.092 general: critical: exiting (due to early fatal error)
+20-Nov-2007 17:20:24.941 general: critical: couldn't open pid file '/var/run/named.pid': Permission denied
+20-Nov-2007 17:20:24.941 general: critical: exiting (due to early fatal error)
+20-Nov-2007 17:28:22.686 general: critical: couldn't open pid file '/var/run/named.pid': Permission denied
+20-Nov-2007 17:28:22.686 general: critical: exiting (due to early fatal error)
+20-Nov-2007 17:40:12.389 general: error: zone 0.0.127.in-addr.arpa/IN/intern: loading from master file 127.0.0.zone failed: file not found
+20-Nov-2007 17:40:12.391 general: info: zone example.net/IN/intern: loaded serial 1195574789 (signed)
+20-Nov-2007 17:40:12.393 general: info: zone example.net/IN/extern: loaded serial 1195561217 (signed)
+20-Nov-2007 17:40:12.393 general: notice: running
+20-Nov-2007 17:40:12.393 notify: info: zone example.net/IN/intern: sending notifies (serial 1195574789)
+20-Nov-2007 17:40:12.394 notify: info: zone example.net/IN/extern: sending notifies (serial 1195561217)
+20-Nov-2007 19:07:04.016 general: info: shutting down
+20-Nov-2007 19:07:04.017 network: info: no longer listening on ::#1053
+20-Nov-2007 19:07:04.017 network: info: no longer listening on 127.0.0.1#1053
+20-Nov-2007 19:07:04.017 network: info: no longer listening on 145.253.100.51#1053
+20-Nov-2007 19:07:04.020 general: notice: exiting
diff --git a/contrib/zkt/examples/views/root.hint b/contrib/zkt/examples/views/root.hint
new file mode 100644
index 0000000..2b5c167
--- /dev/null
+++ b/contrib/zkt/examples/views/root.hint
@@ -0,0 +1,45 @@
+; <<>> DiG 9.5.0a6 <<>> ns . @a.root-servers.net
+;; global options: printcmd
+;; Got answer:
+;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33355
+;; flags: qr aa rd; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 13
+;; WARNING: recursion requested but not available
+
+;; QUESTION SECTION:
+;. IN NS
+
+;; ANSWER SECTION:
+. 518400 IN NS H.ROOT-SERVERS.NET.
+. 518400 IN NS I.ROOT-SERVERS.NET.
+. 518400 IN NS J.ROOT-SERVERS.NET.
+. 518400 IN NS K.ROOT-SERVERS.NET.
+. 518400 IN NS L.ROOT-SERVERS.NET.
+. 518400 IN NS M.ROOT-SERVERS.NET.
+. 518400 IN NS A.ROOT-SERVERS.NET.
+. 518400 IN NS B.ROOT-SERVERS.NET.
+. 518400 IN NS C.ROOT-SERVERS.NET.
+. 518400 IN NS D.ROOT-SERVERS.NET.
+. 518400 IN NS E.ROOT-SERVERS.NET.
+. 518400 IN NS F.ROOT-SERVERS.NET.
+. 518400 IN NS G.ROOT-SERVERS.NET.
+
+;; ADDITIONAL SECTION:
+A.ROOT-SERVERS.NET. 3600000 IN A 198.41.0.4
+B.ROOT-SERVERS.NET. 3600000 IN A 192.228.79.201
+C.ROOT-SERVERS.NET. 3600000 IN A 192.33.4.12
+D.ROOT-SERVERS.NET. 3600000 IN A 128.8.10.90
+E.ROOT-SERVERS.NET. 3600000 IN A 192.203.230.10
+F.ROOT-SERVERS.NET. 3600000 IN A 192.5.5.241
+G.ROOT-SERVERS.NET. 3600000 IN A 192.112.36.4
+H.ROOT-SERVERS.NET. 3600000 IN A 128.63.2.53
+I.ROOT-SERVERS.NET. 3600000 IN A 192.36.148.17
+J.ROOT-SERVERS.NET. 3600000 IN A 192.58.128.30
+K.ROOT-SERVERS.NET. 3600000 IN A 193.0.14.129
+L.ROOT-SERVERS.NET. 3600000 IN A 199.7.83.42
+M.ROOT-SERVERS.NET. 3600000 IN A 202.12.27.33
+
+;; Query time: 114 msec
+;; SERVER: 198.41.0.4#53(198.41.0.4)
+;; WHEN: Mon Nov 5 07:28:00 2007
+;; MSG SIZE rcvd: 436
+
diff --git a/contrib/zkt/examples/views/viewtest.sh b/contrib/zkt/examples/views/viewtest.sh
new file mode 100755
index 0000000..f0a1754
--- /dev/null
+++ b/contrib/zkt/examples/views/viewtest.sh
@@ -0,0 +1,20 @@
+
+
+ZKT_CONFFILE=dnssec.conf
+export ZKT_CONFFILE
+
+if true
+then
+ echo "All internal keys:"
+ ./dnssec-zkt-intern
+ echo
+
+ echo "All external keys:"
+ ./dnssec-zkt-extern
+ echo
+fi
+
+echo "Sign both views"
+./dnssec-signer-intern -v -v -f -r
+echo
+./dnssec-signer-extern -v -v
diff --git a/contrib/zkt/examples/zone.db b/contrib/zkt/examples/zone.db
new file mode 100644
index 0000000..9864cb1
--- /dev/null
+++ b/contrib/zkt/examples/zone.db
@@ -0,0 +1,45 @@
+;-----------------------------------------------------------------
+;
+; @(#) example.net/zone.db
+;
+;-----------------------------------------------------------------
+
+$TTL 7200
+
+; Be sure that the serial number below is left
+; justified in a field of at least 10 chars!!
+; 0123456789;
+; It's also possible to use the date form e.g. 2005040101
+@ IN SOA ns1.example.net. hostmaster.example.net. (
+ 263 ; Serial
+ 43200 ; Refresh
+ 1800 ; Retry
+ 2W ; Expire
+ 7200 ) ; Minimum
+
+ IN NS ns1.example.net.
+ IN NS ns2.example.net.
+
+ns1 IN A 1.0.0.5
+ IN AAAA 2001:db8::53
+ns2 IN A 1.2.0.6
+
+localhost IN A 127.0.0.1
+
+a IN A 1.2.3.1
+b IN MX 10 a
+;c IN A 1.2.3.2
+d IN A 1.2.3.3
+ IN AAAA 2001:0db8::3
+
+; Delegation to secure zone; The DS resource record will
+; be added by dnssec-signzone automatically if the
+; keyset-sub.example.net file is present (run dnssec-signzone
+; with option -g or use the dnssec-signer tool) ;-)
+sub IN NS ns1.example.net.
+sub IN DS 54876 5 1 CAB6127E303A8A8D7D5A29AE05DB60F4C5060B10
+sub IN DS 54876 5 2 7C8CAF1844479F3600213173BB5D1E2A44143D63B6E0B3E10D8C5310 ADF84D30
+
+; this file will have all the zone keys
+$INCLUDE dnskey.db
+
diff --git a/contrib/zkt/examples/zone.db.signed b/contrib/zkt/examples/zone.db.signed
new file mode 100644
index 0000000..1e389ea
--- /dev/null
+++ b/contrib/zkt/examples/zone.db.signed
@@ -0,0 +1,146 @@
+; File written on Tue Jun 24 10:00:31 2008
+; dnssec_signzone version 9.5.0
+example.net. 7200 IN SOA ns1.example.net. hostmaster.example.net. (
+ 263 ; serial
+ 43200 ; refresh (12 hours)
+ 1800 ; retry (30 minutes)
+ 1209600 ; expire (2 weeks)
+ 7200 ; minimum (2 hours)
+ )
+ 7200 RRSIG SOA 5 2 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ FFUGR4+nzjZbpDT/RAncV7dNvBy1xil4MO17
+ DU+gotHHV1Yq+4RRqEnRhOSWydDC9ENAjH7W
+ lmzr+igFHp8qiw== )
+ 7200 NS ns1.example.net.
+ 7200 NS ns2.example.net.
+ 7200 RRSIG NS 5 2 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ mpT5zY57UtLMdl6iKVtvr78vINyaA3NkZ0af
+ E/TtUUBJeIEjLauzxA5jJBGqLWAiLj8HKWhS
+ dq1VfORhRh/Xng== )
+ 7200 NSEC a.example.net. NS SOA RRSIG NSEC DNSKEY
+ 7200 RRSIG NSEC 5 2 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ Q5yxSoL+Df3UbGe1RSFFj01SoBGLgjXvgLd5
+ wKota7wnjO8CxidmrN+qcKQHjF+R+mH8GeQ7
+ xL1qZxKLQqxmwA== )
+ 14400 DNSKEY 256 3 5 (
+ BQEAAAABzN8pvZb5GSy8AozXt4L8HK/x59TQ
+ jh9IaZS+mIyyuHDX2iaFUigOqHixIJtDLD1r
+ /MfelgJ/Mh6+vCu+XmMQuw==
+ ) ; key id = 33755
+ 14400 DNSKEY 257 3 5 (
+ BQEAAAABC23icFZAD3DFBLoEw7DWKl8Hig7a
+ zmEbpXHYyAV98l+QQaTAb98Ob3YbrVJ9IU8E
+ 0KBFb5iYpHobxowPsI8FjUH2oL/7PfhtN1E3
+ NlL6Uhbo8Umf6H0UULEsUTlTT8dnX+ikjAr8
+ bN71YJP7BXlszezsFHuMEspNdOPyMr93230+
+ R2KTEzC2H4CQzSRIr5xXSIq8kkrJ3miGjTyj
+ 5awvXfJ+eQ==
+ ) ; key id = 31674
+ 14400 RRSIG DNSKEY 5 2 14400 20080724070030 (
+ 20080624070030 31674 example.net.
+ BGed6Vivkmx/SM7HuXMy9ex+p0fDWcXW6uTH
+ SZLs9oAZMSkm8Xh2RNNI1sgZefGpsOc7AZJE
+ JuIWttqKm5VL57qpEKeTxZ9oE6Vpk4ko5lMo
+ yTJUoih7lTXo7a1OsNHMFZadE7Fu4Q8pjGUZ
+ ZJI4zBrT7JmgyPNCkgn1JdC2qJlc6ClHEb4E
+ 6pQyH3BnSOFudZDz8MdVQnqdxpShGwucnf2i
+ oA== )
+ 14400 RRSIG DNSKEY 5 2 14400 20080724070030 (
+ 20080624070030 33755 example.net.
+ f03G7Cq3CwWz7Lbe7cl61ciSsdEYv4heYnR3
+ binJ3xWO7jSiRAvUAfkIYDspdlF/PCOnv8sr
+ id8TL8q/qQ0MCg== )
+a.example.net. 7200 IN A 1.2.3.1
+ 7200 RRSIG A 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ VuIrcft9jvWKORJy2SQ4UgWwRnUL4gIiaVpy
+ 3i5hfjM6X38FHsy0SvGrjxQqiurwZZS4NxXG
+ ljUerawxMdHWWw== )
+ 7200 NSEC b.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ yc/tsRYQRaYsPp+5jPUj2NR0R3zHKvXBQ/RO
+ 14b/eKL9i4NnuzS50qFZwzpcOBOJd6XITO4p
+ yJNZQKtryRJuSg== )
+b.example.net. 7200 IN MX 10 a.example.net.
+ 7200 RRSIG MX 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ xVjOhCO2zJVp1SsoMdM6ePCZUkittsqEP7rI
+ 7j8r2S1j4oiIdXaxCBBVwddhS/x1eziI/a2S
+ /HwVRJThIYIKnQ== )
+ 7200 NSEC d.example.net. MX RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ jC171VBU0dqcI1NnMUUqrUIjq09sVHnFo9CH
+ 0jKNwxkj+K1Zkr7CBm6htH+EkKKhqKFW8kz7
+ b2r05FL1xakcnQ== )
+d.example.net. 7200 IN A 1.2.3.3
+ 7200 RRSIG A 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ Q4C7HCpDR6fxIczzqGDnkpXUL5oxdPDYWF2H
+ vmAalL++9A5hVGz8S5IfX87dZAg71c1j8ZAe
+ 5oS0pvLQnweoIw== )
+ 7200 AAAA 2001:db8::3
+ 7200 RRSIG AAAA 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ ECjxqQpJCbL6A9iBk/bImgzDNevUXFjq8n2L
+ 14ewG5zQSz/0l0NqcHKtCiruBjHd+DEXjTEI
+ Qo8RvMm7Rn8OsA== )
+ 7200 NSEC localhost.example.net. A AAAA RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ k+AhslVfBZgXkTaWjDVB+3nLm2ye8UOGMNhY
+ QcKxJZaVYKnUZfyX1sJONN4UdFjmnkdNcRVC
+ 6ouWrLbIwslqIQ== )
+localhost.example.net. 7200 IN A 127.0.0.1
+ 7200 RRSIG A 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ wZjK9o3CElHLPSzynvzft/nQAEeBpNOj22vq
+ 3TWa9HWQ0RqL55NRmzxuDtyMtPOFQpniVxgV
+ jizb8X3SPJ5V1g== )
+ 7200 NSEC ns1.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ e4nOW7PuqCQBYgSCBQH06V2XB7SF85jmfFIc
+ dSMbsLRK+1tN/Y2+85WKVSQrXZzWRHgjQ+Hw
+ iL/FWK5Zfq7ixg== )
+ns1.example.net. 7200 IN A 1.0.0.5
+ 7200 RRSIG A 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ tTfMDk2ww2uWutlhjRMDPGo9ZPugjJqSbdyP
+ 6cJcCDJUBce0UZFxjvDBZhfG7O2XUscooUjp
+ JpXsJ54ksPugXA== )
+ 7200 AAAA 2001:db8::53
+ 7200 RRSIG AAAA 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ x8iMgcICSOxgx4biLForfZxgMbMVpzwMQR6n
+ naFVK79GOwFFT8krAfo6K6Rg7Fyu0jSE/59H
+ 3Y15F0ju6YvbAg== )
+ 7200 NSEC ns2.example.net. A AAAA RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ EYof9XuXHXuWgRF0MzgO/Z8FGYJEfLlJKWCV
+ IWh+b8XJejLO1Tt0vlJZl0orrs6yam/B8CWb
+ dgq8ktbqpNHmvg== )
+ns2.example.net. 7200 IN A 1.2.0.6
+ 7200 RRSIG A 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ Uh93B1J7mOqBcW8sXWHA6vmeGszGJGE/BtFV
+ cdO4tBNoIDbIdkzBUJZphc6HfK7/gu7WFhAo
+ 5v6cZr4bRDOf6A== )
+ 7200 NSEC sub.example.net. A RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ xOkV3aTsgrP7ZyaHfKhLmjJfhboQJpDYFdqV
+ y0zzZuGQr7Yr4PxWED5WJhm4fFf48agNWBmm
+ rk1OaFadv6m2uw== )
+sub.example.net. 7200 IN NS ns1.example.net.
+ 7200 NSEC example.net. NS RRSIG NSEC
+ 7200 RRSIG NSEC 5 3 7200 20080724070030 (
+ 20080624070030 33755 example.net.
+ Pr8KFvU/Fr2lp9W6Wqqq47VKrnh3tL90S8Eu
+ KIPsfmBE00g7eGPVswJUWShXMBZFLtfqI8z/
+ UBM6VzROSTtryA== )
diff --git a/contrib/zkt/log.c b/contrib/zkt/log.c
new file mode 100644
index 0000000..021be98
--- /dev/null
+++ b/contrib/zkt/log.c
@@ -0,0 +1,443 @@
+/*****************************************************************
+**
+** @(#) log.c -- The ZKT error logging module
+**
+** Copyright (c) June 2008, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+**
+*****************************************************************/
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+# include <ctype.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/time.h>
+# include <time.h>
+# include <assert.h>
+# include <errno.h>
+# include <syslog.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+# include "misc.h"
+# include "debug.h"
+#define extern
+# include "log.h"
+#undef extern
+
+/*****************************************************************
+** module internal vars & declarations
+*****************************************************************/
+static FILE *lg_fp;
+static int lg_minfilelevel;
+static int lg_syslogging;
+static int lg_minsyslevel;
+static long lg_errcnt;
+static const char *lg_progname;
+
+typedef struct {
+ lg_lvl_t level;
+ const char *str;
+ int syslog_level;
+} lg_symtbl_t;
+
+static lg_symtbl_t symtbl[] = {
+ { LG_NONE, "none", -1 },
+ { LG_DEBUG, "debug", LOG_DEBUG },
+ { LG_INFO, "info", LOG_INFO },
+ { LG_NOTICE, "notice", LOG_NOTICE },
+ { LG_WARNING, "warning", LOG_WARNING },
+ { LG_ERROR, "error", LOG_ERR },
+ { LG_FATAL, "fatal", LOG_CRIT },
+
+ { LG_NONE, "user", LOG_USER },
+ { LG_NONE, "daemon", LOG_DAEMON },
+ { LG_NONE, "local0", LOG_LOCAL0 },
+ { LG_NONE, "local1", LOG_LOCAL1 },
+ { LG_NONE, "local2", LOG_LOCAL2 },
+ { LG_NONE, "local3", LOG_LOCAL3 },
+ { LG_NONE, "local4", LOG_LOCAL4 },
+ { LG_NONE, "local5", LOG_LOCAL5 },
+ { LG_NONE, "local6", LOG_LOCAL6 },
+ { LG_NONE, "local7", LOG_LOCAL7 },
+ { LG_NONE, NULL, -1 }
+};
+
+# define MAXFNAME (1023)
+/*****************************************************************
+** function definitions (for function declarations see log.h)
+*****************************************************************/
+
+/*****************************************************************
+** lg_fileopen (path, name) -- open the log file
+** Name is a (absolute or relative) file or directory name.
+** If path is given and name is a relative path name then path
+** is prepended to name.
+** returns the open file pointer or NULL on error
+*****************************************************************/
+static FILE *lg_fileopen (const char *path, const char *name)
+{
+ int len;
+ FILE *fp;
+ struct tm *t;
+ time_t sec;
+ char fname[MAXFNAME+1];
+
+ if ( name == NULL || *name == '\0' )
+ return NULL;
+ else if ( *name == '/' || path == NULL )
+ snprintf (fname, MAXFNAME, "%s", name);
+ else
+ snprintf (fname, MAXFNAME, "%s/%s", path, name);
+
+# ifdef LOG_TEST
+ fprintf (stderr, "\t ==> \"%s\"", fname);
+# endif
+ if ( is_directory (fname) )
+ {
+ len = strlen (fname);
+
+ time (&sec);
+ t = gmtime (&sec);
+ snprintf (fname+len, MAXFNAME-len, LOG_FNAMETMPL,
+ t->tm_year + 1900, t->tm_mon+1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+# ifdef LOG_TEST
+ fprintf (stderr, " isdir \"%s\"", fname);
+# endif
+ }
+
+# ifdef LOG_TEST
+ fprintf (stderr, "\n");
+# endif
+
+ if ( (fp = fopen (fname, "a")) == NULL )
+ return NULL;
+
+ return fp;
+}
+
+/*****************************************************************
+** lg_str2lvl (level_name)
+*****************************************************************/
+lg_lvl_t lg_str2lvl (const char *name)
+{
+ lg_symtbl_t *p;
+
+ if ( !name )
+ return LG_NONE;
+
+ for ( p = symtbl; p->str; p++ )
+ if ( strcasecmp (name, p->str) == 0 )
+ return p->level;
+
+ return LG_NONE;
+}
+
+/*****************************************************************
+** lg_lvl2syslog (level)
+*****************************************************************/
+lg_lvl_t lg_lvl2syslog (lg_lvl_t level)
+{
+ lg_symtbl_t *p;
+
+ for ( p = symtbl; p->str; p++ )
+ if ( level == p->level )
+ return p->syslog_level;
+
+ assert ( p->str != NULL ); /* we assume not to reach this! */
+
+ return LOG_DEBUG; /* if not found, return DEBUG as default */
+}
+
+/*****************************************************************
+** lg_str2syslog (facility_name)
+*****************************************************************/
+int lg_str2syslog (const char *facility)
+{
+ lg_symtbl_t *p;
+
+ dbg_val1 ("lg_str2syslog (%s)\n", facility);
+ if ( !facility )
+ return LG_NONE;
+
+ for ( p = symtbl; p->str; p++ )
+ if ( strcasecmp (facility, p->str) == 0 )
+ return p->syslog_level;
+
+ return LG_NONE;
+}
+
+/*****************************************************************
+** lg_lvl2str (level)
+*****************************************************************/
+const char *lg_lvl2str (lg_lvl_t level)
+{
+ lg_symtbl_t *p;
+
+ if ( level < LG_DEBUG )
+ return "none";
+
+ for ( p = symtbl; p->str; p++ )
+ if ( level == p->level )
+ return p->str;
+ return "fatal";
+}
+
+/*****************************************************************
+** lg_geterrcnt () -- returns the current value of the internal
+** error counter
+*****************************************************************/
+long lg_geterrcnt ()
+{
+ return lg_errcnt;
+}
+
+/*****************************************************************
+** lg_seterrcnt () -- sets the internal error counter
+** returns the current value
+*****************************************************************/
+long lg_seterrcnt (long value)
+{
+ return lg_errcnt = value;
+}
+
+/*****************************************************************
+** lg_reseterrcnt () -- resets the internal error counter to 0
+** returns the current value
+*****************************************************************/
+long lg_reseterrcnt ()
+{
+ return lg_seterrcnt (0L);
+}
+
+
+/*****************************************************************
+** lg_open (prog, facility, syslevel, path, file, filelevel)
+** -- open the log channel
+** return values:
+** 0 on success
+** -1 on file open error
+*****************************************************************/
+int lg_open (const char *progname, const char *facility, const char *syslevel, const char *path, const char *file, const char *filelevel)
+{
+ int sysfacility;
+
+ dbg_val6 ("lg_open (%s, %s, %s, %s, %s, %s)\n", progname, facility, syslevel, path, file, filelevel);
+
+ lg_minsyslevel = lg_str2lvl (syslevel);
+ lg_minfilelevel = lg_str2lvl (filelevel);
+
+ sysfacility = lg_str2syslog (facility);
+ if ( sysfacility >= 0 )
+ {
+ lg_syslogging = 1;
+ dbg_val2 ("lg_open: openlog (%s, LOG_NDELAY, %d)\n", progname, lg_str2syslog (facility));
+ openlog (progname, LOG_NDELAY, lg_str2syslog (facility));
+ }
+ if ( file && * file )
+ {
+ if ( (lg_fp = lg_fileopen (path, file)) == NULL )
+ return -1;
+ lg_progname = progname;
+ }
+
+ return 0;
+}
+
+/*****************************************************************
+** lg_close () -- close the open filepointer for error logging
+** return 0 if no error log file is currently open,
+** otherwise the return code of fclose is returned.
+*****************************************************************/
+int lg_close ()
+{
+ int ret = 0;
+
+ if ( lg_syslogging )
+ {
+ closelog ();
+ lg_syslogging = 0;
+ }
+ if ( lg_fp )
+ {
+ ret = fclose (lg_fp);
+ lg_fp = NULL;
+ }
+
+ return ret;
+}
+
+/*****************************************************************
+**
+** lg_args (level, argc, argv[])
+** log all command line arguments (up to a length of 511 chars)
+** with priority level
+**
+*****************************************************************/
+void lg_args (lg_lvl_t level, int argc, char * const argv[])
+{
+ char cmdline[511+1];
+ int len;
+ int i;
+
+ len = 0;
+ for ( i = 0; i < argc && len < sizeof (cmdline); i++ )
+ len += snprintf (cmdline+len, sizeof (cmdline) - len, " %s", argv[i]);
+
+#if 1
+ lg_mesg (level, "------------------------------------------------------------");
+#else
+ lg_mesg (level, "");
+#endif
+ lg_mesg (level, "running%s ", cmdline);
+}
+
+/*****************************************************************
+**
+** lg_mesg (level, fmt, ...)
+**
+** Write a given message to the error log file and counts
+** all messages written with an level greater than LOG_ERR.
+**
+** All messages will be on one line in the logfile, so it's
+** not necessary to add an '\n' to the message.
+**
+** To call this function before an elog_open() is called is
+** useless!
+**
+*****************************************************************/
+void lg_mesg (int priority, char *fmt, ...)
+{
+ va_list ap;
+ struct timeval tv;
+ struct tm *t;
+ char format[256];
+
+ assert (fmt != NULL);
+ assert (priority >= LG_DEBUG && priority <= LG_FATAL);
+
+ format[0] ='\0';
+
+ dbg_val3 ("syslog = %d prio = %d >= sysmin = %d\n", lg_syslogging, priority, lg_minsyslevel);
+ if ( lg_syslogging && priority >= lg_minsyslevel )
+ {
+#if defined (LOG_WITH_LEVEL) && LOG_WITH_LEVEL
+ snprintf (format, sizeof (format), "%s: %s", lg_lvl2str(priority), fmt);
+ fmt = format;
+#endif
+ va_start(ap, fmt);
+ vsyslog (lg_lvl2syslog (priority), fmt, ap);
+ va_end(ap);
+ }
+
+ dbg_val3 ("filelg = %d prio = %d >= filmin = %d\n", lg_fp!=NULL, priority, lg_minfilelevel);
+ if ( lg_fp && priority >= lg_minfilelevel )
+ {
+#if defined (LOG_WITH_TIMESTAMP) && LOG_WITH_TIMESTAMP
+ gettimeofday (&tv, NULL);
+ t = localtime ((time_t *) &tv.tv_sec);
+ fprintf (lg_fp, "%04d-%02d-%02d ",
+ t->tm_year+1900, t->tm_mon+1, t->tm_mday);
+ fprintf (lg_fp, "%02d:%02d:%02d.%03ld: ",
+ t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
+#endif
+#if defined (LOG_WITH_PROGNAME) && LOG_WITH_PROGNAME
+ if ( lg_progname )
+ fprintf (lg_fp, "%s: ", lg_progname);
+#endif
+#if defined (LOG_WITH_LEVEL) && LOG_WITH_LEVEL
+ if ( fmt != format ) /* level is not in fmt string */
+ fprintf (lg_fp, "%s: ", lg_lvl2str(priority));
+#endif
+ va_start(ap, fmt);
+ vfprintf (lg_fp, fmt, ap);
+ va_end(ap);
+ fprintf (lg_fp, "\n");
+ }
+
+ if ( priority >= LG_ERROR )
+ lg_errcnt++;
+}
+
+
+#ifdef LOG_TEST
+const char *progname;
+int main (int argc, char *argv[])
+{
+ const char *levelstr;
+ const char *newlevelstr;
+ int level;
+ int err;
+
+ progname = *argv;
+
+ if ( --argc )
+ levelstr = *++argv;
+ else
+ levelstr = "fatal";
+
+ level = lg_str2lvl (levelstr);
+ newlevelstr = lg_lvl2str (level+1);
+ dbg_val4 ("base level = %s(%d) newlevel = %s(%d)\n", levelstr, level, newlevelstr, level+1);
+ if ( (err = lg_open (progname,
+#if 1
+ "user",
+#else
+ "none",
+#endif
+ levelstr, ".",
+#if 1
+ "test.log",
+#else
+ NULL,
+#endif
+ newlevelstr)) )
+ fprintf (stderr, "\topen error %d\n", err);
+ else
+ {
+ lg_mesg (LG_DEBUG, "debug message");
+ lg_mesg (LG_INFO, "INFO message");
+ lg_mesg (LG_NOTICE, "Notice message");
+ lg_mesg (LG_WARNING, "Warning message");
+ lg_mesg (LG_ERROR, "Error message");
+ lg_mesg (LG_FATAL, "Fatal message ");
+ }
+
+ if ( (err = lg_close ()) < 0 )
+ fprintf (stderr, "\tclose error %d\n", err);
+
+ return 0;
+}
+#endif
diff --git a/contrib/zkt/log.h b/contrib/zkt/log.h
new file mode 100644
index 0000000..9a5d3ab
--- /dev/null
+++ b/contrib/zkt/log.h
@@ -0,0 +1,66 @@
+/*****************************************************************
+**
+** @(#) log.h (c) June 2008 Holger Zuleger hznet.de
+**
+** Copyright (c) June 2008, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+#ifndef LOG_H
+# define LOG_H
+# include <sys/types.h>
+# include <stdarg.h>
+# include <stdio.h>
+# include <time.h>
+# include <syslog.h>
+
+typedef enum {
+ LG_NONE = 0,
+ LG_DEBUG,
+ LG_INFO,
+ LG_NOTICE,
+ LG_WARNING,
+ LG_ERROR,
+ LG_FATAL
+} lg_lvl_t;
+
+extern lg_lvl_t lg_str2lvl (const char *name);
+extern int lg_str2syslog (const char *facility);
+extern const char *lg_lvl2str (lg_lvl_t level);
+extern lg_lvl_t lg_lvl2syslog (lg_lvl_t level);
+extern long lg_geterrcnt (void);
+extern long lg_seterrcnt (long value);
+extern long lg_reseterrcnt (void);
+extern int lg_open (const char *progname, const char *facility, const char *syslevel, const char *path, const char *file, const char *filelevel);
+extern int lg_close (void);
+extern void lg_args (lg_lvl_t level, int argc, char * const argv[]);
+extern void lg_mesg (int level, char *fmt, ...);
+#endif
diff --git a/contrib/zkt/misc.c b/contrib/zkt/misc.c
new file mode 100644
index 0000000..d2465c3
--- /dev/null
+++ b/contrib/zkt/misc.c
@@ -0,0 +1,1157 @@
+/*****************************************************************
+**
+** @(#) misc.c -- helper functions for the dnssec zone key tools
+**
+** Copyright (c) Jan 2005, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+# include <unistd.h> /* for link(), unlink() */
+# include <ctype.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <time.h>
+# include <utime.h>
+# include <assert.h>
+# include <errno.h>
+# include <fcntl.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+# include "zconf.h"
+# include "log.h"
+# include "debug.h"
+#define extern
+# include "misc.h"
+#undef extern
+
+# define TAINTEDCHARS "`$@;&<>|"
+
+extern const char *progname;
+
+static int inc_soa_serial (FILE *fp, int use_unixtime);
+
+/*****************************************************************
+** getnameappendix (progname, basename)
+** return a pointer to the substring in progname subsequent
+** following basename "-".
+*****************************************************************/
+const char *getnameappendix (const char *progname, const char *basename)
+{
+ const char *p;
+ int baselen;
+
+ assert (progname != NULL);
+ assert (basename != NULL);
+
+ if ( (p = strrchr (progname, '/')) != NULL )
+ p++;
+ else
+ p = progname;
+
+ baselen = strlen (basename);
+ if ( strncmp (p, basename, baselen-1) == 0 && *(p+baselen) == '-' )
+ {
+ p += baselen + 1;
+ if ( *p )
+ return p;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************
+** getdefconfname (view)
+** returns the default configuration file name
+*****************************************************************/
+const char *getdefconfname (const char *view)
+{
+ char *p;
+ char *file;
+ char *buf;
+ int size;
+
+ if ( (file = getenv ("ZKT_CONFFILE")) == NULL )
+ file = CONFIG_FILE;
+
+ if ( view == NULL || *view == '\0' || (p = strrchr (file, '.')) == NULL )
+ return strdup (file);
+
+ size = strlen (file) + strlen (view) + 1 + 1;
+ if ( (buf = malloc (size)) == NULL )
+ return file;
+
+ dbg_val1 ("0123456789o123456789o123456789\tsize=%d\n", size);
+ dbg_val4 ("%.*s-%s%s\n", p - file, file, view, p);
+
+ snprintf (buf, size, "%.*s-%s%s", p - file, file, view, p);
+ return buf;
+}
+
+/*****************************************************************
+** str_tolowerdup (s)
+*****************************************************************/
+char *str_tolowerdup (const char *s)
+{
+ char *new;
+ char *p;
+
+ if ( s == NULL || (new = p = malloc (strlen (s) + 1)) == NULL )
+ return NULL;
+
+ while ( *s )
+ *p++ = tolower (*s++);
+ *p = '\0';
+
+ return new;
+}
+
+/*****************************************************************
+** str_delspace (s)
+** Remove in string 's' all white space char
+*****************************************************************/
+char *str_delspace (char *s)
+{
+ char *start;
+ char *p;
+
+ if ( !s ) /* is there a string ? */
+ return s;
+
+ start = s;
+ for ( p = s; *p; p++ )
+ if ( !isspace (*p) )
+ *s++ = *p; /* copy each nonspace */
+
+ *s = '\0'; /* terminate string */
+
+ return start;
+}
+
+/*****************************************************************
+** in_strarr (str, arr, cnt)
+** check if string array 'arr' contains the string 'str'
+** return 1 if true or 'arr' or 'str' is empty, otherwise 0
+*****************************************************************/
+int in_strarr (const char *str, char *const arr[], int cnt)
+{
+ if ( arr == NULL || cnt <= 0 )
+ return 1;
+
+ if ( str == NULL || *str == '\0' )
+ return 0;
+
+ while ( --cnt >= 0 )
+ if ( strcmp (str, arr[cnt]) == 0 )
+ return 1;
+
+ return 0;
+}
+
+/*****************************************************************
+** str_untaint (s)
+** Remove in string 's' all TAINTED chars
+*****************************************************************/
+char *str_untaint (char *str)
+{
+ char *p;
+
+ assert (str != NULL);
+
+ for ( p = str; *p; p++ )
+ if ( strchr (TAINTEDCHARS, *p) )
+ *p = ' ';
+ return str;
+}
+
+/*****************************************************************
+** str_chop (str, c)
+** delete all occurrences of char 'c' at the end of string 's'
+*****************************************************************/
+char *str_chop (char *str, char c)
+{
+ int len;
+
+ assert (str != NULL);
+
+ len = strlen (str) - 1;
+ while ( len >= 0 && str[len] == c )
+ str[len--] = '\0';
+
+ return str;
+}
+
+/*****************************************************************
+** parseurl (url, &proto, &host, &port, &para )
+** parses the given url (e.g. "proto://host.with.domain:port/para")
+** and set the pointer variables to the corresponding part of the string.
+*****************************************************************/
+void parseurl (char *url, char **proto, char **host, char **port, char **para)
+{
+ char *start;
+ char *p;
+
+ assert ( url != NULL );
+
+ /* parse protocol */
+ if ( (p = strchr (url, ':')) == NULL ) /* no protocol string given ? */
+ p = url;
+ else /* looks like a protocol string */
+ if ( p[1] == '/' && p[2] == '/' ) /* protocol string ? */
+ {
+ *p = '\0';
+ p += 3;
+ if ( proto )
+ *proto = url;
+ }
+ else /* no protocol string found ! */
+ p = url;
+
+ /* parse host */
+ if ( *p == '[' ) /* ipv6 address as hostname ? */
+ {
+ for ( start = ++p; *p && *p != ']'; p++ )
+ ;
+ if ( *p )
+ *p++ = '\0';
+ }
+ else
+ for ( start = p; *p && *p != ':' && *p != '/'; p++ )
+ ;
+ if ( host )
+ *host = start;
+
+ /* parse port */
+ if ( *p == ':' )
+ {
+ *p++ = '\0';
+ for ( start = p; *p && isdigit (*p); p++ )
+ ;
+ if ( *p )
+ *p++ = '\0';
+ if ( port )
+ *port = start;
+ }
+
+ if ( *p == '/' )
+ *p++ = '\0';
+
+ if ( *p && para )
+ *para = p;
+}
+
+/*****************************************************************
+** splitpath (path, size, filename)
+*****************************************************************/
+const char *splitpath (char *path, size_t size, const char *filename)
+{
+ char *p;
+
+ if ( !path )
+ return filename;
+
+ *path = '\0';
+ if ( !filename )
+ return filename;
+
+ if ( (p = strrchr (filename, '/')) ) /* file arg contains path ? */
+ {
+ if ( strlen (filename) > size )
+ return filename;
+
+ strcpy (path, filename);
+ path[p-filename] = '\0';
+ filename = ++p;
+ }
+ return filename;
+}
+
+/*****************************************************************
+** pathname (path, size, dir, file, ext)
+** Concatenate 'dir', 'file' and 'ext' (if not null) to build
+** a pathname, and store the result in the character array
+** with length 'size' pointed to by 'path'.
+*****************************************************************/
+char *pathname (char *path, size_t size, const char *dir, const char *file, const char *ext)
+{
+ int len;
+
+ if ( path == NULL || file == NULL )
+ return path;
+
+ len = strlen (file) + 1;
+ if ( dir )
+ len += strlen (dir);
+ if ( ext )
+ len += strlen (ext);
+ if ( len > size )
+ return path;
+
+ *path = '\0';
+ if ( dir && *dir )
+ {
+ len = sprintf (path, "%s", dir);
+ if ( path[len-1] != '/' )
+ {
+ path[len++] = '/';
+ path[len] = '\0';
+ }
+ }
+ strcat (path, file);
+ if ( ext )
+ strcat (path, ext);
+ return path;
+}
+
+/*****************************************************************
+** is_directory (name)
+** Check if the given pathname 'name' exists and is a directory.
+** returns 0 | 1
+*****************************************************************/
+int is_directory (const char *name)
+{
+ struct stat st;
+
+ if ( !name || !*name )
+ return 0;
+
+ return ( stat (name, &st) == 0 && S_ISDIR (st.st_mode) );
+}
+
+/*****************************************************************
+** fileexist (name)
+** Check if a file with the given pathname 'name' exists.
+** returns 0 | 1
+*****************************************************************/
+int fileexist (const char *name)
+{
+ struct stat st;
+ return ( stat (name, &st) == 0 && S_ISREG (st.st_mode) );
+}
+
+/*****************************************************************
+** filesize (name)
+** return the size of the file with the given pathname 'name'.
+** returns -1 if the file not exist
+*****************************************************************/
+size_t filesize (const char *name)
+{
+ struct stat st;
+ if ( stat (name, &st) == -1 )
+ return -1L;
+ return ( st.st_size );
+}
+
+/*****************************************************************
+** is_keyfilename (name)
+** Check if the given name looks like a dnssec (public)
+** keyfile name. Returns 0 | 1
+*****************************************************************/
+int is_keyfilename (const char *name)
+{
+ int len;
+
+ if ( name == NULL || *name != 'K' )
+ return 0;
+
+ len = strlen (name);
+ if ( len > 4 && strcmp (&name[len - 4], ".key") == 0 )
+ return 1;
+
+ return 0;
+}
+
+/*****************************************************************
+** is_dotfile (name)
+** Check if the given pathname 'name' looks like "." or "..".
+** Returns 0 | 1
+*****************************************************************/
+int is_dotfile (const char *name)
+{
+ if ( name && (
+ (name[0] == '.' && name[1] == '\0') ||
+ (name[0] == '.' && name[1] == '.' && name[2] == '\0')) )
+ return 1;
+
+ return 0;
+}
+
+/*****************************************************************
+** touch (name, sec)
+** Set the modification time of the given pathname 'fname' to
+** 'sec'. Returns 0 on success.
+*****************************************************************/
+int touch (const char *fname, time_t sec)
+{
+ struct utimbuf utb;
+
+ utb.actime = utb.modtime = sec;
+ return utime (fname, &utb);
+}
+
+/*****************************************************************
+** linkfile (fromfile, tofile)
+*****************************************************************/
+int linkfile (const char *fromfile, const char *tofile)
+{
+ int ret;
+
+ /* fprintf (stderr, "linkfile (%s, %s)\n", fromfile, tofile); */
+ if ( (ret = link (fromfile, tofile)) == -1 && errno == EEXIST )
+ if ( unlink (tofile) == 0 )
+ ret = link (fromfile, tofile);
+
+ return ret;
+}
+
+/*****************************************************************
+** copyfile (fromfile, tofile, dnskeyfile)
+*****************************************************************/
+int copyfile (const char *fromfile, const char *tofile, const char *dnskeyfile)
+{
+ FILE *infp;
+ FILE *outfp;
+ int c;
+
+ /* fprintf (stderr, "copyfile (%s, %s)\n", fromfile, tofile); */
+ if ( (infp = fopen (fromfile, "r")) == NULL )
+ return -1;
+ if ( (outfp = fopen (tofile, "w")) == NULL )
+ {
+ fclose (infp);
+ return -2;
+ }
+ while ( (c = getc (infp)) != EOF )
+ putc (c, outfp);
+
+ fclose (infp);
+ if ( dnskeyfile && *dnskeyfile && (infp = fopen (dnskeyfile, "r")) != NULL )
+ {
+ while ( (c = getc (infp)) != EOF )
+ putc (c, outfp);
+ fclose (infp);
+ }
+ fclose (outfp);
+
+ return 0;
+}
+
+/*****************************************************************
+** copyzonefile (fromfile, tofile, dnskeyfile)
+** copy a already signed zonefile and replace all zone DNSKEY
+** resource records by one "$INCLUDE dnskey.db" line
+*****************************************************************/
+int copyzonefile (const char *fromfile, const char *tofile, const char *dnskeyfile)
+{
+ FILE *infp;
+ FILE *outfp;
+ int len;
+ int dnskeys;
+ int multi_line_dnskey;
+ int bufoverflow;
+ char buf[1024];
+ char *p;
+
+ if ( fromfile == NULL )
+ infp = stdin;
+ else
+ if ( (infp = fopen (fromfile, "r")) == NULL )
+ return -1;
+ if ( tofile == NULL )
+ outfp = stdout;
+ else
+ if ( (outfp = fopen (tofile, "w")) == NULL )
+ {
+ if ( fromfile )
+ fclose (infp);
+ return -2;
+ }
+
+ multi_line_dnskey = 0;
+ dnskeys = 0;
+ bufoverflow = 0;
+ while ( fgets (buf, sizeof buf, infp) != NULL )
+ {
+ p = buf;
+ if ( !bufoverflow && !multi_line_dnskey && (*p == '@' || isspace (*p)) ) /* check if DNSKEY RR */
+ {
+ do
+ p++;
+ while ( isspace (*p) ) ;
+
+ /* skip TTL */
+ while ( isdigit (*p) )
+ p++;
+
+ while ( isspace (*p) )
+ p++;
+
+ /* skip Class */
+ if ( strncasecmp (p, "IN", 2) == 0 )
+ {
+ p += 2;
+ while ( isspace (*p) )
+ p++;
+ }
+
+ if ( strncasecmp (p, "DNSKEY", 6) == 0 ) /* bingo! */
+ {
+ dnskeys++;
+ p += 6;
+ while ( *p )
+ {
+ if ( *p == '(' )
+ multi_line_dnskey = 1;
+ if ( *p == ')' )
+ multi_line_dnskey = 0;
+ p++;
+ }
+ if ( dnskeys == 1 )
+ fprintf (outfp, "$INCLUDE %s\n", dnskeyfile);
+ }
+ else
+ fputs (buf, outfp);
+ }
+ else
+ {
+ if ( bufoverflow )
+ fprintf (stderr, "!! buffer overflow in copyzonefile() !!\n");
+ if ( !multi_line_dnskey )
+ fputs (buf, outfp);
+ else
+ {
+ while ( *p && *p != ')' )
+ p++;
+ if ( *p == ')' )
+ multi_line_dnskey = 0;
+ }
+ }
+
+ len = strlen (buf);
+ bufoverflow = buf[len-1] != '\n'; /* line too long ? */
+ }
+
+ if ( fromfile )
+ fclose (infp);
+ if ( tofile )
+ fclose (outfp);
+
+ return 0;
+}
+
+/*****************************************************************
+** cmpfile (file1, file2)
+** returns -1 on error, 1 if the files differ and 0 if they
+** are identical.
+*****************************************************************/
+int cmpfile (const char *file1, const char *file2)
+{
+ FILE *fp1;
+ FILE *fp2;
+ int c1;
+ int c2;
+
+ /* fprintf (stderr, "cmpfile (%s, %s)\n", file1, file2); */
+ if ( (fp1 = fopen (file1, "r")) == NULL )
+ return -1;
+ if ( (fp2 = fopen (file2, "r")) == NULL )
+ {
+ fclose (fp1);
+ return -1;
+ }
+
+ do {
+ c1 = getc (fp1);
+ c2 = getc (fp2);
+ } while ( c1 != EOF && c2 != EOF && c1 == c2 );
+
+ fclose (fp1);
+ fclose (fp2);
+
+ if ( c1 == c2 )
+ return 0;
+ return 1;
+}
+
+/*****************************************************************
+** file_age (fname)
+*****************************************************************/
+int file_age (const char *fname)
+{
+ time_t curr = time (NULL);
+ time_t mtime = file_mtime (fname);
+
+ return curr - mtime;
+}
+
+/*****************************************************************
+** file_mtime (fname)
+*****************************************************************/
+time_t file_mtime (const char *fname)
+{
+ struct stat st;
+
+ if ( stat (fname, &st) < 0 )
+ return 0;
+ return st.st_mtime;
+}
+
+/*****************************************************************
+** is_exec_ok (prog)
+** Check if we are running as root or if the file owner of
+** "prog" do not match the current user or the file permissions
+** allows file modification for others then the owner.
+** The same condition will be checked for the group ownership.
+** return 1 if the execution of the command "prog" will not
+** open a big security whole, 0 otherwise
+*****************************************************************/
+int is_exec_ok (const char *prog)
+{
+ uid_t curr_uid;
+ struct stat st;
+
+ if ( stat (prog, &st) < 0 )
+ return 0;
+
+ curr_uid = getuid ();
+ if ( curr_uid == 0 ) /* don't run the cmd if we are root */
+ return 0;
+
+ /* if the file owner and the current user matches and */
+ /* the file mode is not writable except for the owner, we are save */
+ if ( curr_uid == st.st_uid && (st.st_mode & (S_IWGRP | S_IWOTH)) == 0 )
+ return 1;
+
+ /* if the file group and the current group matches and */
+ /* the file mode is not writable except for the group, we are also save */
+ if ( getgid() != st.st_gid && (st.st_mode & (S_IWUSR | S_IWOTH)) == 0 )
+ return 1;
+
+ return 0;
+}
+
+/*****************************************************************
+** fatal (fmt, ...)
+*****************************************************************/
+void fatal (char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if ( progname )
+ fprintf (stderr, "%s: ", progname);
+ vfprintf (stderr, fmt, ap);
+ va_end(ap);
+ exit (127);
+}
+
+/*****************************************************************
+** error (fmt, ...)
+*****************************************************************/
+void error (char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end(ap);
+}
+
+/*****************************************************************
+** logmesg (fmt, ...)
+*****************************************************************/
+void logmesg (char *fmt, ...)
+{
+ va_list ap;
+
+#if defined (LOG_WITH_PROGNAME) && LOG_WITH_PROGNAME
+ fprintf (stdout, "%s: ", progname);
+#endif
+ va_start(ap, fmt);
+ vfprintf (stdout, fmt, ap);
+ va_end(ap);
+}
+
+/*****************************************************************
+** verbmesg (verblvl, conf, fmt, ...)
+*****************************************************************/
+void verbmesg (int verblvl, const zconf_t *conf, char *fmt, ...)
+{
+ char str[511+1];
+ va_list ap;
+
+ str[0] = '\0';
+ va_start(ap, fmt);
+ vsnprintf (str, sizeof (str), fmt, ap);
+ va_end(ap);
+
+ //fprintf (stderr, "verbmesg (%d stdout=%d filelog=%d str = :%s:\n", verblvl, conf->verbosity, conf->verboselog, str);
+ if ( verblvl <= conf->verbosity ) /* check if we have to print this to stdout */
+ logmesg (str);
+
+ str_chop (str, '\n');
+ if ( verblvl <= conf->verboselog ) /* check logging to syslog and/or file */
+ lg_mesg (LG_DEBUG, str);
+}
+
+
+/*****************************************************************
+** logflush ()
+*****************************************************************/
+void logflush ()
+{
+ fflush (stdout);
+}
+
+/*****************************************************************
+** timestr2time (timestr)
+** timestr should look like "20071211223901" for 12 dec 2007 22:39:01
+*****************************************************************/
+time_t timestr2time (const char *timestr)
+{
+ struct tm t;
+ time_t sec;
+
+ // fprintf (stderr, "timestr = \"%s\"\n", timestr);
+ if ( sscanf (timestr, "%4d%2d%2d%2d%2d%2d",
+ &t.tm_year, &t.tm_mon, &t.tm_mday,
+ &t.tm_hour, &t.tm_min, &t.tm_sec) != 6 )
+ return 0L;
+ t.tm_year -= 1900;
+ t.tm_mon -= 1;
+ t.tm_isdst = 0;
+
+#if defined(HAS_TIMEGM) && HAS_TIMEGM
+ sec = timegm (&t);
+#else
+ {
+ time_t ret;
+ char *tz;
+
+ tz = getenv("TZ");
+ // setenv("TZ", "", 1);
+ setenv("TZ", "UTC", 1);
+ tzset();
+ sec = mktime(&t);
+ if (tz)
+ setenv("TZ", tz, 1);
+ else
+ unsetenv("TZ");
+ tzset();
+ }
+#endif
+
+ return sec < 0L ? 0L : sec;
+}
+
+/*****************************************************************
+** time2str (sec, precison)
+** sec is seconds since 1.1.1970
+** precison is currently either 's' (for seconds) or 'm' (minutes)
+*****************************************************************/
+char *time2str (time_t sec, int precision)
+{
+ struct tm *t;
+ static char timestr[31+1]; /* 27+1 should be enough */
+#if defined(HAVE_STRFTIME) && HAVE_STRFTIME
+ char tformat[127+1];
+
+ timestr[0] = '\0';
+ if ( sec <= 0L )
+ return timestr;
+ t = localtime (&sec);
+ if ( precision == 's' )
+ strcpy (tformat, "%b %d %Y %T");
+ else
+ strcpy (tformat, "%b %d %Y %R");
+# if PRINT_TIMEZONE
+ strcat (tformat, " %z");
+# endif
+ strftime (timestr, sizeof (timestr), tformat, t);
+
+#else /* no strftime available */
+ static char *mstr[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+
+ timestr[0] = '\0';
+ if ( sec <= 0L )
+ return timestr;
+ t = localtime (&sec);
+# if PRINT_TIMEZONE
+ {
+ int h, s;
+
+ s = abs (t->tm_gmtoff);
+ h = t->tm_gmtoff / 3600;
+ s = t->tm_gmtoff % 3600;
+ if ( precision == 's' )
+ snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d:%02d %c%02d%02d",
+ mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
+ t->tm_hour, t->tm_min, t->tm_sec,
+ t->tm_gmtoff < 0 ? '-': '+',
+ h, s);
+ else
+ snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d %c%02d%02d",
+ mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
+ t->tm_hour, t->tm_min,
+ t->tm_gmtoff < 0 ? '-': '+',
+ h, s);
+ }
+# else
+ if ( precision == 's' )
+ snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d:%02d",
+ mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ else
+ snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d",
+ mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
+ t->tm_hour, t->tm_min);
+# endif
+#endif
+
+ return timestr;
+}
+
+/*****************************************************************
+** time2isostr (sec, precison)
+** sec is seconds since 1.1.1970
+** precison is currently either 's' (for seconds) or 'm' (minutes)
+*****************************************************************/
+char *time2isostr (time_t sec, int precision)
+{
+ struct tm *t;
+ static char timestr[31+1]; /* 27+1 should be enough */
+
+ timestr[0] = '\0';
+ if ( sec <= 0L )
+ return timestr;
+
+ t = gmtime (&sec);
+ if ( precision == 's' )
+ snprintf (timestr, sizeof (timestr), "%4d%02d%02d%02d%02d%02d",
+ t->tm_year + 1900, t->tm_mon+1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ else
+ snprintf (timestr, sizeof (timestr), "%4d%02d%02d%02d%02d",
+ t->tm_year + 1900, t->tm_mon+1, t->tm_mday,
+ t->tm_hour, t->tm_min);
+
+ return timestr;
+}
+
+/*****************************************************************
+** age2str (sec)
+** !!Attention: This function is not reentrant
+*****************************************************************/
+char *age2str (time_t sec)
+{
+ static char str[20+1]; /* "2y51w6d23h50m55s" == 16+1 chars */
+ int len;
+ int strsize = sizeof (str);
+
+ len = 0;
+# if PRINT_AGE_WITH_YEAR
+ if ( sec / (YEARSEC) > 0 )
+ {
+ len += snprintf (str+len, strsize - len, "%1luy", sec / YEARSEC );
+ sec %= (YEARSEC);
+ }
+ else
+ len += snprintf (str+len, strsize - len, " ");
+# endif
+ if ( sec / WEEKSEC > 0 )
+ {
+ len += snprintf (str+len, strsize - len, "%2luw", (ulong) sec / WEEKSEC );
+ sec %= WEEKSEC;
+ }
+ else
+ len += snprintf (str+len, strsize - len, " ");
+ if ( sec / DAYSEC > 0 )
+ {
+ len += snprintf (str+len, strsize - len, "%2lud", sec / (ulong)DAYSEC);
+ sec %= DAYSEC;
+ }
+ else
+ len += snprintf (str+len, strsize - len, " ");
+ if ( sec / HOURSEC > 0 )
+ {
+ len += snprintf (str+len, strsize - len, "%2luh", sec / (ulong)HOURSEC);
+ sec %= HOURSEC;
+ }
+ else
+ len += snprintf (str+len, strsize - len, " ");
+ if ( sec / MINSEC > 0 )
+ {
+ len += snprintf (str+len, strsize - len, "%2lum", sec / (ulong)MINSEC);
+ sec %= MINSEC;
+ }
+ else
+ len += snprintf (str+len, strsize - len, " ");
+ if ( sec > 0 )
+ snprintf (str+len, strsize - len, "%2lus", (ulong) sec);
+ else
+ len += snprintf (str+len, strsize - len, " ");
+
+ return str;
+}
+
+/*****************************************************************
+** start_timer ()
+*****************************************************************/
+time_t start_timer ()
+{
+ return (time(NULL));
+}
+
+/*****************************************************************
+** stop_timer ()
+*****************************************************************/
+time_t stop_timer (time_t start)
+{
+ time_t stop = time (NULL);
+
+ return stop - start;
+}
+
+/****************************************************************
+**
+** int inc_serial (filename, use_unixtime)
+**
+** This function depends on a special syntax formating the
+** SOA record in the zone file!!
+**
+** To match the SOA record, the SOA RR must be formatted
+** like this:
+** @ IN SOA <master.fq.dn.> <hostmaster.fq.dn.> (
+** <SPACEes or TABs> 1234567890; serial number
+** <SPACEes or TABs> 86400 ; other values
+** ...
+** The space from the first digit of the serial number to
+** the first none white space char or to the end of the line
+** must be at least 10 characters!
+** So you have to left justify the serial number in a field
+** of at least 10 characters like this:
+** <SPACEes or TABs> 1 ; Serial
+**
+****************************************************************/
+int inc_serial (const char *fname, int use_unixtime)
+{
+ FILE *fp;
+ char buf[4095+1];
+ char master[254+1];
+ int error;
+
+ /**
+ since BIND 9.4, there is a dnssec-signzone option available for
+ serial number increment.
+ If the user request "unixtime" than use this mechanism
+ **/
+#if defined(BIND_VERSION) && BIND_VERSION >= 940
+ if ( use_unixtime )
+ return 0;
+#endif
+ if ( (fp = fopen (fname, "r+")) == NULL )
+ return -1;
+
+ /* read until the line matches the beginning of a soa record ... */
+ while ( fgets (buf, sizeof buf, fp) &&
+ sscanf (buf, "@ IN SOA %255s %*s (\n", master) != 1 )
+ ;
+
+ if ( feof (fp) )
+ {
+ fclose (fp);
+ return -2;
+ }
+
+ error = inc_soa_serial (fp, use_unixtime); /* .. inc soa serial no ... */
+
+ if ( fclose (fp) != 0 )
+ return -5;
+ return error;
+}
+
+/*****************************************************************
+** return the serial number of the current day in the form
+** of YYYYmmdd00
+*****************************************************************/
+static ulong today_serialtime ()
+{
+ struct tm *t;
+ ulong serialtime;
+ time_t now;
+
+ now = time (NULL);
+ t = gmtime (&now);
+ serialtime = (t->tm_year + 1900) * 10000;
+ serialtime += (t->tm_mon+1) * 100;
+ serialtime += t->tm_mday;
+ serialtime *= 100;
+
+ return serialtime;
+}
+
+/*****************************************************************
+** inc_soa_serial (fp, use_unixtime)
+** increment the soa serial number of the file 'fp'
+** 'fp' must be opened "r+"
+*****************************************************************/
+static int inc_soa_serial (FILE *fp, int use_unixtime)
+{
+ int c;
+ long pos, eos;
+ ulong serial;
+ int digits;
+ ulong today;
+
+ /* move forward until any non ws reached */
+ while ( (c = getc (fp)) != EOF && isspace (c) )
+ ;
+ ungetc (c, fp); /* push back the last char */
+
+ pos = ftell (fp); /* mark position */
+
+ serial = 0L; /* read in the current serial number */
+ /* be aware of the trailing space in the format string !! */
+ if ( fscanf (fp, "%lu ", &serial) != 1 ) /* try to get serial no */
+ return -3;
+ eos = ftell (fp); /* mark first non digit/ws character pos */
+
+ digits = eos - pos;
+ if ( digits < 10 ) /* not enough space for serial no ? */
+ return -4;
+
+ if ( use_unixtime )
+ today = time (NULL);
+ else
+ {
+ today = today_serialtime (); /* YYYYmmdd00 */
+ if ( serial > 1970010100L && serial < today )
+ serial = today; /* set to current time */
+ serial++; /* increment anyway */
+ }
+
+ fseek (fp, pos, SEEK_SET); /* go back to the beginning */
+ fprintf (fp, "%-*lu", digits, serial); /* write as many chars as before */
+
+ return 1; /* yep! */
+}
+
+/*****************************************************************
+** return the error text of the inc_serial return coode
+*****************************************************************/
+const char *inc_errstr (int err)
+{
+ switch ( err )
+ {
+ case -1: return "couldn't open zone file for modifying";
+ case -2: return "unexpected end of file";
+ case -3: return "no serial number found in zone file";
+ case -4: return "not enough space left for serialno";
+ case -5: return "error on closing zone file";
+ }
+ return "";
+}
+
+#ifdef SOA_TEST
+const char *progname;
+main (int argc, char *argv[])
+{
+ ulong now;
+ int err;
+ char cmd[255];
+
+ progname = *argv;
+
+ now = today_serialtime ();
+ printf ("now = %lu\n", now);
+
+ if ( (err = inc_serial (argv[1]), 0) < 0 )
+ error ("can't change serial errno=%d\n", err);
+
+ snprintf (cmd, sizeof(cmd), "head -15 %s", argv[1]);
+ system (cmd);
+}
+#endif
+
+#ifdef COPYZONE_TEST
+const char *progname;
+main (int argc, char *argv[])
+{
+ progname = *argv;
+
+ if ( copyzonefile (argv[1], NULL) < 0 )
+ error ("can't copy zone file %s\n", argv[1]);
+}
+#endif
+
+#ifdef URL_TEST
+const char *progname;
+main (int argc, char *argv[])
+{
+ char *proto;
+ char *host;
+ char *port;
+ char *para;
+ char url[1024];
+
+ progname = *argv;
+
+ proto = host = port = para = NULL;
+
+ if ( --argc <= 0 )
+ {
+ fprintf (stderr, "usage: url_test <url>\n");
+ fprintf (stderr, "e.g.: url_test http://www.hznet.de:80/zkt\n");
+ exit (1);
+ }
+
+ strcpy (url, argv[1]);
+ parseurl (url, &proto, &host, &port, &para);
+
+ if ( proto )
+ printf ("proto: \"%s\"\n", proto);
+ if ( host )
+ printf ("host: \"%s\"\n", host);
+ if ( port )
+ printf ("port: \"%s\"\n", port);
+ if ( para )
+ printf ("para: \"%s\"\n", para);
+
+}
+#endif
+
diff --git a/contrib/zkt/misc.h b/contrib/zkt/misc.h
new file mode 100644
index 0000000..842a80d
--- /dev/null
+++ b/contrib/zkt/misc.h
@@ -0,0 +1,84 @@
+/*****************************************************************
+**
+** @(#) misc.h (c) 2005 - 2007 Holger Zuleger hznet.de
+**
+** Copyright (c) 2005 - 2007, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+#ifndef MISC_H
+# define MISC_H
+# include <sys/types.h>
+# include <stdarg.h>
+# include <stdio.h>
+# include "zconf.h"
+
+# define min(a, b) ((a) < (b) ? (a) : (b))
+# define max(a, b) ((a) > (b) ? (a) : (b))
+
+extern const char *getnameappendix (const char *progname, const char *basename);
+extern const char *getdefconfname (const char *view);
+extern int fileexist (const char *name);
+extern size_t filesize (const char *name);
+extern int file_age (const char *fname);
+extern int touch (const char *fname, time_t sec);
+extern int linkfile (const char *fromfile, const char *tofile);
+//extern int copyfile (const char *fromfile, const char *tofile);
+extern int copyfile (const char *fromfile, const char *tofile, const char *dnskeyfile);
+extern int copyzonefile (const char *fromfile, const char *tofile, const char *dnskeyfile);
+extern int cmpfile (const char *file1, const char *file2);
+extern char *str_delspace (char *s);
+extern char *str_tolowerdup (const char *s);
+extern int in_strarr (const char *str, char *const arr[], int cnt);
+extern const char *splitpath (char *path, size_t size, const char *filename);
+extern char *pathname (char *name, size_t size, const char *path, const char *file, const char *ext);
+extern char *time2str (time_t sec, int precision);
+extern char *time2isostr (time_t sec, int precision);
+extern time_t timestr2time (const char *timestr);
+extern int is_keyfilename (const char *name);
+extern int is_directory (const char *name);
+extern time_t file_mtime (const char *fname);
+extern int is_exec_ok (const char *prog);
+extern char *age2str (time_t sec);
+extern time_t stop_timer (time_t start);
+extern time_t start_timer (void);
+extern void error (char *fmt, ...);
+extern void fatal (char *fmt, ...);
+extern void logmesg (char *fmt, ...);
+extern void verbmesg (int verblvl, const zconf_t *conf, char *fmt, ...);
+extern void logflush (void);
+extern int inc_serial (const char *fname, int use_unixtime);
+extern const char *inc_errstr (int err);
+extern char *str_untaint (char *str);
+extern char *str_chop (char *str, char c);
+extern int is_dotfile (const char *name);
+extern void parseurl (char *url, char **proto, char **host, char **port, char **para);
+#endif
diff --git a/contrib/zkt/ncparse.c b/contrib/zkt/ncparse.c
new file mode 100644
index 0000000..e67f4b0
--- /dev/null
+++ b/contrib/zkt/ncparse.c
@@ -0,0 +1,317 @@
+/*****************************************************************
+**
+** @(#) ncparse.c -- A very simple named.conf parser
+**
+** Copyright (c) Apr 2005 - Nov 2007, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+# include <stdio.h>
+# include <string.h>
+# include <ctype.h>
+# include <assert.h>
+# include "debug.h"
+# include "misc.h"
+# include "log.h"
+#define extern
+# include "ncparse.h"
+#undef extern
+
+# define TOK_STRING 257
+# define TOK_DIR 258
+# define TOK_INCLUDE 259
+
+# define TOK_ZONE 260
+# define TOK_TYPE 261
+# define TOK_MASTER 262
+# define TOK_SLAVE 263
+# define TOK_STUB 264
+# define TOK_HINT 265
+# define TOK_FORWARD 266
+# define TOK_DELEGATION 267
+# define TOK_VIEW 268
+
+# define TOK_FILE 270
+
+# define TOK_UNKNOWN 511
+
+/* list of "named.conf" keywords we are interested in */
+static struct KeyWords {
+ char *name;
+ int tok;
+} kw[] = {
+ { "STRING", TOK_STRING },
+ { "include", TOK_INCLUDE },
+ { "directory", TOK_DIR },
+ { "file", TOK_FILE },
+ { "zone", TOK_ZONE },
+#if 0 /* we don't need the type keyword; master, slave etc. is sufficient */
+ { "type", TOK_TYPE },
+#endif
+ { "master", TOK_MASTER },
+ { "slave", TOK_SLAVE },
+ { "stub", TOK_STUB },
+ { "hint", TOK_HINT },
+ { "forward", TOK_FORWARD },
+ { "delegation-only", TOK_DELEGATION },
+ { "view", TOK_VIEW },
+ { NULL, TOK_UNKNOWN },
+};
+
+#ifdef DBG
+static const char *tok2str (int tok)
+{
+ int i;
+
+ i = 0;
+ while ( kw[i].name && kw[i].tok != tok )
+ i++;
+
+ return kw[i].name;
+}
+#endif
+
+static int searchkw (const char *keyword)
+{
+ int i;
+
+ dbg_val ("ncparse: searchkw (%s)\n", keyword);
+ i = 0;
+ while ( kw[i].name && strcmp (kw[i].name, keyword) != 0 )
+ i++;
+
+ return kw[i].tok;
+}
+
+static int gettok (FILE *fp, char *val, size_t valsize)
+{
+ int lastc;
+ int c;
+ char buf[255+1];
+ char *p;
+ char *bufend;
+
+ *val = '\0';
+ do {
+ while ( (c = getc (fp)) != EOF && isspace (c) )
+ ;
+
+ if ( c == '#' ) /* single line comment ? */
+ {
+ while ( (c = getc (fp)) != EOF && c != '\n' )
+ ;
+ continue;
+ }
+
+ if ( c == EOF )
+ return EOF;
+
+ if ( c == '{' || c == '}' || c == ';' )
+ continue;
+
+ if ( c == '/' ) /* begin of C comment ? */
+ {
+ if ( (c = getc (fp)) == '*' ) /* yes! */
+ {
+ lastc = EOF; /* read until end of c comment */
+ while ( (c = getc (fp)) != EOF && !(lastc == '*' && c == '/') )
+ lastc = c;
+ }
+ else if ( c == '/' ) /* is it a C single line comment ? */
+ {
+ while ( (c = getc (fp)) != EOF && c != '\n' )
+ ;
+ }
+ else /* no ! */
+ ungetc (c, fp);
+ continue;
+ }
+
+ if ( c == '\"' )
+ {
+ p = val;
+ bufend = val + valsize - 1;
+ while ( (c = getc (fp)) != EOF && p < bufend && c != '\"' )
+ *p++ = c;
+ *p = '\0';
+ /* if string buffer is too small, eat up rest of string */
+ while ( c != EOF && c != '\"' )
+ c = getc (fp);
+
+ return TOK_STRING;
+ }
+
+ p = buf;
+ bufend = buf + sizeof (buf) - 1;
+ do
+ *p++ = tolower (c);
+ while ( (c = getc (fp)) != EOF && p < bufend && isalpha (c) );
+ *p = '\0';
+ ungetc (c, fp);
+
+ if ( (c = searchkw (buf)) != TOK_UNKNOWN )
+ return c;
+ } while ( c != EOF );
+
+ return EOF;
+}
+
+/*****************************************************************
+**
+** parse_namedconf (const char *filename, int (*func) ())
+**
+** Very dumb named.conf parser.
+** - In a zone declaration the _first_ keyword MUST be "type"
+** - For every master zone "func (directory, zone, filename)" will be called
+**
+*****************************************************************/
+int parse_namedconf (const char *filename, char *dir, size_t dirsize, int (*func) ())
+{
+ FILE *fp;
+ int tok;
+ char path[511+1];
+#if 1 /* this is potentialy too small for key data, but we don't need the keys... */
+ char strval[255+1];
+#else
+ char strval[4095+1];
+#endif
+ char view[255+1];
+ char zone[255+1];
+ char zonefile[255+1];
+
+ dbg_val ("parse_namedconf: parsing file \"%s\" \n", filename);
+
+ assert (filename != NULL);
+ assert (dir != NULL && dirsize != 0);
+ assert (func != NULL);
+
+ view[0] = '\0';
+ if ( (fp = fopen (filename, "r")) == NULL )
+ return 0;
+
+ while ( (tok = gettok (fp, strval, sizeof strval)) != EOF )
+ {
+ if ( tok > 0 && tok < 256 )
+ {
+ error ("parse_namedconf: token found with value %-10d: %c\n", tok, tok);
+ lg_mesg (LG_ERROR, "parse_namedconf: token found with value %-10d: %c", tok, tok);
+ }
+ else if ( tok == TOK_DIR )
+ {
+ if ( gettok (fp, strval, sizeof (strval)) == TOK_STRING )
+ {
+ dbg_val2 ("parse_namedconf: directory found \"%s\" (dir is %s)\n",
+ strval, dir);
+ if ( *strval != '/' && *dir )
+ snprintf (path, sizeof (path), "%s/%s", dir, strval);
+ else
+ snprintf (path, sizeof (path), "%s", strval);
+ snprintf (dir, dirsize, "%s", path);
+ dbg_val ("parse_namedconf: new dir \"%s\" \n", dir);
+ }
+ }
+ else if ( tok == TOK_INCLUDE )
+ {
+ if ( gettok (fp, strval, sizeof (strval)) == TOK_STRING )
+ {
+ if ( *strval != '/' && *dir )
+ snprintf (path, sizeof (path), "%s/%s", dir, strval);
+ else
+ snprintf (path, sizeof (path), "%s", strval);
+ if ( !parse_namedconf (path, dir, dirsize, func) )
+ return 0;
+ }
+ else
+ {
+ error ("parse_namedconf: need a filename after \"include\"!\n");
+ lg_mesg (LG_ERROR, "parse_namedconf: need a filename after \"include\"!");
+ }
+ }
+ else if ( tok == TOK_VIEW )
+ {
+ if ( gettok (fp, strval, sizeof (strval)) != TOK_STRING )
+ continue;
+ snprintf (view, sizeof view, "%s", strval); /* store the name of the view */
+ }
+ else if ( tok == TOK_ZONE )
+ {
+ if ( gettok (fp, strval, sizeof (strval)) != TOK_STRING )
+ continue;
+ snprintf (zone, sizeof zone, "%s", strval); /* store the name of the zone */
+
+ if ( gettok (fp, strval, sizeof (strval)) != TOK_MASTER )
+ continue;
+ if ( gettok (fp, strval, sizeof (strval)) != TOK_FILE )
+ continue;
+ if ( gettok (fp, strval, sizeof (strval)) != TOK_STRING )
+ continue;
+ snprintf (zonefile, sizeof zonefile, "%s", strval); /* this is the filename */
+
+ dbg_val4 ("dir %s view %s zone %s file %s\n", dir, view, zone, zonefile);
+ (*func) (dir, view, zone, zonefile);
+ }
+ else
+ dbg_val3 ("%-10s(%d): %s\n", tok2str(tok), tok, strval);
+ }
+ fclose (fp);
+
+ return 1;
+}
+
+#ifdef TEST_NCPARSE
+int printzone (const char *dir, const char *view, const char *zone, const char *file)
+{
+ printf ("printzone ");
+ printf ("view \"%s\" " , view);
+ printf ("zone \"%s\" " , zone);
+ printf ("file ");
+ if ( dir && *dir )
+ printf ("%s/", dir, file);
+ printf ("%s", file);
+ putchar ('\n');
+ return 1;
+}
+
+char *progname;
+
+main (int argc, char *argv[])
+{
+ char directory[255+1];
+
+ progname = argv[0];
+
+ directory[0] = '\0';
+ if ( --argc == 0 )
+ parse_namedconf ("/var/named/named.conf", directory, sizeof (directory), printzone);
+ else
+ parse_namedconf (argv[1], directory, sizeof (directory), printzone);
+}
+#endif
diff --git a/contrib/zkt/ncparse.h b/contrib/zkt/ncparse.h
new file mode 100644
index 0000000..4383c63
--- /dev/null
+++ b/contrib/zkt/ncparse.h
@@ -0,0 +1,41 @@
+/*****************************************************************
+**
+** @(#) ncparse.h -- headerfile for a simple named.conf parser
+**
+** Copyright (c) Apr 2005 - Nov 2007, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+
+#ifndef NCPARSE_H
+# define NCPARSE_H
+extern int parse_namedconf (const char *filename, char *dir, size_t dirsize, int (*func) ());
+#endif
diff --git a/contrib/zkt/rollover.c b/contrib/zkt/rollover.c
new file mode 100644
index 0000000..0c9fee0
--- /dev/null
+++ b/contrib/zkt/rollover.c
@@ -0,0 +1,615 @@
+/*****************************************************************
+**
+** @(#) rollover.c -- The key rollover functions
+**
+** Copyright (c) Jan 2005 - May 2008, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+# include <ctype.h>
+# include <time.h>
+# include <assert.h>
+# include <dirent.h>
+# include <errno.h>
+# include <unistd.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+# include "zconf.h"
+# include "debug.h"
+
+# include "misc.h"
+# include "zone.h"
+# include "dki.h"
+# include "log.h"
+#define extern
+# include "rollover.h"
+#undef extern
+
+/*****************************************************************
+** local function definition
+*****************************************************************/
+
+static dki_t *genkey (dki_t **listp, const char *dir, const char *domain, int ksk, const zconf_t *conf, int status)
+{
+ dki_t *dkp;
+
+ if ( listp == NULL || domain == NULL )
+ return NULL;
+
+ if ( ksk )
+ dkp = dki_new (dir, domain, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
+ else
+ dkp = dki_new (dir, domain, DKI_ZSK, conf->z_algo, conf->z_bits, conf->z_random, conf->z_life / DAYSEC);
+ dki_add (listp, dkp);
+ dki_setstatus (dkp, status);
+
+ return dkp;
+}
+
+static time_t get_exptime (dki_t *key, const zconf_t *z)
+{
+ time_t exptime;
+
+ exptime = dki_exptime (key);
+ if ( exptime == 0L )
+ {
+ if ( dki_lifetime (key) )
+ exptime = dki_time (key) + dki_lifetime (key);
+ else
+ exptime = dki_time (key) + z->k_life;
+ }
+
+ return exptime;
+}
+
+/*****************************************************************
+** is_parentdirsigned (name)
+** Check if the parent directory of the zone specified by zp
+** is a directory with a signed zone
+** Returns 0 | 1
+*****************************************************************/
+static int is_parentdirsigned (const zone_t *zonelist, const zone_t *zp)
+{
+ char path[MAX_PATHSIZE+1];
+ const char *ext;
+#if 0
+ const zconf_t *conf;
+
+ /* check if there is a local config file to get the name of the zone file */
+ snprintf (path, sizeof (path), "%s/../%s", zp->dir, LOCALCONF_FILE);
+ if ( fileexist (path) ) /* parent dir has local config file ? */
+ conf = loadconfig (path, NULL);
+ else
+ conf = zp->conf;
+
+ /* build the path of the .signed zone file */
+ snprintf (path, sizeof (path), "%s/../%s.signed", conf->dir, conf->zonefile);
+ if ( conf != zp->conf ) /* if we read in a local config file.. */
+ free (conf); /* ..free the memory used */
+
+#else
+ /* currently we use the signed zone file name of the
+ * current directory for checking if the file exist.
+ * TODO: Instead we have to use the name of the zone file
+ * used in the parent dir (see above)
+ */
+
+ ext = strrchr (zp->sfile, '.');
+ if ( ext && strcmp (zp->sfile, ".dsigned") == 0 ) /* is the current zone a dynamic one ? */
+ /* hack: we are using the standard zone file name for a static zone here */
+ snprintf (path, sizeof (path), "%s/../%s", zp->dir, "zone.db.signed");
+ else
+ {
+# if 1
+ const zone_t *parent;
+ const char *parentname;
+
+ /* find out name of parent */
+ parentname = strchr (zp->zone, '.'); /* find first dot in zone name */
+ if ( parentname == NULL ) /* no parent found! */
+ return 0;
+ parentname += 1; /* skip '.' */
+
+ /* try to find parent zone in zonelist */
+ if ( (parent = zone_search (zonelist, parentname)) == NULL )
+ return 0;
+ snprintf (path, sizeof (path), "%s/%s", parent->dir, parent->sfile);
+# else
+ snprintf (path, sizeof (path), "%s/../%s", zp->dir, zp->sfile);
+# endif
+ }
+#endif
+lg_mesg (LG_DEBUG, "%s: is_parentdirsigned = %d fileexist (%s)\n", zp->zone, fileexist (path), path);
+ return fileexist (path); /* parent dir has zone.db.signed file ? */
+}
+
+/*****************************************************************
+** create_parent_file ()
+*****************************************************************/
+static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp)
+{
+ FILE *fp;
+
+ assert ( fname != NULL );
+
+ if ( dkp == NULL || (phase != 1 && phase != 2) )
+ return 0;
+
+ if ( (fp = fopen (fname, "w")) == NULL )
+ fatal ("can\'t create new parentfile \"%s\"\n", fname);
+
+ if ( phase == 1 )
+ fprintf (fp, "; KSK rollover phase1 (new key generated but this is alread the old one)\n");
+ else
+ fprintf (fp, "; KSK rollover phase2 (this is the new key)\n");
+
+ dki_prt_dnskeyttl (dkp, fp, ttl);
+ fclose (fp);
+
+ return phase;
+}
+
+/*****************************************************************
+** get_parent_phase ()
+*****************************************************************/
+static int get_parent_phase (const char *file)
+{
+ FILE *fp;
+ int phase;
+
+ if ( (fp = fopen (file, "r")) == NULL )
+ return -1;
+
+ phase = 0;
+ if ( fscanf (fp, "; KSK rollover phase%d", &phase) != 1 )
+ phase = 0;
+
+ fclose (fp);
+ return phase;
+}
+
+/*****************************************************************
+** kskrollover ()
+*****************************************************************/
+static int kskrollover (dki_t *ksk, zone_t *zonelist, zone_t *zp)
+{
+ char path[MAX_PATHSIZE+1];
+ const zconf_t *z;
+ time_t lifetime;
+ time_t currtime;
+ time_t age;
+ int currphase;
+ int parfile_age;
+ int parent_propagation;
+ int parent_resign;
+ int parent_keyttl;
+
+
+ assert ( ksk != NULL );
+ assert ( zp != NULL );
+
+ z = zp->conf;
+ /* check ksk lifetime */
+ if ( (lifetime = dki_lifetime (ksk)) == 0 ) /* if lifetime of key is not set.. */
+ lifetime = z->k_life; /* ..use global configured lifetime */
+
+ currtime = time (NULL);
+ age = dki_age (ksk, currtime);
+
+ /* build path of parent-file */
+ pathname (path, sizeof (path), zp->dir, "parent-", zp->zone);
+
+ /* check if we have to change the ksk ? */
+ if ( lifetime > 0 && age > lifetime && !fileexist (path) ) /* lifetime is over and no kskrollover in progress */
+ {
+ /* we are using hierachical mode and the parent directory contains a signed zone ? */
+ if ( z->keysetdir && strcmp (z->keysetdir, "..") == 0 && is_parentdirsigned (zonelist, zp) )
+ {
+ verbmesg (2, z, "\t\tkskrollover: create new key signing key\n");
+ /* create a new key: this is phase one of a double signing key rollover */
+ ksk = genkey (&zp->keys, zp->dir, zp->zone, DKI_KSK, z, DKI_ACTIVE);
+ if ( ksk == NULL )
+ {
+ lg_mesg (LG_ERROR, "\"%s\": unable to generate new ksk for double signing rollover", zp->zone);
+ return 0;
+ }
+ lg_mesg (LG_INFO, "\"%s\": kskrollover phase1: New key %d generated", zp->zone, ksk->tag);
+
+ /* find the oldest active ksk to create the parent file */
+ if ( (ksk = (dki_t *)dki_find (zp->keys, 1, 'a', 1)) == NULL )
+ lg_mesg (LG_ERROR, "kskrollover phase1: Couldn't find the old active key\n");
+ if ( !create_parent_file (path, 1, z->key_ttl, ksk) )
+ lg_mesg (LG_ERROR, "Couldn't create parentfile %s\n", path);
+
+ }
+ else /* print out a warning only */
+ {
+ logmesg ("\t\tWarning: Lifetime of Key Signing Key %d exceeded: %s\n",
+ ksk->tag, str_delspace (age2str (age)));
+ lg_mesg (LG_WARNING, "\"%s\": lifetime of key signing key %d exceeded since %s",
+ zp->zone, ksk->tag, str_delspace (age2str (age - lifetime)));
+ }
+ return 1;
+ }
+
+ /* now check if there is an ongoing key rollover */
+
+ /* check if parent-file already exist */
+ if ( !fileexist (path) ) /* no parent-<zone> file found ? */
+ return 0; /* ok, that's it */
+
+ /* check the ksk rollover phase we are in */
+ currphase = get_parent_phase (path); /* this is the actual state we are in */
+ parfile_age = file_age (path);
+
+ /* TODO: Set these values to the one found in the parent dnssec.conf file */
+ parent_propagation = 5 * MINSEC;
+ parent_resign = z->resign;
+ parent_keyttl = z->key_ttl;
+
+ switch ( currphase )
+ {
+ case 1: /* we are currently in state one (new ksk already generated) */
+ if ( parfile_age > z->proptime + z->key_ttl ) /* can we go to phase 2 ? */
+ {
+ verbmesg (2, z, "\t\tkskrollover: save new ksk in parent file\n");
+ ksk = ksk->next; /* set ksk to new ksk */
+ if ( !create_parent_file (path, currphase+1, z->key_ttl, ksk) )
+ lg_mesg (LG_ERROR, "Couldn't create parentfile %s\n", path);
+ lg_mesg (LG_INFO, "\"%s\": kskrollover phase2: send new key %d to the parent zone", zp->zone, ksk->tag);
+ return 1;
+ }
+ else
+ verbmesg (2, z, "\t\tkskrollover: we are in state 1 and waiting for propagation of the new key (parentfile %d < prop %d + keyttl %d\n", parfile_age, z->proptime, z->key_ttl);
+ break;
+ case 2: /* we are currently in state two (propagation of new key to the parent) */
+#if 0
+ if ( parfile_age >= parent_propagation + parent_resign + parent_keyttl ) /* can we go to phase 3 ? */
+#else
+ if ( parfile_age >= parent_propagation + parent_keyttl ) /* can we go to phase 3 ? */
+#endif
+ {
+ /* remove the parentfile */
+ unlink (path);
+
+ /* remove oldest key from list and mark file as removed */
+ zp->keys = dki_remove (ksk);
+
+ // verbmesg (2, z, "kskrollover: remove parentfile and rename old key to k<zone>+<algo>+<tag>.key\n");
+ verbmesg (2, z, "\t\tkskrollover: remove parentfile and rename old key to k%s+%03d+%05d.key\n",
+ ksk->name, ksk->algo, ksk->tag);
+ lg_mesg (LG_INFO, "\"%s\": kskrollover phase3: Remove old key %d", zp->zone, ksk->tag);
+ return 1;
+ }
+ else
+#if 0
+ verbmesg (2, z, "\t\tkskrollover: we are in state 2 and waiting for parent propagation (parentfile %d < parentprop %d + parentresig %d + parentkeyttl %d\n", parfile_age, parent_propagation, parent_resign, parent_keyttl);
+#else
+ verbmesg (2, z, "\t\tkskrollover: we are in state 2 and waiting for parent propagation (parentfile %d < parentprop %d + parentkeyttl %d\n", parfile_age, parent_propagation, parent_keyttl);
+#endif
+ break;
+ default:
+ assert ( currphase == 1 || currphase == 2 );
+ /* NOTREACHED */
+ }
+
+ return 0;
+}
+
+/*****************************************************************
+** global function definition
+*****************************************************************/
+
+/*****************************************************************
+** ksk5011status ()
+** Check if the list of zone keys containing a revoked or a
+** standby key.
+** Remove the revoked key if it is older than 30 days.
+** If the lifetime of the active key is reached, do a rfc5011
+** keyrollover.
+** Returns an int with the rightmost bit set if a resigning
+** is required. The second rightmost bit is set, if it is an
+** rfc5011 zone.
+*****************************************************************/
+int ksk5011status (dki_t **listp, const char *dir, const char *domain, const zconf_t *z)
+{
+ dki_t *standbykey;
+ dki_t *activekey;
+ dki_t *dkp;
+ dki_t *prev;
+ time_t currtime;
+ time_t exptime;
+ int ret;
+
+ assert ( listp != NULL );
+ assert ( z != NULL );
+
+ if ( z->k_life == 0 )
+ return 0;
+
+ verbmesg (1, z, "\tCheck RFC5011 status\n");
+
+ ret = 0;
+ currtime = time (NULL);
+
+ /* go through the list of key signing keys, */
+ /* remove revoked keys and set a pointer to standby and active key */
+ standbykey = activekey = NULL;
+ prev = NULL;
+ for ( dkp = *listp; dkp && dki_isksk (dkp); dkp = dkp->next )
+ {
+ exptime = get_exptime (dkp, z);
+ if ( dki_isrevoked (dkp) )
+ lg_mesg (LG_DEBUG, "Rev Exptime: %s", time2str (exptime, 's'));
+
+ /* revoked key is older than 30 days? */
+ if ( dki_isrevoked (dkp) && currtime > exptime + (DAYSEC * 30) )
+ {
+ verbmesg (1, z, "\tRemove revoked key %d which is older than 30 days\n", dkp->tag);
+ lg_mesg (LG_NOTICE, "zone \"%s\": removing revoked key %d", domain, dkp->tag);
+
+ /* remove key from list and mark file as removed */
+ if ( prev == NULL ) /* at the beginning of the list ? */
+ *listp = dki_remove (dkp);
+ else /* anywhere in the middle of the list */
+ prev->next = dki_remove (dkp);
+
+ ret |= 01; /* from now on a resigning is neccessary */
+ }
+
+ /* remember oldest standby and active key */
+ if ( dki_status (dkp) == DKI_PUBLISHED )
+ standbykey = dkp;
+ if ( dki_status (dkp) == DKI_ACTIVE )
+ activekey = dkp;
+ }
+
+ if ( standbykey == NULL && ret == 0 ) /* no standby key and also no revoked key found ? */
+ return ret; /* Seems that this is a non rfc5011 zone! */
+
+ ret |= 02; /* Zone looks like a rfc5011 zone */
+
+ exptime = get_exptime (activekey, z);
+#if 0
+ lg_mesg (LG_DEBUG, "Act Exptime: %s", time2str (exptime, 's'));
+ lg_mesg (LG_DEBUG, "Stb time: %s", time2str (dki_time (standbykey), 's'));
+ lg_mesg (LG_DEBUG, "Stb time+wait: %s", time2str (dki_time (standbykey) + min (DAYSEC * 30, z->key_ttl), 's'));
+#endif
+ /* At the time we first introduce a standby key, the lifetime of the current KSK should not be expired, */
+ /* otherwise we run into an (nearly) immediate key rollover! */
+ if ( currtime > exptime && currtime > dki_time (standbykey) + min (DAYSEC * 30, z->key_ttl) )
+ {
+ lg_mesg (LG_NOTICE, "\"%s\": starting rfc5011 rollover", domain);
+ verbmesg (1, z, "\tLifetime of Key Signing Key %d exceeded (%s): Starting rfc5011 rollover!\n",
+ activekey->tag, str_delspace (age2str (dki_age (activekey, currtime))));
+ verbmesg (2, z, "\t\t=>Generating new standby key signing key\n");
+ dkp = genkey (listp, dir, domain, DKI_KSK, z, DKI_PUBLISHED); /* gentime == now; lifetime = z->k_life; exp = 0 */
+ if ( !dkp )
+ {
+ error ("\tcould not generate new standby KSK\n");
+ lg_mesg (LG_ERROR, "\%s\": can't generate new standby KSK", domain);
+ }
+ else
+ lg_mesg (LG_INFO, "\"%s\": generated new standby KSK %d", domain, dkp->tag);
+
+ /* standby key gets active */
+ verbmesg (2, z, "\t\t=>Activating old standby key %d \n", standbykey->tag);
+ dki_setstatus (standbykey, DKI_ACT);
+
+ /* active key should be revoked */
+ verbmesg (2, z, "\t\t=>Revoking old active key %d \n", activekey->tag);
+ dki_setstatus (activekey, DKI_REVOKED);
+ dki_setexptime (activekey, currtime); /* now the key is expired */
+
+ ret |= 01; /* resigning neccessary */
+ }
+
+ return ret;
+}
+
+/*****************************************************************
+** kskstatus ()
+** Check the ksk status of a zone if a ksk lifetime is set.
+** If there is no key signing key present create a new one.
+** Prints out a warning message if the lifetime of the current
+** key signing key is over.
+** Returns 1 if a resigning of the zone is neccessary, otherwise
+** the function returns 0.
+*****************************************************************/
+int kskstatus (zone_t *zonelist, zone_t *zp)
+{
+ dki_t *akey;
+ const zconf_t *z;
+
+ assert ( zp != NULL );
+
+ z = zp->conf;
+ if ( z->k_life == 0 )
+ return 0;
+
+ verbmesg (1, z, "\tCheck KSK status\n");
+ /* check if a key signing key exist ? */
+ akey = (dki_t *)dki_find (zp->keys, 1, 'a', 1);
+ if ( akey == NULL )
+ {
+ verbmesg (1, z, "\tNo active KSK found: generate new one\n");
+ akey = genkey (&zp->keys, zp->dir, zp->zone, DKI_KSK, z, DKI_ACTIVE);
+ if ( !akey )
+ {
+ error ("\tcould not generate new KSK\n");
+ lg_mesg (LG_ERROR, "\"%s\": can't generate new KSK: \"%s\"",
+ zp->zone, dki_geterrstr());
+ }
+ else
+ lg_mesg (LG_INFO, "\"%s\": generated new KSK %d", zp->zone, akey->tag);
+ return akey != NULL; /* return value of 1 forces a resigning of the zone */
+ }
+ else /* try to start a full automatic ksk rollover */
+ kskrollover (akey, zonelist, zp);
+
+ return 0;
+}
+
+/*****************************************************************
+** zskstatus ()
+** Check the zsk status of a zone.
+** Returns 1 if a resigning of the zone is neccessary, otherwise
+** the function returns 0.
+*****************************************************************/
+int zskstatus (dki_t **listp, const char *dir, const char *domain, const zconf_t *z)
+{
+ dki_t *akey;
+ dki_t *nextkey;
+ dki_t *dkp, *last;
+ int keychange;
+ time_t lifetime;
+ time_t age;
+ time_t currtime;
+
+ assert ( listp != NULL );
+ /* dir can be NULL */
+ assert ( domain != NULL );
+ assert ( z != NULL );
+
+ currtime = time (NULL);
+
+ verbmesg (1, z, "\tCheck ZSK status\n");
+ dbg_val("zskstatus for %s \n", domain);
+ keychange = 0;
+ /* Is the depreciated key expired ? */
+ /* As mentioned by olaf, this is the max_ttl of all the rr in the zone */
+ lifetime = z->max_ttl + z->proptime; /* draft kolkman/gieben */
+ last = NULL;
+ dkp = *listp;
+ while ( dkp )
+ if ( !dki_isksk (dkp) &&
+ dki_status (dkp) == DKI_DEPRECIATED &&
+ dki_age (dkp, currtime) > lifetime )
+ {
+ keychange = 1;
+ verbmesg (1, z, "\tLifetime(%d sec) of depreciated key %d exceeded (%d sec)\n",
+ lifetime, dkp->tag, dki_age (dkp, currtime));
+ lg_mesg (LG_INFO, "\"%s\": old ZSK %d removed", domain, dkp->tag);
+ dkp = dki_destroy (dkp); /* delete the keyfiles */
+ dbg_msg("zskstatus: depreciated key removed ");
+ if ( last )
+ last->next = dkp;
+ else
+ *listp = dkp;
+ verbmesg (1, z, "\t\t->remove it\n");
+ }
+ else
+ {
+ last = dkp;
+ dkp = dkp->next;
+ }
+
+ /* check status of active key */
+ dbg_msg("zskstatus check status of active key ");
+ lifetime = z->z_life; /* global configured lifetime for zsk */
+ akey = (dki_t *)dki_find (*listp, 0, 'a', 1);
+ if ( akey == NULL && lifetime > 0 ) /* no active key found */
+ {
+ verbmesg (1, z, "\tNo active ZSK found: generate new one\n");
+ akey = genkey (listp, dir, domain, DKI_ZSK, z, DKI_ACTIVE);
+ lg_mesg (LG_INFO, "\"%s\": generated new ZSK %d", domain, akey->tag);
+ }
+ else /* active key exist */
+ {
+ if ( dki_lifetime (akey) )
+ lifetime = dki_lifetime (akey); /* set lifetime to lt of active key */
+
+ /* lifetime of active key is expired and published key exist ? */
+ age = dki_age (akey, currtime);
+ if ( lifetime > 0 && age > lifetime - (OFFSET) )
+ {
+ verbmesg (1, z, "\tLifetime(%d +/-%d sec) of active key %d exceeded (%d sec)\n",
+ lifetime, (OFFSET) , akey->tag, dki_age (akey, currtime) );
+
+ /* depreciate the key only if there is another active or published key */
+ if ( (nextkey = (dki_t *)dki_find (*listp, 0, 'a', 2)) == NULL ||
+ nextkey == akey )
+ nextkey = (dki_t *)dki_find (*listp, 0, 'p', 1);
+
+ /* Is the published key sufficient long in the zone ? */
+ /* As mentioned by Olaf, this should be the ttl of the DNSKEY RR ! */
+ if ( nextkey && dki_age (nextkey, currtime) > z->key_ttl + z->proptime )
+ {
+ keychange = 1;
+ verbmesg (1, z, "\t\t->depreciate it\n");
+ dki_setstatus (akey, 'd'); /* depreciate the active key */
+ verbmesg (1, z, "\t\t->activate published key %d\n", nextkey->tag);
+ dki_setstatus (nextkey, 'a'); /* activate published key */
+ lg_mesg (LG_NOTICE, "\"%s\": lifetime of zone signing key %d exceeded: ZSK rollover done", domain, akey->tag);
+ akey = nextkey;
+ nextkey = NULL;
+ }
+ else
+ {
+ verbmesg (1, z, "\t\t->waiting for published key\n");
+ lg_mesg (LG_NOTICE, "\"%s\": lifetime of zone signing key %d exceeded since %s: ZSK rollover deferred: waiting for published key",
+ domain, akey->tag, str_delspace (age2str (age - lifetime)));
+ }
+ }
+ }
+ /* Should we add a new publish key? This is neccessary if the active
+ * key will be expired at the next re-signing interval (The published
+ * time will be checked just before the active key will be removed.
+ * See above).
+ */
+ nextkey = (dki_t *)dki_find (*listp, 0, 'p', 1);
+ if ( nextkey == NULL && lifetime > 0 && (akey == NULL ||
+ dki_age (akey, currtime + z->resign) > lifetime - (OFFSET)) )
+ {
+ keychange = 1;
+ verbmesg (1, z, "\tNew key for publishing needed\n");
+ nextkey = genkey (listp, dir, domain, DKI_ZSK, z, DKI_PUB);
+
+ if ( nextkey )
+ {
+ verbmesg (1, z, "\t\t->creating new key %d\n", nextkey->tag);
+ lg_mesg (LG_INFO, "\"%s\": new key %d generated for publishing", domain, nextkey->tag);
+ }
+ else
+ {
+ error ("\tcould not generate new ZSK: \"%s\"\n", dki_geterrstr());
+ lg_mesg (LG_ERROR, "\"%s\": can't generate new ZSK: \"%s\"",
+ domain, dki_geterrstr());
+ }
+ }
+ return keychange;
+}
+
diff --git a/contrib/zkt/rollover.h b/contrib/zkt/rollover.h
new file mode 100644
index 0000000..8d53293
--- /dev/null
+++ b/contrib/zkt/rollover.h
@@ -0,0 +1,52 @@
+/*****************************************************************
+**
+** @(#) rollover.h (c) 2005 - 2008 Holger Zuleger hznet.de
+**
+** Copyright (c) 2005 - 2008, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+#ifndef ROLLOVER_H
+# define ROLLOVER_H
+# include <sys/types.h>
+# include <stdarg.h>
+# include <stdio.h>
+
+#ifndef ZCONF_H
+# include "zconf.h"
+#endif
+
+# define OFFSET ((int) (2.5 * MINSEC))
+
+extern int ksk5011status (dki_t **listp, const char *dir, const char *domain, const zconf_t *z);
+extern int kskstatus (zone_t *zonelist, zone_t *zp);
+extern int zskstatus (dki_t **listp, const char *dir, const char *domain, const zconf_t *z);
+#endif
diff --git a/contrib/zkt/strlist.c b/contrib/zkt/strlist.c
new file mode 100644
index 0000000..81a84bc
--- /dev/null
+++ b/contrib/zkt/strlist.c
@@ -0,0 +1,166 @@
+/*****************************************************************
+**
+** @(#) strlist.c (c) Mar 2005 Holger Zuleger
+**
+** TODO: Maybe we should use a special type for the list:
+** typedef struct { char cnt; char list[0+1]; } strlist__t;
+** This results in better type control of the function parameters
+**
+** Copyright (c) Mar 2005, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+
+#ifdef TEST
+# include <stdio.h>
+#endif
+#include <string.h>
+#include <stdlib.h>
+#include "strlist.h"
+
+
+/*****************************************************************
+** prepstrlist (str, delim)
+** prepare a string with delimeters to a so called strlist.
+** 'str' is a list of substrings delimeted by 'delim'
+** The # of strings is stored at the first byte of the allocated
+** memory. Every substring is stored as a '\0' terminated C-String.
+** The function returns a pointer to dynamic allocated memory
+*****************************************************************/
+char *prepstrlist (const char *str, const char *delim)
+{
+ char *p;
+ char *new;
+ int len;
+ int cnt;
+
+ if ( str == NULL )
+ return NULL;
+
+ len = strlen (str);
+ if ( (new = malloc (len + 2)) == NULL )
+ return new;
+
+ cnt = 0;
+ p = new;
+ for ( *p++ = '\0'; *str; str++ )
+ {
+ if ( strchr (delim, *str) == NULL )
+ *p++ = *str;
+ else if ( p[-1] != '\0' )
+ {
+ *p++ = '\0';
+ cnt++;
+ }
+ }
+ *p = '\0'; /*terminate string */
+ if ( p[-1] != '\0' )
+ cnt++;
+ *new = cnt & 0xFF;
+
+ return new;
+}
+
+/*****************************************************************
+** isinlist (str, list)
+** check if 'list' contains 'str'
+*****************************************************************/
+int isinlist (const char *str, const char *list)
+{
+ int cnt;
+
+ if ( list == NULL || *list == '\0' )
+ return 1;
+ if ( str == NULL || *str == '\0' )
+ return 0;
+
+ cnt = *list;
+ while ( cnt-- > 0 )
+ {
+ list++;
+ if ( strcmp (str, list) == 0 )
+ return 1;
+ list += strlen (list);
+ }
+
+ return 0;
+}
+
+/*****************************************************************
+** unprepstrlist (list, delimc)
+*****************************************************************/
+char *unprepstrlist (char *list, char delimc)
+{
+ char *p;
+ int cnt;
+
+ cnt = *list & 0xFF;
+ p = list;
+ for ( *p++ = delimc; cnt > 1; p++ )
+ if ( *p == '\0' )
+ {
+ *p = delimc;
+ cnt--;
+ }
+
+ return list;
+}
+
+#ifdef TEST
+main (int argc, char *argv[])
+{
+ FILE *fp;
+ char *p;
+ char *searchlist = NULL;
+ char group[255];
+
+ if ( argc > 1 )
+ searchlist = prepstrlist (argv[1], LISTDELIM);
+
+ printf ("searchlist: %d entrys: \n", searchlist[0]);
+ if ( (fp = fopen ("/etc/group", "r")) == NULL )
+ exit (fprintf (stderr, "can't open file\n"));
+
+ while ( fscanf (fp, "%[^:]:%*[^\n]\n", group) != EOF )
+ if ( isinlist (group, searchlist) )
+ printf ("%s\n", group);
+
+ fclose (fp);
+
+ printf ("searchlist: \"%s\"\n", unprepstrlist (searchlist, *LISTDELIM));
+ for ( p = searchlist; *p; p++ )
+ if ( *p < 32 )
+ printf ("<%d>", *p);
+ else
+ printf ("%c", *p);
+ printf ("\n");
+}
+#endif
diff --git a/contrib/zkt/strlist.h b/contrib/zkt/strlist.h
new file mode 100644
index 0000000..fb87356
--- /dev/null
+++ b/contrib/zkt/strlist.h
@@ -0,0 +1,46 @@
+/*****************************************************************
+**
+** @(#) strlist.h (c) Mar 2005 Holger Zuleger
+**
+** Copyright (c) May 2005 Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+
+#ifndef STRLIST_H
+# define STRLIST_H
+
+# define LISTDELIM " ,:;|^\t"
+
+char *prepstrlist (const char *str, const char *delim);
+int isinlist (const char *str, const char *list);
+char *unprepstrlist (char *list, char delimc);
+#endif
diff --git a/contrib/zkt/tags b/contrib/zkt/tags
new file mode 100644
index 0000000..1471aff
--- /dev/null
+++ b/contrib/zkt/tags
@@ -0,0 +1,324 @@
+!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
+!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
+!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
+!_TAG_PROGRAM_NAME Exuberant Ctags //
+!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
+!_TAG_PROGRAM_VERSION 5.5.4 //
+CONF_ALGO zconf.c /^ CONF_ALGO,$/;" e file:
+CONF_BOOL zconf.c /^ CONF_BOOL,$/;" e file:
+CONF_COMMENT zconf.c /^ CONF_COMMENT,$/;" e file:
+CONF_END zconf.c /^ CONF_END = 0,$/;" e file:
+CONF_FACILITY zconf.c /^ CONF_FACILITY,$/;" e file:
+CONF_INT zconf.c /^ CONF_INT,$/;" e file:
+CONF_LEVEL zconf.c /^ CONF_LEVEL,$/;" e file:
+CONF_SERIAL zconf.c /^ CONF_SERIAL,$/;" e file:
+CONF_STRING zconf.c /^ CONF_STRING,$/;" e file:
+CONF_TIMEINT zconf.c /^ CONF_TIMEINT,$/;" e file:
+ISCOMMENT zconf.c 68;" d file:
+ISDELIM zconf.c 70;" d file:
+ISTRUE zconf.c 66;" d file:
+KEYSET_FILE_PFX dnssec-signer.c 669;" d file:
+KeyWords ncparse.c /^static struct KeyWords {$/;" s file:
+MAXFNAME log.c 97;" d file:
+STRCONFIG_DELIMITER zconf.c 505;" d file:
+TAINTEDCHARS misc.c 60;" d file:
+TOK_DELEGATION ncparse.c 59;" d file:
+TOK_DIR ncparse.c 49;" d file:
+TOK_FILE ncparse.c 62;" d file:
+TOK_FORWARD ncparse.c 58;" d file:
+TOK_HINT ncparse.c 57;" d file:
+TOK_INCLUDE ncparse.c 50;" d file:
+TOK_MASTER ncparse.c 54;" d file:
+TOK_SLAVE ncparse.c 55;" d file:
+TOK_STRING ncparse.c 48;" d file:
+TOK_STUB ncparse.c 56;" d file:
+TOK_TYPE ncparse.c 53;" d file:
+TOK_UNKNOWN ncparse.c 64;" d file:
+TOK_VIEW ncparse.c 60;" d file:
+TOK_ZONE ncparse.c 52;" d file:
+a domaincmp.c /^ char *a;$/;" m file:
+add2zonelist dnssec-signer.c /^static int add2zonelist (const char *dir, const char *view, const char *zone, const char *file)$/;" f file:
+age2str misc.c /^char *age2str (time_t sec)$/;" f
+ageflag dnssec-zkt.c /^int ageflag = 0;$/;" v
+b domaincmp.c /^ char *b;$/;" m file:
+bool2str zconf.c /^static const char *bool2str (int val)$/;" f file:
+check_keydb_timestamp dnssec-signer.c /^static int check_keydb_timestamp (dki_t *keylist, time_t reftime)$/;" f file:
+checkconfig zconf.c /^int checkconfig (const zconf_t *z)$/;" f
+cmdline zconf.c /^ int cmdline; \/* is this a command line parameter ? *\/$/;" m file:
+cmpfile misc.c /^int cmpfile (const char *file1, const char *file2)$/;" f
+config dnssec-signer.c /^static zconf_t *config;$/;" v file:
+config zconf.c /^static zconf_t *config;$/;" v file:
+confpara zconf.c /^static zconf_para_t confpara[] = {$/;" v file:
+copy_keyset dnssec-signer.c /^static void copy_keyset (const char *dir, const char *domain, const zconf_t *conf)$/;" f file:
+copyfile misc.c /^int copyfile (const char *fromfile, const char *tofile, const char *dnskeyfile)$/;" f
+copyzonefile misc.c /^int copyzonefile (const char *fromfile, const char *tofile, const char *dnskeyfile)$/;" f
+create_parent_file dnssec-zkt.c /^static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp)$/;" f file:
+create_parent_file rollover.c /^static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp)$/;" f file:
+createkey dnssec-zkt.c /^static void createkey (const char *keyname, const dki_t *list, const zconf_t *conf)$/;" f file:
+ctype_t zconf.c /^} ctype_t;$/;" t file:
+def zconf.c /^static zconf_t def = {$/;" v file:
+dirflag dnssec-zkt.c /^static int dirflag = 0;$/;" v file:
+dirname dnssec-signer.c /^const char *dirname = NULL;$/;" v
+dist_and_reload dnssec-signer.c /^static int dist_and_reload (const zone_t *zp)$/;" f file:
+dki_add dki.c /^dki_t *dki_add (dki_t **list, dki_t *new)$/;" f
+dki_age dki.c /^int dki_age (const dki_t *dkp, time_t curr)$/;" f
+dki_algo2str dki.c /^char *dki_algo2str (int algo)$/;" f
+dki_allcmp dki.c /^int dki_allcmp (const dki_t *a, const dki_t *b)$/;" f
+dki_alloc dki.c /^static dki_t *dki_alloc ()$/;" f file:
+dki_cmp dki.c /^int dki_cmp (const dki_t *a, const dki_t *b)$/;" f
+dki_destroy dki.c /^dki_t *dki_destroy (dki_t *dkp)$/;" f
+dki_estr dki.c /^static char dki_estr[255+1];$/;" v file:
+dki_exptime dki.c /^time_t dki_exptime (const dki_t *dkp)$/;" f
+dki_find dki.c /^const dki_t *dki_find (const dki_t *list, int ksk, int status, int no)$/;" f
+dki_free dki.c /^void dki_free (dki_t *dkp)$/;" f
+dki_freelist dki.c /^void dki_freelist (dki_t **listp)$/;" f
+dki_gentime dki.c /^time_t dki_gentime (const dki_t *dkp)$/;" f
+dki_geterrstr dki.c /^const char *dki_geterrstr ()$/;" f
+dki_getflag dki.c /^dk_flag_t dki_getflag (const dki_t *dkp, time_t curr)$/;" f
+dki_isactive dki.c /^int dki_isactive (const dki_t *dkp)$/;" f
+dki_isdepreciated dki.c /^int dki_isdepreciated (const dki_t *dkp)$/;" f
+dki_isksk dki.c /^int dki_isksk (const dki_t *dkp)$/;" f
+dki_ispublished dki.c /^int dki_ispublished (const dki_t *dkp)$/;" f
+dki_isrevoked dki.c /^int dki_isrevoked (const dki_t *dkp)$/;" f
+dki_lifetime dki.c /^time_t dki_lifetime (const dki_t *dkp)$/;" f
+dki_lifetimedays dki.c /^ushort dki_lifetimedays (const dki_t *dkp)$/;" f
+dki_namecmp dki.c /^int dki_namecmp (const dki_t *a, const dki_t *b)$/;" f
+dki_new dki.c /^dki_t *dki_new (const char *dir, const char *name, int ksk, int algo, int bitsize, const char *rfile, int lf_days)$/;" f
+dki_prt_comment dki.c /^int dki_prt_comment (const dki_t *dkp, FILE *fp)$/;" f
+dki_prt_dnskey dki.c /^int dki_prt_dnskey (const dki_t *dkp, FILE *fp)$/;" f
+dki_prt_dnskey_raw dki.c /^int dki_prt_dnskey_raw (const dki_t *dkp, FILE *fp)$/;" f
+dki_prt_dnskeyttl dki.c /^int dki_prt_dnskeyttl (const dki_t *dkp, FILE *fp, int ttl)$/;" f
+dki_prt_trustedkey dki.c /^int dki_prt_trustedkey (const dki_t *dkp, FILE *fp)$/;" f
+dki_read dki.c /^dki_t *dki_read (const char *dirname, const char *filename)$/;" f
+dki_readdir dki.c /^int dki_readdir (const char *dir, dki_t **listp, int recursive)$/;" f
+dki_readfile dki.c /^static int dki_readfile (FILE *fp, dki_t *dkp)$/;" f file:
+dki_remove dki.c /^dki_t *dki_remove (dki_t *dkp)$/;" f
+dki_search dki.c /^const dki_t *dki_search (const dki_t *list, int tag, const char *name)$/;" f
+dki_setexptime dki.c /^time_t dki_setexptime (dki_t *dkp, time_t sec)$/;" f
+dki_setflag dki.c /^dk_flag_t dki_setflag (dki_t *dkp, dk_flag_t flag)$/;" f
+dki_setlifetime dki.c /^ushort dki_setlifetime (dki_t *dkp, int days)$/;" f
+dki_setstat dki.c /^static int dki_setstat (dki_t *dkp, int status, int preserve_time)$/;" f file:
+dki_setstatus dki.c /^int dki_setstatus (dki_t *dkp, int status)$/;" f
+dki_setstatus_preservetime dki.c /^int dki_setstatus_preservetime (dki_t *dkp, int status)$/;" f
+dki_status dki.c /^dk_status_t dki_status (const dki_t *dkp)$/;" f
+dki_statusstr dki.c /^const char *dki_statusstr (const dki_t *dkp)$/;" f
+dki_tadd dki.c /^dki_t *dki_tadd (dki_t **tree, dki_t *new)$/;" f
+dki_tagcmp dki.c /^int dki_tagcmp (const dki_t *a, const dki_t *b)$/;" f
+dki_tfree dki.c /^void dki_tfree (dki_t **tree)$/;" f
+dki_time dki.c /^time_t dki_time (const dki_t *dkp)$/;" f
+dki_timecmp dki.c /^int dki_timecmp (const dki_t *a, const dki_t *b)$/;" f
+dki_tsearch dki.c /^const dki_t *dki_tsearch (const dki_t *tree, int tag, const char *name)$/;" f
+dki_unsetflag dki.c /^dk_flag_t dki_unsetflag (dki_t *dkp, dk_flag_t flag)$/;" f
+dki_writeinfo dki.c /^static int dki_writeinfo (const dki_t *dkp, const char *path)$/;" f file:
+domaincmp domaincmp.c /^int domaincmp (const char *a, const char *b)$/;" f
+dosigning dnssec-signer.c /^static int dosigning (zone_t *zonelist, zone_t *zp)$/;" f file:
+dupconfig zconf.c /^zconf_t *dupconfig (const zconf_t *conf)$/;" f
+dyn_update_freeze dnssec-signer.c /^static int dyn_update_freeze (const char *domain, const zconf_t *z, int freeze)$/;" f file:
+dynamic_zone dnssec-signer.c /^static int dynamic_zone = 0; \/* dynamic zone ? *\/$/;" v file:
+error misc.c /^void error (char *fmt, ...)$/;" f
+ex domaincmp.c /^} ex[] = {$/;" v file:
+exptimeflag dnssec-zkt.c /^int exptimeflag = 0;$/;" v
+extern dki.c 59;" d file:
+extern dki.c 61;" d file:
+extern domaincmp.c 42;" d file:
+extern domaincmp.c 44;" d file:
+extern log.c 55;" d file:
+extern log.c 57;" d file:
+extern misc.c 56;" d file:
+extern misc.c 58;" d file:
+extern ncparse.c 44;" d file:
+extern ncparse.c 46;" d file:
+extern rollover.c 57;" d file:
+extern rollover.c 59;" d file:
+extern zconf.c 61;" d file:
+extern zconf.c 63;" d file:
+extern zkt.c 47;" d file:
+extern zkt.c 49;" d file:
+extern zone.c 53;" d file:
+extern zone.c 55;" d file:
+fatal misc.c /^void fatal (char *fmt, ...)$/;" f
+file_age misc.c /^int file_age (const char *fname)$/;" f
+file_mtime misc.c /^time_t file_mtime (const char *fname)$/;" f
+fileexist misc.c /^int fileexist (const char *name)$/;" f
+filesize misc.c /^size_t filesize (const char *name)$/;" f
+force dnssec-signer.c /^static int force = 0;$/;" v file:
+genkey rollover.c /^static dki_t *genkey (dki_t **listp, const char *dir, const char *domain, int ksk, const zconf_t *conf, int status)$/;" f file:
+get_exptime rollover.c /^static time_t get_exptime (dki_t *key, const zconf_t *z)$/;" f file:
+get_parent_phase dnssec-zkt.c /^static int get_parent_phase (const char *file)$/;" f file:
+get_parent_phase rollover.c /^static int get_parent_phase (const char *file)$/;" f file:
+getdefconfname misc.c /^const char *getdefconfname (const char *view)$/;" f
+getnameappendix misc.c /^const char *getnameappendix (const char *progname, const char *basename)$/;" f
+gettok ncparse.c /^static int gettok (FILE *fp, char *val, size_t valsize)$/;" f file:
+goto_labelstart domaincmp.c 47;" d file:
+headerflag dnssec-zkt.c /^int headerflag = 1;$/;" v
+in_strarr misc.c /^int in_strarr (const char *str, char *const arr[], int cnt)$/;" f
+inc_errstr misc.c /^const char *inc_errstr (int err)$/;" f
+inc_serial misc.c /^int inc_serial (const char *fname, int use_unixtime)$/;" f
+inc_soa_serial misc.c /^static int inc_soa_serial (FILE *fp, int use_unixtime)$/;" f file:
+is_directory misc.c /^int is_directory (const char *name)$/;" f
+is_dotfile misc.c /^int is_dotfile (const char *name)$/;" f
+is_exec_ok misc.c /^int is_exec_ok (const char *prog)$/;" f
+is_keyfilename misc.c /^int is_keyfilename (const char *name)$/;" f
+is_parentdirsigned rollover.c /^static int is_parentdirsigned (const zone_t *zonelist, const zone_t *zp)$/;" f file:
+isinlist strlist.c /^int isinlist (const char *str, const char *list)$/;" f
+ksk5011status rollover.c /^int ksk5011status (dki_t **listp, const char *dir, const char *domain, const zconf_t *z)$/;" f
+ksk_roll dnssec-zkt.c /^static void ksk_roll (const char *keyname, int phase, const dki_t *list, const zconf_t *conf)$/;" f file:
+kskdomain dnssec-zkt.c /^static char *kskdomain = "";$/;" v file:
+kskflag dnssec-zkt.c /^int kskflag = 1;$/;" v
+kskrollover rollover.c /^static int kskrollover (dki_t *ksk, zone_t *zonelist, zone_t *zp)$/;" f file:
+kskstatus rollover.c /^int kskstatus (zone_t *zonelist, zone_t *zp)$/;" f
+kw ncparse.c /^} kw[] = {$/;" v file:
+label zconf.c /^ char *label; \/* the name of the paramter *\/$/;" m file:
+labellist dnssec-zkt.c /^char *labellist = NULL;$/;" v
+level log.c /^ lg_lvl_t level;$/;" m file:
+lg_args log.c /^void lg_args (lg_lvl_t level, int argc, char * const argv[])$/;" f
+lg_close log.c /^int lg_close ()$/;" f
+lg_errcnt log.c /^static long lg_errcnt;$/;" v file:
+lg_fileopen log.c /^static FILE *lg_fileopen (const char *path, const char *name)$/;" f file:
+lg_fp log.c /^static FILE *lg_fp;$/;" v file:
+lg_geterrcnt log.c /^long lg_geterrcnt ()$/;" f
+lg_lvl2str log.c /^const char *lg_lvl2str (lg_lvl_t level)$/;" f
+lg_lvl2syslog log.c /^lg_lvl_t lg_lvl2syslog (lg_lvl_t level)$/;" f
+lg_mesg log.c /^void lg_mesg (int priority, char *fmt, ...)$/;" f
+lg_minfilelevel log.c /^static int lg_minfilelevel;$/;" v file:
+lg_minsyslevel log.c /^static int lg_minsyslevel;$/;" v file:
+lg_open log.c /^int lg_open (const char *progname, const char *facility, const char *syslevel, const char *path, const char *file, const char *filelevel)$/;" f
+lg_progname log.c /^static const char *lg_progname;$/;" v file:
+lg_reseterrcnt log.c /^long lg_reseterrcnt ()$/;" f
+lg_seterrcnt log.c /^long lg_seterrcnt (long value)$/;" f
+lg_str2lvl log.c /^lg_lvl_t lg_str2lvl (const char *name)$/;" f
+lg_str2syslog log.c /^int lg_str2syslog (const char *facility)$/;" f
+lg_symtbl_t log.c /^} lg_symtbl_t;$/;" t file:
+lg_syslogging log.c /^static int lg_syslogging;$/;" v file:
+lifetime dnssec-zkt.c /^int lifetime = 0;$/;" v
+lifetimeflag dnssec-zkt.c /^int lifetimeflag = 0;$/;" v
+linkfile misc.c /^int linkfile (const char *fromfile, const char *tofile)$/;" f
+list_dnskey zkt.c /^static void list_dnskey (const dki_t **nodep, const VISIT which, int depth)$/;" f file:
+list_key zkt.c /^static void list_key (const dki_t **nodep, const VISIT which, int depth)$/;" f file:
+list_trustedkey zkt.c /^static void list_trustedkey (const dki_t **nodep, const VISIT which, int depth)$/;" f file:
+ljustflag dnssec-zkt.c /^int ljustflag = 0;$/;" v
+loadconfig zconf.c /^zconf_t *loadconfig (const char *filename, zconf_t *z)$/;" f
+loadconfig_fromstr zconf.c /^zconf_t *loadconfig_fromstr (const char *str, zconf_t *z)$/;" f
+logfile dnssec-signer.c /^const char *logfile = NULL;$/;" v
+logflush misc.c /^void logflush ()$/;" f
+logmesg misc.c /^void logmesg (char *fmt, ...)$/;" f
+long_options dnssec-signer.c /^static struct option long_options[] = {$/;" v file:
+long_options dnssec-zkt.c /^static struct option long_options[] = {$/;" v file:
+lopt_usage dnssec-signer.c 302;" d file:
+lopt_usage dnssec-signer.c 305;" d file:
+lopt_usage dnssec-zkt.c 410;" d file:
+lopt_usage dnssec-zkt.c 413;" d file:
+loptstr dnssec-signer.c 303;" d file:
+loptstr dnssec-signer.c 306;" d file:
+loptstr dnssec-zkt.c 411;" d file:
+loptstr dnssec-zkt.c 414;" d file:
+main dnssec-signer.c /^int main (int argc, char *const argv[])$/;" f
+main dnssec-zkt.c /^int main (int argc, char *argv[])$/;" f
+main domaincmp.c /^main (int argc, char *argv[])$/;" f
+main log.c /^int main (int argc, char *argv[])$/;" f
+main misc.c /^main (int argc, char *argv[])$/;" f
+main ncparse.c /^main (int argc, char *argv[])$/;" f
+main strlist.c /^main (int argc, char *argv[])$/;" f
+main zconf.c /^main (int argc, char *argv[])$/;" f
+main zkt-soaserial.c /^int main (int argc, char *argv[])$/;" f
+name ncparse.c /^ char *name;$/;" m struct:KeyWords file:
+namedconf dnssec-signer.c /^const char *namedconf = NULL;$/;" v
+new_keysetfiles dnssec-signer.c /^static int new_keysetfiles (const char *dir, time_t zone_signing_time)$/;" f file:
+noexec dnssec-signer.c /^static int noexec = 0;$/;" v file:
+origin dnssec-signer.c /^const char *origin = NULL;$/;" v
+parse_namedconf ncparse.c /^int parse_namedconf (const char *filename, char *dir, size_t dirsize, int (*func) ())$/;" f
+parseconfigline zconf.c /^static void parseconfigline (char *buf, unsigned int line, zconf_t *z)$/;" f file:
+parsedir dnssec-signer.c /^static int parsedir (const char *dir, zone_t **zp, const zconf_t *conf)$/;" f file:
+parsedirectory dnssec-zkt.c /^static int parsedirectory (const char *dir, dki_t **listp)$/;" f file:
+parsefile dnssec-zkt.c /^static void parsefile (const char *file, dki_t **listp)$/;" f file:
+parsetag dnssec-zkt.c /^static const char *parsetag (const char *str, int *tagp)$/;" f file:
+parseurl misc.c /^void parseurl (char *url, char **proto, char **host, char **port, char **para)$/;" f
+pathflag dnssec-zkt.c /^int pathflag = 0;$/;" v
+pathname misc.c /^char *pathname (char *path, size_t size, const char *dir, const char *file, const char *ext)$/;" f
+prepstrlist strlist.c /^char *prepstrlist (const char *str, const char *delim)$/;" f
+printconfig zconf.c /^int printconfig (const char *fname, const zconf_t *z)$/;" f
+printconfigline zconf.c /^static void printconfigline (FILE *fp, zconf_para_t *cp)$/;" f file:
+printkeyinfo zkt.c /^static void printkeyinfo (const dki_t *dkp, const char *oldpath)$/;" f file:
+printserial zkt-soaserial.c /^static void printserial (const char *fname, unsigned long serial)$/;" f file:
+printzone ncparse.c /^int printzone (const char *dir, const char *view, const char *zone, const char *file)$/;" f
+progname dnssec-signer.c /^const char *progname;$/;" v
+progname dnssec-zkt.c /^const char *progname;$/;" v
+progname domaincmp.c /^const char *progname;$/;" v
+progname log.c /^const char *progname;$/;" v
+progname misc.c /^const char *progname;$/;" v
+progname ncparse.c /^char *progname;$/;" v
+progname zconf.c /^const char *progname;$/;" v
+progname zkt-soaserial.c /^static const char *progname;$/;" v file:
+read_serial_fromfile zkt-soaserial.c /^static int read_serial_fromfile (const char *fname, unsigned long *serial)$/;" f file:
+recflag dnssec-zkt.c /^static int recflag = RECURSIVE;$/;" v file:
+register_key dnssec-signer.c /^static void register_key (dki_t *list, const zconf_t *z)$/;" f file:
+reload_zone dnssec-signer.c /^static int reload_zone (const char *domain, const zconf_t *z)$/;" f file:
+reloadflag dnssec-signer.c /^static int reloadflag = 0;$/;" v file:
+res domaincmp.c /^ int res;$/;" m file:
+searchitem zkt.c /^static int searchitem;$/;" v file:
+searchkw ncparse.c /^static int searchkw (const char *keyword)$/;" f file:
+searchresult zkt.c /^static const dki_t *searchresult;$/;" v file:
+set_all_varptr zconf.c /^static void set_all_varptr (zconf_t *cp)$/;" f file:
+set_keylifetime zkt.c /^static void set_keylifetime (const dki_t **nodep, const VISIT which, int depth)$/;" f file:
+set_varptr zconf.c /^static int set_varptr (char *entry, void *ptr)$/;" f file:
+setconfigpar zconf.c /^int setconfigpar (zconf_t *config, char *entry, const void *pval)$/;" f
+setglobalflags dnssec-zkt.c /^static void setglobalflags (zconf_t *config)$/;" f file:
+short_options dnssec-signer.c 66;" d file:
+short_options dnssec-signer.c 68;" d file:
+short_options dnssec-zkt.c 89;" d file:
+sign_zone dnssec-signer.c /^static int sign_zone (const char *dir, const char *domain, const char *file, const zconf_t *conf)$/;" f file:
+sopt_usage dnssec-signer.c 300;" d file:
+sopt_usage dnssec-zkt.c 408;" d file:
+splitpath misc.c /^const char *splitpath (char *path, size_t size, const char *filename)$/;" f
+start_timer misc.c /^time_t start_timer ()$/;" f
+stop_timer misc.c /^time_t stop_timer (time_t start)$/;" f
+str log.c /^ const char *str;$/;" m file:
+str_chop misc.c /^char *str_chop (char *str, char c)$/;" f
+str_delspace misc.c /^char *str_delspace (char *s)$/;" f
+str_tolowerdup misc.c /^char *str_tolowerdup (const char *s)$/;" f
+str_untaint misc.c /^char *str_untaint (char *str)$/;" f
+symtbl log.c /^static lg_symtbl_t symtbl[] = {$/;" v file:
+syslog_level log.c /^ int syslog_level;$/;" m file:
+tag_search zkt.c /^static void tag_search (const dki_t **nodep, const VISIT which, int depth)$/;" f file:
+time2isostr misc.c /^char *time2isostr (time_t sec, int precision)$/;" f
+time2str misc.c /^char *time2str (time_t sec, int precision)$/;" f
+timeflag dnssec-zkt.c /^int timeflag = 1;$/;" v
+timeint2str zconf.c /^static const char *timeint2str (ulong val)$/;" f file:
+timestr zkt-soaserial.c /^static char *timestr (time_t sec)$/;" f file:
+timestr2time misc.c /^time_t timestr2time (const char *timestr)$/;" f
+today_serialtime misc.c /^static ulong today_serialtime ()$/;" f file:
+tok ncparse.c /^ int tok;$/;" m struct:KeyWords file:
+tok2str ncparse.c /^static const char *tok2str (int tok)$/;" f file:
+touch misc.c /^int touch (const char *fname, time_t sec)$/;" f
+trustedkeyflag dnssec-zkt.c /^static int trustedkeyflag = 0;$/;" v file:
+type zconf.c /^ ctype_t type; \/* the parameter type *\/$/;" m file:
+unprepstrlist strlist.c /^char *unprepstrlist (char *list, char delimc)$/;" f
+usage dnssec-signer.c /^static void usage (char *mesg, zconf_t *conf)$/;" f file:
+usage dnssec-zkt.c /^static void usage (char *mesg, zconf_t *cp)$/;" f file:
+usage zkt-soaserial.c /^static void usage (const char *msg)$/;" f file:
+var zconf.c /^ void *var; \/* pointer to the parameter variable *\/$/;" m file:
+verbmesg misc.c /^void verbmesg (int verblvl, const zconf_t *conf, char *fmt, ...)$/;" f
+verbose dnssec-signer.c /^static int verbose = 0;$/;" v file:
+view dnssec-zkt.c /^static const char *view = "";$/;" v file:
+viewname dnssec-signer.c /^const char *viewname = NULL;$/;" v
+writekeyfile dnssec-signer.c /^static int writekeyfile (const char *fname, const dki_t *list, int key_ttl)$/;" f file:
+zconf_para_t zconf.c /^} zconf_para_t;$/;" t file:
+zkt_list_dnskeys zkt.c /^void zkt_list_dnskeys (const dki_t *data)$/;" f
+zkt_list_keys zkt.c /^void zkt_list_keys (const dki_t *data)$/;" f
+zkt_list_trustedkeys zkt.c /^void zkt_list_trustedkeys (const dki_t *data)$/;" f
+zkt_search zkt.c /^const dki_t *zkt_search (const dki_t *data, int searchtag, const char *keyname)$/;" f
+zkt_setkeylifetime zkt.c /^void zkt_setkeylifetime (dki_t *data)$/;" f
+zone_add zone.c /^zone_t *zone_add (zone_t **list, zone_t *new)$/;" f
+zone_alloc zone.c /^static zone_t *zone_alloc ()$/;" f file:
+zone_cmp zone.c /^static int zone_cmp (const zone_t *a, const zone_t *b)$/;" f file:
+zone_estr zone.c /^static char zone_estr[255+1];$/;" v file:
+zone_free zone.c /^void zone_free (zone_t *zp)$/;" f
+zone_freelist zone.c /^void zone_freelist (zone_t **listp)$/;" f
+zone_geterrstr zone.c /^const char *zone_geterrstr ()$/;" f
+zone_new zone.c /^zone_t *zone_new (zone_t **zp, const char *zone, const char *dir, const char *file, const char *signed_ext, const zconf_t *cp)$/;" f
+zone_print zone.c /^int zone_print (const char *mesg, const zone_t *z)$/;" f
+zone_readdir zone.c /^int zone_readdir (const char *dir, const char *zone, const char *zfile, zone_t **listp, const zconf_t *conf, int dyn_zone)$/;" f
+zone_search zone.c /^const zone_t *zone_search (const zone_t *list, const char *zone)$/;" f
+zonelist dnssec-signer.c /^static zone_t *zonelist = NULL; \/* must be static global because add2zonelist use it *\/$/;" v file:
+zskflag dnssec-zkt.c /^int zskflag = 1;$/;" v
+zskstatus rollover.c /^int zskstatus (dki_t **listp, const char *dir, const char *domain, const zconf_t *z)$/;" f
diff --git a/contrib/zkt/zconf.c b/contrib/zkt/zconf.c
new file mode 100644
index 0000000..1dee484
--- /dev/null
+++ b/contrib/zkt/zconf.c
@@ -0,0 +1,775 @@
+/****************************************************************
+**
+** @(#) zconf.c -- configuration file parser for dnssec.conf
+**
+** Most of the code is from the SixXS Heartbeat Client
+** written by Jeroen Massar <jeroen@sixxs.net>
+**
+** New config types and some slightly code changes
+** by Holger Zuleger
+**
+** Copyright (c) Aug 2005, Jeroen Massar, Holger Zuleger.
+** All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Jeroen Masar or Holger Zuleger nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************/
+# include <sys/types.h>
+# include <stdio.h>
+# include <errno.h>
+# include <unistd.h>
+# include <stdlib.h>
+# include <stdarg.h>
+# include <string.h>
+# include <strings.h>
+# include <assert.h>
+# include <ctype.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+# include "config_zkt.h"
+# include "debug.h"
+# include "misc.h"
+#define extern
+# include "zconf.h"
+#undef extern
+# include "dki.h"
+
+# define ISTRUE(val) (strcasecmp (val, "yes") == 0 || \
+ strcasecmp (val, "true") == 0 )
+# define ISCOMMENT(cp) (*(cp) == '#' || *(cp) == ';' || \
+ (*(cp) == '/' && *((cp)+1) == '/') )
+# define ISDELIM(c) ( isspace (c) || (c) == ':' || (c) == '=' )
+
+
+typedef enum {
+ CONF_END = 0,
+ CONF_STRING,
+ CONF_INT,
+ CONF_TIMEINT,
+ CONF_BOOL,
+ CONF_ALGO,
+ CONF_SERIAL,
+ CONF_FACILITY,
+ CONF_LEVEL,
+ CONF_COMMENT,
+} ctype_t;
+
+/*****************************************************************
+** private (static) variables
+*****************************************************************/
+static zconf_t def = {
+ ZONEDIR, RECURSIVE,
+ PRINTTIME, PRINTAGE, LJUST,
+ SIG_VALIDITY, MAX_TTL, KEY_TTL, PROPTIME, Incremental,
+ RESIGN_INT,
+ KSK_LIFETIME, KSK_ALGO, KSK_BITS, KSK_RANDOM,
+ ZSK_LIFETIME, ZSK_ALGO, ZSK_BITS, ZSK_RANDOM,
+ NULL, /* viewname cmdline paramter */
+ LOGFILE, LOGLEVEL, SYSLOGFACILITY, SYSLOGLEVEL, VERBOSELOG, 0,
+ DNSKEYFILE, ZONEFILE, KEYSETDIR,
+ LOOKASIDEDOMAIN,
+ SIG_RANDOM, SIG_PSEUDO, SIG_GENDS, SIG_PARAM,
+ DIST_CMD /* deafults to NULL which means to run "rndc reload" */
+};
+
+typedef struct {
+ char *label; /* the name of the paramter */
+ int cmdline; /* is this a command line parameter ? */
+ ctype_t type; /* the parameter type */
+ void *var; /* pointer to the parameter variable */
+} zconf_para_t;
+
+static zconf_para_t confpara[] = {
+ { "", 0, CONF_COMMENT, ""},
+ { "", 0, CONF_COMMENT, "\t@(#) dnssec.conf " ZKT_VERSION },
+ { "", 0, CONF_COMMENT, ""},
+ { "", 0, CONF_COMMENT, NULL },
+
+ { "", 0, CONF_COMMENT, "dnssec-zkt options" },
+ { "Zonedir", 0, CONF_STRING, &def.zonedir },
+ { "Recursive", 0, CONF_BOOL, &def.recursive },
+ { "PrintTime", 0, CONF_BOOL, &def.printtime },
+ { "PrintAge", 0, CONF_BOOL, &def.printage },
+ { "LeftJustify", 0, CONF_BOOL, &def.ljust },
+
+ { "", 0, CONF_COMMENT, NULL },
+ { "", 0, CONF_COMMENT, "zone specific values" },
+ { "ResignInterval", 0, CONF_TIMEINT, &def.resign },
+ { "Sigvalidity", 0, CONF_TIMEINT, &def.sigvalidity },
+ { "Max_TTL", 0, CONF_TIMEINT, &def.max_ttl },
+ { "Propagation", 0, CONF_TIMEINT, &def.proptime },
+ { "KEY_TTL", 0, CONF_TIMEINT, &def.key_ttl },
+#if defined (DEF_TTL)
+ { "def_ttl", 0, CONF_TIMEINT, &def.def_ttl },
+#endif
+ { "Serialformat", 0, CONF_SERIAL, &def.serialform },
+
+ { "", 0, CONF_COMMENT, NULL },
+ { "", 0, CONF_COMMENT, "signing key parameters"},
+ { "KSK_lifetime", 0, CONF_TIMEINT, &def.k_life },
+ { "KSK_algo", 0, CONF_ALGO, &def.k_algo },
+ { "KSK_bits", 0, CONF_INT, &def.k_bits },
+ { "KSK_randfile", 0, CONF_STRING, &def.k_random },
+ { "ZSK_lifetime", 0, CONF_TIMEINT, &def.z_life },
+ { "ZSK_algo", 0, CONF_ALGO, &def.z_algo },
+ { "ZSK_bits", 0, CONF_INT, &def.z_bits },
+ { "ZSK_randfile", 0, CONF_STRING, &def.z_random },
+
+ { "", 0, CONF_COMMENT, NULL },
+ { "", 0, CONF_COMMENT, "dnssec-signer options"},
+ { "--view", 1, CONF_STRING, &def.view },
+ { "LogFile", 0, CONF_STRING, &def.logfile },
+ { "LogLevel", 0, CONF_LEVEL, &def.loglevel },
+ { "SyslogFacility", 0, CONF_FACILITY, &def.syslogfacility },
+ { "SyslogLevel", 0, CONF_LEVEL, &def.sysloglevel },
+ { "VerboseLog", 0, CONF_INT, &def.verboselog },
+ { "-v", 1, CONF_INT, &def.verbosity },
+ { "Keyfile", 0, CONF_STRING, &def.keyfile },
+ { "Zonefile", 0, CONF_STRING, &def.zonefile },
+ { "KeySetDir", 0, CONF_STRING, &def.keysetdir },
+ { "DLV_Domain", 0, CONF_STRING, &def.lookaside },
+ { "Sig_Randfile", 0, CONF_STRING, &def.sig_random },
+ { "Sig_Pseudorand", 0, CONF_BOOL, &def.sig_pseudo },
+ { "Sig_GenerateDS", 1, CONF_BOOL, &def.sig_gends },
+ { "Sig_Parameter", 0, CONF_STRING, &def.sig_param },
+ { "Distribute_Cmd", 0, CONF_STRING, &def.dist_cmd },
+
+ { NULL, 0, CONF_END, NULL},
+};
+
+/*****************************************************************
+** private (static) function deklaration and definition
+*****************************************************************/
+static const char *bool2str (int val)
+{
+ return val ? "True" : "False";
+}
+
+static const char *timeint2str (ulong val)
+{
+ static char str[20+1];
+
+ if ( val == 0 )
+ snprintf (str, sizeof (str), "%lu", val / YEARSEC);
+ else if ( val % YEARSEC == 0 )
+ snprintf (str, sizeof (str), "%luy", val / YEARSEC);
+ else if ( val % WEEKSEC == 0 )
+ snprintf (str, sizeof (str), "%luw", val / WEEKSEC);
+ else if ( val % DAYSEC == 0 )
+ snprintf (str, sizeof (str), "%lud", val / DAYSEC);
+ else if ( val % HOURSEC == 0 )
+ snprintf (str, sizeof (str), "%luh", val / HOURSEC);
+ else if ( val % MINSEC == 0 )
+ snprintf (str, sizeof (str), "%lum", val / MINSEC);
+ else
+ snprintf (str, sizeof (str), "%lus", val);
+
+ return str;
+}
+
+static int set_varptr (char *entry, void *ptr)
+{
+ zconf_para_t *c;
+
+ for ( c = confpara; c->label; c++ )
+ if ( strcasecmp (entry, c->label) == 0 )
+ {
+ c->var = ptr;
+ return 1;
+ }
+ return 0;
+}
+
+static void set_all_varptr (zconf_t *cp)
+{
+ set_varptr ("zonedir", &cp->zonedir);
+ set_varptr ("recursive", &cp->recursive);
+ set_varptr ("printage", &cp->printage);
+ set_varptr ("printtime", &cp->printtime);
+ set_varptr ("leftjustify", &cp->ljust);
+
+ set_varptr ("resigninterval", &cp->resign);
+ set_varptr ("sigvalidity", &cp->sigvalidity);
+ set_varptr ("max_ttl", &cp->max_ttl);
+ set_varptr ("key_ttl", &cp->key_ttl);
+ set_varptr ("propagation", &cp->proptime);
+#if defined (DEF_TTL)
+ set_varptr ("def_ttl", &cp->def_ttl);
+#endif
+ set_varptr ("serialformat", &cp->serialform);
+
+ set_varptr ("ksk_lifetime", &cp->k_life);
+ set_varptr ("ksk_algo", &cp->k_algo);
+ set_varptr ("ksk_bits", &cp->k_bits);
+ set_varptr ("ksk_randfile", &cp->k_random);
+
+ set_varptr ("zsk_lifetime", &cp->z_life);
+ set_varptr ("zsk_algo", &cp->z_algo);
+ set_varptr ("zsk_bits", &cp->z_bits);
+ set_varptr ("zsk_randfile", &cp->z_random);
+
+ set_varptr ("--view", &cp->view);
+ set_varptr ("logfile", &cp->logfile);
+ set_varptr ("loglevel", &cp->loglevel);
+ set_varptr ("syslogfacility", &cp->syslogfacility);
+ set_varptr ("sysloglevel", &cp->sysloglevel);
+ set_varptr ("verboselog", &cp->verboselog);
+ set_varptr ("-v", &cp->verbosity);
+ set_varptr ("keyfile", &cp->keyfile);
+ set_varptr ("zonefile", &cp->zonefile);
+ set_varptr ("keysetdir", &cp->keysetdir);
+ set_varptr ("dlv_domain", &cp->lookaside);
+ set_varptr ("sig_randfile", &cp->sig_random);
+ set_varptr ("sig_pseudorand", &cp->sig_pseudo);
+ set_varptr ("sig_generateds", &cp->sig_gends);
+ set_varptr ("sig_parameter", &cp->sig_param);
+ set_varptr ("distribute_cmd", &cp->dist_cmd);
+}
+
+static void parseconfigline (char *buf, unsigned int line, zconf_t *z)
+{
+ char *end, *val, *p;
+ char *tag;
+ unsigned int len, found;
+ zconf_para_t *c;
+
+ p = &buf[strlen(buf)-1]; /* Chop off white space at eol */
+ while ( p >= buf && isspace (*p) )
+ *p-- = '\0';
+
+ for (p = buf; isspace (*p); p++ ) /* Ignore leading white space */
+ ;
+
+ /* Ignore comments and emtpy lines */
+ if ( *p == '\0' || ISCOMMENT (p) )
+ return;
+
+ tag = p;
+ /* Get the end of the first argument */
+ end = &buf[strlen(buf)-1];
+ while ( p < end && !ISDELIM (*p) ) /* Skip until delim */
+ p++;
+ *p++ = '\0'; /* Terminate this argument */
+ dbg_val1 ("Parsing \"%s\"\n", tag);
+
+
+ while ( p < end && ISDELIM (*p) ) /* Skip delim chars */
+ p++;
+
+ val = p; /* Start of the value */
+ dbg_val1 ("\tgot value \"%s\"\n", val);
+
+ /* If starting with quote, skip until next quote */
+ if ( *p == '"' || *p == '\'' )
+ {
+ p++; /* Find next quote */
+ while ( p <= end && *p && *p != *val )
+ p++;
+ *p = '\0';
+ val++; /* Skip the first quote */
+ }
+ else /* Otherwise check if there is any comment char at the end */
+ {
+ while ( p < end && *p && !ISCOMMENT(p) )
+ p++;
+ if ( ISCOMMENT (p) )
+ {
+ do /* Chop off white space before comment */
+ *p-- = '\0';
+ while ( p >= val && isspace (*p) );
+ }
+ }
+
+ /* Otherwise it is already terminated above */
+
+ found = 0;
+ c = confpara;
+ while ( !found && c->type != CONF_END )
+ {
+ len = strlen (c->label);
+ if ( strcasecmp (tag, c->label) == 0 )
+ {
+ char **str;
+ char quantity;
+ int ival;
+
+ found = 1;
+ switch ( c->type )
+ {
+ case CONF_LEVEL:
+ case CONF_FACILITY:
+ case CONF_STRING:
+ str = (char **)c->var;
+ *str = strdup (val);
+ str_untaint (*str); /* remove "bad" characters */
+ break;
+ case CONF_INT:
+ sscanf (val, "%d", (int *)c->var);
+ break;
+ case CONF_TIMEINT:
+ quantity = 'd';
+ sscanf (val, "%d%c", &ival, &quantity);
+ if ( quantity == 'm' )
+ ival *= MINSEC;
+ else if ( quantity == 'h' )
+ ival *= HOURSEC;
+ else if ( quantity == 'd' )
+ ival *= DAYSEC;
+ else if ( quantity == 'w' )
+ ival *= WEEKSEC;
+ else if ( quantity == 'y' )
+ ival *= YEARSEC;
+ (*(int *)c->var) = ival;
+ break;
+ case CONF_ALGO:
+ if ( strcasecmp (val, "rsa") == 0 || strcasecmp (val, "rsamd5") == 0 )
+ *((int *)c->var) = DK_ALGO_RSA;
+ else if ( strcasecmp (val, "dsa") == 0 )
+ *((int *)c->var) = DK_ALGO_DSA;
+ else if ( strcasecmp (val, "rsasha1") == 0 )
+ *((int *)c->var) = DK_ALGO_RSASHA1;
+ else
+ error ("Illegal algorithm \"%s\" "
+ "in line %d.\n" , val, line);
+ break;
+ case CONF_SERIAL:
+ if ( strcasecmp (val, "unixtime") == 0 )
+ *((serial_form_t *)c->var) = Unixtime;
+ else if ( strcasecmp (val, "incremental") == 0 )
+ *((serial_form_t *)c->var) = Incremental;
+ else
+ error ("Illegal serial no format \"%s\" "
+ "in line %d.\n" , val, line);
+ break;
+ case CONF_BOOL:
+ *((int *)c->var) = ISTRUE (val);
+ break;
+ default:
+ fatal ("Illegal configuration type in line %d.\n", line);
+ }
+ }
+ c++;
+ }
+ if ( !found )
+ error ("Unknown configuration statement: %s \"%s\"\n", tag, val);
+ return;
+}
+
+static void printconfigline (FILE *fp, zconf_para_t *cp)
+{
+ int i;
+
+ assert (fp != NULL);
+ assert (cp != NULL);
+
+ switch ( cp->type )
+ {
+ case CONF_COMMENT:
+ if ( cp->var )
+ fprintf (fp, "# %s\n", (char *)cp->var);
+ else
+ fprintf (fp, "\n");
+ break;
+ case CONF_LEVEL:
+ case CONF_FACILITY:
+ if ( *(char **)cp->var != NULL )
+ {
+ if ( **(char **)cp->var != '\0' )
+ {
+ char *p;
+
+ fprintf (fp, "%s:\t", cp->label);
+ for ( p = *(char **)cp->var; *p; p++ )
+ putc (toupper (*p), fp);
+ fprintf (fp, "\n");
+ }
+ else
+ fprintf (fp, "%s:\tNONE", cp->label);
+ }
+ break;
+ case CONF_STRING:
+ if ( *(char **)cp->var )
+ fprintf (fp, "%s:\t\"%s\"\n", cp->label, *(char **)cp->var);
+ break;
+ case CONF_BOOL:
+ fprintf (fp, "%s:\t%s\n", cp->label, bool2str ( *(int*)cp->var ));
+ break;
+ case CONF_TIMEINT:
+ i = *(ulong*)cp->var;
+ fprintf (fp, "%s:\t%s", cp->label, timeint2str (i));
+ if ( i )
+ fprintf (fp, "\t# (%d seconds)", i);
+ putc ('\n', fp);
+ break;
+ case CONF_ALGO:
+ i = *(int*)cp->var;
+ fprintf (fp, "%s:\t%s", cp->label, dki_algo2str (i));
+ fprintf (fp, "\t# (Algorithm ID %d)\n", i);
+ break;
+ case CONF_SERIAL:
+ fprintf (fp, "%s:\t", cp->label);
+ if ( *(serial_form_t*)cp->var == Unixtime )
+ fprintf (fp, "unixtime\n");
+ else
+ fprintf (fp, "incremental\n");
+ break;
+ case CONF_INT:
+ fprintf (fp, "%s:\t%d\n", cp->label, *(int *)cp->var);
+ break;
+ case CONF_END:
+ /* NOTREACHED */
+ break;
+ }
+}
+
+/*****************************************************************
+** public function definition
+*****************************************************************/
+
+/*****************************************************************
+** loadconfig (file, conf)
+** Loads a config file into the "conf" structure pointed to by "z".
+** If "z" is NULL then a new conf struct will be dynamically
+** allocated.
+** If no filename is given the conf struct will be initialized
+** by the builtin default config
+*****************************************************************/
+zconf_t *loadconfig (const char *filename, zconf_t *z)
+{
+ FILE *fp;
+ char buf[1023+1];
+ unsigned int line;
+
+ if ( z == NULL ) /* allocate new memory for zconf_t */
+ {
+ if ( (z = calloc (1, sizeof (zconf_t))) == NULL )
+ return NULL;
+
+ if ( filename && *filename )
+ memcpy (z, &def, sizeof (*z)); /* init new struct with defaults */
+ }
+
+ if ( filename == NULL || *filename == '\0' ) /* no file name given... */
+ {
+ dbg_val0("loadconfig (NULL)\n");
+ memcpy (z, &def, sizeof (*z)); /* ..then init with defaults */
+ return z;
+ }
+
+ dbg_val1 ("loadconfig (%s)\n", filename);
+ set_all_varptr (z);
+
+ if ( (fp = fopen(filename, "r")) == NULL )
+ fatal ("Could not open config file \"%s\"\n", filename);
+
+ line = 0;
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ line++;
+
+ parseconfigline (buf, line, z);
+ }
+ fclose(fp);
+ return z;
+}
+
+# define STRCONFIG_DELIMITER ";\r\n"
+zconf_t *loadconfig_fromstr (const char *str, zconf_t *z)
+{
+ char *buf;
+ char *tok, *toksave;
+ unsigned int line;
+
+ if ( z == NULL )
+ {
+ if ( (z = calloc (1, sizeof (zconf_t))) == NULL )
+ return NULL;
+ memcpy (z, &def, sizeof (*z)); /* init with defaults */
+ }
+
+ if ( str == NULL || *str == '\0' )
+ {
+ dbg_val0("loadconfig_fromstr (NULL)\n");
+ memcpy (z, &def, sizeof (*z)); /* init with defaults */
+ return z;
+ }
+
+ dbg_val1 ("loadconfig_fromstr (\"%s\")\n", str);
+ set_all_varptr (z);
+
+ /* str is const, so we have to copy it into a new buffer */
+ if ( (buf = strdup (str)) == NULL )
+ fatal ("loadconfig_fromstr: Out of memory");
+
+ line = 0;
+ tok = strtok_r (buf, STRCONFIG_DELIMITER, &toksave);
+ while ( tok )
+ {
+ line++;
+ parseconfigline (tok, line, z);
+ tok = strtok_r (NULL, STRCONFIG_DELIMITER, &toksave);
+ }
+ free (buf);
+ return z;
+}
+
+/*****************************************************************
+** dupconfig (config)
+** duplicate config struct and return a ptr to the new struct
+*****************************************************************/
+zconf_t *dupconfig (const zconf_t *conf)
+{
+ zconf_t *z;
+
+ assert (conf != NULL);
+
+ if ( (z = calloc (1, sizeof (zconf_t))) == NULL )
+ return NULL;
+
+ memcpy (z, conf, sizeof (*conf));
+
+ return z;
+}
+
+/*****************************************************************
+** setconfigpar (entry, pval)
+*****************************************************************/
+int setconfigpar (zconf_t *config, char *entry, const void *pval)
+{
+ char *str;
+ zconf_para_t *c;
+
+ set_all_varptr (config);
+
+ for ( c = confpara; c->type != CONF_END; c++ )
+ if ( strcasecmp (entry, c->label) == 0 )
+ {
+ switch ( c->type )
+ {
+ case CONF_LEVEL:
+ case CONF_FACILITY:
+ case CONF_STRING:
+ if ( pval )
+ {
+ str = strdup ((char *)pval);
+ str_untaint (str); /* remove "bad" characters */
+ }
+ else
+ str = NULL;
+ *((char **)c->var) = str;
+ break;
+ case CONF_BOOL:
+ /* fall through */
+ case CONF_ALGO:
+ /* fall through */
+ case CONF_TIMEINT:
+ /* fall through */
+ case CONF_INT:
+ *((int *)c->var) = *((int *)pval);
+ break;
+ case CONF_SERIAL:
+ *((serial_form_t *)c->var) = *((serial_form_t *)pval);
+ break;
+ case CONF_COMMENT:
+ case CONF_END:
+ /* NOTREACHED */
+ break;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************
+** printconfig (fname, config)
+*****************************************************************/
+int printconfig (const char *fname, const zconf_t *z)
+{
+ zconf_para_t *cp;
+ FILE *fp;
+
+ if ( z == NULL )
+ return 0;
+
+ fp = stdout;
+ if ( fname && *fname )
+ {
+ if ( strcmp (fname, "stdout") == 0 )
+ fp = stdout;
+ else if ( strcmp (fname, "stderr") == 0 )
+ fp = stderr;
+ else if ( (fp = fopen(fname, "w")) == NULL )
+ {
+ error ("Could not open config file \"%s\" for writing\n", fname);
+ return -1;
+ }
+ }
+
+ set_all_varptr ((zconf_t *)z);
+
+ for ( cp = confpara; cp->type != CONF_END; cp++ ) /* loop through all parameter */
+ if ( !cp->cmdline ) /* if this is not a command line parameter ? */
+ printconfigline (fp, cp); /* print it out */
+
+ if ( fp && fp != stdout && fp != stderr )
+ fclose (fp);
+
+ return 1;
+}
+
+#if 0
+/*****************************************************************
+** printconfigdiff (fname, conf_a, conf_b)
+*****************************************************************/
+int printconfigdiff (const char *fname, const zconf_t *ref, const zconf_t *z)
+{
+ zconf_para_t *cp;
+ FILE *fp;
+
+ if ( ref == NULL || z == NULL )
+ return 0;
+
+ fp = NULL;
+ if ( fname && *fname )
+ {
+ if ( strcmp (fname, "stdout") == 0 )
+ fp = stdout;
+ else if ( strcmp (fname, "stderr") == 0 )
+ fp = stderr;
+ else if ( (fp = fopen(fname, "w")) == NULL )
+ {
+ error ("Could not open config file \"%s\" for writing\n", fname);
+ return -1;
+ }
+ }
+
+ set_all_varptr ((zconf_t *)z);
+
+ for ( cp = confpara; cp->type != CONF_END; cp++ ) /* loop through all parameter */
+ {
+ if ( cp->cmdline )
+ continue;
+
+
+ printconfigline (fp, cp); /* print it out */
+ }
+
+ if ( fp && fp != stdout && fp != stderr )
+ fclose (fp);
+
+ return 1;
+}
+#endif
+
+/*****************************************************************
+** checkconfig (config)
+*****************************************************************/
+int checkconfig (const zconf_t *z)
+{
+ if ( z == NULL )
+ return 1;
+
+ if ( z->sigvalidity < (1 * DAYSEC) || z->sigvalidity > (12 * WEEKSEC) )
+ {
+ fprintf (stderr, "Signature should be valid for at least 1 day and no longer than 3 month (12 weeks)\n");
+ fprintf (stderr, "The current value is %s\n", timeint2str (z->sigvalidity));
+ }
+
+ if ( z->resign > (z->sigvalidity*5/6) - (z->max_ttl + z->proptime) )
+ {
+ fprintf (stderr, "Re-signing interval (%s) should be less than ", timeint2str (z->resign));
+ fprintf (stderr, "5/6 of sigvalidity\n");
+ }
+ if ( z->resign < (z->max_ttl + z->proptime) )
+ {
+ fprintf (stderr, "Re-signing interval (%s) should be ", timeint2str (z->resign));
+ fprintf (stderr, "greater than max_ttl (%d) plus ", z->max_ttl);
+ fprintf (stderr, "propagation time (%d)\n", z->proptime);
+ }
+
+ if ( z->max_ttl >= z->sigvalidity )
+ fprintf (stderr, "Max TTL (%d) should be less than signatur validity (%d)\n",
+ z->max_ttl, z->sigvalidity);
+
+ if ( z->z_life > (12 * WEEKSEC) * (z->z_bits / 512.) )
+ {
+ fprintf (stderr, "Lifetime of zone signing key (%s) ", timeint2str (z->z_life));
+ fprintf (stderr, "seems a little bit high ");
+ fprintf (stderr, "(In respect of key size (%d))\n", z->z_bits);
+ }
+
+ if ( z->k_life > 0 && z->k_life <= z->z_life )
+ {
+ fprintf (stderr, "Lifetime of key signing key (%s) ", timeint2str (z->k_life));
+ fprintf (stderr, "should be greater than lifetime of zsk\n");
+ }
+ if ( z->k_life > 0 && z->k_life > (26 * WEEKSEC) * (z->k_bits / 512.) )
+ {
+ fprintf (stderr, "Lifetime of key signing key (%s) ", timeint2str (z->k_life));
+ fprintf (stderr, "seems a little bit high ");
+ fprintf (stderr, "(In respect of key size (%d))\n", z->k_bits);
+ }
+
+ return 1;
+}
+
+#ifdef CONF_TEST
+const char *progname;
+static zconf_t *config;
+
+main (int argc, char *argv[])
+{
+ char *optstr;
+ int val;
+
+ progname = *argv;
+
+ config = loadconfig ("", (zconf_t *) NULL); /* load built in defaults */
+
+ while ( --argc >= 1 )
+ {
+ optstr = *++argv;
+ config = loadconfig_fromstr (optstr, config);
+ }
+
+ val = 1;
+ setconfigpar (config, "-v", &val);
+ val = 2;
+ setconfigpar (config, "verboselog", &val);
+ val = 1;
+ setconfigpar (config, "recursive", &val);
+ val = 1200;
+ setconfigpar (config, "propagation", &val);
+
+ printconfig ("stdout", config);
+}
+#endif
diff --git a/contrib/zkt/zconf.h b/contrib/zkt/zconf.h
new file mode 100644
index 0000000..de8b2ef
--- /dev/null
+++ b/contrib/zkt/zconf.h
@@ -0,0 +1,173 @@
+/*****************************************************************
+**
+** @(#) zconf.h
+**
+** Copyright (c) Jan 2005, Jeroen Masar, Holger Zuleger.
+** All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Jeroen Masar and Holger Zuleger nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+#ifndef ZCONF_H
+# define ZCONF_H
+
+
+# define MINSEC 60
+# define HOURSEC (MINSEC * 60)
+# define DAYSEC (HOURSEC * 24)
+# define WEEKSEC (DAYSEC * 7)
+# define YEARSEC (DAYSEC * 365)
+# define DAY (1)
+# define WEEK (DAY * 7)
+# define MONTH (DAY * 30)
+# define YEAR (DAY * 365)
+
+# define SIG_VALID_DAYS (10) /* or 3 Weeks ? */
+# define SIG_VALIDITY (SIG_VALID_DAYS * DAYSEC)
+# define MAX_TTL ( 8 * HOURSEC) /* default value of maximum ttl time */
+# define KEY_TTL ( 4 * HOURSEC) /* default value of KEY TTL */
+# define PROPTIME ( 5 * MINSEC) /* expected slave propagation time */
+ /* should be small if notify is used */
+#if defined (DEF_TTL)
+# define DEF_TTL (MAX_TTL/2) /* currently not used */
+#endif
+
+# define RESIGN_INT ((SIG_VALID_DAYS - (SIG_VALID_DAYS / 3)) * DAYSEC)
+# define KSK_LIFETIME (1 * YEARSEC)
+#if 0
+# define ZSK_LIFETIME ((SIG_VALID_DAYS * 3) * DAYSEC) /* set to three times the sig validity */
+#else
+# define ZSK_LIFETIME ((MONTH * 3) * DAYSEC) /* set fixed to 3 month */
+#endif
+
+# define KSK_ALGO (DK_ALGO_RSASHA1)
+# define KSK_BITS (1300)
+# define KSK_RANDOM "/dev/urandom" /* was NULL before v0.94 */
+# define ZSK_ALGO (DK_ALGO_RSASHA1)
+# define ZSK_BITS (512)
+# define ZSK_RANDOM "/dev/urandom"
+
+# define ZONEDIR "."
+# define RECURSIVE 0
+# define PRINTTIME 1
+# define PRINTAGE 0
+# define LJUST 0
+# define KEYSETDIR NULL /* keysets */
+# define LOGFILE ""
+# define LOGLEVEL "error"
+# define SYSLOGFACILITY "none"
+# define SYSLOGLEVEL "notice"
+# define VERBOSELOG 0
+# define ZONEFILE "zone.db"
+# define DNSKEYFILE "dnskey.db"
+# define LOOKASIDEDOMAIN "" /* "dlv.trusted-keys.de" */
+# define SIG_RANDOM NULL /* "/dev/urandom" */
+# define SIG_PSEUDO 1
+# define SIG_GENDS 1
+# define SIG_PARAM ""
+# define DIST_CMD NULL /* default is to run "rndc reload" */
+
+#ifndef CONFIG_PATH
+# define CONFIG_PATH "/var/named/"
+#endif
+# define CONFIG_FILE CONFIG_PATH "dnssec.conf"
+# define LOCALCONF_FILE "dnssec.conf"
+
+/* external command execution path (should be set via config.h) */
+#ifndef BIND_UTIL_PATH
+# define BIND_UTIL_PATH "/usr/local/sbin/" /* beware of trailing '/' */
+#endif
+# define SIGNCMD BIND_UTIL_PATH "dnssec-signzone"
+# define KEYGENCMD BIND_UTIL_PATH "dnssec-keygen"
+# define RELOADCMD BIND_UTIL_PATH "rndc"
+
+typedef enum {
+ Unixtime = 1,
+ Incremental
+} serial_form_t;
+
+typedef enum {
+ none = 0,
+ user,
+ local0, local1, local2, local3, local4, local5, local6, local7
+} syslog_facility_t;
+
+typedef struct zconf {
+ char *zonedir;
+ int recursive;
+ int printtime;
+ int printage;
+ int ljust;
+ int sigvalidity; /* should be less than expire time */
+ int max_ttl; /* should be set to the maximum used ttl in the zone */
+ int key_ttl;
+ int proptime; /* expected time offset for zone propagation */
+#if defined (DEF_TTL)
+ int def_ttl; /* default ttl set in soa record */
+#endif
+ serial_form_t serialform; /* format of serial no */
+ int resign; /* resign interval */
+
+ int k_life;
+ int k_algo;
+ int k_bits;
+ char *k_random;
+ int z_life;
+ int z_algo;
+ int z_bits;
+ char *z_random;
+
+ char *view;
+ // char *errlog;
+ char *logfile;
+ char *loglevel;
+ char *syslogfacility;
+ char *sysloglevel;
+ int verboselog;
+ int verbosity;
+ char *keyfile;
+ char *zonefile;
+ char *keysetdir;
+ char *lookaside;
+ char *sig_random;
+ int sig_pseudo;
+ int sig_gends;
+ char *sig_param;
+ char *dist_cmd; /* cmd to run instead of "rndc reload" */
+} zconf_t;
+
+extern zconf_t *loadconfig (const char *filename, zconf_t *z);
+extern zconf_t *loadconfig_fromstr (const char *str, zconf_t *z);
+extern zconf_t *dupconfig (const zconf_t *conf);
+extern int setconfigpar (zconf_t *conf, char *entry, const void *pval);
+extern int printconfig (const char *fname, const zconf_t *cp);
+extern int checkconfig (const zconf_t *z);
+
+#endif
diff --git a/contrib/zkt/zkt-soaserial.c b/contrib/zkt/zkt-soaserial.c
new file mode 100644
index 0000000..ff107d9
--- /dev/null
+++ b/contrib/zkt/zkt-soaserial.c
@@ -0,0 +1,222 @@
+/*****************************************************************
+**
+** @(#) zkt-soaserial.c (c) Oct 2007 Holger Zuleger hznet.de
+**
+** A small utility to print out the (unixtime) soa serial
+** number in a human readable form
+**
+** Copyright (c) Oct 2007, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+# include <stdio.h>
+# include <string.h>
+# include <sys/types.h>
+# include <time.h>
+# include <utime.h>
+# include <assert.h>
+# include <stdlib.h>
+# include <ctype.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+
+static const char *progname;
+
+static char *timestr (time_t sec);
+static int read_serial_fromfile (const char *fname, unsigned long *serial);
+static void printserial (const char *fname, unsigned long serial);
+static void usage (const char *msg);
+
+/*****************************************************************
+** timestr (sec)
+*****************************************************************/
+static char *timestr (time_t sec)
+{
+ struct tm *t;
+ static char timestr[31+1]; /* 27+1 should be enough */
+
+#if defined(HAVE_STRFTIME) && HAVE_STRFTIME
+ t = localtime (&sec);
+ strftime (timestr, sizeof (timestr), "%b %d %Y %T %z", t);
+#else
+ static char *mstr[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+ int h, s;
+
+ t = localtime (&sec);
+ s = abs (t->tm_gmtoff);
+ h = t->tm_gmtoff / 3600;
+ s = t->tm_gmtoff % 3600;
+ snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d:%02d %c%02d%02d",
+ mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
+ t->tm_hour, t->tm_min, t->tm_sec,
+ t->tm_gmtoff < 0 ? '-': '+',
+ h, s);
+#endif
+
+ return timestr;
+}
+
+
+/****************************************************************
+**
+** int read_serial_fromfile (filename)
+**
+** This function depends on a special syntax formating the
+** SOA record in the zone file!!
+**
+** To match the SOA record, the SOA RR must be formatted
+** like this:
+** @ IN SOA <master.fq.dn.> <hostmaster.fq.dn.> (
+** <SPACEes or TABs> 1234567890; serial number
+** <SPACEes or TABs> 86400 ; other values
+** ...
+**
+****************************************************************/
+static int read_serial_fromfile (const char *fname, unsigned long *serial)
+{
+ FILE *fp;
+ char buf[4095+1];
+ char master[254+1];
+ int c;
+ int soafound;
+
+ if ( (fp = fopen (fname, "r")) == NULL )
+ return -1; /* file not found */
+
+ /* read until the line matches the beginning of a soa record ... */
+ soafound = 0;
+ while ( !soafound && fgets (buf, sizeof buf, fp) )
+ {
+ if ( sscanf (buf, "%*s %*d IN SOA %255s %*s (\n", master) == 1 )
+ soafound = 1;
+ else if ( sscanf (buf, "%*s IN SOA %255s %*s (\n", master) == 1 )
+ soafound = 1;
+ }
+
+ if ( !soafound )
+ return -2; /* no zone file (soa not found) */
+
+ /* move forward until any non ws is reached */
+ while ( (c = getc (fp)) != EOF && isspace (c) )
+ ;
+ ungetc (c, fp); /* pushback the non ws */
+
+ *serial = 0L; /* read in the current serial number */
+ if ( fscanf (fp, "%lu", serial) != 1 ) /* try to get serial no */
+ return -3; /* no serial number found */
+
+ fclose (fp);
+
+ return 0; /* ok! */
+}
+
+/*****************************************************************
+** printserial()
+*****************************************************************/
+static void printserial (const char *fname, unsigned long serial)
+{
+ if ( fname && *fname )
+ printf ("%-30s\t", fname);
+
+ printf ("%10lu", serial);
+
+ /* try to guess the soa serial format */
+ if ( serial < 1136070000L ) /* plain integer (this is 2006-1-1 00:00 in unixtime format) */
+ ;
+ else if ( serial > 2006010100L ) /* date format */
+ {
+ int y, m, d, v;
+
+ v = serial % 100;
+ serial /= 100;
+ d = serial % 100;
+ serial /= 100;
+ m = serial % 100;
+ serial /= 100;
+ y = serial;
+
+ printf ("\t%d-%02d-%02d Version %02d", y, m, d, v);
+ }
+ else /* unixtime */
+ printf ("\t%s\n", timestr (serial) );
+
+ printf ("\n");
+}
+
+/*****************************************************************
+** usage (msg)
+*****************************************************************/
+static void usage (const char *msg)
+{
+ if ( msg && *msg )
+ fprintf (stderr, "%s\n", msg);
+ fprintf (stderr, "usage: %s {-s serial | signed_zonefile [...]}\n", progname);
+
+ exit (1);
+}
+
+/*****************************************************************
+** main()
+*****************************************************************/
+int main (int argc, char *argv[])
+{
+ unsigned long serial;
+
+ progname = *argv;
+
+ if ( --argc == 0 )
+ usage ("");
+
+ if ( argv[1][0] == '-' )
+ {
+ if ( argv[1][1] != 's' )
+ usage ("illegal option");
+
+ if ( argc != 2 )
+ usage ("Option -s requires an argument");
+
+ serial = atol (argv[2]);
+ printserial ("", serial);
+ }
+ else
+ while ( argc-- > 0 )
+ if ( (read_serial_fromfile (*++argv, &serial)) != 0 )
+ fprintf (stderr, "couldn't read serial number from file %s\n", *argv);
+ else
+ printserial (*argv, serial);
+
+ return 0;
+}
diff --git a/contrib/zkt/zkt.c b/contrib/zkt/zkt.c
new file mode 100644
index 0000000..e699842
--- /dev/null
+++ b/contrib/zkt/zkt.c
@@ -0,0 +1,354 @@
+/*****************************************************************
+**
+** @(#) zkt.c -- A library for managing a list of dns zone files.
+**
+** Copyright (c) 2005 - 2008, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+# include <stdio.h>
+# include <string.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+# include "dki.h"
+# include "misc.h"
+# include "strlist.h"
+# include "zconf.h"
+#define extern
+# include "zkt.h"
+#undef extern
+
+extern char *labellist;
+extern int headerflag;
+extern int timeflag;
+extern int exptimeflag;
+extern int lifetime;
+extern int ageflag;
+extern int lifetimeflag;
+extern int kskflag;
+extern int zskflag;
+extern int pathflag;
+extern int ljustflag;
+
+static void printkeyinfo (const dki_t *dkp, const char *oldpath);
+
+static void printkeyinfo (const dki_t *dkp, const char *oldpath)
+{
+ time_t currtime;
+
+ if ( dkp == NULL ) /* print headline */
+ {
+ if ( headerflag )
+ {
+ printf ("%-33.33s %5s %3s %3.3s %-7s", "Keyname",
+ "Tag", "Typ", "Status", "Algorit");
+ if ( timeflag )
+ printf (" %-20s", "Generation Time");
+ if ( exptimeflag )
+ printf (" %-20s", "Expiration Time");
+ if ( ageflag )
+ printf (" %16s", "Age");
+ if ( lifetimeflag )
+ printf (" %4s", "LfTm");
+ putchar ('\n');
+ }
+ return;
+ }
+ time (&currtime);
+
+ /* TODO: use next line if dname is dynamically allocated */
+ /* if ( pathflag && dkp->dname && strcmp (oldpath, dkp->dname) != 0 ) */
+ if ( pathflag && strcmp (oldpath, dkp->dname) != 0 )
+ printf ("%s/\n", dkp->dname);
+
+ if ( (kskflag && dki_isksk (dkp)) || (zskflag && !dki_isksk (dkp)) )
+ {
+ if ( ljustflag )
+ printf ("%-33.33s ", dkp->name);
+ else
+ printf ("%33.33s ", dkp->name);
+ printf ("%05d ", dkp->tag);
+ printf ("%3s ", dki_isksk (dkp) ? "KSK" : "ZSK");
+ printf ("%-3.3s ", dki_statusstr (dkp) );
+ printf ("%-7s", dki_algo2str(dkp->algo));
+ if ( timeflag )
+ printf (" %-20s", time2str (dkp->gentime ? dkp->gentime: dkp->time, 's'));
+ if ( exptimeflag )
+ printf (" %-20s", time2str (dkp->exptime, 's'));
+ if ( ageflag )
+ printf (" %16s", age2str (dki_age (dkp, currtime)));
+ if ( lifetimeflag && dkp->lifetime )
+ {
+ if ( dkp->status == 'a' )
+ printf ("%c", (currtime < dkp->time + dkp->lifetime) ? '<' : '!');
+ else
+ putchar (' ');
+ printf ("%hdd", dki_lifetimedays (dkp));
+ }
+ putchar ('\n');
+ }
+}
+
+#if defined(USE_TREE) && USE_TREE
+static void list_key (const dki_t **nodep, const VISIT which, int depth)
+{
+ const dki_t *dkp;
+ static const char *oldpath = "";
+
+ if ( nodep == NULL )
+ return;
+//fprintf (stderr, "listkey %d %d %s\n", which, depth, dkp->name);
+
+ if ( which == INORDER || which == LEAF )
+ {
+ dkp = *nodep;
+ while ( dkp ) /* loop through list */
+ {
+ if ( labellist == NULL || isinlist (dkp->name, labellist) )
+ printkeyinfo (dkp, oldpath); /* print entry */
+ oldpath = dkp->dname;
+ dkp = dkp->next;
+ }
+ }
+}
+#endif
+
+void zkt_list_keys (const dki_t *data)
+{
+#if ! defined(USE_TREE) || !USE_TREE
+ const dki_t *dkp;
+ const char *oldpath;
+#endif
+
+ if ( data ) /* print headline if list is not empty */
+ printkeyinfo (NULL, "");
+
+#if defined(USE_TREE) && USE_TREE
+ twalk (data, list_key);
+#else
+ oldpath = "";
+ for ( dkp = data; dkp; dkp = dkp->next ) /* loop through list */
+ {
+ if ( labellist == NULL || isinlist (dkp->name, labellist) )
+ printkeyinfo (dkp, oldpath); /* print entry */
+ oldpath = dkp->dname;
+ }
+#endif
+}
+
+#if defined(USE_TREE) && USE_TREE
+static void list_trustedkey (const dki_t **nodep, const VISIT which, int depth)
+{
+ const dki_t *dkp;
+
+ if ( nodep == NULL )
+ return;
+
+ dkp = *nodep;
+//fprintf (stderr, "list_trustedkey %d %d %s\n", which, depth, dkp->name);
+ if ( which == INORDER || which == LEAF )
+ while ( dkp ) /* loop through list */
+ {
+ if ( (dki_isksk (dkp) || zskflag) &&
+ (labellist == NULL || isinlist (dkp->name, labellist)) )
+ dki_prt_trustedkey (dkp, stdout);
+ dkp = dkp->next;
+ }
+}
+#endif
+
+void zkt_list_trustedkeys (const dki_t *data)
+{
+#if !defined(USE_TREE) || !USE_TREE
+ const dki_t *dkp;
+#endif
+ /* print headline if list is not empty */
+ if ( data && headerflag )
+ printf ("trusted-keys {\n");
+
+#if defined(USE_TREE) && USE_TREE
+ twalk (data, list_trustedkey);
+#else
+
+ for ( dkp = data; dkp; dkp = dkp->next ) /* loop through list */
+ if ( (dki_isksk (dkp) || zskflag) &&
+ (labellist == NULL || isinlist (dkp->name, labellist)) )
+ dki_prt_trustedkey (dkp, stdout);
+#endif
+
+ /* print end of trusted-key section */
+ if ( data && headerflag )
+ printf ("};\n");
+}
+
+#if defined(USE_TREE) && USE_TREE
+static void list_dnskey (const dki_t **nodep, const VISIT which, int depth)
+{
+ const dki_t *dkp;
+ int ksk;
+
+ if ( nodep == NULL )
+ return;
+
+ if ( which == INORDER || which == LEAF )
+ for ( dkp = *nodep; dkp; dkp = dkp->next )
+ {
+ ksk = dki_isksk (dkp);
+ if ( (ksk && !kskflag) || (!ksk && !zskflag) )
+ continue;
+
+ if ( labellist == NULL || isinlist (dkp->name, labellist) )
+ {
+ if ( headerflag )
+ dki_prt_comment (dkp, stdout);
+ dki_prt_dnskey (dkp, stdout);
+ }
+ }
+}
+#endif
+
+void zkt_list_dnskeys (const dki_t *data)
+{
+#if defined(USE_TREE) && USE_TREE
+ twalk (data, list_dnskey);
+#else
+ const dki_t *dkp;
+ int ksk;
+
+ for ( dkp = data; dkp; dkp = dkp->next )
+ {
+ ksk = dki_isksk (dkp);
+ if ( (ksk && !kskflag) || (!ksk && !zskflag) )
+ continue;
+
+ if ( labellist == NULL || isinlist (dkp->name, labellist) )
+ {
+ if ( headerflag )
+ dki_prt_comment (dkp, stdout);
+ dki_prt_dnskey (dkp, stdout);
+ }
+ }
+#endif
+}
+
+#if defined(USE_TREE) && USE_TREE
+static void set_keylifetime (const dki_t **nodep, const VISIT which, int depth)
+{
+ const dki_t *dkp;
+ int ksk;
+
+ if ( nodep == NULL )
+ return;
+
+ if ( which == INORDER || which == LEAF )
+ for ( dkp = *nodep; dkp; dkp = dkp->next )
+ {
+ ksk = dki_isksk (dkp);
+ if ( (ksk && !kskflag) || (!ksk && !zskflag) )
+ continue;
+
+ if ( labellist == NULL || isinlist (dkp->name, labellist) )
+ dki_setlifetime ((dki_t *)dkp, lifetime);
+ }
+}
+#endif
+
+void zkt_setkeylifetime (dki_t *data)
+{
+#if defined(USE_TREE) && USE_TREE
+ twalk (data, set_keylifetime);
+#else
+ dki_t *dkp;
+ int ksk;
+
+ for ( dkp = data; dkp; dkp = dkp->next )
+ {
+ ksk = dki_isksk (dkp);
+ if ( (ksk && !kskflag) || (!ksk && !zskflag) )
+ continue;
+
+ if ( labellist == NULL || isinlist (dkp->name, labellist) )
+ {
+ dki_setlifetime (dkp, lifetime);
+ }
+ }
+#endif
+}
+
+
+#if defined(USE_TREE) && USE_TREE
+static const dki_t *searchresult;
+static int searchitem;
+static void tag_search (const dki_t **nodep, const VISIT which, int depth)
+{
+ const dki_t *dkp;
+
+ if ( nodep == NULL )
+ return;
+
+ if ( which == PREORDER || which == LEAF )
+ for ( dkp = *nodep; dkp; dkp = dkp->next )
+ {
+ if ( dkp->tag == searchitem )
+ {
+ if ( searchresult == NULL )
+ searchresult = dkp;
+ else
+ searchitem = 0;
+ }
+ }
+}
+#endif
+const dki_t *zkt_search (const dki_t *data, int searchtag, const char *keyname)
+{
+ const dki_t *dkp = NULL;
+
+#if defined(USE_TREE) && USE_TREE
+ if ( keyname == NULL || *keyname == '\0' )
+ {
+ searchresult = NULL;
+ searchitem = searchtag;
+ twalk (data, tag_search);
+ if ( searchresult != NULL && searchitem == 0 )
+ dkp = (void *)01;
+ else
+ dkp = searchresult;
+ }
+ else
+ dkp = (dki_t*)dki_tsearch (data, searchtag, keyname);
+#else
+ dkp = (dki_t*)dki_search (data, searchtag, keyname);
+#endif
+ return dkp;
+}
+
diff --git a/contrib/zkt/zkt.h b/contrib/zkt/zkt.h
new file mode 100644
index 0000000..2f3398d
--- /dev/null
+++ b/contrib/zkt/zkt.h
@@ -0,0 +1,46 @@
+/*****************************************************************
+**
+** @(#) zkt.h (c) 2005 - 2008 Holger Zuleger hznet.de
+**
+** Copyright (c) 2005 - 2008, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+#ifndef ZKT_H
+# define ZKT_H
+
+extern const dki_t *zkt_search (const dki_t *data, int searchtag, const char *keyname);
+extern void zkt_list_keys (const dki_t *data);
+extern void zkt_list_trustedkeys (const dki_t *data);
+extern void zkt_list_dnskeys (const dki_t *data);
+extern void zkt_setkeylifetime (dki_t *data);
+
+#endif
diff --git a/contrib/zkt/zone.c b/contrib/zkt/zone.c
new file mode 100644
index 0000000..dec214e
--- /dev/null
+++ b/contrib/zkt/zone.c
@@ -0,0 +1,336 @@
+/*****************************************************************
+**
+** @(#) zone.c (c) Mar 2005 Holger Zuleger hznet.de
+**
+** Copyright (c) Mar 2005, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <dirent.h>
+# include <assert.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+# include "debug.h"
+# include "domaincmp.h"
+# include "misc.h"
+# include "zconf.h"
+# include "dki.h"
+#define extern
+# include "zone.h"
+#undef extern
+
+/*****************************************************************
+** private (static) function declaration and definition
+*****************************************************************/
+static char zone_estr[255+1];
+
+/*****************************************************************
+** zone_alloc ()
+*****************************************************************/
+static zone_t *zone_alloc ()
+{
+ zone_t *zp;
+
+ if ( (zp = malloc (sizeof (zone_t))) )
+ {
+ memset (zp, 0, sizeof (zone_t));
+ return zp;
+ }
+
+ snprintf (zone_estr, sizeof (zone_estr),
+ "zone_alloc: Out of memory");
+ return NULL;
+}
+
+/*****************************************************************
+** zone_cmp () return <0 | 0 | >0
+*****************************************************************/
+static int zone_cmp (const zone_t *a, const zone_t *b)
+{
+ if ( a == NULL ) return -1;
+ if ( b == NULL ) return 1;
+
+ return domaincmp (a->zone, b->zone);
+}
+
+
+/*****************************************************************
+** public function definition
+*****************************************************************/
+
+/*****************************************************************
+** zone_free ()
+*****************************************************************/
+void zone_free (zone_t *zp)
+{
+ assert (zp != NULL);
+
+ if ( zp->zone ) free ((char *)zp->zone);
+ if ( zp->dir ) free ((char *)zp->dir);
+ if ( zp->file ) free ((char *)zp->file);
+ if ( zp->sfile ) free ((char *)zp->sfile);
+#if 0
+ /* TODO: actually there are some problems freeing the config :-( */
+ if ( zp->conf ) free ((zconf_t *)zp->conf);
+#endif
+ if ( zp->keys ) dki_freelist (&zp->keys);
+ free (zp);
+}
+
+/*****************************************************************
+** zone_freelist ()
+*****************************************************************/
+void zone_freelist (zone_t **listp)
+{
+ zone_t *curr;
+ zone_t *next;
+
+ assert (listp != NULL);
+
+ curr = *listp;
+ while ( curr )
+ {
+ next = curr->next;
+ zone_free (curr);
+ curr = next;
+ }
+ if ( *listp )
+ *listp = NULL;
+}
+
+/*****************************************************************
+** zone_new ()
+** allocate memory for new zone structure and initialize it
+*****************************************************************/
+zone_t *zone_new (zone_t **zp, const char *zone, const char *dir, const char *file, const char *signed_ext, const zconf_t *cp)
+{
+ char path[MAX_PATHSIZE+1];
+ zone_t *new;
+
+ assert (zp != NULL);
+ assert (zone != NULL && *zone != '\0');
+
+ dbg_val3 ("zone_new: (zp, zone: %s, dir: %s, file: %s, cp)\n", zone, dir, file);
+ if ( dir == NULL || *dir == '\0' )
+ dir = ".";
+
+ if ( file == NULL || *file == '\0' )
+ file = cp->zonefile;
+ else
+ { /* check if file contains a path */
+ const char *p;
+ if ( (p = strrchr (file, '/')) != NULL )
+ {
+ snprintf (path, sizeof (path), "%s/%.*s", dir, p-file, file);
+ dir = path;
+ file = p+1;
+ }
+ }
+
+ if ( (new = zone_alloc ()) != NULL )
+ {
+ char *p;
+
+ new->zone = str_tolowerdup (zone);
+ new->dir = strdup (dir);
+ new->file = strdup (file);
+ /* check if file ends with ".signed" ? */
+ if ( (p = strrchr (new->file, '.')) != NULL && strcmp (p, signed_ext) == 0 )
+ {
+ new->sfile = strdup (new->file);
+ *p = '\0';
+ }
+ else
+ {
+ snprintf (path, sizeof (path), "%s%s", file, signed_ext);
+ new->sfile = strdup (path);
+ }
+ new->conf = cp;
+ new->keys = NULL;
+ dki_readdir (new->dir, &new->keys, 0);
+ new->next = NULL;
+ }
+
+ return zone_add (zp, new);
+}
+
+/*****************************************************************
+** zone_readdir ()
+*****************************************************************/
+int zone_readdir (const char *dir, const char *zone, const char *zfile, zone_t **listp, const zconf_t *conf, int dyn_zone)
+{
+ char *p;
+ char path[MAX_PATHSIZE+1];
+ char *signed_ext = ".signed";
+
+ assert (dir != NULL && *dir != '\0');
+ assert (conf != NULL);
+
+ if ( zone == NULL ) /* zone not given ? */
+ {
+ if ( (zone = strrchr (dir, '/')) ) /* try to extract zone name out of directory */
+ zone++;
+ else
+ zone = dir;
+ }
+ dbg_val4 ("zone_readdir: (dir: %s, zone: %s, zfile: %s zp, cp, dyn_zone = %d)\n",
+ dir, zone, zfile ? zfile: "NULL", dyn_zone);
+
+ if ( dyn_zone )
+ signed_ext = ".dsigned";
+
+ if ( zfile && (p = strrchr (zfile, '/')) ) /* check if zfile contains a directory */
+ {
+ char subdir[MAX_PATHSIZE+1];
+
+ snprintf (subdir, sizeof (subdir), "%s/%.*s", dir, p - zfile, zfile);
+ pathname (path, sizeof (path), subdir, LOCALCONF_FILE, NULL);
+ }
+ else
+ pathname (path, sizeof (path), dir, LOCALCONF_FILE, NULL);
+ dbg_val1 ("zone_readdir: check local config file %s\n", path);
+ if ( fileexist (path) ) /* load local config file */
+ {
+ zconf_t *localconf;
+
+ localconf = dupconfig (conf);
+ conf = loadconfig (path, localconf);
+ }
+
+ if ( zfile == NULL )
+ {
+ zfile = conf->zonefile;
+ pathname (path, sizeof (path), dir, zfile, signed_ext);
+ }
+ else
+ {
+ dbg_val2("zone_readdir: add %s to zonefile if not already there ? (%s)\n", signed_ext, zfile);
+ if ( (p = strrchr (zfile, '.')) == NULL || strcmp (p, signed_ext) != 0 )
+ pathname (path, sizeof (path), dir, zfile, signed_ext);
+ else
+ pathname (path, sizeof (path), dir, zfile, NULL);
+ }
+
+ dbg_val1("zone_readdir: fileexist (%s): ", path);
+ if ( !fileexist (path) ) /* no .signed file found ? ... */
+ {
+ dbg_val0("no!\n");
+ return 0; /* ... not a secure zone ! */
+ }
+ dbg_val0("yes!\n");
+
+ dbg_val("zone_readdir: add zone (%s)\n", zone);
+ zone_new (listp, zone, dir, zfile, signed_ext, conf);
+
+ return 1;
+}
+
+
+/*****************************************************************
+** zone_geterrstr ()
+** return error string
+*****************************************************************/
+const char *zone_geterrstr ()
+{
+ return zone_estr;
+}
+
+/*****************************************************************
+** zone_add ()
+*****************************************************************/
+zone_t *zone_add (zone_t **list, zone_t *new)
+{
+ zone_t *curr;
+ zone_t *last;
+
+ if ( list == NULL )
+ return NULL;
+ if ( new == NULL )
+ return *list;
+
+ last = curr = *list;
+ while ( curr && zone_cmp (curr, new) < 0 )
+ {
+ last = curr;
+ curr = curr->next;
+ }
+
+ if ( curr == *list ) /* add node at the beginning of the list */
+ *list = new;
+ else /* add node at end or between two nodes */
+ last->next = new;
+ new->next = curr;
+
+ return new;
+}
+
+/*****************************************************************
+** zone_search ()
+*****************************************************************/
+const zone_t *zone_search (const zone_t *list, const char *zone)
+{
+ if ( zone == NULL || *zone == '\0' )
+ return NULL;
+
+ while ( list && strcmp (zone, list->zone) != 0 )
+ list = list->next;
+
+ return list;
+}
+
+/*****************************************************************
+** zone_print ()
+*****************************************************************/
+int zone_print (const char *mesg, const zone_t *z)
+{
+ dki_t *dkp;
+
+ if ( !z )
+ return 0;
+ fprintf (stderr, "%s: zone\t %s\n", mesg, z->zone);
+ fprintf (stderr, "%s: dir\t %s\n", mesg, z->dir);
+ fprintf (stderr, "%s: file\t %s\n", mesg, z->file);
+ fprintf (stderr, "%s: sfile\t %s\n", mesg, z->sfile);
+
+ for ( dkp = z->keys; dkp; dkp = dkp->next )
+ {
+ dki_prt_comment (dkp, stderr);
+ }
+
+ return 1;
+}
diff --git a/contrib/zkt/zone.h b/contrib/zkt/zone.h
new file mode 100644
index 0000000..e785796
--- /dev/null
+++ b/contrib/zkt/zone.h
@@ -0,0 +1,66 @@
+/*****************************************************************
+**
+** @(#) zone.h -- Header file for zone info
+**
+** Copyright (c) Mar 2005, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+#ifndef ZONE_H
+# define ZONE_H
+
+# include <sys/types.h>
+# include <stdio.h>
+# include <time.h>
+# include "dki.h"
+
+/* all we have to know about a zone */
+typedef struct Zone {
+ const char *zone; /* domain name or label */
+ const char *dir; /* directory of zone data */
+ const char *file; /* file name (zone.db) */
+ const char *sfile; /* file name of secured zone (zone.db.signed) */
+ const zconf_t *conf; /* ptr to config */ /* TODO: Should this be only a ptr to a local config ? */
+ dki_t *keys; /* ptr to keylist */
+ struct Zone *next; /* ptr to next entry in list */
+} zone_t;
+
+extern void zone_free (zone_t *zp);
+extern void zone_freelist (zone_t **listp);
+extern zone_t *zone_new (zone_t **zp, const char *zone, const char *dir, const char *file, const char *signed_ext, const zconf_t *cp);
+extern const char *zone_geterrstr ();
+extern zone_t *zone_add (zone_t **list, zone_t *new);
+extern const zone_t *zone_search (const zone_t *list, const char *name);
+extern int zone_readdir (const char *dir, const char *zone, const char *zfile, zone_t **listp, const zconf_t *conf, int dyn_zone);
+extern const char *zone_geterrstr (void);
+extern int zone_print (const char *mesg, const zone_t *z);
+
+#endif
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644
index 0000000..14d35bc
--- /dev/null
+++ b/doc/Makefile.in
@@ -0,0 +1,29 @@
+# Copyright (C) 2004-2007 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: Makefile.in,v 1.11 2007/06/19 23:47:13 tbox Exp $
+
+# This Makefile is a placeholder. It exists merely to make
+# sure that its directory gets created in the object directory
+# tree when doing a build using separate object directories.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = arm misc xsl doxygen
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml
new file mode 100644
index 0000000..8c17589
--- /dev/null
+++ b/doc/arm/Bv9ARM-book.xml
@@ -0,0 +1,14205 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - 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
+ - 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.
+-->
+
+<!-- File: $Id: Bv9ARM-book.xml,v 1.380 2008/11/07 02:28:49 marka Exp $ -->
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>BIND 9 Administrator Reference Manual</title>
+
+ <bookinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </bookinfo>
+
+ <chapter id="Bv9ARM.ch01">
+ <title>Introduction</title>
+ <para>
+ The Internet Domain Name System (<acronym>DNS</acronym>)
+ consists of the syntax
+ to specify the names of entities in the Internet in a hierarchical
+ manner, the rules used for delegating authority over names, and the
+ system implementation that actually maps names to Internet
+ addresses. <acronym>DNS</acronym> data is maintained in a
+ group of distributed
+ hierarchical databases.
+ </para>
+
+ <sect1>
+ <title>Scope of Document</title>
+
+ <para>
+ The Berkeley Internet Name Domain
+ (<acronym>BIND</acronym>) implements a
+ domain name server for a number of operating systems. This
+ document provides basic information about the installation and
+ care of the Internet Systems Consortium (<acronym>ISC</acronym>)
+ <acronym>BIND</acronym> version 9 software package for
+ system administrators.
+ </para>
+
+ <para>
+ This version of the manual corresponds to BIND version 9.6.
+ </para>
+
+ </sect1>
+ <sect1>
+ <title>Organization of This Document</title>
+ <para>
+ In this document, <emphasis>Section 1</emphasis> introduces
+ the basic <acronym>DNS</acronym> and <acronym>BIND</acronym> concepts. <emphasis>Section 2</emphasis>
+ describes resource requirements for running <acronym>BIND</acronym> in various
+ environments. Information in <emphasis>Section 3</emphasis> is
+ <emphasis>task-oriented</emphasis> in its presentation and is
+ organized functionally, to aid in the process of installing the
+ <acronym>BIND</acronym> 9 software. The task-oriented
+ section is followed by
+ <emphasis>Section 4</emphasis>, which contains more advanced
+ concepts that the system administrator may need for implementing
+ certain options. <emphasis>Section 5</emphasis>
+ describes the <acronym>BIND</acronym> 9 lightweight
+ resolver. The contents of <emphasis>Section 6</emphasis> are
+ organized as in a reference manual to aid in the ongoing
+ maintenance of the software. <emphasis>Section 7</emphasis> addresses
+ security considerations, and
+ <emphasis>Section 8</emphasis> contains troubleshooting help. The
+ main body of the document is followed by several
+ <emphasis>appendices</emphasis> which contain useful reference
+ information, such as a <emphasis>bibliography</emphasis> and
+ historic information related to <acronym>BIND</acronym>
+ and the Domain Name
+ System.
+ </para>
+ </sect1>
+ <sect1>
+ <title>Conventions Used in This Document</title>
+
+ <para>
+ In this document, we use the following general typographic
+ conventions:
+ </para>
+
+ <informaltable>
+ <tgroup cols="2">
+ <colspec colname="1" colnum="1" colwidth="3.000in"/>
+ <colspec colname="2" colnum="2" colwidth="2.625in"/>
+ <tbody>
+ <row>
+ <entry colname="1">
+ <para>
+ <emphasis>To describe:</emphasis>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <emphasis>We use the style:</emphasis>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry colname="1">
+ <para>
+ a pathname, filename, URL, hostname,
+ mailing list name, or new term or concept
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <filename>Fixed width</filename>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry colname="1">
+ <para>
+ literal user
+ input
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <userinput>Fixed Width Bold</userinput>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry colname="1">
+ <para>
+ program output
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <computeroutput>Fixed Width</computeroutput>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>
+ The following conventions are used in descriptions of the
+ <acronym>BIND</acronym> configuration file:<informaltable colsep="0" frame="all" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="2Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="3.000in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="2.625in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1" colsep="1" rowsep="1">
+ <para>
+ <emphasis>To describe:</emphasis>
+ </para>
+ </entry>
+ <entry colname="2" rowsep="1">
+ <para>
+ <emphasis>We use the style:</emphasis>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1" colsep="1" rowsep="1">
+ <para>
+ keywords
+ </para>
+ </entry>
+ <entry colname="2" rowsep="1">
+ <para>
+ <literal>Fixed Width</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1" colsep="1" rowsep="1">
+ <para>
+ variables
+ </para>
+ </entry>
+ <entry colname="2" rowsep="1">
+ <para>
+ <varname>Fixed Width</varname>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1" colsep="1">
+ <para>
+ Optional input
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <optional>Text is enclosed in square brackets</optional>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </sect1>
+ <sect1>
+ <title>The Domain Name System (<acronym>DNS</acronym>)</title>
+ <para>
+ The purpose of this document is to explain the installation
+ and upkeep of the <acronym>BIND</acronym> (Berkeley Internet
+ Name Domain) software package, and we
+ begin by reviewing the fundamentals of the Domain Name System
+ (<acronym>DNS</acronym>) as they relate to <acronym>BIND</acronym>.
+ </para>
+
+ <sect2>
+ <title>DNS Fundamentals</title>
+
+ <para>
+ The Domain Name System (DNS) is a hierarchical, distributed
+ database. It stores information for mapping Internet host names to
+ IP
+ addresses and vice versa, mail routing information, and other data
+ used by Internet applications.
+ </para>
+
+ <para>
+ Clients look up information in the DNS by calling a
+ <emphasis>resolver</emphasis> library, which sends queries to one or
+ more <emphasis>name servers</emphasis> and interprets the responses.
+ The <acronym>BIND</acronym> 9 software distribution
+ contains a
+ name server, <command>named</command>, and a resolver
+ library, <command>liblwres</command>. The older
+ <command>libbind</command> resolver library is also available
+ from ISC as a separate download.
+ </para>
+
+ </sect2><sect2>
+ <title>Domains and Domain Names</title>
+
+ <para>
+ The data stored in the DNS is identified by <emphasis>domain names</emphasis> that are organized as a tree according to
+ organizational or administrative boundaries. Each node of the tree,
+ called a <emphasis>domain</emphasis>, is given a label. The domain
+ name of the
+ node is the concatenation of all the labels on the path from the
+ node to the <emphasis>root</emphasis> node. This is represented
+ in written form as a string of labels listed from right to left and
+ separated by dots. A label need only be unique within its parent
+ domain.
+ </para>
+
+ <para>
+ For example, a domain name for a host at the
+ company <emphasis>Example, Inc.</emphasis> could be
+ <literal>ourhost.example.com</literal>,
+ where <literal>com</literal> is the
+ top level domain to which
+ <literal>ourhost.example.com</literal> belongs,
+ <literal>example</literal> is
+ a subdomain of <literal>com</literal>, and
+ <literal>ourhost</literal> is the
+ name of the host.
+ </para>
+
+ <para>
+ For administrative purposes, the name space is partitioned into
+ areas called <emphasis>zones</emphasis>, each starting at a node and
+ extending down to the leaf nodes or to nodes where other zones
+ start.
+ The data for each zone is stored in a <emphasis>name server</emphasis>, which answers queries about the zone using the
+ <emphasis>DNS protocol</emphasis>.
+ </para>
+
+ <para>
+ The data associated with each domain name is stored in the
+ form of <emphasis>resource records</emphasis> (<acronym>RR</acronym>s).
+ Some of the supported resource record types are described in
+ <xref linkend="types_of_resource_records_and_when_to_use_them"/>.
+ </para>
+
+ <para>
+ For more detailed information about the design of the DNS and
+ the DNS protocol, please refer to the standards documents listed in
+ <xref linkend="rfcs"/>.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Zones</title>
+ <para>
+ To properly operate a name server, it is important to understand
+ the difference between a <emphasis>zone</emphasis>
+ and a <emphasis>domain</emphasis>.
+ </para>
+
+ <para>
+ As stated previously, a zone is a point of delegation in
+ the <acronym>DNS</acronym> tree. A zone consists of
+ those contiguous parts of the domain
+ tree for which a name server has complete information and over which
+ it has authority. It contains all domain names from a certain point
+ downward in the domain tree except those which are delegated to
+ other zones. A delegation point is marked by one or more
+ <emphasis>NS records</emphasis> in the
+ parent zone, which should be matched by equivalent NS records at
+ the root of the delegated zone.
+ </para>
+
+ <para>
+ For instance, consider the <literal>example.com</literal>
+ domain which includes names
+ such as <literal>host.aaa.example.com</literal> and
+ <literal>host.bbb.example.com</literal> even though
+ the <literal>example.com</literal> zone includes
+ only delegations for the <literal>aaa.example.com</literal> and
+ <literal>bbb.example.com</literal> zones. A zone can
+ map
+ exactly to a single domain, but could also include only part of a
+ domain, the rest of which could be delegated to other
+ name servers. Every name in the <acronym>DNS</acronym>
+ tree is a
+ <emphasis>domain</emphasis>, even if it is
+ <emphasis>terminal</emphasis>, that is, has no
+ <emphasis>subdomains</emphasis>. Every subdomain is a domain and
+ every domain except the root is also a subdomain. The terminology is
+ not intuitive and we suggest that you read RFCs 1033, 1034 and 1035
+ to
+ gain a complete understanding of this difficult and subtle
+ topic.
+ </para>
+
+ <para>
+ Though <acronym>BIND</acronym> is called a "domain name
+ server",
+ it deals primarily in terms of zones. The master and slave
+ declarations in the <filename>named.conf</filename> file
+ specify
+ zones, not domains. When you ask some other site if it is willing to
+ be a slave server for your <emphasis>domain</emphasis>, you are
+ actually asking for slave service for some collection of zones.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Authoritative Name Servers</title>
+
+ <para>
+ Each zone is served by at least
+ one <emphasis>authoritative name server</emphasis>,
+ which contains the complete data for the zone.
+ To make the DNS tolerant of server and network failures,
+ most zones have two or more authoritative servers, on
+ different networks.
+ </para>
+
+ <para>
+ Responses from authoritative servers have the "authoritative
+ answer" (AA) bit set in the response packets. This makes them
+ easy to identify when debugging DNS configurations using tools like
+ <command>dig</command> (<xref linkend="diagnostic_tools"/>).
+ </para>
+
+ <sect3>
+ <title>The Primary Master</title>
+
+ <para>
+ The authoritative server where the master copy of the zone
+ data is maintained is called the
+ <emphasis>primary master</emphasis> server, or simply the
+ <emphasis>primary</emphasis>. Typically it loads the zone
+ contents from some local file edited by humans or perhaps
+ generated mechanically from some other local file which is
+ edited by humans. This file is called the
+ <emphasis>zone file</emphasis> or
+ <emphasis>master file</emphasis>.
+ </para>
+
+ <para>
+ In some cases, however, the master file may not be edited
+ by humans at all, but may instead be the result of
+ <emphasis>dynamic update</emphasis> operations.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title>Slave Servers</title>
+ <para>
+ The other authoritative servers, the <emphasis>slave</emphasis>
+ servers (also known as <emphasis>secondary</emphasis> servers)
+ load
+ the zone contents from another server using a replication process
+ known as a <emphasis>zone transfer</emphasis>. Typically the data
+ are
+ transferred directly from the primary master, but it is also
+ possible
+ to transfer it from another slave. In other words, a slave server
+ may itself act as a master to a subordinate slave server.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title>Stealth Servers</title>
+
+ <para>
+ Usually all of the zone's authoritative servers are listed in
+ NS records in the parent zone. These NS records constitute
+ a <emphasis>delegation</emphasis> of the zone from the parent.
+ The authoritative servers are also listed in the zone file itself,
+ at the <emphasis>top level</emphasis> or <emphasis>apex</emphasis>
+ of the zone. You can list servers in the zone's top-level NS
+ records that are not in the parent's NS delegation, but you cannot
+ list servers in the parent's delegation that are not present at
+ the zone's top level.
+ </para>
+
+ <para>
+ A <emphasis>stealth server</emphasis> is a server that is
+ authoritative for a zone but is not listed in that zone's NS
+ records. Stealth servers can be used for keeping a local copy of
+ a
+ zone to speed up access to the zone's records or to make sure that
+ the
+ zone is available even if all the "official" servers for the zone
+ are
+ inaccessible.
+ </para>
+
+ <para>
+ A configuration where the primary master server itself is a
+ stealth server is often referred to as a "hidden primary"
+ configuration. One use for this configuration is when the primary
+ master
+ is behind a firewall and therefore unable to communicate directly
+ with the outside world.
+ </para>
+
+ </sect3>
+
+ </sect2>
+ <sect2>
+
+ <title>Caching Name Servers</title>
+
+ <!--
+ - Terminology here is inconsistent. Probably ought to
+ - convert to using "recursive name server" everywhere
+ - with just a note about "caching" terminology.
+ -->
+
+ <para>
+ The resolver libraries provided by most operating systems are
+ <emphasis>stub resolvers</emphasis>, meaning that they are not
+ capable of
+ performing the full DNS resolution process by themselves by talking
+ directly to the authoritative servers. Instead, they rely on a
+ local
+ name server to perform the resolution on their behalf. Such a
+ server
+ is called a <emphasis>recursive</emphasis> name server; it performs
+ <emphasis>recursive lookups</emphasis> for local clients.
+ </para>
+
+ <para>
+ To improve performance, recursive servers cache the results of
+ the lookups they perform. Since the processes of recursion and
+ caching are intimately connected, the terms
+ <emphasis>recursive server</emphasis> and
+ <emphasis>caching server</emphasis> are often used synonymously.
+ </para>
+
+ <para>
+ The length of time for which a record may be retained in
+ the cache of a caching name server is controlled by the
+ Time To Live (TTL) field associated with each resource record.
+ </para>
+
+ <sect3>
+ <title>Forwarding</title>
+
+ <para>
+ Even a caching name server does not necessarily perform
+ the complete recursive lookup itself. Instead, it can
+ <emphasis>forward</emphasis> some or all of the queries
+ that it cannot satisfy from its cache to another caching name
+ server,
+ commonly referred to as a <emphasis>forwarder</emphasis>.
+ </para>
+
+ <para>
+ There may be one or more forwarders,
+ and they are queried in turn until the list is exhausted or an
+ answer
+ is found. Forwarders are typically used when you do not
+ wish all the servers at a given site to interact directly with the
+ rest of
+ the Internet servers. A typical scenario would involve a number
+ of internal <acronym>DNS</acronym> servers and an
+ Internet firewall. Servers unable
+ to pass packets through the firewall would forward to the server
+ that can do it, and that server would query the Internet <acronym>DNS</acronym> servers
+ on the internal server's behalf.
+ </para>
+ </sect3>
+
+ </sect2>
+
+ <sect2>
+ <title>Name Servers in Multiple Roles</title>
+
+ <para>
+ The <acronym>BIND</acronym> name server can
+ simultaneously act as
+ a master for some zones, a slave for other zones, and as a caching
+ (recursive) server for a set of local clients.
+ </para>
+
+ <para>
+ However, since the functions of authoritative name service
+ and caching/recursive name service are logically separate, it is
+ often advantageous to run them on separate server machines.
+
+ A server that only provides authoritative name service
+ (an <emphasis>authoritative-only</emphasis> server) can run with
+ recursion disabled, improving reliability and security.
+
+ A server that is not authoritative for any zones and only provides
+ recursive service to local
+ clients (a <emphasis>caching-only</emphasis> server)
+ does not need to be reachable from the Internet at large and can
+ be placed inside a firewall.
+ </para>
+
+ </sect2>
+ </sect1>
+
+ </chapter>
+
+ <chapter id="Bv9ARM.ch02">
+ <title><acronym>BIND</acronym> Resource Requirements</title>
+
+ <sect1>
+ <title>Hardware requirements</title>
+
+ <para>
+ <acronym>DNS</acronym> hardware requirements have
+ traditionally been quite modest.
+ For many installations, servers that have been pensioned off from
+ active duty have performed admirably as <acronym>DNS</acronym> servers.
+ </para>
+ <para>
+ The DNSSEC features of <acronym>BIND</acronym> 9
+ may prove to be quite
+ CPU intensive however, so organizations that make heavy use of these
+ features may wish to consider larger systems for these applications.
+ <acronym>BIND</acronym> 9 is fully multithreaded, allowing
+ full utilization of
+ multiprocessor systems for installations that need it.
+ </para>
+ </sect1>
+ <sect1>
+ <title>CPU Requirements</title>
+ <para>
+ CPU requirements for <acronym>BIND</acronym> 9 range from
+ i486-class machines
+ for serving of static zones without caching, to enterprise-class
+ machines if you intend to process many dynamic updates and DNSSEC
+ signed zones, serving many thousands of queries per second.
+ </para>
+ </sect1>
+
+ <sect1>
+ <title>Memory Requirements</title>
+ <para>
+ The memory of the server has to be large enough to fit the
+ cache and zones loaded off disk. The <command>max-cache-size</command>
+ option can be used to limit the amount of memory used by the cache,
+ at the expense of reducing cache hit rates and causing more <acronym>DNS</acronym>
+ traffic.
+ Additionally, if additional section caching
+ (<xref linkend="acache"/>) is enabled,
+ the <command>max-acache-size</command> option can be used to
+ limit the amount
+ of memory used by the mechanism.
+ It is still good practice to have enough memory to load
+ all zone and cache data into memory &mdash; unfortunately, the best
+ way
+ to determine this for a given installation is to watch the name server
+ in operation. After a few weeks the server process should reach
+ a relatively stable size where entries are expiring from the cache as
+ fast as they are being inserted.
+ </para>
+ <!--
+ - Add something here about leaving overhead for attacks?
+ - How much overhead? Percentage?
+ -->
+ </sect1>
+
+ <sect1>
+ <title>Name Server Intensive Environment Issues</title>
+ <para>
+ For name server intensive environments, there are two alternative
+ configurations that may be used. The first is where clients and
+ any second-level internal name servers query a main name server, which
+ has enough memory to build a large cache. This approach minimizes
+ the bandwidth used by external name lookups. The second alternative
+ is to set up second-level internal name servers to make queries
+ independently.
+ In this configuration, none of the individual machines needs to
+ have as much memory or CPU power as in the first alternative, but
+ this has the disadvantage of making many more external queries,
+ as none of the name servers share their cached data.
+ </para>
+ </sect1>
+
+ <sect1>
+ <title>Supported Operating Systems</title>
+ <para>
+ ISC <acronym>BIND</acronym> 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
+ list of supported systems, see the README file in the top level
+ directory
+ of the BIND 9 source distribution.
+ </para>
+ </sect1>
+ </chapter>
+
+ <chapter id="Bv9ARM.ch03">
+ <title>Name Server Configuration</title>
+ <para>
+ In this section we provide some suggested configurations along
+ with guidelines for their use. We suggest reasonable values for
+ certain option settings.
+ </para>
+
+ <sect1 id="sample_configuration">
+ <title>Sample Configurations</title>
+ <sect2>
+ <title>A Caching-only Name Server</title>
+ <para>
+ The following sample configuration is appropriate for a caching-only
+ name server for use by clients internal to a corporation. All
+ queries
+ from outside clients are refused using the <command>allow-query</command>
+ option. Alternatively, the same effect could be achieved using
+ suitable
+ firewall rules.
+ </para>
+
+<programlisting>
+// 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
+ allow-query { corpnets; };
+};
+// Provide a reverse mapping for the loopback address 127.0.0.1
+zone "0.0.127.in-addr.arpa" {
+ type master;
+ file "localhost.rev";
+ notify no;
+};
+</programlisting>
+
+ </sect2>
+
+ <sect2>
+ <title>An Authoritative-only Name Server</title>
+ <para>
+ This sample configuration is for an authoritative-only server
+ that is the master server for "<filename>example.com</filename>"
+ and a slave for the subdomain "<filename>eng.example.com</filename>".
+ </para>
+
+<programlisting>
+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
+};
+
+// Provide a reverse mapping for the loopback address 127.0.0.1
+zone "0.0.127.in-addr.arpa" {
+ type master;
+ file "localhost.rev";
+ notify no;
+};
+// We are the master server for example.com
+zone "example.com" {
+ type master;
+ file "example.com.db";
+ // IP addresses of slave servers allowed to transfer example.com
+ allow-transfer {
+ 192.168.4.14;
+ 192.168.5.53;
+ };
+};
+// We are a slave server for eng.example.com
+zone "eng.example.com" {
+ type slave;
+ file "eng.example.com.bk";
+ // IP address of eng.example.com master server
+ masters { 192.168.4.12; };
+};
+</programlisting>
+
+ </sect2>
+ </sect1>
+
+ <sect1>
+ <title>Load Balancing</title>
+ <!--
+ - Add explanation of why load balancing is fragile at best
+ - and completely pointless in the general case.
+ -->
+
+ <para>
+ A primitive form of load balancing can be achieved in
+ the <acronym>DNS</acronym> by using multiple records
+ (such as multiple A records) for one name.
+ </para>
+
+ <para>
+ For example, if you have three WWW servers with network addresses
+ of 10.0.0.1, 10.0.0.2 and 10.0.0.3, a set of records such as the
+ following means that clients will connect to each machine one third
+ of the time:
+ </para>
+
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="5" colsep="0" rowsep="0" tgroupstyle="2Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="0.875in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="0.500in"/>
+ <colspec colname="3" colnum="3" colsep="0" colwidth="0.750in"/>
+ <colspec colname="4" colnum="4" colsep="0" colwidth="0.750in"/>
+ <colspec colname="5" colnum="5" colsep="0" colwidth="2.028in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ Name
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ TTL
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ CLASS
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ TYPE
+ </para>
+ </entry>
+ <entry colname="5">
+ <para>
+ Resource Record (RR) Data
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <literal>www</literal>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>600</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>IN</literal>
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ <literal>A</literal>
+ </para>
+ </entry>
+ <entry colname="5">
+ <para>
+ <literal>10.0.0.1</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para/>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>600</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>IN</literal>
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ <literal>A</literal>
+ </para>
+ </entry>
+ <entry colname="5">
+ <para>
+ <literal>10.0.0.2</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para/>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>600</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>IN</literal>
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ <literal>A</literal>
+ </para>
+ </entry>
+ <entry colname="5">
+ <para>
+ <literal>10.0.0.3</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ When a resolver queries for these records, <acronym>BIND</acronym> will rotate
+ them and respond to the query with the records in a different
+ order. In the example above, clients will randomly receive
+ records in the order 1, 2, 3; 2, 3, 1; and 3, 1, 2. Most clients
+ will use the first record returned and discard the rest.
+ </para>
+ <para>
+ For more detail on ordering responses, check the
+ <command>rrset-order</command> substatement in the
+ <command>options</command> statement, see
+ <xref endterm="rrset_ordering_title" linkend="rrset_ordering"/>.
+ </para>
+
+ </sect1>
+
+ <sect1>
+ <title>Name Server Operations</title>
+
+ <sect2>
+ <title>Tools for Use With the Name Server Daemon</title>
+ <para>
+ This section describes several indispensable diagnostic,
+ administrative and monitoring tools available to the system
+ administrator for controlling and debugging the name server
+ daemon.
+ </para>
+ <sect3 id="diagnostic_tools">
+ <title>Diagnostic Tools</title>
+ <para>
+ The <command>dig</command>, <command>host</command>, and
+ <command>nslookup</command> programs are all command
+ line tools
+ for manually querying name servers. They differ in style and
+ output format.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term id="dig"><command>dig</command></term>
+ <listitem>
+ <para>
+ The domain information groper (<command>dig</command>)
+ is the most versatile and complete of these lookup tools.
+ It has two modes: simple interactive
+ mode for a single query, and batch mode which executes a
+ query for
+ each in a list of several query lines. All query options are
+ accessible
+ from the command line.
+ </para>
+ <cmdsynopsis label="Usage">
+ <command>dig</command>
+ <arg>@<replaceable>server</replaceable></arg>
+ <arg choice="plain"><replaceable>domain</replaceable></arg>
+ <arg><replaceable>query-type</replaceable></arg>
+ <arg><replaceable>query-class</replaceable></arg>
+ <arg>+<replaceable>query-option</replaceable></arg>
+ <arg>-<replaceable>dig-option</replaceable></arg>
+ <arg>%<replaceable>comment</replaceable></arg>
+ </cmdsynopsis>
+ <para>
+ The usual simple use of dig will take the form
+ </para>
+ <simpara>
+ <command>dig @server domain query-type query-class</command>
+ </simpara>
+ <para>
+ For more information and a list of available commands and
+ options, see the <command>dig</command> man
+ page.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>host</command></term>
+ <listitem>
+ <para>
+ The <command>host</command> utility emphasizes
+ simplicity
+ and ease of use. By default, it converts
+ between host names and Internet addresses, but its
+ functionality
+ can be extended with the use of options.
+ </para>
+ <cmdsynopsis label="Usage">
+ <command>host</command>
+ <arg>-aCdlnrsTwv</arg>
+ <arg>-c <replaceable>class</replaceable></arg>
+ <arg>-N <replaceable>ndots</replaceable></arg>
+ <arg>-t <replaceable>type</replaceable></arg>
+ <arg>-W <replaceable>timeout</replaceable></arg>
+ <arg>-R <replaceable>retries</replaceable></arg>
+ <arg>-m <replaceable>flag</replaceable></arg>
+ <arg>-4</arg>
+ <arg>-6</arg>
+ <arg choice="plain"><replaceable>hostname</replaceable></arg>
+ <arg><replaceable>server</replaceable></arg>
+ </cmdsynopsis>
+ <para>
+ For more information and a list of available commands and
+ options, see the <command>host</command> man
+ page.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>nslookup</command></term>
+ <listitem>
+ <para><command>nslookup</command>
+ has two modes: interactive and
+ non-interactive. Interactive mode allows the user to
+ query name servers for information about various
+ hosts and domains or to print a list of hosts in a
+ domain. Non-interactive mode is used to print just
+ the name and requested information for a host or
+ domain.
+ </para>
+ <cmdsynopsis label="Usage">
+ <command>nslookup</command>
+ <arg rep="repeat">-option</arg>
+ <group>
+ <arg><replaceable>host-to-find</replaceable></arg>
+ <arg>- <arg>server</arg></arg>
+ </group>
+ </cmdsynopsis>
+ <para>
+ Interactive mode is entered when no arguments are given (the
+ default name server will be used) or when the first argument
+ is a
+ hyphen (`-') and the second argument is the host name or
+ Internet address
+ of a name server.
+ </para>
+ <para>
+ Non-interactive mode is used when the name or Internet
+ address
+ of the host to be looked up is given as the first argument.
+ The
+ optional second argument specifies the host name or address
+ of a name server.
+ </para>
+ <para>
+ Due to its arcane user interface and frequently inconsistent
+ behavior, we do not recommend the use of <command>nslookup</command>.
+ Use <command>dig</command> instead.
+ </para>
+ </listitem>
+
+ </varlistentry>
+ </variablelist>
+ </sect3>
+
+ <sect3 id="admin_tools">
+ <title>Administrative Tools</title>
+ <para>
+ Administrative tools play an integral part in the management
+ of a server.
+ </para>
+ <variablelist>
+ <varlistentry id="named-checkconf" xreflabel="Named Configuration Checking application">
+
+ <term><command>named-checkconf</command></term>
+ <listitem>
+ <para>
+ The <command>named-checkconf</command> program
+ checks the syntax of a <filename>named.conf</filename> file.
+ </para>
+ <cmdsynopsis label="Usage">
+ <command>named-checkconf</command>
+ <arg>-jvz</arg>
+ <arg>-t <replaceable>directory</replaceable></arg>
+ <arg><replaceable>filename</replaceable></arg>
+ </cmdsynopsis>
+ </listitem>
+ </varlistentry>
+ <varlistentry id="named-checkzone" xreflabel="Zone Checking application">
+
+ <term><command>named-checkzone</command></term>
+ <listitem>
+ <para>
+ The <command>named-checkzone</command> program
+ checks a master file for
+ syntax and consistency.
+ </para>
+ <cmdsynopsis label="Usage">
+ <command>named-checkzone</command>
+ <arg>-djqvD</arg>
+ <arg>-c <replaceable>class</replaceable></arg>
+ <arg>-o <replaceable>output</replaceable></arg>
+ <arg>-t <replaceable>directory</replaceable></arg>
+ <arg>-w <replaceable>directory</replaceable></arg>
+ <arg>-k <replaceable>(ignore|warn|fail)</replaceable></arg>
+ <arg>-n <replaceable>(ignore|warn|fail)</replaceable></arg>
+ <arg>-W <replaceable>(ignore|warn)</replaceable></arg>
+ <arg choice="plain"><replaceable>zone</replaceable></arg>
+ <arg><replaceable>filename</replaceable></arg>
+ </cmdsynopsis>
+ </listitem>
+ </varlistentry>
+ <varlistentry id="named-compilezone" xreflabel="Zone Compilation application">
+ <term><command>named-compilezone</command></term>
+ <listitem>
+ <para>
+ Similar to <command>named-checkzone,</command> but
+ it always dumps the zone content to a specified file
+ (typically in a different format).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry id="rndc" xreflabel="Remote Name Daemon Control application">
+
+ <term><command>rndc</command></term>
+ <listitem>
+ <para>
+ The remote name daemon control
+ (<command>rndc</command>) program allows the
+ system
+ administrator to control the operation of a name server.
+ Since <acronym>BIND</acronym> 9.2, <command>rndc</command>
+ supports all the commands of the BIND 8 <command>ndc</command>
+ utility except <command>ndc start</command> and
+ <command>ndc restart</command>, which were also
+ not supported in <command>ndc</command>'s
+ channel mode.
+ If you run <command>rndc</command> without any
+ options
+ it will display a usage message as follows:
+ </para>
+ <cmdsynopsis label="Usage">
+ <command>rndc</command>
+ <arg>-c <replaceable>config</replaceable></arg>
+ <arg>-s <replaceable>server</replaceable></arg>
+ <arg>-p <replaceable>port</replaceable></arg>
+ <arg>-y <replaceable>key</replaceable></arg>
+ <arg choice="plain"><replaceable>command</replaceable></arg>
+ <arg rep="repeat"><replaceable>command</replaceable></arg>
+ </cmdsynopsis>
+ <para>The <command>command</command>
+ is one of the following:
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><userinput>reload</userinput></term>
+ <listitem>
+ <para>
+ Reload configuration file and zones.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>reload <replaceable>zone</replaceable>
+ <optional><replaceable>class</replaceable>
+ <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Reload the given zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>refresh <replaceable>zone</replaceable>
+ <optional><replaceable>class</replaceable>
+ <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Schedule zone maintenance for the given zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>retransfer <replaceable>zone</replaceable>
+
+ <optional><replaceable>class</replaceable>
+ <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Retransfer the given zone from the master.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+
+ <term><userinput>freeze
+ <optional><replaceable>zone</replaceable>
+ <optional><replaceable>class</replaceable>
+ <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Suspend updates to a dynamic zone. If no zone is
+ specified,
+ then all zones are suspended. This allows manual
+ edits to be made to a zone normally updated by dynamic
+ update. It
+ also causes changes in the journal file to be synced
+ into the master
+ and the journal file to be removed. All dynamic
+ update attempts will
+ be refused while the zone is frozen.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>thaw
+ <optional><replaceable>zone</replaceable>
+ <optional><replaceable>class</replaceable>
+ <optional><replaceable>view</replaceable></optional></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Enable updates to a frozen dynamic zone. If no zone
+ is
+ specified, then all frozen zones are enabled. This
+ causes
+ the server to reload the zone from disk, and
+ re-enables dynamic updates
+ after the load has completed. After a zone is thawed,
+ dynamic updates
+ will no longer be refused.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>notify <replaceable>zone</replaceable>
+ <optional><replaceable>class</replaceable>
+ <optional><replaceable>view</replaceable></optional></optional></userinput></term>
+ <listitem>
+ <para>
+ Resend NOTIFY messages for the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>reconfig</userinput></term>
+ <listitem>
+ <para>
+ Reload the configuration file and load new zones,
+ but do not reload existing zone files even if they
+ have changed.
+ This is faster than a full <command>reload</command> when there
+ is a large number of zones because it avoids the need
+ to examine the
+ modification times of the zones files.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>stats</userinput></term>
+ <listitem>
+ <para>
+ Write server statistics to the statistics file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>querylog</userinput></term>
+ <listitem>
+ <para>
+ Toggle query logging. Query logging can also be enabled
+ by explicitly directing the <command>queries</command>
+ <command>category</command> to a
+ <command>channel</command> in the
+ <command>logging</command> section of
+ <filename>named.conf</filename> or by specifying
+ <command>querylog yes;</command> in the
+ <command>options</command> section of
+ <filename>named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>dumpdb
+ <optional>-all|-cache|-zone</optional>
+ <optional><replaceable>view ...</replaceable></optional></userinput></term>
+ <listitem>
+ <para>
+ Dump the server's caches (default) and/or zones to
+ the
+ dump file for the specified views. If no view is
+ specified, all
+ views are dumped.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>stop <optional>-p</optional></userinput></term>
+ <listitem>
+ <para>
+ Stop the server, making sure any recent changes
+ made through dynamic update or IXFR are first saved to
+ the master files of the updated zones.
+ If -p is specified named's process id is returned.
+ This allows an external process to determine when named
+ had completed stopping.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>halt <optional>-p</optional></userinput></term>
+ <listitem>
+ <para>
+ Stop the server immediately. Recent changes
+ made through dynamic update or IXFR are not saved to
+ the master files, but will be rolled forward from the
+ journal files when the server is restarted.
+ If -p is specified named's process id is returned.
+ This allows an external process to determine when named
+ had completed halting.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>trace</userinput></term>
+ <listitem>
+ <para>
+ Increment the servers debugging level by one.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>trace <replaceable>level</replaceable></userinput></term>
+ <listitem>
+ <para>
+ Sets the server's debugging level to an explicit
+ value.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>notrace</userinput></term>
+ <listitem>
+ <para>
+ Sets the server's debugging level to 0.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>flush</userinput></term>
+ <listitem>
+ <para>
+ Flushes the server's cache.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>flushname</userinput> <replaceable>name</replaceable></term>
+ <listitem>
+ <para>
+ Flushes the given name from the server's cache.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>status</userinput></term>
+ <listitem>
+ <para>
+ Display status of the server.
+ Note that the number of zones includes the internal <command>bind/CH</command> zone
+ and the default <command>./IN</command>
+ hint zone if there is not an
+ explicit root zone configured.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>recursing</userinput></term>
+ <listitem>
+ <para>
+ Dump the list of queries named is currently recursing
+ on.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><userinput>validation
+ <optional>on|off</optional>
+ <optional><replaceable>view ...</replaceable></optional>
+ </userinput></term>
+ <listitem>
+ <para>
+ Enable or disable DNSSEC validation.
+ Note <command>dnssec-enable</command> also needs to be
+ set to <userinput>yes</userinput> to be effective.
+ It defaults to enabled.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+ A configuration file is required, since all
+ communication with the server is authenticated with
+ digital signatures that rely on a shared secret, and
+ there is no way to provide that secret other than with a
+ configuration file. The default location for the
+ <command>rndc</command> configuration file is
+ <filename>/etc/rndc.conf</filename>, but an
+ alternate
+ location can be specified with the <option>-c</option>
+ option. If the configuration file is not found,
+ <command>rndc</command> will also look in
+ <filename>/etc/rndc.key</filename> (or whatever
+ <varname>sysconfdir</varname> was defined when
+ the <acronym>BIND</acronym> build was
+ configured).
+ The <filename>rndc.key</filename> file is
+ generated by
+ running <command>rndc-confgen -a</command> as
+ described in
+ <xref linkend="controls_statement_definition_and_usage"/>.
+ </para>
+
+ <para>
+ The format of the configuration file is similar to
+ that of <filename>named.conf</filename>, but
+ limited to
+ only four statements, the <command>options</command>,
+ <command>key</command>, <command>server</command> and
+ <command>include</command>
+ statements. These statements are what associate the
+ secret keys to the servers with which they are meant to
+ be shared. The order of statements is not
+ significant.
+ </para>
+
+ <para>
+ The <command>options</command> statement has
+ three clauses:
+ <command>default-server</command>, <command>default-key</command>,
+ and <command>default-port</command>.
+ <command>default-server</command> takes a
+ host name or address argument and represents the server
+ that will
+ be contacted if no <option>-s</option>
+ option is provided on the command line.
+ <command>default-key</command> takes
+ the name of a key as its argument, as defined by a <command>key</command> statement.
+ <command>default-port</command> specifies the
+ port to which
+ <command>rndc</command> should connect if no
+ port is given on the command line or in a
+ <command>server</command> statement.
+ </para>
+
+ <para>
+ The <command>key</command> statement defines a
+ key to be used
+ by <command>rndc</command> when authenticating
+ with
+ <command>named</command>. Its syntax is
+ identical to the
+ <command>key</command> statement in named.conf.
+ The keyword <userinput>key</userinput> is
+ followed by a key name, which must be a valid
+ domain name, though it need not actually be hierarchical;
+ thus,
+ a string like "<userinput>rndc_key</userinput>" is a valid
+ name.
+ The <command>key</command> statement has two
+ clauses:
+ <command>algorithm</command> and <command>secret</command>.
+ While the configuration parser will accept any string as the
+ argument
+ to algorithm, currently only the string "<userinput>hmac-md5</userinput>"
+ has any meaning. The secret is a base-64 encoded string
+ as specified in RFC 3548.
+ </para>
+
+ <para>
+ The <command>server</command> statement
+ associates a key
+ defined using the <command>key</command>
+ statement with a server.
+ The keyword <userinput>server</userinput> is followed by a
+ host name or address. The <command>server</command> statement
+ has two clauses: <command>key</command> and <command>port</command>.
+ The <command>key</command> clause specifies the
+ name of the key
+ to be used when communicating with this server, and the
+ <command>port</command> clause can be used to
+ specify the port <command>rndc</command> should
+ connect
+ to on the server.
+ </para>
+
+ <para>
+ A sample minimal configuration file is as follows:
+ </para>
+
+<programlisting>
+key rndc_key {
+ algorithm "hmac-md5";
+ secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
+};
+options {
+ default-server 127.0.0.1;
+ default-key rndc_key;
+};
+</programlisting>
+
+ <para>
+ This file, if installed as <filename>/etc/rndc.conf</filename>,
+ would allow the command:
+ </para>
+
+ <para>
+ <prompt>$ </prompt><userinput>rndc reload</userinput>
+ </para>
+
+ <para>
+ to connect to 127.0.0.1 port 953 and cause the name server
+ to reload, if a name server on the local machine were
+ running with
+ following controls statements:
+ </para>
+
+<programlisting>
+controls {
+ inet 127.0.0.1 allow { localhost; } keys { rndc_key; };
+};
+</programlisting>
+
+ <para>
+ and it had an identical key statement for
+ <literal>rndc_key</literal>.
+ </para>
+
+ <para>
+ Running the <command>rndc-confgen</command>
+ program will
+ conveniently create a <filename>rndc.conf</filename>
+ file for you, and also display the
+ corresponding <command>controls</command>
+ statement that you need to
+ add to <filename>named.conf</filename>.
+ Alternatively,
+ you can run <command>rndc-confgen -a</command>
+ to set up
+ a <filename>rndc.key</filename> file and not
+ modify
+ <filename>named.conf</filename> at all.
+ </para>
+
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </sect3>
+ </sect2>
+ <sect2>
+
+ <title>Signals</title>
+ <para>
+ Certain UNIX signals cause the name server to take specific
+ actions, as described in the following table. These signals can
+ be sent using the <command>kill</command> command.
+ </para>
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.125in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="4.000in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>SIGHUP</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Causes the server to read <filename>named.conf</filename> and
+ reload the database.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>SIGTERM</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Causes the server to clean up and exit.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>SIGINT</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Causes the server to clean up and exit.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </sect2>
+ </sect1>
+ </chapter>
+
+ <chapter id="Bv9ARM.ch04">
+ <title>Advanced DNS Features</title>
+
+ <sect1 id="notify">
+
+ <title>Notify</title>
+ <para>
+ <acronym>DNS</acronym> NOTIFY is a mechanism that allows master
+ servers to notify their slave servers of changes to a zone's data. In
+ response to a <command>NOTIFY</command> from a master server, the
+ slave will check to see that its version of the zone is the
+ current version and, if not, initiate a zone transfer.
+ </para>
+
+ <para>
+ For more information about <acronym>DNS</acronym>
+ <command>NOTIFY</command>, see the description of the
+ <command>notify</command> option in <xref linkend="boolean_options"/> and
+ the description of the zone option <command>also-notify</command> in
+ <xref linkend="zone_transfers"/>. The <command>NOTIFY</command>
+ protocol is specified in RFC 1996.
+ </para>
+
+ <note>
+ As a slave zone can also be a master to other slaves, named,
+ by default, sends <command>NOTIFY</command> messages for every zone
+ it loads. Specifying <command>notify master-only;</command> will
+ cause named to only send <command>NOTIFY</command> for master
+ zones that it loads.
+ </note>
+
+ </sect1>
+
+ <sect1 id="dynamic_update">
+ <title>Dynamic Update</title>
+
+ <para>
+ Dynamic Update is a method for adding, replacing or deleting
+ records in a master server by sending it a special form of DNS
+ messages. The format and meaning of these messages is specified
+ in RFC 2136.
+ </para>
+
+ <para>
+ Dynamic update is enabled by including an
+ <command>allow-update</command> or <command>update-policy</command>
+ clause in the <command>zone</command> statement. The
+ <command>tkey-gssapi-credential</command> and
+ <command>tkey-domain</command> clauses in the
+ <command>options</command> statement enable the
+ server to negotiate keys that can be matched against those
+ in <command>update-policy</command> or
+ <command>allow-update</command>.
+ </para>
+
+ <para>
+ Updating of secure zones (zones using DNSSEC) follows RFC
+ 3007: RRSIG, NSEC and NSEC3 records affected by updates are
+ automatically regenerated by the server using an online
+ zone key. Update authorization is based on transaction
+ signatures and an explicit server policy.
+ </para>
+
+ <sect2 id="journal">
+ <title>The journal file</title>
+
+ <para>
+ All changes made to a zone using dynamic update are stored
+ in the zone's journal file. This file is automatically created
+ by the server when the first dynamic update takes place.
+ The name of the journal file is formed by appending the extension
+ <filename>.jnl</filename> to the name of the
+ corresponding zone
+ file unless specifically overridden. The journal file is in a
+ binary format and should not be edited manually.
+ </para>
+
+ <para>
+ The server will also occasionally write ("dump")
+ the complete contents of the updated zone to its zone file.
+ This is not done immediately after
+ each dynamic update, because that would be too slow when a large
+ zone is updated frequently. Instead, the dump is delayed by
+ up to 15 minutes, allowing additional updates to take place.
+ </para>
+
+ <para>
+ When a server is restarted after a shutdown or crash, it will replay
+ the journal file to incorporate into the zone any updates that
+ took
+ place after the last zone dump.
+ </para>
+
+ <para>
+ Changes that result from incoming incremental zone transfers are
+ also
+ journalled in a similar way.
+ </para>
+
+ <para>
+ The zone files of dynamic zones cannot normally be edited by
+ hand because they are not guaranteed to contain the most recent
+ dynamic changes &mdash; those are only in the journal file.
+ The only way to ensure that the zone file of a dynamic zone
+ is up to date is to run <command>rndc stop</command>.
+ </para>
+
+ <para>
+ If you have to make changes to a dynamic zone
+ manually, the following procedure will work: Disable dynamic updates
+ to the zone using
+ <command>rndc freeze <replaceable>zone</replaceable></command>.
+ This will also remove the zone's <filename>.jnl</filename> file
+ and update the master file. Edit the zone file. Run
+ <command>rndc thaw <replaceable>zone</replaceable></command>
+ to reload the changed zone and re-enable dynamic updates.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="incremental_zone_transfers">
+ <title>Incremental Zone Transfers (IXFR)</title>
+
+ <para>
+ The incremental zone transfer (IXFR) protocol is a way for
+ slave servers to transfer only changed data, instead of having to
+ transfer the entire zone. The IXFR protocol is specified in RFC
+ 1995. See <xref linkend="proposed_standards"/>.
+ </para>
+
+ <para>
+ When acting as a master, <acronym>BIND</acronym> 9
+ supports IXFR for those zones
+ where the necessary change history information is available. These
+ include master zones maintained by dynamic update and slave zones
+ whose data was obtained by IXFR. For manually maintained master
+ zones, and for slave zones obtained by performing a full zone
+ transfer (AXFR), IXFR is supported only if the option
+ <command>ixfr-from-differences</command> is set
+ to <userinput>yes</userinput>.
+ </para>
+
+ <para>
+ When acting as a slave, <acronym>BIND</acronym> 9 will
+ attempt to use IXFR unless
+ it is explicitly disabled. For more information about disabling
+ IXFR, see the description of the <command>request-ixfr</command> clause
+ of the <command>server</command> statement.
+ </para>
+ </sect1>
+
+ <sect1>
+ <title>Split DNS</title>
+ <para>
+ Setting up different views, or visibility, of the DNS space to
+ internal and external resolvers is usually referred to as a
+ <emphasis>Split DNS</emphasis> setup. There are several
+ reasons an organization would want to set up its DNS this way.
+ </para>
+ <para>
+ One common reason for setting up a DNS system this way is
+ to hide "internal" DNS information from "external" clients on the
+ Internet. There is some debate as to whether or not this is actually
+ useful.
+ Internal DNS information leaks out in many ways (via email headers,
+ for example) and most savvy "attackers" can find the information
+ they need using other means.
+ However, since listing addresses of internal servers that
+ external clients cannot possibly reach can result in
+ connection delays and other annoyances, an organization may
+ choose to use a Split DNS to present a consistent view of itself
+ to the outside world.
+ </para>
+ <para>
+ Another common reason for setting up a Split DNS system is
+ to allow internal networks that are behind filters or in RFC 1918
+ space (reserved IP space, as documented in RFC 1918) to resolve DNS
+ on the Internet. Split DNS can also be used to allow mail from outside
+ back in to the internal network.
+ </para>
+ <sect2>
+ <title>Example split DNS setup</title>
+ <para>
+ Let's say a company named <emphasis>Example, Inc.</emphasis>
+ (<literal>example.com</literal>)
+ has several corporate sites that have an internal network with
+ reserved
+ Internet Protocol (IP) space and an external demilitarized zone (DMZ),
+ or "outside" section of a network, that is available to the public.
+ </para>
+ <para>
+ <emphasis>Example, Inc.</emphasis> wants its internal clients
+ to be able to resolve external hostnames and to exchange mail with
+ people on the outside. The company also wants its internal resolvers
+ to have access to certain internal-only zones that are not available
+ at all outside of the internal network.
+ </para>
+ <para>
+ In order to accomplish this, the company will set up two sets
+ of name servers. One set will be on the inside network (in the
+ reserved
+ IP space) and the other set will be on bastion hosts, which are
+ "proxy"
+ hosts that can talk to both sides of its network, in the DMZ.
+ </para>
+ <para>
+ The internal servers will be configured to forward all queries,
+ except queries for <filename>site1.internal</filename>, <filename>site2.internal</filename>, <filename>site1.example.com</filename>,
+ and <filename>site2.example.com</filename>, to the servers
+ in the
+ DMZ. These internal servers will have complete sets of information
+ for <filename>site1.example.com</filename>, <filename>site2.example.com</filename>,<emphasis/> <filename>site1.internal</filename>,
+ and <filename>site2.internal</filename>.
+ </para>
+ <para>
+ To protect the <filename>site1.internal</filename> and <filename>site2.internal</filename> domains,
+ the internal name servers must be configured to disallow all queries
+ to these domains from any external hosts, including the bastion
+ hosts.
+ </para>
+ <para>
+ The external servers, which are on the bastion hosts, will
+ be configured to serve the "public" version of the <filename>site1</filename> and <filename>site2.example.com</filename> zones.
+ This could include things such as the host records for public servers
+ (<filename>www.example.com</filename> and <filename>ftp.example.com</filename>),
+ and mail exchange (MX) records (<filename>a.mx.example.com</filename> and <filename>b.mx.example.com</filename>).
+ </para>
+ <para>
+ In addition, the public <filename>site1</filename> and <filename>site2.example.com</filename> zones
+ should have special MX records that contain wildcard (`*') records
+ pointing to the bastion hosts. This is needed because external mail
+ servers do not have any other way of looking up how to deliver mail
+ to those internal hosts. With the wildcard records, the mail will
+ be delivered to the bastion host, which can then forward it on to
+ internal hosts.
+ </para>
+ <para>
+ Here's an example of a wildcard MX record:
+ </para>
+ <programlisting>* IN MX 10 external1.example.com.</programlisting>
+ <para>
+ Now that they accept mail on behalf of anything in the internal
+ network, the bastion hosts will need to know how to deliver mail
+ to internal hosts. In order for this to work properly, the resolvers
+ on
+ the bastion hosts will need to be configured to point to the internal
+ name servers for DNS resolution.
+ </para>
+ <para>
+ Queries for internal hostnames will be answered by the internal
+ servers, and queries for external hostnames will be forwarded back
+ out to the DNS servers on the bastion hosts.
+ </para>
+ <para>
+ In order for all this to work properly, internal clients will
+ need to be configured to query <emphasis>only</emphasis> the internal
+ name servers for DNS queries. This could also be enforced via
+ selective
+ filtering on the network.
+ </para>
+ <para>
+ If everything has been set properly, <emphasis>Example, Inc.</emphasis>'s
+ internal clients will now be able to:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Look up any hostnames in the <literal>site1</literal>
+ and
+ <literal>site2.example.com</literal> zones.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Look up any hostnames in the <literal>site1.internal</literal> and
+ <literal>site2.internal</literal> domains.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>Look up any hostnames on the Internet.</simpara>
+ </listitem>
+ <listitem>
+ <simpara>Exchange mail with both internal and external people.</simpara>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Hosts on the Internet will be able to:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Look up any hostnames in the <literal>site1</literal>
+ and
+ <literal>site2.example.com</literal> zones.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Exchange mail with anyone in the <literal>site1</literal> and
+ <literal>site2.example.com</literal> zones.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Here is an example configuration for the setup we just
+ described above. Note that this is only configuration information;
+ for information on how to configure your zone files, see <xref linkend="sample_configuration"/>.
+ </para>
+
+ <para>
+ Internal DNS server config:
+ </para>
+
+<programlisting>
+
+acl internals { 172.16.72.0/24; 192.168.1.0/24; };
+
+acl externals { <varname>bastion-ips-go-here</varname>; };
+
+options {
+ ...
+ ...
+ forward only;
+ forwarders { // forward to external servers
+ <varname>bastion-ips-go-here</varname>;
+ };
+ allow-transfer { none; }; // sample allow-transfer (no one)
+ allow-query { internals; externals; }; // restrict query access
+ allow-recursion { internals; }; // restrict recursion
+ ...
+ ...
+};
+
+zone "site1.example.com" { // sample master zone
+ type master;
+ file "m/site1.example.com";
+ forwarders { }; // do normal iterative
+ // resolution (do not forward)
+ allow-query { internals; externals; };
+ allow-transfer { internals; };
+};
+
+zone "site2.example.com" { // sample slave zone
+ type slave;
+ file "s/site2.example.com";
+ masters { 172.16.72.3; };
+ forwarders { };
+ allow-query { internals; externals; };
+ allow-transfer { internals; };
+};
+
+zone "site1.internal" {
+ type master;
+ file "m/site1.internal";
+ forwarders { };
+ allow-query { internals; };
+ allow-transfer { internals; }
+};
+
+zone "site2.internal" {
+ type slave;
+ file "s/site2.internal";
+ masters { 172.16.72.3; };
+ forwarders { };
+ allow-query { internals };
+ allow-transfer { internals; }
+};
+</programlisting>
+
+ <para>
+ External (bastion host) DNS server config:
+ </para>
+
+<programlisting>
+acl internals { 172.16.72.0/24; 192.168.1.0/24; };
+
+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
+ ...
+ ...
+};
+
+zone "site1.example.com" { // sample slave zone
+ type master;
+ file "m/site1.foo.com";
+ allow-transfer { internals; externals; };
+};
+
+zone "site2.example.com" {
+ type slave;
+ file "s/site2.foo.com";
+ masters { another_bastion_host_maybe; };
+ allow-transfer { internals; externals; }
+};
+</programlisting>
+
+ <para>
+ In the <filename>resolv.conf</filename> (or equivalent) on
+ the bastion host(s):
+ </para>
+
+<programlisting>
+search ...
+nameserver 172.16.72.2
+nameserver 172.16.72.3
+nameserver 172.16.72.4
+</programlisting>
+
+ </sect2>
+ </sect1>
+ <sect1 id="tsig">
+ <title>TSIG</title>
+ <para>
+ This is a short guide to setting up Transaction SIGnatures
+ (TSIG) based transaction security in <acronym>BIND</acronym>. It describes changes
+ to the configuration file as well as what changes are required for
+ different features, including the process of creating transaction
+ keys and using transaction signatures with <acronym>BIND</acronym>.
+ </para>
+ <para>
+ <acronym>BIND</acronym> primarily supports TSIG for server
+ to server communication.
+ This includes zone transfer, notify, and recursive query messages.
+ Resolvers based on newer versions of <acronym>BIND</acronym> 8 have limited support
+ for TSIG.
+ </para>
+
+ <para>
+ TSIG can also be useful for dynamic update. A primary
+ server for a dynamic zone should control access to the dynamic
+ update service, but IP-based access control is insufficient.
+ The cryptographic access control provided by TSIG
+ is far superior. The <command>nsupdate</command>
+ program supports TSIG via the <option>-k</option> and
+ <option>-y</option> command line options or inline by use
+ of the <command>key</command>.
+ </para>
+
+ <sect2>
+ <title>Generate Shared Keys for Each Pair of Hosts</title>
+ <para>
+ A shared secret is generated to be shared between <emphasis>host1</emphasis> and <emphasis>host2</emphasis>.
+ An arbitrary key name is chosen: "host1-host2.". The key name must
+ be the same on both hosts.
+ </para>
+ <sect3>
+ <title>Automatic Generation</title>
+ <para>
+ The following command will generate a 128-bit (16 byte) HMAC-MD5
+ key as described above. Longer keys are better, but shorter keys
+ are easier to read. Note that the maximum key length is 512 bits;
+ keys longer than that will be digested with MD5 to produce a
+ 128-bit key.
+ </para>
+ <para>
+ <userinput>dnssec-keygen -a hmac-md5 -b 128 -n HOST host1-host2.</userinput>
+ </para>
+ <para>
+ The key is in the file <filename>Khost1-host2.+157+00000.private</filename>.
+ Nothing directly uses this file, but the base-64 encoded string
+ following "<literal>Key:</literal>"
+ can be extracted from the file and used as a shared secret:
+ </para>
+ <programlisting>Key: La/E5CjG9O+os1jq0a2jdA==</programlisting>
+ <para>
+ The string "<literal>La/E5CjG9O+os1jq0a2jdA==</literal>" can
+ be used as the shared secret.
+ </para>
+ </sect3>
+ <sect3>
+ <title>Manual Generation</title>
+ <para>
+ The shared secret is simply a random sequence of bits, encoded
+ in base-64. Most ASCII strings are valid base-64 strings (assuming
+ the length is a multiple of 4 and only valid characters are used),
+ so the shared secret can be manually generated.
+ </para>
+ <para>
+ Also, a known string can be run through <command>mmencode</command> or
+ a similar program to generate base-64 encoded data.
+ </para>
+ </sect3>
+ </sect2>
+ <sect2>
+ <title>Copying the Shared Secret to Both Machines</title>
+ <para>
+ This is beyond the scope of DNS. A secure transport mechanism
+ should be used. This could be secure FTP, ssh, telephone, etc.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Informing the Servers of the Key's Existence</title>
+ <para>
+ Imagine <emphasis>host1</emphasis> and <emphasis>host 2</emphasis>
+ are
+ both servers. The following is added to each server's <filename>named.conf</filename> file:
+ </para>
+
+<programlisting>
+key host1-host2. {
+ algorithm hmac-md5;
+ secret "La/E5CjG9O+os1jq0a2jdA==";
+};
+</programlisting>
+
+ <para>
+ The algorithm, hmac-md5, is the only one supported by <acronym>BIND</acronym>.
+ The secret is the one generated above. Since this is a secret, it
+ is recommended that either <filename>named.conf</filename> be non-world
+ readable, or the key directive be added to a non-world readable
+ file that is included by
+ <filename>named.conf</filename>.
+ </para>
+ <para>
+ At this point, the key is recognized. This means that if the
+ server receives a message signed by this key, it can verify the
+ signature. If the signature is successfully verified, the
+ response is signed by the same key.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Instructing the Server to Use the Key</title>
+ <para>
+ 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 <filename>named.conf</filename> file
+ for <emphasis>host1</emphasis>, if the IP address of <emphasis>host2</emphasis> is
+ 10.1.2.3:
+ </para>
+
+<programlisting>
+server 10.1.2.3 {
+ keys { host1-host2. ;};
+};
+</programlisting>
+
+ <para>
+ Multiple keys may be present, but only the first is used.
+ This directive does not contain any secrets, so it may be in a
+ world-readable
+ file.
+ </para>
+ <para>
+ If <emphasis>host1</emphasis> sends a message that is a request
+ to that address, the message will be signed with the specified key. <emphasis>host1</emphasis> will
+ expect any responses to signed messages to be signed with the same
+ key.
+ </para>
+ <para>
+ A similar statement must be present in <emphasis>host2</emphasis>'s
+ configuration file (with <emphasis>host1</emphasis>'s address) for <emphasis>host2</emphasis> to
+ sign request messages to <emphasis>host1</emphasis>.
+ </para>
+ </sect2>
+ <sect2>
+ <title>TSIG Key Based Access Control</title>
+ <para>
+ <acronym>BIND</acronym> allows IP addresses and ranges
+ to be specified in ACL
+ definitions and
+ <command>allow-{ query | transfer | update }</command>
+ directives.
+ This has been extended to allow TSIG keys also. The above key would
+ be denoted <command>key host1-host2.</command>
+ </para>
+ <para>
+ An example of an allow-update directive would be:
+ </para>
+
+<programlisting>
+allow-update { key host1-host2. ;};
+</programlisting>
+
+ <para>
+ This allows dynamic updates to succeed only if the request
+ was signed by a key named "<command>host1-host2.</command>".
+ </para>
+
+ <para>
+ You may want to read about the more powerful
+ <command>update-policy</command> statement in
+ <xref linkend="dynamic_update_policies"/>.
+ </para>
+
+ </sect2>
+ <sect2>
+ <title>Errors</title>
+
+ <para>
+ The processing of TSIG signed messages can result in
+ several errors. If a signed message is sent to a non-TSIG aware
+ server, a FORMERR (format error) will be returned, since the server will not
+ understand the record. This is a result of misconfiguration,
+ since the server must be explicitly configured to send a TSIG
+ signed message to a specific server.
+ </para>
+
+ <para>
+ If a TSIG aware server receives a message signed by an
+ unknown key, the response will be unsigned with the TSIG
+ extended error code set to BADKEY. If a TSIG aware server
+ receives a message with a signature that does not validate, the
+ response will be unsigned with the TSIG extended error code set
+ to BADSIG. If a TSIG aware server receives a message with a time
+ outside of the allowed range, the response will be signed with
+ the TSIG extended error code set to BADTIME, and the time values
+ will be adjusted so that the response can be successfully
+ verified. In any of these cases, the message's rcode (response code) is set to
+ NOTAUTH (not authenticated).
+ </para>
+
+ </sect2>
+ </sect1>
+ <sect1>
+ <title>TKEY</title>
+
+ <para><command>TKEY</command>
+ is a mechanism for automatically generating a shared secret
+ between two hosts. There are several "modes" of
+ <command>TKEY</command> that specify how the key is generated
+ or assigned. <acronym>BIND</acronym> 9 implements only one of
+ these modes, the Diffie-Hellman key exchange. Both hosts are
+ required to have a Diffie-Hellman KEY record (although this
+ record is not required to be present in a zone). The
+ <command>TKEY</command> process must use signed messages,
+ signed either by TSIG or SIG(0). The result of
+ <command>TKEY</command> is a shared secret that can be used to
+ sign messages with TSIG. <command>TKEY</command> can also be
+ used to delete shared secrets that it had previously
+ generated.
+ </para>
+
+ <para>
+ The <command>TKEY</command> process is initiated by a
+ client
+ or server by sending a signed <command>TKEY</command>
+ query
+ (including any appropriate KEYs) to a TKEY-aware server. The
+ server response, if it indicates success, will contain a
+ <command>TKEY</command> record and any appropriate keys.
+ After
+ this exchange, both participants have enough information to
+ determine the shared secret; the exact process depends on the
+ <command>TKEY</command> mode. When using the
+ Diffie-Hellman
+ <command>TKEY</command> mode, Diffie-Hellman keys are
+ exchanged,
+ and the shared secret is derived by both participants.
+ </para>
+
+ </sect1>
+ <sect1>
+ <title>SIG(0)</title>
+
+ <para>
+ <acronym>BIND</acronym> 9 partially supports DNSSEC SIG(0)
+ transaction signatures as specified in RFC 2535 and RFC2931.
+ SIG(0)
+ uses public/private keys to authenticate messages. Access control
+ is performed in the same manner as TSIG keys; privileges can be
+ granted or denied based on the key name.
+ </para>
+
+ <para>
+ When a SIG(0) signed message is received, it will only be
+ verified if the key is known and trusted by the server; the server
+ will not attempt to locate and/or validate the key.
+ </para>
+
+ <para>
+ SIG(0) signing of multiple-message TCP streams is not
+ supported.
+ </para>
+
+ <para>
+ The only tool shipped with <acronym>BIND</acronym> 9 that
+ generates SIG(0) signed messages is <command>nsupdate</command>.
+ </para>
+
+ </sect1>
+ <sect1 id="DNSSEC">
+ <title>DNSSEC</title>
+
+ <para>
+ Cryptographic authentication of DNS information is possible
+ through the DNS Security (<emphasis>DNSSEC-bis</emphasis>) extensions,
+ defined in RFC 4033, RFC 4034, and RFC 4035.
+ This section describes the creation and use of DNSSEC signed zones.
+ </para>
+
+ <para>
+ In order to set up a DNSSEC secure zone, there are a series
+ of steps which must be followed. <acronym>BIND</acronym>
+ 9 ships
+ with several tools
+ that are used in this process, which are explained in more detail
+ below. In all cases, the <option>-h</option> option prints a
+ full list of parameters. Note that the DNSSEC tools require the
+ keyset files to be in the working directory or the
+ directory specified by the <option>-d</option> option, and
+ that the tools shipped with BIND 9.2.x and earlier are not compatible
+ with the current ones.
+ </para>
+
+ <para>
+ There must also be communication with the administrators of
+ the parent and/or child zone to transmit keys. A zone's security
+ status must be indicated by the parent zone for a DNSSEC capable
+ resolver to trust its data. This is done through the presence
+ or absence of a <literal>DS</literal> record at the
+ delegation
+ point.
+ </para>
+
+ <para>
+ For other servers to trust data in this zone, they must
+ either be statically configured with this zone's zone key or the
+ zone key of another zone above this one in the DNS tree.
+ </para>
+
+ <sect2>
+ <title>Generating Keys</title>
+
+ <para>
+ The <command>dnssec-keygen</command> program is used to
+ generate keys.
+ </para>
+
+ <para>
+ A secure zone must contain one or more zone keys. The
+ zone keys will sign all other records in the zone, as well as
+ the zone keys of any secure delegated zones. Zone keys must
+ have the same name as the zone, a name type of
+ <command>ZONE</command>, and must be usable for
+ authentication.
+ It is recommended that zone keys use a cryptographic algorithm
+ designated as "mandatory to implement" by the IETF; currently
+ the only one is RSASHA1.
+ </para>
+
+ <para>
+ The following command will generate a 768-bit RSASHA1 key for
+ the <filename>child.example</filename> zone:
+ </para>
+
+ <para>
+ <userinput>dnssec-keygen -a RSASHA1 -b 768 -n ZONE child.example.</userinput>
+ </para>
+
+ <para>
+ Two output files will be produced:
+ <filename>Kchild.example.+005+12345.key</filename> and
+ <filename>Kchild.example.+005+12345.private</filename>
+ (where
+ 12345 is an example of a key tag). The key filenames contain
+ the key name (<filename>child.example.</filename>),
+ algorithm (3
+ is DSA, 1 is RSAMD5, 5 is RSASHA1, etc.), and the key tag (12345 in
+ this case).
+ The private key (in the <filename>.private</filename>
+ file) is
+ used to generate signatures, and the public key (in the
+ <filename>.key</filename> file) is used for signature
+ verification.
+ </para>
+
+ <para>
+ To generate another key with the same properties (but with
+ a different key tag), repeat the above command.
+ </para>
+
+ <para>
+ The <command>dnssec-keyfromlabel</command> program is used
+ to get a key pair from a crypto hardware and build the key
+ files. Its usage is similar to <command>dnssec-keygen</command>.
+ </para>
+
+ <para>
+ The public keys should be inserted into the zone file by
+ including the <filename>.key</filename> files using
+ <command>$INCLUDE</command> statements.
+ </para>
+
+ </sect2>
+ <sect2>
+ <title>Signing the Zone</title>
+
+ <para>
+ The <command>dnssec-signzone</command> program is used
+ to sign a zone.
+ </para>
+
+ <para>
+ Any <filename>keyset</filename> files corresponding to
+ secure subzones should be present. The zone signer will
+ generate <literal>NSEC</literal>, <literal>NSEC3</literal>
+ and <literal>RRSIG</literal> records for the zone, as
+ well as <literal>DS</literal> for the child zones if
+ <literal>'-g'</literal> is specified. If <literal>'-g'</literal>
+ is not specified, then DS RRsets for the secure child
+ zones need to be added manually.
+ </para>
+
+ <para>
+ The following command signs the zone, assuming it is in a
+ file called <filename>zone.child.example</filename>. By
+ default, all zone keys which have an available private key are
+ used to generate signatures.
+ </para>
+
+ <para>
+ <userinput>dnssec-signzone -o child.example zone.child.example</userinput>
+ </para>
+
+ <para>
+ One output file is produced:
+ <filename>zone.child.example.signed</filename>. This
+ file
+ should be referenced by <filename>named.conf</filename>
+ as the
+ input file for the zone.
+ </para>
+
+ <para><command>dnssec-signzone</command>
+ will also produce a keyset and dsset files and optionally a
+ dlvset file. These are used to provide the parent zone
+ administrators with the <literal>DNSKEYs</literal> (or their
+ corresponding <literal>DS</literal> records) that are the
+ secure entry point to the zone.
+ </para>
+
+ </sect2>
+
+ <sect2>
+ <title>Configuring Servers</title>
+
+ <para>
+ To enable <command>named</command> to respond appropriately
+ to DNS requests from DNSSEC aware clients,
+ <command>dnssec-enable</command> must be set to yes.
+ </para>
+
+ <para>
+ To enable <command>named</command> to validate answers from
+ other servers both <command>dnssec-enable</command> and
+ <command>dnssec-validation</command> must be set and some
+ <command>trusted-keys</command> must be configured
+ into <filename>named.conf</filename>.
+ </para>
+
+ <para>
+ <command>trusted-keys</command> are copies of DNSKEY RRs
+ for zones that are used to form the first link in the
+ cryptographic chain of trust. All keys listed in
+ <command>trusted-keys</command> (and corresponding zones)
+ are deemed to exist and only the listed keys will be used
+ to validated the DNSKEY RRset that they are from.
+ </para>
+
+ <para>
+ <command>trusted-keys</command> are described in more detail
+ later in this document.
+ </para>
+
+ <para>
+ Unlike <acronym>BIND</acronym> 8, <acronym>BIND</acronym>
+ 9 does not verify signatures on load, so zone keys for
+ authoritative zones do not need to be specified in the
+ configuration file.
+ </para>
+
+ <para>
+ After DNSSEC gets established, a typical DNSSEC configuration
+ will look something like the following. It has a 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.
+ </para>
+
+<programlisting>
+trusted-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";
+};
+
+options {
+ ...
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+</programlisting>
+
+ <note>
+ None of the keys listed in this example are valid. In particular,
+ the root key is not valid.
+ </note>
+
+ </sect2>
+
+ </sect1>
+ <sect1>
+ <title>IPv6 Support in <acronym>BIND</acronym> 9</title>
+
+ <para>
+ <acronym>BIND</acronym> 9 fully supports all currently
+ defined forms of IPv6
+ name to address and address to name lookups. It will also use
+ IPv6 addresses to make queries when running on an IPv6 capable
+ system.
+ </para>
+
+ <para>
+ For forward lookups, <acronym>BIND</acronym> 9 supports
+ only AAAA records. RFC 3363 deprecated the use of A6 records,
+ and client-side support for A6 records was accordingly removed
+ from <acronym>BIND</acronym> 9.
+ However, authoritative <acronym>BIND</acronym> 9 name servers still
+ load zone files containing A6 records correctly, answer queries
+ for A6 records, and accept zone transfer for a zone containing A6
+ records.
+ </para>
+
+ <para>
+ For IPv6 reverse lookups, <acronym>BIND</acronym> 9 supports
+ the traditional "nibble" format used in the
+ <emphasis>ip6.arpa</emphasis> domain, as well as the older, deprecated
+ <emphasis>ip6.int</emphasis> domain.
+ Older versions of <acronym>BIND</acronym> 9
+ supported the "binary label" (also known as "bitstring") format,
+ but support of binary labels has been completely removed per
+ RFC 3363.
+ Many applications in <acronym>BIND</acronym> 9 do not understand
+ the binary label format at all any more, and will return an
+ error if given.
+ In particular, an authoritative <acronym>BIND</acronym> 9
+ name server will not load a zone file containing binary labels.
+ </para>
+
+ <para>
+ For an overview of the format and structure of IPv6 addresses,
+ see <xref linkend="ipv6addresses"/>.
+ </para>
+
+ <sect2>
+ <title>Address Lookups Using AAAA Records</title>
+
+ <para>
+ The IPv6 AAAA record is a parallel to the IPv4 A record,
+ and, unlike the deprecated A6 record, specifies the entire
+ IPv6 address in a single record. For example,
+ </para>
+
+<programlisting>
+$ORIGIN example.com.
+host 3600 IN AAAA 2001:db8::1
+</programlisting>
+
+ <para>
+ Use of IPv4-in-IPv6 mapped addresses is not recommended.
+ If a host has an IPv4 address, use an A record, not
+ a AAAA, with <literal>::ffff:192.168.42.1</literal> as
+ the address.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Address to Name Lookups Using Nibble Format</title>
+
+ <para>
+ When looking up an address in nibble format, the address
+ components are simply reversed, just as in IPv4, and
+ <literal>ip6.arpa.</literal> is appended to the
+ resulting name.
+ For example, the following would provide reverse name lookup for
+ a host with address
+ <literal>2001:db8::1</literal>.
+ </para>
+
+<programlisting>
+$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.
+</programlisting>
+
+ </sect2>
+ </sect1>
+ </chapter>
+
+ <chapter id="Bv9ARM.ch05">
+ <title>The <acronym>BIND</acronym> 9 Lightweight Resolver</title>
+ <sect1>
+ <title>The Lightweight Resolver Library</title>
+ <para>
+ Traditionally applications have been linked with a stub resolver
+ library that sends recursive DNS queries to a local caching name
+ server.
+ </para>
+ <para>
+ IPv6 once introduced new complexity into the resolution process,
+ such as following A6 chains and DNAME records, and simultaneous
+ lookup of IPv4 and IPv6 addresses. Though most of the complexity was
+ then removed, these are hard or impossible
+ to implement in a traditional stub resolver.
+ </para>
+ <para>
+ <acronym>BIND</acronym> 9 therefore can also provide resolution
+ services to local clients
+ using a combination of a lightweight resolver library and a resolver
+ daemon process running on the local host. These communicate using
+ a simple UDP-based protocol, the "lightweight resolver protocol"
+ that is distinct from and simpler than the full DNS protocol.
+ </para>
+ </sect1>
+ <sect1 id="lwresd">
+ <title>Running a Resolver Daemon</title>
+
+ <para>
+ To use the lightweight resolver interface, the system must
+ run the resolver daemon <command>lwresd</command> or a
+ local
+ name server configured with a <command>lwres</command>
+ statement.
+ </para>
+
+ <para>
+ By default, applications using the lightweight resolver library will
+ make
+ UDP requests to the IPv4 loopback address (127.0.0.1) on port 921.
+ The
+ address can be overridden by <command>lwserver</command>
+ lines in
+ <filename>/etc/resolv.conf</filename>.
+ </para>
+
+ <para>
+ The daemon currently only looks in the DNS, but in the future
+ it may use other sources such as <filename>/etc/hosts</filename>,
+ NIS, etc.
+ </para>
+
+ <para>
+ The <command>lwresd</command> daemon is essentially a
+ caching-only name server that responds to requests using the
+ lightweight
+ resolver protocol rather than the DNS protocol. Because it needs
+ to run on each host, it is designed to require no or minimal
+ configuration.
+ Unless configured otherwise, it uses the name servers listed on
+ <command>nameserver</command> lines in <filename>/etc/resolv.conf</filename>
+ as forwarders, but is also capable of doing the resolution
+ autonomously if
+ none are specified.
+ </para>
+ <para>
+ The <command>lwresd</command> daemon may also be
+ configured with a
+ <filename>named.conf</filename> style configuration file,
+ in
+ <filename>/etc/lwresd.conf</filename> by default. A name
+ server may also
+ be configured to act as a lightweight resolver daemon using the
+ <command>lwres</command> statement in <filename>named.conf</filename>.
+ </para>
+
+ </sect1>
+ </chapter>
+
+ <chapter id="Bv9ARM.ch06">
+ <title><acronym>BIND</acronym> 9 Configuration Reference</title>
+
+ <para>
+ <acronym>BIND</acronym> 9 configuration is broadly similar
+ to <acronym>BIND</acronym> 8; however, there are a few new
+ areas
+ of configuration, such as views. <acronym>BIND</acronym>
+ 8 configuration files should work with few alterations in <acronym>BIND</acronym>
+ 9, although more complex configurations should be reviewed to check
+ if they can be more efficiently implemented using the new features
+ found in <acronym>BIND</acronym> 9.
+ </para>
+
+ <para>
+ <acronym>BIND</acronym> 4 configuration files can be
+ converted to the new format
+ using the shell script
+ <filename>contrib/named-bootconf/named-bootconf.sh</filename>.
+ </para>
+ <sect1 id="configuration_file_elements">
+ <title>Configuration File Elements</title>
+ <para>
+ Following is a list of elements used throughout the <acronym>BIND</acronym> configuration
+ file documentation:
+ </para>
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="2Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.855in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="3.770in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>acl_name</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The name of an <varname>address_match_list</varname> as
+ defined by the <command>acl</command> statement.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>address_match_list</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A list of one or more
+ <varname>ip_addr</varname>,
+ <varname>ip_prefix</varname>, <varname>key_id</varname>,
+ or <varname>acl_name</varname> elements, see
+ <xref linkend="address_match_lists"/>.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>masters_list</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A named list of one or more <varname>ip_addr</varname>
+ with optional <varname>key_id</varname> and/or
+ <varname>ip_port</varname>.
+ A <varname>masters_list</varname> may include other
+ <varname>masters_lists</varname>.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>domain_name</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A quoted string which will be used as
+ a DNS name, for example "<literal>my.test.domain</literal>".
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>dotted_decimal</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ One to four integers valued 0 through
+ 255 separated by dots (`.'), such as <command>123</command>,
+ <command>45.67</command> or <command>89.123.45.67</command>.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>ip4_addr</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ An IPv4 address with exactly four elements
+ in <varname>dotted_decimal</varname> notation.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>ip6_addr</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ An IPv6 address, such as <command>2001:db8::1234</command>.
+ IPv6 scoped addresses that have ambiguity on their
+ scope zones must be disambiguated by an appropriate
+ zone ID with the percent character (`%') as
+ delimiter. It is strongly recommended to use
+ string zone names rather than numeric identifiers,
+ in order to be robust against system configuration
+ changes. However, since there is no standard
+ mapping for such names and identifier values,
+ currently only interface names as link identifiers
+ are supported, assuming one-to-one mapping between
+ interfaces and links. For example, a link-local
+ address <command>fe80::1</command> on the link
+ attached to the interface <command>ne0</command>
+ can be specified as <command>fe80::1%ne0</command>.
+ Note that on most systems link-local addresses
+ always have the ambiguity, and need to be
+ disambiguated.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>ip_addr</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ An <varname>ip4_addr</varname> or <varname>ip6_addr</varname>.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>ip_port</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ An IP port <varname>number</varname>.
+ The <varname>number</varname> is limited to 0
+ through 65535, with values
+ below 1024 typically restricted to use by processes running
+ as root.
+ In some cases, an asterisk (`*') character can be used as a
+ placeholder to
+ select a random high-numbered port.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>ip_prefix</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ An IP network specified as an <varname>ip_addr</varname>,
+ followed by a slash (`/') and then the number of bits in the
+ netmask.
+ Trailing zeros in a <varname>ip_addr</varname>
+ may omitted.
+ For example, <command>127/8</command> is the
+ network <command>127.0.0.0</command> with
+ netmask <command>255.0.0.0</command> and <command>1.2.3.0/28</command> is
+ network <command>1.2.3.0</command> with netmask <command>255.255.255.240</command>.
+ </para>
+ <para>
+ When specifying a prefix involving a IPv6 scoped address
+ the scope may be omitted. In that case the prefix will
+ match packets from any scope.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>key_id</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A <varname>domain_name</varname> representing
+ the name of a shared key, to be used for transaction
+ security.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>key_list</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A list of one or more
+ <varname>key_id</varname>s,
+ separated by semicolons and ending with a semicolon.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>number</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A non-negative 32-bit integer
+ (i.e., a number between 0 and 4294967295, inclusive).
+ Its acceptable value might further
+ be limited by the context in which it is used.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>path_name</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A quoted string which will be used as
+ a pathname, such as <filename>zones/master/my.test.domain</filename>.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>port_list</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A list of an <varname>ip_port</varname> or a port
+ range.
+ A port range is specified in the form of
+ <userinput>range</userinput> followed by
+ two <varname>ip_port</varname>s,
+ <varname>port_low</varname> and
+ <varname>port_high</varname>, which represents
+ port numbers from <varname>port_low</varname> through
+ <varname>port_high</varname>, inclusive.
+ <varname>port_low</varname> must not be larger than
+ <varname>port_high</varname>.
+ For example,
+ <userinput>range 1024 65535</userinput> represents
+ ports from 1024 through 65535.
+ In either case an asterisk (`*') character is not
+ allowed as a valid <varname>ip_port</varname>.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>size_spec</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A number, the word <userinput>unlimited</userinput>,
+ or the word <userinput>default</userinput>.
+ </para>
+ <para>
+ An <varname>unlimited</varname> <varname>size_spec</varname> requests unlimited
+ use, or the maximum available amount. A <varname>default size_spec</varname> uses
+ the limit that was in force when the server was started.
+ </para>
+ <para>
+ A <varname>number</varname> can optionally be
+ followed by a scaling factor:
+ <userinput>K</userinput> or <userinput>k</userinput>
+ for kilobytes,
+ <userinput>M</userinput> or <userinput>m</userinput>
+ for megabytes, and
+ <userinput>G</userinput> or <userinput>g</userinput> for gigabytes,
+ which scale by 1024, 1024*1024, and 1024*1024*1024
+ respectively.
+ </para>
+ <para>
+ The value must be representable as a 64-bit unsigned integer
+ (0 to 18446744073709551615, inclusive).
+ Using <varname>unlimited</varname> is the best
+ way
+ to safely set a really large number.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>yes_or_no</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Either <userinput>yes</userinput> or <userinput>no</userinput>.
+ The words <userinput>true</userinput> and <userinput>false</userinput> are
+ also accepted, as are the numbers <userinput>1</userinput>
+ and <userinput>0</userinput>.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>dialup_option</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ One of <userinput>yes</userinput>,
+ <userinput>no</userinput>, <userinput>notify</userinput>,
+ <userinput>notify-passive</userinput>, <userinput>refresh</userinput> or
+ <userinput>passive</userinput>.
+ When used in a zone, <userinput>notify-passive</userinput>,
+ <userinput>refresh</userinput>, and <userinput>passive</userinput>
+ are restricted to slave and stub zones.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <sect2 id="address_match_lists">
+ <title>Address Match Lists</title>
+ <sect3>
+ <title>Syntax</title>
+
+<programlisting><varname>address_match_list</varname> = address_match_list_element ;
+ <optional> address_match_list_element; ... </optional>
+<varname>address_match_list_element</varname> = <optional> ! </optional> (ip_address <optional>/length</optional> |
+ key key_id | acl_name | { address_match_list } )
+</programlisting>
+
+ </sect3>
+ <sect3>
+ <title>Definition and Usage</title>
+ <para>
+ Address match lists are primarily used to determine access
+ control for various server operations. They are also used in
+ the <command>listen-on</command> and <command>sortlist</command>
+ statements. The elements which constitute an address match
+ list can be any of the following:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <simpara>an IP address (IPv4 or IPv6)</simpara>
+ </listitem>
+ <listitem>
+ <simpara>an IP prefix (in `/' notation)</simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ a key ID, as defined by the <command>key</command>
+ statement
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>the name of an address match list defined with
+ the <command>acl</command> statement
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>a nested address match list enclosed in braces</simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Elements can be negated with a leading exclamation mark (`!'),
+ and the match list names "any", "none", "localhost", and
+ "localnets" are predefined. More information on those names
+ can be found in the description of the acl statement.
+ </para>
+
+ <para>
+ The addition of the key clause made the name of this syntactic
+ element something of a misnomer, since security keys can be used
+ to validate access without regard to a host or network address.
+ Nonetheless, the term "address match list" is still used
+ throughout the documentation.
+ </para>
+
+ <para>
+ When a given IP address or prefix is compared to an address
+ match list, the comparison takes place in approximately O(1)
+ time. However, key comparisons require that the list of keys
+ be traversed until a matching key is found, and therefore may
+ be somewhat slower.
+ </para>
+
+ <para>
+ The interpretation of a match depends on whether the list is being
+ used for access control, defining listen-on ports, or in a
+ sortlist, and whether the element was negated.
+ </para>
+
+ <para>
+ When used as an access control list, a non-negated match
+ allows access and a negated match denies access. If
+ there is no match, access is denied. The clauses
+ <command>allow-notify</command>,
+ <command>allow-recursion</command>,
+ <command>allow-recursion-on</command>,
+ <command>allow-query</command>,
+ <command>allow-query-on</command>,
+ <command>allow-query-cache</command>,
+ <command>allow-query-cache-on</command>,
+ <command>allow-transfer</command>,
+ <command>allow-update</command>,
+ <command>allow-update-forwarding</command>, and
+ <command>blackhole</command> all use address match
+ lists. Similarly, the listen-on option will cause the
+ server to refuse queries on any of the machine's
+ addresses which do not match the list.
+ </para>
+
+ <para>
+ Order of insertion is significant. If more than one element
+ in an ACL is found to match a given IP address or prefix,
+ preference will be given to the one that came
+ <emphasis>first</emphasis> in the ACL definition.
+ Because of this first-match behavior, an element that
+ defines a subset of another element in the list should
+ come before the broader element, regardless of whether
+ either is negated. For example, in
+ <command>1.2.3/24; ! 1.2.3.13;</command>
+ the 1.2.3.13 element is completely useless because the
+ algorithm will match any lookup for 1.2.3.13 to the 1.2.3/24
+ element. Using <command>! 1.2.3.13; 1.2.3/24</command> fixes
+ that problem by having 1.2.3.13 blocked by the negation, but
+ all other 1.2.3.* hosts fall through.
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Comment Syntax</title>
+
+ <para>
+ The <acronym>BIND</acronym> 9 comment syntax allows for
+ comments to appear
+ anywhere that whitespace may appear in a <acronym>BIND</acronym> configuration
+ file. To appeal to programmers of all kinds, they can be written
+ in the C, C++, or shell/perl style.
+ </para>
+
+ <sect3>
+ <title>Syntax</title>
+
+ <para>
+ <programlisting>/* This is a <acronym>BIND</acronym> comment as in C */</programlisting>
+ <programlisting>// This is a <acronym>BIND</acronym> comment as in C++</programlisting>
+ <programlisting># This is a <acronym>BIND</acronym> comment as in common UNIX shells and perl</programlisting>
+ </para>
+ </sect3>
+ <sect3>
+ <title>Definition and Usage</title>
+ <para>
+ Comments may appear anywhere that whitespace may appear in
+ a <acronym>BIND</acronym> configuration file.
+ </para>
+ <para>
+ C-style comments start with the two characters /* (slash,
+ star) and end with */ (star, slash). Because they are completely
+ delimited with these characters, they can be used to comment only
+ a portion of a line or to span multiple lines.
+ </para>
+ <para>
+ C-style comments cannot be nested. For example, the following
+ is not valid because the entire comment ends with the first */:
+ </para>
+ <para>
+
+<programlisting>/* This is the start of a comment.
+ This is still part of the comment.
+/* This is an incorrect attempt at nesting a comment. */
+ This is no longer in any comment. */
+</programlisting>
+
+ </para>
+
+ <para>
+ C++-style comments start with the two characters // (slash,
+ slash) and continue to the end of the physical line. They cannot
+ be continued across multiple physical lines; to have one logical
+ comment span multiple lines, each line must use the // pair.
+ </para>
+ <para>
+ For example:
+ </para>
+ <para>
+
+<programlisting>// This is the start of a comment. The next line
+// is a new comment, even though it is logically
+// part of the previous comment.
+</programlisting>
+
+ </para>
+ <para>
+ Shell-style (or perl-style, if you prefer) comments start
+ with the character <literal>#</literal> (number sign)
+ and continue to the end of the
+ physical line, as in C++ comments.
+ </para>
+ <para>
+ For example:
+ </para>
+
+ <para>
+
+<programlisting># This is the start of a comment. The next line
+# is a new comment, even though it is logically
+# part of the previous comment.
+</programlisting>
+
+ </para>
+
+ <warning>
+ <para>
+ You cannot use the semicolon (`;') character
+ to start a comment such as you would in a zone file. The
+ semicolon indicates the end of a configuration
+ statement.
+ </para>
+ </warning>
+ </sect3>
+ </sect2>
+ </sect1>
+
+ <sect1 id="Configuration_File_Grammar">
+ <title>Configuration File Grammar</title>
+
+ <para>
+ A <acronym>BIND</acronym> 9 configuration consists of
+ statements and comments.
+ Statements end with a semicolon. Statements and comments are the
+ only elements that can appear without enclosing braces. Many
+ statements contain a block of sub-statements, which are also
+ terminated with a semicolon.
+ </para>
+
+ <para>
+ The following statements are supported:
+ </para>
+
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="2Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.336in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="3.778in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>acl</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ defines a named IP address
+ matching list, for access control and other uses.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>controls</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ declares control channels to be used
+ by the <command>rndc</command> utility.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>include</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ includes a file.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>key</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ specifies key information for use in
+ authentication and authorization using TSIG.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>logging</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ specifies what the server logs, and where
+ the log messages are sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>lwres</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ configures <command>named</command> to
+ also act as a light-weight resolver daemon (<command>lwresd</command>).
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>masters</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ defines a named masters list for
+ inclusion in stub and slave zone masters clauses.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>options</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ controls global server configuration
+ options and sets defaults for other statements.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>statistics-channels</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ declares communication channels to get access to
+ <command>named</command> statistics.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>server</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ sets certain configuration options on
+ a per-server basis.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>trusted-keys</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ defines trusted DNSSEC keys.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>view</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ defines a view.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>zone</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ defines a zone.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>
+ The <command>logging</command> and
+ <command>options</command> statements may only occur once
+ per
+ configuration.
+ </para>
+
+ <sect2>
+ <title><command>acl</command> Statement Grammar</title>
+
+<programlisting><command>acl</command> acl-name {
+ address_match_list
+};
+</programlisting>
+
+ </sect2>
+ <sect2 id="acl">
+ <title><command>acl</command> Statement Definition and
+ Usage</title>
+
+ <para>
+ The <command>acl</command> statement assigns a symbolic
+ name to an address match list. It gets its name from a primary
+ use of address match lists: Access Control Lists (ACLs).
+ </para>
+
+ <para>
+ Note that an address match list's name must be defined
+ with <command>acl</command> before it can be used
+ elsewhere; no forward references are allowed.
+ </para>
+
+ <para>
+ The following ACLs are built-in:
+ </para>
+
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="3Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.130in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="4.000in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>any</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Matches all hosts.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>none</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Matches no hosts.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>localhost</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Matches the IPv4 and IPv6 addresses of all network
+ interfaces on the system.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>localnets</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Matches any host on an IPv4 or IPv6 network
+ for which the system has an interface.
+ Some systems do not provide a way to determine the prefix
+ lengths of
+ local IPv6 addresses.
+ In such a case, <command>localnets</command>
+ only matches the local
+ IPv6 addresses, just like <command>localhost</command>.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ </sect2>
+ <sect2>
+ <title><command>controls</command> Statement Grammar</title>
+
+<programlisting><command>controls</command> {
+ [ inet ( ip_addr | * ) [ port ip_port ] allow { <replaceable> address_match_list </replaceable> }
+ keys { <replaceable>key_list</replaceable> }; ]
+ [ inet ...; ]
+ [ unix <replaceable>path</replaceable> perm <replaceable>number</replaceable> owner <replaceable>number</replaceable> group <replaceable>number</replaceable> keys { <replaceable>key_list</replaceable> }; ]
+ [ unix ...; ]
+};
+</programlisting>
+
+ </sect2>
+
+ <sect2 id="controls_statement_definition_and_usage">
+ <title><command>controls</command> Statement Definition and
+ Usage</title>
+
+ <para>
+ The <command>controls</command> statement declares control
+ channels to be used by system administrators to control the
+ operation of the name server. These control channels are
+ used by the <command>rndc</command> utility to send
+ commands to and retrieve non-DNS results from a name server.
+ </para>
+
+ <para>
+ An <command>inet</command> control channel is a TCP socket
+ listening at the specified <command>ip_port</command> on the
+ specified <command>ip_addr</command>, which can be an IPv4 or IPv6
+ address. An <command>ip_addr</command> of <literal>*</literal> (asterisk) is
+ interpreted as the IPv4 wildcard address; connections will be
+ accepted on any of the system's IPv4 addresses.
+ To listen on the IPv6 wildcard address,
+ use an <command>ip_addr</command> of <literal>::</literal>.
+ If you will only use <command>rndc</command> on the local host,
+ using the loopback address (<literal>127.0.0.1</literal>
+ or <literal>::1</literal>) is recommended for maximum security.
+ </para>
+
+ <para>
+ If no port is specified, port 953 is used. The asterisk
+ "<literal>*</literal>" cannot be used for <command>ip_port</command>.
+ </para>
+
+ <para>
+ The ability to issue commands over the control channel is
+ restricted by the <command>allow</command> and
+ <command>keys</command> clauses.
+ Connections to the control channel are permitted based on the
+ <command>address_match_list</command>. This is for simple
+ IP address based filtering only; any <command>key_id</command>
+ elements of the <command>address_match_list</command>
+ are ignored.
+ </para>
+
+ <para>
+ A <command>unix</command> control channel is a UNIX domain
+ socket listening at the specified path in the file system.
+ Access to the socket is specified by the <command>perm</command>,
+ <command>owner</command> and <command>group</command> clauses.
+ Note on some platforms (SunOS and Solaris) the permissions
+ (<command>perm</command>) are applied to the parent directory
+ as the permissions on the socket itself are ignored.
+ </para>
+
+ <para>
+ The primary authorization mechanism of the command
+ channel is the <command>key_list</command>, which
+ contains a list of <command>key_id</command>s.
+ Each <command>key_id</command> in the <command>key_list</command>
+ is authorized to execute commands over the control channel.
+ See <xref linkend="rndc"/> in <xref linkend="admin_tools"/>)
+ for information about configuring keys in <command>rndc</command>.
+ </para>
+
+ <para>
+ If no <command>controls</command> statement is present,
+ <command>named</command> will set up a default
+ control channel listening on the loopback address 127.0.0.1
+ and its IPv6 counterpart ::1.
+ In this case, and also when the <command>controls</command> statement
+ is present but does not have a <command>keys</command> clause,
+ <command>named</command> will attempt to load the command channel key
+ from the file <filename>rndc.key</filename> in
+ <filename>/etc</filename> (or whatever <varname>sysconfdir</varname>
+ was specified as when <acronym>BIND</acronym> was built).
+ To create a <filename>rndc.key</filename> file, run
+ <userinput>rndc-confgen -a</userinput>.
+ </para>
+
+ <para>
+ The <filename>rndc.key</filename> feature was created to
+ ease the transition of systems from <acronym>BIND</acronym> 8,
+ which did not have digital signatures on its command channel
+ messages and thus did not have a <command>keys</command> clause.
+
+ It makes it possible to use an existing <acronym>BIND</acronym> 8
+ configuration file in <acronym>BIND</acronym> 9 unchanged,
+ and still have <command>rndc</command> work the same way
+ <command>ndc</command> worked in BIND 8, simply by executing the
+ command <userinput>rndc-confgen -a</userinput> after BIND 9 is
+ installed.
+ </para>
+
+ <para>
+ Since the <filename>rndc.key</filename> feature
+ is only intended to allow the backward-compatible usage of
+ <acronym>BIND</acronym> 8 configuration files, this
+ feature does not
+ have a high degree of configurability. You cannot easily change
+ the key name or the size of the secret, so you should make a
+ <filename>rndc.conf</filename> with your own key if you
+ wish to change
+ those things. The <filename>rndc.key</filename> file
+ also has its
+ permissions set such that only the owner of the file (the user that
+ <command>named</command> is running as) can access it.
+ If you
+ desire greater flexibility in allowing other users to access
+ <command>rndc</command> commands, then you need to create
+ a
+ <filename>rndc.conf</filename> file and make it group
+ readable by a group
+ that contains the users who should have access.
+ </para>
+
+ <para>
+ To disable the command channel, use an empty
+ <command>controls</command> statement:
+ <command>controls { };</command>.
+ </para>
+
+ </sect2>
+ <sect2>
+ <title><command>include</command> Statement Grammar</title>
+ <programlisting><command>include</command> <replaceable>filename</replaceable>;</programlisting>
+ </sect2>
+ <sect2>
+ <title><command>include</command> Statement Definition and
+ Usage</title>
+
+ <para>
+ The <command>include</command> statement inserts the
+ specified file at the point where the <command>include</command>
+ statement is encountered. The <command>include</command>
+ statement facilitates the administration of configuration
+ files
+ by permitting the reading or writing of some things but not
+ others. For example, the statement could include private keys
+ that are readable only by the name server.
+ </para>
+
+ </sect2>
+ <sect2>
+ <title><command>key</command> Statement Grammar</title>
+
+<programlisting><command>key</command> <replaceable>key_id</replaceable> {
+ algorithm <replaceable>string</replaceable>;
+ secret <replaceable>string</replaceable>;
+};
+</programlisting>
+
+ </sect2>
+
+ <sect2>
+ <title><command>key</command> Statement Definition and Usage</title>
+
+ <para>
+ The <command>key</command> statement defines a shared
+ secret key for use with TSIG (see <xref linkend="tsig"/>)
+ or the command channel
+ (see <xref linkend="controls_statement_definition_and_usage"/>).
+ </para>
+
+ <para>
+ The <command>key</command> statement can occur at the
+ top level
+ of the configuration file or inside a <command>view</command>
+ statement. Keys defined in top-level <command>key</command>
+ statements can be used in all views. Keys intended for use in
+ a <command>controls</command> statement
+ (see <xref linkend="controls_statement_definition_and_usage"/>)
+ must be defined at the top level.
+ </para>
+
+ <para>
+ The <replaceable>key_id</replaceable>, also known as the
+ key name, is a domain name uniquely identifying the key. It can
+ be used in a <command>server</command>
+ statement to cause requests sent to that
+ server to be signed with this key, or in address match lists to
+ verify that incoming requests have been signed with a key
+ matching this name, algorithm, and secret.
+ </para>
+
+ <para>
+ The <replaceable>algorithm_id</replaceable> is a string
+ that specifies a security/authentication algorithm. Named
+ supports <literal>hmac-md5</literal>,
+ <literal>hmac-sha1</literal>, <literal>hmac-sha224</literal>,
+ <literal>hmac-sha256</literal>, <literal>hmac-sha384</literal>
+ and <literal>hmac-sha512</literal> TSIG authentication.
+ Truncated hashes are supported by appending the minimum
+ number of required bits preceded by a dash, e.g.
+ <literal>hmac-sha1-80</literal>. The
+ <replaceable>secret_string</replaceable> is the secret
+ to be used by the algorithm, and is treated as a base-64
+ encoded string.
+ </para>
+
+ </sect2>
+ <sect2>
+ <title><command>logging</command> Statement Grammar</title>
+
+<programlisting><command>logging</command> {
+ [ <command>channel</command> <replaceable>channel_name</replaceable> {
+ ( <command>file</command> <replaceable>path_name</replaceable>
+ [ <command>versions</command> ( <replaceable>number</replaceable> | <command>unlimited</command> ) ]
+ [ <command>size</command> <replaceable>size spec</replaceable> ]
+ | <command>syslog</command> <replaceable>syslog_facility</replaceable>
+ | <command>stderr</command>
+ | <command>null</command> );
+ [ <command>severity</command> (<option>critical</option> | <option>error</option> | <option>warning</option> | <option>notice</option> |
+ <option>info</option> | <option>debug</option> [ <replaceable>level</replaceable> ] | <option>dynamic</option> ); ]
+ [ <command>print-category</command> <option>yes</option> or <option>no</option>; ]
+ [ <command>print-severity</command> <option>yes</option> or <option>no</option>; ]
+ [ <command>print-time</command> <option>yes</option> or <option>no</option>; ]
+ }; ]
+ [ <command>category</command> <replaceable>category_name</replaceable> {
+ <replaceable>channel_name</replaceable> ; [ <replaceable>channel_name</replaceable> ; ... ]
+ }; ]
+ ...
+};
+</programlisting>
+
+ </sect2>
+
+ <sect2>
+ <title><command>logging</command> Statement Definition and
+ Usage</title>
+
+ <para>
+ The <command>logging</command> statement configures a
+ wide
+ variety of logging options for the name server. Its <command>channel</command> phrase
+ associates output methods, format options and severity levels with
+ a name that can then be used with the <command>category</command> phrase
+ to select how various classes of messages are logged.
+ </para>
+ <para>
+ Only one <command>logging</command> statement is used to
+ define
+ as many channels and categories as are wanted. If there is no <command>logging</command> statement,
+ the logging configuration will be:
+ </para>
+
+<programlisting>logging {
+ category default { default_syslog; default_debug; };
+ category unmatched { null; };
+};
+</programlisting>
+
+ <para>
+ In <acronym>BIND</acronym> 9, the logging configuration
+ is only established when
+ the entire configuration file has been parsed. In <acronym>BIND</acronym> 8, it was
+ established as soon as the <command>logging</command>
+ statement
+ was parsed. When the server is starting up, all logging messages
+ regarding syntax errors in the configuration file go to the default
+ channels, or to standard error if the "<option>-g</option>" option
+ was specified.
+ </para>
+
+ <sect3>
+ <title>The <command>channel</command> Phrase</title>
+
+ <para>
+ All log output goes to one or more <emphasis>channels</emphasis>;
+ you can make as many of them as you want.
+ </para>
+
+ <para>
+ Every channel definition must include a destination clause that
+ says whether messages selected for the channel go to a file, to a
+ particular syslog facility, to the standard error stream, or are
+ discarded. It can optionally also limit the message severity level
+ that will be accepted by the channel (the default is
+ <command>info</command>), and whether to include a
+ <command>named</command>-generated time stamp, the
+ category name
+ and/or severity level (the default is not to include any).
+ </para>
+
+ <para>
+ The <command>null</command> destination clause
+ causes all messages sent to the channel to be discarded;
+ in that case, other options for the channel are meaningless.
+ </para>
+
+ <para>
+ The <command>file</command> destination clause directs
+ the channel
+ to a disk file. It can include limitations
+ both on how large the file is allowed to become, and how many
+ versions
+ of the file will be saved each time the file is opened.
+ </para>
+
+ <para>
+ If you use the <command>versions</command> log file
+ option, then
+ <command>named</command> will retain that many backup
+ versions of the file by
+ renaming them when opening. For example, if you choose to keep
+ three old versions
+ of the file <filename>lamers.log</filename>, then just
+ before it is opened
+ <filename>lamers.log.1</filename> is renamed to
+ <filename>lamers.log.2</filename>, <filename>lamers.log.0</filename> is renamed
+ to <filename>lamers.log.1</filename>, and <filename>lamers.log</filename> is
+ renamed to <filename>lamers.log.0</filename>.
+ You can say <command>versions unlimited</command> to
+ not limit
+ the number of versions.
+ If a <command>size</command> option is associated with
+ the log file,
+ then renaming is only done when the file being opened exceeds the
+ indicated size. No backup versions are kept by default; any
+ existing
+ log file is simply appended.
+ </para>
+
+ <para>
+ The <command>size</command> option for files is used
+ to limit log
+ growth. If the file ever exceeds the size, then <command>named</command> will
+ stop writing to the file unless it has a <command>versions</command> option
+ associated with it. If backup versions are kept, the files are
+ rolled as
+ described above and a new one begun. If there is no
+ <command>versions</command> option, no more data will
+ be written to the log
+ until some out-of-band mechanism removes or truncates the log to
+ less than the
+ maximum size. The default behavior is not to limit the size of
+ the
+ file.
+ </para>
+
+ <para>
+ Example usage of the <command>size</command> and
+ <command>versions</command> options:
+ </para>
+
+<programlisting>channel an_example_channel {
+ file "example.log" versions 3 size 20m;
+ print-time yes;
+ print-category yes;
+};
+</programlisting>
+
+ <para>
+ The <command>syslog</command> destination clause
+ directs the
+ channel to the system log. Its argument is a
+ syslog facility as described in the <command>syslog</command> man
+ page. Known facilities are <command>kern</command>, <command>user</command>,
+ <command>mail</command>, <command>daemon</command>, <command>auth</command>,
+ <command>syslog</command>, <command>lpr</command>, <command>news</command>,
+ <command>uucp</command>, <command>cron</command>, <command>authpriv</command>,
+ <command>ftp</command>, <command>local0</command>, <command>local1</command>,
+ <command>local2</command>, <command>local3</command>, <command>local4</command>,
+ <command>local5</command>, <command>local6</command> and
+ <command>local7</command>, however not all facilities
+ are supported on
+ all operating systems.
+ How <command>syslog</command> will handle messages
+ sent to
+ this facility is described in the <command>syslog.conf</command> man
+ page. If you have a system which uses a very old version of <command>syslog</command> that
+ only uses two arguments to the <command>openlog()</command> function,
+ then this clause is silently ignored.
+ </para>
+ <para>
+ The <command>severity</command> clause works like <command>syslog</command>'s
+ "priorities", except that they can also be used if you are writing
+ straight to a file rather than using <command>syslog</command>.
+ Messages which are not at least of the severity level given will
+ not be selected for the channel; messages of higher severity
+ levels
+ will be accepted.
+ </para>
+ <para>
+ If you are using <command>syslog</command>, then the <command>syslog.conf</command> priorities
+ will also determine what eventually passes through. For example,
+ defining a channel facility and severity as <command>daemon</command> and <command>debug</command> but
+ only logging <command>daemon.warning</command> via <command>syslog.conf</command> will
+ cause messages of severity <command>info</command> and
+ <command>notice</command> to
+ be dropped. If the situation were reversed, with <command>named</command> writing
+ messages of only <command>warning</command> or higher,
+ then <command>syslogd</command> would
+ print all messages it received from the channel.
+ </para>
+
+ <para>
+ The <command>stderr</command> destination clause
+ directs the
+ channel to the server's standard error stream. This is intended
+ for
+ use when the server is running as a foreground process, for
+ example
+ when debugging a configuration.
+ </para>
+
+ <para>
+ The server can supply extensive debugging information when
+ it is in debugging mode. If the server's global debug level is
+ greater
+ than zero, then debugging mode will be active. The global debug
+ level is set either by starting the <command>named</command> server
+ with the <option>-d</option> flag followed by a positive integer,
+ or by running <command>rndc trace</command>.
+ The global debug level
+ can be set to zero, and debugging mode turned off, by running <command>rndc
+notrace</command>. All debugging messages in the server have a debug
+ level, and higher debug levels give more detailed output. Channels
+ that specify a specific debug severity, for example:
+ </para>
+
+<programlisting>channel specific_debug_level {
+ file "foo";
+ severity debug 3;
+};
+</programlisting>
+
+ <para>
+ will get debugging output of level 3 or less any time the
+ server is in debugging mode, regardless of the global debugging
+ level. Channels with <command>dynamic</command>
+ severity use the
+ server's global debug level to determine what messages to print.
+ </para>
+ <para>
+ If <command>print-time</command> has been turned on,
+ then
+ the date and time will be logged. <command>print-time</command> may
+ be specified for a <command>syslog</command> channel,
+ but is usually
+ pointless since <command>syslog</command> also prints
+ the date and
+ time. If <command>print-category</command> is
+ requested, then the
+ category of the message will be logged as well. Finally, if <command>print-severity</command> is
+ on, then the severity level of the message will be logged. The <command>print-</command> options may
+ be used in any combination, and will always be printed in the
+ following
+ order: time, category, severity. Here is an example where all
+ three <command>print-</command> options
+ are on:
+ </para>
+
+ <para>
+ <computeroutput>28-Feb-2000 15:05:32.863 general: notice: running</computeroutput>
+ </para>
+
+ <para>
+ There are four predefined channels that are used for
+ <command>named</command>'s default logging as follows.
+ How they are
+ used is described in <xref linkend="the_category_phrase"/>.
+ </para>
+
+<programlisting>channel default_syslog {
+ syslog daemon; // send to syslog's daemon
+ // facility
+ severity info; // only send priority info
+ // and higher
+};
+
+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
+};
+
+channel default_stderr {
+ stderr; // writes to stderr
+ severity info; // only send priority info
+ // and higher
+};
+
+channel null {
+ null; // toss anything sent to
+ // this channel
+};
+</programlisting>
+
+ <para>
+ The <command>default_debug</command> channel has the
+ special
+ property that it only produces output when the server's debug
+ level is
+ nonzero. It normally writes to a file called <filename>named.run</filename>
+ in the server's working directory.
+ </para>
+
+ <para>
+ For security reasons, when the "<option>-u</option>"
+ command line option is used, the <filename>named.run</filename> file
+ is created only after <command>named</command> has
+ changed to the
+ new UID, and any debug output generated while <command>named</command> is
+ starting up and still running as root is discarded. If you need
+ to capture this output, you must run the server with the "<option>-g</option>"
+ option and redirect standard error to a file.
+ </para>
+
+ <para>
+ Once a channel is defined, it cannot be redefined. Thus you
+ cannot alter the built-in channels directly, but you can modify
+ the default logging by pointing categories at channels you have
+ defined.
+ </para>
+ </sect3>
+
+ <sect3 id="the_category_phrase">
+ <title>The <command>category</command> Phrase</title>
+
+ <para>
+ There are many categories, so you can send the logs you want
+ to see wherever you want, without seeing logs you don't want. If
+ you don't specify a list of channels for a category, then log
+ messages
+ in that category will be sent to the <command>default</command> category
+ instead. If you don't specify a default category, the following
+ "default default" is used:
+ </para>
+
+<programlisting>category default { default_syslog; default_debug; };
+</programlisting>
+
+ <para>
+ As an example, let's say you want to log security events to
+ a file, but you also want keep the default logging behavior. You'd
+ specify the following:
+ </para>
+
+<programlisting>channel my_security_channel {
+ file "my_security_file";
+ severity info;
+};
+category security {
+ my_security_channel;
+ default_syslog;
+ default_debug;
+};</programlisting>
+
+ <para>
+ To discard all messages in a category, specify the <command>null</command> channel:
+ </para>
+
+<programlisting>category xfer-out { null; };
+category notify { null; };
+</programlisting>
+
+ <para>
+ Following are the available categories and brief descriptions
+ of the types of log information they contain. More
+ categories may be added in future <acronym>BIND</acronym> releases.
+ </para>
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.150in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="3.350in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>default</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The default category defines the logging
+ options for those categories where no specific
+ configuration has been
+ defined.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>general</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The catch-all. Many things still aren't
+ classified into categories, and they all end up here.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>database</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Messages relating to the databases used
+ internally by the name server to store zone and cache
+ data.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>security</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Approval and denial of requests.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>config</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Configuration file parsing and processing.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>resolver</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ DNS resolution, such as the recursive
+ lookups performed on behalf of clients by a caching name
+ server.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>xfer-in</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Zone transfers the server is receiving.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>xfer-out</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Zone transfers the server is sending.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>notify</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The NOTIFY protocol.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>client</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Processing of client requests.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>unmatched</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Messages that named was unable to determine the
+ class of or for which there was no matching <command>view</command>.
+ A one line summary is also logged to the <command>client</command> category.
+ This category is best sent to a file or stderr, by
+ default it is sent to
+ the <command>null</command> channel.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>network</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Network operations.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>update</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Dynamic updates.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>update-security</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Approval and denial of update requests.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>queries</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Specify where queries should be logged to.
+ </para>
+ <para>
+ At startup, specifying the category <command>queries</command> will also
+ enable query logging unless <command>querylog</command> option has been
+ specified.
+ </para>
+
+ <para>
+ 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
+ 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).
+ </para>
+
+ <para>
+ <computeroutput>client 127.0.0.1#62536: query: www.example.com IN AAAA +SE</computeroutput>
+ </para>
+ <para>
+ <computeroutput>client ::1#62537: query: www.example.net IN AAAA -SE</computeroutput>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>dispatch</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Dispatching of incoming packets to the
+ server modules where they are to be processed.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>dnssec</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ DNSSEC and TSIG protocol processing.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>lame-servers</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Lame servers. These are misconfigurations
+ in remote servers, discovered by BIND 9 when trying to
+ query
+ those servers during resolution.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>delegation-only</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Delegation only. Logs queries that have
+ been forced to NXDOMAIN as the result of a
+ delegation-only zone or
+ a <command>delegation-only</command> in a
+ hint or stub zone declaration.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>edns-disabled</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Log queries that have been forced to use plain
+ DNS due to timeouts. This is often due to
+ the remote servers not being RFC 1034 compliant
+ (not always returning FORMERR or similar to
+ EDNS queries and other extensions to the DNS
+ when they are not understood). In other words, this is
+ targeted at servers that fail to respond to
+ DNS queries that they don't understand.
+ </para>
+ <para>
+ Note: the log message can also be due to
+ packet loss. Before reporting servers for
+ non-RFC 1034 compliance they should be re-tested
+ to determine the nature of the non-compliance.
+ This testing should prevent or reduce the
+ number of false-positive reports.
+ </para>
+ <para>
+ Note: eventually named will have to stop
+ treating such timeouts as due to RFC 1034 non
+ compliance and start treating it as plain
+ packet loss. Falsely classifying packet
+ loss as due to RFC 1034 non compliance impacts
+ on DNSSEC validation which requires EDNS for
+ the DNSSEC records to be returned.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title><command>lwres</command> Statement Grammar</title>
+
+ <para>
+ This is the grammar of the <command>lwres</command>
+ statement in the <filename>named.conf</filename> file:
+ </para>
+
+<programlisting><command>lwres</command> {
+ <optional> listen-on { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+ <optional> view <replaceable>view_name</replaceable>; </optional>
+ <optional> search { <replaceable>domain_name</replaceable> ; <optional> <replaceable>domain_name</replaceable> ; ... </optional> }; </optional>
+ <optional> ndots <replaceable>number</replaceable>; </optional>
+};
+</programlisting>
+
+ </sect2>
+ <sect2>
+ <title><command>lwres</command> Statement Definition and Usage</title>
+
+ <para>
+ The <command>lwres</command> statement configures the
+ name
+ server to also act as a lightweight resolver server. (See
+ <xref linkend="lwresd"/>.) There may be multiple
+ <command>lwres</command> statements configuring
+ lightweight resolver servers with different properties.
+ </para>
+
+ <para>
+ The <command>listen-on</command> statement specifies a
+ list of
+ addresses (and ports) that this instance of a lightweight resolver
+ daemon
+ should accept requests on. If no port is specified, port 921 is
+ used.
+ If this statement is omitted, requests will be accepted on
+ 127.0.0.1,
+ port 921.
+ </para>
+
+ <para>
+ The <command>view</command> statement binds this
+ instance of a
+ lightweight resolver daemon to a view in the DNS namespace, so that
+ the
+ response will be constructed in the same manner as a normal DNS
+ query
+ matching this view. If this statement is omitted, the default view
+ is
+ used, and if there is no default view, an error is triggered.
+ </para>
+
+ <para>
+ The <command>search</command> statement is equivalent to
+ the
+ <command>search</command> statement in
+ <filename>/etc/resolv.conf</filename>. It provides a
+ list of domains
+ which are appended to relative names in queries.
+ </para>
+
+ <para>
+ The <command>ndots</command> statement is equivalent to
+ the
+ <command>ndots</command> statement in
+ <filename>/etc/resolv.conf</filename>. It indicates the
+ minimum
+ number of dots in a relative domain name that should result in an
+ exact match lookup before search path elements are appended.
+ </para>
+ </sect2>
+ <sect2>
+ <title><command>masters</command> Statement Grammar</title>
+
+<programlisting>
+<command>masters</command> <replaceable>name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> };
+</programlisting>
+
+ </sect2>
+
+ <sect2>
+ <title><command>masters</command> Statement Definition and
+ Usage</title>
+ <para><command>masters</command>
+ lists allow for a common set of masters to be easily used by
+ multiple stub and slave zones.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title><command>options</command> Statement Grammar</title>
+
+ <para>
+ This is the grammar of the <command>options</command>
+ statement in the <filename>named.conf</filename> file:
+ </para>
+
+<programlisting><command>options</command> {
+ <optional> version <replaceable>version_string</replaceable>; </optional>
+ <optional> hostname <replaceable>hostname_string</replaceable>; </optional>
+ <optional> server-id <replaceable>server_id_string</replaceable>; </optional>
+ <optional> directory <replaceable>path_name</replaceable>; </optional>
+ <optional> key-directory <replaceable>path_name</replaceable>; </optional>
+ <optional> named-xfer <replaceable>path_name</replaceable>; </optional>
+ <optional> tkey-gssapi-credential <replaceable>principal</replaceable>; </optional>
+ <optional> tkey-domain <replaceable>domainname</replaceable>; </optional>
+ <optional> tkey-dhkey <replaceable>key_name</replaceable> <replaceable>key_tag</replaceable>; </optional>
+ <optional> cache-file <replaceable>path_name</replaceable>; </optional>
+ <optional> dump-file <replaceable>path_name</replaceable>; </optional>
+ <optional> memstatistics <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> memstatistics-file <replaceable>path_name</replaceable>; </optional>
+ <optional> pid-file <replaceable>path_name</replaceable>; </optional>
+ <optional> recursing-file <replaceable>path_name</replaceable>; </optional>
+ <optional> statistics-file <replaceable>path_name</replaceable>; </optional>
+ <optional> zone-statistics <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> auth-nxdomain <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> deallocate-on-exit <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> dialup <replaceable>dialup_option</replaceable>; </optional>
+ <optional> fake-iquery <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> fetch-glue <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> flush-zones-on-shutdown <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> has-old-clients <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> host-statistics <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> host-statistics-max <replaceable>number</replaceable>; </optional>
+ <optional> minimal-responses <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> multiple-cnames <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> notify <replaceable>yes_or_no</replaceable> | <replaceable>explicit</replaceable> | <replaceable>master-only</replaceable>; </optional>
+ <optional> recursion <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> rfc2308-type1 <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> use-id-pool <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> maintain-ixfr-base <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> ixfr-from-differences (<replaceable>yes_or_no</replaceable> | <constant>master</constant> | <constant>slave</constant>); </optional>
+ <optional> dnssec-enable <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> dnssec-validation <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> dnssec-lookaside <replaceable>domain</replaceable> trust-anchor <replaceable>domain</replaceable>; </optional>
+ <optional> dnssec-must-be-secure <replaceable>domain yes_or_no</replaceable>; </optional>
+ <optional> dnssec-accept-expired <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> forward ( <replaceable>only</replaceable> | <replaceable>first</replaceable> ); </optional>
+ <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+ <optional> dual-stack-servers <optional>port <replaceable>ip_port</replaceable></optional> {
+ ( <replaceable>domain_name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> |
+ <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ) ;
+ ... }; </optional>
+ <optional> check-names ( <replaceable>master</replaceable> | <replaceable>slave</replaceable> | <replaceable>response</replaceable> )
+ ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
+ <optional> check-mx ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
+ <optional> check-wildcard <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> check-integrity <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> check-mx-cname ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
+ <optional> check-srv-cname ( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
+ <optional> check-sibling <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> allow-notify { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query-on { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query-cache { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query-cache-on { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-transfer { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-recursion { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-recursion-on { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-update { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-update-forwarding { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> update-check-ksk <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> try-tcp-refresh <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> allow-v6-synthesis { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> blackhole { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> use-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
+ <optional> avoid-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
+ <optional> use-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
+ <optional> avoid-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
+ <optional> listen-on <optional> port <replaceable>ip_port</replaceable> </optional> { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> listen-on-v6 <optional> port <replaceable>ip_port</replaceable> </optional> { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> query-source ( ( <replaceable>ip4_addr</replaceable> | <replaceable>*</replaceable> )
+ <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> |
+ <optional> address ( <replaceable>ip4_addr</replaceable> | <replaceable>*</replaceable> ) </optional>
+ <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> ) ; </optional>
+ <optional> query-source-v6 ( ( <replaceable>ip6_addr</replaceable> | <replaceable>*</replaceable> )
+ <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> |
+ <optional> address ( <replaceable>ip6_addr</replaceable> | <replaceable>*</replaceable> ) </optional>
+ <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional> ) ; </optional>
+ <optional> use-queryport-pool <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> queryport-pool-ports <replaceable>number</replaceable>; </optional>
+ <optional> queryport-pool-interval <replaceable>number</replaceable>; </optional>
+ <optional> max-transfer-time-in <replaceable>number</replaceable>; </optional>
+ <optional> max-transfer-time-out <replaceable>number</replaceable>; </optional>
+ <optional> max-transfer-idle-in <replaceable>number</replaceable>; </optional>
+ <optional> max-transfer-idle-out <replaceable>number</replaceable>; </optional>
+ <optional> tcp-clients <replaceable>number</replaceable>; </optional>
+ <optional> reserved-sockets <replaceable>number</replaceable>; </optional>
+ <optional> recursive-clients <replaceable>number</replaceable>; </optional>
+ <optional> serial-query-rate <replaceable>number</replaceable>; </optional>
+ <optional> serial-queries <replaceable>number</replaceable>; </optional>
+ <optional> tcp-listen-queue <replaceable>number</replaceable>; </optional>
+ <optional> transfer-format <replaceable>( one-answer | many-answers )</replaceable>; </optional>
+ <optional> transfers-in <replaceable>number</replaceable>; </optional>
+ <optional> transfers-out <replaceable>number</replaceable>; </optional>
+ <optional> transfers-per-ns <replaceable>number</replaceable>; </optional>
+ <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> alt-transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> alt-transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> use-alt-transfer-source <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> notify-delay <replaceable>seconds</replaceable> ; </optional>
+ <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> notify-to-soa <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> also-notify { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+ <optional> max-ixfr-log-size <replaceable>number</replaceable>; </optional>
+ <optional> max-journal-size <replaceable>size_spec</replaceable>; </optional>
+ <optional> coresize <replaceable>size_spec</replaceable> ; </optional>
+ <optional> datasize <replaceable>size_spec</replaceable> ; </optional>
+ <optional> files <replaceable>size_spec</replaceable> ; </optional>
+ <optional> stacksize <replaceable>size_spec</replaceable> ; </optional>
+ <optional> cleaning-interval <replaceable>number</replaceable>; </optional>
+ <optional> heartbeat-interval <replaceable>number</replaceable>; </optional>
+ <optional> interface-interval <replaceable>number</replaceable>; </optional>
+ <optional> statistics-interval <replaceable>number</replaceable>; </optional>
+ <optional> topology { <replaceable>address_match_list</replaceable> }</optional>;
+ <optional> sortlist { <replaceable>address_match_list</replaceable> }</optional>;
+ <optional> rrset-order { <replaceable>order_spec</replaceable> ; <optional> <replaceable>order_spec</replaceable> ; ... </optional> </optional> };
+ <optional> lame-ttl <replaceable>number</replaceable>; </optional>
+ <optional> max-ncache-ttl <replaceable>number</replaceable>; </optional>
+ <optional> max-cache-ttl <replaceable>number</replaceable>; </optional>
+ <optional> sig-validity-interval <replaceable>number</replaceable> ; </optional>
+ <optional> sig-signing-nodes <replaceable>number</replaceable> ; </optional>
+ <optional> sig-signing-signatures <replaceable>number</replaceable> ; </optional>
+ <optional> sig-signing-type <replaceable>number</replaceable> ; </optional>
+ <optional> min-roots <replaceable>number</replaceable>; </optional>
+ <optional> use-ixfr <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> provide-ixfr <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> request-ixfr <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> treat-cr-as-space <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> min-refresh-time <replaceable>number</replaceable> ; </optional>
+ <optional> max-refresh-time <replaceable>number</replaceable> ; </optional>
+ <optional> min-retry-time <replaceable>number</replaceable> ; </optional>
+ <optional> max-retry-time <replaceable>number</replaceable> ; </optional>
+ <optional> port <replaceable>ip_port</replaceable>; </optional>
+ <optional> additional-from-auth <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> additional-from-cache <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> random-device <replaceable>path_name</replaceable> ; </optional>
+ <optional> max-cache-size <replaceable>size_spec</replaceable> ; </optional>
+ <optional> match-mapped-addresses <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> preferred-glue ( <replaceable>A</replaceable> | <replaceable>AAAA</replaceable> | <replaceable>NONE</replaceable> ); </optional>
+ <optional> edns-udp-size <replaceable>number</replaceable>; </optional>
+ <optional> max-udp-size <replaceable>number</replaceable>; </optional>
+ <optional> root-delegation-only <optional> exclude { <replaceable>namelist</replaceable> } </optional> ; </optional>
+ <optional> querylog <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> disable-algorithms <replaceable>domain</replaceable> { <replaceable>algorithm</replaceable>; <optional> <replaceable>algorithm</replaceable>; </optional> }; </optional>
+ <optional> acache-enable <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> acache-cleaning-interval <replaceable>number</replaceable>; </optional>
+ <optional> max-acache-size <replaceable>size_spec</replaceable> ; </optional>
+ <optional> clients-per-query <replaceable>number</replaceable> ; </optional>
+ <optional> max-clients-per-query <replaceable>number</replaceable> ; </optional>
+ <optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>) ; </optional>
+ <optional> empty-server <replaceable>name</replaceable> ; </optional>
+ <optional> empty-contact <replaceable>name</replaceable> ; </optional>
+ <optional> empty-zones-enable <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> disable-empty-zone <replaceable>zone_name</replaceable> ; </optional>
+ <optional> zero-no-soa-ttl <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> zero-no-soa-ttl-cache <replaceable>yes_or_no</replaceable> ; </optional>
+};
+</programlisting>
+
+ </sect2>
+
+ <sect2 id="options">
+ <title><command>options</command> Statement Definition and
+ Usage</title>
+
+ <para>
+ The <command>options</command> statement sets up global
+ options
+ to be used by <acronym>BIND</acronym>. This statement
+ may appear only
+ once in a configuration file. If there is no <command>options</command>
+ statement, an options block with each option set to its default will
+ be used.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>directory</command></term>
+ <listitem>
+ <para>
+ The working directory of the server.
+ Any non-absolute pathnames in the configuration file will be
+ taken
+ as relative to this directory. The default location for most
+ server
+ output files (e.g. <filename>named.run</filename>)
+ is this directory.
+ If a directory is not specified, the working directory
+ defaults to `<filename>.</filename>', the directory from
+ which the server
+ was started. The directory specified should be an absolute
+ path.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>key-directory</command></term>
+ <listitem>
+ <para>
+ When performing dynamic update of secure zones, the
+ directory where the public and private key files should be
+ found,
+ if different than the current working directory. The
+ directory specified
+ must be an absolute path.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>named-xfer</command></term>
+ <listitem>
+ <para>
+ <emphasis>This option is obsolete.</emphasis> It
+ was used in <acronym>BIND</acronym> 8 to specify
+ the pathname to the <command>named-xfer</command>
+ program. In <acronym>BIND</acronym> 9, no separate
+ <command>named-xfer</command> program is needed;
+ its functionality is built into the name server.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>tkey-gssapi-credential</command></term>
+ <listitem>
+ <para>
+ 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 <filename>/etc/krb5.keytab</filename>.
+ Normally this principal is of the form
+ "<userinput>dns/</userinput><varname>server.domain</varname>".
+ To use GSS-TSIG, <command>tkey-domain</command>
+ must also be set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>tkey-domain</command></term>
+ <listitem>
+ <para>
+ The domain appended to the names of all shared keys
+ generated with <command>TKEY</command>. When a
+ client requests a <command>TKEY</command> exchange,
+ it may or may not specify the desired name for the
+ key. If present, the name of the shared key will
+ will be <varname>client specified part</varname> +
+ <varname>tkey-domain</varname>. Otherwise, the
+ name of the shared key will be <varname>random hex
+ digits</varname> + <varname>tkey-domain</varname>.
+ In most cases, the <command>domainname</command>
+ should be the server's domain name, or an otherwise
+ non-existent subdomain like
+ "_tkey.<varname>domainname</varname>". If you are
+ using GSS-TSIG, this variable must be defined.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>tkey-dhkey</command></term>
+ <listitem>
+ <para>
+ The Diffie-Hellman key used by the server
+ to generate shared keys with clients using the Diffie-Hellman
+ mode
+ of <command>TKEY</command>. The server must be
+ able to load the
+ public and private keys from files in the working directory.
+ In
+ most cases, the keyname should be the server's host name.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>cache-file</command></term>
+ <listitem>
+ <para>
+ This is for testing only. Do not use.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>dump-file</command></term>
+ <listitem>
+ <para>
+ The pathname of the file the server dumps
+ the database to when instructed to do so with
+ <command>rndc dumpdb</command>.
+ If not specified, the default is <filename>named_dump.db</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>memstatistics-file</command></term>
+ <listitem>
+ <para>
+ The pathname of the file the server writes memory
+ usage statistics to on exit. If not specified,
+ the default is <filename>named.memstats</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>pid-file</command></term>
+ <listitem>
+ <para>
+ The pathname of the file the server writes its process ID
+ in. If not specified, the default is
+ <filename>/var/run/named/named.pid</filename>.
+ The pid-file is used by programs that want to send signals to
+ the running
+ name server. Specifying <command>pid-file none</command> disables the
+ use of a PID file &mdash; no file will be written and any
+ existing one will be removed. Note that <command>none</command>
+ is a keyword, not a filename, and therefore is not enclosed
+ in
+ double quotes.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>recursing-file</command></term>
+ <listitem>
+ <para>
+ The pathname of the file the server dumps
+ the queries that are currently recursing when instructed
+ to do so with <command>rndc recursing</command>.
+ If not specified, the default is <filename>named.recursing</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>statistics-file</command></term>
+ <listitem>
+ <para>
+ The pathname of the file the server appends statistics
+ to when instructed to do so using <command>rndc stats</command>.
+ If not specified, the default is <filename>named.stats</filename> in the
+ server's current directory. The format of the file is
+ described
+ in <xref linkend="statsfile"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>port</command></term>
+ <listitem>
+ <para>
+ The UDP/TCP port number the server uses for
+ receiving and sending DNS protocol traffic.
+ The default is 53. This option is mainly intended for server
+ testing;
+ a server using a port other than 53 will not be able to
+ communicate with
+ the global DNS.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>random-device</command></term>
+ <listitem>
+ <para>
+ The source of entropy to be used by the server. Entropy is
+ primarily needed
+ for DNSSEC operations, such as TKEY transactions and dynamic
+ update of signed
+ zones. This options specifies the device (or file) from which
+ to read
+ entropy. If this is a file, operations requiring entropy will
+ fail when the
+ file has been exhausted. If not specified, the default value
+ is
+ <filename>/dev/random</filename>
+ (or equivalent) when present, and none otherwise. The
+ <command>random-device</command> option takes
+ effect during
+ the initial configuration load at server startup time and
+ is ignored on subsequent reloads.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>preferred-glue</command></term>
+ <listitem>
+ <para>
+ If specified, the listed type (A or AAAA) will be emitted
+ before other glue
+ in the additional section of a query response.
+ The default is not to prefer any type (NONE).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>root-delegation-only</command></term>
+ <listitem>
+ <para>
+ Turn on enforcement of delegation-only in TLDs (top level domains) and root zones
+ with an optional
+ exclude list.
+ </para>
+ <para>
+ Note some TLDs are not delegation only (e.g. "DE", "LV", "US"
+ and "MUSEUM").
+ </para>
+
+<programlisting>
+options {
+ root-delegation-only exclude { "de"; "lv"; "us"; "museum"; };
+};
+</programlisting>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>disable-algorithms</command></term>
+ <listitem>
+ <para>
+ Disable the specified DNSSEC algorithms at and below the
+ specified name.
+ Multiple <command>disable-algorithms</command>
+ statements are allowed.
+ Only the most specific will be applied.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>dnssec-lookaside</command></term>
+ <listitem>
+ <para>
+ When set, <command>dnssec-lookaside</command>
+ 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 <command>dnssec-lookaside</command>, 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
+ record does) the DNSKEY RRset is deemed to be trusted.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>dnssec-must-be-secure</command></term>
+ <listitem>
+ <para>
+ Specify hierarchies which must be or may not be secure (signed and
+ validated).
+ If <userinput>yes</userinput>, then named will only accept
+ answers if they
+ are secure.
+ If <userinput>no</userinput>, then normal dnssec validation
+ applies
+ allowing for insecure answers to be accepted.
+ The specified domain must be under a <command>trusted-key</command> or
+ <command>dnssec-lookaside</command> must be
+ active.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <sect3 id="boolean_options">
+ <title>Boolean Options</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>auth-nxdomain</command></term>
+ <listitem>
+ <para>
+ If <userinput>yes</userinput>, then the <command>AA</command> bit
+ is always set on NXDOMAIN responses, even if the server is
+ not actually
+ authoritative. The default is <userinput>no</userinput>;
+ this is
+ a change from <acronym>BIND</acronym> 8. If you
+ are using very old DNS software, you
+ may need to set it to <userinput>yes</userinput>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>deallocate-on-exit</command></term>
+ <listitem>
+ <para>
+ This option was used in <acronym>BIND</acronym>
+ 8 to enable checking
+ for memory leaks on exit. <acronym>BIND</acronym> 9 ignores the option and always performs
+ the checks.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>memstatistics</command></term>
+ <listitem>
+ <para>
+ Write memory statistics to the file specified by
+ <command>memstatistics-file</command> at exit.
+ The default is <userinput>no</userinput> unless
+ '-m record' is specified on the command line in
+ which case it is <userinput>yes</userinput>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>dialup</command></term>
+ <listitem>
+ <para>
+ If <userinput>yes</userinput>, then the
+ server treats all zones as if they are doing zone transfers
+ across
+ a dial-on-demand dialup link, which can be brought up by
+ traffic
+ originating from this server. This has different effects
+ according
+ to zone type and concentrates the zone maintenance so that
+ it all
+ happens in a short interval, once every <command>heartbeat-interval</command> and
+ hopefully during the one call. It also suppresses some of
+ the normal
+ zone maintenance traffic. The default is <userinput>no</userinput>.
+ </para>
+ <para>
+ The <command>dialup</command> option
+ may also be specified in the <command>view</command> and
+ <command>zone</command> statements,
+ in which case it overrides the global <command>dialup</command>
+ option.
+ </para>
+ <para>
+ If the zone is a master zone, then the server will send out a
+ NOTIFY
+ request to all the slaves (default). This should trigger the
+ zone serial
+ number check in the slave (providing it supports NOTIFY)
+ allowing the slave
+ to verify the zone while the connection is active.
+ The set of servers to which NOTIFY is sent can be controlled
+ by
+ <command>notify</command> and <command>also-notify</command>.
+ </para>
+ <para>
+ If the
+ zone is a slave or stub zone, then the server will suppress
+ the regular
+ "zone up to date" (refresh) queries and only perform them
+ when the
+ <command>heartbeat-interval</command> expires in
+ addition to sending
+ NOTIFY requests.
+ </para>
+ <para>
+ Finer control can be achieved by using
+ <userinput>notify</userinput> which only sends NOTIFY
+ messages,
+ <userinput>notify-passive</userinput> which sends NOTIFY
+ messages and
+ suppresses the normal refresh queries, <userinput>refresh</userinput>
+ which suppresses normal refresh processing and sends refresh
+ queries
+ when the <command>heartbeat-interval</command>
+ expires, and
+ <userinput>passive</userinput> which just disables normal
+ refresh
+ processing.
+ </para>
+
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="4" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.150in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="1.150in"/>
+ <colspec colname="3" colnum="3" colsep="0" colwidth="1.150in"/>
+ <colspec colname="4" colnum="4" colsep="0" colwidth="1.150in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ dialup mode
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ normal refresh
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ heart-beat refresh
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ heart-beat notify
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>no</command> (default)</para>
+ </entry>
+ <entry colname="2">
+ <para>
+ yes
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ no
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ no
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>yes</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ no
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ yes
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ yes
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>notify</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ yes
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ no
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ yes
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>refresh</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ no
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ yes
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ no
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>passive</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ no
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ no
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ no
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>notify-passive</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ no
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ no
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ yes
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>
+ Note that normal NOTIFY processing is not affected by
+ <command>dialup</command>.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>fake-iquery</command></term>
+ <listitem>
+ <para>
+ In <acronym>BIND</acronym> 8, this option
+ enabled simulating the obsolete DNS query type
+ IQUERY. <acronym>BIND</acronym> 9 never does
+ IQUERY simulation.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>fetch-glue</command></term>
+ <listitem>
+ <para>
+ This option is obsolete.
+ In BIND 8, <userinput>fetch-glue yes</userinput>
+ caused the server to attempt to fetch glue resource records
+ it
+ didn't have when constructing the additional
+ data section of a response. This is now considered a bad
+ idea
+ and BIND 9 never does it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>flush-zones-on-shutdown</command></term>
+ <listitem>
+ <para>
+ When the nameserver exits due receiving SIGTERM,
+ flush or do not flush any pending zone writes. The default
+ is
+ <command>flush-zones-on-shutdown</command> <userinput>no</userinput>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>has-old-clients</command></term>
+ <listitem>
+ <para>
+ This option was incorrectly implemented
+ in <acronym>BIND</acronym> 8, and is ignored by <acronym>BIND</acronym> 9.
+ To achieve the intended effect
+ of
+ <command>has-old-clients</command> <userinput>yes</userinput>, specify
+ the two separate options <command>auth-nxdomain</command> <userinput>yes</userinput>
+ and <command>rfc2308-type1</command> <userinput>no</userinput> instead.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>host-statistics</command></term>
+ <listitem>
+ <para>
+ In BIND 8, this enables keeping of
+ statistics for every host that the name server interacts
+ with.
+ Not implemented in BIND 9.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>maintain-ixfr-base</command></term>
+ <listitem>
+ <para>
+ <emphasis>This option is obsolete</emphasis>.
+ It was used in <acronym>BIND</acronym> 8 to
+ determine whether a transaction log was
+ kept for Incremental Zone Transfer. <acronym>BIND</acronym> 9 maintains a transaction
+ log whenever possible. If you need to disable outgoing
+ incremental zone
+ transfers, use <command>provide-ixfr</command> <userinput>no</userinput>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>minimal-responses</command></term>
+ <listitem>
+ <para>
+ If <userinput>yes</userinput>, then when generating
+ responses the server will only add records to the authority
+ and additional data sections when they are required (e.g.
+ delegations, negative responses). This may improve the
+ performance of the server.
+ The default is <userinput>no</userinput>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>multiple-cnames</command></term>
+ <listitem>
+ <para>
+ This option was used in <acronym>BIND</acronym> 8 to allow
+ a domain name to have multiple CNAME records in violation of
+ the DNS standards. <acronym>BIND</acronym> 9.2 onwards
+ always strictly enforces the CNAME rules both in master
+ files and dynamic updates.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>notify</command></term>
+ <listitem>
+ <para>
+ If <userinput>yes</userinput> (the default),
+ DNS NOTIFY messages are sent when a zone the server is
+ authoritative for
+ changes, see <xref linkend="notify"/>. The messages are
+ sent to the
+ servers listed in the zone's NS records (except the master
+ server identified
+ in the SOA MNAME field), and to any servers listed in the
+ <command>also-notify</command> option.
+ </para>
+ <para>
+ If <userinput>master-only</userinput>, notifies are only
+ sent
+ for master zones.
+ If <userinput>explicit</userinput>, notifies are sent only
+ to
+ servers explicitly listed using <command>also-notify</command>.
+ If <userinput>no</userinput>, no notifies are sent.
+ </para>
+ <para>
+ The <command>notify</command> option may also be
+ specified in the <command>zone</command>
+ statement,
+ in which case it overrides the <command>options notify</command> statement.
+ It would only be necessary to turn off this option if it
+ caused slaves
+ to crash.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>notify-to-soa</command></term>
+ <listitem>
+ <para>
+ If <userinput>yes</userinput> do not check the nameservers
+ in the NS RRset against the SOA MNAME. Normally a NOTIFY
+ message is not sent to the SOA MNAME (SOA ORIGIN) as it is
+ supposed to contain the name of the ultimate master.
+ Sometimes, however, a slave is listed as the SOA MNAME in
+ hidden master configurations and in that case you would
+ want the ultimate master to still send NOTIFY messages to
+ all the nameservers listed in the NS RRset.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>recursion</command></term>
+ <listitem>
+ <para>
+ If <userinput>yes</userinput>, and a
+ DNS query requests recursion, then the server will attempt
+ to do
+ all the work required to answer the query. If recursion is
+ off
+ and the server does not already know the answer, it will
+ return a
+ referral response. The default is
+ <userinput>yes</userinput>.
+ Note that setting <command>recursion no</command> does not prevent
+ clients from getting data from the server's cache; it only
+ prevents new data from being cached as an effect of client
+ queries.
+ Caching may still occur as an effect the server's internal
+ operation, such as NOTIFY address lookups.
+ See also <command>fetch-glue</command> above.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>rfc2308-type1</command></term>
+ <listitem>
+ <para>
+ Setting this to <userinput>yes</userinput> will
+ cause the server to send NS records along with the SOA
+ record for negative
+ answers. The default is <userinput>no</userinput>.
+ </para>
+ <note>
+ <simpara>
+ Not yet implemented in <acronym>BIND</acronym>
+ 9.
+ </simpara>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>use-id-pool</command></term>
+ <listitem>
+ <para>
+ <emphasis>This option is obsolete</emphasis>.
+ <acronym>BIND</acronym> 9 always allocates query
+ IDs from a pool.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>zone-statistics</command></term>
+ <listitem>
+ <para>
+ If <userinput>yes</userinput>, the server will collect
+ statistical data on all zones (unless specifically turned
+ off
+ on a per-zone basis by specifying <command>zone-statistics no</command>
+ in the <command>zone</command> statement).
+ These statistics may be accessed
+ using <command>rndc stats</command>, which will
+ dump them to the file listed
+ in the <command>statistics-file</command>. See
+ also <xref linkend="statsfile"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>use-ixfr</command></term>
+ <listitem>
+ <para>
+ <emphasis>This option is obsolete</emphasis>.
+ If you need to disable IXFR to a particular server or
+ servers, see
+ the information on the <command>provide-ixfr</command> option
+ in <xref linkend="server_statement_definition_and_usage"/>.
+ See also
+ <xref linkend="incremental_zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>provide-ixfr</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>provide-ixfr</command> in
+ <xref linkend="server_statement_definition_and_usage"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>request-ixfr</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>request-ixfr</command> in
+ <xref linkend="server_statement_definition_and_usage"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>treat-cr-as-space</command></term>
+ <listitem>
+ <para>
+ This option was used in <acronym>BIND</acronym>
+ 8 to make
+ the server treat carriage return ("<command>\r</command>") characters the same way
+ as a space or tab character,
+ to facilitate loading of zone files on a UNIX system that
+ were generated
+ on an NT or DOS machine. In <acronym>BIND</acronym> 9, both UNIX "<command>\n</command>"
+ and NT/DOS "<command>\r\n</command>" newlines
+ are always accepted,
+ and the option is ignored.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>additional-from-auth</command></term>
+ <term><command>additional-from-cache</command></term>
+ <listitem>
+
+ <para>
+ These options control the behavior of an authoritative
+ server when
+ answering queries which have additional data, or when
+ following CNAME
+ and DNAME chains.
+ </para>
+
+ <para>
+ When both of these options are set to <userinput>yes</userinput>
+ (the default) and a
+ query is being answered from authoritative data (a zone
+ configured into the server), the additional data section of
+ the
+ reply will be filled in using data from other authoritative
+ zones
+ and from the cache. In some situations this is undesirable,
+ such
+ as when there is concern over the correctness of the cache,
+ or
+ in servers where slave zones may be added and modified by
+ untrusted third parties. Also, avoiding
+ the search for this additional data will speed up server
+ operations
+ at the possible expense of additional queries to resolve
+ what would
+ otherwise be provided in the additional section.
+ </para>
+
+ <para>
+ For example, if a query asks for an MX record for host <literal>foo.example.com</literal>,
+ and the record found is "<literal>MX 10 mail.example.net</literal>", normally the address
+ records (A and AAAA) for <literal>mail.example.net</literal> will be provided as well,
+ if known, even though they are not in the example.com zone.
+ Setting these options to <command>no</command>
+ disables this behavior and makes
+ the server only search for additional data in the zone it
+ answers from.
+ </para>
+
+ <para>
+ These options are intended for use in authoritative-only
+ servers, or in authoritative-only views. Attempts to set
+ them to <command>no</command> without also
+ specifying
+ <command>recursion no</command> will cause the
+ server to
+ ignore the options and log a warning message.
+ </para>
+
+ <para>
+ Specifying <command>additional-from-cache no</command> actually
+ disables the use of the cache not only for additional data
+ lookups
+ but also when looking up the answer. This is usually the
+ desired
+ behavior in an authoritative-only server where the
+ correctness of
+ the cached data is an issue.
+ </para>
+
+ <para>
+ When a name server is non-recursively queried for a name
+ that is not
+ below the apex of any served zone, it normally answers with
+ an
+ "upwards referral" to the root servers or the servers of
+ some other
+ known parent of the query name. Since the data in an
+ upwards referral
+ comes from the cache, the server will not be able to provide
+ upwards
+ referrals when <command>additional-from-cache no</command>
+ has been specified. Instead, it will respond to such
+ queries
+ with REFUSED. This should not cause any problems since
+ upwards referrals are not required for the resolution
+ process.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>match-mapped-addresses</command></term>
+ <listitem>
+ <para>
+ If <userinput>yes</userinput>, then an
+ IPv4-mapped IPv6 address will match any address match
+ list entries that match the corresponding IPv4 address.
+ Enabling this option is sometimes useful on IPv6-enabled
+ Linux
+ systems, to work around a kernel quirk that causes IPv4
+ TCP connections such as zone transfers to be accepted
+ on an IPv6 socket using mapped addresses, causing
+ address match lists designed for IPv4 to fail to match.
+ The use of this option for any other purpose is discouraged.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>ixfr-from-differences</command></term>
+ <listitem>
+ <para>
+ When <userinput>yes</userinput> and the server loads a new version of a master
+ zone from its zone file or receives a new version of a slave
+ file by a non-incremental zone transfer, it will compare
+ the new version to the previous one and calculate a set
+ of differences. The differences are then logged in the
+ zone's journal file such that the changes can be transmitted
+ to downstream slaves as an incremental zone transfer.
+ </para>
+ <para>
+ By allowing incremental zone transfers to be used for
+ non-dynamic zones, this option saves bandwidth at the
+ expense of increased CPU and memory consumption at the
+ master.
+ In particular, if the new version of a zone is completely
+ different from the previous one, the set of differences
+ will be of a size comparable to the combined size of the
+ old and new zone version, and the server will need to
+ temporarily allocate memory to hold this complete
+ difference set.
+ </para>
+ <para><command>ixfr-from-differences</command>
+ also accepts <command>master</command> and
+ <command>slave</command> at the view and options
+ levels which causes
+ <command>ixfr-from-differences</command> to be enabled for
+ all <command>master</command> or
+ <command>slave</command> zones respectively.
+ It is off by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>multi-master</command></term>
+ <listitem>
+ <para>
+ This should be set when you have multiple masters for a zone
+ and the
+ addresses refer to different machines. If <userinput>yes</userinput>, named will
+ not log
+ when the serial number on the master is less than what named
+ currently
+ has. The default is <userinput>no</userinput>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>dnssec-enable</command></term>
+ <listitem>
+ <para>
+ Enable DNSSEC support in named. Unless set to <userinput>yes</userinput>,
+ named behaves as if it does not support DNSSEC.
+ The default is <userinput>yes</userinput>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>dnssec-validation</command></term>
+ <listitem>
+ <para>
+ Enable DNSSEC validation in named.
+ Note <command>dnssec-enable</command> also needs to be
+ set to <userinput>yes</userinput> to be effective.
+ The default is <userinput>yes</userinput>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>dnssec-accept-expired</command></term>
+ <listitem>
+ <para>
+ Accept expired signatures when verifying DNSSEC signatures.
+ The default is <userinput>no</userinput>.
+ Setting this option to "yes" leaves named vulnerable to replay attacks.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>querylog</command></term>
+ <listitem>
+ <para>
+ Specify whether query logging should be started when named
+ starts.
+ If <command>querylog</command> is not specified,
+ then the query logging
+ is determined by the presence of the logging category <command>queries</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-names</command></term>
+ <listitem>
+ <para>
+ This option is used to restrict the character set and syntax
+ of
+ certain domain names in master files and/or DNS responses
+ received
+ from the network. The default varies according to usage
+ area. For
+ <command>master</command> zones the default is <command>fail</command>.
+ For <command>slave</command> zones the default
+ is <command>warn</command>.
+ For answers received from the network (<command>response</command>)
+ the default is <command>ignore</command>.
+ </para>
+ <para>
+ The rules for legal hostnames and mail domains are derived
+ from RFC 952 and RFC 821 as modified by RFC 1123.
+ </para>
+ <para><command>check-names</command>
+ applies to the owner names of A, AAAA and MX records.
+ It also applies to the domain names in the RDATA of NS, SOA
+ and MX records.
+ It also applies to the RDATA of PTR records where the owner
+ name indicated that it is a reverse lookup of a hostname
+ (the owner name ends in IN-ADDR.ARPA, IP6.ARPA, or IP6.INT).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-mx</command></term>
+ <listitem>
+ <para>
+ Check whether the MX record appears to refer to a IP address.
+ The default is to <command>warn</command>. Other possible
+ values are <command>fail</command> and
+ <command>ignore</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-wildcard</command></term>
+ <listitem>
+ <para>
+ This option is used to check for non-terminal wildcards.
+ The use of non-terminal wildcards is almost always as a
+ result of a failure
+ to understand the wildcard matching algorithm (RFC 1034).
+ This option
+ affects master zones. The default (<command>yes</command>) is to check
+ for non-terminal wildcards and issue a warning.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-integrity</command></term>
+ <listitem>
+ <para>
+ Perform post load zone integrity checks on master
+ zones. This checks that MX and SRV records refer
+ to address (A or AAAA) records and that glue
+ address records exist for delegated zones. For
+ MX and SRV records only in-zone hostnames are
+ checked (for out-of-zone hostnames use
+ <command>named-checkzone</command>).
+ For NS records only names below top of zone are
+ checked (for out-of-zone names and glue consistency
+ checks use <command>named-checkzone</command>).
+ The default is <command>yes</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-mx-cname</command></term>
+ <listitem>
+ <para>
+ If <command>check-integrity</command> is set then
+ fail, warn or ignore MX records that refer
+ to CNAMES. The default is to <command>warn</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-srv-cname</command></term>
+ <listitem>
+ <para>
+ If <command>check-integrity</command> is set then
+ fail, warn or ignore SRV records that refer
+ to CNAMES. The default is to <command>warn</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-sibling</command></term>
+ <listitem>
+ <para>
+ When performing integrity checks, also check that
+ sibling glue exists. The default is <command>yes</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>zero-no-soa-ttl</command></term>
+ <listitem>
+ <para>
+ When returning authoritative negative responses to
+ SOA queries set the TTL of the SOA record returned in
+ the authority section to zero.
+ The default is <command>yes</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>zero-no-soa-ttl-cache</command></term>
+ <listitem>
+ <para>
+ When caching a negative response to a SOA query
+ set the TTL to zero.
+ The default is <command>no</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>update-check-ksk</command></term>
+ <listitem>
+ <para>
+ 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 <command>yes</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>try-tcp-refresh</command></term>
+ <listitem>
+ <para>
+ Try to refresh the zone using TCP if UDP queries fail.
+ For BIND 8 compatibility, the default is
+ <command>yes</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </sect3>
+
+ <sect3>
+ <title>Forwarding</title>
+ <para>
+ The forwarding facility can be used to create a large site-wide
+ cache on a few servers, reducing traffic over links to external
+ name servers. It can also be used to allow queries by servers that
+ do not have direct access to the Internet, but wish to look up
+ exterior
+ names anyway. Forwarding occurs only on those queries for which
+ the server is not authoritative and does not have the answer in
+ its cache.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>forward</command></term>
+ <listitem>
+ <para>
+ This option is only meaningful if the
+ forwarders list is not empty. A value of <varname>first</varname>,
+ the default, causes the server to query the forwarders
+ first &mdash; and
+ if that doesn't answer the question, the server will then
+ look for
+ the answer itself. If <varname>only</varname> is
+ specified, the
+ server will only query the forwarders.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>forwarders</command></term>
+ <listitem>
+ <para>
+ Specifies the IP addresses to be used
+ for forwarding. The default is the empty list (no
+ forwarding).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ <para>
+ Forwarding can also be configured on a per-domain basis, allowing
+ for the global forwarding options to be overridden in a variety
+ of ways. You can set particular domains to use different
+ forwarders,
+ or have a different <command>forward only/first</command> behavior,
+ or not forward at all, see <xref linkend="zone_statement_grammar"/>.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title>Dual-stack Servers</title>
+ <para>
+ Dual-stack servers are used as servers of last resort to work
+ around
+ problems in reachability due the lack of support for either IPv4
+ or IPv6
+ on the host machine.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>dual-stack-servers</command></term>
+ <listitem>
+ <para>
+ Specifies host names or addresses of machines with access to
+ both IPv4 and IPv6 transports. If a hostname is used, the
+ server must be able
+ to resolve the name using only the transport it has. If the
+ machine is dual
+ stacked, then the <command>dual-stack-servers</command> have no effect unless
+ access to a transport has been disabled on the command line
+ (e.g. <command>named -4</command>).
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect3>
+
+ <sect3 id="access_control">
+ <title>Access Control</title>
+
+ <para>
+ Access to the server can be restricted based on the IP address
+ of the requesting system. See <xref linkend="address_match_lists"/> for
+ details on how to specify IP address lists.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>allow-notify</command></term>
+ <listitem>
+ <para>
+ Specifies which hosts are allowed to
+ notify this server, a slave, of zone changes in addition
+ to the zone masters.
+ <command>allow-notify</command> may also be
+ specified in the
+ <command>zone</command> statement, in which case
+ it overrides the
+ <command>options allow-notify</command>
+ statement. It is only meaningful
+ for a slave zone. If not specified, the default is to
+ process notify messages
+ only from a zone's master.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-query</command></term>
+ <listitem>
+ <para>
+ Specifies which hosts are allowed to ask ordinary
+ DNS questions. <command>allow-query</command> may
+ also be specified in the <command>zone</command>
+ statement, in which case it overrides the
+ <command>options allow-query</command> statement.
+ If not specified, the default is to allow queries
+ from all hosts.
+ </para>
+ <note>
+ <para>
+ <command>allow-query-cache</command> is now
+ used to specify access to the cache.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-query-on</command></term>
+ <listitem>
+ <para>
+ Specifies which local addresses can accept ordinary
+ DNS questions. This makes it possible, for instance,
+ to allow queries on internal-facing interfaces but
+ disallow them on external-facing ones, without
+ necessarily knowing the internal network's addresses.
+ </para>
+ <para>
+ <command>allow-query-on</command> may
+ also be specified in the <command>zone</command>
+ statement, in which case it overrides the
+ <command>options allow-query-on</command> statement.
+ </para>
+ <para>
+ If not specified, the default is to allow queries
+ on all addresses.
+ </para>
+ <note>
+ <para>
+ <command>allow-query-cache</command> is
+ used to specify access to the cache.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-query-cache</command></term>
+ <listitem>
+ <para>
+ Specifies which hosts are allowed to get answers
+ from the cache. If <command>allow-query-cache</command>
+ is not set then <command>allow-recursion</command>
+ is used if set, otherwise <command>allow-query</command>
+ is used if set, otherwise the default
+ (<command>localnets;</command>
+ <command>localhost;</command>) is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-query-cache-on</command></term>
+ <listitem>
+ <para>
+ Specifies which local addresses can give answers
+ from the cache. If not specified, the default is
+ to allow cache queries on any address,
+ <command>localnets</command> and
+ <command>localhost</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-recursion</command></term>
+ <listitem>
+ <para>
+ Specifies which hosts are allowed to make recursive
+ queries through this server. If
+ <command>allow-recursion</command> is not set
+ then <command>allow-query-cache</command> is
+ used if set, otherwise <command>allow-query</command>
+ is used if set, otherwise the default
+ (<command>localnets;</command>
+ <command>localhost;</command>) is used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-recursion-on</command></term>
+ <listitem>
+ <para>
+ Specifies which local addresses can accept recursive
+ queries. If not specified, the default is to allow
+ recursive queries on all addresses.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-update</command></term>
+ <listitem>
+ <para>
+ Specifies which hosts are allowed to
+ submit Dynamic DNS updates for master zones. The default is
+ to deny
+ updates from all hosts. Note that allowing updates based
+ on the requestor's IP address is insecure; see
+ <xref linkend="dynamic_update_security"/> for details.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-update-forwarding</command></term>
+ <listitem>
+ <para>
+ Specifies which hosts are allowed to
+ submit Dynamic DNS updates to slave zones to be forwarded to
+ the
+ master. The default is <userinput>{ none; }</userinput>,
+ which
+ means that no update forwarding will be performed. To
+ enable
+ update forwarding, specify
+ <userinput>allow-update-forwarding { any; };</userinput>.
+ Specifying values other than <userinput>{ none; }</userinput> or
+ <userinput>{ any; }</userinput> is usually
+ counterproductive, since
+ the responsibility for update access control should rest
+ with the
+ master server, not the slaves.
+ </para>
+ <para>
+ Note that enabling the update forwarding feature on a slave
+ server
+ may expose master servers relying on insecure IP address
+ based
+ access control to attacks; see <xref linkend="dynamic_update_security"/>
+ for more details.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-v6-synthesis</command></term>
+ <listitem>
+ <para>
+ This option was introduced for the smooth transition from
+ AAAA
+ to A6 and from "nibble labels" to binary labels.
+ However, since both A6 and binary labels were then
+ deprecated,
+ this option was also deprecated.
+ It is now ignored with some warning messages.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-transfer</command></term>
+ <listitem>
+ <para>
+ Specifies which hosts are allowed to
+ receive zone transfers from the server. <command>allow-transfer</command> may
+ also be specified in the <command>zone</command>
+ statement, in which
+ case it overrides the <command>options allow-transfer</command> statement.
+ If not specified, the default is to allow transfers to all
+ hosts.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>blackhole</command></term>
+ <listitem>
+ <para>
+ 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 <userinput>none</userinput>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </sect3>
+
+ <sect3>
+ <title>Interfaces</title>
+ <para>
+ The interfaces and ports that the server will answer queries
+ from may be specified using the <command>listen-on</command> option. <command>listen-on</command> takes
+ an optional port, and an <varname>address_match_list</varname>.
+ The server will listen on all interfaces allowed by the address
+ match list. If a port is not specified, port 53 will be used.
+ </para>
+ <para>
+ Multiple <command>listen-on</command> statements are
+ allowed.
+ For example,
+ </para>
+
+<programlisting>listen-on { 5.6.7.8; };
+listen-on port 1234 { !1.2.3.4; 1.2/16; };
+</programlisting>
+
+ <para>
+ will enable the name server on port 53 for the IP address
+ 5.6.7.8, and on port 1234 of an address on the machine in net
+ 1.2 that is not 1.2.3.4.
+ </para>
+
+ <para>
+ If no <command>listen-on</command> is specified, the
+ server will listen on port 53 on all IPv4 interfaces.
+ </para>
+
+ <para>
+ The <command>listen-on-v6</command> option is used to
+ specify the interfaces and the ports on which the server will
+ listen
+ for incoming queries sent using IPv6.
+ </para>
+
+ <para>
+ When <programlisting>{ any; }</programlisting> is
+ specified
+ as the <varname>address_match_list</varname> for the
+ <command>listen-on-v6</command> option,
+ the server does not bind a separate socket to each IPv6 interface
+ address as it does for IPv4 if the operating system has enough API
+ support for IPv6 (specifically if it conforms to RFC 3493 and RFC
+ 3542).
+ Instead, it listens on the IPv6 wildcard address.
+ If the system only has incomplete API support for IPv6, however,
+ the behavior is the same as that for IPv4.
+ </para>
+
+ <para>
+ A list of particular IPv6 addresses can also be specified, in
+ which case
+ the server listens on a separate socket for each specified
+ address,
+ regardless of whether the desired API is supported by the system.
+ </para>
+
+ <para>
+ Multiple <command>listen-on-v6</command> options can
+ be used.
+ For example,
+ </para>
+
+<programlisting>listen-on-v6 { any; };
+listen-on-v6 port 1234 { !2001:db8::/32; any; };
+</programlisting>
+
+ <para>
+ will enable the name server on port 53 for any IPv6 addresses
+ (with a single wildcard socket),
+ and on port 1234 of IPv6 addresses that is not in the prefix
+ 2001:db8::/32 (with separate sockets for each matched address.)
+ </para>
+
+ <para>
+ To make the server not listen on any IPv6 address, use
+ </para>
+
+<programlisting>listen-on-v6 { none; };
+</programlisting>
+
+ <para>
+ If no <command>listen-on-v6</command> option is
+ specified, the server will not listen on any IPv6 address
+ unless <command>-6</command> is specified when named is
+ invoked. If <command>-6</command> is specified then
+ named will listen on port 53 on all IPv6 interfaces by default.
+ </para>
+ </sect3>
+
+ <sect3 id="query_address">
+ <title>Query Address</title>
+ <para>
+ If the server doesn't know the answer to a question, it will
+ query other name servers. <command>query-source</command> specifies
+ the address and port used for such queries. For queries sent over
+ IPv6, there is a separate <command>query-source-v6</command> option.
+ If <command>address</command> is <command>*</command> (asterisk) or is omitted,
+ a wildcard IP address (<command>INADDR_ANY</command>)
+ will be used.
+ </para>
+
+ <para>
+ If <command>port</command> is <command>*</command> or is omitted,
+ a random port number from a pre-configured
+ range is picked up and will be used for each query.
+ The port range(s) is that specified in
+ the <command>use-v4-udp-ports</command> (for IPv4)
+ and <command>use-v6-udp-ports</command> (for IPv6)
+ options, excluding the ranges specified in
+ the <command>avoid-v4-udp-ports</command>
+ and <command>avoid-v6-udp-ports</command> options, respectively.
+ </para>
+
+ <para>
+ The defaults of the <command>query-source</command> and
+ <command>query-source-v6</command> options
+ are:
+ </para>
+
+<programlisting>query-source address * port *;
+query-source-v6 address * port *;
+</programlisting>
+
+ <para>
+ If <command>use-v4-udp-ports</command> or
+ <command>use-v6-udp-ports</command> is unspecified,
+ <command>named</command> will check if the operating
+ system provides a programming interface to retrieve the
+ system's default range for ephemeral ports.
+ If such an interface is available,
+ <command>named</command> will use the corresponding system
+ default range; otherwise, it will use its own defaults:
+ </para>
+
+<programlisting>use-v4-udp-ports { range 1024 65535; };
+use-v6-udp-ports { range 1024 65535; };
+</programlisting>
+
+ <para>
+ Note: make sure the ranges be sufficiently large for
+ security. A desirable size depends on various parameters,
+ but we generally recommend it contain at least 16384 ports
+ (14 bits of entropy).
+ Note also that the system's default range when used may be
+ too small for this purpose, and that the range may even be
+ changed while <command>named</command> is running; the new
+ range will automatically be applied when <command>named</command>
+ is reloaded.
+ It is encouraged to
+ configure <command>use-v4-udp-ports</command> and
+ <command>use-v6-udp-ports</command> explicitly so that the
+ ranges are sufficiently large and are reasonably
+ independent from the ranges used by other applications.
+ </para>
+
+ <para>
+ Note: the operational configuration
+ where <command>named</command> runs may prohibit the use
+ of some ports. For example, UNIX systems will not allow
+ <command>named</command> running without a root privilege
+ to use ports less than 1024.
+ If such ports are included in the specified (or detected)
+ set of query ports, the corresponding query attempts will
+ fail, resulting in resolution failures or delay.
+ It is therefore important to configure the set of ports
+ that can be safely used in the expected operational environment.
+ </para>
+
+ <para>
+ The defaults of the <command>avoid-v4-udp-ports</command> and
+ <command>avoid-v6-udp-ports</command> options
+ are:
+ </para>
+
+<programlisting>avoid-v4-udp-ports {};
+avoid-v6-udp-ports {};
+</programlisting>
+
+ <para>
+ Note: BIND 9.5.0 introduced
+ the <command>use-queryport-pool</command>
+ option to support a pool of such random ports, but this
+ option is now obsolete because reusing the same ports in
+ the pool may not be sufficiently secure.
+ For the same reason, it is generally strongly discouraged to
+ specify a particular port for the
+ <command>query-source</command> or
+ <command>query-source-v6</command> options;
+ it implicitly disables the use of randomized port numbers.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>use-queryport-pool</command></term>
+ <listitem>
+ <para>
+ This option is obsolete.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>queryport-pool-ports</command></term>
+ <listitem>
+ <para>
+ This option is obsolete.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>queryport-pool-updateinterval</command></term>
+ <listitem>
+ <para>
+ This option is obsolete.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ <note>
+ <para>
+ The address specified in the <command>query-source</command> option
+ is used for both UDP and TCP queries, but the port applies only
+ to UDP queries. TCP queries always use a random
+ unprivileged port.
+ </para>
+ </note>
+ <note>
+ <para>
+ Solaris 2.5.1 and earlier does not support setting the source
+ address for TCP sockets.
+ </para>
+ </note>
+ <note>
+ <para>
+ See also <command>transfer-source</command> and
+ <command>notify-source</command>.
+ </para>
+ </note>
+ </sect3>
+
+ <sect3 id="zone_transfers">
+ <title>Zone Transfers</title>
+ <para>
+ <acronym>BIND</acronym> has mechanisms in place to
+ facilitate zone transfers
+ and set limits on the amount of load that transfers place on the
+ system. The following options apply to zone transfers.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>also-notify</command></term>
+ <listitem>
+ <para>
+ Defines a global list of IP addresses of name servers
+ that are also sent NOTIFY messages whenever a fresh copy of
+ the
+ zone is loaded, in addition to the servers listed in the
+ zone's NS records.
+ This helps to ensure that copies of the zones will
+ quickly converge on stealth servers. If an <command>also-notify</command> list
+ is given in a <command>zone</command> statement,
+ it will override
+ the <command>options also-notify</command>
+ statement. When a <command>zone notify</command>
+ statement
+ is set to <command>no</command>, the IP
+ addresses in the global <command>also-notify</command> list will
+ not be sent NOTIFY messages for that zone. The default is
+ the empty
+ list (no global notification list).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-transfer-time-in</command></term>
+ <listitem>
+ <para>
+ Inbound zone transfers running longer than
+ this many minutes will be terminated. The default is 120
+ minutes
+ (2 hours). The maximum value is 28 days (40320 minutes).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-transfer-idle-in</command></term>
+ <listitem>
+ <para>
+ Inbound zone transfers making no progress
+ in this many minutes will be terminated. The default is 60
+ minutes
+ (1 hour). The maximum value is 28 days (40320 minutes).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-transfer-time-out</command></term>
+ <listitem>
+ <para>
+ Outbound zone transfers running longer than
+ this many minutes will be terminated. The default is 120
+ minutes
+ (2 hours). The maximum value is 28 days (40320 minutes).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-transfer-idle-out</command></term>
+ <listitem>
+ <para>
+ Outbound zone transfers making no progress
+ in this many minutes will be terminated. The default is 60
+ minutes (1
+ hour). The maximum value is 28 days (40320 minutes).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>serial-query-rate</command></term>
+ <listitem>
+ <para>
+ Slave servers will periodically query master servers
+ to find out if zone serial numbers have changed. Each such
+ query uses
+ a minute amount of the slave server's network bandwidth. To
+ limit the
+ amount of bandwidth used, BIND 9 limits the rate at which
+ queries are
+ sent. The value of the <command>serial-query-rate</command> option,
+ an integer, is the maximum number of queries sent per
+ second.
+ The default is 20.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>serial-queries</command></term>
+ <listitem>
+ <para>
+ In BIND 8, the <command>serial-queries</command>
+ option
+ set the maximum number of concurrent serial number queries
+ allowed to be outstanding at any given time.
+ BIND 9 does not limit the number of outstanding
+ serial queries and ignores the <command>serial-queries</command> option.
+ Instead, it limits the rate at which the queries are sent
+ as defined using the <command>serial-query-rate</command> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>transfer-format</command></term>
+ <listitem>
+
+ <para>
+ Zone transfers can be sent using two different formats,
+ <command>one-answer</command> and
+ <command>many-answers</command>.
+ The <command>transfer-format</command> option is used
+ on the master server to determine which format it sends.
+ <command>one-answer</command> uses one DNS message per
+ resource record transferred.
+ <command>many-answers</command> packs as many resource
+ records as possible into a message.
+ <command>many-answers</command> is more efficient, but is
+ only supported by relatively new slave servers,
+ such as <acronym>BIND</acronym> 9, <acronym>BIND</acronym>
+ 8.x and <acronym>BIND</acronym> 4.9.5 onwards.
+ The <command>many-answers</command> format is also supported by
+ recent Microsoft Windows nameservers.
+ The default is <command>many-answers</command>.
+ <command>transfer-format</command> may be overridden on a
+ per-server basis by using the <command>server</command>
+ statement.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>transfers-in</command></term>
+ <listitem>
+ <para>
+ The maximum number of inbound zone transfers
+ that can be running concurrently. The default value is <literal>10</literal>.
+ Increasing <command>transfers-in</command> may
+ speed up the convergence
+ of slave zones, but it also may increase the load on the
+ local system.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>transfers-out</command></term>
+ <listitem>
+ <para>
+ The maximum number of outbound zone transfers
+ that can be running concurrently. Zone transfer requests in
+ excess
+ of the limit will be refused. The default value is <literal>10</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>transfers-per-ns</command></term>
+ <listitem>
+ <para>
+ The maximum number of inbound zone transfers
+ that can be concurrently transferring from a given remote
+ name server.
+ The default value is <literal>2</literal>.
+ Increasing <command>transfers-per-ns</command>
+ may
+ speed up the convergence of slave zones, but it also may
+ increase
+ the load on the remote name server. <command>transfers-per-ns</command> may
+ be overridden on a per-server basis by using the <command>transfers</command> phrase
+ of the <command>server</command> statement.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>transfer-source</command></term>
+ <listitem>
+ <para><command>transfer-source</command>
+ determines which local address will be bound to IPv4
+ TCP connections used to fetch zones transferred
+ inbound by the server. It also determines the
+ source IPv4 address, and optionally the UDP port,
+ used for the refresh queries and forwarded dynamic
+ updates. If not set, it defaults to a system
+ controlled value which will usually be the address
+ of the interface "closest to" the remote end. This
+ address must appear in the remote end's
+ <command>allow-transfer</command> option for the
+ zone being transferred, if one is specified. This
+ statement sets the
+ <command>transfer-source</command> for all zones,
+ but can be overridden on a per-view or per-zone
+ basis by including a
+ <command>transfer-source</command> statement within
+ the <command>view</command> or
+ <command>zone</command> block in the configuration
+ file.
+ </para>
+ <note>
+ <para>
+ Solaris 2.5.1 and earlier does not support setting the
+ source address for TCP sockets.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>transfer-source-v6</command></term>
+ <listitem>
+ <para>
+ The same as <command>transfer-source</command>,
+ except zone transfers are performed using IPv6.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>alt-transfer-source</command></term>
+ <listitem>
+ <para>
+ An alternate transfer source if the one listed in
+ <command>transfer-source</command> fails and
+ <command>use-alt-transfer-source</command> is
+ set.
+ </para>
+ <note>
+ If you do not wish the alternate transfer source
+ to be used, you should set
+ <command>use-alt-transfer-source</command>
+ appropriately and you should not depend upon
+ getting a answer back to the first refresh
+ query.
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>alt-transfer-source-v6</command></term>
+ <listitem>
+ <para>
+ An alternate transfer source if the one listed in
+ <command>transfer-source-v6</command> fails and
+ <command>use-alt-transfer-source</command> is
+ set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>use-alt-transfer-source</command></term>
+ <listitem>
+ <para>
+ Use the alternate transfer sources or not. If views are
+ specified this defaults to <command>no</command>
+ otherwise it defaults to
+ <command>yes</command> (for BIND 8
+ compatibility).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>notify-source</command></term>
+ <listitem>
+ <para><command>notify-source</command>
+ determines which local source address, and
+ optionally UDP port, will be used to send NOTIFY
+ messages. This address must appear in the slave
+ server's <command>masters</command> zone clause or
+ in an <command>allow-notify</command> clause. This
+ statement sets the <command>notify-source</command>
+ for all zones, but can be overridden on a per-zone or
+ per-view basis by including a
+ <command>notify-source</command> statement within
+ the <command>zone</command> or
+ <command>view</command> block in the configuration
+ file.
+ </para>
+ <note>
+ <para>
+ Solaris 2.5.1 and earlier does not support setting the
+ source address for TCP sockets.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>notify-source-v6</command></term>
+ <listitem>
+ <para>
+ Like <command>notify-source</command>,
+ but applies to notify messages sent to IPv6 addresses.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </sect3>
+
+ <sect3>
+ <title>UDP Port Lists</title>
+ <para>
+ <command>use-v4-udp-ports</command>,
+ <command>avoid-v4-udp-ports</command>,
+ <command>use-v6-udp-ports</command>, and
+ <command>avoid-v6-udp-ports</command>
+ specify a list of IPv4 and IPv6 UDP ports that will be
+ used or not used as source ports for UDP messages.
+ See <xref linkend="query_address"/> about how the
+ available ports are determined.
+ For example, with the following configuration
+ </para>
+
+<programlisting>
+use-v6-udp-ports { range 32768 65535; };
+avoid-v6-udp-ports { 40000; range 50000 60000; };
+</programlisting>
+
+ <para>
+ UDP ports of IPv6 messages sent
+ from <command>named</command> will be in one
+ of the following ranges: 32768 to 39999, 40001 to 49999,
+ and 60001 to 65535.
+ </para>
+
+ <para>
+ <command>avoid-v4-udp-ports</command> and
+ <command>avoid-v6-udp-ports</command> can be used
+ to prevent <command>named</command> from choosing as its random source port a
+ port that is blocked by your firewall or a port that is
+ used by other applications;
+ if a query went out with a source port blocked by a
+ firewall, the
+ answer would not get by the firewall and the name server would
+ have to query again.
+ Note: the desired range can also be represented only with
+ <command>use-v4-udp-ports</command> and
+ <command>use-v6-udp-ports</command>, and the
+ <command>avoid-</command> options are redundant in that
+ sense; they are provided for backward compatibility and
+ to possibly simplify the port specification.
+ </para>
+ </sect3>
+
+ <sect3>
+ <title>Operating System Resource Limits</title>
+
+ <para>
+ The server's usage of many system resources can be limited.
+ Scaled values are allowed when specifying resource limits. For
+ example, <command>1G</command> can be used instead of
+ <command>1073741824</command> to specify a limit of
+ one
+ gigabyte. <command>unlimited</command> requests
+ unlimited use, or the
+ maximum available amount. <command>default</command>
+ uses the limit
+ that was in force when the server was started. See the description
+ of <command>size_spec</command> in <xref linkend="configuration_file_elements"/>.
+ </para>
+
+ <para>
+ The following options set operating system resource limits for
+ the name server process. Some operating systems don't support
+ some or
+ any of the limits. On such systems, a warning will be issued if
+ the
+ unsupported limit is used.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>coresize</command></term>
+ <listitem>
+ <para>
+ The maximum size of a core dump. The default
+ is <literal>default</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>datasize</command></term>
+ <listitem>
+ <para>
+ The maximum amount of data memory the server
+ may use. The default is <literal>default</literal>.
+ This is a hard limit on server memory usage.
+ If the server attempts to allocate memory in excess of this
+ limit, the allocation will fail, which may in turn leave
+ the server unable to perform DNS service. Therefore,
+ this option is rarely useful as a way of limiting the
+ amount of memory used by the server, but it can be used
+ to raise an operating system data size limit that is
+ too small by default. If you wish to limit the amount
+ of memory used by the server, use the
+ <command>max-cache-size</command> and
+ <command>recursive-clients</command>
+ options instead.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>files</command></term>
+ <listitem>
+ <para>
+ The maximum number of files the server
+ may have open concurrently. The default is <literal>unlimited</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>stacksize</command></term>
+ <listitem>
+ <para>
+ The maximum amount of stack memory the server
+ may use. The default is <literal>default</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </sect3>
+
+ <sect3 id="server_resource_limits">
+ <title>Server Resource Limits</title>
+
+ <para>
+ The following options set limits on the server's
+ resource consumption that are enforced internally by the
+ server rather than the operating system.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>max-ixfr-log-size</command></term>
+ <listitem>
+ <para>
+ This option is obsolete; it is accepted
+ and ignored for BIND 8 compatibility. The option
+ <command>max-journal-size</command> performs a
+ similar function in BIND 9.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-journal-size</command></term>
+ <listitem>
+ <para>
+ Sets a maximum size for each journal file
+ (see <xref linkend="journal"/>). When the journal file
+ approaches
+ the specified size, some of the oldest transactions in the
+ journal
+ will be automatically removed. The default is
+ <literal>unlimited</literal>.
+ This may also be set on a per-zone basis.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>host-statistics-max</command></term>
+ <listitem>
+ <para>
+ In BIND 8, specifies the maximum number of host statistics
+ entries to be kept.
+ Not implemented in BIND 9.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>recursive-clients</command></term>
+ <listitem>
+ <para>
+ The maximum number of simultaneous recursive lookups
+ the server will perform on behalf of clients. The default
+ is
+ <literal>1000</literal>. Because each recursing
+ client uses a fair
+ bit of memory, on the order of 20 kilobytes, the value of
+ the
+ <command>recursive-clients</command> option may
+ have to be decreased
+ on hosts with limited memory.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>tcp-clients</command></term>
+ <listitem>
+ <para>
+ The maximum number of simultaneous client TCP
+ connections that the server will accept.
+ The default is <literal>100</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>reserved-sockets</command></term>
+ <listitem>
+ <para>
+ The number of file descriptors reserved for TCP, stdio,
+ etc. This needs to be big enough to cover the number of
+ interfaces named listens on, tcp-clients as well as
+ to provide room for outgoing TCP queries and incoming zone
+ transfers. The default is <literal>512</literal>.
+ The minimum value is <literal>128</literal> and the
+ maximum value is <literal>128</literal> less than
+ maxsockets (-S). This option may be removed in the future.
+ </para>
+ <para>
+ This option has little effect on Windows.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-cache-size</command></term>
+ <listitem>
+ <para>
+ The maximum amount of memory to use for the
+ server's cache, in bytes.
+ When the amount of data in the cache
+ reaches this limit, the server will cause records to expire
+ prematurely based on an LRU based strategy so that
+ the limit is not exceeded.
+ A value of 0 is special, meaning that
+ records are purged from the cache only when their
+ TTLs expire.
+ Another special keyword <userinput>unlimited</userinput>
+ means the maximum value of 32-bit unsigned integers
+ (0xffffffff), which may not have the same effect as
+ 0 on machines that support more than 32 bits of
+ memory space.
+ Any positive values less than 2MB will be ignored reset
+ to 2MB.
+ In a server with multiple views, the limit applies
+ separately to the cache of each view.
+ The default is 0.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>tcp-listen-queue</command></term>
+ <listitem>
+ <para>
+ The listen queue depth. The default and minimum is 3.
+ If the kernel supports the accept filter "dataready" this
+ also controls how
+ many TCP connections that will be queued in kernel space
+ waiting for
+ some data before being passed to accept. Values less than 3
+ will be
+ silently raised.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </sect3>
+
+ <sect3>
+ <title>Periodic Task Intervals</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>cleaning-interval</command></term>
+ <listitem>
+ <para>
+ This interval is effectively obsolete. Previously,
+ the server would remove expired resource records
+ from the cache every <command>cleaning-interval</command> minutes.
+ <acronym>BIND</acronym> 9 now manages cache
+ memory in a more sophisticated manner and does not
+ rely on the periodic cleaning any more.
+ Specifying this option therefore has no effect on
+ the server's behavior.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>heartbeat-interval</command></term>
+ <listitem>
+ <para>
+ The server will perform zone maintenance tasks
+ for all zones marked as <command>dialup</command> whenever this
+ interval expires. The default is 60 minutes. Reasonable
+ values are up
+ to 1 day (1440 minutes). The maximum value is 28 days
+ (40320 minutes).
+ If set to 0, no zone maintenance for these zones will occur.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>interface-interval</command></term>
+ <listitem>
+ <para>
+ The server will scan the network interface list
+ every <command>interface-interval</command>
+ minutes. The default
+ is 60 minutes. The maximum value is 28 days (40320 minutes).
+ If set to 0, interface scanning will only occur when
+ the configuration file is loaded. After the scan, the
+ server will
+ begin listening for queries on any newly discovered
+ interfaces (provided they are allowed by the
+ <command>listen-on</command> configuration), and
+ will
+ stop listening on interfaces that have gone away.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>statistics-interval</command></term>
+ <listitem>
+ <para>
+ Name server statistics will be logged
+ every <command>statistics-interval</command>
+ minutes. The default is
+ 60. The maximum value is 28 days (40320 minutes).
+ If set to 0, no statistics will be logged.
+ </para><note>
+ <simpara>
+ Not yet implemented in
+ <acronym>BIND</acronym> 9.
+ </simpara>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </sect3>
+
+ <sect3 id="topology">
+ <title>Topology</title>
+
+ <para>
+ All other things being equal, when the server chooses a name
+ server
+ to query from a list of name servers, it prefers the one that is
+ topologically closest to itself. The <command>topology</command> statement
+ takes an <command>address_match_list</command> and
+ interprets it
+ in a special way. Each top-level list element is assigned a
+ distance.
+ Non-negated elements get a distance based on their position in the
+ list, where the closer the match is to the start of the list, the
+ shorter the distance is between it and the server. A negated match
+ will be assigned the maximum distance from the server. If there
+ is no match, the address will get a distance which is further than
+ any non-negated list element, and closer than any negated element.
+ For example,
+ </para>
+
+<programlisting>topology {
+ 10/8;
+ !1.2.3/24;
+ { 1.2/16; 3/8; };
+};</programlisting>
+
+ <para>
+ will prefer servers on network 10 the most, followed by hosts
+ on network 1.2.0.0 (netmask 255.255.0.0) and network 3, with the
+ exception of hosts on network 1.2.3 (netmask 255.255.255.0), which
+ is preferred least of all.
+ </para>
+ <para>
+ The default topology is
+ </para>
+
+<programlisting> topology { localhost; localnets; };
+</programlisting>
+
+ <note>
+ <simpara>
+ The <command>topology</command> option
+ is not implemented in <acronym>BIND</acronym> 9.
+ </simpara>
+ </note>
+ </sect3>
+
+ <sect3 id="the_sortlist_statement">
+
+ <title>The <command>sortlist</command> Statement</title>
+
+ <para>
+ The response to a DNS query may consist of multiple resource
+ records (RRs) forming a resource records set (RRset).
+ The name server will normally return the
+ RRs within the RRset in an indeterminate order
+ (but see the <command>rrset-order</command>
+ statement in <xref linkend="rrset_ordering"/>).
+ The client resolver code should rearrange the RRs as appropriate,
+ that is, using any addresses on the local net in preference to
+ other addresses.
+ However, not all resolvers can do this or are correctly
+ configured.
+ When a client is using a local server, the sorting can be performed
+ in the server, based on the client's address. This only requires
+ configuring the name servers, not all the clients.
+ </para>
+
+ <para>
+ The <command>sortlist</command> statement (see below)
+ takes
+ an <command>address_match_list</command> and
+ interprets it even
+ more specifically than the <command>topology</command>
+ statement
+ does (<xref linkend="topology"/>).
+ Each top level statement in the <command>sortlist</command> must
+ itself be an explicit <command>address_match_list</command> with
+ one or two elements. The first element (which may be an IP
+ address,
+ an IP prefix, an ACL name or a nested <command>address_match_list</command>)
+ of each top level list is checked against the source address of
+ the query until a match is found.
+ </para>
+ <para>
+ Once the source address of the query has been matched, if
+ the top level statement contains only one element, the actual
+ primitive
+ element that matched the source address is used to select the
+ address
+ in the response to move to the beginning of the response. If the
+ statement is a list of two elements, then the second element is
+ treated the same as the <command>address_match_list</command> in
+ a <command>topology</command> statement. Each top
+ level element
+ is assigned a distance and the address in the response with the
+ minimum
+ distance is moved to the beginning of the response.
+ </para>
+ <para>
+ In the following example, any queries received from any of
+ the addresses of the host itself will get responses preferring
+ addresses
+ on any of the locally connected networks. Next most preferred are
+ addresses
+ on the 192.168.1/24 network, and after that either the
+ 192.168.2/24
+ or
+ 192.168.3/24 network with no preference shown between these two
+ networks. Queries received from a host on the 192.168.1/24 network
+ will prefer other addresses on that network to the 192.168.2/24
+ and
+ 192.168.3/24 networks. Queries received from a host on the
+ 192.168.4/24
+ or the 192.168.5/24 network will only prefer other addresses on
+ their directly connected networks.
+ </para>
+
+<programlisting>sortlist {
+ { localhost; // IF the local host
+ { localnets; // THEN first fit on the
+ 192.168.1/24; // following nets
+ { 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
+ { 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
+ { 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
+ { 192.168.1/24; 192.168.2/24; }; }; };
+ { { 192.168.4/24; 192.168.5/24; }; // if .4 or .5, prefer that net
+ };
+};</programlisting>
+
+ <para>
+ The following example will give reasonable behavior for the
+ local host and hosts on directly connected networks. It is similar
+ to the behavior of the address sort in <acronym>BIND</acronym> 4.9.x. Responses sent
+ to queries from the local host will favor any of the directly
+ connected
+ networks. Responses sent to queries from any other hosts on a
+ directly
+ connected network will prefer addresses on that same network.
+ Responses
+ to other queries will not be sorted.
+ </para>
+
+<programlisting>sortlist {
+ { localhost; localnets; };
+ { localnets; };
+};
+</programlisting>
+
+ </sect3>
+ <sect3 id="rrset_ordering">
+ <title id="rrset_ordering_title">RRset Ordering</title>
+ <para>
+ When multiple records are returned in an answer it may be
+ useful to configure the order of the records placed into the
+ response.
+ The <command>rrset-order</command> statement permits
+ configuration
+ of the ordering of the records in a multiple record response.
+ See also the <command>sortlist</command> statement,
+ <xref linkend="the_sortlist_statement"/>.
+ </para>
+
+ <para>
+ An <command>order_spec</command> is defined as
+ follows:
+ </para>
+ <para>
+ <optional>class <replaceable>class_name</replaceable></optional>
+ <optional>type <replaceable>type_name</replaceable></optional>
+ <optional>name <replaceable>"domain_name"</replaceable></optional>
+ order <replaceable>ordering</replaceable>
+ </para>
+ <para>
+ If no class is specified, the default is <command>ANY</command>.
+ If no type is specified, the default is <command>ANY</command>.
+ If no name is specified, the default is "<command>*</command>" (asterisk).
+ </para>
+ <para>
+ The legal values for <command>ordering</command> are:
+ </para>
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="0.750in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="3.750in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>fixed</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Records are returned in the order they
+ are defined in the zone file.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>random</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Records are returned in some random order.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>cyclic</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Records are returned in a cyclic round-robin order.
+ </para>
+ <para>
+ If <acronym>BIND</acronym> is configured with the
+ "--enable-fixed-rrset" option at compile time, then
+ the initial ordering of the RRset will match the
+ one specified in the zone file.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ For example:
+ </para>
+
+<programlisting>rrset-order {
+ class IN type A name "host.example.com" order random;
+ order cyclic;
+};
+</programlisting>
+
+ <para>
+ will cause any responses for type A records in class IN that
+ have "<literal>host.example.com</literal>" as a
+ suffix, to always be returned
+ in random order. All other records are returned in cyclic order.
+ </para>
+ <para>
+ If multiple <command>rrset-order</command> statements
+ appear,
+ they are not combined &mdash; the last one applies.
+ </para>
+
+ <note>
+ <simpara>
+ In this release of <acronym>BIND</acronym> 9, the
+ <command>rrset-order</command> statement does not support
+ "fixed" ordering by default. Fixed ordering can be enabled
+ at compile time by specifying "--enable-fixed-rrset" on
+ the "configure" command line.
+ </simpara>
+ </note>
+ </sect3>
+
+ <sect3 id="tuning">
+ <title>Tuning</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>lame-ttl</command></term>
+ <listitem>
+ <para>
+ Sets the number of seconds to cache a
+ lame server indication. 0 disables caching. (This is
+ <emphasis role="bold">NOT</emphasis> recommended.)
+ The default is <literal>600</literal> (10 minutes) and the
+ maximum value is
+ <literal>1800</literal> (30 minutes).
+ </para>
+
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-ncache-ttl</command></term>
+ <listitem>
+ <para>
+ To reduce network traffic and increase performance,
+ the server stores negative answers. <command>max-ncache-ttl</command> is
+ used to set a maximum retention time for these answers in
+ the server
+ in seconds. The default
+ <command>max-ncache-ttl</command> is <literal>10800</literal> seconds (3 hours).
+ <command>max-ncache-ttl</command> cannot exceed
+ 7 days and will
+ be silently truncated to 7 days if set to a greater value.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-cache-ttl</command></term>
+ <listitem>
+ <para>
+ Sets the maximum time for which the server will
+ cache ordinary (positive) answers. The default is
+ one week (7 days).
+ A value of zero may cause all queries to return
+ SERVFAIL, because of lost caches of intermediate
+ RRsets (such as NS and glue AAAA/A records) in the
+ resolution process.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>min-roots</command></term>
+ <listitem>
+ <para>
+ The minimum number of root servers that
+ is required for a request for the root servers to be
+ accepted. The default
+ is <userinput>2</userinput>.
+ </para>
+ <note>
+ <simpara>
+ Not implemented in <acronym>BIND</acronym> 9.
+ </simpara>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>sig-validity-interval</command></term>
+ <listitem>
+ <para>
+ Specifies the number of days into the future when
+ DNSSEC signatures automatically generated as a
+ result of dynamic updates (<xref
+ linkend="dynamic_update"/>) will expire. There
+ is a 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
+ field is specified in days if the base interval is
+ greater than 7 days otherwise it is specified in hours.
+ The default base interval is <literal>30</literal> days
+ giving a re-signing interval of 7 1/2 days. The maximum
+ values are 10 years (3660 days).
+ </para>
+ <para>
+ The signature inception time is unconditionally
+ set to one hour before the current time to allow
+ for a limited amount of clock skew.
+ </para>
+ <para>
+ The <command>sig-validity-interval</command>
+ should be, at least, several multiples of the SOA
+ expire interval to allow for reasonable interaction
+ between the various timer and expiry dates.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>sig-signing-nodes</command></term>
+ <listitem>
+ <para>
+ Specify the maximum number of nodes to be
+ examined in each quantum when signing a zone with
+ a new DNSKEY. The default is
+ <literal>100</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>sig-signing-signatures</command></term>
+ <listitem>
+ <para>
+ Specify a threshold number of signatures that
+ will terminate processing a quantum when signing
+ a zone with a new DNSKEY. The default is
+ <literal>10</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>sig-signing-type</command></term>
+ <listitem>
+ <para>
+ Specify a private RDATA type to be used when generating
+ key signing records. The default is
+ <literal>65535</literal>.
+ </para>
+ <para>
+ It is expected that this parameter may be removed
+ in a future version once there is a standard type.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>min-refresh-time</command></term>
+ <term><command>max-refresh-time</command></term>
+ <term><command>min-retry-time</command></term>
+ <term><command>max-retry-time</command></term>
+ <listitem>
+ <para>
+ These options control the server's behavior on refreshing a
+ zone
+ (querying for SOA changes) or retrying failed transfers.
+ Usually the SOA values for the zone are used, but these
+ values
+ are set by the master, giving slave server administrators
+ little
+ control over their contents.
+ </para>
+ <para>
+ These options allow the administrator to set a minimum and
+ maximum
+ refresh and retry time either per-zone, per-view, or
+ globally.
+ These options are valid for slave and stub zones,
+ and clamp the SOA refresh and retry times to the specified
+ values.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>edns-udp-size</command></term>
+ <listitem>
+ <para>
+ Sets the advertised EDNS UDP buffer size 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 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-udp-size</command></term>
+ <listitem>
+ <para>
+ 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.
+ This is independent of the advertised receive
+ buffer (<command>edns-udp-size</command>).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>masterfile-format</command></term>
+ <listitem>
+ <para>Specifies
+ the file format of zone files (see
+ <xref linkend="zonefile_format"/>).
+ The default value is <constant>text</constant>, which is the
+ standard textual representation. Files in other formats
+ than <constant>text</constant> are typically expected
+ to be generated by the <command>named-compilezone</command> tool.
+ Note that when a zone file in a different format than
+ <constant>text</constant> is loaded, <command>named</command>
+ may omit some of the checks which would be performed for a
+ file in the <constant>text</constant> format. In particular,
+ <command>check-names</command> checks do not apply
+ for the <constant>raw</constant> format. This means
+ a zone file in the <constant>raw</constant> format
+ must be generated with the same check level as that
+ specified in the <command>named</command> configuration
+ file. This statement sets the
+ <command>masterfile-format</command> for all zones,
+ but can be overridden on a per-zone or per-view basis
+ by including a <command>masterfile-format</command>
+ statement within the <command>zone</command> or
+ <command>view</command> block in the configuration
+ file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>clients-per-query</command></term>
+ <term><command>max-clients-per-query</command></term>
+ <listitem>
+ <para>These set the
+ initial value (minimum) and maximum number of recursive
+ simultaneous clients for any given query
+ (&lt;qname,qtype,qclass&gt;) that the server will accept
+ before dropping additional clients. named will attempt to
+ self tune this value and changes will be logged. The
+ default values are 10 and 100.
+ </para>
+ <para>
+ This value should reflect how many queries come in for
+ a given name in the time it takes to resolve that name.
+ If the number of queries exceed this value, named will
+ assume that it is dealing with a non-responsive zone
+ and will drop additional queries. If it gets a response
+ after dropping queries, it will raise the estimate. The
+ estimate will then be lowered in 20 minutes if it has
+ remained unchanged.
+ </para>
+ <para>
+ If <command>clients-per-query</command> is set to zero,
+ then there is no limit on the number of clients per query
+ and no queries will be dropped.
+ </para>
+ <para>
+ If <command>max-clients-per-query</command> is set to zero,
+ then there is no upper bound other than imposed by
+ <command>recursive-clients</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>notify-delay</command></term>
+ <listitem>
+ <para>
+ The delay, in seconds, between sending sets of notify
+ messages for a zone. The default is zero.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </sect3>
+
+ <sect3 id="builtin">
+ <title>Built-in server information zones</title>
+
+ <para>
+ The server provides some helpful diagnostic information
+ through a number of built-in zones under the
+ pseudo-top-level-domain <literal>bind</literal> in the
+ <command>CHAOS</command> class. These zones are part
+ of a
+ built-in view (see <xref linkend="view_statement_grammar"/>) of
+ class
+ <command>CHAOS</command> which is separate from the
+ default view of
+ class <command>IN</command>; therefore, any global
+ server options
+ such as <command>allow-query</command> do not apply
+ the these zones.
+ If you feel the need to disable these zones, use the options
+ below, or hide the built-in <command>CHAOS</command>
+ view by
+ defining an explicit view of class <command>CHAOS</command>
+ that matches all clients.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>version</command></term>
+ <listitem>
+ <para>
+ The version the server should report
+ via a query of the name <literal>version.bind</literal>
+ with type <command>TXT</command>, class <command>CHAOS</command>.
+ The default is the real version number of this server.
+ Specifying <command>version none</command>
+ disables processing of the queries.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>hostname</command></term>
+ <listitem>
+ <para>
+ The hostname the server should report via a query of
+ the name <filename>hostname.bind</filename>
+ with type <command>TXT</command>, class <command>CHAOS</command>.
+ This defaults to the hostname of the machine hosting the
+ name server as
+ found by the gethostname() function. The primary purpose of such queries
+ is to
+ identify which of a group of anycast servers is actually
+ answering your queries. Specifying <command>hostname none;</command>
+ disables processing of the queries.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>server-id</command></term>
+ <listitem>
+ <para>
+ The ID the server should report when receiving a Name
+ Server Identifier (NSID) query, or a query of the name
+ <filename>ID.SERVER</filename> with type
+ <command>TXT</command>, class <command>CHAOS</command>.
+ The primary purpose of such queries is to
+ identify which of a group of anycast servers is actually
+ answering your queries. Specifying <command>server-id none;</command>
+ disables processing of the queries.
+ Specifying <command>server-id hostname;</command> will cause named to
+ use the hostname as found by the gethostname() function.
+ The default <command>server-id</command> is <command>none</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </sect3>
+
+ <sect3 id="empty">
+ <title>Built-in Empty Zones</title>
+ <para>
+ Named has some built-in empty zones (SOA and NS records only).
+ These are for zones that should normally be answered locally
+ and which queries should not be sent to the Internet's root
+ servers. The official servers which cover these namespaces
+ return NXDOMAIN responses to these queries. In particular,
+ these cover the reverse namespace for addresses from RFC 1918 and
+ RFC 3330. They also include the reverse namespace for IPv6 local
+ address (locally assigned), IPv6 link local addresses, the IPv6
+ loopback address and the IPv6 unknown address.
+ </para>
+ <para>
+ 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.
+ </para>
+ <para>
+ The current list of empty zones is:
+ <itemizedlist>
+<!-- XXX: The RFC1918 addresses are #defined out in sources currently.
+ <listitem>10.IN-ADDR.ARPA</listitem>
+ <listitem>16.172.IN-ADDR.ARPA</listitem>
+ <listitem>17.172.IN-ADDR.ARPA</listitem>
+ <listitem>18.172.IN-ADDR.ARPA</listitem>
+ <listitem>19.172.IN-ADDR.ARPA</listitem>
+ <listitem>20.172.IN-ADDR.ARPA</listitem>
+ <listitem>21.172.IN-ADDR.ARPA</listitem>
+ <listitem>22.172.IN-ADDR.ARPA</listitem>
+ <listitem>23.172.IN-ADDR.ARPA</listitem>
+ <listitem>24.172.IN-ADDR.ARPA</listitem>
+ <listitem>25.172.IN-ADDR.ARPA</listitem>
+ <listitem>26.172.IN-ADDR.ARPA</listitem>
+ <listitem>27.172.IN-ADDR.ARPA</listitem>
+ <listitem>28.172.IN-ADDR.ARPA</listitem>
+ <listitem>29.172.IN-ADDR.ARPA</listitem>
+ <listitem>30.172.IN-ADDR.ARPA</listitem>
+ <listitem>31.172.IN-ADDR.ARPA</listitem>
+ <listitem>168.192.IN-ADDR.ARPA</listitem>
+XXX: end of RFC1918 addresses #defined out -->
+ <listitem>0.IN-ADDR.ARPA</listitem>
+ <listitem>127.IN-ADDR.ARPA</listitem>
+ <listitem>254.169.IN-ADDR.ARPA</listitem>
+ <listitem>2.0.192.IN-ADDR.ARPA</listitem>
+ <listitem>255.255.255.255.IN-ADDR.ARPA</listitem>
+ <listitem>0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA</listitem>
+ <listitem>1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA</listitem>
+ <listitem>D.F.IP6.ARPA</listitem>
+ <listitem>8.E.F.IP6.ARPA</listitem>
+ <listitem>9.E.F.IP6.ARPA</listitem>
+ <listitem>A.E.F.IP6.ARPA</listitem>
+ <listitem>B.E.F.IP6.ARPA</listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Empty zones are settable at the view level and only apply to
+ views of class IN. Disabled empty zones are only inherited
+ from options if there are no disabled empty zones specified
+ at the view level. To override the options list of disabled
+ zones, you can disable the root zone at the view level, for example:
+<programlisting>
+ disable-empty-zone ".";
+</programlisting>
+ </para>
+ <para>
+ If you are using the address ranges covered here, you should
+ already have reverse zones covering the addresses you use.
+ In practice this appears to not be the case with many queries
+ being made to the infrastructure servers for names in these
+ spaces. So many in fact that sacrificial servers were needed
+ to be deployed to channel the query load away from the
+ infrastructure servers.
+ </para>
+ <note>
+ The real parent servers for these zones should disable all
+ empty zone under the parent zone they serve. For the real
+ root servers, this is all built in empty zones. This will
+ enable them to return referrals to deeper in the tree.
+ </note>
+ <variablelist>
+ <varlistentry>
+ <term><command>empty-server</command></term>
+ <listitem>
+ <para>
+ Specify what server name will appear in the returned
+ SOA record for empty zones. If none is specified, then
+ the zone's name will be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>empty-contact</command></term>
+ <listitem>
+ <para>
+ Specify what contact name will appear in the returned
+ SOA record for empty zones. If none is specified, then
+ "." will be used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>empty-zones-enable</command></term>
+ <listitem>
+ <para>
+ Enable or disable all empty zones. By default they
+ are enabled.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>disable-empty-zone</command></term>
+ <listitem>
+ <para>
+ Disable individual empty zones. By default none are
+ disabled. This option can be specified multiple times.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect3>
+
+ <sect3 id="acache">
+ <title>Additional Section Caching</title>
+
+ <para>
+ The additional section cache, also called <command>acache</command>,
+ is an internal cache to improve the response performance of BIND 9.
+ When additional section caching is enabled, BIND 9 will
+ cache an internal short-cut to the additional section content for
+ each answer RR.
+ Note that <command>acache</command> is an internal caching
+ mechanism of BIND 9, and is not related to the DNS caching
+ server function.
+ </para>
+
+ <para>
+ Additional section caching does not change the
+ response content (except the RRsets ordering of the additional
+ section, see below), but can improve the response performance
+ significantly.
+ It is particularly effective when BIND 9 acts as an authoritative
+ server for a zone that has many delegations with many glue RRs.
+ </para>
+
+ <para>
+ In order to obtain the maximum performance improvement
+ from additional section caching, setting
+ <command>additional-from-cache</command>
+ to <command>no</command> is recommended, since the current
+ implementation of <command>acache</command>
+ does not short-cut of additional section information from the
+ DNS cache data.
+ </para>
+
+ <para>
+ One obvious disadvantage of <command>acache</command> is
+ that it requires much more
+ memory for the internal cached data.
+ Thus, if the response performance does not matter and memory
+ consumption is much more critical, the
+ <command>acache</command> mechanism can be
+ disabled by setting <command>acache-enable</command> to
+ <command>no</command>.
+ It is also possible to specify the upper limit of memory
+ consumption
+ for acache by using <command>max-acache-size</command>.
+ </para>
+
+ <para>
+ Additional section caching also has a minor effect on the
+ RRset ordering in the additional section.
+ Without <command>acache</command>,
+ <command>cyclic</command> order is effective for the additional
+ section as well as the answer and authority sections.
+ However, additional section caching fixes the ordering when it
+ first caches an RRset for the additional section, and the same
+ ordering will be kept in succeeding responses, regardless of the
+ setting of <command>rrset-order</command>.
+ The effect of this should be minor, however, since an
+ RRset in the additional section
+ typically only contains a small number of RRs (and in many cases
+ it only contains a single RR), in which case the
+ ordering does not matter much.
+ </para>
+
+ <para>
+ The following is a summary of options related to
+ <command>acache</command>.
+ </para>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>acache-enable</command></term>
+ <listitem>
+ <para>
+ If <command>yes</command>, additional section caching is
+ enabled. The default value is <command>no</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>acache-cleaning-interval</command></term>
+ <listitem>
+ <para>
+ The server will remove stale cache entries, based on an LRU
+ based
+ algorithm, every <command>acache-cleaning-interval</command> minutes.
+ The default is 60 minutes.
+ If set to 0, no periodic cleaning will occur.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-acache-size</command></term>
+ <listitem>
+ <para>
+ The maximum amount of memory in bytes to use for the server's acache.
+ When the amount of data in the acache reaches this limit,
+ the server
+ will clean more aggressively so that the limit is not
+ exceeded.
+ In a server with multiple views, the limit applies
+ separately to the
+ acache of each view.
+ The default is <literal>16M</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </sect3>
+
+ </sect2>
+
+ <sect2 id="statschannels">
+ <title><command>statistics-channels</command> Statement Grammar</title>
+
+<programlisting><command>statistics-channels</command> {
+ [ inet ( ip_addr | * ) [ port ip_port ] [allow { <replaceable> address_match_list </replaceable> } ]; ]
+ [ inet ...; ]
+};
+</programlisting>
+ </sect2>
+
+ <sect2>
+ <title><command>statistics-channels</command> Statement Definition and
+ Usage</title>
+
+ <para>
+ The <command>statistics-channels</command> statement
+ declares communication channels to be used by system
+ administrators to get access to statistics information of
+ the name server.
+ </para>
+
+ <para>
+ This statement intends to be flexible to support multiple
+ communication protocols in the future, but currently only
+ HTTP access is supported.
+ It requires that BIND 9 be compiled with libxml2;
+ the <command>statistics-channels</command> statement is
+ still accepted even if it is built without the library,
+ but any HTTP access will fail with an error.
+ </para>
+
+ <para>
+ An <command>inet</command> control channel is a TCP socket
+ listening at the specified <command>ip_port</command> on the
+ specified <command>ip_addr</command>, which can be an IPv4 or IPv6
+ address. An <command>ip_addr</command> of <literal>*</literal> (asterisk) is
+ interpreted as the IPv4 wildcard address; connections will be
+ accepted on any of the system's IPv4 addresses.
+ To listen on the IPv6 wildcard address,
+ use an <command>ip_addr</command> of <literal>::</literal>.
+ </para>
+
+ <para>
+ If no port is specified, port 80 is used for HTTP channels.
+ The asterisk "<literal>*</literal>" cannot be used for
+ <command>ip_port</command>.
+ </para>
+
+ <para>
+ The attempt of opening a statistics channel is
+ restricted by the optional <command>allow</command> clause.
+ Connections to the statistics channel are permitted based on the
+ <command>address_match_list</command>.
+ If no <command>allow</command> clause is present,
+ <command>named</command> accepts connection
+ attempts from any address; since the statistics may
+ contain sensitive internal information, it is highly
+ recommended to restrict the source of connection requests
+ appropriately.
+ </para>
+
+ <para>
+ If no <command>statistics-channels</command> statement is present,
+ <command>named</command> will not open any communication channels.
+ </para>
+
+ </sect2>
+
+ <sect2 id="server_statement_grammar">
+ <title><command>server</command> Statement Grammar</title>
+
+<programlisting><command>server</command> <replaceable>ip_addr[/prefixlen]</replaceable> {
+ <optional> bogus <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> provide-ixfr <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> request-ixfr <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> edns <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> edns-udp-size <replaceable>number</replaceable> ; </optional>
+ <optional> max-udp-size <replaceable>number</replaceable> ; </optional>
+ <optional> transfers <replaceable>number</replaceable> ; </optional>
+ <optional> transfer-format <replaceable>( one-answer | many-answers )</replaceable> ; ]</optional>
+ <optional> keys <replaceable>{ string ; <optional> string ; <optional>...</optional></optional> }</replaceable> ; </optional>
+ <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> query-source <optional> address ( <replaceable>ip_addr</replaceable> | <replaceable>*</replaceable> ) </optional> <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>; </optional>
+ <optional> query-source-v6 <optional> address ( <replaceable>ip_addr</replaceable> | <replaceable>*</replaceable> ) </optional> <optional> port ( <replaceable>ip_port</replaceable> | <replaceable>*</replaceable> ) </optional>; </optional>
+ <optional> use-queryport-pool <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> queryport-pool-ports <replaceable>number</replaceable>; </optional>
+ <optional> queryport-pool-interval <replaceable>number</replaceable>; </optional>
+};
+</programlisting>
+
+ </sect2>
+
+ <sect2 id="server_statement_definition_and_usage">
+ <title><command>server</command> Statement Definition and
+ Usage</title>
+
+ <para>
+ The <command>server</command> statement defines
+ characteristics
+ to be associated with a remote name server. If a prefix length is
+ specified, then a range of servers is covered. Only the most
+ specific
+ server clause applies regardless of the order in
+ <filename>named.conf</filename>.
+ </para>
+
+ <para>
+ The <command>server</command> statement can occur at
+ the top level of the
+ configuration file or inside a <command>view</command>
+ statement.
+ If a <command>view</command> statement contains
+ one or more <command>server</command> statements, only
+ those
+ apply to the view and any top-level ones are ignored.
+ If a view contains no <command>server</command>
+ statements,
+ any top-level <command>server</command> statements are
+ used as
+ defaults.
+ </para>
+
+ <para>
+ If you discover that a remote server is giving out bad data,
+ marking it as bogus will prevent further queries to it. The
+ default
+ value of <command>bogus</command> is <command>no</command>.
+ </para>
+ <para>
+ The <command>provide-ixfr</command> clause determines
+ whether
+ the local server, acting as master, will respond with an
+ incremental
+ zone transfer when the given remote server, a slave, requests it.
+ If set to <command>yes</command>, incremental transfer
+ will be provided
+ whenever possible. If set to <command>no</command>,
+ all transfers
+ to the remote server will be non-incremental. If not set, the
+ value
+ of the <command>provide-ixfr</command> option in the
+ view or
+ global options block is used as a default.
+ </para>
+
+ <para>
+ The <command>request-ixfr</command> clause determines
+ whether
+ the local server, acting as a slave, will request incremental zone
+ transfers from the given remote server, a master. If not set, the
+ value of the <command>request-ixfr</command> option in
+ the view or
+ global options block is used as a default.
+ </para>
+
+ <para>
+ IXFR requests to servers that do not support IXFR will
+ automatically
+ fall back to AXFR. Therefore, there is no need to manually list
+ which servers support IXFR and which ones do not; the global
+ default
+ of <command>yes</command> should always work.
+ The purpose of the <command>provide-ixfr</command> and
+ <command>request-ixfr</command> clauses is
+ to make it possible to disable the use of IXFR even when both
+ master
+ and slave claim to support it, for example if one of the servers
+ is buggy and crashes or corrupts data when IXFR is used.
+ </para>
+
+ <para>
+ The <command>edns</command> clause determines whether
+ the local server will attempt to use EDNS when communicating
+ with the remote server. The default is <command>yes</command>.
+ </para>
+
+ <para>
+ The <command>edns-udp-size</command> option sets the EDNS UDP size
+ that is advertised by named when querying the remote server.
+ Valid values are 512 to 4096 bytes (values outside this range will be
+ silently adjusted). This option is useful when you wish to
+ advertises a different value to this server than the value you
+ advertise globally, for example, when there is a firewall at the
+ remote site that is blocking large replies.
+ </para>
+
+ <para>
+ The <command>max-udp-size</command> option sets the
+ maximum EDNS UDP message size named will send. Valid
+ values are 512 to 4096 bytes (values outside this range will
+ be silently adjusted). This option is useful when you
+ know that there is a firewall that is blocking large
+ replies from named.
+ </para>
+
+ <para>
+ The server supports two zone transfer methods. The first, <command>one-answer</command>,
+ uses one DNS message per resource record transferred. <command>many-answers</command> packs
+ as many resource records as possible into a message. <command>many-answers</command> is
+ more efficient, but is only known to be understood by <acronym>BIND</acronym> 9, <acronym>BIND</acronym>
+ 8.x, and patched versions of <acronym>BIND</acronym>
+ 4.9.5. You can specify which method
+ to use for a server with the <command>transfer-format</command> option.
+ If <command>transfer-format</command> is not
+ specified, the <command>transfer-format</command>
+ specified
+ by the <command>options</command> statement will be
+ used.
+ </para>
+
+ <para><command>transfers</command>
+ is used to limit the number of concurrent inbound zone
+ transfers from the specified server. If no
+ <command>transfers</command> clause is specified, the
+ limit is set according to the
+ <command>transfers-per-ns</command> option.
+ </para>
+
+ <para>
+ The <command>keys</command> clause identifies a
+ <command>key_id</command> defined by the <command>key</command> statement,
+ to be used for transaction security (TSIG, <xref linkend="tsig"/>)
+ when talking to the remote server.
+ When a request is sent to the remote server, a request signature
+ will be generated using the key specified here and appended to the
+ message. A request originating from the remote server is not
+ required
+ to be signed by this key.
+ </para>
+
+ <para>
+ Although the grammar of the <command>keys</command>
+ clause
+ allows for multiple keys, only a single key per server is
+ currently
+ supported.
+ </para>
+
+ <para>
+ The <command>transfer-source</command> and
+ <command>transfer-source-v6</command> clauses specify
+ the IPv4 and IPv6 source
+ address to be used for zone transfer with the remote server,
+ respectively.
+ For an IPv4 remote server, only <command>transfer-source</command> can
+ be specified.
+ Similarly, for an IPv6 remote server, only
+ <command>transfer-source-v6</command> can be
+ specified.
+ For more details, see the description of
+ <command>transfer-source</command> and
+ <command>transfer-source-v6</command> in
+ <xref linkend="zone_transfers"/>.
+ </para>
+
+ <para>
+ The <command>notify-source</command> and
+ <command>notify-source-v6</command> clauses specify the
+ IPv4 and IPv6 source address to be used for notify
+ messages sent to remote servers, respectively. For an
+ IPv4 remote server, only <command>notify-source</command>
+ can be specified. Similarly, for an IPv6 remote server,
+ only <command>notify-source-v6</command> can be specified.
+ </para>
+
+ <para>
+ The <command>query-source</command> and
+ <command>query-source-v6</command> clauses specify the
+ IPv4 and IPv6 source address to be used for queries
+ sent to remote servers, respectively. For an IPv4
+ remote server, only <command>query-source</command> can
+ be specified. Similarly, for an IPv6 remote server,
+ only <command>query-source-v6</command> can be specified.
+ </para>
+
+ </sect2>
+
+ <sect2>
+ <title><command>trusted-keys</command> Statement Grammar</title>
+
+<programlisting><command>trusted-keys</command> {
+ <replaceable>string</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>string</replaceable> ;
+ <optional> <replaceable>string</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>string</replaceable> ; <optional>...</optional></optional>
+};
+</programlisting>
+
+ </sect2>
+ <sect2>
+ <title><command>trusted-keys</command> Statement Definition
+ and Usage</title>
+ <para>
+ The <command>trusted-keys</command> statement defines
+ DNSSEC security roots. DNSSEC is described in <xref
+ linkend="DNSSEC"/>. A security root is defined when the
+ public key for a non-authoritative zone is known, but
+ cannot be securely obtained through DNS, either because
+ it is the DNS root zone or because its parent zone is
+ unsigned. Once a key has been configured as a trusted
+ key, it is treated as if it had been validated and
+ proven secure. The resolver attempts DNSSEC validation
+ on all DNS data in subdomains of a security root.
+ </para>
+ <para>
+ All keys (and corresponding zones) listed in
+ <command>trusted-keys</command> are deemed to exist regardless
+ of what parent zones say. Similarly for all keys listed in
+ <command>trusted-keys</command> only those keys are
+ used to validate the DNSKEY RRset. The parent's DS RRset
+ will not be used.
+ </para>
+ <para>
+ The <command>trusted-keys</command> statement can contain
+ multiple key entries, each consisting of the key's
+ domain name, flags, protocol, algorithm, and the Base-64
+ representation of the key data.
+ Spaces, tabs, newlines and carriage returns are ignored
+ in the key data, so the configuration may be split up into
+ multiple lines.
+ </para>
+ </sect2>
+
+ <sect2 id="view_statement_grammar">
+ <title><command>view</command> Statement Grammar</title>
+
+<programlisting><command>view</command> <replaceable>view_name</replaceable>
+ <optional><replaceable>class</replaceable></optional> {
+ match-clients { <replaceable>address_match_list</replaceable> };
+ match-destinations { <replaceable>address_match_list</replaceable> };
+ match-recursive-only <replaceable>yes_or_no</replaceable> ;
+ <optional> <replaceable>view_option</replaceable>; ...</optional>
+ <optional> <replaceable>zone_statement</replaceable>; ...</optional>
+};
+</programlisting>
+
+ </sect2>
+ <sect2>
+ <title><command>view</command> Statement Definition and Usage</title>
+
+ <para>
+ The <command>view</command> statement is a powerful
+ feature
+ of <acronym>BIND</acronym> 9 that lets a name server
+ answer a DNS query differently
+ depending on who is asking. It is particularly useful for
+ implementing
+ split DNS setups without having to run multiple servers.
+ </para>
+
+ <para>
+ Each <command>view</command> statement defines a view
+ of the
+ DNS namespace that will be seen by a subset of clients. A client
+ matches
+ a view if its source IP address matches the
+ <varname>address_match_list</varname> of the view's
+ <command>match-clients</command> clause and its
+ destination IP address matches
+ the <varname>address_match_list</varname> of the
+ view's
+ <command>match-destinations</command> clause. If not
+ specified, both
+ <command>match-clients</command> and <command>match-destinations</command>
+ default to matching all addresses. In addition to checking IP
+ addresses
+ <command>match-clients</command> and <command>match-destinations</command>
+ can also take <command>keys</command> which provide an
+ mechanism for the
+ client to select the view. A view can also be specified
+ as <command>match-recursive-only</command>, which
+ means that only recursive
+ requests from matching clients will match that view.
+ The order of the <command>view</command> statements is
+ significant &mdash;
+ a client request will be resolved in the context of the first
+ <command>view</command> that it matches.
+ </para>
+
+ <para>
+ Zones defined within a <command>view</command>
+ statement will
+ only be accessible to clients that match the <command>view</command>.
+ By defining a zone of the same name in multiple views, different
+ zone data can be given to different clients, for example,
+ "internal"
+ and "external" clients in a split DNS setup.
+ </para>
+
+ <para>
+ Many of the options given in the <command>options</command> statement
+ can also be used within a <command>view</command>
+ statement, and then
+ apply only when resolving queries with that view. When no
+ view-specific
+ value is given, the value in the <command>options</command> statement
+ is used as a default. Also, zone options can have default values
+ specified
+ in the <command>view</command> statement; these
+ view-specific defaults
+ take precedence over those in the <command>options</command> statement.
+ </para>
+
+ <para>
+ Views are class specific. If no class is given, class IN
+ is assumed. Note that all non-IN views must contain a hint zone,
+ since only the IN class has compiled-in default hints.
+ </para>
+
+ <para>
+ If there are no <command>view</command> statements in
+ the config
+ file, a default view that matches any client is automatically
+ created
+ in class IN. Any <command>zone</command> statements
+ specified on
+ the top level of the configuration file are considered to be part
+ of
+ this default view, and the <command>options</command>
+ statement will
+ apply to the default view. If any explicit <command>view</command>
+ statements are present, all <command>zone</command>
+ statements must
+ occur inside <command>view</command> statements.
+ </para>
+
+ <para>
+ Here is an example of a typical split DNS setup implemented
+ using <command>view</command> statements:
+ </para>
+
+<programlisting>view "internal" {
+ // This should match our internal networks.
+ match-clients { 10.0.0.0/8; };
+
+ // Provide recursive service to internal clients only.
+ recursion yes;
+
+ // Provide a complete view of the example.com zone
+ // including addresses of internal hosts.
+ zone "example.com" {
+ type master;
+ file "example-internal.db";
+ };
+};
+
+view "external" {
+ // 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.
+ zone "example.com" {
+ type master;
+ file "example-external.db";
+ };
+};
+</programlisting>
+
+ </sect2>
+ <sect2 id="zone_statement_grammar">
+ <title><command>zone</command>
+ Statement Grammar</title>
+
+<programlisting><command>zone</command> <replaceable>zone_name</replaceable> <optional><replaceable>class</replaceable></optional> {
+ type master;
+ <optional> allow-query { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query-on { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-transfer { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-update { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> update-policy { <replaceable>update_policy_rule</replaceable> <optional>...</optional> }; </optional>
+ <optional> also-notify { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+ <optional> check-names (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
+ <optional> check-mx (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
+ <optional> check-wildcard <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> check-integrity <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> dialup <replaceable>dialup_option</replaceable> ; </optional>
+ <optional> file <replaceable>string</replaceable> ; </optional>
+ <optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>) ; </optional>
+ <optional> journal <replaceable>string</replaceable> ; </optional>
+ <optional> max-journal-size <replaceable>size_spec</replaceable>; </optional>
+ <optional> forward (<constant>only</constant>|<constant>first</constant>) ; </optional>
+ <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+ <optional> ixfr-base <replaceable>string</replaceable> ; </optional>
+ <optional> ixfr-from-differences <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> ixfr-tmp-file <replaceable>string</replaceable> ; </optional>
+ <optional> maintain-ixfr-base <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> max-ixfr-log-size <replaceable>number</replaceable> ; </optional>
+ <optional> max-transfer-idle-out <replaceable>number</replaceable> ; </optional>
+ <optional> max-transfer-time-out <replaceable>number</replaceable> ; </optional>
+ <optional> notify <replaceable>yes_or_no</replaceable> | <replaceable>explicit</replaceable> | <replaceable>master-only</replaceable> ; </optional>
+ <optional> notify-delay <replaceable>seconds</replaceable> ; </optional>
+ <optional> notify-to-soa <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> pubkey <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>string</replaceable> ; </optional>
+ <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> zone-statistics <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> sig-validity-interval <replaceable>number</replaceable> ; </optional>
+ <optional> sig-signing-nodes <replaceable>number</replaceable> ; </optional>
+ <optional> sig-signing-signatures <replaceable>number</replaceable> ; </optional>
+ <optional> sig-signing-type <replaceable>number</replaceable> ; </optional>
+ <optional> database <replaceable>string</replaceable> ; </optional>
+ <optional> min-refresh-time <replaceable>number</replaceable> ; </optional>
+ <optional> max-refresh-time <replaceable>number</replaceable> ; </optional>
+ <optional> min-retry-time <replaceable>number</replaceable> ; </optional>
+ <optional> max-retry-time <replaceable>number</replaceable> ; </optional>
+ <optional> key-directory <replaceable>path_name</replaceable>; </optional>
+ <optional> zero-no-soa-ttl <replaceable>yes_or_no</replaceable> ; </optional>
+};
+
+zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replaceable></optional> {
+ type slave;
+ <optional> allow-notify { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query-on { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-transfer { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-update-forwarding { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> update-check-ksk <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> try-tcp-refresh <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> also-notify { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+ <optional> check-names (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
+ <optional> dialup <replaceable>dialup_option</replaceable> ; </optional>
+ <optional> file <replaceable>string</replaceable> ; </optional>
+ <optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>) ; </optional>
+ <optional> journal <replaceable>string</replaceable> ; </optional>
+ <optional> max-journal-size <replaceable>size_spec</replaceable>; </optional>
+ <optional> forward (<constant>only</constant>|<constant>first</constant>) ; </optional>
+ <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+ <optional> ixfr-base <replaceable>string</replaceable> ; </optional>
+ <optional> ixfr-from-differences <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> ixfr-tmp-file <replaceable>string</replaceable> ; </optional>
+ <optional> maintain-ixfr-base <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> masters <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> }; </optional>
+ <optional> max-ixfr-log-size <replaceable>number</replaceable> ; </optional>
+ <optional> max-transfer-idle-in <replaceable>number</replaceable> ; </optional>
+ <optional> max-transfer-idle-out <replaceable>number</replaceable> ; </optional>
+ <optional> max-transfer-time-in <replaceable>number</replaceable> ; </optional>
+ <optional> max-transfer-time-out <replaceable>number</replaceable> ; </optional>
+ <optional> notify <replaceable>yes_or_no</replaceable> | <replaceable>explicit</replaceable> | <replaceable>master-only</replaceable> ; </optional>
+ <optional> notify-delay <replaceable>seconds</replaceable> ; </optional>
+ <optional> notify-to-soa <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> pubkey <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>string</replaceable> ; </optional>
+ <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> alt-transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> alt-transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> use-alt-transfer-source <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> notify-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> notify-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> zone-statistics <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> database <replaceable>string</replaceable> ; </optional>
+ <optional> min-refresh-time <replaceable>number</replaceable> ; </optional>
+ <optional> max-refresh-time <replaceable>number</replaceable> ; </optional>
+ <optional> min-retry-time <replaceable>number</replaceable> ; </optional>
+ <optional> max-retry-time <replaceable>number</replaceable> ; </optional>
+ <optional> multi-master <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> zero-no-soa-ttl <replaceable>yes_or_no</replaceable> ; </optional>
+};
+
+zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replaceable></optional> {
+ type hint;
+ file <replaceable>string</replaceable> ;
+ <optional> delegation-only <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> check-names (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; // Not Implemented. </optional>
+};
+
+zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replaceable></optional> {
+ type stub;
+ <optional> allow-query { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> allow-query-on { <replaceable>address_match_list</replaceable> }; </optional>
+ <optional> check-names (<constant>warn</constant>|<constant>fail</constant>|<constant>ignore</constant>) ; </optional>
+ <optional> dialup <replaceable>dialup_option</replaceable> ; </optional>
+ <optional> delegation-only <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> file <replaceable>string</replaceable> ; </optional>
+ <optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>) ; </optional>
+ <optional> forward (<constant>only</constant>|<constant>first</constant>) ; </optional>
+ <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+ <optional> masters <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> }; </optional>
+ <optional> max-transfer-idle-in <replaceable>number</replaceable> ; </optional>
+ <optional> max-transfer-time-in <replaceable>number</replaceable> ; </optional>
+ <optional> pubkey <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>string</replaceable> ; </optional>
+ <optional> transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> alt-transfer-source (<replaceable>ip4_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> alt-transfer-source-v6 (<replaceable>ip6_addr</replaceable> | <constant>*</constant>) <optional>port <replaceable>ip_port</replaceable></optional> ; </optional>
+ <optional> use-alt-transfer-source <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> zone-statistics <replaceable>yes_or_no</replaceable> ; </optional>
+ <optional> database <replaceable>string</replaceable> ; </optional>
+ <optional> min-refresh-time <replaceable>number</replaceable> ; </optional>
+ <optional> max-refresh-time <replaceable>number</replaceable> ; </optional>
+ <optional> min-retry-time <replaceable>number</replaceable> ; </optional>
+ <optional> max-retry-time <replaceable>number</replaceable> ; </optional>
+ <optional> multi-master <replaceable>yes_or_no</replaceable> ; </optional>
+};
+
+zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replaceable></optional> {
+ type forward;
+ <optional> forward (<constant>only</constant>|<constant>first</constant>) ; </optional>
+ <optional> forwarders { <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
+ <optional> delegation-only <replaceable>yes_or_no</replaceable> ; </optional>
+};
+
+zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replaceable></optional> {
+ type delegation-only;
+};
+
+</programlisting>
+
+ </sect2>
+ <sect2>
+ <title><command>zone</command> Statement Definition and Usage</title>
+ <sect3>
+ <title>Zone Types</title>
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="3Level-table">
+ <!--colspec colname="1" colnum="1" colsep="0" colwidth="1.108in"/-->
+ <!--colspec colname="2" colnum="2" colsep="0" colwidth="4.017in"/-->
+ <colspec colname="1" colnum="1" colsep="0"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="4.017in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>master</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The server has a master copy of the data
+ for the zone and will be able to provide authoritative
+ answers for
+ it.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>slave</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A slave zone is a replica of a master
+ zone. The <command>masters</command> list
+ specifies one or more IP addresses
+ of master servers that the slave contacts to update
+ its copy of the zone.
+ Masters list elements can also be names of other
+ masters lists.
+ By default, transfers are made from port 53 on the
+ servers; this can
+ be changed for all servers by specifying a port number
+ before the
+ list of IP addresses, or on a per-server basis after
+ the IP address.
+ Authentication to the master can also be done with
+ per-server TSIG keys.
+ If a file is specified, then the
+ replica will be written to this file whenever the zone
+ is changed,
+ and reloaded from this file on a server restart. Use
+ of a file is
+ recommended, since it often speeds server startup and
+ eliminates
+ a needless waste of bandwidth. Note that for large
+ numbers (in the
+ tens or hundreds of thousands) of zones per server, it
+ is best to
+ use a two-level naming scheme for zone filenames. For
+ example,
+ a slave server for the zone <literal>example.com</literal> might place
+ the zone contents into a file called
+ <filename>ex/example.com</filename> where <filename>ex/</filename> is
+ just the first two letters of the zone name. (Most
+ operating systems
+ behave very slowly if you put 100 000 files into
+ a single directory.)
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>stub</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A stub zone is similar to a slave zone,
+ except that it replicates only the NS records of a
+ master zone instead
+ of the entire zone. Stub zones are not a standard part
+ of the DNS;
+ they are a feature specific to the <acronym>BIND</acronym> implementation.
+ </para>
+
+ <para>
+ Stub zones can be used to eliminate the need for glue
+ NS record
+ in a parent zone at the expense of maintaining a stub
+ zone entry and
+ a set of name server addresses in <filename>named.conf</filename>.
+ This usage is not recommended for new configurations,
+ and BIND 9
+ supports it only in a limited way.
+ In <acronym>BIND</acronym> 4/8, zone
+ transfers of a parent zone
+ included the NS records from stub children of that
+ zone. This meant
+ that, in some cases, users could get away with
+ configuring child stubs
+ only in the master server for the parent zone. <acronym>BIND</acronym>
+ 9 never mixes together zone data from different zones
+ in this
+ way. Therefore, if a <acronym>BIND</acronym> 9 master serving a parent
+ zone has child stub zones configured, all the slave
+ servers for the
+ parent zone also need to have the same child stub
+ zones
+ configured.
+ </para>
+
+ <para>
+ Stub zones can also be used as a way of forcing the
+ resolution
+ of a given domain to use a particular set of
+ authoritative servers.
+ For example, the caching name servers on a private
+ network using
+ RFC1918 addressing may be configured with stub zones
+ for
+ <literal>10.in-addr.arpa</literal>
+ to use a set of internal name servers as the
+ authoritative
+ servers for that domain.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>forward</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A "forward zone" is a way to configure
+ forwarding on a per-domain basis. A <command>zone</command> statement
+ of type <command>forward</command> can
+ contain a <command>forward</command>
+ and/or <command>forwarders</command>
+ statement,
+ which will apply to queries within the domain given by
+ the zone
+ name. If no <command>forwarders</command>
+ statement is present or
+ an empty list for <command>forwarders</command> is given, then no
+ forwarding will be done for the domain, canceling the
+ effects of
+ any forwarders in the <command>options</command> statement. Thus
+ if you want to use this type of zone to change the
+ behavior of the
+ global <command>forward</command> option
+ (that is, "forward first"
+ to, then "forward only", or vice versa, but want to
+ use the same
+ servers as set globally) you need to re-specify the
+ global forwarders.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>hint</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The initial set of root name servers is
+ specified using a "hint zone". When the server starts
+ up, it uses
+ the root hints to find a root name server and get the
+ most recent
+ list of root name servers. If no hint zone is
+ specified for class
+ IN, the server uses a compiled-in default set of root
+ servers hints.
+ Classes other than IN have no built-in defaults hints.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>delegation-only</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ This is used to enforce the delegation-only
+ status of infrastructure zones (e.g. COM, NET, ORG).
+ Any answer that
+ is received without an explicit or implicit delegation
+ in the authority
+ section will be treated as NXDOMAIN. This does not
+ apply to the zone
+ apex. This should not be applied to leaf zones.
+ </para>
+ <para>
+ <varname>delegation-only</varname> has no
+ effect on answers received
+ from forwarders.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </sect3>
+
+ <sect3>
+ <title>Class</title>
+ <para>
+ The zone's name may optionally be followed by a class. If
+ a class is not specified, class <literal>IN</literal> (for <varname>Internet</varname>),
+ is assumed. This is correct for the vast majority of cases.
+ </para>
+ <para>
+ The <literal>hesiod</literal> class is
+ named for an information service from MIT's Project Athena. It
+ is
+ used to share information about various systems databases, such
+ as users, groups, printers and so on. The keyword
+ <literal>HS</literal> is
+ a synonym for hesiod.
+ </para>
+ <para>
+ Another MIT development is Chaosnet, a LAN protocol created
+ in the mid-1970s. Zone data for it can be specified with the <literal>CHAOS</literal> class.
+ </para>
+ </sect3>
+ <sect3>
+
+ <title>Zone Options</title>
+
+ <variablelist>
+
+ <varlistentry>
+ <term><command>allow-notify</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>allow-notify</command> in <xref linkend="access_control"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-query</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>allow-query</command> in <xref linkend="access_control"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-query-on</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>allow-query-on</command> in <xref linkend="access_control"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-transfer</command></term>
+ <listitem>
+ <para>
+ See the description of <command>allow-transfer</command>
+ in <xref linkend="access_control"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-update</command></term>
+ <listitem>
+ <para>
+ See the description of <command>allow-update</command>
+ in <xref linkend="access_control"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>update-policy</command></term>
+ <listitem>
+ <para>
+ Specifies a "Simple Secure Update" policy. See
+ <xref linkend="dynamic_update_policies"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>allow-update-forwarding</command></term>
+ <listitem>
+ <para>
+ See the description of <command>allow-update-forwarding</command>
+ in <xref linkend="access_control"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>also-notify</command></term>
+ <listitem>
+ <para>
+ Only meaningful if <command>notify</command>
+ is
+ active for this zone. The set of machines that will
+ receive a
+ <literal>DNS NOTIFY</literal> message
+ for this zone is made up of all the listed name servers
+ (other than
+ the primary master) for the zone plus any IP addresses
+ specified
+ with <command>also-notify</command>. A port
+ may be specified
+ with each <command>also-notify</command>
+ address to send the notify
+ messages to a port other than the default of 53.
+ <command>also-notify</command> is not
+ meaningful for stub zones.
+ The default is the empty list.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-names</command></term>
+ <listitem>
+ <para>
+ This option is used to restrict the character set and
+ syntax of
+ certain domain names in master files and/or DNS responses
+ received from the
+ network. The default varies according to zone type. For <command>master</command> zones the default is <command>fail</command>. For <command>slave</command>
+ zones the default is <command>warn</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-mx</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>check-mx</command> in <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-wildcard</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>check-wildcard</command> in <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-integrity</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>check-integrity</command> in <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>check-sibling</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>check-sibling</command> in <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>zero-no-soa-ttl</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>zero-no-soa-ttl</command> in <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>update-check-ksk</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>update-check-ksk</command> in <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>try-tcp-refresh</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>try-tcp-refresh</command> in <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>database</command></term>
+ <listitem>
+ <para>
+ Specify the type of database to be used for storing the
+ zone data. The string following the <command>database</command> keyword
+ is interpreted as a list of whitespace-delimited words.
+ The first word
+ identifies the database type, and any subsequent words are
+ passed
+ as arguments to the database to be interpreted in a way
+ specific
+ to the database type.
+ </para>
+ <para>
+ The default is <userinput>"rbt"</userinput>, BIND 9's
+ native in-memory
+ red-black-tree database. This database does not take
+ arguments.
+ </para>
+ <para>
+ Other values are possible if additional database drivers
+ have been linked into the server. Some sample drivers are
+ included
+ with the distribution but none are linked in by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>dialup</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>dialup</command> in <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>delegation-only</command></term>
+ <listitem>
+ <para>
+ The flag only applies to hint and stub zones. If set
+ to <userinput>yes</userinput>, then the zone will also be
+ treated as if it
+ is also a delegation-only type zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>forward</command></term>
+ <listitem>
+ <para>
+ Only meaningful if the zone has a forwarders
+ list. The <command>only</command> value causes
+ the lookup to fail
+ after trying the forwarders and getting no answer, while <command>first</command> would
+ allow a normal lookup to be tried.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>forwarders</command></term>
+ <listitem>
+ <para>
+ Used to override the list of global forwarders.
+ If it is not specified in a zone of type <command>forward</command>,
+ no forwarding is done for the zone and the global options are
+ not used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>ixfr-base</command></term>
+ <listitem>
+ <para>
+ Was used in <acronym>BIND</acronym> 8 to
+ specify the name
+ of the transaction log (journal) file for dynamic update
+ and IXFR.
+ <acronym>BIND</acronym> 9 ignores the option
+ and constructs the name of the journal
+ file by appending "<filename>.jnl</filename>"
+ to the name of the
+ zone file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>ixfr-tmp-file</command></term>
+ <listitem>
+ <para>
+ Was an undocumented option in <acronym>BIND</acronym> 8.
+ Ignored in <acronym>BIND</acronym> 9.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>journal</command></term>
+ <listitem>
+ <para>
+ Allow the default journal's filename to be overridden.
+ The default is the zone's filename with "<filename>.jnl</filename>" appended.
+ This is applicable to <command>master</command> and <command>slave</command> zones.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-journal-size</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>max-journal-size</command> in <xref linkend="server_resource_limits"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-transfer-time-in</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>max-transfer-time-in</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-transfer-idle-in</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>max-transfer-idle-in</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-transfer-time-out</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>max-transfer-time-out</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>max-transfer-idle-out</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>max-transfer-idle-out</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>notify</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>notify</command> in <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>notify-delay</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>notify-delay</command> in <xref linkend="tuning"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>notify-to-soa</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>notify-to-soa</command> in
+ <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>pubkey</command></term>
+ <listitem>
+ <para>
+ In <acronym>BIND</acronym> 8, this option was
+ intended for specifying
+ a public zone key for verification of signatures in DNSSEC
+ signed
+ zones when they are loaded from disk. <acronym>BIND</acronym> 9 does not verify signatures
+ on load and ignores the option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>zone-statistics</command></term>
+ <listitem>
+ <para>
+ If <userinput>yes</userinput>, the server will keep
+ statistical
+ information for this zone, which can be dumped to the
+ <command>statistics-file</command> defined in
+ the server options.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>sig-validity-interval</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>sig-validity-interval</command> in <xref linkend="tuning"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>sig-signing-nodes</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>sig-signing-nodes</command> in <xref linkend="tuning"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>sig-signing-signatures</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>sig-signing-signatures</command> in <xref linkend="tuning"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>sig-signing-type</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>sig-signing-type</command> in <xref linkend="tuning"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>transfer-source</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>transfer-source</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>transfer-source-v6</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>transfer-source-v6</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>alt-transfer-source</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>alt-transfer-source</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>alt-transfer-source-v6</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>alt-transfer-source-v6</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>use-alt-transfer-source</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>use-alt-transfer-source</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term><command>notify-source</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>notify-source</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>notify-source-v6</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>notify-source-v6</command> in <xref linkend="zone_transfers"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>min-refresh-time</command></term>
+ <term><command>max-refresh-time</command></term>
+ <term><command>min-retry-time</command></term>
+ <term><command>max-retry-time</command></term>
+ <listitem>
+ <para>
+ See the description in <xref linkend="tuning"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>ixfr-from-differences</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>ixfr-from-differences</command> in <xref linkend="boolean_options"/>.
+ (Note that the <command>ixfr-from-differences</command>
+ <userinput>master</userinput> and
+ <userinput>slave</userinput> choices are not
+ available at the zone level.)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>key-directory</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>key-directory</command> in <xref linkend="options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>multi-master</command></term>
+ <listitem>
+ <para>
+ See the description of <command>multi-master</command> in
+ <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>masterfile-format</command></term>
+ <listitem>
+ <para>
+ See the description of <command>masterfile-format</command>
+ in <xref linkend="tuning"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </sect3>
+ <sect3 id="dynamic_update_policies">
+ <title>Dynamic Update Policies</title>
+ <para><acronym>BIND</acronym> 9 supports two alternative
+ methods of granting clients the right to perform
+ dynamic updates to a zone, configured by the
+ <command>allow-update</command> and
+ <command>update-policy</command> option, respectively.
+ </para>
+ <para>
+ The <command>allow-update</command> clause works the
+ same way as in previous versions of <acronym>BIND</acronym>.
+ It grants given clients the permission to update any
+ record of any name in the zone.
+ </para>
+ <para>
+ The <command>update-policy</command> clause is new
+ in <acronym>BIND</acronym> 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.
+ </para>
+ <para>
+ Rules are specified in the <command>update-policy</command>
+ zone option, and are only meaningful for master zones.
+ When the <command>update-policy</command> statement
+ is present, it is a configuration error for the
+ <command>allow-update</command> statement to be
+ present. The <command>update-policy</command> statement
+ only examines the signer of a message; the source
+ address is not relevant.
+ </para>
+
+ <para>
+ This is how a rule definition looks:
+ </para>
+
+<programlisting>
+( <command>grant</command> | <command>deny</command> ) <replaceable>identity</replaceable> <replaceable>nametype</replaceable> <replaceable>name</replaceable> <optional> <replaceable>types</replaceable> </optional>
+</programlisting>
+
+ <para>
+ 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.
+ </para>
+ <para>
+ No signer is required for <replaceable>tcp-self</replaceable>
+ or <replaceable>6to4-self</replaceable> however the standard
+ reverse mapping / prefix conversion must match the identity
+ field.
+ </para>
+ <para>
+ The identity field specifies a name or a wildcard
+ name. Normally, this is the name of the TSIG or
+ SIG(0) key used to sign the update request. When a
+ TKEY exchange has been used to create a shared secret,
+ the identity of the shared secret is the same as the
+ identity of the key used to authenticate the TKEY
+ exchange. TKEY is also the negotiation method used
+ by GSS-TSIG, which establishes an identity that is
+ the Kerberos principal of the client, such as
+ <userinput>"user@host.domain"</userinput>. When the
+ <replaceable>identity</replaceable> field specifies
+ a wildcard name, it is subject to DNS wildcard
+ expansion, so the rule will apply to multiple identities.
+ The <replaceable>identity</replaceable> field must
+ contain a fully-qualified domain name.
+ </para>
+
+ <para>
+ The <replaceable>nametype</replaceable> field has 12
+ values:
+ <varname>name</varname>, <varname>subdomain</varname>,
+ <varname>wildcard</varname>, <varname>self</varname>,
+ <varname>selfsub</varname>, <varname>selfwild</varname>,
+ <varname>krb5-self</varname>, <varname>ms-self</varname>,
+ <varname>krb5-subdomain</varname>,
+ <varname>ms-subdomain</varname>,
+ <varname>tcp-self</varname> and <varname>6to4-self</varname>.
+ </para>
+ <informaltable>
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="0.819in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="3.681in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>name</varname>
+ </para>
+ </entry> <entry colname="2">
+ <para>
+ Exact-match semantics. This rule matches
+ when the name being updated is identical
+ to the contents of the
+ <replaceable>name</replaceable> field.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>subdomain</varname>
+ </para>
+ </entry> <entry colname="2">
+ <para>
+ This rule matches when the name being updated
+ is a subdomain of, or identical to, the
+ contents of the <replaceable>name</replaceable>
+ field.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>wildcard</varname>
+ </para>
+ </entry> <entry colname="2">
+ <para>
+ The <replaceable>name</replaceable> field
+ is subject to DNS wildcard expansion, and
+ this rule matches when the name being updated
+ name is a valid expansion of the wildcard.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>self</varname>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ This rule matches when the name being updated
+ matches the contents of the
+ <replaceable>identity</replaceable> field.
+ The <replaceable>name</replaceable> field
+ is ignored, but should be the same as the
+ <replaceable>identity</replaceable> field.
+ The <varname>self</varname> nametype is
+ most useful when allowing using one key per
+ name to update, where the key has the same
+ name as the name to be updated. The
+ <replaceable>identity</replaceable> would
+ be specified as <constant>*</constant> (an asterisk) in
+ this case.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>selfsub</varname>
+ </para>
+ </entry> <entry colname="2">
+ <para>
+ This rule is similar to <varname>self</varname>
+ except that subdomains of <varname>self</varname>
+ can also be updated.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>selfwild</varname>
+ </para>
+ </entry> <entry colname="2">
+ <para>
+ This rule is similar to <varname>self</varname>
+ except that only subdomains of
+ <varname>self</varname> can be updated.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>tcp-self</varname>
+ </para>
+ </entry> <entry colname="2">
+ <para>
+ Allow updates that have been sent via TCP and
+ for which the standard mapping from the initiating
+ IP address into the IN-ADDR.ARPA and IP6.ARPA
+ namespaces match the name to be updated.
+ </para>
+ <note>
+ It is theoretically possible to spoof these TCP
+ sessions.
+ </note>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <varname>6to4-self</varname>
+ </para>
+ </entry> <entry colname="2">
+ <para>
+ Allow the 6to4 prefix to be update by any TCP
+ conection 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.
+ </para>
+ <note>
+ It is theoretically possible to spoof these TCP
+ sessions.
+ </note>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>
+ In all cases, the <replaceable>name</replaceable>
+ field must
+ specify a fully-qualified domain name.
+ </para>
+
+ <para>
+ If no types are explicitly specified, this rule matches
+ all types except RRSIG, NS, SOA, NSEC and NSEC3. Types
+ may be specified by name, including "ANY" (ANY matches
+ all types except NSEC and NSEC3, which can never be
+ updated). Note that when an attempt is made to delete
+ all records associated with a name, the rules are
+ checked for each existing record type.
+ </para>
+ </sect3>
+ </sect2>
+ </sect1>
+ <sect1>
+ <title>Zone File</title>
+ <sect2 id="types_of_resource_records_and_when_to_use_them">
+ <title>Types of Resource Records and When to Use Them</title>
+ <para>
+ This section, largely borrowed from RFC 1034, describes the
+ concept of a Resource Record (RR) and explains when each is used.
+ Since the publication of RFC 1034, several new RRs have been
+ identified
+ and implemented in the DNS. These are also included.
+ </para>
+ <sect3>
+ <title>Resource Records</title>
+
+ <para>
+ A domain name identifies a node. Each node has a set of
+ resource information, which may be empty. The set of resource
+ information associated with a particular name is composed of
+ separate RRs. The order of RRs in a set is not significant and
+ need not be preserved by name servers, resolvers, or other
+ parts of the DNS. However, sorting of multiple RRs is
+ permitted for optimization purposes, for example, to specify
+ that a particular nearby server be tried first. See <xref linkend="the_sortlist_statement"/> and <xref linkend="rrset_ordering"/>.
+ </para>
+
+ <para>
+ The components of a Resource Record are:
+ </para>
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.000in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="3.500in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ owner name
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The domain name where the RR is found.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ type
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ An encoded 16-bit value that specifies
+ the type of the resource record.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ TTL
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The time-to-live of the RR. This field
+ is a 32-bit integer in units of seconds, and is
+ primarily used by
+ resolvers when they cache RRs. The TTL describes how
+ long a RR can
+ be cached before it should be discarded.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ class
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ An encoded 16-bit value that identifies
+ a protocol family or instance of a protocol.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ RDATA
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The resource data. The format of the
+ data is type (and sometimes class) specific.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ The following are <emphasis>types</emphasis> of valid RRs:
+ </para>
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="0.875in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="3.625in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ A
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A host address. In the IN class, this is a
+ 32-bit IP address. Described in RFC 1035.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ AAAA
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv6 address. Described in RFC 1886.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ A6
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv6 address. This can be a partial
+ address (a suffix) and an indirection to the name
+ where the rest of the
+ address (the prefix) can be found. Experimental.
+ Described in RFC 2874.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ AFSDB
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Location of AFS database servers.
+ Experimental. Described in RFC 1183.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ APL
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Address prefix list. Experimental.
+ Described in RFC 3123.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ CERT
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Holds a digital certificate.
+ Described in RFC 2538.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ CNAME
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Identifies the canonical name of an alias.
+ Described in RFC 1035.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ DHCID
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Is used for identifying which DHCP client is
+ associated with this name. Described in RFC 4701.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ DNAME
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Replaces the domain name specified with
+ another name to be looked up, effectively aliasing an
+ entire
+ subtree of the domain name space rather than a single
+ record
+ as in the case of the CNAME RR.
+ Described in RFC 2672.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ DNSKEY
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Stores a public key associated with a signed
+ DNS zone. Described in RFC 4034.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ DS
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Stores the hash of a public key associated with a
+ signed DNS zone. Described in RFC 4034.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ GPOS
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Specifies the global position. Superseded by LOC.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ HINFO
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Identifies the CPU and OS used by a host.
+ Described in RFC 1035.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ IPSECKEY
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Provides a method for storing IPsec keying material in
+ DNS. Described in RFC 4025.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ ISDN
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Representation of ISDN addresses.
+ Experimental. Described in RFC 1183.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ KEY
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Stores a public key associated with a
+ DNS name. Used in original DNSSEC; replaced
+ by DNSKEY in DNSSECbis, but still used with
+ SIG(0). Described in RFCs 2535 and 2931.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ KX
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Identifies a key exchanger for this
+ DNS name. Described in RFC 2230.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ LOC
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ For storing GPS info. Described in RFC 1876.
+ Experimental.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ MX
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Identifies a mail exchange for the domain with
+ a 16-bit preference value (lower is better)
+ followed by the host name of the mail exchange.
+ Described in RFC 974, RFC 1035.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ NAPTR
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Name authority pointer. Described in RFC 2915.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ NSAP
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A network service access point.
+ Described in RFC 1706.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ NS
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The authoritative name server for the
+ domain. Described in RFC 1035.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ NSEC
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Used in DNSSECbis to securely indicate that
+ RRs with an owner name in a certain name interval do
+ not exist in
+ a zone and indicate what RR types are present for an
+ existing name.
+ Described in RFC 4034.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ NSEC3
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Used in DNSSECbis to securely indicate that
+ RRs with an owner name in a certain name
+ interval do not exist in a zone and indicate
+ what RR types are present for an existing
+ name. NSEC3 differs from NSEC in that it
+ prevents zone enumeration but is more
+ computationally expensive on both the server
+ and the client than NSEC. Described in RFC
+ 5155.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ NSEC3PARAM
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Used in DNSSECbis to tell the authoritative
+ server which NSEC3 chains are available to use.
+ Described in RFC 5155.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ NXT
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Used in DNSSEC to securely indicate that
+ RRs with an owner name in a certain name interval do
+ not exist in
+ a zone and indicate what RR types are present for an
+ existing name.
+ Used in original DNSSEC; replaced by NSEC in
+ DNSSECbis.
+ Described in RFC 2535.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ PTR
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ A pointer to another part of the domain
+ name space. Described in RFC 1035.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ PX
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Provides mappings between RFC 822 and X.400
+ addresses. Described in RFC 2163.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ RP
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Information on persons responsible
+ for the domain. Experimental. Described in RFC 1183.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ RRSIG
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Contains DNSSECbis signature data. Described
+ in RFC 4034.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ RT
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Route-through binding for hosts that
+ do not have their own direct wide area network
+ addresses.
+ Experimental. Described in RFC 1183.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ SIG
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Contains DNSSEC signature data. Used in
+ original DNSSEC; replaced by RRSIG in
+ DNSSECbis, but still used for SIG(0).
+ Described in RFCs 2535 and 2931.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ SOA
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Identifies the start of a zone of authority.
+ Described in RFC 1035.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ SPF
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Contains the Sender Policy Framework information
+ for a given email domain. Described in RFC 4408.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ SRV
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Information about well known network
+ services (replaces WKS). Described in RFC 2782.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ SSHFP
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Provides a way to securely publish a secure shell key's
+ fingerprint. Described in RFC 4255.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ TXT
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Text records. Described in RFC 1035.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ WKS
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Information about which well known
+ network services, such as SMTP, that a domain
+ supports. Historical.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ X25
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Representation of X.25 network addresses.
+ Experimental. Described in RFC 1183.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ The following <emphasis>classes</emphasis> of resource records
+ are currently valid in the DNS:
+ </para>
+ <informaltable colsep="0" rowsep="0"><tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="0.875in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="3.625in"/>
+ <tbody>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ IN
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The Internet.
+ </para>
+ </entry>
+ </row>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ CH
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Chaosnet, a LAN protocol created at MIT in the
+ mid-1970s.
+ Rarely used for its historical purpose, but reused for
+ BIND's
+ built-in server information zones, e.g.,
+ <literal>version.bind</literal>.
+ </para>
+ </entry>
+ </row>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ HS
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Hesiod, an information service
+ developed by MIT's Project Athena. It is used to share
+ information
+ about various systems databases, such as users,
+ groups, printers
+ and so on.
+ </para>
+ </entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>
+ The owner name is often implicit, rather than forming an
+ integral
+ part of the RR. For example, many name servers internally form
+ tree
+ or hash structures for the name space, and chain RRs off nodes.
+ The remaining RR parts are the fixed header (type, class, TTL)
+ which is consistent for all RRs, and a variable part (RDATA)
+ that
+ fits the needs of the resource being described.
+ </para>
+ <para>
+ The meaning of the TTL field is a time limit on how long an
+ RR can be kept in a cache. This limit does not apply to
+ authoritative
+ data in zones; it is also timed out, but by the refreshing
+ policies
+ for the zone. The TTL is assigned by the administrator for the
+ zone where the data originates. While short TTLs can be used to
+ minimize caching, and a zero TTL prohibits caching, the
+ realities
+ of Internet performance suggest that these times should be on
+ the
+ order of days for the typical host. If a change can be
+ anticipated,
+ the TTL can be reduced prior to the change to minimize
+ inconsistency
+ during the change, and then increased back to its former value
+ following
+ the change.
+ </para>
+ <para>
+ The data in the RDATA section of RRs is carried as a combination
+ of binary strings and domain names. The domain names are
+ frequently
+ used as "pointers" to other data in the DNS.
+ </para>
+ </sect3>
+ <sect3>
+ <title>Textual expression of RRs</title>
+ <para>
+ RRs are represented in binary form in the packets of the DNS
+ protocol, and are usually represented in highly encoded form
+ when
+ stored in a name server or resolver. In the examples provided
+ in
+ RFC 1034, a style similar to that used in master files was
+ employed
+ in order to show the contents of RRs. In this format, most RRs
+ are shown on a single line, although continuation lines are
+ possible
+ using parentheses.
+ </para>
+ <para>
+ The start of the line gives the owner of the RR. If a line
+ begins with a blank, then the owner is assumed to be the same as
+ that of the previous RR. Blank lines are often included for
+ readability.
+ </para>
+ <para>
+ Following the owner, we list the TTL, type, and class of the
+ RR. Class and type use the mnemonics defined above, and TTL is
+ an integer before the type field. In order to avoid ambiguity
+ in
+ parsing, type and class mnemonics are disjoint, TTLs are
+ integers,
+ and the type mnemonic is always last. The IN class and TTL
+ values
+ are often omitted from examples in the interests of clarity.
+ </para>
+ <para>
+ The resource data or RDATA section of the RR are given using
+ knowledge of the typical representation for the data.
+ </para>
+ <para>
+ For example, we might show the RRs carried in a message as:
+ </para>
+ <informaltable colsep="0" rowsep="0"><tgroup cols="3" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.381in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="1.020in"/>
+ <colspec colname="3" colnum="3" colsep="0" colwidth="2.099in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <literal>ISI.EDU.</literal>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>MX</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>10 VENERA.ISI.EDU.</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para/>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>MX</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>10 VAXA.ISI.EDU</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <literal>VENERA.ISI.EDU</literal>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>A</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>128.9.0.32</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para/>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>A</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>10.1.0.52</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <literal>VAXA.ISI.EDU</literal>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>A</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>10.2.0.27</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para/>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>A</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>128.9.0.33</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ The MX RRs have an RDATA section which consists of a 16-bit
+ number followed by a domain name. The address RRs use a
+ standard
+ IP address format to contain a 32-bit internet address.
+ </para>
+ <para>
+ The above example shows six RRs, with two RRs at each of three
+ domain names.
+ </para>
+ <para>
+ Similarly we might see:
+ </para>
+ <informaltable colsep="0" rowsep="0"><tgroup cols="3" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.491in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="1.067in"/>
+ <colspec colname="3" colnum="3" colsep="0" colwidth="2.067in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <literal>XX.LCS.MIT.EDU.</literal>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>IN A</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>10.0.0.44</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1"/>
+ <entry colname="2">
+ <para>
+ <literal>CH A</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>MIT.EDU. 2420</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ This example shows two addresses for
+ <literal>XX.LCS.MIT.EDU</literal>, each of a different class.
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Discussion of MX Records</title>
+
+ <para>
+ As described above, domain servers store information as a
+ series of resource records, each of which contains a particular
+ piece of information about a given domain name (which is usually,
+ but not always, a host). The simplest way to think of a RR is as
+ a typed pair of data, a domain name matched with a relevant datum,
+ and stored with some additional type information to help systems
+ determine when the RR is relevant.
+ </para>
+
+ <para>
+ MX records are used to control delivery of email. The data
+ specified in the record is a priority and a domain name. The
+ priority
+ controls the order in which email delivery is attempted, with the
+ lowest number first. If two priorities are the same, a server is
+ chosen randomly. If no servers at a given priority are responding,
+ the mail transport agent will fall back to the next largest
+ priority.
+ Priority numbers do not have any absolute meaning &mdash; they are
+ relevant
+ only respective to other MX records for that domain name. The
+ domain
+ name given is the machine to which the mail will be delivered.
+ It <emphasis>must</emphasis> have an associated address record
+ (A or AAAA) &mdash; CNAME is not sufficient.
+ </para>
+ <para>
+ For a given domain, if there is both a CNAME record and an
+ MX record, the MX record is in error, and will be ignored.
+ Instead,
+ the mail will be delivered to the server specified in the MX
+ record
+ pointed to by the CNAME.
+ </para>
+ <para>
+ For example:
+ </para>
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="5" colsep="0" rowsep="0" tgroupstyle="3Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.708in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="0.444in"/>
+ <colspec colname="3" colnum="3" colsep="0" colwidth="0.444in"/>
+ <colspec colname="4" colnum="4" colsep="0" colwidth="0.976in"/>
+ <colspec colname="5" colnum="5" colsep="0" colwidth="1.553in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <literal>example.com.</literal>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>IN</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>MX</literal>
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ <literal>10</literal>
+ </para>
+ </entry>
+ <entry colname="5">
+ <para>
+ <literal>mail.example.com.</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para/>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>IN</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>MX</literal>
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ <literal>10</literal>
+ </para>
+ </entry>
+ <entry colname="5">
+ <para>
+ <literal>mail2.example.com.</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para/>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>IN</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>MX</literal>
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ <literal>20</literal>
+ </para>
+ </entry>
+ <entry colname="5">
+ <para>
+ <literal>mail.backup.org.</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <literal>mail.example.com.</literal>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>IN</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>A</literal>
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ <literal>10.0.0.1</literal>
+ </para>
+ </entry>
+ <entry colname="5">
+ <para/>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <literal>mail2.example.com.</literal>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>IN</literal>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <literal>A</literal>
+ </para>
+ </entry>
+ <entry colname="4">
+ <para>
+ <literal>10.0.0.2</literal>
+ </para>
+ </entry>
+ <entry colname="5">
+ <para/>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable><para>
+ Mail delivery will be attempted to <literal>mail.example.com</literal> and
+ <literal>mail2.example.com</literal> (in
+ any order), and if neither of those succeed, delivery to <literal>mail.backup.org</literal> will
+ be attempted.
+ </para>
+ </sect2>
+ <sect2 id="Setting_TTLs">
+ <title>Setting TTLs</title>
+ <para>
+ The time-to-live of the RR field is a 32-bit integer represented
+ in units of seconds, and is primarily used by resolvers when they
+ cache RRs. The TTL describes how long a RR can be cached before it
+ should be discarded. The following three types of TTL are
+ currently
+ used in a zone file.
+ </para>
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="3Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="0.750in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="4.375in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ SOA
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The last field in the SOA is the negative
+ caching TTL. This controls how long other servers will
+ cache no-such-domain
+ (NXDOMAIN) responses from you.
+ </para>
+ <para>
+ The maximum time for
+ negative caching is 3 hours (3h).
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ $TTL
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The $TTL directive at the top of the
+ zone file (before the SOA) gives a default TTL for every
+ RR without
+ a specific TTL set.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ RR TTLs
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Each RR can have a TTL as the second
+ field in the RR, which will control how long other
+ servers can cache
+ the it.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ All of these TTLs default to units of seconds, though units
+ can be explicitly specified, for example, <literal>1h30m</literal>.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Inverse Mapping in IPv4</title>
+ <para>
+ Reverse name resolution (that is, translation from IP address
+ to name) is achieved by means of the <emphasis>in-addr.arpa</emphasis> domain
+ and PTR records. Entries in the in-addr.arpa domain are made in
+ least-to-most significant order, read left to right. This is the
+ opposite order to the way IP addresses are usually written. Thus,
+ a machine with an IP address of 10.1.2.3 would have a
+ corresponding
+ in-addr.arpa name of
+ 3.2.1.10.in-addr.arpa. This name should have a PTR resource record
+ whose data field is the name of the machine or, optionally,
+ multiple
+ PTR records if the machine has more than one name. For example,
+ in the <optional>example.com</optional> domain:
+ </para>
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="3Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.125in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="4.000in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <literal>$ORIGIN</literal>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>2.1.10.in-addr.arpa</literal>
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para>
+ <literal>3</literal>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <literal>IN PTR foo.example.com.</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <note>
+ <para>
+ The <command>$ORIGIN</command> lines in the examples
+ are for providing context to the examples only &mdash; they do not
+ necessarily
+ appear in the actual usage. They are only used here to indicate
+ that the example is relative to the listed origin.
+ </para>
+ </note>
+ </sect2>
+ <sect2>
+ <title>Other Zone File Directives</title>
+ <para>
+ The Master File Format was initially defined in RFC 1035 and
+ has subsequently been extended. While the Master File Format
+ itself
+ is class independent all records in a Master File must be of the
+ same
+ class.
+ </para>
+ <para>
+ Master File Directives include <command>$ORIGIN</command>, <command>$INCLUDE</command>,
+ and <command>$TTL.</command>
+ </para>
+ <sect3>
+ <title>The <command>$ORIGIN</command> Directive</title>
+ <para>
+ Syntax: <command>$ORIGIN</command>
+ <replaceable>domain-name</replaceable>
+ <optional><replaceable>comment</replaceable></optional>
+ </para>
+ <para><command>$ORIGIN</command>
+ sets the domain name that will be appended to any
+ unqualified records. When a zone is first read in there
+ is an implicit <command>$ORIGIN</command>
+ &lt;<varname>zone-name</varname>&gt;<command>.</command>
+ The current <command>$ORIGIN</command> is appended to
+ the domain specified in the <command>$ORIGIN</command>
+ argument if it is not absolute.
+ </para>
+
+<programlisting>
+$ORIGIN example.com.
+WWW CNAME MAIN-SERVER
+</programlisting>
+
+ <para>
+ is equivalent to
+ </para>
+
+<programlisting>
+WWW.EXAMPLE.COM. CNAME MAIN-SERVER.EXAMPLE.COM.
+</programlisting>
+
+ </sect3>
+ <sect3>
+ <title>The <command>$INCLUDE</command> Directive</title>
+ <para>
+ Syntax: <command>$INCLUDE</command>
+ <replaceable>filename</replaceable>
+ <optional>
+<replaceable>origin</replaceable> </optional>
+ <optional> <replaceable>comment</replaceable> </optional>
+ </para>
+ <para>
+ Read and process the file <filename>filename</filename> as
+ if it were included into the file at this point. If <command>origin</command> is
+ specified the file is processed with <command>$ORIGIN</command> set
+ to that value, otherwise the current <command>$ORIGIN</command> is
+ used.
+ </para>
+ <para>
+ The origin and the current domain name
+ revert to the values they had prior to the <command>$INCLUDE</command> once
+ the file has been read.
+ </para>
+ <note>
+ <para>
+ RFC 1035 specifies that the current origin should be restored
+ after
+ an <command>$INCLUDE</command>, but it is silent
+ on whether the current
+ domain name should also be restored. BIND 9 restores both of
+ them.
+ This could be construed as a deviation from RFC 1035, a
+ feature, or both.
+ </para>
+ </note>
+ </sect3>
+ <sect3>
+ <title>The <command>$TTL</command> Directive</title>
+ <para>
+ Syntax: <command>$TTL</command>
+ <replaceable>default-ttl</replaceable>
+ <optional>
+<replaceable>comment</replaceable> </optional>
+ </para>
+ <para>
+ Set the default Time To Live (TTL) for subsequent records
+ with undefined TTLs. Valid TTLs are of the range 0-2147483647
+ seconds.
+ </para>
+ <para><command>$TTL</command>
+ is defined in RFC 2308.
+ </para>
+ </sect3>
+ </sect2>
+ <sect2>
+ <title><acronym>BIND</acronym> Master File Extension: the <command>$GENERATE</command> Directive</title>
+ <para>
+ Syntax: <command>$GENERATE</command>
+ <replaceable>range</replaceable>
+ <replaceable>lhs</replaceable>
+ <optional><replaceable>ttl</replaceable></optional>
+ <optional><replaceable>class</replaceable></optional>
+ <replaceable>type</replaceable>
+ <replaceable>rhs</replaceable>
+ <optional><replaceable>comment</replaceable></optional>
+ </para>
+ <para><command>$GENERATE</command>
+ is used to create a series of resource records that only
+ differ from each other by an
+ iterator. <command>$GENERATE</command> can be used to
+ easily generate the sets of records required to support
+ sub /24 reverse delegations described in RFC 2317:
+ Classless IN-ADDR.ARPA delegation.
+ </para>
+
+<programlisting>$ORIGIN 0.0.192.IN-ADDR.ARPA.
+$GENERATE 1-2 0 NS SERVER$.EXAMPLE.
+$GENERATE 1-127 $ CNAME $.0</programlisting>
+
+ <para>
+ is equivalent to
+ </para>
+
+<programlisting>0.0.0.192.IN-ADDR.ARPA. NS SERVER1.EXAMPLE.
+0.0.0.192.IN-ADDR.ARPA. NS SERVER2.EXAMPLE.
+1.0.0.192.IN-ADDR.ARPA. CNAME 1.0.0.0.192.IN-ADDR.ARPA.
+2.0.0.192.IN-ADDR.ARPA. CNAME 2.0.0.0.192.IN-ADDR.ARPA.
+...
+127.0.0.192.IN-ADDR.ARPA. CNAME 127.0.0.0.192.IN-ADDR.ARPA.
+</programlisting>
+
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="3Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="0.875in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="4.250in"/>
+ <tbody>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>range</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ This can be one of two forms: start-stop
+ or start-stop/step. If the first form is used, then step
+ is set to
+ 1. All of start, stop and step must be positive.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>lhs</command></para>
+ </entry>
+ <entry colname="2">
+ <para>This
+ describes the owner name of the resource records
+ to be created. Any single <command>$</command>
+ (dollar sign)
+ symbols within the <command>lhs</command> side
+ are replaced by the iterator value.
+
+ To get a $ in the output, you need to escape the
+ <command>$</command> using a backslash
+ <command>\</command>,
+ e.g. <command>\$</command>. The
+ <command>$</command> may optionally be followed
+ by modifiers which change the offset from the
+ iterator, field width and base.
+
+ Modifiers are introduced by a
+ <command>{</command> (left brace) immediately following the
+ <command>$</command> as
+ <command>${offset[,width[,base]]}</command>.
+ For example, <command>${-20,3,d}</command>
+ subtracts 20 from the current value, prints the
+ result as a decimal in a zero-padded field of
+ width 3.
+
+ Available output forms are decimal
+ (<command>d</command>), octal
+ (<command>o</command>) and hexadecimal
+ (<command>x</command> or <command>X</command>
+ for uppercase). The default modifier is
+ <command>${0,0,d}</command>. If the
+ <command>lhs</command> is not absolute, the
+ current <command>$ORIGIN</command> is appended
+ to the name.
+ </para>
+ <para>
+ For compatibility with earlier versions, <command>$$</command> is still
+ recognized as indicating a literal $ in the output.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ttl</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Specifies the time-to-live of the generated records. If
+ not specified this will be inherited using the
+ normal ttl inheritance rules.
+ </para>
+ <para><command>class</command>
+ and <command>ttl</command> can be
+ entered in either order.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>class</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Specifies the class of the generated records.
+ This must match the zone class if it is
+ specified.
+ </para>
+ <para><command>class</command>
+ and <command>ttl</command> can be
+ entered in either order.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>type</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ At present the only supported types are
+ PTR, CNAME, DNAME, A, AAAA and NS.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>rhs</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <command>rhs</command> is a domain name. It is processed
+ similarly to lhs.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ <para>
+ The <command>$GENERATE</command> directive is a <acronym>BIND</acronym> extension
+ and not part of the standard zone file format.
+ </para>
+ <para>
+ BIND 8 does not support the optional TTL and CLASS fields.
+ </para>
+ </sect2>
+
+ <sect2 id="zonefile_format">
+ <title>Additional File Formats</title>
+ <para>
+ In addition to the standard textual format, BIND 9
+ supports the ability to read or dump to zone files in
+ other formats. The <constant>raw</constant> format is
+ currently available as an additional format. It is a
+ binary format representing BIND 9's internal data
+ structure directly, thereby remarkably improving the
+ loading time.
+ </para>
+ <para>
+ For a primary server, a zone file in the
+ <constant>raw</constant> format is expected to be
+ generated from a textual zone file by the
+ <command>named-compilezone</command> command. For a
+ secondary server or for a dynamic zone, it is automatically
+ generated (if this format is specified by the
+ <command>masterfile-format</command> option) when
+ <command>named</command> dumps the zone contents after
+ zone transfer or when applying prior updates.
+ </para>
+ <para>
+ If a zone file in a binary format needs manual modification,
+ it first must be converted to a textual form by the
+ <command>named-compilezone</command> command. All
+ necessary modification should go to the text file, which
+ should then be converted to the binary form by the
+ <command>named-compilezone</command> command again.
+ </para>
+ <para>
+ Although the <constant>raw</constant> format uses the
+ network byte order and avoids architecture-dependent
+ data alignment so that it is as much portable as
+ possible, it is primarily expected to be used inside
+ the same single system. In order to export a zone
+ file in the <constant>raw</constant> format or make a
+ portable backup of the file, it is recommended to
+ convert the file to the standard textual representation.
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="statistics">
+ <title>BIND9 Statistics</title>
+ <para>
+ <acronym>BIND</acronym> 9 maintains lots of statistics
+ information and provides several interfaces for users to
+ get access to the statistics.
+ The available statistics include all statistics counters
+ that were available in <acronym>BIND</acronym> 8 and
+ are meaningful in <acronym>BIND</acronym> 9,
+ and other information that is considered useful.
+ </para>
+
+ <para>
+ The statistics information is categorized into the following
+ sections.
+ </para>
+
+ <informaltable frame="all">
+ <tgroup cols="2">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="3.300in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="2.625in"/>
+ <tbody>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para>Incoming Requests</para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The number of incoming DNS requests for each OPCODE.
+ </para>
+ </entry>
+ </row>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para>Incoming Queries</para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The number of incoming queries for each RR type.
+ </para>
+ </entry>
+ </row>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para>Outgoing Queries</para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The number of outgoing queries for each RR
+ type sent from the internal resolver.
+ Maintained per view.
+ </para>
+ </entry>
+ </row>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para>Name Server Statistics</para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Statistics counters about incoming request processing.
+ </para>
+ </entry>
+ </row>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para>Zone Maintenance Statistics</para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Statistics counters regarding zone maintenance
+ operations such as zone transfers.
+ </para>
+ </entry>
+ </row>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para>Resolver Statistics</para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Statistics counters about name resolution
+ performed in the internal resolver.
+ Maintained per view.
+ </para>
+ </entry>
+ </row>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para>Cache DB RRsets</para>
+ </entry>
+ <entry colname="2">
+ <para>
+ The number of RRsets per RR type (positive
+ or negative) and nonexistent names stored in the
+ cache database.
+ Maintained per view.
+ </para>
+ </entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <para>
+ A subset of Name Server Statistics is collected and shown
+ per zone for which the server has the authority when
+ <command>zone-statistics</command> is set to
+ <userinput>yes</userinput>.
+ These statistics counters are shown with their zone and view
+ names.
+ In some cases the view names are omitted for the default view.
+ </para>
+
+ <para>
+ There are currently two user interfaces to get access to the
+ statistics.
+ One is in the plain text format dumped to the file specified
+ by the <command>statistics-file</command> configuration option.
+ The other is remotely accessible via a statistics channel
+ when the <command>statistics-channels</command> statement
+ is specified in the configuration file
+ (see <xref linkend="statschannels"/>.)
+ </para>
+
+ <sect3 id="statsfile">
+ <title>The Statistics File</title>
+ <para>
+ The text format statistics dump begins with a line, like:
+ </para>
+ <para>
+ <command>+++ Statistics Dump +++ (973798949)</command>
+ </para>
+ <para>
+ The number in parentheses is a standard
+ Unix-style timestamp, measured as seconds since January 1, 1970.
+
+ Following
+ that line is a set of statistics information, which is categorized
+ as described above.
+ Each section begins with a line, like:
+ </para>
+
+ <para>
+ <command>++ Name Server Statistics ++</command>
+ </para>
+
+ <para>
+ Each section consists of lines, each containing the statistics
+ counter value followed by its textual description.
+ See below for available counters.
+ For brevity, counters that have a value of 0 are not shown
+ in the statistics file.
+ </para>
+
+ <para>
+ The statistics dump ends with the line where the
+ number is identical to the number in the beginning line; for example:
+ </para>
+ <para>
+ <command>--- Statistics Dump --- (973798949)</command>
+ </para>
+ </sect3>
+
+ <sect2 id="statistics_counters">
+ <title>Statistics Counters</title>
+ <para>
+ The following tables summarize statistics counters that
+ <acronym>BIND</acronym> 9 provides.
+ For each row of the tables, the leftmost column is the
+ abbreviated symbol name of that counter.
+ These symbols are shown in the statistics information
+ accessed via an HTTP statistics channel.
+ The rightmost column gives the description of the counter,
+ which is also shown in the statistics file
+ (but, in this document, possibly with slight modification
+ for better readability).
+ Additional notes may also be provided in this column.
+ When a middle column exists between these two columns,
+ it gives the corresponding counter name of the
+ <acronym>BIND</acronym> 8 statistics, if applicable.
+ </para>
+
+ <sect3>
+ <title>Name Server Statistics Counters</title>
+
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="3" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.150in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="1.150in"/>
+ <colspec colname="3" colnum="3" colsep="0" colwidth="3.350in"/>
+ <tbody>
+ <row>
+ <entry colname="1">
+ <para>
+ <emphasis>Symbol</emphasis>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <emphasis>BIND8 Symbol</emphasis>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <emphasis>Description</emphasis>
+ </para>
+ </entry>
+ </row>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Requestv4</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ IPv4 requests received.
+ Note: this also counts non query requests.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Requestv6</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ IPv6 requests received.
+ Note: this also counts non query requests.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ReqEdns0</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Requests with EDNS(0) received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ReqBadEDNSVer</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Requests with unsupported EDNS version received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ReqTSIG</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Requests with TSIG received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ReqSIG0</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Requests with SIG(0) received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ReqBadSIG</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Requests with invalid (TSIG or SIG(0)) signature.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ReqTCP</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RTCP</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ TCP requests received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>AuthQryRej</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RUQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Authoritative (non recursive) queries rejected.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>RecQryRej</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RURQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Recursive queries rejected.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>XfrRej</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RUXFR</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Zone transfer requests rejected.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>UpdateRej</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RUUpd</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Dynamic update requests rejected.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Response</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>SAns</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Responses sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>RespTruncated</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Truncated responses sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>RespEDNS0</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Responses with EDNS(0) sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>RespTSIG</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Responses with TSIG sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>RespSIG0</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Responses with SIG(0) sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QrySuccess</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries resulted in a successful answer.
+ This means the query which returns a NOERROR response
+ with at least one answer RR.
+ This corresponds to the
+ <command>success</command> counter
+ of previous versions of
+ <acronym>BIND</acronym> 9.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QryAuthAns</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries resulted in authoritative answer.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QryNoauthAns</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>SNaAns</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries resulted in non authoritative answer.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QryReferral</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries resulted in referral answer.
+ This corresponds to the
+ <command>referral</command> counter
+ of previous versions of
+ <acronym>BIND</acronym> 9.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QryNxrrset</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries resulted in NOERROR responses with no data.
+ This corresponds to the
+ <command>nxrrset</command> counter
+ of previous versions of
+ <acronym>BIND</acronym> 9.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QrySERVFAIL</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>SFail</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries resulted in SERVFAIL.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QryFORMERR</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>SFErr</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries resulted in FORMERR.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QryNXDOMAIN</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>SNXD</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries resulted in NXDOMAIN.
+ This corresponds to the
+ <command>nxdomain</command> counter
+ of previous versions of
+ <acronym>BIND</acronym> 9.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QryRecursion</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RFwdQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries which caused the server
+ to perform recursion in order to find the final answer.
+ This corresponds to the
+ <command>recursion</command> counter
+ of previous versions of
+ <acronym>BIND</acronym> 9.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QryDuplicate</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RDupQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries which the server attempted to
+ recurse but discovered an existing query with the same
+ IP address, port, query ID, name, type and class
+ already being processed.
+ This corresponds to the
+ <command>duplicate</command> counter
+ of previous versions of
+ <acronym>BIND</acronym> 9.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QryDropped</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Queries for which the server
+ discovered an excessive number of existing
+ recursive queries for the same name, type and
+ class and were subsequently dropped.
+ This corresponds to the
+ <command>dropped</command> counter
+ of previous versions of
+ <acronym>BIND</acronym> 9.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>QryFailure</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Other query failures.
+ This corresponds to the
+ <command>failure</command> counter
+ of previous versions of
+ <acronym>BIND</acronym> 9.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>XfrReqDone</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Requested zone transfers completed.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>UpdateReqFwd</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Update requests forwarded.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>UpdateRespFwd</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Update responses forwarded.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>UpdateFwdFail</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Dynamic update forward failed.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>UpdateDone</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Dynamic updates completed.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>UpdateFail</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Dynamic updates failed.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>UpdateBadPrereq</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Dynamic updates rejected due to prerequisite failure.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </sect3>
+
+ <sect3>
+ <title>Zone Maintenance Statistics Counters</title>
+
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="2" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.150in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="3.350in"/>
+ <tbody>
+ <row>
+ <entry colname="1">
+ <para>
+ <emphasis>Symbol</emphasis>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <emphasis>Description</emphasis>
+ </para>
+ </entry>
+ </row>
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>NotifyOutv4</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv4 notifies sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>NotifyOutv6</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv6 notifies sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>NotifyInv4</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv4 notifies received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>NotifyInv6</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv6 notifies received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>NotifyRej</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Incoming notifies rejected.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>SOAOutv4</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv4 SOA queries sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>SOAOutv6</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv6 SOA queries sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>AXFRReqv4</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv4 AXFR requested.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>AXFRReqv6</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv6 AXFR requested.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>IXFRReqv4</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv4 IXFR requested.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>IXFRReqv6</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ IPv6 IXFR requested.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>XfrSuccess</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Zone transfer requests succeeded.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>XfrFail</command></para>
+ </entry>
+ <entry colname="2">
+ <para>
+ Zone transfer requests failed.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </sect3>
+
+ <sect3>
+ <title>Resolver Statistics Counters</title>
+
+ <informaltable colsep="0" rowsep="0">
+ <tgroup cols="3" colsep="0" rowsep="0" tgroupstyle="4Level-table">
+ <colspec colname="1" colnum="1" colsep="0" colwidth="1.150in"/>
+ <colspec colname="2" colnum="2" colsep="0" colwidth="1.150in"/>
+ <colspec colname="3" colnum="3" colsep="0" colwidth="3.350in"/>
+ <tbody>
+ <row>
+ <entry colname="1">
+ <para>
+ <emphasis>Symbol</emphasis>
+ </para>
+ </entry>
+ <entry colname="2">
+ <para>
+ <emphasis>BIND8 Symbol</emphasis>
+ </para>
+ </entry>
+ <entry colname="3">
+ <para>
+ <emphasis>Description</emphasis>
+ </para>
+ </entry>
+ </row>
+
+
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Queryv4</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>SFwdQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ IPv4 queries sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Queryv6</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>SFwdQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ IPv6 queries sent.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Responsev4</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RR</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ IPv4 responses received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Responsev6</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RR</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ IPv6 responses received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>NXDOMAIN</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RNXD</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ NXDOMAIN received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>SERVFAIL</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RFail</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ SERVFAIL received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>FORMERR</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RFErr</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ FORMERR received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>OtherError</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RErr</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Other errors received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>EDNS0Fail</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ EDNS(0) query failures.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Mismatch</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RDupR</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Mismatch responses received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Truncated</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Truncated responses received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Lame</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>RLame</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Lame delegations received.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>Retry</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>SDupQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ Query retries performed.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>GlueFetchv4</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>SSysQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ IPv4 NS address fetches invoked.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>GlueFetchv6</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command>SSysQ</command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ IPv6 NS address fetches invoked.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>GlueFetchv4Fail</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ IPv4 NS address fetch failed.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>GlueFetchv6Fail</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ IPv6 NS address fetch failed.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ValAttempt</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ DNSSEC validation attempted.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ValOk</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ DNSSEC validation succeeded.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ValNegOk</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ DNSSEC validation on negative information succeeded.
+ </para>
+ </entry>
+ </row>
+ <row rowsep="0">
+ <entry colname="1">
+ <para><command>ValFail</command></para>
+ </entry>
+ <entry colname="2">
+ <para><command></command></para>
+ </entry>
+ <entry colname="3">
+ <para>
+ DNSSEC validation failed.
+ </para>
+ </entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ </sect3>
+
+ <sect3>
+ <title>Compatibility with <emphasis>BIND</emphasis> 8 Counters</title>
+ <para>
+ Most statistics counters that were available
+ in <command>BIND</command> 8 are also supported in
+ <command>BIND</command> 9 as shown in the above tables.
+ Here are notes about other counters that do not appear
+ in these tables.
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term><command>RFwdR,SFwdR</command></term>
+ <listitem>
+ <para>
+ These counters are not supported
+ because <command>BIND</command> 9 does not adopt
+ the notion of <emphasis>forwarding</emphasis>
+ as <command>BIND</command> 8 did.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>RAXFR</command></term>
+ <listitem>
+ <para>
+ This counter is accessible in the Incoming Queries section.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>RIQ</command></term>
+ <listitem>
+ <para>
+ This counter is accessible in the Incoming Requests section.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>ROpts</command></term>
+ <listitem>
+ <para>
+ This counter is not supported
+ because <command>BIND</command> 9 does not care
+ about IP options in the first place.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><command>SErr</command></term>
+ <listitem>
+ <para>
+ This counter could be implemented, but is not yet
+ supported.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </sect3>
+ </sect2>
+ </sect1>
+
+ </chapter>
+ <chapter id="Bv9ARM.ch07">
+ <title><acronym>BIND</acronym> 9 Security Considerations</title>
+ <sect1 id="Access_Control_Lists">
+ <title>Access Control Lists</title>
+ <para>
+ Access Control Lists (ACLs), are address match lists that
+ you can set up and nickname for future use in <command>allow-notify</command>,
+ <command>allow-query</command>, <command>allow-query-on</command>,
+ <command>allow-recursion</command>, <command>allow-recursion-on</command>,
+ <command>blackhole</command>, <command>allow-transfer</command>,
+ etc.
+ </para>
+ <para>
+ Using ACLs allows you to have finer control over who can access
+ your name server, without cluttering up your config files with huge
+ lists of IP addresses.
+ </para>
+ <para>
+ It is a <emphasis>good idea</emphasis> to use ACLs, and to
+ control access to your server. Limiting access to your server by
+ outside parties can help prevent spoofing and denial of service (DoS) attacks against
+ your server.
+ </para>
+ <para>
+ Here is an example of how to properly apply ACLs:
+ </para>
+
+<programlisting>
+// 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;
+};
+
+// 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 {
+ ...
+ ...
+ allow-query { our-nets; };
+ allow-recursion { our-nets; };
+ ...
+ blackhole { bogusnets; };
+ ...
+};
+
+zone "example.com" {
+ type master;
+ file "m/example.com";
+ allow-query { any; };
+};
+</programlisting>
+
+ <para>
+ This allows recursive queries of the server from the outside
+ unless recursion has been previously disabled.
+ </para>
+ <para>
+ For more information on how to use ACLs to protect your server,
+ see the <emphasis>AUSCERT</emphasis> advisory at:
+ </para>
+ <para>
+ <ulink url="ftp://ftp.auscert.org.au/pub/auscert/advisory/AL-1999.004.dns_dos"
+ >ftp://ftp.auscert.org.au/pub/auscert/advisory/AL-1999.004.dns_dos</ulink>
+ </para>
+ </sect1>
+ <sect1>
+ <title><command>Chroot</command> and <command>Setuid</command></title>
+ <para>
+ On UNIX servers, it is possible to run <acronym>BIND</acronym> in a <emphasis>chrooted</emphasis> environment
+ (using the <command>chroot()</command> function) by specifying the "<option>-t</option>"
+ option. This can help improve system security by placing <acronym>BIND</acronym> in
+ a "sandbox", which will limit the damage done if a server is
+ compromised.
+ </para>
+ <para>
+ Another useful feature in the UNIX version of <acronym>BIND</acronym> is the
+ ability to run the daemon as an unprivileged user ( <option>-u</option> <replaceable>user</replaceable> ).
+ We suggest running as an unprivileged user when using the <command>chroot</command> feature.
+ </para>
+ <para>
+ Here is an example command line to load <acronym>BIND</acronym> in a <command>chroot</command> sandbox,
+ <command>/var/named</command>, and to run <command>named</command> <command>setuid</command> to
+ user 202:
+ </para>
+ <para>
+ <userinput>/usr/local/bin/named -u 202 -t /var/named</userinput>
+ </para>
+
+ <sect2>
+ <title>The <command>chroot</command> Environment</title>
+
+ <para>
+ In order for a <command>chroot</command> environment
+ to
+ work properly in a particular directory
+ (for example, <filename>/var/named</filename>),
+ you will need to set up an environment that includes everything
+ <acronym>BIND</acronym> needs to run.
+ From <acronym>BIND</acronym>'s point of view, <filename>/var/named</filename> is
+ the root of the filesystem. You will need to adjust the values of
+ options like
+ like <command>directory</command> and <command>pid-file</command> to account
+ for this.
+ </para>
+ <para>
+ Unlike with earlier versions of BIND, you typically will
+ <emphasis>not</emphasis> need to compile <command>named</command>
+ statically nor install shared libraries under the new root.
+ However, depending on your operating system, you may need
+ to set up things like
+ <filename>/dev/zero</filename>,
+ <filename>/dev/random</filename>,
+ <filename>/dev/log</filename>, and
+ <filename>/etc/localtime</filename>.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Using the <command>setuid</command> Function</title>
+
+ <para>
+ Prior to running the <command>named</command> daemon,
+ use
+ the <command>touch</command> utility (to change file
+ access and
+ modification times) or the <command>chown</command>
+ utility (to
+ set the user id and/or group id) on files
+ to which you want <acronym>BIND</acronym>
+ to write.
+ </para>
+ <note>
+ Note that if the <command>named</command> daemon is running as an
+ unprivileged user, it will not be able to bind to new restricted
+ ports if the server is reloaded.
+ </note>
+ </sect2>
+ </sect1>
+
+ <sect1 id="dynamic_update_security">
+ <title>Dynamic Update Security</title>
+
+ <para>
+ Access to the dynamic
+ update facility should be strictly limited. In earlier versions of
+ <acronym>BIND</acronym>, the only way to do this was
+ based on the IP
+ address of the host requesting the update, by listing an IP address
+ or
+ network prefix in the <command>allow-update</command>
+ zone option.
+ This method is insecure since the source address of the update UDP
+ packet
+ is easily forged. Also note that if the IP addresses allowed by the
+ <command>allow-update</command> option include the
+ address of a slave
+ server which performs forwarding of dynamic updates, the master can
+ be
+ trivially attacked by sending the update to the slave, which will
+ forward it to the master with its own source IP address causing the
+ master to approve it without question.
+ </para>
+
+ <para>
+ For these reasons, we strongly recommend that updates be
+ cryptographically authenticated by means of transaction signatures
+ (TSIG). That is, the <command>allow-update</command>
+ option should
+ list only TSIG key names, not IP addresses or network
+ prefixes. Alternatively, the new <command>update-policy</command>
+ option can be used.
+ </para>
+
+ <para>
+ Some sites choose to keep all dynamically-updated DNS data
+ in a subdomain and delegate that subdomain to a separate zone. This
+ way, the top-level zone containing critical data such as the IP
+ addresses
+ of public web and mail servers need not allow dynamic update at
+ all.
+ </para>
+
+ </sect1>
+ </chapter>
+
+ <chapter id="Bv9ARM.ch08">
+ <title>Troubleshooting</title>
+ <sect1>
+ <title>Common Problems</title>
+ <sect2>
+ <title>It's not working; how can I figure out what's wrong?</title>
+
+ <para>
+ The best solution to solving installation and
+ configuration issues is to take preventative measures by setting
+ up logging files beforehand. The log files provide a
+ source of hints and information that can be used to figure out
+ what went wrong and how to fix the problem.
+ </para>
+
+ </sect2>
+ </sect1>
+ <sect1>
+ <title>Incrementing and Changing the Serial Number</title>
+
+ <para>
+ Zone serial numbers are just numbers &mdash; they aren't
+ date related. A lot of people set them to a number that
+ represents a date, usually of the form YYYYMMDDRR.
+ Occasionally they will make a mistake and set them to a
+ "date in the future" then try to correct them by setting
+ them to the "current date". This causes problems because
+ serial numbers are used to indicate that a zone has been
+ updated. If the serial number on the slave server is
+ lower than the serial number on the master, the slave
+ server will attempt to update its copy of the zone.
+ </para>
+
+ <para>
+ Setting the serial number to a lower number on the master
+ server than the slave server means that the slave will not perform
+ updates to its copy of the zone.
+ </para>
+
+ <para>
+ The solution to this is to add 2147483647 (2^31-1) to the
+ number, reload the zone and make sure all slaves have updated to
+ the new zone serial number, then reset the number to what you want
+ it to be, and reload the zone again.
+ </para>
+
+ </sect1>
+ <sect1>
+ <title>Where Can I Get Help?</title>
+
+ <para>
+ The Internet Systems Consortium
+ (<acronym>ISC</acronym>) offers a wide range
+ of support and service agreements for <acronym>BIND</acronym> and <acronym>DHCP</acronym> servers. Four
+ levels of premium support are available and each level includes
+ support for all <acronym>ISC</acronym> programs,
+ significant discounts on products
+ and training, and a recognized priority on bug fixes and
+ non-funded feature requests. In addition, <acronym>ISC</acronym> offers a standard
+ support agreement package which includes services ranging from bug
+ fix announcements to remote support. It also includes training in
+ <acronym>BIND</acronym> and <acronym>DHCP</acronym>.
+ </para>
+
+ <para>
+ To discuss arrangements for support, contact
+ <ulink url="mailto:info@isc.org">info@isc.org</ulink> or visit the
+ <acronym>ISC</acronym> web page at
+ <ulink url="http://www.isc.org/services/support/"
+ >http://www.isc.org/services/support/</ulink>
+ to read more.
+ </para>
+ </sect1>
+ </chapter>
+ <appendix id="Bv9ARM.ch09">
+ <title>Appendices</title>
+ <sect1>
+ <title>Acknowledgments</title>
+ <sect2 id="historical_dns_information">
+ <title>A Brief History of the <acronym>DNS</acronym> and <acronym>BIND</acronym></title>
+
+ <para>
+ Although the "official" beginning of the Domain Name
+ System occurred in 1984 with the publication of RFC 920, the
+ core of the new system was described in 1983 in RFCs 882 and
+ 883. From 1984 to 1987, the ARPAnet (the precursor to today's
+ Internet) became a testbed of experimentation for developing the
+ new naming/addressing scheme in a rapidly expanding,
+ operational network environment. New RFCs were written and
+ published in 1987 that modified the original documents to
+ incorporate improvements based on the working model. RFC 1034,
+ "Domain Names-Concepts and Facilities", and RFC 1035, "Domain
+ Names-Implementation and Specification" were published and
+ became the standards upon which all <acronym>DNS</acronym> implementations are
+ built.
+ </para>
+
+ <para>
+ The first working domain name server, called "Jeeves", was
+ written in 1983-84 by Paul Mockapetris for operation on DEC
+ Tops-20
+ machines located at the University of Southern California's
+ Information
+ Sciences Institute (USC-ISI) and SRI International's Network
+ Information
+ Center (SRI-NIC). A <acronym>DNS</acronym> server for
+ Unix machines, the Berkeley Internet
+ Name Domain (<acronym>BIND</acronym>) package, was
+ written soon after by a group of
+ graduate students at the University of California at Berkeley
+ under
+ a grant from the US Defense Advanced Research Projects
+ Administration
+ (DARPA).
+ </para>
+ <para>
+ Versions of <acronym>BIND</acronym> through
+ 4.8.3 were maintained by the Computer
+ Systems Research Group (CSRG) at UC Berkeley. Douglas Terry, Mark
+ Painter, David Riggle and Songnian Zhou made up the initial <acronym>BIND</acronym>
+ project team. After that, additional work on the software package
+ was done by Ralph Campbell. Kevin Dunlap, a Digital Equipment
+ Corporation
+ employee on loan to the CSRG, worked on <acronym>BIND</acronym> for 2 years, from 1985
+ to 1987. Many other people also contributed to <acronym>BIND</acronym> development
+ during that time: Doug Kingston, Craig Partridge, Smoot
+ Carl-Mitchell,
+ Mike Muuss, Jim Bloom and Mike Schwartz. <acronym>BIND</acronym> maintenance was subsequently
+ handled by Mike Karels and &#216;ivind Kure.
+ </para>
+ <para>
+ <acronym>BIND</acronym> versions 4.9 and 4.9.1 were
+ released by Digital Equipment
+ Corporation (now Compaq Computer Corporation). Paul Vixie, then
+ a DEC employee, became <acronym>BIND</acronym>'s
+ primary caretaker. He was assisted
+ by Phil Almquist, Robert Elz, Alan Barrett, Paul Albitz, Bryan
+ Beecher, Andrew
+ Partan, Andy Cherenson, Tom Limoncelli, Berthold Paffrath, Fuat
+ Baran, Anant Kumar, Art Harkin, Win Treese, Don Lewis, Christophe
+ Wolfhugel, and others.
+ </para>
+ <para>
+ In 1994, <acronym>BIND</acronym> version 4.9.2 was sponsored by
+ Vixie Enterprises. Paul
+ Vixie became <acronym>BIND</acronym>'s principal
+ architect/programmer.
+ </para>
+ <para>
+ <acronym>BIND</acronym> versions from 4.9.3 onward
+ have been developed and maintained
+ by the Internet Systems Consortium and its predecessor,
+ the Internet Software Consortium, with support being provided
+ by ISC's sponsors.
+ </para>
+ <para>
+ As co-architects/programmers, Bob Halley and
+ Paul Vixie released the first production-ready version of
+ <acronym>BIND</acronym> version 8 in May 1997.
+ </para>
+ <para>
+ BIND version 9 was released in September 2000 and is a
+ major rewrite of nearly all aspects of the underlying
+ BIND architecture.
+ </para>
+ <para>
+ BIND version 4 is officially deprecated and BIND version
+ 8 development is considered maintenance-only in favor
+ of BIND version 9. No additional development is done
+ on BIND version 4 or BIND version 8 other than for
+ security-related patches.
+ </para>
+ <para>
+ <acronym>BIND</acronym> development work is made
+ possible today by the sponsorship
+ of several corporations, and by the tireless work efforts of
+ numerous individuals.
+ </para>
+ </sect2>
+ </sect1>
+ <sect1>
+ <title>General <acronym>DNS</acronym> Reference Information</title>
+ <sect2 id="ipv6addresses">
+ <title>IPv6 addresses (AAAA)</title>
+ <para>
+ IPv6 addresses are 128-bit identifiers for interfaces and
+ sets of interfaces which were introduced in the <acronym>DNS</acronym> to facilitate
+ scalable Internet routing. There are three types of addresses: <emphasis>Unicast</emphasis>,
+ an identifier for a single interface;
+ <emphasis>Anycast</emphasis>,
+ an identifier for a set of interfaces; and <emphasis>Multicast</emphasis>,
+ an identifier for a set of interfaces. Here we describe the global
+ Unicast address scheme. For more information, see RFC 3587,
+ "Global Unicast Address Format."
+ </para>
+ <para>
+ IPv6 unicast addresses consist of a
+ <emphasis>global routing prefix</emphasis>, a
+ <emphasis>subnet identifier</emphasis>, and an
+ <emphasis>interface identifier</emphasis>.
+ </para>
+ <para>
+ The global routing prefix is provided by the
+ upstream provider or ISP, and (roughly) corresponds to the
+ IPv4 <emphasis>network</emphasis> section
+ of the address range.
+
+ The subnet identifier is for local subnetting, much the
+ same as subnetting an
+ IPv4 /16 network into /24 subnets.
+
+ The interface identifier is the address of an individual
+ interface on a given network; in IPv6, addresses belong to
+ interfaces rather than to machines.
+ </para>
+ <para>
+ The subnetting capability of IPv6 is much more flexible than
+ that of IPv4: subnetting can be carried out on bit boundaries,
+ in much the same way as Classless InterDomain Routing
+ (CIDR), and the DNS PTR representation ("nibble" format)
+ makes setting up reverse zones easier.
+ </para>
+ <para>
+ The Interface Identifier must be unique on the local link,
+ and is usually generated automatically by the IPv6
+ implementation, although it is usually possible to
+ override the default setting if necessary. A typical IPv6
+ address might look like:
+ <command>2001:db8:201:9:a00:20ff:fe81:2b32</command>
+ </para>
+ <para>
+ IPv6 address specifications often contain long strings
+ of zeros, so the architects have included a shorthand for
+ specifying
+ them. The double colon (`::') indicates the longest possible
+ string
+ of zeros that can fit, and can be used only once in an address.
+ </para>
+ </sect2>
+ </sect1>
+ <sect1 id="bibliography">
+ <title>Bibliography (and Suggested Reading)</title>
+ <sect2 id="rfcs">
+ <title>Request for Comments (RFCs)</title>
+ <para>
+ Specification documents for the Internet protocol suite, including
+ the <acronym>DNS</acronym>, are published as part of
+ the Request for Comments (RFCs)
+ series of technical notes. The standards themselves are defined
+ by the Internet Engineering Task Force (IETF) and the Internet
+ Engineering Steering Group (IESG). RFCs can be obtained online via FTP at:
+ </para>
+ <para>
+ <ulink url="ftp://www.isi.edu/in-notes/">
+ ftp://www.isi.edu/in-notes/RFC<replaceable>xxxx</replaceable>.txt
+ </ulink>
+ </para>
+ <para>
+ (where <replaceable>xxxx</replaceable> is
+ the number of the RFC). RFCs are also available via the Web at:
+ </para>
+ <para>
+ <ulink url="http://www.ietf.org/rfc/"
+ >http://www.ietf.org/rfc/</ulink>.
+ </para>
+ <bibliography>
+ <bibliodiv>
+ <!-- one of (BIBLIOENTRY BIBLIOMIXED) -->
+ <title>Standards</title>
+ <biblioentry>
+ <abbrev>RFC974</abbrev>
+ <author>
+ <surname>Partridge</surname>
+ <firstname>C.</firstname>
+ </author>
+ <title>Mail Routing and the Domain System</title>
+ <pubdate>January 1986</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1034</abbrev>
+ <author>
+ <surname>Mockapetris</surname>
+ <firstname>P.V.</firstname>
+ </author>
+ <title>Domain Names &mdash; Concepts and Facilities</title>
+ <pubdate>November 1987</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1035</abbrev>
+ <author>
+ <surname>Mockapetris</surname>
+ <firstname>P. V.</firstname>
+ </author> <title>Domain Names &mdash; Implementation and
+ Specification</title>
+ <pubdate>November 1987</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ <bibliodiv id="proposed_standards" xreflabel="Proposed Standards">
+
+ <title>Proposed Standards</title>
+ <!-- one of (BIBLIOENTRY BIBLIOMIXED) -->
+ <biblioentry>
+ <abbrev>RFC2181</abbrev>
+ <author>
+ <surname>Elz</surname>
+ <firstname>R., R. Bush</firstname>
+ </author>
+ <title>Clarifications to the <acronym>DNS</acronym>
+ Specification</title>
+ <pubdate>July 1997</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2308</abbrev>
+ <author>
+ <surname>Andrews</surname>
+ <firstname>M.</firstname>
+ </author>
+ <title>Negative Caching of <acronym>DNS</acronym>
+ Queries</title>
+ <pubdate>March 1998</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1995</abbrev>
+ <author>
+ <surname>Ohta</surname>
+ <firstname>M.</firstname>
+ </author>
+ <title>Incremental Zone Transfer in <acronym>DNS</acronym></title>
+ <pubdate>August 1996</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1996</abbrev>
+ <author>
+ <surname>Vixie</surname>
+ <firstname>P.</firstname>
+ </author>
+ <title>A Mechanism for Prompt Notification of Zone Changes</title>
+ <pubdate>August 1996</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2136</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Vixie</surname>
+ <firstname>P.</firstname>
+ </author>
+ <author>
+ <firstname>S.</firstname>
+ <surname>Thomson</surname>
+ </author>
+ <author>
+ <firstname>Y.</firstname>
+ <surname>Rekhter</surname>
+ </author>
+ <author>
+ <firstname>J.</firstname>
+ <surname>Bound</surname>
+ </author>
+ </authorgroup>
+ <title>Dynamic Updates in the Domain Name System</title>
+ <pubdate>April 1997</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2671</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>P.</firstname>
+ <surname>Vixie</surname>
+ </author>
+ </authorgroup>
+ <title>Extension Mechanisms for DNS (EDNS0)</title>
+ <pubdate>August 1997</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2672</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>M.</firstname>
+ <surname>Crawford</surname>
+ </author>
+ </authorgroup>
+ <title>Non-Terminal DNS Name Redirection</title>
+ <pubdate>August 1999</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2845</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Vixie</surname>
+ <firstname>P.</firstname>
+ </author>
+ <author>
+ <firstname>O.</firstname>
+ <surname>Gudmundsson</surname>
+ </author>
+ <author>
+ <firstname>D.</firstname>
+ <surname>Eastlake</surname>
+ <lineage>3rd</lineage>
+ </author>
+ <author>
+ <firstname>B.</firstname>
+ <surname>Wellington</surname>
+ </author>
+ </authorgroup>
+ <title>Secret Key Transaction Authentication for <acronym>DNS</acronym> (TSIG)</title>
+ <pubdate>May 2000</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2930</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>D.</firstname>
+ <surname>Eastlake</surname>
+ <lineage>3rd</lineage>
+ </author>
+ </authorgroup>
+ <title>Secret Key Establishment for DNS (TKEY RR)</title>
+ <pubdate>September 2000</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2931</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>D.</firstname>
+ <surname>Eastlake</surname>
+ <lineage>3rd</lineage>
+ </author>
+ </authorgroup>
+ <title>DNS Request and Transaction Signatures (SIG(0)s)</title>
+ <pubdate>September 2000</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3007</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>B.</firstname>
+ <surname>Wellington</surname>
+ </author>
+ </authorgroup>
+ <title>Secure Domain Name System (DNS) Dynamic Update</title>
+ <pubdate>November 2000</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3645</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>S.</firstname>
+ <surname>Kwan</surname>
+ </author>
+ <author>
+ <firstname>P.</firstname>
+ <surname>Garg</surname>
+ </author>
+ <author>
+ <firstname>J.</firstname>
+ <surname>Gilroy</surname>
+ </author>
+ <author>
+ <firstname>L.</firstname>
+ <surname>Esibov</surname>
+ </author>
+ <author>
+ <firstname>J.</firstname>
+ <surname>Westhead</surname>
+ </author>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Hall</surname>
+ </author>
+ </authorgroup>
+ <title>Generic Security Service Algorithm for Secret
+ Key Transaction Authentication for DNS
+ (GSS-TSIG)</title>
+ <pubdate>October 2003</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ <bibliodiv>
+ <title><acronym>DNS</acronym> Security Proposed Standards</title>
+ <biblioentry>
+ <abbrev>RFC3225</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>D.</firstname>
+ <surname>Conrad</surname>
+ </author>
+ </authorgroup>
+ <title>Indicating Resolver Support of DNSSEC</title>
+ <pubdate>December 2001</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3833</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>D.</firstname>
+ <surname>Atkins</surname>
+ </author>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Austein</surname>
+ </author>
+ </authorgroup>
+ <title>Threat Analysis of the Domain Name System (DNS)</title>
+ <pubdate>August 2004</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC4033</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Arends</surname>
+ </author>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Austein</surname>
+ </author>
+ <author>
+ <firstname>M.</firstname>
+ <surname>Larson</surname>
+ </author>
+ <author>
+ <firstname>D.</firstname>
+ <surname>Massey</surname>
+ </author>
+ <author>
+ <firstname>S.</firstname>
+ <surname>Rose</surname>
+ </author>
+ </authorgroup>
+ <title>DNS Security Introduction and Requirements</title>
+ <pubdate>March 2005</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC4034</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Arends</surname>
+ </author>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Austein</surname>
+ </author>
+ <author>
+ <firstname>M.</firstname>
+ <surname>Larson</surname>
+ </author>
+ <author>
+ <firstname>D.</firstname>
+ <surname>Massey</surname>
+ </author>
+ <author>
+ <firstname>S.</firstname>
+ <surname>Rose</surname>
+ </author>
+ </authorgroup>
+ <title>Resource Records for the DNS Security Extensions</title>
+ <pubdate>March 2005</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC4035</abbrev>
+ <authorgroup>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Arends</surname>
+ </author>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Austein</surname>
+ </author>
+ <author>
+ <firstname>M.</firstname>
+ <surname>Larson</surname>
+ </author>
+ <author>
+ <firstname>D.</firstname>
+ <surname>Massey</surname>
+ </author>
+ <author>
+ <firstname>S.</firstname>
+ <surname>Rose</surname>
+ </author>
+ </authorgroup>
+ <title>Protocol Modifications for the DNS
+ Security Extensions</title>
+ <pubdate>March 2005</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ <bibliodiv>
+ <title>Other Important RFCs About <acronym>DNS</acronym>
+ Implementation</title>
+ <biblioentry>
+ <abbrev>RFC1535</abbrev>
+ <author>
+ <surname>Gavron</surname>
+ <firstname>E.</firstname>
+ </author>
+ <title>A Security Problem and Proposed Correction With Widely
+ Deployed <acronym>DNS</acronym> Software.</title>
+ <pubdate>October 1993</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1536</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Kumar</surname>
+ <firstname>A.</firstname>
+ </author>
+ <author>
+ <firstname>J.</firstname>
+ <surname>Postel</surname>
+ </author>
+ <author>
+ <firstname>C.</firstname>
+ <surname>Neuman</surname>
+ </author>
+ <author>
+ <firstname>P.</firstname>
+ <surname>Danzig</surname>
+ </author>
+ <author>
+ <firstname>S.</firstname>
+ <surname>Miller</surname>
+ </author>
+ </authorgroup>
+ <title>Common <acronym>DNS</acronym> Implementation
+ Errors and Suggested Fixes</title>
+ <pubdate>October 1993</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1982</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Elz</surname>
+ <firstname>R.</firstname>
+ </author>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Bush</surname>
+ </author>
+ </authorgroup>
+ <title>Serial Number Arithmetic</title>
+ <pubdate>August 1996</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC4074</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Morishita</surname>
+ <firstname>Y.</firstname>
+ </author>
+ <author>
+ <firstname>T.</firstname>
+ <surname>Jinmei</surname>
+ </author>
+ </authorgroup>
+ <title>Common Misbehaviour Against <acronym>DNS</acronym>
+ Queries for IPv6 Addresses</title>
+ <pubdate>May 2005</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ <bibliodiv>
+ <title>Resource Record Types</title>
+ <biblioentry>
+ <abbrev>RFC1183</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Everhart</surname>
+ <firstname>C.F.</firstname>
+ </author>
+ <author>
+ <firstname>L. A.</firstname>
+ <surname>Mamakos</surname>
+ </author>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Ullmann</surname>
+ </author>
+ <author>
+ <firstname>P.</firstname>
+ <surname>Mockapetris</surname>
+ </author>
+ </authorgroup>
+ <title>New <acronym>DNS</acronym> RR Definitions</title>
+ <pubdate>October 1990</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1706</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Manning</surname>
+ <firstname>B.</firstname>
+ </author>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Colella</surname>
+ </author>
+ </authorgroup>
+ <title><acronym>DNS</acronym> NSAP Resource Records</title>
+ <pubdate>October 1994</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2168</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Daniel</surname>
+ <firstname>R.</firstname>
+ </author>
+ <author>
+ <firstname>M.</firstname>
+ <surname>Mealling</surname>
+ </author>
+ </authorgroup>
+ <title>Resolution of Uniform Resource Identifiers using
+ the Domain Name System</title>
+ <pubdate>June 1997</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1876</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Davis</surname>
+ <firstname>C.</firstname>
+ </author>
+ <author>
+ <firstname>P.</firstname>
+ <surname>Vixie</surname>
+ </author>
+ <author>
+ <firstname>T.</firstname>
+ <firstname>Goodwin</firstname>
+ </author>
+ <author>
+ <firstname>I.</firstname>
+ <surname>Dickinson</surname>
+ </author>
+ </authorgroup>
+ <title>A Means for Expressing Location Information in the
+ Domain
+ Name System</title>
+ <pubdate>January 1996</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2052</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Gulbrandsen</surname>
+ <firstname>A.</firstname>
+ </author>
+ <author>
+ <firstname>P.</firstname>
+ <surname>Vixie</surname>
+ </author>
+ </authorgroup>
+ <title>A <acronym>DNS</acronym> RR for Specifying the
+ Location of
+ Services.</title>
+ <pubdate>October 1996</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2163</abbrev>
+ <author>
+ <surname>Allocchio</surname>
+ <firstname>A.</firstname>
+ </author>
+ <title>Using the Internet <acronym>DNS</acronym> to
+ Distribute MIXER
+ Conformant Global Address Mapping</title>
+ <pubdate>January 1998</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2230</abbrev>
+ <author>
+ <surname>Atkinson</surname>
+ <firstname>R.</firstname>
+ </author>
+ <title>Key Exchange Delegation Record for the <acronym>DNS</acronym></title>
+ <pubdate>October 1997</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2536</abbrev>
+ <author>
+ <surname>Eastlake</surname>
+ <firstname>D.</firstname>
+ <lineage>3rd</lineage>
+ </author>
+ <title>DSA KEYs and SIGs in the Domain Name System (DNS)</title>
+ <pubdate>March 1999</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2537</abbrev>
+ <author>
+ <surname>Eastlake</surname>
+ <firstname>D.</firstname>
+ <lineage>3rd</lineage>
+ </author>
+ <title>RSA/MD5 KEYs and SIGs in the Domain Name System (DNS)</title>
+ <pubdate>March 1999</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2538</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Eastlake</surname>
+ <firstname>D.</firstname>
+ <lineage>3rd</lineage>
+ </author>
+ <author>
+ <surname>Gudmundsson</surname>
+ <firstname>O.</firstname>
+ </author>
+ </authorgroup>
+ <title>Storing Certificates in the Domain Name System (DNS)</title>
+ <pubdate>March 1999</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2539</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Eastlake</surname>
+ <firstname>D.</firstname>
+ <lineage>3rd</lineage>
+ </author>
+ </authorgroup>
+ <title>Storage of Diffie-Hellman Keys in the Domain Name System (DNS)</title>
+ <pubdate>March 1999</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2540</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Eastlake</surname>
+ <firstname>D.</firstname>
+ <lineage>3rd</lineage>
+ </author>
+ </authorgroup>
+ <title>Detached Domain Name System (DNS) Information</title>
+ <pubdate>March 1999</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2782</abbrev>
+ <author>
+ <surname>Gulbrandsen</surname>
+ <firstname>A.</firstname>
+ </author>
+ <author>
+ <surname>Vixie</surname>
+ <firstname>P.</firstname>
+ </author>
+ <author>
+ <surname>Esibov</surname>
+ <firstname>L.</firstname>
+ </author>
+ <title>A DNS RR for specifying the location of services (DNS SRV)</title>
+ <pubdate>February 2000</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2915</abbrev>
+ <author>
+ <surname>Mealling</surname>
+ <firstname>M.</firstname>
+ </author>
+ <author>
+ <surname>Daniel</surname>
+ <firstname>R.</firstname>
+ </author>
+ <title>The Naming Authority Pointer (NAPTR) DNS Resource Record</title>
+ <pubdate>September 2000</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3110</abbrev>
+ <author>
+ <surname>Eastlake</surname>
+ <firstname>D.</firstname>
+ <lineage>3rd</lineage>
+ </author>
+ <title>RSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS)</title>
+ <pubdate>May 2001</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3123</abbrev>
+ <author>
+ <surname>Koch</surname>
+ <firstname>P.</firstname>
+ </author>
+ <title>A DNS RR Type for Lists of Address Prefixes (APL RR)</title>
+ <pubdate>June 2001</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3596</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Thomson</surname>
+ <firstname>S.</firstname>
+ </author>
+ <author>
+ <firstname>C.</firstname>
+ <surname>Huitema</surname>
+ </author>
+ <author>
+ <firstname>V.</firstname>
+ <surname>Ksinant</surname>
+ </author>
+ <author>
+ <firstname>M.</firstname>
+ <surname>Souissi</surname>
+ </author>
+ </authorgroup>
+ <title><acronym>DNS</acronym> Extensions to support IP
+ version 6</title>
+ <pubdate>October 2003</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3597</abbrev>
+ <author>
+ <surname>Gustafsson</surname>
+ <firstname>A.</firstname>
+ </author>
+ <title>Handling of Unknown DNS Resource Record (RR) Types</title>
+ <pubdate>September 2003</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ <bibliodiv>
+ <title><acronym>DNS</acronym> and the Internet</title>
+ <biblioentry>
+ <abbrev>RFC1101</abbrev>
+ <author>
+ <surname>Mockapetris</surname>
+ <firstname>P. V.</firstname>
+ </author>
+ <title><acronym>DNS</acronym> Encoding of Network Names
+ and Other Types</title>
+ <pubdate>April 1989</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1123</abbrev>
+ <author>
+ <surname>Braden</surname>
+ <surname>R.</surname>
+ </author>
+ <title>Requirements for Internet Hosts - Application and
+ Support</title>
+ <pubdate>October 1989</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1591</abbrev>
+ <author>
+ <surname>Postel</surname>
+ <firstname>J.</firstname>
+ </author>
+ <title>Domain Name System Structure and Delegation</title>
+ <pubdate>March 1994</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2317</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Eidnes</surname>
+ <firstname>H.</firstname>
+ </author>
+ <author>
+ <firstname>G.</firstname>
+ <surname>de Groot</surname>
+ </author>
+ <author>
+ <firstname>P.</firstname>
+ <surname>Vixie</surname>
+ </author>
+ </authorgroup>
+ <title>Classless IN-ADDR.ARPA Delegation</title>
+ <pubdate>March 1998</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2826</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Internet Architecture Board</surname>
+ </author>
+ </authorgroup>
+ <title>IAB Technical Comment on the Unique DNS Root</title>
+ <pubdate>May 2000</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2929</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Eastlake</surname>
+ <firstname>D.</firstname>
+ <lineage>3rd</lineage>
+ </author>
+ <author>
+ <surname>Brunner-Williams</surname>
+ <firstname>E.</firstname>
+ </author>
+ <author>
+ <surname>Manning</surname>
+ <firstname>B.</firstname>
+ </author>
+ </authorgroup>
+ <title>Domain Name System (DNS) IANA Considerations</title>
+ <pubdate>September 2000</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ <bibliodiv>
+ <title><acronym>DNS</acronym> Operations</title>
+ <biblioentry>
+ <abbrev>RFC1033</abbrev>
+ <author>
+ <surname>Lottor</surname>
+ <firstname>M.</firstname>
+ </author>
+ <title>Domain administrators operations guide.</title>
+ <pubdate>November 1987</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1537</abbrev>
+ <author>
+ <surname>Beertema</surname>
+ <firstname>P.</firstname>
+ </author>
+ <title>Common <acronym>DNS</acronym> Data File
+ Configuration Errors</title>
+ <pubdate>October 1993</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1912</abbrev>
+ <author>
+ <surname>Barr</surname>
+ <firstname>D.</firstname>
+ </author>
+ <title>Common <acronym>DNS</acronym> Operational and
+ Configuration Errors</title>
+ <pubdate>February 1996</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2010</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Manning</surname>
+ <firstname>B.</firstname>
+ </author>
+ <author>
+ <firstname>P.</firstname>
+ <surname>Vixie</surname>
+ </author>
+ </authorgroup>
+ <title>Operational Criteria for Root Name Servers.</title>
+ <pubdate>October 1996</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2219</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Hamilton</surname>
+ <firstname>M.</firstname>
+ </author>
+ <author>
+ <firstname>R.</firstname>
+ <surname>Wright</surname>
+ </author>
+ </authorgroup>
+ <title>Use of <acronym>DNS</acronym> Aliases for
+ Network Services.</title>
+ <pubdate>October 1997</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ <bibliodiv>
+ <title>Internationalized Domain Names</title>
+ <biblioentry>
+ <abbrev>RFC2825</abbrev>
+ <authorgroup>
+ <author>
+ <surname>IAB</surname>
+ </author>
+ <author>
+ <surname>Daigle</surname>
+ <firstname>R.</firstname>
+ </author>
+ </authorgroup>
+ <title>A Tangled Web: Issues of I18N, Domain Names,
+ and the Other Internet protocols</title>
+ <pubdate>May 2000</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3490</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Faltstrom</surname>
+ <firstname>P.</firstname>
+ </author>
+ <author>
+ <surname>Hoffman</surname>
+ <firstname>P.</firstname>
+ </author>
+ <author>
+ <surname>Costello</surname>
+ <firstname>A.</firstname>
+ </author>
+ </authorgroup>
+ <title>Internationalizing Domain Names in Applications (IDNA)</title>
+ <pubdate>March 2003</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3491</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Hoffman</surname>
+ <firstname>P.</firstname>
+ </author>
+ <author>
+ <surname>Blanchet</surname>
+ <firstname>M.</firstname>
+ </author>
+ </authorgroup>
+ <title>Nameprep: A Stringprep Profile for Internationalized Domain Names</title>
+ <pubdate>March 2003</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3492</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Costello</surname>
+ <firstname>A.</firstname>
+ </author>
+ </authorgroup>
+ <title>Punycode: A Bootstring encoding of Unicode
+ for Internationalized Domain Names in
+ Applications (IDNA)</title>
+ <pubdate>March 2003</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ <bibliodiv>
+ <title>Other <acronym>DNS</acronym>-related RFCs</title>
+ <note>
+ <para>
+ Note: the following list of RFCs, although
+ <acronym>DNS</acronym>-related, are not
+ concerned with implementing software.
+ </para>
+ </note>
+ <biblioentry>
+ <abbrev>RFC1464</abbrev>
+ <author>
+ <surname>Rosenbaum</surname>
+ <firstname>R.</firstname>
+ </author>
+ <title>Using the Domain Name System To Store Arbitrary String
+ Attributes</title>
+ <pubdate>May 1993</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1713</abbrev>
+ <author>
+ <surname>Romao</surname>
+ <firstname>A.</firstname>
+ </author>
+ <title>Tools for <acronym>DNS</acronym> Debugging</title>
+ <pubdate>November 1994</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC1794</abbrev>
+ <author>
+ <surname>Brisco</surname>
+ <firstname>T.</firstname>
+ </author>
+ <title><acronym>DNS</acronym> Support for Load
+ Balancing</title>
+ <pubdate>April 1995</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2240</abbrev>
+ <author>
+ <surname>Vaughan</surname>
+ <firstname>O.</firstname>
+ </author>
+ <title>A Legal Basis for Domain Name Allocation</title>
+ <pubdate>November 1997</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2345</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Klensin</surname>
+ <firstname>J.</firstname>
+ </author>
+ <author>
+ <firstname>T.</firstname>
+ <surname>Wolf</surname>
+ </author>
+ <author>
+ <firstname>G.</firstname>
+ <surname>Oglesby</surname>
+ </author>
+ </authorgroup>
+ <title>Domain Names and Company Name Retrieval</title>
+ <pubdate>May 1998</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2352</abbrev>
+ <author>
+ <surname>Vaughan</surname>
+ <firstname>O.</firstname>
+ </author>
+ <title>A Convention For Using Legal Names as Domain Names</title>
+ <pubdate>May 1998</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3071</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Klensin</surname>
+ <firstname>J.</firstname>
+ </author>
+ </authorgroup>
+ <title>Reflections on the DNS, RFC 1591, and Categories of Domains</title>
+ <pubdate>February 2001</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3258</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Hardie</surname>
+ <firstname>T.</firstname>
+ </author>
+ </authorgroup>
+ <title>Distributing Authoritative Name Servers via
+ Shared Unicast Addresses</title>
+ <pubdate>April 2002</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3901</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Durand</surname>
+ <firstname>A.</firstname>
+ </author>
+ <author>
+ <firstname>J.</firstname>
+ <surname>Ihren</surname>
+ </author>
+ </authorgroup>
+ <title>DNS IPv6 Transport Operational Guidelines</title>
+ <pubdate>September 2004</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ <bibliodiv>
+ <title>Obsolete and Unimplemented Experimental RFC</title>
+ <biblioentry>
+ <abbrev>RFC1712</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Farrell</surname>
+ <firstname>C.</firstname>
+ </author>
+ <author>
+ <firstname>M.</firstname>
+ <surname>Schulze</surname>
+ </author>
+ <author>
+ <firstname>S.</firstname>
+ <surname>Pleitner</surname>
+ </author>
+ <author>
+ <firstname>D.</firstname>
+ <surname>Baldoni</surname>
+ </author>
+ </authorgroup>
+ <title><acronym>DNS</acronym> Encoding of Geographical
+ Location</title>
+ <pubdate>November 1994</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2673</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Crawford</surname>
+ <firstname>M.</firstname>
+ </author>
+ </authorgroup>
+ <title>Binary Labels in the Domain Name System</title>
+ <pubdate>August 1999</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2874</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Crawford</surname>
+ <firstname>M.</firstname>
+ </author>
+ <author>
+ <surname>Huitema</surname>
+ <firstname>C.</firstname>
+ </author>
+ </authorgroup>
+ <title>DNS Extensions to Support IPv6 Address Aggregation
+ and Renumbering</title>
+ <pubdate>July 2000</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ <bibliodiv>
+ <title>Obsoleted DNS Security RFCs</title>
+ <note>
+ <para>
+ Most of these have been consolidated into RFC4033,
+ RFC4034 and RFC4035 which collectively describe DNSSECbis.
+ </para>
+ </note>
+ <biblioentry>
+ <abbrev>RFC2065</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Eastlake</surname>
+ <lineage>3rd</lineage>
+ <firstname>D.</firstname>
+ </author>
+ <author>
+ <firstname>C.</firstname>
+ <surname>Kaufman</surname>
+ </author>
+ </authorgroup>
+ <title>Domain Name System Security Extensions</title>
+ <pubdate>January 1997</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2137</abbrev>
+ <author>
+ <surname>Eastlake</surname>
+ <lineage>3rd</lineage>
+ <firstname>D.</firstname>
+ </author>
+ <title>Secure Domain Name System Dynamic Update</title>
+ <pubdate>April 1997</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC2535</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Eastlake</surname>
+ <lineage>3rd</lineage>
+ <firstname>D.</firstname>
+ </author>
+ </authorgroup>
+ <title>Domain Name System Security Extensions</title>
+ <pubdate>March 1999</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3008</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Wellington</surname>
+ <firstname>B.</firstname>
+ </author>
+ </authorgroup>
+ <title>Domain Name System Security (DNSSEC)
+ Signing Authority</title>
+ <pubdate>November 2000</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3090</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Lewis</surname>
+ <firstname>E.</firstname>
+ </author>
+ </authorgroup>
+ <title>DNS Security Extension Clarification on Zone Status</title>
+ <pubdate>March 2001</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3445</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Massey</surname>
+ <firstname>D.</firstname>
+ </author>
+ <author>
+ <surname>Rose</surname>
+ <firstname>S.</firstname>
+ </author>
+ </authorgroup>
+ <title>Limiting the Scope of the KEY Resource Record (RR)</title>
+ <pubdate>December 2002</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3655</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Wellington</surname>
+ <firstname>B.</firstname>
+ </author>
+ <author>
+ <surname>Gudmundsson</surname>
+ <firstname>O.</firstname>
+ </author>
+ </authorgroup>
+ <title>Redefinition of DNS Authenticated Data (AD) bit</title>
+ <pubdate>November 2003</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3658</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Gudmundsson</surname>
+ <firstname>O.</firstname>
+ </author>
+ </authorgroup>
+ <title>Delegation Signer (DS) Resource Record (RR)</title>
+ <pubdate>December 2003</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3755</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Weiler</surname>
+ <firstname>S.</firstname>
+ </author>
+ </authorgroup>
+ <title>Legacy Resolver Compatibility for Delegation Signer (DS)</title>
+ <pubdate>May 2004</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3757</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Kolkman</surname>
+ <firstname>O.</firstname>
+ </author>
+ <author>
+ <surname>Schlyter</surname>
+ <firstname>J.</firstname>
+ </author>
+ <author>
+ <surname>Lewis</surname>
+ <firstname>E.</firstname>
+ </author>
+ </authorgroup>
+ <title>Domain Name System KEY (DNSKEY) Resource Record
+ (RR) Secure Entry Point (SEP) Flag</title>
+ <pubdate>April 2004</pubdate>
+ </biblioentry>
+ <biblioentry>
+ <abbrev>RFC3845</abbrev>
+ <authorgroup>
+ <author>
+ <surname>Schlyter</surname>
+ <firstname>J.</firstname>
+ </author>
+ </authorgroup>
+ <title>DNS Security (DNSSEC) NextSECure (NSEC) RDATA Format</title>
+ <pubdate>August 2004</pubdate>
+ </biblioentry>
+ </bibliodiv>
+ </bibliography>
+ </sect2>
+ <sect2 id="internet_drafts">
+ <title>Internet Drafts</title>
+ <para>
+ Internet Drafts (IDs) are rough-draft working documents of
+ the Internet Engineering Task Force. They are, in essence, RFCs
+ in the preliminary stages of development. Implementors are
+ cautioned not
+ to regard IDs as archival, and they should not be quoted or cited
+ in any formal documents unless accompanied by the disclaimer that
+ they are "works in progress." IDs have a lifespan of six months
+ after which they are deleted unless updated by their authors.
+ </para>
+ </sect2>
+ <sect2>
+ <title>Other Documents About <acronym>BIND</acronym></title>
+ <para/>
+ <bibliography>
+ <biblioentry>
+ <authorgroup>
+ <author>
+ <surname>Albitz</surname>
+ <firstname>Paul</firstname>
+ </author>
+ <author>
+ <firstname>Cricket</firstname>
+ <surname>Liu</surname>
+ </author>
+ </authorgroup>
+ <title><acronym>DNS</acronym> and <acronym>BIND</acronym></title>
+ <copyright>
+ <year>1998</year>
+ <holder>Sebastopol, CA: O'Reilly and Associates</holder>
+ </copyright>
+ </biblioentry>
+ </bibliography>
+ </sect2>
+ </sect1>
+ </appendix>
+
+ <reference id="Bv9ARM.ch10">
+ <title>Manual pages</title>
+ <xi:include href="../../bin/dig/dig.docbook"/>
+ <xi:include href="../../bin/dig/host.docbook"/>
+ <xi:include href="../../bin/dnssec/dnssec-dsfromkey.docbook"/>
+ <xi:include href="../../bin/dnssec/dnssec-keyfromlabel.docbook"/>
+ <xi:include href="../../bin/dnssec/dnssec-keygen.docbook"/>
+ <xi:include href="../../bin/dnssec/dnssec-signzone.docbook"/>
+ <xi:include href="../../bin/check/named-checkconf.docbook"/>
+ <xi:include href="../../bin/check/named-checkzone.docbook"/>
+ <xi:include href="../../bin/named/named.docbook"/>
+ <!-- named.conf.docbook and others? -->
+ <xi:include href="../../bin/nsupdate/nsupdate.docbook"/>
+ <xi:include href="../../bin/rndc/rndc.docbook"/>
+ <xi:include href="../../bin/rndc/rndc.conf.docbook"/>
+ <xi:include href="../../bin/rndc/rndc-confgen.docbook"/>
+ </reference>
+
+ </book>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+ -->
diff --git a/doc/arm/Bv9ARM.ch01.html b/doc/arm/Bv9ARM.ch01.html
new file mode 100644
index 0000000..0377123
--- /dev/null
+++ b/doc/arm/Bv9ARM.ch01.html
@@ -0,0 +1,562 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.ch01.html,v 1.43 2008/09/25 06:24:40 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 1. Introduction</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="prev" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="next" href="Bv9ARM.ch02.html" title="Chapter 2. BIND Resource Requirements">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">Chapter 1. Introduction</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.html">Prev</a> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="Bv9ARM.ch02.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="Bv9ARM.ch01"></a>Chapter 1. Introduction</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch01.html#id2563405">Scope of Document</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch01.html#id2564385">Organization of This Document</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch01.html#id2564524">Conventions Used in This Document</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch01.html#id2564637">The Domain Name System (<acronym class="acronym">DNS</acronym>)</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2564659">DNS Fundamentals</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2564693">Domains and Domain Names</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2564845">Zones</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2567243">Authoritative Name Servers</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2567416">Caching Name Servers</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2567546">Name Servers in Multiple Roles</a></span></dt>
+</dl></dd>
+</dl>
+</div>
+<p>
+ The Internet Domain Name System (<acronym class="acronym">DNS</acronym>)
+ consists of the syntax
+ to specify the names of entities in the Internet in a hierarchical
+ manner, the rules used for delegating authority over names, and the
+ system implementation that actually maps names to Internet
+ addresses. <acronym class="acronym">DNS</acronym> data is maintained in a
+ group of distributed
+ hierarchical databases.
+ </p>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2563405"></a>Scope of Document</h2></div></div></div>
+<p>
+ The Berkeley Internet Name Domain
+ (<acronym class="acronym">BIND</acronym>) implements a
+ domain name server for a number of operating systems. This
+ document provides basic information about the installation and
+ care of the Internet Systems Consortium (<acronym class="acronym">ISC</acronym>)
+ <acronym class="acronym">BIND</acronym> version 9 software package for
+ system administrators.
+ </p>
+<p>
+ This version of the manual corresponds to BIND version 9.6.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2564385"></a>Organization of This Document</h2></div></div></div>
+<p>
+ In this document, <span class="emphasis"><em>Section 1</em></span> introduces
+ the basic <acronym class="acronym">DNS</acronym> and <acronym class="acronym">BIND</acronym> concepts. <span class="emphasis"><em>Section 2</em></span>
+ describes resource requirements for running <acronym class="acronym">BIND</acronym> in various
+ environments. Information in <span class="emphasis"><em>Section 3</em></span> is
+ <span class="emphasis"><em>task-oriented</em></span> in its presentation and is
+ organized functionally, to aid in the process of installing the
+ <acronym class="acronym">BIND</acronym> 9 software. The task-oriented
+ section is followed by
+ <span class="emphasis"><em>Section 4</em></span>, which contains more advanced
+ concepts that the system administrator may need for implementing
+ certain options. <span class="emphasis"><em>Section 5</em></span>
+ describes the <acronym class="acronym">BIND</acronym> 9 lightweight
+ resolver. The contents of <span class="emphasis"><em>Section 6</em></span> are
+ organized as in a reference manual to aid in the ongoing
+ maintenance of the software. <span class="emphasis"><em>Section 7</em></span> addresses
+ security considerations, and
+ <span class="emphasis"><em>Section 8</em></span> contains troubleshooting help. The
+ main body of the document is followed by several
+ <span class="emphasis"><em>appendices</em></span> which contain useful reference
+ information, such as a <span class="emphasis"><em>bibliography</em></span> and
+ historic information related to <acronym class="acronym">BIND</acronym>
+ and the Domain Name
+ System.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2564524"></a>Conventions Used in This Document</h2></div></div></div>
+<p>
+ In this document, we use the following general typographic
+ conventions:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <span class="emphasis"><em>To describe:</em></span>
+ </p>
+ </td>
+<td>
+ <p>
+ <span class="emphasis"><em>We use the style:</em></span>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ a pathname, filename, URL, hostname,
+ mailing list name, or new term or concept
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="filename">Fixed width</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ literal user
+ input
+ </p>
+ </td>
+<td>
+ <p>
+ <strong class="userinput"><code>Fixed Width Bold</code></strong>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ program output
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="computeroutput">Fixed Width</code>
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ The following conventions are used in descriptions of the
+ <acronym class="acronym">BIND</acronym> configuration file:</p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <span class="emphasis"><em>To describe:</em></span>
+ </p>
+ </td>
+<td>
+ <p>
+ <span class="emphasis"><em>We use the style:</em></span>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ keywords
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">Fixed Width</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ variables
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="varname">Fixed Width</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ Optional input
+ </p>
+ </td>
+<td>
+ <p>
+ [<span class="optional">Text is enclosed in square brackets</span>]
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2564637"></a>The Domain Name System (<acronym class="acronym">DNS</acronym>)</h2></div></div></div>
+<p>
+ The purpose of this document is to explain the installation
+ and upkeep of the <acronym class="acronym">BIND</acronym> (Berkeley Internet
+ Name Domain) software package, and we
+ begin by reviewing the fundamentals of the Domain Name System
+ (<acronym class="acronym">DNS</acronym>) as they relate to <acronym class="acronym">BIND</acronym>.
+ </p>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2564659"></a>DNS Fundamentals</h3></div></div></div>
+<p>
+ The Domain Name System (DNS) is a hierarchical, distributed
+ database. It stores information for mapping Internet host names to
+ IP
+ addresses and vice versa, mail routing information, and other data
+ used by Internet applications.
+ </p>
+<p>
+ Clients look up information in the DNS by calling a
+ <span class="emphasis"><em>resolver</em></span> library, which sends queries to one or
+ more <span class="emphasis"><em>name servers</em></span> and interprets the responses.
+ The <acronym class="acronym">BIND</acronym> 9 software distribution
+ contains a
+ name server, <span><strong class="command">named</strong></span>, and a resolver
+ library, <span><strong class="command">liblwres</strong></span>. The older
+ <span><strong class="command">libbind</strong></span> resolver library is also available
+ from ISC as a separate download.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2564693"></a>Domains and Domain Names</h3></div></div></div>
+<p>
+ The data stored in the DNS is identified by <span class="emphasis"><em>domain names</em></span> that are organized as a tree according to
+ organizational or administrative boundaries. Each node of the tree,
+ called a <span class="emphasis"><em>domain</em></span>, is given a label. The domain
+ name of the
+ node is the concatenation of all the labels on the path from the
+ node to the <span class="emphasis"><em>root</em></span> node. This is represented
+ in written form as a string of labels listed from right to left and
+ separated by dots. A label need only be unique within its parent
+ domain.
+ </p>
+<p>
+ For example, a domain name for a host at the
+ company <span class="emphasis"><em>Example, Inc.</em></span> could be
+ <code class="literal">ourhost.example.com</code>,
+ where <code class="literal">com</code> is the
+ top level domain to which
+ <code class="literal">ourhost.example.com</code> belongs,
+ <code class="literal">example</code> is
+ a subdomain of <code class="literal">com</code>, and
+ <code class="literal">ourhost</code> is the
+ name of the host.
+ </p>
+<p>
+ For administrative purposes, the name space is partitioned into
+ areas called <span class="emphasis"><em>zones</em></span>, each starting at a node and
+ extending down to the leaf nodes or to nodes where other zones
+ start.
+ The data for each zone is stored in a <span class="emphasis"><em>name server</em></span>, which answers queries about the zone using the
+ <span class="emphasis"><em>DNS protocol</em></span>.
+ </p>
+<p>
+ The data associated with each domain name is stored in the
+ form of <span class="emphasis"><em>resource records</em></span> (<acronym class="acronym">RR</acronym>s).
+ Some of the supported resource record types are described in
+ <a href="Bv9ARM.ch06.html#types_of_resource_records_and_when_to_use_them" title="Types of Resource Records and When to Use Them">the section called &#8220;Types of Resource Records and When to Use Them&#8221;</a>.
+ </p>
+<p>
+ For more detailed information about the design of the DNS and
+ the DNS protocol, please refer to the standards documents listed in
+ <a href="Bv9ARM.ch09.html#rfcs" title="Request for Comments (RFCs)">the section called &#8220;Request for Comments (RFCs)&#8221;</a>.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2564845"></a>Zones</h3></div></div></div>
+<p>
+ To properly operate a name server, it is important to understand
+ the difference between a <span class="emphasis"><em>zone</em></span>
+ and a <span class="emphasis"><em>domain</em></span>.
+ </p>
+<p>
+ As stated previously, a zone is a point of delegation in
+ the <acronym class="acronym">DNS</acronym> tree. A zone consists of
+ those contiguous parts of the domain
+ tree for which a name server has complete information and over which
+ it has authority. It contains all domain names from a certain point
+ downward in the domain tree except those which are delegated to
+ other zones. A delegation point is marked by one or more
+ <span class="emphasis"><em>NS records</em></span> in the
+ parent zone, which should be matched by equivalent NS records at
+ the root of the delegated zone.
+ </p>
+<p>
+ For instance, consider the <code class="literal">example.com</code>
+ domain which includes names
+ such as <code class="literal">host.aaa.example.com</code> and
+ <code class="literal">host.bbb.example.com</code> even though
+ the <code class="literal">example.com</code> zone includes
+ only delegations for the <code class="literal">aaa.example.com</code> and
+ <code class="literal">bbb.example.com</code> zones. A zone can
+ map
+ exactly to a single domain, but could also include only part of a
+ domain, the rest of which could be delegated to other
+ name servers. Every name in the <acronym class="acronym">DNS</acronym>
+ tree is a
+ <span class="emphasis"><em>domain</em></span>, even if it is
+ <span class="emphasis"><em>terminal</em></span>, that is, has no
+ <span class="emphasis"><em>subdomains</em></span>. Every subdomain is a domain and
+ every domain except the root is also a subdomain. The terminology is
+ not intuitive and we suggest that you read RFCs 1033, 1034 and 1035
+ to
+ gain a complete understanding of this difficult and subtle
+ topic.
+ </p>
+<p>
+ Though <acronym class="acronym">BIND</acronym> is called a "domain name
+ server",
+ it deals primarily in terms of zones. The master and slave
+ declarations in the <code class="filename">named.conf</code> file
+ specify
+ zones, not domains. When you ask some other site if it is willing to
+ be a slave server for your <span class="emphasis"><em>domain</em></span>, you are
+ actually asking for slave service for some collection of zones.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2567243"></a>Authoritative Name Servers</h3></div></div></div>
+<p>
+ Each zone is served by at least
+ one <span class="emphasis"><em>authoritative name server</em></span>,
+ which contains the complete data for the zone.
+ To make the DNS tolerant of server and network failures,
+ most zones have two or more authoritative servers, on
+ different networks.
+ </p>
+<p>
+ Responses from authoritative servers have the "authoritative
+ answer" (AA) bit set in the response packets. This makes them
+ easy to identify when debugging DNS configurations using tools like
+ <span><strong class="command">dig</strong></span> (<a href="Bv9ARM.ch03.html#diagnostic_tools" title="Diagnostic Tools">the section called &#8220;Diagnostic Tools&#8221;</a>).
+ </p>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2567267"></a>The Primary Master</h4></div></div></div>
+<p>
+ The authoritative server where the master copy of the zone
+ data is maintained is called the
+ <span class="emphasis"><em>primary master</em></span> server, or simply the
+ <span class="emphasis"><em>primary</em></span>. Typically it loads the zone
+ contents from some local file edited by humans or perhaps
+ generated mechanically from some other local file which is
+ edited by humans. This file is called the
+ <span class="emphasis"><em>zone file</em></span> or
+ <span class="emphasis"><em>master file</em></span>.
+ </p>
+<p>
+ In some cases, however, the master file may not be edited
+ by humans at all, but may instead be the result of
+ <span class="emphasis"><em>dynamic update</em></span> operations.
+ </p>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2567297"></a>Slave Servers</h4></div></div></div>
+<p>
+ The other authoritative servers, the <span class="emphasis"><em>slave</em></span>
+ servers (also known as <span class="emphasis"><em>secondary</em></span> servers)
+ load
+ the zone contents from another server using a replication process
+ known as a <span class="emphasis"><em>zone transfer</em></span>. Typically the data
+ are
+ transferred directly from the primary master, but it is also
+ possible
+ to transfer it from another slave. In other words, a slave server
+ may itself act as a master to a subordinate slave server.
+ </p>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2567386"></a>Stealth Servers</h4></div></div></div>
+<p>
+ Usually all of the zone's authoritative servers are listed in
+ NS records in the parent zone. These NS records constitute
+ a <span class="emphasis"><em>delegation</em></span> of the zone from the parent.
+ The authoritative servers are also listed in the zone file itself,
+ at the <span class="emphasis"><em>top level</em></span> or <span class="emphasis"><em>apex</em></span>
+ of the zone. You can list servers in the zone's top-level NS
+ records that are not in the parent's NS delegation, but you cannot
+ list servers in the parent's delegation that are not present at
+ the zone's top level.
+ </p>
+<p>
+ A <span class="emphasis"><em>stealth server</em></span> is a server that is
+ authoritative for a zone but is not listed in that zone's NS
+ records. Stealth servers can be used for keeping a local copy of
+ a
+ zone to speed up access to the zone's records or to make sure that
+ the
+ zone is available even if all the "official" servers for the zone
+ are
+ inaccessible.
+ </p>
+<p>
+ A configuration where the primary master server itself is a
+ stealth server is often referred to as a "hidden primary"
+ configuration. One use for this configuration is when the primary
+ master
+ is behind a firewall and therefore unable to communicate directly
+ with the outside world.
+ </p>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2567416"></a>Caching Name Servers</h3></div></div></div>
+<p>
+ The resolver libraries provided by most operating systems are
+ <span class="emphasis"><em>stub resolvers</em></span>, meaning that they are not
+ capable of
+ performing the full DNS resolution process by themselves by talking
+ directly to the authoritative servers. Instead, they rely on a
+ local
+ name server to perform the resolution on their behalf. Such a
+ server
+ is called a <span class="emphasis"><em>recursive</em></span> name server; it performs
+ <span class="emphasis"><em>recursive lookups</em></span> for local clients.
+ </p>
+<p>
+ To improve performance, recursive servers cache the results of
+ the lookups they perform. Since the processes of recursion and
+ caching are intimately connected, the terms
+ <span class="emphasis"><em>recursive server</em></span> and
+ <span class="emphasis"><em>caching server</em></span> are often used synonymously.
+ </p>
+<p>
+ The length of time for which a record may be retained in
+ the cache of a caching name server is controlled by the
+ Time To Live (TTL) field associated with each resource record.
+ </p>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2567520"></a>Forwarding</h4></div></div></div>
+<p>
+ Even a caching name server does not necessarily perform
+ the complete recursive lookup itself. Instead, it can
+ <span class="emphasis"><em>forward</em></span> some or all of the queries
+ that it cannot satisfy from its cache to another caching name
+ server,
+ commonly referred to as a <span class="emphasis"><em>forwarder</em></span>.
+ </p>
+<p>
+ There may be one or more forwarders,
+ and they are queried in turn until the list is exhausted or an
+ answer
+ is found. Forwarders are typically used when you do not
+ wish all the servers at a given site to interact directly with the
+ rest of
+ the Internet servers. A typical scenario would involve a number
+ of internal <acronym class="acronym">DNS</acronym> servers and an
+ Internet firewall. Servers unable
+ to pass packets through the firewall would forward to the server
+ that can do it, and that server would query the Internet <acronym class="acronym">DNS</acronym> servers
+ on the internal server's behalf.
+ </p>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2567546"></a>Name Servers in Multiple Roles</h3></div></div></div>
+<p>
+ The <acronym class="acronym">BIND</acronym> name server can
+ simultaneously act as
+ a master for some zones, a slave for other zones, and as a caching
+ (recursive) server for a set of local clients.
+ </p>
+<p>
+ However, since the functions of authoritative name service
+ and caching/recursive name service are logically separate, it is
+ often advantageous to run them on separate server machines.
+
+ A server that only provides authoritative name service
+ (an <span class="emphasis"><em>authoritative-only</em></span> server) can run with
+ recursion disabled, improving reliability and security.
+
+ A server that is not authoritative for any zones and only provides
+ recursive service to local
+ clients (a <span class="emphasis"><em>caching-only</em></span> server)
+ does not need to be reachable from the Internet at large and can
+ be placed inside a firewall.
+ </p>
+</div>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.html">Prev</a> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="Bv9ARM.ch02.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">BIND 9 Administrator Reference Manual </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> Chapter 2. <acronym class="acronym">BIND</acronym> Resource Requirements</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.ch02.html b/doc/arm/Bv9ARM.ch02.html
new file mode 100644
index 0000000..efe0eb8
--- /dev/null
+++ b/doc/arm/Bv9ARM.ch02.html
@@ -0,0 +1,158 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.ch02.html,v 1.38 2008/09/12 01:12:32 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 2. BIND Resource Requirements</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="prev" href="Bv9ARM.ch01.html" title="Chapter 1. Introduction">
+<link rel="next" href="Bv9ARM.ch03.html" title="Chapter 3. Name Server Configuration">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">Chapter 2. <acronym class="acronym">BIND</acronym> Resource Requirements</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.ch01.html">Prev</a> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="Bv9ARM.ch03.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="Bv9ARM.ch02"></a>Chapter 2. <acronym class="acronym">BIND</acronym> Resource Requirements</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch02.html#id2567580">Hardware requirements</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch02.html#id2567607">CPU Requirements</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch02.html#id2567620">Memory Requirements</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch02.html#id2567851">Name Server Intensive Environment Issues</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch02.html#id2567862">Supported Operating Systems</a></span></dt>
+</dl>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2567580"></a>Hardware requirements</h2></div></div></div>
+<p>
+ <acronym class="acronym">DNS</acronym> hardware requirements have
+ traditionally been quite modest.
+ For many installations, servers that have been pensioned off from
+ active duty have performed admirably as <acronym class="acronym">DNS</acronym> servers.
+ </p>
+<p>
+ The DNSSEC features of <acronym class="acronym">BIND</acronym> 9
+ may prove to be quite
+ CPU intensive however, so organizations that make heavy use of these
+ features may wish to consider larger systems for these applications.
+ <acronym class="acronym">BIND</acronym> 9 is fully multithreaded, allowing
+ full utilization of
+ multiprocessor systems for installations that need it.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2567607"></a>CPU Requirements</h2></div></div></div>
+<p>
+ CPU requirements for <acronym class="acronym">BIND</acronym> 9 range from
+ i486-class machines
+ for serving of static zones without caching, to enterprise-class
+ machines if you intend to process many dynamic updates and DNSSEC
+ signed zones, serving many thousands of queries per second.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2567620"></a>Memory Requirements</h2></div></div></div>
+<p>
+ The memory of the server has to be large enough to fit the
+ cache and zones loaded off disk. The <span><strong class="command">max-cache-size</strong></span>
+ option can be used to limit the amount of memory used by the cache,
+ at the expense of reducing cache hit rates and causing more <acronym class="acronym">DNS</acronym>
+ traffic.
+ Additionally, if additional section caching
+ (<a href="Bv9ARM.ch06.html#acache" title="Additional Section Caching">the section called &#8220;Additional Section Caching&#8221;</a>) is enabled,
+ the <span><strong class="command">max-acache-size</strong></span> option can be used to
+ limit the amount
+ of memory used by the mechanism.
+ It is still good practice to have enough memory to load
+ all zone and cache data into memory &#8212; unfortunately, the best
+ way
+ to determine this for a given installation is to watch the name server
+ in operation. After a few weeks the server process should reach
+ a relatively stable size where entries are expiring from the cache as
+ fast as they are being inserted.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2567851"></a>Name Server Intensive Environment Issues</h2></div></div></div>
+<p>
+ For name server intensive environments, there are two alternative
+ configurations that may be used. The first is where clients and
+ any second-level internal name servers query a main name server, which
+ has enough memory to build a large cache. This approach minimizes
+ the bandwidth used by external name lookups. The second alternative
+ is to set up second-level internal name servers to make queries
+ independently.
+ In this configuration, none of the individual machines needs to
+ have as much memory or CPU power as in the first alternative, but
+ this has the disadvantage of making many more external queries,
+ as none of the name servers share their cached data.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2567862"></a>Supported Operating Systems</h2></div></div></div>
+<p>
+ ISC <acronym class="acronym">BIND</acronym> 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
+ list of supported systems, see the README file in the top level
+ directory
+ of the BIND 9 source distribution.
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.ch01.html">Prev</a> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="Bv9ARM.ch03.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">Chapter 1. Introduction </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> Chapter 3. Name Server Configuration</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.ch03.html b/doc/arm/Bv9ARM.ch03.html
new file mode 100644
index 0000000..d548ddf
--- /dev/null
+++ b/doc/arm/Bv9ARM.ch03.html
@@ -0,0 +1,818 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.ch03.html,v 1.71 2008/09/25 04:45:04 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 3. Name Server Configuration</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="prev" href="Bv9ARM.ch02.html" title="Chapter 2. BIND Resource Requirements">
+<link rel="next" href="Bv9ARM.ch04.html" title="Chapter 4. Advanced DNS Features">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">Chapter 3. Name Server Configuration</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.ch02.html">Prev</a> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="Bv9ARM.ch04.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="Bv9ARM.ch03"></a>Chapter 3. Name Server Configuration</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch03.html#sample_configuration">Sample Configurations</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch03.html#id2567894">A Caching-only Name Server</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch03.html#id2567910">An Authoritative-only Name Server</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch03.html#id2568001">Load Balancing</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch03.html#id2568355">Name Server Operations</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch03.html#id2568360">Tools for Use With the Name Server Daemon</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch03.html#id2570104">Signals</a></span></dt>
+</dl></dd>
+</dl>
+</div>
+<p>
+ In this section we provide some suggested configurations along
+ with guidelines for their use. We suggest reasonable values for
+ certain option settings.
+ </p>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="sample_configuration"></a>Sample Configurations</h2></div></div></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2567894"></a>A Caching-only Name Server</h3></div></div></div>
+<p>
+ The following sample configuration is appropriate for a caching-only
+ name server for use by clients internal to a corporation. All
+ queries
+ from outside clients are refused using the <span><strong class="command">allow-query</strong></span>
+ option. Alternatively, the same effect could be achieved using
+ suitable
+ firewall rules.
+ </p>
+<pre class="programlisting">
+// 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
+ allow-query { corpnets; };
+};
+// Provide a reverse mapping for the loopback address 127.0.0.1
+zone "0.0.127.in-addr.arpa" {
+ type master;
+ file "localhost.rev";
+ notify no;
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2567910"></a>An Authoritative-only Name Server</h3></div></div></div>
+<p>
+ This sample configuration is for an authoritative-only server
+ that is the master server for "<code class="filename">example.com</code>"
+ and a slave for the subdomain "<code class="filename">eng.example.com</code>".
+ </p>
+<pre class="programlisting">
+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
+};
+
+// Provide a reverse mapping for the loopback address 127.0.0.1
+zone "0.0.127.in-addr.arpa" {
+ type master;
+ file "localhost.rev";
+ notify no;
+};
+// We are the master server for example.com
+zone "example.com" {
+ type master;
+ file "example.com.db";
+ // IP addresses of slave servers allowed to transfer example.com
+ allow-transfer {
+ 192.168.4.14;
+ 192.168.5.53;
+ };
+};
+// We are a slave server for eng.example.com
+zone "eng.example.com" {
+ type slave;
+ file "eng.example.com.bk";
+ // IP address of eng.example.com master server
+ masters { 192.168.4.12; };
+};
+</pre>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2568001"></a>Load Balancing</h2></div></div></div>
+<p>
+ A primitive form of load balancing can be achieved in
+ the <acronym class="acronym">DNS</acronym> by using multiple records
+ (such as multiple A records) for one name.
+ </p>
+<p>
+ For example, if you have three WWW servers with network addresses
+ of 10.0.0.1, 10.0.0.2 and 10.0.0.3, a set of records such as the
+ following means that clients will connect to each machine one third
+ of the time:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ Name
+ </p>
+ </td>
+<td>
+ <p>
+ TTL
+ </p>
+ </td>
+<td>
+ <p>
+ CLASS
+ </p>
+ </td>
+<td>
+ <p>
+ TYPE
+ </p>
+ </td>
+<td>
+ <p>
+ Resource Record (RR) Data
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="literal">www</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">600</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">IN</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10.0.0.1</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p></p>
+ </td>
+<td>
+ <p>
+ <code class="literal">600</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">IN</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10.0.0.2</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p></p>
+ </td>
+<td>
+ <p>
+ <code class="literal">600</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">IN</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10.0.0.3</code>
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ When a resolver queries for these records, <acronym class="acronym">BIND</acronym> will rotate
+ them and respond to the query with the records in a different
+ order. In the example above, clients will randomly receive
+ records in the order 1, 2, 3; 2, 3, 1; and 3, 1, 2. Most clients
+ will use the first record returned and discard the rest.
+ </p>
+<p>
+ For more detail on ordering responses, check the
+ <span><strong class="command">rrset-order</strong></span> substatement in the
+ <span><strong class="command">options</strong></span> statement, see
+ <a href="Bv9ARM.ch06.html#rrset_ordering">RRset Ordering</a>.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2568355"></a>Name Server Operations</h2></div></div></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2568360"></a>Tools for Use With the Name Server Daemon</h3></div></div></div>
+<p>
+ This section describes several indispensable diagnostic,
+ administrative and monitoring tools available to the system
+ administrator for controlling and debugging the name server
+ daemon.
+ </p>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="diagnostic_tools"></a>Diagnostic Tools</h4></div></div></div>
+<p>
+ The <span><strong class="command">dig</strong></span>, <span><strong class="command">host</strong></span>, and
+ <span><strong class="command">nslookup</strong></span> programs are all command
+ line tools
+ for manually querying name servers. They differ in style and
+ output format.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><a name="dig"></a><span><strong class="command">dig</strong></span></span></dt>
+<dd>
+<p>
+ The domain information groper (<span><strong class="command">dig</strong></span>)
+ is the most versatile and complete of these lookup tools.
+ It has two modes: simple interactive
+ mode for a single query, and batch mode which executes a
+ query for
+ each in a list of several query lines. All query options are
+ accessible
+ from the command line.
+ </p>
+<div class="cmdsynopsis"><p><code class="command">dig</code> [@<em class="replaceable"><code>server</code></em>] <em class="replaceable"><code>domain</code></em> [<em class="replaceable"><code>query-type</code></em>] [<em class="replaceable"><code>query-class</code></em>] [+<em class="replaceable"><code>query-option</code></em>] [-<em class="replaceable"><code>dig-option</code></em>] [%<em class="replaceable"><code>comment</code></em>]</p></div>
+<p>
+ The usual simple use of dig will take the form
+ </p>
+<p>
+ <span><strong class="command">dig @server domain query-type query-class</strong></span>
+ </p>
+<p>
+ For more information and a list of available commands and
+ options, see the <span><strong class="command">dig</strong></span> man
+ page.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">host</strong></span></span></dt>
+<dd>
+<p>
+ The <span><strong class="command">host</strong></span> utility emphasizes
+ simplicity
+ and ease of use. By default, it converts
+ between host names and Internet addresses, but its
+ functionality
+ can be extended with the use of options.
+ </p>
+<div class="cmdsynopsis"><p><code class="command">host</code> [-aCdlnrsTwv] [-c <em class="replaceable"><code>class</code></em>] [-N <em class="replaceable"><code>ndots</code></em>] [-t <em class="replaceable"><code>type</code></em>] [-W <em class="replaceable"><code>timeout</code></em>] [-R <em class="replaceable"><code>retries</code></em>] [-m <em class="replaceable"><code>flag</code></em>] [-4] [-6] <em class="replaceable"><code>hostname</code></em> [<em class="replaceable"><code>server</code></em>]</p></div>
+<p>
+ For more information and a list of available commands and
+ options, see the <span><strong class="command">host</strong></span> man
+ page.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">nslookup</strong></span></span></dt>
+<dd>
+<p><span><strong class="command">nslookup</strong></span>
+ has two modes: interactive and
+ non-interactive. Interactive mode allows the user to
+ query name servers for information about various
+ hosts and domains or to print a list of hosts in a
+ domain. Non-interactive mode is used to print just
+ the name and requested information for a host or
+ domain.
+ </p>
+<div class="cmdsynopsis"><p><code class="command">nslookup</code> [-option...] [[<em class="replaceable"><code>host-to-find</code></em>] | [- [server]]]</p></div>
+<p>
+ Interactive mode is entered when no arguments are given (the
+ default name server will be used) or when the first argument
+ is a
+ hyphen (`-') and the second argument is the host name or
+ Internet address
+ of a name server.
+ </p>
+<p>
+ Non-interactive mode is used when the name or Internet
+ address
+ of the host to be looked up is given as the first argument.
+ The
+ optional second argument specifies the host name or address
+ of a name server.
+ </p>
+<p>
+ Due to its arcane user interface and frequently inconsistent
+ behavior, we do not recommend the use of <span><strong class="command">nslookup</strong></span>.
+ Use <span><strong class="command">dig</strong></span> instead.
+ </p>
+</dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="admin_tools"></a>Administrative Tools</h4></div></div></div>
+<p>
+ Administrative tools play an integral part in the management
+ of a server.
+ </p>
+<div class="variablelist"><dl>
+<dt>
+<a name="named-checkconf"></a><span class="term"><span><strong class="command">named-checkconf</strong></span></span>
+</dt>
+<dd>
+<p>
+ The <span><strong class="command">named-checkconf</strong></span> program
+ checks the syntax of a <code class="filename">named.conf</code> file.
+ </p>
+<div class="cmdsynopsis"><p><code class="command">named-checkconf</code> [-jvz] [-t <em class="replaceable"><code>directory</code></em>] [<em class="replaceable"><code>filename</code></em>]</p></div>
+</dd>
+<dt>
+<a name="named-checkzone"></a><span class="term"><span><strong class="command">named-checkzone</strong></span></span>
+</dt>
+<dd>
+<p>
+ The <span><strong class="command">named-checkzone</strong></span> program
+ checks a master file for
+ syntax and consistency.
+ </p>
+<div class="cmdsynopsis"><p><code class="command">named-checkzone</code> [-djqvD] [-c <em class="replaceable"><code>class</code></em>] [-o <em class="replaceable"><code>output</code></em>] [-t <em class="replaceable"><code>directory</code></em>] [-w <em class="replaceable"><code>directory</code></em>] [-k <em class="replaceable"><code>(ignore|warn|fail)</code></em>] [-n <em class="replaceable"><code>(ignore|warn|fail)</code></em>] [-W <em class="replaceable"><code>(ignore|warn)</code></em>] <em class="replaceable"><code>zone</code></em> [<em class="replaceable"><code>filename</code></em>]</p></div>
+</dd>
+<dt>
+<a name="named-compilezone"></a><span class="term"><span><strong class="command">named-compilezone</strong></span></span>
+</dt>
+<dd><p>
+ Similar to <span><strong class="command">named-checkzone,</strong></span> but
+ it always dumps the zone content to a specified file
+ (typically in a different format).
+ </p></dd>
+<dt>
+<a name="rndc"></a><span class="term"><span><strong class="command">rndc</strong></span></span>
+</dt>
+<dd>
+<p>
+ The remote name daemon control
+ (<span><strong class="command">rndc</strong></span>) program allows the
+ system
+ administrator to control the operation of a name server.
+ Since <acronym class="acronym">BIND</acronym> 9.2, <span><strong class="command">rndc</strong></span>
+ supports all the commands of the BIND 8 <span><strong class="command">ndc</strong></span>
+ utility except <span><strong class="command">ndc start</strong></span> and
+ <span><strong class="command">ndc restart</strong></span>, which were also
+ not supported in <span><strong class="command">ndc</strong></span>'s
+ channel mode.
+ If you run <span><strong class="command">rndc</strong></span> without any
+ options
+ it will display a usage message as follows:
+ </p>
+<div class="cmdsynopsis"><p><code class="command">rndc</code> [-c <em class="replaceable"><code>config</code></em>] [-s <em class="replaceable"><code>server</code></em>] [-p <em class="replaceable"><code>port</code></em>] [-y <em class="replaceable"><code>key</code></em>] <em class="replaceable"><code>command</code></em> [<em class="replaceable"><code>command</code></em>...]</p></div>
+<p>The <span><strong class="command">command</strong></span>
+ is one of the following:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><strong class="userinput"><code>reload</code></strong></span></dt>
+<dd><p>
+ Reload configuration file and zones.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>reload <em class="replaceable"><code>zone</code></em>
+ [<span class="optional"><em class="replaceable"><code>class</code></em>
+ [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd><p>
+ Reload the given zone.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>refresh <em class="replaceable"><code>zone</code></em>
+ [<span class="optional"><em class="replaceable"><code>class</code></em>
+ [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd><p>
+ Schedule zone maintenance for the given zone.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>retransfer <em class="replaceable"><code>zone</code></em>
+
+ [<span class="optional"><em class="replaceable"><code>class</code></em>
+ [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd><p>
+ Retransfer the given zone from the master.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>freeze
+ [<span class="optional"><em class="replaceable"><code>zone</code></em>
+ [<span class="optional"><em class="replaceable"><code>class</code></em>
+ [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</span>]</code></strong></span></dt>
+<dd><p>
+ Suspend updates to a dynamic zone. If no zone is
+ specified,
+ then all zones are suspended. This allows manual
+ edits to be made to a zone normally updated by dynamic
+ update. It
+ also causes changes in the journal file to be synced
+ into the master
+ and the journal file to be removed. All dynamic
+ update attempts will
+ be refused while the zone is frozen.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>thaw
+ [<span class="optional"><em class="replaceable"><code>zone</code></em>
+ [<span class="optional"><em class="replaceable"><code>class</code></em>
+ [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</span>]</code></strong></span></dt>
+<dd><p>
+ Enable updates to a frozen dynamic zone. If no zone
+ is
+ specified, then all frozen zones are enabled. This
+ causes
+ the server to reload the zone from disk, and
+ re-enables dynamic updates
+ after the load has completed. After a zone is thawed,
+ dynamic updates
+ will no longer be refused.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>notify <em class="replaceable"><code>zone</code></em>
+ [<span class="optional"><em class="replaceable"><code>class</code></em>
+ [<span class="optional"><em class="replaceable"><code>view</code></em></span>]</span>]</code></strong></span></dt>
+<dd><p>
+ Resend NOTIFY messages for the zone.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>reconfig</code></strong></span></dt>
+<dd><p>
+ Reload the configuration file and load new zones,
+ but do not reload existing zone files even if they
+ have changed.
+ This is faster than a full <span><strong class="command">reload</strong></span> when there
+ is a large number of zones because it avoids the need
+ to examine the
+ modification times of the zones files.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>stats</code></strong></span></dt>
+<dd><p>
+ Write server statistics to the statistics file.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>querylog</code></strong></span></dt>
+<dd><p>
+ Toggle query logging. Query logging can also be enabled
+ by explicitly directing the <span><strong class="command">queries</strong></span>
+ <span><strong class="command">category</strong></span> to a
+ <span><strong class="command">channel</strong></span> in the
+ <span><strong class="command">logging</strong></span> section of
+ <code class="filename">named.conf</code> or by specifying
+ <span><strong class="command">querylog yes;</strong></span> in the
+ <span><strong class="command">options</strong></span> section of
+ <code class="filename">named.conf</code>.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>dumpdb
+ [<span class="optional">-all|-cache|-zone</span>]
+ [<span class="optional"><em class="replaceable"><code>view ...</code></em></span>]</code></strong></span></dt>
+<dd><p>
+ Dump the server's caches (default) and/or zones to
+ the
+ dump file for the specified views. If no view is
+ specified, all
+ views are dumped.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>stop [<span class="optional">-p</span>]</code></strong></span></dt>
+<dd><p>
+ Stop the server, making sure any recent changes
+ made through dynamic update or IXFR are first saved to
+ the master files of the updated zones.
+ If -p is specified named's process id is returned.
+ This allows an external process to determine when named
+ had completed stopping.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>halt [<span class="optional">-p</span>]</code></strong></span></dt>
+<dd><p>
+ Stop the server immediately. Recent changes
+ made through dynamic update or IXFR are not saved to
+ the master files, but will be rolled forward from the
+ journal files when the server is restarted.
+ If -p is specified named's process id is returned.
+ This allows an external process to determine when named
+ had completed halting.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>trace</code></strong></span></dt>
+<dd><p>
+ Increment the servers debugging level by one.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>trace <em class="replaceable"><code>level</code></em></code></strong></span></dt>
+<dd><p>
+ Sets the server's debugging level to an explicit
+ value.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>notrace</code></strong></span></dt>
+<dd><p>
+ Sets the server's debugging level to 0.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>flush</code></strong></span></dt>
+<dd><p>
+ Flushes the server's cache.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>flushname</code></strong> <em class="replaceable"><code>name</code></em></span></dt>
+<dd><p>
+ Flushes the given name from the server's cache.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>status</code></strong></span></dt>
+<dd><p>
+ Display status of the server.
+ Note that the number of zones includes the internal <span><strong class="command">bind/CH</strong></span> zone
+ and the default <span><strong class="command">./IN</strong></span>
+ hint zone if there is not an
+ explicit root zone configured.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>recursing</code></strong></span></dt>
+<dd><p>
+ Dump the list of queries named is currently recursing
+ on.
+ </p></dd>
+<dt><span class="term"><strong class="userinput"><code>validation
+ [<span class="optional">on|off</span>]
+ [<span class="optional"><em class="replaceable"><code>view ...</code></em></span>]
+ </code></strong></span></dt>
+<dd><p>
+ Enable or disable DNSSEC validation.
+ Note <span><strong class="command">dnssec-enable</strong></span> also needs to be
+ set to <strong class="userinput"><code>yes</code></strong> to be effective.
+ It defaults to enabled.
+ </p></dd>
+</dl></div>
+<p>
+ A configuration file is required, since all
+ communication with the server is authenticated with
+ digital signatures that rely on a shared secret, and
+ there is no way to provide that secret other than with a
+ configuration file. The default location for the
+ <span><strong class="command">rndc</strong></span> configuration file is
+ <code class="filename">/etc/rndc.conf</code>, but an
+ alternate
+ location can be specified with the <code class="option">-c</code>
+ option. If the configuration file is not found,
+ <span><strong class="command">rndc</strong></span> will also look in
+ <code class="filename">/etc/rndc.key</code> (or whatever
+ <code class="varname">sysconfdir</code> was defined when
+ the <acronym class="acronym">BIND</acronym> build was
+ configured).
+ The <code class="filename">rndc.key</code> file is
+ generated by
+ running <span><strong class="command">rndc-confgen -a</strong></span> as
+ described in
+ <a href="Bv9ARM.ch06.html#controls_statement_definition_and_usage" title="controls Statement Definition and
+ Usage">the section called &#8220;<span><strong class="command">controls</strong></span> Statement Definition and
+ Usage&#8221;</a>.
+ </p>
+<p>
+ The format of the configuration file is similar to
+ that of <code class="filename">named.conf</code>, but
+ limited to
+ only four statements, the <span><strong class="command">options</strong></span>,
+ <span><strong class="command">key</strong></span>, <span><strong class="command">server</strong></span> and
+ <span><strong class="command">include</strong></span>
+ statements. These statements are what associate the
+ secret keys to the servers with which they are meant to
+ be shared. The order of statements is not
+ significant.
+ </p>
+<p>
+ The <span><strong class="command">options</strong></span> statement has
+ three clauses:
+ <span><strong class="command">default-server</strong></span>, <span><strong class="command">default-key</strong></span>,
+ and <span><strong class="command">default-port</strong></span>.
+ <span><strong class="command">default-server</strong></span> takes a
+ host name or address argument and represents the server
+ that will
+ be contacted if no <code class="option">-s</code>
+ option is provided on the command line.
+ <span><strong class="command">default-key</strong></span> takes
+ the name of a key as its argument, as defined by a <span><strong class="command">key</strong></span> statement.
+ <span><strong class="command">default-port</strong></span> specifies the
+ port to which
+ <span><strong class="command">rndc</strong></span> should connect if no
+ port is given on the command line or in a
+ <span><strong class="command">server</strong></span> statement.
+ </p>
+<p>
+ The <span><strong class="command">key</strong></span> statement defines a
+ key to be used
+ by <span><strong class="command">rndc</strong></span> when authenticating
+ with
+ <span><strong class="command">named</strong></span>. Its syntax is
+ identical to the
+ <span><strong class="command">key</strong></span> statement in named.conf.
+ The keyword <strong class="userinput"><code>key</code></strong> is
+ followed by a key name, which must be a valid
+ domain name, though it need not actually be hierarchical;
+ thus,
+ a string like "<strong class="userinput"><code>rndc_key</code></strong>" is a valid
+ name.
+ The <span><strong class="command">key</strong></span> statement has two
+ clauses:
+ <span><strong class="command">algorithm</strong></span> and <span><strong class="command">secret</strong></span>.
+ While the configuration parser will accept any string as the
+ argument
+ to algorithm, currently only the string "<strong class="userinput"><code>hmac-md5</code></strong>"
+ has any meaning. The secret is a base-64 encoded string
+ as specified in RFC 3548.
+ </p>
+<p>
+ The <span><strong class="command">server</strong></span> statement
+ associates a key
+ defined using the <span><strong class="command">key</strong></span>
+ statement with a server.
+ The keyword <strong class="userinput"><code>server</code></strong> is followed by a
+ host name or address. The <span><strong class="command">server</strong></span> statement
+ has two clauses: <span><strong class="command">key</strong></span> and <span><strong class="command">port</strong></span>.
+ The <span><strong class="command">key</strong></span> clause specifies the
+ name of the key
+ to be used when communicating with this server, and the
+ <span><strong class="command">port</strong></span> clause can be used to
+ specify the port <span><strong class="command">rndc</strong></span> should
+ connect
+ to on the server.
+ </p>
+<p>
+ A sample minimal configuration file is as follows:
+ </p>
+<pre class="programlisting">
+key rndc_key {
+ algorithm "hmac-md5";
+ secret "c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K";
+};
+options {
+ default-server 127.0.0.1;
+ default-key rndc_key;
+};
+</pre>
+<p>
+ This file, if installed as <code class="filename">/etc/rndc.conf</code>,
+ would allow the command:
+ </p>
+<p>
+ <code class="prompt">$ </code><strong class="userinput"><code>rndc reload</code></strong>
+ </p>
+<p>
+ to connect to 127.0.0.1 port 953 and cause the name server
+ to reload, if a name server on the local machine were
+ running with
+ following controls statements:
+ </p>
+<pre class="programlisting">
+controls {
+ inet 127.0.0.1 allow { localhost; } keys { rndc_key; };
+};
+</pre>
+<p>
+ and it had an identical key statement for
+ <code class="literal">rndc_key</code>.
+ </p>
+<p>
+ Running the <span><strong class="command">rndc-confgen</strong></span>
+ program will
+ conveniently create a <code class="filename">rndc.conf</code>
+ file for you, and also display the
+ corresponding <span><strong class="command">controls</strong></span>
+ statement that you need to
+ add to <code class="filename">named.conf</code>.
+ Alternatively,
+ you can run <span><strong class="command">rndc-confgen -a</strong></span>
+ to set up
+ a <code class="filename">rndc.key</code> file and not
+ modify
+ <code class="filename">named.conf</code> at all.
+ </p>
+</dd>
+</dl></div>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2570104"></a>Signals</h3></div></div></div>
+<p>
+ Certain UNIX signals cause the name server to take specific
+ actions, as described in the following table. These signals can
+ be sent using the <span><strong class="command">kill</strong></span> command.
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p><span><strong class="command">SIGHUP</strong></span></p>
+ </td>
+<td>
+ <p>
+ Causes the server to read <code class="filename">named.conf</code> and
+ reload the database.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">SIGTERM</strong></span></p>
+ </td>
+<td>
+ <p>
+ Causes the server to clean up and exit.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">SIGINT</strong></span></p>
+ </td>
+<td>
+ <p>
+ Causes the server to clean up and exit.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.ch02.html">Prev</a> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="Bv9ARM.ch04.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">Chapter 2. <acronym class="acronym">BIND</acronym> Resource Requirements </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> Chapter 4. Advanced DNS Features</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.ch04.html b/doc/arm/Bv9ARM.ch04.html
new file mode 100644
index 0000000..4aba208
--- /dev/null
+++ b/doc/arm/Bv9ARM.ch04.html
@@ -0,0 +1,1036 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.ch04.html,v 1.87 2008/09/25 06:24:42 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 4. Advanced DNS Features</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="prev" href="Bv9ARM.ch03.html" title="Chapter 3. Name Server Configuration">
+<link rel="next" href="Bv9ARM.ch05.html" title="Chapter 5. The BIND 9 Lightweight Resolver">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">Chapter 4. Advanced DNS Features</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.ch03.html">Prev</a> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="Bv9ARM.ch05.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="Bv9ARM.ch04"></a>Chapter 4. Advanced DNS Features</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#notify">Notify</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#dynamic_update">Dynamic Update</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch04.html#journal">The journal file</a></span></dt></dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#incremental_zone_transfers">Incremental Zone Transfers (IXFR)</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#id2570509">Split DNS</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2570528">Example split DNS setup</a></span></dt></dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#tsig">TSIG</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571168">Generate Shared Keys for Each Pair of Hosts</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571241">Copying the Shared Secret to Both Machines</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571252">Informing the Servers of the Key's Existence</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571291">Instructing the Server to Use the Key</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571485">TSIG Key Based Access Control</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571530">Errors</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#id2571612">TKEY</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#id2571661">SIG(0)</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#DNSSEC">DNSSEC</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571798">Generating Keys</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571877">Signing the Zone</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571958">Configuring Servers</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#id2572101">IPv6 Support in <acronym class="acronym">BIND</acronym> 9</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2572163">Address Lookups Using AAAA Records</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2572184">Address to Name Lookups Using Nibble Format</a></span></dt>
+</dl></dd>
+</dl>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="notify"></a>Notify</h2></div></div></div>
+<p>
+ <acronym class="acronym">DNS</acronym> NOTIFY is a mechanism that allows master
+ servers to notify their slave servers of changes to a zone's data. In
+ response to a <span><strong class="command">NOTIFY</strong></span> from a master server, the
+ slave will check to see that its version of the zone is the
+ current version and, if not, initiate a zone transfer.
+ </p>
+<p>
+ For more information about <acronym class="acronym">DNS</acronym>
+ <span><strong class="command">NOTIFY</strong></span>, see the description of the
+ <span><strong class="command">notify</strong></span> option in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a> and
+ the description of the zone option <span><strong class="command">also-notify</strong></span> in
+ <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>. The <span><strong class="command">NOTIFY</strong></span>
+ protocol is specified in RFC 1996.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+ As a slave zone can also be a master to other slaves, named,
+ by default, sends <span><strong class="command">NOTIFY</strong></span> messages for every zone
+ it loads. Specifying <span><strong class="command">notify master-only;</strong></span> will
+ cause named to only send <span><strong class="command">NOTIFY</strong></span> for master
+ zones that it loads.
+ </div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="dynamic_update"></a>Dynamic Update</h2></div></div></div>
+<p>
+ Dynamic Update is a method for adding, replacing or deleting
+ records in a master server by sending it a special form of DNS
+ messages. The format and meaning of these messages is specified
+ in RFC 2136.
+ </p>
+<p>
+ Dynamic update is enabled by including an
+ <span><strong class="command">allow-update</strong></span> or <span><strong class="command">update-policy</strong></span>
+ clause in the <span><strong class="command">zone</strong></span> statement. The
+ <span><strong class="command">tkey-gssapi-credential</strong></span> and
+ <span><strong class="command">tkey-domain</strong></span> clauses in the
+ <span><strong class="command">options</strong></span> statement enable the
+ server to negotiate keys that can be matched against those
+ in <span><strong class="command">update-policy</strong></span> or
+ <span><strong class="command">allow-update</strong></span>.
+ </p>
+<p>
+ Updating of secure zones (zones using DNSSEC) follows RFC
+ 3007: RRSIG, NSEC and NSEC3 records affected by updates are
+ automatically regenerated by the server using an online
+ zone key. Update authorization is based on transaction
+ signatures and an explicit server policy.
+ </p>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="journal"></a>The journal file</h3></div></div></div>
+<p>
+ All changes made to a zone using dynamic update are stored
+ in the zone's journal file. This file is automatically created
+ by the server when the first dynamic update takes place.
+ The name of the journal file is formed by appending the extension
+ <code class="filename">.jnl</code> to the name of the
+ corresponding zone
+ file unless specifically overridden. The journal file is in a
+ binary format and should not be edited manually.
+ </p>
+<p>
+ The server will also occasionally write ("dump")
+ the complete contents of the updated zone to its zone file.
+ This is not done immediately after
+ each dynamic update, because that would be too slow when a large
+ zone is updated frequently. Instead, the dump is delayed by
+ up to 15 minutes, allowing additional updates to take place.
+ </p>
+<p>
+ When a server is restarted after a shutdown or crash, it will replay
+ the journal file to incorporate into the zone any updates that
+ took
+ place after the last zone dump.
+ </p>
+<p>
+ Changes that result from incoming incremental zone transfers are
+ also
+ journalled in a similar way.
+ </p>
+<p>
+ The zone files of dynamic zones cannot normally be edited by
+ hand because they are not guaranteed to contain the most recent
+ dynamic changes &#8212; those are only in the journal file.
+ The only way to ensure that the zone file of a dynamic zone
+ is up to date is to run <span><strong class="command">rndc stop</strong></span>.
+ </p>
+<p>
+ If you have to make changes to a dynamic zone
+ manually, the following procedure will work: Disable dynamic updates
+ to the zone using
+ <span><strong class="command">rndc freeze <em class="replaceable"><code>zone</code></em></strong></span>.
+ This will also remove the zone's <code class="filename">.jnl</code> file
+ and update the master file. Edit the zone file. Run
+ <span><strong class="command">rndc thaw <em class="replaceable"><code>zone</code></em></strong></span>
+ to reload the changed zone and re-enable dynamic updates.
+ </p>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="incremental_zone_transfers"></a>Incremental Zone Transfers (IXFR)</h2></div></div></div>
+<p>
+ The incremental zone transfer (IXFR) protocol is a way for
+ slave servers to transfer only changed data, instead of having to
+ transfer the entire zone. The IXFR protocol is specified in RFC
+ 1995. See <a href="Bv9ARM.ch09.html#proposed_standards">Proposed Standards</a>.
+ </p>
+<p>
+ When acting as a master, <acronym class="acronym">BIND</acronym> 9
+ supports IXFR for those zones
+ where the necessary change history information is available. These
+ include master zones maintained by dynamic update and slave zones
+ whose data was obtained by IXFR. For manually maintained master
+ zones, and for slave zones obtained by performing a full zone
+ transfer (AXFR), IXFR is supported only if the option
+ <span><strong class="command">ixfr-from-differences</strong></span> is set
+ to <strong class="userinput"><code>yes</code></strong>.
+ </p>
+<p>
+ When acting as a slave, <acronym class="acronym">BIND</acronym> 9 will
+ attempt to use IXFR unless
+ it is explicitly disabled. For more information about disabling
+ IXFR, see the description of the <span><strong class="command">request-ixfr</strong></span> clause
+ of the <span><strong class="command">server</strong></span> statement.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2570509"></a>Split DNS</h2></div></div></div>
+<p>
+ Setting up different views, or visibility, of the DNS space to
+ internal and external resolvers is usually referred to as a
+ <span class="emphasis"><em>Split DNS</em></span> setup. There are several
+ reasons an organization would want to set up its DNS this way.
+ </p>
+<p>
+ One common reason for setting up a DNS system this way is
+ to hide "internal" DNS information from "external" clients on the
+ Internet. There is some debate as to whether or not this is actually
+ useful.
+ Internal DNS information leaks out in many ways (via email headers,
+ for example) and most savvy "attackers" can find the information
+ they need using other means.
+ However, since listing addresses of internal servers that
+ external clients cannot possibly reach can result in
+ connection delays and other annoyances, an organization may
+ choose to use a Split DNS to present a consistent view of itself
+ to the outside world.
+ </p>
+<p>
+ Another common reason for setting up a Split DNS system is
+ to allow internal networks that are behind filters or in RFC 1918
+ space (reserved IP space, as documented in RFC 1918) to resolve DNS
+ on the Internet. Split DNS can also be used to allow mail from outside
+ back in to the internal network.
+ </p>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2570528"></a>Example split DNS setup</h3></div></div></div>
+<p>
+ Let's say a company named <span class="emphasis"><em>Example, Inc.</em></span>
+ (<code class="literal">example.com</code>)
+ has several corporate sites that have an internal network with
+ reserved
+ Internet Protocol (IP) space and an external demilitarized zone (DMZ),
+ or "outside" section of a network, that is available to the public.
+ </p>
+<p>
+ <span class="emphasis"><em>Example, Inc.</em></span> wants its internal clients
+ to be able to resolve external hostnames and to exchange mail with
+ people on the outside. The company also wants its internal resolvers
+ to have access to certain internal-only zones that are not available
+ at all outside of the internal network.
+ </p>
+<p>
+ In order to accomplish this, the company will set up two sets
+ of name servers. One set will be on the inside network (in the
+ reserved
+ IP space) and the other set will be on bastion hosts, which are
+ "proxy"
+ hosts that can talk to both sides of its network, in the DMZ.
+ </p>
+<p>
+ The internal servers will be configured to forward all queries,
+ except queries for <code class="filename">site1.internal</code>, <code class="filename">site2.internal</code>, <code class="filename">site1.example.com</code>,
+ and <code class="filename">site2.example.com</code>, to the servers
+ in the
+ DMZ. These internal servers will have complete sets of information
+ for <code class="filename">site1.example.com</code>, <code class="filename">site2.example.com</code>,<span class="emphasis"><em></em></span> <code class="filename">site1.internal</code>,
+ and <code class="filename">site2.internal</code>.
+ </p>
+<p>
+ To protect the <code class="filename">site1.internal</code> and <code class="filename">site2.internal</code> domains,
+ the internal name servers must be configured to disallow all queries
+ to these domains from any external hosts, including the bastion
+ hosts.
+ </p>
+<p>
+ The external servers, which are on the bastion hosts, will
+ be configured to serve the "public" version of the <code class="filename">site1</code> and <code class="filename">site2.example.com</code> zones.
+ This could include things such as the host records for public servers
+ (<code class="filename">www.example.com</code> and <code class="filename">ftp.example.com</code>),
+ and mail exchange (MX) records (<code class="filename">a.mx.example.com</code> and <code class="filename">b.mx.example.com</code>).
+ </p>
+<p>
+ In addition, the public <code class="filename">site1</code> and <code class="filename">site2.example.com</code> zones
+ should have special MX records that contain wildcard (`*') records
+ pointing to the bastion hosts. This is needed because external mail
+ servers do not have any other way of looking up how to deliver mail
+ to those internal hosts. With the wildcard records, the mail will
+ be delivered to the bastion host, which can then forward it on to
+ internal hosts.
+ </p>
+<p>
+ Here's an example of a wildcard MX record:
+ </p>
+<pre class="programlisting">* IN MX 10 external1.example.com.</pre>
+<p>
+ Now that they accept mail on behalf of anything in the internal
+ network, the bastion hosts will need to know how to deliver mail
+ to internal hosts. In order for this to work properly, the resolvers
+ on
+ the bastion hosts will need to be configured to point to the internal
+ name servers for DNS resolution.
+ </p>
+<p>
+ Queries for internal hostnames will be answered by the internal
+ servers, and queries for external hostnames will be forwarded back
+ out to the DNS servers on the bastion hosts.
+ </p>
+<p>
+ In order for all this to work properly, internal clients will
+ need to be configured to query <span class="emphasis"><em>only</em></span> the internal
+ name servers for DNS queries. This could also be enforced via
+ selective
+ filtering on the network.
+ </p>
+<p>
+ If everything has been set properly, <span class="emphasis"><em>Example, Inc.</em></span>'s
+ internal clients will now be able to:
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+ Look up any hostnames in the <code class="literal">site1</code>
+ and
+ <code class="literal">site2.example.com</code> zones.
+ </li>
+<li>
+ Look up any hostnames in the <code class="literal">site1.internal</code> and
+ <code class="literal">site2.internal</code> domains.
+ </li>
+<li>Look up any hostnames on the Internet.</li>
+<li>Exchange mail with both internal and external people.</li>
+</ul></div>
+<p>
+ Hosts on the Internet will be able to:
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+ Look up any hostnames in the <code class="literal">site1</code>
+ and
+ <code class="literal">site2.example.com</code> zones.
+ </li>
+<li>
+ Exchange mail with anyone in the <code class="literal">site1</code> and
+ <code class="literal">site2.example.com</code> zones.
+ </li>
+</ul></div>
+<p>
+ Here is an example configuration for the setup we just
+ described above. Note that this is only configuration information;
+ for information on how to configure your zone files, see <a href="Bv9ARM.ch03.html#sample_configuration" title="Sample Configurations">the section called &#8220;Sample Configurations&#8221;</a>.
+ </p>
+<p>
+ Internal DNS server config:
+ </p>
+<pre class="programlisting">
+
+acl internals { 172.16.72.0/24; 192.168.1.0/24; };
+
+acl externals { <code class="varname">bastion-ips-go-here</code>; };
+
+options {
+ ...
+ ...
+ forward only;
+ forwarders { // forward to external servers
+ <code class="varname">bastion-ips-go-here</code>;
+ };
+ allow-transfer { none; }; // sample allow-transfer (no one)
+ allow-query { internals; externals; }; // restrict query access
+ allow-recursion { internals; }; // restrict recursion
+ ...
+ ...
+};
+
+zone "site1.example.com" { // sample master zone
+ type master;
+ file "m/site1.example.com";
+ forwarders { }; // do normal iterative
+ // resolution (do not forward)
+ allow-query { internals; externals; };
+ allow-transfer { internals; };
+};
+
+zone "site2.example.com" { // sample slave zone
+ type slave;
+ file "s/site2.example.com";
+ masters { 172.16.72.3; };
+ forwarders { };
+ allow-query { internals; externals; };
+ allow-transfer { internals; };
+};
+
+zone "site1.internal" {
+ type master;
+ file "m/site1.internal";
+ forwarders { };
+ allow-query { internals; };
+ allow-transfer { internals; }
+};
+
+zone "site2.internal" {
+ type slave;
+ file "s/site2.internal";
+ masters { 172.16.72.3; };
+ forwarders { };
+ allow-query { internals };
+ allow-transfer { internals; }
+};
+</pre>
+<p>
+ External (bastion host) DNS server config:
+ </p>
+<pre class="programlisting">
+acl internals { 172.16.72.0/24; 192.168.1.0/24; };
+
+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
+ ...
+ ...
+};
+
+zone "site1.example.com" { // sample slave zone
+ type master;
+ file "m/site1.foo.com";
+ allow-transfer { internals; externals; };
+};
+
+zone "site2.example.com" {
+ type slave;
+ file "s/site2.foo.com";
+ masters { another_bastion_host_maybe; };
+ allow-transfer { internals; externals; }
+};
+</pre>
+<p>
+ In the <code class="filename">resolv.conf</code> (or equivalent) on
+ the bastion host(s):
+ </p>
+<pre class="programlisting">
+search ...
+nameserver 172.16.72.2
+nameserver 172.16.72.3
+nameserver 172.16.72.4
+</pre>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="tsig"></a>TSIG</h2></div></div></div>
+<p>
+ This is a short guide to setting up Transaction SIGnatures
+ (TSIG) based transaction security in <acronym class="acronym">BIND</acronym>. It describes changes
+ to the configuration file as well as what changes are required for
+ different features, including the process of creating transaction
+ keys and using transaction signatures with <acronym class="acronym">BIND</acronym>.
+ </p>
+<p>
+ <acronym class="acronym">BIND</acronym> primarily supports TSIG for server
+ to server communication.
+ This includes zone transfer, notify, and recursive query messages.
+ Resolvers based on newer versions of <acronym class="acronym">BIND</acronym> 8 have limited support
+ for TSIG.
+ </p>
+<p>
+ TSIG can also be useful for dynamic update. A primary
+ server for a dynamic zone should control access to the dynamic
+ update service, but IP-based access control is insufficient.
+ The cryptographic access control provided by TSIG
+ is far superior. The <span><strong class="command">nsupdate</strong></span>
+ program supports TSIG via the <code class="option">-k</code> and
+ <code class="option">-y</code> command line options or inline by use
+ of the <span><strong class="command">key</strong></span>.
+ </p>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2571168"></a>Generate Shared Keys for Each Pair of Hosts</h3></div></div></div>
+<p>
+ A shared secret is generated to be shared between <span class="emphasis"><em>host1</em></span> and <span class="emphasis"><em>host2</em></span>.
+ An arbitrary key name is chosen: "host1-host2.". The key name must
+ be the same on both hosts.
+ </p>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2571185"></a>Automatic Generation</h4></div></div></div>
+<p>
+ The following command will generate a 128-bit (16 byte) HMAC-MD5
+ key as described above. Longer keys are better, but shorter keys
+ are easier to read. Note that the maximum key length is 512 bits;
+ keys longer than that will be digested with MD5 to produce a
+ 128-bit key.
+ </p>
+<p>
+ <strong class="userinput"><code>dnssec-keygen -a hmac-md5 -b 128 -n HOST host1-host2.</code></strong>
+ </p>
+<p>
+ The key is in the file <code class="filename">Khost1-host2.+157+00000.private</code>.
+ Nothing directly uses this file, but the base-64 encoded string
+ following "<code class="literal">Key:</code>"
+ can be extracted from the file and used as a shared secret:
+ </p>
+<pre class="programlisting">Key: La/E5CjG9O+os1jq0a2jdA==</pre>
+<p>
+ The string "<code class="literal">La/E5CjG9O+os1jq0a2jdA==</code>" can
+ be used as the shared secret.
+ </p>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2571223"></a>Manual Generation</h4></div></div></div>
+<p>
+ The shared secret is simply a random sequence of bits, encoded
+ in base-64. Most ASCII strings are valid base-64 strings (assuming
+ the length is a multiple of 4 and only valid characters are used),
+ so the shared secret can be manually generated.
+ </p>
+<p>
+ Also, a known string can be run through <span><strong class="command">mmencode</strong></span> or
+ a similar program to generate base-64 encoded data.
+ </p>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2571241"></a>Copying the Shared Secret to Both Machines</h3></div></div></div>
+<p>
+ This is beyond the scope of DNS. A secure transport mechanism
+ should be used. This could be secure FTP, ssh, telephone, etc.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2571252"></a>Informing the Servers of the Key's Existence</h3></div></div></div>
+<p>
+ Imagine <span class="emphasis"><em>host1</em></span> and <span class="emphasis"><em>host 2</em></span>
+ are
+ both servers. The following is added to each server's <code class="filename">named.conf</code> file:
+ </p>
+<pre class="programlisting">
+key host1-host2. {
+ algorithm hmac-md5;
+ secret "La/E5CjG9O+os1jq0a2jdA==";
+};
+</pre>
+<p>
+ The algorithm, hmac-md5, is the only one supported by <acronym class="acronym">BIND</acronym>.
+ The secret is the one generated above. Since this is a secret, it
+ is recommended that either <code class="filename">named.conf</code> be non-world
+ readable, or the key directive be added to a non-world readable
+ file that is included by
+ <code class="filename">named.conf</code>.
+ </p>
+<p>
+ At this point, the key is recognized. This means that if the
+ server receives a message signed by this key, it can verify the
+ signature. If the signature is successfully verified, the
+ response is signed by the same key.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2571291"></a>Instructing the Server to Use the Key</h3></div></div></div>
+<p>
+ 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 <code class="filename">named.conf</code> file
+ for <span class="emphasis"><em>host1</em></span>, if the IP address of <span class="emphasis"><em>host2</em></span> is
+ 10.1.2.3:
+ </p>
+<pre class="programlisting">
+server 10.1.2.3 {
+ keys { host1-host2. ;};
+};
+</pre>
+<p>
+ Multiple keys may be present, but only the first is used.
+ This directive does not contain any secrets, so it may be in a
+ world-readable
+ file.
+ </p>
+<p>
+ If <span class="emphasis"><em>host1</em></span> sends a message that is a request
+ to that address, the message will be signed with the specified key. <span class="emphasis"><em>host1</em></span> will
+ expect any responses to signed messages to be signed with the same
+ key.
+ </p>
+<p>
+ A similar statement must be present in <span class="emphasis"><em>host2</em></span>'s
+ configuration file (with <span class="emphasis"><em>host1</em></span>'s address) for <span class="emphasis"><em>host2</em></span> to
+ sign request messages to <span class="emphasis"><em>host1</em></span>.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2571485"></a>TSIG Key Based Access Control</h3></div></div></div>
+<p>
+ <acronym class="acronym">BIND</acronym> allows IP addresses and ranges
+ to be specified in ACL
+ definitions and
+ <span><strong class="command">allow-{ query | transfer | update }</strong></span>
+ directives.
+ This has been extended to allow TSIG keys also. The above key would
+ be denoted <span><strong class="command">key host1-host2.</strong></span>
+ </p>
+<p>
+ An example of an allow-update directive would be:
+ </p>
+<pre class="programlisting">
+allow-update { key host1-host2. ;};
+</pre>
+<p>
+ This allows dynamic updates to succeed only if the request
+ was signed by a key named "<span><strong class="command">host1-host2.</strong></span>".
+ </p>
+<p>
+ You may want to read about the more powerful
+ <span><strong class="command">update-policy</strong></span> statement in
+ <a href="Bv9ARM.ch06.html#dynamic_update_policies" title="Dynamic Update Policies">the section called &#8220;Dynamic Update Policies&#8221;</a>.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2571530"></a>Errors</h3></div></div></div>
+<p>
+ The processing of TSIG signed messages can result in
+ several errors. If a signed message is sent to a non-TSIG aware
+ server, a FORMERR (format error) will be returned, since the server will not
+ understand the record. This is a result of misconfiguration,
+ since the server must be explicitly configured to send a TSIG
+ signed message to a specific server.
+ </p>
+<p>
+ If a TSIG aware server receives a message signed by an
+ unknown key, the response will be unsigned with the TSIG
+ extended error code set to BADKEY. If a TSIG aware server
+ receives a message with a signature that does not validate, the
+ response will be unsigned with the TSIG extended error code set
+ to BADSIG. If a TSIG aware server receives a message with a time
+ outside of the allowed range, the response will be signed with
+ the TSIG extended error code set to BADTIME, and the time values
+ will be adjusted so that the response can be successfully
+ verified. In any of these cases, the message's rcode (response code) is set to
+ NOTAUTH (not authenticated).
+ </p>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2571612"></a>TKEY</h2></div></div></div>
+<p><span><strong class="command">TKEY</strong></span>
+ is a mechanism for automatically generating a shared secret
+ between two hosts. There are several "modes" of
+ <span><strong class="command">TKEY</strong></span> that specify how the key is generated
+ or assigned. <acronym class="acronym">BIND</acronym> 9 implements only one of
+ these modes, the Diffie-Hellman key exchange. Both hosts are
+ required to have a Diffie-Hellman KEY record (although this
+ record is not required to be present in a zone). The
+ <span><strong class="command">TKEY</strong></span> process must use signed messages,
+ signed either by TSIG or SIG(0). The result of
+ <span><strong class="command">TKEY</strong></span> is a shared secret that can be used to
+ sign messages with TSIG. <span><strong class="command">TKEY</strong></span> can also be
+ used to delete shared secrets that it had previously
+ generated.
+ </p>
+<p>
+ The <span><strong class="command">TKEY</strong></span> process is initiated by a
+ client
+ or server by sending a signed <span><strong class="command">TKEY</strong></span>
+ query
+ (including any appropriate KEYs) to a TKEY-aware server. The
+ server response, if it indicates success, will contain a
+ <span><strong class="command">TKEY</strong></span> record and any appropriate keys.
+ After
+ this exchange, both participants have enough information to
+ determine the shared secret; the exact process depends on the
+ <span><strong class="command">TKEY</strong></span> mode. When using the
+ Diffie-Hellman
+ <span><strong class="command">TKEY</strong></span> mode, Diffie-Hellman keys are
+ exchanged,
+ and the shared secret is derived by both participants.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2571661"></a>SIG(0)</h2></div></div></div>
+<p>
+ <acronym class="acronym">BIND</acronym> 9 partially supports DNSSEC SIG(0)
+ transaction signatures as specified in RFC 2535 and RFC2931.
+ SIG(0)
+ uses public/private keys to authenticate messages. Access control
+ is performed in the same manner as TSIG keys; privileges can be
+ granted or denied based on the key name.
+ </p>
+<p>
+ When a SIG(0) signed message is received, it will only be
+ verified if the key is known and trusted by the server; the server
+ will not attempt to locate and/or validate the key.
+ </p>
+<p>
+ SIG(0) signing of multiple-message TCP streams is not
+ supported.
+ </p>
+<p>
+ The only tool shipped with <acronym class="acronym">BIND</acronym> 9 that
+ generates SIG(0) signed messages is <span><strong class="command">nsupdate</strong></span>.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="DNSSEC"></a>DNSSEC</h2></div></div></div>
+<p>
+ Cryptographic authentication of DNS information is possible
+ through the DNS Security (<span class="emphasis"><em>DNSSEC-bis</em></span>) extensions,
+ defined in RFC 4033, RFC 4034, and RFC 4035.
+ This section describes the creation and use of DNSSEC signed zones.
+ </p>
+<p>
+ In order to set up a DNSSEC secure zone, there are a series
+ of steps which must be followed. <acronym class="acronym">BIND</acronym>
+ 9 ships
+ with several tools
+ that are used in this process, which are explained in more detail
+ below. In all cases, the <code class="option">-h</code> option prints a
+ full list of parameters. Note that the DNSSEC tools require the
+ keyset files to be in the working directory or the
+ directory specified by the <code class="option">-d</code> option, and
+ that the tools shipped with BIND 9.2.x and earlier are not compatible
+ with the current ones.
+ </p>
+<p>
+ There must also be communication with the administrators of
+ the parent and/or child zone to transmit keys. A zone's security
+ status must be indicated by the parent zone for a DNSSEC capable
+ resolver to trust its data. This is done through the presence
+ or absence of a <code class="literal">DS</code> record at the
+ delegation
+ point.
+ </p>
+<p>
+ For other servers to trust data in this zone, they must
+ either be statically configured with this zone's zone key or the
+ zone key of another zone above this one in the DNS tree.
+ </p>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2571798"></a>Generating Keys</h3></div></div></div>
+<p>
+ The <span><strong class="command">dnssec-keygen</strong></span> program is used to
+ generate keys.
+ </p>
+<p>
+ A secure zone must contain one or more zone keys. The
+ zone keys will sign all other records in the zone, as well as
+ the zone keys of any secure delegated zones. Zone keys must
+ have the same name as the zone, a name type of
+ <span><strong class="command">ZONE</strong></span>, and must be usable for
+ authentication.
+ It is recommended that zone keys use a cryptographic algorithm
+ designated as "mandatory to implement" by the IETF; currently
+ the only one is RSASHA1.
+ </p>
+<p>
+ The following command will generate a 768-bit RSASHA1 key for
+ the <code class="filename">child.example</code> zone:
+ </p>
+<p>
+ <strong class="userinput"><code>dnssec-keygen -a RSASHA1 -b 768 -n ZONE child.example.</code></strong>
+ </p>
+<p>
+ Two output files will be produced:
+ <code class="filename">Kchild.example.+005+12345.key</code> and
+ <code class="filename">Kchild.example.+005+12345.private</code>
+ (where
+ 12345 is an example of a key tag). The key filenames contain
+ the key name (<code class="filename">child.example.</code>),
+ algorithm (3
+ is DSA, 1 is RSAMD5, 5 is RSASHA1, etc.), and the key tag (12345 in
+ this case).
+ The private key (in the <code class="filename">.private</code>
+ file) is
+ used to generate signatures, and the public key (in the
+ <code class="filename">.key</code> file) is used for signature
+ verification.
+ </p>
+<p>
+ To generate another key with the same properties (but with
+ a different key tag), repeat the above command.
+ </p>
+<p>
+ The <span><strong class="command">dnssec-keyfromlabel</strong></span> program is used
+ to get a key pair from a crypto hardware and build the key
+ files. Its usage is similar to <span><strong class="command">dnssec-keygen</strong></span>.
+ </p>
+<p>
+ The public keys should be inserted into the zone file by
+ including the <code class="filename">.key</code> files using
+ <span><strong class="command">$INCLUDE</strong></span> statements.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2571877"></a>Signing the Zone</h3></div></div></div>
+<p>
+ The <span><strong class="command">dnssec-signzone</strong></span> program is used
+ to sign a zone.
+ </p>
+<p>
+ Any <code class="filename">keyset</code> files corresponding to
+ secure subzones should be present. The zone signer will
+ generate <code class="literal">NSEC</code>, <code class="literal">NSEC3</code>
+ and <code class="literal">RRSIG</code> records for the zone, as
+ well as <code class="literal">DS</code> for the child zones if
+ <code class="literal">'-g'</code> is specified. If <code class="literal">'-g'</code>
+ is not specified, then DS RRsets for the secure child
+ zones need to be added manually.
+ </p>
+<p>
+ The following command signs the zone, assuming it is in a
+ file called <code class="filename">zone.child.example</code>. By
+ default, all zone keys which have an available private key are
+ used to generate signatures.
+ </p>
+<p>
+ <strong class="userinput"><code>dnssec-signzone -o child.example zone.child.example</code></strong>
+ </p>
+<p>
+ One output file is produced:
+ <code class="filename">zone.child.example.signed</code>. This
+ file
+ should be referenced by <code class="filename">named.conf</code>
+ as the
+ input file for the zone.
+ </p>
+<p><span><strong class="command">dnssec-signzone</strong></span>
+ will also produce a keyset and dsset files and optionally a
+ dlvset file. These are used to provide the parent zone
+ administrators with the <code class="literal">DNSKEYs</code> (or their
+ corresponding <code class="literal">DS</code> records) that are the
+ secure entry point to the zone.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2571958"></a>Configuring Servers</h3></div></div></div>
+<p>
+ To enable <span><strong class="command">named</strong></span> to respond appropriately
+ to DNS requests from DNSSEC aware clients,
+ <span><strong class="command">dnssec-enable</strong></span> must be set to yes.
+ </p>
+<p>
+ To enable <span><strong class="command">named</strong></span> to validate answers from
+ other servers both <span><strong class="command">dnssec-enable</strong></span> and
+ <span><strong class="command">dnssec-validation</strong></span> must be set and some
+ <span><strong class="command">trusted-keys</strong></span> must be configured
+ into <code class="filename">named.conf</code>.
+ </p>
+<p>
+ <span><strong class="command">trusted-keys</strong></span> are copies of DNSKEY RRs
+ for zones that are used to form the first link in the
+ cryptographic chain of trust. All keys listed in
+ <span><strong class="command">trusted-keys</strong></span> (and corresponding zones)
+ are deemed to exist and only the listed keys will be used
+ to validated the DNSKEY RRset that they are from.
+ </p>
+<p>
+ <span><strong class="command">trusted-keys</strong></span> are described in more detail
+ later in this document.
+ </p>
+<p>
+ Unlike <acronym class="acronym">BIND</acronym> 8, <acronym class="acronym">BIND</acronym>
+ 9 does not verify signatures on load, so zone keys for
+ authoritative zones do not need to be specified in the
+ configuration file.
+ </p>
+<p>
+ After DNSSEC gets established, a typical DNSSEC configuration
+ will look something like the following. It has a 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.
+ </p>
+<pre class="programlisting">
+trusted-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";
+};
+
+options {
+ ...
+ dnssec-enable yes;
+ dnssec-validation yes;
+};
+</pre>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+ None of the keys listed in this example are valid. In particular,
+ the root key is not valid.
+ </div>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2572101"></a>IPv6 Support in <acronym class="acronym">BIND</acronym> 9</h2></div></div></div>
+<p>
+ <acronym class="acronym">BIND</acronym> 9 fully supports all currently
+ defined forms of IPv6
+ name to address and address to name lookups. It will also use
+ IPv6 addresses to make queries when running on an IPv6 capable
+ system.
+ </p>
+<p>
+ For forward lookups, <acronym class="acronym">BIND</acronym> 9 supports
+ only AAAA records. RFC 3363 deprecated the use of A6 records,
+ and client-side support for A6 records was accordingly removed
+ from <acronym class="acronym">BIND</acronym> 9.
+ However, authoritative <acronym class="acronym">BIND</acronym> 9 name servers still
+ load zone files containing A6 records correctly, answer queries
+ for A6 records, and accept zone transfer for a zone containing A6
+ records.
+ </p>
+<p>
+ For IPv6 reverse lookups, <acronym class="acronym">BIND</acronym> 9 supports
+ the traditional "nibble" format used in the
+ <span class="emphasis"><em>ip6.arpa</em></span> domain, as well as the older, deprecated
+ <span class="emphasis"><em>ip6.int</em></span> domain.
+ Older versions of <acronym class="acronym">BIND</acronym> 9
+ supported the "binary label" (also known as "bitstring") format,
+ but support of binary labels has been completely removed per
+ RFC 3363.
+ Many applications in <acronym class="acronym">BIND</acronym> 9 do not understand
+ the binary label format at all any more, and will return an
+ error if given.
+ In particular, an authoritative <acronym class="acronym">BIND</acronym> 9
+ name server will not load a zone file containing binary labels.
+ </p>
+<p>
+ For an overview of the format and structure of IPv6 addresses,
+ see <a href="Bv9ARM.ch09.html#ipv6addresses" title="IPv6 addresses (AAAA)">the section called &#8220;IPv6 addresses (AAAA)&#8221;</a>.
+ </p>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2572163"></a>Address Lookups Using AAAA Records</h3></div></div></div>
+<p>
+ The IPv6 AAAA record is a parallel to the IPv4 A record,
+ and, unlike the deprecated A6 record, specifies the entire
+ IPv6 address in a single record. For example,
+ </p>
+<pre class="programlisting">
+$ORIGIN example.com.
+host 3600 IN AAAA 2001:db8::1
+</pre>
+<p>
+ Use of IPv4-in-IPv6 mapped addresses is not recommended.
+ If a host has an IPv4 address, use an A record, not
+ a AAAA, with <code class="literal">::ffff:192.168.42.1</code> as
+ the address.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2572184"></a>Address to Name Lookups Using Nibble Format</h3></div></div></div>
+<p>
+ When looking up an address in nibble format, the address
+ components are simply reversed, just as in IPv4, and
+ <code class="literal">ip6.arpa.</code> is appended to the
+ resulting name.
+ For example, the following would provide reverse name lookup for
+ a host with address
+ <code class="literal">2001:db8::1</code>.
+ </p>
+<pre class="programlisting">
+$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.
+</pre>
+</div>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.ch03.html">Prev</a> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="Bv9ARM.ch05.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">Chapter 3. Name Server Configuration </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> Chapter 5. The <acronym class="acronym">BIND</acronym> 9 Lightweight Resolver</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.ch05.html b/doc/arm/Bv9ARM.ch05.html
new file mode 100644
index 0000000..29ff97c
--- /dev/null
+++ b/doc/arm/Bv9ARM.ch05.html
@@ -0,0 +1,143 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.ch05.html,v 1.71 2008/09/25 06:24:41 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 5. The BIND 9 Lightweight Resolver</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="prev" href="Bv9ARM.ch04.html" title="Chapter 4. Advanced DNS Features">
+<link rel="next" href="Bv9ARM.ch06.html" title="Chapter 6. BIND 9 Configuration Reference">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">Chapter 5. The <acronym class="acronym">BIND</acronym> 9 Lightweight Resolver</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.ch04.html">Prev</a> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="Bv9ARM.ch06.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="Bv9ARM.ch05"></a>Chapter 5. The <acronym class="acronym">BIND</acronym> 9 Lightweight Resolver</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch05.html#id2572217">The Lightweight Resolver Library</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch05.html#lwresd">Running a Resolver Daemon</a></span></dt>
+</dl>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2572217"></a>The Lightweight Resolver Library</h2></div></div></div>
+<p>
+ Traditionally applications have been linked with a stub resolver
+ library that sends recursive DNS queries to a local caching name
+ server.
+ </p>
+<p>
+ IPv6 once introduced new complexity into the resolution process,
+ such as following A6 chains and DNAME records, and simultaneous
+ lookup of IPv4 and IPv6 addresses. Though most of the complexity was
+ then removed, these are hard or impossible
+ to implement in a traditional stub resolver.
+ </p>
+<p>
+ <acronym class="acronym">BIND</acronym> 9 therefore can also provide resolution
+ services to local clients
+ using a combination of a lightweight resolver library and a resolver
+ daemon process running on the local host. These communicate using
+ a simple UDP-based protocol, the "lightweight resolver protocol"
+ that is distinct from and simpler than the full DNS protocol.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="lwresd"></a>Running a Resolver Daemon</h2></div></div></div>
+<p>
+ To use the lightweight resolver interface, the system must
+ run the resolver daemon <span><strong class="command">lwresd</strong></span> or a
+ local
+ name server configured with a <span><strong class="command">lwres</strong></span>
+ statement.
+ </p>
+<p>
+ By default, applications using the lightweight resolver library will
+ make
+ UDP requests to the IPv4 loopback address (127.0.0.1) on port 921.
+ The
+ address can be overridden by <span><strong class="command">lwserver</strong></span>
+ lines in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+<p>
+ The daemon currently only looks in the DNS, but in the future
+ it may use other sources such as <code class="filename">/etc/hosts</code>,
+ NIS, etc.
+ </p>
+<p>
+ The <span><strong class="command">lwresd</strong></span> daemon is essentially a
+ caching-only name server that responds to requests using the
+ lightweight
+ resolver protocol rather than the DNS protocol. Because it needs
+ to run on each host, it is designed to require no or minimal
+ configuration.
+ Unless configured otherwise, it uses the name servers listed on
+ <span><strong class="command">nameserver</strong></span> lines in <code class="filename">/etc/resolv.conf</code>
+ as forwarders, but is also capable of doing the resolution
+ autonomously if
+ none are specified.
+ </p>
+<p>
+ The <span><strong class="command">lwresd</strong></span> daemon may also be
+ configured with a
+ <code class="filename">named.conf</code> style configuration file,
+ in
+ <code class="filename">/etc/lwresd.conf</code> by default. A name
+ server may also
+ be configured to act as a lightweight resolver daemon using the
+ <span><strong class="command">lwres</strong></span> statement in <code class="filename">named.conf</code>.
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.ch04.html">Prev</a> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="Bv9ARM.ch06.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">Chapter 4. Advanced DNS Features </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> Chapter 6. <acronym class="acronym">BIND</acronym> 9 Configuration Reference</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.ch06.html b/doc/arm/Bv9ARM.ch06.html
new file mode 100644
index 0000000..1f39b96
--- /dev/null
+++ b/doc/arm/Bv9ARM.ch06.html
@@ -0,0 +1,8784 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.ch06.html,v 1.201 2008/11/07 01:11:19 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 6. BIND 9 Configuration Reference</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="prev" href="Bv9ARM.ch05.html" title="Chapter 5. The BIND 9 Lightweight Resolver">
+<link rel="next" href="Bv9ARM.ch07.html" title="Chapter 7. BIND 9 Security Considerations">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">Chapter 6. <acronym class="acronym">BIND</acronym> 9 Configuration Reference</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.ch05.html">Prev</a> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="Bv9ARM.ch07.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="Bv9ARM.ch06"></a>Chapter 6. <acronym class="acronym">BIND</acronym> 9 Configuration Reference</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch06.html#configuration_file_elements">Configuration File Elements</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#address_match_lists">Address Match Lists</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2573721">Comment Syntax</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch06.html#Configuration_File_Grammar">Configuration File Grammar</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574292"><span><strong class="command">acl</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#acl"><span><strong class="command">acl</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574550"><span><strong class="command">controls</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#controls_statement_definition_and_usage"><span><strong class="command">controls</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574910"><span><strong class="command">include</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574928"><span><strong class="command">include</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2575088"><span><strong class="command">key</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2575111"><span><strong class="command">key</strong></span> Statement Definition and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2575202"><span><strong class="command">logging</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2575328"><span><strong class="command">logging</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576640"><span><strong class="command">lwres</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576713"><span><strong class="command">lwres</strong></span> Statement Definition and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576777"><span><strong class="command">masters</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576889"><span><strong class="command">masters</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576904"><span><strong class="command">options</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#options"><span><strong class="command">options</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#statschannels"><span><strong class="command">statistics-channels</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2585469"><span><strong class="command">statistics-channels</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#server_statement_grammar"><span><strong class="command">server</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#server_statement_definition_and_usage"><span><strong class="command">server</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2586153"><span><strong class="command">trusted-keys</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2586204"><span><strong class="command">trusted-keys</strong></span> Statement Definition
+ and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#view_statement_grammar"><span><strong class="command">view</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2586423"><span><strong class="command">view</strong></span> Statement Definition and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#zone_statement_grammar"><span><strong class="command">zone</strong></span>
+ Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2587892"><span><strong class="command">zone</strong></span> Statement Definition and Usage</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch06.html#id2590422">Zone File</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#types_of_resource_records_and_when_to_use_them">Types of Resource Records and When to Use Them</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2592652">Discussion of MX Records</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#Setting_TTLs">Setting TTLs</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2593204">Inverse Mapping in IPv4</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2593399">Other Zone File Directives</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2593656"><acronym class="acronym">BIND</acronym> Master File Extension: the <span><strong class="command">$GENERATE</strong></span> Directive</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#zonefile_format">Additional File Formats</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch06.html#statistics">BIND9 Statistics</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch06.html#statistics_counters">Statistics Counters</a></span></dt></dl></dd>
+</dl>
+</div>
+<p>
+ <acronym class="acronym">BIND</acronym> 9 configuration is broadly similar
+ to <acronym class="acronym">BIND</acronym> 8; however, there are a few new
+ areas
+ of configuration, such as views. <acronym class="acronym">BIND</acronym>
+ 8 configuration files should work with few alterations in <acronym class="acronym">BIND</acronym>
+ 9, although more complex configurations should be reviewed to check
+ if they can be more efficiently implemented using the new features
+ found in <acronym class="acronym">BIND</acronym> 9.
+ </p>
+<p>
+ <acronym class="acronym">BIND</acronym> 4 configuration files can be
+ converted to the new format
+ using the shell script
+ <code class="filename">contrib/named-bootconf/named-bootconf.sh</code>.
+ </p>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="configuration_file_elements"></a>Configuration File Elements</h2></div></div></div>
+<p>
+ Following is a list of elements used throughout the <acronym class="acronym">BIND</acronym> configuration
+ file documentation:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <code class="varname">acl_name</code>
+ </p>
+ </td>
+<td>
+ <p>
+ The name of an <code class="varname">address_match_list</code> as
+ defined by the <span><strong class="command">acl</strong></span> statement.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">address_match_list</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A list of one or more
+ <code class="varname">ip_addr</code>,
+ <code class="varname">ip_prefix</code>, <code class="varname">key_id</code>,
+ or <code class="varname">acl_name</code> elements, see
+ <a href="Bv9ARM.ch06.html#address_match_lists" title="Address Match Lists">the section called &#8220;Address Match Lists&#8221;</a>.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">masters_list</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A named list of one or more <code class="varname">ip_addr</code>
+ with optional <code class="varname">key_id</code> and/or
+ <code class="varname">ip_port</code>.
+ A <code class="varname">masters_list</code> may include other
+ <code class="varname">masters_lists</code>.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">domain_name</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A quoted string which will be used as
+ a DNS name, for example "<code class="literal">my.test.domain</code>".
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">dotted_decimal</code>
+ </p>
+ </td>
+<td>
+ <p>
+ One to four integers valued 0 through
+ 255 separated by dots (`.'), such as <span><strong class="command">123</strong></span>,
+ <span><strong class="command">45.67</strong></span> or <span><strong class="command">89.123.45.67</strong></span>.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">ip4_addr</code>
+ </p>
+ </td>
+<td>
+ <p>
+ An IPv4 address with exactly four elements
+ in <code class="varname">dotted_decimal</code> notation.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">ip6_addr</code>
+ </p>
+ </td>
+<td>
+ <p>
+ An IPv6 address, such as <span><strong class="command">2001:db8::1234</strong></span>.
+ IPv6 scoped addresses that have ambiguity on their
+ scope zones must be disambiguated by an appropriate
+ zone ID with the percent character (`%') as
+ delimiter. It is strongly recommended to use
+ string zone names rather than numeric identifiers,
+ in order to be robust against system configuration
+ changes. However, since there is no standard
+ mapping for such names and identifier values,
+ currently only interface names as link identifiers
+ are supported, assuming one-to-one mapping between
+ interfaces and links. For example, a link-local
+ address <span><strong class="command">fe80::1</strong></span> on the link
+ attached to the interface <span><strong class="command">ne0</strong></span>
+ can be specified as <span><strong class="command">fe80::1%ne0</strong></span>.
+ Note that on most systems link-local addresses
+ always have the ambiguity, and need to be
+ disambiguated.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">ip_addr</code>
+ </p>
+ </td>
+<td>
+ <p>
+ An <code class="varname">ip4_addr</code> or <code class="varname">ip6_addr</code>.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">ip_port</code>
+ </p>
+ </td>
+<td>
+ <p>
+ An IP port <code class="varname">number</code>.
+ The <code class="varname">number</code> is limited to 0
+ through 65535, with values
+ below 1024 typically restricted to use by processes running
+ as root.
+ In some cases, an asterisk (`*') character can be used as a
+ placeholder to
+ select a random high-numbered port.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">ip_prefix</code>
+ </p>
+ </td>
+<td>
+ <p>
+ An IP network specified as an <code class="varname">ip_addr</code>,
+ followed by a slash (`/') and then the number of bits in the
+ netmask.
+ Trailing zeros in a <code class="varname">ip_addr</code>
+ may omitted.
+ For example, <span><strong class="command">127/8</strong></span> is the
+ network <span><strong class="command">127.0.0.0</strong></span> with
+ netmask <span><strong class="command">255.0.0.0</strong></span> and <span><strong class="command">1.2.3.0/28</strong></span> is
+ network <span><strong class="command">1.2.3.0</strong></span> with netmask <span><strong class="command">255.255.255.240</strong></span>.
+ </p>
+ <p>
+ When specifying a prefix involving a IPv6 scoped address
+ the scope may be omitted. In that case the prefix will
+ match packets from any scope.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">key_id</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A <code class="varname">domain_name</code> representing
+ the name of a shared key, to be used for transaction
+ security.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">key_list</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A list of one or more
+ <code class="varname">key_id</code>s,
+ separated by semicolons and ending with a semicolon.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">number</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A non-negative 32-bit integer
+ (i.e., a number between 0 and 4294967295, inclusive).
+ Its acceptable value might further
+ be limited by the context in which it is used.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">path_name</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A quoted string which will be used as
+ a pathname, such as <code class="filename">zones/master/my.test.domain</code>.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">port_list</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A list of an <code class="varname">ip_port</code> or a port
+ range.
+ A port range is specified in the form of
+ <strong class="userinput"><code>range</code></strong> followed by
+ two <code class="varname">ip_port</code>s,
+ <code class="varname">port_low</code> and
+ <code class="varname">port_high</code>, which represents
+ port numbers from <code class="varname">port_low</code> through
+ <code class="varname">port_high</code>, inclusive.
+ <code class="varname">port_low</code> must not be larger than
+ <code class="varname">port_high</code>.
+ For example,
+ <strong class="userinput"><code>range 1024 65535</code></strong> represents
+ ports from 1024 through 65535.
+ In either case an asterisk (`*') character is not
+ allowed as a valid <code class="varname">ip_port</code>.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">size_spec</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A number, the word <strong class="userinput"><code>unlimited</code></strong>,
+ or the word <strong class="userinput"><code>default</code></strong>.
+ </p>
+ <p>
+ An <code class="varname">unlimited</code> <code class="varname">size_spec</code> requests unlimited
+ use, or the maximum available amount. A <code class="varname">default size_spec</code> uses
+ the limit that was in force when the server was started.
+ </p>
+ <p>
+ A <code class="varname">number</code> can optionally be
+ followed by a scaling factor:
+ <strong class="userinput"><code>K</code></strong> or <strong class="userinput"><code>k</code></strong>
+ for kilobytes,
+ <strong class="userinput"><code>M</code></strong> or <strong class="userinput"><code>m</code></strong>
+ for megabytes, and
+ <strong class="userinput"><code>G</code></strong> or <strong class="userinput"><code>g</code></strong> for gigabytes,
+ which scale by 1024, 1024*1024, and 1024*1024*1024
+ respectively.
+ </p>
+ <p>
+ The value must be representable as a 64-bit unsigned integer
+ (0 to 18446744073709551615, inclusive).
+ Using <code class="varname">unlimited</code> is the best
+ way
+ to safely set a really large number.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">yes_or_no</code>
+ </p>
+ </td>
+<td>
+ <p>
+ Either <strong class="userinput"><code>yes</code></strong> or <strong class="userinput"><code>no</code></strong>.
+ The words <strong class="userinput"><code>true</code></strong> and <strong class="userinput"><code>false</code></strong> are
+ also accepted, as are the numbers <strong class="userinput"><code>1</code></strong>
+ and <strong class="userinput"><code>0</code></strong>.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">dialup_option</code>
+ </p>
+ </td>
+<td>
+ <p>
+ One of <strong class="userinput"><code>yes</code></strong>,
+ <strong class="userinput"><code>no</code></strong>, <strong class="userinput"><code>notify</code></strong>,
+ <strong class="userinput"><code>notify-passive</code></strong>, <strong class="userinput"><code>refresh</code></strong> or
+ <strong class="userinput"><code>passive</code></strong>.
+ When used in a zone, <strong class="userinput"><code>notify-passive</code></strong>,
+ <strong class="userinput"><code>refresh</code></strong>, and <strong class="userinput"><code>passive</code></strong>
+ are restricted to slave and stub zones.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="address_match_lists"></a>Address Match Lists</h3></div></div></div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2573499"></a>Syntax</h4></div></div></div>
+<pre class="programlisting"><code class="varname">address_match_list</code> = address_match_list_element ;
+ [<span class="optional"> address_match_list_element; ... </span>]
+<code class="varname">address_match_list_element</code> = [<span class="optional"> ! </span>] (ip_address [<span class="optional">/length</span>] |
+ key key_id | acl_name | { address_match_list } )
+</pre>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2573527"></a>Definition and Usage</h4></div></div></div>
+<p>
+ Address match lists are primarily used to determine access
+ control for various server operations. They are also used in
+ the <span><strong class="command">listen-on</strong></span> and <span><strong class="command">sortlist</strong></span>
+ statements. The elements which constitute an address match
+ list can be any of the following:
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li>an IP address (IPv4 or IPv6)</li>
+<li>an IP prefix (in `/' notation)</li>
+<li>
+ a key ID, as defined by the <span><strong class="command">key</strong></span>
+ statement
+ </li>
+<li>the name of an address match list defined with
+ the <span><strong class="command">acl</strong></span> statement
+ </li>
+<li>a nested address match list enclosed in braces</li>
+</ul></div>
+<p>
+ Elements can be negated with a leading exclamation mark (`!'),
+ and the match list names "any", "none", "localhost", and
+ "localnets" are predefined. More information on those names
+ can be found in the description of the acl statement.
+ </p>
+<p>
+ The addition of the key clause made the name of this syntactic
+ element something of a misnomer, since security keys can be used
+ to validate access without regard to a host or network address.
+ Nonetheless, the term "address match list" is still used
+ throughout the documentation.
+ </p>
+<p>
+ When a given IP address or prefix is compared to an address
+ match list, the comparison takes place in approximately O(1)
+ time. However, key comparisons require that the list of keys
+ be traversed until a matching key is found, and therefore may
+ be somewhat slower.
+ </p>
+<p>
+ The interpretation of a match depends on whether the list is being
+ used for access control, defining listen-on ports, or in a
+ sortlist, and whether the element was negated.
+ </p>
+<p>
+ When used as an access control list, a non-negated match
+ allows access and a negated match denies access. If
+ there is no match, access is denied. The clauses
+ <span><strong class="command">allow-notify</strong></span>,
+ <span><strong class="command">allow-recursion</strong></span>,
+ <span><strong class="command">allow-recursion-on</strong></span>,
+ <span><strong class="command">allow-query</strong></span>,
+ <span><strong class="command">allow-query-on</strong></span>,
+ <span><strong class="command">allow-query-cache</strong></span>,
+ <span><strong class="command">allow-query-cache-on</strong></span>,
+ <span><strong class="command">allow-transfer</strong></span>,
+ <span><strong class="command">allow-update</strong></span>,
+ <span><strong class="command">allow-update-forwarding</strong></span>, and
+ <span><strong class="command">blackhole</strong></span> all use address match
+ lists. Similarly, the listen-on option will cause the
+ server to refuse queries on any of the machine's
+ addresses which do not match the list.
+ </p>
+<p>
+ Order of insertion is significant. If more than one element
+ in an ACL is found to match a given IP address or prefix,
+ preference will be given to the one that came
+ <span class="emphasis"><em>first</em></span> in the ACL definition.
+ Because of this first-match behavior, an element that
+ defines a subset of another element in the list should
+ come before the broader element, regardless of whether
+ either is negated. For example, in
+ <span><strong class="command">1.2.3/24; ! 1.2.3.13;</strong></span>
+ the 1.2.3.13 element is completely useless because the
+ algorithm will match any lookup for 1.2.3.13 to the 1.2.3/24
+ element. Using <span><strong class="command">! 1.2.3.13; 1.2.3/24</strong></span> fixes
+ that problem by having 1.2.3.13 blocked by the negation, but
+ all other 1.2.3.* hosts fall through.
+ </p>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2573721"></a>Comment Syntax</h3></div></div></div>
+<p>
+ The <acronym class="acronym">BIND</acronym> 9 comment syntax allows for
+ comments to appear
+ anywhere that whitespace may appear in a <acronym class="acronym">BIND</acronym> configuration
+ file. To appeal to programmers of all kinds, they can be written
+ in the C, C++, or shell/perl style.
+ </p>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2573736"></a>Syntax</h4></div></div></div>
+<p>
+ </p>
+<pre class="programlisting">/* This is a <acronym class="acronym">BIND</acronym> comment as in C */</pre>
+<p>
+ </p>
+<pre class="programlisting">// This is a <acronym class="acronym">BIND</acronym> comment as in C++</pre>
+<p>
+ </p>
+<pre class="programlisting"># This is a <acronym class="acronym">BIND</acronym> comment as in common UNIX shells and perl</pre>
+<p>
+ </p>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2573766"></a>Definition and Usage</h4></div></div></div>
+<p>
+ Comments may appear anywhere that whitespace may appear in
+ a <acronym class="acronym">BIND</acronym> configuration file.
+ </p>
+<p>
+ C-style comments start with the two characters /* (slash,
+ star) and end with */ (star, slash). Because they are completely
+ delimited with these characters, they can be used to comment only
+ a portion of a line or to span multiple lines.
+ </p>
+<p>
+ C-style comments cannot be nested. For example, the following
+ is not valid because the entire comment ends with the first */:
+ </p>
+<p>
+
+</p>
+<pre class="programlisting">/* This is the start of a comment.
+ This is still part of the comment.
+/* This is an incorrect attempt at nesting a comment. */
+ This is no longer in any comment. */
+</pre>
+<p>
+
+ </p>
+<p>
+ C++-style comments start with the two characters // (slash,
+ slash) and continue to the end of the physical line. They cannot
+ be continued across multiple physical lines; to have one logical
+ comment span multiple lines, each line must use the // pair.
+ </p>
+<p>
+ For example:
+ </p>
+<p>
+
+</p>
+<pre class="programlisting">// This is the start of a comment. The next line
+// is a new comment, even though it is logically
+// part of the previous comment.
+</pre>
+<p>
+
+ </p>
+<p>
+ Shell-style (or perl-style, if you prefer) comments start
+ with the character <code class="literal">#</code> (number sign)
+ and continue to the end of the
+ physical line, as in C++ comments.
+ </p>
+<p>
+ For example:
+ </p>
+<p>
+
+</p>
+<pre class="programlisting"># This is the start of a comment. The next line
+# is a new comment, even though it is logically
+# part of the previous comment.
+</pre>
+<p>
+
+ </p>
+<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+<p>
+ You cannot use the semicolon (`;') character
+ to start a comment such as you would in a zone file. The
+ semicolon indicates the end of a configuration
+ statement.
+ </p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="Configuration_File_Grammar"></a>Configuration File Grammar</h2></div></div></div>
+<p>
+ A <acronym class="acronym">BIND</acronym> 9 configuration consists of
+ statements and comments.
+ Statements end with a semicolon. Statements and comments are the
+ only elements that can appear without enclosing braces. Many
+ statements contain a block of sub-statements, which are also
+ terminated with a semicolon.
+ </p>
+<p>
+ The following statements are supported:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p><span><strong class="command">acl</strong></span></p>
+ </td>
+<td>
+ <p>
+ defines a named IP address
+ matching list, for access control and other uses.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">controls</strong></span></p>
+ </td>
+<td>
+ <p>
+ declares control channels to be used
+ by the <span><strong class="command">rndc</strong></span> utility.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">include</strong></span></p>
+ </td>
+<td>
+ <p>
+ includes a file.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">key</strong></span></p>
+ </td>
+<td>
+ <p>
+ specifies key information for use in
+ authentication and authorization using TSIG.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">logging</strong></span></p>
+ </td>
+<td>
+ <p>
+ specifies what the server logs, and where
+ the log messages are sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">lwres</strong></span></p>
+ </td>
+<td>
+ <p>
+ configures <span><strong class="command">named</strong></span> to
+ also act as a light-weight resolver daemon (<span><strong class="command">lwresd</strong></span>).
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">masters</strong></span></p>
+ </td>
+<td>
+ <p>
+ defines a named masters list for
+ inclusion in stub and slave zone masters clauses.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">options</strong></span></p>
+ </td>
+<td>
+ <p>
+ controls global server configuration
+ options and sets defaults for other statements.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">statistics-channels</strong></span></p>
+ </td>
+<td>
+ <p>
+ declares communication channels to get access to
+ <span><strong class="command">named</strong></span> statistics.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">server</strong></span></p>
+ </td>
+<td>
+ <p>
+ sets certain configuration options on
+ a per-server basis.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">trusted-keys</strong></span></p>
+ </td>
+<td>
+ <p>
+ defines trusted DNSSEC keys.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">view</strong></span></p>
+ </td>
+<td>
+ <p>
+ defines a view.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">zone</strong></span></p>
+ </td>
+<td>
+ <p>
+ defines a zone.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ The <span><strong class="command">logging</strong></span> and
+ <span><strong class="command">options</strong></span> statements may only occur once
+ per
+ configuration.
+ </p>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2574292"></a><span><strong class="command">acl</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">acl</strong></span> acl-name {
+ address_match_list
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="acl"></a><span><strong class="command">acl</strong></span> Statement Definition and
+ Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">acl</strong></span> statement assigns a symbolic
+ name to an address match list. It gets its name from a primary
+ use of address match lists: Access Control Lists (ACLs).
+ </p>
+<p>
+ Note that an address match list's name must be defined
+ with <span><strong class="command">acl</strong></span> before it can be used
+ elsewhere; no forward references are allowed.
+ </p>
+<p>
+ The following ACLs are built-in:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p><span><strong class="command">any</strong></span></p>
+ </td>
+<td>
+ <p>
+ Matches all hosts.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">none</strong></span></p>
+ </td>
+<td>
+ <p>
+ Matches no hosts.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">localhost</strong></span></p>
+ </td>
+<td>
+ <p>
+ Matches the IPv4 and IPv6 addresses of all network
+ interfaces on the system.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">localnets</strong></span></p>
+ </td>
+<td>
+ <p>
+ Matches any host on an IPv4 or IPv6 network
+ for which the system has an interface.
+ Some systems do not provide a way to determine the prefix
+ lengths of
+ local IPv6 addresses.
+ In such a case, <span><strong class="command">localnets</strong></span>
+ only matches the local
+ IPv6 addresses, just like <span><strong class="command">localhost</strong></span>.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2574550"></a><span><strong class="command">controls</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">controls</strong></span> {
+ [ inet ( ip_addr | * ) [ port ip_port ] allow { <em class="replaceable"><code> address_match_list </code></em> }
+ keys { <em class="replaceable"><code>key_list</code></em> }; ]
+ [ inet ...; ]
+ [ unix <em class="replaceable"><code>path</code></em> perm <em class="replaceable"><code>number</code></em> owner <em class="replaceable"><code>number</code></em> group <em class="replaceable"><code>number</code></em> keys { <em class="replaceable"><code>key_list</code></em> }; ]
+ [ unix ...; ]
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="controls_statement_definition_and_usage"></a><span><strong class="command">controls</strong></span> Statement Definition and
+ Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">controls</strong></span> statement declares control
+ channels to be used by system administrators to control the
+ operation of the name server. These control channels are
+ used by the <span><strong class="command">rndc</strong></span> utility to send
+ commands to and retrieve non-DNS results from a name server.
+ </p>
+<p>
+ An <span><strong class="command">inet</strong></span> control channel is a TCP socket
+ listening at the specified <span><strong class="command">ip_port</strong></span> on the
+ specified <span><strong class="command">ip_addr</strong></span>, which can be an IPv4 or IPv6
+ address. An <span><strong class="command">ip_addr</strong></span> of <code class="literal">*</code> (asterisk) is
+ interpreted as the IPv4 wildcard address; connections will be
+ accepted on any of the system's IPv4 addresses.
+ To listen on the IPv6 wildcard address,
+ use an <span><strong class="command">ip_addr</strong></span> of <code class="literal">::</code>.
+ If you will only use <span><strong class="command">rndc</strong></span> on the local host,
+ using the loopback address (<code class="literal">127.0.0.1</code>
+ or <code class="literal">::1</code>) is recommended for maximum security.
+ </p>
+<p>
+ If no port is specified, port 953 is used. The asterisk
+ "<code class="literal">*</code>" cannot be used for <span><strong class="command">ip_port</strong></span>.
+ </p>
+<p>
+ The ability to issue commands over the control channel is
+ restricted by the <span><strong class="command">allow</strong></span> and
+ <span><strong class="command">keys</strong></span> clauses.
+ Connections to the control channel are permitted based on the
+ <span><strong class="command">address_match_list</strong></span>. This is for simple
+ IP address based filtering only; any <span><strong class="command">key_id</strong></span>
+ elements of the <span><strong class="command">address_match_list</strong></span>
+ are ignored.
+ </p>
+<p>
+ A <span><strong class="command">unix</strong></span> control channel is a UNIX domain
+ socket listening at the specified path in the file system.
+ Access to the socket is specified by the <span><strong class="command">perm</strong></span>,
+ <span><strong class="command">owner</strong></span> and <span><strong class="command">group</strong></span> clauses.
+ Note on some platforms (SunOS and Solaris) the permissions
+ (<span><strong class="command">perm</strong></span>) are applied to the parent directory
+ as the permissions on the socket itself are ignored.
+ </p>
+<p>
+ The primary authorization mechanism of the command
+ channel is the <span><strong class="command">key_list</strong></span>, which
+ contains a list of <span><strong class="command">key_id</strong></span>s.
+ Each <span><strong class="command">key_id</strong></span> in the <span><strong class="command">key_list</strong></span>
+ is authorized to execute commands over the control channel.
+ See <a href="Bv9ARM.ch03.html#rndc">Remote Name Daemon Control application</a> in <a href="Bv9ARM.ch03.html#admin_tools" title="Administrative Tools">the section called &#8220;Administrative Tools&#8221;</a>)
+ for information about configuring keys in <span><strong class="command">rndc</strong></span>.
+ </p>
+<p>
+ If no <span><strong class="command">controls</strong></span> statement is present,
+ <span><strong class="command">named</strong></span> will set up a default
+ control channel listening on the loopback address 127.0.0.1
+ and its IPv6 counterpart ::1.
+ In this case, and also when the <span><strong class="command">controls</strong></span> statement
+ is present but does not have a <span><strong class="command">keys</strong></span> clause,
+ <span><strong class="command">named</strong></span> will attempt to load the command channel key
+ from the file <code class="filename">rndc.key</code> in
+ <code class="filename">/etc</code> (or whatever <code class="varname">sysconfdir</code>
+ was specified as when <acronym class="acronym">BIND</acronym> was built).
+ To create a <code class="filename">rndc.key</code> file, run
+ <strong class="userinput"><code>rndc-confgen -a</code></strong>.
+ </p>
+<p>
+ The <code class="filename">rndc.key</code> feature was created to
+ ease the transition of systems from <acronym class="acronym">BIND</acronym> 8,
+ which did not have digital signatures on its command channel
+ messages and thus did not have a <span><strong class="command">keys</strong></span> clause.
+
+ It makes it possible to use an existing <acronym class="acronym">BIND</acronym> 8
+ configuration file in <acronym class="acronym">BIND</acronym> 9 unchanged,
+ and still have <span><strong class="command">rndc</strong></span> work the same way
+ <span><strong class="command">ndc</strong></span> worked in BIND 8, simply by executing the
+ command <strong class="userinput"><code>rndc-confgen -a</code></strong> after BIND 9 is
+ installed.
+ </p>
+<p>
+ Since the <code class="filename">rndc.key</code> feature
+ is only intended to allow the backward-compatible usage of
+ <acronym class="acronym">BIND</acronym> 8 configuration files, this
+ feature does not
+ have a high degree of configurability. You cannot easily change
+ the key name or the size of the secret, so you should make a
+ <code class="filename">rndc.conf</code> with your own key if you
+ wish to change
+ those things. The <code class="filename">rndc.key</code> file
+ also has its
+ permissions set such that only the owner of the file (the user that
+ <span><strong class="command">named</strong></span> is running as) can access it.
+ If you
+ desire greater flexibility in allowing other users to access
+ <span><strong class="command">rndc</strong></span> commands, then you need to create
+ a
+ <code class="filename">rndc.conf</code> file and make it group
+ readable by a group
+ that contains the users who should have access.
+ </p>
+<p>
+ To disable the command channel, use an empty
+ <span><strong class="command">controls</strong></span> statement:
+ <span><strong class="command">controls { };</strong></span>.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2574910"></a><span><strong class="command">include</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">include</strong></span> <em class="replaceable"><code>filename</code></em>;</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2574928"></a><span><strong class="command">include</strong></span> Statement Definition and
+ Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">include</strong></span> statement inserts the
+ specified file at the point where the <span><strong class="command">include</strong></span>
+ statement is encountered. The <span><strong class="command">include</strong></span>
+ statement facilitates the administration of configuration
+ files
+ by permitting the reading or writing of some things but not
+ others. For example, the statement could include private keys
+ that are readable only by the name server.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2575088"></a><span><strong class="command">key</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">key</strong></span> <em class="replaceable"><code>key_id</code></em> {
+ algorithm <em class="replaceable"><code>string</code></em>;
+ secret <em class="replaceable"><code>string</code></em>;
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2575111"></a><span><strong class="command">key</strong></span> Statement Definition and Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">key</strong></span> statement defines a shared
+ secret key for use with TSIG (see <a href="Bv9ARM.ch04.html#tsig" title="TSIG">the section called &#8220;TSIG&#8221;</a>)
+ or the command channel
+ (see <a href="Bv9ARM.ch06.html#controls_statement_definition_and_usage" title="controls Statement Definition and
+ Usage">the section called &#8220;<span><strong class="command">controls</strong></span> Statement Definition and
+ Usage&#8221;</a>).
+ </p>
+<p>
+ The <span><strong class="command">key</strong></span> statement can occur at the
+ top level
+ of the configuration file or inside a <span><strong class="command">view</strong></span>
+ statement. Keys defined in top-level <span><strong class="command">key</strong></span>
+ statements can be used in all views. Keys intended for use in
+ a <span><strong class="command">controls</strong></span> statement
+ (see <a href="Bv9ARM.ch06.html#controls_statement_definition_and_usage" title="controls Statement Definition and
+ Usage">the section called &#8220;<span><strong class="command">controls</strong></span> Statement Definition and
+ Usage&#8221;</a>)
+ must be defined at the top level.
+ </p>
+<p>
+ The <em class="replaceable"><code>key_id</code></em>, also known as the
+ key name, is a domain name uniquely identifying the key. It can
+ be used in a <span><strong class="command">server</strong></span>
+ statement to cause requests sent to that
+ server to be signed with this key, or in address match lists to
+ verify that incoming requests have been signed with a key
+ matching this name, algorithm, and secret.
+ </p>
+<p>
+ The <em class="replaceable"><code>algorithm_id</code></em> is a string
+ that specifies a security/authentication algorithm. Named
+ supports <code class="literal">hmac-md5</code>,
+ <code class="literal">hmac-sha1</code>, <code class="literal">hmac-sha224</code>,
+ <code class="literal">hmac-sha256</code>, <code class="literal">hmac-sha384</code>
+ and <code class="literal">hmac-sha512</code> TSIG authentication.
+ Truncated hashes are supported by appending the minimum
+ number of required bits preceded by a dash, e.g.
+ <code class="literal">hmac-sha1-80</code>. The
+ <em class="replaceable"><code>secret_string</code></em> is the secret
+ to be used by the algorithm, and is treated as a base-64
+ encoded string.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2575202"></a><span><strong class="command">logging</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">logging</strong></span> {
+ [ <span><strong class="command">channel</strong></span> <em class="replaceable"><code>channel_name</code></em> {
+ ( <span><strong class="command">file</strong></span> <em class="replaceable"><code>path_name</code></em>
+ [ <span><strong class="command">versions</strong></span> ( <em class="replaceable"><code>number</code></em> | <span><strong class="command">unlimited</strong></span> ) ]
+ [ <span><strong class="command">size</strong></span> <em class="replaceable"><code>size spec</code></em> ]
+ | <span><strong class="command">syslog</strong></span> <em class="replaceable"><code>syslog_facility</code></em>
+ | <span><strong class="command">stderr</strong></span>
+ | <span><strong class="command">null</strong></span> );
+ [ <span><strong class="command">severity</strong></span> (<code class="option">critical</code> | <code class="option">error</code> | <code class="option">warning</code> | <code class="option">notice</code> |
+ <code class="option">info</code> | <code class="option">debug</code> [ <em class="replaceable"><code>level</code></em> ] | <code class="option">dynamic</code> ); ]
+ [ <span><strong class="command">print-category</strong></span> <code class="option">yes</code> or <code class="option">no</code>; ]
+ [ <span><strong class="command">print-severity</strong></span> <code class="option">yes</code> or <code class="option">no</code>; ]
+ [ <span><strong class="command">print-time</strong></span> <code class="option">yes</code> or <code class="option">no</code>; ]
+ }; ]
+ [ <span><strong class="command">category</strong></span> <em class="replaceable"><code>category_name</code></em> {
+ <em class="replaceable"><code>channel_name</code></em> ; [ <em class="replaceable"><code>channel_name</code></em> ; ... ]
+ }; ]
+ ...
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2575328"></a><span><strong class="command">logging</strong></span> Statement Definition and
+ Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">logging</strong></span> statement configures a
+ wide
+ variety of logging options for the name server. Its <span><strong class="command">channel</strong></span> phrase
+ associates output methods, format options and severity levels with
+ a name that can then be used with the <span><strong class="command">category</strong></span> phrase
+ to select how various classes of messages are logged.
+ </p>
+<p>
+ Only one <span><strong class="command">logging</strong></span> statement is used to
+ define
+ as many channels and categories as are wanted. If there is no <span><strong class="command">logging</strong></span> statement,
+ the logging configuration will be:
+ </p>
+<pre class="programlisting">logging {
+ category default { default_syslog; default_debug; };
+ category unmatched { null; };
+};
+</pre>
+<p>
+ In <acronym class="acronym">BIND</acronym> 9, the logging configuration
+ is only established when
+ the entire configuration file has been parsed. In <acronym class="acronym">BIND</acronym> 8, it was
+ established as soon as the <span><strong class="command">logging</strong></span>
+ statement
+ was parsed. When the server is starting up, all logging messages
+ regarding syntax errors in the configuration file go to the default
+ channels, or to standard error if the "<code class="option">-g</code>" option
+ was specified.
+ </p>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2575380"></a>The <span><strong class="command">channel</strong></span> Phrase</h4></div></div></div>
+<p>
+ All log output goes to one or more <span class="emphasis"><em>channels</em></span>;
+ you can make as many of them as you want.
+ </p>
+<p>
+ Every channel definition must include a destination clause that
+ says whether messages selected for the channel go to a file, to a
+ particular syslog facility, to the standard error stream, or are
+ discarded. It can optionally also limit the message severity level
+ that will be accepted by the channel (the default is
+ <span><strong class="command">info</strong></span>), and whether to include a
+ <span><strong class="command">named</strong></span>-generated time stamp, the
+ category name
+ and/or severity level (the default is not to include any).
+ </p>
+<p>
+ The <span><strong class="command">null</strong></span> destination clause
+ causes all messages sent to the channel to be discarded;
+ in that case, other options for the channel are meaningless.
+ </p>
+<p>
+ The <span><strong class="command">file</strong></span> destination clause directs
+ the channel
+ to a disk file. It can include limitations
+ both on how large the file is allowed to become, and how many
+ versions
+ of the file will be saved each time the file is opened.
+ </p>
+<p>
+ If you use the <span><strong class="command">versions</strong></span> log file
+ option, then
+ <span><strong class="command">named</strong></span> will retain that many backup
+ versions of the file by
+ renaming them when opening. For example, if you choose to keep
+ three old versions
+ of the file <code class="filename">lamers.log</code>, then just
+ before it is opened
+ <code class="filename">lamers.log.1</code> is renamed to
+ <code class="filename">lamers.log.2</code>, <code class="filename">lamers.log.0</code> is renamed
+ to <code class="filename">lamers.log.1</code>, and <code class="filename">lamers.log</code> is
+ renamed to <code class="filename">lamers.log.0</code>.
+ You can say <span><strong class="command">versions unlimited</strong></span> to
+ not limit
+ the number of versions.
+ If a <span><strong class="command">size</strong></span> option is associated with
+ the log file,
+ then renaming is only done when the file being opened exceeds the
+ indicated size. No backup versions are kept by default; any
+ existing
+ log file is simply appended.
+ </p>
+<p>
+ The <span><strong class="command">size</strong></span> option for files is used
+ to limit log
+ growth. If the file ever exceeds the size, then <span><strong class="command">named</strong></span> will
+ stop writing to the file unless it has a <span><strong class="command">versions</strong></span> option
+ associated with it. If backup versions are kept, the files are
+ rolled as
+ described above and a new one begun. If there is no
+ <span><strong class="command">versions</strong></span> option, no more data will
+ be written to the log
+ until some out-of-band mechanism removes or truncates the log to
+ less than the
+ maximum size. The default behavior is not to limit the size of
+ the
+ file.
+ </p>
+<p>
+ Example usage of the <span><strong class="command">size</strong></span> and
+ <span><strong class="command">versions</strong></span> options:
+ </p>
+<pre class="programlisting">channel an_example_channel {
+ file "example.log" versions 3 size 20m;
+ print-time yes;
+ print-category yes;
+};
+</pre>
+<p>
+ The <span><strong class="command">syslog</strong></span> destination clause
+ directs the
+ channel to the system log. Its argument is a
+ syslog facility as described in the <span><strong class="command">syslog</strong></span> man
+ page. Known facilities are <span><strong class="command">kern</strong></span>, <span><strong class="command">user</strong></span>,
+ <span><strong class="command">mail</strong></span>, <span><strong class="command">daemon</strong></span>, <span><strong class="command">auth</strong></span>,
+ <span><strong class="command">syslog</strong></span>, <span><strong class="command">lpr</strong></span>, <span><strong class="command">news</strong></span>,
+ <span><strong class="command">uucp</strong></span>, <span><strong class="command">cron</strong></span>, <span><strong class="command">authpriv</strong></span>,
+ <span><strong class="command">ftp</strong></span>, <span><strong class="command">local0</strong></span>, <span><strong class="command">local1</strong></span>,
+ <span><strong class="command">local2</strong></span>, <span><strong class="command">local3</strong></span>, <span><strong class="command">local4</strong></span>,
+ <span><strong class="command">local5</strong></span>, <span><strong class="command">local6</strong></span> and
+ <span><strong class="command">local7</strong></span>, however not all facilities
+ are supported on
+ all operating systems.
+ How <span><strong class="command">syslog</strong></span> will handle messages
+ sent to
+ this facility is described in the <span><strong class="command">syslog.conf</strong></span> man
+ page. If you have a system which uses a very old version of <span><strong class="command">syslog</strong></span> that
+ only uses two arguments to the <span><strong class="command">openlog()</strong></span> function,
+ then this clause is silently ignored.
+ </p>
+<p>
+ The <span><strong class="command">severity</strong></span> clause works like <span><strong class="command">syslog</strong></span>'s
+ "priorities", except that they can also be used if you are writing
+ straight to a file rather than using <span><strong class="command">syslog</strong></span>.
+ Messages which are not at least of the severity level given will
+ not be selected for the channel; messages of higher severity
+ levels
+ will be accepted.
+ </p>
+<p>
+ If you are using <span><strong class="command">syslog</strong></span>, then the <span><strong class="command">syslog.conf</strong></span> priorities
+ will also determine what eventually passes through. For example,
+ defining a channel facility and severity as <span><strong class="command">daemon</strong></span> and <span><strong class="command">debug</strong></span> but
+ only logging <span><strong class="command">daemon.warning</strong></span> via <span><strong class="command">syslog.conf</strong></span> will
+ cause messages of severity <span><strong class="command">info</strong></span> and
+ <span><strong class="command">notice</strong></span> to
+ be dropped. If the situation were reversed, with <span><strong class="command">named</strong></span> writing
+ messages of only <span><strong class="command">warning</strong></span> or higher,
+ then <span><strong class="command">syslogd</strong></span> would
+ print all messages it received from the channel.
+ </p>
+<p>
+ The <span><strong class="command">stderr</strong></span> destination clause
+ directs the
+ channel to the server's standard error stream. This is intended
+ for
+ use when the server is running as a foreground process, for
+ example
+ when debugging a configuration.
+ </p>
+<p>
+ The server can supply extensive debugging information when
+ it is in debugging mode. If the server's global debug level is
+ greater
+ than zero, then debugging mode will be active. The global debug
+ level is set either by starting the <span><strong class="command">named</strong></span> server
+ with the <code class="option">-d</code> flag followed by a positive integer,
+ or by running <span><strong class="command">rndc trace</strong></span>.
+ The global debug level
+ can be set to zero, and debugging mode turned off, by running <span><strong class="command">rndc
+notrace</strong></span>. All debugging messages in the server have a debug
+ level, and higher debug levels give more detailed output. Channels
+ that specify a specific debug severity, for example:
+ </p>
+<pre class="programlisting">channel specific_debug_level {
+ file "foo";
+ severity debug 3;
+};
+</pre>
+<p>
+ will get debugging output of level 3 or less any time the
+ server is in debugging mode, regardless of the global debugging
+ level. Channels with <span><strong class="command">dynamic</strong></span>
+ severity use the
+ server's global debug level to determine what messages to print.
+ </p>
+<p>
+ If <span><strong class="command">print-time</strong></span> has been turned on,
+ then
+ the date and time will be logged. <span><strong class="command">print-time</strong></span> may
+ be specified for a <span><strong class="command">syslog</strong></span> channel,
+ but is usually
+ pointless since <span><strong class="command">syslog</strong></span> also prints
+ the date and
+ time. If <span><strong class="command">print-category</strong></span> is
+ requested, then the
+ category of the message will be logged as well. Finally, if <span><strong class="command">print-severity</strong></span> is
+ on, then the severity level of the message will be logged. The <span><strong class="command">print-</strong></span> options may
+ be used in any combination, and will always be printed in the
+ following
+ order: time, category, severity. Here is an example where all
+ three <span><strong class="command">print-</strong></span> options
+ are on:
+ </p>
+<p>
+ <code class="computeroutput">28-Feb-2000 15:05:32.863 general: notice: running</code>
+ </p>
+<p>
+ There are four predefined channels that are used for
+ <span><strong class="command">named</strong></span>'s default logging as follows.
+ How they are
+ used is described in <a href="Bv9ARM.ch06.html#the_category_phrase" title="The category Phrase">the section called &#8220;The <span><strong class="command">category</strong></span> Phrase&#8221;</a>.
+ </p>
+<pre class="programlisting">channel default_syslog {
+ syslog daemon; // send to syslog's daemon
+ // facility
+ severity info; // only send priority info
+ // and higher
+};
+
+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
+};
+
+channel default_stderr {
+ stderr; // writes to stderr
+ severity info; // only send priority info
+ // and higher
+};
+
+channel null {
+ null; // toss anything sent to
+ // this channel
+};
+</pre>
+<p>
+ The <span><strong class="command">default_debug</strong></span> channel has the
+ special
+ property that it only produces output when the server's debug
+ level is
+ nonzero. It normally writes to a file called <code class="filename">named.run</code>
+ in the server's working directory.
+ </p>
+<p>
+ For security reasons, when the "<code class="option">-u</code>"
+ command line option is used, the <code class="filename">named.run</code> file
+ is created only after <span><strong class="command">named</strong></span> has
+ changed to the
+ new UID, and any debug output generated while <span><strong class="command">named</strong></span> is
+ starting up and still running as root is discarded. If you need
+ to capture this output, you must run the server with the "<code class="option">-g</code>"
+ option and redirect standard error to a file.
+ </p>
+<p>
+ Once a channel is defined, it cannot be redefined. Thus you
+ cannot alter the built-in channels directly, but you can modify
+ the default logging by pointing categories at channels you have
+ defined.
+ </p>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="the_category_phrase"></a>The <span><strong class="command">category</strong></span> Phrase</h4></div></div></div>
+<p>
+ There are many categories, so you can send the logs you want
+ to see wherever you want, without seeing logs you don't want. If
+ you don't specify a list of channels for a category, then log
+ messages
+ in that category will be sent to the <span><strong class="command">default</strong></span> category
+ instead. If you don't specify a default category, the following
+ "default default" is used:
+ </p>
+<pre class="programlisting">category default { default_syslog; default_debug; };
+</pre>
+<p>
+ As an example, let's say you want to log security events to
+ a file, but you also want keep the default logging behavior. You'd
+ specify the following:
+ </p>
+<pre class="programlisting">channel my_security_channel {
+ file "my_security_file";
+ severity info;
+};
+category security {
+ my_security_channel;
+ default_syslog;
+ default_debug;
+};</pre>
+<p>
+ To discard all messages in a category, specify the <span><strong class="command">null</strong></span> channel:
+ </p>
+<pre class="programlisting">category xfer-out { null; };
+category notify { null; };
+</pre>
+<p>
+ Following are the available categories and brief descriptions
+ of the types of log information they contain. More
+ categories may be added in future <acronym class="acronym">BIND</acronym> releases.
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p><span><strong class="command">default</strong></span></p>
+ </td>
+<td>
+ <p>
+ The default category defines the logging
+ options for those categories where no specific
+ configuration has been
+ defined.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">general</strong></span></p>
+ </td>
+<td>
+ <p>
+ The catch-all. Many things still aren't
+ classified into categories, and they all end up here.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">database</strong></span></p>
+ </td>
+<td>
+ <p>
+ Messages relating to the databases used
+ internally by the name server to store zone and cache
+ data.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">security</strong></span></p>
+ </td>
+<td>
+ <p>
+ Approval and denial of requests.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">config</strong></span></p>
+ </td>
+<td>
+ <p>
+ Configuration file parsing and processing.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">resolver</strong></span></p>
+ </td>
+<td>
+ <p>
+ DNS resolution, such as the recursive
+ lookups performed on behalf of clients by a caching name
+ server.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">xfer-in</strong></span></p>
+ </td>
+<td>
+ <p>
+ Zone transfers the server is receiving.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">xfer-out</strong></span></p>
+ </td>
+<td>
+ <p>
+ Zone transfers the server is sending.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">notify</strong></span></p>
+ </td>
+<td>
+ <p>
+ The NOTIFY protocol.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">client</strong></span></p>
+ </td>
+<td>
+ <p>
+ Processing of client requests.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">unmatched</strong></span></p>
+ </td>
+<td>
+ <p>
+ Messages that named was unable to determine the
+ class of or for which there was no matching <span><strong class="command">view</strong></span>.
+ A one line summary is also logged to the <span><strong class="command">client</strong></span> category.
+ This category is best sent to a file or stderr, by
+ default it is sent to
+ the <span><strong class="command">null</strong></span> channel.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">network</strong></span></p>
+ </td>
+<td>
+ <p>
+ Network operations.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">update</strong></span></p>
+ </td>
+<td>
+ <p>
+ Dynamic updates.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">update-security</strong></span></p>
+ </td>
+<td>
+ <p>
+ Approval and denial of update requests.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">queries</strong></span></p>
+ </td>
+<td>
+ <p>
+ Specify where queries should be logged to.
+ </p>
+ <p>
+ At startup, specifying the category <span><strong class="command">queries</strong></span> will also
+ enable query logging unless <span><strong class="command">querylog</strong></span> option has been
+ specified.
+ </p>
+
+ <p>
+ 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
+ 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).
+ </p>
+
+ <p>
+ <code class="computeroutput">client 127.0.0.1#62536: query: www.example.com IN AAAA +SE</code>
+ </p>
+ <p>
+ <code class="computeroutput">client ::1#62537: query: www.example.net IN AAAA -SE</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">dispatch</strong></span></p>
+ </td>
+<td>
+ <p>
+ Dispatching of incoming packets to the
+ server modules where they are to be processed.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">dnssec</strong></span></p>
+ </td>
+<td>
+ <p>
+ DNSSEC and TSIG protocol processing.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">lame-servers</strong></span></p>
+ </td>
+<td>
+ <p>
+ Lame servers. These are misconfigurations
+ in remote servers, discovered by BIND 9 when trying to
+ query
+ those servers during resolution.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">delegation-only</strong></span></p>
+ </td>
+<td>
+ <p>
+ Delegation only. Logs queries that have
+ been forced to NXDOMAIN as the result of a
+ delegation-only zone or
+ a <span><strong class="command">delegation-only</strong></span> in a
+ hint or stub zone declaration.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">edns-disabled</strong></span></p>
+ </td>
+<td>
+ <p>
+ Log queries that have been forced to use plain
+ DNS due to timeouts. This is often due to
+ the remote servers not being RFC 1034 compliant
+ (not always returning FORMERR or similar to
+ EDNS queries and other extensions to the DNS
+ when they are not understood). In other words, this is
+ targeted at servers that fail to respond to
+ DNS queries that they don't understand.
+ </p>
+ <p>
+ Note: the log message can also be due to
+ packet loss. Before reporting servers for
+ non-RFC 1034 compliance they should be re-tested
+ to determine the nature of the non-compliance.
+ This testing should prevent or reduce the
+ number of false-positive reports.
+ </p>
+ <p>
+ Note: eventually named will have to stop
+ treating such timeouts as due to RFC 1034 non
+ compliance and start treating it as plain
+ packet loss. Falsely classifying packet
+ loss as due to RFC 1034 non compliance impacts
+ on DNSSEC validation which requires EDNS for
+ the DNSSEC records to be returned.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2576640"></a><span><strong class="command">lwres</strong></span> Statement Grammar</h3></div></div></div>
+<p>
+ This is the grammar of the <span><strong class="command">lwres</strong></span>
+ statement in the <code class="filename">named.conf</code> file:
+ </p>
+<pre class="programlisting"><span><strong class="command">lwres</strong></span> {
+ [<span class="optional"> listen-on { <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; [<span class="optional"> <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; ... </span>] }; </span>]
+ [<span class="optional"> view <em class="replaceable"><code>view_name</code></em>; </span>]
+ [<span class="optional"> search { <em class="replaceable"><code>domain_name</code></em> ; [<span class="optional"> <em class="replaceable"><code>domain_name</code></em> ; ... </span>] }; </span>]
+ [<span class="optional"> ndots <em class="replaceable"><code>number</code></em>; </span>]
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2576713"></a><span><strong class="command">lwres</strong></span> Statement Definition and Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">lwres</strong></span> statement configures the
+ name
+ server to also act as a lightweight resolver server. (See
+ <a href="Bv9ARM.ch05.html#lwresd" title="Running a Resolver Daemon">the section called &#8220;Running a Resolver Daemon&#8221;</a>.) There may be multiple
+ <span><strong class="command">lwres</strong></span> statements configuring
+ lightweight resolver servers with different properties.
+ </p>
+<p>
+ The <span><strong class="command">listen-on</strong></span> statement specifies a
+ list of
+ addresses (and ports) that this instance of a lightweight resolver
+ daemon
+ should accept requests on. If no port is specified, port 921 is
+ used.
+ If this statement is omitted, requests will be accepted on
+ 127.0.0.1,
+ port 921.
+ </p>
+<p>
+ The <span><strong class="command">view</strong></span> statement binds this
+ instance of a
+ lightweight resolver daemon to a view in the DNS namespace, so that
+ the
+ response will be constructed in the same manner as a normal DNS
+ query
+ matching this view. If this statement is omitted, the default view
+ is
+ used, and if there is no default view, an error is triggered.
+ </p>
+<p>
+ The <span><strong class="command">search</strong></span> statement is equivalent to
+ the
+ <span><strong class="command">search</strong></span> statement in
+ <code class="filename">/etc/resolv.conf</code>. It provides a
+ list of domains
+ which are appended to relative names in queries.
+ </p>
+<p>
+ The <span><strong class="command">ndots</strong></span> statement is equivalent to
+ the
+ <span><strong class="command">ndots</strong></span> statement in
+ <code class="filename">/etc/resolv.conf</code>. It indicates the
+ minimum
+ number of dots in a relative domain name that should result in an
+ exact match lookup before search path elements are appended.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2576777"></a><span><strong class="command">masters</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting">
+<span><strong class="command">masters</strong></span> <em class="replaceable"><code>name</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] { ( <em class="replaceable"><code>masters_list</code></em> | <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] [<span class="optional">key <em class="replaceable"><code>key</code></em></span>] ) ; [<span class="optional">...</span>] };
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2576889"></a><span><strong class="command">masters</strong></span> Statement Definition and
+ Usage</h3></div></div></div>
+<p><span><strong class="command">masters</strong></span>
+ lists allow for a common set of masters to be easily used by
+ multiple stub and slave zones.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2576904"></a><span><strong class="command">options</strong></span> Statement Grammar</h3></div></div></div>
+<p>
+ This is the grammar of the <span><strong class="command">options</strong></span>
+ statement in the <code class="filename">named.conf</code> file:
+ </p>
+<pre class="programlisting"><span><strong class="command">options</strong></span> {
+ [<span class="optional"> version <em class="replaceable"><code>version_string</code></em>; </span>]
+ [<span class="optional"> hostname <em class="replaceable"><code>hostname_string</code></em>; </span>]
+ [<span class="optional"> server-id <em class="replaceable"><code>server_id_string</code></em>; </span>]
+ [<span class="optional"> directory <em class="replaceable"><code>path_name</code></em>; </span>]
+ [<span class="optional"> key-directory <em class="replaceable"><code>path_name</code></em>; </span>]
+ [<span class="optional"> named-xfer <em class="replaceable"><code>path_name</code></em>; </span>]
+ [<span class="optional"> tkey-gssapi-credential <em class="replaceable"><code>principal</code></em>; </span>]
+ [<span class="optional"> tkey-domain <em class="replaceable"><code>domainname</code></em>; </span>]
+ [<span class="optional"> tkey-dhkey <em class="replaceable"><code>key_name</code></em> <em class="replaceable"><code>key_tag</code></em>; </span>]
+ [<span class="optional"> cache-file <em class="replaceable"><code>path_name</code></em>; </span>]
+ [<span class="optional"> dump-file <em class="replaceable"><code>path_name</code></em>; </span>]
+ [<span class="optional"> memstatistics <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> memstatistics-file <em class="replaceable"><code>path_name</code></em>; </span>]
+ [<span class="optional"> pid-file <em class="replaceable"><code>path_name</code></em>; </span>]
+ [<span class="optional"> recursing-file <em class="replaceable"><code>path_name</code></em>; </span>]
+ [<span class="optional"> statistics-file <em class="replaceable"><code>path_name</code></em>; </span>]
+ [<span class="optional"> zone-statistics <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> auth-nxdomain <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> deallocate-on-exit <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> dialup <em class="replaceable"><code>dialup_option</code></em>; </span>]
+ [<span class="optional"> fake-iquery <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> fetch-glue <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> flush-zones-on-shutdown <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> has-old-clients <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> host-statistics <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> host-statistics-max <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> minimal-responses <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> multiple-cnames <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> notify <em class="replaceable"><code>yes_or_no</code></em> | <em class="replaceable"><code>explicit</code></em> | <em class="replaceable"><code>master-only</code></em>; </span>]
+ [<span class="optional"> recursion <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> rfc2308-type1 <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> use-id-pool <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> maintain-ixfr-base <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> ixfr-from-differences (<em class="replaceable"><code>yes_or_no</code></em> | <code class="constant">master</code> | <code class="constant">slave</code>); </span>]
+ [<span class="optional"> dnssec-enable <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> dnssec-validation <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> dnssec-lookaside <em class="replaceable"><code>domain</code></em> trust-anchor <em class="replaceable"><code>domain</code></em>; </span>]
+ [<span class="optional"> dnssec-must-be-secure <em class="replaceable"><code>domain yes_or_no</code></em>; </span>]
+ [<span class="optional"> dnssec-accept-expired <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> forward ( <em class="replaceable"><code>only</code></em> | <em class="replaceable"><code>first</code></em> ); </span>]
+ [<span class="optional"> forwarders { [<span class="optional"> <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; ... </span>] }; </span>]
+ [<span class="optional"> dual-stack-servers [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] {
+ ( <em class="replaceable"><code>domain_name</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] |
+ <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ) ;
+ ... }; </span>]
+ [<span class="optional"> check-names ( <em class="replaceable"><code>master</code></em> | <em class="replaceable"><code>slave</code></em> | <em class="replaceable"><code>response</code></em> )
+ ( <em class="replaceable"><code>warn</code></em> | <em class="replaceable"><code>fail</code></em> | <em class="replaceable"><code>ignore</code></em> ); </span>]
+ [<span class="optional"> check-mx ( <em class="replaceable"><code>warn</code></em> | <em class="replaceable"><code>fail</code></em> | <em class="replaceable"><code>ignore</code></em> ); </span>]
+ [<span class="optional"> check-wildcard <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> check-integrity <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> check-mx-cname ( <em class="replaceable"><code>warn</code></em> | <em class="replaceable"><code>fail</code></em> | <em class="replaceable"><code>ignore</code></em> ); </span>]
+ [<span class="optional"> check-srv-cname ( <em class="replaceable"><code>warn</code></em> | <em class="replaceable"><code>fail</code></em> | <em class="replaceable"><code>ignore</code></em> ); </span>]
+ [<span class="optional"> check-sibling <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> allow-notify { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-query { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-query-on { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-query-cache { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-query-cache-on { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-transfer { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-recursion { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-recursion-on { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-update { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-update-forwarding { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> update-check-ksk <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> try-tcp-refresh <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> allow-v6-synthesis { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> blackhole { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> use-v4-udp-ports { <em class="replaceable"><code>port_list</code></em> }; </span>]
+ [<span class="optional"> avoid-v4-udp-ports { <em class="replaceable"><code>port_list</code></em> }; </span>]
+ [<span class="optional"> use-v6-udp-ports { <em class="replaceable"><code>port_list</code></em> }; </span>]
+ [<span class="optional"> avoid-v6-udp-ports { <em class="replaceable"><code>port_list</code></em> }; </span>]
+ [<span class="optional"> listen-on [<span class="optional"> port <em class="replaceable"><code>ip_port</code></em> </span>] { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> listen-on-v6 [<span class="optional"> port <em class="replaceable"><code>ip_port</code></em> </span>] { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> query-source ( ( <em class="replaceable"><code>ip4_addr</code></em> | <em class="replaceable"><code>*</code></em> )
+ [<span class="optional"> port ( <em class="replaceable"><code>ip_port</code></em> | <em class="replaceable"><code>*</code></em> ) </span>] |
+ [<span class="optional"> address ( <em class="replaceable"><code>ip4_addr</code></em> | <em class="replaceable"><code>*</code></em> ) </span>]
+ [<span class="optional"> port ( <em class="replaceable"><code>ip_port</code></em> | <em class="replaceable"><code>*</code></em> ) </span>] ) ; </span>]
+ [<span class="optional"> query-source-v6 ( ( <em class="replaceable"><code>ip6_addr</code></em> | <em class="replaceable"><code>*</code></em> )
+ [<span class="optional"> port ( <em class="replaceable"><code>ip_port</code></em> | <em class="replaceable"><code>*</code></em> ) </span>] |
+ [<span class="optional"> address ( <em class="replaceable"><code>ip6_addr</code></em> | <em class="replaceable"><code>*</code></em> ) </span>]
+ [<span class="optional"> port ( <em class="replaceable"><code>ip_port</code></em> | <em class="replaceable"><code>*</code></em> ) </span>] ) ; </span>]
+ [<span class="optional"> use-queryport-pool <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> queryport-pool-ports <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> queryport-pool-interval <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> max-transfer-time-in <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> max-transfer-time-out <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> max-transfer-idle-in <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> max-transfer-idle-out <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> tcp-clients <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> reserved-sockets <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> recursive-clients <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> serial-query-rate <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> serial-queries <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> tcp-listen-queue <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> transfer-format <em class="replaceable"><code>( one-answer | many-answers )</code></em>; </span>]
+ [<span class="optional"> transfers-in <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> transfers-out <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> transfers-per-ns <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> transfer-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> transfer-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> alt-transfer-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> alt-transfer-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> use-alt-transfer-source <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> notify-delay <em class="replaceable"><code>seconds</code></em> ; </span>]
+ [<span class="optional"> notify-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> notify-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> notify-to-soa <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> also-notify { <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; [<span class="optional"> <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; ... </span>] }; </span>]
+ [<span class="optional"> max-ixfr-log-size <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> max-journal-size <em class="replaceable"><code>size_spec</code></em>; </span>]
+ [<span class="optional"> coresize <em class="replaceable"><code>size_spec</code></em> ; </span>]
+ [<span class="optional"> datasize <em class="replaceable"><code>size_spec</code></em> ; </span>]
+ [<span class="optional"> files <em class="replaceable"><code>size_spec</code></em> ; </span>]
+ [<span class="optional"> stacksize <em class="replaceable"><code>size_spec</code></em> ; </span>]
+ [<span class="optional"> cleaning-interval <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> heartbeat-interval <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> interface-interval <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> statistics-interval <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> topology { <em class="replaceable"><code>address_match_list</code></em> }</span>];
+ [<span class="optional"> sortlist { <em class="replaceable"><code>address_match_list</code></em> }</span>];
+ [<span class="optional"> rrset-order { <em class="replaceable"><code>order_spec</code></em> ; [<span class="optional"> <em class="replaceable"><code>order_spec</code></em> ; ... </span>] </span>] };
+ [<span class="optional"> lame-ttl <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> max-ncache-ttl <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> max-cache-ttl <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> sig-validity-interval <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> sig-signing-nodes <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> sig-signing-signatures <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> sig-signing-type <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> min-roots <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> use-ixfr <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> provide-ixfr <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> request-ixfr <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> treat-cr-as-space <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> min-refresh-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-refresh-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> min-retry-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-retry-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> port <em class="replaceable"><code>ip_port</code></em>; </span>]
+ [<span class="optional"> additional-from-auth <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> additional-from-cache <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> random-device <em class="replaceable"><code>path_name</code></em> ; </span>]
+ [<span class="optional"> max-cache-size <em class="replaceable"><code>size_spec</code></em> ; </span>]
+ [<span class="optional"> match-mapped-addresses <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> preferred-glue ( <em class="replaceable"><code>A</code></em> | <em class="replaceable"><code>AAAA</code></em> | <em class="replaceable"><code>NONE</code></em> ); </span>]
+ [<span class="optional"> edns-udp-size <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> max-udp-size <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> root-delegation-only [<span class="optional"> exclude { <em class="replaceable"><code>namelist</code></em> } </span>] ; </span>]
+ [<span class="optional"> querylog <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> disable-algorithms <em class="replaceable"><code>domain</code></em> { <em class="replaceable"><code>algorithm</code></em>; [<span class="optional"> <em class="replaceable"><code>algorithm</code></em>; </span>] }; </span>]
+ [<span class="optional"> acache-enable <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> acache-cleaning-interval <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> max-acache-size <em class="replaceable"><code>size_spec</code></em> ; </span>]
+ [<span class="optional"> clients-per-query <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-clients-per-query <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> masterfile-format (<code class="constant">text</code>|<code class="constant">raw</code>) ; </span>]
+ [<span class="optional"> empty-server <em class="replaceable"><code>name</code></em> ; </span>]
+ [<span class="optional"> empty-contact <em class="replaceable"><code>name</code></em> ; </span>]
+ [<span class="optional"> empty-zones-enable <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> disable-empty-zone <em class="replaceable"><code>zone_name</code></em> ; </span>]
+ [<span class="optional"> zero-no-soa-ttl <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> zero-no-soa-ttl-cache <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="options"></a><span><strong class="command">options</strong></span> Statement Definition and
+ Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">options</strong></span> statement sets up global
+ options
+ to be used by <acronym class="acronym">BIND</acronym>. This statement
+ may appear only
+ once in a configuration file. If there is no <span><strong class="command">options</strong></span>
+ statement, an options block with each option set to its default will
+ be used.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">directory</strong></span></span></dt>
+<dd><p>
+ The working directory of the server.
+ Any non-absolute pathnames in the configuration file will be
+ taken
+ as relative to this directory. The default location for most
+ server
+ output files (e.g. <code class="filename">named.run</code>)
+ is this directory.
+ If a directory is not specified, the working directory
+ defaults to `<code class="filename">.</code>', the directory from
+ which the server
+ was started. The directory specified should be an absolute
+ path.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">key-directory</strong></span></span></dt>
+<dd><p>
+ When performing dynamic update of secure zones, the
+ directory where the public and private key files should be
+ found,
+ if different than the current working directory. The
+ directory specified
+ must be an absolute path.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">named-xfer</strong></span></span></dt>
+<dd><p>
+ <span class="emphasis"><em>This option is obsolete.</em></span> It
+ was used in <acronym class="acronym">BIND</acronym> 8 to specify
+ the pathname to the <span><strong class="command">named-xfer</strong></span>
+ program. In <acronym class="acronym">BIND</acronym> 9, no separate
+ <span><strong class="command">named-xfer</strong></span> program is needed;
+ its functionality is built into the name server.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">tkey-gssapi-credential</strong></span></span></dt>
+<dd><p>
+ 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 <code class="filename">/etc/krb5.keytab</code>.
+ Normally this principal is of the form
+ "<strong class="userinput"><code>dns/</code></strong><code class="varname">server.domain</code>".
+ To use GSS-TSIG, <span><strong class="command">tkey-domain</strong></span>
+ must also be set.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">tkey-domain</strong></span></span></dt>
+<dd><p>
+ The domain appended to the names of all shared keys
+ generated with <span><strong class="command">TKEY</strong></span>. When a
+ client requests a <span><strong class="command">TKEY</strong></span> exchange,
+ it may or may not specify the desired name for the
+ key. If present, the name of the shared key will
+ will be <code class="varname">client specified part</code> +
+ <code class="varname">tkey-domain</code>. Otherwise, the
+ name of the shared key will be <code class="varname">random hex
+ digits</code> + <code class="varname">tkey-domain</code>.
+ In most cases, the <span><strong class="command">domainname</strong></span>
+ should be the server's domain name, or an otherwise
+ non-existent subdomain like
+ "_tkey.<code class="varname">domainname</code>". If you are
+ using GSS-TSIG, this variable must be defined.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">tkey-dhkey</strong></span></span></dt>
+<dd><p>
+ The Diffie-Hellman key used by the server
+ to generate shared keys with clients using the Diffie-Hellman
+ mode
+ of <span><strong class="command">TKEY</strong></span>. The server must be
+ able to load the
+ public and private keys from files in the working directory.
+ In
+ most cases, the keyname should be the server's host name.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">cache-file</strong></span></span></dt>
+<dd><p>
+ This is for testing only. Do not use.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">dump-file</strong></span></span></dt>
+<dd><p>
+ The pathname of the file the server dumps
+ the database to when instructed to do so with
+ <span><strong class="command">rndc dumpdb</strong></span>.
+ If not specified, the default is <code class="filename">named_dump.db</code>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">memstatistics-file</strong></span></span></dt>
+<dd><p>
+ The pathname of the file the server writes memory
+ usage statistics to on exit. If not specified,
+ the default is <code class="filename">named.memstats</code>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">pid-file</strong></span></span></dt>
+<dd><p>
+ The pathname of the file the server writes its process ID
+ in. If not specified, the default is
+ <code class="filename">/var/run/named/named.pid</code>.
+ The pid-file is used by programs that want to send signals to
+ the running
+ name server. Specifying <span><strong class="command">pid-file none</strong></span> disables the
+ use of a PID file &#8212; no file will be written and any
+ existing one will be removed. Note that <span><strong class="command">none</strong></span>
+ is a keyword, not a filename, and therefore is not enclosed
+ in
+ double quotes.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">recursing-file</strong></span></span></dt>
+<dd><p>
+ The pathname of the file the server dumps
+ the queries that are currently recursing when instructed
+ to do so with <span><strong class="command">rndc recursing</strong></span>.
+ If not specified, the default is <code class="filename">named.recursing</code>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">statistics-file</strong></span></span></dt>
+<dd><p>
+ The pathname of the file the server appends statistics
+ to when instructed to do so using <span><strong class="command">rndc stats</strong></span>.
+ If not specified, the default is <code class="filename">named.stats</code> in the
+ server's current directory. The format of the file is
+ described
+ in <a href="Bv9ARM.ch06.html#statsfile" title="The Statistics File">the section called &#8220;The Statistics File&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">port</strong></span></span></dt>
+<dd><p>
+ The UDP/TCP port number the server uses for
+ receiving and sending DNS protocol traffic.
+ The default is 53. This option is mainly intended for server
+ testing;
+ a server using a port other than 53 will not be able to
+ communicate with
+ the global DNS.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">random-device</strong></span></span></dt>
+<dd><p>
+ The source of entropy to be used by the server. Entropy is
+ primarily needed
+ for DNSSEC operations, such as TKEY transactions and dynamic
+ update of signed
+ zones. This options specifies the device (or file) from which
+ to read
+ entropy. If this is a file, operations requiring entropy will
+ fail when the
+ file has been exhausted. If not specified, the default value
+ is
+ <code class="filename">/dev/random</code>
+ (or equivalent) when present, and none otherwise. The
+ <span><strong class="command">random-device</strong></span> option takes
+ effect during
+ the initial configuration load at server startup time and
+ is ignored on subsequent reloads.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">preferred-glue</strong></span></span></dt>
+<dd><p>
+ If specified, the listed type (A or AAAA) will be emitted
+ before other glue
+ in the additional section of a query response.
+ The default is not to prefer any type (NONE).
+ </p></dd>
+<dt><span class="term"><span><strong class="command">root-delegation-only</strong></span></span></dt>
+<dd>
+<p>
+ Turn on enforcement of delegation-only in TLDs (top level domains) and root zones
+ with an optional
+ exclude list.
+ </p>
+<p>
+ Note some TLDs are not delegation only (e.g. "DE", "LV", "US"
+ and "MUSEUM").
+ </p>
+<pre class="programlisting">
+options {
+ root-delegation-only exclude { "de"; "lv"; "us"; "museum"; };
+};
+</pre>
+</dd>
+<dt><span class="term"><span><strong class="command">disable-algorithms</strong></span></span></dt>
+<dd><p>
+ Disable the specified DNSSEC algorithms at and below the
+ specified name.
+ Multiple <span><strong class="command">disable-algorithms</strong></span>
+ statements are allowed.
+ Only the most specific will be applied.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">dnssec-lookaside</strong></span></span></dt>
+<dd><p>
+ When set, <span><strong class="command">dnssec-lookaside</strong></span>
+ 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 <span><strong class="command">dnssec-lookaside</strong></span>, 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
+ record does) the DNSKEY RRset is deemed to be trusted.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">dnssec-must-be-secure</strong></span></span></dt>
+<dd><p>
+ Specify hierarchies which must be or may not be secure (signed and
+ validated).
+ If <strong class="userinput"><code>yes</code></strong>, then named will only accept
+ answers if they
+ are secure.
+ If <strong class="userinput"><code>no</code></strong>, then normal dnssec validation
+ applies
+ allowing for insecure answers to be accepted.
+ The specified domain must be under a <span><strong class="command">trusted-key</strong></span> or
+ <span><strong class="command">dnssec-lookaside</strong></span> must be
+ active.
+ </p></dd>
+</dl></div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="boolean_options"></a>Boolean Options</h4></div></div></div>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">auth-nxdomain</strong></span></span></dt>
+<dd><p>
+ If <strong class="userinput"><code>yes</code></strong>, then the <span><strong class="command">AA</strong></span> bit
+ is always set on NXDOMAIN responses, even if the server is
+ not actually
+ authoritative. The default is <strong class="userinput"><code>no</code></strong>;
+ this is
+ a change from <acronym class="acronym">BIND</acronym> 8. If you
+ are using very old DNS software, you
+ may need to set it to <strong class="userinput"><code>yes</code></strong>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">deallocate-on-exit</strong></span></span></dt>
+<dd><p>
+ This option was used in <acronym class="acronym">BIND</acronym>
+ 8 to enable checking
+ for memory leaks on exit. <acronym class="acronym">BIND</acronym> 9 ignores the option and always performs
+ the checks.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">memstatistics</strong></span></span></dt>
+<dd><p>
+ Write memory statistics to the file specified by
+ <span><strong class="command">memstatistics-file</strong></span> at exit.
+ The default is <strong class="userinput"><code>no</code></strong> unless
+ '-m record' is specified on the command line in
+ which case it is <strong class="userinput"><code>yes</code></strong>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">dialup</strong></span></span></dt>
+<dd>
+<p>
+ If <strong class="userinput"><code>yes</code></strong>, then the
+ server treats all zones as if they are doing zone transfers
+ across
+ a dial-on-demand dialup link, which can be brought up by
+ traffic
+ originating from this server. This has different effects
+ according
+ to zone type and concentrates the zone maintenance so that
+ it all
+ happens in a short interval, once every <span><strong class="command">heartbeat-interval</strong></span> and
+ hopefully during the one call. It also suppresses some of
+ the normal
+ zone maintenance traffic. The default is <strong class="userinput"><code>no</code></strong>.
+ </p>
+<p>
+ The <span><strong class="command">dialup</strong></span> option
+ may also be specified in the <span><strong class="command">view</strong></span> and
+ <span><strong class="command">zone</strong></span> statements,
+ in which case it overrides the global <span><strong class="command">dialup</strong></span>
+ option.
+ </p>
+<p>
+ If the zone is a master zone, then the server will send out a
+ NOTIFY
+ request to all the slaves (default). This should trigger the
+ zone serial
+ number check in the slave (providing it supports NOTIFY)
+ allowing the slave
+ to verify the zone while the connection is active.
+ The set of servers to which NOTIFY is sent can be controlled
+ by
+ <span><strong class="command">notify</strong></span> and <span><strong class="command">also-notify</strong></span>.
+ </p>
+<p>
+ If the
+ zone is a slave or stub zone, then the server will suppress
+ the regular
+ "zone up to date" (refresh) queries and only perform them
+ when the
+ <span><strong class="command">heartbeat-interval</strong></span> expires in
+ addition to sending
+ NOTIFY requests.
+ </p>
+<p>
+ Finer control can be achieved by using
+ <strong class="userinput"><code>notify</code></strong> which only sends NOTIFY
+ messages,
+ <strong class="userinput"><code>notify-passive</code></strong> which sends NOTIFY
+ messages and
+ suppresses the normal refresh queries, <strong class="userinput"><code>refresh</code></strong>
+ which suppresses normal refresh processing and sends refresh
+ queries
+ when the <span><strong class="command">heartbeat-interval</strong></span>
+ expires, and
+ <strong class="userinput"><code>passive</code></strong> which just disables normal
+ refresh
+ processing.
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ dialup mode
+ </p>
+ </td>
+<td>
+ <p>
+ normal refresh
+ </p>
+ </td>
+<td>
+ <p>
+ heart-beat refresh
+ </p>
+ </td>
+<td>
+ <p>
+ heart-beat notify
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">no</strong></span> (default)</p>
+ </td>
+<td>
+ <p>
+ yes
+ </p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">yes</strong></span></p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+<td>
+ <p>
+ yes
+ </p>
+ </td>
+<td>
+ <p>
+ yes
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">notify</strong></span></p>
+ </td>
+<td>
+ <p>
+ yes
+ </p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+<td>
+ <p>
+ yes
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">refresh</strong></span></p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+<td>
+ <p>
+ yes
+ </p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">passive</strong></span></p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">notify-passive</strong></span></p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+<td>
+ <p>
+ no
+ </p>
+ </td>
+<td>
+ <p>
+ yes
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ Note that normal NOTIFY processing is not affected by
+ <span><strong class="command">dialup</strong></span>.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">fake-iquery</strong></span></span></dt>
+<dd><p>
+ In <acronym class="acronym">BIND</acronym> 8, this option
+ enabled simulating the obsolete DNS query type
+ IQUERY. <acronym class="acronym">BIND</acronym> 9 never does
+ IQUERY simulation.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">fetch-glue</strong></span></span></dt>
+<dd><p>
+ This option is obsolete.
+ In BIND 8, <strong class="userinput"><code>fetch-glue yes</code></strong>
+ caused the server to attempt to fetch glue resource records
+ it
+ didn't have when constructing the additional
+ data section of a response. This is now considered a bad
+ idea
+ and BIND 9 never does it.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">flush-zones-on-shutdown</strong></span></span></dt>
+<dd><p>
+ When the nameserver exits due receiving SIGTERM,
+ flush or do not flush any pending zone writes. The default
+ is
+ <span><strong class="command">flush-zones-on-shutdown</strong></span> <strong class="userinput"><code>no</code></strong>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">has-old-clients</strong></span></span></dt>
+<dd><p>
+ This option was incorrectly implemented
+ in <acronym class="acronym">BIND</acronym> 8, and is ignored by <acronym class="acronym">BIND</acronym> 9.
+ To achieve the intended effect
+ of
+ <span><strong class="command">has-old-clients</strong></span> <strong class="userinput"><code>yes</code></strong>, specify
+ the two separate options <span><strong class="command">auth-nxdomain</strong></span> <strong class="userinput"><code>yes</code></strong>
+ and <span><strong class="command">rfc2308-type1</strong></span> <strong class="userinput"><code>no</code></strong> instead.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">host-statistics</strong></span></span></dt>
+<dd><p>
+ In BIND 8, this enables keeping of
+ statistics for every host that the name server interacts
+ with.
+ Not implemented in BIND 9.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">maintain-ixfr-base</strong></span></span></dt>
+<dd><p>
+ <span class="emphasis"><em>This option is obsolete</em></span>.
+ It was used in <acronym class="acronym">BIND</acronym> 8 to
+ determine whether a transaction log was
+ kept for Incremental Zone Transfer. <acronym class="acronym">BIND</acronym> 9 maintains a transaction
+ log whenever possible. If you need to disable outgoing
+ incremental zone
+ transfers, use <span><strong class="command">provide-ixfr</strong></span> <strong class="userinput"><code>no</code></strong>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">minimal-responses</strong></span></span></dt>
+<dd><p>
+ If <strong class="userinput"><code>yes</code></strong>, then when generating
+ responses the server will only add records to the authority
+ and additional data sections when they are required (e.g.
+ delegations, negative responses). This may improve the
+ performance of the server.
+ The default is <strong class="userinput"><code>no</code></strong>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">multiple-cnames</strong></span></span></dt>
+<dd><p>
+ This option was used in <acronym class="acronym">BIND</acronym> 8 to allow
+ a domain name to have multiple CNAME records in violation of
+ the DNS standards. <acronym class="acronym">BIND</acronym> 9.2 onwards
+ always strictly enforces the CNAME rules both in master
+ files and dynamic updates.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">notify</strong></span></span></dt>
+<dd>
+<p>
+ If <strong class="userinput"><code>yes</code></strong> (the default),
+ DNS NOTIFY messages are sent when a zone the server is
+ authoritative for
+ changes, see <a href="Bv9ARM.ch04.html#notify" title="Notify">the section called &#8220;Notify&#8221;</a>. The messages are
+ sent to the
+ servers listed in the zone's NS records (except the master
+ server identified
+ in the SOA MNAME field), and to any servers listed in the
+ <span><strong class="command">also-notify</strong></span> option.
+ </p>
+<p>
+ If <strong class="userinput"><code>master-only</code></strong>, notifies are only
+ sent
+ for master zones.
+ If <strong class="userinput"><code>explicit</code></strong>, notifies are sent only
+ to
+ servers explicitly listed using <span><strong class="command">also-notify</strong></span>.
+ If <strong class="userinput"><code>no</code></strong>, no notifies are sent.
+ </p>
+<p>
+ The <span><strong class="command">notify</strong></span> option may also be
+ specified in the <span><strong class="command">zone</strong></span>
+ statement,
+ in which case it overrides the <span><strong class="command">options notify</strong></span> statement.
+ It would only be necessary to turn off this option if it
+ caused slaves
+ to crash.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">notify-to-soa</strong></span></span></dt>
+<dd><p>
+ If <strong class="userinput"><code>yes</code></strong> do not check the nameservers
+ in the NS RRset against the SOA MNAME. Normally a NOTIFY
+ message is not sent to the SOA MNAME (SOA ORIGIN) as it is
+ supposed to contain the name of the ultimate master.
+ Sometimes, however, a slave is listed as the SOA MNAME in
+ hidden master configurations and in that case you would
+ want the ultimate master to still send NOTIFY messages to
+ all the nameservers listed in the NS RRset.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">recursion</strong></span></span></dt>
+<dd><p>
+ If <strong class="userinput"><code>yes</code></strong>, and a
+ DNS query requests recursion, then the server will attempt
+ to do
+ all the work required to answer the query. If recursion is
+ off
+ and the server does not already know the answer, it will
+ return a
+ referral response. The default is
+ <strong class="userinput"><code>yes</code></strong>.
+ Note that setting <span><strong class="command">recursion no</strong></span> does not prevent
+ clients from getting data from the server's cache; it only
+ prevents new data from being cached as an effect of client
+ queries.
+ Caching may still occur as an effect the server's internal
+ operation, such as NOTIFY address lookups.
+ See also <span><strong class="command">fetch-glue</strong></span> above.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">rfc2308-type1</strong></span></span></dt>
+<dd>
+<p>
+ Setting this to <strong class="userinput"><code>yes</code></strong> will
+ cause the server to send NS records along with the SOA
+ record for negative
+ answers. The default is <strong class="userinput"><code>no</code></strong>.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ Not yet implemented in <acronym class="acronym">BIND</acronym>
+ 9.
+ </p>
+</div>
+</dd>
+<dt><span class="term"><span><strong class="command">use-id-pool</strong></span></span></dt>
+<dd><p>
+ <span class="emphasis"><em>This option is obsolete</em></span>.
+ <acronym class="acronym">BIND</acronym> 9 always allocates query
+ IDs from a pool.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">zone-statistics</strong></span></span></dt>
+<dd><p>
+ If <strong class="userinput"><code>yes</code></strong>, the server will collect
+ statistical data on all zones (unless specifically turned
+ off
+ on a per-zone basis by specifying <span><strong class="command">zone-statistics no</strong></span>
+ in the <span><strong class="command">zone</strong></span> statement).
+ These statistics may be accessed
+ using <span><strong class="command">rndc stats</strong></span>, which will
+ dump them to the file listed
+ in the <span><strong class="command">statistics-file</strong></span>. See
+ also <a href="Bv9ARM.ch06.html#statsfile" title="The Statistics File">the section called &#8220;The Statistics File&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">use-ixfr</strong></span></span></dt>
+<dd><p>
+ <span class="emphasis"><em>This option is obsolete</em></span>.
+ If you need to disable IXFR to a particular server or
+ servers, see
+ the information on the <span><strong class="command">provide-ixfr</strong></span> option
+ in <a href="Bv9ARM.ch06.html#server_statement_definition_and_usage" title="server Statement Definition and
+ Usage">the section called &#8220;<span><strong class="command">server</strong></span> Statement Definition and
+ Usage&#8221;</a>.
+ See also
+ <a href="Bv9ARM.ch04.html#incremental_zone_transfers" title="Incremental Zone Transfers (IXFR)">the section called &#8220;Incremental Zone Transfers (IXFR)&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">provide-ixfr</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">provide-ixfr</strong></span> in
+ <a href="Bv9ARM.ch06.html#server_statement_definition_and_usage" title="server Statement Definition and
+ Usage">the section called &#8220;<span><strong class="command">server</strong></span> Statement Definition and
+ Usage&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">request-ixfr</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">request-ixfr</strong></span> in
+ <a href="Bv9ARM.ch06.html#server_statement_definition_and_usage" title="server Statement Definition and
+ Usage">the section called &#8220;<span><strong class="command">server</strong></span> Statement Definition and
+ Usage&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">treat-cr-as-space</strong></span></span></dt>
+<dd><p>
+ This option was used in <acronym class="acronym">BIND</acronym>
+ 8 to make
+ the server treat carriage return ("<span><strong class="command">\r</strong></span>") characters the same way
+ as a space or tab character,
+ to facilitate loading of zone files on a UNIX system that
+ were generated
+ on an NT or DOS machine. In <acronym class="acronym">BIND</acronym> 9, both UNIX "<span><strong class="command">\n</strong></span>"
+ and NT/DOS "<span><strong class="command">\r\n</strong></span>" newlines
+ are always accepted,
+ and the option is ignored.
+ </p></dd>
+<dt>
+<span class="term"><span><strong class="command">additional-from-auth</strong></span>, </span><span class="term"><span><strong class="command">additional-from-cache</strong></span></span>
+</dt>
+<dd>
+<p>
+ These options control the behavior of an authoritative
+ server when
+ answering queries which have additional data, or when
+ following CNAME
+ and DNAME chains.
+ </p>
+<p>
+ When both of these options are set to <strong class="userinput"><code>yes</code></strong>
+ (the default) and a
+ query is being answered from authoritative data (a zone
+ configured into the server), the additional data section of
+ the
+ reply will be filled in using data from other authoritative
+ zones
+ and from the cache. In some situations this is undesirable,
+ such
+ as when there is concern over the correctness of the cache,
+ or
+ in servers where slave zones may be added and modified by
+ untrusted third parties. Also, avoiding
+ the search for this additional data will speed up server
+ operations
+ at the possible expense of additional queries to resolve
+ what would
+ otherwise be provided in the additional section.
+ </p>
+<p>
+ For example, if a query asks for an MX record for host <code class="literal">foo.example.com</code>,
+ and the record found is "<code class="literal">MX 10 mail.example.net</code>", normally the address
+ records (A and AAAA) for <code class="literal">mail.example.net</code> will be provided as well,
+ if known, even though they are not in the example.com zone.
+ Setting these options to <span><strong class="command">no</strong></span>
+ disables this behavior and makes
+ the server only search for additional data in the zone it
+ answers from.
+ </p>
+<p>
+ These options are intended for use in authoritative-only
+ servers, or in authoritative-only views. Attempts to set
+ them to <span><strong class="command">no</strong></span> without also
+ specifying
+ <span><strong class="command">recursion no</strong></span> will cause the
+ server to
+ ignore the options and log a warning message.
+ </p>
+<p>
+ Specifying <span><strong class="command">additional-from-cache no</strong></span> actually
+ disables the use of the cache not only for additional data
+ lookups
+ but also when looking up the answer. This is usually the
+ desired
+ behavior in an authoritative-only server where the
+ correctness of
+ the cached data is an issue.
+ </p>
+<p>
+ When a name server is non-recursively queried for a name
+ that is not
+ below the apex of any served zone, it normally answers with
+ an
+ "upwards referral" to the root servers or the servers of
+ some other
+ known parent of the query name. Since the data in an
+ upwards referral
+ comes from the cache, the server will not be able to provide
+ upwards
+ referrals when <span><strong class="command">additional-from-cache no</strong></span>
+ has been specified. Instead, it will respond to such
+ queries
+ with REFUSED. This should not cause any problems since
+ upwards referrals are not required for the resolution
+ process.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">match-mapped-addresses</strong></span></span></dt>
+<dd><p>
+ If <strong class="userinput"><code>yes</code></strong>, then an
+ IPv4-mapped IPv6 address will match any address match
+ list entries that match the corresponding IPv4 address.
+ Enabling this option is sometimes useful on IPv6-enabled
+ Linux
+ systems, to work around a kernel quirk that causes IPv4
+ TCP connections such as zone transfers to be accepted
+ on an IPv6 socket using mapped addresses, causing
+ address match lists designed for IPv4 to fail to match.
+ The use of this option for any other purpose is discouraged.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">ixfr-from-differences</strong></span></span></dt>
+<dd>
+<p>
+ When <strong class="userinput"><code>yes</code></strong> and the server loads a new version of a master
+ zone from its zone file or receives a new version of a slave
+ file by a non-incremental zone transfer, it will compare
+ the new version to the previous one and calculate a set
+ of differences. The differences are then logged in the
+ zone's journal file such that the changes can be transmitted
+ to downstream slaves as an incremental zone transfer.
+ </p>
+<p>
+ By allowing incremental zone transfers to be used for
+ non-dynamic zones, this option saves bandwidth at the
+ expense of increased CPU and memory consumption at the
+ master.
+ In particular, if the new version of a zone is completely
+ different from the previous one, the set of differences
+ will be of a size comparable to the combined size of the
+ old and new zone version, and the server will need to
+ temporarily allocate memory to hold this complete
+ difference set.
+ </p>
+<p><span><strong class="command">ixfr-from-differences</strong></span>
+ also accepts <span><strong class="command">master</strong></span> and
+ <span><strong class="command">slave</strong></span> at the view and options
+ levels which causes
+ <span><strong class="command">ixfr-from-differences</strong></span> to be enabled for
+ all <span><strong class="command">master</strong></span> or
+ <span><strong class="command">slave</strong></span> zones respectively.
+ It is off by default.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">multi-master</strong></span></span></dt>
+<dd><p>
+ This should be set when you have multiple masters for a zone
+ and the
+ addresses refer to different machines. If <strong class="userinput"><code>yes</code></strong>, named will
+ not log
+ when the serial number on the master is less than what named
+ currently
+ has. The default is <strong class="userinput"><code>no</code></strong>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">dnssec-enable</strong></span></span></dt>
+<dd><p>
+ Enable DNSSEC support in named. Unless set to <strong class="userinput"><code>yes</code></strong>,
+ named behaves as if it does not support DNSSEC.
+ The default is <strong class="userinput"><code>yes</code></strong>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">dnssec-validation</strong></span></span></dt>
+<dd><p>
+ Enable DNSSEC validation in named.
+ Note <span><strong class="command">dnssec-enable</strong></span> also needs to be
+ set to <strong class="userinput"><code>yes</code></strong> to be effective.
+ The default is <strong class="userinput"><code>yes</code></strong>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">dnssec-accept-expired</strong></span></span></dt>
+<dd><p>
+ Accept expired signatures when verifying DNSSEC signatures.
+ The default is <strong class="userinput"><code>no</code></strong>.
+ Setting this option to "yes" leaves named vulnerable to replay attacks.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">querylog</strong></span></span></dt>
+<dd><p>
+ Specify whether query logging should be started when named
+ starts.
+ If <span><strong class="command">querylog</strong></span> is not specified,
+ then the query logging
+ is determined by the presence of the logging category <span><strong class="command">queries</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-names</strong></span></span></dt>
+<dd>
+<p>
+ This option is used to restrict the character set and syntax
+ of
+ certain domain names in master files and/or DNS responses
+ received
+ from the network. The default varies according to usage
+ area. For
+ <span><strong class="command">master</strong></span> zones the default is <span><strong class="command">fail</strong></span>.
+ For <span><strong class="command">slave</strong></span> zones the default
+ is <span><strong class="command">warn</strong></span>.
+ For answers received from the network (<span><strong class="command">response</strong></span>)
+ the default is <span><strong class="command">ignore</strong></span>.
+ </p>
+<p>
+ The rules for legal hostnames and mail domains are derived
+ from RFC 952 and RFC 821 as modified by RFC 1123.
+ </p>
+<p><span><strong class="command">check-names</strong></span>
+ applies to the owner names of A, AAAA and MX records.
+ It also applies to the domain names in the RDATA of NS, SOA
+ and MX records.
+ It also applies to the RDATA of PTR records where the owner
+ name indicated that it is a reverse lookup of a hostname
+ (the owner name ends in IN-ADDR.ARPA, IP6.ARPA, or IP6.INT).
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">check-mx</strong></span></span></dt>
+<dd><p>
+ Check whether the MX record appears to refer to a IP address.
+ The default is to <span><strong class="command">warn</strong></span>. Other possible
+ values are <span><strong class="command">fail</strong></span> and
+ <span><strong class="command">ignore</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-wildcard</strong></span></span></dt>
+<dd><p>
+ This option is used to check for non-terminal wildcards.
+ The use of non-terminal wildcards is almost always as a
+ result of a failure
+ to understand the wildcard matching algorithm (RFC 1034).
+ This option
+ affects master zones. The default (<span><strong class="command">yes</strong></span>) is to check
+ for non-terminal wildcards and issue a warning.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-integrity</strong></span></span></dt>
+<dd><p>
+ Perform post load zone integrity checks on master
+ zones. This checks that MX and SRV records refer
+ to address (A or AAAA) records and that glue
+ address records exist for delegated zones. For
+ MX and SRV records only in-zone hostnames are
+ checked (for out-of-zone hostnames use
+ <span><strong class="command">named-checkzone</strong></span>).
+ For NS records only names below top of zone are
+ checked (for out-of-zone names and glue consistency
+ checks use <span><strong class="command">named-checkzone</strong></span>).
+ The default is <span><strong class="command">yes</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-mx-cname</strong></span></span></dt>
+<dd><p>
+ If <span><strong class="command">check-integrity</strong></span> is set then
+ fail, warn or ignore MX records that refer
+ to CNAMES. The default is to <span><strong class="command">warn</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-srv-cname</strong></span></span></dt>
+<dd><p>
+ If <span><strong class="command">check-integrity</strong></span> is set then
+ fail, warn or ignore SRV records that refer
+ to CNAMES. The default is to <span><strong class="command">warn</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-sibling</strong></span></span></dt>
+<dd><p>
+ When performing integrity checks, also check that
+ sibling glue exists. The default is <span><strong class="command">yes</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">zero-no-soa-ttl</strong></span></span></dt>
+<dd><p>
+ When returning authoritative negative responses to
+ SOA queries set the TTL of the SOA record returned in
+ the authority section to zero.
+ The default is <span><strong class="command">yes</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">zero-no-soa-ttl-cache</strong></span></span></dt>
+<dd><p>
+ When caching a negative response to a SOA query
+ set the TTL to zero.
+ The default is <span><strong class="command">no</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">update-check-ksk</strong></span></span></dt>
+<dd><p>
+ 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 <span><strong class="command">yes</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">try-tcp-refresh</strong></span></span></dt>
+<dd><p>
+ Try to refresh the zone using TCP if UDP queries fail.
+ For BIND 8 compatibility, the default is
+ <span><strong class="command">yes</strong></span>.
+ </p></dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2581106"></a>Forwarding</h4></div></div></div>
+<p>
+ The forwarding facility can be used to create a large site-wide
+ cache on a few servers, reducing traffic over links to external
+ name servers. It can also be used to allow queries by servers that
+ do not have direct access to the Internet, but wish to look up
+ exterior
+ names anyway. Forwarding occurs only on those queries for which
+ the server is not authoritative and does not have the answer in
+ its cache.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">forward</strong></span></span></dt>
+<dd><p>
+ This option is only meaningful if the
+ forwarders list is not empty. A value of <code class="varname">first</code>,
+ the default, causes the server to query the forwarders
+ first &#8212; and
+ if that doesn't answer the question, the server will then
+ look for
+ the answer itself. If <code class="varname">only</code> is
+ specified, the
+ server will only query the forwarders.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">forwarders</strong></span></span></dt>
+<dd><p>
+ Specifies the IP addresses to be used
+ for forwarding. The default is the empty list (no
+ forwarding).
+ </p></dd>
+</dl></div>
+<p>
+ Forwarding can also be configured on a per-domain basis, allowing
+ for the global forwarding options to be overridden in a variety
+ of ways. You can set particular domains to use different
+ forwarders,
+ or have a different <span><strong class="command">forward only/first</strong></span> behavior,
+ or not forward at all, see <a href="Bv9ARM.ch06.html#zone_statement_grammar" title="zone
+ Statement Grammar">the section called &#8220;<span><strong class="command">zone</strong></span>
+ Statement Grammar&#8221;</a>.
+ </p>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2581164"></a>Dual-stack Servers</h4></div></div></div>
+<p>
+ Dual-stack servers are used as servers of last resort to work
+ around
+ problems in reachability due the lack of support for either IPv4
+ or IPv6
+ on the host machine.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">dual-stack-servers</strong></span></span></dt>
+<dd><p>
+ Specifies host names or addresses of machines with access to
+ both IPv4 and IPv6 transports. If a hostname is used, the
+ server must be able
+ to resolve the name using only the transport it has. If the
+ machine is dual
+ stacked, then the <span><strong class="command">dual-stack-servers</strong></span> have no effect unless
+ access to a transport has been disabled on the command line
+ (e.g. <span><strong class="command">named -4</strong></span>).
+ </p></dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="access_control"></a>Access Control</h4></div></div></div>
+<p>
+ Access to the server can be restricted based on the IP address
+ of the requesting system. See <a href="Bv9ARM.ch06.html#address_match_lists" title="Address Match Lists">the section called &#8220;Address Match Lists&#8221;</a> for
+ details on how to specify IP address lists.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">allow-notify</strong></span></span></dt>
+<dd><p>
+ Specifies which hosts are allowed to
+ notify this server, a slave, of zone changes in addition
+ to the zone masters.
+ <span><strong class="command">allow-notify</strong></span> may also be
+ specified in the
+ <span><strong class="command">zone</strong></span> statement, in which case
+ it overrides the
+ <span><strong class="command">options allow-notify</strong></span>
+ statement. It is only meaningful
+ for a slave zone. If not specified, the default is to
+ process notify messages
+ only from a zone's master.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-query</strong></span></span></dt>
+<dd>
+<p>
+ Specifies which hosts are allowed to ask ordinary
+ DNS questions. <span><strong class="command">allow-query</strong></span> may
+ also be specified in the <span><strong class="command">zone</strong></span>
+ statement, in which case it overrides the
+ <span><strong class="command">options allow-query</strong></span> statement.
+ If not specified, the default is to allow queries
+ from all hosts.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ <span><strong class="command">allow-query-cache</strong></span> is now
+ used to specify access to the cache.
+ </p>
+</div>
+</dd>
+<dt><span class="term"><span><strong class="command">allow-query-on</strong></span></span></dt>
+<dd>
+<p>
+ Specifies which local addresses can accept ordinary
+ DNS questions. This makes it possible, for instance,
+ to allow queries on internal-facing interfaces but
+ disallow them on external-facing ones, without
+ necessarily knowing the internal network's addresses.
+ </p>
+<p>
+ <span><strong class="command">allow-query-on</strong></span> may
+ also be specified in the <span><strong class="command">zone</strong></span>
+ statement, in which case it overrides the
+ <span><strong class="command">options allow-query-on</strong></span> statement.
+ </p>
+<p>
+ If not specified, the default is to allow queries
+ on all addresses.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ <span><strong class="command">allow-query-cache</strong></span> is
+ used to specify access to the cache.
+ </p>
+</div>
+</dd>
+<dt><span class="term"><span><strong class="command">allow-query-cache</strong></span></span></dt>
+<dd><p>
+ Specifies which hosts are allowed to get answers
+ from the cache. If <span><strong class="command">allow-query-cache</strong></span>
+ is not set then <span><strong class="command">allow-recursion</strong></span>
+ is used if set, otherwise <span><strong class="command">allow-query</strong></span>
+ is used if set, otherwise the default
+ (<span><strong class="command">localnets;</strong></span>
+ <span><strong class="command">localhost;</strong></span>) is used.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-query-cache-on</strong></span></span></dt>
+<dd><p>
+ Specifies which local addresses can give answers
+ from the cache. If not specified, the default is
+ to allow cache queries on any address,
+ <span><strong class="command">localnets</strong></span> and
+ <span><strong class="command">localhost</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-recursion</strong></span></span></dt>
+<dd><p>
+ Specifies which hosts are allowed to make recursive
+ queries through this server. If
+ <span><strong class="command">allow-recursion</strong></span> is not set
+ then <span><strong class="command">allow-query-cache</strong></span> is
+ used if set, otherwise <span><strong class="command">allow-query</strong></span>
+ is used if set, otherwise the default
+ (<span><strong class="command">localnets;</strong></span>
+ <span><strong class="command">localhost;</strong></span>) is used.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-recursion-on</strong></span></span></dt>
+<dd><p>
+ Specifies which local addresses can accept recursive
+ queries. If not specified, the default is to allow
+ recursive queries on all addresses.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-update</strong></span></span></dt>
+<dd><p>
+ Specifies which hosts are allowed to
+ submit Dynamic DNS updates for master zones. The default is
+ to deny
+ updates from all hosts. Note that allowing updates based
+ on the requestor's IP address is insecure; see
+ <a href="Bv9ARM.ch07.html#dynamic_update_security" title="Dynamic Update Security">the section called &#8220;Dynamic Update Security&#8221;</a> for details.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-update-forwarding</strong></span></span></dt>
+<dd>
+<p>
+ Specifies which hosts are allowed to
+ submit Dynamic DNS updates to slave zones to be forwarded to
+ the
+ master. The default is <strong class="userinput"><code>{ none; }</code></strong>,
+ which
+ means that no update forwarding will be performed. To
+ enable
+ update forwarding, specify
+ <strong class="userinput"><code>allow-update-forwarding { any; };</code></strong>.
+ Specifying values other than <strong class="userinput"><code>{ none; }</code></strong> or
+ <strong class="userinput"><code>{ any; }</code></strong> is usually
+ counterproductive, since
+ the responsibility for update access control should rest
+ with the
+ master server, not the slaves.
+ </p>
+<p>
+ Note that enabling the update forwarding feature on a slave
+ server
+ may expose master servers relying on insecure IP address
+ based
+ access control to attacks; see <a href="Bv9ARM.ch07.html#dynamic_update_security" title="Dynamic Update Security">the section called &#8220;Dynamic Update Security&#8221;</a>
+ for more details.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">allow-v6-synthesis</strong></span></span></dt>
+<dd><p>
+ This option was introduced for the smooth transition from
+ AAAA
+ to A6 and from "nibble labels" to binary labels.
+ However, since both A6 and binary labels were then
+ deprecated,
+ this option was also deprecated.
+ It is now ignored with some warning messages.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-transfer</strong></span></span></dt>
+<dd><p>
+ Specifies which hosts are allowed to
+ receive zone transfers from the server. <span><strong class="command">allow-transfer</strong></span> may
+ also be specified in the <span><strong class="command">zone</strong></span>
+ statement, in which
+ case it overrides the <span><strong class="command">options allow-transfer</strong></span> statement.
+ If not specified, the default is to allow transfers to all
+ hosts.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">blackhole</strong></span></span></dt>
+<dd><p>
+ 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 <strong class="userinput"><code>none</code></strong>.
+ </p></dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2581660"></a>Interfaces</h4></div></div></div>
+<p>
+ The interfaces and ports that the server will answer queries
+ from may be specified using the <span><strong class="command">listen-on</strong></span> option. <span><strong class="command">listen-on</strong></span> takes
+ an optional port, and an <code class="varname">address_match_list</code>.
+ The server will listen on all interfaces allowed by the address
+ match list. If a port is not specified, port 53 will be used.
+ </p>
+<p>
+ Multiple <span><strong class="command">listen-on</strong></span> statements are
+ allowed.
+ For example,
+ </p>
+<pre class="programlisting">listen-on { 5.6.7.8; };
+listen-on port 1234 { !1.2.3.4; 1.2/16; };
+</pre>
+<p>
+ will enable the name server on port 53 for the IP address
+ 5.6.7.8, and on port 1234 of an address on the machine in net
+ 1.2 that is not 1.2.3.4.
+ </p>
+<p>
+ If no <span><strong class="command">listen-on</strong></span> is specified, the
+ server will listen on port 53 on all IPv4 interfaces.
+ </p>
+<p>
+ The <span><strong class="command">listen-on-v6</strong></span> option is used to
+ specify the interfaces and the ports on which the server will
+ listen
+ for incoming queries sent using IPv6.
+ </p>
+<p>
+ When </p>
+<pre class="programlisting">{ any; }</pre>
+<p> is
+ specified
+ as the <code class="varname">address_match_list</code> for the
+ <span><strong class="command">listen-on-v6</strong></span> option,
+ the server does not bind a separate socket to each IPv6 interface
+ address as it does for IPv4 if the operating system has enough API
+ support for IPv6 (specifically if it conforms to RFC 3493 and RFC
+ 3542).
+ Instead, it listens on the IPv6 wildcard address.
+ If the system only has incomplete API support for IPv6, however,
+ the behavior is the same as that for IPv4.
+ </p>
+<p>
+ A list of particular IPv6 addresses can also be specified, in
+ which case
+ the server listens on a separate socket for each specified
+ address,
+ regardless of whether the desired API is supported by the system.
+ </p>
+<p>
+ Multiple <span><strong class="command">listen-on-v6</strong></span> options can
+ be used.
+ For example,
+ </p>
+<pre class="programlisting">listen-on-v6 { any; };
+listen-on-v6 port 1234 { !2001:db8::/32; any; };
+</pre>
+<p>
+ will enable the name server on port 53 for any IPv6 addresses
+ (with a single wildcard socket),
+ and on port 1234 of IPv6 addresses that is not in the prefix
+ 2001:db8::/32 (with separate sockets for each matched address.)
+ </p>
+<p>
+ To make the server not listen on any IPv6 address, use
+ </p>
+<pre class="programlisting">listen-on-v6 { none; };
+</pre>
+<p>
+ If no <span><strong class="command">listen-on-v6</strong></span> option is
+ specified, the server will not listen on any IPv6 address
+ unless <span><strong class="command">-6</strong></span> is specified when named is
+ invoked. If <span><strong class="command">-6</strong></span> is specified then
+ named will listen on port 53 on all IPv6 interfaces by default.
+ </p>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="query_address"></a>Query Address</h4></div></div></div>
+<p>
+ If the server doesn't know the answer to a question, it will
+ query other name servers. <span><strong class="command">query-source</strong></span> specifies
+ the address and port used for such queries. For queries sent over
+ IPv6, there is a separate <span><strong class="command">query-source-v6</strong></span> option.
+ If <span><strong class="command">address</strong></span> is <span><strong class="command">*</strong></span> (asterisk) or is omitted,
+ a wildcard IP address (<span><strong class="command">INADDR_ANY</strong></span>)
+ will be used.
+ </p>
+<p>
+ If <span><strong class="command">port</strong></span> is <span><strong class="command">*</strong></span> or is omitted,
+ a random port number from a pre-configured
+ range is picked up and will be used for each query.
+ The port range(s) is that specified in
+ the <span><strong class="command">use-v4-udp-ports</strong></span> (for IPv4)
+ and <span><strong class="command">use-v6-udp-ports</strong></span> (for IPv6)
+ options, excluding the ranges specified in
+ the <span><strong class="command">avoid-v4-udp-ports</strong></span>
+ and <span><strong class="command">avoid-v6-udp-ports</strong></span> options, respectively.
+ </p>
+<p>
+ The defaults of the <span><strong class="command">query-source</strong></span> and
+ <span><strong class="command">query-source-v6</strong></span> options
+ are:
+ </p>
+<pre class="programlisting">query-source address * port *;
+query-source-v6 address * port *;
+</pre>
+<p>
+ If <span><strong class="command">use-v4-udp-ports</strong></span> or
+ <span><strong class="command">use-v6-udp-ports</strong></span> is unspecified,
+ <span><strong class="command">named</strong></span> will check if the operating
+ system provides a programming interface to retrieve the
+ system's default range for ephemeral ports.
+ If such an interface is available,
+ <span><strong class="command">named</strong></span> will use the corresponding system
+ default range; otherwise, it will use its own defaults:
+ </p>
+<pre class="programlisting">use-v4-udp-ports { range 1024 65535; };
+use-v6-udp-ports { range 1024 65535; };
+</pre>
+<p>
+ Note: make sure the ranges be sufficiently large for
+ security. A desirable size depends on various parameters,
+ but we generally recommend it contain at least 16384 ports
+ (14 bits of entropy).
+ Note also that the system's default range when used may be
+ too small for this purpose, and that the range may even be
+ changed while <span><strong class="command">named</strong></span> is running; the new
+ range will automatically be applied when <span><strong class="command">named</strong></span>
+ is reloaded.
+ It is encouraged to
+ configure <span><strong class="command">use-v4-udp-ports</strong></span> and
+ <span><strong class="command">use-v6-udp-ports</strong></span> explicitly so that the
+ ranges are sufficiently large and are reasonably
+ independent from the ranges used by other applications.
+ </p>
+<p>
+ Note: the operational configuration
+ where <span><strong class="command">named</strong></span> runs may prohibit the use
+ of some ports. For example, UNIX systems will not allow
+ <span><strong class="command">named</strong></span> running without a root privilege
+ to use ports less than 1024.
+ If such ports are included in the specified (or detected)
+ set of query ports, the corresponding query attempts will
+ fail, resulting in resolution failures or delay.
+ It is therefore important to configure the set of ports
+ that can be safely used in the expected operational environment.
+ </p>
+<p>
+ The defaults of the <span><strong class="command">avoid-v4-udp-ports</strong></span> and
+ <span><strong class="command">avoid-v6-udp-ports</strong></span> options
+ are:
+ </p>
+<pre class="programlisting">avoid-v4-udp-ports {};
+avoid-v6-udp-ports {};
+</pre>
+<p>
+ Note: BIND 9.5.0 introduced
+ the <span><strong class="command">use-queryport-pool</strong></span>
+ option to support a pool of such random ports, but this
+ option is now obsolete because reusing the same ports in
+ the pool may not be sufficiently secure.
+ For the same reason, it is generally strongly discouraged to
+ specify a particular port for the
+ <span><strong class="command">query-source</strong></span> or
+ <span><strong class="command">query-source-v6</strong></span> options;
+ it implicitly disables the use of randomized port numbers.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">use-queryport-pool</strong></span></span></dt>
+<dd><p>
+ This option is obsolete.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">queryport-pool-ports</strong></span></span></dt>
+<dd><p>
+ This option is obsolete.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">queryport-pool-updateinterval</strong></span></span></dt>
+<dd><p>
+ This option is obsolete.
+ </p></dd>
+</dl></div>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ The address specified in the <span><strong class="command">query-source</strong></span> option
+ is used for both UDP and TCP queries, but the port applies only
+ to UDP queries. TCP queries always use a random
+ unprivileged port.
+ </p>
+</div>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ Solaris 2.5.1 and earlier does not support setting the source
+ address for TCP sockets.
+ </p>
+</div>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ See also <span><strong class="command">transfer-source</strong></span> and
+ <span><strong class="command">notify-source</strong></span>.
+ </p>
+</div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="zone_transfers"></a>Zone Transfers</h4></div></div></div>
+<p>
+ <acronym class="acronym">BIND</acronym> has mechanisms in place to
+ facilitate zone transfers
+ and set limits on the amount of load that transfers place on the
+ system. The following options apply to zone transfers.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">also-notify</strong></span></span></dt>
+<dd><p>
+ Defines a global list of IP addresses of name servers
+ that are also sent NOTIFY messages whenever a fresh copy of
+ the
+ zone is loaded, in addition to the servers listed in the
+ zone's NS records.
+ This helps to ensure that copies of the zones will
+ quickly converge on stealth servers. If an <span><strong class="command">also-notify</strong></span> list
+ is given in a <span><strong class="command">zone</strong></span> statement,
+ it will override
+ the <span><strong class="command">options also-notify</strong></span>
+ statement. When a <span><strong class="command">zone notify</strong></span>
+ statement
+ is set to <span><strong class="command">no</strong></span>, the IP
+ addresses in the global <span><strong class="command">also-notify</strong></span> list will
+ not be sent NOTIFY messages for that zone. The default is
+ the empty
+ list (no global notification list).
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-transfer-time-in</strong></span></span></dt>
+<dd><p>
+ Inbound zone transfers running longer than
+ this many minutes will be terminated. The default is 120
+ minutes
+ (2 hours). The maximum value is 28 days (40320 minutes).
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-transfer-idle-in</strong></span></span></dt>
+<dd><p>
+ Inbound zone transfers making no progress
+ in this many minutes will be terminated. The default is 60
+ minutes
+ (1 hour). The maximum value is 28 days (40320 minutes).
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-transfer-time-out</strong></span></span></dt>
+<dd><p>
+ Outbound zone transfers running longer than
+ this many minutes will be terminated. The default is 120
+ minutes
+ (2 hours). The maximum value is 28 days (40320 minutes).
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-transfer-idle-out</strong></span></span></dt>
+<dd><p>
+ Outbound zone transfers making no progress
+ in this many minutes will be terminated. The default is 60
+ minutes (1
+ hour). The maximum value is 28 days (40320 minutes).
+ </p></dd>
+<dt><span class="term"><span><strong class="command">serial-query-rate</strong></span></span></dt>
+<dd><p>
+ Slave servers will periodically query master servers
+ to find out if zone serial numbers have changed. Each such
+ query uses
+ a minute amount of the slave server's network bandwidth. To
+ limit the
+ amount of bandwidth used, BIND 9 limits the rate at which
+ queries are
+ sent. The value of the <span><strong class="command">serial-query-rate</strong></span> option,
+ an integer, is the maximum number of queries sent per
+ second.
+ The default is 20.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">serial-queries</strong></span></span></dt>
+<dd><p>
+ In BIND 8, the <span><strong class="command">serial-queries</strong></span>
+ option
+ set the maximum number of concurrent serial number queries
+ allowed to be outstanding at any given time.
+ BIND 9 does not limit the number of outstanding
+ serial queries and ignores the <span><strong class="command">serial-queries</strong></span> option.
+ Instead, it limits the rate at which the queries are sent
+ as defined using the <span><strong class="command">serial-query-rate</strong></span> option.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">transfer-format</strong></span></span></dt>
+<dd><p>
+ Zone transfers can be sent using two different formats,
+ <span><strong class="command">one-answer</strong></span> and
+ <span><strong class="command">many-answers</strong></span>.
+ The <span><strong class="command">transfer-format</strong></span> option is used
+ on the master server to determine which format it sends.
+ <span><strong class="command">one-answer</strong></span> uses one DNS message per
+ resource record transferred.
+ <span><strong class="command">many-answers</strong></span> packs as many resource
+ records as possible into a message.
+ <span><strong class="command">many-answers</strong></span> is more efficient, but is
+ only supported by relatively new slave servers,
+ such as <acronym class="acronym">BIND</acronym> 9, <acronym class="acronym">BIND</acronym>
+ 8.x and <acronym class="acronym">BIND</acronym> 4.9.5 onwards.
+ The <span><strong class="command">many-answers</strong></span> format is also supported by
+ recent Microsoft Windows nameservers.
+ The default is <span><strong class="command">many-answers</strong></span>.
+ <span><strong class="command">transfer-format</strong></span> may be overridden on a
+ per-server basis by using the <span><strong class="command">server</strong></span>
+ statement.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">transfers-in</strong></span></span></dt>
+<dd><p>
+ The maximum number of inbound zone transfers
+ that can be running concurrently. The default value is <code class="literal">10</code>.
+ Increasing <span><strong class="command">transfers-in</strong></span> may
+ speed up the convergence
+ of slave zones, but it also may increase the load on the
+ local system.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">transfers-out</strong></span></span></dt>
+<dd><p>
+ The maximum number of outbound zone transfers
+ that can be running concurrently. Zone transfer requests in
+ excess
+ of the limit will be refused. The default value is <code class="literal">10</code>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">transfers-per-ns</strong></span></span></dt>
+<dd><p>
+ The maximum number of inbound zone transfers
+ that can be concurrently transferring from a given remote
+ name server.
+ The default value is <code class="literal">2</code>.
+ Increasing <span><strong class="command">transfers-per-ns</strong></span>
+ may
+ speed up the convergence of slave zones, but it also may
+ increase
+ the load on the remote name server. <span><strong class="command">transfers-per-ns</strong></span> may
+ be overridden on a per-server basis by using the <span><strong class="command">transfers</strong></span> phrase
+ of the <span><strong class="command">server</strong></span> statement.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">transfer-source</strong></span></span></dt>
+<dd>
+<p><span><strong class="command">transfer-source</strong></span>
+ determines which local address will be bound to IPv4
+ TCP connections used to fetch zones transferred
+ inbound by the server. It also determines the
+ source IPv4 address, and optionally the UDP port,
+ used for the refresh queries and forwarded dynamic
+ updates. If not set, it defaults to a system
+ controlled value which will usually be the address
+ of the interface "closest to" the remote end. This
+ address must appear in the remote end's
+ <span><strong class="command">allow-transfer</strong></span> option for the
+ zone being transferred, if one is specified. This
+ statement sets the
+ <span><strong class="command">transfer-source</strong></span> for all zones,
+ but can be overridden on a per-view or per-zone
+ basis by including a
+ <span><strong class="command">transfer-source</strong></span> statement within
+ the <span><strong class="command">view</strong></span> or
+ <span><strong class="command">zone</strong></span> block in the configuration
+ file.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ Solaris 2.5.1 and earlier does not support setting the
+ source address for TCP sockets.
+ </p>
+</div>
+</dd>
+<dt><span class="term"><span><strong class="command">transfer-source-v6</strong></span></span></dt>
+<dd><p>
+ The same as <span><strong class="command">transfer-source</strong></span>,
+ except zone transfers are performed using IPv6.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">alt-transfer-source</strong></span></span></dt>
+<dd>
+<p>
+ An alternate transfer source if the one listed in
+ <span><strong class="command">transfer-source</strong></span> fails and
+ <span><strong class="command">use-alt-transfer-source</strong></span> is
+ set.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+ If you do not wish the alternate transfer source
+ to be used, you should set
+ <span><strong class="command">use-alt-transfer-source</strong></span>
+ appropriately and you should not depend upon
+ getting a answer back to the first refresh
+ query.
+ </div>
+</dd>
+<dt><span class="term"><span><strong class="command">alt-transfer-source-v6</strong></span></span></dt>
+<dd><p>
+ An alternate transfer source if the one listed in
+ <span><strong class="command">transfer-source-v6</strong></span> fails and
+ <span><strong class="command">use-alt-transfer-source</strong></span> is
+ set.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">use-alt-transfer-source</strong></span></span></dt>
+<dd><p>
+ Use the alternate transfer sources or not. If views are
+ specified this defaults to <span><strong class="command">no</strong></span>
+ otherwise it defaults to
+ <span><strong class="command">yes</strong></span> (for BIND 8
+ compatibility).
+ </p></dd>
+<dt><span class="term"><span><strong class="command">notify-source</strong></span></span></dt>
+<dd>
+<p><span><strong class="command">notify-source</strong></span>
+ determines which local source address, and
+ optionally UDP port, will be used to send NOTIFY
+ messages. This address must appear in the slave
+ server's <span><strong class="command">masters</strong></span> zone clause or
+ in an <span><strong class="command">allow-notify</strong></span> clause. This
+ statement sets the <span><strong class="command">notify-source</strong></span>
+ for all zones, but can be overridden on a per-zone or
+ per-view basis by including a
+ <span><strong class="command">notify-source</strong></span> statement within
+ the <span><strong class="command">zone</strong></span> or
+ <span><strong class="command">view</strong></span> block in the configuration
+ file.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ Solaris 2.5.1 and earlier does not support setting the
+ source address for TCP sockets.
+ </p>
+</div>
+</dd>
+<dt><span class="term"><span><strong class="command">notify-source-v6</strong></span></span></dt>
+<dd><p>
+ Like <span><strong class="command">notify-source</strong></span>,
+ but applies to notify messages sent to IPv6 addresses.
+ </p></dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2582923"></a>UDP Port Lists</h4></div></div></div>
+<p>
+ <span><strong class="command">use-v4-udp-ports</strong></span>,
+ <span><strong class="command">avoid-v4-udp-ports</strong></span>,
+ <span><strong class="command">use-v6-udp-ports</strong></span>, and
+ <span><strong class="command">avoid-v6-udp-ports</strong></span>
+ specify a list of IPv4 and IPv6 UDP ports that will be
+ used or not used as source ports for UDP messages.
+ See <a href="Bv9ARM.ch06.html#query_address" title="Query Address">the section called &#8220;Query Address&#8221;</a> about how the
+ available ports are determined.
+ For example, with the following configuration
+ </p>
+<pre class="programlisting">
+use-v6-udp-ports { range 32768 65535; };
+avoid-v6-udp-ports { 40000; range 50000 60000; };
+</pre>
+<p>
+ UDP ports of IPv6 messages sent
+ from <span><strong class="command">named</strong></span> will be in one
+ of the following ranges: 32768 to 39999, 40001 to 49999,
+ and 60001 to 65535.
+ </p>
+<p>
+ <span><strong class="command">avoid-v4-udp-ports</strong></span> and
+ <span><strong class="command">avoid-v6-udp-ports</strong></span> can be used
+ to prevent <span><strong class="command">named</strong></span> from choosing as its random source port a
+ port that is blocked by your firewall or a port that is
+ used by other applications;
+ if a query went out with a source port blocked by a
+ firewall, the
+ answer would not get by the firewall and the name server would
+ have to query again.
+ Note: the desired range can also be represented only with
+ <span><strong class="command">use-v4-udp-ports</strong></span> and
+ <span><strong class="command">use-v6-udp-ports</strong></span>, and the
+ <span><strong class="command">avoid-</strong></span> options are redundant in that
+ sense; they are provided for backward compatibility and
+ to possibly simplify the port specification.
+ </p>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2582983"></a>Operating System Resource Limits</h4></div></div></div>
+<p>
+ The server's usage of many system resources can be limited.
+ Scaled values are allowed when specifying resource limits. For
+ example, <span><strong class="command">1G</strong></span> can be used instead of
+ <span><strong class="command">1073741824</strong></span> to specify a limit of
+ one
+ gigabyte. <span><strong class="command">unlimited</strong></span> requests
+ unlimited use, or the
+ maximum available amount. <span><strong class="command">default</strong></span>
+ uses the limit
+ that was in force when the server was started. See the description
+ of <span><strong class="command">size_spec</strong></span> in <a href="Bv9ARM.ch06.html#configuration_file_elements" title="Configuration File Elements">the section called &#8220;Configuration File Elements&#8221;</a>.
+ </p>
+<p>
+ The following options set operating system resource limits for
+ the name server process. Some operating systems don't support
+ some or
+ any of the limits. On such systems, a warning will be issued if
+ the
+ unsupported limit is used.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">coresize</strong></span></span></dt>
+<dd><p>
+ The maximum size of a core dump. The default
+ is <code class="literal">default</code>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">datasize</strong></span></span></dt>
+<dd><p>
+ The maximum amount of data memory the server
+ may use. The default is <code class="literal">default</code>.
+ This is a hard limit on server memory usage.
+ If the server attempts to allocate memory in excess of this
+ limit, the allocation will fail, which may in turn leave
+ the server unable to perform DNS service. Therefore,
+ this option is rarely useful as a way of limiting the
+ amount of memory used by the server, but it can be used
+ to raise an operating system data size limit that is
+ too small by default. If you wish to limit the amount
+ of memory used by the server, use the
+ <span><strong class="command">max-cache-size</strong></span> and
+ <span><strong class="command">recursive-clients</strong></span>
+ options instead.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">files</strong></span></span></dt>
+<dd><p>
+ The maximum number of files the server
+ may have open concurrently. The default is <code class="literal">unlimited</code>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">stacksize</strong></span></span></dt>
+<dd><p>
+ The maximum amount of stack memory the server
+ may use. The default is <code class="literal">default</code>.
+ </p></dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="server_resource_limits"></a>Server Resource Limits</h4></div></div></div>
+<p>
+ The following options set limits on the server's
+ resource consumption that are enforced internally by the
+ server rather than the operating system.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">max-ixfr-log-size</strong></span></span></dt>
+<dd><p>
+ This option is obsolete; it is accepted
+ and ignored for BIND 8 compatibility. The option
+ <span><strong class="command">max-journal-size</strong></span> performs a
+ similar function in BIND 9.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-journal-size</strong></span></span></dt>
+<dd><p>
+ Sets a maximum size for each journal file
+ (see <a href="Bv9ARM.ch04.html#journal" title="The journal file">the section called &#8220;The journal file&#8221;</a>). When the journal file
+ approaches
+ the specified size, some of the oldest transactions in the
+ journal
+ will be automatically removed. The default is
+ <code class="literal">unlimited</code>.
+ This may also be set on a per-zone basis.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">host-statistics-max</strong></span></span></dt>
+<dd><p>
+ In BIND 8, specifies the maximum number of host statistics
+ entries to be kept.
+ Not implemented in BIND 9.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">recursive-clients</strong></span></span></dt>
+<dd><p>
+ The maximum number of simultaneous recursive lookups
+ the server will perform on behalf of clients. The default
+ is
+ <code class="literal">1000</code>. Because each recursing
+ client uses a fair
+ bit of memory, on the order of 20 kilobytes, the value of
+ the
+ <span><strong class="command">recursive-clients</strong></span> option may
+ have to be decreased
+ on hosts with limited memory.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">tcp-clients</strong></span></span></dt>
+<dd><p>
+ The maximum number of simultaneous client TCP
+ connections that the server will accept.
+ The default is <code class="literal">100</code>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">reserved-sockets</strong></span></span></dt>
+<dd>
+<p>
+ The number of file descriptors reserved for TCP, stdio,
+ etc. This needs to be big enough to cover the number of
+ interfaces named listens on, tcp-clients as well as
+ to provide room for outgoing TCP queries and incoming zone
+ transfers. The default is <code class="literal">512</code>.
+ The minimum value is <code class="literal">128</code> and the
+ maximum value is <code class="literal">128</code> less than
+ maxsockets (-S). This option may be removed in the future.
+ </p>
+<p>
+ This option has little effect on Windows.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">max-cache-size</strong></span></span></dt>
+<dd><p>
+ The maximum amount of memory to use for the
+ server's cache, in bytes.
+ When the amount of data in the cache
+ reaches this limit, the server will cause records to expire
+ prematurely based on an LRU based strategy so that
+ the limit is not exceeded.
+ A value of 0 is special, meaning that
+ records are purged from the cache only when their
+ TTLs expire.
+ Another special keyword <strong class="userinput"><code>unlimited</code></strong>
+ means the maximum value of 32-bit unsigned integers
+ (0xffffffff), which may not have the same effect as
+ 0 on machines that support more than 32 bits of
+ memory space.
+ Any positive values less than 2MB will be ignored reset
+ to 2MB.
+ In a server with multiple views, the limit applies
+ separately to the cache of each view.
+ The default is 0.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">tcp-listen-queue</strong></span></span></dt>
+<dd><p>
+ The listen queue depth. The default and minimum is 3.
+ If the kernel supports the accept filter "dataready" this
+ also controls how
+ many TCP connections that will be queued in kernel space
+ waiting for
+ some data before being passed to accept. Values less than 3
+ will be
+ silently raised.
+ </p></dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2583331"></a>Periodic Task Intervals</h4></div></div></div>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">cleaning-interval</strong></span></span></dt>
+<dd><p>
+ This interval is effectively obsolete. Previously,
+ the server would remove expired resource records
+ from the cache every <span><strong class="command">cleaning-interval</strong></span> minutes.
+ <acronym class="acronym">BIND</acronym> 9 now manages cache
+ memory in a more sophisticated manner and does not
+ rely on the periodic cleaning any more.
+ Specifying this option therefore has no effect on
+ the server's behavior.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">heartbeat-interval</strong></span></span></dt>
+<dd><p>
+ The server will perform zone maintenance tasks
+ for all zones marked as <span><strong class="command">dialup</strong></span> whenever this
+ interval expires. The default is 60 minutes. Reasonable
+ values are up
+ to 1 day (1440 minutes). The maximum value is 28 days
+ (40320 minutes).
+ If set to 0, no zone maintenance for these zones will occur.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">interface-interval</strong></span></span></dt>
+<dd><p>
+ The server will scan the network interface list
+ every <span><strong class="command">interface-interval</strong></span>
+ minutes. The default
+ is 60 minutes. The maximum value is 28 days (40320 minutes).
+ If set to 0, interface scanning will only occur when
+ the configuration file is loaded. After the scan, the
+ server will
+ begin listening for queries on any newly discovered
+ interfaces (provided they are allowed by the
+ <span><strong class="command">listen-on</strong></span> configuration), and
+ will
+ stop listening on interfaces that have gone away.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">statistics-interval</strong></span></span></dt>
+<dd>
+<p>
+ Name server statistics will be logged
+ every <span><strong class="command">statistics-interval</strong></span>
+ minutes. The default is
+ 60. The maximum value is 28 days (40320 minutes).
+ If set to 0, no statistics will be logged.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ Not yet implemented in
+ <acronym class="acronym">BIND</acronym> 9.
+ </p>
+</div>
+</dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="topology"></a>Topology</h4></div></div></div>
+<p>
+ All other things being equal, when the server chooses a name
+ server
+ to query from a list of name servers, it prefers the one that is
+ topologically closest to itself. The <span><strong class="command">topology</strong></span> statement
+ takes an <span><strong class="command">address_match_list</strong></span> and
+ interprets it
+ in a special way. Each top-level list element is assigned a
+ distance.
+ Non-negated elements get a distance based on their position in the
+ list, where the closer the match is to the start of the list, the
+ shorter the distance is between it and the server. A negated match
+ will be assigned the maximum distance from the server. If there
+ is no match, the address will get a distance which is further than
+ any non-negated list element, and closer than any negated element.
+ For example,
+ </p>
+<pre class="programlisting">topology {
+ 10/8;
+ !1.2.3/24;
+ { 1.2/16; 3/8; };
+};</pre>
+<p>
+ will prefer servers on network 10 the most, followed by hosts
+ on network 1.2.0.0 (netmask 255.255.0.0) and network 3, with the
+ exception of hosts on network 1.2.3 (netmask 255.255.255.0), which
+ is preferred least of all.
+ </p>
+<p>
+ The default topology is
+ </p>
+<pre class="programlisting"> topology { localhost; localnets; };
+</pre>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ The <span><strong class="command">topology</strong></span> option
+ is not implemented in <acronym class="acronym">BIND</acronym> 9.
+ </p>
+</div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="the_sortlist_statement"></a>The <span><strong class="command">sortlist</strong></span> Statement</h4></div></div></div>
+<p>
+ The response to a DNS query may consist of multiple resource
+ records (RRs) forming a resource records set (RRset).
+ The name server will normally return the
+ RRs within the RRset in an indeterminate order
+ (but see the <span><strong class="command">rrset-order</strong></span>
+ statement in <a href="Bv9ARM.ch06.html#rrset_ordering" title="RRset Ordering">the section called &#8220;RRset Ordering&#8221;</a>).
+ The client resolver code should rearrange the RRs as appropriate,
+ that is, using any addresses on the local net in preference to
+ other addresses.
+ However, not all resolvers can do this or are correctly
+ configured.
+ When a client is using a local server, the sorting can be performed
+ in the server, based on the client's address. This only requires
+ configuring the name servers, not all the clients.
+ </p>
+<p>
+ The <span><strong class="command">sortlist</strong></span> statement (see below)
+ takes
+ an <span><strong class="command">address_match_list</strong></span> and
+ interprets it even
+ more specifically than the <span><strong class="command">topology</strong></span>
+ statement
+ does (<a href="Bv9ARM.ch06.html#topology" title="Topology">the section called &#8220;Topology&#8221;</a>).
+ Each top level statement in the <span><strong class="command">sortlist</strong></span> must
+ itself be an explicit <span><strong class="command">address_match_list</strong></span> with
+ one or two elements. The first element (which may be an IP
+ address,
+ an IP prefix, an ACL name or a nested <span><strong class="command">address_match_list</strong></span>)
+ of each top level list is checked against the source address of
+ the query until a match is found.
+ </p>
+<p>
+ Once the source address of the query has been matched, if
+ the top level statement contains only one element, the actual
+ primitive
+ element that matched the source address is used to select the
+ address
+ in the response to move to the beginning of the response. If the
+ statement is a list of two elements, then the second element is
+ treated the same as the <span><strong class="command">address_match_list</strong></span> in
+ a <span><strong class="command">topology</strong></span> statement. Each top
+ level element
+ is assigned a distance and the address in the response with the
+ minimum
+ distance is moved to the beginning of the response.
+ </p>
+<p>
+ In the following example, any queries received from any of
+ the addresses of the host itself will get responses preferring
+ addresses
+ on any of the locally connected networks. Next most preferred are
+ addresses
+ on the 192.168.1/24 network, and after that either the
+ 192.168.2/24
+ or
+ 192.168.3/24 network with no preference shown between these two
+ networks. Queries received from a host on the 192.168.1/24 network
+ will prefer other addresses on that network to the 192.168.2/24
+ and
+ 192.168.3/24 networks. Queries received from a host on the
+ 192.168.4/24
+ or the 192.168.5/24 network will only prefer other addresses on
+ their directly connected networks.
+ </p>
+<pre class="programlisting">sortlist {
+ { localhost; // IF the local host
+ { localnets; // THEN first fit on the
+ 192.168.1/24; // following nets
+ { 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
+ { 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
+ { 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
+ { 192.168.1/24; 192.168.2/24; }; }; };
+ { { 192.168.4/24; 192.168.5/24; }; // if .4 or .5, prefer that net
+ };
+};</pre>
+<p>
+ The following example will give reasonable behavior for the
+ local host and hosts on directly connected networks. It is similar
+ to the behavior of the address sort in <acronym class="acronym">BIND</acronym> 4.9.x. Responses sent
+ to queries from the local host will favor any of the directly
+ connected
+ networks. Responses sent to queries from any other hosts on a
+ directly
+ connected network will prefer addresses on that same network.
+ Responses
+ to other queries will not be sorted.
+ </p>
+<pre class="programlisting">sortlist {
+ { localhost; localnets; };
+ { localnets; };
+};
+</pre>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="rrset_ordering"></a>RRset Ordering</h4></div></div></div>
+<p>
+ When multiple records are returned in an answer it may be
+ useful to configure the order of the records placed into the
+ response.
+ The <span><strong class="command">rrset-order</strong></span> statement permits
+ configuration
+ of the ordering of the records in a multiple record response.
+ See also the <span><strong class="command">sortlist</strong></span> statement,
+ <a href="Bv9ARM.ch06.html#the_sortlist_statement" title="The sortlist Statement">the section called &#8220;The <span><strong class="command">sortlist</strong></span> Statement&#8221;</a>.
+ </p>
+<p>
+ An <span><strong class="command">order_spec</strong></span> is defined as
+ follows:
+ </p>
+<p>
+ [<span class="optional">class <em class="replaceable"><code>class_name</code></em></span>]
+ [<span class="optional">type <em class="replaceable"><code>type_name</code></em></span>]
+ [<span class="optional">name <em class="replaceable"><code>"domain_name"</code></em></span>]
+ order <em class="replaceable"><code>ordering</code></em>
+ </p>
+<p>
+ If no class is specified, the default is <span><strong class="command">ANY</strong></span>.
+ If no type is specified, the default is <span><strong class="command">ANY</strong></span>.
+ If no name is specified, the default is "<span><strong class="command">*</strong></span>" (asterisk).
+ </p>
+<p>
+ The legal values for <span><strong class="command">ordering</strong></span> are:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p><span><strong class="command">fixed</strong></span></p>
+ </td>
+<td>
+ <p>
+ Records are returned in the order they
+ are defined in the zone file.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">random</strong></span></p>
+ </td>
+<td>
+ <p>
+ Records are returned in some random order.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">cyclic</strong></span></p>
+ </td>
+<td>
+ <p>
+ Records are returned in a cyclic round-robin order.
+ </p>
+ <p>
+ If <acronym class="acronym">BIND</acronym> is configured with the
+ "--enable-fixed-rrset" option at compile time, then
+ the initial ordering of the RRset will match the
+ one specified in the zone file.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ For example:
+ </p>
+<pre class="programlisting">rrset-order {
+ class IN type A name "host.example.com" order random;
+ order cyclic;
+};
+</pre>
+<p>
+ will cause any responses for type A records in class IN that
+ have "<code class="literal">host.example.com</code>" as a
+ suffix, to always be returned
+ in random order. All other records are returned in cyclic order.
+ </p>
+<p>
+ If multiple <span><strong class="command">rrset-order</strong></span> statements
+ appear,
+ they are not combined &#8212; the last one applies.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ In this release of <acronym class="acronym">BIND</acronym> 9, the
+ <span><strong class="command">rrset-order</strong></span> statement does not support
+ "fixed" ordering by default. Fixed ordering can be enabled
+ at compile time by specifying "--enable-fixed-rrset" on
+ the "configure" command line.
+ </p>
+</div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="tuning"></a>Tuning</h4></div></div></div>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">lame-ttl</strong></span></span></dt>
+<dd><p>
+ Sets the number of seconds to cache a
+ lame server indication. 0 disables caching. (This is
+ <span class="bold"><strong>NOT</strong></span> recommended.)
+ The default is <code class="literal">600</code> (10 minutes) and the
+ maximum value is
+ <code class="literal">1800</code> (30 minutes).
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-ncache-ttl</strong></span></span></dt>
+<dd><p>
+ To reduce network traffic and increase performance,
+ the server stores negative answers. <span><strong class="command">max-ncache-ttl</strong></span> is
+ used to set a maximum retention time for these answers in
+ the server
+ in seconds. The default
+ <span><strong class="command">max-ncache-ttl</strong></span> is <code class="literal">10800</code> seconds (3 hours).
+ <span><strong class="command">max-ncache-ttl</strong></span> cannot exceed
+ 7 days and will
+ be silently truncated to 7 days if set to a greater value.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-cache-ttl</strong></span></span></dt>
+<dd><p>
+ Sets the maximum time for which the server will
+ cache ordinary (positive) answers. The default is
+ one week (7 days).
+ A value of zero may cause all queries to return
+ SERVFAIL, because of lost caches of intermediate
+ RRsets (such as NS and glue AAAA/A records) in the
+ resolution process.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">min-roots</strong></span></span></dt>
+<dd>
+<p>
+ The minimum number of root servers that
+ is required for a request for the root servers to be
+ accepted. The default
+ is <strong class="userinput"><code>2</code></strong>.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ Not implemented in <acronym class="acronym">BIND</acronym> 9.
+ </p>
+</div>
+</dd>
+<dt><span class="term"><span><strong class="command">sig-validity-interval</strong></span></span></dt>
+<dd>
+<p>
+ Specifies the number of days into the future when
+ DNSSEC signatures automatically generated as a
+ result of dynamic updates (<a href="Bv9ARM.ch04.html#dynamic_update" title="Dynamic Update">the section called &#8220;Dynamic Update&#8221;</a>) will expire. There
+ is a 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
+ field is specified in days if the base interval is
+ greater than 7 days otherwise it is specified in hours.
+ The default base interval is <code class="literal">30</code> days
+ giving a re-signing interval of 7 1/2 days. The maximum
+ values are 10 years (3660 days).
+ </p>
+<p>
+ The signature inception time is unconditionally
+ set to one hour before the current time to allow
+ for a limited amount of clock skew.
+ </p>
+<p>
+ The <span><strong class="command">sig-validity-interval</strong></span>
+ should be, at least, several multiples of the SOA
+ expire interval to allow for reasonable interaction
+ between the various timer and expiry dates.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">sig-signing-nodes</strong></span></span></dt>
+<dd><p>
+ Specify the maximum number of nodes to be
+ examined in each quantum when signing a zone with
+ a new DNSKEY. The default is
+ <code class="literal">100</code>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">sig-signing-signatures</strong></span></span></dt>
+<dd><p>
+ Specify a threshold number of signatures that
+ will terminate processing a quantum when signing
+ a zone with a new DNSKEY. The default is
+ <code class="literal">10</code>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">sig-signing-type</strong></span></span></dt>
+<dd>
+<p>
+ Specify a private RDATA type to be used when generating
+ key signing records. The default is
+ <code class="literal">65535</code>.
+ </p>
+<p>
+ It is expected that this parameter may be removed
+ in a future version once there is a standard type.
+ </p>
+</dd>
+<dt>
+<span class="term"><span><strong class="command">min-refresh-time</strong></span>, </span><span class="term"><span><strong class="command">max-refresh-time</strong></span>, </span><span class="term"><span><strong class="command">min-retry-time</strong></span>, </span><span class="term"><span><strong class="command">max-retry-time</strong></span></span>
+</dt>
+<dd>
+<p>
+ These options control the server's behavior on refreshing a
+ zone
+ (querying for SOA changes) or retrying failed transfers.
+ Usually the SOA values for the zone are used, but these
+ values
+ are set by the master, giving slave server administrators
+ little
+ control over their contents.
+ </p>
+<p>
+ These options allow the administrator to set a minimum and
+ maximum
+ refresh and retry time either per-zone, per-view, or
+ globally.
+ These options are valid for slave and stub zones,
+ and clamp the SOA refresh and retry times to the specified
+ values.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">edns-udp-size</strong></span></span></dt>
+<dd><p>
+ Sets the advertised EDNS UDP buffer size 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 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.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-udp-size</strong></span></span></dt>
+<dd><p>
+ 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.
+ This is independent of the advertised receive
+ buffer (<span><strong class="command">edns-udp-size</strong></span>).
+ </p></dd>
+<dt><span class="term"><span><strong class="command">masterfile-format</strong></span></span></dt>
+<dd><p>Specifies
+ the file format of zone files (see
+ <a href="Bv9ARM.ch06.html#zonefile_format" title="Additional File Formats">the section called &#8220;Additional File Formats&#8221;</a>).
+ The default value is <code class="constant">text</code>, which is the
+ standard textual representation. Files in other formats
+ than <code class="constant">text</code> are typically expected
+ to be generated by the <span><strong class="command">named-compilezone</strong></span> tool.
+ Note that when a zone file in a different format than
+ <code class="constant">text</code> is loaded, <span><strong class="command">named</strong></span>
+ may omit some of the checks which would be performed for a
+ file in the <code class="constant">text</code> format. In particular,
+ <span><strong class="command">check-names</strong></span> checks do not apply
+ for the <code class="constant">raw</code> format. This means
+ a zone file in the <code class="constant">raw</code> format
+ must be generated with the same check level as that
+ specified in the <span><strong class="command">named</strong></span> configuration
+ file. This statement sets the
+ <span><strong class="command">masterfile-format</strong></span> for all zones,
+ but can be overridden on a per-zone or per-view basis
+ by including a <span><strong class="command">masterfile-format</strong></span>
+ statement within the <span><strong class="command">zone</strong></span> or
+ <span><strong class="command">view</strong></span> block in the configuration
+ file.
+ </p></dd>
+<dt>
+<span class="term"><span><strong class="command">clients-per-query</strong></span>, </span><span class="term"><span><strong class="command">max-clients-per-query</strong></span></span>
+</dt>
+<dd>
+<p>These set the
+ initial value (minimum) and maximum number of recursive
+ simultaneous clients for any given query
+ (&lt;qname,qtype,qclass&gt;) that the server will accept
+ before dropping additional clients. named will attempt to
+ self tune this value and changes will be logged. The
+ default values are 10 and 100.
+ </p>
+<p>
+ This value should reflect how many queries come in for
+ a given name in the time it takes to resolve that name.
+ If the number of queries exceed this value, named will
+ assume that it is dealing with a non-responsive zone
+ and will drop additional queries. If it gets a response
+ after dropping queries, it will raise the estimate. The
+ estimate will then be lowered in 20 minutes if it has
+ remained unchanged.
+ </p>
+<p>
+ If <span><strong class="command">clients-per-query</strong></span> is set to zero,
+ then there is no limit on the number of clients per query
+ and no queries will be dropped.
+ </p>
+<p>
+ If <span><strong class="command">max-clients-per-query</strong></span> is set to zero,
+ then there is no upper bound other than imposed by
+ <span><strong class="command">recursive-clients</strong></span>.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">notify-delay</strong></span></span></dt>
+<dd><p>
+ The delay, in seconds, between sending sets of notify
+ messages for a zone. The default is zero.
+ </p></dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="builtin"></a>Built-in server information zones</h4></div></div></div>
+<p>
+ The server provides some helpful diagnostic information
+ through a number of built-in zones under the
+ pseudo-top-level-domain <code class="literal">bind</code> in the
+ <span><strong class="command">CHAOS</strong></span> class. These zones are part
+ of a
+ built-in view (see <a href="Bv9ARM.ch06.html#view_statement_grammar" title="view Statement Grammar">the section called &#8220;<span><strong class="command">view</strong></span> Statement Grammar&#8221;</a>) of
+ class
+ <span><strong class="command">CHAOS</strong></span> which is separate from the
+ default view of
+ class <span><strong class="command">IN</strong></span>; therefore, any global
+ server options
+ such as <span><strong class="command">allow-query</strong></span> do not apply
+ the these zones.
+ If you feel the need to disable these zones, use the options
+ below, or hide the built-in <span><strong class="command">CHAOS</strong></span>
+ view by
+ defining an explicit view of class <span><strong class="command">CHAOS</strong></span>
+ that matches all clients.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">version</strong></span></span></dt>
+<dd><p>
+ The version the server should report
+ via a query of the name <code class="literal">version.bind</code>
+ with type <span><strong class="command">TXT</strong></span>, class <span><strong class="command">CHAOS</strong></span>.
+ The default is the real version number of this server.
+ Specifying <span><strong class="command">version none</strong></span>
+ disables processing of the queries.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">hostname</strong></span></span></dt>
+<dd><p>
+ The hostname the server should report via a query of
+ the name <code class="filename">hostname.bind</code>
+ with type <span><strong class="command">TXT</strong></span>, class <span><strong class="command">CHAOS</strong></span>.
+ This defaults to the hostname of the machine hosting the
+ name server as
+ found by the gethostname() function. The primary purpose of such queries
+ is to
+ identify which of a group of anycast servers is actually
+ answering your queries. Specifying <span><strong class="command">hostname none;</strong></span>
+ disables processing of the queries.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">server-id</strong></span></span></dt>
+<dd><p>
+ The ID the server should report when receiving a Name
+ Server Identifier (NSID) query, or a query of the name
+ <code class="filename">ID.SERVER</code> with type
+ <span><strong class="command">TXT</strong></span>, class <span><strong class="command">CHAOS</strong></span>.
+ The primary purpose of such queries is to
+ identify which of a group of anycast servers is actually
+ answering your queries. Specifying <span><strong class="command">server-id none;</strong></span>
+ disables processing of the queries.
+ Specifying <span><strong class="command">server-id hostname;</strong></span> will cause named to
+ use the hostname as found by the gethostname() function.
+ The default <span><strong class="command">server-id</strong></span> is <span><strong class="command">none</strong></span>.
+ </p></dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="empty"></a>Built-in Empty Zones</h4></div></div></div>
+<p>
+ Named has some built-in empty zones (SOA and NS records only).
+ These are for zones that should normally be answered locally
+ and which queries should not be sent to the Internet's root
+ servers. The official servers which cover these namespaces
+ return NXDOMAIN responses to these queries. In particular,
+ these cover the reverse namespace for addresses from RFC 1918 and
+ RFC 3330. They also include the reverse namespace for IPv6 local
+ address (locally assigned), IPv6 link local addresses, the IPv6
+ loopback address and the IPv6 unknown address.
+ </p>
+<p>
+ 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.
+ </p>
+<p>
+ The current list of empty zones is:
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li>0.IN-ADDR.ARPA</li>
+<li>127.IN-ADDR.ARPA</li>
+<li>254.169.IN-ADDR.ARPA</li>
+<li>2.0.192.IN-ADDR.ARPA</li>
+<li>255.255.255.255.IN-ADDR.ARPA</li>
+<li>0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA</li>
+<li>1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA</li>
+<li>D.F.IP6.ARPA</li>
+<li>8.E.F.IP6.ARPA</li>
+<li>9.E.F.IP6.ARPA</li>
+<li>A.E.F.IP6.ARPA</li>
+<li>B.E.F.IP6.ARPA</li>
+</ul></div>
+<p>
+ </p>
+<p>
+ Empty zones are settable at the view level and only apply to
+ views of class IN. Disabled empty zones are only inherited
+ from options if there are no disabled empty zones specified
+ at the view level. To override the options list of disabled
+ zones, you can disable the root zone at the view level, for example:
+</p>
+<pre class="programlisting">
+ disable-empty-zone ".";
+</pre>
+<p>
+ </p>
+<p>
+ If you are using the address ranges covered here, you should
+ already have reverse zones covering the addresses you use.
+ In practice this appears to not be the case with many queries
+ being made to the infrastructure servers for names in these
+ spaces. So many in fact that sacrificial servers were needed
+ to be deployed to channel the query load away from the
+ infrastructure servers.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+ The real parent servers for these zones should disable all
+ empty zone under the parent zone they serve. For the real
+ root servers, this is all built in empty zones. This will
+ enable them to return referrals to deeper in the tree.
+ </div>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">empty-server</strong></span></span></dt>
+<dd><p>
+ Specify what server name will appear in the returned
+ SOA record for empty zones. If none is specified, then
+ the zone's name will be used.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">empty-contact</strong></span></span></dt>
+<dd><p>
+ Specify what contact name will appear in the returned
+ SOA record for empty zones. If none is specified, then
+ "." will be used.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">empty-zones-enable</strong></span></span></dt>
+<dd><p>
+ Enable or disable all empty zones. By default they
+ are enabled.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">disable-empty-zone</strong></span></span></dt>
+<dd><p>
+ Disable individual empty zones. By default none are
+ disabled. This option can be specified multiple times.
+ </p></dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="acache"></a>Additional Section Caching</h4></div></div></div>
+<p>
+ The additional section cache, also called <span><strong class="command">acache</strong></span>,
+ is an internal cache to improve the response performance of BIND 9.
+ When additional section caching is enabled, BIND 9 will
+ cache an internal short-cut to the additional section content for
+ each answer RR.
+ Note that <span><strong class="command">acache</strong></span> is an internal caching
+ mechanism of BIND 9, and is not related to the DNS caching
+ server function.
+ </p>
+<p>
+ Additional section caching does not change the
+ response content (except the RRsets ordering of the additional
+ section, see below), but can improve the response performance
+ significantly.
+ It is particularly effective when BIND 9 acts as an authoritative
+ server for a zone that has many delegations with many glue RRs.
+ </p>
+<p>
+ In order to obtain the maximum performance improvement
+ from additional section caching, setting
+ <span><strong class="command">additional-from-cache</strong></span>
+ to <span><strong class="command">no</strong></span> is recommended, since the current
+ implementation of <span><strong class="command">acache</strong></span>
+ does not short-cut of additional section information from the
+ DNS cache data.
+ </p>
+<p>
+ One obvious disadvantage of <span><strong class="command">acache</strong></span> is
+ that it requires much more
+ memory for the internal cached data.
+ Thus, if the response performance does not matter and memory
+ consumption is much more critical, the
+ <span><strong class="command">acache</strong></span> mechanism can be
+ disabled by setting <span><strong class="command">acache-enable</strong></span> to
+ <span><strong class="command">no</strong></span>.
+ It is also possible to specify the upper limit of memory
+ consumption
+ for acache by using <span><strong class="command">max-acache-size</strong></span>.
+ </p>
+<p>
+ Additional section caching also has a minor effect on the
+ RRset ordering in the additional section.
+ Without <span><strong class="command">acache</strong></span>,
+ <span><strong class="command">cyclic</strong></span> order is effective for the additional
+ section as well as the answer and authority sections.
+ However, additional section caching fixes the ordering when it
+ first caches an RRset for the additional section, and the same
+ ordering will be kept in succeeding responses, regardless of the
+ setting of <span><strong class="command">rrset-order</strong></span>.
+ The effect of this should be minor, however, since an
+ RRset in the additional section
+ typically only contains a small number of RRs (and in many cases
+ it only contains a single RR), in which case the
+ ordering does not matter much.
+ </p>
+<p>
+ The following is a summary of options related to
+ <span><strong class="command">acache</strong></span>.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">acache-enable</strong></span></span></dt>
+<dd><p>
+ If <span><strong class="command">yes</strong></span>, additional section caching is
+ enabled. The default value is <span><strong class="command">no</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">acache-cleaning-interval</strong></span></span></dt>
+<dd><p>
+ The server will remove stale cache entries, based on an LRU
+ based
+ algorithm, every <span><strong class="command">acache-cleaning-interval</strong></span> minutes.
+ The default is 60 minutes.
+ If set to 0, no periodic cleaning will occur.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-acache-size</strong></span></span></dt>
+<dd><p>
+ The maximum amount of memory in bytes to use for the server's acache.
+ When the amount of data in the acache reaches this limit,
+ the server
+ will clean more aggressively so that the limit is not
+ exceeded.
+ In a server with multiple views, the limit applies
+ separately to the
+ acache of each view.
+ The default is <code class="literal">16M</code>.
+ </p></dd>
+</dl></div>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="statschannels"></a><span><strong class="command">statistics-channels</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">statistics-channels</strong></span> {
+ [ inet ( ip_addr | * ) [ port ip_port ] [allow { <em class="replaceable"><code> address_match_list </code></em> } ]; ]
+ [ inet ...; ]
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2585469"></a><span><strong class="command">statistics-channels</strong></span> Statement Definition and
+ Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">statistics-channels</strong></span> statement
+ declares communication channels to be used by system
+ administrators to get access to statistics information of
+ the name server.
+ </p>
+<p>
+ This statement intends to be flexible to support multiple
+ communication protocols in the future, but currently only
+ HTTP access is supported.
+ It requires that BIND 9 be compiled with libxml2;
+ the <span><strong class="command">statistics-channels</strong></span> statement is
+ still accepted even if it is built without the library,
+ but any HTTP access will fail with an error.
+ </p>
+<p>
+ An <span><strong class="command">inet</strong></span> control channel is a TCP socket
+ listening at the specified <span><strong class="command">ip_port</strong></span> on the
+ specified <span><strong class="command">ip_addr</strong></span>, which can be an IPv4 or IPv6
+ address. An <span><strong class="command">ip_addr</strong></span> of <code class="literal">*</code> (asterisk) is
+ interpreted as the IPv4 wildcard address; connections will be
+ accepted on any of the system's IPv4 addresses.
+ To listen on the IPv6 wildcard address,
+ use an <span><strong class="command">ip_addr</strong></span> of <code class="literal">::</code>.
+ </p>
+<p>
+ If no port is specified, port 80 is used for HTTP channels.
+ The asterisk "<code class="literal">*</code>" cannot be used for
+ <span><strong class="command">ip_port</strong></span>.
+ </p>
+<p>
+ The attempt of opening a statistics channel is
+ restricted by the optional <span><strong class="command">allow</strong></span> clause.
+ Connections to the statistics channel are permitted based on the
+ <span><strong class="command">address_match_list</strong></span>.
+ If no <span><strong class="command">allow</strong></span> clause is present,
+ <span><strong class="command">named</strong></span> accepts connection
+ attempts from any address; since the statistics may
+ contain sensitive internal information, it is highly
+ recommended to restrict the source of connection requests
+ appropriately.
+ </p>
+<p>
+ If no <span><strong class="command">statistics-channels</strong></span> statement is present,
+ <span><strong class="command">named</strong></span> will not open any communication channels.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="server_statement_grammar"></a><span><strong class="command">server</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">server</strong></span> <em class="replaceable"><code>ip_addr[/prefixlen]</code></em> {
+ [<span class="optional"> bogus <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> provide-ixfr <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> request-ixfr <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> edns <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> edns-udp-size <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-udp-size <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> transfers <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> transfer-format <em class="replaceable"><code>( one-answer | many-answers )</code></em> ; ]</span>]
+ [<span class="optional"> keys <em class="replaceable"><code>{ string ; [<span class="optional"> string ; [<span class="optional">...</span>]</span>] }</code></em> ; </span>]
+ [<span class="optional"> transfer-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> transfer-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> notify-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> notify-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> query-source [<span class="optional"> address ( <em class="replaceable"><code>ip_addr</code></em> | <em class="replaceable"><code>*</code></em> ) </span>] [<span class="optional"> port ( <em class="replaceable"><code>ip_port</code></em> | <em class="replaceable"><code>*</code></em> ) </span>]; </span>]
+ [<span class="optional"> query-source-v6 [<span class="optional"> address ( <em class="replaceable"><code>ip_addr</code></em> | <em class="replaceable"><code>*</code></em> ) </span>] [<span class="optional"> port ( <em class="replaceable"><code>ip_port</code></em> | <em class="replaceable"><code>*</code></em> ) </span>]; </span>]
+ [<span class="optional"> use-queryport-pool <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> queryport-pool-ports <em class="replaceable"><code>number</code></em>; </span>]
+ [<span class="optional"> queryport-pool-interval <em class="replaceable"><code>number</code></em>; </span>]
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="server_statement_definition_and_usage"></a><span><strong class="command">server</strong></span> Statement Definition and
+ Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">server</strong></span> statement defines
+ characteristics
+ to be associated with a remote name server. If a prefix length is
+ specified, then a range of servers is covered. Only the most
+ specific
+ server clause applies regardless of the order in
+ <code class="filename">named.conf</code>.
+ </p>
+<p>
+ The <span><strong class="command">server</strong></span> statement can occur at
+ the top level of the
+ configuration file or inside a <span><strong class="command">view</strong></span>
+ statement.
+ If a <span><strong class="command">view</strong></span> statement contains
+ one or more <span><strong class="command">server</strong></span> statements, only
+ those
+ apply to the view and any top-level ones are ignored.
+ If a view contains no <span><strong class="command">server</strong></span>
+ statements,
+ any top-level <span><strong class="command">server</strong></span> statements are
+ used as
+ defaults.
+ </p>
+<p>
+ If you discover that a remote server is giving out bad data,
+ marking it as bogus will prevent further queries to it. The
+ default
+ value of <span><strong class="command">bogus</strong></span> is <span><strong class="command">no</strong></span>.
+ </p>
+<p>
+ The <span><strong class="command">provide-ixfr</strong></span> clause determines
+ whether
+ the local server, acting as master, will respond with an
+ incremental
+ zone transfer when the given remote server, a slave, requests it.
+ If set to <span><strong class="command">yes</strong></span>, incremental transfer
+ will be provided
+ whenever possible. If set to <span><strong class="command">no</strong></span>,
+ all transfers
+ to the remote server will be non-incremental. If not set, the
+ value
+ of the <span><strong class="command">provide-ixfr</strong></span> option in the
+ view or
+ global options block is used as a default.
+ </p>
+<p>
+ The <span><strong class="command">request-ixfr</strong></span> clause determines
+ whether
+ the local server, acting as a slave, will request incremental zone
+ transfers from the given remote server, a master. If not set, the
+ value of the <span><strong class="command">request-ixfr</strong></span> option in
+ the view or
+ global options block is used as a default.
+ </p>
+<p>
+ IXFR requests to servers that do not support IXFR will
+ automatically
+ fall back to AXFR. Therefore, there is no need to manually list
+ which servers support IXFR and which ones do not; the global
+ default
+ of <span><strong class="command">yes</strong></span> should always work.
+ The purpose of the <span><strong class="command">provide-ixfr</strong></span> and
+ <span><strong class="command">request-ixfr</strong></span> clauses is
+ to make it possible to disable the use of IXFR even when both
+ master
+ and slave claim to support it, for example if one of the servers
+ is buggy and crashes or corrupts data when IXFR is used.
+ </p>
+<p>
+ The <span><strong class="command">edns</strong></span> clause determines whether
+ the local server will attempt to use EDNS when communicating
+ with the remote server. The default is <span><strong class="command">yes</strong></span>.
+ </p>
+<p>
+ The <span><strong class="command">edns-udp-size</strong></span> option sets the EDNS UDP size
+ that is advertised by named when querying the remote server.
+ Valid values are 512 to 4096 bytes (values outside this range will be
+ silently adjusted). This option is useful when you wish to
+ advertises a different value to this server than the value you
+ advertise globally, for example, when there is a firewall at the
+ remote site that is blocking large replies.
+ </p>
+<p>
+ The <span><strong class="command">max-udp-size</strong></span> option sets the
+ maximum EDNS UDP message size named will send. Valid
+ values are 512 to 4096 bytes (values outside this range will
+ be silently adjusted). This option is useful when you
+ know that there is a firewall that is blocking large
+ replies from named.
+ </p>
+<p>
+ The server supports two zone transfer methods. The first, <span><strong class="command">one-answer</strong></span>,
+ uses one DNS message per resource record transferred. <span><strong class="command">many-answers</strong></span> packs
+ as many resource records as possible into a message. <span><strong class="command">many-answers</strong></span> is
+ more efficient, but is only known to be understood by <acronym class="acronym">BIND</acronym> 9, <acronym class="acronym">BIND</acronym>
+ 8.x, and patched versions of <acronym class="acronym">BIND</acronym>
+ 4.9.5. You can specify which method
+ to use for a server with the <span><strong class="command">transfer-format</strong></span> option.
+ If <span><strong class="command">transfer-format</strong></span> is not
+ specified, the <span><strong class="command">transfer-format</strong></span>
+ specified
+ by the <span><strong class="command">options</strong></span> statement will be
+ used.
+ </p>
+<p><span><strong class="command">transfers</strong></span>
+ is used to limit the number of concurrent inbound zone
+ transfers from the specified server. If no
+ <span><strong class="command">transfers</strong></span> clause is specified, the
+ limit is set according to the
+ <span><strong class="command">transfers-per-ns</strong></span> option.
+ </p>
+<p>
+ The <span><strong class="command">keys</strong></span> clause identifies a
+ <span><strong class="command">key_id</strong></span> defined by the <span><strong class="command">key</strong></span> statement,
+ to be used for transaction security (TSIG, <a href="Bv9ARM.ch04.html#tsig" title="TSIG">the section called &#8220;TSIG&#8221;</a>)
+ when talking to the remote server.
+ When a request is sent to the remote server, a request signature
+ will be generated using the key specified here and appended to the
+ message. A request originating from the remote server is not
+ required
+ to be signed by this key.
+ </p>
+<p>
+ Although the grammar of the <span><strong class="command">keys</strong></span>
+ clause
+ allows for multiple keys, only a single key per server is
+ currently
+ supported.
+ </p>
+<p>
+ The <span><strong class="command">transfer-source</strong></span> and
+ <span><strong class="command">transfer-source-v6</strong></span> clauses specify
+ the IPv4 and IPv6 source
+ address to be used for zone transfer with the remote server,
+ respectively.
+ For an IPv4 remote server, only <span><strong class="command">transfer-source</strong></span> can
+ be specified.
+ Similarly, for an IPv6 remote server, only
+ <span><strong class="command">transfer-source-v6</strong></span> can be
+ specified.
+ For more details, see the description of
+ <span><strong class="command">transfer-source</strong></span> and
+ <span><strong class="command">transfer-source-v6</strong></span> in
+ <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p>
+<p>
+ The <span><strong class="command">notify-source</strong></span> and
+ <span><strong class="command">notify-source-v6</strong></span> clauses specify the
+ IPv4 and IPv6 source address to be used for notify
+ messages sent to remote servers, respectively. For an
+ IPv4 remote server, only <span><strong class="command">notify-source</strong></span>
+ can be specified. Similarly, for an IPv6 remote server,
+ only <span><strong class="command">notify-source-v6</strong></span> can be specified.
+ </p>
+<p>
+ The <span><strong class="command">query-source</strong></span> and
+ <span><strong class="command">query-source-v6</strong></span> clauses specify the
+ IPv4 and IPv6 source address to be used for queries
+ sent to remote servers, respectively. For an IPv4
+ remote server, only <span><strong class="command">query-source</strong></span> can
+ be specified. Similarly, for an IPv6 remote server,
+ only <span><strong class="command">query-source-v6</strong></span> can be specified.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2586153"></a><span><strong class="command">trusted-keys</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">trusted-keys</strong></span> {
+ <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>string</code></em> ;
+ [<span class="optional"> <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>string</code></em> ; [<span class="optional">...</span>]</span>]
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2586204"></a><span><strong class="command">trusted-keys</strong></span> Statement Definition
+ and Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">trusted-keys</strong></span> statement defines
+ DNSSEC security roots. DNSSEC is described in <a href="Bv9ARM.ch04.html#DNSSEC" title="DNSSEC">the section called &#8220;DNSSEC&#8221;</a>. A security root is defined when the
+ public key for a non-authoritative zone is known, but
+ cannot be securely obtained through DNS, either because
+ it is the DNS root zone or because its parent zone is
+ unsigned. Once a key has been configured as a trusted
+ key, it is treated as if it had been validated and
+ proven secure. The resolver attempts DNSSEC validation
+ on all DNS data in subdomains of a security root.
+ </p>
+<p>
+ All keys (and corresponding zones) listed in
+ <span><strong class="command">trusted-keys</strong></span> are deemed to exist regardless
+ of what parent zones say. Similarly for all keys listed in
+ <span><strong class="command">trusted-keys</strong></span> only those keys are
+ used to validate the DNSKEY RRset. The parent's DS RRset
+ will not be used.
+ </p>
+<p>
+ The <span><strong class="command">trusted-keys</strong></span> statement can contain
+ multiple key entries, each consisting of the key's
+ domain name, flags, protocol, algorithm, and the Base-64
+ representation of the key data.
+ Spaces, tabs, newlines and carriage returns are ignored
+ in the key data, so the configuration may be split up into
+ multiple lines.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="view_statement_grammar"></a><span><strong class="command">view</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">view</strong></span> <em class="replaceable"><code>view_name</code></em>
+ [<span class="optional"><em class="replaceable"><code>class</code></em></span>] {
+ match-clients { <em class="replaceable"><code>address_match_list</code></em> };
+ match-destinations { <em class="replaceable"><code>address_match_list</code></em> };
+ match-recursive-only <em class="replaceable"><code>yes_or_no</code></em> ;
+ [<span class="optional"> <em class="replaceable"><code>view_option</code></em>; ...</span>]
+ [<span class="optional"> <em class="replaceable"><code>zone_statement</code></em>; ...</span>]
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2586423"></a><span><strong class="command">view</strong></span> Statement Definition and Usage</h3></div></div></div>
+<p>
+ The <span><strong class="command">view</strong></span> statement is a powerful
+ feature
+ of <acronym class="acronym">BIND</acronym> 9 that lets a name server
+ answer a DNS query differently
+ depending on who is asking. It is particularly useful for
+ implementing
+ split DNS setups without having to run multiple servers.
+ </p>
+<p>
+ Each <span><strong class="command">view</strong></span> statement defines a view
+ of the
+ DNS namespace that will be seen by a subset of clients. A client
+ matches
+ a view if its source IP address matches the
+ <code class="varname">address_match_list</code> of the view's
+ <span><strong class="command">match-clients</strong></span> clause and its
+ destination IP address matches
+ the <code class="varname">address_match_list</code> of the
+ view's
+ <span><strong class="command">match-destinations</strong></span> clause. If not
+ specified, both
+ <span><strong class="command">match-clients</strong></span> and <span><strong class="command">match-destinations</strong></span>
+ default to matching all addresses. In addition to checking IP
+ addresses
+ <span><strong class="command">match-clients</strong></span> and <span><strong class="command">match-destinations</strong></span>
+ can also take <span><strong class="command">keys</strong></span> which provide an
+ mechanism for the
+ client to select the view. A view can also be specified
+ as <span><strong class="command">match-recursive-only</strong></span>, which
+ means that only recursive
+ requests from matching clients will match that view.
+ The order of the <span><strong class="command">view</strong></span> statements is
+ significant &#8212;
+ a client request will be resolved in the context of the first
+ <span><strong class="command">view</strong></span> that it matches.
+ </p>
+<p>
+ Zones defined within a <span><strong class="command">view</strong></span>
+ statement will
+ only be accessible to clients that match the <span><strong class="command">view</strong></span>.
+ By defining a zone of the same name in multiple views, different
+ zone data can be given to different clients, for example,
+ "internal"
+ and "external" clients in a split DNS setup.
+ </p>
+<p>
+ Many of the options given in the <span><strong class="command">options</strong></span> statement
+ can also be used within a <span><strong class="command">view</strong></span>
+ statement, and then
+ apply only when resolving queries with that view. When no
+ view-specific
+ value is given, the value in the <span><strong class="command">options</strong></span> statement
+ is used as a default. Also, zone options can have default values
+ specified
+ in the <span><strong class="command">view</strong></span> statement; these
+ view-specific defaults
+ take precedence over those in the <span><strong class="command">options</strong></span> statement.
+ </p>
+<p>
+ Views are class specific. If no class is given, class IN
+ is assumed. Note that all non-IN views must contain a hint zone,
+ since only the IN class has compiled-in default hints.
+ </p>
+<p>
+ If there are no <span><strong class="command">view</strong></span> statements in
+ the config
+ file, a default view that matches any client is automatically
+ created
+ in class IN. Any <span><strong class="command">zone</strong></span> statements
+ specified on
+ the top level of the configuration file are considered to be part
+ of
+ this default view, and the <span><strong class="command">options</strong></span>
+ statement will
+ apply to the default view. If any explicit <span><strong class="command">view</strong></span>
+ statements are present, all <span><strong class="command">zone</strong></span>
+ statements must
+ occur inside <span><strong class="command">view</strong></span> statements.
+ </p>
+<p>
+ Here is an example of a typical split DNS setup implemented
+ using <span><strong class="command">view</strong></span> statements:
+ </p>
+<pre class="programlisting">view "internal" {
+ // This should match our internal networks.
+ match-clients { 10.0.0.0/8; };
+
+ // Provide recursive service to internal clients only.
+ recursion yes;
+
+ // Provide a complete view of the example.com zone
+ // including addresses of internal hosts.
+ zone "example.com" {
+ type master;
+ file "example-internal.db";
+ };
+};
+
+view "external" {
+ // 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.
+ zone "example.com" {
+ type master;
+ file "example-external.db";
+ };
+};
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="zone_statement_grammar"></a><span><strong class="command">zone</strong></span>
+ Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">zone</strong></span> <em class="replaceable"><code>zone_name</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em></span>] {
+ type master;
+ [<span class="optional"> allow-query { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-query-on { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-transfer { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-update { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> update-policy { <em class="replaceable"><code>update_policy_rule</code></em> [<span class="optional">...</span>] }; </span>]
+ [<span class="optional"> also-notify { <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; [<span class="optional"> <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; ... </span>] }; </span>]
+ [<span class="optional"> check-names (<code class="constant">warn</code>|<code class="constant">fail</code>|<code class="constant">ignore</code>) ; </span>]
+ [<span class="optional"> check-mx (<code class="constant">warn</code>|<code class="constant">fail</code>|<code class="constant">ignore</code>) ; </span>]
+ [<span class="optional"> check-wildcard <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> check-integrity <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> dialup <em class="replaceable"><code>dialup_option</code></em> ; </span>]
+ [<span class="optional"> file <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> masterfile-format (<code class="constant">text</code>|<code class="constant">raw</code>) ; </span>]
+ [<span class="optional"> journal <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> max-journal-size <em class="replaceable"><code>size_spec</code></em>; </span>]
+ [<span class="optional"> forward (<code class="constant">only</code>|<code class="constant">first</code>) ; </span>]
+ [<span class="optional"> forwarders { [<span class="optional"> <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; ... </span>] }; </span>]
+ [<span class="optional"> ixfr-base <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> ixfr-from-differences <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> ixfr-tmp-file <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> maintain-ixfr-base <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> max-ixfr-log-size <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-transfer-idle-out <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-transfer-time-out <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> notify <em class="replaceable"><code>yes_or_no</code></em> | <em class="replaceable"><code>explicit</code></em> | <em class="replaceable"><code>master-only</code></em> ; </span>]
+ [<span class="optional"> notify-delay <em class="replaceable"><code>seconds</code></em> ; </span>]
+ [<span class="optional"> notify-to-soa <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> pubkey <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> notify-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> notify-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> zone-statistics <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> sig-validity-interval <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> sig-signing-nodes <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> sig-signing-signatures <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> sig-signing-type <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> database <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> min-refresh-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-refresh-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> min-retry-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-retry-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> key-directory <em class="replaceable"><code>path_name</code></em>; </span>]
+ [<span class="optional"> zero-no-soa-ttl <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+};
+
+zone <em class="replaceable"><code>zone_name</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em></span>] {
+ type slave;
+ [<span class="optional"> allow-notify { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-query { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-query-on { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-transfer { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-update-forwarding { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> update-check-ksk <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> try-tcp-refresh <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> also-notify { <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; [<span class="optional"> <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; ... </span>] }; </span>]
+ [<span class="optional"> check-names (<code class="constant">warn</code>|<code class="constant">fail</code>|<code class="constant">ignore</code>) ; </span>]
+ [<span class="optional"> dialup <em class="replaceable"><code>dialup_option</code></em> ; </span>]
+ [<span class="optional"> file <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> masterfile-format (<code class="constant">text</code>|<code class="constant">raw</code>) ; </span>]
+ [<span class="optional"> journal <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> max-journal-size <em class="replaceable"><code>size_spec</code></em>; </span>]
+ [<span class="optional"> forward (<code class="constant">only</code>|<code class="constant">first</code>) ; </span>]
+ [<span class="optional"> forwarders { [<span class="optional"> <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; ... </span>] }; </span>]
+ [<span class="optional"> ixfr-base <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> ixfr-from-differences <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> ixfr-tmp-file <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> maintain-ixfr-base <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> masters [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] { ( <em class="replaceable"><code>masters_list</code></em> | <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] [<span class="optional">key <em class="replaceable"><code>key</code></em></span>] ) ; [<span class="optional">...</span>] }; </span>]
+ [<span class="optional"> max-ixfr-log-size <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-transfer-idle-in <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-transfer-idle-out <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-transfer-time-in <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-transfer-time-out <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> notify <em class="replaceable"><code>yes_or_no</code></em> | <em class="replaceable"><code>explicit</code></em> | <em class="replaceable"><code>master-only</code></em> ; </span>]
+ [<span class="optional"> notify-delay <em class="replaceable"><code>seconds</code></em> ; </span>]
+ [<span class="optional"> notify-to-soa <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> pubkey <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> transfer-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> transfer-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> alt-transfer-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> alt-transfer-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> use-alt-transfer-source <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> notify-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> notify-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> zone-statistics <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> database <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> min-refresh-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-refresh-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> min-retry-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-retry-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> multi-master <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> zero-no-soa-ttl <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+};
+
+zone <em class="replaceable"><code>zone_name</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em></span>] {
+ type hint;
+ file <em class="replaceable"><code>string</code></em> ;
+ [<span class="optional"> delegation-only <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> check-names (<code class="constant">warn</code>|<code class="constant">fail</code>|<code class="constant">ignore</code>) ; // Not Implemented. </span>]
+};
+
+zone <em class="replaceable"><code>zone_name</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em></span>] {
+ type stub;
+ [<span class="optional"> allow-query { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> allow-query-on { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+ [<span class="optional"> check-names (<code class="constant">warn</code>|<code class="constant">fail</code>|<code class="constant">ignore</code>) ; </span>]
+ [<span class="optional"> dialup <em class="replaceable"><code>dialup_option</code></em> ; </span>]
+ [<span class="optional"> delegation-only <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> file <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> masterfile-format (<code class="constant">text</code>|<code class="constant">raw</code>) ; </span>]
+ [<span class="optional"> forward (<code class="constant">only</code>|<code class="constant">first</code>) ; </span>]
+ [<span class="optional"> forwarders { [<span class="optional"> <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; ... </span>] }; </span>]
+ [<span class="optional"> masters [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] { ( <em class="replaceable"><code>masters_list</code></em> | <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] [<span class="optional">key <em class="replaceable"><code>key</code></em></span>] ) ; [<span class="optional">...</span>] }; </span>]
+ [<span class="optional"> max-transfer-idle-in <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-transfer-time-in <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> pubkey <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> transfer-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> transfer-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> alt-transfer-source (<em class="replaceable"><code>ip4_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> alt-transfer-source-v6 (<em class="replaceable"><code>ip6_addr</code></em> | <code class="constant">*</code>) [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; </span>]
+ [<span class="optional"> use-alt-transfer-source <em class="replaceable"><code>yes_or_no</code></em>; </span>]
+ [<span class="optional"> zone-statistics <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+ [<span class="optional"> database <em class="replaceable"><code>string</code></em> ; </span>]
+ [<span class="optional"> min-refresh-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-refresh-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> min-retry-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> max-retry-time <em class="replaceable"><code>number</code></em> ; </span>]
+ [<span class="optional"> multi-master <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+};
+
+zone <em class="replaceable"><code>zone_name</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em></span>] {
+ type forward;
+ [<span class="optional"> forward (<code class="constant">only</code>|<code class="constant">first</code>) ; </span>]
+ [<span class="optional"> forwarders { [<span class="optional"> <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] ; ... </span>] }; </span>]
+ [<span class="optional"> delegation-only <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
+};
+
+zone <em class="replaceable"><code>zone_name</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em></span>] {
+ type delegation-only;
+};
+
+</pre>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2587892"></a><span><strong class="command">zone</strong></span> Statement Definition and Usage</h3></div></div></div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2587899"></a>Zone Types</h4></div></div></div>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <code class="varname">master</code>
+ </p>
+ </td>
+<td>
+ <p>
+ The server has a master copy of the data
+ for the zone and will be able to provide authoritative
+ answers for
+ it.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">slave</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A slave zone is a replica of a master
+ zone. The <span><strong class="command">masters</strong></span> list
+ specifies one or more IP addresses
+ of master servers that the slave contacts to update
+ its copy of the zone.
+ Masters list elements can also be names of other
+ masters lists.
+ By default, transfers are made from port 53 on the
+ servers; this can
+ be changed for all servers by specifying a port number
+ before the
+ list of IP addresses, or on a per-server basis after
+ the IP address.
+ Authentication to the master can also be done with
+ per-server TSIG keys.
+ If a file is specified, then the
+ replica will be written to this file whenever the zone
+ is changed,
+ and reloaded from this file on a server restart. Use
+ of a file is
+ recommended, since it often speeds server startup and
+ eliminates
+ a needless waste of bandwidth. Note that for large
+ numbers (in the
+ tens or hundreds of thousands) of zones per server, it
+ is best to
+ use a two-level naming scheme for zone filenames. For
+ example,
+ a slave server for the zone <code class="literal">example.com</code> might place
+ the zone contents into a file called
+ <code class="filename">ex/example.com</code> where <code class="filename">ex/</code> is
+ just the first two letters of the zone name. (Most
+ operating systems
+ behave very slowly if you put 100 000 files into
+ a single directory.)
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">stub</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A stub zone is similar to a slave zone,
+ except that it replicates only the NS records of a
+ master zone instead
+ of the entire zone. Stub zones are not a standard part
+ of the DNS;
+ they are a feature specific to the <acronym class="acronym">BIND</acronym> implementation.
+ </p>
+
+ <p>
+ Stub zones can be used to eliminate the need for glue
+ NS record
+ in a parent zone at the expense of maintaining a stub
+ zone entry and
+ a set of name server addresses in <code class="filename">named.conf</code>.
+ This usage is not recommended for new configurations,
+ and BIND 9
+ supports it only in a limited way.
+ In <acronym class="acronym">BIND</acronym> 4/8, zone
+ transfers of a parent zone
+ included the NS records from stub children of that
+ zone. This meant
+ that, in some cases, users could get away with
+ configuring child stubs
+ only in the master server for the parent zone. <acronym class="acronym">BIND</acronym>
+ 9 never mixes together zone data from different zones
+ in this
+ way. Therefore, if a <acronym class="acronym">BIND</acronym> 9 master serving a parent
+ zone has child stub zones configured, all the slave
+ servers for the
+ parent zone also need to have the same child stub
+ zones
+ configured.
+ </p>
+
+ <p>
+ Stub zones can also be used as a way of forcing the
+ resolution
+ of a given domain to use a particular set of
+ authoritative servers.
+ For example, the caching name servers on a private
+ network using
+ RFC1918 addressing may be configured with stub zones
+ for
+ <code class="literal">10.in-addr.arpa</code>
+ to use a set of internal name servers as the
+ authoritative
+ servers for that domain.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">forward</code>
+ </p>
+ </td>
+<td>
+ <p>
+ A "forward zone" is a way to configure
+ forwarding on a per-domain basis. A <span><strong class="command">zone</strong></span> statement
+ of type <span><strong class="command">forward</strong></span> can
+ contain a <span><strong class="command">forward</strong></span>
+ and/or <span><strong class="command">forwarders</strong></span>
+ statement,
+ which will apply to queries within the domain given by
+ the zone
+ name. If no <span><strong class="command">forwarders</strong></span>
+ statement is present or
+ an empty list for <span><strong class="command">forwarders</strong></span> is given, then no
+ forwarding will be done for the domain, canceling the
+ effects of
+ any forwarders in the <span><strong class="command">options</strong></span> statement. Thus
+ if you want to use this type of zone to change the
+ behavior of the
+ global <span><strong class="command">forward</strong></span> option
+ (that is, "forward first"
+ to, then "forward only", or vice versa, but want to
+ use the same
+ servers as set globally) you need to re-specify the
+ global forwarders.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">hint</code>
+ </p>
+ </td>
+<td>
+ <p>
+ The initial set of root name servers is
+ specified using a "hint zone". When the server starts
+ up, it uses
+ the root hints to find a root name server and get the
+ most recent
+ list of root name servers. If no hint zone is
+ specified for class
+ IN, the server uses a compiled-in default set of root
+ servers hints.
+ Classes other than IN have no built-in defaults hints.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">delegation-only</code>
+ </p>
+ </td>
+<td>
+ <p>
+ This is used to enforce the delegation-only
+ status of infrastructure zones (e.g. COM, NET, ORG).
+ Any answer that
+ is received without an explicit or implicit delegation
+ in the authority
+ section will be treated as NXDOMAIN. This does not
+ apply to the zone
+ apex. This should not be applied to leaf zones.
+ </p>
+ <p>
+ <code class="varname">delegation-only</code> has no
+ effect on answers received
+ from forwarders.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2588250"></a>Class</h4></div></div></div>
+<p>
+ The zone's name may optionally be followed by a class. If
+ a class is not specified, class <code class="literal">IN</code> (for <code class="varname">Internet</code>),
+ is assumed. This is correct for the vast majority of cases.
+ </p>
+<p>
+ The <code class="literal">hesiod</code> class is
+ named for an information service from MIT's Project Athena. It
+ is
+ used to share information about various systems databases, such
+ as users, groups, printers and so on. The keyword
+ <code class="literal">HS</code> is
+ a synonym for hesiod.
+ </p>
+<p>
+ Another MIT development is Chaosnet, a LAN protocol created
+ in the mid-1970s. Zone data for it can be specified with the <code class="literal">CHAOS</code> class.
+ </p>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2588352"></a>Zone Options</h4></div></div></div>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">allow-notify</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">allow-notify</strong></span> in <a href="Bv9ARM.ch06.html#access_control" title="Access Control">the section called &#8220;Access Control&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-query</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">allow-query</strong></span> in <a href="Bv9ARM.ch06.html#access_control" title="Access Control">the section called &#8220;Access Control&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-query-on</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">allow-query-on</strong></span> in <a href="Bv9ARM.ch06.html#access_control" title="Access Control">the section called &#8220;Access Control&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-transfer</strong></span></span></dt>
+<dd><p>
+ See the description of <span><strong class="command">allow-transfer</strong></span>
+ in <a href="Bv9ARM.ch06.html#access_control" title="Access Control">the section called &#8220;Access Control&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-update</strong></span></span></dt>
+<dd><p>
+ See the description of <span><strong class="command">allow-update</strong></span>
+ in <a href="Bv9ARM.ch06.html#access_control" title="Access Control">the section called &#8220;Access Control&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">update-policy</strong></span></span></dt>
+<dd><p>
+ Specifies a "Simple Secure Update" policy. See
+ <a href="Bv9ARM.ch06.html#dynamic_update_policies" title="Dynamic Update Policies">the section called &#8220;Dynamic Update Policies&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">allow-update-forwarding</strong></span></span></dt>
+<dd><p>
+ See the description of <span><strong class="command">allow-update-forwarding</strong></span>
+ in <a href="Bv9ARM.ch06.html#access_control" title="Access Control">the section called &#8220;Access Control&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">also-notify</strong></span></span></dt>
+<dd><p>
+ Only meaningful if <span><strong class="command">notify</strong></span>
+ is
+ active for this zone. The set of machines that will
+ receive a
+ <code class="literal">DNS NOTIFY</code> message
+ for this zone is made up of all the listed name servers
+ (other than
+ the primary master) for the zone plus any IP addresses
+ specified
+ with <span><strong class="command">also-notify</strong></span>. A port
+ may be specified
+ with each <span><strong class="command">also-notify</strong></span>
+ address to send the notify
+ messages to a port other than the default of 53.
+ <span><strong class="command">also-notify</strong></span> is not
+ meaningful for stub zones.
+ The default is the empty list.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-names</strong></span></span></dt>
+<dd><p>
+ This option is used to restrict the character set and
+ syntax of
+ certain domain names in master files and/or DNS responses
+ received from the
+ network. The default varies according to zone type. For <span><strong class="command">master</strong></span> zones the default is <span><strong class="command">fail</strong></span>. For <span><strong class="command">slave</strong></span>
+ zones the default is <span><strong class="command">warn</strong></span>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-mx</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">check-mx</strong></span> in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-wildcard</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">check-wildcard</strong></span> in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-integrity</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">check-integrity</strong></span> in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">check-sibling</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">check-sibling</strong></span> in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">zero-no-soa-ttl</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">zero-no-soa-ttl</strong></span> in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">update-check-ksk</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">update-check-ksk</strong></span> in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">try-tcp-refresh</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">try-tcp-refresh</strong></span> in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">database</strong></span></span></dt>
+<dd>
+<p>
+ Specify the type of database to be used for storing the
+ zone data. The string following the <span><strong class="command">database</strong></span> keyword
+ is interpreted as a list of whitespace-delimited words.
+ The first word
+ identifies the database type, and any subsequent words are
+ passed
+ as arguments to the database to be interpreted in a way
+ specific
+ to the database type.
+ </p>
+<p>
+ The default is <strong class="userinput"><code>"rbt"</code></strong>, BIND 9's
+ native in-memory
+ red-black-tree database. This database does not take
+ arguments.
+ </p>
+<p>
+ Other values are possible if additional database drivers
+ have been linked into the server. Some sample drivers are
+ included
+ with the distribution but none are linked in by default.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command">dialup</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">dialup</strong></span> in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">delegation-only</strong></span></span></dt>
+<dd><p>
+ The flag only applies to hint and stub zones. If set
+ to <strong class="userinput"><code>yes</code></strong>, then the zone will also be
+ treated as if it
+ is also a delegation-only type zone.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">forward</strong></span></span></dt>
+<dd><p>
+ Only meaningful if the zone has a forwarders
+ list. The <span><strong class="command">only</strong></span> value causes
+ the lookup to fail
+ after trying the forwarders and getting no answer, while <span><strong class="command">first</strong></span> would
+ allow a normal lookup to be tried.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">forwarders</strong></span></span></dt>
+<dd><p>
+ Used to override the list of global forwarders.
+ If it is not specified in a zone of type <span><strong class="command">forward</strong></span>,
+ no forwarding is done for the zone and the global options are
+ not used.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">ixfr-base</strong></span></span></dt>
+<dd><p>
+ Was used in <acronym class="acronym">BIND</acronym> 8 to
+ specify the name
+ of the transaction log (journal) file for dynamic update
+ and IXFR.
+ <acronym class="acronym">BIND</acronym> 9 ignores the option
+ and constructs the name of the journal
+ file by appending "<code class="filename">.jnl</code>"
+ to the name of the
+ zone file.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">ixfr-tmp-file</strong></span></span></dt>
+<dd><p>
+ Was an undocumented option in <acronym class="acronym">BIND</acronym> 8.
+ Ignored in <acronym class="acronym">BIND</acronym> 9.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">journal</strong></span></span></dt>
+<dd><p>
+ Allow the default journal's filename to be overridden.
+ The default is the zone's filename with "<code class="filename">.jnl</code>" appended.
+ This is applicable to <span><strong class="command">master</strong></span> and <span><strong class="command">slave</strong></span> zones.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-journal-size</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">max-journal-size</strong></span> in <a href="Bv9ARM.ch06.html#server_resource_limits" title="Server Resource Limits">the section called &#8220;Server Resource Limits&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-transfer-time-in</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">max-transfer-time-in</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-transfer-idle-in</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">max-transfer-idle-in</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-transfer-time-out</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">max-transfer-time-out</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">max-transfer-idle-out</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">max-transfer-idle-out</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">notify</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">notify</strong></span> in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">notify-delay</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">notify-delay</strong></span> in <a href="Bv9ARM.ch06.html#tuning" title="Tuning">the section called &#8220;Tuning&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">notify-to-soa</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">notify-to-soa</strong></span> in
+ <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">pubkey</strong></span></span></dt>
+<dd><p>
+ In <acronym class="acronym">BIND</acronym> 8, this option was
+ intended for specifying
+ a public zone key for verification of signatures in DNSSEC
+ signed
+ zones when they are loaded from disk. <acronym class="acronym">BIND</acronym> 9 does not verify signatures
+ on load and ignores the option.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">zone-statistics</strong></span></span></dt>
+<dd><p>
+ If <strong class="userinput"><code>yes</code></strong>, the server will keep
+ statistical
+ information for this zone, which can be dumped to the
+ <span><strong class="command">statistics-file</strong></span> defined in
+ the server options.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">sig-validity-interval</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">sig-validity-interval</strong></span> in <a href="Bv9ARM.ch06.html#tuning" title="Tuning">the section called &#8220;Tuning&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">sig-signing-nodes</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">sig-signing-nodes</strong></span> in <a href="Bv9ARM.ch06.html#tuning" title="Tuning">the section called &#8220;Tuning&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">sig-signing-signatures</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">sig-signing-signatures</strong></span> in <a href="Bv9ARM.ch06.html#tuning" title="Tuning">the section called &#8220;Tuning&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">sig-signing-type</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">sig-signing-type</strong></span> in <a href="Bv9ARM.ch06.html#tuning" title="Tuning">the section called &#8220;Tuning&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">transfer-source</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">transfer-source</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">transfer-source-v6</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">transfer-source-v6</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">alt-transfer-source</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">alt-transfer-source</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">alt-transfer-source-v6</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">alt-transfer-source-v6</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">use-alt-transfer-source</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">use-alt-transfer-source</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">notify-source</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">notify-source</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">notify-source-v6</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">notify-source-v6</strong></span> in <a href="Bv9ARM.ch06.html#zone_transfers" title="Zone Transfers">the section called &#8220;Zone Transfers&#8221;</a>.
+ </p></dd>
+<dt>
+<span class="term"><span><strong class="command">min-refresh-time</strong></span>, </span><span class="term"><span><strong class="command">max-refresh-time</strong></span>, </span><span class="term"><span><strong class="command">min-retry-time</strong></span>, </span><span class="term"><span><strong class="command">max-retry-time</strong></span></span>
+</dt>
+<dd><p>
+ See the description in <a href="Bv9ARM.ch06.html#tuning" title="Tuning">the section called &#8220;Tuning&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">ixfr-from-differences</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">ixfr-from-differences</strong></span> in <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ (Note that the <span><strong class="command">ixfr-from-differences</strong></span>
+ <strong class="userinput"><code>master</code></strong> and
+ <strong class="userinput"><code>slave</code></strong> choices are not
+ available at the zone level.)
+ </p></dd>
+<dt><span class="term"><span><strong class="command">key-directory</strong></span></span></dt>
+<dd><p>
+ See the description of
+ <span><strong class="command">key-directory</strong></span> in <a href="Bv9ARM.ch06.html#options" title="options Statement Definition and
+ Usage">the section called &#8220;<span><strong class="command">options</strong></span> Statement Definition and
+ Usage&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">multi-master</strong></span></span></dt>
+<dd><p>
+ See the description of <span><strong class="command">multi-master</strong></span> in
+ <a href="Bv9ARM.ch06.html#boolean_options" title="Boolean Options">the section called &#8220;Boolean Options&#8221;</a>.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">masterfile-format</strong></span></span></dt>
+<dd><p>
+ See the description of <span><strong class="command">masterfile-format</strong></span>
+ in <a href="Bv9ARM.ch06.html#tuning" title="Tuning">the section called &#8220;Tuning&#8221;</a>.
+ </p></dd>
+</dl></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="dynamic_update_policies"></a>Dynamic Update Policies</h4></div></div></div>
+<p><acronym class="acronym">BIND</acronym> 9 supports two alternative
+ methods of granting clients the right to perform
+ dynamic updates to a zone, configured by the
+ <span><strong class="command">allow-update</strong></span> and
+ <span><strong class="command">update-policy</strong></span> option, respectively.
+ </p>
+<p>
+ The <span><strong class="command">allow-update</strong></span> clause works the
+ same way as in previous versions of <acronym class="acronym">BIND</acronym>.
+ It grants given clients the permission to update any
+ record of any name in the zone.
+ </p>
+<p>
+ The <span><strong class="command">update-policy</strong></span> clause is new
+ in <acronym class="acronym">BIND</acronym> 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.
+ </p>
+<p>
+ Rules are specified in the <span><strong class="command">update-policy</strong></span>
+ zone option, and are only meaningful for master zones.
+ When the <span><strong class="command">update-policy</strong></span> statement
+ is present, it is a configuration error for the
+ <span><strong class="command">allow-update</strong></span> statement to be
+ present. The <span><strong class="command">update-policy</strong></span> statement
+ only examines the signer of a message; the source
+ address is not relevant.
+ </p>
+<p>
+ This is how a rule definition looks:
+ </p>
+<pre class="programlisting">
+( <span><strong class="command">grant</strong></span> | <span><strong class="command">deny</strong></span> ) <em class="replaceable"><code>identity</code></em> <em class="replaceable"><code>nametype</code></em> <em class="replaceable"><code>name</code></em> [<span class="optional"> <em class="replaceable"><code>types</code></em> </span>]
+</pre>
+<p>
+ 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.
+ </p>
+<p>
+ No signer is required for <em class="replaceable"><code>tcp-self</code></em>
+ or <em class="replaceable"><code>6to4-self</code></em> however the standard
+ reverse mapping / prefix conversion must match the identity
+ field.
+ </p>
+<p>
+ The identity field specifies a name or a wildcard
+ name. Normally, this is the name of the TSIG or
+ SIG(0) key used to sign the update request. When a
+ TKEY exchange has been used to create a shared secret,
+ the identity of the shared secret is the same as the
+ identity of the key used to authenticate the TKEY
+ exchange. TKEY is also the negotiation method used
+ by GSS-TSIG, which establishes an identity that is
+ the Kerberos principal of the client, such as
+ <strong class="userinput"><code>"user@host.domain"</code></strong>. When the
+ <em class="replaceable"><code>identity</code></em> field specifies
+ a wildcard name, it is subject to DNS wildcard
+ expansion, so the rule will apply to multiple identities.
+ The <em class="replaceable"><code>identity</code></em> field must
+ contain a fully-qualified domain name.
+ </p>
+<p>
+ The <em class="replaceable"><code>nametype</code></em> field has 12
+ values:
+ <code class="varname">name</code>, <code class="varname">subdomain</code>,
+ <code class="varname">wildcard</code>, <code class="varname">self</code>,
+ <code class="varname">selfsub</code>, <code class="varname">selfwild</code>,
+ <code class="varname">krb5-self</code>, <code class="varname">ms-self</code>,
+ <code class="varname">krb5-subdomain</code>,
+ <code class="varname">ms-subdomain</code>,
+ <code class="varname">tcp-self</code> and <code class="varname">6to4-self</code>.
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <code class="varname">name</code>
+ </p>
+ </td>
+<td>
+ <p>
+ Exact-match semantics. This rule matches
+ when the name being updated is identical
+ to the contents of the
+ <em class="replaceable"><code>name</code></em> field.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">subdomain</code>
+ </p>
+ </td>
+<td>
+ <p>
+ This rule matches when the name being updated
+ is a subdomain of, or identical to, the
+ contents of the <em class="replaceable"><code>name</code></em>
+ field.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">wildcard</code>
+ </p>
+ </td>
+<td>
+ <p>
+ The <em class="replaceable"><code>name</code></em> field
+ is subject to DNS wildcard expansion, and
+ this rule matches when the name being updated
+ name is a valid expansion of the wildcard.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">self</code>
+ </p>
+ </td>
+<td>
+ <p>
+ This rule matches when the name being updated
+ matches the contents of the
+ <em class="replaceable"><code>identity</code></em> field.
+ The <em class="replaceable"><code>name</code></em> field
+ is ignored, but should be the same as the
+ <em class="replaceable"><code>identity</code></em> field.
+ The <code class="varname">self</code> nametype is
+ most useful when allowing using one key per
+ name to update, where the key has the same
+ name as the name to be updated. The
+ <em class="replaceable"><code>identity</code></em> would
+ be specified as <code class="constant">*</code> (an asterisk) in
+ this case.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">selfsub</code>
+ </p>
+ </td>
+<td>
+ <p>
+ This rule is similar to <code class="varname">self</code>
+ except that subdomains of <code class="varname">self</code>
+ can also be updated.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">selfwild</code>
+ </p>
+ </td>
+<td>
+ <p>
+ This rule is similar to <code class="varname">self</code>
+ except that only subdomains of
+ <code class="varname">self</code> can be updated.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">tcp-self</code>
+ </p>
+ </td>
+<td>
+ <p>
+ Allow updates that have been sent via TCP and
+ for which the standard mapping from the initiating
+ IP address into the IN-ADDR.ARPA and IP6.ARPA
+ namespaces match the name to be updated.
+ </p>
+ <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+ It is theoretically possible to spoof these TCP
+ sessions.
+ </div>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="varname">6to4-self</code>
+ </p>
+ </td>
+<td>
+ <p>
+ Allow the 6to4 prefix to be update by any TCP
+ conection 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.
+ </p>
+ <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+ It is theoretically possible to spoof these TCP
+ sessions.
+ </div>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ In all cases, the <em class="replaceable"><code>name</code></em>
+ field must
+ specify a fully-qualified domain name.
+ </p>
+<p>
+ If no types are explicitly specified, this rule matches
+ all types except RRSIG, NS, SOA, NSEC and NSEC3. Types
+ may be specified by name, including "ANY" (ANY matches
+ all types except NSEC and NSEC3, which can never be
+ updated). Note that when an attempt is made to delete
+ all records associated with a name, the rules are
+ checked for each existing record type.
+ </p>
+</div>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2590422"></a>Zone File</h2></div></div></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="types_of_resource_records_and_when_to_use_them"></a>Types of Resource Records and When to Use Them</h3></div></div></div>
+<p>
+ This section, largely borrowed from RFC 1034, describes the
+ concept of a Resource Record (RR) and explains when each is used.
+ Since the publication of RFC 1034, several new RRs have been
+ identified
+ and implemented in the DNS. These are also included.
+ </p>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2590440"></a>Resource Records</h4></div></div></div>
+<p>
+ A domain name identifies a node. Each node has a set of
+ resource information, which may be empty. The set of resource
+ information associated with a particular name is composed of
+ separate RRs. The order of RRs in a set is not significant and
+ need not be preserved by name servers, resolvers, or other
+ parts of the DNS. However, sorting of multiple RRs is
+ permitted for optimization purposes, for example, to specify
+ that a particular nearby server be tried first. See <a href="Bv9ARM.ch06.html#the_sortlist_statement" title="The sortlist Statement">the section called &#8220;The <span><strong class="command">sortlist</strong></span> Statement&#8221;</a> and <a href="Bv9ARM.ch06.html#rrset_ordering" title="RRset Ordering">the section called &#8220;RRset Ordering&#8221;</a>.
+ </p>
+<p>
+ The components of a Resource Record are:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ owner name
+ </p>
+ </td>
+<td>
+ <p>
+ The domain name where the RR is found.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ type
+ </p>
+ </td>
+<td>
+ <p>
+ An encoded 16-bit value that specifies
+ the type of the resource record.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ TTL
+ </p>
+ </td>
+<td>
+ <p>
+ The time-to-live of the RR. This field
+ is a 32-bit integer in units of seconds, and is
+ primarily used by
+ resolvers when they cache RRs. The TTL describes how
+ long a RR can
+ be cached before it should be discarded.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ class
+ </p>
+ </td>
+<td>
+ <p>
+ An encoded 16-bit value that identifies
+ a protocol family or instance of a protocol.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ RDATA
+ </p>
+ </td>
+<td>
+ <p>
+ The resource data. The format of the
+ data is type (and sometimes class) specific.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ The following are <span class="emphasis"><em>types</em></span> of valid RRs:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ A
+ </p>
+ </td>
+<td>
+ <p>
+ A host address. In the IN class, this is a
+ 32-bit IP address. Described in RFC 1035.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ AAAA
+ </p>
+ </td>
+<td>
+ <p>
+ IPv6 address. Described in RFC 1886.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ A6
+ </p>
+ </td>
+<td>
+ <p>
+ IPv6 address. This can be a partial
+ address (a suffix) and an indirection to the name
+ where the rest of the
+ address (the prefix) can be found. Experimental.
+ Described in RFC 2874.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ AFSDB
+ </p>
+ </td>
+<td>
+ <p>
+ Location of AFS database servers.
+ Experimental. Described in RFC 1183.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ APL
+ </p>
+ </td>
+<td>
+ <p>
+ Address prefix list. Experimental.
+ Described in RFC 3123.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ CERT
+ </p>
+ </td>
+<td>
+ <p>
+ Holds a digital certificate.
+ Described in RFC 2538.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ CNAME
+ </p>
+ </td>
+<td>
+ <p>
+ Identifies the canonical name of an alias.
+ Described in RFC 1035.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ DHCID
+ </p>
+ </td>
+<td>
+ <p>
+ Is used for identifying which DHCP client is
+ associated with this name. Described in RFC 4701.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ DNAME
+ </p>
+ </td>
+<td>
+ <p>
+ Replaces the domain name specified with
+ another name to be looked up, effectively aliasing an
+ entire
+ subtree of the domain name space rather than a single
+ record
+ as in the case of the CNAME RR.
+ Described in RFC 2672.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ DNSKEY
+ </p>
+ </td>
+<td>
+ <p>
+ Stores a public key associated with a signed
+ DNS zone. Described in RFC 4034.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ DS
+ </p>
+ </td>
+<td>
+ <p>
+ Stores the hash of a public key associated with a
+ signed DNS zone. Described in RFC 4034.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ GPOS
+ </p>
+ </td>
+<td>
+ <p>
+ Specifies the global position. Superseded by LOC.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ HINFO
+ </p>
+ </td>
+<td>
+ <p>
+ Identifies the CPU and OS used by a host.
+ Described in RFC 1035.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ IPSECKEY
+ </p>
+ </td>
+<td>
+ <p>
+ Provides a method for storing IPsec keying material in
+ DNS. Described in RFC 4025.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ ISDN
+ </p>
+ </td>
+<td>
+ <p>
+ Representation of ISDN addresses.
+ Experimental. Described in RFC 1183.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ KEY
+ </p>
+ </td>
+<td>
+ <p>
+ Stores a public key associated with a
+ DNS name. Used in original DNSSEC; replaced
+ by DNSKEY in DNSSECbis, but still used with
+ SIG(0). Described in RFCs 2535 and 2931.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ KX
+ </p>
+ </td>
+<td>
+ <p>
+ Identifies a key exchanger for this
+ DNS name. Described in RFC 2230.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ LOC
+ </p>
+ </td>
+<td>
+ <p>
+ For storing GPS info. Described in RFC 1876.
+ Experimental.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ MX
+ </p>
+ </td>
+<td>
+ <p>
+ Identifies a mail exchange for the domain with
+ a 16-bit preference value (lower is better)
+ followed by the host name of the mail exchange.
+ Described in RFC 974, RFC 1035.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ NAPTR
+ </p>
+ </td>
+<td>
+ <p>
+ Name authority pointer. Described in RFC 2915.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ NSAP
+ </p>
+ </td>
+<td>
+ <p>
+ A network service access point.
+ Described in RFC 1706.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ NS
+ </p>
+ </td>
+<td>
+ <p>
+ The authoritative name server for the
+ domain. Described in RFC 1035.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ NSEC
+ </p>
+ </td>
+<td>
+ <p>
+ Used in DNSSECbis to securely indicate that
+ RRs with an owner name in a certain name interval do
+ not exist in
+ a zone and indicate what RR types are present for an
+ existing name.
+ Described in RFC 4034.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ NSEC3
+ </p>
+ </td>
+<td>
+ <p>
+ Used in DNSSECbis to securely indicate that
+ RRs with an owner name in a certain name
+ interval do not exist in a zone and indicate
+ what RR types are present for an existing
+ name. NSEC3 differs from NSEC in that it
+ prevents zone enumeration but is more
+ computationally expensive on both the server
+ and the client than NSEC. Described in RFC
+ 5155.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ NSEC3PARAM
+ </p>
+ </td>
+<td>
+ <p>
+ Used in DNSSECbis to tell the authoritative
+ server which NSEC3 chains are available to use.
+ Described in RFC 5155.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ NXT
+ </p>
+ </td>
+<td>
+ <p>
+ Used in DNSSEC to securely indicate that
+ RRs with an owner name in a certain name interval do
+ not exist in
+ a zone and indicate what RR types are present for an
+ existing name.
+ Used in original DNSSEC; replaced by NSEC in
+ DNSSECbis.
+ Described in RFC 2535.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ PTR
+ </p>
+ </td>
+<td>
+ <p>
+ A pointer to another part of the domain
+ name space. Described in RFC 1035.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ PX
+ </p>
+ </td>
+<td>
+ <p>
+ Provides mappings between RFC 822 and X.400
+ addresses. Described in RFC 2163.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ RP
+ </p>
+ </td>
+<td>
+ <p>
+ Information on persons responsible
+ for the domain. Experimental. Described in RFC 1183.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ RRSIG
+ </p>
+ </td>
+<td>
+ <p>
+ Contains DNSSECbis signature data. Described
+ in RFC 4034.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ RT
+ </p>
+ </td>
+<td>
+ <p>
+ Route-through binding for hosts that
+ do not have their own direct wide area network
+ addresses.
+ Experimental. Described in RFC 1183.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ SIG
+ </p>
+ </td>
+<td>
+ <p>
+ Contains DNSSEC signature data. Used in
+ original DNSSEC; replaced by RRSIG in
+ DNSSECbis, but still used for SIG(0).
+ Described in RFCs 2535 and 2931.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ SOA
+ </p>
+ </td>
+<td>
+ <p>
+ Identifies the start of a zone of authority.
+ Described in RFC 1035.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ SPF
+ </p>
+ </td>
+<td>
+ <p>
+ Contains the Sender Policy Framework information
+ for a given email domain. Described in RFC 4408.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ SRV
+ </p>
+ </td>
+<td>
+ <p>
+ Information about well known network
+ services (replaces WKS). Described in RFC 2782.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ SSHFP
+ </p>
+ </td>
+<td>
+ <p>
+ Provides a way to securely publish a secure shell key's
+ fingerprint. Described in RFC 4255.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ TXT
+ </p>
+ </td>
+<td>
+ <p>
+ Text records. Described in RFC 1035.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ WKS
+ </p>
+ </td>
+<td>
+ <p>
+ Information about which well known
+ network services, such as SMTP, that a domain
+ supports. Historical.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ X25
+ </p>
+ </td>
+<td>
+ <p>
+ Representation of X.25 network addresses.
+ Experimental. Described in RFC 1183.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ The following <span class="emphasis"><em>classes</em></span> of resource records
+ are currently valid in the DNS:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ IN
+ </p>
+ </td>
+<td>
+ <p>
+ The Internet.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ CH
+ </p>
+ </td>
+<td>
+ <p>
+ Chaosnet, a LAN protocol created at MIT in the
+ mid-1970s.
+ Rarely used for its historical purpose, but reused for
+ BIND's
+ built-in server information zones, e.g.,
+ <code class="literal">version.bind</code>.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ HS
+ </p>
+ </td>
+<td>
+ <p>
+ Hesiod, an information service
+ developed by MIT's Project Athena. It is used to share
+ information
+ about various systems databases, such as users,
+ groups, printers
+ and so on.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ The owner name is often implicit, rather than forming an
+ integral
+ part of the RR. For example, many name servers internally form
+ tree
+ or hash structures for the name space, and chain RRs off nodes.
+ The remaining RR parts are the fixed header (type, class, TTL)
+ which is consistent for all RRs, and a variable part (RDATA)
+ that
+ fits the needs of the resource being described.
+ </p>
+<p>
+ The meaning of the TTL field is a time limit on how long an
+ RR can be kept in a cache. This limit does not apply to
+ authoritative
+ data in zones; it is also timed out, but by the refreshing
+ policies
+ for the zone. The TTL is assigned by the administrator for the
+ zone where the data originates. While short TTLs can be used to
+ minimize caching, and a zero TTL prohibits caching, the
+ realities
+ of Internet performance suggest that these times should be on
+ the
+ order of days for the typical host. If a change can be
+ anticipated,
+ the TTL can be reduced prior to the change to minimize
+ inconsistency
+ during the change, and then increased back to its former value
+ following
+ the change.
+ </p>
+<p>
+ The data in the RDATA section of RRs is carried as a combination
+ of binary strings and domain names. The domain names are
+ frequently
+ used as "pointers" to other data in the DNS.
+ </p>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2591995"></a>Textual expression of RRs</h4></div></div></div>
+<p>
+ RRs are represented in binary form in the packets of the DNS
+ protocol, and are usually represented in highly encoded form
+ when
+ stored in a name server or resolver. In the examples provided
+ in
+ RFC 1034, a style similar to that used in master files was
+ employed
+ in order to show the contents of RRs. In this format, most RRs
+ are shown on a single line, although continuation lines are
+ possible
+ using parentheses.
+ </p>
+<p>
+ The start of the line gives the owner of the RR. If a line
+ begins with a blank, then the owner is assumed to be the same as
+ that of the previous RR. Blank lines are often included for
+ readability.
+ </p>
+<p>
+ Following the owner, we list the TTL, type, and class of the
+ RR. Class and type use the mnemonics defined above, and TTL is
+ an integer before the type field. In order to avoid ambiguity
+ in
+ parsing, type and class mnemonics are disjoint, TTLs are
+ integers,
+ and the type mnemonic is always last. The IN class and TTL
+ values
+ are often omitted from examples in the interests of clarity.
+ </p>
+<p>
+ The resource data or RDATA section of the RR are given using
+ knowledge of the typical representation for the data.
+ </p>
+<p>
+ For example, we might show the RRs carried in a message as:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <code class="literal">ISI.EDU.</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">MX</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10 VENERA.ISI.EDU.</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p></p>
+ </td>
+<td>
+ <p>
+ <code class="literal">MX</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10 VAXA.ISI.EDU</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="literal">VENERA.ISI.EDU</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">128.9.0.32</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p></p>
+ </td>
+<td>
+ <p>
+ <code class="literal">A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10.1.0.52</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="literal">VAXA.ISI.EDU</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10.2.0.27</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p></p>
+ </td>
+<td>
+ <p>
+ <code class="literal">A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">128.9.0.33</code>
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ The MX RRs have an RDATA section which consists of a 16-bit
+ number followed by a domain name. The address RRs use a
+ standard
+ IP address format to contain a 32-bit internet address.
+ </p>
+<p>
+ The above example shows six RRs, with two RRs at each of three
+ domain names.
+ </p>
+<p>
+ Similarly we might see:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <code class="literal">XX.LCS.MIT.EDU.</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">IN A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10.0.0.44</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td> </td>
+<td>
+ <p>
+ <code class="literal">CH A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">MIT.EDU. 2420</code>
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ This example shows two addresses for
+ <code class="literal">XX.LCS.MIT.EDU</code>, each of a different class.
+ </p>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2592652"></a>Discussion of MX Records</h3></div></div></div>
+<p>
+ As described above, domain servers store information as a
+ series of resource records, each of which contains a particular
+ piece of information about a given domain name (which is usually,
+ but not always, a host). The simplest way to think of a RR is as
+ a typed pair of data, a domain name matched with a relevant datum,
+ and stored with some additional type information to help systems
+ determine when the RR is relevant.
+ </p>
+<p>
+ MX records are used to control delivery of email. The data
+ specified in the record is a priority and a domain name. The
+ priority
+ controls the order in which email delivery is attempted, with the
+ lowest number first. If two priorities are the same, a server is
+ chosen randomly. If no servers at a given priority are responding,
+ the mail transport agent will fall back to the next largest
+ priority.
+ Priority numbers do not have any absolute meaning &#8212; they are
+ relevant
+ only respective to other MX records for that domain name. The
+ domain
+ name given is the machine to which the mail will be delivered.
+ It <span class="emphasis"><em>must</em></span> have an associated address record
+ (A or AAAA) &#8212; CNAME is not sufficient.
+ </p>
+<p>
+ For a given domain, if there is both a CNAME record and an
+ MX record, the MX record is in error, and will be ignored.
+ Instead,
+ the mail will be delivered to the server specified in the MX
+ record
+ pointed to by the CNAME.
+ </p>
+<p>
+ For example:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <code class="literal">example.com.</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">IN</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">MX</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">mail.example.com.</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p></p>
+ </td>
+<td>
+ <p>
+ <code class="literal">IN</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">MX</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">mail2.example.com.</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p></p>
+ </td>
+<td>
+ <p>
+ <code class="literal">IN</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">MX</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">20</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">mail.backup.org.</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="literal">mail.example.com.</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">IN</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10.0.0.1</code>
+ </p>
+ </td>
+<td>
+ <p></p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="literal">mail2.example.com.</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">IN</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">A</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">10.0.0.2</code>
+ </p>
+ </td>
+<td>
+ <p></p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ Mail delivery will be attempted to <code class="literal">mail.example.com</code> and
+ <code class="literal">mail2.example.com</code> (in
+ any order), and if neither of those succeed, delivery to <code class="literal">mail.backup.org</code> will
+ be attempted.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="Setting_TTLs"></a>Setting TTLs</h3></div></div></div>
+<p>
+ The time-to-live of the RR field is a 32-bit integer represented
+ in units of seconds, and is primarily used by resolvers when they
+ cache RRs. The TTL describes how long a RR can be cached before it
+ should be discarded. The following three types of TTL are
+ currently
+ used in a zone file.
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ SOA
+ </p>
+ </td>
+<td>
+ <p>
+ The last field in the SOA is the negative
+ caching TTL. This controls how long other servers will
+ cache no-such-domain
+ (NXDOMAIN) responses from you.
+ </p>
+ <p>
+ The maximum time for
+ negative caching is 3 hours (3h).
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ $TTL
+ </p>
+ </td>
+<td>
+ <p>
+ The $TTL directive at the top of the
+ zone file (before the SOA) gives a default TTL for every
+ RR without
+ a specific TTL set.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ RR TTLs
+ </p>
+ </td>
+<td>
+ <p>
+ Each RR can have a TTL as the second
+ field in the RR, which will control how long other
+ servers can cache
+ the it.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ All of these TTLs default to units of seconds, though units
+ can be explicitly specified, for example, <code class="literal">1h30m</code>.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2593204"></a>Inverse Mapping in IPv4</h3></div></div></div>
+<p>
+ Reverse name resolution (that is, translation from IP address
+ to name) is achieved by means of the <span class="emphasis"><em>in-addr.arpa</em></span> domain
+ and PTR records. Entries in the in-addr.arpa domain are made in
+ least-to-most significant order, read left to right. This is the
+ opposite order to the way IP addresses are usually written. Thus,
+ a machine with an IP address of 10.1.2.3 would have a
+ corresponding
+ in-addr.arpa name of
+ 3.2.1.10.in-addr.arpa. This name should have a PTR resource record
+ whose data field is the name of the machine or, optionally,
+ multiple
+ PTR records if the machine has more than one name. For example,
+ in the [<span class="optional">example.com</span>] domain:
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <code class="literal">$ORIGIN</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">2.1.10.in-addr.arpa</code>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>
+ <code class="literal">3</code>
+ </p>
+ </td>
+<td>
+ <p>
+ <code class="literal">IN PTR foo.example.com.</code>
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ The <span><strong class="command">$ORIGIN</strong></span> lines in the examples
+ are for providing context to the examples only &#8212; they do not
+ necessarily
+ appear in the actual usage. They are only used here to indicate
+ that the example is relative to the listed origin.
+ </p>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2593399"></a>Other Zone File Directives</h3></div></div></div>
+<p>
+ The Master File Format was initially defined in RFC 1035 and
+ has subsequently been extended. While the Master File Format
+ itself
+ is class independent all records in a Master File must be of the
+ same
+ class.
+ </p>
+<p>
+ Master File Directives include <span><strong class="command">$ORIGIN</strong></span>, <span><strong class="command">$INCLUDE</strong></span>,
+ and <span><strong class="command">$TTL.</strong></span>
+ </p>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2593421"></a>The <span><strong class="command">$ORIGIN</strong></span> Directive</h4></div></div></div>
+<p>
+ Syntax: <span><strong class="command">$ORIGIN</strong></span>
+ <em class="replaceable"><code>domain-name</code></em>
+ [<span class="optional"><em class="replaceable"><code>comment</code></em></span>]
+ </p>
+<p><span><strong class="command">$ORIGIN</strong></span>
+ sets the domain name that will be appended to any
+ unqualified records. When a zone is first read in there
+ is an implicit <span><strong class="command">$ORIGIN</strong></span>
+ &lt;<code class="varname">zone-name</code>&gt;<span><strong class="command">.</strong></span>
+ The current <span><strong class="command">$ORIGIN</strong></span> is appended to
+ the domain specified in the <span><strong class="command">$ORIGIN</strong></span>
+ argument if it is not absolute.
+ </p>
+<pre class="programlisting">
+$ORIGIN example.com.
+WWW CNAME MAIN-SERVER
+</pre>
+<p>
+ is equivalent to
+ </p>
+<pre class="programlisting">
+WWW.EXAMPLE.COM. CNAME MAIN-SERVER.EXAMPLE.COM.
+</pre>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2593482"></a>The <span><strong class="command">$INCLUDE</strong></span> Directive</h4></div></div></div>
+<p>
+ Syntax: <span><strong class="command">$INCLUDE</strong></span>
+ <em class="replaceable"><code>filename</code></em>
+ [<span class="optional">
+<em class="replaceable"><code>origin</code></em> </span>]
+ [<span class="optional"> <em class="replaceable"><code>comment</code></em> </span>]
+ </p>
+<p>
+ Read and process the file <code class="filename">filename</code> as
+ if it were included into the file at this point. If <span><strong class="command">origin</strong></span> is
+ specified the file is processed with <span><strong class="command">$ORIGIN</strong></span> set
+ to that value, otherwise the current <span><strong class="command">$ORIGIN</strong></span> is
+ used.
+ </p>
+<p>
+ The origin and the current domain name
+ revert to the values they had prior to the <span><strong class="command">$INCLUDE</strong></span> once
+ the file has been read.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ RFC 1035 specifies that the current origin should be restored
+ after
+ an <span><strong class="command">$INCLUDE</strong></span>, but it is silent
+ on whether the current
+ domain name should also be restored. BIND 9 restores both of
+ them.
+ This could be construed as a deviation from RFC 1035, a
+ feature, or both.
+ </p>
+</div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2593552"></a>The <span><strong class="command">$TTL</strong></span> Directive</h4></div></div></div>
+<p>
+ Syntax: <span><strong class="command">$TTL</strong></span>
+ <em class="replaceable"><code>default-ttl</code></em>
+ [<span class="optional">
+<em class="replaceable"><code>comment</code></em> </span>]
+ </p>
+<p>
+ Set the default Time To Live (TTL) for subsequent records
+ with undefined TTLs. Valid TTLs are of the range 0-2147483647
+ seconds.
+ </p>
+<p><span><strong class="command">$TTL</strong></span>
+ is defined in RFC 2308.
+ </p>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2593656"></a><acronym class="acronym">BIND</acronym> Master File Extension: the <span><strong class="command">$GENERATE</strong></span> Directive</h3></div></div></div>
+<p>
+ Syntax: <span><strong class="command">$GENERATE</strong></span>
+ <em class="replaceable"><code>range</code></em>
+ <em class="replaceable"><code>lhs</code></em>
+ [<span class="optional"><em class="replaceable"><code>ttl</code></em></span>]
+ [<span class="optional"><em class="replaceable"><code>class</code></em></span>]
+ <em class="replaceable"><code>type</code></em>
+ <em class="replaceable"><code>rhs</code></em>
+ [<span class="optional"><em class="replaceable"><code>comment</code></em></span>]
+ </p>
+<p><span><strong class="command">$GENERATE</strong></span>
+ is used to create a series of resource records that only
+ differ from each other by an
+ iterator. <span><strong class="command">$GENERATE</strong></span> can be used to
+ easily generate the sets of records required to support
+ sub /24 reverse delegations described in RFC 2317:
+ Classless IN-ADDR.ARPA delegation.
+ </p>
+<pre class="programlisting">$ORIGIN 0.0.192.IN-ADDR.ARPA.
+$GENERATE 1-2 0 NS SERVER$.EXAMPLE.
+$GENERATE 1-127 $ CNAME $.0</pre>
+<p>
+ is equivalent to
+ </p>
+<pre class="programlisting">0.0.0.192.IN-ADDR.ARPA. NS SERVER1.EXAMPLE.
+0.0.0.192.IN-ADDR.ARPA. NS SERVER2.EXAMPLE.
+1.0.0.192.IN-ADDR.ARPA. CNAME 1.0.0.0.192.IN-ADDR.ARPA.
+2.0.0.192.IN-ADDR.ARPA. CNAME 2.0.0.0.192.IN-ADDR.ARPA.
+...
+127.0.0.192.IN-ADDR.ARPA. CNAME 127.0.0.0.192.IN-ADDR.ARPA.
+</pre>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p><span><strong class="command">range</strong></span></p>
+ </td>
+<td>
+ <p>
+ This can be one of two forms: start-stop
+ or start-stop/step. If the first form is used, then step
+ is set to
+ 1. All of start, stop and step must be positive.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">lhs</strong></span></p>
+ </td>
+<td>
+ <p>This
+ describes the owner name of the resource records
+ to be created. Any single <span><strong class="command">$</strong></span>
+ (dollar sign)
+ symbols within the <span><strong class="command">lhs</strong></span> side
+ are replaced by the iterator value.
+
+ To get a $ in the output, you need to escape the
+ <span><strong class="command">$</strong></span> using a backslash
+ <span><strong class="command">\</strong></span>,
+ e.g. <span><strong class="command">\$</strong></span>. The
+ <span><strong class="command">$</strong></span> may optionally be followed
+ by modifiers which change the offset from the
+ iterator, field width and base.
+
+ Modifiers are introduced by a
+ <span><strong class="command">{</strong></span> (left brace) immediately following the
+ <span><strong class="command">$</strong></span> as
+ <span><strong class="command">${offset[,width[,base]]}</strong></span>.
+ For example, <span><strong class="command">${-20,3,d}</strong></span>
+ subtracts 20 from the current value, prints the
+ result as a decimal in a zero-padded field of
+ width 3.
+
+ Available output forms are decimal
+ (<span><strong class="command">d</strong></span>), octal
+ (<span><strong class="command">o</strong></span>) and hexadecimal
+ (<span><strong class="command">x</strong></span> or <span><strong class="command">X</strong></span>
+ for uppercase). The default modifier is
+ <span><strong class="command">${0,0,d}</strong></span>. If the
+ <span><strong class="command">lhs</strong></span> is not absolute, the
+ current <span><strong class="command">$ORIGIN</strong></span> is appended
+ to the name.
+ </p>
+ <p>
+ For compatibility with earlier versions, <span><strong class="command">$$</strong></span> is still
+ recognized as indicating a literal $ in the output.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ttl</strong></span></p>
+ </td>
+<td>
+ <p>
+ Specifies the time-to-live of the generated records. If
+ not specified this will be inherited using the
+ normal ttl inheritance rules.
+ </p>
+ <p><span><strong class="command">class</strong></span>
+ and <span><strong class="command">ttl</strong></span> can be
+ entered in either order.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">class</strong></span></p>
+ </td>
+<td>
+ <p>
+ Specifies the class of the generated records.
+ This must match the zone class if it is
+ specified.
+ </p>
+ <p><span><strong class="command">class</strong></span>
+ and <span><strong class="command">ttl</strong></span> can be
+ entered in either order.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">type</strong></span></p>
+ </td>
+<td>
+ <p>
+ At present the only supported types are
+ PTR, CNAME, DNAME, A, AAAA and NS.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">rhs</strong></span></p>
+ </td>
+<td>
+ <p>
+ <span><strong class="command">rhs</strong></span> is a domain name. It is processed
+ similarly to lhs.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ The <span><strong class="command">$GENERATE</strong></span> directive is a <acronym class="acronym">BIND</acronym> extension
+ and not part of the standard zone file format.
+ </p>
+<p>
+ BIND 8 does not support the optional TTL and CLASS fields.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="zonefile_format"></a>Additional File Formats</h3></div></div></div>
+<p>
+ In addition to the standard textual format, BIND 9
+ supports the ability to read or dump to zone files in
+ other formats. The <code class="constant">raw</code> format is
+ currently available as an additional format. It is a
+ binary format representing BIND 9's internal data
+ structure directly, thereby remarkably improving the
+ loading time.
+ </p>
+<p>
+ For a primary server, a zone file in the
+ <code class="constant">raw</code> format is expected to be
+ generated from a textual zone file by the
+ <span><strong class="command">named-compilezone</strong></span> command. For a
+ secondary server or for a dynamic zone, it is automatically
+ generated (if this format is specified by the
+ <span><strong class="command">masterfile-format</strong></span> option) when
+ <span><strong class="command">named</strong></span> dumps the zone contents after
+ zone transfer or when applying prior updates.
+ </p>
+<p>
+ If a zone file in a binary format needs manual modification,
+ it first must be converted to a textual form by the
+ <span><strong class="command">named-compilezone</strong></span> command. All
+ necessary modification should go to the text file, which
+ should then be converted to the binary form by the
+ <span><strong class="command">named-compilezone</strong></span> command again.
+ </p>
+<p>
+ Although the <code class="constant">raw</code> format uses the
+ network byte order and avoids architecture-dependent
+ data alignment so that it is as much portable as
+ possible, it is primarily expected to be used inside
+ the same single system. In order to export a zone
+ file in the <code class="constant">raw</code> format or make a
+ portable backup of the file, it is recommended to
+ convert the file to the standard textual representation.
+ </p>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="statistics"></a>BIND9 Statistics</h2></div></div></div>
+<p>
+ <acronym class="acronym">BIND</acronym> 9 maintains lots of statistics
+ information and provides several interfaces for users to
+ get access to the statistics.
+ The available statistics include all statistics counters
+ that were available in <acronym class="acronym">BIND</acronym> 8 and
+ are meaningful in <acronym class="acronym">BIND</acronym> 9,
+ and other information that is considered useful.
+ </p>
+<p>
+ The statistics information is categorized into the following
+ sections.
+ </p>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>Incoming Requests</p>
+ </td>
+<td>
+ <p>
+ The number of incoming DNS requests for each OPCODE.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>Incoming Queries</p>
+ </td>
+<td>
+ <p>
+ The number of incoming queries for each RR type.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>Outgoing Queries</p>
+ </td>
+<td>
+ <p>
+ The number of outgoing queries for each RR
+ type sent from the internal resolver.
+ Maintained per view.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>Name Server Statistics</p>
+ </td>
+<td>
+ <p>
+ Statistics counters about incoming request processing.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>Zone Maintenance Statistics</p>
+ </td>
+<td>
+ <p>
+ Statistics counters regarding zone maintenance
+ operations such as zone transfers.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>Resolver Statistics</p>
+ </td>
+<td>
+ <p>
+ Statistics counters about name resolution
+ performed in the internal resolver.
+ Maintained per view.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p>Cache DB RRsets</p>
+ </td>
+<td>
+ <p>
+ The number of RRsets per RR type (positive
+ or negative) and nonexistent names stored in the
+ cache database.
+ Maintained per view.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+<p>
+ A subset of Name Server Statistics is collected and shown
+ per zone for which the server has the authority when
+ <span><strong class="command">zone-statistics</strong></span> is set to
+ <strong class="userinput"><code>yes</code></strong>.
+ These statistics counters are shown with their zone and view
+ names.
+ In some cases the view names are omitted for the default view.
+ </p>
+<p>
+ There are currently two user interfaces to get access to the
+ statistics.
+ One is in the plain text format dumped to the file specified
+ by the <span><strong class="command">statistics-file</strong></span> configuration option.
+ The other is remotely accessible via a statistics channel
+ when the <span><strong class="command">statistics-channels</strong></span> statement
+ is specified in the configuration file
+ (see <a href="Bv9ARM.ch06.html#statschannels" title="statistics-channels Statement Grammar">the section called &#8220;<span><strong class="command">statistics-channels</strong></span> Statement Grammar&#8221;</a>.)
+ </p>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="statsfile"></a>The Statistics File</h4></div></div></div>
+<p>
+ The text format statistics dump begins with a line, like:
+ </p>
+<p>
+ <span><strong class="command">+++ Statistics Dump +++ (973798949)</strong></span>
+ </p>
+<p>
+ The number in parentheses is a standard
+ Unix-style timestamp, measured as seconds since January 1, 1970.
+
+ Following
+ that line is a set of statistics information, which is categorized
+ as described above.
+ Each section begins with a line, like:
+ </p>
+<p>
+ <span><strong class="command">++ Name Server Statistics ++</strong></span>
+ </p>
+<p>
+ Each section consists of lines, each containing the statistics
+ counter value followed by its textual description.
+ See below for available counters.
+ For brevity, counters that have a value of 0 are not shown
+ in the statistics file.
+ </p>
+<p>
+ The statistics dump ends with the line where the
+ number is identical to the number in the beginning line; for example:
+ </p>
+<p>
+ <span><strong class="command">--- Statistics Dump --- (973798949)</strong></span>
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="statistics_counters"></a>Statistics Counters</h3></div></div></div>
+<p>
+ The following tables summarize statistics counters that
+ <acronym class="acronym">BIND</acronym> 9 provides.
+ For each row of the tables, the leftmost column is the
+ abbreviated symbol name of that counter.
+ These symbols are shown in the statistics information
+ accessed via an HTTP statistics channel.
+ The rightmost column gives the description of the counter,
+ which is also shown in the statistics file
+ (but, in this document, possibly with slight modification
+ for better readability).
+ Additional notes may also be provided in this column.
+ When a middle column exists between these two columns,
+ it gives the corresponding counter name of the
+ <acronym class="acronym">BIND</acronym> 8 statistics, if applicable.
+ </p>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2594562"></a>Name Server Statistics Counters</h4></div></div></div>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <span class="emphasis"><em>Symbol</em></span>
+ </p>
+ </td>
+<td>
+ <p>
+ <span class="emphasis"><em>BIND8 Symbol</em></span>
+ </p>
+ </td>
+<td>
+ <p>
+ <span class="emphasis"><em>Description</em></span>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Requestv4</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv4 requests received.
+ Note: this also counts non query requests.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Requestv6</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv6 requests received.
+ Note: this also counts non query requests.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ReqEdns0</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Requests with EDNS(0) received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ReqBadEDNSVer</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Requests with unsupported EDNS version received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ReqTSIG</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Requests with TSIG received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ReqSIG0</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Requests with SIG(0) received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ReqBadSIG</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Requests with invalid (TSIG or SIG(0)) signature.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ReqTCP</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RTCP</strong></span></p>
+ </td>
+<td>
+ <p>
+ TCP requests received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">AuthQryRej</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RUQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ Authoritative (non recursive) queries rejected.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">RecQryRej</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RURQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ Recursive queries rejected.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">XfrRej</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RUXFR</strong></span></p>
+ </td>
+<td>
+ <p>
+ Zone transfer requests rejected.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">UpdateRej</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RUUpd</strong></span></p>
+ </td>
+<td>
+ <p>
+ Dynamic update requests rejected.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Response</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">SAns</strong></span></p>
+ </td>
+<td>
+ <p>
+ Responses sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">RespTruncated</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Truncated responses sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">RespEDNS0</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Responses with EDNS(0) sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">RespTSIG</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Responses with TSIG sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">RespSIG0</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Responses with SIG(0) sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QrySuccess</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries resulted in a successful answer.
+ This means the query which returns a NOERROR response
+ with at least one answer RR.
+ This corresponds to the
+ <span><strong class="command">success</strong></span> counter
+ of previous versions of
+ <acronym class="acronym">BIND</acronym> 9.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QryAuthAns</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries resulted in authoritative answer.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QryNoauthAns</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">SNaAns</strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries resulted in non authoritative answer.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QryReferral</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries resulted in referral answer.
+ This corresponds to the
+ <span><strong class="command">referral</strong></span> counter
+ of previous versions of
+ <acronym class="acronym">BIND</acronym> 9.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QryNxrrset</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries resulted in NOERROR responses with no data.
+ This corresponds to the
+ <span><strong class="command">nxrrset</strong></span> counter
+ of previous versions of
+ <acronym class="acronym">BIND</acronym> 9.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QrySERVFAIL</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">SFail</strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries resulted in SERVFAIL.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QryFORMERR</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">SFErr</strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries resulted in FORMERR.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QryNXDOMAIN</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">SNXD</strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries resulted in NXDOMAIN.
+ This corresponds to the
+ <span><strong class="command">nxdomain</strong></span> counter
+ of previous versions of
+ <acronym class="acronym">BIND</acronym> 9.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QryRecursion</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RFwdQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries which caused the server
+ to perform recursion in order to find the final answer.
+ This corresponds to the
+ <span><strong class="command">recursion</strong></span> counter
+ of previous versions of
+ <acronym class="acronym">BIND</acronym> 9.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QryDuplicate</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RDupQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries which the server attempted to
+ recurse but discovered an existing query with the same
+ IP address, port, query ID, name, type and class
+ already being processed.
+ This corresponds to the
+ <span><strong class="command">duplicate</strong></span> counter
+ of previous versions of
+ <acronym class="acronym">BIND</acronym> 9.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QryDropped</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Queries for which the server
+ discovered an excessive number of existing
+ recursive queries for the same name, type and
+ class and were subsequently dropped.
+ This corresponds to the
+ <span><strong class="command">dropped</strong></span> counter
+ of previous versions of
+ <acronym class="acronym">BIND</acronym> 9.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">QryFailure</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Other query failures.
+ This corresponds to the
+ <span><strong class="command">failure</strong></span> counter
+ of previous versions of
+ <acronym class="acronym">BIND</acronym> 9.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">XfrReqDone</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Requested zone transfers completed.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">UpdateReqFwd</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Update requests forwarded.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">UpdateRespFwd</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Update responses forwarded.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">UpdateFwdFail</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Dynamic update forward failed.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">UpdateDone</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Dynamic updates completed.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">UpdateFail</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Dynamic updates failed.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">UpdateBadPrereq</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Dynamic updates rejected due to prerequisite failure.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2596153"></a>Zone Maintenance Statistics Counters</h4></div></div></div>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <span class="emphasis"><em>Symbol</em></span>
+ </p>
+ </td>
+<td>
+ <p>
+ <span class="emphasis"><em>Description</em></span>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">NotifyOutv4</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv4 notifies sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">NotifyOutv6</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv6 notifies sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">NotifyInv4</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv4 notifies received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">NotifyInv6</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv6 notifies received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">NotifyRej</strong></span></p>
+ </td>
+<td>
+ <p>
+ Incoming notifies rejected.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">SOAOutv4</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv4 SOA queries sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">SOAOutv6</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv6 SOA queries sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">AXFRReqv4</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv4 AXFR requested.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">AXFRReqv6</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv6 AXFR requested.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">IXFRReqv4</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv4 IXFR requested.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">IXFRReqv6</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv6 IXFR requested.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">XfrSuccess</strong></span></p>
+ </td>
+<td>
+ <p>
+ Zone transfer requests succeeded.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">XfrFail</strong></span></p>
+ </td>
+<td>
+ <p>
+ Zone transfer requests failed.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2596604"></a>Resolver Statistics Counters</h4></div></div></div>
+<div class="informaltable"><table border="1">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<tbody>
+<tr>
+<td>
+ <p>
+ <span class="emphasis"><em>Symbol</em></span>
+ </p>
+ </td>
+<td>
+ <p>
+ <span class="emphasis"><em>BIND8 Symbol</em></span>
+ </p>
+ </td>
+<td>
+ <p>
+ <span class="emphasis"><em>Description</em></span>
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Queryv4</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">SFwdQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv4 queries sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Queryv6</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">SFwdQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv6 queries sent.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Responsev4</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RR</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv4 responses received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Responsev6</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RR</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv6 responses received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">NXDOMAIN</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RNXD</strong></span></p>
+ </td>
+<td>
+ <p>
+ NXDOMAIN received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">SERVFAIL</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RFail</strong></span></p>
+ </td>
+<td>
+ <p>
+ SERVFAIL received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">FORMERR</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RFErr</strong></span></p>
+ </td>
+<td>
+ <p>
+ FORMERR received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">OtherError</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RErr</strong></span></p>
+ </td>
+<td>
+ <p>
+ Other errors received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">EDNS0Fail</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ EDNS(0) query failures.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Mismatch</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RDupR</strong></span></p>
+ </td>
+<td>
+ <p>
+ Mismatch responses received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Truncated</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ Truncated responses received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Lame</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">RLame</strong></span></p>
+ </td>
+<td>
+ <p>
+ Lame delegations received.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">Retry</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">SDupQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ Query retries performed.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">GlueFetchv4</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">SSysQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv4 NS address fetches invoked.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">GlueFetchv6</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command">SSysQ</strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv6 NS address fetches invoked.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">GlueFetchv4Fail</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv4 NS address fetch failed.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">GlueFetchv6Fail</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ IPv6 NS address fetch failed.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ValAttempt</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ DNSSEC validation attempted.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ValOk</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ DNSSEC validation succeeded.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ValNegOk</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ DNSSEC validation on negative information succeeded.
+ </p>
+ </td>
+</tr>
+<tr>
+<td>
+ <p><span><strong class="command">ValFail</strong></span></p>
+ </td>
+<td>
+ <p><span><strong class="command"></strong></span></p>
+ </td>
+<td>
+ <p>
+ DNSSEC validation failed.
+ </p>
+ </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="sect3" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2597389"></a>Compatibility with <span class="emphasis"><em>BIND</em></span> 8 Counters</h4></div></div></div>
+<p>
+ Most statistics counters that were available
+ in <span><strong class="command">BIND</strong></span> 8 are also supported in
+ <span><strong class="command">BIND</strong></span> 9 as shown in the above tables.
+ Here are notes about other counters that do not appear
+ in these tables.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">RFwdR,SFwdR</strong></span></span></dt>
+<dd><p>
+ These counters are not supported
+ because <span><strong class="command">BIND</strong></span> 9 does not adopt
+ the notion of <span class="emphasis"><em>forwarding</em></span>
+ as <span><strong class="command">BIND</strong></span> 8 did.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">RAXFR</strong></span></span></dt>
+<dd><p>
+ This counter is accessible in the Incoming Queries section.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">RIQ</strong></span></span></dt>
+<dd><p>
+ This counter is accessible in the Incoming Requests section.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">ROpts</strong></span></span></dt>
+<dd><p>
+ This counter is not supported
+ because <span><strong class="command">BIND</strong></span> 9 does not care
+ about IP options in the first place.
+ </p></dd>
+<dt><span class="term"><span><strong class="command">SErr</strong></span></span></dt>
+<dd><p>
+ This counter could be implemented, but is not yet
+ supported.
+ </p></dd>
+</dl></div>
+</div>
+</div>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.ch05.html">Prev</a> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="Bv9ARM.ch07.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">Chapter 5. The <acronym class="acronym">BIND</acronym> 9 Lightweight Resolver </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> Chapter 7. <acronym class="acronym">BIND</acronym> 9 Security Considerations</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.ch07.html b/doc/arm/Bv9ARM.ch07.html
new file mode 100644
index 0000000..c973734
--- /dev/null
+++ b/doc/arm/Bv9ARM.ch07.html
@@ -0,0 +1,254 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.ch07.html,v 1.178 2008/11/07 01:11:20 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 7. BIND 9 Security Considerations</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="prev" href="Bv9ARM.ch06.html" title="Chapter 6. BIND 9 Configuration Reference">
+<link rel="next" href="Bv9ARM.ch08.html" title="Chapter 8. Troubleshooting">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">Chapter 7. <acronym class="acronym">BIND</acronym> 9 Security Considerations</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.ch06.html">Prev</a> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="Bv9ARM.ch08.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="Bv9ARM.ch07"></a>Chapter 7. <acronym class="acronym">BIND</acronym> 9 Security Considerations</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch07.html#Access_Control_Lists">Access Control Lists</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch07.html#id2597645"><span><strong class="command">Chroot</strong></span> and <span><strong class="command">Setuid</strong></span></a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch07.html#id2597722">The <span><strong class="command">chroot</strong></span> Environment</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch07.html#id2597782">Using the <span><strong class="command">setuid</strong></span> Function</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch07.html#dynamic_update_security">Dynamic Update Security</a></span></dt>
+</dl>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="Access_Control_Lists"></a>Access Control Lists</h2></div></div></div>
+<p>
+ Access Control Lists (ACLs), are address match lists that
+ you can set up and nickname for future use in <span><strong class="command">allow-notify</strong></span>,
+ <span><strong class="command">allow-query</strong></span>, <span><strong class="command">allow-query-on</strong></span>,
+ <span><strong class="command">allow-recursion</strong></span>, <span><strong class="command">allow-recursion-on</strong></span>,
+ <span><strong class="command">blackhole</strong></span>, <span><strong class="command">allow-transfer</strong></span>,
+ etc.
+ </p>
+<p>
+ Using ACLs allows you to have finer control over who can access
+ your name server, without cluttering up your config files with huge
+ lists of IP addresses.
+ </p>
+<p>
+ It is a <span class="emphasis"><em>good idea</em></span> to use ACLs, and to
+ control access to your server. Limiting access to your server by
+ outside parties can help prevent spoofing and denial of service (DoS) attacks against
+ your server.
+ </p>
+<p>
+ Here is an example of how to properly apply ACLs:
+ </p>
+<pre class="programlisting">
+// 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;
+};
+
+// 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 {
+ ...
+ ...
+ allow-query { our-nets; };
+ allow-recursion { our-nets; };
+ ...
+ blackhole { bogusnets; };
+ ...
+};
+
+zone "example.com" {
+ type master;
+ file "m/example.com";
+ allow-query { any; };
+};
+</pre>
+<p>
+ This allows recursive queries of the server from the outside
+ unless recursion has been previously disabled.
+ </p>
+<p>
+ For more information on how to use ACLs to protect your server,
+ see the <span class="emphasis"><em>AUSCERT</em></span> advisory at:
+ </p>
+<p>
+ <a href="ftp://ftp.auscert.org.au/pub/auscert/advisory/AL-1999.004.dns_dos" target="_top">ftp://ftp.auscert.org.au/pub/auscert/advisory/AL-1999.004.dns_dos</a>
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2597645"></a><span><strong class="command">Chroot</strong></span> and <span><strong class="command">Setuid</strong></span>
+</h2></div></div></div>
+<p>
+ On UNIX servers, it is possible to run <acronym class="acronym">BIND</acronym> in a <span class="emphasis"><em>chrooted</em></span> environment
+ (using the <span><strong class="command">chroot()</strong></span> function) by specifying the "<code class="option">-t</code>"
+ option. This can help improve system security by placing <acronym class="acronym">BIND</acronym> in
+ a "sandbox", which will limit the damage done if a server is
+ compromised.
+ </p>
+<p>
+ Another useful feature in the UNIX version of <acronym class="acronym">BIND</acronym> is the
+ ability to run the daemon as an unprivileged user ( <code class="option">-u</code> <em class="replaceable"><code>user</code></em> ).
+ We suggest running as an unprivileged user when using the <span><strong class="command">chroot</strong></span> feature.
+ </p>
+<p>
+ Here is an example command line to load <acronym class="acronym">BIND</acronym> in a <span><strong class="command">chroot</strong></span> sandbox,
+ <span><strong class="command">/var/named</strong></span>, and to run <span><strong class="command">named</strong></span> <span><strong class="command">setuid</strong></span> to
+ user 202:
+ </p>
+<p>
+ <strong class="userinput"><code>/usr/local/bin/named -u 202 -t /var/named</code></strong>
+ </p>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2597722"></a>The <span><strong class="command">chroot</strong></span> Environment</h3></div></div></div>
+<p>
+ In order for a <span><strong class="command">chroot</strong></span> environment
+ to
+ work properly in a particular directory
+ (for example, <code class="filename">/var/named</code>),
+ you will need to set up an environment that includes everything
+ <acronym class="acronym">BIND</acronym> needs to run.
+ From <acronym class="acronym">BIND</acronym>'s point of view, <code class="filename">/var/named</code> is
+ the root of the filesystem. You will need to adjust the values of
+ options like
+ like <span><strong class="command">directory</strong></span> and <span><strong class="command">pid-file</strong></span> to account
+ for this.
+ </p>
+<p>
+ Unlike with earlier versions of BIND, you typically will
+ <span class="emphasis"><em>not</em></span> need to compile <span><strong class="command">named</strong></span>
+ statically nor install shared libraries under the new root.
+ However, depending on your operating system, you may need
+ to set up things like
+ <code class="filename">/dev/zero</code>,
+ <code class="filename">/dev/random</code>,
+ <code class="filename">/dev/log</code>, and
+ <code class="filename">/etc/localtime</code>.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2597782"></a>Using the <span><strong class="command">setuid</strong></span> Function</h3></div></div></div>
+<p>
+ Prior to running the <span><strong class="command">named</strong></span> daemon,
+ use
+ the <span><strong class="command">touch</strong></span> utility (to change file
+ access and
+ modification times) or the <span><strong class="command">chown</strong></span>
+ utility (to
+ set the user id and/or group id) on files
+ to which you want <acronym class="acronym">BIND</acronym>
+ to write.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+ Note that if the <span><strong class="command">named</strong></span> daemon is running as an
+ unprivileged user, it will not be able to bind to new restricted
+ ports if the server is reloaded.
+ </div>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="dynamic_update_security"></a>Dynamic Update Security</h2></div></div></div>
+<p>
+ Access to the dynamic
+ update facility should be strictly limited. In earlier versions of
+ <acronym class="acronym">BIND</acronym>, the only way to do this was
+ based on the IP
+ address of the host requesting the update, by listing an IP address
+ or
+ network prefix in the <span><strong class="command">allow-update</strong></span>
+ zone option.
+ This method is insecure since the source address of the update UDP
+ packet
+ is easily forged. Also note that if the IP addresses allowed by the
+ <span><strong class="command">allow-update</strong></span> option include the
+ address of a slave
+ server which performs forwarding of dynamic updates, the master can
+ be
+ trivially attacked by sending the update to the slave, which will
+ forward it to the master with its own source IP address causing the
+ master to approve it without question.
+ </p>
+<p>
+ For these reasons, we strongly recommend that updates be
+ cryptographically authenticated by means of transaction signatures
+ (TSIG). That is, the <span><strong class="command">allow-update</strong></span>
+ option should
+ list only TSIG key names, not IP addresses or network
+ prefixes. Alternatively, the new <span><strong class="command">update-policy</strong></span>
+ option can be used.
+ </p>
+<p>
+ Some sites choose to keep all dynamically-updated DNS data
+ in a subdomain and delegate that subdomain to a separate zone. This
+ way, the top-level zone containing critical data such as the IP
+ addresses
+ of public web and mail servers need not allow dynamic update at
+ all.
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.ch06.html">Prev</a> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="Bv9ARM.ch08.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">Chapter 6. <acronym class="acronym">BIND</acronym> 9 Configuration Reference </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> Chapter 8. Troubleshooting</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.ch08.html b/doc/arm/Bv9ARM.ch08.html
new file mode 100644
index 0000000..d25df0b
--- /dev/null
+++ b/doc/arm/Bv9ARM.ch08.html
@@ -0,0 +1,139 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.ch08.html,v 1.178 2008/11/07 01:11:20 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 8. Troubleshooting</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="prev" href="Bv9ARM.ch07.html" title="Chapter 7. BIND 9 Security Considerations">
+<link rel="next" href="Bv9ARM.ch09.html" title="Appendix A. Appendices">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">Chapter 8. Troubleshooting</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.ch07.html">Prev</a> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="Bv9ARM.ch09.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="Bv9ARM.ch08"></a>Chapter 8. Troubleshooting</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch08.html#id2597862">Common Problems</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch08.html#id2597867">It's not working; how can I figure out what's wrong?</a></span></dt></dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch08.html#id2597879">Incrementing and Changing the Serial Number</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch08.html#id2597896">Where Can I Get Help?</a></span></dt>
+</dl>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2597862"></a>Common Problems</h2></div></div></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2597867"></a>It's not working; how can I figure out what's wrong?</h3></div></div></div>
+<p>
+ The best solution to solving installation and
+ configuration issues is to take preventative measures by setting
+ up logging files beforehand. The log files provide a
+ source of hints and information that can be used to figure out
+ what went wrong and how to fix the problem.
+ </p>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2597879"></a>Incrementing and Changing the Serial Number</h2></div></div></div>
+<p>
+ Zone serial numbers are just numbers &#8212; they aren't
+ date related. A lot of people set them to a number that
+ represents a date, usually of the form YYYYMMDDRR.
+ Occasionally they will make a mistake and set them to a
+ "date in the future" then try to correct them by setting
+ them to the "current date". This causes problems because
+ serial numbers are used to indicate that a zone has been
+ updated. If the serial number on the slave server is
+ lower than the serial number on the master, the slave
+ server will attempt to update its copy of the zone.
+ </p>
+<p>
+ Setting the serial number to a lower number on the master
+ server than the slave server means that the slave will not perform
+ updates to its copy of the zone.
+ </p>
+<p>
+ The solution to this is to add 2147483647 (2^31-1) to the
+ number, reload the zone and make sure all slaves have updated to
+ the new zone serial number, then reset the number to what you want
+ it to be, and reload the zone again.
+ </p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2597896"></a>Where Can I Get Help?</h2></div></div></div>
+<p>
+ The Internet Systems Consortium
+ (<acronym class="acronym">ISC</acronym>) offers a wide range
+ of support and service agreements for <acronym class="acronym">BIND</acronym> and <acronym class="acronym">DHCP</acronym> servers. Four
+ levels of premium support are available and each level includes
+ support for all <acronym class="acronym">ISC</acronym> programs,
+ significant discounts on products
+ and training, and a recognized priority on bug fixes and
+ non-funded feature requests. In addition, <acronym class="acronym">ISC</acronym> offers a standard
+ support agreement package which includes services ranging from bug
+ fix announcements to remote support. It also includes training in
+ <acronym class="acronym">BIND</acronym> and <acronym class="acronym">DHCP</acronym>.
+ </p>
+<p>
+ To discuss arrangements for support, contact
+ <a href="mailto:info@isc.org" target="_top">info@isc.org</a> or visit the
+ <acronym class="acronym">ISC</acronym> web page at
+ <a href="http://www.isc.org/services/support/" target="_top">http://www.isc.org/services/support/</a>
+ to read more.
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.ch07.html">Prev</a> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="Bv9ARM.ch09.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">Chapter 7. <acronym class="acronym">BIND</acronym> 9 Security Considerations </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> Appendix A. Appendices</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.ch09.html b/doc/arm/Bv9ARM.ch09.html
new file mode 100644
index 0000000..f16f4c6
--- /dev/null
+++ b/doc/arm/Bv9ARM.ch09.html
@@ -0,0 +1,630 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.ch09.html,v 1.180 2008/11/05 01:11:19 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Appendix A. Appendices</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="prev" href="Bv9ARM.ch08.html" title="Chapter 8. Troubleshooting">
+<link rel="next" href="Bv9ARM.ch10.html" title="Manual pages">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">Appendix A. Appendices</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.ch08.html">Prev</a> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="Bv9ARM.ch10.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="appendix" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="Bv9ARM.ch09"></a>Appendix A. Appendices</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch09.html#id2598026">Acknowledgments</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch09.html#historical_dns_information">A Brief History of the <acronym class="acronym">DNS</acronym> and <acronym class="acronym">BIND</acronym></a></span></dt></dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch09.html#id2598198">General <acronym class="acronym">DNS</acronym> Reference Information</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch09.html#ipv6addresses">IPv6 addresses (AAAA)</a></span></dt></dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch09.html#bibliography">Bibliography (and Suggested Reading)</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch09.html#rfcs">Request for Comments (RFCs)</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch09.html#internet_drafts">Internet Drafts</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch09.html#id2601546">Other Documents About <acronym class="acronym">BIND</acronym></a></span></dt>
+</dl></dd>
+</dl>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2598026"></a>Acknowledgments</h2></div></div></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="historical_dns_information"></a>A Brief History of the <acronym class="acronym">DNS</acronym> and <acronym class="acronym">BIND</acronym>
+</h3></div></div></div>
+<p>
+ Although the "official" beginning of the Domain Name
+ System occurred in 1984 with the publication of RFC 920, the
+ core of the new system was described in 1983 in RFCs 882 and
+ 883. From 1984 to 1987, the ARPAnet (the precursor to today's
+ Internet) became a testbed of experimentation for developing the
+ new naming/addressing scheme in a rapidly expanding,
+ operational network environment. New RFCs were written and
+ published in 1987 that modified the original documents to
+ incorporate improvements based on the working model. RFC 1034,
+ "Domain Names-Concepts and Facilities", and RFC 1035, "Domain
+ Names-Implementation and Specification" were published and
+ became the standards upon which all <acronym class="acronym">DNS</acronym> implementations are
+ built.
+ </p>
+<p>
+ The first working domain name server, called "Jeeves", was
+ written in 1983-84 by Paul Mockapetris for operation on DEC
+ Tops-20
+ machines located at the University of Southern California's
+ Information
+ Sciences Institute (USC-ISI) and SRI International's Network
+ Information
+ Center (SRI-NIC). A <acronym class="acronym">DNS</acronym> server for
+ Unix machines, the Berkeley Internet
+ Name Domain (<acronym class="acronym">BIND</acronym>) package, was
+ written soon after by a group of
+ graduate students at the University of California at Berkeley
+ under
+ a grant from the US Defense Advanced Research Projects
+ Administration
+ (DARPA).
+ </p>
+<p>
+ Versions of <acronym class="acronym">BIND</acronym> through
+ 4.8.3 were maintained by the Computer
+ Systems Research Group (CSRG) at UC Berkeley. Douglas Terry, Mark
+ Painter, David Riggle and Songnian Zhou made up the initial <acronym class="acronym">BIND</acronym>
+ project team. After that, additional work on the software package
+ was done by Ralph Campbell. Kevin Dunlap, a Digital Equipment
+ Corporation
+ employee on loan to the CSRG, worked on <acronym class="acronym">BIND</acronym> for 2 years, from 1985
+ to 1987. Many other people also contributed to <acronym class="acronym">BIND</acronym> development
+ during that time: Doug Kingston, Craig Partridge, Smoot
+ Carl-Mitchell,
+ Mike Muuss, Jim Bloom and Mike Schwartz. <acronym class="acronym">BIND</acronym> maintenance was subsequently
+ handled by Mike Karels and Øivind Kure.
+ </p>
+<p>
+ <acronym class="acronym">BIND</acronym> versions 4.9 and 4.9.1 were
+ released by Digital Equipment
+ Corporation (now Compaq Computer Corporation). Paul Vixie, then
+ a DEC employee, became <acronym class="acronym">BIND</acronym>'s
+ primary caretaker. He was assisted
+ by Phil Almquist, Robert Elz, Alan Barrett, Paul Albitz, Bryan
+ Beecher, Andrew
+ Partan, Andy Cherenson, Tom Limoncelli, Berthold Paffrath, Fuat
+ Baran, Anant Kumar, Art Harkin, Win Treese, Don Lewis, Christophe
+ Wolfhugel, and others.
+ </p>
+<p>
+ In 1994, <acronym class="acronym">BIND</acronym> version 4.9.2 was sponsored by
+ Vixie Enterprises. Paul
+ Vixie became <acronym class="acronym">BIND</acronym>'s principal
+ architect/programmer.
+ </p>
+<p>
+ <acronym class="acronym">BIND</acronym> versions from 4.9.3 onward
+ have been developed and maintained
+ by the Internet Systems Consortium and its predecessor,
+ the Internet Software Consortium, with support being provided
+ by ISC's sponsors.
+ </p>
+<p>
+ As co-architects/programmers, Bob Halley and
+ Paul Vixie released the first production-ready version of
+ <acronym class="acronym">BIND</acronym> version 8 in May 1997.
+ </p>
+<p>
+ BIND version 9 was released in September 2000 and is a
+ major rewrite of nearly all aspects of the underlying
+ BIND architecture.
+ </p>
+<p>
+ BIND version 4 is officially deprecated and BIND version
+ 8 development is considered maintenance-only in favor
+ of BIND version 9. No additional development is done
+ on BIND version 4 or BIND version 8 other than for
+ security-related patches.
+ </p>
+<p>
+ <acronym class="acronym">BIND</acronym> development work is made
+ possible today by the sponsorship
+ of several corporations, and by the tireless work efforts of
+ numerous individuals.
+ </p>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="id2598198"></a>General <acronym class="acronym">DNS</acronym> Reference Information</h2></div></div></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="ipv6addresses"></a>IPv6 addresses (AAAA)</h3></div></div></div>
+<p>
+ IPv6 addresses are 128-bit identifiers for interfaces and
+ sets of interfaces which were introduced in the <acronym class="acronym">DNS</acronym> to facilitate
+ scalable Internet routing. There are three types of addresses: <span class="emphasis"><em>Unicast</em></span>,
+ an identifier for a single interface;
+ <span class="emphasis"><em>Anycast</em></span>,
+ an identifier for a set of interfaces; and <span class="emphasis"><em>Multicast</em></span>,
+ an identifier for a set of interfaces. Here we describe the global
+ Unicast address scheme. For more information, see RFC 3587,
+ "Global Unicast Address Format."
+ </p>
+<p>
+ IPv6 unicast addresses consist of a
+ <span class="emphasis"><em>global routing prefix</em></span>, a
+ <span class="emphasis"><em>subnet identifier</em></span>, and an
+ <span class="emphasis"><em>interface identifier</em></span>.
+ </p>
+<p>
+ The global routing prefix is provided by the
+ upstream provider or ISP, and (roughly) corresponds to the
+ IPv4 <span class="emphasis"><em>network</em></span> section
+ of the address range.
+
+ The subnet identifier is for local subnetting, much the
+ same as subnetting an
+ IPv4 /16 network into /24 subnets.
+
+ The interface identifier is the address of an individual
+ interface on a given network; in IPv6, addresses belong to
+ interfaces rather than to machines.
+ </p>
+<p>
+ The subnetting capability of IPv6 is much more flexible than
+ that of IPv4: subnetting can be carried out on bit boundaries,
+ in much the same way as Classless InterDomain Routing
+ (CIDR), and the DNS PTR representation ("nibble" format)
+ makes setting up reverse zones easier.
+ </p>
+<p>
+ The Interface Identifier must be unique on the local link,
+ and is usually generated automatically by the IPv6
+ implementation, although it is usually possible to
+ override the default setting if necessary. A typical IPv6
+ address might look like:
+ <span><strong class="command">2001:db8:201:9:a00:20ff:fe81:2b32</strong></span>
+ </p>
+<p>
+ IPv6 address specifications often contain long strings
+ of zeros, so the architects have included a shorthand for
+ specifying
+ them. The double colon (`::') indicates the longest possible
+ string
+ of zeros that can fit, and can be used only once in an address.
+ </p>
+</div>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="bibliography"></a>Bibliography (and Suggested Reading)</h2></div></div></div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="rfcs"></a>Request for Comments (RFCs)</h3></div></div></div>
+<p>
+ Specification documents for the Internet protocol suite, including
+ the <acronym class="acronym">DNS</acronym>, are published as part of
+ the Request for Comments (RFCs)
+ series of technical notes. The standards themselves are defined
+ by the Internet Engineering Task Force (IETF) and the Internet
+ Engineering Steering Group (IESG). RFCs can be obtained online via FTP at:
+ </p>
+<p>
+ <a href="ftp://www.isi.edu/in-notes/" target="_top">
+ ftp://www.isi.edu/in-notes/RFC<em class="replaceable"><code>xxxx</code></em>.txt
+ </a>
+ </p>
+<p>
+ (where <em class="replaceable"><code>xxxx</code></em> is
+ the number of the RFC). RFCs are also available via the Web at:
+ </p>
+<p>
+ <a href="http://www.ietf.org/rfc/" target="_top">http://www.ietf.org/rfc/</a>.
+ </p>
+<div class="bibliography">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2598386"></a>Bibliography</h4></div></div></div>
+<div class="bibliodiv">
+<h3 class="title">Standards</h3>
+<div class="biblioentry">
+<a name="id2598396"></a><p>[<abbr class="abbrev">RFC974</abbr>] <span class="author"><span class="firstname">C.</span> <span class="surname">Partridge</span>. </span><span class="title"><i>Mail Routing and the Domain System</i>. </span><span class="pubdate">January 1986. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598420"></a><p>[<abbr class="abbrev">RFC1034</abbr>] <span class="author"><span class="firstname">P.V.</span> <span class="surname">Mockapetris</span>. </span><span class="title"><i>Domain Names &#8212; Concepts and Facilities</i>. </span><span class="pubdate">November 1987. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598443"></a><p>[<abbr class="abbrev">RFC1035</abbr>] <span class="author"><span class="firstname">P. V.</span> <span class="surname">Mockapetris</span>. </span><span class="title"><i>Domain Names &#8212; Implementation and
+ Specification</i>. </span><span class="pubdate">November 1987. </span></p>
+</div>
+</div>
+<div class="bibliodiv">
+<h3 class="title">
+<a name="proposed_standards"></a>Proposed Standards</h3>
+<div class="biblioentry">
+<a name="id2598480"></a><p>[<abbr class="abbrev">RFC2181</abbr>] <span class="author"><span class="firstname">R., R. Bush</span> <span class="surname">Elz</span>. </span><span class="title"><i>Clarifications to the <acronym class="acronym">DNS</acronym>
+ Specification</i>. </span><span class="pubdate">July 1997. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598574"></a><p>[<abbr class="abbrev">RFC2308</abbr>] <span class="author"><span class="firstname">M.</span> <span class="surname">Andrews</span>. </span><span class="title"><i>Negative Caching of <acronym class="acronym">DNS</acronym>
+ Queries</i>. </span><span class="pubdate">March 1998. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598600"></a><p>[<abbr class="abbrev">RFC1995</abbr>] <span class="author"><span class="firstname">M.</span> <span class="surname">Ohta</span>. </span><span class="title"><i>Incremental Zone Transfer in <acronym class="acronym">DNS</acronym></i>. </span><span class="pubdate">August 1996. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598625"></a><p>[<abbr class="abbrev">RFC1996</abbr>] <span class="author"><span class="firstname">P.</span> <span class="surname">Vixie</span>. </span><span class="title"><i>A Mechanism for Prompt Notification of Zone Changes</i>. </span><span class="pubdate">August 1996. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598648"></a><p>[<abbr class="abbrev">RFC2136</abbr>] <span class="authorgroup"><span class="firstname">P.</span> <span class="surname">Vixie</span>, <span class="firstname">S.</span> <span class="surname">Thomson</span>, <span class="firstname">Y.</span> <span class="surname">Rekhter</span>, and <span class="firstname">J.</span> <span class="surname">Bound</span>. </span><span class="title"><i>Dynamic Updates in the Domain Name System</i>. </span><span class="pubdate">April 1997. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598704"></a><p>[<abbr class="abbrev">RFC2671</abbr>] <span class="authorgroup"><span class="firstname">P.</span> <span class="surname">Vixie</span>. </span><span class="title"><i>Extension Mechanisms for DNS (EDNS0)</i>. </span><span class="pubdate">August 1997. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598730"></a><p>[<abbr class="abbrev">RFC2672</abbr>] <span class="authorgroup"><span class="firstname">M.</span> <span class="surname">Crawford</span>. </span><span class="title"><i>Non-Terminal DNS Name Redirection</i>. </span><span class="pubdate">August 1999. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598757"></a><p>[<abbr class="abbrev">RFC2845</abbr>] <span class="authorgroup"><span class="firstname">P.</span> <span class="surname">Vixie</span>, <span class="firstname">O.</span> <span class="surname">Gudmundsson</span>, <span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>, and <span class="firstname">B.</span> <span class="surname">Wellington</span>. </span><span class="title"><i>Secret Key Transaction Authentication for <acronym class="acronym">DNS</acronym> (TSIG)</i>. </span><span class="pubdate">May 2000. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598819"></a><p>[<abbr class="abbrev">RFC2930</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>. </span><span class="title"><i>Secret Key Establishment for DNS (TKEY RR)</i>. </span><span class="pubdate">September 2000. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598849"></a><p>[<abbr class="abbrev">RFC2931</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>. </span><span class="title"><i>DNS Request and Transaction Signatures (SIG(0)s)</i>. </span><span class="pubdate">September 2000. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598878"></a><p>[<abbr class="abbrev">RFC3007</abbr>] <span class="authorgroup"><span class="firstname">B.</span> <span class="surname">Wellington</span>. </span><span class="title"><i>Secure Domain Name System (DNS) Dynamic Update</i>. </span><span class="pubdate">November 2000. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2598905"></a><p>[<abbr class="abbrev">RFC3645</abbr>] <span class="authorgroup"><span class="firstname">S.</span> <span class="surname">Kwan</span>, <span class="firstname">P.</span> <span class="surname">Garg</span>, <span class="firstname">J.</span> <span class="surname">Gilroy</span>, <span class="firstname">L.</span> <span class="surname">Esibov</span>, <span class="firstname">J.</span> <span class="surname">Westhead</span>, and <span class="firstname">R.</span> <span class="surname">Hall</span>. </span><span class="title"><i>Generic Security Service Algorithm for Secret
+ Key Transaction Authentication for DNS
+ (GSS-TSIG)</i>. </span><span class="pubdate">October 2003. </span></p>
+</div>
+</div>
+<div class="bibliodiv">
+<h3 class="title">
+<acronym class="acronym">DNS</acronym> Security Proposed Standards</h3>
+<div class="biblioentry">
+<a name="id2599056"></a><p>[<abbr class="abbrev">RFC3225</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Conrad</span>. </span><span class="title"><i>Indicating Resolver Support of DNSSEC</i>. </span><span class="pubdate">December 2001. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599082"></a><p>[<abbr class="abbrev">RFC3833</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Atkins</span> and <span class="firstname">R.</span> <span class="surname">Austein</span>. </span><span class="title"><i>Threat Analysis of the Domain Name System (DNS)</i>. </span><span class="pubdate">August 2004. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599118"></a><p>[<abbr class="abbrev">RFC4033</abbr>] <span class="authorgroup"><span class="firstname">R.</span> <span class="surname">Arends</span>, <span class="firstname">R.</span> <span class="surname">Austein</span>, <span class="firstname">M.</span> <span class="surname">Larson</span>, <span class="firstname">D.</span> <span class="surname">Massey</span>, and <span class="firstname">S.</span> <span class="surname">Rose</span>. </span><span class="title"><i>DNS Security Introduction and Requirements</i>. </span><span class="pubdate">March 2005. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599184"></a><p>[<abbr class="abbrev">RFC4034</abbr>] <span class="authorgroup"><span class="firstname">R.</span> <span class="surname">Arends</span>, <span class="firstname">R.</span> <span class="surname">Austein</span>, <span class="firstname">M.</span> <span class="surname">Larson</span>, <span class="firstname">D.</span> <span class="surname">Massey</span>, and <span class="firstname">S.</span> <span class="surname">Rose</span>. </span><span class="title"><i>Resource Records for the DNS Security Extensions</i>. </span><span class="pubdate">March 2005. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599249"></a><p>[<abbr class="abbrev">RFC4035</abbr>] <span class="authorgroup"><span class="firstname">R.</span> <span class="surname">Arends</span>, <span class="firstname">R.</span> <span class="surname">Austein</span>, <span class="firstname">M.</span> <span class="surname">Larson</span>, <span class="firstname">D.</span> <span class="surname">Massey</span>, and <span class="firstname">S.</span> <span class="surname">Rose</span>. </span><span class="title"><i>Protocol Modifications for the DNS
+ Security Extensions</i>. </span><span class="pubdate">March 2005. </span></p>
+</div>
+</div>
+<div class="bibliodiv">
+<h3 class="title">Other Important RFCs About <acronym class="acronym">DNS</acronym>
+ Implementation</h3>
+<div class="biblioentry">
+<a name="id2599322"></a><p>[<abbr class="abbrev">RFC1535</abbr>] <span class="author"><span class="firstname">E.</span> <span class="surname">Gavron</span>. </span><span class="title"><i>A Security Problem and Proposed Correction With Widely
+ Deployed <acronym class="acronym">DNS</acronym> Software.</i>. </span><span class="pubdate">October 1993. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599348"></a><p>[<abbr class="abbrev">RFC1536</abbr>] <span class="authorgroup"><span class="firstname">A.</span> <span class="surname">Kumar</span>, <span class="firstname">J.</span> <span class="surname">Postel</span>, <span class="firstname">C.</span> <span class="surname">Neuman</span>, <span class="firstname">P.</span> <span class="surname">Danzig</span>, and <span class="firstname">S.</span> <span class="surname">Miller</span>. </span><span class="title"><i>Common <acronym class="acronym">DNS</acronym> Implementation
+ Errors and Suggested Fixes</i>. </span><span class="pubdate">October 1993. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599416"></a><p>[<abbr class="abbrev">RFC1982</abbr>] <span class="authorgroup"><span class="firstname">R.</span> <span class="surname">Elz</span> and <span class="firstname">R.</span> <span class="surname">Bush</span>. </span><span class="title"><i>Serial Number Arithmetic</i>. </span><span class="pubdate">August 1996. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599451"></a><p>[<abbr class="abbrev">RFC4074</abbr>] <span class="authorgroup"><span class="firstname">Y.</span> <span class="surname">Morishita</span> and <span class="firstname">T.</span> <span class="surname">Jinmei</span>. </span><span class="title"><i>Common Misbehaviour Against <acronym class="acronym">DNS</acronym>
+ Queries for IPv6 Addresses</i>. </span><span class="pubdate">May 2005. </span></p>
+</div>
+</div>
+<div class="bibliodiv">
+<h3 class="title">Resource Record Types</h3>
+<div class="biblioentry">
+<a name="id2599497"></a><p>[<abbr class="abbrev">RFC1183</abbr>] <span class="authorgroup"><span class="firstname">C.F.</span> <span class="surname">Everhart</span>, <span class="firstname">L. A.</span> <span class="surname">Mamakos</span>, <span class="firstname">R.</span> <span class="surname">Ullmann</span>, and <span class="firstname">P.</span> <span class="surname">Mockapetris</span>. </span><span class="title"><i>New <acronym class="acronym">DNS</acronym> RR Definitions</i>. </span><span class="pubdate">October 1990. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599555"></a><p>[<abbr class="abbrev">RFC1706</abbr>] <span class="authorgroup"><span class="firstname">B.</span> <span class="surname">Manning</span> and <span class="firstname">R.</span> <span class="surname">Colella</span>. </span><span class="title"><i><acronym class="acronym">DNS</acronym> NSAP Resource Records</i>. </span><span class="pubdate">October 1994. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599592"></a><p>[<abbr class="abbrev">RFC2168</abbr>] <span class="authorgroup"><span class="firstname">R.</span> <span class="surname">Daniel</span> and <span class="firstname">M.</span> <span class="surname">Mealling</span>. </span><span class="title"><i>Resolution of Uniform Resource Identifiers using
+ the Domain Name System</i>. </span><span class="pubdate">June 1997. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599627"></a><p>[<abbr class="abbrev">RFC1876</abbr>] <span class="authorgroup"><span class="firstname">C.</span> <span class="surname">Davis</span>, <span class="firstname">P.</span> <span class="surname">Vixie</span>, <span class="firstname">T.</span>, and <span class="firstname">I.</span> <span class="surname">Dickinson</span>. </span><span class="title"><i>A Means for Expressing Location Information in the
+ Domain
+ Name System</i>. </span><span class="pubdate">January 1996. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599682"></a><p>[<abbr class="abbrev">RFC2052</abbr>] <span class="authorgroup"><span class="firstname">A.</span> <span class="surname">Gulbrandsen</span> and <span class="firstname">P.</span> <span class="surname">Vixie</span>. </span><span class="title"><i>A <acronym class="acronym">DNS</acronym> RR for Specifying the
+ Location of
+ Services.</i>. </span><span class="pubdate">October 1996. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599720"></a><p>[<abbr class="abbrev">RFC2163</abbr>] <span class="author"><span class="firstname">A.</span> <span class="surname">Allocchio</span>. </span><span class="title"><i>Using the Internet <acronym class="acronym">DNS</acronym> to
+ Distribute MIXER
+ Conformant Global Address Mapping</i>. </span><span class="pubdate">January 1998. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599814"></a><p>[<abbr class="abbrev">RFC2230</abbr>] <span class="author"><span class="firstname">R.</span> <span class="surname">Atkinson</span>. </span><span class="title"><i>Key Exchange Delegation Record for the <acronym class="acronym">DNS</acronym></i>. </span><span class="pubdate">October 1997. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599840"></a><p>[<abbr class="abbrev">RFC2536</abbr>] <span class="author"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>. </span><span class="title"><i>DSA KEYs and SIGs in the Domain Name System (DNS)</i>. </span><span class="pubdate">March 1999. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599866"></a><p>[<abbr class="abbrev">RFC2537</abbr>] <span class="author"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>. </span><span class="title"><i>RSA/MD5 KEYs and SIGs in the Domain Name System (DNS)</i>. </span><span class="pubdate">March 1999. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599893"></a><p>[<abbr class="abbrev">RFC2538</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span> and <span class="firstname">O.</span> <span class="surname">Gudmundsson</span>. </span><span class="title"><i>Storing Certificates in the Domain Name System (DNS)</i>. </span><span class="pubdate">March 1999. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599932"></a><p>[<abbr class="abbrev">RFC2539</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>. </span><span class="title"><i>Storage of Diffie-Hellman Keys in the Domain Name System (DNS)</i>. </span><span class="pubdate">March 1999. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599962"></a><p>[<abbr class="abbrev">RFC2540</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>. </span><span class="title"><i>Detached Domain Name System (DNS) Information</i>. </span><span class="pubdate">March 1999. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2599992"></a><p>[<abbr class="abbrev">RFC2782</abbr>] <span class="author"><span class="firstname">A.</span> <span class="surname">Gulbrandsen</span>. </span><span class="author"><span class="firstname">P.</span> <span class="surname">Vixie</span>. </span><span class="author"><span class="firstname">L.</span> <span class="surname">Esibov</span>. </span><span class="title"><i>A DNS RR for specifying the location of services (DNS SRV)</i>. </span><span class="pubdate">February 2000. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600035"></a><p>[<abbr class="abbrev">RFC2915</abbr>] <span class="author"><span class="firstname">M.</span> <span class="surname">Mealling</span>. </span><span class="author"><span class="firstname">R.</span> <span class="surname">Daniel</span>. </span><span class="title"><i>The Naming Authority Pointer (NAPTR) DNS Resource Record</i>. </span><span class="pubdate">September 2000. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600068"></a><p>[<abbr class="abbrev">RFC3110</abbr>] <span class="author"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>. </span><span class="title"><i>RSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS)</i>. </span><span class="pubdate">May 2001. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600094"></a><p>[<abbr class="abbrev">RFC3123</abbr>] <span class="author"><span class="firstname">P.</span> <span class="surname">Koch</span>. </span><span class="title"><i>A DNS RR Type for Lists of Address Prefixes (APL RR)</i>. </span><span class="pubdate">June 2001. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600118"></a><p>[<abbr class="abbrev">RFC3596</abbr>] <span class="authorgroup"><span class="firstname">S.</span> <span class="surname">Thomson</span>, <span class="firstname">C.</span> <span class="surname">Huitema</span>, <span class="firstname">V.</span> <span class="surname">Ksinant</span>, and <span class="firstname">M.</span> <span class="surname">Souissi</span>. </span><span class="title"><i><acronym class="acronym">DNS</acronym> Extensions to support IP
+ version 6</i>. </span><span class="pubdate">October 2003. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600176"></a><p>[<abbr class="abbrev">RFC3597</abbr>] <span class="author"><span class="firstname">A.</span> <span class="surname">Gustafsson</span>. </span><span class="title"><i>Handling of Unknown DNS Resource Record (RR) Types</i>. </span><span class="pubdate">September 2003. </span></p>
+</div>
+</div>
+<div class="bibliodiv">
+<h3 class="title">
+<acronym class="acronym">DNS</acronym> and the Internet</h3>
+<div class="biblioentry">
+<a name="id2600208"></a><p>[<abbr class="abbrev">RFC1101</abbr>] <span class="author"><span class="firstname">P. V.</span> <span class="surname">Mockapetris</span>. </span><span class="title"><i><acronym class="acronym">DNS</acronym> Encoding of Network Names
+ and Other Types</i>. </span><span class="pubdate">April 1989. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600233"></a><p>[<abbr class="abbrev">RFC1123</abbr>] <span class="author"><span class="surname">Braden</span>. </span><span class="title"><i>Requirements for Internet Hosts - Application and
+ Support</i>. </span><span class="pubdate">October 1989. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600256"></a><p>[<abbr class="abbrev">RFC1591</abbr>] <span class="author"><span class="firstname">J.</span> <span class="surname">Postel</span>. </span><span class="title"><i>Domain Name System Structure and Delegation</i>. </span><span class="pubdate">March 1994. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600279"></a><p>[<abbr class="abbrev">RFC2317</abbr>] <span class="authorgroup"><span class="firstname">H.</span> <span class="surname">Eidnes</span>, <span class="firstname">G.</span> <span class="surname">de Groot</span>, and <span class="firstname">P.</span> <span class="surname">Vixie</span>. </span><span class="title"><i>Classless IN-ADDR.ARPA Delegation</i>. </span><span class="pubdate">March 1998. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600325"></a><p>[<abbr class="abbrev">RFC2826</abbr>] <span class="authorgroup"><span class="surname">Internet Architecture Board</span>. </span><span class="title"><i>IAB Technical Comment on the Unique DNS Root</i>. </span><span class="pubdate">May 2000. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600348"></a><p>[<abbr class="abbrev">RFC2929</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>, <span class="firstname">E.</span> <span class="surname">Brunner-Williams</span>, and <span class="firstname">B.</span> <span class="surname">Manning</span>. </span><span class="title"><i>Domain Name System (DNS) IANA Considerations</i>. </span><span class="pubdate">September 2000. </span></p>
+</div>
+</div>
+<div class="bibliodiv">
+<h3 class="title">
+<acronym class="acronym">DNS</acronym> Operations</h3>
+<div class="biblioentry">
+<a name="id2600406"></a><p>[<abbr class="abbrev">RFC1033</abbr>] <span class="author"><span class="firstname">M.</span> <span class="surname">Lottor</span>. </span><span class="title"><i>Domain administrators operations guide.</i>. </span><span class="pubdate">November 1987. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600429"></a><p>[<abbr class="abbrev">RFC1537</abbr>] <span class="author"><span class="firstname">P.</span> <span class="surname">Beertema</span>. </span><span class="title"><i>Common <acronym class="acronym">DNS</acronym> Data File
+ Configuration Errors</i>. </span><span class="pubdate">October 1993. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600456"></a><p>[<abbr class="abbrev">RFC1912</abbr>] <span class="author"><span class="firstname">D.</span> <span class="surname">Barr</span>. </span><span class="title"><i>Common <acronym class="acronym">DNS</acronym> Operational and
+ Configuration Errors</i>. </span><span class="pubdate">February 1996. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600483"></a><p>[<abbr class="abbrev">RFC2010</abbr>] <span class="authorgroup"><span class="firstname">B.</span> <span class="surname">Manning</span> and <span class="firstname">P.</span> <span class="surname">Vixie</span>. </span><span class="title"><i>Operational Criteria for Root Name Servers.</i>. </span><span class="pubdate">October 1996. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600519"></a><p>[<abbr class="abbrev">RFC2219</abbr>] <span class="authorgroup"><span class="firstname">M.</span> <span class="surname">Hamilton</span> and <span class="firstname">R.</span> <span class="surname">Wright</span>. </span><span class="title"><i>Use of <acronym class="acronym">DNS</acronym> Aliases for
+ Network Services.</i>. </span><span class="pubdate">October 1997. </span></p>
+</div>
+</div>
+<div class="bibliodiv">
+<h3 class="title">Internationalized Domain Names</h3>
+<div class="biblioentry">
+<a name="id2600565"></a><p>[<abbr class="abbrev">RFC2825</abbr>] <span class="authorgroup"><span class="surname">IAB</span> and <span class="firstname">R.</span> <span class="surname">Daigle</span>. </span><span class="title"><i>A Tangled Web: Issues of I18N, Domain Names,
+ and the Other Internet protocols</i>. </span><span class="pubdate">May 2000. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600597"></a><p>[<abbr class="abbrev">RFC3490</abbr>] <span class="authorgroup"><span class="firstname">P.</span> <span class="surname">Faltstrom</span>, <span class="firstname">P.</span> <span class="surname">Hoffman</span>, and <span class="firstname">A.</span> <span class="surname">Costello</span>. </span><span class="title"><i>Internationalizing Domain Names in Applications (IDNA)</i>. </span><span class="pubdate">March 2003. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600643"></a><p>[<abbr class="abbrev">RFC3491</abbr>] <span class="authorgroup"><span class="firstname">P.</span> <span class="surname">Hoffman</span> and <span class="firstname">M.</span> <span class="surname">Blanchet</span>. </span><span class="title"><i>Nameprep: A Stringprep Profile for Internationalized Domain Names</i>. </span><span class="pubdate">March 2003. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600678"></a><p>[<abbr class="abbrev">RFC3492</abbr>] <span class="authorgroup"><span class="firstname">A.</span> <span class="surname">Costello</span>. </span><span class="title"><i>Punycode: A Bootstring encoding of Unicode
+ for Internationalized Domain Names in
+ Applications (IDNA)</i>. </span><span class="pubdate">March 2003. </span></p>
+</div>
+</div>
+<div class="bibliodiv">
+<h3 class="title">Other <acronym class="acronym">DNS</acronym>-related RFCs</h3>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ Note: the following list of RFCs, although
+ <acronym class="acronym">DNS</acronym>-related, are not
+ concerned with implementing software.
+ </p>
+</div>
+<div class="biblioentry">
+<a name="id2600723"></a><p>[<abbr class="abbrev">RFC1464</abbr>] <span class="author"><span class="firstname">R.</span> <span class="surname">Rosenbaum</span>. </span><span class="title"><i>Using the Domain Name System To Store Arbitrary String
+ Attributes</i>. </span><span class="pubdate">May 1993. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600745"></a><p>[<abbr class="abbrev">RFC1713</abbr>] <span class="author"><span class="firstname">A.</span> <span class="surname">Romao</span>. </span><span class="title"><i>Tools for <acronym class="acronym">DNS</acronym> Debugging</i>. </span><span class="pubdate">November 1994. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600771"></a><p>[<abbr class="abbrev">RFC1794</abbr>] <span class="author"><span class="firstname">T.</span> <span class="surname">Brisco</span>. </span><span class="title"><i><acronym class="acronym">DNS</acronym> Support for Load
+ Balancing</i>. </span><span class="pubdate">April 1995. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600796"></a><p>[<abbr class="abbrev">RFC2240</abbr>] <span class="author"><span class="firstname">O.</span> <span class="surname">Vaughan</span>. </span><span class="title"><i>A Legal Basis for Domain Name Allocation</i>. </span><span class="pubdate">November 1997. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600820"></a><p>[<abbr class="abbrev">RFC2345</abbr>] <span class="authorgroup"><span class="firstname">J.</span> <span class="surname">Klensin</span>, <span class="firstname">T.</span> <span class="surname">Wolf</span>, and <span class="firstname">G.</span> <span class="surname">Oglesby</span>. </span><span class="title"><i>Domain Names and Company Name Retrieval</i>. </span><span class="pubdate">May 1998. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600866"></a><p>[<abbr class="abbrev">RFC2352</abbr>] <span class="author"><span class="firstname">O.</span> <span class="surname">Vaughan</span>. </span><span class="title"><i>A Convention For Using Legal Names as Domain Names</i>. </span><span class="pubdate">May 1998. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600889"></a><p>[<abbr class="abbrev">RFC3071</abbr>] <span class="authorgroup"><span class="firstname">J.</span> <span class="surname">Klensin</span>. </span><span class="title"><i>Reflections on the DNS, RFC 1591, and Categories of Domains</i>. </span><span class="pubdate">February 2001. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600916"></a><p>[<abbr class="abbrev">RFC3258</abbr>] <span class="authorgroup"><span class="firstname">T.</span> <span class="surname">Hardie</span>. </span><span class="title"><i>Distributing Authoritative Name Servers via
+ Shared Unicast Addresses</i>. </span><span class="pubdate">April 2002. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2600941"></a><p>[<abbr class="abbrev">RFC3901</abbr>] <span class="authorgroup"><span class="firstname">A.</span> <span class="surname">Durand</span> and <span class="firstname">J.</span> <span class="surname">Ihren</span>. </span><span class="title"><i>DNS IPv6 Transport Operational Guidelines</i>. </span><span class="pubdate">September 2004. </span></p>
+</div>
+</div>
+<div class="bibliodiv">
+<h3 class="title">Obsolete and Unimplemented Experimental RFC</h3>
+<div class="biblioentry">
+<a name="id2600985"></a><p>[<abbr class="abbrev">RFC1712</abbr>] <span class="authorgroup"><span class="firstname">C.</span> <span class="surname">Farrell</span>, <span class="firstname">M.</span> <span class="surname">Schulze</span>, <span class="firstname">S.</span> <span class="surname">Pleitner</span>, and <span class="firstname">D.</span> <span class="surname">Baldoni</span>. </span><span class="title"><i><acronym class="acronym">DNS</acronym> Encoding of Geographical
+ Location</i>. </span><span class="pubdate">November 1994. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601043"></a><p>[<abbr class="abbrev">RFC2673</abbr>] <span class="authorgroup"><span class="firstname">M.</span> <span class="surname">Crawford</span>. </span><span class="title"><i>Binary Labels in the Domain Name System</i>. </span><span class="pubdate">August 1999. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601069"></a><p>[<abbr class="abbrev">RFC2874</abbr>] <span class="authorgroup"><span class="firstname">M.</span> <span class="surname">Crawford</span> and <span class="firstname">C.</span> <span class="surname">Huitema</span>. </span><span class="title"><i>DNS Extensions to Support IPv6 Address Aggregation
+ and Renumbering</i>. </span><span class="pubdate">July 2000. </span></p>
+</div>
+</div>
+<div class="bibliodiv">
+<h3 class="title">Obsoleted DNS Security RFCs</h3>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ Most of these have been consolidated into RFC4033,
+ RFC4034 and RFC4035 which collectively describe DNSSECbis.
+ </p>
+</div>
+<div class="biblioentry">
+<a name="id2601117"></a><p>[<abbr class="abbrev">RFC2065</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span> and <span class="firstname">C.</span> <span class="surname">Kaufman</span>. </span><span class="title"><i>Domain Name System Security Extensions</i>. </span><span class="pubdate">January 1997. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601157"></a><p>[<abbr class="abbrev">RFC2137</abbr>] <span class="author"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>. </span><span class="title"><i>Secure Domain Name System Dynamic Update</i>. </span><span class="pubdate">April 1997. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601184"></a><p>[<abbr class="abbrev">RFC2535</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Eastlake</span>, <span class="lineage">3rd</span>. </span><span class="title"><i>Domain Name System Security Extensions</i>. </span><span class="pubdate">March 1999. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601213"></a><p>[<abbr class="abbrev">RFC3008</abbr>] <span class="authorgroup"><span class="firstname">B.</span> <span class="surname">Wellington</span>. </span><span class="title"><i>Domain Name System Security (DNSSEC)
+ Signing Authority</i>. </span><span class="pubdate">November 2000. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601239"></a><p>[<abbr class="abbrev">RFC3090</abbr>] <span class="authorgroup"><span class="firstname">E.</span> <span class="surname">Lewis</span>. </span><span class="title"><i>DNS Security Extension Clarification on Zone Status</i>. </span><span class="pubdate">March 2001. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601266"></a><p>[<abbr class="abbrev">RFC3445</abbr>] <span class="authorgroup"><span class="firstname">D.</span> <span class="surname">Massey</span> and <span class="firstname">S.</span> <span class="surname">Rose</span>. </span><span class="title"><i>Limiting the Scope of the KEY Resource Record (RR)</i>. </span><span class="pubdate">December 2002. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601370"></a><p>[<abbr class="abbrev">RFC3655</abbr>] <span class="authorgroup"><span class="firstname">B.</span> <span class="surname">Wellington</span> and <span class="firstname">O.</span> <span class="surname">Gudmundsson</span>. </span><span class="title"><i>Redefinition of DNS Authenticated Data (AD) bit</i>. </span><span class="pubdate">November 2003. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601406"></a><p>[<abbr class="abbrev">RFC3658</abbr>] <span class="authorgroup"><span class="firstname">O.</span> <span class="surname">Gudmundsson</span>. </span><span class="title"><i>Delegation Signer (DS) Resource Record (RR)</i>. </span><span class="pubdate">December 2003. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601433"></a><p>[<abbr class="abbrev">RFC3755</abbr>] <span class="authorgroup"><span class="firstname">S.</span> <span class="surname">Weiler</span>. </span><span class="title"><i>Legacy Resolver Compatibility for Delegation Signer (DS)</i>. </span><span class="pubdate">May 2004. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601460"></a><p>[<abbr class="abbrev">RFC3757</abbr>] <span class="authorgroup"><span class="firstname">O.</span> <span class="surname">Kolkman</span>, <span class="firstname">J.</span> <span class="surname">Schlyter</span>, and <span class="firstname">E.</span> <span class="surname">Lewis</span>. </span><span class="title"><i>Domain Name System KEY (DNSKEY) Resource Record
+ (RR) Secure Entry Point (SEP) Flag</i>. </span><span class="pubdate">April 2004. </span></p>
+</div>
+<div class="biblioentry">
+<a name="id2601505"></a><p>[<abbr class="abbrev">RFC3845</abbr>] <span class="authorgroup"><span class="firstname">J.</span> <span class="surname">Schlyter</span>. </span><span class="title"><i>DNS Security (DNSSEC) NextSECure (NSEC) RDATA Format</i>. </span><span class="pubdate">August 2004. </span></p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="internet_drafts"></a>Internet Drafts</h3></div></div></div>
+<p>
+ Internet Drafts (IDs) are rough-draft working documents of
+ the Internet Engineering Task Force. They are, in essence, RFCs
+ in the preliminary stages of development. Implementors are
+ cautioned not
+ to regard IDs as archival, and they should not be quoted or cited
+ in any formal documents unless accompanied by the disclaimer that
+ they are "works in progress." IDs have a lifespan of six months
+ after which they are deleted unless updated by their authors.
+ </p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="id2601546"></a>Other Documents About <acronym class="acronym">BIND</acronym>
+</h3></div></div></div>
+<p></p>
+<div class="bibliography">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="id2601556"></a>Bibliography</h4></div></div></div>
+<div class="biblioentry">
+<a name="id2601558"></a><p><span class="authorgroup"><span class="firstname">Paul</span> <span class="surname">Albitz</span> and <span class="firstname">Cricket</span> <span class="surname">Liu</span>. </span><span class="title"><i><acronym class="acronym">DNS</acronym> and <acronym class="acronym">BIND</acronym></i>. </span><span class="copyright">Copyright © 1998 Sebastopol, CA: O'Reilly and Associates. </span></p>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.ch08.html">Prev</a> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="Bv9ARM.ch10.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">Chapter 8. Troubleshooting </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> Manual pages</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.ch10.html b/doc/arm/Bv9ARM.ch10.html
new file mode 100644
index 0000000..3fa321a
--- /dev/null
+++ b/doc/arm/Bv9ARM.ch10.html
@@ -0,0 +1,111 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.ch10.html,v 1.11 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Manual pages</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="prev" href="Bv9ARM.ch09.html" title="Appendix A. Appendices">
+<link rel="next" href="man.dig.html" title="dig">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">Manual pages</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.ch09.html">Prev</a> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="man.dig.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="reference" lang="en">
+<div class="titlepage">
+<div><div><h1 class="title">
+<a name="Bv9ARM.ch10"></a>Manual pages</h1></div></div>
+<hr>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt>
+<span class="refentrytitle"><a href="man.dig.html">dig</a></span><span class="refpurpose"> &#8212; DNS lookup utility</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.host.html">host</a></span><span class="refpurpose"> &#8212; DNS lookup utility</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.dnssec-dsfromkey.html"><span class="application">dnssec-dsfromkey</span></a></span><span class="refpurpose"> &#8212; DNSSEC DS RR generation tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.dnssec-keyfromlabel.html"><span class="application">dnssec-keyfromlabel</span></a></span><span class="refpurpose"> &#8212; DNSSEC key generation tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.dnssec-keygen.html"><span class="application">dnssec-keygen</span></a></span><span class="refpurpose"> &#8212; DNSSEC key generation tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.dnssec-signzone.html"><span class="application">dnssec-signzone</span></a></span><span class="refpurpose"> &#8212; DNSSEC zone signing tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.named-checkconf.html"><span class="application">named-checkconf</span></a></span><span class="refpurpose"> &#8212; named configuration file syntax checking tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.named-checkzone.html"><span class="application">named-checkzone</span></a></span><span class="refpurpose"> &#8212; zone file validity checking or converting tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.named.html"><span class="application">named</span></a></span><span class="refpurpose"> &#8212; Internet domain name server</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.nsupdate.html"><span class="application">nsupdate</span></a></span><span class="refpurpose"> &#8212; Dynamic DNS update utility</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.rndc.html"><span class="application">rndc</span></a></span><span class="refpurpose"> &#8212; name server control utility</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.rndc.conf.html"><code class="filename">rndc.conf</code></a></span><span class="refpurpose"> &#8212; rndc configuration file</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.rndc-confgen.html"><span class="application">rndc-confgen</span></a></span><span class="refpurpose"> &#8212; rndc key generation tool</span>
+</dt>
+</dl>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.ch09.html">Prev</a> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="man.dig.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">Appendix A. Appendices </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> dig</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.html b/doc/arm/Bv9ARM.html
new file mode 100644
index 0000000..79ebc74
--- /dev/null
+++ b/doc/arm/Bv9ARM.html
@@ -0,0 +1,276 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: Bv9ARM.html,v 1.193 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>BIND 9 Administrator Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="next" href="Bv9ARM.ch01.html" title="Chapter 1. Introduction">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">BIND 9 Administrator Reference Manual</th></tr>
+<tr>
+<td width="20%" align="left"> </td>
+<th width="60%" align="center"> </th>
+<td width="20%" align="right"> <a accesskey="n" href="Bv9ARM.ch01.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="book" lang="en">
+<div class="titlepage">
+<div>
+<div><h1 class="title">
+<a name="id2563174"></a>BIND 9 Administrator Reference Manual</h1></div>
+<div><p class="copyright">Copyright © 2004-2008 Internet Systems Consortium, Inc. ("ISC")</p></div>
+<div><p class="copyright">Copyright © 2000-2003 Internet Software Consortium.</p></div>
+</div>
+<hr>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="chapter"><a href="Bv9ARM.ch01.html">1. Introduction</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch01.html#id2563405">Scope of Document</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch01.html#id2564385">Organization of This Document</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch01.html#id2564524">Conventions Used in This Document</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch01.html#id2564637">The Domain Name System (<acronym class="acronym">DNS</acronym>)</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2564659">DNS Fundamentals</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2564693">Domains and Domain Names</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2564845">Zones</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2567243">Authoritative Name Servers</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2567416">Caching Name Servers</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch01.html#id2567546">Name Servers in Multiple Roles</a></span></dt>
+</dl></dd>
+</dl></dd>
+<dt><span class="chapter"><a href="Bv9ARM.ch02.html">2. <acronym class="acronym">BIND</acronym> Resource Requirements</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch02.html#id2567580">Hardware requirements</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch02.html#id2567607">CPU Requirements</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch02.html#id2567620">Memory Requirements</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch02.html#id2567851">Name Server Intensive Environment Issues</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch02.html#id2567862">Supported Operating Systems</a></span></dt>
+</dl></dd>
+<dt><span class="chapter"><a href="Bv9ARM.ch03.html">3. Name Server Configuration</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch03.html#sample_configuration">Sample Configurations</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch03.html#id2567894">A Caching-only Name Server</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch03.html#id2567910">An Authoritative-only Name Server</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch03.html#id2568001">Load Balancing</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch03.html#id2568355">Name Server Operations</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch03.html#id2568360">Tools for Use With the Name Server Daemon</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch03.html#id2570104">Signals</a></span></dt>
+</dl></dd>
+</dl></dd>
+<dt><span class="chapter"><a href="Bv9ARM.ch04.html">4. Advanced DNS Features</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#notify">Notify</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#dynamic_update">Dynamic Update</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch04.html#journal">The journal file</a></span></dt></dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#incremental_zone_transfers">Incremental Zone Transfers (IXFR)</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#id2570509">Split DNS</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2570528">Example split DNS setup</a></span></dt></dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#tsig">TSIG</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571168">Generate Shared Keys for Each Pair of Hosts</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571241">Copying the Shared Secret to Both Machines</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571252">Informing the Servers of the Key's Existence</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571291">Instructing the Server to Use the Key</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571485">TSIG Key Based Access Control</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571530">Errors</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#id2571612">TKEY</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#id2571661">SIG(0)</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#DNSSEC">DNSSEC</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571798">Generating Keys</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571877">Signing the Zone</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2571958">Configuring Servers</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch04.html#id2572101">IPv6 Support in <acronym class="acronym">BIND</acronym> 9</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2572163">Address Lookups Using AAAA Records</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch04.html#id2572184">Address to Name Lookups Using Nibble Format</a></span></dt>
+</dl></dd>
+</dl></dd>
+<dt><span class="chapter"><a href="Bv9ARM.ch05.html">5. The <acronym class="acronym">BIND</acronym> 9 Lightweight Resolver</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch05.html#id2572217">The Lightweight Resolver Library</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch05.html#lwresd">Running a Resolver Daemon</a></span></dt>
+</dl></dd>
+<dt><span class="chapter"><a href="Bv9ARM.ch06.html">6. <acronym class="acronym">BIND</acronym> 9 Configuration Reference</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch06.html#configuration_file_elements">Configuration File Elements</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#address_match_lists">Address Match Lists</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2573721">Comment Syntax</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch06.html#Configuration_File_Grammar">Configuration File Grammar</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574292"><span><strong class="command">acl</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#acl"><span><strong class="command">acl</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574550"><span><strong class="command">controls</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#controls_statement_definition_and_usage"><span><strong class="command">controls</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574910"><span><strong class="command">include</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574928"><span><strong class="command">include</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2575088"><span><strong class="command">key</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2575111"><span><strong class="command">key</strong></span> Statement Definition and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2575202"><span><strong class="command">logging</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2575328"><span><strong class="command">logging</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576640"><span><strong class="command">lwres</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576713"><span><strong class="command">lwres</strong></span> Statement Definition and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576777"><span><strong class="command">masters</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576889"><span><strong class="command">masters</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576904"><span><strong class="command">options</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#options"><span><strong class="command">options</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#statschannels"><span><strong class="command">statistics-channels</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2585469"><span><strong class="command">statistics-channels</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#server_statement_grammar"><span><strong class="command">server</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#server_statement_definition_and_usage"><span><strong class="command">server</strong></span> Statement Definition and
+ Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2586153"><span><strong class="command">trusted-keys</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2586204"><span><strong class="command">trusted-keys</strong></span> Statement Definition
+ and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#view_statement_grammar"><span><strong class="command">view</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2586423"><span><strong class="command">view</strong></span> Statement Definition and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#zone_statement_grammar"><span><strong class="command">zone</strong></span>
+ Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2587892"><span><strong class="command">zone</strong></span> Statement Definition and Usage</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch06.html#id2590422">Zone File</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#types_of_resource_records_and_when_to_use_them">Types of Resource Records and When to Use Them</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2592652">Discussion of MX Records</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#Setting_TTLs">Setting TTLs</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2593204">Inverse Mapping in IPv4</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2593399">Other Zone File Directives</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2593656"><acronym class="acronym">BIND</acronym> Master File Extension: the <span><strong class="command">$GENERATE</strong></span> Directive</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#zonefile_format">Additional File Formats</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch06.html#statistics">BIND9 Statistics</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch06.html#statistics_counters">Statistics Counters</a></span></dt></dl></dd>
+</dl></dd>
+<dt><span class="chapter"><a href="Bv9ARM.ch07.html">7. <acronym class="acronym">BIND</acronym> 9 Security Considerations</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch07.html#Access_Control_Lists">Access Control Lists</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch07.html#id2597645"><span><strong class="command">Chroot</strong></span> and <span><strong class="command">Setuid</strong></span></a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch07.html#id2597722">The <span><strong class="command">chroot</strong></span> Environment</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch07.html#id2597782">Using the <span><strong class="command">setuid</strong></span> Function</a></span></dt>
+</dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch07.html#dynamic_update_security">Dynamic Update Security</a></span></dt>
+</dl></dd>
+<dt><span class="chapter"><a href="Bv9ARM.ch08.html">8. Troubleshooting</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch08.html#id2597862">Common Problems</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch08.html#id2597867">It's not working; how can I figure out what's wrong?</a></span></dt></dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch08.html#id2597879">Incrementing and Changing the Serial Number</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch08.html#id2597896">Where Can I Get Help?</a></span></dt>
+</dl></dd>
+<dt><span class="appendix"><a href="Bv9ARM.ch09.html">A. Appendices</a></span></dt>
+<dd><dl>
+<dt><span class="sect1"><a href="Bv9ARM.ch09.html#id2598026">Acknowledgments</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch09.html#historical_dns_information">A Brief History of the <acronym class="acronym">DNS</acronym> and <acronym class="acronym">BIND</acronym></a></span></dt></dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch09.html#id2598198">General <acronym class="acronym">DNS</acronym> Reference Information</a></span></dt>
+<dd><dl><dt><span class="sect2"><a href="Bv9ARM.ch09.html#ipv6addresses">IPv6 addresses (AAAA)</a></span></dt></dl></dd>
+<dt><span class="sect1"><a href="Bv9ARM.ch09.html#bibliography">Bibliography (and Suggested Reading)</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a href="Bv9ARM.ch09.html#rfcs">Request for Comments (RFCs)</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch09.html#internet_drafts">Internet Drafts</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch09.html#id2601546">Other Documents About <acronym class="acronym">BIND</acronym></a></span></dt>
+</dl></dd>
+</dl></dd>
+<dt><span class="reference"><a href="Bv9ARM.ch10.html">I. Manual pages</a></span></dt>
+<dd><dl>
+<dt>
+<span class="refentrytitle"><a href="man.dig.html">dig</a></span><span class="refpurpose"> &#8212; DNS lookup utility</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.host.html">host</a></span><span class="refpurpose"> &#8212; DNS lookup utility</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.dnssec-dsfromkey.html"><span class="application">dnssec-dsfromkey</span></a></span><span class="refpurpose"> &#8212; DNSSEC DS RR generation tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.dnssec-keyfromlabel.html"><span class="application">dnssec-keyfromlabel</span></a></span><span class="refpurpose"> &#8212; DNSSEC key generation tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.dnssec-keygen.html"><span class="application">dnssec-keygen</span></a></span><span class="refpurpose"> &#8212; DNSSEC key generation tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.dnssec-signzone.html"><span class="application">dnssec-signzone</span></a></span><span class="refpurpose"> &#8212; DNSSEC zone signing tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.named-checkconf.html"><span class="application">named-checkconf</span></a></span><span class="refpurpose"> &#8212; named configuration file syntax checking tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.named-checkzone.html"><span class="application">named-checkzone</span></a></span><span class="refpurpose"> &#8212; zone file validity checking or converting tool</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.named.html"><span class="application">named</span></a></span><span class="refpurpose"> &#8212; Internet domain name server</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.nsupdate.html"><span class="application">nsupdate</span></a></span><span class="refpurpose"> &#8212; Dynamic DNS update utility</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.rndc.html"><span class="application">rndc</span></a></span><span class="refpurpose"> &#8212; name server control utility</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.rndc.conf.html"><code class="filename">rndc.conf</code></a></span><span class="refpurpose"> &#8212; rndc configuration file</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="man.rndc-confgen.html"><span class="application">rndc-confgen</span></a></span><span class="refpurpose"> &#8212; rndc key generation tool</span>
+</dt>
+</dl></dd>
+</dl>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left"> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right"> <a accesskey="n" href="Bv9ARM.ch01.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top"> </td>
+<td width="20%" align="center"> </td>
+<td width="40%" align="right" valign="top"> Chapter 1. Introduction</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/Bv9ARM.pdf b/doc/arm/Bv9ARM.pdf
new file mode 100755
index 0000000..b56a05d
--- /dev/null
+++ b/doc/arm/Bv9ARM.pdf
@@ -0,0 +1,14133 @@
+%PDF-1.4
+5 0 obj
+<< /S /GoTo /D (chapter.1) >>
+endobj
+8 0 obj
+(1 Introduction)
+endobj
+9 0 obj
+<< /S /GoTo /D (section.1.1) >>
+endobj
+12 0 obj
+(1.1 Scope of Document)
+endobj
+13 0 obj
+<< /S /GoTo /D (section.1.2) >>
+endobj
+16 0 obj
+(1.2 Organization of This Document)
+endobj
+17 0 obj
+<< /S /GoTo /D (section.1.3) >>
+endobj
+20 0 obj
+(1.3 Conventions Used in This Document)
+endobj
+21 0 obj
+<< /S /GoTo /D (section.1.4) >>
+endobj
+24 0 obj
+(1.4 The Domain Name System \(DNS\))
+endobj
+25 0 obj
+<< /S /GoTo /D (subsection.1.4.1) >>
+endobj
+28 0 obj
+(1.4.1 DNS Fundamentals)
+endobj
+29 0 obj
+<< /S /GoTo /D (subsection.1.4.2) >>
+endobj
+32 0 obj
+(1.4.2 Domains and Domain Names)
+endobj
+33 0 obj
+<< /S /GoTo /D (subsection.1.4.3) >>
+endobj
+36 0 obj
+(1.4.3 Zones)
+endobj
+37 0 obj
+<< /S /GoTo /D (subsection.1.4.4) >>
+endobj
+40 0 obj
+(1.4.4 Authoritative Name Servers)
+endobj
+41 0 obj
+<< /S /GoTo /D (subsubsection.1.4.4.1) >>
+endobj
+44 0 obj
+(1.4.4.1 The Primary Master)
+endobj
+45 0 obj
+<< /S /GoTo /D (subsubsection.1.4.4.2) >>
+endobj
+48 0 obj
+(1.4.4.2 Slave Servers)
+endobj
+49 0 obj
+<< /S /GoTo /D (subsubsection.1.4.4.3) >>
+endobj
+52 0 obj
+(1.4.4.3 Stealth Servers)
+endobj
+53 0 obj
+<< /S /GoTo /D (subsection.1.4.5) >>
+endobj
+56 0 obj
+(1.4.5 Caching Name Servers)
+endobj
+57 0 obj
+<< /S /GoTo /D (subsubsection.1.4.5.1) >>
+endobj
+60 0 obj
+(1.4.5.1 Forwarding)
+endobj
+61 0 obj
+<< /S /GoTo /D (subsection.1.4.6) >>
+endobj
+64 0 obj
+(1.4.6 Name Servers in Multiple Roles)
+endobj
+65 0 obj
+<< /S /GoTo /D (chapter.2) >>
+endobj
+68 0 obj
+(2 BIND Resource Requirements)
+endobj
+69 0 obj
+<< /S /GoTo /D (section.2.1) >>
+endobj
+72 0 obj
+(2.1 Hardware requirements)
+endobj
+73 0 obj
+<< /S /GoTo /D (section.2.2) >>
+endobj
+76 0 obj
+(2.2 CPU Requirements)
+endobj
+77 0 obj
+<< /S /GoTo /D (section.2.3) >>
+endobj
+80 0 obj
+(2.3 Memory Requirements)
+endobj
+81 0 obj
+<< /S /GoTo /D (section.2.4) >>
+endobj
+84 0 obj
+(2.4 Name Server Intensive Environment Issues)
+endobj
+85 0 obj
+<< /S /GoTo /D (section.2.5) >>
+endobj
+88 0 obj
+(2.5 Supported Operating Systems)
+endobj
+89 0 obj
+<< /S /GoTo /D (chapter.3) >>
+endobj
+92 0 obj
+(3 Name Server Configuration)
+endobj
+93 0 obj
+<< /S /GoTo /D (section.3.1) >>
+endobj
+96 0 obj
+(3.1 Sample Configurations)
+endobj
+97 0 obj
+<< /S /GoTo /D (subsection.3.1.1) >>
+endobj
+100 0 obj
+(3.1.1 A Caching-only Name Server)
+endobj
+101 0 obj
+<< /S /GoTo /D (subsection.3.1.2) >>
+endobj
+104 0 obj
+(3.1.2 An Authoritative-only Name Server)
+endobj
+105 0 obj
+<< /S /GoTo /D (section.3.2) >>
+endobj
+108 0 obj
+(3.2 Load Balancing)
+endobj
+109 0 obj
+<< /S /GoTo /D (section.3.3) >>
+endobj
+112 0 obj
+(3.3 Name Server Operations)
+endobj
+113 0 obj
+<< /S /GoTo /D (subsection.3.3.1) >>
+endobj
+116 0 obj
+(3.3.1 Tools for Use With the Name Server Daemon)
+endobj
+117 0 obj
+<< /S /GoTo /D (subsubsection.3.3.1.1) >>
+endobj
+120 0 obj
+(3.3.1.1 Diagnostic Tools)
+endobj
+121 0 obj
+<< /S /GoTo /D (subsubsection.3.3.1.2) >>
+endobj
+124 0 obj
+(3.3.1.2 Administrative Tools)
+endobj
+125 0 obj
+<< /S /GoTo /D (subsection.3.3.2) >>
+endobj
+128 0 obj
+(3.3.2 Signals)
+endobj
+129 0 obj
+<< /S /GoTo /D (chapter.4) >>
+endobj
+132 0 obj
+(4 Advanced DNS Features)
+endobj
+133 0 obj
+<< /S /GoTo /D (section.4.1) >>
+endobj
+136 0 obj
+(4.1 Notify)
+endobj
+137 0 obj
+<< /S /GoTo /D (section.4.2) >>
+endobj
+140 0 obj
+(4.2 Dynamic Update)
+endobj
+141 0 obj
+<< /S /GoTo /D (subsection.4.2.1) >>
+endobj
+144 0 obj
+(4.2.1 The journal file)
+endobj
+145 0 obj
+<< /S /GoTo /D (section.4.3) >>
+endobj
+148 0 obj
+(4.3 Incremental Zone Transfers \(IXFR\))
+endobj
+149 0 obj
+<< /S /GoTo /D (section.4.4) >>
+endobj
+152 0 obj
+(4.4 Split DNS)
+endobj
+153 0 obj
+<< /S /GoTo /D (subsection.4.4.1) >>
+endobj
+156 0 obj
+(4.4.1 Example split DNS setup)
+endobj
+157 0 obj
+<< /S /GoTo /D (section.4.5) >>
+endobj
+160 0 obj
+(4.5 TSIG)
+endobj
+161 0 obj
+<< /S /GoTo /D (subsection.4.5.1) >>
+endobj
+164 0 obj
+(4.5.1 Generate Shared Keys for Each Pair of Hosts)
+endobj
+165 0 obj
+<< /S /GoTo /D (subsubsection.4.5.1.1) >>
+endobj
+168 0 obj
+(4.5.1.1 Automatic Generation)
+endobj
+169 0 obj
+<< /S /GoTo /D (subsubsection.4.5.1.2) >>
+endobj
+172 0 obj
+(4.5.1.2 Manual Generation)
+endobj
+173 0 obj
+<< /S /GoTo /D (subsection.4.5.2) >>
+endobj
+176 0 obj
+(4.5.2 Copying the Shared Secret to Both Machines)
+endobj
+177 0 obj
+<< /S /GoTo /D (subsection.4.5.3) >>
+endobj
+180 0 obj
+(4.5.3 Informing the Servers of the Key's Existence)
+endobj
+181 0 obj
+<< /S /GoTo /D (subsection.4.5.4) >>
+endobj
+184 0 obj
+(4.5.4 Instructing the Server to Use the Key)
+endobj
+185 0 obj
+<< /S /GoTo /D (subsection.4.5.5) >>
+endobj
+188 0 obj
+(4.5.5 TSIG Key Based Access Control)
+endobj
+189 0 obj
+<< /S /GoTo /D (subsection.4.5.6) >>
+endobj
+192 0 obj
+(4.5.6 Errors)
+endobj
+193 0 obj
+<< /S /GoTo /D (section.4.6) >>
+endobj
+196 0 obj
+(4.6 TKEY)
+endobj
+197 0 obj
+<< /S /GoTo /D (section.4.7) >>
+endobj
+200 0 obj
+(4.7 SIG\(0\))
+endobj
+201 0 obj
+<< /S /GoTo /D (section.4.8) >>
+endobj
+204 0 obj
+(4.8 DNSSEC)
+endobj
+205 0 obj
+<< /S /GoTo /D (subsection.4.8.1) >>
+endobj
+208 0 obj
+(4.8.1 Generating Keys)
+endobj
+209 0 obj
+<< /S /GoTo /D (subsection.4.8.2) >>
+endobj
+212 0 obj
+(4.8.2 Signing the Zone)
+endobj
+213 0 obj
+<< /S /GoTo /D (subsection.4.8.3) >>
+endobj
+216 0 obj
+(4.8.3 Configuring Servers)
+endobj
+217 0 obj
+<< /S /GoTo /D (section.4.9) >>
+endobj
+220 0 obj
+(4.9 IPv6 Support in BIND 9)
+endobj
+221 0 obj
+<< /S /GoTo /D (subsection.4.9.1) >>
+endobj
+224 0 obj
+(4.9.1 Address Lookups Using AAAA Records)
+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)
+endobj
+229 0 obj
+<< /S /GoTo /D (chapter.5) >>
+endobj
+232 0 obj
+(5 The BIND 9 Lightweight Resolver)
+endobj
+233 0 obj
+<< /S /GoTo /D (section.5.1) >>
+endobj
+236 0 obj
+(5.1 The Lightweight Resolver Library)
+endobj
+237 0 obj
+<< /S /GoTo /D (section.5.2) >>
+endobj
+240 0 obj
+(5.2 Running a Resolver Daemon)
+endobj
+241 0 obj
+<< /S /GoTo /D (chapter.6) >>
+endobj
+244 0 obj
+(6 BIND 9 Configuration Reference)
+endobj
+245 0 obj
+<< /S /GoTo /D (section.6.1) >>
+endobj
+248 0 obj
+(6.1 Configuration File Elements)
+endobj
+249 0 obj
+<< /S /GoTo /D (subsection.6.1.1) >>
+endobj
+252 0 obj
+(6.1.1 Address Match Lists)
+endobj
+253 0 obj
+<< /S /GoTo /D (subsubsection.6.1.1.1) >>
+endobj
+256 0 obj
+(6.1.1.1 Syntax)
+endobj
+257 0 obj
+<< /S /GoTo /D (subsubsection.6.1.1.2) >>
+endobj
+260 0 obj
+(6.1.1.2 Definition and Usage)
+endobj
+261 0 obj
+<< /S /GoTo /D (subsection.6.1.2) >>
+endobj
+264 0 obj
+(6.1.2 Comment Syntax)
+endobj
+265 0 obj
+<< /S /GoTo /D (subsubsection.6.1.2.1) >>
+endobj
+268 0 obj
+(6.1.2.1 Syntax)
+endobj
+269 0 obj
+<< /S /GoTo /D (subsubsection.6.1.2.2) >>
+endobj
+272 0 obj
+(6.1.2.2 Definition and Usage)
+endobj
+273 0 obj
+<< /S /GoTo /D (section.6.2) >>
+endobj
+276 0 obj
+(6.2 Configuration File Grammar)
+endobj
+277 0 obj
+<< /S /GoTo /D (subsection.6.2.1) >>
+endobj
+280 0 obj
+(6.2.1 acl Statement Grammar)
+endobj
+281 0 obj
+<< /S /GoTo /D (subsection.6.2.2) >>
+endobj
+284 0 obj
+(6.2.2 acl Statement Definition and Usage)
+endobj
+285 0 obj
+<< /S /GoTo /D (subsection.6.2.3) >>
+endobj
+288 0 obj
+(6.2.3 controls Statement Grammar)
+endobj
+289 0 obj
+<< /S /GoTo /D (subsection.6.2.4) >>
+endobj
+292 0 obj
+(6.2.4 controls Statement Definition and Usage)
+endobj
+293 0 obj
+<< /S /GoTo /D (subsection.6.2.5) >>
+endobj
+296 0 obj
+(6.2.5 include Statement Grammar)
+endobj
+297 0 obj
+<< /S /GoTo /D (subsection.6.2.6) >>
+endobj
+300 0 obj
+(6.2.6 include Statement Definition and Usage)
+endobj
+301 0 obj
+<< /S /GoTo /D (subsection.6.2.7) >>
+endobj
+304 0 obj
+(6.2.7 key Statement Grammar)
+endobj
+305 0 obj
+<< /S /GoTo /D (subsection.6.2.8) >>
+endobj
+308 0 obj
+(6.2.8 key Statement Definition and Usage)
+endobj
+309 0 obj
+<< /S /GoTo /D (subsection.6.2.9) >>
+endobj
+312 0 obj
+(6.2.9 logging Statement Grammar)
+endobj
+313 0 obj
+<< /S /GoTo /D (subsection.6.2.10) >>
+endobj
+316 0 obj
+(6.2.10 logging Statement Definition and Usage)
+endobj
+317 0 obj
+<< /S /GoTo /D (subsubsection.6.2.10.1) >>
+endobj
+320 0 obj
+(6.2.10.1 The channel Phrase)
+endobj
+321 0 obj
+<< /S /GoTo /D (subsubsection.6.2.10.2) >>
+endobj
+324 0 obj
+(6.2.10.2 The category Phrase)
+endobj
+325 0 obj
+<< /S /GoTo /D (subsection.6.2.11) >>
+endobj
+328 0 obj
+(6.2.11 lwres Statement Grammar)
+endobj
+329 0 obj
+<< /S /GoTo /D (subsection.6.2.12) >>
+endobj
+332 0 obj
+(6.2.12 lwres Statement Definition and Usage)
+endobj
+333 0 obj
+<< /S /GoTo /D (subsection.6.2.13) >>
+endobj
+336 0 obj
+(6.2.13 masters Statement Grammar)
+endobj
+337 0 obj
+<< /S /GoTo /D (subsection.6.2.14) >>
+endobj
+340 0 obj
+(6.2.14 masters Statement Definition and Usage)
+endobj
+341 0 obj
+<< /S /GoTo /D (subsection.6.2.15) >>
+endobj
+344 0 obj
+(6.2.15 options Statement Grammar)
+endobj
+345 0 obj
+<< /S /GoTo /D (subsection.6.2.16) >>
+endobj
+348 0 obj
+(6.2.16 options Statement Definition and Usage)
+endobj
+349 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.1) >>
+endobj
+352 0 obj
+(6.2.16.1 Boolean Options)
+endobj
+353 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.2) >>
+endobj
+356 0 obj
+(6.2.16.2 Forwarding)
+endobj
+357 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.3) >>
+endobj
+360 0 obj
+(6.2.16.3 Dual-stack Servers)
+endobj
+361 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.4) >>
+endobj
+364 0 obj
+(6.2.16.4 Access Control)
+endobj
+365 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.5) >>
+endobj
+368 0 obj
+(6.2.16.5 Interfaces)
+endobj
+369 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.6) >>
+endobj
+372 0 obj
+(6.2.16.6 Query Address)
+endobj
+373 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.7) >>
+endobj
+376 0 obj
+(6.2.16.7 Zone Transfers)
+endobj
+377 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.8) >>
+endobj
+380 0 obj
+(6.2.16.8 UDP Port Lists)
+endobj
+381 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.9) >>
+endobj
+384 0 obj
+(6.2.16.9 Operating System Resource Limits)
+endobj
+385 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.10) >>
+endobj
+388 0 obj
+(6.2.16.10 Server Resource Limits)
+endobj
+389 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.11) >>
+endobj
+392 0 obj
+(6.2.16.11 Periodic Task Intervals)
+endobj
+393 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.12) >>
+endobj
+396 0 obj
+(6.2.16.12 Topology)
+endobj
+397 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.13) >>
+endobj
+400 0 obj
+(6.2.16.13 The sortlist Statement)
+endobj
+401 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.14) >>
+endobj
+404 0 obj
+(6.2.16.14 RRset Ordering)
+endobj
+405 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.15) >>
+endobj
+408 0 obj
+(6.2.16.15 Tuning)
+endobj
+409 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.16) >>
+endobj
+412 0 obj
+(6.2.16.16 Built-in server information zones)
+endobj
+413 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.17) >>
+endobj
+416 0 obj
+(6.2.16.17 Built-in Empty Zones)
+endobj
+417 0 obj
+<< /S /GoTo /D (subsubsection.6.2.16.18) >>
+endobj
+420 0 obj
+(6.2.16.18 Additional Section Caching)
+endobj
+421 0 obj
+<< /S /GoTo /D (subsection.6.2.17) >>
+endobj
+424 0 obj
+(6.2.17 statistics-channels Statement Grammar)
+endobj
+425 0 obj
+<< /S /GoTo /D (subsection.6.2.18) >>
+endobj
+428 0 obj
+(6.2.18 statistics-channels Statement Definition and Usage)
+endobj
+429 0 obj
+<< /S /GoTo /D (subsection.6.2.19) >>
+endobj
+432 0 obj
+(6.2.19 server Statement Grammar)
+endobj
+433 0 obj
+<< /S /GoTo /D (subsection.6.2.20) >>
+endobj
+436 0 obj
+(6.2.20 server Statement Definition and Usage)
+endobj
+437 0 obj
+<< /S /GoTo /D (subsection.6.2.21) >>
+endobj
+440 0 obj
+(6.2.21 trusted-keys Statement Grammar)
+endobj
+441 0 obj
+<< /S /GoTo /D (subsection.6.2.22) >>
+endobj
+444 0 obj
+(6.2.22 trusted-keys Statement Definition and Usage)
+endobj
+445 0 obj
+<< /S /GoTo /D (subsection.6.2.23) >>
+endobj
+448 0 obj
+(6.2.23 view Statement Grammar)
+endobj
+449 0 obj
+<< /S /GoTo /D (subsection.6.2.24) >>
+endobj
+452 0 obj
+(6.2.24 view Statement Definition and Usage)
+endobj
+453 0 obj
+<< /S /GoTo /D (subsection.6.2.25) >>
+endobj
+456 0 obj
+(6.2.25 zone Statement Grammar)
+endobj
+457 0 obj
+<< /S /GoTo /D (subsection.6.2.26) >>
+endobj
+460 0 obj
+(6.2.26 zone Statement Definition and Usage)
+endobj
+461 0 obj
+<< /S /GoTo /D (subsubsection.6.2.26.1) >>
+endobj
+464 0 obj
+(6.2.26.1 Zone Types)
+endobj
+465 0 obj
+<< /S /GoTo /D (subsubsection.6.2.26.2) >>
+endobj
+468 0 obj
+(6.2.26.2 Class)
+endobj
+469 0 obj
+<< /S /GoTo /D (subsubsection.6.2.26.3) >>
+endobj
+472 0 obj
+(6.2.26.3 Zone Options)
+endobj
+473 0 obj
+<< /S /GoTo /D (subsubsection.6.2.26.4) >>
+endobj
+476 0 obj
+(6.2.26.4 Dynamic Update Policies)
+endobj
+477 0 obj
+<< /S /GoTo /D (section.6.3) >>
+endobj
+480 0 obj
+(6.3 Zone File)
+endobj
+481 0 obj
+<< /S /GoTo /D (subsection.6.3.1) >>
+endobj
+484 0 obj
+(6.3.1 Types of Resource Records and When to Use Them)
+endobj
+485 0 obj
+<< /S /GoTo /D (subsubsection.6.3.1.1) >>
+endobj
+488 0 obj
+(6.3.1.1 Resource Records)
+endobj
+489 0 obj
+<< /S /GoTo /D (subsubsection.6.3.1.2) >>
+endobj
+492 0 obj
+(6.3.1.2 Textual expression of RRs)
+endobj
+493 0 obj
+<< /S /GoTo /D (subsection.6.3.2) >>
+endobj
+496 0 obj
+(6.3.2 Discussion of MX Records)
+endobj
+497 0 obj
+<< /S /GoTo /D (subsection.6.3.3) >>
+endobj
+500 0 obj
+(6.3.3 Setting TTLs)
+endobj
+501 0 obj
+<< /S /GoTo /D (subsection.6.3.4) >>
+endobj
+504 0 obj
+(6.3.4 Inverse Mapping in IPv4)
+endobj
+505 0 obj
+<< /S /GoTo /D (subsection.6.3.5) >>
+endobj
+508 0 obj
+(6.3.5 Other Zone File Directives)
+endobj
+509 0 obj
+<< /S /GoTo /D (subsubsection.6.3.5.1) >>
+endobj
+512 0 obj
+(6.3.5.1 The \044ORIGIN Directive)
+endobj
+513 0 obj
+<< /S /GoTo /D (subsubsection.6.3.5.2) >>
+endobj
+516 0 obj
+(6.3.5.2 The \044INCLUDE Directive)
+endobj
+517 0 obj
+<< /S /GoTo /D (subsubsection.6.3.5.3) >>
+endobj
+520 0 obj
+(6.3.5.3 The \044TTL Directive)
+endobj
+521 0 obj
+<< /S /GoTo /D (subsection.6.3.6) >>
+endobj
+524 0 obj
+(6.3.6 BIND Master File Extension: the \044GENERATE Directive)
+endobj
+525 0 obj
+<< /S /GoTo /D (subsection.6.3.7) >>
+endobj
+528 0 obj
+(6.3.7 Additional File Formats)
+endobj
+529 0 obj
+<< /S /GoTo /D (section.6.4) >>
+endobj
+532 0 obj
+(6.4 BIND9 Statistics)
+endobj
+533 0 obj
+<< /S /GoTo /D (subsubsection.6.4.0.1) >>
+endobj
+536 0 obj
+(6.4.0.1 The Statistics File)
+endobj
+537 0 obj
+<< /S /GoTo /D (subsection.6.4.1) >>
+endobj
+540 0 obj
+(6.4.1 Statistics Counters)
+endobj
+541 0 obj
+<< /S /GoTo /D (subsubsection.6.4.1.1) >>
+endobj
+544 0 obj
+(6.4.1.1 Name Server Statistics Counters)
+endobj
+545 0 obj
+<< /S /GoTo /D (subsubsection.6.4.1.2) >>
+endobj
+548 0 obj
+(6.4.1.2 Zone Maintenance Statistics Counters)
+endobj
+549 0 obj
+<< /S /GoTo /D (subsubsection.6.4.1.3) >>
+endobj
+552 0 obj
+(6.4.1.3 Resolver Statistics Counters)
+endobj
+553 0 obj
+<< /S /GoTo /D (subsubsection.6.4.1.4) >>
+endobj
+556 0 obj
+(6.4.1.4 Compatibility with BIND 8 Counters)
+endobj
+557 0 obj
+<< /S /GoTo /D (chapter.7) >>
+endobj
+560 0 obj
+(7 BIND 9 Security Considerations)
+endobj
+561 0 obj
+<< /S /GoTo /D (section.7.1) >>
+endobj
+564 0 obj
+(7.1 Access Control Lists)
+endobj
+565 0 obj
+<< /S /GoTo /D (section.7.2) >>
+endobj
+568 0 obj
+(7.2 Chroot and Setuid)
+endobj
+569 0 obj
+<< /S /GoTo /D (subsection.7.2.1) >>
+endobj
+572 0 obj
+(7.2.1 The chroot Environment)
+endobj
+573 0 obj
+<< /S /GoTo /D (subsection.7.2.2) >>
+endobj
+576 0 obj
+(7.2.2 Using the setuid Function)
+endobj
+577 0 obj
+<< /S /GoTo /D (section.7.3) >>
+endobj
+580 0 obj
+(7.3 Dynamic Update Security)
+endobj
+581 0 obj
+<< /S /GoTo /D (chapter.8) >>
+endobj
+584 0 obj
+(8 Troubleshooting)
+endobj
+585 0 obj
+<< /S /GoTo /D (section.8.1) >>
+endobj
+588 0 obj
+(8.1 Common Problems)
+endobj
+589 0 obj
+<< /S /GoTo /D (subsection.8.1.1) >>
+endobj
+592 0 obj
+(8.1.1 It's not working; how can I figure out what's wrong?)
+endobj
+593 0 obj
+<< /S /GoTo /D (section.8.2) >>
+endobj
+596 0 obj
+(8.2 Incrementing and Changing the Serial Number)
+endobj
+597 0 obj
+<< /S /GoTo /D (section.8.3) >>
+endobj
+600 0 obj
+(8.3 Where Can I Get Help?)
+endobj
+601 0 obj
+<< /S /GoTo /D (appendix.A) >>
+endobj
+604 0 obj
+(A Appendices)
+endobj
+605 0 obj
+<< /S /GoTo /D (section.A.1) >>
+endobj
+608 0 obj
+(A.1 Acknowledgments)
+endobj
+609 0 obj
+<< /S /GoTo /D (subsection.A.1.1) >>
+endobj
+612 0 obj
+(A.1.1 A Brief History of the DNS and BIND)
+endobj
+613 0 obj
+<< /S /GoTo /D (section.A.2) >>
+endobj
+616 0 obj
+(A.2 General DNS Reference Information)
+endobj
+617 0 obj
+<< /S /GoTo /D (subsection.A.2.1) >>
+endobj
+620 0 obj
+(A.2.1 IPv6 addresses \(AAAA\))
+endobj
+621 0 obj
+<< /S /GoTo /D (section.A.3) >>
+endobj
+624 0 obj
+(A.3 Bibliography \(and Suggested Reading\))
+endobj
+625 0 obj
+<< /S /GoTo /D (subsection.A.3.1) >>
+endobj
+628 0 obj
+(A.3.1 Request for Comments \(RFCs\))
+endobj
+629 0 obj
+<< /S /GoTo /D (subsection.A.3.2) >>
+endobj
+632 0 obj
+(A.3.2 Internet Drafts)
+endobj
+633 0 obj
+<< /S /GoTo /D (subsection.A.3.3) >>
+endobj
+636 0 obj
+(A.3.3 Other Documents About BIND)
+endobj
+637 0 obj
+<< /S /GoTo /D (appendix.B) >>
+endobj
+640 0 obj
+(B Manual pages)
+endobj
+641 0 obj
+<< /S /GoTo /D (section.B.1) >>
+endobj
+644 0 obj
+(B.1 dig)
+endobj
+645 0 obj
+<< /S /GoTo /D (section.B.2) >>
+endobj
+648 0 obj
+(B.2 host)
+endobj
+649 0 obj
+<< /S /GoTo /D (section.B.3) >>
+endobj
+652 0 obj
+(B.3 dnssec-dsfromkey)
+endobj
+653 0 obj
+<< /S /GoTo /D (section.B.4) >>
+endobj
+656 0 obj
+(B.4 dnssec-keyfromlabel)
+endobj
+657 0 obj
+<< /S /GoTo /D (section.B.5) >>
+endobj
+660 0 obj
+(B.5 dnssec-keygen)
+endobj
+661 0 obj
+<< /S /GoTo /D (section.B.6) >>
+endobj
+664 0 obj
+(B.6 dnssec-signzone)
+endobj
+665 0 obj
+<< /S /GoTo /D (section.B.7) >>
+endobj
+668 0 obj
+(B.7 named-checkconf)
+endobj
+669 0 obj
+<< /S /GoTo /D (section.B.8) >>
+endobj
+672 0 obj
+(B.8 named-checkzone)
+endobj
+673 0 obj
+<< /S /GoTo /D (section.B.9) >>
+endobj
+676 0 obj
+(B.9 named)
+endobj
+677 0 obj
+<< /S /GoTo /D (section.B.10) >>
+endobj
+680 0 obj
+(B.10 nsupdate)
+endobj
+681 0 obj
+<< /S /GoTo /D (section.B.11) >>
+endobj
+684 0 obj
+(B.11 rndc)
+endobj
+685 0 obj
+<< /S /GoTo /D (section.B.12) >>
+endobj
+688 0 obj
+(B.12 rndc.conf)
+endobj
+689 0 obj
+<< /S /GoTo /D (section.B.13) >>
+endobj
+692 0 obj
+(B.13 rndc-confgen)
+endobj
+693 0 obj
+<< /S /GoTo /D [694 0 R /FitH ] >>
+endobj
+697 0 obj <<
+/Length 236
+/Filter /FlateDecode
+>>
+stream
+xÚÁJA †ïó9¶‡M'™d2s´T¥‚Beoâai·Rp·t­ïïÔÕ*êArÉÿ‘ü /A}È–ՓºsžŠvíèƒ ¨B)þP+!ÃlQ¡bJÕÂwìNì1úÈP©)&>áóÚÍ®˜€-A½bEM¦pæêÍÃd¾¼[L+V?ÉcºØt»~÷ršã~[÷í¶Ú~ÝNë a¤(±ø˘’å÷9·MÿÚ<Ÿ
+endobj
+694 0 obj <<
+/Type /Page
+/Contents 697 0 R
+/Resources 696 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 703 0 R
+>> endobj
+695 0 obj <<
+/Type /XObject
+/Subtype /Form
+/FormType 1
+/PTEX.FileName (./isc-logo.pdf)
+/PTEX.PageNumber 1
+/PTEX.InfoDict 704 0 R
+/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000]
+/BBox [0.00000000 0.00000000 255.00000000 149.00000000]
+/Resources <<
+/ProcSet [ /PDF /Text ]
+/ColorSpace <<
+/R15 705 0 R
+/R9 706 0 R
+/R11 707 0 R
+/R13 708 0 R
+>>/ExtGState <<
+/R17 709 0 R
+/R8 710 0 R
+>>/Font << /R19 711 0 R >>
+>>
+/Length 712 0 R
+/Filter /FlateDecode
+>>
+stream
+xœu˜;“d9…ýû+®Ùe´R©— lG`XËkz#†10gwÙ~6ßÉ[53}+ˆ}tI%åóäÉT½ßs*{Ö?·¿××í'¿ûŸ?lï·¼Ÿ#5Û_7}÷n³æ3õùæóýÌ»íwû7\^ûõÃVö×oøÿ_·ÒvþmÕSéœmqöÚ¾æh)ŸÏŽ™,ײ—Zjj•ÅVÊ•ëµÍÔÆn¹§±†Ö5͵[+i6}Ÿk’¨Í–§ºØ±ÖRöÝVIƒ e´Ä¶yKfZWTp¾ÜÏç9ùÀ–ÆŒõÒý>R_­êÂJsJƒ¥.ŸËÊiôÝ×\
+û”_g'®Û_6´§ÖØËÍ“[8føƒ”œKj“È4­¹¯5Ã#6ÆJ²4·œª+ÚøاkÇä~¤ž19wR7ñm¦U%s˜,ÃT|
+Û2Æ‚ŒjUçq¥K"ηbøR<™¬¨™ãŸ¹×²RU| Ñ$ÞÕZ*Š–ŒCõu«|ˆhL$,I˜–¼`¥Y|ÃNżŠLó’#pÕ‹BÖŽj9-- 9@‘ €DÌ©….¶áJ{N]Á©¥Z*zÃ3…?´T®²$À“%ÁXF°Zê%.ä’@ŽO­—€!$t\'<Ž¶*W
+èj˵ãB;Žþ"%«ê;¥+ßÚ)Éú¾Œ¤IJ5yÝGN>³ʧ*=5Dt'ŸtˇÀùiQ{
+ ˜‚ÚIq%˜3vH­wÁKAįr‹þq n[Uz¯!*â)ôàKG°€ÝgG-dL#¹X0¹Â“@ñ´×£^ëµ½æHÕÊ_7S41Ã,ëÀO%ê*\ç/1v¢\¨Î¡¨êG´P:‘Sœ¸1ÀÞ£q‹uc¤,¯J¶”e— '‚; F/É&N(AWÖšNfãÀŠq‚ì’htËØ“ªØOàÙ‰GÎ4óHD'ª:SÙ#Oœ™äD4Ltæª3—=Ý™pÂSè¬F$_)^"åÛ•.ªd­Ôd´ÁJŒÓ¤¨,à}‹F:IòP<Á:‚é¡û½¶H­JŒŒÀvÎ9±”8G
+%S}8\Ž»Ä{!•pŸj yî8NíÖL-»Ä¼1_yk¦“ˆÔøèus‘#¸W™˜ÁAŹ{0º¤Œ4±à8pª0ŠÚž]#H ªiÓºhS”28Ú*7»Å'¤«ÎwMpíD¦9d=‹rêÀ Öd ðlÎmF1Û\ÓjÍ J$¾›ƒlHO†¯,x!Fàqê*i!ߪ ‰ ž£‘\·î"o6,âM(¨$‡^êP^Å>˜³ ÔV¬ˆ¦#Z†ª¼§?Áj¹“LÃ¥R»š¨¦VÅo€Ž –eõT¥ Ø€ùU¢ÙÜ* „2ÊNvÊ@ÈËY#E?°+êEn£±¦h“ÊFØläƒbY3Âc0CEW'ñÖÆ4€»Öm"ŒÙ©˜94A¬#—ª Áõ¢ÙëN)ÅZþÅÖ…µˆ‘ç#µxì‡Ð:Å ÑqYŠ¢ŽÞ\U¢ÜÆÕ²hb \´ÑP£’šð¢>Ô9Ž¨Ñ¸ˆùUm!‰§¢Zh!ú‹~(Ât~¿ÙA,«×>*"œD0QEuÑ|Îóî`‰ö™%„U™&2WjDó5EŠ)€®ä
+«SÕ0Ý4jÆ0çU6Ñœ5Õ”ê0*ÊBóî" gܲ¥–ÃÄHgæ:2®xļô¨ ¤èCúð¨˜*#{ëÖâsôÎ
+¯Éæ’×M¼ 1ÖQQ ½»î0@yP,£§"cf6‹ÃH%aDšjÑ÷ÄPjëš(²f§ Ø®ì·q,fÙLhgÌŒ#Çd±0xDÉYWíû¾0yš’*á_àºFî®.˜tƨj²ùKÐõàº5£7¬bi«¸3׽Ŕ
+óÔPĮ́Yu¢e¢a5エ0kÓ,¤×äþ¤V¡Ò(*Gãë0[;=‚Ãát çX3pD¦iÜ'ÃëÑ+ aqz JC "Ê1ô(Œ
+FÑÞIca­Ç0Ú) ¹A¿+ÇÀº ¸|-Tuùa>‚s:½¯•~K“ÒÞV׋„OÒAŠI… ɪÁr2Q“°Ø¨Á>.z
+ÏÆ狼eÇNdæÌdï"gK2cëÉ—GoOá8GëÏϦ:B Àht[
+endobj
+704 0 obj
+<<
+/Producer (AFPL Ghostscript 8.51)
+/CreationDate (D:20050606145621)
+/ModDate (D:20050606145621)
+/Title (Alternate-ISC-logo-v2.ai)
+/Creator (Adobe Illustrator\(R\) 11)
+/Author (Douglas E. Appelt)
+>>
+endobj
+705 0 obj
+[/Separation/PANTONE#201805#20C/DeviceCMYK 713 0 R]
+endobj
+706 0 obj
+[/Separation/PANTONE#207506#20C/DeviceCMYK 714 0 R]
+endobj
+707 0 obj
+[/Separation/PANTONE#20301#20C/DeviceCMYK 715 0 R]
+endobj
+708 0 obj
+[/Separation/PANTONE#20871#20C/DeviceCMYK 716 0 R]
+endobj
+709 0 obj
+<<
+/Type /ExtGState
+/SA true
+>>
+endobj
+710 0 obj
+<<
+/Type /ExtGState
+/OPM 1
+>>
+endobj
+711 0 obj
+<<
+/BaseFont /NVXWCK#2BTrajanPro-Bold
+/FontDescriptor 717 0 R
+/Type /Font
+/FirstChar 67
+/LastChar 136
+/Widths [ 800 0 0 0 0 0 452 0 0 0 0 0 0 0 0 0 582 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 841 633 576 686 590 540 923 827 407 760]
+/Encoding 718 0 R
+/Subtype /Type1
+>>
+endobj
+712 0 obj
+2362
+endobj
+713 0 obj
+<<
+/Filter /FlateDecode
+/FunctionType 4
+/Domain [ 0 1]
+/Range [ 0 1 0 1 0 1 0 1]
+/Length 39
+>>
+stream
+xœ«N)-P0PÈ-ÍQH­HÎP
+endobj
+714 0 obj
+<<
+/Filter /FlateDecode
+/FunctionType 4
+/Domain [ 0 1]
+/Range [ 0 1 0 1 0 1 0 1]
+/Length 36
+>>
+stream
+xœ«N)-P0PÈ-ÍQH­HÎP
+endobj
+715 0 obj
+<<
+/Filter /FlateDecode
+/FunctionType 4
+/Domain [ 0 1]
+/Range [ 0 1 0 1 0 1 0 1]
+/Length 40
+>>
+stream
+xœ«N)-P0TÈ-ÍQH­HÎP
+endobj
+716 0 obj
+<<
+/Filter /FlateDecode
+/FunctionType 4
+/Domain [ 0 1]
+/Range [ 0 1 0 1 0 1 0 1]
+/Length 50
+>>
+stream
+xœ«N)-P0Ð365³TÈ-ÍQH­HÎP€Š™X ‹™›#Ä ô -,ŒÀüZ
+endobj
+717 0 obj
+<<
+/Type /FontDescriptor
+/FontName /NVXWCK#2BTrajanPro-Bold
+/FontBBox [ -45 -17 923 767]
+/Flags 4
+/Ascent 767
+/CapHeight 767
+/Descent -17
+/ItalicAngle 0
+/StemV 138
+/MissingWidth 500
+/CharSet (/Msmall/C/Ysmall/Nsmall/Osmall/Esmall/Rsmall/S/Ssmall/I/Tsmall/Ismall/Usmall)
+/FontFile3 719 0 R
+>>
+endobj
+718 0 obj
+<<
+/Type /Encoding
+/BaseEncoding /WinAnsiEncoding
+/Differences [ 127/Nsmall/Tsmall/Esmall/Rsmall/Ysmall/Ssmall/Msmall/Osmall/Ismall/Usmall]
+>>
+endobj
+719 0 obj
+<<
+/Filter /FlateDecode
+/Subtype /Type1C
+/Length 2657
+>>
+stream
+xœ}VkpUž!!i0dHÈ:=«°î"ŠÏ*QpYWÊD@p• ‘$$ç$!a2ïžé×éîéǼ’ÌäÍC Ãû)Á]^º+–B-®k)ZˆËµîÄf‹½´J«¬ýÓÕ÷ÜÛçÜïœï|§Í¦Ì1&³Ù<q™£d]IM‘£ö¾§j«J ÓŒty•óûÙ#ÚØ;M¦7Õ “9™§~•cŒ†oGÛ&¢ŽIÆÁã jë6:*×V4ÚzàìóKk_+³/ÝØÐXVÝ`/¬YS먫u”4–•ÞoŸ_Ue_bm°/)k(slÀÆ[¡í• ö²ÊÆŠ2‡½Äî([[‰?w”•Ú%¥eÕ%ŽõöZcç'ËòÿÉ^YcǾì/ÖT«¥ØØ`/©)½ÔŽFYSÛTÓè¨,k¸ßd2MX°´0Dyi ècX“iºéÓL³Í<ÓLšíæ)æ»ÍÓÍ3ÌÓÌ¿1åâ|™^0!óæ1 3ò2­™h쬞ì=ÄêqóÇ}>þdš…Ãhëôõa3NO?œ™iv¤è›…$}ت?‰´±èË,Ý®³"cqC;‘µjô=©ãuVú¨ÕxÓUîÈçðÈœCæè×éÎþŒt§Óz>Tww$Õ°,'£ÛãŸBœÐ85HqL+kc6zjœ-kŠ_ô?„>M/DãQàZçÕ çɽ»Oö|
+_ÀźŠþúD…PE¸EJ‹ˆZ»`»øâ€8(ÅA…‘}Bµ´>R&+åáE ÿf­YPxïÃôñð Ìܤg~ý(qe.Ê®Fw‘›¾ä<8ò§ý“?ßúzñÛW»§Z>CšÓjùè¼9üÆûzÞƒa¸ºú=}•Úî¼ÇN7Â~â}CØ,ÎÂÖêö–îz¹
+„W
+©š¤õ\ o…„ TZ
+ˆõjIt!†CΞ«y|×ÓhÌ£¤åËýk?^Ø^ /ç/õùmþ ÉF'™nH P¬ÏÅÛøVf1,ƒ&‰î–ÏZ†ö‡ rÓ/±©‘Ò”=†&eàÇn+Ì„¹t [r63Î˹€ð2,TÙ¹NK½°N³çàpÎÝ1MReZò¹šDÑMV‡ƒ)v33—àþ˜ hlßµäf9.jBˆ¨"j
+%zÈ2(bPÏIe†§VŠ Q
+'x6FöÐQ§X)®‡ZÐg¹ßÏÆwÌk6'¾¿+ãóËV¦–ªl`Ý\‚@h†¡T.Bn·¤$tÀnv§á0¡‰Z8¦(J\¤Kò*x¯Mˆ‰ío¡Oò¤¬­EGíjk´áïú”îÒ¶ú¨3Qµ®Ýè…ô$¼èF¦ÔÀùi.?Ä1,0@ËL7?È¡Û™ Q <$Q>· :È:ꥎ=‘îÉcSþH( ‚A·î»Ñ˜§ûÒ5ÞÞP8
+n¨`×rŽ`ëF†â|¼?C3A•‹“pJê>8Åž0`ÅUI Ó²ßÛ"à$Ö‡©®ŸÛƒÐF¼› [¸M‰m;Ðd´jëöÎ^MëŒ$”Žpç] +rHô“Nxkz¨k `(¨ñG¶³a|oð1®@‹§Þ®/ô5»úôlôJë¦`œ‰‚
+ªVŶ° 
+-R¶5ðöU…¢Ëðå q¡Âª±v:#“TsOÕ¶U(G_¬xâm#¹#—ÙTpÃȤd{ód4åÌMóqŸé¦ižÏ4Õ2€3¿Ú*e%]_Nÿj6a©úâ!4æ®/Eñ@;ªªu’Ñô€pPmïSóc’
+.9,«”à%WÃ:Î-°R,6îâ ðAZbbñn d7¥¹„‘¹yL–'®C9‹O–¤~º]ÏC¾˜«Ý›ða2…¼N’º!ðóÙÆÆP¾—m5jA…šÒø8¹SLÃ4ÚÞ­…&bö‡ýn§ »H§âëâÎa„ïº÷§ßßg>ˆ¦¤+ÐÔŒô,·5£»Ð}hZ¡ÛÐDÝ¡wÍЋôú½ßè Q„ܱߪ?~²¡¨eý«ø­Ûk‘¹é ô¡•)eúÇ~Ô|À•Tqî¦c1[Ö5ÕÒæï¬Õ2ÇóàYf-ë 1‹Ë_|åç=>–fH|
+&–ê„n>ÚÝ)D 6Á
+x¸ \3§gA34–ITž-‹R8õ-ǵÛö2ªWuÉ~Á!"(0Š*FÂ͢ùĨ¸SˆˆoÊQPˆ0¦šåiFäݸVN^_!Ô‚–bž "-Qy$ÑÎsªm ¥Ä¡@·âJ=Ŧ¿íÝëL ÍDËQÆTË?GúÓlRÎ$F*4’ƒð6–š\`Œª Ñ“Œôöd]˜é`û™ü9¸DijeI Û.q
+ȼLçÇ<;— *X³«¥×ÛGâ_Y1ETïƒ4ˆÒ-U…_>´üØ¢æ}õï÷v¼ §ádù#¹rÛŸå¥@ÔÁ\5l…hð<8Ús·
+»O·Øèv61Bá5*È<6ÞÍ,‡bh‘˜¶ž\Î]Çé#¹#ØÔÍ1Oúñ°Ï¤5oÂ]цÆß4}h˜î0$å,6ü¼”A,¯?/å;Rôcy6Ò½UJ¿§Y½X^é¶ÙÉŸ‡‹º–2¸K|o½Ø”/Ȩ/ƒ( Â2Ð#žNMKðrˆ rœÛf9ËyZ¸Ú}$«Ö õ–©)  h`iÎGàAç÷´€H+Šˆ…Õ&*áX$žèìVŽhª”—›¾÷‡A1Ý£¤œÏ0‰÷—Hi éƒw~I(Áö2;à]¸L ™x4[¡OÜ,¾®ÆûÂQQ°”FdQ“ƒ¢¬„%\î¢Åâ:Ó;ÈÑ”ÌEb1ž’¡ˆÿ§=$¸¥?Iš¿CÐõ3¾C=VÐ'>·¯ôÌÒ+Ü~8 ç#;úÁ_£×á*qň+ô 8®‚ãÆpêŒ_YR”¾d%a ç¡H\eÄõãDf£Ñ¨­ŽR[kφG¸ù/WT®ò•A5”H¥ÛVoo8hnû)¼ÞÃDn…ñëqÌzfåhý&þcQbµXÇß‚çLŽúõ;{²Ðñðué¿ÊÛÙ†-©[SÄ-Û¼ÔyubÜñhüm´œ4^Ë™ ääšLÿQ‹¡endstream
+endobj
+698 0 obj <<
+/D [694 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+699 0 obj <<
+/D [694 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+696 0 obj <<
+/Font << /F21 702 0 R >>
+/XObject << /Im1 695 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+722 0 obj <<
+/Length 999
+/Filter /FlateDecode
+>>
+stream
+xÚµV]“¢:}÷Wð¨UC6|å‘AT¶\ÀÚÚÝGq†ªQ¼‚;5ÿþ6$Qï¼lÝò!ô±ûôI'„h~D3-dqÊ5›ÈÄÄÔÖ»Ö^À7‰ÁšŽãNëügðó7Ö6
+;IgÒÎdwÕ-·õûê8"Î0¿–]ëgaÄ©åh6eÀŒÏäS`ý}«že"ŽÒÅlÊYäÇ]QUE¹œêRŒ§*—õ¬AÞ!d(ç»rSl{+«ýF›¢ªÅó©–Ö¯…ì¦ê¦ømyTÿþÆát<”•t¿õ«°®Y)ORÌm.q Ùu8øŒ€„ nš´-í5ùžeü—ã
+6d#IZgù§ØäÅvU+KF_=—òNÑeít_ÖÅ:¿ª¿«÷p%k~8ä+YT!ý«··¶Âؤæ$\V¹‹¼j›sÄŒæR"6âŒÚ-$›ù²ÍâIö4âtè&r%HŸHâïÁØ‹YsrÝT!š™°Ýh¬=aŒÁ
+Ý`.Án
+CfIÜ( |é|
+²™°ê&cq$á¢e¤_RÖ¨ h6Sï¼p9¢éUò`¾UË=&ñDŒs?ñfàÙÆÐ}  ûÑÚ°³7[±#-»IE~š"ÅAŒ‘äë÷!ž <ë)½%õ0pCiOâDe•éÓ…ïnø 4N|¯å¨nÛèf B´ @029ç}=½8JýoK AeLwîNÏr\çïyŸfn“(Kc¨-Q˜.Ãvõ¬þ$‰ç²¶8ítnXa÷âÕ/S_•'·{ÐçM b§Š‡œôewÕèeAõwÊη'SäOÃ`êGžßÏ·‘ÛËÂ@Ô!¤¿å¢!“³¡àx™^攑Ý$HÏZÄˬO%¾¢ Ô"ÿ‚rw4ÎgêmmsøáÐqá'Ð<s·«gòÙ©¹ù’¨73Qó4ºûSùþú¦«lºa#æ8ôþ—ˆ:ðŲٙTû]½!}N™Eï0ÿýžfendstream
+endobj
+721 0 obj <<
+/Type /Page
+/Contents 722 0 R
+/Resources 720 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 703 0 R
+>> endobj
+723 0 obj <<
+/D [721 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+720 0 obj <<
+/Font << /F23 726 0 R /F14 729 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+732 0 obj <<
+/Length 2891
+/Filter /FlateDecode
+>>
+stream
+xÚíMsÛȆïþ¼E:p2ß
+–˜•U~}Àô )ÚB¼k¯E–¢$6ºÝž™%fÜý³Ô0®2=K2Í f¶X½à³k÷»7/„6Š­”û&òÛ¹Q)3©Lfs|‘——/þøZŠ™Ô,I1»ü4ø2’I©²ÙåÕ?ŽN«²)Êf}üÏË?uˬ´íûùln%Ó©J»wŠã¹àœ—M]]mͲ*[«g—!£³\è™M3–h.ÚPú_Ö׳þŇ­ØýûçØ
+W±ïëå*¯úoÞæ®x­]Δܫ!$j2È¢
+¤§àâ6¿<™îÏLñ9. u“¹@†X‚‹H¤ó c™5™B\(à¢)òÛææ–g‡"dm2ÈB«B  ƒB‚t>ÔZ3cÅPC_Cœæ‹›ey=Z=¨Tì]±ùX™2+¹’øDBÀnŽ #„ì\¿‰#‰ƒB„ô>ŒJ2måPS˜PS¼®êÿäÝûUÇŠþN0_aB ÚAö&³ )6¶Ô!؈ÄA±Az†É™²z¨4¬>bë ´“þvsÛ,ïný[>T·íò7Sö™®=‚X®É0 C
+†-9"qP0ìxLJÇpî­³„%ÊMh­séO³_ž¿{åE.ÖÕ¦^€äÅ¿7˺XÁÙx4]ኟ9åi‘Sîëvi£i—#Ò³ë5v¸ ]ž¬Rý .Ã1÷~üôã¨OOÿºMQ÷¢OÓ<U‡Íòþ
+9žzaCâþÚÒ'é=
+5ž't9*?;^£·w÷O“>?Cßk¾
+ ãGyiKnSñSî,Hîä; Rw"&Eé=l»¨Œ3-¸tBûщç¦ß¼WåíC|×åÝf{EDÈÙT"°!AÄ–&±8"hïIÊ”û.F'~Çm«'€Ãhõlú™ƒ8žÉâ#CJ|œ~JüH”ø¤w˜H\éΤ𜨰1ðç*÷¥ØËü6/])–Jsè-úR˜ ß“aB†LXO¡ÇaŠÄAÁDz0Í„0P•(r™çkü®2ÑÏç‘œßh‚ÌNÆRØ`å(l"qPØÞ‡ HKÆE%‰
+%Éåq&ªêÖŸ
+¥ï±D™*ÆÓ¬ŸÚ´ßH<¹ºwkØl»*òfSã=ábOÝBÄÄâVb¼_ŽÈÌ®×X±.βLôC¼[ˆïªfùÉ­ïݺGÏ“|ëeacê=ˆ ‰{pKlŠ°Hi¤÷@šIÝ°®<h°Åðê¡ÌWPØ}¼»Ê7§‰9@ôCäó<™¡ÁŽB©H´å:”R[–d:‚†õ!,øþUmjWÀƒÔ\¶§ 雧qé 2¤ÈÁòQèDâ Ø!½‡ÁGif3ë €°'u^.†6
+2¤PÁjÉñ&ÔX*¤÷€ŠoL–BE]*w·Ë—Š©=ÔB¿åp2Lf RŒa™)Æ"qPŒ‘Þ‡¹LpæÒ—da.;ûÞ¯3×þ¬h6wm‰¤öHßd8!–‡‚#é ‘¥Lsu4G]^œ¿9ž»7Vb_mS$H1•3lHp¶%µ?ôÅApF{ƒH-S\
+øƒÿÝÙ/ËuS”탙‰0ß™æ•Éš#CJsœuJóH”æ¤÷AsiX
+M…­æ:h¾nêãô¨ýèá·oðÐkƒh—#öùlk…lMfR,`5("qP,Þ„b‰Ðø˜Ž~]í»=Ãמ,Åzž%húg°º
+ÁîGÓäm2ƒÅREŽ7XD‚ ˆ \@pÁ,tûµDÀ'/œÕ½ÊýØø@Á_™'Hûd !E–•B*Åéö®ÒŒ‘@aaëêdz¿µÍ:ê°uõÕ¶HA‰©”!;2¬3ÁX$1Ò5–$LCK¢[ÎÂéÌù›ödŽ÷ÇršgľڀŠL% Ù¤a½ Ò"AP‡…r=|Ê?SRxÐRèWywqqvê:ûñÌ7ƒÊ'*SƒVZâï<Ž`¨ðwæ2ciìÈÛÕ÷ Ε[~©‘&Å3çë™SÿÀóøóp%ðö?ž­®Bendstream
+endobj
+731 0 obj <<
+/Type /Page
+/Contents 732 0 R
+/Resources 730 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 703 0 R
+/Annots [ 735 0 R 736 0 R 737 0 R 738 0 R 739 0 R 740 0 R 741 0 R 742 0 R 743 0 R 744 0 R 745 0 R 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 ]
+>> endobj
+735 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [532.6051 688.709 539.579 697.2967]
+/Subtype /Link
+/A << /S /GoTo /D (chapter.1) >>
+>> endobj
+736 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [532.6051 676.5858 539.579 685.4425]
+/Subtype /Link
+/A << /S /GoTo /D (section.1.1) >>
+>> endobj
+737 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [532.6051 664.4876 539.579 673.3442]
+/Subtype /Link
+/A << /S /GoTo /D (section.1.2) >>
+>> endobj
+738 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [532.6051 652.3894 539.579 661.246]
+/Subtype /Link
+/A << /S /GoTo /D (section.1.3) >>
+>> endobj
+739 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [532.6051 640.1914 539.579 649.1477]
+/Subtype /Link
+/A << /S /GoTo /D (section.1.4) >>
+>> endobj
+740 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [532.6051 628.0932 539.579 637.0495]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.1.4.1) >>
+>> endobj
+741 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [532.6051 615.995 539.579 624.9512]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.1.4.2) >>
+>> endobj
+742 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [532.6051 603.8967 539.579 612.853]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.1.4.3) >>
+>> endobj
+743 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
+744 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
+745 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
+746 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
+747 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 543.4055 539.579 552.5112]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.1.4.5) >>
+>> endobj
+748 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 531.3072 539.579 540.413]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.1.4.5.1) >>
+>> endobj
+749 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 519.209 539.579 528.3147]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.1.4.6) >>
+>> endobj
+750 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 496.7003 539.579 505.4125]
+/Subtype /Link
+/A << /S /GoTo /D (chapter.2) >>
+>> endobj
+751 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 484.5772 539.579 493.5832]
+/Subtype /Link
+/A << /S /GoTo /D (section.2.1) >>
+>> endobj
+752 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 472.4789 539.579 481.485]
+/Subtype /Link
+/A << /S /GoTo /D (section.2.2) >>
+>> endobj
+753 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 460.3806 539.579 469.3867]
+/Subtype /Link
+/A << /S /GoTo /D (section.2.3) >>
+>> endobj
+754 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 448.2824 539.579 457.2885]
+/Subtype /Link
+/A << /S /GoTo /D (section.2.4) >>
+>> endobj
+755 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 436.1841 539.579 445.1902]
+/Subtype /Link
+/A << /S /GoTo /D (section.2.5) >>
+>> endobj
+756 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 413.4314 539.579 422.288]
+/Subtype /Link
+/A << /S /GoTo /D (chapter.3) >>
+>> endobj
+757 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 401.353 539.579 410.4588]
+/Subtype /Link
+/A << /S /GoTo /D (section.3.1) >>
+>> endobj
+758 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 389.2548 539.579 398.3605]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.3.1.1) >>
+>> endobj
+759 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 377.1565 539.579 386.2623]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.3.1.2) >>
+>> endobj
+760 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 365.1579 539.579 374.164]
+/Subtype /Link
+/A << /S /GoTo /D (section.3.2) >>
+>> endobj
+761 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 353.0597 539.579 362.0658]
+/Subtype /Link
+/A << /S /GoTo /D (section.3.3) >>
+>> endobj
+762 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 340.9614 539.579 349.9675]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.3.3.1) >>
+>> endobj
+763 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 328.7635 539.579 337.8693]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.3.3.1.1) >>
+>> endobj
+764 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 316.6653 539.579 325.771]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.3.3.1.2) >>
+>> endobj
+765 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
+766 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
+767 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
+768 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
+769 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
+770 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 233.5408 539.579 242.4971]
+/Subtype /Link
+/A << /S /GoTo /D (section.4.3) >>
+>> endobj
+771 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 221.4426 539.579 230.3988]
+/Subtype /Link
+/A << /S /GoTo /D (section.4.4) >>
+>> endobj
+772 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 209.3443 539.579 218.3006]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.4.4.1) >>
+>> endobj
+773 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 197.2461 539.579 206.2023]
+/Subtype /Link
+/A << /S /GoTo /D (section.4.5) >>
+>> endobj
+774 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
+775 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
+776 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 161.051 539.579 170.0571]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.4.5.1.2) >>
+>> endobj
+777 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 148.9527 539.579 157.9588]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.4.5.2) >>
+>> endobj
+778 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 136.8545 539.579 145.8606]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.4.5.3) >>
+>> endobj
+779 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
+780 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 112.5583 539.579 121.5146]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.4.5.5) >>
+>> endobj
+781 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 100.4601 539.579 109.4163]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.4.5.6) >>
+>> endobj
+782 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 88.3618 539.579 97.3181]
+/Subtype /Link
+/A << /S /GoTo /D (section.4.6) >>
+>> endobj
+783 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 76.2636 539.579 85.2199]
+/Subtype /Link
+/A << /S /GoTo /D (section.4.7) >>
+>> endobj
+784 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) >>
+>> endobj
+733 0 obj <<
+/D [731 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+734 0 obj <<
+/D [731 0 R /XYZ 85.0394 711.9273 null]
+>> endobj
+730 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+787 0 obj <<
+/Length 3167
+/Filter /FlateDecode
+>>
+stream
+xÚí[wÛ6Çßý)ôh?‹ûå1מvw“4q_¶ÛVfJ¢W’›Í~úEZàÈØ­ÓØR{Z;1‡3žÿO ’lBý¿l¢4ÑŽ»‰q’(ÊÔd¶<£“kÿ³ïÎXÌ44…G=¿<ûËka&Ž8ÍõäòãD*E¸ÚÌj-›\^ý|þâí›ËWo.?\ürùÃÙ«ËxVè™QÑžò_g?ÿB'W>€Î(ΪÉgÿJ˜s|²<“J%…³8ûpöc<!øéÎ4û›0J¸Ð<ó«p~•ö‡ŠMŒrD ÿ“ö‘Äv1eœÒóïêU½®¶óÕõÅ”+zþ×úËæbj5?'Såx|_¤sØÉîJM}ÖÐ)Ÿ{Ú¬¯'Ý7ï¡ZÁn
+ ÷ÕÚ?«×{qõsq`¬ Þ+ÒM©Ž¬ðž•óëUeû©î¾ùG³òߪOÄ Ä„¬ 1b j1™80bPÒÖEbDOÌ‹fõOJùõí:ró¡^ÿ^¯Û1†‰cEe”‘ÇbF€!ÆÔ‰›qF2q`Œ Þ óCŽöå‘ûª& ï!qêyøþÝïº'ãöæ¦Yo»?ÌWÝ×çß¿yÙ}ç gwù*
+0ÄHba¤dâÀHÙóžs%–ºSݹ{Cmêàªí¼Yr>Öëz5«Ç3N~ïñ`ã- Z°ñŒÓa™ÚóšýL1KŒéWuo³©y=s‹W‹zY¯¶~¢˜9Ö~e”ÒâO0Ä>YP2Œ“L/¨÷0i¥š©UÀe¼Qù{µ}
+EyÓ¢¢ ?õ´wP é,Fb¨@¹G%†
+êqM¤`r¢<4†I›`Ùá"Úõ/«mõï‹©pê´´zPb*KA†(©Prq  àÞ(–m ð”—u[‡VóT…ªÕUè{«ëvuþ[˜éUö˜¥b€!Æ
+0ÄPra¨dâÀPA½§áBY¢™3 –S]ù_A ©,b @©0P2q`  Þ(ReSsãA9Õ•}B–Š
+àñÉu³ÎÍt$%Úš;ðHjªBÅô– xòI:
+O.Ü{_¡„±„I *Ôá«U‹Ïë:·ÐÇ}}Š°ŒMo¸ÒG|Ý3¦»%`ˆ¡å”ã[ðrq`(¡ÞJZ{z8(aüAP:<Ó‘Ì=¡Ñ'¤µ`ˆ!eÃÉÄ!ƒzÈ(I¨e<!søJÕ²ÚlÛûãóócéôÁþJWõ
+9.æbü@ 1~2q`ü Þ?’*Jüȇâç>ý•{ÌýUÌe1'Àãj…q’‰ãõ8í„vW‡/U57­Ô›üëÏvðR;®©MÈq1?Àãjˆñ“‰ãõøa†8«AÒÅÏ}.XÉG]B.‹9†'P+9¾q"Æ ê=µâT§$¨H:¬ã<ošE]õ¢¾íé˜*áŽøjSLW1 ÀƒÊ!Çsq`0 Þ# Ü â8·†~]æu³þ\uOXÙÝv.)?ÝV0d#f¯” hˆ°1PG”\¸÷ĆõÕÂÁÖG·OkÙxy[-¦›m5ûíÎÁÄ·wËÒ×$bªŠA
+ „L¨÷‚vÄ*7¨²áÙlo…~Ñn°kÇ‹fÑÓ}Ï)qÅX
+¤Æo1ÉÅázOxHEŒÓ â¡;<~¼­Û‡íè¨ Œ9QóVL0Ĩ€º`TdâÀ¨@½'*„ F»ÓQÑ=…¶…âòÂÑóuµÚ|ÜM*”a',b⊱
+ !e? Ìuâ„+"ÍEw <¿/¶Óðš“ èWæ«»×ÄÿiVíZ¸1îQY(Öb²<¾&™‹“õž4f‚Hy§19_-o¶_Ò;³Ú«ßÐÔÃö !IÅ
+…Óú iÝg£Xêd‡) s=¾Ðœ ÓsÝŽ+Á=H‡oÖßø†À7óÙfÚßÀ–Û.çû\©ì¡'ƒøIÉ##ÆØI,eØ!l $ß • au^MeˆP
+endobj
+786 0 obj <<
+/Type /Page
+/Contents 787 0 R
+/Resources 785 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 703 0 R
+/Annots [ 792 0 R 793 0 R 794 0 R 795 0 R 796 0 R 797 0 R 798 0 R 799 0 R 800 0 R 801 0 R 802 0 R 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 ]
+>> endobj
+792 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) >>
+>> endobj
+793 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
+794 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 734.5129 511.2325 743.3696]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.4.8.3) >>
+>> endobj
+795 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
+796 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
+797 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
+798 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) >>
+>> endobj
+799 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) >>
+>> endobj
+800 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) >>
+>> endobj
+801 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 629.6343 511.2325 638.4909]
+/Subtype /Link
+/A << /S /GoTo /D (chapter.6) >>
+>> endobj
+802 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 617.6225 511.2325 626.7282]
+/Subtype /Link
+/A << /S /GoTo /D (section.6.1) >>
+>> endobj
+803 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 605.5908 511.2325 614.5471]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.1.1) >>
+>> endobj
+804 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) >>
+>> endobj
+805 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) >>
+>> endobj
+806 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) >>
+>> endobj
+807 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) >>
+>> endobj
+808 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 545.4324 511.2325 554.5382]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.1.2.2) >>
+>> endobj
+809 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 533.4007 511.2325 542.5065]
+/Subtype /Link
+/A << /S /GoTo /D (section.6.2) >>
+>> endobj
+810 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 521.3691 511.2325 530.3254]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.1) >>
+>> endobj
+811 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 509.3374 511.2325 518.2937]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.2) >>
+>> endobj
+812 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 497.3057 511.2325 506.262]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.3) >>
+>> endobj
+813 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) >>
+>> endobj
+814 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) >>
+>> endobj
+815 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) >>
+>> endobj
+816 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 449.179 511.2325 458.1353]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.7) >>
+>> endobj
+817 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 437.1473 511.2325 446.1036]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.8) >>
+>> endobj
+818 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 425.1157 511.2325 434.0719]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.9) >>
+>> endobj
+819 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 413.084 511.2325 422.0403]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.10) >>
+>> endobj
+820 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 401.0523 511.2325 410.0086]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.2.10.1) >>
+>> endobj
+821 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 389.0206 511.2325 398.1264]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.2.10.2) >>
+>> endobj
+822 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 377.0886 511.2325 386.0947]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.11) >>
+>> endobj
+823 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 365.0569 511.2325 374.063]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.12) >>
+>> endobj
+824 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 353.0252 511.2325 362.0313]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.13) >>
+>> endobj
+825 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 340.9936 511.2325 349.9997]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.14) >>
+>> endobj
+826 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 328.9619 511.2325 337.968]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.15) >>
+>> endobj
+827 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 316.8305 511.2325 325.9363]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.16) >>
+>> endobj
+828 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 (subsubsection.6.2.16.1) >>
+>> endobj
+829 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 292.7672 511.2325 301.7235]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.2.16.2) >>
+>> endobj
+830 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 (subsubsection.6.2.16.3) >>
+>> endobj
+831 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 268.7038 511.2325 277.6601]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.2.16.4) >>
+>> endobj
+832 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.5) >>
+>> endobj
+833 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.6) >>
+>> endobj
+834 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.7) >>
+>> endobj
+835 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.8) >>
+>> endobj
+836 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.9) >>
+>> endobj
+837 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.10) >>
+>> endobj
+838 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.11) >>
+>> endobj
+839 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 172.4504 511.2325 181.4067]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.2.16.12) >>
+>> endobj
+840 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 (subsubsection.6.2.16.13) >>
+>> endobj
+841 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 148.3871 511.2325 157.3433]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.2.16.14) >>
+>> endobj
+842 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.15) >>
+>> endobj
+843 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 (subsubsection.6.2.16.16) >>
+>> endobj
+844 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.17) >>
+>> endobj
+845 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.18) >>
+>> endobj
+846 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 (subsection.6.2.17) >>
+>> endobj
+847 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 76.197 511.2325 85.1533]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.18) >>
+>> endobj
+848 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [499.2773 64.1653 511.2325 73.1216]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.19) >>
+>> endobj
+788 0 obj <<
+/D [786 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+785 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+851 0 obj <<
+/Length 3445
+/Filter /FlateDecode
+>>
+stream
+xÚí[SGÇßùzHÕ½}¿ì>laÀ){1©lm’YƒÊH"º@¼Ÿ~{4ÓÝG¨ç@oÖáW
+æÌ9:ÿßœ¾Îˆõ¨ÿÇzV*œì'‰¢Lõã-Ú;óï½Ùbí1»á ]xÔ«Ó­¿¾¦çˆÓ\÷N?ƒsYB­e½ÓáÏÛûïOO?îüzúÃÖái<)t̨¨ÏøÛÖÏ¿ÒÞÐûÿa‹á¬ê]û_(aÎñÞxK*A”"üåbëãÖ?ã Á»+ÓÜQÂe¹É|.À'aœëŒN9¢…¯þ(špÂiýAüá .±–Jï£>l^Í®ªY{<«ðqk­ÛÃ>.ú‹j\M;»\ÑíƒêJùd´M'Í_ú“aóâÇyÿ¬ÚÙµŽn“]Eïå‡t®Èà†ÜŠ[¢9e)£úÌÎzÍ‹¨X°Û…†›Šmž¥˜Ýˆ#‹ãõžx‘†(Eyâ…ÝÊËb¶œ/ªáî—êë<C²ÄqÛAÍ›Y<îÏ<ò>áøc¨ÜFLÈi11À#fM3×ML&ŒÔ{"F("µÄðoJÌíu†+ñÈJJHa1 ÀdM"L ¨÷DXÍ âV@®FÕu .ý2ê–R¢„x0¥äÿY_îSHw1LÀƒiMN¦LL¨÷cDP `’ߦ۫Œvúñ±Ó MHk14ÀƒfM6šL4¨÷vηJ …R·2óŸé¤Ê3C3· kŸrå¹…¥íR”€BÔÒ°N2A ¡®FÖ&Eú›Pt{å1Š=æªMj1,Ñ c% fD7*`¤ ~™’ÄãzÚ(B•‘P!Ìq¼„ÿ®‰X‰yºã‡Ã_/«¹Ï|à–{("!…Å`
+LWÎo c~:¯Ú‘Íb6¡S|^ý
+ö,{!aÅ8
+ !BÁš–wR‹¡
+xÛŒæƒeFîwÿÊy¯òß÷ÌzÌa1!À#j„’‰#õžÑ æT$D´„|¬‹Ñä¬mÕOß®8/ýËr~B†‹ù†?PAÛ=–‹ãõžøñ &ñ#[~Ž&WÕ,ô
+ßõ//#L£¶æ}¸òs+^†"1‹ÅŒ
+†á’‰Ãõžpa†8ÇÀ…—àrt¼ÿöǃÃÜÖ5E¨]¼pñôêJHe1(ÀJ…’‰õž@¡Š8ê (¢ßóÍ­ÿkb¥ë€ÄÜÏ´üýu^BŠ‹†@PB  L@¨÷Øy‘N<
+™OÿIãô.bªJA€†kRØ\¸÷‚eÄH•@0-{Ãáj¯O˜NK¼žÎÆý…ï¹j£_91Åx
+';LafLáÍ 0…1×IaΈÔ8í‘&PßõG^ÆI2¨nÓÙ—–‡>?r±˜ÀS¦Ôvß­›‹Óõž¥ŽpÅ¡ ìÚ¸¸Ãµj5Bµ9ä£Xm`ˆ© ó©‰SõÕÎf¨jËVíýéøÒ+üit1Z|m$¾-Λ)
+w7uÞÏ–º·Fé—)Ë<0!§ÅÀ
+"—ÔšŒ;™80†Pï±a纞$â¡Ø_<Zü¥0O¦íãJ®§³/þâú{óÛùôºy1è‡mÚÍú™&gÍ]dmáž.ÃÎûñ´×mò쾞3û€Ý’b½“&7H8¦öf˜Ø˜ëX/”"±Zð¶ZMTuW>våâ œûçýÉÙZ/,Â.–ãåøS=ù,´{Ýø6IÅÚG3Lú$
+1Y¥(@C…51rq (àÞCaVÅ] 7EäM5©f¡_E>©>·-uܨq4ù¼Ú1¼š"Óîy­9Å܃ 10 6®{é?ê=ÕÉ”í˜{Í ~]#Ž>\éö¢ÃS³Y~ñº=ÿŸÿÉêE{ó²ë7汘`ˆQuÂ(ÉÄQ‚zåCS"´
+ˆ¦|¼}ºMÏfýË󯉋ØF|\žUõÃØCYéýÈ®AFpþLŠGÈ\1ÀÃ*ƒa‘‰ÃõžŠ‡ô#{ÛÞk¹×<Ë©.'ÕoK/}#¼o:ÂVˆqÛY ¬œ¼ÞŸ7@XÁŸG3¦¬`ˆ%Á€ÈÄzO@M| Þ¶&õþ®IâÌúŸk œã/ÃŒA´°&eõ®Ì´v»Ð0ÇÌÍóת1ڽ̒ ƒuŸ á’0ÖÞG¹×<ꥆ<…á`:X‚Ú±÷)Îñ6#ÅžzùR…\£
+™@06Üçæ{eDiÓÌY¾ª[±ý®?‰»ìŸå¦}BìÁú¶iŸ˜`›ö¹yÞ&'ÝO)çÃr±á6×粎H«ÚT¬Vᶇ£³'U6Ám\-AŽÒëØ!—#,ê;pf ‘T´˜ñ³óiÝySæ…³?³VŽRÌ’BšQäûß6BÀ¾(qŸ+¬ˆà¡’‰¶’Mæój°;œnfÇ_*?ˆöûMAß Ms):É AHÈEžF~3„ tâ—QîrG¬µ¹ÆÒÿψSͽíì»/Ó7tÖ\²]ß)&¨ó‘SÙ«¿yL4׈B6Ó®‘ÿî£A{endstream
+endobj
+850 0 obj <<
+/Type /Page
+/Contents 851 0 R
+/Resources 849 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 703 0 R
+/Annots [ 853 0 R 854 0 R 855 0 R 856 0 R 857 0 R 858 0 R 859 0 R 860 0 R 861 0 R 862 0 R 863 0 R 864 0 R 865 0 R 866 0 R 867 0 R 868 0 R 869 0 R 870 0 R 871 0 R 872 0 R 873 0 R 874 0 R 875 0 R 876 0 R 877 0 R 878 0 R 879 0 R 880 0 R 881 0 R 882 0 R 886 0 R 887 0 R 888 0 R 889 0 R 890 0 R 891 0 R 892 0 R 893 0 R 894 0 R 895 0 R 896 0 R 897 0 R 898 0 R 899 0 R 900 0 R 901 0 R 902 0 R 903 0 R 904 0 R 905 0 R 906 0 R 907 0 R 908 0 R 909 0 R 910 0 R ]
+>> endobj
+853 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 758.4766 539.579 767.4329]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.20) >>
+>> endobj
+854 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.21) >>
+>> endobj
+855 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.22) >>
+>> endobj
+856 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.23) >>
+>> endobj
+857 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.24) >>
+>> endobj
+858 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 698.1661 539.579 707.1721]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.6.2.25) >>
+>> endobj
+859 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.26) >>
+>> endobj
+860 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 (subsubsection.6.2.26.1) >>
+>> endobj
+861 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 661.9199 539.579 670.926]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.2.26.2) >>
+>> endobj
+862 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 649.7382 539.579 658.6945]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.2.26.3) >>
+>> endobj
+863 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.4) >>
+>> endobj
+864 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 (section.6.3) >>
+>> endobj
+865 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 (subsection.6.3.1) >>
+>> endobj
+866 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 (subsubsection.6.3.1.1) >>
+>> endobj
+867 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 589.328 539.579 598.2842]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.3.1.2) >>
+>> endobj
+868 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 (subsection.6.3.2) >>
+>> endobj
+869 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.3) >>
+>> endobj
+870 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.4) >>
+>> endobj
+871 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.5) >>
+>> endobj
+872 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 (subsubsection.6.3.5.1) >>
+>> endobj
+873 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.2) >>
+>> endobj
+874 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.3) >>
+>> endobj
+875 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 (subsection.6.3.6) >>
+>> endobj
+876 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 (subsection.6.3.7) >>
+>> endobj
+877 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 (section.6.4) >>
+>> endobj
+878 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 (subsubsection.6.4.0.1) >>
+>> endobj
+879 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 (subsection.6.4.1) >>
+>> endobj
+880 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 432.2613 539.579 441.2176]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.4.1.1) >>
+>> endobj
+881 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 420.1793 539.579 429.1356]
+/Subtype /Link
+/A << /S /GoTo /D (subsubsection.6.4.1.2) >>
+>> endobj
+882 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.3) >>
+>> endobj
+886 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.4) >>
+>> endobj
+887 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 373.4431 539.579 382.2997]
+/Subtype /Link
+/A << /S /GoTo /D (chapter.7) >>
+>> endobj
+888 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 361.3809 539.579 370.4867]
+/Subtype /Link
+/A << /S /GoTo /D (section.7.1) >>
+>> endobj
+889 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 349.2989 539.579 358.2551]
+/Subtype /Link
+/A << /S /GoTo /D (section.7.2) >>
+>> endobj
+890 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 337.2168 539.579 346.1731]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.7.2.1) >>
+>> endobj
+891 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 (subsection.7.2.2) >>
+>> endobj
+892 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.3) >>
+>> endobj
+893 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 290.4806 539.579 299.2128]
+/Subtype /Link
+/A << /S /GoTo /D (chapter.8) >>
+>> endobj
+894 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 278.4184 539.579 287.3747]
+/Subtype /Link
+/A << /S /GoTo /D (section.8.1) >>
+>> endobj
+895 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 266.3364 539.579 275.2927]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.8.1.1) >>
+>> endobj
+896 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 254.2544 539.579 263.2106]
+/Subtype /Link
+/A << /S /GoTo /D (section.8.2) >>
+>> endobj
+897 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.3) >>
+>> endobj
+898 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 219.6002 539.579 228.3323]
+/Subtype /Link
+/A << /S /GoTo /D (appendix.A) >>
+>> endobj
+899 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 207.538 539.579 216.4943]
+/Subtype /Link
+/A << /S /GoTo /D (section.A.1) >>
+>> endobj
+900 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 195.456 539.579 204.4123]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.A.1.1) >>
+>> endobj
+901 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [527.6238 183.3739 539.579 192.3302]
+/Subtype /Link
+/A << /S /GoTo /D (section.A.2) >>
+>> endobj
+902 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 (subsection.A.2.1) >>
+>> endobj
+903 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 (section.A.3) >>
+>> endobj
+904 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 (subsection.A.3.1) >>
+>> endobj
+905 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [522.6425 135.0457 539.579 144.1515]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.A.3.2) >>
+>> endobj
+906 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [522.6425 122.9637 539.579 132.0694]
+/Subtype /Link
+/A << /S /GoTo /D (subsection.A.3.3) >>
+>> endobj
+907 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [522.6425 100.3916 539.579 109.2482]
+/Subtype /Link
+/A << /S /GoTo /D (appendix.B) >>
+>> endobj
+908 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [522.6425 88.3294 539.579 97.4352]
+/Subtype /Link
+/A << /S /GoTo /D (section.B.1) >>
+>> endobj
+909 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [522.6425 76.2474 539.579 85.3531]
+/Subtype /Link
+/A << /S /GoTo /D (section.B.2) >>
+>> endobj
+910 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.B.3) >>
+>> endobj
+852 0 obj <<
+/D [850 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+849 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+913 0 obj <<
+/Length 762
+/Filter /FlateDecode
+>>
+stream
+xÚíÙKOÜ0
+*q jÉ q »a[Á†–mUµ¿¾NˆƒaWá!$X¡aã±ÇžO–qÿƒL0$ˆYR 9j¶Xœ­ü½ömÊШŒ[íUÅ»iaXuÎ”Ö t×™î²jy2{ÿñ¨Ú?ªŽç§Õa±_ ½Æ##—m—?Š“SΖ>ƒ$§Ùoÿ$l](-A+)Ã7—Åqñiè0ºÛ…&g‚„4"1!£©X#ON“¿ð·Ú™ìš—$i¶l6›zQ^ÔίçèfWë˳/õå¼tœf0/5ç¯å—¢'˜Ñ½Ê+òNÈ/ê°º[¥º^±›‹ÏQñ†¸2Ü.Þvÿmõq‹`ÐJ$g';ü`GY0ÖboGß·³ª¿¾J¿21/§)¬÷dMQ`NS\OD9®)‘HNSvøA“Ô`R¯ÉÜÑ´ù¶jþ^5uëIî =RXêÉ¢À¤¸”ˆzR"‘¤ìð$!ÁãzHöRs¶®—åâk½¸X\5çóÒh±ô`Aa' Šs‚â"ºqA‰Dr‚²Ã‚Á!š^ÛÔoEz·=\PXãÉ‚¢Àœ ¸†ˆ4.(‘HNPvø ÈÓFõ‚(äÑô–ŽDÏGë?†Lf„Ý©1
+1*,•HFX~øA˜³@Ãr¿¨-±Í¯ï˳Ÿ~wÒVíx='¯P€É¼¢À¯¸À(Ô8¯D"9^Ùá^V)žíü£eÇëºY.üº·¾½€·P‘ÉÞ¢Àœ·¸â(Æ\©DrÞ²ÃÞŒ"žþ°ÛMß(ŒÚ
+„ª¢mÔR„î(ßµ¼Ó«Áö”gû–;£Oê0Tj²Ã(0ç0–€büà–J$ç0;üàP àR‡‡G”·û^ÙbëÞiI”»=îiQ…eŸŒ*
+Ì¡ŠËŠrüEi*‘-TËøÒ Ã…M½‹÷ÒÿæÿöÊ‚tN¤§+²’˜ÔÐöÕNÖŒNµoeþwã¹endstream
+endobj
+912 0 obj <<
+/Type /Page
+/Contents 913 0 R
+/Resources 911 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 703 0 R
+/Annots [ 915 0 R 916 0 R 917 0 R 918 0 R 919 0 R 920 0 R 921 0 R 922 0 R 926 0 R 927 0 R ]
+>> endobj
+915 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [494.296 758.5763 511.2325 767.5824]
+/Subtype /Link
+/A << /S /GoTo /D (section.B.4) >>
+>> endobj
+916 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.5) >>
+>> endobj
+917 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.6) >>
+>> endobj
+918 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.7) >>
+>> endobj
+919 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [494.296 710.656 511.2325 719.7617]
+/Subtype /Link
+/A << /S /GoTo /D (section.B.8) >>
+>> endobj
+920 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [494.296 698.8005 511.2325 707.8065]
+/Subtype /Link
+/A << /S /GoTo /D (section.B.9) >>
+>> endobj
+921 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.10) >>
+>> endobj
+922 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.11) >>
+>> endobj
+926 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.12) >>
+>> endobj
+927 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.13) >>
+>> endobj
+914 0 obj <<
+/D [912 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+911 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+930 0 obj <<
+/Length 2197
+/Filter /FlateDecode
+>>
+stream
+xÚÝYÝã¶÷_áG-pfù)‘y¼»¦¸ ¸¢Ý òæA+qmádÉÑÇnœ¿¾C)˶|wé-РX`M†äpæ7¿ÚlMá­µ"T¹ÎŒ$Š2µ.ö+ºÞ»¿­XБJ%…€‡…·%4QšgëÍ|‘·«¿|ÏÙšS’¦\­ž¦½ÒL#¤Y?”?'ïvùa°Ý݆+š°»_~Ài’d:cn…-É Õ~‡fèÚr,†ªm‚ºXbRžFí 悹Nûagaiºi¶kì€OïÛ}^58þ˜ïƒÎý±ìÇÿ¦Š¾ÿxÌ ²¤h›¾ê‡_·Oø9Äõûc3ä¿ad[TOÇ Íö»XÅ6C5T(Í’êŽ% Ý$8£;cÄ(Å£Âa§‰;ˆà,ÉñqWÙ.ïî˜NŠ]Uä5J÷yÓ€›3™¼Ðh{ÓÝéd¬Ýæn‘±·%ÊŸÚ¥­í6ªfö‡]ÛU˜yDIûlƒ®?\Ø!oÂJa+Nò>;ó'ªö‡ÚîÁ¹ë†ƒ¡Ã.wáÊT’Ø×õåûüÐã(ºT¼ÏA4‹³›X–Þ¶ïmOÀ-ˆ*ª–ù£ZÕÇ•+° jœ ܳ‡ˆ[·~­v< ¢·›@ÒUãàQKñpR·ùcî­Š˜g’™ò€bI Obž
+¥ŽrÜ\AÕ„ 78Y˜ÙdÍHÊ%¬áƒh±ùùla+°_¥™ê@0ˆF(ažsý®7 °t2ÏRN†,
+ôœA)*ìaˆÔqf§†dJfKÖñ›Öñ  R
+}å7A,û+£c”ú…%%”Æ8yÿiU ¢¿^OI¢ LQ¦=úP
+F”Qò܇‡àðYÔ<P T.k´^Íã߆WOcãè«$cÌUynBÚÁû¼*q.Z
+Œ=¾Aæ‘óB´f3bØ„ç̹ljj_jÊü¹×¼Kúydð„ S×íKTy<.E#¥Ðæ)¶`¹‘‘e1k½{Lò²ƒ&¦*v8 òÊUÿ
+½´HÙ5#¤‰ºÁFˆ%FH#U¥362(¨«ínx±î  ªˆàF.ÑDßÖÏغҥ¡5ɸm *Þ¹ À.ë2ø°¤òŠƒÝ„t)ø0dY$ƒS™Ì®“ Dyغ
++úF…ÓŸ°3±
+hÇqÕR®°„ë%KôMK¢á³´ýP>ÇG¸²ìÚÖçâMÎiªÏñ¶³õÁqØÚ_‘ĶV&myœ³žŒ|ÖB‚¸
+ä8'&éˆÉK{ h ,$_ÆœQ“SÛ”•«ü ‰—¦áöŒª/»ÀKÒ;
+Ãêó¥6ñLæÒ‰j6}ugA˜°Œ„«‡‘á¶ã[§pS‰•ïÊm‚+zz=ßâÛ¬ž–ü‚ÙÚFérúÌìŸî8MnÂ¥Žõõ!”ëS¥^ñ’ÃÕƒBÖoÂÜÿœ8ð„øœ)θ 'DnŒ8}·)áäÚL‰l“»VXÂ=|عoBÝJ÷zÊk; xòã¿þþ5wm?Ì4×êXÝ.¾9¨H1ºAß_€Ã¿±/¶ÛŸ¿
+}ëmDÏNùmŽ›!úÒsàž%DÏ<÷}õ›ãØè÷¥*‡Ým𾚽"ðÆ@¿"RC¤Té—ÀË¡‚Gˆ §²¬ÒÅšw?ƒŸÙF¯Æˆ—ÆCU_ÂÏÜø€~ò
+B·€ójæþYpÃÝ]KÝ‚ˆŒËùÏ~W?ÿqOÁ@¨0_k½øaüéo#q¿$.¢G@
+Nå:(¹(dWn¿6žVŠ»ýñG¬endstream
+endobj
+929 0 obj <<
+/Type /Page
+/Contents 930 0 R
+/Resources 928 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 941 0 R
+>> endobj
+931 0 obj <<
+/D [929 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+6 0 obj <<
+/D [929 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+932 0 obj <<
+/D [929 0 R /XYZ 85.0394 582.8476 null]
+>> endobj
+10 0 obj <<
+/D [929 0 R /XYZ 85.0394 512.9824 null]
+>> endobj
+933 0 obj <<
+/D [929 0 R /XYZ 85.0394 474.7837 null]
+>> endobj
+14 0 obj <<
+/D [929 0 R /XYZ 85.0394 399.5462 null]
+>> endobj
+934 0 obj <<
+/D [929 0 R /XYZ 85.0394 363.8828 null]
+>> endobj
+18 0 obj <<
+/D [929 0 R /XYZ 85.0394 223.0066 null]
+>> endobj
+935 0 obj <<
+/D [929 0 R /XYZ 85.0394 190.9009 null]
+>> endobj
+936 0 obj <<
+/D [929 0 R /XYZ 85.0394 170.4169 null]
+>> endobj
+937 0 obj <<
+/D [929 0 R /XYZ 85.0394 158.4617 null]
+>> endobj
+928 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R /F39 885 0 R /F41 925 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+944 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&bKȪ»GGämšªjeý@?×Mýäê¾lêŽ&òÝ¥J— ¼ï\A£²¦oáºõ®lGš }ûp÷×7o†Ã‘R?ìw9nü—ºr9eiœŠXIÀ:ŠDøOu&™œðô?Ûð P
+‘Yû;Ð> gñ0옵
+4­£…UÑQµ³‘¼’Hdi²HL º$c×¥RjÙŒy~<[©T³üéRË‘ˆNøßõÏ3ü²Dd*Ã{\þ;êlñÂ0-…µpö¬†Ži°¾ÈFžcÝó¡ñº[tHû7ï"5Ú¢uB7Jý®ü„šK¹ü©,úÇ—¹EˆdrvIIp˜¿Ë.¥á4Iþà)ß•ù}åþP^°øóò*ÎÀ?F©ý}^Iôµ–ÂÌ{ïîò*xÂv߃%ÆFÚåÏw—™^ºO=¯±OtõºjÎ|g÷Û~â]ïwùú£ë»__äè×?Š£Çóÿp¯Zf"M€å+T2cÌ8Ô…<¤"J „¼äg X¥¦*&‚x8Šy1œ*3ৠ' z;D¿7Í6â¸É·<{ûÜõn{žxÓ˜¨D OfI6Šª©Y¶û]ÛtüÃGDøö^R½,šõ~ a–æiÖúºOmEXùM|JYw}^U!rÂL^tܾýè\{zïãð #$å[·ûè*÷L3×uïvµë‘²q¤CZ˜YÌL¢IgvÙ5›þpÔ\€hAqó÷êredÂxÁô—ï݃'‡Ïtí~*§°DÃ`³¯‹Ù“WA{¢Æ ƒÜ`ì@fú’)­é†(ùL#ÂøâgsL_‹^ æD²‡-c“ɧbý‚«hó»1)óêc…‰GÊGGâb¤
+Á7§õÇÒíH@ëÇrW¯p"aÙõ8ì{ï‰
+OåÚÔ“Ûu¹'LeE³~c³ï‡ûG¸{`s<«áïhˆŒ |Š;c÷¬&#zPÚ¶ûôW ÛR¡UB>çuU‚ô½²ÙeÕ4i´oé;嬟 /go6¨XÎ¥Z>Ó$ZqÆnAä^¯&)¤FïžÆGlæfSÏf´Ðˆ.F1pUBÚ=û„óÝw
+^0ö5žy ›–îCž›ÀH0Z”Y­bmÉäp‘œ$Ž2¾zâãpf0/+œr¦Cå‹rúìcÆþ2‰€Á}Œˆg&fƒ›‹9 I‘eà&ˆÞWc›°™7z›N¥ìg¦¢<ÇJU‘@™y”|uع9~›²¥4 €îÂØEÁÞªbP¬ñùVŠ$Õ#ź/ëYò€I¤ç´uB‡ÿA9P]u ÍäO`þ˜¼ÒÏ ù€-ýº¾}Íðž.T:)¤ÖéTérNÉ\›ï†P4‡ºjòâkÝ¿îß;ðP@×Å|®ñu’öNF%GÏ\Ð
+ž‡ß>€zwÈ&Q`9EvØžìÜd–Æf,‚‚QEðúTc%b;­Ì{‚? `AØ>äuù9\Ÿ3bLQOàŒ~¾^sÑæý›'­¡/ͯXˆ6Ra"86O>$ç˜ í8U*¶e «OœÝ7œÑ…>G2[¾Í½—ƒ¥º)Ü éTÀ0SÞûhŠ—ÌðÕèL òì cϹ ;M;²p8<$†€sÈùèêî*FÕÄ3Å
+‘ëøžúd½ÍûGšÙ©
+ FD|Lá¥sÎF
+œb’©±×hš~†·
+*‹$ΠϧP EPŠ|J¦ »£4=â¬
+¾$r,)B€š¾‡]Ù÷Ž`D§QÎûsú`üðQÆžð­¯p
+N1({z¦ °Ûð 9<Ÿÿô |‹¦G ‡joy5—«yÈ-Õ.Ô¨M]qÂsKu ŸÆ‡jveeÏŽ®e˯ûà=Qñf³¢wÞ.!÷)߶•7&r 89h,ŒYc¡ªØ„= Å©$NôA*ëfÛæõœ›Ó”¨&æøvrýu½s¹F"ÒØ׸nöUA×Ü»™f‰É„N’pA³ß!ž‚é€Ùœ‚*#l©ÁúI;­ÒÄD;˜³ªi£³> ˜ÎÞC™Gƒ®²”Xå9¨WK3•{B­Àa‡lŽRÂs”g°ùwé·ÂFYØêØÔÝ«9î¢7•B>uæÄȈT¥Ù •9áÞíï~Üfšˆ$ŠN²P0Ðê”ÐÑ ÜˆÁ>Æ „WÇ$`F^ð*M¦¼š£áL2¢fÒà­‡ÆÅYïÝ3ŸÈÌ@->¬œ¢Ádò$@â71:,ëS6/‡ûpÔAáÏCŸoÄÞ ô%
+ï}æ#x<<%ä É¡s&fF‰Ð& ÕËg8k.ÑZ(’bDÒùîqëŸEàÝ=Yæ1˜JbO²oŠ<V…œMa'
+®µ”OiDõŽ
+œV`/ù†FxLGC*‚ŽÐ£¥£$×¢0$zýÐÓ€¾¢ gÛ³AŒ±ôc® ÂÃþ¹
+6èÍ8‡·#çÒÈ(t&ƒk›UMEd&y †‹P?¢!t,éüQ +õ'êû™ËI|Öž¨æÓ jFƒg:0µ›¾Y7Õœs·"ÖƒCÁ#(¡2{b+$€$ Íå]׬K¹ðã"XÉ(š%C4K¸ŠïD8Ï}¸Œ³ 4µ(át”ÖN{jþð4 ™u1›È'ùÇ¡ÄÖÒ‡¶–Pñ²hyÛ¤½{aäˆQ‰±´'®³Û·m³ëƒ~Íà4̆lŸ%ûܺ¹gÇðàuTØ“¹NÀßCyª (Àü3­í4ø0i#øj Þû?;ÕwÝúøv 5“P§È`ʯ‹ãÓÏZÙÔ8?m¤¨:²SezΩCB3ô^|¥U8ï7ÊŠ*±dÚ|òՙठޗ5Ws›ùj3æŒJf–ƈNÚ@
+W¹‡Ñ;ÓÙS×Q3„;W4{¼kÝÔØc7>JØÇái [¨åÃ~5gë@
+½þ`J9ÿdÑÆÇVþ¢Ì!ûȨÀÌBÖ?e‘úñcΗ`ùX¹žŸš¦-zXæç-@fØ:\a½ã¶Gî7žÛù¨ß•=Éȧv)½»@2wl(kz+0h´zx6éqŸSS> u»žQ¶àðI¼þ˜CÍ-í‚f¡œoMoqÓâ›äÚµ|Éï…2VDÓWÜãÒ|ññþkÿ=êø_bP*˜4Õ/øÃ[Df@
+ž!þêóy©òendstream
+endobj
+943 0 obj <<
+/Type /Page
+/Contents 944 0 R
+/Resources 942 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 941 0 R
+/Annots [ 951 0 R 952 0 R ]
+>> endobj
+951 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
+952 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) >>
+>> endobj
+945 0 obj <<
+/D [943 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+946 0 obj <<
+/D [943 0 R /XYZ 56.6929 756.8229 null]
+>> endobj
+947 0 obj <<
+/D [943 0 R /XYZ 56.6929 744.8677 null]
+>> endobj
+22 0 obj <<
+/D [943 0 R /XYZ 56.6929 651.295 null]
+>> endobj
+948 0 obj <<
+/D [943 0 R /XYZ 56.6929 612.4036 null]
+>> endobj
+26 0 obj <<
+/D [943 0 R /XYZ 56.6929 555.4285 null]
+>> endobj
+949 0 obj <<
+/D [943 0 R /XYZ 56.6929 530.6703 null]
+>> endobj
+30 0 obj <<
+/D [943 0 R /XYZ 56.6929 416.0112 null]
+>> endobj
+950 0 obj <<
+/D [943 0 R /XYZ 56.6929 391.253 null]
+>> endobj
+34 0 obj <<
+/D [943 0 R /XYZ 56.6929 164.815 null]
+>> endobj
+953 0 obj <<
+/D [943 0 R /XYZ 56.6929 137.4068 null]
+>> endobj
+942 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F39 885 0 R /F41 925 0 R /F21 702 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+958 0 obj <<
+/Length 3415
+/Filter /FlateDecode
+>>
+stream
+xÚ¥ZKsã6¾ûWè¹jÍàA
+J$”š.º\.³/ËA*™… _ÕÏ5ŠAç ãîøˆ›ÔoÉÛéÌ‚ÖþoâFð 6ñ—·'\d"`X¦Ûµ¯Dí”»@/HhBg©3¡½¡&+JNaz
+ ¢â¥ 486Có\\ž(ÙÓ *'Ø`||$Ý㤣@òkw$)\µ&òçß÷Ô‚(L{Cʱ™ÑK„{ OÙåÑ‹E pàg`6Ž;ð’è:×€4Î"ÈÆÇ8@Yƒ67¿ ¡VÇvHÙ ÆÇåвº}³Júí{ -Äü»wï¨Eë÷®ÚÖ[¸ Òoà<Ãã;[9´ÈʱÅ"µ7ìX×pºÔ܈ÓS¸O‚gÚÓ2´é1Ì1„ÞðÛª<¼ ?çÇJûïÛêÙU­WmuÞH ÇëÙ7ã~]l/¸³5x‡ÝCÊ/ª¬ˆ&ˆçÑò¢ý¾^5¯´žß„WAê‰D¶VÜ›+çÿÙÔ;¢³ÆYMžˆÒw[ž5À*.Ð ]Jpä./‹3{Ej,®º§÷—¦mIµ0HèˆèÑÞ+z Â
+&‘|ø D`ñ‚ZÈ
+æ<ð¡œãFn¾¸.Õý„3€O(_Çq ’(J@J×Ö‡Ê'D@öç
+Ô ÒH#˜â®^ºÃQª¦=r4„ž¸P1öôjAã6^óüJ/5:ž8f˜žÊ’¾I!ÕTY8Bâ,0($ÃýC}š/2Ë}Ð?×ýðŽ7 w»Å·âüàq
+p‘æPj¶]åK]¼´ç‡3õBypÀ&؈\û`‹æ€¹‰";$×ë†ê`Ð^²
+“©Ò3:­Ó8˜k8¾óšlùø¿óå ¥BÐ=&óرk„Óâ¼nÍ€¨µ Žöu“ S=qsz †€\…nß| €ÅtMô=M¸ª{^!ȧï×¢Q%à)Ì €àà¢úþ!éœ œ‹Íåè,Œ-Ï……(œ‹,²2^
+”r¬¾*{êÃÂ4Òçাc¡Z¯; ·]u‹ο0b0–9›7Œ÷13;w|rQ 'èú¾Yzlq\QF‡¤A_ )â)b—×i|H£>î’àœ‹˜¿„›#ÎJ*NUF+ •¿šâ ªúºåL²xnô'sLÑÛof2ýqÉë6;„7Öé¥`F¤ðE|Èl‡ÍßD˜ŸûPˆ0b26o† ¨£ßô<ê €Ì$Íòý1J4˜DôTE‡_Ÿ‚§OFŒ»¼ÂE6ÅÉ}b`¯OµFxìë8gâ¼// •ó—vC3ÎÔR&Z¸Ì¨<V×ÇûÙ4zÉxõâ³ñi†Éá²'ÉêdÀ¸?_ VÍ+÷•|ÖŽ‚öƒÉšÔ(ò1-ucBj‘9=VÕä4†±jtòÐ&]Gû°ì·íB^ëd¨Ýž·W$/
+,Ê,ÿJ@T&¸«j_ÿ™¾,07šÈކС¶’Ûù/¾¶r$:]iYíEE¤Q°¸ñ]b¢o¸6wCûò¯¾(ÏsU#i[•¹Ü˜ókAº§ž˜
+¾P(Å& L®©§&à™`Â稙þ˜£­á
+?6`³<sö Ôq¿qÁâK Nÿ¢@C+žsê^ÎÌo.Þ÷³Å"ÏÅE}”0Õó©áÅœ¬ݦ5F;Ž
+—%^G¦ð8Ê‹`øûÕ%çÿ^_'kendstream
+endobj
+957 0 obj <<
+/Type /Page
+/Contents 958 0 R
+/Resources 956 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 941 0 R
+/Annots [ 961 0 R 962 0 R ]
+>> endobj
+961 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) >>
+>> endobj
+962 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) >>
+>> endobj
+959 0 obj <<
+/D [957 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+38 0 obj <<
+/D [957 0 R /XYZ 85.0394 570.5252 null]
+>> endobj
+960 0 obj <<
+/D [957 0 R /XYZ 85.0394 541.3751 null]
+>> endobj
+42 0 obj <<
+/D [957 0 R /XYZ 85.0394 434.1868 null]
+>> endobj
+963 0 obj <<
+/D [957 0 R /XYZ 85.0394 406.5769 null]
+>> endobj
+46 0 obj <<
+/D [957 0 R /XYZ 85.0394 301.1559 null]
+>> endobj
+964 0 obj <<
+/D [957 0 R /XYZ 85.0394 276.6843 null]
+>> endobj
+50 0 obj <<
+/D [957 0 R /XYZ 85.0394 200.1512 null]
+>> endobj
+965 0 obj <<
+/D [957 0 R /XYZ 85.0394 175.6796 null]
+>> endobj
+956 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F39 885 0 R /F41 925 0 R /F21 702 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+969 0 obj <<
+/Length 2458
+/Filter /FlateDecode
+>>
+stream
+xڥ˒ã¶ñ>_¡[4Uš
+Yþýî×ßÂU üù. TžÅ«LÂ@ä¹\5wQ¬‚8RÊCê»ç»Œg«n뢤DH•ÈQIµ$ª8K(ªwp9®‹®ý†òe8j[u-O{s¼ÙÚÐÔîyp8V>žiÒèÞš÷æøêÇ•íM½ãqO_ÍhÖèÚîö0^·³†y væHƒ’Yé˜ Û <á¯RFûª,a3(¤z ò8–îªÌ6"z]_ô«âhý¹5´<ô<ØuÈ_ƒ‡·[ H‹1Ê!$2
+…>°®Á€º}á’` 2™#Xô
++x¨mO+èG¸`=ª¿£ßw¾8tž@Ü~®€iãb&ýÊyÊÉe£pη³-X¢(…Žgò.„ŽÁ&Uk!¿X2üÈ¥óüÎ8‰Û0,@ÞYT¯öÂT½¡]8-õV¹I@©äµ‹¼.OÈXxœ‹k¼I´ygWŽ3Ïo¾NÀT×{ŸéÏmמ›nèAŠƒ`TÁÜœ¨˜I×µi_¨II @„É«d­08í«‚±4}XH”pK‚5úL¶fŽduÕF©ZúZÏ
+3‡zÙM¥ÄEö‡<'Ĭ¢‡Â‚k‰ŸºãIK”Íÿ¬>¼’‰$s“™Taâb2 Åéºìœ[âzgy`Ð[¡Ê ")™å˜°P¬®µ±<»‰’ GS‰Œ™BæSF[ÐÆg¥@|º]ªJ°óI£)¾¢l–RHE„cñÒáÍ‘*š8~±È$
+K³ËZ! U¢|õ },ä-T\Èiù)¶†—™M¬)¢Ût‡KBaŒÂ´˜ŸS7`\&Ö^±¡‰&&Ú¡Ù’å^_ˆ¼=¢ µŽ¸Š©/@ð$.˜Á²n 0ãf—«{/Qc‡çöùŽ±Éñ¡ÚÖ=¯tñÍX>Ëî)z /{0„öG1Y C*5÷Hò|ÅjAÀùеa0ÂXë–KƯ,†•p=†”Fä9‰ñléÜî|uÚ$1Sû52Ñ”*?õVù8ijÞC@üû 3ß‚ü¹=á¬zÛ”SsÀÖ'¨‹«ƒNøÒÕæOwíi¸þáñé=|ë5ë~ÒÅÀªƒtk¨€ƒ6¼Ý ]´Né!)½=Á˜*5$ÐyúÿPŠrla±Ö¯æj§›íb5% îÖfÏX.]äü©pšwzc 4vÖ׳Ü]Õ°»“™2_$¡OæÖ#ç’_åpÚÐØ°ö4uîëÜzû.—H38Bn«‚'äô°…ïúýuoõÖV1J¹–cݽŒñ=Ãm}„R/"$•§Ž4÷•>‚tùª[«_Ð@âIŠý[†a{ÓШk/O \¯\iܽŒ‹µyîbm^`8O_Š­j˜=:9M®<uH&)!Íf¹² E ¤òïFÜÙ Ív¤Yžú*Ï]‚ÍŽb7KFY!ëö4¹é>a±¬z Ù\˜"T‘2»Œ·SCNE˜"¿ÄTz[Õ•=L A05h1„u”»œdkM9C€/¥x$ue¿
+…3¸U£©UPk\‘;cpËÜÓ…à8~*”©DGÊR
+endobj
+968 0 obj <<
+/Type /Page
+/Contents 969 0 R
+/Resources 967 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 941 0 R
+>> endobj
+970 0 obj <<
+/D [968 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+54 0 obj <<
+/D [968 0 R /XYZ 56.6929 717.7272 null]
+>> endobj
+971 0 obj <<
+/D [968 0 R /XYZ 56.6929 690.4227 null]
+>> endobj
+58 0 obj <<
+/D [968 0 R /XYZ 56.6929 550.0786 null]
+>> endobj
+972 0 obj <<
+/D [968 0 R /XYZ 56.6929 525.2967 null]
+>> endobj
+62 0 obj <<
+/D [968 0 R /XYZ 56.6929 393.0502 null]
+>> endobj
+973 0 obj <<
+/D [968 0 R /XYZ 56.6929 363.1913 null]
+>> endobj
+967 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+976 0 obj <<
+/Length 2095
+/Filter /FlateDecode
+>>
+stream
+xÚ•XÉ’Û6½û+täTîË1Þ§*®T<9Å9`DHD …
+wQàgY”îŽÓYYžûYš»‡êoïM-ÎFwû( ¼èßh[âçEâ¶
+JòÚC 2ã ÆÕŸÞ½!ú(…Éš8 ¬ýR¨ UÒ§7"Îtƒ ‹3=}yÌFGòÍ¡:ƒ&q[êþ*AÏ»<ñÀÔq˜{š…ôVöItê+¹‚Ïø†ñ[ñd •yµ—‘£f^¤¯©!r¤ã®¯Œ{3$®J×¼¥§ïTP¥Xæ5¡'7Ö7mdk¥¤Þ±ÜqÓYâ|nÔn‚±S
+fhWü(½¾YhovçåvlŒ25©,*Yݳ÷›¦¿ªîÄqˆjØ|SüÍ‚Ø{©uÏ•cqÀ]#Xg±¬,ÕI’Êøߨ ´8͸dD\2lL|£ælV‹„Jn Ë`«.hš±š#A&Fªä=¢;I^4¥ŽTRdûC#4‹hÅ¡V|.ÓÊhMË4`šÑ_ûiÓ\Õ†+ït¿åab\rc8JK§ rgM¢ ÷Ô‘¸·~$Â&TE´´ð¬“a«ì¯nhQYdçJÉk„“âªÒZ¨xm¯v¿•|“UllÑY6HúQƒX½¾G9(©§²æ
+dXõcsý.Û~¸ý¿ Šç•‰×:%<ä7IE”èÚ–Ø’ª2yÑT
+hZvýxªY/ý‘áÝN6“dy 8xp]Óc~{î0¨”~‚’$¡½„3×|Ó$ý$ÈR¸2Æ/{ë³ý4±òÕc¯ÕW¹aµ¤ôó,ÎXT¦JP¶Ø¶ÖVDÙ6
+^AÁ³"r
+DŽ49œvDü¹„šný~¹ æÒû/å¢õ>ÉÃP©_¬MËZç¹—ù
+ÜѸU‚>Gy%â*哦tð–RW8
+Ÿ¤IhsÜ]W‰y
+Õmíš™Q‘‚z
+â~ó ¯ fÙ"‡èâ9Lt¨ž¹£j¡ mK(ÈÏbµ
+endobj
+975 0 obj <<
+/Type /Page
+/Contents 976 0 R
+/Resources 974 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 941 0 R
+/Annots [ 982 0 R 983 0 R ]
+>> endobj
+982 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) >>
+>> endobj
+983 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [84.0431 256.1579 143.5361 268.2175]
+/Subtype /Link
+/A << /S /GoTo /D (acache) >>
+>> endobj
+977 0 obj <<
+/D [975 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+66 0 obj <<
+/D [975 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+978 0 obj <<
+/D [975 0 R /XYZ 85.0394 574.3444 null]
+>> endobj
+70 0 obj <<
+/D [975 0 R /XYZ 85.0394 574.3444 null]
+>> endobj
+979 0 obj <<
+/D [975 0 R /XYZ 85.0394 540.5052 null]
+>> endobj
+74 0 obj <<
+/D [975 0 R /XYZ 85.0394 447.7637 null]
+>> endobj
+980 0 obj <<
+/D [975 0 R /XYZ 85.0394 410.3389 null]
+>> endobj
+78 0 obj <<
+/D [975 0 R /XYZ 85.0394 348.7624 null]
+>> endobj
+981 0 obj <<
+/D [975 0 R /XYZ 85.0394 311.223 null]
+>> endobj
+82 0 obj <<
+/D [975 0 R /XYZ 85.0394 189.9853 null]
+>> endobj
+984 0 obj <<
+/D [975 0 R /XYZ 85.0394 156.0037 null]
+>> endobj
+974 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+988 0 obj <<
+/Length 605
+/Filter /FlateDecode
+>>
+stream
+xÚ¥TËr›0ÝóZŠ™¢êŒ´Ìƒ¤îŒÇài;iŽQ¦QIó÷HÄ$qW†A÷utî‘.`óÀgh&©‘ Ç„ƒÝÞÃàÁÄ.=âr‚1)˜f¦Þç ‰äŒÎ@z?Á A@šÝ@Š8ò †ÉfµºZû,‚i|î”cxµŠ×'~Ât¾¼´®äG’ƋĘ <ûr²Jãµ Qt:_ºúuœ\mÖgñh]oæëx/ÓÄ¿M¿zqúÚôO‚YßÀoïæƒÌ´ûÕÈIÁÁ³10"RR°÷BÎ=…—xׯ€“èPzT7‚e3zD8J
+4‹$
+ó}å*!²á ]ÖÑUA«ƒlÛ*kyÓÚ Ë54<ªàmgvd¦gíTúä,¥ì¢}Tã?9_¸ûÿcZ8^¾Klue…zR…]fù •Úµº~±®Û´î0lÒqÐÝPµS#HÓÖù]ךÃ@ÿ;ÆQ?+G†Ä¼îPÿ{$ÿ©0BLz˜¶éTÐH PGª—œÐÌÇÙýHý/š@endstream
+endobj
+987 0 obj <<
+/Type /Page
+/Contents 988 0 R
+/Resources 986 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 941 0 R
+>> endobj
+989 0 obj <<
+/D [987 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+86 0 obj <<
+/D [987 0 R /XYZ 56.6929 769.5949 null]
+>> endobj
+990 0 obj <<
+/D [987 0 R /XYZ 56.6929 744.7247 null]
+>> endobj
+986 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+993 0 obj <<
+/Length 1222
+/Filter /FlateDecode
+>>
+stream
+xÚÍWIãD¾÷¯ˆúäH¸âZ¼©OÍ°‰Hs`8TìrbSeìrBƒæ¿ójs6sà
+©Ç¥·†EòS€Š2Of=§&ü¡W.tÀLFXôÚyÉß'1´¦÷fÓ¸<Žn§&=Z|KÁµ½áDnãÖ [;ÑiteL-dçÞ^z@3Š Ñr0¡sSùØò¶Ð°´@EžQ/ëph‘@#†I¨„ƒÜkg+¡Û“€:cŒ£¯&L0À3LDc‚o`Â=æÕÔÕn¹ó"¦iâ$ü©ÏÍZ™Z}!W‰37µu£VDS' 0|‹Cš R&®}› ô ½=+·-n;N;)LùÍæìÏíxp+íµl)Ýrn¬Ù4ƒ:¢[ظbñª»ø»xøË=pIÎ
+ÄP²!ìåö0¿>üô²J×­Ù¦‘ %*Š¼¼•«ÛZ  ÿVòy#tµ1ÃQïžs*ô^ mÌ梸”Û®®³
+©Þ†/F¶œWˆåçÁ¿líÝc
+q/ÇV”ðç^Ƕġà2…¿@¡žKñÿ‹ubóÆ7Ü#ar/¼o°+ߨ £ØœWÕL ìõ…Áýñqùvå»`W¾Ý@˜UxÎ$U‹†O^re˜†ÑŽJûÓÌ©¿¦L¯
+/9ƒ¶‹Ôïè˜PTâ„ý'tüôívþÊ ß.4EæKhé;(ˆÄ÷txšd¨ e ™¼0½÷6R=ºû*Š™Üendstream
+endobj
+992 0 obj <<
+/Type /Page
+/Contents 993 0 R
+/Resources 991 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 999 0 R
+>> endobj
+994 0 obj <<
+/D [992 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+90 0 obj <<
+/D [992 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+995 0 obj <<
+/D [992 0 R /XYZ 85.0394 575.896 null]
+>> endobj
+94 0 obj <<
+/D [992 0 R /XYZ 85.0394 529.2011 null]
+>> endobj
+996 0 obj <<
+/D [992 0 R /XYZ 85.0394 492.9468 null]
+>> endobj
+98 0 obj <<
+/D [992 0 R /XYZ 85.0394 492.9468 null]
+>> endobj
+997 0 obj <<
+/D [992 0 R /XYZ 85.0394 466.0581 null]
+>> endobj
+102 0 obj <<
+/D [992 0 R /XYZ 85.0394 237.1121 null]
+>> endobj
+998 0 obj <<
+/D [992 0 R /XYZ 85.0394 206.4074 null]
+>> endobj
+991 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1002 0 obj <<
+/Length 1860
+/Filter /FlateDecode
+>>
+stream
+xÚÍËrÛ6ð®¯àøDÍD0^$ÁæäÄvêL⸲RO'Í"!‹>’²êvúï]<HQ2e»­gÚá `±Ø]ì“ÄÁðÇó‘ÒÐ BŽ<L<'ÎGع…½w#bq&-Ò¤õf6:>g¢Ð§¾3[ôh „… Î,ùâ2ÄÐ(`÷òäãÙxB=ì^ŸMÇžçþ ƒžº:›žŒîÎ.>]^'¹ûöÇ“«Y‹ñ4·Ÿ.Ï/Þ}ÞÒ½Í:)ú’Ì”ßG_¾b'ß0b¡ðœ L0"aH|Ä=†<ÎX»’®G?u{»úè æF”ùt@uœ ©Î ‘Ï(Óªû½,äxâcìa,Ð
+EÕ*:2{(A"!x"BPèyThîW–@Õ¬^kT¼‹´H³ö–¬Œ£lYÖ ªäÝѶy΢lÒŽÁ/Jƒ2¼üÏÁÛŽÍÙ{gTY Yî°jàZVw-¼(- ‹òU&Q\æCö´ÖÃ|yeõˆ£d>¬­VÚ‹++-¼¬kY›i¹°bfÑìKl÷£,+72±
+*íXEE½O)Ãð«)Lv<¢RD|ÀCø @-‚‡<öŒÇžeÇ-#: ¤}³(nÑÚè›Æ.öß1ÍÈ }ëØ¥æߎõ‡= Ùµ}ÑùÉ
+šwÄõ4Ž
+»nÏFñ2•wÒb§vWGœª<£ñï͸®;Zù:kÒUf1«1®ŒK=&µYü{¸^ÇK{W=¨úŽŒRƉö¨b6´+@Û¨Š(—¨# Ñ@>ר‚µÎÿ
+f!uÓ…Zåî}9&îÚÀKí3
+·Yš«¥Ù¸¹¹1ë]ÀQ“MÚ,Í~!›MY}3ËÊ(õaºÔ~¹0[De&ÈM–;¥ö\‘l»Ì^ Æ(P"æÀHc
+g:+Â`ón™é‚W­|_Ë*UiXMtÕ 
+n9ê®ÐB©ªWúQEBŽ| ÌNuë`:ôkn‹}8ÔXÅÇtªëmý÷­¯ý=^¤8æñ Ç̃€×á<ÊÃ>%Åê+'Йú>êçòE@Û߈¶¿4E¢þhh!V²ŠúO@º¬bºMæ1áwÿ$‰%7BܲÌê½>ìsëD7c¸¦1êÿ0§‘ÌÁ¬‡^˜yö·èl™ê.$ ˆßf’È:®Ò¹ïXÀŽ2³—à‰+YÔÑ\÷¦
+=n ˆi¬¢<UZžiÝ(]ÜY$Ë
+endobj
+1001 0 obj <<
+/Type /Page
+/Contents 1002 0 R
+/Resources 1000 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 999 0 R
+/Annots [ 1007 0 R ]
+>> endobj
+1007 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [55.6967 190.8043 126.3509 202.8639]
+/Subtype /Link
+/A << /S /GoTo /D (rrset_ordering) >>
+>> endobj
+1003 0 obj <<
+/D [1001 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+106 0 obj <<
+/D [1001 0 R /XYZ 56.6929 480.2651 null]
+>> endobj
+1004 0 obj <<
+/D [1001 0 R /XYZ 56.6929 441.7923 null]
+>> endobj
+1005 0 obj <<
+/D [1001 0 R /XYZ 56.6929 373.7178 null]
+>> endobj
+1006 0 obj <<
+/D [1001 0 R /XYZ 56.6929 361.7627 null]
+>> endobj
+110 0 obj <<
+/D [1001 0 R /XYZ 56.6929 167.4388 null]
+>> endobj
+1008 0 obj <<
+/D [1001 0 R /XYZ 56.6929 126.8733 null]
+>> endobj
+114 0 obj <<
+/D [1001 0 R /XYZ 56.6929 126.8733 null]
+>> endobj
+1009 0 obj <<
+/D [1001 0 R /XYZ 56.6929 98.4089 null]
+>> endobj
+1000 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F21 702 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1013 0 obj <<
+/Length 2705
+/Filter /FlateDecode
+>>
+stream
+xÚÕZÝsÛ¸÷_¡—NåéÅA°O—Ë%×ÜÌ%×ÄiÒÌ”– ‰w©);Îôï À$EJÎø©ãàò·ËÅ~f3
+l¦SBE.gY.IJY:[ì®èl Ï~ºbž& DI—ꇛ«¿¾Ù,'¹âjv³ê`iBµf³›å§ùË¿¿øõæÕû넧t.Èu’*:ûâ—W¸ò¥éüŸâå»·¯ßüôñý‹ëLÎoÞ¼{{d4—ðæåwßýúêñ½ןo~¾zu¿¢û¥Œ
+û \}úLgKøàŸ¯(¹Ng÷0¡„å9Ÿí®d*H*…+Û«Wÿˆ€§îÕ1Í¥B“TólDuœ©.͉\8ÕÙof„]'ŒR:ÿ±,ÖUÝ´å¿öæš16¯ëmc¿ðDήHγÜ!ÝlŒ'ê2e9¡)³²Zše¹b’äRhOóÝŠ$Z$Ø€€c(9*ã%á’Í‹j9Çaw¸–ž´j¶uýûq?‚)SÐ>Ë<áþpÍô¼^Š]ðBÏ ·bì$ŸÛ-®.êÝÎ2v“mYµNŽtUp èŽðÞÎþ8šÃCY­qV;ܘÃ94ÄJ8KÏ@ëvž1’§)êÀM[–++ÕÊp^VøÛ´[ƒC”õ±Ý[ƒP»¢%'6MaÁÑ”ÎÁ¸r6(éRM›`¤êE—g¯hÁÏó D#<{vAÁ¼”LûL­µ&œfóe½+œ†¨M¡ʺ‡kÜñ½S%ÌÿMS:fäR°6ñ VH 1Ë™·A¢µo7²›Ò¸]
+Ü5XÛoMëéëUhü’7h7vfqçjþÆoŠÆÛR
+’S¡ú¶ÔÞ×׉  DYšæo׉d|Þ”–)®—UkÅ¢-ïÌ#!Žœi ˆ%ΰçðš³oRÀ=“øEöÉmÑ.6C¨ûMͳ8¶¦ÁYÑ…³ßAûò£{I›Ât ÀŸmÙx«wÚ³Þa@ÛÅ'ˆì)+cÕ'¿Øž>¯÷Ö\ã,¦iÊÛàt+4¦Îp»að-<·S„TÇ5xƒTD0H‡#ÞÀ  •ÂxÌU¼@Šèbœú'£0–ê‘“ÕæǦX›I™„$"ÕêY2u0œLrT¦@\,Q`eŸ¾GWK»®&R¢UšzWÃè‰d=d¡·õdŸG€‚Qy¿ÆPq
+$ÑR O#@)ɳLyg=Iû°7#Xœ³,ÕQ(üÊ1Ù ®{˜‹mÑ4# *%Y*ä
+›Ai:ÿÁ/ͪ8n[»ùJ WufÝ6øÖ­iï©ðÑ‹"X¶e±¯^$ôLŠòkPÑÀÞØ"¥2Þ8‹åͺiL0ºÛPú–­·ÎÕ±ZX³,ü§[ó vtë-Ô|iMµ4ËàÖífàÌ'1À›údbO)'TÁN>#‰v1¦{¤º˜ØeÊ….é92u1¦{¤Š¦‰á=)^.·Õ¡¹¹¿ ?YŒå~¯eÈnS9çÐDSHòöbùP-ëv/6¥°½8‘øû™+âýë2^¹3ÐÇ=!ÉyÈ÷#·5Q9—ýÄ}0í¡4ÍÓ±wÅ]m‹õØçCÐË4âÉ8RcZ¯±¶ãšæ‘B,è+´o+ûeÏA3>÷ÿ5¹NgF{Zv•<³GMò|víRMg×H5<³éeX®¡ŸÍøyΑêk‰•iØÂIÞ§çEZçá¼ÈvÙ ÏöÓvúi‘fýÚ>Ä̓AUWIç©MÚ§³.=6ÊîÍí¶¾¼6~²ÐÓ¤Ê œz|'RfKDÈê®›…™?s‚‘whàqŽ=u–=Ú,<sf kÅmíR) ï`¹8”õÑ¿g­Éý*_²úUÄUQ ý¾—
+\ñN
+µ#÷‚+ÏÌ.¹cWø}ìzì¬'¬#[õBcå–jü½õO¬ ÖÖ•,¿r4êÓ’À°Á_T3 ·Ü>íl‹ëµ?Pgè£îLfq3où§{³(-²²ó»
+#¿UÃ¥ìœôý©e0fÆOØGG÷ãÑê‹aº°¿®™´”úGGà32’ØMZ ÿ&ƒÃ`3GÕÚK!¤M4Ý×Û•[³)îÊÚIdÒ¹žß{¤¥—¡ª=-â9ØÅðEàð{»]ëÈ•™&™Œ%â¹J&•…>ËœlÌø5œÚo8Ó¢¡5Å’Œ€%L䶵U6‰%™ìÜor¿ùb¹++På¡ÀSï8±;{?\ëÙZx[<„B<ø­YÇk…}qhû×ñÌ
+ÏÒ¡äñ_•NEÿ…6_0endstream
+endobj
+1012 0 obj <<
+/Type /Page
+/Contents 1013 0 R
+/Resources 1011 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 999 0 R
+>> endobj
+1014 0 obj <<
+/D [1012 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+118 0 obj <<
+/D [1012 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+966 0 obj <<
+/D [1012 0 R /XYZ 85.0394 749.3395 null]
+>> endobj
+122 0 obj <<
+/D [1012 0 R /XYZ 85.0394 221.8894 null]
+>> endobj
+1018 0 obj <<
+/D [1012 0 R /XYZ 85.0394 197.4323 null]
+>> endobj
+1011 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F53 1017 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1021 0 obj <<
+/Length 3394
+/Filter /FlateDecode
+>>
+stream
+xÚå[Ý“Û¶¿¿BoáÍX>‚lŸœÄN™Ú‰ïÒ´ãø'RwŒ%R©;Ë“?¾»ø")‚’'éL;é܃Àår±X,~Ø]àØ‚Â[È„$Ï*‹‰¤L.VÛ+º¸‡wß^1˳tLË!×W·W_¾j‘‘,áÉâv=•š¦lq[¼‹ä$Ðèõ󿿸^rI£›o¯¥Œþ?úùÍ÷/Þ>¿VqtûêÍë›ë¥¢Y}ý·çßß:ŽË2¾~óúå«oìå\¿¿ýîêÅ­Åp¤Œ
+¯WïÞÓEþ¥rñ”°,ã‹íU,‘±Ž²¹º¹úÁ ¼ÕŸ†,KJ¤Œåb)b’Bÿ!.–L$Ú!
+ôf)‡†ÌH"¸ðÆÙÀø)#2ËäÂs¡ñë|[ËÕC¹úð©©ËëeBiônYüòëã7ïÝÓ
+-õåK)Ò˜‚yCPÊj“·­auÉ3’¦*³\^^'$Œ^:Í¡Ûº€Ä1›—Ø]”XTûrÕ5ûc@¨ŒIÂ%;ú
+³„sÊÔbÉɤä¿Wú‡‹*ÿL%­îëf_VXcFÒX8©¿„q¢[†§|_¤pA2tõÏ”²Î« hÅæ¦:=dý'äÔŸ
+:
+O‰¢i<v”ÿôp?SÑÀúµJ½ö/‰y#I¦Tâ,WmJ”€¤X‘”S5Th½Œ(Æ’…¢’(¥Â{ŒåY˜4ÊqÚb,Ó
+¡~&=Ÿ¡;Ðè顺fÑêÁ|üd‘À<国H‰¨n:«°™
+"¿T^ð7MáÔ~ªº‡æ`1¯-€6;\­ESûö©Bo4€Úî6ùq²‡6¿·ˆ¼-Ûþ!oÚêåý— ÔBr€VL%”³ô¤#CS$véˆçÂáÿ¨QIbÖ˜Àrùý* EÌgHžËOÛ™Dr<Hgð­«ûPâ’ÈÅièØ^ -ä%róS‰»‹q)…‚½Q˜ìå/ÊûP†Òá¯Ì’ÏA-’†bÇ”p–±ÏBÏÒñµe#„¼Á­Hc$F8ŠdiÖïØA0d‰G1PÁ¹ie— ‰À°±6¿f—õ‹³ªï'ËÓy²”÷² ÞÞ3gOCÎn™´¯—›&/&Ñ1"N
+þ}Þ–žkjÌñ>‡ÑE–²±5‡SïÝÿ¾z,ë~’gç8Î(¼°
+†\ósì¹Ì¯! yMò(=7É“´yvzþ˳C
+þäo›W˜{æ:†·9àïõˆuy¦Ä_pñÇe|œº]»=x4 ¤øÒ—Aÿî
+”¥ð§8Öù¶Z™ K™pLØ4©núW¦UYAº µ´¥AbqZŠ0Õ.ÌS3Þ¦k0Ò¤þ<52[Kói+<´Fù²ÀÊ‹!bÔq^
+)¼¶>äVRYT%›º‰ŒîJój›åð)È¥¾l­ËeXbñÐqjjl‡†½;â/C£AÎmíφ µM Õí ³I¾±µÊ­6?¶!A¾7LWóh‹4ú¥9ìë|c\¨†œugÛ#
+€¿±\¶4DÇó`×÷’sóqW‡âƒ>ñÁ‡‡ÐÖöÎ;ûì*lzb°ççû™÷"|0Ö0ßæ]Wnwzn¸Ï³9=‘¹ûXµžªMp­z8sÑ¿…µOe=‹_°0ˆL“ô<~ ¹æñËsµò§yô#Ê
+dÿWÀËŨg-ÚG²“†#Ù‘M_ÔùvÂ$í±‹'™ñH æ江wCî½^Z,I¢± ß×MÿÊP*+±ÌA™HIœÒ“SÉj€eÊc™rX¦ÆºÀ³Ç65Ä6¬ÑãØ4²·;dK=Fà¶D¬\ÁÂÃh„ÙPÈìðL ·yø ¨ÚÏBЦ¡
+À3¢MÙé¡J.£çî3®·ø±[
+ðVV4.&md#¦,C8à¦XÒoŒjxzšáwÓ
+¯ßܾzù¯Q¶KƒÎæ>KßbæjN?÷®3sï¸LîÓ×3G!˜Ö˜Ó ={®i×㚈IŒw†F}ûÊ€HÜ©e¨ÑoÿÐ6‘4úkpÝÐè†`(2w^šDEc¹KA<—«¶«êû^Æ°×ÖžPp󘡪4ÉL–Eby–â8Ž†ò?–†fb+­2qØŠß´æýÚÅA@¨© 57„õðcZ—ä‚“8ñ§4Ã’ÕÈò‚AúêÏŸžœ¾ §‡ÿÌn8@ÎÍãÆì úD¨õa{gL±’iŽ‰“k¶|Œ‚n{ÑЦ÷Žñ‰FþØTE{âùuYºú…Èò# © §ú|°)ô~·Ô »jë:œÔXÊØ©œ__”¼$j C®3ëËqéÚ~—wí´ÜÊ`/Wò|·žkÚïxq±\ xÔñO˜7ï«ÎÚÂoÙØÐãWíØêÞp§ Æz³ÆËbT° ÓkÞxž Çðë¡Ü7Í<8í¹§I×apõ}{ñ¨¹¿×™SFlÂê
+endobj
+1020 0 obj <<
+/Type /Page
+/Contents 1021 0 R
+/Resources 1019 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 999 0 R
+>> endobj
+1022 0 obj <<
+/D [1020 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1019 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F53 1017 0 R /F14 729 0 R /F21 702 0 R /F23 726 0 R /F48 940 0 R /F55 1025 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1028 0 obj <<
+/Length 3881
+/Filter /FlateDecode
+>>
+stream
+xÚ­ÙrÛ8òÝ_á·•«"' î>erÌxª63›xª™<Ð$eqC‘‘ŠÇ[ûñÛx ’\5[©q4ÐFßù5ƒüÚèˆÉT]'©Š4ãú:ß]±ë˜ûþŠ;˜µZO¡¾»»zýA&×i”Æ"¾¾ÛLö23†_ß¿¬Þþðæç»÷ŸnÖB³•ŒnÖ:f«oþúžF>Ô֫xˆ·?}üpûýß?½¹IÔêîö§7ë„¥
+V^^ûÓÏïÇuŸo¾Üýxõþn8Åô¤œI<ÂoW¿|a×øÇ+ÉÔèë'è°ˆ§©¸Þ])-#­¤ô#õÕç«¿ NfíÒç´4‘6" °NÈ ë¸ä‘‰¥¹NtÅæwUq³–±YU}÷7ܬÊþ°oʸÇzu·õ“Y]·O¾Ýзü½/÷MVc/]=Úõm^v¬oé[”
+c«_Ö_Žˆe”(%/à¡Ž ˜ßWl¢DèŸáô ŠB®úm‰ ±êÊý·rOƒÕ¸Ye}Y?ßpÎWp…’ñÕ§2/›ž@òmÖ<”7|ÕQ—¥ß‘nïð°¥ân§Ê Íá±€}i¢uènÿõᓽ#¸6.næW•‘4 \¯š¶§F—}³7M+\ÑYp`—u=žÛ¿2&ê²{=ÉW÷·ü©ªkjÝ»EDu]û]7íþ‰P´ý† v©Göïöà$wÄæpx:à™Ò5 <Oc«:"ud”]Ÿí{«;J%«Û Í­ç°Ýc™WˆiÆ «ê¨3Ó"¯ŠªAKi)Nf7k¾ªá‚IYq*+~e èÕ)Ø:¼üNT»Äl9ÕŦU]lŒªëÆëþ¬®Æ __ÐÕ)Øi] ð<ý>ËË#¼2Œ”é¼êï\E•Š þÍß69ÝÏŽtY¹uÌ#¹é<cïÀêÖå·²¦æý3}Û¦<Ã:ž‚W`É%ÖMÀΰÎCÍX÷úƒÖ`©AÉa„Y(¢wI]¢£8xž:uLÝœÁ†E±afNÞç²ï‚|G®VºÈ]/Ø™“ãò÷ǺÊ+wWß²úp†ëÚ »•—¸>;Íõ
+2(²šG‰IùÌêóœ£:Ž’„©9êÿGÙ¾éÇù6;Ã7…ÄoêC·=©èçñŠ~„7¬è3ÄqùÆåY¾='R"†Fj.±fv†5j` šé€2ƒ cR§ÌhF`
+V BÐ z¨cç<LuÄE¼ 0ÌÇêÛÔÉPkôâß*#‹Küž‚æ÷
+ì&‡¸ü<buŒx¡Á,JR˜a~Wuu†nƒ O†m·0.²!\vE¨ÕǶwSý6ë}Ë 5‡Ý½ t` ÚJ¬þnÉí^5y}(|oXU5cœäó©Q¨AL8¹»¯šâõÛàôœRÆè$Ä<LAäÞ| Q(ÊMv€ýk*`æ=Wôúöc
+éô¢kŸ‚ᮇÂBLQAöTµËÛæ¿ífóÅõÖ™ i‘J'Œßªò‰€£("ðVP*#Xì 2SaÒH$RŸ?â
+·ÂS$'Hh¦µ{{²›Pé€8‚B„«ãËÒ—#lùFAn_Ò¨wpv]ÝæÃ…Ej¸ŠÅB‘€¸ôÖ ç¾)ò‹È°Ø‡„º”£‹Ú•Ó5Ed’Hê!¬|]öùkÄÁn›
+´ÈNAã»Ûï\±’ñ(Ö<™+æý¡ªQ6ÐVá®Â‡fpŽ7ˆqï‚RÃÛ1B£¢à„ñÀÔdà“g©ùCÙ”{2 8l‹BðÝߘաi\¬¶t˜7(Í’ þ5òòÁæS°zh\y-¤Ã#K»|_Ý»2üZ&2J…^IÌ,ž.’j Ä cÆ(‚&÷×Ôø4¬<üzº ;íK¥‹|ÔzHi#*Iɘñ=Á’”…ºDÅÑn6£ ÅÀ|®øÜG[ë-ck¢wè8dL¹Žõ~òØ…”—
+ G.rWÕÙÞ-o <Ž´›-ƒ¸H+Î'É~qÊ"ëõË y-Sáªï°} ØÉ¥O°· úd:âaï¤l£äqº|¼yƺ(–õEœœðV%¤ŒÏÌj(â’ˆ‚O}Çb n$ñY_X 9$™,I^º‰ v´0ð¯©ÃX#ÍF*Ü…ËC{Å hÊ_ÁÈ3t- å Pš
+àü8‡}5¾¸àä…)Ðʺ®ÍñYˆîFà‹&3ûGžÊÄó Æ$ȸŽflD„_M&õlu[Û*߀>ÓàHtveÖ¸íý¦÷ýÈ¡¥å© 
+2<HØ'Ö
+oœ{ŸZJ,Dõ`ÜÅË$ ì+3bq=Zyœz(kW ¢Ì º_­iÁ¾;@Õ»µÓkrI…
+IÅ!v!‡
+š* xW½Èäq“ÚݤÞïC¹IÞ4H³çàön Ÿ åPEàÛãøn–}~[è-!:V¡¨î„‡/‰ä·*àŒÄ°£nF’sh«t–¾à2lr P`Ô€¨
+m^p·)÷èž÷ùXáò©‘CçHˆ’ˆ‰A'¨:äsšÒkó¨tuÛ»ÃvÏ`ö~÷¹2R-R Œ€Ñ\Dæ±ÚýˆDŸ*|%¸Á¹+Á¿Åd¼‹­!4cÐŒ¿‹ÒÅõ
+x¤âA¿üA7-þàÊFÛšl’$ãç°Ž„½ò‰­ŽRÃÞÀGc¬vëë„«‹ÀHF[¥fÑî2«U
+¡B5p<º\ÈúòMXëÀB&«Lü’è ØÕ˜ðÏóÖÃŽëé–Gy©€{
+çâÕc¶ïl¼¦b¥A+Ëóò±wí晃Ø*M!…òI’Š—1£ryÎxæ ¨äè @(·žíçjË/ÑŒí.Ë×»B‡ïÈ!sp¢gÅåe¯q/k˜¾Ùßu RçQ&™ãÄ¿gî-$ëÊu¬üóFÞþoàw¡ŠíÄÕúðÖýÖW+ãœ4wL¼ÈE|Ç3—bM©
+!Ù˜Owd©2&? ýi4 ã÷þ(Ù 'e‘ ¯}'TŽ–j¦ÈåÞ#-³g~ÈËü#»à®°^€ª”¾0» È⡺l=—àSÏ%¨r‰_ô\‚¹„ (²Ç–­#Șpá±› qÌ` #yAhg’1p¸v@fåÖ®aãlqò§“fÔ0u¾
+´VÀØ$ ÄÄá;çéĬņŸàl<Æñ')†íè°pp«l7ôhh›øÚ$4Ü5%®l9N¹ÐÔŽ´4pïÖPhŠ#®Ÿ¨é{"ꃤ÷D»¥«ÛÀáÐÆq €¯?ÿdi hÔ`/„]’¥é‚ãûÑäýÖ…Ú“÷Y˲Íó"]™`š‡âà Œ¾øþ6ç(Ë¢Ç#—eM8J•¦:âO¤Žðï pøïäñÿÙÂø×èááRºd1é°#
+Í“%åÃß7“þ?(†endstream
+endobj
+1027 0 obj <<
+/Type /Page
+/Contents 1028 0 R
+/Resources 1026 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 999 0 R
+/Annots [ 1030 0 R ]
+>> endobj
+1030 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) >>
+>> endobj
+1029 0 obj <<
+/D [1027 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1026 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F48 940 0 R /F55 1025 0 R /F21 702 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1034 0 obj <<
+/Length 1676
+/Filter /FlateDecode
+>>
+stream
+xÚÝXmoÛ6þî_!û`ÃQ$×Oi¦îдKœlmW Š¤ØBõâYr³`èßQ$eÙ–Û  ¶að‰Òñîx÷ÜsgÃx<D¡¢Ê*@îÅÅ{sxw6"VÆwB~_êÙltôœ O!ÒЛÝötI„¥$Þ,y?fˆ¡ hÀãóãW§Ÿr<¾<½˜p>¾†K»~ýæôâx"‚ñlúúürâ ¬‚ñÉ‹ã73'ñu'¯ÏŸOÏ®6z&f/G§³îý“Ìô~½ÿ€½ür„S’{w°Àˆ(E½bp†xÀ˜{’.G?u
+{oÛ­ƒ‘#QÒÐQÖ $ˆ+Å=Á
+¼Ò¡;6'«£b™§æ¾Èʬˆr³ˆ«òWŒé|½Šš¬*ÍCýÄIgµ¹Föz[åyuWÿ Csô< =°çS…¤”­åéýÄ1¯Ê$þ­[ý©7zVÎ')ÎM–£|^­²fQÁ'‹"Šý"áOž¶[°“¦­tÆ«´±¢1»¸¿¡¼œž]¯oØu<+nØtþöòYóöç`þ¶¼ÆÓ3²xwv5W¨ûéÙé<¡J¿ûѪ÷·]2F>ï˜6ŽVKªúðyÌæ$½Öyã×éêSº2Ò„
+„áGÏäv´Á¢A/vƒ>’ž;Xp©ª•™-\Mj¿·¹½µ×²n¢<O“.ÕûÉ%#…ó¸Õx”6ñ‘ö‚n< …@kÄ­Á»j;#Fæ¶Y¤ŒE•É¶|"û2äp'bÔ€ì;+*û‚”¡5¬]´0Ló*J<õí«X´ûš
+\\×G™ÆY¸‡]ÍrY­¬€âÌÜÀ)ìþh]§v÷ÂÞ”Qaï4úÊW"Ç­¯:h’˜,i_ÚÝ–nßH^ÅPã ƒªZd¥ø]jÌ™Õj"Çë²Ìʹ} ÕدúîD¥i7V¹Å
+é„—¸óUT wY®S£BËOi™AJò{ó.6å‰2ÑPŠÀ†}g‘"Ì‚wnwm éì·î«5Ô=ÃÊ"KÍëÊÄ‹±”ˆídõ2´Ç„Z ³2Î×˪Lt<÷ÃHHHæÖŸ®,÷gF
+åûÈmMF± ΛGeÚ6xÔÒ<‰’̓C*Ì5Ç%ƒ¨\vHjãwœ7骄æS
+¹#„@Ë1!ƒìTÛ•mÕLæªÔpßÔ8ÔBZ»Ï\Ðüp—ç6ºàS[êë¥eˆHh"
+•êƒi¸ 8”5!lK-ñX*+k°¨’ìö~ÀšVU”?$ì!E4 hÔtmuAë" M5À1óG„à°›äéća¦ïl^FƒhÓ C('骉²6Þd|u>ýÅÜÕv?,h×gá¹'ˆë”ZÔuJýº2;šè£{»LãL06ë(nç»ïœ| gu¼ÊnÌ]¹Ü±¶Õ"µú›<EC x¶Hk›©ÞzP¼qo»Þ°®»Ö;̇Pt…üQ3Ú
+endobj
+1033 0 obj <<
+/Type /Page
+/Contents 1034 0 R
+/Resources 1032 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 999 0 R
+>> endobj
+1035 0 obj <<
+/D [1033 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+126 0 obj <<
+/D [1033 0 R /XYZ 56.6929 424.8255 null]
+>> endobj
+1036 0 obj <<
+/D [1033 0 R /XYZ 56.6929 397.5211 null]
+>> endobj
+1037 0 obj <<
+/D [1033 0 R /XYZ 56.6929 368.0037 null]
+>> endobj
+1038 0 obj <<
+/D [1033 0 R /XYZ 56.6929 356.0485 null]
+>> endobj
+1032 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F41 925 0 R /F48 940 0 R /F21 702 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1042 0 obj <<
+/Length 2335
+/Filter /FlateDecode
+>>
+stream
+xÚ¥XKsÛF¾ëWð¶`•9™7€ä”õ#åœZK{ØJr „´#ÿúížžÁƒ„äT¥T%6æÑÓÓϯGl8ü‰MfW¹Þ¤¹f† ³)7|ó
+>VfwFeÌd2ÝìæLþ}wóÝ;)6’3k¥ÙÜídzlš2#­ÜÜ•¿&¯Ýq¨NÛ4<ÑÛßï~¦mš¥Y*p‡#R&r؉~,?»¶¨JÚñæÃ-ï*7œOU?rš)‡xÖ0asã9h&¶;Á9O>tC½
+[Ô&g¹•6ìPœ¥:³~‡?E)›|øåîý»ÿ]÷ø›&Ž>UñèÚº?Ðçðè†0ß4Ý—>,r½¿,Ò}uú\ÂÄÐÑâ–$
+,ª:®mÜçêj[št{Ä£ª ^/†W‚åƾ¿vmõ/X(•IJ78k¹IÞ·4tÚŠ,©úc×ö 7üu£f'5 i™i‡ ï kujÁ¬ViX¶÷‡t‡È×ÿDÍ MWܦ:y…j"ÌüR7 QÅcU|Z
+ÛWQzo¤ê!ܵWwá¾ @TÒNؤ×](‹ÎïB­…VÇßqª8ŸHií@øpmù*lÜÓ/X8Ž´õP»!ðq—' '×ö{ÒM™ƒW Š„wzO“CGÐWÝî»ÓÁ ^p÷Ýy yÅŒî,uú-3*8œK–½"–^ÕHx QV}qª“
+º¢kèf>/ ûcUÔ¿q.¡Bú̦ ô¥
+Ù"³Õ!?}|÷š¨¯–]ªeô2ÒàV¸òŸ7¿þÎ7%èççÎTž™ÍøàX¡åæp£…dyntinnoþ3r„–)fHXçEû8ð
+dܱdµ‹Òí”æp3µ°ÈxÙý&Çü’A̘’šböÃLÇÆj4gÿ²ÝY‘ÜÁ™¼½Ô ðÔDS¡ ÷Qºùs#×y®hÑŒöwtà¾{›7Üh3»Td¼›sö—,3Oš)ã©2È5†l„Ng¾–ä9VË­„‚´•‹Î|Ý
+Ž…6 0i“‹`¸CÕ÷. !øó|¥„
+?HZ_;µÔL-¸ªè·é\é/l„Hn1¶öOuû°"¯ä
+ǪÖÝ7È?PQ~²-š3é ‡Ý<Á4ö(„A_¹;?ç@V±Ô¤0€×7ËDãš8íŽ]Sk°ÎZèÚÓ늆òJ‹ÊQQ^Ÿb!˜ÌØ\x°yÍ\bȨ˜Áû%¡ì§e‘ùÒeÐný5uX¥Gçy<uøT=íÀÒÇzWœªv£§]Ë!¸Â'Œ¸ÏÅܹÔ[άµÙœwÙ\Ý®i ò™ÙBkèd™ Ÿ‚ßgÔ&™¹hwúµ¶`‚r®¹õ¢Àš|m:Æ!PCm‘ :l±,¶¾Š`¯Z=t³.:v¿1ÐB
+ÐçÍÓôCÕV'wʼnü.·S
+%8 ܇ ’F¨É:@y¬Ú‹i<üä|
+¾àæZÅZÖÍÀ
+@ׂ!z6šMAb™^‹'ÙâkR>3,OΈÀZøŠlIO°
+ù³/‹+'þ¹ö|endstream
+endobj
+1041 0 obj <<
+/Type /Page
+/Contents 1042 0 R
+/Resources 1040 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1056 0 R
+/Annots [ 1046 0 R 1047 0 R ]
+>> endobj
+1039 0 obj <<
+/Type /XObject
+/Subtype /Form
+/FormType 1
+/PTEX.FileName (/usr/local/share/db2latex/xsl/figures/note.pdf)
+/PTEX.PageNumber 1
+/PTEX.InfoDict 1057 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 1058 0 R
+>>>>
+/Length 1059 0 R
+/Filter /FlateDecode
+>>
+stream
+xœeU9²,GôûeË@@Q ‡!é¡%bd(dèúʤ—÷ÿ(žÑ¯
+’$¡T¬)ÿ®ïë¯ãïãÇ_¢ýþÏaíÏc‹®½Ú¿G—=ûÌöÓ1ÄF¬lÖ]töö×ãqu‰Ý¦‹÷5š”<8Ç—ý:\;âúãñ‰ü<q¸Í;.\ži2c¶û~ð¶e¸í×qc¸=7Ä+Àg ¯ãã×ctéa³ÙL1ca·cu™šm QOƒ½¥ì-¡{wñ¨¼&kñÄÞ
+¨9xcH
+¤Ï’Ã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Ù
+г2"ïE9~ 
+n*Œ1½÷¨¾x¥Æˆpîâ‹&XîÃœ§³±è\íD¤ßä0}#XŒûž˜‹¸À>#^V°¡|2Îi‰9ÊÎr)`˜¢Xh¡Ò& „hb—H°Œe"Ãê
+þrÓGçX5¾ûû8‡´ÕªOª«t–Ô³$Ây°‰—BÒ›ÀÄ5©/¨vp÷o`kA“ôr ±ñœÓ4N.4Žæ
+endobj
+1057 0 obj
+<<
+/Producer (AFPL Ghostscript 6.50)
+>>
+endobj
+1058 0 obj
+<<
+/Type /ExtGState
+/Name /R4
+/TR /Identity
+/OPM 1
+/SM 0.02
+/SA true
+>>
+endobj
+1059 0 obj
+1049
+endobj
+1046 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [470.3398 477.3512 539.579 489.4108]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1047 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [316.7164 465.396 385.3363 477.4557]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1043 0 obj <<
+/D [1041 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+130 0 obj <<
+/D [1041 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1044 0 obj <<
+/D [1041 0 R /XYZ 85.0394 580.0302 null]
+>> endobj
+134 0 obj <<
+/D [1041 0 R /XYZ 85.0394 580.0302 null]
+>> endobj
+1045 0 obj <<
+/D [1041 0 R /XYZ 85.0394 539.9341 null]
+>> endobj
+138 0 obj <<
+/D [1041 0 R /XYZ 85.0394 315.9171 null]
+>> endobj
+1054 0 obj <<
+/D [1041 0 R /XYZ 85.0394 282.0038 null]
+>> endobj
+142 0 obj <<
+/D [1041 0 R /XYZ 85.0394 146.7217 null]
+>> endobj
+1055 0 obj <<
+/D [1041 0 R /XYZ 85.0394 117.3479 null]
+>> endobj
+1040 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R /F62 1050 0 R /F63 1053 0 R /F41 925 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1064 0 obj <<
+/Length 3348
+/Filter /FlateDecode
+>>
+stream
+xÚ¥Z[w£F~÷¯Ð[ð9#4Mþ93öÆ9‰3k{/'—‡6 ‹ …k4¿~«ºªHÌæaè{W×å«‹®ø W2ñ“,ÊV*‹}„r•ï®‚Õ+Ìýý*ä5k·h=]õÝóÕ·wB­2?K¢dõ¼™œ•úAš†«çâW/ö… 'ÞýÃûÇÛŸnž¯UìÝüx½ŽdàýòóÃ-µžožînŸ¨û[ ƒûÿÜ=Â7¼^ GÞûïo>>ß>Ò|̧Þ|ø×u†ÞÍÃûÛ4õáϸ»½Á»žÿùxûtýûóW·Ï㣦/úóê×߃Uïÿá*ðE–ÊÕ:fY´Ú]ÅRø2ÂÔWOWÿœÌÚ­‹Œ ?I´ÀÉH,qRf~"`
+9ù¼-áY‰òLÙ½•µU]SKצ¥V›çÚTm£ëúÈ«ºªçÍÈ×ߢ(.†Ý¿Ä_œéÝùy»Û×e?öš¾lzÃgoÎûB÷eA/mc‡S¯gZ*·ÑN €ë0ô3)#ûªß‚ ªKf,$<±ÂåYä¹oÓöÔ(èhœÚíÊ¢‚Kíë²ÐÓ›Þ²æJoyý±Ñ»*§ùô(ˆ¼—2׃áÃú­æ íPtà‹›l[j˜º=ðªmÙPK/½¦ÖÝu˜z¯x@”9~@˾¾'vAgc—À_x ª±O4Þ7¦/uG"ffG©‡B›ŸW”µ>ºó^ŽîúZ!À7”ôÝUÍЗƞ*@aàUUóJsº(ªÞ*Íü]dÅD¶!³²ÇâW*©µ¯u2tSÌ•”ößįH¿à“œ”†èÒ#6˜^wÌšd”©Û(=³ú¢=ðimGëòN›­}P
+0B
+‡cG.º‘'`d›'Ï O0ú:hàN_ÒqõhKµeH–°˜3åíZ+æÌékܧþÄ
+'9™¬â,ò#&ÉMv¯+j<N²·qýzºá2{»<¹öëGzÈܵC„ …$Ð:“ {Ÿz0rå…ùýœè0ˆý8€¼;N!Ñ “åDs\µž.»$õò´‰¯ãW!8À™«£€^ı§óÞJܶ éÃø¹7æ\~wÿð¦2ú˜aÑuÏÛHÚز*Œ k°É16!ýršC‹¸Ñ@ÐdŒîŽØ•¬Ç4î oabQ‘7bÚƒN ¶š%BH9Þ4©/Le P--1¸¤Éë¡àŽÃil;*aûb<ŒóP/q
+cKüž|*,rÀû°Á†‹ótÞB¢qà€/²Q¦ÖAÛ\*ôÚw3SFXûÔ¼£Ô)8Ü;ÑŒçœ\a•Í11køè;Ç[xFÇß-U×îË@¸!(ÓƒáÍ`C;„© ”À8‚ä ƒ$çÈ ‚„ˆ[XÅìƒ`˜QløL 68µ·*pé.E šÄέWŸ){Zoºv·.àè
+äd5Çwí×óŽ™-G€ú¥zjÒy¤fŒ6ïhÆ”%5Hpmiò®ÚŸÎ±ŽW,T€õAš9ÉtXÌ1ýÚjÊ¥ˆ¤ô¥ÌœˆòšóË¿¼E*"·˜÷q åòxøa(¶šðCŽÅ˜œèKgç±Q̱ÑȤ?Tÿ2Üy*{Ö%@ L×ð{²+8Ìkqø­*(ˆÕV¸vÌT/Ü9f9‚ù"¸èb¶¸‹ ³·µÁEü‚•”Ø
+‡TT”ŸûëÐg”«‰´5EFv+C˜¸ a´ žB ƒ1‡»Â#ü©,øíÈ&œJ 9`{$ÇXX¼ÌØ8öS¥£´ûaÏAýóÉýÙ»Nëà5TÒŠ™VmÚÆ0y M½ê¦úâlF]ítÓÏ_FÈTVŒ¹¦ 3L>²)ôS€§³J€KÍÿg™çg ñJ`Ùyg RSúiŽœ L§e8j R6êÀ.ÕýqÑ|׎™
+%8LVì ” *Œ
+& âN‰°Mó|®8Ø‹iK…mØš79K(H~ꊊéØiA-j’~+¬üâ–Œv(9•8ÎV¼Ó´;)Ê
+##¸bV¶XÝom|‚—ñ×–¬p5qfz*xŽ°ØžØ_
+AîO†–H6ÉDžÅS0P—ú“¡¦cZDß-“b ËЯ¿Uš:%„$|ÃÒ 0UÄ„Ìň¸â³Æ_*ø'" “ÇÃmI [F¿½¿&p^:ÿ'³€d†UCÜHµ*{œtUhÌ_H3GZßØÚŽQÄ6[æ?ÌïJˆ`PªByß·´V §Êƒ-9ßQCÀJÀ.]ŒVæ<¤gXÇ‘Š öao’õÅ®$ÃN©7ê¢í¸j)l€°˜’BálÑþ°B §ã\YNcʾpAÛ@8ÎF}ûßBÑ#,&Æ,¨’qÔP¡‹V !¨ër) SÔÈ·-…ÅŠÓ\øn@ÓÇ!/4Ù¦Ok÷üª½º=¾Æ€@J4Õž†Ð{1Mú"–õf~àÅÏ,¯¡7„7ŒmW‹¨xÓ°ê` :"£HæÈs„Œ"™ £„Œ.¢NƇ 6V»@Ý⎺.j¶äCßþ:DCÕ‚`V -cÝ«FgÃ/å¶jŠ¯þÞדߠRÅ8hSwD§0 SÆ:vô*²øàä
+^0d~œ,Ĉ5ˆF(,Ú|ÀÈ­]¼ÇýÆ|BÎI„@„qHð°ž7o¬*žQ¶A4ûÍä…õa0îWWÍvb6C«—~ÙiÔ àÙüw—ñ×:WŽŸˆSNœ“ѽÆFxBùi˜
+ú!G‡·½\@_x¥ [¾5&~(Š7,ûol
+©mø¯(¡Ÿ¡AAÉM@rgJ'Ï¢«P
+ó§ñº«¾¸Ë8‹W‰=öÃO¿PÚ¾
+endobj
+1063 0 obj <<
+/Type /Page
+/Contents 1064 0 R
+/Resources 1062 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1056 0 R
+/Annots [ 1067 0 R 1068 0 R ]
+>> endobj
+1067 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [464.1993 488.466 511.2325 500.5257]
+/Subtype /Link
+/A << /S /GoTo /D (proposed_standards) >>
+>> endobj
+1068 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [55.6967 477.5271 105.4 488.5705]
+/Subtype /Link
+/A << /S /GoTo /D (proposed_standards) >>
+>> endobj
+1065 0 obj <<
+/D [1063 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+146 0 obj <<
+/D [1063 0 R /XYZ 56.6929 556.0057 null]
+>> endobj
+1066 0 obj <<
+/D [1063 0 R /XYZ 56.6929 521.4772 null]
+>> endobj
+150 0 obj <<
+/D [1063 0 R /XYZ 56.6929 361.9951 null]
+>> endobj
+1069 0 obj <<
+/D [1063 0 R /XYZ 56.6929 325.2573 null]
+>> endobj
+154 0 obj <<
+/D [1063 0 R /XYZ 56.6929 133.2872 null]
+>> endobj
+1070 0 obj <<
+/D [1063 0 R /XYZ 56.6929 104.8892 null]
+>> endobj
+1062 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F55 1025 0 R /F41 925 0 R /F48 940 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1074 0 obj <<
+/Length 3001
+/Filter /FlateDecode
+>>
+stream
+xÚå]sÛÆñ]¿‚o¡2æå>CòäÆJãLâ&±Úfšd¦ ›¨)€! Ñj§ÿ½»·wÀI©™>u<2îc±··ß» ˜qø'fÖ0®2=K3Í f¶º»â³÷°÷Ç+áahCýáö곯T:ËX–Èdvû.Âe·VÌn×?Ï¿üúå÷·7?^/¤ásÍ®&áó—¯þr-„˜¿|óåÍ+Úzõæ- ¾ºyyêù퟼aµ±ð^xóí÷ß¾¾íßøõö›«›ÛŽÒø6‚+$ó·«Ÿå³5\ê›+ÎTfÍì
+¶û7Á’T8_9äUÛ
+GźØÔ{áÁ2Üxº-›_ß” *£4^°Ös^8”H!.7EKK÷;ÿîÁ#…†–p\Aý oíQ Ym³ùŸªb„Ìã‡ÑÒoÕþHϤ<Ÿlǘ¤Ùün8HÎmã`à‰XØëïi§Ùå«Þ4ujŽûÝ«5Œö©ÅM¢—–ª¢eÞ´eíGB¶J ʺ)WF§0ùEJ½s õÇGœ /KÞÔ!+Ø*¯üR¾ýàG5=—5šŽIÍP›Ê€Ê³íEЭ‘²½úîo“ªEfi¶3/aœØ NX^zàU]ý¹|O—_ÓªÓGx¾«÷bËšäáýßî‹}Y8å´N±k;ò ZDL™©$ .´)ÛB°ŽìckKl"=ø‹ Œ mãÝ~¬ˆYþ>Ì)©PJ Š ,q¥àài…Í:œ ’#— ?Ëc>È'a!Gqi™ŽhpÐq5(ÚMz Ç"™‚8ähR "‹=Î:´8!]Âùl9ïU´E
+î·ÚÞ¯Ëê½ÇïbЇ½ð™Ð1J5màŽË†»Hé’Ö)qâx¶Iw(N•Eñ ÑGÚ.•u绸|¿Ü–+”݉N¤#.¸ZqByÁý
+Û9S§¼¦$K2¡/él’rñ,G–Wð¯¸\Ó0Åd}H¶þÜo×tq®²ö0Í=%0bž7ýeÝ2Ÿ–ˆ¿+Ÿvú7½óE]
+Ž“v¢N‘ Rëu‰ÆŒ¬:3äA7&ãP¢?Á¦ãVʳw”œñä¹&!WÆ&E×h6dHHº¯0quW¬Jrv|þÝO´x$w\tÙ=…¨£²ê($¸ºÔ©¸¹õªËšÑ=£ÚüýÓO‚ré)åÒó] aŠ|8¼C1B_®#_»Þ—C´2Á]`𘪢X»¸„¯«üÞE
+õ’Šc"DŒdñbTnbBÂëê8¿¨i@Têuï÷b3TyúBá9¨7…
+/ª}µX ϶N‡ø¯=™Ÿ4!µ¤§·¨a)šwŽÙ‘àsȳÏ'ŒŽGûåškŸ:šÀfØ,ÕÊ£ys½H8aƧàô š:Èû§ºq‹€tpÝ7¨`J_—Ó¨x¤v–v~•Ä‹#—±8ƒÙäÛw~Í?AÓ]È¥YYuÃB—6Á¬¯ß•Iz >-‚‰ïàÐgEîÅbRC]>ijù‡ÊÝŠgd?]ãˆÛÞ~pÑß©ÛÎùo—.´MÈÑc[gØÂÔ ë@ qQKG¾DØûíµ˜?º²Ë¼uß­·úB‰gÇ$r8GÓŒÍÏñiØXñ
+<‘šGPÎÁž0ÓQ ÏU®QÓ%>d•£öxw½{¤yÒò~è2«<;pcVÅM]Ü },åûXèj›Cähpç‘ž]²7ÄØçî2 í3XîËŸÿ¹Õ(,xbSz(œô…‘Ç
+|_æ«]ûôß;N]W—¼hs²½*!DÚŒSº¨0¾‰Wk7ªéé;•0Ú]», …JXÌQ¹;Í–RÅlØ®·ïPS„ ¡wlÂŽ5´ƒ2N<ää+ á`ÊvE±kqOä?³‰
+I!ñNDÅ/e¤ó=mEû$…÷
+Ĩ ìSgyT©¸¦y32ËÛ>xßUP‡2Çm‹U[>xHäÍÈõÄ&œí®ûøUÀ ‚Ãv
+“7 `©gŒN¡wbAÎÇü&ePÁ†¬¶ÿL„N|&‚š
+ä•Pn»ÎK0‚:#Á
+endobj
+1073 0 obj <<
+/Type /Page
+/Contents 1074 0 R
+/Resources 1072 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1056 0 R
+/Annots [ 1076 0 R ]
+>> endobj
+1076 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [417.8476 181.7231 466.5943 193.7827]
+/Subtype /Link
+/A << /S /GoTo /D (sample_configuration) >>
+>> endobj
+1075 0 obj <<
+/D [1073 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1072 0 obj <<
+/Font << /F37 791 0 R /F39 885 0 R /F23 726 0 R /F41 925 0 R /F14 729 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1079 0 obj <<
+/Length 853
+/Filter /FlateDecode
+>>
+stream
+xÚÕWMsÚ0½ûWxr‚ƒ…¾üÕœhBÚf:™4¸½$9¸F$Ì›X& íô¿W²°‘ƒ€PÒÎt˜Y^½]½}+VȆâƒl×^ˆCÛ)p!rídjAûN¼û`¡¥S9ºÕûÈêßAèaÏŽÆV
+ùLšó'ÀŽäÏ[Bì½eK¸]—q¶Ð]»PïØ8ž§Ûš?Óe„¸@Þ WØðxðEeuG£> A€›;HKôØ
+endobj
+1078 0 obj <<
+/Type /Page
+/Contents 1079 0 R
+/Resources 1077 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1056 0 R
+>> endobj
+1080 0 obj <<
+/D [1078 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1077 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1083 0 obj <<
+/Length 1946
+/Filter /FlateDecode
+>>
+stream
+xÚ¥ÙrÛÈñ_ÁòYeŒ0ƒ{ý¤µd[›¬ãXL^Ö[®!0$Q‹ƒÆ!™IåßÓ=Ý Ú7¥*ÍLOOß(—.üÉe×Küe”ø"pe°LË…»ÜÃÝÛ…dg@rÆX?nWo¼h™ˆ$Tár³ÑŠ…Çr¹É~Y½~wýasûqí¨À]ùbí¡»º¾ùçZJ¹º~ÿúö†®nÞßÓæÍíõ:òW›|¼EˆT ¾ øåæþîíú×ÍO‹ÛÍY¾±ÒõP¸/‹_~u—¨òÓÂ^ËG8¸B&‰Z– ?ðDà{Þ
+6WWhLÛ5yÚÑiDP§©i[´íH)’ P# “öM›×ÕwóWþ³ü/Dgø
+!¦`9Ÿ“GÀß(O$èb„þ«®XÍmÞ)ÌW] #Òº|qVHzcKµƒ÷…~à­%…,®öÝéÈx¥nÁ¯æÛåÝåɳ«k+Ë«9É]£«vgšïµÿÈVêOØJÍÚê0€µÙéß^ßÕŸLÙN×UÝLóy w?ŸuÛ}.õik¦šÏÆòŸ3åZòê äì%µ'…ù¡Å¹«¨hØ„<É}5?Gˆ YR`‘j7C8Œ…ò}ɸŸÜÀ­¢m¾ôùƒ.LÕT¬ñµ6ÐnH¡Å?Ìæ@U‚º7èYž­ÑMz »|“¦d’J—¦5ÍÃ`e)!CÿÕœŸG÷¾ºÏ“Ké Ï»"
+-VÒ¼;±˜ ýñîý í]7gÇÌ´i“o‘§'ƒUzÐÕ~8 vÅÀ±·uõÉuÕ¾o41F B
+FÐüòÑÅÈAw3,4iLÚCÓ&#èc7Y¾C8¦-^WLog.†{9Yy•}F~§ÁÑ>ªm×£DÙÑš5Ý]ÞL¬ €ß̉é*£Mß>Þæû©{ö˜wÚ‘“É!eXÉñP¢
+eS ´™¶&ÐÖÐÚ·f×tKn`v‚:–§ŒqÌtgЮ·º&ùýD‡³SÇ$ô7”’Á]øäP÷EÆÂÕUG!Ïb<?ñÙÌbÎü(¹G( J(Sž_‚—úŽÀwö>`Föf"^æ-¯UÛÛÇ‚’æß`Š0ð&!@ætìê}£e^òÖ>ÉîP¥3‚lO´’ÿpgeðØé†Õë¦ÉkîVœÈŠ3t˜Qû–žðbü  öÔ²‘¾m-~ b•DŒÈRRå™#§öT´‡\Óf~|@6IbÅdßf8Ë@Dž8cZÎŒ!®}ÿLæ4CÆÑ>gâ'ƒ7Ö“s1,òŠ«l}ì83ñÀcJ^]Ð T?Í´ w³††QD(é,!â9MCºQÈ8â2 ò‚
+ÌKÔÂKàÔUÃd $ÏoMeé(ÎýA7†Õû˹üï•nuÊåüƒÎ›©&ï`Æjç§ ’Æ<TAÎ{ž9«/ φæ–P|Ïâ1šÍYX±à ÚS2[Ó=S‘^2ö¹J„繃Óq"”3Ò*_$nò4z¦”ð9ŒG„Ô!Ÿ(NÎÞÑ
+^Ebêf›C“Áš‡Gô¯ÝàÀ7Õ?ú¦ú¦rSª+a~žÄä'¥|«ŽcexÆ ¥j3Œ–nˆîʾí88Í“¡¡=# ½}[}y´b&fqšŒ Æ¢ècç(»î»º„&œ:þ$þý€!BìøYãf2JE8<æ8‹án‰g8iZ¤Š°8pä”!í·§Î £g²z÷óõkç盀Nd3$ÒÒ:Œ‘ÌSoëÛÉÂhõ×ƽنÊC6ˆa Äj70ê*xc§mš_âç^Ýæ
+M>1:C‰õ¾î¹³S©:nJý5/ûò̃6ðEµ·n憥 R±Ày‡ßˆ*Q$ÔLC-ÈKúüE¦»a´NE\–Ã,Ô ç2,’ðq=c³>å—š–‹c9Èq@ãèôãiP§™¬j¡â8ðâ…>®Më¡Ô©SfC·üé¥b0ú»¿ÝoøÁ(÷žû%Î þ|6ó»™{®×ÿ÷¯t—Ÿ%ýút¬Î?ÀMòËsCjÎ,ÚCyO%?ÿœ÷­èÿ¢ „êendstream
+endobj
+1082 0 obj <<
+/Type /Page
+/Contents 1083 0 R
+/Resources 1081 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1056 0 R
+>> endobj
+1084 0 obj <<
+/D [1082 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+158 0 obj <<
+/D [1082 0 R /XYZ 85.0394 427.2881 null]
+>> endobj
+1085 0 obj <<
+/D [1082 0 R /XYZ 85.0394 390.6298 null]
+>> endobj
+162 0 obj <<
+/D [1082 0 R /XYZ 85.0394 229.0656 null]
+>> endobj
+1086 0 obj <<
+/D [1082 0 R /XYZ 85.0394 200.0179 null]
+>> endobj
+166 0 obj <<
+/D [1082 0 R /XYZ 85.0394 151.3455 null]
+>> endobj
+1087 0 obj <<
+/D [1082 0 R /XYZ 85.0394 127.291 null]
+>> endobj
+1081 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R /F21 702 0 R /F39 885 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1090 0 obj <<
+/Length 2296
+/Filter /FlateDecode
+>>
+stream
+xÚ¥YK“Û6¾Ï¯PåbªlÁx|Ä•Ãx<v”]{½e/q”DItøEj&J*ÿ}h
+l$#¥<ÅiH$er´¨®èh cﮘá™X¦IŸëõìêå[R’F<ÍV½µB“„fË_˜@Æ° fwÓwã g<¥ÁÍ×g·?CWR`A†ë7ÿ3Æ‚ë7·opè͇;l¼½½Ça0ûåçÛ»ño³Ÿ®ngN¾¾Œ
+%Ü—«_££%¨òÓ%"Mäè:”°4å£ê*”‚ÈPK)¯î®þíìê©^›0J¸ˆ¸Ç(\øŒ"S RF™mrP ìð{~ÀFѪ/ ŠûåøD)/s¥òË·!ë-œ
+ÂY¨äQ+þcÓ´›¨ÿ9yÎdüœªd»+î³ÎÌÆI•vðA(Xð¡é6E½Æ½—ÅnÌ’ _t¥sßæ­ЊŒ¾O¥Á|߀MG'D2°ñ„1’JÉõvó¬Í'QˆÎÍëE³Ì—Øi»
+
+{èéü¢ÛYmxÁ<¦•µæk”ÚdhJ«d¾À~÷½G¡ ‹cÂÇR§Ø$+ÿ3{y+o>¿Kÿõ¼iÙç/4㟗×?üàQ›טYùûf>cWÉ O„µØ7ìÉBABH‹¦~l/gßó#fÇ¡ÅRIbÈÛÑD„p4v‡#|<a Áû¬Þg%.÷.¯ó]ÖMí·—*[{&ñP$õDÂqŠ^T[0@Ëð³ƒÑ!¤§}ÙCÄ›E›RçE×Bñ°Ÿ@×ð™„!*Ídðòé×w7Ó©YX»´5£hعÏÊb©Ó‘žKC‘ 碒fm»¯0J`¸³v(ózÝmX´==“ Ú—]±-º%YÓDÑk4ObÓÄXW¥Ý®5Ü}T €DÌX¨m"%}×x´8ʇ•Ž -ôÖù’¸Åzt]¶#fZé(~¯›‡›.« »@CïßÝ8 ö†ÖmðXÙ¯7žpf '"J“AU…!á UÈÑ0v9Úìpu#bQf†¶Å ×»¬2"4øµêa]D@ÇF"äY `ÄжˬˎéFt À¾Äd‘JE›ˆ7Íöà—ñwàC›íwà1ë--'|_7:è¤Jä€ ÑåÔÕñ™D§‰_†@ÃØ.šmŽ4²ð…ƒàà5 †ö."Õä1SYÝn›]‡”*‡®‹¶26;\Ú]‘¦ÂX-‹h2XX¾Èñõ6ó„óÛÙÇ1TQÁ s2¶Óêò2ßnš:7ý¼[|Ý5¹F×LëU³«<ÎÉw÷˜šÐÑFê2=K0$voÿ(ÚNq—4­²5xù
+`éJÉ9Äo©ñJÛg­‚¹d„RiÍPgТ©WÙ#€ë(²¶ÀúÄ[]„œ‘$@ ˜&ÑüºUµE¿DÊ_:mü B1+×Í®è6•™[e‹Iµ”¯ÎÂ*§ãw窉ïpêäd7¼KüýÊP¨;¢µ ü(šªLYèd3]åÅÖY~%A´ ©ÝoUz+÷)úü€ä×Óo’Ün}ˆQžåsqèbÄœ7÷9ñÙë®ÐE‚ˆBSl«–ýfê#{Û*µR]ŸO¦€o„è8Äå2Öƒ þ<' r‚ôIÕ…”CÖ¹‘¹nêÉC³+Íž(H¶ÌæxWH…F+ÇLQ1ˆP7HÉù‰ûבâ>¸'ÉLåÝCuûb<.äÑ0ýì”{·öüà3•º‰ÁEø –‚;`»lF¯O\_(ãÉI™¡‰ì=K€7EÝé“Ý>0ŒHi
+C9¹‡h?ƒÆÃxÿ¥Í£òE
+mÀ·lr3£n:ä‚€ë2ý
+endobj
+1089 0 obj <<
+/Type /Page
+/Contents 1090 0 R
+/Resources 1088 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1056 0 R
+>> endobj
+1091 0 obj <<
+/D [1089 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+170 0 obj <<
+/D [1089 0 R /XYZ 56.6929 691.7741 null]
+>> endobj
+1092 0 obj <<
+/D [1089 0 R /XYZ 56.6929 668.7722 null]
+>> endobj
+174 0 obj <<
+/D [1089 0 R /XYZ 56.6929 579.8329 null]
+>> endobj
+1093 0 obj <<
+/D [1089 0 R /XYZ 56.6929 549.1878 null]
+>> endobj
+178 0 obj <<
+/D [1089 0 R /XYZ 56.6929 502.9124 null]
+>> endobj
+1094 0 obj <<
+/D [1089 0 R /XYZ 56.6929 474.9173 null]
+>> endobj
+182 0 obj <<
+/D [1089 0 R /XYZ 56.6929 277.7919 null]
+>> endobj
+1095 0 obj <<
+/D [1089 0 R /XYZ 56.6929 249.7968 null]
+>> endobj
+1088 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F41 925 0 R /F21 702 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1098 0 obj <<
+/Length 3185
+/Filter /FlateDecode
+>>
+stream
+xÚ¥Ùrã6òÝ_¡·•«" ;O'™“¬GÙ­T&´[ÌH¤"Röx·öß·/ð2=NÕ–«L 4¾!½P𧩠”É¢E’EUÚ.6û3µ¸ƒ±oδÌYùI«á¬×볯ߚd‘YÆ‹õí
+n^l6®i¸}YWí±Þáùa3`½Z¬Â(È"ú×ïÞ#[S½Ìw»ú—§áòÝÏ+Šã¹N—€×5ª
+nóêÎÉü¶fØãosp›ò£R!ÑÊŠ..àFáp¸*Û²® bfzõ€^é@Ù$‘^¢rÅóàý¼0 ’Dg2ívS$i$ãžÜñqK˜$ô›ý1ƒn#‘áXÐܺã ¸òPgÑð¬"«€b›-VÀÔÓ¡È[7‡$6‰áÝÌÅ&A¬;ÒŠ’ïmÓ–÷®0Ö,×ÛYÛå6§Fæ*n¹Ï­«
+º/˜@
+Pb7ƒDø
+?åcFs¡FwÊñÂ}Z4™ <QÒ,’T1Žâñ}ÿzž…ËúÄìóG‚ª3ƒ™ ¥ ³§v†}Ís¸w¨Üñö´›9Oˆb¡Y¿:Ô»ró8sž ˆñzÚ´0yï<u`&'+Ò`‘¢0Z€rÚ€ßÁƒÇ»7®Φ›¿.`g3$ã)^$ç
+|-ZaÆAô„¤4X·IO¼^7ë%Bž`CB‚ŽÏÿ¸Š”
+²4´‹XÃ4ŠÒÎCÆâ!¯ŽÇúؼìöØZédy K®Ñs–ÕÃÈ<èØ[<€t‚í=LÍÙóAoC6&‹Ÿ<íZ ‡Kݽ;æ;î¸#owD“féòÝ-äÏî#ØÞ¥aQ r¿²ª+òŠdÿþD΂]~È;†nãŽ@ÆO_! #D
+!Ûè+h^ÅßSõ©ª*^…ž#|ฉRf3Âå®
+J–Bè<"Ùf†ce»…YF JhÈñŒD;ïÄš»›ºp<­q­ ¨ùûúâ ¦HoÀâ |s^á·Ð#B·ã ´'4ŠWë¡Ó N"òöÔí¡b8(*ªQɲ¨ 3ÀH¡tŸïJtMÈçPüÂ'|†%Âg»HÇg‚
+a´¡ ‘chÀY•Œ8 ƒÂY•ggÔ™øYä3` ¸C,ŽbbRäQl YõŠ‰í ‹ûÕ=‹¡#'‰,Âʽ A@Д…ïÜò—Ï‹Ó1ò¢CÂ"Ê„­qöÔL…3Õ1Y+Ïd­˜Éº®x”Óþžt'Y*²àCCWX¬½ðj6ø¦®ßýxõ÷ȲŽvÃC dåD|ó„ΉyàkñANÀAÕ’@("„ífOx€vžÐð¸(Dmˆ³È|¸PI$)Ï
+©}èM¶Z¾ÄØKʵúÖív{ÒFœâ>£LÜ9ObF‰Þx²úK¸OËNˆ;µ¬Êïeïœó$๔/G{¢¥¤]ù®ÝÖ§;¤Î  .± wæ–ÐåÀ—•ÒÌÑÃD·áh¿1 ƒÃ2Šñ Å?øù7\ k49»õÖÍe¿~EY—
+È„uÒÄÝIv'¬‰6 lO<U~ãŽ%UÁ( Ék8º0’ÞNïñC4eár5 y©ºÐ§w+«5+ä`„Ú](f¢ô&¢ÂŽ–­|e.ŽÅd²WLhÛ-“7ŒŒ*Ϫ†¶°ó‰•V©¼4@®À¡B¦|ÃQ¬FS5%^^ܶdŦ‘d8 åØW\A¹a' ùšò“‹Å©ì pÌUâN
+cýaÒ±ãIׯª‰ÏñNý)yQhTŒ—ÈKmjäÁ-Fà[Ÿ‰ÿ8aÛG&öRPÎ~©GáôáQàYpb)h ÈHî¬&{@’*âCbÚp̆¡¨}1Þ—$ð}î3eÍAà/A¤¶D‚´Óƹ´9õ±•bâ›÷>\]òÈh¥×­Ü׃qñ°à (èe
+Î&ßÏ&ü Ù"tíM6t¯%Í+ï‹Ëûrçº(£ |p÷ÐvÏ6G Te÷Ó?ûÒ}÷ˆ1z–™­
+endobj
+1097 0 obj <<
+/Type /Page
+/Contents 1098 0 R
+/Resources 1096 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1105 0 R
+/Annots [ 1101 0 R ]
+>> endobj
+1101 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [418.3461 611.3335 487.0181 623.3932]
+/Subtype /Link
+/A << /S /GoTo /D (dynamic_update_policies) >>
+>> endobj
+1099 0 obj <<
+/D [1097 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+186 0 obj <<
+/D [1097 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1100 0 obj <<
+/D [1097 0 R /XYZ 85.0394 749.4437 null]
+>> endobj
+190 0 obj <<
+/D [1097 0 R /XYZ 85.0394 597.4103 null]
+>> endobj
+1102 0 obj <<
+/D [1097 0 R /XYZ 85.0394 573.0707 null]
+>> endobj
+194 0 obj <<
+/D [1097 0 R /XYZ 85.0394 410.9267 null]
+>> endobj
+1103 0 obj <<
+/D [1097 0 R /XYZ 85.0394 378.8211 null]
+>> endobj
+198 0 obj <<
+/D [1097 0 R /XYZ 85.0394 204.765 null]
+>> endobj
+1104 0 obj <<
+/D [1097 0 R /XYZ 85.0394 171.4256 null]
+>> endobj
+1096 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F14 729 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1109 0 obj <<
+/Length 3252
+/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¹À–` ÈSÌi‘H© ?âÍáyß·O‡r¿©W “"Ÿ—Ç~ãš¾^•}Ý6„k×øÕ,8@Ôͺ=ìuGß}Ûuõrë¨Õ_Ëùæp-í¼=>m·áÎ8Ùƒ[uÿL­Ÿ…ĸ*Œ«"O”²v€ŒÓKX÷r“ hkdR˜P"Ñl‘inªíl!e“ú~÷©wM;é^*ŸWîg!ÒÆUØLa¯ô½û5Ï„RLʸqãʦ ð¬Q 0µ—ÌÒ¹‹(*×­õÒuÔ$ÑÊ Ï•'Ê8û±cPîN„]É€ÈÌ»ú‰vðïmãº$Ž°`nžþ]ƒ ‚ªýŠ•;`SÏû–Ðë qÜ¢¤fX†h@ž_êÃ¥@&*¸¡aOyjÄ™:w¨qÿž‰5ãz·gÔG0Ð awÇ®'ä’ç[·ÛmûÑU ä̘ùWïÞßA1 )¼ÛÔqÖºßæ?¸C¹Å†]·[¦è7%/6b¤_mÝš‡ìÉâW®ëxû‘y3žÅ}Úo˺¡©ò8Õ®U®/kflé`Ÿ×E:÷;µ¬5˜u»2‚UÙ9oÕyámÊ•LŽJ–%i®ŠŽÊb3qšÀëè"SLÒîÙs ­›¾#¸¤Ïúœxh[£–Ò<#ïäå¡Ü¹Þ:< ZÏß·½£.’2AŒŠŒHÒ‚$™ßŽu®ýêž½¥"Œ‡xë::úÚ&6SzlÞ¸SKf”²*¡í§CÄÇöðkÝ<¶â%W}{x¦þöp6à‚Æλ½[ÕÈ‹×2Ð,ŸOƒ.’Z ½ÐA#Õ”Ft’J›Ž4‚––r¸
+Ûí¹`ÕȽ«H6JˆÄäÆŒ…CG]'„Š$M>H~
+K‡8„ãª]Ý€±JPZGÞd‡DûrÈžwò_´^fSo+"C—Ç#™˜¶évu?åˆÐZñ g¥`ðËüøW>”*r§3p…eäÞ3`ýNS7nÓ;yD?šc­³ÏëPÏÚïP%µã±Ԫܗ˼®Ý~p<¶8ásúõ³Rļöþ€ªìK<öR„ˆ½¡“ņ1L†²g\³bLŒn9D®9u¶L‘d¹µ!‡x˜övY¦ ŸfŠ<sÆYå¶î)ÚpÚ‚[$ÛEÉ%…Ìòa¨}ëÝF–Î[”ý@®á½_Âo%’  ïý`8ä
+Éùó×®l ÷¾çùNê Ù´N”±Á3Åeévn
+6¨ªéà\/`ßO®™˜1 ÍŠºr&ùùn|`(ýð;léûDŸäÊÞsam’K3ö¡èm -&lØfyÄ&EßÝ@úÑP#ö{•"];=ž=D/•‰^‚>Ö>]H)G%¨ ¨`
+
+ЦüàÎè 7"¨‰Ð$—¯§¼.zo«ÂP€úç=CTœYen“BÄjêÇïßßM#TŠ*-‚/|MÓQà·1
+´ä•Ž‡ â
+ÒêI wòVéíÙª¨ßÝÎ5•ã8)ˆ• Ó/ƨ’ì¼@ÿjÏ2¼ÕY}k¡€Ú>µV7;jBå–Ç:´’DøŸÓ4ÛÁ^KÊäå|ëÝ~ë€Ñiµ $Xð:‚ßÝ=¾ýƒìf(YÛnrÂxÙ¿¸yøæF¾”UBÑo¡Dc¦Æ‡íÂY”ô1¹…zº-væ¥×CW~_•ðVSŸ%îS‰òš0/ë¯IBa:þ’'µª…²àA…ÑÃ:v£‹üÌ¢¤oäÜ#—ô…½1‚©½Å{hÄe2íäG¢¾.@”¡UyJ¿?ú +b½á;HÖùâ¾ìË«ãÊU_NOæ") cq|7æë¯Bè¿ÊTe:AmLä-&OŒAö¨ô‰H@µ—¿´WÚ€Ó± žV‡šïZÎBƒžd~ºve?XŸ…Ux£V>ÞS;X‰Gúò%5½ù!ЗOx™“ â,Ùü©èIèyö¼°·Òû­FŽG{%ª2;¸Š›¹Ld:måSöcU’Û<ÜFa¦fFžK7\MÑ”fÈPo^F‚:,ù?n5Ï£/úð
+<ß"/X=ƒ¸/çÁb<9¹Àât4‡|Á›Hk“‰Œ÷–§E"R}’0Z¿õ#N;Zšs&\¯¥ïÀ B‹â
+J b±ß„щÖù…“ƒxƒŒJÉƒÝ°í –Ëj÷ ˆâ|PìùöîÐû>ìEÑ,-ûó JBTõG­Ý p®È¾À'%áVhïJžŽ¹°±p
+RËâV²³´¡†AˆdÀßÀÕöXÑ…¡}É­©T%Jhõ™Co’¼°ùèÔw´Ê±Ã.%™!ƒû_Þ½ó÷n§ÒzÈÀ!Õ0âìo|ZÛýÙj9åjù<ML9cþ#ç³ÿ¯šýÙïÓs™ä_3sÍyJqz¶)|nÒÀ¸nnž§²ª4¤7Ø$_A_2©lbuQ\¨T@èl¹>èömSÕའÉï/òìmX?.}µÉ½Á–Û²ƒû²‹®\ò€.¶bÁ/CÂrÊ*b\ôE—Û]`¢š¥ÙØzÞO¿7¦xý%T,!/§[°*¸FœEMÉ.MŒ•˜Û‚Í‹Õûû‡w_¿4‘È'¯÷üíj … ·§"Þ® .±
+ UˆÄuV¼¼Ô)e ç/> –|}Ä[¾¸»¿‡CÔMT4ÃðF‹Ó üIT¸ ;?ðËPñVUè‚èô7 øpiKìOD“"VØØŒ66ð8uRÈ(L0”lÙuÇ]‰¥¶â§s$ôuJAï¡þœ .ºj2˜dàJU>¨¡“Ï•ÝPK'ºÈO1ta  øŠ#~Õ Ä9ÖsåÖåqÛ³ºÊp0ºÈe©ó['‚|ËÅežÿ~(!ˆA§Ò`xË0zDúÜMç8kO&.βºóhB×íÄe
++â~Ú;Ä(>õw¥üÎÄŸoDÌvþç¿úœþÝ’QÖ¦§ñŒ“< ÂI˜)Üvš_pþtÉú
+endobj
+1108 0 obj <<
+/Type /Page
+/Contents 1109 0 R
+/Resources 1107 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1105 0 R
+>> endobj
+1110 0 obj <<
+/D [1108 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+202 0 obj <<
+/D [1108 0 R /XYZ 56.6929 769.5949 null]
+>> endobj
+1111 0 obj <<
+/D [1108 0 R /XYZ 56.6929 748.4014 null]
+>> endobj
+206 0 obj <<
+/D [1108 0 R /XYZ 56.6929 549.4516 null]
+>> endobj
+1112 0 obj <<
+/D [1108 0 R /XYZ 56.6929 521.7105 null]
+>> endobj
+210 0 obj <<
+/D [1108 0 R /XYZ 56.6929 231.5025 null]
+>> endobj
+1113 0 obj <<
+/D [1108 0 R /XYZ 56.6929 201.1114 null]
+>> endobj
+1107 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F39 885 0 R /F41 925 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1116 0 obj <<
+/Length 2902
+/Filter /FlateDecode
+>>
+stream
+xÚµYI“«F¾÷¯èx«§Ýˆ¢XÃ1mOûÚl @b‘
+WýÀ«,0,TøWIá«῰¯6¢µ_@Æó‘3}<rÕÕ—êw(½*Œ"r⫺{%3¬,ƒWÕüµÒèÔ&jkööÁ l…gÞ>‘­Ôš‹7
+8?r*‰ÆO3F[ƒ|c=¡HBEb  +ÏP~ÂŽÒ†À‡(¬Î„c”Òá1t1¨„=ü² £Ìdº‚×b›Rò
+ d%šÏ8!ÊK–e+0À!aŸ# 3·¢‹•á‹äpÈnaŒå¨o
+WÁJp©¨o=«ØüÁ'AÅd@ºOCë‹d
+r!ŸÇa–ÿO–?Úôe…"Ÿ]îŸãÌÛÂÝ_<šZ1ñ#HŒ¢ ºô8”Áÿ
+QÐE”gáBæ·ˆP¢Çr
+#¡¾•±2%f| ŽÆÈ
+¾3 7^¬½"ºü‹ˆç%FæXtÑDG°<a®’€/u¸,2)á„ëó@˜…¸ìa±}‹v0Ü?¸’å™Ü‡yºß@—Sàsl~c¾QÉœ Ñ|z|«Öü5ZAÐØõÞ+“«tí‡ÛDŠ[­]ÞlÛÖÕë¼w‹Ú‡[onÎbWšÜ{gº5ºnK,iP·ûÆk po×:Þªo¶øûº{œ9z½\Œ§)þÆ9˜ÚÑ‹8¬vjæ~dÉè÷5,sÞ=åV)ð–ãZSÜçÅÒý½¼
+uïß rÚ$äH…Ãðœ¢ÏzõS\p¡+®I_ò/U¯Tðw6øWƒ!Ã(=£`Ýtÿˆz¯_¥"dR»¶j5ý63îÆv¶Ó¿´6u1l5Wï;ŠBë¨ûh 6zmæOœÖfCÕ0+~¹»ÁµâîìÖù$]6Õ{{£™­öh™¾÷6÷sÌzÚ1¹ÚûöÕÑæ@äΖïõµí¶,8ƪ1”ו·g[î
+†Íï ßó<oõ15@ëk»ªß:—ÝuÝ©Ö-Žk²Èð"7è÷Ž`lóéõ>V–¶7<Hûín ¡­õ/n¤v"Nh¤¹:Õîõ­ Å·Ò“’ìÙAªj$°wm¬§¿§ï7¿¶ØL8ÖµU÷æU00"{Uí[m³Zj¢{¾|çO½Fjž]«s>œ×°Ã¯†5cö~suŽštµÉů†ér&×—UgiÞÇ— ÌÄyCu¼ÎÞܵg5·I5cuÊ*5öŸy¼:íÿðîý¸ûæÁMÏPÈÝ $ð—ʾ„îZœ$<›É1øë2ÇtGµfs6©1£–úGq>sþT»öX;Ö'=¸ íûո͑~c%0
+µA™R§·îôœÚ¦) eqÙÏ'ñ¦×±š -]®£ËdcÅ›fwvqšÍ²ýnÞ¿lËR{š/¶œÃ=MF#n>RÄéì ï«nWv·EØ—zóß¿ä’i2Ð?è'ûò£Ðãj†aþÛ?&…:„eÿo°E2ýíS>ÿ@BêAYæ>ÿ(yú¬ˆ¿œ£s~®É é«æÅß.?ªþÛúÞendstream
+endobj
+1115 0 obj <<
+/Type /Page
+/Contents 1116 0 R
+/Resources 1114 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1105 0 R
+>> endobj
+1117 0 obj <<
+/D [1115 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+214 0 obj <<
+/D [1115 0 R /XYZ 85.0394 717.5894 null]
+>> endobj
+1118 0 obj <<
+/D [1115 0 R /XYZ 85.0394 690.1986 null]
+>> endobj
+1114 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1121 0 obj <<
+/Length 2380
+/Filter /FlateDecode
+>>
+stream
+xÚ¥YKsã6¾ûWð°ªÊBð"H:'gÆ“8•õxmMöÉ¡1w(RCRÖz«ö¿o7¤(šv¶jì*£4~|hÐ"àð+‚È0“Ê4ˆSÍ".¢`½=ãÁ˜ûùLxžeÏ´sý´:û჊ƒ”¥Fš`µÉJO¬ò?BÍR¶
+âæ"XÀûƒ'…ˆS:S]A`È8 ë ¶IØ=ú¯ ÉC‹ž[š*‹¶³9ÍUÏ^´4bŠ‡ÿζ»ÒÒTÖxIO …XJGáuE㻬Y,5»b½/†<Ÿ(ÑÔuGC#u¼^«
+8fz´éÄÚ€S“4 ÆAð}q…¥ë˜Ëßõ§¡ª5ð ¡*¡™ÒFŽ3Šc
+-˜Q:Ò¶¨ºe%OCÅDÚbÅqøÑmêöG·€M[RjÙû¨”&¼O¨(©–(ª¬y&¾2{°¥s‡3‹ˆ9‹ãDÌg°”Ç|…_«úPIXa¼Ô®íˆAìÀ
+A,äàsB…‡}G£#`ŠèÐzÄ2Uó<ÒNÀc­ß{]cAÕY‚¦h
+MQ¸s&ƒÅˆÇ3ɇèìê.þ=«œf»]Y¬]ßÒÅâ`b#û°ÏkêV®b_—ÚÎÃqot Ž“dp"±ûömé'¶”¾öÜ›¼—î®ã™cw·o*<[êîNl-!¦;v‹ µ_
+7&C‚€Û‰¥†@ )Âï¹ûn
+wƒyvæmß(FÕ„JóT؃ïm<è>ÚoÉ=n‰jq¬QÖ`_gçÓµ¯TAç~­µÓŠ[Eƒ‰L<Ê=ži²ùâŸ7w£WïÀ¿/èßicà›ÊE ÜÃuVô5Õ%“L¼xðÖ~Å¿x{\¡ÅKi¨óØ'ÆïJw²8uG„G‡ÏÂ×ë—`Qª`AùßèF¢Î§öxóQiÔÞ{pÏ×î X z¬¨‹zç2DH5^4¹Di̽°ðE >צ®Ëlp/¶#ÙxáIÎJuÅ…‹2Oí«²øjO„èéUCªš7äµ;».0l;—GC¤CÑXŒÃy6ŒOŸG¾AË÷Uø©
+ˆ¬‚“ÎÒøœrò‰’²$¡4ýÛÇ»ëŸñÓ~eñ«€=›;ÂcÝB†ÆXðÃVšÓ‡/ìöá€cÀ".ò‡äâB¼¨‚üÂÊG)í[)òß²¨–dœÙÂMN@zòäÁ¡¢¥…„t0Ð[g»µpMäî“›
+¯7^5t\ç.<7SQK„S£Ýš£ˆ^GfˆŠ×/†qˆ€[èò::-vÞ¿÷ºÇo aàÍ>Ô)ø¹) ‰I˜ö 2±/.âF'~QÖN°vt¦yxJ2ŲÇ3àƒœÃ‡þÅyCO‡7ãƤþ#'!þ_BÆ?݃UqzD:QØÙï¨ÍüäIòà@á'*¿'ÒC}¤àùáì1»«¸«Î÷³>_±Ó$ÏDŠ÷ÜI5á¿ö.ª¸vv÷ŠÌ=ô!ļ"xß½t½†rZ¸¯p㺛Í,‚HHDÏØë ƒ±Oº ‹pt8³?ð¾ì¼Eµ«# StìÙ 9µØ¦.Ëú0øâPïK¿fý„¯b*r¹f1“"÷ôÕƒ©1Ľæ_a”²C¾¼@Í™JxèØ[çm`2‹#Õ'›‡o2耵_EQÎNöÀrh…ëIvâÉ)Ä
+Æßú…ìK` ¡5¯£ïíê=ÀÉHlŠåsÇ!¹õ|ÑÁ8øî/¿ ê˜)¬’f«xÝaõ¢z¥œ³’š÷ÿ‡x©úÿ
+endobj
+1120 0 obj <<
+/Type /Page
+/Contents 1121 0 R
+/Resources 1119 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1105 0 R
+/Annots [ 1124 0 R ]
+>> endobj
+1124 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [349.4919 384.4828 408.4801 395.2672]
+/Subtype /Link
+/A << /S /GoTo /D (ipv6addresses) >>
+>> endobj
+1122 0 obj <<
+/D [1120 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+218 0 obj <<
+/D [1120 0 R /XYZ 56.6929 594.1106 null]
+>> endobj
+1123 0 obj <<
+/D [1120 0 R /XYZ 56.6929 562.6395 null]
+>> endobj
+222 0 obj <<
+/D [1120 0 R /XYZ 56.6929 370.2937 null]
+>> endobj
+1125 0 obj <<
+/D [1120 0 R /XYZ 56.6929 341.714 null]
+>> endobj
+226 0 obj <<
+/D [1120 0 R /XYZ 56.6929 214.6004 null]
+>> endobj
+1126 0 obj <<
+/D [1120 0 R /XYZ 56.6929 186.0207 null]
+>> endobj
+1119 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R /F62 1050 0 R /F21 702 0 R /F39 885 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1130 0 obj <<
+/Length 1913
+/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<KË’›§ý¼VYÕi#òfóÔý'ùÇAGuzØò"KŠ‡ÿ>ýFÓò´ª+†Ó2X¢H«&«ý„§ƒ"áOŸ¿<ÕÐã_úù0žþã«r¶åQ+ËS‘—<h-EZ•™Q¤ìa˲,»è¿¯. ïNòôt‹M“6%/ƒj^§eÕ2ø¡É’“ìô¨­‘}ÿ
+ 5e"Ç^·™Ž8ù¢ª’R†x½6ßUGôY—Äpã´#êôÀêd6&’y^~<È1LQ¦s×sÚéä4­[&_þ  MꤕÃÍávK›¢à~;£¥ýKzô¶•=‘­lÚ<Ó‹‘Cð£S'´ªÊ“tÖWA@Æ ¾Ï¿¿”[«[Ó*¤ªD›Ñ[g»©ÅÝã¨QglípìÕÿôøJ lid<(bÍî˜Ð½Ä;’ÆV9÷þa 霸©=ÐDéHfoûÞžýý1Ö¤6.ˆšnÍ+_>þûØ/¯£_­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º
+M&PÄqíèÙi7jÓŽ4¾§YyŸ"A¦͠ì‚d,"û©ì±‰kkÒ;¥)ÏR^Š:”&JÓ×9*—“²,Jן©IW؃È!6Š‚O
+q¿–D"mX• ‘¹ÈjmËúÿ@CH®2#¶¦È²&RØš8"u£
+:åô³¡&Ä«»Û†ý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¹ÿÐÆ}endstream
+endobj
+1129 0 obj <<
+/Type /Page
+/Contents 1130 0 R
+/Resources 1128 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1105 0 R
+>> endobj
+1131 0 obj <<
+/D [1129 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+230 0 obj <<
+/D [1129 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1132 0 obj <<
+/D [1129 0 R /XYZ 85.0394 576.7004 null]
+>> endobj
+234 0 obj <<
+/D [1129 0 R /XYZ 85.0394 576.7004 null]
+>> endobj
+1133 0 obj <<
+/D [1129 0 R /XYZ 85.0394 544.8207 null]
+>> endobj
+238 0 obj <<
+/D [1129 0 R /XYZ 85.0394 403.9445 null]
+>> endobj
+1134 0 obj <<
+/D [1129 0 R /XYZ 85.0394 368.2811 null]
+>> endobj
+1128 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1137 0 obj <<
+/Length 69
+/Filter /FlateDecode
+>>
+stream
+xÚ3T0
+endobj
+1136 0 obj <<
+/Type /Page
+/Contents 1137 0 R
+/Resources 1135 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1105 0 R
+>> endobj
+1138 0 obj <<
+/D [1136 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1135 0 obj <<
+/ProcSet [ /PDF ]
+>> endobj
+1141 0 obj <<
+/Length 3113
+/Filter /FlateDecode
+>>
+stream
+xÚÍË’ã¶ñ>_¡K*šªŒ7ÍiýØd}p{o¶«Â‘8#ÖJ¤,R;ž|}ºÑ
+Waƒš)m%ÂÌ ™æLZEBµL€ap~ƽ¯Wq/¿£ÍïòI:pH^”ïÛÕª}Žòâäv -©YÕ]O½`ùÐV sø·ëª¨ý’XP»ëÓXu¬,óݤÔ_´ó.>¿Eúï¾û8øoAè…žh!™å^¢óÿíîç_ùd±âû;Δwfò 8
+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Ý}
+{Häí¶–Y@ªùî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
+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æµò‡•ñ
+'ö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!&Ó
+²>Ÿ2˜ÄáÎG9ü)¿²ÁrÔ™½ã7àã~€ª;'è¼UðB4²nÃÑ2–'ÁN;ú3Þ*ü?ÚªŠª•YZêð€rõ\¾ÄE^í…
+¶ÍÍ^f"|-Ô—0zp™=Ÿ?¬†3©­ÒŠI®åÍØ^fSi Ó¿ŒËX9\+ÒGêý:ƒÑZ0)-Ø ºÈÙ"{Kšž‡ã$¾6Ï_Ôr i;ur-;<IߣJËý~ÌÑóendstream
+endobj
+1140 0 obj <<
+/Type /Page
+/Contents 1141 0 R
+/Resources 1139 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1148 0 R
+/Annots [ 1147 0 R ]
+>> endobj
+1147 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [356.2946 363.7923 412.5133 376.6291]
+/Subtype /Link
+/A << /S /GoTo /D (address_match_lists) >>
+>> endobj
+1142 0 obj <<
+/D [1140 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+242 0 obj <<
+/D [1140 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1143 0 obj <<
+/D [1140 0 R /XYZ 85.0394 576.7004 null]
+>> endobj
+246 0 obj <<
+/D [1140 0 R /XYZ 85.0394 479.565 null]
+>> endobj
+1144 0 obj <<
+/D [1140 0 R /XYZ 85.0394 441.8891 null]
+>> endobj
+1145 0 obj <<
+/D [1140 0 R /XYZ 85.0394 424.9629 null]
+>> endobj
+1146 0 obj <<
+/D [1140 0 R /XYZ 85.0394 413.0077 null]
+>> endobj
+1139 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1152 0 obj <<
+/Length 4061
+/Filter /FlateDecode
+>>
+stream
+xÚÍ[[sãƱ~ׯ`žB¹ÌÙ¹_’ÊÃÆÑúlŽ½Nl¥òà¸|
+’PK2®V©üøtÏ
+­«o®¾½úpýü¢ÂM¿úŸ·¹¾ú>ÜÓ‘ÈßøSèqár€ê÷W﮾¿úðÕÕåO×¾¸ºÎ‹.˜Q+ùåâÇŸèäÖýç J„³jò?(aÎñÉòB*A”"õ,.~¸øk&8¸ë-1PJF4Wb2³šp£Õá׆WPxml*GŒQvç­3m‰f÷„ZÂùvK$l‰‘ÄY31@D .üŽ4»<±†(áÜvØ ˜Â°µe–ÌÁÙâþì%ŠïNï±]÷8Á7ï c;–qh¯ÀQoW(%vúþ/x5ƒ§Fo†au|hµYÞÔëq¡ˆÕJÅa jÜééõC] ÈAl¬<IÐ'„‹Ãš.LvÑ,›¾¾ 3îÛÐIãχõ%³Óvsÿúa>B}‰´'3&1œCƒ§÷TŸš‡23ýT-6uÚ7õ¢}¦2Êeè쟛yµX<‡ŸþMuׯ›y˜‹ÓîÍ%›vuhßÄñajóºëà58#:žÊú\­šÕýåLP=­:¼ªð¢¶í£ÒÀf­Âí®]ÖaÀ¼Š_B›ÓiµJ÷õºé>†ÿ Šþß¿… ·çÕº‚y¯ãOxl4£`vnðÊL7.[~N
+ȇŸ‹j^?´‹[OH൫õ¼]W«ÛvÚÍýÃ,î;rñ¶Ä”F²«eÒP0â¾ÕØ×Ù
+JÜ,Ð@ÔõŸA—[ÜKÃ<5¼Ve‡â„“w”[JœƒG´QÄIÍ^½£™âlHrG¹…]²€lò°c;jˆ¦:íè²z+nÁ?G
+·–ÍýCzï6k0äëÐS— Ì6ÿ¥B¸è°·þИ·°ÞÏ}øÑD‹üôÐÌ£p5éVÄChÐØ`ï^'ÿUM½ñãÆ}>Ã…4FÕ?ìYiˆ2ð8|µ•ŽgCŠûóc”i!Íð
+´1Œ?&‡`2`¸Õ£4}IóÀ³Éáâ9Íð\Ø•C°N-(’KØSLèaðK³C-d€ÏJŸoý‘Þ‰åsg‰’@¤¸Aû?L"eb
+ùÕ†‹Ƴñ=D•3Æ™L¢ù. wC³é"J S;¡ô0]*© ‰:¸†D4
+ŒhÄ:ÂHÌ Xa€‘šàùr‰âlH²”“09Í·o>*4RÑdÀ‡g®…T?Å}Lxà…þålkÎO¬YhX³Ñn¼æ£Â38¾QÞGÄO
+KeøQ½‘†Ê©>ßÒ3ÅK—€FÀ–È—l7¦yÁc›£·Ü ·—´¢ Ä–RŠé"$š|Ø%Cj·x²ÇÀ˜Ë ÚzáÀMg^Ê3ÅÙdI8ð…# {±eÁ3ˆ.ýÉ.|ò3rÍF¡µÛõÌhìNË1ÏC1‚¦46”N
+€®¥ ê[åY›Û„8þ
+/ÀÖ¨”;üai†iÌÙûY†·©\{BXî\Jå; è 0{G… þmaþôaªsAÄ<™„J­Ø.R7·§c”âèCüMÀƇÙÖW›ÝDq6$Y0»Bƒû˜‡(âd´4ŒCÎuZù+Eõ¯¡™9/qcGÃ%ŠèÃD$Üü³>.¥ç —…K£VI¸äCÚÉHŸ&qžBNõ¶`0#Úåài³JÙ ýw‚Ñ6ÎRÎIû¼
+ %GäQê»j³(‰%X*+såÙF+#Ç–ámÑ
+Ô±41æ(¬œ~líÍs_w%L „ËüÌ·ˆfÐõ‚‰-_<±e}_ʼnçwƒˆzLjs•ë_¿>à ï_<Ãû&—ÂÂ4ÛÙ¦íô…ÈÁ±
+Ô1‡ž=ÌÏ\rEm¨H…'´ŒÇDеYuÍý*
+“@ÄŠçB”‡bW°ÖÌJ©”ÔCq]šù#!¦öŽ„`Üôo]¬ Û˳ÄKú%¾]˨ޖ9…Õ“]|Ìßlšnê.ÛµtlÔFUÝÕ‹T
+S÷£sÈÀÈX÷Œ–2w»(æ0 
+žèͶKê-‰?˜^À¡E×°NžÄô;,)ÒJ”¯0¬•;ªå ëÉ3½&„–˺/ÐñÐè›»ç“_A½Îì±ê%”ÔTÚêÏk]ß­ëËAt•Û…e›(Cµ|LÌœÜnè?cX/J•–±È
+jLŒ˜æxqºñ¿IýÅã=þ\%öúoõ꾈CþuèÃcUJ‡w7žæU¿ú£äí'ÛÒagÐ;ð-JZœòEð½™3
+endobj
+1151 0 obj <<
+/Type /Page
+/Contents 1152 0 R
+/Resources 1150 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1148 0 R
+>> endobj
+1153 0 obj <<
+/D [1151 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+250 0 obj <<
+/D [1151 0 R /XYZ 56.6929 165.9801 null]
+>> endobj
+1149 0 obj <<
+/D [1151 0 R /XYZ 56.6929 136.242 null]
+>> endobj
+254 0 obj <<
+/D [1151 0 R /XYZ 56.6929 136.242 null]
+>> endobj
+1154 0 obj <<
+/D [1151 0 R /XYZ 56.6929 106.2766 null]
+>> endobj
+1150 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R /F21 702 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1157 0 obj <<
+/Length 3064
+/Filter /FlateDecode
+>>
+stream
+xÚ­]sÛ6òÝ¿B{ˆÜX4A€y}J]§u§ur‰3w3M'¥%Øâ˜"U’²ãéÝ¿]ì"%Z¾´7z
+ÕÓRÝTöh¡¼C¡w™Âª`’Ò‡¹z¬}¶ƒÍ!ôU2dëtsñ–u3Ptluxñö^±Æ‡~Ÿ¸ã>ª¦HZÆé3jêaP“Ãz^M‡¸öÔ´Ëv\M}¶»jZ“’Ði}Þê©`¬ßN_P§ª;{àª
+ø©LfϨª‡u@UëyUâÚSÕ.ÛqUõÙæ´tc¬Ê¾;aÓb‹Z¯7ì߯·‡pÄõ€ïQJ8ßsGsWŽ |X*wÝÎS3<1°9¨ñ>ÖÓ÷XÏjü ×­Æ÷ØŽj|ÀÖ»/ŠÛ}ÏæìvïX»èÝ­§ÜÙ™‡¢[Ú›(RAªUìbǼÛ›8ˆD”þÏ{£!qu`ozXöÆa=¿7‡¸ööf—íøÞôÙòi¨ DàÅ—ì…©æeݺ9γ\79¤ ÷@ûY˜$
+Ƙ׫5ÅA¬®SÎòLj: ¤äDÐbø(ÙyD±hkžßåw†g®Kp”Ì¿Û„|M’ÖŸ¡ì Ö€2Ó7èÛ„Í×ìwW¬ ÞDÑô‡úÁÜ{Ó•2£³$£°'HKÓh¿o
+ïUÖ2ï\A䱇I‘#äÚMkr`k÷?7ì:uó±ccuÆ篗†9›±®éd§ÆyHÐïÉ
+ûµéãi$m©Ú ™†M£s~†ìª±¾ÃF¸ýFȬMµh îЖƊj£ÏJPÑäÚX ˆmŽ çØ+ã1š„‘K‚Àˆv·¥4ÕP ·'ÃÚÈÅêÜéŒÊå]ûµ hÏ—ŠK™9lª™,8WçbNµcNÿz`Ë
+è¶'’X!;òž¬rëŠ='æ/LU?6¦c$Š®T@ñ€áCe[¥OgÌUMß–þ õ½P=<ËC½ 3)CŽ€íXf«D&PÐpf‹kžA1WÜŒ•q%Šv·'#ô SÓq< Ö`tk‹Ñ;-ˆ#ÉŸ$H:ëNƒT©h¨ÛQ~€
+5p–}UðíU{¶½O/QHÓäËèÑÖ+( ´ñ0âmÖ6%¹µA¬ÄaN¡H£'¢6§ú7 ö–{v…7sZyÊ3ÉžbäÈ%A:‹¾†è}·¬Ë1iUô}^ŒÅ6 ¤Î ‰Rù Â•HËþï‹UQæ ~!„“b
+cú+S¨µ" *P;gÉ¥íP¼<P&½9§ÕÐåb(ÙÞ#°¦–®GF#ÏŽ,]U"àf‡ä*Ç(o^ð„Þª w­
+ÝóF_é§
+TÀh¼yCÙ2EaÍ\CÔƒEºÀžr$ÖÝßVTÈÚÞ,ü킧¬¶5Ì€ì¨b’•¡Ž†Ä€Z‡õêì§!+WtiÒ±åàò M††lÖ¦²8RÙ±»÷ù@>Pc:g»ýÜ F(ºáð„¥ŒE%{!§q
+¨4TGá7Øë@`:[ªyy[C}¿\Ñ'{Pyç„8ÖÿÁ¬²®ï6kÒKÛž\Ö±Šhß¡‰ZÉ»–
+£ÛMãîX“ÔšH‰2Ó«ã ð Jši¥†– ç¶ÉaMMK@ëopBÉØw”Ñ'ô¼Ú-íu
+endobj
+1156 0 obj <<
+/Type /Page
+/Contents 1157 0 R
+/Resources 1155 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1148 0 R
+>> endobj
+1158 0 obj <<
+/D [1156 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+258 0 obj <<
+/D [1156 0 R /XYZ 85.0394 731.767 null]
+>> endobj
+1159 0 obj <<
+/D [1156 0 R /XYZ 85.0394 703.7216 null]
+>> endobj
+262 0 obj <<
+/D [1156 0 R /XYZ 85.0394 229.6467 null]
+>> endobj
+1160 0 obj <<
+/D [1156 0 R /XYZ 85.0394 201.8883 null]
+>> endobj
+266 0 obj <<
+/D [1156 0 R /XYZ 85.0394 144.1965 null]
+>> endobj
+1161 0 obj <<
+/D [1156 0 R /XYZ 85.0394 118.9605 null]
+>> endobj
+1155 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F21 702 0 R /F23 726 0 R /F14 729 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1165 0 obj <<
+/Length 2262
+/Filter /FlateDecode
+>>
+stream
+xÚ½koÜ6ò»…€~¸ÝÔ+“"õ`ûÉqlŸ‹KÚs¶8Ú'k¯P­´•´qÝ_3R¢lÙIϹ€ÅÇp8ï— þx'a¢"¤J†1ãqPìŽXp {—GܬÐʇz½>:¹i B•DI°þàáÊB–e<Xo~Z$a.[œ}ÿîâêòÇëÓe*ë«ïß-WQÌWÿ8§ÑåõéÛ·§×ËÏb¾8ûûéëókÚJ,Ž×WïÞЊ¢ÏH¯Ï/ίÏß/Ywt¾xñùåL #¿ýô 6ÀöwG,*‹ƒ;˜°+»#‹0–B¸•êèýÑ?„Þ®9:+?ÎÂH$ÑŒ
+ãab¢ Fd‘L\„EEplB#®Y"64Í ãäM×Ñ|Œ]8˧wtßÂ8‘Wam›´°MmUs;žã.LLˆœq·™€yLcÛqÕ…WN(jùÑƨ$F-MҚ͸.tÛØùlL¢PxÑV_iV<28´sÍßíÃÜŒ~ݵƒã»ƒwÌÇ4Óuíˆj·[{¶Ÿâ°ê øÌ…Ïĸ}«?–Í¡{ì¼3E™çï·ºª|D·qšØëÖîY*­Ü7 AÉèƒnGÏú”–á;¡ eA…J¿ša&
+È#%€h‘!-Áo Å¥ÈæG¡˜…“«Þ4Àbàqé¯|̆KhUG;‡n Ò@
+ºÝ•unÞK¦=·½ÊôLÚ_»rÂ!ˆÙTáoï{|"Ñ›oúg–† R—жIÆ?Ç—„_â «‰/ýo§¼Ì Øî¹óQ|p'8³e Tª ã©lþ!ò‰Èx·€ö9å”2ò¢šñNÎ2èHS›7ô¼i"i¢L¼„Qç;Ó’ÁÊÕ´”o6¤ƒÎ‚îò¾Ø…ávN‹aJ*[‹¬(:5ï=õvÕœ‘oªM¿ÕíÐOu#p
+IZòÀ—ÇË$ŒºŒy’Ž}>Jwâ)¥1(SR™|Biʉ„îÚ6U÷š+*ëÝðÖ;Ș¶P&誛> ÞèA¾Vè7÷cqO×údrÅ°qÅT[oŠâ iQ‰pÄú²*ûû%ç|ñŒ=ñ¼LàÿGª8„*ŸW¡R
+endobj
+1164 0 obj <<
+/Type /Page
+/Contents 1165 0 R
+/Resources 1163 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1148 0 R
+>> endobj
+1162 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
+1166 0 obj <<
+/D [1164 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+270 0 obj <<
+/D [1164 0 R /XYZ 56.6929 769.5949 null]
+>> endobj
+1167 0 obj <<
+/D [1164 0 R /XYZ 56.6929 749.9737 null]
+>> endobj
+274 0 obj <<
+/D [1164 0 R /XYZ 56.6929 246.2071 null]
+>> endobj
+1168 0 obj <<
+/D [1164 0 R /XYZ 56.6929 214.3631 null]
+>> endobj
+1169 0 obj <<
+/D [1164 0 R /XYZ 56.6929 155.5938 null]
+>> endobj
+1170 0 obj <<
+/D [1164 0 R /XYZ 56.6929 143.6386 null]
+>> endobj
+1163 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F62 1050 0 R >>
+/XObject << /Im3 1162 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1173 0 obj <<
+/Length 2334
+/Filter /FlateDecode
+>>
+stream
+xÚÍZÝsÛ6÷_¡·“;%Š/â£}r'çNâö÷)Ídh‰–x¡HŸHEuïú¿ß P”MYv­Îdü@`,»‹ÝýAf#
+ldRB…•#m%I)KG“ÅÍ`ìÍ s’8)éÏúñêè»×B,±Š«ÑÕM—!Ô6ºš~Ÿþóä—«³Ëㄧt¬Èq’*:þñüâR,~N¾x}þæ×Ë“c-ÇWç?_ ùòìõÙåÙÅéÙqÂLÊ`=v,x}þö [o.OÞ½;¹<þxõÓÑÙUw–þyî ÿ9ú𑎦p쟎(Ö¤£5t(aÖòÑâH¦‚¤RˆH)Þý«cØõK‡ô'¹ œ[1JRJ$c»wÅ(ìš°Ò:9·7MK‰H…3‰”„Zº1 g=“0Έæ6éÔ%¸ð6)ëÙ¬¨fN70_ôçSC˜Ôn7±¹Í'Åo”ò¼­
+=^ϳ[í<w 3nòå—|‰D`Ü| MIÇY5K`”™q¾µÎÏE‹ü˜›&›á&fœ…ù Èg%6M9
+”W-¹oÓ”jb4e£¾.^¦_a9I™Ò£$N8¤É8Ì4”ï3™H¡Á,šl½õì5ؤ®œ¹f+Ta\Ñç/Á”’aA•-òé
+µ™5m¾|‚çLsç8•»ƒB§hOÜÃS"'ß)‹¦Å7õIE5)WMᬇ]oÚÕu`YNM™}¼ÝÔUŽ¶ï6sI™­š¼Ùm¿¾b¾â{¯4‡–ݪ•ÑÄR†¡º¾mA¥O»ù­¿kuéÔfÍxVÖ×YéÚv¤¾‰YëÍå&Ä}ü ŒÝÖÅö¶Áñi~“­Ê¶2›wg¨ºç¡Ù´Y›/ Z?f¶ž>¾f³IC¤´ûµRÀÈR ×îøpEŠI“LæYUåå“® xz ÜPå(0Õb±ªŠI0”'Ev¾ç"³ûÎòÙd’7~P»Áð)¡œ‹=ñ?éæmçßî\˜µ§¯C™5Êðt–qÅn³
+E¤•û¬*)Ô²T…êÃߢýe^ºòe›!¡=¼xîÎtÏu1ÃÏ-VNIw{v5ÅcÊßœêeŠú{uÏG³/“)jå©Ä"d¹‚œ0M>çwÏKgNkÍدÇþ«‹÷ïÏN±í>¢Ðž¨‡Õ(;¨F07
+M
+ŠÉ–ì6uÒÍÝ®Á:ð°è¼îÞDÙ¡dß.ØrÿKÐþí« ,Ù>•½Ü¡SnD_ÖERHp*F\ÚÞmxÙ Û\ÚçàÜÃÌÅÜ”§ ‘ jµ'â\f”å[ï=ô¯†à
+endobj
+1172 0 obj <<
+/Type /Page
+/Contents 1173 0 R
+/Resources 1171 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1148 0 R
+>> endobj
+1174 0 obj <<
+/D [1172 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+278 0 obj <<
+/D [1172 0 R /XYZ 85.0394 537.224 null]
+>> endobj
+1175 0 obj <<
+/D [1172 0 R /XYZ 85.0394 512.8844 null]
+>> endobj
+282 0 obj <<
+/D [1172 0 R /XYZ 85.0394 444.1158 null]
+>> endobj
+1176 0 obj <<
+/D [1172 0 R /XYZ 85.0394 414.002 null]
+>> endobj
+1177 0 obj <<
+/D [1172 0 R /XYZ 85.0394 336.6639 null]
+>> endobj
+1178 0 obj <<
+/D [1172 0 R /XYZ 85.0394 324.7088 null]
+>> endobj
+286 0 obj <<
+/D [1172 0 R /XYZ 85.0394 175.0326 null]
+>> endobj
+1179 0 obj <<
+/D [1172 0 R /XYZ 85.0394 144.8676 null]
+>> endobj
+1171 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1182 0 obj <<
+/Length 4254
+/Filter /FlateDecode
+>>
+stream
+xÚ­[Ýsã¶÷_¡·ê:C|ÀÝÓõ¾êLsIv’<ÐmqN"]‘ŠãÎôï.
+?Çß®>¾¥K“~z÷þݧwß¼{ñÛõ÷ï®ã^Æûe¹Àüçâ—ßòÙ
+¶ýýEž kÔì>òŒYËgÛ ©D¦¤¡esñùâŸqÂQ¯ûi’,ϸ(x‚’¥¨lV.ÿ÷
+÷ðÝ{ÎfŒeV)ŽCs˜ÕdZæ&rYãò<Ÿ/ۦߵ›Ž8ñ¹/ûj[5=}¾­~ÍsÞÔ}Ý6ÔR6+zù¹+ï*¿–QK‰<Ë Ø.u½®"Aà ÛWZÃ`I8žM+€ï4®ˆ…¯ªå¦Ü½`f^õBû½`C»¡!ËuÙ4ÕÆw÷-µÞTôÜwÕŠzn©¥{ì`j+WÛº©»~Wöí®£þ0Ãt!œš¶9[y’§g‹È} ¼½¯`âa¡çí->û‘khÊmEM]µû½Ú¡tf¸Gþu¾o²(þlØv{VPm ßpka±ãƒ9ÈB.=ƒwÍj™8.2&´ñƒö}½©ûGšBt7~½e»Ý‚x¢ ß±Ep› ÉÌ”/Q˜ˆô~WW¿WÔÒ´ÍâíÇÏãîn¿é½˜Þ¶^&ýOˆ‹ð6æ".2ÉY&½Š¼nŒ`*3@°ßcÝT}‚ ^ ãc±çÁ£´á‡™×5–ôyýæ'úîÚå—ª§÷ ˆWÕÔÍ)}3É4t÷Õ²F „ÃL(‘,À:¨@òý¡ñÒfynĬà*“ÆÏ1_vhLÚx-⌋ñ”Î2M¥JÁ![͆•‘Âûv—b*œLnƒ)p*ò|hø­aâ$ ¤»­At¿ âŒgX •ÎXQè) ÊÕjw‚‚ù]\ÂÆ…˜?¬ëåš”GB¿Êåò,Kä•1Îœq’濯~ú]RK»‹-½9œ2u``$W'´ÌãZžd,çè ‡í1phBʯflœq1žò˜± ™aàã°§+2›ËÀY°»nÈÄ‹K ‘ƒ³eàÍö×ÄT&3
+ìúhÔ¯¹ÊKPà]Ý}wFvz¼¯è¹÷†ÍcdGOoÎÊÌêÍjI6|åÏs8«W$œiQA`Á5ÕÝ‹ós
+§rnI’§ƒ–r¹¬î{òvÊ)ö–Í£o¸¥§# _Èþ¥£qD¤›g ©B* À¨–Ï[ê'ƒF¿¢UF“’z‡½z=ñ Ã2  ‚qôgð’#þH›i”>)­L˜ŒÂT‡ãÿZa .Æ3Ë*“ Œ€5ÃÂOɪÌrV¨3²ªAgý—/S.ʳ‘† Ž+²[bÞc»Ѳ6H4µÍæ‘ÞÅǬµ:Bó³
+%#ãSÓ€nZÁ‚ðÀHÝA Â#ÀJ•>·ÎDÃ˶ü£Þî·¿,÷;ÄXŒ1a A2—ÅÉà¹X¢§ó°“EGîóòpŒUb:A#ÂN–;ØNØÊ8úú•s™`ø+@ü`Ɉª“FTeVëb6åftsƒ?kZOÚM5P40*! _F³ÓÈ™å@˜ÂCUøzf\Œ§L@ ïŒóaå' çÂì ´™ ¨
+Z™£›f'‹7`e´\h}7hD]˜§Èå¾
+Ù”Çú–
+šB„¾A¨‹"~³­Œúzôf\Œ§L¡ožÒ²aegxWi$bÀÅø]T—¹ñìi½ãJ+FgÏ-;£F!pÿf<ˆ3žá sìiÅÐy¦ €‚oGd˜ñ‘¢#vcLä)ŀЫˆÐsdÜ
+LDÈÜ>é¦Ázh&˜»]»¿O;|«clý4øh=ÿØöž;Îi:.m}Ëý¦ìÁ(o;bâýÏûæÇÏÔë)Âè
+Ü$:þÜnJ
+c˜I€Û«˜¯æQ˜p1žñ˜Eü†oqÔI0á‚ß`¨œÍfþ®${”} Ííi™ÀìÅôÍ7Ûoœñ̆ÑlÛ¼°ÏØ1¡d ˜ 9å ¸É${B €dEû 7f<³aøÜhðˆ“ ŸR ¸OÅLG[æÄ™MdAKÏêj¹wN>FU'ø¢p7ð ^ô²À_•ñ¢ô¹ªNÕ~en2‡†¤¾ÝÝŒ^>¥ªÞãñÄ‘(ÚÆQ¸Õ_>U[òšÏ?RK‹ùÛšj}3¡:+Y:ûÛQ| TfJLh?ª3ÇQgH†#ÉášëæhUÀíŠqö\ŽÅñçÖ?š×ùuŠß‰;"
+G%fi±ëåK6J36¿jhHï2Ø·,»ê’ðsœ³Üt-{X»RŒ‘§À“²+”yÖ- !£/_ÃÀM„ØÇ¢šærŠ6F籓œßìý˪­\<‡bç›Ö¥+ÿÃ[™yŽaÏ$F*P‘’4
+ð^:ˆó}×í¤K⥛Êé&6iÝjÁëv¿YQ#Z<zKyt]0~Ñ:©B…Hß""«‡ÚhUO|ûÐÐKÜ`};¡ /<uk¢1^ˆÍ °ü@e"ÝÆÛ.¾‚¶cÖK
+—ØèÒÒη=¬ýͬÁ4åÁ>cùßQÊ-ÆF­êÎS<^e-ñƒ`èe$ \/ 'ƪ)ÔÂ1‹¤Šg¤v
+Lò$UÄ„Qþa
+endobj
+1181 0 obj <<
+/Type /Page
+/Contents 1182 0 R
+/Resources 1180 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1148 0 R
+/Annots [ 1184 0 R 1185 0 R ]
+>> endobj
+1184 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [55.6967 404.4849 256.3816 416.5446]
+/Subtype /Link
+/A << /S /GoTo /D (rndc) >>
+>> endobj
+1185 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [268.5158 404.4849 332.4306 416.5446]
+/Subtype /Link
+/A << /S /GoTo /D (admin_tools) >>
+>> endobj
+1183 0 obj <<
+/D [1181 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+290 0 obj <<
+/D [1181 0 R /XYZ 56.6929 724.3071 null]
+>> endobj
+1031 0 obj <<
+/D [1181 0 R /XYZ 56.6929 689.0661 null]
+>> endobj
+294 0 obj <<
+/D [1181 0 R /XYZ 56.6929 117.0915 null]
+>> endobj
+1186 0 obj <<
+/D [1181 0 R /XYZ 56.6929 87.6248 null]
+>> endobj
+1180 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F21 702 0 R /F23 726 0 R /F48 940 0 R /F14 729 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1190 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
+Îq³æ_I¹.Ì70âùrD÷ú±Dà’Š Wzg±óëMþ ˆ8øÍìÎÙ²éxIüÞÄÛ”‹Žo´“>y(¼÷ÕU±CèÁQU
+gRLöõ„ÝáÉC)’g~.™‘ R‹ë„zÎÍË\D€úQQy($-ËåßÍ®Á2x{Œ{ Çöˆ‘ÃU?–3ü‚¼Š:åN)"B®Ni<éDã RG•ð`ð qgÄ
+·Önꢙ+ƒ4x¿d»qÚ ÁH!>Èq;æÐ4$“j*A4„”SÝáà 3®4¡ûF‡– ZmH~êÐÖ).&ÔöaÒ²PnŸA|UÒ%,Ÿ=“ö ~AÀ¡ –8åÇ¢‚<´?ØèHœÃ3(Š\ˆt¾åÆI¬µž…=Å`HÒ)kÌÔa UGæjñl΋¼›¢ßX“fàM WËߪú¥B0ið‹
+´k®„á‘«ÝNŽï‹Œ+Y]&¹ßïëE€¶UþûÖ¸ÂF¦ª6ÜaÉÍ£ñŒ±¥sM¾¼iq]€‡Žžum¬ÒÁããèóš£Â%
+I»²È²3^J e|îédãFˆ4éC–@ cÓ=› :ävÆŸŠ³õ0jÁ¾ü©œX0áÞÜ©NENýX,ŒB\–!/Ç/“6]ùà¢G6“cK‘#Ëðr¬h½Þàvü2 <;êÒ¿’ô¡À°¾Jž ®=Sá\/ À^í*I;Ö€c±§ìEÕª·²Xí«ønìË¡™‹QÒ/Ÿtk[(+ѹõþ½pèܸ(NH™-!ùû}Û †g\;„Æjpðq׆ÊG²þ%j„=VÝöƒO„ñVCp1ת€G£ëV48×m0PºäíîÛd 
+›ú
+ÄíÔ®
+UÕòî*óû¶ëum›"Ó·\‡àV”omU&iPfrF"xLiNU¬¦$%Q²¯%x¡°RRkqŠ”> Åy8C,²¸ýÃéÍ|q%&ÿ[bBÏrY3êËRï'ä€*”ô$ãGéu‘Ð?ÜÉ6èJÈ B´Š†C°µqSˆð ¬`³ta£Y¹f}£Â-x3B<á»Ó×k(Ò0ZÀ´Oîbi›Då¶D¤j[>¸
+ÉÔ`Yû®Hì¼Ê3`߶nÀî y"3ÊŽ¡>f‚Zh éŒ¶#Jtµ¡íAn>µ"ÈcQŸ¡°wq²‹H³p•Ë{CVG0Rœ†,a[‚1Óûƒ1‹º
+êUÛž
+û1ú†Á`𠶿ïài')"=æ…G_'í
+wíÃùs¡¶h $48ÚÓê<ÖÂàg[y™»;𸠡/s©ßÓoò› 9n¸3˜•ËŸÚìPåþê{Ó»¹ÈÐíj3³ÙÌñõG'_Qìå¸òÁæ1¶ kw{E¥¶÷œ&ÅHIpj=VÛK²©zCèN¯a§é¦ìÙ>ÐŒdÉ«Çz´-3[OÈså;¨Ëê®?O‡"5>>n$è<¦ lF
+endobj
+1189 0 obj <<
+/Type /Page
+/Contents 1190 0 R
+/Resources 1188 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1199 0 R
+/Annots [ 1195 0 R 1196 0 R 1197 0 R ]
+>> endobj
+1195 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [406.6264 524.1437 456.8481 536.2033]
+/Subtype /Link
+/A << /S /GoTo /D (tsig) >>
+>> endobj
+1196 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [140.5805 512.856 196.7992 524.2481]
+/Subtype /Link
+/A << /S /GoTo /D (controls_statement_definition_and_usage) >>
+>> endobj
+1197 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
+1191 0 obj <<
+/D [1189 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+298 0 obj <<
+/D [1189 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1192 0 obj <<
+/D [1189 0 R /XYZ 85.0394 749.3189 null]
+>> endobj
+302 0 obj <<
+/D [1189 0 R /XYZ 85.0394 679.8163 null]
+>> endobj
+1193 0 obj <<
+/D [1189 0 R /XYZ 85.0394 652.1211 null]
+>> endobj
+306 0 obj <<
+/D [1189 0 R /XYZ 85.0394 573.4726 null]
+>> endobj
+1194 0 obj <<
+/D [1189 0 R /XYZ 85.0394 542.9681 null]
+>> endobj
+310 0 obj <<
+/D [1189 0 R /XYZ 85.0394 335.1831 null]
+>> endobj
+1198 0 obj <<
+/D [1189 0 R /XYZ 85.0394 307.4879 null]
+>> endobj
+1188 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F53 1017 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1202 0 obj <<
+/Length 3489
+/Filter /FlateDecode
+>>
+stream
+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¡-`E5Ù²ô†“ãò°Ôí½Ÿ$&“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
+ìí ·ã)õ•
+09¤ …@Ã&tž™‰è¯øìÜáÀV¸ÚÕ½ .v`+ð…Ý­½od”O¸/yUÌfÆãZî{çÁ&ÍH3a¼fÂ.rÔLÉE=ÐÈ£ãsi@fÑwNŽ %Ï$z/¦í3r[*U$µÁ~™%ÃÁø
+›0©j‡òµ«½ìöüJÝÒ“ó¨Šl*Œ†M…ö]Çot³7u8\‘}öQŽƒ&ïYR ð±ÔD bR·ÞE•_¥Ô‘P!¬ •ûýZÆvÔËES#êa’JÎ4ýCµ®Q{Î0Gn´™N¬Á¸ª
+¨}ùÔ ‚¡Ë«Ä{Ä"8Éš
+Žú†šbƒ#ω³
+‡H¿nêˆ$'ÐØÎD¢âœP±ŸN°7÷8h+~©\¯«‡ÁA2_=-0îPMMFNÀ‘ºÂÆ<)„)øDÔí¶‹Åš<ÉEbMjÄ ro­³$SFÌ]ÃÁ?%²Ñß°ã-<ƒ'c§Œ!7a’\ûœ†•Á&v’Ó¤(” !²j+õ¯<Ô ¯
+Ð]’Fâ$F˜ü]¡PÐ^"…<­˜Æ1¤vDtþ ýÙƒ «dê6q(/@¡‹€Îy y˜
+’˜È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¨
+0sÈèi.AëÆò9¤}kÂé e5ð¬=Lò×å’oŸG\d¹Ø-ÆRˆoÍÒĤG †o¹=
+ˆÒ†–/º°µáúØpˆD ;&9^UÌÅúHáÈÕ‡uUmú£ëvS¯Y!˜„–Á{Y™-Þt4Ãg
+
+̉ˆµ·üƹ|Aƒ*ŒEN ( #Ëì§Ñ0Ai‡(ö*›•Ã~èÐx!”J´qŠ¯|½…„°Ð†X
+íISÓkè K¿ q:Ö©J”ÍåÜF‘#%ón·#w‘|×+±vXïëU ¯º÷üWÖÒ•ðh«Gj€¢‚ØJ8ñw‡Ã`aØ©äôs
+vk^)úåDa%“…KåãVYH13ø ŠmG+4ÝtÝM9”\k
+ü“Å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$†âÖ•Æ'Ëý н.ô' &
+endobj
+1201 0 obj <<
+/Type /Page
+/Contents 1202 0 R
+/Resources 1200 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1199 0 R
+>> endobj
+1203 0 obj <<
+/D [1201 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+314 0 obj <<
+/D [1201 0 R /XYZ 56.6929 769.5949 null]
+>> endobj
+1204 0 obj <<
+/D [1201 0 R /XYZ 56.6929 749.2381 null]
+>> endobj
+318 0 obj <<
+/D [1201 0 R /XYZ 56.6929 540.3599 null]
+>> endobj
+1205 0 obj <<
+/D [1201 0 R /XYZ 56.6929 517.4049 null]
+>> endobj
+1200 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1208 0 obj <<
+/Length 3336
+/Filter /FlateDecode
+>>
+stream
+xÚ¥ZYoãF~÷¯0ò22`1}‘lÎ<Mf=ÉÉd×ñ>%A@K”DD"’²â]ä¿oUW5/·í Ã`_ì®ó«ª¦ä¥€?yiãHèÌ\¦™‰b!ãËÕáB\naîë Ék–~Ñr¼ê«»‹/?êô2‹²D%—w›Ñ^6ÖÊË»õO‹ß¼ÿçÝÍíÕRÅb‘DWË8‹¯>}þdôøðÃ矾þ÷íû«Ô,î>ýð™†oo>ÞÜÞ|þpsµ”6–ð¾âžyáã§ïn¨õõíûï¿{õËÝ·7w=/c~¥ÐÈÈï?ý".×Àö·"Ò™/ÏБÌ2uy¸0±Žb£µÙ_üxñ¯~ÃѬ{5$¿XÛ(¶* Pé
+Êi€dLíó®\íhöÔ:1À ¯{(šGšª÷ë~¨-k>´Þ¸YÊÄF6K§bzIG*U†ùévyGîRWûGjy²Ä¢;×Ô Ûž .?ÇSψ8‘Ò©7°¹
+ÈùYÄþe€,ž-¯’Í©ZuÀöuFå[%Ÿ¿Úç@(µýX[î@ÏG¹­jrŒuD2ã D
+lô‚ÃÎé
+
+ˆY1Y^(14Qo¨Ï[(I©Ä+É91ìÊ –í¸Ê¹žùZjzrÉÆBl!þDIjfð¹>í94
+CDžU=yØv{òæÊ.NA=Žç-?é±á vË‘a_;Rº¾¦²®§€CÉœ
+‡ÍÛáz
+h Ì’kP—†Ã`ñH¯-xý˜è"À5o°œ)Æ)® ¨`¦¬;€½×ëÂU¯Š*1WCΈ#ƒ˜ðÇe_ßçhN6áèÍ´Ïã`”•,¶l&i0õ¹*Lý‡Ð­všˆ}µK&2O¥4q.!Ur —yÁt%σc ƒä ³A
+“ÂtQ9k‹Ž µ()¿ÖŽz¤1ðŠ†1zÏUÉ
+J8¼Ž½€Ò}™Dòî!ÝÚïo&)¡€û,dÚët%<úƒ¡êœIÞÔû}}F(³•ÓãXCøq‡=ô^öv@fdäsä†
+[A£ÍPáo4ÕzÅ
+ˆü‘1ƒ½¡¢Ö‘HŬ„´ãÑÀrЬDcT¼xO.‘MÇŽCšµ„Öþµ#\ÍüÝ‹µ„pvð®Îœ“Z–Ì÷uR`-¸%ð²(GÎc(b&,C½—{dëSw<u¨y)(xù ”þê¥=«rÃÕY>Ch^Q¿7Q5'¥\\ÏjDFÿ·‡›!xJáI(W¿ºs~eÄ™ÿ:^•†<l®ÝM‰a}±©ë/Þ…ÈPà:æ›ú¿“ ìü绀ÉÀÎCdi&ÇùvŒ®ÝQcd6º>M¹ÌžÌ65Ï4´zFF#yõH®<ÜÚq£G8¾vÂ14È'ÇKçt7©Ïx·œ‡ 'Ñ…Þ“ ë³ºGmÍds˜r|€]¥`ƒ]áÌ3©´""õ`´~@/W!ÐÒ‘”z~ï嶦²ÆšÂYÆ…sÑÚ뇽àa´«Yõx”š×z£‚ÛÝPôn2Mlýý£KŸ»¬x*† PJË¡þ¯º¥Ór@6²i_ î\bf$@±‹îF Pjð–ÑhüÏYan 9µtpÎñŒÛ˜žP l¹Üš«0îL_ ý êùãø¼x@ÔÙ$žÕ¡R9 TŠÿÂ7mŸ 0è\sX;u®(ÓNÁÀøB5ðG¾‚smY­ÂWÍ’æ%û«„ø»Ï”ÄØÒ‘\I¤^g±0„‚v!\‡-KeY_àvV°Ï¶nB÷ÆI¥I_úÆ$À˜ÂßOP4¹’S{¶4@¢:Å›]>ÍõÜM`Óì@ô^Ê—¿ð$㶳ö ÷=¢Œ†Œó#”k¨u°ˆ ÉAYÙ_)^¸?{K¥Ɉ¯®ûê©bÑ°8¼D €¥Tc¨‚ž‡h:è—rXÙË;F uÏ#Þ—&Kž)yb"­ú»1âñ™šWô `}Ä2§e"òÇé±t÷Ž-O¤C«´Ã=Ë× hôÚ}É{©³UHoY¹mæûsþØÒ¨S4Œ9r ^ê²)í­f)µ¦Ü‹2ew Ú¼¥«!tT Tʽ¹y“ÐvšœDtßóM1\¯Ç¤axºÜÎêU$|7Z›¸K@méEP5
+¾_í9}OAÜvuó›óiGoÙ€¡s
+4rÿêçºCt²¦ûc:•õN¾Lt@”¯CUS¯¶Í†_:ºŲ̈÷%͘
+)×ÙœòþYOIÿwB)Îendstream
+endobj
+1207 0 obj <<
+/Type /Page
+/Contents 1208 0 R
+/Resources 1206 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1199 0 R
+/Annots [ 1210 0 R ]
+>> endobj
+1210 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
+1209 0 obj <<
+/D [1207 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1206 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1214 0 obj <<
+/Length 2391
+/Filter /FlateDecode
+>>
+stream
+xÚµ]sÛ6òÝ¿BÓ—H3B€ ^žÒÔιsIZŸûpÓv2´IœR¤Ž¤âª7ýïÝÅ.ø!ÓŽï27z °X,ö{œð“3‹8Ué,I#¡©g«ýE0ÛÂÚ» É8K´b}{{ñê*Lf©HcÏn7ZFÆÈÙíúçy,”X
+E*ƒh¶”R¤Z+·—Ð^ƒF“0_½¢÷uÞÚ†ÆmE_¦ˆ¤O„hìg N„——›
+ †j@°* ^nl¹¦Ñ¡Î«ñ6âSjPc8æÓÓÉüæ]¾ÝYâf©ÂMu&ÚŸ¯=¯$yøPYå±(†*’‰HCeÆt åI‡ò´UÓxŽNí./·tm§6'’B&A<ÖXGf—3Ï×zu¥ÂG x©0&IÎíÎ2ÒÐmT "…=äÜï%¸`G³X¢«ä9Ž¯DjŒ™vû¥'¸Rt.=âMÊP„”Þ¡“wÇ털¡: ¥3f˜Äó]Öà ¥Z‚4»Ê3^>Ô iæÕÁÖèqiwYK;ò– ä¥ìõqe^;¶‡#ãßïléiø³l A°XB’yÑ 1í-¯‚¹T@Ø4D/ÀoY•X:òY(ƒùuëWê}V {8óñ‰cŒOüfôù%Tai¼‚vMjåXœ†õXf{»õ±œÐ8¤eLʘyɇîøˆ±ÜÄ\Uÿæ'ë܉cWmUŸRʹ í„A,¢$Aõ¸¨#»_U@K¥Ð])9àŒhdMU6/¸•M€kÄ
+ ~Q*šUF¡0©”,Áò8!¤·¡8BŽäªÚï]ÊÁI‘—î$ ^ÔæïLßcc׎7í8šàC§"cý<'*õÛYtpÚŠ5ÒÚ5³„®KŠM”PR%lÓRº<O JiÔ©©°ƒ¦W¡‹4¥[Ç6쇉w 3/í=A~ºþî%H—°Y“ ]<˜.¼µ¥­Y:—S‰ ´-"“&ÿû9sß´Yݲ£šùñÀêK¤Šä™úãàäM›cÍÀa½€]eI`î´’°³VJ’„t@×y³ÊÜÒìŽbÔüzCk§êHƒÒZ>Çi¾«ìÐÉØDJ.‘¾P³&èIìM;äÉ9£ ÿ¯8¾ÏÛÝT=ï‚û‘ˆ‚’¦LêSÂrûÜ€Š]äèÀ;CÀÑÝg
+Î,- °Æ‚íª¶~"ñùì
+ié“‹ql|,WÀ¸%ûú0
+- æAJ%G3„¯
+r -›¯<oð:<|—}îêô0†g-)×송ã
+ /ºÝÙÑáÌØ»:kì#ýP$ÒHF¾òÁ¦ú‰™ï]Bp/Ø<
+õ¼©hÁÉ‚¸N‘¡öATúškÄè¯2lqÔV´ÔXƾ÷¹0|°‹ÀЄøžî¶-Yü‚ŽVžSç*Uù¢%Òs.™R¦UFKz4n“œs †˜pÞ0‘j3ŠvÈ Õ鿳9'ŽSPIHÀ&¡ímÓd[Ë<çå”s[¦ÌÀä¡JA%˜xŽÑ‡j¶â´ v²ý•‘†@‡àó:¡EêsÖðp¬6­Í0À58j¡d98—µ‰°N›ÏÖ¨*2žoP„‘PõÙígSEußÅ!¦ÓQìò¤O³¾ŸÄ¦äo<w]½¬ƒ+¤¿¯•§Œùz t5œaϹ¤¼ÁpQ…1¦T<·¿gûCa. Í²í‹†šìD˜¬èØ€Èäš|Ë!w#‚!¼Ê–ÉxÔŒ¦T(ø4—3GGdEÃøþ°xþ›µ>ÖE=€^tîÁãTj!ÂEŸ¸§ÿ×"UP½_pYëão˜œ;›?i?óðR»?}òªø4Z˜| œ²ÁöÊ!}3ÜŽào^O‰8uåç«ëÄ+߯§ÙØëzó}áÉbB¾IÏ]v‚ƒ3þ’
+O§‘«AV ¢¾¶ã„¡Ÿ³¼Èî
+h¸2êbõ¡0¸؆†kÛ¬êÜõªŒUmF„¡?ìÙ•9`<Àu[]ÚuâÓ«²ÍòRL)è}Õ‰0Ñmí³“Ï(ì4ëµ]ýhs\ôð5” Ü¡m#¼ý)4`A
+•R hôs n‰$HÎ^=ÿ·]žì¡VÇú h_
+™Ìd‰ÀÈ/ti$ùHsÍi&}ÉŒÂA/ÄKÔû64miKÜ „VÞÕp‚½Õd_T5¸7–#×Àù}ßåF1†]êÀÓW¼­*q¶=ÖìšÄËüÔ]ÂÚrªyºM¤I¸}üu6Cï€ÖÑôo¶Ï'éw<êF‰8 “§Ý 5Ò©v: Gˆâyn S—ZV»%äz ®œ¿w7 é©ÀÖ ù ‡œ³\óèYÓ8“ad#î_UG|9e©þæ2ºTsÊÖë׎¾¡±Û<nÙξΠÿWËjÈ)qø…
+endobj
+1213 0 obj <<
+/Type /Page
+/Contents 1214 0 R
+/Resources 1212 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1199 0 R
+>> endobj
+1215 0 obj <<
+/D [1213 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+322 0 obj <<
+/D [1213 0 R /XYZ 56.6929 496.5566 null]
+>> endobj
+1211 0 obj <<
+/D [1213 0 R /XYZ 56.6929 471.7746 null]
+>> endobj
+1216 0 obj <<
+/D [1213 0 R /XYZ 56.6929 154.8032 null]
+>> endobj
+1217 0 obj <<
+/D [1213 0 R /XYZ 56.6929 142.848 null]
+>> endobj
+1212 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R /F21 702 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1220 0 obj <<
+/Length 3046
+/Filter /FlateDecode
+>>
+stream
+xÚÍZÝsÛ6÷_¡™{¨<­pø
+T ä^S°QÄxÂõ`#ËŒµ¤í³ªüsy7(ØÓÀ¸Y§M^•$>¬)Ñ«t]çåÝ¡‡Ó˜¹ˆ¸³ö×±T,9xe¾²íñ¼ˆ%pÆ\‰XÁ¶¤H¼äÖ®®Š{·ñÙå Ø
+®‚VB¯ Šú'4 v\of lŽÆiMlÍÂQñà ©ó{GmEU}Ú¬jj_9Ï1ÁÀ\A÷HæÕzéÂaµÇúÑ-Òb¾SfEîʦ á˜C[:[l¾L—A#j·Æmƒ½;pî~Ý!}Û«Åc&åàÍ‚qb!Œìçyz^žü«2ȬY§e =ƒ ýwdéé¼î¯™Ëï_­ÝÚ¿cãeð•&‰Dl’„ÅÚDû"®6Í7’qíÊì t»ë~]ñŠWo1%¢!§kbË.Èé–U“χ]îm+¿Ë«Û‹óÿìÙý¦šUÅáuVõ=릕Lédèú«Y™àX½½Þ‡=ÿØgr_Tº }-y ³öE°íñ¼<…d:VƒÊhÀÒ'œ¼è¦\¦Íl®jH¤ïA–éƒ , ·;mŠ¼cʨò!­©nS¦ÀxΊê2׸õ2/ÛêE fEZ×û.Tú ñ¼TœŒ+°*áèR©âa‘£ÏÆ:…Ž0´à°¾¬¨Âo5€v·'X
+PÛT¡\¸¾%kXNF‘¾ Ò2«¬nÙÒÆÝU0¿· 
+[/7EÑ'ÁZŽÙ"-KwÈ–v.Õ×]ÔokK9gFƃ¶”GLŠ ¡¥kªõ§Á›øÈŠêõ¡Ê!{ÙYÌwìtƒPj@f:‘Lê$ØËUWc8æx³˜ÏHdÔ瀼º ùŽÁŽ¶†YEi:†Ixwä5ùV‰†p/ðåÝM¼š¬eÊÊè%c¶]ž•vĦ"=„ܵUD G°ùuîêA)᪚ 1¨—Û÷âg;áôEµ)²6|¥r민1f}Öúlu„n¢I×Íff?Ša0šÕ2lõ
+ ¿2ð=ä`øýØÞÏ7 (NAĶç¦]€*Ò&8ú±{O _¸Oð±) W×} g+#wø={V'f#øªUH÷ÀØ D-ÒÆ aW¶^™³$Vñ'ˆDë²^±SÈ
+jÐúm9 Ÿ\m3­šÛó3íôØ%¿+ýúŒösÞl0ã)æ¸z„ðp++©ÜÔ(ý(ò#LÞaNåٕ؃ÞLOéûê2Sßí¨(‘wg4ühÔ‰žµiNÍOnöi¢å5ÞÆŒæòÆ)Ýf šN/d`tÇ¢îm|2Sê ãEåð/þf¤Væ D’“¹{|Ó+¼‡æ>§ËUáجZÒ(—TžÀQ?ÞLû6ÙúÍšÔšT~1iéšç&Ф½®ë8¾Ò}Ó¤¯‚GJAÖÀdb-‰'Ëë†tÃ
+èe•m
+W÷*ʾ…îmw¯ºÚw£~0罧ٕÒwœÉUV1ðñCXZY¸„Æ–ÎJØúì¯äï½Úƒ·7o¿L‰½ìq¤»æׂ‚J³Ø¼è´ÚÏ‹(#¢! ¨Œfá[J>€Gú£ÁwþiAé$(|ÎVY„uhØj2~,óz¶ÿlå=6'/ ļ¬(Pú2”÷“ (”oô¬ºw[÷«Aù(éy©„
+¸i%Q€eü%ötE%yÍž Ú,ªz/|J1Iëzö‡(Mç4¾î„¿­Òph3¼2ôj‚qu…»óç9©Êb8V;Ûò#*Tcß©M2l|WÝÕÔ²‹)¬
+©C¤é½#Ê#_Oa–Nbæ¡rW}:tùﳫ÷'þµßŽ #˜öÉÁ¶‡ésKøMᢥ‡5óÅF}ÛŸá!Ã"zéQ¢´üƒ´mr KÏF,ŠxÊäåÞcxª
+‡òuÛΤÓ{FÕ3t,Yâ‹ýèB
+j{$jçÅàÃo97erlª*£¨bbÀì\„δ’>ÐGŠ’¡“A£?MWÛ²¡éî\Ca˜Ÿ†ÊÝÑ™¸ÕG¨ž§yºVT;¶ª¼`LüŒ5$i>ÍÝ„÷iV•?„Ê°myo.áí æm‚YU*äXÒ[}ÌÒ’
+Ñúš¼6+Z| ¢$’ w;`]³>éþìÂEDeOT'®'L¢Žò¾¶óKªµAÕ¡ºUõYÿE%ùØN¾ ¢rÔm‹ &«é mÀò–wß´°GH£à5ප˷!]i·oOçÇEïVˆfœhk& ÌpŠØËÈÐu÷nßuˆ°älót»-
+Þ$diö2ªs8E7YUuÞø_½ì°‘ϪÒ•ØZÌ&-Ыj©Û×A$)'§ó‘áÅ:$–pýVÔÖÐdi^í¾@þ÷:˜ôhÍ*}µi2 &Xn(I€Ú€ù&XŒéª ÒŸ×òiÌðàØ]žG9¨vCdûú|„'[mODÐö‰U||ŽR.Ìõ9¯|þØkQéà£Ý½AG"* %m¿m(iÛ@„mãqã% ¨coçÀ•/{g‡I½€cI=c± Ç î>-ò¬E€ð^f‘­ÍƇÄZ$~ æý(k«›Ý¨/ü"§µ¸ýñôÎK
+§; ãëpÌí~ð9ô Rìc¹}ò Òÿ¯×v!Z²Hà
+8³’~óñô‡§|4ñÿÕŸ¹î~YÀeq¾íeã¹a±L,K‹Î6OE«˜éXîØ:‹ÿ®æ¹÷endstream
+endobj
+1219 0 obj <<
+/Type /Page
+/Contents 1220 0 R
+/Resources 1218 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1199 0 R
+>> endobj
+1221 0 obj <<
+/D [1219 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1218 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1224 0 obj <<
+/Length 1962
+/Filter /FlateDecode
+>>
+stream
+xÚÍ]sÛ6òÝ¿BôL…üÀõ)Mœœ;W·g»OnÆC‹°Å)?T’²›»Þ¿],@‘•(i:ž1‹Å.°_Ø…ø"„?¾ˆbk¡‰V,
+y´XUgáâ æÞŸqG³ôDË1Õw·g¯ÞÉd¡™ŽE¼¸}ñJY˜¦|q›ß1ì8„Á›¯Þ]¾ÿùúõy¢‚Û˯Η"
+ƒw—ÿº èýõë~x}}¾äiă7ÿ|ýÓíÅ5MÅŽÇw—Wo £és„éõÅ»‹ë‹«7çn¿?»¸Î2>/%ä·³»á"‡c2©Óhñƒq­Å¢:S‘d‘’Òcʳ›³ G³véœþ„ä,‰äb)KAü˜è8I™J¥
+Y ›i®}Zp=JŽž|9¦§Ü8VÎWÔÑY-É5”ŒX†|êdG®U1±¿ÏX¦‹H¢Þ“Ù4ïi–#¢Ã½ísBÑ ´I[hŽ>AÚ¤­TÙG,BÕ¶ì‹M9ë8aÊ%Ôç<'f©ˆÕ¾çt$gç:EýD"'æFš©¹Cæîˆþ¥èׄ΋G$}tG÷´úç1$z'Ó¤²±DÍÆ´}a:6D¾M¿é'F€‘!tÝ©‡¤{xr%Y"g"FFA·1«nƒEÆÖÕì7bl"¶çïˆ6²¾mcé0!wdOœë×™cÐÛ«qE Òë•Ùcì%Žƒ æIšsÝŽ ôÔq‡¸ã<È3S¡#Ü­›m™œ­Vfƒ yèþ¶5g›¢&¸|$DÝЗ®„
+GºSTþ †z<¢Ñ‚“O¼íà"žrvZ@N# €™›¦©Š¾·¢0¯NwŽ˜—¢, zpe Ô¸LìS3‡ÚÜ„qlj6m IÁ¿À× 9+;²·æL€)Üÿ\“ÊࡨóŽ@RB;‡À‘­¥à›Ñ§,Îy0ò ÄM#1Þð–q3a@—;Éñ’¨·W7à•Ðùô¨ XãûÑ™­ êN¦^Â:4º¶°NnpûÚ4ugˆ Û/iðàÈ Ét}{žÛYÊ…çêˆ:{K!TeumωqÙ.£OÝ´Uæ¸Óa
+ çJ©™(P)5ÊÆrñœ•Þz®ÒÇÚàÇ’ÿ9ÑõLµ½Ôp3¼2ýêUkƒëX¡#+î€×ÈP—=íÝÝcÏEnÜ)3úÐ]‚PóH‘&c`”ˆ½|NE²OpëKl›Ù¼gØÁfcêܧ9«·!A–Y_<;:ØÓ
+Ããð†ýŒÉ÷µ&ÕݳݛN5Ÿkߔ룩ÁO>ap¨ø$Éâˆä#öN£ïWYjZkñSW^¬@hçÎD2$Í—U%vó¶<Ûº¨¶0S±ëaN¨$
+Ç]‡&]‡VePñµ'¼sL<
+endobj
+1223 0 obj <<
+/Type /Page
+/Contents 1224 0 R
+/Resources 1222 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1199 0 R
+/Annots [ 1228 0 R 1229 0 R ]
+>> endobj
+1228 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [491.4967 546.2465 511.2325 558.3062]
+/Subtype /Link
+/A << /S /GoTo /D (lwresd) >>
+>> endobj
+1229 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [55.6967 534.2914 89.457 546.351]
+/Subtype /Link
+/A << /S /GoTo /D (lwresd) >>
+>> endobj
+1225 0 obj <<
+/D [1223 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+326 0 obj <<
+/D [1223 0 R /XYZ 56.6929 744.5408 null]
+>> endobj
+1226 0 obj <<
+/D [1223 0 R /XYZ 56.6929 717.3918 null]
+>> endobj
+330 0 obj <<
+/D [1223 0 R /XYZ 56.6929 594.9189 null]
+>> endobj
+1227 0 obj <<
+/D [1223 0 R /XYZ 56.6929 564.805 null]
+>> endobj
+334 0 obj <<
+/D [1223 0 R /XYZ 56.6929 340.8686 null]
+>> endobj
+1230 0 obj <<
+/D [1223 0 R /XYZ 56.6929 316.529 null]
+>> endobj
+338 0 obj <<
+/D [1223 0 R /XYZ 56.6929 259.8095 null]
+>> endobj
+1231 0 obj <<
+/D [1223 0 R /XYZ 56.6929 229.6957 null]
+>> endobj
+342 0 obj <<
+/D [1223 0 R /XYZ 56.6929 197.042 null]
+>> endobj
+1232 0 obj <<
+/D [1223 0 R /XYZ 56.6929 169.8331 null]
+>> endobj
+1222 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1235 0 obj <<
+/Length 1102
+/Filter /FlateDecode
+>>
+stream
+xÚ½XKs£8¾ûWpŒbyjN™¬“ÍÔNf×ë9eS.„QYHŒ${ÿ}…<x
+g+•€Zô§îOÝ­ŽlÃR?¶á{¦åcLLϲ=#LG–±Vs7#»üTæW߮ݙ˜ÁÔ™˸囖ïÛÆ2º¿¸úãò¯å|1Žg]LÍ1ð¦ÖÅûۻߵ$ЫOw×·7Ÿ—ãÙäbyûéN‹óëùb~w5Û÷l¥ï”G®oÿœë·›ÅåÇ—‹ñÃòÃh¾¬}iúk[náÈ—ÑýƒeDÊí#Ëtß3žÕÀ2í pŒt4ñ\Ó›¸n%!£F×€Ù½jžë›žïÌ:œØ mË7ƒI03f^`N]ÇÝ3x?S˺´k!`†AÈQ„¨Ä蹌câ ’wzüP¸­Ö¶mžçü„±bªúÂõÖNÔ_=V/«Bõe$áºÇnâ„0Lˆ1)53(“UO¢<ͪ¦(J,$…íX1¾¢¬‡Õ-õ&d8¨ÉQ˜s麿~ËúW›þ•QNä¯
+
+¢ð‘ ÈÑRý A9h×JÂØ
+¡æù\¿<Wéi˜0Þœío_Z
+\†aˆ2©êq†U_2 22þ yô²½ú­È’ÖfƘ YÕgKKdÄËØù¦Ue+E%÷ã²–ƒ=*—1M³ZoÿøÑ«QQeJÕºp£èæOµG×ú¶s\3(zÓW/¼èÝjt]Gá¾ïá*ÃZöó½ ¹b¡€X55mN@§Uÿ— ÅJ£ú¾øw,[’ªø7ìì Î9 Nm‡Ĥ%ÀkÊ8:d ¾åQº=tç•kZ¿ ï“(¬3ç”ÌÕúªN£5Çr7 ÝêôôYð§·]³ÃM‰j»ô»ª]}Íf¡¬@Eî!!V)TMáŠàª®ýèÁƒmt¡Ã0#˜ :¹Î »ÿï-HÐÈç7[rHE\U¢³Átugã¢Æ=?y¦:ô&  <¢ëô:%²ÎÝØœž·RE• 3Åi¬¬H~Ðu·äzfq!ÔqdÕ‡ñ«ï^.å&3Óõ}§¾RrÜÆ•’kMMß f•Q…“÷Ðòú‚êgÓÿ]Ágendstream
+endobj
+1234 0 obj <<
+/Type /Page
+/Contents 1235 0 R
+/Resources 1233 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1237 0 R
+>> endobj
+1236 0 obj <<
+/D [1234 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1233 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1240 0 obj <<
+/Length 1162
+/Filter /FlateDecode
+>>
+stream
+xÚ½X]sâ6}çWø:#U–mMž²)I³ÓͶ,ûDƱEâÆX¬-ÈÒîþ÷
+l° Ø&Éð€-ù{t¯t%l ýó Å 7lnB†03¼Yºï¦ƒ³oÀö#Püêðóë5µ ¹E,c8-`996†þ¨kA{u¯>ß]ßÞ|\öl³;¼ý|ׄ¡îõíýôéfpùéÓå °Ãp÷ê÷Ë?‡ýAÚeenï~K[xú÷è Ýôï®ú½ñðc§?ÜùRô#ºvä[g4F†¯ÝþØAr‡ÏúAÌ91f“QÈLJ·-açKç¯`¡wcZ©FP‹Thâ‚€‚ÒP6ãТ„nõ€…P× Cù –HV‘zI¤íÿeݾ‹$™Ì\å=N QiûÏ‹ô¼B³CÎ)B߇®÷ô(Cñjˆ‹D€¥ þÌe¬ÊT×-§ñpÉù¥ üsZ¯‡—1´^Ïçõ×"2J_G9PúÌ'ùËøÕ¦n7¬væ}Gþ¶ñ
+$r{Y$þÚ
+ææd=Júöcƒ‡m)±™†…¶IÍ ê/iW6N¡CcáMÀ– ©MÌJýs‹ƒ<ÏÆÆ:ÿmÆéØ쥱Y>vQ· #œVÇV*j-%¨ MÇ4›³Ii˜š”[•4Ú Rg2Š‚ä G©á—Bg·ÕÑcjÆmH,Dh–2r¤úíÅz×è±NEOƒ©;=Eï#HÝè9Ø 6´&£o¦í+‘Ld<‰dÝÅkg_Ü¢Åì^Ä5ü=ˆ R"^ºái”‘™û¨Ø’©ˆ
+fB !ª¡3%ŒÀÏ¥±¨E£„¡¼9ðÂ@DgC猖_øzUñžDsR6÷q,EýáKözðÀ Ó°±«DCúû@$-TËê
+ÆÎK›Bjr~ÌϺI“gà[ä7Ç8Ä>FTIÍÕÝ›ÏÚs↉)Ré<¨Y实b;ja!,€?kÁ÷i Bù
+¼¤-‚’s©ÃoUïöd|ql>tRäß6…*W­q"±¿­Í2´MËá$Žöî§fž¡GnŸ\}ÚP*lqÚˆ<×{¬i|Î'm«î)ƒë‹ßŠ_´;¬ž}¿œ_¾›z/s²»:&´puLlGÝ5HFjíŸi0ß^DRÿv2°endstream
+endobj
+1239 0 obj <<
+/Type /Page
+/Contents 1240 0 R
+/Resources 1238 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1237 0 R
+>> endobj
+1241 0 obj <<
+/D [1239 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1238 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1244 0 obj <<
+/Length 1750
+/Filter /FlateDecode
+>>
+stream
+xÚ­XÝs›F×_¡·Ê3ÞÇÇôÉMíÔÆiuúfÜœ$&(v”6ÿ{wÙƒŒSYi<–»½ýüíÞ">gðÇç¡°™yó òlÁ¸˜Ç»›o`ïÕŒ«c²†\ß/gß^ºÁ<²#ßñçËõ@Vh³0äóeònñòÇó_–7g–#Ø·Ï,á³Å÷W×?ÐJD—o®/¯^ývs~x‹åÕ›kZ¾¹¸¼¸¹¸~yqfñPp8ï O¸¼úù‚¨W7ç¯_Ÿßœ½_þ4»Xö¾ ýåÌEGþš½{Ïæ ¸ýÓŒÙnŠù=¼0›G‘3ßÍ<áÚÂsÝn%›½ýÚ ì¶G§â'ÜСLÐãƒ
+$€ªM8µZŒ8S²½¦®Ú#ó.O*˜‘5q–ª\×V©*«ÍÍÉùdInÕŽu
+)^”óCíiõQÿSÉ{,ª£-S»Æ™"Üñ¬®DÇã"×2ÖÇçÏ*rU%l:à?H¤u¤ž×i?©ª€¹Ìª iiZ‰bŽ½B,ǵ#œŒG¦AõÁæ·—Ÿ÷ËkT Ó¯ãù¢eÂéœû0ª3V”سjÆßj©ÕàG¯?¨?sòö†£¸¡ˆø­–et¹ƒÑT9í ´ª–[Õ4˜Ÿa|Ž"˜‘§³à±0ׇéÚ†¯纋Zá‰TSÒs“+¬¤Ü‚]àÓ[¬”9P«„¨Õžžø¡c¹Ü¦æØÂ4Ìx+ÊÊèi{=Q±¢Ìfóqf°©º¾¿øP
+ÛMSIŠ.îáJ¦À_D‹«5-ê-TŠ¢q¸  ˜¬ÚañÿŽl
+‹„S“Q±cþì”C×£’s=(AùAå´$kz’/ȽS´Òºeȶ
+‘zp=朷^EÜÄ9:ø "@ig)lÁÝGÄ®¨5Q݆ÌE£ËƬ“Su÷"˜²76•Îèãÿ ‹cð»jò‰*ƒ¦D¡kªŒî[ÒÒ6˜ s©I'ÝÐi»
+2г¦…¶sïŸp}׆û¨k"öT
+endobj
+1243 0 obj <<
+/Type /Page
+/Contents 1244 0 R
+/Resources 1242 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1237 0 R
+>> endobj
+1245 0 obj <<
+/D [1243 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+346 0 obj <<
+/D [1243 0 R /XYZ 85.0394 285.8176 null]
+>> endobj
+1246 0 obj <<
+/D [1243 0 R /XYZ 85.0394 252.9894 null]
+>> endobj
+1242 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F21 702 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1249 0 obj <<
+/Length 3961
+/Filter /FlateDecode
+>>
+stream
+xÚ½[_“Û8ŽïOÑo箋٤(ŠdíÓlÒ“ÍþÉÌ%ÞººÚÝÙVw«bKŽ%%éûô$Mɲ{î¦ê*•˜¢ 
+.q"_oþñ/~»…iÿù†3iºýœ k³ÛýM®$S¹”¡gwóùæ?â€É[÷éœþre˜Êòâv)sf€ÿ¼–ÓB
+<Ó*ëIAˆ .þ6Uµ­¶@²EÝûÞÇ¡Ùà•»ºI?°‹õPïzßÕô^f¯ÀÛeÆaör¢R8ºaW¿´àšì̽µkZçZ¿â Õ—T(Eÿ¥zY>u]y¨—›#̺éërwæ
+Tlsu]ŽH5#Hº¢È˜ÔÊŒ%Y¡5
+‹êØ G§a|Ú¸5Š‚¹¾ïuÿì[ÏõÆ7ûÓ÷NÔ~n‡Ý–Úå
+±C„‰Žšdqô¹£Žî¹ô®NÏ„gØzªš
+Ãå–¾p€y¾¸2 ¶¼ð+¶úËÃÍ,k¦™ÈÌÉWpüÿtò3–…†¨Æž¸ÙÕ€Aˆ°EŠ°s}9‘H –+n_È2® 퉪›ç²yr8ÁÁ==¿}ùBöHìbGÓz’˜ ák>
+À¥®ŽZuô.P#Í#Uœˆ«„ öbñᑺ)TÌþ éGpÉ­ž(ȃaà-\dü¯ÒEÆg‚Gh|¯wžqyw`Eþa]Í€ŠÐS… «¦àÜk¡ÆáñÒ¬~Fç¬Àš€ÿ>ðÍØ߆
+ p
+ä0lÍëðKò,xÃk»'¥<W?¨±­Ÿ0œÑÏ¡mÕYNòÔ*¬K’Qø}Ûõ4³MÙUÝrñùlJ)ÎrCìŽ;Î0Ï
+šq«K›£“Ì•°Ë0Þ2ðü-|\@‰ˆÂb{˜˜‰÷°@& vque šÔ˜7‚½ÜáÆÕ—vð!7æ`ð0tuóä7b¨÷ÉXÈ¿•ÇÚç”ðtŠÝ!bo+ÌÆšj{1n+Y0e P\Û)Õ帩N®òŒ:œ¯Ú_á©f˜Ëóª}ÂÝ…íÌêÅ»úuŠj¨–ªv»½³ek<"ÛPˆc×Ú÷ôáë˜-[ŠñØ‚4õŽpÞj̱EåÒnw-«M*M™ÑY9vŽ ’P²u˜!ŠÎTÖ 9Uäæ—àÀ¤57ι‘UA/‰Xx‹ƒ–Ó ¼ÙµåÖ÷„!ÃzWoü®ØÁÎcýT½^UÐz¤jcThOfC¨¬ðv_7iYïíñKt—­Ï6}{ŒÞ9œÿŒ°˜J ÂâÑ` XRæ$MÜ*RN‘ºžãØ8ÆE¿ð`ByÝïRªË~©\’Pnž«%ikÊw¤FÌ1D3̧¡3òhÄ}¡)üºìË) rȸD®˜NVæ]êÅ> ßÝA£ÈŽ¯ë.¡º¢»@å`|Ø.¨NpÁ”È_a©f¸•W°w´FìW!JwöŠóTÉKè’‰RÈ°!¬ip*Ýä»m uuÙù'Ú0„üŠŠhÕM×ïÌbØP ’m[Ï"|4_š@*ËŒ-&y˱Ùn¼g‚TÛõ|ö’©"K’Ë$>F£pI¯ÄíÔgGûu7—("¬«Ó Çé*CJ ôBÜæÒ2H¼íïN?âˆËtHg#餀arkOœƒA²Y…å‚™\Š¨°K®ì…Î_ÙL©®¸J rûÕ¾ëËr¿zÓ]òˆÈâ«RDª1F>S–ÞŽäð!‹'>ƒO®3Á> >“tŠ$ÌA9Ö½ /ІÉaäpí¡+Ÿüw§ ûqZϬ¡_H…{0ÝœSI‰]hº.¨a(U6vŒßgÏ\‚¯ÙÔœ™_•¹RÇ@šd»`0²(pGà•¸”R]6˜Håvíëí31–ÿÈë¬Ñ ëQïΠŠ1ëÕü‰ áª>¨œp59e9ªŽ6âmzŽãw7Uç;>¼ Ç:Xê̾p8æÆ­»,ø‰]\wÊt¾îhþÒØàú÷d_y†–œV@}pš{gô/ƒ…˜«„¥†‚&OËûB{ï‚*6Y=÷ì¢;üúÜZ.w.lz:ãiú粧Ö÷²ñ-ç:–¢ÿ¾«Ÿšr×%¯5?eÈQ¼QNè‚UÓ¸¬Bj¶t6:œYÚ,>Ó®’ÎdÌJ2X…xÀ”LÖ Û6³7|$òXÖæÅ}Bë ‚ ÄYt”ôø«³hœeXêÀÒ÷$bøh­Ã •
+H
+
+u;RªËØ©\žÖÒ¡WÊTÆâÕ¥«LÑ Ó6r–[ÀëSfñ÷w¿Þ¯ÞþJNhA’?ìסˆà&ÁƒaG¤nk »¼ÝVõ7Je¹¿BŸ6ÛØûîãgú4½²ây˸_¼Á|ÍäÑðøa1) ’X¢ã *ȃ±òÈâ>žŽ·ÞN÷¦ô;v/ñâ”?Ç7~·/Ù9ÇSqÚùûÝ +Ï âQ‡oIŸøÎ9Q'¤Ms|?†`ܧ°i0 ;¶§C’è7í~?4þZQŒôcïÚµëÒ ª¿láÂê•› ÑûöD§£Ìå¶úVoÎÃb–3]hq•w$:g>Nø,Ó`/#]íàŒmãŸÛGúÜ%#<ø;_¨Yü]{Bª ]ÏËüe/*Ï2èx˜Vû+^‡c½/õÎwÓ?jûs}·4ŸÞú|Ï@^f&ßðÄÌØ»
+(¼%9FG¿î”ĵÀ‘š®t˜ÚÑ)¨÷E@~<ÀC |[g;ئL»"¶òÄÿ ÅO‡Ž¨l¸DŠ”?° ‡ø˹«^.æ"•AP`Èu–
+endobj
+1248 0 obj <<
+/Type /Page
+/Contents 1249 0 R
+/Resources 1247 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1237 0 R
+/Annots [ 1251 0 R ]
+>> endobj
+1251 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [222.5592 220.8351 286.2499 230.2447]
+/Subtype /Link
+/A << /S /GoTo /D (statsfile) >>
+>> endobj
+1250 0 obj <<
+/D [1248 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1247 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F39 885 0 R /F23 726 0 R /F41 925 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1255 0 obj <<
+/Length 3390
+/Filter /FlateDecode
+>>
+stream
+xÚ¥]s£Fòݿ•—ÈU a`€¡ò䬽9'YûÎÖ^.•äK#‹ZŠ@v|W÷߯¿„äMÝn•fšéžþî©ó
+HS¯dÄg ;[èkØŽ‚—¸àÊúO¢°¿…¡¾ºÆ¿ïd†?]dáäŸ{“Ÿð¯;Í|·ðñÓÃõ§8êtô›º¯\pžHùÊ:³
+s %òÖÊêvÝG€y P!ÊTˆVÌ@ÝrfÍfÚ•RÒ?Eé>Nw:ûÕI·osDmSJEšbU”ù†r4ܾÞ3—\VÜ÷Çù4¯-çl#ÚܹjG
+¸—v>ŠÕ|ŽÊb²ç9Ù>qÄ9*ŽòÙÌ®[WÍ‹Ý4ü‚V‰O؉@“]ªÓ»ãû\M’ÆX…²ª#^pŒxq¬8vŽÇ=ÇJü AtDCÁ Úu¦97*ª'|‹& r“0 åSO踀pdç0ùè‰]”b¥ZqpƒT»
+laî â  ªù®®KëjÍ;)´Ž¸ªHC© Þ¨dz@Ç•"ÝضK¯úSÄtЗÒ~šÀùOá»R™Ÿj¨)ûØGà¢ø¯™z*±–(0.MØÏW! Ô©K?//Çö5~œ(òèq—®•ÝdL‘Õ’ÝþëêîãåÍm?Üq¯©í³K ]¤—¨‰)öæÙn:l’ã(?LM:´eö¿&CÕÛ‚-¿ÊˆK§ I%©¤Cú[°¾ëo#ö¸®À§&N¾ÜK}ë¸M±¸gÎÙ2¯ž,£\p¶¿âi/ÃÈ¡‰t'³Ék½•=v-à b89,ÜèÛyÌŸ ôN{Ñ£.ç]Þàš0‹öE¶“þcÁ:0—Ê°²ûIÄ.ÓØ5G¸† wÓU¥§ÔÕÌÑ\òY?UúJ²uÜÄ;(rtþ b¯WWžý³h«I(ÝÃ8;MC5BÄð¼ÔÔ‡TL—.g㎒ÔÛT
+dì$PÈÒîÂ0jwÍC[IçVgK;ûÌ
+oÑH¶vUsëWA‘vÈ+×Ë+Zj(FÄ <QáP¥ä
+réc7{Ý„þyºV›sÔ7¶ kµÿÞ×ú1°ï }èAÐEqÌ®°}R4m1;l[A]Ÿe‰>¾ƒÁ?ôúÀÈ4M‡üŒ—Bà­Ŭ°=,”jG½;±sÆL1Hþ9 ÛS°øø:âþÃÀø)yàÉv#
+ºâ yA—EÐ$ëFNýÑ€Z¢¼à®;p®á)LGðÝ•8ýèàí
+9W÷±Àn >XH•„ÙøÆmÍÓÈkŒ9sKŠF>6JüX§{ Bñ¢8FMüŒ)“
+â,vCh@µCœLãöiÙò‚ûaø"Ý]üR¤§¢³§ú`vy }A!
+GÂJpS`ä ‰^¸DÍ+Ül^ÐöxˆÌªÚ±n˜
+"RT9‰½20EÅ<™»4C÷‰NÍ'篫àØH‡FIÛmø&ñ-ÄF
+‡Ò§ö°‘„
+âC`D~ÎÄÔÀ…Ç*oZ*Mø¡Uæªíþ]k\‹gù.>WÝv¾½›Þ|ø…Çl‚lm#0äÖí³CSæÏb©{þ [bFÜcôtž;CÿµÅò0JЋ§'¢69à@¸P,-Фq\mW”rvÞŽ|eÿk¢Œ‡HÊ=}ÂÙA‚×_:z
+f‹ü¼Æ]fvåM§2‚¬_²÷¹Õ«³ÜÎ꺒©—VUÿ×3.yt­¡êjbçYäM¿@Þ€½,Ò |¥ÒoA8Ǭ†Í5 ³˜º,];šÚ«LùQÚ¥UÝ"F¬$ðU’¼é+¢8uU:1ïè~ *ÖÇ3Y×n‹}üýÙH>t•ÿûgn»ß
+endobj
+1254 0 obj <<
+/Type /Page
+/Contents 1255 0 R
+/Resources 1253 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1237 0 R
+>> endobj
+1256 0 obj <<
+/D [1254 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+350 0 obj <<
+/D [1254 0 R /XYZ 85.0394 396.2024 null]
+>> endobj
+1060 0 obj <<
+/D [1254 0 R /XYZ 85.0394 369.4308 null]
+>> endobj
+1253 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1259 0 obj <<
+/Length 3376
+/Filter /FlateDecode
+>>
+stream
+xÚÍ]sÛ6òÝ¿Bo•gB” ><¦©“sçâ\wnz½>Ðeñ*‘ªHÙñýúÛÅ)Rt.—™Ëx<Z `w±ß$ŸÅðÇgJ3m;K­d*æj¶Ø^ij˜{wÁ=N¢.Öwß¿éÌ2«=»[uö2,6†Ïî–¿Í5KØ%ìÏß|¸y{ýî—Û×—©œß]¸¹ŒÏß^ÿõŠ w·¯ß¿}{q£øüÍ_^ÿíîê–¦´ßã‡ë›iÄÒÏ™Mo¯Þ^Ý^ݼ¹ºüý«»–—.¿<ÈÈŸ¿ýÏ–ÀöO1Ö¨Ù<ÄŒ[›Ì¶R ¦¤adsññâçvÃά[:*?³DèdD€‰èÐp¦¬U³TY¦L¡
+CñAF—*™¶‘ÊËç(2¿lTT"¾aQqÒ
+ÒËét¡/­½š’V‡ŽoØ,cͬ 4--( TÊÅ !ÿEåš0Ãß®n)«X ™ð´´T”šë—2½3Òú ŸÕ%ã–,N¥|AX%jÍ»‰ó—‹l»Ô|-™‹èÿG.Äm
+UVfÌhaºµü ¦Ol âv·¢ Þñ„O×ôJà=¦8|S59%"Íú˜’SnxšžãXÑ&¡~q¶B¤U¾h°¾Ã‘ûç±zj!¨wÃuû¤k¨(€4 EÝ wUœ¥œëyÆ…<×ô ¤¨‹5ÔÚÐi±\ û#
+¬-9¶DˆéÃ[¬‘Ó{¹ÇLOêþñ×X¶CÚã»MFÎ VÂu9ÑÃ\µóå=Ìæ%Kš¨‹ía“5tWFù– `U÷uµÉÝÅÃð7 .Fó¼ó³×?ÿru{ ‰ë¯—œs¸=jn}),XŸTFeN¬XªP­tösÏȪ<{¹Rƒi1}·¤óWÜÍæÍb=lùðb¦H§n‘†'÷®5N™Ž;LàÑwtwÚï6aÌ߈
+À°9@f´Oõ¥4mÝØáò€øLÆþY(ìº5‹ìP;Ý3|{-íôãŒo™yÖ4ùv×t;J†Nôý$2#l¿9@´$Öø¨®XôF•ûÅJ‹†~—ŲüÎÃkê-ä›j
+ܳðB¸®OK3­f]¬ójÖb¹F\\l–ÑbSäe3Høx"@ ¸œ& Å¡ Çl‚¹<ä©=ȪEª[çŒðSæ Ъ¼”פƵ–q|»Ûä[ ÚµµqÀ¯$›FC·Œý[‡ö|(«ÖUˆTQK¼·Ö‚ªhcæw—ô’O¦,æ‚Ÿ(õÖÍO`[³\澕š·9=ƒãÑ4Ž”m†6r3'ú¥ 8}z<Ñ¢¯ S™8™×»|5zŸäæ©
+ß]¶Ï?L—2j;¬<(ovhÖQùiYm³bÌ@98‹í‰ÝŽ“ÄL&"°ÖöwûÇ[ˆ¥i0Ìýj‘ˆØD˜Hñ1aa¦.'MQ‚øUèßòlyÞ"cY£á/XdkÂ"–»÷ªn¢º ­nŠÅÐ"Ñ©`'d’€k„‚¾E‚å‚{ë“à2 Å;ÑÑ%ÁŠ‡$ J|}€ü#ÏwÞçrŠêðÛáÁ!­Ü›I\úHi/€Èl¿òoV\,†ã·
+9Àî…A¶ ‹
+Úþ…Ú¾z„Œšwäí¤MÝ·¸_žû$<&_6m{¬ Û XÎöŠ²Øf›hïkŽ¡¯•‚) Ió$ -Ö ýø†"Ó´OÄõjDxRN£?#°›N`Wiø¼C©P©ô
+Ùäˆ=ü}ÙN'`ŠV‡HC…ŸòŽ C(NÓá1Ûl\AúñÙ¯Ãòù ŒüÐIQ­óÍÍë÷Wd* 2 Õm_Ææ–¢.IæEEý<vú”„ïµ`€Ú ~V–ù=œ´)Ì‚Ïñ”OYï ló”=×a}A5Îäåªò=¥úäÔ#Kñ)/f~h3ÇûªY÷Ó±m‰·oÁ@µ´¨mÓfù ’->Víð³ú¼Çœ/}¡QÝÅšPã€ÕÏÙ=ÖHȨŒ™>6 ÛK¬°À‰yÿØÑxªÔNŒ„3Å•é¼ì§^Žný
+:8ìʘ”tF¨ÎW[º÷u̴ΧjÈ+"¿ìh€Ò „è<eÛ0ƒƒEØî@ñ€¼/µ¸-S‰<Iã\Î&b1_¬³Ò}B>#×0i›O´”(G®áEsû‡·]—УþˆK9݉úºšH˜dü”(ºéKÑÎÖÃ×Jiš€Á^>ë–ÚP¤@:Wwâ"Nù«Š)ßÆéfÝNá½Ôô°Ú͵G
+É—fèsýÇÎCÒÿù§3†endstream
+endobj
+1258 0 obj <<
+/Type /Page
+/Contents 1259 0 R
+/Resources 1257 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1237 0 R
+/Annots [ 1263 0 R ]
+>> endobj
+1263 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [154.2681 85.4256 203.5396 97.4853]
+/Subtype /Link
+/A << /S /GoTo /D (notify) >>
+>> endobj
+1260 0 obj <<
+/D [1258 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1261 0 obj <<
+/D [1258 0 R /XYZ 56.6929 679.1143 null]
+>> endobj
+1262 0 obj <<
+/D [1258 0 R /XYZ 56.6929 667.1591 null]
+>> endobj
+1257 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F48 940 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1266 0 obj <<
+/Length 3662
+/Filter /FlateDecode
+>>
+stream
+xÚ­ksÛ6ò»…¾=2x’àܧ4qrî\œ;ÇéMÛ4EÙœP¢"RQ}¿þv±
+exý^™d™$‰;B¬³¦-va½©^t€4ÖQ¢¥r°¯®C)Ó`S·å¯Œ‰¢g!‚lwÍMPà,"»Ü›–ÖVõŽ–ˆ-þ·Þ nˆPólrÔ²ažxñû¶*ó²áR%‘,ù\zÞDÇ/ÚQ/BÉT ¨žó(ÕZX¬M±ûVì²Ï ~ŠÏU r-i¾oÊÍ“c’÷Å‘ t™hÇeV5uˆ<®æô®ÒHhå%-IÎNhIE‰ê 7õ 2ƒÕƒl¤jÂçNMø€jŠH+‚ÅQÂ(%d¬,ª‡çbFPÁ¢XpÕqtBDÉŒy®êm[Ö3ÁJ^h‚:¢ÙcAc³-rbw‰ :(Ý7í,+ìW$ÜëMn†¡#-¥ç¤i³¶Xƒà (%EGáð\æÏ4ͳÆñS¶4Ö`»rimí$7¡P2b*Y‰Žê7éiuÅ ìó˜E0 %âඥõ¾ZÒ”ÌZcUg1yÑ4Ùî…Ûš^·ûÝÆ}²Â_¹×Ï¥ãÈï —îméæÙ¾±vïš*ûV4rk4Äô@Ú|—5ÏÑij²ˆipúq2òD$q@aŠ!Ÿ‰$ÔÑ Ã¶›:Sç°/\3sž|5CpÜ”‰8ú³‡×€zRox/ ½ã¡;׶ÄMc¥¡Iþ\ä_pšZ›£—Ùº8z+X@ Ʊƒ¸ûLãý}S´ôuö”•›¦~þô†&ïÞ|¼‰Ü×õnU.@1D!†›œ$øÖ»O·ïÿCó5ßSAÖ¶`$9ºX!„$»„â&ÄL,4ý•iÖ­º¿ýp{Kœž3‡¼l‡Äšýv[“¹"þšèå5PæAf•„ôéè‚ÂCï7­ý€R@ÆxLìH Ê$ØWm¹†IË.ÄAb^›éàs½.
+µ+òý®AG;öM²tgIwP3´¾I
+Èm؈ø‰,QŸõM(¥R˜^ÞÅ„³TX³NyðÎjž¿î |`J9,4mCP´âtà0ÁÞlžv). £Od5H©…p¸miÙ,.ÝH†/<’C½ûBÎKcVž˜¡}yæJš 4LZ&A¼æ`9À5ò“ʉÆ9ÇC/R›ÐÚ±=Ûðêná”Æäe')Ì—µµvxí?|PêlùBo¾lêÈ+Ǫs4\”<]›Ó£0Ž[—ÀsÖ_^A†“
+B=¨3AÈCÙ3²Ê…d&l_¶Ÿ&É
+?‘œ'ßAÍÐœop½Rèö‡C²ÄU vVÏ8‘êÞ˜éK¹sjR¯~òsˆÐ–-žJAÆéíÈ´#e#8Æ£óçµ— }šUµgúP¶ÏÄ åh6ü–üqÄU’O™í—ئxÓýæ­Ìúso|>s9:\Ìkf®N¡vï
+3MÑ9Üñî»î’ÉÐéwô¾¤±­<3ßû‚ã—ð(f±>‹¾c€ËMýCT¡ç.”&Žt"Ò¾ÑušE!u •,”RðAJ'ÿ®§+NÝ´HËîä~ºc<ÀÜLTH¥Ðf¡‹ wÄ_~TšJ‚êÍ­´G-Ø…×·k±xWƒL‹¾XsØGmåŠÅ`ADÃ$2Ú‘XµKÅ_®
+÷P®·•í£ßµUa–Nv_¥Ø‹å¢¯ß?·eÒ
+õ >#,—ᶮ«‰ ÈÐÊtÑG;õjJû äÁbä¨#g¼ëÈÐy§µÇ¦®Šv.²€Ò”ŽÍ°—8i¢gÕ!{iºZªÎ¡ds>q‡éí;·ÖË!ðP5'£–„íÑüRk§uf_<”ïê…؃ò®Ì›iÜJ#ÁŒ8Ï@5ÃÁ0naS:ÕCNP1ò;²Ü~ãšùê>Õ½bGwÅŽ‚Š½ª( B/¶Ív`Áey)&…4ºúGSÃp`ÿd¿©(­A4¾­šÛÆŽ]Ã2ÀúÄåj³à@'Žæ {²½[,h€œ ¿mÇÕ®<f Ås˜¾Ðh©®^N´ËÁ§A}*z­Ûþ&[³ Ò~#¹u¥ãk¾#+Lð ía…,÷^±á„ý×8ÅPÜ81Ç,bšKýsðœJh9Œô¶9«“ ˱9K͉øäœÞ\v›eN_#Ñ9óR2R©PýÆ¿ñ}lüÎP\î×[ZE­Ý¬¦w®E’h UA‹Ç^Jâz)§ºÞb’`¼¯?RPèðÍÔa6Ǻï±d—lÇ]²=—žˆTF±²~•^íž\½ÿ0“.ôÀO_¨y ÊPó£ï… MxÁˆ§”è33õ7èc\³É™÷ž"` Æœw±}¨Ó.¶ƒêBßïàó'©„Üjì³”;¨)éa܃“f’4Ò¦¸'“ãMλµÓq/$<îÝ¡Åib3Ò0j^"‚Ma¯’ºÁqY6Ù#Ú9>Üþüþ~ø:£a›íÀˆ÷U¶#„à
+ ?ÝÝþìØ}Rm=wåánÑRt?û‚§§bƒw&d ®“
+ƒq“‰³ìu@Sþ†EŒ€úkŸAß
+JÕñw}Òví6äk¼ƒJÝE?¾y,ž³o¥­Sû«
+endobj
+1265 0 obj <<
+/Type /Page
+/Contents 1266 0 R
+/Resources 1264 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1273 0 R
+/Annots [ 1268 0 R 1269 0 R 1270 0 R 1271 0 R 1272 0 R ]
+>> endobj
+1268 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [108.9497 292.4924 172.6404 301.7078]
+/Subtype /Link
+/A << /S /GoTo /D (statsfile) >>
+>> endobj
+1269 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [293.8042 246.568 355.0043 258.6276]
+/Subtype /Link
+/A << /S /GoTo /D (server_statement_definition_and_usage) >>
+>> endobj
+1270 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [395.8905 246.568 444.6373 258.6276]
+/Subtype /Link
+/A << /S /GoTo /D (incremental_zone_transfers) >>
+>> endobj
+1271 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [309.3157 215.2488 370.5157 227.3084]
+/Subtype /Link
+/A << /S /GoTo /D (server_statement_definition_and_usage) >>
+>> endobj
+1272 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [305.9683 183.9296 367.1684 195.9892]
+/Subtype /Link
+/A << /S /GoTo /D (server_statement_definition_and_usage) >>
+>> endobj
+1267 0 obj <<
+/D [1265 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1264 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F48 940 0 R /F21 702 0 R /F62 1050 0 R /F39 885 0 R /F14 729 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1277 0 obj <<
+/Length 3827
+/Filter /FlateDecode
+>>
+stream
+xÚ¥]sÛ6òÝ¿Âo'ÏT,ðóÑIž;mšsœéÍ´} %Èâ…"U‘´âþúÛ/€¤D;—9ûAÀb,û ªËþÕeœI®óË4‚8Tñåjw^>ÂØJp–i9Æzsñý;“^æAžèäò~3Z+ Â,S—÷ëßI ƒ+X!\¼ýõý»Û?Ý]_¥Ñâþö×÷WK‡‹w·?ßpëÇ»ë_~¹¾»Zª,V‹·ÿ¼þpsÇC‰¬ñæöý Éùç…EïnÞÝÜݼ{sõçýO7÷þ,ãóªÐàAþºøýÏðr Çþé" LžÅ—Gè„Ês}¹»ˆbÄ‘1R]|¼ø—_p4JSgù§Â@›DÏ0P›3Äy_¦q$†¿mm}µ4J/šnË­fÿÝÖ¶›jÑ컲©[†‡+•-,wZÛ vƒÜøþ]”öT)Ò"­¸Û³miB˜VAhò\pþãvæE×vSôU0%{×ki0aõöðÌRÈ{°eýè°Û£ejeÚ†zÍNÆû%Òs¹T¹
+t
+¿*ÈãX!ݶ9”]Ñ•O@ŒŽòźè
+
+d…}qèJÛÂ¥˜$Y\WmƒÒ v¯xjÊ5‹Fâ®0A‰d;@Œ†þŽ;s¹»LO…;SNÈ`Dä`íÞy
+Uó(ñ†Å¡æH:;0Å£ób_cF”™J\:0ˆürshvK
+°0ÌÕ/\†J•(g‹„’Æz¬±‘ÓBh0Ç"-õhd²['Hµ[Žõ2½9fÕäŒ"‰ƒ<ͦ\d}5 r®ùÜïQ…bˆÑP\Êâ‚-Wq19¡0Eä)qú‹é)ÅÄä ¦”ÁP)«÷­p
+J[°E܇ßQìÅ€)ÅÑ”b‘á87ªFé Ë¡ýªU5/YÕ¥Ÿ?¹½-ƒq‡ u3B~ŽPL% æ÷skŒ %Gæk.ýh÷ {•LÒ®Ü%ñ
+ãf“ůÓá±f™¸ï4 $‚SJn7sµE*{¾ZY„X 7z”tšŒr r­œ›8]Ü~xŠäœ<
+ÐiY‚õGQÀËN&1‚IEZÏ<HX8ãO\ÍÌB0ÞòHÁLôò
+œÆ¢Ûó(²æPÙÉÙkΨlÕ<>ò[—Tï"W½‹bbã?Zþ› WÐqw‚m±ÃQì,û°B´Xm‹úÑÊ«B6xõérve×9
+ÈPÃïR‰¶cú‹ìƒ"ÑòÄ¢]þD$¦µ³±HÌ&Ÿo0 DY¬ õcC½óU½ é‘ µÒmø÷A†Á¯¹Å‘#*HïúòŸrÅ#ôV„>Äø73T(1ÐØn…0ûDi9Ç…c¹¦Ô14 BŒ‹<Ìð¢bBÎ]èVzûᓬP dgw ¥lÐÇÜö;ç7Î÷‰œuá²F”äôHˆôJ…‚ïR¥X~IëЃ’ÖaÃkv¸ä ¹t¥ýõj)2Pò·¯lÇ¥€Ø zÓžâÈè‘3ÖþS5¦=)ƒŸ q!ÒÓcæÕÈÜÌh %¹,óðõoË)['Î/qÄåWBCŽeÍÉ0qXQሕàH0w¼ÞÁ½m“|Ïcú݆"Q>s&-.Oò¯çv·oÅ¡tµ&T®Ù?.6²x§l÷4'Ê@Õ'¾T©,ñÚÕ±º`&‰>Qó¯ 'N9ÏH°½WæÒpžJ4ÙÎlÇA¬ãÄ?õRœ/lL`ò$¹û™3D :u©»Ç™¸! t蟃Èç©{ÝN©Ê>yàOG…aèTöÉVÒ>nK~ƒO]œ~NÔŸužœ„ßÌØ4ÈR¹Ûwï¯CR2κ –»z²ÂGC/ó[¹N܆î‘nÊndI}ÝñøqÁ=õµ€=¦/TŒTJ¡)4*\ÜvÓbhÃì‘S‹ȇ3/FÑ*ÑR*}=Šc½E{,bìZ.ÖM‚f³¼º»ÇšÙ~4ƒ.mÒéþRËã«@‰–/&”X[hÈç ÐznzÆÙÊ7ŠÏ°¯\ÎÒNžâ8GM|Êè Ýð¸w’Ú1ȵ‘[|̉Ôi245Nô­>X¯¶`¬éC<Ÿ/€¥Ñ¡2ßVÑYJÅÔ5ïã>Êp•¬Ì=÷¤¹ã^æªWU}ËÂMèwüÉF(‚|@t‰¶ùÓX˜h=yq
+endobj
+1276 0 obj <<
+/Type /Page
+/Contents 1277 0 R
+/Resources 1275 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1273 0 R
+>> endobj
+1278 0 obj <<
+/D [1276 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1275 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F48 940 0 R /F41 925 0 R /F21 702 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1281 0 obj <<
+/Length 3465
+/Filter /FlateDecode
+>>
+stream
+xÚÅZÝsÛ6÷_áGy&B € ÁG×qrnÇ'»÷1m‰²5–IHÙqÿúÛÅ.(P‚äæÚ™‹g"p±Ä.€ß~§ üÉSkD¢‹ô4/RaiN§O'Éé=ô}<‘Ì3öLãëû»“ï>èü´E¦²Ó»y0–‰µòônöËèâoç7w—“³±2É(gc“%£ï¯®ß¥ Ÿ‹Ï×®>þ<9?ËÓÑÝÕçk"O.?\N.¯/.ÏÆÒ ï+áÀ ®~º¤ÖÇÉù§O瓳ßî~8¹¼ëçÎW&'òŸ“_~KNg0íN¡ kN_à!²(ÔéÓIj´0©Öž²<¹=ù{?`Ðë^­_j¬0*ÍNÇ:6ƒ1¢«œˆÄÀªsSˆL+ݯ²’±Uö\¸Ê³ºm«éø¹\.fe·hêÝyËÌ•åÅi8øž
+=WDè óD¨´ÐC%.ëò˲:ƒIÊÑûëÛÛË jZ¹çÿÖåS5Ãý´ztÝtê¼3Y•$"Ë
+ êÓ¬H±‡ze¹0yV0w¹l–TU³–š“¾°¢mÕõnÀÔŽµ‚­3°2RÆ(7îkÕFd«D¤J§,Å Q þVó3iGójÚ-ž+˜³–Éèî;gÕ¼Ü,;zX´=¤*À¤üàqd.
+P—yÄò^¹Ì„Íù®#ô\Áæ”ÓiµêÆÕ×Õb]ÍöphS‘)£«ÑsEôLÙü’,*rî4€5ÖräÔÀ¥U€ŒÚÅ}]v¢µÄôòPÕÔû\­ó×E}O=Š¡=|a Ém!öö[ˆÑ-ç PN2%Òµnb;É`ó;éÐr[uS AÒ=€ ×jVdXŽÊ ûU©0‚?DXVåsÅ/8«£æófYWk2Úð}šãjY¾ÒsÙuåô±=©,Ggj#*`: (Ï„óþϦZ¿.›û=©L$‰IŠí™öåVZ'¢°Y>|»ª¦€˜{š"6º‡jšT":(vOÛíC³YΨí,xÛ®\wÕ¬¥¦–_~| 9I:±£«yÄýi ë"¥GB¸";I5„ˆ0ÄèÀšŽE­ª39šŽñMpj
+¡u‘‡òÍÁ½&¸V@啳3Aᙂ5±£3C•éÑÜ­&—Õ}¹$ÚCÓvlßØãÒŸ_ŽDž€‡`£àðå´Øð,6ðM>\¹0Šß¬™‘»ôÈ*ÉByð§f¶Ǭ’Þ0XÑ0Ѐ°«EdY¿&Qÿ¾[(xë ’ÕjI¾ŠVçqsÍÎÍKí¼мgDêœ~ÏßQ×9ü#
+9] }ú©ì‘0±È¬]uÄÅÕ¾¸UC³©SÃm½Wy°RÞm«¢wÛØ$’eTaòž
+rüïœH.ÄÃïõí;b¾ýÌ=´uÐÀ àïþR“¹ 8v7×òp²™øGt¸¹› q C÷rW*LÙzPÂ#  Þ&lâJPkQϘ­à„$îiÙq‡ÿåQKú¡‘¡Úhy€eÓ<nV,a>àõ¦DOèXXít(¼¦'ÇyUÏ8C[pJwu=>ÿ~"Î'7g…rØrä›l—äL›»®®ïÐÌ¡RH+%„‰ã9TÈu8‡ê¹¶6öôu¿°B¹:.¹çŠˆÖMs› e_ l\”F{GLÖ‡¿C €Z•ë–ßhBÆy?“Kú¹ºáÇÙŒ3W!ÈÂèÐõkN¾u|1Ì’ ”7I¡¾5D‚´Ïnª‹\h›î” «¦m}éø\.7¾ÂôÎ<±!H­y#×È¡$S>n¡“ˆÄQZ&×ÿCl‹Wg0Áü Ün™ŽÀ–™¶¨}Y,gÓr½bR‘§¹9*¼gÚ—>ÌÎ
+H›­ˆ§Ì_ét{D
+ÏEƒÈ§5¤T
+ÌѸCÙ«ÕEäÁÀ™óÆN†\‡w²çr)[µnÆu3n›rÜuËýÄÌ¿vU çŠh0ÜKp¹–Cx/¥ÏB» 9»
+VW™¿&å‘f[èô à\G€ç¹"ÀOËéÃ~ŒÂãGq\ž+¢ÇðŠL
+ O.‡Šü$ä"¨‚³Y¸¤m‘†O!Òˆ w {˜Ýá é|A
+³åz}ûã忉q2áΆ~ûë)Ô½˜ûw]j­Çꕺúë<@üÂ#ÓU ÅøE
+/`µ£‚[>+³ý‰¬ÙÎAg#OÛ&k3î˜SG|ˆ‚Çm±‹ÜLˆ“ ù¥é¨õ² VÆ5-“ "f*Ñ`‘µø@7¸ûàtŒ˜§€Z[ý)ÏëÏߌÀ»´ì'ý­¸?}ew{Ÿ9ÅVÅ­H'P8áí
+V
+7rWs£­0VåÕÿ ƒ^'endstream
+endobj
+1280 0 obj <<
+/Type /Page
+/Contents 1281 0 R
+/Resources 1279 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1273 0 R
+>> endobj
+1282 0 obj <<
+/D [1280 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1279 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1285 0 obj <<
+/Length 3124
+/Filter /FlateDecode
+>>
+stream
+xÚ¥ZKsã6¾ûWèªj„‚äq2ãÉ:µ™ÌzœÃV’MQ6k(Ò);Ú_¿ÝèÅ—ì­ÍL• 6@£Ñ¯AÉUÿå*²Â¦*]Å©Q(£U¾¿
+WÐ÷ã•džgÚ ¹~¸»úþ“ŽW©H­²«»Ý`®D„I"WwÛß+”Xà aðá—ÏŸn~üõöý:6ÁÝÍ/Ÿ×…Á§›^SëÇÛ÷?ÿüþv½‘I$ƒÿxÿåîú–º,ÏñÃÍçDIéqaÒÛëO׷ן?\¯ÿ¸ûéêú®ßËp¿2Ô¸‘?¯~û#\maÛ?]…B§I´z—PÈ4U«ý•‰´ˆŒÖžR]}½úW?á × ]ÒŸ‰)cA“J$¡ZV²±”À 2¦g%+¹¤dÏ…Jî§M—?mÅîP´ÓMK%EšÄj5œz&@ϵ H •…vbÇ"Ü­Ó08œÖ g×5ø„÷µLÉ=@.ê|,¨ñŸ¦.ˆïØ–õï>|¡F¹£¾_?2áÏcq(‹–^vYYMX©‚OÍhd8&!BÞ쟲®¼/«²;­¥”Á;舭t„'#´Ö°õ(Rn'Ûb—«Ž ©l‘qrF #­µ!ÿ©ð<#-‘0X˜e“h¡l š×J(cÎþ"áxA†¸¹—ì°EõÌ×W…ËHCGàÚ`ç¡Ò·¤×0…å¤Ç‘g5‘ïyȱ-¶Dqg‡,tjYÇuW4ñSÛ²+6/嶠Þ<˽ ¯±LÅ (ÏÅ¡Å“)[Èö˜³ p6‡l‡ÄßÃPåî”Âñù40XMTeý­¥¦“Z§AñWWê¬"jí jñªFâ4¸éˆJj€FVµ µîy
+*Ê(6¿%W“çÇhêêD“Âq/œU÷Ø´yR¯3|ÙáêØxy,óGjº½aƒÙûŸ{:ía#;Âœ‡²¿~fþ¬ÞRcÛSv§ìñôYݾôÓ×üìx 3`1Ë›mh!~Gæõ
+BEÑëëz¦…u‡Á’²
+m2^÷î¬S4O]é\6•AO£ÓʾÈj0€Ý±¢œSË09ä@«Ê¶OH>
+h&Pš
+B”Î?‹<=×[bÌf»XÿhÏFõb¤¹
+©õë"x¦ÆU»þŒeeNm"Ö ^¾z¢+¨à9É¢ÈåìºX‹<àŽ…úûRÏpý%]C½™›Útº3syÎ*I“LÊ® 74 í6µÖ6:N\1õ/Êϵ1:*:‚eéq=ôyä…ýû£Û5P]‘ ” L™(Nê8íý¢zöÌë×ÃuJðWNÂКY¹oÑ”ü|Ìps&ŒÝæÂpQy53KO4$léÀYƒÌ°GÂʯ?±J°~
+„¾¸€6¡è½çN¶çîPæÛ#Ð
+¥­ɳþ™ë )|üWx1
+.à!qÑeeÕŽmøoä†>áŠÈÝÉg6v”Ña8#o»Ë• ¡õ©lÀt9“y&çÁXl
+-µ/"öÙ‰fçKâ„ó<WDpxŽe›Ë !®…Æø‰Ü ·#‘0‘‰™ R „(vÜ5–êWàÄfñˆõ2Ne<VX鲶ò塃ðÚA^3XnS/e_â˜7J–ÖÎDGGtë+Æýõ"´F׋1ß-¸õèá ‰š¨4?ߎHX¹íËSµUcü0¹Wf¾é§žQ(y"´~N7½ñ#jöP´çÒ’17 Ú24Êü]ë4š(úÊÅø#¡rŠâ8z=
+i(åØì‚€cÅ$¸PÏå‘(˜Ë¤o„*Yˆ* ûù½vcC‚Gcõ0\–E&¡ˆ•ÑÓH€#^×æyø7¬0-Â(™ÜãÝì&÷+ÿ¯ãò‡ºùG§±oºkd.rç` ‘"ÂoÛ³ub¢ÿå—ha’$Ë¿
+endobj
+1284 0 obj <<
+/Type /Page
+/Contents 1285 0 R
+/Resources 1283 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1273 0 R
+/Annots [ 1288 0 R 1291 0 R ]
+>> endobj
+1288 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [339.2005 483.6075 400.4005 495.5077]
+/Subtype /Link
+/A << /S /GoTo /D (zone_statement_grammar) >>
+>> endobj
+1291 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [455.0966 291.3684 511.2325 303.428]
+/Subtype /Link
+/A << /S /GoTo /D (address_match_lists) >>
+>> endobj
+1286 0 obj <<
+/D [1284 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+354 0 obj <<
+/D [1284 0 R /XYZ 56.6929 712.783 null]
+>> endobj
+1287 0 obj <<
+/D [1284 0 R /XYZ 56.6929 687.8416 null]
+>> endobj
+358 0 obj <<
+/D [1284 0 R /XYZ 56.6929 470.2923 null]
+>> endobj
+1289 0 obj <<
+/D [1284 0 R /XYZ 56.6929 447.8217 null]
+>> endobj
+362 0 obj <<
+/D [1284 0 R /XYZ 56.6929 335.2388 null]
+>> endobj
+1290 0 obj <<
+/D [1284 0 R /XYZ 56.6929 312.9276 null]
+>> endobj
+1283 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F63 1053 0 R /F62 1050 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1295 0 obj <<
+/Length 3121
+/Filter /FlateDecode
+>>
+stream
+xÚµZKsã6¾ûWè¹jÈà ²ršd<‰SOÖñž’h‰¶X#‘Ž(ãÝÚÿ¾Ýh
+>»[þ:ÿ?ß]Ý^fB³¹É/3mØüÛë›wD)éç»7ﯿÿ×íÛK«æw×nˆ|{õþêöê滫ˌšC{á{8Ñàýõ?®¨ôýíÛŸ~z{{ùûÝWwq.Ãùr&q"\üú;›-aÚ?^°\–…ž=ÃËyYŠÙæBi™k%e ¬/~¹øgìpPëšNéOé"×B™Y¦A¶,§µÌr¦Ak™• SÁMÔ²àSZ\¨åj½îž³?öõö%ëÚñ¤¹Ö¹Z̆=¹&¸©2cR ~yªÍoŒ‰º‡ÅüyÕ,VT\w‹jE;¯–Ëí%/æußÆEÕR¡Z,꧕;ǵlÚjûB”w7¿P0Ë~×tm¦
+Ú¶ý®j¾ë\’Ž©ˆŠnp(ü
+NÀÖ­k´{êé3Y°%Ù#ÊUæ–³S–82+rÅ-4CîM…’qÍúŽJ÷5ýöÑ –DhÐL¸tr‹ÁÏ´ÜwüoÐÉÄàBæVxXä]½©ÛªNpß¿Š† ÅEÕ{iœ=Áo÷©Þn›¥33ø<!‹5¹Öà4P÷äÌ•Ì\½Ì¦«ù9Z³Öè±è9ujýJXÇtýà´óæ0Ð蛑 ,ë‡j¿ö|_z4|gd¤XŒ†OfëOÙJ…L‚ ‘‚ âŸ{eáRI1{Áô,¬º2êt_ÔŽA_¾Z¤]eAºLkŒjÖƒ_\*X[®s#”^äRIÒõÍ`É´¹!'˵Ê/Ù‡ËÌðùü/æWGªá.ô3ÐK.XéŸý1ã9Se)‰kPv³=hÁ¾¾ÞˆÙ»æ4N+ôœ »vó2IP×0Å‚ÏÁ²y4ËK®çdš„Ùü%[T‹K(Ë7b˜œJL†ÁÃœ!Ùb¾ïCÉ™ü:S|x¡Œû}Ÿ2eZÌ (‚ Gö¤J ³®Ø—, Ë`AvÈæ_f¢™(s¬ÿÈMQÈ3™–HʼP¬<Ÿø#×8pªÆ¦e
+…¾vTÛ iŒÌ™Ñ6f[/öÛ¾™Žøª
+Pp:œw%(54Œ‹Ñ\Éy#oŸ›~2%1Dž†ëbbhmsˆÏòï Š&Wº,‚b)šLg›ß˜f¬V¢ÓwIÿ 5rßhZßLˆY0ćþyš×p"GÑ$ oe‹\eÏCô!×iO\“ž:Ô p/ Aþ¬‘kBŒÄY Üv
+2™|Í\\gÌ5pPé–<\¼2~`š?ÝPò\1 %¤IÅÄ %CRâ!©àGL*† þâ®JÄêfôÉ“;9l±" Þ?®¡ñU}½ä‡ `ÉÆè錓ŠRBϸ?ë@eØR‹>µX~2µ
+tf's"·pû3ÅÕßO.âï%iK
+V§;\0lÐgà³cÆæô¹Ùd$É—î„£9H+¿{=c®3æ¸æ°ZV»ã ‚¡åùÑ#×Äðé¾öDR‰tüÆ8BÆ÷±©1v»»‘É­ûýýƽ@ùÝK[mš1Ði Pi’àR7U¿«}‚z?î‚9@z…#R€z0SúÐä;—µƒ @9 äè±Á
+ûÀ–¾,vxCÝ¢@5짼°)€Øz±}4wµt=â1Üšq¡S×Ó§ £ 7.8©‚””§z =m°d’•ó»ËRÌ;â©Ûê~íùâÐÊ =¿!æpœ7¡§öOZÈN7•yÞd^µ°a šýæ¤jeÜ.e`#d¿/t#ÙüSµÞÓ•ÇþôiUµ¢s ÐÆ
+û×–Øâa`–i¢_‘£Fݦ7Õ+(/X åÞ÷{Ðç },º=^ã<Q:Zîጋƒfäa?íb
+Ù‡k)@ïr0Þî‘gÉ`âþšÎúsEUĹa9µvO««Ý>î:@÷u€`¨#ŠZŽâgàÊîªË ûçS××HÓ=0÷S£ÑÖ/ƒ¿ã4NÀcJ„
+7øtµî uØ—=0FÛß6lz›ÇÖ›ùòð¶ÀGƒnS‡Q¶mŒJ|mðxfÃË$²Â¼rþ1ä:ã ëà Îpêíñ–·Ì…(Θ&†O7¼îU¦ã'HY P=RVÂ2Ò#RÆ´7üõëS»s$¸‡ Äâgçû:x…«\y®áAåÄ•˜Ö¹Á\C8&
+þÌâÄ‹9<ß‘“÷×,¾øâ×t‡§†ÊÒÍ4D`öø¥ B¡õ$вÈu!ì„èÿ¤â/
+endstream
+endobj
+1294 0 obj <<
+/Type /Page
+/Contents 1295 0 R
+/Resources 1293 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1273 0 R
+/Annots [ 1297 0 R 1298 0 R ]
+>> endobj
+1297 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [213.0783 309.0057 261.825 319.7901]
+/Subtype /Link
+/A << /S /GoTo /D (dynamic_update_security) >>
+>> endobj
+1298 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [398.1622 184.6228 446.9089 196.6825]
+/Subtype /Link
+/A << /S /GoTo /D (dynamic_update_security) >>
+>> endobj
+1296 0 obj <<
+/D [1294 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1293 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F63 1053 0 R /F62 1050 0 R /F48 940 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1302 0 obj <<
+/Length 2626
+/Filter /FlateDecode
+>>
+stream
+xÚ­]sÛ6òÝ¿B÷tòMˆà“É“›Ø=w7q}ssÓö–èHc‰tDÙ®çæþûíbIQŽ3éøAàb±X,öV jâR‘º˜d…N*7™­ää3Ìýx¤' HI뇫£×g&›¢Hu:¹ºéÐÊ…Ìs5¹šÿ6M…Ç@ANßýrqvþã¿.OŽ3;½:ÿåâ8ÑNNÏÎ>¥Ñ—'>œ\'*wjúîŸ'¯N/i*e?œ_¼'HA?ˆ^žž^ž^¼;=þãꧣӫx–îy•4x/G¿ý!'s8öOGR˜"w“GøB…ž¬¬3ÂYcduôëѧH°3ë—ŽÉϺ\8mÓIb¬Èaÿq)+‘)H™+Dj´‰RÖjLÊ ¥|½*g·‹fU Ï«¤NÁÖ]¢{[G¬‘½Mgo%Sa 7Øü×»j¶ü]J]µÇ‰ÑzZÒÏjÙniÔÜðÄ|¾9Vù´jÛ€»]”Û0ªhÐV›‡jCãÇåjE£ºa¼r6«îxüå¾Ú,©O»YóžLá¾õdÍtÛ€9hVU`„6I4ÜM‘Z†…sÚŸ 7x:VJMA’ÓOaGT³ÝŽøÀ½p88(‚è$8ò'ÁÁ5c3ê]SÏ«9Ójx¿«#Í«›ò~Å+—-òüúÌæÛ1&6“Ü)²^7uEX½;ÔF¨ù„$£«a‰ÉÁjó õµ
+|³–ÉÁ×k•öhïûgéFjHOù …ªêòz…È «
+Š}‘ˆ¢`Sû”„Š'F÷ÉÔ–ÑI°0ë¡=QòYš¡BB”gHÜóºZ”èÍý²œH.wGl)PÙŽlùoBÖ‡Ú3îO0=Œ­¥¨ÕPþírv¿*7ôMrEŒa&g¾„ƒA¹jÂÂ|!ý˜otæSœ˜…–Bë}“C)n¢¨N…¹ó7î [¼Ž™ÊæÙÛg?Ù+!^u;ŸY‹V±¶h8Kz\TÀñfÌÌ«vI+™0)F'c9XÌâ†Òo¯#ºÍLEdr›Ì¿Îý¢æå…D‘ (!ó¾ªõøéfÿxÿ|>WJh)Õ›ùuþæÍk£ßŽïð’jÂH« #¹@ UŠ:
+P¯–
+»ìùN<ê¶ vj:vŠ}bL›ë¿oiâ¶n¸¡áî ÷–éjÛ– “9ŸkšØŠ`d—4òʱ òÑŽvÈ +ŒŽ6ç)%ms¿™½o$½ŸËô©R®mLêú‚3äýaÀ—8Ô|@E#´÷>û‚I®ëAwS—Q€G„ÝÛbûr±7À8Ÿ5äõCïq–“°x—£íkÈÞsËfÜ%…>…ì=Kø+µ:k…ÌÍ~? ‹OO¹êx†}JP‘[çãc¬a=p†‘­;Ü,Û[‚ „4”Óïw=)DÝõr»%×IâÂÉ~€G4ß~L‡­B
+ãìçؘ1©aýÿˆdM3endstream
+endobj
+1301 0 obj <<
+/Type /Page
+/Contents 1302 0 R
+/Resources 1300 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1273 0 R
+>> endobj
+1303 0 obj <<
+/D [1301 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+366 0 obj <<
+/D [1301 0 R /XYZ 56.6929 725.2846 null]
+>> endobj
+1304 0 obj <<
+/D [1301 0 R /XYZ 56.6929 700.2184 null]
+>> endobj
+370 0 obj <<
+/D [1301 0 R /XYZ 56.6929 148.5316 null]
+>> endobj
+1305 0 obj <<
+/D [1301 0 R /XYZ 56.6929 118.3446 null]
+>> endobj
+1300 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F48 940 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1308 0 obj <<
+/Length 2999
+/Filter /FlateDecode
+>>
+stream
+xÚ­ZÝsÛ¸÷_¡·Òˆ‡Olžr‰“úæ.ISg¦3w÷@I”͉D2"e'íôï.vA‘2e;I'3!´X,‹ýø°œ ø'gÎÆBgf–f&¶BÚÙr{&f×Ð÷æL2Ï<0͇\?_ýôZ§³,Ε̮ÖY.ÎÉÙÕê÷èåß_¼¿ºøp>WVDI|>·‰ˆ~¾|ûŠ(}^¾{ûúòÍÇ/ÎS]]¾{Kä¯/>\¼}yq>—ÎJ¯X‰¯/½ Ö›/~ûíŇó?¯~9»¸ê×2\¯òùì÷?ÅlËþåLÄ:svv?D,³LͶgÆêØ­esöϳô½~è”ý¬v±u*0 ÒS´YœhèB^®q À)œÐo\Ò‘£©wó ¥)§™fž²"E,²$c–¿NÈHaQ©d†z¦ÍÊ‚oÕÛ²ëŠÕ³ó¹–2Ê©s—W«zK ͹ŒP7ÿ£ÚoKXïÎ¥‹l<±˜/ëê!Ôõž~¯ˆ ä^ãù›rù‰º]´oXVÅ„»r³!Ò¢À…ÍæÆÅ™¶Él.eœY«üšöm°¦å¥Q‘/oˆôy_쾞KXxlttuÃ*4¼¬”ôúCXÑÂr¨`u7yG”¶)–%®*ÌVV¥˜Ø•ÚX»Ä°áAÉù­™ïWÍ'n'6ʉØhvõY‡íº|k‚n©7Ðý ð¼Ôêá|ɜͦDì²c³= 
+ØY(cUÑJ¢* ©¢•Šê¦+ëªEÿÑYT|Ynö«²º¦N4Œã ÜqdFìD3î 3ZKg‚ƒç·u¹zÌ™€Ð2ÁòÓÖ‹ˆ$KÇb{{ATeJÛ`0ù¸Á ʤR!Êz«`£Àuwåm± ÞH3ñ¸¹Ìbi!ãprQ¹*Öù~Óµô«^ÓwÚPÎÄ©•!νÛÏÛz¿[ê&W„{Ð@ ¶©™všJ3rh26
+€šßª˜oór“/6ÅÔ6e¡ibߦT93Þ&˜܇æ Íʲޅ,ZWT`°¿ß$`é ‚¾à<ÇÝK£¤ìîʶÀtìDT2ÏÄ|%¹*¬ÂQ “-QßUã¼<•ÒÄ8•Ý /Ÿ/þCDØ”Po©•X«ísjÿ÷ùxGätx}‡Ì£­ã´ñ¶î _nH¢mþ ýJ¤à(´ø˱k
+w(îÐ^0­Ý¯‘ãxYUEÏÓ7T ®Y"y*òËý®ì@Í™èuAXaHìÐÕ˜¹üwúš¢ZñÜuEßÛ|WÖ{&6ù|ʧ!& ðj_¡Œ{ô
+%
+"=âó FÄG8‚Úʱ³³@­ìÁµäWáéžr…åc» !eöÆ9º5@¸ÚÁñ·X…›€EG]¸§H ›Oòà‚ÑùðhXÞÁ>6ŒáŽ
+í«€[ŸÑ•˃’Hâ ·dÁ]õfOFrJl‰ð˪Øäð¢(Ó¢8fìB aÅ<€¨r‹KÍ+æöù¾Çùw¸R¶ξf²ãñ¢¹èBzXæ ]œXÚ|]„dtH,eu” ¥ú}ã|3̾»º-É[+€FÝdâù?Üf<éÖÇAS«o¸Óè/}ž,õé×NCÂ;¾Ö˜X!÷c˜¯Né7d?…àÝ(ÝgýM½È"8øÇ1î4cÌÕ~IÈäÔVà}†„Ä *û˜C@­z3}'\ŸïÉl<GMª´û†/`˜Í óïð¥³)öõwÒ@ éAþÝ)ËcžµÚG€I
+„kÙÐ!²ø­CVLôk—Ó§Éw€|÷ˆ‡ü`Þ[è¡#‚‘'¼KãmŠUO¾¶Ld’<t57Æ€»ºd\Ó¾ïþò9gEN¢­{|éZÙâ©´=Ê™ä:ƒG¾ §VN£lhу
+¶ÑÄur¦’,†cÑô‹óÌLô%'Þ£ÓéΟBƒR gº¯Áа2u±
+endobj
+1307 0 obj <<
+/Type /Page
+/Contents 1308 0 R
+/Resources 1306 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1310 0 R
+>> endobj
+1309 0 obj <<
+/D [1307 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1306 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F41 925 0 R /F62 1050 0 R /F63 1053 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1313 0 obj <<
+/Length 2984
+/Filter /FlateDecode
+>>
+stream
+xÚÝZÝÛ6ß¿Âo•šå‡(‘i²ÉmqÝäwm´¶¼"KKÎvû×ß ‡”%[ò¦—
+®p!Ÿ®~ùÏְ쟮8SÖèÙ#¼p&¬•³ÝU¬Ó±R¡¥¼úpõnÂ^¯:¶èÆ×â‹Ä
+ɬÕñ¸XÆ€¥¤°ó“sÑ8sy2ŒNu4/ügZ*Ó™Wª™Ìj-Ѿ‰d*É,Õlž}oq‡§e:‰2
+δ’ ¹ãx;_$"ZÂÙæä©Lg)È1J¢äÙ§™`<¶VOvK=nkøáf'g¯jXЬ·¦0ï¢7±[R"{ˆ H—Š¥65Nßu™í„:*šùBÁ®0AdV­‰È=OYä{jY×¹ç¯ê–ˆæððPCẉВ·mQÝÃKj£v›ûÖú°_y:[¯÷yãgÚÌj/`ùònÚ¾³
+èÛÔ«¹äÑGü—·Í”b§Û'–Icͬoâ¯C âSÛ`sDþWcüC[n¿ ÿÌJýˆ)ÿÐ4Lªžq¼]ñø›ºGÂ-)ßÞ?ú3O;H"&dœ’ƒä
+ã4NŽ0#IXkX”ìR0Ø/…xÅ9þSW9eÉå\9ûäû¦‡Ô0y¤JMDÙW%I´Í"vùj›UE³óïEEχ2s ȶÆgm²U10۬ͩ駊cê´p¯f€xIDYìŠÖ÷Ö^ÅOdßÕ‡Ê3Ö? ÎÖ$¥ÝfíXàìÉÄÝð*#‰ðé Ñ<5m¾ƒ"DŽ—¡uS—eýè¹õÐuågËÊ'?KMÏ?ºï$ŸaQ +™Åiíx=æ™}®i(t\Î¥Àgä4§²‡¼ƒ·_ÞqHx)„¹3é¯ò_9—•K”>Ò辬ﲒšÊ¢i‰r†„Þ›wžã\˜’#O=‹‰ªl—ÕäûÏ„"é Oci¤Á°åš¼ò ·o—7¯ÿMô$d÷¹sp
+½¸r™ßp{ª #§PæÕF½â_[·Vn‚J™ÐÊö7ÁñNo>TÝ<‰OU QLE ‰¶‘i$3R«®V‘
+¶t€ù»³h¯€
+Á é.¸ù ¶™.kYê4Ñ­óMv(=CÑœ$Ç|÷ÐúTçÕêW®yå_ˆïHãº1¬2Šlað‹élÈ¢1~&ö¸.dÃÀ…{µË~_„dŒæ]´Å._ÕYjÔP³›Ëzxž5pTëD¨¡7ÕT0îh‡ì
+‚´‰UEçGè.ëêžNŸˆÂ¬
+[cX]õD#wEuhsßLHBê.ÈÉ÷»bA Jè*Ò!¦*ð½õ¡BHîD4H"·P©7díát`‹bwØÑËç¬<äÙ¥ñb³§Þ¬1W'/"IAYœè©{®€¤>×4’:®Q$ërIqÊ ÔP—5é¸FT¢I²Ô
+3Ôåˆ&Ñ¡I Ñ$ I@£§âóÁé^߇XG­®ž²D‡,¡qÓ¡¨÷à‚w.áÁ%NÀ% ÇIù¿‚+™Â–8bëÿ-‘2-éBî´z\ ¸¦ƒT}hÏ£œÒ…—Ué¸Ft`+cqDj_™·‡Öƒ «ŸÅ±*í¦àµªð½øhå¸]´"*ÔR„)Guæí<‚éÊ2͹Ö!™h%ñ:ÄÒmÝ4¤ú\Ó긦£Õ(¤ XŽí3ªt\#º ÕaJñeŽR<@Jq>ˆW\ãÐ.^Ás$^Á@¯xÀuñŠ¶æˆ!ßãã'x¹Q~K<À–BF,˜ä¯³$œd?sÍÐçº
+,…ûyYÏ3"
+š{ã%~áéî1ÖÄ€~ã‹ 5ø°H²‹Ì ¬»;Ï›   qpµ%ðVíÞ!,–It­¶ÔÞ”ò@g 2zé}“¿“†®T°Jwœ®ì$Ò*ç‹4Ž¾ó³UyûXï?ÒË]V­‹u»eÃ6…Üå܉8!ừ:$µm@;-°@3/¬/@¤á3ðØÞ”ÍÉœV4»÷¸ÅÆ•Ÿwˆî!¥»ª€—Ædá0e¼¿7¹ØÈ‚S—O°e´áŒ:†ú¸¦)€Tä¸j!"—9Þ$´9fJ°„ïq>ÏýÕ²ƒ¸"Ž ìqí\„“ w˜M«ºZ3:Á.iex·§˜Ñúä@9Ö$Ÿ *xÄ‘)¦ÆîsM•Žëd{ ºžDaXòŒtÏ3"|Q¤bI e ýÍ#m
+}FvPœØ­—Výõf,$ 4"¯÷p\ ǃÎ}UûRâkFîs ˜Öv×J_bZÁe20­?7ÞiRÜ“tÉ7wáz t9 w1†;ˆutK[8Y¥'žÛ]Ñ—‹Ÿ&ºP8¸%ÊšPÅÐýš^M÷cb7RÃ4lÉŸ‹iœš“ ™'Æ2‰éýb4é1M“ÀÔÿøãJ½M½ße絯Ô0N©‹tLç* ‹Îüh××¾Ä «û¥.¾®0 qçûÉJHys¸A5k¨;`~5+­ªù~,k©”‡¼z,@G˜`äB2ójqúIöÄ#˜áîË(.ª'?ߨ;hH2;øe(sðŽtˆßå8à` ãN¡ Cž"N0˜³èªOh©+?¨%ôxï1ÇbP§]™äjz®sw$­<;¹¥ãöú ÿ[®éÃßé¹@£˜žMüÖpƒ(×Ãð6i/(‡%þ´‰¦¡ÚP¹eaè¥^Ý~ L­®4ÀV
+endobj
+1312 0 obj <<
+/Type /Page
+/Contents 1313 0 R
+/Resources 1311 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1310 0 R
+>> endobj
+1314 0 obj <<
+/D [1312 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+374 0 obj <<
+/D [1312 0 R /XYZ 56.6929 573.6377 null]
+>> endobj
+1061 0 obj <<
+/D [1312 0 R /XYZ 56.6929 551.8981 null]
+>> endobj
+1311 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F62 1050 0 R /F63 1053 0 R /F21 702 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1317 0 obj <<
+/Length 3275
+/Filter /FlateDecode
+>>
+stream
+xÚÅ]sÛ6òÝ¿Bo'ÏD,¾?ÓÄé¹sMs©;7sm(‰²9•HU¤ìº¿¾»X€"%JN&¹¹ñŒ¹
+g&¼»ý× Aß}|ýï?^ÿv÷ýÕÍ]w–þy9“x?®~ùM–pìï¯X&½Ó“'h°Œ{/&›+¥e¦•”©g}õÓÕ¿»{£aêÿ´t™vÂŽ0PÈ9X™‰Õ>3†»kî¦ESï°(àxÜÆÞE¾Ë†:óøÝÖMSÎ×µ¬Ú:ŽÓgS4M~_dÈ €÷)ð"ƒ›ƒÓ„½7yõ<Ë«æ©Ø5»O¯{æÒGä2î¾!¢âîÅ
+¿2&eQµ¯ WÈé|ßFâ⤺Z?Ôì·Ûz×KÜp2†eÎk1™qžy
+¥“*I:g#²ÖNÊ0Sào+Ræ"7¢ :sLš# I×x´ kt=Ý@Š›mFÁý¿*Huè
+ä2.„4HqÐ l$ R‚…KÃ> 0ª¶H…ê©¢“
+á@P!泯BˆzF…Hs€XkŽ\ÿæá“I-Zâ}Ñ´Mú. â‰÷¿:¾ÿrS¶>•ëõÐàÓš«}S,3òòwiÞÁÕA#jpØtLƒ%‰Ìsñ9*|F
+µ7™R\–Â>Öy)ì°†R˜üXÕœ£6™uÞ\¦¢Ã!cpbÃ3k™ÒAæì ŒØHÂ( è
+wÈÙÁœcƒd¡ž,†æEEQ±k1Odo0& °8ŽLV(!}žB
+hR><*‚îÞ|
+1còN µÂ…‰`}ðCÁ3Ápù-yÇõ:}É›˜DA/€öÍ>2KÅ {<D`(—‚ì ’Úk>%$‰…®b·ÊqίB¨Åºnfc÷Q"r¨á¸vÌ> Æxq÷ì)à HB¤Í>­™o·E¾£Þ²Šû<ĵ†kK\û£•n2ÍMòÃÀœúiÖiþH1ÎfŠ‰d‹Iüh”©è‚eæ!—:rNR‚¾3«Ø˜T¥€LöHùP*¤™–+B¤¸KÆ¢t€Ï_”X𣠙©È´0–l7M‹ã~B2È…+á\2{‚u¡6él“)p †X‘Ý!à Éá„Žù?7ä¡cà±Çsj&üXR v„FbÑF’gFð™ DYï—ä¡;
+•iñ¹áF»Ï$t(w–=•íCY]*R)›Y͛ÉOw
+›¨­wcgˆ­NÄþŒ®Ã¬OìÖïïKçÀô èÝïw9)
+†že]D|ôu z8dD ;±§h[Ò=hµÆ^R*Ú,>Y{h¬®!ʉ†õÈ·Pd1ŒX\ 6ýÿ¡¥¢N„Py ™DÛ½kþ2Á4 br2;<I}™XC*—áà ôP*w©Û3dã—Ãê댛=š¡4ò]X­¿Ãid°FÀ*Z%(éÊ; eë:<äÈ&ãbümá¬í\WÆ}u¨Mmc鯓ÊV,Zå݃½2àóE±<yM€(՜͉œ×`Æq1'êc¿¼‹“vö)yäã" i„ŽáÝÛFS7 ä5:ck‘ bWå!¾²¦W%ÄÁ~dmŒbðK
+èä ¡g]6á¹,`Ucy2=3Ö}®/62MYå庉DWË1' áWÉdC–0Cn§÷2•9/õx¥áÅIÚÎé¦*°€g}¤`†•_ÅG:,¨Ï°ta‚ôg]$W`˜˜/ùHá“…¤ø«úHn±°%ÝÿÀGö—¾à#¹ƒ Þ Ñ·á}…MŸÑëÔ{j,±Æxô ózL%Š¯5Œô%a•Aðá» î.(¬Ò9EĨé;mLe±,ÇÌ‚æ¡Þ¯—.âÛ«‘çkfIÚI¢‘ Ø R@’ì!O¸È„ÖÉÊB&¶«·1f€Sa‚©©
+ÎA¼µ•—R‡uÁ)E,2ÄþýMNýRD!eà—FdViA¿$,ëû%lö^¯ 5¨8YNÙµM‰e1Ͷ¬óKû%æ2λ ø<Ž¨w*S\‰¡o
+„û&0M‡ß_ ¶’Z(0ÊNXuü^{6J8&ŒëjÊ—|SŠZ¬Í„5/D6=¤ó2”NíÏåØïÝÀu_¢¤C:%e CDM93 åçð¢í’}p~ LÎõ…Éùž054\Ç°háÉISñF0qoâ’]” ý½"¶TÃq®_Äþz¬¾úb™0úJU={*Ö$E5œo®)½¥¶ƒ·Ö(
+£;rÈá­ð©Ôð\Œ=W@ÀÂù•iË­ý_$ºTHØl󶜗ë²}Tžû)¡ÔþþoäÎY„|ñÏ ¿ÁT6ÛzæIÜ.(d‘‘(<§¶Ç”w¿G<%ýo
+~_õendstream
+endobj
+1316 0 obj <<
+/Type /Page
+/Contents 1317 0 R
+/Resources 1315 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1310 0 R
+>> endobj
+1318 0 obj <<
+/D [1316 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1315 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F41 925 0 R /F62 1050 0 R /F63 1053 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1321 0 obj <<
+/Length 3347
+/Filter /FlateDecode
+>>
+stream
+xÚ¥ZÝsÛF÷_¡·Ò3»ß\^žÒÄɹÓ:9Ç}¸éõ–(›ITEʪ{sÿû ,EJ´L’s?@
+0ÖOò¢÷ðâf|cÈjµ›ZoRŸ»ì
+ŒPz‹­À3`!’¦
+fÔOÁ‘¢'c_ïè%ÄZèäsyR‡£1„l¦õ=hn{Çãº_5EòiþôŸp !¢œqØÍØÙOÀÄB$³«¾>#hÆDÏkÑÌdpT´"-ŠÛ:žùûz”¡Eµ,n—ܶÅ:ÒÔ銥9VB½,3å_Åj³,]0e;’°¨1#§¤q$%
+>kún' ÓiÆÏDk‘ü—Ûb}WRS«Ìyj:kµ}Míÿ½‹Š#‡§ÏÖ
+ ú¡0è+GÉêpØGfiþI‹•ÑöHêU˜×9ü{E8¢À{Á%³á ‘å0¤z‰ü/ÀŒ%SÑ…  4¸Í Ú©oÀt¨¦‡^`ê3}#ôöØbý6UB
+qNÅpdCîwýTƒ23Ûʼn'·ê)!biÒ¹M3»¯ë†Î!H è
+£U8ï0
+r•mØ
+z ®ˆ€€ôÄ™nÍ¡óØ{Ë-øU?ÓG¢u³´÷õn9§—¨b€±»²ísu‡7 IÜæª4DoÂûÙÝùh«:¹0|O—B–7<Éb®¸+ª5^@I“\Õm ˜`¥b`~^6iÄÜQ±Ž6ŠeSù-OÑ+|(
+ãëõzÉ’ÃVŒƒÀð.íEPÑw‡ë‰ì „˾#³ ·<a+äSF¥^)7À™±cË32²¦‹Ç†øva;löÝz^?†¡
+ìÆZA%b£‡“ÉËp
+´ÔÛ’‹ "“–«Ë)l·ñýîø^<KŸ«V9‡MƒÎè¦á7ã,Ïì7oŠ?*80ÔÌUšy§†G3¬ÅB­Øåýù!øC3 ><ë2½…[ÊQ&T¬— ccô_‚¤¥„Ùœƒ©¦ªyb‰¿Ühù•>ïŠe—ÍÂG³ O'£jÆ3¨Že›È¢.Š ð•»x· ­$VÚÇŸ’à(oœc  ßm¹µ,CU#ûÃ2@çiHPÓ"ÆŠ:ï®>Þªf”yž|ÿ»§/û%§R˜&ê\Ъ1sT£vÛrÝ*mRïÅQÛéps„c=öÓ„Há8@ðÇË7œO@Ÿ4n‹˜“€[ØÚGj>ØLP^ñúª…édK1¨\‚2+©É—DšÍ ÔÛ¢jx2Ò¢¹íEsÏ+´bûÉ­ë’[GÓݺfú]j¡>4LJ0s‡þþÄOÄ´Mñw]#(%ºïîßýó±Ãoë ìÐÞ«q¼S$I˜°R¸Ö?ùAãTõÿ5µùÍendstream
+endobj
+1320 0 obj <<
+/Type /Page
+/Contents 1321 0 R
+/Resources 1319 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1310 0 R
+/Annots [ 1324 0 R 1326 0 R ]
+>> endobj
+1324 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [442.7768 483.7823 511.2325 495.8419]
+/Subtype /Link
+/A << /S /GoTo /D (query_address) >>
+>> endobj
+1326 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [361.118 212.4953 409.8647 224.5549]
+/Subtype /Link
+/A << /S /GoTo /D (configuration_file_elements) >>
+>> endobj
+1322 0 obj <<
+/D [1320 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+378 0 obj <<
+/D [1320 0 R /XYZ 56.6929 540.8756 null]
+>> endobj
+1323 0 obj <<
+/D [1320 0 R /XYZ 56.6929 517.8101 null]
+>> endobj
+382 0 obj <<
+/D [1320 0 R /XYZ 56.6929 293.4989 null]
+>> endobj
+1325 0 obj <<
+/D [1320 0 R /XYZ 56.6929 267.9627 null]
+>> endobj
+1319 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F62 1050 0 R /F41 925 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1329 0 obj <<
+/Length 3260
+/Filter /FlateDecode
+>>
+stream
+xÚ¥]sÛ6òÝ¿BoGÏT<|$8÷”䜞;iÚsÜëC¯Ù¼P¤*RqÜ_ß]ì‚"eJnç&ãp±X ì÷Rr!àŸ\X '‹,Ob#¤Y”Û+±x€¹o¯$Ó,ÑrLõöþêïïu¶Èã<Uéâ~3ZËÆÂZ¹¸_ÿ½û×›ïoʈ(¯—&ÑÛÛÿ$LNw?||ûíOwo®³$º¿ýá#¡ïnÞßÜÝ||ws½”ÖHx_ñ
+g^xûᆠoïÞ|ÿý›»ë_ï¿»º¹Î2>¯òÛÕ/¿ŠÅŽýÝ•ˆunÍâ "–y®Û«ÄèØ$ZL}õéêߣYÿêÜýmccU6sJ.P
+€“t‘™<N5Lá>·8‘È£§ª{DÈF}K˜ºÚV=£áŠm{hÙn·uÛvÿL¸CçÖ„]=Ÿ¼Ú¹ý·Ç ý2CÚ# \$°+Gì*8L¦s<&2º-¾.Ë¢|tË®ú=ЗÁj™3yѬgÖ”n ÑL³wåaßU_ÜIKmul¥Ñ‹¥”qnŒòTe]¹¦ïfvÔ*ÖÆ&¼Z»ë«¶éH?ª¦ë]±Ž_(ˆˆ…Ýͤ‰³DËyƒ`¢å˜Šä)ç "P!ÿBÕ®;Ý”1¶‰Í.o<PÍì<Õ$[=ÝøÞËYg(¨j{ØÒ 9lW t{}g`Ñúð«/Ê£môX|áévç‚ʶ±í¯¥@.õóµ”2»Õ™X»Mq¨{Z¥º–Ë/_ Îtœ¤Ú²
+H{,Ù=F™‚‡è „ˆ>x¿s]{Ø—ÌíT›9!K•ÇɎרUmÚºnŸªæ‡öè8p®s=5-J áú°B¸Gp¦ãÉ ºtýàá’iÁ^ºÃÖïV)x‚^¢M\³iùÅ5MWMïöMQƒù1¸tô“bêg…»/
+þÍgð–Û³Ve2 ð9—­jLuÞªªSª¯êeÝ>,g-,•q¶p™j†‰…¥iœ¡ŠM¹¬PŒ¹fe@XEnÕµµëÝ?®—IšD”ÇÓEYº]ï…†£fÍÓ É3Ì x=@ùÒXB”ívâXUuÕþ4ÏyO‘•BdLÕTòÌëK‹Ò2ÖB#÷ÿÀ\@“ÎÆnˆ'²=z”xÝr(-XGÀê‚UjshJº'
+¶ôå}çuIÙX*™¾¢K#ª º¨ÎòT¡’Ë T3,œª¤+vÊÃ'ç=Fâ/ ƒÃÆçÊC¤
+9Ô ñD’Ärx„!+,÷Õ®o÷!¸YàO@¯ù’
+ï˜sQ€|ê¾qûÎw5ÓÐÕLÇ]ÍôL[L¤ ¬2ô¤TgmÇŽòécë|IÕ„þm ¶Tg÷ƒâBjšœt¤²sÑW@†¢ô¨C¿TIð,ÉØ‹%Çs&àËsŠ°ÚŸÙ±v]¶ô-)Ú3X°c¹»üÄ•nÎuL…PG¯=°bÞGµ!ªæx:õà¹UvRn=µë\<(ðŸÙqcˆZfdžÇcÑ…@Ø÷5ûU·Áe6ྦྷ%ÏÏ×®°Y·Oçë¨páÎ^ #¢óN2Ͳ™æÁ:¹Î.n>½Ü}¢ÑÆÆ"3r²=õ[;î‚¿`á„Ï€{Õ8ï3–ÄÒ×)¸Yº¯€9í¾Ê³°L{É#Îgf E)XWèäG}H°³Ë“®@hª§Šë(­‹¾ Èë<¹S´-œVq3!•@äU¦|ºä=¡9¾:„q€9Œû),9奨XS‘ûº«BóÇ;Öÿ"hó|Ç`EiŸ$õL"ê ›èÃÝO 4 Ÿ}Ñ»‡gš â> 9‰ ‡ |ª„Y²L-¹¯%Ä(jQ¨$zCdÁ½ 'zŠé¾ò-j¼7ïŠ]õlÜ÷ÓùòÊyl²'pOC{þÁç¿€¢ös»%jV2D‹`Ûø<@O¬Fž®ÚÓ÷÷x«£T|›JGoà|gù@ôÒg÷üÄ|²sµÓã^lÎd˜„`‚×ÔQo™N’Ë‘ù6T&9UGˆÒj¹
+=íCÓU u¬¥ónÏ ¢k_ÉË]þÝ7æ,*ƒ«|‹ÓóñL 5¡­xŸè(/6´ö
+°bH${^ª%4¬æ¶!LAÃàuEõb±6©vuà²rOTÑŠÁ[žk°w}ÔšR+ßïÛè2êðá±=ùðæ¨Â?@¸ñ5èÇkÍLÿgƒ©2Ö‰yåsÕ˜ê|8¨B±Iùíʃ›ë,ÉLä—9¨fX8í,I¨ TsN´ &n–ÚßÕ®ôAÏi‡ ôØ `H45_+"5¿{»™ÝÖ¾q5ÁlC½:DT“ÄJ¤zjÎT˜¢Áð/z¯8R*ÁØÊ‘sýŒš¢Ø‰õ”‚Ú¸'W]óÜcûDÀ¶hž ò?S+iZ²`.(Ú"äÍÊZº¿5áªfNáÃé•”dö>E…!H@_
+endobj
+1328 0 obj <<
+/Type /Page
+/Contents 1329 0 R
+/Resources 1327 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1310 0 R
+/Annots [ 1332 0 R ]
+>> endobj
+1332 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [375.4723 524.316 432.5882 536.3756]
+/Subtype /Link
+/A << /S /GoTo /D (journal) >>
+>> endobj
+1330 0 obj <<
+/D [1328 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+386 0 obj <<
+/D [1328 0 R /XYZ 85.0394 661.0164 null]
+>> endobj
+1331 0 obj <<
+/D [1328 0 R /XYZ 85.0394 635.6995 null]
+>> endobj
+1327 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F41 925 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1335 0 obj <<
+/Length 2714
+/Filter /FlateDecode
+>>
+stream
+xÚ­]sÛ6òÝ¿B÷tÔLÄà‹_“'7uzî\œ«{jû
+'Œ'“Åö†MÖ°öÓ w834 ±~˜ß¼ý ³I©H'óU@+YžóÉ|ù[”Æ"ž½ÿøðáþ§?ÞN3Íï?>Lg"aчûÞÑè§ÇÛ_~¹}œÎxžðèý?n?Íïi)u4~¸ø‘ }.}¼ûp÷x÷ðþnúÇüç›»y—ð¾œI¼È—›ßþ`“%\ûçË"O&/0a1/
+1ÙÞ¨DƉ’ÒCª›_oþÕ VíÖQùq ™Š
+>&À¤ˆS)d/@žÆœƒ\cÑ'³/›e¹ ‹Î§œóH·Ÿiz_wfÿ¬«öìÞ<Î8O'™à1—B]à“f!Ö6=²¹¨Œ®Ëz=+ §p Oy~…k„ðÀes%ù‰ù¦l§3™‹¨ç‚fjVSžG+³èÊgS½°yj›ÊtSвŒ¥Ñ§=¢™ç²9´€…~3)žDÝÆЦ¨›=_šCµ¤!mÜ6ÏÍ|Ý•[¢<@Äj ˆ˜ó¸HaÙ&Œ¶9ØÁ÷&…ƒ.û]¶\ÙY³¥±ƒ…^ø¡¾^ñ°“WãY ¥
+óÅ÷:rÎc¦RîvlËúЙd”ÊÌY"XЧn^h°Õµ^›6dÌ^]€Þˆ‚û«“{Ø‚°ö¯„[ÂÔ4ÔŽ]ÞÞ,ÚfïÛ• Ý™eVmŸ–uí€Ë†Nϧ.”¥}q
+Š_4+ü ‰B,Øë7/2¯ßávÔoü’~ã(ÐÓo¤ú+V¿q€úä­~ƒ²µ$® ÜmhQn÷:yá#¥(¼[ :#Ñ“Á`ÑÔ¿3&Ö‡½v1¶ ¤rÖxá[5zi–À¶yt»êÌþ„òLKƘ×<¼çíɬKwj…©gcn‡¢·LÈbqðå
+9w4Ž'UÕ¼xJO£#;yŽ¶”8tnÇB†Ç\üäIP[ÞK²éÑÐKµ]³£Ôg/>ßïMnOw>eyvþoMÎOxÑ”,_vz,Óo;½
+<n‹,’c¹$/þhA’*nUb#–Ȥ!áãÑþÑY$Oã"+ÔD1(¨ÖàèÉ— ‚E! )Û»e`oï·bòc7š„—r„g!e{©T„Z.dœJ%'ŠËN¡ÈCc3¸<z
+¨ŽÜ¤Üî*³5µ­- ¦¯ëÁ¨8{z•P/@J
+÷ûÞ òXpI j–cèû´i¨`£ßèÄH(‚ Dô‹„ëQ‡¨Ù5` ¯#.4W¤;)ra·¶ÎÁ¶X…¡ÀÊ£^·~26J Ø|9è
+# wÙ!Âìk0
+qXA€tÍ
+’ˆŠö’à‚©¼æ iw”nÛr]ÇŒ;RàK`êtͲ4–¶%ZÕCSÏj³v­8Á=y¤ >zNÁšæž$Ÿtë·ÙT\Ø´¿Üh×´%Õ¸`…
+õnLåÿ$€ó–§ïh"‘’ý÷ëÜH‹çɱ/-„[š» L}8[nðØ‚ gôuý
+Õ-ýt[D’ÄøX‹ŒÕ¥²JF™R \¶ÛÐ2± óua|û0щ Ø3ª¨KEe•4² ˆžM˪/ïñt§û°§t´2‚:Ñ€Êh¯ð«» ¹9þƼf_óõý/*μŠ:»;Wê£þÔNUÛ~ªR+Ï»`÷o9öƒ®Lbüv¤¦g}ÍôÝ?ö WY )¼o@åC…-=S6-gçM÷«ð9ëÿ‹aèendstream
+endobj
+1334 0 obj <<
+/Type /Page
+/Contents 1335 0 R
+/Resources 1333 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1310 0 R
+>> endobj
+1336 0 obj <<
+/D [1334 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+390 0 obj <<
+/D [1334 0 R /XYZ 56.6929 769.5949 null]
+>> endobj
+1337 0 obj <<
+/D [1334 0 R /XYZ 56.6929 751.9325 null]
+>> endobj
+394 0 obj <<
+/D [1334 0 R /XYZ 56.6929 369.5823 null]
+>> endobj
+1338 0 obj <<
+/D [1334 0 R /XYZ 56.6929 344.1885 null]
+>> endobj
+1333 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F62 1050 0 R /F41 925 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1341 0 obj <<
+/Length 3169
+/Filter /FlateDecode
+>>
+stream
+xÚ½]sÛFîÝ¿BoGÏDÌ~’ËéSš:­;­Ó:¾¹‡¶´DÛœJ¤#Rq2þ÷XjIÑqñŒ îb±X
+P†L3Eº˜§EëÐb0¬“:¨7+òÔæ¦Ô«ôBÊ´°V¡~ ‘æÔš[ :ÏH¿(aY¤63¥H­VÀ¹Çx{ºÌdrÿUr6ÕÐ4Ò³&S§î¼x¿©0E¡ '‚ýQ"ð/Ï·jñ] ZDg
+t—a¤LE+UžŠÜàö.u…Ôžá«»Š•é@mùL}{ßnÚÛOŒÓ4ö“±½ï붓Ì]RwôlÚž¶÷›j[5}µæÆäûP‘N%f@I™Öbm=Ï
+3V<ÜÕ+&íK(®y%Ù…JÎ!+’VAúm&¹Þ!JCäÔûý2[à2ÿdg‡||œ ¼zýTã äÏÏP‡WVÞÇ©60¬}"  Å«™ (Ÿ¥Î¿B¬`ŠË˜ä\¬0àA…=ìüx@ËA®Ò÷¯Çd ø“¹MUAjÄäc&i 晋Áí±ÆnèYyï‡÷~°÷ó –‘Þ áÓ8|®îªÕŸ¤^`Z˜4¢Œí붬›ÐNè]†¨ØÆ$í`…4à+ÿxEè
+—„Ž.w>]" ,2]*_*CSÌ:j™±]byÓSÕ…†'àV57…;4SIÅ$¹7Íèa†7£oý3§h0têù(ŽwwíCCà5У¬C+ä¨cª*´Œåm­N~ ð'† Ø‘aÂ[I¶0Mý[OÝPIs®ÉŽ«ml è`þ[¹NMÞ’qŠ“›ÉúDÆxh§úðD}dµS…P}ä3£ˆƒ´l1•–]ãCÁÃÒ¼º¡f¬v7¼{(–fPì”Aš"t!#<”g,Ì‚…9sšé]F‡Ø ±Þ¸®Gll—F7«±Ä^¾1rüI0δß3!’¿<SJ§þ(`ÄÚ_„á
+ð¼ŒøYòåKš9ƒ¿Nìº\½ÈghË#ÚÀ{÷ RÊ"ÚW?œ]tSï³75(¢Œ7>ì1‰¢ñ=@ú6Ð÷<G1Ç‘‰9ý0£±ù~3Ò‡¡¿ŸÔ)òÎ|VS. 5'ápàÕ¦ÄHŽàëÉú'9Ý)s³òÞw¬ÌT¾`iïx@MÞõãÂÿ¿ÉM=Snê‹å¦¾Tnj*7ù_ËMþÏ䦟)7ýÅrÓ_*7ý”ÜÔs䦞'·Éæx;Þ ‹Ý39’å3ßï(XW+ûÁ+Í9¥Àï¬ôiòøg!Ójªg±ÄWÎœé… ЭoP Äõn×6åuÀ»®îʵO¯<Eú°Gø<
+ Åa„¸T¡¡Ž@úæM£Œ¢Ý\fvȦ´rɹokeÜsÊ“®ÞÖ›rGƒ¾asvÄ<¼Q-MOZ`™žD×WR0~Ò—%&-ÒÌÅe”Æã2*ç"†ji IËcuÔ‰AŽ†ìoH>4$>培À /š»ˆº8ЋG¢D_ãÔ4Ïâcà,ÃSléy(ªà%ÎT‰‹G~„…:þ*p曑~w÷ì(~Š…Ÿ}œS|~Üú"LùbÉ)çøqÒ:•Ï°þorc\endstream
+endobj
+1340 0 obj <<
+/Type /Page
+/Contents 1341 0 R
+/Resources 1339 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1346 0 R
+/Annots [ 1344 0 R 1345 0 R ]
+>> endobj
+1344 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [242.0197 602.0286 315.2448 614.0883]
+/Subtype /Link
+/A << /S /GoTo /D (rrset_ordering) >>
+>> endobj
+1345 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [238.0484 522.6184 311.8142 534.678]
+/Subtype /Link
+/A << /S /GoTo /D (topology) >>
+>> endobj
+1342 0 obj <<
+/D [1340 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+398 0 obj <<
+/D [1340 0 R /XYZ 85.0394 673.0194 null]
+>> endobj
+1343 0 obj <<
+/D [1340 0 R /XYZ 85.0394 649.1998 null]
+>> endobj
+1339 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F62 1050 0 R /F63 1053 0 R /F21 702 0 R /F41 925 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1349 0 obj <<
+/Length 2450
+/Filter /FlateDecode
+>>
+stream
+xÚÅÛrÛÆõ]_ñØ ×{Çnò¤8’«L"·4;Žãˆ„,N@‚&À(Š§ÿÞ³7`q¡$Wét<–‹³gÏý’`øG!‘ÔT'™æH`"’Õö 'ŸàÝÛ3âaæhC}¿<{}ɲD#-©L–·.…°R$Y®?¤Q4 8}óîúòêí?糌§Ë«w׳98½¼úé­Þ.Îþù|1›%Húæ¯ç[^,Ü+éq|uýƒÛÑîqéââòbqqýæböqùãÙŲå%æ—`fù|öá#NÖÀög1­Dr?0"ZÓd{ÆC‚3vʳ÷goFoíÑIùŒ(“tB€”M Ph$¼2¬š»â
+¦LÀt/Ÿ·XD¶…ŸÇÆvŒ×Ðñ¥Ó‹M5Î Ùˆ& ¡FiÖ£ië[¨§(a3” §RÆÁµä!¼eöåùnJôaÀå%ÚÚjL8Ü$•Ê¡(Ÿç$=
+Ä)5òæá<ÆèX쑆1’Y&º‹­Ò÷ÅjÂ0(E‹àMŸÖ…q‘ŒúíÛª,«ûú[qA§‹~.ø°*óºv‰ÞEA%AüE-T,0Bʘ‘˜ä¦’a/–X‹q£´"ëG@5" `†ÈI¸"cHÌ='h>4ûb‚mˆlDÒ`'¨Çµ9b%ÿD®Ƨ¸€
+ePw÷½÷¿;1u¸LDw.¿ '†q305çYœH°D þÍ5…ì"2Á|~‡|9(4&ÖÒœ@½f€ã¨àdØ Àk[Oò`‘
+**œ[ò¤©¯ÔŸˆÅÞó­þnûºÚwÑ ‹d<}Dê;/Q'užï8û
+”áÄi©C¯âOH]H¤2¨mø°*7«ÿ™Ô}æo逫ãn=w«›
+Œ™3ƒ7……YŠ²ÈMp2?Lž6OW˜•“â\wãaÙ›ïpcòR·F<ƒ#ÎgwËa‚£Œ´u4^7÷­«Âf­Õ,êã~o£é.ÜŽ­qLX™AýP¬C`3s)À “˜¦ ‘:½1ä=¸5tàéÂMè€færã1;€‰ó+÷éDû¯#:5å–ÁY†C.þꨎ‚Íf[Œ °ÅÌíƒï–G STйæï½Â.Sî£<+üêŠÇ¢ƒ¶BÝÂÑݸJ‚R‚*­’؃^æ”Æû…£ùŠ*éñˆÑ÷s–i5Ý 0ÍŽ¢÷qNøsËRô¸óÚ˜
+u Ú Æ¦>àäÉV󹟟;ž¸™():]”ùâ¢,KtDyøN=&ý?o>¤Uendstream
+endobj
+1348 0 obj <<
+/Type /Page
+/Contents 1349 0 R
+/Resources 1347 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1346 0 R
+/Annots [ 1351 0 R ]
+>> endobj
+1351 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [325.3322 596.1482 398.9856 608.2078]
+/Subtype /Link
+/A << /S /GoTo /D (the_sortlist_statement) >>
+>> endobj
+1350 0 obj <<
+/D [1348 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+402 0 obj <<
+/D [1348 0 R /XYZ 56.6929 666.7383 null]
+>> endobj
+1010 0 obj <<
+/D [1348 0 R /XYZ 56.6929 639.147 null]
+>> endobj
+1352 0 obj <<
+/D [1348 0 R /XYZ 56.6929 513.4583 null]
+>> endobj
+1353 0 obj <<
+/D [1348 0 R /XYZ 56.6929 501.5031 null]
+>> endobj
+406 0 obj <<
+/D [1348 0 R /XYZ 56.6929 101.3093 null]
+>> endobj
+1354 0 obj <<
+/D [1348 0 R /XYZ 56.6929 74.6262 null]
+>> endobj
+1347 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F41 925 0 R /F21 702 0 R /F53 1017 0 R /F62 1050 0 R /F63 1053 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1357 0 obj <<
+/Length 3401
+/Filter /FlateDecode
+>>
+stream
+xÚ½]sã6î=¿Âoç̬´â—$>¦»Ù^zmö.Ioæ¦íƒb3‰fm)+Éɦ¿¾
+kÌJ9‰R‹2cãTIÕKYŠ9),”ò¦Øº¨ë6ûÛ2‰µNÕb¼æåk†´‘ÒÄZfé”öµëZ¹–ËîÁaC-«ÝöÖ5¬ïèÛºU]­[Bèj®ŠÍ‘Ë‚Fp'aBó)«u¹*º²®àüU’/‚¯Ë¶¸Ý8^W+«S±¼g¬_“Ü<”Ì|A<{âT9´…Ô ÜÌåçFo<Ò‰‰½[c¤ÇmNE¾„]m·®Z»u ÔÐÉòÆo
+´píîŠÝ¦£N ¯Çô¨„Í{úi’ÌÐÇó‘*àà®DBknËj×¹–H# ¨ÖÔèÛâ[¹Ým©óTlvî5v²,–VI&%òy~ÒX'bÄŽ:d'>0=ÖïL¤±•&{ÃFX¯AÀBF`£Qå5jÖ€%-­}~5ÃÀÄ ˆ@5åàæԂƒ(¤aíXïV(n©—•ëžëæ vMq‡ã¿&‰\Ñ8Œ•ÕŠæ­#È£kîêf[T+÷!–†z#Ú®¦‰-UîLæ‰1‹ª}vMÏØ@¤a3©QSõ>çž Ò<NE¯•ÞʤZîZ·¦–7rø¶®£FA|
+ 0â¸s7Ï+½ €ìšA®eïƒ:eÕZAaP“篰¦Í/¢À8o—.*¶Ù¬·ÙC9«ƒ«ø3ò±FÊA>‡æn4×Y0¶dÞÚ”ïl c ~xõ¶G͇z× †·o/2¶‰–ó`à«¢ªêŽ¨¸o+çÏÚË«xanP…½€E‚‚(Ôs¹Ù›¸eÔ–8øÍ {¬æ4_ÎVÓ7coÊ”ÀwÝñ®›bô¹g ê¼.¿wÔ%¥noY^wIc¬ã.©Ç
+’>î‘4\*Z毓ï±fèO=ŒJ-¦ ðålÒp¤ãûÀ[0Ù4žÊÕÃdÎÈÍà8cÚßÞÐ$ϳ.«¢y!ªæcÝ–] ¦÷ä •Ž(R2÷fçuF×Y¾§2Ãý™kò0ð­+$š›å³s_„Ä2j¢’DZ¨åAý‡ÓïhöïÎó\t[¼PcUìZÆ,üFõëÎ5¥còÏ`ϵk*ê_C” ¢úï' IÏ.~|Gso­ˆ›L¦.9Q*_nê¶Ã–%‰¶¥Q n ´xëÖ%h3\]µþX±;owx`ˆ[0ôòš¾þRÁ{¿}Áßû3j‡†£¢I^ÀK½Ùy?=Ù Õ#IsåÚö¨™\Å©öu;c·³ËÛYYEM]wía
+*£T.ÏD‹*8Ã…†Ë]ÊÔ'•‹¯ 'ÚZEX£¶ßí x±•‹5ìi1ÞVX9/í÷Íñ[ÌäÀÆ‘S»ôŠ–o7R#ºÍPÑ—³hÙƒ×6ƒÌRѱHÿÞ)©–´ëGCŠþ÷t(wƒh.Y¦^ @†Zƹ"u;îÍz,â•÷\Xåºì^"ïþ¡wpþ™‰³<—‹1CÏ°fø˜x6`7K!Èœ0rýèV%æ(þîËB@eƒw ÷nYx® Æ ¼ØÁMé}õŸ\E(/¯¯Ï?v^±¥ñb×Õ[Hd"rQYçR™©‹ZÁU÷·N—÷®r ‡Ð-ZþÒ‡W&·¥™wø®_ªb[®¨³{\Ã</Ø}Ù+
+Ÿ€JiÜ€¸P¨4Øܳy]N¡ÇÆOáp]ŠáVœ;pp“‚àxÇ‹hBõ«q’/ˆÿ å¾=òÝäË-o†þˆa¼œŠ¾~Ä]<™Ò¾u LÑ ÆgêõnƒñK"BPŠÍv¬”x¨Ÿ©±©«{jݺ»:°‚}Ïê µé¦¥﫧è÷I‹Ñ—†{ýÂ
+
+±øMðFC踜Ù؈g›Ïçï:‹¥Èr¾¯Õ\ö.tl¥!ïÖ»/ŸJTWl£…ØŒO8Bm쇦Lxwߌ&ˆ÷’ú¸,ê£Q¼G€ yt|þÔ‹ÞH¡ã ‰°Ô‹+š–Ë#2ÊfSåõ•†4M†L¼¯5x¹åqfS5Š‡¥œšÊ
+cI.õȾÔ#¹|$1ÿ­,ÉUxŸ>T$—”$§€ÐÀÓ¥ÖØä=jàbµk^uûDÃr@ }H(9Íè×6å¶ì«ŶÞUþÖ\XmêÕ®M|qÏXÜ“‘ìetX¦A÷oT¨» ö4Ì*LüC Ý‚H6ëÖcš’›@ÀÆmÇ°ÖAà ¶` å#UÒû„%ÔpýùŒ ƒÓ§>ñ,¬R
+’©W(!$DfY6)'*É2T;áÄo7¡8ËáÞó%£Òýj¯¶ýT4e½ã¢žk³WŽŸ”.õ£¹)Ä£«¨7j@c¬ãÑ\Ž‘M:ªêµ;ÌQSÈ
+r•¾ÎB5ÃÃÄß@¬Rm§LøHî!BP&Æ.BŒB:hûóâ—&Õº…³æéîÄL•7@ðן¤/ä뮨º°<|€€Âà`.±¹Ý»'½ïŠy¿“µCë¹ì&C•{¦‘ÿ:ÿß©ìÍCþÂŒ„4ÕŠ¾Þ)f«°"‹­’Ù±LµW#•ÆBgê 5a½¢Fk_‚cÑ¥<Á­g¯óÑcÍ02Ù³±Ì§| š„
+üœñÀ±ËC½áWŒ^› íµ ñûѽŸê}´8°D˜k@¯|¹Ë? •%R0j«Rj¯ö^èºðìÅÊçKÎárý*X¦ ^Õfõ‹ù~C¿x{­“7^ÏÆXÇõ«ÇÚׯîåѾŸYÈ…“ôuz¬&»Mu,29eaP-«)&Òpøåit®>Ò{¿¯°ȳJ-tPÖÐãôù!
+Z|úÐâ虣+½üâ˜Ú(æÒûeQ ¬´*ÕFcQäX¡ú˜hØ(øððÎkŒ2s/«XYè fü^Ú£m¦Ä\o:ÈÉë`V¾0‹¦Ø:ŠµE¨xCà L„moë'Z„ChAGŸI
+ÃXF¤ûY`Q~åA7Æ"êý"mw3E LOð¸º+²ÊÞ¨±^Q÷€ÕWŒÝ¸Ð‡‡wýcù,ØcwÍË!n
+ÇÙuK¡;ršøá! èîË€%¢±Bߺ‡â©ô!šRKÊ*¼ÖÞoO£èe>ìH=È|Ýa¨Ð¼0–æˆð(š„Æ
+ò½ûþç H¨êúɘåÆ+&´»¦¨Ú;~DJÌòçIb¹†O”×ĹXž¨[;JŠ,ófCÙ ¼h&ëÝÊ;¬„CŽ½ëž§÷Öœ$Z”Ã
+endobj
+1356 0 obj <<
+/Type /Page
+/Contents 1357 0 R
+/Resources 1355 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1346 0 R
+/Annots [ 1359 0 R ]
+>> endobj
+1359 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [318.204 427.0782 366.911 439.1379]
+/Subtype /Link
+/A << /S /GoTo /D (dynamic_update) >>
+>> endobj
+1358 0 obj <<
+/D [1356 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1355 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F48 940 0 R /F62 1050 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1362 0 obj <<
+/Length 3826
+/Filter /FlateDecode
+>>
+stream
+xÚ¥ZQÛ8~Ÿ_‘Ç 0ñZ’mÙ¸ÃÝît·‡Ûv¯=°»žXI|uì4¶gšýõGŠ”b;Î ‡jJ¢%Š"?‘ŒÅ"„b'A’Él¡³(ˆC/Öû›p±…±oó¬ÓjÈõýÃÍwï”^dA–Èdñ°Ì•ašŠÅCñÛ2 dp 3„Ë·?¼{ÿ㯟ÞÜêhùðþã‡Û•ŒÃå»÷ÿ¸'êÇOo~þùͧەHc±|ûÓ›_î?ÑPÂs|ÿþÃÔ“ÑãʤŸîßݺÿðöþö‡¿ßÜ?ø½ ÷+B…ùzóÛᢀmÿý& T–Æ‹gh„È2¹ØßD±
+âH)×SÝ|¾ù§Ÿp0j_ÕŸ©9£@©
+LEgY¼Ðq$
+†PÝÎО>|CÄñV¤K³¡G»£Î¼.†£ÝñDͮܛ–ɆŸnÆö`Öåïa( ¿û”W½iƒ ¥‰@ ‘,´LÇÙ•MÓjÈE{sFâ¸p¦¨ÛU_Vmù§™®.d¤Zd//ï¹fÖêXÈ8Hc%Ç|6U’vÊI–yñdŽ]Ù’nôòþ‡Ÿiä×~¡®Ç~ƒÊÞ˜#µ­ô–¥¬™ãÔ¡>WJ…ËÝfr™WeA,¤kbËéШ It^z…YBÔïaò{ ¤Å*Š` àƒ+!‚,ŽÉãš¾kË'“¸×Éò˜×[î|.«Š¨GîiËÊÔ]u"Ö¼øOßv¦€å
+ªåƒU Œf“÷UG¯YYˆtË °Ówú¶ÏyAÚhÞ65µ7Í‘%0]WÖ[»¯ÐmHÎXÇJ&¬šGͺ©WgÁ’Ä –°`þ•d¹5ÌCLj“Ôí³9NØyÛÒp·³B7ývGCÔþbjj£ѾžóªòoåÝÜf«fý…¼msÌ·{P»ó¾C¾þÂvhýù;« ï°íM˜íbôÚÙ’Â喵ݙ£ç«‰b# …^ñø$A("ñ²Ç¹®{¼çB5ìóo×^¤àµ/®î¹f–;¼
+ÂL%ãõÉáU‘Ã#"•û~O òv¤¬Æí¸iÛ|ËÌdŠHÕùIò+;ljîC$À§C-ä phäÑ"ˆ²hl2ƒ3Uîà"FåÑ!¢ƒ9²@·‚Ø ŒÜ3
+ØIŽŠû4’CÀ¶wml8˜¼CV9e>Oïm#`¾znSTX)'^2Ìøg]˜X8ÈLÍfYŒ/O”¬MùÄ ã«3´¶‹M°Cê"!À˜p>N˜øzAΘ™Œö
+°Åk¥B¿lC®ëÀæ¹ØÀaŽxø•Yïéᛊ©uô²žkFŠ¾E\Æ©‹ñÙ‡vh i‚9 H4¢Y>KãâóϦq¶®‡­¹Àj°¦
+²,Ô¯ (Z©”™,þÃŒU“¦¸›Q]
+²«¡æffýjt¦óDÓ6û’5Ô6{Ã}· ÖÊzgÖ_X6|«Ó¦¯nÅ’ÿ‘ß>˜#jÂYFVi" 0ËlìG¨h03`×ö ØŸfTè
+D!dÆYòºŸE"ö–ÐÔ¸ì¶?æt‰âô¤\{J©‹ô ®Îì)¾Ã&ešWÅ©ûô8q%º¬v…a20Z!·) híÒ
+x›ø åo¯ÍÉ!Ä-å4`ŽO†ÁÃVS” '‹ .žÔqÖks°ÅG¼aP3\ÖvAÕƒÃ`zò¢(ÑOìñ&ÂY,Bu”¸ª2r_é
+¸wP
+•îI}R„“ß.D~Yð)$;•Wœ »@¶;ˆù
+¢iV
+¤òA>ê(’)) ´³†Èž#-YÏ–ç¬glº9jûž^ö«,ìzlzÔ’\
+¢÷óšXËý¡±E_Ë|š‹R…ˆ¡e<VêÑnãs·2„šiæbê«1#ÆÞq¢äË1ãëzÌè¹ÕºrsZ¦ÊO—¿YÉ ÎÀC^\ÝsÍ,?:T£rÛÑút»j@J+b‰.“rZ¬1B„ »°IþädºgcüPÍ)‹Ö.ŸŠê+ ïúø‡®–FèVÔô[+<Ãmq+
+ä®{­—>ÓƒLG“"³Á`Î4 —ÈBð‚&2¤†î‘Àßí
+ƒpù}_VÝÊe>þ²¥V>¹°äŒ!GB-¤ÎÎzUéy2•Š%ÕD›§²°p‹£6`@jgªÃ¦¯ˆ±(ómÝ
+WØ¡5}Ѭºæ°²õ‡UÑà 0W&Q2HbíÐü±¬‹ùª¬ÔÂEÉV$¥¯•#àzð…Ÿ·?½ùøyfBˆ‰³ÔGÕ68ÇB3 ç88¿Û2æÕ¾Œ»ËQVU”Ëcs 1hQÞŽÃW~¯pŽ-€ˆ´zíç
+ÿåÓÿÒ_/fýX!Ef­XªKÔˆT:g5˜ë).g¤/ ƒõuxò¢Ñ)*,Ö§É+Ç\©ð…@W‚…i)DÇ”ËF<RâGÖø÷4ÆQs6@ hpµÅ‰o]Q†)äȱ3¢÷ænDÀ ¹kâ/~aþlŠÓ®;þÔ…rHK«æ1wé[œ >=†.5^ïx´-5ÚÞª ÓXí›»ÛEÊÔ¹[^A”wõ:‡•UèymÁ6K¹` „+ØfîC¥ÌÞÞ-“Ö{À©"flˆ }§¦'bclQ2KÝ«zYSº€]¼RQ¶ùc5šÙWÌ…Ò“:›+Ñ©$]öÖ…#÷A^I
++x¶ß=Xvª¸aÿÎ~¡0zÏ»ôÌùÃ'“¾5X×zX¹¢™O´h©¢¬í}ˆýyMOóíP•kOC˽æ@Ï5³„´9tšM‚šPˆÌAëùã¸5Ö;Ÿ)»ÀÒ'þWâÁW¨—ÃÓõhÇ1Y¥Çšzºh†Õó—×d–Ë%'?˜EJ«Ñ’N¤~mÛè\¯÷?¤]î4ÿ†Ù;~»Ì‰à‡ ðuÊÑÎ`N›×_ÞRCœ¦”ƒB–'¸rSjü¦Óÿ¢À©1®r:˜+¿‘)Æ>üûaÀTñ‹¿ýÊó5:ç(^ñò5,×A"ý•ŒQ]&9âü›vFŸÏà³s£üMIE-dØð‘ ÐÖu2WrBŠÏQG¸ †tÜ~«°9ñ×ÓK)„02Õ“£àuæKÛG»¨x V mì^ß­!ÖåªÆÌg,¾èp%ŠPhų^.Ü)ýß_ŸƒH*M¯ä ø©L”Â$,”£KÐàO‘/Eÿ/²Wendstream
+endobj
+1361 0 obj <<
+/Type /Page
+/Contents 1362 0 R
+/Resources 1360 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1346 0 R
+/Annots [ 1364 0 R 1369 0 R ]
+>> endobj
+1364 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [324.9335 578.0115 381.8296 590.0711]
+/Subtype /Link
+/A << /S /GoTo /D (zonefile_format) >>
+>> endobj
+1369 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [55.6967 152.6674 116.59 164.7271]
+/Subtype /Link
+/A << /S /GoTo /D (view_statement_grammar) >>
+>> endobj
+1363 0 obj <<
+/D [1361 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+410 0 obj <<
+/D [1361 0 R /XYZ 56.6929 226.773 null]
+>> endobj
+1368 0 obj <<
+/D [1361 0 R /XYZ 56.6929 199.6254 null]
+>> endobj
+1360 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F41 925 0 R /F11 1367 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1374 0 obj <<
+/Length 2801
+/Filter /FlateDecode
+>>
+stream
+xÚ½ZÝoã6Ï_aôå Vù!ê£÷”Ý$=]ï^’;×íƒbËkaɵ䤾¿þf8¤D)²œEC`h4ÎÌoHÉQøŒÁŸÅÊg2 fQøŠq5[=]°Ùhûé‚™¹š»Rï.~¸•Ñ,ñ“P„³‡£+öYóÙÃú7ïý?®>=ÜÜ]Î…b^è_ÎUȼw‹å5qz¼ÿ¸¼]üô¯»«Ë(ð—ľ»¹½¹»Y¾¿¹œóXqè/Œ†n¿ÜõÓÝÕ‡Ww—¿?ü|qóÐbqñr&È¿ýÎfk€ýóóe«Ù ¼0Ÿ'‰˜=]Jú*ÒrŠ‹û‹¶
+VÝu,~Š}%‚p6W`5Œ‚ñ(3Ÿ)ˆÚ<
+@— xeÁÇ¢l¥0ÊÛªnÊô)Âå"ñ%—3Wå+ÃVhÄ°t sø" –¶< ;ô[cÙu¶Îö†ÞV‡btäí/yìe»jßPÛsža²ý‘Èj3Ði‘þp¸‘1÷ƒ(L
+`õ³WI÷æäi”‰YgHt^FJL{)8L¦vïqÒ&Ñ1G˜·"i§mQP—Uz¨3“@c ‰!äýX >\ú‚ÑÞ#¸wÐ{–° '{C{Z×îœ@êšÚã;'vrwNfô4'ƒ±Dq?âq2—ׄðÀçck ‘±]b8ð#Z„€4Äí
+9hàS"‚ÈÂrÄŠâÉŸÃ ,‚õÅ
+…¤ÚLIž^6˜­ÖšmÚ/iW9­”ÕþÉœ6àñ˜Ñ“ºV¿&NQ­¬˜"Ï‘kCIè¡çÐtY5}å5ä,¢ô,OÌ‘‹²ÉöeÖüÍè¡Um˜ …YN_8]{€(Eª‡>¸Õ­òVžÒ9gÉ õø«ŠvH‰±ÒqEJ½KW™é@qhû’Ú—¿^üpµXÒµÖ»ª¬©ƒ$XÐÑÑ٥ɀI»tßä«ùظ
+^¸¦â^‹VU¤Z§#7 È Äh-| iv ?]¯Ãä-°6ä'z»»}O]`oŠM=Ú]›ò¤„íaŽF¬¨+êš—«â°ÎÆ`‘ÇR <–¼ç1´“ÇÀ_|z‰¥§ 1Ô† «›¢(Á—2[ãÒÁÊ°ÕĽ"/¿NéÌjÓŸÛ÷¢ÚÍÇ&ÞcºúJé¤ï2tÝc°ÑÔ¡üZV/å«ž~kïIÜË@B$f_A*mÌ6èžÝ8Èá°’žô _󑥇ÎUÔA§C`aÞ02ù®ÄÈþÌë¦&š†…ÑmEèÛJþl:â Ðì´‰M;Ë7ªý %®õSÛØ$qdÚ‹Ä:ƒcÚ>ÅíÊl`n\M0€¢lÄÊ€hLÄSzd]Ö7ˆ•‰žÔöNël0î)%{²Pš.E^7ýKÏÀ–™ yýã©S
+¹·ãXÊiä®Ôiä­ÔYä“V;ä¯ÌŽ"ï™åpyx3v¸©Xñ3Ø© ìVê<ö)«ö¡Ùqì®Y¡ –ÉÛñã-9“3ø© üVê<þ)«þ¡Ùqü®YácÑW¼
+
+Þ2[£—OÇW{ÿüžècu°—ܲ';¨Q8Å·ÞmÙÞ‘[AÝ@@Æ Upðügú´+²G¾EÜ$¬ Çge®NÆ™¹ïœÌ†ŒyßùßÛçc:ªÔÄÎDyó}2 »Êc¿fƒ¥Ç´übË™ý¢0ì\Áïô,ê̸uÏ~ÌnÓçÌ)k¶Å¯¤›?ÖVÏ¿±oÌý2–xµH°r1…ÔeFäìöX¥YeôÖÐ
+endobj
+1373 0 obj <<
+/Type /Page
+/Contents 1374 0 R
+/Resources 1372 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1346 0 R
+>> endobj
+1375 0 obj <<
+/D [1373 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+414 0 obj <<
+/D [1373 0 R /XYZ 85.0394 592.2428 null]
+>> endobj
+1376 0 obj <<
+/D [1373 0 R /XYZ 85.0394 565.4551 null]
+>> endobj
+1372 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F14 729 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1379 0 obj <<
+/Length 3229
+/Filter /FlateDecode
+>>
+stream
+xÚ¥ZÝsÛ6÷_¡·£f"Ÿ$ñ˜6NëNëÜ9îô¡í-Qç$R);Î_ ì‚%ZI®“™\,‹Ýß~
+shšnJ„¼)ËỪE&|f´7 ø«- ©j|†-ë`2¯Õh“‚<T‘=Ÿ«Þfõؘ úŽFMpgwtû2IÞkåá04lÇü«²ÜkWõ`uʲ×/´N-“¹Ígq,ý³ðt‰ÀØâsH1ÿ,y,4³¹€t$5@*§“¾`™€h_¤*c&WzÈ
+b"é÷\ÎCÞ @ÈXðÄB “é4—³XîÙê=×Äò*Z^HÁ´¶f¼þÇ}¹¬Ö
+™G:<[·£?9—åê R@±ºáÀÉÿ}€ûs#
+=åØ–«3䨌Vjs1×ë è¹P,›º+–Ý*$gÐ2d——ï¹&֣°<Uãõ{PÈ\(dn’ '“Õ€LVZ@…c¾2!3êT¸)Šaj@…›\7s‘pÜç<ÝC ÝCk&SÀó(¿0þ”àî¿ÿF‚&ý"® @\üž.ooË34@ŸdLf/ëÐsM(1Bƒk¿dÁ‘׸²·ƒ/xðô59‹`­à(Š0ç(ã{¢­Êuqô OäýO"übl i̤ا\°uÄuÁÖËí’v´l~në”å:·‹:ô\JŒm-XžAáiñn°«‚ZUOÕêè[
+xïÍ«#óZ2¯ŽÍ«zü«Ø¼*ìrå>…&€˜hö]ÕÔ8^5J|ÀÖi‘q&3cÇźn‹Wû
+Ôù¡EUÚ$E$Ni ŽÄ¹É%ˆ+!'¨Ôõ–mƒ,K€5lí|"‡$#jÛ ÿù„.
+V–åÄFò½½B5®RÕ]y µHœè$U»½w`óD[éúµÝ7uKSІ­1‹.ÐqRhÆ9ô-#ÏíŠzYbÛܬ]^í‹@±6O~ÇäsÎvŒ{o
+ícƒsy< ³7’õ‘°õ6+('
+HŠDUôD_ý}¬(-!uwôµÒš¾µT®DÁû Î`¼{¡¤pTÛàÍk¶¢Íõ¶XˆT1‘ Î ÷ŒÇÖuOÐDT.C§d\eÎjL£3íËŠ eHàµÎÇ}J¥ÑÍý
+J{ÜQKì‰ÀÍ{ýæýû*èßL央÷ÂÈ[)3VȯpVjq m€¿\[†vénÛB{ot7úz:ÐÙçÚŽ•ˆŽš'º¤)Ó\«‹YD0rs1‹£ …a€ÞЭ1^XZêÃeß´mõÐ_W6´§þŽ"ºã…h™ÉO£û¸ß‡Ve[íª“ ïqkNüîc:x‹(z^Â¥À´U%íŒRipZñiA–m«ÏSvÍãÊd½Ep/pN2©U¯·SQ‚Õ~èÐ`†,¨BeUX}á}WÕŸ:ªÿ8…’úŽÄ`Ç„´qÃä» Z·ï_Æ-’ ÚQsòûÜ@Êï6‹© iŽÝ$@Y–©ü[Zç‚ ?i¨Ë—å¶ZNÉÉ™}[Ü!p‹9
+ÏÿúSƒyt;ùÇå²,ý8|—–FÚ#^·¬¶eÛÒ¢ë‘>ºOÇaö‹]Þá
+#8Á¬ÎáLÙ7eîÒ "¸žqDJ¿<9Jø©ÍQè+Ì¥T²ÁÇQB{'ðøê>"Oº¡o Eà<F›{ÂÁq½ì Ça/£í»ººõõë0ò·ÑUÝâ[vW`DeI}Ü=`
+endobj
+1378 0 obj <<
+/Type /Page
+/Contents 1379 0 R
+/Resources 1377 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1346 0 R
+>> endobj
+1380 0 obj <<
+/D [1378 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+418 0 obj <<
+/D [1378 0 R /XYZ 56.6929 489.6987 null]
+>> endobj
+985 0 obj <<
+/D [1378 0 R /XYZ 56.6929 463.7183 null]
+>> endobj
+1377 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F62 1050 0 R /F21 702 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1383 0 obj <<
+/Length 2832
+/Filter /FlateDecode
+>>
+stream
+xÚµ]sÛ6òÝ¿Bo'ß„(>I }JS'uçšæRwî!õdh
+²9•H•¤œøîúßoø!ѱ]÷Fø^ì.ö›b
+?¶ÐŠPaä"3’(ÊԢ؞ÐÅ5¬½9aaO7%ã]ß^œ|õZd CLÊÓÅÅzKª5[\¬>,_}ÿòÝÅÙûÓ„+ºLÉi¢Rºüöüíw8c°yõÓÛ×ço~yÿò4“Ë‹óŸÞâôû³×gïÏÞ¾:;M˜V Îó
+g6'?Ÿü³8ZõGçø'•&ŠËt‘(N4MÙ<—)¡
+¸–d’‘Ô(Ùs™³9.Ç]ŽËÛüs’yqc“¶ü·=¤š4Sl1}„@¿k1€¥0MP¸¸±§‰ ÂáRn÷[äÛz_uد×aƒÝÖÍöË
+Û«»Î¶Øíjl÷m
+…3bÇ•ôعv•w9ön®õ׺Þýæ”é¥uã6î*CoSnËî…ë«álDÙõ?•› öŠÍÃ-À2\u}ö-oíæ.
+Î8Àv Yú#nšJvFŒà:ì!aèODfí´,GJA™…"ŒKDÑY&–™¢”.Û.ïʶ+‹6)nòª²›1ûìÖVÑ7M¾ÝæÍ ¶À
+žz›òêóvÃAk¹ÖÑH¿dú`{ŽÄE«_ŸˆÖTC
+†›«×)²@g0n¦‡vGì­‹.üÖuh;\Á£)<M¹ SŽÒz@ãcÂ,PÝäWZºç4*<'¬åÕî/îoÛ0bµÎËM`@ gBôÞÎak”³û•àe5g|@qy½¢7¶3®ººw¯E]ux—Õ›øn ‘M0™ãðâÕ;·uñ›×~è;`«²ºÆ=y˜FÂD»³EéŒ-¼Ê1ÊlC¢¦ÜÄ"ˈPRCøÞ<cú1‰
+µžO’b2y¾ ó…SÞosz[qÌTÎ5© dxkñxdpX3y/¤æ.+zˆð@B£˜`Sødž"ªªÓ!–ŸnJˆQôa]Qyü^äÁ xó£Í2ŽÏßÝJœqIE˜I±çÀ˜Ûå\Ý£)PÏ!2»±÷C„h€<É ØðìÙŒí!&cÇŒåÁ1•™áæ/1VCeÔXŒ¼‚f’
+ʃÂÃP<;Í"Dšƒ7eûF‹ŽÃhw© :=Ì*°¿|€ßßJ;›·*0\Y…÷Þêð„  XSA¨ÁìÎÓº(Æ{g>@Ç÷‡Æ]x‰«Þ
+û‰5¶˜|:×裟wÂ>DÒÃP²N€R-—.Y©q-žÂ[F@Q
+‚­3ÉÐèšhÖ}¢ìü±¸¦†è,»ß²¢O‘µdššŠgKk1ƒ<–VO@͆›¿,­
+žøiå2‹[¾þzÎKFŽ<—[¢ŒSWx"É*„ž!œÃüÊÁü¾8Ü£ét/ˮ竮Ü;ôb¤r˜ÕFÂѯœËªdn2¥&(©¼WI1Y–.F»<DÄ
+©R0„»þÎ./Ã…@b[vå­?Ä1 rêí}Uc&¥çQ´
+øj×Øuùyc«ËqÙe îƒÙ\ýõª¾Þ‡‚ôm?ÖÍG4¹á¤{PšŠ¥ã¦¾-W6)?¯›'À˜ Р> †]Ušw6Ù¯vøñÍOUûíUdí#nwðž kòª]Û¦}ìi6w:Árêჺ² lødûoéê.Ì·ý6½ôK8ÿfïúï¾qæÈ…P#
+endobj
+1382 0 obj <<
+/Type /Page
+/Contents 1383 0 R
+/Resources 1381 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1388 0 R
+>> endobj
+1384 0 obj <<
+/D [1382 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+422 0 obj <<
+/D [1382 0 R /XYZ 85.0394 690.4757 null]
+>> endobj
+1385 0 obj <<
+/D [1382 0 R /XYZ 85.0394 663.4801 null]
+>> endobj
+426 0 obj <<
+/D [1382 0 R /XYZ 85.0394 582.7428 null]
+>> endobj
+1386 0 obj <<
+/D [1382 0 R /XYZ 85.0394 552.623 null]
+>> endobj
+430 0 obj <<
+/D [1382 0 R /XYZ 85.0394 310.6261 null]
+>> endobj
+1387 0 obj <<
+/D [1382 0 R /XYZ 85.0394 286.2805 null]
+>> endobj
+1381 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1391 0 obj <<
+/Length 3884
+/Filter /FlateDecode
+>>
+stream
+xÚ¥Ërã6òî¯ðQ®1x$P9M2ž¬S›IvÆÙG%9P%s‡"‘²G©Úßntƒ/ÓcOR:h
+0ˆÅ·?¾{{óÝÏï__¥ñâöæÇwWKeÄâíÍ߯©õÝû×?üðúýÕRZ#ßþíõO·×ïi(aßܼ{CGO }ýöúýõ»o¯¯~»ýþâú¶;Ëð¼Rh<Èï¿ü&.7pìï/D¤5—БtN]î/b£#k åŇ‹t£~é,ÿ¤ˆ”NÔ c9` Q"
+ÙŒ2&“ÏI¡C…ŽŸ“BzŸÊ)LõbUÔ¨×ëÓ‘šѹAbÚú@2¿ÏKž¿MLu…×°;3V7
+€=ÉËìÕÅ"²©yÉÝ©X>Ú¾A%3¶ôš{µwuÃÛ£¤hM –`K§¤Yd-4Î<©>,é‚I‰¬tcU¨½½Ò„„Ïæ5´ØUu¯³q*ü øi4á¾
+vx;«R62 ×|?Dãì-Ê$ ³Šfxm©ƒiéÄSD&‚–ž˜n@©_bº•ˆâ¸ïñ¾“¸,>mçÏÀÁv N íÜ&oÑW.öé%€îrÏußñz¯S»(ë5Fbë¸êØ QÝ4 ú†ùû¬i“d¸g˜B×Ü`ÛmˆßÔÇ!AEÌH]$‰£k/ª5 )‰§G$‹?¼ÝÄV !B³õ´ ƒ©~Ç@zl$ìÐJKG†àevŸ#H ^²×Ò&$rqš²¹B4-ï9g•4„¿iÓ9Ÿ“/0&.îœï<=8™0°©Rnì‡z& ¯$¶«TQR3//žŒÊïÊCÝ4ŪÌ#ºÈvÓþ`ˆgö`J§ô‹øå2Ðg%‡솻õ(:PãÀÔÓs¼ŸRó!!l­«%çöKúú9AÂKT’ÎjSXÝRt:!+Íš§·óÁUj"#{¡Š‚»2:ès}à°U¿ Q@.Ørœ
+ŽuE/Ãëd:A†ÑÁ3ˆ¢#/¥/—Ö›¿ÅJ‹Ž'fÔ€¬ Œ òɘã#Þð0qçX§ Ñ1‹À²S[ï!é¤Ô3^lÉÔAk•ù ö} ("jÞÞqòºå€Ø§Ã^ýûd`QêëÐî¿]T¹g@h ǪS ¼yAÙ/zûb}GÍÁáíð„®;¡ã Æë(¤ÇÖ&l_·_C+憺ëÕv•áê¹P,Ö±8g>ë(—ݬ/š»úT"•„fåCvn¨ýP?¢æ$ LJ
+’¸§Ì¹UQ¬µy±9S‚DäÚ¬¡4q§DÏk\êÜÈNò¹
+þ÷7íïþ@ÖGÝþ”ìÑ»y=@– :“Ž£H2šjÃíA£³Êäò:™‡VN†ÌjŽ·pÖªöU%€±Ñòm’hxëK3á$Åž7«y´“<èäåb[3–üS¶ÇÐ1ÐX0Ed€­îHäkœªJ/僲:ívçI}o}Ìš»b+µ®Ç+»8ZÀŒ‡Z||h1s&kb”ž©ËØX[œoªæ‰ÂBÜÉcÔûúRï:1‰í#zi9hˆèÖ%zÐæ8sßòÓCËËjúçMÒÅõ›wxÅÙËûý©£ç/ùr*£ÇBÆUGLÝ‚CyA#ÆÕƧsºÙôK&i$”Œ¿ ̘*Oî‹2°¤«Šá%-O›Ã²)þ˜«
+I.±nâ1!@¯÷d¹8‰ æ-´~~óy´Äi»%é±l¬j *
+ÿeÆ4MgÍÛgŸ>«¦`®t—tB!uPS©ƒEçö©ØŸöØQ=Ô¬³8ž7þˆÖ“C+¨¥Ô±Åì¥ò•O7Ñ*´Š´4Ž´5íTM)Eª¦¿ü
+\ù`sn=?ÖÅèg5´µÏa»==VtÄ|žÄÉâaÅŠ¸éqƒæŽ°”_åÌXªŸ?
+Äë}Ù'TÝ“ô$‰Øñ—(#ZïòK¬ËãdZ¤Â+@P‘*zêc.™AÿTm€Ž¶®7 ?œ¿G
+½¿…ÿÒˆ ÿb»=S‡Q_sö:CmïNÓ¯BÃ{:ldŒ$è&âàê³}ª8v×Ä*ÜE§©Àû%à…D.=íVÀ¼-DSo}qu&ùÅš˜ø²ÍR Û½2úB8ªW`ð<~]×*~â Öa´þvlD$øXTŠ'öK5hvÜíì›Ki×ñðˆŠ[x×Äqé$|b°Ê'IØ„ˆ‰õî xéˆÁnje‡:™v娔.@Êbï“ï4„Aiø€…æQ-ÓÉj}:öa!ŠjUŸ¼6A'Ô帮8òEÃMFüÇeã<ŠÞU)1㣌„sþ)L—ê¾x†=žØi5wàp'Ÿy ÃÄÀ³áìœÙ:˜äÎY‡G¿yÁRõõ’ŽæåÅyVÊÒ8R±çhQx}•‘pþõõÙ8l-
+üú˜ŸŸÈÞHÔ4{!ûØ€(‚Ì}„`u÷´Â&Ó¯À”€{u  RËT½ä;09kíüW`ËãrˆÒâ59?˜p›$ýÎ^Y6sI¸ŠlMღ Û›Žø©z¸«Í„S& ´MÌš@~bòû0ãùÍZä+pk|GðY@Œ9è+~ŠÐžùÅÀNMQ0¾¾ýpóÝ«é­@š_¦¹È&HCÇÝ%5Þ>ª ³—ƒéÄïá)§8‘€y Ú¦àQÍ”©“(M3$äÑ7}ݤÏïÿs@Òî¡ô,Ú¬äOð9«æ
+mÓqµÁ&cË•B6ÿ/F”zÞ­à÷Ío\´´j?¿ ¾=· >¸P–WšN‹!¸§q“= VvUÖžºr‡éJh†E þwy•é«;ìžbƒ é<,B &„#
+€>ÏÁž´|ãp€œ1LjñD#”®H—‰N¯ç«ñ“—/t»¢ÊÚÎÎŽ“žçêu#óMÏ%¦7/8Ê[ðUWØUaluûdÈ,\Ìf\¯KˆüN;âbÁDbcwÌö{Hê|}nsr„Ø$ÏXm ùè¹±B’Y?4ÔöæûSÙ‡’§ NLµ4~éUÂ}îÓF™L¥ú+eþb»àj€Lâ(}ô…Õ  (™‹œ{rø3÷­°6ø¸1gD÷í_þŽ¸ÿÈ:†xÎZ5oOTjñY¢ü÷ºöåáƒãǤÿC_ý¢endstream
+endobj
+1390 0 obj <<
+/Type /Page
+/Contents 1391 0 R
+/Resources 1389 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1388 0 R
+/Annots [ 1393 0 R ]
+>> endobj
+1393 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [87.6538 116.0624 137.7628 128.122]
+/Subtype /Link
+/A << /S /GoTo /D (tsig) >>
+>> endobj
+1392 0 obj <<
+/D [1390 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+434 0 obj <<
+/D [1390 0 R /XYZ 56.6929 718.7806 null]
+>> endobj
+1274 0 obj <<
+/D [1390 0 R /XYZ 56.6929 687.5668 null]
+>> endobj
+1389 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F21 702 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1396 0 obj <<
+/Length 2509
+/Filter /FlateDecode
+>>
+stream
+xÚÅY_s㸠ϧð[™µJ‘")Í>ew“m®wÙk’{èäv2²ÍØšµ%Ÿ$ÇM;÷Ý ¤þØò:¹›NÇ")@à@G ~á(–I4ÒIHÊÑl}ÆF x÷ù,t4O4éR}¸?ûë•Ð£$HW£û§¯8`qŽîçã»øùþòö|Â%«à|"¸¾ùD+ =>~¹¹ºþüË폎Æ÷×_nhùöòêòöòæãåù$Œeû¹ãpdÃÕõ—4ú|{ñÓO·ç_ï8»¼otéê2Šüvöð•æ ög,I,G;˜° L>ZŸER2¯¬ÎîÎþÑ0ì¼µ[‡ì'EȘër1d@™JÀ+4àýÒ @vHÃ$9çÀiê2Í«'Sž‡ñxRÛræ÷tÙk‘'±Û“æóa¾" Õq¾“g5À:k*íYÏVé¶2\D$ÇÕÆ̲§œ¨q ÊØÕ럟#ZB9ü’r[à$<rfÉ|nç¦r<ë‚^L78Í*3š„ ‚¯†aHÉ­@OEy>,ÿ»È Žd«š]ßeõÒ­/ -щë¢v*S>9¸Û;X€wN$P¯ÎžÍêå< Ã1¸g¤ÅøŠ” q#}q¥Ï7:ä[äÀëðfx‡’±zÓ•Oš]={ÌP,Îái/éWƸ™(ßeël•–N-‹ìˆô´_û;ƒ•®Z–cW-Ü{D-.#‹Ë7{œíñ
+}®Ht=^$*ù‹€ÐL8Ä­³ÖÜÔi¶ªÞ”TÆЀ¼sSÍÊlSgEN ÅÓP, @ ™·©–ÑÉ •Zü å¡ð¬³|#Ƥk.­TŒ(E/Ëň·Xkè'Ý ‡°vÈϿøñöC`U DR
+ØÞé
+xGÑ ¬,ÀV§íQ¦˜`ï1¼Õ2à Æk/Y¨{‹GÖ&À‹ˆØ¼LŒì¡TÈPÈuaºhq÷£žrªºÊ!0A]þ¦ù6“¡î.ðT…â ♉¿&ž8€žb™~Ûšòûá”0¦¾NÀPFI2Àð¨vZ4¹µ‰&¡YMB%®:ÐÌçsÍ(šðÝŠÝÒ‰&KÒ&˦ SGЩ_b+¹ª_„²šdV2¡]
+¡½‰”+)ºœðþ½H› 4=ç¬ê2ËD–o×S¬©¿7îÒ¿·lYŸáÃ!ÝÛùÚÇC_¿’íÉNôûû!cƒ<¬8̲Fæ¯5ò'ƒ×˜gmqCù¿`öðÆú'jŽ¨m±zbr„’cUËÜ µÆX½Z m†é§›»»Ë4®Ìl[fõ ÍlpE]aWÃÂeVyfX
+Om5€Ë‡U%Â@ÅÐ)GPã$úTUéé'Ý CÅÜ>ß~U ÂDA¼/d`™(é sد;¢ð¢jëâñ…·ç¤Å/Î’ý>Ìú#olšYóÂÓßšW°ñnirzAu 6Ûé*›Ñ¼¡Û¨Á ¥G^ä“t[/ 8/Eô§ej‡‘±?ï[^ìrÛ±Éñt넴ʽ`S·ÕzŠOÂÇ6ˆ)²Š)´PVn(@ZRo»XÒ¸Ò;h½m"ÚÏ0óÒ$ÃäJ+ñ0Í^´&ÙëíaT ³s|6)Éìó'mó*[ä¾’ÙC§/¹Më×øpFÇù2­hejð–piVäx gª¹ÛèèRšÖåy<¶áLsdè²—ÐÎ’®wÕÄ+­ûì€à‰ü†e:÷òœ‡c)?§«lÞÙœ;¢ YóÙäCZ·×íí½ï…]UQ¬0oÞÕ€6›ÚÁc0vg·m³GÈÕª!vvZ§4ÊMµÎ‹5øTÕ´Ü´×'î&˜d‹\í Ú”²Û…= *‡á0ú•IF0 “YQúR©Èç6§à2úI„!MWÝŽ õ
+±c N|}í\”¸Ï €·;ɶJð4ÿ‚ãiH¤ Ú2_QËëÖ@ðÜ-SGÙñ|J‰
+£Æ:0¶ŽŽÆãW'Žc_ÎÛ’Ì5·Eeönmߧª¦ƒõþßk-¨üýòŸ¾TPP+¨¤o—ÛÛÊÔûÞßšô/Þß[rî2ïߣºåtÒ£E
+TÄQˆÔ´ºÞ®êl³24sé$Aõ°íÀ¼’¤³e³·‚‹v!’8—K|r²¬]€–‚—–ótmÞ‘­ñ£æ{ý`¦H¶o‰¤G¦º˜+·”®˜Ê–k;ŠqŸ$`ð!…Ü«"šÐm\Tƒ6ƒðÊÜÛIxΥŠl@ø»M:3^ž:úanv«Ì†‹àÊ÷¢û©p––e†•_/ëmé¬õWD»E^4¹¢ Í·Gº‘þ e±GÔæÚ®Ó—ý¦c•9ÜnüqµãÕq˜Y-ƒ#ÅòAG"\±üœ™ÝŸëDˆƒr¼Ñq¬‰… b%÷Üæ÷ªúÚíXöÒØ:­gËÉl•$MgcØ£t>ZŠÇ•EW\ÿýýЕ¨}Á÷­…ÿ³®P%&°
+J³ áÒ¿˜ê±(óât·dÍSØOÒ®ùÁÞgHv·aþ±…ý=“A¿¾]ŠNyÀÿ°Mâ<ñ}¶=þã
+Ê
+$_p E›ã<ÔÀ4Â5@ÁcŒÀÛzÈÁ—é3±A€+<ˆÂÉùP¹O^Á±?~Á¯ñßÚ¶5>ý§ÿnÿ1t â˜7‚© æPô9¡lô$-«ÿ÷øPôÿLÎ8Èendstream
+endobj
+1395 0 obj <<
+/Type /Page
+/Contents 1396 0 R
+/Resources 1394 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1388 0 R
+/Annots [ 1398 0 R 1401 0 R ]
+>> endobj
+1398 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [399.2874 719.9611 467.9594 732.0207]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1401 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [461.1985 450.514 510.2452 462.5737]
+/Subtype /Link
+/A << /S /GoTo /D (DNSSEC) >>
+>> endobj
+1397 0 obj <<
+/D [1395 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+438 0 obj <<
+/D [1395 0 R /XYZ 85.0394 615.421 null]
+>> endobj
+1399 0 obj <<
+/D [1395 0 R /XYZ 85.0394 585.8633 null]
+>> endobj
+442 0 obj <<
+/D [1395 0 R /XYZ 85.0394 502.9736 null]
+>> endobj
+1400 0 obj <<
+/D [1395 0 R /XYZ 85.0394 470.6064 null]
+>> endobj
+446 0 obj <<
+/D [1395 0 R /XYZ 85.0394 298.1533 null]
+>> endobj
+1371 0 obj <<
+/D [1395 0 R /XYZ 85.0394 271.5604 null]
+>> endobj
+450 0 obj <<
+/D [1395 0 R /XYZ 85.0394 137.8852 null]
+>> endobj
+1402 0 obj <<
+/D [1395 0 R /XYZ 85.0394 105.518 null]
+>> endobj
+1394 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1405 0 obj <<
+/Length 2683
+/Filter /FlateDecode
+>>
+stream
+xÚ­ZYsÛÈ~ׯ`ù%P• Ï…+~’½²W[±ÖÑ*IUv÷‡Ê$À%@ÉJjÿ{º§{pP EÇ*— =zúøúˆr&àŸœEqg*›%™ #!£Y±>³O°öþDòž¹ß4îzs}òêNfY˜Å*ž]/¼ÒP¤©œ]/~ âP…§ÀAo¾|wñþWg§‰ ®/~¾<«Hï.þvNÔû«³ήNç2dðödz×çW´37—?ÐLFL¯Îß__¾=?ýýú§“óëN—¡¾RhTä“_³¨ýÓ‰u–F³{ˆPf™š­OL¤ÃÈhígV'¿œü½c8Xu¯NÚOŠPéXMPé)FYkXBžçÅ-j{å`¯2p^„G঻ÒÞó¦!C…ÊÈ”75mÞÚµ­ÚÓ¹–*XØß„P•mp(ƒœf'GÕKZho-Müpù ÍTùÚ6›¼àùö6g–÷åjE[nx­±¶"êæatN³»il;>©X• ]¾6Yœ¡B3 Á1€OÊ0‹"åT¡àë4 Öy[Ü¢8Èñ‘‚§2@EpP.i­lySSﶧ2 P_|ä— 7o›†Þ±F;8›‘¢$”J¶1²À×÷`§Áµ°SΓ„qÄÀSa–¦é4ìæÇù¥ÃÔH> XR&îF)^dL³0Ñ2~F=ǧdÌT˜(aÆB®Ê¦ÂtÂŽˆí]/{ç8ñû—f"`ÀI,|,8 ÌaJ…Q”¥Sk&$Ð::ö«|×8´§A^-ˆpPCba›¶¬ò¶¬+š@¬¹­C¬áD‡5ÀšFÝɱ…BÅÉ,јUfÏ€5æ8²œÂ$~ÅýÉ_[Š‰P=£žãSBf24ÙXÄCPKB‘dr
+jwæÂny¸¤gW“F„^?…Õ'úPš$ÙoCâ[ò³)?UÎaàÔ–¦~S*Aʸ¾&º¾è±h‚M
+%ÞhàYÁýáÍÁêK$¿È EG%“„ þ†EJP¹ýõˆn=´T1%œpf e«Ü¬x¥l°üÂb·
+ž«ï\[à¸Öž«OÓšh…w9£Ž
+L!µ \u*±Ó0>Ð×±žFPÔ!Ýb®‚œD¦Ü”žïUæâ€'\pˆï-ùéÁ«¤._\Ž·ÁÂnmÌ÷²nùt_äb¾¸Ãª¹ý®z½s JÍH>œd!ïpŽEHr*oÊÞ?”ØŽ¸¸ô¹›t@.9E½Þ”+»˜{öðåÚÉìíÌá§?ÛYúóÞü°¦¸kð±8"3“Mõ‹À—Dõ &ÀjèÚO4B’‹œ"«©¡Vþ 'qÈy®ÿЇ/Qe’}·‰§úÅ][Ãî²
+*±ðÜäÛ–(ú®‡(v†O‡ÈLú
+õ’¾ÓR±Le ™(È@ÙQµCdÙÄ÷räÍm/P¾äâuð@ÌS
+dQ1ûÚ¦¢l'ï¦.øY–|O à@Df—Øßm—¢&ì5®ú
+endobj
+1404 0 obj <<
+/Type /Page
+/Contents 1405 0 R
+/Resources 1403 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1388 0 R
+>> endobj
+1406 0 obj <<
+/D [1404 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1403 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1409 0 obj <<
+/Length 1124
+/Filter /FlateDecode
+>>
+stream
+xÚÍXÛnã6}÷Wè1)@®¨»§lê¤Yt³­×}rƒ‘(‡nKÒqœzÿ½”(Ù’/Éq…aHâåðÌpf8C¤éò‡4φºé[šë[ÐÖ‘­É@×f²ïf€ª1 š£>Ž®MWó¡ïŽ6ŽXÔ=iãprvõÛåãáè¶~æÀs`;úÙÇÛ»_U‹¯W_î®ooþ]ž»ÖÙøöËj ¯‡£áÝÕð ÏFr¾Q!˜p}ûûP½ÝŒ.?¾ß? †ãµ,My‘n‚|Lîu-”bèÐô=[[È"ß7´d`Ù&´-Ó¬[âÁ×ÁŸkÀFo9uŸþlÓƒ¶g¸{h !èÛ¶ÑÒ íCÇ4ÌRƒ…І-5 ëúÙk–%àWIH**yNÌ
+y?\[¨±-ºLº®«6D!8Ö4ÅIõ9 bÌù½úø·
+äYLƒ¶bUÏTõLÙ<®7BxßG<i&hÔ†§ù´à]aæëöâ£Z¡Z`rÄI³f×YÅÁ# ž@aÈ\5ü­Ûú³ta¯è,Í‘m¨µÒÄWˆÉËIá4ÌBÕ¶$|š±išu¦‚ÌË-€Î4BŠãyÞ|Ÿf¹ µu@ˆhmO\0šÎ~4±%ŠÅteLšüF³‚¼ˆË^ý'›³Ç]¹m./ š8}­’oSž“ ƒ4R„Åz# ²4^®"ʸè%E…Co9Ùÿè7­åéKÄÀæÇmi9;bYBɈIÒ ö¿7l{—„HrÐǶ¶öSz†üƒ-y:9Ú¶Œ$Îf ÓHçÉC}"t´¯ú4”&ŸÍÅû‘Mz!µ$k†ò-½¬Ôƒ¼äòÈ ¢Õ¨ÜæÝ™´Z
+„$ÆÕ$N‚, y_‘žáþÑ2Ÿ?<‘定½÷4·Š—$ ›@s«á®«
+YÕOü©ÊVzO×þÜàç¬.÷]™6,îvö\êèë{›w_!mî×,™/xž±¹2÷8¦î@ÏðÝšT¡Pm3_ß5íRÿŽ@íendstream
+endobj
+1408 0 obj <<
+/Type /Page
+/Contents 1409 0 R
+/Resources 1407 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1388 0 R
+>> endobj
+1410 0 obj <<
+/D [1408 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+454 0 obj <<
+/D [1408 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1292 0 obj <<
+/D [1408 0 R /XYZ 85.0394 748.6299 null]
+>> endobj
+1407 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F41 925 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1413 0 obj <<
+/Length 1090
+/Filter /FlateDecode
+>>
+stream
+xÚÝX[sâ6~çWø:#Å’ï³OÙ”¤Ùé²-¥O”a[NÔõm%± Yúß+_
+ãýíèç²Ç+{@ÇÃëáx8ºf“½ád£K]_¤¹"_zÓ™®Jí=žkiêE‡Èó°÷LË€–i램÷Gï÷ `m´m´Ò!6lÜ`@Õ èêÐÖ”cyÐ6°Qp:
+ÊÁV‡4‰–«q!;iQáP^yø[ù¨FY6'AÀ«¾,årÓŸ¿Ìv¦®ç+ÿ´˜ž=…ÜqšK é§1XRN©K*æ)Ÿ'i[2Î@—ØúΟ,‘ê¾Ógâc”Š#ÿ¶õûŽØ<b¢Xuñàô3]–-Õ˜mÀwÃhªÜÁµyŒæˆÒûZ'‹øŽòN™"9I„r/`J^–´B‡Ò…<Ÿ’dqJG€:PÚQ.I% —1WÅ}Ê"æ³Ýà(£äKGkÒåT  ©„õÓ$]d
+DJZe뎮Ùân­u3íkwLåC„ZŸ}ºM4–™µTZÈñ K!AÇ4¬è§bÈ‚žãØZ­›PÇVÒ’_^’@C µá ¾ÚuªöKªž±Úé+ªæªæiT±n¨jÃñ=F" :™µ†öfź1²¬F³6p=jZŒDŽn¿]ì@dº¸‘îBP°×¼]²ªJÊVAo;Ðp°¹O]ë¼ w h˜žwhéhòÛüy‹ìôÄ.v‰>§ B©öcæ‹S«€HÒ¥:ÚÝ^T=ÂiÈ©x(v—“÷¨S@ÐK&’/ÏåqÄ"’ ”{Þ©y¦<I±s)£ã0
+1WÇPÿ¡Vµ·)¬k˜`}p~ØW9ì£×=ì¿Rìý0wÿÝSûÿøÚíxÙt±gX0¿k¸†SÿjÒ³/ý¶7¢¦ª¿\oîó°Q»ÏÃŽ MWT¤reü‚ùúvð%õõ~Lendstream
+endobj
+1412 0 obj <<
+/Type /Page
+/Contents 1413 0 R
+/Resources 1411 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1388 0 R
+>> endobj
+1414 0 obj <<
+/D [1412 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1411 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1417 0 obj <<
+/Length 2117
+/Filter /FlateDecode
+>>
+stream
+xÚµYÝsÛ6÷_¡Gú&DðÉñ““Ú9w.nÏQ_êf<”Y¼£HAYQ¯ýß»ÀmÓ‰OÇX.‹Åîo ™M(ü±I¦¹œ¤¹$Š25™¯èäæ>1/¡x(õnzôö\¤“œä O&Óå@WFh–±Étq½ÿçéÏÓ³«ã˜+%ä8V Þ]\þ€œ‡÷?]ž_|øåêô8•Ñôâ§Kd_Ÿ]]¾?;ŽY¦¬ç^à Î/þu†Ô‡«ÓO¯Ž?O<:›ögž—Qaò¿£ëÏt²€cÿxD‰È35ÙÁ%,Ïùd}$• J
+8Õѧ£÷
+³né˜ÿ”ȈÊx:â@Éd4#¹ÌÓIªr’.œ¯ã„Òh]|‰»¶¨ÍR·qW®u\Ö8So×3Ý"}‚Ãg{nØ<fŒäJñ¡¢Ívö_½¼ô)ÚtmYß>[}o£i¶í\#ó7ªh¹‘7ÅbáµþáT°4'‚§
+4‘T
+éýÃM)’§i2ðA ÃÅ×›¦í,77öãóˆ}3DÀ¢`'ûŠñ]245yljžž
+f rëÉýqUž +î«Šû#ÅBP’%Ð…Ž·ZnÈ,Ë&B&DÒ<s.ô¥]-â)ø‡ubÓ•õ,8ÕèöΖK¯
+È*žåQß¡ìXzÞlöH5Kê‚
+[ð‘‚ìD¢Ÿó`±:€µ+«
+©™«ŬòQï7í1Ë¢æ®\ø‰bÛ­š¶´WÕ]`Õf窂ý@;€(;ò1ŠÛØdèÛ×ÅËƒå ¼- £
+©‡¦[ÞôÓŤà…oÍR4.–^-ê²^ymöœvtñq©¿x3šxp. ç°Ä½º&”ð7“šy‘\2]¿°
+ܦ@õ†ØÅ°Æc 7Áªj©ÒŒº ‘i#Î^’‚ro[Õ@¦xÎ!9ì—·¨Þ P`,pèýÚ+„×]ÛÙúœ$Г…UË°jľ žS†÷B¯kÞ¬¡Ê,œíœA2–õ<v86Kç<»â£Ù=T-m-ÚnP{àêª\—£´†Zéoy{ýÈ<ªAqFæ΂IW9A`jwå¢[Y3]6A"ÔðÐ1€p…•êÖK`V›qÏ(j¿¡"‰4êÚ Ë%/pVÛÚgÙ"Ì,½ìªÙ°Íà è0Åj Jm\ûbg,´%Ö¾j:œÖLãu |sûC2
+üîvM\d+äBùwÕÍN™ùJ¯½´o¦xßø 
+w_LÉs‘þ2¶b½©ô›Cw åºo=€
+¯ ªü^‹Ò—¿®M>âòwü™1ìß_÷&<ó¿0f”€Qc?ÓÓIðЫÿ)pø 4ÙÐÿñþr¿K§ ÉxžÂû›X]62©xäŒðß/50ý/—$Šendstream
+endobj
+1416 0 obj <<
+/Type /Page
+/Contents 1417 0 R
+/Resources 1415 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1423 0 R
+>> endobj
+1418 0 obj <<
+/D [1416 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+458 0 obj <<
+/D [1416 0 R /XYZ 85.0394 421.6574 null]
+>> endobj
+1419 0 obj <<
+/D [1416 0 R /XYZ 85.0394 391.5435 null]
+>> endobj
+462 0 obj <<
+/D [1416 0 R /XYZ 85.0394 391.5435 null]
+>> endobj
+1420 0 obj <<
+/D [1416 0 R /XYZ 85.0394 367.1321 null]
+>> endobj
+1421 0 obj <<
+/D [1416 0 R /XYZ 85.0394 367.1321 null]
+>> endobj
+1422 0 obj <<
+/D [1416 0 R /XYZ 85.0394 355.1769 null]
+>> endobj
+1415 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F21 702 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1426 0 obj <<
+/Length 3415
+/Filter /FlateDecode
+>>
+stream
+xÚ¥ÙrÛFò]_Á·@Uâx.\µOŠ#;J­å¬¬­Ýª$ ŠHH€!@ÉÌ×o_‚$'ërÉÓè¹zº{úš‰†f'*Ém>Is¯bmâÉl}¡'OÐ÷þÂȘi4ŽúöáâÍ;—Nr•'6™<,keJg™™<ÌŠeÕ%¬ £·ïÞݾÿ÷ýõe꣇Ûw—SëèÝí?ozýáÃõýåÔd±‰Þ~ýãÃÍ=w%²Æ··wß1&çæ•EïoÞÝÜßܽ½¹üåᇋ›‡þ,Ãóíð ¿_üô‹žÌáØ?\håò,ž¼À‡V&Ïíd}ác§bï\À¬.>]ü«_pÐKSÇøçm¦â$Èf¹Š÷¯ïË{hØW@›8¥ 0úxßifT’¤(íUž„âÍ@(Æj•ÃB“4ÎUâ¬#©´ÝîYóæ ƒ“L¥Þâö8èxéR PýÑÔ%ãªVúªuµ*¶ÜÝ5Œ,¤oU<—‡‰WæQùyVn:Ñ- ªŽn/M•›U5+ºRöhêÕiª¦Æ¨<Ž-‘×-augóèLž5ÔÎ[îlÜYðçºh»rË(>b«°ÅüxF¿~Yw¯}˜‡úè“è“ðñ”6‚äkaªÕ:ª›N°üÝvE=çsîØÛŽûĈøîîÓ?zÔžqƒÕûEeÑí†øvSΪŸµ¶³cZù†’ØàÎð>ñð’Uëͪ\Ãù‹®jj5vRâ
+3'!’…@]¾0
+:%ŒaÿˆP¯øAç´l•aÊf[=KhSÊî¥ÙþÆ»v:.àúIÝ¿{kr“ñÇÀíÊ
+þ&9ñØB SnëbÅ£„¥40°4$gR²û›4Dz¦ÛÒ_\øà‹ëà“
+Ï$`Àžü­Êmò¯@ 1òª/@Ì%8’ñ`J\~|¤ÓËì|:8ù)®2/‘1¢ØÅzqû˜ô^q
+NÊØ>Zñ–¬úpóljüi•©WFögj}.Ézù‡ålYÔOG1% ,!Ь‚# “ûóiœoÁÜ Éǧ
+5Æ\i«óžo½òʧùé™(.´ÞBökñÌ’>Ìï¬÷çn{Ñ‹lÛŽ=NîîDQi½±‰˜¼a‡,NŒ
+nr3
+VåÕ‡§áùçÄ„89dUyoCØMÛ(´\JAˆ³Ê:MÈTe‚žÓí‰QÅNc§ ‹×‹mÑvÛKˆfý#ËŸ?
+²8ªüL¼7¼Ú˜Xrï?Òð(.w©N‹‡«²„|G_«ç˜¿¨ÔpLì‚_¤b«#‚°ñ‚ˆûœQÄí8(‰Œ?èE3ñ°“Ž“Ø°éiûå°ex±¿ÎVÌÏáý‹ïò0'ÎããgùÿkR (P™ê ò³Ê%¨ðšöªoÓ ‚6ç&ø{ˆ}ÒÃÏ"Ž ò“ãS•¦&éaá?PP ·™œÉˆBhÜF´ð}¤drV¹oZ†Ù%#DµI8o—¿eÀ¢Y­š¾pš2ul nÈÝÒ5ÑäÎO»¬Â®|õГ³2úü:@f )¯ õ
+p#fݩ̧!ßAÓ9^*5©Êµ ·TÐ,ÇBMå!4œhL=XZŸÛ“ò@Höà;|<Å$@÷ÞE÷ý³f+·¬;+tŠÕx.Zé[¿Š•&€ô v7så]œõb92€:Ü[–mÕ¼– æ.ÔDrøh^IK¯Â öOìá½¾B¹&ô<4“·ù¯·ßÈ’?rǯl–
+Ϙú3ÊVÖ!>'ýÿÞüendstream
+endobj
+1425 0 obj <<
+/Type /Page
+/Contents 1426 0 R
+/Resources 1424 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1423 0 R
+>> endobj
+1427 0 obj <<
+/D [1425 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+466 0 obj <<
+/D [1425 0 R /XYZ 56.6929 167.2075 null]
+>> endobj
+1428 0 obj <<
+/D [1425 0 R /XYZ 56.6929 139.8789 null]
+>> endobj
+1424 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R /F21 702 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1431 0 obj <<
+/Length 2969
+/Filter /FlateDecode
+>>
+stream
+xÚµ[[sÛ6~÷¯Ð£<S¡¸À£›ÚYwZ§ë¸»mh‰Ž9‘D…¤ãº¿~"
+t¦ÞÉd ‚Ï Š,0ü# %fš/¤æH`"ëÝ^|‚{ïψìzÐjˆúáîìû+&éŒf‹»‡,…°Rdq·ù}ùî_¿Þ]Þž¯¨ÀË ¯D†—?\ßüh{´ýóîÃÍÕõûßn/Î%_Þ]¸±Ý·—W—·—7ï.ÏWD ÏS'áÄW×?_ÚÖûÛ‹_~¹¸=ÿóË;ïËÐ_‚™qäËÙïâÅÜþé #¦•X<ÃFDkºØqÁàŒõ=Û³gÿöw»G§â'˜BBQ9@ʦ(4ÊÜ2¼ØWícQƒWJ,¹¾3 ¾Ü_‹muØûÖÞ)û÷Ýc^5û¢ý.5[æ¶÷ç‹ûÜ¡>'jYµÕºÚÚ[뮧ÈÛbã$í-´ÚŽ]¹Y-q±ç„/ÿ[íÝMÞæüP9 KgÏ:ß›ØC
+/Œ¤~š0  [®bÈõÿŒn*¦›óc¤\R$e&N34ÕB®¦×ãgœŽå¾šqK¤¥`éè{ÔŒ!±´$ã„!(3Œ¢N3ΣŽ#ÕÖù¾y€ÅT”à4¢T¥Õ÷  õßGkêK¾ ½)Ï2”IÐ}’oFxšâ[Ÿq:–ûú §’
+Ïß£æ ‰¤¥ù %aPÓ| |ëQÇ‘z:À
+¹ˆÙ™KPÖîQêC¾A~cœ†úß’oG/Æl£HaÐ|šm\ a˜“lsø—c¹ß°v3´ÀY:ö5gH$-Í6äÄzŽmT‚m=Êh´#´:TÛr=±zSˆPÊÓê=jBH7f6Î24à£ßÎ56þ¹ýóHüXî[GB£'»ß´×¿u†”½vB Š°¾Â‘ÇcotÂ`Í7´4E«?ãZ,w’Vtê¥ °ôeé{ÔŒ!±´$­¸â¨Ó´¢NÓÊ£ÆÓ;üç¼Þ”ûOc;(†¸Áö1mˆGMX2tžbDºõÿÉg#‡Æ4' ­ÈÉÜÆ6W8 ¡ÇϸË}ýÊ œÍˆâéqð¨9C"iiB^`ŠÍ‘p€J°GÙ1kªSEK-Íg”{Ô„ö`Ȭ朗ÿ°ß¾@Ø©^îŠ|dyxÚÚërŠoàŒ^¿à?Yõ€å’²ßµvµ;˜Ã -lÛÔ Ñ>ö·ÿ®ö…ÉŠ˜-ï¬)ZÛ
+_UõÄÔÊ2„a)Ö¿@¬ï“ç>Ò¢ƒu3#Z-†câÍ-‡çd<äåvjYoEMéô´élR¬÷5ÛüëԚŸ1ö†–ÚvªI¢œ-?5õ‰†,ÉÌÔ S¿G§þî¯hÞSØwjIÓš=jBu¸†ƒÝ©9 t¿ÍæaèÁø-+PÆÕé2/…!‚¨ÀÉÄfÁãgÜåžÚ,h ï2I4KÇÝ£f ‰¥%YF gÆgX6Df™GÇÖº›5líâƒo])Òú=j€0hÈÏJ…¼%׆~Ä D+•8X0»mLW“ ?ãt,÷ÕŒãØT5´LGߣf ‰¥¥' ¾˜ÐÆ P Æõ¨ãH•û¶øT—m¼E…‰‘ X4' ð¨ BÊ)óaˆ
+MxKÊŽŒ9GÁ4Á9&aäXàkŠs=~ÆëXî7pŽ£ŒJ™¿GÍKKsÎ|eÂÔç¨çzÔq¨šò~;Që¾åàð
+Lª÷¨ ý!ãâTëЀ·9¬Ü/0¤´Ö‰ãóé =M/8üŒÏ±Ü׿U5F”Òtì{ÐœcYI² Ü4­I² Q§ÉæQÝš´¨Í>vÕTùªm·q‚Ã0JD¥ ð¨ Bº¯’‘Є·¡Û„#cÂ)Äxâð¶œ*¸šÌo?ãt,÷øfÎ]OGß£æ ‰¤¥)T:G¹*A¹58βùásó9â\,!ÙŒ5aBÀ9‰‘ÔrdÃÛ¼T§<ô ³L&>€3å>94oî´ËágÜŽå¾þ­
+»1-2Ž¿GÍKK³Î|äÉ2iÖ P Öõ(£±­_Víú°ª‹‡ºh§ìÔeÚ
+µ4mUÛ Ìq(÷Àî÷5EóÌñ‘‡ÊÒ¦¾à†64,,ã«Â›Í?þ¹xyvµJÐB¥­›¿°ý©í7ò…=M¢j™»›¹ýcJç¶ÕÅ
+£Þ()Æ–ûŸ’Ħÿýì{endstream
+endobj
+1430 0 obj <<
+/Type /Page
+/Contents 1431 0 R
+/Resources 1429 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1423 0 R
+/Annots [ 1434 0 R 1435 0 R 1436 0 R 1437 0 R 1438 0 R 1439 0 R 1440 0 R 1441 0 R 1442 0 R 1443 0 R 1444 0 R 1445 0 R 1446 0 R 1447 0 R ]
+>> endobj
+1434 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [312.6233 667.7189 381.2953 679.7785]
+/Subtype /Link
+/A << /S /GoTo /D (access_control) >>
+>> endobj
+1435 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [310.4119 636.5559 379.0839 648.6156]
+/Subtype /Link
+/A << /S /GoTo /D (access_control) >>
+>> endobj
+1436 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [340.2996 605.393 408.9716 617.4526]
+/Subtype /Link
+/A << /S /GoTo /D (access_control) >>
+>> endobj
+1437 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [328.1051 574.23 396.7771 586.2897]
+/Subtype /Link
+/A << /S /GoTo /D (access_control) >>
+>> endobj
+1438 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [320.3548 543.0671 389.0268 555.1267]
+/Subtype /Link
+/A << /S /GoTo /D (access_control) >>
+>> endobj
+1439 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [359.1386 511.9042 427.8106 523.9638]
+/Subtype /Link
+/A << /S /GoTo /D (dynamic_update_policies) >>
+>> endobj
+1440 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [429.9426 480.7412 498.6146 492.8008]
+/Subtype /Link
+/A << /S /GoTo /D (access_control) >>
+>> endobj
+1441 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [286.0435 315.5214 354.7155 327.581]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1442 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [339.144 284.3584 407.816 296.4181]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1443 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [336.952 253.1955 405.624 265.2551]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1444 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [322.5463 222.0326 391.2183 234.0922]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1445 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [331.4327 190.8696 400.1047 202.9292]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1446 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [361.2812 159.7067 429.9532 171.7663]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1447 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [330.3165 128.5437 398.9885 140.6034]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1432 0 obj <<
+/D [1430 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+470 0 obj <<
+/D [1430 0 R /XYZ 85.0394 726.6924 null]
+>> endobj
+1433 0 obj <<
+/D [1430 0 R /XYZ 85.0394 700.1172 null]
+>> endobj
+1429 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F41 925 0 R /F21 702 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1450 0 obj <<
+/Length 3050
+/Filter /FlateDecode
+>>
+stream
+xÚµZ[sÛ¶~÷¯Ðô¥òL…
+6§éd2†€Ø]àÛÅâ‚WüÃ+ÆWD­„Š‹0[m÷ÑêÚÞ\`‡ÙxЦ‹úîîâÛk*V
+)Nøên×éK¢HJ¼ºK[sDÐ%ô­_¿{{}óæçÛW—"^ßݼ{{¹!,Z_ßüûÊ–ÞܾúñÇW·—,^¿þ׫Ÿî®nmw}|wóö{[£ìŸ™No¯®¯n¯Þ¾¾ºüý«»Ö–®½8¢Úÿ^üö{´JÁì."D•d«gø!¬Yí/bF‹)õ5ÅÅû‹ÿ´vZͧ“ã‡#D('Hhg
+gn+ôl»kÉËmqJµ<ýë9omÉÈ3ŸæusÌïOÚ"[e[(«2›èÒ`»wß¼¸Þ,õÐÈ›0ó— aíÓì· MeÉ'¢G‹Ò£‘æ0‰‡¡XÉÀó XšÛõ>Ç@‘žØ÷Y6ϬÞóÃy8«s­® J ˆ€KFå2)ø)Ès0ì}
+[A`ë CÉ0§€‘¢„·ñÙV%ˆì¼Ÿa–.dv,³4ïÖ´Í5H…>óÇ2´µ#§3$“-Me¯v˜ 
+pÒ£LÂõçÎh³1éý0*sDUaé4!½ÇË#W¤/þ—KEÌʆa‘<–b†è»Ó%i4}õOé݋ýaF\·–É>³UšI&(!Z%.¹ÓØ¢z°-"ýQŽ°Ù"ö•)\¯fÖueúò­Sö
+¹¨ÒçC/µQB¯R†2î(«»Ñ´mrïÏlü«7Ñ8ˆóØë°Oj—N ¨ób¯CàD_
+Öá5­ }5aƒðL½@·'œ¡2•1)‚F5OåeíüsãX³©óOãˆ;âˆ-(àA
+ôw×EÆ¥§Á—9È™²c ^H$³G:&ø%z¶ŽtZü‚Ùã~gt¢‘NƳðø·¨%MF½Ït((dÄ ¤ë ¤ó(?Y&óÙenÅÊ÷Ùf<#ö¨L†õp˜ 5zÔƒ]ã˜öõørÔ›³fÕ!)Õëä,y„0Ã}“CôøóÇýÎQP UÒûI1 ÏB‹ZPdÜ[˜°óŽ÷]T€59gyZL2VX~YX“5¡JŸ… ¥§¡«Ë?ÄÂŽECRÄ#IæYÈbÄ1=£C,ôøóÇý~ 1"Šð<´¨EƽYH¤DB.„Áhžƒ46ªS3Ž‚°2`…ƒz´ ±"=r « 0µ«É?=»n…¹š§ €¢QÏæ=<lý¨×¿Î?
+[ÄH…¹Ð‚ÂZŒú
+“öVúò+L¾3(@>š“䣈Æ*¬G +ÒQõ5ù{äSÁè7M>¥¯RÚì|jf0`¸kqp ¶è°éÃ>?ƒxRí°ñoAa%F}…‰K5añó:¨
+iúq'a©3!tp8Ábhì ½Ñƒ,bÞ%ù?6ç«PÓåCù9q•yÙ˜SYý‹¹+J¨v7dîÒ>¶×汶­ÐWXºìnRà+m®©j?ÿ˜Íí69‹4W1€®ó‡2Ù¸³gˆ 1¾]9ï´ˆ½ÍÓ¿ûþýÕk[Ö}‰ÕÃAŸí#bÞ:¼ØÒùº”èk»$õßÙ[˜jo¥yýdY¶×lP©\[åØëVb ܽœ•IÎJO¼Dô. Åî{ûWxÝð`§k–¿B "øBÚ×ͳ׃üñö¦n`Úê&ߎŸÀF\r,‚Ò[ÐX|/Lê+ˆ¦]ñ7»‰GUJ¿õ’ÿד*ÿf˼5åóSª§,;ø_ÎÞÄ5ååN¿qÜ…
+Kló8+¯Ï¯³Œ ©®lmí6)ÛçYæozÚ²Ô²¶µ2ŠpŸÝËˉ·/B?Çðéêyb:‡Ã”CATh¿H3 ,‡×r-ÉÚ¡9¿2@s½)C3¯á¿óß¿ýüüB>ˆJ9—à C©WJÛ*øØWÜkñ±êÿ×è"Rendstream
+endobj
+1449 0 obj <<
+/Type /Page
+/Contents 1450 0 R
+/Resources 1448 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1423 0 R
+/Annots [ 1452 0 R 1453 0 R 1454 0 R 1455 0 R 1456 0 R 1457 0 R 1458 0 R 1459 0 R 1460 0 R ]
+>> endobj
+1452 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [231.137 681.3376 299.809 693.3972]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1453 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [324.1075 378.783 397.7608 390.8427]
+/Subtype /Link
+/A << /S /GoTo /D (server_resource_limits) >>
+>> endobj
+1454 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [359.1555 347.5161 427.8275 359.5757]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1455 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [353.6164 316.2492 422.2884 328.3088]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1456 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [370.2338 284.9823 438.9058 297.0419]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1457 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [364.6948 253.7154 433.3668 265.775]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1458 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [226.7331 222.4485 295.4051 234.5081]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1459 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [283.1811 191.1815 356.8344 203.2412]
+/Subtype /Link
+/A << /S /GoTo /D (tuning) >>
+>> endobj
+1460 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [287.6042 159.9146 356.2762 171.9743]
+/Subtype /Link
+/A << /S /GoTo /D (boolean_options) >>
+>> endobj
+1451 0 obj <<
+/D [1449 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1448 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F48 940 0 R /F21 702 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1463 0 obj <<
+/Length 2955
+/Filter /FlateDecode
+>>
+stream
+xÚµ[Msã6½ûWè(WEX|¬=MϬS›IÖqjI‰²Y‘H‡¤<Ñþúm D$¨©8•J‰Ÿ¯»€njLVþ#+-f _©„#‰Xm7xõÏ>܇Ùt MõõãÍ?Þ3µJP"©\=î{¶4ÂZ“Õãî—õ7ÿz÷ããÝÃí†
+¼–èv#$^}ÿñ[;’Øo~øøþþÃÏïn_?ÞÿðÑ?ܽ¿{¸ûøÍÝí†hAàûÔY˜ùÂûûßÙ«ï¾ÿþÝÃíoßÝÜ=z_úþÌŒ#Üüò^íÀíïn0b‰«ÏpƒIº:ÞpÁàŒu#‡›Ÿnþã öž¶_Š Êåj`"ŸŽ2FX@Ô6ŠÄ\uQ¦d*ÊÊD¹ÎŸ6¯é!ßåÍy“MVÁÝØw¢RZÓU‚€†GMð`=ø*™ˆ!‘Ÿ²ÌÆ¿yv»¬ÞVùK“—…(÷†ØÈ«D!L¹
+QwF†(
+ö[y1ö˜iŠ(%jà±}X=­ìÅCÏw_ð=´k}ß^¼4R%1ædáñ,xÔ“Кa‚Ù;m)BÌÒLØCEØ¡ºŒÁÿE^<mŠrˆOJÄ4“q
+5Áa >ÞJž Iü5ñ%=ñ®Œæ×uæ¿1!<É'tèmLx~ÁïÐîAâãñ xÔ“ÐZTx.4Kd\x}Ô¼ð<jœ-ó™6§jB}Â’hçáQDêK¢zÈãí6¾ioÆ0Cj~ããð˜r:ô7¢?_ð<´ûúS%˜‰x<j‰I`-®?‘HìÑ_Ñ_‡g¬9¿dòDe–q5Aav e‹¢C
+o/½Î‘ÑìJ"ÉId×ã X”C_c»^‡_ð:´ûª£I­x<þµÀ$´WÀ' ¢»€"šs 3]S¥E½Ïª[¢×›º<UÛ ÕQ”PgàA!…æ„‚•&†ÞFs3žŒeÓ*˜VvL"ž˜­àâFLu<îv`uNsjjó%ŠEcßaâÆ–¢b9"œ@QU[5/7šÉÒæUNxJÒ5Ad\à)ÎFLþ6Õ9ÆUG”°ˆðÌnlZ ¾/Ñ*Ïáœí^¯=§!¦Ñ$t ­¸üàÓœŠùõPùu(3czh6×lyR!-tœGšà1T55yõEÜËO †Ä¼ü Y’„ \ŽÊÏá¼í~ü«x<jHh-®@šÀ™Ìè‚{¨ˆ;T$eS› &HB-¥Ò&¨ _°@¹¥`÷pù[E8½ &P›rÑaÂ!h}¢ :ìð í^¯C‰‘‚ÅO„G- ­EuÈ!`Œ³…—,}Ô¼=ÊÌxª³Íµ»¡„ØEÉxÔ›qÃ+¹–C:oóºeÁ© ï…£hG;ßD%ÉÀñ…ηÅ/„ ´{½¡€•¢ŸÌéÆס–ˆÖâb”Ð;%|áÅKc‡23e“ïÏsòãpvIØ°£Ó{ÔÄüÃÄ”¿L ¼ÍN¸1š[B%@˜žßü(îÁ¾ ±Í¯Ã/øÚ½ZoLk86¾G- ¬ÅõÆ4ÕbáEKÑ[‡
+5uôB@1q5A!xÑ¢‰rø$7}äš7-‚èø›.ÙÀÙ¥7-¿àvh÷ú]Ž¤¨Ðñø{Ô‘ÐZ\uXÃÁ¼´É]@Í9™î˜›*ÛWYý¼iòcö•À1ýsr¸E7Õ9ÄvƒáJ‚ê(
+WK ãtàA+X’8Áš‹`ÍÀÄ
+
+¬iŸUìíàq~Õ² “Ùwxê/¡ !‰…Ƀâ4[Q]1¥áä‘:.¬>j^YÕ.é?÷¶ÒÙWåq³Ë÷檟¬ØNýz§ÐEéxÔŸa_!Çtȧ
+“Â
+…I>Šy2¹³L Šœt;Õ’[ak µ†#l×}—¢­…Ã/Ä ´;P£q·ScØZÀ kÑdxÔ‘КÕãF
+¾þ ü±l|fÒƦÆä(Lņ àLÌ&Oì‚^›8™g•VÔeä˜Ö ”äaâ`W†é:XZì&,¨O…ïëCú:U`1
+uŽ/è·Ïenxµ›gÚw'-œšnô5Í駃O›Ñ‘ü¿²pW‡ì5; ˆ"™]ß ÂÏéBµÒGEÖw‡2~üž!Öª¬ÎSÕqB1OïQó«ãC±0 ð6¥JàƸ:f<¢"Õ1EÐ7Ò§ÑêØá|íÎÔ)á‰kÞ½0½G-ѬÅO,N–ÄvE´æ@í=š|sY©C¥1$µÖÑ©=(œ{ 3®‘T˜ &›w
+ >O½U“ç~¸·eû¹ó{àT´›«¼˜¨•‘WèrV4Jß\!è3“Q^(c뼶ŸEöÙ bŒv‹Fûaäj/ŒÜ׎¥o àÎ,Ÿ"Û@äó"shXUM‹)Öp ´>·m”¹º¬Wcß™´âÀ“a†ZÙÎ$œ²õ;@±®³¶ýà.ê2¢×§ƒí`„uFÍ‚È Ñl×. 4`óÉ. ŽXgéöy`à ç­Ê>èÔÕNXÙ绬È37vÑŽØw(×]¾æc8Øžlò`Œ-¬ú4_Êì½ÙÎ ží 5n.*û — Íb“7ÀbÇ _ßï-ÌÊ—mÔOaÖ̧¬nìC V§OîiîHš¶f9‰¶gn;å‰m7¯Ý.•7ÝzØN»®Ý¼Dýxüéþƒ[Uî ˜)pÛUN¬A3þÕh•¹
+»>‰Òp¦µ'Éh pÍüŠŽÅõž%Ltèºð’g´%ÞTw>ÔðÀøš+¨"µ·—Ã=u% f•Ý™*{kÝÖs™¡
+wrõAH¤œæn²2ºjCÈ´ù3:\ø=ÇLÌ•š9(û÷µ$*™à¥h§ÅÖÙŸ©ÑymÇíê€a¿: xoÇR{ë6ƒöwóÒSÛÌÂÒÝÎùU[@îæ0¯”¬ž(ƒƒ-¡C=Ù/²×Ô„cæ‰rl²Éƒÿ±¿üGF—¿Àâ
+1óÇ9ÓíÔ…š&ª#eœPÁ5PÖ#¡©š þ4A‘endstream
+endobj
+1462 0 obj <<
+/Type /Page
+/Contents 1463 0 R
+/Resources 1461 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1423 0 R
+/Annots [ 1465 0 R 1466 0 R 1467 0 R 1468 0 R 1469 0 R 1470 0 R 1471 0 R 1472 0 R 1473 0 R 1474 0 R 1475 0 R 1476 0 R 1477 0 R 1478 0 R 1479 0 R 1480 0 R ]
+>> endobj
+1465 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [381.2254 737.5325 454.8788 749.5921]
+/Subtype /Link
+/A << /S /GoTo /D (tuning) >>
+>> endobj
+1466 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [362.4163 707.2832 436.0696 719.3428]
+/Subtype /Link
+/A << /S /GoTo /D (tuning) >>
+>> endobj
+1467 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [402.2465 677.0339 475.8998 689.0936]
+/Subtype /Link
+/A << /S /GoTo /D (tuning) >>
+>> endobj
+1468 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [348.0303 646.7846 421.6837 658.8443]
+/Subtype /Link
+/A << /S /GoTo /D (tuning) >>
+>> endobj
+1469 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [335.4973 616.5353 404.1693 628.595]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1470 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [363.1733 586.2861 431.8453 598.3457]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1471 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [365.365 556.0368 434.037 568.0964]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1472 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [393.041 525.7875 461.713 537.8471]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1473 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [402.9837 495.5382 471.6557 507.5979]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1474 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [320.374 465.2889 389.046 477.3486]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1475 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [348.05 435.0397 416.722 447.0993]
+/Subtype /Link
+/A << /S /GoTo /D (zone_transfers) >>
+>> endobj
+1476 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [488.512 404.7904 561.5676 416.85]
+/Subtype /Link
+/A << /S /GoTo /D (tuning) >>
+>> endobj
+1477 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [397.3443 374.5411 467.1586 386.6007]
+/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 [321.49 332.3366 382.69 344.3963]
+/Subtype /Link
+/A << /S /GoTo /D (options) >>
+>> endobj
+1479 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [317.0267 302.0873 385.6987 314.147]
+/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 [356.8967 271.8381 430.5501 283.8977]
+/Subtype /Link
+/A << /S /GoTo /D (tuning) >>
+>> endobj
+1464 0 obj <<
+/D [1462 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+474 0 obj <<
+/D [1462 0 R /XYZ 85.0394 256.8016 null]
+>> endobj
+1106 0 obj <<
+/D [1462 0 R /XYZ 85.0394 231.4888 null]
+>> endobj
+1461 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1483 0 obj <<
+/Length 3014
+/Filter /FlateDecode
+>>
+stream
+xÚÍZ[sÛº~÷¯Ðœ'¹c!¸ìS}'õ¹8©ãN§““Z¢-6©ˆTœÌôÇw R LYJÎt<c€Àb±X|Xì.$FþÄÈXfS™Ž’T3Ã…M—'|t}oND ™´D“˜ê盓¯U2JYj¥ÝÜE¼ãΉÑÍìÃØ2ÉN¿|{õúòÍ߯ÏO=¾¹|{u:‘†__þvAµ7×ç¿ÿ~~}:ΈñË¿ž¿»¹¸¦.xü|yõŠZR*ö0½¾x}q}qõòâôãÍ/'7ÝZâõ
+®p!ŸO>|ä£,û—ÎTêÌè>8i*GËm3Z©¶eqòþäoè×ÔŸàL*+(ÕMʬ‚.Tàͼ¨iQm9¯¨’Q±>uãÍ"§Yþç²,š¢*©eQUŸê?£"^¼Ö"šŽ&2eÎ9?ÏÜðÓ‰å||¿Îʆªÿ¦b–—ߨT‚j46EÚËl™7ßVùö‹j¨À®šªI’ÞÂ[I’Ô‹r‘Mç »µÑÒàÃËUS½Zc™ dEÚVëâK±ÈïóТŒ¿-§ahFÅ2¯ëì>§¡ó,Œ«7Ó)tÜm‹o.k¦ó|ÖD9ƒ¯4œ«U¾Î‚²)ì,$K‘~AÅr™ÏŠ¬Éý.¥¥ø œ£µ@£_ËŒêY*eEåÝf s®iD¥´ëSáÆ9}ä_³eQæ3P–v|N­[=‡ÇpÙ®æyI5ZTê⾄{ë¡CM#‘N½v"°a˜/fgÔ×4 bÒõ']¿kPsQRc6V~¹³Œ6úŠf>À…àq
+¢ jöˆÆÂ*Õ¶Þïmõ*Ÿžû,Ñr€˜jAÖÍ°TÉÄÏ}U!`E«q¨K¿KØF›ûySPeF½w՚Α‰Ï‘†9e€½_Ñt5©óÅÝÀ3‚))’@8ÌK2—˜–Ä6•ÞË,a2MU ë”¡EÒÊ[7 vê,^PÖd™­VEyO½/¨Xêî«WÜDª„)¢÷6oZ•È©³yËMÝD{¸³)P÷nŒ Æw
+¬6@c§´ðx”×èÀ[ýzDÙ xLŠ4jœ-êŠZ‘ã2¿¯š¢½Èð4æͼšQ¤ÂÚí7*ß¼?A|Ñçü C&Ç€€ìvQÔÁnJ0·aòèÐ)Ò[ÖÐÇî¥)¶[%R3þ5_ßæ^ûUM-pÓ—Ób•-èõ‰e7bº(`2Žûë}NÍY¼ Û9—€×Å]0_?Áb×™W
+ö·D°äxážr‰½ahq‚„^`e”IÔ1>qoØnBp°Wðfåêá>"¡´c OvÿݨVŒ¼ÃØ+ãÀ+T[ëÐg5é³,‘JviŽ¾!JÑ.{&™„Kô ;”p–"RãÅ×lÚL‚G¯gj™¡o„¿u<äJ°§»|ð£‹ãðƒ]•èàHAS;ùîUs›ûxM;9»³~"†®™)º!>¾¨vâ ¼FrJYòúÚîÇ·€„‰¥Õî€]¶LwWE¸ÄàÒi‘‚‚£mxÞÖ"ˆw®E‹ú¡h1j
+™@‹ŒN^8}Ì´é3§ÉDÚ‹6÷ÑÆ«X qÔ:ˆbܲͨðM†P´õª»³PYïÐÙ3$œc\KóCmÍB2ÌYc¾ƒe;b?‚„e©Nôið•µV‡üŒ]
+JÁÒ5sȹáÛ?œzÏ« ^ƒ©*([;é<XC©»/ 4gÆ8s”b4j~W1Öè­búŽ. w!ð<M$¸óBŠï›/«6nƲªjÙÔ9Ä¿}ƒWßbQ=4­¨ÊÀ)$¶äxµû°œ&ÛçT€%X7-<–Û· O3b Ô”<Œ»ÂN8ñŽ‰¬T¸ë•õY©Šª·¡i³‚6R0Æí¾ ^HÆ]—Ez:v:D»„)?!f?©ÚVPQâ*ÞïÔ2Ç-n$K´"7úOƒ[nRÆÖh¡èX¶ï}Y›â¨›|]ÔŸèu¯ÿÑ:»Ó¬Î÷æØâ=ÏŠþO]MÅ1‚ã\M°Ì¥Øöd`ÐÑ´½÷ØðØf1¾,ÙšìûiXªœ<½
+‡êÿ^sA'fÚ'd’9—m ôR¢-ø?J¤,hn Â÷Ô…—ú'2<CPQ<vËxp¥ ì ‚ÃPOß}*)¬u*ž§‡
+Öªrñ-LÆ÷ f"àd¤‰Q}+þV»P£ƒÌÑ@‰wàGœ&¹ùžaÈчЖaFõI¤È$a<‘‡²P} œã‹NYûÚæ=46›çÙ—œj·9ù}SäeèýRdT¹yùŽ*þwH„Ⱦ%¼Ý`uã×»•JmŸjñ㎞f–ôE=xoþ%k:²ËwTf³ÝéuM Eé'Û±@{5IŸ¿zuÍίߦÒÿ° Pâ‹Ëw6î
+O£õ*›¶õC/Ám˜ÏÃ9Ûu U8À¸à€<ð8±æ˜<ž”þÍFìÍÈ%–Y<9ǃ”F<ŽHZñ&üI0ã:þáQ§ZLl¢ûâÒ‘šIßW@ýÓß¼5=oÁ!ãø/Ç~k%RðLÒ‘
+endobj
+1482 0 obj <<
+/Type /Page
+/Contents 1483 0 R
+/Resources 1481 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1423 0 R
+>> endobj
+1484 0 obj <<
+/D [1482 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1485 0 obj <<
+/D [1482 0 R /XYZ 56.6929 512.9872 null]
+>> endobj
+1486 0 obj <<
+/D [1482 0 R /XYZ 56.6929 501.0321 null]
+>> endobj
+1481 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F41 925 0 R /F53 1017 0 R /F48 940 0 R /F62 1050 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1489 0 obj <<
+/Length 2789
+/Filter /FlateDecode
+>>
+stream
+xÚÍZYsÛ8~÷¯à#U!8ûæq쌧f•¬¬©­ã!‹5©ˆ”ϯßn4@Q‡íÉ$S»•*l4€Fãë Š8üAªWY$YÄ4:X¬/xpcï/„ã{¦ñë»ÙÅÛ•Ëb³å`­”ñ4Á¬ø%¼úþòãìz:KÍØÆ:æáw·“wDɨ¹ú0¹¹}ÿÓôr”DáìöÄÈÓë›ëéõäêz4*ÒPn‰Ÿ?L®‰éæöÇëÑo³.®g½ÈÃc ®PÞO¿üƃN÷Ãg*Kuðœ‰,“Áú"ÒŠéH)O©.î.þÕ/8µSÏ©)â‚ ©U0±f åóûÒöu]¡2&¹ÖGû¹é”Ë”%™V½ò#1P¾ˆK•ÒA¢3+©¬ö㮉ƭ©–¨ ·7@ÝÏH8ˤB!󲪚Çœ! »•¡ΦÞf;ih~å\~vL ¶i8w¼»M‘w®?¢6¯]gvõ‘:‹¦6‹®lj”v Á2­¥ai7iÖ£±ŠR’BE^
+$Õ¦{l¶¿¹Ùñ™Y‹fK2·›¦.ÊúžÆo?>DÄãsBnV 8SZ„³UÙÎâ(¤V…eÝ™º0QQØæ¤?d˜Ü %ÄöÝäòŸ×44¶¦kg‚ä »É Ú
+
+ÊLRaæÀ º6²TÁ½®)*`[7ŽÐ–÷µ½LHŽdAl™Œ)ŽØIÏ}}Üšíƒåv-¯C
+zª-ÖlöÚ¢^ÃÕ€ÖxùÁ,¶çΉê´ù9é«u$8 Ò÷àé0Š&Qh“˜$l›­ ƒ™ë]Õ•›ÊM·º’N'HؘíºìÈbá“"
+·éÊuù‡CåÜmñ
+[·YÏi>çh÷gc¿÷ûùŸ‹æûLp›ö™|;w̤NêÏûB¸ô/qÛvŒnãΘãúFEÇ" —à¢3fÜÞ»
+o:Ì°=ÿx8á4Å>]Ï{çÞ=Ü;²@‰xRs Y<”¯Ã-Nš<×+’@ÁÏÀM‹CI\Ð9,õ4ŒsýgUÑó¿&ÀɺϪ":– ªa¦°ÄxQ=×+’œ®†’¸
+Š\&3ÈpJˆ™MÖCÕàå|˜ïx7Ù–A^æÂØ?ŽØ¿íI(õt’Æÿ«Rsàe¾ ~v3ž}°”:a±TÏÜHÿ`)cÁ$9…æ±öMn
+‰dÇ õÑWîÓ„>£˜ºGç²õ)õ®.N_9 "NbH“‡Ò~öR±ìÅçç“%ýŒç•Š1hÓ¯(5ʘÔQF¾’ôÑ8Žb^¢ú²84õ¢¡ÆL‡"ÏËŽòjg¨ë¼10ìkÊÖy»4òX«Ñ¥Ð#kªÈó³c³9,i^¸©
+¾N­û›Šð¨üKž¸üŒgoJ€¼i&_…¿ÔP§Eô¢9›ý¥3î@Ÿ€>˵C´á¸*Ñ*;ñÊN4€ŽWiÿàdOÌéSIwã@Â÷ì{kvÈW?_»º´.PQŽŠm ×U6ðG¾¼réØ6ÛroKû¸Ÿ»Ö8†¹£$AD²åι„aepR ÅdÓ†º”BÄuúÂÇ^T!v%~®èyž‡Uc¡Ø樴ˆ_·¦ÎülŽi·-|¾±l†N§ô¯Y«fW‡9IQ¶‹Üå§/ z—¯ƒàßê ³aY*_ó?"I˜–î½aQA
+pè*Må3u¥¿/(ª`-òfIvR7¬u*÷láÿ êê]endstream
+endobj
+1488 0 obj <<
+/Type /Page
+/Contents 1489 0 R
+/Resources 1487 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1499 0 R
+/Annots [ 1493 0 R 1494 0 R ]
+>> endobj
+1493 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [341.1654 298.8688 414.8187 310.9284]
+/Subtype /Link
+/A << /S /GoTo /D (the_sortlist_statement) >>
+>> endobj
+1494 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [434.6742 298.8688 508.3275 310.9284]
+/Subtype /Link
+/A << /S /GoTo /D (rrset_ordering) >>
+>> endobj
+1490 0 obj <<
+/D [1488 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+478 0 obj <<
+/D [1488 0 R /XYZ 85.0394 509.1791 null]
+>> endobj
+1491 0 obj <<
+/D [1488 0 R /XYZ 85.0394 477.0735 null]
+>> endobj
+482 0 obj <<
+/D [1488 0 R /XYZ 85.0394 477.0735 null]
+>> endobj
+954 0 obj <<
+/D [1488 0 R /XYZ 85.0394 447.2177 null]
+>> endobj
+486 0 obj <<
+/D [1488 0 R /XYZ 85.0394 390.5598 null]
+>> endobj
+1492 0 obj <<
+/D [1488 0 R /XYZ 85.0394 368.2486 null]
+>> endobj
+1495 0 obj <<
+/D [1488 0 R /XYZ 85.0394 281.9323 null]
+>> endobj
+1496 0 obj <<
+/D [1488 0 R /XYZ 85.0394 269.9771 null]
+>> endobj
+1497 0 obj <<
+/D [1488 0 R /XYZ 85.0394 89.8526 null]
+>> endobj
+1498 0 obj <<
+/D [1488 0 R /XYZ 85.0394 77.8974 null]
+>> endobj
+1487 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R /F62 1050 0 R /F53 1017 0 R /F21 702 0 R /F39 885 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1502 0 obj <<
+/Length 2893
+/Filter /FlateDecode
+>>
+stream
+xÚí[]oÛ:}ϯð£4\~‹Â>¥iÒúÞÖÉÚ)°»÷ÞÙV¡Žåµä¤Ù_¿3Ê–]ÛJÈö@9Q4uf8s8TE‡Ã_Ñ1–ÙD&8ÑÌpa:£û#Þ¹…{ŸDèsRw:iöúx}ô· w–Xi;×7±ãΉÎõøÈ2ÅŽaýû²w~|" .º_AJ}9½º>ïÓ º~ìö>‘&¡æì²wÑýü½zëèº{Ù#uÿüâ¼Þ;;?þëú·£óëå”›¯%¸Âùþçè¿xg o÷Ûg*q¦óœ‰$‘û#m3Z©Z39ýc9`ã®tLš &¤Q¥™ƒßÎÏ*íXÌã?Ë;'R±Dp½{,zŽÃXA¤'ÔÆP'‚'LÀ?`FeX,E²4£T 3
+a˜vq'6‚I F3žŸØX[l•TÑ]QV$¥ãñüX¸(+K4žL¢î”îTw ݵ£IZ–@Önæ%i©ÕQJ—Jž ó0v÷jËo€¥;±f‰1ÞI€Sü”•£y>ÌÆäù4øÈÅ
+W_!ó%¢ÓõuÍ×ÜŸ4“¼¬BÄÝ„}„E´3+!÷¡Ü˜þ¡âpÝá(k‘Û”µbÖÆäng@U]ƒ»'@¿“q
+#d9kÓ!XˆñЋ
+d1ï½}FB›wKHG{¼»á6¯sÅ7MFrf¤k‰LFYÆc"Soðûù¿ÀÜ*áÑ *ÍAúx‹A3[ 'ùˆäÙSHΈƒ7‚g¯ž*óÛi 7ü
+)ÿ[LWñæd·«·„"®öl š(6ÔXÀv˜®…*!™°<„¢nY¥Y3”H‰‰îÒòŽ$\ئԣ¶!ª¼ ý½µ¬¡ƒ —O™¥ QFn±…„5»¾ÆxMT»›8(ÏÕNƒUz¿ñ´s=@Ÿ¯.Áxð˜ˤPn®ÛI1¬‰î¬(sÜöT‹Yéf¤¡FvVâ×˳=x6&úŽ©­¶œÅ°ÓjÁ3¶L&ÚyD¿t{—
+ÂÙÕw¨Ò‹
+"`(y$áNJ—XÅ´‘¬(àŽwfèø
+’Û|ÓwLr5$ §eÜbØ•Â^€\¼{58?óÉDÆJGW>B@j˵PtŸUwE*úB¤ˆh¯‘Êl«–ê{ˆTs_kÃ+´EˆK¯(k.÷«Â{N%$%Û¢‘tLÇšpé>õŽO 71’ÚL°bA¥&#©>h°ZO]åZ0Ãm @<7ª^÷ŠÜ¾¿ØÔ|ÓCä ÊÑ*Ž·¶…ˆi®™±ŠÂ™_8
+Iã#(u£@ƒ7æxD$•‹†‹jÛ®¢¬òIÈ}!2ƒX%Hƒîg,Gs,6·2rYõ1kevP%jÏ.¶i·ÃV”ºÞ•QLÛB•uÌ&Ž¨ãïÿê(”ØL•°þ}™ÍÕÌ ûs{¶[¿3¡:B]5pΛxY>Pëå è²Ï³V›.©øc4ÞòSA¥“\´_;ÈØÑR ˆKtá±…€¹LR&À¤Í§7…?)QkðBïëÒ(A!\lC×õ€¼ÝÆ´ßñÁžâ†A¤j‰¤JIæ”$x¿«›Düâê˜À°Q@$ò Iµ¯Ó¹z}Ä,K  ±HªzaéHåBoöä½p&7õU'¢‡t²"F¶Iñ藜㾪‡êaVã Çkp}SL°×8Ü}¢–& Ñá=ªBU$Hâ[bírÇ
+endobj
+1501 0 obj <<
+/Type /Page
+/Contents 1502 0 R
+/Resources 1500 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1499 0 R
+>> endobj
+1503 0 obj <<
+/D [1501 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1500 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1506 0 obj <<
+/Length 3252
+/Filter /FlateDecode
+>>
+stream
+xÚÍÙrÛFò]_Á·€U"‚9€lžYŠ•8²–b6®Mò
+o­B+$}¤CÎ×”ç¢Cy&E¨…ˆ{
+ÖIô!é¯?Œ€V’‰à·ÆäýÔiPVøÔÁ›ëÛÛ‹sµ5=3Y.úLfúäGçå$kWd-AÃaCÀcÙeò §d˜Æ1žœ!ÀíAêÇÊ,`gA•Íp5Îé$€Éè11‹6#_b0ª5‹‡lJø¼v«Ô-æSÙ´Ûëá9¢Í|®+XPÄ œ3'`ýnØz´ï†ÐpHÏöinUU?§Fc*7á®^ø¥éi5Ø<)CY̦݃Ҿ ²”Üñ‘ø<A½(ïË
+߱ĩ¨A{ϧÙÄO?ÑóÚ²Ó-³ƒ´Ì¸l`[Á¢ài&‹rl—%²{£Æ]ž
+&Õ¥IÒ4Ôq"-nFC40" ΀PRóÚÊ 5PUð™9Ï-AõVòzf…aj„š9ðí0ûìR’—Ã,‚w?À¢îËA·y$_”GIÊHŠc<Rq˜Ê„Èró¡?H@@ƒ«õC™£ªr­‚Y6Ÿƒ–¹ÖØ´ÆTÔ º 9'ÀÚ>À"‡Ës§àiÂý6í¨þ°D`Nç­_–9/«@" e*ñ&æàmA·‘.ÃË\U`gY[ÖHÅÿœ›ESW 5­ç€(ÇSCHkQ¹¤Gˆ!=BÓ¥Tpñ –Àyƒýì)g`Ÿ³é3cú³ÖTxͼb<Œµ8jì¸Æ …ŒÝpx{õ¸!°wÁy]¡¶Ž­Ý6yД÷UÖ.½DTžµ—EQÜ¥/vQÁ-}÷rHFB yçm^Šè`-uÿ§ågì%z¬’P1Í=’!gΨûB#Ô "X/[3h 2dË{ˆ¦¸ˆƒ1F'6X.À@ ¨›¶!b1„0&§‰ì¨ìÁøA¦tS!ÛÏŠ¼$ÆN0”Õå† ù`Œ&£ sZ/>º®MC9Ð^3ת§•^ù·èoy¶ƒúØ%ú×1òÛʆŒ ¬àÇ2Nà 2M,Y¬:Æ:M;ê¨x´
+×ÞÒEDy]D˜âI„¬
+"âU<¹ß™ùS°x+Æ„ÂƘØãÌ¢lP¨•8…¶`ÁxÙÒ€¦-§S³Äí’k`7¬úgGü±£»Yǧ‘GT*Ø©é°ã¥¤æÄC1K ÐáÇâ¡XðPjI„¼}†‰Ø«t¯ü3Š¸ ˆ[»Ð¦µaªõÄwôÌh%G˶
+“DPLt;ìÇqð/L¹ÅŠòƒqmM\¢ƒGc-@+ô¯\ùHl4fñPNlZhã:Ƶٯ6¿ÿrël!râhª¡4?À© ^q(e !;f÷$$N*Îîݾ½¼ÁÐbÍíT0¶ÖM'ÁcöDmÌݱYæžùr<-›‚º3­G¹Y…å6v}4Oß5„EK[HCîÍb¾(«ö¹:Çãæ²K¢—â¤?ìó—ô3ösRˆÇªá$dUZr²—#[ªL €õS˜O-ÄÅ¥µ}æÏ­]ö:Ýó}Ý;[Û¥BV}„Œ\†Z«ÄÛ #fÎv+æ±·[>å¤@0q& ‘΄!¸2a8›°ÓýBÞ,q9Š¹àìö×ÑMŸñ48¥¶ËVpD×Ü,çózÑzæ¾-›b f{YØ¡Í+v?Î QÙ±¢½Œ¢0UŠˆùÇ9Ä*šN©Ù{ -¨ÈÏ!Ehís ±—©(ÝÊËöF _W&é¾íK1e}Ûrìúç¨Hm]ßü³üA¸N¡€i膑ڼöùâúGD`Ðxª0™T@T½‡ïþnJ@BñØ@¦ïêé´~ÄÜèüý¥H;3 §Ô¶Ã)“i†,¦q;ð4äBãlP¿²¥MMnmbvZX§¥+Ï ðƒÔ¬Zë0õMË-!iý @FømY©„@k•J¾-G£oâñãa©cz.˜­#’®]]÷ Þ­8…×  Ê4¬³ÏKy®oPøà
+´EË—D$ÃXèÔÝãmX¯ó"« Âé:C… ûÝ^CM±nëI=%ÌÄU¨Zkµ0@o©ã׫!¬„‚$€Y™Xª¢CåýaÖ ™ @¾8 ¨ÒÖâ
+Î õÅBñÁ¨‚¥ e9YGŒûAw õáÆuÞµ¦r¨Ù|ZNÊÖVsu°ÈÜ-7·1¼„Re/'°á‘Èàûš@l¹+q»¸ŸîvC.k·²ù”Á¶Æí9˪§]0йQɺ,ß
+V•M)——öpµ¤ †ÆYc Ø"£D2| ƒåÄ—Ò›Õn~á¦vvÆ‹ûSúJÃ]Ë`RP*£cú.qðÖ°ä5ª:·‘¸dÒrdÇËÑ 0'¢[Éìw(\rKʆPë°LúÂ.
+Š<½Ãsù N/ÝN¼mZû ¶‰(0 ³E{<¿BÚ/ypš– ïrwX’ Ôy<Üð }ï…gî<Ù"¾ZÛl˜•1>Nõ¡íªowŒ;6DU4d>Å WÇÓƒ¸ H_à43“'°ðmEXù¯:
+u¸ÁË4{8÷)>Wkd9Ø9P0ƒÖV¥Î:àÔz,ÌÊý®—žn€r7q-%æ +¿åt§Ah€ø¨šá©‚¬H 06ôtÁ¤f®¸É<ð¬ülü„ Òφ.©·X¤¨ðøLÇ­WÛàbì¢S„ûÅ:Î02Ç)ÈÛÒ¸‘V#áé“™]ï67 ˜T¨4Ëû{ӸȄ´Ÿ Ó¸(B\ÔË© |Æ®›î \:K¾‹;'„ß,<¹UˆÝ)`))„ÇÞ´‡T
+endobj
+1505 0 obj <<
+/Type /Page
+/Contents 1506 0 R
+/Resources 1504 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1499 0 R
+>> endobj
+1507 0 obj <<
+/D [1505 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1508 0 obj <<
+/D [1505 0 R /XYZ 85.0394 337.2163 null]
+>> endobj
+1509 0 obj <<
+/D [1505 0 R /XYZ 85.0394 325.2611 null]
+>> endobj
+1504 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F39 885 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1512 0 obj <<
+/Length 2929
+/Filter /FlateDecode
+>>
+stream
+xÚÍ]sã6î=¿ÂÎL¢?ôÁ{Ûf“6^Ú˦7;×íƒlѱneɵädýï @™väì^»w×ÉL’ 
+Ÿ%àâS±Z×ΡÅBxªÊãEïo®h&¸}q¸72‘…&ë]m¬VU ²s ´J÷]=B‚íûpü®Š®·Œÿ!Ž¥ã ϘmwÇóHN¥=XJL»eûìe–æ-¨¨é™Z~Á
+4WlzÉ÷)o&Ê­Œœ>VOd-Á(l“ìodæý}DÀ-DÇSTÓ™}¬&ù\õË
+2…Ç-ªæ ?Æ'ÙuËŒxÚ†Ò^¸îEâš{{FYuÿÂdUŽ›Ãâ­w+Û/B»F€v,†­„dˆÔêçbÇ00Ö£PbÍÎðnïB®Oî Ì—ÔÀSQo?wÚUÕ÷à  è³ò)Å™Æò—õPë»Ã“
+<nNœ,tyzˆ’[̹קžš£©~™qê0ãÔìõ¼¸qÂ=}÷û†ºNžà}4€›ö¹¶å£=A
+4WÍ]ž50äÆ#Õ‘Äp[£â¸ñ¨,ò j=ó¼$-ì )¢P¥Ð—„Éu .Î:!ÉíŠÇÁÅþõøžIE$\+’8ƒ;“”_rSQi¥©Lo*¿o–g$âIh^ ´ô3I]›ºÔ&‰Û_ƒt˜i‹ØÀ%É艆ûb&Têtrûî6º~û3ÃTåñôoïÏ/3•IH¿ Rð\ß]ß¿‰´#êT¿™šKÿ±Ý ÜÀÿ;òÉÊD>. )ã(7)ì%O£,ÉéÒðR"oÞò8-Ž`¥¯*ñUå‘Á]K¤Ÿ5˜LGy¬èâ|h˜«ƒÙ€¯Ê ÊH摉€%yZ2ÁšbKI Ð*
+',%•Q®ùî:$¯È  þ'–Î"§êsÖ‘ 0¤!ë$y¡m
+€ïßG?\½‹þvûÀ)¥4Ýè0o‚C–‚_Ã8€Z¿tpàM Öþ£.Ð|åð¸„XgêTБ°2Ä3œ@Ññê»Pbº—öJ-ãÓ2 –ûJ2ùOÂÂ×·Z‘H0,(eF˜/ ¨æIj^ pf£X˜”QÕ½î~ø4»w”ô´px2 ù
+¥¦.BçÁK´9ÅÀ‘Ö) ð
+7¯à”©¸þ’=Fò\Òg½©ZWJ¥Î¦ô£c¥{o0:ãÜÙEOâúZ: ÷ÙÑxïÃ×<hÍtHü¡ËížÀ@<ˆÛnуº×½-Ѧ3áÍ4\/pÈFŒÖß°ÜŽÜp5<¥',e8,Á0ïÉ9Cl5ùÜ×Þ ½.‘¯ÐìÃòý£- T<}>\R>Ý€´ÛUí«ØÁú9x&ì}¸[»ç/}ïfö’sFÇùàÃ×mSòCÆðTžë) ñz`°Ük!4‹GŠ„9žÜšqApÇ*æy^Ë_O²±Ÿ˜FMŒ<:LJCÓ¼-âéOƒ áÒSGèe;f“äŽÁ©Ñ=SJF¼£®bÖµõ¶·ÔZÙ¢¡’<à|2£nàÔ£‚’æدI|à­Ñ /­~Q·qÄâŸd
+endobj
+1511 0 obj <<
+/Type /Page
+/Contents 1512 0 R
+/Resources 1510 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1499 0 R
+>> endobj
+1513 0 obj <<
+/D [1511 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+490 0 obj <<
+/D [1511 0 R /XYZ 56.6929 729.6823 null]
+>> endobj
+1514 0 obj <<
+/D [1511 0 R /XYZ 56.6929 704.98 null]
+>> endobj
+1515 0 obj <<
+/D [1511 0 R /XYZ 56.6929 519.4358 null]
+>> endobj
+1516 0 obj <<
+/D [1511 0 R /XYZ 56.6929 507.4807 null]
+>> endobj
+1517 0 obj <<
+/D [1511 0 R /XYZ 56.6929 339.3113 null]
+>> endobj
+1518 0 obj <<
+/D [1511 0 R /XYZ 56.6929 327.3562 null]
+>> endobj
+494 0 obj <<
+/D [1511 0 R /XYZ 56.6929 227.5589 null]
+>> endobj
+1519 0 obj <<
+/D [1511 0 R /XYZ 56.6929 200.4217 null]
+>> endobj
+1510 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1522 0 obj <<
+/Length 2732
+/Filter /FlateDecode
+>>
+stream
+xÚÍZKsÛ8¾ûWè0ºj„Å“çæÉ8YOMœ¬¢­Jm&Z¢-ÖJ¤V¤âdýv£%Kv²Ijb
+åMÓ-°–Åqâ ú`‹8[ÝW¨|ùö3OÎû4×p)YRñˆå&´cÈ„i£Â)‘u“òè\åÁ²º«›êX'WuÛ•®ÈHÉ+ò9k vy8Èž •»Q ´åY¨¾.gWä[Á^ç*‰‚ò#Š´uSÕÝ`ª½­’BÞ|"å D :Pl ÀR~,VëeùË¡{Ê3!5Œ›fZdÆëÏòO:.SÙ¾úÿzÅu ¶xrÔOÂX\=ö‡Ç=ÓTŠÌ›Þ÷Y5pàŒ…•ÊŒÒÔ
+“‚[@±œÄ¬Y¡¿1Ö&WŒ– ¹àû“·ü¡äù8“ì¿Ä^·;Âr½ –óuDQªÌèï"3ëD\h‹1*¥N «¬ Bc åA±C…¥c‚tôgŠ‡fÎpù˜Tø Ìë ùX)¬ËÍ ùè¡|ÄM1û÷v-šÍÝ#ÒÌûKBl®2÷”ÉiÀ'Ò’ç~h@c³gwGJ%ð_–Ñ`öXFJ£DžtK*œçó^FfÁð!éÓBLÿ­„´ƒ¢Eì
+Ì0Œ’ñPerÛ,—Í}¯Ý‚æàÖîÓºl÷í¶‡ºØ¯>f[Ê€àÔ–lAØ”-Ö܃Šÿ6u“O©ÁØC€R ~.³#ëRa³ÏÂú&7"“™ù2}¼×
+`5pîZ©G«¹f9Àïqª…vizìw/r½ÕWÿÊf÷K#› ã½>Ž{ ÇÂÃöæÁ)ÆŸã0×`éÿ3RºNendstream
+endobj
+1521 0 obj <<
+/Type /Page
+/Contents 1522 0 R
+/Resources 1520 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1499 0 R
+>> endobj
+1523 0 obj <<
+/D [1521 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1524 0 obj <<
+/D [1521 0 R /XYZ 85.0394 685.0919 null]
+>> endobj
+1525 0 obj <<
+/D [1521 0 R /XYZ 85.0394 673.1367 null]
+>> endobj
+498 0 obj <<
+/D [1521 0 R /XYZ 85.0394 537.6026 null]
+>> endobj
+1526 0 obj <<
+/D [1521 0 R /XYZ 85.0394 510.2982 null]
+>> endobj
+1527 0 obj <<
+/D [1521 0 R /XYZ 85.0394 468.8256 null]
+>> endobj
+1528 0 obj <<
+/D [1521 0 R /XYZ 85.0394 456.8705 null]
+>> endobj
+502 0 obj <<
+/D [1521 0 R /XYZ 85.0394 288.1559 null]
+>> endobj
+1529 0 obj <<
+/D [1521 0 R /XYZ 85.0394 258.1665 null]
+>> endobj
+1530 0 obj <<
+/D [1521 0 R /XYZ 85.0394 168.8733 null]
+>> endobj
+1531 0 obj <<
+/D [1521 0 R /XYZ 85.0394 156.9181 null]
+>> endobj
+1520 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F39 885 0 R /F41 925 0 R /F21 702 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1534 0 obj <<
+/Length 2208
+/Filter /FlateDecode
+>>
+stream
+xÚ½ÛnÛ8ö=_¡‡}šÃ»¨ÁbLêt=Èe6õLÓéƒb3µ
+7t@ýi~ñWrüœ\^œÎßüzu<Édº˜_^àòÕìtv5»8™M>,~>š-:–ûb1*¿ŸŽÞ É
+¤ûùˆ‘•ÜÔ°<çÉöH*A”"®lŽÞý«#ØÛõGÇÔÔá
+õéPgâvSnLz^€ªwR&OOëÝÖ[V*Û²Ø8_q®ì”òÊÛÉïâÑ«Ó\€„¯*ª€³FRyÚì¯ûio«6R»¶¶BÈ~nmµ²+ç³à#ïÖŽ«ŸDo¹;ÚèD
+Žu0=àê™fcÙtà#.›rh+ïÕ)ð_ÃD$4¿89ûõõl„’‚ Êøê«Zä’a²Hs±8CEL¹†Â–S !IfT/ ±ˆºŒB áå8xû¥j‹Ï?Žð%QL«1¥©Ò2"çoUo‹²šVδ/׆p)£!ÞP@,‹—.ëíÖù䈥 Ì‚¼#ìOY® ® B’/äà2Ú¡±­÷+Ý•ÑÌÓ*¸.‹™ û£†ç¾N¹H˜5~‹ê ûêTªÒeÄá㸪$ Øpo'ÿ Ù…hf©#²kZôœ(Ê ú"éÂ]Ä$Æ0|}FuaÙ‘ƒ‹°]Bù*—e;U JNfò1aƒ˜ÑÀDô¿#‚ì#d$“Æ'ZÏ}” ±…¦>’úÇSRd,0‰TyôŒs¹ß¡ª1I!˜MvˆÐ§=¨/(jRö}À©»îÔŽŠNåÍ&p!7HóÍ­]ö|ä~ÛõX²ƒŽ€e¹~™ÙAØ^üûmWÊX.ÚaÙð­™Ïf×M½Ù·–ŒXÐDæP§Ðë
+2õ¹™jH]{#ANÆÊÛ»wïÀû]’;¹8>wƒšøüx~1};»ú fµÑäÖ¿/ò •¶¼+6l`…Ç<?8 דٿÏ9›‘“Ës‚LVô“!âc›
+à‹ ¼Þ¹¶u„pŠV]þö2‘oæ*û_ê(I¸iÎeýŽâ
+s ˆm™È`æqÞ_»Qw0<pq·±#ÞÂÀU•”æ«TÆL—=Špƒ/¸Ú‡ü}HÃn{™À^Yù´1—ß.Ú¸Yâ·5qµƒêt~3Ös0A¨áâE3QP Èû) È÷3ÖêÆÐ<{¢?í˜í¥‘žÊc^»/Ûõh+Š.S}mFƒÞ{H—±†T°·¡'«]¼/û 7}¾"° ¬ŸÉÿ–§(¼›2C“'² ºj†>ŠIAšh£»Êè20éwºàТ
+¤Ÿ e–‡ ZÚK9 na4#dÇEƒ·Ú{5Á…f]ï7+Ätý¹[ÛÙ¦­w6¬7~ÒtE5ò&''Z‚ÊìÛÂÆÀY{¾?†9(¡ü0J©Òk÷,µw¼Kík‚[téÂ}›[×âܯ->†¸ET
+ÄdÿyA<jN‹³¿îmÁÜúïFv³ÚÊÞûM;mÛÍÿùaa¬’€
+endobj
+1533 0 obj <<
+/Type /Page
+/Contents 1534 0 R
+/Resources 1532 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1499 0 R
+>> endobj
+1535 0 obj <<
+/D [1533 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+506 0 obj <<
+/D [1533 0 R /XYZ 56.6929 663.594 null]
+>> endobj
+1536 0 obj <<
+/D [1533 0 R /XYZ 56.6929 640.0743 null]
+>> endobj
+510 0 obj <<
+/D [1533 0 R /XYZ 56.6929 573.5829 null]
+>> endobj
+1537 0 obj <<
+/D [1533 0 R /XYZ 56.6929 548.3076 null]
+>> endobj
+514 0 obj <<
+/D [1533 0 R /XYZ 56.6929 357.2459 null]
+>> endobj
+1538 0 obj <<
+/D [1533 0 R /XYZ 56.6929 330.4365 null]
+>> endobj
+518 0 obj <<
+/D [1533 0 R /XYZ 56.6929 105.6253 null]
+>> endobj
+1539 0 obj <<
+/D [1533 0 R /XYZ 56.6929 82.6167 null]
+>> endobj
+1532 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F62 1050 0 R /F63 1053 0 R /F21 702 0 R /F53 1017 0 R /F11 1367 0 R /F41 925 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1542 0 obj <<
+/Length 3049
+/Filter /FlateDecode
+>>
+stream
+xÚÝÉrÛ8öî¯Ð!¹ÊBc!¸ôÍí(O¥Œ­éêšt”HÛ¬¡HµHÅI¾~ÞøHìžt×T}
+¦‹ë÷74|;3¿ß\ÍÏgBZ
+ïûûÙÇO|’v?ãL%±ž<ÁÎD’ÈÉú,Њé@)7RžÝý£8˜5[}dÒ*f:–‘‡NRùè¤*˜B:Ýå- “ðiû˜S'ËïÓ]iGçZO‹uî~%rZSÿ]ñÙŽþÆ5_,ÞA#hà¾ÞR§Ù-›ü÷]^YhÛsOóUmÚ¬¡Á§¢}¤Þ®Êòß8—UžÙóï { øô<:-‹Á öÄ4% 4\ß÷È
+-­lêé¬rph&úcÚÚÍUù•zYqKîèÃï{³£^˜<]=Ú ùvÉÒnM+j Л´…£ÀøTæ°’gIæ?Ž+<L…át™cYšáÒ Û<m
+ûy…w²kÒâp“· õz8u@'œ¤ÁßwuFçD`‘7›zÛZˆ»%u~Ápóç|Ûýœ9DFØgy™?¤-–ÎÆ5«m±<aãDdmÐêR™7vçõÍìòõë[vyû‰yéà¹,K¯5¶bûþöúí5xîL"gèF%À½d>W`9ˆæ÷‰™´
+Hž$8h@Z÷BöÉ•/J(3æG@F/EÁ®<rÞ0R<ªŽ0û!ãàj^*ªD±ˆG{¡â·Ë݃›ð"µ>~ÚÇ–íºcP³'ŒØ`%¢C‘R0¥Àó:baƒ
+­À W‡Ó˲¤Škº¤…hQ
+£ Œ/ª‡2÷„/Hlj‹È}H3j·
+ÓÞÊ—"°$.’G„€"9{``…F¢K™*2XpBÄF§a%ˆ@»|tÿ™p~
+Öˆ,ëô+Q£Þ`°˜–¥ýmÚ{åúÉðGöBƒ6% ‚½¨v]gZw~‰ O&*
+0W¥=è?³4
+# ½?&ãnAÏø†{/EŸ>y 'pv¨ |xv(Mߘ¨ˆ’I×›2¿ð\)ÔL(­ŸÃ*x)V3É/ÔEæ3 Sê#@RiY.ã‹Fјå-ˆ &²’Ë©äتaÞÎ¥µ`xµÛ’h›fŒ’BN7[õfo‡õµT¾„‰Ô.Hi:ËWÅ:-iÌ8¯~î[N—˜yÃ¥4Ë\vÛ)/þ0™æN‰¥S¬£7ÕÏiQ¦KW#B}“R·÷u°½¿£¦Òª×LrÊ®¾ù*ŒÇ‘è•V\Ø+¬Ú´´ü‰À´óXŽùsäÈQí©ö•ç˜V‰ˆ&-¢Øíá#ˆr‡Î9(NX :…ùâµGAÐi3(ŠGá!"ìaüê ; ¼ä]¨g
+Öx§ÝfCb°}F$LŽ§Œ·2 ºâ8þè=¡XøŒÏL€ú„(ªÏå‡âܯ­H«N6ŽZœ``q´´‰NpÄ
++E0ýl$§“QyàUuKtÙÔå®5êÛ'TÁHÉ}œFÉ®¨îj=œ"8]F{§§ÀÏ
+5—øE½²Ábm«+®:Ž±¼7Ü6VYIµ×MÚË¢,Zqö'ót[F$`KiX'ópE,N’ηùœ›P ±Âš¶ÀÄá»4â¡*¾Q˜£Ñö¨²Ây_pC<Ù¯b®
+ã;¹ýDbK¹ãc¯ä ³1Ðtï# ½dõ:u
+AQœÉÄ®÷4ž^¯ò¦qjÔkHÔ¶æa™^ÚÜ—'¸0@ïûHÖs¡ÿÌçñ„!Ž€Þ³ `B‘ipß|w¤8~±˜üòÑ8<ýÙQÓçT[Ïýö$;9þùˆ<ü|ÄEÏ™}ï¦oXFì¶ÂÑ-“»ïböTŽB)tÛŽóû.j ÚÉHçí®oôîd+.ÕÇô>¥y2Ó$"HÜ â:I¢AŸØIoÞì]¤{®Ç߶ÚI¿ðc¤1Wï.ïîFÅŠC)v\‹ŽŸ—y¾+ã“gMÂK¿bë¿ä L­Hú%¥({)¤R¬ôÏ}îvxõÿ
+endobj
+1541 0 obj <<
+/Type /Page
+/Contents 1542 0 R
+/Resources 1540 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1547 0 R
+>> endobj
+1543 0 obj <<
+/D [1541 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+522 0 obj <<
+/D [1541 0 R /XYZ 85.0394 713.4234 null]
+>> endobj
+1544 0 obj <<
+/D [1541 0 R /XYZ 85.0394 686.2623 null]
+>> endobj
+1545 0 obj <<
+/D [1541 0 R /XYZ 85.0394 478.4096 null]
+>> endobj
+1546 0 obj <<
+/D [1541 0 R /XYZ 85.0394 466.4545 null]
+>> endobj
+1540 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F53 1017 0 R /F41 925 0 R /F14 729 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1550 0 obj <<
+/Length 3201
+/Filter /FlateDecode
+>>
+stream
+xÚÝZKsÛ8¾ûWè¶rÕˆ‹ ‚Ç<œYOÕ&3Ž÷²³s %ØbE"5"eGóë· € DÉÉćTÊ%³ñn4¾n4Ðà|’©D¢˜äEšdŒg“ùú‚M ìç îêÌ|¥Y\ëõíÅ?ßÉ|R$…jr{õ¥¦5ŸÜ.~Ÿª$M.¡6}}ýþmq9›~¼½ÌÓé+üw{ýñöúÍÇËYQh1}ó¯W¿Þ^ÝP-5¤×ü͇÷ï®þÏëàÃ{ʾ¹zwusõþÍÕå·¿\\݆ Ä“äL"÷^üþ›,`®¿\°D:›<A‚%¼(Äd}‘f2ÉR)}ÎêâãÅo¡Ã¨Ô6g‰JŒHMð çI‘eb ¶¬H”Ò‰M&ùåŒ3Ʀ¯‹ª«šº\Ñ<ßU+ã¨f».»ç ½Êh-Ød&Ò¤Hyj»»®/gR²i麢T׸ïÒÑve½(·—\O®È|îv80&îíp?A"ó«‚Ù…k¼Ûlš-p3ì³¼«VU·Žh‡0¥¤ÙÒw±[o†õþjj×Íÿ+c§Š“ òƒÉU8‘MsK$qÚ"€d6½^¬ˆR‰d›°ˆÙ^¶åÓˆOxι«CÝÒUKßùnK³©»Õž²ÊDzZ•w¸J6éj–ŽÏ2ZÏžYÇëõA÷%}ÜîãúV3
+žK/R:bhCŸ8«êBL¤Kÿh‰¨êÎl¸eWÕvÛK=ÝÍ»õãÊ+JÍq¶œóéO”oew{Ê ÔºÜ~I¸¼jM<5!‹$VM¹ès«µIÂZçI!…¶3{‡X…@¹àg³­ÖV0¢àÓÖl 0
+ˆQ*Š"°Áo7ŽŽ\&iÊõyt°DËB ÃvÞÒ×|Þ\r”–Y¸ÑúÞ9.Lm¶e(¾'ù¬iBŽÿ „£“!€´} v-
+ò_!˜)Q^IYÎ¥… oÐ0×ú°Øp0`[’Œóg£Xz„èÔú×0Ⱥüd¼ôòÆÌ»rþi·qó¹ïù±AÏáÀc—
+(WÌiûÞm~UÓ‚‘VNY±$xÌ ãzk HÎÎÚ6„ù¾œûBò©”EúÖåYI*ô5;×ù·Ê„»ø^EĨõó”=LA‰ŽO9Ê”®êùj·ðuí4RkÞìjØ?;âUÞ\
+vê³×3ÔŽAWŽô-†]ÍüŒf)¬zŠNQ¸y‰•XAkÃÄÁz1!¹»)ƒ„vcþÜ™–nXb™I–'™ƒðmL‡.ŸáZrthx6d› ”Óz·¾³HÍɈc^ÕÏ Roߤb‚§› -Bã1¢/¦$¯ŽM?üúæÃÛ«c1 s*ø ŠÁ"É&³þŽíA¥Ô°[æ"{•L$9OÅ*Û™meNƒ2à¥@yžé”1×”2—”H[Ͼ=(1õ§›’MØ= ¼ í7ÛoÌi0¾œ¾0‚‰Ö*ûšù'Á˜±¤`ú0Ê\')Ëè2ùî{h¾ŒÑ
+wù—Äìä!+œ[ñ¥1/G›Q¨tž…£¾¬%´ŽÈ €]ÅÄ#c²ð:ø›*÷Ds¨µç>츎)d^«#Îý‹æcÖÿQ(Tendstream
+endobj
+1549 0 obj <<
+/Type /Page
+/Contents 1550 0 R
+/Resources 1548 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1547 0 R
+/Annots [ 1555 0 R ]
+>> endobj
+1555 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[1 0 0]
+/Rect [55.6967 62.1828 116.8967 73.5749]
+/Subtype /Link
+/A << /S /GoTo /D (statschannels) >>
+>> endobj
+1551 0 obj <<
+/D [1549 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+526 0 obj <<
+/D [1549 0 R /XYZ 56.6929 769.5949 null]
+>> endobj
+1370 0 obj <<
+/D [1549 0 R /XYZ 56.6929 752.4085 null]
+>> endobj
+530 0 obj <<
+/D [1549 0 R /XYZ 56.6929 542.1781 null]
+>> endobj
+1552 0 obj <<
+/D [1549 0 R /XYZ 56.6929 510.0725 null]
+>> endobj
+1553 0 obj <<
+/D [1549 0 R /XYZ 56.6929 447.7453 null]
+>> endobj
+1554 0 obj <<
+/D [1549 0 R /XYZ 56.6929 435.7902 null]
+>> endobj
+1548 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1558 0 obj <<
+/Length 2647
+/Filter /FlateDecode
+>>
+stream
+xÚÍZÍwÛ8¿ç¯ðQ~­¹üDqöÔ¦I'=¤­ãîÎÛéd[‰5+KKvšýë (YvìÊù˜÷ü|‚ ð¢EÃOô¢€qeüž6> ¸z“ùïÝAßÇ3áx5Ó Íõ~töK¥{†™P†½ÑmKVÄx‰Þhú»wþë»/£‹a î…¬?Bºþ@CóÏ×—W¿ ßõµï®>_yxqy1¼¸>¿èŒ‰$Œ÷[ÜØ›r#oFWç7ý?FŸÎ.Fm#W¨ý_g¿ÿÁ{S°õÓgÊDAï^8ÆÈÞüÌ |¥jJvvsöµØêµC÷¨ˆ‘Ô{P“bja¡’Ê¢††ÂÌýàœ{£YâL­â*-«tRÒûeš%h,ˆT-‘¼7>3¾ð­°fx•ü¨¨u[,ç±k—;B§«ù‚Zãä.Íõ>­fÔŠé‘¥yò¶nþ7ùÅé!¶õš%#«Ç›7oö›ñ¡™±aùÎn´‚P2¾±ßL¯7f*®½|5'Kj§9>#o/û"ò’¼š%eRºN÷Œé@äSâ›Ò¨oyúcPV™“\¥ó¸æ 0\IáÍ“¸\‘`7"v"ËdRäÓú%Í'N§8_ÅËboÑ*k‡`&¤µCÍ2„Þe‘eÅ}šß(>øof}¦ŒŸZh>cb)ÇQÜÒsË»Àæ·E_xèþ´ÈѾôîgéd¶-oWÉ]±Lÿ‡–áÀØuL“r²LÇ–ŒóŽ‹uÂȸ‹¤lYD9
+ÝÒ[„ø³Q%uYxá‰
+—¨±T^Ò Þ*Nsr¼Wv
+½í +t•WVYè\ÇÙÊñÝZÇ[Œkü@Ô´žò*Îè…²ì‹%T",(;i ˆÆ&N³$Z¼ŽÓ,gŽÅ©Uº¡—5Û˜b}V}!„‡†kÑ°“P¥À>‹× Ñb"Ô†@ qÇ@’‰–QËYqŸ-ÍkéÉ>Cw“ØwÎeqY³>Ê2Ú.ñaOBKh¡H«h˜vkI÷³¤V{‹£I@@L t
+¹' Ó,oAäªVfk ,Ð|KfDËÆFÔëQ¥6™ÉÈSÙÏ—ò]JÝ•˜7<‡2³è5ÙTÀ„àº)gu1Û㼞ãê˜RW TgF¤T»ˆ´^¹šÏcL\ÔµåeÕV;Ð+ÒiO‚4C„…õm±ÏáB‚€²ÐRG.bº'25«ZSÒëí¾¤H<]r[Í‹Õ¨^¶šçÔccGðšU@²mV ¤gÀ`Jôòa>.2bÎm"Ä–ÕFˆÚF Ôé¶J`‘obZ:vRº™šÀÆZ†V¥¼–yÄ24¶Ú¸RƒËòüd’”¥MlÐ fP#vÝ¿ŽF_ˆ²% z&³8Ï“ 3’Šê-ñ–éÝÌ¡g¹ldX
+Ç\nÇ\}!vߥ+¡´e’À"œB*0‘ð®!ÃüÒ@ ºd|”bP†]„%µsrÀî:ƒ ðÔ…~kÏÈ;«ÄËÝu–z=gA·èð”ŠXè‹hËSáÓ<ž¸§j^ËMµ6¯–s [ø~Ôá)á3­ÜV<u1ÍKÞíŸaã‘íõŇëÜLp»EoÁY»ë œ-m_+K½v—Æ0ÀAw Ê%Ó:T5Nïã)¢ò/{t…zøllWy¹Z,ŠeEûX›ZPgËæSÇq€·y]À_/„e¤™T~ðsÀ%pGR4eatsõñù(ÛÑOÁ±¥ãÉâ¨&µé(¯RG,
+SÃ@¼ Àèg%‚¶®'›BÅpÿÕgbÊZ‰àE‘™æë8K§›ï!›P­¿¾´Aß
+endobj
+1557 0 obj <<
+/Type /Page
+/Contents 1558 0 R
+/Resources 1556 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1547 0 R
+>> endobj
+1559 0 obj <<
+/D [1557 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+534 0 obj <<
+/D [1557 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1252 0 obj <<
+/D [1557 0 R /XYZ 85.0394 752.4444 null]
+>> endobj
+538 0 obj <<
+/D [1557 0 R /XYZ 85.0394 549.5629 null]
+>> endobj
+1560 0 obj <<
+/D [1557 0 R /XYZ 85.0394 524.9842 null]
+>> endobj
+542 0 obj <<
+/D [1557 0 R /XYZ 85.0394 417.5407 null]
+>> endobj
+1561 0 obj <<
+/D [1557 0 R /XYZ 85.0394 395.2295 null]
+>> endobj
+1562 0 obj <<
+/D [1557 0 R /XYZ 85.0394 395.2295 null]
+>> endobj
+1563 0 obj <<
+/D [1557 0 R /XYZ 85.0394 383.2743 null]
+>> endobj
+1556 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1566 0 obj <<
+/Length 2456
+/Filter /FlateDecode
+>>
+stream
+xÚÍ[[sâ8~ϯàÑ©´º_Ó¹Ì25tf«kfç`gâ©Û$ýõ{dÉF€ÁÐSTWµ…Ðåè;ß¹è8†¤'$’†šž2 LDoòt‚{Áw?Ÿ?¦_ꇣ>NþuÅTÏ #©ì4ÂZ“Þ(þ#’ˆ£SXGŸ×æ´OŽnG§ŠGgö¿Ñàv48¿=í£itþï³/£Ë¡%ƒ‰®ÇO?¿¹¾üüÛÐ/psíº‡—W—ÃËëóËÓ?G¿œ\Žš„‡$˜YéŸOþø÷b8ë/'1£Eï>`DŒ¡½§.œ±ºçñäöäk³`ðm5µ 4Î5`ÈôFœÍ»º0ìê›”!cå\Þ´/ RŒÁ‚Šs„ ^¨’@ RÃ!ê)ad”Ujøš¿ “û$Ïǘ‚)DÕpا<Oò4)NûŒó(?%:JŠùc™Ä®'†ßøE«žñ´xMr««:âÑCê—™d¹_i–MãÂ
+»õ AFZm[fNåCâe EâZ
+/b¾ù0L"*
+59$Ôš#F¸ê€Z+d0iBÁÕÍð3X¢…D*@ø,èPûµ·
+7±ãb>{L'ãÒ*›2 ¡cÞBL­yk›kl£æªmË2yš¹ÐbÇdî¹`«Ÿs7/]#N‹~o&™OÆìR²‰ñÔ=“ïiQ¦Ó¿Ü§ç¹½¹O. µ­J8Û(ÆO¾5øâŠcOÞ⧶gY^þÂ1^­þfÓY .ª>MaAÿuù6KÜ·ckJöÛÉã¸(|ߣÛf¿¹ïî’JlÛt”Íúm†;Á’lNUÛœj³9åð­žíV^_J©¼"ãFÿ-f©äÚÕË® æãÒa#¶Wçe´i|­?f(?Ôö@Z£Ýn|B
+à$w«&^¼Az‘Nvó
+ Ò³ H8¹îÀP@ta\.cøîˆáB¸cæ!§HÚ…!‡0« 0&wC8…üÝ•v7ÂèÒª-03Ž rO¦dŽ¹8‘ «7gû˜âÏáßZt8Ä@²c¶e¢‘Ñ´+SŠ„4$pS~€dÇÌ@¬¦ª+Œ$a.Ÿ}»“ç½(h笕ä¶p ×ÃW½wT´# £‘Z-Á·÷†/”ë˜áÓ ZÒtÀ§á^ˆ!µ­@yû{ÃÈuÄÞ(WZÒ†‰X¸æKðíþýá ä:fö ƒ(–Ñ—HŠ”aÍ«ÛùÄþD'~¿¯½ÊÙôN¢°+&ñVDQQ®„w *0ÒL×€n(V¾Í µË”NƃæÝ«f?¢äŽ
+1àÙº™ TíR7«^ê+¸ec¶½n¦9¢2øÙ A̗͆I‘=¾ÔšØµRÖÔ〠Ì]WeĽNnîú›šÅ¯Œ@íL‡…¶ô3_L¬¥²§ÕzMvȃ(“´Møÿml ºendstream
+endobj
+1565 0 obj <<
+/Type /Page
+/Contents 1566 0 R
+/Resources 1564 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1547 0 R
+>> endobj
+1567 0 obj <<
+/D [1565 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+546 0 obj <<
+/D [1565 0 R /XYZ 56.6929 352.0981 null]
+>> endobj
+1568 0 obj <<
+/D [1565 0 R /XYZ 56.6929 326.9775 null]
+>> endobj
+1569 0 obj <<
+/D [1565 0 R /XYZ 56.6929 326.9775 null]
+>> endobj
+1570 0 obj <<
+/D [1565 0 R /XYZ 56.6929 315.0223 null]
+>> endobj
+550 0 obj <<
+/D [1565 0 R /XYZ 56.6929 102.2008 null]
+>> endobj
+1571 0 obj <<
+/D [1565 0 R /XYZ 56.6929 77.0802 null]
+>> endobj
+1572 0 obj <<
+/D [1565 0 R /XYZ 56.6929 77.0802 null]
+>> endobj
+1564 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1575 0 obj <<
+/Length 2081
+/Filter /FlateDecode
+>>
+stream
+xÚÍšÝoâHÀßóWðÒÒ×ßÙfYí$àV+íµ€lå¿¿j·mÚl¸äNh¤ 6U]å_WWUÓ& ÿHG „™áe8˜ˆÎly…;ßá»/W¤é—BýPêçéÕ¿†Lu 2’ÊÎô)K#¬5éLçvo~¹þ6Œ{}*pW¢^_HÜýytwëïÿçæþn8úòïñuOñîttçoÃÁxpw3èõÑôy0B¡;™:¥Bs2ÝLzO½L«’`æ¼ÿqõç߸3‡gýõ
+#f´è¼ÂFÄÚY^qÁàŒ•wW“«‡jÀàÛ\õ4Î5°¢ªÓgi cœb–3Ä%­[ý¯”J?p§O2B4Ø÷z†*>–õ¡úüBp…¤Rd&ˆ“$$é(A• .
+&oËÇdÑëKnh>wº˜»â>£œvom:ÛÄë,NVû3(C„3Ñ mìa5,aÈÏçÃR”˜Š%‡ø0ƒŽÏÃÖnÞ^8Ķ²;¾ÎPe*ÑB
+çJ£oNÃaüê±MýEjW:0pîs’ÏHRRê€T!&
+ã¢;†ëvœ;¥3ø¾]l4* —¤…ŸŒå0h~ö„è^~ƒ šwÇÃ(^´ƒtÚ Ú®ÏrÚg
+»¼™nåê5¸¹]Øï‘ÛbŸG2ðòRI
+C¦¥Œ #æRmzæR_Žr þ„=ãÃ.[ztÙn㸶›§d³l:y± 5¨bÞRÐ…fHâ ú—ÅÖ-äA·dŠñîdò–žõÆÝÄÿæóbÁTŸÜ¸%âxõ’üÓØ;ÑÛsHˆqÓRâ…‚A˜¤{€åÙ€å眿XÀB‚*o©þBÀ½âgê €Ok¤N Ü]cÕ5pøb¡rŽ83-õ_p0z?jO¦*?‘jàñ¥¶û°GG\ó–ú/˜DXa_ÿÏ»ªhqev¹ÎÚ©BÏ?Üxf/Ñ"žç @Á×Òˆ1pñbƒ“b$¨n+þ”#B„¨a¼ÿçcÓílfí¼‘`àÝg¤ rVo[j&)I¢ÛŠ¡ˆHÌjïì÷s *nj@ÌÿÂýUÞ¾X7^¹~*Ö}ghw¬åÓwÛ„÷1Zÿ»†%[zÖR´¸ÖÐ@ÖðŸ–Z›B¸-‘†®}VüîŽNÿÿ‡¢6†m
+VìV±Vá \†%ÒÔIsÁ”ê#%°<fæ”@Ù) wd —½>Áwo’å¸?Æ‹8+v¯qöìg6%ÁìQ…\tûÉËÌý‡©F° e!Tœ©Þ$ÛUf7éèè3
+hs“uဋ¯òË<C»ÏÉ“»öªá¸ðrMA­ôű Š6õ"ùmæñêû!'%ˆ3UŒ¥‡ž– i$i~XȦÒeÓZ>šÇó#G: Ú M°h9—€©†˜+¥ò˜»þcø>Úˆ„y³ÙJê€ÝZ´A
+eœ¨ºáésœÖm±Ëõ ½bšÆy®Ü[¤þÃh5K–n–ò«‡ú{ 3GaRM‘¡T6à ¥ŽÃ¬¤r˜£‡w(1ä>,e³ÑJê€ÕJ ÈÝaoÍìç¢Û[›f§²Ч0®ZXR ,K©œåý:Kß&„’pMg“ÙJê€ÝMÀ€½n¸…fUB‚üç.òŸ„þRuNJ0eݲûfgµŠ”ÁÑ·¢®ƒ_­ßÍõ_ÓMZ¨¬ÑÌŸZêºZÿOÃÔR S[Jùsrˆ¹¿NŒä¼Ùj%uÀìþ:1\¨ºÝ#3 ‹j lËõÂ.-ÈÌ*¾)1¿‹ƒ7»èØ{•L ÷2ä'ÃÖ]Ò©ï\îÞBåÐIjM#ªšõ©¼™÷;èœ5U\ÿðçœendstream
+endobj
+1574 0 obj <<
+/Type /Page
+/Contents 1575 0 R
+/Resources 1573 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1547 0 R
+>> endobj
+1576 0 obj <<
+/D [1574 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1577 0 obj <<
+/D [1574 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+554 0 obj <<
+/D [1574 0 R /XYZ 85.0394 439.3709 null]
+>> endobj
+1581 0 obj <<
+/D [1574 0 R /XYZ 85.0394 411.7795 null]
+>> endobj
+1573 0 obj <<
+/Font << /F37 791 0 R /F39 885 0 R /F21 702 0 R /F23 726 0 R /F65 1580 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1584 0 obj <<
+/Length 69
+/Filter /FlateDecode
+>>
+stream
+xÚ3T0
+endobj
+1583 0 obj <<
+/Type /Page
+/Contents 1584 0 R
+/Resources 1582 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1547 0 R
+>> endobj
+1585 0 obj <<
+/D [1583 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1582 0 obj <<
+/ProcSet [ /PDF ]
+>> endobj
+1588 0 obj <<
+/Length 1324
+/Filter /FlateDecode
+>>
+stream
+xÚ•WKoã6¾çW99@D‹¤DIÍi7ÛmS,Š¢ëžº=Ð2m ‘EUdÝbÿ{9R¶lÁÛÀ08¿΋…æGgiLBžE³$‹HÒx–ïoÂÙÖ¬ýtCLsGœ›ÉÄjó”Ä)KfÁ)ÈûåÍâ#£3!X<[n]"Iå,-×Îw²îTs°8œ'w-ÁmI҄¶ШHHœ±Ìnxÿôë”Îpø¬ò¾)ºÎuÕkÕÈ®0Ô€G#Â#ÁžˆI,¸…3¦Ü4 Ãù»<Wm; t.qò©h;ÄgɈS™ÉïçÌí¿£é0€–üÆá»ÇO­é½añt.­¬Âu¹^ãÔƒíe—ï,0ÝNvHtD.+$Zå–úÚaVk$ª"®äÞ©Úè:ßô]jCß*80‘R’Å1³G,ªÁ¡G7SfdAD–¥~ *ݛÄÏbA¢(Iœðý\DÒXŒÀþîU3‰›˜²·Cºš@KBÂÒ8ûÜ €x ä^[LšÜH©x“}Þ´©0éGÿrUÊüy§K5AFß›A¥™˜"w™A­D×Ȫݘ:¾TÅcQqTekJu9A<¿ÐŒ$<Â"ÿ£-ª­‘¦,M© e­p´Íy :ãN¾(¤¾„!«lGtž?Òù±§_p5œ¿îÜn[9V‡o¨ÃÉaÅ
+ŽÛýâþá-ñÕa|ìkç›üÌYˆ2K›éœòá=4v{Ix ¬°7L ÉsaM
+endobj
+1587 0 obj <<
+/Type /Page
+/Contents 1588 0 R
+/Resources 1586 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1592 0 R
+>> endobj
+1589 0 obj <<
+/D [1587 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+558 0 obj <<
+/D [1587 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1590 0 obj <<
+/D [1587 0 R /XYZ 85.0394 573.0962 null]
+>> endobj
+562 0 obj <<
+/D [1587 0 R /XYZ 85.0394 573.0962 null]
+>> endobj
+1591 0 obj <<
+/D [1587 0 R /XYZ 85.0394 542.127 null]
+>> endobj
+1586 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R /F39 885 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1595 0 obj <<
+/Length 3437
+/Filter /FlateDecode
+>>
+stream
+xÚ¥Zm£Fþ>¿ÂßÎ#1ý4Ñé¤É¾\&íæv=º‹’|ÀÀØÜbp
+Êú`ZFs‚ÄîXËpþT7DŸ²˜@§âUƒ;P}n¼J²È—;ÖÍ¢p”ÝçMy¢gEå$¡ IÓé¡LXÒŒ¸ð¶À§`€ê7À®s7±X‰é!ƒU‚3å…Ap‘~_2b@?ÆDñ b¡!Gk
+÷ìúÀWlÇK’?yh{zþžÓíÜíeä7ÈìoTãàZae㳩 HÏE~ÄØ<uÄ€c –_ BÈìAäâfÁëÆñ1Êž#²[›R ~ñ}Yæ„=`g`ËO(ª
+€©À¾\Ó5Éþwh»‹õž“ò·ýjötDˆa% ÆÇCX©u¨ãK>];OÛ”¡;°^¶Ü‰ÚNA¶ ]ÀŨ8@cOm_d :ˆ)w ¼Ð„1.IÓúPqàxr2RËÙJD¢ÅE²z¬x›€ŽE·%$‘'MYþ±8¦åSÑl*@EKº£¡u‹XNû‚eyrü@Qð^ƒø±pòW“GÀœ¨O'¬h@ ŠÅå Z d`.3ÉuDSqßÛ.醒Wuãà<¢]`¹ ÛáE*Ú&¶PÂÓøºIšÂœAÈb#1>! 7h·G¢8O@\›ùwõ14LQ|ŸWÁ˜oŸé[Hð
+²Smã3b¿£B‡ôÔ]r¢Ù|ŽÆ‚Ë2.­rÂÜ÷æSmÚK/—&B„K¸Ë,^þ‘7õBP^÷m±©£•é!«|…Úeˆ Ä(ý35dVÖ›ú.ÒÎÀÅÕʸXÜcžy—:èŠÝ”›…nê6ìM°)å‰(4=0p%üãÍr]cá¿çÒóÏ
+õë ç<pK
+aµÉd(Iå: B ¶k䪯?óü•ówW]Xéù‘Œ (ãaéÙo3áù:ŽMŒí^Ïg` ˇœ½­aG³Á¦ãųÝÄž@+¬o`# í©î,HÒŽÂ{(DaÓG×ÐÉ^Å‚Ñb̤ËQ,`î-]ÁZEÐǤ$ö‰"Ô ÷XìÛIçŠß’ÑúÁþP°Ôj (ì`3ðñ!ó(¥Æœ¬o%$5ô©ˆ
+€è­ æ„ ÁbËË|nDºÊa pêÐXÿšý£§àüeæ¯yçØ¥ N×g—µªÝ<飑Ɗóœâ,÷ö¦T¤Z÷YÒå®YÍ}ÇWÛÕ÷à•PÜop}U!ç™ãÔóÇñS’ràÅ»v[ÊŒÆk~4Ê.y†íE¢¶શæFj˜ñ…3`ÆG˜ñÊ€y <«ÊÓT‡îh[¬¸®Ñó¬æû-US`ï¶7¤uÒR¤(¾ÇÚ•Rjþð#’,#ŒÚòKTt)7SÏ·5•MŠ0iþTL +‡ÓèäîØ¿XȲè§jjÕ½°ô⤬…^ÖQç@P™Þ
+*þ[Êá¿Ý6[ób 0ŠÞØ^¬êÉÕ˜>ŽýÁdsn—+p»É»¼ÛÖ‹Á4(Ð8ûàèPÊçgí춦)îÁX¸¢+I#p¿*—‘)0Ó-ŽßâéØBI¿>0½XyÒ¶ñ5ƒ6Ö`±#_¶5ŸxÝõ¢&ŽÅÓHøˆ´8:çeìùRÖ)¼¨+Oʾ¢™E?}¢6‡el#ÉvL膄…Áød`­Ð¥-“gžÚÀŽìH½å ~Dn‰
+ä¤ëP·=\3µí«ÁÀ¹y ¦¡ž9—‚Ýõ{Œ§ú¯+z¸GzDßZ&Xñnø}Û,ð3`;Ãô€9€Ï6å_:ÔôÉa¢Ö9/zÆžÉ~ð¥Ê¢ÜÎ}37=ð Å0tæ‰O<ö'Ê·æÓZ qèKZˆÝâ0íç4 ³¾íßmlèçb?·Mnˉ To t³fîisÚwõ¦Iö[×kÀÇÉ$¨°ýÐåÌhÍkìò¤š>[4A
+endobj
+1594 0 obj <<
+/Type /Page
+/Contents 1595 0 R
+/Resources 1593 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1592 0 R
+/Annots [ 1600 0 R ]
+>> endobj
+1600 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<</Type/Action/S/URI/URI(ftp://ftp.auscert.org.au/pub/auscert/advisory/AL-1999.004.dns_dos)>>
+>> endobj
+1596 0 obj <<
+/D [1594 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+566 0 obj <<
+/D [1594 0 R /XYZ 56.6929 723.0302 null]
+>> endobj
+1601 0 obj <<
+/D [1594 0 R /XYZ 56.6929 689.3491 null]
+>> endobj
+570 0 obj <<
+/D [1594 0 R /XYZ 56.6929 552.677 null]
+>> endobj
+1602 0 obj <<
+/D [1594 0 R /XYZ 56.6929 525.9649 null]
+>> endobj
+574 0 obj <<
+/D [1594 0 R /XYZ 56.6929 411.5673 null]
+>> endobj
+1603 0 obj <<
+/D [1594 0 R /XYZ 56.6929 383.9327 null]
+>> endobj
+578 0 obj <<
+/D [1594 0 R /XYZ 56.6929 225.6356 null]
+>> endobj
+1299 0 obj <<
+/D [1594 0 R /XYZ 56.6929 193.4614 null]
+>> endobj
+1593 0 obj <<
+/Font << /F37 791 0 R /F69 1599 0 R /F23 726 0 R /F39 885 0 R /F11 1367 0 R /F41 925 0 R /F21 702 0 R /F53 1017 0 R /F48 940 0 R /F62 1050 0 R /F63 1053 0 R >>
+/XObject << /Im2 1039 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1606 0 obj <<
+/Length 533
+/Filter /FlateDecode
+>>
+stream
+xÚ¥TM›0½ó+|©¸6Æ`³IÚ²RÓ4a«ÕxT‚Ó@6Úýõµ3·¶ôTEóÆoÞ|x€"b~ Ž “1JeŒ9¡•[ µ9ûêQÇ Ï¤ð–u—{Ÿ¿°I,“(AùË–ÀDŠòêÉÍóé"#Nü!Oˆ—Í&à‘ðXNÇ‹,4þ1[f“éb¤±Ÿga,ˆ0ñÌ)Lg£ïÙøó P§Ôžó{oš_¹m–f»øí==T™žï=‚™ ˜J¡­s†yÌØÙÓxKïçEðæô:4<Îæ"J¦±¡éq‰fŽìô–z«lO‰ßÕ½êÀ,7ZwÎÝkûäþ/¥và)šŒê­-¶uið[xØUE¯*8˜ØyžE_€U· ã`wXUz[€×H¶.²RZ!—{Sô7üÐŽÛôRŠ%çÑ©'ÂTÊä)…Ú{2è]·ÊÜ,#‰Ÿoê˜Çâ- ”úŸ Œ‰I§Àßë]بWÕ\cÁ*uÛ›|u»vx_÷v
+endobj
+1605 0 obj <<
+/Type /Page
+/Contents 1606 0 R
+/Resources 1604 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1592 0 R
+>> endobj
+1607 0 obj <<
+/D [1605 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1604 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1610 0 obj <<
+/Length 69
+/Filter /FlateDecode
+>>
+stream
+xÚ3T0
+endobj
+1609 0 obj <<
+/Type /Page
+/Contents 1610 0 R
+/Resources 1608 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1592 0 R
+>> endobj
+1611 0 obj <<
+/D [1609 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1608 0 obj <<
+/ProcSet [ /PDF ]
+>> endobj
+1614 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“v
+i ·¥Ý3éÀ–yíˆùðŠ&Â8K<æcø¡›‚hïCû™<»úÐŒ­êhüýÔï Æס\@•‰ó÷w= vV
+ŠØmT¹,(¾ÊÞñ‰}q´€¨\Â&|&d¾vKÈTÝVŒÐhÆKI›S?s@Õ+6¸k0mHšŽµÇrRϯÄ'¨
+ý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Œ$
+­è×ØÚ:‰óÎÐÃ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ˆÌ¨W
+¥Ì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¸ÉÀUßÄx³Q³Ô}\Wù¸·ö߶
+ߣ«ª]qöü´Þíâ³äZÄ^d{‘¡Éep …E\æÞ†RÊ[oóûæ½»ÿ
+endobj
+1613 0 obj <<
+/Type /Page
+/Contents 1614 0 R
+/Resources 1612 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1592 0 R
+/Annots [ 1621 0 R 1622 0 R ]
+>> endobj
+1621 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<</Type/Action/S/URI/URI(mailto:info@isc.org)>>
+>> endobj
+1622 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<</Type/Action/S/URI/URI(http://www.isc.org/services/support/)>>
+>> endobj
+1615 0 obj <<
+/D [1613 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+582 0 obj <<
+/D [1613 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1616 0 obj <<
+/D [1613 0 R /XYZ 85.0394 576.7004 null]
+>> endobj
+586 0 obj <<
+/D [1613 0 R /XYZ 85.0394 576.7004 null]
+>> endobj
+1617 0 obj <<
+/D [1613 0 R /XYZ 85.0394 548.3785 null]
+>> endobj
+590 0 obj <<
+/D [1613 0 R /XYZ 85.0394 548.3785 null]
+>> endobj
+1618 0 obj <<
+/D [1613 0 R /XYZ 85.0394 518.5228 null]
+>> endobj
+594 0 obj <<
+/D [1613 0 R /XYZ 85.0394 460.6968 null]
+>> endobj
+1619 0 obj <<
+/D [1613 0 R /XYZ 85.0394 425.0333 null]
+>> endobj
+598 0 obj <<
+/D [1613 0 R /XYZ 85.0394 260.2468 null]
+>> endobj
+1620 0 obj <<
+/D [1613 0 R /XYZ 85.0394 224.698 null]
+>> endobj
+1612 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R /F11 1367 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1625 0 obj <<
+/Length 69
+/Filter /FlateDecode
+>>
+stream
+xÚ3T0
+endobj
+1624 0 obj <<
+/Type /Page
+/Contents 1625 0 R
+/Resources 1623 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1592 0 R
+>> endobj
+1626 0 obj <<
+/D [1624 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1623 0 obj <<
+/ProcSet [ /PDF ]
+>> endobj
+1629 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/°öùÇ<a¬£0`²°ºŠ‚t¥~r±šorýôîÃ'ß»ðÝuûÑÅÓ~<+N’µ¥OÅ«¦‘u¡~]®üÈu®.ÿ÷ô•ÄÂu’&Š¹pD²ã$žKäÒŒÌ^¸ÂØgæ8Z‡A’óÚ»\y® [çϵ>•²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ñ
+\Ó±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ƒÚ̓
+’ r”OœBç=Á 1j"«¢ºÑpQɧUäzý"GöÄÙ G,ØÝfS6ä ÐBdz˜€z²Ó„Q™DÏ B0q
+ã”U#7Cã@Q²€.ÿ¾ô
+ÝD‘øñðñ^=:\è±æí
+®o¬ƒñ+ñ'E\2}8Ç’;i %Ò‡ï&ª°Wõ\~jÀaÛÍ{³˜¢GË!zeoA_^†NmÞxš^Xð”Ð;’ù‚Ïr{z8Ø'"Hóȃ…×UØNÑô
+endobj
+1628 0 obj <<
+/Type /Page
+/Contents 1629 0 R
+/Resources 1627 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1634 0 R
+>> endobj
+1630 0 obj <<
+/D [1628 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+602 0 obj <<
+/D [1628 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1631 0 obj <<
+/D [1628 0 R /XYZ 85.0394 573.5449 null]
+>> endobj
+606 0 obj <<
+/D [1628 0 R /XYZ 85.0394 573.5449 null]
+>> endobj
+1632 0 obj <<
+/D [1628 0 R /XYZ 85.0394 539.0037 null]
+>> endobj
+610 0 obj <<
+/D [1628 0 R /XYZ 85.0394 539.0037 null]
+>> endobj
+1633 0 obj <<
+/D [1628 0 R /XYZ 85.0394 510.2426 null]
+>> endobj
+1627 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1637 0 obj <<
+/Length 2893
+/Filter /FlateDecode
+>>
+stream
+xÚ­ksã¸í{~…¿Õ™‰IÔ3ÛéL.›ls×Ë¥‰;íÌíÍ”–h[]Yò‰r²¹__€
+'é<%Ø«Ô4hνd®J%µÊ‰¢¨ó¬ö­Ú­TCSßu]"UN ‚yH‚ïäêfÈõµ)ZE¸zMˆJɦ|ãeeÉ õ^e-3³”í–—ª\~ 4
+hfáyN†¾9fùVT²"ŸFÒÐg[Ø>k$ŒÓ­%ya4P’~¯$œø#Ìùp
+"‡Ï®ëgýFÐ\í‰s&[ÔÂŒjp`‹1ãÄ.}Qe½ß©ª%€Ý)«+]ðq‰§
+~H¿°OQ­4Áæ:“¥$o…Ù=ŠR©–fì-DM¸û"çËm/Èá¤ÝÒÌNßöæ@1t$ê÷Š,ví-#‚؈p
+þU‘IÝN˜PxN,::¼I47׶!ËYøÐ`TÎBÄ ,ôÆ·R’¼¹†c¢Dàö&ù0!eâ;">o~]½½'¤
+æíœH¸>ø8þzduÖ+ž™ ‰èMY¯0† Ð:„™ ¼‰(5Dòâ=@¶«‡›}´ÁãBnÑŠw|º»!&ñÅÔeúìûÁ'ãL'Ž© ‡â àÎläࢩìÒG¯ÃÍq Iôo£´œ²<Ô‰PÓlÏÍ@ÔÁUæÄG» y¿Nxø¸ë=ãÝ=}ÊSK¨+Š˜5†þsºC:¡'¼£ªÜ¦ÂCìDPÚó’έþÐv±püPص”ï8AâÇcË,)?§½Er¤@@Žh T
+$Œ©!cš JÓ©ÍüÉü°×Ê•Ü Ù™E AL&ÚûçÇsjÛ sîOM–c©6ÛòÍ$;³
+v!¨/rÍ[×½® ÞLh܇l›„´¦5õÃD œ$ŒlH„r«å&Âçݳ5º?¾·hdµÁk+ §/-UçI0>
+è¾ÏÝG$”uf,Õ­DC¡Æüx¾;˜t
+(–"—ÜYi4¹B™º¦qfèY'ÉíŽÑ–\z ¬nÌ\³&ÊKŸ ‰•v(Äð1“‘㣓Æ|ÒØŠž«Ëˆp}µ6eè£[SWöj›ŸMñ¢Âú`K@®Ö j]¼©VP%Û
+endobj
+1636 0 obj <<
+/Type /Page
+/Contents 1637 0 R
+/Resources 1635 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1634 0 R
+/Annots [ 1641 0 R 1642 0 R ]
+>> endobj
+1641 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[0 1 1]
+/Rect [253.7995 146.8976 417.685 158.9572]
+/Subtype/Link/A<</Type/Action/S/URI/URI(ftp://www.isi.edu/in-notes/)>>
+>> endobj
+1642 0 obj <<
+/Type /Annot
+/Border[0 0 0]/H/I/C[0 1 1]
+/Rect [63.4454 108.9117 208.8999 119.0735]
+/Subtype/Link/A<</Type/Action/S/URI/URI(http://www.ietf.org/rfc/)>>
+>> endobj
+1638 0 obj <<
+/D [1636 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+614 0 obj <<
+/D [1636 0 R /XYZ 56.6929 652.1213 null]
+>> endobj
+1639 0 obj <<
+/D [1636 0 R /XYZ 56.6929 614.8935 null]
+>> endobj
+618 0 obj <<
+/D [1636 0 R /XYZ 56.6929 614.8935 null]
+>> endobj
+1127 0 obj <<
+/D [1636 0 R /XYZ 56.6929 584.5024 null]
+>> endobj
+622 0 obj <<
+/D [1636 0 R /XYZ 56.6929 289.5256 null]
+>> endobj
+1640 0 obj <<
+/D [1636 0 R /XYZ 56.6929 251.3901 null]
+>> endobj
+626 0 obj <<
+/D [1636 0 R /XYZ 56.6929 251.3901 null]
+>> endobj
+955 0 obj <<
+/D [1636 0 R /XYZ 56.6929 222.7156 null]
+>> endobj
+1643 0 obj <<
+/D [1636 0 R /XYZ 56.6929 53.7852 null]
+>> endobj
+1644 0 obj <<
+/D [1636 0 R /XYZ 56.6929 53.7852 null]
+>> endobj
+1635 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F39 885 0 R /F53 1017 0 R /F11 1367 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1647 0 obj <<
+/Length 2824
+/Filter /FlateDecode
+>>
+stream
+xÚµZ]{£6¾Ï¯È¥ý<-’ KÇö¤É4™4v·Ûα›glH ÎLúë÷} 0’;Ûî“‹€tЋÏ{>%ðe
+’_.×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É!˜
+¨¯…bãX•×"ÚÅÜ^óU&§&»M SÛ½œ“aO>ÒÆJ¸—±$|P,ÓÏ©öZÒ«áBгXÈüè¼&Oy|¹–¡…½rh¡èÿ5-†êÓÙlt_¦‡óÜ¢yk~‡šýQ;|•?—¯öÌ]ÇÊ*ø•éIÂÕýàén§æ>¬êÒ6?:¼¿É#hžúû›m£ÚÒÖl-}׶' ð0ö›µ-å6k#eÌšY{¡[³>Á6ëøm±nlL·•OYUî^µ¢Ç——òPŸtœ‹ùt(SG b†cÿ´,†êY¶ê†ì 'b§ôœÞ-)Þµ”Ñ{B©Gï>hKï}l‡ÞmðåVFƒ” /]xº{«òJÞ U‹ÿrk .ÌÖ\«­5¸Ò™@\Û™`8àSá$í^›X)ðúK^(h¹[Oz:¡,!!Ä‘îŒT=­íÔÓ@fè$“pŒŸÙ#µ¥Üd)MføÈôB·dž`“Ùo æv^À<ߪd>*×GÙÅh£`!,J²¼=sܹIBèXìb*HbÄóù,t=ý ؽW£?¦Õ²;/sŸVU¦#·ÜUNÛcD¤¸ªlx·ègnú#Œâ
+-©ôfªò·¸híEÜ™]§Áƒ ,>q­þ˜2.”öl¡H,[£÷JÜØ‚œ©mqƒÐ¡¾c!½3å¿h Pú2ÑŽûÁ’òƒ–²ŒÁ“P½Ð–1ô±Æ`ƒ««º\•bË
+è}¹îí¦'DÕr:Ä‹Y¥ˆ¨ÞV)p'bŒG.» 1JBnsË
+
+íÆ3aGu1z¯Äµ]¨ð®Vî؃Nç]œp1èž
+´ ¸ ¤ƒùÈ
+’Tï*
+µ9Te>#ôá¶6Ø6Ay2¾b$´ÌHÜ)³|Þ‰zA 4lY3ª#Óò`ï§6c¿ŒI0‚¶Æ¾[g;µú,{Ù•oúùFÿÍ+”Ÿë¯’ù Ø.…‚1¦‘•ß‹WñÈÌvìï&}•/\ u˜sê 8˜$Ðk“3©-å¡ZKY\{h½ÐÙ}lÛ6ø´Üïå®+Ö›­ßÁä\²Z*)#ý&ÇÍ:±¦‚ñwù·á£s£˜cû‰†Íçƒb‘÷Ç}ªO]žkÓçÁj%¬¼SƒS5ø´‰3zÝÏÞs–äWœ¹Ïw;sâû}&ÁDÂ(ò[„%ä6-Ô~P‘xN|¸­9ô‡­ÁF^d‡\•<ÛkÒlIdu¾ª2!³ðôtÖÅ:Úsq\û½I$Ø‚?Sÿ[Bn…k¡6ãû>ûòá¶
+ï+ÜF6Þuþ}^=gÛô5Õ Œ@õµ®­Ñ LKç„ }RÛˆÈB
+endobj
+1646 0 obj <<
+/Type /Page
+/Contents 1647 0 R
+/Resources 1645 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1634 0 R
+>> endobj
+1648 0 obj <<
+/D [1646 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1649 0 obj <<
+/D [1646 0 R /XYZ 85.0394 752.3015 null]
+>> endobj
+1650 0 obj <<
+/D [1646 0 R /XYZ 85.0394 752.3015 null]
+>> endobj
+1651 0 obj <<
+/D [1646 0 R /XYZ 85.0394 752.3015 null]
+>> endobj
+1652 0 obj <<
+/D [1646 0 R /XYZ 85.0394 746.3107 null]
+>> endobj
+1653 0 obj <<
+/D [1646 0 R /XYZ 85.0394 731.5461 null]
+>> endobj
+1654 0 obj <<
+/D [1646 0 R /XYZ 85.0394 728.1497 null]
+>> endobj
+1655 0 obj <<
+/D [1646 0 R /XYZ 85.0394 713.3851 null]
+>> endobj
+1656 0 obj <<
+/D [1646 0 R /XYZ 85.0394 709.9887 null]
+>> endobj
+1657 0 obj <<
+/D [1646 0 R /XYZ 85.0394 651.9592 null]
+>> endobj
+1071 0 obj <<
+/D [1646 0 R /XYZ 85.0394 651.9592 null]
+>> endobj
+1658 0 obj <<
+/D [1646 0 R /XYZ 85.0394 651.9592 null]
+>> endobj
+1659 0 obj <<
+/D [1646 0 R /XYZ 85.0394 648.8377 null]
+>> endobj
+1660 0 obj <<
+/D [1646 0 R /XYZ 85.0394 634.0731 null]
+>> endobj
+1661 0 obj <<
+/D [1646 0 R /XYZ 85.0394 630.6767 null]
+>> endobj
+1662 0 obj <<
+/D [1646 0 R /XYZ 85.0394 615.9121 null]
+>> endobj
+1663 0 obj <<
+/D [1646 0 R /XYZ 85.0394 612.5156 null]
+>> endobj
+1664 0 obj <<
+/D [1646 0 R /XYZ 85.0394 585.7959 null]
+>> endobj
+1665 0 obj <<
+/D [1646 0 R /XYZ 85.0394 582.3994 null]
+>> endobj
+1666 0 obj <<
+/D [1646 0 R /XYZ 85.0394 567.6349 null]
+>> endobj
+1667 0 obj <<
+/D [1646 0 R /XYZ 85.0394 564.2384 null]
+>> endobj
+1668 0 obj <<
+/D [1646 0 R /XYZ 85.0394 549.5337 null]
+>> endobj
+1669 0 obj <<
+/D [1646 0 R /XYZ 85.0394 546.0774 null]
+>> endobj
+1670 0 obj <<
+/D [1646 0 R /XYZ 85.0394 531.3128 null]
+>> endobj
+1671 0 obj <<
+/D [1646 0 R /XYZ 85.0394 527.9163 null]
+>> endobj
+1672 0 obj <<
+/D [1646 0 R /XYZ 85.0394 513.1518 null]
+>> endobj
+1673 0 obj <<
+/D [1646 0 R /XYZ 85.0394 509.7553 null]
+>> endobj
+1674 0 obj <<
+/D [1646 0 R /XYZ 85.0394 483.0356 null]
+>> endobj
+1675 0 obj <<
+/D [1646 0 R /XYZ 85.0394 479.6391 null]
+>> endobj
+1676 0 obj <<
+/D [1646 0 R /XYZ 85.0394 464.8745 null]
+>> endobj
+1677 0 obj <<
+/D [1646 0 R /XYZ 85.0394 461.4781 null]
+>> endobj
+1678 0 obj <<
+/D [1646 0 R /XYZ 85.0394 446.7135 null]
+>> endobj
+1679 0 obj <<
+/D [1646 0 R /XYZ 85.0394 443.3171 null]
+>> endobj
+1680 0 obj <<
+/D [1646 0 R /XYZ 85.0394 428.5525 null]
+>> endobj
+1681 0 obj <<
+/D [1646 0 R /XYZ 85.0394 425.156 null]
+>> endobj
+1682 0 obj <<
+/D [1646 0 R /XYZ 85.0394 355.0758 null]
+>> endobj
+1683 0 obj <<
+/D [1646 0 R /XYZ 85.0394 355.0758 null]
+>> endobj
+1684 0 obj <<
+/D [1646 0 R /XYZ 85.0394 355.0758 null]
+>> endobj
+1685 0 obj <<
+/D [1646 0 R /XYZ 85.0394 352.0499 null]
+>> endobj
+1686 0 obj <<
+/D [1646 0 R /XYZ 85.0394 337.3452 null]
+>> endobj
+1687 0 obj <<
+/D [1646 0 R /XYZ 85.0394 333.8889 null]
+>> endobj
+1688 0 obj <<
+/D [1646 0 R /XYZ 85.0394 309.8192 null]
+>> endobj
+1689 0 obj <<
+/D [1646 0 R /XYZ 85.0394 303.7727 null]
+>> endobj
+1690 0 obj <<
+/D [1646 0 R /XYZ 85.0394 278.3282 null]
+>> endobj
+1691 0 obj <<
+/D [1646 0 R /XYZ 85.0394 273.6565 null]
+>> endobj
+1692 0 obj <<
+/D [1646 0 R /XYZ 85.0394 246.9367 null]
+>> endobj
+1693 0 obj <<
+/D [1646 0 R /XYZ 85.0394 243.5403 null]
+>> endobj
+1694 0 obj <<
+/D [1646 0 R /XYZ 85.0394 173.5556 null]
+>> endobj
+1695 0 obj <<
+/D [1646 0 R /XYZ 85.0394 173.5556 null]
+>> endobj
+1696 0 obj <<
+/D [1646 0 R /XYZ 85.0394 173.5556 null]
+>> endobj
+1697 0 obj <<
+/D [1646 0 R /XYZ 85.0394 170.4341 null]
+>> endobj
+1698 0 obj <<
+/D [1646 0 R /XYZ 85.0394 144.9896 null]
+>> endobj
+1699 0 obj <<
+/D [1646 0 R /XYZ 85.0394 140.3179 null]
+>> endobj
+1700 0 obj <<
+/D [1646 0 R /XYZ 85.0394 113.5982 null]
+>> endobj
+1701 0 obj <<
+/D [1646 0 R /XYZ 85.0394 110.2017 null]
+>> endobj
+1702 0 obj <<
+/D [1646 0 R /XYZ 85.0394 95.4372 null]
+>> endobj
+1703 0 obj <<
+/D [1646 0 R /XYZ 85.0394 92.0407 null]
+>> endobj
+1645 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1706 0 obj <<
+/Length 2889
+/Filter /FlateDecode
+>>
+stream
+xÚµšKsÛ8Çïþ:JU1>´¥ØJlÅ+ÙÙ™Êä@KtÌ2E:"•Äß~ă E‚™ÝÚòÁÐÄ_ÂÝ@7I&þÈÄõÒpâ‡r1q'Ûýž|ƒ¾«3"mΕѹiuqöÇ{æOBzÔ›Ü?c™Üï¾L#ÄÐ FÀÓ‹åÅÍòÓÕ:º»þkvN]<ý»8ZÍŇÍÃÕÕbs¿׋h¾\] ™û^ˆ§ÑÝÝb5_þ)ú#>*Ö­—‹Íìëý‡³Å½þÚæO#˜ñïüýìËW<ÙÁ/üp† wò>`DÂNögŽËë0¦Z²³ÍÙ¿ô€Fo}kïTŒ(óhÏ\Q2!…®K[“å†Èc”Õ“µNÊâxØ&r
+’mq؉ëûÌÀÛkRþJFï;@ÃJ|)ÖPYñïôeýþ’€}í*Ja:\ß.­­NµYhhê#—úmíUò~>aÓùj#.ÖkÙü1ÍÓ*-òzN:?…`¦•yð%ø@ïà.Š§—èý,¤S$ÆXüH3LŸãCUéìŠêÿtzïã—¢”½kÙûeû8Ïå q¾Íw3BC5øm±}‰_“êÂÝðý`&ÔW:Ë@øǧmU<Â÷¨)âÃhˆ°†(ðœ¦Õ0am¥ ûØ&l•nŸh÷ni °ðÓW›èN-{îLÛz1ƒ¶ú¡ì/ø Òü›ø 0ñÑdïe‘%YË{ºœa>è3âp0¬,”•æø66iƒCW»Ÿƒ©ñµìOo“Ü .½éSqm‹_¯5¤,ÅdBçM±¹ë ‹eÆ{ÝàMSÙQ='âb^ìãTv®â½lݼ•U²ïÁÊ0A.¢ VFÀ{å`ñ´”mÏAÇç™ëNÓ_i"=Ns®/Œv?ó)z×YK¹*æéö%ÍË"—âüÞôºð†×…ÛžÃÆüÓ°²¬ e¥ÖÅ.µ¬ ›´±.ºÚýëÂÔ†uÁˆ+Ü”§Ž¿¼¡^übóšlÓ§·zeðÏ5rnÙ,Þ\<Ióäð#Ý&%ê¡Nqˆ£u„y(æw^³Çà*“\Ôèx^üƒ±êÛ•_× B+´„*ñqÝ‘ƒ‘ie¡ª¬4UâYöU«´Aµ«ÝOÕÔ~ž 3!yÁÅ2¯’CžTâ“
+†•…‚²Ò`¯·P°IºÚýLíù&?ýã⯲s¬Ø,¯dSšwç]ù?ý
+?â7?Òù1Щsàží’9(ô½6¡¹$´ˆË*‹_ÙÌjGß½Sçbá÷ÏšX8LŒÀÌ6 + 1eeó-ÄlÒ±®v?1S{½‰þ¸»°³øŠó‰<QøŠ¿â€ø±M‚¢ÆµúI_PóBä;80v9_`ã£ØlbãŸlâ0£Fjå“V˜N€‘“n‡iZ ÃÔVLËng•n`žh÷ÂlioªâPïR$dÓËä ¶08|&%osj†¼¯fÈCÞ(ò+Å[Œ0¤ H;†ü~ÎßkºvCaS¯0~ñI_wû#jåáFÜbÚDÚ⹜ã}æÓ؆•¶²2`‡Ø6ivW»¶©ÍaÇbŸ Ä¹Æ álúTŸZί“º2#zas,E*[dè ŒÐêС7[
+°I+ «Ý¿Lí{Ôqî‹5eÇaÓèX=ö[½‰®»"ååÑÇ¡®¢»ûµðOÞ_3æ}í¬“wÉä¤?Èz®Óð†hÁSÃú.•®‘Wä‘ÊïlEÕMò
+ñC§)vŽ ¶á‘#occa(lAFˆ%¼ZD ~mÕ~z*?èn®£s"`Èl„Ê£.¥”[ˆ™¼À•(ÔU½¥Fõ–èê-i2\l—ðÀŒ˜cˆˆ¿´uæåE\#þò‚tü&™ª1ZP"¦}Ô Ç‘…£4j@RKÝΦkì÷£4„£&]ÉøZ?¤üÑ`'¿¿IËJ¦ž"öâv1Ž7܉üðô+)‡²w7JcðìLÚ[ªz!¯*¶Ï'5+0ˆ8ˆ‘ÐÌ0¦Œ407´”lº °®p/0SXÔP8þª’¼¬ŸTÂŒEMþ—Ç××âP £åhü‘JQ6‡F¯¯2ㄽÐØêN7HÜqÿ\ìE¾À[/eëõ1_eëg]0‡®ešÇy%»D
+ ͪ§ÕÚÁ´8¦e™öÕ€0&Ì‹· !6¬,Œ••ÙRM°J”»Úý˜Mík˜´L?gTÎö¿äÅϼë´7ß“.×rí²·üC㇌¤ó]Ë*~*›ÌñtûcêL뽈KV0£ü LHû9­®lé:–~p0ÀòYÈqðH6­†™k«æÍL†™[¥æ'Ú½Ì[Úz>ù¶ØÀ_%ÕÏâðÒä0ݺà'˜¾Ão@Æ¢Ø ,aö³ù¡õÖX¯‡4SÉK0œ¼7D«˜VJʪ¡dÛ/­Ò¥®v?%S{|?¦bÛ'¹ÚõÙ<ò⟮ ½až«¹{ÍÒ­QHoʺ2r÷¹¥É“Ó)œ_â]2P.·Aaðcg¤^gZY (+ Å m®c“6 tµû¡˜Úãéý¦:·•“Igæg=[cè"ÏgN{ò?Hç¸À<GHì‡ßø $ܱ„À´²`PV:­cIJkY¥ ]í~ ¦öe—e¦‚ËÕy4Ÿ¯Q´Ñ%úé†åw&ûZUUÒ]ž¨ t%w’æU=÷EQußÂèD¶æQ~?²á纲;L‚‘Çö¦•™²ÒÈj9MZ¥ d]í~d¦ö2ºP[/Q$ÛçÂS¦^gÚó'÷¡îæ‡<ý~Lº‡ лéP¸žßÛ–‘DÇÊŽ§^q§‚ö;•“
+endobj
+1705 0 obj <<
+/Type /Page
+/Contents 1706 0 R
+/Resources 1704 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1634 0 R
+>> endobj
+1707 0 obj <<
+/D [1705 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1708 0 obj <<
+/D [1705 0 R /XYZ 56.6929 748.5056 null]
+>> endobj
+1709 0 obj <<
+/D [1705 0 R /XYZ 56.6929 748.5056 null]
+>> endobj
+1710 0 obj <<
+/D [1705 0 R /XYZ 56.6929 748.5056 null]
+>> endobj
+1711 0 obj <<
+/D [1705 0 R /XYZ 56.6929 743.7078 null]
+>> endobj
+1712 0 obj <<
+/D [1705 0 R /XYZ 56.6929 719.6381 null]
+>> endobj
+1713 0 obj <<
+/D [1705 0 R /XYZ 56.6929 711.8197 null]
+>> endobj
+1714 0 obj <<
+/D [1705 0 R /XYZ 56.6929 697.0552 null]
+>> endobj
+1715 0 obj <<
+/D [1705 0 R /XYZ 56.6929 691.8868 null]
+>> endobj
+1716 0 obj <<
+/D [1705 0 R /XYZ 56.6929 665.1671 null]
+>> endobj
+1717 0 obj <<
+/D [1705 0 R /XYZ 56.6929 659.9987 null]
+>> endobj
+1718 0 obj <<
+/D [1705 0 R /XYZ 56.6929 635.929 null]
+>> endobj
+1719 0 obj <<
+/D [1705 0 R /XYZ 56.6929 628.1106 null]
+>> endobj
+1720 0 obj <<
+/D [1705 0 R /XYZ 56.6929 601.3909 null]
+>> endobj
+1721 0 obj <<
+/D [1705 0 R /XYZ 56.6929 596.2225 null]
+>> endobj
+1722 0 obj <<
+/D [1705 0 R /XYZ 56.6929 569.5028 null]
+>> endobj
+1723 0 obj <<
+/D [1705 0 R /XYZ 56.6929 564.3344 null]
+>> endobj
+1724 0 obj <<
+/D [1705 0 R /XYZ 56.6929 549.6297 null]
+>> endobj
+1725 0 obj <<
+/D [1705 0 R /XYZ 56.6929 544.4015 null]
+>> endobj
+1726 0 obj <<
+/D [1705 0 R /XYZ 56.6929 529.6968 null]
+>> endobj
+1727 0 obj <<
+/D [1705 0 R /XYZ 56.6929 524.4686 null]
+>> endobj
+1728 0 obj <<
+/D [1705 0 R /XYZ 56.6929 500.3989 null]
+>> endobj
+1729 0 obj <<
+/D [1705 0 R /XYZ 56.6929 492.5805 null]
+>> endobj
+1730 0 obj <<
+/D [1705 0 R /XYZ 56.6929 467.136 null]
+>> endobj
+1731 0 obj <<
+/D [1705 0 R /XYZ 56.6929 460.6924 null]
+>> endobj
+1732 0 obj <<
+/D [1705 0 R /XYZ 56.6929 436.6227 null]
+>> endobj
+1733 0 obj <<
+/D [1705 0 R /XYZ 56.6929 428.8043 null]
+>> endobj
+1734 0 obj <<
+/D [1705 0 R /XYZ 56.6929 414.0996 null]
+>> endobj
+1735 0 obj <<
+/D [1705 0 R /XYZ 56.6929 408.8714 null]
+>> endobj
+1736 0 obj <<
+/D [1705 0 R /XYZ 56.6929 382.1516 null]
+>> endobj
+1737 0 obj <<
+/D [1705 0 R /XYZ 56.6929 376.9833 null]
+>> endobj
+1738 0 obj <<
+/D [1705 0 R /XYZ 56.6929 350.2636 null]
+>> endobj
+1739 0 obj <<
+/D [1705 0 R /XYZ 56.6929 345.0952 null]
+>> endobj
+1740 0 obj <<
+/D [1705 0 R /XYZ 56.6929 321.0255 null]
+>> endobj
+1741 0 obj <<
+/D [1705 0 R /XYZ 56.6929 313.2071 null]
+>> endobj
+1742 0 obj <<
+/D [1705 0 R /XYZ 56.6929 298.5024 null]
+>> endobj
+1743 0 obj <<
+/D [1705 0 R /XYZ 56.6929 293.2742 null]
+>> endobj
+1744 0 obj <<
+/D [1705 0 R /XYZ 56.6929 267.8297 null]
+>> endobj
+1745 0 obj <<
+/D [1705 0 R /XYZ 56.6929 261.3861 null]
+>> endobj
+1746 0 obj <<
+/D [1705 0 R /XYZ 56.6929 199.468 null]
+>> endobj
+1747 0 obj <<
+/D [1705 0 R /XYZ 56.6929 199.468 null]
+>> endobj
+1748 0 obj <<
+/D [1705 0 R /XYZ 56.6929 199.468 null]
+>> endobj
+1749 0 obj <<
+/D [1705 0 R /XYZ 56.6929 191.7053 null]
+>> endobj
+1750 0 obj <<
+/D [1705 0 R /XYZ 56.6929 176.9408 null]
+>> endobj
+1751 0 obj <<
+/D [1705 0 R /XYZ 56.6929 171.7724 null]
+>> endobj
+1752 0 obj <<
+/D [1705 0 R /XYZ 56.6929 157.0677 null]
+>> endobj
+1753 0 obj <<
+/D [1705 0 R /XYZ 56.6929 151.8395 null]
+>> endobj
+1754 0 obj <<
+/D [1705 0 R /XYZ 56.6929 137.1348 null]
+>> endobj
+1755 0 obj <<
+/D [1705 0 R /XYZ 56.6929 131.9066 null]
+>> endobj
+1756 0 obj <<
+/D [1705 0 R /XYZ 56.6929 117.2018 null]
+>> endobj
+1757 0 obj <<
+/D [1705 0 R /XYZ 56.6929 111.9736 null]
+>> endobj
+1758 0 obj <<
+/D [1705 0 R /XYZ 56.6929 97.2091 null]
+>> endobj
+1759 0 obj <<
+/D [1705 0 R /XYZ 56.6929 92.0407 null]
+>> endobj
+1704 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1762 0 obj <<
+/Length 2542
+/Filter /FlateDecode
+>>
+stream
+xÚ¥Z[w£º~ϯð£½Ö˜Jqé›'Og’ÔÎô´kÎy ¶â°ŠÁœ9s~}·Ð‘<=]yH>Øß¾c<Að‡'1õI‚I”E˜N¶‡+4ÙÃÞý–2s%47¥®Ÿ¯þrG¢Iâ%¡Nž_{ÅŠc<yÞ}›.žžn–«Îæ>EÓ…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.-#€Œ‘%d8ú·õÝ (Šü6ÄÄyqÏï
+ÔÆCùÎ/¬g8‰#Ϫl Η6äP·!åP¸’Ò*§$r¨Üm(}ˆmQ» ~S¥T¼¶¼eÚ¤âè.Ë™8º)‹_ò÷'ÁƒX¼­ªŽ§œ¦*@™A>O3ì'SÉÇ5cUéÜ{Ü6¥AFB¬d„ †t!T™Rv2´”&#Á¾ 'tGÆö8=ðQ2tHséÅîÏRâcê…qì÷)Y*6ÒÊô;öRÍâé)­~hFB;#¼9EñF )#JJ1â#ŒŒ¸  F†ØFLð3åßTYêLºÇk)u]–Œ(éAz̆UשׁG£Tƒ ÆaŸ‡kÉ×´(²b?`»ç8ÿ˜Q:Í~ϘÅs<>Â_ ©r°$…4I>N$9p ŽÀŠ 䯵Twù:pœEž¥5«L=°æ{Yý»£(Û²qŽÂØ‹ü Ï$ÓC–7Êé4Ik¹ý ÷£*Û¿5‚"Ù+æ>I<J¡®˜¾"¬pU€ÍÒ³?˜3“&7;k@£Ä‹¾P)˜RvÖµ”¦=ö©v'tÇûö8ñ=ð¼yNŸgc``Ÿ·z #P¾¦ì寳9 ü骮O­ÀNk#pÍ
+ÇÄ¡V"l·Jäë‘¢š7&vᨒ׷„°FœEÄmÊm™E]â'B‰™`µ¸÷ÕHëÖ&&s-?¦! }™fðŠÊ S“}„Õ×iya] ½r°.…é$HÙ…kp>
+‘gDDvXýZdüR±(’>¬Ž%PØ×q#êâ,«%7æ-y¨^ôB0WD¡õˈ…§JøŸrö³:û ¸ÊY'ˆŒ¨2”¨‚æËÓF @¨µ> ‡ÐÈ¿P˜R3RRº›‚ÐaF.hÃŒ†Ø32Á¿Ö­uˆ]Vçê(•:_Ýü
+”vйQ`Å­cCÊ¡d%Õi9q¸ŠÚPóÛ¢g\ëss:˪¨ûs™îÔˆ€'+‹¾Ià…1Ì{žy'¤ UVo•ÒÇ*˵Ʃ]ã~ì¡(¾0ê1¥WR]Ï8êX'´¡ñ!¶Eã&øBj–íÕdá:­³3;txª±ÍKQÎŽŽÓ> zløÓô´Eé˜éÛ EðÂñ…v”r¡¤4$pt‘Nhƒˆ!¶…\g„P×
+9±ôIŒ»©Òï¯bF²SÁà´?Õæ!±ò
+endobj
+1761 0 obj <<
+/Type /Page
+/Contents 1762 0 R
+/Resources 1760 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1634 0 R
+>> endobj
+1763 0 obj <<
+/D [1761 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1764 0 obj <<
+/D [1761 0 R /XYZ 85.0394 748.4854 null]
+>> endobj
+1765 0 obj <<
+/D [1761 0 R /XYZ 85.0394 748.4854 null]
+>> endobj
+1766 0 obj <<
+/D [1761 0 R /XYZ 85.0394 748.4854 null]
+>> endobj
+1767 0 obj <<
+/D [1761 0 R /XYZ 85.0394 743.3452 null]
+>> endobj
+1768 0 obj <<
+/D [1761 0 R /XYZ 85.0394 728.6405 null]
+>> endobj
+1769 0 obj <<
+/D [1761 0 R /XYZ 85.0394 723.1655 null]
+>> endobj
+1770 0 obj <<
+/D [1761 0 R /XYZ 85.0394 708.4607 null]
+>> endobj
+1771 0 obj <<
+/D [1761 0 R /XYZ 85.0394 702.9857 null]
+>> endobj
+1772 0 obj <<
+/D [1761 0 R /XYZ 85.0394 688.2211 null]
+>> endobj
+1773 0 obj <<
+/D [1761 0 R /XYZ 85.0394 682.8059 null]
+>> endobj
+1774 0 obj <<
+/D [1761 0 R /XYZ 85.0394 668.0414 null]
+>> endobj
+1775 0 obj <<
+/D [1761 0 R /XYZ 85.0394 662.6262 null]
+>> endobj
+1776 0 obj <<
+/D [1761 0 R /XYZ 85.0394 599.7666 null]
+>> endobj
+1777 0 obj <<
+/D [1761 0 R /XYZ 85.0394 599.7666 null]
+>> endobj
+1778 0 obj <<
+/D [1761 0 R /XYZ 85.0394 599.7666 null]
+>> endobj
+1779 0 obj <<
+/D [1761 0 R /XYZ 85.0394 591.7571 null]
+>> endobj
+1780 0 obj <<
+/D [1761 0 R /XYZ 85.0394 565.0374 null]
+>> endobj
+1781 0 obj <<
+/D [1761 0 R /XYZ 85.0394 559.6222 null]
+>> endobj
+1782 0 obj <<
+/D [1761 0 R /XYZ 85.0394 534.1777 null]
+>> endobj
+1783 0 obj <<
+/D [1761 0 R /XYZ 85.0394 527.4872 null]
+>> endobj
+1784 0 obj <<
+/D [1761 0 R /XYZ 85.0394 502.0427 null]
+>> endobj
+1785 0 obj <<
+/D [1761 0 R /XYZ 85.0394 495.3523 null]
+>> endobj
+1786 0 obj <<
+/D [1761 0 R /XYZ 85.0394 420.5376 null]
+>> endobj
+1787 0 obj <<
+/D [1761 0 R /XYZ 85.0394 420.5376 null]
+>> endobj
+1788 0 obj <<
+/D [1761 0 R /XYZ 85.0394 420.5376 null]
+>> endobj
+1789 0 obj <<
+/D [1761 0 R /XYZ 85.0394 412.5281 null]
+>> endobj
+1790 0 obj <<
+/D [1761 0 R /XYZ 85.0394 388.4584 null]
+>> endobj
+1791 0 obj <<
+/D [1761 0 R /XYZ 85.0394 380.3932 null]
+>> endobj
+1792 0 obj <<
+/D [1761 0 R /XYZ 85.0394 365.6884 null]
+>> endobj
+1793 0 obj <<
+/D [1761 0 R /XYZ 85.0394 360.2134 null]
+>> endobj
+1794 0 obj <<
+/D [1761 0 R /XYZ 85.0394 345.4488 null]
+>> endobj
+1795 0 obj <<
+/D [1761 0 R /XYZ 85.0394 340.0336 null]
+>> endobj
+1796 0 obj <<
+/D [1761 0 R /XYZ 85.0394 325.269 null]
+>> endobj
+1797 0 obj <<
+/D [1761 0 R /XYZ 85.0394 319.8539 null]
+>> endobj
+1798 0 obj <<
+/D [1761 0 R /XYZ 85.0394 295.7842 null]
+>> endobj
+1799 0 obj <<
+/D [1761 0 R /XYZ 85.0394 287.7189 null]
+>> endobj
+1800 0 obj <<
+/D [1761 0 R /XYZ 85.0394 272.9543 null]
+>> endobj
+1801 0 obj <<
+/D [1761 0 R /XYZ 85.0394 267.5392 null]
+>> endobj
+1802 0 obj <<
+/D [1761 0 R /XYZ 85.0394 252.7746 null]
+>> endobj
+1803 0 obj <<
+/D [1761 0 R /XYZ 85.0394 247.3594 null]
+>> endobj
+1804 0 obj <<
+/D [1761 0 R /XYZ 85.0394 223.2897 null]
+>> endobj
+1805 0 obj <<
+/D [1761 0 R /XYZ 85.0394 215.2245 null]
+>> endobj
+1806 0 obj <<
+/D [1761 0 R /XYZ 85.0394 149.4956 null]
+>> endobj
+1807 0 obj <<
+/D [1761 0 R /XYZ 85.0394 149.4956 null]
+>> endobj
+1808 0 obj <<
+/D [1761 0 R /XYZ 85.0394 149.4956 null]
+>> endobj
+1809 0 obj <<
+/D [1761 0 R /XYZ 85.0394 144.3554 null]
+>> endobj
+1810 0 obj <<
+/D [1761 0 R /XYZ 85.0394 120.2857 null]
+>> endobj
+1811 0 obj <<
+/D [1761 0 R /XYZ 85.0394 112.2205 null]
+>> endobj
+1812 0 obj <<
+/D [1761 0 R /XYZ 85.0394 97.4559 null]
+>> endobj
+1813 0 obj <<
+/D [1761 0 R /XYZ 85.0394 92.0407 null]
+>> endobj
+1760 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1816 0 obj <<
+/Length 2121
+/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<hëž›8ÍÇ—Sç!ÞHÕbÎâPVrƒ£G©™ùÏJæeZäÚL'»c!%Aø°.%û¯Àâ gF k\VYü.Ç g\GìÆ,t–¨'ÎMãÆЉ÷o›87R>Çù>Þ”VØr­hÒÀúà\¤=ê’ê
+›ª‹†ªÃ~4¨úˆÆ™îN8Zº/Û¿h†ý($Š¼ÿƒ_bÝMÖ Q?~H"\ÈK6Õ
+¸÷‹Š{Jð/qYÊŽéZA/‰E©¢
+\§Il‡·îLx‹j
+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ý²©Î“ ì‚
+ÓÙ„õç‘A­Ç<r¦¶3´´b¡žq+êÛ–²íC@ …ñç)ÞgÈ4ÍàÂõlj¤8Nš¼ëøýût¯™ çö°KWk\F,an¨þ^¡æ9Á%@?.aÂIàG°O‹îe^×å€ÃúúdQâÚò5.«b[èhAöfúwœyüË3¤™yÂçžÒur¥kª‘)\+’ÎrÙ[tÀaUuàE›cýÿ/eU/aßU„f¿^”6 ågK¯ÿÁ:_ûøpÚendstream
+endobj
+1815 0 obj <<
+/Type /Page
+/Contents 1816 0 R
+/Resources 1814 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1634 0 R
+>> endobj
+1817 0 obj <<
+/D [1815 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1818 0 obj <<
+/D [1815 0 R /XYZ 56.6929 749.4437 null]
+>> endobj
+1819 0 obj <<
+/D [1815 0 R /XYZ 56.6929 749.4437 null]
+>> endobj
+1820 0 obj <<
+/D [1815 0 R /XYZ 56.6929 749.4437 null]
+>> endobj
+1821 0 obj <<
+/D [1815 0 R /XYZ 56.6929 746.6461 null]
+>> endobj
+1822 0 obj <<
+/D [1815 0 R /XYZ 56.6929 722.5763 null]
+>> endobj
+1823 0 obj <<
+/D [1815 0 R /XYZ 56.6929 716.7581 null]
+>> endobj
+1824 0 obj <<
+/D [1815 0 R /XYZ 56.6929 701.9936 null]
+>> endobj
+1825 0 obj <<
+/D [1815 0 R /XYZ 56.6929 698.8254 null]
+>> endobj
+1826 0 obj <<
+/D [1815 0 R /XYZ 56.6929 684.1207 null]
+>> endobj
+1827 0 obj <<
+/D [1815 0 R /XYZ 56.6929 680.8926 null]
+>> endobj
+1828 0 obj <<
+/D [1815 0 R /XYZ 56.6929 656.8229 null]
+>> endobj
+1829 0 obj <<
+/D [1815 0 R /XYZ 56.6929 651.0047 null]
+>> endobj
+1830 0 obj <<
+/D [1815 0 R /XYZ 56.6929 636.3 null]
+>> endobj
+1831 0 obj <<
+/D [1815 0 R /XYZ 56.6929 633.072 null]
+>> endobj
+1832 0 obj <<
+/D [1815 0 R /XYZ 56.6929 609.0023 null]
+>> endobj
+1833 0 obj <<
+/D [1815 0 R /XYZ 56.6929 603.184 null]
+>> endobj
+1834 0 obj <<
+/D [1815 0 R /XYZ 56.6929 579.1143 null]
+>> endobj
+1835 0 obj <<
+/D [1815 0 R /XYZ 56.6929 573.2961 null]
+>> endobj
+1836 0 obj <<
+/D [1815 0 R /XYZ 56.6929 558.5914 null]
+>> endobj
+1837 0 obj <<
+/D [1815 0 R /XYZ 56.6929 555.3634 null]
+>> endobj
+1838 0 obj <<
+/D [1815 0 R /XYZ 56.6929 540.5988 null]
+>> endobj
+1839 0 obj <<
+/D [1815 0 R /XYZ 56.6929 537.4306 null]
+>> endobj
+1840 0 obj <<
+/D [1815 0 R /XYZ 56.6929 510.7109 null]
+>> endobj
+1841 0 obj <<
+/D [1815 0 R /XYZ 56.6929 507.5427 null]
+>> endobj
+630 0 obj <<
+/D [1815 0 R /XYZ 56.6929 477.5928 null]
+>> endobj
+1842 0 obj <<
+/D [1815 0 R /XYZ 56.6929 453.2532 null]
+>> endobj
+634 0 obj <<
+/D [1815 0 R /XYZ 56.6929 369.7201 null]
+>> endobj
+1843 0 obj <<
+/D [1815 0 R /XYZ 56.6929 345.3805 null]
+>> endobj
+1844 0 obj <<
+/D [1815 0 R /XYZ 56.6929 310.6805 null]
+>> endobj
+1845 0 obj <<
+/D [1815 0 R /XYZ 56.6929 310.6805 null]
+>> endobj
+1846 0 obj <<
+/D [1815 0 R /XYZ 56.6929 310.6805 null]
+>> endobj
+1847 0 obj <<
+/D [1815 0 R /XYZ 56.6929 310.6805 null]
+>> endobj
+1814 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F39 885 0 R /F14 729 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1850 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§F<e&·ÎÅÍÅr¹s]¸•ÑY x¦•|æbS–Y!U1 (s–ei~¸º
+¸*+WW>2e™äé9æ÷ÿævµè‰B¯7Y6KÿÝm³ëÿtÉÙù?®Š}Ad©X.¸:Çë¯âõ‡öÀûyÝi
+O3i_Üüá*Ü×ͶXüú€ZÿúÝ&sÎtÎí9´FöÁgDr®¸ßÏW„Ž¼hŒ8öN'?önwhÚž1öp)öU*™NʼnýSˆË±?pc?Ù\ÍHfs•þÑN ~G´È5m]5E•Œ¬˜9X6šõJö}ÿáË»ÜþýþöóÝÀ=Jþ#P“ÿË
+! ˆ(ñ7|Ùl‹²†B ù¼¬WÍn[ôeƒ•Ï×»‘Í›Öí€U¦ŽÖ
+š~ã\¹ŸåcåˆÜ7ME+€a{·#¤5€×kâ¤Zë>¦=‰ÒwÇnÅÓùmOT8åꈷy‡ŽºŒü™ê°*"ÖKH,£][‡@î7ŽÈEÝ=Ãq‘Zôa›—5ðиßïj·¤å©²=#-DZ q;2.ááȈ3t€Ò-Ae³OM×Ç‚ª–·•²ò˶¬Ë1ïú]Ñ7^x ï;7á l>Tœ .ݲ1Û÷ ö¤äîµÛ4 ŠnùQŒ––auÛÑÒ£[(…_nVô-û°½„ kþ ,d`…â|O
+³‰1éï\³\«XûXÌΚeyn@Çœ¥iJÿ¦ê7Í~½™8Jè8•ºvµ2eàÁÀUJÎkŒñª:àÌ›{Iôç²ßmÑl·`ý¤*kGkëýÖÕ}‡Wg$\.qU×צè‰æE¿Ûf ü=ãšR7€ÕB¹»ýB(bŠ%%}r¡h©ëCŽ8†(ÎŽ™JVÎç;C´Gˆ½ »=(½;Ф DïÀxÆØ$õÔ$ä½ ··¨X7$̉ˆnw˜‘ßêùóÆÕ4Âtò²È§9Âêp‘ÉfÚ«Lfc@¤OØð]—O®Fõšÿ³®ÊïŽè®ØU¥˜`úEÑÁiJÙMZ3{{÷ž8ò€ºm!øA÷âxR³šŒ x‰¡¾X—Lj¢7ƒw6ÏdµDãÓ*züÛ}Õ—måN£»GòcX,»nïB”Ÿø…âÀ.7€Á ³áÆN‚lF)A‘ïK¥B1”phµ$Š?(¾°© J׺E‰N¸ y,{*Œ›TCV|i@ÉsïyÍ€^5繬ª XŠ2 —Ô«‚QÕ%jUvä–¨e=á‹Â&¤ˆêk×/^à ª©žb*Ëàá$@º‘¿/šz5!÷¸Ñ‘82ÿ¿(Fd ¿éɵ1&ŒÎH>ÀŽc\|a“ŽIëë ³É®Z_Èll}@ ^ñ}Ûßè!0\E᥮þ#:ötM0!ßmzì)¢¡,<ƒyfÇ–ò}“ÍBà§ðëºÐ Õ;(P;ØZêG¨;ZZºUÖÑ:
+7Ñ[¤ʘÐ×ìbyíòTSþ*¤Ñ›þüïŸ?}øÏkx»Åb¦˜Í¬ü:5¿ßDU)ÇŸªŸ µƒ8Èa€\Ô¢7…r$sÍ´gõȇ½á'®ƒ“¶…ü¹ŒYÍu\¼œcN‘‚³N¦{ß`Bɺ½£/uµ0x÷‘¾ô{ƒo™1§tDm ¦«¢¥I¨í0ê¯ÂõMK`•{rÑè•ý!`zfó%5YH§Î-œ1ñ³¼eL–ÅBç£ëMÓÙ+5´‚çžy1W±»M—ª¢T£ªÊ!Å¢´¼:Ë/ ðw¿F“™C]ôª^®×"‡¤aÉ~\”,†Ïpî‰4êHi0Fë)šP´ƒ4ʧۻ˜@`eè¡¡„*œžõÐÈøîcäw H¨©Ômá/„íàÍ]tì¦}²÷/açïðãó˜áϲ“íÀ’yèÙÑo#\Ó/U€:q~ÜðïËóþ Ðažƒendstream
+endobj
+1849 0 obj <<
+/Type /Page
+/Contents 1850 0 R
+/Resources 1848 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1857 0 R
+>> endobj
+1851 0 obj <<
+/D [1849 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+638 0 obj <<
+/D [1849 0 R /XYZ 85.0394 769.5949 null]
+>> endobj
+1852 0 obj <<
+/D [1849 0 R /XYZ 85.0394 573.0107 null]
+>> endobj
+642 0 obj <<
+/D [1849 0 R /XYZ 85.0394 573.0107 null]
+>> endobj
+1853 0 obj <<
+/D [1849 0 R /XYZ 85.0394 538.4209 null]
+>> endobj
+1854 0 obj <<
+/D [1849 0 R /XYZ 85.0394 504.6118 null]
+>> endobj
+1855 0 obj <<
+/D [1849 0 R /XYZ 85.0394 432.7569 null]
+>> endobj
+1856 0 obj <<
+/D [1849 0 R /XYZ 85.0394 303.3232 null]
+>> endobj
+1848 0 obj <<
+/Font << /F21 702 0 R /F23 726 0 R /F41 925 0 R /F53 1017 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1860 0 obj <<
+/Length 3824
+/Filter /FlateDecode
+>>
+stream
+xÚÍZÝoã6Ï_ õk•)‘ê}à²ÝMÑM÷6)®EÛÙVbamÉkÉ›¦ýÍp†´$KÉ÷rÑCŠçã7CÉsò<I£4‹³s“é(29_nÏÄùô½9“<fîÍ»£^Üœ}ó2çY”¥qz~sÛ™ËFÂZy~³úuö"’Ñ3˜AÌ^]¾y6ÓDij‹÷ï__½ºü~'†À
+…œ|:ûõwq¾¾¿?‘Êlr~?D$³,>ßžéDE‰VÊS6g×gÿvzÝ«£"ŠUH –çRFY’Ä=$Y”ªX9\_¾{ÿÃkÚ×O×°)ܼ©:²çÐcS÷Ênvå2ßвú\/ó¶¬+ú]ßò<²3ˆ$¦nžUy7²˜4‘V:á1›ºþØД›òcñ-½ »³Î¥Ô‘N@vsiaÿ± ³ÏS8¹5Åþs±§U¾-¨ì#ËÏ“(3&õsÑŽï×ð¾´3Z¿wâ22R¦çišÂ ‰©¢Aóî(w@ÚŽ¨h…K3óƒe³8J«_Ö:]¶·ãÌD‰ÊLÙ…nAJkWl2’ê==/ßSO¾Z‘p~Î~ê]Hmk¢}:û‡gRʘšÊ²ÙÍÚ¯¾Ì+»à÷Ýo·ög=±zÉCVuÛ«9JNU Ôo¨!ŲÜ:¶jVÕ­W_øE{T¼žÂõR¦ô×S¼žš-ëM]ÍWŦܖ°pVØ™Ùì?ë‚G“l Ñv»M ã*&݃QÆD63’MᨠƒT6J­ÎxXîØã}k™F‰ û&¯wwØUËvËÆ•Óc]7-žÖóQë562{Úz•g™%Uo>¼N»ÎyeV
+hÁáÊÙmMƒ‰ät¢¬î¦_bií´F‚JÜòzD”1¸<ÇñˆR%`”O‹2î‹R[%<wî­ús¹*VcrÌdd?)F™¦<fYWÍaÓ6#Î6èûià7E»üfïÁK·#3Cøé(¯VÄ4
+¼,x¤œ:.HbÜ¿)ÒpK‘˜bF2–²/§›5Ýmèç-ÉjëϹ˜8æ°^íêjÕôõxU6»MþP¬¢)OX”@ü¸£î šöÓ~nÐq<XÑŠ(»[Ñ9Y±wh6ÕÓioŲ™Z};èòvxpeº$Ã[ e毃•R†ˆ\ðèÃnZ̉‰RTóÇåÜõˆ ý(Ü·Û£’~lÑ£¨‡‹ŽËº»hY­
+mý
+´
+¶üV° ñ‹öÇP/À"j{d0„O7¯Zó¼+{MÞT?~Yeaí£æ¢(X¿Áõ¡ë¹;³·NZìj!Õ Ne…Ñ´êe§jír’ ö“\\a«PÓÇ Ødáçz< 
+'C–Ê—Þ–ãQÀ ±d2ªŠTzëp6ÓÖVy°‡E *Ûb‹q’àÓöyÕàþ±HêÊ¿£;41ƪà£Òÿß-¦ìã0 ©Ìöõ0¤J¢»ñ¿‚œ”‘ž×y;…MOs>#|Îg¤ªâˆ¯C)ÈñqP穼ù:"
+˜ù²¥¸œÏµ$ãK@Wvÿ‘£ûuIAxŒU
+÷HωL¢D‚CÇ@¹øù»‘èN‰~¡²ZÒXúq‰1t:¦]wŸ=—
+Âl”õ¹×›±<xXƒ{>V¤T‹ä ­:–TJÆíMÑd?R¥7ÀH¸9)ÿ¸Ýÿãj $X%I:ÆÞ¬C‚2 Y,*îŠèʱEÈ“›ÖO¶\çÕ]ÑøŒÊç9”—ujô&&é­ê¢(pU ªÍYK/¢|Â7sÝ8Í×%¯¼˜®JßçÍÄ¥$êþ(Æ$Ê—¹^ ¤ô)ˆ9ñº[H)¼Ï›·_¥“!4„,Ó»[íw¬îVïV¦Ü-`B@D9N$p§îV¢`æÃ3ÔÌÛÆ~®j~f=”ÍúÈß 2ê
+.ÜXÛmP”>–Å7Äò¼d¸Msá”`bÈÏ‚r
+£L¨¸Â›2Ž¤Šà˜ÊjŽŠåû]>ê|“(ÑÆô®³av½Ò»^q¬$C“¡Ç|qYðw)Ð÷þæ Wr–ÇëçbÙ–Ÿ‹ÿx…f&@
+Žx»k¹|t’†ó
+Giß\_¾AQ?çM@#`£JU¤7ÏøJg]­T;Tˆ8I§r3À-KBnöq\‘¬ºIËlö‹;—­@‰-Úñ¦©‰ÔÙ†¿(êÓeÛ›["’¨Ò£±r™—¨\ë ›ã+‚ òŸ^ŒÕPð«ÔP%z˜¸vé^àŽÿ6u±•øȱÞæËqè"™’ð)ˆYaÆw&®úâ›!=Çoß]¼œ¿{•ŒãX€Yf¡ˆ=Ô‘¥pè'<Q šä‰ZxtüI„³5€\S!ŒÝ ƒ§2'"%Ó.ÔÃD!$`LçS€ˆøO&EÊÕ ó¿Ó,-Â9=ySÌSM}Eµ¬WŸ¼/DûÓÒÖ»áIîŠ
+/ÉpÚQœÀ¬*VË9pcÐ-Zq4õM´ÂRˆû2G„/%þçï¥_ƒk)k'¾ñ‰ $†´™)‡:„>ý–‰¿¬>åý¿
+endobj
+1859 0 obj <<
+/Type /Page
+/Contents 1860 0 R
+/Resources 1858 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1857 0 R
+>> endobj
+1861 0 obj <<
+/D [1859 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1862 0 obj <<
+/D [1859 0 R /XYZ 56.6929 752.1413 null]
+>> endobj
+1863 0 obj <<
+/D [1859 0 R /XYZ 56.6929 501.191 null]
+>> endobj
+1858 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F48 940 0 R /F53 1017 0 R /F11 1367 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1866 0 obj <<
+/Length 2981
+/Filter /FlateDecode
+>>
+stream
+xÚ­Zmsã¶þî_¡o•'
+ázvw¿ú ;£æÕ1
+ÈXÆFöׯŸ»TjùO2ä—Ûû›_¾Ü¬@£ Q±ž£iðÇÖŽvcr\'šàO²,ûGCHèª6Ô‡4<Ù.ãVì+oÛâ’/×[;Á§Üä놞‰’Ðõ–Ú—ÍÆŽmá^ÚUÕóñÅ™`Œ²oíÓ,·Ý†É<q3ê%ÉÕàÎjë|ìâzg++ê—]z"Fƒ»«öø¾HhaÂøºÚvÕycÇ4fu¸nð0"}¢öcaÈ!bZ‘p–‰*Ûæ°‚Ã%x<>’-k¯?Ë›ü°/Jûèð€—j€ÏìíL\Pž®´¬ßÈy°å“1p¬Ê&Ͼ·§¼
+c §‘]×/HDëágp YÆqÞÇ%­i?µåkº;¢Ë\ðÏ;%ìÜÏ9uS&ƒ ÇkÇÓq€YÀ©c„ùDÛôuøâ¦:ìÇÈã N´K ¾£ud?ÛFàLD%QèC€SLzéœØûW²Ì[Ÿ‹Ç’¶þ¯g©2 ˜‚4\É8C%£¹½Zu¥Lf+“‘ÌÖK™U~+«‡fý2TÌP9bïhöRçªÌ‹á`ðî¯x¬þ[†[.!ªêŒåZ÷ŸniÌæÕÐe ¥ÔßÁTÌôS*
+ªŽû-q6`¦4®ÒˆÊ&ýµëmU/ÿ” >í´aHâAÈ´+ñ
+ë4eÈÅ…êS¯“áÙ@¾q|{L×Ïoi¸ Iö/P=»¢9]rÎÑM Îèp Äa(_×ø¿Ë C¨3¡âÐÓ·0jÖÇ¢Á±I¾ĮE¨çùÖ•šæ›—òhBô¨ùç b&óʽԹöAù­ Ñ—¼¯þ5»¬–—Pe•®ö„¢™3#Ob:lÎð>ß$ç <œþ4£qŠ²ÄÌÆ_Fe¬‘AóPã.âÀÇu[‡n„;Ñ™ ’:K)$a2 Ã~!˜f挎3.DBR'Ãæ·´#5³¥NÊliVíÓ¢üóiW^÷ö&Ï[à¥ÎMèï+ØAðî™p‡ ˆ\ª
+Sz¸þrw÷ùµ_Ó]‘¥m!Rmzù qy’
+:¢K§Y&t„¦‰à„Zì&¯ç´¶·ƒCµã—ƒ]½×ô­p*-´Ÿ¡ôÓÏWwwî*6/;à|zèemVä?†LÀ
+ÁD„ïÜ™´2Ó Z™öB±Í>ƒUÊ á@˜­^f¨vðGŽ_¤ºzÿ;Lïïþ?!ê*à_üŒ¬ùðÿóµ6%ñ¯<’‰*˜ „ÐÜ…0q¦†¦û?A:·ýßh @endstream
+endobj
+1865 0 obj <<
+/Type /Page
+/Contents 1866 0 R
+/Resources 1864 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1857 0 R
+>> endobj
+1867 0 obj <<
+/D [1865 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1868 0 obj <<
+/D [1865 0 R /XYZ 85.0394 674.4719 null]
+>> endobj
+1864 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F41 925 0 R /F21 702 0 R /F48 940 0 R /F53 1017 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1871 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
+`<O9aTAS‚2²¬&œfQÆpJ
+F½šX¾¤&G¥ÔôêKÛÝäþ|êåtɘä)#4øb‰»§š³'4`)Mâ$æ«ôÝ=>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Ы•)¢ò<t‡r¨÷fV5TÕ}yßÈʬ`–
+"EK}~’­q¥O-5¥f`ùLp+õ«¶ïeyuÌ×%yîÖ×&ƹðjz5œÊ½\˜‰æ)å‚X2c^-bw`ݽy)¦Ì˹—U:ó{ë\"ÏRT |ÛCªuôTÞC•D.H8 ¾MöžjÎâ‚E
+¸Ícþ¥­GqÖÓ‡–Q’i»>€ýëØbT¤˜d|·9MgŒräá8Øi‡Î<¿"DÚÊ "M
+@ãâ]0ƒ±î½±½&Óè‰wç<ÐE0…lõ KžLQ– ¹ìÉ>ÊoÒ:`=È“wÓÜå»t¡Fà8^»ö|B­{ô]£¿%ÌêF¬¡e=Qz•A·QEÉÇÁ >×P44yy蚦{™<ÈÓ©lz;<Ú<ÓÀæ@d-­Ò8ƒÔÿÔ={A\¤ñŽi*OÈîÏÎwG§C+ôï1<—ý˜‰ì`†«£Èë•:”Vüž ‘f$Û~R­û½§ò~¿?T3¯GP«cz³§š³ŽáÙ…lÂ{ôz¥0aCMŽ§ºLІn
+”]H¹!Õ†aÕh{Ö;ßM0”Ò¬ÀÛü=Õ\€Ø6PfSX,ÁhælÃœmXdæOŠQ2Š¬_GóИ‡ó°%ó Ìš‡…æaÖ<Ìš‡E§ËÛæ`E1»°ë©6Ìã¨FóTU­VW6sûu×’m à©æÄöI)Íc ógáÌ#"ódÎ<" DÖï£}˜°öÆ>bÉ>…³í#¬}„µOæí£ƒ©(Ҍ擊hÃh¸ )b]@´n2G4Z¬iVç¶ØŽgsS¾ËGs!ãOÒÆW¶íYÚ¦’go¾"DËÇõ* u
+®’ñÌÜß.äPŸøÛPðƒ®­ú8‘äF&+¶ˆ' 7øû·­Ö\ëy9-é° 0(Žd0‰ÝdYpØK¹SQ—°2
+Óš8³tüÌÕÿoœ'xL:´Uœnþëvßœ«éᢾŠsPÿ~µòÇ;à«þ-·€´sÎõÿ)oüË!Ë cædO$ã)|,œPJ‰¹ã ”PH»sÙÿn þ¥endstream
+endobj
+1870 0 obj <<
+/Type /Page
+/Contents 1871 0 R
+/Resources 1869 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1857 0 R
+>> endobj
+1872 0 obj <<
+/D [1870 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1869 0 obj <<
+/Font << /F37 791 0 R /F48 940 0 R /F23 726 0 R /F21 702 0 R /F53 1017 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1875 0 obj <<
+/Length 3266
+/Filter /FlateDecode
+>>
+stream
+xÚ­ZÝsÛ6÷_¡™¾ÐÓŠÁ'?òàÔnÎmš¤µÓ»›¶”HÙœR¤*’NÝ¿þv±
+Ì™DI~¿øùW¶ÈAîo/X(ÓD/>C‡…<MÅb{¡´ µ’ÒTw?øoÍÔ9(„Z¨h±âX¦|^M,d¶½Œ ãH(¯&•Ì©ÉQ¡š¾¬ó¦k__o—K&ã‹ášΞjÊZÈk.ã0Qüˆ÷]Ñ].¥Œƒî± FÝoWÅÛQÐlh åsd™ð˜=Ù]CÏl·+.yí©[Ö¸¡Wßè¡‚¥a”(²#û:ÛD5’UÄ¡ˆ"n‰`ýéB\„LIKq=³FJ ›$‚Mã„ê†2GÁÊîaÝÔm™Ã¾y¹ÝϪmª¾+B\}±I
+ÁQå<Lµfå{£7 :*6Y_uÔyʪގ—-=­æ å/Œ‰Ú°nß– µúÁ‘ÙyµU:4Û.ëŠmQÛùN±ŠU–¨P
+ £ nH2ND°u«²s+ªHµvc¥Å‘Ò¾ÙÁ0¨7#-¼;WJï–äsÙ=bK›â3bÝÚ
+…§c—­»b¿£‘Ui(ìB4\e]ùTЛúÀ%«-õ粪hhe@šm[Çõ£YÜ•6àÌÓœ6òf›•uKªl;7eH9=5'aÂcSä¸~œ9+™„p Îj@Š™¥8¸íV"yN®äL+/IUk«)xº¸!dôwÁN<¹u—Q¬Bóô¼ORö©žÊøÔU¿iË?‹×o&^U)P9ñYÞžjÊ|ìUUÆi¤ÇÜWΚ±ñéú#5
+_пÉdÌú QnŒ6gl‰×U€µeSÛ÷ =½sãè+w^engú£Kh/&´¶ €ÑwÖHÏÊBÁ
+Ww[¬'Ç©d""9ÏÜSM¹š8V|ÌþÇ‚ψCÖ þÝÍ×Ôž\^œÒjólM1ÀŒ<»+aÇ@àxÁßÙ¥ú ÓìúüÏ©7#O£Ãìïçd¡3WÜZrT»™dñYž—„.Þ¶1áhêé2Ä(ä?™ÂE“0qCªÓ@ðTmù°~ÌÚ™HG„1¬q–»#šr²ÉX¤rÌþkÃv) ¾p‡&æ¯uÖõÞ4O°.‚v —7âÇVZzW¯i˜V`!n»++ch>ŒÁÖòz¦ ¬ªTªÑN_* ‹0M’d¾ ¼ô+¾ §´b¬–»Û·_ÿëêîæ4@éÂï<Tgðਠº}E§åoÅóë/àÏIÔ‰</‚§šÊ0FEÊÃH¦ÑX“am³0Àä.øÀ¡ª 6ºy@„5~°¦ýeôT/Ã>Èo'£GÆçÊÎì[GcP1S•*Ô©/¦}94#ù±”Ÿ&‡òÔRÀ²7&lE€éïnþëJžp,I*ç‚æC`k. ØÆ8s®£ì\À•0Ò } 1Z”&fá[ô2© nø·Ö+5Ÿ dS¬IË—Y—ù¹’gTMó1ØÌ–u i¹ÏMÅo
+¬Ò ¥r»«Ìw¿ÌÆÌÊ|˜ÞY¨Z þbõ…§îEÛïv¶ĩ¥ª/i¸˜BØ®²‚¡BJcb(@Mƒt[À
+Y€½M0 J~tùÓþ$“TŠ`ÊÉg$2ãó_ûÐûjæ”å܇3®Â4NnVY‡1 ²Àà’¸Kì6;”Ó!üŽs½ sóÕHºGS*Ä!¯_gVúUq¾*Í÷h%ƒã&l1+~®-¥ù¹
+endobj
+1874 0 obj <<
+/Type /Page
+/Contents 1875 0 R
+/Resources 1873 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1857 0 R
+>> endobj
+1876 0 obj <<
+/D [1874 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1877 0 obj <<
+/D [1874 0 R /XYZ 85.0394 179.5067 null]
+>> endobj
+1873 0 obj <<
+/Font << /F37 791 0 R /F48 940 0 R /F23 726 0 R /F53 1017 0 R /F41 925 0 R /F21 702 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1880 0 obj <<
+/Length 1912
+/Filter /FlateDecode
+>>
+stream
+xÚ¥X[sÛº~ׯÐCgJ͉`Üx;oJlçøLŽãFÊ´Ç4 YœP„BRVÔNÿ{X¦$jt:=
+?6öÄ<‡±$>eþ8]èøæ>Ž˜[3mMû«Þ/FW·"Ç$x0^,{º"B£ˆÙ£÷žp2 Ôûíó|1™r?àÔ›=<ÜÜ_ßýÃŒ)¬”zÌî¿Î>¡ìasoöñf>yZü>ºYtÖô-fTS~ŒŸè8ÃQ"âÈï`@ ‹c>^¤/ˆ/…h%Åh>ú[§°7kÿ:ˆ
+ãÑöõJïLÀBéAÏ­ï› yH)ìÆÚS,$A(Ú¦z[d¨ÒÚm­œdYMXäé5Ž0ãÂ~ÆÁÀdœ›×Ø®“ï­de(7,´þ¾ÝÔ¿ü~äÙ
+h´éK›RFÖ ©Z,̼Óá1]㈲àÉý¼¿Qªm›Õݧ.$ŒƒØÙûgý2ŒOâv- ˜]Ð><haHdÿ9€Ï ÒHk’°XD;L]Î Yg3*K6–É äœ{µFi³JšdŽ8ñ£Î3ÉBj׸ó:vò2orë9 ÚÈyƒí:ÉÜJŒtT’®°‡Á$e$½ª =Ã6å¡J & |"ÀœL<´«ÄYa³Ã4…N-‹·Œ²ƒÜö‡ gÖÕ–QÏ°go'd•OŒÎµJJgÇ9¸!£.qÏ UŸΑR7ØÙTyÙ´Û(ìt8ry·RÖaacÐèïÎH8rS.Câ‡"8LPÔ ÔmN“iON“³¤•””ÿϧ©E¬³c 6qIxd˜GJ‚WõÝõ=î>ÿúððùËÄ÷½Å0³s`³0Ä?-Æ/s¹ˆâ6ܘi2ðž' H·tƒm^4xÝîòf…B´Ò]ü2U•‰IÀ¤Èÿ…•Fàezäî¢.“µjïïÀ«·›®šw8²Ñƒ¶»Õ“´-$¯«L²¼ÞÉ¥¥.§.¾ÊÈ?<2³ù‡»;s¼Dg„ ÜQ“¤ª€¬¹„UÐ6¿‰ðrƒŒMUìq»T—ÀýM¦«¤JR
+ aWš½
+Ná¸Æ~<ö¹$
+ÙF¬šDÞ¶¬ÏP- HeˆTËã8¶¹½û„ï»Óº½G¯WªI¯*Uëâ•À _¶iÇ0ˆìŠ¿üû·ÏÜü犀U:d
+nþó{×mEÑÖý¦¿mò"oöçÓ1›ïK½©á|ÑŽ`$Œà1FPQ@å1ðy€‘Ü7—Óð·0šÁ©ìi8å˜îË[ôæ¢yb>N“YQVõb÷úÔŠÒ¡BS˜'l/Ó´HêzðUB,-ÚEÂû…Â'Qà· Xfº9«/Œ~¹¬p»~VƒÏÅ€p.Ù±Ææ¢Æf¿üú!H̨<Ö÷÷‹úvIÞœÕ':}ø ‹‡à­ Â0>N×»´,’—¡]$‘at‚‚ìzëaíbeX <ûnÞ™]™J»£ñS{ûd(M‘ñáÏe<ô ü9h2N2˜Þ~};µý¿p"5endstream
+endobj
+1879 0 obj <<
+/Type /Page
+/Contents 1880 0 R
+/Resources 1878 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1857 0 R
+>> endobj
+1881 0 obj <<
+/D [1879 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1882 0 obj <<
+/D [1879 0 R /XYZ 56.6929 581.7741 null]
+>> endobj
+1883 0 obj <<
+/D [1879 0 R /XYZ 56.6929 460.6765 null]
+>> endobj
+1884 0 obj <<
+/D [1879 0 R /XYZ 56.6929 366.7195 null]
+>> endobj
+1885 0 obj <<
+/D [1879 0 R /XYZ 56.6929 293.4426 null]
+>> endobj
+646 0 obj <<
+/D [1879 0 R /XYZ 56.6929 247.3727 null]
+>> endobj
+1886 0 obj <<
+/D [1879 0 R /XYZ 56.6929 211.2315 null]
+>> endobj
+1887 0 obj <<
+/D [1879 0 R /XYZ 56.6929 172.539 null]
+>> endobj
+1888 0 obj <<
+/D [1879 0 R /XYZ 56.6929 96.3402 null]
+>> endobj
+1878 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F41 925 0 R /F21 702 0 R /F53 1017 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1891 0 obj <<
+/Length 4197
+/Filter /FlateDecode
+>>
+stream
+xÚÍ[[s㸱~÷¯ðÛ‘«F\\xOU¼3³'Yïdìœl*›Z¢,ÖJ¤F¤ìx}ú¢¨ÕlååÌ<j‚@£Ñýõ°¾Vð__»$R6¯³<Ž¥“ëÅöJ]?ûﯴô™ûNóa¯o¯¾ùÎf×y”§&½~\ Ær‘rN_?.ÿ9»ýôéãý‡»Ÿnæ&Q³o£›y¢Ôì‡Ûû¿Ýþ…iŸnr3»ýþãþL v2Ø-U³?þøðxó¯Ç?]}| Ü 9ÖÊ"+_®þù/u½Æÿt¥"›»äú~¨Hç¹¹Þ^ʼn’ØZOÙ\=\ý5 8xKŸNI ±.JœÉ&D`ôµÖQž$æHI¥ÖX’Á‡ï?ß}z¼ûñWCßôbS×s“EF©Œ:¯›¶“^vÐËèÈÆ:cŸª½™ÃJf?Új»Û”Øv³CWmªî_¬š=7våÚÛª~æßiš_»ämr;»ëx?~ ß›ŒvhË%·º†Ÿ‹¦~)÷òQ]lËöøýÝ'ás¹Üßh7+ÛºÀâ`ɼžy,«¨a|“ºÙKµ(¥UîÛ¸³©ý}]ÖL­~4êóa[Ö]Ë$\1=w]ÕÔí° ™Íž«—²~7± }‘Š“X„|n# ìpâwb·¯ÂÔ?Úuƒ"¡æa»-öo<o³bbåû/x Kfydh4Úx‰°õlªºd+/I$.hÈZ#æ6±ÇÊ¥ó(ÎD¹p¦Ö WÉ@¹ŒV³n]rcÙl‹
+%¯5 ¯‹Ž[჆û<IÔ-Ôlv¤b©EÍbÓŽ¾+ü´]W.çËrQ2íîÓKÌ*ůhãû¯ͦ©ç"[^Þ‘®-ËMµ­:äÏêN±• ~kg¸v|óº®kî¾(ÚrBƒtf¢Øä(ÑÆKûµÚlx̧7žfY®ŠÃ¦c¢.ÿ(¸³‡–Q2˜ÛdòØàý­hJE@Aâ(õH@m¹‡)&ø·y¤u¦Úb ð†B2™è"îQZË/Dèê?-+Pµ=ÓHéÈŠ†­F^!˜Ð˜Ã§«³ßÊ"äuÑMì™Í²“ {6-x›,ÕÇæ ¦~؈~9”déЬê¶+ oœ+~²9AÃóD/÷CšØõ¦jI/y(æ&>*›F™GÆ<Sv‹oöeÛl^"@äÕÿ°Æ4ÖV>ˆØ,¬5‘udŽ^>®Ë‰)¡‡N3/¥y11‡Ž£8Àø³J¸xè!Hɪd¥å—CõRlH9HFGב¯ò‚›`(«Â’æ/92 ³hÁ‰NÕ™H[m.˜²Ž\’ù <÷ÛâÚ'ª´ám'}nïÿq£Ðü¦À˜iœ»cÜf×gµ=#8…„ðD„ñ~J æ™ŽGÂÀ!Éá‰þ}Ê/‚¤•±æ"ªÅ.Ö#T³³@|»ë„ùŸf¶¬ÚݦxëWD‡o¹Áæ½hè¹îØììצ.'`Ì€à@Ž Îyº Ö’ùµ¬h†f+¬zžEÆ`õ
+Æ„µ#£·OkâYqèÀÝW]ÑATÁ$>IoÕHfþ¡!À -\ Fºàc×ò5Î_3¬õãÅÇã1z¢»øY)S{†È‹Ð,òFzØo,T\ :†3qé!Ú ]5o.+XÍx ~°¯Á‘<øŽùbZOMœÕÔjBÕý D¸ €¬e¸À7lpH)˜@á-6Ðònôì‘Dá¹Øm;¥BZEn7O>èv¬Cyä\ÀBÜÀÄÀr+áŠ"œæ©ä'ÇÍC†ƒÃÚ˶j–ÂàÞƒIä´ƒï×EÓÖ¥lsGMq‡Í‹rH ŽA4ÄE~ãB˜1ÌcóÝ=?Èïê®ÜÃ̈æ£Íf|ú?‚°rÿÔ´4<ćnwè¸ÍCBä]Öå¾ß–¡ªN„P^$IP‘óÀ›Іƒ$;‡Ž6JÁ_x­[N»ŠD§^ëöSš SÚ$½ào`}âoz  *D¼×²Àók#" ) üX`6ð“â%
+G•vœœá$¢A""ëí7·ðq•ˆw+~‚ý=UäÕñèüzÊ’2TF“^ËMòŠqÎrDaÛ“sQŠÕ°#ô$ºM¢A$›pgü> —ô†UM1
+ûgÕ8ZÇÊR»+F9¡¾D
+¾:Ê…‘ -þŸëP˜Ý#å¸Å£K'%.&Ò.cãîSÝÝ?ò_ ¡š–|ÞÇ_¿G‰³Ù±vU’v|þî½v`L¿åŠ½ÿõÙÄÁ
+rrû™«¥¿CòFE*f9¿Ÿ¹l–œÄ\±ÅD £šØÇ“@ªÛ'J©HЖMß‚[ ± "ún>É >­EðI‡<ã|
+*o@ïÇ.Äï È|ðw>£m’ÄÌÐâØáÐ2vPŸ’5
+›-¤ %—Eh¸É<?É`wC©èwçùï ]aJÍjÅSRu‚))šÙÄF¢±cqÇƉ£r>h)8ùììž Áø’p‹Z«ò•áÞ‰¶`«rp@ 2e4q|leø’ÉI³R÷³0îÒtoÆ1RÁ³-y‰‘fïçã)|¶7J†ØÖ§K2ã‚ŽŸã¸¨ê¦Ø®pegK;`þËÒ&ñ9Å°
+îï½ðTÛËß:æ™Õ)I!Mããm «çµøcq,„‰Fêp¢—Ål…¹Ÿ*ç ŠPŠCaaÝ«àÏ}©;È9‡(O8mÇ÷¬_UP"<‚ïÞÉÁ¨EÎøô5•“b_‚‘*ïíOß}îÏëü<eÛµ¿'ÑÏ!— Ú<ž®H¤‰>©íegR{mT¤mª/ßÎHÃôd-V$QÖ&óÙ4ä&A֟Αd²kö”ÉdæÜé@,”Ãæéÿã5¦>¶1xY*PìPõ+ÿ=[Ä.:vÓbp&=9u’>:'‡#Æ1~"…ÍÛìy ¬"ímWNÅþ:K#•…*(°N^uÉœö(÷Pœä‹SÉ7æÆ×ÇžëêWæð„‰ÿE4ÏfïïoøøŽÉXd$Lâ¢Q,üðã-u4³‡»ï¥õç|þK?õ PÞ@î‡x¢óÉNÚáX1þ(ÙIM(}½lò<Trwêuû˜a[4 íSËSÂ_±“c†Ý¾‚”J„‘Û(NM>­}¸õ´¥ó²òo…4ÈQA:±¸×r“ÓxxÇÍgXG•&× ñÃOÜgTìÄny>{:È°Tqù¹ã
+GV÷æþþŒžŸO8ä+0€¹uF{d—[y¤“Þç’6•SÄÔgÖ_ñ˜Ûdb}6‘²ö«V“æ¢ð #¹Xn3}âÍGœ| ãZHc\¥NG÷t€KÏ6_Í^À²é
+Ķ+öq*º9PÂ_Ÿ@_ÏS™þXØ 0,Q¡:?0y! ÆYÖËpæ¿'_lüùþfÓ¼Ž¿ë+]I 7+ÿá0ÇX¢Œž¥Ê=—tåðmlœ¤™;{Ì5
+SqEZ ?_ ‚+W)°QðCj&Lð“b¹ÚL„¦î•6|Vg1fÊáy-ÓLgN‰‰²4ä8ó¿Ÿ9aqý ËäÁ"ޟʳpPózn˜ôCèÐT`Úÿ&Y”¤yòõ¬`‚åž;êK5øÇ`ð_{Ž5‘w¯L®üz2ªødy ÄÞÓˆcB®Ú‚íÕdwI’O— ÑX8ûªQÇìl#ØDEµš[.~zÛR¿.ªQ¿0ÖÙ0L[Êk¾ßAcø7Ⱦp/—¸¬=[M"[÷[J2c%x¹þÈ]ô.'•( ;ËE:M/c¥1#°ÄÁËZÍŠëØ dÞ2]êƒÛ’«)B >ÿîMU®Ä:£‡NbôЃÁñÐÔ(øxƒX‰|ã¹Ì$šKic7sA¨6NŸKÿf5Q?ƒk¹?!÷(ÊÿiýmÀWÛÃVnÈÒð*•‡aÔ­g?=@rÝõ7/Îü „Å3;õ *üQÂý÷ýŸÄHÑ™þOŽŒ[A˜dsí™B k•YIqÊû
+endobj
+1890 0 obj <<
+/Type /Page
+/Contents 1891 0 R
+/Resources 1889 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1894 0 R
+>> endobj
+1892 0 obj <<
+/D [1890 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1893 0 obj <<
+/D [1890 0 R /XYZ 85.0394 751.6872 null]
+>> endobj
+1889 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F53 1017 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1897 0 obj <<
+/Length 1971
+/Filter /FlateDecode
+>>
+stream
+xÚ½XKsÛ8¾ëWè6RÕÁƒ £ËYÍdl¯¥líV&Z„$ÖP¤†¤œñüúm
+ðäæn¹œn–·÷¿ý:ÿÏ4 ±Àr2{x˜ßÝ,þ= (Ç ÚO~›Ý}ž}2²‡©¤“ÙÇùrúuõËh¾ê<ë{O0Óný9úòSØÄ/#Œ˜|ü ^0"RÒñ~r†xȘ“ä£åèŸÁÞlû©7#Ê"ê e¾pp‰"S:«Ò›xw’ž*‹a(Á¾Ö j£2°F8â”
+«Rš¬,¦ãbÒ¨<w_ôÂV¤‘ýbWÖQb²¿2E’…ÎlQ6¾¥#$Â8¶:Mi–­U‘Z`OíàÏ£ª^¬¬ÌÉI¡þjŒ¨HöªVÕ³ªÌ{¶1Ϥxq–O“Õ”ˆ‰ªe‘ÖFò-kvöíë8 T"΄€A’sÚº¹œ?N9Ÿüëv‡“ÙÂVÒÉ\­~6¢o»l½3ì6ÏÖé“:8S[A¹1Ï¢¬öInÆus|X/óÖ}-yR»ä9++íjÝÅà¦@Yz¥ˆD$Š»zØû’¢0ä.që¤p šç±V©ÝLiÝTÍÙîöj_ê|ýdkÅ©z:n·Y±5¯¿cÌ’­-0Þw²j2r…Q©uY¥WG"âܪýì±B¥fŒ+3±¸«ç¤H=† pŒÇÎRS%kŸ%(!\èP×:]ùlÆ“ E„@»Ã&C†M÷.nîLP–ŸîÛ[yìCŽ)‡7l p±ñt§€žÂâ¢9‡~(lFœR¢Ë“Äc¥³ µötÌòÆM[h¡qD¿cŽ³¢QU‘h´Hòìï¶(`*-÷Ifè~UbfêãáPVnN2kÝÔ('ëµ:X¡N±–Õ‡<y±æÊ"0É
+!*uð¥Öå¤. ¨1Æ`wP}˜ª6š¡gqLˆèµÏ¸
+‰‘ˆH4,L·Òðì‹o;Àz¥!ômø¼;Ū©˜‹Ú·€´(Œq<„ÛÛÅ'ÃùÎ~†¯ïT³~Wµç.‚ßøVÀCËËùÜìoöiyÿ6‚§ÙVƒ)Ñ0iiƒFƒT …öv"FnÍ".wL(/n›u­ÖAZoªrÿ‡zqeó¨Õ¾Óhãw b/…ñëdÈ4¾6fNmJc32´ÛŽ—æùøhž[U¨*1TÒp…2ÿžè½å¡ÎêódÁÍà }@ü— ˜’”ëÚÏ­õ‡P¢}—ç¨u§u ˆbý%xöñªé´tD!Ž—ûx¹&
+]uI7¢Ý(ñ¬¢û-ìxM’o}À&à
+£áàý&ËÕ«ñÅ.XšˆoÏÄ•ø:­×ã —•kqÒÝðaÿ÷( ÖsC¶ºÎ“ºþþÊHß4˜Ø{ý£’„9ßE!´à°! Å †0JHvëÍ|ùáqñ°ZÜßyüé<ÐtA‚#(0ÇJËcs8¶œŠrË h4¹Q¹Ú:`‰e¶-ZVc š7KË8A×ÝšŽí`­Œ–‘® ÏJO_>>:†O»®£V¯el0ýxûÁXÄ…ÙkÃ8p»Ðó
+n1{wïäø¤§6É1oήéew×µ—ß²Ù]®Y¤'åQ—*o€Êgáo$ §u%N«M
+{AÈf†¬ë‰ç$?Úa¹ñ‚>dICß/ÿK<Aîþè–~²î”Åiöéꆺà•XÀÕÚ•@*˜>Ýåð|T‹ý¸kàeXoЕV»E[QIw%†—uâT²®ÇuÖ
+endobj
+1896 0 obj <<
+/Type /Page
+/Contents 1897 0 R
+/Resources 1895 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1894 0 R
+>> endobj
+1898 0 obj <<
+/D [1896 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1899 0 obj <<
+/D [1896 0 R /XYZ 56.6929 684.0716 null]
+>> endobj
+1900 0 obj <<
+/D [1896 0 R /XYZ 56.6929 572.8605 null]
+>> endobj
+1901 0 obj <<
+/D [1896 0 R /XYZ 56.6929 509.4701 null]
+>> endobj
+650 0 obj <<
+/D [1896 0 R /XYZ 56.6929 470.2699 null]
+>> endobj
+1902 0 obj <<
+/D [1896 0 R /XYZ 56.6929 433.5878 null]
+>> endobj
+1903 0 obj <<
+/D [1896 0 R /XYZ 56.6929 401.47 null]
+>> endobj
+1904 0 obj <<
+/D [1896 0 R /XYZ 56.6929 335.1577 null]
+>> endobj
+1905 0 obj <<
+/D [1896 0 R /XYZ 56.6929 244.1508 null]
+>> endobj
+1906 0 obj <<
+/D [1896 0 R /XYZ 56.6929 168.8052 null]
+>> endobj
+1895 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F41 925 0 R /F21 702 0 R /F39 885 0 R /F53 1017 0 R /F55 1025 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1909 0 obj <<
+/Length 1658
+/Filter /FlateDecode
+>>
+stream
+xÚ¥X[wÚ8~çWð'±ª»å¾™„´i“4èžîiûà`A}jì,†¤Ù_¿#KœÐ=›<X¶G3ŸæòÍÒÇðOúJ Ì"Þ#Ž&¢?[öpïÞõˆ“ ¼PДM{o.XØP$©ìOç ]
+a¥Hš~Ä··ã›óË/À
+<¡a 0\Ç7Ÿã+ûìvÑAün<D(%Aˆ1‰ç7“Éø,ø8þëâîÓõU<_ ¿O?ôÆÓ-¸æfÙß½¯ßq?…s|èaÄ"%úOpƒ‰"Ú_ö¸`HpÆü“¼7éý±UØx[oír
+ Êe?`•cÕí6Œ°
+)˜¥¯ç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´Ë
+Áà"ö<š©­Ï§r“»å½ö¥_mtú¶ã@à@A[j«S¨¨*= Òj¾*—
+¦×ã)]»Ž‘VÊÀí,1ͨ1<HuÅjÊÔÜÝ?Û뺱Ý.²¦‚ºÌÓ™;hÄÜóÊÇþÐI’$'™ùë
+‘
+Uزo“Ÿ“É0Tí‘c‡ ™sâS‘Pªý™ÜZèB¯’µöÕ⺟+Ц*Ó0
+O“çj­—ŽÎà{©\­³ÍrgêŽKŸP…!§¶ãŒäÁ¸É[¦{çɽýÒ¯ÓIBù0KV7ÝUh¤ È¸ÜË"ÏNVŸ¯„pûá1ŸmëªE«¦·Øô/Ëü¥_`€"ÌÏ&9Þºúÿ:³û-Š‡ˆ)õÂGÆÜ"âA?À(¼]À”. ;°ÿ \y™bendstream
+endobj
+1908 0 obj <<
+/Type /Page
+/Contents 1909 0 R
+/Resources 1907 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1894 0 R
+>> endobj
+1910 0 obj <<
+/D [1908 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1911 0 obj <<
+/D [1908 0 R /XYZ 85.0394 575.4191 null]
+>> endobj
+1912 0 obj <<
+/D [1908 0 R /XYZ 85.0394 427.1073 null]
+>> endobj
+1913 0 obj <<
+/D [1908 0 R /XYZ 85.0394 329.3834 null]
+>> endobj
+1914 0 obj <<
+/D [1908 0 R /XYZ 85.0394 262.8864 null]
+>> endobj
+1915 0 obj <<
+/D [1908 0 R /XYZ 85.0394 196.3893 null]
+>> endobj
+654 0 obj <<
+/D [1908 0 R /XYZ 85.0394 155.0304 null]
+>> endobj
+1916 0 obj <<
+/D [1908 0 R /XYZ 85.0394 117.4002 null]
+>> endobj
+1917 0 obj <<
+/D [1908 0 R /XYZ 85.0394 84.3344 null]
+>> endobj
+1907 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F55 1025 0 R /F23 726 0 R /F41 925 0 R /F48 940 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1920 0 obj <<
+/Length 2406
+/Filter /FlateDecode
+>>
+stream
+xÚ¥YÝoÛ8Ï_aà^ fù!RÒ½¥MÚdÛ:¹Úv¯ÛÅ–!²ä³äÙ¿~‡RmÚ^ààRä3CÎ'i6 ðc©ˆJy:ˆÓˆHÊä`¶º ƒ%Ì}¾`3r Qõazñþ“ˆ)IWƒé¢G+!4IØ`:ÿ9ü@"r èðz<™Ü|}¹ùãÓ÷ûo_¯>Ü|½1™$jxõðp3¾¾ûýrÄ%…%°€Òá·«ñ«¯8öp™òáÕç›Éå¯éo7ÓN¸þZ²ÿ]üüEsØÇo”ˆ4‘ƒWø „¥)¬.")ˆŒ„p#åÅäâ?ÁÞ¬Y<F ŠN„³c$•’{G"S¢æH&oU½nŠf+‚‘8Qb J¤d,ÄšÁqs ‘‹ÄŒ)«Gˆ±¢JK5¯š&Ÿžó·Å¦^•Ùc^^Ž¨a”iAß®;LÄ$J¢øêÅY¹¬7Eû´B¨Ï͈Ì-rT†¨Å$<±ä}HHH’()-êçh ÄIµ fVfM ÄS’$qjQ¿pŸ?G‹
+ß&µJÛˆÎé,Ø´08¹½ÒÆ(D<¼ž\½Ãñ1˜°èO&8ŸÀõ-¶šÃu±Ðv® 9ÇÑÛ¼,WY¥ùê:FàÌ; §¶ÍMFцŠâbúÌúþ2ËšÜ9E“WMÑ‚ç·ŒƒIššeãºÕÈ8² •‚6³G´Ïšº§ö¾¤Û>Î ¶6 ÷<këÍBuô0¨ÕºÌWyeévŠ4cëš>©Ž,À=ÍêÕÈß2j(Îóù©mé  ·ÅðÐM(ضõ*k‹YV–o8Ô˜è©{hÉÐ=»`DE¶$ÇÜ?‚*DÄ2:íþ}Ôq÷ïP^•Òwÿ”0.ãý"¥/W*IL•<-—äòüžRˆÔñž`“u>+Œµî™­Øt×8´˜Œú±¹C»ä¢û‡ÉÅå‡/'ÿbÌ…û—b–£_ÓˆR©8£ê„>Êè£
+…cF »R£_7yј)Ñ$=-\‡
+HçGc×Ê}ñ|­¨Äž3tê×*×^¬[ ‡ƒ •Ÿ!CÚfŒ uœVÒÆi˜2§[
+Ò1aqW^ûÕ££¡ÚL…ðc4Í! Œ Ækàúßûñ Žh3À@™ ØR‘Lù‘"njaÀOm9¢‡4!¸û½4ÚŒ\I¨ÛûÉa†´7ãéÝôœÝÉ
+æÇPØ@*b_²»jé§5' —pM/Ç(Cwx—
+:ÍS½--ú){É=6]´põ9ØíncUm…2hÔ¬N±,˜o±HÉÖæx¤¦{7¶±ß~ƒEΚø ‰ ðœ6ƒ>ê¸t(c‹`&U‰P{wjÏÀN•œËbyW5 õsÂ|±&¹)†ìåLw|­ÄÌÖºÏ1öÑ»I¼hå¥]eb{¹‹yHÊ7)­õXØp¯—W¦*‚žÃ-«â¯ HX†Ž˜€<”(ßé¿L¾ì²ø—ÜZ“biÍ>`Ô%¼ài13‘H‘8–g’{uÂDʘÈÓ>Ke¼õ K
+°ì«?f„­Ígù°)*Wtf¶
+}ª7­ínW«lóæS]éT¯Û¢®š½›-ÆååV—Ù®4«¯ <J çÜ•‘»×†e^’6l2•‰ ˜ÇuÃ"BádÏ覇:¡‡2ºy>ª›S,wº9`ÔMŸåçJ¦ÌÝÐo$Ýó{Ä€ÃÚÅ((«<k-;z‚,ÂN‰3'ØG?ÁeNp}¶tí?ÏKדÂíJ×Cé‚¥«'ÞŸ®XjŸ©à’»Æ×(ÉLÙ"TOšŠÈƒ/­¾æ8þ¼+d%³aª:1é™ ?«íê1·WôǼ}ÍÍ[LP WÃò3…¤®NúKi2(µ±”3¸°,²mÙâ‡É‚Ð
+ÝPWrAÁêJ.˜»·ÆÝuÝ4Åci)u˜;
+endobj
+1919 0 obj <<
+/Type /Page
+/Contents 1920 0 R
+/Resources 1918 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1894 0 R
+>> endobj
+1921 0 obj <<
+/D [1919 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1922 0 obj <<
+/D [1919 0 R /XYZ 56.6929 748.122 null]
+>> endobj
+1923 0 obj <<
+/D [1919 0 R /XYZ 56.6929 665.5133 null]
+>> endobj
+1924 0 obj <<
+/D [1919 0 R /XYZ 56.6929 579.9397 null]
+>> endobj
+1918 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F41 925 0 R /F53 1017 0 R /F23 726 0 R /F55 1025 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1927 0 obj <<
+/Length 2100
+/Filter /FlateDecode
+>>
+stream
+xÚ­Y_“Ú8ŸOÁÃ=˜Ú³V²$[~$ÉÌnBr©Û«Ù<x@€kÍa3©ÙO¿­ÆÙº›y°,·ZÝ­î_w 2ÀðO‚#LS6HR†8&|°ØÞáÁ¾}¸#–&tDa—êÝüîç÷4¤(£x0_ux „… ƒùò9}ù2™Ž†ÇÁ;4 9ÆÁ§Ñôë裙û2L£`ôa2†$<"®ÈbŒ§³Ùä>üuòŸ“éðÛü—»É¼«+:ÁTÉôß»çox° ~¹Ãˆ·ÁwxÁˆ¤i4ØÞ1Ng”º™ânv÷¯–aç«^ê3§q%[Dd@J9zÆà)ŠiDµ1@‹ÉÓHé;ŸŒö ›¼ü&
+¤Ú¼dµƒ‰I`Ü#vÚ&ÖåÒÌÐC>ØærE’\€m½D!5 tÄXª•Ao9ú¢ïÍËÓ³Ø^
+çíŠËK¾—9IC.I ʾ‚=Ò—GÉ qìúž<V÷(%pÜ1é÷|#}R¦(‰Zc¢ Šal°!uÒËpÜ‘N½eꑨÊɼëúB Œ×,*—Õ\³ÉËDå?5x‘†0”{í
+j¼¢êðƒ?«ÒnßEEÄ2·;5P9hV*FÔWã&ÿxœ†Æ\,F±€ ìyÊýǯãI›Î¹•ðRuÑmÓ‚[á8vÁ}åÄkDÚœÔêÄp×¼¬ƒ›ê•õN.L±`>kx(–µª_ÔtZu «^^!êòêPÛurq
+xè±Tm<NO•Ø´£?ÚÑγQ
+QƈSg·¯šjá‚Às‚ñé>{Oˆ\sw ±‡2®Ú.å«_ø·Ö2­o2…ü Ë5”·\­åÙxx†T©o*ºîŃßïúgÒ2~½)l!_eñƒîW‘î°Hy‚YŠÆ“ÙýÓã—ùã穧=¹’À=`§ˆGiÔw9ÓbÙfdoJDQ…®gªüÑYºýî*xËìò¥TÅOiÚ5¨yš¼ ÈIÜ®(—'ß Ý1u×Cyðؘ)UâêàrÒ÷2+êªMÓ&€úäÞçPÛo®ÃÂÁ|öøáØ·)V¾\g‹c˜AÁ“5VíºUîz¨§.¶êb§Öe”jŸõÏÎÚz›/DŠ"JèõœÒ!rW›ç)Åi”véƒ÷ÒJDÊ}Ù£×û³ÅQr]´–è\¶^bÐ(!xO¸™, QVfÌvo0XìßvMµÞg»î)aªs)ý‰Ð=|àÁ+Ô$8Ø·jå P@ì”ÆÄŸ+û½F ²µ¨³=ÔÙþÅJ¦[+=X™ Ÿf£Ocn›j( D”Ò¾÷*¯*åUæžVûªÐKg#íj) Ƴ‘¾ÇeÁâ‘ö?ê)GÁƒñƒy*Öã|¥ÜVw7föAÅ6+Ãr·ãçÑ}â»4-'q]š °éÁ]•fG0€†+s$ª-ë¼É_/ß|ª+{Ïà6Fþç_Ž÷]1¨è\ìõ¯’0°4%N(¥1!ôTôö7„sÙÿ(l7wendstream
+endobj
+1926 0 obj <<
+/Type /Page
+/Contents 1927 0 R
+/Resources 1925 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1894 0 R
+>> endobj
+1928 0 obj <<
+/D [1926 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1929 0 obj <<
+/D [1926 0 R /XYZ 85.0394 752.0811 null]
+>> endobj
+1930 0 obj <<
+/D [1926 0 R /XYZ 85.0394 529.0618 null]
+>> endobj
+1931 0 obj <<
+/D [1926 0 R /XYZ 85.0394 453.6936 null]
+>> endobj
+658 0 obj <<
+/D [1926 0 R /XYZ 85.0394 414.4777 null]
+>> endobj
+1932 0 obj <<
+/D [1926 0 R /XYZ 85.0394 377.7886 null]
+>> endobj
+1933 0 obj <<
+/D [1926 0 R /XYZ 85.0394 345.6639 null]
+>> endobj
+1934 0 obj <<
+/D [1926 0 R /XYZ 85.0394 279.329 null]
+>> endobj
+1935 0 obj <<
+/D [1926 0 R /XYZ 85.0394 194.9705 null]
+>> endobj
+1936 0 obj <<
+/D [1926 0 R /XYZ 85.0394 119.6023 null]
+>> endobj
+1925 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F14 729 0 R /F39 885 0 R /F53 1017 0 R /F55 1025 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1939 0 obj <<
+/Length 2835
+/Filter /FlateDecode
+>>
+stream
+xÚ¥Z_sã6ϧð£3³VHJ”ÄÞSº›Ý¤’½Ú¹^ÛÅ–ÍÊ’kÉIÓO J¤-Ë7;;¤È@€Ÿ0øÇ'2b%Ô$QQ —“åöŠM60÷åŠffA3õýâêæs˜LT bOk‡V°4å“Åê÷é÷ ®›~zœÏï>Î~¼ûíËÝãõŒ«TªéíׯwŸþs=’ ŒM¾}üõö'ûz­ÄôöËÝüúÏÅWw‹N,WtÎB-Ó_W¿ÿÉ&+ØÁW,Ãä >XÀ•“íU$Ã@FahGÊ«ùÕ¿;‚άY:¨
+ÎÆb@"tt‘ò@*%'‰TA”ÖÅcÝæ°©DMùw׳0VÓö%kqd]ﱃjú
+#;P\å+8Ÿ³ég#,Îbþðåvï¾ý8ûù“Ä/CÚ^HÎù4°”…X+W+
+¿ß`;Épà¥Æ(Ó‰ÐóöÙ¯ó»_ôf…»sä
+ r¸Æט[$Äý?œ°Ÿ÷.§^-‚49v 4ÄSüXfRTM^ & Mѯ¹ Wù:ƒèA1À¤+ÐÒiCom“
+û›lîúº:ëø =})Œû½:ïöd¼~9äõ:ùƒ”ÍxYÂIK¥b !¢Q©,æT*Ïݯ ÃvÅz¨V÷´æD¢Ð榗c´§;¢ËçL»ÂÉe]µYQÕæhtš—úPú%{Í=œ˜6]´±µô ³tú°Æ±ª&¡ -c&tÎqß@e¨OÓ}xôÓH¼âÏ
+.á0d[ó‰Ò(×´ÈR4à[¹%vwûb›cwmä©·¸ø—ÏqXÈPaï­(Kì=Ó×^¬‰^Ý4Ås™ÿK{„:?|+ÂkWHœV˜Zøw†8k¾aœŠEŠ~uÞ|;”1ß—“ #˜J.°´ –®IBÐbIzÄò뾨lNE®ð=é¢9l·Ùž|ÞÖgÝI½Ó‰UsTnÑuqÐoH}²†9½—ýG
+LJ$ä—«ªiòå l¬i €M*™ÚÜéüÙè?Ž¦œ ÌÁ|;{0#üús9æ7x,¿/èP¤ç.›õ>)pX™£±½›-;«;¡T^(€{ÌyÍÆ(nw±øÝíë¶^ÖåÙâwD¬¾ô=–k°ðuƒ[Û¼)z+:™øƒÂ˜)*`õ¤©.<8=€¸rŸ±$Yœ§Šáƒ!|v/fÂyÇÐŒ`àXXº*ÈçYâ‡`!¥ÉžéáLîD3ø0Ñ ÚP7Ì–kPìÚr æžÈ€ kÃ'~uÅ›U€ÄÛF÷\OwGhuy­Ùc™©%©°5]w °KZF[<*ÿ
+?šÃr™CÕº±ÝŠä’õ:¨ûµ(cÁûKYçį·«üõ4£€š%‰’qá:Ô€t¾Ë€ËؗΈeöå“A¥UÌa˜'T†Ù¤nQÚ*7UWKÌIú•€Üõ¹‰&ôg¸Å©Umù˜MO“}¿+Zž ¼ô„`¥\ ëò7 ¬kÔiDiêŸ<
+9p €°0±wú$Ü_‡lÕ˜¡ö _,ss„Ò¾«Þ/ôO=<¥få¨Ç‹¦sïç:³µ°™©v¬‚Ž7BÆÇX:dGÛ%¢tÒ{÷ðO5²gš72ÂóÄÔšåK¶Ï–­ $€C r­&XÒ˜[Èk<)ÜÌ­²–ˆêGÝ>wJ·`¤¨À(²•/ÊxvEÏ8 ›=˜Mf%~`¤=Õ¥þùAòî‰Na5üDrn-¬pÞ9ð^l»b×9G“ïésì2|¼pž–GŸx"Çœs>âÆÄ›æâÃQÓîójÓ¾œÞ˜øh}D¬s"—ÿ«Ü5"Ž\ÁŽBýÍ: ûF&3b/NF?ݸh÷÷žØþÞ3H¥ F6ÝEÉÜ‹>ÁLí.µëóй:Ó
+2å{Ùò°'Ž­ýð%#ƒ©èyq•ëW9Åî°‡2·†Ó¥ZpŸž·¨Y,.</¹¨;±(c)íàÍ÷„C¿)¤údS5.– ˆå½‡€-éŸÎ=±Ü'Fa«¸äñ]IPÑϸ1
+endobj
+1938 0 obj <<
+/Type /Page
+/Contents 1939 0 R
+/Resources 1937 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1894 0 R
+>> endobj
+1940 0 obj <<
+/D [1938 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1937 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F55 1025 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1943 0 obj <<
+/Length 2184
+/Filter /FlateDecode
+>>
+stream
+xÚ¥YM{Û¸¾ûWèЃüd‰½ÉŽ’x+i¤<Ý6ña‹»©){½¿¾ ( ½­} gï|Sd„៌C˜ÊhË1LØh¹¾À£Gxöþ‚XšÀ]ª«ÅÅßßÑx$‘ä!-:¼ÂBÑ"ý>ž|ù2½½ùå2_¡Ë€a<¾Ì¾M>™½/—2OÞOç—1‰ˆk2ŽÇogóùô:˜ß¼Ÿýçólzy·øùbºhë*O0ÕZý~ñýR8ÃÏQ)Øèn0"R†£õEÄ(b¥n'¿˜_ü³eØyÚ¼êƒQ˜c!‚$cáL"NCÚÀñ~:›~è/¦oÍù?Nÿ=×'ƒ÷iM<‚§($Òàø¯•*,éP…Â8Pk¢´¨*µ ~S/-u—'—(Ž¨%^–ëM®jU±W»åRUÕÃ.Ï_. !ãŸ`_Äã¬ÖW<Þl³¢¶´‰ÙªjØ{4[åƒÙ«WÊl<”ÛµQ!:P˜bXKb•øXÀz“$É›Lÿy”oŠB&í uiØk9@;
+¢P Q>
+Z쬪“"M¶—DŒSs¹«7»‹<^¬²Êl»kRØûTuöãp™ÔYiwÛ“Âf樰
+`‘¬U/T\pˆ‡(:U—ªª–jª³R÷PˆõBu œÞ‡w { *vkµÍ–æ¦ñoµ1—
+·ã²M@vßLòÇr›Õ«u?À·5ÎÜ¡:°£øœÔÀÇbý
+—ÊÝãêLÞÒ¨ø³‡yìŽÖ°ý}49¸ý¾htÆ°eM›®µ™þ2¹ýòi:<,ôL¡{cJ x—D$×°Pf?1—˜‹à¾iU)ŒXó‰Ù5ÊR×ßÂŽ9)ì¤åbÅš]˜èHtÍŠú#Ñ#‚ÉÂ7|À©XÛØhŒ]=ÒÂÊ</ŸM“ "ÅÚ€
+ÏžË]žšý{K¾¾Sé?<:!çH„°w¦ì†Ð 1ׂfãÞ\ »a)›á³Y?¢'{5&ߟnÜi˜©¬‹œ'œ©|G>û±£$zƒ1}rÂñ°¾7Mµ`._áÈ÷'OwGÐÑSòúÉÆíØÛÕ4•è2ÂiŠÜˆ‰t¹ªçŒ=)ŒpPºª³9
+¶Äm-n˜\A¥9îh„Ÿi=(ä=Ì]%ò~ÐÙ`{>µÕròiþy8XCTÙc¡«¹®ÝB—WkB*»l’9¥®nfö‹„´ÓuVdà‘IízÞ¯êAÛKë”·I±ƒšäsÎyð§
+@'Ú:þõݵáÓ¼ôð‹ 8j üev"bÿ;»è˜8=dç70• ‰ˆÄ~òmñáó×aÃÞ@»¾-”Mó—
+Z'Û»^C«Qnël·Þ‹…ÊqWP"h[¥Я‡²€!—¹Šë(œÞmˆg0Lô¨&à\±×ç쨆±Y™¯xf½®©ÛTW—e>\ ç/E¹©²êx”„Ð#’ SǘžIRGwÈ´5½Ã-t”L4ѽgq:eº¸¥òž^׉ïArçVKs2v8‹HÑý˜—'•/é… »œÔrL='Á™ËЯC¯^n_<LY„xغjËT 2UEÔÙÚ×’G1Ô\ó|ðð (ø“q|˜KÍ÷¹à!Ë}ü›‡–ÿc»Zµ«ß<2!ðxÔÆr[$ó¿
+…asœ r¬Ê$€q5Kò~m t œˆ“)¹ÃœðøW¬öÙ‹0£Ž'6çʽÇ=ĉ§mÚÕÖ#ë0¶ÐÔëT=õÄ7f'€WÀ×ɶî‹p PÜ6 -׺]=õ*íøç0Qå¯ÏrÞÙÞKH(fòhNûPÀ"I°C©JòÚû„&¢Çò> Çe­‡R˜6«×4±+]šäfö!!„îú>Å‚\ý;”§Vá¶>þß?wí¿éBV¡Bì¿ó~.m¾ïCb•ÒÇ#„«Þþ0vªû<¥ø¾endstream
+endobj
+1942 0 obj <<
+/Type /Page
+/Contents 1943 0 R
+/Resources 1941 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1952 0 R
+>> endobj
+1944 0 obj <<
+/D [1942 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1945 0 obj <<
+/D [1942 0 R /XYZ 85.0394 752.3199 null]
+>> endobj
+1946 0 obj <<
+/D [1942 0 R /XYZ 85.0394 504.8188 null]
+>> endobj
+1947 0 obj <<
+/D [1942 0 R /XYZ 85.0394 359.3246 null]
+>> endobj
+1948 0 obj <<
+/D [1942 0 R /XYZ 85.0394 298.3625 null]
+>> endobj
+662 0 obj <<
+/D [1942 0 R /XYZ 85.0394 260.8495 null]
+>> endobj
+1949 0 obj <<
+/D [1942 0 R /XYZ 85.0394 224.9084 null]
+>> endobj
+1950 0 obj <<
+/D [1942 0 R /XYZ 85.0394 193.5316 null]
+>> endobj
+1951 0 obj <<
+/D [1942 0 R /XYZ 85.0394 129.6476 null]
+>> endobj
+1941 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F14 729 0 R /F48 940 0 R /F39 885 0 R /F53 1017 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1955 0 obj <<
+/Length 3093
+/Filter /FlateDecode
+>>
+stream
+xÚ¥MwãÆíî_¡#ý±óIrÒ““u7N²Þmì¤M“h‰²ùV"‘ZÇùõŠ¤(i_k8Ä`|c(9ð/g6‰§Ü,u&¶BÚÙbs!f0÷öB2Î< ÍûX_ß_üí:¹Ø%*™Ý¯z{e±È29»_þ}'ñ%ì ¢7·ww×ßÌïnÞÞþçýíõå\f©L£«®oßÜüûr®¬
+X¸%œ6ð³x*×Kævhš“ÜüYE8$ùƒ?
+|J§±RÖúß{ç8ôu§R&³D›8ÂñMBš÷±‚kª éÎó1IŒs2;M2 MìK/aªåäÏ— «Ø–+Ök¾^Ó 8)Ë Ìœ••
+¨…­€6«~.Jî’F{~>4õzçÙW–:ØXCŸö© žÍKÈèª"äþRCzÙãÒÈó§0?-Kè |f€øvIQZƒGµÛ<ÖJÞÿø{÷îÍ|تQn|óí·ïÞÝÝ¡½§ØŸùŽòïÔM+à‡Ò+¢€( @B?B|i¾2ö«0õÓ=pö }Eï|E
+|`ÑO¼@Àš²Q­¡\6Éç©uqº¿Aa‹4Za‰¯‡>êC"Ä^\³ª³FɆ#ž %/ãpÕE&„…Èä³Å¸Ðý–£8‹äjÆyb”W+÷Vž1gŒ9MÒóTÄAÅqhÐ-½îƒ
+Àúwr!m8°âºt`Œð‡r]Ðw]ò¸ô-(œt<ĪG{½?ì3A}ãiTÿÚH>$NTõË·11Äáìdˆ“FÇ*Ù„»º1el/Âáæƒ7×Ð iA3Ëü•qöD6üiýR’ ‡yyùñ H4—3$'s•ÎÄ&ƒöp e±Ê¡…>ÂT*¡HÏôG}¬ã!¬Ãò!l5Ù3'™YïÚç];_•ëà æ]ϹÓìuXü ‹´4–Rª!ƒ¾[Õ2á.=»L„&àY$`¸0E8xA .݈À{ö
+Ò8þ«»
+ZDh£åPçÌın.´gívYùÃî[”ÌqËQYœ@|<c9=¬–°¼å<t_I,\z†d@š 9è¾À I~Ø–UÛ„+v*žê- £Ùm6ùöõÈMÝq…Å7dôáq·)ºÛz⃑‚¼ª”êî‘Î02 2gúv0¥‰ŸðœÒ§µÓÇ:®Ëk§<w¢,¶ÐV&µÓ§yë°&˜8µý)‘ ¹ûWWfäôàï+ŸÊz׬_çÁ?qŠ>á¨äJâ9oš0›3Ì;&F¡¦ë¯‰ƒ‡¢_½%.UÐù'|tï”1rv®³$vd>pôp½:¬¨›q•ÿºX‡¶"ðo9c漘6p¾¢û‚Q×€Ý œ4žlh„wY z¬ª}W¡º®"§}BO ¡l§
+˜}ˆ|g
+å×É”ÜC:ž‘’OÈ7ç
+mŸÂæ ù YÈ°ÒÎb) ®<Å\‡tȵL"˲{÷¡–fú06\hÛ}¡Í¥'ÎQZF ¡¾~6чºiÊ*À oÖpѼ·‚ƒê*Áï£Ý÷ èÓÚâÏŸ.§@jÝý
+æ1¬t+ä)…Ú|èÚØUhÓ#²Í_ŽÑÀV$Sã2>â~ä¯|oëì>Í;Ø󶄚´\¿2œÑ]óoÔ?'dðN=#ŽÈÙa°|…â¾\ÐËþg4vÿ#
+endobj
+1954 0 obj <<
+/Type /Page
+/Contents 1955 0 R
+/Resources 1953 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1952 0 R
+>> endobj
+1956 0 obj <<
+/D [1954 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1957 0 obj <<
+/D [1954 0 R /XYZ 56.6929 752.112 null]
+>> endobj
+1958 0 obj <<
+/D [1954 0 R /XYZ 56.6929 665.106 null]
+>> endobj
+1953 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F55 1025 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1961 0 obj <<
+/Length 2978
+/Filter /FlateDecode
+>>
+stream
+xÚ¥ZK“Û6¾Ï¯Ðm9UAGÇv¼N6c¯gRÙÚ8J¤FL$R©ýv£Š HªR[:l|
+)˜J¹?íÚ¬*êSÓ³T6„ õ`¬Ý?Œ¡¥¬Ö4Ù¾€s²ƒñ†Lç
+°HíðªhzÊv%”úØØyªÜ/ŽÀ¢E­^,q  CÃÆ:[oG ÌØl݈Uºó•¢ì23ªÓ~EkCŸ N@4ŽÊÒòºúGKd_}’|<Ég
+Ò‚C'­_¨Ö8SÃÀ*â0
+;Q©œÞ|úeZ³
+2Û4ÕW4ÛCÍhÖ¡ŒfïÆ4‹‰·K™š:[‚Ï(³ÝÒ¦¯caƒ!Ì2Ù¡F¸ì+Y0&QûlšÔ6bIpÿñ56â€X"¢Ó4¶]ŠÔ:ÒZ7Ú%؉ ¨<ÜàSÝ4åjWôghè%;‡™8—‚Ãt°ï6¾ýY|ŽÅR¨-4sgæ SÌš4ùw#«Dbtê‚/ΊáÉ„¦‰%TÊ´ÓºýËY!I•ÈÞ¬§ªüŠ¾ejRjº fÊYÐ(\B5^cu¨evi¨®ÆêPc‚õ–)±HÅW–w¨‘å=7%!±ö×[»Z§sÔy¹:jcžT&‘yš!dž*N .J¨<Á¼àú°iÁu¨I›ñxˆÁe|… áÀ“]”'‘χ~Fõ7$fÚ§¦ËÌ>ÿð†\§Â†Í#ÔK{ÈÖÍŒp#j®ô5áö`3Âu¨©£ãËä¡¢ô
+ 5‚']R‚ðy¸/þ¶L]ÒèwÖ72žÜåÉ`B[êõv2RE\„Qþ{6RõQÓ‘ªC™HUç 2êY},Ë겺!$bžµ5›Ÿ„$PÔKå3÷ài Y£aÆäÃŒ
+Þ¾÷8—NùwC]tÉžÓD{9{wå¤lÉŒg*úý0Ñtyl7‡ãkB2å üDÎ믚Ö_‡2úûx-Ó€Šêí‰,ƒ'$ÂØYþh„?O‡Ð çHú Ê„u)„L8%Ž‰«¶¡ALRÛ)ö:ï–Æ]!©ãÒlÛ´#†þsÚq^µ¡¡3iG‚i7¤^¯'·Р7>žuXÛÍ”†
+ˆ4†¤&M‚–xóÁ¢s-Ã-¿™åve·Dq)hHqþÝ&B…ªùÁGÓÎr*g9ȇWgKkZÉ7I÷YÐYdwÈ­ˆgDOÿK"çó+’8ƒfþ#aAÆ"ÿy­
+‡”™>ê]~ÍQi¨…³¬u KÞü«,Ð#“±Çܯ“âËÆ…×Éß Ù©hŸU/.Rwû&]n×W.g,œúGähÑxFÎΈþï+ÿ—%¡LÓ‰ ¹8\ÍS(?Γ!ëÝÿš.yÿgH,endstream
+endobj
+1960 0 obj <<
+/Type /Page
+/Contents 1961 0 R
+/Resources 1959 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1952 0 R
+>> endobj
+1962 0 obj <<
+/D [1960 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1959 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F21 702 0 R /F55 1025 0 R /F41 925 0 R /F53 1017 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1965 0 obj <<
+/Length 1813
+/Filter /FlateDecode
+>>
+stream
+xÚ¥XKsÛ6¾ëWðÒ©4 Q¼ˆÇQ±•ÄMb»‘2M'É–(‹Dº&åDùõ]
+‰¤ ,ê
+¨ôL•¬£RR$9=•n²b3ªÇ·Y‘ݧu^ÜÚ÷Ô>.ç³3fÉå&Ís•Õ–¨7™%®®¢ÆWïöý#Æ,u¢J·+ÝnBïÍ®lY6ÏUå‹•%V¥}eݳ23@E
+©DF1!H' müq’Mô $›Å5¼6D^TÙroyìÊ*Ûf·
+¦»Å— Ž}©xvqynÕh§mÃl^ÕÐü$ö¶›[véMZìÓm(ÃaÒ$N|H¿Tˆ/oŸŸY‰3Ç ¢<!mÁƒ:AJŸ ƒÓw‹—Wo8 ^EæÂr~€¡dçŠÑÜnËû:ßïŽZ9‚®Ùž3ÿ3$'1Á&M‰ˆ—›lùÙ× Ã̸­„½yKØ2F ¾‘c©éȱ’Ri©æs{5Åævï—A)=À õ«c6wÕ²ÜþL,Šò®²“S÷òæJ%X$Rá¿‚ 5MÌi?~—m4·J¼ÉZž 6&??Ä›Ožzh©¿[ÊeIrŠ5¢Pã}Ëï]I£„#AÛHtR×ù63Æxß>}ïÿ7– ó§Y
+endobj
+1964 0 obj <<
+/Type /Page
+/Contents 1965 0 R
+/Resources 1963 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1952 0 R
+>> endobj
+1966 0 obj <<
+/D [1964 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1967 0 obj <<
+/D [1964 0 R /XYZ 56.6929 612.518 null]
+>> endobj
+1968 0 obj <<
+/D [1964 0 R /XYZ 56.6929 335.1485 null]
+>> endobj
+1969 0 obj <<
+/D [1964 0 R /XYZ 56.6929 267.4555 null]
+>> endobj
+666 0 obj <<
+/D [1964 0 R /XYZ 56.6929 225.2657 null]
+>> endobj
+1970 0 obj <<
+/D [1964 0 R /XYZ 56.6929 190.8284 null]
+>> endobj
+1971 0 obj <<
+/D [1964 0 R /XYZ 56.6929 153.8399 null]
+>> endobj
+1972 0 obj <<
+/D [1964 0 R /XYZ 56.6929 83.2251 null]
+>> endobj
+1963 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F48 940 0 R /F41 925 0 R /F39 885 0 R /F53 1017 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1975 0 obj <<
+/Length 1710
+/Filter /FlateDecode
+>>
+stream
+xÚíYßsÛ6 ~÷_áGû®bùC”ÈG7qÛt“Åκ[ÚÕ–µ–”JrÒô¯(’²$Ëö’f»ín—»„¢!
+Þ¿‡Œˆ”´÷\Îw³;«Þ´÷k¥°öiùjœ Äõ;Р¤O’œÓ\"QVÂq<ž]œœÏNÎ&ê4å;qß¡.’¾ï•ÂI‡ g~οÎÓdi^`uÈ)ò)—ò¥d®Q-nB½È’"øþB?|^z‘¤E[.Œƒ¤ˆæ¹M—úo`^P¾è%øòcz½Î‚"J½©vV!ªU±^:ŒêL'ÆY Ât+¦a¹ãyq*dwB!§.eC°•”²ëÜ´MB]×=`Ò
+u˜¬DJäRÞ2yžEIîu\[ä×qdîÄ ~
+´F‘G<v
+u˜lTž€Xú-“]•wfyE[–åÔ§Û| Mª{&AËÇ&¶×Y?¦¸¡ó!Áá¿Ú¿*ÑÿÑ>c‚îµge¶íµ°gDò†½ó0[¦YÜÈÌ"ÌM4Vi°hõ™ÕJ/â /ÂL¯¤Ih™®-zQÒQõªsà‰Z¬ÐŽ0AGö¡-ÑÝ`IÊøHÔ¤ö„ÂJ•±ø² ‚<ßu÷›´B&ÑðÇÕ&?Ü„Éú(¹nFál)J³‹b(¢ªt¾¤ë, VM&ŠŠ*§ó"ß &†ø| ¡×¥ö€i¥ÔÉ´ß*Þ[ †)‰¹ßv%Õa¼Ñ‘¨„,g´i}VbÃü2áÔJ茆 llLði7@+÷>ÛÅ(Š†Á'K½«g6ËoÃy¤ÞjXsM @d.ƒõªÈ]Ý‘¹0ã˜ä󗛆
+‰2$ vë…´5ý¹@ÌÄ·Ã_)x1ž]^LtÚü6`£÷—ãéóOÄ: ÈÚÜ2ð†€M·,‚b7¹ˆ43<Ì4‘gFì>´\=-ÂfÛ[+ŠÇF%dAvå§ã±~yô~zÖqÆ.P>bŽü"/j=^#¥‹»ú¸ÔÇd=³]ÅòĆñÕÉäX+‘ÆE%Pܾ©!æ‹pi@Hæ‡Ó Y7l»K<¨çy{³„Á—¢‘&£ËÙÛ³‹Ã
+KúE©¿áãú½ÊL.Á*ZDE5×ÒŠÈm` ,`À)ªý"MW]€ãVÊ=$émåm
+…†”çhpt":gz§Ww¼ŸÚë*Jvu»¨½’ê@oèx›+gñÉ®nªÕ—jõ­ZÝU«¹¹Õ4¸ ÒRJb†ù*Èó®¹BúvV¨4.;4 :¯UÓOPt1pC¬Òøúù4–Dî¹ÛM"¿r¢.,J·PÄé"ìB¢Aö•ß_ú½Wkë‹Nß–§Ïì_òÌúÒÃq6óMû®ë#A±ßÖ™wèt˜¡´0m&D^<¬Â¿ž÷ÓgŽNqP_ëßPÊ,('m¥÷‡Òãjõ¡C½Ç‘Ï™û ³Ùèªñ ‰le@=«;¯
+~:;×4ì&g+Tãæzk³ó8™«KœàOãä£gÎ͆ã&|Ä]ÏoÖåcUGÏ|ø;­ÿwi˜ u?' añ?kîdÍòi?Zâ‚c¨¯u:WCñO{´ùž Ò A»ÿÀ°úƒ$Ö)u(BdÛõê{¦mßÿÅl”–endstream
+endobj
+1974 0 obj <<
+/Type /Page
+/Contents 1975 0 R
+/Resources 1973 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1952 0 R
+>> endobj
+1976 0 obj <<
+/D [1974 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1977 0 obj <<
+/D [1974 0 R /XYZ 85.0394 752.397 null]
+>> endobj
+1978 0 obj <<
+/D [1974 0 R /XYZ 85.0394 692.2263 null]
+>> endobj
+1979 0 obj <<
+/D [1974 0 R /XYZ 85.0394 446.6274 null]
+>> endobj
+1980 0 obj <<
+/D [1974 0 R /XYZ 85.0394 386.4567 null]
+>> endobj
+1981 0 obj <<
+/D [1974 0 R /XYZ 85.0394 326.2861 null]
+>> endobj
+670 0 obj <<
+/D [1974 0 R /XYZ 85.0394 289.3231 null]
+>> endobj
+1982 0 obj <<
+/D [1974 0 R /XYZ 85.0394 257.1813 null]
+>> endobj
+1983 0 obj <<
+/D [1974 0 R /XYZ 85.0394 222.4882 null]
+>> endobj
+1984 0 obj <<
+/D [1974 0 R /XYZ 85.0394 159.3957 null]
+>> endobj
+1973 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F55 1025 0 R /F41 925 0 R /F39 885 0 R /F53 1017 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1987 0 obj <<
+/Length 2836
+/Filter /FlateDecode
+>>
+stream
+xÚÍZ[wÛ¸~÷¯Ð£|N„Å•½‰³Í¶q¼·ÝÓÍ>ÐmsC‘ŽHÅq}gpáE¼HÞí9m|NDC`ðÍ7ÀÌlAá-TD"ÃÍ"6’(ÊÔb½=£‹{èûáŒy™UZu¥¾¿9ûî­ˆ†˜ˆG‹›»ÎXšP­Ùâfóëò{¢É9Œ@—Wï/߬^ÿåòõ_ÿõáêò|Å∳åÅõõåÕ›w¿œ¯¸¢ ”.ß_\ýýâo®íúÜðåÅ—Ï»ùñìò¦Q¬«<£µúröëot±5üxF‰0Z-žà†f _lϤDI!BK~öñì§fÀN¯}t F Aƒ³cÄ(Å{p(C"Á……ãÍåÇ×?¿»¾y÷á
+WcŸi¤ X0‰©PV¸H¶éfµ~Hןÿ]©@tÐ’HKxå­d… ‰eýâ…\VÏE|sI±qYQ§÷»¬~víåïw½v2Ûð‰Rž§`–zW»ÆÇtwW‰@[×Ôê!—I5²N!4aVBÛuŽ¬n%9{˜x±r¸:JmÊ×rùôî*/“MVÜã[†vË
+íU¿†Ûå™^úÎuY`ÿý
+ç>D”Hɸ›nç†ï
+ŒZº«ÄýÞ"tY¥»¯éî<–K2N;¦‰T¬G»rû˜åéÄê"œEÌ¯Þ ÓdÛ,OìêÙ”N¥$Ñ\šÓQ†ES®¼ü+Y/o÷µ›/«ÝTIþ”<{6ûí£¿tÔ„þ
+œ”Á&=~Z:™UG(œ•ÃÈ!ᤫÍá|`)jâùù‚Ìp¾.J1#4Öýù.‹ä6÷¶Ù¤·ûû{ØbÉäš%±q1ÇÌ¢;R3«RvÙ“Ëž›²]÷`ÊÑ…w§¼†Ã¤n¹g/öUrˆºßn“ݳ'ráÙš~Ëêit8PZDGÐéHÍ ¤,:_&Ñ™›²Eg0å(:Ý)Úg©Gg[n<&«wµnºÊÂïê“èH SÆGü¥#4M²Ð|@£0xšŸ/È çëC‰´?ßk ƨš}Æ•SûÄë×Ðè%ñ–0"D6d*ïwÉö%Ä„¨ø˜Ûv¥fÀRýßè "xlæ§ B#Sv×ið‹þ”î쳇Püv¢xÚÇxíBÍds ü{¹ßxÛ“È[. ­êjTn‹Žy{WjÔ eA];(Õ#¤_,D ë<©ªCÅ œ]ŒËyłЈb¢7,
+™ÝÔ‚Ý"æÚÌ«„FÔê%naŽßSëÚe¢
+lV1?ݨæ°ê"$æY˜ •ÞÿâZÖ.ÅßTÝÆ;›Õ,¦¡Ø|ánË¿…cƒ8)¤Ò-¤5N"+VðÊ…v¤}½*ïVáD…=
+ÒI›2Ú¶N¿Õs¼eã¹T[yë¡Q]7ß%OSsÄÂÞM%F©‚)—1úU:R3T R–*oÇŠŒÙ8ãW1TéyÕ©Ýúl0QÃ1ØS®a‹ÐÒŸÑZ4lÁFd ¶ùNÙ¾YÒ¢}/¤{¯h€@
+ÃÏŽùI+4ã&^ÈzÉçq/ÑF‰™Šî|FÏ+d†JõêQ1‘±é+ÊQ#U kÌ…t±Æ]¹°zœ=1èÁØa–©Ùò)³ŸæÁÉØÁûNh¸K²|â l@4ÐϨìùkj^0Ü\ÍKëîp† ÍW6 ¾8JZwkΈ±Íb‰¾+ÌŒ
+endobj
+1986 0 obj <<
+/Type /Page
+/Contents 1987 0 R
+/Resources 1985 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1952 0 R
+>> endobj
+1988 0 obj <<
+/D [1986 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+1989 0 obj <<
+/D [1986 0 R /XYZ 56.6929 752.1653 null]
+>> endobj
+1990 0 obj <<
+/D [1986 0 R /XYZ 56.6929 611.3886 null]
+>> endobj
+1985 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F55 1025 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1993 0 obj <<
+/Length 2490
+/Filter /FlateDecode
+>>
+stream
+xÚµZ[wÛ6~÷¯ÐÃ>PçT(®$ðèØJënìdm§íé周ˆ§éåe]ï¯ßÁ…)”ÛdOŽ†À`ðÍÌ7ˆÉ Ã?2“a¦ø,Q LÄlµ¿À³ÏðÛwÄé,:¥E_ëÍãÅ·oY2SHÅ4ž=nzsI„¥$³Çõ¯Ñå‡˻뛟ç *pôÍãèöòîãå;+û0W4ºünù0_$¦”¤V‹qtwy»¼^\}¿¼úç/ïï–ó߸X>zÃúÆÌ´Uÿ¾øõw<[Ã~¸Àˆ))fÏð‚QŠÎö\0$8cdwñpñ/?aïWóiÈ\H$(g Á‘"J†]†à‚E‚Aâ]FIÈe–vÙâVoôÛ·Bô4‰@I‚%Ì®Uöå:;ö¡%‹YÉüVÀ2Ö_*”`¢†¦]m³Õóã,Ê7ö™ên¶¯ÕœÈ([•æ¹îË6YUÛ÷¦ì}Ê¢+}ÌÈNó¡¬ëüÓ.³¿èmºoR;‰õÌÀ‡TRÄ™Œk~£”oÒ|§ŸN»¿/*‡#vÊßæ‹a‰èÍöœVÅÈl,F€ØN ¼Î6i»k`HœÝÅ:°Æ‚%qœ08‚”Ô¯–.Ê*!†ig=: ‡ºX ° Ÿf_kš^Ë@³A“ ©›„&F’‹i»:¥€]C`
+$i|dØÃS¶Ê7/Q‹ž·Y3'Ñ6«ìû݃}±Yk!êmÙîÖVáSfe+ óÌ 5Zb–YF¾4ÛÌ-ØÓˆÓõÚ¾ÖuVkXcуµÖp°î€D¼”˜Ÿ"d
+Ý R\œâÑfÚ ìüt!ASŒºŠtŸ­«rÿ”ï²ÿ–EXEAÀQ*ËPID•T¯Œ#8J%ÔW0\ŸÜˆÙüˆiÏ;ÄÎQ€‰E?|•ÈÅB©3‘ÙÓšˆÌNËDfŽLƓΨ œ¨öÒItrŽ(Nø´q^+`Ý >¹BDÊdhÞOó„GUÞèÄÎHdNF8*Ûæ©m¬´q{àýݪÉ„ÒÀŽæ äœøX@ÌD7›À”¢D€ÏN ; Dtù=¯CsA'¾\,BÑ‚hB:hCÎ(ìfŸ;o`[AT7
+ž}­qxz-Ï&
+Å¡. Ì»ÚÚ‚¢c˜af©\ !㠽ǜRóY¿3šÌ¤ÛÔMŸ«]»Îì Ld±¯«Gí ÑÝWNRŸæŸ[(ayé~µ¬ÂŽ}‡ª_z2[Û„¨A<&Cä¤õ0ßUs iÙŽ?¹Ä˜ÚGïó]Zíœtå}fÈŽNº€Œc 0¨Ä¹ ‹¾Ö¶:-ƒ­çPêÓ×…ç±åÑ0eœ×
+X7Ä`ÆCëV[}À@‡øª€ãJúPI„)§=P™9 ¨ôhHB´Ä‚CŸJ­pgاu“U}%;þÇÍÝÕ»×KûvL‡!Hs2>ªªÏeõ‡NÄ»¦_l\q,ÊêaßϬvŽ;èIŠ€Ë(†Ã¥¾ß²°ƒðØ„¼¦P’ˆ³M S)y®«ékƒÓkp^/ Í®áð“KvJ%ˆÃаd¸ä50(ë=Ç›`Ô²ó©õsZ”…¦Ë}R3zŒéî9}qcÀÔÚõTû T1ÆØß¾r?ª·@LUOkâ¨:-sT?}Ùü¤a‡;ùSË‚wòÓ|ªI¯¾ú4÷žúÅp"x®ÍR‰ë
+@Ç»€8ßç…>cói¾[¯ÜíƒæÐ —ÑÝ´–j ,îLƒf˜+ ¾†E¥Ã
+§.ÒyÇðj{áï¦oæ†Íé‡æ^­¿cå–íég[¬6¦/LØ7ÓJ
+endobj
+1992 0 obj <<
+/Type /Page
+/Contents 1993 0 R
+/Resources 1991 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1998 0 R
+>> endobj
+1994 0 obj <<
+/D [1992 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+1995 0 obj <<
+/D [1992 0 R /XYZ 85.0394 225.6507 null]
+>> endobj
+1996 0 obj <<
+/D [1992 0 R /XYZ 85.0394 155.4035 null]
+>> endobj
+1997 0 obj <<
+/D [1992 0 R /XYZ 85.0394 85.1564 null]
+>> endobj
+1991 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F55 1025 0 R /F23 726 0 R /F41 925 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2001 0 obj <<
+/Length 2597
+/Filter /FlateDecode
+>>
+stream
+xÚÝËnÛHòî¯0‡‘«Ã~²X,ØN ÁÄ㉒h‰’ˆH¤F$g¿~«_M)ÀÎ^69°Ô,VUW×»'üÇ.PDMbÅ0Ÿ,vÑd ïÞ]`‡3óH³6֛NjWoi<QH "&«-‰")ñäqùiú)t ¢éÝë÷·7—3ÂÓ×÷÷·w7ó?á7
+¯„ËŽ`‡y²K—zG@vF9Šá;ƒr/ô:У-Q(æ±Õ¦ýÜèç3!±…æy•ò´²¿–Å.Ér kt •éá9=8 0FŠsâ8ÐqÁ¤áðð=/öeVöµN1Š¥ AA‹–0ÈM8èqD…(ÖÎÚ$ŒXQƒÕÚ·
+Çuu¸ÄrZ8nó‡kd¡·ÅÁ»Â`¤î´Ün:Þ”å«â°K,Q|ýÓ¢ØÁ•ËnéÃÛëÒBÓèU2&ù²YãÈg,‘‚¶lRÃG
+TB} ¸²çÄ ùDœôª-­Öðw dyVeÉÖ¥Ó¤JúG°³IÝ™®´ahà¯:=di‰~ Çþf|hXظÉ BˆÑZÌgÑ6–¯C†Y´ÁÒ|g¬ÏR0¤–§Yz¤
+¸œ#%cÁ­zÂcíÈMæÐ'0E…(©'#FÉx¿H\¨°û¨«:Ù6[Ylë2{NјPÉ2Vê´´±Æ­ Á:
+²‚“,+² YA‡eÛ
+ÄÿÞ
+Øÿ‘
+ì$=c-¬Vౌà¾bæmÁu“ƒy¸`n‹‡)A"ŽÕiù¬€€}Apú²Ž„Úh†•‰€¤”c5}ß…ä¾*Jt­¡¸+&"ýÖ%"g9Äy4¶©&ÚŸ»¤v²5,€&-_ä(¬)馣‘„f‹fopPHÁ¦º;..gŒòiš—µ·1ý»Ú$•†˜KpÛ"YfùÚ¿tXƒÝëE¿{ý1 TY^§¥ûÐqûV¾Z„d}gª+Ç ¼IJ»]¿ƒNI»Ø$ùZ)”BÅR•ÐÔ¬úTåf¶2·Kuj-Nû™ØǾ(Ëì)XIh(U‰pÉßQ9A8nêøbïÌC êžÖ
+h šÑ‹VW¡ŒH‰¢XàáÑŸ°c‰c>r•PÎm]%ò”úÒÄ=ŸÊb[WnuŸTmv£Ñ…( $’ÓÑ¥5],]–¡è‚‘Tœ†ûæntÑóhÜOÊ×`ìFˆØ°ÒðÁŒK”;H ,“tWä?—΂VÄ…æ Œ-0f`Q…ÇÆd¼—_f<žÞèOÖÆêD‡d¡N3lÚ‘@¥Ž¡“W‚ž¯Ô!ûxù”Î\AŒ9Š`¹g…~\Ôt9æxôSáSxRö’´W•.Œ­ªl½påuéŠâ BsM;S궱N Ç2¸9B.äö“,=R€eÏ!¥€R¢ÃòCÝoó|0´úè½\9¯í×¾¹Ðn†RÝwb=Ís“¼Â÷Œ™fÿNu <®W¹"&gŠÇ6Ö ½z,£×õ@¯q¦Î°ôH–m½B¯ÇiÔcù7éµéÞÂÂÛóÖYì¶ðNÈžÞ+!¡‹<ÎwÊj™!ŸëŒF C‰ ‡x¦¶kcRƒeiŠ¾Ð• ¦z£Ä¶\Š#"$>-—G
+ÈÕ Š”’L±®`PµDÓú`f-tjg.lº‹6ùÖê2Y§\âƂœJ“u©o
+€È½ÏóÕ½³?’〦_;BA¢ˆf>§y
+®ÎÔ3”Ŭ!câõù£T )˳Æt–N ¡a´ˆd½©ÑŸŠnhºžn’ët=»Eõò#•ªŽ`›Ô§Ø¡=›r_xo¬Šžÿήû†©Ã¬€VKð?µÓ\ùhö´öC>3OpÖ¦84bu ±<2Öûzû~  ¤ˆüwJè)žQ
+DpwE¼¹}óñÝŸðϧç6]—‹Cö䯑²<Ôã2ª…ó6õ¬\¼/E›ŽÖ4磋ϥú6Ö‰hç±L´ËÏÖšÍýF'ÜI !ÈiÁ<R@°n¸£Ððż+Ùµ«€ªP0Òj˜Å} ‡å[„#ßÂêîH'>Š)8Œ_긇™í„ô‹äkjW’ås’W6 Â ÓÁÂs]k¶ß:¤ëû¥»~;Slèwå>]dº™I—¡a1Å:6Ò• Ð-ƒ1ÚëyÜÔ"v¥£¿
+s? 6
+åÎÎ{ôòÆy½{2‰ŸÙÝh\-¿]Ù»à’æ•]°)€Åñ Ì7Å‘rk¬Ixê@YÜùÊ®dŽhæ¸Õ¹›=1æª3ou¸í]´#\³‹ÖÔJï™]‘™Ï϶ü¹[2ݱµ¾›Áãn—£Þi\Aø?íŒ-¤q_ôHÆ÷g]Ñß v<‘ ¦äi¡<ÎP¨Î}i Þ§ºBýzbZß½Ÿ9ÞZöî‘™Ž±dp·y"úä7_õÊ÷ŽGõû¨æ’ä8â4Ì ÄéèaB¦Ÿ¹topÆÒᘓ,CbF¡c<ÁÌ£ ˜õ†rÐ|â6³?ôõÝ!óc _jØÕƒFuURÁQf‹òD‰®›qÁȱB×W_°*¡œÍŸú’UhìÏM Ó#ØwÔ\õü׊rüS¦ïáäÈHƒÄ`ß
+`'”Þ&dhîV†²ÿŠfendstream
+endobj
+2000 0 obj <<
+/Type /Page
+/Contents 2001 0 R
+/Resources 1999 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1998 0 R
+>> endobj
+2002 0 obj <<
+/D [2000 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+674 0 obj <<
+/D [2000 0 R /XYZ 56.6929 769.5949 null]
+>> endobj
+2003 0 obj <<
+/D [2000 0 R /XYZ 56.6929 747.9385 null]
+>> endobj
+2004 0 obj <<
+/D [2000 0 R /XYZ 56.6929 712.2038 null]
+>> endobj
+2005 0 obj <<
+/D [2000 0 R /XYZ 56.6929 645.6981 null]
+>> endobj
+2006 0 obj <<
+/D [2000 0 R /XYZ 56.6929 561.1687 null]
+>> endobj
+2007 0 obj <<
+/D [2000 0 R /XYZ 56.6929 455.008 null]
+>> endobj
+1999 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F41 925 0 R /F53 1017 0 R /F55 1025 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2010 0 obj <<
+/Length 2569
+/Filter /FlateDecode
+>>
+stream
+xÚÅZ_oÜ6÷§p•®Êÿ"qOÎ%¸hÝ\ãÞÐöAÞ¥m%Zi»’âäÛß ‡Òjwåu{N°Èáp8ÎüfÈ Oüã‰Õ“N%¹S™f\'ËõKî`ìõ<‹i1åzq}öÝ?ež¸Ìa’ëÛ‰,›1kyr½ú5½xóæÕÕËËÿž/„fé‹ì|¡K¼¸úå⢽9w"½xýê-t•’˜²–^]üøêåùï×ߟ½ºÕ™ªÌ™D]þ8ûõw–¬@óïÏX&ÕÉtXÆÉúLi™i%å@©ÎÞžýk8 SçL „ÍŒ49´l&8ÈøËJ aç—e`Ï<3ÆœØÍc +6‡û¢œÁ1(“,Œ=¹HÈ„óÌi-ð„8×™*Or)3†48¡+4pàt™6ŠF–i)GŽŸÎ†§×ðW¤¯eJ¡mb`·Ž[\:ù#áSÎIbš´ÃVw&„ï.×"yÙÀ†’éžÁ‹‰ä°)#&^Ç5ìÏ2›ä 
+”F•¯ïËÝ+O›MW65µ‰fÒuQÖÕ§8~ÇêÎo}ÛQ¯kèûâòê%ÍqDXùsÉÒçB§¾j6~—)ê5Ö2|¢I7žˆ[¿nιŽóVhC<ÿñh@ãf ¬¹M—÷E}çWÔ)kúô¹í»~멽õ•/ZR³Ã3Q.Go•ÉÄžç`ÒÝA´-vAò<÷_—á ØÜC‰yäaà¦èJfœvç×|xF.´çâ-ùµÖSgá™uZF¿þÛºø¸h›åûöÈ©µÉrÎL2]øH»‘kF?9]Õp0wû
+^TUócoº°Knsu¬‹5ùËL`eÕ°rW–ö­ }a€¬0«U&%ØeÎ
+Ë‘ cVäò]{äoüÀ\J~päÒe*‡xþóÎ;Ny UÎ3f{5ÔtNÿ™ÃGžé,Df¹Èøsø{°òrl‹ôõ£ˆ©…ÉÀD„L §Áä´ýdÊS9}3u®ÀNN1ÓÙfB»½oújEí
+ÔñãÀ,`Â<)%¬„jK)Fµ‘º$­±9Aìšq8r
+½…`yf•ÍÜ'øW(¦F¸ÂB«k‡Š«ódÆàSH꟪²¦Yå™™ê+×YJi°Ùôþ0Wg\¡Îêfê,—q({ãA®Ê­_‚Ý?%B•Ã (‡¦ËWY׌v{>¦$yÈò{êýã@2Zƒ H˜ù‚Ê2'场k@ÁÇZ:p·ä+ vC«`R –
+¡#,×kº@§*ë@†Ø sîzªö[ IžÞôQÏÛ„ñ(ƒÚÅ
+¥÷æJ`W3舅ß ‹áþÃbÄ<Z¾)¸A)ãÜg)ß\(PÝ_ˆ‰aÆcÅ›„€Ž!qªv š#¾pñ&¨-Å—(Þ¦¢OoÒ@<Z!öŠ·É…×™Iñ–Çâ-G8‹”2r¯¼ëëå0-OÊîžZèOÁ‚jïŠ" lt£ ý –sVàÃ)õ-Â9‡j„/ï·—£G ÀDqèÐÁ$-›mˆ-êÐCB )Å0â\Bq³j|[ÓÙ×Ï–ž:­_ö“I¡h„ïºiã *°Ú¿cIÇ+¦ùL ±ô›1`*ËE4
+q˜òX:ä‚g¹ÕOæCk§Øç}ìå{ Tø¯½SÑ'²Ÿ€bÅrž“Òàʤ?”t9úøíÌ%DëJcŸºƒèLë|-‰¦;!4èVï¾úæ\)ò
+j½ËåtoÒøÙ×mE*ì]¨-½Žc#<>Ь&ÞÓ¸EÜÑæð©Óþ÷À¦ßböV2§÷’áF H”þR9\¯¯‹ÎÃõ—3–Ð(Hoô@„“×¾¨£Ôxé–æ±Ç@T0{ºÄe‚ï•8$s|ZÁ< nÊn¡á²ÂÞãq
+GÏ.Ç^ eâN=íµÒ
+;)PäP(aÏR•Ô¦A‘‰Œ[b@ÅVˆî:œe¤Ïp
+âÏL _¹Tr •öt¥40…úph¨­3<™ˆ:Znà9^o4Îf6Ï÷×ûÙcÂ?‹ ×ä~ÛŽ×ã:>ªa;þž~÷±ìŽÎ6̓I‹Ÿ° 4v<'~¹"ž`–™Åd
+endobj
+2009 0 obj <<
+/Type /Page
+/Contents 2010 0 R
+/Resources 2008 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1998 0 R
+>> endobj
+2011 0 obj <<
+/D [2009 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+2008 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F62 1050 0 R /F21 702 0 R /F55 1025 0 R /F53 1017 0 R /F63 1053 0 R /F41 925 0 R >>
+/XObject << /Im2 1039 0 R /Im3 1162 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2014 0 obj <<
+/Length 1639
+/Filter /FlateDecode
+>>
+stream
+xÚÅXKoÛ8¾ûWè(÷HìÉmu‘ºÙØÁ.Ðö Zt"¬-e-9iö×ïP¤Ù’Ý]`aÀ¢ÈáÌð›'E ?‰¤¦:ˆ5G,7#ÜÃÚÕˆxš¨!ŠºTo£³KiIe°Xux)„•"Á"ý¾E£1°Àál~ws>Ç<\\Œ#J9“áäææbv>ýÞb Ä8ü8™ÝM®ÝÜÍXÓpru1]|],Zµºª̬N>ÅA
+'ø0ˆi%‚gxÁˆhMƒÍˆ †g¬™Yæ£ß[†Õzë\($(—
+CŒ*6 A1!@s‚HÌh %C€5T°è»=èÙ¥JÀ0VZ
+î©×R èǺRE”i¹¯àu‘¤Î4iR%n´ÚŽ‰
+‹W½Ë$ÆHÆ
+ͬ?°àùôj6¹ž$°†¹¨ §A*C—¨vU–7am—XWzevŸ'ëÒ-–Ånmm@½[ÙÉo~§u+7ª<—E^9k·Çe'XÉ“)ÍöÉlóºv ƒ„SÅ}¤nót9p"JH6™ôUµ¾FÖ‹ËÊ$iÏ#šÊ$˜•|O–¯.ÕñòÕRyƒ¼¿»9«c„5!§Å6Db÷ª¦Ç”ï˽,jà—¾øºTÏA|6«W5œMlOr*#†ô¯Pu¨N@ÕPy¨¦³…-Soœ20±¸¸ýØ+êò¼ŠùiMZªUöà¶%Dã¾.;_:Óâ9? XŠCÐ…¸ÐħfÓ½l‹qziò4Ëï½ò¿
+b¶ž  =+½Ö¢gžh—§æ Æ47ÎÕs$&‘Š†ï>Í.§Ww·‹ùbúiöã´aÕW¢ÁœV]$ÚØNX1Ž0‘´é|ŠÜjz¿sÙªf¡YÛ*…¹+I0W…,‹ÍãÚ|w«•ŸLM¹Üfßš=y3[%ÙÚ-œÖ
+endobj
+2013 0 obj <<
+/Type /Page
+/Contents 2014 0 R
+/Resources 2012 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1998 0 R
+>> endobj
+2015 0 obj <<
+/D [2013 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+2016 0 obj <<
+/D [2013 0 R /XYZ 56.6929 586.3808 null]
+>> endobj
+2017 0 obj <<
+/D [2013 0 R /XYZ 56.6929 444.5078 null]
+>> endobj
+2018 0 obj <<
+/D [2013 0 R /XYZ 56.6929 369.9671 null]
+>> endobj
+2019 0 obj <<
+/D [2013 0 R /XYZ 56.6929 265.0122 null]
+>> endobj
+2020 0 obj <<
+/D [2013 0 R /XYZ 56.6929 190.4715 null]
+>> endobj
+678 0 obj <<
+/D [2013 0 R /XYZ 56.6929 151.8306 null]
+>> endobj
+2021 0 obj <<
+/D [2013 0 R /XYZ 56.6929 115.5088 null]
+>> endobj
+2022 0 obj <<
+/D [2013 0 R /XYZ 56.6929 83.5219 null]
+>> endobj
+2012 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F55 1025 0 R /F23 726 0 R /F53 1017 0 R /F62 1050 0 R /F39 885 0 R /F48 940 0 R >>
+/XObject << /Im3 1162 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2025 0 obj <<
+/Length 3855
+/Filter /FlateDecode
+>>
+stream
+xÚ¥]sÛ6òÝ¿Âo•§ƒ$ûæÆI›ë%õÅÎô®i(‘¶9‘HW¤ìº½þ÷ÛÅ.@‚¦gn4#‚øX,ö{”Ç~ò8K"¡óø8Íã(29^oÄñ5Œýp$yÎÒMZŽg}yôü•Nó(7Ê_^`e‘È2y|Y~XœžŸ¿|{öúß'K•ˆÅ÷ÑÉ2bñæôíûÓRßùI®§?¼¼€Wk“¤ÀyF,Þ^¼??;=IãÅåË“—ÿ8zyéÑ£.…Fœ~?úðQ—p‚‰HçYr|/"’y®Ž·Gq¢£$ÖÚõlŽ.ŽþåŽFíÒ9R$:‹’L¥3´PòXÊ(O#É#£•¶Ä¸xhÚÛ®î¦G1€ ©ÖQj
+;†ÌáÕˆán³Þ=°~ã{±¹nwàÁ·ø/®ËØ鶴­GÃçoN_,ßœ%dqS¯o£äÂvóÀTj@ÛsÉÅÏͺ¢[8ÉnNŽ=fh-Ó±ÓNƒ­pÌ¢ýˆö3ž ¦vmmGGƒ÷õfCcME+5ù|è©€}ã
+[|Lž§"•ÊÐE¤Aª6^Få¹Ë¼#Q*ž» Ñ
+÷6˜Áh«íx6@€’+¾‚wr9ñQè_´RN¨mŒ´«ŽC²žå΂üô‚ÿ;úV&iôí_TVÿ;_y7OL™æ‘ ½EY&Êp ›BžöKJôÎÔî@ºP8c1à7¦\¨ì±Š2™Æs(2Ò$Êtœ†Ðgw>µ…xJG`ÉÓè twƒQ•»ÌYŠ
++E˜™‰xñ Eh™< ×2‘‘^Ù¹4ÑÓ¤aÚâì %)–ÖâH‡Ž'Ko€JZëå“Êš±µåI¨±æîU"-=;íØ êö^k¸¦ù”ðFc‹6€«OçÝ¥Jrt!ac()‡j[(™Û8mF%ämJ9 ßóxè›ê«¢«LLUµËÀ{t‚uO±
+ìPÖݺÝïŠk+,1Ö˜¹­]{7‡&p SL^–Mkb*ÑÃàºÝn)Ñ€¾MÝpÚšg`6ÀÊ…Ï‚¿Þo)V)Elð\oª#|•-úêÞ–]•+»Âø¶x ÑÕ‰´¾
+šwuWÛ¤g ˆØvßßÚ!˜9²å0rÛaÄ*9bÅ©»1ŒÌ†šðJ¶í^Øz12µ½ß±ï+ÆÍåì£nØ
+1B’ö¬×àTÍÄÔ‘Þ°ôøå“ R•û‰\[ÂÉÈOê¼|ÁË8VNjé¾ÜŠ‰> "
+\J*¹›×==­Ã6kà22¹ÖOâ¬ÖF¬ èá9[S­)_çk-åY–N
+¡^ØI‘Gw„¨\A °rWÒTL²ÂÍ“‹~Íw“Ö¾¶îB-Á˯3KÊ×}–ý³$ÌÔS³@@íæÚ¸ÂÝÿ¨·û-÷Ö[î.xÅ`>ÌD° cífõÀJj­ª«áöÞkžj«¼(ª)[ŸK‡ÅKù¹f¡…Œ“ž~Gn³mJkÇ Tøµ"g3ù$ÀqíçèþœõÀLoÓøËœ¯`G†AH÷óìBÄSvˆÄ±C8v@i148$°ŽP`¥ãRl"*µáĘp8©£§và…T–þŠzÿdJÙ`.vv;\Wã
+<!â
+~ÓÐw4’¿91#[âwsŠh|õÒØò±S™LéIòúÕ–Ff¾†0÷±˜„P¿OœýX, 4ä”änBÕ(x訣àþàëÅB¡x—|«Õü”H˜¸{}œi/¼ù²
+þn<|Vn–©áKb=ùHë\:¤þR%SÔý‡Éqÿ &ãQendstream
+endobj
+2024 0 obj <<
+/Type /Page
+/Contents 2025 0 R
+/Resources 2023 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1998 0 R
+>> endobj
+2026 0 obj <<
+/D [2024 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+2027 0 obj <<
+/D [2024 0 R /XYZ 85.0394 749.1471 null]
+>> endobj
+2028 0 obj <<
+/D [2024 0 R /XYZ 85.0394 677.0612 null]
+>> endobj
+2023 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F41 925 0 R /F53 1017 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2031 0 obj <<
+/Length 3132
+/Filter /FlateDecode
+>>
+stream
+xÚÅ]sã¶ñÝ¿Bo•gÎ >I oÎÄÉ\§ç\Ͼig’{ $êÌž$*"uç×w € EÉ—¤ÓŽgLp±X,ö{Añƒ?>Óy–[ag…U™f\Ï–Û+6ûs?\qsnR¬o¯¾ù^3›Ù\ä³ÇuBËdÌ>{\ý4ÿ6ã,»l~ÿðþíw·×…š?Þ]ß¡d>¿}ûöîþ»×ÿ‚wÍ
+w×BÏ8ˆƒúÝ[z#vÝŸ¯ñ$ºÚÖ»ºíeWöëöÇþiQ¹Ž 3„7ÝSuh‰@BMÌ«ghì•æÙÂ×f~\¢ñµî lhSŽÎç{¢Gÿ9Ömíˆp6_>UËO-a¡°ðÙ=…Éf×U».L¯GÓ¿ á
+-î©j+šN)¶U)­jbÓÓ(;Bg#´Ó¡_>u*`DäÒ›fÛÝ`‰JÍ•‡.²Ÿ–Pfš½{ô`À ÄêÆ¿‚’ZZßxXí—–‹d@sÑäÝŒ¼ $ø BÓ3ãûöØz2 ±­:¿×š&âàÀdˆ°,BX­
+›µì\‚ÃÂ'wP`T¶ô¤”ƒïž! ÖKÿrÿ@ƒèð0:<–
+ž:±¨C ¥à?X\N:×cXÑgRx¯Þ–g,Bz} á¶*w¤TDˆ)9κqÿדê”gç9<Uf„gªIBºI±¨˜äÅdÄ"E»'‡ï…ñÓ¾9tÆ,ñ¼È¤É‹Ë<E¬ ¦R‹âØ]n†L=TT&@MXbÀÅÁ*è_¢wÃ8Q¯[£È½a†ò. |¢Ä•Ž{Z€ (â´â*ÚÅ©@1^ÚxTôÄBÏÿ ˆ,ZZeã¨ZÝ!SÂD»q§ØRDT‘áÓ‡¥ÏõªZ½šðU®L¦°g`/V¦:“‚N){.JÃèÒ¾tžG ¶eÛEfƩг="D>;_Z™˜!D.•{W²ùüÍýí›;ê\œuýÀ]Ñbuh=
+iÞ@×”+32ÿx@æåÀÒÜúj‘WÕº„önÕƒ¼Ø€œ3xj9$O癀ª¤Îr­ŠË5Å:P#tÓ,]KŽÁ}µ:Tm{1˜*™é<W—ù‰X ÉQ`€ÉbÈ‘¦¢`MEÁíI²,øXû8ëë‘Â72£CNDQŒám/`"0ñÌ(Éû*¼ ¡n#gUqr±òÆGX &®¡–NH¹¢@Êå‹ÔˆLqûUa”Å0ŠÂ6>Šr™DQ®‚ÀpXîhAå_&V4 “Fœå4¹;‚.ž æ;GØêÖv*¹Ë=. Î‡#bÈÒ1Çs®Ï
+¹î-_úÒ‘›´7×`«ÁLÈ5€â;-$‡òD„ž#ÄØ (Y‘„ íSPîRÐm›Á›žv­BuÔccŒÆI;44—[ U})²€Î¹ˆÝÔå»C+cÙé 6(;`fßÑ˪‚jeë»9Z+;¨ºÀ[â4ôŒ±Æ‹²¥ÌÒ5_Jʇ'OÇ¥T?MIñŒéQN÷×|ç\‡ËŒ©^pë‚ë,¸6eHªnxÖyDa/s±&Ø8qfÅç>®´<[¹8þ2º­{íË”IsåRfÖê`¯tÄSkÁ¼W˜|PO~}•®n'™€V\ë`Œ¯ï'8úžxFùÂ@‚—:¿¬üë¼ò#–»è6¡YÅ ²öDñ r5ã—H ÏÊ ‘Ѐƒ^í¡ÅÄA/h„Ö[vnÏ»ÍÆÔbľ5½vMð~=äæäëIuò©góŒêÓûîLÈÓ ?1 7@r¹©ÊÙ#ù’ËBŸ>®êAçM@B1*Å vŠuÁ–ÿ†uzm³<ÐÕ÷0ØŒ[ö+k‚—¡w(¨ùˆ™a5,äPŠmÃ’jÒëão¢Œ¿ç‚çãÃën°2¡8Ý߆õ÷vCk ÈÆKVÀK/˜ñi   ÁB¾/ëäÖëF1 –ÏFUÖãäÍ!ñå…é˜Ú ÈY#‡÷†¾ú‚Fö
+í ¿}œ×¾
+8xÁú¾øï¹ÿߺ‚É ä„"Öÿ^DûÄÉ30YýÿwŒp¿¡3üÅà„µ±XFþé&ö?ÀTømölr/ EÄÞž)<;ù©OûŸ0žòþ
+¦ˆæendstream
+endobj
+2030 0 obj <<
+/Type /Page
+/Contents 2031 0 R
+/Resources 2029 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 1998 0 R
+>> endobj
+2032 0 obj <<
+/D [2030 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+2033 0 obj <<
+/D [2030 0 R /XYZ 56.6929 699.775 null]
+>> endobj
+2029 0 obj <<
+/Font << /F37 791 0 R /F23 726 0 R /F41 925 0 R /F21 702 0 R /F53 1017 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2036 0 obj <<
+/Length 2472
+/Filter /FlateDecode
+>>
+stream
+xÚ­YQoã8~ï¯p—
+À7WúËà€²ŒÑ ë\ éìš²ÞJ>Xëa²”Bʾáà8@ªûƬu(Ñ™Õ"Ѷ^†ÛÈ ØÂ,Q7òŸŸ†Ð²^]Øê1‰÷[}xs²”°øb鳂¼­¦XEœ¹ÊV½äK½|gH
+³™ÅÏ A'Îö#‹0Àmæ¨íôBB^.ôA*"ƒ8½2¹á‘M—ËÓ±c¦è^@ŠÓ™Ø9&ìÆ1麱ƒ½Ë”8«20ëìÆöu
+³m¥÷ ÔA)úÛ`f'p@p (ðÙ=MP^²"𛣊¥›Ú…6è‡Ç"+¿ã°€ÓÍI'‹22J.ì6×i7.ÜÛõ’©ïi
+{›ñój×€ÞnÚ)¢( uGñ|]æn[ú*î»n0ç2Æ5‹œ“$†ön
+ý2Pn>ýYã|ø¨¹ †•¦•kµ^狪ðâ§"ì Ö u¯±èð´â Þ¸ÇÆ8M.t7Ʋëßf_o¿\ßTjê0áî/i,
+Âñz½)ìzTë',’[¢ƒô^8™ˆLÿç `Y»FãX5X:½jW,Q…í>AÁ®ÖŽb7.Pò²ÖÛiè„#0 õø@· ¬‡k$«ÁÃ/S œ
+& HᨮúÊ3ä~Æ%î6vi´[Sl9sù–°í¤Y3 m­oüÞ IÌøÒî%}5Ôut®¬¡˜i×:M싧†.¹åv—ç‚u“Ú£$N•]Ñß&ÐIÒNÊõýdñ›±O3®ŠåªªÒ ·™˜u…±SÂl'mÐûaI*”z¡öÁ’‚„vÆb_„·oÛ³Ò^ˆq#Ú<ŽŸÓ½kfWk&·}Ôo/s”± KÇS¶4EÇ 6LEƒÎ0ýù6LÜŽvù×òU§Òc紇ɥ÷ÅÛÔNµsó`¤¡­|j;hfþ`ãŽoó¹û)âw*© æ+l×e TöMMÅoÙ_ñ@æÞòÅw³_:nü³i9$£Ÿ—ïof_¯]ÚUk}º¿š¥ós t€Âeîîô é¦ßÅ;ä0ðç‘ÃLW®Ç_éÅwÿE ’º™½ýRº
+H8T¶ Hë<`ﱬ&wÔwŽƒ35è}“´\˜‹&`I;6ÂÎFs4‰„ªàª>àªñŒÚŠ•N¬r¿sXâÂ:*íi•ûÔÞŒ;e„É0f¸*{Ð]ÊZ ê°e¾'W¦ç®wιHpqÑ~¥»—¿!ÄÚ3š
+*Y‰¶›qUÂÑŠç /›.E7ÁÐp=Oí½²)¨‘ÚNÀ·…½€T¶Z³4ß}|Ï(HD« 9CúÓð· K«õ'Ò²Ú}†·žP–m¨-­KV‘½c1³ù“³§-´îIÅWë6‚cƒWv§¡†Ö ä ,þQÛ0pæÒË
+endobj
+2035 0 obj <<
+/Type /Page
+/Contents 2036 0 R
+/Resources 2034 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 2039 0 R
+>> endobj
+2037 0 obj <<
+/D [2035 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+2038 0 obj <<
+/D [2035 0 R /XYZ 85.0394 372.4169 null]
+>> endobj
+2034 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F23 726 0 R /F53 1017 0 R /F41 925 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2042 0 obj <<
+/Length 2188
+/Filter /FlateDecode
+>>
+stream
+xÚíY[oÛ:~ϯðÛ:85Ë»¨Ç´I»>Û¦Ù&],ÐöA±e[¨,ùXR‚üûrHY’e§Ày]o£ápøÍf
+l¢4Ñ1'Q,‰¢LMÛ :YÃÚÇ æifhÖ¥z÷pñöƒˆ&1‰5ד‡U‡—!Ô6yX~Ÿ¾#Œ‘K`A§_o¯ß_θ4±œ^ÝÝÝÜ^Ïÿ cE((~¾ºývõ çî.c>½úxsùóáÏ‹›‡Vœ®ÈŒ
++Ë_ßÒÉ$ÿó‚5y†%,Žùd{!• J
+fò‹û‹· ;«îÓQ0J¸Ð|DœMàˆ±R¼§-¸pJø0ÿ4rF"Æô$âŒhÅ͉}‘hÖ¥rÛJ3¦ú@ew}›Ö‹·û´*ó'²(‹ÕP
+tªƒBðõQaÃH³³æŠ/g5˜-yò”dyò˜§!ÄùÔ™L½³q[4è8>«r8kj+dSd H#`k)¯pÛs’ŠH{@Û©)m¿l{ 6ïï,§HuÙMY€Ö%àËó\KyPû¼ ^_¸Ä¡ç…ì!/@AN—Ù:« c)[IÈ3$¥˜Î ¤DmÕ¢Ù#EQã
+H_À(ÃCû‡À–¯bXRÚõZ]HL§¢ZŽ°”ÄqëVu_‚1Õ”=”Å=åYä Wi3Žžú’|]îA…[`­…³6Û†ZÃîiä3ä|\iªÔÓ$ØT›¤ÍrÝ8õIcëm›&EZ8Ré\¤@LA'`¤,àÆ´Œ}þk—:Nªêç±hp69ŸUõKîX™¡
+ÜœËj…ŽÂ†æà6ì
+$qñŽ…¸ÊÝ÷˜‹,#t,ž½XÄÃ'¬ã6=¯r@0°!o¬ÆȾýÜäu¶ËÛz½ª“b‘VÝLïí,òëzøÄžä9Z5Ûº>z2},]°îš÷üîIÒ˜ÒžIGŽä  ÿV0öû Ôm¶¹|ÚBþoÿvsømJÚû4ü„ß‹Dp[ó PVÍŒ›cÃò¿òËþ?ƒü¨Jendstream
+endobj
+2041 0 obj <<
+/Type /Page
+/Contents 2042 0 R
+/Resources 2040 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 2039 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 752.0628 null]
+>> endobj
+2045 0 obj <<
+/D [2041 0 R /XYZ 56.6929 615.2568 null]
+>> endobj
+2046 0 obj <<
+/D [2041 0 R /XYZ 56.6929 551.6561 null]
+>> endobj
+682 0 obj <<
+/D [2041 0 R /XYZ 56.6929 500.3546 null]
+>> endobj
+2047 0 obj <<
+/D [2041 0 R /XYZ 56.6929 467.1661 null]
+>> endobj
+2048 0 obj <<
+/D [2041 0 R /XYZ 56.6929 431.4263 null]
+>> endobj
+2049 0 obj <<
+/D [2041 0 R /XYZ 56.6929 364.9038 null]
+>> endobj
+2050 0 obj <<
+/D [2041 0 R /XYZ 56.6929 292.3128 null]
+>> endobj
+2051 0 obj <<
+/D [2041 0 R /XYZ 56.6929 107.6861 null]
+>> endobj
+2040 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F48 940 0 R /F23 726 0 R /F14 729 0 R /F41 925 0 R /F53 1017 0 R /F55 1025 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2054 0 obj <<
+/Length 2477
+/Filter /FlateDecode
+>>
+stream
+xÚ­Y[oÛ:~ϯðÛ:@Äò.ò1mÓ³9hÓnã.8=Š-ÇBm)kÉÉæßïŒHên»§SÃ9œë7›Qøc3£VÎb+‰¢LÍ–» :{„¹ß.˜ç‰SÔåz»¸xóAÄ3K¬æz¶XwÖ2„Ãf‹Õóë/_nîÞßþç2âŠÎß’ËHQ:ÿt}÷íú££}¹´|~ýÛÍ=<rk`bœ\þ¹øýÍ%:ë kI,Š…+½{ÿŽ¼û|÷Y/n¼Ý31*PØÿ^üñ'­àh¿_P"¬Q³x „YËg» ©QRˆ@Ù^Ü_ü«Y°3[¿:¥#© Q\êYÌÔ0=­IJ¨ÍD±dDÂV&9›ÒdàÂóFK¯Õád”pq*Yù:{ŒÖÙ6*…iF(—bÖÝy$_Ã5!`×LkB©Šû~+Ó ³1C´¦vZÄÁº:ÞXzÞ¤¼Œ8GµIÝ
+ä
+sÌ{rk @àËdû5+Ž1 ÕýCd«q Zb4ã§×pMh®_Q%+Wý]¿ÕÆÓ>eã Áa½hS´IÕqmr
+x‘ õë´Ù¬8¡Í^ˆ:‰)œuB#O”Õo¯]Xï
+§v ºÔN&ó'‚Ùø¸j4‘Ð>È_§šfÅ3ªÚÚ2]5»Öm<øCp‹¼xñºÀú͵%I/YµiÕXu„ȱÙ{ø¦tHL©y²},öðÚÎ?ºj 
+%Ñ(iYhºùÈuÛðb€­ïý­j¹[
+Qø¥4DÆN3¿š:ÌM‚Iß
+¿ËÃÞ{Pµ}u¤:ÃïKâ •'¸Œ[<g«z‘Ì`¦—¸í£ xv©™ã•ÎÄ¥¹²€0•>ñÒ«fБHaü@<¿bÔ]²®ú=Ù
+Bo-ÚOA<ÞôËmDÀ¡¥ƒXܶ§ v`ð Ë Ôxjƒ¥ïëŸÛ¤˜:Û…ö!TOlrn¸#YnSo§ýe,瓱FûAvsãÞ½þxÿyâÔáUìøNUðùö'"œ€¬Žs¦3W#ÝIâäR°R‡¹IØ®?I˜†éÜ@ø“ )†‰Hm"}´sh­»mF K*ŠL¶¯Ìëo‹~þz^‹·y•îóqî_KÀ?Þªï
+’¬…VÆg¾
+À¸õdÂe@ŸcÙÿ9Īendstream
+endobj
+2053 0 obj <<
+/Type /Page
+/Contents 2054 0 R
+/Resources 2052 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 2039 0 R
+>> endobj
+2055 0 obj <<
+/D [2053 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+2056 0 obj <<
+/D [2053 0 R /XYZ 85.0394 409.4177 null]
+>> endobj
+2057 0 obj <<
+/D [2053 0 R /XYZ 85.0394 311.5951 null]
+>> endobj
+2058 0 obj <<
+/D [2053 0 R /XYZ 85.0394 250.1972 null]
+>> endobj
+686 0 obj <<
+/D [2053 0 R /XYZ 85.0394 212.3815 null]
+>> endobj
+2059 0 obj <<
+/D [2053 0 R /XYZ 85.0394 179.9082 null]
+>> endobj
+2060 0 obj <<
+/D [2053 0 R /XYZ 85.0394 144.7976 null]
+>> endobj
+2061 0 obj <<
+/D [2053 0 R /XYZ 85.0394 80.4778 null]
+>> endobj
+2052 0 obj <<
+/Font << /F37 791 0 R /F53 1017 0 R /F21 702 0 R /F55 1025 0 R /F23 726 0 R /F41 925 0 R /F39 885 0 R /F48 940 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2064 0 obj <<
+/Length 2904
+/Filter /FlateDecode
+>>
+stream
+xÚ¥]oÜFîÝ¿b{¨Üf'ó¡’''qz.š4׸@^ä]Ùª•Ü•Ö®q¸ÿ~䣕vå8ÅÁqF$‡ßäZ-$ü©…uÂå:_dy*¬Tv±ÚœÈÅ ì}¢øÌ2ZŽO½¹<yùÞd‹\äN»Ååõ—Ò{µ¸\ÿ–¼J‹Óß/xùÞšÑa ‡•Ô@
+±êN—ƪ¤¿-q!øêßRê›Ý¶è«¶¡]„Ô|àºÝ2Ö1J§Âé-20C[K‘f†Ï¼
+~S-WmÝ6ÀOjÒäm]ì:Ä®Áµ"ž
+*D@7â7nÃKݵ|lÀÊßÌ1•Ëˆp×튚­Ú bf¾úÇ:r‰àmä.wwwíð¾v½p)ÊvßR”¸^X”L^~K°o_N?Èèƒï¾›ùä%Áú–ž%Ší5=ëª)ç°ýÒT£ûÇWb;
+ï‰o(²û’wÈÑk¼zŠ—
+ieÜëòºØÕý’%pÌŠw"KmÌÇD¨UÌÁu[×íCˆ$ðvõHOŠã°a;ÈÞ(+ÒTªihiCl…x°^“š»Ž
+ñ=°}³c $Æ~}è’#“ûš”ˆwKíŠÔ™ð™özDó<Æêr!µu‡JÔžï—•РD³…“³V<iÅ“; üá¶Â1ÆY­A"è!Þbî>¹*s‘Éù‹h%´Ló±c,ɸR ¾e±K™üséœK.qçQßÇÄ!Bgö´«õ uUÍí¸VryrGåÇ}V¹7`(•\” ú Ì\”ˆŒñ+ŸÜsr†³jÕ®´Ùsâq25‡zœÄ¬=ï"™P 8Ò$¼nŠ~uË zjÕÜÌ(êõ ‘§ÂˆÚÕú£ˆWO•)þ¼ŠvL/d\^FOöìÉ~ðdO©!Åd ö¶Ô!ÙÑèÐ.¾a:¬~#ÑÃIŠ@,(ÏSÅ„lŠ±Yö„k:……zzàšXzÌH&K1#ù¦t`í$À:°6X—¼aÕƒ¶´„$Ñ”«oé“`”2ÖØ
+¤)4CÊ.ãñgüdœ]ðÈXù7òÈ™]B/•ê/÷ZH™ûãE*Ñ4o„×a¶e¾ f‚j ¯C‚@
+ãAnpÅ
+ñç°µrÎ÷µÐ^Æ"z$¦Ã?u MûÐ0{ÝMéEjÒˆjS}¨Ê D_°ˆ­
+¹©™“èW Cˇ*‡ò±è2šuãñÁìݨ ‡ýkºâ†vâ¥ÂLén׋™‹ig…ö—e™Â:ö”-•r8ë‰vw[݈ ®ÈDq7gÎw}œ9{!s=Ç0uÞU] >ÃÀ¦hâÿ
+ªMÇñàsY$êó_Ï>|úñœcº8‚‡h? ÐzOÄŸnºƒÃ%Ôb{ñ~†•Eê-ý¢éÎd,è$öG{Ž<üÒ°tR&ÿ ’‰¸ç»k®•†óu»*jlÓ^Ï…ÐñࢃŒ†÷×ÜêÎQúï€ 2²å[E²nLõY¦åÌ?OY}eÓýøý9Ò:å"á¹-
+endobj
+2063 0 obj <<
+/Type /Page
+/Contents 2064 0 R
+/Resources 2062 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 2039 0 R
+>> endobj
+2065 0 obj <<
+/D [2063 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+2066 0 obj <<
+/D [2063 0 R /XYZ 56.6929 752.0756 null]
+>> endobj
+2067 0 obj <<
+/D [2063 0 R /XYZ 56.6929 252.6303 null]
+>> endobj
+2062 0 obj <<
+/Font << /F37 791 0 R /F53 1017 0 R /F21 702 0 R /F41 925 0 R /F23 726 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2070 0 obj <<
+/Length 1788
+/Filter /FlateDecode
+>>
+stream
+xÚ¥XKsÓH¾ûW¸rY¹ š‡4ÒRLp‚8ŠâqP¤q¢E–‚%c»ÿ}{¦G²ìˆM(ÊÍô´zúùuËtèÁCŸx<C â{Ô&Ë7¼„³ãµ<nÃäv¹žÌ¸F$
+X0œ/:²Bâ…!ÎÓÎøÕ«ÉìéôÝÈe¾ç<!#×÷<çd<{3~‰´W£ˆ9ããÉùÈ¥‘˜(×|çœÍžº‡§³£ãÉlôiþ|0™·juU§×:}|øä S°àùÀ#<
+ýá6¡QĆËð9ñç %œ^·;§æÕ>Wø<$~Èd/íø‚rFÂÀ£CéG$àŒgÄiºRU¥ª‘€~à#/“8¿*«·×åÊ®|îóG¸ü÷‘6èRJ"ßgÛ…k½¡+hÇCý¬nðÝ*^^çªÝþ0̽‚âü²\eõÕr’€õj'î2õ[ù]æJ%+…šzÎApt²ø[ðÓê»Èo.˜8*–O¾Gù‚æùóÓ?óïý6ÐûØP«ªþE ‚ûÀ„6àŒ?›†¯‚'/6Ñûͻ͌¿}ÿbýúñã{hýð⻽Ë}ˆ½ïÃÂ#ƒLÒ¬ÓÂÜäÔW
+<râ‹ò«BšúfBôÀ
+ë&Ô’¤T€îZȪH“ž$›ù–i“å9ʽ¸Á«Rµˆ×9šê¬+«
+…1æÔ¥}š[ÝÑè­pd­*Ú}­S šÞÜù@o¥³¹Ê’+<Y®Q4…„ªìåVHª>z+Œm@Ίí%;IFm’¡j€khk¤t’²Ð.׫¸ÎJýº MÉ2l q…šÃ1hn‹v…ÎׇÈ#:ªÖÞ4_Y4U³Ôq­–ª¨‘ži–
+fm‹‰° wè<;º'O}ÜÅùˆ:mŠÑYm_Ý*‹û$1Pz]uœ†Sn/¹ˆ+å7ªHÊ4+.qW.~¦ÐO
+¾½:ˆÊËÊv&ðLËõ…‰¬¿¬Kpi……$…M=Õ’úB·X¡¨ãj‹83(fâvË„‚Ûw³
+ß\£zÜäWÑs£/ˆün|RîáH*©í%·h@“|·Þ€[”>Ð-ªÑƒÂ›zšÚÂ7V8"Aà®»­õ*vȹJtþ¥*”ˆ EŒdT¹Äõ~<MÝÜv¡îŬã#,_\¶íú*€îFXæ¿C„]|g^DhNßQý¹Þ.÷*UJ–ºÞje¯Ù‰¬O±ƒüDKïíKÀTŸZNDÀ4ÎÎ Å×X.ú:Z7B±.ó$4ÎN‘±Z ¦Œ>Ð(¨Ÿ(ò E±eW<,
+•e+RäiÞCaIyYdß­BX‰Àc XSªk•dúòæÖ¬èë‘vŒÙ/™€D<ˆîƒEÀIå-,â,j:§¼QcõiõuJgRÑÛ¬èU*ÓïSdðù¯ÑFD‘s®ÔžUÇÃÜ´½æ¸‡(‘\ȻĞO$ƒÍîÒÆ:ƒ¶Mý•<=ÅU„qºÌŠ¬ª¡°u5hÒ™Z(Œ{‘Ø×Nâbç[pÂiFÁD•ãsGiœOleŒ_žŸÞü: ôgA¨?ØîÜéûgM‘šO ¤›;xÔõ­Ô½Œ5 ø{ž¸m B¹A›=^q¹€ï7£w½3~3vzv·[¦€]«¢×ó›
+Bm;Æ!$LNÙz¹½WÀ4Ñ€O_)àãȘ@?r©þ¸ÞŸ,Là ±„°˜¦Ñ§_1Èþ@²Ûó‰Ñç#|õlã†+Ù¶?Ptv–eþ³¿`@=Éõüaⵞýí¿g¶C Ix²öŸ—«¹.åm”Ò¦SN÷Uoÿȹ­û`&ã±endstream
+endobj
+2069 0 obj <<
+/Type /Page
+/Contents 2070 0 R
+/Resources 2068 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 2039 0 R
+>> endobj
+2071 0 obj <<
+/D [2069 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+2072 0 obj <<
+/D [2069 0 R /XYZ 85.0394 343.1761 null]
+>> endobj
+2073 0 obj <<
+/D [2069 0 R /XYZ 85.0394 255.6488 null]
+>> endobj
+2074 0 obj <<
+/D [2069 0 R /XYZ 85.0394 192.0319 null]
+>> endobj
+690 0 obj <<
+/D [2069 0 R /XYZ 85.0394 152.6743 null]
+>> endobj
+2075 0 obj <<
+/D [2069 0 R /XYZ 85.0394 115.923 null]
+>> endobj
+2076 0 obj <<
+/D [2069 0 R /XYZ 85.0394 83.7361 null]
+>> endobj
+2068 0 obj <<
+/Font << /F37 791 0 R /F41 925 0 R /F23 726 0 R /F21 702 0 R /F48 940 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2079 0 obj <<
+/Length 3192
+/Filter /FlateDecode
+>>
+stream
+xÚ¥ZYoãF~÷¯Ð£ D=}اIf8Øxf3°@6´HÛÄH¢"Rvœ_¿Õ'5%?°Ý,U«¾:I²ÀðGB"i¨Y(ÑÀD,ÖÛ+¼x„{?]‘@³ŠD«!Õ÷wWï~dja‘T.î¼4ÂZ“Å]ùûò{Dºxùëí‡V?|ºýñ§·×+b¸âË÷Ÿ?¼ýpóßëˆãå/ïo{ÿo¿÷ùÚÐåûŸ>~¹þãîç«wI¬¡è3+ÓŸW¿ÿ%<ÁÏW1£ÅâþÁˆCÛ+.œ±¸³¹úrõŸÄpp×ý4«
+‚e’ftAÉ‚d„ #eƒ$£Ì)ãËë®Ù·u;}FÒ’-c+ªsGP4 ÜŒ\H"A¬ ''9E*+ÕaW®Wëf÷ðXí®Wôÿûªø#®î­°ï~„“{6X8Û2øZ½¶õß•'Ç Òœ‘@—x®3<™@Z
+ѳ|¨7ßÀò)­¾f˜K”`¼g¾+¶ßÀ|QÞ}sè2ü(CÆbsÂïá·bàG9@+ÁȧؕÍvF€-¥„ž²o/Š[”å¡jÛ·k »Èrýthš®¬99ÁCE‚Kbz¼ÈôØV9~”#:`çÆî·b„‚3kXh¤ŒðÁèÃÇ/?üzóùîæÓmúQÏ/VT"!Œ8u O=‚CÓ) ©EWµ´´YÂÏþ‡1}<Â^Ýìü¦ÝÙDŠ‡æp††È„“™£)F\EPAÈäT-oºprN»¯üTXúUŽ.’ŒÏÕ®®vá—Ŧ«;÷9ü²küõåPw++è‡*Ä4—cŒÖ»G 4rÙ=åP
+±Æ¸°šž Yµf “â4âÙëËs/° áŽp;ëæp¸&zYµûfWZ2êMQa"RàÔîÐlÚÌÉÌ .U„½=-ÃÍ MíƒH†ЀV"Ÿ¶HlAí—¹ÞeÔ#Á㌎lm`*çô#)R4…“ûWÏõ ÄEÞ>œpÈ]ÜŒíó¾·ìæõš²ü~ÉAkzÎh¸ð Ãµ^ÃÞKÝ=ùÝdÞ±Z„FDs¤Z9µ`¤˜ˆ‚7ûàÀÝ x·Uç7Ž{¿QdT¥42˜!’òfÖîŠNì=,ÿç¦.ƒ Oá±wU¶¬{ΊA¨@B©‘Aÿð!zñ¨q—³&ŽÉTF(y¼Œv‘Q7D ê~¤1at
+ÅÀyÓ5<øáª0” ¡kÄ0 1Ôƒé“ Ÿ§ÕX(@‡¸«•<_¥ ©bñtZ¥$ªWÃ#%GÆ}þÈH”9räY°TöFG~p‚ϱk¶à>ëŒ9À%µ‚€x>`3ÄhŠk“ä`8ı»§ºõÇ­}\‹ÙDú€-#D2xä‚doò ©pÌ®ÙpÉ™ßUÝ:\%qï^;w_ž@ìçlÒ†bE3cqûÚZ·Hõ×BRC€õØ^l#Ú}µ®­:¬»ÚxãåÉ–°võýÍ퇰oÞëMÂÿo¢º6dY‚ ÷ÀÓ†Wwm þž
+¨)%%,O')ðÍäxV¬Í0äÜ™"Ó«¯ n}èŽ{d3 åàauI¥<VÐå@¾Õzœ-f›‘IÈ­0_–•ýoçÀŠ…«Û}(Ž›Îÿ³n¶[Ô€` ùjWmü´ >vM–`>p³X3Á¶Æn6ÍK>Ë35#7â¢%6Ñ\.íÉŽ;{dtÙŒQ%Æ:q90ƒÈÇœóK–cˆCM=°œÀ>éÀbÓ¬‹_>5mˆÏ!éÂj×øëÃñàµûç$„8Ù!nB”Q :„~ƽè¿w»¼Þ ÔÇ‚šÚú.²g>“+(P™Š`rVi=¹÷8*äÒø<Ú5Ùøó3¬‡Æ†®:þ¡¤µG„³KçºÍ~UÙ½+ï7Å:Õ_ðCŸÕ²ª¥Ž…-GXˉ+ÌÖL¤ú;ÿ
+5©à-?ÂÝcTá[»;œÂ“Û¤W-}KWHuJ=É'ù©OòoGœ¯ ¸X"Ñ\q å:à"ìÙâvH5_Ü&*§ò8ec•k“ >² E#
+ÇWÙ(|V¶>
+—Â#éFQØV³ÁF24I°p¢¹•·ã€Æ×,v5 Ì‘ƒ­LOÜa7¶Gß‘ÈT|þò\lÜø –e³-ê]/:„ï"®¦Ñ8Ó¶ÚILj®tþ‘GSÁ ƒÆ<zHu6‘ÊÁf6ñõÐP.C7ú‚\‘(#×PF!®ÌD®qÚãy·Hý83ƒ~ÜÞq‚ºÕ‹m6]™Ÿqk 5M§ÙÆ—ƒ0©QÚ@3Sí‚(®ìö¢Àáëc¬8¾•Ûæ/†Á#H¼áíd¸8±åE˜þ†Ò
+e‡øvÂ眧²ÿ¯îŒ—endstream
+endobj
+2078 0 obj <<
+/Type /Page
+/Contents 2079 0 R
+/Resources 2077 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 2039 0 R
+>> endobj
+2080 0 obj <<
+/D [2078 0 R /XYZ 56.6929 794.5015 null]
+>> endobj
+2081 0 obj <<
+/D [2078 0 R /XYZ 56.6929 748.9271 null]
+>> endobj
+2082 0 obj <<
+/D [2078 0 R /XYZ 56.6929 674.5821 null]
+>> endobj
+2083 0 obj <<
+/D [2078 0 R /XYZ 56.6929 573.362 null]
+>> endobj
+2077 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F41 925 0 R /F53 1017 0 R /F23 726 0 R /F55 1025 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+2086 0 obj <<
+/Length 965
+/Filter /FlateDecode
+>>
+stream
+xÚ¥VMoÛ8½ûWè(+–ß"NâdS$N6v€mª-;ÂÊ”×’äßïP$]Ùa›CÀJ3o†oF$ †?’(0Ó<É5G‘,·#œlàÝ͈xL@Ùu±}ºfy¢‘–T&‹õÀ—BX)’,V_ÓÉããtvuûeœQÓ 4ÎÆéýdö<¹sÏÇš¦“›é|œÍs Â,Nâôivu™]>Ì®o¦³ñ÷ÅçÑtq¤5¤N0³œþ}ýŽ“dðy„ÓJ$¯°ÀˆhM“íˆ †g,<©GóÑ?G‡ƒ·ýÖX)¸PHP.“LP¤0× #, ÿ,çI­Ö‹’X½ÊÖ+;Ø<?] 1@‚”@¬‡Úr^ B1R\$ÈïxP„F£)*ψ=·å
+L²ôµê^¬ÅÓî¥tlOò’å¹ žmVxÈIŒ4%ÚCš]W5Æ9ïçº-;ÿ
+E=¢jó¢nC–»rYÙ¸P[Øœ@,‚º™úÍ5‹«G²`Wæìåòe?&*mšÎ­‹~YnõR´~_çPÚ~ka66íî‘Ç:É(GKii"B sKnúerÿxíû>{ì¶pÂ{äÂvzã)Õuó©)‡Ödš Î.â—R0aö8Pç]þðÙœRÁòJËx̶0‡¢ö©6ÆVqs€ƒýýåžîÇ*=/+5šIs†*8šiFó#à <­A1ãLÂl‹
+‡]ê¤ Ët·¯LçÌÂýk‹í®Ž)[Ä؉®m䘰%4ú¹®ûfåŒe³w¢hwYUf9 ˜ªHæÄêöMÝFâ1PmN¹Ú o`)<&Þ€‘"~Ú:p[+S˹óûá“q‡i[î*“ù¢ne:ì!š]쉔—kÄqnŠ-´Á¯ê«íˆ 'ñ¡rÖˆäZÿF:‘vç}6ŸN]œÉÝüáãf³Þ¿aüÀ0Hƾƒ}²tï”68NQ"hêâvvå¶jOjµ­LÕvÐK%Oåºt3Kßš÷®ý"/¢R†Y? >¾¾§u™</þ~xú¸ ·¦+÷¦ô#qþÖ‚¶üü»lLÛì»ê°ýÕ%Ú›Aä«Šÿøòó¢ÅsÄ”¢ñï3ÃÜŽHÙä KÏ© WZ{Ïýyb´endstream
+endobj
+2085 0 obj <<
+/Type /Page
+/Contents 2086 0 R
+/Resources 2084 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 2091 0 R
+>> endobj
+2087 0 obj <<
+/D [2085 0 R /XYZ 85.0394 794.5015 null]
+>> endobj
+2088 0 obj <<
+/D [2085 0 R /XYZ 85.0394 687.41 null]
+>> endobj
+2089 0 obj <<
+/D [2085 0 R /XYZ 85.0394 561.6045 null]
+>> endobj
+2090 0 obj <<
+/D [2085 0 R /XYZ 85.0394 501.5525 null]
+>> endobj
+2084 0 obj <<
+/Font << /F37 791 0 R /F21 702 0 R /F55 1025 0 R /F23 726 0 R /F41 925 0 R /F48 940 0 R /F39 885 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+1187 0 obj
+[694 0 R /Fit]
+endobj
+2092 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
+1598 0 obj <<
+/Length1 1628
+/Length2 8040
+/Length3 532
+/Length 8905
+/Filter /FlateDecode
+>>
+stream
+xÚíte\Ôí¶6Ò ˆtÃÐÝÝÝÝ¡Ä0 00Ì ÝÝÝÝ’‚R"‚´t ÒÈ‹>ïÞûüž³?³?½¿w¾Ìÿ^×Z׺î7¶‡Œ5Ü
+¬‡¹rðpr‹ t´P(ÐWç…C­fL9g0ЇÉ]Á¢
+Äü{fXE
+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
+~"ÅVöè=”Žòíí`õ§ï3t;k‡–Bf?õ[¼„Y®¤¾ša£„+gl’ft]ÎB‚²w3ë‹,£ªˆôkêyô’­úÅ>¡ï„móW¯µrÅý¼0Ï”dË#»§BŠ¸ÝUJàžuÕñÆIÍôaòÔã·×¸§ ™ žL¦€Ädô<­cË-8àÒ—£t‰Äº4ú£|©D„¡¹šŒ]¸ãÏßE¯¡>ÓR·9xyôöŽ[Ìï`º~ͲûDœ¨'ˆº5e[-0GMÓ=KÊÊJþ&â&’PøS¤8ëãin,õ 2PU«r`ZÅÄí¢v8Q—ÁèÍ ×ë¯oã»o[2ÝO2Ó¾Ðm/Ÿß×Y¿üìvV¹"_=5Ó›é¶è áaÖ™7þv|g “y×&"YæЖ(¾+ÐMoûÁ|°>›à¦± vZÎI ÏW´Ä%^‘›üˆ¯­Ú]Ö%½ZÆÁ_Ï@ÄRdçÒÄ9è©‚†õ‘kãC¾¥HzõOlnÕžÝÍà™>{óbÙ7U^|ä-)G?
+8òÞ¼x“mì¾%ÿjã=!•š[žž;[#ÆŠ™ éJ©/A%Ñv–µû`éióöí؜njP~^z•çQ•7˜¿\扯â ÈÛ.|âùúÁèéá™
+¸È÷»Œq„z`²\F棖ûEœ!~õT¦¾\Ž'4/ýCîe– 7,î9tãÒ¾Â1 ¦’·IM^y/¢˜kIm;˜¨½}O«•oÐHâ•¡Ç6—]í7ôh`† J­TÂcweófœkÔ­—ÕRÐÓ(9%Ö¯c
+Ó·_Ü€¡èüêr_7ýGmÔ&œÐ‰lÞÆŽ
+Kê#TðÖ†§øñÞ ¿šûDE&ñžËœ^QH¶!’Þ»¸>àáÉà̹ç$ÚxþF`Š×Í4IŽ@N@ÒÖ>_9²J¾ÃEúOê
+uÿ'¢µ?s_¯Ð‡öÿŠ˜'u
+BêH—‚?ý
+$OíœàÅ€DÈ
+¶_O®ð -¡;…®u§uªºXÄ[AŒù××¼^L¹ê=_󱑵ħŠfJ—äÌ;7œ1¾,`_q”¾´9›Œx•±tþ”
+>C{(©¼Ê°nwð,K ?EÚ7þBq&‚´”jɸˆ·?è¦ú-ŸCØüƒ%¥uXcýøââBïÅ ´;ÁµÜ3höŬ ¶÷Ét(‡„šœì :î´cØ¢>:ƒ‚¯úò‚#ÑǤ_VItSÏ$ëŽ`ø~"ÔܲÜr$ŒU–Y7÷“ø?¢ê¹iâ¯ÉqÅõãÏØISª5ñ4Â…èÑb“EÝêÑÑn›p³ú†-.ä‰ìošå•Hû~B»ÎÂî‚T§Z§Ï_)©OqÓzèß÷>ë˜Ê;­dpI¡rr1ÛA
+öÝPî2Pw]¶u¢èúä»(£ý/Ž¾ªˆ§þßÜ¿~&æ[1¸Aé-KžÚEО5JÃ÷.føzßwi°h“bLñB³ß6ˆ
+ÃÐÙ²¶©HÈ  9^©;¢Ìœp»Ãm%{r7E•€ÏŒµÂE±…ʨ*o,„ó QÞúʭ䦀(ô$íªy{Çgk9©‘5Â1ª0Û˜F3ŒÛ!s0¸4XàŠú#r¥Æ2á\8nqå°Ãs}䮀„s–è5)q…i¹C9ad¼¿`u ^<‰2@´ÄR­×$âƳ—xº>áÈïž¡wdª‡}Té†×ÎÂËõ€Èøt\1Ü~‚9 ÿ½8ia D9©ì"Ð!gÑßqÝ ùA“ׯøŠ
+»]‚ÄÙªAÓ8ﯙÎd@Iî?_ɽŽbÎJÊ8&1ß’bçy·ÌJü®J_ƒ|¡iïÂC®¡L;¡Æ–=x8"ÆÝù\šGd'—®®ðÖ/B¿ÝÞpRÆ'µsñX'MÂÁd;ŸäÕEûtGmý«†g¾ ¿¨öùWí},¾Ï†Ä›tÓk„fªõžÑ »›&oô/L¿ÇGìü²•âBZmÎOw݉Úñ¼>–¶ü^ÝvšÉŽHk6Œ´­¶DM0¦›}Öda'¨šßo·é˾xWp¼311ïçdϘ9óÅ­Ô§?¯jò>*§¨¦‰Ð:’-+X}7¿$ÏL\œö¦nD™ðì¡ÉX˜vWŠñ=mç¡|'M}„ç‹çÄ_’øÏ£÷rci%Åës܃ ¨ÄÏ,n±±ˆ" 5Ù½6ìÉ6úQèÒõmŽ¬öó–à+q®Æ¾ùÃ$ô|Òî]¾öÒñÕäË&æèñ²€Õ„KfVº”DfƒŒåZóbúä`#öZ·<Ò_Ç÷-¦ªÏôª
+_˜lg˜¨Î>«ŠTÂ70¡ðW~—ÛC!<ZüòþÅ#(·3¨bæ:ߨn¢Œè½Ù$ÞÄ‘Îf;®Ì*=ËnÙ†b…ƒ´ÂVE¼Á<öuBgˆÿׯxî×_ò­Ìz—XˆÖ`©Ö4siÝÏAí+<¾ŸãÁE.Q˜ÒQqúÖDõ”ÏÓ$`dlÚ/BŒñY<xŽ%Á„+{æÔ¢´®³N‡­”TøTõ”V3Tj+"}âžÂr}©Xž\L$ÓÇÈš÷ŽEh®Š-xù
+>_ŽÎr¦x‰|„ŠúNx‡<7M–/&×gaÅj[²Ë±‹4—À¤ÀÖO–|¾1_JSw{ðÐıDÃP~ÜFY­Yy³]ˆ:¬aÔ_|žjÓM+ý­‚0@îhÅtÙl¿Êgšê…µAbDå·Ôw¿þ}ûYÕ×iîBÕ*jòýZö˦ÏN’FéT/Hn±úÁÖ“4ÑOEìØœz~Ÿ Þ88‡á ‹w|q£ªšîFªãÆÇ
+TT>/5—䬽%‰”dðqÚnCÃ%Î4ÃXDmeß:#ƒU¹Ø•l1~à 4±GL§%ÕëEЈ®ìÒ\;ãÛ8Å+§êJZdº×d¡K©¡ZÅIŽf3zV#W•c[Û¡*_-߈¯Þ­—¶5k ª€º—,ìd¿»Ìë÷S/úò¢×Ž Nâ)uóÒY~ ]ßjÑ×Ù˜fšuž²K,tÊ÷“\'gy¿÷5­<TÏ4CUMà£Ægÿ3Q£8Nð²Ã‰ËzN5\/MØr®]SÝé}pæ§VD@™:]¬ÔË7>1ÌÈéC•'ÛEÆŒ!…Ù7aVì:ASQ×µ{|ãÇj9YÈ4Ö|m Î·*_íw4ø!D1 ñX¿Ù¤X•³ç
+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>è.<Sâ¢éX3p7«Á~ª"럽Ÿ“lË´ÍÔDQÿfŒ°Ì
+*s"}Y ;Ò‰¢ú{YÌÝÇí]p¶Òݯ€Ž¶Xo³êÙ}
+endobj
+1599 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 67
+/LastChar 85
+/Widths 2093 0 R
+/BaseFont /ZIFUNW+URWPalladioL-Bold-Slant_167
+/FontDescriptor 1597 0 R
+>> endobj
+1597 0 obj <<
+/Ascent 708
+/CapHeight 672
+/Descent -266
+/FontName /ZIFUNW+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 1598 0 R
+>> endobj
+2093 0 obj
+[722 833 611 0 0 833 389 0 0 0 0 0 833 0 0 722 611 667 778 ]
+endobj
+1579 0 obj <<
+/Length1 1630
+/Length2 6133
+/Length3 532
+/Length 6981
+/Filter /FlateDecode
+>>
+stream
+xÚíVuTÔí¶VA!¤†”ºQº¤»{€!f€J¤SJº !¤‘RBpé–NI%‰‹~÷;ßYß=ÝsþºëÎZ3ë÷îgïg?;~ïFZu-Ik¸%DCrpsr‰€t4õÔ--¬¡pe)¸£µ"ÒÂtñ¥]!H(&c„ˆ€ô Ö ˆˆ‡Ä-,, `Iý\¡¶vHó  û_–_. K¯?‘›HÔbºyp‡8 0ä Åÿ:P !í ¨#$­¦n ¨*b–WÕÉC`×›"ÔÝ,¡V e¨†€°€là® Ç? +8Ìú«4ç —$dB8C¬ 7aO+ˆó/ˆä qu‚"7Ï (dëjCÞô
+ý-à …Ùþ¥€ä
+±µpµv„ 747Ü¿ºóW ªÞÂÙÙÑëw4ü·×?4@‘ˆ£ '€›ç&§ò&·-
+âàæâú¦mµr€ýj?ÿfýwí7ƒú­¬£©¡¨,Éö¯o×ß¾ê7[€Ôör†€þ;‘ž
+Üú‡_LRRpO7· ˆƒ÷F7— /H˜—ßç_dýMÄý×YÅé
+õqqrqqƒn~ÿüþu2ù,Ì
+nýko´0ë›Uû‡álåæêz3áßoÿMáž/=â ±LOÀ­DƒíS3ÒUä9=ý2F:¸1zBœ‹k´_çûWÀÛýRÃ…ËÌ/*C8kE®š¼Æ·/W•X×z;È·'Cöò¨|èYÞçÍ3½d[ ›ã§}Õ‹òÞS^À4àÒ][ê×Ð4-º¸|Ç늽ÊâOïžïOÊpâLàk•òöÕƒÂÚ[ÄUÛ_™6OOwõ}ìén?¼û~•’-û£¨;&>S¤¿K6åSCRÙò·ª·ãòŽXXðð+yÏ—×ro1XçFèÅR61žêDžeâ§Á ×^‰mùkT³ïT ¥ØÜ KCvá)µKö±éû¬l´¾úï.ú¹üA¢IὬ}‹xp—ÆÌ:…x÷dlt×VEæ¹®ëºB4ߢé:°h`M$z¯=Ä*óù ?7l &?QäÔ…ÚvÆ<=yÊÙûÃ㎣²=÷'ºçä ÄAŸßÊ}gw‡U¸'b%6—=\5Æ„¶O€X)Ô| 6*˜Ö}ØŒôDVs§Up ˆíbëÞ­×…+Ïo_MX`êÁWÉC.Âß6¼|í½ÏÊ)¥2ÉP0–b®G+kGõýZŠÿåÆ~+`çÑáËé
+Žòêˆ
+âÜy­@/èqú‘³ v &¹
+Õ8àñ´ZÕHƒ»k|鵑dèC<g¨7¢µ?Ó¥›-;ë
+'´æ«:C\›ë¨úÙñ}ž¥•ý)4?BºÈ Q1­®ÑZUy!/”´C.pûÁ¹1>(ŒžJAÿÝëáæ…\™F{3dk*ƒ
+ù£ÜÛõŒÚGa¾Tµ ˵µ;¥¬W~òn+–lO­4 o¥ø!=ËMS¸âØ(kb¡,D ZÆ8T'p—.ø;2S•cf‘¦>dÇvË%·*­7 }Åçj£&ã—6Y”<P£-µdšûpÊͱá4xÜÃÍÀªNIÙžGÔi®ZyˆJNœ¦‹Âƒü´ÉP»£U?ÐçKÕ¡Â$±åîU¾¨•¯î´¤Ä6Œù°Ï÷b0Ol&‚3ûh.R²ÔEµ6¿PDÌsXykdìnq¡9¬[–º4$4´vŒwäú¾e'1 PEêA„÷ƒ?´ó2k¡†ãÌ2ž"šüœ÷‘ R´«Årg?Òûü°ºÍ(çóˆÇxemL Ïç&¯Ë0ú¼B»=0Ò\3$Kr¶êó„ÒÛ+©/fÃl»,{„ÉŠSÕÇúߥÛÌûzTÉߥ\ç›
+j2ri ÐÔaSïC§[Ev„¦6”¸£NÚ±ݸü}Šuò{´’Ú0G/P4t‡!ïL ÖöÙ9ºj>«Dd¥×VÑà›lh`2爙0#·êZ=4í%牵7h%Å Y$Zü¬ˆv±?‘©‡É=áមð;Ïcc„—÷:IêÖá°5ž’”ö×yÇUµD2>ÃÙ}ÐŽvk2š>2òQ× ›yôASLPkQ¡âZõ>×_À
+ZŒvR¸pdÎ& QºÒàî¯E¦âx|E&ù'Ar0Ëèh" ’çÏvÙý½Ï»ÓçêßV¤0²iRÂyO„jßÌé&šH¹£(Âμ4™
+V1-S8`_3D ÝËúÅ7BëbØ r¨Ãt©aÊÓêغ0‰¼•5ï´ñïâ¨Î)9É@[gbL¦')Ä?Ê„ãÐ÷*éT“꟱Eê+ãIõ_â‚R§—«·>noߢiŒ!L½<©35¢$2MIÝs™ôäu¢¨bâ8 ûVÇÌšDT£ä¶"Q TFÉ…Cóuø9dcÝI¥Z’f@A
+»<¶ÚL9’00#†ô}à…ê¬ëè¾>€à)†fbˆù†7sÑ¿×ÀÅ}ä׊³ÒgÍ¿?FІæNP˜ké÷2è´à2|Ö§™¥£[¶WDMåtè3?èù:28¢È;Xf1S§³EŠ$´×å0Ä0d—5ŤÐ4|ybæ)OÄ|˜léË@Èu±}µ\"üSÀd5ŒÃkùp ü3ʇ×Î
++˜^p€&9I‘òÝÂcJ-Ù.Eâ.ÂÄSL”
+”kx±saóÝÒ÷ÁÜ÷Kk ]ö¾ô3 ·/*ÉmÌKgƒwõÇ–ˆýIô‰ù¤ŽòŒ¿Ù=a£ïe€üvû# }Llb9_ÚEƒˆÓFHRòæ›=ë­GýTùH:ñ9ˆe¬ù6PÃ%BÒ§4ž£Ò.n+¿ƒª°ÿ9ÌèÙïc‚4Ã_gÇÓ¶ú‰s+>傹»˜‡¬9,Épª½è!׉·ïhuF ÒiU2Æâ-A6L;iY­"Û ±+hô3…RÝOïi¦¹Í —Š‹ä©ˆÏHžn5÷ò”JDýÉ›³¯pôÝÞó4ÇÃøJ~t‰•|§›19äÚ¸N±)¸}> ˜5.¶5Œ¥¿þ“ <ö¨õëGš±×1{!•Å²ê3‚A-üMÉcÂ[ ×%Üû/¾¶°½9oØPO;fiv±}½•@ÃœJ#(G9j>2š?¤Æ ñ?~ªÑWåïBç¡ÛµO±B¥™Ÿ†ñúÃ&e“v”3†­ÉÞ&™<)ïÈxbý'.¼Ï\Ì_³Ÿ±‡Ý'0þààõªckêUPe¤cne„žÁVó“pÜ Ê½ö>ÄÐ
+½c–î3Ó5¬´0ÏÚEdÊŒƒH(‘©,ðÉôä‚<Iµ±¾»ê» :—Ò´Ä!ܼ^ÞXÒ›/¾5obÿd¬ë¥KºÃ{ƒø‰Õ˜ÞMG0C&ÂØjãž;áÔ+5ó¸Ç›“°äFÀ.³†ÎDú²À}]lÃúÙ²f“_¼²v-úHÞœ_qØ*ñ yžNÂŒ°dŠß³Ó¤¨Jµ¼½·8òý·äæ/›Ü&Õ
+yn£­ŽZ°Ü_N@%3&“µÀeÑ¢ÓnEoÍ“Óm’~XvK”¸8­é3-äëýð ³ú
+¼0ʪœw(îø7¼ûVdÖ‰o›áÞÇâ-ã±®3Å(·ˆ˜·gy„Mª/‰Ã¼–Ô÷€(sq%£Êª$¦Ì±lvá3_‡ìäÁUGÑ8[ÃDUOÓ7¿éç=åÕUcQQZ¨cÞ­(§ó†64†0\LT\Æn^·¸’ÃÎéŒââ›Ñˆh\}Cëõv…ì=^ÞQ¡7°ç¹‹].Fè‡!–‹5·›\ƒj+Ø3Š7B ‚äÔή˜ °w>Nnád¥
+ecŽ¡ñ³b2•ßÃÄœ¯ît¸âËA".0mÕjÛ;÷$èÓ#Ó“]Q;Ò­vü‘‡¦ýO ¢Â{'ˆÈ‚1N ;$F_<tïy ã.“yw`¸`[ÀÉ¥½¢‘öâÈwxúÎÂ-çsy¬û³B£¼!ç?7p>Õ~@
+ÈÃñôß[Ƥ7œàÀfIŸŠ¿iÍPŽêb FDt¨%Sc<ØCÞ±‰¤_¥}#툎~áß\°ÕÃjC¾35𮾌ŠãÖEf˜ä÷q}ÔUp¬$Ú¿•×çyD*û*ݷ÷î@òQŒÞ7¬â¢¾yçã,£êìª%É0®š¹î³È6¸½}ˆŸ^½÷s®Ã´ÔøÛܪ{‚€79»#¼¸ùߣf²sË©W½ørÄ(€Db^Ð*A|üÙÀø乪“ÐzÜÙ™N>uêתͲ, ¤Õè/‡üî¥IM€©*õO ÀgÆC”kìþ‡•
+5Y_£cóclNŒf•@Uï '¯jwåB ^…gzrÖ¤º|`ÿ! Î~û¦ã­t¤w¹>îη¯Œ_‰_Tó¾
+Ÿó/°Kê¼-œ [—¿çÃq-øz~Ii‡³®>ëGGÈF¶Üšqˆ‹¢À¤^Ý µºÜzœòŽLy*Ø!$ëȯ²È¿Äø
+Òí¸FúïšyË«mn£°MWÑl‡ög2w™SçäSCþ¹A¡‰
+endobj
+1580 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 66
+/LastChar 78
+/Widths 2094 0 R
+/BaseFont /URQILA+URWPalladioL-BoldItal
+/FontDescriptor 1578 0 R
+>> endobj
+1578 0 obj <<
+/Ascent 728
+/CapHeight 669
+/Descent -256
+/FontName /URQILA+URWPalladioL-BoldItal
+/ItalicAngle -9.9
+/StemV 114
+/XHeight 469
+/FontBBox [-170 -300 1073 935]
+/Flags 4
+/CharSet (/B/D/I/N)
+/FontFile 1579 0 R
+>> endobj
+2094 0 obj
+[667 0 778 0 0 0 0 389 0 0 0 0 778 ]
+endobj
+1366 0 obj <<
+/Length1 771
+/Length2 1151
+/Length3 532
+/Length 1711
+/Filter /FlateDecode
+>>
+stream
+xÚíRiTSבª¡¬2©¤j=,ŒiF !¡€D ¢a”Abî ¹%¹—^n )ƒˆ•TeYÄF—Œ¢¢TXUê€RK¬B 8‘VJXÖ"U«"àÔ ÖÕUúó½_o½sþœýíïìýïlš[„Œ!‚° p0† “#R©„Ãä™Í¦Ðh8,' ’°p/°R«Üe€Íò– y|
+ bizIQÀ#>Aâ‘Æ…R9¡‚5d …\ d˜ =ˆÔj°vâF:X §Ãx 1)€6À)JaMh’ J ðßÀ6ím*ÆÓIQÀcR&"! Uë+)¬pŒì“Zþ²¦ÖªÕárÍDùI§þ•—kµþ/¦IÓ0¤ãèTj üFœ†­fjVBÈÕˆB„¦¨aÀà,g²—¿Á‘ô`DC¡P¥\Oâ0
+MUBú7©ƒµZíù××N&#äJDêÓ`Àþ›=sþŽI“pDâÙL6›CÉýö”8¥™U`‚¦
+Á:
+-ŽÃ(19>¤Aoc%Bz
+Ã:XA1ßÀ>[>Þ{j[M®¸ªó¨-=}¾ñð–ös[O}˜C½>N×ðÆ#áþpÜêø1rÌ¡d8ì+¤äõQO‰²MY2ÖÖG“½ ½bŸlÆÅPBÒ´Kem­ïil¿k^hIkô|ð“ûÓ;çlëVÝãð+©Ã…ÓknÞxù87ucGŸÙîKÈ}°„’XvzÕ8ú×;EWÆï‡`U˜¹úÒÜ„}O_™©­·»SoÙ†2©Íu£ï‹YlºNÙßAáìO]hŽ-¬” gÎ÷º]nVïûºcýš›Â¤¿Ïè¢ ÜŒïvKòsJBc$Q#óŽV8)jæ©}Cª©Öp}ëºz¡ÀR¿&ß)µ¾“ë[ÌIkÜC[›<ö’öÇ¢ÓŸ$>ÞûìµÚò@‘åfåz|ZŒ§÷~ÿ Ï!z;›j{õ3“[œ\õÅ]BäÚk·ÂЦùÁ¿?»yT
+b×ó\nùÌÝ̥܎iö–(]çùu“iw‚Xg%ˆ»ˆ~Ô_ùð·‹-†ýܤàÀøÞä3‘7=/Õ6œ¯
+r®-˜žhj
+®ZÔ4ë˜ëæç<ßg¶ƒ(Á T;ͺuE÷Ug³xãc Ž ½t¿ðü±$ÊÔ8|ØkA®íàæy©;™÷#—fyÿns.¬6Yßé]{Âôýœ%{¡ÈlÆš½©ÇjÂj¶iô³öÔ?äØ”gŸ}"júNY†:°O—ÒÛhë/×>"Š"žW&3ñ8ÿ3-­(ŽZŽeepϬ^ÏóIHyÕíwxíÁê¬]<º¹|Áöõ¡]Ï€€š&þ´$÷õ–‘ž­£¸©=ÞŒÞ=j¼ý}"Ø|ö £ÖÝ7ö«Å~-Ժ󿌮XÃà:*#³Øê8ÏBëþqÔ\©©u¡A.–Kò³«Iêü­ä‰+jjN3l &h‡^ž¨*‰fåZzVœôr#VV
+QÙbÉ)õR«i·§>.qµ<Å7¸Êo(ß ùߪˆX7R1î{§k\›ç|y¸°ãçÓˤJéëxÙžä¹ÊL½®sNfSWé<‡r] ÃcËéÕYŸs¿8ehÜd5—D@ßX«Ú·]s¾m¯álŽè¸ÏŽÄväÛ¼›S¸’Jý5,®Õí« -µôÙq13êýÓh×RqÉ+ë¸èºÁv버C\¡S£¢±Þ°ûBe±ýGÑê@¼42_Ñv+ióÊ!i]Ãñ]vÛ9UÙÅ]³ šgÌß±é'—GK2d_®ó;ÇÏψ>ÌëóŸõ­ûÂ"%åœ,WH¹+î Í~æÿÝ{Ð;¶A#‹Çœ1<·¨zO{—K†.wŠn¶î¦Õv©›ªK vKg×8­'ÄáPûeáUß]íÅí¼OÚƨKˆ¯âO.uùZŸ\Ä ê6< iY• ¡‡[° ûðÞF§6f^ž¨4 ëúÎaURCǵ²¼ŸÑ(Yu¼­jß,NT˯m¾P`3ãÞWâ>ý&¹š?0z^Ü’xµçó‘5;ø/̉,zbCN¬èæÍ1ox’q(¿ŠZÛÏþåÿþ'
+(Ô°'0O¥ü ÛGŒŸendstream
+endobj
+1367 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2095 0 R
+/FirstChar 60
+/LastChar 62
+/Widths 2096 0 R
+/BaseFont /OICPNV+CMMI10
+/FontDescriptor 1365 0 R
+>> endobj
+1365 0 obj <<
+/Ascent 694
+/CapHeight 683
+/Descent -194
+/FontName /OICPNV+CMMI10
+/ItalicAngle -14.04
+/StemV 72
+/XHeight 431
+/FontBBox [-32 -250 1048 750]
+/Flags 4
+/CharSet (/less/greater)
+/FontFile 1366 0 R
+>> endobj
+2096 0 obj
+[778 0 778 ]
+endobj
+2095 0 obj <<
+/Type /Encoding
+/Differences [ 0 /.notdef 60/less 61/.notdef 62/greater 63/.notdef]
+>> endobj
+1052 0 obj <<
+/Length1 1608
+/Length2 7939
+/Length3 532
+/Length 8789
+/Filter /FlateDecode
+>>
+stream
+xÚívgPTݶ-HPPÉ™&çÐÉ™–œƒº–††î&K(HÎQÉH ’sÎ 9#$ˆ€øÐïžsn}ïüº÷üzõvÕ®ÚkιÆsŽ¹VmVF-]^Yª„p@óùž4`ö–Î(]°ƒ¯ÜEXYå‘P0†pP
+G8ÚCзÿãºP(
+²BÂÑ€Û¬Z
+JñDÛ‚Ñ¿s£`·n
+uƒZ|™BX‰¼LLIB—Qdt (<okbu:æ}Ò{ŸíûÑ쓼,Vôâº4¯rèéMûäŽãÏõg\=-äpöæxèA­3gkö£¶Qî ~ó<¤]ÃpÏà µ%l“Ç+Ú:æ¹×w醄x‡ß9}™]²}IYΉ¼­*"ÉVb—åìì²Å|ý~ÎÞÑÛÝÕÙ|ŒÓºNÉÏ*î‚MÈæë”N#m¢_äa™ ŒéøÛÔªÏ!´0sL^µ$0ÙÂÿTh5ë¹[­Fúù{ª\™ÏíßÉúÐâ¦Ùé%üföC ~–fí*!Î:‰EvýÔzð­´÷Û6гßÕ•Ü 곺£Âgü«e‰;}ƒv©b]ùßÖÒï6”‡ùÚ}sø.Gj¢T«$Kñ£•I âQ–®‹Â~ÒìEÛ1w.ì*Çbr|¬½}$oÖ‡·Gs]> Ã?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
+ušÅ?Ó<–“G¬
+hEá$=k
+jK‹ê\ô#Œ²Ô_j$ø>Û}~';Äë08~Ⱥ:{¤j7l˜ŒEÖÉ/‘ÕØô 5³î*Tô#ÛýêŒm¥(Ÿ¡\B½MÈb\Zk³u
+ÂKJ^'W²Ù3FÁå¤éÉ.ðÊüÊÕúìðã‹’c=,®¬3jÉ/Ì ¬}橃”.‡Ó6Š& êÝîU¸¨Ûkh•kgݺKÙ!ì`M«a'x0¡ƒÌ ùts«,t-¥§†ìC+µýÝû¡ÝÒ^aâBý" ðf°Üpû š±›õvV¥³ƒÃ÷Ì ×pJs®a¯—ÀœÉAgÔ6tå„è/ZÅkQ^î›íF“’Ô¯[t#¾]°rÛÅ‹60^Ùý” ðzFYËP’OI*ÄmÉ×d«òñ¦¾âWfÖòûé!ou¾qÊÜCZhµ ÐÞ“iQ'÷|(D¦¶xÙ*ª÷d_R½˜Ñ%8Z?Èb+
+à‹)קw&¬š>òÕäø° DxùAt€næ£`öVkøqvëð1']/¸t ¡yô8,TÎ.a Os%/i5
+ÉzY`yÖP@-ª¤9¯ŸÇæžÓçý¤>Vo€Ì¢éªd>Í/ˆöõÏ}êY
+³¸~h—•¸8˸ƒŒFF¹õ•Šû?ih
+vžj ×`­Ú[­›öÇ|-…>°ë=].žàŽJ,}”›­ûÈi±ð!æÛ‹õÛ‰ÌJ«—–r•øœEk±9,ð”ˆO’ܽ…n®Ðq !páxÓ“1¶¥©~à]ÙDXÞÑTtÿ Xwd‰–¸rϽ”T…³k«eÛ?ƒ6òg¶òõPªj~«YÏZš{JÃÁp´hü@AÓœlú)ÿ€úBè×@aS‡ž”Y2(õ¡r‹¼û^*84å¹uÞVi¢¾¡HÑÂé…ØÊÏ–)ŸÃ;c4¢ž/{Ž¬Ûe/HìEˆ…jŽÚ¼9CÖ•Š ‚ŒüsB—W¨Èòè!&÷E*l.\ÙÈL4´ÚËÚ÷h„¢Æ·GñZÍŽ<çYÎz9†CÅŸäá¦TKñÅ3c/ÕQYV;Ò+Q%_Vªdá¸ô¿ð‘8ܳ v4e$2iä*õ Œ9csõ3k~YžØaí¼zf¡äö•Á’±¥;Éb1ª"(GO_XLô>ÅGçë%:}¨=Â[#™µ¿Nôp½vCžªÂíu>N1 ¬Ê¼íQù„8¬ì¨`æWn-aö­§m+´Y¬~5A”XĽh§"hV לÞ_9æJqB—¡Ìh'·ïžrs)¤<ÃÑ!]‚ŒšÙZ~\ÍHÒzU´NÏh“[€Hái3
+RgT­$vÊ®éï9‡á׺ù§ßWŸa|…psØ´"ÀÅÑÁñgð~¸¿Õxy¿oA‹z¾Â¼âÕëPúí
+GZ÷± Z6ÂlƒÝI§(²‡
+?Uôü¬Ë÷
+žä¶5Äõv!.[7$›\ÙÌù ö %Ü-DÇ9øÓ\¯ÔÍŸÄ7& Oâ×ÏžÅÚÅ8“£òÅff\Æ
+-â×6™…ÈXÓØø¬ï¾ÆÇ„)h}YÆð–êA±>–?qhYêJÁoȯü¸"Š˜‰œñµŠýVw$ˆÇÑ5-C¶Ãö&šg ŸI}2Ñ»5ãùáö¶DăuéBÿ;¤»¥ªïÕ\rþhüæx€Í?‚^z:“Å„ê!Ïå¨Ú
+DЃqB[äßTœB<ug(°Ø˦×ý9J~¿|º#ß*ý2üÌ‘ÔLÉ{¾OO±ÏïùƒiÌ‚øœÎ'=Ú‰dž•TŸT¿ÇÍ8ÕíÌ¿Þó£œÁ8©È«ÚÁZ±€,m³2ÓDŽñC£{p›® Î>*«ic:5uª ÍÐåS;ùEÑÎÙÀHoÑÏWçx ×ØÄИ0uÎlPÎ5 —¢ú½»<>ÕW:‹ƒoY2’˜HJyf€ÇòTcª§Y½ªÄæ'Jçx{êI_Í[¾ÆuE^n¥ñÙ±pmËISDx°ñ¸U
+JŠ+Y–¾^#Y%ÿ GpXŽÒ0Nãˆ&^-`iªiðŸ;ÐNU‡UîS’7K±Åüð[Žç&“vñ;ÁsZ§â§u‰ö´{§¸àôò‡ëòÔˆBW ×B‹CóáiòT£ÊÚÿ“±'ŒÒÞÚ¾ ZwÕ¢‰?UÛ.[ h‡)qŒÐÇ
+¯5Áƒ ¨“¹Ýa%µxkÐÏ_WÃp)ÉâüdÃS<C&fåc—Åo FÏT±Õ„ú°
+)è@#{ë>Y]K¢þäWOk‹à0É
+m›Hi‘œô d„†q. „WôâPløFûÐÀî±Ü"“­[¹É`¬?sòŠô£NÙêqüiv Ž&#‘ÑPb6G¨4Ùpòã¹>¼¾_$”ì¹J‘Nx?~«=!ädœGû¥ªw³
+‡¯0&;ì8u¶IýÚ¼ü?"¦ûø}¶lÞK©#«ÞÓBüFçõ'Ã÷bc-~Žò8îêÜÕ, |¦,kÏ%äq†Ö‰~^÷ŽÓ×™E°~r¥¡˜[©¹Ùéù _T¾lÌâÍî
+ù¡M½Þöxhá,ÿ
+áHQ þY»Bå<GJÞ,6]JOU?ÀÕ«Uh´\ï MNñÂçzŽùy¬˜+߸+¤ „#äoàùØÈ)ÏøÅ PØ
+Û9ÔB1®¥Ò[Yù=cÁ­öâS§¹óp—ü›ÏUÞYKf†mˆ¡ãž\%¬,Ü1õ È<o«»—ÆØ1D*@„ã¯O‡¿q¡ùî)uô¼ÍÌâýükjgWØ!›ÖöÎÏb¶wéÜ/žbmS`¼•9yì>ÕjªâD^ûÐ."ß·ƽú5Zï°Æ溱@²¬®fµ4ðÎ^‚›M²¸©ým|ÿ ¯©‰É«ê4
+$L¦nW`6»SN™’h܉¥::`í ?ä·¾:*Q “ן”„y·±,ˆÅ’·õç ?‘²}ùT{·BV°£3ëÉZmmsÇBkÙ-’Ãøá+@™d׾€ËM¥Üšô³lŒ~‹ûÛ«/xôñTpïÅM~âÓ¶•˜IÓAéoc_3¥KNI/6Và&âûßÕ{´adÂ{Þ@:C&] [°A=Ûe¾¶5YØøJ>ªí®(íPãHš(b"»,ŸÚšíÑ)„Ï\˺_ºw‘©¿cð>b»¨Oœ»ÛybôÃ$N`ðöL~kñ^óÛSïž]Þ ÙXƒ‚AW°}´e•!]¨µØìà×fÏH Í·Œš’ ƒGïa:Õsg«1ì8ñÍÑ –äiöÉñhCìò´g¯Ë8ßêô-Ì–~‘9V|T±&Nn·äML†‘§ÚDü”¹Ú>I^Ž”[û•ÞJ¶½ÕÉò< ë•Zv·yÁ<ü0ˆ¤5ºŒ„hO!ƒÈ÷sÿððd‡åÁúÌ´Jb+"ä(2mfƒ77Ê¿”Í
+8*v4ºÏÄ^±ûà+h5zê2¶;šÞþ,-õQü! C$yw9†CšJO ™ňq\`±"H,Þ)T<icº ¿ª}ZþK§{«Þ®ûªè&4CSQ~åâ7ê
+QH;ǘ¢&šùŸe“ô¿žUÙ|µ°Sc0R2YE]¨
+‡á{__bçâ.°ßþ
+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
+<¤þ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–¬ö…Àÿò!øÿ
+endobj
+1053 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 36
+/LastChar 121
+/Widths 2097 0 R
+/BaseFont /ZKLPWP+NimbusSanL-Bold
+/FontDescriptor 1051 0 R
+>> endobj
+1051 0 obj <<
+/Ascent 722
+/CapHeight 722
+/Descent -217
+/FontName /ZKLPWP+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 1052 0 R
+>> endobj
+2097 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
+1049 0 obj <<
+/Length1 1166
+/Length2 8309
+/Length3 544
+/Length 9124
+/Filter /FlateDecode
+>>
+stream
+xÚízeTÛÖ-–
+Ìj +àsÛ@C£†Ùþ~ÄA¦0°DÂöŒkX»
+r¶Cž! s{¦îâèhY¨ .Îæ (ÐòyeÿY(îàèá ¶²†é4Õ´é™þaçååšyü…
+²spü£Ò3…4r~^´Å¹*–¦’`Øíé¬a0G>VVGKSÐsŒjÉÁXéŸ* ±w°ÿƒ
+øC3 °3Èü¹)Ö¿ëf qpƒxýGØ ±ø³% GVMØÉ$+ñ?ÉÏ!À¿bV ›ƒ—r‚ÜÍ­Yÿ(©ááúdÿ#l
+±ðörtpZšÚAAÞ`KÐóà5uaÎ. o¯ÿø÷€h6‡Í@VÏÛð/öç0ÈòsES˜3بÏÆÂÆÆdûãÿÏ‘áó†Z8@ì<þ•®dj²Š*ȨÈ)2þ½÷f‰‰9<S2³¿ã2s¼ç~vÊ3#/7çßÿ©Å_:üU1ÿÏ:ÙþE) ±t
+ÝØ)[7q\ä딬Ÿâ}2Ç”¥Wº4BâÃ8êÁø¾d7z»{NÊ/IÈKsËQ•÷fèy eì|Tù^N ~“`³ IA“k¯¿¥•ÓC«?¸Æ-oÃ1™žéÃàö
+–ÀªOÌHt‹ßñ}n縳.i±¼«tÌå–ã4t\dêÍFÔÏZïÖEη2Úú`¿Lè-Š²FsŽ]Ä!JÞlø*@çìwÓ>ׇ&ª©æˆy²¥@¥]kU>=­rEÞ-çŠÇ™°V£¨ÙaQmL1!h²R%^×àj¸Öl;ÓÛì^R‹
+8ÆßÆûOvj(øÏñTÔ¤\¥+Ö#2\…¿n5;ÿH¯i}¤ß®£Ñå~º9$m`Ƶ'4É)ù6b›•½.†eC[•+ÚËG}*”µ>A¼­dÏGæjøf¬%€Ê4ìªÉ$›Š ÛwÃPoÄd‰÷ú´ÊÈÓƒ8~Gžõ‘÷<Yqðæ3z©ÞÆ 2[¢ÉIJIH>Èe¦_h‘Q¤Ç‹×g\<©‡3Ѿ¯òJ­’ûÁ«‘e‚gìº N¦bŽO+ÞÀ“îS­™c­Hœ4ÞCØKH÷²m:§dÔ’ÆC»t½€!…Âæ©.—IóÉ^!Øæ¾ÔD’ZÐZ¢˜ÝËMïQ•¦ùÜȇ®CÄTÄZÅ‚zŽz­‹Ä#EÄ7ÏLm}.éF?:ÃÓ¬v­Ä3*ŸH“¾˜sLfZžÓ$Vf‹B4®»%DÚ”6òÛì!Ó7ôRI¿S{ŽØ¸Õü ØKÒG;ë¢Od€V@Sp¾¿–_
+eÀ_±2äÀéŠê×Ü÷qóºÄÃfhÙzÇð#e6Pw=3vd[¼¶#mýç;±ýO߇P÷LèLI Š `ßy·bgh¶£ûô•À|ª¿2Õ 1äÔ@ßX ˆãàç¹ÒH_Li¹=YK/0¯§E ÒÀ(èù\²ÈÖ«:˜ðCÃkX[ÐBf µÝ÷l¼
+¥ô€áëÖKŒ× m5X€>ÚíÀ½ æؙԄ(QjiVJÒ˜˜¢`ßÛCÄ9UoðzÙ„íÖðWvªD+ž
+VËkþy…Šä]WzÃÈ”} ÑDE\Mó½}º Ÿ záuÙ Ë
+Ec'b£cƒâºb+"±¡ežê±3<}M ëMÖM6À–è¿ùùn¬¹˜¶´30ÿ= ùƨÔc¿¯¸§šŠQ½¤
+cª†O\—aðIoìì}¦êZzPoë
+Û¸Áü—%N㞺°Åøjâ6c¹×tÔ¶­æ§dÆ#ÒÎIî!QLé=+£oì·Ìl‰Hžñ EF˜‘gr8™!söw’RZ¥÷ªëEËpÍxé(R”Iã½E£"ŒÖ!$ÿŠ+3þà\aø-ñ^Ønàêdb{QÉ°n«D75¡¤Ý`:4ä¾é-TËu—6"Ä;ü¶·M9—sïôñ«£#ÚO1èÒ{!Ìá8„‚_Ü2ähh.‚LjÚqÍŒè• hê1€RàZlƒ‰N?Lä&ÍÀ÷ÝÛ@Tý¾‘VÒb\0í¡ë0ÿª…É0N‚%»î•+1¶•Ì1ÁÙ7Lûêš_Ô>X–ÙG]td1KâƒÑŠQ¶SF$‰·U¥8:ï¾Ó5Ÿ½OÜÇ'vp¦3gGp|wã›À„J÷Wó¯c¶LLËFÊY7pŠäh·nK.q ¥'Œ/®Â9bŽ‡±Ïw 9_2ÇÐfÊê¶VWdÞ·¸áË™w7‰œ"Óù}R4T˾jVø?âó~:Ãí1~uÊæ|*€Ó”ʱŒ«HÂ@pÎúNšú 7¹á8[³?p~¨y4Ñ5r€»ö£õ5C6Œæѵ,âM˜“ÕQÓ8®‚ùÐùU7 ¬Ûþ§>S+zâŸ[VÑUŠ<¥< s²Ê&:Nð )ÎIJÀÃTãÃX×ò
+ÓsñŸ¬5ŠN!úŠNÌJiJ¥…+kkŸÏÆròæ¢ß ÛŠ)Äxžcé\Œ>Ð~í.í¯râ<èªëf׌Óy¬VÑ‹ÌYÝn§ FÈK Rd"1f…U´†ÇŠŠ”> ¿¬öH‰Bç9Ÿâ‚â%¨„$‘ûò$,gÊóMV0êôÈ­ž·ñQÔ‡‡´
+åƒb3èu¯ÃízSHø”Ç!=ÐSV«ènÞèõÐ`åÍ’ª;qg?Ìj†o+ÌÊ€/F;=!`ž· ÀË!¢Ëþiú)*z‘ñÄïø.ëœØ½ 8Òà4AgÉ—õ:fÞv\JÞ
+L^e°ls›NäºÔ§ßýšR6úù¤Û°éµÁkkùéÓü½I°±U-«a¾rBïñØ;e9Ïx¡‹K€q("Ãßj¯mµW.~ØÛüÔÚuf«ù)ýûU=¼?R‹ï7éÙ5ĺºWéŽò¹ÊaÉ[Ð4Œ@Çrßg|óy¢X–%}ƒ _l3÷ó*CÈz:â0ÂÈ(PóÇŽZÝô†vÌ£1Í5KUFêçöóÉ„¨Bß¹DóV¿ý\öâ•GþÐò$uI“!š›*«±5í1ÀÌD(©u›P¹©üò®¤Ãóãõ€2^DõÚTnÀo—£AÜžÈ77lŽ×¿2+ó33£‚…VØsùÜÁ&ùK
+
+ ×yLˆßº§(Pœ(4Ä3dBmÝkÇ–?v7‹]çì£ PܹïÏ›ËèÓ}
+ð(8ôðY&Ò”}„yäÖ5ð±KêÑ&Ek)Oá†x°ñîs=BˆFÆðïDœxѯÁÛìÍ㓶‹]Õ¼ô½Ó lIÃÏ6<<*°OÖehÞÁ»GÝ„1S¯¿–Z
+4; ÃkÊZTwïG¶¾htû»Ï4êªÖR¡Þ'­ DIn>˜Qâܤ¹*'_I¦äÆ6 ¦æ>»\<º¿UQ, ‘baà&#ç^ËmÛÝ[oâù$Ç©e$òÔqµ=¿=jY ÄPs˜³ûD<‰™*Jß–¡£fo,_mSBºØɾ z ªS Q_øi¼ÔR@¯KFÀ®+µ™øìiåÁMwš”¶µ<ñiÒ^ìjg–Öëã~f쇬òÑK§kY¤Ó
+
+j¤¹‹4;X£O<eïc¯¿ðK’s…]䆎sÇï#ó ThäP•©îyÙú¼Ø ¤× ‰"i§ ¿wç}¨Þ‡ø Û¾yI¨A¤ÚáTŸÑ8{Z/|&jêãõ®Ý>]ãPò÷2× EQà{‚°rëáÞ8,~;;ÁWâŒÄ¯Fõ9ŠCá•
+j[ÕeÀUoóOõe¹#´M7îL°”XËzÛƒñ…Œ‚´Wvû¼‰¼†Æ«<¶eªhYÃ<ÀæþÆêè²o¦ B‹Ï¯¢:YAW󹄛é_³óöÛЛë7.ï.¹m{(Az>oɧÊé^˜ë@Zc—‰7*wÈê
+›»WVö]°dÙ®ã\öý™fÛµ‰t9¶¤V}îñìÝØì¾Vᱸ¨Ô3Z( -ógWÎà iÔ“g±Âî1µúnG¿Õi/ Ö®aª\z6wH5VkÃÂXŒYg týSH}vˆqé-ÂY/Dbø¼ýdyP8s
+$RÇÌvé…h'w$K´|†·í…§™;Y¸ñç?óg›+HGÓðF~pQD=YwW´äL;v£ˆ§&Ì3p}OG_½¼¯2y¼¢@Õï·URåo<õ4"¶ÐþÁ€àþ2½öÝCI;¥ €)ª¤ÿéì¼Íµ¾ZnùˆÛ„œß~‹øŒþ—¢@™ðÔ6!†%ÿKu9Èš¸ØA`ŸÊŒa¦ ±¾!¿¯yÙ´FmîLRÂöqu8.ó‹j5Žó®Ö?ÍžÉÎÅ¿ïÅ4‡ôc…g96·¼ oìŽ~¬ðBGÆY6-¹ª…M6õÐêY Z`–ÄR:´t‰¡¼JÆB ÂP™\µÔäœöF-<u¯Âû]ÍÞ¨6ÆÚÚ”u0ÜôæN;q3ŒN³Pq]Øw'çjªóMõÜA0”‰R‡Àâ=ùé.Ùèí'wÜÒÛD†äúŸu®ûÍ£\y6EGíŽC¾ô/èÆbIÝ72Š#ÜrnTözêñ k7Ób’Q|{wy™ÉsŠBd‰êqzðõåñ·D‹,j1^U‰pðá—‚[vžgVD#vR…ôz¤uí3íë œ¬ûvªÈ¤©³q.ÑA øƒ„£Â«|Ìon<oÌaJ‚P4„¶@“ bIðò)R!%|rÏOì6&Ö¡‡Í
+s–¬7ôäP"sÌœ9|p]\ÉlfÏ'ªv7K¶iÍÕ$¸Áî}S[ÜVK cب0D×”ê0Ø5ò«¤gitËZhg7ñí­¢•dÞÚÇ_ê¶~XD¦pô§Æ%=Ñ*F꟱–⯹ߟþžª+ ýê»\~d+Gϼ%OÙU2ª©³g(÷|˜KÞ8åº~ý=M¿¨U;µ
+ëAv4>ÂâÉb[&èëÛXåõ‡ R'䄉¥ü"Üñý"É)¥F{WqÜj³‡h!YNéðˆ~~ò"ÙÐ5Œ©»Xçà ‡‹-Ýxä%ñqÉ>ÿó1¹rP*#7
+¶²çìÞê’ñ¬Õ(àmÆÊÞš± ~µnH¤a0³•JT½6‹’¾eËŒL£õ•ÃSóM <zÉÞ7B“Ü¿‡Ì/ñd=£TªÂ÷!Ö«7#.lG‘e‚ª'6;?3n*Ìö{<^iÿyŸÇ5½ÆL ž›4Ûã6P_††
+Ëȯúô$ šü=Z¤ïs£öjïM ­È"±óBc!¤d³£©Ëb”ű‰„g²@›€³y‹u
+¢ï,Ý™Š£°ƒûüµ±ÒI‡c&”ü¼ün®'ñ°~ÅH¿ßýø ‡é+RúŸRû#Ì»’ŒŒ[È1Z‚«„äî<úüEþ„þ'¢DEPˆ¨½|”‘s¼j#U(»1é·–½,ÝÓ4Ešç×Ü WŸuÓ‚S{:D¦àæ }ª¯ÏB%Ö^‰$—Y –Œ8Ǹ %³šc&h˜!ç¹ÙG£ÀŽ–+([;3ˆý¡ŸA`´ž°ç£G°øªlV˜SÞRÿS”W~V'¦—,É*ZÊÿëH™­ >FþrRZ§³¹™ª$@!È¿Æf'%N¯Íqg'á4¤ÄÛeù+¡D‚A¿x0J1»ôÖ©Cøp:©¡Ý69‡Ñr;âš>ã|º‹Úˆ²;h“Ùé gÖÐŒíõÒ½Ó’iH)è¿iŸö&Iû RKÈÜ-‹Åx°VÅ Ec°ÖH·1ÁïX™hF¸íµnQtCç¬``*<L5f¾ž‹•3®h¥ÞÞÃI‡€Ú;¿ ñXú¡}JlZaÒÝO—˜‹s1ä¥gH—Mî\åœàdH
+_„á}<É!‹à¨'…K^y‚ë:­C†j½Åê%½2šI‚£Dϵé¼H
+Å2ÑÈùðîì”í êzTóM¥ŸýØc¶ªáq_Ø™
+endobj
+1050 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 2
+/LastChar 151
+/Widths 2098 0 R
+/BaseFont /ALHPJM+NimbusSanL-Regu
+/FontDescriptor 1048 0 R
+>> endobj
+1048 0 obj <<
+/Ascent 712
+/CapHeight 712
+/Descent -213
+/FontName /ALHPJM+NimbusSanL-Regu
+/ItalicAngle 0
+/StemV 85
+/XHeight 523
+/FontBBox [-174 -285 1001 953]
+/Flags 4
+/CharSet (/fi/quoteright/parenleft/parenright/comma/hyphen/period/zero/one/two/three/five/eight/nine/semicolon/A/B/C/D/F/I/L/N/O/P/R/S/T/U/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 1049 0 R
+>> endobj
+2098 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 0 556 556 556 556 0 556 0 0 556 556 0 278 0 0 0 0 0 667 667 722 722 0 611 0 0 278 0 0 556 0 722 778 667 0 722 667 611 722 0 0 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
+1024 0 obj <<
+/Length1 1624
+/Length2 8579
+/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_׃ƒóŸ’?*
+ÿ†‡;bÿÏ80=fë rw¢yâþSæ ø/Ù]]}þ²†þ¥õŸ1€áî g;nL>þ'Ÿ6ð'ßö`&ÏŸaQØA|¼Ëm=\ÿy‚`ˆõÏÌ°=´…Bœ}
+«_5Ücâ->³ß]¶UÙwºHY:Ó@'ÔÏÙ¾¬2·‰pì„òX”àdÆùΨ¯£˜óìlŽèèZ|ø…F3Ö&
+qh<ë/=íq|ÜÞ>“f¾WV “Ž]m(;Íe J[<ÃaÃlœùb\¾¡ æúžè×}#-#ÈÉq©¾çeÏ[9Já¼ù¢_¸ØWaøáÖß
+ié”ç-ÚX'ÕE1xãÕ^r%LSõ)çœ+眛 Ë
+<Hh–~H{ úýÖ¨¿®_#ø{Öq»†ŒRÞ}ËêàáõwuÈ­5/‘ùfXo0º²ÙȨ~qÑÔ2š^¿—•tËLg¶M–-‰—
+K1<›@T¨p\¤’‹¤«oë¤Á‰Ý3´Ž'öä÷6Ƶ"n^Þ#‘µÓ‰4Kל‘(_§.‹Ué¾°PµÏ9iil­\ «|¥Wñ¬=ò7>õÞÇÂ[&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<O?µÉ1Q›? N7öÙ; ~­Î6Ä“´Õ"ݾ2.A;Á
+ùzòÖ€Ç'éö±i©Ým¼…Vk%ßÕ’·3ÉÄ궋åË+Üt ¢ 'ÙèÚßF¦TÓ'ß{öÛR?SƒÒÚ-búpVûȯ×Ó^D .P?ÎöMF,½Ö—BåIψWcâ·å}eâ²ÔèÙ7lÄŽÓ$•F/
+Wòí\Mߢ[œ¸ò³FŒ$¯áƒc9Iý|Ù—r d ž…C"ÝÛúÎmÌÔϧ>)3'ï÷*Ò]_™¾ÓÄÔ~Ÿ®vx¥ÞòÊ¡
+wøvÄü¸61vø'6çlò=n¡íˆc–¾Å[확;ýQ3Z¦Á„äô™Ò+~Yq"§÷p1_—Ï<!Õí;âæ§né© 6×ÞË!ôÝ*?Ö‚/Ø\ò`r*ËšúÑtØ´Yó&×NŸ·d0êë„«’k{%Ø!£ÖŒ¯ª=~ s‹úŒÍc|Ÿóç}¶wý>.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ç“:)õ
+ý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
+ÓD‘ˆy“ìÆæQj})ó½¤dï=¿èèWh£‹q>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
+b&c,±í™Ðò´6@ýMãÇlå‚¢Ý+§¤õþŠ´JX)Ò~Ú ®~_òŒ`|µ*ÊOw`à™]ÃtíÓ?³Ý…‰ÎZÖz¾xï¥<QFöè>Ý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Â
+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[<mÒƒýÇ×?^Dtú¹Pi(‹Å¼¬ŒfB)…iã™Àòfr°.Á}ã4<åòXFj¨ž‰.<P?ó°-—RJF6Žr¤•ææ\’è¬ìÔô51^ßúkÔkÝ ¢ø²ÊáuÑ„ªE¿…û¾ ] +9Z@ÖñííwÍ®¸!Å4¢mee&®PÖªñÙÊ\;ÒAª{Ä-h'æ!z}²¨ª5)äZ呆π$‚~WÏOLŠSá+óÉ'½-±sꨙø˜\I¯m!÷²ïY½’똟“Ù¨*Bqä¡*¯¨ß$7”ïæç]J…î%~ÌNoÖûšÁþ•_6låÅùÝukA³ Ê–‚ŠBûþCñÑß‹?{šØ+/øxõš/c#MÎE ¢ˆ$YN?Œönˆy•»ndvúv¬í´4• à éºñt½~¸õ¦'dFX¼ü8a
+É]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š+Èó
+^õ,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ó¼žýÂ
+rW²tˆjêÏé
+¼õ¥¦Ø[?°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'Ìÿ
+endobj
+1025 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 35
+/LastChar 122
+/Widths 2099 0 R
+/BaseFont /EETKYY+NimbusMonL-BoldObli
+/FontDescriptor 1023 0 R
+>> endobj
+1023 0 obj <<
+/Ascent 624
+/CapHeight 552
+/Descent -126
+/FontName /EETKYY+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 1024 0 R
+>> endobj
+2099 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 ]
+endobj
+1016 0 obj <<
+/Length1 1630
+/Length2 10814
+/Length3 532
+/Length 11687
+/Filter /FlateDecode
+>>
+stream
+xÚíteT\ë–-w‚-Ü ®ÁÝ]A (\
+ww‡à…;AÁÝ!¸÷à—Ç9·»oûúWwÿzãÕ»ÆþÖ\k.™kÔä*êÌ¢fö&@){;03 +?@ dkââ¬ho§À¬´pQ6±Þ
+tø b8
+¯Æíwu»d±Ý‰¹ÜÆXæ§R÷)Áxãi³åyª¶š—ܾí9ÞYò<0”jûˆ/²­pÛ2 D¯"k<û¶¨ó¼ˆ­pΛlxEv'Ê%Ëž…¹`|R_•·–ñÿd{÷ç9óÙ¢Ü߶e@°-Q–äÿˆO$¯ê2Á³|ÀnåäÉ4¸Ø¢¶œ£íG>ÐK´®‹²üE{ÝsÔGµ÷Î~ï—¶Gí'Ä”›’V¬Éà‡$¾}¿6?dÊ—|ñÔ'Hr;ùMŒ]IJd÷d“ÂUu?¥¾q¬Àe¢zœUú… ~Æ¡dë/O *‘¶²læ ³,D/L§­„Ÿ5)¹;+În3†Ô¼Á¼ô× ÃXؘA¢(¦! rµšT ®çjm¿‚ˆ"ê:=8„é‰ÓvÅÒýÒ´ÉoèwÌ»ã¿ÛŽû«h»‚¬Î.zµŒ4Í$‚Ÿ!‹8s»wè«© }ÌT8-TCšP×í±¿Ò‡š…ß¾*hÔ>_˜A‚»êEžä>A£%»Y÷¾¼Ó‡—
+bEh;m&¶2q@¤}Ï7 ëX£ÇuénÉ=µLiØ®Z#‹ ÒÃxLçÜȾÓ>•ƒàÑYô…Í ¤qk#è3‡ãMà¸ò“üLvq|ìD\0D¿Åv „|uw•­ K³KòÉôﺸ씪ÊÌ=½Ðz ¢˜A‘'¨÷GêîéÃä}-.ÍÒ!˜ 1†Akµ§„öŒÜ̆(;¿+ñ‘7ÕÖÊ(C²I|ÒAÿG÷CŒuŒrQÑV…=3åŠè’>·uŠ?œ5Trh¯©ŽòÒ^¢HNåç4 ’/Sîˆë‘~_Ë.ÿôa÷rû»õPã ôdìo0gùš²þ›</½‚Wõƒ'…‡Ý|é䨳 eçK[ ¯-8(VÅï>D"îbHèœé–š”¢‘:æ]jx6Ϥ0õ!5½‹%CDAçK*Ë3W'Á¤='€.I5p4¬›#CF¢NóÕ`Âv'F.ÛB|Ê]ÞOŠá€íú #&ãøÆ6“¦P~…‡mŒo7±™›1Ϩ)b´S«ü²h*^‹ÅÇâçü¸ð1~çŠæÆß_ÒEàj¦cþسի9ôžÆP±&*Y £ xkâÇ¡r_u¦Ó«8¦Ca1è³M/FìÝHHºq˜ÜÂb¿Ïá[l×êkû¬úËƦ¡¶¯F$¹äÆÇ´vyW
+†üdË‘È)ÜÑ˹ʱ„ƒ¡¼(«BuV•ÚèHbNÒnAÂé¨X^‰$2a€ÕóEч(¤hÉãcTsë5V»´"ËŒV÷o¿=ÍÊ~€íçÙ7¡èûÉ;ÊÝ/ÁP®}€ ƒ·õMDK°+Ãä²4'ø«<£¥sâáÙ9,ìú)t aúBD.ÈÊ?ÃîƒÑ $ÜjIàsT¦9õ¸zNÓõ% (ªÎ»é}ìsZ^N Û÷FÎ9PJ‡¦4k[«ç f4e«’ùN·C Ì«üj}B¨ª–^xÄ€(4ì—ß«qe Ë:m“®Æ ö¤¼êͶW=§µjØÊo„’Œ 3²8yj‰ê`nûÁâ'YÚTKM”‹ùÂÔì %Ù³¹Â]¢þãEš ®ßHœÑ"P/V,N~οPóÙ3ãþ™Ç ­ù¡cÈeü¤S¯ƒ´
+ýÏTa%ª£3»Ùª]`ÁQ êó}³x:HX¿U;úŒ hHØõKጬ‰•Y)f.¤«â£Þ„ÇG8îàôº¯a»p7åsÚBc£µÎ¥7apx X&_­ð¬)wMÔY„«9y™ÁŸe!Ë×÷*$“ §E¿jéŒ)f?ÂwJ×ÓŽRIßU±($ {û‹xÜ©ÎMYÈÅäJõÅc?—Þ^Ì:yðý¡_nA7üÕ©Ô–?Ài¤kðÉPHRòÎzçiÞY­Ýû+Öäˆ2…tzW3¦Ž­à:]q¨¢–½¾:µ;›ôšÿL±î\ì{¯1üÛüë]¥ôî•ÀJªÏªœûÄøø¾z$A)ŽöNÏÊþû>ϾЇÑu—ßR±Â ö’ºÛua{Ø°¨ï•›)wËÜ%ÒUùœ×“ǘy‰–wè–š7ô¹ÇÑöˆøoµÃî:5Nö˜~ø§•ûß¾ËPéä—b@3¢€iÓ,m ¥däg àø¤'®/}"Lø¡-”ÉP&kB;…}ü§D7×±0œ^þ +ú)[¾ž¤.ª×VYzd,Ò#áx]RÁÜõ]òe&`”2Ÿé3WÀâ•ZŽ°X…Eµ®ÙßWÌ¿vAJ|,„$={Kýë§Ò/Ð0Ñ4ͨÙEiÜ.äîOîþŸmÏ)¶9ÜÂOq?¸ ííë[ï]ÄtŽþF™]ðL7
+—ÑÅW%HkÂE©(ˆö6i°¶&b°Þ¨ïnwÓ÷߀MÙð#îVbjXèÿÞ«[k‹ÄA³±8Õ 7j/I$Êý¥í¼ž;‘zJFžÀÊÓÔµFÑÌ®mÆ"F̶ƒ°‰¢2­`Ÿ¨3pCQŽf©:ÇvlÔÁþZ[zCºåçš8ÓîŠu¤ì5í¶rÅŸßÛ¾25ùŠ †ÒVÔgó°Õ_Γæ@ÒïÅ™…Á)DWÐ6+Þ­ë ‡ñß¼©MüâÆaªƒi>_ªóCËLD CP]ÐúÂL½\=ö›ŠLE Ñ:Ç¡õ>_ç¾”ÕÓDÀ`h{#oÜ1§ÌT«®X²é¦ nh¿,ÿá2ž’ ‰ˆFÙ`TMN>ÜïO?èdÚg>|Y×ð²,"ë•ÊWBJ° ‰ëÊw ª7¹·DþAG—/Øi¬\¤C§õœ.óbƒAÆ.Iµ +ËÁúŸõ#¤½ü?PÝuØ¡™BŽTÜksmuçÛÇ¢,3ÔZ
+rÍå…Œ†ê# Rßò,"lêþ¨¨T"‚è:‰¹'\â­CrÞ×z,Õ¸ §A:æ‹Ïg<¬>Ú'dPîÐÿ¡1ŸibT,­L”¡ïéd¢º6[*1½[)R«¢x úJ6Ž°ÉÊlÅß ùЇº¾“¾%ß6%€ÌZ€ÿ@ ×/Û:œŒœPœLö'½<Òpk\yOO6ÒÐÆÈÔ©B"ÑitÚ>€Bµ8o)vçùêµFÕ¬$¾üESúÀŸüY=ÁÂýŠŽëWÝÏ¿6nhϽ±ý;]¢f%(ÞŸèA¸Ž‡yÛ$o/Aûv sÙzOÖÆ’±È^d¡›_Û"Õ3ôܱS+­¸Œâz»ö­‡?5Šž:¡ô´Ä)lI_%Š¨ ªÂý»6}ê™;Ç]CË‹/—øMÊ›md>&ö3¾OÝÑzÙ¢²ÛbÒ¿'•?OäºÈ"`ùÌθrÌJâ˜ô튓yðYtè»;íAýºû);†1åO¯º2¶€ér´¥Ró˜”LÓ Á©^šv¤öŸ‡G/„ß_ú±Ø«'.‰ªÔM“k—K26é÷ÿôWSºÛ§¯÷ŸšN×V¦KÃã|³DZ£…C3¿åB”‰…³[ÏY *J“›Ûä—añüïM–͇»‡[R»³Ÿ"ýŽ‚fç¹8¬™<G×JÃÍ™Úx˜¢#Ïúdç/û#]o¥LÒ( ª–Êô}.X¯²þ“²{ïC\Ò§;ûè~&^,rÂEÀÚÒGØÅ ž`bhUh×5çAÇú{ÊEkõ¼3ùÁ¼íXÙ¨®ê6~•jË?è[d­{4qó*Šçv¡ŒÌïßì›ê‰ð~é™Je ll[Ñ·!²qšï²¼à>^} µö:›QòbSpìØcø±gÊX?KÀð~íó‡6ÞOX¸:âZôÍ 
++Ë,¶öyL,Z&1ÝÍz*ÐßeÑIå²ONçÓ‡õ™Í#ùÝ1Éq…•-eÀh‡ÛQ$ßn:pEä®Àì]05‰°=5˜®‡¶­2P‰5eÃí+–
+aÉÁ_¹5wCs̲ÕûÖþŸjÆàùØ÷–¯ž™‘ÌJþ¯swQ⢃³F‘1b˜üÒ|ë FžøßIµç+x-Jï)#ÌÙªëÃn¾(ýpð»*tYÜÇÎ}Å›Ço¸Æ³jÞÒ±ko{!dhÖ- \˜`[Kþ)pLžXlø ÈÖQø~‚¸×Çl7¬S¹þ›¥*¼”>§Â.öÝìþñÃdi‘;`‰‚j#–•µß¯XB`ZdHnh“¿èI¤Ž$Ì‚Õvz!Œ^ !+NypÛÈŸVͧÁ`f–fU®äi l'Nªw!]ÅúŸÑ|È'Žb&‘$US —ŸÞF`'CŠ‡r(¾Kª‰;Æf+eZ´X‹+öÿ说oÃ
+®0QU?Åt v¤T1_¼Yp¯ÏÑn1×’äê'ŒWÔZB¾y¶¦}Âw’ ë°È‹G¤Î
+f‡dúë‘|3ÝÖ¬9»pï°h1ûó¸í•½ÈW©”qn‘9¤pÙ²Q@ýDîã6Ó>ëo\,«m÷º·óSP¼ÕÆé‹cŠ˜/»f€¾-Ïxˆ®;SëP´JáŒU'â#VúÝ](ëeQb}–¡˜hïá\¢°»­ŸÓ¢aKY3Ê´R°ÝĦŽTWòã?É ç4ÙÚ¼~pÕôÉs;.“=@K?ò°ÞŸmG¢«Óg‘n1»€˜ótÆ[;ËæW{¼«ó¼¶¤êqáãï876} ÎÆEòY‚i›XëzPD}ÕÓq>ÌÖ=¨[ÓeÚÚÛ-DuoãáTç+ÄGQ½Ma.Ù¹êÜ×,r„U16W Ý¡UPÎQâ sªÞûÛT—ž´Þ>UtB%®Q?™†o\?‡c ©ãàò DíDÞÌÁ<¨‘‘å±cW'}¿ü%)yõ(¶Lz,£›Ú÷=Á‹º“Ûˆƒ„ªk_mÖø'\ÿg:óÈm§j³.”ŽÑ}½³‘šÞJAàÈ<X¶ûUõP=ÊþŒ¬ÄPC_*rËTs×çñ™¿l® ˆôòݽݵJ^‡Yn½Þë”iõùÖ(@.ùÆéWšG>¶¨â>ÓÇBt^¿æt8Lyäån¨ðª~ÛÓœ„×RD"Ÿ"nN4U¨·áìDz
+#ª5¶ãƒýŠŒ[ônjŸÛ\vù$/ãRÖyÕ\-¨üKŽà|B8x“AíÁ.O_JŸqD×=®_ž~:? ³7—2⊦Ý|jèÚ~e“hŒ¬Ò`2Æ`PzwL˜,Á”‚Ó­à¸=] {¸â>uD-‡UÙð›Ãí÷Qri|&
+Ô>ÏíFŒòóGL2Õ×i#yûyNÕÓSáÄ.ì(¢ ê—´®u߃]bùž<hŽˆpÎ<Ûê/Qmé‰ñ3¡
+úÎŽq¼E{¾ fáñ$¯}’škªÇqŒi†ik›ÈV+Rê°ƒØÆDK'æ—{áß Ó~±ªßÂ5í±”»±ÐNû†c¼«PèR)r°s½e¾ÉQ­‡‹ö®â߈T~7`ù½¤w~(  Ú/פöHóe®B'?/ÇÃ0SÏ) X&Þ‹“f•mhUöN áîË…;<§­ŒLÏYì‘ûAߪ»=øþÎ~eYá€37¬àqÊ„ÄJóWmÚ;
+ò<e{œBÄ4è6X~S…ÕÓ´¤mF¼§k­¿üJ‡­"fÒ탽tâ #ð<ŽNÕ½¨)­“o¹ßÖ^ÿˆŠA«-|o¬÷é&ÍS&Tí––
+ñ]X}UÐDÇgS_x&W_d;½´Ö‘tˆ-…%eC˜Ww:.{ñOÎþ˜­¢¡t¨_Døiņ@×}Ýò‰ÃÐ1ÊÇ$¶g¤ ¥&·á)^D ´¢¥Îô…ë‡ÔïŒC¬‡“Ba¥†øêLÜþ®‰nfÂhš*ë(¥=àëڤ̋>¹Tè²ÕV YŸ(uAyFìT½ª7?‰ã[×4¯#ã:ªÞš|1¥·cÿÂÄ=SŸ¶Q,hÛñðh]©¤ßûàzÑ÷ùÝQywÚë\ç£V}—À&}nJÎ_#2ž½+¢û%Ì°Ë=NIW™H9ถÃM”†òó?¹>HÛÀh[ÃdýÀ#þñøV¸°ÏjT̆Š½Úß'9Q£•ðD
+ƒ¥=Ûe!sdê)‚.l4lóþE¿‹'@ÑN“Œ
+žKXø4¼]íywbZâü™rœ¤ÂQ-<µÏ¬À¯´)"‡£]·ˆçÚ\¹çyy/Àbý‚ .G¢×.èßY÷®! É>a'c6CU¢y{nÞ#‹MÝ¢UüišB|!# V­}'­5®Ð±äNÆ ]túPÑ:/­ò¦X˜f9Žó¦žWv·Ô•©:N"õ³g²N î‡íæV¾–HYÈ.J°M¼FWÁqAéoÑxJ!&Wðˆâ­Tþ“$(®m Xïe{Ì××Ð8]/^¾g«Äo‰M·9}SO‹ý‹³n£zbÏ<3³ºÍö½9dÏDy6ÔDPM:Žð˜S“ wh…µ„cK´Äã‹{:Qö¦Ò-‘þh[N½œ;M7 !ìX¶lç
+ûÆnÅOøÙ/šåvýÑ;Á¿Š(æÀêzÑÊ–>ì9¬Ç”°n÷ùv®Û·Y^+ùå+ÔÅKl—‰æÀ+gbïç6Å”E”vÕ8÷¸Ü¯¸.ÔF,ÜcjÇqx"3¦Ò™L•*×5FžÅVÝMçï©Év%¿ã´Þ'£N·ò6iM¯È-ËÅ8ò̉Xµ3<³ƒE´p“®Rºçèg
+® v'ö½Îln;mÿFN• +/Ÿ3Áô1êˆõí‰~4HFz>5#Ε{}mBl+ï Èà+S>îϵ ³3™ýžYZÍ?º°ü|(ø«8EÛN¼-<g~£PØp*Ÿ<Á3—æé6ah/Ä°l;¢,,r_T¯ÝXƲÉ%Ï™Óßæc†¿¾g–µÚÃw°QY>Zr^’3©ÒÓ8 3ÅX£n Õ¤îc„Ô#gAGŒT3$kÿu‰mßêÃ0¦ô%BV¾®”ÍXKƒ²ÿ )¦|¶
+«÷îõç‡k¥¨9îx]R Éé !lŸàk<“™HÏÕ2Ú3'Ð_}Á±nwYíÖP¤z™$z¸ˆå¬uBZö˜ò,ïД‰ˆ6”E׋8'<óٔ᭦ó'îôÇÇ)§Óˆ%£‰[LgPÌùÃ[VëÁçµü÷=iˆçv¸#¨<¼‚¿ÏûN¶Ë9·©\qwqVb§E9¤»çóÆØ';<G\òp›Ýk¸ì1Â\©øÓˆK
+ÈÂcR *7Jô1B-[Å\‰Ë^áÖ: QÌDIB–-Èsì.¯õqþeÖÄ*Úzá[L&y@ 5þC5
+wóÔ
+Áéãå)«#sLWM>†0€z!1q*L»_E³%)dª8„qb" Béãkë}™`_ölz?d(d𠺢¼ùŠú·nöM|Îëv N–È1@´é}Þ…gðvÉ–ßoµµRj¸Mk5"YŸ~bÐW¯ÔÛǦ¤}wQ1øA³x/ÆP/3Þ‘,¼#[¹3'Ì™^4ªýJw“çM›vŠ%Y37ÚZ-í!ÚZ„¯Nêý÷ÆA@U/#ÀJG4½øˆ®Lš„(Ûq¤—ZDÉŒf%)1[1$EβU?ç]ùÅÏ÷àº|/»çº86
+ÏÆ^é(t{äg^Ì)¾^Äyoߊ“8E˜‰YjÚ é]ÁØ¥ÙDf’ø iÌÌR¥®Û·‘•¿#ëÊቛ¯½ð“_“9>~"iú
+M)Ã9Âp:Ä'°ÂyFJv5„yfù¾ZF|šÿ˜Œû;àcêØBüß›©î¬ÃŽNÌtèÔd/O7ðŠëË–“Õ7ÑyD¿‹3<B¢ažpøwâÎÁû~8J­_¾\÷ë\·^M­ùífƒ‚Xv\Vr€åÂÝñx4O?ï:±ªY¤xg$!ZÏ6ÄÂaé’±½òÚKvª|R¼Æ”œ k½Ò°@·&¥1ú-lß0ox„Èæ»W`š¯{òø»î•ÒÏâ~­E §…[2–ÙÚ¹‡ h|^ÉV®ÈÍ/4^PJeë ?³cD\r´šdûhhç_é®êû¦U²SýªÛžhšúÔï:é#ù^¦¸%Wk`}Œ¶Ïá­êÅEM3Ê+ `‡*
+G‘áR웸5™UP®ÇÇ°H„×5Åã>½,TGè±8ñª4ô~È®š††,h»®ß z¿š l–,hËÐ%ˆÁC}ìÜbÒŽy’Ÿ&þÕöZïtï|çil¸#é¹–8!}BÌ’ñé{‘ˤFX.K·¿ìܦ|ºgÀM¤ûÆ¢•Ü=ÿ=²X_S`ìÿ<ì)ú¸Ô#»oøý–‹¿ˆ‰´ƒAF;ûû
+Ûwôd¡Üw÷xgXøÉ\›ôi3“ŒIDί¹N%àŒ±éï\á>Ø°tmÖ$¼ãÅ,ñá…uÛæþCU˜Å6é*xsÈé4矾½–çëOf%,RKÁÖñ¦¤EÎL_2¾›Š‰iŸ¯œ±zÇÍÃÁs}~± à)Ë~ת0üÈ»€ñ¹R.Ä•!/`9ºz\h­õx–jÖ‘þ:9OñÉÉjð‰¬”ÔÌ°–˜Þè.h1ýdftX*ÿ7=™q FB1w)ÝúiC$ü9œsðàÒŽžQÔÄÚÂdÝ@BN~CªÝ©.ÉÊ¢^r’¹º¨JªÂ˜ †C4|¡" ‰j&m¤cYõ"¡
+#‡O/$v$R®cià¤Çâ÷Û¹6AçU‘©®¼n„ ¥Ä£Ïš‘mÛ«ðáäwãëuÃ&µ!¿®êÐ0š{©Ld"Ö½þ¤´4¡æmTu{5v÷­õýT_ekp¤¹¾r§Ð~ Q4ËÍRK2'¿ÊÀRŽõ‹l9Ù‚<£G{{©ÅVØeÞ=þ½ãøkæÈr by&?Ý!`@Ê‘Ъu
+5«€ßbÑdûClC‚eÑ3›i“É_É>`"cGKó‚+îœÂ”SË%ëŽX½úð±Å­¾ç2]p ×9¢øõÛu“°WÙ8å{‘+cc"]•Á½[ˆ‹uÔ§Š®åëÜe\¾"Õ?M!©Ø‘5Yñ>>ƒg™. faSçõ"VY %¨öôÒPâÀ}ç_~[Š3šXh¬Xâ&4ã‡4ó ZòU‚õ(c˜äœMÈ>õ”D{Ê=ëÚ
+B4½0üÂåZ8CÆzh¹Äõ ë­ÍÙ”™\ÛÑíÎ¥+ò—áE¢ì¹:BZ
+ï!ÖdÙÌ>‡·‰—´ß•D¿l,¸Y‡þl½P ºñé:®DÁUÃñî+k#/™P¼|±ÔTa=Õ*¥­T^훳ø®Q¶t°HKZ®Åœ~`LgÊ`ømq%['=§!Y§ù“%–±y»¾nrI
+endobj
+1017 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 34
+/LastChar 122
+/Widths 2100 0 R
+/BaseFont /TMDQVH+NimbusMonL-ReguObli
+/FontDescriptor 1015 0 R
+>> endobj
+1015 0 obj <<
+/Ascent 625
+/CapHeight 557
+/Descent -147
+/FontName /TMDQVH+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 1016 0 R
+>> endobj
+2100 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 ]
+endobj
+939 0 obj <<
+/Length1 1606
+/Length2 17112
+/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ŠË©
+.†ÖF
+¢bÿÎÓÙÜÀùŸØNÍ
+à gçü7$€òÿŽeúÿ>’ÿ(þo!ø¿…Þÿ7rÿ“£ÿíÿ¿Þçÿ„s±¶–3°ù;
+FzÆ+-œÄ,ÜMŒ,œÌ¦Ö{ô/½Š­±‰£µ…­É_.ÿÕF
+Ð÷ª-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¸Ë¯ö
+RÚ8Ýw>SÓ¯S®A˜Ç©ó-×;%¾À˜úe
+ß$TAÂrü—ÇDUËx,¬mCFË„vh”V¬èæÝod%·Ýͼc‹ò¡R´©kð97Aa¸ö<ër Ñ¿5{ßîRÖÀª—Öì
+(ÙóŸAuÂ)¡¦HŸÞ OØV";M¸’…ܶRýd°2auÒ/3ߘ–¿AjqBGÎÓÙ1\æ›+>€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²}$.îÁ³Ö
+Œ(iýŽà-º 7~õSLcüýkÅ!.0Yü:7— `hPêoˆÜä¦ójÂlƒG¥v‚j»8Ç«Á¨›ÕäÅÆ6nÂN'éú3ÑX®ÐH¨Ïü%›zl½ ýƒ©´
+)‡¿ ÕÖÏéÛ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ñ@ü
+åÚ`qÈoa’:Üà}ÒË’àóI¡ Å¡H±`í ¾‹¢R¯u²Í3}›’«˜Œ(-ž ŒßD<Akº z³,¼u˜Kí mÇkûL”4iH!±¡wÅE•Ô›ß¶ÑËf½Ä¯Z8_‚vŸªÙÿMÞW'n%Õ‡óyï+ kpKx®˜XnÝÅçel\¶êaºÆ§#§ˆA³K ES÷éüT¶È
+Œ¾ˆeD;õ›‘ æB,º„5µ³äé
+IEVx[i©ó•û MCá–‚C÷=…ÐÈÏ ½~ÀÕõó)Þ7ƒNòw8>Çîwëôêé‚t­»Ìt«Ã<EÀ ‚†Å5#²üd ¡,º%¯BBç;¦é.lãWœ›ÜûÜÝ<’ÂÚ9a¨Äƒ.vKž
+q›ÅßZV¶¸Œ&®äò®Å©ði¬Ÿa•ÌF/wø†¤°•|ÒÎmyÒd`Í\º¯*ÚßDw§Ìw °)eG8ïÂ5´B¼Hc†µÙt¢ùš^¨3€6ŸoÈ:W¦ z´˜˜éÁéä’*ëÔ£Ÿ@îàâp¯_© ¥ì%Šcga>¯W¹4#UâRwXPƯY“4ìg·FRß vßû<ÔxP>†uÂËe&+
+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æø>±§“ <?;dPy\Ÿêd汉ä»tóñ#+|þ­1qÕqVø‚¥Éh¢‹P³Á4>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šW
+`þ* ÎŒÔÀ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Ñ
+ ’¦ž~o8LÃć4»DÜ϶ÒlÊô‰'´:Y'ϵ:X–¹ȃKKÖr97…ü dé2
+{¡„Fuœ·3žÍÇoÕ‹Ü2C7§jy¸-Í@Šæ,dL//¢„KàôÌ°FYîÊ„³Ýþ9Å™
+*–÷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³<IíºÛ‹ÉÄ[t>Å¡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Ç
+ŠéÑ:kÅÖ ›r}’õéŽVbbérªïHÎ7Õã³ßêí¥‹_©¼“×2[ëAõ°çô­JCRz!»‘<ùq3mÔ¢W[M0hÒ VÊíaL¦3zb¥ÿÐCNãú?O“lVŠšßÍÒ4Øë>Rj•·•ÛéD[÷87ž
+vÚÑKâåÅíÍÓ¿½Í~¬?קS§ÎªôÉžµè6.¤K±“H?R‡yþnv8Âax9™:¯¼&ýµêo<çßb%ðórÿDí;Ú%§1M–UΗUÈÁXÒ6G«NJ"€Ùíì£â%Àì”w¶ðtý—_7×¾`!—
+;ÜÆŠ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µÆ
+Ú…W¨•fI•M@ï±–KÉ­7‹û)Cc¢ïS`…,8'Îl[stÂ<¡\nc<BU¿Q×ÓãäKüŸþ<¬ÍŽÙ»¯ÅƒúÉM€^ÆÃT»Ì«ÓË4 §¤Š1´\Ï"µÒˆÊ®ˆéâ]x µŒ'ƃÙIÏKXPõ}BÎè‚YÓÝ2Ä6å¶ a«í™TÙÀô&†’–Àiû‰Ÿº¾îpÆ4
+~[ØÝñ°Lå ¸ ¡©Ûa¨Ë=‘yÿn¬%YçYt½¿Ëú7R¬lN%mÄQ$: QŒ²›DµØ†È¨Ð¬)¦ÃºÊìH%Ûß ^>«¡T&8Ñew‹¹ƒã'}'ÅrW÷ ŸMì7#X1nfœ÷ ~¸ŒÓ2Û*¡U§ %›ˆÁÇ:èDMÂ|Ò.Ž«ªˆàc:š®)IËü*ŠÎ¿žê³Â:
+ºâ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
+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â÷Ž<M×mÆô|UíZ0¥—¶µ™r'·>û’VuûtñCv.¯ÉÞ¯²”ì U=Ú·rèöI3 Í¢¹ØO7( S~ãÈ”‡ «ÒÛšt”š®`½öÈl/ÅY¦37›„Û¦š ;ŠôÑ à<‹ÆN–T‘Z.!`ßêã…”´I¼M%0,(`Y³¡mm¡ §<!È’WÏX®l‘«oÎFž5Ô¥ÕÂYe%13ð}‡yBjú$·¢³-71 \4oà'!¿¾¡Þ­«’[É2@2´F´‚ø„ö€ñг…ǬÜÄ#ºÅ[i©R(|˜.Èm‚F x¼HÃ>&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<Pdc–0`RôA˜‹¬ß”™…r8HXÞú§Ó•~ «÷®tOý08em_¦;nÒB0ÕüYÂð-'y©_‰ôÛº@Á=¬È*ÃE\ŽKδ¿ÅÿØÙ½/™‰HíMâÑÁ8g7m‘ÿ{<Q-u·´å´_;M;S1Dá[ñ7;žŒØ‚†ò”ÎD!m÷í¯`èhpÚh16jä¬Ö’ØŸ¸*¿v/¯`%–ëekáÍ?LhÎ=”v‹…}éƒíý8ÔµÑ89riL&òëcO ý‰„iŽý†àÁ¸¬Go›‹Í²fÂɘz(¸—¡3
+ßÜ}º^hîëgŒÛ·S~¢Y 
+ÄSä–5“˜{'Ë¡esøücl\î½gˆî*š1ŽšÈõ¼3ª¶è:ÃegMvc¦‚Ê癚ËÖ¢&§,€íIš®Ø1¤¯à
+©*É&;jDú`çsÞ#)„Ê4s‡oEcà &ßÙIÉ;qÝ#K¸n›å¯ý´Y|”àŒmãø•6ŒÊÑé>Ÿ[å˥ߺŽ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<p!uš/ÃúZÇÉ vc&Bãž³'˜3{âC"Ã^z| 8m§¥ØÛ#¦ÔjÞ¿øËú½:¡(Èn‡óÐ)˜âq—4Ù¶³dÑåÚ³;AúGòùVQ°!‡®´$ú>®â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\Ô<C‰é>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é><ZwúµžËtÄw/*‘ê}5Tö4[Ï*ùaÅ6y¡W;åRÊØŸ7¦½jJAºjæ”ÅhÜU–Fî¦|ð¥Ûê:]Ù+ärå’ß±¯µíju:Ûdí>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¸¬óÇ;½<nõ ÄߺƶrEiO8võÞH•kö}aq²2ß5|LÇŽ´Fa
+ÐQk|/Û9¾ÑxÜÜúÙP7˜ªl©¼å© 敱<ý6œÍ¶Â=Ÿù …3ñTI‡@TƒÌ07ƒI`5¼áô‡lcoƒ|áþü]¤ãÏ(^¡¥µºÈÕ6ÿCÞŒ Ú롾—lšÒÚ´ë÷aµ1Óþÿ×Îœÿ3¡
+šþˆ/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•šà5A
+endobj
+940 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 34
+/LastChar 125
+/Widths 2101 0 R
+/BaseFont /VWNNCO+NimbusMonL-Bold
+/FontDescriptor 938 0 R
+>> endobj
+938 0 obj <<
+/Ascent 624
+/CapHeight 552
+/Descent -126
+/FontName /VWNNCO+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 939 0 R
+>> endobj
+2101 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 ]
+endobj
+924 0 obj <<
+/Length1 1612
+/Length2 18760
+/Length3 532
+/Length 19672
+/Filter /FlateDecode
+>>
+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
+ŠšRò
+P7É;8hôJÓÏ4¢<¯e·!´ØÕv'•”õŠß¡¾Ow°8À\=Qù‘¸ø¡“>Ú!ù¥ÖÇbt¢4‚|«-<=#O<~z¤ê¹ìÛǣɉ…%ãq@$ô³ÏÁÐR«ð §‚JoBÀ»i¿ú$ÔèöÔË##Å%°–}U4Í_³i—}O‚LoàM”slݯüy=?É+”8Í5—ûµîL&æˆÅÛ„?Ø;kI8“ ]O0ü
+ôX‹ýv5FMç|.òöZSª‡æâû÷eµo® ºG¦|ß^£dìfÈ婯?ÿxñ¤}GðrçXQ†•¥ïí«°nãÄ"‘ì v¢t³íg•×ÛudkàXþæš1­´¹û±¢þúgÔ\Ô®:è'&
+yY·ŽeFÞÜÉe$WemDGóÒaž@²§—ñqfS–ô6BÙßõȽÒU?ùÏ žRÀ=²ÜçqEË4|Y²Õ7˜Yàýe•çŠuóL*”ÅK 㟠$HÙU&Ä–ÒòÈõ×€® 8ƒw}_þ×ïÝk0žGFÔÃó'€r¥wŽ—m­ølËsöxRxÏ¢ªVæ±YD
+rÆËo}s˜[, Yw?Üg±‘g x :Ë é²\<cï:—©w<5s ¡Ì²¯ … œö!±îÃøܦÉjª¥RC·Þî+~»ÌŽO¿H~Ëa&¶¼<“à­ô䊈ç¸ÿ潂I£Ÿ•æ {—]Ÿé10.ã=gVýé~Óàèñ“yß_¢‡qk£.nÈ2OS›0$a÷xb _¾÷
+'ëZ;/€Ü –^dŸ”¹\ ô 0:ŸæëFVEò‘¥0\^ƒŽ å³Ý1wé¡•>Rh’`ÛêüÁT~Ø QaZ­d
+U~-UÙ1`¿ôB}èÿ[à|ýÛ¢˜‘èþà éz]n¡·†ätœÍOîø
+é+¦ÞâwªÉ"=ÖšTÂb.Ê;9§D¿KBr•ZDIé°É¬/$h-5…œë¼_àï_æE݈P`„‰
+eŸCN[hÀÌ"¯5sß¡¶s«ÒVÛBfžáœD(˜Ü¤胢&BˆóáÛ§Œ—=Ü9bª©s ß¨nZîÉÄõn^’¡ïg^í*ªüdïfº×D°>M*|™vži­}ç`1;s~ŸNÀê~m©Ó±‡„æ\£"éc ã9D^ŸÍ1ÿ˜,F»9ÿÙªø¥só=Ê>çR³¿N§EUÝ£¾ÊPäý60|õ‘³9& x¿«é:d=ˆ“ºª¯’!êö9šu96¯¬|ö
+ œÉò;Fª¥)Ò—³ö­nEä ûÆÀ%g5HF¢´`Æ÷‘1
+S4DB~Öõ‚iJìÞóex
+r€Ð5™'­§øÌ·¶YPNøÌHý ú†C¦ÝÖïLS]Ý(…3¹p¬Ï–z«ôtNzTD¨7KŒ:®žh[µg¥Ñ¤ë­‰ ¿ø˜¹Ô¹¶âÂõA?Â}û Ž>uÝ'9*Ë25 ÄÜ£ýR¹'«3Ir¿'ãƒz‡&ù#uf9¯*¡ì@ Œ÷OÑĬyáw‚ÀÙÚÞœ«‚ó—o
+s%Ú¸üf„ŸËcÉ£ç ©œ>V† x*sžlKÍ?–‰N£“í³Þ;TÙ6qoam~gfÞÃá¹b:èÅ `Âî ƒ3öæùfÛVÓT”75"úzEÒ²4Yj©sÊNõ Ñ?±Šèqu""¸RϹ·ÖÏð­f†¼ÀA'bϧð!KI4 @·Ã‡u&“w]!&$ià}ߊ½£ƒimói×Y +RÀCÔÂÙ—ð¤ü‡Ö†8ó1…œ)ÛC0H Éª­ÀP[¹@SÝ~w0æOÍ‘àÝÔ´#Þ%ì8MÖ™E
+t.Û½«½DŒ/vÄ”õf&|aªŠ«-÷­c†ƒY¨}ÇEWùn¾ß¬úvtÿtšúgÓ±ÇFé…ÁI{>2›Ðø‡¨ÏÂØ#7nPe…cÄ\k¾Boq_„t˜V/|å|ªeE2óFm<Þƒòc):¥¢@y'¿v4œ¸}!™RkÃKnpÁÿ"}ÏHj/Æ*.@¶<A¹;p`6{ü°ù]J©84~ ãK3½4¯À_<IpDK¦|è)ÍûA±¼INâ\œ%XCK e’ÿÞÇw‚è2V1Bˆå1 h=­M¸Š=Ç3ÉÜF1×Ô¦Kgy@[²¤Î1ßÒ̪ص;#=˜³8–ÜK~.Ô/j¨°äôl×·_PG{
+Î(ª`¹ «8¦Ð®2hcöuõÆîþ2}¨±*ÔcN §¸veg "…”…X×…^¾ëfêHá?v
+]›°¶wša|õ&‹r, ¨<P«¬ ¶ð.X ŸçècŒ#î™ç-£F¯Sÿ¬œÆ˜ —å¬çXPAf'ËÊjÙ
+T´Zu~¾EÚ­§HÀÖ}Uüz¢ÜÌ G}!Éj@6ª<ÃôsìDïD&©B–%êáw¶0&ò·†j·e£ÉIø’+ÿG"ºb nYˆ#ÎÊ…5Æ|èZ:éŸ_ xØ0g÷à?§û3â£8®ˆÜ˲À˜Qïü±Ç7×X¨œÞmÙCìc#y¨àýIì&†œ·5Y²M¿>B™¡áì8³h¨ûÂò0:z$X(q»®%ù9ÞÃX*´ŒEŸ|ÆB¬-$MXÜ/ƒ°I,Ø iÀ~™3Ó &"sÐöb“–ZÁéÃÝog„F#º¡séc¡Êöïpð{Ž‡Lã³EÔ]¥™PÙu`Jvqíªi‘0ñ}ÅóEëg2!­Œ:¾~¤ÛS¶ïgãÞ¨e}èGóíÜ+¶býÂW¦âEñ%,ðÑ„ U |έR †÷Ó¸ ‚“7|Y0¦¡ÐŒ`c”h"ï¥]$¯ÙDøy–¢U”÷³*Ëö;•»°žˆž½X€Vºi<„#ÑÅÒ8ù³‰·5òNéK#Û”îËÏNï‘r®[nXôf$AO"Ý–¸SVµ¼7ê^Y´]VsBe÷ ´g¬KI^¹A5Çr &&# zK½q*
+´ÂØ÷þÞŒ4à…÷r Å› ‚$Œ¾£Q`ƒ-`¬×ðÇŽMéˆüyÀœJØ ò`’…hQý)*¡ $ˆY
+5Ëñò­Àóv3.]”T'‘™×_ìÎ"À<aôàëÁýXø èÒˆÙ¨>T'8±ìƒJÕ2,ί„q;§oék9ãñÙ^¼è½þ#±ª‘l VgÈDÝ/tHõÿ¨ÀQ—Œï±<=fYM[=€7 µ¡éPÅ°¯qdt³a³
+x^ðÁ=‰/‰Ž³'Bhùb£ÏX‚ghÃF/çœBÀî™ñ(qF¦ü¦S>à6æŒ#°ÅóŽùI4MœÑb¸ï=pû{níÒË%ˆfcY¨¬×¿þécaöyqÌÝ1¯Æ ì—n7
+4?äÀYÜ
+Yت^éιAÈ•Ë5í
+Ñaµ+Ë“º±\‹0ïdÅ C´Ð²(Ó©Öצpy§’éÛ …oû x#z–ÓŽú­iÅ6„_´'Æõœ¦?óØ&¢6ºT&V@t½E ­B:3ç|¡7›Ãù)èq‘ y#釪sfWZâH«abzTÆcóY!ë>=ä€Ë„—ö†ÅŒÎF1-Ùòò}\Ò|3GŠXi
+TpndØtº7ù)åç«sç/4ƒ8ôÃNE#.VØjÑ6sÇþ·Šª,o¿¢N(Þ-Ú›:ŽoLªḻ9ö8èš?&f¾>©¾*æËäIâ~‹zÅ}HôäX|]ˆ…–5Ö‰¤õö3›‰ø/(‰[ï ˜Vîb6ðÀ—ˆ¨ÔÆ¿<—ªîïá
+ï‹i’6RNbl¨°› (¾/`Á%àÁ¶
+èýJÇF@´ø¢umŒ¯Æ8|‚…$³(ßUH§k‹ÖÐÓà ÷¹eeÕmÖGJ•#𠜶k%ââ];$ÖJt ‡Ÿû?`ö„i¶Iq~?•°©Âá/üªÄÕÎk‰ÎX¬Êù˜³SÜÛ¶‚ÜHvòÅ¿¯ö—Slöèeî‹*bN¿ÿe¾¢\h¦µð®ŽRöã
+oçë÷¤¸Ñ^u¯LÇåô¼ë‘¡—–‰È/º¸ïr£ìu_
+¹ÊGÜ.×÷ÂÌ?áw…_«DP×vÀÊîúðMEi‰Í;èÌjêL¾ÓÍç¸×l£ÖJáðœ4ݘ$í$©QøRdàdzFaÆ
+±aÆ°ö¤ûÐq#Ê õ;–>u ßЂÑȲ¨ûÜ î(x­Ô>|»zsÇöMïÜÚ ¡<£²€*¬R¶nè«jt¤g6ö!;¢
+AQé}lߧ‚>œ'Øoy=Û“õÀ!»šp£v SO`MÚ
+ÂEdqðÏVŽ<[^/à•‚³mQB(ÉJ4åïPÓ%›ù5`¦—¼<áN]´ÍrªuÓD…8#¯U…ÑxšŒŸžþØë$@Ñr<M´žöÐÙñìlDîå®
+œ8ªm²IŽñÅa&2 i=-ªÜÿ: Ž}aÌG½o_ˆ<­2smÔR·™ß.;¾ `¾sð3¹]ƒß9mg!€fLÒ ^R„„>ˆ ¥åpT_ç6þ3$$mýñmmòk ŠÊƒ!7gN?¥÷Ó
+4“R¥VU»4¦^¡ËþõúB–üLJ#£·nγsl€tŸh‹P¢ÀB¯B¡1ÔÏ’‡’ÀmA8onTƒ¯üàŸœŸ™@©5Ý£ m>è|Ìãé$Œè8L¢äë×RõC™u´„î0a\*;­A° 0‰ì…ÀÏ?'ê=¤†CcÕ×ÇógEw{ñ§X<¬Ö«Î§¢¯‘Ö/¬+±]éÐf¾ë{Î"²Â.`W_‡—ú¸R2´  ¬ ÑßèûnȨ÷„W:È%¯Qý#?‡uÓÌá†8p¶ÄÖKê"“`t@ º^õÛ“TºXÔ+©eÝy,NÄ™‰âJcì³¾ýóiówh²i©1K½à#<í‹6uƵ(E
+¬Ç¿Ñ¦‚¤E(#ÍËŽâ~qõ¥]ïãDí
+zúÎ}™‹KŠcw|¤ªïhu•ëôSˆÆ¡ÐãË­„[ö:Ò-DqnFå†üô’êP>Âz^ʧÁÒÀ”¬Ì»›~–[T¸4عâXïîif%ŽE„óN˜¸þÒ:Í“dõ¡#d©ðº+†ðŠÊoFš{ÈY_5¡»$ž…Sr25Õ¼îà>Ó ë°+a“^r8Æz5³w ³„­JÚ%uàÏŠŒ²¥oŸP,ã¦8(+{(š\‚J)æ}kŒné?op¡Œ®_@U<º°4Êßo‰ÔYÞ<ìaÁ ŸMˆ§õcDÏSÆ)ÃêNiñZMEèG5­:—ÜüÂ.Ì{á¥Åu[R½Q0È›®iÔú#ÅU·@„ñ`lˆ-gb”Ŭ\ÏŽXIP'°(Gý³»`š˜º„€B@BÖ&íOrÒKn°ÉŽ‡{ûgÕ.V­„Ó
+.^7=º6Š2#0 Ÿ“8uGzƒ)?&¯~Ó&Î^
+)׆þ®ì¸}Ÿð‘„¨ÍŽà”ÿâMµ3ëîDþþF·X#›Vx„¥Šš9—ÅÁ¨¢S@§¾Õ§+Öf.;™•óÛtÆçÕÍ&…¸eýÁˆQ³ý Qi†•hOr{jY%ÙJw¯ÂT„—lFt{¸ö81÷(Â¥…ô¶äÃÊòûb2ÒJ8cá”ˈÒbÁÀm¼J&­Z‚A
+Õ!R3|´î|ܽ$uà×­GY‚œ æ{Âx¡  ~.œú&[qæfôð†hZ³O D_‰Ã`z™7ÊMìòMA•WsÕ [ž„væsÅÜ!ƒØ^ZÉ»‘wïFÞVeGò‚\l¹ÑS\Ÿeæ"þÌDnÚ‘15Nôz{ƒ¸Yów0[° ukz?¡Þì%¥
+Ü0†Ç/OLj[É|Z«×Ûž<Òí°4ûº ·Dɇvk5A´oã ÌtAÔ”
+çHBžO+Ú‚ÄîóÎ"«g,Ç}õS?3Ù³”“´§+Ôö·V¥+ÂÜÖ/'Ên³÷^ö/€Õ…Óÿ곕µ°€ùÙ?"0ÁAÉÃ\(à-ŸÍ¹À/¾7mù±y}ýÔm“ýmùkìµ4#±$ß”
+¢0ÓžœÇ‹·z´RÒCfwMÎ-‡Ý ’օʹºwvE:…n6OAÆR . ½Ã Kæÿ>©´‹™Ü¾hiÓn#Ç*ëÈÎ^ª ‹{n„œƒ|Q‹évÝ 5¼ã›ènB uv%ò9{d|ÞQP>CöŽŠß$qˆÒÊšÙ8”Ç­š¥«­u#Õ¸)«Û×¼¡ëSœiQ¡zJõÏA*tµÓ¦¤§ 3;Ûtès-|b~0~B-Z)ñBšª©*·?ƒæ–+[L’0o!ìÆ»UÕ‹B"Œ¾ªÏ5jdÝi·©dVéc]Ð[æa÷Ú(i³ ¿=ב;†L íu߆+YÙÔ¯jÒðoAs-á÷!Þ;ýÈž8íöêš«Î~à 0 À„
+Œè†²}­°[^­ÄÊ"<TÞØ€êä£jÈq˜`iNe“äR'l¡' Iß<N³NK×?‚ÿ’Œé ªOŒÓœÅçÖ“© <À ½2a´/êZkДv{²Y–Ú¹¡u©¡ BÍøÒŸnN;‘ÌøÈ¢+ä¼ÖοyKO€|DÛ/à5€" /‰)‰‰•ˆ½~» |fkYѵ7³C¥¼°´s›Ôªó`(4_çÏ‚5ܯ3·ªôF3eê)¼õ®#Ù —°mÀâÜ ‹¯aÍ—ó¿O(2Wr'ž~ÀU‘,ã€
++
+Brãx­€V¿…{x=p m9‡ãCäb Á¼lº•ùWß Ç¸(Nn@¬vt&4Å03§Ø=: ËI{ñ·A
+º¶ãúv$.yûK®¶”Pï By-½Ñ‚ý·¤[€¼?.à~ØŸ)¹aynË"ª ïèQóVQ"WñÈvö(W«pßè‚U‰ª™0U7šùœçá.¸½Ns˜ÜïKQÁzbžü™
+ó½ýÙ ÍËF£jkN°3½WäfÜÁ)8+í':º/¨%²+žG%$Åw·í=¾tÀÜ~ÆéÁúäi*¨ÐuÙ>lû2{†X’GVM"¹ï§¿äØÞóŠ-I¦./q*#Ú-ÍÌûS­n®Þ~¿5f58O&Ó=ƒSµ@·ŒVÓÃܧçOPkÓÿ hÙ)&ÒªîÏWfzv,Þ6ì,Ïp¸êÉã7­ ‡ixÔÆ­SÆ;Øc¹}¤ÛUŸV¼ðœxç.»wQ~ßÓJ3CÙNcYB»Ñƒ¤3Æ›õ?­ÔæuÅXŽÝʇÌ®þÈ}‹b×"¼ô)ÿÆ;Ñ€¤ˆÍ
+Ú‚+m.'ª®ãæáLVò ÊacL-À³…KË+@±ù~àI mªÎw3$‰/pKx÷ÛNìv þB ͽ2ÛÏA‹É]`Kmâd¹êuW‡¶oŠ\ˆ©/QÙî„„!'Ìqzî¿æÞ`rŒjéÒÍd‹ß”¥
+¹•úÑÅ0v ñ>R0Þ{W8ý34®H‘ó£îH±±­
+—0oj+tóH*ßj<šÊ¡ÁYzdÍ¿f1hJãg<+ïa??Â…VMQ·IŠ´Ö`ÁÖK)²jâ‚·8óK×…
+t‚i]ÕܹQ7•¬¶">ø'2cq’ÅuE}sÀ£e9L&„MrÐ`yOCÀ´ó'{›HPO˜ÒoÅø8ì»n·Šš¹Î1è˜(]zš¦ÊÜ÷ŒDÈQ–Í’>¸iŒYñvÃ×LT%ù+0&—¢1BµUkæÞê«–Ì«l
+¶Û2g§yö$®ö*Îæøe"'WèÖ£“C N1.-ÖsÛòQí5rJ÷ÛYAQ&¢V1R7Œ¾'NI,Ÿ*˜å~Ƶ”›~÷Úrò9!ˆcV†aCPµO;;PÝÌå³(t>ƒ ¯ì~0Óâ&ý¥tdW)T?&ÔzISÆ—µ Ñéô9óóŒl|—T¶·ô¤+NÓÄn“4üÑ«#éÜ‘ñÑÄüÁÉ֕aã_.›+A¯@™øêSÈ3•'üp‡IøÐÌySzùO ‡´æìÍ®¼Ck;ë2O3Ô‰áy/sT²—»ŸŸhŸúĈäomg…Zˆ­‰fº9ðþÒnjĹ.&i&ß7AŸÀ’\aö(±V­J¸ãnÔœm> ØŸ) þêy…ñålkMO¸éX8VEdàŸs][» NÆoñ3F_ 4å`}†v,ïˆnd ‚ì’تLÚB+;1‹h²QÀú·î´¢f)²kß8OÒ# õ:‰É°*NøG0Úðž{Ï·¸Gâ3]ÒB]ÝãŸeõÊUút–Zä¡ÛQ*He'3u}š&ºaVÙ0nÂ_å · Ø5J泧Þ;R~&ôc5Æ¥:3…/ïì&Ó¢.AðáÁÎƸÃÄžR¿nÈ€¦ã~E2Kâèš”¾³klÌM"÷mkòù¶Bˆ)™öøï¿¿ÓIF{/õð·לuù[Š“‹ÜhV¥<õ!1QÏG)9ì(Å¥ ÒtM ËëqÌõþ¸]%tƒP]¦ûtàÆ&Ks:!lg‡€†)®7ì,èøÔ:Åaäæá·ãäQùÔò=•ÃýnÙ,×À­¼kZ^IºgàÁô.uQ³÷ },Œz“¸»•dA@{â^@±ÝƒžÅ&ýþ°Æ¹rVL*ç‹jïRf§ž¦|ú¦ØhwFjPÜ{tnã𠞸Â1LM‰ðg6þ>¬€ä¨è!³ßO’N·3PsÞvz¤' W›Bb×÷d•ª;ì;Ъ"j7Ž”‹98ô©å,³ÑÕ4ÛÕ-뀌éÂçË+[ã®fΠ´=5"ëO_Z§ÝQýJå÷# ;~Æ×:¦ùOuP2Ãþû9¿™Úã†ß°q¸D’!ˆñÛü"Np G“ó TI¹Düˆmu áê°q¤boówH/Xâ¼¹vbh™‚79}Øži• 0!5mù'p¸ªŒÍ-ÖЗXéçQdrîá•fè÷ëåÞ1ŸdÅ˛Σã…ê(?ÞOCüUd;â±ñ.&- ÆÍ á©UÃ&ÄlÈQ¶œFWü ÊîG˜ç;!:XV†à Ž«¦g.šÆÌ" ƒâÝ`”Âp¼](G¦•|ªf?„ËÄŒjݬ~h2w|¶A™¿îÇ숚ˆ‘u #S0g0XÌŠo æ< ~°fC1å¹TËI€I¯v8ì{0®BôÂPœŽì>@;QÐÃ'‡³ †êÉ2$¢b(ŸÜ~¦r Ž}žjÈê 6G\æ«ëVáÃðšOD©h#Œir ~7úsaóÊÀ?Ô³©§²ÆÍ9Õܯ»
+%*RŠ 8$ ²Bí¦®ä[D¥ªÝ«ÔGÆ;üÑh<®^‰¨´ÑE—@$|ûÈ89O\2¾ãw3ÆRæò…iŠR)ÇäN(˜$ âBd ±ÈÔ: ¤cCœšÒ
+БQöw>}N·>¢Z[@ß HÀ—ÞäN—÷“$wŽp»X0õ•Äƒ<±´Áí¼sÎ*`<Ñú¶øAF‹/©
+¦£Ò턳`à*ùê™>÷)›td¾ñlË•]“î×=í
+9l¿»YªjËŠÍa™°Tt÷W.™”Õ>/žú„ VݪdspÏ#¸îú§+^üƺ§h¥ÔS-b©\LÔåg› llª¦¢,#Un¥`ÙD2ïÑw^´îWƒ…jžÚòHƒ,ߣ4i´Ø$ƒšš4œ¤c„\œÐ9˜n³žK=F™•S'a&È6cS4 EV×#ž°Nšy’ QN¦]ˆ‚{4)gáŠÈZó±ñëÛ¢¸$¶§”tÖ©ç< K·fÐ2o„mê„‘iª:Ï”)Ðö¬ ×ø,m/@=ÉFËi‚tÖ²$Q."]å+&•²jjÄD™Þ}Û­n38e(Ö²õ²·™s,ÒõáÙĽëÃîñ¦Öà#”
+, kÉ÷´éhÏ·.rLgâ×hž„—pZ??ÎË;@·aQÞ¦fÍ‘Á£˜ÁüÒ,_g+õÇDê–[ÖË`lƒÿmjC“½ µ‰¹ñ•«ßyÁÙUe°M ©P21=ÑAC6R²ãxÖ¢Ó»ÌiI˜µnþ¡twÙW|$Ø©Ýv;Œ4âcƒäy.,üôFÖm@Ë1›ÚÜÒS½V%¥ òN)®#ò÷~H}ç†/œ¶C<ZÅ-#©óô;=Ôg…æÙVÝæ<T³4ä5ªhš íIRaت¹iýjÕ{Í!Á
+ÛhÆ‚p!Þ 7©ÃïsíÝ!³Vðû”Sr«­r ÏýØÛ 6ç¼ÓÆÐè Y2f@Þ#'G*)†ó¬£sHj†AvÙøÖ£œw›ú<K%}9©CLû2Ý~a…z
+¿zN@â{äye‰z•¢tø8h(òD¬LnbDw•i±Ž™1·mq±’™Õà‰¼V¡ØY`Ta}Võ–«Ô+@<‚wàGô*”Ú3·†™èÊ×ZO@X@eúåé3Ÿ!U›£×øª·ü|Nú‚,=[ÑLšH2ŸH÷’3?2Ã<ú1øŒÞ|/ÂM'6¹ÄÂæÚÎ[»Õš¾{/".¤´oIÁ®x¨tw!g;ëÙM|@j²†l»¼!9û–ƒ
+ ’â;ŒºÓ/I}hŠb@xž¹ß£vÿ¨É•BxÞk_Î(7Œ˜
+—M±ñdr%´/™&HñæQÕ´+ y–›=PÎ3këЗìº;KNrÉ CMH°è-ª»Êìü9!… [ZÖ´DvI—4ê!\†Cj.©­eœ’ 0
+ÂJY†Z†ûš|ý4-¼©‡ôÄÖ/äNø&vL‰¸y)û÷oæéÆ¡s¨Fâ²JJ–à!`²K-TîÍ$\ \8fÇ®Ÿ™ºˆ¤]z‹9L9‘Ïÿö4ÆðÞ/Tþ&š¥ëÕŽÛîäHŒ7ýø1ô°’ë{ÇnŽrbÍ¤à„©7ëã!ÀÎ|#^ìñ›C§.Öçì1Ê"‰ >B÷‹=^Õäìb—bu/ÙÒXÄ‚™Oå§kY‚O)™:&Bç|i¿ôÚ¸rŽ:7q.8VJG±Ú–=
+¼œggÍMÛR9éà½Ù»T¿Ø6žft»@ã.‡±v¸g8ËÃ7ÖÇËñˆùƒs‡@JE¢ ÌL‡²¾ì§£é-ø?ÝÉ8݇uÊ I·ï*"3 Ò÷ËVA¬¢Õ- ¡Z"ÞÆmU{/)tŽÎ›ð?KŸä~_†ÜÙš Ö¶lâ’¡n˲aþq+—ôú¨¤ë1æo/+žQTËq&ÕHdn„Ô¾u ˜Ñ­-ëMåÇ‘sÿÉÅ™[tœ¼¨øµŸÀÄíÞ®ßPx|òúËüá‘æ/¨-epsƒÛ;ʽQÊeŽÍYszgÏLf²Ê%—â
+‡3¾•þ4¡´°Ç4s©Ó(œ#qp6ß ïȈLÞè¹xÌ9ÿ*Ͻ-+\NÆ"ìÊלý 4±ëè“B»5ýû/VQO‰Aüp ÈÄ@ˆtö·­ã*EÕV0µ¬7Vn¸¨bÍ[u?¹CöuJ4,Òk|_Ë­|Ïë2•`k”äÅhÅEdÔ<üÉgÁÛ{Ôrä5ø‹›o{Ÿ¬cy¯£ÓJ¥Ò/âðÉÞ28Ê8®9!úzÕP“¤¨x÷6`1©ÖÝ`¯îOzó€Xú8jvƒXq¢™°£»kÌí²¶¡‰2D¾ß•‰”uaôBAwõúà ‰¿
+€ÞŸ|æ`xFÎärãiwÍBÄt·Ñ9”kE‡-ñL¡•´]^`ƒ|ðv?B@ÕÚ,eç¼oì.9‚¿‡ú‚8ÛƒïûÝ
+2h°Ø‹­ˆÓçBJ6 rD÷ öy@hÓ©A˜orÉbo»­]hdçb;é^ûxw^c»{$¯öw÷ª(:©]Bæ?0B¨Zt=qsŽ»_ý¾$UÎö×ÐíT! vMIöM»ªéKk¦øy"Óî“hŸQ¨¿tHg½Å#v³ Ë¢¹(^Ë×"F¸Cáß Úï~µÍO[ŸåÇ•ÖZ²Æ~!íg‚dö¯hÙ¿¿«ðÉ×_j¼ºÞÑñ¯EAåƒß€MŽ›_ô?¸M¼½Ñ¹t~ŒÜ+ì SVáu¤T…r©¡l®¥Uƒ0P;Þ‡™OØ~uLáÑwöÞ5gL›É+Êj/1ˆwv_›Æª¥µ[þ±žœh…{eóåa"ë‡
+É5w½‚'☺²¡tg‚ÉGѺÐäQ`Æ9vÉlpúÿÖ§ÿ¢^ʆÁ.¸7%Ò` ã±¬Fœ}a<õŽÞµªž2Ȇ´h¶”RÒ`k‰ÉÓUúÞê¤/˜÷¢ú¹«É«¿ð\”)$q‘1)Û
+ !˜s¥8cs;ªÄj­ÌÜfºô#·Ãÿg:‘s2$Œ©ˆ×6'?^1„4=Wk¯^éßÈsê&Ù¸e;ìðìÐégªA¬½Ù¢vXþ]ïz¿Y¬ÍrôÞ=
+ Þ?”XÉÙTVà†Q¢›‚3=A(ÊŒ®?Ît??xnkà1›Ô›ÔÚ äŸA`ã×0滬²tôŠ¡Œ»*!ÂFë¾ÈÕÁ(»L lô-eFf×Å
+§,Éù¾Nª„8’sŽ±©U WSi—³¶,keõ%ï"‚×cQ:Á`c„†3p› Ò£ïט vv„_Y†)„A(@n`'7)$P²tJíòkÓp? ¨OÝï°¸>ózäö o"DXÓº3Êlª‘ûÁ†êÙKß±6ÎÀš9ŒÌ9‘ 寧«Ÿ#Áâw©üljœ]rlXÀfñêjéÙÖ ˆ¹œqwLLCÖŽ¯ËAŒÍƒ•è­0|¦·Ý¢fZ/Ç
+qH {ÃŽÆ¡I<Ü“QvÏÍ ‚TD†¶ßûu|s˜ÙöoÜœ¼ •ÁáÊË—1™­.·óüe|î÷œzzE<wèÙÀ
+L¦zRŠÑФtÔļaÇ;újwÛ³
+ž‘ÊòüÂœNBMßL¢váKÀ$¸èŽ`e2s®5‚}ا:Yo
+} v³m"ä¿â¶O›‘%)6HMí°uÉ]²GTšëseZ,Áa‡ýft{ñ«èÉÀ¡?*Xù å¥}’lºâç0íùË·=öâoÆ,˜ÂpÈ~“ œ¬L+̯Ú÷;Õ½²?¹®$Ó wï¤Á,í`ô‚
+ÍøƒRëOIz6¥K1#:­¥¬ìÃ4›çTPb§qø/:ÙsÉém½ É*Ácîowæ\·‡t‰Èâ’D…>Ý³Ý U1d•1°Æ½™Ä<‚Ǩ‹Ç/œapbÑþ?íÌ÷?
+eËè2R¼ÄûÛûyŸ?à ·Cžtж‰ä€¢rªØt°W¨ÂÃ^Ã>
+ŒÙí?ÄSËÜ·7 ¦Mwv½ r#aCp ÑÁ¤»Ê«Z²â™×?åYó›j‚foM¤Ž¾ïhWò÷%Ñq.4ƒ5ÍÞóŒ®:žªFï€uI|Òxóstóår}¤‘(º…íOëËD›ïö0C³Xò™Ï­mtý#¿#/OÙÉU5ƒ|¦ðžË%åOŸ8+‡!ðÕÈïÆÄ»Þpi¯ÏÊ*ÓK(’èÛ¾½ÙR„n9 ½i3Í“~i/]L‰ÙA•+®ƒ¬-ãÐúˆ¿”X£Ôëë"M3µ°hónf;ñˆYþÒ$qW½ÒG_¹jcR2š×»‹7¨Š}r ¼áègJ?%Lë9bBú<–ŽÌ&f·´È’Mµ½>ºç|lÙQs-
+Ï7û1'»öoσAü¬¸²a«Í¡K-é¢äþ{." xÊDï ùÐæI~˹G=Ö±?‚§>Èyüñ°“NÐ%îIß×µ¿è4É^)Oïä¥ç¾®ÁÉ’F°³¥1ŽžzÓ€SÚóJîi¸g_ ~`ñ›1E!ûŽ±Ö]Óhcotí¿AàçUpö„ß*&"-š{~gò&ú{ …rO]ÉOœ…È”[‰„î£-•;J×VAЊü$JJX&Ê×"é 5
+¼ØñÆV¼_±  ’™c€AÆ
+€~g´¦™L#ZeöܬðrF
+¨ì¿öžÓpÇ£†äH¶Õ2Señϵt(å¶õOÖt†Ò[ \„¢73}ñƒça-ø{û9…Ô8‚Ãõa8K<ªä-™£UÍZˆjzìɲ¦Omuã–‹
+|BÖÝB|kæZÄ@ºÛt7B5úÿü¥/Òµ׃1šòò‚Æû±®¸—ÜQZÖ¿S^©Àþz?§â7*¬UÌ‘Ž´Á9a¸|ø2DyúQZg‰?D[á4m|‚B–*õ¹÷kîìDRºÚ0„¾ýç–É­wó~ýØÒPÇü>?
+»ë~÷aœ¿nïOÝp}ê#Æ)f’’¦„?BË`„ú ~R(hà'Ùç¾óì ØÉ»žOÛšù.»ûe<™“1êÌÇÒïÒÂfÔÕóÏ“¤òÞ!°(íTLÈÃÖ¥råúDÌ|–ÐÅ8Gä|}¥|è+ÏTPDpƒˆíJN5ª,»sa}èàÝ!/ÿhEî:±‰–ÂÖuL¥èmzÍŒÈ%áØß+pJ^‚…®Ù†V§óÕ7ƒ° 3¡‘ áâ9zU¯Ì…‰ò;é–Ÿ·(Nâ°­|&=×ÝÉEr4GîÇ4ê˽/Vñùén :,'劘ʕc(x^µ@$<B'Ϙ½23n
+ͬm wðôš].{aëyjø0}ïuÁ¸lƒÁ'ŽC»£"éƒíK±Ú¢@=Ñ~ºÈµÔÁ'pî,¿,Çî×/¶'™¯æµ‘Ʊiá«‘ œGäÂôÞtµoyOYú÷zšH™
+ŠwêˆVM¤¬Èôv£äGÓtøu #£yå\x¦CžšƒÇŸÇ˜ZçU.æ@ÈÄôÄe²˜=æ÷ÉáyÜuù^é"HÄÇ׬íôœ™Í ®h;@‰¦$ˆ;ï¼ã>ÛL‰†¸æVìP¤ýÄJÍÏD{¤>pV$QJ¬©ô=˜Ð9 Úp€Õâ«ùD¤å0ù_‡b>éRêVtÃÖ ÄM
+Úð­,6äX€qÐ-}nJ®k^¨£ô@l€¼ÜI>Œ˜×TqÅOшتxín°úâ…õµ4JÌäÅV kw¨Š‘þI’€¥¤\°^0Vò˘íep«%"h* ê mQôB±Ýë“ÙÏXšEÿ¶Éµú0üöA•ÚªÏPbÑËöê6EL7‹:Æ6
+ϥ
+mŽ[A±Ræ¦ØíŸeµ1£¿YÝÒ~kð¢|Xžë,|@î~èÒ<¦maöè“žÉGJPòíRWù˜ž ‰P ŠïMÏÜ£Ëÿx½qì’‡î“ü\Ÿ,³›}ÛÃë½E#û¼ÐÄ!áosA8G'Ñ´2›_ð‹¿Ào8V  qqML2ÔËÜIVœmá\©ü:’P -wÇrµ? ²T§‹ÏlKðKáJì}Z%=|Ó˜~¹´ê¡¿QL-jÅ¿Vq†/¥ökåàM×±Û÷a”÷1•£Ôq/dWµ8à UnˆÇrÉ•Ü “6ŸùÙ¥»R̓AczCËSåã§
+endobj
+925 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 33
+/LastChar 125
+/Widths 2102 0 R
+/BaseFont /XFYNBR+NimbusMonL-Regu
+/FontDescriptor 923 0 R
+>> endobj
+923 0 obj <<
+/Ascent 625
+/CapHeight 557
+/Descent -147
+/FontName /XFYNBR+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 924 0 R
+>> endobj
+2102 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
+884 0 obj <<
+/Length1 1620
+/Length2 20127
+/Length3 532
+/Length 21036
+/Filter /FlateDecode
+>>
+stream
+xÚ¬ºct¤]·.Ûv*I§cul'[£b§bÛ¶mÛ¶­Ží¤cwý¼ï·÷>cŸóëœý£jÜk^s^×Zë5FQ’)ª0›Ø%ìlA ,ŒÌ<
+o(:¨Ñ_‚ä¤ñOFuØI)Q’¬¥®‰Í:T\+kÀ2ñ´Ò(ÏË2+­Ô»Ð]é¾çAM¾×Q­?A"tto¯$ÏÊAœÇÛwÎB¼ã¢ü1lþUxq¨eÝÒäöt¼d"$ÀÇŒ‡™M ,tEÃ2g§ö“0ACª•ƒÇ“IyàbLżê|c
+ )/úh½0HéZ=`|K›@?ôî3Ob¨cËL<Bß1d÷h•ß$™§”±ù¡î]C¶Y™GOýú!‰ëŠ.=÷«Ý¹½.oÇ°,½ƒšt­¯”3sƒÆÖ®·qbé§0ŠÅ°ÈDY~–iÃøu(Ò˾‰ªæ³?ž cŠÔbdS7sYð§>ádÍíìÉQûcz‹þú7¾cèü¹$ Æ>2Í%—¹ß°%F
+>@í£dJî'¾T¨WÝ– ’ÆÑë«úþ®@Zl—,P* ï™7o6x©bäÀ×ZëíùOרc ‰^à°HY¹ê¶]¼„qGÝx- $v·úyüJŠÑ‹lüwÝ„ze|5lÇ¢‰Û&^^Y†¯d¤å¸=眫Ø'ZðþžQ.,°#p¯ü°Éøù¨~j‡|i¯ÖÍ_)¢é<-ëqHb_Ò»S3‚4~«Ò/²Jú
+ó»kœAUyÑ® D‰<aº/Q߆W}á{N·râ‹0¢ž¦¸ 2üuŠþK!Ìe§óç-õœ_…Éæé&·öŽtºö›)×öÜÑiÞÜ=39^TùyÖVÑúA`›Ë¯“Š×1³[´³Cr!F\YÔT¯É$0¹âv¬]1¹â2õ¦2˜÷¨ÏQï<^™2ÄH‘,Fð«­ЀöÕúSöËö$§f@ÂÝ}7EŠqÂl™ûÑ0†R
+CùV¿·¬žg&>ˆ„’"µpVk_í+t·—$ïÒBhtçß’¼`ª-‘C†<l®I4@‚ŠÕÆ6Ã0;˜‚û;>Èù}îÒôƒ¡OQN¢¾hÉlÙ‚¦X©ÍÉÃÚ-ðÝ󜚮Ӳå‰f]D–„]fp`Ý
+‘ו‡ošDƒŒ ¾”¹yÙÚ<1Þö÷Š3
+9à Ù÷:Å„Ÿ\ÉFlý¹ŽNÁçµ±½F¥1¢{1I#ù#gÐM!Å&Ð!ùf¸¸<:â‘[Ç‚êÞ—dx²UÃü9‰Åm³{¦¨F®Aº/b›ƒÞŸ&ŽiÊù0ÆÊ<É{ –3Á—)t;¾
+I…ÆÄ8á J’«2ðÚÁF–û†t÷+àK‘D:rtËSα£³ÒFX°Y¿ƒw0¢ºãÎo‰Õ"Ú-P¼L>Vš˜ñפ2 Ynîë|CVÞZsZú Ó†x9„ĶU&bNž\@š'üýlNÔÞû1ãWÎèjöE¡¬¨ÿI1©~´Ç)¨¥P#çP&¦B5ãrEò¬é&ÜìPÿgÖ©‘ŽrÏ3ä5ë(h“‹£66q¨ JÄ·­ ï|à·Ë Ç#·û:[‘úìƒîi0žì­ÎÚoœ*3ö8¡|SgrJ_ˆ·¬»TáZ‡%{ÍbË„pøTþÃiK¢`È$Ñò-ž— r
+g}%ž¿<ÿš¦¢§y>ÕdsŸZˆ—ŸäØt‘ùB<*Cuù­ Xò4RWJY¾?Ôse4¿¦öÁGGøË=1nI6ö>â¶dxøÛzÀÛö§úø÷^`K­™u ÒZ¹$gMÍÍE®Ý§R‰³› |~Π;âIךÚCXFçÔ[ "9Û
+%Všy¯Žç½wd`õ\¥
+?>Lîw\_¼__º‚+úˆ—Ï*×5²,Üâ~‡
+ËGBÐ×4$<]q…x\6_ÌI_ϱȸtÓ<< ±ã[ôV(“K—ê£hAÑLÿžƒ«±î«k”“Á™-H¼~„ÈëRtàÆ;ê¬ԧОSŸ«,Ä>x›ºQmMΠà¸ÀöH|’MÇD-2:s»ÁK¾jÍ)yu$–©Ó:ž•([mq!+GŒ™SÞz‚PùÒ†ÞjLñpö«Ys%²Ý¶p¬z.M[›t]Þ§ÀŽKxÀKPų½×ÕêL•ªçLý=à'd{ì-¥?Ö­#†‚­¢E^+#6#– ñ/–“õ­ñ¼ÍTñÖ<ínÀZ‰/”Ú8Y2ÓØ/gÓAÓ›øæ±,dx
+v]šÑØ}a(ôÉ:eÝX!±«AÏ[–Ž×ÊÜ’ÀæƹƣÞ3a‘^£ãxR°šË\ì2ª<2€ÿŒÍmxÕîQžæ‘QáE‚žÈ¿¼=±HF,ÃØðªÊжÌ>Èü]¼¾Ø¨ÍqZ\Q0³“×-|/SS´æ;ª? [B«˜jÜë&BØ’ÆIRòu“$€„ƒƒj°i&ÝY³$——½å£
+ç¨÷i ¼%0¸)xëõdïIG•&Ž¿œÃtɳ6†ž7|¸.&õ
+ -ΈŸçf™ÕÈPMC°3p§î¸eÚìq²áBÞæh‡~ò¨,þ¶¢Æ®¹ÿã
+¥;Kƒ{jPÌCÛf¯¨“Ø£_:©Ãb*¬Ž–Ôº°AïhµûÞÈq‚F΃a¹¦Ô9›X´Öò€)t‘ÚQPAng©§âÏíÿ4»š†ü˜©>¹I¡Îúîá
+-5ù\;³½2>V®±*T# +
+@0‡cz´ëðcL"¸¶©ˆ1tQ mhž7OyÙK/=mŽ1Ü´iüŒÇŠ··ôŒÄŒ%¥”v= \lB­×9Ɔ½‰ü‘“WŽÄõÝ©s;Ú¾†øðýa_ 7,Z±jg[À6¾bV¤ÊY—qá=›TLÀTæù4¸©ŒZä¹xæÇ©D S7Aof„ûoŽ¦¹¶†d¬Å(?# Í”¡4÷Ú7©¯;˜Ác%$P„P|¹Ú“k½T˜dpR(áæÓþ; @UÂŽåo.P
+·?å?«ì:º;rº¶;(œåÒHBÐUQ%Wy¯ÇûcEàÝÚóÌãÁÏbמgo@¦ð­q´ÔDÖèÈ' )øóÁ«ÄhåHø*²ï›#™·ZÏYHá( %Òïg!›µ ß¿ûW{|êõhñGÆq¡ÄL»»o–DTèd·ºãú±‚e6D²]}~Ç¢jé‰
+S(xÚ#oÓÜõç ç‚
+¦cô)E}dðHÓœGNoj<]Sç¬<âu½âyקûU7Áê­²‹E«¤py÷á8'ËÍibHö qT?q::جöì(ݽïRgÝý>^ØûûWM€Õ}ýÐ駋–Ê{ÅóZˆÔ(sï[6ìÂO ‘zü
+I³ÙêéÇ–T©-˜R§5߇›‡þÚ@ÂÇŒçoT§÷uf‘‚‚Ÿ£;?®IÖB,$ÊqªG¶vÚâ¯PIJ •£Æ»¨(¡àœ•SÕ`RHáRp·É/i¼™É6rƳ¬È»ÚôÊvökU;]äW¸é­ysV†$Z k›oÀëãõK„ö Î£ æe*|LÞ¹*p¼§}¸ò× }an²éÜ¥ºÏ¡öÚò´Ú7dîyˆg9ÏÅõð¤éFOdtã’ý‰,5FYrè¼c}í¤Ná§à:†KÐe fŸvE#Ÿ?Íю˪̘ í‘0S(Ó¿£ME J+dL©¬¼I­ð^>|$½g'IàŠ´?"týy0ïù4=:9W8ùÉÝ1Õ
+6AdQ›¹Í,>N)¥Ò©ðOã’ÛÍ·o}ŠÓ3U¢ªõ3“ÏŠC…}àp)Æó¿a™FK›ó+ •W1{‘¨íœiNŒZ?¿~Ô<îZÛ×Áˆô~ô}“IU?û
+^ºö*ÕÊ;â˜<\éæjB† :æ‹ãk‡o™ùžËýtaA=« ÓÔ'ŸÔÐH•ÄN!z^“«ÿw¢ëKËÌ´«vߪý'ZÎØS³_-Ÿ!¡ÑÐ9†˜­yƒ±<`–ìÜkÚìƒ8˹‚®UF¡èýÒ¿äâôëO‹¦3xª©‡ì†°b$pãÀfN2rI[ ÷Ð`-IêѸ\\AIëÇz£AÅ ;²;»¬·Ó@sûÑ’Ðë"ø ,méG(;vø™Ùd×"|‘"¦ŠÄ`྅Óé‘«¬óõlýÖ!|t]Œjø0Š–¬¿Ö¾ª0Z )ˆM&çEî+É÷Éœ GÌ7kʱ—Ed`X]ŒÚE•ÀQd¸À'D5õüDU°p¯)+7sZz Ce´–
+Ý)k=g<
+ýÀ”å•LâàÛìàwD#XY«yû¸é ‰zp£^àž¡°óRÈÒˆþ‰B˜D²¼¾Ý_v|˜÷ÕìÆ”¡v’S|*B‰ã˜D#ÑŒ¹N7uˆ'ôx’ÎvïNEy-‡UI 9̽Ç|iýB[}¥­ Ó¨ÜE>T ”;pf4_·Ñ%ÙøN} T…—Äï÷uĘ¿”õ‰¦ûñ,Ri.ï
+„y„ÑŠ<¦ªòÐYtÍþz`Õ4ŠMÇ>f·ÅH3¯ð(±…¼]¨!9‡çߤ–šà›cà
+è°ƒXC#Ä1ž7róѧƒ†1÷‹þØ*:½Ý
+¾¬üš"¨ùᶓ°P ¾¢®tþkºô¡ßs˜8ÁºÌÈ8õc°ã9­•Qæ3EåŠü±¹ÙΆq«¿tÔöÙËCCY^"fDzJ
+ÛnÂ÷Ù'Î{ü®ÒÿŒŒ®AiD–Xg‰¸N
+Ã2k}„‡Œ°±hd7,=½åÒp3{9 uN4Òœ°T—£b ؆F–i$ïó‹'p‘}¾Ÿt¥™´ð^ɨ"3±Ut¢¡zx²ØÆx4D K¬ZógÜ–z‘xC6‹]äÂØý9&yóï³t6?ðÌ"%
+‘¼FøCAÌÑð}>€¶6‡¢ÓVÛþ\ý di B´«ÙQ¯è.Ç~Þ‚´ÈÌ=ìäm’6yS$ý-Ñ¥ª¶™)P‚´)keÅÃvM¡Gã¶Ëe·5%¬_ØYûMŠKÒ}ƒ†Œ8 îÕŸÃl5wìóµ Ô<öÅ·£„²3dz’œVÉ ÷
+ žóø.Ñ°\éd¥(š˜>¯–LãPÊ  Ôš3,¿Ô16še¤³Û²˜BG»OåÔÏæ¦_ƵW‚®e oÎP×½'”@ç×Ò KLýº-/ÞJ[ýŒxw]öG8förˆVƒÉcvÄþh;Ìšé£è‡µŸõ!qîL¾Â mÕBÇïã@håR}ºûür†¢'rû⣖í5qq!Š¥¥¾Üt¿°wô¯µžQ8É@Œ‹«}Hë%‚Õ›E1TâìGäìï¢vF9Õ´½Öœþó«õ‚y¦
+°YN0ÛæxôÞù¾•·Z1#‘pÐG)œïò±ž{+¿ÝªjwÒ±E©áš=P´Þ7±ÙÑ[7û¦“¸NYYÇU¸yd
+¢ˆÉd)$± ¶Š¸[a# :‘ÁÜ.‹ÍÉü7LÓ„(èòGÚyö é안øžwbMŽÓüÇÞNËe?ZÎÂfRc¯PÌeš²ªéQÚ"äI8
+4Æg÷ÎüôL¬¾¾Ò?Âlœá6_±Â؈u‡ëî$àÝÌ;ÇDpBÝu¢Cbî›#13º;Ï
+*‡Kò·¶‡;¼-’"+ܦ˳-ý<ÎÈt_üöYëÎ’áBÁ‚¡$üé©Ò.&>Ùe¸R¸¡3›Áÿ]u7üaÌõñ.R8‹zAµÓãvnXLûçpYTÓôª['ÒøUÒà=|¹üº*ÚÜOAŒ/–*CØ ¿?CÞêh67÷ Wáïx,V½ªŽ_RÆò^/H–}èÈ;‡¨=+mä káÕÊuS®ÉẇNbnN’²‹Y)êctž-yá¬JHw‡d`‹£Mó®úí}KÕ4¬«–!øWù…sYÚá•MS |•Ð§D Nß"æµdYDé
+Á4õ5’KÄó}†#‘.§­¤‹R‹«
+õS—¸­oïV‚•¦x{ì—?]Ž{øjA}øé{¶$õ†BÇÃh>/o†"U¹»ý´P‡SkwUçn0þ€8âàB¶ü¾F;u¶pL)#–à
+}c6!„L¹âP’{ƒá;D¾dçqí¨ˆz`Ë2«f§µ­])ÊFDŠÜ›/˜[öÃð"§Ê^wHZÁ‘³"¯oD{¼_7züä5àb«;ýS@$ú¡W °²ZðDò¢òuÙÙ‡W{fMÞ2ó ¥I*,~…Ä©¹#xÖÖŠìz‰KkVßL™E›)¹‚¢ÞIXbÄSóùÈ»´[N[lº3íLX¬˜üçw^@dqór
+G%vA)ÁÃG¬³¤f‹o¥¿ñ`Ý­LF™óVõ‹ÔK‰óÔÝwø`ø?qŸàÁ¨Í tj@®È<a‹÷÷äIFÞµåüïñõñÚ1*Oîc=÷Sï×Rf•«xh¡«>Îê3cçÈ
+ž(—NÑÄåi¾%¦Še¿€Ù?ó‡ Ÿ›o†`ƒbîª0Ø– õÚ MR¾
+Xá…<§õ0ØC"ôñŸjè(–ŸÚŠeÂÑ_{Ú#‹p7ƒLìÙ5`:ì¥~Áì4«¼„?ãL®Ý8Qó\‡,OÇ™ÒÀ;ŒmhT Î§µVÄ! ¿h¥¦ž;t*ê¿ôŸçq !·Ë,·*¤Z…ΟÐWŸ¼T‘*”„6C‰:(ç›ø9ÖɵQçQÈÔGæǦߑ_<Â9ç×YÛ­ÐÚºMîƒ3u"JL üüÒ¦Q#ÆV_©©…vYTóVKYðçæÄÞU™gÔ»ð¼ òù‘Ïz‘Z(ßC?¢1Ý=žâD®jŠR8€‘%öøg×Èži2v»n›„¸MM¢t QdÂ*l%–¿‡RS7ÌÖgj¿¤‚<ÿWßÊ}#ó9¼ˆ¯†eç^™êgÞÀ Ïõ#²z:Ý¢
+Ha\»¤ÿEH Ü„Ôçì¾f• %bA¯üIÃvÊ¥lPsw‰8º8Ö­æŽÚz1IÝûQgÜûØÍMw­©•—#ŠC$=ꤡ ºí=ŒjâwÔŸD*/ÜÒdêÅÎV
+ž‘õ÷¦ÝÔÆ.3±õƒ¤9ù]v\_17OnS{‡71¼ôtÝêÅËCgû!Ìõ’+Ì\\j·Äž¸,1Èßß62–e€Æ§¥ì¶£þ&kL¿ÜêWÎc½aàJÚQà&AY¸Úãt¼Å+«8•õàZõг…V|Òœ½ÅÆú¡/½99t<g¸`^B?h¸Ç0Àûµ©¢ûOÛâD¥¿¸ÆŽAôÅöŸÐˆ"&üÒÙGZ‘úáMŠ÷1Ó.Ø›ÉÕ
+}É6¡©†þÇÈE…<ÊP&öÌ>sDõbÛ_ÇÜÛWp vµe>‡ÿö²fßé(!‡°~i0bkzì¾ÕIä­ÖÙ²¥©@ œæ‰R&ï…Ãi$|i ׶Π³ùòR¥ñ-f —ºŸ æžæœby,I꾟pXðØ©»›¦Æ)bF°¡K·b¬H‰ÌçubØ<A¨õ¨Y*ÓIÄw7y èÃokSI‡&úÆΤ Kʱ¯¨/ÞQwŽŸž±“&×í1™>JŽ%Yô¶yX}<¹ƒùÂ3éîe›i0Û~4f$­z6n/¾˜z¤ðvÀÓx$×ÂìÀˆæÑnmeõaàtçTŠEð­*>÷ËMÉCJÁ0Ýg¿WæWk¡0[(ÃL(”ÂÁÒ/;í:1J ÛÙÞ¯£ùþŽŠ's
+†‚˜!Y5ª¬h›Âø
+’9„©²Íºi=ÿ¨nuþò©­'h¾N«˜4Õ 7<±–¹ûIíÓö†÷Õ=Î)iÇN{À$dQñãTË0¿‡h¹KÝçµÙÚÒ9äóÌèÍï@¢ËG¢ $éðfKvHÀÑ:ÓÝ&îûAoà `žŽ“DGO?Ìd¨ö3ìŒ Â̪i¢ì'Y"-°ö-¸™¸O-õÂ5¾4¡Ã­š6rMŸ4Éì’‰üË¢¸U9F4Ò±SÑU-ÚÆ
+¡à£"Ð,‘gÏKîD~^ººÓÜÉ/Zn\Æ$ÿM­Œù–1ÄŒ)Á×BoÅ£E[âcQóh¨X*úêÊÒO>0”ëw+ÇœðaÚ¨F~¶zñyþþ{ ‡gS(êá9‡&IdÑX2)Fžb¡8ÚËp¤‹PX,Gæ(xõš2œS`º faje‰ªh.,w¤á«7
+cLÇý2 Ža®
+L­ysŽ<q›é;u %ý¡xCߤi67k]|Õ•ðÓ*‰I
+Ñœ±îÙª Zˆ¼¿›7Ã_ÆvN¹—Ks6Ù\£÷ˆ[wåÝ4
+Ò ÝzI6…®uê+¤S9ü$±ì
+³î^x½«nŸN)ýŠ‚Ÿƒ.Îq:¢:+ùáŽ{ÎúsX~²‚e–yÚÊYTº¾ws!kœ(IÛÌÀB(ëÊ#’ØMëü««}d˜D2è9 ‰‹â—'Ì¡ø´ïƒšÛE’,6bOö O;fôu-~_Çxð¿7¾ØÄ(Òñ÷í/Ú݈9?’WÛïµÈßFgùè`æ}ô}4*¦
+…3© ¤ô1.aõÂ’ AÜÿJ&ªƒ0E|R*ü(ô¯[ \eZ¢¬ ÏÑZõçú½á¸sÅ%¶_,sEjìœÌ.®Ü¨llüqÒé;¼ô½ë|i*VÖŸ
+¸Kþ­Óp’¹«³>ú±ägWüD³É÷?æKåÖôm#|žZ¡£ ¢Ieí "b0G`½t¢n¢J¯q¨ÜÜPé¢G08mÜ8Ùªç µÝ¯Ýã¤ßRf§2e±;$D/Æ&.mÈ—(Ân¹\çU"S#Ð!=7±æ
+’Š±à÷+ÐáËú­qJ®lHsIw¹eòª zDëÞªÔ• NÚšO%ÒçÕñr‰½¯=W¸Ë„TF%:uÀ䀙2º,~u‘\ıáýú”oC}xù‘Žq"4{‰
+@ûÅ#\t£¼ó¿º™/K®Ÿ±UgR¯H€d~È
+a«Ç|…Á|e¿g½¯ }ð”uT©ûa3s+³Ì¥•¿½ã1KÇ×1¼tþ~¸O`Ë’tyQ[ýÈ—M!›ªo®J¿¦½Á'‚K›ð⊿Sî|ÿ˜û\WAƒ#‰Å9Žê2]2Z³lp‰Fûû–†ÜûO¯†O &¤ ÜDpªV¦8ï…ñ™÷óìº è™zgØùÝg¢‚5¹’-É}P«†öž/£y+¢rC*î‹#&ï]:x"v˜rNµ4¥‹|ÓWíJû`føZ1mü-msFYîÐ:8[Ž–?[¯+v~ôðá²› ó&pÀs–K‘v£y¨¤}Üšÿˆ÷[â01%¸.cœY‰]j˜ª:Ç¿ùö:Qqæ!åµ¾©ÏÁÈégƒ¡¾{£6jÊÑõ({ö;¯`ôô«î½A$äÆä¥=ÿ7<‰†ÐZLLSXëFŠ}Db62×,èÿv;=›#˜‡Ãc(íˆFrEƒÎUA7Á¾ºñ°¤‘ïμ Ÿ³ËØ 0
+ ·‘—Vh/†¸MƒD:•ÄÇNñü°†•:#Þþ>PLÇÒwïÿQ5GbÄñ Òû¦ªð@` Ìz(iVþÉOëµ6 ‘
+³ãÆ Y§u ïèœÙ+èï°9¤- ˆíRUöMxöOþúíú¡ÅsC¨3‚Džú›„àyEà·£¸q ›—Rôd}ŽO± æé[ÞÄ™G`c·§;[‰^L–çÎ(Ön^v轈î½—’‚IA?‡Zdߦx¶ë‡0Þê5/„·ï0iñUE°—,¿"7ZE"Y÷­à ŒçÂëáÂBG¾8˜¯§µ#êÂ^ êa¹bÙø´­b÷VîæלuHmzæî
+P̪è¥Ôqõ D·Š@ÞDzˆ‹òuçöÿäüfN?ag>-šŒÊM©a7šµjª)Ð¥0c1å˜Åêž&¶Á0®ï¸‚«n9¯ÀMæW )õêP&°C˜Ù‹÷¥J@eôOqðȾÿçx˜¡ù3ÜÏú\åušà$å·=„þ’»:0¥äí ¬ {]Û7°PPÎþm1ˆ’=pËvÑ18Zµ±ˆÀºrG»%±6.«ßÌ¢8Î8П«woZKÉ9'çêí#úG—ïj²X+§ÃšP8†»Œݸ¼0J…®D“-ýf¸=_U0óA­ú¤‰Lÿé-àK‘ú¥Ïã&zŽ^Lqêm²ù›_º´~æ9ö$ |òÔ«*9k+ôûÒ—eL€<•Ëu¼É]ý v¨Œº_rœ!¬ß§Ìèèn"X[,#ѬR;Ry\³¥»VXÀƒ±AA+w
+©õŠÊ»üyž+¾û™%’I†2£mÞá­¥\÷¤uçó:µš¥WbÕ‘¹éˆ×h'¢IµCŒºÛ 
+JÎtŒa½µ~öB¿çn 8b¦”W»VŽn$èÍñ)4Üê¤÷VûËÌŒ;µ•èN ‰R£ËÐŪ§ýÿ×>Y¶5( QD‰!%ÝHîfà¨Ñ9º‘n i’"]Ò-Ý1ºKÝݵ÷þ‡÷Û}îùçÃyžã•”4|œ"ïñ`Ûý]_€ßÿ¼Ý²í\£$«:ê¯{¶F†Æ»lìÏ3¢?ÑL$G@Öóå×vmôãŠ#Žª×°tή4ËFIñê\é±¹†òã–ÊcLÏBÙðn¶²e™i¤ÿs;<¶ ¼ÿñÏ7JŸ¨ie/þ5÷“FàEZUuç!í¯îðœJMþ•³ŽôÓ }Ëß–~¸
+Âòé€z{JE‰FªM Û„u–æG0i ž³ÍÀ†^µYkúzþ'ôÍòH¬n“È([ÒKFR}ÿ^÷ôdk
+±5b$ßì}Cd%#vﱓ*š°ßÉ ‘ú°»­¥8hñÀÜ_Œ»Ð7¥U½2f
+b›oÒm÷ãÅY…½jãnQŒ˜fýÊm½­ªm&*þ8”Èç1|ñ˜a¬~– F‘«•¢ûÎòXQ;( _ÆSI0ü+p˜ý&á¸$BF
+ý1ì_v#ZâÍ,µgªìVØ
+*‹š@i‰úû¿ž8ëäCî3luRŽn£ÒsbX‰É ýÚNã0Lb£?yrK—Søƒ=ÕˆáÜá@Æ žÀlþ ¦Ã<˜'•AÅ87gñU˜
+Üxäø›Š•XGŠyº'üá9vµ,Õ½OÓà¬KÏýØIC`­” ¿¸9Âò§é¸ˆ ßcZ”Âh.RÕŒI8¬_$òfIKmÌXró–€àÇêŸ%Ŭg”ÆÂüˆßY'ºVR, ¨B~ ÐÔAQäϲ¯u£s¢€Ý_˜Œ\@øt-ò©Ÿ’>ö‡Q÷FÉÎUŽ«l$Ô.ËW(¦8*³Ÿ{>B7@ -7쑘ôy™Ù7º!„³¶ QèÌL}*Ÿ$‚WVÉÉ®š±Èñ×´//2ZA$¼§¥ªb;>~T6EÕ<Õ¿¿Vj3ps[‡Ú[ë #.JìñåY¯ª0ûì©'™„±ŸµQÖ8}Q¥ÞÒš½.HÒý¤ñ‘õ$=¨â¯oñöaZ]‹#6ž/¿¦Ðô¹e¸ÞZ‹ÇM{ªh= Hp¿œ¦-Õôš£åežÂúz‚€ÛÆ«ì(Onû÷söQY²æ‰Ï&¡I(Ja]U›-fø´Û[ˆÿÞóݦ6vº%š.[Íá§KpyJÖˆàêh2nösjJ,©VŽ&EͯU¨•x9øW+0éOžÜX‰3„\
+‚¾¡ÉzŒ:s[­+ž:[´‚r 7À«_ó熈ÑFÂ2Õ:¨Ù˜-Aè
+œÆâO­Œ,Eß÷;XM«âU†æüìeçÎ&¾¸cë2“.D£T«h8&Ëe7nV"ÎCøpÁ¨Ö# }&_ot-ç2ÃæXL¦ºŠðï"’‚Áf&ѭ탔w¤éʼŽE9Ãê¶Y|t\dà=_©Ÿiµª¯9ÅÝU5½<}âoCʬe±É·mQJ_”–õx-ºDïä»3¦Ÿëï"‚_
+{8þFÑÇæ–éì é–sEcø ôc/ ¥Xne­£ß Ip’XÌ,X§x©oÞC§C7}yñ8㟑KÓ•F<Ø—¶cÚùc§>É÷"ÊåæÔYxVì#³í³9y«bTjýé‰NÜáù„…ªjŽ\«WÍX!Ì[Ê뺧b'ÞŒÆ)<$1ôÊÚ[,ৠƒ@ŽWÃc3/—°WnY"¬Æ4áé[_Šüå–#xÎöf3I¹[V¦;ñ²è2f’a_ÏãX;q)ö&Öö4FØ…È÷Ÿ
+=X¤9ƒ:Ø•ñÒ
+†*Nñ(ßc“À“
+ÎQÓp/6è~
+ê™ã2ú»‚îY$óµÉ•­ßª2^IÑPYm3ïÜÚ×Juý¼=ÕùÌ~9Äÿ 2©”pmPkDÉ Ç¥)DcX¨Ù콘ûk*+ÇMCÆ{Ù´~­Íµ)²è5¿¯ÅL|yÿ1ª5u‡Êëñ÷Òc9„ÍrU ¶óBDøò3TyÈ嘙 SzH1ß+`Îð¶+§`½°W5Ó㎎²ÁÑÃiÁ™,÷ò}cýö3!§ïÒƒŒ‘Pu aÛ›”Ë tòÍ|T\ÅL,pÈBHðì9çÑô)8H-úäjj*ê=êOŽ
+Œ†<\a/r¼ˆvÈxµfíÉCvP€ÕóuóföÈy§Åm4ÍÛÆajùlW¤JÕ4pñûZ¢Aÿ6Ñ®–B][¢µš×´B©®¦Ö
+åUÔwUMõ»gÕ"&
+C•Á&ûA×"4ÂÌ]iÅ Î|,›ž(mÍ…pêÖ.‰ý³oRŽÕ] ¸kŽ¬¢PÖ¡ZÛZŒŽT2Ê©‚pC¯–dô.Rn®f™7£žØærðk®–-!OõŽž1t¿9~‚ó–‰æ·q¼mxYæó”9gK’}ÃÜÕè×å HéÏAf™\pCÊˬM‚._óBâÚjq À¶]qL÷‡ Âa¯¡n—ˆ›´¢('â¥&Cv­pñf–¿‡OFÙ2ö
+# ð:øF(‰¥YäsäLèÆùxÂJßÓ%ÌgæÂîˆñe:‡¯#0®ÿëÊ»3¯‡óíLM¤\“wŒgßRkHäŽÅ_KØwÓªÂìni–ŠØ± ¨wŠlNþj sßÑ8v<o¸ÞâÖ²ãU8^ë|Wš
+ÆúÁÿ%ž†ëÿ öÿÿsK¨«»³#ÔÕûÿ
+endobj
+885 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 2
+/LastChar 151
+/Widths 2103 0 R
+/BaseFont /NHNDXP+URWPalladioL-Ital
+/FontDescriptor 883 0 R
+>> endobj
+883 0 obj <<
+/Ascent 722
+/CapHeight 693
+/Descent -261
+/FontName /NHNDXP+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 884 0 R
+>> endobj
+2103 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
+790 0 obj <<
+/Length1 1630
+/Length2 15892
+/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Ïð_–\
+ø›UY\òßuºZ™¸þ“Ûô8Xüõ4w0sûgKÿÂþÒüE]M@ö.
+`abû·Wÿ²kØ›mAöÀ¿šþ«
+™**À)—PHW£B¢ªU³m·WÛÔOrí]VÉ• $«ùqyĤ"õÂzŒf<0ëûë£Îðf}/Ÿí¤>bêFè,VØUd‹ÕƒæÔJlNÍo’©+¬OXÏ1Ï-¼§c-NÂ1ipÝ›í\AÖ
+úêì`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áï›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±ò½U<b´Iïqç·3Áì\³ù«çsÿ^«Qº×I?^s2XÉOzG÷6vïáæàæiðŠáãAûÍ6ü‘îav-œ2æ¯Krʃzs_4/“íBào[çç3r„¸)_&x†·¦3‘ÂÓeX’9iÏiëxêל-9ˆ‡sA\U Û=$˘¹¦G ÐñSÅ¿%ÂßR2õ«&öòôtÈZ¡EÇ£ÚùÌ.êòhnSm»Ä³=£Dý”Çõ6àÆœêk0¼îSF£4pºJÆßú „c¦…QØÉG‹Ìû,\…RXÒ<5µ[ŽwÂ×ó é ‰ªš Rš,¯þþ’\™mÄT0쪃ó‚×sõ`ÃO4â„W…¾lï‹Ãë"Z2µ0lÁ¬{¦'( zñ.9_ÄzÎãБ²þãbîÂÑëwS*ú[­FspÛúÛߤ_é~} ‹s\±š“fÿ{ô÷ÁÑ#ŽÊ‡/°² V LlQ9áŽ%Ã¥€T… h(£Œ"Îå
+Þ_#þÍ:ÑdŒ´r@SÓ^É2çQ›¨ô]´à8UY¦âq¿½Ÿžj_'åm~²˜O±ö òà –,®ùé‹‘c^·Úû…ç C)¾ Êt%E—fã$‘P9¼žˆã4yo(¢‘d9mšjW˜/¢qge>KмÎ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Ù%ŸT<RÎm*ˆæ“SÞÑ-ÏaŠC!)wȨÊ;ý&NÀêpêüôÈtöÅ;ÉÈ]¶ÇŒQÉŽ_@q²Óa–Û÷Ý n}ù‘Ûü¤ŸZù“íÓúY»hy5}îê]5P×*»a$G(®‹uý"»ÊÏc9‹z›”­
+Qm®­.
+_ Hf³ÚU;ì­^º~ÁÀÝ3µ5é øÚ¡ºø[\Ù¡&÷Ú;Mo9E*Ûí¬ E Õm¹lê·šÒqd‹¸þýà¡xZ¯ïvô£æQ¤䨟JêÅcFv£1Xc:bv´æQ43ÜËg¡ã6jÄK¸ú¡|R¹š“øÃ÷N7œô±°ÆDL³ ÒYTmN`ÄÔŠÓi
+öYˆ=~åÇk8¨ehúRZ^±V<£‘x–@#”"s•ýÇÚdÔIðP…®÷­•úz8*uÝKœdÕY…®Ùð.Ó©¬á.‚ºuÆTaˆVÇñŸC—nXЫç«j”«žŠçµS¹ Í[džN–üèÇæz ôÛ¶IµWV€A¶šéÝØNQõÆ6W
+ÿ·^]Ä“†[#"‡6]”ý¬…Xí=ïóñhé¼ÜmÄ%ýÖF¢WÛþª†Úû—tµdý
+á;¬/¨`>‘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
+ùΦ*-Ír»b3‚Ë1<]#°Õ¤pX%'Lèw²ƒIýohZrI ®ìñõQ„è1šØ—×¾˜I×ì —UHð¢îq‡G[Y(|#8°ˆ ¾«ü Ì¡"@áBÔóѳ{¾¨'™†V æŒþžßˆ)Iª‡ýE«HÞË]~@wt<ª7çqÄEÔË̬´¥!yšj½7§ßÀÛ*«4øÑ?rê9ðgÅ£ŽÈKj…4HÍD}LÂà=™òâ1å7Ü4S¨r/êö,m@Í H΋pø^T*õg´ ²è‚V e™'&¯F€™ámyÛvîÃQŠ€X¿6~pl“È3ÍeôÆ`âå=õïÒ3(¬•éq7¥sšçWÐ)¿Ÿ•µ®K¬1¿!qÄI b^B,Ësb¬@¼ ‰ja¦•0?8ì@?N©¶ôÚo s¬y¡¸TF3ÎRer9IÎÊè7?°0x?Dtebv
+"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¯Ì^¹Ÿˆ<H|…vøuMgÌ[¸åßÎ e7wjrò2DüÛ6dlœ H.)=í:{˜;œ5vrUå(è
+«°;‡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Í@
+(§[$$Òè,ŠÕ%%yÔ »´Æ”V°ß{Ó(±3· Z„Ö= (0ÜHnƒ«%1œÍBz;¦ßŽÚsÌ9û=u›UÛþígàÑv±Ú9Ž{â’®0Ý
+ø%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¾Ö(ß~™„¡
+ö99'(ÜÛG(#?‚iÎä²q
+[(†ºÍ ö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ËÉ&<j ©C@×Þ¶ÃtH.‰ŸkèA™ÎÿÎ!á
+u­WfH´‰6çÈPG
+.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ô•ÿ
+'î»ìØ•Ë#>¼ºê£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–
+qQ)[‡ŸäW=Òлe~ÙŒB‘»ëó´#âý mω;y»Š%üŽ@D$zfªéA%OÕtØ9ø»«óu 6’RáÞŠxƒ„ï”
+2:RÒ]š¡¸\•´²DÊ™º´^-;nðÇY~þ0Ÿ1Í»PÒø¤0«¬}¦“?f0­úÙq†cŒ¶[ú¾;¶96Ø/
+P„ é*Ë~fûiöðÐÁ± y;§‹¸Ãà’ßÐpù<3A,
+HG€BÊ!´q<6õûœp—-HM¶Ýu'¯ýôhË)
+Û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
+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÷
+á°âÐÑÄÕ—bJŽãû—"oRc¸°€~:ƃKÚX^ªðTp—£™#›2¾&úÑj±7ÊLåzm-5?ø± %;7Ü'GÈav&³}.uƒîãÑ-ÏAmixûÞ ¢²c
+MIª\ÂuTØjGI-gýÂÓ–GâydføæÅxÃÃ,oÛ.رÌ*_ùSÕúƒóØCkëÚ™­¨·>]ÙrÿÅ:K¥ÓS%œx
+æ¨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ë …
+¯41¶{ºQµÚâl·Pãg;‹($@QQ~:ú4¥ /麞e„¼æª't“Ê>~œÍÆTÂ={š÷ÈcW ä­ë6Å͆ÇIjË‚¶{Al ¸¸ ²œís è¹”Lª £ÈàýÞùqœöÇ=*Y€þK
+endobj
+791 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 40
+/LastChar 90
+/Widths 2104 0 R
+/BaseFont /VZSVYR+URWPalladioL-Roma-Slant_167
+/FontDescriptor 789 0 R
+>> endobj
+789 0 obj <<
+/Ascent 715
+/CapHeight 680
+/Descent -282
+/FontName /VZSVYR+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 790 0 R
+>> endobj
+2104 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 ]
+endobj
+728 0 obj <<
+/Length1 862
+/Length2 1251
+/Length3 532
+/Length 1860
+/Filter /FlateDecode
+>>
+stream
+xÚíUkTgnõJÀ+Å€€¸
+æ2%X4-wDP¤2$H20I0@¹,P ‚A…ÊE ÒJi½
+& X¹ê
+ºè±KîþÚ³3æ}žç{¿gž÷;ç33ñð&8²‘ ØŠ ¤N®ÞA2
+WJ}áes®0›'¬d™bˆÏc9
+ƒù0@
+Dƒ
+Z$eñaÖâÔÄ‹ì2AHAXæðŸ 2ÃPˆóaΟaë7ðòÐßᶡï
+ÿ®~çœ>#†øEõ©ƒOKëåÚÝõz î®»½N™/
+µÜ:4Ò(®’+³²Zîñ1~xܦ£ûöÞÒ‡ñ‚÷t ¾ýÊ3 —á9¿ÒÈh<v-Œ¢e*뢙yà%suùZQ‰Å&QÉÅø±DzÿQ°êFgx_5žq8'–9ÉLÓË ¾š
+!üm94¡ÜÜ—=7âjp¢ŒûLé^g_]flB쵧%õ„DàPYR»rÍü ëÀÎCûîSŒÃ㲎„™xh躗Ë.Ûk'$Ô\—-”…ÌîЉМV*¦…­FÔ=2À5½[wì™üPûR×ÈÉ?ª)–’Öokö³ïOWûlzyàYC?÷£ÐèÎú©_†çÍVS¹Ëúä—pïç7J¿üñ·¡ÒÉðõùWoʯʉ΄։Öþ›E¶TÅÑ“Êk•×Ç$ 7ìÍe$å-ŠOÂé,¶ižï…ÔË*‹GUM=uó)ƒ¢…0订êcú<Êyê<^a?YYêOÿÔ{߯qT1ç„ãó_N’^'v?רk••ù2ªR¦¦K´Z_oõÈjrÔ“ÍYY2(Õk$ûš @šÝî~Ã{8sç—Úµ¬÷U$FÛéx7:á,?ÔyòÓæݯ¸ùOiD§È‡‹øÄuþ÷T«TêSFaô{ò€Š1b]aÚù_Ýv*S’ç#¶ä]k¬Øu ÙìÝò€vlÃlÓËD Õ7™U¦«‹ûJ*ƶábuÁÀ$ñö²×p}Â(5ñiQBCG¸ÇÀ\—$§!7!ÇM~9Šœù¸)ökµÑ)Ç÷D_uo€£ŒÚjnÿ=Õáh׺™;wáÔúBÙ˜‹jU´fŸîNç²QÝÖ…Zöî–[£!CŽWµ$Aü6ÍŸd‡š@Â!ß¼tÍ› ‰ˆINzÀxwÁv}ÃuÙF{I¾?>¬iÿ˜ú`v«ç íøT6Ý1¿é0S x}Î䇯£Ž¨Fü׆þÜ×¢¯ª«;rª³+Ù7ÖÅt®]šrZ9µqg{7áø®l÷GÌ}Ÿ3\NkôÏɵV'•Ç²;Bêmиƒ’ž˜l/^·`m`onç=òøàþßà¢vuC¨@h(î_<þuendstream
+endobj
+729 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2105 0 R
+/FirstChar 13
+/LastChar 110
+/Widths 2106 0 R
+/BaseFont /CWTQLU+CMSY10
+/FontDescriptor 727 0 R
+>> endobj
+727 0 obj <<
+/Ascent 750
+/CapHeight 683
+/Descent -194
+/FontName /CWTQLU+CMSY10
+/ItalicAngle -14.035
+/StemV 85
+/XHeight 431
+/FontBBox [-29 -960 1116 775]
+/Flags 4
+/CharSet (/circlecopyrt/bullet/braceleft/braceright/bar/backslash)
+/FontFile 728 0 R
+>> endobj
+2106 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
+2105 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
+725 0 obj <<
+/Length1 1616
+/Length2 25334
+/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ÈŠÈÅdU
+ü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
+€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Û
+Ïþ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™\<bxÂ0×í°–h¹ÚU\£ÑÈÖ{¥ß\«E²È²æx,3wר•Ù.$UÚr¸kÀrJ“»Ü$œ)»
+'Þõ¹TÒktÊ1 ÊYµœóý–,‚Å w†Åáù.Ûå•OسÐ-Ž^ö}ÃÊÔ§4¼°…ï¿•U;hŒIv@™È8Too?â.i¾NFNû²O *¿‹Ÿ9áäu7é8ã›
+|V뛚¢”ø±W’\úyëªb™=)ÎþWà öûI¢¥Í|ûBŸx§/i¾Úæ3“"¬ì!óYº&4«?©eL:ˆ˜¨^lHëž|´XÁSº)7x}:Z=n¸Ö‚žäQÊü˜‚>›+Gr*|wݨWÔÐæ>zuÚÐÜHq…ȃŠ0?‰Ù“]¢¨=+ûfUˆb9TV¶54ç,Te5®Åj
+–€íÖ—ݯUÛˆ¢¿ß$»Zµg-SÃ]‚.(#º™‡`¿ Ât´Üæ 6¿mà¯ò™9M}§’ˆù'WÃÙð´£ÜNæÜ‚é§$# ÁIÀq¯¹
+ýl…;œë‚$#¥Rј'ûBYâSö JLj N·—“\ð“ë¨zå0y¥~Сª{úë#Òsa¢¸²ÆfÙà´ñéöªðc~ßâ} ]˜ V42lï
+T ›+=Ý"N¸F{VwÜ«Ýê'O¼o3Mk¹‘)& Y)‘-ÍÇaÊgþÆ®
+˜r ]w9jr‡šØ[O§ÎéåMÍÏÞ@Í?éÀ0ÕíµDJF„rFhS[ͺ.ÆŠz¤9dR’XL
+fÎ$Ë\nÞq94e#q0r±MnJïù» 1ç5Gö>
+ª *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¼<k -Ÿ>ðh¼D°A€'áO¶0„0²8t³˜¡hÀ~AÛ{ˆ&î)'`Gï^¦‰m ½\‹HBõoW"Þ<y]7}rÈ“!Vý, U4.Ð"‹¹ Üw9… ÆžîôÀjìS›•ó™…)å’æøUOí›|XÚr
+j«ˆ•Úý¶”À´.u-EaAB´=?`Š)/ æúÂÆ=šöÌé×K¼xX¯·ÎŸÙ5½È}áÍŠ•ÛìŸZñf6nŸÛ2£‚õ¥­¥gÕv/ð^€ ax e¦÷Êcé…|Q*íÎÅ>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íÛ&ÛÆ’ú
+ˆ!Ý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
+Ô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ñ
+´afÓ´s!(ˆ)§é‡¸˜Š  Mí0Âß<_°7;3s]˜(ª¬Þ)JÁsTæû°€½F’§Ò“_íç#¹ÏïЉ¯"#(àÖ!È¢‹ù£áõDóòöÔfÆë"S§ÔtN'Þf~¥ê:#Ï¡Ú®“×5¬'9/ŠŲ
+1«¬Ù]͊¼аŽÎžl_ø)J%r˜#sŽ-Àë÷­Ýà,Ó’µÿV¨ðyºoèLLe·rÝLû—‚ f{ûc†lî %Gä·Ú÷<{­ëk†¯¹­ey4X«Þ>¹×¢ìØÀª"¬‰åLóp å4I»{lî5<o„îÌû4%s‹_?Y sP[ϱ0Êh5è²ÀEÎÀ—B] X´sd«3*8w†çñOSDŸkâHÅkd/t$æÕû9ÃÝpš®²èwm·Ù`×E¦mSû™ªf.þÝ‘¤ÐjõmïòïË`m•œyò§oURl»î*8
+©~ó lP}EH¦à%ÄM¼·¾t›t‡¥âÐ{cöÞBÑP ,Ì6@–0®ª7ëSB¢sÐãiÃ]î“
+á¹×»­còh¹ÂY!Ä÷­Kο™x¤õbVÑÄŠéw‘q¢†BŸíú·\¦å!ÎïÖt–N´AGsƒaÃ6ö¥¬0%˜Y—½ãX*íUϼ.;ÆëÚBØåŸÕ$’a’ÉÅ/KáKv2zQü ÜIDîÔ”´Ö# ­w±Bl*sA™vœFûô¹êH¨ËWŠeÍ6«T¬GK¨´gÙ¯Æ#&¤'E¶ÞèÛƒbmAФMÞùpþÀx¼(³L½†^PÅ”‡¤•ã°Ò'_ÊsGÈxh4ÒçÝ06‰½`}‡­¹Gî‡)U¦5u†=¹‰€®qäXZ`”…*ƒ}^­Ý›ZÆËYÝ…Ô ÀüF0j ÉؽoÑuo·àd¶lŠôæ¦|•À|ÒM ÒÐ$<tÒ;¹–®ö¿¾Þ~<€·j4uuþe»ñW¥”ñƒ£D9ovˆ<Õ¹çp¶Ö\g‡=–ã;`×_LtZ±É'òãó2MiBE‹À¿×jö
+rÂWf¯(¾ Ê.Tsûœ$rG~‡ÌR)G…-ú²O2cl?ÂBüX CÇäd"iXćÏà÷ÈÏ:ŽDN
+ä¶Ôñ{mƸM¯ýœîdßË
+‹¬)Ì Ÿž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ÆZ
+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
+ª`Ί‹š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ß
+–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
+ ™ðˆ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¥
+<”â׭Ҫܹçò3¼+çÓ2> $´‰G£éœ'¹’Ž¼ˆÔ
+ªwQå\T1‡`ï–*!7Ñb¬§¤ƒÌ%©©Â+¨÷|¸M·äv×·vã„z²Žç§ñN4És÷ôq€ÔüY ÐW<o9tƦ7°6UL¡y¶s-ýsŒ,ÓÁDHHZiÝwà¾8›5‘ÊK×>8­-²¼
+!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æª"<ž ‚õÆ—½
+;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ê«<Hú€·Ïg†Îq¯Kîý \—|XY¿k˜ôÆñÚ.ŠÖ§ rõy£çu‚dàlríÝ‚KWe >À¡꓃ 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š]ÓÄ>º
+Á¸ç‡Âú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Ö° ´
+tE$ úoÜK‚†¥ocÙÙ E/¥ïµ
+žž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¬î“‹
+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©¶Ô}ÅÂù„×
+³ÝMB®Oá÷£…ˆ¾b4Ûm5Ðo{\ˆciÿ™ÇWáÿ3Î%üg©çŽŒ¸Û¹J…QÒ‚Q ]¢À›ÿБ:™¾††4§VõÏ_$2}Y뤩ØÝððÙ ÿ¶cÚ¨"yog2ÃŽ‘} º8SJ)ì"Ko™†øžJ/ Æ´“+b<7H @,U¸)‹}ȼŒë§ü`J†g¹÷ûŠ¡tm
+…™¡é*®ïÏ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æË‚Þ
+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‹EW9
+¦?Ä›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Àðß‹Ù§¦ß
+_Ãý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
+¸* Þ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Á
+¶Èãé©t²„4å¼н”n_0gþZXßåì…×bKÀ!È*Š¢Só±[¸ùq]²Q¨ù
+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
+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^¯-;<BÖ6÷¨qs LâãÔ#½×ÄoQ ,Lñ¹½
+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
+'óP4I×¥ŸÐ?`b¬FH. ÷R}ÿÀ#] «iÀAñ7FÌÐ5øùq6O‰ Ç/êúWbõÑFåq-¢´ð §]xžök%˜Ã–td˜¯‘ŒÎ¼r¿
+ä&oH[œ¯A•9f
+endobj
+726 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 2
+/LastChar 216
+/Widths 2107 0 R
+/BaseFont /WWIPFK+URWPalladioL-Roma
+/FontDescriptor 724 0 R
+>> endobj
+724 0 obj <<
+/Ascent 715
+/CapHeight 680
+/Descent -282
+/FontName /WWIPFK+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 725 0 R
+>> endobj
+2107 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 ]
+endobj
+701 0 obj <<
+/Length1 1614
+/Length2 24766
+/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:MAaQiªÿó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“Ó<M`IÍÍÍLÕ‘˜‡‰ŠŒDa_gÁ¡Ãœá½]é–§ 9ç8sêÓšÆô e¬bô:miØ*N±«z|+hytHOÛV77Ùa‰
+×Nä&ýâ3­çï²E@\æYzm¾~D9šru] ƒR¢á×0u+»Y}Îî+\·¤èƒ˜`Ixï|P>½«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õ
+|\4YÍùô\VŽAò¡iÙœÐV
+'Œ†Ý¥ýrˆøœ]E ‚ˆó(‚ƒ+c[€Éj‹®¦Qíä¼_Þâgˆí44U÷“É;2–×LC
+JOÉÒ4WÑœž:óû\™Ñ™ïÞ! ×yÖ\3Ûø=«/Τ€çÞ¸ ¯æŸ/8ˆÇîc+Š GI1(yBª5ŠÝ
+ˆÐ÷™ê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â?å
+”;çÙßëÀÓùÙ—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
+Ä’£×¬÷°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ˆÕ<d0 ¢‰úJkáÜ«mµuˆ„‘¯H`Ž6彋EÖùñïùBÅ«/hüî#Ô^†§ö¬i(]‘×Z]°&ÈC˜ìö¶ãíöù{Ùj+à€Ú‘ZQ[){¤iZ_Âì“à=Fº(s!:T KØ;XžZÆ#›DÂ,vÌ4ÐüQD~ô¡²ôå *×BêbŠµÊ´è˜:³pu þ§þ9rK28]±„»]Êö]– ÌiŽ rÆf§>Ä ó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
+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|£>†²ª
+«Mˆí&/·}Î I Ø%΄%0W¦É·¤¬´{âI\5d§1ÖÙA)£7½¡TDƒÖcÆãM~ÉÛ0l4ÚÔÕÝ„ùäˆ÷)—h7¿d~aùruÖ[l¡F÷è\)ãƒ|<kz?D \]ò7ï2¤ÎÐdåÛTª³ WdDmI!÷Ï€S‚'#Q~ On )vE6ün¡Öi¢ Ó€(IIŠ?´ëôWÞbÚ¼%­ÂbAP­`6D
+–fçÚïC%ÇÎbl·Å$ûÄÒéæÅÇDÙdÿ
+Ÿýpô¯°0TO@,{i`·Î¶ÍÆ¢ãÚâ×Kܬ ¾yOàï–<ÀQ–
+ðÕ Ž£èÈp¬­°"M¸p‘)š!(´Æ[É⯻¹ÑòsŸûùWÅʨBP¨h Ù'“¨¿ ÞÞÀOԫøŠ½â{Ë eÊdëô¹Kx5QªÎ™6!â–­a˦½ë}2 ¨Ýˆð+0ö|3k³Ÿr™eÈ[A˜ýl\ÊŠ}óÃ\&Ñ[Ããóqt“´ú8ûy :µlõUñ®¥"„KЯ¬’Cpeªb•^¶¨¦oÀªs'ª¹þ¯cÙKñ]ùw+VuN|äáù s.…¸¦Ÿn ª4—&Ðøš{«î‹½±é
+uW–ÿðžZ—â9«ÞËÛråŠi~Û0¿<€G<æÀ›3¦?›(íPÒá“~šGÁqFëÝŽíƽHšJ+3"Ê«F…@™'›ñ‡îIŸŒ‰õ‰ZêÀ7Y
+gìзt@Š™+[Ñ3²/*;œ÷Q¿.ønÐDâ]ñê “R£Þ?*ã]£_×êCék~Á3A¬
+$1üf¡
+‰¾É%|¾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œ
+#‘%‘Ï+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
+¤á¾}˜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§ó•
+©Ø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ê ñ
+J±&éù雈‹˜9›âÆæZue)äG $ LË#[|íÕϬ4ÈÝÕbO
+€£AÚ¤x8mw›þÖµÔ„±ßxèÍ#ºaýªU!˜ù´TßN.ÓÙÇ-É™Q‚«iy@ŒWc²8qá/øç ‹ïåqYw'`:ÓN·ˆ=
+*¥6©!bÆ¥$ž)ÈFå¨3Çx=H3/xR ÎWGzÊt¡Dc€Ê'ÒHD´öXM-®ÁöpáØîÐÌ’!#ŠÅø*ÒÕ Íè/<Ô¢8>§Ð†ó÷‰rŠeÀìåtѦ’ ¾Lñp m… U?ˆ+
+½ŽîÏ>¿ÇrøKKíùƒrÍAfjxy‘ ^W_ª^ø‘UŠäNGReÈ\®v/ÖVö†¶Rú׌hÉýy3˜Œßc¼b'óÑl«ð‘Ä›k,¢°§ƒ.ˆkx„Kªý( 9×^ÅÈ
+…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
+Å s?Òr&Fd¿Ä6ë&>N´.Š ¦¾1:¹rP1ûØ——k¡f)ØdQmŸèÄI BÐä5Mþ¦1T¿`m[;­z!î_µ±=ñp)ä5^Išõ@ÑðÈ š¢žAò'tG<ÞÊÁæa¯šm-mn(Ø
+‰|¿"]ˆ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Ê–»{.
+àé%.@”ØÀÄ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Ô
+ˇ—Õøê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
+µQu-W€»×4~Q.£ÎÐ)ÅÈLHQ-Û(èÖü¥> ø|kúÜ„X`Ž×¾®º] #.ëwx+«;.ñml3ÁѪ۰çµs
+:Ê(׸B®Ó'=êû’ýeÅ9,†`óÙ‡{ß%€ª ¢0<ý}õ¬YâÁ}‹
+ˆ¬BÙp:©Ñx”Mî§?ó}¢Ø×4¹„“ùïüGßßaWGÄð«à
+«1,u6AS£áx\|czíR¢€oÀbÐ.P³¦‹Ý=Öö+<µU ZäÍ&zÐÑÅReu–
+[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Ü$Úùd
+×D½í¤»a £ªâ*¶‰ÂÀÜÙš*û(Œõ¤qÁÃåäÌ°[¨.xÔŒHhý {§ú·–æýy澡:ÔuÓçg¦¨÷œ4k ÜÀ=ñïElD+Ž9Ó{û¤Î=£n„ÉÐE:xª»n½†í·ô
+é4NÈŠóv É.Õƒ_Þn$`¬ÓÖ)<ËEŠþê°õç@‘q6I„òÝäŽO¦ù¬R²Ôg-£d–‚îAúô>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×ß[ñ_ˆ
+ï%,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
+ŽsU ? ë{x[òq=4£øŠÉTññbEK'òmç±v§9ˆçì‘È$“CXcþ©\“±>ÊG˜m@>¥¼lX1 ©ô¸dwO AþŠEÒÖ’±Sc¸I/cK+–5>¶V‘+"zg
+*»åMì•¡p_ÐV—+}¤ªÞTžY!æĹ(K§i"üÇ(*wOzŒF®¯’«X`Ž¡ÿ­Š¢É
+™*r[¶Â—n³î+ˆm•€Î êËÜun2qÄi"P6h£.ü·T”•OdÉ_ùüånµ~ ‡q#$i5’2ÍçšuÛOÖL[˱ÙE¶IkQñßå:¢_é²w«®º!É·Õ7ˬÞýóÌlÒλª> ^ØH•€ þfuĶgŽÍÆm4N}Ò
+žº²Üà9UwgÒBkÙãƒËÚž½Gr˜u)Ôë
+èòÔ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'Ç
+mÁR!/¤ïmYz'Úò”¦ÀÀh'¨1I ÌѨõéI¹;b ’@\Öq×Ü[¤µ*ýôF£½™ÃØ»ÚRqõ¶›0ý×nD%ŒãßÉ€¦ ]:bĨvÿŽ“U®ïqî{Ĥ
+Èù#†ð÷†(£ÃÐ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-߹̫\šM0
+¯'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¦ä¦¥Æ¢[~ÕÇÆ
+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šý‹Üè
+µ(à\èaª
+E‰7jŨi¥oòƒŒ:½úþ·cêSJo*>»u+Æ#@Ä«áb\[k!s&D “‹Ãd`È<HØò†T¦EÚdò:±CíkE
+j!H·îà3ÁE.
+ ø!{mž/ƒòZú+p%Œ«u–}Fcí¿ èýˆ/ì…Ƶ1>§ÌM)ÔÐ O%Sýù8½î×Ç
+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Ë›ƒÌð`
+Z®§Ñœ8Îeä¾ÏFþ±Ã,ô\5ˆI.èÑaM 4Ž´mÇÕ‹èqWM‘±•î·egcØøí «\[þT
+¿Á…æËU¨—xÙLDÞsäÓš
+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Â&<
+| 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
+[`÷QìÿY¨OÖØJæÒ2‹„a¤.‡yMÙB.½T›.¡
+¥í’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®˜
+šÒ30D”€`Ÿ†§¾ç4}&1xÒ¤Ö¥ ÎdP•Ý‹$ȾCO‡Ù’jÛvëö?`C&W'aÔCJ•I'sŠFðìM˼k©¡¨»°+X ŠcAÐÀ«á¥£ùr!<s%!ÈbˆÀNÑ* d3³Ê6†Ø0´+3ïÍNYÀ8îj•ÛP³7Þ¨VäÎc=$0€Ž9€òõ «£…WCÒ¸1å Ô²9L±ž±~óŸ –äWÚyüInÐäöÀ'¼I3 ú]`+ò7vÃÝ!’ÔËö—k«Zœ–(&4¨j„¸`é+àpôxÿÅë«SüWâ$åM7ƒ[IZÒýš®ê~‚VƒÍ:Ø\é«…Œ€Øy_à£öý
+.ÈëÃ6‹û¯™ÅSßcŽ¾Q&É5 fd
+ön’“,6"”@K;\ÿŸÁüø¯
+endobj
+702 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 2092 0 R
+/FirstChar 2
+/LastChar 151
+/Widths 2108 0 R
+/BaseFont /ZBDFML+URWPalladioL-Bold
+/FontDescriptor 700 0 R
+>> endobj
+700 0 obj <<
+/Ascent 708
+/CapHeight 672
+/Descent -266
+/FontName /ZBDFML+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 701 0 R
+>> endobj
+2108 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 ]
+endobj
+703 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2109 0 R
+/Kids [694 0 R 721 0 R 731 0 R 786 0 R 850 0 R 912 0 R]
+>> endobj
+941 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2109 0 R
+/Kids [929 0 R 943 0 R 957 0 R 968 0 R 975 0 R 987 0 R]
+>> endobj
+999 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2109 0 R
+/Kids [992 0 R 1001 0 R 1012 0 R 1020 0 R 1027 0 R 1033 0 R]
+>> endobj
+1056 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2109 0 R
+/Kids [1041 0 R 1063 0 R 1073 0 R 1078 0 R 1082 0 R 1089 0 R]
+>> endobj
+1105 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2109 0 R
+/Kids [1097 0 R 1108 0 R 1115 0 R 1120 0 R 1129 0 R 1136 0 R]
+>> endobj
+1148 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2109 0 R
+/Kids [1140 0 R 1151 0 R 1156 0 R 1164 0 R 1172 0 R 1181 0 R]
+>> endobj
+1199 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2110 0 R
+/Kids [1189 0 R 1201 0 R 1207 0 R 1213 0 R 1219 0 R 1223 0 R]
+>> endobj
+1237 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2110 0 R
+/Kids [1234 0 R 1239 0 R 1243 0 R 1248 0 R 1254 0 R 1258 0 R]
+>> endobj
+1273 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2110 0 R
+/Kids [1265 0 R 1276 0 R 1280 0 R 1284 0 R 1294 0 R 1301 0 R]
+>> endobj
+1310 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2110 0 R
+/Kids [1307 0 R 1312 0 R 1316 0 R 1320 0 R 1328 0 R 1334 0 R]
+>> endobj
+1346 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2110 0 R
+/Kids [1340 0 R 1348 0 R 1356 0 R 1361 0 R 1373 0 R 1378 0 R]
+>> endobj
+1388 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2110 0 R
+/Kids [1382 0 R 1390 0 R 1395 0 R 1404 0 R 1408 0 R 1412 0 R]
+>> endobj
+1423 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2111 0 R
+/Kids [1416 0 R 1425 0 R 1430 0 R 1449 0 R 1462 0 R 1482 0 R]
+>> endobj
+1499 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2111 0 R
+/Kids [1488 0 R 1501 0 R 1505 0 R 1511 0 R 1521 0 R 1533 0 R]
+>> endobj
+1547 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2111 0 R
+/Kids [1541 0 R 1549 0 R 1557 0 R 1565 0 R 1574 0 R 1583 0 R]
+>> endobj
+1592 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2111 0 R
+/Kids [1587 0 R 1594 0 R 1605 0 R 1609 0 R 1613 0 R 1624 0 R]
+>> endobj
+1634 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2111 0 R
+/Kids [1628 0 R 1636 0 R 1646 0 R 1705 0 R 1761 0 R 1815 0 R]
+>> endobj
+1857 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2111 0 R
+/Kids [1849 0 R 1859 0 R 1865 0 R 1870 0 R 1874 0 R 1879 0 R]
+>> endobj
+1894 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2112 0 R
+/Kids [1890 0 R 1896 0 R 1908 0 R 1919 0 R 1926 0 R 1938 0 R]
+>> endobj
+1952 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2112 0 R
+/Kids [1942 0 R 1954 0 R 1960 0 R 1964 0 R 1974 0 R 1986 0 R]
+>> endobj
+1998 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2112 0 R
+/Kids [1992 0 R 2000 0 R 2009 0 R 2013 0 R 2024 0 R 2030 0 R]
+>> endobj
+2039 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 2112 0 R
+/Kids [2035 0 R 2041 0 R 2053 0 R 2063 0 R 2069 0 R 2078 0 R]
+>> endobj
+2091 0 obj <<
+/Type /Pages
+/Count 1
+/Parent 2112 0 R
+/Kids [2085 0 R]
+>> endobj
+2109 0 obj <<
+/Type /Pages
+/Count 36
+/Parent 2113 0 R
+/Kids [703 0 R 941 0 R 999 0 R 1056 0 R 1105 0 R 1148 0 R]
+>> endobj
+2110 0 obj <<
+/Type /Pages
+/Count 36
+/Parent 2113 0 R
+/Kids [1199 0 R 1237 0 R 1273 0 R 1310 0 R 1346 0 R 1388 0 R]
+>> endobj
+2111 0 obj <<
+/Type /Pages
+/Count 36
+/Parent 2113 0 R
+/Kids [1423 0 R 1499 0 R 1547 0 R 1592 0 R 1634 0 R 1857 0 R]
+>> endobj
+2112 0 obj <<
+/Type /Pages
+/Count 25
+/Parent 2113 0 R
+/Kids [1894 0 R 1952 0 R 1998 0 R 2039 0 R 2091 0 R]
+>> endobj
+2113 0 obj <<
+/Type /Pages
+/Count 133
+/Kids [2109 0 R 2110 0 R 2111 0 R 2112 0 R]
+>> endobj
+2114 0 obj <<
+/Type /Outlines
+/First 7 0 R
+/Last 639 0 R
+/Count 10
+>> endobj
+691 0 obj <<
+/Title 692 0 R
+/A 689 0 R
+/Parent 639 0 R
+/Prev 687 0 R
+>> endobj
+687 0 obj <<
+/Title 688 0 R
+/A 685 0 R
+/Parent 639 0 R
+/Prev 683 0 R
+/Next 691 0 R
+>> endobj
+683 0 obj <<
+/Title 684 0 R
+/A 681 0 R
+/Parent 639 0 R
+/Prev 679 0 R
+/Next 687 0 R
+>> endobj
+679 0 obj <<
+/Title 680 0 R
+/A 677 0 R
+/Parent 639 0 R
+/Prev 675 0 R
+/Next 683 0 R
+>> endobj
+675 0 obj <<
+/Title 676 0 R
+/A 673 0 R
+/Parent 639 0 R
+/Prev 671 0 R
+/Next 679 0 R
+>> endobj
+671 0 obj <<
+/Title 672 0 R
+/A 669 0 R
+/Parent 639 0 R
+/Prev 667 0 R
+/Next 675 0 R
+>> endobj
+667 0 obj <<
+/Title 668 0 R
+/A 665 0 R
+/Parent 639 0 R
+/Prev 663 0 R
+/Next 671 0 R
+>> endobj
+663 0 obj <<
+/Title 664 0 R
+/A 661 0 R
+/Parent 639 0 R
+/Prev 659 0 R
+/Next 667 0 R
+>> endobj
+659 0 obj <<
+/Title 660 0 R
+/A 657 0 R
+/Parent 639 0 R
+/Prev 655 0 R
+/Next 663 0 R
+>> endobj
+655 0 obj <<
+/Title 656 0 R
+/A 653 0 R
+/Parent 639 0 R
+/Prev 651 0 R
+/Next 659 0 R
+>> endobj
+651 0 obj <<
+/Title 652 0 R
+/A 649 0 R
+/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 639 0 R
+/Prev 643 0 R
+/Next 651 0 R
+>> endobj
+643 0 obj <<
+/Title 644 0 R
+/A 641 0 R
+/Parent 639 0 R
+/Next 647 0 R
+>> endobj
+639 0 obj <<
+/Title 640 0 R
+/A 637 0 R
+/Parent 2114 0 R
+/Prev 603 0 R
+/First 643 0 R
+/Last 691 0 R
+/Count -13
+>> endobj
+635 0 obj <<
+/Title 636 0 R
+/A 633 0 R
+/Parent 623 0 R
+/Prev 631 0 R
+>> endobj
+631 0 obj <<
+/Title 632 0 R
+/A 629 0 R
+/Parent 623 0 R
+/Prev 627 0 R
+/Next 635 0 R
+>> endobj
+627 0 obj <<
+/Title 628 0 R
+/A 625 0 R
+/Parent 623 0 R
+/Next 631 0 R
+>> endobj
+623 0 obj <<
+/Title 624 0 R
+/A 621 0 R
+/Parent 603 0 R
+/Prev 615 0 R
+/First 627 0 R
+/Last 635 0 R
+/Count -3
+>> endobj
+619 0 obj <<
+/Title 620 0 R
+/A 617 0 R
+/Parent 615 0 R
+>> endobj
+615 0 obj <<
+/Title 616 0 R
+/A 613 0 R
+/Parent 603 0 R
+/Prev 607 0 R
+/Next 623 0 R
+/First 619 0 R
+/Last 619 0 R
+/Count -1
+>> endobj
+611 0 obj <<
+/Title 612 0 R
+/A 609 0 R
+/Parent 607 0 R
+>> endobj
+607 0 obj <<
+/Title 608 0 R
+/A 605 0 R
+/Parent 603 0 R
+/Next 615 0 R
+/First 611 0 R
+/Last 611 0 R
+/Count -1
+>> endobj
+603 0 obj <<
+/Title 604 0 R
+/A 601 0 R
+/Parent 2114 0 R
+/Prev 583 0 R
+/Next 639 0 R
+/First 607 0 R
+/Last 623 0 R
+/Count -3
+>> endobj
+599 0 obj <<
+/Title 600 0 R
+/A 597 0 R
+/Parent 583 0 R
+/Prev 595 0 R
+>> endobj
+595 0 obj <<
+/Title 596 0 R
+/A 593 0 R
+/Parent 583 0 R
+/Prev 587 0 R
+/Next 599 0 R
+>> endobj
+591 0 obj <<
+/Title 592 0 R
+/A 589 0 R
+/Parent 587 0 R
+>> endobj
+587 0 obj <<
+/Title 588 0 R
+/A 585 0 R
+/Parent 583 0 R
+/Next 595 0 R
+/First 591 0 R
+/Last 591 0 R
+/Count -1
+>> endobj
+583 0 obj <<
+/Title 584 0 R
+/A 581 0 R
+/Parent 2114 0 R
+/Prev 559 0 R
+/Next 603 0 R
+/First 587 0 R
+/Last 599 0 R
+/Count -3
+>> endobj
+579 0 obj <<
+/Title 580 0 R
+/A 577 0 R
+/Parent 559 0 R
+/Prev 567 0 R
+>> endobj
+575 0 obj <<
+/Title 576 0 R
+/A 573 0 R
+/Parent 567 0 R
+/Prev 571 0 R
+>> endobj
+571 0 obj <<
+/Title 572 0 R
+/A 569 0 R
+/Parent 567 0 R
+/Next 575 0 R
+>> endobj
+567 0 obj <<
+/Title 568 0 R
+/A 565 0 R
+/Parent 559 0 R
+/Prev 563 0 R
+/Next 579 0 R
+/First 571 0 R
+/Last 575 0 R
+/Count -2
+>> endobj
+563 0 obj <<
+/Title 564 0 R
+/A 561 0 R
+/Parent 559 0 R
+/Next 567 0 R
+>> endobj
+559 0 obj <<
+/Title 560 0 R
+/A 557 0 R
+/Parent 2114 0 R
+/Prev 243 0 R
+/Next 583 0 R
+/First 563 0 R
+/Last 579 0 R
+/Count -3
+>> endobj
+555 0 obj <<
+/Title 556 0 R
+/A 553 0 R
+/Parent 539 0 R
+/Prev 551 0 R
+>> endobj
+551 0 obj <<
+/Title 552 0 R
+/A 549 0 R
+/Parent 539 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
+/Next 551 0 R
+>> endobj
+543 0 obj <<
+/Title 544 0 R
+/A 541 0 R
+/Parent 539 0 R
+/Next 547 0 R
+>> endobj
+539 0 obj <<
+/Title 540 0 R
+/A 537 0 R
+/Parent 531 0 R
+/Prev 535 0 R
+/First 543 0 R
+/Last 555 0 R
+/Count -4
+>> endobj
+535 0 obj <<
+/Title 536 0 R
+/A 533 0 R
+/Parent 531 0 R
+/Next 539 0 R
+>> endobj
+531 0 obj <<
+/Title 532 0 R
+/A 529 0 R
+/Parent 243 0 R
+/Prev 479 0 R
+/First 535 0 R
+/Last 539 0 R
+/Count -2
+>> endobj
+527 0 obj <<
+/Title 528 0 R
+/A 525 0 R
+/Parent 479 0 R
+/Prev 523 0 R
+>> endobj
+523 0 obj <<
+/Title 524 0 R
+/A 521 0 R
+/Parent 479 0 R
+/Prev 507 0 R
+/Next 527 0 R
+>> endobj
+519 0 obj <<
+/Title 520 0 R
+/A 517 0 R
+/Parent 507 0 R
+/Prev 515 0 R
+>> endobj
+515 0 obj <<
+/Title 516 0 R
+/A 513 0 R
+/Parent 507 0 R
+/Prev 511 0 R
+/Next 519 0 R
+>> endobj
+511 0 obj <<
+/Title 512 0 R
+/A 509 0 R
+/Parent 507 0 R
+/Next 515 0 R
+>> endobj
+507 0 obj <<
+/Title 508 0 R
+/A 505 0 R
+/Parent 479 0 R
+/Prev 503 0 R
+/Next 523 0 R
+/First 511 0 R
+/Last 519 0 R
+/Count -3
+>> endobj
+503 0 obj <<
+/Title 504 0 R
+/A 501 0 R
+/Parent 479 0 R
+/Prev 499 0 R
+/Next 507 0 R
+>> endobj
+499 0 obj <<
+/Title 500 0 R
+/A 497 0 R
+/Parent 479 0 R
+/Prev 495 0 R
+/Next 503 0 R
+>> endobj
+495 0 obj <<
+/Title 496 0 R
+/A 493 0 R
+/Parent 479 0 R
+/Prev 483 0 R
+/Next 499 0 R
+>> endobj
+491 0 obj <<
+/Title 492 0 R
+/A 489 0 R
+/Parent 483 0 R
+/Prev 487 0 R
+>> endobj
+487 0 obj <<
+/Title 488 0 R
+/A 485 0 R
+/Parent 483 0 R
+/Next 491 0 R
+>> endobj
+483 0 obj <<
+/Title 484 0 R
+/A 481 0 R
+/Parent 479 0 R
+/Next 495 0 R
+/First 487 0 R
+/Last 491 0 R
+/Count -2
+>> endobj
+479 0 obj <<
+/Title 480 0 R
+/A 477 0 R
+/Parent 243 0 R
+/Prev 275 0 R
+/Next 531 0 R
+/First 483 0 R
+/Last 527 0 R
+/Count -7
+>> endobj
+475 0 obj <<
+/Title 476 0 R
+/A 473 0 R
+/Parent 459 0 R
+/Prev 471 0 R
+>> endobj
+471 0 obj <<
+/Title 472 0 R
+/A 469 0 R
+/Parent 459 0 R
+/Prev 467 0 R
+/Next 475 0 R
+>> endobj
+467 0 obj <<
+/Title 468 0 R
+/A 465 0 R
+/Parent 459 0 R
+/Prev 463 0 R
+/Next 471 0 R
+>> endobj
+463 0 obj <<
+/Title 464 0 R
+/A 461 0 R
+/Parent 459 0 R
+/Next 467 0 R
+>> endobj
+459 0 obj <<
+/Title 460 0 R
+/A 457 0 R
+/Parent 275 0 R
+/Prev 455 0 R
+/First 463 0 R
+/Last 475 0 R
+/Count -4
+>> endobj
+455 0 obj <<
+/Title 456 0 R
+/A 453 0 R
+/Parent 275 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
+/Prev 447 0 R
+/Next 455 0 R
+>> endobj
+447 0 obj <<
+/Title 448 0 R
+/A 445 0 R
+/Parent 275 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
+/Next 447 0 R
+>> endobj
+439 0 obj <<
+/Title 440 0 R
+/A 437 0 R
+/Parent 275 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
+/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
+/Next 435 0 R
+>> endobj
+427 0 obj <<
+/Title 428 0 R
+/A 425 0 R
+/Parent 275 0 R
+/Prev 423 0 R
+/Next 431 0 R
+>> endobj
+423 0 obj <<
+/Title 424 0 R
+/A 421 0 R
+/Parent 275 0 R
+/Prev 347 0 R
+/Next 427 0 R
+>> endobj
+419 0 obj <<
+/Title 420 0 R
+/A 417 0 R
+/Parent 347 0 R
+/Prev 415 0 R
+>> endobj
+415 0 obj <<
+/Title 416 0 R
+/A 413 0 R
+/Parent 347 0 R
+/Prev 411 0 R
+/Next 419 0 R
+>> endobj
+411 0 obj <<
+/Title 412 0 R
+/A 409 0 R
+/Parent 347 0 R
+/Prev 407 0 R
+/Next 415 0 R
+>> endobj
+407 0 obj <<
+/Title 408 0 R
+/A 405 0 R
+/Parent 347 0 R
+/Prev 403 0 R
+/Next 411 0 R
+>> endobj
+403 0 obj <<
+/Title 404 0 R
+/A 401 0 R
+/Parent 347 0 R
+/Prev 399 0 R
+/Next 407 0 R
+>> endobj
+399 0 obj <<
+/Title 400 0 R
+/A 397 0 R
+/Parent 347 0 R
+/Prev 395 0 R
+/Next 403 0 R
+>> endobj
+395 0 obj <<
+/Title 396 0 R
+/A 393 0 R
+/Parent 347 0 R
+/Prev 391 0 R
+/Next 399 0 R
+>> endobj
+391 0 obj <<
+/Title 392 0 R
+/A 389 0 R
+/Parent 347 0 R
+/Prev 387 0 R
+/Next 395 0 R
+>> endobj
+387 0 obj <<
+/Title 388 0 R
+/A 385 0 R
+/Parent 347 0 R
+/Prev 383 0 R
+/Next 391 0 R
+>> endobj
+383 0 obj <<
+/Title 384 0 R
+/A 381 0 R
+/Parent 347 0 R
+/Prev 379 0 R
+/Next 387 0 R
+>> endobj
+379 0 obj <<
+/Title 380 0 R
+/A 377 0 R
+/Parent 347 0 R
+/Prev 375 0 R
+/Next 383 0 R
+>> endobj
+375 0 obj <<
+/Title 376 0 R
+/A 373 0 R
+/Parent 347 0 R
+/Prev 371 0 R
+/Next 379 0 R
+>> endobj
+371 0 obj <<
+/Title 372 0 R
+/A 369 0 R
+/Parent 347 0 R
+/Prev 367 0 R
+/Next 375 0 R
+>> endobj
+367 0 obj <<
+/Title 368 0 R
+/A 365 0 R
+/Parent 347 0 R
+/Prev 363 0 R
+/Next 371 0 R
+>> endobj
+363 0 obj <<
+/Title 364 0 R
+/A 361 0 R
+/Parent 347 0 R
+/Prev 359 0 R
+/Next 367 0 R
+>> endobj
+359 0 obj <<
+/Title 360 0 R
+/A 357 0 R
+/Parent 347 0 R
+/Prev 355 0 R
+/Next 363 0 R
+>> endobj
+355 0 obj <<
+/Title 356 0 R
+/A 353 0 R
+/Parent 347 0 R
+/Prev 351 0 R
+/Next 359 0 R
+>> endobj
+351 0 obj <<
+/Title 352 0 R
+/A 349 0 R
+/Parent 347 0 R
+/Next 355 0 R
+>> endobj
+347 0 obj <<
+/Title 348 0 R
+/A 345 0 R
+/Parent 275 0 R
+/Prev 343 0 R
+/Next 423 0 R
+/First 351 0 R
+/Last 419 0 R
+/Count -18
+>> endobj
+343 0 obj <<
+/Title 344 0 R
+/A 341 0 R
+/Parent 275 0 R
+/Prev 339 0 R
+/Next 347 0 R
+>> endobj
+339 0 obj <<
+/Title 340 0 R
+/A 337 0 R
+/Parent 275 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
+/Next 339 0 R
+>> endobj
+331 0 obj <<
+/Title 332 0 R
+/A 329 0 R
+/Parent 275 0 R
+/Prev 327 0 R
+/Next 335 0 R
+>> endobj
+327 0 obj <<
+/Title 328 0 R
+/A 325 0 R
+/Parent 275 0 R
+/Prev 315 0 R
+/Next 331 0 R
+>> endobj
+323 0 obj <<
+/Title 324 0 R
+/A 321 0 R
+/Parent 315 0 R
+/Prev 319 0 R
+>> endobj
+319 0 obj <<
+/Title 320 0 R
+/A 317 0 R
+/Parent 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 327 0 R
+/First 319 0 R
+/Last 323 0 R
+/Count -2
+>> endobj
+311 0 obj <<
+/Title 312 0 R
+/A 309 0 R
+/Parent 275 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
+/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
+>> endobj
+299 0 obj <<
+/Title 300 0 R
+/A 297 0 R
+/Parent 275 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
+/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
+>> endobj
+287 0 obj <<
+/Title 288 0 R
+/A 285 0 R
+/Parent 275 0 R
+/Prev 283 0 R
+/Next 291 0 R
+>> 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
+/A 277 0 R
+/Parent 275 0 R
+/Next 283 0 R
+>> endobj
+275 0 obj <<
+/Title 276 0 R
+/A 273 0 R
+/Parent 243 0 R
+/Prev 247 0 R
+/Next 479 0 R
+/First 279 0 R
+/Last 459 0 R
+/Count -26
+>> endobj
+271 0 obj <<
+/Title 272 0 R
+/A 269 0 R
+/Parent 263 0 R
+/Prev 267 0 R
+>> endobj
+267 0 obj <<
+/Title 268 0 R
+/A 265 0 R
+/Parent 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
+>> endobj
+259 0 obj <<
+/Title 260 0 R
+/A 257 0 R
+/Parent 251 0 R
+/Prev 255 0 R
+>> endobj
+255 0 obj <<
+/Title 256 0 R
+/A 253 0 R
+/Parent 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
+>> 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
+>> endobj
+243 0 obj <<
+/Title 244 0 R
+/A 241 0 R
+/Parent 2114 0 R
+/Prev 231 0 R
+/Next 559 0 R
+/First 247 0 R
+/Last 531 0 R
+/Count -4
+>> endobj
+239 0 obj <<
+/Title 240 0 R
+/A 237 0 R
+/Parent 231 0 R
+/Prev 235 0 R
+>> endobj
+235 0 obj <<
+/Title 236 0 R
+/A 233 0 R
+/Parent 231 0 R
+/Next 239 0 R
+>> endobj
+231 0 obj <<
+/Title 232 0 R
+/A 229 0 R
+/Parent 2114 0 R
+/Prev 131 0 R
+/Next 243 0 R
+/First 235 0 R
+/Last 239 0 R
+/Count -2
+>> endobj
+227 0 obj <<
+/Title 228 0 R
+/A 225 0 R
+/Parent 219 0 R
+/Prev 223 0 R
+>> endobj
+223 0 obj <<
+/Title 224 0 R
+/A 221 0 R
+/Parent 219 0 R
+/Next 227 0 R
+>> endobj
+219 0 obj <<
+/Title 220 0 R
+/A 217 0 R
+/Parent 131 0 R
+/Prev 203 0 R
+/First 223 0 R
+/Last 227 0 R
+/Count -2
+>> endobj
+215 0 obj <<
+/Title 216 0 R
+/A 213 0 R
+/Parent 203 0 R
+/Prev 211 0 R
+>> endobj
+211 0 obj <<
+/Title 212 0 R
+/A 209 0 R
+/Parent 203 0 R
+/Prev 207 0 R
+/Next 215 0 R
+>> endobj
+207 0 obj <<
+/Title 208 0 R
+/A 205 0 R
+/Parent 203 0 R
+/Next 211 0 R
+>> endobj
+203 0 obj <<
+/Title 204 0 R
+/A 201 0 R
+/Parent 131 0 R
+/Prev 199 0 R
+/Next 219 0 R
+/First 207 0 R
+/Last 215 0 R
+/Count -3
+>> endobj
+199 0 obj <<
+/Title 200 0 R
+/A 197 0 R
+/Parent 131 0 R
+/Prev 195 0 R
+/Next 203 0 R
+>> endobj
+195 0 obj <<
+/Title 196 0 R
+/A 193 0 R
+/Parent 131 0 R
+/Prev 159 0 R
+/Next 199 0 R
+>> endobj
+191 0 obj <<
+/Title 192 0 R
+/A 189 0 R
+/Parent 159 0 R
+/Prev 187 0 R
+>> endobj
+187 0 obj <<
+/Title 188 0 R
+/A 185 0 R
+/Parent 159 0 R
+/Prev 183 0 R
+/Next 191 0 R
+>> endobj
+183 0 obj <<
+/Title 184 0 R
+/A 181 0 R
+/Parent 159 0 R
+/Prev 179 0 R
+/Next 187 0 R
+>> endobj
+179 0 obj <<
+/Title 180 0 R
+/A 177 0 R
+/Parent 159 0 R
+/Prev 175 0 R
+/Next 183 0 R
+>> endobj
+175 0 obj <<
+/Title 176 0 R
+/A 173 0 R
+/Parent 159 0 R
+/Prev 163 0 R
+/Next 179 0 R
+>> endobj
+171 0 obj <<
+/Title 172 0 R
+/A 169 0 R
+/Parent 163 0 R
+/Prev 167 0 R
+>> endobj
+167 0 obj <<
+/Title 168 0 R
+/A 165 0 R
+/Parent 163 0 R
+/Next 171 0 R
+>> endobj
+163 0 obj <<
+/Title 164 0 R
+/A 161 0 R
+/Parent 159 0 R
+/Next 175 0 R
+/First 167 0 R
+/Last 171 0 R
+/Count -2
+>> endobj
+159 0 obj <<
+/Title 160 0 R
+/A 157 0 R
+/Parent 131 0 R
+/Prev 151 0 R
+/Next 195 0 R
+/First 163 0 R
+/Last 191 0 R
+/Count -6
+>> endobj
+155 0 obj <<
+/Title 156 0 R
+/A 153 0 R
+/Parent 151 0 R
+>> endobj
+151 0 obj <<
+/Title 152 0 R
+/A 149 0 R
+/Parent 131 0 R
+/Prev 147 0 R
+/Next 159 0 R
+/First 155 0 R
+/Last 155 0 R
+/Count -1
+>> endobj
+147 0 obj <<
+/Title 148 0 R
+/A 145 0 R
+/Parent 131 0 R
+/Prev 139 0 R
+/Next 151 0 R
+>> endobj
+143 0 obj <<
+/Title 144 0 R
+/A 141 0 R
+/Parent 139 0 R
+>> endobj
+139 0 obj <<
+/Title 140 0 R
+/A 137 0 R
+/Parent 131 0 R
+/Prev 135 0 R
+/Next 147 0 R
+/First 143 0 R
+/Last 143 0 R
+/Count -1
+>> endobj
+135 0 obj <<
+/Title 136 0 R
+/A 133 0 R
+/Parent 131 0 R
+/Next 139 0 R
+>> endobj
+131 0 obj <<
+/Title 132 0 R
+/A 129 0 R
+/Parent 2114 0 R
+/Prev 91 0 R
+/Next 231 0 R
+/First 135 0 R
+/Last 219 0 R
+/Count -9
+>> endobj
+127 0 obj <<
+/Title 128 0 R
+/A 125 0 R
+/Parent 111 0 R
+/Prev 115 0 R
+>> endobj
+123 0 obj <<
+/Title 124 0 R
+/A 121 0 R
+/Parent 115 0 R
+/Prev 119 0 R
+>> endobj
+119 0 obj <<
+/Title 120 0 R
+/A 117 0 R
+/Parent 115 0 R
+/Next 123 0 R
+>> endobj
+115 0 obj <<
+/Title 116 0 R
+/A 113 0 R
+/Parent 111 0 R
+/Next 127 0 R
+/First 119 0 R
+/Last 123 0 R
+/Count -2
+>> endobj
+111 0 obj <<
+/Title 112 0 R
+/A 109 0 R
+/Parent 91 0 R
+/Prev 107 0 R
+/First 115 0 R
+/Last 127 0 R
+/Count -2
+>> endobj
+107 0 obj <<
+/Title 108 0 R
+/A 105 0 R
+/Parent 91 0 R
+/Prev 95 0 R
+/Next 111 0 R
+>> endobj
+103 0 obj <<
+/Title 104 0 R
+/A 101 0 R
+/Parent 95 0 R
+/Prev 99 0 R
+>> endobj
+99 0 obj <<
+/Title 100 0 R
+/A 97 0 R
+/Parent 95 0 R
+/Next 103 0 R
+>> endobj
+95 0 obj <<
+/Title 96 0 R
+/A 93 0 R
+/Parent 91 0 R
+/Next 107 0 R
+/First 99 0 R
+/Last 103 0 R
+/Count -2
+>> endobj
+91 0 obj <<
+/Title 92 0 R
+/A 89 0 R
+/Parent 2114 0 R
+/Prev 67 0 R
+/Next 131 0 R
+/First 95 0 R
+/Last 111 0 R
+/Count -3
+>> endobj
+87 0 obj <<
+/Title 88 0 R
+/A 85 0 R
+/Parent 67 0 R
+/Prev 83 0 R
+>> endobj
+83 0 obj <<
+/Title 84 0 R
+/A 81 0 R
+/Parent 67 0 R
+/Prev 79 0 R
+/Next 87 0 R
+>> endobj
+79 0 obj <<
+/Title 80 0 R
+/A 77 0 R
+/Parent 67 0 R
+/Prev 75 0 R
+/Next 83 0 R
+>> endobj
+75 0 obj <<
+/Title 76 0 R
+/A 73 0 R
+/Parent 67 0 R
+/Prev 71 0 R
+/Next 79 0 R
+>> endobj
+71 0 obj <<
+/Title 72 0 R
+/A 69 0 R
+/Parent 67 0 R
+/Next 75 0 R
+>> endobj
+67 0 obj <<
+/Title 68 0 R
+/A 65 0 R
+/Parent 2114 0 R
+/Prev 7 0 R
+/Next 91 0 R
+/First 71 0 R
+/Last 87 0 R
+/Count -5
+>> endobj
+63 0 obj <<
+/Title 64 0 R
+/A 61 0 R
+/Parent 23 0 R
+/Prev 55 0 R
+>> endobj
+59 0 obj <<
+/Title 60 0 R
+/A 57 0 R
+/Parent 55 0 R
+>> endobj
+55 0 obj <<
+/Title 56 0 R
+/A 53 0 R
+/Parent 23 0 R
+/Prev 39 0 R
+/Next 63 0 R
+/First 59 0 R
+/Last 59 0 R
+/Count -1
+>> endobj
+51 0 obj <<
+/Title 52 0 R
+/A 49 0 R
+/Parent 39 0 R
+/Prev 47 0 R
+>> endobj
+47 0 obj <<
+/Title 48 0 R
+/A 45 0 R
+/Parent 39 0 R
+/Prev 43 0 R
+/Next 51 0 R
+>> endobj
+43 0 obj <<
+/Title 44 0 R
+/A 41 0 R
+/Parent 39 0 R
+/Next 47 0 R
+>> endobj
+39 0 obj <<
+/Title 40 0 R
+/A 37 0 R
+/Parent 23 0 R
+/Prev 35 0 R
+/Next 55 0 R
+/First 43 0 R
+/Last 51 0 R
+/Count -3
+>> endobj
+35 0 obj <<
+/Title 36 0 R
+/A 33 0 R
+/Parent 23 0 R
+/Prev 31 0 R
+/Next 39 0 R
+>> endobj
+31 0 obj <<
+/Title 32 0 R
+/A 29 0 R
+/Parent 23 0 R
+/Prev 27 0 R
+/Next 35 0 R
+>> endobj
+27 0 obj <<
+/Title 28 0 R
+/A 25 0 R
+/Parent 23 0 R
+/Next 31 0 R
+>> endobj
+23 0 obj <<
+/Title 24 0 R
+/A 21 0 R
+/Parent 7 0 R
+/Prev 19 0 R
+/First 27 0 R
+/Last 63 0 R
+/Count -6
+>> endobj
+19 0 obj <<
+/Title 20 0 R
+/A 17 0 R
+/Parent 7 0 R
+/Prev 15 0 R
+/Next 23 0 R
+>> endobj
+15 0 obj <<
+/Title 16 0 R
+/A 13 0 R
+/Parent 7 0 R
+/Prev 11 0 R
+/Next 19 0 R
+>> endobj
+11 0 obj <<
+/Title 12 0 R
+/A 9 0 R
+/Parent 7 0 R
+/Next 15 0 R
+>> endobj
+7 0 obj <<
+/Title 8 0 R
+/A 5 0 R
+/Parent 2114 0 R
+/Next 67 0 R
+/First 11 0 R
+/Last 23 0 R
+/Count -4
+>> endobj
+2115 0 obj <<
+/Names [(Access_Control_Lists) 1591 0 R (Bv9ARM.ch01) 932 0 R (Bv9ARM.ch02) 978 0 R (Bv9ARM.ch03) 995 0 R (Bv9ARM.ch04) 1044 0 R (Bv9ARM.ch05) 1132 0 R (Bv9ARM.ch06) 1143 0 R (Bv9ARM.ch07) 1590 0 R (Bv9ARM.ch08) 1616 0 R (Bv9ARM.ch09) 1631 0 R (Bv9ARM.ch10) 1852 0 R (Configuration_File_Grammar) 1168 0 R (DNSSEC) 1111 0 R (Doc-Start) 699 0 R (Setting_TTLs) 1526 0 R (acache) 985 0 R (access_control) 1290 0 R (acl) 1176 0 R (address_match_lists) 1149 0 R (admin_tools) 1018 0 R (appendix.A) 602 0 R (appendix.B) 638 0 R (bibliography) 1640 0 R (boolean_options) 1060 0 R (builtin) 1368 0 R (chapter*.1) 734 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) 558 0 R (chapter.8) 582 0 R (cite.RFC1033) 1767 0 R (cite.RFC1034) 1652 0 R (cite.RFC1035) 1654 0 R (cite.RFC1101) 1749 0 R (cite.RFC1123) 1751 0 R (cite.RFC1183) 1711 0 R (cite.RFC1464) 1789 0 R (cite.RFC1535) 1697 0 R (cite.RFC1536) 1699 0 R (cite.RFC1537) 1769 0 R (cite.RFC1591) 1753 0 R (cite.RFC1706) 1713 0 R (cite.RFC1712) 1809 0 R (cite.RFC1713) 1791 0 R (cite.RFC1794) 1793 0 R (cite.RFC1876) 1715 0 R (cite.RFC1912) 1771 0 R (cite.RFC1982) 1701 0 R (cite.RFC1995) 1659 0 R (cite.RFC1996) 1661 0 R (cite.RFC2010) 1773 0 R (cite.RFC2052) 1717 0 R (cite.RFC2065) 1821 0 R (cite.RFC2136) 1663 0 R (cite.RFC2137) 1823 0 R (cite.RFC2163) 1719 0 R (cite.RFC2168) 1721 0 R (cite.RFC2181) 1665 0 R (cite.RFC2219) 1775 0 R (cite.RFC2230) 1723 0 R (cite.RFC2240) 1795 0 R (cite.RFC2308) 1667 0 R (cite.RFC2317) 1755 0 R (cite.RFC2345) 1797 0 R (cite.RFC2352) 1799 0 R (cite.RFC2535) 1825 0 R (cite.RFC2536) 1725 0 R (cite.RFC2537) 1727 0 R (cite.RFC2538) 1729 0 R (cite.RFC2539) 1731 0 R (cite.RFC2540) 1733 0 R (cite.RFC2671) 1669 0 R (cite.RFC2672) 1671 0 R (cite.RFC2673) 1811 0 R (cite.RFC2782) 1735 0 R (cite.RFC2825) 1779 0 R (cite.RFC2826) 1757 0 R (cite.RFC2845) 1673 0 R (cite.RFC2874) 1813 0 R (cite.RFC2915) 1737 0 R (cite.RFC2929) 1759 0 R (cite.RFC2930) 1675 0 R (cite.RFC2931) 1677 0 R (cite.RFC3007) 1679 0 R (cite.RFC3008) 1827 0 R (cite.RFC3071) 1801 0 R (cite.RFC3090) 1829 0 R (cite.RFC3110) 1739 0 R (cite.RFC3123) 1741 0 R (cite.RFC3225) 1685 0 R (cite.RFC3258) 1803 0 R (cite.RFC3445) 1831 0 R (cite.RFC3490) 1781 0 R (cite.RFC3491) 1783 0 R (cite.RFC3492) 1785 0 R (cite.RFC3596) 1743 0 R (cite.RFC3597) 1745 0 R (cite.RFC3645) 1681 0 R (cite.RFC3655) 1833 0 R (cite.RFC3658) 1835 0 R (cite.RFC3755) 1837 0 R (cite.RFC3757) 1839 0 R (cite.RFC3833) 1687 0 R (cite.RFC3845) 1841 0 R (cite.RFC3901) 1805 0 R (cite.RFC4033) 1689 0 R (cite.RFC4034) 1691 0 R (cite.RFC4035) 1693 0 R (cite.RFC4074) 1703 0 R (cite.RFC974) 1656 0 R (cite.id2504427) 1846 0 R (configuration_file_elements) 1144 0 R (controls_statement_definition_and_usage) 1031 0 R (diagnostic_tools) 966 0 R (dynamic_update) 1054 0 R (dynamic_update_policies) 1106 0 R (dynamic_update_security) 1299 0 R (empty) 1376 0 R (historical_dns_information) 1633 0 R (id2464966) 933 0 R (id2466572) 934 0 R (id2467531) 935 0 R (id2467541) 936 0 R (id2467713) 948 0 R (id2467734) 949 0 R (id2467768) 950 0 R (id2467852) 953 0 R (id2467945) 946 0 R (id2470250) 960 0 R (id2470274) 963 0 R (id2470372) 964 0 R (id2470393) 965 0 R (id2470423) 971 0 R (id2470526) 972 0 R (id2470553) 973 0 R (id2470587) 979 0 R (id2470614) 980 0 R (id2470627) 981 0 R (id2470721) 984 0 R (id2470731) 990 0 R (id2470763) 997 0 R (id2470779) 998 0 R (id2470802) 1004 0 R (id2470819) 1005 0 R (id2471224) 1008 0 R (id2471229) 1009 0 R (id2473110) 1036 0 R (id2473122) 1037 0 R (id2473515) 1069 0 R (id2473533) 1070 0 R (id2473969) 1086 0 R (id2473986) 1087 0 R (id2474024) 1092 0 R (id2474042) 1093 0 R (id2474121) 1094 0 R (id2474161) 1095 0 R (id2474286) 1100 0 R (id2474331) 1102 0 R (id2474345) 1103 0 R (id2474462) 1104 0 R (id2474599) 1112 0 R (id2474678) 1113 0 R (id2474759) 1118 0 R (id2474902) 1123 0 R (id2475169) 1125 0 R (id2475190) 1126 0 R (id2475291) 1133 0 R (id2475438) 1145 0 R (id2476300) 1154 0 R (id2476328) 1159 0 R (id2476522) 1160 0 R (id2476537) 1161 0 R (id2476567) 1167 0 R (id2476718) 1169 0 R (id2477161) 1175 0 R (id2477272) 1177 0 R (id2477419) 1179 0 R (id2477780) 1186 0 R (id2477797) 1192 0 R (id2477889) 1193 0 R (id2477912) 1194 0 R (id2478003) 1198 0 R (id2478197) 1204 0 R (id2478249) 1205 0 R (id2478942) 1216 0 R (id2479645) 1226 0 R (id2479719) 1227 0 R (id2479783) 1230 0 R (id2479827) 1231 0 R (id2479842) 1232 0 R (id2482169) 1261 0 R (id2484043) 1287 0 R (id2484102) 1289 0 R (id2484598) 1304 0 R (id2485793) 1323 0 R (id2485852) 1325 0 R (id2486200) 1337 0 R (id2486839) 1352 0 R (id2488339) 1386 0 R (id2489091) 1399 0 R (id2489142) 1400 0 R (id2489292) 1402 0 R (id2490761) 1419 0 R (id2490769) 1420 0 R (id2490774) 1421 0 R (id2491188) 1428 0 R (id2491221) 1433 0 R (id2492840) 1485 0 R (id2493223) 1491 0 R (id2493309) 1492 0 R (id2493330) 1495 0 R (id2493498) 1497 0 R (id2494737) 1508 0 R (id2494865) 1514 0 R (id2495022) 1515 0 R (id2495385) 1517 0 R (id2495522) 1519 0 R (id2495544) 1524 0 R (id2496017) 1527 0 R (id2496141) 1529 0 R (id2496156) 1530 0 R (id2496268) 1536 0 R (id2496291) 1537 0 R (id2496420) 1538 0 R (id2496489) 1539 0 R (id2496525) 1544 0 R (id2496587) 1545 0 R (id2497018) 1553 0 R (id2497363) 1561 0 R (id2497368) 1562 0 R (id2499022) 1568 0 R (id2499029) 1569 0 R (id2499405) 1571 0 R (id2499411) 1572 0 R (id2500259) 1581 0 R (id2500446) 1601 0 R (id2500592) 1602 0 R (id2500651) 1603 0 R (id2500731) 1617 0 R (id2500737) 1618 0 R (id2500748) 1619 0 R (id2500765) 1620 0 R (id2500964) 1632 0 R (id2501136) 1639 0 R (id2501255) 1644 0 R (id2501257) 1650 0 R (id2501266) 1655 0 R (id2501289) 1651 0 R (id2501381) 1653 0 R (id2501417) 1664 0 R (id2501444) 1666 0 R (id2501469) 1658 0 R (id2501494) 1660 0 R (id2501517) 1662 0 R (id2501573) 1668 0 R (id2501600) 1670 0 R (id2501626) 1672 0 R (id2501688) 1674 0 R (id2501718) 1676 0 R (id2501748) 1678 0 R (id2501843) 1680 0 R (id2501917) 1683 0 R (id2501925) 1684 0 R (id2501952) 1686 0 R (id2501988) 1688 0 R (id2502053) 1690 0 R (id2502118) 1692 0 R (id2502183) 1695 0 R (id2502192) 1696 0 R (id2502217) 1698 0 R (id2502285) 1700 0 R (id2502321) 1702 0 R (id2502361) 1709 0 R (id2502366) 1710 0 R (id2502424) 1712 0 R (id2502461) 1720 0 R (id2502497) 1714 0 R (id2502551) 1716 0 R (id2502589) 1718 0 R (id2502615) 1722 0 R (id2502641) 1724 0 R (id2502667) 1726 0 R (id2502694) 1728 0 R (id2502733) 1730 0 R (id2502763) 1732 0 R (id2502793) 1734 0 R (id2502836) 1736 0 R (id2502869) 1738 0 R (id2502896) 1740 0 R (id2502919) 1742 0 R (id2502977) 1744 0 R (id2503001) 1747 0 R (id2503009) 1748 0 R (id2503034) 1750 0 R (id2503057) 1752 0 R (id2503080) 1754 0 R (id2503126) 1756 0 R (id2503149) 1758 0 R (id2503200) 1765 0 R (id2503207) 1766 0 R (id2503230) 1768 0 R (id2503257) 1770 0 R (id2503352) 1772 0 R (id2503388) 1774 0 R (id2503429) 1777 0 R (id2503434) 1778 0 R (id2503466) 1780 0 R (id2503512) 1782 0 R (id2503547) 1784 0 R (id2503574) 1787 0 R (id2503592) 1788 0 R (id2503614) 1790 0 R (id2503640) 1792 0 R (id2503666) 1794 0 R (id2503689) 1796 0 R (id2503735) 1798 0 R (id2503758) 1800 0 R (id2503785) 1802 0 R (id2503811) 1804 0 R (id2503848) 1807 0 R (id2503854) 1808 0 R (id2503912) 1810 0 R (id2503939) 1812 0 R (id2503975) 1819 0 R (id2503987) 1820 0 R (id2504026) 1822 0 R (id2504053) 1824 0 R (id2504083) 1826 0 R (id2504108) 1828 0 R (id2504135) 1830 0 R (id2504240) 1832 0 R (id2504276) 1834 0 R (id2504302) 1836 0 R (id2504329) 1838 0 R (id2504374) 1840 0 R (id2504416) 1843 0 R (id2504425) 1845 0 R (id2504427) 1847 0 R (incremental_zone_transfers) 1066 0 R (internet_drafts) 1842 0 R (ipv6addresses) 1127 0 R (journal) 1055 0 R (lwresd) 1134 0 R (man.dig) 1853 0 R (man.dnssec-dsfromkey) 1902 0 R (man.dnssec-keyfromlabel) 1916 0 R (man.dnssec-keygen) 1932 0 R (man.dnssec-signzone) 1949 0 R (man.host) 1886 0 R (man.named) 2003 0 R (man.named-checkconf) 1970 0 R (man.named-checkzone) 1982 0 R (man.nsupdate) 2021 0 R (man.rndc) 2047 0 R (man.rndc-confgen) 2075 0 R (man.rndc.conf) 2059 0 R (notify) 1045 0 R (options) 1246 0 R (page.1) 698 0 R (page.10) 970 0 R (page.100) 1707 0 R (page.101) 1763 0 R (page.102) 1817 0 R (page.103) 1851 0 R (page.104) 1861 0 R (page.105) 1867 0 R (page.106) 1872 0 R (page.107) 1876 0 R (page.108) 1881 0 R (page.109) 1892 0 R (page.11) 977 0 R (page.110) 1898 0 R (page.111) 1910 0 R (page.112) 1921 0 R (page.113) 1928 0 R (page.114) 1940 0 R (page.115) 1944 0 R (page.116) 1956 0 R (page.117) 1962 0 R (page.118) 1966 0 R (page.119) 1976 0 R (page.12) 989 0 R (page.120) 1988 0 R (page.121) 1994 0 R (page.122) 2002 0 R (page.123) 2011 0 R (page.124) 2015 0 R (page.125) 2026 0 R (page.126) 2032 0 R (page.127) 2037 0 R (page.128) 2043 0 R (page.129) 2055 0 R (page.13) 994 0 R (page.130) 2065 0 R (page.131) 2071 0 R (page.132) 2080 0 R (page.133) 2087 0 R (page.14) 1003 0 R (page.15) 1014 0 R (page.16) 1022 0 R (page.17) 1029 0 R (page.18) 1035 0 R (page.19) 1043 0 R (page.2) 723 0 R (page.20) 1065 0 R (page.21) 1075 0 R (page.22) 1080 0 R (page.23) 1084 0 R (page.24) 1091 0 R (page.25) 1099 0 R (page.26) 1110 0 R (page.27) 1117 0 R (page.28) 1122 0 R (page.29) 1131 0 R (page.3) 733 0 R (page.30) 1138 0 R (page.31) 1142 0 R (page.32) 1153 0 R (page.33) 1158 0 R (page.34) 1166 0 R (page.35) 1174 0 R (page.36) 1183 0 R (page.37) 1191 0 R (page.38) 1203 0 R (page.39) 1209 0 R (page.4) 788 0 R (page.40) 1215 0 R (page.41) 1221 0 R (page.42) 1225 0 R (page.43) 1236 0 R (page.44) 1241 0 R (page.45) 1245 0 R (page.46) 1250 0 R (page.47) 1256 0 R (page.48) 1260 0 R (page.49) 1267 0 R (page.5) 852 0 R (page.50) 1278 0 R (page.51) 1282 0 R (page.52) 1286 0 R (page.53) 1296 0 R (page.54) 1303 0 R (page.55) 1309 0 R (page.56) 1314 0 R (page.57) 1318 0 R (page.58) 1322 0 R (page.59) 1330 0 R (page.6) 914 0 R (page.60) 1336 0 R (page.61) 1342 0 R (page.62) 1350 0 R (page.63) 1358 0 R (page.64) 1363 0 R (page.65) 1375 0 R (page.66) 1380 0 R (page.67) 1384 0 R (page.68) 1392 0 R (page.69) 1397 0 R (page.7) 931 0 R (page.70) 1406 0 R (page.71) 1410 0 R (page.72) 1414 0 R (page.73) 1418 0 R (page.74) 1427 0 R (page.75) 1432 0 R (page.76) 1451 0 R (page.77) 1464 0 R (page.78) 1484 0 R (page.79) 1490 0 R (page.8) 945 0 R (page.80) 1503 0 R (page.81) 1507 0 R (page.82) 1513 0 R (page.83) 1523 0 R (page.84) 1535 0 R (page.85) 1543 0 R (page.86) 1551 0 R (page.87) 1559 0 R (page.88) 1567 0 R (page.89) 1576 0 R (page.9) 959 0 R (page.90) 1585 0 R (page.91) 1589 0 R (page.92) 1596 0 R (page.93) 1607 0 R (page.94) 1611 0 R (page.95) 1615 0 R (page.96) 1626 0 R (page.97) 1630 0 R (page.98) 1638 0 R (page.99) 1648 0 R (proposed_standards) 1071 0 R (query_address) 1305 0 R (rfcs) 955 0 R (rndc) 1187 0 R (rrset_ordering) 1010 0 R (sample_configuration) 996 0 R (section*.10) 1776 0 R (section*.100) 2058 0 R (section*.101) 2060 0 R (section*.102) 2061 0 R (section*.103) 2066 0 R (section*.104) 2067 0 R (section*.105) 2072 0 R (section*.106) 2073 0 R (section*.107) 2074 0 R (section*.108) 2076 0 R (section*.109) 2081 0 R (section*.11) 1786 0 R (section*.110) 2082 0 R (section*.111) 2083 0 R (section*.112) 2088 0 R (section*.113) 2089 0 R (section*.114) 2090 0 R (section*.12) 1806 0 R (section*.13) 1818 0 R (section*.14) 1844 0 R (section*.15) 1854 0 R (section*.16) 1855 0 R (section*.17) 1856 0 R (section*.18) 1862 0 R (section*.19) 1863 0 R (section*.2) 1643 0 R (section*.20) 1868 0 R (section*.21) 1877 0 R (section*.22) 1882 0 R (section*.23) 1883 0 R (section*.24) 1884 0 R (section*.25) 1885 0 R (section*.26) 1887 0 R (section*.27) 1888 0 R (section*.28) 1893 0 R (section*.29) 1899 0 R (section*.3) 1649 0 R (section*.30) 1900 0 R (section*.31) 1901 0 R (section*.32) 1903 0 R (section*.33) 1904 0 R (section*.34) 1905 0 R (section*.35) 1906 0 R (section*.36) 1911 0 R (section*.37) 1912 0 R (section*.38) 1913 0 R (section*.39) 1914 0 R (section*.4) 1657 0 R (section*.40) 1915 0 R (section*.41) 1917 0 R (section*.42) 1922 0 R (section*.43) 1923 0 R (section*.44) 1924 0 R (section*.45) 1929 0 R (section*.46) 1930 0 R (section*.47) 1931 0 R (section*.48) 1933 0 R (section*.49) 1934 0 R (section*.5) 1682 0 R (section*.50) 1935 0 R (section*.51) 1936 0 R (section*.52) 1945 0 R (section*.53) 1946 0 R (section*.54) 1947 0 R (section*.55) 1948 0 R (section*.56) 1950 0 R (section*.57) 1951 0 R (section*.58) 1957 0 R (section*.59) 1958 0 R (section*.6) 1694 0 R (section*.60) 1967 0 R (section*.61) 1968 0 R (section*.62) 1969 0 R (section*.63) 1971 0 R (section*.64) 1972 0 R (section*.65) 1977 0 R (section*.66) 1978 0 R (section*.67) 1979 0 R (section*.68) 1980 0 R (section*.69) 1981 0 R (section*.7) 1708 0 R (section*.70) 1983 0 R (section*.71) 1984 0 R (section*.72) 1989 0 R (section*.73) 1990 0 R (section*.74) 1995 0 R (section*.75) 1996 0 R (section*.76) 1997 0 R (section*.77) 2004 0 R (section*.78) 2005 0 R (section*.79) 2006 0 R (section*.8) 1746 0 R (section*.80) 2007 0 R (section*.81) 2016 0 R (section*.82) 2017 0 R (section*.83) 2018 0 R (section*.84) 2019 0 R (section*.85) 2020 0 R (section*.86) 2022 0 R (section*.87) 2027 0 R (section*.88) 2028 0 R (section*.89) 2033 0 R (section*.9) 1764 0 R (section*.90) 2038 0 R (section*.91) 2044 0 R (section*.92) 2045 0 R (section*.93) 2046 0 R (section*.94) 2048 0 R (section*.95) 2049 0 R (section*.96) 2050 0 R (section*.97) 2051 0 R (section*.98) 2056 0 R (section*.99) 2057 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) 478 0 R (section.6.4) 530 0 R (section.7.1) 562 0 R (section.7.2) 566 0 R (section.7.3) 578 0 R (section.8.1) 586 0 R (section.8.2) 594 0 R (section.8.3) 598 0 R (section.A.1) 606 0 R (section.A.2) 614 0 R (section.A.3) 622 0 R (section.B.1) 642 0 R (section.B.10) 678 0 R (section.B.11) 682 0 R (section.B.12) 686 0 R (section.B.13) 690 0 R (section.B.2) 646 0 R (section.B.3) 650 0 R (section.B.4) 654 0 R (section.B.5) 658 0 R (section.B.6) 662 0 R (section.B.7) 666 0 R (section.B.8) 670 0 R (section.B.9) 674 0 R (server_resource_limits) 1331 0 R (server_statement_definition_and_usage) 1274 0 R (server_statement_grammar) 1387 0 R (statistics) 1552 0 R (statistics_counters) 1560 0 R (statschannels) 1385 0 R (statsfile) 1252 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) 326 0 R (subsection.6.2.12) 330 0 R (subsection.6.2.13) 334 0 R (subsection.6.2.14) 338 0 R (subsection.6.2.15) 342 0 R (subsection.6.2.16) 346 0 R (subsection.6.2.17) 422 0 R (subsection.6.2.18) 426 0 R (subsection.6.2.19) 430 0 R (subsection.6.2.2) 282 0 R (subsection.6.2.20) 434 0 R (subsection.6.2.21) 438 0 R (subsection.6.2.22) 442 0 R (subsection.6.2.23) 446 0 R (subsection.6.2.24) 450 0 R (subsection.6.2.25) 454 0 R (subsection.6.2.26) 458 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) 482 0 R (subsection.6.3.2) 494 0 R (subsection.6.3.3) 498 0 R (subsection.6.3.4) 502 0 R (subsection.6.3.5) 506 0 R (subsection.6.3.6) 522 0 R (subsection.6.3.7) 526 0 R (subsection.6.4.1) 538 0 R (subsection.7.2.1) 570 0 R (subsection.7.2.2) 574 0 R (subsection.8.1.1) 590 0 R (subsection.A.1.1) 610 0 R (subsection.A.2.1) 618 0 R (subsection.A.3.1) 626 0 R (subsection.A.3.2) 630 0 R (subsection.A.3.3) 634 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.16.1) 350 0 R (subsubsection.6.2.16.10) 386 0 R (subsubsection.6.2.16.11) 390 0 R (subsubsection.6.2.16.12) 394 0 R (subsubsection.6.2.16.13) 398 0 R (subsubsection.6.2.16.14) 402 0 R (subsubsection.6.2.16.15) 406 0 R (subsubsection.6.2.16.16) 410 0 R (subsubsection.6.2.16.17) 414 0 R (subsubsection.6.2.16.18) 418 0 R (subsubsection.6.2.16.2) 354 0 R (subsubsection.6.2.16.3) 358 0 R (subsubsection.6.2.16.4) 362 0 R (subsubsection.6.2.16.5) 366 0 R (subsubsection.6.2.16.6) 370 0 R (subsubsection.6.2.16.7) 374 0 R (subsubsection.6.2.16.8) 378 0 R (subsubsection.6.2.16.9) 382 0 R (subsubsection.6.2.26.1) 462 0 R (subsubsection.6.2.26.2) 466 0 R (subsubsection.6.2.26.3) 470 0 R (subsubsection.6.2.26.4) 474 0 R (subsubsection.6.3.1.1) 486 0 R (subsubsection.6.3.1.2) 490 0 R (subsubsection.6.3.5.1) 510 0 R (subsubsection.6.3.5.2) 514 0 R (subsubsection.6.3.5.3) 518 0 R (subsubsection.6.4.0.1) 534 0 R (subsubsection.6.4.1.1) 542 0 R (subsubsection.6.4.1.2) 546 0 R (subsubsection.6.4.1.3) 550 0 R (subsubsection.6.4.1.4) 554 0 R (table.1.1) 937 0 R (table.1.2) 947 0 R (table.3.1) 1006 0 R (table.3.2) 1038 0 R (table.6.1) 1146 0 R (table.6.10) 1498 0 R (table.6.11) 1509 0 R (table.6.12) 1516 0 R (table.6.13) 1518 0 R (table.6.14) 1525 0 R (table.6.15) 1528 0 R (table.6.16) 1531 0 R (table.6.17) 1546 0 R (table.6.18) 1554 0 R (table.6.19) 1563 0 R (table.6.2) 1170 0 R (table.6.20) 1570 0 R (table.6.21) 1577 0 R (table.6.3) 1178 0 R (table.6.4) 1217 0 R (table.6.5) 1262 0 R (table.6.6) 1353 0 R (table.6.7) 1422 0 R (table.6.8) 1486 0 R (table.6.9) 1496 0 R (the_category_phrase) 1211 0 R (the_sortlist_statement) 1343 0 R (topology) 1338 0 R (tsig) 1085 0 R (tuning) 1354 0 R (types_of_resource_records_and_when_to_use_them) 954 0 R (view_statement_grammar) 1371 0 R (zone_statement_grammar) 1292 0 R (zone_transfers) 1061 0 R (zonefile_format) 1370 0 R]
+/Limits [(Access_Control_Lists) (zonefile_format)]
+>> endobj
+2116 0 obj <<
+/Kids [2115 0 R]
+>> endobj
+2117 0 obj <<
+/Dests 2116 0 R
+>> endobj
+2118 0 obj <<
+/Type /Catalog
+/Pages 2113 0 R
+/Outlines 2114 0 R
+/Names 2117 0 R
+/PageMode /UseOutlines
+/OpenAction 693 0 R
+>> endobj
+2119 0 obj <<
+/Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfeTeX-1.21a)/Keywords()
+/CreationDate (D:20081116011130Z)
+/PTEX.Fullbanner (This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4)
+>> endobj
+xref
+0 2120
+0000000001 65535 f
+0000000002 00000 f
+0000000003 00000 f
+0000000004 00000 f
+0000000000 00000 f
+0000000009 00000 n
+0000070820 00000 n
+0000731720 00000 n
+0000000054 00000 n
+0000000086 00000 n
+0000070944 00000 n
+0000731648 00000 n
+0000000133 00000 n
+0000000173 00000 n
+0000071069 00000 n
+0000731562 00000 n
+0000000221 00000 n
+0000000273 00000 n
+0000071194 00000 n
+0000731476 00000 n
+0000000321 00000 n
+0000000377 00000 n
+0000075519 00000 n
+0000731366 00000 n
+0000000425 00000 n
+0000000478 00000 n
+0000075643 00000 n
+0000731292 00000 n
+0000000531 00000 n
+0000000572 00000 n
+0000075768 00000 n
+0000731205 00000 n
+0000000625 00000 n
+0000000674 00000 n
+0000075892 00000 n
+0000731118 00000 n
+0000000727 00000 n
+0000000757 00000 n
+0000080171 00000 n
+0000730994 00000 n
+0000000810 00000 n
+0000000861 00000 n
+0000080296 00000 n
+0000730920 00000 n
+0000000919 00000 n
+0000000964 00000 n
+0000080421 00000 n
+0000730833 00000 n
+0000001022 00000 n
+0000001062 00000 n
+0000080546 00000 n
+0000730759 00000 n
+0000001120 00000 n
+0000001162 00000 n
+0000083518 00000 n
+0000730635 00000 n
+0000001215 00000 n
+0000001260 00000 n
+0000083643 00000 n
+0000730574 00000 n
+0000001318 00000 n
+0000001355 00000 n
+0000083768 00000 n
+0000730500 00000 n
+0000001408 00000 n
+0000001463 00000 n
+0000086696 00000 n
+0000730375 00000 n
+0000001509 00000 n
+0000001556 00000 n
+0000086821 00000 n
+0000730301 00000 n
+0000001604 00000 n
+0000001648 00000 n
+0000086946 00000 n
+0000730214 00000 n
+0000001696 00000 n
+0000001735 00000 n
+0000087071 00000 n
+0000730127 00000 n
+0000001783 00000 n
+0000001825 00000 n
+0000087195 00000 n
+0000730040 00000 n
+0000001873 00000 n
+0000001936 00000 n
+0000088275 00000 n
+0000729966 00000 n
+0000001984 00000 n
+0000002034 00000 n
+0000089985 00000 n
+0000729838 00000 n
+0000002080 00000 n
+0000002126 00000 n
+0000090109 00000 n
+0000729725 00000 n
+0000002174 00000 n
+0000002218 00000 n
+0000090234 00000 n
+0000729649 00000 n
+0000002271 00000 n
+0000002323 00000 n
+0000090359 00000 n
+0000729572 00000 n
+0000002377 00000 n
+0000002436 00000 n
+0000092896 00000 n
+0000729481 00000 n
+0000002485 00000 n
+0000002523 00000 n
+0000093155 00000 n
+0000729364 00000 n
+0000002572 00000 n
+0000002618 00000 n
+0000093284 00000 n
+0000729246 00000 n
+0000002672 00000 n
+0000002739 00000 n
+0000096500 00000 n
+0000729167 00000 n
+0000002798 00000 n
+0000002842 00000 n
+0000096628 00000 n
+0000729088 00000 n
+0000002901 00000 n
+0000002949 00000 n
+0000107160 00000 n
+0000729009 00000 n
+0000003003 00000 n
+0000003036 00000 n
+0000112147 00000 n
+0000728877 00000 n
+0000003083 00000 n
+0000003126 00000 n
+0000112276 00000 n
+0000728798 00000 n
+0000003175 00000 n
+0000003205 00000 n
+0000112405 00000 n
+0000728666 00000 n
+0000003254 00000 n
+0000003292 00000 n
+0000112534 00000 n
+0000728601 00000 n
+0000003346 00000 n
+0000003388 00000 n
+0000116796 00000 n
+0000728508 00000 n
+0000003437 00000 n
+0000003496 00000 n
+0000116925 00000 n
+0000728376 00000 n
+0000003545 00000 n
+0000003578 00000 n
+0000117054 00000 n
+0000728311 00000 n
+0000003632 00000 n
+0000003681 00000 n
+0000124364 00000 n
+0000728179 00000 n
+0000003730 00000 n
+0000003758 00000 n
+0000124493 00000 n
+0000728061 00000 n
+0000003812 00000 n
+0000003881 00000 n
+0000124622 00000 n
+0000727982 00000 n
+0000003940 00000 n
+0000003988 00000 n
+0000127456 00000 n
+0000727903 00000 n
+0000004047 00000 n
+0000004092 00000 n
+0000127585 00000 n
+0000727810 00000 n
+0000004146 00000 n
+0000004214 00000 n
+0000127714 00000 n
+0000727717 00000 n
+0000004268 00000 n
+0000004338 00000 n
+0000127843 00000 n
+0000727624 00000 n
+0000004392 00000 n
+0000004455 00000 n
+0000131746 00000 n
+0000727531 00000 n
+0000004509 00000 n
+0000004564 00000 n
+0000131875 00000 n
+0000727452 00000 n
+0000004618 00000 n
+0000004650 00000 n
+0000132004 00000 n
+0000727359 00000 n
+0000004699 00000 n
+0000004727 00000 n
+0000132133 00000 n
+0000727266 00000 n
+0000004776 00000 n
+0000004808 00000 n
+0000135910 00000 n
+0000727134 00000 n
+0000004857 00000 n
+0000004887 00000 n
+0000136039 00000 n
+0000727055 00000 n
+0000004941 00000 n
+0000004982 00000 n
+0000136168 00000 n
+0000726962 00000 n
+0000005036 00000 n
+0000005078 00000 n
+0000139609 00000 n
+0000726883 00000 n
+0000005132 00000 n
+0000005177 00000 n
+0000142684 00000 n
+0000726765 00000 n
+0000005226 00000 n
+0000005272 00000 n
+0000142813 00000 n
+0000726686 00000 n
+0000005326 00000 n
+0000005386 00000 n
+0000142941 00000 n
+0000726607 00000 n
+0000005440 00000 n
+0000005509 00000 n
+0000145423 00000 n
+0000726474 00000 n
+0000005556 00000 n
+0000005609 00000 n
+0000145552 00000 n
+0000726395 00000 n
+0000005658 00000 n
+0000005714 00000 n
+0000145681 00000 n
+0000726316 00000 n
+0000005763 00000 n
+0000005812 00000 n
+0000149865 00000 n
+0000726183 00000 n
+0000005859 00000 n
+0000005911 00000 n
+0000149994 00000 n
+0000726065 00000 n
+0000005960 00000 n
+0000006011 00000 n
+0000154684 00000 n
+0000725947 00000 n
+0000006065 00000 n
+0000006110 00000 n
+0000154812 00000 n
+0000725868 00000 n
+0000006169 00000 n
+0000006203 00000 n
+0000158401 00000 n
+0000725789 00000 n
+0000006262 00000 n
+0000006310 00000 n
+0000158529 00000 n
+0000725671 00000 n
+0000006364 00000 n
+0000006404 00000 n
+0000158658 00000 n
+0000725592 00000 n
+0000006463 00000 n
+0000006497 00000 n
+0000162385 00000 n
+0000725513 00000 n
+0000006556 00000 n
+0000006604 00000 n
+0000162514 00000 n
+0000725380 00000 n
+0000006653 00000 n
+0000006703 00000 n
+0000165534 00000 n
+0000725301 00000 n
+0000006757 00000 n
+0000006804 00000 n
+0000165662 00000 n
+0000725208 00000 n
+0000006858 00000 n
+0000006918 00000 n
+0000165920 00000 n
+0000725115 00000 n
+0000006972 00000 n
+0000007024 00000 n
+0000171027 00000 n
+0000725022 00000 n
+0000007078 00000 n
+0000007143 00000 n
+0000171156 00000 n
+0000724929 00000 n
+0000007197 00000 n
+0000007248 00000 n
+0000174630 00000 n
+0000724836 00000 n
+0000007302 00000 n
+0000007366 00000 n
+0000174759 00000 n
+0000724743 00000 n
+0000007420 00000 n
+0000007467 00000 n
+0000174888 00000 n
+0000724650 00000 n
+0000007521 00000 n
+0000007581 00000 n
+0000175017 00000 n
+0000724557 00000 n
+0000007635 00000 n
+0000007686 00000 n
+0000179033 00000 n
+0000724425 00000 n
+0000007741 00000 n
+0000007806 00000 n
+0000179162 00000 n
+0000724346 00000 n
+0000007866 00000 n
+0000007913 00000 n
+0000185987 00000 n
+0000724267 00000 n
+0000007973 00000 n
+0000008021 00000 n
+0000192355 00000 n
+0000724174 00000 n
+0000008076 00000 n
+0000008126 00000 n
+0000192484 00000 n
+0000724081 00000 n
+0000008181 00000 n
+0000008244 00000 n
+0000192612 00000 n
+0000723988 00000 n
+0000008299 00000 n
+0000008351 00000 n
+0000192740 00000 n
+0000723895 00000 n
+0000008406 00000 n
+0000008471 00000 n
+0000192869 00000 n
+0000723802 00000 n
+0000008526 00000 n
+0000008578 00000 n
+0000198137 00000 n
+0000723669 00000 n
+0000008633 00000 n
+0000008698 00000 n
+0000206589 00000 n
+0000723590 00000 n
+0000008758 00000 n
+0000008802 00000 n
+0000227810 00000 n
+0000723497 00000 n
+0000008862 00000 n
+0000008901 00000 n
+0000227938 00000 n
+0000723404 00000 n
+0000008961 00000 n
+0000009008 00000 n
+0000228067 00000 n
+0000723311 00000 n
+0000009068 00000 n
+0000009111 00000 n
+0000235196 00000 n
+0000723218 00000 n
+0000009171 00000 n
+0000009210 00000 n
+0000235325 00000 n
+0000723125 00000 n
+0000009270 00000 n
+0000009312 00000 n
+0000242275 00000 n
+0000723032 00000 n
+0000009372 00000 n
+0000009415 00000 n
+0000250260 00000 n
+0000722939 00000 n
+0000009475 00000 n
+0000009518 00000 n
+0000250389 00000 n
+0000722846 00000 n
+0000009578 00000 n
+0000009639 00000 n
+0000254380 00000 n
+0000722753 00000 n
+0000009700 00000 n
+0000009752 00000 n
+0000257620 00000 n
+0000722660 00000 n
+0000009813 00000 n
+0000009866 00000 n
+0000257749 00000 n
+0000722567 00000 n
+0000009927 00000 n
+0000009965 00000 n
+0000261821 00000 n
+0000722474 00000 n
+0000010026 00000 n
+0000010078 00000 n
+0000265032 00000 n
+0000722381 00000 n
+0000010139 00000 n
+0000010183 00000 n
+0000265290 00000 n
+0000722288 00000 n
+0000010244 00000 n
+0000010280 00000 n
+0000274081 00000 n
+0000722195 00000 n
+0000010341 00000 n
+0000010404 00000 n
+0000277408 00000 n
+0000722102 00000 n
+0000010465 00000 n
+0000010515 00000 n
+0000281163 00000 n
+0000722023 00000 n
+0000010576 00000 n
+0000010632 00000 n
+0000284537 00000 n
+0000721930 00000 n
+0000010687 00000 n
+0000010751 00000 n
+0000284666 00000 n
+0000721837 00000 n
+0000010806 00000 n
+0000010883 00000 n
+0000284794 00000 n
+0000721744 00000 n
+0000010938 00000 n
+0000010989 00000 n
+0000289362 00000 n
+0000721651 00000 n
+0000011044 00000 n
+0000011108 00000 n
+0000292729 00000 n
+0000721558 00000 n
+0000011163 00000 n
+0000011220 00000 n
+0000292857 00000 n
+0000721465 00000 n
+0000011275 00000 n
+0000011345 00000 n
+0000292986 00000 n
+0000721372 00000 n
+0000011400 00000 n
+0000011449 00000 n
+0000293115 00000 n
+0000721279 00000 n
+0000011504 00000 n
+0000011566 00000 n
+0000297818 00000 n
+0000721186 00000 n
+0000011621 00000 n
+0000011670 00000 n
+0000301909 00000 n
+0000721068 00000 n
+0000011725 00000 n
+0000011787 00000 n
+0000302038 00000 n
+0000720989 00000 n
+0000011847 00000 n
+0000011886 00000 n
+0000306096 00000 n
+0000720896 00000 n
+0000011946 00000 n
+0000011980 00000 n
+0000311992 00000 n
+0000720803 00000 n
+0000012040 00000 n
+0000012081 00000 n
+0000323134 00000 n
+0000720724 00000 n
+0000012141 00000 n
+0000012193 00000 n
+0000330383 00000 n
+0000720592 00000 n
+0000012242 00000 n
+0000012275 00000 n
+0000330512 00000 n
+0000720474 00000 n
+0000012329 00000 n
+0000012401 00000 n
+0000330640 00000 n
+0000720395 00000 n
+0000012460 00000 n
+0000012504 00000 n
+0000341427 00000 n
+0000720316 00000 n
+0000012563 00000 n
+0000012616 00000 n
+0000341814 00000 n
+0000720223 00000 n
+0000012670 00000 n
+0000012720 00000 n
+0000345189 00000 n
+0000720130 00000 n
+0000012774 00000 n
+0000012812 00000 n
+0000345448 00000 n
+0000720037 00000 n
+0000012866 00000 n
+0000012915 00000 n
+0000348312 00000 n
+0000719905 00000 n
+0000012969 00000 n
+0000013021 00000 n
+0000348440 00000 n
+0000719826 00000 n
+0000013080 00000 n
+0000013132 00000 n
+0000348569 00000 n
+0000719733 00000 n
+0000013191 00000 n
+0000013244 00000 n
+0000348698 00000 n
+0000719654 00000 n
+0000013303 00000 n
+0000013352 00000 n
+0000352344 00000 n
+0000719561 00000 n
+0000013406 00000 n
+0000013486 00000 n
+0000356394 00000 n
+0000719482 00000 n
+0000013540 00000 n
+0000013589 00000 n
+0000356523 00000 n
+0000719364 00000 n
+0000013638 00000 n
+0000013678 00000 n
+0000359826 00000 n
+0000719285 00000 n
+0000013737 00000 n
+0000013784 00000 n
+0000359955 00000 n
+0000719167 00000 n
+0000013838 00000 n
+0000013883 00000 n
+0000360084 00000 n
+0000719088 00000 n
+0000013942 00000 n
+0000014001 00000 n
+0000363183 00000 n
+0000718995 00000 n
+0000014060 00000 n
+0000014124 00000 n
+0000363442 00000 n
+0000718902 00000 n
+0000014183 00000 n
+0000014239 00000 n
+0000366164 00000 n
+0000718823 00000 n
+0000014298 00000 n
+0000014360 00000 n
+0000368398 00000 n
+0000718690 00000 n
+0000014407 00000 n
+0000014459 00000 n
+0000368527 00000 n
+0000718611 00000 n
+0000014508 00000 n
+0000014552 00000 n
+0000372713 00000 n
+0000718479 00000 n
+0000014601 00000 n
+0000014642 00000 n
+0000372842 00000 n
+0000718400 00000 n
+0000014696 00000 n
+0000014744 00000 n
+0000372970 00000 n
+0000718321 00000 n
+0000014798 00000 n
+0000014849 00000 n
+0000373099 00000 n
+0000718242 00000 n
+0000014898 00000 n
+0000014945 00000 n
+0000377366 00000 n
+0000718109 00000 n
+0000014992 00000 n
+0000015029 00000 n
+0000377495 00000 n
+0000717991 00000 n
+0000015078 00000 n
+0000015117 00000 n
+0000377624 00000 n
+0000717926 00000 n
+0000015171 00000 n
+0000015249 00000 n
+0000377753 00000 n
+0000717833 00000 n
+0000015298 00000 n
+0000015365 00000 n
+0000377882 00000 n
+0000717754 00000 n
+0000015414 00000 n
+0000015459 00000 n
+0000381321 00000 n
+0000717621 00000 n
+0000015507 00000 n
+0000015539 00000 n
+0000381450 00000 n
+0000717503 00000 n
+0000015588 00000 n
+0000015627 00000 n
+0000381579 00000 n
+0000717438 00000 n
+0000015681 00000 n
+0000015742 00000 n
+0000385344 00000 n
+0000717306 00000 n
+0000015791 00000 n
+0000015848 00000 n
+0000385473 00000 n
+0000717241 00000 n
+0000015902 00000 n
+0000015951 00000 n
+0000385602 00000 n
+0000717123 00000 n
+0000016000 00000 n
+0000016062 00000 n
+0000385731 00000 n
+0000717044 00000 n
+0000016116 00000 n
+0000016171 00000 n
+0000409752 00000 n
+0000716951 00000 n
+0000016225 00000 n
+0000016266 00000 n
+0000409881 00000 n
+0000716872 00000 n
+0000016320 00000 n
+0000016372 00000 n
+0000412612 00000 n
+0000716752 00000 n
+0000016420 00000 n
+0000016454 00000 n
+0000412741 00000 n
+0000716673 00000 n
+0000016503 00000 n
+0000016530 00000 n
+0000430434 00000 n
+0000716580 00000 n
+0000016579 00000 n
+0000016607 00000 n
+0000437928 00000 n
+0000716487 00000 n
+0000016656 00000 n
+0000016696 00000 n
+0000440723 00000 n
+0000716394 00000 n
+0000016745 00000 n
+0000016788 00000 n
+0000446647 00000 n
+0000716301 00000 n
+0000016837 00000 n
+0000016874 00000 n
+0000453150 00000 n
+0000716208 00000 n
+0000016923 00000 n
+0000016962 00000 n
+0000462862 00000 n
+0000716115 00000 n
+0000017011 00000 n
+0000017050 00000 n
+0000465578 00000 n
+0000716022 00000 n
+0000017099 00000 n
+0000017138 00000 n
+0000475305 00000 n
+0000715929 00000 n
+0000017187 00000 n
+0000017216 00000 n
+0000481121 00000 n
+0000715836 00000 n
+0000017266 00000 n
+0000017299 00000 n
+0000495077 00000 n
+0000715743 00000 n
+0000017349 00000 n
+0000017378 00000 n
+0000498576 00000 n
+0000715650 00000 n
+0000017428 00000 n
+0000017462 00000 n
+0000504687 00000 n
+0000715571 00000 n
+0000017512 00000 n
+0000017549 00000 n
+0000017918 00000 n
+0000018040 00000 n
+0000025869 00000 n
+0000017602 00000 n
+0000025743 00000 n
+0000025806 00000 n
+0000711071 00000 n
+0000685128 00000 n
+0000710897 00000 n
+0000712096 00000 n
+0000020903 00000 n
+0000021120 00000 n
+0000021189 00000 n
+0000021258 00000 n
+0000021326 00000 n
+0000021394 00000 n
+0000021443 00000 n
+0000021490 00000 n
+0000021823 00000 n
+0000021845 00000 n
+0000022013 00000 n
+0000022178 00000 n
+0000022347 00000 n
+0000022526 00000 n
+0000022835 00000 n
+0000022995 00000 n
+0000027233 00000 n
+0000027048 00000 n
+0000025969 00000 n
+0000027170 00000 n
+0000683907 00000 n
+0000657386 00000 n
+0000683733 00000 n
+0000656701 00000 n
+0000654557 00000 n
+0000656537 00000 n
+0000038940 00000 n
+0000030289 00000 n
+0000027318 00000 n
+0000038814 00000 n
+0000038877 00000 n
+0000030823 00000 n
+0000030977 00000 n
+0000031134 00000 n
+0000031291 00000 n
+0000031447 00000 n
+0000031604 00000 n
+0000031766 00000 n
+0000031927 00000 n
+0000032088 00000 n
+0000032250 00000 n
+0000032417 00000 n
+0000032584 00000 n
+0000032749 00000 n
+0000032911 00000 n
+0000033077 00000 n
+0000033238 00000 n
+0000033393 00000 n
+0000033550 00000 n
+0000033706 00000 n
+0000033863 00000 n
+0000034020 00000 n
+0000034177 00000 n
+0000034331 00000 n
+0000034487 00000 n
+0000034649 00000 n
+0000034811 00000 n
+0000034967 00000 n
+0000035124 00000 n
+0000035286 00000 n
+0000035453 00000 n
+0000035619 00000 n
+0000035780 00000 n
+0000035935 00000 n
+0000036092 00000 n
+0000036249 00000 n
+0000036411 00000 n
+0000036568 00000 n
+0000036725 00000 n
+0000036887 00000 n
+0000037044 00000 n
+0000037206 00000 n
+0000037373 00000 n
+0000037539 00000 n
+0000037701 00000 n
+0000037863 00000 n
+0000038025 00000 n
+0000038187 00000 n
+0000038349 00000 n
+0000038504 00000 n
+0000038659 00000 n
+0000052318 00000 n
+0000042272 00000 n
+0000039025 00000 n
+0000052255 00000 n
+0000654006 00000 n
+0000636925 00000 n
+0000653822 00000 n
+0000042862 00000 n
+0000043025 00000 n
+0000043187 00000 n
+0000043350 00000 n
+0000043508 00000 n
+0000043671 00000 n
+0000043834 00000 n
+0000043989 00000 n
+0000044147 00000 n
+0000044305 00000 n
+0000044461 00000 n
+0000044619 00000 n
+0000044782 00000 n
+0000044950 00000 n
+0000045118 00000 n
+0000045281 00000 n
+0000045449 00000 n
+0000045617 00000 n
+0000045775 00000 n
+0000045938 00000 n
+0000046101 00000 n
+0000046263 00000 n
+0000046425 00000 n
+0000046588 00000 n
+0000046750 00000 n
+0000046912 00000 n
+0000047075 00000 n
+0000047238 00000 n
+0000047401 00000 n
+0000047570 00000 n
+0000047739 00000 n
+0000047903 00000 n
+0000048066 00000 n
+0000048230 00000 n
+0000048394 00000 n
+0000048557 00000 n
+0000048721 00000 n
+0000048890 00000 n
+0000049059 00000 n
+0000049228 00000 n
+0000049397 00000 n
+0000049566 00000 n
+0000049735 00000 n
+0000049904 00000 n
+0000050073 00000 n
+0000050242 00000 n
+0000050412 00000 n
+0000050582 00000 n
+0000050752 00000 n
+0000050922 00000 n
+0000051092 00000 n
+0000051262 00000 n
+0000051432 00000 n
+0000051601 00000 n
+0000051771 00000 n
+0000051932 00000 n
+0000052093 00000 n
+0000065459 00000 n
+0000055941 00000 n
+0000052416 00000 n
+0000065396 00000 n
+0000056515 00000 n
+0000056678 00000 n
+0000056841 00000 n
+0000057004 00000 n
+0000057167 00000 n
+0000057330 00000 n
+0000057493 00000 n
+0000057656 00000 n
+0000057824 00000 n
+0000057991 00000 n
+0000058159 00000 n
+0000058327 00000 n
+0000058484 00000 n
+0000058646 00000 n
+0000058811 00000 n
+0000058977 00000 n
+0000059139 00000 n
+0000059301 00000 n
+0000059463 00000 n
+0000059625 00000 n
+0000059792 00000 n
+0000059959 00000 n
+0000060126 00000 n
+0000060288 00000 n
+0000060450 00000 n
+0000060607 00000 n
+0000060774 00000 n
+0000060936 00000 n
+0000061103 00000 n
+0000061270 00000 n
+0000636036 00000 n
+0000614704 00000 n
+0000635862 00000 n
+0000061437 00000 n
+0000061604 00000 n
+0000061759 00000 n
+0000061916 00000 n
+0000062073 00000 n
+0000062235 00000 n
+0000062396 00000 n
+0000062552 00000 n
+0000062707 00000 n
+0000062864 00000 n
+0000063026 00000 n
+0000063183 00000 n
+0000063340 00000 n
+0000063496 00000 n
+0000063652 00000 n
+0000063813 00000 n
+0000063970 00000 n
+0000064132 00000 n
+0000064289 00000 n
+0000064451 00000 n
+0000064613 00000 n
+0000064775 00000 n
+0000064931 00000 n
+0000065086 00000 n
+0000065241 00000 n
+0000068260 00000 n
+0000066412 00000 n
+0000065570 00000 n
+0000068197 00000 n
+0000066626 00000 n
+0000066783 00000 n
+0000066940 00000 n
+0000067096 00000 n
+0000067253 00000 n
+0000067409 00000 n
+0000067566 00000 n
+0000067724 00000 n
+0000613738 00000 n
+0000593771 00000 n
+0000613565 00000 n
+0000067882 00000 n
+0000068039 00000 n
+0000071445 00000 n
+0000070635 00000 n
+0000068358 00000 n
+0000070757 00000 n
+0000070881 00000 n
+0000071006 00000 n
+0000071131 00000 n
+0000071256 00000 n
+0000071319 00000 n
+0000071382 00000 n
+0000592977 00000 n
+0000574660 00000 n
+0000592804 00000 n
+0000712214 00000 n
+0000076016 00000 n
+0000074836 00000 n
+0000071569 00000 n
+0000075330 00000 n
+0000075393 00000 n
+0000075456 00000 n
+0000075580 00000 n
+0000075705 00000 n
+0000075830 00000 n
+0000074986 00000 n
+0000075179 00000 n
+0000075953 00000 n
+0000330576 00000 n
+0000385795 00000 n
+0000080671 00000 n
+0000079635 00000 n
+0000076140 00000 n
+0000080108 00000 n
+0000080233 00000 n
+0000079785 00000 n
+0000079947 00000 n
+0000080358 00000 n
+0000080483 00000 n
+0000080608 00000 n
+0000096564 00000 n
+0000083893 00000 n
+0000083333 00000 n
+0000080795 00000 n
+0000083455 00000 n
+0000083580 00000 n
+0000083705 00000 n
+0000083830 00000 n
+0000087320 00000 n
+0000086179 00000 n
+0000084004 00000 n
+0000086633 00000 n
+0000086758 00000 n
+0000086883 00000 n
+0000087008 00000 n
+0000087133 00000 n
+0000086329 00000 n
+0000086481 00000 n
+0000087257 00000 n
+0000281227 00000 n
+0000088400 00000 n
+0000088090 00000 n
+0000087405 00000 n
+0000088212 00000 n
+0000088337 00000 n
+0000090485 00000 n
+0000089800 00000 n
+0000088498 00000 n
+0000089922 00000 n
+0000090047 00000 n
+0000090171 00000 n
+0000090296 00000 n
+0000090422 00000 n
+0000712332 00000 n
+0000093412 00000 n
+0000092524 00000 n
+0000090583 00000 n
+0000092831 00000 n
+0000092960 00000 n
+0000093025 00000 n
+0000093090 00000 n
+0000092670 00000 n
+0000093219 00000 n
+0000093348 00000 n
+0000265096 00000 n
+0000096757 00000 n
+0000096310 00000 n
+0000093524 00000 n
+0000096435 00000 n
+0000573985 00000 n
+0000561996 00000 n
+0000573806 00000 n
+0000096692 00000 n
+0000100548 00000 n
+0000100358 00000 n
+0000096883 00000 n
+0000100483 00000 n
+0000561455 00000 n
+0000551709 00000 n
+0000561276 00000 n
+0000105074 00000 n
+0000104676 00000 n
+0000100714 00000 n
+0000105009 00000 n
+0000104822 00000 n
+0000171091 00000 n
+0000107419 00000 n
+0000106970 00000 n
+0000105213 00000 n
+0000107095 00000 n
+0000107224 00000 n
+0000107289 00000 n
+0000107354 00000 n
+0000110116 00000 n
+0000112663 00000 n
+0000109960 00000 n
+0000107544 00000 n
+0000112082 00000 n
+0000112211 00000 n
+0000112340 00000 n
+0000111759 00000 n
+0000111921 00000 n
+0000550839 00000 n
+0000541419 00000 n
+0000550665 00000 n
+0000540855 00000 n
+0000531769 00000 n
+0000540680 00000 n
+0000112469 00000 n
+0000112598 00000 n
+0000712455 00000 n
+0000111588 00000 n
+0000111646 00000 n
+0000111736 00000 n
+0000206653 00000 n
+0000242339 00000 n
+0000117183 00000 n
+0000116248 00000 n
+0000112819 00000 n
+0000116731 00000 n
+0000116860 00000 n
+0000116404 00000 n
+0000116569 00000 n
+0000116989 00000 n
+0000117118 00000 n
+0000389821 00000 n
+0000120797 00000 n
+0000120417 00000 n
+0000117335 00000 n
+0000120732 00000 n
+0000120564 00000 n
+0000122047 00000 n
+0000121856 00000 n
+0000120922 00000 n
+0000121982 00000 n
+0000124750 00000 n
+0000124173 00000 n
+0000122146 00000 n
+0000124299 00000 n
+0000124428 00000 n
+0000124557 00000 n
+0000124686 00000 n
+0000127972 00000 n
+0000127265 00000 n
+0000124888 00000 n
+0000127391 00000 n
+0000127520 00000 n
+0000127649 00000 n
+0000127778 00000 n
+0000127907 00000 n
+0000132261 00000 n
+0000131363 00000 n
+0000128097 00000 n
+0000131681 00000 n
+0000131810 00000 n
+0000131510 00000 n
+0000131939 00000 n
+0000132068 00000 n
+0000132196 00000 n
+0000712580 00000 n
+0000323198 00000 n
+0000136297 00000 n
+0000135719 00000 n
+0000132386 00000 n
+0000135845 00000 n
+0000135974 00000 n
+0000136103 00000 n
+0000136232 00000 n
+0000139738 00000 n
+0000139418 00000 n
+0000136435 00000 n
+0000139544 00000 n
+0000139673 00000 n
+0000143070 00000 n
+0000142311 00000 n
+0000139850 00000 n
+0000142619 00000 n
+0000142748 00000 n
+0000142458 00000 n
+0000142877 00000 n
+0000143005 00000 n
+0000385537 00000 n
+0000145810 00000 n
+0000145232 00000 n
+0000143238 00000 n
+0000145358 00000 n
+0000145487 00000 n
+0000145616 00000 n
+0000145745 00000 n
+0000146250 00000 n
+0000146059 00000 n
+0000145909 00000 n
+0000146185 00000 n
+0000150252 00000 n
+0000149486 00000 n
+0000146292 00000 n
+0000149800 00000 n
+0000149929 00000 n
+0000150057 00000 n
+0000150122 00000 n
+0000150187 00000 n
+0000149633 00000 n
+0000712705 00000 n
+0000154748 00000 n
+0000154940 00000 n
+0000154493 00000 n
+0000150351 00000 n
+0000154619 00000 n
+0000154875 00000 n
+0000158787 00000 n
+0000158210 00000 n
+0000155065 00000 n
+0000158336 00000 n
+0000158464 00000 n
+0000158593 00000 n
+0000158722 00000 n
+0000161394 00000 n
+0000162773 00000 n
+0000161268 00000 n
+0000158925 00000 n
+0000162320 00000 n
+0000162449 00000 n
+0000162578 00000 n
+0000162643 00000 n
+0000162708 00000 n
+0000166049 00000 n
+0000165343 00000 n
+0000162928 00000 n
+0000165469 00000 n
+0000165597 00000 n
+0000165726 00000 n
+0000165790 00000 n
+0000165855 00000 n
+0000165984 00000 n
+0000171284 00000 n
+0000170496 00000 n
+0000166161 00000 n
+0000170962 00000 n
+0000170652 00000 n
+0000170803 00000 n
+0000171220 00000 n
+0000510397 00000 n
+0000175146 00000 n
+0000173875 00000 n
+0000171422 00000 n
+0000174565 00000 n
+0000174694 00000 n
+0000174823 00000 n
+0000174952 00000 n
+0000174040 00000 n
+0000174192 00000 n
+0000174378 00000 n
+0000175081 00000 n
+0000712830 00000 n
+0000179291 00000 n
+0000178842 00000 n
+0000175272 00000 n
+0000178968 00000 n
+0000179097 00000 n
+0000179226 00000 n
+0000183212 00000 n
+0000182833 00000 n
+0000179416 00000 n
+0000183147 00000 n
+0000182980 00000 n
+0000186051 00000 n
+0000186245 00000 n
+0000185796 00000 n
+0000183324 00000 n
+0000185922 00000 n
+0000186116 00000 n
+0000186181 00000 n
+0000189675 00000 n
+0000189484 00000 n
+0000186357 00000 n
+0000189610 00000 n
+0000192997 00000 n
+0000191830 00000 n
+0000189787 00000 n
+0000192290 00000 n
+0000192419 00000 n
+0000192548 00000 n
+0000191986 00000 n
+0000192140 00000 n
+0000192676 00000 n
+0000192804 00000 n
+0000192932 00000 n
+0000194483 00000 n
+0000194292 00000 n
+0000193109 00000 n
+0000194418 00000 n
+0000712955 00000 n
+0000196016 00000 n
+0000195825 00000 n
+0000194582 00000 n
+0000195951 00000 n
+0000198266 00000 n
+0000197946 00000 n
+0000196115 00000 n
+0000198072 00000 n
+0000198201 00000 n
+0000202789 00000 n
+0000202420 00000 n
+0000198378 00000 n
+0000202724 00000 n
+0000202567 00000 n
+0000359890 00000 n
+0000206718 00000 n
+0000206398 00000 n
+0000202927 00000 n
+0000206524 00000 n
+0000210794 00000 n
+0000210300 00000 n
+0000206843 00000 n
+0000210599 00000 n
+0000210664 00000 n
+0000210729 00000 n
+0000210447 00000 n
+0000215794 00000 n
+0000214662 00000 n
+0000210919 00000 n
+0000215729 00000 n
+0000214845 00000 n
+0000215002 00000 n
+0000215186 00000 n
+0000215359 00000 n
+0000215544 00000 n
+0000713080 00000 n
+0000289426 00000 n
+0000220074 00000 n
+0000219883 00000 n
+0000215975 00000 n
+0000220009 00000 n
+0000223936 00000 n
+0000223745 00000 n
+0000220199 00000 n
+0000223871 00000 n
+0000228196 00000 n
+0000227253 00000 n
+0000224048 00000 n
+0000227745 00000 n
+0000227873 00000 n
+0000227409 00000 n
+0000228002 00000 n
+0000228131 00000 n
+0000227579 00000 n
+0000297882 00000 n
+0000232129 00000 n
+0000231567 00000 n
+0000228365 00000 n
+0000232064 00000 n
+0000231723 00000 n
+0000231893 00000 n
+0000373163 00000 n
+0000235454 00000 n
+0000235005 00000 n
+0000232298 00000 n
+0000235131 00000 n
+0000235260 00000 n
+0000235389 00000 n
+0000238850 00000 n
+0000238659 00000 n
+0000235579 00000 n
+0000238785 00000 n
+0000713205 00000 n
+0000242404 00000 n
+0000242084 00000 n
+0000239019 00000 n
+0000242210 00000 n
+0000246107 00000 n
+0000245916 00000 n
+0000242560 00000 n
+0000246042 00000 n
+0000250518 00000 n
+0000249704 00000 n
+0000246276 00000 n
+0000250195 00000 n
+0000250324 00000 n
+0000249860 00000 n
+0000250453 00000 n
+0000250021 00000 n
+0000254509 00000 n
+0000254014 00000 n
+0000250673 00000 n
+0000254315 00000 n
+0000254444 00000 n
+0000254161 00000 n
+0000257878 00000 n
+0000257429 00000 n
+0000254634 00000 n
+0000257555 00000 n
+0000257684 00000 n
+0000257813 00000 n
+0000261950 00000 n
+0000261283 00000 n
+0000258033 00000 n
+0000261756 00000 n
+0000261885 00000 n
+0000261439 00000 n
+0000261601 00000 n
+0000713330 00000 n
+0000265418 00000 n
+0000264650 00000 n
+0000262119 00000 n
+0000264967 00000 n
+0000264797 00000 n
+0000265160 00000 n
+0000265225 00000 n
+0000265354 00000 n
+0000269455 00000 n
+0000269083 00000 n
+0000265601 00000 n
+0000269390 00000 n
+0000269230 00000 n
+0000274209 00000 n
+0000273530 00000 n
+0000269623 00000 n
+0000274016 00000 n
+0000273686 00000 n
+0000531414 00000 n
+0000529417 00000 n
+0000531249 00000 n
+0000274144 00000 n
+0000273849 00000 n
+0000356458 00000 n
+0000293050 00000 n
+0000277537 00000 n
+0000277217 00000 n
+0000274335 00000 n
+0000277343 00000 n
+0000277472 00000 n
+0000281291 00000 n
+0000280972 00000 n
+0000277662 00000 n
+0000281098 00000 n
+0000284923 00000 n
+0000284346 00000 n
+0000281433 00000 n
+0000284472 00000 n
+0000284601 00000 n
+0000284730 00000 n
+0000284858 00000 n
+0000713455 00000 n
+0000289491 00000 n
+0000289000 00000 n
+0000285035 00000 n
+0000289297 00000 n
+0000289147 00000 n
+0000293243 00000 n
+0000292193 00000 n
+0000289603 00000 n
+0000292664 00000 n
+0000292349 00000 n
+0000292792 00000 n
+0000292921 00000 n
+0000292511 00000 n
+0000293179 00000 n
+0000296310 00000 n
+0000296119 00000 n
+0000293355 00000 n
+0000296245 00000 n
+0000297947 00000 n
+0000297627 00000 n
+0000296422 00000 n
+0000297753 00000 n
+0000299421 00000 n
+0000299230 00000 n
+0000298059 00000 n
+0000299356 00000 n
+0000302297 00000 n
+0000301718 00000 n
+0000299520 00000 n
+0000301844 00000 n
+0000301973 00000 n
+0000302102 00000 n
+0000302167 00000 n
+0000302232 00000 n
+0000713580 00000 n
+0000306225 00000 n
+0000305905 00000 n
+0000302409 00000 n
+0000306031 00000 n
+0000306160 00000 n
+0000312121 00000 n
+0000309387 00000 n
+0000306337 00000 n
+0000311927 00000 n
+0000312056 00000 n
+0000309651 00000 n
+0000309813 00000 n
+0000309975 00000 n
+0000310136 00000 n
+0000310296 00000 n
+0000310458 00000 n
+0000310629 00000 n
+0000310791 00000 n
+0000310953 00000 n
+0000311114 00000 n
+0000311275 00000 n
+0000311438 00000 n
+0000311601 00000 n
+0000311764 00000 n
+0000317105 00000 n
+0000315364 00000 n
+0000312233 00000 n
+0000317040 00000 n
+0000315583 00000 n
+0000315744 00000 n
+0000315913 00000 n
+0000316075 00000 n
+0000316237 00000 n
+0000316399 00000 n
+0000316560 00000 n
+0000316723 00000 n
+0000316877 00000 n
+0000323263 00000 n
+0000320266 00000 n
+0000317230 00000 n
+0000323069 00000 n
+0000320548 00000 n
+0000320702 00000 n
+0000320856 00000 n
+0000321010 00000 n
+0000321164 00000 n
+0000321325 00000 n
+0000321487 00000 n
+0000321647 00000 n
+0000321807 00000 n
+0000321969 00000 n
+0000322129 00000 n
+0000322288 00000 n
+0000322439 00000 n
+0000322602 00000 n
+0000322753 00000 n
+0000322915 00000 n
+0000326791 00000 n
+0000326470 00000 n
+0000323375 00000 n
+0000326596 00000 n
+0000326661 00000 n
+0000326726 00000 n
+0000331027 00000 n
+0000329830 00000 n
+0000326960 00000 n
+0000330318 00000 n
+0000330447 00000 n
+0000330704 00000 n
+0000329986 00000 n
+0000330156 00000 n
+0000330769 00000 n
+0000330834 00000 n
+0000330899 00000 n
+0000330963 00000 n
+0000713705 00000 n
+0000334374 00000 n
+0000334183 00000 n
+0000331209 00000 n
+0000334309 00000 n
+0000338114 00000 n
+0000337793 00000 n
+0000334460 00000 n
+0000337919 00000 n
+0000337984 00000 n
+0000338049 00000 n
+0000341943 00000 n
+0000341236 00000 n
+0000338226 00000 n
+0000341362 00000 n
+0000341491 00000 n
+0000341554 00000 n
+0000341619 00000 n
+0000341684 00000 n
+0000341749 00000 n
+0000341878 00000 n
+0000345707 00000 n
+0000344868 00000 n
+0000342055 00000 n
+0000344994 00000 n
+0000345059 00000 n
+0000345124 00000 n
+0000345253 00000 n
+0000345318 00000 n
+0000345383 00000 n
+0000345512 00000 n
+0000345577 00000 n
+0000345642 00000 n
+0000348826 00000 n
+0000348121 00000 n
+0000345832 00000 n
+0000348247 00000 n
+0000348375 00000 n
+0000348504 00000 n
+0000348633 00000 n
+0000348762 00000 n
+0000352603 00000 n
+0000352153 00000 n
+0000349023 00000 n
+0000352279 00000 n
+0000352408 00000 n
+0000352473 00000 n
+0000352538 00000 n
+0000713830 00000 n
+0000356782 00000 n
+0000356024 00000 n
+0000352742 00000 n
+0000356329 00000 n
+0000356587 00000 n
+0000356652 00000 n
+0000356717 00000 n
+0000356171 00000 n
+0000360343 00000 n
+0000359635 00000 n
+0000356907 00000 n
+0000359761 00000 n
+0000360019 00000 n
+0000360148 00000 n
+0000360213 00000 n
+0000360278 00000 n
+0000363634 00000 n
+0000362992 00000 n
+0000360455 00000 n
+0000363118 00000 n
+0000363247 00000 n
+0000363312 00000 n
+0000363377 00000 n
+0000363506 00000 n
+0000363570 00000 n
+0000366293 00000 n
+0000365908 00000 n
+0000363746 00000 n
+0000366034 00000 n
+0000366099 00000 n
+0000529136 00000 n
+0000521853 00000 n
+0000528956 00000 n
+0000366228 00000 n
+0000366760 00000 n
+0000366569 00000 n
+0000366419 00000 n
+0000366695 00000 n
+0000368655 00000 n
+0000368207 00000 n
+0000366802 00000 n
+0000368333 00000 n
+0000368462 00000 n
+0000368591 00000 n
+0000713955 00000 n
+0000373228 00000 n
+0000372285 00000 n
+0000368767 00000 n
+0000372648 00000 n
+0000521532 00000 n
+0000512319 00000 n
+0000521346 00000 n
+0000372432 00000 n
+0000372777 00000 n
+0000372905 00000 n
+0000373034 00000 n
+0000374270 00000 n
+0000374079 00000 n
+0000373465 00000 n
+0000374205 00000 n
+0000374697 00000 n
+0000374506 00000 n
+0000374356 00000 n
+0000374632 00000 n
+0000378010 00000 n
+0000376784 00000 n
+0000374739 00000 n
+0000377301 00000 n
+0000377430 00000 n
+0000377559 00000 n
+0000377688 00000 n
+0000377817 00000 n
+0000377946 00000 n
+0000376940 00000 n
+0000377112 00000 n
+0000378464 00000 n
+0000378273 00000 n
+0000378123 00000 n
+0000378399 00000 n
+0000381708 00000 n
+0000381130 00000 n
+0000378506 00000 n
+0000381256 00000 n
+0000381385 00000 n
+0000381514 00000 n
+0000381643 00000 n
+0000714080 00000 n
+0000385987 00000 n
+0000384768 00000 n
+0000381794 00000 n
+0000385279 00000 n
+0000385408 00000 n
+0000385666 00000 n
+0000384924 00000 n
+0000385103 00000 n
+0000385859 00000 n
+0000385923 00000 n
+0000392873 00000 n
+0000389045 00000 n
+0000386140 00000 n
+0000389171 00000 n
+0000389236 00000 n
+0000389301 00000 n
+0000389366 00000 n
+0000389431 00000 n
+0000389496 00000 n
+0000389561 00000 n
+0000389626 00000 n
+0000389691 00000 n
+0000389756 00000 n
+0000389886 00000 n
+0000389951 00000 n
+0000390016 00000 n
+0000390081 00000 n
+0000390146 00000 n
+0000390211 00000 n
+0000390276 00000 n
+0000390341 00000 n
+0000390406 00000 n
+0000390471 00000 n
+0000390536 00000 n
+0000390601 00000 n
+0000390666 00000 n
+0000390731 00000 n
+0000390796 00000 n
+0000390861 00000 n
+0000390926 00000 n
+0000390991 00000 n
+0000391056 00000 n
+0000391121 00000 n
+0000391186 00000 n
+0000391251 00000 n
+0000391316 00000 n
+0000391381 00000 n
+0000391445 00000 n
+0000391510 00000 n
+0000391575 00000 n
+0000391640 00000 n
+0000391705 00000 n
+0000391770 00000 n
+0000391835 00000 n
+0000391900 00000 n
+0000391965 00000 n
+0000392030 00000 n
+0000392095 00000 n
+0000392160 00000 n
+0000392225 00000 n
+0000392290 00000 n
+0000392355 00000 n
+0000392420 00000 n
+0000392485 00000 n
+0000392550 00000 n
+0000392615 00000 n
+0000392680 00000 n
+0000392745 00000 n
+0000392809 00000 n
+0000399519 00000 n
+0000395955 00000 n
+0000392985 00000 n
+0000396081 00000 n
+0000396146 00000 n
+0000396211 00000 n
+0000396276 00000 n
+0000396341 00000 n
+0000396406 00000 n
+0000396471 00000 n
+0000396536 00000 n
+0000396601 00000 n
+0000396666 00000 n
+0000396731 00000 n
+0000396796 00000 n
+0000396860 00000 n
+0000396925 00000 n
+0000396990 00000 n
+0000397055 00000 n
+0000397120 00000 n
+0000397185 00000 n
+0000397250 00000 n
+0000397315 00000 n
+0000397380 00000 n
+0000397445 00000 n
+0000397510 00000 n
+0000397575 00000 n
+0000397639 00000 n
+0000397704 00000 n
+0000397769 00000 n
+0000397834 00000 n
+0000397899 00000 n
+0000397964 00000 n
+0000398029 00000 n
+0000398094 00000 n
+0000398159 00000 n
+0000398224 00000 n
+0000398289 00000 n
+0000398354 00000 n
+0000398419 00000 n
+0000398484 00000 n
+0000398549 00000 n
+0000398614 00000 n
+0000398678 00000 n
+0000398742 00000 n
+0000398806 00000 n
+0000398871 00000 n
+0000398936 00000 n
+0000399001 00000 n
+0000399066 00000 n
+0000399131 00000 n
+0000399196 00000 n
+0000399261 00000 n
+0000399326 00000 n
+0000399391 00000 n
+0000399455 00000 n
+0000405692 00000 n
+0000402254 00000 n
+0000399631 00000 n
+0000402380 00000 n
+0000402445 00000 n
+0000402510 00000 n
+0000402575 00000 n
+0000402640 00000 n
+0000402705 00000 n
+0000402770 00000 n
+0000402835 00000 n
+0000402900 00000 n
+0000402965 00000 n
+0000403030 00000 n
+0000403095 00000 n
+0000403160 00000 n
+0000403225 00000 n
+0000403290 00000 n
+0000403355 00000 n
+0000403420 00000 n
+0000403485 00000 n
+0000403550 00000 n
+0000403615 00000 n
+0000403680 00000 n
+0000403745 00000 n
+0000403810 00000 n
+0000403875 00000 n
+0000403940 00000 n
+0000404005 00000 n
+0000404070 00000 n
+0000404135 00000 n
+0000404200 00000 n
+0000404265 00000 n
+0000404330 00000 n
+0000404395 00000 n
+0000404460 00000 n
+0000404525 00000 n
+0000404589 00000 n
+0000404654 00000 n
+0000404719 00000 n
+0000404784 00000 n
+0000404849 00000 n
+0000404914 00000 n
+0000404979 00000 n
+0000405044 00000 n
+0000405109 00000 n
+0000405174 00000 n
+0000405239 00000 n
+0000405304 00000 n
+0000405369 00000 n
+0000405434 00000 n
+0000405499 00000 n
+0000405564 00000 n
+0000405628 00000 n
+0000410270 00000 n
+0000408006 00000 n
+0000405804 00000 n
+0000408132 00000 n
+0000408197 00000 n
+0000408262 00000 n
+0000408327 00000 n
+0000408392 00000 n
+0000408457 00000 n
+0000408522 00000 n
+0000408587 00000 n
+0000408652 00000 n
+0000408717 00000 n
+0000408782 00000 n
+0000408847 00000 n
+0000408912 00000 n
+0000408977 00000 n
+0000409039 00000 n
+0000409103 00000 n
+0000409168 00000 n
+0000409232 00000 n
+0000409297 00000 n
+0000409362 00000 n
+0000409427 00000 n
+0000409492 00000 n
+0000409557 00000 n
+0000409622 00000 n
+0000409687 00000 n
+0000409816 00000 n
+0000409945 00000 n
+0000410010 00000 n
+0000410075 00000 n
+0000410140 00000 n
+0000410205 00000 n
+0000413065 00000 n
+0000412421 00000 n
+0000410395 00000 n
+0000412547 00000 n
+0000412676 00000 n
+0000412805 00000 n
+0000412870 00000 n
+0000412935 00000 n
+0000413000 00000 n
+0000714205 00000 n
+0000417403 00000 n
+0000417083 00000 n
+0000413178 00000 n
+0000417209 00000 n
+0000417274 00000 n
+0000417339 00000 n
+0000420874 00000 n
+0000420618 00000 n
+0000417556 00000 n
+0000420744 00000 n
+0000420809 00000 n
+0000424122 00000 n
+0000423931 00000 n
+0000421013 00000 n
+0000424057 00000 n
+0000427851 00000 n
+0000427595 00000 n
+0000424248 00000 n
+0000427721 00000 n
+0000427786 00000 n
+0000430691 00000 n
+0000429983 00000 n
+0000427990 00000 n
+0000430109 00000 n
+0000430174 00000 n
+0000430239 00000 n
+0000430304 00000 n
+0000430369 00000 n
+0000430498 00000 n
+0000430563 00000 n
+0000430627 00000 n
+0000435364 00000 n
+0000435108 00000 n
+0000430830 00000 n
+0000435234 00000 n
+0000435299 00000 n
+0000714330 00000 n
+0000438315 00000 n
+0000437542 00000 n
+0000435490 00000 n
+0000437668 00000 n
+0000437733 00000 n
+0000437798 00000 n
+0000437863 00000 n
+0000437992 00000 n
+0000438057 00000 n
+0000438120 00000 n
+0000438185 00000 n
+0000438250 00000 n
+0000440916 00000 n
+0000440207 00000 n
+0000438468 00000 n
+0000440333 00000 n
+0000440398 00000 n
+0000440463 00000 n
+0000440528 00000 n
+0000440593 00000 n
+0000440658 00000 n
+0000440787 00000 n
+0000440852 00000 n
+0000443940 00000 n
+0000443555 00000 n
+0000441068 00000 n
+0000443681 00000 n
+0000443746 00000 n
+0000443810 00000 n
+0000443875 00000 n
+0000447035 00000 n
+0000446261 00000 n
+0000444080 00000 n
+0000446387 00000 n
+0000446452 00000 n
+0000446517 00000 n
+0000446582 00000 n
+0000446711 00000 n
+0000446776 00000 n
+0000446841 00000 n
+0000446905 00000 n
+0000446970 00000 n
+0000450308 00000 n
+0000450117 00000 n
+0000447201 00000 n
+0000450243 00000 n
+0000453409 00000 n
+0000452699 00000 n
+0000450434 00000 n
+0000452825 00000 n
+0000452890 00000 n
+0000452955 00000 n
+0000453020 00000 n
+0000453085 00000 n
+0000453214 00000 n
+0000453279 00000 n
+0000453344 00000 n
+0000714455 00000 n
+0000457067 00000 n
+0000456748 00000 n
+0000453574 00000 n
+0000456874 00000 n
+0000456939 00000 n
+0000457003 00000 n
+0000460443 00000 n
+0000460252 00000 n
+0000457193 00000 n
+0000460378 00000 n
+0000463120 00000 n
+0000462477 00000 n
+0000460583 00000 n
+0000462603 00000 n
+0000462668 00000 n
+0000462732 00000 n
+0000462797 00000 n
+0000462926 00000 n
+0000462991 00000 n
+0000463056 00000 n
+0000465837 00000 n
+0000465063 00000 n
+0000463272 00000 n
+0000465189 00000 n
+0000465254 00000 n
+0000465318 00000 n
+0000465383 00000 n
+0000465448 00000 n
+0000465513 00000 n
+0000465642 00000 n
+0000465707 00000 n
+0000465772 00000 n
+0000469228 00000 n
+0000468907 00000 n
+0000465990 00000 n
+0000469033 00000 n
+0000469098 00000 n
+0000469163 00000 n
+0000472297 00000 n
+0000471912 00000 n
+0000469341 00000 n
+0000472038 00000 n
+0000472103 00000 n
+0000472168 00000 n
+0000472233 00000 n
+0000714580 00000 n
+0000475693 00000 n
+0000475114 00000 n
+0000472436 00000 n
+0000475240 00000 n
+0000475369 00000 n
+0000475434 00000 n
+0000475499 00000 n
+0000475564 00000 n
+0000475629 00000 n
+0000478674 00000 n
+0000478483 00000 n
+0000475833 00000 n
+0000478609 00000 n
+0000481314 00000 n
+0000480605 00000 n
+0000478885 00000 n
+0000480731 00000 n
+0000480796 00000 n
+0000480861 00000 n
+0000480926 00000 n
+0000480991 00000 n
+0000481056 00000 n
+0000481185 00000 n
+0000481250 00000 n
+0000485767 00000 n
+0000485446 00000 n
+0000481510 00000 n
+0000485572 00000 n
+0000485637 00000 n
+0000485702 00000 n
+0000489361 00000 n
+0000489106 00000 n
+0000485893 00000 n
+0000489232 00000 n
+0000489297 00000 n
+0000492296 00000 n
+0000492040 00000 n
+0000489487 00000 n
+0000492166 00000 n
+0000492231 00000 n
+0000714705 00000 n
+0000495466 00000 n
+0000494691 00000 n
+0000492422 00000 n
+0000494817 00000 n
+0000494882 00000 n
+0000494947 00000 n
+0000495012 00000 n
+0000495141 00000 n
+0000495206 00000 n
+0000495271 00000 n
+0000495336 00000 n
+0000495401 00000 n
+0000498834 00000 n
+0000498190 00000 n
+0000495632 00000 n
+0000498316 00000 n
+0000498381 00000 n
+0000498446 00000 n
+0000498511 00000 n
+0000498640 00000 n
+0000498705 00000 n
+0000498770 00000 n
+0000502306 00000 n
+0000501985 00000 n
+0000499000 00000 n
+0000502111 00000 n
+0000502176 00000 n
+0000502241 00000 n
+0000504879 00000 n
+0000504301 00000 n
+0000502432 00000 n
+0000504427 00000 n
+0000504492 00000 n
+0000504557 00000 n
+0000504622 00000 n
+0000504751 00000 n
+0000504815 00000 n
+0000508675 00000 n
+0000508290 00000 n
+0000505017 00000 n
+0000508416 00000 n
+0000508481 00000 n
+0000508546 00000 n
+0000508611 00000 n
+0000510245 00000 n
+0000509861 00000 n
+0000508815 00000 n
+0000509987 00000 n
+0000510052 00000 n
+0000510115 00000 n
+0000510180 00000 n
+0000714830 00000 n
+0000510430 00000 n
+0000521774 00000 n
+0000529362 00000 n
+0000531661 00000 n
+0000531630 00000 n
+0000541154 00000 n
+0000551267 00000 n
+0000561743 00000 n
+0000574367 00000 n
+0000593432 00000 n
+0000614319 00000 n
+0000636463 00000 n
+0000654358 00000 n
+0000657188 00000 n
+0000656958 00000 n
+0000684495 00000 n
+0000711606 00000 n
+0000714910 00000 n
+0000715033 00000 n
+0000715159 00000 n
+0000715285 00000 n
+0000715402 00000 n
+0000715494 00000 n
+0000731830 00000 n
+0000750703 00000 n
+0000750744 00000 n
+0000750784 00000 n
+0000750918 00000 n
+trailer
+<<
+/Size 2120
+/Root 2118 0 R
+/Info 2119 0 R
+/ID [<E7B0BB00F44154DCC90012FC495A8314> <E7B0BB00F44154DCC90012FC495A8314>]
+>>
+startxref
+751176
+%%EOF
diff --git a/doc/arm/Makefile.in b/doc/arm/Makefile.in
new file mode 100644
index 0000000..d727da9
--- /dev/null
+++ b/doc/arm/Makefile.in
@@ -0,0 +1,67 @@
+# Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2001, 2002 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.20 2007/06/18 23:47:33 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_RULES@
+
+@BIND9_VERSION@
+
+MANOBJS = Bv9ARM.html
+
+PDFOBJS = Bv9ARM.pdf
+
+doc man:: ${MANOBJS} ${PDFOBJS}
+
+clean::
+ rm -f Bv9ARM.aux Bv9ARM.brf Bv9ARM.glo Bv9ARM.idx Bv9ARM.toc
+ rm -f Bv9ARM.log Bv9ARM.out Bv9ARM.tex Bv9ARM.tex.tmp
+
+docclean manclean maintainer-clean:: clean
+ rm -f *.html ${PDFOBJS}
+
+docclean manclean maintainer-clean distclean::
+ rm -f releaseinfo.xml
+
+Bv9ARM.html: Bv9ARM-book.xml releaseinfo.xml
+ expand Bv9ARM-book.xml | \
+ ${XSLTPROC} --stringparam root.filename Bv9ARM \
+ ${top_srcdir}/doc/xsl/isc-docbook-chunk.xsl -
+
+Bv9ARM.tex: Bv9ARM-book.xml releaseinfo.xml
+ expand Bv9ARM-book.xml | \
+ ${XSLTPROC} ${top_srcdir}/doc/xsl/pre-latex.xsl - | \
+ ${XSLTPROC} ${top_srcdir}/doc/xsl/isc-docbook-latex.xsl - | \
+ @PERL@ latex-fixup.pl >$@.tmp
+ if test -s $@.tmp; then mv $@.tmp $@; else rm -f $@.tmp; exit 1; fi
+
+Bv9ARM.dvi: Bv9ARM.tex releaseinfo.xml
+ rm -f Bv9ARM-book.aux Bv9ARM-book.dvi Bv9ARM-book.log
+ ${LATEX} '\batchmode\input Bv9ARM.tex' || (rm -f $@ ; exit 1)
+ ${LATEX} '\batchmode\input Bv9ARM.tex' || (rm -f $@ ; exit 1)
+ ${LATEX} '\batchmode\input Bv9ARM.tex' || (rm -f $@ ; exit 1)
+
+Bv9ARM.pdf: Bv9ARM.tex releaseinfo.xml
+ rm -f Bv9ARM-book.aux Bv9ARM-book.pdf Bv9ARM-book.log
+ ${PDFLATEX} '\batchmode\input Bv9ARM.tex' || (rm -f $@ ; exit 1)
+ ${PDFLATEX} '\batchmode\input Bv9ARM.tex' || (rm -f $@ ; exit 1)
+ ${PDFLATEX} '\batchmode\input Bv9ARM.tex' || (rm -f $@ ; exit 1)
+
+releaseinfo.xml:
+ echo >$@ '<releaseinfo>BIND Version ${VERSION}</releaseinfo>'
diff --git a/doc/arm/README-SGML b/doc/arm/README-SGML
new file mode 100644
index 0000000..e33c937
--- /dev/null
+++ b/doc/arm/README-SGML
@@ -0,0 +1,329 @@
+Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2000, 2001 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+The BIND v9 ARM master document is now kept in DocBook XML format.
+
+Version: $Id: README-SGML,v 1.17 2004/03/05 05:04:43 marka Exp $
+
+The entire ARM is in the single file:
+
+ Bv9ARM-book.xml
+
+All of the other documents - HTML, PDF, etc - are generated from this
+master source.
+
+This file attempts to describe what tools are necessary for the
+maintenance of this document as well as the generation of the
+alternate formats of this document.
+
+This file will also spend a very little time describing the XML and
+SGML headers so you can understand a bit what you may need to do to be
+able to work with this document in any fashion other than simply
+editing it.
+
+We will spend almost no time on the actual tags and how to write an
+XML DocBook compliant document. If you are at all familiar with SGML
+or HTML it will be very evident. You only need to know what the tags
+are and how to use them. You can find a good resource either for this
+either online or in printed form:
+
+ DocBook: The Definitive Guide
+ By Norman Walsh and Leonard Muellner
+ ISBN: 156592-580-7
+ 1st Edition, October 1999
+ Copyright (C) 1999 by O'Reilly & Associates, Inc. All rights reserved.
+
+The book is available online in HTML format:
+
+ http://docbook.org/
+
+and buried in:
+
+ http://www.nwalsh.com/docbook/defguide/index.html
+
+A lot of useful stuff is at NWalsh's site in general. You may also
+want to look at:
+
+ http://www.xml.com/
+
+The BIND v9 ARM is based on the XML 4.0 DocBook DTD. Every XML and
+SGML document begins with a prefix that tells where to find the file
+that describes the meaning and structure of the tags used in the rest
+of the document.
+
+For our XML DocBook 4.0 based document this prefix looks like this:
+
+ <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
+ "/usr/local/share/xml/dtd/docbook/docbookx.dtd">
+
+This "DOCTYPE" statement has three parts, of which we are only using
+two:
+
+o The highest level term that represents this document (in this case
+ it is "book"
+
+o The identifier that tells us which DTD to use. This identifier has
+ two parts, the "Formal Public Identifier" (or FPI) and the system
+ identifier. In SGML you can have either a FPI or a SYSTEM identifier
+ but you have to have at least one of them. In XML you have to have a
+ SYSTEM identifier.
+
+FP & SYSTEM identifiers - These are names/lookups for the actual
+DTD. The FPI is a globally unique name that should, on a properly
+configured system, tell you exactly what DTD to use. The SYSTEM
+identifier gives an absolute location for the DTD. In XML these are
+supposed to be properly formatted URL's.
+
+SGML has these things called "catalogs" that are files that map FPI's
+in to actual files. A "catalog" can also be used to remap a SYSTEM
+identifier so you can say something like: "http://www.oasis.org/foo"
+is actually "/usr/local/share/xml/foo.dtd"
+
+When you use various SGML/XML tools they need to be configured to look
+at the same "catalog" files so that as you move from tool to tool they
+all refer to the same DTD for the same document.
+
+We will be spending most of our configuration time making sure our
+tools use the same "catalog" files and that we have the same DTD's
+installed on our machines. XML's requirement of the SYSTEM identifier
+over the FPI will probably lead to more problems as it does not
+guarantee that everyone is using the same DTD.
+
+I did my initial work with the "sgmltools" the XML 4.0 DocBook DTD and
+"jade" or "openjade."
+
+You can get the 4.0 XML DocBook DTD from:
+
+ http://www.docbook.org/xml/4.0/
+
+(download the .zip file.) NOTE: We will eventually be changing the
+SYSTEM identifier to the recommended value of:
+
+ http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd
+
+NOTE: Under FreeBSD this is the package:
+
+ /usr/ports/textproc/docbook-xml
+
+NetBSD instructions are coming soon.
+
+With packages listed below installed under FreeBSD the "catalog" file
+that all the tools refer to at least one is in:
+
+ /usr/local/share/sgml/catalog
+
+In order for our SYSTEM identifier for the XML DocBook dtd to be found
+I create a new catalog file at the top of the XML directory created on
+FreeBSD:
+
+ /usr/local/share/xml/catalog
+
+This file has one line:
+
+ SYSTEM "http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd" "/usr/local/share/xml/dtd/docbook/docbookx.dtd"
+
+Then in the main "catalog" I have it include this XML catalog:
+
+ CATALOG "/usr/local/share/xml/catalog"
+
+
+On your systems you need to replace "/usr/local/share" with your
+prefix root (probably /usr/pkg under NetBSD.)
+
+NOTE: The URL used above is supposed to the be the proper one for this
+XML DocBook DTD... but there is nothing at that URL so you really do
+need the "SYSTEM" identifier mapping in your catalog (or make the
+SYSTEM identifier in your document refer to the real location of the
+file on your local system.)
+
+HOW TO VALIDATE A DOCUMENT:
+
+I use the sgmltools "nsgmls" document validator. Since we are using
+XML we need to use the XML declarations, which are installed as part
+of the modular DSSL style sheets:
+
+ nsgmls -sv /usr/local/share/sgml/docbook/dsssl/modular/dtds/decls/xml.dcl \
+ Bv9ARM-book.xml
+
+A convenient shell script "validate.sh" is now generated by configure
+to invoke the above command with the correct system-dependent paths.
+
+The SGML tools can be found at:
+
+ ftp://ftp.us.sgmltools.org/pub/SGMLtools/v2.0/source/ \
+ ftp://ftp.nllgg.nl/pub/SGMLtools/v2.0/source/
+
+FreeBSD package for these is:
+
+ /usr/ports/textproc/sgmltools
+
+HOW TO RENDER A DOCUMENT AS HTML or TeX:
+
+o Generate html doc with:
+
+ openjade -v -d ./nominum-docbook-html.dsl \
+ -t sgml \
+ /usr/local/share/sgml/docbook/dsssl/modular/dtds/decls/xml.dcl \
+ Bv9ARM-book.xml
+
+A convenient shell script "genhtml.sh" is now generated by configure to
+invoke the above command with the correct system-dependent paths.
+
+On NetBSD there is no port for "openjade" however "jade" does still
+work. However you need to specify the "catalog" file to use for style
+sheets on the command line AND you need to have a default "catalog"
+mapping where to find various DTDs. It seems that "jade" installed out
+of the box on NetBSD does not use a globally defined "catalog" file
+for mapping PUBLIC identifiers in to SYSTEM identifiers.
+
+So you need to have a "catalog" file in your current working directory
+that has in it this: (these are probably more entries than you need!)
+
+ CATALOG "/usr/pkg/share/sgml/iso8879/catalog"
+ CATALOG "/usr/pkg/share/sgml/docbook/2.4.1/catalog"
+ CATALOG "/usr/pkg/share/sgml/docbook/3.0/catalog"
+ CATALOG "/usr/pkg/share/sgml/docbook/3.1/catalog"
+ CATALOG "/usr/pkg/share/sgml/jade/catalog"
+ CATALOG "/usr/local/share/xml/catalog"
+
+(These would all be "/usr/local" on FreeBSD)
+
+So the command for jade on NetBSD will look like this:
+
+jade -v -c /usr/pkg/share/sgml/catalog -t sgml \
+ -d ./nominum-docbook-html.dsl \
+ /usr/pkg/share/sgml/docbook/dsssl/modular/dtds/decls/xml.dcl \
+ ./Bv9ARM-book.xml
+
+Furthermore, since the style sheet subset we define has in it a hard
+coded path to the style sheet is based, it is actually generated by
+configure from a .in file so that it will contain the correct
+system-dependent path: where on FreeBSD the second line reads:
+
+ <!ENTITY dbstyle SYSTEM "/usr/local/share/sgml/docbook/dsssl/modular/html/docbook.dsl" CDATA DSSSL>
+
+On NetBSD it needs to read:
+
+ <!ENTITY dbstyle SYSTEM "/usr/pkg/share/sgml/docbook/dsssl/modular/html/docbook.dsl" CDATA DSSSL>
+
+NOTE: This is usually solved by having this style sheet modification
+be installed in a system directory and have it reference the style
+sheet it is based on via a relative path.
+
+o Generate TeX documentation:
+
+openjade -d ./nominum-docbook-print.dsl -t tex -v \
+ /usr/local/share/sgml/docbook/dsssl/modular/dtds/decls/xml.dcl \
+ Bv9ARM-book.xml
+
+If you have "jade" installed instead of "openjade" then use that as
+the command. There is little difference, openjade has some bug fixes
+and is in more active development.
+
+To convert the resulting TeX file in to a DVI file you need to do:
+
+ tex "&jadetex" Bv9ARM-book.tex
+
+You can also directly generate the pdf file via:
+
+ pdftex "&pdfjadetex" Bv9ARM-book.tex
+
+The scripts "genpdf.sh" and "gendvi." have been added to simply
+generating the PDF and DVI output. These substitute the correct paths
+of NetBSD & FreeBSD. You still need to have TeX, jadeTeX, and pdfTeX
+installed and configured properly for these to work.
+
+You will need to up both the "pool_size" and "hash_extra" variables in
+your texmf.cnf file and regenerate them. See below.
+
+You can see that I am using a DSSSL style sheet for DocBook. Actually
+two different ones - one for rendering html, and one for 'print'
+media.
+
+NOTE: For HTML we are using a Nominum DSSSL style instead of the
+default one (all it does is change the chunking to the chapter level
+and makes the files end with ".html" instead of ".htm" so far.) If you
+want to use the plain jane DSSSL style sheet replace the:
+
+ -d ./nominum-docbook-html.dsl
+
+with
+
+ -d /usr/local/share/sgml/docbook/dsssl/modular/html/docbook.dsl
+
+This style sheet will attempt to reference the one above.
+
+I am currently working on fixing these up so that it works the same on
+our various systems. The main trick is knowing which DTD's and DSSSL
+stylesheets you have installed, installing the right ones, and
+configuring a CATALOG that refers to them in the same way. We will
+probably end up putting our CATALOG's in the same place and then we
+should be able to generate and validate our documents with a minimal
+number of command line arguments.
+
+When running these commands you will get a lot of messages about a
+bunch of general entities not being defined and having no default
+entity. You can ignore those for now.
+
+Also with the style sheets we have and jade as it is you will get
+messages about "xref to title" being unsupported. You can ignore these
+for now as well.
+
+=== Getting the various tools installed on FreeBSD
+(NetBSD coming soon..)
+
+o On freebsd you need to install the following packages:
+ o print/teTeX
+ o textproc/openjade
+ o textproc/docbook
+ o textproc/docbook-xml
+ o textproc/dsssl-docbook-modular
+ o textproc/dtd-catalogs
+
+o on freebsd you need to make some entities visible to the docbook xml
+ dtd by making a symlink (can probably be done with a catalog too)
+ ln -s /usr/local/share/xml/entity /usr/local/share/xml/dtd/docbook/ent
+
+o you may need to edit /usr/local/share/sgml/catalog and add the line:
+
+ CATALOG "/usr/local/share/sgml/openjade/catalog"
+
+o add "hugelatex," Enlarge pool sizes, install the jadetex TeX driver
+ file.
+
+ cd /usr/local/share/texmf/web2c/
+ sudo cp texmf.cnf texmf.cnf.bak
+
+ o edit the lines in texmf.cnf with these keys to these values:
+
+ main_memory = 1100000
+ hash_extra = 15000
+ pool_size = 500000
+ string_vacancies = 45000
+ max_strings = 55000
+ pool_free = 47500
+ nest_size = 500
+ param_size = 1500
+ save_size = 5000
+ stack_size = 1500
+
+ sudo tex -ini -progname=hugelatex -fmt=hugelatex latex.ltx
+ sudo texconfig init
+ sudo texhash
+
+ o For the jadetex macros you will need I recommend you get a more
+ current version than what is packaged with openjade or jade.
+
+ Checkout http://www.tug.org/applications/jadetex/
+
+ Unzip the file you get from there (should be jadetex-2.20 or
+ newer.)
+
+ In the directory you unzip:
+
+ sudo make install
+ sudo texhash
+
+ NOTE: In the most uptodate "ports" for FreeBSD, jadetext is 2.20+
+ so on this platform you should be set as of 2001.01.08.
diff --git a/doc/arm/isc-logo.eps b/doc/arm/isc-logo.eps
new file mode 100644
index 0000000..c6a1d7a
--- /dev/null
+++ b/doc/arm/isc-logo.eps
@@ -0,0 +1,12253 @@
+%!PS-Adobe-3.1 EPSF-3.0
+%%Title: Alternate-ISC-logo-v2.ai
+%%Creator: Adobe Illustrator(R) 11
+%%AI8_CreatorVersion: 11.0.0
+%AI9_PrintingDataBegin
+%%For: Douglas E. Appelt
+%%CreationDate: 10/22/04
+%%BoundingBox: 0 0 255 149
+%%HiResBoundingBox: 0 0 254.8672 148.7520
+%%CropBox: 0 0 254.8672 148.7520
+%%LanguageLevel: 2
+%%DocumentData: Clean7Bit
+%%Pages: 1
+%%DocumentNeededResources:
+%%DocumentSuppliedResources: procset Adobe_AGM_Image (1.0 0)
+%%+ procset Adobe_CoolType_Utility_T42 (1.0 0)
+%%+ procset Adobe_CoolType_Utility_MAKEOCF (1.19 0)
+%%+ procset Adobe_CoolType_Core (2.23 0)
+%%+ procset Adobe_AGM_Core (2.0 0)
+%%+ procset Adobe_AGM_Utils (1.0 0)
+%%DocumentFonts:
+%%DocumentNeededFonts:
+%%DocumentNeededFeatures:
+%%DocumentSuppliedFeatures:
+%%DocumentProcessColors: Cyan Magenta Yellow Black
+%%DocumentCustomColors: (PANTONE 1805 C)
+%%+ (PANTONE 871 C)
+%%+ (PANTONE 301 C)
+%%+ (PANTONE 7506 C)
+%%CMYKCustomColor: 0 0.9100 1 0.2300 (PANTONE 1805 C)
+%%+ 0.3569 0.3608 0.6353 0.1882 (PANTONE 871 C)
+%%+ 1 0.4500 0 0.1800 (PANTONE 301 C)
+%%+ 0 0.0500 0.1500 0 (PANTONE 7506 C)
+%%RGBCustomColor:
+%ADO_ContainsXMP: MainFirst
+%AI7_Thumbnail: 128 76 8
+%%BeginData: 10692 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
+%524C45FD1CF852FD63FFF820272726272727264B27272627272726272727
+%26272727264B20F827FD63FFF827FFFFFFCFFF84365AFFFFFFCFFFFFFFCF
+%FFFFFFCFFD04FFCAF852FD63FFF827CFCFCACFCA2F0607A8CFCACFCACFCA
+%CFCACFCACFCACFCACF7CF827FD63FFF800FFCFFFA8A8070D06A8CFFFCFFF
+%CFFFCFFFCFFFCFFFCFFFCFA7F852FD63FFF800077E2F0D060D060706537D
+%CF7D2FA8CFCACFCACFCACFCAFF7CF827FD63FFF8000D062F070D062F070D
+%062F2F0D062FCACFCFFFCFCFCFFFCFA1F852FD63FFF8050707062E517651
+%522807060706072ECFCACFCACFCACFCAFF7CF827FD63FFF8002F067C757B
+%757C757B512F072F2FFFCFCFCFFFCFFFCFFFCFA1F852FD63FFF805075251
+%75517551755175512F062FCACFCACFCACFCACFCAFF7CF827FD63FFF8F859
+%75765176757C517C757B2E2F07A8CFFFCFCFCFFFCFCFCFA1F852FD63FFF8
+%00517551757CCFCAA751755175060753CFCACFCACFCACFCACF7CF827FD63
+%FFF8F87C75757CFFCFFFCFA7517C752F072F59A8CFCFCFFFCFFFCFA7F852
+%FD04FFA87D527DA8FD5AFFF827757551A1CFCFCAFFA0755175280D060706
+%A8CFCFCACFCAFF7CF827FD05FF27F827FD5BFFF8F87C51767CFFCFFFCFA0
+%517C752F062F060D84FFCFFFCFFFCFA1F852FD05FF7DF87DFD5BFFF80552
+%7551757CC9A7A05175517606072F7E7DCFCACFC9CFCAFF6FF827FD05FF52
+%F852FD27FFA8FD33FFF80059757C7575517C517C517C2E2F06CFCFFFCFCF
+%9293CAFFCF6FF852FD05FF7DF87DFD04FFA8FD05FF7D7DA8FF527D7D7D52
+%7D52A8FFA8527D527DA8FF7D7D527D52FD05FFA8FD05FFA87D7DFFFFA852
+%7D527DA8FF527D7D7D527D52A8FD19FFF805075275755175517551752D0D
+%0653CFFFCFFFA78C6899939344F827FD05FF52F852FFFFFFA8F87DFD04FF
+%7D27FFA87D7DA8F827A87D7DFFA8F827A8527DFFA8F852A827F8A8FFFFFF
+%7DF8FD05FF2752FFFFA8F827A8527DA87D7DA8F827A87D7DFD19FFF8F82F
+%0752517C757B757C2E0D062FA8C999CFCFC28C928C8C8C6EF852FD05FF7D
+%F87DFD04FFF8F87DFFFFFF7D52FD05FFF852FD05FFF87DFD05FFF852FFFF
+%F852FFFFFF7DF8F8FD04FF7D52FFFFFFF87DFD07FFF852FD1CFFF8000607
+%062F2852282E060D0607067D928C9293688C6892688C44F827FD05FF52F8
+%52FFFFFFA85252F852FFFF7D27FD05FFF87DFD04FFA8F852FD05FFF852FF
+%FFF8A8FFFFFF7D5227F8A8FFFF527DFFFFA8F852FD07FFF87DFD1CFFF800
+%852F2F062F070D062F072F062F0D9A8C928C928C928C928C6EF852FD05FF
+%7DF87DFD04FF27FF52F852FF7D52FD05FFF852FD05FFF82752527DFFFFF8
+%52FF527DFD04FF527DFF27F8A8FF7D7DFFFFFFF82752527DFD04FFF852FD
+%1CFFF827CFCF7D2F060D062F2F7EA82F062F938C68928C8C68926E994AF8
+%27FD05FF52F852FFFFFFA827FFFF52F852A852FD05FFF87DFD04FFA8F852
+%FF7DA8FFFFF82752F8A8FD04FF7D52FFA827F8A87D7DFFFFA8F852FF7DA8
+%FD04FFF87DFD1CFFF827FFCFFFA80D062FA8CFCFCA927693928C928C9292
+%75517C7B51F852FD05FF7DF87DFFFFFFA827FFFFFF52F8F87DFD05FFF852
+%FD05FFF87DFD05FFF852FF52F8A8FFFFFF5252FFFFFF27F8277DFFFFFFF8
+%7DFD07FFF852FD1CFFF827CFCFCACF06062ECFCAFF928C688C6892688C6E
+%765175517C26F827FD05FF52F852FFFFFFA827FD04FF52F852FD05FFF852
+%FD04FFA8F852FFFFA8A8FFF87DFFFFF8F8A8FFFF5227FD04FF27F8A8FFFF
+%A8F852FFFFA8A8FFFFFFF852FD1CFFF827FFCFFFCF7E53A8CFFFCFC99292
+%8C928C92757C757C517C7551F852FD04FFA852F852A8FFFFA8F8A8FD04FF
+%527DFD04FF7DF827FD04FFA8F827525252FF7DF827FFFFFF2727A8FF5227
+%A8FD04FF52A8FFFFA8F827525252FFFFFF7DF827FD1CFFF827CFCFCACFCF
+%CFCAFD04CF93688C688C6F7651755175517C4BF827FD05FFA8FFA8FFFFFF
+%A8FFA8FD0BFFA8FFA8FFFFFFA8FFA8A8A8FFFFFFA8FFA8FFFFFFA8FFA8FF
+%A8FD09FFA8FFA8A8A8FD05FFA8FFA8FD1BFFF827FFCFCFCFFFCFCFCFFFCF
+%C38C928C8C6E7C7576517C75767551F852FD63FFF827CFCFCACFCACFCACF
+%92928C8C688C6875517551755175517526F827FD63FFF827FFCFFFCFFFCF
+%FFCA938C928C928C99517C757C517C757C7551F852FD63FFF827CFCFCACF
+%CACFCACFA093688C6892757551755175517551754BF827FD63FFF827FFCF
+%FFCFCFCFFFCFFF998C8C926E7C7576517C7576517CA7A1F852FD06FFA87D
+%527DA8FD58FFF827CFCFCACFCACFCAFFCF996892686F5175517551755175
+%7CFF7CF827FD05FF7D2752A82727A8FD57FFF827FFCFFFCFFFCFFFC2BB8C
+%928C8C6E7C757C517C757C51CFFFA1F852FD05FF2752FFFFFF52FD58FFF8
+%27CFCFCACFCACFCF99688C68928C6F5175517551755175CAFF7CF827FD04
+%FFA8F852FD5CFFF827FFCFCFCFFFCFFFA0998C928C926E7C517C7576517C
+%51CACFA1F852FD04FFA827F87DFFFFFFA8527DFD04FF527DFFFFA87D52A8
+%FF7D527D527D527D7DFF7D7D527D527DFFFFFFA8FD06FFA8FD04FFA87D7D
+%7DFD26FFF827CFCFCACFCACFCACFCF99688C6893517551755175517575FF
+%7CF827FD05FF52F8F852FFFFFF52F8A8FFFF7D27A8FF5252A8A852A852A8
+%7DF827A87D7DFFA8F852A87D52FFFFFFF8A8FD04FF5227FFFFFF7D27A8A8
+%52A8FD25FFF827FFCFFFCFFFCFFFCFFFA08C8C92927C517C757C517C7575
+%7C7CF852FD06FF52F8F852FFFFFF27F8FFFF52A8FFFFF87DFD07FFF87DFD
+%05FFF852FD06FFF827FD04FF2727FFFFFF2752FD29FFF827CFCFCACFCACF
+%CACFA799688C68927575517551755175517526F84BFD07FF52F8F87DFFFF
+%A8F87D7D52FFFFFFF8F87DFD05FFA8F852FD05FFF87DFD05FFA8F8F8A8FF
+%FF7DF8F8A8FFFF52F852A8FD27FFF827FFCFFFCFCFCFFFCF9368928C928C
+%995176517C7576517C7551F852FD08FF7DF8F8FFFFFF52F827FD05FFF8F8
+%27FD05FFF87DFD05FFF8277D527DFFFF7D52F852FFFF277DF8A8FFFFFF52
+%F8F87DFD26FFF827CFCFCACFCACFCAFF938C688C688C6875517551755175
+%517C26F827FD09FF27F8A8FFFFFFF852FD06FF52F827FFFFFFA8F852FD05
+%FFF852A8A87DFFFF527D7DF8FF7D52A8F87DFD04FF7DF8F8A8FD25FFF827
+%FFCFFFCFFFCFFFCFCFCFC98C928C92927C517C757C517C7551F852FD04FF
+%7DFD04FF7DF8FD04FFF852FD07FF7DF8A8FFFFFFF87DFD05FFF852FD05FF
+%52A8FF272752A8FFF87DFD06FFF8A8FD25FFF827CFCFCACFCACFCAFD04CF
+%99688C688C6E7651755175517C4BF827FD04FF5227FFFFA8F852FD04FFF8
+%7DFFFFFF7D7DFFFF7D27FD04FFF852FD05FFF852FFFFA8FFFF27A8FF7DF8
+%52FFFFF852FFA852FFFF7D27A8FD25FFF827FFCFCFCFFFCFCFCFFFCFCF92
+%928C928C926E7C517C75767551F852FD04FF7D272752277DFD04FF7DF827
+%FFFFFF7D27525227FD04FFA8F852A8FFFFFF7D2727525252FFA8F8A8FFFF
+%52FFFFFF2727A8FF275252527DFD26FFF827CFCFCACFCACFCACFCAFF998C
+%688C688C688C68755176517526F827FD07FFA8FD07FFA8FFA8FFFFFFA8A8
+%A8FD05FFA8FFA8FD05FFA8FFA8A8A8FFA8FFA8FD07FFA8FFFFFFA8A8FD28
+%FFF827FFCFFFCFFFCFFFCFFFCFCF92C29A928C928C928C99757C7551F852
+%FD63FFF827CFCFCACFCACFCACFCAFD04CFFF998C68928C8C6892689344F8
+%27FD63FFF827FFCFFFCFCFCFFFCFCFCFFFCFCFCFC98C928C928C928C928C
+%68F852FD63FFF827CFCFCACFCACFCAA8537ECACFCAFF938C6899688C688C
+%689244F827FD63FFF827FFCFFFCFFFCFA8072F07FFCFFFCFCF992F0D5992
+%928C928C68F852FD08FF7D7D527D52A8A8FD54FFF827CFCFCACFCACFA70D
+%060753A87DA8CA5A0607069368929AC244F827FD06FF7DF8527D7D7D52F8
+%27FD54FFF827FFCFCFCFFFCFCF2F2F070D062F072F062F07539993C2FFFF
+%76F852FD05FF7DF87DFD06FF27FD54FFF827CFCFCACFCACF7D0D060D0607
+%060D0607060753FFCACFCAFF76F827FD04FFA8F827FD07FFA8A8FD15FFA8
+%FD3DFFF827FFCFFFCFFF592F062F072F2852282F072F072F7DFFCFFFCFA7
+%F852FD04FF52F87DFD0CFFA87D7D7DFD05FFA8FD05FF7D7DA8FFFFA87D7D
+%7DFFFFFFA87D527D7DFD04FFA8527D527DA8FFFF7D527D527D527D7DFF7D
+%7D7DFFFFA8527DA8FFFFA8527DFFFFFFA8FD06FFA8FFFFF827CF5959CA53
+%07060D066F688C6892684B060D06077DCFCFCF7CF827FD04FF27F8A8FD0A
+%FFA82752A87D52F852FFFFA8F87DFD04FF7D27FFFF7D27A87D52FFFF5227
+%7DA87D27F8A8FFFFA8F827A827F8A8A852A87DF827A87D7DFFA8F852FFFF
+%A8F827FD04FF2727FFFFFFF8A8FD04FF5227FFFFF827A9062F070D062F28
+%928C928C928C928C92282F072F847E5953F852FD04FFF8F8A8FD0AFF2752
+%FD04FF7DF87DFFFFF8F852FFFFFF7D52FFFFF8A8FFFFA8FF7DF8A8FD04FF
+%27F8FFFFFFF87DFFFFF87DFD04FFF87DFD05FFF852FFFFFFF87DFD04FF27
+%52FFFFFFF827FD04FF2727FFFFF8272F07060D060D278C688C68928C8C68
+%8C688C060D0607060D06F827FFFFFFA827F87DFD09FF7DF8FD06FF27F8FF
+%A85252F852FFFF7D27FFFF27F87DFFFFFF2727FD05FF7DF852FFA8F852FF
+%A8F87DFFFFFFA8F852FD05FFF852FFFFA8F852FD04FF5252FFFFA8F8F8A8
+%FFFF7DF827A8FFF827FF2F2F070D06938C928CBCC9CFC9BB8C928C6F070D
+%062F0706F852FD04FF27F852FD09FF52F8FD06FF52F8FFFF27FF52F852FF
+%7D52FFFFA827F827A8FFF852FD06FFF852FFFFF852FF7D7DFD05FFF87DFD
+%05FFF852FFFFFFF87DFD04FF2752FFFF7D52F852FFFF277DF8A8FFF827CF
+%CF2F0D064C689268C2CFFFCFFFCFC2688C682E0607062F52F827FD04FF7D
+%F8F8A8FD08FF52F8A8FD05FF52F8FFA827FFFF52F852A852FD04FF7DF827
+%FF2727FD05FFA8F852FFA8F82752F8A8FD04FFA8F852FD05FFF852FFFFA8
+%F852FD04FF5252FFFF7D7D7DF8FF7D52A8F87DFFF827FFCF59062F6F8C8C
+%99CFFFCFFFCFFFCF938C8C4B2F0759CFA7F852FD05FF52F827FD06FF7DFF
+%A8F852FD05FFF852FFA827FFFFFF52F8F87DFD05FF7DF8FF52F8A8FD04FF
+%A8F8A8FFFFF87DFF52F8FD05FFF87DFD05FFF852FFFFFFF852FD04FF277D
+%FFFF27A8FF272752FFFFF87DFFF827CFCF2F070693688C99FFCACFCACFCA
+%FF998C686F060759CF7CF827FD05FFA852F8F87DFFFFFF5227FFFF52F87D
+%FFFFFF5227A8FFA827FD04FF52F852FF527DFFFF5227FFFFF827A8FFFFFF
+%2752FFFFFFF852FFFF27F8FFFFFFA8F852FD05FFF87DFFFFFF52F8A8FFFF
+%7D27A8FFFF27A8FF7DF852FFFFF827FFF827FFCF53062F6E928CC2FFFFCF
+%FFCFFFCFC28C926F2F077ECFA7F852FD07FFA8FD06277DFFFFFF7D27277D
+%527DFFFFFF7DF8A8FD04FF527DFFA827525252A8FFFFFF5227527D52A8FF
+%FFFFA8F852A8FFA82727A8FFA8F852A8FFFFFF7DF827FD04FF52277D5252
+%A8FFFFA8F8A8FFFF52FFFFFF2727A8F827CFCF2F07066F8C8C92FFCFCFCA
+%CFCFCF8C8C8C4B060D59CF7CF827FD0BFFA8FD09FFA8FD05FFA8FFA8FD09
+%FFA8A8FD07FFA8A8FD05FFA8FFA8FD05FFA8FFA8FFA8FD05FFA8FFA8FD05
+%FFA8FD05FFA8FFA8FD07FFA8FFF827AF2F2F070D4B928C8CA0FFCFFFCFFF
+%998C8C92280D067ECFA1F852FD63FFF8270707060D0607688C688C99C9CA
+%C9938C688C680D0607065A76F827FD63FFF8275A062F070D07528C928C92
+%8C928C928C928C2F070D062F072EF852FD63FFF84B842F597E0607064C8C
+%8C68928C8C688C6828060D0607060D52F827FD63FFF827FFCFCFCF7E060D
+%062F6F928C928C934B2F070D0684A85A59A1F852FD63FFF827CFCFCACFCA
+%590607060D06282728060D0607067ECACFCFCF7CF827FD63FFF827FFCFFF
+%CFFFCF59062F070D072F070D062F2FA8CFFFCFFFCFA7F852FD63FFF827CF
+%CFCACFCACF2F07060D0607060D06070653CFCFCACFCAFF7CF827FD63FFF8
+%27FFCFFFCFCFA82F070D59CFA8A8A859060D07FD04CFFFCFA1F852FD63FF
+%F827CFCFCACFCFA82F0D2FCFCACFCFCFA80D060DA8CFCACFCAFF7CF827FD
+%63FFF827FFCFFFCFFFCFFFA8FFCFFFCFFFCFFF7E7EA8FFCFFFCFFFFFA7F8
+%52FD63FFFD09F820FD07F820FD07F820F8F827FD63FF27F827F820F827F8
+%20F827F820F827F820F827F820F827F820F827F87CFDE2FFFF
+%%EndData
+%%EndComments
+%%BeginDefaults
+%%ViewingOrientation: 1 0 0 1
+%%EndDefaults
+%%BeginProlog
+%%BeginResource: procset Adobe_AGM_Utils 1.0 0
+%%Version: 1.0 0
+%%Copyright: Copyright (C) 2000-2003 Adobe Systems, Inc. All Rights Reserved.
+systemdict /setpacking known
+{
+ currentpacking
+ true setpacking
+} if
+userdict /Adobe_AGM_Utils 68 dict dup begin put
+/bdf
+{
+ bind def
+} bind def
+/nd{
+ null def
+}bdf
+/xdf
+{
+ exch def
+}bdf
+/ldf
+{
+ load def
+}bdf
+/ddf
+{
+ put
+}bdf
+/xddf
+{
+ 3 -1 roll put
+}bdf
+/xpt
+{
+ exch put
+}bdf
+/ndf
+{
+ exch dup where{
+ pop pop pop
+ }{
+ xdf
+ }ifelse
+}def
+/cdndf
+{
+ exch dup currentdict exch known{
+ pop pop
+ }{
+ exch def
+ }ifelse
+}def
+/bdict
+{
+ mark
+}bdf
+/edict
+{
+ counttomark 2 idiv dup dict begin {def} repeat pop currentdict end
+}def
+/ps_level
+ /languagelevel where{
+ pop systemdict /languagelevel get exec
+ }{
+ 1
+ }ifelse
+def
+/level2
+ ps_level 2 ge
+def
+/level3
+ ps_level 3 ge
+def
+/ps_version
+ {version cvr} stopped {
+ -1
+ }if
+def
+/makereadonlyarray
+{
+ /packedarray where{
+ pop packedarray
+ }{
+ array astore readonly
+ }ifelse
+}bdf
+/map_reserved_ink_name
+{
+ dup type /stringtype eq{
+ dup /Red eq{
+ pop (_Red_)
+ }{
+ dup /Green eq{
+ pop (_Green_)
+ }{
+ dup /Blue eq{
+ pop (_Blue_)
+ }{
+ dup () cvn eq{
+ pop (Process)
+ }if
+ }ifelse
+ }ifelse
+ }ifelse
+ }if
+}bdf
+/AGMUTIL_GSTATE 22 dict def
+/get_gstate
+{
+ AGMUTIL_GSTATE begin
+ /AGMUTIL_GSTATE_clr_spc currentcolorspace def
+ /AGMUTIL_GSTATE_clr_indx 0 def
+ /AGMUTIL_GSTATE_clr_comps 12 array def
+ mark currentcolor counttomark
+ {AGMUTIL_GSTATE_clr_comps AGMUTIL_GSTATE_clr_indx 3 -1 roll put
+ /AGMUTIL_GSTATE_clr_indx AGMUTIL_GSTATE_clr_indx 1 add def} repeat pop
+ /AGMUTIL_GSTATE_fnt rootfont def
+ /AGMUTIL_GSTATE_lw currentlinewidth def
+ /AGMUTIL_GSTATE_lc currentlinecap def
+ /AGMUTIL_GSTATE_lj currentlinejoin def
+ /AGMUTIL_GSTATE_ml currentmiterlimit def
+ currentdash /AGMUTIL_GSTATE_do xdf /AGMUTIL_GSTATE_da xdf
+ /AGMUTIL_GSTATE_sa currentstrokeadjust def
+ /AGMUTIL_GSTATE_clr_rnd currentcolorrendering def
+ /AGMUTIL_GSTATE_op currentoverprint def
+ /AGMUTIL_GSTATE_bg currentblackgeneration cvlit def
+ /AGMUTIL_GSTATE_ucr currentundercolorremoval cvlit def
+ currentcolortransfer cvlit /AGMUTIL_GSTATE_gy_xfer xdf cvlit /AGMUTIL_GSTATE_b_xfer xdf
+ cvlit /AGMUTIL_GSTATE_g_xfer xdf cvlit /AGMUTIL_GSTATE_r_xfer xdf
+ /AGMUTIL_GSTATE_ht currenthalftone def
+ /AGMUTIL_GSTATE_flt currentflat def
+ end
+}def
+/set_gstate
+{
+ AGMUTIL_GSTATE begin
+ AGMUTIL_GSTATE_clr_spc setcolorspace
+ AGMUTIL_GSTATE_clr_indx {AGMUTIL_GSTATE_clr_comps AGMUTIL_GSTATE_clr_indx 1 sub get
+ /AGMUTIL_GSTATE_clr_indx AGMUTIL_GSTATE_clr_indx 1 sub def} repeat setcolor
+ AGMUTIL_GSTATE_fnt setfont
+ AGMUTIL_GSTATE_lw setlinewidth
+ AGMUTIL_GSTATE_lc setlinecap
+ AGMUTIL_GSTATE_lj setlinejoin
+ AGMUTIL_GSTATE_ml setmiterlimit
+ AGMUTIL_GSTATE_da AGMUTIL_GSTATE_do setdash
+ AGMUTIL_GSTATE_sa setstrokeadjust
+ AGMUTIL_GSTATE_clr_rnd setcolorrendering
+ AGMUTIL_GSTATE_op setoverprint
+ AGMUTIL_GSTATE_bg cvx setblackgeneration
+ AGMUTIL_GSTATE_ucr cvx setundercolorremoval
+ AGMUTIL_GSTATE_r_xfer cvx AGMUTIL_GSTATE_g_xfer cvx AGMUTIL_GSTATE_b_xfer cvx
+ AGMUTIL_GSTATE_gy_xfer cvx setcolortransfer
+ AGMUTIL_GSTATE_ht /HalftoneType get dup 9 eq exch 100 eq or
+ {
+ currenthalftone /HalftoneType get AGMUTIL_GSTATE_ht /HalftoneType get ne
+ {
+ mark AGMUTIL_GSTATE_ht {sethalftone} stopped cleartomark
+ } if
+ }{
+ AGMUTIL_GSTATE_ht sethalftone
+ } ifelse
+ AGMUTIL_GSTATE_flt setflat
+ end
+}def
+/get_gstate_and_matrix
+{
+ AGMUTIL_GSTATE begin
+ /AGMUTIL_GSTATE_ctm matrix currentmatrix def
+ end
+ get_gstate
+}def
+/set_gstate_and_matrix
+{
+ set_gstate
+ AGMUTIL_GSTATE begin
+ AGMUTIL_GSTATE_ctm setmatrix
+ end
+}def
+/AGMUTIL_str256 256 string def
+/AGMUTIL_src256 256 string def
+/AGMUTIL_dst64 64 string def
+/AGMUTIL_srcLen nd
+/AGMUTIL_ndx nd
+/agm_sethalftone
+{
+ dup
+ begin
+ /_Data load
+ /Thresholds xdf
+ end
+ level3
+ { sethalftone }{
+ dup /HalftoneType get 3 eq {
+ sethalftone
+ } {pop} ifelse
+ }ifelse
+} def
+/rdcmntline
+{
+ currentfile AGMUTIL_str256 readline pop
+ (%) anchorsearch {pop} if
+} bdf
+/filter_cmyk
+{
+ dup type /filetype ne{
+ exch () /SubFileDecode filter
+ }
+ {
+ exch pop
+ }
+ ifelse
+ [
+ exch
+ {
+ AGMUTIL_src256 readstring pop
+ dup length /AGMUTIL_srcLen exch def
+ /AGMUTIL_ndx 0 def
+ AGMCORE_plate_ndx 4 AGMUTIL_srcLen 1 sub{
+ 1 index exch get
+ AGMUTIL_dst64 AGMUTIL_ndx 3 -1 roll put
+ /AGMUTIL_ndx AGMUTIL_ndx 1 add def
+ }for
+ pop
+ AGMUTIL_dst64 0 AGMUTIL_ndx getinterval
+ }
+ bind
+ /exec cvx
+ ] cvx
+} bdf
+/filter_indexed_devn
+{
+ cvi Names length mul names_index add Lookup exch get
+} bdf
+/filter_devn
+{
+ 4 dict begin
+ /srcStr xdf
+ /dstStr xdf
+ dup type /filetype ne{
+ 0 () /SubFileDecode filter
+ }if
+ [
+ exch
+ [
+ /devicen_colorspace_dict /AGMCORE_gget cvx /begin cvx
+ currentdict /srcStr get /readstring cvx /pop cvx
+ /dup cvx /length cvx 0 /gt cvx [
+ Adobe_AGM_Utils /AGMUTIL_ndx 0 /ddf cvx
+ names_index Names length currentdict /srcStr get length 1 sub {
+ 1 /index cvx /exch cvx /get cvx
+ currentdict /dstStr get /AGMUTIL_ndx /load cvx 3 -1 /roll cvx /put cvx
+ Adobe_AGM_Utils /AGMUTIL_ndx /AGMUTIL_ndx /load cvx 1 /add cvx /ddf cvx
+ } for
+ currentdict /dstStr get 0 /AGMUTIL_ndx /load cvx /getinterval cvx
+ ] cvx /if cvx
+ /end cvx
+ ] cvx
+ bind
+ /exec cvx
+ ] cvx
+ end
+} bdf
+/AGMUTIL_imagefile nd
+/read_image_file
+{
+ AGMUTIL_imagefile 0 setfileposition
+ 10 dict begin
+ /imageDict xdf
+ /imbufLen Width BitsPerComponent mul 7 add 8 idiv def
+ /imbufIdx 0 def
+ /origDataSource imageDict /DataSource get def
+ /origMultipleDataSources imageDict /MultipleDataSources get def
+ /origDecode imageDict /Decode get def
+ /dstDataStr imageDict /Width get colorSpaceElemCnt mul string def
+ /srcDataStrs [ imageDict begin
+ currentdict /MultipleDataSources known {MultipleDataSources {DataSource length}{1}ifelse}{1} ifelse
+ {
+ Width Decode length 2 div mul cvi string
+ } repeat
+ end ] def
+ imageDict /MultipleDataSources known {MultipleDataSources}{false} ifelse
+ {
+ /imbufCnt imageDict /DataSource get length def
+ /imbufs imbufCnt array def
+ 0 1 imbufCnt 1 sub {
+ /imbufIdx xdf
+ imbufs imbufIdx imbufLen string put
+ imageDict /DataSource get imbufIdx [ AGMUTIL_imagefile imbufs imbufIdx get /readstring cvx /pop cvx ] cvx put
+ } for
+ DeviceN_PS2 {
+ imageDict begin
+ /DataSource [ DataSource /devn_sep_datasource cvx ] cvx def
+ /MultipleDataSources false def
+ /Decode [0 1] def
+ end
+ } if
+ }{
+ /imbuf imbufLen string def
+ Indexed_DeviceN level3 not and DeviceN_NoneName or {
+ imageDict begin
+ /DataSource [AGMUTIL_imagefile Decode BitsPerComponent false 1 /filter_indexed_devn load dstDataStr srcDataStrs devn_alt_datasource /exec cvx] cvx def
+ /Decode [0 1] def
+ end
+ }{
+ imageDict /DataSource {AGMUTIL_imagefile imbuf readstring pop} put
+ } ifelse
+ } ifelse
+ imageDict exch
+ load exec
+ imageDict /DataSource origDataSource put
+ imageDict /MultipleDataSources origMultipleDataSources put
+ imageDict /Decode origDecode put
+ end
+} bdf
+/write_image_file
+{
+ begin
+ { (AGMUTIL_imagefile) (w+) file } stopped{
+ false
+ }{
+ Adobe_AGM_Utils/AGMUTIL_imagefile xddf
+ 2 dict begin
+ /imbufLen Width BitsPerComponent mul 7 add 8 idiv def
+ MultipleDataSources {DataSource 0 get}{DataSource}ifelse type /filetype eq {
+ /imbuf imbufLen string def
+ }if
+ 1 1 Height {
+ pop
+ MultipleDataSources {
+ 0 1 DataSource length 1 sub {
+ DataSource type dup
+ /arraytype eq {
+ pop DataSource exch get exec
+ }{
+ /filetype eq {
+ DataSource exch get imbuf readstring pop
+ }{
+ DataSource exch get
+ } ifelse
+ } ifelse
+ AGMUTIL_imagefile exch writestring
+ } for
+ }{
+ DataSource type dup
+ /arraytype eq {
+ pop DataSource exec
+ }{
+ /filetype eq {
+ DataSource imbuf readstring pop
+ }{
+ DataSource
+ } ifelse
+ } ifelse
+ AGMUTIL_imagefile exch writestring
+ } ifelse
+ }for
+ end
+ true
+ }ifelse
+ end
+} bdf
+/close_image_file
+{
+ AGMUTIL_imagefile closefile (AGMUTIL_imagefile) deletefile
+}def
+statusdict /product known userdict /AGMP_current_show known not and{
+ /pstr statusdict /product get def
+ pstr (HP LaserJet 2200) eq
+ pstr (HP LaserJet 4000 Series) eq or
+ pstr (HP LaserJet 4050 Series ) eq or
+ pstr (HP LaserJet 8000 Series) eq or
+ pstr (HP LaserJet 8100 Series) eq or
+ pstr (HP LaserJet 8150 Series) eq or
+ pstr (HP LaserJet 5000 Series) eq or
+ pstr (HP LaserJet 5100 Series) eq or
+ pstr (HP Color LaserJet 4500) eq or
+ pstr (HP Color LaserJet 4600) eq or
+ pstr (HP LaserJet 5Si) eq or
+ pstr (HP LaserJet 1200 Series) eq or
+ pstr (HP LaserJet 1300 Series) eq or
+ pstr (HP LaserJet 4100 Series) eq or
+ {
+ userdict /AGMP_current_show /show load put
+ userdict /show {
+ currentcolorspace 0 get
+ /Pattern eq
+ {false charpath f}
+ {AGMP_current_show} ifelse
+ } put
+ }if
+ currentdict /pstr undef
+} if
+/consumeimagedata
+{
+ begin
+ currentdict /MultipleDataSources known not
+ {/MultipleDataSources false def} if
+ MultipleDataSources
+ {
+ 1 dict begin
+ /flushbuffer Width cvi string def
+ 1 1 Height cvi
+ {
+ pop
+ 0 1 DataSource length 1 sub
+ {
+ DataSource exch get
+ dup type dup
+ /filetype eq
+ {
+ exch flushbuffer readstring pop pop
+ }if
+ /arraytype eq
+ {
+ exec pop
+ }if
+ }for
+ }for
+ end
+ }
+ {
+ /DataSource load type dup
+ /filetype eq
+ {
+ 1 dict begin
+ /flushbuffer Width Decode length 2 div mul cvi string def
+ 1 1 Height { pop DataSource flushbuffer readstring pop pop} for
+ end
+ }if
+ /arraytype eq
+ {
+ 1 1 Height { pop DataSource pop } for
+ }if
+ }ifelse
+ end
+}bdf
+/addprocs
+{
+ 2{/exec load}repeat
+ 3 1 roll
+ [ 5 1 roll ] bind cvx
+}def
+/modify_halftone_xfer
+{
+ currenthalftone dup length dict copy begin
+ currentdict 2 index known{
+ 1 index load dup length dict copy begin
+ currentdict/TransferFunction known{
+ /TransferFunction load
+ }{
+ currenttransfer
+ }ifelse
+ addprocs /TransferFunction xdf
+ currentdict end def
+ currentdict end sethalftone
+ }{
+ currentdict/TransferFunction known{
+ /TransferFunction load
+ }{
+ currenttransfer
+ }ifelse
+ addprocs /TransferFunction xdf
+ currentdict end sethalftone
+ pop
+ }ifelse
+}def
+/clonearray
+{
+ dup xcheck exch
+ dup length array exch
+ Adobe_AGM_Core/AGMCORE_tmp -1 ddf
+ {
+ Adobe_AGM_Core/AGMCORE_tmp AGMCORE_tmp 1 add ddf
+ dup type /dicttype eq
+ {
+ AGMCORE_tmp
+ exch
+ clonedict
+ Adobe_AGM_Core/AGMCORE_tmp 4 -1 roll ddf
+ } if
+ dup type /arraytype eq
+ {
+ AGMCORE_tmp exch
+ clonearray
+ Adobe_AGM_Core/AGMCORE_tmp 4 -1 roll ddf
+ } if
+ exch dup
+ AGMCORE_tmp 4 -1 roll put
+ }forall
+ exch {cvx} if
+}bdf
+/clonedict
+{
+ dup length dict
+ begin
+ {
+ dup type /dicttype eq
+ {
+ clonedict
+ } if
+ dup type /arraytype eq
+ {
+ clonearray
+ } if
+ def
+ }forall
+ currentdict
+ end
+}bdf
+/DeviceN_PS2
+{
+ /currentcolorspace AGMCORE_gget 0 get /DeviceN eq level3 not and
+} bdf
+/Indexed_DeviceN
+{
+ /indexed_colorspace_dict AGMCORE_gget dup null ne {
+ /CSD known
+ }{
+ pop false
+ } ifelse
+} bdf
+/DeviceN_NoneName
+{
+ /Names where {
+ pop
+ false Names
+ {
+ (None) eq or
+ } forall
+ }{
+ false
+ }ifelse
+} bdf
+/DeviceN_PS2_inRip_seps
+{
+ /AGMCORE_in_rip_sep where
+ {
+ pop dup type dup /arraytype eq exch /packedarraytype eq or
+ {
+ dup 0 get /DeviceN eq level3 not and AGMCORE_in_rip_sep and
+ {
+ /currentcolorspace exch AGMCORE_gput
+ false
+ }
+ {
+ true
+ }ifelse
+ }
+ {
+ true
+ } ifelse
+ }
+ {
+ true
+ } ifelse
+} bdf
+/base_colorspace_type
+{
+ dup type /arraytype eq {0 get} if
+} bdf
+/doc_setup{
+ Adobe_AGM_Utils begin
+}bdf
+/doc_trailer{
+ currentdict Adobe_AGM_Utils eq{
+ end
+ }if
+}bdf
+systemdict /setpacking known
+{
+ setpacking
+} if
+%%EndResource
+%%BeginResource: procset Adobe_AGM_Core 2.0 0
+%%Version: 2.0 0
+%%Copyright: Copyright (C) 1997-2003 Adobe Systems, Inc. All Rights Reserved.
+systemdict /setpacking known
+{
+ currentpacking
+ true setpacking
+} if
+userdict /Adobe_AGM_Core 216 dict dup begin put
+/nd{
+ null def
+}bind def
+/Adobe_AGM_Core_Id /Adobe_AGM_Core_2.0_0 def
+/AGMCORE_str256 256 string def
+/AGMCORE_save nd
+/AGMCORE_graphicsave nd
+/AGMCORE_c 0 def
+/AGMCORE_m 0 def
+/AGMCORE_y 0 def
+/AGMCORE_k 0 def
+/AGMCORE_cmykbuf 4 array def
+/AGMCORE_screen [currentscreen] cvx def
+/AGMCORE_tmp 0 def
+/AGMCORE_&setgray nd
+/AGMCORE_&setcolor nd
+/AGMCORE_&setcolorspace nd
+/AGMCORE_&setcmykcolor nd
+/AGMCORE_cyan_plate nd
+/AGMCORE_magenta_plate nd
+/AGMCORE_yellow_plate nd
+/AGMCORE_black_plate nd
+/AGMCORE_plate_ndx nd
+/AGMCORE_get_ink_data nd
+/AGMCORE_is_cmyk_sep nd
+/AGMCORE_host_sep nd
+/AGMCORE_avoid_L2_sep_space nd
+/AGMCORE_distilling nd
+/AGMCORE_composite_job nd
+/AGMCORE_producing_seps nd
+/AGMCORE_ps_level -1 def
+/AGMCORE_ps_version -1 def
+/AGMCORE_environ_ok nd
+/AGMCORE_CSA_cache 0 dict def
+/AGMCORE_CSD_cache 0 dict def
+/AGMCORE_pattern_cache 0 dict def
+/AGMCORE_currentoverprint false def
+/AGMCORE_deltaX nd
+/AGMCORE_deltaY nd
+/AGMCORE_name nd
+/AGMCORE_sep_special nd
+/AGMCORE_err_strings 4 dict def
+/AGMCORE_cur_err nd
+/AGMCORE_ovp nd
+/AGMCORE_current_spot_alias false def
+/AGMCORE_inverting false def
+/AGMCORE_feature_dictCount nd
+/AGMCORE_feature_opCount nd
+/AGMCORE_feature_ctm nd
+/AGMCORE_ConvertToProcess false def
+/AGMCORE_Default_CTM matrix def
+/AGMCORE_Default_PageSize nd
+/AGMCORE_currentbg nd
+/AGMCORE_currentucr nd
+/AGMCORE_gradientcache 32 dict def
+/AGMCORE_in_pattern false def
+/knockout_unitsq nd
+/AGMCORE_CRD_cache where{
+ pop
+}{
+ /AGMCORE_CRD_cache 0 dict def
+}ifelse
+/AGMCORE_key_known
+{
+ where{
+ /Adobe_AGM_Core_Id known
+ }{
+ false
+ }ifelse
+}ndf
+/flushinput
+{
+ save
+ 2 dict begin
+ /CompareBuffer 3 -1 roll def
+ /readbuffer 256 string def
+ mark
+ {
+ currentfile readbuffer {readline} stopped
+ {cleartomark mark}
+ {
+ not
+ {pop exit}
+ if
+ CompareBuffer eq
+ {exit}
+ if
+ }ifelse
+ }loop
+ cleartomark
+ end
+ restore
+}bdf
+/getspotfunction
+{
+ AGMCORE_screen exch pop exch pop
+ dup type /dicttype eq{
+ dup /HalftoneType get 1 eq{
+ /SpotFunction get
+ }{
+ dup /HalftoneType get 2 eq{
+ /GraySpotFunction get
+ }{
+ pop
+ {
+ abs exch abs 2 copy add 1 gt{
+ 1 sub dup mul exch 1 sub dup mul add 1 sub
+ }{
+ dup mul exch dup mul add 1 exch sub
+ }ifelse
+ }bind
+ }ifelse
+ }ifelse
+ }if
+} def
+/clp_npth
+{
+ clip newpath
+} def
+/eoclp_npth
+{
+ eoclip newpath
+} def
+/npth_clp
+{
+ newpath clip
+} def
+/add_grad
+{
+ AGMCORE_gradientcache 3 1 roll put
+}bdf
+/exec_grad
+{
+ AGMCORE_gradientcache exch get exec
+}bdf
+/graphic_setup
+{
+ /AGMCORE_graphicsave save def
+ concat
+ 0 setgray
+ 0 setlinecap
+ 0 setlinejoin
+ 1 setlinewidth
+ [] 0 setdash
+ 10 setmiterlimit
+ newpath
+ false setoverprint
+ false setstrokeadjust
+ Adobe_AGM_Core/spot_alias get exec
+ /Adobe_AGM_Image where {
+ pop
+ Adobe_AGM_Image/spot_alias 2 copy known{
+ get exec
+ }{
+ pop pop
+ }ifelse
+ } if
+ 100 dict begin
+ /dictstackcount countdictstack def
+ /showpage {} def
+ mark
+} def
+/graphic_cleanup
+{
+ cleartomark
+ dictstackcount 1 countdictstack 1 sub {end}for
+ end
+ AGMCORE_graphicsave restore
+} def
+/compose_error_msg
+{
+ grestoreall initgraphics
+ /Helvetica findfont 10 scalefont setfont
+ /AGMCORE_deltaY 100 def
+ /AGMCORE_deltaX 310 def
+ clippath pathbbox newpath pop pop 36 add exch 36 add exch moveto
+ 0 AGMCORE_deltaY rlineto AGMCORE_deltaX 0 rlineto
+ 0 AGMCORE_deltaY neg rlineto AGMCORE_deltaX neg 0 rlineto closepath
+ 0 AGMCORE_&setgray
+ gsave 1 AGMCORE_&setgray fill grestore
+ 1 setlinewidth gsave stroke grestore
+ currentpoint AGMCORE_deltaY 15 sub add exch 8 add exch moveto
+ /AGMCORE_deltaY 12 def
+ /AGMCORE_tmp 0 def
+ AGMCORE_err_strings exch get
+ {
+ dup 32 eq
+ {
+ pop
+ AGMCORE_str256 0 AGMCORE_tmp getinterval
+ stringwidth pop currentpoint pop add AGMCORE_deltaX 28 add gt
+ {
+ currentpoint AGMCORE_deltaY sub exch pop
+ clippath pathbbox pop pop pop 44 add exch moveto
+ } if
+ AGMCORE_str256 0 AGMCORE_tmp getinterval show ( ) show
+ 0 1 AGMCORE_str256 length 1 sub
+ {
+ AGMCORE_str256 exch 0 put
+ }for
+ /AGMCORE_tmp 0 def
+ }
+ {
+ AGMCORE_str256 exch AGMCORE_tmp xpt
+ /AGMCORE_tmp AGMCORE_tmp 1 add def
+ } ifelse
+ } forall
+} bdf
+/doc_setup{
+ Adobe_AGM_Core begin
+ /AGMCORE_ps_version xdf
+ /AGMCORE_ps_level xdf
+ errordict /AGM_handleerror known not{
+ errordict /AGM_handleerror errordict /handleerror get put
+ errordict /handleerror {
+ Adobe_AGM_Core begin
+ $error /newerror get AGMCORE_cur_err null ne and{
+ $error /newerror false put
+ AGMCORE_cur_err compose_error_msg
+ }if
+ $error /newerror true put
+ end
+ errordict /AGM_handleerror get exec
+ } bind put
+ }if
+ /AGMCORE_environ_ok
+ ps_level AGMCORE_ps_level ge
+ ps_version AGMCORE_ps_version ge and
+ AGMCORE_ps_level -1 eq or
+ def
+ AGMCORE_environ_ok not
+ {/AGMCORE_cur_err /AGMCORE_bad_environ def} if
+ /AGMCORE_&setgray systemdict/setgray get def
+ level2{
+ /AGMCORE_&setcolor systemdict/setcolor get def
+ /AGMCORE_&setcolorspace systemdict/setcolorspace get def
+ }if
+ /AGMCORE_currentbg currentblackgeneration def
+ /AGMCORE_currentucr currentundercolorremoval def
+ /AGMCORE_distilling
+ /product where{
+ pop systemdict/setdistillerparams known product (Adobe PostScript Parser) ne and
+ }{
+ false
+ }ifelse
+ def
+ level2 not{
+ /xput{
+ dup load dup length exch maxlength eq{
+ dup dup load dup
+ length dup 0 eq {pop 1} if 2 mul dict copy def
+ }if
+ load begin
+ def
+ end
+ }def
+ }{
+ /xput{
+ load 3 1 roll put
+ }def
+ }ifelse
+ /AGMCORE_GSTATE AGMCORE_key_known not{
+ /AGMCORE_GSTATE 21 dict def
+ /AGMCORE_tmpmatrix matrix def
+ /AGMCORE_gstack 32 array def
+ /AGMCORE_gstackptr 0 def
+ /AGMCORE_gstacksaveptr 0 def
+ /AGMCORE_gstackframekeys 10 def
+ /AGMCORE_&gsave /gsave ldf
+ /AGMCORE_&grestore /grestore ldf
+ /AGMCORE_&grestoreall /grestoreall ldf
+ /AGMCORE_&save /save ldf
+ /AGMCORE_gdictcopy {
+ begin
+ { def } forall
+ end
+ }def
+ /AGMCORE_gput {
+ AGMCORE_gstack AGMCORE_gstackptr get
+ 3 1 roll
+ put
+ }def
+ /AGMCORE_gget {
+ AGMCORE_gstack AGMCORE_gstackptr get
+ exch
+ get
+ }def
+ /gsave {
+ AGMCORE_&gsave
+ AGMCORE_gstack AGMCORE_gstackptr get
+ AGMCORE_gstackptr 1 add
+ dup 32 ge {limitcheck} if
+ Adobe_AGM_Core exch
+ /AGMCORE_gstackptr xpt
+ AGMCORE_gstack AGMCORE_gstackptr get
+ AGMCORE_gdictcopy
+ }def
+ /grestore {
+ AGMCORE_&grestore
+ AGMCORE_gstackptr 1 sub
+ dup AGMCORE_gstacksaveptr lt {1 add} if
+ Adobe_AGM_Core exch
+ /AGMCORE_gstackptr xpt
+ }def
+ /grestoreall {
+ AGMCORE_&grestoreall
+ Adobe_AGM_Core
+ /AGMCORE_gstackptr AGMCORE_gstacksaveptr put
+ }def
+ /save {
+ AGMCORE_&save
+ AGMCORE_gstack AGMCORE_gstackptr get
+ AGMCORE_gstackptr 1 add
+ dup 32 ge {limitcheck} if
+ Adobe_AGM_Core begin
+ /AGMCORE_gstackptr exch def
+ /AGMCORE_gstacksaveptr AGMCORE_gstackptr def
+ end
+ AGMCORE_gstack AGMCORE_gstackptr get
+ AGMCORE_gdictcopy
+ }def
+ 0 1 AGMCORE_gstack length 1 sub {
+ AGMCORE_gstack exch AGMCORE_gstackframekeys dict put
+ } for
+ }if
+ level3 /AGMCORE_&sysshfill AGMCORE_key_known not and
+ {
+ /AGMCORE_&sysshfill systemdict/shfill get def
+ /AGMCORE_&usrshfill /shfill load def
+ /AGMCORE_&sysmakepattern systemdict/makepattern get def
+ /AGMCORE_&usrmakepattern /makepattern load def
+ }if
+ /currentcmykcolor [0 0 0 0] AGMCORE_gput
+ /currentstrokeadjust false AGMCORE_gput
+ /currentcolorspace [/DeviceGray] AGMCORE_gput
+ /sep_tint 0 AGMCORE_gput
+ /devicen_tints [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] AGMCORE_gput
+ /sep_colorspace_dict null AGMCORE_gput
+ /devicen_colorspace_dict null AGMCORE_gput
+ /indexed_colorspace_dict null AGMCORE_gput
+ /currentcolor_intent () AGMCORE_gput
+ /customcolor_tint 1 AGMCORE_gput
+ <<
+ /MaxPatternItem currentsystemparams /MaxPatternCache get
+ >>
+ setuserparams
+ end
+}def
+/page_setup
+{
+ /setcmykcolor where{
+ pop
+ Adobe_AGM_Core/AGMCORE_&setcmykcolor /setcmykcolor load put
+ }if
+ Adobe_AGM_Core begin
+ /setcmykcolor
+ {
+ 4 copy AGMCORE_cmykbuf astore /currentcmykcolor exch AGMCORE_gput
+ 1 sub 4 1 roll
+ 3 {
+ 3 index add neg dup 0 lt {
+ pop 0
+ } if
+ 3 1 roll
+ } repeat
+ setrgbcolor pop
+ }ndf
+ /currentcmykcolor
+ {
+ /currentcmykcolor AGMCORE_gget aload pop
+ }ndf
+ /setoverprint
+ {
+ pop
+ }ndf
+ /currentoverprint
+ {
+ false
+ }ndf
+ /AGMCORE_deviceDPI 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt def
+ /AGMCORE_cyan_plate 1 0 0 0 test_cmyk_color_plate def
+ /AGMCORE_magenta_plate 0 1 0 0 test_cmyk_color_plate def
+ /AGMCORE_yellow_plate 0 0 1 0 test_cmyk_color_plate def
+ /AGMCORE_black_plate 0 0 0 1 test_cmyk_color_plate def
+ /AGMCORE_plate_ndx
+ AGMCORE_cyan_plate{
+ 0
+ }{
+ AGMCORE_magenta_plate{
+ 1
+ }{
+ AGMCORE_yellow_plate{
+ 2
+ }{
+ AGMCORE_black_plate{
+ 3
+ }{
+ 4
+ }ifelse
+ }ifelse
+ }ifelse
+ }ifelse
+ def
+ /AGMCORE_have_reported_unsupported_color_space false def
+ /AGMCORE_report_unsupported_color_space
+ {
+ AGMCORE_have_reported_unsupported_color_space false eq
+ {
+ (Warning: Job contains content that cannot be separated with on-host methods. This content appears on the black plate, and knocks out all other plates.) ==
+ Adobe_AGM_Core /AGMCORE_have_reported_unsupported_color_space true ddf
+ } if
+ }def
+ /AGMCORE_composite_job
+ AGMCORE_cyan_plate AGMCORE_magenta_plate and AGMCORE_yellow_plate and AGMCORE_black_plate and def
+ /AGMCORE_in_rip_sep
+ /AGMCORE_in_rip_sep where{
+ pop AGMCORE_in_rip_sep
+ }{
+ AGMCORE_distilling
+ {
+ false
+ }{
+ userdict/Adobe_AGM_OnHost_Seps known{
+ false
+ }{
+ level2{
+ currentpagedevice/Separations 2 copy known{
+ get
+ }{
+ pop pop false
+ }ifelse
+ }{
+ false
+ }ifelse
+ }ifelse
+ }ifelse
+ }ifelse
+ def
+ /AGMCORE_producing_seps AGMCORE_composite_job not AGMCORE_in_rip_sep or def
+ /AGMCORE_host_sep AGMCORE_producing_seps AGMCORE_in_rip_sep not and def
+ /AGM_preserve_spots
+ /AGM_preserve_spots where{
+ pop AGM_preserve_spots
+ }{
+ AGMCORE_distilling AGMCORE_producing_seps or
+ }ifelse
+ def
+ /AGM_is_distiller_preserving_spotimages
+ {
+ currentdistillerparams/PreserveOverprintSettings known
+ {
+ currentdistillerparams/PreserveOverprintSettings get
+ {
+ currentdistillerparams/ColorConversionStrategy known
+ {
+ currentdistillerparams/ColorConversionStrategy get
+ /LeaveColorUnchanged eq
+ }{
+ true
+ }ifelse
+ }{
+ false
+ }ifelse
+ }{
+ false
+ }ifelse
+ }def
+ /convert_spot_to_process where {pop}{
+ /convert_spot_to_process
+ {
+ dup map_alias {
+ /Name get exch pop
+ } if
+ dup dup (None) eq exch (All) eq or
+ {
+ pop false
+ }{
+ AGMCORE_host_sep
+ {
+ gsave
+ 1 0 0 0 setcmykcolor currentgray 1 exch sub
+ 0 1 0 0 setcmykcolor currentgray 1 exch sub
+ 0 0 1 0 setcmykcolor currentgray 1 exch sub
+ 0 0 0 1 setcmykcolor currentgray 1 exch sub
+ add add add 0 eq
+ {
+ pop false
+ }{
+ false setoverprint
+ 1 1 1 1 5 -1 roll findcmykcustomcolor 1 setcustomcolor
+ currentgray 0 eq
+ }ifelse
+ grestore
+ }{
+ AGMCORE_distilling
+ {
+ pop AGM_is_distiller_preserving_spotimages not
+ }{
+ Adobe_AGM_Core/AGMCORE_name xddf
+ false
+ Adobe_AGM_Core/AGMCORE_in_pattern known {Adobe_AGM_Core/AGMCORE_in_pattern get}{false} ifelse
+ not currentpagedevice/OverrideSeparations known and
+ {
+ currentpagedevice/OverrideSeparations get
+ {
+ /HqnSpots /ProcSet resourcestatus
+ {
+ pop pop pop true
+ }if
+ }if
+ }if
+ {
+ AGMCORE_name /HqnSpots /ProcSet findresource /TestSpot get exec not
+ }{
+ gsave
+ [/Separation AGMCORE_name /DeviceGray {}]setcolorspace
+ false
+ currentpagedevice/SeparationColorNames 2 copy known
+ {
+ get
+ { AGMCORE_name eq or}forall
+ not
+ }{
+ pop pop pop true
+ }ifelse
+ grestore
+ }ifelse
+ }ifelse
+ }ifelse
+ }ifelse
+ }def
+ }ifelse
+ /convert_to_process where {pop}{
+ /convert_to_process
+ {
+ dup length 0 eq
+ {
+ pop false
+ }{
+ AGMCORE_host_sep
+ {
+ dup true exch
+ {
+ dup (Cyan) eq exch
+ dup (Magenta) eq 3 -1 roll or exch
+ dup (Yellow) eq 3 -1 roll or exch
+ dup (Black) eq 3 -1 roll or
+ {pop}
+ {convert_spot_to_process and}ifelse
+ }
+ forall
+ {
+ true exch
+ {
+ dup (Cyan) eq exch
+ dup (Magenta) eq 3 -1 roll or exch
+ dup (Yellow) eq 3 -1 roll or exch
+ (Black) eq or and
+ }forall
+ not
+ }{pop false}ifelse
+ }{
+ false exch
+ {
+ dup (Cyan) eq exch
+ dup (Magenta) eq 3 -1 roll or exch
+ dup (Yellow) eq 3 -1 roll or exch
+ dup (Black) eq 3 -1 roll or
+ {pop}
+ {convert_spot_to_process or}ifelse
+ }
+ forall
+ }ifelse
+ }ifelse
+ }def
+ }ifelse
+ /AGMCORE_avoid_L2_sep_space
+ version cvr 2012 lt
+ level2 and
+ AGMCORE_producing_seps not and
+ def
+ /AGMCORE_is_cmyk_sep
+ AGMCORE_cyan_plate AGMCORE_magenta_plate or AGMCORE_yellow_plate or AGMCORE_black_plate or
+ def
+ /AGM_avoid_0_cmyk where{
+ pop AGM_avoid_0_cmyk
+ }{
+ AGM_preserve_spots
+ userdict/Adobe_AGM_OnHost_Seps known
+ userdict/Adobe_AGM_InRip_Seps known or
+ not and
+ }ifelse
+ {
+ /setcmykcolor[
+ {
+ 4 copy add add add 0 eq currentoverprint and{
+ pop 0.0005
+ }if
+ }/exec cvx
+ /AGMCORE_&setcmykcolor load dup type/operatortype ne{
+ /exec cvx
+ }if
+ ]cvx def
+ }if
+ AGMCORE_host_sep{
+ /setcolortransfer
+ {
+ AGMCORE_cyan_plate{
+ pop pop pop
+ }{
+ AGMCORE_magenta_plate{
+ 4 3 roll pop pop pop
+ }{
+ AGMCORE_yellow_plate{
+ 4 2 roll pop pop pop
+ }{
+ 4 1 roll pop pop pop
+ }ifelse
+ }ifelse
+ }ifelse
+ settransfer
+ }
+ def
+ /AGMCORE_get_ink_data
+ AGMCORE_cyan_plate{
+ {pop pop pop}
+ }{
+ AGMCORE_magenta_plate{
+ {4 3 roll pop pop pop}
+ }{
+ AGMCORE_yellow_plate{
+ {4 2 roll pop pop pop}
+ }{
+ {4 1 roll pop pop pop}
+ }ifelse
+ }ifelse
+ }ifelse
+ def
+ /AGMCORE_RemoveProcessColorNames
+ {
+ 1 dict begin
+ /filtername
+ {
+ dup /Cyan eq 1 index (Cyan) eq or
+ {pop (_cyan_)}if
+ dup /Magenta eq 1 index (Magenta) eq or
+ {pop (_magenta_)}if
+ dup /Yellow eq 1 index (Yellow) eq or
+ {pop (_yellow_)}if
+ dup /Black eq 1 index (Black) eq or
+ {pop (_black_)}if
+ }def
+ dup type /arraytype eq
+ {[exch {filtername}forall]}
+ {filtername}ifelse
+ end
+ }def
+ /AGMCORE_IsSeparationAProcessColor
+ {
+ dup (Cyan) eq exch dup (Magenta) eq exch dup (Yellow) eq exch (Black) eq or or or
+ }def
+ level3 {
+ /AGMCORE_IsCurrentColor
+ {
+ gsave
+ false setoverprint
+ 1 1 1 1 5 -1 roll findcmykcustomcolor 1 setcustomcolor
+ currentgray 0 eq
+ grestore
+ }def
+ /AGMCORE_filter_functiondatasource
+ {
+ 5 dict begin
+ /data_in xdf
+ data_in type /stringtype eq
+ {
+ /ncomp xdf
+ /comp xdf
+ /string_out data_in length ncomp idiv string def
+ 0 ncomp data_in length 1 sub
+ {
+ string_out exch dup ncomp idiv exch data_in exch ncomp getinterval comp get 255 exch sub put
+ }for
+ string_out
+ }{
+ string /string_in xdf
+ /string_out 1 string def
+ /component xdf
+ [
+ data_in string_in /readstring cvx
+ [component /get cvx 255 /exch cvx /sub cvx string_out /exch cvx 0 /exch cvx /put cvx string_out]cvx
+ [/pop cvx ()]cvx /ifelse cvx
+ ]cvx /ReusableStreamDecode filter
+ }ifelse
+ end
+ }def
+ /AGMCORE_separateShadingFunction
+ {
+ 2 dict begin
+ /paint? xdf
+ /channel xdf
+ begin
+ FunctionType 0 eq
+ {
+ /DataSource channel Range length 2 idiv DataSource AGMCORE_filter_functiondatasource def
+ currentdict /Decode known
+ {/Decode Decode channel 2 mul 2 getinterval def}if
+ paint? not
+ {/Decode [1 1]def}if
+ }if
+ FunctionType 2 eq
+ {
+ paint?
+ {
+ /C0 [C0 channel get 1 exch sub] def
+ /C1 [C1 channel get 1 exch sub] def
+ }{
+ /C0 [1] def
+ /C1 [1] def
+ }ifelse
+ }if
+ FunctionType 3 eq
+ {
+ /Functions [Functions {channel paint? AGMCORE_separateShadingFunction} forall] def
+ }if
+ currentdict /Range known
+ {/Range [0 1] def}if
+ currentdict
+ end
+ end
+ }def
+ /AGMCORE_separateShading
+ {
+ 3 -1 roll begin
+ currentdict /Function known
+ {
+ currentdict /Background known
+ {[1 index{Background 3 index get 1 exch sub}{1}ifelse]/Background xdf}if
+ Function 3 1 roll AGMCORE_separateShadingFunction /Function xdf
+ /ColorSpace [/DeviceGray] def
+ }{
+ ColorSpace dup type /arraytype eq {0 get}if /DeviceCMYK eq
+ {
+ /ColorSpace [/DeviceN [/_cyan_ /_magenta_ /_yellow_ /_black_] /DeviceCMYK {}] def
+ }{
+ ColorSpace dup 1 get AGMCORE_RemoveProcessColorNames 1 exch put
+ }ifelse
+ ColorSpace 0 get /Separation eq
+ {
+ {
+ [1 /exch cvx /sub cvx]cvx
+ }{
+ [/pop cvx 1]cvx
+ }ifelse
+ ColorSpace 3 3 -1 roll put
+ pop
+ }{
+ {
+ [exch ColorSpace 1 get length 1 sub exch sub /index cvx 1 /exch cvx /sub cvx ColorSpace 1 get length 1 add 1 /roll cvx ColorSpace 1 get length{/pop cvx} repeat]cvx
+ }{
+ pop [ColorSpace 1 get length {/pop cvx} repeat cvx 1]cvx
+ }ifelse
+ ColorSpace 3 3 -1 roll bind put
+ }ifelse
+ ColorSpace 2 /DeviceGray put
+ }ifelse
+ end
+ }def
+ /AGMCORE_separateShadingDict
+ {
+ dup /ColorSpace get
+ dup type /arraytype ne
+ {[exch]}if
+ dup 0 get /DeviceCMYK eq
+ {
+ exch begin
+ currentdict
+ AGMCORE_cyan_plate
+ {0 true}if
+ AGMCORE_magenta_plate
+ {1 true}if
+ AGMCORE_yellow_plate
+ {2 true}if
+ AGMCORE_black_plate
+ {3 true}if
+ AGMCORE_plate_ndx 4 eq
+ {0 false}if
+ dup not currentoverprint and
+ {/AGMCORE_ignoreshade true def}if
+ AGMCORE_separateShading
+ currentdict
+ end exch
+ }if
+ dup 0 get /Separation eq
+ {
+ exch begin
+ ColorSpace 1 get dup /None ne exch /All ne and
+ {
+ ColorSpace 1 get AGMCORE_IsCurrentColor AGMCORE_plate_ndx 4 lt and ColorSpace 1 get AGMCORE_IsSeparationAProcessColor not and
+ {
+ ColorSpace 2 get dup type /arraytype eq {0 get}if /DeviceCMYK eq
+ {
+ /ColorSpace
+ [
+ /Separation
+ ColorSpace 1 get
+ /DeviceGray
+ [
+ ColorSpace 3 get /exec cvx
+ 4 AGMCORE_plate_ndx sub -1 /roll cvx
+ 4 1 /roll cvx
+ 3 [/pop cvx]cvx /repeat cvx
+ 1 /exch cvx /sub cvx
+ ]cvx
+ ]def
+ }{
+ AGMCORE_report_unsupported_color_space
+ AGMCORE_black_plate not
+ {
+ currentdict 0 false AGMCORE_separateShading
+ }if
+ }ifelse
+ }{
+ currentdict ColorSpace 1 get AGMCORE_IsCurrentColor
+ 0 exch
+ dup not currentoverprint and
+ {/AGMCORE_ignoreshade true def}if
+ AGMCORE_separateShading
+ }ifelse
+ }if
+ currentdict
+ end exch
+ }if
+ dup 0 get /DeviceN eq
+ {
+ exch begin
+ ColorSpace 1 get convert_to_process
+ {
+ ColorSpace 2 get dup type /arraytype eq {0 get}if /DeviceCMYK eq
+ {
+ /ColorSpace
+ [
+ /DeviceN
+ ColorSpace 1 get
+ /DeviceGray
+ [
+ ColorSpace 3 get /exec cvx
+ 4 AGMCORE_plate_ndx sub -1 /roll cvx
+ 4 1 /roll cvx
+ 3 [/pop cvx]cvx /repeat cvx
+ 1 /exch cvx /sub cvx
+ ]cvx
+ ]def
+ }{
+ AGMCORE_report_unsupported_color_space
+ AGMCORE_black_plate not
+ {
+ currentdict 0 false AGMCORE_separateShading
+ /ColorSpace [/DeviceGray] def
+ }if
+ }ifelse
+ }{
+ currentdict
+ false -1 ColorSpace 1 get
+ {
+ AGMCORE_IsCurrentColor
+ {
+ 1 add
+ exch pop true exch exit
+ }if
+ 1 add
+ }forall
+ exch
+ dup not currentoverprint and
+ {/AGMCORE_ignoreshade true def}if
+ AGMCORE_separateShading
+ }ifelse
+ currentdict
+ end exch
+ }if
+ dup 0 get dup /DeviceCMYK eq exch dup /Separation eq exch /DeviceN eq or or not
+ {
+ exch begin
+ ColorSpace dup type /arraytype eq
+ {0 get}if
+ /DeviceGray ne
+ {
+ AGMCORE_report_unsupported_color_space
+ AGMCORE_black_plate not
+ {
+ ColorSpace 0 get /CIEBasedA eq
+ {
+ /ColorSpace [/Separation /_ciebaseda_ /DeviceGray {}] def
+ }if
+ ColorSpace 0 get dup /CIEBasedABC eq exch dup /CIEBasedDEF eq exch /DeviceRGB eq or or
+ {
+ /ColorSpace [/DeviceN [/_red_ /_green_ /_blue_] /DeviceRGB {}] def
+ }if
+ ColorSpace 0 get /CIEBasedDEFG eq
+ {
+ /ColorSpace [/DeviceN [/_cyan_ /_magenta_ /_yellow_ /_black_] /DeviceCMYK {}]
+ }if
+ currentdict 0 false AGMCORE_separateShading
+ }if
+ }if
+ currentdict
+ end exch
+ }if
+ pop
+ dup /AGMCORE_ignoreshade known
+ {
+ begin
+ /ColorSpace [/Separation (None) /DeviceGray {}] def
+ currentdict end
+ }if
+ }def
+ /shfill
+ {
+ clonedict
+ AGMCORE_separateShadingDict
+ dup /AGMCORE_ignoreshade known
+ {pop}
+ {AGMCORE_&sysshfill}ifelse
+ }def
+ /makepattern
+ {
+ exch
+ dup /PatternType get 2 eq
+ {
+ clonedict
+ begin
+ /Shading Shading AGMCORE_separateShadingDict def
+ currentdict end
+ exch AGMCORE_&sysmakepattern
+ }{
+ exch AGMCORE_&usrmakepattern
+ }ifelse
+ }def
+ }if
+ }if
+ AGMCORE_in_rip_sep{
+ /setcustomcolor
+ {
+ exch aload pop
+ dup 7 1 roll inRip_spot_has_ink not {
+ 4 {4 index mul 4 1 roll}
+ repeat
+ /DeviceCMYK setcolorspace
+ 6 -2 roll pop pop
+ }{
+ Adobe_AGM_Core begin
+ /AGMCORE_k xdf /AGMCORE_y xdf /AGMCORE_m xdf /AGMCORE_c xdf
+ end
+ [/Separation 4 -1 roll /DeviceCMYK
+ {dup AGMCORE_c mul exch dup AGMCORE_m mul exch dup AGMCORE_y mul exch AGMCORE_k mul}
+ ]
+ setcolorspace
+ }ifelse
+ setcolor
+ }ndf
+ /setseparationgray
+ {
+ [/Separation (All) /DeviceGray {}] setcolorspace_opt
+ 1 exch sub setcolor
+ }ndf
+ }{
+ /setseparationgray
+ {
+ AGMCORE_&setgray
+ }ndf
+ }ifelse
+ /findcmykcustomcolor
+ {
+ 5 makereadonlyarray
+ }ndf
+ /setcustomcolor
+ {
+ exch aload pop pop
+ 4 {4 index mul 4 1 roll} repeat
+ setcmykcolor pop
+ }ndf
+ /has_color
+ /colorimage where{
+ AGMCORE_producing_seps{
+ pop true
+ }{
+ systemdict eq
+ }ifelse
+ }{
+ false
+ }ifelse
+ def
+ /map_index
+ {
+ 1 index mul exch getinterval {255 div} forall
+ } bdf
+ /map_indexed_devn
+ {
+ Lookup Names length 3 -1 roll cvi map_index
+ } bdf
+ /n_color_components
+ {
+ base_colorspace_type
+ dup /DeviceGray eq{
+ pop 1
+ }{
+ /DeviceCMYK eq{
+ 4
+ }{
+ 3
+ }ifelse
+ }ifelse
+ }bdf
+ level2{
+ /mo /moveto ldf
+ /li /lineto ldf
+ /cv /curveto ldf
+ /knockout_unitsq
+ {
+ 1 setgray
+ 0 0 1 1 rectfill
+ }def
+ /level2ScreenFreq{
+ begin
+ 60
+ HalftoneType 1 eq{
+ pop Frequency
+ }if
+ HalftoneType 2 eq{
+ pop GrayFrequency
+ }if
+ HalftoneType 5 eq{
+ pop Default level2ScreenFreq
+ }if
+ end
+ }def
+ /currentScreenFreq{
+ currenthalftone level2ScreenFreq
+ }def
+ level2 /setcolorspace AGMCORE_key_known not and{
+ /AGMCORE_&&&setcolorspace /setcolorspace ldf
+ /AGMCORE_ReplaceMappedColor
+ {
+ dup type dup /arraytype eq exch /packedarraytype eq or
+ {
+ dup 0 get dup /Separation eq
+ {
+ pop
+ dup length array copy
+ dup dup 1 get
+ current_spot_alias
+ {
+ dup map_alias
+ {
+ begin
+ /sep_colorspace_dict currentdict AGMCORE_gput
+ pop pop pop
+ [
+ /Separation Name
+ CSA map_csa
+ dup /MappedCSA xdf
+ /sep_colorspace_proc load
+ ]
+ dup Name
+ end
+ }if
+ }if
+ map_reserved_ink_name 1 xpt
+ }{
+ /DeviceN eq
+ {
+ dup length array copy
+ dup dup 1 get [
+ exch {
+ current_spot_alias{
+ dup map_alias{
+ /Name get exch pop
+ }if
+ }if
+ map_reserved_ink_name
+ } forall
+ ] 1 xpt
+ }if
+ }ifelse
+ }if
+ }def
+ /setcolorspace
+ {
+ dup type dup /arraytype eq exch /packedarraytype eq or
+ {
+ dup 0 get /Indexed eq
+ {
+ AGMCORE_distilling
+ {
+ /PhotoshopDuotoneList where
+ {
+ pop false
+ }{
+ true
+ }ifelse
+ }{
+ true
+ }ifelse
+ {
+ aload pop 3 -1 roll
+ AGMCORE_ReplaceMappedColor
+ 3 1 roll 4 array astore
+ }if
+ }{
+ AGMCORE_ReplaceMappedColor
+ }ifelse
+ }if
+ DeviceN_PS2_inRip_seps {AGMCORE_&&&setcolorspace} if
+ }def
+ }if
+ }{
+ /adj
+ {
+ currentstrokeadjust{
+ transform
+ 0.25 sub round 0.25 add exch
+ 0.25 sub round 0.25 add exch
+ itransform
+ }if
+ }def
+ /mo{
+ adj moveto
+ }def
+ /li{
+ adj lineto
+ }def
+ /cv{
+ 6 2 roll adj
+ 6 2 roll adj
+ 6 2 roll adj curveto
+ }def
+ /knockout_unitsq
+ {
+ 1 setgray
+ 8 8 1 [8 0 0 8 0 0] {<ffffffffffffffff>} image
+ }def
+ /currentstrokeadjust{
+ /currentstrokeadjust AGMCORE_gget
+ }def
+ /setstrokeadjust{
+ /currentstrokeadjust exch AGMCORE_gput
+ }def
+ /currentScreenFreq{
+ currentscreen pop pop
+ }def
+ /setcolorspace
+ {
+ /currentcolorspace exch AGMCORE_gput
+ } def
+ /currentcolorspace
+ {
+ /currentcolorspace AGMCORE_gget
+ } def
+ /setcolor_devicecolor
+ {
+ base_colorspace_type
+ dup /DeviceGray eq{
+ pop setgray
+ }{
+ /DeviceCMYK eq{
+ setcmykcolor
+ }{
+ setrgbcolor
+ }ifelse
+ }ifelse
+ }def
+ /setcolor
+ {
+ currentcolorspace 0 get
+ dup /DeviceGray ne{
+ dup /DeviceCMYK ne{
+ dup /DeviceRGB ne{
+ dup /Separation eq{
+ pop
+ currentcolorspace 3 get exec
+ currentcolorspace 2 get
+ }{
+ dup /Indexed eq{
+ pop
+ currentcolorspace 3 get dup type /stringtype eq{
+ currentcolorspace 1 get n_color_components
+ 3 -1 roll map_index
+ }{
+ exec
+ }ifelse
+ currentcolorspace 1 get
+ }{
+ /AGMCORE_cur_err /AGMCORE_invalid_color_space def
+ AGMCORE_invalid_color_space
+ }ifelse
+ }ifelse
+ }if
+ }if
+ }if
+ setcolor_devicecolor
+ } def
+ }ifelse
+ /sop /setoverprint ldf
+ /lw /setlinewidth ldf
+ /lc /setlinecap ldf
+ /lj /setlinejoin ldf
+ /ml /setmiterlimit ldf
+ /dsh /setdash ldf
+ /sadj /setstrokeadjust ldf
+ /gry /setgray ldf
+ /rgb /setrgbcolor ldf
+ /cmyk /setcmykcolor ldf
+ /sep /setsepcolor ldf
+ /devn /setdevicencolor ldf
+ /idx /setindexedcolor ldf
+ /colr /setcolor ldf
+ /csacrd /set_csa_crd ldf
+ /sepcs /setsepcolorspace ldf
+ /devncs /setdevicencolorspace ldf
+ /idxcs /setindexedcolorspace ldf
+ /cp /closepath ldf
+ /clp /clp_npth ldf
+ /eclp /eoclp_npth ldf
+ /f /fill ldf
+ /ef /eofill ldf
+ /@ /stroke ldf
+ /nclp /npth_clp ldf
+ /gset /graphic_setup ldf
+ /gcln /graphic_cleanup ldf
+ currentdict{
+ dup xcheck 1 index type dup /arraytype eq exch /packedarraytype eq or and {
+ bind
+ }if
+ def
+ }forall
+ /currentpagedevice currentpagedevice def
+/getrampcolor {
+/indx exch def
+0 1 NumComp 1 sub {
+dup
+Samples exch get
+dup type /stringtype eq { indx get } if
+exch
+Scaling exch get aload pop
+3 1 roll
+mul add
+} for
+ColorSpaceFamily /Separation eq
+ {
+ sep
+ }
+ {
+ ColorSpaceFamily /DeviceN eq
+ {
+ devn
+ }
+ {
+ setcolor
+ }ifelse
+ }ifelse
+} bind def
+/sssetbackground { aload pop setcolor } bind def
+/RadialShade {
+40 dict begin
+/ColorSpaceFamily exch def
+/background exch def
+/ext1 exch def
+/ext0 exch def
+/BBox exch def
+/r2 exch def
+/c2y exch def
+/c2x exch def
+/r1 exch def
+/c1y exch def
+/c1x exch def
+/rampdict exch def
+/setinkoverprint where {pop /setinkoverprint{pop}def}if
+gsave
+BBox length 0 gt {
+newpath
+BBox 0 get BBox 1 get moveto
+BBox 2 get BBox 0 get sub 0 rlineto
+0 BBox 3 get BBox 1 get sub rlineto
+BBox 2 get BBox 0 get sub neg 0 rlineto
+closepath
+clip
+newpath
+} if
+c1x c2x eq
+{
+c1y c2y lt {/theta 90 def}{/theta 270 def} ifelse
+}
+{
+/slope c2y c1y sub c2x c1x sub div def
+/theta slope 1 atan def
+c2x c1x lt c2y c1y ge and { /theta theta 180 sub def} if
+c2x c1x lt c2y c1y lt and { /theta theta 180 add def} if
+}
+ifelse
+gsave
+clippath
+c1x c1y translate
+theta rotate
+-90 rotate
+{ pathbbox } stopped
+{ 0 0 0 0 } if
+/yMax exch def
+/xMax exch def
+/yMin exch def
+/xMin exch def
+grestore
+xMax xMin eq yMax yMin eq or
+{
+grestore
+end
+}
+{
+/max { 2 copy gt { pop } {exch pop} ifelse } bind def
+/min { 2 copy lt { pop } {exch pop} ifelse } bind def
+rampdict begin
+40 dict begin
+background length 0 gt { background sssetbackground gsave clippath fill grestore } if
+gsave
+c1x c1y translate
+theta rotate
+-90 rotate
+/c2y c1x c2x sub dup mul c1y c2y sub dup mul add sqrt def
+/c1y 0 def
+/c1x 0 def
+/c2x 0 def
+ext0 {
+0 getrampcolor
+c2y r2 add r1 sub 0.0001 lt
+{
+c1x c1y r1 360 0 arcn
+pathbbox
+/aymax exch def
+/axmax exch def
+/aymin exch def
+/axmin exch def
+/bxMin xMin axmin min def
+/byMin yMin aymin min def
+/bxMax xMax axmax max def
+/byMax yMax aymax max def
+bxMin byMin moveto
+bxMax byMin lineto
+bxMax byMax lineto
+bxMin byMax lineto
+bxMin byMin lineto
+eofill
+}
+{
+c2y r1 add r2 le
+{
+c1x c1y r1 0 360 arc
+fill
+}
+{
+c2x c2y r2 0 360 arc fill
+r1 r2 eq
+{
+/p1x r1 neg def
+/p1y c1y def
+/p2x r1 def
+/p2y c1y def
+p1x p1y moveto p2x p2y lineto p2x yMin lineto p1x yMin lineto
+fill
+}
+{
+/AA r2 r1 sub c2y div def
+/theta AA 1 AA dup mul sub sqrt div 1 atan def
+/SS1 90 theta add dup sin exch cos div def
+/p1x r1 SS1 SS1 mul SS1 SS1 mul 1 add div sqrt mul neg def
+/p1y p1x SS1 div neg def
+/SS2 90 theta sub dup sin exch cos div def
+/p2x r1 SS2 SS2 mul SS2 SS2 mul 1 add div sqrt mul def
+/p2y p2x SS2 div neg def
+r1 r2 gt
+{
+/L1maxX p1x yMin p1y sub SS1 div add def
+/L2maxX p2x yMin p2y sub SS2 div add def
+}
+{
+/L1maxX 0 def
+/L2maxX 0 def
+}ifelse
+p1x p1y moveto p2x p2y lineto L2maxX L2maxX p2x sub SS2 mul p2y add lineto
+L1maxX L1maxX p1x sub SS1 mul p1y add lineto
+fill
+}
+ifelse
+}
+ifelse
+} ifelse
+} if
+c1x c2x sub dup mul
+c1y c2y sub dup mul
+add 0.5 exp
+0 dtransform
+dup mul exch dup mul add 0.5 exp 72 div
+0 72 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt
+72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt
+1 index 1 index lt { exch } if pop
+/hires exch def
+hires mul
+/numpix exch def
+/numsteps NumSamples def
+/rampIndxInc 1 def
+/subsampling false def
+numpix 0 ne
+{
+NumSamples numpix div 0.5 gt
+{
+/numsteps numpix 2 div round cvi dup 1 le { pop 2 } if def
+/rampIndxInc NumSamples 1 sub numsteps div def
+/subsampling true def
+} if
+} if
+/xInc c2x c1x sub numsteps div def
+/yInc c2y c1y sub numsteps div def
+/rInc r2 r1 sub numsteps div def
+/cx c1x def
+/cy c1y def
+/radius r1 def
+newpath
+xInc 0 eq yInc 0 eq rInc 0 eq and and
+{
+0 getrampcolor
+cx cy radius 0 360 arc
+stroke
+NumSamples 1 sub getrampcolor
+cx cy radius 72 hires div add 0 360 arc
+0 setlinewidth
+stroke
+}
+{
+0
+numsteps
+{
+dup
+subsampling { round cvi } if
+getrampcolor
+cx cy radius 0 360 arc
+/cx cx xInc add def
+/cy cy yInc add def
+/radius radius rInc add def
+cx cy radius 360 0 arcn
+eofill
+rampIndxInc add
+}
+repeat
+pop
+} ifelse
+ext1 {
+c2y r2 add r1 lt
+{
+c2x c2y r2 0 360 arc
+fill
+}
+{
+c2y r1 add r2 sub 0.0001 le
+{
+c2x c2y r2 360 0 arcn
+pathbbox
+/aymax exch def
+/axmax exch def
+/aymin exch def
+/axmin exch def
+/bxMin xMin axmin min def
+/byMin yMin aymin min def
+/bxMax xMax axmax max def
+/byMax yMax aymax max def
+bxMin byMin moveto
+bxMax byMin lineto
+bxMax byMax lineto
+bxMin byMax lineto
+bxMin byMin lineto
+eofill
+}
+{
+c2x c2y r2 0 360 arc fill
+r1 r2 eq
+{
+/p1x r2 neg def
+/p1y c2y def
+/p2x r2 def
+/p2y c2y def
+p1x p1y moveto p2x p2y lineto p2x yMax lineto p1x yMax lineto
+fill
+}
+{
+/AA r2 r1 sub c2y div def
+/theta AA 1 AA dup mul sub sqrt div 1 atan def
+/SS1 90 theta add dup sin exch cos div def
+/p1x r2 SS1 SS1 mul SS1 SS1 mul 1 add div sqrt mul neg def
+/p1y c2y p1x SS1 div sub def
+/SS2 90 theta sub dup sin exch cos div def
+/p2x r2 SS2 SS2 mul SS2 SS2 mul 1 add div sqrt mul def
+/p2y c2y p2x SS2 div sub def
+r1 r2 lt
+{
+/L1maxX p1x yMax p1y sub SS1 div add def
+/L2maxX p2x yMax p2y sub SS2 div add def
+}
+{
+/L1maxX 0 def
+/L2maxX 0 def
+}ifelse
+p1x p1y moveto p2x p2y lineto L2maxX L2maxX p2x sub SS2 mul p2y add lineto
+L1maxX L1maxX p1x sub SS1 mul p1y add lineto
+fill
+}
+ifelse
+}
+ifelse
+} ifelse
+} if
+grestore
+grestore
+end
+end
+end
+} ifelse
+} bind def
+/GenStrips {
+40 dict begin
+/ColorSpaceFamily exch def
+/background exch def
+/ext1 exch def
+/ext0 exch def
+/BBox exch def
+/y2 exch def
+/x2 exch def
+/y1 exch def
+/x1 exch def
+/rampdict exch def
+/setinkoverprint where {pop /setinkoverprint{pop}def}if
+gsave
+BBox length 0 gt {
+newpath
+BBox 0 get BBox 1 get moveto
+BBox 2 get BBox 0 get sub 0 rlineto
+0 BBox 3 get BBox 1 get sub rlineto
+BBox 2 get BBox 0 get sub neg 0 rlineto
+closepath
+clip
+newpath
+} if
+x1 x2 eq
+{
+y1 y2 lt {/theta 90 def}{/theta 270 def} ifelse
+}
+{
+/slope y2 y1 sub x2 x1 sub div def
+/theta slope 1 atan def
+x2 x1 lt y2 y1 ge and { /theta theta 180 sub def} if
+x2 x1 lt y2 y1 lt and { /theta theta 180 add def} if
+}
+ifelse
+gsave
+clippath
+x1 y1 translate
+theta rotate
+{ pathbbox } stopped
+{ 0 0 0 0 } if
+/yMax exch def
+/xMax exch def
+/yMin exch def
+/xMin exch def
+grestore
+xMax xMin eq yMax yMin eq or
+{
+grestore
+end
+}
+{
+rampdict begin
+20 dict begin
+background length 0 gt { background sssetbackground gsave clippath fill grestore } if
+gsave
+x1 y1 translate
+theta rotate
+/xStart 0 def
+/xEnd x2 x1 sub dup mul y2 y1 sub dup mul add 0.5 exp def
+/ySpan yMax yMin sub def
+/numsteps NumSamples def
+/rampIndxInc 1 def
+/subsampling false def
+xStart 0 transform
+xEnd 0 transform
+3 -1 roll
+sub dup mul
+3 1 roll
+sub dup mul
+add 0.5 exp 72 div
+0 72 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt
+72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt
+1 index 1 index lt { exch } if pop
+mul
+/numpix exch def
+numpix 0 ne
+{
+NumSamples numpix div 0.5 gt
+{
+/numsteps numpix 2 div round cvi dup 1 le { pop 2 } if def
+/rampIndxInc NumSamples 1 sub numsteps div def
+/subsampling true def
+} if
+} if
+ext0 {
+0 getrampcolor
+xMin xStart lt
+{ xMin yMin xMin neg ySpan rectfill } if
+} if
+/xInc xEnd xStart sub numsteps div def
+/x xStart def
+0
+numsteps
+{
+dup
+subsampling { round cvi } if
+getrampcolor
+x yMin xInc ySpan rectfill
+/x x xInc add def
+rampIndxInc add
+}
+repeat
+pop
+ext1 {
+xMax xEnd gt
+{ xEnd yMin xMax xEnd sub ySpan rectfill } if
+} if
+grestore
+grestore
+end
+end
+end
+} ifelse
+} bind def
+}def
+/page_trailer
+{
+ end
+}def
+/doc_trailer{
+}def
+systemdict /findcolorrendering known{
+ /findcolorrendering systemdict /findcolorrendering get def
+}if
+systemdict /setcolorrendering known{
+ /setcolorrendering systemdict /setcolorrendering get def
+}if
+/test_cmyk_color_plate
+{
+ gsave
+ setcmykcolor currentgray 1 ne
+ grestore
+}def
+/inRip_spot_has_ink
+{
+ dup Adobe_AGM_Core/AGMCORE_name xddf
+ convert_spot_to_process not
+}def
+/map255_to_range
+{
+ 1 index sub
+ 3 -1 roll 255 div mul add
+}def
+/set_csa_crd
+{
+ /sep_colorspace_dict null AGMCORE_gput
+ begin
+ CSA map_csa setcolorspace_opt
+ set_crd
+ end
+}
+def
+/setsepcolor
+{
+ /sep_colorspace_dict AGMCORE_gget begin
+ dup /sep_tint exch AGMCORE_gput
+ TintProc
+ end
+} def
+/setdevicencolor
+{
+ /devicen_colorspace_dict AGMCORE_gget begin
+ Names length copy
+ Names length 1 sub -1 0
+ {
+ /devicen_tints AGMCORE_gget 3 1 roll xpt
+ } for
+ TintProc
+ end
+} def
+/sep_colorspace_proc
+{
+ Adobe_AGM_Core/AGMCORE_tmp xddf
+ /sep_colorspace_dict AGMCORE_gget begin
+ currentdict/Components known{
+ Components aload pop
+ TintMethod/Lab eq{
+ 2 {AGMCORE_tmp mul NComponents 1 roll} repeat
+ LMax sub AGMCORE_tmp mul LMax add NComponents 1 roll
+ }{
+ TintMethod/Subtractive eq{
+ NComponents{
+ AGMCORE_tmp mul NComponents 1 roll
+ }repeat
+ }{
+ NComponents{
+ 1 sub AGMCORE_tmp mul 1 add NComponents 1 roll
+ } repeat
+ }ifelse
+ }ifelse
+ }{
+ ColorLookup AGMCORE_tmp ColorLookup length 1 sub mul round cvi get
+ aload pop
+ }ifelse
+ end
+} def
+/sep_colorspace_gray_proc
+{
+ Adobe_AGM_Core/AGMCORE_tmp xddf
+ /sep_colorspace_dict AGMCORE_gget begin
+ GrayLookup AGMCORE_tmp GrayLookup length 1 sub mul round cvi get
+ end
+} def
+/sep_proc_name
+{
+ dup 0 get
+ dup /DeviceRGB eq exch /DeviceCMYK eq or level2 not and has_color not and{
+ pop [/DeviceGray]
+ /sep_colorspace_gray_proc
+ }{
+ /sep_colorspace_proc
+ }ifelse
+} def
+/setsepcolorspace
+{
+ current_spot_alias{
+ dup begin
+ Name map_alias{
+ exch pop
+ }if
+ end
+ }if
+ dup /sep_colorspace_dict exch AGMCORE_gput
+ begin
+ /MappedCSA CSA map_csa def
+ Adobe_AGM_Core/AGMCORE_sep_special Name dup () eq exch (All) eq or ddf
+ AGMCORE_avoid_L2_sep_space{
+ [/Indexed MappedCSA sep_proc_name 255 exch
+ { 255 div } /exec cvx 3 -1 roll [ 4 1 roll load /exec cvx ] cvx
+ ] setcolorspace_opt
+ /TintProc {
+ 255 mul round cvi setcolor
+ }bdf
+ }{
+ MappedCSA 0 get /DeviceCMYK eq
+ currentdict/Components known and
+ AGMCORE_sep_special not and{
+ /TintProc [
+ Components aload pop Name findcmykcustomcolor
+ /exch cvx /setcustomcolor cvx
+ ] cvx bdf
+ }{
+ AGMCORE_host_sep Name (All) eq and{
+ /TintProc {
+ 1 exch sub setseparationgray
+ }bdf
+ }{
+ AGMCORE_in_rip_sep MappedCSA 0 get /DeviceCMYK eq and
+ AGMCORE_host_sep or
+ Name () eq and{
+ /TintProc [
+ MappedCSA sep_proc_name exch 0 get /DeviceCMYK eq{
+ cvx /setcmykcolor cvx
+ }{
+ cvx /setgray cvx
+ }ifelse
+ ] cvx bdf
+ }{
+ AGMCORE_producing_seps MappedCSA 0 get dup /DeviceCMYK eq exch /DeviceGray eq or and AGMCORE_sep_special not and{
+ /TintProc [
+ /dup cvx
+ MappedCSA sep_proc_name cvx exch
+ 0 get /DeviceGray eq{
+ 1 /exch cvx /sub cvx 0 0 0 4 -1 /roll cvx
+ }if
+ /Name cvx /findcmykcustomcolor cvx /exch cvx
+ AGMCORE_host_sep{
+ AGMCORE_is_cmyk_sep
+ /Name cvx
+ /AGMCORE_IsSeparationAProcessColor load /exec cvx
+ /not cvx /and cvx
+ }{
+ Name inRip_spot_has_ink not
+ }ifelse
+ [
+ /pop cvx 1
+ ] cvx /if cvx
+ /setcustomcolor cvx
+ ] cvx bdf
+ }{
+ /TintProc /setcolor ldf
+ [/Separation Name MappedCSA sep_proc_name load ] setcolorspace_opt
+ }ifelse
+ }ifelse
+ }ifelse
+ }ifelse
+ }ifelse
+ set_crd
+ setsepcolor
+ end
+} def
+/additive_blend
+{
+ 3 dict begin
+ /numarrays xdf
+ /numcolors xdf
+ 0 1 numcolors 1 sub
+ {
+ /c1 xdf
+ 1
+ 0 1 numarrays 1 sub
+ {
+ 1 exch add /index cvx
+ c1 /get cvx /mul cvx
+ }for
+ numarrays 1 add 1 /roll cvx
+ }for
+ numarrays [/pop cvx] cvx /repeat cvx
+ end
+}def
+/subtractive_blend
+{
+ 3 dict begin
+ /numarrays xdf
+ /numcolors xdf
+ 0 1 numcolors 1 sub
+ {
+ /c1 xdf
+ 1 1
+ 0 1 numarrays 1 sub
+ {
+ 1 3 3 -1 roll add /index cvx
+ c1 /get cvx /sub cvx /mul cvx
+ }for
+ /sub cvx
+ numarrays 1 add 1 /roll cvx
+ }for
+ numarrays [/pop cvx] cvx /repeat cvx
+ end
+}def
+/exec_tint_transform
+{
+ /TintProc [
+ /TintTransform cvx /setcolor cvx
+ ] cvx bdf
+ MappedCSA setcolorspace_opt
+} bdf
+/devn_makecustomcolor
+{
+ 2 dict begin
+ /names_index xdf
+ /Names xdf
+ 1 1 1 1 Names names_index get findcmykcustomcolor
+ /devicen_tints AGMCORE_gget names_index get setcustomcolor
+ Names length {pop} repeat
+ end
+} bdf
+/setdevicencolorspace
+{
+ dup /AliasedColorants known {false}{true}ifelse
+ current_spot_alias and {
+ 6 dict begin
+ /names_index 0 def
+ dup /names_len exch /Names get length def
+ /new_names names_len array def
+ /new_LookupTables names_len array def
+ /alias_cnt 0 def
+ dup /Names get
+ {
+ dup map_alias {
+ exch pop
+ dup /ColorLookup known {
+ dup begin
+ new_LookupTables names_index ColorLookup put
+ end
+ }{
+ dup /Components known {
+ dup begin
+ new_LookupTables names_index Components put
+ end
+ }{
+ dup begin
+ new_LookupTables names_index [null null null null] put
+ end
+ } ifelse
+ } ifelse
+ new_names names_index 3 -1 roll /Name get put
+ /alias_cnt alias_cnt 1 add def
+ }{
+ /name xdf
+ new_names names_index name put
+ dup /LookupTables known {
+ dup begin
+ new_LookupTables names_index LookupTables names_index get put
+ end
+ }{
+ dup begin
+ new_LookupTables names_index [null null null null] put
+ end
+ } ifelse
+ } ifelse
+ /names_index names_index 1 add def
+ } forall
+ alias_cnt 0 gt {
+ /AliasedColorants true def
+ 0 1 names_len 1 sub {
+ /names_index xdf
+ new_LookupTables names_index get 0 get null eq {
+ dup /Names get names_index get /name xdf
+ name (Cyan) eq name (Magenta) eq name (Yellow) eq name (Black) eq
+ or or or not {
+ /AliasedColorants false def
+ exit
+ } if
+ } if
+ } for
+ AliasedColorants {
+ dup begin
+ /Names new_names def
+ /AliasedColorants true def
+ /LookupTables new_LookupTables def
+ currentdict /TTTablesIdx known not {
+ /TTTablesIdx -1 def
+ } if
+ currentdict /NComponents known not {
+ /NComponents TintMethod /Subtractive eq {4}{3}ifelse def
+ } if
+ end
+ } if
+ }if
+ end
+ } if
+ dup /devicen_colorspace_dict exch AGMCORE_gput
+ begin
+ /MappedCSA CSA map_csa def
+ currentdict /AliasedColorants known {
+ AliasedColorants
+ }{
+ false
+ } ifelse
+ /TintTransform load type /nulltype eq or {
+ /TintTransform [
+ 0 1 Names length 1 sub
+ {
+ /TTTablesIdx TTTablesIdx 1 add def
+ dup LookupTables exch get dup 0 get null eq
+ {
+ 1 index
+ Names exch get
+ dup (Cyan) eq
+ {
+ pop exch
+ LookupTables length exch sub
+ /index cvx
+ 0 0 0
+ }
+ {
+ dup (Magenta) eq
+ {
+ pop exch
+ LookupTables length exch sub
+ /index cvx
+ 0 /exch cvx 0 0
+ }
+ {
+ (Yellow) eq
+ {
+ exch
+ LookupTables length exch sub
+ /index cvx
+ 0 0 3 -1 /roll cvx 0
+ }
+ {
+ exch
+ LookupTables length exch sub
+ /index cvx
+ 0 0 0 4 -1 /roll cvx
+ } ifelse
+ } ifelse
+ } ifelse
+ 5 -1 /roll cvx /astore cvx
+ }
+ {
+ dup length 1 sub
+ LookupTables length 4 -1 roll sub 1 add
+ /index cvx /mul cvx /round cvx /cvi cvx /get cvx
+ } ifelse
+ Names length TTTablesIdx add 1 add 1 /roll cvx
+ } for
+ Names length [/pop cvx] cvx /repeat cvx
+ NComponents Names length
+ TintMethod /Subtractive eq
+ {
+ subtractive_blend
+ }
+ {
+ additive_blend
+ } ifelse
+ ] cvx bdf
+ } if
+ AGMCORE_host_sep {
+ Names convert_to_process {
+ exec_tint_transform
+ }
+ {
+ currentdict /AliasedColorants known {
+ AliasedColorants not
+ }{
+ false
+ } ifelse
+ 5 dict begin
+ /AvoidAliasedColorants xdf
+ /painted? false def
+ /names_index 0 def
+ /names_len Names length def
+ Names {
+ AvoidAliasedColorants {
+ /currentspotalias current_spot_alias def
+ false set_spot_alias
+ } if
+ AGMCORE_is_cmyk_sep {
+ dup (Cyan) eq AGMCORE_cyan_plate and exch
+ dup (Magenta) eq AGMCORE_magenta_plate and exch
+ dup (Yellow) eq AGMCORE_yellow_plate and exch
+ (Black) eq AGMCORE_black_plate and or or or {
+ /devicen_colorspace_dict AGMCORE_gget /TintProc [
+ Names names_index /devn_makecustomcolor cvx
+ ] cvx ddf
+ /painted? true def
+ } if
+ painted? {exit} if
+ }{
+ 0 0 0 0 5 -1 roll findcmykcustomcolor 1 setcustomcolor currentgray 0 eq {
+ /devicen_colorspace_dict AGMCORE_gget /TintProc [
+ Names names_index /devn_makecustomcolor cvx
+ ] cvx ddf
+ /painted? true def
+ exit
+ } if
+ } ifelse
+ AvoidAliasedColorants {
+ currentspotalias set_spot_alias
+ } if
+ /names_index names_index 1 add def
+ } forall
+ painted? {
+ /devicen_colorspace_dict AGMCORE_gget /names_index names_index put
+ }{
+ /devicen_colorspace_dict AGMCORE_gget /TintProc [
+ names_len [/pop cvx] cvx /repeat cvx 1 /setseparationgray cvx
+ 0 0 0 0 () /findcmykcustomcolor cvx 0 /setcustomcolor cvx
+ ] cvx ddf
+ } ifelse
+ end
+ } ifelse
+ }
+ {
+ AGMCORE_in_rip_sep {
+ Names convert_to_process not
+ }{
+ level3
+ } ifelse
+ {
+ [/DeviceN Names MappedCSA /TintTransform load] setcolorspace_opt
+ /TintProc level3 not AGMCORE_in_rip_sep and {
+ [
+ Names /length cvx [/pop cvx] cvx /repeat cvx
+ ] cvx bdf
+ }{
+ /setcolor ldf
+ } ifelse
+ }{
+ exec_tint_transform
+ } ifelse
+ } ifelse
+ set_crd
+ /AliasedColorants false def
+ end
+} def
+/setindexedcolorspace
+{
+ dup /indexed_colorspace_dict exch AGMCORE_gput
+ begin
+ currentdict /CSD known {
+ CSD get_csd /Names known {
+ CSD get_csd begin
+ currentdict devncs
+ AGMCORE_host_sep{
+ 4 dict begin
+ /devnCompCnt Names length def
+ /NewLookup HiVal 1 add string def
+ 0 1 HiVal {
+ /tableIndex xdf
+ Lookup dup type /stringtype eq {
+ devnCompCnt tableIndex map_index
+ }{
+ exec
+ } ifelse
+ setdevicencolor
+ currentgray
+ tableIndex exch
+ HiVal mul cvi
+ NewLookup 3 1 roll put
+ } for
+ [/Indexed currentcolorspace HiVal NewLookup] setcolorspace_opt
+ end
+ }{
+ level3
+ {
+ [/Indexed [/DeviceN Names MappedCSA /TintTransform load] HiVal Lookup] setcolorspace_opt
+ }{
+ [/Indexed MappedCSA HiVal
+ [
+ Lookup dup type /stringtype eq
+ {/exch cvx CSD get_csd /Names get length dup /mul cvx exch /getinterval cvx {255 div} /forall cvx}
+ {/exec cvx}ifelse
+ /TintTransform load /exec cvx
+ ]cvx
+ ]setcolorspace_opt
+ }ifelse
+ } ifelse
+ end
+ }{
+ } ifelse
+ set_crd
+ }
+ {
+ /MappedCSA CSA map_csa def
+ AGMCORE_host_sep level2 not and{
+ 0 0 0 0 setcmykcolor
+ }{
+ [/Indexed MappedCSA
+ level2 not has_color not and{
+ dup 0 get dup /DeviceRGB eq exch /DeviceCMYK eq or{
+ pop [/DeviceGray]
+ }if
+ HiVal GrayLookup
+ }{
+ HiVal
+ currentdict/RangeArray known{
+ {
+ /indexed_colorspace_dict AGMCORE_gget begin
+ Lookup exch
+ dup HiVal gt{
+ pop HiVal
+ }if
+ NComponents mul NComponents getinterval {} forall
+ NComponents 1 sub -1 0{
+ RangeArray exch 2 mul 2 getinterval aload pop map255_to_range
+ NComponents 1 roll
+ }for
+ end
+ } bind
+ }{
+ Lookup
+ }ifelse
+ }ifelse
+ ] setcolorspace_opt
+ set_crd
+ }ifelse
+ }ifelse
+ end
+}def
+/setindexedcolor
+{
+ AGMCORE_host_sep {
+ /indexed_colorspace_dict AGMCORE_gget dup /CSD known {
+ begin
+ CSD get_csd begin
+ map_indexed_devn
+ devn
+ end
+ end
+ }{
+ AGMCORE_gget/Lookup get 4 3 -1 roll map_index
+ pop setcmykcolor
+ } ifelse
+ }{
+ level3 not AGMCORE_in_rip_sep and /indexed_colorspace_dict AGMCORE_gget /CSD known and {
+ /indexed_colorspace_dict AGMCORE_gget /CSD get get_csd begin
+ map_indexed_devn
+ devn
+ end
+ }
+ {
+ setcolor
+ } ifelse
+ }ifelse
+} def
+/ignoreimagedata
+{
+ currentoverprint not{
+ gsave
+ dup clonedict begin
+ 1 setgray
+ /Decode [0 1] def
+ /DataSource <FF> def
+ /MultipleDataSources false def
+ /BitsPerComponent 8 def
+ currentdict end
+ systemdict /image get exec
+ grestore
+ }if
+ consumeimagedata
+}def
+/add_csa
+{
+ Adobe_AGM_Core begin
+ /AGMCORE_CSA_cache xput
+ end
+}def
+/get_csa_by_name
+{
+ dup type dup /nametype eq exch /stringtype eq or{
+ Adobe_AGM_Core begin
+ 1 dict begin
+ /name xdf
+ AGMCORE_CSA_cache
+ {
+ 0 get name eq {
+ exit
+ }{
+ pop
+ } ifelse
+ }forall
+ end
+ end
+ }{
+ pop
+ } ifelse
+}def
+/map_csa
+{
+ dup type /nametype eq{
+ Adobe_AGM_Core/AGMCORE_CSA_cache get exch get
+ }if
+}def
+/add_csd
+{
+ Adobe_AGM_Core begin
+ /AGMCORE_CSD_cache xput
+ end
+}def
+/get_csd
+{
+ dup type /nametype eq{
+ Adobe_AGM_Core/AGMCORE_CSD_cache get exch get
+ }if
+}def
+/pattern_buf_init
+{
+ /count get 0 0 put
+} def
+/pattern_buf_next
+{
+ dup /count get dup 0 get
+ dup 3 1 roll
+ 1 add 0 xpt
+ get
+} def
+/cachepattern_compress
+{
+ 5 dict begin
+ currentfile exch 0 exch /SubFileDecode filter /ReadFilter exch def
+ /patarray 20 dict def
+ /string_size 16000 def
+ /readbuffer string_size string def
+ currentglobal true setglobal
+ patarray 1 array dup 0 1 put /count xpt
+ setglobal
+ /LZWFilter
+ {
+ exch
+ dup length 0 eq {
+ pop
+ }{
+ patarray dup length 1 sub 3 -1 roll put
+ } ifelse
+ {string_size}{0}ifelse string
+ } /LZWEncode filter def
+ {
+ ReadFilter readbuffer readstring
+ exch LZWFilter exch writestring
+ not {exit} if
+ } loop
+ LZWFilter closefile
+ patarray
+ end
+}def
+/cachepattern
+{
+ 2 dict begin
+ currentfile exch 0 exch /SubFileDecode filter /ReadFilter exch def
+ /patarray 20 dict def
+ currentglobal true setglobal
+ patarray 1 array dup 0 1 put /count xpt
+ setglobal
+ {
+ ReadFilter 16000 string readstring exch
+ patarray dup length 1 sub 3 -1 roll put
+ not {exit} if
+ } loop
+ patarray dup dup length 1 sub () put
+ end
+}def
+/add_pattern
+{
+ Adobe_AGM_Core begin
+ /AGMCORE_pattern_cache xput
+ end
+}def
+/get_pattern
+{
+ dup type /nametype eq{
+ Adobe_AGM_Core/AGMCORE_pattern_cache get exch get
+ dup wrap_paintproc
+ }if
+}def
+/wrap_paintproc
+{
+ statusdict /currentfilenameextend known{
+ begin
+ /OldPaintProc /PaintProc load def
+ /PaintProc
+ {
+ mark exch
+ dup /OldPaintProc get stopped
+ {closefile restore end} if
+ cleartomark
+ } def
+ end
+ } {pop} ifelse
+} def
+/make_pattern
+{
+ dup matrix currentmatrix matrix concatmatrix 0 0 3 2 roll itransform
+ exch 3 index /XStep get 1 index exch 2 copy div cvi mul sub sub
+ exch 3 index /YStep get 1 index exch 2 copy div cvi mul sub sub
+ matrix translate exch matrix concatmatrix
+ 1 index begin
+ BBox 0 get XStep div cvi XStep mul /xshift exch neg def
+ BBox 1 get YStep div cvi YStep mul /yshift exch neg def
+ BBox 0 get xshift add
+ BBox 1 get yshift add
+ BBox 2 get xshift add
+ BBox 3 get yshift add
+ 4 array astore
+ /BBox exch def
+ [ xshift yshift /translate load null /exec load ] dup
+ 3 /PaintProc load put cvx /PaintProc exch def
+ end
+ gsave 0 setgray
+ makepattern
+ grestore
+}def
+/set_pattern
+{
+ dup /PatternType get 1 eq{
+ dup /PaintType get 1 eq{
+ currentoverprint sop [/DeviceGray] setcolorspace 0 setgray
+ }if
+ }if
+ setpattern
+}def
+/setcolorspace_opt
+{
+ dup currentcolorspace eq{
+ pop
+ }{
+ setcolorspace
+ }ifelse
+}def
+/updatecolorrendering
+{
+ currentcolorrendering/Intent known{
+ currentcolorrendering/Intent get
+ }{
+ null
+ }ifelse
+ Intent ne{
+ false
+ Intent
+ AGMCORE_CRD_cache {
+ exch pop
+ begin
+ dup Intent eq{
+ currentdict setcolorrendering_opt
+ end
+ exch pop true exch
+ exit
+ }if
+ end
+ } forall
+ pop
+ not{
+ systemdict /findcolorrendering known{
+ Intent findcolorrendering pop
+ /ColorRendering findresource
+ dup length dict copy
+ setcolorrendering_opt
+ }if
+ }if
+ }if
+} def
+/add_crd
+{
+ AGMCORE_CRD_cache 3 1 roll put
+}def
+/set_crd
+{
+ AGMCORE_host_sep not level2 and{
+ currentdict/CRD known{
+ AGMCORE_CRD_cache CRD get dup null ne{
+ setcolorrendering_opt
+ }{
+ pop
+ }ifelse
+ }{
+ currentdict/Intent known{
+ updatecolorrendering
+ }if
+ }ifelse
+ currentcolorspace dup type /arraytype eq
+ {0 get}if
+ /DeviceRGB eq
+ {
+ currentdict/UCR known
+ {/UCR}{/AGMCORE_currentucr}ifelse
+ load setundercolorremoval
+ currentdict/BG known
+ {/BG}{/AGMCORE_currentbg}ifelse
+ load setblackgeneration
+ }if
+ }if
+}def
+/setcolorrendering_opt
+{
+ dup currentcolorrendering eq{
+ pop
+ }{
+ begin
+ /Intent Intent def
+ currentdict
+ end
+ setcolorrendering
+ }ifelse
+}def
+/cpaint_gcomp
+{
+ convert_to_process Adobe_AGM_Core/AGMCORE_ConvertToProcess xddf
+ Adobe_AGM_Core/AGMCORE_ConvertToProcess get not
+ {
+ (%end_cpaint_gcomp) flushinput
+ }if
+}def
+/cpaint_gsep
+{
+ Adobe_AGM_Core/AGMCORE_ConvertToProcess get
+ {
+ (%end_cpaint_gsep) flushinput
+ }if
+}def
+/cpaint_gend
+{
+ newpath
+}def
+/path_rez
+{
+ dup 0 ne{
+ AGMCORE_deviceDPI exch div
+ dup 1 lt{
+ pop 1
+ }if
+ setflat
+ }{
+ pop
+ }ifelse
+}def
+/set_spot_alias_ary
+{
+ /AGMCORE_SpotAliasAry where{
+ pop pop
+ }{
+ Adobe_AGM_Core/AGMCORE_SpotAliasAry xddf
+ true set_spot_alias
+ }ifelse
+}def
+/set_spot_alias
+{
+ /AGMCORE_SpotAliasAry where{
+ /AGMCORE_current_spot_alias 3 -1 roll put
+ }{
+ pop
+ }ifelse
+}def
+/current_spot_alias
+{
+ /AGMCORE_SpotAliasAry where{
+ /AGMCORE_current_spot_alias get
+ }{
+ false
+ }ifelse
+}def
+/map_alias
+{
+ /AGMCORE_SpotAliasAry where{
+ begin
+ /AGMCORE_name xdf
+ false
+ AGMCORE_SpotAliasAry{
+ dup/Name get AGMCORE_name eq{
+ save exch
+ /Adobe_AGM_Core currentdict def
+ /CSD get get_csd
+ exch restore
+ exch pop true
+ exit
+ }{
+ pop
+ }ifelse
+ }forall
+ end
+ }{
+ pop false
+ }ifelse
+}bdf
+/spot_alias
+{
+ true set_spot_alias
+ /AGMCORE_&setcustomcolor AGMCORE_key_known not {
+ Adobe_AGM_Core/AGMCORE_&setcustomcolor /setcustomcolor load put
+ } if
+ /customcolor_tint 1 AGMCORE_gput
+ Adobe_AGM_Core begin
+ /setcustomcolor
+ {
+ dup /customcolor_tint exch AGMCORE_gput
+ current_spot_alias{
+ 1 index 4 get map_alias{
+ mark 3 1 roll
+ setsepcolorspace
+ counttomark 0 ne{
+ setsepcolor
+ }if
+ pop
+ pop
+ }{
+ AGMCORE_&setcustomcolor
+ }ifelse
+ }{
+ AGMCORE_&setcustomcolor
+ }ifelse
+ }bdf
+ end
+}def
+/begin_feature
+{
+ Adobe_AGM_Core/AGMCORE_feature_dictCount countdictstack put
+ count Adobe_AGM_Core/AGMCORE_feature_opCount 3 -1 roll put
+ {Adobe_AGM_Core/AGMCORE_feature_ctm matrix currentmatrix put}if
+}def
+/end_feature
+{
+ 2 dict begin
+ /spd /setpagedevice load def
+ /setpagedevice { get_gstate spd set_gstate } def
+ stopped{$error/newerror false put}if
+ end
+ count Adobe_AGM_Core/AGMCORE_feature_opCount get sub dup 0 gt{{pop}repeat}{pop}ifelse
+ countdictstack Adobe_AGM_Core/AGMCORE_feature_dictCount get sub dup 0 gt{{end}repeat}{pop}ifelse
+ {Adobe_AGM_Core/AGMCORE_feature_ctm get setmatrix}if
+}def
+/set_negative
+{
+ Adobe_AGM_Core begin
+ /AGMCORE_inverting exch def
+ level2{
+ currentpagedevice/NegativePrint known{
+ currentpagedevice/NegativePrint get Adobe_AGM_Core/AGMCORE_inverting get ne{
+ true begin_feature true{
+ bdict /NegativePrint Adobe_AGM_Core/AGMCORE_inverting get edict setpagedevice
+ }end_feature
+ }if
+ /AGMCORE_inverting false def
+ }if
+ }if
+ AGMCORE_inverting{
+ [{1 exch sub}/exec load dup currenttransfer exch]cvx bind settransfer
+ gsave newpath clippath 1 /setseparationgray where{pop setseparationgray}{setgray}ifelse
+ /AGMIRS_&fill where {pop AGMIRS_&fill}{fill} ifelse grestore
+ }if
+ end
+}def
+/lw_save_restore_override {
+ /md where {
+ pop
+ md begin
+ initializepage
+ /initializepage{}def
+ /pmSVsetup{} def
+ /endp{}def
+ /pse{}def
+ /psb{}def
+ /orig_showpage where
+ {pop}
+ {/orig_showpage /showpage load def}
+ ifelse
+ /showpage {orig_showpage gR} def
+ end
+ }if
+}def
+/pscript_showpage_override {
+ /NTPSOct95 where
+ {
+ begin
+ showpage
+ save
+ /showpage /restore load def
+ /restore {exch pop}def
+ end
+ }if
+}def
+/driver_media_override
+{
+ /md where {
+ pop
+ md /initializepage known {
+ md /initializepage {} put
+ } if
+ md /rC known {
+ md /rC {4{pop}repeat} put
+ } if
+ }if
+ /mysetup where {
+ /mysetup [1 0 0 1 0 0] put
+ }if
+ Adobe_AGM_Core /AGMCORE_Default_CTM matrix currentmatrix put
+ level2
+ {Adobe_AGM_Core /AGMCORE_Default_PageSize currentpagedevice/PageSize get put}if
+}def
+/driver_check_media_override
+{
+ /PrepsDict where
+ {pop}
+ {
+ Adobe_AGM_Core /AGMCORE_Default_CTM get matrix currentmatrix ne
+ Adobe_AGM_Core /AGMCORE_Default_PageSize get type /arraytype eq
+ {
+ Adobe_AGM_Core /AGMCORE_Default_PageSize get 0 get currentpagedevice/PageSize get 0 get eq and
+ Adobe_AGM_Core /AGMCORE_Default_PageSize get 1 get currentpagedevice/PageSize get 1 get eq and
+ }if
+ {
+ Adobe_AGM_Core /AGMCORE_Default_CTM get setmatrix
+ }if
+ }ifelse
+}def
+AGMCORE_err_strings begin
+ /AGMCORE_bad_environ (Environment not satisfactory for this job. Ensure that the PPD is correct or that the PostScript level requested is supported by this printer. ) def
+ /AGMCORE_color_space_onhost_seps (This job contains colors that will not separate with on-host methods. ) def
+ /AGMCORE_invalid_color_space (This job contains an invalid color space. ) def
+end
+end
+systemdict /setpacking known
+{
+ setpacking
+} if
+%%EndResource
+%%BeginResource: procset Adobe_CoolType_Core 2.23 0
+%%Copyright: Copyright 1997-2003 Adobe Systems Incorporated. All Rights Reserved.
+%%Version: 2.23 0
+10 dict begin
+/Adobe_CoolType_Passthru currentdict def
+/Adobe_CoolType_Core_Defined userdict /Adobe_CoolType_Core known def
+Adobe_CoolType_Core_Defined
+ { /Adobe_CoolType_Core userdict /Adobe_CoolType_Core get def }
+if
+userdict /Adobe_CoolType_Core 60 dict dup begin put
+/Adobe_CoolType_Version 2.23 def
+/Level2?
+ systemdict /languagelevel known dup
+ { pop systemdict /languagelevel get 2 ge }
+ if def
+Level2? not
+ {
+ /currentglobal false def
+ /setglobal /pop load def
+ /gcheck { pop false } bind def
+ /currentpacking false def
+ /setpacking /pop load def
+ /SharedFontDirectory 0 dict def
+ }
+if
+currentpacking
+true setpacking
+/@_SaveStackLevels
+ {
+ Adobe_CoolType_Data
+ begin
+ @opStackCountByLevel @opStackLevel
+ 2 copy known not
+ { 2 copy 3 dict dup /args 7 index 5 add array put put get }
+ {
+ get dup /args get dup length 3 index lt
+ {
+ dup length 5 add array exch
+ 1 index exch 0 exch putinterval
+ 1 index exch /args exch put
+ }
+ { pop }
+ ifelse
+ }
+ ifelse
+ begin
+ count 2 sub 1 index lt
+ { pop count 1 sub }
+ if
+ dup /argCount exch def
+ dup 0 gt
+ {
+ exch 1 index 2 add 1 roll
+ args exch 0 exch getinterval
+ astore pop
+ }
+ { pop }
+ ifelse
+ count 1 sub /restCount exch def
+ end
+ /@opStackLevel @opStackLevel 1 add def
+ countdictstack 1 sub
+ @dictStackCountByLevel exch @dictStackLevel exch put
+ /@dictStackLevel @dictStackLevel 1 add def
+ end
+ } bind def
+/@_RestoreStackLevels
+ {
+ Adobe_CoolType_Data
+ begin
+ /@opStackLevel @opStackLevel 1 sub def
+ @opStackCountByLevel @opStackLevel get
+ begin
+ count restCount sub dup 0 gt
+ { { pop } repeat }
+ { pop }
+ ifelse
+ args 0 argCount getinterval {} forall
+ end
+ /@dictStackLevel @dictStackLevel 1 sub def
+ @dictStackCountByLevel @dictStackLevel get
+ end
+ countdictstack exch sub dup 0 gt
+ { { end } repeat }
+ { pop }
+ ifelse
+ } bind def
+/@_PopStackLevels
+ {
+ Adobe_CoolType_Data
+ begin
+ /@opStackLevel @opStackLevel 1 sub def
+ /@dictStackLevel @dictStackLevel 1 sub def
+ end
+ } bind def
+/@Raise
+ {
+ exch cvx exch errordict exch get exec
+ stop
+ } bind def
+/@ReRaise
+ {
+ cvx $error /errorname get errordict exch get exec
+ stop
+ } bind def
+/@Stopped
+ {
+ 0 @#Stopped
+ } bind def
+/@#Stopped
+ {
+ @_SaveStackLevels
+ stopped
+ { @_RestoreStackLevels true }
+ { @_PopStackLevels false }
+ ifelse
+ } bind def
+/@Arg
+ {
+ Adobe_CoolType_Data
+ begin
+ @opStackCountByLevel @opStackLevel 1 sub get /args get exch get
+ end
+ } bind def
+currentglobal true setglobal
+/CTHasResourceForAllBug
+ Level2?
+ {
+ 1 dict dup begin
+ mark
+ {
+ (*) { pop stop } 128 string /Category
+ resourceforall
+ }
+ stopped
+ cleartomark
+ currentdict eq dup
+ { end }
+ if
+ not
+ }
+ { false }
+ ifelse
+ def
+/CTHasResourceStatusBug
+ Level2?
+ {
+ mark
+ { /steveamerige /Category resourcestatus }
+ stopped
+ { cleartomark true }
+ { cleartomark currentglobal not }
+ ifelse
+ }
+ { false }
+ ifelse
+ def
+setglobal
+/CTResourceStatus
+ {
+ mark 3 1 roll
+ /Category findresource
+ begin
+ ({ResourceStatus} stopped) 0 () /SubFileDecode filter cvx exec
+ { cleartomark false }
+ { { 3 2 roll pop true } { cleartomark false } ifelse }
+ ifelse
+ end
+ } bind def
+/CTWorkAroundBugs
+ {
+ Level2?
+ {
+ /cid_PreLoad /ProcSet resourcestatus
+ {
+ pop pop
+ currentglobal
+ mark
+ {
+ (*)
+ {
+ dup /CMap CTHasResourceStatusBug
+ { CTResourceStatus }
+ { resourcestatus }
+ ifelse
+ {
+ pop dup 0 eq exch 1 eq or
+ {
+ dup /CMap findresource gcheck setglobal
+ /CMap undefineresource
+ }
+ {
+ pop CTHasResourceForAllBug
+ { exit }
+ { stop }
+ ifelse
+ }
+ ifelse
+ }
+ { pop }
+ ifelse
+ }
+ 128 string /CMap resourceforall
+ }
+ stopped
+ { cleartomark }
+ stopped pop
+ setglobal
+ }
+ if
+ }
+ if
+ } bind def
+/doc_setup
+ {
+ Adobe_CoolType_Core
+ begin
+ CTWorkAroundBugs
+ /mov /moveto load def
+ /nfnt /newencodedfont load def
+ /mfnt /makefont load def
+ /sfnt /setfont load def
+ /ufnt /undefinefont load def
+ /chp /charpath load def
+ /awsh /awidthshow load def
+ /wsh /widthshow load def
+ /ash /ashow load def
+ /sh /show load def
+ end
+ userdict /Adobe_CoolType_Data 10 dict dup
+ begin
+ /AddWidths? false def
+ /CC 0 def
+ /charcode 2 string def
+ /@opStackCountByLevel 32 dict def
+ /@opStackLevel 0 def
+ /@dictStackCountByLevel 32 dict def
+ /@dictStackLevel 0 def
+ /InVMFontsByCMap 10 dict def
+ /InVMDeepCopiedFonts 10 dict def
+ end put
+ } bind def
+/doc_trailer
+ {
+ currentdict Adobe_CoolType_Core eq
+ { end }
+ if
+ } bind def
+/page_setup
+ {
+ Adobe_CoolType_Core begin
+ } bind def
+/page_trailer
+ {
+ end
+ } bind def
+/unload
+ {
+ systemdict /languagelevel known
+ {
+ systemdict/languagelevel get 2 ge
+ {
+ userdict/Adobe_CoolType_Core 2 copy known
+ { undef }
+ { pop pop }
+ ifelse
+ }
+ if
+ }
+ if
+ } bind def
+/ndf
+ {
+ 1 index where
+ { pop pop pop }
+ { dup xcheck { bind } if def }
+ ifelse
+ } def
+/findfont systemdict
+ begin
+ userdict
+ begin
+ /globaldict where { /globaldict get begin } if
+ dup where pop exch get
+ /globaldict where { pop end } if
+ end
+ end
+Adobe_CoolType_Core_Defined
+ { /systemfindfont exch def }
+ {
+ /findfont 1 index def
+ /systemfindfont exch def
+ }
+ifelse
+/undefinefont
+ { pop } ndf
+/copyfont
+ {
+ currentglobal 3 1 roll
+ 1 index gcheck setglobal
+ dup null eq { 0 } { dup length } ifelse
+ 2 index length add 1 add dict
+ begin
+ exch
+ {
+ 1 index /FID eq
+ { pop pop }
+ { def }
+ ifelse
+ }
+ forall
+ dup null eq
+ { pop }
+ { { def } forall }
+ ifelse
+ currentdict
+ end
+ exch setglobal
+ } bind def
+/copyarray
+ {
+ currentglobal exch
+ dup gcheck setglobal
+ dup length array copy
+ exch setglobal
+ } bind def
+/newencodedfont
+ {
+ currentglobal
+ {
+ SharedFontDirectory 3 index known
+ { SharedFontDirectory 3 index get /FontReferenced known }
+ { false }
+ ifelse
+ }
+ {
+ FontDirectory 3 index known
+ { FontDirectory 3 index get /FontReferenced known }
+ {
+ SharedFontDirectory 3 index known
+ { SharedFontDirectory 3 index get /FontReferenced known }
+ { false }
+ ifelse
+ }
+ ifelse
+ }
+ ifelse
+ dup
+ {
+ 3 index findfont /FontReferenced get
+ 2 index dup type /nametype eq
+ {findfont}
+ if ne
+ { pop false }
+ if
+ }
+ if
+ {
+ pop
+ 1 index findfont
+ /Encoding get exch
+ 0 1 255
+ { 2 copy get 3 index 3 1 roll put }
+ for
+ pop pop pop
+ }
+ {
+ dup type /nametype eq
+ { findfont }
+ if
+ dup dup maxlength 2 add dict
+ begin
+ exch
+ {
+ 1 index /FID ne
+ {def}
+ {pop pop}
+ ifelse
+ }
+ forall
+ /FontReferenced exch def
+ /Encoding exch dup length array copy def
+ /FontName 1 index dup type /stringtype eq { cvn } if def dup
+ currentdict
+ end
+ definefont def
+ }
+ ifelse
+ } bind def
+/SetSubstituteStrategy
+ {
+ $SubstituteFont
+ begin
+ dup type /dicttype ne
+ { 0 dict }
+ if
+ currentdict /$Strategies known
+ {
+ exch $Strategies exch
+ 2 copy known
+ {
+ get
+ 2 copy maxlength exch maxlength add dict
+ begin
+ { def } forall
+ { def } forall
+ currentdict
+ dup /$Init known
+ { dup /$Init get exec }
+ if
+ end
+ /$Strategy exch def
+ }
+ { pop pop pop }
+ ifelse
+ }
+ { pop pop }
+ ifelse
+ end
+ } bind def
+/scff
+ {
+ $SubstituteFont
+ begin
+ dup type /stringtype eq
+ { dup length exch }
+ { null }
+ ifelse
+ /$sname exch def
+ /$slen exch def
+ /$inVMIndex
+ $sname null eq
+ {
+ 1 index $str cvs
+ dup length $slen sub $slen getinterval cvn
+ }
+ { $sname }
+ ifelse def
+ end
+ { findfont }
+ @Stopped
+ {
+ dup length 8 add string exch
+ 1 index 0 (BadFont:) putinterval
+ 1 index exch 8 exch dup length string cvs putinterval cvn
+ { findfont }
+ @Stopped
+ { pop /Courier findfont }
+ if
+ }
+ if
+ $SubstituteFont
+ begin
+ /$sname null def
+ /$slen 0 def
+ /$inVMIndex null def
+ end
+ } bind def
+/isWidthsOnlyFont
+ {
+ dup /WidthsOnly known
+ { pop pop true }
+ {
+ dup /FDepVector known
+ { /FDepVector get { isWidthsOnlyFont dup { exit } if } forall }
+ {
+ dup /FDArray known
+ { /FDArray get { isWidthsOnlyFont dup { exit } if } forall }
+ { pop }
+ ifelse
+ }
+ ifelse
+ }
+ ifelse
+ } bind def
+/?str1 256 string def
+/?set
+ {
+ $SubstituteFont
+ begin
+ /$substituteFound false def
+ /$fontname 4 index def
+ /$doSmartSub false def
+ end
+ 3 index
+ currentglobal false setglobal exch
+ /CompatibleFonts /ProcSet resourcestatus
+ {
+ pop pop
+ /CompatibleFonts /ProcSet findresource
+ begin
+ dup /CompatibleFont currentexception
+ 1 index /CompatibleFont true setexception
+ 1 index /Font resourcestatus
+ {
+ pop pop
+ 3 2 roll setglobal
+ end
+ exch
+ dup findfont
+ /CompatibleFonts /ProcSet findresource
+ begin
+ 3 1 roll exch /CompatibleFont exch setexception
+ end
+ }
+ {
+ 3 2 roll setglobal
+ 1 index exch /CompatibleFont exch setexception
+ end
+ findfont
+ $SubstituteFont /$substituteFound true put
+ }
+ ifelse
+ }
+ { exch setglobal findfont }
+ ifelse
+ $SubstituteFont
+ begin
+ $substituteFound
+ {
+ false
+ (%%[Using embedded font ) print
+ 5 index ?str1 cvs print
+ ( to avoid the font substitution problem noted earlier.]%%\n) print
+ }
+ {
+ dup /FontName known
+ {
+ dup /FontName get $fontname eq
+ 1 index /DistillerFauxFont known not and
+ /currentdistillerparams where
+ { pop false 2 index isWidthsOnlyFont not and }
+ if
+ }
+ { false }
+ ifelse
+ }
+ ifelse
+ exch pop
+ /$doSmartSub true def
+ end
+ {
+ exch pop exch pop exch
+ 2 dict dup /Found 3 index put
+ exch findfont exch
+ }
+ {
+ exch exec
+ exch dup findfont
+ dup /FontType get 3 eq
+ {
+ exch ?str1 cvs
+ dup length 1 sub
+ -1 0
+ {
+ exch dup 2 index get 42 eq
+ {
+ exch 0 exch getinterval cvn 4 1 roll 3 2 roll pop
+ exit
+ }
+ {exch pop} ifelse
+ }for
+ }
+ {
+ exch pop
+ } ifelse
+ 2 dict dup /Downloaded 6 5 roll put
+ }
+ ifelse
+ dup /FontName 4 index put copyfont definefont pop
+ } bind def
+/?str2 256 string def
+/?add
+ {
+ 1 index type /integertype eq
+ { exch true 4 2 }
+ { false 3 1 }
+ ifelse
+ roll
+ 1 index findfont
+ dup /Widths known
+ {
+ Adobe_CoolType_Data /AddWidths? true put
+ gsave dup 1000 scalefont setfont
+ }
+ if
+ /Downloaded known
+ {
+ exec
+ exch
+ {
+ exch ?str2 cvs exch
+ findfont /Downloaded get 1 dict begin /Downloaded 1 index def ?str1 cvs length
+ ?str1 1 index 1 add 3 index putinterval
+ exch length 1 add 1 index add
+ ?str1 2 index (*) putinterval
+ ?str1 0 2 index getinterval cvn findfont
+ ?str1 3 index (+) putinterval
+ 2 dict dup /FontName ?str1 0 6 index getinterval cvn put
+ dup /Downloaded Downloaded put end copyfont
+ dup /FontName get exch definefont pop pop pop
+ }
+ {
+ pop
+ }
+ ifelse
+ }
+ {
+ pop
+ exch
+ {
+ findfont
+ dup /Found get
+ dup length exch ?str1 cvs pop
+ ?str1 1 index (+) putinterval
+ ?str1 1 index 1 add 4 index ?str2 cvs putinterval
+ ?str1 exch 0 exch 5 4 roll ?str2 cvs length 1 add add getinterval cvn
+ 1 dict exch 1 index exch /FontName exch put copyfont
+ dup /FontName get exch definefont pop
+ }
+ {
+ pop
+ }
+ ifelse
+ }
+ ifelse
+ Adobe_CoolType_Data /AddWidths? get
+ { grestore Adobe_CoolType_Data /AddWidths? false put }
+ if
+ } bind def
+/?sh
+ {
+ currentfont /Downloaded known { exch } if pop
+ } bind def
+/?chp
+ {
+ currentfont /Downloaded known { pop } { false chp } ifelse
+ } bind def
+/?mv
+ {
+ currentfont /Downloaded known { moveto pop pop } { pop pop moveto } ifelse
+ } bind def
+setpacking
+userdict /$SubstituteFont 25 dict put
+1 dict
+ begin
+ /SubstituteFont
+ dup $error exch 2 copy known
+ { get }
+ { pop pop { pop /Courier } bind }
+ ifelse def
+ /currentdistillerparams where dup
+ {
+ pop pop
+ currentdistillerparams /CannotEmbedFontPolicy 2 copy known
+ { get /Error eq }
+ { pop pop false }
+ ifelse
+ }
+ if not
+ {
+ countdictstack array dictstack 0 get
+ begin
+ userdict
+ begin
+ $SubstituteFont
+ begin
+ /$str 128 string def
+ /$fontpat 128 string def
+ /$slen 0 def
+ /$sname null def
+ /$match false def
+ /$fontname null def
+ /$substituteFound false def
+ /$inVMIndex null def
+ /$doSmartSub true def
+ /$depth 0 def
+ /$fontname null def
+ /$italicangle 26.5 def
+ /$dstack null def
+ /$Strategies 10 dict dup
+ begin
+ /$Type3Underprint
+ {
+ currentglobal exch false setglobal
+ 11 dict
+ begin
+ /UseFont exch
+ $WMode 0 ne
+ {
+ dup length dict copy
+ dup /WMode $WMode put
+ /UseFont exch definefont
+ }
+ if def
+ /FontName $fontname dup type /stringtype eq { cvn } if def
+ /FontType 3 def
+ /FontMatrix [ .001 0 0 .001 0 0 ] def
+ /Encoding 256 array dup 0 1 255 { /.notdef put dup } for pop def
+ /FontBBox [ 0 0 0 0 ] def
+ /CCInfo 7 dict dup
+ begin
+ /cc null def
+ /x 0 def
+ /y 0 def
+ end def
+ /BuildChar
+ {
+ exch
+ begin
+ CCInfo
+ begin
+ 1 string dup 0 3 index put exch pop
+ /cc exch def
+ UseFont 1000 scalefont setfont
+ cc stringwidth /y exch def /x exch def
+ x y setcharwidth
+ $SubstituteFont /$Strategy get /$Underprint get exec
+ 0 0 moveto cc show
+ x y moveto
+ end
+ end
+ } bind def
+ currentdict
+ end
+ exch setglobal
+ } bind def
+ /$GetaTint
+ 2 dict dup
+ begin
+ /$BuildFont
+ {
+ dup /WMode known
+ { dup /WMode get }
+ { 0 }
+ ifelse
+ /$WMode exch def
+ $fontname exch
+ dup /FontName known
+ {
+ dup /FontName get
+ dup type /stringtype eq { cvn } if
+ }
+ { /unnamedfont }
+ ifelse
+ exch
+ Adobe_CoolType_Data /InVMDeepCopiedFonts get
+ 1 index /FontName get known
+ {
+ pop
+ Adobe_CoolType_Data /InVMDeepCopiedFonts get
+ 1 index get
+ null copyfont
+ }
+ { $deepcopyfont }
+ ifelse
+ exch 1 index exch /FontBasedOn exch put
+ dup /FontName $fontname dup type /stringtype eq { cvn } if put
+ definefont
+ Adobe_CoolType_Data /InVMDeepCopiedFonts get
+ begin
+ dup /FontBasedOn get 1 index def
+ end
+ } bind def
+ /$Underprint
+ {
+ gsave
+ x abs y abs gt
+ { /y 1000 def }
+ { /x -1000 def 500 120 translate }
+ ifelse
+ Level2?
+ {
+ [ /Separation (All) /DeviceCMYK { 0 0 0 1 pop } ]
+ setcolorspace
+ }
+ { 0 setgray }
+ ifelse
+ 10 setlinewidth
+ x .8 mul
+ [ 7 3 ]
+ {
+ y mul 8 div 120 sub x 10 div exch moveto
+ 0 y 4 div neg rlineto
+ dup 0 rlineto
+ 0 y 4 div rlineto
+ closepath
+ gsave
+ Level2?
+ { .2 setcolor }
+ { .8 setgray }
+ ifelse
+ fill grestore
+ stroke
+ }
+ forall
+ pop
+ grestore
+ } bind def
+ end def
+ /$Oblique
+ 1 dict dup
+ begin
+ /$BuildFont
+ {
+ currentglobal exch dup gcheck setglobal
+ null copyfont
+ begin
+ /FontBasedOn
+ currentdict /FontName known
+ {
+ FontName
+ dup type /stringtype eq { cvn } if
+ }
+ { /unnamedfont }
+ ifelse
+ def
+ /FontName $fontname dup type /stringtype eq { cvn } if def
+ /currentdistillerparams where
+ { pop }
+ {
+ /FontInfo currentdict /FontInfo known
+ { FontInfo null copyfont }
+ { 2 dict }
+ ifelse
+ dup
+ begin
+ /ItalicAngle $italicangle def
+ /FontMatrix FontMatrix
+ [ 1 0 ItalicAngle dup sin exch cos div 1 0 0 ]
+ matrix concatmatrix readonly
+ end
+ 4 2 roll def
+ def
+ }
+ ifelse
+ FontName currentdict
+ end
+ definefont
+ exch setglobal
+ } bind def
+ end def
+ /$None
+ 1 dict dup
+ begin
+ /$BuildFont {} bind def
+ end def
+ end def
+ /$Oblique SetSubstituteStrategy
+ /$findfontByEnum
+ {
+ dup type /stringtype eq { cvn } if
+ dup /$fontname exch def
+ $sname null eq
+ { $str cvs dup length $slen sub $slen getinterval }
+ { pop $sname }
+ ifelse
+ $fontpat dup 0 (fonts/*) putinterval exch 7 exch putinterval
+ /$match false def
+ $SubstituteFont /$dstack countdictstack array dictstack put
+ mark
+ {
+ $fontpat 0 $slen 7 add getinterval
+ { /$match exch def exit }
+ $str filenameforall
+ }
+ stopped
+ {
+ cleardictstack
+ currentdict
+ true
+ $SubstituteFont /$dstack get
+ {
+ exch
+ {
+ 1 index eq
+ { pop false }
+ { true }
+ ifelse
+ }
+ { begin false }
+ ifelse
+ }
+ forall
+ pop
+ }
+ if
+ cleartomark
+ /$slen 0 def
+ $match false ne
+ { $match (fonts/) anchorsearch pop pop cvn }
+ { /Courier }
+ ifelse
+ } bind def
+ /$ROS 1 dict dup
+ begin
+ /Adobe 4 dict dup
+ begin
+ /Japan1 [ /Ryumin-Light /HeiseiMin-W3
+ /GothicBBB-Medium /HeiseiKakuGo-W5
+ /HeiseiMaruGo-W4 /Jun101-Light ] def
+ /Korea1 [ /HYSMyeongJo-Medium /HYGoThic-Medium ] def
+ /GB1 [ /STSong-Light /STHeiti-Regular ] def
+ /CNS1 [ /MKai-Medium /MHei-Medium ] def
+ end def
+ end def
+ /$cmapname null def
+ /$deepcopyfont
+ {
+ dup /FontType get 0 eq
+ {
+ 1 dict dup /FontName /copied put copyfont
+ begin
+ /FDepVector FDepVector copyarray
+ 0 1 2 index length 1 sub
+ {
+ 2 copy get $deepcopyfont
+ dup /FontName /copied put
+ /copied exch definefont
+ 3 copy put pop pop
+ }
+ for
+ def
+ currentdict
+ end
+ }
+ { $Strategies /$Type3Underprint get exec }
+ ifelse
+ } bind def
+ /$buildfontname
+ {
+ dup /CIDFont findresource /CIDSystemInfo get
+ begin
+ Registry length Ordering length Supplement 8 string cvs
+ 3 copy length 2 add add add string
+ dup 5 1 roll dup 0 Registry putinterval
+ dup 4 index (-) putinterval
+ dup 4 index 1 add Ordering putinterval
+ 4 2 roll add 1 add 2 copy (-) putinterval
+ end
+ 1 add 2 copy 0 exch getinterval $cmapname $fontpat cvs exch
+ anchorsearch
+ { pop pop 3 2 roll putinterval cvn /$cmapname exch def }
+ { pop pop pop pop pop }
+ ifelse
+ length
+ $str 1 index (-) putinterval 1 add
+ $str 1 index $cmapname $fontpat cvs putinterval
+ $cmapname length add
+ $str exch 0 exch getinterval cvn
+ } bind def
+ /$findfontByROS
+ {
+ /$fontname exch def
+ $ROS Registry 2 copy known
+ {
+ get Ordering 2 copy known
+ { get }
+ { pop pop [] }
+ ifelse
+ }
+ { pop pop [] }
+ ifelse
+ false exch
+ {
+ dup /CIDFont resourcestatus
+ {
+ pop pop
+ save
+ 1 index /CIDFont findresource
+ dup /WidthsOnly known
+ { dup /WidthsOnly get }
+ { false }
+ ifelse
+ exch pop
+ exch restore
+ { pop }
+ { exch pop true exit }
+ ifelse
+ }
+ { pop }
+ ifelse
+ }
+ forall
+ { $str cvs $buildfontname }
+ {
+ false (*)
+ {
+ save exch
+ dup /CIDFont findresource
+ dup /WidthsOnly known
+ { dup /WidthsOnly get not }
+ { true }
+ ifelse
+ exch /CIDSystemInfo get
+ dup /Registry get Registry eq
+ exch /Ordering get Ordering eq and and
+ { exch restore exch pop true exit }
+ { pop restore }
+ ifelse
+ }
+ $str /CIDFont resourceforall
+ { $buildfontname }
+ { $fontname $findfontByEnum }
+ ifelse
+ }
+ ifelse
+ } bind def
+ end
+ end
+ currentdict /$error known currentdict /languagelevel known and dup
+ { pop $error /SubstituteFont known }
+ if
+ dup
+ { $error }
+ { Adobe_CoolType_Core }
+ ifelse
+ begin
+ {
+ /SubstituteFont
+ /CMap /Category resourcestatus
+ {
+ pop pop
+ {
+ $SubstituteFont
+ begin
+ /$substituteFound true def
+ dup length $slen gt
+ $sname null ne or
+ $slen 0 gt and
+ {
+ $sname null eq
+ { dup $str cvs dup length $slen sub $slen getinterval cvn }
+ { $sname }
+ ifelse
+ Adobe_CoolType_Data /InVMFontsByCMap get
+ 1 index 2 copy known
+ {
+ get
+ false exch
+ {
+ pop
+ currentglobal
+ {
+ GlobalFontDirectory 1 index known
+ { exch pop true exit }
+ { pop }
+ ifelse
+ }
+ {
+ FontDirectory 1 index known
+ { exch pop true exit }
+ {
+ GlobalFontDirectory 1 index known
+ { exch pop true exit }
+ { pop }
+ ifelse
+ }
+ ifelse
+ }
+ ifelse
+ }
+ forall
+ }
+ { pop pop false }
+ ifelse
+ {
+ exch pop exch pop
+ }
+ {
+ dup /CMap resourcestatus
+ {
+ pop pop
+ dup /$cmapname exch def
+ /CMap findresource /CIDSystemInfo get { def } forall
+ $findfontByROS
+ }
+ {
+ 128 string cvs
+ dup (-) search
+ {
+ 3 1 roll search
+ {
+ 3 1 roll pop
+ { dup cvi }
+ stopped
+ { pop pop pop pop pop $findfontByEnum }
+ {
+ 4 2 roll pop pop
+ exch length
+ exch
+ 2 index length
+ 2 index
+ sub
+ exch 1 sub -1 0
+ {
+ $str cvs dup length
+ 4 index
+ 0
+ 4 index
+ 4 3 roll add
+ getinterval
+ exch 1 index exch 3 index exch
+ putinterval
+ dup /CMap resourcestatus
+ {
+ pop pop
+ 4 1 roll pop pop pop
+ dup /$cmapname exch def
+ /CMap findresource /CIDSystemInfo get { def } forall
+ $findfontByROS
+ true exit
+ }
+ { pop }
+ ifelse
+ }
+ for
+ dup type /booleantype eq
+ { pop }
+ { pop pop pop $findfontByEnum }
+ ifelse
+ }
+ ifelse
+ }
+ { pop pop pop $findfontByEnum }
+ ifelse
+ }
+ { pop pop $findfontByEnum }
+ ifelse
+ }
+ ifelse
+ }
+ ifelse
+ }
+ { //SubstituteFont exec }
+ ifelse
+ /$slen 0 def
+ end
+ }
+ }
+ {
+ {
+ $SubstituteFont
+ begin
+ /$substituteFound true def
+ dup length $slen gt
+ $sname null ne or
+ $slen 0 gt and
+ { $findfontByEnum }
+ { //SubstituteFont exec }
+ ifelse
+ end
+ }
+ }
+ ifelse
+ bind readonly def
+ Adobe_CoolType_Core /scfindfont /systemfindfont load put
+ }
+ {
+ /scfindfont
+ {
+ $SubstituteFont
+ begin
+ dup systemfindfont
+ dup /FontName known
+ { dup /FontName get dup 3 index ne }
+ { /noname true }
+ ifelse
+ dup
+ {
+ /$origfontnamefound 2 index def
+ /$origfontname 4 index def /$substituteFound true def
+ }
+ if
+ exch pop
+ {
+ $slen 0 gt
+ $sname null ne
+ 3 index length $slen gt or and
+ {
+ pop dup $findfontByEnum findfont
+ dup maxlength 1 add dict
+ begin
+ { 1 index /FID eq { pop pop } { def } ifelse }
+ forall
+ currentdict
+ end
+ definefont
+ dup /FontName known { dup /FontName get } { null } ifelse
+ $origfontnamefound ne
+ {
+ $origfontname $str cvs print
+ ( substitution revised, using ) print
+ dup /FontName known
+ { dup /FontName get } { (unspecified font) }
+ ifelse
+ $str cvs print (.\n) print
+ }
+ if
+ }
+ { exch pop }
+ ifelse
+ }
+ { exch pop }
+ ifelse
+ end
+ } bind def
+ }
+ ifelse
+ end
+ end
+ Adobe_CoolType_Core_Defined not
+ {
+ Adobe_CoolType_Core /findfont
+ {
+ $SubstituteFont
+ begin
+ $depth 0 eq
+ {
+ /$fontname 1 index dup type /stringtype ne { $str cvs } if def
+ /$substituteFound false def
+ }
+ if
+ /$depth $depth 1 add def
+ end
+ scfindfont
+ $SubstituteFont
+ begin
+ /$depth $depth 1 sub def
+ $substituteFound $depth 0 eq and
+ {
+ $inVMIndex null ne
+ { dup $inVMIndex $AddInVMFont }
+ if
+ $doSmartSub
+ {
+ currentdict /$Strategy known
+ { $Strategy /$BuildFont get exec }
+ if
+ }
+ if
+ }
+ if
+ end
+ } bind put
+ }
+ if
+ }
+ if
+ end
+/$AddInVMFont
+ {
+ exch /FontName 2 copy known
+ {
+ get
+ 1 dict dup begin exch 1 index gcheck def end exch
+ Adobe_CoolType_Data /InVMFontsByCMap get exch
+ $DictAdd
+ }
+ { pop pop pop }
+ ifelse
+ } bind def
+/$DictAdd
+ {
+ 2 copy known not
+ { 2 copy 4 index length dict put }
+ if
+ Level2? not
+ {
+ 2 copy get dup maxlength exch length 4 index length add lt
+ 2 copy get dup length 4 index length add exch maxlength 1 index lt
+ {
+ 2 mul dict
+ begin
+ 2 copy get { forall } def
+ 2 copy currentdict put
+ end
+ }
+ { pop }
+ ifelse
+ }
+ if
+ get
+ begin
+ { def }
+ forall
+ end
+ } bind def
+end
+end
+%%EndResource
+%%BeginResource: procset Adobe_CoolType_Utility_MAKEOCF 1.19 0
+%%Copyright: Copyright 1987-2003 Adobe Systems Incorporated.
+%%Version: 1.19 0
+systemdict /languagelevel known dup
+ { currentglobal false setglobal }
+ { false }
+ifelse
+exch
+userdict /Adobe_CoolType_Utility 2 copy known
+ { 2 copy get dup maxlength 25 add dict copy }
+ { 25 dict }
+ifelse put
+Adobe_CoolType_Utility
+ begin
+ /ct_Level2? exch def
+ /ct_Clone? 1183615869 internaldict dup
+ /CCRun known not
+ exch /eCCRun known not
+ ct_Level2? and or def
+ct_Level2?
+ { globaldict begin currentglobal true setglobal }
+if
+ /ct_AddStdCIDMap
+ ct_Level2?
+ { {
+ ((Hex) 57 StartData
+ 0615 1e27 2c39 1c60 d8a8 cc31 fe2b f6e0
+ 7aa3 e541 e21c 60d8 a8c9 c3d0 6d9e 1c60
+ d8a8 c9c2 02d7 9a1c 60d8 a849 1c60 d8a8
+ cc36 74f4 1144 b13b 77) 0 () /SubFileDecode filter cvx exec
+ } }
+ { {
+ <BAB431EA07F209EB8C4348311481D9D3F76E3D15246555577D87BC510ED54E
+ 118C39697FA9F6DB58128E60EB8A12FA24D7CDD2FA94D221FA9EC8DA3E5E6A1C
+ 4ACECC8C2D39C54E7C946031DD156C3A6B4A09AD29E1867A> eexec
+ } }
+ ifelse bind def
+userdict /cid_extensions known
+dup { cid_extensions /cid_UpdateDB known and } if
+ {
+ cid_extensions
+ begin
+ /cid_GetCIDSystemInfo
+ {
+ 1 index type /stringtype eq
+ { exch cvn exch }
+ if
+ cid_extensions
+ begin
+ dup load 2 index known
+ {
+ 2 copy
+ cid_GetStatusInfo
+ dup null ne
+ {
+ 1 index load
+ 3 index get
+ dup null eq
+ { pop pop cid_UpdateDB }
+ {
+ exch
+ 1 index /Created get eq
+ { exch pop exch pop }
+ { pop cid_UpdateDB }
+ ifelse
+ }
+ ifelse
+ }
+ { pop cid_UpdateDB }
+ ifelse
+ }
+ { cid_UpdateDB }
+ ifelse
+ end
+ } bind def
+ end
+ }
+if
+ct_Level2?
+ { end setglobal }
+if
+ /ct_UseNativeCapability? systemdict /composefont known def
+ /ct_MakeOCF 35 dict def
+ /ct_Vars 25 dict def
+ /ct_GlyphDirProcs 6 dict def
+ /ct_BuildCharDict 15 dict dup
+ begin
+ /charcode 2 string def
+ /dst_string 1500 string def
+ /nullstring () def
+ /usewidths? true def
+ end def
+ ct_Level2? { setglobal } { pop } ifelse
+ ct_GlyphDirProcs
+ begin
+ /GetGlyphDirectory
+ {
+ systemdict /languagelevel known
+ { pop /CIDFont findresource /GlyphDirectory get }
+ {
+ 1 index /CIDFont findresource /GlyphDirectory
+ get dup type /dicttype eq
+ {
+ dup dup maxlength exch length sub 2 index lt
+ {
+ dup length 2 index add dict copy 2 index
+ /CIDFont findresource/GlyphDirectory 2 index put
+ }
+ if
+ }
+ if
+ exch pop exch pop
+ }
+ ifelse
+ +
+ } def
+ /+
+ {
+ systemdict /languagelevel known
+ {
+ currentglobal false setglobal
+ 3 dict begin
+ /vm exch def
+ }
+ { 1 dict begin }
+ ifelse
+ /$ exch def
+ systemdict /languagelevel known
+ {
+ vm setglobal
+ /gvm currentglobal def
+ $ gcheck setglobal
+ }
+ if
+ ? { $ begin } if
+ } def
+ /? { $ type /dicttype eq } def
+ /| {
+ userdict /Adobe_CoolType_Data known
+ {
+ Adobe_CoolType_Data /AddWidths? known
+ {
+ currentdict Adobe_CoolType_Data
+ begin
+ begin
+ AddWidths?
+ {
+ Adobe_CoolType_Data /CC 3 index put
+ ? { def } { $ 3 1 roll put } ifelse
+ CC charcode exch 1 index 0 2 index 256 idiv put
+ 1 index exch 1 exch 256 mod put
+ stringwidth 2 array astore
+ currentfont /Widths get exch CC exch put
+ }
+ { ? { def } { $ 3 1 roll put } ifelse }
+ ifelse
+ end
+ end
+ }
+ { ? { def } { $ 3 1 roll put } ifelse } ifelse
+ }
+ { ? { def } { $ 3 1 roll put } ifelse }
+ ifelse
+ } def
+ /!
+ {
+ ? { end } if
+ systemdict /languagelevel known
+ { gvm setglobal }
+ if
+ end
+ } def
+ /: { string currentfile exch readstring pop } executeonly def
+ end
+ ct_MakeOCF
+ begin
+ /ct_cHexEncoding
+ [/c00/c01/c02/c03/c04/c05/c06/c07/c08/c09/c0A/c0B/c0C/c0D/c0E/c0F/c10/c11/c12
+ /c13/c14/c15/c16/c17/c18/c19/c1A/c1B/c1C/c1D/c1E/c1F/c20/c21/c22/c23/c24/c25
+ /c26/c27/c28/c29/c2A/c2B/c2C/c2D/c2E/c2F/c30/c31/c32/c33/c34/c35/c36/c37/c38
+ /c39/c3A/c3B/c3C/c3D/c3E/c3F/c40/c41/c42/c43/c44/c45/c46/c47/c48/c49/c4A/c4B
+ /c4C/c4D/c4E/c4F/c50/c51/c52/c53/c54/c55/c56/c57/c58/c59/c5A/c5B/c5C/c5D/c5E
+ /c5F/c60/c61/c62/c63/c64/c65/c66/c67/c68/c69/c6A/c6B/c6C/c6D/c6E/c6F/c70/c71
+ /c72/c73/c74/c75/c76/c77/c78/c79/c7A/c7B/c7C/c7D/c7E/c7F/c80/c81/c82/c83/c84
+ /c85/c86/c87/c88/c89/c8A/c8B/c8C/c8D/c8E/c8F/c90/c91/c92/c93/c94/c95/c96/c97
+ /c98/c99/c9A/c9B/c9C/c9D/c9E/c9F/cA0/cA1/cA2/cA3/cA4/cA5/cA6/cA7/cA8/cA9/cAA
+ /cAB/cAC/cAD/cAE/cAF/cB0/cB1/cB2/cB3/cB4/cB5/cB6/cB7/cB8/cB9/cBA/cBB/cBC/cBD
+ /cBE/cBF/cC0/cC1/cC2/cC3/cC4/cC5/cC6/cC7/cC8/cC9/cCA/cCB/cCC/cCD/cCE/cCF/cD0
+ /cD1/cD2/cD3/cD4/cD5/cD6/cD7/cD8/cD9/cDA/cDB/cDC/cDD/cDE/cDF/cE0/cE1/cE2/cE3
+ /cE4/cE5/cE6/cE7/cE8/cE9/cEA/cEB/cEC/cED/cEE/cEF/cF0/cF1/cF2/cF3/cF4/cF5/cF6
+ /cF7/cF8/cF9/cFA/cFB/cFC/cFD/cFE/cFF] def
+ /ct_CID_STR_SIZE 8000 def
+ /ct_mkocfStr100 100 string def
+ /ct_defaultFontMtx [.001 0 0 .001 0 0] def
+ /ct_1000Mtx [1000 0 0 1000 0 0] def
+ /ct_raise {exch cvx exch errordict exch get exec stop} bind def
+ /ct_reraise
+ { cvx $error /errorname get (Error: ) print dup ( ) cvs print
+ errordict exch get exec stop
+ } bind def
+ /ct_cvnsi
+ {
+ 1 index add 1 sub 1 exch 0 4 1 roll
+ {
+ 2 index exch get
+ exch 8 bitshift
+ add
+ }
+ for
+ exch pop
+ } bind def
+ /ct_GetInterval
+ {
+ Adobe_CoolType_Utility /ct_BuildCharDict get
+ begin
+ /dst_index 0 def
+ dup dst_string length gt
+ { dup string /dst_string exch def }
+ if
+ 1 index ct_CID_STR_SIZE idiv
+ /arrayIndex exch def
+ 2 index arrayIndex get
+ 2 index
+ arrayIndex ct_CID_STR_SIZE mul
+ sub
+ {
+ dup 3 index add 2 index length le
+ {
+ 2 index getinterval
+ dst_string dst_index 2 index putinterval
+ length dst_index add /dst_index exch def
+ exit
+ }
+ {
+ 1 index length 1 index sub
+ dup 4 1 roll
+ getinterval
+ dst_string dst_index 2 index putinterval
+ pop dup dst_index add /dst_index exch def
+ sub
+ /arrayIndex arrayIndex 1 add def
+ 2 index dup length arrayIndex gt
+ { arrayIndex get }
+ {
+ pop
+ exit
+ }
+ ifelse
+ 0
+ }
+ ifelse
+ }
+ loop
+ pop pop pop
+ dst_string 0 dst_index getinterval
+ end
+ } bind def
+ ct_Level2?
+ {
+ /ct_resourcestatus
+ currentglobal mark true setglobal
+ { /unknowninstancename /Category resourcestatus }
+ stopped
+ { cleartomark setglobal true }
+ { cleartomark currentglobal not exch setglobal }
+ ifelse
+ {
+ {
+ mark 3 1 roll /Category findresource
+ begin
+ ct_Vars /vm currentglobal put
+ ({ResourceStatus} stopped) 0 () /SubFileDecode filter cvx exec
+ { cleartomark false }
+ { { 3 2 roll pop true } { cleartomark false } ifelse }
+ ifelse
+ ct_Vars /vm get setglobal
+ end
+ }
+ }
+ { { resourcestatus } }
+ ifelse bind def
+ /CIDFont /Category ct_resourcestatus
+ { pop pop }
+ {
+ currentglobal true setglobal
+ /Generic /Category findresource
+ dup length dict copy
+ dup /InstanceType /dicttype put
+ /CIDFont exch /Category defineresource pop
+ setglobal
+ }
+ ifelse
+ ct_UseNativeCapability?
+ {
+ /CIDInit /ProcSet findresource begin
+ 12 dict begin
+ begincmap
+ /CIDSystemInfo 3 dict dup begin
+ /Registry (Adobe) def
+ /Ordering (Identity) def
+ /Supplement 0 def
+ end def
+ /CMapName /Identity-H def
+ /CMapVersion 1.000 def
+ /CMapType 1 def
+ 1 begincodespacerange
+ <0000> <FFFF>
+ endcodespacerange
+ 1 begincidrange
+ <0000> <FFFF> 0
+ endcidrange
+ endcmap
+ CMapName currentdict /CMap defineresource pop
+ end
+ end
+ }
+ if
+ }
+ {
+ /ct_Category 2 dict begin
+ /CIDFont 10 dict def
+ /ProcSet 2 dict def
+ currentdict
+ end
+ def
+ /defineresource
+ {
+ ct_Category 1 index 2 copy known
+ {
+ get
+ dup dup maxlength exch length eq
+ {
+ dup length 10 add dict copy
+ ct_Category 2 index 2 index put
+ }
+ if
+ 3 index 3 index put
+ pop exch pop
+ }
+ { pop pop /defineresource /undefined ct_raise }
+ ifelse
+ } bind def
+ /findresource
+ {
+ ct_Category 1 index 2 copy known
+ {
+ get
+ 2 index 2 copy known
+ { get 3 1 roll pop pop}
+ { pop pop /findresource /undefinedresource ct_raise }
+ ifelse
+ }
+ { pop pop /findresource /undefined ct_raise }
+ ifelse
+ } bind def
+ /resourcestatus
+ {
+ ct_Category 1 index 2 copy known
+ {
+ get
+ 2 index known
+ exch pop exch pop
+ {
+ 0 -1 true
+ }
+ {
+ false
+ }
+ ifelse
+ }
+ { pop pop /findresource /undefined ct_raise }
+ ifelse
+ } bind def
+ /ct_resourcestatus /resourcestatus load def
+ }
+ ifelse
+ /ct_CIDInit 2 dict
+ begin
+ /ct_cidfont_stream_init
+ {
+ {
+ dup (Binary) eq
+ {
+ pop
+ null
+ currentfile
+ ct_Level2?
+ {
+ { cid_BYTE_COUNT () /SubFileDecode filter }
+ stopped
+ { pop pop pop }
+ if
+ }
+ if
+ /readstring load
+ exit
+ }
+ if
+ dup (Hex) eq
+ {
+ pop
+ currentfile
+ ct_Level2?
+ {
+ { null exch /ASCIIHexDecode filter /readstring }
+ stopped
+ { pop exch pop (>) exch /readhexstring }
+ if
+ }
+ { (>) exch /readhexstring }
+ ifelse
+ load
+ exit
+ }
+ if
+ /StartData /typecheck ct_raise
+ }
+ loop
+ cid_BYTE_COUNT ct_CID_STR_SIZE le
+ {
+ 2 copy cid_BYTE_COUNT string exch exec
+ pop
+ 1 array dup
+ 3 -1 roll
+ 0 exch put
+ }
+ {
+ cid_BYTE_COUNT ct_CID_STR_SIZE div ceiling cvi
+ dup array exch 2 sub 0 exch 1 exch
+ {
+ 2 copy
+ 5 index
+ ct_CID_STR_SIZE
+ string
+ 6 index exec
+ pop
+ put
+ pop
+ }
+ for
+ 2 index
+ cid_BYTE_COUNT ct_CID_STR_SIZE mod string
+ 3 index exec
+ pop
+ 1 index exch
+ 1 index length 1 sub
+ exch put
+ }
+ ifelse
+ cid_CIDFONT exch /GlyphData exch put
+ 2 index null eq
+ {
+ pop pop pop
+ }
+ {
+ pop /readstring load
+ 1 string exch
+ {
+ 3 copy exec
+ pop
+ dup length 0 eq
+ {
+ pop pop pop pop pop
+ true exit
+ }
+ if
+ 4 index
+ eq
+ {
+ pop pop pop pop
+ false exit
+ }
+ if
+ }
+ loop
+ pop
+ }
+ ifelse
+ } bind def
+ /StartData
+ {
+ mark
+ {
+ currentdict
+ dup /FDArray get 0 get /FontMatrix get
+ 0 get 0.001 eq
+ {
+ dup /CDevProc known not
+ {
+ /CDevProc 1183615869 internaldict /stdCDevProc 2 copy known
+ { get }
+ {
+ pop pop
+ { pop pop pop pop pop 0 -1000 7 index 2 div 880 }
+ }
+ ifelse
+ def
+ }
+ if
+ }
+ {
+ /CDevProc
+ {
+ pop pop pop pop pop
+ 0
+ 1 cid_temp /cid_CIDFONT get
+ /FDArray get 0 get
+ /FontMatrix get 0 get div
+ 7 index 2 div
+ 1 index 0.88 mul
+ } def
+ }
+ ifelse
+ /cid_temp 15 dict def
+ cid_temp
+ begin
+ /cid_CIDFONT exch def
+ 3 copy pop
+ dup /cid_BYTE_COUNT exch def 0 gt
+ {
+ ct_cidfont_stream_init
+ FDArray
+ {
+ /Private get
+ dup /SubrMapOffset known
+ {
+ begin
+ /Subrs SubrCount array def
+ Subrs
+ SubrMapOffset
+ SubrCount
+ SDBytes
+ ct_Level2?
+ {
+ currentdict dup /SubrMapOffset undef
+ dup /SubrCount undef
+ /SDBytes undef
+ }
+ if
+ end
+ /cid_SD_BYTES exch def
+ /cid_SUBR_COUNT exch def
+ /cid_SUBR_MAP_OFFSET exch def
+ /cid_SUBRS exch def
+ cid_SUBR_COUNT 0 gt
+ {
+ GlyphData cid_SUBR_MAP_OFFSET cid_SD_BYTES ct_GetInterval
+ 0 cid_SD_BYTES ct_cvnsi
+ 0 1 cid_SUBR_COUNT 1 sub
+ {
+ exch 1 index
+ 1 add
+ cid_SD_BYTES mul cid_SUBR_MAP_OFFSET add
+ GlyphData exch cid_SD_BYTES ct_GetInterval
+ 0 cid_SD_BYTES ct_cvnsi
+ cid_SUBRS 4 2 roll
+ GlyphData exch
+ 4 index
+ 1 index
+ sub
+ ct_GetInterval
+ dup length string copy put
+ }
+ for
+ pop
+ }
+ if
+ }
+ { pop }
+ ifelse
+ }
+ forall
+ }
+ if
+ cleartomark pop pop
+ end
+ CIDFontName currentdict /CIDFont defineresource pop
+ end end
+ }
+ stopped
+ { cleartomark /StartData ct_reraise }
+ if
+ } bind def
+ currentdict
+ end def
+ /ct_saveCIDInit
+ {
+ /CIDInit /ProcSet ct_resourcestatus
+ { true }
+ { /CIDInitC /ProcSet ct_resourcestatus }
+ ifelse
+ {
+ pop pop
+ /CIDInit /ProcSet findresource
+ ct_UseNativeCapability?
+ { pop null }
+ { /CIDInit ct_CIDInit /ProcSet defineresource pop }
+ ifelse
+ }
+ { /CIDInit ct_CIDInit /ProcSet defineresource pop null }
+ ifelse
+ ct_Vars exch /ct_oldCIDInit exch put
+ } bind def
+ /ct_restoreCIDInit
+ {
+ ct_Vars /ct_oldCIDInit get dup null ne
+ { /CIDInit exch /ProcSet defineresource pop }
+ { pop }
+ ifelse
+ } bind def
+ /ct_BuildCharSetUp
+ {
+ 1 index
+ begin
+ CIDFont
+ begin
+ Adobe_CoolType_Utility /ct_BuildCharDict get
+ begin
+ /ct_dfCharCode exch def
+ /ct_dfDict exch def
+ CIDFirstByte ct_dfCharCode add
+ dup CIDCount ge
+ { pop 0 }
+ if
+ /cid exch def
+ {
+ GlyphDirectory cid 2 copy known
+ { get }
+ { pop pop nullstring }
+ ifelse
+ dup length FDBytes sub 0 gt
+ {
+ dup
+ FDBytes 0 ne
+ { 0 FDBytes ct_cvnsi }
+ { pop 0 }
+ ifelse
+ /fdIndex exch def
+ dup length FDBytes sub FDBytes exch getinterval
+ /charstring exch def
+ exit
+ }
+ {
+ pop
+ cid 0 eq
+ { /charstring nullstring def exit }
+ if
+ /cid 0 def
+ }
+ ifelse
+ }
+ loop
+ } def
+ /ct_SetCacheDevice
+ {
+ 0 0 moveto
+ dup stringwidth
+ 3 -1 roll
+ true charpath
+ pathbbox
+ 0 -1000
+ 7 index 2 div 880
+ setcachedevice2
+ 0 0 moveto
+ } def
+ /ct_CloneSetCacheProc
+ {
+ 1 eq
+ {
+ stringwidth
+ pop -2 div -880
+ 0 -1000 setcharwidth
+ moveto
+ }
+ {
+ usewidths?
+ {
+ currentfont /Widths get cid
+ 2 copy known
+ { get exch pop aload pop }
+ { pop pop stringwidth }
+ ifelse
+ }
+ { stringwidth }
+ ifelse
+ setcharwidth
+ 0 0 moveto
+ }
+ ifelse
+ } def
+ /ct_Type3ShowCharString
+ {
+ ct_FDDict fdIndex 2 copy known
+ { get }
+ {
+ currentglobal 3 1 roll
+ 1 index gcheck setglobal
+ ct_Type1FontTemplate dup maxlength dict copy
+ begin
+ FDArray fdIndex get
+ dup /FontMatrix 2 copy known
+ { get }
+ { pop pop ct_defaultFontMtx }
+ ifelse
+ /FontMatrix exch dup length array copy def
+ /Private get
+ /Private exch def
+ /Widths rootfont /Widths get def
+ /CharStrings 1 dict dup /.notdef
+ <d841272cf18f54fc13> dup length string copy put def
+ currentdict
+ end
+ /ct_Type1Font exch definefont
+ dup 5 1 roll put
+ setglobal
+ }
+ ifelse
+ dup /CharStrings get 1 index /Encoding get
+ ct_dfCharCode get charstring put
+ rootfont /WMode 2 copy known
+ { get }
+ { pop pop 0 }
+ ifelse
+ exch
+ 1000 scalefont setfont
+ ct_str1 0 ct_dfCharCode put
+ ct_str1 exch ct_dfSetCacheProc
+ ct_SyntheticBold
+ {
+ currentpoint
+ ct_str1 show
+ newpath
+ moveto
+ ct_str1 true charpath
+ ct_StrokeWidth setlinewidth
+ stroke
+ }
+ { ct_str1 show }
+ ifelse
+ } def
+ /ct_Type4ShowCharString
+ {
+ ct_dfDict ct_dfCharCode charstring
+ FDArray fdIndex get
+ dup /FontMatrix get dup ct_defaultFontMtx ct_matrixeq not
+ { ct_1000Mtx matrix concatmatrix concat }
+ { pop }
+ ifelse
+ /Private get
+ Adobe_CoolType_Utility /ct_Level2? get not
+ {
+ ct_dfDict /Private
+ 3 -1 roll
+ { put }
+ 1183615869 internaldict /superexec get exec
+ }
+ if
+ 1183615869 internaldict
+ Adobe_CoolType_Utility /ct_Level2? get
+ { 1 index }
+ { 3 index /Private get mark 6 1 roll }
+ ifelse
+ dup /RunInt known
+ { /RunInt get }
+ { pop /CCRun }
+ ifelse
+ get exec
+ Adobe_CoolType_Utility /ct_Level2? get not
+ { cleartomark }
+ if
+ } bind def
+ /ct_BuildCharIncremental
+ {
+ {
+ Adobe_CoolType_Utility /ct_MakeOCF get begin
+ ct_BuildCharSetUp
+ ct_ShowCharString
+ }
+ stopped
+ { stop }
+ if
+ end
+ end
+ end
+ end
+ } bind def
+ /BaseFontNameStr (BF00) def
+ /ct_Type1FontTemplate 14 dict
+ begin
+ /FontType 1 def
+ /FontMatrix [0.001 0 0 0.001 0 0] def
+ /FontBBox [-250 -250 1250 1250] def
+ /Encoding ct_cHexEncoding def
+ /PaintType 0 def
+ currentdict
+ end def
+ /BaseFontTemplate 11 dict
+ begin
+ /FontMatrix [0.001 0 0 0.001 0 0] def
+ /FontBBox [-250 -250 1250 1250] def
+ /Encoding ct_cHexEncoding def
+ /BuildChar /ct_BuildCharIncremental load def
+ ct_Clone?
+ {
+ /FontType 3 def
+ /ct_ShowCharString /ct_Type3ShowCharString load def
+ /ct_dfSetCacheProc /ct_CloneSetCacheProc load def
+ /ct_SyntheticBold false def
+ /ct_StrokeWidth 1 def
+ }
+ {
+ /FontType 4 def
+ /Private 1 dict dup /lenIV 4 put def
+ /CharStrings 1 dict dup /.notdef <d841272cf18f54fc13> put def
+ /PaintType 0 def
+ /ct_ShowCharString /ct_Type4ShowCharString load def
+ }
+ ifelse
+ /ct_str1 1 string def
+ currentdict
+ end def
+ /BaseFontDictSize BaseFontTemplate length 5 add def
+ /ct_matrixeq
+ {
+ true 0 1 5
+ {
+ dup 4 index exch get exch 3 index exch get eq and
+ dup not
+ { exit }
+ if
+ }
+ for
+ exch pop exch pop
+ } bind def
+ /ct_makeocf
+ {
+ 15 dict
+ begin
+ exch /WMode exch def
+ exch /FontName exch def
+ /FontType 0 def
+ /FMapType 2 def
+ dup /FontMatrix known
+ { dup /FontMatrix get /FontMatrix exch def }
+ { /FontMatrix matrix def }
+ ifelse
+ /bfCount 1 index /CIDCount get 256 idiv 1 add
+ dup 256 gt { pop 256} if def
+ /Encoding
+ 256 array 0 1 bfCount 1 sub { 2 copy dup put pop } for
+ bfCount 1 255 { 2 copy bfCount put pop } for
+ def
+ /FDepVector bfCount dup 256 lt { 1 add } if array def
+ BaseFontTemplate BaseFontDictSize dict copy
+ begin
+ /CIDFont exch def
+ CIDFont /FontBBox known
+ { CIDFont /FontBBox get /FontBBox exch def }
+ if
+ CIDFont /CDevProc known
+ { CIDFont /CDevProc get /CDevProc exch def }
+ if
+ currentdict
+ end
+ BaseFontNameStr 3 (0) putinterval
+ 0 1 bfCount dup 256 eq { 1 sub } if
+ {
+ FDepVector exch
+ 2 index BaseFontDictSize dict copy
+ begin
+ dup /CIDFirstByte exch 256 mul def
+ FontType 3 eq
+ { /ct_FDDict 2 dict def }
+ if
+ currentdict
+ end
+ 1 index 16
+ BaseFontNameStr 2 2 getinterval cvrs pop
+ BaseFontNameStr exch definefont
+ put
+ }
+ for
+ ct_Clone?
+ { /Widths 1 index /CIDFont get /GlyphDirectory get length dict def }
+ if
+ FontName
+ currentdict
+ end
+ definefont
+ ct_Clone?
+ {
+ gsave
+ dup 1000 scalefont setfont
+ ct_BuildCharDict
+ begin
+ /usewidths? false def
+ currentfont /Widths get
+ begin
+ exch /CIDFont get /GlyphDirectory get
+ {
+ pop
+ dup charcode exch 1 index 0 2 index 256 idiv put
+ 1 index exch 1 exch 256 mod put
+ stringwidth 2 array astore def
+ }
+ forall
+ end
+ /usewidths? true def
+ end
+ grestore
+ }
+ { exch pop }
+ ifelse
+ } bind def
+ /ct_ComposeFont
+ {
+ ct_UseNativeCapability?
+ {
+ 2 index /CMap ct_resourcestatus
+ { pop pop exch pop }
+ {
+ /CIDInit /ProcSet findresource
+ begin
+ 12 dict
+ begin
+ begincmap
+ /CMapName 3 index def
+ /CMapVersion 1.000 def
+ /CMapType 1 def
+ exch /WMode exch def
+ /CIDSystemInfo 3 dict dup
+ begin
+ /Registry (Adobe) def
+ /Ordering
+ CMapName ct_mkocfStr100 cvs
+ (Adobe-) search
+ {
+ pop pop
+ (-) search
+ {
+ dup length string copy
+ exch pop exch pop
+ }
+ { pop (Identity)}
+ ifelse
+ }
+ { pop (Identity) }
+ ifelse
+ def
+ /Supplement 0 def
+ end def
+ 1 begincodespacerange
+ <0000> <FFFF>
+ endcodespacerange
+ 1 begincidrange
+ <0000> <FFFF> 0
+ endcidrange
+ endcmap
+ CMapName currentdict /CMap defineresource pop
+ end
+ end
+ }
+ ifelse
+ composefont
+ }
+ {
+ 3 2 roll pop
+ 0 get /CIDFont findresource
+ ct_makeocf
+ }
+ ifelse
+ } bind def
+ /ct_MakeIdentity
+ {
+ ct_UseNativeCapability?
+ {
+ 1 index /CMap ct_resourcestatus
+ { pop pop }
+ {
+ /CIDInit /ProcSet findresource begin
+ 12 dict begin
+ begincmap
+ /CMapName 2 index def
+ /CMapVersion 1.000 def
+ /CMapType 1 def
+ /CIDSystemInfo 3 dict dup
+ begin
+ /Registry (Adobe) def
+ /Ordering
+ CMapName ct_mkocfStr100 cvs
+ (Adobe-) search
+ {
+ pop pop
+ (-) search
+ { dup length string copy exch pop exch pop }
+ { pop (Identity) }
+ ifelse
+ }
+ { pop (Identity) }
+ ifelse
+ def
+ /Supplement 0 def
+ end def
+ 1 begincodespacerange
+ <0000> <FFFF>
+ endcodespacerange
+ 1 begincidrange
+ <0000> <FFFF> 0
+ endcidrange
+ endcmap
+ CMapName currentdict /CMap defineresource pop
+ end
+ end
+ }
+ ifelse
+ composefont
+ }
+ {
+ exch pop
+ 0 get /CIDFont findresource
+ ct_makeocf
+ }
+ ifelse
+ } bind def
+ currentdict readonly pop
+ end
+ end
+%%EndResource
+%%BeginResource: procset Adobe_CoolType_Utility_T42 1.0 0
+%%Copyright: Copyright 1987-2003 Adobe Systems Incorporated.
+%%Version: 1.0 0
+userdict /ct_T42Dict 15 dict put
+ct_T42Dict begin
+/Is2015?
+{
+ version
+ cvi
+ 2015
+ ge
+} bind def
+/AllocGlyphStorage
+{
+ Is2015?
+ {
+ pop
+ }
+ {
+ {string} forall
+ } ifelse
+} bind def
+/Type42DictBegin
+{
+ 25 dict begin
+ /FontName exch def
+ /CharStrings 256 dict
+ begin
+ /.notdef 0 def
+ currentdict
+ end def
+ /Encoding exch def
+ /PaintType 0 def
+ /FontType 42 def
+ /FontMatrix [1 0 0 1 0 0] def
+ 4 array astore cvx /FontBBox exch def
+ /sfnts
+} bind def
+/Type42DictEnd
+{
+ currentdict dup /FontName get exch definefont end
+ ct_T42Dict exch
+ dup /FontName get exch put
+} bind def
+/RD {string currentfile exch readstring pop} executeonly def
+/PrepFor2015
+{
+ Is2015?
+ {
+ /GlyphDirectory
+ 16
+ dict def
+ sfnts 0 get
+ dup
+ 2 index
+ (glyx)
+ putinterval
+ 2 index
+ (locx)
+ putinterval
+ pop
+ pop
+ }
+ {
+ pop
+ pop
+ } ifelse
+} bind def
+/AddT42Char
+{
+ Is2015?
+ {
+ /GlyphDirectory get
+ begin
+ def
+ end
+ pop
+ pop
+ }
+ {
+ /sfnts get
+ 4 index
+ get
+ 3 index
+ 2 index
+ putinterval
+ pop
+ pop
+ pop
+ pop
+ } ifelse
+} bind def
+end
+%%EndResource
+Adobe_CoolType_Core begin /$Oblique SetSubstituteStrategy end
+%%BeginResource: procset Adobe_AGM_Image 1.0 0
+%%Version: 1.0 0
+%%Copyright: Copyright (C) 2000-2003 Adobe Systems, Inc. All Rights Reserved.
+systemdict /setpacking known
+{
+ currentpacking
+ true setpacking
+} if
+userdict /Adobe_AGM_Image 75 dict dup begin put
+/Adobe_AGM_Image_Id /Adobe_AGM_Image_1.0_0 def
+/nd{
+ null def
+}bind def
+/AGMIMG_&image nd
+/AGMIMG_&colorimage nd
+/AGMIMG_&imagemask nd
+/AGMIMG_mbuf () def
+/AGMIMG_ybuf () def
+/AGMIMG_kbuf () def
+/AGMIMG_c 0 def
+/AGMIMG_m 0 def
+/AGMIMG_y 0 def
+/AGMIMG_k 0 def
+/AGMIMG_tmp nd
+/AGMIMG_imagestring0 nd
+/AGMIMG_imagestring1 nd
+/AGMIMG_imagestring2 nd
+/AGMIMG_imagestring3 nd
+/AGMIMG_imagestring4 nd
+/AGMIMG_imagestring5 nd
+/AGMIMG_cnt nd
+/AGMIMG_fsave nd
+/AGMIMG_colorAry nd
+/AGMIMG_override nd
+/AGMIMG_name nd
+/AGMIMG_maskSource nd
+/invert_image_samples nd
+/knockout_image_samples nd
+/img nd
+/sepimg nd
+/devnimg nd
+/idximg nd
+/doc_setup
+{
+ Adobe_AGM_Core begin
+ Adobe_AGM_Image begin
+ /AGMIMG_&image systemdict/image get def
+ /AGMIMG_&imagemask systemdict/imagemask get def
+ /colorimage where{
+ pop
+ /AGMIMG_&colorimage /colorimage ldf
+ }if
+ end
+ end
+}def
+/page_setup
+{
+ Adobe_AGM_Image begin
+ /AGMIMG_ccimage_exists {/customcolorimage where
+ {
+ pop
+ /Adobe_AGM_OnHost_Seps where
+ {
+ pop false
+ }{
+ /Adobe_AGM_InRip_Seps where
+ {
+ pop false
+ }{
+ true
+ }ifelse
+ }ifelse
+ }{
+ false
+ }ifelse
+ }bdf
+ level2{
+ /invert_image_samples
+ {
+ Adobe_AGM_Image/AGMIMG_tmp Decode length ddf
+ /Decode [ Decode 1 get Decode 0 get] def
+ }def
+ /knockout_image_samples
+ {
+ Operator/imagemask ne{
+ /Decode [1 1] def
+ }if
+ }def
+ }{
+ /invert_image_samples
+ {
+ {1 exch sub} currenttransfer addprocs settransfer
+ }def
+ /knockout_image_samples
+ {
+ { pop 1 } currenttransfer addprocs settransfer
+ }def
+ }ifelse
+ /img /imageormask ldf
+ /sepimg /sep_imageormask ldf
+ /devnimg /devn_imageormask ldf
+ /idximg /indexed_imageormask ldf
+ /_ctype 7 def
+ currentdict{
+ dup xcheck 1 index type dup /arraytype eq exch /packedarraytype eq or and{
+ bind
+ }if
+ def
+ }forall
+}def
+/page_trailer
+{
+ end
+}def
+/doc_trailer
+{
+}def
+/imageormask_sys
+{
+ begin
+ save mark
+ level2{
+ currentdict
+ Operator /imagemask eq{
+ AGMIMG_&imagemask
+ }{
+ use_mask {
+ level3 {process_mask_L3 AGMIMG_&image}{masked_image_simulation}ifelse
+ }{
+ AGMIMG_&image
+ }ifelse
+ }ifelse
+ }{
+ Width Height
+ Operator /imagemask eq{
+ Decode 0 get 1 eq Decode 1 get 0 eq and
+ ImageMatrix /DataSource load
+ AGMIMG_&imagemask
+ }{
+ BitsPerComponent ImageMatrix /DataSource load
+ AGMIMG_&image
+ }ifelse
+ }ifelse
+ cleartomark restore
+ end
+}def
+/overprint_plate
+{
+ currentoverprint {
+ 0 get dup type /nametype eq {
+ dup /DeviceGray eq{
+ pop AGMCORE_black_plate not
+ }{
+ /DeviceCMYK eq{
+ AGMCORE_is_cmyk_sep not
+ }if
+ }ifelse
+ }{
+ false exch
+ {
+ AGMOHS_sepink eq or
+ } forall
+ not
+ } ifelse
+ }{
+ pop false
+ }ifelse
+}def
+/process_mask_L3
+{
+ dup begin
+ /ImageType 1 def
+ end
+ 4 dict begin
+ /DataDict exch def
+ /ImageType 3 def
+ /InterleaveType 3 def
+ /MaskDict 9 dict begin
+ /ImageType 1 def
+ /Width DataDict dup /MaskWidth known {/MaskWidth}{/Width} ifelse get def
+ /Height DataDict dup /MaskHeight known {/MaskHeight}{/Height} ifelse get def
+ /ImageMatrix [Width 0 0 Height neg 0 Height] def
+ /NComponents 1 def
+ /BitsPerComponent 1 def
+ /Decode [0 1] def
+ /DataSource AGMIMG_maskSource def
+ currentdict end def
+ currentdict end
+}def
+/use_mask
+{
+ dup type /dicttype eq
+ {
+ dup /Mask known {
+ dup /Mask get {
+ level3
+ {true}
+ {
+ dup /MaskWidth known {dup /MaskWidth get 1 index /Width get eq}{true}ifelse exch
+ dup /MaskHeight known {dup /MaskHeight get 1 index /Height get eq}{true}ifelse
+ 3 -1 roll and
+ } ifelse
+ }
+ {false} ifelse
+ }
+ {false} ifelse
+ }
+ {false} ifelse
+}def
+/make_line_source
+{
+ begin
+ MultipleDataSources {
+ [
+ Decode length 2 div cvi {Width string} repeat
+ ]
+ }{
+ Width Decode length 2 div mul cvi string
+ }ifelse
+ end
+}def
+/datasource_to_str
+{
+ exch dup type
+ dup /filetype eq {
+ pop exch readstring
+ }{
+ /arraytype eq {
+ exec exch copy
+ }{
+ pop
+ }ifelse
+ }ifelse
+ pop
+}def
+/masked_image_simulation
+{
+ 3 dict begin
+ dup make_line_source /line_source xdf
+ /mask_source AGMIMG_maskSource /LZWDecode filter def
+ dup /Width get 8 div ceiling cvi string /mask_str xdf
+ begin
+ gsave
+ 0 1 translate 1 -1 Height div scale
+ 1 1 Height {
+ pop
+ gsave
+ MultipleDataSources {
+ 0 1 DataSource length 1 sub {
+ dup DataSource exch get
+ exch line_source exch get
+ datasource_to_str
+ } for
+ }{
+ DataSource line_source datasource_to_str
+ } ifelse
+ <<
+ /PatternType 1
+ /PaintProc [
+ /pop cvx
+ <<
+ /ImageType 1
+ /Width Width
+ /Height 1
+ /ImageMatrix Width 1.0 sub 1 matrix scale 0.5 0 matrix translate matrix concatmatrix
+ /MultipleDataSources MultipleDataSources
+ /DataSource line_source
+ /BitsPerComponent BitsPerComponent
+ /Decode Decode
+ >>
+ /image cvx
+ ] cvx
+ /BBox [0 0 Width 1]
+ /XStep Width
+ /YStep 1
+ /PaintType 1
+ /TilingType 2
+ >>
+ matrix makepattern set_pattern
+ <<
+ /ImageType 1
+ /Width Width
+ /Height 1
+ /ImageMatrix Width 1 matrix scale
+ /MultipleDataSources false
+ /DataSource mask_source mask_str readstring pop
+ /BitsPerComponent 1
+ /Decode [0 1]
+ >>
+ imagemask
+ grestore
+ 0 1 translate
+ } for
+ grestore
+ end
+ end
+}def
+/imageormask
+{
+ begin
+ SkipImageProc {
+ currentdict consumeimagedata
+ }
+ {
+ save mark
+ level2 AGMCORE_host_sep not and{
+ currentdict
+ Operator /imagemask eq DeviceN_PS2 not and {
+ imagemask
+ }{
+ AGMCORE_in_rip_sep currentoverprint and currentcolorspace 0 get /DeviceGray eq and{
+ [/Separation /Black /DeviceGray {}] setcolorspace
+ /Decode [ Decode 1 get Decode 0 get ] def
+ }if
+ use_mask {
+ level3 {process_mask_L3 image}{masked_image_simulation}ifelse
+ }{
+ DeviceN_NoneName DeviceN_PS2 Indexed_DeviceN level3 not and or or AGMCORE_in_rip_sep and
+ {
+ Names convert_to_process not {
+ 2 dict begin
+ /imageDict xdf
+ /names_index 0 def
+ gsave
+ imageDict write_image_file {
+ Names {
+ dup (None) ne {
+ [/Separation 3 -1 roll /DeviceGray {1 exch sub}] setcolorspace
+ Operator imageDict read_image_file
+ names_index 0 eq {true setoverprint} if
+ /names_index names_index 1 add def
+ }{
+ pop
+ } ifelse
+ } forall
+ close_image_file
+ } if
+ grestore
+ end
+ }{
+ Operator /imagemask eq {
+ imagemask
+ }{
+ image
+ } ifelse
+ } ifelse
+ }{
+ Operator /imagemask eq {
+ imagemask
+ }{
+ image
+ } ifelse
+ } ifelse
+ }ifelse
+ }ifelse
+ }{
+ Width Height
+ Operator /imagemask eq{
+ Decode 0 get 1 eq Decode 1 get 0 eq and
+ ImageMatrix /DataSource load
+ /Adobe_AGM_OnHost_Seps where {
+ pop imagemask
+ }{
+ currentgray 1 ne{
+ currentdict imageormask_sys
+ }{
+ currentoverprint not{
+ 1 AGMCORE_&setgray
+ currentdict imageormask_sys
+ }{
+ currentdict ignoreimagedata
+ }ifelse
+ }ifelse
+ }ifelse
+ }{
+ BitsPerComponent ImageMatrix
+ MultipleDataSources{
+ 0 1 NComponents 1 sub{
+ DataSource exch get
+ }for
+ }{
+ /DataSource load
+ }ifelse
+ Operator /colorimage eq{
+ AGMCORE_host_sep{
+ MultipleDataSources level2 or NComponents 4 eq and{
+ AGMCORE_is_cmyk_sep{
+ MultipleDataSources{
+ /DataSource [
+ DataSource 0 get /exec cvx
+ DataSource 1 get /exec cvx
+ DataSource 2 get /exec cvx
+ DataSource 3 get /exec cvx
+ /AGMCORE_get_ink_data cvx
+ ] cvx def
+ }{
+ /DataSource
+ Width BitsPerComponent mul 7 add 8 idiv Height mul 4 mul
+ /DataSource load
+ filter_cmyk 0 () /SubFileDecode filter def
+ }ifelse
+ /Decode [ Decode 0 get Decode 1 get ] def
+ /MultipleDataSources false def
+ /NComponents 1 def
+ /Operator /image def
+ invert_image_samples
+ 1 AGMCORE_&setgray
+ currentdict imageormask_sys
+ }{
+ currentoverprint not Operator/imagemask eq and{
+ 1 AGMCORE_&setgray
+ currentdict imageormask_sys
+ }{
+ currentdict ignoreimagedata
+ }ifelse
+ }ifelse
+ }{
+ MultipleDataSources NComponents AGMIMG_&colorimage
+ }ifelse
+ }{
+ true NComponents colorimage
+ }ifelse
+ }{
+ Operator /image eq{
+ AGMCORE_host_sep{
+ /DoImage true def
+ HostSepColorImage{
+ invert_image_samples
+ }{
+ AGMCORE_black_plate not Operator/imagemask ne and{
+ /DoImage false def
+ currentdict ignoreimagedata
+ }if
+ }ifelse
+ 1 AGMCORE_&setgray
+ DoImage
+ {currentdict imageormask_sys} if
+ }{
+ use_mask {
+ level3 {process_mask_L3 image}{masked_image_simulation}ifelse
+ }{
+ image
+ }ifelse
+ }ifelse
+ }{
+ Operator/knockout eq{
+ pop pop pop pop pop
+ currentcolorspace overprint_plate not{
+ knockout_unitsq
+ }if
+ }if
+ }ifelse
+ }ifelse
+ }ifelse
+ }ifelse
+ cleartomark restore
+ }ifelse
+ end
+}def
+/sep_imageormask
+{
+ /sep_colorspace_dict AGMCORE_gget begin
+ /MappedCSA CSA map_csa def
+ begin
+ SkipImageProc {
+ currentdict consumeimagedata
+ }
+ {
+ save mark
+ AGMCORE_avoid_L2_sep_space{
+ /Decode [ Decode 0 get 255 mul Decode 1 get 255 mul ] def
+ }if
+ AGMIMG_ccimage_exists
+ MappedCSA 0 get /DeviceCMYK eq and
+ currentdict/Components known and
+ Name () ne and
+ Name (All) ne and
+ Operator /image eq and
+ AGMCORE_producing_seps not and
+ level2 not and
+ {
+ Width Height BitsPerComponent ImageMatrix
+ [
+ /DataSource load /exec cvx
+ {
+ 0 1 2 index length 1 sub{
+ 1 index exch
+ 2 copy get 255 xor put
+ }for
+ } /exec cvx
+ ] cvx bind
+ MappedCSA 0 get /DeviceCMYK eq{
+ Components aload pop
+ }{
+ 0 0 0 Components aload pop 1 exch sub
+ }ifelse
+ Name findcmykcustomcolor
+ customcolorimage
+ }{
+ AGMCORE_producing_seps not{
+ level2{
+ AGMCORE_avoid_L2_sep_space not currentcolorspace 0 get /Separation ne and{
+ [/Separation Name MappedCSA sep_proc_name exch 0 get exch load ] setcolorspace_opt
+ /sep_tint AGMCORE_gget setcolor
+ }if
+ currentdict imageormask
+ }{
+ currentdict
+ Operator /imagemask eq{
+ imageormask
+ }{
+ sep_imageormask_lev1
+ }ifelse
+ }ifelse
+ }{
+ AGMCORE_host_sep{
+ Operator/knockout eq{
+ currentdict/ImageMatrix get concat
+ knockout_unitsq
+ }{
+ currentgray 1 ne{
+ AGMCORE_is_cmyk_sep Name (All) ne and{
+ level2{
+ [ /Separation Name [/DeviceGray]
+ {
+ sep_colorspace_proc AGMCORE_get_ink_data
+ 1 exch sub
+ } bind
+ ] AGMCORE_&setcolorspace
+ /sep_tint AGMCORE_gget AGMCORE_&setcolor
+ currentdict imageormask_sys
+ }{
+ currentdict
+ Operator /imagemask eq{
+ imageormask_sys
+ }{
+ sep_image_lev1_sep
+ }ifelse
+ }ifelse
+ }{
+ Operator/imagemask ne{
+ invert_image_samples
+ }if
+ currentdict imageormask_sys
+ }ifelse
+ }{
+ currentoverprint not Name (All) eq or Operator/imagemask eq and{
+ currentdict imageormask_sys
+ }{
+ currentoverprint not
+ {
+ gsave
+ knockout_unitsq
+ grestore
+ }if
+ currentdict consumeimagedata
+ }ifelse
+ }ifelse
+ }ifelse
+ }{
+ currentcolorspace 0 get /Separation ne{
+ [/Separation Name MappedCSA sep_proc_name exch 0 get exch load ] setcolorspace_opt
+ /sep_tint AGMCORE_gget setcolor
+ }if
+ currentoverprint
+ MappedCSA 0 get /DeviceCMYK eq and
+ Name inRip_spot_has_ink not and
+ Name (All) ne and {
+ imageormask_l2_overprint
+ }{
+ currentdict imageormask
+ }ifelse
+ }ifelse
+ }ifelse
+ }ifelse
+ cleartomark restore
+ }ifelse
+ end
+ end
+}def
+/decode_image_sample
+{
+ 4 1 roll exch dup 5 1 roll
+ sub 2 4 -1 roll exp 1 sub div mul add
+} bdf
+/colorSpaceElemCnt
+{
+ currentcolorspace 0 get dup /DeviceCMYK eq {
+ pop 4
+ }
+ {
+ /DeviceRGB eq {
+ pop 3
+ }{
+ 1
+ } ifelse
+ } ifelse
+} bdf
+/devn_sep_datasource
+{
+ 1 dict begin
+ /dataSource xdf
+ [
+ 0 1 dataSource length 1 sub {
+ dup currentdict /dataSource get /exch cvx /get cvx /exec cvx
+ /exch cvx names_index /ne cvx [ /pop cvx ] cvx /if cvx
+ } for
+ ] cvx bind
+ end
+} bdf
+/devn_alt_datasource
+{
+ 11 dict begin
+ /srcDataStrs xdf
+ /dstDataStr xdf
+ /convProc xdf
+ /origcolorSpaceElemCnt xdf
+ /origMultipleDataSources xdf
+ /origBitsPerComponent xdf
+ /origDecode xdf
+ /origDataSource xdf
+ /dsCnt origMultipleDataSources {origDataSource length}{1}ifelse def
+ /samplesNeedDecoding
+ 0 0 1 origDecode length 1 sub {
+ origDecode exch get add
+ } for
+ origDecode length 2 div div
+ dup 1 eq {
+ /decodeDivisor 2 origBitsPerComponent exp 1 sub def
+ } if
+ 2 origBitsPerComponent exp 1 sub ne
+ def
+ [
+ 0 1 dsCnt 1 sub [
+ currentdict /origMultipleDataSources get {
+ dup currentdict /origDataSource get exch get dup type
+ }{
+ currentdict /origDataSource get dup type
+ } ifelse
+ dup /filetype eq {
+ pop currentdict /srcDataStrs get 3 -1 /roll cvx /get cvx /readstring cvx /pop cvx
+ }{
+ /stringtype ne {
+ /exec cvx
+ } if
+ currentdict /srcDataStrs get /exch cvx 3 -1 /roll cvx /xpt cvx
+ } ifelse
+ ] cvx /for cvx
+ currentdict /srcDataStrs get 0 /get cvx /length cvx 0 /ne cvx [
+ 0 1 Width 1 sub [
+ Adobe_AGM_Utils /AGMUTIL_ndx /xddf cvx
+ currentdict /origMultipleDataSources get {
+ 0 1 dsCnt 1 sub [
+ Adobe_AGM_Utils /AGMUTIL_ndx1 /xddf cvx
+ currentdict /srcDataStrs get /AGMUTIL_ndx1 /load cvx /get cvx /AGMUTIL_ndx /load cvx /get cvx
+ samplesNeedDecoding {
+ currentdict /decodeDivisor known {
+ currentdict /decodeDivisor get /div cvx
+ }{
+ currentdict /origDecode get /AGMUTIL_ndx1 /load cvx 2 /mul cvx 2 /getinterval cvx /aload cvx /pop cvxs
+ BitsPerComponent /decode_image_sample load /exec cvx
+ } ifelse
+ } if
+ ] cvx /for cvx
+ }{
+ Adobe_AGM_Utils /AGMUTIL_ndx1 0 /ddf cvx
+ currentdict /srcDataStrs get 0 /get cvx /AGMUTIL_ndx /load cvx
+ currentdict /origDecode get length 2 idiv dup 3 1 /roll cvx /mul cvx /exch cvx /getinterval cvx
+ [
+ samplesNeedDecoding {
+ currentdict /decodeDivisor known {
+ currentdict /decodeDivisor get /div cvx
+ }{
+ currentdict /origDecode get /AGMUTIL_ndx1 /load cvx 2 /mul cvx 2 /getinterval cvx /aload cvx /pop cvx
+ BitsPerComponent /decode_image_sample load /exec cvx
+ Adobe_AGM_Utils /AGMUTIL_ndx1 /AGMUTIL_ndx1 /load cvx 1 /add cvx /ddf cvx
+ } ifelse
+ } if
+ ] cvx /forall cvx
+ } ifelse
+ currentdict /convProc get /exec cvx
+ currentdict /origcolorSpaceElemCnt get 1 sub -1 0 [
+ currentdict /dstDataStr get 3 1 /roll cvx /AGMUTIL_ndx /load cvx currentdict /origcolorSpaceElemCnt get /mul cvx /add cvx /exch cvx
+ currentdict /convProc get /filter_indexed_devn load ne {
+ 255 /mul cvx /cvi cvx
+ } if
+ /put cvx
+ ] cvx /for cvx
+ ] cvx /for cvx
+ currentdict /dstDataStr get
+ ] cvx /if cvx
+ ] cvx bind
+ end
+} bdf
+/devn_imageormask
+{
+ /devicen_colorspace_dict AGMCORE_gget begin
+ /MappedCSA CSA map_csa def
+ 2 dict begin
+ dup dup
+ /dstDataStr exch /Width get colorSpaceElemCnt mul string def
+ /srcDataStrs [ 3 -1 roll begin
+ currentdict /MultipleDataSources known {MultipleDataSources {DataSource length}{1}ifelse}{1} ifelse
+ {
+ Width Decode length 2 div mul cvi string
+ } repeat
+ end ] def
+ begin
+ SkipImageProc {
+ currentdict consumeimagedata
+ }
+ {
+ save mark
+ AGMCORE_producing_seps not {
+ level3 not {
+ Operator /imagemask ne {
+ /DataSource [
+ DataSource Decode BitsPerComponent currentdict /MultipleDataSources known {MultipleDataSources}{false} ifelse
+ colorSpaceElemCnt /devicen_colorspace_dict AGMCORE_gget /TintTransform get
+ dstDataStr srcDataStrs devn_alt_datasource /exec cvx
+ ] cvx 0 () /SubFileDecode filter def
+ /MultipleDataSources false def
+ /Decode colorSpaceElemCnt [ exch {0 1} repeat ] def
+ } if
+ }if
+ currentdict imageormask
+ }{
+ AGMCORE_host_sep{
+ Names convert_to_process {
+ CSA map_csa 0 get /DeviceCMYK eq {
+ /DataSource
+ Width BitsPerComponent mul 7 add 8 idiv Height mul 4 mul
+ [
+ DataSource Decode BitsPerComponent currentdict /MultipleDataSources known {MultipleDataSources}{false} ifelse
+ 4 /devicen_colorspace_dict AGMCORE_gget /TintTransform get
+ dstDataStr srcDataStrs devn_alt_datasource /exec cvx
+ ] cvx
+ filter_cmyk 0 () /SubFileDecode filter def
+ /MultipleDataSources false def
+ /Decode [1 0] def
+ /DeviceGray setcolorspace
+ currentdict imageormask_sys
+ }{
+ AGMCORE_report_unsupported_color_space
+ AGMCORE_black_plate {
+ /DataSource [
+ DataSource Decode BitsPerComponent currentdict /MultipleDataSources known {MultipleDataSources}{false} ifelse
+ CSA map_csa 0 get /DeviceRGB eq{3}{1}ifelse /devicen_colorspace_dict AGMCORE_gget /TintTransform get
+ dstDataStr srcDataStrs devn_alt_datasource /exec cvx
+ ] cvx 0 () /SubFileDecode filter def
+ /MultipleDataSources false def
+ /Decode colorSpaceElemCnt [ exch {0 1} repeat ] def
+ currentdict imageormask_sys
+ }
+ {
+ gsave
+ knockout_unitsq
+ grestore
+ currentdict consumeimagedata
+ } ifelse
+ } ifelse
+ }
+ {
+ /devicen_colorspace_dict AGMCORE_gget /names_index known {
+ Operator/imagemask ne{
+ MultipleDataSources {
+ /DataSource [ DataSource devn_sep_datasource /exec cvx ] cvx def
+ /MultipleDataSources false def
+ }{
+ /DataSource /DataSource load dstDataStr srcDataStrs 0 get filter_devn def
+ } ifelse
+ invert_image_samples
+ } if
+ currentdict imageormask_sys
+ }{
+ currentoverprint not Operator/imagemask eq and{
+ currentdict imageormask_sys
+ }{
+ currentoverprint not
+ {
+ gsave
+ knockout_unitsq
+ grestore
+ }if
+ currentdict consumeimagedata
+ }ifelse
+ }ifelse
+ }ifelse
+ }{
+ currentdict imageormask
+ }ifelse
+ }ifelse
+ cleartomark restore
+ }ifelse
+ end
+ end
+ end
+}def
+/imageormask_l2_overprint
+{
+ currentdict
+ currentcmykcolor add add add 0 eq{
+ currentdict consumeimagedata
+ }{
+ level3{
+ currentcmykcolor
+ /AGMIMG_k xdf
+ /AGMIMG_y xdf
+ /AGMIMG_m xdf
+ /AGMIMG_c xdf
+ Operator/imagemask eq{
+ [/DeviceN [
+ AGMIMG_c 0 ne {/Cyan} if
+ AGMIMG_m 0 ne {/Magenta} if
+ AGMIMG_y 0 ne {/Yellow} if
+ AGMIMG_k 0 ne {/Black} if
+ ] /DeviceCMYK {}] setcolorspace
+ AGMIMG_c 0 ne {AGMIMG_c} if
+ AGMIMG_m 0 ne {AGMIMG_m} if
+ AGMIMG_y 0 ne {AGMIMG_y} if
+ AGMIMG_k 0 ne {AGMIMG_k} if
+ setcolor
+ }{
+ /Decode [ Decode 0 get 255 mul Decode 1 get 255 mul ] def
+ [/Indexed
+ [
+ /DeviceN [
+ AGMIMG_c 0 ne {/Cyan} if
+ AGMIMG_m 0 ne {/Magenta} if
+ AGMIMG_y 0 ne {/Yellow} if
+ AGMIMG_k 0 ne {/Black} if
+ ]
+ /DeviceCMYK {
+ AGMIMG_k 0 eq {0} if
+ AGMIMG_y 0 eq {0 exch} if
+ AGMIMG_m 0 eq {0 3 1 roll} if
+ AGMIMG_c 0 eq {0 4 1 roll} if
+ }
+ ]
+ 255
+ {
+ 255 div
+ mark exch
+ dup dup dup
+ AGMIMG_k 0 ne{
+ /sep_tint AGMCORE_gget mul MappedCSA sep_proc_name exch pop load exec 4 1 roll pop pop pop
+ counttomark 1 roll
+ }{
+ pop
+ }ifelse
+ AGMIMG_y 0 ne{
+ /sep_tint AGMCORE_gget mul MappedCSA sep_proc_name exch pop load exec 4 2 roll pop pop pop
+ counttomark 1 roll
+ }{
+ pop
+ }ifelse
+ AGMIMG_m 0 ne{
+ /sep_tint AGMCORE_gget mul MappedCSA sep_proc_name exch pop load exec 4 3 roll pop pop pop
+ counttomark 1 roll
+ }{
+ pop
+ }ifelse
+ AGMIMG_c 0 ne{
+ /sep_tint AGMCORE_gget mul MappedCSA sep_proc_name exch pop load exec pop pop pop
+ counttomark 1 roll
+ }{
+ pop
+ }ifelse
+ counttomark 1 add -1 roll pop
+ }
+ ] setcolorspace
+ }ifelse
+ imageormask_sys
+ }{
+ write_image_file{
+ currentcmykcolor
+ 0 ne{
+ [/Separation /Black /DeviceGray {}] setcolorspace
+ gsave
+ /Black
+ [{1 exch sub /sep_tint AGMCORE_gget mul} /exec cvx MappedCSA sep_proc_name cvx exch pop {4 1 roll pop pop pop 1 exch sub} /exec cvx]
+ cvx modify_halftone_xfer
+ Operator currentdict read_image_file
+ grestore
+ }if
+ 0 ne{
+ [/Separation /Yellow /DeviceGray {}] setcolorspace
+ gsave
+ /Yellow
+ [{1 exch sub /sep_tint AGMCORE_gget mul} /exec cvx MappedCSA sep_proc_name cvx exch pop {4 2 roll pop pop pop 1 exch sub} /exec cvx]
+ cvx modify_halftone_xfer
+ Operator currentdict read_image_file
+ grestore
+ }if
+ 0 ne{
+ [/Separation /Magenta /DeviceGray {}] setcolorspace
+ gsave
+ /Magenta
+ [{1 exch sub /sep_tint AGMCORE_gget mul} /exec cvx MappedCSA sep_proc_name cvx exch pop {4 3 roll pop pop pop 1 exch sub} /exec cvx]
+ cvx modify_halftone_xfer
+ Operator currentdict read_image_file
+ grestore
+ }if
+ 0 ne{
+ [/Separation /Cyan /DeviceGray {}] setcolorspace
+ gsave
+ /Cyan
+ [{1 exch sub /sep_tint AGMCORE_gget mul} /exec cvx MappedCSA sep_proc_name cvx exch pop {pop pop pop 1 exch sub} /exec cvx]
+ cvx modify_halftone_xfer
+ Operator currentdict read_image_file
+ grestore
+ } if
+ close_image_file
+ }{
+ imageormask
+ }ifelse
+ }ifelse
+ }ifelse
+} def
+/indexed_imageormask
+{
+ begin
+ save mark
+ currentdict
+ AGMCORE_host_sep{
+ Operator/knockout eq{
+ /indexed_colorspace_dict AGMCORE_gget dup /CSA known {
+ /CSA get map_csa
+ }{
+ /CSD get get_csd /Names get
+ } ifelse
+ overprint_plate not{
+ knockout_unitsq
+ }if
+ }{
+ Indexed_DeviceN {
+ /devicen_colorspace_dict AGMCORE_gget /names_index known {
+ indexed_image_lev2_sep
+ }{
+ currentoverprint not{
+ knockout_unitsq
+ }if
+ currentdict consumeimagedata
+ } ifelse
+ }{
+ AGMCORE_is_cmyk_sep{
+ Operator /imagemask eq{
+ imageormask_sys
+ }{
+ level2{
+ indexed_image_lev2_sep
+ }{
+ indexed_image_lev1_sep
+ }ifelse
+ }ifelse
+ }{
+ currentoverprint not{
+ knockout_unitsq
+ }if
+ currentdict consumeimagedata
+ }ifelse
+ }ifelse
+ }ifelse
+ }{
+ level2{
+ Indexed_DeviceN {
+ /indexed_colorspace_dict AGMCORE_gget begin
+ CSD get_csd begin
+ }{
+ /indexed_colorspace_dict AGMCORE_gget begin
+ CSA map_csa 0 get /DeviceCMYK eq ps_level 3 ge and ps_version 3015.007 lt and {
+ [/Indexed [/DeviceN [/Cyan /Magenta /Yellow /Black] /DeviceCMYK {}] HiVal Lookup]
+ setcolorspace
+ } if
+ end
+ } ifelse
+ imageormask
+ Indexed_DeviceN {
+ end
+ end
+ } if
+ }{
+ Operator /imagemask eq{
+ imageormask
+ }{
+ indexed_imageormask_lev1
+ }ifelse
+ }ifelse
+ }ifelse
+ cleartomark restore
+ end
+}def
+/indexed_image_lev2_sep
+{
+ /indexed_colorspace_dict AGMCORE_gget begin
+ begin
+ Indexed_DeviceN not {
+ currentcolorspace
+ dup 1 /DeviceGray put
+ dup 3
+ currentcolorspace 2 get 1 add string
+ 0 1 2 3 AGMCORE_get_ink_data 4 currentcolorspace 3 get length 1 sub
+ {
+ dup 4 idiv exch currentcolorspace 3 get exch get 255 exch sub 2 index 3 1 roll put
+ }for
+ put setcolorspace
+ } if
+ currentdict
+ Operator /imagemask eq{
+ AGMIMG_&imagemask
+ }{
+ use_mask {
+ level3 {process_mask_L3 AGMIMG_&image}{masked_image_simulation}ifelse
+ }{
+ AGMIMG_&image
+ }ifelse
+ }ifelse
+ end end
+}def
+ /OPIimage
+ {
+ dup type /dicttype ne{
+ 10 dict begin
+ /DataSource xdf
+ /ImageMatrix xdf
+ /BitsPerComponent xdf
+ /Height xdf
+ /Width xdf
+ /ImageType 1 def
+ /Decode [0 1 def]
+ currentdict
+ end
+ }if
+ dup begin
+ /NComponents 1 cdndf
+ /MultipleDataSources false cdndf
+ /SkipImageProc {false} cdndf
+ /HostSepColorImage false cdndf
+ /Decode [
+ 0
+ currentcolorspace 0 get /Indexed eq{
+ 2 BitsPerComponent exp 1 sub
+ }{
+ 1
+ }ifelse
+ ] cdndf
+ /Operator /image cdndf
+ end
+ /sep_colorspace_dict AGMCORE_gget null eq{
+ imageormask
+ }{
+ gsave
+ dup begin invert_image_samples end
+ sep_imageormask
+ grestore
+ }ifelse
+ }def
+/cachemask_level2
+{
+ 3 dict begin
+ /LZWEncode filter /WriteFilter xdf
+ /readBuffer 256 string def
+ /ReadFilter
+ currentfile
+ 0 (%EndMask) /SubFileDecode filter
+ /ASCII85Decode filter
+ /RunLengthDecode filter
+ def
+ {
+ ReadFilter readBuffer readstring exch
+ WriteFilter exch writestring
+ not {exit} if
+ }loop
+ WriteFilter closefile
+ end
+}def
+/cachemask_level3
+{
+ currentfile
+ <<
+ /Filter [ /SubFileDecode /ASCII85Decode /RunLengthDecode ]
+ /DecodeParms [ << /EODCount 0 /EODString (%EndMask) >> null null ]
+ /Intent 1
+ >>
+ /ReusableStreamDecode filter
+}def
+/spot_alias
+{
+ /mapto_sep_imageormask
+ {
+ dup type /dicttype ne{
+ 12 dict begin
+ /ImageType 1 def
+ /DataSource xdf
+ /ImageMatrix xdf
+ /BitsPerComponent xdf
+ /Height xdf
+ /Width xdf
+ /MultipleDataSources false def
+ }{
+ begin
+ }ifelse
+ /Decode [/customcolor_tint AGMCORE_gget 0] def
+ /Operator /image def
+ /HostSepColorImage false def
+ /SkipImageProc {false} def
+ currentdict
+ end
+ sep_imageormask
+ }bdf
+ /customcolorimage
+ {
+ Adobe_AGM_Image/AGMIMG_colorAry xddf
+ /customcolor_tint AGMCORE_gget
+ bdict
+ /Name AGMIMG_colorAry 4 get
+ /CSA [ /DeviceCMYK ]
+ /TintMethod /Subtractive
+ /TintProc null
+ /MappedCSA null
+ /NComponents 4
+ /Components [ AGMIMG_colorAry aload pop pop ]
+ edict
+ setsepcolorspace
+ mapto_sep_imageormask
+ }ndf
+ Adobe_AGM_Image/AGMIMG_&customcolorimage /customcolorimage load put
+ /customcolorimage
+ {
+ Adobe_AGM_Image/AGMIMG_override false put
+ dup 4 get map_alias{
+ /customcolor_tint AGMCORE_gget exch setsepcolorspace
+ pop
+ mapto_sep_imageormask
+ }{
+ AGMIMG_&customcolorimage
+ }ifelse
+ }bdf
+}def
+/snap_to_device
+{
+ 6 dict begin
+ matrix currentmatrix
+ dup 0 get 0 eq 1 index 3 get 0 eq and
+ 1 index 1 get 0 eq 2 index 2 get 0 eq and or exch pop
+ {
+ 1 1 dtransform 0 gt exch 0 gt /AGMIMG_xSign? exch def /AGMIMG_ySign? exch def
+ 0 0 transform
+ AGMIMG_ySign? {floor 0.1 sub}{ceiling 0.1 add} ifelse exch
+ AGMIMG_xSign? {floor 0.1 sub}{ceiling 0.1 add} ifelse exch
+ itransform /AGMIMG_llY exch def /AGMIMG_llX exch def
+ 1 1 transform
+ AGMIMG_ySign? {ceiling 0.1 add}{floor 0.1 sub} ifelse exch
+ AGMIMG_xSign? {ceiling 0.1 add}{floor 0.1 sub} ifelse exch
+ itransform /AGMIMG_urY exch def /AGMIMG_urX exch def
+ [AGMIMG_urX AGMIMG_llX sub 0 0 AGMIMG_urY AGMIMG_llY sub AGMIMG_llX AGMIMG_llY] concat
+ }{
+ }ifelse
+ end
+} def
+level2 not{
+ /colorbuf
+ {
+ 0 1 2 index length 1 sub{
+ dup 2 index exch get
+ 255 exch sub
+ 2 index
+ 3 1 roll
+ put
+ }for
+ }def
+ /tint_image_to_color
+ {
+ begin
+ Width Height BitsPerComponent ImageMatrix
+ /DataSource load
+ end
+ Adobe_AGM_Image begin
+ /AGMIMG_mbuf 0 string def
+ /AGMIMG_ybuf 0 string def
+ /AGMIMG_kbuf 0 string def
+ {
+ colorbuf dup length AGMIMG_mbuf length ne
+ {
+ dup length dup dup
+ /AGMIMG_mbuf exch string def
+ /AGMIMG_ybuf exch string def
+ /AGMIMG_kbuf exch string def
+ } if
+ dup AGMIMG_mbuf copy AGMIMG_ybuf copy AGMIMG_kbuf copy pop
+ }
+ addprocs
+ {AGMIMG_mbuf}{AGMIMG_ybuf}{AGMIMG_kbuf} true 4 colorimage
+ end
+ } def
+ /sep_imageormask_lev1
+ {
+ begin
+ MappedCSA 0 get dup /DeviceRGB eq exch /DeviceCMYK eq or has_color not and{
+ {
+ 255 mul round cvi GrayLookup exch get
+ } currenttransfer addprocs settransfer
+ currentdict imageormask
+ }{
+ /sep_colorspace_dict AGMCORE_gget/Components known{
+ MappedCSA 0 get /DeviceCMYK eq{
+ Components aload pop
+ }{
+ 0 0 0 Components aload pop 1 exch sub
+ }ifelse
+ Adobe_AGM_Image/AGMIMG_k xddf
+ Adobe_AGM_Image/AGMIMG_y xddf
+ Adobe_AGM_Image/AGMIMG_m xddf
+ Adobe_AGM_Image/AGMIMG_c xddf
+ AGMIMG_y 0.0 eq AGMIMG_m 0.0 eq and AGMIMG_c 0.0 eq and{
+ {AGMIMG_k mul 1 exch sub} currenttransfer addprocs settransfer
+ currentdict imageormask
+ }{
+ currentcolortransfer
+ {AGMIMG_k mul 1 exch sub} exch addprocs 4 1 roll
+ {AGMIMG_y mul 1 exch sub} exch addprocs 4 1 roll
+ {AGMIMG_m mul 1 exch sub} exch addprocs 4 1 roll
+ {AGMIMG_c mul 1 exch sub} exch addprocs 4 1 roll
+ setcolortransfer
+ currentdict tint_image_to_color
+ }ifelse
+ }{
+ MappedCSA 0 get /DeviceGray eq {
+ {255 mul round cvi ColorLookup exch get 0 get} currenttransfer addprocs settransfer
+ currentdict imageormask
+ }{
+ MappedCSA 0 get /DeviceCMYK eq {
+ currentcolortransfer
+ {255 mul round cvi ColorLookup exch get 3 get 1 exch sub} exch addprocs 4 1 roll
+ {255 mul round cvi ColorLookup exch get 2 get 1 exch sub} exch addprocs 4 1 roll
+ {255 mul round cvi ColorLookup exch get 1 get 1 exch sub} exch addprocs 4 1 roll
+ {255 mul round cvi ColorLookup exch get 0 get 1 exch sub} exch addprocs 4 1 roll
+ setcolortransfer
+ currentdict tint_image_to_color
+ }{
+ currentcolortransfer
+ {pop 1} exch addprocs 4 1 roll
+ {255 mul round cvi ColorLookup exch get 2 get} exch addprocs 4 1 roll
+ {255 mul round cvi ColorLookup exch get 1 get} exch addprocs 4 1 roll
+ {255 mul round cvi ColorLookup exch get 0 get} exch addprocs 4 1 roll
+ setcolortransfer
+ currentdict tint_image_to_color
+ }ifelse
+ }ifelse
+ }ifelse
+ }ifelse
+ end
+ }def
+ /sep_image_lev1_sep
+ {
+ begin
+ /sep_colorspace_dict AGMCORE_gget/Components known{
+ Components aload pop
+ Adobe_AGM_Image/AGMIMG_k xddf
+ Adobe_AGM_Image/AGMIMG_y xddf
+ Adobe_AGM_Image/AGMIMG_m xddf
+ Adobe_AGM_Image/AGMIMG_c xddf
+ {AGMIMG_c mul 1 exch sub}
+ {AGMIMG_m mul 1 exch sub}
+ {AGMIMG_y mul 1 exch sub}
+ {AGMIMG_k mul 1 exch sub}
+ }{
+ {255 mul round cvi ColorLookup exch get 0 get 1 exch sub}
+ {255 mul round cvi ColorLookup exch get 1 get 1 exch sub}
+ {255 mul round cvi ColorLookup exch get 2 get 1 exch sub}
+ {255 mul round cvi ColorLookup exch get 3 get 1 exch sub}
+ }ifelse
+ AGMCORE_get_ink_data currenttransfer addprocs settransfer
+ currentdict imageormask_sys
+ end
+ }def
+ /indexed_imageormask_lev1
+ {
+ /indexed_colorspace_dict AGMCORE_gget begin
+ begin
+ currentdict
+ MappedCSA 0 get dup /DeviceRGB eq exch /DeviceCMYK eq or has_color not and{
+ {HiVal mul round cvi GrayLookup exch get HiVal div} currenttransfer addprocs settransfer
+ imageormask
+ }{
+ MappedCSA 0 get /DeviceGray eq {
+ {HiVal mul round cvi Lookup exch get HiVal div} currenttransfer addprocs settransfer
+ imageormask
+ }{
+ MappedCSA 0 get /DeviceCMYK eq {
+ currentcolortransfer
+ {4 mul HiVal mul round cvi 3 add Lookup exch get HiVal div 1 exch sub} exch addprocs 4 1 roll
+ {4 mul HiVal mul round cvi 2 add Lookup exch get HiVal div 1 exch sub} exch addprocs 4 1 roll
+ {4 mul HiVal mul round cvi 1 add Lookup exch get HiVal div 1 exch sub} exch addprocs 4 1 roll
+ {4 mul HiVal mul round cvi Lookup exch get HiVal div 1 exch sub} exch addprocs 4 1 roll
+ setcolortransfer
+ tint_image_to_color
+ }{
+ currentcolortransfer
+ {pop 1} exch addprocs 4 1 roll
+ {3 mul HiVal mul round cvi 2 add Lookup exch get HiVal div} exch addprocs 4 1 roll
+ {3 mul HiVal mul round cvi 1 add Lookup exch get HiVal div} exch addprocs 4 1 roll
+ {3 mul HiVal mul round cvi Lookup exch get HiVal div} exch addprocs 4 1 roll
+ setcolortransfer
+ tint_image_to_color
+ }ifelse
+ }ifelse
+ }ifelse
+ end end
+ }def
+ /indexed_image_lev1_sep
+ {
+ /indexed_colorspace_dict AGMCORE_gget begin
+ begin
+ {4 mul HiVal mul round cvi Lookup exch get HiVal div 1 exch sub}
+ {4 mul HiVal mul round cvi 1 add Lookup exch get HiVal div 1 exch sub}
+ {4 mul HiVal mul round cvi 2 add Lookup exch get HiVal div 1 exch sub}
+ {4 mul HiVal mul round cvi 3 add Lookup exch get HiVal div 1 exch sub}
+ AGMCORE_get_ink_data currenttransfer addprocs settransfer
+ currentdict imageormask_sys
+ end end
+ }def
+}if
+end
+systemdict /setpacking known
+{
+ setpacking
+} if
+%%EndResource
+currentdict Adobe_AGM_Utils eq {end} if
+%%EndProlog
+%%BeginSetup
+Adobe_AGM_Utils begin
+2 2010 Adobe_AGM_Core/doc_setup get exec
+Adobe_CoolType_Core/doc_setup get exec
+Adobe_AGM_Image/doc_setup get exec
+currentdict Adobe_AGM_Utils eq {end} if
+%%EndSetup
+%%Page: Alternate-ISC-logo-v2.ai 1
+%%EndPageComments
+%%BeginPageSetup
+/currentdistillerparams where
+{pop currentdistillerparams /CoreDistVersion get 5000 lt} {true} ifelse
+{ userdict /AI11_PDFMark5 /cleartomark load put
+userdict /AI11_ReadMetadata_PDFMark5 {flushfile cleartomark } bind put}
+{ userdict /AI11_PDFMark5 /pdfmark load put
+userdict /AI11_ReadMetadata_PDFMark5 {/PUT pdfmark} bind put } ifelse
+[/NamespacePush AI11_PDFMark5
+[/_objdef {ai_metadata_stream_123} /type /stream /OBJ AI11_PDFMark5
+[{ai_metadata_stream_123}
+currentfile 0 (% &&end XMP packet marker&&)
+/SubFileDecode filter AI11_ReadMetadata_PDFMark5
+<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?><x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='XMP toolkit 3.0-29, framework 1.6'>
+<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'>
+
+ <rdf:Description rdf:about='uuid:8aa76b3d-2474-11d9-a8a3-000393cd9a96'
+ xmlns:pdf='http://ns.adobe.com/pdf/1.3/'>
+ <pdf:Producer>Adobe PDF library 6.66</pdf:Producer>
+ </rdf:Description>
+
+ <rdf:Description rdf:about='uuid:8aa76b3d-2474-11d9-a8a3-000393cd9a96'
+ xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
+ </rdf:Description>
+
+ <rdf:Description rdf:about='uuid:8aa76b3d-2474-11d9-a8a3-000393cd9a96'
+ xmlns:xap='http://ns.adobe.com/xap/1.0/'
+ xmlns:xapGImg='http://ns.adobe.com/xap/1.0/g/img/'>
+ <xap:CreateDate>2004-10-06T16:15:40-07:00</xap:CreateDate>
+ <xap:ModifyDate>2004-10-22T21:51:43Z</xap:ModifyDate>
+ <xap:CreatorTool>Illustrator</xap:CreatorTool>
+ <xap:MetadataDate>2004-10-06T16:15:40-07:00</xap:MetadataDate>
+ <xap:Thumbnails>
+ <rdf:Alt>
+ <rdf:li rdf:parseType='Resource'>
+ <xapGImg:format>JPEG</xapGImg:format>
+ <xapGImg:width>256</xapGImg:width>
+ <xapGImg:height>152</xapGImg:height>
+ <xapGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAmAEAAwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8AiX5AfkB5O/MTydea1rV5&#xA;qNvdW+oyWSJZSQJGY0ghlBIlhmblymPfMfLlMTQbIQBDOPM//OKX5U6B5e1DWZ9R1uSOxhaX0hcW&#xA;il2H2U5G0NOTUFcOCcskxAVuWOaoQMj0Y1+Wf5EflJ56N+kUuvWEtgImZHu7OTmJS4+Glmv2eG+3&#xA;fMvXYJ6etwb8v2uPpNRHNdCqZz/0Jp+WH/V01v8A5H2n/ZLmv/MSczww7/oTT8sP+rprf/I+0/7J&#xA;cfzEl8MO/wChNPyw/wCrprf/ACPtP+yXH8xJfDDAfzv/AOcc/JHkPyHN5g0i+1Oe9juIYVju5bd4&#xA;uMrUYkRwRNXw+LJ48xkaRKAAfT/5V/8AksPKH/bE07/qEjzJaiynFXYq7FXYq7FXYq7FXYq7FXYq&#xA;7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq+BfyU/MTzH5Nhnn0yUPbSzt9ZsZqtBJ8CAMVBFGHZ&#xA;hv8ARtmz0uihnwkS58XPryDrdVqp4sorlXL5st1/z/8AmP5whlgu7p20+b7VnCqwW9AwYL250YD7&#xA;TE5eI6TSncgS+Zccy1OoGwPD8ggfLXmTzl5HvJLzTD9X9YKtwroksUiqSVVjvTc9iDlkp6bVjhsS&#xA;+wsIxz6Y3Vfc9B1b/nJjWZ9Hhh03TYrPVmH+lXTt6sQp/vqM/wA3+UTT365iY+w4CVyNx7v1uTPt&#xA;eRjsKk9s8j+YrjzH5W0/Wbm0aymu4wzwtsCRsXTcng1KrXemaHV4RiyGAN07jT5TkgJEVae5jNzx&#xA;v/nLL/yT91/zG2v/ABM5dg+pjPk9M/Kv/wAlh5Q/7Ymnf9QkeZzjllOKuxV2KuxV2KuxV2KuxV2K&#xA;uxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV+eX5W6Yl7aztLvBDMSy/zEqtB8tsyJ644NP6fr&#xA;lI18hZcX8oMuf1fTGP6S9h0Ly3rGtzm20q1M7RgF6UVEXtyZiFHTbOa3ke8u52Adr3lvWNEnFtqt&#xA;qYWkUlCSGRx3oykqeu+DeJ7iuxDANasU07UIriJFaF29RYmAK8kILKVPVc7bsjWnUYiJfVHY/oLy&#xA;/aOlGHIDH6S+zNB1K31TRNP1K2UJb3lvFPEg6KsiBgu38taZzGaBhMxPMF6DHMSiCOoR2VM3jf8A&#xA;zll/5J+6/wCY21/4mcuwfUxnyemflX/5LDyh/wBsTTv+oSPM5xyynFXYq7FXYq7FXYq7FXYq7FXY&#xA;q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq+A/yedP0NepT4xccie5BRR+FMxNfE8ET0uX+9bNP&#xA;IcZHWh+l9K/kxr2kW1neaZcSxwXskwmjaQhfUUqF4qT1Kla098wMUg5Mgq/nNrujzada6XDKk9+s&#xA;4mbgQ3pIEZaMR0Lcht9PhjlIWIeCebnQQ26U+MszA+AAAP31zoPZyJ4pnps6ftqQqI67s3/KGD81&#xA;YPMejRFNVh8ts6tKJ0mFp6HAsOPqDgFYUoVzYdonTGEvp4/hduJoRnE4/VwfY+lCyggEgE9B45yr&#xA;0Lxb/nLe8tYvyoe2kkCz3N7bmCM9W9NqtT5A5bhI4wFlAmBI5B6l+Vf/AJLDyh/2xNO/6hI8z3EL&#xA;y3/nLq+1nQPJem69oWsalpWoyapHZytZX11BG8UltM5BijkVK8oFoaePjir0v8ooJB+W/lq8nu7u&#xA;9vNR0uyvLy5vbme6keaeBZXPKZ34jk52XbFWYYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F&#xA;XYq7FXYq7FXYq7FX5z/l3fy2Nq88Y5D1mDodgylE2zaafSR1GnMJfztvI0HWanUSw5xIfzf0l6Zb&#xA;a3plwnITrGe6SkIR9+x+jOdz9k6jGa4TId43dti7QwzF8Ve/Zq61zTLdORmWU9kiIcn7th9Jw6fs&#xA;nUZD9PCO+W37Vzdo4YDnfu3S3y5bW3mjzpptlqVwtnZ3U6xO5JoEFTwBAPxP9kH+Y+GdXDCNJpyI&#xA;CyBfvPf+Ojz5ynU5xxbAvozTPzt/L2W4vbT60bO109R6E8qFY5kX4SIVUF9uylakduucN+aiSbfQ&#xA;Z9gamMYkC+LoOnveJeYvzDnP5kTeatBmlMUUoayS7qRxMYSRCgbZHPLYHp4HMKWT18Qet03Zo/Kj&#xA;DkA5b179vixD84/zA8y+btFi/TEsbJaSVt44o1jVTIRy6bn7I6nMzRZJSyi+4un7Y7OxabSS8Mcz&#xA;G32N+Vf/AJLDyh/2xNO/6hI83jwxeUf85q/+Ss0r/tuW/wD1CXeKvVfyn/8AJWeTf+2Hpv8A1CR4&#xA;q8j8x/nX5n8ifnH5nGr28+o/l4tzp9rNKnxtp082nwSckAqQklWYp0Y1K/FUFV7F5gutN1/yJe6h&#xA;pmoSNaT2M1xY6jp1zJC1fRfi6SwMh2PY9+o2xVjP5faLe+ZPyb8tx3WtanDPqNraXmo6jHeXBvpD&#xA;QSMqXLSGSIOwAbifs1HeuKvOfzm0m/8ALHnz8tdI0fzJ5hhsfMmqG01aNta1GQyRC4tI6KzTEp8M&#xA;77rir2bQfIEWia5+kbXWtYurZ7SW2msNQ1G7voS7yROkyC4kk4OgjZajs2KvH9Is9R1n/nJrzd5Q&#xA;utf12Py9p+mRXtnZQavqEQjmaOxJIZZg1K3D7Vpvir2Xy/5JTSdO1PTZdW1PUbS9ujcW8l3fXUlz&#xA;bxmGKMwpcmT1uIkjZx8X7WKvB/8AnH/RPMX5gflhrGqaj5x8wQa/BqE9rYagNWvfTjEdtBLH6kLS&#xA;NG685TyqtaYq9K/5xr86+aPOH5Yw6n5kJlvYbqa1hvWADXMMQUrK3EAVDM0ZPfjirHPzm/M7zt5G&#xA;/M6wvNIt5NV8u22jC78waSrbCD620RuUG5R0LKC4FKfa23Cr1fyr5t8s+ePLcWraHeG5066HFzG7&#xA;RTROAC0UnAq8ci13FfwOKsS/JBbuS183fXNQv9Qaz8y6rp1s97eXFyUtbaVUijX1XYLxA6jfFWA6&#xA;RZ6jrP8Azk15u8oXWv67H5e0/TIr2zsoNX1CIRzNHYkkMswalbh9q03xV6vB+XE8Oi3+ijzJrJs7&#xA;2/S8W5e+uJL6GBI4gbWK8eQzIjSxFiQfssy964q8i/ObSb/yx58/LXSNH8yeYYbHzJqhtNWjbWtR&#xA;kMkQuLSOis0xKfDO+64q9n0DyDFoWvDU7XWtXurdrWW2m0/UdRur+Eu8kTpMq3MknF0EbLUdmxVl&#xA;WKuxV2KuxV2KuxV8tf8AOKPkvyrr35Z6zJq+mQ3k02qy2zTSL+8WJLa3dVRxRk+JyaqQcqnqsmMj&#xA;hkR1T4EJg8QtKPzn/LXS/JV9pzaXNNJaakJisc5VijQlKqGULUfvO4zoezNdLODxAXGnR6/SRwkc&#xA;PIsk/Ln8gtN17QNP17V9RnSO9VpPqMCKhCh2VaysXryVQ32B1+nMXW9ryxzMIgbdf2ORpezIziJS&#xA;PPownzdp3kO384XUWjyXMOkWbMrRg82kkiFCsEjVKhn25PWg+LfZc1uP2mIgRKPFLoeh9/7Ofk9P&#xA;H2GyT4JxkIxl9Q6x93f+hj2oXjXt9cXjIsbXEjStGleILmpArU985ORs2+nYcfhwEbJ4RW/PZG2X&#xA;l+4mAec+ih6LSrn6O2TjiJdNre38WI8MPXL7Pn+Pek/5j6Pa2nliWWMuW9WMfEQep9gM2GhxgZHm&#xA;O0u2cuoxGEhER8v7X2j+Vf8A5LDyh/2xNO/6hI83LzpeUf8AOapH/KrdKWu51yAgd6C0uv64q9V/&#xA;KYg/lZ5Np/1Y9N/6hI8VYb5Q0/SvMf5j/nBpWq2yXNhdzaVbXVq+4ZBp/p12oQTwqCNwehqMVea6&#xA;5Yeb/wAgZ9Tgtlm1r8qtdWWJVrym0+edCq1rQA1NK/ZkHg2Kvevyiiji/KrycqDip0TT2I93tY2Y&#xA;/STiryz/AJyO/wDJp/kv/wBtw/8AUXp+KvoDFXzXp/lvSfMH/OXnney1P6x6CaPbzJ9VurmyfmsG&#xA;nKKyWskLkUY/CWp3psMVe6+U/LmkeW0vdK064llV5hfGK5nluZo1nURqGlneSRlLQNxLH27Yq+XP&#xA;yK8n+e9f/IrzOPKfmS5025fULiJdIRLcQ3LLa2zOPXaP6xE8qNwqkqjYV74q93/Ij8xPLvmnyhBp&#xA;tjaR6Pq2hItnqnl9FMZtnj+CqI3xemxB3O4NQ2+KqFxLDN/zkwllKitGfJMpYPQhxLqiqUKkb7R4&#xA;q8984/l15r/JzzNP+YP5axNd+WZjy8w+WBXikIqzMgFf3a7lSByj90qMVehf8476tZ635O1fXrON&#xA;ooNZ8watqCJJTmFuLkugehI5BKA0xV57p/lvSfMH/OXnney1P6x6CaPbzJ9VurmyfmsGnKKyWskL&#xA;kUY/CWp3psMVe6+U/LmkeW0vdK064llV5hfGK5nluZo1nURqGlneSRlLQNxLH27Yq8e/5yO/8mn+&#xA;S/8A23D/ANRen4q+gMVdirsVdirsVdirsVfOv/OGn/ksNU/7bc//AFCWuYeo+pux8ntWreX9C1hE&#xA;TVtOttQWLl6X1mFJeHOnLhzB41oOmQx5pw+kke5M8UZ/UAUFq3mDyp5P0+zhv7iLTLI0t7KMIxUB&#xA;F+yqxq1AB36ZTlzC7kdy5ek0OTN6cUb4Q+XvzM13S9c866lqGmRJHZO4SOSMcfWKDi0xG28h36dO&#xA;u+arLIGRIfRey9PPDp4xmfV93l8EHoGmqVF5KtTX9yD2p+1/TJ4odXS9vdpkHwYH+t+r9f8AanuZ&#xA;DyTEPzS/5RKX/jNF/wASzJ0f1teb6X2H+Vf/AJLDyh/2xNO/6hI82zhlb51/K3yR52EK+aLGXUYr&#xA;ducMBvLyGJXpx5CKGaNOVO9MVTHy15Q0Ly1p0em6MlxBYQp6UFvJd3VwkaDosYnll4AduOKoTRfy&#xA;68p6Lr1/r2m29xDq2qFG1G4a9vZfXMYIT1ElmeNuAYhart2xVPNS03T9TsJ9P1G3ju7G6QxXFtMo&#xA;eN0bYqynYjFWtK0yx0rTLPS9Pi9CwsII7W0hBZgkMKBI1qxZjxVQNzXFWO+avys8j+a9VstV16xm&#xA;u7/TW9TT5heXkIgcFTyiSGaNENY1NQOoxVlFvAkEKQoXKIKAyO8jfS7lmP0nFWDXn5Gflnd69P5g&#xA;n066Ot3NPW1FNT1KOZqKEHxpcqacVAxVO9F8g+WdFsr6z02K5ij1Fle8le+vZZ3ZAFWlxLM8y0Ap&#xA;RXGKqPkr8s/JfkmGWDyxZSafbzuZZbf63dzRNIVCl/TmlkTlxUCtMVWXX5XeRbjzT/ir9Gm28wkF&#xA;ZNRs7i5s5JAQAfVFtJEslaCvMHFVWb8ufKU3mtfNklvcnzAkRt0vhfXqlYCxcxCMTCMR8mJ4caYq&#xA;yUgEUO4PUYql2g+W9D8v2cllotlHYWck0lw1vCCsYklNXKrWignstBirFLz8jPyzu9en8wT6ddHW&#xA;7mnraimp6lHM1FCD40uVNOKgYqyLyx5N8v8AllLpNHhmjN66y3Ulxc3N5I7KvFayXUkz0A7A0xVL&#xA;vNX5WeR/Neq2Wq69YzXd/prepp8wvLyEQOCp5RJDNGiGsamoHUYqyi3gSCFIULlEFAZHeRvpdyzH&#xA;6TiqpirsVdirsVdirsVfOv8Azhp/5LDVP+23P/1CWuYeo+pux8nvOY7Y8/8Azo8q6Nq/lK61O/eW&#xA;O40aCaayeJqLzYCiupqCGZVB75j6mAMbPR3XYeryYs4hGqmQC+XIYmlmjiX7UjBR82NM1z3+XIIR&#xA;MjyAtmqIqIqIKKoCqPADYZmgU+X5MhnIyPMm12Fghvzc8i6jZ/lNJ5hvHEKS3FsLe1pV2SRtnY1+&#xA;HboMy9JH1W1ZTs+nfyr/APJYeUP+2Jp3/UJHm0cQph5t84eXfKWjSaxr94tnZIwRWILvJI32Y441&#xA;DO7t2Cj8MVYZqX57aRpCQXOs+V/Mel6ZcOkUep3ViiwBpCAgfjM0sfIttzQYq9MxV2KuxV2KuxV2&#xA;KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvnX/nDT/wAlhqn/AG25/wDqEtcw9R9Tdj5P&#xA;ecx2x4p+e3lfzteTXGr2dy7eXLa1Q3NoJ2ChkY839H7J6jf2zC1MJXfR6z2f1eniBCQ/emWxr9Lw&#xA;yw/3utv+Mqf8SGYkeYen1wvBP+pL7mZZmvmTsVZ7/wA5N6hZ6h+Rn12zINtNc2bRhabDkfh27r0O&#xA;bDTm5Boyci9X/Kv/AMlh5Q/7Ymnf9QkeZ7jF43/zl1Lrmk3vkTzVBAbvSNC1Fp7m3IPpfWFeGWES&#xA;0rtIsLqK9PpxV6v5X84+R/zX8mXB06cXFleRGDULJqLc27Ov2ZENeLKd0bcGlQTiqF1P85dE0r8w&#xA;NN8j6ppGp2OpauwXTr6ZLX6lKDWhWVbhm+0OPHhyrTbcYqnfn7z3pvkrRYtWv7S7vo5rmGyhtbBY&#xA;pLiSa4PGNUjlkh5knspJ9sVa1vz9pOg6TZX2t29zY3WozJbWGjlY576a4k+zFHHbPOrN40eg7nFV&#xA;C2/MOI6rHp2p6DqujGaGa5hur2O2Nu0cCeo/7y3nuOLcd+D0b2xVj+t/njDofl6TzFq/kvzJZaPC&#xA;sby3M0OnrxEzrGnKP676gq7qKccVRNp+cf1rSrPWU8meYho97HDPFf8Ao2DRiC4CskzLHePIE4sG&#xA;Y8dh1xVW8+/nFpHknXNH0bUtG1S7u9flNvpDWS2jpPMGjTgPUuYmU8p0HxAdcVR+kfmFNfa7a6Pe&#xA;eV9a0aW9SV7e6v47P6uTCvJkL29zcEMR0FMVTTW/OGiaLrWiaPqEpiu/MEssGnGg4GSGP1CrGu3I&#xA;bLtudsVTvFUj8u+cdD8w3utWelymWTQb06ffNQcfXWNXbgQTUKX4GtPiU/MqobzF5/0XRdZtNBEV&#xA;zqfmC+jae30iwjEs/oKeLTSF2jiij5bcpHUE9MVVPLXnBNb1HUdNl0nUNH1DTEgkuLfUY4V5JcmV&#xA;Y3ikt5biKRawOCVfFWQ4q7FXYq7FXYq7FXYq7FXYq+df+cNP/JYap/225/8AqEtcw9R9Tdj5Pecx&#xA;2x51+eHmy/0HysLa2sUuYdZE1jPPIW4xCSOlAi05MyluPxbU6HMfUzMRXe7zsHRxzZrMqMKlXfu+&#xA;YCHR6EFXU7g7EEZrn0AgEeTMrO5W5to5l/bHxAdj3H35mRlYfNNbpjgyygenL3dFbJOIxj80NQvk&#xA;8i3Fis7izluIXe35HgWVtm49K++ZWj+trzfS+u/yr/8AJYeUP+2Jp3/UJHm1cMpxrekaHr2nXeh6&#xA;vbxX1lcxgXdlLQ1jcnixA+JfiQ8WHcbbjFXx/wCefJXmT/nHvz/p3mzy1cyXHli9mMSo7fEU+1JZ&#xA;XIFA1UFUf2rsVxV9Efnb+XUf5geRuWnEx6/ptNR8vXa1WRZlAb0ww+IeqAB7NxPbFWLfk35j1D83&#xA;LrTPOOsxenY+VIhaW9r+xNrTxA3N5xB+ykLqIlP2S7HFU7/Pv8vvN/mO20LzF5MuBH5o8p3El3YW&#xA;zlQswlCc1Bf4OX7paB/hIqD1xVA/lD+ek/mzXn8necdGOh+drBWlELIyxSlFIdo1kq8T8GJpUgrU&#xA;hqbYqmH/ADlH/wCSJ8zf9GP/AHULfFWVflQA35VeTlYVB0LTQQehH1OPFXkn/OTk89v+Y35Pz29u&#xA;95PFrEjw2kbIjyut1YFY1aRkQFzsCzAeJxV61onm/wAwahr0Ol6n5SvdFR4JrlLy6uLKaP8AcsiF&#xA;V+qzXB5H1h1ptirxr/nJzRvMHmLzXZRaFM8eoeTNDm8ywrGKuXN7DH8BrXmEt3kX4TulO+Ks6i/O&#xA;car+TVj5q0dFk8x6z6el6fp43/3MzH0fTof2Uesu/wDusVxVhn/OMdldeWPP/wCYvkq8uWu5rOe3&#xA;uVuXJ5SGsgkkIPd/UQ4qmv5xeUPzP0Pz/b/mj+XcS6ldrZDT9X0dl9RpIUfn8EYKtIrUWqoeYK1F&#xA;a7Ksv/Jv839H/MewvZVsW0rzDphSDWNOloXQ1fgVchWZOQfZgCpqCO5VejYq7FXYq7FXYq7FXYq7&#xA;FXYq+df+cNP/ACWGqf8Abbn/AOoS1zD1H1N2Pk95zHbGiqkgkAlTUHwNKfxxS+UPzkutEufzA1KT&#xA;SkdOLCO+5rwU3UfwylFNDTYVr1apzV5iOI0+jdiQyR00RP4f1ejGNK1RrOQq9Wgf7Sjsf5hkYTpe&#xA;1ezBqY2Nsg5H9BZRDNFNGJImDoejDMoEF4TNgnilwzFFif5pf8olL/xmi/4lmVo/rcXN9L7D/Kv/&#xA;AMlh5Q/7Ymnf9QkebZwykHm1PzQ0f8w18xeWdIh8w6BeaZBYajpf1uO0uVnt7i4lSaJp6RfZuaHf&#xA;f2oDirH/ADj5I89/mxe6Rp3mfSI/K/k3TLpb+8tXuoru/u5kVkRF+r8ook4uwJ5k71xV7DdzSW1o&#xA;8kFs908Y/d2sJjV27UUytGg+lhirx7/nGDyX5z8keT7/AEHzPo0thcz6lLexTie0miMb28MYH7ma&#xA;R+XKE/s4qzXzNqX5haV5piutG0L/ABB5euLRIrq2huoLa5guY5Xb1Y1uWjidWRwGHMHb23VY/pvk&#xA;zzH5j/NnTvzB1/SU0CDQbGSz0ywaaK4vJpZxIjyTvbs8KIkcrBUDtua1xVGf85AeXvMnmb8r9V8u&#xA;eXtNk1HUtSNuIwstvCiCC6hnYu08kXVYzTjXFU9/LC11iw8haBpGr6bLpt/pWnWllcRyyW8oaS3h&#xA;WJijQSSgiqV3p1xV5z+fXlHz/r/nbyHq/lny9JqsHlO+a/umN1Z26y1mtZljT1plf/j3YElcVZ/p&#xA;3mfz3qGr6fay+TrrRtPeR21HULy70+ZUjWJyqpHbXE0jM8vBelAN8VSnyzpHmVvzd8z+YNU0S4tN&#xA;Jv7KxsNKuZJbSRSluJHnMkcVxI68pHAX4DXvTFWOflr+Q0vlP8ytZ1R5eflS3ma78q6dyDJFc3iB&#xA;LiUx/stCiekh7qcVdZ+TPO2hf85H635ztNElvfK+uWEdrNPBPaKVlWKD4/Rlmhf7dvStD9onFWXX&#xA;ut/mbpHmnWI4/K7+YfLtzJFNpNzZ3tpDNCBbRRywyxXckAoZkd1Kt3xVB/lr5C1ew84eavPWu28O&#xA;nap5nkhWLSbdxKttb26BAZJFCq8spHJ+OwPc1xV6RirsVdirsVdirsVdirsVdir51/5w0/8AJYap&#xA;/wBtuf8A6hLXMPUfU3Y+T3nMdsQGoa9omnT29vf30FrcXTrHbQyyKryO7cVCKTU1O2WwwzkCYgkB&#xA;hLJGJomrQd15K8p3eoXWo3WlW897ex+jczyIGZkC8e+wPHao3zGOKJNkOdDXZoxEYzIjE2Hyf5k0&#xA;uzj81alp2hRTzWkFxLHbRspaXhETy2ArQUPUVp1zWGO5p9G0+c+DGWUgSIHuspTBc3Fu/OFzG3en&#xA;eniO+AGm7Pp8eWNTAkEr896vd3Plp4JuLD1IzzpRtj7Gn4ZsNBMnJReT7d7Jw4cByQsGx12/Hxfb&#xA;v5V/+Sw8of8AbE07/qEjzePFFlOKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV&#xA;2KuxV2KuxV86/wDOGn/ksNU/7bc//UJa5h6j6m7Hye85jtj5B/OE2S/mVrEun3KTwvKkglicOFkM&#xA;amReQJ3WSvyztuzb8CIkKeW19eMSCzGx/wCcmfMNvaWsM+k29zJDGqTztI6tKyinPYUUnqeuYM+w&#xA;4EkiRDlR7XkALDBvzG8+t5y1tNSXT49NVIkQxxkO7utfjkkCoXO9FqNhmZoezoaeyN5Hr+hp1naW&#xA;TOBAkiEeUb2vvZjpf5M+bNeg8vanNJHLYX8UL3tz6oNwkUjGQu4YDkwjYKtGY9K0zi+1cHFqZcIA&#xA;jfT7ftfRewO2oYNCIzMjkAJF7+4Wln/ORn5QaL5T8irq+k3F1KGvIYJobgo6qrh25hkRKfEoXfxy&#xA;OlwCGQENGt7ZyanBKExEcjt7w+kPyr/8lh5Q/wC2Jp3/AFCR5tnnCxj88Pzoi/LzTrSz061Gpeat&#xA;YPDSrA1KD4gvqyhSGK8moqjdjtUbnFXaF+WHnPUrGO988+dNYfV5xzmsNGuf0bZ25bf0k+rKkknD&#xA;pyL7+GKpJ5+/Lfz15b0afzB5N89a4X04fWbvTNUufr8UluhDS+m8ysyssYLDlyrSm2Kva8VdirsV&#xA;dirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVfHH5K/mFceTPyPvZrD021W98wzR2qyg&#xA;soSO0tGlYgUqKUXr+1lul0Yz5al9IH9jRqtUcWOx9RKa+aP+cgPNGu+XW0lLaLTZ5zS7vLV3BeKm&#xA;8aK1SnLueZ22za4Ox8eOfFfF3AutzdpznDhqnmkUApyfv0X+uYHavb/gyOPFRkOZ6D9r1Hs97HnU&#xA;wGbOTHGeURzkO/yH2nyVQqAEBVofYE/ed85qXbOqJvjP2Pcx9l+z4x4fCj9pPzu1jwIw+H4W/A5t&#xA;tB7RzEhHNvH+d1H4/FvOdsew+MxM9L6ZD+AmwfcTuD7yR7no/wCT/wCbcnlK4k0vWZJJNAkDsigF&#xA;3gmAJ+AdeLnYr47+Ob3tHs8ZwJwri+8PBaLWHCTCd19xX/n5+cXlzzh+Xt/pGm29zC8c1vOs1yEQ&#xA;OElClVVWc/t1zUz7MyYQJSI+Ds8WvhlJiL5Poj8q/wDyWHlD/tiad/1CR5BtL5u8+3Bv/wDnMzSL&#xA;bURW1srrTYrMP9mgt0uEpX/l4kP04q+usVaIBFDuD1GKvMPzU/MTW7LzT5d/L3yq6QeZvMzGR9Rk&#xA;QSrZWUfIyTLEdncrE/Hl8PwmuKprc/lSs9sKebPMkeohaDUE1OZfiofiNsKWp3PT0sVYX+Vv5k+d&#xA;NP8AzL1L8qfPk6alqVtGZ9F1xEETXMKp6gEqr8JJiPIECoKsGJ64qk/mP86/M/kT84/M41e3n1H8&#xA;vFudPtZpU+NtOnm0+CTkgFSEkqzFOjGpX4qgqvYvMF1puv8AkS91DTNQka0nsZrix1HTrmSFq+i/&#xA;F0lgZDsex79Rtirz6383eYPLf/OMsHm2ykn1PXhpNvdtPezS3bmacokkzGZnNIw5k49NsVVfI9jo&#xA;/nfybZavoHnbVbvzAkcMt7cDUp1CXNFd4LmwRhBGjMrLQRV4/ZJGKorzz588wal+Zenflf5Uuf0b&#xA;dzW5v9f1wIkstraAEiO3SQMnqybfEynjyFB4Kpxqn5TyT2kh07zd5isNVKn0b46lPOgfqC9rITbs&#xA;teoVF9qYqxj8kvzR806t5j1/8u/PHpyeafLvJhfwKI1urdHWMyFV4gNWRGBUCqsNgQaqsa0qz1HW&#xA;v+cmfN/k+58wa7F5fsNLjvLOzt9Xv4hHM8diSVZZq0rcOaHbfFU5/KrV/PVl+avnj8ur3WLjWtI0&#xA;i2juNN1i9P1ie3kuFjeGKSQ8WkJSY1qesZpSuKqX52eTpvJv5R6vrmkeZ/Mn6Y09bQRXk2tag9TL&#xA;dwwuzR+sI/iSRv2cVT3yT+Xh1n8v/LesnzL5ii1m+0ywv5Lg6zfyRtcSQRzNzheVozGzn4lp02FM&#xA;VY//AM5AX+sad+Zf5X22m6tqVha6/qv1XVra0vrqCKaFbmzjCmOORUX4ZnBKgVrirJv+cj5b3Sfy&#xA;d1fVdK1C+0/UdNFoLS6tby5hkAkvIYW5tHIvqVRyKvXFWUflR6z/AJa+WLu4uLi7u77S7K7urm6n&#xA;luJXmnto3kYvMztuxrQGmKsJsDej/nJi80U6lqLaPF5bXU49Oe/vGtxdC8ii9T0mlKH4CRxI4+2K&#xA;oX8/fzcvPIHm/wAivDK/6PknuZddtkJo9n+6hqyjqV9RnT/KXFXsFzrGmW2kSaxNcoumQ25u3u61&#xA;jECp6hkqP2eG+KvJf+cd/wAz9U8+XnnafUGkQQanHNY2cvW2tJ4jHDEFJ+Ha3JbsWJPc4qwz/nFD&#xA;QdH138oNY0/VrWO7tJNbn5RyDofqlrRlI3Vh2INcx55pY5iUTRZ+HGcakLDyTU7a1j1y9t7RWW0i&#xA;uJlgSQ1YRI7cQxHU8RnU6zUyxaaWT+IR+0/tdN2Xo46jWwxfwyn/ALEbn7GWflb5Oh82+bodPuiR&#xA;Ywo11ehTRmijKjgDsRyZ1Wo7Z5tihxy3fae1dZ+VwcUef0x/Hk+p7Py/oVlYiwtdPt4bMLxMCxIE&#xA;I/yhT4vpzZDHECqfPZ6nJKXFKRMu+3g357/l3pegyWuu6PCLazvZDBdWqCkaTcS6NGP2Q6q1V6Cm&#xA;2YOoxCO45PY+z/aU8wOOZuURYPk8buFHIMB1G/zGdr7O6g5NPwn+A18HgfbbRRw63ijyyR4vjyP3&#xA;X8WX/mR+VFlon5Kx+a57trnUL9rKW3iQcIoormj0Nfid+JG+w9u+U63tE5JnEBUQfudfo9EIR8Qm&#xA;yR976m/Kv/yWHlD/ALYmnf8AUJHmI5heIf8AOUv5ZeY013TfzQ8qxPNeaV6LalHEC0kbWr+pBdKg&#xA;3YL0enQAHpUhV6z+U/5y+VPzE0aGayuY7fW1QfX9HdwJo5AKsUU0Mkfg4+mhxVkHnfzlpXlPQZtT&#xA;vpYxMR6en2jtxe5uX+GKGMAMxLuQDQGg3O2KvEvzwFx5K/PPyX+Z1xE7+XkjGm6jOoLiAsJomYge&#xA;MNyWXxKnFX0LZXtnfWkV5ZTx3NpOokguIWDxujbhlZSQQfbFXhOlab/i7/nKm58z6YPV0XyhYfUr&#xA;m/XeKS9khkiMKMNmZBcNy8OPyqqyDyhp+leY/wAx/wA4NK1W2S5sLubSra6tX3DINP8ATrtQgnhU&#xA;Ebg9DUYq811yw83/AJAz6nBbLNrX5Va6ssSrXlNp886FVrWgBqaV+zIPBsVe0/l3e6Lp/wCVHkSz&#xA;1Dgtvq+l6dZRxygGOSW4sRIY2DbH1OLCncmmKvHPze/Ke0/K7U9L8/8A5cXMumajLqMFmdAVyYrl&#xA;rhifSiqeXF+NGiNVp0pTFUx84T/8q9/5yis/OOsAxeWvNdqti+pN/dQyiFIOLtSi0aCNmr+yxPY4&#xA;q+jY54ZIVnjkV4HUOkqkFSpFQwYbUp3xV4P+VWlN5k/5yB88fmNZrXy6iLpOn3Y/u7meKOCGV4mG&#xA;zov1U7jb4hiqS2Wk6vqn/OXXniDStauNBuk0eCT65bRW87Mog05fTZLqOZOJLBthXbriqffkj5qf&#xA;yz5r1v8ALfzoEg85zXcl7DrT1H6YSUkpJzcmrhBRFFBxHEAFWxVkX/OUf/kifM3/AEY/91C3xVlX&#xA;5T/+Ss8m/wDbD03/AKhI8VeVf85Hf+TT/Jf/ALbh/wCovT8VZv8A85HaVeap+Snmi1s4zLOsENxw&#xA;UEnha3MVxIaDwSJjiqY/kjrFhqv5S+U57KVZUt9LtbObiQSs1rCsEqNToQ6HFWN+Xok1T/nJTzLr&#xA;Fk/rWej6Bb6PeSrui3c1wtx6XIbFkSP4h2OxxVCeavK+n+f/AM1vNXl6+/3ktPKtvp4f7XpXF7dt&#xA;dJMFr9pTbxMNv2cVYD+WeqeavNGi235IazBLDcaBfNH5mujXidFs3V47cPt8U0pWJaf7qFcVZL+W&#xA;PDRP+coPzD0FVEUOo2kOoQqo4oSBDJRen/LU3TwOKsC/5x7/ADR0byR+VF8LqGW71C61m5a0tYxx&#xA;Vgtpagl5SOKip7VPtksWglnnsaiObVm1kcMd9yWBTXZn1Ca6ICGeR3I6hfUJr91c6DXabxNPLGOf&#xA;Dt7xydZ2TrRg1mPMeQnv7jz+xmf5V+cYPKfm+HULsH6jPG1relRVljkKtyA/yXRSfbPNcU+CVvtf&#xA;a2jOpwGMfq5j8e59U2etaPe2Iv7S9gmsqBvrKSKYwD4tWg+nNkJgi7fO54JxlwyiRLup4D+fP5ga&#xA;ZrtxaaJpE4ubSwdpbq4jNYnmI4qEYbMEUt8Q23zB1GUSNDkHs/Z/s6eEHJMVKXIda/a8duGqwUGo&#xA;A3HgTna+zmnMNPxH+M38HgvbbWxzazgibGOPCf63M/oHves/m/5m0DV/+cb7S10y8WebTjpltdQH&#xA;4ZY3iURnkh3oSux6HNbqcE4ZyZD6iSGjTZYSxARPIB75+Vf/AJLDyh/2xNO/6hI8LIspxVg+v/kl&#xA;+VOvXbXupeWrRrx25vc2/O0lZ615F7ZomLe9a4qoaR+Q35S6TqUGp2nl6Nr+2dZbe4uZ7m7ZHQhk&#xA;ZfrMsoBUio8MVZvf6fYajZzWOoW0V3ZXC8J7adFkjdT2ZGBUj54qwy1/JD8s7MsLPS5bWByS9pBf&#xA;X8Vq1a15WyTrCRv0KYqy7StG0nSNOi03SrSKwsIV4xW1sgiRR7BKUPviqT6L+XXlPRdev9e023uI&#xA;dW1Qo2o3DXt7L65jBCeokszxtwDELVdu2Kp5qWm6fqdhPp+o28d3Y3SGK4tplDxujbFWU7EYqk+p&#xA;+QPJ+qeV7XytqGmR3Og2McMVnZOzkRLbJ6cPF+XqAouwblX3xVB6P+VPkTSdSt9TttPkmv7Ov1O4&#xA;vru7v2gqKfufrcs/pmn8tMVT/WtD0bXNOl03WLKHULCYUltrhFkQ+BowO47HqMVYnbfkj+WltEbe&#xA;HS5VsmrXTzfX7WdD1H1VpzBT24YqzOysrKxtYrOyt47W0gUJDbwoscaKOiqigKo+WKsXsvyo8jWX&#xA;mqfzZbWdxH5iul4XOo/X79pJEAUcHDTlWWka7EU2GKovzf8Alz5L84NaP5h0xLyexYPZ3SvLBcRM&#xA;CG/dzwPFKvxAGgbrirfmL8v/ACt5k0BdA1yC4vtJWnK3kvbwF+Lh19WRZhJLxZQRzY0xVHeXPLOj&#xA;+XNMh0vSI5YbC3RYreCW4uLgRxpsqoZ5JSoAPQYqlPmn8rfJHmnVrHV9dsprvUNMcSafMLy8hEDg&#xA;q3KJIZo0U1jU1A6jFWTRW0UVuLccniA40lZpWIP8zSFmb6TirCh+SP5ZJczXNrpD6e9weU8en3l7&#xA;YxOf8qG1mhiP/A4qyjy/5c0Ly7pqaZodjDp9ihLCCBQoLN9p2PVmPdjviqA0nyH5Z0nX77X7GG4T&#xA;VtT9P9IXEl7eTCb0UKRc45ZnjPpqxC/Dt2xVMLPy/otlq+oaxa2ccOp6qIRqN2oo8wt1KRcz/kKa&#xA;DFUmvPyw8k3fm7/GEljKnmQoIjqMF3d27lAnphSsMsaEcRTdcVfOX/OO/wCXGled/wApJ7e+mktm&#xA;svMFzJHPCFL8XsrUOnxVA5UU/Rjj1stPMkC7DDLpY5ogHoU9/M/8hodE0RNU8r/WLtLQMdRgmZZJ&#xA;TH19VOCp9n9oAdN+xzZ6Dtc5J8OShfL9TrtZ2aIR4oWa5vHIphTi/wBDf1zF7V7A8WRyYtpHmO/3&#xA;eb0vs97Yfl4DDqAZYx9MhzA7j3j7R5qoZCvLktPmK/d1znD2Nqga4D9n38nuI+1HZ5jxeLH7b+VW&#xA;sedR9j4j49vxzcdn+zkuISz7D+b+s/qeX7Z9uIcJhpbMj/Gdq9w5376rzZn+Xv5ReYPOkFzeRyCw&#xA;sYgRDdzozLNNX7C0INB+029OmdDq+0MenqNWe4dA8Dp9HPPcifiepQv5oflBrHlD8vdZ1PWJYZJP&#xA;XtLayNuxdGV5eUjnkEYEcFA27nNZrO0o5hGML7zbsdJoZYiZS+D6p/Kv/wAlh5Q/7Ymnf9QkeYbm&#xA;FlOKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV86/wDOGn/ksNU/&#xA;7bc//UJa5h6j6m7Hye63Mxht5ZgjSmNGcRoKs3EV4qO5PbKYizTMmg+NNH8sa75q85nSVga31C7u&#xA;He8EiFfQBYtK7qeJASvT6O+dzlzww4uK7iBt5vJwwyy5OHkSfk9Lk/5xf1YT0j16BoN/jaB1f2+A&#xA;Mw/4bNUO3o19Jv3uw/kc/wA77Hk+q6PdeW/M8um6nCJJdOuAs0RFVkRWDAivVZEoR7HNxjyDLj4o&#xA;/wAQdZPGcc6l0L7Wso7SO0hSzRI7RUUW8cahECU+EKoAAFM4ORNm+b18QK25PIf+csv/ACT91/zG&#xA;2v8AxM5Zg+pE+T0z8q//ACWHlD/tiad/1CR5nOOWU4q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX&#xA;Yq7FXYq7FXYq7FXYq7FXYq7FXyD5H/Lj/nLDyRpMuk+XLW1tbGedrqSN5dPlJldEjLcpGY/ZiXbK&#xA;5YxI7s4ypkX1b/nNfws/v0vI+BHuZcZUv0Z/zmb9Z+tehYfWuHp+vx0r1OFa8OXXjXemHwhVb0ji&#xA;3vZV+rf85r+Fn9+l4PAj3J4yl0nlT/nLmXVv0vLp2lyaoEWMXjx6S0oVCStGIqKV6jLBYjw2eHut&#xA;rIjxcVC0x+rf85r+Fn9+l5X4Ee5s4ykfnHyH/wA5becdEfRdftrW5055ElaJZNOiPOM1U8oyrYY4&#xA;gDYQZW+m/IelXuj+R/Luk3yhL3TtMs7S6RSGCywW6RuAw2NGU7jLWsp7irsVdirsVdirsVdirsVd&#xA;irsVdirsVdirsVdirsVdirsVdirsVdirsVdirsVf/9k=</xapGImg:image>
+ </rdf:li>
+ </rdf:Alt>
+ </xap:Thumbnails>
+ </rdf:Description>
+
+ <rdf:Description rdf:about='uuid:8aa76b3d-2474-11d9-a8a3-000393cd9a96'
+ xmlns:xapMM='http://ns.adobe.com/xap/1.0/mm/'>
+ <xapMM:DocumentID>uuid:c63b31d6-45fe-11d8-8e7c-000393cd9a96</xapMM:DocumentID>
+ </rdf:Description>
+
+ <rdf:Description rdf:about='uuid:8aa76b3d-2474-11d9-a8a3-000393cd9a96'
+ xmlns:dc='http://purl.org/dc/elements/1.1/'>
+ <dc:format>application/postscript</dc:format>
+ </rdf:Description>
+
+</rdf:RDF>
+</x:xmpmeta>
+ <?xpacket end='w'?>
+% &&end XMP packet marker&&
+[{ai_metadata_stream_123}
+<</Type /Metadata /Subtype /XML>>
+/PUT AI11_PDFMark5
+[/Document
+1 dict begin /Metadata {ai_metadata_stream_123} def
+currentdict end /BDC AI11_PDFMark5
+Adobe_AGM_Utils begin
+Adobe_AGM_Core/page_setup get exec
+Adobe_CoolType_Core/page_setup get exec
+Adobe_AGM_Image/page_setup get exec
+%%EndPageSetup
+Adobe_AGM_Core/AGMCORE_save save ddf
+1 -1 scale 0 -148.752 translate
+[1 0 0 1 0 0 ] concat
+% page clip
+gsave
+newpath
+gsave % PSGState
+0 0 mo
+0 148.752 li
+254.868 148.752 li
+254.868 0 li
+clp
+[1 0 0 1 0 0 ] concat
+54.9161 147.252 mo
+1.5 147.252 li
+1.5 1.5 li
+54.9161 1.5 li
+54.9161 147.252 li
+false sop
+/0
+<<
+/Name (PANTONE 7506 C)
+/0
+[/DeviceCMYK] add_csa
+/CSA /0
+/TintMethod /Subtractive
+/TintProc null
+/MappedCSA null
+/NComponents 4
+/Components [ 0 0.05 0.15 0 ]
+>>
+add_csd
+1 /0 get_csd
+sepcs
+1 sep
+f
+7.82032 17.3956 mo
+12.9034 12.8946 20.6797 13.3624 25.1856 18.4405 cv
+29.4395 23.2481 29.1768 31.1573 24.5225 35.4014 cv
+19.4395 39.9131 11.2784 39.8477 6.76954 34.7637 cv
+2.26661 29.6758 2.73926 21.9004 7.82032 17.3956 cv
+cp
+11.7549 43.3096 mo
+12.2579 48.5938 li
+16.7979 48.8663 li
+17.9268 43.7178 li
+20.3682 43.4747 22.7608 42.7344 24.8936 41.4756 cv
+28.8946 44.7803 li
+32.2999 41.7657 li
+29.4512 37.3243 li
+30.8975 35.3721 31.9356 33.1631 32.5196 30.8428 cv
+37.9678 30.3233 li
+38.2413 25.7842 li
+33.0137 24.6417 li
+32.794 22.21 32.0909 19.837 30.8458 17.6924 cv
+34.1573 13.6866 li
+31.1416 10.2813 li
+26.8135 13.0518 li
+24.8252 11.46 22.5674 10.3506 20.1846 9.75684 cv
+19.6973 4.61329 li
+15.1592 4.34083 li
+14.0616 9.35645 li
+11.6202 9.62598 9.22754 10.4092 7.04786 11.7168 cv
+3.06153 8.42383 li
+2 9.36426 li
+2 15.0967 li
+2.42969 15.7667 li
+2.27442 15.96 2.14551 16.167 2 16.3663 cv
+2 42.168 li
+5.16114 40.1416 li
+7.12208 41.6631 9.37012 42.7315 11.7549 43.3096 cv
+/1
+<<
+/Name (PANTONE 301 C)
+/CSA /0
+/TintMethod /Subtractive
+/TintProc null
+/MappedCSA null
+/NComponents 4
+/Components [ 1 0.45 0 0.18 ]
+>>
+add_csd
+1 /1 get_csd
+sepcs
+1 sep
+f
+19.8682 23.167 mo
+21.6221 25.1495 21.9336 28.1055 19.6426 30.2452 cv
+17.7315 32.5264 13.9385 32.1124 12.1084 30.046 cv
+10.2051 27.9034 10.4053 24.626 12.5489 22.7256 cv
+14.6924 20.8213 17.9698 21.0293 19.8682 23.167 cv
+cp
+24.5225 35.4014 mo
+29.1768 31.1573 29.4395 23.2481 25.1856 18.4405 cv
+20.6797 13.3624 12.9034 12.8946 7.82032 17.3956 cv
+2.73926 21.9004 2.26661 29.6758 6.76954 34.7637 cv
+11.2784 39.8477 19.4395 39.9131 24.5225 35.4014 cv
+/2
+<<
+/Name (PANTONE 871 C)
+/CSA /0
+/TintMethod /Subtractive
+/TintProc null
+/MappedCSA null
+/NComponents 4
+/Components [ 0.3569 0.3608 0.6353 0.1882 ]
+>>
+add_csd
+1 /2 get_csd
+sepcs
+1 sep
+f
+42.0054 124.904 mo
+38.6949 132.106 29.9537 135.87 22.7505 132.561 cv
+15.5523 129.245 12.4058 120.72 15.7144 113.527 cv
+19.0259 106.334 27.5503 103.179 34.7427 106.488 cv
+41.5435 109.62 44.98 118.187 42.0054 124.904 cv
+cp
+52.1324 108.189 mo
+46.0132 109.425 li
+44.6382 106.935 42.775 104.731 40.4371 103.029 cv
+42.0914 97.1954 li
+37.271 94.9756 li
+33.9527 99.9629 li
+31.0816 99.1973 28.1519 99.0762 25.3277 99.5635 cv
+22.3921 94.2989 li
+17.4175 96.1416 li
+18.6011 102.011 li
+16.1207 103.443 13.9351 105.404 12.2232 107.825 cv
+6.41944 106.179 li
+4.2046 111.001 li
+9.19288 114.318 li
+8.42237 117.192 8.30616 120.126 8.78467 122.94 cv
+3.52295 125.882 li
+5.36475 130.86 li
+11.2349 129.672 li
+12.6656 132.151 14.6226 134.34 17.0562 136.049 cv
+15.4068 141.854 li
+20.23 144.069 li
+23.5582 139.057 li
+26.3648 139.764 29.271 139.844 32.0865 139.344 cv
+35.1089 144.747 li
+40.0816 142.907 li
+38.8687 136.883 li
+41.3609 135.473 43.5679 133.563 45.2554 131.213 cv
+51.0806 132.864 li
+53.2984 128.045 li
+48.1685 124.64 li
+48.7964 121.878 48.8687 119.031 48.4048 116.281 cv
+53.9722 113.169 li
+52.1324 108.189 li
+1 /1 get_csd
+sepcs
+1 sep
+f
+25.3804 126.851 mo
+21.3306 124.99 19.5601 120.199 21.4234 116.152 cv
+23.2847 112.103 28.0757 110.342 32.1226 112.198 cv
+35.8609 113.921 38.1509 117.934 36.23 122.414 cv
+34.9371 126.865 29.2769 128.645 25.3804 126.851 cv
+cp
+34.7427 106.488 mo
+27.5503 103.179 19.0259 106.334 15.7144 113.527 cv
+12.4058 120.72 15.5523 129.245 22.7505 132.561 cv
+29.9537 135.87 38.6949 132.106 42.0054 124.904 cv
+44.98 118.187 41.5435 109.62 34.7427 106.488 cv
+/3
+<<
+/Name (PANTONE 1805 C)
+/CSA /0
+/TintMethod /Subtractive
+/TintProc null
+/MappedCSA null
+/NComponents 4
+/Components [ 0 0.91 1 0.23 ]
+>>
+add_csd
+1 /3 get_csd
+sepcs
+1 sep
+f
+51.919 34.2159 mo
+50.1553 34.3702 48.4336 34.6612 46.7647 35.085 cv
+45.0293 31.7598 li
+41.462 32.9639 li
+42.0958 36.6563 li
+40.4815 37.3428 38.9317 38.1573 37.4639 39.085 cv
+34.7881 36.46 li
+31.7666 38.7081 li
+33.5157 42.0323 li
+32.1993 43.1778 30.9776 44.4268 29.8624 45.7686 cv
+26.5 44.0938 li
+24.3194 47.1651 li
+27.0049 49.7813 li
+26.1094 51.2696 25.3331 52.837 24.6817 54.4659 cv
+20.9756 53.917 li
+19.8526 57.5108 li
+23.2159 59.169 li
+22.8292 60.8477 22.5831 62.5772 22.4659 64.3418 cv
+18.7579 64.9659 li
+18.7999 68.7315 li
+22.5225 69.2696 li
+22.6778 71.0323 22.9639 72.7549 23.3868 74.4249 cv
+20.0635 76.1573 li
+21.2667 79.7266 li
+24.959 79.0928 li
+25.6456 80.709 26.46 82.2569 27.3887 83.7256 cv
+24.7627 86.4004 li
+27.0127 89.4219 li
+30.336 87.6729 li
+31.4795 88.9883 32.7305 90.21 34.0713 91.3243 cv
+32.3975 94.6895 li
+35.4698 96.8663 li
+38.085 94.1827 li
+39.5743 95.0782 41.1387 95.8555 42.7725 96.5069 cv
+42.2208 100.211 li
+45.8155 101.335 li
+47.4737 97.9708 li
+49.1524 98.3584 50.8799 98.6104 52.6456 98.7227 cv
+53.2696 102.43 li
+54.8282 102.401 li
+54.8282 90.2071 li
+50.5508 90.4063 47.168 89.4581 43.1543 87.2188 cv
+31.6788 80.8194 27.5655 66.3292 33.9717 54.8516 cv
+38.3282 47.044 45.9112 42.2872 54.8282 42.667 cv
+54.8282 30.4581 li
+52.4581 30.4971 li
+51.919 34.2159 li
+1 /3 get_csd
+sepcs
+1 sep
+f
+33.9717 54.8516 mo
+27.5655 66.3292 31.6788 80.8194 43.1543 87.2188 cv
+47.168 89.4581 50.5508 90.4063 54.8282 90.2071 cv
+54.8282 73.5127 li
+54.4903 73.5616 55.1485 73.5948 54.7969 73.5948 cv
+50.8213 73.5948 47.5987 70.3731 47.5987 66.3975 cv
+47.5987 62.419 50.8213 59.1944 54.7969 59.1944 cv
+55.1485 59.1944 54.4903 59.2286 54.8282 59.2764 cv
+54.8282 42.667 li
+45.9112 42.2872 38.3282 47.044 33.9717 54.8516 cv
+1 /2 get_csd
+sepcs
+1 sep
+f
+3 lw
+0 lc
+0 lj
+4 ml
+[] 0 dsh
+true sadj
+54.9161 147.252 mo
+1.5 147.252 li
+1.5 1.5 li
+54.9161 1.5 li
+54.9161 147.252 li
+cp
+0.99 0.99 0.99 1 cmyk
+@
+0 0 0 1 cmyk
+%ADOBeginSubsetFont: TrajanPro-Bold Initial
+%ADOt1write: (1.0.21)
+13 dict dup begin
+/FontType 1 def
+/FontName /TrajanPro-Bold def
+/FontInfo 7 dict dup begin
+/Notice (Copyright 2000 Adobe Systems Incorporated. All Rights Reserved.Trajan is either a registered trademark or a trademark of Adobe Systems Incorporated in the United States and/or other countries.) def
+/Weight (Bold) def
+/ItalicAngle 0 def
+/FSType 8 def
+end def
+/PaintType 0 def
+/FontMatrix [0.001 0 0 0.001 0 0] def
+/Encoding 256 array
+0 1 255 {1 index exch /.notdef put} for
+dup 67 /C put
+dup 73 /I put
+dup 83 /S put
+dup 127 /Nsmall put
+dup 128 /Tsmall put
+dup 129 /Esmall put
+dup 130 /Rsmall put
+dup 131 /Ysmall put
+dup 132 /Ssmall put
+dup 133 /Msmall put
+dup 134 /Osmall put
+dup 135 /Ismall put
+dup 136 /Usmall put
+def
+/UniqueID 45714 def
+/FontBBox {-248 -284 1528 985} def
+end
+systemdict begin
+dup /Private
+15 dict dup begin
+/|- {def} def
+/| {put} def
+/BlueValues [-17 0 750 775 638 660] def
+/OtherBlues [301 305 405 408 -261 -256 -222 -209] def
+/FamilyBlues [-17 0 750 767 638 656] def
+/FamilyOtherBlues [301 305 405 408 -273 -255 -214 -209 -252 -239] def
+/StdHW [47] def
+/StdVW [118] def
+/StemSnapH [47 55] def
+/StemSnapV [118 126] def
+/ForceBold true def
+/password 5839 def
+/MinFeature {16 16} def
+/OtherSubrs[{}{}{}{systemdict/internaldict known not{pop 3}{1183615869
+systemdict/internaldict get exec dup/startlock known{/startlock get exec}{dup
+/strtlck known{/strtlck get exec}{pop 3}ifelse}ifelse}ifelse}executeonly]def
+/Subrs 5 array
+dup 0 <1C60D8A8CC31FE2BF6E07AA3E541E2> |
+dup 1 <1C60D8A8C9C3D06D9E> |
+dup 2 <1C60D8A8C9C202D79A> |
+dup 3 <1C60D8A849> |
+dup 4 <1C60D8A8CC3674F41144B13B77> |
+def
+put
+dup /CharStrings
+14 dict dup begin
+/C <1C60D8A8C9B6D5A0DEDEC57B918D61DDFA401F5A49FEA3B89C6864173301
+6BDC674395116B42D2387AF24DF2F1DC60C61A5B6585CC0DA86F050A110B506B
+B65171C092F0636620BAA275DBDEA04B3E655EC58BDFB8B9B535650BF4DE0E82
+1C2ADFD8C9F649E0C395722C228833505318AA21D61F3D55D035246FCF9BC983
+692D83F8C9AF492468B91F4CB872C7D1953185BF38A8E7A5B72C7F51E36572D3
+718D9C26EEF5DDFAB02F3E79248875F4CA6CC06F7C289C017B388B2CFE4B85A5
+1B0090> |-
+/I <1C60D8A8C9B77771C05B04C6A1CDBDED73825D1016AD1A9F739BE3AE28A3
+2F89A16FA0ADB365C478020BF11BB9ADC332932373DC2832A2FD54E961E2B084
+4B0EB81447C317CA2A36F9297140F653C6CF38B651D9BF313FA9254650245A3A
+6E604D8E9EFFEAAF12423E3B4CFD19A9AFAFF5FC58BD3FF4189B6F8AF938C510
+BD91FB49103F7E5C2AE8440096A8B2CFB59E1B448BD934D6C96663C7ECAD3789
+1B4FEEBF9172B6A7CCC0965D9AA12297E39BBF30EB7B8F6243DD70D9185FBD81
+8CFC74B60F41E69C4533165A53D5C2FC5A9B44BA5F12F31CB79A71FA4F70F551
+E84E63E5837361F7B7736F91> |-
+/S <1C60D8A8C9B7F51B95A0DFD92CF0B9552EA2D8DB80CD668D35E3A70F4576
+D4238E8EEA2F046EF8BC16C7785D1607E04A62100A5AFF084F37B544AFC2004C
+0BC4AE1356D2B0EC8700AB99117F620401AEDDDFA69D53F0F4E5314303A9C779
+D85053ADE7DEA169C445735EBAC333F65F31A077498B479248885315A58C9DAE
+7AD6ABA3F9562E1A36EA3EA3274E191D557F04A6CB9FA3B240660C95B31FD1EC
+ACE3874E2F240022DE09CA2256274ED580EE94FBAA5793BD5F9D37682BE7C541
+ACC5EE4D95FB35149493D2CCA9BEA729ABD0DCEC9C95E902EA9DD124CA919CBA
+F3364C7699DDBE268B46D54393CC359D98EA67700B83CEF348489F1F90A16D> |-
+/Nsmall <1C60D8A8C9B6BC88BD85FE8659C453EEEB8E1BD03325A00213B3F3D
+4D450DC128DD37CC24C857B6D60D557A08CD43D812DF35B5BD6760576A63576C
+506A238602F1E6EA5D2CF18DAD28B193AFC0FA899C7F243B47EAB7B8460C0CB0
+4242476B1602C4D8E3342E27EB421C00D297126C6E43889F0137C7A1C441FC72
+2BE08EFEBABED7A59A7395971A284A820995BDAAE7D9478AB8745D9C9402C363
+B7514AFE9E3D0AF6A39663E1D555B5F7BDA2CE94F32DDC1E19216692DC849907
+7A3E6206E838004DD8DB4A986C8F31EDCAB6E6B82F722A0EF26221ADD2189144
+83D5E5F90B6CEB939F64EF523B4531C4C0B4ED4F521923EBA94C1FE7AE3B2648
+AB7B1D48BCD570F1DED35E03DBB412CF55B5989A09E378971DDF42BBC4FD1669
+7B92AE130992922E13408AB712F27D256F7305A6C6B07A0AD7C13FE23EFB63CE
+65111A1A787D3875B8B8D9507C694904CE3BA8114CCE10FF99A55> |-
+/Tsmall <1C60D8A8C9B66C0E1D18F4614EAB544F0CEC538C8C01A016933AA12
+429EBE5390D596C5F67CFF90C2108DEC0E3557EFE47A84AD0A504C83D7E8F287
+5DCBB9233950E37680119C5422B9BA74EB5E3A2AE4E2F090670CEE3CC015972E
+6CE8DF50DCD73A5ECEE824E6627364F3B83B1B73833AA7E396445D318F119C4C
+5EA2429D5B49B0EDBDDF4808A5790BF8CDC63B184CD3A9CE7C22C4D23ACC081C
+FF7BCA42342880880724EDF5A0F6F9059ADD736C441B65FC95D81D78B14BCAE7
+32E0959A4FEDBBA605D7DB559BC1CFFED39160EF11111F189C967E86115A679A
+21BB269B7452490D7C600719A2B02BE0A92DC8D7E101DFFE6011D579AD666FD2
+6352E7C3F88546D427880A3ED55A53668B9B911F227F478005846196CB2A821D
+9436A361DD997E24624546B193AD16A013BF60C83D456FEFAB524A4C3C4DAF51
+640204EE51B9A6B98D186E77DE45F4BD3696405A93E6DE14A3A251AC1EF6440B
+3F074B20C4913F3447DE56969C6BBDB2354148031166D8E9781263F94442062C
+991765ADD918972AAE466DE6B9C6E0991428CD75BCCEE> |-
+/Esmall <1C60D8A8C9B7FBE1B006E95A68A3EFE857D335EDE0BE9AEA4BE7F95
+2FA0109C6CB803A7F2B985E7BDE818880C9FD186C7136A63CCA57CEDB6AF2828
+DE38E8685BB8771E2988A810F73E0345E8908310C31FD0F7C222F54500389519
+240356E338A96366351A20F484B5651422D1A0FDAE927D548045766A19F6150D
+CC390EA0D98D6C0EC5E1C97E0B4512533CA015299550D65A6EA9A741DBD81A7F
+575EC26534A2210CD8BC3335B163A776277B6F29843653C092C384FA226EA0E5
+F40EBE1799B10828B444468B3DA053A6ABB46879088C5CDBC46D899C794B325A
+A3C97D044BB760BC39839995FB64819C682832A40321F78B99C09513B805CEC3
+996F9F6C14C0DA278CFDCC8EE83409A0C9BCAE8289E42BA209582E05976E48A0
+66222F364CA72855AA1A8DD971B9E012D88EC883F11B6B8DD1F7A3A1A193533F
+B42207516FD3B0F5443A7865F511A1795EBD587D37DBDF03F04386AD8496835A
+76A8A2EA2B1821C0A26A3284A32DDD223178AF712B0015CA9C866D881702FB56
+88AFCD83EBB5B8B70C983ADB28C933F563180B2F5D693852DE904FE07D55275B
+BF14C6F4184BD1B4A9AECA29C644CB5A0BE9622ABA21F24CFE079641418F3570
+3415A4A73F296C050FA68AD25A13C7E948BFB4A1F5816B4ED0207AE7F70F6A21
+CEF402873ACC39E699949E03BE7A042549D2AB51127EAC04572696553A61D3AD
+7A50684611A83B8CC45B07DFB59CE66FF4633DDD79F> |-
+/Rsmall <1C60D8A8C9B6232B67C2503515E3E19A361BD6B49811E165A598B41
+3BB79166E3FDF489EB666983D5C7D39CD639562A5B5DFFD54539B03730F39196
+01122BFF4EFD30EC733326ACD5E99E075E6AD0B22300446FDA3039558CE7D82F
+A6C33C70F1D07536B16D4B1DC2398D650AD9DE1FE1EEF9FC8801CF7C62691F3D
+44ABC62967E1B752BCC2F000EEC07286667F57839EF2E6B9C04C2DA9F22FCE01
+4B7A5598EA7A603107AC2DBC5AB39CAF9666BA8BD1E17DD88F1B0183C4C1C3F1
+1214AD45BA4F39EED6AE5D1943AADDA9D1EC079FB2B1E8FDACACF0141DE87287
+5FA936F561AD9761380B6FCDEE2C83C4F292D6BC0EFBBEBA1571BC78DB7E53A3
+C2355971E9941081B36BC438EEEB16D9D4B14BD1644AC5E58981D2AC452FD6A5
+580957C704505040E5A864423A1DEC798AD589C92753FF4E99FE4D12AC55E99D
+5F0AB1E5E4B10AE2F480F509E7AF89EE8CEFA0BA716FB8CEAE96307008D32070
+D365B7F6583B829884DD2FE6EB7D95965527303A93BC3BED5A9AD904DA3DA> |-
+/Ysmall <1C60D8A8C9B7CDD8BD7DBD65E184B9680768C945EF501FFBAF34DB2
+EB89B7C35DCB2E8CDE46F9D37FB471E35DF335DEED86CBC9BD25ACBBBE505717
+85D55C56B45ACC3A263ED736CAA051A570F787892A1CB6821A2FFAD018F8067C
+A681AE9EC8078E3C7AFE94C42C7FD5A558E11749ACDE333C8BDC9884D4FA3DAC
+AE8A34DD32D0843E9B8D09766739B4ABA55282A00532DD1F8B6DE1183006D340
+67C1700BABA7CDD73E0CDB5BE2DDAE32FBEED1C6D7EEEA3B5CEB4C4205571F0D
+CF1A506D8FC5DC8499A45715F34A9B98FE00C59CEE5F28BBF36D76480FA97A6C
+7DA2BD1F5844A8385287554D6A25D036C1B44B3D155C43934FF8AA5F5EFA8691
+C8A756E6E6312D494BA1468BA6D0686CD0C8B3FDB8C0351FA65E6040F976F25D
+799285A835570C29A2FB34B27E1A794353E610FC2C4A30406992C247A28AA7F6
+E944BDFAB0BBA11598F8F567A868E003F8F3944F74A873C0B590A5CBD543024C
+D6E3B83887E8B4201> |-
+/Ssmall <1C60D8A8C9B79FB048C852057885B7FB39D71FC3016435158EC7538
+3A43C835122312509B1BFED76A61F209ED65A42B34BB62984E18488BC60B5218
+01752FF5C2563FA0352A4574582BF27E08DA350B6E25230194888F1FA389A5D9
+3FBF39576DDF170A31E4F9A79349B244BDF70FC82577F5D740926CBB4F2ACA8D
+2425F341518CF5F38A11D5613BD07DDED6A6C9CC2A89D2BA18004761AD9B9FC3
+4EDA3D0BA2574B07F9B17535C3DFBDB872ECFEEFC15F4D3F7BCA04E0B730A15B
+DD0D5BCB061E10476825BE14CC3CD57D1B8CD428D2118BB782F85F1A67B39448
+980A962927A8E8DBBBF65E6278D0AFECB529564B170722C87DEFBDB> |-
+/Msmall <1C60D8A8C9B5BDB4869BB7396C2BCC7E2D035A8DDF69463A769AD1A
+A49DB431BF0660A482C35C477875AA9502C9E16D281765C1FE89158C85EF4F3E
+57125A0E615EF95AE1B7077390D7D5D6DDBA63FCBAB687625D16C58A812887A3
+BF8B333347AF25B78756DD80DFD049480BBC5CC2E60C8AAAAAEC52485278ACB4
+CB64431DB98372ED33A1281E6970D65A9DEE7B405CB6932D27F2DFA40B98C2E6
+9A163099093F74C6495CCB4C78B91CF36A00F110217924E037A2F56731347A29
+95E8AFF22D6698D628918F5A55716FEBDE556231C95D2821D1B0DE3CCFA65E60
+C9DDB56BAFC7C7328AEA86A4824D8004029A0A0834D297E9E2EE5DAE0DFFB8A2
+CC6F17A3EDC65> |-
+/Osmall <1C60D8A8C9B6AE36D8AFC06EF7691CEA7388408CB5711A90AA9C8BB
+7DF107C83E9F4C9D93C2707EED4FFD917928C910BF7966EA41381731C2EDBAD2
+707004603AE29A600E85B2D80CC1F8253013508BECCA2FDAB8779E3B7D43916A
+0E2CE1B80BB3DF3> |-
+/Ismall <1C60D8A8C9B704CCC403F91AADD9CB2F76DB90BC6EC90EF3D45C6A9
+10C33779B027A5893F399469312EDD288FF0EA2B3848F5A530D7C0162C275993
+6728784ECB91933A5B31FC0120544923268E389858466EE39EB2181D57CD3BF7
+07FB3669BB94B89A418CD729CFF5FBF8DC7045D58C25F7CB07F19116123D927E
+59434BBF93B4FE5DBF40C126B117E6B60590BBF45DA98B6DE8B19144213326F9
+87495E510476E3585AE1A21D73828E47A902A177877DAAAB4C0EE1255BEF7F14
+75F7B919B37EA781F4D15EE851B6A63CFE7192BA2E00BB3BF61621837B8C6E3E
+7AB8CE9EC58E9FFE71C29175C76E5> |-
+/Usmall <1C60D8A8C9B6ED055F5BB1EE84E1A93ADDC8E7C125E88D8FF53587C
+17D959293900B8FD46371B21619962E4E05301A5E3EA5963AEEE83B21393A2AB
+3695359695D60CA9917C3B4C055638C566E55787F9201E25FB6F1ED940BE5C4D
+321EC5E70BC368233DBA0CBD12DA827A229D0CC8A349901F7F6297A8D2B5EE1C
+32919F009B7DEC73D0710E8891AA9A0D36238E9E944FAFD91D10D63C6B88D5BD
+C3A7985808BE85B22B832353DB0C8315F69AE576B8073207A5E9FE25F5A1E4F5
+9C748E9F7D4D5B9763098CB580B40B6CD00897D0384713B624EAD8EE1E24E326
+A2BE8083CCA899DE1FAB4FB90AF9AEB63CFCC24D405FB6596CE1D598C7EFABAD
+D016781F1785ACBA6641462356572572D87FF66C89B7A4AFB38B24B24E1E7B07
+44FD561E659DB89FDAA3D90E0980DCB66> |-
+/.notdef <1C60D8A8C9B7A73DC56ED86593A26411A239A9F576A4BB06AD4079
+CBD73625AFEDCD129CE8B573E3C4C05A38ADB9D43C2E751D7FE69FF5F6F4BCAD
+D50244964753D5C819FE275F32A27920BE3EA3D1AFD957ADA922B28CD2CD8E15
+58DDDC89C143A1> |-
+end put
+end
+dup /FontName get exch definefont pop
+end
+%ADOEndSubsetFont
+/FDJFDP+TrajanPro-Bold /TrajanPro-Bold findfont def
+/FDJFDP+TrajanPro-Bold*1
+[
+67{/.notdef}repeat /C 5{/.notdef}repeat /I 9{/.notdef}repeat /S 43{/.notdef}repeat /Nsmall
+/Tsmall /Esmall /Rsmall /Ysmall /Ssmall /Msmall /Osmall /Ismall
+/Usmall 119{/.notdef}repeat
+] FDJFDP+TrajanPro-Bold nfnt
+FDJFDP+TrajanPro-Bold*1 [32 0 -0 -32 0 0 ]mfnt sfnt
+63.709 49.9312 mov
+(I) sh
+FDJFDP+TrajanPro-Bold*1 [26 0 -0 -26 0 0 ]mfnt sfnt
+78.333 49.9312 mov
+0.080658 0 128 0.288605 0 (\177\200\201) awsh
+131.874 49.9312 mov
+-1.83563 0 127 1.73947 0 (\202\177\201) awsh
+188.218 49.9312 mov
+(\200) sh
+FDJFDP+TrajanPro-Bold*1 [32 0 -0 -32 0 0 ]mfnt sfnt
+63.709 85.9316 mov
+(S) sh
+FDJFDP+TrajanPro-Bold*1 [26 0 -0 -26 0 0 ]mfnt sfnt
+81.7983 85.9316 mov
+0.213654 0 132 -0.177307 0 (\203\204\200) awsh
+127.864 85.9316 mov
+-0.0141907 0 133 0.276245 0 (\201\205\204) awsh
+FDJFDP+TrajanPro-Bold*1 [32 0 -0 -32 0 0 ]mfnt sfnt
+63.709 121.932 mov
+(C) sh
+FDJFDP+TrajanPro-Bold*1 [26 0 -0 -26 0 0 ]mfnt sfnt
+88.9883 121.932 mov
+(\206) sh
+109.841 121.932 mov
+(\177) sh
+130.882 121.932 mov
+(\204) sh
+144.271 121.932 mov
+(\206) sh
+165.124 121.932 mov
+(\202) sh
+182.77 121.932 mov
+(\200) sh
+199.487 121.932 mov
+(\207) sh
+210.59 121.932 mov
+(\210) sh
+230.869 121.932 mov
+(\205) sh
+%ADOBeginClientInjection: EndPageContent "AI11EPS"
+userdict /annotatepage 2 copy known {get exec}{pop pop} ifelse
+
+%ADOEndClientInjection: EndPageContent "AI11EPS"
+% page clip
+grestore
+grestore % PSGState
+/FDJFDP+TrajanPro-Bold*1 ufnt
+Adobe_AGM_Core/AGMCORE_save get restore
+%%PageTrailer
+[/EMC AI11_PDFMark5
+[/NamespacePop AI11_PDFMark5
+Adobe_AGM_Image/page_trailer get exec
+Adobe_CoolType_Core/page_trailer get exec
+Adobe_AGM_Core/page_trailer get exec
+currentdict Adobe_AGM_Utils eq {end} if
+%%Trailer
+Adobe_AGM_Image/doc_trailer get exec
+Adobe_CoolType_Core/doc_trailer get exec
+Adobe_AGM_Core/doc_trailer get exec
+%%EOF
+%AI9_PrintingDataEnd
+
+userdict /AI9_read_buffer 256 string put
+userdict begin
+/ai9_skip_data
+{
+ mark
+ {
+ currentfile AI9_read_buffer { readline } stopped
+ {
+ }
+ {
+ not
+ {
+ exit
+ } if
+ (%AI9_PrivateDataEnd) eq
+ {
+ exit
+ } if
+ } ifelse
+ } loop
+ cleartomark
+} def
+end
+userdict /ai9_skip_data get exec
+%AI9_PrivateDataBegin
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: Adobe Illustrator(R) 11.0
+%%AI8_CreatorVersion: 11.0.0
+%%For: (Douglas E. Appelt) (Mad Doug Software)
+%%Title: (Alternate-ISC-logo-v2.eps)
+%%CreationDate: 10/22/04 2:51 PM
+%AI9_DataStream
+%Gb"-6CMtIYE[^blnitWj!HrIdV0lorEFGN3p=d2AK:U\*q_!hY[_$iT*gP5UX1]SSqSRQ?_'$)V>TY%qP`SMZ@PZ&5]GQS5IeD7R
+%m`Y!Qle<L>GQ7K.<ATW8Y&.3ff<4tLWP85on#ub1r+t\(\B,1VnRC\d?aFN#k'iiu,P=Jej)_iEpKp\9gP9_8n(o-NJ)9&<gtdJZ
+%c"d.Iea;XG=$QIuY#bRC]XbTMbA)*>p&6?3aPlR\_,pU'rp&CDDZ00VZam^DTYCI"bGS,pf>eC0p"$ku^->l[*"R8fVlPU'FAYD.
+%pH<]YO.ZB_I5g)6.fSi&qjT5\No0V,*'aApjM1[&?VKA;s5+k>*rNhPC\4:.?Tp^0SRbF/qI]^'n%Sf"Iau[8YhK*1=8[PW@95Bj
+%feh2g<p8L3A_Z,@b<N!cr+8s4l3l4F)ZS3.jk%=mrI?bp\bL4Cb1F/eHN2#M)10h-\l(\1c#S;^"2j?\A#s>C0m5p>Dk5X:Z"Oie
+%_>('6rT`ihmf%TV6aJF?pEP/0^\r2;05#YbIeS'\a5_%#</7$:3`Y.podN#Y[0)AgpUKKQL2Ok'].nKiG?6^6&XYr6NSe+CnDck=
+%d?+"\lhda;+2Wq^BXjUsa1jXk?iT6ap8=BiCnj_^n;[HORXgF0o\5ig-[E'j?N,`?LX9Z("VI(0Lot+`kmtfVY!5/+?ThZOh>Z`D
+%M#tCQSj(t84WKTq]6a,<n([nmj8WB5P83V<H.@$R:$^2BE;aO?4\HWk:*fbtIp=)qnf&+kpXckbGFs@1$N0&_4jiKiro)Vts74)f
+%2XP7"/X?=obK]SVO13_+fi[>!Z/=Ac38STd5'sfM!j\oF_"j]3hd,(<E.%/VlgEmCN:f-1\`U)Es5in@lK@1jd58MolVGRUn*^/k
+%p9n\jC8eaE[rSTh\+/\1&lSEE_>Bg28!D:rMsrhk/^7$3khgXInb)kR&(e;*iD*,)s5!YHLWE;hFu@_jloh"cpiZ.#*V<iiGW=Q#
+%LSsUUqshkocaR!-*[$G42:&XBs2p=ngY:Q7_j)mW8(XpCrqN+dc-Hp9ct`U0FmsSpiNI=lGIs-gY(P''K5\@3^?muXp2GP[l)AZU
+%>2om4is<'4&Sd<ci?2tu#BcPh3mRc@e':62kF`Ug#CiGuFpk^d>Bk2#Kl=D(W,jr6[thj\_UF8BI"+-&1Xoq"0D1+W8Dh:JnpT+i
+%?bp*J"_3/!:^b8g,Gjj:7.;#X^kgo%N*@Djcbc(-0AOC"i%MH*E2&Y,7.;#4%A-H(@tJn;2!Os8$cW@"U!DTsAMQKsF+Q,4Oe;i,
+%kt)dRoq)"TIA=8=cXi-4#5pe=(a&[0Q=pJ:eFXd+(jnY%(n]#+6%tnan\JSBK@/*E_dD[hPe^Y)"lk6M1lI#5"BTn6]MWVJH7nt;
+%F%6*QW'`.gS%s_I:;)FS;nqP0e?[:7eW:lO"/?ORK[IWb1huk&`Wq!e(?%32O'k<#_I'5DUT;*AbSJnUaO(q4]*3rn<s79NkCb:;
+%$UPXbVZ_5/*C67Q95oNTbDaNpW:*PUhG13%oCP3E:sXtR$(GYS#r^;M!IkB),IPuVeQ5)>Og5*b&bcUD"n*]8_:'!OK[Sm3$^B[6
+%5`Z&2n8s><oMt`<n"k3lael'-#<mtp2Z2%4oM,7ZT>%6#pdm^#=2R9LnWSF!M=0COrQI(Rca192k+D=8^58KSZe<]Rr1otMX5/e.
+%i[=]kpN.KAl),"U`6Vl[i%N>*h9-geqXLul[N?!kAp]o#p95J:So\,F?=@Y?r9HTE9mTU-eQ5>%g-7NM(++>09[hd@j04R<oEk-3
+%-+gb_TBi9Xe(0#T?,LT-W5j3fcZ0Q2*hUt'rVB#`%hO6g5O3SXf2KA`7qdIri+`$@rEW41%lg\<s*"Dnr_E.MQ-(+04mgrjg*?AU
+%A:9!kHj`mNoJ>P-UK1TF%c8k1lR(l6i1KQ.D>/ZiP77uF=:=.,l*oJ5h?SSg[%2rnj-9S%rs]G0#5Y%NI9>jRd)*Dm_=p:p6Ha4(
+%%s]7ECC]5b_C2&frY,1V!dlA`)%DM2%tN!shJ!Ad=ANrJE#?0-pjfm:H\(YXcc>jYILn%7LGPCXK7=doF?NF3Tq-Amq6356p8p]/
+%6aLY9>CE'2qW-gq0ue!MF2[/GR<gh4r$VJ.CnuOdT@cBS6UD;RUk@LYQY$S.Rs)N"S[@N^<@]lf+m.A)=s,dKjrC8s[,ZTqlJ$Q>
+%ID^&7gH`q9k)StGE/[64elI6>-HA)u?IH9bK3#J6Y3dN$<6>cP#CnF3fQ7'/b18A51>EE4/c=%\dK7XPDtQBgl"Sm!\%$3Y`+g>^
+%phb4CTn#q_5Gi]fcCeRTY4"5qE(gL_B,hStRio_GnkVgFj:;#QGL.SM!pD(QA:T_K#IUb-.^[@YnKl!DO]%%E@$]M0nJRC?TJaO/
+%[/OG4$eMo?o)eM8UH$VVn0^Oaf&iE!L-:Ue^bO'_&jB#SoZSTJ1gB+)*ZLLtcG87`T*)j!Fq4E8\oG`8B]7Fc")p\s#s\DC1H6&Z
+%^V)m<pRSgHbQ.8oc3V[ZH>8VOV"`D@n-.9Ri:D?2".%s#oN+DNk$.ZdGU'mT6QL,4qBY+@H[MF!OkpI7,gZ#I6AsAq1^9,N+OLJ_
+%0Uc_EnIin#3eBHQ$c%8\>ec#;QRRJ25F&?&^'+35b_\N[GM$P^0gZ\=Xp$HD=ZE^Y$$\,Fqge4XF^7(gSot56ST)P"8AU6<-)7,Q
+%UpuHR/l2P/J=dI!&;Q><JFf>Z5h'uT%#cI\]flh6U9K+%qklsH<82S$i^Hu'LXNQmOTH#g)t?H/7.Z$'dRL#8OCRF`K,oY:V.i/9
+%6)H_q\\OhK#AX<J#(!"L_A\h\_$Iht_&o$lkoK:[J2Uh*e2orH-12:iWjJPUNmA$PJl_8dC_*=U_XlN7E$>7.#W%%<d;S#\OOU"J
+%n_GIe2X*0mItVA3*C%6<>uFnAA(PN@jK0cnHeo(4+86'6O_)EI+eS)ToS`:0W?-MjmcVDF>)bc3-+I\o]2!?0a6sf"DnFd0hfJ5)
+%\rN<<b%g\d\Ec?:]9OH#*/jqY<sf')oNIAbi(,VmE"-s&\HEd`e#ur;-HCc+O/L?AWoJX=+t8Qi\JqCc>5l"eD!!=b>g:hX64>lD
+%i`;cm+I."DJKlOj`I80gcMO&DUHLk:Uti3!YmPSWJ0`AeoMEF;oMh?aKV!aA7%S/TP\ARfcOZbDd4]kh[C4_BbZ!$4@E+trFtD[Y
+%JjO)n0TcLpVOTL6d`BmG(5\YKJ(H7+f#5moL'QgDl\XCe\.c9Y7emMN[R1WS&E\YX*rEF$ILt,.D8b;<mf7\QK1OZDH/LojECJ]8
+%@4+0%E`(?d>n1#3d.J)-X@/Vp+ZtJ<>D"11Z@q@ATG6L%WhJZTRLR+L/Zi,iT\cg0.(BXI7/.<q!,4$e\Nu<EF3n4q#"0J0CHYl#
+%K7k$l`A-m6T]B0X!U.Vs>T$`VXDO5J0!,;0gilp_l^?ft$cOeN8]rFHV4KH5c.$C>L'c39Qq9D?s5N.7<b:f"96Sm4Uh-BT!bQ*_
+%)6Jd=AAVcj9?(SD2%"It0+Ba8Au!%A+M(pAg57on`;5,MCJ;&i^[d%`7u7'i:'%*sl]RYmg:/W;<,Z?Wa4ZcS6-aCIfKs?R(W82-
+%+c1W,jA4:hKL<^sUF*@>UUD!7#`V>hS`R7pP.&nB&VgH0O'61pfquQW9(N(dBXOB*5Nth7HqL%'4duc(9>$L^\o$7a=ck_HMh$i#
+%U_*o&d28')d7gtLiXT!2b3)f(:Ab9oS^Y\CrcHUQjV/<9iG$odb.+72JK5HUV@"4Oeu45M\0cX&'5ItAGNeXIXkBQX2E9VG?LM53
+%CKeCbhf\7%kSMSsi+KF>#h5[;'N2HH[]=0C-EtO,g$UPR"maTmgp,MlBbrA4f^kY9;[:sA&NeecGlt/b"Q*&E7Z7Idl#mijK9L`g
+%M[&hpCi6ju>86t'XOXQ4>L@2Mge2HoM:Qa0HfjEu*>RsKA^(RRNqTd2E`(FL#Rgqs3'Y"qfU3"_iutR%qi/B(m>?\$dOp0Rg=9ue
+%1l7Q7BphR9il8ne78KT,**L+Plk=.OQ)n-gb-a"AQ8"Y^VGkjii-D6&3l"rNc+5U@F732Dc=;s!*\q3aT!J>rQ3O1h"^NO:8gGY)
+%:snJ:C;h5G3n>@M^BLRTdVSQ[2EAj;efM-EmQ_a%<prkZBE`?BBc4#:UK55eIM<e:@%LN_%eQl2)tkRSYfJ#ocE1`mMC;)&77XWL
+%0[n02,iX+c8r[(E<iDK>g;"`1_J$=kpM+*KnI7)=&]%"8ViA:^+gp6j'fs3%H4VrOXW9fech-gF2?f+09bSrjX;81`e2)5b>9sNr
+%Sj\lFfNjA\DD.;``k4=5K&ZX*Cun;HO#WaeO(*0e(gW`VPUjmI$^thg\cYj0T;!oOpSlAl)4nO=LN:;O4['aCP"O-AV>@Q0$`*dc
+%n^,a"[3bTF[$M"kk\9_r;ao:Flh`A6P(k/\BA*_pqk9aLN4<(!,Lu*`ZE6PV&hZ[p7s%0J?-E.\)e)pS-epH/\=ti)io;3GAS*e9
+%?n%PAXKAnm/>LfI\tR#eh?/1hlk`mP+ma!'#U?N!`H`4nF,Y9EdX&m`,@t$_OOOi42m2)37!>F5C/LT52P*U_:0/>&4@k+Cc:K]M
+%&/;@6ABkLn]ja:]&ab)FMtV-]ng8FliDD\;5slM]i2Apple@,k#IY>CV4reK?3L8]Db,J]lU[.'TemP=,K72KG!OdQ-<VSiXf#ri
+%j*#F%*-UGqPHdQ.#0K%L2Iflj7k6Fp-G&;FpS$Kg4mWGMbTV>o/QsJFs.$Jb'Q0XfDq'AX5Ds'oGR3d,LaU%1F78@74ZEh)W3pqF
+%F]%_<J8+<)]IGmC*sg7d`SY*[qTPc-RR?_+YW`UB98(bB4[FMUmealX5O'gdT>t66M/\_\F#Yef+'r0JfDs>b>N>8L>oW4@]\cZV
+%U,PR.JR9'*ej4tgqL7/9ITO0H+;@XbU/:n2c#&GbY!;)/;VoThfae;,?)JuAT>%eH4_ps&m;G4>HRJd$]fUe7m:UG:r9""Hk3`KN
+%0)UdfI!^89nu;Iae[`kQs)RjQr-Wqi_p*2_`lfIlYQ!Pf/u4j"&(ejKs39`MotCD%Er5k2iVM^!l>hCIrl`4Lo(N[H2]n'H?V@fl
+%nrMad/#mWDX^,8H^V53tjn/**pn*mSYmrpHKoNj6`fKn*Fa9cQO6Y,&Gk@Gn^SX'DWm5acF,S:EQZlF'Np>K#\p'k9*HgHO<W,6a
+%^Vm/&jd/g<_po8^*:GOFp^S@+Qg[)M00_Z@mr)SJT9&HWZhX+;?Z'bA&!rokmK!B]I_>;KS??`or;"?"koTf*I;9oWhqrkYq&]IT
+%0-BVc4rd@"pHMq]+2[=rDXSW1*'[c4pQo6:^:F+<@hjkbh0f$G]"\+U/'6u#a4ned(L(-Up#P`4rkldODsI2m#lgO"5/7,<"#j-:
+%b*V_Ss8C.21CWilh-Y%QO8o%Tk3@X"HL/4lIs'cn#Z#l]\au#SGN4H3I]AI,]8)m9a+nn0O>u+P>^q?fJ,XQ_rckuNa]L@)n]1Y"
+%%WLM&KC@7MnUr!?a<&:PW8(4=GSeQ&nAFpK>Q]Q\TEU__9DIu9r>!T@rlb6\p(Sr%oGd8'\a&bG[3%)tLO\pW-i]dM%tGc^f9+AX
+%I.d:P3f#`/lGJ[,?TrfNW@ld07JH*I2.=KgFDamIq(7m3<hnu!6`&[<V6?lHf;^tOpX`C)O&Y/#\sYe2=!(hI5(C;\<):t2S?C`+
+%"2<Y7WS5mL,R>T.U?Ln5a"Ond>hslih->ARn8ro!Hi3.!rKVl8qJMANo#!\>s4uikVrM\r^\;)5bQ+rJrU'JD#Vu8$lMEE6a%#k%
+%l-`P@2"esZs1A<')Ya/+RU3*\h#7'Dh9V^ReXr;8@Cfc&;g7KbF8Ybc=#U]IFEr<3dF6.Rc\guf-<S)?c/TP_1>GjRg]6kiid\JP
+%](p=Dn`-Gfg^3!k/jJ1LIJEBiZ\E8QiWCkphu)gn^HNZf\6;ml)_O9$!('jHDS!LWj<+.mmY.,`GK62.X&[pHN4khJrp+h+_f=6#
+%2,q<[q#(*"5G.q&GOtbZI<#l%%=KA/Idc7nNLqI%4/dW.$,2hBs5rI%s6B(@n%O2GmHqs+l;n7ZeMe%PE.@cXXoIS)e`QkSk9!d_
+%h;-obHBhOhYG`32o):r,55PgsGId\)d#6W7??q9W>kn/DWVOF*iB9i[SpfSVk3Dp_gVDS5H1o?uh]jOB]hH0JN>J0GrrtlJld)K]
+%YUYM05DBc!U2E*fr>_9"gXrcTfDd"Jk8W.r5Mk4geC7slrq8R:2g:l.(dj/COfNuC])T.e/G.5Ol3@ibDnfOA*90HESN]?dip,8?
+%Y<G6l<g+rM1C$VrJ+GU3#cF(kRp5RahZ<7n%euODYBIt4Su]'ohM]2L]"@o`AICUpqM.6"WrBc5?h^%=g[FueIi.IEnI*'Kk_ER`
+%LM?6-Y?1EV_fjZAqr'6[@l(Q'2tl8cNh]tNN,Dm]RrLOX`r1/OCS@Wr9>YT3EVF+7k/g?`BesV(S_%*WF$2I2.FQK>4NuhJc1C;7
+%@_M<tPhj!E&$C'bGgO"XNG`dpbIF_1`bhckoj(jIl[D!ua#33S4)d_tDqDVoIXTkuRqC,e\kTpW2WJE'bT"#oD`4*PB"-H3%bl<a
+%Ctig9mC0uVgeP)Po.(Q[V/:E\^T?2?]4T[_\m<&iG2mJobr`C=ml%d0Gd6]Iqg./dgO6R"pVVIP3r$@3qt5EEhsP^crVgc7&'^fM
+%%c*iQ?#=t%_3a%dD;G#gY<?Q=!A`2Hm71<_rO&VQ^\j812sqcCl:ob(X)!$2%:1<=c/`%(gpgs%2=&6mZIq.MVp2r,pXN*PD;3?C
+%4YHcVbC+8:RrdD3OL0JhmB58tcR\X`CS5_"Fa_g5h#O!OIJ*R$hY.jn#QD/N%0sW@I-p^_ijI`\c'RI+jpQU(/,s8C97D3"3kee3
+%)STstq?()O^34Tu*`(bKn?muY0a"[L?ZU7a5O7Ca,hJ?bMZ;?Uf06_TqHDLmeKgKRM$j7Oe]EMNBB0d!,Qnhrogn@f<3VVV<%sSV
+%<NqbXeRNEL.#UV8d$>5E:fiaFd$G?3;:m*.i39sY[JL>4LGZfa`a;q`'C'&YEPa)nh&^48_7>3og>_b7IdX+_oMaW@?/Kt0Y.I'1
+%pO1qB)\2r#c/$l8aDUH$ZE660ep`arpB\D(W4N8;/e$_V4F22md36I"i/rNP!OhNkFe1K<O1'\=Qd4%]`6fQ>E$X:dl<78\cmSt3
+%GK_;HJ%Dd?aqonV6mA2J&8?bbg*)Rg8>Hn3WN1!TJOm7@UjFB8)Mtgi,$cPE*KoY1,uYpa:So1&UPG(HS/jS5Y<DM9*eo1Kq[OsS
+%#*.YHL[+@bGc6ZEp7B\.=]dJDhZ=5f-6/E)'=T?<:E6!O^-epW+Kb*orX['d)Ou#)>0@HrRACLkFpt4%g"=(kbV<4C%$H@]JY8qQ
+%&o34'0rftq'FoQ.@BXstHQI'_6QLE=:<Tp-/HhK-A(<(4g#,>Qg5JQ+gtY-Hikt81cTH9eAgS#(EnD?g\A:Y.=_JYT"#aLfY/.0X
+%pN625*ng%=Qa"<IoHJo$DAIMaT:\aG-fV618m@Cd'?])J=XFB+U%ANa]0dJ&V(g'N)J(Woj0mYaSg(KfJMEm<SnM*EERuV92^k[l
+%=G+,<b;5WDCOg8TDlFk=1n%5i@pgc[R8,8pVad1G8rWm0V,bC[PZg5Q<_TZLY['T!;kR2Y?D1Ifi<>[P(nVJI-+l^I-.E^A,m7;6
+%)qeF)g>,ndS+,/[ESKau]3X@'ou5kdU,nR`WLd*QYBFONh!3Sco36nT(06C<=O"+>j^atM9_2LjJMh3`MC1M?B[NVdcLn:)H1s+%
+%l)BH[s+QL8+.X!,U,_jmcGoGikP<rpFeHRGIck.sGjIJ9T!7f+@cR9<o=ST(S7M,:V=X<-GhbB*#.4!gB]E6Zo8IGTChot3"a,8,
+%)ipEmcgGtJokcf!F.OsYSja-\auVc7NCVcVkH$bkB/cF,3R<7(c]8=WSNBXCNCRcC6)u+B_tW'aED.2jf_`LmIZUthQM,dS><hnj
+%#K#hY0m]Mb*]Pb8eYl.0:j659`Mn/&bpa9Goer7;,ipMPA\<9)ro?XtK^9ro;QsOmR!OA^&OX8&eY1F#eQ:Y#YI+,l>A57m`7S!(
+%$i"<R/fG9#fYh5.I(k4a'a%F'0W3,[FU$BOjXSUYk>C3Hqt@m&i><UgInS*rk*5Wej<<d.7Qn=Z6/F*Qc#hpdHqN70^Vd>%aZ"3i
+%VVKeZm"/5'N!!X<_=+NkI(9#up$GO>s16W;^9p`&"L8U298N5/bVbm5/=UV;iNGlQfl*$hCTa5=m*@u#MEVMmE])uoc./5_O&s<d
+%+FT73R`mXY.p40!\;nE6q>\VUF."[_05&L?rO.$PJh+8J<%pVG4J5=">)Q,J>*FrRfMp7/_qZ[HPG^sqk6T;sjV(RaQg3ZG;kB?@
+%jV(RaQg3ZG;`:IPes8dOckpjhdJr@%"hL?7ME\NV>+oVa]:^8*<<_Bc_\M`WKW>J^cW@><TdD5B,VC!+WLSTU.I-"U.%-fCDM,O2
+%$VDcsT$2bu0Wfp:g&t-W%Jm$eUj^T`76;NBN]Mko$*HrOe5o(O'tn`'[+B0A@7?75M`)M2g,eH*ri0)6'c!'o<V>kBX+/8l4fqnt
+%]#Uu=nLE[9cX544'ae#`m]+Q^]m)..<*@&pVCJ%(CWNb>A$3A8+DC^iYm)Ws%TK>aI\YGnd[0`.4cb\NY&6<tJ*P%5;F<TqY0qA*
+%R,9"cZ?g`-qWQIrn?6aX-nh1$mSI+J0SaM,IQHVt^hJYWc=fCJ1WS=G2s6e.DRA5A<A<3eb_3CG7[n2?<!1nWkpPt\P^fK6`:=Pa
+%;&!B:EqU-69QC;CUQ*PPjPoui8@>fLJf<0)L1I_:P7@>\Z.,hpPQ0*RETcDbQGpA&J(mE^heM0Amsm8am3Yrh^iD-UcUH<+E=MG_
+%9dC[]jT?Xb3_'ifktCp'7Fr5%I&Xu(M!UW.j+j[j]DL.XkG'E3jOUfm$aBk)PVTHW+]B_hH$h)2]OE#[J^tF7VN>O#>%=d_K1D[d
+%-kE9YOXLfNDGj,aF?o,h8e_Z8>%mTG.N)F;8CS)H34-i%eW-/BS7<P_/h3WU'UV@X>o<5[W$mq]<5bM2S*AK;X<ogKANG$][^Iqi
+%H=kU9coPG>mZJVMKDfgK+OiYLFg_u6)A6fC<RB)jh2M"^V37\?=K70+-*.H0UQdF=0_VehMKVIp1m4t<m#@#a(,rljKNEkn8$Y;G
+%__S\2#3[D4RU%U9pU!_S#&2d^RWpX11W'QZdq#$S^:61Ab^9oX<h-dJ_YWUZgj;s_CQ8%@eT2I+C!Tq[SQS6[KpCAUf4qt-Ot>20
+%bPC<lHC"5homX]U59.=$hg*&PnH.Qm5sKXG5Bt$%H)tlnp&<kaJt5sO2Z=l_+.dj)K@_)(heKL$G6e/>SU]P:^Xql8b'.=eS`tR#
+%>2Ql:Hgi'3^"bYRQ-I3"[glJNoC0r*_c>APr,V+B[CFQS6L/T%c,4iL4kW)gPMMF>@;Gbf]s:7IDl9(9D:gBYQnQ]m[ql_$bNp9o
+%>:&%Z7.g:E2j1plFYaEhO9:Z>ib^iT1^@1G+4%7,<A1WJBYK&8b\XLZ]r\?%YA3<[QX6r5(]KN7dd)dRKIY'AU'Zs9<0^"RdMel+
+%Vb696iq?R_cUsS%E%UVJ)N`kKLsi*#YeQOqoSPh=dCW'L\o=2[S@SJGG]H4`Y3<JD?<bfcCQ3_b+n(k^E(RGSOGeBJ<Zs/#A7ol3
+%aOC^$\*T3eD-=8L,Em2MqFnur7TPOqjEY.<6N%4&JdadIA:]).]sbuh2lrNX!\%Z;PVmVPIR\W\LFgmR<2]lLa=@eB0DDCtP4H+K
+%cFIQ[E^gO"Z2Qa+-gd%cG,S"'\tR,\[f\.i463SLepl;mB,td/'PE0l`R_G1^LI'O/aZ+67O]a+0^b,o;(0:8MSghR=X7$?.Rprs
+%Otk,!-llmn1^_;P,/YI:P`nsBZE.$R1<N7PQr.IM4k2%'bpYTIlkJ\%j_'gN,"$ts,ro-4>SAZX(qW2)MEHk229Jm\W_oo?WZYJ6
+%\46!,"Dl_@NA<Eg;i!qtm)+,rr@F6!EK-uEM[am4;,qP>iN>&<l7FpL[7400`J2"UW2d>ZE)62^4l7S9J3g?cZ&<:(_VpN9E:j9.
+%Y7sX%;jJIeF+pC@JT<S3&$EC[bq$cYLWIaU0<Z$q^<F]eO&pnbLli&]D_`rZ9t9sB&$I/b:H5lRn(f5d46,04Ec9pmLQ$G\'Ab=2
+%HUp,?b."-7EJ7H,G0l6L<.L8uhh`*Wm]K'P$9CYrlPi"?o\)=Zr#W%6^(V"41StZ-XLW<BdC8*X0t#/ZimFd?`J-E9Kb;7Tk?&]'
+%E-6U+B/hUmr9'Oe`Q%Zgb=p.oX1)2CC7\P@`A1B``9Jq?R@5N&?g,4`c@d5kmIRb1T6+)U1AN7up%g#$)P#[HWnsbLEeEuLY:;%n
+%qun241b*_j'sHPC<#K&=g`,JaX'NCkXU8ji_t%AdQO818<T_Y-Eb[Yui+-)`.dcc%Y2RT9SY-U>W%.Cq>4RYVp63@qdO.)h51P@b
+%HC\tSDVD'rk?F4@L9&r%<oq>ll?0g@\Oj;W?8u2(o9V!]mM4>PfYj9NSc9A)pA^(nH&W)(RIa(RLtdjr0/2Qj?FI[k,2u0qp$>2o
+%8M#?kO&^Gm71EE2h'ZRJR(Ki@r^So'bJ),8iP56cT@P,&P[:VB.]o;B[u'("X/G6"@Q<B4WHt$NNjsD8hBmt%Y+DZF`GhU]q6f0M
+%<n"'TlUbYFXm3=Q797m;Sen:"\>E9>:#^`&BiQf^4L!n.qj=1/<)7dE5C-!l;k@'UEQ$#UYtEVkq5T<i>PY[Vj9dE<C2qAgQr!.e
+%:K;?l0429R6:UlPEW2hMaX\('k:E'[f/[.,PoI[)K86&4@Jmcl]Y4dfI]e1s)gfrp=4%NOVM;LnRN:aSlsYr.cCVdu,fciBZ;-=(
+%<P=Z?>1BV<XfU!G?<(oTSJLmuH7S<gW)qMR=f94u?.$O`_DU/6#%#djkXl%pfm,#8?_"<SHSfUY#?=438^'5Sj'40NVoEZbs2#ga
+%2$>#n;7CVL(:D&L8Q1['m%Q.[YM2'=Mh4?9YhW63T[[X4JBl]>G+&V$37bF8Tpn&@krCh(h]?]#6W1Q]*'aA49($)^.tjGV?.^0m
+%F`^NKPE"2(kuom/bB@Z?SZ17[-Mkr.N:t)++`+<!Pj?2fS7?(o'i^1(8phId)`;N-MC1d`AWWJ34VLD/BL#Ip_KKYK.W(PfA</S8
+%OG\77m#C_]_a4"1cURIX)nqqQm!bs[HblF^4_Dis$).dY-GM#=ONF\3nLErM`#mDSbI]"Bb255Pb@j6*2D:Aoa\5BNAjVf]i,"eR
+%3A<*R[0T:n_0C)JFh.^X?6;b0/jZPi7oH6Xd-CGKn'6Z6"oVM87BoE]fNt4,iX@".5\IB#8TCadH#[q<S2n+UC1go8mRmsYE5n&Z
+%MJe^jUqB#;E.oA_bH[Qd,nA,WR%/tsQ^:t'[oU8Z]_mRkpatOnGMn2L7U(",_De#lkS\*0QEit[-G`oqi!F<W0e+:(2T[$t<K]P%
+%11%[tY"Ku5$L.Ku10k6l=$l<#ZWoW?G4F>sQ)@h=Cp]Xj="?eBjZ*Y\HWRV:SA:M^(31$5>7Q=5Pm"?<./]OYe&(e8Y^-)VlYZT"
+%A-;Z;%H/#.pP+Fl@BSJ<&3e^r>8k@-qe,7shD<oq]Q]d,PkQm#A)>DAT:r.tlUr*#/auT[7<:XRJr=`N3T[i9jek+/%6W0OBim6?
+%)=)f)kB'dmYJH?R-SO(7j?!"P<-bekY=],2-j'Q!JoGQ/.rEMUO9M=B?Bpi;/`t_)LW6LM<U\45@KXHn"WPBKkHV(pYWl(N=UY+^
+%j7-`hrV6X2F2Q]q/V$l;=l6u2VBnh`nV3Htesi\,dDoaf#SLM8,Y.j3=p:t)3q>Mc.TiNZ6/?b4Mp:NgIUp-lh+=?]"_k(P>$sjr
+%ahC)/CkpEj%@^i<fER^RaXBeo=Ye3aBi^2!EVDQIB.IJdIEY7:D`U%q[mc#D[X-,m>JT[,QYMS-P])nQK-Y,QFt)n^,-=J<GWgWp
+%>GTMe^MX_6cq%EkJ>)]X`\\73jKVQ\_3"Z+UUP^6gZ>(QLfZ7iN!X]S)J<759pRkX/%'4K/]FSAQa3<!_Q/>oi<3+B"6gdr1_)t6
+%eBGUl/AR)O\6=^$=bs]KYa\PK%>We>@N=Oo)i:EHF%-F1&AaJgRuiunKkj`@7#P!S`cG4O8D"083!(AYp!ADge;RAb)R.`WW"\b+
+%et+k"`*H'#(]1Jj[%):i?peKF0)u;[UUpMS?gUaU^87nl/N#GF(K94i<'L!`MTk$\pVV]W5#p?d6)3Q#GJf+R[(_ilA)/1FQnCK]
+%\lEN9>l9nP3c;"c]Pc4n8qf'.@-u?-]$FD-<jCjKC=F>DDm)pV&$$e^a=C.k;;<V"0cef4Xinb4_[:]^Fd='7$aH^adTE6h')4bX
+%0SD`5jIj<T6CaWG*+:ZDJ[oj@9O[f(;s5%XnTG4GfMmP)CE6kIo^^H[((m=DS&d,DWpgNF$OaE7F,i8&AU2JiX,72i+1\t\>ns!%
+%nXOASG?&:i*+*_d`T$.D=+u.*Hf'GRjI+UU4j9N9@J,?]+*2(`=(Z2p/2uTe#"J=)H\3%#dBlldV.'j:>4jd&guJ7=HHB#$k8#Z"
+%o5^,;U.(QCB=57=_@fY1H$%056D=q.FJt?>c-KY6)&Zt/0Q)KbcSf#I^=M8+,D0UB4J\tt*=Y4''i%`^amhi+\0Ope9_ZVoA@6]n
+%YBYt+\e0EMI'(:4k8MV(&l'(M;;cb_8IC4fIN4b8Z[4m56ZJeb=f))nIGqJW/U+2$W)RpLHeAOj0m[&2BbnCm$DH;L)@P.n\-ftE
+%V9jdV_e83]j"b2$e<1>XamV*Rad]<g@9`<F4WA6,)rWOM^mLr?k]HZPjTG]IWD$m0b+)$QP:%M%,aG?F<gcGj&]@WOlRWbO-R4^P
+%"Qtp[m$!YhBf^i+8OkI6Bhk'DV3G+1.1&[GJgt/4^o(hBPbHI+?d9mA"(>6D2"B.["jZNr]]c0.?VXc"mlP+BnPcK!a&nsMF>*qb
+%`j=cgcDkNJ=nMp\K<"9dY]sVWaZh.E_,hr.3BP@!a*p%nOIoSh'C\G_SEQ*a<,-'.W&Z+^92Bm/;`oa;r+HIBBZ4ocoG653RcnjZ
+%DRf2OlbJnI3E<7%3*5JZ:Y&sa(n4[s<]s?EX@_(+?KG\cq[;#"3krjIQ,5O9f'695p,,kl&(H3)#>4qV>*U''\K^1;OK$)_MRf+"
+%9)cM'fO/aS[DLk3I#9+<$_8\hU>RbOpaS*-D'f40Z5YDh.To`-+@8p>KM`]6$,dJYX,q+'P0*./Tn%/%?p"a7@N":Eq1%Ai5M7Qj
+%_O5n+g+f5qUq_0"hgQTlpqu_%eDYlQ?p@_lF8b*dIUYO9ZVJWP,F01OL<SW+dl"=;[cFm8g[0@gC5iUT2B7A'LSI[[$XO<2F`Jl[
+%?F3JE:&,,tEX+cP[H=kfb=ACPHsCEYS9Ui*2psl`_6GD2Qq]\R1U#Hd(Y1R]<f-Qdg$a(*^UWLs>!:k>Hp3@cn5C'Z?Dp<l6K5bA
+%pb*ol$]4mMikLTM0-pN)M>op%^QA4D,lZCAnKd-G=TZ22U?g/Z-Tcu>IYAYGbKe75q<RARY%UUMl<lP+VGL<I2mQR"Mu%Ac9ROY\
+%D"Vs0CLJjhXOb.O;ZfL#I%.BfNh-+"bVQ`\=`qe,G.V?-)@tTg.e66+>ou6jBB#-L-n7L7l\83n,<!`Cn1h8OkF-Vdg'U@,1$=O/
+%nr;/Y4==e5&M)`--E*H^[q@0ZbA;mEL+W#[Nd8!Nl&e!6KH:]>?8Kpai%F=JE:,k#HkdJXS`\D@fV:D'q("AuZL]QPl_Ohn5/"cX
+%8kRjk[A@0`g@J-**UK[5mb<V9mYAaCY-%,$GE4,'BZn!tr56mr.\,oql.9lE7J9\Yh_sfd8t.?:]oot:"Xgd:gg5nO10@=2npH]s
+%(YNsd^9:OYI\dOhi@Yp[',BtV]l9#_O&;uf6o'm0P6C`YB+UC"iKP#"W&V7a`iF+uX&<9(/Cd]7d'?4GFPJXe";[5USHE+LL@XKD
+%;GFi-JKD#oK>V?ecLF(dGN$,VbZ]Fr4uo0#0k?!Y/JEoU3#=G7R:e^/6JY_B&8cD[U,?-fY>7a^f1r"2P\SP6WdB0>W.bGJS(fFe
+%kQ<kogITK'<GrgJ$'C*`Qr4JtBD%Q>"bCr"D\_5j'-\n=#@KGU2\Nf;#^Xl<f!+J5&#kgFWBuk`66'skLD?pte'b6sYA<OJ[ZT*W
+%'pc>n!d@,1/?WrU2=A"TDRI"$V.10_At?QHb2kKu<ES6YGj%=ogW#Lq+2UIeYb#u?fVfd\h9a7`*p6fX5k7UF8+J%(RB"P5HQB0T
+%MQFB^Nq%R)f_AYrITuH)ISspl^T(f5RmiiKl)I_<C!U@hHh+.6ia5Xg#G[V4!B*,2<U+,e='ei(F]L'8HKFg'8-'C]12hb9Thrt-
+%,KFE)ljucYf''b&"oEl'%Q7cXW/Tt+bQ_T;&=^KQC^+t%+s?R\@k4M1<8]2548bP2'M>[@@U]1dEtlc[\;I!t'+0>C?!IPDN^HUb
+%Po&HN;&48l_["I%(j5ZJU@%WA:J\'qA,\W4E@Nh2W11qma6UH7TF=8?1-k&+&1G]ahYQ*$]*_=!FB,lprpj(3o4BXqniq?cSoBCU
+%C:j,EH,?u7YK@Qh-X?8RX%M@bc<Y^_'f%+U-mtAPe?,5\bEZjgE%ffQk5*l]9pLCf3^*^Qa4I."G,=E6,R1_UhWGN)].lM5:5@Y[
+%B\U?_UU*=6V1$eF.m<Q!f14rEOf)tYSNcnK:OIoq;"9\Anbc>QXkoE^%ir]q9u8c>ms5`.0[a>:*Dhkf9a"gHP3d+KUIQh.e_>hj
+%&,YYZ&qSEHZ?j^\%j9)r\'4gOiiIJ%b#4_hrd*_bs#CND_,Sa@:OM7"T@@8CbWb8Bm=]#r&oA@YMI.^b`sDFeoNI:hmht\Ub2sSj
+%d%_kfLq"p4nRG2U'?ocsQ:WrWI(]'pRp3PEa2X[A%t(6;L6hQOE3B:pM.i6&c_:%2W`YLl&VddO*:H8=S:b>2NB2s2+*[mK`*UWT
+%3H1#\ZBs+O<H6saMENKd>Mcg@n;5S/hS=*CTf@&9rlB*VP#%pX3/pAM@JgRgo&BfO^e%T#*7hl7m:$`hiK^0_*=orp?6pb7&f.AI
+%j'%HlN59KH+K%Tf-qKBEl'4e"F]pH#c<k\1o5^p.os,7&QXbHDQ_!WY*:$P:m"FQ`=J+k)a75Zm(LNI!`KR7tT>RP`Wkn^^L%4sC
+%duChn1@!It2SgS[B\eR;p#@7H\Vo;hZcYK'[/(K/6OVh41@s%FASjBV\uA_7HV^_=$h9pG2oCg40A-/t'7(+:[b@dJhc"7^4lsC>
+%A5n<U_/GMs32d#2Ji`qA6D*]]TiuCngVsn&6`S8/-4($DYeVVG/;QsEo'55iY*Ig'8@FC10r1G4I_P;r2A]([$Ph.c[qt*X=.H1n
+%J'&h?<94m$/).mL-S!f3c;o9%%f``m%p,gVc'P1qh=s4A(!K,+1oT7#F@<jgCs]2_9.ie$JQW3_FcG[Te5\Khq!A-k'oc3H&(aQd
+%16Y\a:Wq8caN76.iqZ<Z$fp=3ani$/FE#1IN^cKlZ$PKHLpP,Cj)i$'4Q:bQ;SDK\inWru^$\#BI)/^ojud+2E[jr$:<Pl#*;hkX
+%I`S[aj:5186R>l[ba/j(`*9an#&^_pgSml]ajr&=]qG(jo3jD#$NB]OU[1LHB1CQ4!I@t.5EtknML.ltbcMO-V6ZUm8m'WC)j<i'
+%s.'#S$`Ck,c?Ll>PT?SV/lB<u0f'-VW6R/Xjce11%o:N4RsFj=1Ol7]B(?%:?>uS8=g1j5:c`eSce/Ea98E4'oba;F[-`E#kH;ZI
+%Pc)Kl<HJ-h:KY-,B1*:n)Ge0?Cc34B9&GJ0AMKV1-<t>m!Pt6:<O*8MG9]H:S?O.K2^RJ'7,4:<)\eZtWgJ47P\[:`<lu\MZDjTk
+%Bqf'GW)=rjPP#5&5)VFmnpF3/e4j)7VCM+_.6/fB;X9TKp#H+(kIS=b^'j.deQ_IRJGN3Xjh;,$5Lj!+]7B`V^#cs9W'AgJc>5Lb
+%5SG[WB9,&64,@'Vj^1l:?$%mllTtM.bO`JJ5p'u(UG3tR6HRP2bUVh#4*55LB\5Nmp^g5H0@!PYi21fD\1&kVcI29UI_:+hrkEnJ
+%H1h.a^Ud*VIB11#g%3e.T9?=KRPcS$'.U4>5")c(NE*K!'X$<\\,\8k=)W:f!#^Kkf3!`"7cEVi<oK3=\14$nMQF?U(9CEp96=M)
+%@$!E:a1=sP)8X#mD-)5V`E+u&H_j\'eGk-=^E@M&M'#73k90XG')R:LIt)\>c2I>&_tEC-J+GT+\+LQfmm"WI*I[P(e\f;prmi=m
+%qYk`IqSSXA4Jmm`=&!a5:L1"bPCJ><p[S]af0d7MkF_;<+8inRjpV3pl;t`)rTR\TeH[Z*k<FJj0s.%ObS7ca$gDe=HF>LkIZ*c4
+%r<_BZ2'ib8JVqkerU/Ci:SINboKMY70E"PenrE@]53JcIn7-tip$i+X+rp:gCrFSSh.n#o3k>\p%Pr:+SM+0M4,1%a]'u0P%/6@Y
+%go;AJ`hDd#':_oV\CD@dJ[2kbZ50Kch%4M&\Y8nOmsP`:Om/TWC'W#7DOTK@j4o]rEV9`-^M;`&*oIk9#9,*rl<3;_^,&M#FZ5@X
+%B7_]T\;+\6B__S?J#7!7I+9[1FT^7[ICXiE\8TkQ>W,7ldocK.gr;%DmudMAe2Q_eW5F&VpR\hRGi4#j"Tg[CTa*ic"<^'UiMh89
+%5T<l11^5Lse_NjU%eh25NTUN7]f*s8_>+2Jd`M5Kk1AL7cJq2-%GrB53]cCqauV`pc?H[?(Of(4Y<!Lp1Va#"?A3=e4ahP%_gr-m
+%HniJHp(Opi?h>C0_nCeH..`OT_lT\oWOj#FngM.`JoPoR^.8#T[2s^$Z]`$,Ho3n^T#m\?^o]V=N^^)#__7^75*BGXqu283Y2pS(
+%05]]cPFrd&ecVk=<qQ;D)gn%eHpPCTFlnV8H)2MK^$ri7H5bc!Zfb3TItYKQO-^t2&BF]9E+jt2E*'u_*">h'/YKC<pP^*;OA$cI
+%6Zsd(bfD^jmii-i+oAP`Z6ooK7fWI=mLa7hF^B[C1C./4)[:[#[O9O>&Ki8+#PY=p^P7!ESc=m+@h_N(Vt>SB'6tru"7_h>kJSCI
+%<>StFc`W?'C19LIlqKPE.^h&kjre4tZacC^C&sr*N47kETGWD;$;=PZp*_d'KQ%$+Y07mp'^S[B-(XKaLa>jjd-j"P3=fu%n)N'd
+%0_X'^]94LgYIr`T<q70dle-&g1j7ch="+1'>OW#64^uqAYMR18ojt:B3O`G`"gT+1&#Q)KX."9L$q%Bfl.6Y>dmYhQZ")F>VhCa;
+%.Rp(7H!?HR4P15MmsMGM%0&pqR+'4'b;RWj4$BsW@]Wj1-eUa:+Nc7ZE&l)FEt%aEQj=d<O=PdaJr^!B;!o"lNe*XHqr:<&n:Pkt
+%Y=fRDfoK]?q7IsdB-t#?mg?k:LouatOmURg%6\gf%dV?c"*cBlb"O!j,aQiJ@n+>>/41q<pu<7b[:/`:E_;ge16=,[qV]*ZD,)md
+%1(?oGe&+>K(@[=grq@<_:lHcY#"Z\-qZJ1n\A2<6$h<Km%3Naj$tC.t/nhs.h>9V]h5?-'K*jHBg:)M\JX?YfKdHfjd)UJL!@DA6
+%kW"+iT_!DG2hMSsN'Z?jB;P'Jmc<o]JM,Kt!!$-#XrN@&=Y@eo<\68m6*2Y`'&c_8J=TmWnJ:n\kug_fR&iJFQCBrH"-@sphTsKJ
+%#&s$tiHS_UKQmsQg5'mk^2@=Fld!]:M:IC@"C!-"+Gh+32I6b%"1&,jXb%dr"JJ4Q4P-M[=J.'oD`PYB`tlJcSq(K\T\#7Q#/AY$
+%EZ`GmNmSRic:qlc(4^<N-NfML:-)G)fg*iqTT9KAYe2o*F-7_7=dJW9eEMaBAK>Ii!0*+d+Pb8&merBm,P+<GH<)HVOmaZ!,3Y)n
+%,#_tCUfM2Uq.j$OV$1s*;:3<c#)p*iBnZA$i:#JA*q>'.c-R[e4YdVAcfFs`S]b+b/6#aU9DG5mRjGoj4ZDk\#+='S$M=iZmh,bc
+%HVHiTDmkDE"+p]J"!,aLFTdD9kQ&6,ejC.;I$<k!RpGEJWj#/"&((T')ONe:EBFM"BX=e`fWh!G/7gr00pQFRK+k!dKV1mo/PkA>
+%+>O]TdO!*t!Mfa;@4'9u&b`%K@N]C*Cra_O9::`M6AA?S$h&N\\dCqo?=5[\Bo3*P44QG*4g(X>^&8@akrbMhL=IO/.]BIM[EV\.
+%P'U@U0ggL0Oa805cm+R;.;ig<0)IpO;i)0abf]K3MmsP51ZU2#a>q43=B*lcM`NT25kjb@r<>6SkU)jeTqg5ijhC2(rM9a1']]@q
+%5^i+?Y$Vu#:XrJkiV$A321aN";4h:\Gj]2p8epnB32iPBcsWI+Du6e^JJ*8GaQO7J^ip+p6mCj2psaO<;YQS7coJC_Lbd<pV5c$o
+%<NT<%=;d;X;:`Mu!X*?@+"-?d;C-bA8lad,igXJ!?`+q3lb'"@H*.%!!EoJn!KmXt!pJ'C0GDDdi$luGeDK:a7/2_UmlDdF;,hpG
+%4%(+3h_sN!Z64Fm9%>EuDI@&V>'N?,&#P-8+IH<K'@RqhAT)*h?]^8\P)W76W"d@06C!XsV7.(/6LUTSXtfJ63!U3'pJ$jU0W[%U
+%JVE'2mn.[Q\s0X0M_8QmgsuO5[$#c2L!R7]n7fQ(,,9niJRt0]>Z`?<'0jnR7DnsXZmjtK?r%k-[hT3R;_OWN*ESur$q>Tp,7=e8
+%0!$NF7B?jgT%3mC9-e.PUu@sm-HkDFT.V#^UkfiecCk8N@#"E3/nG6\f.am9"%3=WN=+Z,3`#DM<E]$(fh7_:Bo!XGRa+*o8sql6
+%Pg1*AD9$5-SkO6m^a%qPQ@fn0EDDe)A0BrF8]?ij7W-dFC.tQP1TRHf@.tU[l$s]-i.j(3@hGCiUbbPE^tTLZ0l3i)\PPSE>qG0*
+%(8ASR%4(i9MS+Rl>Z30k881c[fHe(%ZU`*@=jUC^n>qjsn-O61h")Stf*gtB2PUH[\#=\8ZWC2dXr1(+##*$B19[O^Ng9Z!`XWj<
+%J;^ga*9Zn<g3h<E5mIct`sWik:ka8P0.rakMmi:dpPMVuG]l'ml0b;$oA0`?5__>46TNK*6Wp^09sjLO_fm?mFj5A<55T>C['A/.
+%S-P-6@hXg-ZU^)p2\XTK3(9LpM2>sK*<Og8CbeMIqGSI`P+.[[H(i"I.T5IDh"l/KoEi,=$b$=6"$E[,WtqjDYRT4oGe67Kf^Q8;
+%U=lDXH"/^#&W8sZ/G&^4#E?*s+,n6UcYL,u%g+QfZ*e\FFBPu*C1CtoqU,Gd?n'(N"l";iX&&)"$XebH`9orh4\!"sqh1obXho!*
+%Rpg+bdXO@U\'-PsAc_9sbd<aA_JWl8[<CGjD4$EMS5#+21op`3F_EI#)2"*W2jM`B5u!9K"mkr!I%$,sAd?\6cPB5trA5&(.C$3k
+%B=0G`--Mgdgt=Q-HSPD(irU+k\UcYN-7Ef1inBq'4H6WOgo3GEqi6jQ*FWf'fD[)nJF/-ZB43@8V'pWAML3FUQ(cS=(T!kCaH7cG
+%'?$"F=!c.+R;9fg$WJmB*cJkQN-ids.."@nEA(PNME:cCm@l`M[Zqj5$ek/b<FAY)rr@_L.%1Co4js[a;BeJJn:\Uo(n,#^L*[U[
+%VX:c/<GCNfD"8h/NA?#*=Nq&2;?^8%(e5unB1A!P0?`4tYe\=+/JHBb)S-+=Knn;I[t2Vm0Z8JA(-us\ilMWf&X:tnRCQ%#Amnm.
+%PjPt$=Ad)64O<T:nl.4*O$\fZ^_=jEH_:`Ll@jP9VK/jG1fRmOn)d#<J_R>q'0-74TOo6t*:&>Y<RIZn;,quS'31mp;H60ROapPD
+%PVUW7rHnLU:Z5WL>>uKo'h*0Y_d^_P:"1+hB:Qf9NR\tM$B!CDV!?\SHe41)1Z3ilgdT^lZr8c^m*n-tK+t4Em;*Z1nZ9(RJjUVR
+%`)*A3Y[87C!BHQ@^FgFh%g>]ePXSRhmPMZ!]k2%X7Vp>e'5=BN.go,\n+*!EIYGf1YiM;K;6_B@'rh\?8,*eESrfu?Z7$gCAPkXe
+%b6;CCZ!\@Vgl"X@0pGm0q@Xqt`+Fk25d/DbI2UZl!]\!V3CZc9@r"Yi9Mt#LfKm;.MhNHNc&HDf`g5<:=<[7=l1uPQ7,TL$#+J%s
+%UU<W2K;C;:g537o:dPq0log^eS-t;3pT0'.WWLj:7>$hUS<T<X#&Ace!gkiA=9D"n@-9@;K3;A.;SjW?,mA9u78bJ<$G<^`?PDRk
+%E?*Q*huUcDetf+h^t6/&c01WrP6-rZd\J^.S^Sa![n^@/**B%GUa9Vgq/OEV$iHN@4f6phi3V"+ouJ_,1?]Gqbe,j-Kp,\28)@u`
+%D`53F5;MT*W.:[BA#HId]r\FA'OZVh#$E/:F)#6"m']L_b&^\:VoikD^VU[hp0u_$i^bc8[-La,P/;NUdA;$W/7Y-rLXq%,eSAV7
+%m%ZM=@9U;4ATaf.R^uWYp):\Ml^)tLGF/8TNVi1--Yh$l^j:o@D\D)MU@%Et,or1*!XQTD!5R0[^O"r&l-(LO"Ls/RbIUPF8ZAo%
+%c2=,(^UE=&7&I?lX3=#L\kjr<V2S]W>C&q4[L0Ad:Y=^5HXJ/35D*M1]jRnk^6i7LG[==#aA\b'CrP)p#I?Kh_J+r&O3inVWn?ob
+%@#MX1AL@r=?"E7-#C7d!'[%K[WV$tV'+U8"^.G[g//t(_`JXCBm'&P!U@aJ,K<7Jm"_*72#@!%E'8LePMQCjXFrfh_&r-P6WQjcr
+%N(FkEMF3dtDt[F5b2t.'%p]b-?F,Vf`c3ETL;]J#HZU6boL7<H^.KB&$qEC!bD=i^?2u1poaEY$;&H=m'.?+YT0Se\D1In^'>)$'
+%Xk<9`=HqWkju%mXJIrfj-H5C;pR+$a@b29M\XJ6Q,)jX4$K40H-F$k)L;\Q2CUD594cuS4oJBsU_</6k.=8d^qK$1-NZ9mOaKZ04
+%-ko_o1SKceG.7PZapAXI'5VC\.Rr$(A(Zfo]iVuqjh^@G>*_^@J7Cs%":5e4bMloiUDY+W>gI*B%(ue41,N(,b6%(.[(Sa(I`N/>
+%+Wuma%KW%/0He/'%$H-(bcR<4Lb@e^/N`bU<@7KLYc$uF68-bNQ:B7q*r$?p&LNOU,f4tn]L@np_^)#e$'SIVZ4ma"P3.R:E8=>W
+%JQU3PCt0Z94=ASbVW2n6EO'\j<Bj3oag/i3/LSd[D,)V>\1plDNDlNo0W7;LMNg[<&jIu\81!WI`*4_i$3H@q.P;;7Lu8mhcq78p
+%R^Je"T2rE%=X\eP'PNJ2'p>RJm>.o]V^<l/-2/AeZ]d"OY\JtIEA,SqEXnH]YQknV4VG6b9\bd]`%<t_[j5f]gsQ6i>1SnCVS`6M
+%%'^(;5dE0u6FKf?2>GO<40UMn%fim8/9;-@8M$cBk!kJC=cSdKq5i;mWfHFq1Of"iE/4C15Zr1ZOUZ7Y8:jW(Tf<MVK#E9FBuBd-
+%:uTcVL_;1V>mMkc,aJ.,f,bL5FX,iU25#haJ#ETor_2;nTFANE-1\!HeL?.mKn<iG>Sr'RlA5XbN'8_G+.:b6>]\GgUt)`sZ'$F7
+%@Wk)t">9Hhf5o[+P:i(jTULOKN!1[6"(d+Xrn=(.^c2QS%G2*]q>?2I["KQ^Re]:+ii!`uP=UIt7=L&X$8@TM.17E?'c,Sd9;,W,
+%MA_WdD^kG"p9lY%a&F2?)\#XA1og>1@K8nAk3WbYA@pPUWE#m'&1,Mr_L`,cqBQs]mlac5)?Xln9i-1@kXWDr7_Jru%n_baO'9CI
+%_,*RtOgC;co)Ua!hCE:@Mf/[/o(ereg*&k<:k<l)FA8094i^"%#$%I;;fbnIW^u<;m0lsV_("DId<\h#=[Jp:OI@fM29![/fM[hs
+%/X+GhE045rK]sX&VIn('7)[a:Sl^fT&LE9fFRTop%.S:q1lF[`KMIf30B5,3B.AfU"%!CV;N0El#A2^N@I@_5G*(h$[8LOM``4e.
+%;hE=U7qPEZ-R&/I)e@10n.WDn0oMBm)@bn$]!`GR@7G5#-'m$nU(u$06eESdQ\[h8$T[g/]g;/SAC!*Z!*nCbca4=g4<&JtZ8N"N
+%;M>ha,6BjCs"FX)cM(#i+W<Z13s9X3+ET_tn6QN3$&hqp=9@MW2XX!m$sWJ#4bgXs<KQO6Z?n7)WpJT#d*TE!U1$Vm=&?_:X1bne
+%m4F14&oB$"@L8Dh,aP![a"1jh5=fE?(1IE1kR8*@,Xe%g>6r[bi>0;;6G,a,apWHV@88_V_S@a:b#*D;TIJ9h6A/DW4bn8b&3X0C
+%9;9Lb;&mIQ65YLI^C\F_#'E*OfmMm(ZbnQ9/k#k+U:Y!T'pYJO";;+od]dt5oIf\i$-rmi9Y2n[F\/)ddXhY^s/;`H%X/L6+lP$t
+%-7%BCAD5.K8+OogdKYU;DD:o5"3VnEZ"GS).<&(/XW"aKA[>sZ6tJ\/TgY72Xo@4Eo`'$*O4D1Qd3jf^f]a'SQu)GP=:?oJ+r3Q,
+%=TO`3BPh@G-b\Mt/1P.=$hT3(:l+*D'r\Sk:g[+OP)-d[YSlNnff:"dDr)I5pS<<7#`@ZLgaM2ajiGq<!8lHhIQRS(6D3l`2I]+g
+%P+C6gh:*?E1ZN85LiYU9I)(o@-r&]7'soI\Zs)Tn)->#V?H*s@][&"$5X4EOM<?nlloqC(naq%`SMdt9`\42RmHG-#%Bu%tlL_tF
+%T)Pmf`NXO7#)atN%radm"/e65CZ9l3P5RuG4s_IJp-'d5/G)ViQ-J5@4O0X:k'\Zb9p9p@.g]d'6(GP4m&7-o3Y,qT$LFF:Ti_@u
+%B(fV10&cDlHH_/D+GY8)1JuaPq[qS2?bPnMp4htkEI!$Ok<T/sA=b'^8*3^]Wq1%"I"WVp"@#H/FF]#HF_QYC1HBhSKL?,Q(8M`,
+%`E>e,\]m<_Bs7FZ/c%6&#\>hUE#[sMm[AUSh0&&r/)Bk\2%??c1^%BulHG^1D"AFc\2Bg1:fBu+Q6Jt$4'["ukp9.oJ0KOg(2sk"
+%$gtqKP>6uc"DkEs=Mi_7?>%N.\]Jcaa!JODJL`<?E,^?XZF)9na]YZM5,DlN/S:6/LY_hQ>f;2dK7GTb(F]sT3Oe!a4M8@j$p"J_
+%$#mmRO;SXfO?;W.CpE=@q+6el<jq)[a2fYZ_b/]@B=O6L>8@@rh`B-)2/+10@!#!S%_^s0-5[2:\k3*(M9=->(7T3H^t-0IZIU5s
+%buqF4i$B_2*LB<rcn%[Z'aJXXA,o_^Z1)*h&]/uqIVY=US_]5^)9u5kDY_f7WQRfaVf@$es/P,S$H.A4Za_i2gRruR)4XW(A#CrO
+%?HZe/$X+H>=g=2DLo^PI&ZM!$!K-c(\F4G^'dn$q;YDg]"Od:pU*rRbL+!BAekpHTl]V#`dJq,hW9uG^;$,06c]isf!!!b`-MgiC
+%_to`'`YGV1/-.'Z7jOnKr5`,X+*j_qM9HN?(V&51H)bU.OU*>R5bs?Gah\;3.IF]!*LBSG)46'a'l>5I;:R_5(>K"o$Xr1,=S+pR
+%0uRNt$-S.h8jJ.c>m68lAlc=h<n:*e5nLo53!c6<_\NV2QBX)FfVgSNp3BTG2Mbumo7CDa:':G_lOfKk5LD/2-I8Ki+GH%u+a78%
+%>VbWA(,fZQ/)aimUDAVXGg;7I68X@X8r,rVi!).YoG0A=1*^FL"Z<^n;>VW/9[l64-X/Jk5,)9HR'k-H@dPF0>Dhg)l"P,skB'?i
+%[jSTMNWR/AQXq&QEluP0&jIu;>f2^t>T9NH6oG2ad\I59[]kU?-"WfY8Jk?^F$2t(e.As'B(%;D9?R*1l]oho,2lW9@KfHF:bC-R
+%4F(Z1(AK8bYSEaF=`T)hPSdB:]eV&Ze(?]YjdlUr-<9.AP%9C@"9gTL?d#)n""V]_SPM?)q,$Es/N=([3u;15h-NlKTlQ1<gh.!i
+%[f(pGk;EP4e.@TA)tkFqV\JijeI(\7PZ?C"+EtfLI!(@mUKK6JLD.@fRCVBh:-1l\"F+bHS-h-s@a1J`>#k+o0*(8lJ0u9CYrB,+
+%A]K\Pr??=0=S.>S5ec5IL#(%s2S@2s)iJ-Y2Csdl)WJW":&R`V;!N)PD"c`61b@[8TV!EnfmT?+@qTdTAXAU3FjjA/C-rjX9F"U"
+%>ILIWaZJ0F2t0:Zb>*@T@`+W%d4n#!h$grag9SoT5^TI^];,nC=k>.<XFWMS>2G,RfQEm!hpcVKbSX7/Z'Xc!h@8fq15^.*$H3l/
+%9<Zj5dPg/m^F,7c?RWjk$%3gS7A_+:7UL7))"Pa.6NnZ4SO3k0VC"PDNJgLE+Kr(_bN.#f7@:iP'5,DaL3l'%8ZmX,E6<D7LkhBe
+%#!OmEP%uIep_4>KoNk<63@/`2V/V`IS/_1ZOg8;mQI&)SM_Ogi?5?u)'>[`6WQ")2asjsi%!+Ir-WPo!0/\/uhNC?r<WT;pdgh5M
+%Ue[O?+nl;)qg^Hc:lJgPh*d$!9b_d#dmO@p4cK',KF6q22KC.qE6;5gbq(=[:j!)8"3Oi2.$0E7Xc2ntOJa:29B$g*(rN%_F9l)5
+%Ym<W>&JH(!qYW8PD4#GM]u>SZ2<D>,MZS\l.@+L8<-Uj2)lB,#:tUu)A\ZNQ*=8NIkuoj3/Z/W63h54gZr+]I!]F4u?,GfUop.'7
+%P]P+tB4,`1.-KiGFTbBD0Mn^XPOo*+r3bf+k_8[HlX58@&DQ+[nODb*kb'tYS9J$S=Qr3U2]$bGjkgr*0+fS.8T*51GbdIDD.a(%
+%,tNZ+/lFU3Q]![t+rMV/XlM'*B6KQ%nV37^(`[^6U8Ce.)7&9^0s^#:)F0NqPqkGE$qk8mBqefmHje@[E16!61_:]CK\=C9b//^8
+%gd[DW/Jk]tWi44='5&Z#2#1e^Q#*X+P,1<#,:ea;K91dp)9OBqYmdPKPRQTXN3*6EF1Q269BKiD37`.I[?U?sl-QY*m+K&+W%cDd
+%j&-hnhOXgJ)igIhq6*2Yn&Z3rE`c&^hMWrhh1uuuW]g*J%J($UP4WRXDqL6t$q=kO7Pf+eK6Cof855>T5#_F,<Os.65Rd@E-4jSu
+%JoIpE-JaoP^!gP5%OoH)/$L@nIn])6p%r:"0Xt</cm+m;Hl+2NVOJT;A"OTmi*#86J_B;:"#2Jn[Q(f5!HJ=b7UelW6"A'2f[i+t
+%6Wm(1&`&6(BFXq.hEnL6*Gs\RdZE#JmD=3!B,QJn2B8m2!8A4aG&FUWAtuW+X`GmRiY659k9OVn[M$_5ct5B\_f:rU<r)(.Nnu65
+%N?kbl-$b]@J/Q$gcQ@EEXMsBp(<0r0S1Ts5Ms5Ig`fM75d>W03EM>\k&<T\RQ6TE7G)+"K]!3[CTA^5ri-HRWQEnK"D<B><+l<_s
+%\G%W8:uB8sKc\ZVNQeD=*nhd+MHH\ofP]+c4&k[cWAguO>&sY5poFR!6CMI[`X_;[9LUb/S2'+.`c:*ZN!5g54U,rC#n6QsWON"L
+%)_c"4(M;Tara=W.dUgiWgZpW\YjB?7T6t0Z5-f6Yc?>LLA5=CC@$BZe`j(88Q6hMJdqZ#9>LJH<Uh*+N,>[1@CY?n3kM<e:h7sf:
+%:s,^l5%[of_/"\s-.4cN:sF((RrJ+_bq>`3JA:1+>gQ%h5t@c\9Uq)$eDY5VUAKa$8b:Df%k(mF5;=Z&5!SRg.=1V"+2oc>C#Y>F
+%Kcs0<C9T%?&-^5A^r2#+Ml70(d0YC!&9]LlLPnP@QjZNO.k"DkN0Q+k*74DRX'+Z,fdc;eP@=Y]^(AU#lYe5AgP\HHcY_N=g\l?-
+%9SR4G:]aQ"arJpMl%"DXKoo-CQkDkLnO^`hh+W3t]'(UW+0.#([W$LcX0OE>kq[gZJSXKj=[2J+QH"M(2[ep[m5"!t$:<27pBcZX
+%/G5O/bYXZM^_2XL,G5iIXIgc9.h!k*S+n6SFT@+X!_f^af.\%OeNQQe0mm3CGgUd(R_ZM>NBV=LM*%k#pV_[tjX[n)dqInWPs.dC
+%)EA%sQ=IG>#R2p4BOi6[nYl?+q[.*<Um,u:5<^21<J)Lc=ak)\Bo2$D+]U(5-5N@#EU<2?X&aBTN0a:TN)DG$\a#oR/5VYo,aQp?
+%!(e;FTNP*#cKJ<;9.-$,8[n)k$6#RK!:P#t0F>oj$K*nA>?NE]`0M$nV5)6ORbCCjF)&hXapCF(@iIF:W+^9!FL!<-0sZJ>"f>dS
+%;T?.)*Ot<K';kpKIBLLKcCR8:*`7788]j);\aRL1MI#dADsikEIP5#*Yte($s1nl;(Z1N23hH!'pc&D;3HBN.+I;#YS%.-lfU*MV
+%3o6Y=4]>d!kghi7Z;02'nQ^r#ghVgU.$KkB\n'j,@,L8%n[+S![3j$Uhoan]1So/1eNkoEMZ=dR,?)EKpR%A*l9a15\"E5Z$t[p6
+%3b3s=p$ANM\tk@R^g7Q<]I9OY0G<#DH+Rjam=X-+;S/:,0_[#F=SsW,R.u8UACqZBF<!n\@4!\:7Sd>pVhS&a3%Z(NZ-P!,4\;:9
+%4G%heIAUQ4Z`I>]E`rt2&Ai2ZPk\Ds"4FOMS<T`5gGi">p:2UrT>aTa^I8i4Xh;X\>d>%s](OdbWL0V>o9(gmA_:WLe7*A'aX,t.
+%a$]Lc-&3Aj]7ih]'5&]$2#3QEcJ%j[PrANa[N)g-ZeoTBJR,)erAfpFq[UPSZf8G0J^QVr5I,_R`cB@qf@&q5idI%.<hAA-a2fPW
+%[n7VsB<mg.>>"/5Bt!--SXuBaV:@hm.VpL)QK*sNG-^JgOQ7YH<Tflt%2K=e:O0KZoQK:5n$B[3`'<jBgMu=bBBRVA+*J,'nB39O
+%,>1B-H.G=q2J1WIOVR$FdW!YJ_eo4f$JAp^Ai]"R3(Sr1#"]/HFN0ZV1qaZ>(92#O:3G>%/0DN9I[3![B5:)0PU1jA,hag1X;HfX
+%lr#U(H]>,#N$CAFNU.MHQhG,7;RSfNWE:S%Yi[rG>in%H>f(n-BhF6j/!%"bOfVfBnLFcBXH'!7*2:GFCsdr2cA,k?B9Mk[L(J?`
+%a/LIjS`CJ,@\=AVikn$j'D%SLBmoMH\h*^DBs"mQJ=)d)X2&-4E=C;Q0d`ogSGJHp:ORg$iDr[1PR1uljQIKDCh7"Nn?h[;c&$F'
+%['#63pVi2N-A3\9GSr])Th+<@fG+'^'<:\,1_AoVBHTaUR'gj:qffkGDXHYUS\7E_QJ*lI('rL;%2^^O\'KG\;LjSHH2F<kC!c(^
+%-Cb4f/1)-o[:E+?"ug=^itK*o0q.l*02[[o/<A@CBs!_uR7q5I@RC0)pjaOHlkg5fN.J;OB^_H@Bh*1f]2Ugp$]VG01Gr9:K15lN
+%B-Y=*9QoRH_MF@$BbMbTO]WplC&)PaI1%T]%LciQ.Q#;Z<5<`)dH<QUqA@P]["8?fSPpb-YLoqEnk.(ucg]]1OtF`"R/32M8(3^&
+%:Sk=/n?MK+62WHt;(1D!,bsA%$1faQ)U"-rG#dI6G&GOZSK">;CbeK-fEu/;7ZAr04`/Q[Ygb*`3HjtN69F9\QM2qiUDT.mEjcuK
+%\cpDkR\Ls3_r3uA?H$%^lJR4eToG5sf/htrLY\+lYAsKJNkn@0W^Yfrgl'*sR:NaN4*L6kiOBpX)`Xpsi@(hi/bjA1;6d=5:%M-7
+%YAIuKbe+^>,HUouorhI;9+ejR[q&\dgWhM-?$8<2ZjAGW0E`XG*ufA5,j2sLgm5:9&U(LTK[pq3+!D_R`qJ5KD/i@Rm):.EZ.#l-
+%YmaPDn<1Y.6@tT\3J>PuDQDekUpA_^@H_.sa2M#)iX5-6;l7(A43j'>mbLY"@[&j;E6\bO83"n%X6q2Gi3JcWf1MRUCr23Ejd@62
+%.T.TJ.+3k*lh@>5m#/f]KQBo0]iu#&SaL(-icHgb&XK/AVXl,=:I0PVP%K8X75b0Wil&Vco;_5b9`RlY!R>GCkmZq&?u2!"B.EM,
+%"D6&4AE-8`[jDat1_%RN?iZRY;0\J8+PO8QMlcQH-\A2C;iAb;EDlLdO_Bs^o;)jopC8?5`>Lu%Pb?D/Sb4_A8"'_XBoIe2!EuFs
+%X<>]jGd]]!+]KJP1B?-"r.*gTW[.ekER<_/+s$to2mcDUQ].dmc(1P$9tL^KQft'Z4(QDFhB=#(^]P$(M,Ig(W[S0d=U^*'F$?Zu
+%VYX92aM*0J(4ut_.!3@K1)gH':cQ`2.fg@4C?V(7$O9L!R06>W)auU,0[\nE+t<u3VpnNeQu``k5toiZME7\c(td_'63!]FIP&C4
+%5\knD0W9NM:=*ck'bDB@g1&L^/i\8?c3de8ba*MnhHhI&1bUi24Y3j$c32'FQXUCLmZ8n4&B,(m$-!<P,BQS!RG8usW8a'cTZC^m
+%C)?'M\stNWg6#Q('L654SRmLd4Jj@:3:!jQ2E;H'j9gH4c3-$s)b%?F4NR)l1*=sYB4eP*nRihsCnFI&$u$+J[c8irh81Ol?O=`,
+%T3-P@j@PYU=h[penN$!%2oJ/L_>Ph>&BAlt6Ph]"lS`lU#mIt/7=GB5Q8fN,S/Y0:T9*8<lm@ck3;*sm67f&&P13?D09/@D+C@7$
+%AJel$0OK42>k@9+*aT+H_LiiL[=VkOC0%%f^m(E*U6DB,KHo#pqIkg`;Tk"9qPDbLTs3YmBI/+dNo"_*1ECK/*f9KgeT%l<:e1p\
+%A.Y<,0W7gA@U*(c0J/766DFgm&nDI<QR6C1j#H7aG`)+.>k_2_i=M@Y^1kGRVk!\4FYT13%,V+XZ%PX,^3$/?#/gqoV>$4#@sV?!
+%&Ogq0<dQ*Di!fuD_Pro`E_P9;?'XfW-cB!;Q'#B2Q'PF5fQcUI^kUn)n`"lR<)ti(MM.>$af,nq4VUt-+0,r$("beX=\DmeJYs2B
+%:Ip=YcL[uEa9X)7RtKl=Z?`J#%Hap@0(Q&U3%P<0:X+0!''gFtmhpF_0&nK\Z(MrZ</P=gq&E4fBWClucm!$:poEAh,rR@613b@c
+%X9*"t=Fb+NNV:"GPRT#ITh7d77V]nDL;59":1@NT]StedQ;iHrKjY*ogM\ml/5j^cNT1&a#dQ0g88P\i-q:9fIZe]@*'B9MN$Uk5
+%(l;Z(Q;Laj@b1s1/Q#blLaBIk4AEYV>#QWC,+`AuR,_rgWJ^mt=[LCnfKG5b:6&WL:NN%UZG\$7.;iRX>=:%2Mbm*/'IKaIeXY)/
+%rU:R$L;3qcmLYd/e1G"`#pa&62t1)ZBaK/gN)0i<%D2A/(P_=(d2_2nFOj^M^m@C@_&"t/G4;oXOH;+mY<kdIk[1Kg]$2PO/JO'h
+%'OnENXR1s/Aj;b!T?pM-@80W:igN8H#k8+f1dh1pE39b&+e5Smo*+b?#ZM^A2Y7tK(5/uYR);o27B[''?NC-B9TSFVfm?I4fYu2I
+%iI`;^6hoRPYd5c5P?-si2R7_s,r,C$YZY^o#hqOho>'cFPVsUQ(R2,aIdD[(KB>lJYp-8T,$'B)(JH%qR:dcb5sjTe^6*E$1B.Z[
+%LZ^\9R0689:)=3a:*6O+oPJ):k$$)-iNga$0N-%k1T"BN:Pk/GeRDEl$regUdR%=k/HfN+l\o94:UJ9Ko;/9oM#S&9)$5=V8erf;
+%9GEp5-SrGp=_6s$5_g!2,q@;Q<MHIg&nNaiUA4k$1Y<KjkZgZII<?0?(HRom@=dAS[ZiMLP)>ZMiN]We$j2ZP=]VE:`iNiX7AFI,
+%q+M6m"o_>-+bmlKQk4RLM%V+@=$b#5j8^'ia>cc:D_f8?UerD1F+2*&LX55s$??*413)]*SD63]/$#<m_bAD9s6hAfZaaj6Q+0p?
+%AK5?)QUi"7$/GuT-k7&Wbts6DPKcpH+$1g)RGf;'m7O,(jt7+GRFNGp@S$uNjA<6:NCZZ";!"XS+cT%0K+d;`WJ;A#q*5PcTqCL)
+%,"^^1k9apaA_1D'(OSiuAA?db-g,j%*;UlnToPn@h"g<JXs]F--?usF,!qAWh++g$'T`[NLJ-,",q'kXn?OaU0JC\/g&/:Jj/!3,
+%*NA2NM&nE<;TA=kVBcojPB?DA3RVCs]`8NNP9/3;"Y(?F2%4&Nlcc_A14X"Lo$!,#TI<HTQ7,CZbMa\+PK6DlL]U3N\qmg!(Lr@s
+%V^b//8gc/V/iZI6k.AjMB3)JSIHC7r"Gsj5I(I2#!R@(sN#AfYULr@7@[)t06V&p.r6WK#o:1NK7#+PE=pr7,E2Rg%"sudfWNdFR
+%VM-5Pc8chJ1ufu1,=8Jb=dDB*WN7?qERY'A2,(R![k[jeO*siU9s.%iS"sip$jS[^R05E.:@2C4['Pm1VI+.o:3if"Z01ndime>[
+%cT"&m:eA\RJ1:u/2#&%U(4[9a5H7!V<N'lVaE0",c?PE3:R6Kq5]<PJS%`s=m*jl\2l=EJR`<YWYE]?2S$]BC]4EA2:1.4pVl[nD
+%U;`fW*2;2aR!6tiEjchj#7)KqJjL,$H^KR<m!p_,b3mUpN?k/aF9W'H&=oNYVT&g,dJ(RC./I?8RF2s!?qnchTM>&R\_"3db30DE
+%3E=?s#"8h)&m6V+5p@huJR6YL`GI;'X/VcPI(GgsSC95>83p%J.`4.jEe.RHNpXDR&k=5GQ8g'+=2@F<Hrpb/Y*o!%*=T%PimR0@
+%(h,4uJ7N.L9*cDRJ-Rl:$T!?RAnP^SKX"!Zp?Es)p5$-A1pg+Z%.:SO=eQpLVG(:4-`)$UQV.11PY(e-nBrNW=VS7l>Xn>7[Vh)n
+%72,W?+IcNFLQ"1C`b94N`_:*/e08l=d5ckI=K-sm#V.K&90..Ie.rXh?q&;`N4CBh6d8%!P>F'_s%5bAVhDB&8nMrUZ"B2_BuTea
+%p9ZZHF%W;Q>TLYV"@s_D$6mQKWD&6cph>TJ-4DmZR5U>X'([B.#1?Ik5*Rp=b`aGX"ho+;VTn$So6J7*/_eU+T!:W*.Z5K4mC40=
+%C%,'$T1Nja!3ekZ+0-7?W(39G1rJoWI*o7FN3O.3S-D!N;2_0jPm1s-+N'?D-CkN[/'Y;PRt^/g`9Ym&_D&@6kUdIT9QFRQQ6MBI
+%0#nTnK-r<<b51%)9F!MqfUPiURoGP1.VY`ls)6_V1WSU_HZS<PS[h<F\a*ju(O(YYgg5$OaddWskCa\*`WoP`.'tPflA7f.A_/-l
+%.?V/=PQ7:LbG18ZA$SJC#J'13<5uT1IYHV0b'(M)rNU3R8n%F&YZMYm`a(c<o7&%Z/a7?-D"cj$6jmB]6s&04aYn,)%aWRjroejf
+%l;t`,rUW8Ls1\9cB!qVkK*B7Qj+,[sdqi#OHfS00rT9f#\PfmND;X9Gek_q$6(QV-n:Wh?U0eA\Nms!iX``Tf/T/RO@;FYB,(4$I
+%?4gp3^/4[r/h-FOPIS^?4)coF2RK<E*G-s\HYh=n7+ll=n(fYhY)jed(.,7P5atNt0ZR**@U%<FH<2=CFkjq95#BoRm9iF%Q0$25
+%Tl@q:2brEWltWatH;,#]mLcoi7lA)s*]rSB'Q#<@lCQ63"Z2E5h8[ViW"louPL%P-E@l:b0jU1BmZAN@h/;Lt^0A_kP+3c]qqhmr
+%3aI,O:)QhQM2o&l'h'hA$UN^KQe$^3?:b\gHs.O;bhre=64NG;4%0Q(>'LK*']uNZeN9!%*H90f8-U@iGU3q9\e_MKOhaXfRt1VD
+%V#p`p$Io:Z>LM(HqYOpAiRG6,,6&;D(])gjUt1nD(_6IN&0F*V?=A9hn_Y2PUF>&d[4Lf?D34p&e>dRR_ila?"D(Gl0XK]*"Yu_m
+%U+ckqU?YR%;.@&=P6YZM:m;7LFOt8i+F\U9O2KHCpfsdp((1G<%<B9D9Y56f(]s/eP(EX)70>^r9qZ=<7U;nsa=fbB^nmV-q-];7
+%"9]'d-3sl.:G@qR5QC0'M[2a#+q-T-LjY#Cnle@/J>c1Ak0D&(5U@s,'Tj)DjAdI'R_Vhf;No$O[7XCdngIDVCPeh9_*j\/XLo+e
+%&0VSk6R7D`$P=8=/6HLPW[JM!,#+:_*9;jO#SA%C&0a(872-'fNTgI+b9f.n7uTg6Hpc3S\9s`79'4OsNjWVMlBe0g(fEcuV2Yj_
+%n<8m)P6H.d:<Bch;FOcU-LgEf/^VDG%X)9^.s7Yc;Jo""p@=eAXCC*,Q2W1CIVh<X2'+78Hc]uq_btL^pL"A[]$1r4A7JfsOF)86
+%hRo`Z0nBeB1%jdX-C'-SqBBLEs4i>LO4k+kPVpOf5(Nm(5n%kkU%9IKW$*l(:#R.%_0)SJ9K5VSl!l-*p:7>rDBE8['.e-/.1?++
+%j[E96M%Pa*Cc7:b\ioqUJu%RK1SFl)a8qG7UUl4T5"KP,cgYg/]$t-D\R!<?[,pR24G3*l64*^/(G(EI<?gl@pY7_+%":]:ZspXf
+%0CQ=/Z*lW!N_p+Q_[458H;'+BcmLg2ou(:8Y(.;.a`YU[fW);5abeb=h5po=muh'aG!(I>Te<eTFWk!j^IRQ[?_e.qWuY!hq!uI?
+%?[]?]D>4#.p;8gj%hH_X>Ir]3J%35SP2E?i[CuEYJ%b^PiVr]&naiq7F-"rTHu]o:bk@RVV7g46KE(]'I,SF5rT\U-5Q,B2qLI]-
+%r!1)%KK;#F@Del:YJu',rk-5Mi@2t^JfXX,Js`03J"]btam\0CPgtcnmopD=K'NAl:uSuqW&oaF:Bo=0f=/fHa45Cc2[$)?*n*Dt
+%SU>\-?T[gUK22^.Q[Bd65V?pH'MIKjmmp@@QR-3JrE[uTK_<q"0OU?RJ[rXRZCg\G:(+6ToI,2hTg'X:9Hu[tpU%U;1Y-l6_!JtO
+%oajjIiHZp/^`al'=+G$J+r@'Z^(W7h1gR'R/lmU)JX>Zj$B7@)BC6iQTR>'H1`]%UXh7T_n7=Jj(fE@&9rXF8-8-NHa\':5JRBg9
+%I[B]S%7@)g:=\Bk]usUf0B&%M@0YW+E.V,dP>Y35L."R_.TM\pj>@umTj\MQ,Jq@mNc;q'[18,W(/DR3BiE]cgI"&2DFnr6nCfJ.
+%A4qtCaGL=9NXi0/q\kM^C4YJ5r^gLs^(&[OUc3`q$<P\MBZtIX:Z+WP;a3.ufac[!geul?VGLs%mC&du0X!@1iu<=:`,43DD3"57
+%@s6>3Vo+D=kUs(5TE>p*JAB8A.#T>NT`[Nr\JnfS64Z@qh+0fhA#R53%?Dn@+S;&i]bqtN/-DRN"g9!S#ji>`%bl]q2p=PFhuJ.*
+%J:MLc8M18OHp8qJ`_V'`%#O<^#bDL@&AUG.TE(a?h*-BV!.IGmA,^f`KK0VeRuZ6BNY7)aGQ&Vc#%tZAoniN3jrV)lof,Wk:!;sd
+%T[NM3U4YNMN7P6\n1C>Uf20X-?Ak36+U6,>H*h/=)4GFlgUh"G8(:qrCRZ*1;.m*LqYRG`-QE0@04AlKJc^2Eb522U#"lfp%kLf_
+%?Y136635F>P5,G!!9IgEF9=-R\GYlTE%nR((nf/F_k(7o(Jl'sKHW%&f2&c,&2<St&g%92i,[4(NEK'q%/B\($"2C`4!UiN"Ukhd
+%bs<`d[,OK*A1.TEqb__*"ub0rRJDEeDbF?pgW4pDRn&P6RWVDj,ZH8i)&Y0aW.d>80\>M2idlpF@(PQ0T?/`74f1="cKLMPQ]4.u
+%O=)W6E`G%\DsHJ:8%>N,n>+3GLs5M]:#N`$(dG$c&2Q3<=r'4a3/F\\E:+uqP*6Z3[$7gd6W-q,<E4<jH"bQQi8B&D(rh$aH"9d)
+%AU<30/9tO4l%VT*%A7"WmYR\@6W?c7&\)YCl0'Jbk\o5fh^[`fDKt$fc,V2p$HL7a9::`;Sd'ktOq)=3(U^0d7//o/]Op)sZCm\g
+%S,ejL2,+Ac-bP]09"D)TcRUPi@!-/'GW&%WH+63c5]R@ZHHGM$%jgl'M7i<QklCitDbR5,3DW5Qpo.poRK`Wi*4g7(TWJ3,\QPF2
+%GQWI*Sf#'nPuoB*n$p?51AQ<!BMY[.IaGZi;D`Z=-2K$7J!Gre_0:0/jqS69r%+25f(_Ti<[`f#I4"IDgJmd<-pB.E0,;J"9O%3*
+%)G'G+*c*6'?jb5Gapark"m@1)D^(/OjB'MW6%4C>K+Ym4l\'7XSkeP\:Rc*r@1J_YR$BZYe9>?@':P^hj&[q;ND6d-aqMO%95GQr
+%np<(tH%I3:WlLkJ*V_a>"!qJf(6/o%%?H*(AG)/L]gTjBL%lCETKRt9EAp!1)Z(SfJ_frM@Fhn1;8C''2I].ld=s[jNR.ks9YX(3
+%+jdPYC>]REZZR8%UQ"XM*&+VV\HN+#P16E48VP!]kk,L[kOHWCn0H8W%lY_O(bkS#:'cF/)t@4t:a-:S<X#far1j\;:Kij"l'L>\
+%EOegb&_KWE"b(G>Ta$QX=s-@hGLUWAPh-MTKCd?"nebtmAjg^kHndlO5.!GFU!le$9jQN"6#t,k#?2Gc.N_i-3$;8Y!k.]7(6e7o
+%WZpX>0IZuI#^H&;@2?m+Lcs5UfO>>p#!_9Ia.k2aXO7;H<tE=ZWqX;nK'Fe5JLLg?8EhY_"?7doiIj6SjNn)u,eSo+(3EIch2.*V
+%3*tCNp"c6p!0RPpV`KED)]%H8dk(mLJHCF->&R3s1re]Kd\u7BX@Z3$Y"+!DQH]D3#,oS\!RGt2C>$^O"JF7rJ5b;J_qYk8a*n:B
+%\<d8rTPa`dLTnMo6^9,0LsQ.>9#'FI<iLSYqVfWJrN@aIBB>I3/Sqt*1k"E)iYN+gr\KR%ocb>SBE['X!N9Ar:)2,kW5uX+'S],c
+%&ZT`rNNWAh.Zc's$D8j5YM=no!Z59"U"p<@bk3L'St+t0&,M,?'?E?*Gn0BtjL$dj7C4r2F@Wn'rL3Wc30D6hHA:nGPC/a>*Jg05
+%FWc)Nh9Yj;HtFWRCbW[g3JmmX1r*UPCA^4ufKd+a<:\qW(7')@pl9S"](\.f0Pk^ALu-)";GBcL*i@Y%l-KaM#Q$TM2DE`S_q?2`
+%N6ncI[tCP;?8Z,";ZI=hn\_n7,OFjYaqje&7Yo,K_h[eME`p^k9Z)9S6+n<R%4"N]B0[S*k/k'/33AktqZq9KenM>le%r1t!hbRL
+%CC22'Q%l[tk2VuZ'Jg9U5YV:GZ_?Z4.)b(n`+1PX!N^GGUPWJ4!7m\K/$#7FCWIkBMub%ZAc;^"&8[Ke6c499>in'B#j^;ch\/LM
+%I-H&h$m]j4D/7ks*glsa/V=n7LE#0U$']b-ZNNl&_&8o!S'QUC3,?71V?8rdK2k`_#4ct.EYBksIL;<E2\Wje?Il+dl6289(=BtL
+%j$ZuLp^a*n$$S@4n?Hgt;9p1LiP))[492,Y%gm]]B*W)LRWb@!<@ND:*8OT3IT+M*\-[fm9L`IlKW?[):g^[;+>9fWC20W2?oh$d
+%+FjrqdL>CQ)"L/Y66IUZJhoGqTt1:`/^Wcd%Q`l#2'F#nL,_R7bP)DfFS(p*T%A,D^8#M\!218MY8KZ;b4cI949Gb0!1c/9VKn7(
+%`*1Y"%=mRZJ=f)?Uo58`ciBL6i..C">VTX&%f(sfYso"EEJd#]EKr6l6Ik#O`'>Nu#bZ.(:^.QH#(SQ&,9C<L(-<@@:X#aa+[Yo3
+%Uh0bi1m\5a)L?PpgO]DcJ-W6;nY(uEh=)cH`IlES6kDo)4JU?S%DuS(1^Z]e+AIZo!$`0rIUl-G4ddS%TdgmR(aeOU*2"t/Z31m9
+%'9Nsuh6pC&6a1(U1HPTN#"^8jj/usQD3PBLs.1!*?Aj\P*^FtsICO3`Hi&0>Zej0R%3mQWUI%)>(N3fCnF4)&6@06Bp'H*np,Xqt
+%iSfF(9>`,toe`rT%q)\1<<*q,Ekq,EHR=MS"?"7XL(PsUi44:P'6h@,\E+sFd$i_]9FlB8inV"a\7Z?^*I&9<RE$b6rf_]5Qa\59
+%L7t"=7$N*1E8P^hN:TNN1'f;k0Nc!.]MA`&\.hSejG@tHmKknGC0I8B[*dLNN`8<#Pd(]d#XjNCgI^4@0"nD7)`'U4Pf+[G?A7>2
+%95-)0cRlE!%Q&\Jjg!SrHuPJuAUR:MZ>e^J;&^oeRP%.H)1r`Un\EVh]5\i!gph2LeRgo8#!Ogp-<'\!g'n,Y[!e#$s1)Q\Z3@+g
+%NDtJ-V*N54_,rjp3RhUX7(E$4QJ<0tWG4a*!;MA'ei+U8"lgOk1*O_%6>7cBJ5?Ir@M>@7XMTB9?j)(-I7#M5[.)[\>X^RUkRO##
+%HJr3L87!V,)N.#M=j`n<LCO<"BaN]B9M79E"f-I;GS^_bXH=BOLAqo#'mbf>PH-^7!k;1Z%7/cDZm/"Z>VNl-&W,1$h(suo34pB`
+%EMOVu4`3&MKUaXhSMH,DLg_^%C>/9JqRYd2"/`lL<$_j0\f_h(N'P=CQ9"LO=:Lr^bb"<_Gro'g[mPIa$[PWD=rXUi-NOhuj.Y^,
+%[SpS+#aH<)155h/%Hec;fHVU5?4dJ;%&A%bqcLndH(+">cNcm`a><tZ6n?8_#[#&>/Lc3f-Hdk+G?H?=cDj?AmWL!"4YN0gcG6=;
+%5kNYc%L^_$.O]S@XZ-fj-3m#EBMBcI4[9SMDus3$a`jD?G(cfsViAb82n4C,M'nEm!8f#c@#kZ#>"]mg`G3#0n&SC\PQ[C[K[]ZP
+%\WiZn<0Ncjd=D?%XF?ZK:BHQ5L+WQR4F+0Ie]'^Ao+dcH$A"St=;?o%bQcjcmPkeoMEi(oO1lXoZ/ZK&W,ij7#[jRAB;t/^fI2b:
+%,-m2qo+4oQL@0$n;H&m9FKi&ieRNG6C_O5*MAAD'/d-'I@RHf=e<=F(_u.]f/^`TB/"X?c\t"dY.G&36q.%[MD[:8kVZmEJX?!A>
+%%MPT@HsL6I@A"@AMed^]9FY!,LGclr$Z>,KFWrr=bL7#ub2il*QA]J\h9:`g3.anm0;>'^bDD,f8.8n^cmpAZ%m5C$hMgKObBWY4
+%CFHb)?ch=u#<d%n7A:WF8VR[HJR9XK&Bt0DZS+h3jB.^1_7p()0Md('BX"."">jer3<,d,jq/I_Y7Q13+KI;u_Tb#De5UL$dkHsk
+%[K5D.1,'EB.e->>3286/WH^XW`l\D%AuKE@NL#:nV87]nQ.uL@E<L6d\?PeMB/YF$rgZNtE7TnhnZ`237_]AqD6X"b0_5c$O)I8g
+%5J)@k[Jp]+.35lqOWe[f!87b&^^u=eD2;>+#Yl7WJ!,b&2Y(@6RMQ8k#%4,E<E9G&@fSuXTDp5hfX[7ESl8M[?2828?1nS])i>Df
+%[QS86lh>>4N9G+H5*.=Jdfcnf_4goP&fR!hciWRcA`Eu*]d=>rUrHe`GopIP]qg$C#ClLMqj;t(#IM)%RNZ7g>%%b_.LW/k_?OH/
+%gB?%p,ug<lhe'g>c=W4Lalg0&KF#pU?,<$G6Tdm2.eN^&6ss4c[G;]QFI1Tm6U<QbiE.Zi?[VjLcj[9FbV4E:hZSJnq83X)WEm7<
+%+D_2$r*ort@9\:;);%si`0pML:B7ac@6j`[\=d0idtEl<6\Xha:u9?0WL6$K4@f$%^)gG3S-K*F'/mhRmd28U^rI.qZR5r-$_Z2!
+%liJiSVoTKe$<F`'*<^inVP)Z4:t"<4M?.>jPX"Z533]2t&_''G4PZJ(O"D2Xc7[bb7L4=a7q#6HU0-<5:j]SZaVNcDH5/s]X>"ET
+%oK_14KY4d_0PX2-'*RG&Q69N<c:6=<@>R1/ef,Pb+<]7K2n%3:Rl&32A:G#O7dFIg[QJsH0`g4#?=PrQF!KuUl%pN)2k;Gs=@*=$
+%&AB9[**kN)1hMiWjd.^8NL97o7K@t)+!A8reqL,-30;krb#<7![\+_"it4q-:I1Lf$dRi$_M*uDIb&)kci@';k(Y&5$-sSXWK5FU
+%^l5j5-5?b'I<e]:(2R3arT5/j[R_OMq:NPi?!DTW?\\222Z>fuJidBN(W&Fs0[/iW6A6#boggSW]sr^uJM!UA?sD^O1Fue90Eq/"
+%88`CJ%Z?4H.9[+KJsRV2$@^<66SP5-3BS_?69a^rS$@n&^26.PQ!On\Tgh!/183b64T9CmDhHuoKD[q-_mITIHmlcGp#A>J*Rlfc
+%Q]bku7g"8k0ZNft!!,KhU2:)g=Q=ISXfY<K'+T-tX:s*.BoM/kFI48T.7JhM#2Fk#3C)6s0a@Rg)iu"ppGuo&:]nNZr`R89*n/;?
+%Qb4NtD:fAqKIo[HQI&3$iDU=P-)KO=38imWTGYDSESrb.64R!mmce3i`o@0[CD'&KnsVH@e]Mm1+Skpi`b/.GUk.RD3=2<g(T)jp
+%0bsRFbZgbGU\jUm#5OT?]a\^@&)(Z066b,#oHhnX7RSU^"aBC#Xq7E!7,Ys0.@WYoA6j^ZQic4%D+H5O2=M8$e)Y+11'fkV0E%8n
+%[h@LEd1Q!Ja,ShE4]tBAO"<Bl*?k#>+BbT1$sDS:5]6a+8G=k7S)F,7'pdd?#tn5+X"RI;5*d>fQ?&Wr.Uc3G0:ssQo/7j8VEjq]
+%SjAYU:d0X7IHY'0r4$$"Q6<:GG=3>#N_-676AH.TB:FMC)m;)klUD8UL*7Pt011%)T8qnNpLi,HOde+^n8rCjPfhH@if=YfmBhSM
+%cZt3X,H6q$Ysldk+d7@@Tlt<T;/h/<WT5`:iP?W-0W:IDkkToHINk'9^e"uM_fD0+X%l`"Te2^Un5bl)^.39$Km`837r'S&:&&6t
+%-k?8>GUeI;g/q*@`UZ8uF9`mdE5N(d^\<mtVG0?Qp`<%__\@JFlXn+6`g*fm4ENbCN`2@BBKAPRfs!1RG`&F;@EjbkA]hdH)%I`"
+%o#8JKFh>*.&`$.NYn9<"\QNE4-QaD_11'6`q8'a\*_*5)9Kp*Y#R]M$*_ANq/9%_F]k)^X]e:c\<Feh*?X/Fj1f#/W\(se?FE&fj
+%r8c;F*WVK>lrmu?,8T92.OL.PRiT+k*p@Z%D\Ecmj$Z'[XF\0C=jtAUL>.0s[l2:uci9(e5sNOb3.Shbq(o>drH]gU3ia]7VDhk,
+%_ijj/*a,32+l:atC=7&dp`h(F+O\Dnb"'Bs3Pk6P?X?lq`ReRFjn9_M[<tb_!Vd'i(DFM<*VUEQhfC:a""Wo0?#Iu!J#Ak+Hs-$d
+%GI\;JB-FX(V$&c8a]lSY'J:^TMeGl(+e/WgHYj>sbXAX@=m,-%@uVTY?Y;74Q'G."s4LY&/53hslsaP'^OmQ\I,30D=dTE%b>91&
+%P06Z,JD]d)e.JZ[V@5``1i_el*TD+.r%0s\L_>f;$>5<gkGV+'I^^+-dM@b=MR,!>%e]c9`FHN;`@mRZDg`Su2BtF5C%//e%^#IE
+%8m>q#(u1tH9obEVb.&HQ,+asYCM0f)`\h%m0-O;&7DTRN/(IjH%4,?AlV(S*gJT;$hA?,#r!#=br^sErZ`8Q*7oM$Z@.<]$#ZD;a
+%T)#==&Zq5]#fUcU`jb_<9hD+*%%F]U0UaLH(s;!72M4Y4+`"raI-*4*FZ3&#Bu#0Tl>8S29GC?DAq]&fE;19p0NSGZ-_E,/1VfIa
+%0TX[[9qm76!Oq[S_8L;4`=)&3fkHCE4X"P^K?Js+bSr*i,I2!7)!>dhnG(@rn%TFm/kV$X&6rh3N>D_7@q<`L9`eUB<rJ:O#P=hi
+%-(_pQ%5'Rea.0BE#4p0`,HQf^`\&(,<LMAi`Lc6I2I+)/cXqIt2XP?Zrd2p_>!`]R=lq_#P"]X;D=ur79dR//,7OL[Y2DO\B2h@b
+%j)8Ra(?b$o:RM`d.G5nEo<H52ok7;JQfMWhO:o_la*b,4nTg?.;4AiX8r+Vu'X.89/28A^5*us5To.>+Bo=Y75XtS2A,9uK-WGUD
+%B:`6:jF<OJ.P\&02:Cm7F\E#RdNfkk4jCHAYNbgBGK*jhbpj3u;U0q,<ibPP42eVE'U"CGd:3'(Fp8L/Rg5^+RY&`c%\ILaQ#SDZ
+%T0S>f.2W(`R)/SH=S52qTg92>Z?k?d"REY_8Y\u8,r0=YdDl(2Zoald+asFCJMg7#;FZCJdW)A(K#W]T.Ep77&ST7mPD>C/Aft;1
+%gnd]UT6WhfGG@PChSS*O[gDm!q)e0*nAa2)/B)F-,kr$(+fu81jCY8:jrHQ)!atMAA=YEJkPTVqM>8U'S'W,J;J3:ur$qadm%RD\
+%N[_@G&2ulg!Ej4XM>+!jdPpI%>_YiPj\LDRhJ_)X4k"uR"F?!MIUb4UIE&a<*k*<AT9BN!Q:g%dSUr[LP4`41%81J$2\d^c1a8iV
+%!(./O&'Nhlj2W\p?3'2&4GR\=R?>XUa):NUOh0kq#C&_HD#65EO;:?.e$mW#AJug\bco@'Td6#%[N(E?EqJqTfL*W7Xi^aFParo5
+%*!'Q$"-N%51jI4TI$8feF\DQe%6m-G4^=&&$\9$7hr8@/!uIP"+779B?G.k5i=o7f'A+EuVSTN3'Gl"bqjL!=M)VY=rmoo,\*<ZB
+%O\)aHf@(L&CWo;6O8CrtR;#en3[?*<3?MO\#G,B1G*$4_NA?1g^]`b.h7RWe+_GFDF&3T1UPqeUAJ.pp#tg%167[CPGeJ^p)f?M1
+%]Yq<KkmtPdo%#oZJoEhI22nF$3R>1E:67T8_f.5\Tf="1\$Wj(Qo/Z6*$I+mKo"L\j%!Gi=h(OK_1,7uhIbihF=R:(<qfXlp<8=:
+%_.q#?#:Z41R:g'\Xt#3I"uVq+TpumqBGRMML9i(kVVOXhbl.m<I7U)a,oT#epb&s0g0cN(0=_VD_#U/kT7M'-iqfjZSeo>Ae_5/F
+%;tH)T+R/8r`JSU('Vhpq2-FQ]1/ad(!jf&S>c(7Ea"mj<_Zac+1btm0fg4+nJ$J<V6@MPknuj:cMW_u21,![-WiraWnKKn7\Mt\K
+%2amBI$@"a47nmc((O@=^5V2Rj,W`cbBF"M8<'Mgt+V"^p]?M\>@H!H#iK/oE7CIib]&*t/-Se.25uG4G22gau/Ode1fhYk"f<sBO
+%q(Uo<_s:@h8iY:8p6!Iq,GmeOhGhMV(R&0(nT.0fIm7Z?F.o5::cqi+)u1?`ajH32"7jK260K$XhS<t=DhI!l,s@0>f=#Vc&QN?9
+%aFnql(47`\Lng6/EgBVOFDi"%3V.f@,P4gBkGGJS]*Joamg$nDbj.<&UE8d*A&"IRhV[<q]_$!L*b%HHa^UJ`/ki(gE>3(^G?#/f
+%JE%u#AO0/$hV0%.GJi9LjN#J&m>6g\#LgBg&DE@/9M`$6L+59)8s##!>&'5\l)OT$%n0)\$`;'-2Xfg&;R(G>UkE"X:'g"('>k1Z
+%G.M;c0--!n0Q>PVV+I%D`r:Sq&aor\k'c(L4OLJRb4-)q9?*=.BBVFA];K22.nVZuH'u(_Q1aGBbaI&o45AgMq6s;i!l#TG2BtHK
+%f4@&r1O:]e7MHIN+6iYeK";Ye,+]@k(7eN1FL\LY3sdSP`iE7<ik-ORgq9MG#_`!5%RacA7qlTaOMQF1m0(JD8;[VV5"!,sKVHkr
+%M:]ZEbNZUaR5*?k&]%+2bbU!Y?$3r$fuC7tiZVQ5bt]Tko+@*re"qj6[c_ZP@qQ$%33!QTm!>._+1(lM-Lee?@%UL3Oq\P_8)dZb
+%e+/[`N%>_5PY^/+&Q,Q;8"`9TX(pq!dk?Dh91I!eVJWKJg9d'V'D'SAmG8O\@rW0FUPoO7P=I]9::q[OT2_s2.0dYC"#7so%UYAY
+%-BoTI?si#;i>59ORG"$@Vgb60QFqe..5DZ[TbQn60<<s,j1eP3Gk`\?jR&dh5iH)V0L6X,jJR3hja_Y$lo,ZWdnjMU+pFi69R5YB
+%UQ<Ja_5Jt8ZCZ_jB9mfe]#^B$[fua7s3H%ALgorH\r:BI%r]KAa=;IpWC[$5O=E.g/X(hd&jGV&kc/o`<>BikeWRFp\l:)[KN^6.
+%X@.a-nQ=nA%7Kp-ZFAoF^Jm@$'>XVfh[0L^qI/"0c;Du."Tpn]rkX;nAFnI#9=]8>.IW3e+I%8pH,3TUE,b,UCh&sfA.`V]liNfG
+%UiqgJTP5D.j2GqZStCoL;j)t7"YJ`9N2e8Y>L@5@SP-Po+XINh!hpti-.`;F)2C-qOq95eRuYm+;arcLc.f07qg=IYFQ=?_]EC<p
+%.fXW61rZDMTDA0IDo;R@9`@qI"*;#-WGjQZKpU&p\V2Rf,LOsM5]h%U##>'V(m;R69]Ku\j_VAEa<F+/)#%"\juMjf)?c8J6,Ajc
+%N@I''nM4C@]&2t*)tgrkbWe`44H=Zl"l:)K'dl-'a_1jLeJdoAHH:[;]fA9HR,[/E!,h]am6_ptf:\ORqB!$8Z8$$:p15EHfoC]#
+%#B,fj4+4jAD;7A:Up3FWbQ6N%r,E1W$Q5P*XsA1*f&`<;9=rCb"&PF(g8FqlC(7Tp(dE3lc:,H[%!mbAj#LeMqI@kRFHg;E>Uc\k
+%E50eMroNNcaIf(\^GqH97tt\q#@W^87p,)h%s>.[PW[]8#qR,(r%<=Jk_<!D0rmFU<Z/dQ2WsurCq@/a_p2J8RYG\$A,^%KIF(sC
+%VAciuCI,_Jr,((NjB#b\b5-5!o7-XrPP^KCqj,W`41_`d3_=;IL(FfV[4u?]V6c(4dAG/tmW'*[LQ/OGrAna9m4iE(qUeEsg^#LU
+%>9;1UnTb)gW.3*%ZCTb9RJ1TXgrC7p,Ao^$8p`4dIB]<r1kX:J1iI/D2J_TWS$/;a%NmVLE?6E!6utSI^4_`2Tm'P$nC->+B<aH$
+%#Ks:q\;gIMPTfa7,@s(0BkGlU+iZW;XoeC'BpKb`)#JF@l#FOd%bD3b[&(6fWFjW(Z7EmGI31NElhAc(4OY.YRW>]bV_ftG]A*SX
+%q/l\HU&UXP.qSqD0nsQD[s(#o`9bbtSn+k3ETl3NBOoVLhI+`WL+XYPq"MFBcn;G^/%]XSL7VDZGn-B*ruf'aIQ8K9'XeTLq%\QR
+%rAoJ`d!s8k_'`t[^8cE2s7ZHdY:KWm:T*KG(jDP96D\b,GW+"%35Yd_i__q,Q93JhoVZ9*CZ+N?[%)[XAb]cnXE<F!DH^lEm/IJm
+%B)gukDoe`HF&"\Po\1[B*<Z%]=i;W%".PA_(0$TGb?.:I3i^5Keq9n,(P;M7:6It>p_e?cDo?_T7&\,@<=mBJh8\PP-&D8ek`,Ld
+%qqJ?):@)BC0G+?KFIL7.:!LVC"5#BbcEH77j%f$:AVj_._K(CeP-L400A3MP])Vk?lhra0WfZh!i*C&h(q=lWZI:/e>\'Y#X-HM1
+%)8L+Q5A*f3F2WMSmF'nNI4_.##2p#%dTi72[BcZm?t8;BpGbO4V'pu3";P/+VA!6h39/c?kA$(9":jJ%2S&1GK@gs*ANN&RZA+k/
+%^Yf&Lnt/hq,c]*men"@JgIm*o/`M2G=_4(5etarGj04D^W9*(XZ]9^OEaWNYZ\V%Sk^\JO2aK157pa^]rJ,lia,ZuYh.>?k%7X[t
+%?f1lAo)G!j^a;[m:p"JVQ*DQjeO4LE.p#)Zg]p"%Jf[P.`e\DS\KN8CF;df&,HeE.OLmJFT0jra,).Z,#-`L0Ce(Q2o&)6H`7O=i
+%7iW$!oD02J#:=Af%@6_.B4+R3\`oN2[F3L0LFWUa<6B7?;Yid\'ST)eI1?1D?m^o+/b<0D@2FMe(3Be$OZZt?23Ml-+["T*I"Zt<
+%9*#DqLjZG-W9LN\-.<S/omTQWP78L[/M:9_hT(o8iEb<G$9`02^'7Z'M29!q#m+"<\,G&7DttFhkOSAc-(;^D9WIERQ%;=9\FT1U
+%JJa`/9?83DQ(k/\UVd*A>uLNPLq\uOmQFGK*aH8NU!MZf`DoM@BG)4@SK@QP_tOEmTLGeGbA*qEQB_eca%FrX5f-.e<HspN-1o#s
+%OhY]XVB1(AYUU$*M70hSDIX1$S-b7M*QhW,E_X")0k('+`HO9nd*F!E9!ELjnm'BmO17&$NhL&BEV"i.a(F(GNJuN<?4Dl]e,qA4
+%]34\5Xf88h27+X[k<Hh1@tU0l&APm>CX<_=/1a!K>E$XBj#V36SdJR:%6Pa)iit-d]AA&RO;bSSm#,?g7h"GW]VYLB!M;0ZY$C[K
+%F9&hF\Lp>fJ3MhVO*>sV+@72Fk\Luo1D2Z@;P=8l:TsN2Fu&jo(^$:&o_%Qs`^OPK(*GF.?kNU4T[/OBK**((`kM_d<"+_:mA4]@
+%0ipJEnhh2<$_XgPKI:o$NYs\G:_Fq)r"lY\`3sRnO0E^_W3jVPB6U3F+aY$s"/)]+[k!4!-EHt]h@pag&%e4A:?PY4kEiZ*NGU,e
+%(esb@737>!o'#eqZ[l\$aCKoR1-h8jk#ItqVFTlL0FH)kVc\sa^h[o]cFsKq?pkE`r\HUKPmI27a4D^OjR'1adF-R>b(lp/We$>C
+%:[T6&P6^[V?%3=o+o4WRph37?]H0CN,eHB-9sUd(%.5GKHlH;las-E=/-O69]HiQ)HjdK@9]5(oeeo[B6EC2LhtM51%uhLXE$"Fl
+%+##.p-"[Jr-E##.I-(NcK:Xk]o[c2\jO:cu0g*=\d?NK3O)TTnf.[Eop7VdEl+i)X$J551mlrVc=BkqWZ7K%blrH@uoM4'AGP+3L
+%St*lU#<E?_RDq"Fm.WBO-D@+M+/+t+bC%(;k%ddY0iRE$5r,f:Q@t[`EAO4$g0,cFZ:]DtME+Q<72\?qMT^rL/%b2+iBW>T/,9,_
+%?WE/.Uji\,i1SQum?cFP?"-=*?_m1V,LMF?`Lc)J8g.L\k82kYVeSnIk(dY+@sFejaMKs;)W:lI<?jW;U;H]Wk_ekB0fo/r',1L8
+%^Zk`\YKPIm.YfggY*Y@@5_0PBA')BE"<bQ3.p\o[VK2aW4NC$/Z384.c/"mAptUh')PS:jX)-no)I94!(KimJZI$4NK,3bOOtWiM
+%p`6k35EFkhbK4BNmlKMj.UBoOdLdp<<`[R3(8)eT+mPnpiaTQQFe&?\R!A+M%4\>?q4q_U^-U5^\:,L&ppQ2d9Mn_a,hEL#.#_KW
+%;nH$]h1rZjg;1)ZA5$[#Ma+5Mae5geFa9Pa*nfmtXra4iBtDG=IV+O*%dI9ghK46(].SR"M&<R&?aG(gE6'V+jXF<JWp(YX-#plI
+%0AopU$5bu2>h@$;h_od`Y=2Ku'>I@rX0`P>#KT\qe-R)'!m;Y[mAfN/9e2P#VRq\A;W'I!)91Gq9+]V;Sa56*-=_h#W0*;UEJ6Qf
+%FM]/c`T!hb+Kf2jXlT<A+<Cn@@u/<^6&1bF<g]@uM/L@[M=?\nqjm6q!<o9arJ\oJ7"j)$9>)nc(VuGh>*rseddI88(ELb!n3]N=
+%&RrmU")]NZc32NQ!fJFp@.aqEX88Lu[7@T@#@8@na@X7cbb']\;DkL4_n[A#:)Cl_Ic1=5o64K)_2KstV!dhFPe;7_#Y@H<$Z8M@
+%%qbD+_ub'lZBHFi6PqC#)CI,^g<IN9Dl_5R-Pp_D5uH97GU,uGF(Km"K%l%9AUoCGcKJU(/QO:8-8GZP_;To(BG.'f16R18jutie
+%<qo%DT_#ImijDVNDC@uj3MSjdU`O2WbJliP;VCNWa'i@1B>Ps-:!nq`W*mK9:\*EgY=8UM<GqsmnM_cFIm6;,KFLuodQK/SWn_IZ
+%YC0oVCGm#q,OU%mFEpcX;p7BP2t":0TiGL4$<)K;">S73\\E%Or;f0jTZrL><eCG+,ipqgd]UBN#Z^_nVK8QV70bm_%DM$WfYAd>
+%A0[&AggY`PekSgOTVu6#YB*Pg2Q$V*5]F)$1q)-@*i=6f=@Z#!-c6QM6!9T1&6P)dI!i*JSG8"2q4X*Y^jZb==.>bR/L!-+ndPVc
+%9[!ou3.7O?VE0ZeNO^V-QSM'hk`%M"ghKHs!`hj22aQX]0m("=Gd7Gd$4AY2b:jh^Y]UVF/j%aQ`GXG^U]`S0_.Lm[+CBCmU&)Z+
+%YA3i$,R-Z6jVd2LS-K.Z.RkV)QpuU)OFA,GS$Y6Ua:d)^0k(:-IEp9:UAY_S`U'G"#_A(:DNo4d8TJU6""nY^H0lU&,npL5L!DO-
+%.p]k';nakYVYeU&<.c$)Gp/Z<Q\i>?C#>o4SErnc%tH0Ii$BY<*)/@-/@BphN:dr=:inMtUf')\`YTunL,^[`H,Q;Dk/LP="IG*0
+%YJm>JDk!gGX])4I`8h\Ckp]'a6kNo4gE<uD3JNp_M]*l@[.d(.73!djXk[o\J7*-MRT#%Vl%R=%FPhq"^eXb(Mcp#CQR@6O9d=*-
+%/3L<3*0MH38MVYrO9f)?Yen:_Dh/5V:kgZP+Y+4`$/@%Sndr4Q&r9qQm>m5VDTuK+.H'-_(iF%",a;>3]8$opdS:K@FCih7C+kXl
+%$\H&M_n_d;eg<u-!hbrR&<(J<>QFU87R^9$Y>HUuFCr51R@'=d))R"lmqPprheK/;<U!I#@d>:-!l+-p(Aq"*&h<I5&QbN@Y&.GK
+%nM9&^K?NQOWLD*ZL_&`-'>K9#bYXXJ^d)?e;&;f3,dK6`fcnZk085!EOc&7mE`0t)O#%_jft;C53,;AG/cF$L'PCEBA0Oi<YUW%!
+%J6=1H)>TgWEE*$+-8nXb@+GBJSFlQI`d.rt#j=t+S8:mQE5I'3XtIF[Z&4*"cUT1`1!/cPOCpLT,`>sOPnMO2!&1>o6u?A1hn`D<
+%(n+aH?M0t>LiS#XQ5C\`rlYWkfbIs1\4?5JB,A^p9eKNh,LY5=NsD:%E?FPoP"LTf\+T$l[1?/t!_'Y-o9:_P>3miBUUoMTUff+D
+%M:.X'$X!"LES1rNJ=\+^3Rk"q:U?Go.E+'4&jU1u1F53*m^$faJZZX$p=[>H"2U%t.HkOFW@Kisb7G$NT3ksmH;K(A9_8IO*_T/L
+%(?#UoQ"ojLCuEI%V'Cn_IQQ@Q2RM37X7U4dAlt#r>g_F5HOD*uJh?MC.Od!bQDZZ;5pARJA(ZmbY].T)!Td^0aQ;GC5l]lO":!Ea
+%m_'>e+QIF@mq=*$;M^R,8e;*IA?rLSaKpsd7n_@f/PW$>8ntF]ZHK_-<)(@DKK*KtR+''?.K-L@;!M=EArK=B&$@qAU(ha+4tZFC
+%YC`!=p#^-T/jAlk(6`h=a6ctsrC2)V=hIK6G#)ohfo505(c4#TC`tCYpm?3gF0%'NOegk9lL?/.'>=;kpBPQ]_\sob#[[Z:^7YAh
+%rZ<'GAn!NR@VleN+Q,#K>Bk)>Qj6h4H/=P)>Rl=.R%U1=WP0#oY<L2'(*$9'[7uJ&9QC(]M1DW-\a=jR;6]`'1Ml/]!-GL4/0l8U
+%>*-`>I$]2"dEZPr&H,oHR]-%;j;#2)VH@7tD3J74T@Y6\N2DY\B&,X?C^*u#kUu`L\en'cf3@DZ@n<-$8b:GMY4@b9B1[*;.++]Z
+%(g*^?JJ82YWoa4CODJ_K\pPZa>o\k+#=ZV1LQ2<S^/KHE1cY`2'Nqq;LnRuI#"JiWZlVo*fHg0TOXVeq7216=Q,Srl>=/JKU)l#[
+%o-Bu(oI4p<4%To4"ClrHe5@>@b6B1X**e*Bf9:h=Wig,8EmdN4SfUmYGt*@J..M;/Zt!"B%KfF_3f]P/,#e."3MJpm09>RA'Vc,#
+%A[[I4Xbe/B(4M/pWp\r+hOosY=@">;eYF8D&U,$b<^JJlg#n@U[@;`Ka_"!r/ul$Anktno)JJ4*PL*1soCHEUX%ml.R4KW;5YhjV
+%"/iHV\jY@@kfpJM[>U$0rY72kcb[=h010)Y\F1KJ>M+c"/a5>(`D!oAhPTV\<g#3JgUM5X0&_,b2,/nJ.:W2o#,`WP$ibNU@fSL)
+%-"^`^B9k"+odTQLROZMFS6IT#d.RL!I4T5;aP#MV"f9'mojJe*n[Wb[eK-0VA@]q)\DLnV+^$'CVS][Yp+i8F/,LVBq`I8U<Ac:J
+%^pdea`"H3`f54#\7s2GM4e1X9?>YjKKn'GZQGF17[WWY2:uak<Egb=tp0t5Agr_WE2Zm3tZ,O]1RSl_M<a)@MBI!<Gh.g,?"@bsK
+%h/h@i;nnQA>&'=7=*PQ5S(j7jjPo5&D_XLqCbR@7JDH^JWi^nn4*M+g!a)Zl%hJb:nZ`56NM2W\.h*%0`4*^r:X\(n@kb&m(_LNe
+%MGffIcr#B*"e%>L#,=ck%Ftt2!X2Pg$k_M07(?9]q&]:2<,P,d[hBLC:/)7bdgetePjsp+'hFZb>?R"n[#dfl-,Fo:<>\Tj,;3aj
+%:2IA]ZkPk9lu<`K<tTBWg1Z;UQC6`K.5jQ/H6<ZOg'D.Je4Hp>TcfDj+dcfK1Wum,gP@g"4!30)fEPm7`5;?lo%TB[[+2T6;-D0Q
+%>;`a[+qfNuLY-X*+Ghukd6MMW)DDl7co0QFZ$Q5SOH+1s6Xid[&/Y)W!aUY[@VUK0U+Np7_cAnQZDCa1\`C.C&K?As+utY3=tmHI
+%GugCi]fS&sT*'P->/aFa/gnc_Kp<@t<tUugpe4(LW,W<4ZAVTZgK^PnWmf]//O30pMr"2,j=!c)K/JOuD2>bA[,>=SL6`gn$bHH>
+%@QSQW6)t,r]7tb_dRIHPN/'Q05U/XNb>P\#"ZD!R'5,h)ki\Vrk"$q9fH+"8YZ@QU8GH+qE+pQE(:Iu'5*LD]p_OMjFatjm`&kn9
+%Q^tK8k"5a1D3qE2,T<+r>p4&GZH3&4h#]W,aQ]e+e#OeVP\*uTTXeZ/(/Oh1&=[,1((Mtr#?kM6Pa*dOr\EcJa\GB;1(D"K0,2up
+%Zk%;,MY#>d$aZ^q+b+a+JA%>MQ@rncZ"p(.1$(H3LFuL.jLDRA3_eGnb=,M]MU;`D])6@rG`fpg;nndag`4J36TV3&S!iTt[US4i
+%;!QOWXt_[c<(a';%Jb/+&ruT6C8Bb=_HPLp.#9_&&pT$3>0TeE[Us$WKfPJ4,cde*/l!8"<cR-9V8\8lHHX>$9'6Xu0^-5(gSSdg
+%J5`d.29S/j,eK0."=b$]=L5%;8u1GMN5[,IZQa''4AaJF:Z\:AK79;?XO:*:_.2SB=`'(g0\qX#(H2e\,esuD<`D39hOqi)4s]dA
+%4LO-Q#?Rm!77)%Y*`3Jj$I>rfC'kY-gm3>,'a1t>&(W:rDU.mba8cHfZdC'81G5M+l'*$h%d-dW.m3Bo,CZ1KX<Q+^d0jYi>=t/O
+%eBC.8!(ZJ63Z:^:$&MIKG"bPjG9skE;qh_,>)"$Ejj[A:J/OAUA59C/-YX>Hd^%6"/!ben+TUecM>N\Y[L/nu6!'?9;_51BlL3b>
+%i&I3D4Ci(IS>`g9%7*;@kC?ne!3>/k\MD<1;GfEH3t*!&nmO,$1i4[9bTO5tl%5NaARocF-i'Cq(:BjW70pV)<1Y3;M'=)_Gas65
+%53<b"4^`DLLZ1FgM69boR[&SB_ZCKkq?ldVkRJqPgj+7n4/h:DYf?9_`30i"<SSpOKX>bO.:`c^ZpOa,#KSY$'f`mC.3A*=fATFg
+%Pj@"g^kL2Td9l&^^p-9A'&M`V-ZIu%`[;:GVtqXI4?WH$E]>?0i,?K$E.OZCSAZ:>8#f=NmDQKX7j;'m@ZnNDLC#,tU6a<\J7#56
+%5h=T_HS,?W@\D9"79WF5:6m=2:8eqDhuM\138cM+^`#q(2A<M#fN_8NEl2dWVqErk&=S<BL$q>2&T0"Q\HADmGo%d'_>NuZ`DHI8
+%Olpa$2FP<\W*+&MN?\.KQ^0(-/<?tB<V%4$Mp,;u4[[FY@3cPFE;5!0Qcc4aV1+"-Co#%>Y`"PWa"hCF5gI1ni_;Gf@5t]Xj=_l@
+%Ig(C*Q,c/!-`_EG1dNhB_+=4QSP#i52oJVP8L<%:p=es)_JDkU;2fUAFA"3?lC3h8^Wf_D/e"e&$BRN'PQdJQnl":hX/R(<:]Asl
+%a_bsi5ThjLPu2$3LDo?U;cM,U.[L8aIoQ5FirOAX2(+V2S)ZuMB#l8Ta<o[/oK],'-psm;!f@2QMBt\Pr!:YTAEAC)r]L2toui:/
+%61^XC?%Q0a`sq[>ckBj7d<(.V:Y$PKUa*4J8W/!8:P"n71uVcgUBAnE$:>9m(n@o83-S#:`%ur2_pO$%0Fmc)':NZ'^%Rgg+A+]3
+%5c!M"0PosRJes.@%[6El5)?d?h1/%(Nac21k@oIUWN0I\A&u(^E<'S`%c;*&(3c[oVs(Hp\1-[2;gj6a4gN<,o,s'JN&q(db&r*e
+%#"Sf*`7,GV":4`:15`:Ub*_]m2u@(M&lJ!gll")nEl4Uh#oH9:%Tcl<\hMdUdqET!)f.MM@7F*K(p/VXpRK?b%1a,bc!jQI"lSi#
+%D$-8fDUbbV(75Rc(mkqmNc%P6/=-iA:U1FVD)149REM;l:Z2f%_A^-Wm1aOP1u/u2M52U,;oP5l44rAd*K)g(l6IQ<f%CI)`t^ap
+%aPrlU/L\7r#&@I_9OrmV$KU)JZLlCYpoe^@ckZ.>]t:od%7dLCS5HM?0D$KM$+$#:J?b0M_k(0Xe/;IL7sJMmq\R?goW/IVAB;0'
+%*:u8;1J.M"XXePMQ`>Bj)K@U+j[<7Hm]q=D\Jh#u<0t4rHk&XZUZe-bp>^q/]h]$Kc#$=V:X@Dh[,m[a`d%a^'UFA=O.D-CY?Qa'
+%3dGGg!B`3@:4hL4[iHd+&nRsYbe\>)JY9SJjeAW>i&m3fXns)N/-%pZX#LRDVS$tb%LuVOpEnTAdFlEdhr<cM-_-m=KJ6uID4Zoe
+%NCdm1lI,m>P$M&#7+>sZ\a:_,e"Va>Ft9j3l[[V-<Qf02E*#he3R962YL[P=\-Xi.cU:;,2H)JB&Q6!<q=]UlP,KsP$Qq:oq]biM
+%9Aff??cXsD,ZgnT8q@Q@/dOcV2V]nJ:#Sb`:8":nVfT\:']EbV[tucpgj4u@4WBDFf$*^OHVr0/L+I44LT?%F)TM6].tLVnfu).`
+%fGmJC,pFjq_:)(YNcd65,d!GX50ma`jk<ZPXRD)7ZRnI&0jOLtYT1s&hA'RD6Th'5RdAhh#ii+j7p_7k(\^'(.Sg_j9nGZe)./b&
+%HekRZc,>%6hK@u?H$j'gA3&).VKkkUF;,\15-p6.#+&mpoea)%H5.utlcH67_uRs]jaA1ik.48Q#_uR$D*#6i3;L?4dPIpad**ab
+%U[te-[2bhJMW(9']j>>"C=e(X1VZ)ns#))+eQP*0Ys2_6g8t^ba*h$"2u`4r;H1jrFqa!dKG8^T/ilKb:f-u*G9DHrF.l_r3r2^K
+%,_;a0XuT#]T4bIh.NE-mZYE<k[]T6ACdp0<A0k#k>6#bpc)WVJjnRl9^i2aXdK%H&8N#:.W7=")n1m5ZII<csCg+KSPI1kS%[Sm9
+%7Q:CP)4e\WCo`8L,3aXT!oZ(+9n@,Sc`e^a%9+rbIB$0d>2bMg4)$^BGrX^-C5$Is,-pJ[[`R/.O's7Omb-If'OJ&Rj3Cu;3Ha\`
+%5B1J,&oBCo."73TD5N8V$^K$QM[&i(?O*_W3\M&_/;_`9ZlMU\?l(C+q&#)ghlt$'((0=E_bhQe/"CZ7>Mr]>d('J#p"L][*%O_h
+%I#>rb]?S@0DQ6+ACik;rh;G.<$s-(U6"1SW"g:N0FJgj5mUA%;LAs/KL=;gGf]pLn<9'j:ZP<:ZY:V_th'EDq.%Bt/>OMn2!_hA$
+%i%rTjh57B)CDhlq:J\!i@,`PkeB6J\/M.LEH,Xh1rNL"`,16p=TrtAb&`T#dF!`+>qN,KL:/JuJFB!5Aq?Hp;s4\e;Ho3IjZ.(OB
+%].kB0]9(=8W2U3K/("f7g(l$8?J%7*:t-T\KpkoM!s%\b*LES=8iWL2`k:sumoMX2MI5-/E?V\.>/Tj5OT7aJ#u:tJJpkFHokAR^
+%oM"F@6ilT[#7S1>YrB8%*en*):BS7(WcdnF_U7XW\0?1<E(L+c6d?3X)0ZGE(J-<NW\3=>lQRh\q*a;tg?-L7`9,IUf2`\Tl.r+"
+%O"DT%4lKugX=Z7T^tW%ZfiUZLg!H>P5;8hNl"9c\&ouY!#H&$;/NiI[V=:rhV/W&Zs7c.(VM7l?[:\,tK95Gr1g;WUWADC2%'a8V
+%GV%NS9K5DD(7+41_]r.aE$^eZIqNC?c%d"H_e;Y+Nr[R`:PpC?`B"go0EnYfi[J(BQPR&@2anXJ*oZYLX@&I<KAXMO:X;"oqD?"B
+%F;ktM)Ue]>j@mXcqF<.VEgo*g2,4*E*Eus=)-%CuYn1^rSu>85i>Wp+SlN#*Y4UHDLAo'^6-ucNfc"=ADCSnGWb0d?[M9,6otWHh
+%["!2).VmStA51>":C<0J%',p8h58emrgVf2H'siM]"L?qd7l2\#_7.YPaehe0;\o:;-@^WdghKgo3#O*?tR[k!6gB2aTEZZa1YuH
+%``J[(>=m[+^iIO"E0LDKC5`EG(_uP1.GEs%L=Z,nWt&#$a3T9YN&oc)"\m!!m<4-obI!Q6CmK.:NWkc2ZM/Pf^!59)Q@W$E^B>Ya
+%)]-&XBsFXK=TR;0B[$os(Sm0)])AeNaI_[*k6S_&=ntS]O41\2=f=#lI&!X4A=3Q9M3?tN%g($57$19S%<b%Z$LLhA.0=],T5@n@
+%$Looqhr.031.\D`;[J:=`7?4*=q%*3%I\ZR/>t%hi@d:+:$ld*#f*,?_CsCEP,:u@SPA_"S+q%*bcSYo/di:T^M@PH8SYcMFnYhp
+%S]$7Ng38?X,Rj$X'O@F`$OSpJ0&/>7K%8)`]\T\d[o/mO]^.oRB:G6'1O^Z?mm.5Tl!K4'h/Mlpa#0OSJEb)N6I;G]4Jl$Ndn6f!
+%J9V@p*+%G:?\_Z)-)A#Hr/?*Ch,>TDb97BpiVfp%8O*<./(CdeG%AL5+6qOQD(eL:+5$E^@E6>:j;^M/V;$cV&gX$iWfEDtOtMtj
+%XO0M'V"dX4G4@E.cNlTc0!7Y+,Nj%$1i.^s75%*B/HfFh7P+CfLR$_.$+K"X!XEN,ZI',r)ibbg&Q-5,J3pJI'$+oH;:,:0<=+U6
+%4;[o7/;^092[(D-]*,kUlc*#-n\*.T%Q>lM=4D5@I7!@ElY,2We6ML@fH8E()ZTm25/]kg&Nc:T1o[AtTdd"WV:gp<E"OuT?5SQ0
+%,^=<-^sc,`Ef##HZ[mA2=tBZ()Y+kBF[iL91,N`6/6-?%cH$'UoPRE0!oPM[g(+Su&3P")bKA(;).U\>`f7/9AMt<Mr[MEN'g4PW
+%,,-?@9LdIH5fTEc)+P&6+FruPS$jYDB55shjm&m>3>F:*=8F.KH8fRgn`rM;$L*T0XPD8sD\J/crLjpUG9[J0n.=Lf!V;.".83#]
+%Ba/r-:*.?`\3>AnZD?[lZ8*Q?!9>$YA)62jYV)%!kTL5t``J$G)<dD$`X"T?B(0*AgO^uZ73:.I%X8h6lAcbPBA1sr_soP"F`AM^
+%*6sj1ie`F-D9PX/Ki`H1n[>##Y3rAam;Ai2=\1^\,9cB<SF?NuBe%ku?*^PnKG#/=#>F)W&VJLa^M@DDh[u9'paf(k*JAbV!R7*&
+%ra>?;2l["a/MDZg@6&A4#^3^QKLEt8OChkMS&]0rQ<.l"9G1[A(R#I="KlA(O]$RP!qAQk;84[cgNiL\dGnr9\!]n)c*:/344Vb>
+%)5s\GU.GLA!3Hs+ZOK;BbL/[)Z_<W\].?GV#I"jcY[7.<Dpb,1,nE3gC`?`[_WWXg(aD-^:/<FAqB5)l/=m1;M4#([#9`%$B^9\)
+%`6Y7*Q$<^q<W_=bTFku*dc0'uL=b0H_%[30d11Etb=4-`Rs9mV>"uOdS!H8;0OHmB/VAn-Urepe9FteH1X"a_+%dSp*6ZWA+**]^
+%>5&nfC#^_or>&[&))2k\:BCHeQ'iG,65EQNMi3;+D7ig-ZY`>^ZM9j!FY[s]UmV7F<8#aL,QRHJp3aM*[,-mI_Q<kBe'gj+F.h7s
+%j27rf2D1c1W67O.]t6mgJ/c#=,s#0!Rf"eeTtlI(@hsDHF7j^1C##T?3K+naED,1-@LG[\]XB%g9^;I4Kn\?Kj)(Z$Kb9%h8Gl.K
+%<B3)&4$KbXN0nX:fO1K_A(=>6,Mj2XA6:abMBh>!UUQZ>m>Ak2l2pcc5qtroL+BV2H35LMU^5,9;!Gq.N/0%L5(hgE+[p3Bn5^2a
+%@!=OeNSAU<KlQ-'TXpu>2>dJ#@"JDt3@[FgFnnRYq3fP6<D1_.)kUtNqQ]RU-"cgN`IeOt+XS$R:R`a"TO;uV.s4)bF-"4*]O*"3
+%RnUeB4BdWRbA:@T#]Q4V)Z[(nX->=Ii.9O[L_m(&)h<Aa+0Kr2Q<_]&Y*XVPbVBhLQM!2:%UkkhJ8>cijH`N19lLY_m9&PAgP)Qo
+%OpT_8BZ&77NGhM40"!#-<.Nn/Q?,sRSf>f4i`3IaH<C'HoYJ6MoJYAp0l^34R_clE/SF1#$`/hO+-jdY5SG9L^4g4p>t39`2%6r%
+%cq.;q`.hij'S_UN\CGa?EJouZFELen%6cFtI4%bC0_nP-11bj1SLei2^,+i6_M^c9)KoYs-s[,rG"68o8kqCQW/9P0L:nJght+*t
+%@&ZOd&;*\LhumkPr%"+mO@Uo]iDaIl4:iG1]0fLB6K!!][K=(Y+%8<ol%jg/!?feuS&SO08q"4N&>HHe*dOk5%:49h70c+Y[56P#
+%fJF>8D,]l,o,[FUUL.t:_3U#mXSZAYW*-P'&j!]SINg?F@._o;Dc=*"Lqbhp.YDQ).-k'4A&>DKcZd`c@pUNH6h8'dbOM]u/]e6@
+%$\#NN?e7N'PQ.Gu!tlt^;F[i6p*7kpRoIPW]`.mp(Xj^79X);CV_hG"1IEk<8DkEf<S21]"!6CDe1572fQY\A3=;KiJprXBfZ=]5
+%BpWZ;&ZK%&Wu$Air)BbcmNnZ^<'rV<QB!'LF:NJgn&mUpS`c<(@)OmE`?!)uFj&QWK,b4r=(.TdScC^@>:@*%>4fudhe#[+"pG9:
+%[2/0Ba[.C]F7@ct`SAfC.okEp`@GT1+M:(f46Znm*<G^V*&5u^$1SbSnPkq9=:"/VWE+22Ln`M<G99k5D>AsDGgM5&(qnF1I<AWp
+%l"9#U-'@s>l.Z=heb7YN<92I4'f9E*[-*9MXt')G'9SW3'Wm([VE%c28ErVEW2Y<4"<)Ar5,T`!.(b]Pf>Y-`i>.et=]C`n-;.U@
+%lR"EcJUX##$&]__d<&^*BQB43Ih(s//H#)Zl)QA41`.%$@OFLpLNS7a13Urb;oQ)#.>4T')KBEZc"2g8Y99(pMS4`Z,%-rbeus't
+%5\qq-f!U*P5jBTBZQnP*m.Zidi(K,h3LohcSV$Hpi"',B[@8$%3R"sX8;]Xi*6WBCK5$g[Bh_VEK=iOK?.d2t8^4;kiiY%41E"r1
+%)(6B>[$eJ].,cFt^CpI31_@WN\AWe^;i<$oLmO7TF,u=\*177X[)0GW_\B/0%Nrn,eP,]2EP>$iOpI9d(0NYoYRX+Zb2Khp$j2R%
+%-CB4oGRi179h:l#AZ^ob%DNTo8KWb!]Md6B`fV^pN!&+%))DpUIu4.QK)[TdBdghZ"Js^F4=k+^4]j\+]9NoA7f#"Z8D;Rh:(RJ[
+%%[VH`@qUU+;Wj^;@$U!>r*`So2X6/n+K6J.M7a>/`@P:Z@UF*uNd7rC$!iJGS2QNOlfZ$,3AdZ'^5UQ@`]jO5fZ<9]*D*WY"=g[#
+%`]UqAK706:PCR4VT,Q1q@3t<8d(0<@+5;[1TPX0KA0ps0raij$i<K)HV.TnI;A)4M'V22hFjn)PWs+@30+BWB]2c*V+#DGSAPfF[
+%og=?BhDKE$n1_^qoB7e6,(CKtgZ7/;l:%=F0:/**>7++-;HDe'K&[1om4#k"))>Rs[TGR9Dr)8W_[3m<*D"$/;G+$*Z8uTl9NRMB
+%9*HoI.9);gR&Mg&nms,B]8o30rbf,[2L2Q)-pS$;U_Fo'I@4]B[P)BKka@#i(Hh=PFO=o)buRFaYnSuY3hM/)6[>(M#;m'5+]i[W
+%(28J+2iQfPic&i-^6Wa7Qk#TD.OKH`GIbtq*9<HKnm.B[$@dkT;[R[_Ha1)KbEc\Xf3mLubGYSq,VIg><kbY'b!9qBnCM0_M68^7
+%+V]!#Z4\nFItbB$3DYOK%qL]t>(&8>(:5H7o6$b0NfhDpe@fZI?,t9WVR;Pt)ET!03eU1khZ\-'Ca+uL_*lKUq9)=dVS+D(JSGO\
+%3J521_UuQ.5B_rg.[jd=E+s6ElI8Hk,&Z-<[n/T$.H:mj&eDbC_?3;BA6>i"8#bD)Z]'KYE!M,2qMpi2G5/A+IFk7FMl6erRnM``
+%$rO7@7^ErRIC*ok=AmdR,X^M%L7)/<7N4'l%eA:(T&%VXl#`8[NZ^)Q7N<#idS?*=iRb]1UM2&I4-$qUZ278%!R"@IKMOHY]+'&R
+%$m4nL.U0Hr,8l%_%6mP;;9%FEB'CTlI1>me5)P[SS=lR9\BoX<3Kau^8"-C[E?',DAL-iAr8h3VeZrX8&[s?W3)O<mEgGno9Prs&
+%,H=_h3',t<K"Z>57\bs/P)*I'=p!Y&$"-.]pgLR>$u's`ps#C?rV,([DZ^[hfn@*50b:Z^.)<AEY++Ka'E69GbVb(3W6SlodWE?n
+%'GSMLLgc4RUP(ng]$e2I%eCGdf%j/"%gQFO)[@p,q-ff8EotaThJ2>`<a8W+)@Il&/"YOOqDLhHl>#/Vq\!1&((b_$>a99"6-7!M
+%)3Me=kCu'[\ua+c&VQ0eU=M_W?ogkdMcCW>!-mI1<Ah$*2`KM.>EtZsVSb'%b<$g;l$A=2;5Js@!IFcKmsq,N`R[djLu9*M&O)ON
+%&kX7kXMmqhnS:RESI;u,A;C'pk(2bpL^F3=Y+M)t&oW=R\YhIfn,L$&"&AAc"bXI#JOC*7TE%Dc2*1usXi/pr/BDsK2+Y>oUVdm<
+%I2^s=0uVaD6/a8G*/HM("e1D<M8SLeAB@#75EA\YatVbHB``eMF2"m$n[!&r&XG:oU/mV'd?b@:REMMJ*3d<q/3YU71EG+ign5Si
+%1%kQm8qoLRG'"/,CjVY7T0\-/6;Y<-9X2A"QGWC93O;un_o2[r2ld`^L;D-n'JbB:M`G'/jKpcnPRE=>RCYikKED6cBA?1R3@Ddl
+%'%O/%Y[@ss5]u5QF1tfkj(GmcflbsO+G(,(,g&S\mAmW2!+r6rU#\VGW>P,$UfSWJ\g.4+PL9X+_&qN5+o&A1D,,Na*Y&c(i8.4+
+%1E:!KAZlP,;1Gle(f\Ag&_n+Y]BkhTdCHAOK4ATb]Mg.+;hD=1R,:^F^lBo+Y\10o_R"R-*!WMXC6Jdhb$AI0b!4T)D!siF&5-HA
+%D%W*>Mam6i>]JUG$Kd=CLsAr]('0+2/nsR'k9Eo\OY]8<E$8p*VIOc7'<hGNT#)8j!XM5DHVVOs$@b<"G/5ddV+PkR;^\J@b(k!'
+%G'>k.Y@14SB#;)cH$@VHMVSig]%`Inbc1`PiWLLVccR]&;^\K1Q$=Hloe@\ok\ZJ)bTJ%'a:+_S!H@_VN"at)rm?J;^95S.MIGt^
+%X#oj!:'/+T6V3L<oA;,O2BefqlHR4X-taq'Lg0`'-g2To0EDiP&r[%p+4DU^o$AS+9Z8l=rrSn\>+<`>2eB_.1qH"0+?t%R6^,Z0
+%MUF(r7d"Fij\_RCTu7="a!)cMS3hOVnF+8c!o<s'.LH_>U"ee^G-O2V$<[feDA5PfDA?([>Fkc@Nadt\o86SIF8%U/Q-RFG?9HQ-
+%dPsTGNL2NW,p`@fA#BB[,\DI#,$19@X4[=RaFM\Kd+6-mq-Qp-Q2400^!1%FDR9*?::$oL#=lYZ;Y\Yhmnls<:gW3iZD_qKP/qff
+%?'cqu)`_4]!psOs+<3(pV/QJYM\uX+#bo@9$m]%(Q%/ouil7?Q`kmqhm-I(5P[^WiU\S;nLhVi3KW(E0IeECp;1.#O,(G7pbdto`
+%rN!(QS%o7Q38:AU[Od#65o0ru&dTUK=b`G$FI`=pArqNDk+B.dmZVX[^n9#I71mF8F1^U3fcpT%J6SMe!EauOM"Dp&d9Nb"'F)4]
+%Ui\?l#<]pq9p#s)n7q$$juF]iSOm@TT+Y4U<5:-L,\9^\%V$)pLIcllpeO#-/4#A(Q4lM(:e4"FR.P$+p_phfIQ"!9'_$%2@9JSA
+%%'uq5mQrpe1b&I)7cGl<HIG%]AL=W+p#=VmV@Y.<T;Dc!MSM?tbQiYGF]FI1'mq?23W?5r:;RLb4KJ3e9irSAISAPO>W+R>:e+fH
+%lj.h\-6l3D%"&;2SOFn6U,&n8/qZ2K@)J^mfa)N@FG..O!3?1-"-1dMVk8RIPY@:/ak2@_,5u7L2S\7PF;jEPG0]4pfB4Hs\S\0:
+%dcPfc`Ffs3m%p8F%<XZRBZ.0k,:R8JcSpmaF;UaA4&`8@-PAJG!#KF^^d6>"e8lA+KF\LQN=)L&+O(A&U00sd;FjUlE6]>&&0!")
+%R/YHnfRf$!!VV+J/l)%h?aKGa+hq<IgM0"K>PloRS3$AM$eWFbH+*-;=&W2=*N[U=Fe:=R^m:E@f9EL"I&LHn$Ll;bV"bX+fc`da
+%2D\s7hs&i;eR,R4kWddu`$Z@F/Ib>Z1#K%bk@Ybi\Xg'-5O6J*bUA(Oe"WYc^nSPnAraG^2)*C38D,N`.lTW<'_1\i;lsq;%05;n
+%AG<5:'6Jn91\bI]I<Hk3)]mTFXj(@E?5=0pb"Hqs)IuSG*-J-#,]&A>.$Lp"TPCRVob3<]*1.o:+CX+"gld>%9k==0Y=&:)TJLcR
+%D)%'EnY.M-@ILMbQ=Umea5V$rGiU_sd?K,;;*9"5Z]LJ%q*nFL-pGKsW9NY@rN)LE$)d![J!eIudmFC`\i0VL)`lL0[c+C.3B^&b
+%f#;(LeM$:"AL-#`^;N;H^o]NoWb`pPVc`35Z<cVaAqu\5NUJ<B>PfOW?C#B8i^utK]j"&K#;3h\<@C/+"fJ@6A4$\_(Pc$LNb:ed
+%Go?H;X?eKhHp5tYR_sm6\u+b3[$p/<V3TQ3.P0L3A/_hsc2C-GPu2LR2hmP12HWgKR)a5pc=RcN9urrLq7#FT)@Yfmr>$1PZ`[:l
+%;FD>+ebM$2*&d?^7&:*<_Z'bXn8o/7X73HYg/*MJ3'a<[pZn"jQegTiKdfKoV82=U:N$V"fORusVZEXs9UOp&AM_s?=a<@ldjRi\
+%ZjUAZkD=&;W2;IrPc.?gK]2ugmc<0O6CqG6QE[-7+C2-U?rHJqs-2Om#5]k^Q.Z]@0fShkROFH3S,/5^H8SY)@,=+3j1Z?Wi]'0g
+%U;A4+h.2A)N#)!jKHEFJ</OWk13\(DX^V&sku+o.=(mW>3.c/+HB<4^9Q(Mo[/J)N@2i6p@0ipI'ja,%l#"+J7?&\\$ufi%EAeN[
+%l2:TO&bS"iHeDsq,`6Xr\2&l0RL2YATd\&r@o%r\DHZ'4GCQk>K9K%ukd&KCZ$ohL0Q(DH&Wn'$`afeD$pDF[Xe7Sf&@4pq[C?qt
+%5%C^KPAkt_nn-/g:M0.fR7J?,+nUm[_33eKkFs7W^Hf-S)+F$tRsJg1-U-osUl\hk]2R[??\a"E=FI\7rb%j>B&%[Wdb?fcS-ZW6
+%ST_k<@G(Y#8BuHmT<j:X`-(%]5NPp^<n@H()/:2#Httn'qO!W5"fU\!X/aGt2Dp1MmCAK<m*sNAAd#"j[`gt--VZNei[Rb,r%tq'
+%nJR7$]?#>Jf&b(bg8GuDQ:d#<YW/TFKT@sB_6STHdrJ5gUlt54iDhF[GlQ3g_Y>'u/_mnXRi7HG$leQJY-d"?A3[eJaW$FFpG#>@
+%?Jo$nTeqj&&I%2S(rYJ0qD8lt@=q\(<N!HODW!c'`*eHSF,:JDdgY4rGRm_QhSU-?XpZGAQa!m]iF@=I.uoX8`NR5]9.'q#lH03q
+%DN"<CfZ8fX2fgS0_TlthO&M(0B1Y>R-B@[d:0`Ta>*;'9CFuQQ\.=sXb9h0p_ASpq-*P,6Ypj?WFr4#V:/gh&XlJ^3:pVXA5M@65
+%e\jD8a@$W1,rJ\Pc.&jXq-t!@:!72qfV859:08;IB6HlKSGGdVB+sC#_(f4;nX$8D_rGCF:f/=3MN+-`!JP/P:VfYpQ%K7]O1V`s
+%qeQO."Ao4!=#;RXU.Va@$PEcd$E;&k&/RsKJ86IYZQkq*cM@6*J*9B2M39!,@$s;/R]T5LQ*GH&2Z>*aR`PCMY6tJ'BSeGCiPU%%
+%X8c:6+d(HL9Ms=]<i9T8's4nq.B"`K0L4idYO^j1HM5>tVT-W`K8l;&RO"E$E;EFV#CdP:'(!>oiT]AC-]8YBEkr$I:G`Z#A=^LA
+%<4:'XTgY9H\skf2@rsYT;GGI`4LB[U*O>*Q(R\![*!.^0"^3kYTLB8AKgVbnl#%::mo>K^"h1TB&^;=/]t3X$:q0c6!((S*j7mG3
+%X,I\KWKI?r7X%FQTEs%.K#+mOklDYI!XF/>%oKW1#>1`#+oI@"]1%_&:^Y(=2?4=ci4I[R8PA)UC37jrIl`tuAW,+f.r0p[;8U0Q
+%?2@4KJ]Y[+RWUDIB.<$5YhL`0s071'9L?CF;7=%"XDZLf3K!tf-gDW67jer"T>TMcB84-!6^UuID*e1\Q&11snd.%I'l)f?=.A63
+%KJ*?fkhruG&;`N@e:],9AI:/a81K>;.JDiYk"GAt]?usI%$GB%%69#+h.5jaFOBYtX.]-P2?YJAVXj.g];*lB>%\r.],CR^(ECf%
+%#B''#`&8(m`bB)AS,'>JBdX9o<&VYXZOPb>AK'H?'%"^#_#i\V19J\lpiIXP*Qp3-7$6P(JL$/_=Pob4B$H?MO$ngk@/I1<PL3M[
+%S[dF$0XG^W\&4@SB,k2bP(P#A5NX?"IX\@'m_Xoj"tKf*e-m?lm.t;'S#q1A%7#:M>b+MeJ$aDs!4T%GY_<^!?31;p-,D<c%!-XP
+%0)_&>rK&^tXTlg^o"[4+[#HEdF[D[6B\*@!PaHp30%m4C=1jp=Xm8M$8fg^]]mQ6[Ms0>AD[.7Rr$'C072C1eUkf9j^o_"uiMGPX
+%AE.2V7J%5YkJM=YPOm]N@`:uHQ47/borgPF,^5W0$NcG(ou-bg/<6+UI&C,(<=gHa6R_0fT7H9*67_T/_$j/ILa&cCK>Z]fh-\,Z
+%`s7o1O$="#[0-.l]T`^Rfr3uhmG3G8^Y?A!"Psiuc)@3X>$^b[_G@;.jnh^JTjoUJm82%$>Wu(0^r(221ZYZoL'^DhE)8=97/rur
+%AJDSZ/@L(k!@p@ghGrjGr_AYlfuLl2BdB_mb5>SK]L1;u#pP/q&Bc_%Hn==#99nDl.OJctBnpM/(1rO(%6U\Z:?F',DKMDC&e?.m
+%,Dcj5_HKL=gukRbaaKeRVNQRg.,[X(`tqa#E-`b+XRbQSZEm%Tb*`k(HDd4[*gV8Cj9?q,AC?7J`:K`PdMu-8SV%^h+(Hb=mZ0(c
+%`.@b(TN4F)JT>#?iFT8MghWD7>t`kg@e/J$b1L1M9,6HF^E:3Lk;Xo*pn$afa%T<3>HIUI!-4ZQ-!1PN-t=EtO*ju6Qc+;q>W'1?
+%:-Gr$j/E6M,J0eC1*flD)LlJ5<U!6LI`?K&=u1:d4m`))<=SDfU#O%CeWN>JVE>rj:D?iPpV`:Pl&VF-ZHp9E'u@?L&N(7.Fn^/3
+%Y]@.3TGi/F/IG(+-SQs,/(i<,$%pbXW)ed(OpA"A6"jbRFqb.]@Cqt++mD\%j6Iibh$4,c]DLrZfT?U8^ebQiR)6j[9O6]HNjb'^
+%Fhf/l.SPR2V4"*))#8$;)&!%#IF<D<qN%HbVF<'g)8,#<=)'t=VjNmDcbF\+@+1'7ZgP"Iq+\sW2@RHuYWGEZ5F4[q<0B5]!kA0B
+%gKTRi:'U5(FfN5-"!XTjg!&o/*KsXW`*,K2jo5=M;99U*3AL=Bal?,k$9o*Z;n))>-;qdm?&HDA%WcU],mBeM9O-*+],C6X5*up6
+%n;fUF4V)AV)N+/@%_5QOQD&>Pb`>!.7-*t.>t![FZAk-FY>tbs/8W!HV1Z+KMlr>d:7Y"]ZD173Fa8i=P.)]<+Vt5u$:9MJ=7[]Y
+%9@gdY%>SoVWc!ZL,XLr"niB19#"`K"5I0\#8d<PUeB\V\5!fTB!YZrR)&b&oa-QYJ]/AKCD/8Y)/,\EQ/CQ#:eT#=a:O1\/2bW>/
+%-UH0Br^I^_s0T(LeX\qT9',0Z,R`&Ng+^rmd!7s_:0aTX/b;qTP%8DL9t2[R3ab3IJF.Z8R+1O(>CZqM*4'/'k_,cWhV,5aaU\5a
+%<`+N-iJK..hNFTN[nh;TnOsnoH6FO:_2FL=\D-Z5PH9#$bgPg!D]hfJ_TA&]g!o_b+tij3qu@r;nSELGa#CU#3)f1_[Da)eW90h&
+%&,UC'7iU6r3)mHl/@!jdbd@g5M0VcWS]O#pRhC$I<%&<HAdV-Z'$gSQ>*XD'M`74\9$O(NSk5-hpT'>;MtjqK+*iE;\_s\Hh-7-K
+%Hd\;,kY`;:_?Ku1Yl<FE<GuTG+1jDOdTr^%?l2_H7Tn1p*$Ju1bs@=2<TTS'P7c\#j"N-A3Z?^k->=t*d7>EWe_mY#)F$hXqC<`s
+%!L+Q5(g)f-D:<:N;hjU-*r+j/Mtp)n5DJn/s1E*:kgh.P'KE0XgoZUhgj*_"&?*_MrmHk*9NWGFZ1/!.!-!VF,])0dmNi!Y-[?f)
+%IKOk-`3%$1-*c<*CJm:dA5d.g=U(if4GBdkdT3(=+!^!DM#iO\A-2OAHoJD0QoAZT\<=qr81d0^#e:*YeF8]=(Blnl,)%-u=IYcF
+%r`aaRi?]sVs6/'I<'ZRB60/),;7Zm%<'$-*Qtipt_0Z7WR\WcI%?l>$U>udX"rf)&R(uf@G=o>Z5n!k88Q()s$1o5"bre4+PM&6U
+%L0D?X%I5IfZG;SaK:G2L?H</O0%\E!pas3VQ@()"LX%I/:R&/a_NP.m%4I+\dYUH9RZ;C?*J\,.V`;U#RX??D.l!79MPR%a)em?<
+%%,eieTM:]69\XrSnRe9jSr/8#!9rh(7K([%:Goo%%E!jK[E>Q[Z^lmS0I=Gb#4h-c#h1YLh'.no3\-F,;!HaJ%&6m%PN]eF9TiqK
+%ncu+S.Y\U]@gELa--n'f.=HB_=2lA/oQgtc,L8Y^QMD>V0uP9k^$L[T>6?(M5($,0V`W'RT57&8`*"PnY#;-TYFs>E,pV0!Z!=5q
+%G)JJfmBKUdL42E_(V]qaT%F]eA/Z@[ZJ7HN6#[f`a,@FD[\71KK7IfX;PC+FbPX*7Rq[>u&1\)+)'RNCL10oiINoJs2@L0"&.&M*
+%e-?NeIrnYG;O1Zu.^4pe$mV0LV(Q_[n^su?3QXmO3nf0_!(n5q[9k+@JbU#kR;-cLiOBGj;Q)7$qf8#Z$Lf(Q2*f<;C\9F)Rq[<e
+%$?HG2-l2-VCrRNtlOXJ@lYn1I2]G5I2bOah1S#-tr!K02e1L^jNb(_H+kL*X_p-#E4@omC4#Q?rO.ufT's]I5aZr)-ViSdk#b1"b
+%7:g"6LOi),".Y'IY,r$*nJp]94?naT'iiIL!aO%1iPc0p(Y([8l)<lR/M?<eLe*h(eX,1==5\\+*9O6e,2ONaJ:nN/PS!3Lmc]2Q
+%TD!DV+N@fb.b;C<F9E?DO`%!B0RG#b3?^]q@i-m1;Q]G<OMlSXo4FSd28AER#c0HUhmY&t&U:Cp;T@WaNt[uM=dG.qHm;o*jkYms
+%=AB-!]7I6V$E8Y5*35AuoFdU\PV8ZonHhoL/>XO[F=men?0JXUfShQWXsF.9FboY]CQ(4,r$^i1,s?q@."XCIL;?(0oA$(;:;)VO
+%mX9"3Xn\W*f(i'AXhs4/Hr6Gb#AmjLjdL`AN_Y</p+p3F/;C"GCmnUGT?i2aJ?]Y'?ka;BJ#GH.*5_bh-'+oITCFqcb<#ZthdmWA
+%"7^0gN+m-cG!QUKZD#!1Rtn&PqTM%YES&W'\!:+&AT4\t?P:@\MigMK&Mh:7A`R#h`!2Vmlir.585aSG$K7?n+Wr\>,S]9hI1WEd
+%:b[9Uo4FVeQ+Eu6UFgS"#Ue#L?TJp<*sIco$(Sd>E#6$*oR*S#DQnPfB*muVl2WYH2)pG7]hlf\Z#).,W"_"?=+t0'@KWF:lSK4>
+%P&OO2Zl>VT8jgQO.##2W#`sJmh1p83cd.2J;^iZ=_V5q^GciUd+C3L+1p%/Ae.?R;XBbSYJ+kR,RVrOgp4j/4kSmJC0K/1XfW,Xp
+%k;u,r@%1-=YRh`^c,cmo>)FT[P\mEmaP*HC>4-')_?NC`&Jdi>lT*+sR42rUf(F!h3A&Z(+0pPLJou<eD"10Vr1K\AJ%'R!\q<g"
+%kp]hlBo:UZ<-](uJ%UGuoc5m9ll"C5OW;IVMIY223pMfO(,oGtckNMcs%bI=OsDeAr]!52?fV(YF:jhL[kpH:$b;D0Pj>oA(o?BL
+%csm$61=4)J@>gcH<-<b<PWG85:2oE&+e;krEaGQ<<AcF"rX<d8;RF<Z&S<'B'Wt(Ka2i.?W>@9bj_&fo`&L$-$L\Xn7&kf%`d%rq
+%ISA^"B2VPI0T<Y6-:B;Qg+=L%kRjhF<fB6eoM3\>ltXKFM0]$A&gHra.;Ei\#!5;5?2B<>1dJP69["Z!h>WPh22_EA<ViXnQ_`g;
+%(]6e(dPnsQg&"n6!%HeF*nYHbCC_F'qKT\1PeEF_.).M8.lZAE@E2RVmAG=DSEn%BkjWCrS&oXp[fpi,Sc$,'jj\$"HA`<frnXmF
+%C3-bj+,#i7mP'=uf16UkW^K3n*j[&YPo$<dm+uIpYGQ6`.qX?O"I.Hi5$*GJ_=]qopEusd8h-D<rb\au.S#i)IH7YGO-sAc'C[Z*
+%e>c)VWk6E8]jf(=e>_lXTMNf4Wq&b[icM4Gi*k9mFSqN(Wm5CRjqFF5dc2l='k&#c,_3-FFt\aS&$O`+82ddI[Oe-L.ATb'CWZ/h
+%d885-G_f[a<>si;,f-VI$77>)DNZQqaQ]-M>+$*VDa9Gh%re,jkZD^pM_V@ij)4eVlIJI'"f*d&@E*[kiOoLWJ=.AI[>`@-o"(lp
+%i8T]uXX0F*l?3M>nq]i.B"^pZO*NJJKq+Fn.5RiRi&=>";K7Nu/Fp5_gH[ZG9)LP:K,PMp"_*n6"B]W3EM'&Lh,dKOf"m)MRLCf2
+%>P9XH:L=#U&#0qm^(B9L6P4oJZf/cQ^iIj$<tNT5);u\)J<[?<_2P],=q]X:+j5B31`O=$ZE^oC^B3EseJt`2>g9?*Run?2+=dfR
+%&^_0,*6o.?beplu3Vi.>\8$#JE-=5b9mJWB8pQ?*Tna8aoE`HqE%ah;(/8:k0OR8h,%,GWp55$A7G%`="uWQ'<_oSrL]Qm7\O=fp
+%iD$#h'A+.D01ljC:rS0s7OT?!0Uf<4m&Fs]N5*SWMjPJ"c!-H8pJd5KJ/g"Cfp1uC3>FcT$AOR1='k+7i24;PMgscqgd:WqNHt]7
+%r0[MbL2/P>br[6s@Tf";n`j)3=VB?eW+nj)JNLX\6F:Gc)B\K-Xqp;_0!7abiQMqZ"(e!gDQT_<X9oE@$OL['e(9ANW*Dk@O-r:f
+%R2cSciPI,O33a'!mlJ,`OQSi&OMPH8DrT<o"A/0CCkMTtnHD=4eYn/G'2GiIcaC*MVs]Ge8!oHQDU![boemol4m>LpiP@40>MPE.
+%L"0d<K<!oE:2o!:E1=(i@C'O*LM@/Y9!),(90%h[jUkNQVG=Ve[0"7n#uAu@/gSQ3qZPO]*$(i5!5;h++K`1"JY(p#eB#?G(*UZb
+%loNJ5q(!r>poGW/A#!O,9_=tR%Nu/:aQrJp[I=3<.blS^qm`HdGnO0'"nB@XpnD@Bn7gJ.>l9uN`2t^>T,+L^I#FtF$9@Zlm0[6/
+%#o^AhQLc/qps(S<H5!C"24eDh_B)Cui_#$./Y-5oSrutY`VR'ZH*U/M$K6iQ@]2=%lfOou!m)LNYt2B$lnR>Tr4ZUKoqqnA:u'l'
+%XnLf.?sb$KMH*l5<@U7tJ0cG<HKPH]kdGF<D5B:=dRL4)AQ66KGI-.<j2[rFZ-e8L%=<[h*NUbflDO-5A_EV7Ao8)"XNbm&cNa8"
+%RO&K#J(0`ggtkg@5>uEj%,SbO@9#gXZD(!@#VUnVaWSKo-\ET0.6D^`HT8-k)\#nE0rq]0UC/s#cE-"lCpi]eT<Wh6-OHt'H;I?N
+%nYXiG7RBo<QjRHCE@c7cSmF<J(q]hA2!Sp5ISA]EJcHT!&ZRk3A8'^4nWsH7"GQZaS8ta%N=qei!IAQgQ,l=%=]&$E>uj4W7??7*
+%?M6kGJ/'5PT/c-cCp_0,j9[9O#m2iH$`+m,NQh:($_e^;%o\K`86_\mfP]K4^2].>s&7gS^mlY->68nIqaFI#jA)^I`Un/$ck2rB
+%F;f=FPRAb^ib@-$Pl-b+`a+:X#fL&S5*>nKc$VK1S!rtUjT&oQSYr.JSe!,bQXn?\#W#Z=3o>fP6(/b<A)Ro7#j)A:h[[($+I+$:
+%$h.g']!XLl<AW$T9@UE`I&qM,p.dCUBYnE[V[5F<5p]]oYjlOka:DL&/@d@'Nc%.S'\<=@HV:FPL<M?o">WZ41K@SA6kQ%\]qpU8
+%bZ!![P;`sRmD#4Mi3FmpJ>fYJ(^Q=A%bF,9`j*a/FU0Y1e;7/[C=*I*K+V2h?A`bd*R+6Zj1rqqkBJ`K9,@V5Z6AKja)P:^$:+5r
+%m]sSq=r@aS7n93)TAoZC11=t3U;fjl:K==le9=lV1FkAiR)2da*"`"dl,.MDbHC@o$TKqsRG8nFKmDDG2CC`O`pjPKPu(JA*[r:P
+%1Ui1qaC>#VL<i7=-L(;s*YMOSRMf%#_8Yb"UWKcN^l++$-r/9$"V0l)SE7_CXdJr/B=Zq%L*m_g8]lHT(A&@#9LDD,-Y;\5G&LB;
+%5Afm?(u1NoF:5KhUacC8Q/en1JZ7?K#Vm'SQCRcod=<oI/<dmFVZWN5E^%`oRuX,WW%Q5*[G6!bLgJ,<$lr1"=O"r$*_p"FU-R1,
+%K,!%L.Q(.b.biga@sF\@Fi2j,N(pN$MXaQ6dOo3!EBc!87I&Ei6:f,:5iB%Y]hGq@otF3*`6Fj=HmJ]51+#YjP9iC+:Blj_Ql,d;
+%[>;SZZ"%8$V<_]"`*15,B2(-#.<)9p;-]&b^74e4mN6WR45hFros`c.+mb@GS6>i=M\aHOf:cQ!q>kPRk$F,2*;DukSM*'86`g*T
+%NIATOo)%28X>>leqnS+O]#B:u*d).@<VR"_%C%1JcoJ2$n.a3HPsTs\ah]*O-e%hO-1Rl\$qMFm*,qRNqje;#/5nXjEb+kg/khAA
+%:,NP`D21B$1\:/km(_-jkar?Bgj\+.`)NsL"]LP+_1>o&NF##+-H0^``'"]"M$r0Qe-0RabS!bRUNbk`'1K`(]F&Y,([40RO*26l
+%YZUQg9Al@d#cYd:6,1eodH\Al4(XsQr[[ig8SR#oTW9Y+H6/;;)$Vq\lVrIkbtQo/lED6UruafXMoPn"=0J>jiPV\)7+K&nc$e+_
+%8@BS)#uqaG<#DWGA6/bcPio\_VnYN7ZuK1[L(oUA^_A[>%kM9l<nqnN%P@i@'7"o+_4$`oKMXKt:%"#GdR9$.P#ok>+j7Wb:u:EY
+%3?-YrnNmU?m6Bf!Jq_pAKtnpq>CWYB#a9oA&-<sW:UH$O7kl).IctNJ6YJ0YJG?noe+QE!4>l+$,RnQ\!hg%KC0RA],`i`H:[OHg
+%_nP$P^iD"ia7D3g%qZ[@\%6T/[KDG_JFd?pQ6BH9c!9g;W-U_0ZkJ.L#/$lJ*_Qgm"RqeG=[EfjPKYG\""Bic=&,0,FegR(\'baV
+%%?5O=Ub+Y^C"BELmdrXSG[_Nf)UI/S3nfUNj;VRCV]?0i)()k!MWqog&,EhR9F2+@"AhY^=h9m?EbJW"fU=uq[d"TKSjM'D2)H_r
+%fT/R!!#-aK)\`439V&VE6U9<j$_RgV35q<A?%IB`k>_`@,eL"m,>W"m&Ch.'?_gnl1<!(hc]VmKnpOK63h8JK@C\H#^b1?L(W:9K
+%f/D7,*(8&o"DeJ9MQSueTZrL\,N8\!hT#ao^W?UH-heC)Wg$N!6*PWdI?!B+k'64Y8)5%_Fm2_93WPfs$(dWPWaN!&.KMI0N7.<k
+%,[kdSgfd#cW_-;E@bJ2-)t4*#d*]5>g`n4KL`Bf?WV[snLM6aX!Pr,]2?US2W([ULCiRaBCWS`Zo."1L.t@VP)G2;*%?)i+cZFpF
+%2J0LU5)6\)?1?hNO*\l9`.1fT[H=WNfid[+$(,,rR"/!H':)>pN=u5A.+2T,2!_sZ76FDb%ZjAE.9.S=-PjRI1iK^r"ssQ`9Ytsf
+%3/'1D9KRrtV/j*`<`k%qm:,%q7XgCJfF95mi7Cb3fOf[;0p_nP6_W8AW+-EP#DfpPXeQJqDR'io)p&FS_W:o)=CSX!/+OP&g[$0e
+%En$lXTn<@*<)F/+Y;!c0QK6b`34e=06KB@@(%<:6Do3i`'H..C;&7LLdNO381GJN#5Q^[W-fYBnFh1>>%X"2!YU$=r,7r,OXYT>J
+%$t,&#PJ2hD2CiH$9*"ujp^5ULV>N9!Qg%J0Ak>IMVjJj(7W@c#[.Mj5aDQ1E]"-V91b4VW4OJ:uc7X'EOf068#/6Hq/=5*O&N61Z
+%fcUZq\#<mhZ$I(F4N?qI$THUS1!Euu^.\^/\GZsl%qQ(Q\r40g)L5l%S$nLg<\P.]ADG_fk;1)#i\<L[l2ELW,KS.I^oA7VWrb%&
+%M>sf]lBmB(7,K%sGa&jDkam#%*@3BG_T0]9hPS&bn?NVLDYB@(Jd[,)(E'.'I5JNm(8U\Z.R6r$^gHZ8Uh\?]F5I=5VB)!pa)RDY
+%;sHan_NU]bV`$=j_T6VHJ"VF@/AM;.!Xqs,CSf=gaNLgYJ`2(ej__;;.ZZEDW1!Y93Ou[/R*Kp!gi2SV\P#+.9/??)>?HM@7F9%O
+%UETD+EVL&#7^JP#$](>$i\XfDB@BUjidHDC@M>-&kRV;2G1M_3gqB\JK,\(IP<$GRDQ5&!.Y&6_gr!0D9Do_)gP!pMqAT[YZ9PU9
+%G7W.eFB-g\f."-3L81-W#^*/nQ!(Z#Wi9F:\QnG<66YA7$!l]564mms&P4;U4-C)ZE7lL^m'^&Z/cW&%<&mRfmnSW\?+?\<"!:`@
+%Ve@jt"X4o?I2\J*m4nCFBq(f((X<\e+FcI\5Zb6qFM!o<#*?B3jCY3"+dp(biQ@$GFY@T&a93(@D/s*4[BeHJU**0Fdb><^1[WsF
+%'m@VlUtKe[_t`DJs'o+.s2q;.4crTe<V!5%H:0$Y71Ee\/j`FH7oj3H4@7BV8->-:KMD/OSpsPMAC8?4'+;jp#V5tJ($Pm5P_T"t
+%d=asG0#ZMAo&Djai)?["[KjF5*q$TOrc1!;lbJ>ojOC#c;PM8K)nsO+HP4A272Le/5;9reDHiqYQEhel4aj([eQ\7,InZQgoM$s"
+%cN(P0:#oPkj/.%;V8iuS4pD=RMsG?Ai5[,=>qd9F=M?B_2W)qY<#30_bE?P`b4>PKcpo<;O^8<XVpdG%^sU5L<';r6O8G$jG6rX>
+%;1t1EEg^`%a2+osQLGo`LjnGIOQF&HWOXH2Z,ANu4c5SoQEH=7N9S$&0=0I@E>(?9Md=@HU9SOp!\P#m0Mi%-\'Onu,$>KGVJ7F7
+%WT/ciF@Pj^c\_jT,&%qqLrc]l00SR#o6=&'3SJhSc2jtnT030hqp3uKR)NPdDj)_XJ4Iu2D3K?AKi-NhLVF*C#I8$6d^r,T;D?qG
+%/1_Oe_qdsU1#lLKaCH.#\1VGs\&^_8@ISY`:<ALc\O;UpRa3R).A7I's%]hg]5YBY%.kC\gB<G@le*KCZ2qcCd"Ldh9TnI;7Vs5`
+%\4'qHV-eqo*6=tV'4?a!SV1XOqbZj1$>3i:JTA;Z*;*EJW<oIYOCtSZ%?Lm@9Z_Qh;o`Eh].3)u]fSXj^..ZCZdNr[;C<T$"h<q\
+%3.J8-mFem(`(4$!K1BfA>P/U8Hh>d)SN><3L#J&UE@IoDmhlsDf%Q?Z#EAt-ET1%3\SCb0lo3le;tu$>:c/o8&lA<WR(%p;VZ'Z`
+%mZ8@lMcs-3Pa$bk.ia6.-DG-7&NT9?5cg*e7E)PY1fY9=BQkc?O:dn2m(YCbB0rC,--H+Ihoua/!s,s6j=/HG6H(Dk&/[FT#Q>R`
+%X/&@O%u7L)\Tr4o5R5h?PO+LPJXHO,QsHqd:h7`%/acd0e5C0:pm.FmXo/m@C-Ehr@>&+d$$[s*:El/Cr/T91<jnD/9B9AP5,hPU
+%p`@T4PY)T)%nY/flafOeEC$+\9DMF=E*$W?%"'LtXI\.TPbi194[I.;d$7(]3oMOhU6FGJ%:qS[*90L[/Esclf`J\;ZMP+D-7E"?
+%VGjoC+Gn't[dTp&9rCs%V6c5*=b(<_fpM@WPQA9V!)VGXS<.1::0qM<?pUoVRLJc3@1i&9M]/U%)M?QO2[^R;jUlKE@S%qqG9.E.
+%@=08R*#;7V.V`qW%tOBq6[>.oWTn!<k"kq[LEd;hlkK0C'P+D$V;MP+k6RcjBR\;9430(nPUc##+0_.KXU+kQ$P;2&(^s#e=lS()
+%c,pbL.ZE*^W(,>t"";G,`3DbQF;.7G3I-SFAM0h-Z,gN$P6&V(]7S=hJHPT=&D!8F[RibTV)4m5[PFh\0G!m^U],0s;.fVnit%rS
+%oKHe6nr(U%crWC0Wr#oYQ_$bp6JZI\fj+%("*pA(WCfG7Q>]'&Vq@F823TcTg<u=VeDqkRUp2iE)B-.:Q55@IgP[MqWp5Elj1@4M
+%*&RqWP+n)^eONk*'n6b/l$h7R\YUFR5]=kMUtth9mub9-TbMRBc`<D_h1cX'@6Dk')7oCK*f!"R<4Um`11=Z"5s!)1RXS_F2HUK@
+%`M#a)Y*WX1e<aHh9T]jAYM'+b%H9-oAD9:tJg,gk<26K(.d?E,]Zl9I?Z]PN14XW.\+hPW$\`1OE!d#-@_cmU'NoHRS5&)GRQ50c
+%l(BS,\T&`-jm#.m!\AIpM7o:],jDq;>Sc8^V?g'GNaY'Y!TN]MB_40H\+u$C@c^K\MCcQ/22DkfJ*Mi^H6>c5WN8W>\*15#ls#(Y
+%:l:0]/g-f8$<mgT%Zn7*K7%uW)\pm8)IR9Ug&OK1V$nJLPg:?Z<jHOqcmcuYa&r=()<'^R*,gDM.4.VZ;?D!AA5^OFWG/]K@G,W0
+%I:Eh`2$PH7hMN7_9q,8?DPDLcER-mXZmA1H;7\/)E'PQf4A\iq\t&@@*L(psiC0dA23;V7g@rL9cm29N`3%)pC6s\$hC>3R'$AA[
+%k#?JK+Ya.M-H"q4!X8@]0uPc1i@cj\,5WQAF:nBR).UJ$NVG62Ui'EuJ&qVF,1>J3s.kRJ)krhNV<.fS5JTa8.=k90K1(8mEj)2O
+%]d./[3e..*+\FYkU.nJh80PE<S/6Pd#ZQ#_W7ng]389gh^&lVWA1!UW3\>E0OXL+PcSbTfTC0??p1CVC$^@oQ6Ks/_nY%PFS7L&A
+%jPSp6i,(Zm(]TGoa`aD6Vl\sZG#fB*3iNG1@U(2-o_iPs`T&Vr/nn-);8]^;Q3,PcMA.1DLM[*L\%os^9=J$l!0;YDAp78"SdQmr
+%)/=oA2m7C]Sg2.2L,EXh=IP9Uo4k.3*!04nUG-DL6L)am?krKY92ohZC5s^"!Z>H4,5]gd/[o2A@g,UWKLCE4Ijg'W<C2j?RYMU8
+%+.t0Igd]Hsi'BjfFN]f6AtDD!(monh.`&[VI6m>?2uCbgP,W&g;OK^-V<OQu$Ib9X6;$e_*^NN0pf8u5'Kpk:@]1'Y5t=r)+/hG3
+%6J6YYC,+Pd"kDBH50oO(B2%X]mhR5E5?700#4YBYgs^X/9[hYu_$(QMU&mI/6$Fduk_*@'AM_Vp80'1^TS[@qQ"LnTF(-k2mGla(
+%lG`C<eY$45OVQ!82`3E6!ahsS,WD(Q-5#lZ4gH;:M(:@.cU_DPGsNn7G-h;N'<ls9\g>I'dmc`5OY:t_A9NegmU$[kCm6//VqUZu
+%YTcf0MT7j"oH.!JZ[4G;_bi_EoHC4WZMSM;J5p9IdTM5*fXU%<iij+@pkS!BU#]9U7lQoVOF5.9$;]]k?f'_BbcXE4SFKj'`^qpD
+%4?it7*:"(Xp2/dMli]?[n1+7*bacWp<-Uu7`/fJbMi'C^CUo&&Ep(!#ETm=lGZDP`WO[[7m"84n2cJ#f[*WhrAOrS-nR?2DpW(A=
+%8>-=<7o37h)$&a2#+]'I!P`GG:suhlZUlro0er_m45spa&&H;<"c/'`,EQ"[qP%]=:bs]FQS2)E+-ZUX+(q=&MV$$&*.R9V+W:n>
+%q,5S"!.A((N]^@P6DncOJ*GSS5fC&uFhqO"B!9ZU:#O9&(J?Qm)-'De<KrJEh:<*eImR_k>PeGd^2^;W,uZ37K2ZncL:<PUJ^CdQ
+%V'0PZkNN#07m&QO[96cGTMDh@-R@H/l^1n!jm#_k<%_$R""OWrYs5['eO_2g(dQ%l<V<BJ/K5HQ?,b`mc;AXq^s)ul%>P22a-^bS
+%OBgl!$M]OuD<^g=SQ21]U9O)q;.`<T*_Sr8I@Qe.V7a8lpd53;I#4aP@Kn;Li2Q">J<]1&Q`?3[8?\Zg'&FAPY\<^J`K'i&)=&G"
+%4WGiX?Z+\4]*MXPH;r[,CE<1%alXOrloJU`TJ0_A72)2iBF^]hY5&meP-]F2P@K;PYJ\YC:Q;?Db$*B[0TLD`&#5Vgp(E7Lca\su
+%mT;?Kn9q25N,uJ?^7H$D"=Gf;<B&03O!\50ALD0ui(/Cn+bYKZ:F)I1UjJM_b`GU%[68SW_F$2!([@=KARsST_BGSjn5<(:5a`7i
+%bdbbh_\$?\AZ=TR`!f8R7:hA>?t,P@3MkI#&0c^Mb>O05!&jbgDKJ%WcaX2+-A^Oc'PN_]6bJ1VO%-9>T%_X-pKa:IcqKM%5e@I9
+%Itih>5Wfmo$pPj*9f_W7PRJ?_^mU!dJWR]n91cuqpRA-/BKY<Vg:&;T^mHa32_eP+^Qm(b@[CLDO2#S+$S&e^\3USVFgn9r_O0O"
+%!d>:"p_]h2TEIBL,l)?g*ask6\[0.^1N+%H8aCs:Z"o!7$Mfgh'`M(h*JboP];cDbUF:4N`<7PJ0NMd!,Vlm!o0)MG*+Rf$E&?Ql
+%M3P8c#sJQ<Mr\=d7l)[H&2uD@QC.1sSFS]<0FQpZ/P87aZ@Db,T3.^sEMhp.,]@*.l9gO1(ncB2br7<`oYNE\FJ*!#?j2?BlJ;W5
+%S1#(D>!'=N7[?#*$)\cr1h[,8(5AV8&\q-DJr0!@"CJAh&E8q)UbN,d)Of[B!09UE#@;+Y1Qu!YC+R7+#_Z.'*?rC;^Qb!,dlK&,
+%]Xktep^SL:_+3-^mI;up4%rSqRsGY99tp\+**I"1jn1EE7d12+_Gioq7B$g)MpO1N(8"$rCTn-gqBf7&`E5_;2'pteT!u?k.;Z,%
+%<TURkjsqV6<2G'R_FJi\^FY(@,J-OETm=9d5pd'NCDG\c-!Q95A`Xj:.qVP&LKFg]]6QCJ&jo90+<.1`8$";(.R>5=D2-tdQmQ^<
+%St@BBe\5hiMFhOpc_*&J>jQ%/T#H+.SQ.-S[rcSp96HZ&p72B(Eq_?J0#Gb;;ELSh&ncR4FR"M<]Wm8t*J#s.:sH3b)N;26#6eIt
+%Do*f,Q.W-545]c\92?&js7S,+RRB8u\86(\qa6qli3Ma54*7]:a)0V_SW^$1nLgi`/N7WYW:5&@EVFp:aZ^t/==5a7i7p[9+&X#6
+%7E-n'><\9?f8=pE#pLo:$7'9MEpP-%`13,MMYPg>8IhqR2FaJl'>^@6(-\XSCk7'CpG,Zd'FD`X>m8GLTLdlBa0_'a_4HOI5/3.2
+%H9$8,KMn!9Q3jK\Ejk'"+a*&Y_k)_lZB7`r+%;s(i@S&6mUUS>Vi>:WnM=8B_9cQnA0$/kP"n!,d.Ts;oPlc!G;D@.jJ%qdc?FD:
+%X%=Q?;_agd=N*qQG6\h=;>+3e.\`W99_DjBh/KHhA;sOr"iFa?D-/AiP1%csSMq3+UWGXJjPn)\Z&]TK$.,3_i]W3gV#g@@6OW[-
+%s%pjnWE:2DJ!*BEKJeihAUpD#nF*J5Pm0W@jW:-``,dJ6iaD1<)XnRU3=)Zf]g1-Ki9iHi-aTi1IP%spBS]%6\Rg4mX::nsG*[7!
+%07u9[A>plS=1]C>SB4M],WHsHnU?K+mZ'u'6@OKTNM3A%L7?t0ARKg4eqhdu-mE4BbAM/6s7ti]pG.Zs:g%/Fh^T'O'n$p*9BM5u
+%r:<hA%ej&I=UsR9pCVc2AJQ<k'qm"mlL2K8J"mGhTbYDq@m)(gFXh&b*R1#RqVd!pprD-]:3e]Y,ITQaZ5OlkR^,H:7hH:s'9'gS
+%*8'EWpL^ad@(!(PV<Um,b1WHD/kn(%%3i=+e#*(=n\uKqC%rRDOgl[.:0%3HqoZJXMq/$kcr8VoJe]be<=5\/'\@^KGAeoX29htT
+%j-VZIMeOC*SP9p%5oE*:=&sm1:E_nB,((SM67/Otk\gLKqdjesNt=_co]f@CE(&(\-4qMr'MHRg"%%#"R9udZ>p5]YUK-K_P$A-s
+%1aA6P!in6B$=1"',4fHB9GU806J4sj$G))QT;W/3`)\KY056'H6>/9Ri]mf;s7q",f4j@>f*!+:F/'@/dj`/X-j!L<q>eDYK^4Ku
+%Zbn)tW&'pAg=e6kZ'njRUBm-SLo6"+a)<S2iP\/oXXPSAnFOG&kslM/_\F1&fc?/GWd7O3.YOV./u_$<\f]LkY0u:19"S'!Ed:B4
+%TI19(Gr.pG2LO0AA6`*N"q([a>/k<]H$Ze85I@T)"0/B&b.Zi<.'`h3/Sh8I^VID9J@m#dD\)bCZgaA1]JKN%9U[[8c+pa-HQA/K
+%;;Q,20q?`(lnER#Pf"WjSg\5o.Y5?I#$?i%UFJ^\P+LrfAEDL'`)JtpI`gs2JoAh#<08@r[muS$kp\fE0Yu^/7&O3@Aq.2"([M$Y
+%E=oXjXu;J"B''%ipMRU+,[#<C(Xt\!MguZH.bO]o2_)cOO\&AWCQakm#bb*8$)=(3:rA\Fo_45cg#a>q:1g%<64X./;&OO>4P\2i
+%R;L]*mBr0tR?E-=MLr/O>kQ1Q=L3'?+ioL;m$@ul(f:a',SlT>dQ9::+r&h#M+Jkfq%N^WISb(S]n:gi@"fnc:j7qs'3>)p,1j1A
+%gA1TT'ch@)G+Pt\Hd9]LdeSm?L@nU1>Nmkjo'qNt#9<:aSbaqY#$?.%otU;P@\-[F6p:CKm!T+^(5A6Zg'enP*Ru97fTBE(\0arG
+%M6$ht%]F?9*"ofM&Q-AR9q'^HY't2i<,71F-RKDk'MKP=n%1?tpS)F@'h@U1&M=J&*e8>LjGTV`aI^!6g6fJ^<&)J7=+H'eEuuPp
+%E4CI+RoAuQ3VrqAXf`WAd.T'B`*bQch^8!2F&@P9'.pX?67p1m\fX*`NGBi*6."j]J^1j'/a-3^kKSmHAb*`N`K44^kFQ.>G^4J=
+%QHRW=]8`)[BI&NAgbYT35XSClk,FEEUKdFPTZMssV:X/7L`HRT[=)'ukiU9&gXtLp9J%(:i&>Cc_gK<YH0`1(444;&f6?:2%q6_#
+%XBo+P9'a<662+@sYc:mFIkWGYWL3T7,,_HW5;9MaN4Bm#a(@]=`mi%V.=mK;-D2?73#Le:<mD\7].&`aCe#d#._"2sV76d.`Yde[
+%XGC1K5,TpgI^)5AEI+bD4M&%@NVg`YU$kZjgt-`B/.7M?'=f8O!bMNi2)]3+C3cP]L2Ip#B*/XJaq&K.o2gHU?rU`DDhD4@QG%LI
+%[UAPh1o+oa%>XRolDC$j5PM6+%$9#jOs.X2QFp*gb\qFdo>I5i7Mca:.Q'a\B4QdMBAg=O>XKoY-(?4;,@Z92ri'n<EMkc9GK1NE
+%W(ZS9"@Opqkl6g7m]e\:WJH[KgJhdCp'h665g)sgC"7kNUXq`2/"%i^5KrsKXG<=fAug7L_T-e%qQ\D8Yp_#%IrMT8nS'HslXOHZ
+%J+[pj7KSVSB+J5aj3XHLRsb\B8ftNHBV"$W`!YjP>[jU9Z">1X5fF:=#mM4G#X&`h/2L^QTe[g(`[#F>,gLRX&=frR]j=-!_aJ;W
+%*G]2e8I_/l1k/J"=B.1uQ.81R@Q?kR40FL[J0$lKeX>PY"<ccjYVMEagIfNaNh`=JG7b:*2mqDfVItAm3H9F)X-$C08?!]^7AilF
+%ArHGhcRoQ;k,DQ`hQ$iP=R[$>(r/:maS[k0"jKG.rWMj)T;%^k;T(KDfTKHGi]rBB3=)%1]#?3sHjt/jFVnf>3Xi7W'U+W-_\%#2
+%n;`5R_)4[2+@re:CTI@W:,j[EeT8:O95=(UV)L;adu<8P\o./!qf!AY0S&i?`FR;C&j:@o+T9O8c'UF5aQ@5HWt@&KfG(9M@UjUK
+%P:DGag5$LKQm^.T(L=e3I86F0U2;!HgETC[Q(SYBFXXNF9=qK69t0dO=P^M,,f="`Z"E$Y$JeG4+It)>\piqXHfu]5o9jM61;3UJ
+%G`1^"%/rP1gYWU<r#'Ef$VX;q5">2K*7+E%d]V1=hKj"7h>-n6-jV*#I/e6*j)dHYD*WmOHs%64\)3n9hKn&THA%.YD]d.Rq$hIl
+%m&sqX6KX5576@0I\3ZV`r?khGbr4-XORKa"'4rYeJm[Lm(j@N*/>%\6\U&A+D]T5%Eh9^FoorV/?g9525dO3$5QGF^POg@_e8FU[
+%4Sp`?c0iD-L0;ia=ef_f5>PYUm;ALnLq(<#i^E&*!IF!tHb>?bD8pn1AMLEOZT'/LaUj#&HI:Ls'hR<A#0^Go$,L8"i,J3X<(eTe
+%qaA@K.L-0GB7j%)jWTB_2*h8]0P93c(_E:P!f]HJVjHUWEP=9HO,c"S`EIA>.LLnc7Jul0YOc:)&LcKJ)lWTY$([Kj9A4N'WCm)M
+%`gCaqf(]4Z3`EuIP2cD\ro&*VB>Gh]D4#,OSs=3GTf$4?c_5F&:\+QCZQ>#.F0Eo8NG?uE$`TY,.8P*jO?,I]`0,[]_"G1C`R0t*
+%iUD3gmWFBLZE#.Rn7Z@O$_E=H@K;3\,Q$U(N^G64%irRKrK7P2-F4H?)d'6G82=b[9t8DTkm>*?d3lf.kZk@9'gnD\.3L#sZ0PWC
+%fJ)B.&A-(#Icf[Wqi@GK,OdY17tXZ<dQ]oSV\"i<]N\65;4p8R'^m@eJNbUtJOs5+#9AkHGWA2:U5't>*==$#1VlH+UO)=FX)CT-
+%Z1A,AbG&4neT`C5G9>/FPNsJg8;?J;/VdP#T[5,KO_gIXfU-XWrXo:mr?00dHr"7KRi4NQgR+uP#3)Su<9=%LU7`nA`,<@4=[[tV
+%-n\=,D:TOm.3U_>/<JGI3F!%_]_"O4:=@Mi:IQ%VAP@N:'(RRa@^MZS"UDpnO[tK5SiCj<,rMTQS?W&?T<Fl.,"Wr0#U#W`7!;4T
+%F.P=R<(u.4a-kH:.=6BTs5(g7/C1>8NI4kF$7^ujoc'o;@<T"t`N=k8A=%_Yrm7bTIoM1'<#a,,H\E]WSV,hV8'bh!l*hmQq]%u-
+%Csi^D;8SY.Dne6p=5)bn.P:Sj[;rEj2E1&EFt-nAhZ"'+N9@\GW"lG6+6o$7qPK>`';&PL0;dUn,Q*juT<BZWLSD>kWgDX!(eh<K
+%YL")O;m57pilCpP7#kmT[Wrn>BWfh&8C1@raA>[nY305++@-^SJYgeD`.jS`3OiU[oC7KPVOPNq3F1-uokmX>ONTf^'TiYkVhuS5
+%O*H/2(`"*UW!@LNNu!M.RkRsJ7':)brAfJh9G)Mn.$F0)9S9_.EPpNC32tP\E%k8oM9%Z0W1G*sS/=C<G<S!HC:XnJ,)^0N2^\t,
+%pJ<$hm3L$:L1=lLY4I6hMjpjiG>LhZ*K(G-g/>IKFjZ-]p7Xj_Y%!2`=^.V*NA#+a%pn*:?LG")T0N@p?iKuTs+-gAePH5$^\j_i
+%s8K5$r]g?7J,I?:r0r32H[Yl8s5s@ZgV7sUs7#Ver7aI8h;A4n:\rCIktc\c6/Hs)MiTsuPP.TI1&_%%rsq?nlc26iY=IW&rOMn)
+%Dh%cDraYg#5I(0js#pCGfXE<t_DV,a`qQ@+,aeW/p\ad#EsmHm:]J]6N(Q8Z5_)fXUPgN1dKgas67lTJq'7`Vo`<cAO@,1)!Nqje
+%9XGblJ-2;N8Gs*f2As=ZLc'n\M0a)ZF3h04$5Q,<*5Yu\j%Xfn.>AJnHn\-83pZlF#ng:6Lj+ai"bcVc2(8`$fl(@M*EAD.jFn$?
+%iR'G;i6STVAkZ(d#&4eR5#EQ:3>L*Mq6@,3kR-DP<'H`e3B>8_Ml&CO)@45m`CPfs_)rqrHg9u]d?k3U8Jij=<d5DR`8hr7q_Kl&
+%&gU'%G?sm[2'$6G#m"SQ:Jh'f6GT6r?c*FmWXQJR=ag4r")$^G8kC.E\4m#:J.5m!E82igGloGpFdMSBH*0K@[N)h+PmC/c-mM.$
+%nkoE.S6nUI*qor;6\I3tWFBkACcc,eo4")Lj_[E)(s9mFLe;amAXMsKA8hrCKre0k"JQ"(81?'6>cPRf%KNg*-h@cFe-45W^sp6+
+%jSlRJOT98Q<,='6NlU11IY4i7Z5.Z3/e]Gl5T2N<E?[^F$27i\G8IkO2@/I*qc+Ve^`j/HVJ,f4dmq/Lhub,^Od$hh'r9NL(lJ[(
+%W)>1mVP3#,7:ahun[OuYH`<o6bf#Q1Ktb;"$,X*F@74+RDe]ru_"C6[[d9H[b">X8/6'jG-euZ3g!S$,U`hH$Kri_&K,@Zh[Y#<g
+%g$T)4</c!P?DJ3r:Vhc)1Bh?d<O5&LiMJA5QR3qpQB_k?=oqYgQED7GHJR?U&FTAemEa2%QfCJpksm@kV@#uK!h%:U.[s#/75>E0
+%'Q2VFV%%ZMXG5ST:#BAu/Z&MW^*!GL`^MjO3:p+!D[c1VWpH^Q]s*uqacs$TTFoA%3Ptn"%ftf,p?pmbNX:mFq2T,F#GE5)gCA3T
+%0MM'6rm<AIhSCeJW$@j+YAoYG]=:s_qE,_ulIi#]bIX\B)@7hQ=XO[?nuDmo!2Z5MRuj5B?"L31hGZhBOee5hGpGS9.#+dZ8P%>"
+%5Ybt'@35JDK)'YLkT^Jj5d1g[5M][LjuqoXlj!O-1P$+efCt>Tnb/!b#+Xg7\c)ru/Bn/[.llp^9'q`c-H4<B=H3B5=B^/U&-Qq'
+%>QCi1_V^XL#m/ReWdjTN%JoqBNktut;&mp47E"`\m@t^ejBP*&7P';IRbl`&QYu_o`+NaF!F]Hhik_j7AXC=ee*6j0ZDtq014VBQ
+%R`dledQX27n#,c%T:R+kEgeJND=ElMqSuPPJ't!r<6ZJi%<RddL%H]7a@<FG&km(Q<Bd4:"_h/e4fM<j(ka'\^qDUndeVq,=tHPr
+%ID!PgEg1iS(oA6r>/:MMnTr8.kRRK&EH>NA,2FJnmT2!\S0(<[`^je4UojJB?la@_bk'?*iKk/M*Q!(Yj!ns-6]b4Ieh@EN6Q%q4
+%k[ZXDeJH!F#YNS6UlfCOV;R*h'16.D4XcRSfYfQ[Ea3.JO`+>u/%GD',]>lgX^W!bd+Qame7r7]=U2REpdKq^k]<$<1K\)tCJ"s0
+%cr]EtXZF0o/0pk[4m4H[Ae#h!>OboFd<C"fDE:JDf^hPI6ruIli03ZFKcENi@<RX1RV3mq,3_Bbp4^#ck/m:MU>kRE6,g-W4m\0(
+%+/-_+BTg-ee:[b4CBXT1G)8OR!<Njl_OhHt1jXfue(_3%I*cGs[00>[,8o`#j`^G9?fpA`3-d^]'`NH4C-:g4LD&838@&$Agk7@n
+%+]TWq,@FS`E6h=.4^6@^]uk[XQ[S&oo'*7M5fmC#J=J5=+OTIC0m_Cr@HB0gNV%]lS760"=ssdW'D@<8oc=dR(nbN=9VF.leT2`p
+%,WL[#jK_X?7HH#.B43Vc^P/MJ9lM=R(j*A^`"^f*_+gVII_03\Vs/MMYcK6<I9j6$s0s-Jr>BTnHC7oCjL177\#:43?fHu$pF63H
+%K/?sj2V=LeqpER'-=[d].q6sA(&e(\b7dmH%DK<Ag_QHC[4KScO3aj@,!;9ZE1,&DiqHT22fPKlD0p)ukD.>O&'ore]>UMOV$D@u
+%Fch=F\(AF4c(OEGd?\7`m@ne?r+7duRmOp\rpaP=.4gRa(NhNtm*DjR0oi8I24Jon/D!nk%HkIO6gF0([##0\8I_W%EV0TF05\^8
+%pt99ai3]!OYg5KIOSM1h_In/m'[d]S"C#+cQ\>QTdh6Ps?-<DnbE9pYcSDDE(-qilK)c3dhWLqP;"KIKgW_-LI/(%!cYSur<G/a'
+%RYWo5/L4i,X)>6_7)k4>?UpjqeW:nCZuRRaWkAA4Y<Yj7j4-#*O!f&+(]d`$eEnG._K>e4[DZi\$EX0*Z+p*UA)N+t)uT%3l<HQu
+%*MoOoGIA*kGU<*$3MKe]fTh[-o#KYKm(j9V$]qKds48UfZAfi*]aG5%XRGaT^Vk_BJ62ZiH<ZoOj!BLu)=_op'(41"TG2fG$*tHN
+%p%[!I)O@;%4Ed*"h)66?b_j@:A-f\]Ke_:fnE@!=-aVh"p9XFCU"M.l=_K<%'3U\W65n%u(Y7G*o:@9t;E3Z"GApi'cVk5QnTb#"
+%M9W<?gO-udDD06hX'6<hi+_c>J(@92^$B,N6)5j#I^.`dZi&^I,s\5Eb.XubGeEH.N^YQW,O]F,drehK0k/O/Z*(s*@c<0?2qh_P
+%^43"([6K/PXmq)2H%'uc\3E:G(JgBC>C!g*S'Sd'@ZPiH:-0=M'<A5^p:I6G&gt[VICOFb,*(Ys)cp6[^/(A*e`Wqq.(8[Cqo!B%
+%It2JFmY2[p_p`aO0b>>Jo/ImI19\IOV-pH9RNC?U<R&aHhYj!YHi<m8juM7qH8o%%adet$YhRqADscep*YO`3[+l\:Vp"@fVEQLs
+%\<0S=@8SE30pigFNadmaajElLr=/,HEbVmLg\\ZKR9enN'#\(LR9Gsk6%8P+U$R`qHD7!GkVH]AlL31[4Y<oa?RO<Qhi"B9TG7Kt
+%Lr0?tX"dskUPR5#ol2XA2X`KPZu59t7Ig3*gNI_Bd=rE4o(C_smZ/95,Pl:;`::E-IK&IbJ;a3/MsbVDpp3@@.b:S;D`Yh74ETR0
+%=$;Upn^2!fk[GP]H&.D,n-Lnj>U/LJ#nt5JC"sk,YHca"!B7amX%\jmi:@s2Oi.$CLq\?bNnKq4_Cb?ncHkP<*5%p,fs^&;kHcB8
+%BS1:mhuJfo,V*7"\AYX46d.4cN83>q7OMZkH?VfiYBi+RpJsq]K""dk.<[3G<19Z)?C,(JN<EB:.`.7F%D$diE?,Hm`((O9Br6fF
+%TFfQ]V7sPT3P*^X,ei_bEf*bg]+=t'(fk`Y7(Hd]2?HnJasoQSLm-e?&/C.#)EpZ#-\?4!EhG?8()L!ciOZ6]6VA<DMr0P>?X+6f
+%_77Oho#;M(%!0)Z3p@qrK!$>U5o^+9qi3?:BcZ?^02',514)e95Ne<:#5eiS^@T\Ndn`2eK#ZM#L^X-(CU'\/I9>WY!DDM]f25;+
+%c2!&<q_UST;JH4/a^_,/XgLu[q<"'r@<t?n^/O8lk&?QBX"Nh8,^Ws3O-:@;>,SDWGVRU`a<"@u0n,:`1Q%C@]*XZR#!m7r-\[>,
+%$OtK,A9`ou8+![@UJ[(Hg"aV-IaqKCZ?kRTOsJ"GRm(BU>d9hdnAD-PJR>h0W.R<MZfc>=X-*s[IA6T:q)<RT/>\=a^s@:`$`pmb
+%.mEq^&"5N-BERQ3MS5dZ!TZt7BT5C$O(+TlimF>L+c*E:%4J8h+3P0engq]">S8gLM'QR9EPc,VG(P)LJh#OsR3.Qd7g?gqK42]U
+%R&obU*8kF+-pi(ZQL4W[&q3^h_c;8JA<b[El3FH6Qn+A;h,gW:,"p`_.REq;.>&s0%(o"FR'VC!Uu'"VV!HhIW(t.]C.tCFM]%Ob
+%FnQqZ3HpHt^3"?(fFjYZ.(W@YX!+-9SHm*XFCAmi<(7T)"*P0maX`?a>BE-s8]FdZGYehNXu]!;QQh>3*\:OjIL_2[bFd:GQC&;R
+%W$99-H..:t!V6esGB!gL$<T9!-Nu6pRk@4!LunebJKJIRMXd<(73F`j_I/]%&W7s:n@<=,%j0)TZ-k&s&`uH)kj/H-Lf)KqqEG'4
+%">OWQ8%"LHPI1DUc3jIr\RgDb\3Lcrk,Ph]@7_^lI<kc1GX*bN@dO&jEtq&D(fdXLp_.*@Uml<068^>HC]uFlOdm7=J[g0&Lm^+5
+%;sFA,Fr0g+ef`0dXA+rD:0d&i`<HcKn<h`W=t!dk0Zieo<V8dCC/b9In=@X?U%SW;@)RaF<JH(<P4hk"cFgo1=9l9JG4AC8e@_[N
+%?AdZq-s\7DnIUK&SI?do6pJX$&sER9TX)-<kC0KFi-FWkos@9Xp7MjHB?d@@-T$)LBLSaC3XY(?r#Em]9H_b(o:WD*,Wd)V4W%u`
+%9YA*aao35C9$s!!&CF$PJ?,(K]$ULW\QIq=MCH<$1f+fV;HQJ+Fk+EpVGO)==-WcmANMFE%\PQeo;,Whc!A0&7uSJ*?;2#il;Ck$
+%ne>*,EiX7W&:T[Ia]9r\Tf@aT<;61[`\H<UC#Q]Y:EgNf@D]@ZQijI0^EJ(]/TG.;-!rN,Ke_6CN'cGY8=6ZH;dZ@M/qYn4iArj<
+%'p,PnEKfDiN;\30\s?/JYADM>'8DK)MEroa4B7KKkn63SYYu>XW46`Afe#>.cuJc*q%Gj^e.+biG)EcGC8_AB60a7T6J81Z6ie`5
+%cu$>S/.ira(aSe^$TGkJk]kMdAC_&ZbknD^S4U*G3ksZ&OD<\uLjQp]5_]?AK;EpLl0Z"[Eki3pF[=Fs?^WBfVta@OiQ(9-L/%T(
+%^Nt#iIrm.L\3X&EmEHBj-5?-0="oAF_U(Ou-/il0j,KI"<SX9cJq/'Q9Gr$*ALTL0clT@rL@RH`FhFpk`0s!e]8H`-&.D_(n],RJ
+%F`(@S:-N$FPoB"6/MYIWW5CJs%%2h0[Pb42mJMegCcd,a$JuDBj_5h2d3!kO*)*ge5DT0`XkeMVkg'lObF3()LEbqNe^++:P&GB3
+%[Pfl+a_m@tR[+Q!?buuUep7s!<K^Z/b.F*jTG07ZA5l.C;OMQpW^".I;RG'r,*M4^;2C>g/-RC4S&Q8TksRAK+b\Cg8Icq,"6LB2
+%nkY&Q,jLE:q'.03Jse%VgJiT0eV]!W`=!d5Nu6Y3@aIPrW:!b'`aQ\@EJ6S!FWUcQrNm$:_6/H6('N')n%`+_e-(]SUf.Yj_T%>E
+%U)=n,ODRTX/QIB(3$#cVnq=!5o#bg<d>PK\'$:M*p'bb6U?2a_We`-U%uqhfKbT+1M"s5Hk?[&"&$]KDcI3G%7+e;sfV'f%ZLrZY
+%Q+0JUpiM'/cUMQMlWI]uLfMA@&:$I$AI5UgC0OU.JmLmO.CqD_#qtJNUbR^%cF6l":b^?FaD)@!(*>:.P87\l@iC;jQ"u#[/?1t9
+%jK,CM!;VbJ"hG$JAeE(Vi2TT]KfT:n."VEknl"XaZ'6meFafE@+lH8n1h8s>F?&UN=>HJWJ^@E.23*8Cg&eYkKJRVT,p]^^B\Pt.
+%38o*L/_JVf"lu)pU#W]7V)r5>2,:mbNYFgWp]Nj<<qXa[riP+62`LeVlSO^M@1B3;ATjX>;-nPkHKO;W$.0*WF1Ps,K3k9S1o\Xt
+%2g$/XHj[lg*n#YM^oe3O6q@C`^AX8@[pG@HMe@`W;@d7]5RD7"dFW<$82EXu"G%3:Uci=i":OFRm#0X&CD%hS>Br%><,V+RU-sK[
+%cZA/N,&%8VZFLGdD+1+*iiNe]Se`p9.;kX/ZH5.WeJUgF"h7H)Z$hMDQjjKNr@E'(b"iSP,0nYOf-V*2CtTI5D^3Fs'Y(2%6+>EV
+%r$9<L"D\;!\&C)S(l:6s'@"2@Y`:?49L:a2,0tu<l0ZA:5\E1rEL9T<"+c$KTYe]ZBYiO+%)HPA;7q`WTi%G'kl6=r5c7`A8ZF!G
+%V7s&6oFN'TqqO)8olUr0f\X`*E_r`6L0Qa`.d,7X[-fQ<#I^rc>6u5s0sYQkrf1Cu&::=>5S_81dDoM2;&Vlp`$lP&$`V4$]snCk
+%b-GGWJHaOGZ!.8M1Uj__`l$gKC1I.PY`'8Ao%>'p1PIWQRJ!YQa2A;`g>Q^Z2F@KoXcm6MPFBus0,*@RiG1F1Uf"L:0A(m?cnuB\
+%J^^+b8$83R:#2I:/?(]rK*JE$2Q$V7guRZMb>.'`".$$*JaY-Xpm.,'oJT9N/g[^KaGmMPo`BRd"<=jVj7.pfhJU<=N>F2=SV$a/
+%3&o7[f@PE@U-Dfkp$_nO5Q:&RJ,HpNs6tO<di\VKDuRperq*'V78cK($0F&?l+a>m.Thi"9&/n5eFq]ZWF*$ciadRh]G+'<o5655
+%iSWtR_0_B^0bL:6>*>NX%@5tn4$NA9TDtrs)C`*OiR#?qg*#Dh#rYK,^#!O^Dgm/uDJ8o#HlA4rA)i\6WueD6BqS$C3q!GqU*^q&
+%Hl$`8_MrrH/\_)WmG2Xj0_Ck$#g)'hll-HhVn00l6LW[2M)=Pc^af\)Gd#A!rVZA,f)m;@S]<^oL@*l3U/1POL_H=HZeMA'Q3Mnf
+%[k5>kq47E=*e8Qu8Ni^O8K%XQBD<BL0#G)%gJ$cn8DUT*HVO%TcgTZV4FuZ5IZ]3bM\9dFlqZ<F`fBPWokm^=%,pksnV^p-8MnIb
+%4g`VF=QF9XU_8m[1rVC<^N6lFoPBMWkL-KIh:bo@maG/Uo1i53oCG%fqd&5+rRrTnr2Qkh\=.9-BWHOua2!"\GFIN\TAR367j_<F
+%L,:E?9NW<P&9("+@2[s>Msl+DkC+LU@>`_Q4*dS8XG\tJo#856S;3gDn$L&X5JM9SlPY/Uk.:Hs*^c=SBcB"C9,cf6gWF(JYP3rf
+%-ou_.O8jC2KG[$X1?s#=C\'JL^U_rdHFiD`?+9cU[FB?T"BGs'`-ZA"HD'GJIDj^pK7G@9C&W$P$\B<7YV9O,DnXW^Dgm.VYMYma
+%e>4MDk[R_HLYH[IHT/A7k52j#q!R<hme;jOLAX*o=kYjh:lZJJ!qYNqpmnkgmcSf^pYIsVLf2?mGkKh)X^4@r/<'@A>Ip6XbPf^Y
+%hF+27ZMkV#1h,'cGc[8+5nr7H(4Y`CgH0hZA)V(Y0$(fkVqk24FV?_U$qn@af&M%Ime"+\"n*Z,`1?%VB+Re&^lEP"%cf%qC\(Ul
+%^V/Al-5?@cP.H;-1S&n/gAktn;;P0bh\P,Jr6G7)[%qNO$0bPZ/'r-E?LIs!"0_H*>C?2:488Wni_A:QbZNgY^M'AHj7,H,"obAF
+%^A%GoHc>H'oW[qBs89A+nAi:jS8nH;k!6sbd:Fu.fcAR05klQ'o+!gbGPu]#M]6GsGl>29f(f7-GOB_sLjZT+`MXk2B0ZF^T:"tk
+%m.V,8RDI-*\nIHur"dGQT\#U]_j3XEmSiCeg[Un#r'\3=9L<kd%_IKpnM*L<2&OQ1'&$@pBb$8+D[Fe?l!iOY]"jUH%ffPnlB5f7
+%!;_4;]b%mK\>SX,6!TpOR*m$g?Y4b&+a.FJGlceO8CJ(`eEA;CP]D[/&H3HmfsSK3PFeTr\XiBmK3"D&2JFL>[aY&^KM`3*P2spZ
+%EG`RR/gQ#E<\8/G5+O(q+UC[t_MlUYcK$_oM\Hk3%/$gb9\UZ%SJGehq*"S%KSAo%N"^irYU(JeU^fU_\<ek_:l^&=_R#E4ZgkdU
+%[pbG]!"P>NJeL6q2;AtrJ"mdr)g7\B5Upgt96*0h@17-fJM%!I60eGlC76l#%-U.sB(^tJ5o,qpN/2%/9F8>?KF8W*Jqs\/*_;`h
+%D]Y]7\3&aY9/ibXD^).\J?Q!f]UER"FCPp?*7^d,$,OSdK_n8gPhM,";LlJk0uH#A\If6]9ak1KFfm0\MKC_S'>^?=<ip,AXEG`f
+%*_dnTD`JE$o'f3gVISJ?K2lfD\!;RIf@jKdZH0=H[Q"Pc!n)f[)DdmqoDj^rBt1s?]USs)9CU0"1SbR7K\cJ9SNBE"E+A#s8l<FF
+%YB",W,2(l%0tjirI#.EuGLA8Q,6X+Tg-L4YlI%IDdfA_:YSK7GI#fo4PLRX;9Xp%p&_sR6-@!>E)5_Jnj(-G3/i"]"ZY6)0:dB4D
+%<!=rs/&GJ-X]p6"j[Im"F5%iOdBASV^p[]5iAcA7\sRF:VD"/qHn8r]Ad*%oddicP5Z87AFnURaA*tmF,AmYe41QmUc:j!"P*GI3
+%G-1/?o,u0bmA89%9aN96cQp,@_"oJ@:?Wkr3"[_bmES[!TqnFM/VM/A%[i0XTQq'SB].<4apE*)m&Mo=&)'@YQ/@CmEI]E\4=M'2
+%/PXbMWjK/i#ucudK_2\Z-?1E/a>`,46_JSAWiEQ3)PnB.oB`Gs$>ph[JRIA%"R#$R4#EjmU'lnMXGBngdZu'XJm/:45aL:0Q`\Q=
+%1@_]LH:ch%C>#a9?_3+8,bp*9r"A:<O%jXd*jGp[*Z*=I[U_I@5(mLBK5DPuYt5[^]f.[T,iG&caC-(q&N\;m&2$Y/M`<Y`O@.f-
+%,ul4+g#0[-+Z;^n#eKJT\9V:I)$(sPeru`U%53mlY(Us0q%%MT&5(pM"&WC%?m<$4n-c6/G)GJt*^iY!)sgZ=ORYahR4>#?4<$NI
+%>qGk-RF7\gXSZ*;$>*A@r#(jQ]^JLCgl<\(pN8T^]3=J_7o[=gD6Dr_hjD_?H1q/qV49$[><+mMjdF<L/5N<,+!N#!@@`0gmpR<K
+%Q)mh%eAJ,/(XRDcfJ<uZ?1;hJ?#TTfKCZ+?rS0],]-\TaoFR3*?u1fTU@\TZUt7d&]!rrDk]4EjIS_lmkC""8f)#'VR1r?\)TA,4
+%Z%Adg1e8)8#RHDVJ-JRMTT?meJufG^%\)aLO_6\5Hr]+68\SJAM$gu_&ui-(a"sS>UbbYs2]t;;r=):HoKAIZKq'WViX[9G/0FX<
+%Y!X>g"6-D]7Lq9b=`Q4T<(Y1qcKQjLd)QVTUs3+8RDQA5GHF,<rrWuX*o5]3P\q$6SS7:26V<;*p+a)BE?PSE1bsoM^e.=cirBl_
+%]r`Z]rrPtlFcV<S;<l#&#c+;:``e*sFc\1@ckK$V8f`[NWte.RAYkc^W6_5V8!dMTQu[-1pG%YaKGi)(W2eYr0Z=qbH#J"3^WLEU
+%9I&16MnTEgNRGXggi7H"Lk00h4#mSb.IoG1Dil.p(+fO(_!-H7*'gfkftiF=amS\HN!5;@d-)J]h-6WLc'.H#e"5Wm%(T`W3[Cuc
+%jFO$r+Og`q[+,WWR7f\dHDUtV"c)(l3=k3a:H)8!R=iXEIA^g?mR@XP@U(\AqQC&9eJDV;?KKn^VRJbQRC#Ocg,N?BmK=Xg)@I&F
+%2[9UIY>%]P%q!i-NO1Q=Yb#\mHUSi<E/gZA_Z1[IKs>R-Ld[@aOJHa@\qYPSd>VTf7Z(uBT[Sl%52njEIr0gV^D\e"k7^A'-A[Vr
+%%TURS,gK>N*)B9E!?trJC2t17-G6u[Cclq'kpe"FEAZ[7])7R^au.:s\)q-J/;?Q;!km@(*Y%Q!OdH.rVuTf!F?pHXfpDR;hH'cW
+%/V"M(.g`CEgBYT!/<rd,/UO7R,r8727[:]*UK(PM^nTg'C\MpF&UKqn2U_7-bP$MC[HAtQnU,Yi:_#)Yc.GshV%?fRa7\Sc&6TWU
+%2akKEASrYj"L1h(/-GO49Nmp.g]]#6]!4mr>pYo`%3AJI`ePW*SsnX]3Pu0BlL,G:Ap*.3fME45or02t3PGS@FgDD4!<uEDE<C>q
+%ZiubPCi(I<H8\-SPhRP!'Y5i7ADs$_H84R$^cj1.o$CubmK"E'p]q7jZq6o8aN+E;%:<aoeUS0%_(fn1c7CiW1o-U9eM%2*+d]Ot
+%m/RHG!*,kmb"R)4KPad@\sCKKeDoakU^ER##s:sJg1+o8(Ej^jAP.@p2J2W#CqH_Wq;+6qJb9MN1*3J]R7proG_!p41Vtbc-,hf3
+%b3-PpW*6j%cr.b51BlsQ\?i_E_g6YGRl+!9Pb9&"ese'8!2pX"XA-\:T@pO>R(-PQbK,i7rmeaf4gRfgMFf:9dX-%`.$NCV:K7b!
+%I2_tc'R$e'mS4NJa%@Y_883'bKu2?3eabPT7/r6Q;FPPZbhHX]JO'dMkYON>pO)?cI18pC$NCYQRM^t+npLP?-L_<)a^>3>[_.uL
+%Rr6Z[[IMJ")%W,+/m9r40RNnodj.r/F5lhkK,j4<MHd*i^ors^l3,bVGd;_=Dg0r%ggekgSJ#Dh[N$:ARVVl=E6q09#__"VBg_3m
+%ft_`I#-rp4o[j8_BSm)rO3Q&5hG5J^Nj2D2$p1\1V,gH;hb=8nf_mLrYS<>r'nJGX.$@fIS&o/YnEG]tK)/WO=(*=);L(#/BZ&mp
+%O+#BMhto0i-$IBXlfc3@LN+HSJl?13#-p@ooEi\ha!7BcPbqh_Qj$=*H/'/m=?BB6QpSL4=S'_5YT=>M)kPVq;oV@#1m+*AV!$PE
+%TeLWL?qm?a@Zg#A;FZW]TSeH9P[-<fc"[r@[;K-JRfrl&S"sg!GS.''e5;GTrc#Gn-7=]P.NGajl/@K&XC1Ye?B:YDDA('2IGXFK
+%`@RP<Tdrhp9TaDZg*FUm4'-O>Vm@6l5uoop6:88.-lrF2CTN8L+jlQF#'rp/Q@:3omQEniY6s(k.;Ko.EE2:lSu;A@E+:k\O8Y$%
+%+hu_W@mjdmJ<G,]7De,AYqFo%X[:8q'@ii`2/U:+ZmJ\q3AncB-pU+</qp`d\eqa?K2N#N/a67hQ4/'UQGB4US95-/#5G!O"!qd\
+%@4_OPUNDIu=,<#6TWs>s,O,a"+-'R@rXdc`q7EGSPGT,ujok]:<D"f=Ka3#iU@UXlm2l2J*J>s^#9J0$8P75E%$I:i^P1L@<$8;i
+%Ml[P-iYac\&+9V8!d=9X$O%Yn3NOTG)aIXJ=TrqdZ+fh[]?$-/p>!2QbOauQ+h0j\/N2@Pl;Q"1+H+<9oIR:Y,S!!YCM`-3^S\&%
+%;=Zp6l-QHZot<F+[Aruc9ghb.]dpp;17roVP72%pb[Q`7]Sg/YOsT=,f]omu"[=ZfK_pFi42Q3p0&]W7QK!=k7GB+4^KjP55h(rk
+%^KqZG$e='9*F*]R,F-Es$N9E?kA=^Q8Oc9!qp68gQD%At7:s]P/D*YT?dOQXXr]ijI)r[9]&Fu(J]t3o`ngo)hhq%Sg.nn\Fq6=b
+%J7pirNXKK3XW5M6&`n)VF%2#CHsJ7S+QPiGAh./9_(!r7p)[tA+N.+=/OGYuH#s^A#HLW1<5g96Q4`RA-3]P\R0:fHb>,[^d!LG#
+%c9nmN/;or3)(Qo&j]##S3]g%0nYClHSeG+D0:]T9FhF+V3b.Md00eK=/L!fYE86og+tX9;BcI[q6kjEROX$BpFjX'UjNOcM#1X7B
+%]7<.$dZ&"Gb+&[PnH"#*ZELdLYZ\%3;9[H+or[iU4K*ftf`B`1P2`d@ieUPtpbd%,`*neHgQOkrE,9YZ7Q(]E2qTtojDCoDlU@4(
+%(?@;Do:h8;U2ukqYo7bfKo-QY4KBu0:9=.\:&(l9FQsu_J6\[IP2RBF+snm=HC#oL1E6@Ep619iO(?d472ho[5o%A:GDZ=TU:`NY
+%#_Ien"mFZcOf3eCKu-"(L_e$9S=ea.+:Tcb@AYDKkhQ%rl%qqq^WB4r*DSkoSGFZga?,Ne=k06W3b\-mS)be!H>"'+ZTDrgiBtRm
+%d_t7_oO5VeAc@X:W<_B!KY6i^9JnklRb2#cBSqd7T,T.dm._R`.a;iRjec"98[Qe)5*=E,<b2j[.!'END=R2(7R(kc66IZOXH?o0
+%)?;I8\`Gn4[TN3n4*A-)X>nZ`4K9rNqPb-Y[E;DUIB82SHEA9V`:,$L&F,cBrKtS2=:oY-Qe)sFh+;Pu&t+`K-o;GP=<S$*`)i`R
+%&Ca(m))5F,5b&9g^8W>aQTTJl"Q.fR.QSA<Xc/'h_0oeT'uJY)8U-[E#$&>\IhYh)UoVF5GH::0E.U-ErbO1C$/&'+@ndBEK,d(G
+%rYs18*R&X"LBAiJVTpcIf>"kY'nMa.d[FPi(<[6R?=%j]!\-VuMsGh:I$Mc:N7ef"2!*YXmfWZ\+ikPfB@s?uesrVA^G^bHiF?G5
+%%0\>]`YL'c-&]^KmBWf@e#lZfE?F#&>6/4V^6J#qK4LiN-VG=5_\_NFJL>7^86<f07Wsfkird2"?FW"X\W'>FqTI%P8$IZ0Ll1If
+%r@6*$_K&S4Nne):g"_RP"MANKKdqrnZKoEaa#XRfVnh3M=gb-2C2h9V7CF((4M%gk>;9c?d`Ic'UpgDZVNA6P$ilX_o,4L1/h`!e
+%<O_2<@qX;o3B_Xjba]Be@9=*(:?5nmU[T:T0:7';dFU7&lZIU6*qmkE*Cu-To;Y'NN2/.S'qf-r"A9+1k,^eg&_`E,lIqDq\>B#J
+%a7MR7!U.3J!HE'C"LXZ=>HQ`M7iX.gO5Y!RG3"pD47\ab(8S-k6';k<!!>2Io+G?sp1FuCVe1OiE@r1t6Gr<:*j<dE_#4S^ODd$/
+%kCl@2fJj_,8(=e3<12]E?jl2'ZJ>C6i$ih2Ge#611Q$bd#.Z6LJ8bsPIqRr%&QHkN_Je&%6?&bX$-SNki7h1?j:.WG@8+7H>@ftM
+%8N3/2:\K`m2A^XT?$X$6?8CjEE]O")%Zq1K^2>Ve:(g`Pm0Z`)*+r>\3$$1OC^Yc$'Ll>7p'$0mL-3`;f/QPrR1:j>/3mcC_QgJq
+%KNo/u%VB1bD-Ag?UOKeL`3JlU6U6]OX?/A:?:J(9n&LepC/X^e('!jpI97[&K+odeOi\3/O$&U-Iainqkl>;B<R;,-&9**A7=(V@
+%qCn?ae&]ZdQYn.g^kYYsV!-b,TcpI1m^];]9ncmEiAoliaE/U-7"68/@u5u8iY8`<HCG157(eB(jee<>PqIbf3f\Hk<LBO!+[.q>
+%QB42$%!G#i_&ZC-i%hVL!@]6]B.1#:&Qp/D9pQKd1>69(^I21,L0ogg\8c(6FbZ%G5S7:V+/@n@^rmQc9bL:*Th%_Tq"3#=0Ok*1
+%9D_D<,C&k&.b?XmSm4=+bnr75dd&q:1FCOO4XdY74F5r0(g8@T,8+\0?cV+hOCl!UH/D@%)et+LH>Wc:1Y+*u6`oICc*Aa#gOYh_
+%em;2g$Sk3"rnu%gZS+<=B29EB5b-4O<^2BroHlj0!BJV2hRrS=V,S,aSnA`K8jF&\#mEt6J&cqghFZG_Gree+C\DO%!Rid6AHehJ
+%2UIeYeB]7O*_i1Uc8<C6'sj9tBuC0tT1SYlBfrl&&?<mB*J'SD-_qLK#;rGb]KLZS871]Fp-m1@U$Ot7,.;#i6Cc!q>:sKf7(d[n
+%8,,ih('4Y@8dj$MP%2^?X;1hjd]ZJ!i#qi-F9hNKoj=K;M>@<!"D2J#rZHb]7UBU(8:MCS+bon<'8$#)62VHD:(Q9$kktJFV[N"7
+%BBofjLMSEbb^oI<>M82/CWZ2u9&4R<+U$B"Bg;dc2mdiPTO60b_)$2kr%Or+_<<*3=sQ`rb`@ucj!fASl#r,S+R;]5S-YGq=!aDN
+%$"aT/T@[Jm7j7'qlTb?c5Q9Krr8g`E&$Sf&iT"qO`PDOZ.A5biFoV*[WiLQZUMD!SNcW:S?[g(4(B!/R9t)e4X);'J5tqfek5OWF
+%oABO3U-IT6JYAi2rdtenjDuD%rKAdqqZsUSqdJ"npU6(k2E+&u*^>8YI:<pPgR(6GSOHdRi_m8)Fn8ki7.8RK]]V$^ndckpJ%j\8
+%Cg#*ClhDE9hsQie2YDH8j*-(KN9f1u&qN[Fd5LsZG.e+^oUou7mJ>XN?`f`%bI)-5G-1qsb\cN%5jQGep$:FKpN:p#*6S&h:&"[^
+%.3?fT4`<L@]:O6A\pA/HlLuE`Fe9*:ajoO&8'L)eEDo(&CNUS#NDI9:GFc!%I=gC/a6\c(M#6#_L;/)I+&HQfY3Tu;g!n*hpA&I@
+%^\r6WWMJ9O-B"t*1j*bfplcbA!]Jp(B9XYiH*lQ"a'6.pC&6kWq7LiG4OUg/YHGJH$]`JfqfF>;H3j/#j7_<oB=i:<:5Sn.qln##
+%Y1p2U^$(5Wjq-"8ge<4MjQ=_Z7iF$m?B=pUS*?tj>h9R3Upb;"rTsE`S*@ulGTDTMB>(139g>5Ege>JrR1@-deQ\N0/'n:R9V:?k
+%Iu``:Y^bG%5J*!FA,F7sq`HcU9q-RNXPQW89XESLHG;3+q<iD$eYYfb[a/"o^.eRIb<Do9.^;'g=@ZXNg&OGM0m#BC6^X1?/buu*
+%M5DME6CE%N&sM'DAVG+eD8UD`8_cd2D<:"CEKdl0qf+8WjS=24pptlhbC8TJ7#.BP:2;dE9KY)!&9eOSJ`\mq[pSO:gO<m9n(hO7
+%j"8:L=8grPDf6"hPY,c6FWGuQPIiqZD#AClSj,(]DXB:g$u#AsI=5a55QCALV=6TH&X(&o:i-]<:iY*)S&<dBI%A$!2]Hc>eMDTt
+%k&@_NRn/"nZu'loGAaiL>\uc6IlFptlgBCjr6487_V*7?DpKEl]5GsC:>>_1[LM6q*nB(qh9YOEm_A)V,(t(8NTFT]:HNTj5*%lf
+%G+P0a,^ZLUZcTlUFJl>2N9i9TRpIuQHO0WO$(26+Y@c8h`Y-dQXDZ]i6p3l-FqJ\4p3^nYqWr;NP`t\19L<`0$62AV5EToBKH<.]
+%_2&:UA`NBc>5B`dn=gAgL7l7qk)fPA/X$l=^$5pA]0dM<VU<tsVOAeXLi$o0j'G.^p=^J#Sgi/mKa0h!KfTjN8Kh^?,*gpOF!q[$
+%BLCD]EGl!BK'oR^Wu>$7qkX55`c'EXD!aVs&ZuF8>[P-+;N9:]@ou"32@Djp[Wmh/b[`XMg*\O/LaBoT6'r+d"[Mpg?1TjKlV#tp
+%We^D@a&\9WF.)A>`4AbSbM;6Q1r3G>eFGE9W[LF[D/G*qZ<;Po@tK&9*+7-cZt7kGGV-JjH;P[a]R:R9=q7NiVZ2j(Dhe:mW]f)L
+%7i2^h]BNtr6iSTiIV@r-'LZgW8k8pkPN2UQ#d9qO=>]`t@7ARD['u&OJ_6f<9Q*:*Mq^d%SlMYHk5ed'cHBTTA(nF^Dj,F)9almf
+%YQLgdJu%YA9Hdt%:nM8(A68*oE!?prf8XhK>sfa62FUG&:;Z4Vr#F`3FI4VG9hat&YT$[(#Z2E3A-`*M4)"UgZQ8PJMVeH%'0lT1
+%WO8iQ6QhYa+o"5rG'putAVM=[[H*?p:iQpgBda4X3WpXHKh`W))0;boW(E@,li<_[3)d%H6q8DG"1*NP_<Z&HB(5L.O))RJ*%QLI
+%4^sOe.oHZsM;CddPpfl"F:;^NS"jhH=$\D<`U,/l==-tOC8)]"`QuOaA&];7B6",Je!a!7>;9P?+4ADmq+82Xi7:>t*uR%a<FU_\
+%;nc!_9FbD1'G$.@kXk&o+g[kEl/(%=l_?tAdVj$?U.sGVlQp&YDN0BiTVND^5c'qnUE"N21mYp2mg_ISPnZQ//dg,G,_t(\aFVUM
+%Rkp)>dq!i.>[;[3^ap!pkgF*g)U<-^],^(L-r`:@'m))/9C`q;dN$QEP0rs:pAj^`-;ca_PB"@fOs4hC7d"eR3L`TqH^<T0[B[:p
+%nZB=^QREk\@L9JO0Lj77lR!?2,NpfiABANgS#\qkLZ2XP-g7U2%ne6MH>q[i"0--KosbIKUhAIJnA:+:C<d_7#(@g]gG0&TN&F-L
+%1fR@M`nap=])4'446l</&c^k3gI6S2KbS-<htLt+9NH:gOG(Rrp.6GaX></EDiQ-;M<Hl6>JsjT;%khY3l%@O\hd%)%SZi7__1"A
+%,t[]Ver##.">isu!UmiN>uUtAh1cGDk?3kfT#`h.WQk0pK?I_U,bsG%>Mm7TYlR(8ZuMc_l:$gE66(o+kdq!r5M:<M5otYHRj9AO
+%Z'=WK%.Os6ce7WI!C/Js5RS!"!LNsqI%J^QB!JNWeu\BSD/f)$b6\;D9;-K3%6$4M"nO+#>D\N8#=)=u@AK(u;iJR(]hW5>M!G5o
+%,nN-<b,mc&fuss.5X@A>Xbe0iK/&4='.6goDEj3N0oK]5H9i(:n#%1XS-s!\Mt@h>g6Xd[TW<Xsf;BJ&4luj2a_2VkG1_Q@!V6Vr
+%0iE$#r9r"s,O,Q42,Fc*5Fdt+TH4I%JMn<@/h(rl)Y+);#F#XIAN"%Z=];'#bQPu<,9GBM'QIPn;a^%2ipk\Hc>pL0"6D+g^:"&$
+%-@pb;@/"hFP=Q^YK]9Kd(^qLYE;HN!lRi;$GK^DQGT'#\L)@nW,q'JdJH?TNV$Z`bLCHlL_CcBN!(<^k%TRa9GT+kgmLV`=f%6+D
+%8D86o_:&IT!hakq*\pW]aR(2HEXl5cb?#WIlT>%B<S,I.T<;UfIQ+)Sr(Q:0kV(Rh<!bTrEQgO_A[0<`1:5KV<j!_p9mQ!a:&mT]
+%Os]"lYIGtN[7%!_AY*XMfWGkc%A8CpD]:@<Ebu^g#k-5snU^NKDLiE8307)k_\(FE:=p()R$WLR1[ZE^,$?2(bd=SYFtmHEWgpJ/
+%c*BOp3A^MgeRFDhfTlSP1oB2sTb'\M"f0P4GT-,p\rlU.hTJ$o;*<QE0JS/$4n54ja?]lu>.`6r\EuG"LaE"$qsL7;*ic#J3k^[W
+%JMeLf]ZC"eQg\&#0GiX=aB#RMdi5,Fc:S9["(s<JDGr<;'KtP+Fg5N):Y^&?C^Zco&>$_]j+XaL!:E8=n.Ni]I'tc6,!"@*MUuQ<
+%$3Ukk(e!f;@gibcF&101OC_t98FD;nB2s<!jc;0@hT_gTd0Hf^)-cCoU7e27K0)4P.=bL1g<prk.o86NKBtm""8lR4@OU7+A/NRh
+%@2BC&_W)&,6a1G?^UcFu@0:2C)GepA@"glBU&421cX!_UUPc@%eopqqF?HU6%,hfpF9/n,<tV8fMQ2]q]E3GrBrGK&ecXoQ3CY\O
+%h32pt_@+7fH@B!/o$`I]]PFlO'<hj(5%FeDjF6L=3.8ZKa3SjQS>;q#PPXda5-2X!gBM]I.M6ANC>iT!+<].%./kr@]"K0g5B%=S
+%W^5mSV4o?+5p`AYdr=/eNuuC-YuRG5&GX(fAlL&gMp_6$Ha/5(DJ]MAke!s'0mB'2,1Q93%ZdGMQRf;^hlmT("@]ErQpQ';E<aV9
+%>QIY+M^buD7i19YDEC-Fcn>iVpDfDoh%d4Si?Ue*PflJ*?'iiZkBDb0e90A]pr)dRk!"%dNHO+<*q\%\f'>JVq]7,pdoP;N<YKL\
+%C##$"ZVQ!1DLL5e?+GraQOK17?=TrhlIU5q5&FrfC-Q3WnfjT,qVC`oeQsI.Zc]gRcSmN3GdY9sjqZ1nS?dDqgKPTZR-d&EF.)EE
+%a)(JhZ^jnJ).pM;1#)\fftPRJ@$Q/\D"emT]pnS([f)3=hVusBZQ8M%m=*)lpH*!AhjA8-RXS\Rl]'S`Rjm*.T;H[ggV,6MQeAN#
+%Am9362U<6%GKb6D1#(G>\=)`/A%$T&]Zdh!A%)8og"u)\,KoIr]iDaklbM6hBb-gj"!,]g%/ofG=CCW(Z6RA3l!/G?ASlPVAf#G-
+%_@:M"Ba5!fL2e5%,[/,pj*.E\"j!U3[c[&8C_XDb?[(k2qjHp1m1JZt/`.QrQ8DT.i;<34B:d^1MB!1WGMfQES>PE&FkM1h>F)ON
+%Z`hg-cf]cKG+J4f3,[U,i]U%D+alT(oCgW"ADH>P!c#>3ccP-#HKr9/e(ai@37j^FA'O:3T)tGKrk!!Fa<Q97emfU4+9Hk`?)I.&
+%Ormq[BCt?5;gd&X.Fsigd/gdAYFE#0X>bR5G[H4DG^Cs_<XojfqsDoYj16=)'5Y(Sf,m/b?`e=te!nr[`9[/ep$?lRH.X&(QJ=S8
+%rQ.s#XnK'g)"%94NQkLN?0>(<ZZdrWB)!t3HgWhb/:#uba*P/SqlFP1?`phWB(OOXbO9ee`dFr$qX<^uCHScs?)uS_L#2Y?J-5Q'
+%IJ%'W2`P8D)&[U*'>7a3]kZEYSo!tbni^_GN<8VD+t$+*)p4^<92?:'1*V?>*_B3K`+C8KX!6hf9f#/>O-kEXo>kkE9=gLCi\o$<
+%NtYB!2,pdb@,5,M"N;fo[g3d^3nL(nQ*_PD-IBEDJjU2UQ;c?KX,G"a8%])^""J)C&.qT)86[8d$*9f]OR?EIiIpk<)-A](c8TUU
+%Hm4Hff2M.\@h$Qk6t6DFWZ4G0cnifgStr0\235ZuW0f;[)u*YX"<nM#A\SfY!*DXsJM#t2W7m(7MpSpH'Wg-uZl%9OS^j0.JO336
+%isoJ8gF%!+'rIi^*_(A]WQq_*.2mD35&Qt-,Z?I0T5:ocpZ@f/j9S%]Ak=Rt#J_5V<a:R1`DV4`AJ-2ZjS9:Rbaq7HLd`CdJnXrq
+%K.[=e(ne`*A5uPiCIoDr7Of0c/W#sqb/:oOk(e$090-mV2)d$n9jdfr;9TR!?@s`g3D%>/QC)<(8;9.o<MDeLB.TNK]/"&.;HS>b
+%r6WuJ9U'Cn59h(:Y%Z",igM;F"_IgT(r2Y#&HmE-W94]'Eckmu!@V&49tDb8JYRX8']SAd;5a+.Ks?mNV`nt&O;76k#]5bho*fqh
+%gjL?0aFI5qb)RtB\AN*'C`WD-`k5DRR-@uopZo.>MHIUA8P;pi$7XLK8n\Fp(i8IMZac(Q%qCPkML9NSDBhk.\tV#Q*":1;;mjuL
+%"(b`XrQE&r[O#Bb(eqnL`mQ,Gr!MJ7JPomH3T`ELUd/ZkeZE#.3,s8-CX:nZ9m"umV/D7Ke8(0iR"D.A/q@LF7D=f>=JNDoAVG5&
+%>7YOPbti$ZWAJ8HF.2Fk1&Ld,;]NMra%2(b"\2JE%B>#9-t2Z/T((Qek?^tZ70T&G'#+JUU@C&'+':ji)D4Zh@6n(;8h,'$0R?s0
+%k\2k<RYTN#Ce4bu=U.KX:@@%_:1C:e`6VLrW0D3fmpu\@/!FX<nP*5BR)@b"S3j4O:=6"k6D-?<lEE#-74>:*R$3t6-BiM[N'e^p
+%,K5HeJ7l;gi(H\.YqQbieN?1=3%,:VQW2Fqco=G#n=FVj>WafE#q.PfSumt\H"eU#pAsbO!<T]$U_tR<5%rX*3=k1gYXES+:#_<_
+%e6+[X#4"+62]=njhebQO7S7]'J:p67knc/N-@f3)#Pc2fk,"j_DHk^q*OHeud:'fr[T4s%WDmiS9^0uLdrh@D=h5lg&#W<l;4pN"
+%K6%U>%YS><&L*MnR\6dj<8slZ5LS+\hG3JF>I\T"D&_V,\@]Y(8.t1Zn.Q"+9jU)?9BunX+k<hEHqs>C5I#+e8F'LV>DjiHi`ok+
+%9P&rq`8fa[6fSfr)7IU6Wp?+IL/:=LcfD)^PbQOmH:LkMX(7ET86!c?hpC#HGG9g;%i^?"D^G+eqeE*W)U#HFg`>`mA:@Es`8f*O
+%p_G$.U6K`,e1/$?&TNsNU]U[li*3Qsa.UYl<qe?I7,$)E"+[h6r2Z-i`3-\!.V<:$ajIqDa%"-c1>T^Y11qa<-np5"`FPV+oMFdo
+%H.3K_)"7g"\F%B48_/2@Tu`,@)r*(Zr+O!K,2#L7,oaiXPkDg'T/<3d1AQ8gbBq\^dgSs8gcSJlZ%oQF+0Np$BItR7>_?JTKRF3#
+%GmI392[t+%24k7?:NbgKG^^XCPk@E@Ad->qD#&1ocp2dj&!o0$AhV$cQC.96gVe]GXEC4/<0loChB5"7l6b;BWeI'q2QQp]0.9>q
+%[p1R>r5I,Ecj)6+l45,XVJ9]NN"\X2g"tJ4T)%J!r&W":+#1G&eaer2Z:##05!i&g9'>[QnN^1mJs.'"fqr+*W;UOeDK=@W1-WA_
+%OK1;UM]k>O!fEK.8qIs=ShpXW0D&EAW<&'sY2@BP,N1b]6VOuQAMAVS)9eI`eMV>$n2u_KYom*mn8#rFO?8AhF&RFlX`Urc?8Gf[
+%FVJRDTQG<n0cB?n6Vh#VlM-YpfNZi&a(gPbUM?F^aZM?,A74\3"Ms@e20XlkL@;t9^MS<7F+=7hZSF?ZiPX/k4MlcH@jI*tp-cTg
+%XkDO!iqS#u#>G%.4%$]JR/^H'mC3A-TnFrlk6.o_,'*(f:O;N<oQ5nP#a`CScXj`$V'amS&S@PCF-3-3n@qO^#e\FJOT$+F5l!V0
+%(2<l<Hfe-Xmf^R:ckPR"d)BIe\fI:h$&9@YR"D27*q(L;J?p!(1tHmn/;sEc*bqoQ!"Zu]hYF7X[)6q(<*O1hQH)@9PmU[E")C*0
+%V_MaD(iAcM:hW6[K;rc*@nHoV.aK9XPR!p4e6T\6:)&Kd?NSQ0B:+&^JL_l!8:.!c'HX4m6dWL*jT?FJ_Qe4mVlj]a$J4("Z$?jf
+%p0(p@_)=&6^faA(KG5k50)2T%I4W==%\!tKIllPFknRqpD]s0fi/@sZETlNr45s@=+XlTtd5tGj>R27bYYS'jjb).;XZh]"$0"N'
+%"(N2b%b-$,&Bq5749N'ob&]<)[%E%f!;>J;.NY0J"ObeLWU.1**(To4<>fn*L57u8]$Sk3-;kYlD$`Rtmg<V'<HF9A3dQkW[%\iO
+%+]<ufJ8hkKJG`.T9*VrWa#)'p#o,@W9TVdQT;ub*k[YaeJbinq,`)f_HgEco]\NcG8g5,3+LuR8nf<K%66]C#8X"8SP%7QHY?lJ`
+%=W#QFO8\:#/s.Y_%G/RUCU1G%W>#pk/r""+^/km_3@f&VNi3Yl$uffPUrR,=7@-.6?Y+Nj#hb2nX:(a7<*_0Y#<G!!,B'I>L*<a.
+%L*gX]BqJcfVE4>La%&4"*hoNfgt[QAEE^"sjONEXoY+F"XC!UI&D`=X'qT+n5B[QZ/\"m;rBo+S"?uD:d)X2%\G)D)D(^u=Dppe?
+%MGg-IT52ui5h!WW#W#l;%N4l@;sZ*>^&R?-pPGsQ=Zt*3#l>&`."p7eG$h!8F]Ra]a%s\"@;_HWhs#ObOm%0(b+KL`.qtd4!246'
+%DL?YjS79A]88t0'-KQU?VPppJ*G&e`diY:AS0G%]fr)VC/7PQ0ep#=,e9*suB%IdXTO&?,72::]pTsSt:2iY>X4N"ZmJJSjN/+kC
+%oIF%rOT,Ig(h_8FlbRW&H+L8Mib&6O@d3Vs%#.?A@9D363KS?o"BrGc3113o+7$1<HgQS]aY\s&$S_D$^$ZL6c8`W$Ge^3X_H6CY
+%nVQIPQn3:%W5:j(A,$#_CD_JGSAp@E*@c!E+UGg$aldsaU=Z_6;kdQsj.KpWVr8*4nIfEs.\&5A0#K0E8bap1^SriF)9f`-$h+pl
+%CU+*18G`P7QE$<,H&%JmU[#,-Wh\I\`eL`dLcmA?AW)Z?hNctQkiF"X@C!=*%iKo=.#i4^XrTR:mE/!'HGA(d0M%'h<Eas`VREK\
+%#`7qh7$e]OEQN<:XYk.2Bt7TnZ(P0GFNHVAoan,;iJ"B+IBp$u-GkIfE,m5;Aj,Ghm7%FpRsiK.,"&cY3;(&L'S'BA-6$KGAN71c
+%<^gG0miD5OGZhLYnZZr8)8L+0E+jP7OK?SP''GWF+uT0GK^<l,qO)UJnm?k92+`X"DM5eF@puFTc?:"#i>=Q:Z$%blk[3]#n.Dt3
+%6mO?(`l0^-E4WeT)+WSOhDnk12QYAdrm0uUO,VK*HB+p6,cmI"rjY4'eB(2hrpY<d(p6`;qdeq)o-TEA(PAW(rV3Ot2oh5QZ=;eO
+%@`\$-0_fnRpj*A9<2E+TB.bdNBkNB?(o.1;(GT,JZ6K9u!^(pTXimp5h!-fGW!tOHJn,l#j]=MY,s=V^:md4K82AG`,l&i9!&8B5
+%rhoMfr';:?]ssjQ"ij;JV0c2Go>Bm4W\*oAY%dKt`RoMrCN;.CPn7i\_UBbpfq!cm?;+o1U(!XDPHmIK)%q.QFa0UJ"@*n-BL/VV
+%ccA@qa#ifORBd`m,K)A<[mM$,GFF<V4&'#On7A5P4>n)F10CEXS3K]/!Jc%?5#ZgTo;m*F0Rfh!7gs.[:!'fkQFM)]d%sFS$D3"Y
+%@b=j30<n,qTt)j*gd[#mS5Z1@P?rWHaIN**Y=&!U#<OBXO-Se%lZ^!^j^O)E#N6(>@]R<U?SqDV!on4/]E/!>&Il?DYtYNa;H%mH
+%kI)qaPfRa__3%uQ3!G[hJQ`SE`HI+#PpC@ZmS$\:jPKN*da6`H:gjgOU4qqN8Q$OH&Sl_=)$A!HD]AY&As#1+/(UYrgU8nK_Su!`
+%%LiYX,l("o'&ehFdMA/l%"esT8EmC\2+oM4;L;%K_0Tr['G!QUYDP=,Bn3A&r1UV"ST0X6&edIm9F/BgP1Xr:X7jZ:'-U1i=:%fE
+%JIlQ]8T8hrLLjE?>LN)`=M#(Igt,-]ek*WZ9!YNTA9Vi(SV_pj=EanJW!K,-1Aq?'`]ZH:=C$iK<%*74E=/=<e-K)GCA@EGW%,T9
+%/SIsC7@tBoCck2oL&_Xh0;0bM;9N.<i3;2cQa!1T[Kd_n&$/YIng@8G;@TcJ;jC8nrV*LOPG/>Dr;D3Gh1[j.06<X>+#[M==BrI8
+%!4Xm5o\'!)r](T-,i[6;Z\m!;gssuZrM']56NP'l5Socka!5lW+..%u5uS??npmB,_0H[r9p&a]k.,euVoD=2+d@SV7\n\C$n)=P
+%J=*-33U)nm.1WgVT1kV@8HY#;/!aU1aCrCU>?Z#cl@KOt:;@>435S?o5%(?]7jc7-MpE(/$^7jTp%U#S+>(ki9O\5A;)XAo>`c:J
+%/Ns"=_.U<@0>eX%5KkR:I)E0H4DX8g(fS&(X/=?8fNC>Jg3/Zn>Bm*o[`_[iUT8ftq)sZSF!3nngKk:F[S>*_/.Tb'(Y/H@L58"S
+%@GD,"7iOX%SVk`JN3Mf7cQoAhN6`P7Ana"rfH*NHMe@tC<NVb0Z6GsFJmnHb&\,[p'Z2nb+i_H@;.Yt8!/tA`fab?^OSj](cHFaK
+%Eor-+)j7X6rsB:$<@"';U\/sqD\3DVS*u]hp0J(qG9&OU!%0JB"3V$o4;:=GYR_]L"q1=n/JHGJi-C8*Q?8':>coa+f1=eJW&u(W
+%5?#O*!^#LZ@Z\/CDHYO%UVNF)6^G=.E!X-fAThSA..&=(AXnr5B:["%KO>0q=L^fH`aXLR1KfTm]5a9DZ;^%a%22L\.n;`Ba!,<m
+%i%^Tr8X=l9hL^tU9\Pafc/hJVFoO3:BB3r#KD.lpgDWP?ER6-I)5J5@U,7!/4ChMHFsE5R=?j@E/Nb'2Yc\g1DP^T[MIL>9^L7O*
+%!Bc*mSRDdSK0dDZe$PpY_T37%Am:0*e>?JMTt6L^`^chMEEkgYT\/pn!T`%CcS/&VJjD"m:d6^eaZ_m37lVT6T)l54`.f.;aqX90
+%'<<&'UGG*O'ug)"*^[jR9"<d9)8b:g5d`?u"a[oI`3#TM-jlK%C$Sun+^_kj=$[1\[D3dA%d&;(:Z*tR7&#>iG`eo%1SK)#A8-q$
+%oscAI\[<lj_F:GCO8G`.'ATETQNYr_\i<-HI#R+FYVLju@AF-YV&N55KM[ioHV?iU*>B:qGSg`m-r*9A`j!s=-q$),$@dtN4>tN[
+%ficS*Y75Y(90ZY`=Dg"pUNsa_@Np7AO8#M\*J`G:j:MEe_$CR8I3CG48;P<ca5KQi)8-WO+Yi^nna9,3?:%m"I\<a!.&F_k$+!Br
+%`fF\CEh8lcb(osK/m=D%IMMko]i:i]SP;k6]I`n.#IdF(W[*5ZOl-I`J<,<_kL03X8:`c8qOr.D5-tXMGCOJmOGDF?,,5d)\QQ/[
+%W@=qfH7Vgl;J6?f2#&=-IS/+lJJ[qSH63<JTJoYsc$b1q'h4KE;q@!SQ<k@k=O?N0Mc)\<.3@EHoUQ,1m?4<B0Jim)F2)fh.&#NZ
+%Kn]1*Y9[*l%iG35\TDSO*CblF2be47R)9WJdKg\%@<-:)pYj?,ADr8%lCd5c_9gOs-%TX("RR?Q@1RIrG+:OX@3D[$3%,sCW4Q/@
+%bMg<Wn!,M%g@G_]:kVgc<Q%-b)Khf+jtE2$2=b/-+G"+@Z]PZqRA+L7ch.-]5D54/q-7Fbk'kaYM70Q<8l<oBKd,n(*B5U6O[$<Y
+%#:%YqNr#`GF1qC_(C&?Jc^hiW'FLtN66A"rO+U)t$s[g:\Jqsu;lCC+Rh;=2QWO&?k0%P$+FZraAc.PH?&#oZ_MHf?fd?=:-!l^]
+%#5#.04uF?:B$rG1-A20K-Y:i[:1;O1;YO>@.an/%=8S>\j!?(j4GZSKN.r&VWWcs`^K5lNc[bP<iP_M'KtIq0;n3e3!,sta5c35Z
+%(ur&d$tVeG4<SR$9Q_[RF2<#R#G1gHE34K%3%d+qC-BX?04S/+?4sHCcG/=oai;<\dGW`iO=2%K@t&^:>IQk*'.;XgDOL?#+RpE,
+%i`#*t>"It62Pt:7gc-%#-(\Z=?qY`r@4S/M5q6G:Z&bRMRC3"p^5,b8]jiBP[-)mPE$eEA,rR2!aEXB7+s)Wj>8[Z\3LlfKdMW%u
+%GTCThYHR\qV5.5D']C!!``t;pnrVi.*\-9mOh"_=1$%/NFkr\#e'.#,=n#PRd3R_1XW0?[U%f^NI-eS/8:u[ZW^pM%=5HnF$6oma
+%9-a[=#dXgXR"ZkrE-VXFEE<S>hW7s7g:bh!8tT_#AhloVMMV9M/6N>7i,`F<Bs3ad*'=)VD38SFgp_b1+=)O!6+RM:&`*D])ai<s
+%%m_+1@P&uGm0jDukh\JEH\$IHPpSbi"Z#ck0Tc?N)dJ^h7O5<qm0tV+Lh<@PPC,!Gakf(a)P_?A8=pBh%m$)r9D2(V+`X=s*esIF
+%Oeg_uZ/Ur+%&D'SD,$&\;jY.`U2jfbSirFhC\5m!#D<P/Ac,AR>FLNe`jW(Y!dHe;"4>['nn4$f.1%Brom$iOk^F2J^g'rk[@eU=
+%?k0C@\7uQ^T&jSJ?%m^jV4o4W$X@(g;j2jA3VU85P.eI"2-q1\rTU=*6LT!ELoD/GS&@-PVer'Al7'/LJct7;c:-[NHTus9)dAl_
+%*JT7Qd0,OW5d^oIW>tmQD'Z`#TXXfe0q"*[$D^RdBZOc*co(DQ"4o<^<KFuV>>UYhh.#N)Y+G5Ll^fhAO9K/b.FH?!0fkJ"JKb8f
+%HhS>Q2"'1ljWDbl*GRq.$bMl>4"N0or0[V-pYuh#hH*[7S2S8aUp'alY,T0TL.(,'cdYnCVO16MWu5bLF?YV>,$KM%JfPl"fGf)=
+%eO?/kp#lo^B]f/X1.Rsd\r)+`mMpg+bu>B@Ye$'"WSVq/Q"T2MZG8B2CmetA?CBl?:(!5as/\(7!pm*r&Gm@<>9t_E0;_\Q`SQ"t
+%Ad(D#`(e(L%YI/m1JhA70JZeh$Qk!U<X?*5EAs(d/$Bmpj,gD*.BZqH?r/Q%aj-mIL7dcT$75ZVD2O=N6)d,eBp'YPqnbS6k--'s
+%MM]^OWI.WfeG$"uJl]Rm=Z9>F3N)bn>:(Pa>Le'cCG8mn(!lt2#1FQTSUl/I6p+Nk'VfIo3t2li":XT7Vs99s$`MgdPf#V[+=l]R
+%P@V\.?Kj(0[h4-5*Gq)p'mNK^oN\$.pVU>+EceuZQ!SK@i_aSIMT3r]j"QM]l4hkNEZ?f?.!T-A0O8*=fL<7N@&$`OFp][d)'PLn
+%Q,=;nNa,=?n2u60V>sG43BKD@kE["\JIn9i"L0.=1o]I^3<$OU!mS9FV,1>l2'?86%'inl-[DrKW<Ung)*#+)?uG,*1c&,U'lSkX
+%APahZ&q0YQktLWQgpHGMmtPP\bRN^G.Tf<iW?Mt]BKTffCVd7>_O%4X..mqQ1ad@+2oj-Y.M=#_^>ON;"9-3Eo5Z[m4Y7QZf6.bg
+%ZEt67Pj/m)""kJ:mAE!7"_gEY3Ng>I;na"\TtL`r1/I_BoFXfd_`I3S;rF*\o-!f]2h;LQo94eh_lkR_F&<YHdE,#s;sfl[AJhBd
+%.!mRMTkse2TnJ5((*+cDZ&l!A:7G\fJ/.4B'Lu)*(C&Y_!)!h,:L)I"dA;e.PB;2.hnT@+O<COd_q`TN.jk6r$ltlbRUbKBMeTK3
+%@fjk\_ZX'mS=F5*lC6CFrFk+s)3!!]CW/!LCHDh8c2Xe\qKL3#Tb%^A)+1Xs^n#'j>l+Q#-M'?Ie9!Bb3tYr=3Uo,(2T9a8WGe39
+%c4HpbU:n`>7Q+6J$Fm?iEto8K<CTiNlF0V%]p00OTCcL$SRafl2@B:0YeMq^l%ngj#d^PLpdgN<'6*:X!@2o`&.ZV[Mm++i/A/+N
+%mho*HAi7"C&^6X`)Mg@+EcQ\/iA4mXk&!1mE,FeiB46@/ZS0fj&T.^KkA2>%@+%j(a"V2D`Ci-\[AqZk7&j\6H<.'7N#/BA1:bSU
+%ikW!5Mlmjt&Rg)]EF)p3K]X\<hl!qd0>c%@T*'OH$mk$nb4@?pM]IG(>i2jtl9rBh7oM:'Xb/bH\hqQ0`#b(!$Z-o;4QdnV&ljgI
+%m$M5DWQZJ9@HS<+B=JO?U.%M@1?@\=[\X;I>IAV#kd(A)#ip$%Z\_+&>0fTA<.6^TX;"b8^s`E\!F-,p`p\P-N8rRl(Vaj515&C8
+%NN0r^C0Zl7*%H>K1`e''1!`]j;A;]F(I:7rLT.kJ)E%:DKg77,UR8<P]'bT0+/k8F)"gmu"(U37OUkV7e7%oSQ,-`+C_5I=]PiNF
+%j1J&+EXQM\UFS's]2FF/Ma$ir,,@D60=&]C^:8fH\BEjn%2%c5?s/CJ<7-IKmc?"]7(n/dNtM,cGRo19Z\>.-4Kf-<edSq.hLEU5
+%4P8W_ZRSYo!_.P'=m1SdH*s\@^*q,$3j'R^0N^hAb,poW6q(eD66RP)5lo@V/47MaYnb@\&3rV.$%>`kX;])4<GMuj-(^UW<PO;3
+%3aJf;7?in584uW)5I7+XPV-CqDn2<);#nb#[!QU$$uj>$T2A^>/5nib$u_%\'@`bg%B`hc%gRoi8f1%n@7_kL[93b?)S<CW.:ArS
+%N8rW'qR%?<N>C3lqE#s^P9"foJQ5BuI9=W217d&dYVj=Hfog`Z-qNs/[no"`?SOQ$_)6q,"A.d]S$NV!AUo9VRDb7+E`"_!H<eF0
+%bG]7u_XR((J>F-u"8L]dOs4/E8MVPnP?^Zk?7!E4Yjdo.`PskE(<@Yk:nlrTmO(2.b=#tIBf(3*FFNY\cn1.<@FH@H5Z%q9)mj4(
+%fTLl1+oG6h"9WjQLoU5$]ol+&3r*'+I.VHsRL\3NZ%_]\L4&M>F;hhTi:6D&4$-r,\I3)%E%n-EVd]'eAoX;FViF_,ernfKK:MFU
+%]k&sDVfb"ljG)>OTiB:C7?Yapmt(0(Fc?>?#GMS#Eud*7_kL9]2_(%+U@2%pRrrDao;4<Wndr8#FVoB$QRdbLKAJPI-0)3qD'[kV
+%=87ga6-JQHF\7'lp'!ibZ(ZV'bh8#a,dt'.jbE-,l@CpYE*F<OC`A?PpJ'-e<OH<jVdXj&L@hd!Q_fk0h6`m'?XTm<$f)u@J^73g
+%E3.^/1e/ZG:E>C>MCJKD[/:Y"C[;a8F#!HJ8OrNK.8uB'Ku7h/Qj5/iZ`EZ3')Ft`QId:/c[?)1_0k:+`bkuiDSc\ijX)0#9t=so
+%Br]0@B%KP#j9/n2`Jc,i[$/[Q0)#hM%K,u1]h3f?j.VNJV][eW`\=ffR-KbjMtt@qrVA,gXdic6#TSVnpsD%XMpp9+1jXZ_Y?-KN
+%b0W6T#J=u[4Y4.+<X@p;ORFZe1RaO)]Z&(rh>7RWBL<rWVT)unHfA/U*<66fh4Z,G[Si(hM%HNDZ8#p%L<"\ALqt.`'Ys4%qOW53
+%.EMN;Jq5-"pTRJS:=Vn/M3Y;B`"=jmi]YM_nMO4cG0cGD>1$Ni);TBn&?M,n;<iGlr2UP0SZ5#pWBBjD%."IiF,jm1s!((H'drdV
+%dlc;H:pQNlnd)Z`f[:>H.k*A5I^.V=,a;h,IUn06@]74HBo*rW)4O=lP=CQ_Ze(-'`,W+a_0/i.@qdVd[0H`I68@Q^Kt*n*RZU%Q
+%2,BA0E!Urm`"u6)(_:("/"N)^7n*agX!WK=P<KN$+94Whp9Sg<72]Q:4@]lF2&8O>Cu#Oodo"RW8PeS/)V;e'\B<M&X1;Rgi$_FY
+%>,Z`5m*<FcH!_U\\sG]*\HU[V$/EG>F6QYc%,@k-\fmSOi2Kk(.W%NqT1R.umd!_&G\utVo`S!qL<rdkm>!>BAMK%.4:K'%&&A"W
+%$G-.PkX/41;_VH+;a2=H.8T)gjPI3'l!dCsEQI^94cl&]#_*Ds;H7RuMZCiU)bBfnL'1m8H,-P6T"-B8jl,!I!hu#I3FhkiG=Udf
+%`d<;aTrD9.mPqJ6=bk&B]CL_tXIH;l5tO0Gd\]@]?[fRWFf5"4W58o>M=;N_VFoYIWSq9Y."s)L]:4DMhe(dX=cjTFTXOp*[[\oH
+%:EAF<,Lgk?C5#8TO7uaGXXE4XDnIDrPg$Y38J-nr%iCo&jT`%ICWMslP2nPjXJ98*Q%j%_!@pcb_#-bOYZN*0!t:\r_i8f-ZA.T/
+%@/OuolmJmS#P,ZM^i3>/WrP>$*2o/kL-0L;+1PEH=VEt&LA<$cJAI'k^D&OpaHFadUM\VtLF\H\NrjKoams?m#5\kE5%HgoE_m7g
+%RhZ[G,`/.J,=F5%6u[ks[3W[g+B\^M-lAqi8#,ndDSCNtbYJaKXDr'F>D"jpKit\YkW9RF%Qd!2pf"qu'o'ah(!2E]#L:mN%CeBM
+%A7-u1XL`WpPBSBZfD:Nr@*CcOMPCuM"@Mquq<Om;e5uN^!/*#a\Z!G?)oe'#JRcO]FA\[9X&HGCoa+`)IW9'7_8@uUmu87G#".5K
+%JD"&:+l@p`Q:6qeEH0cf%c+?MOhou4-*\7e)C#(EClb'oBd(`F7ZAXR?GU)8nei`#TYG1,2%?UFP*1ZU)2K.X7JO6[]%'IU0-fsp
+%R[PkQ?7qRCh/s"FKaUU67I.7rA^OU2q*q!`-Si'n#U;4M\8[U@,DHMBKA?*:]\ZVX%-%K-JZ3+\QsP;V9il(u_SZOI(q66#&b5'[
+%)GG_@=cIs]43=G42s5=_5#ITN,IpHCNXgPME0fim?Sr/t`b%Lmc/qb;(I;<C?'9XP!F(5Z^Za5gg$EaGW(=dL6KsHJo<JFhQsN9+
+%7dlsUjr**LfL,*=mpR%5&?2AJ%Bp"UB(OI5N]'-NDJ`'PhS:#bF9B!!K!qRr77^m:Icj9d>l'H,PT\/.*Vg0*eP:*l"]%3.;kg;b
+%h?Hea)EHOBMrH]HiL^]0nGaFN1_lV8kBA!.H@^:_X1H]Ak-k)_mkZ%>llZ#p\"Z8(/rON07>J5QCV.'<:d2'M<Y+3#qbmTge=YT7
+%jF[Z5@lpb3"dIYsU[$%O^.2*4a=R70i+I3Mda7i'c=js(PKpP?2F8QQR)LWkqn3FljAR^\*I.lP.J>a1dI[E+,e2Vd0n-qlnd$a2
+%Zd7ICE^.?nC9[d8,(;4Nmap(d1TV1GeI[MOZJf+4lt';-eD7nbg+Y?>h?Bm*,2QLPC'.i]!>9I=N@M#4MTb-8[SJ0U:s_3U$iZk,
+%a3<DR'<7-6JYPV=rYC<Q"MnI&^.i^d?TnD'J,YA@r;!Pr_`LL`1/gs^g4hm.4n7P[c^RZ)<hh,cW@!%5>ZY@5SBj*`7;DhO_VOgt
+%%)"d@7n:nTR&n"XG-7eOrGe_>[T,J'C2,4E"<S?W#$r2K5<`'[Vs>A#-J!`07T4R#qtfpT$pRoa*4EZ""8E@M>!:>Rm%+;r)=T8O
+%ML.B'%iFn`MoLjg]/eY'%B=4-Jh8qIAlY_]H?qrE5Mha#Q\Ts,m:bK]nm)3lqk-?(31%ZSfZ;f"%KsH_GD\[E=hPX/k<<T=;eCP"
+%G-<,p3?$n6l/]&&P5%IoR'.\IK&EG])QSgTO^fR2qW8MVC2\*!cgG^QdsVhlU;0*X_N*_T&tG>]1UK_aT_H".`$PW:j"t._M*2q6
+%&,cA=HLALFr6h4G4qX?3A\#%N;9o(0"s7%mbaM_sE.7Cn^_T5KouVaQYFOUrg8.mcW5<L;.2](c28['HULMQap=fh-AicH`e;^&^
+%IY!>mX)o,_,4T#OkU<`/1&D:15+aMJPLqBJ1oskZIHpEb?'"c(b"jCG-*HIP,,E6l$;-g8`;l9X(:5d7P_OKL\ki,I+5#/\"L2tE
+%:VV%Dl8Fam4\\4.a(*e_=d#"<P-GQ$&ALusPN3hJoLtE^?HuEAEp;[75+:Fr(!8it,MC'.A8+38[q%f+NLMqGJJ3MaeVTm1`@0`^
+%8-G/FM.o<!/GRlhDo@k<f^u^>1m'kd,H"#OpWf*.pP2nE_,N)NGPsrZ_e`X)2Lr\eR8E/0hB-$VYi,\9?2K<mT8r;8D$2Z/$I)Yr
+%AW"mrSF956i(0EGbNF/EPMf+ZLm1V(JX$D4YWS^[)DB(8Sklh^@_Ig5'T?;Ul/8VI11>tJ];oK,l00jkr&^+?0JnQRS33S8M=ZG&
+%)1qKZ_RJ')aaBP-RU2',oFcU8<gL'AXJneq-1TNKW6[[G%u:*)*a5-ra1KM$CX;T[fbo^o6dpQKAPMae.)h?%IM>[9q2@ODBTgU`
+%s8&5R!SY<_>_MuJ'r1<0KEr`VHp$&T)ps:$S>1A#*@^6j/8_)U-JZ_McgdPR;eJHLWHei_pIQLn.3MsoVQFiA7i>q)dMD[je3J)n
+%$>nk<7kl^pQ/..A.8LcS+8om#`N4s#!$mE:O%jDa;Cbs3BDQ.6OI`.D(c"FdVRP6Y,!MgM*t+pVG$a_olIm^IZo`g7$38AU;"j!:
+%U,r6s(*s)&(-UAu&3t+*nu@K2W=b6%al'/c-F(S2I+,n/Qk0(t^\HcqWp"P^HZ^Q\YTf/7WJPZu:Pk&,0LC#O.j$4RFpO3ac$:9]
+%?2e;V@aV4q<a_^G&V/mr.4O^"_U)4cHLDY_&kbeanB<eL0$*V/B6MJs$ga1Zj'g.GpnZE<dh.Wq4M3:qr:T`4J$J#61(eK:8qD4V
+%_g&iLll+0nmrT9hS/.\!8[AM!<8I(>TXoH7/7BXCb#PD+ZCHO'0;0%A$1b%B2XNYucgIk(g/n(_Mkoo$cBLmAD>"j2e)g8qhd,Z-
+%l`r$,D5W.e=%ZSiN`?+UP(6?D]B6Z;0XC4?0<_TS(<htsOg@CD]0ln'gc6ek0Wc'$YQ/RM?/3PXW4@\hq<_:br7[(c?7C[(e;Ho2
+%7OpA+"@jJ]<[XU]1L`pE$ne3eES+$n"?#JdmiD&ZjY4aI,%#B_.tUVd4`j0KaH_:S"%jQ2;qJq-?hZ)TT+I_`*#J4)0a!p"f9gVH
+%ghOaY4FJhKN0/)!8f6%1J$d&9q0CFqYF`.h<4$(FL8)]ToC^/)CU5MUNoMl/=/"YPKYSHOC/s_NoH!O6.1^IYfNc=&!D#,Cr6q)s
+%aM[YODM>bBR<4`@btdEN@5M6r4u.5.%7;UM!=;qSo=9ZO#-aD%<]RO<*WU%GFf+/<SXOQd7[AfugT2l3^4#G4_ps`<<Gg]&!HBs%
+%lLSs-jkF<7?=,cC3qAg^n!ul[3DLA=i2hMOc5J$m,m+XSC^@!,M%iqR!#Vem^!1"fGu9aHkh_U.S]OK$24NAKrW&uhS#'PV@ED.B
+%PF!Zn_<]m/Y?OL/i(N2YdYp:Nl@L_-_cu?re8DjE=h/njldGs)Cqk.75YZ",gjn_Brf"O[>m&s\EV\KcbG,M\&3<(&*n;b;=bspY
+%p43;=jl#ZNRL;s>UuHI<[6eK%WS%.5=-%D?.L:sRQgiYS<G4_3)RlS9L8bp[gCfM@FR,<!NiCHK]%'TR9.-\HXYl,oF/6.JiIKQD
+%R+%).A211rnu,4<p?aSa\D\Ci!d\L4*kk(tE*M9O5g>OFMo3gm3L\_$Q&5QJOjCiEUL0-USX9d@H=.Otg:+)X1R@F]Q$]W#6OK^O
+%/UZ19@t*S\_V'YPmp,hFRBs3l5d%tDVjEOA!N^LulMCCi4<5`ics'0PP#VaE?ch)dSpp>/;m.tdS/n-t`\jD`$$i+V<7QY37Pspo
+%8,:W:>p;iDB#Q-^r?fRQP>rcEEIl%0f^P7AEL.h0SFoih,j5h"]KbT"K9Dr<*eK>"-qRKp&5Eq].VVat39-b*,:(/=\g\D50mo4.
+%P7$6@5<qmDb_>89#e/"b<E<Nu[7p9\?+\/HG!$n*RW/?p]La@MG#FOr8o:n+eTmtd=c4fqDGQsa`1nF>9bH/O4KUN<\.`2=!Q37?
+%+!0=a-<\Fpj`_cfSSoYEe_hCB,0COc[fG:k[M]JRdaBchqkL],NBe0/UE\\/4QbT7n0T#='NHVNb)Ra4&ZV8+bFmRB*#K3mdeN1(
+%,:rGdXq&_1`N*G"<Xn$0\Mq9n[#1=Y3K2',9+YQVU4@72;rTI61Equ(`c36pl*6SJ7^j4mChb1oJp#!ZMs':AP4^f``K1Y.0N>Yr
+%daB\<_9@I!FD9<L7\hiu`,JRrQ)BIUT)8>sV'oOSb[n6R&>]5'WTo_U1#eDRNPI)!YU019=c4m.IPI/0RUUr?&5u8cG-0//:%3BH
+%Eg=ER^u).kWNt>2.XDdUKoTEh1-s#B]V::5CGeBJq*!_;X&sBRgp-3<'bE1$KX2Jg`bK-R.SIAb5Y:i)V@]-nYBimVIhEQm0nkH]
+%,7LqLOt`OPU/hsg2I^*o+dOE:N/phaQfWUhM(DqAR)@iZNq2F75'g6Yl:=BLVUoi'[umi0mTa0G`fmPsY0Oa$/@_&L5.J%=d?c,6
+%(J&^;SJ(CMp\PU%_/uPe$!?cf-s5c9]#glf6Dgd8b>Wd'mLKRDiX.Fl8d>=s,8O0>^"LFG8V]T_r<Z3R@Btur7&]f"UdHAFSXr/2
+%=X"(EVO*d$F<@Lm^iZ8IA=H5)1.d(s0]V\6Mep81i^KN7S)^9d#:<!OcC[fX4\WPO(h\\?q/eqZ*fDUm+B;:[C?+>U^M#HT(u%aD
+%?"ekWL]>b*mlAom=K*%4jXs_:/=V]g=S7fFP(Ig10&URO0tJN)0;cBbF0-t^`><V:=L"!4Q1Y7FJISi!FTm"G$HKbZRpjRI/;847
+%7;s5Wc`qZSo\?tL*#W)=PZ:H'\&1u;r3Gdn\/*T[k$6H$N5oQ2TSV?]1r,uX/J>#br#@54f?nae!N2E.crm$i:\&P3\q&9u<h#/E
+%N$L/dY9QVefj[rnJ;M]ijNDpsglM$;\tTXI?/uImQ@rih)c?j#UIknN+Z52I8o99-Me=e:.a_rZb_Is[hVmgRksR'"%OBmPB99R>
+%:R?>_L!I3McS#h+*agd.(!KZAZ=49l'&@Y1,%m:Y_8*S>"0XXUpk6Q-R7VsN,*Ljb1<;1KCaBZOd/.e.M^GK[a%*fRS`"B<oU!UX
+%2gW(sROjA+GsT1q$nqE466oh9`*okj<uoB]Pf'i*ZE;r%CST\riebWkeX?:[Q,+67MDiE%F9_6rYs,arB$!YD6Hr)e,_7>a'btQB
+%N1n:+q2;]GWK;m;jL+)H0+IUI;UE5>L>6!1bS3rg,bImr$u.k&J0hKXTEtj@6MI7T!BD)"9-gOH7E4B(/ZN6]6N-Mo>gGgrPk;\Z
+%9hnsD]c;kAL]>;VB/P*mq6c\gk=LRH&)2URgcg$"R6"nNYOeSPImg77s-lQC+d($Wb'Hl"rC@C$>*3S4E`PmK@hCs8#+b^)5\sHs
+%YoBQ;QjE'`S*@&PUj"<a<[?CO'!b",OYW>;&VEZ^)O$b#7d>a"IC_n2d''86hkLT4mcX(@SY6t$$<0ahr8-n7"lAJ^3l8Bu+eD';
+%W%D+r`8J'8SN_0*[a7*[oXAHJXq`Gij\tSH>SrX7ZdZi1LJI-OEH^8^#ppshcgVmAG,!,d80mdi8U?>V@96T#gLt&u^I%-4fZj*$
+%*L#%Ni&C#M(T\(?N#X38Z2QILqnM>V>@kDt?rEO2/=bK,mhrc1D[lWiW^pj?]_1bN2Q<\Pod7oS6LMO'c-P\nhbSuIqIl"%j]9hJ
+%XahDZ:\'"?l@A=-i<*Ssf[LU4:oK'k6HX34E-l^B&H&rH8Q^Zj=_]f'HkFE5lRI`aO*d))\5WX79n?B.b]?5ej^q%BN.[o)!hhDD
+%o\[$>?q5aIh^";cqNit?pj1`ua2W.KS-]U'1[c&Q,+N$:U7+JohlipFXt/*?LL(*U7aY#d:$_'l#@&F!'2:-tE8U/N#\6M8?BIoJ
+%.(FNkW!chrX_R@80S#'03ud!Da8u^I?DC*/E\9=q2_[X""eAR*BeXOW^TQ!$a1Y&O2!.FUV:@#%&)g#(QhWQ816aZVTV]JgL>(4\
+%S)+SubJU_1^'>kr,At\35kTHKnN>L9o'PoP>5P=,:&T/SM=i\0]LPOp5A`:>X`=SNV;=lihYI(m(h3!kUbRVNm\gf8ELOpD(CR@'
+%i"4RVE`9!JM+pp?Bn$17&6@=]RM,^0VJ)62\2Ss\+[As+C9t'^h!Xn,BHMB,JBVU?E$g\4S!t7fa\%VDem#GuA'%@aL3tTs)8?%0
+%JqLa=K3a3""i*Q0oO42\GtH0iCN9i7+B^tFW^,.h$rWbmj4=]@G^#tc`f;Od@7!cXSGa).$]`Q,JlAI/)CqtG;!(4FI-:j1Bdpe:
+%+3Ah-T0CTZq*]J!\p.6O8`5G5Ge<8TO06$#\O2PNM?%KoF"H5FreGMQgLQ[GBZY1-'9ucHKF8M&0l4gj:UK*5Lsk:e$<0)dn\O=7
+%<JDVsl$>\IeRT(H:A5gb]no0i]e7_/8<W9Scj1cd6I(9Tp]"glh0(A3Q7K3ni'6_-!NG$ekP\jS8L6OPfPWY%&CH/>#XV*7b<SpZ
+%Hup;*pV"S&&WsWThCOtC,N41._7=UKbY)JW`/#"bPc[Oc>=S'<bdYl\@,T5B;E'pg\ILD68F()[T?GU$e2A-13J)XBR;0t`F,^>^
+%fNGsH_3;-hWVdtg^7C^#!gY[Zj=SJS`-E28F4SsW:<?!1)$'$XP"3VVX(h012llDA:Lu#lb!'`5l'!]K=n>*4)k`+39cLC&Zi'fm
+%35Tg?j@/fg+Y[6o_T7m[Z%8gd12f6Y?A!6'>Q)[iV@&\*/KZ>JnA1l2kTB!J*i>GbN@_"bKVhkOqB[]:->[;t=m-Dkh)%/3jL5gY
+%2fQ0Mr+h]Dm!I#G%KDgkA<Dl;cYAu1q?;+1Z\,B'jG[:!pWEtnY?MdK5PL0Ud`bm4SETJ!XtPG:`t[d3NGJ&:84q&?ZGtm-$l&g/
+%[&>9%iJEm@c&*g<=DX0?)QJd]5u[qOMOLfN8KjkN'G*gc9r9rA\ZVm2_gELH$FS%jL(uH#AU\4K2)=d-Bo+j'_aIPK8k0g6$-W"N
+%OMlGMX4Uuh.piPRqiHBG*bCV81+uWOI7pmH[J>3(U8H79`XLEo^$RbM*UO[\gW4D)`6XSAO6G9*1Vr#$7#kjord&qKV=-R'Qf3L_
+%=/i.\e8jh@Neo$j=YE`h&r>l5V-g@k!-eUe:1dg3no)@U&[0Fo*]P?MYe4_IpsT)DQtCTa0T*@B<eJ7J9-9LMWLcdmohsi__[04C
+%A715Kc[rBnO4i>kG^,W,G*mJ`gL_?Oqc:/\0J*M6;Z,*);)/FJVNtbrPFY.sEo=DMk-LTF^UtZc1M-"ci[)U?A=S9ZY@"1@J=*q$
+%(/Okm@_/ZkV+gk+:<ZVX_3bNAY#N$qiD4^#WfhLo_2$9ni?G9\X&CaSKOaqF]]aH<?Eif'9iEj'">Gu#j`5Zs""Q=RZr.@9/o>.J
+%+M%cH3bBj`$aX].nQ<.3KmZb)f-7[^FkuBa*kGL^AXAM"aXDh.\be7.jRHEFOo7-5+4[etWA.(m3Z0?ap_O$tg3a`O;)K"-7N8>M
+%J@7<?+)a#33@=<IXKki+P>s1d7SY7dGhL3YKVE]Vr"Xp2Mopbmm7\7$aY7_7gY<8EVif_JOI^ru+iZ8p4?>elATP[MO`!)M2!AC-
+%BCiKP^[[M'q'dksZ""W?mP'F9P'mlHob,rjZ"%\CkUlesD07#ie)5KY^ABBh-SR@)LMCs(QX2K"X8iB`'"IkYe&[Bii[gFp:]hE&
+%oB*]B^UO\87a\_P\^*hBer:X`=&TY>T\oaQQ&IM8,7(KpE'YG@X7V)Df$pt%M(G"B#g%k8_U!*E=0kcIaHkE5DfM530p""T;dVmS
+%%(nr*?!:W36hbT-i2$\`=oNu4O"*'0p^Vk@Ac_46V_qjk7Jmn5VJiNl*3T:-ng0MpF+TG\>m(d=<dC1t\*u3`CTi)\!AFrkmgrJ(
+%AO@cdQGK1>,A%?":\FDq>K1e@IQQr/E/..Xk']89m<ERA\I$9%Ir?",1b/6E?^g3.#_]DO>Z[Qdhte2I17O2L`W3Z=P-H\$,JB]E
+%it&.:126FP1(L0mbGo/6Wd+s#WD(\Ln38Zu"fDB]/j<H\IWsXb'i!;DaLY>G<1;UIf$,%H'YEnu6FI<,F_;UC:[f.e(ke8a?UVUV
+%?Pi:BEYD:r9m';=qA"E?:H=a'ER/4&i#A]I/L?BcYn]pfF`Xc:NUuD>Ac<(mA01H,Y;KY#E<?C@ijB`_93f?k=UGs\\>];0/qt!U
+%X10gfO)saHkl1J"esX9qD(3/a%f+^oI#HgZc;5[7,)O=f1l.%"kd:gBj/s/)iNIOp$K2"RN&/Cr[slkNs/*]hl]:8$qpfk@b`(I@
+%D#%0Sr=%\1/mJH:o]oFE+*6-c5-2dp=Jcrr8m7S&3(qHff\nP2Nuqr`I[]H9>o)Z9&Au)K&Bp<=]s9:odVm_`P7@dIBXHs.Go.Mo
+%Mn\\k,+Sid1UQgFHcFe68u9E0,F?<!<2>SY0gc*R::>G0Skb2"(c[V5"1^f<s(ej>L1d'>osM/%o2,/J=k&=ck#IbFq-9e:1d0T.
+%:Xs7EB5(G,Rq]U$IP%M]AbV_rK%@V6rE?;a[=4-rja@SjqRN4fB"gH/Ud(I5icSeSWT',Ee]LrSNK[DDa]+O,.s&J+*E6lXiI\gF
+%TrkJGa\r'1aD*h][qE!ll2m4dIE>Zp>Ub3G?E83a"`LMD>LD!8;ld=@N$Cme?ab#MmhTlmp:EcDQb]^gps_JPlPf>O.+IXQB3_K;
+%U3<Y>9kM.@/).Yei>/oc[IU3r\b`_.T%@8Lef0N+blrUtGhYO..c/N3Z+]]SZ4?f&Bc?2a_*\dKAa3!rS#!cS=it-ml:MBSp&HpI
+%TZo\@pn.>\BCb\9cF?W)bX60_5E_214fO0"XqPR)MM9:7@ES`&-tM/.g(c@'j$&I#$6kf%R+:$r'$=Q2;4gY)S]SlsChQ#QAb.g,
+%lhq.?Z3knB"6/&+QD#Qp[BK=@R\E.ZR8jO0%7C.??`f6.R8q5V\mFSJ>ZV)A=!D&FD#0DQJ(9a.?$oa)++"W+[Qr4W[f1C7Yfs4k
+%R@h'1p3Z_D-5^H6gI:hdm0oAh%i/[^O`dI)A#Q^;fERu>VK\=C6Il`qH0&2aB2&i[gHA+q?e(`L:k%(K<T_34d1C]WVE-5ECQ[Jg
+%h=9>=\L%k0=Wqk-CaHHd*TZg>n$JlSkPJ#L;>5q?@gdG8I,FXb_q:%@rSt8,2J\D^Dd*i<lJV9sGNGkIchciFYTIrT!sAVri,J&N
+%Ztg\Mpr]l:[SNA/<"e!gcu]#]$sj+Y8XPNd%=GLsj6_KnhF><Ln\K"!TBl=^c#r7mH`S5>2.I8/H1"K=a4g5=4eC6Rdn;nd"2I9]
+%P63W`\3A&!Z.t%Qmab];U!@F*D=]kQek4b)btf^-^$jn0b^<sF`I1tP(SBF)2M"Z=9m2#i[kD1S*W+8)c3%@Er!&J8ZS'"D[,_,A
+%96QnjM[7ir6J74c*S9W#f3s*A`iA5p?>k=Ib_1:R<u(8=Z@)G-pADDelJK4f\?:(&DH^_T>aABK<IYocS)8Db5Dm1M?#s<r-0cK@
+%bA[TgWiDd<mM#+JUig):H`b!5[Iu[$HtY)7/2lY^Sicb+E7C102Elliq<r_olRg)cN_>H04)TKDDG@n>msIbq4]"IK3u%ebY'm\A
+%haP;sds%chqU9Yfr8GhC&Ztp-=j5fL('0QsnkipqH2/jXLL*10WH6seTWQ%W/u.f+,%'f4j0+JY1FSbqkOBt2o<-60pY,V%*54)&
+%.&FS8qtJeIY(41ULDI1\DlD8J<NVgT?@6I@AKK-8PM443DrlAcF0YOa<.[0g^7m9#0m=Y!K(>T@<rBC4:/nE)&s/kZVq[ONW?F?O
+%;2sqTYP,9)9Dc;DH#c]/H7l21dq<<_\Xa3PPaT4V40n#^QKkbQX^=$&g>:^LX%6LeI+%8FcSViaRj';Q7QBkSHl#W00`-4CF'J$k
+%V^f+B:Png0='O2][e/-nSUNa&B2NNrdWf)Gp=j@JiN(=D:E>I^7K5H=e3-?-]O0LEH(E.o$fN//$?D*<Y>O[VQiW7II[/`q1sTc?
+%-W(L>dC^7j\nBhXN;rjs]>*Ns=92_qU*V*ohQrF=]CiOND._Dm9eU#Kh3qRUbK!IiCHd[ToSlksh3NoD_/40Caj.nIft-<W`&^Ka
+%b4_BH.@R/QF\BOMro;gAIqH`>:)1QdBVf/sjS3#mG).T7orRBG1&@FShq-d8Vfg!3?]gt[0g=oI`7Wnlq;-B8GHFm=d2gU5pE+Mr
+%leCcoZT_hl@!PA4g7!ERqc0cYS"=ErQP$l$#(3D)`@tc:,-4MQSB5e&"4ee/Y(YPa'qLAnD@"`N4Hl^@#*'h>]\#-&QZI_DZc5fS
+%$`IAI/gr2=N81dX`DE\9cenQ[ISXqVYHN-!)F=+/_u$]"lMKBng63OpmG0PN[.eLpL.CrC[&9/shP+SXd>!*oihe=(G2f#JAG(TS
+%>21c$+8GRPF\:St):-D$jaI!E1d;<37sR-Q>Sc36cdh@Lr\CprlYoKEmJ=80phDQnpk]h<rYfC6h4`@GF*Cm@M!i0(;7gpI-'(^P
+%F\=X+3FAISlZs.GSW\B7j0cWlH[Km?G7F@A<t1ZF?F"E.h"jc]rX)pen#AN,e"aC:X\5OI-K'hWVF8`BM7pXGTGpZN-^287kc)Vm
+%Tm+;%\o0PfD+jOr9$s,b=I1E2]9n]oJ(aM<&CPLc)nh7qPngS*Ao9F(nPCmqQcXh\jOeP:b96f&Y+X$e]Z!dG=^mZ,=fg[Y!)9dD
+%OMtUlW7]:no1$TMba5_BTemq-P0]V_^a5re^(ISlA2Xmt<hGdJ(m%cOBO;3iK_'iq>VcRk^?*dMh^eoqaCtbAI(_)V@J%s?+Xofq
+%O\G<^qd_!4&q3rO:EOr]ZTV_36*6ds3>#Za)17+B6k7+I>H4cX(k[u$P?s(aKklEVR8T<c#"K+BU0`Ir)0Sf@NlZaX7s+b+o=c#>
+%bHW<rR!GRC/oY>E]m20(6#FOP!^b./)4!sl)EB)ViX+r4W!JQYNI[J,%%]Um].`!\6/TZBr,gFh-E@9STjBh#^/>i'`CQBgCTH*(
+%*"uR,S3uW?oB1Oc?:>F*DC9ah"K:tZql7/`RoSIs82,rT)uFDJXoo:e.aSY;.m$s676(<XXMMD1Aflg(e'S7GYI>tlCFeF_CoG?b
+%NY0GSPZ>BMSq<TRn:qhbi#Yj-puU8EJ&cpj,-4Gn/O.k)+H7ZJ1a!5ao%="JptW^PgSboejB6p?#\jiX"DheXILgl<D%o@S"Cs_U
+%$)gP;EI\X9AD8HJ3%@h\4]T7g7KBd1;bUQW5(3I51&:bWZOA`RoC6:Rc0@%4M1\-X5A<ao1hgK46ZV02=]NqDN>e'O->Jj:.tV\k
+%rF7De#a+CWT1.[^N!elO,g1RQWb@c&!s^'dA52s[:jI=2c/MdW/E8Z_J_V>jN<_/;]M\/Mp/dZC<=n0kojsa0j2"?IQ*.)u3#HY(
+%C-7lYOtF![-k,Uo-UV/<CenTbg.1'<j-Q.Y9:N<pGG"f>(bX9^5QQ%?rXpt/7cJ7.T:g$'p+T^Ad*H<MfqlT$g#HCn9$\u_rpk?L
+%Va*-XT"+RuGa#RWfHVRd<&j`oOjLK]=g5Ce/*./-YMD>3a5fH"o>7-PJUW>WrQXD*1D2bqpN81_$!cn#$W9A`r3d6>>\_A/[2c3$
+%,lM6YZ0@>l'ifSU\po>>@7b"am&i[r3b7?;i8k0W(h?TOL[HqZX[+AY8,u&aW\G[p/t%!?5H-24)U&+@];8`Nknk(sW[?JV9m&Hr
+%cF9d+CGH0oIa3(tX<Idh#e8*YAN.8LhFHg$Ht33jbAoVJ.QWc_`F@\cdoL;W<?n)YY3th1o5UoACYNPO`!8"^PB^?j0<Q"V+K+PE
+%M0je9"K494R.r+-XL?bS=2.raG0<$K^)Ofu@0k_2l/Q1]j:V?/:Zm-\V3K1MLG#"N;rGf,QdA#:AtLr*KdIXPAA,YR,BUML+k,DZ
+%.+K[@2T&rn`39;M)[F\^")`-@N)O:GGo`2,0qEJ.bmN"i,$FT=Ms)mTI#:e:qsT2RMs9fpP;2bIXq5f&4=3#-bs3gs;=rk#b<ku0
+%9\i:)?@V2#pb%\]H`RnO!,Gufo`S>2/lf#K*W^7[OUimFM+q7tX*qf;mmm#>Y,>]m(?pK^U)""eq4!raAt;3GfUpCdF!t_-Xml.c
+%Z2;93br%_e/nXY`4[tZk^n=ojMI[*`P_@.r8WGGqG+n^/eCJpB[llIU(=JIX(ZfJ@\W^AoRJ(-%;W"(;rncBhIW..SU,k/<8B'4V
+%^9^'$]j4\t"#'ki#Be=0ibhTtG1T[CSpKE-*Cb.-8:oFeM5b\l[f\hX[,jN28i]UA4h]62(Q)c.![=9X4._<O1@ak1Z1\*S?G?:u
+%B>VD["QZ:,:tss7m<Ye(fW]ujqCSuoX=K`SKKf?ll*^:p`;Qa.]&)X8]KkHdU:Hd[/"VV?U&`b[A+TX8]mTQu0<SlDFU2QPb^-/U
+%N=4Qp9R/gG&^l6DNio4(4f@#@aHQ6B^tO%QEdL#PoN\IcGW#<R]0/r"DHD0W0ndS'TDn@$j+9SmGOu9\m0VQ,>%Hh@33I'&<$,ZN
+%Y-``sQi"HLj6,GdF^Pr\KRLOFj7r8%@V#*O*?!=n8q)q+>3-JXK<&l/.HbD`fm&)*d'9]?^u$*'b.Lc5E<Tej`6,_(fAiNn193[b
+%(c(7sRKoDNhZg^3a7XQ`^2jM]l-I[_Vt+QC`p&3g8Z>KQ@U7/Q1:&"(0[:5o1uI]"?>$u9bGPSRaD3c;d.Mi+:A`O]5'8n(lSZ(K
+%>G7"R@HY,96%9@@dhmK,0dj+k"F@a8&rm)HM<G2kK(!5"U5a,_^XKlqpNUlM><??CG0"iTrU"h:lRmV;$)u$6?,dcV[PUbX_Db"m
+%hJ8cA$^3`q"Qjo/?a\LmN+:/%cWNEgiVgC+DE*0RIEln?/a[j;q8m!P?HgG)AFEIWI)4-!$J?<[q8$uVk4a5I'2QcB7iOn1pA;2]
+%#;U`,S[6__F9j`$-nj'*Y/n<fEIV^V]l!jQ@+#bTRL7sCpGCT%l.7bPJ<_+B/=7fQn.Xp+;/+IE0?a'[>4MUJg(N=INR`;LeQqb=
+%hHmTh/sO./+(niUQJ#QY/B'M1j1ISNmE>EVYIZuFkK(YFl>1c<'h(Ma8/"BTr&^@"r;>':lG7*.CbCjUDTB0@?f($QI7IaGaE(IC
+%=7iP]&LJY3a^Z.pZI1NXVcgWW>J/33CS\)K\Y%m&67%t-SE=^gYdqXCihtCVDfnD]F?pp`Uo0$^%:l0'QO.9FpMJ3[FR$@Hn\dlB
+%(p6DLgknP(.7p/_`o-N]j7`DnD^?#+;%pb;DSp1]GgX[r0(LL2aiJ\V]2ndY+"PY"Ip'`]Mtb=g,*e!b=abSU8$rgkmaU16H%DM%
+%+.19_@Ip5OT%H#iD4^[P*Th_oBqW&dNFAFMpfm^mrT_;/NDJg[$Q1aL5ULrI^7AS9L=HifAfO-"-EQ'mgo=aB5<'b&Z4s5;>N4aM
+%hSjs`\Xm_9,rpB2Ohl8QYTaJCd*F&[Oo7Xf6JXShZDd339EACZ.IF]P,3A[Nl\>i(VPd`s^SOaY+?ke"$sdq;IU55*ZEF_*C(5[c
+%OldHEd>_9V6Z8)$.R!<iNTq3j!C%J`hqJb9jaB58(Ot^f9;9>12LHk2$c_hq8&&[2G2fK(>]cpr=InJl]T7+4m`(*'s5\M)b=MF/
+%(9>4$NAoZ1D"Apo1Wp`NEShrs>=F=(Xs"YSG+M]+`S8#uiW-P=04Z34]0)\_B^JF7(c"e=FeSME-(NBEaR!,LIQ?(^:Y4s,)-;^`
+%&-/X$"%4$@RP.&3(maXRFO7<e)E\u^OF$M>B0>pjn+Y_dA\>D9$B7Cp%VL*UrOHB4k^-!j=XI;H0P7\9SeI?i?.hluQZ@Z,]2_Q*
+%W76Y2]mK#?>lV0O9ng6dX^"f`_l)Sk+ZQai&H'p6M[cS%[:BI`r;00?:o(3UD-29pGW)'qY[3um+m`+-f+\_.o6I)o/]2'KI;jdM
+%ZWgTthP?hhFR><J70t[;b-pWUnJF=(D[C[]+l5ZsoCOK3ac%CgkK*DVMr-k+i8edBbK<IDhX?.Adk$a2[O(S!0'NW=2cT.%\\<4d
+%q"gE99>3T1ZlSWoYc&?G%+0p4naYFS<pu'6)@hD&RinX[_QWX[pltATBT3qZJ!Q*Fj6OAq+4hdbWkUDTHH%e]bBJE!!`:AD<_j3)
+%aDU1/CR88sV%:;`hgH:Pc10T!^-=I=or\5MH`K@'mitO9dK?eGiaAg13r%8WoBDLHe=Q3[\"[)VJ<*uq4F%!M%O8C&$=/baWL4Xr
+%ZRI.q*'20Q'g@>!h34fkTAHLj*p*4Sm?bkghum[BpHc"SU0Ob'/%5E;(JlGb\c'ZCasiYhdZ:#/Ut8JT=)/9f`S&Krgi!5$p9P=0
+%iuo@B<Y`?<WWEPq;>P=&3ne_,8&T>hn\<j+OiID"mF/'pMY$_P7+%$YQLMVJ9-^t5?9+jp\0'b?8h9D%jCA!UHcGY=m'%(2e(]-g
+%lRt<O;E55Gf7&3bfCp<3-ND)@bgunJY:`@1q6!LXPFaLGPbOf!CP%N[:6`*I]rgH2kG\t6mHj=*-#<O]X`k/Mk*(5^)=gT&W,=La
+%:+-(U.tNcrBg)0Iq5E^D,c,n6T:C5,/"j,=N%9e:PDK+G?E]T+IU+H`\V5GIN]qPLBg]&f.i[G0Ffb98JS4F_e@oKLFBSK$SQ+(@
+%lLHr@,M]%Ql[0QTG[Fr0*V2Bc>Fde3nab*=c0siJS8)$^o%o&?A4o/'VhE80<"ZQ"A'!fig",IbN<SR*C6iBI?r-,)3u%UV<Fl2/
+%QsN[/Zh,#tne/JsEec!B&;ouPWH6s4J4tTpolT-/e+fKm`</[UkfJZE+,R@m/90M"!CucIYhN#.U<%$rjp9HAn[i.E*#EZ.#mSK)
+%\B#_F,76Fc`%;GY8c*=r:ZiCT'`lr;<`5Lt?04Re-.sVg4p$Muhl6LnaHtV8QN?Xn-s>VXJ9;M8lg.WYL;@*i9L@_Vfc7W&-=6uC
+%S$eK"N*0"KY@e&+'$N4<\tgfGr>DYZ^j05j@_fU>b!o+K8gj'9H0?/3j?tP\F,"pNjP,<Rdcf\Lj"[%4F'<#-C*:i:-n<9mfi51$
+%)TEM@+F"Y%;.F%U[-b(M>e_g;W4=U0bqp3GU7rXX5]0-m5V4Zl8*IR^,,)S9e+m;195LUmqMPg86@DW_;=QDl=/O3NTO15d!Zs.#
+%fil]MM[9;dTUT(\/fB*Fisu((&'(5i:pa+k%(K1.VDSTsZ>:`)*OL?k2'iuA1;<W'B[=(X<rFlEre<hdI*p)WX[5f?/(-mrHdC[!
+%\2VnZ-BtW@%#nIk[?jKDP.2iJ8rgN`GuFq6(S%4Po?a]a2"#n!Z#324nTFanb,/HFFc^`-[POZk5Dtn--Z;pfVBcGj*EG"tW<VNu
+%WIVf'"2)9BbTk;NTU>OS))\X&9?/Ru*YMR+Wu=QPE6lrnT)=u%p0H1\b=ZN%%h!O!0jOW<)c2hiHr:tWbhh@KO@M6fLOcr%Pm-MV
+%h?ma=\kLIXFXq7NglF!!&hiYC103;^(fh]=0D"IEh<5m\]nWCLlRJ`)Rpm6g]b^^TJRTXCrh=pkOu*oL[j#X</b=N=kq=4Sn]?\g
+%e3(AbX\;V&)'3Z5J[?hNZOJbe26h,*$8M$\,R-#Gm21#k"?DZKIg)LgA8LaW1JIf(Cu)r]Ukt`^JmJn_[:7jZ$7u0c_aT)/;!OGE
+%Qf7hG1>([YC1;paO-fW@^q9^=7EY'U?oRVM>O-C%l?SH,*gr:Oi;`kk_./Hk(SLD]Qq:CUWs2/\[-sL7kZ@<%a:*`[HW_X4N-LQW
+%EW%A9Df?)Zr$!op;$m=aQ`N]h%,.d+p'OQrG_70Z(;^Vqqtl!hk1UTt#-FVU*+FK@/!U.OLRLia3$DYKmsF:-=jrTXn\199%kfdW
+%E.KL2UhD*s$]&(0)AX)/aEX2a,A^2THEdNfAJ2W2<3g9X=ZeeiUH+GgRE]a4_#LG582c+g,[<kb7^38H!<N2@IRR2nZ,=el)AuTm
+%fkAM#i^H,131HHJIToBF&pDse8Im3H%TOrF1d[Xr9*9``('XVGfNHs&_f">SBnX\`j7hNTY*L>2j[6IsR5B!#A/'JnX)%rP6W/0V
+%P<--P2Q'u_WeOUgfXI[TZ\@SQf$K@pE?fMII#;_u*6ot6IiS6B)JqRS^R,V[_>OoA%ZIoRBK(i'1CF#;*EW`@!m2J4UgLk'HS<WH
+%AIE:^_uQ46=QEjC`IaCU"2ZT_i6QS.,PhQj!u>p`ZFl!F6bRWC++u6W/^/+f"E:9ST>)phM@DMdmYa>?ZGK\ObSV9a(n<H0F:r*A
+%&Am_PHc\!go_j\"#9M"^alG"?k2#;1Nf_DW`d.;Ik?'ZE`\)H$dhMC)AC+2XCmCNE1=8WK:8U4&:UR-0J<j'Sk:nc35V6!=K_rQt
+%*fLP;nlWD).9XXB3bu!3/?QgsZ!sTjlP+cj5=!)&>U7`nJmTYpg^6],(26rcV&Ek-cXpZt_c+sf1G$nolJ%_V6Idc4BXeM,F=fJg
+%^qL5OUs@GGjYsZ:[A;j0&'0*W2P<]!-^.PF3:<'N[tiU(+SNoFUkraBi['8h!e3-JId.LBm459:Wb)iR]7<t@((I\IcaIaoBEhB8
+%iu*1QC'q:[4rdm-R0'0o$,/FlWq_iOV'%L_37tGH?s9gQG6nqI4SG.N>dp<fjJ$5aQALVAn8-<6Ur`CIT?'tp1kZE'L5bCUgXYG!
+%ftY&nA$Nf]o)@ao)TDl`g*b@+X/ZujMPqE%aCL*YBa#b9!a(H"J-/ILe#o(8!K6BQZF=4'65saaSL?h(Bh>OH&jE62_5(WX38@i>
+%+KS/bHq?$9;,e8B9*.(Pr4T22m+WtsfLNA#PEeVQ&tp(55C'AOX:i0t94M,i4\3_Rl>U0aj%]eaL7=!`!*RI&lGUG4eT[@E"^0Sl
+%3u`NA;f'BLamr8!ErcA+=o+5W34"cp;JfC_RP2`MTg#eCAgJb1Jmo<b#C3WA%\)O=AO3Wm<e"'T'e$'"n2k6B"lHrHB?YZP64n$,
+%jTA`uZa,Q6\n&F?EK7A*Z,ADJ&VB9J8DYQPY#U'_oiV-9]Yl1c.D8iC1m;WbiQl7[CR*8.ZKO*G>9<77=>*Xof7kD^.N'"@UA4Zt
+%5&GpL>)''"c,V]Sg=J9lF_7T^5CfA<c4=,!jK.F/9Tsi],ChULao!u_/EgU+%1/unk.nEg"Nthh3M4JOQO8X2("omma[P:dbA)9s
+%_f/&4?,q#p.#a\`7)A%qjlBrq32Y"pfk4f-jFs"E2!DKerm6dC,T597OO$t9B5!+L2j(5m3Mk-T=X9H?Cs&0#>uBm@s/cS0%hRqa
+%FC'"X_Lo"$R[)Q?&?35YHA)bR*kR9pYSMS?-/3mR\Y3KJ.&5VM\b[([2g-0ubM]k^:RYA9<PT*]'nmqM3g0QQB*(5&#lk-bgS(CN
+%o$FjW\Cne5+'"Vn3?Xq\;;pYK:*.W#*Ib3OKD8?W-*%;7gj#C8Z@PVD`(PEAk$gdBY\9/0K;ga"B!E1C2d@349h5EIbRTQ5(0,nD
+%c*HN=I^Ttli:]`NZePI3QL9HTLFWG#4m)d=%g%O)gulb]8h?jF9i_Ri.CRc>NV1=GK[gE,50_$$B)XR/]VneiAh1-"WL(6%.m,/>
+%+7q=63i(sZ^t^&J8&SAWN_Ts%@c))&Lo)OP2Nq/q<OUoXgnZFc"6+hs_mlIZanJLN06`d8B'%0<7"&*=gP?Zq,$0h;O),>Ks42$G
+%PeeA/F)ie3ZWM+/Hd,r+P<%@*/ebN_2qKPH3Ep[#i-AEtG61p$^YSU#1SuhC;d?sjgWS)opZ:&MZ'9C*8T=%&TZR%%29n717n('m
+%^XrsXV?DacM5?D\n&:pW^T]/_l`l89A_SYl.E&n%bImG)fR')S?@mFq-f2rsD-0msS9j"7b'#-6.)?:h!u^3'-+--"KF+Ft=j2oR
+%"Bp>X=FHGs72!PE3>b+)[OC"lDS0g_c_AkJq1S,nWY+c%A91[gX42&g\(,.<fJ]aCgBLYk,g0PM'e]7$4UiKr#SnomW"cXN#gO+r
+%V92bajoG*e(P-=8nL4FN"c_'t5E1*[FVacW8E,NY)hERTIc,70c2EOhTk2m)>X]nNk&*>k:hLHme,ZjNW]2dicE"\@YJaM=)>Sf_
+%diKN=_8*.8;,,d%S;b55+VMOlVO"6%B#Oc0<Ss2FNiY(mE1sO:NWLCW8)oCjWe"/:@raf4P\[(5G88J_O%F;tAHj?iC3^P8ahGFP
+%Hde<CaJ>5om.',+Ho3TF!Urhn?FKoA185#4,qcc<3<*fS&Z_C;g<fP*nu!4pO&pao.Gi<S9V0VXF/8BA/DIZ2l*(Om/St9-0ZU"Y
+%#'3g5kfUiuh!]7d:%NWZBRZEHhEf)"5e7/L3U%:NEfcZML4b&]U:>9Qp^I.4!F[4jnZWdF^9$n:YXH#c;R^*:HI_Jon/77F%U%A"
+%F=7fubQ>`)mY+fboFLh/#E+Ij4q*_%8_pHa(N9/q*<AmhA%1HG7t';RRE9HSZ?_[ZG\7,]QXijDC`Ynb/"HOj!^!mt1pUK4#3:3F
+%lD"OWZ7<TR;k^Ch2e`Geq1D-.?[k&f#O]UC4mDN/-8[4TBQtRRa0$S4%=]$3;H2IoR7.<:bd(d&#pn*?K6,RElGY7-5P'"0H8+8:
+%FsoV*hkTYg%c-Ijn$R6?]bU&`@+H1XcXEJ8s-jKM&Y.m+^`<P;:n4`)Og8)-Z-+H"7D1g%[Nbg\Z/?i2oEroP0VISi][2!f%7W3F
+%gH?BB2+lsf,B;CI/grlEaC&1><Xrb16%[H;1gsr!_euliTaftqGo`)e*_h^QXMs)@C]'R%mkU].iq/)BLY_e(D[o7GYW-AT']rCt
+%h6:?n3"E#0(<+YieYn+ZhJN_>&44)^lP]]AQf1l.W,)/hgug6J`6fMn%EP1Tr^=s1CY@bI86TWuL17WihIGhBFRV=8hg:@nj#9:\
+%f0FL[k`uXU@:3I3CpJULYdj\`5VgR1Qh`YW69'tHOOa1]Cl^5:(#n?3=D9h_<('rAARn1bf`K*dL(Ej#,fqh54Hf2k%oKq>5Jqf&
+%<Fs,Q%Ks#8WcD[;EuH".fE*nZa"ZEKl^3(oO^D*C;t#lH6IrW>b>9!CUrt+k_r*9%/0j*A6BR@A"(2MG)Dbn$XX^RLDZF<9=G!UX
+%V?*c-?*OY99<=f'+afr^p]Q])&)%'S7V:8G=<-+s8K2]PV[7&1PC!A"`K9U?0W]EiQ=Q*+]L6&,4QNBp1rc+Vl9f@")'igO@U%t&
+%QNU]^9JJN[nAUYUMip14?K<%K:lT[/<el:S5MJ!4CN+E*l)BVY=3_+Q!eRh.SeZbn_g\(pc7fA4IlAVL\:9)5I]1i3/IVfjJu]<k
+%#2fH!9F<Z)2!5UB,Q(e@]T1-YYKa4*I>KQc+n"RC)%N-N/7j_klC9fj4dPe];lg#$AdhC!Kd_^MT@XFB<[Yaq6UZb#G;X=-r>Y0t
+%`aV6%at[+"&^S<36t#q%Z5EN`I*]7J#BH?m!q5,.)[c,MN66(+cXosDfsqjBjX\:ulX5R4Pl]>Qjb[do[gjB$3m+]E\j/M?DF-7h
+%7FKY'c._BJbfM2qohPj/9@hg`SYT-o5er[*[M'YkGC,A>`R)SJCiR#Jo34_V,E4#+].^"E?Y&i8RY5,SGt,kUOD!?s[cdL$cgqWS
+%pXSk>UV?+385g'r/;J>efuZ5E2+Q`LI+DuTNk%TqfYWAf2nS+/^i.pW9>A6C=Vt>uH@=K]]_CY`HE<k<l[0F1XTXYN[aC!+p%KQq
+%RJ$32;fe0rJbn`_l[:t6m7I$D:#Bgbc9hi"c<0jcT+r^F05+!2HeVTu]lJMEb0s&]Z#@3j`\[NsA'pm>;-oX!o8A$lp%;Y)b)pr6
+%_ok";%f6!85/5sd]j86f`/ZghB`s:b/IRa,oVt'Gqeb@rT6>5%pRV"Q!ShdVkIWVHc?B^l`Notj1S\>e+uRG!E&IF4I8rkK_sG<3
+%c%=Z^%T[']Kq4^G"S$h&AZuET-2F'7:J;]YERpD07fYI@1ck9lrdD6`!j/h<f<6K&_Hb1m+=:S;V@`!D`N!/E<s_KO;\+34DUb/@
+%IV@Pb4EduAXL>SO-=O"de+*W('U:@_VUFLt7BF6QCMe<$=&n77(!K!8(m#=`fEaO\\DUr?AJ+gr"5(gZ3!C!]7Pi['LT2T5%)k1(
+%,hYL1d(TSGDSo$8I)0Ab[nUit\[`s2QA(7<Udj6C&h:%Af".Ss8YAEZ;fV<WdS6Rm'`ubhg&si$\bK8D@)XOq'f54_0mLhk()p'o
+%*4nX0c3?MNo@WI#Hk"2gpK\PeDH=L+N&]I60;J'N%\7EhRDT"U,+`1=Mh]+/?4%,M(BLS6_Vn*O`,pBsfsVD9"l,_h`h=q=`b$*o
+%M`6hPZ:^)uK4R%1TJdWTlXl_Gj8*EUqI8XhLD=7,%:RBb:eAPuFG%k`alF:&"!g*l*eP82H%7ZCi&b0F6X8D"6h/uZGFMBhoo><+
+%MYJ<fnk'#+ifo+Q#hMW`1\hk/W6^-hd*C;QV.CRB[+L]SGOJ<-&b:Wb>R)FkI_ip@A-']DaE%h61P'qdG7P2:QLfcrAaEaI"qRTF
+%,Q<M&AYjoop]@Pd+jO:&)oE>LRi)<`0>m<!!D)?di"GJ<7B[#8#p:H\<3I5o5,!lV%G*M]`54OV9PdN-TUfr`146iXD.A).IDg\l
+%'al?)^aco\.TqL"=5bQ_B&[FNKb&sR'B!(UQOJI>[m2[T["aO(A@T9S/<RG>*!l%/7uG1GD2[c,:S[Gu#l$-O$6kKe,;Guui;d0a
+%EE%Ju+/=S0QW<2\/jJN1cf2k*5V>\YK7=_0dsre+'J++n=p/f@/LsGL,>T]qN"Q/_\4uOt/[AY_Ks"\-blXS\dCYJ-pP(CYW_LOk
+%YaE(9*$Ci)CK@h[r&l5GY.J*i'hj#aUqlL(d=3"#AH_T/h-=(FE:2uKB-;K`H"dsZ"-ELf7CIa9-(m[\G4P3r&kh<>997c>=GMWA
+%6t6YQ@)d8l08*mLZBfB*fSs")]Wk!.<'u)u0k*qFJX--5@G-6\1.OouPaE1W9>gA>J;0sP7.sInUq>M$hdIB^aCY(M>=9GsRmYlC
+%\ZLDh#61*a[gu\p]jfQ:Ms#nq!N-<mj!>p)c8\DpXLcnA'@URqZ1[\3GZ7'QFe8ZV(P-FS..>mqCZ8Pf20N)sq&D,EDBKguJ>VNG
+%+U=Je^aU:3oYC9V-'!##P&4a^YkYDO)IU@K/n$Z#h)U?-dHj>b"ZiDo,'BZQZ8nS)?@0SS3DeJ:prAkldZ!&GmG/"q2^E]OA7I=Z
+%_8h+")cKfp`OWUmS!>Z!c-),-)Pk*&?oTBbh2Qlr!'$==82NLJQ59J>\YES@`#^ZfAn+gX6NHRL)MJBK%4A'l&g0AHaImm,s#n-'
+%!gq.r_M>p0J0p,[#Nsr/.h\2AX>2_;*3MY/QeWe<1()M$T3BOH]_(K17[h4+^qhr1&!fgIRRB9K3<qW(pYF^;DcH9R2F4^("r^UU
+%/1)`-;1o&@kBouq`_k><XZc1qq1'`SnV63/JfnfDf5G#Z.=IiX*SkJm8u";d>5Yg^/=p(sPpgle5(kOAe^(ONg"UDd:N%TGlL!h=
+%IfBRjBtb!HMdOK5Y8F^srM6T^e,<]!;I#j7(hR[V7]@If1Z`ASBI*25b[-bJKER7Y[(lFZ5Mi0&D3f7nqsHVsU[9jY5/ZW2hb1QJ
+%e#\Iu68JS<e)&7Tr8n3"%$H0C&3'3ap)+NOc.9(,de3_#L^ZnJB'(K>;%&+I,9G=XMAFkr(=j_%qYY.qgK(MdMh\MSSgtT;,_ll_
+%['d[g#kFRaDjWu0A=ade0rEpuI=)!^hlW<9=Un!/hX\HlGdJRE[=<")S1=KtiJCi*)R:@[R]GNd2[*P)\%I*j>^GDiiUQ(ta5@f6
+%Q<>-F-?G6=GFj0Wc4BU%11M=90;mOB8d!/>RqLSpJmr,17XJZ,gaOT`+__D=6bnB6TSA:)n>6ca9L'DibaBS-p'-03[8%[nncKs%
+%D)1[:"WUB=raL"+B`;#P(2;;i[CGRp:9m7mhs6%,.,\^+e25O;4eu^mMB!l]\?gH^@;:u?,DWJbP`BK5o_+^'MA9i*PPthWh.<E#
+%qQX2/WRO#c@c[r(PT9?+&#JBrSHt!LG4W['5rX]78X9?5.S;:&Hd0i=@e9PF?^ARDANTGZqZW4$7WJd/&?MAQ1&@Y.@rNSaOMsg^
+%n<1F4Ru=2B*$b5IQGBkT.67fTDQ>H/>51OTPA,6sdRN*]TBRQjp-GUkWD1"WH$%J'[W!/2$c1_q_)K!2LjN"](pE-C(AK#-'e\uu
+%pe+_Y?r,H59]`2HJ%1OO:[,N([YIWP"?^q[i$&Oj;G:^^.10#dT^:.AaL0;IKO>go!G5u(+(!s2=R[\/8s\U\]85[/,.`SZ.WcG;
+%p0MY]\enN60^PApj546\dpI`AJ`HR,m9d^oh<Nit>V1lCq.I#S-D8jVdfP6b=D+IR&N=S%gp@-;bOg7e9iVpq2q\#Rp&o5L/$=Nr
+%XhiV%k\6F]X;j)B_e%Ki2iE_0$chO#]SBmY-iSY:^_[r&k'k*JV2qta%GRW8./CurrL@2G@Hla']G*ejL1pWO<Mnb9!^/8n_=KTa
+%;+WuMKY5-1*K&tppL>X+niHd-8hQo@=7(poTVs=U7L'u,^WL*+@!%89mhQr%<i\X2l=X7Ebk'#D?4?-0pI*G\,"Fr?<mU-aF>DS0
+%ct"F[)m93RBrT,5(h2n&Eb)1n2Ui3!h^smcZcS*,>q$9,>jW_Oc:7`Y$pNg8Gnt0NYE&Jm]?P1I(Qc@n"5b]KDmV,cY.OLnVr?[g
+%""1r@mkb^dUA*Di+J*_/Bd@4OQQKS3j#ae9MAL=$VpKH]aZHkGf5fqZJCt[gN97A)39Mu!lGEF$6j?5^QAXSaTHf:(Nbm-@<6P'R
+%XA8S:Tl;q;OW[tB2t0V?H"n*6m"m$M3`*h]2$B'*K2laJ4<+reS"m6Nf_Mo`jkagC_Ztfs(@>*e>*6QQlp'uuNP?Q)e7*;T!sNEd
+%$QSNS3:8nb6u>Ri7WV.EZt6s.*$dehCs/9u>gi3O,g*K)eU(1Xo'Udt*4Am$Z2LV<8Wo'InX>6MeGg_&R(m*A3N(?Nm@(Pb'YVPr
+%>+T&qk-TY=<SB`&aaiS5bkjh1Uq@blN"f"?#2dHV-6D@mJ?fCnO6GMQ:WX_7iJ>c1"Y$#U!Znt!GF7t(n+ZG9K/;8$n6!EW<'qtt
+%MP=WnEIBaGM5TMn9JoquOC(+%bsSm*l',CaaWpiWEIoC4B31][B%YK*)(0@MVrM"W@msMQI'Es(;=c>7+\e]UF"*bLDX1[?]'Uo;
+%bZW_ZIV:T&_CG`^$ZY/UUd0EHihdZ$#7]E-rnh9*P]u'(g%;XRhX-\5BR4+.eLpMWXH_j$KV`97,A&mqd98GU9(pEM>9(XMTc)q:
+%+,1bDC,7&)8dm><2^I[67;&$*2(a^q1KsS`]]&g*:XH'NHC[IiRM[@o1#u7d8t<m\_Su@40->)DA2.EE$[_^)1"QjX#DOFWW3#;>
+%R:,n@n!2cqSnr`i-chPl[8KlWlt*KP%e8*(S:(*QfiQ#Hd:DcPn4I6?%$)9W+G)Sl/EZJ[bg^Q8_:t@67;M]<P6HZAl1@[K8T#@"
+%E6r=d@Dt#MpQA\5ar4D^qjJu-D-;OJ=_BR$<qbOTag/Nd#uo*[J!u)[N['A`*DVUZ$tI)+0A;B__CP[+rCfAoPTFQ:%VqU1Y;AKM
+%rccs+/83mbe%$pE8\NC,_XRbo[B2(<calYXAstFuQrT2g>)#(UQ(*uVPJYYP<<e*)MrtuVpc*Yu7?/3&53-<d(BNSul&.fC3$BIs
+%67BQZ4F3GHOWj;V_;,h+M.L,@T4R7?c6(^taF2H-C;_2>bH]4OfK(uiaa>3j_!<P!=:-`rIu(_`pR-Cb_,OP7,'5QB14IeeS6:;d
+%k&^@&<!l*=f.lj:p=$F,e3`nh4e<"h<DJ$n@W'MD%.<`,XSRSd-Ta5M4V`p<7EhJbP9njpN=,]5]'u_1bWe=?)RaQjLIE,.;b"XL
+%?2aTLUtaPc@5R4jG5![^P]+iqR9,c[X0nk7H4QVu&,aZ_J,R:"qhtK^rp=(mqY1$Sn,Dg3J,#@;nTW%2J,:>fq:GZ=0E:\1+9(NV
+%J,Jr\`..Rns7fC)hZ)Pis7lWQ^F]78J,(btqZ$R[hThblc*+n]h:I/OqhOn?o,lDAJ+<<kJ,+"Ir9NDCZ1r,Irg3Zapu?jNr6,-;
+%&H0'[gQ2C3O8mi3SUUK`4Stb#ps]q9UGi)Gs8'X2\dR/$:ocFkDboAtJZn=JpdY]6af_99b$P#g5FekGoUZcR4qmZ!%kkl2)*_XH
+%.,:Oe&[XA4&Le5.Xh_su2<dkHQV+QqhEHD?gCO=Lc\j<)s5BZ\X*(-<T5BRKT8^k@*[Yk8V%<O"Of8JW8\FcWr3p>9j1'_\>)&m\
+%]m%rBWh7fA'9O`@"3d>_7#7u9,5GYk5O1D">lJu:L_KXqq1_V&ZdkXQ86Fs=R,r-Nrs7?Vl<+eR-DWb*9UKdpf_6SArF#r\Z`3H@
+%j$+78TdG4na4L^[Jsroq8!H=]!@Hn+M*g`tR+NhHq(.P:$->)^QdNS=@1Q,b?<['*22(3BDP_^3*bVjkefO"6$O;SRVdLU33,`ra
+%7ie_7>h$P1h>kHB-H(o)F*)5sJ]CKo`3[_#Pod!a2[5&p`X$JD/k4HI^5^f)\DU.&D7C3E861UacTVbT'>hctau9T)AO_6-]1r9g
+%Fr2dRa_,7kD]:7;/n*UnUO^Q$AC0iEU?QoY_8m$t&"fsaZ%4NR5<d962hY+7TbM[9a>WQ:Xm-SX:9b!YL4hm"<_`A!(Nf<b=>Fff
+%euAq!&=Kc=S][;Hpjj"=cr.?Q/LQCQMa\j#0qp4(HoO<Eo`5br_`B+\"GF"gD&/9:mn>k9&]lZ#&f/peiRhtT(0I?T7+hhL+f([O
+%ALAN!Cf^%^Z:tV2m5%_J!:Pj5Fne<t"YA]*PB%S37O.i5VM>p"2XFEa:ea-q<F@sT0S,MK'=(cHop&8i4prlOAI2LNRghLBa;Z6<
+%V=\OF5(^dpLu7g8J['q_.:ihOp6d@1G_on0D%ieeIT0r%QBR!4>?<N^?/#t`YglaYaQ`&6Q+Wj@d-tMYl023SNt%%^l`Xt3EHK!6
+%ejlg=-Qg7brIqk-952GUl0`GX+#b,EH^pA=HnNtM]WZZr**:PVfCFQ6V;]9jQ6123WXmbG=^shq:CUDGBTHr2O5f2?UJkZ`e=m%7
+%8;m-U?\!46`ap%_bVjpiqW!dhpg9g--M\u3/m>[0*MC*PB-1V7iBs`VX4>PE8+[!^9[.Cj!RE9MF=QTJ";gDu?DWCJo;/\8?Ye!=
+%SuVHkBJTb.e$=Ji(oMpCLG(>SK908BG)iL&VJ5/A]8g#tn^?@%qeG!<'ej)t^<;n7B[8HAar6A="8#!bR`9aG=\$9_IaTSm'S;@6
+%-7;B9T>Q0;`%UZX[AVanPOV7.*LiDVaq/_h(pklH:n%c<$KY-5QU)U'<1Fc7`YOOBY7;,(C[[.Pf#0.a%0B<V',J)Ofdc%7-EPnF
+%U=NuT^(+?gn-,5W@u7XjiV%=7=bYE!"OeEoJJgA-]F`Wo)6Z_Z9J^c5/6TS^e3RiYH"X2(/aF-q<sLdlV`AN8e8H/9UG#dQ)%PJP
+%lUNA-VV*m[$&GY`Z4a]N#H*JCgM2m/hOFOoktTEBa6M).2-\DD*3lXXLY=p;<@b!dSD1e$NNEC!``0Q[Kr(_^H)Lm&kXLT(<\kms
+%i<o:>Or9LiH-TeSATKg";.fSg#d2S/eS&f'<3mLHPo5Xjkg;6!>FF:]d6o=^)mmWG@+*ld^nXQQKFbD7lM'$#'=h[QS[rW/jF>hQ
+%&HL.1`72'BmA;!K0fK$lT[=$=ACo'%4=tUk'agR]/-]l)Fl^"_<5sit!P!'*T$8uA0X\O=XDdL:9O%,A\Rj<D8\&WMSF&ArhoNCE
+%nZ$11E9FK+C<]PhD.^\HSc-`B"ANlNfec%oR;b*okiFNUEAc2pAWLF"e(n)'ZB&+DbuW(,%sntIReY819ld\SZ2q:K.]]*r9,Y%d
+%.U^7-2DaeN<".?rHj/7>%*QRn<gRic+X@eh<]IK9KMWq:qZfp]L]mtDHXn&3"6'K'Y/XO#ZQKHQcL2OO\J@/<S(<%@MpS%h13q#R
+%L[9+W:kF#o6G[2LQ.bE.O\N-p?_J#PieLO0"hD48C:fpSCs0)Q3o#P8<inI?@&sC+\ba0o]C/ZkYdKWg7'l([K_,<09G.FB4;ir3
+%(+Ec8JIlEl3]`J/UVc2F1O5(O`u]'Mqut8-Pqqbd4$'U&m561BhgO,e@Ad<'_iIY>'B\^`&H-ea'$;>tK!'32!&n7DLq0_QT:s6i
+%a*KT#.LkWEp*QS)\nOSWYg</g$0+dW9HaV2r02%dm9r?HGO$%bnMUEk'FJ_-dk8<JO'M>ea`."d2fk:Sc*_Kn;>=7?HBui<',Fl!
+%PGdu>fJaI8O__=n9]+l:KjYXK?qbDU>VcC%6;YnZSJ<8G]5ggIGZ6W61?7%-Qad?Kfiu_4_C^$e-luls>sZ2!S6Aq)_Zu@V4P^jB
+%UhR\.QC]?JR^Gfb?JSd&X#6TZ%BcT7Vj`]N_!^teZ\`P:,0@DTgP*aU2LQWU1QiS!ju<1Wf5fsX$TV_V,)[4aPsoG)MhK\oU1Sln
+%V5C;:%s%_fpXct+o$fgP;gZ,N4l(CkF*LQTkY5W,eqr#%L0`(?l[HfNn9`gAVMhP/5"93Y3g"M-2s&n%$0.<^Um.kEAbQqL*t80Y
+%igc0Y0Q;G]eR%laZ.g:0X?A>F<3?*?hB+f#YS?"O1*P2>c"+9KlmhFDb11o\G!,HW*funls#tXN!?lPo^E7W0T`\J*r-^$+pp85*
+%_AnIdS+j]nd`2q^[6V,E.@)V=.tu*j;X$&NN[5KBF"(MINce+r1jB&:(?p1gVX^&XX&F(4M*N<n7JIC5EF"2WQo8;*J<RTqP.WP,
+%@#K\q"\EMg2"=Qpb>opPKMOg+1gQhFDAqjb2^MT_[QDl_pt"<tm,Y!4Q&g"KD0JsRZq,2'U4Obbb[%L/HakZ.^n-"^lh7#7dZ'rj
+%/gCe*iksBiWG&\5jN8WVk,Z)F,igi3?cSZd]8ta\G\Q.h*1"bfE2e2gbeujq<]=bh^IC0R:*uZ/hEGi</R5uq\YZaJj7LIIeO!Ch
+%12LOCB=#_(#_&-O=dEC(Q=-l<2U6L8^O>l8ojTX+FBn@!YAS#r]4@aJ)T$!;V8R$.+bQJRXat>rPFpBCV5Ag2E@Y1,1he(+(-d'$
+%!R9uV@A>2^TRE(+2f5IjA=5V.ln\9RVV"Aoahl79nnR,!i*o,'oO0*HrIPL)8)8cEpO;c#Dgq1PgAPrKL]-nLJ,^2lqqWCJGR9Q3
+%>Jk!SEgrUF*$/@7];Zs1hk%asF_!LsDblAjLA5KdnZmZEY<V(is69r\+k)[,1Y>bjl(ZH71jd-5V`T$f/nEmj"X_pJ0Fs^K;d":L
+%mNi+RPIS_3$_a`Bb8;Ht8E+^ua'9o/=K/e6\'0bk$:5B9,EIOYg`f\UX\\R]5JBVUIiPBKBuY147rcp&"N`*MN?*A8%d5c?`3@J=
+%cj7,ghjRgV;=g]rY_EC]!A.4Jfk$aaet$Y!ag2RI`O"nOi5'9F0B!7CiMuD<cShk:`\_:[8k)kY0D`@D)i+[`HBoGGZL,mp5]2MX
+%Ri=?_V$<eh5]aHE>mA-d-[!/@>sc--j;u5"Th$/21]6f/PsV#R4t;K2?,$bE5X4PDDV_mD6UE.Cm^S-,2=llt:nDI"L!1=IG"[ei
+%Ir5Ma]sAfsFa0t3%459DVNBaib\f8K_strYZNK`]3Q1"fDAHUXU3MYt_rOO4DYJRk0,M^m("!4GS/UX#5O8&"]+\aT3Ssi_0(+4N
+%Jk*n^2-lY@"Dl/ek',e?m#o[c<gIMPO6ViY`R:@5BRO6Mb1b\Ch3pEV]"HV^!NLlpG-<bRo@TU@@1`dQ>,uekKh:0TQ1i1HY?5Qr
+%F_&?Dm2k"iK/@kO;n/*[)tQL9A9U@kZ,03hq1P.%l,K0IJ(k^LJ6u+l!8pru4]29?VIpXGJoLM_Y6ZX3J3;Tn/GK&pi8=2H1CZ_.
+%+(n!,(g-Cak#rgn,')>=[^fC`f3tGs%5D)k9IhT*@YGd8/*[j4X'6*826d/45c@=q-V@XLmpJUKoWg*)oiu?'"'OoPVUu\j+.'Xm
+%^e3g<VAidh_Q^3ag;gc"=;JfOE2Qe?oiUe.;O)&%B62!Dn-p(UBSCGcB,-R1*K/`Md&NV5g#gJ(0R&k7ZK$hMOVdG/SU30N@r\D"
+%K8]:0PT`E=,E<JMO%%nTG8^&4Y-tWYj)<o67h_>q(<:=`nsT&[fNF9lN8i.nSgCc.*bN1a1?\k60Y;?/5Vc7faSI91P7%Y;*^]Y#
+%CpXbak1t$m224cZ(Cr+g63_F9*f;i<*FsgSg(D$^&qoaZrG]XFi^3/i&TX<)<LiU'J$.?QZ6alq".A,4Yt8G1p$C_]>YSm\0'g?X
+%<b]HFST%;W(b*b-%(]Q"B\%oe(6Kqt1l=H'BTWsa\JM6'3nGNLj_e]n80_`t'U8+3)M1<%<Wt<f]r!)3<sfEonQLV1VsGXAPbNJG
+%aW(<FlYKkAn("URAM1ZPEH<'!GW#E)d+`Y5:JtT+KN"*]ad\lL*1#$Wfu*%o!-qrsEHLOc3YlJ.RIu"K?PLt+89+<8R4sm(=Yh%X
+%-+pQ]\:0`p9N]P,$m_jDOa*0eIL+$uA&=!if1e5FefegRs/pdSm$)._Oq/`m-SP`f6J7<)CCFqe^MYhIQ&TTS9.GfMTJd1=:R$XK
+%5E%>A!pb5Z[)V*7-l$Rt)T[;3-BBDl.s&?&`1di:(9,=_cGA8H3t>2q)0AE(lWlJ?/ZOTEfBK4bZGtY^=.PMl.hY.<N#kS@hASY.
+%6hZ_qK@$h>99XjUi*;a;PS=uR^T=@`cDFM4/E:q$b^0Z$7O[sH23=[ugEQj@:ji=,A1#")mGMaSn,E#Fr5HGKiNN7Fb9-`JT7?gO
+%J,/Otrm),&T7(25['oOts7d]8cTh?N5Q1G>5Q9>CroIL7q=:^rs78JTiU?:&TE"[N4eDRY*rgRlX8Y_Xor;,1Z@&+E$@?@;Cl%X1
+%'%QB6Ys$pLqj;WaZ7R)oaA`<gHWGBH7;A4dI/-5/AI]"Kb.*P[?j8r03A\!:V@N?:8E^RKi(l3ss8HrtE-tcFgGU5Bn#u-`['HC;
+%g'tpqd[TP7((L(-cWi(kqn:)#U%iWFaAN,#p>^2?ZgNpDjEXnV,AUs+U&fNqZ=1TA1*QoN9\FiH,UY<Tpo,W6YSMZ?e81e<YA([Z
+%_eEVrA6RGW2'62,0fDk0kj3&()APV#84\OA2-KAu/j*0K*FbngWE$O`fn5f"pbE4ar^=)/9@t7Ufked6no?W,D/`YIi7A-d(+t7@
+%?:3@fd^cXL9^iFl"eWh50pbZ=V04,b5$k+,^edVTqn(UHFQo6k!dnLV!GXk*X03+[cDi<i,SK)?liEO;3P_`V"g%uKC52%!D'Y1n
+%7C(PmTg8r-j:$H6"'e:W[V9>0Z#W^nZdN0qn.V]3rZ+qgaXEOJ^:#?R[rh\PnJ]:^m9Zg<.UEC=hN\i'#%=0a+ZeN^Hu]9gHe$&\
+%s.[W+3NEDVEfAK;$_cI7+lpauAO&=*0F/n;90I0%:!X_=#X[N-5?p^..TN9e1TJ1LEFBPf]ci;Gl)VFVbuTS5NS]#Qc:#BUd;Tft
+%^Af$lM.I::7\f83Wg+M.1j,R/dIA3^qeECHk.<1IAmQ0T?IW&61(B<,dR&g>',]hCG;1'E-FCi%KI"huTge:G`8'<:Bm1N>DqpE2
+%2`%duroSfq<ZMEceO%Z*3UFgYQ1aQKKG9rBr*jFIk/eDM2=OM`?)oak7?Hid([Z$sqe=N?Z/+T!KTd;5jpJtE".W5>pE3_k[79q\
+%poH-+;U'<dh:V.3V<G5\IeimJ'e#LGMo(A).%.G'>4W<b1lGrsO2'(d[i?(2AlJJ_[8\,1,\TX_G$Vrb4"$!un4RqAcdetl^8M)'
+%4]nq+/B96*YoW0^SHJpk)i@U[JFAN[51,lE$p.(7UJi#fTN9>Rf;CRb4_hl/E0BmIqpDjN`Ti4hJqY@)M^./dI]oOIF?n\%J4\!j
+%Fpu3BPOKriiC/W`D0M#*,D<Gk%RooLa7>o.+"^8%DY]e-4gN&pc=@*880S)oGW,Bs(Fk>0:Mq<0>4Vr;2g1N.K?Hc$_@01@$6M1S
+%Hm^J+rsPHi3sFp*5b"X%lE(t*mC2SCY/G&!&.A6b'G3)n0T_p-]?(oa)2Od<M6"1&9NFlA<i[/)%lUh`G.k/l>M:[5gjj,U=_q@K
+%5@!0Rb.9]D._qDhO>*q7JLhWTbu;UR.9oc27(Km9KjK.*bt<LOX0#E(pb&V#@8g4_AVR>9VE_*81T"P5#o=.$[TqTl;ln!OYG/*#
+%UDWmY-fHU^]b;,.bCR9a67;t81eCdqg8>9$:8IX8Y),^^$?]jko!\*XQ>jkHjr&24GSpe6IP8_rf:It;[1k7b)BsDg27K/iYa9;m
+%>d6:s0;R!jOI)Un_W0![?t*@RjPUurSQe*7.OjU?E*U`-5agMm>Bq*b#WcUcff`n211jV.n@U\&"M]10D_2LQDK>uQ"?C5iVa)@E
+%0Q#!Qb=l3&c#0Ib',nfE_IZO`5T,=4:f^g\g!q?@@`h^u>0B6DK*/dAo5!;<l5ZkSA&oltp:CLBE6F(T@%.@L-gfl`*G3FoXt-E+
+%&M;?sDqBVR$+s?8Ik!$u7u7g2?$C\jnW1Hb@Jm+aaa]JDbMmMbX7J?3o^,5-q:rsZ@D8DkbKd;@<Ms/$0!jHF%:SW>1t1n6B1]fq
+%'/J?Y6(_R<753^LnCh@1;!am3C6;p2PP^/<!QTl(9ofb!\?lHDi7*\Tm[C@1lP%B[k(,6n%LHcY.02q;4Vl%BoJ_VlXd07-SKY/j
+%6.PE&A*R79c"'A;R6cpPHG1:AR2Rd[BkrWMkr?"m"3Ca*NRfE,r<l:+&`t<2YXW7Qn(4WeL0$?!kdY=-:^@5`6$tV<UW)31A]OGY
+%s5K0\d\]7P8<UiCEW_@nCoCC:4rTfK.+1Zk=n7F5bl[M*(RX\<88OV9>f=Jd.FS$Y^r1#2+"u-kGf"ETG\)ZTpZu5Df!E],/eDt*
+%fBQ<!-lJ<ZN]#g'4E[;QLcXoI%Dpf,e7dO?aJQU5[O'-ob2eJ;%#6<8O3fR68C7Ht:,=p=Dfj*h928%l$8mQXS0"1GWN>:'11eph
+%Frg5KRE3*S`9VH)M/;^ibV#&T4lGaF^(P_uS`")]_u],j_bOpDr\^BghW2`IR!0'W.66PG+\tbq:#]KG7fqd."%19(mBfK/+`!4.
+%Ycb=Pe*7EqD[nd=f9RQYoZGi@qEi7mN2X-4S4L(D)]E`S\IChn%U[O"+GnN:X8B!pQU1Q7iY.=?B(C$/7FJDL:qs[c5CW<@oa"p&
+%d/\/4QE:e\^.Ra*R2)>QiJ$WEG#i0si0M+l^ZLKB*LUJ2;d9A9QNNG-A-6CYkGo,pD/[9@UtmeMQac:[Nq6e),FQgraLuo?4IH\j
+%_=+XR[^8U)CK_ho2q\j_\*Z,4Vq2"@,:!nne/8Gi?@Z1:Gp=S@;HC;f.g*[kem.M9E8/8%-@G`\6`bB.Gs=N`39's$qo[Qt^IgOZ
+%&Y+X3kU(E<es%C_:F=EJ/:kOm&YG]8BI;\Y4Hs7c5NmX$.,]'EYXab*e7-H=@Wl&";fbD4Uc[*ln>GPH&C5*$*7Y_/?J>&g10u?t
+%A_WfiJ"h2@MRpC'8NRKL.\RbMp.iPC:?#loH9lHmY2^/,Yj;mRq%cH3_Mj=5cr[iS#C8VOV[q5]YN!TL^-6eHBSZL9Y0A(gG!i](
+%1L[H@e';`Q<'`7JN5VT*+g_eh5&SJd*H8<8@H5B9#qo`LrL0%$@$_[SkrbXm$X9hZCbqsM\D!LN#e2bP7^h[Gs&fg+-$oBLMc)sl
+%hrQX+WKV-Tjca:j8WE)Pl6k!+N)7I_R_(:d>aMo7fDK0iL&q[X.k3Sl,Wd>G*On1#A?8+@k^i;odq)#[jln[UK(MSlh$<OuAY;(D
+%Jainf"*?Odecl#$5<f2pA#t>GY0K3_EHAYC_sl6q;1+NEc":N#fhK36f8h#^qt[m$:oqg4k3ot/'>CNt@PD5kAU=g>r<1Hk*h>+h
+%':V8Vo[UoB]5j4lqB;@a6$AWN+"<h#C%o>6Ud0&u(*rt%\f_"?qgP(GT.G>\^O@_`Gf[gX7`)EmNpCDU)JTNRJPpT?<Y5>EJ"<X/
+%A6bkOgdi`5NQsfa+C$EB++3p5bpHtC3%Ikh"N;1?jdjY*CQBX=4dQeTlEhDN#J*D'8tPU<j2lZs6!!`-']#s32kJ<lJSq=*>rg4<
+%gn0XsC>l1'U>-dJ]L[XV=1(%O-r9P#ELL^),1#6D0LYAS"1fr!Z]iPZb<o&(,4?\0g+_)k2<(%)=rsF2T\3$Wd:or08Pe&&i`n%l
+%KBY`eJ,rkb*nYWeYP&'#@<=(\fqoUOlL42]1i0-A&_eq7.J1F&fI,X1]4e!4N.421Nr(:?2+0ou+p?.W[h>.kSo7]JWm3_iFg^ei
+%fW6r4_jjiZ@HupZ=0bo@Z@$manTK>l8JZ5#+L;kNRAUURVaen(qQUoR,[L$Vks[XJ^&KfO5-JEq0N--^/&56kaF*5$oal>Fd$aE;
+%R@`XXX1d_U+<#Q3M9*94iX:tOLJ4i<cT9-pkp:&&",,bpgNu%/(j1\5<Ze@JIBjE?ZMd1BBYk`UWcSKbPic?Aq$>3^[R<($*@4MB
+%eeq+Y,$2G#iO'Lc6,rsdRD+/@DN9UZ!&k.4pX=YqH.cF)TBOZTodOZlNn=onC0l--r&8HFU/rZ$k;$I'cnK0fMauSdb*N+t4RJ_6
+%6VgsS/C15!e?OaTjBLl2@PN'`YQEhAjLJjSId-3>_dNV#-'<uWHa(<P85YkX+Q41F@MG4nghFqs_@GY[h2g#=\H-M;3YgGTK'B1%
+%8G0ID[49*PQ"-@LX<eOaXL/fcEE7GojSXHP(k.c(&pMGi_P?TolESXqemZ\-8>o4B6t\(!haLJtA?J^k'8b[AS+i?CHrbRARHjb'
+%Cla\\=Z/Yj"Wg%Y7neX,\VBhK:l?`i)!1+>O^WDLHYa,-iX9OJRkO5S.q;*+DmC?]O(J1@O=VI76;Ntk+9(kq\Xpab3JNj/#7rTS
+%abd"\1AL79G^`\b7^hT1rUIenqff#)RlLdOW6<FKGHoE^,JgZ)6^M:Q?GQg[k&0#q)HDo$MOd]J4?.4i4bh%3@SMJoSF,Qifbkb=
+%&2q#^G07P`?bYG8L@1U=p'q"8F*b\aT`Ate*a=rn[=l!a.,6upmjq=mc-RW`F2k!C.X?tYN7`3dgk%X.4"<Pm<FY\f:34+`q:!K6
+%RLql@Y_H)OPoi5,p0<V@UF7(Y/oJ]UN72jYD3bPpeklfm?PXT2%c]T;NID)kj?ENbDZ2^m6<_52J5A@`3E_D77ll[a1?>(D)U,gL
+%KPC%[0[hN?Df7NuTTea]45T&[b+aU@;.pFdk^i#86f^7d0,"V.Y+Xe,$93K-%s^4R<iuga2:*q9.mWi0[pO_H^#"D%"EH'j4>]=d
+%)@g3H1TFURA=`XmW7kjqk];r?DPj&=4#l$(@;'-^($,KZ/'f%cV`O<?!_0U[GsS#\auB+.RW*A,8KZ6i+k.!^'G9TW@%-9N&8fiR
+%gm"on-.hZ#9Z&)4WHSYO#fIOX5uWb%0_p^D.7MRu:fsN8H$;7!lWFJC/]r^BTpsF'=KI,f=aTVGhHT4(V%((Ro=7Lj3V?'ClE9r+
+%3mUtJ$\W(@nL:$pG72sueA+L]FrGVi!RugDCHi\Pf(;U5JkPI2`"+q22_n-cWRZZ9O\O!/0O[l^TuFp'BEZc(Kl(W_^iF#^H*\0#
+%iUU0KWH/oUjW_*bBA<=l//&rd5CQ*N7VMgt^53E5[/+4,8Fd,)Ubj9$p)qX(7u4-LY7J8Z(DOKZQr&0J/9^.85,o8Io\GP$4,2W7
+%K^h<s1'MVSaoNc)cFd:p3sV`tIGuGV_l1#R?nQGo$@"%m%%bi!S.:aI.Fi9@VqB4kJJpJ,Ca<HJq,p^`l1V_]oA+SR?Sprfa`=V3
+%"$;7l4TI;Mgfm$NLkI45?tMW^A2<Ho50b[4b#kn/#VGr6[0NEQL2gLSJ$,RHb-=0h?NQU7'+6f5MJ7m%+d$6LS(ie=;p&8-1&,V/
+%2%.\Kc"0+]jj1@OI+KD=P0dJ?*DJJZR9oja+LL8pa<ihf*?R=pQjP5+*0.S#(-gh/#l:l<3BAKn`ccqmbuVNUe)L`=!,"OB+d[k@
+%ilK:&JnS,(Ae[#Hlhcn7mooS8)r`otggVp?X'uY$V.7(`P&h(X<=tB=\%V6k#cCI/V>8T3=[0=s0j(WZprF0>!SnQqYs"G-[l-7D
+%[oJ6gI`W=YADJ@Mb$e=<b8UC0]np@Z;'WQ[qM@]2SXP9O<s$_#i=V2MpaWP]e[\e]]/PTDaSe[6%:5L0b?B;dF0dtiQkE=-&%C';
+%<u36F9p]b@K&$>Hg+Fn0YW.VGNL^5mTL-:99J#Za=hi_)mt'i`hE@<kDU3/i??0*AC53&)j-nk2S@7J8P?>&L13qc[^G+oN5U_4p
+%Y"h`%p(B_)YZdTf-IGn)&W6#/r0('I7%!qe?+gf'DNZ5OaCbD$`Oap)f]S`^ARh%Y^T<]!ok`%(KhrZ?`NIa`5CT00nta''A4*+]
+%5([U[E)AQiOSLRl4Z.m)&EL_'XP^MH#_Te7`QAC>2laODpDl4lios4mEWNqd3,]W-)#G4cPB<`qR$KrsJm'9g&QlXL&qt9>DkN'g
+%>Eeeia#'*1RO?$_DciT<>o_*GWBO.$k?OY>F:\pX_*&d#BHVWf\QBF6qSrfYl2&+!5+'642k(s`P*R'*EffCHA-1WQiI!m#,b@<=
+%T5D]"rjZ6H6>DYI%Te_sjhP=Kka\M$G^"96df%[K:(+6t-6K\n3<juOio5C,#N*4Xfo@9`[Gi%'Pc/n34KIZAclZ^hj[f%^pq`jT
+%?XE1?4h4W5A.*@WI$N?:q%?>fF*41bGm^EQ#sWb=ij3;6\p=2JFdeD>E"k6t4t@^%(X$c/"he=.(D7@FMVD\Cin;Ho19'2J=M.D'
+%93D4Ln+Wgm,:J$m^\Fj&PLhm8k^L3"J<!I0_f(">;@Q-+emXZFG&sTK31])nN7f:q^h8[F>ko^krVS.M*0RhtlB=jNp<amGdm@Ag
+%^TL?[oOKkP?\.%n_"p:M^%+3IhY5rMmA4C_R[4](NI,upk8$4601*o?+kX4hD7jZ0GIA_.KWW6W?LF2A^<NMgjVbCr-G.,r(C08N
+%P91l5OgD>U9pO)7rO2!5T@JI)+s2N\#)7elFmQIG00T(M>MpVR4'Xe["]Bl(3@^YM)lL5hfTdua"kA=V$_4c^+dKcYbJD6$#ZV]$
+%Pk5/"oi=E.&O8CRRrqNP,Wh8P,3>HshOQ-P![l$LW^[+n"6<(qa4HP-FR9Ms8-.>Ij^1j&^b=gQoq4=HB>g4*QZF.0Cd\QW>>aNf
+%]E`<[-7cag%;_0#Ai$T+Ak$c&,gULF\3A\3N>+$Fm;$Tu3_qD@4F4f)U:k:K:0=YC'BjuelqeNnn]r2.MR9ZYFDO$qEOQ#foq"XW
+%.HGM+ABp2B?f?=UGNkK^neEl-6u^be(%3;9%U?Q'*u"),I=58kB0/*A.H62Z`-,6KlW&R.3Cd&$:MV_:Xn)l'mXrg>OUsoKc8.a>
+%YIdJ^W%LCD-oVl+&S>MC;S/oImd6V>2qiDbF+<TSG0c<+FC46T(&StZ"'8+]-Ya;-Y/`Df_E-N]TA+L%):36g"=]CA1(l+dE1_Y:
+%^/4#0jYC'09MP7=6l^J?22dekO77&ZW<;"`XElHT/TH.9)WDL_l1SRI:"e+<NkJ?W<0-.I)X(TS2apXg'L0d$jnZUqpRo'<i3FJD
+%ER]e(i'E-iI.YPLIXXF!35M?Uj*.\N6Sgec13$BU'81W-1$^HsSqG.#>>4Br4^4ccZ;05Bo4TcHqj2MP-Yf/(bKd2m+,cnCNr\7a
+%l=*@6MCe+"0@8_J?ll%kAbr'&\)!Q&/6O`Y)fJcH^fZ)VDUHS:P7>JY&M-p&"t@?XG]l'/V?cqDkR+hnEsB>D^pSK[G"aG.A`nXi
+%:4='VS.%h2Tt$'?#Kn\Sj^j#6fc%IQE2p;diQIOp$hnam&L_3&^\B:`0e?/&N;%MD.Rn5A#R*j@Q=fsG)lR(d_niWp^t-i9jEV&Q
+%G%$V'H/C?#&ZB#4ZN<9_2lh^9%!0_^!JrR$#*N?!$Z"6ZMLZ3E7EI#"k*>mU<'^QRo6G8I<:<"+dt:tdA]%e)HP!<:+)SsP^5\e.
+%m<450&%l2u*4J4Q(eKe@5au'p$hWkb.b4;CWptoXF#r(aY:n(KID1r^:*4AGDYITsLBOrY4aufUV>Ofu"PS_?"Po6Mhn7M+LXg]Q
+%kokL7[h=be@`A<"aW!PuRZIiq1JTP8VH2o5EVqgQm'%r;r-eZpNg9:C2I^5$-m=S;>.9Ik]sd;=@8th"*ZKVdH,r,VilfVnE'B34
+%l(c434Y'BF&XaQB9?Y;ll@^AnB$[GqQq]+!LaTfM3a=F=dl)jBU(o%cB*6UeIHeSi(`5TogGaK!J>81'Bl4S6f#B7rjhWu:^enJa
+%*=)P$fY\RqNo,+K.QIK6o;&JK.oG=l"Q":q'Wq#/TPc0/Y:e\G=WJE<16QCI#;d-K/EL>g#QoJWEV4WgDL&JMj`KGkZE_tdfRqt^
+%Op">q4$4$t\(j^KrY*Sgp8^H6?QbYW$1i*A+U7%m^!N5>B`,<Y&k!8VcJmR&h&efJr9l]93<n<!P[U.$+*<2p^_a#hVM_r>?HUD>
+%HY\X,s0s1I(!Lp1\@D@@nm7si_.7<kd.oBZXuG8KmU7#-0+7Jr?bYtn_7pG)+5R-K(LKPra2cPh5iHm<<:S32G1YLa4p#QudcurX
+%Fl58Rc\bGG@e&mRY]tppbS/;lP^GJ>hE`IVOR`u\Qcjjqga[:9kB2BtSu=#P_HNDh4M(^l0V>/F[_9JD+%NYBK=&QMLf?0U^P2pT
+%]n*nl(>3t6Te!kDC,H:ip\?Kr[YLkm_]KnsNa[u250m"B<s^((I]"85g%cb*PiY8!fl@)0a,i6halcIsihpg$3m]o0+>i_,EP#?S
+%)?fN@F&on_M6V7ha6&**4Z.*Zf@,BGE5[3t-i&1Z?0e.cGF%8c=M?PFU*ZT[5=3\S!U/&_lW2MeF-]P5lQk.XpN+Ot',S3=1]1P=
+%?k-h&N994MRB4K.%PY&!6;O3qZ6h3:eZcC%Im.H]Pht$Rn?PGtDaji#Kh4H<LLGIrT,G#?#F/!c+]),_q9aS!"g%3Yr;bWE!!ICE
+%cr[XgaE"1&Ie6iXCS9q7<NGVR.S7Tpa:t=`<d)+]L>)aukEH%tb\b=_Kn5T8k4$3&b:0,,J15b!LXfOcI#ScH$KYS[^;b+ZYB^SF
+%H9$7K7'K]$hVo:&P#Xqd@`ZXTn?.BaD:]TJ_[#SZbXthIK<TU76XOi`mH^FW"B@_HXN2ELh;OAD5@7HL/>[ImrK&'US1-N'/&F@B
+%p1ZNr-JVHL[VRV"F"G@e(AEr>LBM`FBo2DHSkK,m<(*jG0gI_S4sO]n[6"J*35`G>L1kr$Qri"cajQfIN:97FS5S)/O+gC;R5)S;
+%_Pk4qkc<<oZt:<7ArnVj1FM(+Eb^eGB1?30]m6@HIB;\d33&KY"4X+!=7%ErPWii%q/r`XVq<2+?pFr54ZEZhW8k1QY!ft:8aIIe
+%iMGAp3gQ)1A&r'A##()p4_R)rr7El70^Ncb$abL,$npF[E^)ij\6Z5Em4@7'nHGA%qU]VU/,dV5fR^I640gIHCr"5a3f8O]UL*))
+%03<;WNH.\AF0353<P5ZL3:9?:Tb6Mo1[(7&ObP#LhH[^F-<KP*22kk/#2OtS65s"M%pVlMIk[StY6H\uEP6-iOY_7Fm:BkCW$K$W
+%qC+H?h>qOko(s1G)r?,:AWQ<gK8HQe87#/rh4rE]Yk-@ncO0E\m8T]oH!V6^>*98YYE>];;a7NhT[s@;!T)MTY%Uluo<l@;X"`;4
+%'WfV)cEG\["dW"nD#.5%6(KJ2[mG65ouY/,:No]p;s'+".:t7@rLPlblMhJhGoD*i=0HZIe#V!KW5*a"9,+#_2ErF?*YjHMOBn_M
+%DQGkd^\7!]0[;*\T(9G9QnmX2T9ke]?U^D+2jl5+MpFGo?lH#;$!6["=BQ9:+?75Cn2^s*_(rrf^afR^?8h*c-NMo+>($J(^"hkO
+%OjK*MV'JBbcaAb$lqLq8Xnm,WNPa)?QgcrT)+OATMd\`,LEX:l-/Qb9*&3.?*<S'E%NSo"rim06a/[?FnQa&=S/Rc4.h&1$GZ/V*
+%;_:"6.8bH>p,\X!;#OhCs*+;*X?:*;h]NZ0KMblY&SR$_Qg-fcpq9oAQ)p(3jR$9->\f<@pZX@CZ`gKgB6#)kj[2u140XKcC@0TG
+%#$U:XUnIk"c.jbJ\/D]:#o8GQTiKmlNNQhI]IXMW^<)\)B(_NU)HirngL98I&Mn3#moIM.lmM1uQpXQG!ntmmFaMV(0_Oc?B2]uS
+%4PkN@/`rlC>FlXb0d*+%4XrNH!>%r+aEQ+<:DQ.gTXJ7Zj'a#Lnk'j$!>O];MshaZYQMj%^!K@&6E:.4YYlhuaO\SG*<eTJmAT"`
+%0pT/:jiL8BC=/TCd(heVHrf05L6AId/?N:k;A6R(lI"Zd4@[e1bn_s+Hr]Y=.?2rVYlm93)Ul6IlLNAt*dDN&n[;@d5h$_I"-c7,
+%%QIAM$tiuX=AX3VG48rD(E,FSp3Tl0:69(!<Eer2Ddd8F\0=po<P1o9V2)(d]iJ98oOuDC2PJa=BkC+b]5u$`(7GmigV2p8Iqq(k
+%Mu)\'hl3)Rnh^K$:M@rJ!;PE^N1>+)(5Ea%q`5A2Hlpg@jRFS`\j4m%.\3/5j7D@9;pR:^cV6a";40j`XV1@R@6(Idc)jH,Lja?>
+%3V7HtX!50-V/AIW<b'Al>T5F@Me2)H#]*"]"CMoQkWCAN*+VO`aciu]E\PHucDTS/82l_sl[4JnopRe+IfmpZX?fZaO7cU+'AaWR
+%mQa.$LPL1A[9K3,ls]Kf'/tQ:(IYl/eTtf%Om"\ob`i/09%rOH/p&#A>NHmJT"un??e[J/"VTUD!d!Dt*h]`T?DN`?@gsQuYXn-&
+%A35L2.foN4X-V[2Wku8Q,r6(uA]:i^WB#"A;k2DK:,"qV*5K957@La[W*8FDE&HO1DNclT)'c$jcZUsYmsKSoN[EqEnU1eZp?d+n
+%<J-3<#LFLN\0jA]?U!/3qk@XQ4\-B4&0#5&G?P*(*NmSR[AK)UfoqPo"EAQHQ9t?t.H%RW%T,K^JF(-n'&%!fJLL]<*?.(%9K([,
+%o;C]&Xk_JF2GeB5Zi/U7/@4afoW6OM@'uPt276i4gQADd4H"k8Z0AD/%l;#e?6q*J[Wg6f7>^*`/e!o(&]MoV#FEX@i'8Y%^YYZ/
+%PBc=-rL0Tj`MIa#W*3*-s4lpo$`<G@E=Xrp*qc_.WFD.64rKbZ:bnp%S.0!s(.KSGJIj/T25XQSdr+qHR1F9F:<t=RS(h?skV36a
+%Q*O*4=D]*XJDX:ke\)Dh@<oEC>OnOD"kKrE;4D-tGS_1YFqoi<WhY!KoCZrr$D_W/b&[',[6nrOFZUW"c7@!a\p8^Fk6U+a-![4"
+%DQkT5$+DtQg(G\>T&'?V&"N9(<d%]&l(dJ-?;BY7](.8hhGNgPH>,Cj)"n/3EQ"iS-dA,-10?PKV!Y*bmalXih,?e'img.+LLhN#
+%kXJB4l#S)n9.[(($!f^20KJDCbUtRd;4o]?aPpX&S0OZmd)i"C?=_Br^75qpb-g*mf0QE(*;K#T!fe*n#4MK.&<c')Ze_iJZK/%l
+%Qb%Fm6dOAgQDj>03e-g5%m#\b%\GjmjT51J.SB]3b0T,5D3]Y<VKO]lXo?b(V^>ACm'dl3N*Y;kHp907^6aW<HbO.fqo"H+IAThc
+%!Rt0f.cN?]at[<E/TO&QpSu5a6<'OaSDl@tB3h=23`c-*J01c40G-K&2)t(L\MQAe91nVk7$q"p-ku)/baVmlU3=o'9bd-=@^Y5j
+%nWTg9WK[FG]-i.aX+\bZjkd=aZ)p35UkK^,KMU/iS9Akd-(S>+NaBD5>rcogDj9I$=*!Sd16'i;09cee=Css(96XM$\0A6@7l%?@
+%F@^^5GD2J"^bH^LL&]qk*/O8M;/J8OOp*:O04sItA;R&nd&gV50^.n]k@6mC\_ADsQWaR,nWghKNqM<5nXr4+gtX7Q3Eq4cBAXp8
+%aU>/$N$qb7"O99[A&BS`2n@L3g+pc,d$qt&,Kkh[E#n6\rY,r&-pH%iVC3cK:GIB:a?/#0<n?lACZ?>$fn*eUD2X'gh]%sA,=T2k
+%p.B!s[5r"d94ml1AS%F*YSY7i@Qjk?Wkc/.;@m>GLuJ,204VHXZK/p5QE-%AZLT!iVFEqJ[d[GU]Hr[kcY&e#Wp=,r!gjSfVg80F
+%S%H>_'FRHhWC`\q=-[WQmqPQm?I@nYK;fC7<EC?;)3jR5FLTc<H)5=NVl%AGpC,5J6clI*V5bLi<b\8!'`=Jf(LSYB3uPrD<1jUk
+%<.Y_NZ#<+D0&JMbV@^<Rd?pfFUskd!(JMPaS-oJeefYWW;B4NIoi,pr]]6>p#"=5KXrN'UgRW3k2W,l'VA)M3.u"PbPP5rQg7De]
+%PN*5k#_dA-&aDe_\E\2f]+')h?M8K[oa=paZnJAWANZ`>oChj"_:4T)iaUG4*)"pM91N9ZC#3VS?>q-slhA+SS7EX?OFj(4WY4/j
+%f,)ecZj%L)b4/Nd$Q=iIlHuQjpU0)KpIghsG!HhoQjSf,nImab;q\;=o%lYP><g;C_96HS>-F[6jF<un=mj?r]"QlW;Y=r@YMrQA
+%UWCZ:k^69b()oVpIH92TG1Uhf>ZXng6ZO<]?e?M1$S+.HCm/l^;OpjK#3#nZ_'7e\oQ17Da,[cGMW2BU-1P[<+S[6>?b,)Gf&hE#
+%VXLH^!h!SQh<\(8JR^iQ+mMsgK8L)T/O)K1.Pf6"o).Jb<.XLpJ">PBCnKP9@3`G\a1ae>+_;`>s4h%=j4)o?G(k4*ph]-\e`73K
+%?m=F?aW)^mY52]@2n'D_USb*kNLf-&6if3qgH8dILnhECM!B<"H,d2^4$dPuU(@O[Rh_ii%^@JR"U[EaJP[?n[qA4'GlKb1#O1_M
+%\)9\N;=FS&mK\3%ieaE8^b5rM6jqA[nHFlKZ?bT0o?6!(W\&(uLsGNP<+=IFLTl/NG/sPb.$]@N:#%:PM0@As\WR\UUJRJcGkP+W
+%hSE-0M@`%#Y&&NrOso91`X4Xd)7^j,YMIKB1O,hjCY2Js3QUoY5%;AIB$4:*lBs)b/7!(Tj$5HLTbTl7gaOTFg.re<:e@0Lf\6=O
+%Y=X!*muaddh1tN3pbg2FS1)*PG8N-Qn$#lB<a@'YBL)EA^2%+acNQYN-;6aM4iaQ,hLJO-UbIqNI5-R%5VfJ!!"MrW32j*(\Bo$d
+%MGf[&Y7Uq4()2YVF]m8jb!:?O+E4T2VX3R+2=O5:SeuJ10T8C\J)+A$*p8V82W.W<h[m>:HtYMq^<<CCjhl.%7_;uMP`IOq;'mA%
+%[VkVX`2S7C\l&FlUg^ic;5\3`.e4Zb%5T$0(EQV*MV)Jd9\='Fic'?*p.a]0!9oGYS6aGJ[p%[$HhhjOW[rpgO-X?8P*,95GR0g/
+%NoGLQGtP2"3NsCEe!GJ\&ZblZ.6O&`!cN-1IYspDYHbmaE_D^<U+u:MY]$SVB@!SWGi(80\8;q_6E;^6/L2f@N>*\3c>C!Of;[$T
+%G2ZQJ(J"5Jci#TdboIX*jO+QI;gH/mr6V(;!+p;!OSQoIJC+/5bd2u?DD"JL)K@ZfVC-Z.K..LKYAl:!(DsY`L!2O9b5l'XJN[64
+%MW48Sl'*b`o3T=uQnCdKB11W1Pf(;o]dZmO3^kn5HS\^,QT`pS[7Q,e`SC@<'/L[r_aW;@gV*Aq?l)mPf?b5(*j;m%j[6<MXBTTS
+%a6hW<cTmFGh'q9mrk1f785__qPPUhATqaP@A0F%3=k6:V\4rF9FfC)!^!?L(mtFrBJu,B_W\Z1XfflHqBQa"<DIASHkOuW"'![Is
+%+'>6\6=Jp:3ej?epjK8a[ah=\8g5qVYi"Ta0sP`=fm0K@R<#`T)4'\:?B&jFDC4C#@$P5].k8W>k2d((;2*[1Du4F<;#WadD7nD/
+%dH0El1b2>[=DfA9TTWa-r:`rSRKT;P1Q:l=1&[1.CF%a[(*cPG5uNu#b6u1C!gW&[Y^S?(caBF<*5R$Pc=rqRC7I4ZMUO&"W4r_E
+%eh"=r]i_:ICQs_k^Q40f*HDRii\1V.e)WZ[;66k`2BlG2^1/.6IhVdoV\jLF\ViJ!FRP>J;(SrK28>Y@";Tg(hti&%6nWG.$<*8C
+%[N>;s([VXL@=pXq)h^O]>r2#2B$GIr@n]MAOnTcY1C"ct2*F'Pal&4=E3KXjKh0Yt09GAp69#t\P3P)RkTr;O_TT"R@]?EQU=(L5
+%eone1S=:A6,6ES%]sHK_2Ie@$71`&#B"uYh1FHC9Ln7W;%EjVF#p&'Dn7]K7*8!p#DKJKYQG\94YK@pDlEC_F"B8q4rQ>("(ZhZI
+%9?bMNE&)UOPC&^chC_,-GFnLD!7Pc%)96=YCJ5AU:64BJ[n^<O#lh3]:'5@CXr1*@X;@!O)aV8]637C^"Ud[N_*+%N[1&RlO)9pY
+%X"JKX:KB.:rRJ,b"_D<^o5kTRD0+-VY1P`1eC&d#a8<b7jV:%TXKoeUPLiu%r"sOapd4OD_m0?6=O;]g.=aHBM<a^[j7mJ346,T!
+%Yg4\[(nQp;l""TaX8M^^=oQ/&Me]Cg=)&2pn_Co'T]JmD)t?DM&gm8Ae2rJ"S'g-JE96[H2]hX14pWM;8BsjA[W"q8ICLAP@'\J[
+%6#a4*TpfZlRe*[nhn3P'NJ:7CD>b"%hKIM6,s)T`JprLP7f[858!Vu"eh=>r+#_i7+bMTX_%;DL.FEc(!ldS5H@,+g,%>,ShH>%*
+%CEs;mF75PY\Z<$A1=o#aXIJ6k/bT.EP5nPs5%JO-KI'FF03,tiPsP:)ZCpX]4M.qooStFGh.I>6=48^dWh3`j.[V.u>?A1FZ,pQd
+%7%cW2Q_qFOmLEqTQfRdFW$U^d#V0qhY:8%>$9,dMW*JAF`c3Y.Y<i(`9A\jF(q#!Bb>6@5p)P.)UXr=D=1*u%S[tN](@u&GE,@g8
+%-bh)`/>]Bp>tS18LggQ;M+45bMR%I'(c*sc7GRX.egh_eC')u+6F,>YiX/bi;#*g"!B7'MpB#mY`j,0pW[\h5(C21K5cut"k"I7P
+%VtkI3e^'jYh;(i/TPW<;p5iRZdaIlF8<Iu)FCRSlqk>I>_X9>I-A"cuAtm;J4JQUA&F"0$a6aG@`oA[;s%G\QBt*/#>W[MApRG/&
+%[hk>t'[aiSC2::a%E9"6Sg&`?U.+.*1r(Xs1K0/Hnn'M%2DCHdb6.ZMnf^Bt[j7.'=c7Hp'Wh8!<L57f(UCT/1T7TfNBM'M-WE%1
+%[G=m7Br,mi^5i!$'F<8-<Tb>_dl&_C:i@X`d$f7D;fmUUn$^;1'Y2J#@"aJNgU]!f%W$#$->*liDgC9KKkeW*#AEkCI?EerD%QqV
+%6-6p?FN'!5Z_iFLHD,a"^Oo0ETZti4I5CGU/l76ZXr>)^+];Z_La-3H(W+8%BD-/TmW#H/,4WpBBZP,r.+GCMncSgUd[ul&1kd^k
+%?kiD(g';D)V?Ml6m/_b;N80Z+#aJGYpk-+R`m$^eM]HA(9kAY04adTIAHacjKei1j]pr8D4.X8@0lE$&Q+OD)'?)e)`C"C<?6m5Z
+%rC2@I?:5pkli6Xhiu691iZp/#98DC#U..[J[s").8S\YfSE+bor-aH_%_EZV:!D#\`3:JLrDIGFhA&ihUqkrfhH9B_0$)tF9&'G;
+%5jVG3.kg^DXDsV<9K;/YX&j'KF@@B)VSEgQ;6Z:;;BnH=63kGf!ArQUFmAB7PX5KLHj?(nb(/criL4aJ0_6.+_$55!%48r,^(h5C
+%"g5VT6?5um4%3)."B6q2U,&X9GYnh#D#-jo9Jnj`3XuAU"^@Ein2\V9egpC$CnmMIAOS];aV&s6e4%W_?R`pt"95k=7qG*kOGnkB
+%GF@&8?]?+=IJkVe]ul6201FL!QSJM&K4Wl0\aXO[;KE(sEq*AX9:.Z(oNRM6gBDg1D]hk[*ZaM.7#Sgsod`\K'X%mE;Aun46T[7V
+%1UoXc!'9"Oerb*K*%5l$3luX5QALP-[r=S\M@i6U45Y!mqtmJ!rh`dZ,0`^3VbM#EloPP'1U8DFZKs:5jJ1(]AHjiAbTI<JDNu.U
+%BZmp;Z<:abQI4I.3p#U"7P>BpSRiJ(Jj>;V.pe:@F_.E@A9Stbi/)Om1FB*gkFsrl#)G99LPR_9@-pRKLpC)g!^n*t5ac@lFk^JD
+%_B[Gu0WHc--)YpiQ*Nhafk)6onO!p%Kp\rI@IDOKh97[>?4E8"SRqm'1OR>!LQo/IOCa_>;:)rW01$9o3L[B@M-7<W_QZX4V5i"!
+%'-F_J>3',[\[tal/X2M:.+SVN3$Jbc9*p&P!]Ni'^EMcH%E=$cd#,N2$[/N7'm=G^s4<Nf.podN@UW&23kU]%1:]u%d3M\U')AbY
+%I]6l-'jtXaY&#Q3'Ri]cJqeG7%0?W:i@nW%3\OR=*)kcJo*Q78]&bd?jrTtA6X6+m^`E!.ndJ.QF_b6RGM?e?7Q<XJ)TU__XqWHE
+%h(nnRhL*krL51'0FIk!Yf=Z7rXr@p+pOJSUPi#p)9%+STXkE4BEi3)#d4b)SbrBqMq\p3]5EB$Hq4!WI\0Vh<HLEm7@=eStf1#QC
+%IGoGUq^)B)Cs#B?j)r[t&0uG6F+5cFnB.oeTMo(EjS**s?%NM0=3dpR<<kjR1S$:KKfBh=KL::92/<BMhZrCB,$FU>72'fjVt(4M
+%^7RLhc^^+Ef&Os2a:]kl/FY[CVl)ZXgMe'.a`cV21i%$NaJO];M(7SOddLE@Pr`+q6N#V++l3je]X8N4-n/+Cr7ZP?`se[1(>R@h
+%S@NG=aXZ0l&dL(2jgM!@=)QEhEqbePA((2?C2EbFm7Rdt@FkuX^"tu?<sGeL`FAN;1L*$s*:b^QQ1ut8eCdAbf&$k^[b6?uW2^RV
+%$KW%#TODQ;4TSHab-;WC(@o:%0X#)I'5]1+bS:F2SjlZ'A0ukGKu+XDXAK2U13kOZY\P+"TK:\\Q;doURVUEo126V=,F]BWJETO#
+%,#l0s,:[I)kTk6!C3-p_V7+`e0!U:WUThDWXV>6h[jS]'2003mNn\/D62JRS?jZO<>U`"65'HB8\\mZ4(s_f?<)FHW+'/]\_r/8#
+%RKD`=n%`c*roJHaH0(sYS*W2L192Yn@f`(Q3O!mln/'&!Et)jZ$Yf[/`MA;t7LI8]5pR*U/*B_:9<h25g-<E$j1I*+IMo!3@B0>i
+%cuO@Aq1c#t3Rhq&oFq"0d>pR(?umkPDPo4km7,\dmLY0B1^c=6UI06#2[XPPGM\iUgLN^beoW-]`JPnbfYk*qhsGfF\kp-2BCZck
+%jXeOAS8Q"bP[(Q0n)AL\52?-bW;[.3&3#IZ>=33cXjD8A:gWbpbfm^iM0,61r<M_^E9:*.(RR;?jq<cT'KsacaK<LA?0W(T#WQOF
+%<lMVLl:iBs\;%Ysh(0qN7.n?a8+9oi[cI/#rmYFJdf35FWrZ\U*r&ZK_.Cp^(/d]8G`#M]%bQ1!_Qm1>F,mt!MEopuk?Yf>K6gl?
+%(q2W0R.TjL$f\F9>W5W)oiUcfm0Sm7booK]j=[<3D=.=J-_f1b4?^(2-"#L1)f#OLh,UqJ9V864K0._s0J;Ki=sUIkT:ZaV:>p3[
+%n=ZI/oj&M"j/J&1`3pthCQE-f[ntEg2o)GcpK@?=OnZ(cI7ZT&;KC'CgD66#'W9,+Wr&A,Y;'o$7A_ii<h`%-CBTaC]F3k(7aRoO
+%O0.k'/t.,HF;%Xf(_]?(Ae82&QbPlUZgI?o;*]D]+Fu[X2"/N?O!n64.gfECO-3*LS(s$rcj79E&uoORHq6;4'XX?e5l'(n(qW^S
+%%2s:X8&dN'kd:gJ/`q*&>GmFXfp7)cm)Z*[Pt7=gZ#paiA_5j=D4p]TQ`gY8nGkqZKiFedmL3!F*&3Sef9`^!c!<T&LXO[WM>i`<
+%KLk.#fq22Npcg@`]/XKJlP6=dl#09R(R&VhD@.;k4`3M\o<q!pE?K:Z-tf2DW1-\aAa[9c<_&9)RVVT]Q6[Wbf'S\N&rC^lcL,Kq
+%XYF0+194Kp((%F@3EJbVp7d:42]97nW$R!3DBci09+MH0C2c8k.X![5UFXWs!Id,&Ja!O-m?DbCMI&'I[])DkBUa$SmE_9U5dS5P
+%HXE@(;S0[&>oCge`$nGkC:jS4(F^q(#NXYI9^2?VGs<3#ogO'13S27":R0"(jXhL`UAL.dI-RE.e4e.2o"4>e'Doi0%S6FSk:h@"
+%O."K#CdT"WI8!`3;s`l0P$QH],A6[p2EA.;@,u_$a<IF_h(,#U7$sh=1sqZlQf6OK[d@(=,]eX6ds5B^M]<@7hVbk\:Km8%("l77
+%1ogDu9m/QVj&"pJ(8*r4+C7c!'\k^X\OS711NR/<!$2B]%F;2![Q"H/;!3q_[O6k<TSF!?iGC3u[A-&@0%\gh1p1#$mgt*QC7N.F
+%Lr)#b^NLo/qpTKR^A)i=o,;n<)N'ck@D1IsF\(*/j]U^[IGqAVhJXpd=O+Xf37W4C]6QL(6,rZR9l6dpC=4)p(6PBi]mEfE"OESB
+%&\2ttos]f(@99]bV+jrDl_T?n.<t$dMd^,5;FJE#9%!E)A]QuO?*3k`@qdttA(hs[ll#$H"pSrE]hMSp]m3'cI0F:;:\>Y"Fc_i8
+%,7Q?'>D^8A!.Q=[Z?0g4Cth&HCL4Qd4#NP5S/h5.muPb:\0ORScPg>P*#qi)EE&*:MAYMG,oVX-YeL^k\6TGS,GfpI>#r26Km)ee
+%92u,DGK^Z5/HL*[ZHQ;%n972h@>XKFma^$3W@)-^$=^9oG@"H;4*Q^FDYDg.[o-+G@G`SHGDNINU+gK,C6*(Q'qE[7Dl]nBnVQr3
+%5_:M',\`,)?Tjj"#LG6q4(r@06GU#m/DZPR<JS%R%:G($p#u8-`:!A8kL+Q3oiU!)dKOrtDLfeD)k`t7D1*q-adoS*%[Ei"2I/7B
+%\c#WHZ(C4Y:30T"-[4o[8lSY'Rb3:]=ec`-0Ui<!J_#6i=7jnQ'g,)VFXr[X9+=CU*5\mc8fFecZXp%L;%*B20864e)5qSi9<uKQ
+%e^gQ-fagp0jS7-#.l-O!)!)a!-#i/0q=RZ\ECG2qIXe<FJeSC3L^`%N.484(Fm;MRih'+T/%R050oo$L(/g@ko<,f\(V?nmb]j6T
+%:1Rp#-Kle0*V9?di=e/bbU@]=?*gW%Zf5+ae^5=i'%r=gQgLQ#m&j;k-DnpE@9?d#Yar4>Wb'R(U4dqSJT\-Ibr9YBn2nkt25K'!
+%\N9PVis$XYTcC_M[T*%#$/d@^]Kln+\'P'jr]<BGG5l^F6qE%dHrMqO.REa3ME)hB7EhPq[D&h00d4"Z#6Y-.V&%j?#T0HLcRYe=
+%$uF$jh?#&D"#Q9'e$Zee28OIbefh)"6;<;U,7Mp6A>E#r\"UH9g2q<>)9W%WB8IP#O%jDT-WmiCJH:CiOQFWtXb]sd<6^"?eJ<U]
+%JU+a$'UlLJXl:5oMYF!'IL!l`LiLrhfsqcsl!(YSW`8]S%4?#Q;U0AQ*t/D1CVoZm6K0N#]P_t'"5R$QU,r+WHb[fJ@qE'#Z%H`p
+%aXmnZDf<J/6EqDKgr#<5<6K%D@*;keQ))i5,/50gibiV`Kasu"&)nh!:5$k$X1\m0$JsC]p:^(U2Sc/[;H5<Df!#4a+u`obLT^)[
+%$e60Qk#/_>6n9ge5;KMQ8k@?)j^P%^HZ`+k8E+)jl7GThh:_T48R8SS[cMdQ4K8(ZP6o)#9Xh0EK/%_2(9=UN^?Hl8lJ6du264kL
+%3`d-<<['a`58004Bc`qQ`e-]0?nl)*`ia:(M=N@#WUBskj;S?VrARrP)F-I:-\]1gW0h_agaqK5`]5:E?JDb"3u;9]bb`q$U6'*]
+%e9L($IZ$oYmD."M*%qmfmtsn!@I.^?[qd'b^6d!SXf<o0-]d-.d0SQT"c,C0@Ufig@C1d],G^,"a=2*&J*iZW*_KA%]1%k95$c$r
+%NADFkc&K'>cdBIn\5gHTkCu:';&5'V%7Rac:%;VuF8-"?^-_D:mZoU97[c`$T5MSO>Ep+7GDp3.X=5R9M\3BC/)b?.\M#SK>jk7A
+%e#=pAs8"QZrDH)<?M^$5Z7Cmd%XYt?Gq%S=Q**!<m8"<]&!^r=3TqRW91a(!V3(D,eg7bdQnWVb%>?Nj\W<<c!`'V[57EVWbck0l
+%DPZ.R2f$gGg3%0'9Cl,)+p^l'P+tOfQfJI!oVC>0=!pZ.F8tNGld%-WS/JX7n_:a;8?%P"hbuqr]U`Nf!="EAV$9j$H*W8u8m:ss
+%;5Pj7oK<R-ld8Fi0F*`Pr[fTOeVgXp^1O]n)p1tq;&'ZVT;^I<!`S8+1J>Ff*NEH!1&?>O\].<r!3o,gnAtN4U:<cp8!J*!N9PIr
+%EjE2>lO%p>C6`f#O!Ib*,K4Uf2&+';h6afD`_X:e6PUi4fT;sOijLm_W8*>&G'Q1+Ql=7p_T!-2*r?mf-F$bUnPY`7[KP!@\)'LA
+%cE;<,%T[6M\K_;f.J/F9V:$&Y!7Ck/6SKT_X^ZVjbK]'cIN]IKAc@oA=ti4&:jYikp3XAD*U\5TCKp1()PG.-+Vm]e3='i@U^f9X
+%dR!*Ih_Sd*gD&X:)mnht>s=@Zb.G6&eY4,3*<ZV4f+Pjb4&XL:eHh9r3Rd&gfJm8iKGO,X\OA4$6JcE)c=^V2Cf/7-\]intaE?oT
+%k`I6:VO")*o''(dLH]V$ZH*Hfht"Lu1\ImP9"JmGRm(^Y!B'na+,`9+(?bIP2No_QF[&,S_u$!:apt?*mFsMWpjGarBN"L8ab6#p
+%04$,o-2>'`eG6s"%eZPF*TE;,,ch#QXt-[jAClc&<&7-CDoV9VqLI"sqgr$b_gX5;j<mO`^2C*Sp9W'SH&G4>2gsO(\Xp&F=EFO!
+%@8q0UIb1c-MS$PD[4luO&$U16b.OJ?64X(o\,qFI5j?[hFa#LnlA@pdN=`9O]tnB/o]_'pBW`Rk^_MS&^-@PkJSYF47lMOs-`:U3
+%.UK4['o9J8np,$t4@<6%-A<%#gQL:Bm@JuI)(>o.Cf%4b+tp^eKZ$QoQn4:6n0"4<WqJ\U(Gd<5.lFP]^Ms84*F&<5,D@Hc>@>l=
+%oj/XG*U@::SbL^1Gjj37ZgaBpK:3/\7ha)d5PJ)8>OTIf2Esjj%t/[%OL[e=@.j#XpL^Rg%YQRYf\)B`f5ck2\2)X`D91$fDteCJ
+%"`M.bnX*bqgE61GU:NfuJY&W$R[r?pjQnKP)oM&\WVSKa7ON[9WKENF)`GL.L/U6]PaG)Z?$./'.tOc:h8j&@hAiMt`q0/cX4c6t
+%lb7[GQ['m5qB]4jk("kaIK`3GhHHP=`)SJ'<a@Z\B&D-(+PG5LRn*]li7i7gg&9Y,M.doJm&:L"/PIas`/dQVna<)/feu*thc,C_
+%^5*hbA.J5^0H*)XXnIaK1)e/m3Hi#'Ffb;(VeU++GC$lN>@d*lgbsY^UOrFV!L9*3._"WHNs8ZrluHNd1q3h/\+@,eD_$1k)EU#l
+%l9f1;jP7uC*SJrp_f]7Sp;u\JS$H8MV<md:'!-V<Zrhbe>gT&^*oDp^IZ#aOaMm/1L<e_LDOs#)qhT]pg^67+1K<aU>E6S'AnAVF
+%m_Km"UA!D@PNX7$!$-4*34#e(YDBC9g(:7lFX8^5rPis"2>32iO[!LprPcp[>rmKlTL+fT/CAgH6d%b7`/GRsG++7s`q)gF_"IPE
+%*1Ghu);K5q/'*T6'LqoMU;%N,d<Hhn&(P(fF^TXmYjo7Q-g\*<1h$rlNX\6C8r*!FA(b_E\)a5t.H<%A=G*8hIfc07F,0?='$UNp
+%;?W!WHtGoYfDo^f0Rjc1o[=blIG7dB+.<Be!e892:!Js41F"o"]?RBr=K52THZk@&1"EHd"`_cOj/b-*hXEHJ8`+odFTYW)<E(j9
+%h,.08/b3ejfTG!E;<g$iIO9RX$c"TdKmm8-mHL+BYbEju7l!hNmjg*!P]X,W8AYY4G4[u+[tD<BONVK35((_Yc`1DHUlk$XSSS&1
+%IcZk7keLeZ,o9H#mNBrjN9F2c3uY2dQiu"TRrgUh)o3Q\\%]trEKFHEalO5m3n-@D$V7!!Wdi(-e-*%\C7U4pf>B\;iUjmD]P9B;
+%1Su>)lkt<\Rh4T)-`HPh10%aA2=eJ.D,ZI]r(^aZ%_)RdQ:>-ioQ%qe>\`b1#!`[U^;qjqh\A$3)X"\b&'EHq[T9I*o1]b\J\/6T
+%pAPKaY`s;mek9uGb@\5j+CH%31!?\a$t1SO+o1:Ado(cO18&!S'"qDR"3EkHo1BV'/O:CHoPr`l=Q;GKqcb\a[a-6n-hS)<VjL<u
+%.*uXX*I%l(l.;qoODeeAih5Fn>%/$KUgS]f9tW@nJQUrJ0`ZkV+fe1k];/Z2iq?k`=!N'SqWuA<MWYGQZ:HF6_&b,kef8#!X'_hd
+%8C>Jt`f1L0/S!!AphEZ1m'`Y#]dJgsJB3cL->cpa8<3=MJWpieF?N0b[lL\BQ+#c5C+8,Qilio%kZ^37g?`g7p+09crP8N;91r5Y
+%b\S&P]#I@jU26BYG*>n445bnGgaS"Q_?DM:?HTsFlkZ9NF.<OsW*ZdNX0Y751T^gla'^k0S[[fKlK6>Kn>lUjX?*sNPc4@sUq!=9
+%(1uH*eOe];%Xj73>K$W*`C6AG".P\JI_sI,COu8fE5t/)&"83sCn[T\[f1p`\Q,q>L#k8-E4GL$jQa45JI,l;fIWj'2K).t"X\B@
+%4?G$(Wq=mkDG&?^cB'+9JRp_:5k#M_^Sq,0V7`!JnO)H_>8?r=.;4M0`7<-Q$<na&Ne+%&E>>7o?%AtS8aL5I$HS/hAT#Jb:%4c6
+%YHZ:k<^7e;\o-E>W:_KY[Zl&YBD!5,>>Ff;4P5%:;2%G+<m2:d#F/6Sg=:JN+N6Np$KB[fo`uLt[$s54[9Ntf5`#,=JOpXPfrejJ
+%^HU!1#$gfP9&<KNKF(]N3RaYU3SYDHCH[QU]8$VlP"L6U'\V5H68/\YAB(QWmaeFN"ucEYDRU)rOQiVJ2M/BB,2Z:FGcL'F%Cu:4
+%G$:9+*`<Lf_rX)ti:^ibBA-?:^[ID6h-KQ:,3(`6&)e2uf06nC/M@=G.-RJ'+Z*D_mGJd90L*:!R`&u7^"`)p\uCdZRDF3:5e?.`
+%G%#2G2n>o3D>ZX>YoufjltO[IiI8LU>`"(CiG!/;Z]8nuR3i5`#nD'HQl_u0,>*<j8,%h1ehO9dAj2.g[II2\nSUa_d+D7n\f"#K
+%+h4h>*?/6c94S?#NL,l0n&fE<Yg^s*jJRts[;QsS,FY5,7CM$/.RLe9],o4@&"2O!Nk7h_C(\\79COjEktG,]]':HP'uV.W7-r,A
+%cM<H"cGPJ/\LDPf+u_@1apjFLgR<\%oZC2[[-M<<N*ltA'#Hb0HJ3KDMC.$il0m.2d/YZOIBoMr::SG%l?jR"TAge]dCl4uZGa/N
+%Pk=16=*%d>qH`2U,$TM0Wi;GF3DJV8k_'jB0g+k()/a&(^TGj5G3b/(DS3>+XW)S+hSUWphPJ3lgZcJOG[qr?9?Wu5<SBu\M>t-N
+%a^kXJYf#FrZ,nDGGB*6oIk$4#c4ZngmYe$YZ9g,!+>Eo>Q)D66RtanEno;$`Q`X`FiBG&e'-N=[df<;$kYVjD46^\%a<j`bA5Lu3
+%h0oIQ2AE#6pb\a$,IbK1[YsW*$?+bFg)F.WH8EtlC09Xc\rNN7[OTlU+3'78Mgj)3"c9,UArBiii""=o(ehW%?W-i^<(M(`2tb`4
+%X_'I(5^>\aK"=,0l9,6Vo18beia`BPb=E@,*nqls37cGoKu+orkSE]hM%:*@c#/O%jqZFVTm`3F=+A%RLg/9NXQ+;J:A#AJ.Gcs_
+%`hLgdh=XJ7FC2Qn4*QIpSQ>bD0]ni-jSuCamWY=IbuTfsd[Ro5/<XTQUYpRfVLINGYjUA]`#>J<e"SRo?-B%T[9<nPai,`>]j]CV
+%IRbqo\a1Xi_'N,84dUI>eJnOkef.?=)B&)X<4f4S6,K#"doCX]EX%2lX#Gf+$`6/jQB!;GM<bW8A6r/3;(>5[F2dr[+XDaBdaG8S
+%e3.HC2\pK@Jl*.uFZYX7oOBAZ56V:d$Im-M<qZ"SCU`oD=MCmK]i'riDlIObjU3aH,Q"N?L5TMSk@iS3DOAu^;Nmcm.J+,2OgQ1q
+%dMh,)n%l'!g)>ei1;5tdh@W!:ncld<U9Err0'sFDqhi/u2kg45]YASE;%<D?AC+dG^HfTCd%tQn$#[L85?KC[48Fs_Cs[gQpoOOs
+%1WPu>CKRQcom<G:ZIc6#r=J?gI``6I2G7_!8!M?H!bHJ]kd9.AXg#0:%Ga(E1e8&7>#j!?U`inLk4QDO@(e.tW7HYrE<ED!lR/uh
+%o`:K8Ro2/fY.`m'BKrdmBM'r^(4:d?B>9;2)c/C3<@L'L:mG7L?->,Eo/;+@;&I(]N%4-hZ9,_NOI5;^:I/P<XZ8Y<NWHH@hj?(?
+%<_T>Y[C0\[D0?H;!&sp\?eu42VKq8K"^'SL[<iFpIib88CCR&ea;]KTB(Vtg2naaM6Jpb1i`7n;hS)omEK7AIY5pE7R2uFYArIA#
+%W7ki_`]E0Zg5:i3`si5T31`c<;DXB>1G24%hs2'1Gl$h5#EUY<0()lgWJJ*<<3l3ugni"B(Z2mg01.JOs)_a4]-GIRe]`f%!.re+
+%U0$LL4uk?'<<:FJduL4nFt;8#U7F4KDmP7&^NF=n0qu:8I:P^GNd0NRb&SnTeICkfd%c71RKL8o"H6,d[Q&p.\du4m<>ElFi,9PL
+%4!Om4c'uihj5*e6I]>=:YrHo0c8?2QA\'&p*b):l<#BZ=K"+`tkTP)I[GFrXa5Q3`#,kZ1$88H<6D:9+*QhVB[m2ZZp?7OF><".1
+%g7/"^YhdI2^#/[;3:Z#rk"l'hXL]:E=%i0+h,:NTFR`"JgW_ukhE%CdN1nbd`c(&;12+`.n5h)hRNBB[jMq5dK4ZQLe[ll$SasAA
+%A^U]5R"q]N:s@-@649)n9T\6Po(tDKmrq#e,->&lA1j,7X9BfjAW1aFL#1<gP2E&rQCPT>Rc]ZSd1P'[iGZL)4mjM"+pp=2$+DY,
+%Ri$]U2][u^V1"8Sm#B8PTAMVY3+k&<=_U@aeP[VpP$'7"lW[*(AsuO-Xe)J$Y\U!l.AWbsLbarthTT4&4H0=@%\PEC@p:=ZN%k5f
+%#Q#7di.3n`:[^i[5Wh:g`DT3082&&so<[j8Hp<\:2j/AKQ[5]!8dMMG`>2nGLJ-q3[00BZKH6EWmoq>BDi];K@(^2PB>H6M\cDgG
+%YK6%&V&Ji[]DE/)BYV/>#LMc<.bp!Ief)L0VUMc>I4P74[Gu;kcNh_HO?*&.7JTg1[Rr5Q-YH(QE48mt%(Q91`8N;A$/s<VQe9P3
+%#1ssfhJ_b-gbDWTd$S]"mT:aL.qJ<XH?sSsoBun'M[kRY;:RAW`f2pg8?f>1#Q`e4&TkJDoMLg(KD->6*?/"!.8<%7Y?M%4#&u6k
+%9\\)@"d"udHlmun>?^7!&>uC8(QR.b,C%U=h0e!pqL0JR\%Vp\FQ"bJ[F(Vk57OnGL4-n/K_4!51bn!3;oi$<"=n"LEmP`^#MBJR
+%T@h*CBqal-\pK&1(g5:U>%@o(h2'B8!SMo?QCh("[gjCL`VlHTA1c"DWdrV3'3QjOAhG5-l`$HDkHX]A1\s]paD?>SMj_Of'<U%,
+%qZKd`AiXEOXdAIX8C%C^i;`.5T'plrq'bs)-l\b"CM&U:2B(H-A^S.Y6=XECh/-'[5RKe_C*>M!:h8>HV</CTh7t,GZP;rhmEX5U
+%U@2,aDi+IlMd2BWY#1I'oM#KOVlsIB[?j7d2D2W31oso4[t@6dSR>Ksa`5Ytp+Z&oM1N'N=[[6S'Hg*tJFCd<X\.T0M6hc"XsbEL
+%3u<-t,i0133M*a8E13JW=r8@PRmYSs_D)"pLsbNH2F0QCLa1['#%g#ENO\j#0k^-9qIs\'L-k9@-L)ft9Q)dH5*u@)2G&G#Q?s3t
+%,iW[g1cG1Z9$-Y\2`IuV!W'#UWH$>'Ld&f#YIP9*4+mc-^TolY%,C"B'Bmj#7fK&`D0BP'e(S\PF6e@(Z,NCUGN722WpFV(C?6X!
+%"HB51p[mrkq?RB0ErtSSH[BGc,PoCn-%aM"nOE0.c\$V+GIlGEB&5^kUX:H3i"gpJAI;/A0e6V1hRq_ENK7p[E;K/s)AMV4hB\Ol
+%`V89i&T;37`2Y0eogU-Z(\/@]8ed-sRkE'*J2Y#_"MTcMQG6sEYr_"Dq"$T/H?4L/ek%;l7FJZja]0n9CXWX8(l_"/qnI;m5pc%B
+%CXu\=G$+]khX<_=AkYp5\o*=&M@HD-"T4fkFg>k_RX[O3nNG_5;s:Zk/1n!55qLq0UhV@2iR_rNHUVOq+e8KHG>T*fA2YUE"Kb>/
+%mt0p37=kS$g:P9.$A)a;DcPare8=:F!VW>f1pCR$:%4fM(Rn;0,`G@i/ncGXFp`P;9BofPU1JCb!Rhd`_5@P87qRO0:)UiMIOOI1
+%Q$W&AgGB+n6IYFk65IaY6sdZf6$'.(0&CJ2G?/TWllh&U%-:LR2LXc=Hg<*pFn/;8Egt3herFqD&CUs!QB25Ed/p8G<>cJm;M_&@
+%l%&GW_7ngpVD#bOo"Ai&3Vr/K3cE8PltT%HRFtRrAM.b<1Cnm:jCclT0^(bdrReThMg^!L,p0o$F"L[;FcaGh@!r7IoR0uX^(thi
+%!A)D!c%6-0i)F-L^Gqt0Rq3fh"E7e8W#>j)gURReZ-S]*iuMec1-++G6ci_MU@pma"MGn`aKCpikN8_+^CR(5D99rsG1J[O-1MH4
+%^r&\h6RS(!H\02^(7u8%SF>XGoqTp$3`/CSO!O,9'H!:1KIq4)JO(59l@k,:2bcl"Q-P28m+7!Q#uuf=bfI.['C?!%HpOG6pO9`%
+%Nj2-.6m&JHm:\%c(OHZTVUibuoima+^fX8rqeM&V<+]J%(e=qO=A^-sn^GZ`U6F1ErZ.2e&F\;`oU<cF+5W1iXH`MlP:'ufj(0c5
+%*I=&CiB>1kDc7on^pt?Ser*1<@`AgkiruNf"qZ5mX&Frp<%0"'@74*+;kWiH@hLNU:WCs5A$A_iYG'-o)NWVsa#5J%WX6uc$QF_5
+%FDN28B_:'pf!NlYAdqfZdPGD&bJ3qlAn2_1M=e.R4GB-&S<=b2Q=&<&kf),Wo-OPuKJ/$^*m,$0eG%]0Z[uEn5%/h!G5oj+$7@[-
+%-$=(W/3JnX%ZqVDY1OXrH8$/*d/_P#_=h3B\oG15[@*EPZ#6%_]?+7Id%/T1I+JVCi+P/].BFbSQQAe#DW/6X?^gAOcG3nqW&Ood
+%`d'd9Uq]#FK)5E.j7&Rqol2flQEI'PB2`n@GBYAp$uk]e&2dt!/I/Ukge=Z:RjX^g1U81o%$L'Y6VZ?e":aO)2.(n>mV>X```FoG
+%luU)L^K[V^ESG\81r,L]65dB?WYmm>:sl0X7dpA1Y;U?+F%"3R/(@P\\7J"g&_LsVg+S@e@ceQ-7nO0B!7;ra9dJkWg9,Xif)Rs%
+%!@WU(@uU]>K/M<7(`N/r.@"#AG'0_ugL@T&$J85rZNV?-\hQii$c4t'0YEm$CQ"_)1S*+>8Z`$4bFS=W%rU_3b`/i!:g2;WBrYrJ
+%LOV;,Xa>#b6MW/Fn$:[WG`\?bVtS$c[6ffFHK!bY[1?6j;6;ll$8V<tCE$a?8;j@^JV':=+LNP8#U%Dd!G/_O2<iTC#E*?MArPT3
+%nKP-7S#=VVYhL)D_(Y6t6"'eZn?pTlB\]Y258O,*7=Xd$,=(GZr>ba^G1i,3<L1gg0h*m!T[Li9Wps@\dB?Pk4s<CCe9(_qLQhKT
+%\QOGkMK:<>efOMrPGZlr4/ha6-U0jTZ3/\TYaPpB/p'-#hCf78d;R'i@"4rVUGTD1J;.FNhIiWfZo<rh[N*pBV7(.$WQee8n'T88
+%7Ks@[`TX,:qMcq0o7";lqE!`,rD]aH*^fAj$n0fm>_7d#!+1"4g7KHs<?5j[D<aaW^I>*]gMM@sgXXTWd!&.WX(J>qoaO\@[*E\_
+%2STd.4l@o%l1>g<^f%5#+NMr.']=Zh=2S?TO$CtFs.u$PpXu5*&h<!D74,#,rV-&A2aZodpX$E),i;=s/%/kBG=`6i1&Uoo&3ff.
+%p$t@@W,T1C0NekO!:OqS&T,1q-Qp0>'+HT+lb7?=je]-$gT;_m2]lFAJ=l7;J(E4L[:a8sbf/WEc8m?hbsA`X5Ac;g:piCZ5EKB;
+%);m*>NO12Y<K9!&-*2101[sIdbcWOX4d+po3SB#0NGXAh.JLO8Mk'*6,F)Z`<#]*RX'!?.MsqU6MBEE_b<[N^hL/GU758`<J`\@h
+%p+eGJACRb4*9AK8LtSeGQYA94(U?gjB1eSn$@ElSG/+5]TdCU[`5@jCoj1bFMK2d\L7=ZP$Wd'r>RcT`XD<%U\<*W(he/b)5K."\
+%qKuOLYZ+^'eDjY_bI0s>)Rhe?oK1(scba&8&.R'jFtlst#*`&&b%!"o_fN?m2(*3!kZug-%F7$l5[/goM*g7[KWl(.Lqcilc`TMV
+%Y2(&Z$Jaq2UZ1)VQ!78CRk':L(W]%cO)H7!;?YKt5SaXfVL[CJ!8h?/!b3C:J2-m/U\j"a>]'Y8:QVK_M`:>>=Ji_tRbWZ1^s<Q5
+%lZOB5gJ^2=gL@E0N6n.Y1jb?f/ksU-NkaJAp=2_kZnDGA5sAsgoFYQ)Ec3*d0Ec!jHRIg4Fg@nT</VYjf`7?sCFNH`=g*kO4""qK
+%/9MPKJ!iMj_4N5[W1NM.QT0^d]CuQZ'-!uW$&qr\DR:=g771iVRtnN?f+$C)50+fDVdVEnKXUU?L,g@n9M:g+#C)%S.B<WEoH*%_
+%DAp"3R9.<)/c&-o1WU0;1tV$Zgkc<"+)<7Uh2PDee,-BHZ,KqXDEcB]2m<+9L/OpX?q(EU4W47=bG_";=/\s1s4k)nO.YQ;pAr:1
+%0*Y&#QuOUY:aEQ@7](Sh]`4l73P<pmA:-eV9L@X(%gI*e6d'WRbm\KIbP8+5Wf7TJ)$f_^57Xff/8E#aP-a_oB"]?W)ETLp&9bYX
+%<j2if8nO["<kPIK2D39;(rT;uhPFY3FFV%-Gt:n9Gl8]f0UWH?-"*@?%QZ,#;`>>KCq5')b?";'9seJ1eR["$Qa'"iSA(;J="$d]
+%4X2a]W]<RZ2B)YX,9)nV]X9qp]R_!g(&UfG0>.Q#W@Dm>P5nT`X/_q+EbUIJ"70c1K\KLX\a/1No]r]8nj7'ZZ8O@NLr,p2hIUe-
+%#l2aeU<k?^qNeU!O/hOQ5hR7n?*K[\mreX6q-^pP/sd2#kjJmE/#0+TR+VC7Mmd7l64NHA9>%LH'UaQAY">D?MdgG35)Xn9*0f94
+%l@.W/2kW6:;;\hOZ#6bZ-$<qOTfXiI-@1=8#h+tP&oA(Yr*7'*A[g"S2".T5K!!`i,cR,AG(tI\Z++<#JE_3*r;(?.&<IRkG-8XC
+%Dt;)L+`A%#[MY#iL1[%:a[cDXY$:KgYL,Kq!6mX]8*I.eZ#u%`h>dE`[/1Mh%>WT1fFOApRjrs:bG^s'MDVSLfU6)Lkk"\2"$d1X
+%e+#/12(&Ptmromu[&_$/GprpTad7;.>g12u,0X+rOI]J:`dJI\]^[g0IkU3gOOh^U':GB!!9F1uM+45!#:X@@P%$:+a`#c@gmO3A
+%;FmBV3o.W5I;>HFeuc4-RAD$HN4`U#+V]2>\!dp5Tl=e5?]<K(!Z'D42t6lh8nAc4@\V<rmt'.mnRg'&nW.&VlHB%cci3j/^\PVc
+%romef`W&"!h>d&X^]2L7s7?9f+9%>9qnjNTiV1*>nLsq$huD0o5+2H;YC?5X^\de]^]1/1q3UE6^Nf_ODuS4PIt%@ZqBc)\q1&D+
+%5JR3ZIs_.3s78#EVdJ^Bs8+JLpA_jUq0TaIhgG5\k0&VNo?L63hHfY/WA""b[&%,"?Wb'm[Z6<&q"s4t*m?@Yn,2&AobUOP?GF!S
+%;#PlMTt&W%o.RlOhsh%gZN8b!ie(i-/RW`jnM)&goNEkboSaB@[8('(\fhS\h<[[X%++"[4+@U*=T>(+8JF+l%*uc70$rtI?L6<d
+%A%-QI)r1NZ5(L?CJ+<",j^7rb&-)5crV48prQ!goh=(C80E9MEoOf3e^J<0@s5dVeT7?Y75Q1$-s70fPq3QU$j2XB6r1!`]LVL/g
+%s885`nTEg*HMuG;_RniN5$J%ab0@+#B[U^D1Mf\pkAiIu]1ia\A=*h1!HU,,GrP038-W+fd@;XJ)r`LJrTcne?!:Qs!KA[Fd%Bb+
+%:H19[iM@8e7d&:^gE!'Ikf32arckE7]l*K5.?"gUL3_Z3.VK[L"B0#.)YN\2r(5eXVbaPnbjX/1+.(h=_EJeGg54QTqeboi[Ellq
+%P<U"7p#6FAqJJC.F[puQK?CiI)UTTaLH.OoXBg0q]nG0`o.LW=:ZPX8e'n?kQs"Vsh)q\af"2=%D=1DAa+N-4@mK_SBc:TgRQS?j
+%_<45p[K"7-AqfO/qm\*KjnKr\(Ze[.5AA?UOQM7[15tYr\?U.sg6hjE&qk.O=YVj)h=TO?I]HOt;&)nB)A,<Gfk%8@N7@"5fJJ`^
+%gA?4a+$_d9P-gKu]nf8DYo+"X1+#IrMkf!TQ91'0^#XQGs'"4E`-oBNQXt;D/,]9\JH2<-oNAi7<[M_"jcarWd+#4po-(k,)GY'<
+%&G\*-QWoU\c'G;_O^!\\=/n)hMqg!:%E]N*hS9*]^iaU%X82<ki:Q"[R\dj_P9+?[L,HVAMZ`#!gG425WX8I5LAk`,di=6*o_m)M
+%#JG[@-hh4G>/B>1d9\^58%kMlDuESW13DpNh@88"A+n6@fs%iC<SK4kbW=6*no'NJH:?PI/dLLXf=*hU9L_6hA*oUhKQ.sh!147H
+%3Vb@LFp[9i!109XmE5@\bl,h%O(n*'X1?o$lkaRj,N?M(Uh@3JdflIJ&WK4@eZ,JFEh)S_l+?S!Lj:*Nf?GsuR.KW#<#Ao.(WI=O
+%p[E9A'i$it%:J7:ADbUiko&,ZGHXsCR$FU1^sX7a(:T""ipP]!OJk!d^8dO1=R=>R/K2E=<i7tQ'5lnY=`eY"hZpBPgB-bi]"IsF
+%<'r)eLuFhm-*%HHN$Se_.a4`3/fp7Uh,o#akoH>7hR-*oD0l8#qt=Nc@>&X>!9fsH1)<E7_g#b\UmB`.Qg3i>]!bgL)FatS\T,%"
+%B,.60AZdGCn650^aZHa\rRfY7bcU*;104b*/^/:T[:AJ8^:&%#/sI^nPF)+,#&+Q^efDE_5Mg6[q[Q(H>cIqcDS('80]VY-?.TR2
+%=#L5pV`A'BWh7$ujdQ;!"[e<H*Mi.Z3raT@R^P+iciR]mSHGPWkJm%LHF4+-=PV/:C4OoULY('ohjBTO@.`@<HBfkF]TF%\/Bt3:
+%g@+oNI(4eEPN?hfHEK,S>)(@]i/2*UVLFJqdX<"agH&p[7,4-[$QjHq?d$X-04VI2Q]?Shr`&0-]R;QNk_2S<^mEKS"79%R#7#2K
+%3':.!I@<PujjQSU_i:5E`<\mt2gaG#R(]i9)dOWj7aHInd;/)jMrX>5L*tluV6S.-pXknR]Z/2PNWFCc3uQdH'B4\XWRYNq3nQPk
+%^n9A-f$'/4ZXqsb$G?NXQ%dVV1]#j3".1QsVH`e`GBRD(-lD9sp6rS\+F>8q5;oQ(%;'^Z*e)=JoRG,$QW;E._QgX^913(>hBkRD
+%m+AoGp1"D1m%Xo_cFA$O::8i^S;\DRg_M^/FjVdg]uA-ng$onH2kM^N0"tkGI!N6o39Ki$+7Ags<0&i.RC+C/\27EnMKZTG`pNE.
+%1bntnj0Wj51GCiQL_S0#Wo3[W%^53n@c%s;Y:c37(>%GmH!6$E-2XpZD;7&F/Le,R4[Mk9hK-=&,Ru+23dP/Hb_@+UERrNbl")]j
+%o$hBD*G8@E^6:Cf<WQ,.Q'-*(G.+%]/N&E&]7I-^14#F-4BKH"lN<Na&YbIdM>i"8q8UCjG$o')GRNOu=7U&C8_:oP!Cf@*75nTC
+%)Q029NQ.;(iPt,8^]l$1l^56Ba1Z]]=&3hunGTm%]dg)3Tln>4e&d=c>%QJDIbOr2"E?t^f^KP??k,Z_b=lb.6t$BSfuS/N/8V=E
+%,@9Nj0:@9u5J)&u9^X1b#u/79qgt9f%2LB:=33i-B5G"Gs2+SLptH_TNAnXZ2!TYYc/Hb6dc9Dt<XU<u06>#IC27H1b*uE96kUYI
+%oC0asP<?K?Pbg5fU?1"LfD.C3BG`g%;7-4Hpd$5-eo\K:DKHK^"bCbhJSE3co3$kbgfWWH=gGfc>e3]%M=mZL2]\EWpeuHs'$&a\
+%>j=-H@_)[(7!?<1OY5J+7.C"-^0V+Q@.rH\"m0B''b@g;#?F:>Q%S4!RDj-SCELoeGmoG'B(S8.\Cldm)BWP[8r)*A8Z=EETPsh:
+%Z[/-V.?fLQO=\c/>4oiS*`Cc1qA-]jV4@$\PjkpR-q`P3=,<LlDJ[\=b:(U[5;]B,Pujof4@Y`b!qp8Lo:4HP]f5WDDd>GViot'=
+%70RQfo.6Blc,/\%)DK>*\W?lFOZNBCB[)'ISHD,]gl:)lI9r:`=k["1^U3'660k(R\N/MS'bbp_$tmR$Hc)4&#,k0nF",.@T[9R[
+%>HQ&F9gj_J[+"-WQcEk`7X_e!j4tcKlSo,;+QJ_;TAP4ii`90G4S1^WUS!G$R/9fiZ@ILm&cVZb&(J"Toa$hbQi4rWjs66m*ujZV
+%0o."oiN$T52$XeV?jtuXDVc4V+hLUc4`RDSWhQ^?'s@Z!DD0(`@:HB1ogK(.,*b_!Xd9lt2?d>:B%\DR;]VB@QL<kPVSo+<>442&
+%NrA('?(17`P`6OA27%eWCWe$%7W-(<pH#7"r7ZPebh5mSD7]L]9\2O[HgPX>_*5ol",*i^iQkFlj_t00fpYm6:sIXNR8)SkMGb2b
+%MEneZgc2'PB%[:_5bHI^<Cb=tcnjmX??'e_L6>H)llMo'm@@@YldD2d;tr(12W:8LiQ%R&HN&SOn+g<fpbpW)05u_0<LG)aT,e+(
+%D(u(ahGr6h5CG6_huA^\oWQ$fNa,,kleArP>PC26iT,C-3]o4HKMun9.kN*<;32%.Ph1+hUQ]7i<WpY3TUD.o^`T/1Cb@2#C#l73
+%`fcbQ1g.HYN^ok#NYsG(G'C<u-SUK12OgR^7XK28G>)(Z%9M?O;KBo*),QO<VX*M[Ll%<FKjs1AHjahFhRnfd%LG?TgOMnQ)3]qX
+%Am@Ul^Wb8-)b.Ws?D[d;cHAb0DAYHY$'XUbT"):@PtcD1@t&YpfG3h%PB#:/#pW(PDA95_k.WeT*!s*j)=Q1k-USVn8DV`H;/JH"
+%VU*$)juHFq[*b3pX&_0lUO]P*DD"ZG!7iFrgNU-t61Z2)*Yt*7JM1M;)9*(R-TCaBE=&&[cK-[(0+'+_93_4,nReCAE4E9?]<`9'
+%OaZJ+eo'kYSAN1tR8eCbCfK<ic,Sh=h:7m__J5T7gcu%T%G/=gG2'[AAI6%LAQQHMp+j3!GPo.<]DPR!(c,(Jb)M\TTXne_Y=sQr
+%NL=(d`c&X;7i8e>XYD3T;"aO#*Cfci1k=Vcr4rAk`W2?P2r8-!I4"unm,?"Nc1Wmc!-Ct^L1WFe_>4$._KgV+F"R,U?cLgsN&g+!
+%!9.V;r7tJ4]*:FW&;SY7M(d/Z1l%sC5.'B&C>s.T;DFHs'MhOYlo<iRW5fQ2ak+e@YYF`6r1"';UL<CWjEjQ3\Y^8IGQHOC%=sr'
+%_+<2u-MsRJO^X["+h.CMh'"DZ3P[GUB4XfUKSttp_/dNHh*^5MboL581G)60:m>?G6"Cb\b_VM%bNN8s#4N8%S*T'M=eS4cP_Q<q
+%3bVJu)7_%L]0`Zi_811;/(lOkZ5,[n21<rYT.71d!<2e%gNG%b"rNPF!)3XreDag&FTN$1LhJ_/^\cKgiHoR&Gq%O+'3UK9pA=R8
+%ol<A\YFPraCkm,(Y.lT5\$7bkI#/%mY?]lcq)S@TicZ6tJ[Hn%]J?m$p(QAKZZ2,>pZZEcq_>l4B(VLD;&+7iW3[gpq1Zo<N>$)C
+%O^8D?E!*Q,@kT+D$eE-ic3V=AT7J5iYamHF^(!,V2m[rm[H^-O*h52#p^S+s&<%)kFQ56!M$&So[Upr/3..(rC[>I3,Q6YGX,6W9
+%LQKM>"E"C>6B;1@bPMG<aif+]N*6%'0p.s^[,Q=PHR@TD[:!1?T-S0d^'JkO?QeQA:kT;?,^=_;$_BkIFUmi!^<bYpbGCt,$>1@/
+%(nL0&p_B#$Y6`.Kkl+M.**!T94VT,K;`Nel>@J25KXkq\E[kDPLWg$%h#5=HhhnW_AmA>si5nP!;"9_<A0(G3CG3>B\!iZsToZR>
+%oF>5jSD6Hl2b/]ic](AO^m!5d92iF(,.^%Cm;ah]\6"@;@>rs0_WnXu<NMpgbZ2i;dI>GtmO;6^Z!QC+-1#RgiM5Oc6&u??+lN+j
+%\o>e+!Zq:dTX=?sq+K9g9K4HfdY3b=qP>OP7:ohA)>"4G2PV)]%m$T3&Y$-MO4697.e,8@pA&j+Y9$qO[VJ'gLTo\,hP>&=<`0Y*
+%NSJE8?()bfgu>dMGr#^CGkdZ,!FOq?[eL7lroXPV?LHil^RRL$O"ZQ$l/?E,q!O2i`,R_]fQeN]WPa2YYkK14alAD-hL1GHom'=t
+%DuWT\`T^&V+$YOEl?K0hS:AScnp%/uSA<1oqVb[Dq>_meiPD^Bn3N*6b/(E0n:Hg\BkD7'R'*K1BmN)bn(!PtDFD@tf1";Y9_+UV
+%`F$*S]o_.WZZS^SB!.?\9[DMjfouQiQDSot\FCV!l/QsdYk:4#'8H\OiUD+PW")>O_sqq5.Z]AM_ZB[S=MGsD%kbZF>rXk\#9W$>
+%F2![?hgRT"[Z<)&YP>UE*Z!%8NL^jFC"8fAp\?mq#TO=?`^;`V&@rjuS7=hV(d&f@X^anF%,[)=hD$E@L6'A?o,*WSL9JWopD=Sd
+%"6a7!I14<F&c>##In0r0U_&RNL1=]P0o9mDGT9X,a#(pQlI/W`NCg#OEg7T#)Jth`m@Cmps*I<c_q_J?\rJFUbEUS?hJ/B`U)R&/
+%rET?9/a)2h6n`&ek3>EfH<Uq*H@rdErgpDMa<MkQ5$A^+T^N?GHKJXgZBSM%N3/a]#'5&_f/iI(pNdQ:J>MpXUpjX1*%eC5SL%;m
+%2PIj3%CaWs&qe.Ikr+k4R*'H\`[E`p47qM+gF>OLC08(<;NA$k@GH22!liKO,7K=/P2bR.o04#),C@9Xe(@W.)VnR\/il'M"!__?
+%:Le!<T9lejpX@C#huiVmIG8U!$.+[,,'B>Sl?LRAiD_jtH3J`^S?i"s8&1(:6eUMi473<mQWqJt#\IE;L[B?Dh5\/Pfha&_]o42g
+%"?ke8oZc0!._YE[P^IruGuAenP+%>na_M![1iC=n[6pgjcZ;":X\mK-*WlDn2[hi*_`07i-c8(><qTttk+$-e2(IW8#?,@LFBc<n
+%?tqK@1H5gRR@_!U0@B'H'j9*-Ea(2<J=Pu^E5bs/1Ha5B/mst'n4qs.k9]l8M\Q%D-64,8GY&Kt=C]14Sd<@:Hua&D);kD"_eX3U
+%B<fJ'0ij0SRsN`%bj7L7^W2KlC-,0N];pXBF_89.hYfcp"ToTI\aWd9)S4=c+i6d1_AkgQct,uQl]"JN"3cB^B$4EMP$+oTH[/s;
+%?#+%u;&3WN2UKW\1/Afro)"k+NfImfE_HY8lI+;S!XsMZ-5V0(a]ktcK8n?e=qgt+$s-Bc2#5fWMrl\;i?U,7C-.8RHA$nO/9B]j
+%r_Clu)PR["-@R!_Cr1^C69bPSYbpL5[O]EV$n+hrG[_i.FH>itVR[R'A/D`\0L[C:\P?FKZ&;dfJ@i437+"gY=I#6UQ#;Sf2!$5!
+%]jd9"T(u$>@8[]-OA!2bm%,=t[80VRf5)o^DI\;/p:/?"3'\X)ef?,g%LT/Gp&p;CJO<%U;bTm_b[n9g7I$'rEs'RlXuU#';MWf\
+%r4c2>2>iJiOc5l9$=hZiFR^)?E2-Za!!/Mj7-@>l!egH,qapJT?9uKg'[45jWp3&dGS-soh=(KKd3g%O;2EIQRk"FWSVsqVik<7b
+%n>$*=YW@2[0n'P2qQJcmM:0QE70@c]"i&rS]ZJo;<lBs.JP05b#EQ@:/"=s:NY?%_0i>p7&SES@VN#>XH3O"KL0u6?++G_)GM*]t
+%Z+6YGW8F9h4rItL+!>2>62[X2cS^7Ai84nMP:]Qg37E.m0/rL\&L2%)^3^Q9Wb,ijE,K1^lOM<?=:*lj')SM")dS<U88sJ)K4Nn7
+%io\[bG][Q;fsSArn8E:#"Jgk*LkV#<'DY/D5B)G?ME=@*G]4Tfb;RZrd@8h4]eCZE3A'ejcEIsp"f!.sbWdhlR3fQ_q^iLlc'V`%
+%j>[Ii3-40o>^Cs5h9,j24A-`S89JoP>2^N1-8St[i*)&G9.ubP3&fuEKlHD7fYU9Q@h18kB;<`/L'qfWAeNNQ+2s0J/1(.B(Qn0P
+%JSFt8[Gd>cT0TiVSXIJ=\)j+V2\)K'->N\Wf9V"<ZSS)AH#<Ji2jBQ;i=dcf@T.BhF/3b>Kj2]PCt:,r\3bI%UO'Y_l&3##9V!I;
+%a5Z9FFSh@U6k7`/Q,FlRLgk0JVN(>KlM;fXH)l-qMsh*:5UF"YK,C^5lcDGr\D^21!%UEU'<;.;[1$,84eI\Kl&ZV`>l,YO'EZ$o
+%*aW1o&A:mNYYc'ok?DIQJ1gKqClXsb-+qH^?8,kd2Q'aa#tM094Im05$U!L0(`L#+AhA')qQW>n"4D^Bl&u/2G;nS<DQ=97hB>N$
+%,BGDbYLm'*^HKAe:j2/aj[m8%BaT:,VnM<th)H(#UH3&m!t:;mm/a^1Fp#S@*EWLThm(-i8WQKWLTc_9T?L.@,W<BjoL.',!8fKu
+%g.&)N*k@/e!W\>aM[1]-i"b\0iS:6Cq&^C*+H^T+V6F?2AA`C7&1fNLp=`7dENDpc_V,tg'WG#4Z0V*[O:WHI`o\>=@K6#/gQ$*?
+%A.Y^J;:\-J`tWJ?E"mA'...VH!OUhpW9,V]iPn;XQ3CO.WHQTmocZ**5/i]JVM,b#XFl=?F[?r/]e(:\l6#6A.YkOl.`82YgO^&!
+%N+<<`Vk$5'Eu]C9ok1rr"5PQeN8=XW%ZPPUOZt'Z;,cDDT.p=oQ[)$iBIVX"":V)M/[@rOL\ATXo$B:4fKl73kVQ18SZg]0kiNW'
+%@)0NE?7o;2RFciW%SFDd/rf.1lWAtaJ6?oHT\GfQ_q)2TN$;1Jb:Ls5_Z1/?Lp@kTD.]m2,&D.YP;n0O@0!oI10HqoZ0Vl0aAN6K
+%&,e)!H'\O&bo=?*jBKJVnOOO`1f!\ZgKL.Tp]QT66L7Tl#79W(qQNu3!Jt%C6f[blgJVW=X&s#s.k*%R'#0QZ(iT'],j)g+hEeqX
+%]@\i5m$7lF4UTpIOU/DUP:srMG%PL_?5e)dM66Pr*I1LQ3V[4A(/oW_YZkF@s-c<S(TN(/(KQmk5Y/':f>,)dH'`73OR_(p[mZW%
+%=WHpa:9-FN:dMKB51G)K>1D@KV9%\iJEqj`@qb+%?dnpcZ'3Dr(ime7R.M*GX+X.INnH_%IM4LUH]$7PkD?p[\\NorNP$f<A;pK]
+%3KaU+[^6o$f]tI)8o3t++uJbGC2>Wr)n(3Tn/Xt40,M,p0U=o4rq?ZI\e'lC=lX(=5s,Iu8qanPMbj8I;"F\)Wc/mj]*l=6q6`Nk
+%+'6`;URb4GkS%[N)SaZ&(*2s`__,QS@_<C2ZGj;B]toSq]uqOWK%!JDPD3FHM^=Ds\IAX&YZO(44&5OPW.pAIe]n_I`%5MsBb.O,
+%HKcE9;H;RmZZ8m@NP\4?akApmo+6JbGV0ONB\0BIU/.`!m]LL0`mTB9\j.tKPT-U!:9Gj10G[aJ![]]"(gr4fDe:9jbge#SEj)Ot
+%+W#^s53Q-MM<ToA#N_arI)Bg$qWY/+;2VMg;&g!A4*82nIUWCiD7>b40OsO57]B!4(ehD]cJd;+r>97$p5P$4!FF6SPoYfe_[F8^
+%[KVl!j4*!l[LnP5+VmllnE$86#_on3S?=nljI!3q)d&&DbrCuOp%'+)Ui>4ofL`3G13U_#bW$G<*02m2rY?CYWMFu3DQI+s!PJOs
+%Zs#T`pGQ3@</l9BiVmcGg_K!cYmj>dVn.N8H!>uZTp>:gjo?(J"'eDkF<c98"47#%BQoL^0DQ4hY(p!B*+#CWg^j__d^Eb=`MQc<
+%Ido8<:6H7TYL*"9iW[/"-Gdj_(FN&I=D;baH_X:u5`IhnMHlB3(3j$sS=cu+a0/hE#[Y+;_=4$!co-IglNmd?(/s%$,jNA2C,X=&
+%L@u<^4I$J8SZBn\k,PN%Pr_.)5`kl>8U1^6b"K=2-?MFTL?2%M]6/g.QAs"?aV;"Eb8$lAV0]'X]mtdJg)1sP,/D94c'F'K5H=*&
+%YGg`i%6q'2'1n3r-IpY^D@cm@j>BZKJ_ZZ-\Qc(@am6#BgDDtEk64p@2poS2UlWkZ=!di.T+#)TdWQr7Bm`;$@M1if7;[*BI?@+j
+%4ZA;Nn+?^oe/9^TldE(rEfK[/Vma7g.2js--fD(hq=t@&]7Lr^FHe!bZ>]ut4q7=:DHpZ);Rsf+28i;qZM&NHmPnf0$</90?q)hA
+%gtTr?Wp:WsC`2;GS"9m!oeW!+-:e3T7AE\E'$[LmgK-cd#"qR4O`'e,SL%;CU$uk2"sAVV7g.p"$;NLt,^d#!LneZRgPUJ7eP=8s
+%R;8.D;9r\3H0?a5g9baT-JlV*:Zafl^O#jo`Fnr*_UsTLGR::pqS6,P;P=H)Tgo2/8@W]d5mj7HU4WJ&904Xp?D`oXmckLWVg2W.
+%rB7\g3"G7P]nX2E[P_3hi03g:!J59U]h?c,72<lN<t%k.@51=IXg5VneXIJDiBWV:,;Bbl$R\@:=,@+X$BHAj^N):E*PGE[9LMVJ
+%i:=KfV3r5g0)U!PEiLc_^X1ZM67jqfkur8$(V1;..X"Gc!4p(Bkd\JUCOt44<f!=@'O/]KVG37d+^RjBH"Is,fpb\e]8kHlq"l,#
+%O<1XbeaHgiC7W@f>8F[K1'@Ls:qP6l(>Go_&?VqIC:@BHeEuO:#6U7u^LM1hfI@q[<\YU+6u"i`n[Cr`*]I"Ac,qM;(g4p3&s">H
+%9n-NQV+L&R-nLOEYa]!i^8tS4:!'><GE)Dp2hu@AlWqCfV8YocK%U4?C,KLe.sh8td6ECF+:-5LqLq)JIfC:D!K0YjH7:Q19e8MI
+%SJ05hg/Kh>EsJ(p%lGU'b^QkuE12_IB:u$$L9eF&.gk16ODNC8Fn2]&^NX2=48`'en";X%E3H81:\_qY!c',?';*ES)ufgMQI47.
+%JPol\Aeela(UGQoUTYSc+$-$R.;M0r</9o4ZA3'%os1=QCcIEb&nb699ugT(@HjYXZ!8@#[(>R_2D1[M(-*TYBh"EI%$h6VU8'gt
+%q#hpa2JlRE:CFd5]9-jKL.WbLaX'k@;5k&1eJ*6MN!Y^sT>4p<Mq?CtF81QaZ7YG]e0\;Uk0gbB"t5o:QpaS[;#^+fjFJ6s9dgHD
+%m_OR9eL^:fDM]C+C4\1(c7=DB2E54ub7^<+X^5\ig.>[I,-3lQL3W565oG%"e3mt!>/%V:[2-AWe6;cRSno?iiK>+0GbhIL@/(g\
+%NB'6FVAsRb%NmU)6&c-X:5E)%!1.b/S1_Xf`X]d>'$J-LM:CP\PTO7_Q]a_'!t8il@T402&PtbJ\.p/Ap/?kN49j*ZSrj#>KTVPl
+%)umk)^/_Aa;h<gc!-RI2AoW'N+d"W:3f.+tBTVMbU&:587HN8O*1tG/A<ibP,1>.BWLO`2mJ[)K^e28<9+/o5;%p0O96h$GFIbJ1
+%%$V%:5asocJ^/Tp<UU(;+,:Fc0ku:GiNSK'\#E0U.H9jb18%'C*=4aA^pXIT<jHSVN2gr\^jVgp]U%8l#.c'F`;)c?#L60*9K+HT
+%qKGuZ24@*U<YZJb8s;G(h9>X6-V4anQBmdmGMk#:=<=(O?m5[Yo*Sg1F9&U'q]+kECdCN'"p6]5]pbDX3$u0Yf!SA;Tl[g>W)P/6
+%Zl94J88Q-Oa3c=_KJZ\o^`;[bChiWL3r&RbY"K3q?-<<ND.Z7d6rqL.$pf$NgR"R9PI=^1bKNGe\_24l)Qs#g@;MCKFCSo7jO_W>
+%GZ>_%_Dru02d3`ufm7\<b"SA`)F@qG]]&^t3L-'t6bS)b<'lAkE__-@f_L&DT,HH>JC,i54pAndZ0V8uim0AO5qPIEk%?$uOnEqZ
+%#9G9FB/YH30j4`qe>o[b1Od\%4<\2ZIX?TX=WJFB)D_^P0Q-'/q'3]MH-L[+4/WLF%14GO3Sm/.E4VL5o0%BQ2hlZp!H]K0bc"-6
+%#>YFd4X$PZl92HL[Ms?C$*52>Lap,jX4:#\`n';aatR1ff;^CP%-&TXM[aQg#AQ[[B_HVto=d6iRpo)=SH.nm_dJfdG["$J1%W-6
+%/-p;+]T@Ag<gP.:W$;>H]pl1!h%g@gAo&l((p!hFH"Ni[m=3T<+`A!IG'X-hSA?GUa8rC@%tD3Z3.W(QfZB<[(25#q=<4$lJZ\Li
+%R8O$Z+SC]qB,'^_2lsF$"ZWN4J9DnfTk,U>5_E[O_F3m\0SquhYPSe<q\8,=.Z2&01k8%.dXi&a;'I5)_G7cYTID#Mc+bQ10^oYI
+%47o*1W!89i:O-Yt(KVaKQP'RpJ53TUPMhWNr/W)Q;&Ad0f=<b2TJVCf[`l^01_ku1"']Jc/K1goof&>&N'6_`B(U$P:Q*)k)[XKS
+%a?<s^Wm#+JgNg-s3"tEdhHs,T]W\H;@t2hh?<@L./aZOG4$7mLiRc[Vk74m`EH@<+1h(ulIT#YV7:hnD$=85.FJM3#:^%hk^^/.L
+%+bY=pM9p0T.!K$^Y-")m!.,$^Omi?lTEUIFW:NLfehj^CdY1I>[JFCp$d6tM/M]L*khV*sGf94n!.NBq=#^mHqRALfg\p[)E.rMO
+%!e=WN-n%<BYDf0.Tt3PZX3PhaLe-[!g^r7C3/OskdAuXP"*EVS0RtKi`8c"dKt_kT4coKHZQOL8e&ChO`gpQ4'mU$Ph0'$6\6+If
+%=_1gY)o,dEpbO_s*]:Gt+^&ZM+R4a9.T/%L;G!$":XWD<ecXRE#5a4fNSi-n#D2YR$_jda`1a8X![[;5pjWLJ?P6<IUlOWO:ntL%
+%!f,'1dr;e<!OW>AK>;TC"d7_c=uWZV]sd?%aKUUCHtqur6oD<0e+e^HJLCr:)(6:'jeLI;7c8C$@k2)K.0>$AUc&!<989b2o1<_2
+%Pe]7\^ED`]N<3)=&#M^jUg-<(1a?u][Ond;E(.I_@;aJgWJJZ*itCQs'fd.T#HS;<("0@)F9`?Z1k<\f#LjX+bW!(GoPt(Tc`HTG
+%Jo99kBsNC]g)8_D7/=&NBN;]uQg;sJDlSA>C$5s)`&U*82)_Pmg5`DV_fa-o-h%>EnS&?18qDE6mr)Z'BBZ'MeE9[2f&;%&-CohR
+%-BiOQiaca@Ye]J,@VR/pb.SW)%h3Nk`sY`rA`&',#F2b4Z)fDRG2HaGAo+2JGm-*<?iu&8;H@./Iq"I2W&\I0S@ik`MdTf$f28?Y
+%.5I!;HFX6u]W*)o6s0R@W]!u_(7G(I&'q6Xc'9NoL2M_GW&G$Ks/@<jp1sZ=<46l<bJADTG9=:b@+kTZ17)k!fCn8+N9cX.3Wh<T
+%iiG]FRj/1[VJEdV!Big^Z6GIY?D#1(K3lumQqLaA96+%$jFjQN`g/0\l9D:Q7G4GuOJ0\p'[<lNW*cJXg;-^%$ja613!]dq1#5lj
+%Ud"Ju?eNt[.>W6M)2\H,lrt:jCKC4@<$aLEN%AhuSYgd5lc7CcLcg-A7em$:`-+ZQ;Q\mXL_un';P!Ot5[sJrEEY@9p^I>mWo_/u
+%!ml>"WB,I%Aid<BYH<?$r`hVILi\1=+d=Z4hY=oR0e6CZoj\c+LEu5W.tgOfQLnLW8no?.Rai73J/OP4XO6NP'bN"pAXb'D&o1(5
+%ER)e7f57S:2Qe03E.=HjHR*Ls&<neE7l/g6.O5hGCggkikf.Bo3LILL)ol;j[>)[N!(YFN1@I;%.HkaR7;DD@9JQ\6,KhKB=]c,(
+%NE8fac[VoDKmGO\JET]e#+,Zt$GXO)@(8*Rc@i0'CBdM/:^NA;GDIS#U+:_3`^!1b/gK#rhWUDaOAMQ,kEN2Xe(-c9h.EJ/%91I5
+%']:b(pk"H/dR*#ccj?<kM+/$?]7?ISl0T05kKT$T+o5Y;ZAU<"/MVSsi\Y?\$hS-_)H2u;D_@A9gEs9H;R1S)2a0POa,EEqNHs\2
+%mJ[86p5g9U;%ru-W,>r#BD+<V9Uc.Zo3iTiNCu[<NV+QI1o8*19&o*;k&dGSd!\FH9$9J*/":!VHaO5q)bZZ!/@Z7:KM<^o#_p4u
+%I,$h61-mI<L'k+mT[i;B=MC!4:H,8Z?I=t$d-.Zn3+E;<KO3`@71%J[r2.4u"66Xb=:q7OjRNm9%I8ZITLE^kc('kN`sk"6L0gtu
+%R_ChMOS'@SBcnCb'pFi!Ff>%1*RX;KY_0<X)0rrTXLast)(@A3+?cJ#oX"pL7/RmcE?bYb]Qu&fTg_hE_@_oH_03d]iWGj%;5gag
+%E?U;4Gbss_egUg&k@K1824u<e9u8']h<uO*1dUWg,Y4g2('U)-!l2/+&lmC9V!MZ5_/mHMmmFu&;noW3mjuc4.R7r#T5<K]a'X&T
+%W7XHLZtR%\i=\*/H)Fh2\=5&9He[^n$K@3l=g4%@r8TU,$SO,tEWpbOKo9CL'!VRF[A*73&.QV#7[$cV.@m&A>4a+CaKTGePKm_c
+%'H=>SN8Y`qm,('8noTjI5k!5C/qAX,_8,aS$8CtHK2,ui?sdb_5`g17",JPqDoU?'C#qKC'#2EK&>-U0#NmT@G]mV;ip9r@ql*H\
+%;aXfO`P3PWH,KtIE>ZElo%OSgQ#.3pcs4\D1mG#iO%"&Q=LSVZ4YNk2$SuCJOYuo<nt3$_bD:t<\2eK8\eK,gG'5jh;irUaA<hH,
+%Sep7=6kQmQ1%a'#)LEfmpHJdn[EktUh9#o1`F_.J!+Un=m&qUk$["2e@&73iA!:@*pfOkKTNORICk7:,5)b,10PZS@n,.,Zn[7KJ
+%m0kU>-D@o^)l]+Z7l6b+p+;+U`SNu+1Etf0,eL[e:f9;k!U=hX<%uq`"e'@aVAWtmO2rg<6i$UGaIO(7R5J`g(2@G&WXB+0lc..G
+%jlF_>Y<2ihD9U3HA+_=gKf_U;D&FgHITP%mM-R=CJ$(&D;Ig@KF8F_n[RBsBbVW,V#QIb6FmHe!FQ[c$S4<WNnsP7[d[SWV/knMq
+%C!LVVHmEjiZ+Je00*Qd5"Gb$VA.t9e6p+E4%^`h]5OX`WGGP0X$%aN[iK8A0VC4XT)3<:f,>%HW:jF<n*bh&RPg0C.o10OCU6H_`
+%VamKH,H:?$J3?eA+)/,Q$LWJHq`sL2;Lf9Wi<NQVOb.s+.mFT7:F,-K?2BC]IAC9n$/9*5pQ5`1VMq/#j[UNk"(hGLDEecm:R(Z2
+%]DbLBJ"Z-Ml2=+$J:hCJUU\*:Lu9[aE0N:@8g,0C'-7;mc=.20fnQ9?_bgp'X;c.[QoKt#*+UQ@,VG*t(e<PD8!/ci4cZ:Va-4Tb
+%;%VeS3oiS=j<.$7'JDK4S/`hP%ald:+tH/LQBQ@4K?26J*6_8<k"0%E-qA=mY'CSh3==acV/m\gFrhoSNoE2lTq@Mqcq-=_;.f#7
+%8TYY"H5&D$Bd+S9P9,CCNhT59i_9q=:M37tUNk:@d*tpWl6p$4+E_gk`B"?>4c!sGFLdD5?4ULP7q&WSK\1q4fRl$6;8hfenE_Q`
+%G*GjNOBaliZQ4bT*_"rr!c]S:\[1SV=eP12AbRU"GEg01M!7&.mlcL!*T[,>V#QH1JO`#B#P#Wo:>o'sn3R!A.$St><.'d7I$/5,
+%ME2d^+<SNGO0Xp=$-K#Jj\a\$5m6d-R!FqII$!<7OR,)cH_,pVO.r=\H-ljGdKeIRUVQ+c$hYp;H5'IECU"pl>E8ih%q;b5iRj@2
+%lrf;@-sV+b\:'IV4\FlY7<TaUH&E4j(<uGLoQC_%Qc^B-f!%c'io.E-8b7NA@s>_qSHY2)1k*?j5+un%0C$%%-@TEBI*d7OH5npg
+%&,_Q6U<.tIo"\OVi45?q0dlD5O_&UpiuGTk8"S%h&bNj[3YRJ_N2-^PdZNd9j?u0#ViG#_,:i)2_0$rK*Ece]%'gQ"m)VeG@'Deu
+%h2].X'8Q"s[lZD;*a!e;_V^InprFXA0Fj_bM'jA)RIYU`7NQi>OdU@;-,E.V.eL5$/rV/)k`Ib!1UZk+JU1k-*dOlK*7uKCp;!bX
+%@,[[_]16K%!t4mT1&T$CIc)A6E0a;\js(91aHo(GWukHr%ufm#\,/Pq5;L5SeFEh[qN8%3jL.;Bi/aE(1V*M'_gg\4+5-T?-%N=:
+%^enIs6&XYe\)<oun=YMT<),Df/3N,N*46`G.M!&I&.e%<#G$\V9o:=sMPJV==V]tqTQ/K839kN(2*=WK*tQL:B,-Q(hT1=-a[sM5
+%W-@g*NH3NG3=2iNBX8[X>`NPP&'?RR'q(iRb`ag,6,Vi`G4VYkF&^OIkj:KJo,M:g%XL@#g->l`TqgVoK0%CWalo[KoUq7U71VP`
+%nt9TR4Gi@Q#%h@*pl8@Zq>e'[)td4`W!IH@Y`fc6D"1rI,d.70\SOPb6ePb/]+1>04DI8IkXce[ViE6,#<f*mh5d;?eq9RF;0hK+
+%de09sFk$D:<s^tRM4KpPc6?g1H=f\/Z_L.HPG6c.HgRWXG1:UqWkU\F`BC0B*VJS:[-E[_G"2_K#IV3sZJJH2mm4/G,jfg*!.<-$
+%I*`WkWXta9$]jS-B-"psA7?%HI]B7*FQ1!*T[E=oLa2o1W%GQn_+W4>f4\;?)h-AEhW.P'nm03)61=A9)tU/*Gu39YWcK5(4<HCE
+%O8>Ls+jig)d<BlaUQ4T6k35GYoj()\W470)ApmKq4Y"/eeR9PAA=k\kht:]E9"#81[grhV#;+a:h;&<qhP6P.c_A0ED;_1Hn6'c+
+%W(q`)0n*(a5)LR,<Kp::b=?^;UQ4r@k4?d6d4*<6BDHJcMBd:@j7[VL,e8efAFRW!0Sid=c<"M5#nQM4:q<]5K"m?H[<i*c"^5T>
+%@;+iue#/k?(B5baSf,u<*O327at"dDe''cceOOZ-bkY.?6-/N/'fEQ6?ac\*3;+u%>;]S_h:.82=(G4$7]%KU./B:B\_Y!JWRtF-
+%.U\l@;@_Y#l>NoRUsXgrr;e8-24,5M:;^F4::=,5]ErU`MPk7jaN&WS[:fqE[\-7L^l3r"TIDTMS$k-B@&e2N)T$*eG>od#8t;st
+%W"s5:XAud[#f0fjb0F4H<&`sUHgRTQ\-!bG%95P0RFqqp!]NlO]68@43Wua.)3kojTG156A25iC8Sdoq:h91Jj\+jZ0piL5?H1hl
+%WrSkHLE$]Tig7uoR+:)s3878SSViFS;F]UL9N<CO;_nGY*OlE#mZ@(.hG5tsL^%V?Z[GIQ?H*JHJR)N$68#_F+Z,DrFc]p'Dap&L
+%8*pp(iHqhP%VCM)N<FRB74K`9H$1d%[k;1/P;N'_<fZAETJ,9_AX-(sqjP'oCTCfHRB0'*Wej=/I3#SZ?@b7W!C(Euj`MeYrQVC$
+%Lna\_11:r&_M!nFr%MIiiZIU3iRFq;hrG2h"Q=Ks<_4*K`W2qXRub\qCHnX^[CNVMY&lH-=ml+fd:l&_4+^dFf8WR+j5d\(S3klq
+%DrsC1neD-dJ6K)HB"R$i=LPOr,eBbJkWs0=Kaa^i_u(g*QMUo^11f?a"Msb_cfkN;r`h@CjP%R"k7'-I\cSF"7_"[aUjQLbW`"=\
+%T1B0V@mmPLQVp)#Eat3i8:!45]<7->CSgX-'[g+',?I#Bhs8HV>_QIoRZ^$Bh']2`WM@Ir7]#O:V3.^KiZ1aI)Tq`MnO899:K`Cu
+%QKRqTHHth6Q[Dqef.]!=Qn(qmS0RiVD2t"8q"SP_)IIus]V"=9VheuoS!l]j_CLFo;!7.''"DC:`.;IhoRe-HQSI)X6+Io8ABPGm
+%.<#$fq?kSNP9-4E7,"nUEWHpQI8t>k]DF,CdattHM-:XLoZNWQigedp`C7/t('mD4E\W91TYpC:M;oaJ]No,'Hkuc&B')Zo"D45d
+%8H9G\2DuA^.IDDLRkE*bcTPRCpW%I(Si]FDTe^tp4FO8)juSa)pB.$lgJWA`EnT`[n$/:-^:9"RH8/_bpM9ol?mNh%Z2]_3%E)>u
+%(!tL3`CU[_n%C'bpNl58`FbFIBaP4APm&4H8b`s#-R`-ZmOA4F<H*[fR)7>%1a5EOaq-6'8l=nI&-L>\UtWE,>::*II*%L*]7S,P
+%#ROA5ajI(I,cPisQ)tqsnJ(g$q3p9m-%W3g9Xof*e0Gn5#MB*XU"n:qOBmAcM2EAg$Y@pj)mEBB#c*0cVFV])9t:9\.l?,hX_$=Z
+%[19&<BV5rHEQk]RPnhR-D0[_-goM.VMp#-K;-,8Cq0Kq#\k4Oec$%/cBuJ/n]#9X'dVRH>3V6Yn>NuULY_usD8_J/HNnYj;=b9!+
+%/]DC8.Lt1?'MH!tRb'fF)&TOBlWUD`X_%k?CR7Y#F/mSp5!g==I3jm+JbNYUr>G7^"#Ob)p&Jf3b'P%CT]>qC]j,fW)*@oVba,VY
+%LsPYJE(\@I9fM^'<I)9Uhl<?@KVnL7qLaKN00slJ^[ui^c^=;dMi<j]kHa>N?;W(^-3l/776\pmcUi9YT76h)NaEighm&G[#\*"b
+%(Vf"C]0t>""&bAcE*.hHTL,q_XeX`'TXgJo<p>bT6=p=9(^$%Lnd\@Z9i<\6P'MaP!q)?k1c':T<:Y5(lW2'K4mH9(&2q(uV7Qm<
+%5l-pHTHW/A#&&R!ksU7&:\?'U!&gnP)>nd*^J[%sO;d3tY7I'J<RnI)\o_Ks=iaAe(`0^n*MML(+2Enu/-ZXX5:bDg^fY_O5;oKu
+%]&K\G^l3Tq7Fr]9`0/AJN'h^"0cMD_/`RNhG]cDXE'ma_A!_on;nZdR;S^910)bd.WmM*VLN0u=Pj(NH1/cbZitI*_rk=3*'U(DM
+%Vduc_6LE&1nA>G683K8>dPl!2JYDXh]e6$EN/g()Ll9EHcdmihFiZO'pO,VP&*LVD;c'Eq]%';R$Z[^;G#ZpI7B,%'I`T@YQ/ZTq
+%d%rQ!;o@ER@P!'3(ccc0b_9UpMOA!&Vp'SL,%MJATnYqdMR6ILnf8M9O8"q-1;Ja:EPps,.l.R'D0SqI-k-PTk@'J7%O:!@'3>OF
+%QR>H^8[R2IbXgs]6EU;Xj^]/E%N7STi[?ArDQs7,@GoXnEgopEZ:%k?:;P-`huP&7`heO\IS)8,[&Crfp8n/2M%Ln@.P!`r\Ps(!
+%P5K2,D8\sP].,I5&hKM63JSB2k[m<oq-IqGbl@"t?_<Kn$_1eCX"8f&60[:`iF,54+:eY,$<B,moT7ed./TQqS*JYVX-?1%fO`3'
+%K'(gq'Rn5?c/f;29*u>aPrk/QGBapP#V9^$b.\T"n<=q%:K"fg,aGif:m@Z/QX=iO"mf\X&uooMl3Ohg-);%<<^YTh';Ugf.qF(_
+%,'QIB!f&cu:%XP6FXIGd'.nZ-e;=\m9I,O+V)rN8ZX_eqJ@.fLflT)!=3_/0_>QN!H7hjAdgm3YH7Y=_)pKU9!3`mXrg7?Z^H+V@
+%XiX$"L^4EN&I%)r?<SUL@5]kXCg4NI00"Vi2noYq9tr9[NE-&mD,ts2^_4q'ZXTO,IX`/Pjqa&<7FgR%ms`_>`;o@)V^FXWZZbV*
+%BD%q<qOlVi<-^Xm_*2PQ53U33'kr`o[7@(JUF,D]IdVj>mST8D6,E:ilh@=ar1G-Ze/CNN&jIc]5H#SEFcfH<b"'/,ZSM-)MXuJ[
+%o2-HQ91\Ae;lnn:O_p_U,cs.O`sq7:9D+*R9Q._tl%dJbIF\H#FVHWp6u#&!,'RPt;G<K$*mfl8_b=9eN%4^GaoX;be<nUtR6,KO
+%0=_SXUH,?*q[q!%-M[[N,(K3NN4sdOJ/#kd$Xl5XoXKi3FBt(`Gp1:E3XA.TYLg3+EH]<cG.'I$)%cH8I0pMV4I<e:g&NBpKLmW_
+%g7YGPUCujqAQL,--\9Yh!cbisb`#,16+gBeC<BttKFdfV'9&W_lt3'c)l+'W]P(j'eW"O$.`I9&!(@5HW"C8XJ-#K:E@3$`g^%)?
+%6Z%Q7<"jpm?KS!Q\kCcZ/SIWA#L:"M1@V[T79[Q"cM/^N2S66bkJ^,@IfY>6[$j1f7KgP_nkTQg1,b]#YpIt]R^-*[P&8\b_]3g-
+%4fnbiRqYq]R0A)aIiWTAa/mu^#4@ST46H2WF+D;YiBq5IR"`32]Hb$;Tj0mN2Z`feK[[:jXBK'p3.<>S6n"G?kh2upU:Q+E.HFaf
+%-f4"p^f#uDR8LB$9Bs&OX[psLCTCD1M^:G/!WL6n`L>j&BBe\p>_3Andk]f?gC(Ds(n#.qUBHAp16BOmjY<t7Qie'E18t?AP`(Zh
+%6tIG!r@<-m<05g0r#-Rnnj2jMCssZmUj7:*c;?n]`9I=nJlg*0.-7YG,7!M]@/04:D#h_ZRM9Ph*CO*D]9]ff1Qr'*/s2iBh*RuW
+%O)TEj&O5+@7=DDKUXWpDZ2#o7:$\]_%k7[>H]]DL?5Q>o#J->7VCQDi<QPJ%0(=;F(ifgeI>*eooGgbN#)6ZJ5#YW(`fPL'1c_nY
+%eG4f\b(DTD6p"QYO!do?$02to*)<#t1dPP),I(9u/]uq\Mqi.;0%='G<UIP5g^C05TFef>c+-G_Prjk)F9B(&`PIg,$8#U7]N]Q4
+%O-#[uYeGF<6lhR9&_0mcJ&,nHk14F#KRS:">`o9G`ueP(<&Cr`F@fp[&3=/ecgqON43)e@h<56b]_X>tIpM7J>SNZU?\)"piRcla
+%QA[Odl_/KgpXG@;l+7.>cR/atIPY$(p'rdMlRau1F3A$-m0^,2oEjnAb;A4[ocbj2FRqdE@$$TI?']il$^;*.bW%RId)g&n$^u!;
+%[7f,70Pa/;"T3.g)KX;3cWo,$"sf(P1q\3_KT[ie/Nq1t6nhXnYr24:\QeTnT"EeZ<@IDPCSpgP=Yh984>nZI(RPNB1c)2)GtAk$
+%N5Qa*lm\0G.n-%/P@p&X%QrcQLpWn&C!rDT2>uiU]J.&<UG5$`cUBaqOPKs0er<#uWB$$H`sbK?<!gbu0d's3@1`oFZ(5cO@4`"C
+%&/`2!G*\Our?e'f1[]_;KK6V`P6G^Ml^"cd&IUi1XUGqQAEpk:)pGm8jTAf&Zj;o4P`RoGXK!4eUZ`0::cg=/S^6)]\+ER];)5`s
+%S22(qoT5po%UVWRoNeprW6"ltYWo:4bVu1PQZ>W/L,3;YrRE[tm3D\W6-"P1!KpE*C^ub-1o(YnW+lp!T28AuJ5q`P?oY?nRTn32
+%Q`rJDelaQ11&TOcEjn-73<_H`30k-5@/ts?<FmL9JjEMlQJ`^SJ8SO:?4M%T"0;V3^g7gF\Wg@>9,NQRCC+7F@<95jpE.Sqk0Tak
+%T*jRP1o9\W6Yr32ZPb%r<KrpD&1>&HPD*77d*.AKZ?^aUW<OI8rr!fm@.I/FN\BApo+EacQE?E77H-2bP,"7/0>27gef9Q*2<pZl
+%8,2Va5<8uZ:;kQ=34^FIDTpMi3B9T"2sSND3kAo6DVU`!GB=6(8,-.XhG4=OM>/"L+r,R4f*LF"'E+!ALC]=*j3-Ha4"eLE(@=%5
+%g'MaQqfAa^Z#^3+,D+cXT=rU2pFNHO+S`&ScinMi>+^gbH<BiYcM@@8q=3S:1Hp9WDk"X'D%8\(Eki+,&E(Jk36LHQ.s5i^9kJBd
+%UE:@d7*s?3O7;oMLZ`JiGQP(s6JW0@fgVQOZnn.9dbE"$QQ3b?ZG&.m/m;;5YXSrH-)mBJ21:"@@fVh!3olQU+/iYqV^=(I3P]5l
+%0Zk]CE8iQ:\bXUNJ_EgqiPJR?8a<Z#!(3pOgP^(T@Fik@/Zp[_5pc+!5)"KfI@s0_%C$3ZOTL>-Q`oD=Ua7^G^oAV?>FuH2?Q[&h
+%-d]^T^-V\X(>5f0:!Kb#`ak00IYW1ITmi4n8DIV56k.he''_KOWUBWlS0/G_!!PV5@U32`"#7RBo"41iRO1B2A<i!658slZ-8^C=
+%Lu*6\nAdT]dSCF.#<9U%q!\9H39)IEE>Jk9`d`!&]gs[2oNkM+W_.)QK8?N?))WtCiQq+]6)*/,pJ6F1M'3L.9=5jOQ)TV-@"QpW
+%mW'<#8M7i5jJ7tV13;GMYkjVYs03niX<.;e2#5n*oC:qiWB.UtLX#JC2W!I0rHUL)_#X]=93]0;.A^a]o=/ta&>8J))TR6S,8>o@
+%eKbub)(?9X<7sKZE#oPCo5X^(i-q0WGGk@kjoqDDD5#?kWA2J7e4g9j[]L%2/X'lP!(-^o416:iG"+1>Z/'uAKSg*B#3Z-]GkNCB
+%!t?`BG2J:@I4MV*n7g)E%^%.^!LR_BLk0?NU\ba,4N&A_B]UhOH(Sg2:2'>`a,P`K](riMCbfM\YuO/SpiL?Ng(ANk$r7,kc5:(X
+%_e\mD1$=LQqi:$mTFQ>JV?\Vlo*PA;,L]^?JC3ganAgd2hTr<b0>DPI*DaR#ADfP,n;'#NJgLhE>X/0MV.==SYaH(h&D1^ojBgi3
+%V$_4Q>_<Dd7<:2YJG3llLB0;%]#cb7CF/jF@*HO9s*f"'222%&q:It/ct`EN/bMI=lU/#ELW7sW9sd^P[a0B4%kYGTc+]hHJfe0P
+%+.J6S2C:XF0gE*.IqXgjCnlGq\GjjFrRf3ieFNR34hMN:d##tl/pQ9^BbUm@8c$]@Xitfa#qrbc4ElO++7>Eq[tQG2#k7$"M^?+Q
+%"YV[,Y&&cKXM;M&O^AHLZYBcB3auAED)J!5F\,tgG_3A[PX_@Yg0u]\b=$92GQltU\Vt=j!LIn&Hu3k5\U`D`3[@>FbY=^gaH</!
+%DBII_j'@tfp:iPg%fi._d)5$a_XW"XClEH!c2N]Prnb]of^\pi*WCJrG]V=uBP,RL2i!mJ,MS/n?<O1lT*$f<X:mnWQ_GXmD`[M(
+%%"POrL5n@t.8PcC,<F:[NHuI@1]TI2)*1U2aR4-NPN&a[;#\a!)?TN3\<_T>@DWdh/:1?JMqK+Q"2#grR4EKY)$oi:%)ardqM;^H
+%i3ON1gkVQf+oHWoeW*2[Xu6^&&IV3)^9f'CW-i:\+$ch3@J0<F`(H*-VFLsBUKhP'4qG^lasMGC@hE_*mL48MTq_/'lPe'k<JLpI
+%U&Au1\ktD(.n(QA[S)X@g0N\IW6ol`+gKDr'DObJVjVG-8>qI?6*l3d!1>1&Zq&T.WP-C%%t\4OSdIDjFVQ'!g#C*sY?`RA3J:L]
+%".4Lb#,@_tCHnNI3\%*;\b4Fi83*IX?[)rUj0AE7DJ%An&\G(]"3+M9<I:@L;p<O'!0SPg:a9Qo$Af2#9B?(Q/oETR/iu;.d=Z3;
+%buT[d[M5.f_fn^aMaT:@BW>Sp>nZWGn":oh\'._oKJ=%jp9M3o]g'Bu3EIX!2/m_&BU4!H"6&=p'p<6<6Q-3Q?;&R@\Ph30PO?`6
+%%ln?YB]a7i1"9^BZ+$96J9c4s7ITe/.!4LWA%t7FiAlZ<HKZ)j%dns]VEc'#+(&;3>COsf:U@5WYUu-mYsmVAoV!rI-PtD_/J@Vj
+%bp\)7s'tM'Qg6]8F3uA^45c1#S/d1LHhWKar35EFQ!O$Y,0/H;?+X&I#['\(5QOI"b1#f#QZ(*)[<`IP-&IiHWcO?*$r6H[H]Q?/
+%^7i3'dK!ECi"LYTLh\sh+02!mRVY&b6"J0r-Y']WKN.8:R)c$Q>]'f]P7T3t;AZX9;9Lc"R^&>K6o.1VE-YEH/V1KIXor+4&\'EA
+%WhC%gD/uHU-8_V'Xbb4-7DMKrYtIEslQoeKA[*0'\a"a.[@/Q'-e"'U]a[r1<";+J<3!tPp/GG.bjl'JG+C/d\r+ILb,"Z5k*NCn
+%<9RnGMU9k'2Wm[Oq[3@j;Ml5h9qbU]m4HHpOVjn8C4#P[7:F885``rg@BCkp]f4RNm=$@&Y71LCc@XC`fW8IKSh"d/$>Q\Z8rca)
+%oP,,qF0ZUOlDgkmSg8ga\aH,E-)BcIICE3*HVZa[b3>N6ll^,`@gdo4V:\A;K-ar<e:nk_imC>iD!&C'Cp#J4Wp"3.:olD\1SiIG
+%.SC>+?K,MNe)%8,\HE*OE6H$T_UU4aGZ?`<:sDrF<`0$e[e8<W./K\i<rKIWJg8P<h7>2*CI?dUSZSl\X#uSj:/k;u2L0Qoa,X_2
+%A^2hAO0WjaZ[`oe!;KQYqc+"Rj.n[aN(GKS&1Fi`)oT6gRK7l=\dE@`;2gi%rDJh&WEH&?.Gh*+Ca$#uW(_gK^ls[0@'>.bd:bQ$
+%$3VkJ:e#3VeM+J6cn`'\FfoBoW.Ueh]WkML=t36+-&l?&k$3ZA*_F6/'YBctQ"_kbYeQ;jYiT03l'4lID7(fBbBH682bpMV*:"[.
+%Q$YO2`t"6=X/Oc&;+IK!'THX<<^+I#72`QS_>h:ejn$"f!TLZLN)3&cf"20'(Vkf?#u7\`QP-QATH6r$OI_jYcte'ukZksmcBW4!
+%/":^jCZ#O)0>'+4G&Is^mbg7;pQ^Wd2b#FjU5nu*]8@R?9)LplZ;O@ZAX$U_AI9K^=HI?p*b9q^(QF)?5=-D.hr(mp@<Ui![7'co
+%`BBBtC7s6^.YN0:gip;XLJHik6b*L*ZT.TBLcAC:-k'aFW&d(`rNCn]L&m"ai5=1lS])g:+Bc:-GY#n4Ui%*u4:Na5L?)2^6rQHN
+%WYPB1+k>,!'l/LeCIkk@6H_5/n6.4:g*[(D;2D@$NK'pZ"r(Z"A7mF2BL<-7'tUdR2;=52D3aU-9Fa"WO^"NL)q*1EM<r6XG=-tp
+%!L;LKmG81=hiQ'#L%oRW&ic[#*)[:WBaTWKL+D>?.n#4]9#VD>ieXLP8EdQUr\u6^*)]B=fI'0WPs\0e(&#fo;<Es:F+np]8CKRA
+%oNWR>N(2%Bk/,!WFG4<=kt:7DF+%ZHV(1VI/dbHQg70`:\HsOrNeB:+MDc]Dl^\9BJ6T_I@]oZAXK5[Z(sLct.*/38R=(ih[4Et2
+%/@Qg<!/HbTCeVSE=\^4H>O_iSNQX#&<&mcI#cV;D@d;mfGLi;3BMVMu>(foH^mQfYJ.?*E\=tcpL*YB;[L*Ygo4jSP85"tPg<+F^
+%pU7a?9hE=bP&<V3e[RdlG-#5'P#/Kf8a+#roc,-H@]BhCgS@mrC5WW37X9TMJK>8NMCr,`kn[+(SkN:B6KG;bP%C6drZ9@q#gP1\
+%mT#O4V?p+VE67l$L#4Q_*otOOP,kqjAWujlE/.tO:.:(7893Wt:9[InJ"s8L1XJb##rI6%HVUNX]O'"2FtCO]@'O7s!"Hc[L3`u5
+%pSuh:Mb8g;>X:0J0kJ-]6ke675QbsZ7(^M'k>h1?NIs-%'WU%2)\Ahn,#[*>[l<f+Yu=?B77C*"0[8.R4?4N8cTp%G+=u$j8po2:
+%4;b0fi!>X!#-'ihlngFl,DBo0%e>:g5I7BJ'%"i9&gotG<(kRcTu)<E*;`IR>GRnp1$q3q;=KR?j%&oJ^6p<J'?t&30j$(2P(uWm
+%Q*EFg!/g3VKWNa63b^1c6PflqWBq+3LJj[#Fs_eGDa&\/>>5clC1^`0?*\sJMc(VkROuJDV7`ldON\^`%"hlM.CJ$T[M(#Y1b)(t
+%H!UTIDiBklFA2A+FU(U"#_Bte>]`Nn679\u9u>EV&icP?81;Ni(u1_Y/Q$5i9Qi3OO@51L:A+g_.FC^4"K<nR#E&`mRF=C\n("%&
+%(6i9Na[Il'Q+]J)fm4qb,SLZXk7'k%#TTMYVG\5F5F5lIPp&F:'r,;4bn*jMapDcq;?nk^d9>HNE`)qC0``1$H%ishXrIq8RgfR9
+%^rmmdhLc)^cIK9OZ)q-a$ar[^C_:@2.-BX?iB+[(B&6SN06c]>YfJirj/\)>"2Q/i.KYZ@D@84&j+h$II]4K:&qPhdRqfb#%r`sV
+%gu$IMjA=e'/*Q_LT8H;s@.`bck*L?=^slFB_2>?Gcj-:A&Z^tV/g)rP_'2h<LYN5?n"*P8U-^gQ85l(@[Pc;V*H@f6I&g2:XWS&N
+%R"M*4VA%(Q[M@]4=a(h-MJ"/$V(JXbapC[>J_XXR9UOAOEZhiE<sp#D<>1biL?-JF`24"9VCNCZi(\P-GiG_jSWCl!h/WmhL-:An
+%,k#'Hpd;Bp[MD/R_4*bkJS8#lFY;Xiki&7nRhD8E1l29/VcC-?77A.DF"<.*MNTqq-O6[7Gg^qg(_F3<]T>,I#c08qF0%-<%9^>u
+%Hs\DZ@+EW^#b01LNg$1oQmh*=*7$iTO8TSd!\9'.p"qI`*FN&S2hs(!d3($`PX44439,8knP]q*?6(5s,h0%M`t5'-ELohn<Mo9r
+%g+97Jo>Tb_>EHb*UL/aHR3AG>%tF1G\(q$e#07G&MRThHglLf7::_MR*(Q@*ADr^.TE*%!XZG#A%3lleC'6?_706QD>ccD,gRMF:
+%VJoVW')oNLTi$]O5LCMtL%jYrpq[mY',Tj80C__,bLROP0<9P,b[9;Ia!\`=FNL'7#+13&->cbI"]Ae:SO+k%nUp?f(SGA\-,bAa
+%d7Q5hZg(Pt(,#onN?CD6Wh69?bkm:']6Q.Ng^-hLjZ679[umMn=&q,G?T]AR1dYFn5:+QAAsM60"JSjn1*T[Aclpf+d(g^(.%<]/
+%5/^+2K^#i6@cTPQ'$&2(M+K"W<-J7hM3lW0%tIT@f]/C/,SPsSQG(]l6T/5VY,`Kr#n0/t,@73'1TO(n:JECL?i_pZ+?8Rh%9IS(
+%dB)5?1*ge:%&%7[1Td8R(/QNGFu1&O<LJpnJ`MG1OVR53cn71IAeC^LPLG+_Sc+4o"r&L)R%^'WF/\Yg`$TS@71U^iWC[5rQNkOG
+%$YFL@o?+%e'&Y&0?%b"@\dO&/&k&j)eHLr"dVY[o%$P[?P7]*_AYbD,+3aYUUrg,VkgXn)<#aYe6g6qO_`cq[G0A?Hf,_rO+=q-*
+%bY`-]h'&52"noQd&:V+.YWlj;+:]`C\.gI:2I,7,c*4Wr7[n4u*ET[eZs0H%":$.jjk<Ba3cAT_=161h1[T%lI0eihm<&$SauqYo
+%moJkrnLZf7D21'V?gJq1Q=>`pQLD?1Qr,Krn$s[UZY0-GljSq@6'?%/PrjaF'G2rW/he]gT7FSO1SP5Hi)=bc+<?RY]EC%rRpaZq
+%!p:ET2*sIOb`)TtJ1R6n-mq\2]@!F*L>5;MCF!,X3ah#.R]^n*YXE2u4>9-@-:;LGJjJ>qLK<*/X[::hSg6Bn0G;dW:bmJ6<#=qa
+%BL^$Ga\N+^OWB`Q"@]qF'W48QALEiJ^oYD1%a<Q+MB.AMSQ.b=KN]48B#3pk/SLd+m[(]7;Hd7j7aY]L()\,BeX+D>-70`t`Hd2+
+%Yua=?7WI+7;mAtO@9OT)g\atXTF3/Y-Kt.+..J.i''V7Xap^Qn"8L+J<+cBcZO[%>!=Q$fMFRB9'rY#2ZC8mk&=Zo%^/cn"!0eh[
+%22RirJSru;K0]l-1]C-bH8N.A\Q.loC('`Ll<&^t,QWNW+W$#hb%f./)Q,g=ag3mZ!k;c8`>L4'@XZ2R"2*fM0JJS1=@B96aBV=H
+%MjU:U0L8348@l2U/`]kHPdBG4DW#YO@'$KG=]5E#Z^27t$:Cf!9:W8<U(O`Ai5`Xq=QON6@?;+lWQo<7N'pZi9Elk)+^&qo%-UuV
+%l9!NVS#]`3fU87cd(*>"+jF`VjL,fU_1M35Un!aFGE-^u:3a41EWh:3"BSTtB=LTu_!.8.IKF/$dp'#EV*fF*?L_$CR.;4JfnkeH
+%7(<>Ua<[hV9Fjp"3f5C^mW3g&'VN,:f'<-qE7WojFS-B.I]WAVb_2Z]0fD3"L<;[jC5'^"c5A4m'uUCf6E=f)BP1,H+N;pSM[W7@
+%N/Eq&'K?u]65e<I=Y6hO;;.gsHkCBA>"5?7`8jek;edG*ShV'(?3?LLKLdh9aIT2+1:Sa$&55UsK[PB,'e"/JLt!6QM<9-,r/Rbl
+%I,eC*dQg9QnRS%e`&t%F@L^OlX&->MXDS2l[fY,"!;hK^^f@o&XC<AfMQhpLO/#XjFeTAR7519bfLLA.K+g+]j!_eR>8D`Ak67]0
+%pW99V:/H\6=?7YmLEkeh8`\!UD\q"<kO*E\_aQ7KdsIe@/!iN3c`0fAfqe8.D147>2APYqL-W'qa?8QBV$sf5+J)u!b6GbI[WN6s
+%mOU)0K'&n\0$H1tX/Q%ScR[r^nIU>dZN18nN3JkRGY&5Mhb2n*,Gn6C^!2ToZZk\EdmQP:iT0L:>EUpF+q(W8'F[IMaeU[H*>lac
+%H,#_[o?:(R1QC6i"%bMDJe9lmiT<IAhEi\,!G!:+T2r\V;Wp:fDiT$l6pJ8e"RHkM/c$RDOYn/G\KV\$?^-<=D:*tC+H:;??JATu
+%IrO&,A15]5R=9mR(Fts;:l'[d&GaL5!QkR*JP_f')bi7HI_Ob,dq[hpU@=CL28.4l;L/G28>`B),7:FZ,/r"$=&mV*1+D^#e-0!1
+%Y:*hDk!J"?)!\I.!9+CERqVo!o%APlUdjSM19<B"?'4'I:FIh]cb7RFm/V9[<!sH;Lo<?@-'sM_(%ub^ep90GR:$C\6Q]1],[&\3
+%oq:TVR>(<*)OR'(M%OJPMdZMc$A^2@2K4@P0ZdN^8Zko8I#bnH33^ML'DEqtAI1hJ]0g&aI1kFY]gdCMMFRkP.:$'tX;P#H&?].2
+%dNifKBqV-C+c2E>Gst[B'hT1k'k?]+F7qQKY9ec+7*?Rsm@9=G,n*GrfE.hXK;^,?mHR[knmj`U#o)Ys+3H6A!Ac`#H[*aK=\Ckr
+%EbgjMN,_:t,-=2H0$BE!#0K`l$mgMd4".H)qpS??X\Sk#j1MPaCScpak/UiuQcrBrJUQ.?W&-jcRBg#(fjnfW<%H3Qs6?\!X\m:-
+%%7*:9$6K""ds;qkr=1je\c09/nu5h+<+SKo.EAA(X[G`-$Jsk*TbjhO1)#+3b\I@L"(eXs!7>k[o[#CA'PcmlNY>Y\$2ME'L!fOT
+%2H'`Z@E*YsMXepWML\6uJD2D:E/I=l]oqLsipVN%GBKcL$QtNOWtMDc=3UDs6kM@&.#Sh5GbsDR'2%NN6P9i#hFGNsKs^?+3(%M8
+%]MJfO>)@[O6Z(eDZNtV,?]1Cc.S@rB@E<s6V4A5A"3g[`.U88@"6Z#XU&h\>Tsth'Xb9h#D%aoR'fJcbnX?9r0Zb[.'&:f$a/MP"
+%-"[d0Vq*D0h]*>skSHFt6MJ6BMts)e#m)5qUPNYoF[uT;P(Xo.W1(hU^B"<XnBtM9.sRr<5V^`"6!bHVKF*OQL14?IS!@Fl,YR0>
+%<a.Lp;8kD=Q]/W$Te\2)cD?(#l;#c50OK+an52(Y&iRZ&fY^-7^(/kl3f09b;6[>GkU9hm`AP$((E4_IENp`>Jsob^VPjSsYS"t`
+%4Agd=1>G-`[F,@i0I!Pt9HLgI*/[MSfsELW47Rq@p'^X]k2o+^5Vk.*m'Wo=7k-ef8aJAG[a?Ap>@TR4=LVH8P%h&"]'^!A@JZH#
+%Z19iN[-0deB-mr^AHil/!'NfA?lA*464^A-HB[lHYEf).<='b5'Ak<'/q7dNHTn0EDUS_l!`D^uV)TnX1Y%mmK[ZWbZ!=?@a4>Eb
+%-SDH5-I.Vm&70$kEgJ9BSuJ1;?0]aY;.4G=I30CT+><Y>fS258!Q!7h[i([21+Fe;bm["e=)jq^_G9]LY-#]4/2eFKOBKC2G[9Yq
+%E5=D1j/Jca'I9Hi(0^m9CLQs:2NDN.%Pgr1)ur\i#:T)_e^pYA(hqTqJZj4=E)Be1o0&OZBjcXXHU-H$6M*Dd"Wu0JY>C4^d#nnG
+%bf<uO6X'+*JbkIEI7VSr6K(+;HQNm<%k6S[D"@a8qB:Fg3naI^(k5)M^Ikt"T]R>Zpob8.%uUMub6[I"*-eWt&QAaA)-)C425l4t
+%=%#@cpU,!hE.*@jV7!T:ZhLDMUP5gl4.^M2<L?M,-F=p?KO/=EV1%`K/^.P%k!aSP^,/dl?=J0B)uS6>[=jOd"=5>1H#QfKMK,&9
+%$qNj%e/082/pjF.=LO[;+a1!t..E>%;DCEcS[-,8"thm]K:Y)g8;[IN<fi>pcl(&tBK7YZ;OH=sUaD:'HQ,7\6;^"nhA&asKir[l
+%_E=W0?D2Nh9Q8?jiNp[]GG\[q0V3oTfZag:`uCr[#-"9*&\jYBZdfQm)Yc$.d:V3LnhfX((\=iq\uo`J?-d2'DeVmrVo9Tg-$r>E
+%c8NBA?h051huUoDKLT8O0(1dSQQ)W$l3P<-E/.2S]gZBd/2aHJ]ACFG"u,c9Yo=\1iF*eOR#(Q,P:9R%GD<ge(8RZ0pE6Y87f`34
+%'bA+H6eM8s7"0Z`+2I<b#lPJlrrD[U9Fhsc&r[G5<g"-I&fHEQ%kHlV50_P(7M]!cPscHmAZr^f!Y$tm%NE085<VRu3gr8E+.M;_
+%+FOj<mlir54V^qM%Bn&C8m8XdA+5e+Ya;#e[n69kBWb>"5j"c;E-2P1/&/9cS,e3_iW[HJ>pOCl)AjF(q?7go'(tX)&E3'_a[X1T
+%Um2Xk@CjoA0kr"kC*hhRR$om+iu4eBXX/a^'?Pu#B>aAKPuKXF0ek\g-n3)-<KO[,V1p@odNKnraMLLN'f>-U44pIR:#JlgPD'$f
+%Y@^cSWpthi3&45XQ9sbN?Pd7N_;.4FOXmN-Q<7[m="^<f/]^-W3DDh/b0[I4O]>_?Br)J<'j%\9f^MG>[]0kf<G,7o:oZEJk16PM
+%&_:R?_rqpHN`n<d($S51@9oilc\]"GO>e:?nV!Rq)15>b/C',nRdfnrh'&I^b+i:jebibGVSP\niZ+)9Ms>mn6X8sq/gl4,6c*aQ
+%/Hg-j2]'A!"#B%*Etb[ac2RK.PI-YmHDTV0%d>\%FI8IWb[Ol"GMUT(*Tk_/ZY`c!F,)cg_d)*,]\lWsnM&^B,r9g2KmB'M]TO"h
+%gkbdVAD/RG*9!3\r$F;4VhH9b;^KJ5Acn?Hq["\jlJs(<Rj^SUMi.W%#PM`GMWcsfm,HDu//pjZBI(gk"q\r',7t"qE-5bk$pnd.
+%>;0Fkk."lk$)Af_pa"<EZ,egEUc.+oBi?<u,q2J]X(7AqX#j6(:is].WsMfq1AFZ&6#A\k_&`+.Y%AIZ1QhBPQIbYsoH#/PY7Yd;
+%#pn*O.F1?rU'NBF%Vj$@QhjHd)i.<jnjO.714C_:D1+jE%K!\4fc9ZF33\@Yj;DN"p=<W)f+&'2'0-B0S-6#9&aCl&HYGB#?83i1
+%"5!de=/H-tOpG*Ye3KFPXsS`9n](1XB<\Z/&[.e/PI-A7>fY?tMBXA]T%&/I?AW`ek[X^[:H7:/c5^#Q[sHK.oGOWI&UGGaT?.<Q
+%Y4*)8\;Z3Ea6UitUVsuWMW$60dGd24<k'ZnFTK_"T[_fP"X@(#4`L:`MJGY/@]fUL`F\C?2.-]ZN_2l<fSm>,6seW@W_CQC85F$+
+%TU:o*H,0uhC2E6`>,bU\36`Kg-"''qBVhnX#;gk;4Z0%Scub$CLZjWa5aII.kTdV6#h^7&,qbgA50sZ$,dk3Y8)Sc/?j,O46N5Tb
+%"'/;+#"]%M#n"R\L1/fR+@Tb3Xtp/]_6uh\8e_EEGHdgKQ66Jk1;V)=jdef!/#81-qSs>Na<@\HOFV?dK0R<?O+@2H*.VMfmqJXB
+%/rN[fo`MoQ$Xo.%0[+B9c%G4pL!C+p74)URTVKsbgfq]/rcaFRoLd(oW$&B)R!]^%rRhQ_Z3V=;g8qH1i#IoF7IYVE[[AR<Ze@r`
+%9GYj%M-SIuqZlfUE?MhhWLHFgaOtMF,Q.'M<dBL9^'h<0#("=c#:,U7GoD8jZpU'-Vnt9Lj@Ag.;@5g!INU9k9pV.Y1sHm'f97Kb
+%M%qNi(rLHT+Ud\!YBI]u]?b41&=s*Lk*:h?pI?&$A`SfKG=,!7Ub,>]Yp9]Z<2@6:<<9I%<o@aKo(=F>8$Et^.nh_["d)Fj#65(2
+%E)pKsnEeUI-0XSSHg$Q(F9Q>@!+h5<gFGPX+Xh^D+('Sf%q4]i!;d,UI0CHPK[?p<m8<h!Z5SHr0TbLOYlA)INOIO^J*iMYP9kdS
+%6Sm&[',SV:KDhP3a_H3@cIqOB-2gu"3dGguM9%1%ZgZSOe/n.[lt7$/(Nbf9Y7r*#bUl>ddO<`$`CVcCUbHQYf0tc'dFF4O`C3[*
+%0rru=@gD\HIn1t[c(CHcY>,t>3SW/EE0^^^,3^j3K8H)rk71`CY1]#I`8e?6*,cfY&DrS=(:]X,ITSNHOE;,B2E0Q\.td]l%fA0M
+%LD:YYT=ka"WK=mhi`8of;uAo;UNYFoJMPAQkl[4?qck)-PVpr`=&'W+$aP"qr1\X8:A3\6QQAQ)(:,qd4E").\j3[N"?%<)!^h,+
+%"OnuNW[J'iCc_2mc5R[(Ji^9r&B==\[YBRK`$"FS@LUTa"XeXm^,.AJiOk06!U1*t109g3iP@Z.6dd'F@/rEXaQghNW%8(IC/P!C
+%r<=p8P<:Moo48\YWucNZC8ZJHM^Y^3TWmSJI5^hILd3[16'eadTt%mS]S!5"o(n-Q(qiu;,$Y5MXa2\&&;7nr#[4Hl/Jnh5N[Gk>
+%.:Y&P7&u&p1"\BeSS8/(:+LlKk)(9(*[68q@^0HW5P'J)/`d?4O5b=1,#nGZ<hUC/=#0OZ-dZTT-R6:aH&Il'WW3ZNJda@XH/;NU
+%!s0<B(l`$IVh0`R3.aMH1*beknU0CdZ$Gj,3[5?6@/9.:<'%HF4PC@Y2FP*X,2rgj\KT79'pCSlmgYD.X/Nf7JoHN'>fA!!0T8B+
+%itrXo6rB!7Q7LV3+c^W"p`+oR=)as&`9@UiFb"!C@U<.*YsU)0&9YUBclJj+#IrY+N:71GG_eI'Tp1=gjtZRT"XcIO<"IC..nK%N
+%Wd=pL]n-t@ilVK3oG+b0&D97c^^guVVlSaV!D7,2dDbWT,j?ba2Ec-qE1#SA?HLS5VK33p^/bocp63UQBkJq6C;XSj@G9I.MVKnV
+%DO>[XP,($1kSpDuXeZ9+U_N6n*j-b;NY37cWK1h/P/EO,EUMp\Rc]&gk:lRM,u&KK;EDr`>tIs8A[DqG?WYZdLFKXKjP,qfh-j4M
+%+T6L1<HoglGaO#oR]JWQK/0Bm18q@](O"q'3:Ou_js96YMT(a:WNU@a*=3HMk[pFW/ELYXSuQd4k1Ks@`]fa-gf7cP/`.,UX7*(=
+%cm!Hr&&:)kliuRRL9eM4"[lg]:sRk<XoM#<]V#l$I>A]8B;gpNMKpMS!K0JsNfgFB^sNRNAskId<)m<B_j-*`7)]SuGFnF[&%I6Y
+%5eY'\js\Z2?;=PjU5Pcm9R=BM,Ff`_49L3i=`g8%B4WPdL+&?l!Ya#+HJTOV@%;[41kKGl*"oqsmZr,W:r]\>J'0hF_&Eu7T&JbH
+%)\6;a)hq(tW]LV89^(:^<EF&5DP`;p=3Ep*=s>-K-49hT(8c&3p=E&ff'sVsk8rD*,a/X(*fq'!PSW%<a0TF/fW+d"_TZt_XOPAk
+%lj]gO=LaGR8XBm,l)J^$d/"r9RZ_G`ZU3t)PKGW_6MM*X]cgq(h-joj^UGDb/2S;^!l5`P(*c\FJ3#0e)bk9ZA@7dC1]dp3<AO\t
+%&dR>b3"unr#+1X6XRs1T(tD:ep/)S>itVuk>'5jVL.K-''$66'>kbsA6DS"ZLqWB3dQGA<aZ,g[m?*C''sloJ*a5.Q$n)u4/);`@
+%(t]qGBTrg+1j#E+*&t5dQ#phSP>?7FH`Kq;6I]dEZ6c?:`TH!VNjItb<QS&fKM,*LS6RiaVJ?tH%2<Uj+UZUEiIr<_@0Gifa>9NN
+%SAp&I:u:IsP>m<U9UT&uYG,%D)0q`k.C)I+]?)\/$%#MVHT)G'-JS6/[nlS!b-c%t7@IUidOM4hMG1Sf+?%JOfcS$9Pa^qCC($gW
+%77]:X4dk'%A/)2h((MZ7C=#ac:3/&p(snd2?r_U\n:2E'5U95j>+m\/dOAW(HhEJ"o;<?uVdQ4K&'>8Hl++G-JP\t>BL#_aPLY>'
+%ikl[0_*-Hs"9'U2U#"mH)R;E+'0oPCOs/ILN@G*0"k7tIJ[I+S$^J?::YKrfib#`M;0hSuOU3hn#K17G\mh70`6k6u=7H_j*).4u
+%<LCk.Ttk*hE#;tf#tEK7m[Z+VE@*[YbS;Z'Ni_hLK).0bI3n3m1o0tI\R/H@OaE6h7bTuOHH"go'Y2a-OYd1f'9J3P!OUM(0%cEO
+%\-3$aokc"[1']XS8Tn7"CJM:%UJpFY-J:cA5A4).2D/SGlW"LC.!0'\[V\S*2C*no&BDK]T^?gN@Fsr=g'nqhf%KVKb^'@$^6K9%
+%9"90YfO!8,_c&<Q:W&AT324<s]LLJ]7dN(.!8O=W*0I)bS.5Qm%/D,KQmRQh'LN(_&_Fu/0?0AHA&u*`a39)=OKrGT&d^jVRfUd3
+%DCNGjkZ*T9SjjKQSm/T0R0:gqKS+8cjb?mL9LdXZhA%oJ^j;=I"Vk,E>U`$@PnaLh+^<-Of4BX<B#kdp_CRKRTrI/gbJr0q($)&b
+%"(KrD3+2I)b!!V:.h-J.aH;368h6-!6[GUQOjf]hBuCK=UleiSS/TgSNJOZ:8?^+=/soK9ab)Bl`(hT2QAAuaW@@OG%JEV;U_2du
+%r%jKbM3;e3gnU;ZWYa(`>f;r,`ik*@PC_.)+c\pUr#YWT;?&KmPb&l.lMg2i,".lt6C^:Ej[VEXg6;dKPo;+BD!Y1.3VdKe[TRXD
+%c?0A*^'9EOZpNM6:J/WR]?6O!jOY;*E=H$^p9"5*FRgrAILK-#LIpbq7RHuY2tr^NY#P>UR1G%E%N?F3@+a/kYQj/!UVb8;4<5j*
+%4QQ,OY^``"3EK,]._JjTpI`G#=+jbZ"/:m$RO3Y,@AG;I;Cn,?)Iu9,^h9W6>,XGc[9;(Ci2U=g\\UhbZp+27";hPNSnkI@e$p%?
+%TOcPEH)[',<5YG1.g<)1\Yc-te7&>k[:I#Z$LPj`8F-Z2r2Rt\(qisC>U0lU<-8coAeBW`]P-7+P$qOOUisr='B$Yl<E&oZV$e[7
+%A6,JM&88/X=Nt;f4RC&"66n,G!8^AKY$B>+CjCkk&5[U)K).eAl.JlV:i/-n@WE6[#l_OE-=p%XS:55T4WiNB.Ktq,]BJA`_!+Tl
+%T2d4r3IY*J:jBUGr!h9SNo5\k(@4_XCnp<rYf:5<[9N^C5rdOEY4B`>=<WbWFQfh>Y&b)!JP`VS]&.TGB<-j/-+T[cnLYnNi#_Ft
+%6ffPfaU&hs"UR%k6Tkuo-Qfhug'C_8cp//T'uNsl&r?^qB`haKT[Oo91!FflRfHG5Oo\[je^I97A7gPU@Z:k-8=VCYfbb?BXAF,"
+%=?_Im+=kqb6^j,P8s04#aXZ>fLn%npiipJuE"=nNhR3H1_JkDB2WMs"?.n;Vj"NSV`@dc.DPk%Ze_o=H2stXK&!"Qck_rUjG&I++
+%*N,bL-S&Rjf82tia?cN8]eu73&Z*@+HsrSE@8QQ9=<2IZP30"6k-.&4?7jLdlE<t&d]_5/A*/*9TR7MCfPMAR^KD_D#,3i_AV3ZR
+%\"lV5fbO?a^Z2$?HW,Z[ccSV_nu*"i^Qk^;s&g@+^h]#(pg"sk!(1=+W)sI.OFb"6DB3_HeI\SpY4-B`%/8#N?L2Q,fp19t_`G3C
+%MRMR)\'"_(J)@>P/eChM=la[RoTB6gHtnJ_TE.N6'1UN%XgCGpc@i41/@&`\>bD=jF\8ihK$fGgieUDgN\Xb_<Y>3/;h4KGZ3:Am
+%a-iAek/_kb(!BB_'t^G_:hIVW$M$oEW!uUcj$JY*7iW?;Zh4D7V]^,>UHAnAbXS6b3qr)lQhJ%=p"AX"L(ggQBh=+H8<!DfeGqT5
+%F[F[!4Ii".M;4Tm#L_$/WAhgB*@lda6h69M9?8TV#ajeD`K'3Oc23;J%E^gc\G-n'Je$]W.*-G+&SNU_&h8!@j`ISpUu@^\S^67t
+%?9@i?$Y!4/HWY=cISQ-@.dg@f*`dY1e:q>0,JQ^l0Oeu<OZcYdjHop9c;QUW!$]_i;p,MncB)^PKp$)&^1U9KISedJD[,ZW[eBIh
+%Q&7HLQkhT2?4$P.P<f1`>3*VBcqc:n,[Lg<S6i*P#oZeRVoR[*fm_0&_1Z)TA!WHO?in:^:]dgfnj,(`$;J(.\i:q(XJCi+G_F>4
+%driO%20,H($dtCrBt-A34)'shA4T3G,VE4C3Do+%Zf;sa#Z>'CAW(MX'Xbn>2[p3Q"6h2D`@F$jEL3]:<@=ORV:;f=V.HYt['5G<
+%<#60n1aqkeH")"3NB(QNfOoq422"W.RVBpn',E%_?=E_*Yra.'E%+]9[,rFVodIQs%>*;-A#:O,3@l'\9;+u;p(2:I7L.kQfTc%n
+%A@$=dnCa=""@\7cC''KO+4lAbX;:GA>'Z4*-ja$-Cr3$j&G9^/7S0LkC8Rj0)dW'P/$NDF6Y*W-nHl'f6O-_=^ce>.n+?28UJIZt
+%$0jq`9@_0(\al=%?J`AbCmT9o=+/de2cmS/#=Lm'b+TPrU,=Eq+mIA]6.5`U)'5^+P;bIsUXQl%n;!@Kn2f77HJ\VY&Dg,h;re9/
+%K[l?F;%L"-Qn*OK4`j`?\OQ#adkt5,-ml1@Oh/T13b2N%AS<*i\INml7i\d$51q[^lj?Cf?\AO7=X6=PZcu)%,37LcEW)?7kWt6u
+%=$!7$R^8<N:pI70CF*[*X;3[SbY$F$'2=[h1p]b-3AT:42]r^V6,:$":!Fl8,A=cf$DAg6P2.ZWGO4e*"r'A?5GkF[ZnlZ?P'@I*
+%Qo-"f'n`?6Ch\:'o8S?kb#=ER*G'^BYO27``*V+.1!G\=JM5/M=o&,_1(bXSA[;c]`cEV`js;e$UdJ]ZfAs`nV[6R4;a-TF;+q6X
+%1Z\tEVEm)XRK$>&OK:=T-daD4rQpGij;A;-J\F;e%?Y".p&a\Lk,e'++\m4'A2gn_fBM`TauU=/8LPWbdIfnFPb9o*s%SiFr2'-J
+%BLti%:Cdm`ArmbP8]AmWEQUBoHC7S3`h,M-Ci-&?='hB/TJGVs4roimS?DFl%#J;FUbLgi]#0-33tt:B"!b7N+YD.aKp2H58gWJ*
+%c/N/[@qQ@p8H:]TGg&k&Z_B/N!K.[O5cELn,WHJk-gE[H9Ok73_6kK7UO(A+_UC#(W^l``LP;r+MIc>9k6ZT+53$s:PVIlHWk4o$
+%Q]i^qVh.-O`p`/f15?iAo`NRiXL(gJ[Z'sL*A9Cf_-:N"[0E.4bH$?@2h8/00FgMi-j&0=77KqSB(kHP[q``5k?NQ=U)Y:"SdBs*
+%;T/<01NI,^>VQmu"IUkk8('XZ[GEld.n=?3.UC\\`0RIuV%Y2VkB`,&Fri)<+Lq$AYJ@M8>,7bH3W,-'+]`3O!lpEiHq:43Q.uIK
+%:PK\]4WNX;qX7JsMfR"oT+*&e?ncS$,Bn"O/)Lh@]r(r1/e@&-Y#Gsr5<p7Q"-BY^:8;+CkUVo.q5&j?e3>p.ot)BbqtNKLI.NLm
+%h]ui6ZBZhN1W.`PR#Ob9V"@mBE+=pT>"R7E,_!6@WEh)Hk-CcgM%2Uu*e_]1=b$`&#[OBAO97TKWN6(+P"Ljg2))"D>JM4,q1Tke
+%BVG#9PSupl#F6:PTEnssgP!LJjV+I3BWi%(M&8pUciLHI&`oOI);*2m=;g4o.74k)SLcIckIQOeYVcG^"dH]#7`>Q-cP_FW;W:Pf
+%J1+ad+&eiu"TJ[/f<2:9<;44MHQYl\c`L.Y*Rl%a9m^NbIP!p9QqP1l8S(_@AYhT68hHB<h3VQ(R$DDAalZRe"?DIeck15A&B.@s
+%_kZ\NR6%"UMMO_OPmL=S'UYu+'h1aEIJi#0l(omF&'?_g$9G:'Ii9,\)O?Uk.6f[@<Ac=B[8I!?==e5i<bnN7f<AN3Ycu`ZF(!os
+%(qL[kAf\U>`=#Ko=jIEL%j`\NTe^>[]ZBY>d/Z?JW=L9@S&#_D*%HTK#pE)f)IaG51+3o(?ce1J,u`t,rXEKgc6@ttc`mofm&]9g
+%,h*69G#0HGc2d-2,`S<5LslD\$8`C_:AYh#nu.AsKAj,RU1,Y7a+!e]Ac%:L($OhbPg$Ambcj'dEJBTc=l&ks>7]/<U7666pc/J6
+%%cO36d*j.3FU2Zo(G9hk_INZjqfGN_42-,>'qTdA)S6#Ee2hl$5k?"g%NF45W%L10n"4T4Zh4+T0Al@$rpoWdZM`X`i+Kh$fCn;j
+%?bcO3mG$7Mr:0-uRu?$:&cVXdYF!jb`'=:rlg(mXMjGeB4]1`6oL=>\s5u&mobi,"Zf[T;pg<tarj.Ns4%Ug748D,@f:BRMYQ'TQ
+%f!Kaf(t`FEg,t:"/4El3>;,-RgR$jEY.5L$cis&VS7k8e5[sLOIHQFgQ^m=89hiX%s.];KMa7_(qWshp\u."s'K\(EeD?TIYsZ/-
+%#mS+?Z'/E/qF+t<mm<jWCT>$?]1a,7QB1fATBjflJKReH"@:*LQ>@RV<<@Y$e1\qKZ/Fp7g7\.@h^*.tZ.2JVUhDms=o2rEAgHd[
+%0\Q].C]^S6$cZ5nRBZTs;o2pG2BWns8)'82QicqeKo4.5\WpP8L"iW-gk.&r>0oVSFE3`o&o5lZRWO"l:(JpQ7$!URQ+h?8a&^$.
+%_W$ff+-S$ld<;Rl:::EDa$C6->LuL?'4r(aT.T*3VsgO<ZrdL?;C3sYN3`WnG*fO+W?p9@Y1Y/Vq(9f$WOQBRY:5#0MldZ7#A!6W
+%^TRp^2Ip5ffY1X,d8$(hLsANnIrj6"nFnN2P@4\M4Vd3jq"dV%b"tUg99oo:I^1kYIc&O-.E94\0d5r;8T$YOC]^rMo!n30AGc6H
+%<8Fp&e>5[-8d1*L?=Ok@&n',4Bu\:hL-eeC'Q.?I(tcK@oW4-4<qX0\###Yr'_PRI0_:"lbDZ+a`0pa"H/Adp+lLE7-MI7`H\':,
+%6nF:f1:X25>J=_^%YIo?*\/0?pEJAY#`]#-iglR4f\OZnjOUZ?qW`fEn)Ok4j]1BZmA#O,[XfZ22%43nO:?uHhDB5*N0hj8,F++m
+%jj&&bX03CWF>sAIW@9E$e2n9NIhoLsE@YcTS+C/<XI\JBOgsX%'ppoLKh=3eSbA+*H<ZR]^'n.mPktR#Cm*N2ouUag_A1!hNffrt
+%lq,rnrU'^=ARS1B(/"_#OK_#[AFu'tP#PO14`Ga2d&mro[?DrSX92?ME[aa"K-P4d<31=4g@T\cOjH$KN!Y?iMTD[F"?;#)WMehI
+%`],fJ%]#uL%M<IHBB'UKeV;k=)kCI\jrO['=;&lKKQnd&S?tTA&1_o1R._mq-C_jl6s+ie3Nuam&o3@f^B+m["YjlRp6fQp9rJ7b
+%E#4Kj;9KCN<n8Q0<[#t,6.0uHF%m`?%rIaSd-&CBJ"DO7P"C.<0&b0a+JL]C,](@FEX=3/138ChG/j:E;4E+%>tGn6b%oW+-j\Ai
+%E&0(h=i)V@^R(b+Y_cYts5=?5>UiJr7K$R%gX,8>q!]4T-!-dBG&^3#+uhIMKo/7@!O"cjFh?e)d]Sh1;AT,-\%uVD)2Vj[McWB$
+%9S"Qq78%A,*P7)q([%%TJEeS*'K,I9Kqp>9Di:3\BMW:0CBI-1&bt,%`!OJV7LT[P\1*#`KRO4YX<cA%*YN7MNeAIe_N(@i'nd8-
+%/Jpa,"XN_/Rg08p`&-&L-#p5Spp=SV!1P,$r-Z+J'C_>l1"["_X-61+%*=6cK`+9!-EIF:KB0Mi<m\)?']mo3)e34ESP:p/eB-2\
+%:'AUTnksU?H0kb0mdVm;NPi3(.#p^QAo"'l%ag^mXPQTiV#;@-CLeS&<Iqu*aAO,H=CdspkY+8L%DHm8JtI"s9JN2k,+>Dg$YAf$
+%kC0st;pSiHF=_^-=$A#c5.fRV=op#de/];m>7PgX#OBCTcUg?g))*rh$0U#I60t=?:c5i`K#8V9:iR<FM`WSpnE8MUQ6KlZ.\_Ks
+%AP\4)-pgY:=WUZX/)5]a7&]g]+Ah5A`I4l8`scZ*Co&^MZ1)-ZFU@>uJgd"'Z9m0M82#$_3n"@u[r8/IRpup@C"=+!PelLQ`g1_E
+%2T0iF^lrDYUUe.T:sMBb)GFTJO&1GY.Fa'^=LUPJ8arUQRdOE,P=dqoBZ1`#EsNN0?B@K?P7k1DLS<\XUu6pT:[t5/f80>b$Ag00
+%N.*/fXb+beg/i&e1XYEiQ%EcqDCB.pGu`PqgiFkNJ$7r8=LXR<A<Z-Bo+S,?9a1\2XX[F7\@bFOG23=@PPC@t?AF8-0'mM@m>aS$
+%DI>Y83-<)XL8RG_>EBE*=qk?L/e@'[>F;Nk(-AWM/L1,?]%'NNC^p"KkV9p[12(WO"K:`$9IFeP8Kb;#2f^LoWkVL`<_F*c=K))-
+%(ZHD34i`(TSFDgWV0^X^P+ie[`,(o^L+E&[KZ)I0&Xk9(=;+:EclUX)NH5KRL9Zk%H#;Zkb-p'4LkrFm`'s,WLdkO(TBi2L%B+T5
+%Ket$U<b469RI,U%M'FX'!KE'[+Q6U.FI!Aj(Fnj"""FVg&;63RAfS)0@!ad_ZBU0Tf[OHg#BJm2JG*Jh`Y%DKhOItGEG>_n"%n?<
+%m+WYQ$$s3S"IQ&E+>QFG!3L=jHM#KTJ$;@TXj.Fu@kuD]`a@q6:%k8]eJ/gjc&F>&X'&/a"9s*e,nXklM;KAd+(;K/oImdbnXdr.
+%74<sUTsHW:/tNFJKZTo1"sF:h%6/XmL#2>m(L&Sf@673WcIIWN1C%RgPpm"XL>j6]nrf=qX'&?3lTn]@5F0R<NKP>M:X<#/g9Z`L
+%W)6RACfSB@ff;?,eRC=&iTr9,`dli46'Q@``ENF%_G3RP%Ohc7hpm\kg'6&g]rkX,lnGm/D.on^_dJ?JTas3@`<0:[/JiPjWamK7
+%&1@p,No<UhE%Qh,p#((O&E6nrQWfqr34\ct=LOYu8rnjKJoN_*Zkl$Jn,ah?PB7s\ILIO2Tl1mo:?D"OTCaZQ$ssc44')su37U=d
+%SgEMJ1,)/#BJ!@2icgZJ]^Y*`H]<`BFjdX]eFR[p?>,+Xh8N^;p/`_E:a/]K^(JKB)]gp'4)R!k<V8f!h1W8h>G[Ya%U^b8-NL<#
+%DWWfD3jJFfR0uX%F`9@*q3aedf2K-@W8snlQ5$1To_-_I3]qFE5<kbj9sr"?`TDeajs;AN!\/91/^M'#`OHLc%poH>.*>Z=6u\c\
+%akR/Y0B\7l[Nsd'nK"I!njtfn=Z?R5hGf]]_'OoK*+$HWErTm?RSVkBjg`@*HBkcmPP^nM(`nG[cS59klM2Z6Xq7gAnZmG8P[k`U
+%C/B.c.<3-r46B8b,p0DQ%8[/Kiamf17K`VRJuPKc!m_,e(mBhRn]i$YdOH/c`>9eZk#;^U=D1A?7XjUDS$S&9iGO:>/^e??W-%_7
+%1\-?fI57ppllY`4S*;XN)hNaLG>Rfuo[c2$L63dgIYY:[DUNV]fP-Op$%h9KOKb2(D1t,b)LT%V7+_PTE`X7C`0n?%N!7NNV2[\K
+%keO9<=9UT1OIBd18Mn6N/*R&i\sUu^:+p+DF(2II'1s-2MdjsXIOf9;$>aCNa)`#gdN?qT;5&hd]`d\f=edma!H2He)f"ngFe$X9
+%JPM=[.)]SS8qj:o3=LjEiR+[21XY:3D'`Ygg4tFj#<sal1!SCEj/I="1^b^pb,9FVjauSI0&fePnaTKOQfk>6",s%=%ArbJ,kTFr
+%6%@,o?LUk`i]Pg9-q=N7`<e\`%JLHt'<)o-"RD9m0'GS.Qpu3t$<8C(O&""@&IR6.c.P;!@-J5ff1\l4,]l6.ge8hD<9t;nJXoUM
+%lND1Pk6i"oLNp8`W0t.+l=)9d4[8fp1e&_IcH^!EXeT1Ii+u&OQn%c&k0?i5#ITKJV)DIA+%1OGUg2N?cj-Mj1I46^oo=ht#t.1D
+%ju0LK//BId930DK-:'I`9FAr$hU>*5gae.L/YL*(:_bT$b8:O+67#VCJ:!?T52"eFb(Nfg6'YP:bNoJ_@iKA-n<G@fe4SG1(I-Q6
+%^]L.'r87]O3ZDP&("'M9Sg>(UC+.\T`s#$#U3<;^7T?EodR#F`gc%L*&Keu!C[)rG-M>k`$PWp<Bg&^F6Oh9DC++LG&Rd$A&7MjM
+%)iC,*"#pQ(Cr%BgA(W3BjsSNF/gc,6GpF691Rurj@ctkO.W9cTk!0?pr^[L^QVheF"F$mqg9O.)0g7R*g6I)]-1M8f4AV[h]d/X-
+%Q$ZLHWI]pu"?-koGKg@rk.a]DnYRa#m1nXJY`O@@&PO'\<=2Ra"(f1Hd\161)1('L#=e*I@/b^64!:AEMem;`[Oac?RM+W$>ffnh
+%(0qd>^W.6^]/o^cN"r/sW6e1k%l\g0:A*aa,2a,rc\"OZKsno0Du;a7(_lY+gn6<B@]SdAajBp6!Zr<e6!\8":=MOL\9f/%;NP!H
+%"XK(^=+K-r1qar2<c5oKbk,Gj^a*UE2n75e)38s3SWJ_5[4WNu!rh8ln6@e;OS`cVqO%hF=Fn`gO/-3!^u/QhmFnC.Yi0Z=7@8ZS
+%4E_'t-3iT6/V4jccp5"sN5fbG=-BE#9&>4O:6REcB![8(n!8V=<'eg\,dMZkdQ,0D.B`;0`QgU%\X9D,gW&#lo%<qXl(E#EE"W"[
+%r.>07Wl\:%#))NV8>E<,XR<.39gTB_@"hXkf)^:VJmY0:pqMo-d<mZC_<_)o_dR^,3FkgP&.V#1W&Zo#2!D:G;s4=[M97uE"Rp3G
+%OBU$qF3IX;F,1%Z,g+b9^gpW?H)d&9KH)CGkgD4k))c79MlUeDYbP*U#`pGV$>4o4)Gpi6+_`q<[Y\E("^3CfEh!kclMjk'hPWr!
+%0`e]64;;*741)%NEsil5.a"@9T0UUOESs==eH+/'JJ(-8,,4@9+MN0.Q1^g\I7'?8(Db$ML_Hi_1]>"<N>->%_ASXt=0eN<K5'_P
+%J]M"Ns7oC@3`jjZ8;e<EM/bi,-U(LNHd"*kqD-A>:qP&CWN>/$(4@]4O>\j,7V(SO"6,"HOSJ]braK9u"/2QaY?>`,Amh:AW9bP%
+%-/pGM1,KXZc^0UsZ+5"Uq"p?W&HY=KTR?*?k=(udp00QhU,,c6"n5W-0Lk+);/'d'7Bj6h)R+TVIQb)iV.0W7-<,3?1is2lMg/[!
+%CH8.\?5WHrYeQs"Eja>GBndlC#ce9O:8EF5c":Dn'&euUXrAu+_?5!D4'AB4YQ.XBn6=V+$NjL,I\_UOirK[2b_pu].sB?W[R7Vk
+%A.r$iYS[II`DiSdILDT=Ul8mK5j%_^$?[LUk%4ubeN2(L#,og@-,'fr_@H>'g&]2N[A?k=Zfnd%%'"hSAS'VQEu$-cYZD4Z.eb"_
+%=>[?&_^\PP7TR@J(K(dlA.O;p.'Y?$,;!]IAg6\2,W$W-+0-9Z;522d<"(>"Cqk!#%a[t>FA9V3+d0IiTQPf(Ke"IXjeG^B"/;E>
+%UXU]"@pQl^E#VUoC6&IKqSR`l&W.sn,o.g6BO-@Hg<e4IRF14"UEpo.b*p?s7`f^M/Q15o88)*=X(*0p1Ml?-Lu&!5iJr^%9tI9-
+%Ql9X_f'`/1cBTfsnO,?@6e-Ojl79G'kL!.Tm($Uc#gmJM`U44D+.sZS(p>YrUd,Z:>S>?[\u^n7:$HJ.,E.RAWYT.fiW2AJN3(j4
+%%bOTSN1i\hV8MjT!,iPAZ@VgTcbr&/dob/>6WL1^+`8#J'Cs#g_*ZN+=.j-eH),?dZqA]hKOe+0F;)/;,GG_F[gpD*Dke,KSQ,1r
+%S+T6m(P[c3P&(a6TW0qbeun.F$cY<oK;n%_gd&?UE#gQHGpDrnk^!gV"CS)8h$,!+of^T8#bDCQZ4=iO-j!MKp@Tg^=;_j:q<4UE
+%/r;I,Oc1'3KUO3N/4."`?;X4_AG0$%L)LZ-"t]OE&%$-LQQ"9ePGoc6O5ikbhu[':FE@H+9`,s$^pWi=dKc]+JR7TK2Rld^iP2G^
+%?4Fi].<d\rTC(B<#N++DBNKoMT=_./&&2EJfL!*CSU[a\Qp%+eN+!-)esRE8L%E1"B!R3U?@FVH6u>E9FIcgho'X1hna%l?!6#=n
+%D#hVN6j=p,XnCn?D7e9"%YlL9TtiGk$tW2&K2TiWO;AIt!fUe%=0%2Lq[DJaSTaZ2M7D=AA):$AMoiate@K?H-.+J#0X$n=L%Nb"
+%]Uf^<Q3cbXFoc"P8mEpM-CG0o1#+p:c:]ufO)?b\Rp&QHC2huENSs&J-@Rr>K?(k5/[Wl^iN-'17pb?)AJ/#mSK-URDf[=fBR_QY
+%hb8_K:@o*kBn0lfnEL#\I!Q#0J\5`*8W4s0?k,XPH-J`:#<"hR>+>c0UI9ma!,VOK>_,l%eFk/(F^dR2kS>!7i<H6(BXA^WCW[:u
+%^\[G`4e0G'A6?p@Ho+o'A$oF[.?gK9+m7B%7Np"k9_(YE"(d>0/65jQEL8"2GS+\)m^<7uAg<%A+/ROcd,GgXl#,Ege_$Nge:7af
+%gNqPgYZ7t>m+!dY>3aUHDDa+C$/HB?!d^,Hl:1+m6ZnRE.Bk`[/JXW%#aX+qME;DTZg^-$hp[:7;p+p#,-7*K#%p0j!"$+mSY`V_
+%T:U846@,qEjCs1TJJaFp>D!2cKW&f_NJs7,YZS*%AS[,a-X-MG0juidTSHJ%.:^,"A="K.8*ik`^=6hL0ML,9(R<UX,$koLRKXJf
+%94U_M"`XY;+P7[RK&K2j*^a#'_:f"9V1l#PKk3_aQI:i=Gh]6c8kSM((7/,76NY+C/]u1gj)4,A&n*8(\RD=cB$!.AeL2A8-_URj
+%HQaSm.5!J;1]Y$fP_q<gjA`COoNkU2a+>3AC_0ac/7i!m.gq[P'APjCe9E1[LbP=;BU$\pac<X[:T;F1-3I3;MnHj7QTA3cSoYR7
+%Oa8:rPGU.0?d9N&auIE5,DNbk=M+KV>eJip5Fc!oYd.DV-V"P/*YX!-PEo;fVB("0V1goi_g.&Fdc9>pU??N)"\c1p>?VoH.DH5d
+%T*$:>N2W(S%H_o*YPr'[J/i%Jg?6;f<L2IB@a1s3MdT'GQKGS/<%#RG,_4mAYf>Vs#4h$<AhYISSY<fR2S&>P9T)'L\N/)'s/cEZ
+%VInt1l1g-K7WIage<u@/a_1(hor>\=:/)]HD*T3Lm+mMs_P3HS?m;=`bq,KO1PhsPDS?sH@)p*m@sQ>Ci_gBDJSQKU:`Vm=<M@B7
+%%=gml[V/;%e83)r[DSY$T1"7)N4ZFLBNkQCBi4@`/C7F:=:dWTU:Ir_(S<2I%h=FT[r.)%Dq#IRoYSOiaORqs>ol-+I#@&]WY*HJ
+%Ak1H\rB\95Br6@caFL!`VECk1/?2uq4Y>T:=g&KI[T##Y66P5Dg$qj_'hE-f/6C2\bA0!IC^<ZnaIImGQG@2W\%19((32$9QlCQ`
+%`L_7],:rNo8u-256"1n%+?0b&2mSb=>d+/f,7si`:`@XfFum&k[,#P+Zttd1P_1)l6PUs?^^'e#p[EX;DN@8^h<B)"a_?Dn!;iBV
+%Qjq:pLGDDjXT>iCR3W.JZOeaph(5EqO(\M_*!M<ugea7D4lS7u3@nj[ke/mYd?4gi81kGu\t^1JD%DU,j;F9@7mbs5`_KflKq2$l
+%S]!>_"#.imY;j12^]H;&Ajo)tfPY<O\+"Apm4;I:BQ[^;p6Lm"X],H[]@M4NreRqe_7VAbe7MTTbPS\,"S$u1$'/b4Sfu!;J<?k>
+%3d@8+gd$2@A6C;fXWsrlFuef,+i7T=8C$FBk!leqHHc_,MP4E\^ck%'T0YZ`*l7,hK7:rl,VTI<QufaBhM,"/_gn&%62P2J(0<0>
+%E&2iK2UI;D<LCI'[%tRO`)\$+O+f8OfV3r!`Y$@*k(g=D2+q+0W$k`%F3)LY-(bP^eX)S9^UG]\1<j<picm/A][]Rr,IBe.[O%\Z
+%%H'b0D(T+LLaA[o+4`jf/qTp10C*I;@nQ><P\;fSL'4;jkD=aif>+Z!1t@fl:P9c4=JG<Xd+n^e+tMHb+@)<Q^7<oKCS!#IH1N\V
+%`BR-kf!J,Nf/Z.%W"o@ZEQ%IjPOUt&#opOA9273[`Ig=8I2Np:N#hYTqNZkCgfMrFQ,&$jZYPt+=>(f*>G2u#QOD@'Y-CTS1\s8%
+%X(VIqk'l[(N.09,f84>\h5:b>_5=kg/"8JM'>4PopZ/W9G@#^bJ3@E6I5r/6f5QgGk'3rr3-#m$4PZ.k3L5Kt,Lj(EJ#U$;KU7/i
+%;_ii<eem\1F/r,_&RjJ`_/nq2Q;tpfJ?E=2Og?@mkYjsh()J6%qebQ,CGLSk$@.jinh-L.N0\mcihY.WAt#?42%hlm.B-6f9WJ)%
+%TURqo=GnJV-RBMe3^4OB:SrM<M%b$%j@.IJ3\,GH]Jufo?j)ft#5J`Ff$](LP1&::!)[#I[=QuYPPLV?5te)s&8@X=;6uo<:V#0t
+%?iio=B!T^H^tj+L-H(a5ZP7r6Dr)oZ;6(S#+G.5%)U:/k5Y`Sr0K#YA^/1d^hTo)bl0UoN'@[UUP=m4DiBsZM0Bqr17>g0HaqR5q
+%(g/D&C>h]8Q;Ek_)"fX/Tp&`i,1O1p/Kl.B.&Eb^/"%Ke(q2kqXN=Bna9Oe)Vd"gNh6gRo1m"Qp!<&(,'?Zj.Rg^T4AIVnaA0\jr
+%:a2dc^P>6Ukc^Lo!C2iAZp$&^LigWNGoq`p72f9?V$L1Y^<Ch:/-VfE7E>b',kWYT3Z^mOlRPT*0n(_T2iD%A3,>TP4[XKZWX@ee
+%G#>maY:JDL*d%"Z"O7uZeWukYf+#f9qPAdEB9sAcCboQu%lb<CS@h"#H8/GT]&^:VO?SLQB9W:ZFq+p>%M19.0(_sM_"p=8.4X-K
+%Mopm_V%L\!TP&-PbpjoiIOYHTbRPFG&<34'<i6;'8k,\h(^W"8+#=Oe$83Y9QU'"OeY8#EPd)io.m#?R%-`LdGQeWd>e=J-pVI8@
+%8@t2&#,Apl)eV*s5,g(i/JURI[`Bg(MsG=ol;EB3e\@a*e7L>\/oKf@6Zrp(%k0c/!#e8\mfir_1TKZ5[t=dR]M`0H`"#\QQXYE<
+%N@L(/Z_o5uX_$T1W>PjMQks@fAcZ[]^`-A(>cYOB9>d,=RMls&YS#NM(hcs$K>17Iqui<WT0P.dk2ZpgCpKSDZq07$EGDA_7ZGAf
+%I5^3m>D1)S9]dn$E[_mncJW/XR[%S<R>[dd99Mm_PM"JI<7@OmLbWQbp]eE0V.%q$(cD<p?Y;XKXjA8_1Q9WEXj',RAc3dP"fUpq
+%/C6Q17MN\)iTI'JfTa_Wot#N@2-.o+W3RlUK7e1.JD5+&bh>+1[N1S=oke^.Zjf@XeXSOgP_#)OD=/9AD9tp0K--;XO(i8e92uK7
+%L*Xf($_C.Kf")IUoijLlc"JMg5[-[EZ9>)<k,+itU1ukF</Lr[Z:IT[*<6DP"at-N8A74AA[,dU0=<:9#b(o#bmL[,mn;,,88>ba
+%U"B!(3(0j9q[I!s"cC0O\7IcW!#/;H2<@0Kk/jS9WX#sY5C&gDQZ?_+G9tbuJr%9%-]<Cc`)N<\S%8s-Pb\Jo(,BsA.\T!fFLV0N
+%^R_&SW%1RWng;iDoQ&s^G,DR7&PhFOUtuN^R_hLlJXA-q8URO;=X7!'"`V(Nemub!7QNsG$glZ*nL7&2NXM^a>@*?t@%oSen"soH
+%q^pMOA-o*Uha`Sjc7JMP;8E-h*,jJ'G83S8=_.R?8`JpYl\]a+8;)4r.!QcpJsH7`aDVC`+b(Fn%]$hp99*T]WE5PBJpC;'_.6.6
+%qmXarmIZ`O:E8Oei7^J!31C,s)(<U%Vt9AgFso+CD>"@KL)e)^+\33^KZFNP`dYs7m-nhPrbIKb4-T0Whqq]=nb2PMc/nV*:JXF'
+%"P_+Lq!@b4d_C#Ss7F:&s5g_VYBi!srR1]:jI\X5j^3K2iqGAb0D^1tr+d)I_oXRHGgkFBlcIKQIeE!;s4]"$0B29rLQc(m2ZD=C
+%S\9?ms6NO1q6/Cgmf)79n%[t6qrP#!DpQ/TrR$Nf]tOC0mAl02o8B7!Va$gRrVW/.="eJFY5-t)F*[cIo&ff8G.2tL_E7Yfo/HE'
+%_"nmsYWa['lFZ*MnuK6</md">r?&,[`Ah`g?GCp]jrku&`Yd([];,/dm.J>9D_M+eD4g1`mi)[tY&7`'45IV4VX(]mIlMq!p,DjE
+%h#e#=(sTA(GDGbcc/kGdDuOkSlMe%nhgE6^Ddu=^3rY%]IJSkmg["[[e[IK@0AgU:o")KJD]-:!H$amenLq@ahgTWl^5]P1]\_IF
+%Qe-"7ItJORGP5qSDn`op4aV6khp]0N>X.`ik5O4Y'HXq2n%Z2Y[Z)`g];>Q,U%J9O]062^o&Z@KCY!h#h,aBUh7Yn)D_<[BqTZ_-
+%bB=)@rpJQO0CKjrYQ"4<?bQ=0S$OdH2TA$Grl)ZDq"O*t2toN+2dcOH`VH!1hn6XOfg#?+c.Wd+M8s^N"Rj"]IefIkY>7>H)GEB*
+%_=[Ef=]Z_QrVksMp!I=(QH?LrMrt>NR*ml^F0q<p(=S??8foX^UW)l>Vr25C]s%DW/LIcj2Y,?>/Z&t\9`K/,p@[apZg1u5HM^Y=
+%pnKM<LKPO&XnR8XQGu:7-U+`g(s'GRo_QhUhd$*Hnr3SI"0jKHG55"Hp`I6LqXqgU)fNVaieI@1Nar$=*/s8)mJR^gnm3&Q,Nn"H
+%SdP>b?6+,<?2sdH&+17k?C\cYFa!Y6[&2^WTDV:Zj3?]YRhlU^1#L1AEUT2Vm@(5"gK=Bo>>D)A1S*DZT)Rp0cA1d\rVufb#5c:Z
+%Y1NXMro*7uB?+*>#LMMFIs#ZLig&AlVrp"BDJoL=]5Q96P!?KPa5,Vje(`W\cd"2X3'Y$)BH'6$h<jdYE:aV:kJ)LnF+&',!,'8?
+%`jF@dn[P1J>eb`/p4.."CKPYe59@<5-ZgeUC(O0u9Pi'KnEC'(5.X,[lLN1AcRr:;i=G!KIk4I;NSR?*51aGVQZ'UK\p1QH`E8`#
+%j`pc?c+u,)iO1H@lKD!pfCYf^FkuM/4anM7+*D\'lh;IZX`Q]gnh'ap`U.#^MK`n+X7UmZnHHW+h:\6LrUR3*NXpO:\#$c#@.k-0
+%N?86HEuMK=Ed32:G;FYs,"s>#V>l=dA2Z6""(3n!^A-I%X"V1IH[55=[aGOI4?UaSDJm5fk2t4=?gkUQ2Ja1J`4,:L6V/>69>8&d
+%FgdRF_jVTkrsc<"A_=oXh4D<mI![O=c9L&SFu?l.3%akL\<&V#7Xs]W[$CUiM-iUhfgVOq2>!T[$,>2M?Mn>!`\tCmL^`'gDDs?D
+%qZlkEr8[$B:k[^jo"6#"M78^@r7+iNrZ<>FGU$_oJb"UUJu8D>o8"LahJMB%GfkZJOV;c=%rV-hps%pdDdT'+?X-lA^\Q^=[p+5?
+%*dHSF7;4]#hgWqas*c*3B"%_'#35etG9]1^?Wm@,q);s<f,(X)\9N.9rW&_n=5+S5I^aO<A<._]^MRI_qq^+S[3("]hT0#M%1)\Q
+%Sr2\6X8h!Ys6.0Vk@P0^X*=79__E`$@\H!]WS>K;G`nf1Oh'A!/@YfVg'd<Os51rTJ,28,\W(T<<0+ViIU\%^jc?$>?XBirhV[W&
+%q=WjM=8.&L/h[-9,JFuYn(kCZO+,D<^'C6WJ+in<4J\P9n*Jf`S#[&&XsmYig\j&i+,Jg.3kF>c^A")kH!\*cIql1VgHE6VX)dC<
+%]=A^kq=@[Sf,&'=6%7+-hDsKVkARQ\^*@a1E-tr0jITQKH"Sre?XCIWr7enp\\2AmbXR=sS_hgihjiNZO$n<eh:_NA3@rbC*ToAH
+%d(!.Sg;k,<ZgT9HrMto_fh]%5[\Blg`R<D[h!\GcO'u&BLr/]hZRVMaA-kFc(rTIPr^ef"[Z/!C@1XA[KW"\scSlIS3`_ml]ZhDc
+%nK!/l)gsW9o&OZK]RRLXM"?To=.ZG\D0Yg4%trTZp4!D\@OjP'#_Z:tf#IoHfSFfm"@Bcq,ri]MfSFnCa\U_n0&3?QH5i:L*t/G6
+%O$JN'C:"p7]:XJp[rPH>Em-HtpRcaGilH?:"MU_WCu-PAp4k`uRgEAL@e7;_eq1g0$9p*$i;neM>N(9^8e$W:FT%'/@X]h+s/GUI
+%4hnOQp$3'<J<(H?Nf7[:pcJ:;n8EeM9Ks&_bLq\1m"&\-O5H97\UT+HX81jHVW(/2GeB]0(R0oTCh"#\\=b`8'up^IGX3?t6!`:&
+%XEo7XW;C9R>/P^#TDk5oo;FkoYG^FR['f46,<E^HY,@9'`.rY%D&q3sR*bIpYQ9dl:&d1CA%AUHDIcq2-fk5uOLgFRYdG.MO_OVF
+%:WNc9drTkUFgF[jYlU;bLI!WmM>o]J';,1%Fsm6<54AO-s520"5FcP"E&6eMaXfic^]/.n3jqFBoDg'T^D14:".4%6InO$+gDIqm
+%$0U`qG%AHM1?"24?q`P(fAbPCZT#Y0s5(?"IX1JVjn3rmo:LD!XQ,oqV#RL?e=cbr9@c7V@q[[AE#?<=,IYr"q#9G8=5VlI?GE$p
+%J2;V6+oL<d7OfBBR;ut&a5SO>kaRN[m,b!,2#OVi>jjE@n`_+]NFYpM3>HIRGLQX@HrJ2.PL'!VmH'gUXtJRIjf2LBEW4Qn87FKA
+%[P7dIkYBa]:@72Tme=<,L?-ujDC9RKVsF'uj/mDd4Ru3.-DNaN)0L;0kVa+I*Y\tYj5o/O?N'EEg%SikAM-4H7&BjuX[b6\id>s5
+%2tFO2qL"6(rd]4MV\?>rbtKk8i'-&F`]cj@pGAqQ">,Z,3f[([+*fid.-8Q*9)56aa>$;tNHI3M.C[\$:HV8FS'/"MIf'!$"jr8#
+%@2quaS!m-m"T&,WeZ52.56's9`PqN5rFB5^hVYEX^YXA;\'(7B(N2LP]m0AKc0a3WWe9fYZ]/;UG!A,;innS]lX0hZ=O?PN+<:oe
+%UOdMDOPYnHoUF%<P1OVY4FgQ%]dP]RYPKn77&_aWnUW;R]Q7`acfN^3#>bu?N=<c%qa79K4j<&:.4Y<Tk2N-=nD.mKDJBI^-L]^D
+%YP[AZ`C$YQCkN)hDO5R3AXVrK2qNF%Iit,<]jC0l2Z;PrBSeW&TK><N4.$9+?TSJW2?pSDo1,bc?[R3?hR2k-UUT@6osUf;7D(5;
+%H=<_pdG&^6[N)t4HQ2A9D0bTf3I4n)No$(s\)gHoc2BQZX*8[a]j$.[B@2(<D;VP'kd?j-S&qQ((`c),n[J9(^u9l>o?Vpd[OYbs
+%n@3:G9RH^ZO6aWRUlF.Qqu&^srR*:GD%,_QhoeNO[JSA,c'oZn-_I\k9Z_eAL\oW`Rm3KMY.cV4aN<9a;8j3op9k$Ga&N!(jKh&o
+%'n7Iu\>Q.^De7LlOG^f<Y!4fZs!)j52R;kFqNu-c8Uf)L[R!Xbpm,dZC-'ecHm!@\<k<aUQ2(`"AN'7.IMA#%CFAJ^#MP3&1+,Ra
+%R31qd4/Q_1_fj\*F*Mm?O%FHMaSgBLU@TJ@rqc<,-D;Uo3taL-Ilc/i(G@_SY<Ku$r6+tpA8\6`)g-8#lYB\?k.:QdUFl#rgCd`(
+%2'-.)HrTF9fsoZ>C"Ie'c.U:0muBN(5MhcNN4Pc)FL6[\G0kC>?6AR-c"T#,VB+0pdIjEi6!NUMd1/4k5t="MdnB0Om%A]DhG^%r
+%[Z(UK]6j"[HFMAt^[Lmp]??NO8/=j9,Q66^hAsKm(D"TEr4.km)$Kg5M^NiQ2A2T@H3-"g$2E!(gTTJJ]!u'@Va&V3%/8f5kuJio
+%61WRZl\jZW?MsQP^(8edeh&V<I!p?_FY=HtfgaC<V6b@NnE/m4mVdbAS%?1@4PnDZE28!Z6&0HUJ%9q!*pI$\6Md$EJ3;r@)M3))
+%h:(oemFh<)ZWFoV\_KfSS@/-*\+9>a9Sfqmq'#%Hp@Ns-?JcdOp"QN3o\K,Jqn\t1@9$G'GW14rq<%UE5@)"7Ik]J5?gu+j(t+t8
+%5;mP%^6SKjIU^g?Y(NhrGOZM4_Z.74m(`kmRB=^1Omlcu6[1<D_rE]9KD^LCc8Lk^Gk<&+lJBE#78&,OhZuC_*M#[*NA:>R>.XU@
+%eF\aY.6`24rR9.0[r^JgqVk#K0A_1gs(iWQn9DUb<dOa5["[7,rsqD"Ch=4`TIjbeprbP'NMFa?[$a+*S*=F?ChuUuqE_3[NMNcW
+%5Xs3l7WUDTN^hLFBNc@od:bQZ9h1uCBJ^`G1i:1iHSh0LBJ^_Cepe$:irdS'HecTHSV7oFRsmcBrC.3kA&A3,;J/56K_tYmp!(*l
+%dsF=48)glb&dJ:-e]l?eqeF%Cc\@<HY?X*^UJ83RK[FT5rV]_%^SX.>Fk?WWX&irss7Q2ELi0pi42617rBG/=0rr4fGW^GIjt"-A
+%,P)U.k#U*o,P,M2mN-i%C]Vj@['^q_s8S).-$u>N0Rn*r`CEgLHRi5)a1C"hDT""#T'L94Wo2g5Bj,Fi#mP_P,Dq4oj@m7fB"6.[
+%K1fuu@mk[W*[,PF<nDa="1ltA]7YB6Q147Vfh>TI6$:&Zd#**=($dOgCE$L:W*p](//Wk@.u!dRC0;XHP(Gjgc[Yugk5+'<>09>&
+%N;\3da7Y!t?i/YCC+LH\p\LYqRl<9f,6i@E?L(DQE,Ve9qT"R']Dl\cbKG%0#/?^ll;+>_^Ce0K.Fm@c1@&q`lh;IZX`XNHe_lL,
+%fgai(D2mOHce&F:mGh-RR@EFI:YAd[re.1c/$JFUT!GJ?rNT/OYmAqp16]2*M0mD1J%4gK`TR9jLsRBtmmp9\-%_;,=(;nIoqQ1m
+%4uR<!Xi.V2I\)_#3$gfMVj,$M^H:a'h3WW!ft7%E?+p8GDW-*04a?pcYl,n$iVQEhefL$'k6?.grYtUMl2N^=09^3^O;QE@:B&:"
+%Gd'>Hk-+j;L'BCu(EJ>75+n\@LQ.c":H]iT)p/'c\N^,pF<d*n;_mi<2fbi=SV$kR7)!=?F9;HK)1',sT&YfE\k`Z_D=qfFFFdU;
+%LH<%0jVpdSIHiQEhM$*>6L2*Yf'ra*QJXt0V#T]Qm/$D,mt#*>[r8Irs)!\Wo-'^&2eQK7jjb80R^d]oIZSn$S8?-=I&G;OUK-S@
+%l!KH4l$`#rBD'36Ch+drmA4/3pX4EG9E%;kQ@;5%n1X`srpAh77TT8Y1AF$rmt!Hc5Q'oU]n:;iP1R\d>!>sT_%BK<"<?/309mUd
+%c1^o_Q5B-oY?l'U*p1Z=LRjA#iu<Ft2'X/LEb%7[Iq$ff]TrI<;KQG*K/fOfaT&ubH26(HZ`Ulta,2)hT7?R@?i@$L?iKZi9<10A
+%U.g_'It)P<a$(^0J2e;6Y:om$H+j-2c[Pnr[_`"9`V3G@h7W$RI=(\<`U!Ql6iYB$r2TeC?bZF(D?#+bn<nWhU/*0)=n]8qs/5Pi
+%M7)E.s8$O9'E.%irdXjLrZD0n7GjZ3PM_r/TE"4P?;a/jp=X.s;gF[-S5*7-oO"_k>]oStH<\j_83B%N0qOKN5AR55ObK/8$fa&3
+%@O>N1k,4SASnkZ]b)sX<=e4i"6GiN!(29Fc\$pMN+8fu(eg3o%FYO+!Z'oHlI^S7*r`JcG^T>b%%?Z-Vl@7qDBqY)IW;LAu5Y,#r
+%/L>[Z1mT+P(nR#Rb/q2;2W`N)c-u;9pQ9H.q\QrT,jZO"26bFlb>VeWI9(B\IVGH.JnloTI8t%5#$`[Br0WB8-N!_IYGm*(s3/*J
+%Zfk'?<M4Mfp[l-0cU,_WI7SK^(nOGRdM-pZP:Xo8T1un)/b-buS$$>e6`?99[^G@&$B@1`T/iM[J)6\JDMh#7.eOP>RI*3R;fD]^
+%r,&'<l?F,WB=1JH"0U140_d>9""o<N4n*@+,l0]n:eC$NiWT7c4u"A&+uAO4m;;6]#qF.tY0oT$isEGW\8P]',/Se$ZA^>*YP)TJ
+%b7Lq@I$!`>V;`&%>_lD4gqGHHhI$mY7fs4Li3KZn+to?WI?iq!En'NSOQQgO%:3)@c]?:E?\jlOr`CXV(8Bp))7/alP%E\IBh/OT
+%F0T+jHq[7pdmVB+XprlEKsG^qTuE(h'Tu.-haHR:3F=?(l_4j\D%l"n/\ZAR9&IiSXnH$d*T-*ImG#$00>3okO`0LR:4@,uG?.D(
+%ZA*#69gNr:ErDg);V'LTo2R-#Y:C7:B>12d/!312@C(kDaBce9;6sP[I2BH<)lgB9VPl`1>[LiEM4.tJH;Znu^KPUU]$T']Zj0NP
+%p!/S^l#EPs]:7D8o<bH?G'WQCPZl^&&\Zl?)g?RRq?ZqgipWJF5$_$@[60XaH<.qJA`H7NXaYK[*q0-ZYIKeTF?c+7.")V$.EW!a
+%f!jt1MQ8@VR3pdb,RQDeYklil9K]X,Uos2:Ph`n:ol]Km]_3l:XS6T3ae\n#;judh8c=b7htQBV;4jc;[h\pDJ"F;83DH(G?H#73
+%-o]5smuk]XQ=:YB^H-WIas8Pj06c(P^"`5h"C6U3cZe9)rZU+_G@-ZMZ`;4JmOQe:C#U4A^/o_TqRo^KhmUtBM_"Y6o!'NM^M5R]
+%Td7+hr^,"(qT$)$rr3EbeA$+4Z1pg>?0/_\IB#UC=a!`5A9N?^A'b#f>K#]Rhj#T1jAX&=oW95$(/u`UX1A[+s+7CF(:qV/YC.M$
+%Y<$I<<"1lmI;eEcom_J-df)k%.`'r3b/@r=(HF3*EDEZuhQL+hDNU*OSitt<.>N&(dIB5lVbKr^QggWZ-9IULjBMUgV^jV"rSFS;
+%n\"K?8CPL%kVn7qIF4bN7ZVZ<D+!'8TAE8.5b7]56iYIt?-W<`R;s'O^W:/l,0X?CO_G,D?8=[,FL`)G:*KB3,__s'ZhLYr!S?3N
+%q'j%k\-LFUVlFb>F<0rQ;HIs,iXW?P.ot3sc2!<!9S@eMEsHaSNK;krn*c3K+8q:eaIV]WG>07Ec;0YU#-ncL^&!b)oErs\@a8,;
+%NZ?L&O+o02=4:C,W7?@$.qtljX/EhtK^Pp5[MJP@o&E+IcnUfp`I#0,EpnpU)IC;[_T'Y]efWEX<;?e\g*3jL8lb.<7OG`S,l1W)
+%U>f9K[rugm?d^Bep-DWmYFiI;H@\"ieM#d-^3`PT_Sf&[(Y2/10:L0U\%2mlnQZeNmsa$[O2AA5-H/tkOG0dnXo2h\MfL8lWF$`p
+%\k4'@j0b_e$eko.J!T:uA'RN?488WG\175VN0A.^9M\G_bopc8EdpJfGLB?/T'&2ag5;'A2e8O>Cp'Mt]i4%("RJiDnP*r@hGMk%
+%pfaLum5^a[-Q6AWaeA5=jKuE_?(Wg]s1<L_6$;3e$ElbqI4,M<P$Qirec)$'rPgeA\P?.S.$OR.TSl:"6"Sl5]%'tt3#erRd/6=1
+%pLG*7HSq-8ids[j?KmDgkmL+1TWca0.(d"Hf2L>tQ>Efc71m+[&m<it=)`JNQL&3nY&?JR[mQ;D]MGiBEQ.4^^e0#X;r3ppM&oE?
+%)H38GrirH[d&p&>k-ahG?stbD+NP!D(*5V;<SIu]#14L9<`brlm6B)=Pk.=JUYdKTZ$p]e+4R>Q"P+tK<gtIb]Ace$F-*mr$<XPg
+%Ac9'p'"SOcBMBbj:\DPc):$.mr@n+\qcI[\rgqX+1Nn-ZK=:(h+o%VW6$@.68sFJVN@H9cS+nb5AV,K`mrgl8Hp26^T7=:"k0s6;
+%8)-%2o2/6&(`ZlpWX%i9<N=n1oSu(9$VPUBZ;[4).=HPsRe2bQ`BtOqH."46GI?(JFRJ5\mG_Bt!St10N,fcHORG7C3ZQqhD+fAu
+%7GQCem7M`arS8PFNt1f[2XqK)@AGtaB!sXfq;1@;Ib1l_DN7]lWU.N#j/=V=<tXQ^me9%ED5/U(GZ2\ZMSA;`rR'SLl+K]jdncRb
+%JJ;Y#)nkt#K@%)'&M9k1QC3(]"k$k\SoHr\>o7:Ri\W^boe8gTW8pP%QERiu^WWJ2^%,BUVhhSWI:R2Gf!,1/r&on7U>f/)-7<4\
+%PBg8PHlrfNFjD[5?;F)VG=\\/V5b(??(G+FJ1a7CnTgiF^5B5TkTKHbpUdp'HW<#9$Gh.eG:%Sg05X7cj1@q<-\XL6(PPX'TGJd8
+%Zej"GT?k@q-!Kco</u"a1Mn-rLgB5;Ed#F$pQd?I;AVZAgd(S=9tIQ9ao/\EA?andoHLAYP%=sra;d8a\laA/Zs::39n[gg:EaoK
+%Njg`W-IdS4U'Y&4W%UJU'@Ca_a!/84Hm-qfF^\W/;I&:?ENgRsH.(Rq?8,0A"n)Ljk"/pB$aF0eGB(db*p]<%n6:NWs/+'+I8ib&
+%@teLZ$?CXJR`o5SPLnVRM9i8b+e>>:X>R^8b2V]U7'RQ%O-9piZ=>'6a>,H^$FI<'aP-:@[GQg<2aV[ZO1dXjZt1#e\0t^g\B/\]
+%(i!$hg#[fIWj.VKKV=l<HGuh06H"-9!li3r\Uce9&E[Hj/PdD]+KF1u+-n;n;n_5>8=Ak-5$6D!T<$[K`5M,^Xf6Ws47a^6,/(H[
+%[(aQZ4l44kH;*B)jqC?FTfdl'qaksDQFW+SgaDH6[J<5Gm3c0m(9;Jl^.A,!+E%n);f^7@a`#UKGZdGRKm6s,9dk<@$ZiTX9''9C
+%[V)%:p@cf'546%u<LCJ6n._$_S%QI7rQcg1=*65K>k46&@I?$6q251F)0@UiEW(sj.$;s>S_"P#\tBB\bR@SF9d+Mt:!\SF@KLbI
+%)HFKLk[_BK73Tfms(?N'SZ=]DGeUfd\BW)jnD3_BjC%&d"]';62\2s(_\:lKni!GAM)9.kCI>G-j!)/sB&/2`I\3ZuRhIF.i1"KW
+%Ung(RA7/8OfR>,-2sH;+FYj8);7Yfjg1@P4&GNYagPt$jlGl?3I=A\_f^'@AB;(qI?CV.r+87^OqkUuMH6L[hP+BC.";9<s=-?A5
+%1OUhL$%Ps07o?L&;7_i09hEbl`/1t7cOKo-*(G8$cZRB@DS&`(o00S<hH%hLa1co2=1R$26+]m.RbiGSK3RSO%3G41Q=he-@dmXY
+%:XGoYR6I%Hf&eJP/ihWaH6EK4TOE1*-U1(hT%NE.5K*ZC"/&.OKJ@dX7s'ID0P9Lu@YP=pPPUQs33P)jrpQ5+ITqr4i`o9H\A252
+%&lYQ%gr_tlcmp<(h)21T+dh!:f-Q8/8kP_e@T(YT&IDs5,G#6)cfF_SqHD;oaDBP7h^"*JRFEb\4k%'>8T*3Hr]!sq6>dp-"2^=o
+%Du7\'fs05CqRqIB/"Rh<4eJdA/'-2`:PBW>Np[kC7HEKKigY""aGW+9(YO!Q?2R"bU5S=cLd0)1b!\,^]GH!Fhbcn(4==IJ.E_k"
+%p;og#!_n)YW\p0fG=n!l+Ps-t^eWnS?J(VpKVph(EOu$aNO%HK<P@q9`%&,!!Dc/r?*oOg1H:<h)Tm?l0.e.NUlEPZ#U(6PY9q`r
+%m?D0_Zr+nfAjAK/UdObD;HHF)#:G@6''m)X5RoNsok9AdY(jNm8-/($i$9npAdX#B[j=2X-)b/6SbPDn>_uu07-Rl^HM3n$"3qm#
+%<Sg7YHF_,=-kcb>374m2$YRABFY`fq.B"Ok]EE;tii$Z#G$u&,@Nnl_(@PKDkF+4];,g3-`D&q=m;8hV#`C`)4I`IoFY<MG/IoKH
+%6%1@GEPHLo)Bu%ZV]^E4&dWcc%HnHui`N3=ct?OojYasqq;r#6CbU0EOqYuI]eHA:D/P^5gJl*:Vesf5@miXOi7Pn=<Q2*04h_X(
+%$R17K1>GA4P+o53MT+g]hj"P,Y!^efA(EAR:k8"-%Iqg5l8'N$M<_=d:G+u^QITls:lN"?W\k^:Y2o2j^<R%N9U"io2OaVC?\?J"
+%Q-ZqDN(O/-eGWS$`CeD?k,)u`&O6su][-5P7-\HYc-,6EoUa^dWZ2m&C$b<<#pq-8UH5@0ajW7E'H#*kk-KD&%W0)57B1m]@a$-E
+%hBrS?)lI5(@M`Lkdc1tR8n$Z>+GQ_k`HmR>eW4I(`bpC-M5aoCEBWWt84/Z0!'Sl(PtJ>o]j0p"2E3NYlCW;3a?*^2V'D[%LZoQD
+%KcaT8+@PH[Q,Sslm!5A.OndJp4mKdDl-=$$X6m'L2@34%%+%;a9fBi;`(Egn[[Sn%?F&W=n23mAD*'@%nhWfh'ceclbu(!'I5@e"
+%B@(p$Y9qhri8\cs#g$@*:6rWGqn%sN9.sp0;ET[K%Z2NqWd1bZ.bCV3`R-P2_Yu<'eo"ZAmtl^G!9WC2U,G9r**'((6kU7D1dmC?
+%Yi!1K5Y<)!Aq(??Ug$sOs$!($;QG*r]U5sG43RVa@M[,T#:RLNm+9u=O<p)j=G(Dr](;t(@EtS3n+S[m?5M=EMDWN]4\?,]qL&eZ
+%;*6)8@PaZ8HOVZRB`Xc02fo,Nl`bjAog/9L:+Tko3go([*Llo3.:OdqBqN@^J&#oomN6ac;aeNXp5':1Br,d9qH:,gW4ffhNH?2m
+%5sJ$'O?JAW6LF[(`KPNk)IaMiOd\DrUpMG/8.@_%cdbUM`?dm,8FJYWi?Rg'1MLN_I'ReQ&B)@Si0Am2cslHhH-fhQY<fDECjudP
+%./WJ*rVL4lqsp)g\p\W)ch=[us763as7MFkqu8\tTq/@]*tH4N8J;=OStpF_!6d-SLI'/Fl[qH7dcEi(Aj?1`li'*_9BYa06^Vt4
+%%K\@nBat-&8J;?E`iO^r!QX9eK:l`L_#qJ_Z8ea,5SKIF+@m/)E>YV\h)bUmAkbB.MM<H!#"Ff[%t^RMM$!`l[^c2W.:(`H?rGdu
+%5sQm``'MI$C#Yi=2#6tjFIFc)+o&Ei?$:`o=#M3,5bDRe%KSdc$O>V>Uk(mpC=9sdZ"ik&!GF?l``)DBZD%hI*4b2Z$-B.uE]*ka
+%/bT_7Okb0As2X-b\X?i4\+sgYYjD>HF7%H2jkDj`ZH5<NKOs0j%R[Qo'Dm#4OWT6iP9pdTZsi6kNbXan%`5Vn'8Iac\;>jBD;<!:
+%kVbG8#N=EViu`ejP<8[RN19(;:Ihs`9(@"nRlu3r7_7Ofho!%I59,?"PO3Arh@1FlabVm&arZ4]PFjo:onH%"!;@g5H4]XA2V(1H
+%2qXN'T\m\.4:(s69fs*j#?19q$lh3G(^a$,3!]a:"$$Vn#KqT-$b-!DO%7+(=?ccr-_34&&LU9mJr,[o4pVlNCOHaHNgi!:)95Gk
+%KT5"-%RJ-,!sdfF\;A*7Emhll(ccKn0U/(Ya$D[FfiJD%jeR`g@ccZ%4:j*"V@UJc@=SS*k+mid0QVDm4<6;7S*\8,\``Zi++Tl6
+%3r<IS*8IFsT]beq*.XY;DpZrFFD.CJM.)R^h\h0O8Y<][YH)iQr'PtoS,S&SO9CB'aeU88aS)9Ld)lk#f0Kd,!+#mHaoMK(d>&6`
+%fKl:h"50)Zn8t$<2_bBfM4sf3W1C<d:p?L<rD:"pI!l"QDP"WK5jm^^6U5kbUE'?H1\9_m^cS(F"/'itJPQO.a^cFq^Vg%5!.ZG'
+%T7\82E6]I(_@u[o5qoql#O)MQ-i\,s*"Oc`!s!Vp`$(4)]VSC/jWQfA"QnYb%Y3\uc#F:S:RX6GSgQ*0"ON>Z%YEo$Z@3?U%o"#D
+%duu*g!pX2u*!"NqD7:&-KD;Er4W30DO?I=;&C@#UE!U:+B'5#d^%l%H^jGV_LVWY[KnBAQ@fIJPi=da>+:t/%E<(qnB&We5+-+g6
+%TmUh%4;l@u]ljCG:RX6KcmMO-!9o[O%Kc=V>Our=+(jL4@%X"G&\&@HHoenNYK5/nIcaRS3lDQ#SHD-+n>[N0o95RhSDSGZo7&aq
+%bQ%#1ooCW-5Gs`j6m$Vn:41K.Y@!m6roWS%Mj#Y<JGhq:lLY!>rVuo@s4@8eJ*[,Zp?'W=mI_RX^3OjHIIZ']gFp:S4o>6<G4E9E
+%\C'%;1#7A[manZ!?C^r]k4[PJDXNV:.>J=QegW3,UF>F(]u64I.t.<DKdJf18KC#H0)YpCaL=0mE`pJQ/2%62+(@m,0M]]j+u.,F
+%8^)`g&UFr:Og'WK6c.b!5=&qA$jSVN,KJ+,:?2LD_C-32J(lW9W^73bc<j0GR<6t/io"qbI;?A-(I,>YjAqmgL0fg=4-kfJC>DlJ
+%T_ieG<bd+S`&gRXQU*<'1_eUBUPLGcPXCqfdHa%a0:Lfs8.IY8#(hNd=^6$f[rR7eOAT3XV4`W,4k_$FTQUJ]e&<WU,a/&9#6!+3
+%Yo!5(jZ2f5%BB-rnfj8S2mH-"V^nf=TX3jZI:8S-NM%uN5e]*<O!#QIkV_EoaIf2_.Fnre9OoV<\ETT[&]CD/Whu^#MAZYLjOfL2
+%&@r(?+M`a,11>@QXZfnFCK`7cAOP23Qg!"O9_BSBE`>p;Frk`X<A6^jq$K0d<Gju47LLG2J\=m\o[87$N2$]<-M&.YWWX,T$J\jq
+%7:r7^b-g>V"ZjMZ46!K0)N\]F9\'1m+VNk0Lg%\-=CDsC]88UKKp@9-?-#j*;g-l8l7a/hPAu'a+E:jT#CS,V6t8l@Dr<8/0^,Yn
+%AIu.D%*1MdUP"nZ;A5]0Z<;n7KJP2VOX8BZ-Manj-s%HBRkl84Wf0X2bsm;n?n,;QG0;BNZhoj'PKkAo,_ka*<ne>nbIXR,QVW&R
+%<acC0Xb-HZhD=D#.fF*9m0WG!oZ*E=fVPp-D>?!%ST7ufdiqc8?^hIQa=pror6Rp#^dXur.GZ$O^XZ?A[+I/Ylm>E_gIOslT:ig5
+%hNXC)GD4#F71UYU_V:hh?aDZUW\p4JUr?Qhder:E2MkOoE,%r`<P0G3eKgqm`FnsN;]_L1H4mOY`<f1LW)^cfS*2=KPJ:ErWu$bQ
+%TNlg-3!K=VI!cB!mZ!Bb>c`N*NtP_YjbU\CE]l6VBhg\Jc^o6-HD[bmqQ,agM&VfnE[%]B9+2df"h%,Z%(`%!jcrK[9,;Gu=0[r0
+%7!bS\1Dq#iAI.u)FW0k<*#J2C#8O9O'A2r:MUtfD7Ng<r=-Pp>T&oF)AKXCRI3K@RW<ZIe4Zr)?+[!dBqa$NR^j@b-aQ`(B^k*0D
+%-[(XYSqE\-c]q-moMH:j$@0=.Kl0X!l8hZT,XoImgJh.SNe,#ddtI3!#q&#g9c?/[DJ=1ma#Gq%Bs\KiS#Vk7dQkoO;b8tBN]@AS
+%W"YoP<W#rK<KUBq.J7RQ=^?0tj_>6\<kod0Uip,W-&I&/HG_ATe^XLe"&:D*q9GXi&U:B_%Y)t'lMCj;L?PmO$LjhNWUPF'0ci&]
+%kp8b>C2h`V+\<qu4Y=Hf)JUCg02^PIZ!k#R$+PT+M@q<'KmG]2fdIj`2,BajoSd?moMeaV]lB"d3gFs$?961Z85BhOTQ^?''._+h
+%N8(6/"GQ,<a?(jIK@YJaFbRed>9pK3=BOc7I&h]9dOD)o(9a3,];4<CM@1><jN,$\l4tl_G9W_a[>e!X_:rYbOs4md&IktT+O2lf
+%m*KkIN@Um^"<oHok$q7*9qD6mm"f*!\jS\<rJiX;PTq/MDuN'se-l=NE`MKn<eNmi#s'=go!bGT^sbY1!:Nn,WBTT&E*d%Hm&`Sq
+%TNoPbQ;M@LP!C!Qd:!196+D06$lSP?<QR`\#'6RZI4>lRMt/]^OOGIW3%)"p!\_j(6@*I:o\7*8f_0LjBU,.=)^QXN@m[tsn,#qQ
+%a\;0-4:.Oj_Y4Q;n)WW+`!Ns]EgCoM35><Rl6'u[l8@qr9Lp>sG]]Wp]SMt\eN*a5e$1WjF0p.G5]IF5bRq[RM;0'c58:rM3&UJN
+%1S+=MoRSFSjSe$!:BdZ3"ss'GC@U4\mOrO!l?$Q,YiqC!%VZ_-esLP`KbOcK8j[#&1Q`oE)ZQ[5m0\He/chZ8.1.72f`FpE7eW4]
+%lbMJ\U#Iq=59^%rN*hTK)r2^1l);F7f#1,srZ>WgXt*/N.uA^@rkjjOYRY+`jE8ku<r2ku:8!kR-$B=^pFf+,O[dZ%[9KY2[QPKL
+%*^7q2(thuK^c:BBlH=Q%3+EjG$s!9a@m,;=b;2lP:@)s`9AKHhTm9/8^_X*/&E(S]@Xp?@O\F^;oGNS#nFD;$e'5%7':$8[JqJK$
+%37\Gf51j)/Z,iq$nFE,s2^LEi/e2cG0,SCNAcU[tAlo&PSB2PUYG9oQ["C2sHN_/HC]Q6HG)FAg(Uunk@"@h\:P-R[q_>rA8(E%5
+%5^,m,LiE:j[HT6<@Bn;p:M\b1,92`lrMI2=h]ai@bJPO$F2BtWocT2.7r1'nT:qVhk\>`'NX\?`s*jc,@Ri7\#hYiV>$D41$[B2e
+%+><p-mWKeXa`;L)IN$mQ,9$I`cJ]SFA0G4M/I)*tm#mQ+__sp'_;H29oQT"MCk$MIjHobl4a\]1aQt_h!=J:>"MS^7YE+lWM`@jm
+%GH]nD'sfo@OnX16A#Vst6:?.1j*mDa;A%)[?hB:M,+[gQ91&fM)!er?kr1<X-LP=8;Ql?eCp7Mh6?)90aViKU5OVjP\.9F]/0s_>
+%::&aRJef?:1.lXScL,iYRodOXLT/h>-.Xf9:g2(^d4a>*6$LSBEgo5EYn9C2F&E&+&Q'Ft*^k%:3s6@N2'N5+h!PG`hBI`?!nR68
+%(,-p_?b01Sa8)jT"&cnh4Et":"O`^9+sZ["Bntr+?Z.8qRV?L,J3St@5p">\ouRB=B7qP?EGS(4dL3_NYW!SE!1Ns8HY29os0D9:
+%$UHI0aU<mV;P))V@DtW>BDhe&]HIlGf=!mEcb9u0bgZ4_MYHj4<<@e]0+Wbe!YSbU?;Mc0c.=n%Dd2.??16]FXoKE6aQ3UeFt/!U
+%7DOA':V?%N!L1$a!.DhbJt1-YUa:%\B4::R"`g"iJ]G2?Qkj)>&JCl>`96m'"\K:4FIN]Bfuk:P-9\RRH9VY6Q8H1G>JC..b41qS
+%\%n\i^:lO<er<n#7<U>J8f`8/ajJ/%NU6!4$Xo#Yo+KuND+s?drlq=uc0*E??Uo>GE&XB+DL:_X9oQuQi9.ts%o=inUeYYGqY#/.
+%h>l,Z6VY$gh<4/\&-4tDlb12RJ&fFhrA;BZ%*m30"l6rl+'cjkl)@nq.QPKiR"').A7[n/!O^i$\&L*">NI.q5oKkSp\8s#?c&Ae
+%K^KVpG)MRCqpF0XC]+:dO4!Y5bpO@rPO_Xc9-hR*<l75-]5$->jDB*qf9N2M5X2CG@N5OG5Pf$FnhM`ti$da7Ekk^*_$7nZbWt'O
+%rdJr$9-j-%*l*9!"rK/;^GLg*Hcn?Pb#)ukTKA,,]Lfe%2f2&OqK9L[Ql3Q8h+I!_R8qICGi)nB07-L3ICuH$K91YP_AgJaigWX[
+%-W+aJn;Jb\kn_*DiUjQ\A0&T=&EG?hD#7)p`ua:l36B;5p'/RB^\rPeX;MdWSU<]7l5j%,IV/'pVeCk;oq6/B\_eNe"ShrBQ7&5)
+%ZEhZs,P0M\W'sjU;jD<OUBY`ui$K?X97PT4^jVs=VSQ#D1\O)LlDoQpI0iehS(&I;bk2)fT]#1=K)W>dn!noYqt(!cf440"Zn3uP
+%[_O-)g7Q9i4sDPeG:`]5AHbftHg!'Bre"0&(/pOnIG>d=,=@?;!\%.51f`sZO1pW_IoHG+6.(kEUYs`G)7P5K_bMkZ9&6N4N4(TU
+%Nm(r^E/pSq"YK(R>K;A:g;4l_=5t4m)dSA;'m5VuPI*a*niZAVpk[Jk$D6%YT;]&^=@P@G2XX:OPNFdi>B]r"N;26]*ZG,df0NJ!
+%:T2ILW&WefUtE"5b+LYTj)CR+(5H:J$m9u3[RM=JJCU514hs?*@"`fo8oWVqrk6YN&8a"Js-iIq%T'Q(g6Q%q+>bcqJBn;p#N43n
+%fqV9=$sp$Db=#j,Jb-UNV-B!0\)7pf[gfuO$s/"$Q*$/L>@s$]F`=oFK!->f74JJfi?f)),":N>E9KU(dK;\7JV.koAk,T7gB!W=
+%l;OtID+(X=\BLW7;=4^9&,pljbFtm;["Ig#>Dor!/<DO>5^D%GlMBjcTaX5MMZfs)=1`G%NT'gsn$KkG(-,S2d4)-s`bZl#!4."V
+%PF(#pmD]oaoWGEXL=PTtDLcYYc'2gf((n^$>G*>ZT>?H7"uL,XC\nG`XX.$(AC!LZ"gG4B.LMrC3E*dP#,C(3\KN]!^.*?71F.:X
+%6U:/<7L"p/adPNQred>oTOTeQ..3.3EG)FW+)0XbRk);%'YDbB@c2FMgM[Zl&E(-;],5dbNtHR4j[Zq$J3j!o/R<nGApVsl)NHEC
+%oCO_2ks5D7S<^9C\ZcZqH-d,>MUe/C0S4R?TPdkq&+J0s*2$r;r!^.p&-<D]k4$%@aU8g9%16t]g?o$NFP#GZ;;5j)\^:2Wd#2K/
+%d^V>D#JptnU)n>f'%cV7"IoC+a<S;l5*)NTL-=#PfOk=tfh>b^9r;2u?PU<$9L0).j8cd[VEbL`fTsPRReX):El[_tkd+kc)(WHD
+%8\&MaL)8tEccDJ4$U!FNRg&e!6Er]3pfBEIX8/>ON]$iaN%!LFc2*JQULAH))narVG+o)$:d4b(R/\&[,iE)0LR4P##Vq^hVF0"X
+%kpUd?7ehYW90i"h.(EeJhqti4,6fa8@m:['!'3$(bgEj:*I\mr8dMprW\"BR>9pk^?XsI%f\c0V>iBhT[KV94BE\9qTt:A$%#^4S
+%oD[A"7G/mLYrP,6pZnJ47cuef(g"Yt=b?6m<jdhk..\Gem\-$tK9fdP0C*L)%l4j5pQGVh]C?<>+2aV5'DI]=MY'+Y2W)`+?'ZcS
+%SK`?&2`eVY&b51X?6b0[P;.ZJ@bgD0A13OGU]'\)Du9T^7MO=:P`YtR+q!9h\=MuhK#HSf;41oJ'#D$rmM4'04ZG:HK0=Jg)gF&f
+%=@%j8aWBBbKIa)-nN;GKV@E9F#0Z5:IiMBcK&X`?O2H<YP[B4HQ^1]hjNg?nk_)G["Vc2N?s>\<&EJ=0aE*hm7Lk1>e!cnp*+Q6t
+%cc6=/INsd0][LlM5YpQf@c:;?mu2CQ$bBd=r_;@W*B"GF*Ln@M\S[5Ddr7)OTlqp/W<aCffk`m*G4;g4EYEE4V,P2V3%]Hc!)`g*
+%`G8&b//\Kl09'?g?M1uo\`_cFWj2IrOR6j"PBi<&a)oO-#n!R8<'eGo)7Ui0$QoU@c@Ea@p:=Tg>c8Ei(6g'/K1.=AIBWm%2!YEb
+%a9*!Q)ZRI@EDd!Z&m_F>g3Kr.",N1g$AaL\K,9G\p5O)S&02k">X8tkC?p>-mdOd\k<cMfM'iEWl13XTeB#GH@Wpb4WB6H;[s2J?
+%`<KVgRlXX>06hjt=:NmC&<jOV$Um]$JAJ"N0&r?P@i2)eAUMD/S45=;O)@Pu!SbB`ArLkfF/61ilMK[G-:%cGT\%Ma_g+CZ2+C..
+%2C#_<bkm]''1"D<1l,S.&/K0Q#0#-`9c$8&'=<GZM_*<uO66RJ>;lrg!Y"d>)MS<`iTsc):hMZbST$<"6+0=pe^dGc+nl%2L:DOn
+%\AETB@I8@"Kd-lGma',?It?c@WHTu1f/HspqX),5'MpJ731!Q=:#/M$q+;5YTV9V9!,O6ZHQ[rSj>lu3OJa>M^^(u%5Ro!REGX+i
+%CP0.aiLrrSn])c)0+UT]<_OeO=m3`6>]3u9Y@,0nBD%p*\?HC#Utc"3HO]S4T.s')neK:LAROS`PlJ_/_m\SX>Nd`5a95/:WMG)*
+%cQAQY/l9>j&dm9!?_J^3CK\LGb=Eg[?hY;lSi]>W"op(p;MR,2kI$d%NN?@l#.h4P)um;tp8q]57A]BYpTh6n&VN0966e<<c2?@B
+%OmuEUH#9%*F5:;639SRkN/YKGpU52ge/j[G@m!Vc?p<)BhjHWnq&I1#ZGcU%&hN/1nKpNH[#Y5`FXS:Kk*]jcY`N\f(0aORDN=k[
+%Zp'/s_b'Y+"L[MX=8=7)XY#%cN$ue_g[t`Y4Nd?RPnU#t(3W)@k?j8^hI)^d@&cm(,3nOl9gEGk57%$-6LA8>>Cd`lQUMM@j%t%g
+%5@Y&K(-LG\H7]c;Z#1YMq>QFQ0l^!^k4thl]s1=_f)%U&O(JT$a1IY][W@V@2UFgM.:CO&^P9qLIIHdS/V(LDIr&=4M''Ql^Ae[)
+%HfGB89I$YJT;!D8j/&Vj>.>siUTO9g]_)s9CUcak?M;q;RrX.f`.FX0CNmk2Yf[tADt:OnI^T&*/sa.?'E6XmY-ne@CN/DJl]q9U
+%<9\`4.]55..XGgT3U]p^)8aO^Rr6?YCn.&BBK7kYaZ;jOa#j(1#?-9m6gCc`gL]tWL,J/lPq5BRL6FD1'&3/dACq>ga9<W*HYMtu
+%*q*sp:6Z-Vi+OM7BP?,E$hB$(qiWb$W%k#OUS[:!-siYhJ[RJ>:3X[<-Fa,@hl\MI0EQ9;<Z&.[p>0;KhrCAb%Aql75=S]bOk:i8
+%A(:4mq!QJ%i1GYA5=V">&;a`Um12*n&V)ncAMSbP&rn6uf3b?02d,_UZb>,l%=AP\J&7]E+n4?/(J[BiD\kb<NFhj=9>lmD-bL.s
+%]AW[lm_E7g]R_3*p/Lb,p7Y:D$27#E+n)kI*hX!&15!T,R@nuS"EO\6Rlc0I+'m>Y4=j,9./9*i5UY.'jFr#*g1'a)PS4E,1O?lP
+%]Yq/,_"+UmJ-OKroJ+bQh)Rt+*tgPF6qHXQ4_LWnd:X9tQquVpN`K3A?M['q+p.(i9FE4OTJ,r)<e\;Whc(SkT_>Id9OI/K=%us.
+%-eQp`h0]Z,ht65:@be<jomE+0T<_aOaG`.###,nTJ4S*%DpN\SUCFYkkeZR5N3k*T!Z?Pq,^?:I42Lk*g=>XEJFH(.J"s+fRgsAk
+%::]II^Hn5q8,U)26eq6Img=UnEJVZ7Jb2YoE6]DRkoRYW/oE)H8ajRjD/)gb,8-dP:Le2;^U1s_&`C5g3n[.%Y:i\ao!m=q!h$'s
+%Of$f'7)/^MSVmR7$u@'4_"[VX#^^g`,.hAK(l.+(LkkglGe60@_qhCI%@&SO;/6Xf_0fdK/\)F@Sro[R]"j8np2)(fg_!%nhrr=R
+%i5Ta\j;FA*Al]d7BJ(H9L8Dmg4=AYT:]XOD9LFkghWEd3Y`n7)J-]m-5X#P5pX"P^@GI1(\&;""XL9-;+sLCQ9E?EO.I`"Bh#n8t
+%!L_"-'!Tn+\X?erO1tu1gU2#1n#5C8Df@DVQ?puE)n(sHJhoFm<\nd0P2&Wl@R$7-fkgi%D,N[L)mgYOPA8gW,u[.2DICsg9CVg5
+%_FZ#AYmeVW$E'ma?_Z*UZB*Z>p1pquNrSC8b+.PL;],U72,F.A*3*)3A&b7dENPi+kOU%0jCW+u$Ui47`0F]11Xkd76!8/-AJ9E<
+%XR<DEpW0"F607bZ`im%K2QrEh"BQ;U9TW2'0<jUOi7[aB2e5C9$H:7B3j@$gjI9%I5iFSbonY`L2f<tD&3[u'2sOmBO*5@Zg+n(>
+%QN/2B!8?Xll>;CG:ld^Z0RC*=GoIX8SOKhRGias^T^ufTTO03jrhB::dVbH^Ag49bEis>VN$-495Jg1Wgs0-#:>a[MKB+.!pk/VY
+%_Ka/U6ig,4?XWS8#IRLE63u6&P%bHU[WI[:&W(e\qtBboKJ/G%1oUPB<!Ok&n5311P8EFF_:5D#4R_eE#H9o#7c=qtHUdR99Irs*
+%!XAb)>\<gO>a>l*gm6[t\q!GD@LYe-P%Vbse@pOs<Ht&#Cqo1E0c9!!=7or;?>C7bE3S)Lp_=*>^stW/pRO$:"i<gLBgd]V1fG.&
+%PuT.U=[5\K(nN^JpRQDZZq!!8;$%4!(SH9b_%n5&KpsOT,ca6[7VYY)K'fAcFUF([,jq_rS2KG$UTqnZMq4h)c6P)4F@J[7N*o)_
+%]Um=!RYl^%*B_t1rB;oAIW0GfjTef5#lbh27#Y&#TohCl"'0[l6DW9nIdXVGqLrHQEXL=GqeF`Y+Zd&>HMU#_STED3=&pojpU=#5
+%B!`(H0A<X8a#*pg3(,;OC-iAC]DhTj&RF.>#rC(G&'a[*h_U7=EXAu(_\_@K:+8`(TUUJG+![:E6knFl*e2MC3OTWKX#rMnMKDL"
+%C=j0BZt,E^-fa>=b3r)*bc"*0AA]mj/5ZDEmUokqjM5W\GInEjVL`^o$d#Tm."_38HY#7MI;&E<)`[#^1?NVqNu$]BdA9?18-t0d
+%[nuCFaaTHAWb/YY_]r,<A#>fTh%)g[pUl^/j<1)AI\o?].Z)1mcF*b*,G2sX$7In"FdIU_Jnht:)QYbtm+5]&Z\lH>(dMl%B+`gt
+%[M!*'K$c00/QPQ(7^qAI[R+R33F9n8ihS5`^eKHF(D2FF/+#c3aum+%[\No3Ke;_Z_b8_N(4'eUCt9!+G&S\t+2RD9^hXjor,KIO
+%Hh<ZY_@/i7QEjX2a,Q:WO"Y>A`n*6Wd'h&3]9<Ya+9d#6G].qZ8ot&IAS_G+*kWaFh72WC`:%@:]JKC(@JI`6LnQh]l`9BM!P[ui
+%b95a1;<'1JXP$1eUL8M(-D3P5RcqEF>4DPk%Y;nDJDZD"c<$CT-EU2/N:<-@I@[iA5_7U@M8^V6+ANdb%KV'l_:]&.+lIgWhEE(_
+%f.QHX[Zul<D;8XQ.0-1l]Ja?N3].s*k?_0[Vj/AmloB5"mKj&TJDYlp./el#E*eG#<&UBk^iBT8R'p#rA[ed3!?>I?[4MVNDQI4p
+%)L(=qRt(Q]CVRulVe:X2Z$Z_G#K<Je'3%jKF>C>6S=mFMGL/P`-YPXogJ3pN+Pl$FOtk=?P[gA'lZgo&3-h35UI?E;Hik5%s*F>%
+%WD`P+dig%)eD,HsR.HK*#JieeW1sqIIpXn;;ZY'cAd'rp,m/PS*;5i:A(u4jRt.Nq2E6&ai"djeqC$mD"?`u!Cg/$An1Rdnko"7+
+%03pu2YuEeao<T>Ef39juBgX_Zs7'd6'B'P!D8(RM20lpX9heVR2q\.iLTTOf;cPcA4L*pn4jCUr&t8A>ApC@>Pl,0,0^FQfb*7hI
+%@taGgYjtgclZLgEG:0PB6J"D20uLi`e`Y927P@(qiA,<a4l`;QqU(B8VkRO9pfiYId^_%*&(Css!>_-7_f!.U'hYZm*DU"Q]fI2*
+%%Kj,rF2&gqAq^eO&`f3XY$4F5T`>3R*G'cr$"UM1:]:6**Ku6r"`a#Pp/b@+-1V79!=36]*!0dpqZ6=DGiC(8ThjK`IARn'be!+'
+%J1r_,$rl_=dLHGX3Ah&68V4GZMfOFddND^5%-t&j=mZejgLa/\G[HO+T*kp25_9\hD2a7\Nf+%ri)/hBpo%e!efM&i>SE3,fteeR
+%1^1=r"N?t7i-HA301e6m$t1"u/&+W$0Lb1N%;?!p%O?d!n`o2VRd^6INgp6V"\MaUZ"ZtVYRk,K"JBB%%g?@\0R#&0-;6<feHp^a
+%SV0@M[RjR2`V"@-_kCakmRPGkqK%2+@\%:1nsj6M1_]:G2EhH%P.%T;[[1kL8HOg#>#/Ur^;Sq];m.7NOfh$ZR\.A.;#;.Y<!OqB
+%XL7\:ZVeNY[e1!8/J9&3;"7#>),$eAfQo6L1T%R6'hWh7B8\bUD?f)W36*/D>I+/Fkl*"(TK4EPLr2dfeA18`,]IXpo)!IkeNq9)
+%R9%(SpC5`Nl4psuJ+l=ZX(o>FiZH'N!$'o0_,hZ<9EN:!JBO3>9C%5#A9)Jg*!S])o?nV=-l+V='-8CoY09]_q4saL+V6+1[@)WU
+%R0AtW9'n2(nZH3sK.<066]$U1:nn(2]Ygcs>&"6+23mr!Vc$fU:qZjsS.&okf-dDb3d&7I_tcIZZ[qk.W85o:ppVclQX=qd(L6AC
+%H8Uko+2GH+!?A:4X_lm1(lHgHqVCPlH_;/g(3O:kij'-NP24aJ]EP-c5R1.P)8s1El6'[LoNm`J:>T"'"2n(%'h6q5BW4Rg]9Tgi
+%LTt^^(*<^A?\.k1o!&$!H<[D+V"(Dnc:aCR$igo:,@o!#Y*Z(M6Ytk%P.#\V#`i&n;E\QI+t@5AkmG\FS.U9=0*GR(V4-!g-2O)N
+%2K1d>H[Wk_bN=.>XffEoUX<i'NE7!S<gW1qT#Bf%KFa<"W=+kM3(oZS*n%WEM(c2WX:"bV&0>")37V!,gC%QBDpaY'j]XJd#l+&s
+%Ih\%%fMje60"C+o1'jk_WmnTfrR`h:5S1j+f40JpWli5><Si@MCN.g^>G#b*q\6"5h@YK(C9$hFhZWlUkbHKc<hN6m^Y[["+f"^2
+%5Ro$S;$RmRGR[AAEV[2m_4SUK\ekQ\MPDbGVcl.2m=2UdE4=bOU-^.5ruJPi-GWNm,/:169^#J'D\icClb6YNIM[2W)$l$nr"H<$
+%6jjap8:GU-O9jT2ELsOZ#DK/01lrZ`0W?lIP#_5Nba2ErS-G.BJ9/V`?2.qU2'T@AIKCg&@[",K8S0_86%%,C0hGB=!gHnn="A_#
+%B#[.d((I'^<mhi7P%uE:R!]OYD:N?qY_0lC$hoao*paL12Y_3D.B.QL?6)OUZUUd&C1RM]MZ6aU*oI8"C2?U:AC]E1$4RcL3K'"6
+%7@15D$#A,/0VV%ajlHu]@q]*%;T/[e_"<"hg4^en(k^U+^OaVI&Eg09@7bd`*lY_?ql<j=9u%?@0eVu])gL=/at"n1QS;hs/8_/f
+%TOp-MOqQ;=#Y#?--lLLg?<.&L+/E5AN&^<s.@aa26'9=.'62kIlqu<"pn*$9.nQQDW$IYZ(.B$]G%jS`%Na`oAC_e]pn,%PVVE8"
+%iT'6):6)]`:G.9%Zu0_D(9Lg&UBi9OTO7q;Lg9a8G1"%EGu+W_9n9\FL])OXXg8PG)B.g:a]J(6G;sf8H<<54ohfDu/qC<[Z:G/S
+%,#eARc>MaKWrO!;.2jKiFL/'n8,:p+:q9\b-jA+t<k`>%rcGc\Ej=BW-10VRm^:Z]8boAjGQfT<'8p;aEDs5h\2',C7;L(?3.R-m
+%HY(QWZrN4^Esq29kW"f^.@c0gK"PDKW=H5CeZirf"'G"<VfpJ_[2pI);Cj;?jRUG54]"*UlP*$(_Q"Sl$;pjdkh<Ikcp7Bf>I)[Q
+%D%"Q]:BfRSo_fUgQ>JET;Chr>:=r/4cEM[R':-!?jf?0dH)C^Ke,.Zq+4U^^$W2&kf1*5)[5P']?:BUI.D)QlBl^DcFHbVV@r+e.
+%X(Zf'+LOP9b>^"N0rH2$KB3CO`>3nh$7Im%kt3b7'HL&QeSeB$pc0W6L*Qhe>I7:_focCDVN[s01ibFWI'?%&W,7`45Rbt-C+p"1
+%[=rel029J&#H!#*WJ?"uFXp+sYSI'9-K0V3(mO\_KU2F@ILcqn"mk^n(6P4["o&nfOr9t+*C>!P5*Q7Pidu+t+N`RQ^h;dc0__8l
+%Zo'_F#QdFI9Mk[6)TZ!q-(#\t2ab93YUG`W<X9Wgs62QArq05e`COWQH<1$[`j,uQ,Snk4rcsPS/1k+lQ#l\KJ[R*'QX1aeP\^3'
+%07QVC\n57k@2W/?Oc@@qdcPsF5h(6)"Mc@b!ceD.<%#44$<Kij3S,%3ZJ+hXIcY9,a5_km(XPF;,6Wc8ZF;EIF>"*)n@q!g#e-@-
+%"k:?S0q?Q[+7LJEOc_68)Yo<l\HS/rYUFFC"3.XgOsGWq/O@=m%?+s4$8t_0NsS;Fff(U%S"#:-/bVR_"B6<_Rg.R^kmuF_%!nVj
+%0j\pg+EH:`(%$j)+r4:U1DCb!i^4C\<Cjcg\66;(0!<%2]Y:kg_6m=:=nnk@)n2E"D2!/4[N:%WKAoK8!O[-^a)bc`n\W?d=f.?4
+%jYkq/5)-L=&_9t*75DI9@8!K:2GaMfS:agUm(l$&INa?WQWRk5jVmAB@h7/?L.&hs''V9.A=qpa"G7)m.f0H4+sj.r">b>95n`;k
+%mUM'Yg$NjC5]$4Q0:5pu]E,g_gMf`HmqS?!QlV\AB9;-o*D?0#aE;q7rDpqp(7\p).TO:LJV2jt.tE<E9:1C.Jk@bk%^_Z3-T`=4
+%KsE<<M8b)69Bs2)Xd<"L;%U*Wcc6=;Lt7]D2%Z&?[,t)<P9[8;5tF8AV3FBrLC&$oJol0,?W#3aHj/I=,ep>l)Nr.#e;*Sc,[FuL
+%XtQKS1XMO`^6Ec$A\pdL*_M%%#85(8ifEcU^6IW<jJ!e?)$u![Eb!5Mj9GQ\RRSf/R9V,/7A!)jZJM'iD.Y4_CH*?9)sQ,ZnI;NJ
+%.`qSi9VTYK/]tN@Q.[QJh9Grt-:$:N!0PEiVdpbS74\63%j3l=;$M[T$NAZnFo+4ePqkE`073lMX!T13UfCr&\N[E4@Ee1W@+GYO
+%9X"bD`hLi0q,ZjENL7&>-F5V!P!TMZAl200FacPE3*3#0\N3`*Q4$VX@G)!2O@:u9c!inTgEA!`gD6](F,qkK8m81o`/FYAo\De-
+%2QaLL3Y.^([1$NhDu;diTFK.2"PJmuU``NE42@#mOXD9j<nh=1BI2E<=HAo(#,@"<malYBnjia2j@`pkkJ!W#.SoVV1JHb#WU.j6
+%4-*)2WqM`n!-P_[6LLu6_+L,i)3@2V=')3il;2dOmN,)`i@SV?kI7H(;YLKuBmC6G9&;)5?Ph#fqS/*e?iLRJ650a3Dd4@>(Hf=q
+%_-i=P"rPS";t5oNm)uYRP%6Fro1/RueD#Rta.dRW"`7,IX*b>GO`YV_Q6ZL4)<['R!+&buWS@R[HK6mLn/ajUPCJ9d^g+m.O-A"/
+%AXr3>/IhMR4K^dI:$Rb7``>4)>R@r?j'h\2%Vsn#eU+H1DAM,K/l'k%h<A*T(:f8PY%oYW]LS8ZZ^,n.[e/oDas3@m#4umkVO<"6
+%kuJkZ<e\oYaGQ3cFWI9@eA-4!b&Iga[CpVhat'LdJ0rMB_(PY%(Z-4$0/<Fi/t05d<%8b&&;rkinGNWqa`#r;X@[!IcR:r\(p7Ej
+%H@X,bXd;(]IKCt+$*](nY6np3o=`LM]'$t5%R"ap^1tugJde-G0?#rTq6>Q/:g;L67(uB$3RZDli+r&C_].MT63.8]+DCl[jS.5P
+%8;!bJ^B$!B!1@*t]>7HNj%D]2[HNCh`lgI1I]j^QIW@A%ZUVI=m64^M?sm"jE"]4k!H=X.1*:a5:rp>M7#a:Rn!t.YAO#-bQ;aI7
+%V5R$qs6(8+=A%5/cQDSmUK!9ukYb::@BdPGJ@_U"ajV_`s$MAYV$C!\U<Gcd)*#<Pl_W$@*`O#>mOO<frk5JE2tU1eKmr@hkeBWL
+%lu6E3^nV)QO??3C[fhM\""gha_0'9/>LJ<aYAQkC.rNWR'dSO)Bq3]LNKsF];<PX+%Ora.38S:A4^%t"!7%k:D;-SVmF)8:i9Gm,
+%!nK<U?u=R-At(U.Nh)4FHTN7lIPC4\g:$DYqJ0,3NA4P?9AVVM@ba8Y&iL'GPhU'Y_5EuY!X`87.+3$!f)]n#TEe%?R6*`f*Mc:S
+%YFsJI)m>6)^d3%GJtt>@!pWn[Z1WIA+6")\s0?afOg%+4_>T0/g:#fc>qj/C@-_E^*aE[r@,ZHAX+P[4ZF7rq[Wg/1h^OhjrB;H2
+%^/mn1jc#2Q/A2_+^B3R[SO#PJ)EkU5']93aFY(>$\;43WhcDMT]%#i_hn)$#RcY/N9XnS'E_D=84Qr$mn&m.6:Z-;B"8)gc^k(8$
+%R1*ZH^,o]s?F`Yd:?18<[t#qHj4-Q^@A:$Jenn=6o;ooj3Y-E+i/Rf$Xr6#3>dJ7+lQD]eLGS)h_q$BPG,uYJhQVNbW$VL)NF()'
+%]qp0:kq&K-jc6/Q@o.<*D@j&Kr$Dq<MU;Z2I_LWgErl#4Xp'#W3LlSJo6nV>8p`8$!n\"Xp^*ug9FB=Y-GajK9d`Rro7jk/ld]V+
+%$]E`8hYfIFhY@KJ,i3KIp[t)pZI)!#0.T)fTnJ`fV(l?Gpkp/[ERD@L4tFEV+*7OV9!Cg2']r6[jJ'?3Amm_(,)Ed0E6/^=.b1iD
+%d1V9l/bX7bIJ!A8#HC(b=Np7<B2D[M__;D[-0sd9USQ,AS5`DI-kF9=_0Oes>kda9B(XT]G86OE*]V4qjNr^"/B:ruS6VUj5f$o<
+%r@R5<]P2(_iY;H'DM7$L'BgbL$J7KEdN=3bh<"nK$uP7'X#2]&c^I@e^$\Y+(S&qI0\EOf7rl1qJ_B)O?5#'5G#-E5m0:&4J_)_n
+%(+`*bMqRPuo9#/J[Qr%.4J+1D()]Ep;QH`!=1Q0!H=[\Pn=e'=l"h`3fk+]1.*\a+#Kt+:+'71IV_-qSmO#8C$.$(p=9dd]>%1mR
+%6,PFE\@$0WW!ejG]Ujenmd'r!hl?FR+O&dh.+\D?g@AgEeEVVN6Fe+CXJnW%Q&N-WGhneMm?74<Kf3fo.6#&P3=K<VH)4#^h_8NC
+%]a*dgg,t&=YT908*Ab$u$(c)#m<g4bK&%e@K;`hNq@s%.L)pSR3C)k=*'D(:0W'(gLec(/B$\13/lUF#gNN?*\5`i?;ab8!;<,W;
+%7aUZ*7_hJHmUddZS3KHfBUVd8!>`k_S>[;o1gmN3[]bKCbcqWH6k=$Mlp`IRXQ*Bh-u:OoY3mKlk*["kTF68,BZ[MtHWAkH'K*\m
+%/$f)l9%U1&XYcH%II-Q%i*$Erj8tTje\u>o1=Uk:,7G`MlON=1^j2gEm_f[,0i+cS_O!8a`A6nuNfnJ8fe\>lmI9p6Q-ZHV]r#*Y
+%DoLM&^6B)P<Qi=")t!9Ah$j0h-r2LW\&1TQUBO_S`<*T$a1HJ)"V[,eF/_84/Df0GA:3:mU=he8mLR47/DY%fM[e24%^RAI::m`H
+%-IT"S#0'!E@?6hW+?+C^lP<RBDDj10*KR%sW#Rf*DA3J`!*3'r]HW.O+P*'//[L=l*_@4hbi?_tL6(Ga)S`c!I`7_tdBX^dHaX=b
+%K<RjTc]IC\*If.^bhi'9.P@p07GAe`7ZSF3hUVWDMWC10Y9d:r[\`:>[/V2XQ/G@ci.1S"$n>VC8mG[a(nl,*J/tUVeut#G`B82V
+%L/bPuN8@k*(<IY"-c,lD7V;c>rd',A`]u2'^bMWs[07j#`W51\;-4mT?pUH#(Va&H@/]rZJu)^a[[Cm9RAuq6WH]C*Q&^[d9pa/$
+%#Ql_,L<Q=I9N@UsPT\IT'gM$UfHl/^R*=+E"]ikcZO7&,="(OX0[B5RnGG_"?lWK$Fli':<Q$WII64BgLOi-k[=LZp01i)RBJ-<S
+%'kZ8Uo7T'f6<qNn`_Q]g*E?U;]MLep<pI"2C(`t`5l1M_[`EV9hPBRbR6mgZ65q<S$G>N5"@UDXd'c3%$L_El6$iCgW`fnR%c1%7
+%RK+])[>4\\;VN&l'MQ3Y>d2lAVqBZ)j:sj.$Ic*q3ID_f<+*Z]AQBnXDu>!OGF/An21%o%nX<TCms\gq]agsHR$\GQnE1`a>&l>;
+%D4/'`i$q_Kg`pmW;oT_sV@0+^kZ1/*bAoeRcP-B@h;tB.i@N=NC'Mp_."3)YlIlG;2r*%gkAa61p_$9kBbA&CZE@h+'/ohu=BF@7
+%n,"uN&A69WXSVAak8VWS=#O(s/B>ODHiN>$OIM<=S[/h"S5,6GdUJl:0;SpN=^r]GEP+46\%qk[4Rm1!;e1R'T7l17\5Ss*b*/FN
+%k?&K1gup^H+8nu0K>uc?PfA!u!4n:3oDQ4$^[b#_pS9V@cSq5EXYr[W0&0U!fEZUEeilJA%Sgo3GpKO-K]h<sH+1V2EMYmKT;`6%
+%dk)$C.mEf&>6G2cq[:IbK;X20B2m0]LrNA[`gjJ+,?r9IM);a1iRlF)P!Pd3RJu#O'&[r/T;2/=)`\Vpl^4r-4:L5q2u#LU#?`er
+%`&XM\cok.W[CA(sgU!dWb"rXM7'cJa-'"%minpYn[I!YcC8dI_XXnK<K0DE4i#9S%\^@<sF:89@SZ@N`dQ94_\9\XW,mL[gi1>V5
+%"tm<\B"!*#iDDQ4aNQF7cFnAVfet_2o!@1=U,BNI!KXqm#_Lipn&CDH8%Ff<)<+OR/aCPh@;IG75.@*qbDsPaaA?3NVhj_\E5!*2
+%m'pr?F;lS2Cj1UkV->sTlssLYmaldh`CU7gk%sbX<ek*YF2-B;E*746jg;98`j8p"$Y$]nLqMa4UB'T-mldU4!*;<E("p!&luh2c
+%eb%Z\c1iF)41f[^m+P_m+Kcg;M`e^l3(V=G"_E67(Hj#bd`gV?r'/X@h)\1=a7hNSPqn'`$gN5EPje^f?l$F1&2D[MeS?KRP5>\<
+%!bKO/Z,N3WH.qWjDC%gKh\P"`E%B&4J%bA+:\BLmKtX<X>oqaGdhi]1J:$$2*UgA%Xq=\0E=BSC&70@k1a<1EB#21TF]O&^FK\g,
+%]r($.k(^AeDRZ.10ZEGlEK0W)hgOA1ZhDrNmegXP4@0EccOb]k2s8uRgk"]FmPT2)cR3h]Y>R5i4)W_phojuHd'If<-k;\oeYV2r
+%4mk7!"h76O75O8I6C/QA>=Xo\X&+@_P;cFJ@fV9=W7B&$)s4P5XS3%-`6@Ok"7*Ur2>2u2J^c!9H,Qh697D&un!P_MdPJ<"eW?Eb
+%.\EXCR!J2Hd#&e1)Uf`X!eIll8$%=+'WrJJ;*edR!5&id'\*Be*8nET2)$&6WJGbRUr(_Te`%k]QXYe&=>7%(oZ2"_#JaRNXVkt0
+%c`/$Tb3%IM\_"4&igeE*RaU[30__#hVqUOrBfBumnp<kJbWM5t"Ik#@f$\CO>W[.o1k-Trh.G[1^*?+B:@nX>#oRP5Tn9%jRDq6U
+%4CGO\gL6dRs1<`0c=^kgXTRdTj?p`er[6VHF>Wd,:MpjCbp\=r0M>QY-#^j_7\j#>Br^mR#(#F8b')oeC7_)8PFs<fCu7!Wiac`=
+%%P-rD)p#i#46uIchrZupY!(!^93'B2:up4n(?_a!gMGsV-#rLEBfBMK8/hcc%P9Od04*"m**c,:>WcV/UK0(F-Y1?(O_mri?bY>k
+%fs-JJ$t;8IY>Te(0sJLiYQ(0"-\;]7R+L+E&9Milr^bZsJ&4)gV(j2NGF1rQq=2&Iat7cH+,BSRmF,M'pB6'C-?041%1LIL[:XWt
+%,A$Si@bPGgO4qe^*pJ.EQZ@&g.c]ZSW?d1T%q^^9)0U;U-o2=AhsN;`2H2O,<YB"#4.5m]$tKG*Ju$4T)!DY\])EF`_p,Lj[u36R
+%TB_PTi)s(c8k$I0^LCnlX$ikoWQQ>*hf\9OV8:=A7\jeBrK^!Kb)K^#g5++!duCk&qslbjK+b>m@T!jJD!Y+#FeP(R>L-IG>l)>n
+%J-pIg`Ss3T@bI?3S0Rs)P!WP6AODgWi:Tpgc\8rch.Y9uB^euFEn')TiY2]\2;N,%$HQ!JrgY+Klij+TcQ9C]+_=HV1:LSs\@&_b
+%U),Fu<&([pH4PDL,(U(##]=?cCB>2^ke0+&DQ,%GbS';+K.;edHfY(3Z0f(UgZg$IhG+DC6$LFq2WFV4SnRe<&?f:qhAKZ@!YhNl
+%TLuslcLm%]B8E"ZMXXn:[Co[n1<[3Ar!*7*c<\</X*-VsbsHrteD`n^"&\Bh$cpKX&o$fnW&*K6;;C6FE<uDdP/ZanZmO-Q/a!$E
+%MoGXBN9H*)b90;-q#<WQ'`58T#^f-Bhu,1FG#\i]_OYnX$>Pbb+@&mJQ]8M_o^IG["JG1dm,[`A+$`$t."H9--1\8EnkfCZO+1j?
+%;/1YpEaq$/gGW^3lR5acVjZ'QpLoG5**,Z"/tdM`VgV.u+j1olY4,>Re./3J35P((#W$A%8j+-*1*X0-r,kpEjC-J;H^d1F6(B_:
+%8LC!eJR'P!o*n+D>(2q/@4Gd&Im*Y@8*aMLCJ:U4=LT^LH8"MC\'6SK!nnjWhR/IW]rg%K</n1QCHnnrRG<1FI7)s,Gt/<S%YoSe
+%cCU(/AnjgW'a#;.8qR!AC)]$k^pa&VLiVr"h?K1VX+>PF-s2]Q%F,&(X87!Yb3YM<6;CXhO;mE(ASclIC=i7.$DW8qG0N""H$?a/
+%p(>J*bn5X*KE+';jp:D`E/nnb(J*-H/9dTjFPdXK_Cn`2F]n(@ko:',@5r!a]HiDQ<]Q,Yd5H[`!Ld0$G]1U+C<i`/RIdDNkBoGu
+%!G;TA-(1dQaX<LV(h(InoLp<Mk&>\N26l.7:'39Sj%=GhN2s1#+m.uoC&N2Zm+]*g[_LG5BsL":K+-C%nE#Qm[A6"f,<FffZdcS!
+%aHVON74ZQ\s3*[UBu9bb3KrUY92XV9(<#;PkXA=HX'XtH?%I0BUK!.L[&0sHhAiVeD>T[!d8)/Ni<&LYr^?GGUkFb3"4S@Df3&SY
+%X/1ihr.XeUXj[!Yi3G^OcMMV,;bPD<Mk5a\rBPP]>SZ<-e1L\U;Zj4cYbkV0YU@Z:]_-`BO/di_SV+M'J`=SeQ(^_:H6S-K<5RFY
+%<@Rm>BF_%["L^0^FT]Uhmkiu"4Z?tT=AnXSe_6A&05MN.IEn7PGH`!^bY9XZkHOZ?1oK"`N*mFm"XEKm^k4gFpSd736pAn3f7^;>
+%]gCI"h1W!!M[i^&?dH4[:Mr\XXlUIsTPU9*]!LS,aIJ&jMtOVV4>ReLDVi6qB&%u`\KT/GM'.YB#0>..:1Ec6g6q3!(%rA$.#[7<
+%M3A?1[5)kd\M--C.DI(*".%_:cLO:T]ZeRd)@;;V9`.rS0[5Hoo]\Jcb#;al!d[+boKE_sm4Z9!X#e+>nKfa:^5!mO;F'>68lkD6
+%qj,sO+:ujtj;S/F]Uij3F+2*L1qablOhBnriq\?HC.Vud'UR8`q90uq7elra'e1Mb)[X(0O]cUV,P1de_L?1lQYdiiYSs@TKrf?"
+%N;"%[&?@c.N]!M%ODZpZM)4B!p?Jc*I2Ct)-H1+]O>RL+YV\$*p4a?3m)f!AA.7-,0gsF9G*!QY/HR>K$l@P8NAM`6S!f4Rd=hg<
+%9AX9?('AWVN9s,ik$&JP`lA;pIj?epq=Dai>V#%/_Lf<CJj!;#'CD(e*>UKBB4,#.JMZ5'MTO@5o0QC^@YWV(*$k#H'LM'tr>f-N
+%p/%b%aY72?I&%*&g(>J4':+kJ!t,J.T<KkKA\X6*6Z\D5f_>VjKp]lhnEK"#\`;^H^bLt<N:GK>Jbn`Y9?)r9f54.nP^(>C.$VeG
+%3041E7EZN-3CgN]#$J)H>AtB#bpig?AW_Se+hj@4AR*^)JfmjmD&GPCR0t5j3UK'p,:%)Bg'Cd]WU@I[$m;V'S2@VY]OrbXi>P=W
+%K-#usLGK-aarl.[q9XQQ3C=]g4Dq\8C+0Ue\"=as1dR2-Aac$Z0c(R!1@LV)nP0)g*_G17Yl9mqJ48H$P!Vo1MHT6i_%8lCIJ<-Q
+%kJ4aZ5pQe9^c-Q>Or]97O&@pf\M,tkKim[3KJf.(2't1IMVPt$btt6/"SECm)nfbR<?C9_?6Oicdh\>=h>5,:VB^N2r1On0INg14
+%_VJE1q4&mLCUb;lS0BR%;(Q,(+^KOdZ%T#F@E.8=-%Q)-5)L\uHJ65q"G,VS3-0;rr_;s.dLa-9c7'dg-PsFl(Yh^JTkD%E#:4-h
+%@/U!Hp#TEu%K!u7=\hPY8M>I':s<O9_9YW,O6"SK=C'F/MkI?/B?A5b$3RTB3sV8Q!<-9g:1]H#94Z\T<68?n_['j$6qrWk")XO,
+%'\.BMHUARIkc)Q'[p0=G/cAV"7aAl(8]PX).aAJdi*A?Y>kD"UpEYk2<gJ]0@R<?(*lYP%+b8$dcX^YjK>YuTQ)R8gP)<Uu-t'/6
+%m[GMfQjAM2ScLSiAf!7e<Pc0Nmh6@TR&Yk8\M#1UJc/2ua$!no!^s9(B2J!>MQ0XXP9_[gFX'XTDDF>G72<Nm,hDOa9Q:F@)eu'm
+%DB4"H[bP>/SP5U*Nk&V@=r3W=%2RI4oVR#:$8ZCI<CprEJ?8f;<2EtcWpKs]iPcQ2-!p'<>iVS/?ess.(c%BX201/IZ'F^#7WK]@
+%FD&Dh=+of\11HI*pNpMP<YB.\8>.[h%KSR&AD^ZjWE`r6rFup=+@G'+0H4TJGg.PuTcD7G`u6HR8js!IbXu3)'s#VD1YCb9+I@[$
+%ad*B^1+5a%]M/d?LG$S6XMQ>^>"'4Id#=Wi5j"H6?IRh[R"?3@\Rc=WH\G0R/OTR`$sO5l-qf0*:ff)RL37AOZ8Yk5N'9jc]f+RU
+%9K>3jb8$Aifj\DKApBVVlSPC\?r,p?W<-o-RUlj'GnL6%[9Wk]=c-(\`s".KHJtFIg>3^T?Qiq6]iE9ZKpVU-#nRu;]S_).S4A1K
+%9'C-J<Z`,Pf"J*m+n4-'-BfZ&m[@uGW3e&5rR:Y+%Eq7!kD]"7\WS:("?;J.V.q/j1'!`i]:m#NhCNGS4-E5Z@L0;?E^8@gq,eM2
+%7'`Q,+S>O(Of!"^DYq^W2VUug#0SR"ONc9O#[lTdQ(\Jk>+M[+)cFHJaQM+sXMC)_Xu&hkqUfJKb46ZlQ[&+6PENR/[0c4NG?;,=
+%hKpU"Y7h=Eb7KD#MbkH_#Eu3cNS@Hdj*7.,A"V=/q/3HFEpcCLZ6b[`0'q8B@>=0G(!,pgV,Nna.u7L`*pXqEl]oL==,q;o.Oq]5
+%^B'&AnHU+-Y+4]j]KOq*Q.Ssu*bd3lm(c3WT=Aht5"8"Q;Tc;++@#H?T\u?U$L[B94THoR6=JY43UmYKq*["S_]Ineo*P/'q1q0M
+%il(<-#[>8LDpV[H+Aulp?%e,[l4_6kH+(q"6>[;1I@omGB&HHc`UST"jkcCr7h3MX+%RGEofX\OT6n.i%JaK+TURP).1q4%!mBZ1
+%e#;Gip.BEmh=2:@_rrB7Fi7k\3P<.C]h]L\k7Ooc;KHH%!#ZN,_A:HfLKh@G%3J@RoOFts(<j!(S93;pf8Y',kFa)5p`[,DfZILd
+%QL#(>NA`Jke*V+8qNFN;3`u3t>^`jLg?sXPXed52bJ/U98bSgo,r:9rMd%[J.Zsi89[u9]Zf&Al*Z*n.CFp5,/d9lBr?d%OHS&V^
+%Mqej`VtV0g*Mp&0MD&c$[sI-Olg;f=Sf:]Dq_V^?SC8LBa1DSYbY&t>.0!sh50GiZ"/EK_44^IiX:,*X!8Te"42n+Ud9[[`A)TAG
+%,"2B&,>>9uK0U?Yl,,;$;M#@!"d*-l@655tI,/k90D9_sbSGF34=V.?/^aF,T<-1P23g-+/js81M0e`()Z><#k7-8[ODT_=[rIf9
+%hS6(l-X#*Nk7KQtNJF(eM%_]o>$%^R`0.Br5n/s)V<+RLMg/]qp-'K2!)I)<E)%:6[B!s6EfJk$$T5VKF4R"j@+Ha[9)'n<"E$Ei
+%KR^^F.p;G$T%O:O=_$lA+JLWTfrj714#23>baW6*I\tY*Ub$7sVVrr5$Of,Ufelu/D#Dlt).cS\/]&T?n8&'60b$tSrgG'&1:AbM
+%/Ha)Mm(djA76.Xukhj1_,\/&P$Q*+B;KpaVJH_"[^gL+j&cOsoQ<BI]Rp>bbX%*k<UY(XR)StIDKT6:+g+6ru0,q>l`NgU50Ub5D
+%b@e_U],o8akWZ.%<AA>?f3+g1X_^C6;`8T!%UL7)9oD0B9,-"JH28^=QutT:`lM;]"g]V`_"e:7AA3N/cM#_Aq@lu3!q1pHaIRF0
+%&qkJ*CO?8k]Gj-X7te(g[b-sa@BWN)1K]pg.nmM/M^)6Ri,-cO%1?NLkt)N7&m)!YneH#JS0h!po*hO4gJ&!'kE-_dDEBd19^>EH
+%b;S.cndX%0&Sf_ZpIS)F-aLc)>s+6HU$`&IC?k`%nX`1RlIssFRZXT&<KU(AZKud!KBITcO(?Y[5%0JEQcsa9#'9+4f,)>"&gc8>
+%P[t.$pjA$>QIF'hY$-'+lO:'i-[QEu&VK7.'e@eE\%iPYE,-@Cjc>XE)^s"r..q=>-hC\^3@I%Z+42aOpA<@_C2,>_8(k^=4qY90
+%TRu]#VfN_p6a]&>\iA5q!Vh&$n55[km&X1C"#=oH\=s3J_LcJbg_'JE:!%rlHg)Lk[/>=lp!tcCc.D-IMsEYpY91sZ#\D@Y;.C,7
+%,%t]H.dd]6q&&($>0NCS^s^Z>W*\8gi2^)e8$$)'ZWfEoX@C>e#VT+,;S'aHC'*s$Sf)+['sZBgMG%dM`u0oG[Q57X14oKR*\--J
+%CHXZ8p$dR5>[@Z=DYC#LWECVihb<00KEPGKeTB<k(]YPj6>Kf`?7C7*DTP0roph'm93@IO)osMV9n:+&&l_l=IfNaSB4=]M[YJ.e
+%QPH-)/XF$Uhod$P'S(;?(VJYi%q<*<1P:8^ZtQGoOql8/$l>18CCBjm.aN!@:DU_A:!YNMXATP0FSHKHplt5Y.UuG'[FKM7Z'kh;
+%-/VMDFDg[M=ct;_@MIDKjsi]*6P,O7%%]51#KdeUShCD*kZabb2S%Ym"CuK(`i*#&a]]Q6Ks4\F5un@P^"I0Mq5-i/Y=p:NRauR2
+%1.EZ"?.UU.BZmXTN&&fGf?(:`V3&G6%6j3#X_sf3nZRI:Vi9*gH_S=a^Oh[+`)kTb+&*J!_Jk=i'kTiVq+c_?GB9+jBm#qW&%cnH
+%^lCq:-o^'/*PjCj("86'!bF&PK(P$`GF4_%:Z>;6>TLJok&IVAKn2n.2G$s%C;)LDJPH%5;=ZlBmm.`CZkeYBbi%i[I_TI<[QNHM
+%pr>76@#[;Jn)4EMpNNa6oiX5R=1qC2]"\7jr0[?K,8dG-qWA<WY)9V:oUZpnJ1P>^ln8Z6aNa&j4+YGb`3t:r1DVJTPP?QLU!:EX
+%CtQII0q8/5j,SgN_PV[Ad:>3388XQa!_@Z*cqkSGVO-N69..@Sj=S1lFlMt*!qNL2iD*fmZs\[\jp59*QtukPc'0-?5.aP:jK>n_
+%FVsQ^qj,KhV2C%^EQKP1(5o9!,s6e?jDEh`dlVCi6npNA%%q(V$hW]C5<g#t),C3rq9=n0p*FWUQP#9_(i"F$(j9<Y0p3M_T_jB%
+%"a9Z`G)rge(`g]*Z/dr,Np)GJGA"o%!EXqt`&,C[?kB_?/LF##(.mr*:KVEk>V`=`Hs(ZR3seY;O/5pIcf"/C8!)kj#-OBhCB"tA
+%,h"EmZY/+(!9BA%YS:%Ej1a*>/$jE7j/+`2$,6TSU]?d>V/9fcfbq'6^^;uRDh;J$nBTOahh%F_`Z`-B'5lk/'3Npt-K)to'3`4D
+%*^)aP;/annd]h\7DF?Md9H2+Ndn<\)co-d-jQd"0n&tPc"q#Dm2)#7n_*_?49hEGW$0RhlK)=PE-Mp4_"u2iJqD;k>/"J]1bS5"o
+%^q+EqbYAM$Y\1^5J@=3r$tekI9Xh9pm_K%*GB4ha.o8a^KS6if>2\t>U&2&>*5rmDT]HjXX?9=)-]Z08e>7NApblqWNCN%4jS?pT
+%,AY`%7N$c'd%]Y`.<^3*9oC6)iXIN@?Q-QsR;$Z6[*Kf`SWLY;4BF[:'#GRN1"Oi"WQ37$PA0o!."W4Oa7)k/>T:1!!WE,gQuAu]
+%8nMnIn$LQNF`>+5ai3W`-R7S'<LiGM_!t:SBee&8al9P3CCEa<r6tIYF[*4&CT4f<4V_+o=7Af^N9deBM2Ehdk,m`c=8**q6Yutt
+%pg_Bl*gGQ7J30`NPNoUtWqcrq+1kF/adGG>"@Xe+9=C^SVe-q'rkao=?.$m4UnYj9N7U3K5bG_QK<=bP!INU"#id3tQ#nX+PZD?&
+%bAIO[$@Xf8gF'JNdr%9N,F6Nfc&&6q4@5)X/k"JiT\L@m#NV;EAHR4Vb[-m`kNg,Ak`b'n5364)4XV.%%rh5O9:r_WVol33H%@fS
+%P$*nT]nZiEO=fiYP2MBLn/+CH_"Erdhlk*]>P%J*-o,JGMk>VA^Ygb>7.W4s(p_WW2E=c\)n'VL0Fpt!5fYa-AY5&2IX7f!VPI_B
+%1X_LNe(::r13MtW;oebC'V(K4Es'`pa,p%TmXO9K3(XNi7f4SLHEPGe=m=c"(_knGZ7nl&-V:#5L0*'h2Gfh!\0<fV8#e=b%k;n$
+%3jLaIV/R1p6TO>TA0A:*JueO,?B%VhDe@mJ!JP2/-oa.;a,hPM9V^r=B?oW,H0YG+!NJ([PAtBK<8[MA+$_bQF6lQf%S)q7ju(i[
+%MI=4`9i>fN1te+SLB;o)f7P'12CGs.d"'0!B#\RoCN,GWr.;Q5h_r5J:1nlQ8LHobh[\MPerm)E^*d'=`\0Q%H&Jn%*E9M6SXT2V
+%k00T8k[0QY-MC[\%uk]EC\\/BTkMYbgbL`#c_!"^k![-"/7*8[^!YW\G:M%>N-d1G+qN6SCCAmtga-M+Na%6,L^@gn9frZ*m;e"e
+%rfL]rP&Y62S\\KmKd+j%5'JBOmG$F@dg;@,?[+MZJ&+4$8R<lgCqEmuIb64pW(Ur=_dR(g:/EOk\O@ec=ioiu4Lcck'HK:k0mc"B
+%rSd=iN<fE^3bGg)HbiI$qb?7(SO7"72K^Z6(1`q\k,)EZDS-5]3%^#@Y1N7VO"?jjk6[`#G;LBH1Zgut7.5,S^mT)X.pWVH^C/m5
+%GJ2"MhDu-*4hSg2#_3NV]TTRihH^AM0]T!$#/,h<5.=5P4r@R7I=Z\:"M+)gDVAdGYGJtf"t(M1(@g=LqAkLPV"l$J?].`!Rft`H
+%0CEuEMj1mj+FfH6(&LU.YT(K'?Mu*+BG-)Cc`-_@Tr8s=OEPS*[PoW-TtS:)LY\(q1-R".bW/,u'q7P]*o"_pE3-C991>=]T,*br
+%`S@%,*Op/@W-ZY+s!&Ze`@PQt>8d$K1_Xl"-B*`)oI/1F<4#qZ(=^7)aCP-FDBnO71/_5mL#kfn&*Bh^lnCCV-H8;CCdsO8[3-),
+%W1"pQC'sFLQSUNCeBfC/&4nD=:3/*oLObX(7eWlE[W8'hRa^[WTXn<[$#7R1MW2mlQ6c.(&MR'8I5Sb?hFn+6pCa\o2o4rH$`l"K
+%"=L2:%%HFlcU)-lb)Fsd=\Ao'#X-\oQ@!^7_$nOjGYpW:Q=RokU9lV.?<6qN<!4'>dlrF-$gr)QD%`7e)A\k6f,@-eLCie8Z@pgc
+%BAmhbS-p(SMf.WC4D?DnB0%sg3G^U]0`l-HO*<b#^g&uN22[T@@t3(T]g!,:>UXl:IL&Kf9BustWT./e(HBE)co!eC+bsi+;@f1!
+%!nKjAaHa-N($jS:qV6:K1"8u_!^QI0n.F14fLlcF=i#j,iEWuS^?okJ_hl;bqMDa-<&44=,QK[`fK5L!0'!]C_bgi`^.Ope(2JcJ
+%nN'LM6^^heD-1]6lT"bF(lUD,q_r=62\LYuNtFRkDr/9h#0R*Z$jlKh3Y3ulrk!9KFjFI=OoN?e;t&/Bi+BLA=(H@X$gu;5U<FaT
+%(-g^=eZ%joWr<k!'iFk"Vn]FgAu-$Y7>TUMhXHE;pgG$nCD7!%S3o_#>$a&TW@a3Z:IS":D,&1(W!/kllZLNf;<rBa$:d/=#$@s*
+%A<@SG2FJ_YVR_:pa%DHT:!$O*]_gWW:(j;f^gQXiL+=N8Sue7G+:\->UkE&GGY%r!`jabsZ&W)ILmu0&$9l.aiKSFMCZ\ugAo9`$
+%Zs=BEW<7$"RLatsgBb6upJ;++J3@ApW:.'%bE;3Gl0YX?30Jq8E<f,e=a3dMJ%=gh$&sQ,M#9>9&gAh"@'\K3)]%h%YbVXM?rD7u
+%UL96^oR%DJ5Mm`YAXLG&SoW#KfeO$tGQF=30PPqE``+^qNPEM?B\6&g=*m-'5DR3_b1##76'PE/L1Y0`8F#=[%C>P8hc65u3Y5B'
+%]2B3@gfqr^1)M=^VAOXOFuk`X`'E+b!G?RRpH!!9;L@%dn:r&=WT)QaH#':&5+,V%p^CgW#A&JVkb1h+3?9I/BI1KKp:qR?BV7#h
+%9_&hmRNbNA7NAdG%mUgRWFNeP;s@u7aJ'E$KViDP]CR\KQ">^i[Jg):/Ko#P_G15qILd+poR_'E8OAe>2O>LE\P(##7_^s`2c"Ka
+%YF)Zn->.J8<YCkZ[2=/h:6fNg6]j5hR:`oa<FWp%mfSs/,7F2Ge^0iFnC@VfXehE&P,W!oo*?QO80oPr(JD%tbo(q</Y`dVHU%U*
+%Pf0[P5i;3>.O1`@8cfE"WtsH[F4IA2G;QY5M,t*I)5,!$CoH"**e<+`MA@Bgo;G8PCMF#CelOQ>cD!8-K@&g[)EeHd=]s6+3Vek$
+%jTTrG)[2mDl@^Y,nM%1M-r!g07^Z-844=Nm[)_*`Ub/R_+d^+bS`q]K!]_phabMGqgTh0rFK:PN9h6',!jqcJlTsYU,Y:I*%34?Y
+%IeGCE?j8P9p^I6c./-J\i'c$OPCW6-<7"prHioCfYb(goEjSWApF#H1__ihARQ0f"';b<Nc+.eI>>N(o;_1b#^c@0NE2f!l_"QV:
+%1;qf&0\9eh2mi%o#h-0@Nni9M[u?q-mO<bD':ZUeSubi2m@B]r99,G_q"g>,i6D8m;GBI>H7q0i(O27Y+S;:VO(/@6:8hL.Pp>!Y
+%:^gb;<=f:Gf&I5b.NuS8C`b&eF^*t&TGo6Q%0=M_XoH``(UMuH62'5Z?lX*%fr]mRMREZ_r>8rgfDQI)?GYqZoN-8hfl\4j9>Qg.
+%Yl2h.!cR#(%<&XIi@WY&q"%(nYtH0(`7^1>^JRGK7lBe+(P(qs#Q]:JGWUjN=LZmP3u2NlJd2V/4"Lmm&F$_';=Y&Ur8I$cpS<i_
+%W>eHj,fh$+>OU2dO(ced4%:6q`_3C)N3rl/Aq8?YO@mOZ]@!lP.c_bWiLZGPm4;eQ9c+-fF2m&K!i@)mEZu/*m?@k<4L6<emF7ai
+%pu*!W(N-/75gcT^%BOm>%:$7%PmB?hQ#sm+8B\_agIr)KPYf#`UN6MLL&60_^ld/F03/`FOH^>AJ=^TMI#K`d[<8GT<Y*J0Jjg2n
+%dL"V^(,^XXPTK0'H!aGu@)3_6_u2J'=qL6_E!+ARlNGp%3sEprL(;(JWD\d,k2"c9ICXu70L?]!8uhra&-0/=hR5\3>+kLqNKBAW
+%TYN]_9F&W_@n<qU6GS3D1-=f-)]6OLZL%q/+-A_]:"toD=Jh^BmfG]H!-^L.UW@EP^;OonZP`rcZA.m]\7GiYNp[`K`R]i,1QWo8
+%!P\S?g(js/[LQ()UYJmioo*\69"'3Q70'[M';U0J,,F#N2RT:iqMjG/(h#AY#.UN#0-E6i#dO\gQcN\)!l.><+N^+>;DE+@3@Hl&
+%LoYX''c>?#W5>,p#g??.$D)6Mh_U'ki7D$2'.Z0_32((#EWITH8t(,_N\upoO_.#gC+lnijAj1#1Ec"OP$#&AoOKe_p#'=a^/pM%
+%4n*5%"d&NXc6?7p')@:XLc5KI4^%MJ>)%PXg&(7!>`uP:I#jTV`/5UKL;k(L8qbn1mVVD<=>a^dUc3LZ!g&6,O'S*G/XX.sb:Af)
+%f@/Qs2]^??O$W1O*:2&gnRBM1+6pI<7Z&ljqcAM8#^VSiW+"`q+NI,o\88NAR.1h01.To#2WJEQES[Kg`>.ar)=h:gfnHm0HY85W
+%]g_A)++mhYl&0mcCWhZ7Oh4)Uei2[<8A:oBr$QHD9F+6"!EO2PVr\fD%+9;nc`DXiR,IaO"Z)$6Ub388'&X@n-F:`gb[J4Ahi7+2
+%MUV^(#6h;6)F5Fq^j9,gfn2';9A=c[]E5q[``FQjg/;Yf#H8Ck%*]&1./27W09J<0_AoiE]itQ@$m"[9empV+1G#C0p^"I\k@915
+%>%K=HM#Y3P9Ei2_oYJa;=j%jc>?25rhL5U*#c2f17ed*\OZ]^r;;sAtp7Pf(<o$@9E_idM<7l>?'N[D';24\V5^IF.'#&oiB&)2M
+%acik76Fn!0>-9BMM7S3fbbPr'#ZAMa-isaWN'!L@iPX'OF#(l8!;`I"$l%RVGAg@_X<&p\1t^`ID<8Hc0mLDAU9lLKU__U/J2f$,
+%h4,AZD0*G]gC?m(lBCU?M:d%UX'L%/pi5`cgutXE/%<rUOWC+$\.0$BjJ/^@"g:5B?j'Mmk@;JYZMk;"Ko@;E,YutVP0?qu)PIEc
+%nblnUBtkak@EKJh0+dPkgWO3K;jb.X>[=kj3Z'<b[\%Vb0R\TW?60XNKGkO?"5f,I*d/X[QM^KCaq[M]^9lQ$4YR>-DmkC%1I1K,
+%cFAqZ=hA7'o"NVO&X-Z-f>>Dl8iD!bnJ$-m5`4\5>86O:e4bn8PAF*VfJO>P<"'20qd>aXE=9Ao#9A0T/'El%FHF-s=I3l89UHU%
+%kKf:hCm-"^#Hsu>7p2(piPYLqqQJ"%-V2G<@a(ps,&i(*?Ee[/nE?@,o;1^qaM=?Qh_9LslOFb*!!^`tGn6Q?FY]c]7u&`5gA1h$
+%WNqOGN&BKYljd<9m\\QY3L@?p`sUZ/i&0k-%QP$=T5.)Y8ff<7J6_P=r;8\.V60N>=^q!%'d)B"cU5JZ@#5&bSoK5gE#tq^hU?ba
+%4cCLe;Js=,TJ-q1&uB=+UI<Sp0[uO$635Ln'4j`WQAUrN$fKo0Dc[-eh9/EVM:/t8.ahG=L[C3_h7l<`#P<op&NfJFHq4iG++4Y9
+%p"t2G;oC(#?;hSXrgVjf3ks\Fo1,F05Y(0XDVo?"bl64XJgXI.oNI%94\eaWd5ZZ05IS8B.Ga.e^ut1j>$HGW!KA[T^#&r@S6*ic
+%!dEJW#7(9XZmB$;oD2X">c8+^rRT.SNhTT^]9ZqDKtQ,DDqCIHXD&V-pg!N<Gh<?A(9r-5fQpA7BDOo0Ct7h!^l+o`$84^!Ue>D%
+%A&&cUIM4scd:+Yt'L3n,N7Jn:p2LYeU6V@JJL+=@>WL_V4rZd+g'!(#meI^YI9MBa>04-NPH.paA@Te1-_L`An0%Ir%]si]4tXSM
+%r);?9m`-A2s/EJT=9CSHe2#b3d^7`^EXW[m_5NC2#2DT^`YTB%E;Kdi\dY4-N7.9<R'3,LkL'!aTi5Y'a07a3CWd%>f5;LF,%tq6
+%!m3L[H>s&m8/LdeCQ)2poq4S76%Q-C+56!FVUScUBZUbsa1+/dAD,+P'mKkPaR_.'+Qh:PfYH.R'E!:m5`\b,\E]lP4oL>NDI&Z0
+%T9O.^-YpN^UX%eLi>?N$C'*D)r_]\2q4iK2b/q_2jA=?%UWu2o*`pj;k_!!o7ZiQHP?i*"\9I6P3)@An47'[fBPtEX(UI9R>gV.+
+%H:EZ2Lr8j4YTC4:Q;AUFLZK?L$'ZLla0@B;a)V\R.&V'5"h)WVQk$uA&+\Cr?LU!O_8tZco/p-jbq>U#RA'VWeQ[sQ-!*-(6"Pn1
+%YQ:oI"LkjqT2WOKSU_:m)*Kqb_J`c0P@2.n$uJ!YXP0_MXa^!K^M*^iVI&RY"?>Tg]e*m@$oV"#3%(PTChMl'YPiR?ai(FL@\&]-
+%Y62=.\!G[@J&"TFTkHnMWCV<,>ch&lAq/]r$',04+9r&-F'(c2/\s<eG`8<9=,[1lNR9-N8n+(rH3i_R)A)=7.iLgi5D!7^q1F3\
+%Yq8=HjA?iF,7giB+;',HX:_P,,'gMP@$8hai0H7b1bPf8!f<USX<M>B[1TWTi=Q*kS-K3BpTB-T+7AT+d[ar+WAu1)C1,=8WAL-:
+%PhSr$G-%7+Hk^EX`uP!28]DV'?*7S'mX*+lN.urd0OH@dWUg+,7rVl\7>LJC^B$VK5Fu0&1Z-7=,C#M7l8NS-gHKBRNg&lVSR2?)
+%!cf?h=/bp@Y?O)\FK<28L^N<qf<fH=HZ0]SV$\nlmd^"ZG9)L0#.G9BI6Y`n!Cjpi27Bf$n2+l55Qf%\jf5FRXd200^>B'0UY01>
+%b2iYcLG'I"ZrJfVVKU[+J\iU]TZdICF:RI'^W430D$`,""h#J:J1\k.Du6-hH?90@O9NkTdKN1r-K(?&lop$/+3g,HIkH.:'<)4p
+%\7lJXF&B`cAM$0U[8bk&PD9>*f7a9S&Eet*TmGGpZWdUm;;[Ee\$jfDK>(2IhZRoqD%@<,;m(lhjB_150EM_/qu!@q^b=9Q6@nMS
+%grHi4^%FsRG[9$Zjtd9W!]2""Kk158s*`,kqX91mT(u_ljCL##4,a^lSo#!$anb0]66;_87hJ97%u/&J\F;t:<g6K?E*dJ0_dugf
+%&"&>M84tpG(<2epo\)hnY-@$3=arq%C'Q_=lN.Jmi/-N*"1TO>e_upL\-L4X(1N^h]/4:A30@8sBalWsFp@oW`Oa+WNFi'?%MdQ7
+%e*=d9GXd9e]Rn#D(5e`7Y=S^Q7fuPa#9"Rn(57k#6[M+0R5DM[7N(tDIQd;s6o301@Z-co2-B_7<0`3=CkiH(]<uit%6E(2]W2WJ
+%9]F`:Ti'9<rfo=P.-0Hq!/+j/UnS"%7m8^8Fe]0\Z3PteXC@da")N5??1ia..i?`gUX`a+aqdF;KcD=MnX)(N]R^f.DO'iH17qlM
+%KZHE'Z(5hL&4mW"E:Lro:N?M>+r*KFc6U_AaLc103)2"HKSbX/ndG`CXSclUe/c2+'6t_UgC!)-3?ePm^qt#/B#^LalR&ek$CZ5S
+%n.pAek-\]jkWi\5fa..DD+uZ]hh#U`ICM(9qW^\A+h18g(n"_)PkCK8^cWiT6!9?/]*mm@4(DM"]'br91FX_7q@pTUF&;&kjl+$u
+%pgX0e&hHW"$k*BLJp08#/1`[lOq5(e!$3DM"@]JGl[nT7VJ0ds-,\]:6=$?qYZ"`n45K9;fIOF-'.@5m5O=]iK-f=oUtXTO9Yi/9
+%Pg7&.El$RIBf-h5OFV[&_i)R7JkLQn4DBM%5oSD""eX7a$NBcBj(#+%_^cP9(T.9NnUUq^2ZV.VOumqZfi-7u(^F[".Km6n4K!Kf
+%#LF;Pfi-C'Z<\:NE@es`Gj)\FF8S9:AAm]A4^7b]`2o&,.mc/`,YN%<->)co,^!=SK[kZLXs=BZ1(o<-8]hCl@FT+2TV$</O(<s6
+%9)ptiek"P)JER0J/>k(Up_]<F;,T>g)ppK/l=Q('M"s"hVK5-Z9l)a\/(\3al^b+SB-<(?>I8.@Sf=&%TB9L?/_A(W5YYi8$\`&J
+%R$&&G=1B(iEc0!"C./@nOT,mqYLE7]WZmIR9gJBElHr`':s;_qD7Y=?_Yh+[pgOY-i9$6,E5Xu]7+t5O@)S=S#/k!&G,gWQ@l]/O
+%`lPQb=lNRo41)RgbK5jb.iFSm,&:R@5\77^co)'3,(_h[&VdeA(#9VtaXH(4R?oF<NigGK\?.<sn,VT/^qai5"#,t0<Qk)BP7?p%
+%Z4n(>(,Y(T6bk0^B&jd":oY8K:tpZRS9,_T->Tg$#J_"rG)=kAU6%^[,K`.uYEVP(po:Am@/#W(0#PIaAmm"[M)o*pg;M;blKd%A
+%!G9`&6Rf8a8eRgias>:<>MU^cUXUKb\lm;/@FP[qR<S&;i/Wd[fYOP>$?6cqN`@qsMfsq:#(;1,Q'f^Gj?e,H[\ji@fINq8%0ZX;
+%7;[DAEsJZZG\gjQ<*++4fYi`S8hP5Jg&d<gWO9IF%cc.($qu''/Ja"l#:_^a,U>$B/7bPQ(Q>=67<XWUkutPTd#7BVq$(^t9mD&Q
+%ZQ!=f7kkp_-oeR$CFpD=Yd']`#MFa]5>Sa>`.[5pfr_9(.,?ZLMY2A_!T5%'(uI^-VJ3HX#*Y7Y#nRY6QNY&Fs3UHAq"CYk#91<%
+%*d9ZI2mM`k5l@5&!#=UK`QCLfUE\Jd^jXMG@Ga.c,R;e\[;.@WC;$h0%;I5b-"f!fK!hVL5-3(e_g\J5@Y(P#?"g%0D/q-u=&6SS
+%ILdZBi\K5m,tGAIH)VY]Y&U*s]VhMtXHsIaa^8\#dq_")r6cB0TVcel2?L=5"-[6WcLO*kphSt(30kT2>)s*Wk60;$0,2W.I19Lk
+%U[0XAEN4:$ln#bq<BV_Y#I"qE+^3'XM&Kn?@XVRJq(mdX_$#:p`4f3TZPj/%1`\TXXqS4C[l%<j5V<nelgn?--41YqfNSPd4!,p7
+%:M!S2>c&rB;+.L<-k'\maH7R\#)$iaps-Z:4EUqI>V]A3kiu=K3*tQU@5,P!i[S>K&5)[7P7Z`t(U:L$oq]_`b@StnXI"o,K.'ng
+%+tMM)E>u8ElPWdB24:[lQ;9=K#8[]E6GUUeBE==$'3XgHC`0*IT4.YcP"!lDP\F8N,W_s+fk3X5eWe&69Li[RjT.i@,b1Tk!1#dr
+%;[!GlSL);Y`1le+q5(C)9)o63oO/3I![l&D5a>WeWs%U3gr\SbHe]odpI"j;4q2G@'N".3(0J>W%_.%Z0q_\09]Q=.rZ.Ea1:q:P
+%BFS`[9JZ!rL`i_+=LV]SYoKD/g1r\jfDa>:]=HG](/PBiq_dh3Q4_9*hIhT?0+eEi0Ir8I1I@Z;;/";XPqUo]:.]``f"A\:3rheP
+%"m6_/=WkECBZe+#++\9e!`-OhI)QIu6_2i3I;onca`_'HY;CFHA=C-nZ56MY!lM4dg'0=<ZZm#SYY'7ilRL!_^A]*@4ec$`,ZBoW
+%`>'WAD$>9>llH0D\Iq($G(U7gKXE/;a=&/d+U.tk`(91$h?,->)jg,d-M"UZpNj$s$Y1]Y60ID4:cbQ!ZU-b9N"j_Deh@lp1rF_R
+%fB`dCT'hET+$oHM!;qT!Qn10(F-Wk/.$f!W0NWit&GCe)37<s'VC@rG^0V15c.7lKXS3K`49c;^5Ol$c"3@69e)$fDZVh60!EKG5
+%>DIb1]b^"lUj61dfkk-e"Q^btW9NLXd<&p5cik[($h)bd,X9B*QF$m/S0I?f#D>2],J7qs1ae/\$H\a^=L@-ON7l`nb`Rj%8SM8(
+%@^6nL5V9VF3pHi284'iF<8<X1;cjJ$>YZ'PgV:eA%Yrc\C488p^E6ri<;cC\W@7;^,FJ1HnjA:b;CtYl@>_&=9n:lk8iHd?'TJa!
+%=pp'RFPSimEXP0J493-OA(?rBJt#A3Ys%\JCZdT;G8cFCI+Cb&._C0T%t.3!YI_MJ_+ZF&0TO9U@GOg8Q0`su^39F>\OIbC2a97B
+%XLr<.l=_'@k?c^DSpu8\0Qgn0O6I@"7EUl:i1?T)a@ge[Z5$-RU0^.$H5+0`a#LLOJ-.#WEXcJ>f6<OL1<#slgiFA8]N8E^E)WG7
+%5gsA^B0?Z)SIVChHfM^Q!MT\WoiJuX\=aoR=64e0/D!eQW#2IN[7^P[#.#@s"/e!T;J'<N_M8W+QPrrkkUZg^JP$YmHe?2o*mhZZ
+%CWDTS\4^lh2_r_5$?DK_D53YD$ModS\e/U38LWaS^Zc`al8?Zjf:]V6DHJTmcu^rP3X,KOU&^6Nn>(hnN[PYiZ<2HNc9.?N8nLP-
+%B9E0Dgl0t<3#&97n0hr9JR[UK,:m:bEk%,<4-c#TPj7;O;fMu),[b;+o7==mj)f5Ln-Z?4cXe0VB1BHO#k$+sN-.s+-MCin4<p$o
+%qGuj3K%DoATNr\dlV4uHGMoq"@Jb_/8KT+HpXt2edhcmjeIRjb;Y<,FbuBr5E7Z!I8F9"Q=GZt$UlC"S4Oo'po@1MBP-?8R_bnpq
+%"e*iAa8m:R4$*]`WcHVX[dqSAIcj>\3!N4V7]hfG%#cZl1C;k8@0g!-n<aYJ^dY43Q4LeFA*=_cJce,V0a\aTGs.kaT!nP&"bUNs
+%5KqlBO7JSN:_-2"oi_f`#baNaK3!(48DDiC17BZV="3&/.8k"')>2H*+sVb]cA)B6[^_"SeDb!#F$`&##Y>K,-!mY*@VL#VaX%+d
+%Jk9aV!k\ca7u%V@N9Xf2_2<7Q_\d2LDM,hbJmgd=IE-NH^t4p'E'D#/TO<l,lbd$jbILqH\#uZBbV:6&es/6J2?r=OSj);saN.g\
+%@h/p$0>rL@nB%l<`8Q(%!b?HY7[[A]#VK=^><$Yo/-k.ToHW]7nu1.Ac<l>MgX:'g>Y-KQ_HgO"d&C)+%:e^PrL3A^0kGtSEZtOd
+%Xc>*f)gLpYbT5gLhSo)QRu&`>,pT_"a3@P;$eB`m+EsT4ms>rVR%nUHa@DZ!;RSB)CbAo/gs4Pq"Lh$_#2&2'L!FsHbP![+Pu3Ij
+%OuujE`4c:?8aS8La-o_Sq#V'S\H=UgcI+HFL<3RT"\Y@[?;?kFkr#ro6*#9)O=TQ$$:!Qg4[MH@pro/bU%\Rc>uLf:7$jb[eq-)h
+%SbX,tiYKGD#Ee23q-*neBF&SBN-T[!&bhd9*E`EWrdCD)SEd.*"<_NZhuKMR`W/J*^O0)in7lWb#S`f\FTf10Wh=lui^u07edXef
+%GYS)2-GZYEh"WcU_.I)>$hOk!p#M-l/W(\6&SK-&*3AO$YRP!pLSJTB%tE$u(2TmgP/gnX6Cq;LC:S>),!YT%]<fV)DGsetS>b!j
+%TK]tr%[)mW<P]^UMFCLf<F`E>8:We(gG2G)%+Z*`k]KfA56:nclXA0r6E>idFG@?F@1j^,Y1eJsR/*D\&hlD>_buRfqZD(\pF[S8
+%E6T?Vh?[A7Jbt,bI3-KjNH;tHO."g@k](!]*)W3Y6eE4G0Q3a6^7l6/KVc")]YiKXaEIQO\W$hWAHok*UKbNPr;(O@"h[@M5`^%P
+%FpK4OM+,"J!?,<)o?]&!i9#gJp<6nKafB8?BCao4cQIEPmsfsGDm[=6?lF:HLSU^+W^k$1"/k`Q37qd=E##5CN9Ge'M!jH1Q'ffL
+%Bub-[Ya`mUe`iMiO>)</k8P_9#4M]G0gH)uNg3l%$b3\u5j?-@fVe%@lHF:?T(tFlB0T6/UM2rRh?/%+/AuH4!'dAtArEpR`ft18
+%.0-sq"mg#p#]!C.K[_6,0,+P@e7HJ\kN?dW@)&'k$,s]dF>((.ci'sN^:YnF]r`O7-K;EUs)U[%l8$9Md^N/uH(3r%i";cnd(mQA
+%`OuZ#LV74MkL&sf`N)./UM@*%&oeCrN+KY-o/6kV;4Z#HI2T6<iK%h7YX:@KXU!B\C1=L:jtr.Ba<FQ7MfCco[*=QP.<A`4aR995
+%3L)D.f\KS12qn\9mrbej_chRC8cdCe,ATIVC@5W%T8KfO7YmaR_[EH7)Ou'`#u4W#8/Aq=hRTDN1[Ke_I2q%*UTCi'pc,6o8"OT/
+%H09oekbj`=YW[L5g8qLJaif"&,;u+)?p'9PlGl2ImDtLS.Q0$R\kZ>",K;+ofe0tpZ2hn4@K';J?p8P-5VZjk=kr]F_(ZJ>-<49E
+%g^@tc>-:M%IeON6Z[a,_[u'2QYU9MV=?,XY^V`@l5^j3Np;rfGp"h%_2OM6oVf)4J`R@1fa,J`-#0pGYVLVgeniIYV/[@X#cK-fr
+%eIf[,@h8K&bnFKYObG]V3c]]OPBg=i"N(0=Z3Q!^O3r'=<3b.ok6h)j;H?d&Us+n_^nRi+R?VGb(B^7?/DoN]01/`VlWlc,q$%1l
+%SZ*)!Yt<JHX^H&357@8]0\Y7A("D#PYIiWZA!kj>A9b)=!,H(^hs6<F:eB,J[^mF/7WL]88&RjV3D?3RrCbmcLeCD6l-%,,:k=YO
+%+MQF1%1i()@ta*+DBPJl%<T'8"lQa%mto8_E`"K/NF1N?dU3Y`+9O\D=FhJN>*6R7/8Lp,0L^KN&E^Nl\#L4.:tL&R5>[FOS-E#!
+%7d]cJgSUl73V;FSObeUDIVeimXFL:2hs,:)JQX'q2FDUpa^urr?(59AbN-mi&=0IpCHt."rrX+!C1Ri9bg;a./bVFd'7_Oi@/RpT
+%n-8a#O)+B>N_9msQs#[#]SN5%Z#@.u#]j+W9T2Fm>.P[MU$Qb+.#sJrD,Ab9",;?"kG&Q(77<s6hE^L>$20(SOc"FSA6<CB/uS)C
+%>E0i`TV<gp],[(bbKF@UL_.+"oM`R5iQTQRH'2rue'Lo/R#JA-i`jGP/LfV#j>!1,Qo(-U)#q'%qWCo-.]<-\DGoC?U!.9`:I`W8
+%A3I!P`a+W,fWh_:jVB;MHhqTuSZf6/'K&C?=%3_O6KeIZ?5^RMAddAgOscMG`jm%sLkOLB,dLA'B!>k6E@n,`bXnogFnL^Od#G)[
+%55X^J;+D9kFQ5iC=:q@+e>97#`qU@B%RuB'<-amC$=qrVNo<-t7=WL^[n(Me*T]eiTQC@6LpHdK35FF#8%n/ke(p09d&+HDn:r#l
+%7f<9EQZ4.R9g&J@TC9ra5gt?a2*@9l^u,4qkBn%:=6]r=JmVPqFgY7u-9oQkPS2W/U1V#;bKVOd_FcC1iQ.Rc$@CZ#=t+CEN7WS]
+%q"!gtYcn<jBli>;+qujui,U&FJcqnZ,R(FYO:P0CKY/h=1--aBJL,_3IsmQnTRNIM.D9;)YET?";M`KnmD\<m,E1"aR8ai+UGLA+
+%[^>6n(THRLK*Q#6N-ri>L#X[T"/H1d[ur#6nlrL1Sdm!sVLpg$O%no1*fl9/P\cs!h.Qj,n!fBt(iX/a#7S>2bbP_\,+"'V@M/!r
+%s+%>ef-'L"Lc\1<"=FtRWB;qmXk)R=$t(8mO&pS("$3IQXH:"IME<&sRE>/M[-7!pM],^2XVj,pVP$nGT7cJ2nj8^Q(U&@"Hp6mi
+%UFDV)(F(mEnQ3M:`1L2Uj=2CPJOm[]j7YnBb_TNQ\2DOI-Sl*;DV#9Of&B8Gh5MMU_m<dSN7S7#O:s3>\%F6q'R[,;Sq9L(P`XBY
+%"rY3[.?P8.W[""$0tdhG<WjPJ<dV%T*H\[t!?&#?YHS1E6Pltjs.R1/Qk17/2[&ea]#qE7X&B)W$$%JLgWJH4@/t))2I)Z))^&lW
+%&EJCe,<+5;Mpj]%Pj'dm1'*B.CFXC$Gk;E9VP:*%,&_nTOQSZf9Yc%A`<lc0c8eerE2%87l&IiJ;tJCR.i8sI^LR8Ha7QS8I^JlT
+%js0m4QjZV\VU=_sRDV_rh'0SN7l%tn4D8n&OV9lp8C$#3"`Yj-LI]BS=a:,<UQSZk'SjR^UG,PF3ndmKj^lkU93kj9T&fC'7>KIP
+%LiICY.QgSphSH75#%o4P/QloB<8biKF7:H"@_WqHVe78kg>.'F;s"?YqKGqiR:@qCpjLZ'oX6<gp?M"Y6@df(H?pg3nf)QDP1%<6
+%=!ja[2Tu2k+NUbiEs@dCs!/$(L:^o'=!fSk2e**jHQ=U>jSFogcXWZ!9M!/UCuCb#2Y>r)nUDV[otPJf:X]C<_m:3[`&Z/Nc7Nbs
+%bX&N(6t=c4ie#U+CP+Xc3.$*;@O$]%&NRK<XIUnp7f&u.4%X:.%28gHf"RWY%D(k:(e#+Rk`3CCAUK:$O;V5`;ZGq-jgMVVkr%t_
+%kBAUYpO<`NHDJ3j7fG)nc_"RR5Qq"Di3CIU8(^>t/OM6*r6Jl+V75en"05XKVTHa0f;6t=5'`V=.lP%$<FmXO%ht8[9b&srbCE8,
+%YG1=IVeW3`EWTUB1$)Q_GiRaf04e5gA<*'m(<g<(qOM/GPqL]T&Pul@2>f\GFfGE4pt1A,[gCW4@HiiV]B0"GG,:Zi%7iQECfRp'
+%rDPHF>!5=\B;lJm!d:o)_`K9XCKV`pd6JJW`**'K>=o$t-3%5#:,O"2=4bu4E1CTZ?h,7qqrJ41%aYR<f^nZ[fpVP+!8p_i8'j-k
+%-]C(Es"on;'E//\fG,1?0>0rl5YoMeY!.J:pIf95gOABupcs]b`uo3L#-W5S'.C9:8PAe>mKe+YX>qrdbD^nL2<14T2Ol+4Vk:Tp
+%$9'.+;BGT.qUZ!*?rSekaU;?,EO`m,6?m<>VR"e$_8/$F9O%*N(hCnq)NS@IPI8Wp&/_%h\dtZ@,L9gVSMX-Kj^=Z,qph$:rJNY8
+%K=1hOg[;UBK0LFUEI^RKg92)&lDP2VZ;)Il5^!RofWd5)%/5g0Wo]jS$W'>&'AQ]ak.s^LFACRQ?<G"ue,qCp\S7PuDR*Se+MTPE
+%n"BtXe"ik;l/,@$=#Lrc0b*j1+'O8gYfser#'7&VA8&&QA?j=F8-A=-T2T_Q4S.\Xqdp'XHEo7q<FDg<57*aV.O07#Ms?N`WJ&=P
+%h/=0:.`e-ONtHPprf9@aBGXo'/pSc-YHVVPO/QtP$DmbKbET#q(5'UF=JD/amUP!:NboGk7ob^uQ++(qQ^SgkqGe1ln$"_JdH;J-
+%G5V7@mTGUMcD27=URG&7DDs9*('KCQgY3LRJh*XJ8TlEo>ZY0jTn5;<q^^`odFZXT_+,&(b>hJ80@X,#l1^Pu"PEfh4PH+ki'2fr
+%Y>[(odB?o<elX9CB8fd$^K'r,5!]Wn^8cXKC"d?7?uDQ;V9G_F<%N@$4`]-q%0,,C8+=$O3?0LW5mi-WeD#ETfe%`,oADaj2VsM[
+%G"<'4+&Bg9JG1?WS9].^URJ+9-6Xi/YiN`%%0YTrDi-u<cW=<Y^ps\G1;WMQ"JoWNK<9aLCCnm6g^N7dCY^q2McRkkk*P20mJF,(
+%97s0K[L9$Ff@gug;@@S=bAl5XA@h[NjJj4''J'bF0Y:>C\\1<^a56M7#cm#7!%1le>@;VI6$\0sr9N\J!5]p6$=IdFBp<JCbl`Fa
+%2XP:+aAgFeY_1_YRXj+>8k51WWK_3Z!A,(GUsQCl5^Dhq%&e7E!X[DL>6f%<YGTd'*BC<7`lC.M?IRAo(;otWN6AQq(tFfH6bA;A
+%g"\55r-cEE]T*ep#4hQi8*.6u8HPd"]7\tBEBf_s2:?Vi.W$I9C:HO$(@cO]%A+'E&,e/K+Xq7.GbJqll6%GX^V@.X9s8H<ZKX6X
+%s-f7`eGacQXiZYI1V83C"*uIM4gOe_Ms.B)Y+9PVk^g99Na/jB"2_/FHJ@&;Ej8]V%_'dZ'.B`3&n&%VhtlZ=BqYqq9gBa5g/c&V
+%JV*l-hu>>2>.6Js0UZkkg"S%*PhN"`6!BXZ0aEE=QpY#)RY?QMG_ARq*5nTZ>1@2LC(LQW*n6Y[*^T8GJ,3U0gO9;$`BY+3r?d']
+%JIP9tQ\$:T`\3&k7GI)D>OV2!cmFRp32d4$ql;4JC*tODUeHh3K)9<(K2nh?Jg(38.N^N-4EThaq7M?ig!ZVg`.]"nnoG.i1qI_S
+%RW*drjX?L=3=+&6s.QPe?'aUMkDg:I]97afhol=FE$k7d\B=OHY<eD4ibcc+b+_q`qRW"_B@]ai1Q58sXQW?KTFQude]2t4_ohMG
+%pO$1*\P^!ke%^X>]e+^@BH%*Y*+?W)DWkiqY-"^T[4?OUQuQ2b_D2"+UC'@qG*"`>DV;-Uh""Jli!cXb6),d^=/-1Jbo#e<K0N,G
+%Q\,%L$bS;p[H=Ora<dib0%Up&(-PnRa<Q%%\ncF?cG?,NC[h_K)C!a7!QdTiP;HK'WE9A\VdN@l'Vs5(5Np(P.^i$8Vt.)i:\ms2
+%>7:<VVj"&t'f.3uWIReP7ffT'<kt0fO2XKn75KCaoTH&a(OKtsq-P2:F(]cW\kl@bNa+d%cQ2r0cY\kH[t=qk+rCj6i$#Z1=B8-!
+%>DOl)=9Wu"$3sqX[d_lJ$S]Ga`#)=(_&YrA'9*urMt0#?q[a>,K\cgd+eK<r==Lda2NXMg#5Wc>qb=k][]Kc<f(E39XDZIg[j%(h
+%gFLe#e4j+9ep+om`XuW1FFAO(!!:HI)TS@b&Xk&t1(g1F[A&&U\f&SOrs@b]!(IJSOA:bC(A<Mm(hF[<`^Y)l1_b-!L7.YmDmX%C
+%B=]oF_XTFJ<c?0_\Z`h->YW2.,;%k"@Rn7:WIsboJ8/3sV<"CMO&V6Ol3FCFKjBg.NNgUTWcVh%,iTbm!ftR.CiC/QWehl4^;.0d
+%C1>8IX,56"%PsRU\3[LP`<fo6T_D`Eo9FC/%$U6gZK,a1[TBE2+:kNVcp38JZ7ZXmZ/FEH'Qc.rhiG$P1qCbAC`ksQRSb#o)leM(
+%;?-SQ1eFBF?`\hV@VR?-]/SQnZLt=N(t?AQ*2U[_cFZ&dJsoLfA]\bE_idMiSR?_pek,Vp:mG[C3.C2[e5Nr_[&4X]I$p0Jr*7d/
+%%%!ZV'YhuP)QG7$hUE7eEtCVj&IK7qe.j9`C!7.i%4pm<kda\YP%4NbBmo>6eiE(-q]IcVWS/r/_7U=;:m=C`KgQB&C9&5Z;VT^Z
+%&X)[\jbi><_0J[Q0Q2dTat5=_B%>2U4fu_o.P'1)%9c+TY:Xmp7J49rG%n12qs/XAF\$IMJP4O;XkW<="_,U6ec\s]/8G8P!`^1=
+%Mt//%R2"b`qZVmk#)GUG%&9OU^Y4-](?2t&P;!."[:daqjT7&;ePG&PLk;gSCP0T(-RTY`U($'`]6FA;=(H5<5kT;/NAR1FCIE5b
+%,$l)'g%$@uoKrjD&_e.9>9AK)O0Ng;%12/$ONRhNQPcl>&e?@_'S=QJaNmBXa<4q@a:[M*W;VCuA(]ujpo]0Q+TfYO*.K&MHMp]u
+%@H.C^r>8aVj*oW&NidMM3%h1A^o4AB7-5rG*j.(tmP9"ML/j#/AF98Ep>=K=P*Q*gDqE\YaOqd[J!C)jXf]qC[[@g,ld5sAAp`@]
+%[0IS%b*g8sWj]VsqO?"ZPYXGt0n/KV*4[<mc/tZFrD,Yi%M)KDLG^oV7;hK#[Zprt"hRuZlIK*V'eH=biAQVIeg`"/9)S`nM5%+%
+%45`3e<Yo`tL9'/r"r?\(I#RQ?SnuRV5:;A)"+=RV)F7l=6H/+)N6Ek75aHK1=/:@,"+,*8AO_kYK@Jn,7GH<#FX'OB:mXnVQ@4Ud
+%#&?*:kH&lLXii=erKgi[RanZ"F0RbaOB0C+Q@#DAG(!KH8id7D6Po5Z>MQh9?<CCJl8[Q.`;*DW1pMKgYUno,$M#kS76lFcTP8GQ
+%[`!)M\*=L$%abAi^rls+2lWZJf549)iO[9j3a_VQ24VhFZOE`UTLks[.+@Vd;XpoJ/jPjuBZ?-hAbp21GpT;p75n:KX;Y6j1o"-@
+%![k*?;AH'%8XJ_b1>iM*In(tSQ]b[Y5UHBthV4Klnn."@Oci?u4f"*(g"!KI3l@d:(LJ<gA@cZlY%7G/s4"aLXsM82-2%K)*Vtft
+%8p4-5=d<>Pr'NNN#I9CFL?3-U@2K+BLt9YY9bJH:%f#b#Lfc/OZM$JKRbN>3TQkUiG+PY6WiXG>>S1m*24VjMq:(QQXJ4K?G`)d3
+%!@G:#C1l'q]j\97/ma)F/Vi:8I`:3N]<HXtf3,pn9_HOgfX\lu%-+nn8%u\?%rUHpi/s83;)U>9-f)-)(AYrp(_f\Qnl?\;B%\VC
+%bsa`HXlMo#qk*$gf`ErLQ58ihnkoJPBS<!6+#bp,cmNl>G?%N9p[Ca,rR6&jW*!1TFLjNrqo3Y&Cbb7J#O&QM$d,N^6Zg/q=l,[M
+%fk(MP@65eI9&o6\IB4Oa^26c`br_9bc5<$-<8W]PX#dnBaT>79!IjjDYrB3DR'"CS+K7JPGi[PtRC;>DTq!ZD"*Eo[^u]`,DHPZP
+%N6JkW9WK!r^s2nLXR/FVc0@+fBT;ajJ<'HCm:9!RI:rX'J@^S9/l`DGR5Cla+_Gepfk=?V6)`JdY@9%_o$G@Skl5AiP#?ttR.,N)
+%fgEg)FUI7/rV$!aQSDQTUC.8Rm=h)tm=1%?/OQ3<Ep+P1bR@f!^ffEo;.uQ75?-M=I2+'o,8SM2I@fQ_Q00?a)A]Qlf_B9H8J7N/
+%DB)UL9dU1&bqRg"Ynq"RdK1fq$Z9Vca@e*,6;225)k\-=):YkMrX@5Q(q6`"SEl<LaQBbAoAnT%);K+q`uIm>FKmgQddA'PDt5;'
+%)O!-ZZ>/LaA6'%8%:iKtg]O%QSZIBq?Bk*XX;SS2STUS/6jM9/RSKuk,%ENR7J5Hke;uc4k#Zdan&ND^?U-FS,=hj.=,DaX.KK:e
+%WM=T279Eu/'!,K0!C9uUp#YGVI^n4%B-$&iH0fF6l[c84cI,fOoj4Kc-/9g_nC+X<5u!*D^KchiA]8oq\N3VJ/Sk1H@_S.L1sB/,
+%,>`O[_BR)`)0IAu,n*$UCA183jDutaT7Y/bN&W`8^:i=b^sqa^!_*=;2;o'aMlAYLDkop0`hMuq(o>FI_[aT:?SW.4PV?r8r&3D<
+%Q>IuW+I#'lYi_7t0]$pJMXp('N_O75bVaB!gsT*B?s7=HC-\-f\8.qejlp6&pokf(QR;hs;Op=T^jMI6@Ia88HX&^P)(D_[GDATe
+%a*RZ1h+,mLn;`A$(;(/fQKgUP3J1B=5^u;@G6*.#H))c,fF49;-Lu^cj3(!?87XTgat35'b[\=*jslW=VSsDUS8J@%1=oa_5q94R
+%Km^L.">!?7!g[+F"=tom*(en5'r9!:]OK[\["@ePjTPlb'GiONLu^52T_gDuq".Bi'EERg*lUks*BmFQ6<Wf*lh$$gq_<NEff.o[
+%"B._!bJ<?U:5H:#KX2eJ>f&8BC)#]:=l7@=>r1eRe)-<Y#.BM;_f"0LKt>#^ccF"YH1K(8T5W6>EVY`m]8pTnr%dNEKG-PaPb^\C
+%_H;4b)28AXXhsG/b$]OH^9Y$d.o-QPVECsp8'&iTf70lpX3C)Bn6kZW.-]Nlgu9pJVsTV.(&#*RHFUS"dRfk_1\m#WUcH20[mfjK
+%9%5G<_7Ja8NeIiaK/ng]XH@%-L<hL*Uorn-VSB[nE_OeZV%nYeFVhiuao9VZ>L47(*Y]%%Y)7/+XL</7fD0.N[T$[.mF2(Rrg)9O
+%do#m/WW^`Gh#SWA1f&c5A%t$^DRa)!YuN9$"nY']NeQ"bP(\Rf!u#')%OoZ1)S>8TA5g>*<<;lTL`h;!(OUf@2aWD03B_?b+"?+_
+%0hLG\AH<jeX?qp3=_%ef&u:&.r>%NV?!HGl79F\\"s2aL!^&moha0_]!A`g=Z0c[MJ-VN#/`8)VVXBT.1g?$DY99S*"<#s+aEnfJ
+%i:o'[!;@`"dni:lK+p$N!@^-l>BkS,O4>-Gn8]W<1sqltQ=_(m55^^_@\*[%Kn$YXRt1"5/HXoN>m,8q/OK`mJg($4^A?HJqnU=,
+%,ikdj(-idM]80bG$!*490/B0JjqP@-"CE=f>/^:*Fs@L@8IqD@[=Y?2\\K9bN4a%_)&@-$Y`<$Xj:i'$Td+50**IAtCt+/Ep?#Ka
+%Z31RR'!Dk^lCg16db&Ln/mpZH(YEfUU/5P)5ncMF1Z6oMK,.?0>`e@]]%-]$qIibV@Q[%XE%Q!PjYMfW]MqoH@oHrB##kJuf.Z7^
+%cUbSC!-I%3KtRWTc[\jfmK+#H>"gH3pVe^l,Te4/$.E_^6hH8laO*](=^FWr)],\9V-#q.ik5_^hC&-FY0;/Y\B"oCGssC]"r%F.
+%KnA[h16JZ!8h.UfN-s2R6BTXQJJk5NB4.P3%fqaF:dX+U&-CIh=+a'aRfmt=7(s@)EX%nHn951`JG?q5AHXP<YVCd^T+V\Oo,5KR
+%:djpOEhBHAO<TUXh<mp.2tkHQB"--h&(iqt!5Y.7i,SCWSh(%Ej3Gp\qua0+2[tAB06au+)Y7'qa/kqt'FCl-@B&JQdW<fm4`M/B
+%W6G[i6IW<YW"'Heg'%X#O^Ldg\PSb%3d^,Wjeq>H+(DL2*R,DHT[,fSc4MAl!=rF]I++,Jp$lUt3N)G0K5.P(;e'^%3B2T]=B;k5
+%@2X7fjT(jqkdh+H3*A+N!\t2@+p%#nE(QbiC^"r,"^!F\<4=3Ip#/Vf5QY+2hPK^YL#"%$I+SO]62/nE1MXr^5&cUq4?Q6p;bN](
+%nYas^F86/-)>K>8R)kh2cbUo3.)YI4E;s;+R:Hm%eT<^dVoFqZm:GgfAWMRm2RD*)5./qgikD^7U'I(0mVk[l,kDcEZ/OtO5e8Q`
+%)a>;Tb?0'I>THs5O%lbYFR7c,H/T@UParL3bNt?^WP@,1i%a6X-?)s<AJ%e?]_N$ipoO?E\L9fE=TF[rc6-L*SpO!QV<A*f]AOJ'
+%8=&l=5=[sflh1^TY)Y3Z$6hr,OC;o-H'722L*jf&>UPHq+oE5$=SbsZ59`@[@(3p5mC:J&Pe@F^<#5T'kfI^s!0_pA(2rf7DE#f_
+%*&:*#G^gL@4-+NrgN.^BOT(_cogYrLPm/`$/Rp1**[1VpnU?-mk1XWHCBTpN3YmgV,,_!Mn*o3gg#NQjl1!4K0UsnrV,k@FXDSp'
+%H'&[#2>&JUnp=-tojo/U3.$b#^!6V3L7H)T$crRjmA;6M2[b^2XJ]Rm`55_d@4!",a]B-/-[@qn2n,mBGi`XfI/q9U;*Q**`;4NK
+%?FUD.!1+RVHdP'?%+<D*GTG7W'48ZJl16,o=]=iN_^WA3O8IG4pG.NQo<rZHBW>TF@8o!mE+]uu(%`cVeY0(Bb3I>s4$A3FD($K!
+%aj1t[Fg&0o7pRUN>.se)eAo\tApOqP//^5U_+=DokQXZ_K??W_!m#r.'H;st,D5`i*sk<AN,Jpe&a9^Mn2p9S,u?4RC)V\a*`PAV
+%:F$1%"&-Y!=[7j_L5q\]gr1>^4i3Xre=$bIqt:;i,>+igIPUVPQW<kSb4n(Wl.Hs(+S#>'^g\%W:,<MIJJ]Nrhic6aN5?):J%f<p
+%<.NduMD2iQrSV\%WfiX/D9?B#Hn^juEI(d@W_KrEB%\A.NP.Qi//)6*$hdNg0+4^1%9@N9r!8hI3^9[^#3,2MFgDIiC-HE8L-]<$
+%!qs<o'hiNlEEd(d:1Bb'j!5c6C.sODGed_=cM$r5L/b)6rc%4&n9-7LnaHU]@h82>F+Wn(Upfa%qZ4>eb5,Yrl6AO3e-RH>ii<&C
+%=`<2[V5?^$.h%C^$]+e"ku(/-\9R,l[4O&-O?2LI;V,(>^6(WADbQ=\G7rik;Jp]A%/b4Z@GXKjQ?Au^W(EU`1gETo@i!uak;i_F
+%T(<ArJ2Aia$K0/HZ/.+RVCm5c$rTm:/0MA#bFi%<5<b&!2tglMS\a?&^!kjDD_0bINoZYfo'hBtH)u3ibRY:k(%8?]><(d4%kTG9
+%WM4@(_f(+4[J$?\b@MX<F9Gt'XIaLu#uU6s=.K#VP/W`jM\a/MpZB-1A#'(V#W"U#Q+$V'n)#kQ(lHG<GFJBLk2uej(%;6Kf()Lb
+%_COj;D=_e1N!f#g(+XYJ)dr-pVVB1#f'@TG/dX0Qbt"Fi!ktiod!Hc*Ftmn_S<eobb],Pm=.mQ$5N;;N3VEqtk8t$:3*e)24omB>
+%C88kYP:9BOpVf"dFV,<":MQBYQ.mM7%=U=ZGODTg`d5DePV>Xi^,DcYZXpUsaGc&>hAJ`)E!ck1jWk"cQJqXD!dMJ670'79=]N(+
+%*FTSjq*=]b-3:>7V!WKo%r##cNI;-d1Ou_D/_6+g["<7!MVIXQWgd"-6aHI`>q2;U-f8V*'#.ah6u!gVQn&FMDU,3H9ds3(UFbT1
+%k[4QSf4bEg'YoXOn9sJXH.HK>PR;YhD/*Zr'/(M-/8;<q320U/]VnQ[H2Bs\?P<t%\U$OF"4a50+e(MHcD[0go=epe:ugG;[^M7A
+%r`1-:."K"=h2*MPZX;+rd%o7knA7s^,91"n80>s"go0E>Y,*p]be0DQ89`s6&7/t>(UMS5,-^bHbt_%VRiNk?nkhXkNR_lH=s`*g
+%_"A%,<-AX&TQpqLY'XppA's(V*BDCWe:Re"Z'GT;"3oBXi9H)>\LZ=cE&8PJ!Zp4Xan*RVAm5lA_$Sb?,A>rFVG6:NE$l^I!r`MQ
+%gnPA9B<[=(E(=E%"]Y)X!^^d7j[5V*h<KBt"Vn8Q;Ob&k7,fCHg"J'e34eQ5AZb@OaZ;Ia4VQTjc<f*5_3V(L!Zq5d*';Q[Bt;`h
+%*OniqNO<$&&&CP1p-Si`d8p)R*d`r;b2sq7k;A.'Tc+Gr4BO@3d^OL+L\.`1]RHMfFiSC(HjL3s#d!""FmBY>P6Z9@b9<t.c'KBG
+%e>4:.b-]m"DWQkWiT=;8h4*06L!^lHc\)hEdC]FlV>Cn=A*M;AXAV1Qrc!9[grSZFJ4C\3SUli,%mY]TZZE4=TZd/M'3)bncA5ZX
+%)=I!?Yg6QJ@%)WgQ.0<Bo;(D-1o[9>\?/-[L(RkZLe6b9D=Rd*2(@g2!NV6*^K:OLAL;X0C<Ol+_B9QPb&5qe]XXDF+g$Es#J&;a
+%3\5VjlG-"Do*-6rG3oL/`:Bu+ql&XM\'IXpQ5Vp%]1l-T\b0P=B/Mot(\-6%@@[YY>J"&/fdLiUD)Fr&@jje+a5-b0VIB%\R1W&h
+%(*-eg>r%V"q)2V?qODVJBX!t%b7fFZfMfFFj(AOXF$u)kSrS4KoeqHsQPI5NV,kX7Ihenh3bL.cUUg.TdW5_m`<*&lj8KH5\9IS#
+%M`h):Mp1!q+^?S_/URPul\Nh`A4,I`iPq)b5%KM('6BR-j=Zu3)6TW*c!^=R(:eNY,u6(>>3jX0%D^T#ac6,7\!d3!iR^`g43\n>
+%CcDWca.6h(a1?IPT'TAVE;JDpKPN=pjlH&n7?<T)&=YUP:G-D.D59[N*U2D?f5JmF6>"U!E9:jXr,D\+NAGpPCa<h/RHGP#o1rHY
+%,YZ3753K:BJgMW'JNas@@Lk1+i%&DYl"RUt8HMhd,Tc:2jNk'F_^lp]S6#>Z0<d*s%mWb3mc?9XE3VpQB3n$sA3UbnO)K>N.8Jhn
+%X6V?JfOl.;]4kFl(#\E$IB7oiSi42UMjMR]lNR!A,;-ETUG8L*[\J**C%$rtV#;hsKoqnAG%uL6DY:&\F=>)P!ou.^3]95fQEgJo
+%mgh-8jF84E-Yltgjm6d>mK[.ph%p+Wc!K:Z46+d^2C7A^/`r1#S!'(W?cIij%<BG"c[<Pq@UT#ccUP(h=a-rpD,7!',@ed;(jF!$
+%;Iu*Erc;2c4AP[]msOM8=IqP#E:bL]-\7s3+=cr24,1Z#T>3kqcW`dEhI#\)$=kp%8.AC\fXi=-Gb+4,TZ1OkJGR*&0kq_)5s0es
+%.nF11E*o1f?Qg-Nqt`n\G:^K7(o;@9,4T`.)6ukM21bR$kn]kNrBMhuh!BFnl%*K/JZs6qjXiS#pu-BU/TUZ#V@g5m6&dL:@Xobl
+%^!6FeS?/B.1]VHTL&ugKJ/O7P&WB.1h\\lSV,MMoBNSF\bJ[k<2-,I6YWpqpi$kVnluCkXfY$_Pg%p`EB5k1Eo'JVh0`DuW.,P*(
+%QP6RXT>AG"]q61c$4?n64iYP_W*I%lL$oE,^YSgEUi/30kqe</97sX%HF^q&U-FTrK.Du!3%4>p)@'0qQ>[e;jQ*9-!iN"qo1=#G
+%=3B-mh@MJkN_p<hs-cPI*Z5g`-t><3a$457qpN[!2*]>=l8$d7A(p1C3e(:mLEdu-d*`[G;DF=9W^Oen!hN!n:flc=%/c$-0Rk_<
+%0=Nh>C+=`?\.moh7%Cc^5i;^OC?#eq424IK-rU-)Ld#1=7Ie6?PTYs5gE.64Q<8N1""X]B]E2fBJEh,PYg,i]=fP(AS78Dd=UJ94
+%n"A`I$n.LpS]h-/?)J?Z6,fh4@b1ZAZ2QNr$l`Z9DOQ)=Ka6LEJ<G.i-)\k_\:EGS;rD_3<q\S??pq=Ia3Q59$/Ph:@fp7tHN>@_
+%^<"j0Dh*&41/:To"f,qB,AJ:YBrsVTi<!U:R_rB2%*BVsalFFg]3QTge0t#2<(A_JBOFMBND:C:=?k+GR80*#qjIRE.s>L6=MShE
+%br^/eH0&!"b"Y-fDY=>eC[f6WUXcY2gKf>[IBTl$K_.gIApD6Z^h^!A"d*6L+:TmE1Z6Ye'2U8>,6rci5:qrV%X)DE&5\;F9gFFN
+%>tH0U`IGbWZg9ION!2>jGB4@8>T\60Br##c`erfin7's,dmM;c?LDbN>A>5j?qfm*f!"1E#[(e:b4)LBmK0eT4i5P[&28]8!k.K@
+%"F7TZ*sEbuT#'abgo[O@!jt-TK%hWFTWbAN[ganB#p=qqY<eN&4@TZ0gB5bUU3?ZR;+HWjYMeo-hC_+F3HGIL[#&O<M+R-coVU3U
+%/)`3SrHkODZXp`b1S>.->%cpD<WTBOB;lE#FM:)WAjO6=f+-n+g2aFI^gVf6*!"6f7o7gjlIZhF0jK9fV*50+756#cVuW'Rj#2O)
+%=Va"+/RrSH8"4EU_!>N^qbl)&&)0,jV&Q&*'PpCYKVH_]@7%;#D&H)L'OOsH_sji_G8Lqd'gukE^p++1mq^k8;NZCAJ<VO;'8Jc:
+%S-U7A&I"u+JTWNl$Wa6uMBMD3:Kr&R0"9c\&5VAi!n)9(e*<n`3Sf:b@seQjAt(HL;Ll?7mh[dcKFbn1"p+V!S3^\MXHuiSog(h]
+%)rS.HG;(>^a;/3#,0SUI]%#P@\W=@bd<=:JE9sm$BpIJBf96B6]sE5D+se)e9bJE1qo_#9R72%EV^5\<_NF3,W_u>J_R`V)@(Yn"
+%l!+Sbl,e03L3^#",<HAc:D&eQercDHBD5o+fk=LtG`Jb@nTn+Y@VBEpc`scu=$cuM1pb,fH<f6>9@I6$3`%L$Q8=X;,A:+WU:/bU
+%+2^bSW@:_7U.#H*QE(VN%29AXX)S8`HA(U"%_b9F:o!]\#F]].Td&aW7+SWeYAgHNI^tG4)K+,0fnr/<''=Wi"dp/7Qmn^:aCGc^
+%AK?/P!%IZTC&O`!0<.6:oYhRQ312N>FAjO@%aIQhn?@@cMqR_"In)hEqD1h.LDM$<9k?VX[_2NH!]`2iY7DFh6SC\M=mK)CaNBq&
+%a\H'[&r^r!`MSU<CT0'Fg8@rd*0u'eW@eRW(,0A4n=s-UZ+/.=iptDb5*L6'q!3R/NM06oG:FOMD#3hN/Ks:@oab:/%dq1^O:uYZ
+%H&dlK*/XPnqeW*m"@?Od"f_X"Vk>'nGShBm9>0tQY.gWkAe9e_Nu.\@F,K2W6!oJ[4p,--,W14fmJT<NHnam*(9m276NDL^\W>R*
+%[4Ak9Oq/rnPuE[*JE0kUT_atg4H+F'<60b0m.94@>.j+fSB?lMlS4HTE/Qf%h-[Sn_QL@lDIrK9L;,@[1YjoYnE-1_@mfG]o(k9G
+%E6YLp#tD@'`erA@_IJqLL!L;oNqG&^VX1FpbC&9Y`E#H%4RU6WbeBqk+o\!;IB*AJ<ar)6/#>hVArTCP5_-<lrOJP<nM]DMbi.%'
+%eFVMnp;Mk@X-&N`/j-5U*$G"%,X2t<\s=8EqoVXtAFWP5YgeFmO6)Jo#3&XZFG:WhFGBO$jeNk$fj0VXqst52K%fP6^LD"O%uVB4
+%;T[p$V6TQpPLN]6Mgu5B4E:H[q;\p0jID=A=NWIWO[jAKA@X-hjT?(W%Dgf-RPT"oBr$EUG_f!u1>c05ToMo&AMIam1S4$,CXeKE
+%lUT)u4I&T9k'*)I`;CIt<W)i!Zek_)4^'WX>m?k-/q^0)hDD"G!u;u+ih-g9RVWHmbr(V!KQ`OBal6U2^7Qp!h^YZ"SRKcEGNNc6
+%:QFB#*NW`QoI$-EnA]DVA2ZV<M7(YgOd2`hf+j\UQPDb4[e3,[W*e..0>2r3N60$3VqZM(5)\'#;t#UjNmUXT\fgY2eFG87AodLH
+%Ih-.?>"[H@'5?1niep8#U>^Bb]1[)6Y]s)NZEVktTUGI'?!&!a]O:0scFdQQ6#`E7]%l&[[U^Y,EQ:D?FU`hUF3)^>1=<Y`qZLQ2
+%5qM0t%O\@:%!M9\FV<CR25kB0h<d$YSADb!LPL@-&UT3ZC#Kd7DcZ@bKo7MP'o1tt_:ALPW.`%fRV7c#I7r/M`$m>.!.DB+C4-*1
+%e*FY<Nrm`<37_5j<WUKbZq_#D>QSYmRnOJ1DJA:0U)ST4Rg_thT9C3YnT'=&h]Ig56=k*%HnkK@DrC"\Wu#+#G1nuP\$1DF6skb`
+%_V:PmlOLnPFHr2$,/.Al0LCJc0u&DG9FH^C30n!#"\p&&^;JHh/q$tM^<Qi07mR+66E?`mq"tk<!=_%0ksDB$G5C23'4AD=o2asG
+%/RL6mH-=hK]$p_H)>FE&Do&p-<<+r%gi%Ro_8s<ABj)Z[6#O]pG?4g8ecNj>H$d@"H26+j]Ti?k%S!VX+r>)8o?JFG@HflTaBJr&
+%2sq+N(*A;?Ne>s<M&)mrfBK1S^\*\^$hnfed>>K*B^SsH7j;6KM$hsE3+eqlBa02-1n:[Y)Pd0B%b+l)$["*`^dQa=C*C3`j==NO
+%CHWQ-b(>fF1ec10KN^t:VJR[ZZNYIL,D3#hh->en'J4mmGrhon9@MqjjfN$d7AnG[$`N;0'G)s&=/Us.+K#D4p#Q[iMpS($]fGsN
+%K9RSOFBZ?1gF^4;R!N*e2)GSaPLY6PEAo8!pQ*K73I\lb_>\:qWsRSk5;-&9BYd8*DYBDJOm$bL^nb1icCP?%PCB-_T!2@\dN=4^
+%k"_4Qa<[f<7_6j19b%?k@tGpV>:cADQOTNJ0t^E)?i+Bi5Ag+BCsi?Yb5[[?;*+MO&t1Y%;m+jk2+dW)c\>Ra/Dpi7.fnsEJW!G6
+%@Q"M=C`0qR$asfQb65?s]=jrFTV[:%2=OF,P)SbQ#C,ZK@9r@LFI8[/ZPF<nT<(JqYe"%&`jKVGWcc-mbUQl"S%X?aL3WnaAD)EW
+%(jfXJ0Apse4G$e6-g-(=FrTpk!uWXZC_rbhet9c>Q=)YKLca6PR4HAo*S,JMdgRM4UU8eI!m"Rgh!F**"]T,b\LpkkdGj!6g\_)U
+%F/kQ%Fru!I7kC!M>"6VJI:d</(#:1=&+l3#I\)o"\i$:oeA3\s"[8b[Ne++>@;_b'!s-,F^$ELMaX`/XS/p_1P,31?(7[UE72RoV
+%Up/Ci$L^dm/l4XPC#VQOL?\j*"=ZU2[gJH=CW4pb!QKksM(6fAQ,[9BbNGG44E<K";o$h1#@WP#057BfKdEPc_/KUGfEEcgN.BNj
+%UoDi6ACWZN^j;OnRelE4gB:dEdQGftlie0LW7Jn_@W'oc;V1Z8hsL@X0&pF("?+N2:9,f*,k3:in&k5dN!jsF=7"uPen/VrQPS^t
+%ZDXW=]'2f,%n,lLJ4k6B((tQ_!rG7eFW%6aJR*mWo#YRN^cJcu[*nTXdMEi=><q'3V-UJEX,(6dY8:D.5(i1]EIAunKBD^soHf?F
+%Heq'T6kg3:De7@0`cBq?mB)_l8.+:nd^Br&;/GLn#V&%>+!SGG]GJS?8Q'%9@Ks;;1#G=1)I2VmKB3mD^sh[_!SoOU(>+\)!7U1t
+%_8Gk'Q8uI*GRI)."2CLiI&F9CDUIS<b+K+:Enb7^p'5El9%@ksJL&lq/n[ukG0YY;RoW=r/s%>$QH,^R`$8%Zih^"o&DDZ40*gG4
+%bIZ#I0X`3iB,TBnkToOfb?/Y=dgSPF7@h+"W1r2:F]FKMpUo!(o[XG=7C%R>qd5,qF^\:NZ8g::Td<S%?XKh$en!m))$>H`JiPtb
+%h(9"6dEQ^N/o5In2P3)a?b8VUN5(\&eu^S!I:5hV'faM<qDp(Zr>!lKW0hssI$kcVL7@;Df1Sj&jgK1^YUdJ!ej$"-TTYbICU[>+
+%K^N=V``FTq73u2De].jUa1?epln0+72t8j^"%t3V+%h.6m=p.*PXu'oX[oPLqeTb6f4LFC++o>m&q7JL)[eP]c;q_ulpC5MFN5%2
+%k'i?Fm9\P?p65:`]Ss,S!j:'T+"e=:&eHiiY<:,hNSSPiUdZ(EQY17d(e9!Vhtq+pbYFlpq:M`KWOX0A<@cu;CA%h4YcD8<,"Mai
+%=HY9!gKg-1Vr;A6``SUqDlWr&/PeTn1\b@hMT,J]?N.!Ts&X^Kq`k#G5JR6WT7?a-J,&u755hr,oW/#kqSutBnbS%=p\O49ZGuDh
+%GGD25(-e$(kNS[6H\S(JRUGP6aM\$k\t?Kc??,m%9*%'6%VU$JYj+L4Trruqf*4R+?sXB>iR.o&i>s[(Cseqa/qMKQ$&Y+IRE#gB
+%:+I)__/@r8qm88X+_$`H?i#GZm?AU:ZZ@r3oBj,!0%/E0nQ\M]`Qk5JP=49u%l=1R3*L'*HuSDe#8d)V54$Fd<n,<4&@B[\,-nYG
+%-F+GZ-50NW,$0,[Wn_LKb_JbdK'&^,DquE8eS#\U3.r5fgeHUeqAic6E"c*mO(k4!P(U\H2L;Y:C^<h-'!g?g+Z4C!:k\N=e;jo1
+%,qeM/oC(6>YCjOrNhhIuni,de!BmV'i+>8*#\./bTE]AmHuWHW)N"d&+4/D(<A5g/5Q-_5Lo6m;#9Wt_UNgnn[uKK$IMaFj_MJ9U
+%"h*I$5GSZ,K-RL#cpUFkUuMUeUfCbEoLT4%IfNJdLo>a>1=4Sd:u+%[_$)B\.b441Z"isQKSWgY%7ca$Sqf`2[Xj,<!lQJ,"@Yj0
+%PR8\hYlsD4<6`,/QS$8(<cD"e^E>sele,m*@'^]Y*,OX8fF`>,>2ff"D2scIBZd'/#$7=F`rn@uL\0rOV24miY1FTb(0YGS@V;%7
+%[kf:'l0(g+$3b"(")sb1pL]k0gQN)Xe_NYN=$UsQ_R'R"XtS&"a"G_kd/d9`.nC8k@ak/UWUSV-[923na@VJURN\`'K/5\UO_o5)
+%dL-hYCQa"k$V'U&1?4k9@E#(Jod$6\$3pbK6sDAN^Ok'r#=*7cmLlcs,-K=i^m!@.QI,=aG0F57P"t*#g&^]s]j%'sf0_elQq8jR
+%Eq\H.6up+$b>Kd``kmnd=@:'`qlO#8^4I<H+!b/lc9]gl0aS`N(,#A9c1;"k\[.stfI<NG*Fa6YqFD4S(dW<:_9m,PC5^[9.X0m4
+%[iYF+"TCKTd=r3=lW.R!YQ?nnOd'=pEGQ9!e_\phE4cHYMi79!^U%mfU-+)39r#0>:uU,;=")(HBX=8k`3hjp8J+SBBg9Ca-+D8@
+%8&P'FZe.3#SmJaZ@Sm>pNNq+*2EA%a,/d^1AI,5]k7^2;n,feS:.8F"oK3Fd=q9>LRWj>#8J5:dV%/3S95!(<C='8I%k:((Mi[-s
+%T2qcEW`LY/Bs$^MWn8[6ZmJ+KBamM@XT+M1LGD.XmGVM/DDr8b.9gMBW;B/pg0:#!@!Y/q5njr1_UGgN-O%XgMO@2W#GoaBMkk7p
+%eKJBP%2E`-o[b@g=0<"Y/5]-W^n]uFYet^LoQHksob$2(kcSQ>(q@%J2je:hf.I<VEOr\+!PpU-&]$#eLEc@%nWP9bW2ogTURr7<
+%5:r@S.'_q=T,-KP/_tnSk&2G-+9d!^+7MNQ5S6eJ$(b$34J=hj&Kd)Z4Jbob;(fMmLo1@b5=stp/J1[pa8?L0,SKCDpHO$t9(AFc
+%i^S&&,&YmIDbkh,8u1u34idF5&PiZnI[VI6+s%%ZSl1V3dZd#8T-H4=`dVAS<>=qe<95S-aobWO7=7Aenq7),7M\>l:MFC3da-^I
+%C-o^7@[e_Z3"L*k'QH0p[.nMtncS,bY9<Kf!K2-%'Q0LQW_/gION'^$:ob<V=jFVN5T:C]SrsMU\]Y/NR=^M?)2#Sb*;)*/An>mN
+%)%EueiH%%lIg!Ud6kOL0j@Y$I6bpTW4-FOcX:<[%l4Q]5WfIo/$=BBd8F;Ci=^5-s)0,50DZ(]ceoBF9-@&]B,"T=.6)?T*eFY=o
+%5jQH=TGTX3inVWYk[cj#b/"KskP5Lm<ikl#X[e2*(_(%e]qFjdR+(k?qr*KGM7tQiHAt'g"d_X7\+IS+J+1jM1AqE\OT7m,]&_/e
+%H)&SseXo<-W$1j');U`WU)`t6"-M[mTX0fL$)CqRQG*U[mDad3@JsC67-9/QNSj1g>("tsN&r=-;LYGjX)/;Q,teoT,Ia26TB`!n
+%PVIQ)kMT"&-W(sh1d7)kKnpalYM6oSId@P*T<W^%lr!+R^5oU_]'Cbu<-_uSrB]k25E@"CkZFM9@kt!eZg@ohFqj,22"-;Rff#"L
+%I<'nf*@L38elH**n@I)2CO).]:uQt'I,>$M/<0Uka!U^9iT5oTdN5[Rq&EuegcS@B<\MWgY4dMQPTkR>2"W61W,hu;"PGdc=-`Q7
+%$H@DBY=u#<*4b7!d4=JVR/<R"3<h.=^u\bJ1,&?mSg;EVgYj>[iM51C&@PA4N%0C.R`.`[J*%orQk9ek8Gp43;T^KL+!jT:hsgg@
+%'`mKB"R"p?[QC4>I1DcYWVPVcD`l(UJ1#p'7LiTN^V_>X"2]p>$hrH/]idNZR'_pV%Og7f`X#@E.,<N.:rLiF$m2ir\@$\i&Pj<5
+%4DcD7cut!br_/N5gs'<qHU.[.Rq+WuVt&,[K-EKmeFBoBa$]_7MKmi+jCqh\LDD-^ib?;n%pGGbZp?DY:Re5/csGh-'amGmD;=]h
+%`QPA(9SbsJMDUA[iJ]TX;g$="c'rS9AtraY7DsH:%2,g<VdQa.#Qco-=W[9_($oeE,f1V/[D4eJ]lNP3T_HENkfZ=*:V-<`l1aeF
+%2irmkTTdaOSjO%eM(%A9DFRG!*o2,f;2!HuH:+ML%GJ`S4-2S(mgG,L:-)uE'pg,C;^;mGK'dYU+BiH$cRN4*O7L3P*SGd!5c-NH
+%4Zcc`fE.X@1rR!jXh[@om)*n1-DM:,-=n02i`nCJ8jE](*fSF9^3@mjU@BVj4'GHn+?X-HpTlYH^t'@)fDY6i7>ru6,t,nPJ9>@4
+%r@+ZdVjIX;fIXp]^#/t_@K9mRf5'SAp)Wd.#RONPBd?-c&*\Z`lqKi*/(h:.PDH*%OJY$?ri1M#WJ8gA[7qmLGLo/YPTOL%>5I4F
+%iJ572n3"X?cbtbtXKQ"Mfr\6?@="(c3'$c^7ZlX<3f<RfenC0CE#e#,4rO<ae^_Zr5g6T=qcP3<Ai[2Qm@b(g,b[KPRNse#Fn#O!
+%UVPd37W1_qA!kK@q`[G*DKD!&]4pE.JEl7)1uSWEJ`^fHV<&pfB"oT@>AI1=ccq9bL'@):3E]J\qI!1P6kS$D^%M<8^rmuKBpuT4
+%Y<NZOEPYu4dVYKi`A]-M?3`r\A&m`RIYpQlbEKOp"<\jTJ#EUm>*M:g*oJp^\tq&Em)K7R(EA==M!K<F(hqXZA34M:N9)IX/RIXL
+%rZjQf9aMQ=NK/X42eu[6@s2m:'t;TO#C:GMMr,@bWi;!7m7A!bShRCFATaOEPC?Klnk@a(p)P@N'+a^2H:N6Cm,a#)e&;^F5f&X&
+%!%PJm/-F3b^[i"VDB03qUmpR![!SeKI0\h*Gj5FAV\;gCj;bZAPgB]7qi!OfNJTnc.<@7@Hdmh,lU9hFV;l8nreV8E=XJkdG:H`d
+%QAQKq+#J!&c%"AY+6a#\f:mQoXWJ7nf-Ffj%n':0^2.F-CDMBK]<4Y9)1.EWe0hfC.N^)'hOKGB<lG3TeXSEYU$En!P>N&B?q8]0
+%)W*jcCFq^*`We4!I,T>@>6df#2>;>"@62=X-lYAf=NAu*pr,bP,V%Y<<kuDtCp?7!JEO!:6hA^A)^\Ia.T\q.9dl<;#4O%F['It#
+%;sp3`:@gSc2g?b[kWZS.C0JU"it%V*#31E]!lkr%?0mS5_/R*N7raC<r@uoV4W2]6$U:"ZOs^ioDCA46I>]0cSQ=;#YpOhmkgLW%
+%@!O+\nb$a"aU7O1Om<t([5ps9Z*,_r63J9@i=D&f7)/Y=Hi3)sc?1Qq.F]"9E$pI%`KK,d9f0UV;'+Q%G'X1:'jVGE-+F1>f`j]A
+%WXr#SH)QbpnBKE?3>mgrbG&;<`ABQiKcsT9"gZ\)&+EtJT$:r@"MAhhod!f"s(nsLCm&\`m0EZo2mJeWmY)dl$h9+3+,X7poVOU-
+%"kEalgfDI8-b)*u591@7'?,?bM$k@odj&8XbY-et);PP)0*O_BQ8Dh@O;l@s'g+I4]rD+8?mD]gg+Sm#aVHS5U/:2%5A2:t&m1gh
+%mNa6u/CjZ`?Flb3,>&)M/UbT)0bt#U?n)VYj]F%:P')(*$'P+*Jf6(SS9#b8d`9lfBg!4K'Q?]d=FV1TalrO'%.C=sE'=qDc8PcN
+%JA]2Z?AA[Dg%YutPQIH:!2ulM#*P'AEZ*0p/GHu8BRH-6&<RN-ZTUU[XMCA2L8^3\ZtjZUNY:h<VEpA=IJ)"1Ch#[H0q!XjjCmkr
+%,+s[T'N>Sb0A)53=YFIQ$A.raU?.teO;^*;b=.3tXh9T*L885@&"q-CE3%on3j"[>Jn8De)SWJ6[r$b635bs42NVVq=s@>+=nXYU
+%G8C7nKOnt-`e(U-8L[?j=,[mGC^8].$CZ*qYeu@R=L"P>iu%"c"7aWa"?(8^^Uo<s!@?BD(9$.t7tU=]G/iq5TP["j\F,;eTIsLB
+%0C5CP0&)kXa/@24RVq[$Lp6';?up9gNE<oe%'PYGWt5:N+bP@p=g,9'j'nnUp<(+Z5)[Z<==pgN&\9h,\G;+4>C_;Dpe!Js4%/?2
+%gQN_&C,`cP=)1BVTk,Cj<22[ZktfX9D'0$JX37LA)>+CGLcMMahZ-9OAm-mrlFnBD:=s#'[5?!0Z4uH6j?Q%n,iApteT!9F2hGFQ
+%C,Lb29I/8JgXuC.RC<k]`mM1M"'0@8e1\2t()P%BY)oQ^q6@PSV&U*PW8T6EjN.NH([Z+sZTG["0hMX/P!.\E`Q"FIoLT6[7/D!r
+%T+N::T`qdTA-T5hLSa10c%70-,<.XB9H!JNB=Ud^+X=DS1e+@%W#oEkE#"&nb*=WtdS0l"2c[(c\!'$7doh['XN-/dIuJnc@+:<5
+%56T*!4A&gGkW'tS=I$IL7g8*8dOhb5@%YUnc2u\Tlnk[PZhTboKc3lMAkuftYT#/gbBJB6=5[fof1XiJ5nt%\;`"!'TV)nd;YNFm
+%UZjGTYtGFoL\"X=K$2Hgq`$FL.[e#Io:4Dq:r/B<.E[6+>8r"MI*@Oj8k`jTV8H^%IVp`oYaeO\?@c.V.4;$Ea&]1-b[sXl\)9W0
+%5TlO\i.;`mr<VaZ-9r15KDLV%+*CK*J[d=n"FX.kiW,U/P8sscfR;,oM3^%b*<VD0&A<"Ba3jd[#jOMROqKF%l/d]d*J;m;M.?T-
+%]#.P4=E./sKs"O?5SCDR\g]l1ViOl>Z%=[M'\&1;aJ>n%JW$b6,Pe$AFh3#P+MZA/N05aj_)Q)g#K`rp$^H+snH72ukDmb>V<cj;
+%lcIq+AkGYbKWJq2hSlQ"8RH1%k@eKp6T2B))i;r6@Nf3idp4Fh2Mg#(&F0>dqDK8bUsl(A#uV1&5Vg'(7b"*$I'@KHkPT(QZX*iO
+%7^fZ"^%i2Mr<G3QJ_!49OU+_P1iF<]r7'K?kYD,.*\d]?M@e-la:u#R41SHSqkS_#AiQi-GYg>2H4-[>=9bK7\P0,+f>"f2*'.NP
+%Z[sn4@B9cthdHmX4Pljkme5ecf%)E/<r)QmMFFbtaR3]g\n7WJ78iQ5r.#K:H<M`A5]dX?QVhG.m++un,hU`c$!*DP5CD$ih6a8d
+%'l;DA3C)Fg[@EfbkS$@J#EoYKOU?+EVs1&S6\FJPrqWG3C_h#bej[Bt;T^2F/g_=gEdYWI3"d8^rpX'CQZ*^NE(=c'K9X'ER`[;[
+%k!/>gK_Gb]^0B`#N&GY@bH:C#D((\#[tU\UilAJY`HlhTE"<LAQX`FD/YjqUlg+j$i"fHk+.7fQO$f2qokR?Ss2:p_JQc:L0rU@1
+%O!9/g19q<$-)A&(%m<EB1,:)9ee#3MdeBCKCiPc'+6aR%HApnnX51l;NfgT/GR!?IUf"EA7Y42/^bhr[&4rt*Oa+1'[$%;\iL;f@
+%hct>\+k*N;MTnXcC;D2"VTH7gA\=-oPK3pHKl$"BThD1LS;%/WMV(4SiBQ*`ZKNn`8.-M.OL?j+LSV]na]Y':]L1B#W!Gi5KC!/H
+%&1)n,=IP\?$uVX#<lc3i2Eqp2#.J.m1LbBj\)L+-J'hS('_[c#*j(&.o3Lu0:,IIJhNeod7<jQc'Eg/<eT6L!YbJ@3!INKE'=9MB
+%9rtR4%BiC4K$7+?=bAIkVkT-j+5Zo#1b9EN^",bgDM/=2!\sYtPJjXDXDQ/6j(QX[O5o"D!Xd0u_WgL8s&Kt[8'M+BhUohkB=Z$@
+%`N\W&UN\.k"B02sjNrO'\Jr<=B?f,=8m>Fbr7WBXrrP&jK-I*`]5dI2Me*2GB_Y1be347RSpab1gCZHjS(NFVm@<p?Z.^+@:0&g6
+%Vh;uZjWZ6mn+m&B6fRhY#Hi98@.p`[TLtRQb-+!PY\:B(FD1[P_9^?Z,RCO4,WD[ADXf.9#LaSn3GRK_+0^8,SJQ77R`=*>"j99O
+%^AAGk.li^`.j-@/]Hj=F?,Xgjct`1I!>hh!LqDt\6-YpqrRNhu#m80-\s(Z:nkU]J2Ge0f5-q6nS"Z.<Ka;X12l%rB=@S(R`RM*Z
+%$-(4Mas_kuJEquFG'`?[Xe9mU)r`<dY$P$EZ,dt+XVESkc$-*&*%Zo7]jkUDj6@/PDoiN&pX,1KQ_"@I'QUY+aMegJAih/f$1M61
+%V+T^7Kjq`5WK247L!?c[ZaLN;+1a,t:9UNc+RNofb0eJ@Srdo^8JGHR0*="i8l!l5.JGkHaRhRcPLp7[cXZQIA%Pm-!hurP<gV3a
+%5'!o?8"uZ6*^4moRWi[CerB:@1kV)?Co7g#U'DU/>%,C9J-.huWVJ/)Md<\L<dOA(]NMrg^fCb2qMY>\;/5oXSL-F3SaPG#Ea-j&
+%S/QkZ$]fC=;p#/!iVCSPUaW2K?W*_4Z[Dp?J5!HrH,[S54#dNfgV/L5+4)$-_;Z769s_<uIl<3p:Hpsn8VG7r4oH`tT?lSIoIN%K
+%rXi-hn:9\2Cu/>K3Br[u/tB85SCc#hGFH:M#)c+b9ja-bF/Ji].MVa\8ZC.X_6OP=*<th\JCQe#qqRA@XasP2Rm\qCDqGG?ml=K=
+%$@_<1VCk(IC?i2`11qP9P(:qjEJK609WOrl8]s;*DR=9PAe=)/<^)D`K%b0?/.XO]`F6n+88e1aA.".uhKoj%L`ig,3:f^e?_[ld
+%f_&>3c'sI1%jXqBm2*V>9[+B6FjnQ!^]Ik/f[MFM4)'N'[XP"o5,3Z[SHB2ZRU8K?d3*W1J1k3^,B&cHq)eqg0gi3W5RGi,U%g7r
+%3_Q2JO<"mU9.-Bgk)L3;8r^2VPWR>pKH%'S9a=rJ65U7=LaXpBet+NCaW[LX3Ib)8OC?9(X2A>D'=-6__:8iUYPb,+<L]i*[LX&q
+%M9QtT;+$1QD+:mKmO@?nl5Dao^/JU/r(n;;Gd(`_gm]8U40`XokmMc\#oidRNF>$Rh2R6h=MR5C=c1MY%jsN&Vl?O#*Y+dt62+MO
+%BN9O1%C0UQm^k4CWGa1F=8uO#5I?4>041WVMR"sEUD=F/W+^Q&/9PG-LrLkXTfV>A>9m$%^'`)?_!&b1J.iY+hTEZ"e931jJh.g]
+%V;0:EE@<\JqDA4&a^X%!s(m@Dk,H%^s6C3?WT#I']df#"ICo&]FTtJ1bGGPZBP#o)r%L+_S,6#d]g+/F#V[M4b:d\'g7dFaDao\G
+%lk#jjVb+hPn.8eg<QVs6Q05f?,BHQ"2r>"%]Fk6Eq8!>eeBi9"9&m/iN)Ul*bYbMX5:k>SM(2!rkb%Zg#t53P`4dN^^uVWC$R2[>
+%(2_Z(1#5.?I25YS,SYfGH?G>9Q80^n5<D2dA.TCQ:>:?NJ=dH.,=^qV_%fA7_[;utMirROo$O#'kp(i@jg/u6=i!jJ9qW]#3\.[;
+%&7WJ^g_r!TALcJCe"UlMKi3>e^V^0-8p$!h#IYF>j3Z1)"LM[V%m2<EX9<gk$Y\4-U5D>GVu<9'KofuT@q?Dhd('hqQ`DB.[&?mS
+%+!sHuk8)Fu#5)Y@-t(ekgQD//q-d$/CeU`S52!MtUdF7K*ZOiiPk<m4UP!e[OjKgJB'/Snl:Zqh+0O`*31=.%&r9e^=IE8WBlo&#
+%ZntX9"W2+I.)H8ME_A?bXgNRGr",f=O7/K^8+DicE8<s<"kctA2qPmL^;[t/ns$'fgWW_F"LPk:771OM=`AO">X1GpIsa#?p9eqq
+%Z4A,S%;S8cR"C0\YtEHLg4(=edrDGt0A"==nF:D$($6U&NaOlMU^*V_=n9XsK0VJ1<)o90aMj'E9CU(qfS+U(WPh?bPA+`o"h=AC
+%dD?M"OaNY,6HM2$$fg'p/9[r@_br]^"2j^HgBq/#EnPYk*/0-A:%Cs_GV+%n;YRT^Bo#U^NKK^(/g-XW-4k4Ts0X'':3HZ'I.L3g
+%2m5BVj[Kc!YDZD12RER+^5R4,Zo,:N]TjA,@LH6_^U$G(JEA^&XqT["KUT#.@5e]jLsQX(<Y!=U5Xr)>3I.0KH5r/&kRns]=BH1&
+%itE8G5mrL?nokZjQpg%XhG@IX)/fY[RJ4o8Usjr"&dr6Z$rL+W$Y-Z_()H'&f"tO)<^[O*h3_C6$BKmkI7I_IYK[E#!3Jc6.ljW9
+%5]:/jV(8/Bc>DaoNnp^/=2(X)6pSb[X)'V;#e0)h/SX:g>'?JChe4$sGa$u*IVA7>:MiWH;/hHN$XuC5YA"H^`bFC3YT]B`!=lQa
+%8q2_i.#G'#Lf1A,bDl!Cpf@4.$4[GFIo['2!BR;jX[srcs6t,Ple<XD<Y=8Fe]\5@fE%E,2L.Ck's4n\'<JUcP<7-GjB@:pX]O2Y
+%U2]V.'&m'p.?t`^g>S<^muXomHDVbmCmCNL8<Zn7igl$\_87F[-Y`P;@l^DH[&rs4k)iIaUP,s)9%G_"N[A"ni'e3]YY,Bqo+).I
+%%9+RI6&J6qX^IgAR,+,4ZuT+HND8=r],&A-&#07N3H:?[E8_+*#>7O[2*V^QMhqB\/EE'6rS*MXS4EN,j8&j>He?$FY`cF90__Wt
+%HVsu1?i`47aJuh<XRAK=BX^"&.4,7:PMV.u:#8F#+JRZtC9\<=h!+#g&DQR3ZZqH7-./Ec-^n)K?$k24LaAU&<7m[q@"tNG:G4ZW
+%E7EQ<1oDh-#IK$'e_aEOSb7VIZ<Y.h]]h>R4QFYRV@*..O+)=aDu8/aJEnb^B'M&J(-e#c>T1n]-8r834!)ZY-_TRpBVn.MKg`k!
+%ieIu/Uib7t/.ge>34r,\[(rZ&I>F$t,*:;(UT6>:5E'"Q;gs$7l!XpK_b%!:M7J'C>hqAsUB-m8c2]SN!$VWe6+Q"9&/em";Xd(P
+%`I/(J4Y=\;qa&,n@sV=>0i-`9V+f\KbV5L0nqn=p_.9+M\pu3cfV0-WKle)K(gjgZX`G7/6+Tj/S[KkClXdI(53<;C:Fmd@`(E5#
+%QFJGY/c6<i5_1K7E,F>?*M^rkZ^/OS/dsik!_LS9nTOe<<1a:TJ"qVinM\fYVYkWt%)0[kHfYcTpFQ6UTR*;lc?b.(fo]+cgiJ'F
+%:VY?r;8(=e(;!)9K:8lt6h7fdUUFD0K8dM3#0N,iIpHA!Q3>rV`_3r3*M+L[(Fs0%C'$/#[^4#]J>mEm<fl\Y,.m^3h2iXRg%7l%
+%P.Gr/:_K9dlt(<jjU5+<VGD(TIIQ2s@)9W;rrGQOWLLGKLj)Tef)p7-p,u2&Gp;"q#fSUM62%K*5CdW#$B#:?==q([Q2\JUK!()/
+%@j?b6GJ)^KKQejc0'9'=r5GR@r?'Y+m@XCO`<42Zk@ONsEfX=LA9s+4Ia)@C:U/mnnc&CWH8.>(iCc5`*eNi8_;eo5!HWZ7/YI-+
+%gVGrJ'57_#O(oUu58CG!-4s>ir<FbOTe)jKT'^s@4o9e@c2sR;bBa#RA;faYX-qLcNSR%1L=$7;%/a)aajqdO7+Cu5Gd><%LNahX
+%jRr3jG!r0LV8nMH2hmF-^N*tU[\O%ffCf-7;]`nTOi4Jr8,KYu:F+G,I!Ri11rDhueMmNeZl"o&J>FH_V1o@kooCQe61@$*R.G\G
+%blUMW/>)gb\B@!Z,JM,-HUGofS&uW8olMiW+i.o*?<r$,>]Bkr-XcWCked5P-c.<aBdi2!^A/;tf[^CN2F=ZPF6tb\]fXAl]i<>u
+%91C/&7)Wi7Rl3F_?1)PBBnhc5.GT*@2gt9>OI7NpFX)//G&iqD/^FNqibJgu4,=oF&[Yfg]C%l,+\bdKY6IZfjad4$j9P)NA`0D[
+%_!GSojC=p3U%k]/]oc;:]g9RT*eRodDE9JLMf*>l0[Nq.Ge;8AqoE^7JYVh+s'Udo`aamrcc3Wr)7`d4a`oir-q+#rbMH)D_35;'
+%:RFJZ@6IH9Iu>DK'A:8D,dj8Vl.aL?(;8lON0KE>:W!^7M0I;uTjT20r=ad1RGqS&cuWt!oN-P:Rm2;s`F&Z$^3t>-mC2!Op5cua
+%a%ua*5Q&FfIf8NcDu]@ZJ+;d<\OQOAf71"(qpg1ErBnWns6DoIi=E^&rGV]&+91iJ5QBlts5S$Is7a;*rBL5Ef=t,ArVRJbs8INC
+%bs24+T>(9]^\n35qepr^:]L>3+MW1"LMss)Vr,[os5IVeo[h]EJ+]F?rqNdKqWm$Es8KLZJ,ep/?hr%Il!IcXTD$$Kor%,*r(kqZ
+%r4a'?T0Ag<rg-F\kPqr<qF;.e^S-k(q)H;kYADSCDXbZ9IPl@#P^;MahU%;260ibYR:/HbqgsZWfJ5"@#g&nrgrrnc&/_:@@KVq_
+%q:!<K6l]?k)BIEBdR]J:a1M\l^+=Ioq!DY'j!5fi9tFF.0sT?n:\RT[H.uQ0s(DLQe^8$7qR1<eJ1ud*r#l-L`MOVG4'<Mo_Vi'%
+%!H$`aom[*W+_i3=jT3YJqa%.+FnSsZ]TGn*5I0OG+J_ol'A<=Yetk'"P!`o;bn&-Sr:"?f^cd*Yh")TD0e58UXbc.Uk@'q/A+6]T
+%h]@6&7Jpu05COKRp\TeC-G3^[n*]EFqQS[?UV!YR[tc'R>(3pF+.kGMcMqAJb^]52\_cW_J,G@oct1u09A)>?B@Au]n$.N,:+VZK
+%J58<Weal!g$.4"GVNk4.8D;K_$I&B?#-2BmC@0OXa6Z:ig[l8P<<Kf*[9_\]=@\5]_:Dr:LJrMFV6J_/07?n:<N9l.@Q]ZB5$taX
+%4'8P_UpANsZ2p3U9:;;)BW&+6cY3)p62'?cBeC\.@tHe3cmT^pDW)IGXd4k^/\F4<@f=iY-L`iNs43,=hZT%nY8YC=.eTUh!]?&%
+%iLP=S2XS*DAbgi`O]5L^[sQ\l5eR2,KE:IG)EZEe8=Q#4&FZ"e_W"-VV`U_@kf*u]oH,#XB`0bCYLAAMobNG'F*@&R.EBkL,8<5@
+%$VR2<-cCa1petbY\p,^:U,f/A@R3#rF?ceWjVFh<nX[7a(TT5P?<>PArcI=5OehXW;C&j&arnM;6(Pi381%AE`uafC)u%kLL.Qt*
+%3jE;(TR$&"baH@$GtF<HUE$-"EHS<0deTfGc.U?.W"e$;>qeN8gMUTZ-Qr5:TL+O*P%9m3D@_8j]n/U\pua[r(.OIU^c[7"dqlFs
+%j12Af<?qgUbkj1E-c>^r3$ghP/T%4kXBVT`6n,$Z>UM]\\_,"b5c!pED10"3h1<I3M$>M8PG%:G;R`GKHl@?[T#J4)/udog:#IiE
+%1q++569fOsY^=u^OdaOJc`"'=7u;jZ<q.6,4VNYc<a&66-SK*RhY^h1Pr$V#ea]NNCt*FIe"33RU,RK^ghGSnBcXLlF;jsbW7fAg
+%,di*_\:M9RU>50D9NLKtb*q.JMoeB9CEp#hHA3V@do^qNNcj^8<:4giR_V%<$s,)qdcM:ao.roQ.V6#80@Mrm;Sra'VPG]XALO@3
+%VfC`?^9iK+-cp?%W23Png04]@h.Nie^/R!9[".o>ZdgMnA7u+jKRe$aceV5`UlS>bo,oUtE[.EOBL1,+((bLQ94j=7;^B(LSS'0#
+%hr1Sc.*o6/gK:-TWCT'JC2a9uBGd^[N-:jQ<aSLh*VB1J<%!p?Cl>_H!5[a3f*GJZ,!/SnUQMbmJU(SYB04BA;O9]"Af<1HL$`hN
+%Aq8(t'7<t]aWa`VC\7#2$jaSbEZ<"(OiL4li_km:mZ[t`J):TZMi.pYkNkH!gV@[1c'%f1lf?k7D;Vi15?hF<fcV%XZKd5-b?!oL
+%BjP*p3o+BLm0Qa:0Ci6,QXNrE3c5S_X?hOH+KWN"kkJ99-$"<dZ;88%^;FaJgrD=c(Ze)gFI&8qJ=1Upr!i++OCPfYPEiV_Z%ZGq
+%JA#jA@a\d[rHfunh(,J.OWQ#$BNe93m-r6S&:T-3o_Bo_&QgB)+FQfSI;;NjUT.JhCfX2$&V-2&C,8r`qKgZ]?e+lK>M/VtfGZhR
+%8B_(dS^8pRGV@q#jKN0SY?9e]ZccKo^_s3X?3,2:9`")HX,.Y/*YRA7C>CoWD5h7>r+Re92pC[Ce^1_.Tk$H0KL$(u+V.n_#bbBg
+%jqU2spM52b.7ddPemb]=Eh)bDa]DR6S<Zb,%>I'XHBosRPV]*'+A,_+;J.-[VR@;(`mAZ)5$SN&Qtj+#:r.L&+3Gun'?-&B0.,%[
+%%-8k'nBajSOFu/+cn<aIWdn6OX=%7ChaR7;crMu>pn/V/1p$CSn-s@Z[T73h\d)!O*>L8sUh2^m"s8!.)Is?rM&htk-AcB_(hS0r
+%YPMWpdBKR'(jr@Dl][Gp+e/-[W6tBLpO9(io)=O<d"m%fOAlV4Hu@PKYL-57VuYDUa3/nM4K?/R_[b480;_:b^>iYe$2X@)qO+`'
+%;U0Q0CJb#=_fHsnjdRmUVV/\QD$3WfLO#hLgSg!co).m/1%u\kkf'=jh0@MX<d^eKGAbpm[%,4%DqX2GTBd*`ej^A#4<n(hd_Dc@
+%mQ3;P6%WE#qIr5:Vs7_p=1XN(Eul:KqmTGmkMfE<(VS>t3q_BJ>i$L7NLnujek&a(,q+W(p/Ra.Yp"Tie:/J!o+2Pb$LM-@FS/'B
+%63sPf"Y#)Bo+G)F99^1J"%i%]qYYAPpN_j6i&6X,?cG48YNS+:o<;hRI@Z..Rp3SPK9sJ<[L#0VE]T)4ch6",,JU(no6%`=MjB!m
+%dfpnIj:Sg-2MoOm9dH'&;>1/eo#^!t??LB4kR48--(RP:HX'q@TYW6L?u2")Q1nWm\-t=WWM+O%RQ@=/:P@955//)07n:k#W_&@1
+%_WOe??D,'e^er/Qm[tiqS5<L[V3IER7.Ne:[he,son(7cki,AlJfS[X.#dcI'*LLX9NShkR>!.cDTj+El/ZMR,-4Sp"t.N1[,P\>
+%?2G+6iFuffH#^VVd#.h#cbM^cmGR*kY1B:r_kGSqq&rmRC]\\eo06Iu6H>PF2G&nXNV]%sY(:JQ;FX0ArS_Ls<rV[IXV$9-?2NC"
+%dlm]tU\!EcB)^neNW7,^^-Fo-:^"Kq<u^![3:e6"K.e<]&s!k+Jo0W.e+i\oHMdu]]KH.%hELkK*\W:o4J$cSStD$]+!,9[a5E9p
+%O3GYf@31J6kJu?Diu\$Xjlqg%p>PH:Ge&TTn0n,-fQfS8DY)cmF.5Z\N?0a.<ViXMIs\&"^O<%$5:Fre51I+bYJj<!_,0n5UZ0*8
+%YRB=TLUW==NJFQC)NT6-XjMoplg9=!m`>t3jhop@nS2G/jLZG)h`a/;+-5M:cO]QT%o;-(bC01B+iqFrUF.-G"G?KecO:'Kc[T7d
+%aJ+OK&JAOeofIalRLT,b_a=([h[p\\!T+V1iZ,ZW3+P%Sh\@4'4Q2nS+C`4ZcOUVUK^T6\R>C;='<-fV#o&eXmg0_sK^T6`h'VZ5
+%_F=/L^FN]6>?3s9AAgq,*C1n`nQfQJqb"URE5W:cB8;N6@=D#AaJSGii?OQU>lgbUF8.a=,c97B7hCMkMr,+9@RA@a"Hn!Sh[rI9
+%&`4<so$!i#+&8Ocn/VNUAq>D$8BI&pIr8*)1IZeB=NU,N^FQPL22=CT[,h$f5<lYg,/,S?A5D3s!_as#HU:E/49+(Y';+C4%l;m5
+%Hrlt476Cl60ua,RJk],6Fnb]\$iFXaIA8pmkIS?D%c?=AVM(T/qY!GObWTZ)I$]JKZG4:GBd1:78]db+45?&n\],PdMPSpt+0+=7
+%q=B5=SAW[6fC=[mNelNk*sr&Jc0p/\led*dleh[/LL2\`Xc^f<rTE:J$B;U$#`:_/J.#,DO-TF=Rh6Bt'0Y%ATfH\t\6:7SjHD#4
+%dTE/aFJD$=dU&U;IMj.-Ls;ct]apA,CYb-[OF@9n4M9-Hh["IAY9rY\:9ErgC8r-H:4JIP(smFGeaC[5;K[2Je!MJ9$-4#l9<2sr
+%Wb/gKT#&,G<I"W"V;L\JT#QBZrj'D[93[W5h+GRSeC-Om"i_>-V6+>N3]59FIr-=$+'$06o>VffUroPUa%$)&JV_d#5N[T'B(C!/
+%n/?.`Jo'N,L/dPAd]AoNg4m?eTED_V"GlsO@*?+:kh.^NdL61XWe$-m@_hjem/nIR/i@6'FP/)DbC0mQ3,+1b[kOj[m$\t:T\k@&
+%)a%>IXPeA@]\N^J"gF#77m%'dON1B<E;C!_BmWX+>W7^R[8>\p(1?)/QS66hd/>-51K12l[[U&c)Fr^/VRJ7JhsQ;)&1UW]V:6Pa
+%`M[*A[02l++C(pk]4\hp`_'#-d_$X8@_06+-9uF^^3I8lF10=0LZnA8ZST:KSsM4a61:$f%:/`?IBH1dHcB:Ja&Mt[j#%/K.)G%D
+%cRcjr&YW+]/+3uA&Ff0HC9l5?a!]W`rricLN01]e[L/)jDDYt:hK?U0Ci4BjD\kV\GO"2S<8ur@aRkWkb.>=/)VS!4BK$PYD9juJ
+%pM!EHqhi=7_.:0`X!o4XI7)-Hc@0<P2B3ZQ"-oM(<VKq9CEo+l0,_f^G\rHB",0X,+S7?tpp<XX'2Zb!13TPqd),+*(l<E5ZdhP)
+%LWsZ(G=6c(=#6te0&CK@F2!r`Vk&Qh'gcSG*m9aU]:-Y6_qN]OY2WE'4[^r9mJ<[Hi$F2R[#qV#+0Fp6U`M`ODJ"G:oZNDlqGMb!
+%7FsAAn8)hCqHs1,^!Te,<H\W)cT=Mif$d6ioo.Tr4^`Faa]bR1qlgP^1N(ZS,fS0'Uq6ir_bTGX#p-TU+*OkB>?#2-XUnhU*Vkn`
+%kS8eOk!!FTZ4LWT6L(W>(@\/P2Ua\9JAW/%e\M`9HVcV]AZRipKqQ;Y*oL2R5R]8$ckaOS@u\d\#f'P`W`-9ndh?9U-S'D+9<E2`
+%W[:E)"&N,k+e3NkMiS-Dp-OY81h"qO0=u!ITMsg5[I'rdYZCpF:Z$]i/XM>Jn#RU;KLkR*R*BCD1Q0NaKiJeFhE4hX.$Hls>J2p3
+%g1U^-nb^$F'gW/=oV"<?:B`DSg;\Bc&r"qI?=Qk0n@rnjb-/GA;tft:ZU2Q.kG3R<SNDF39c=c:gH)rd@1=I]^clQh-UcO.(I)_)
+%'^OlC`Dp<Cnm9N1n;RKI?M#u>F&buX!h3YD2RKQ.iQ=)2Yb3GlJK7B)2G9>Xhn\PF]k&Pnb(M:k%KXt"&!00gp/XE!pb1oAZ/CmH
+%O!")kO%B#1nC9K;gDloXYF<07I65h\E>-n\det\-kW?(:cCNbTD8Z?qH5Edu]!@jGecMLJVS_X,T;_0X6EY-")^/*J/'&?sn"?.o
+%W[KsI_$qrBjYWPnmBAANa27?q>U3:3M^LVo-V(R>8/6!)n3LqR^qGEPAt1iTHuhf@:XA66Pehc%[h[^dlEI4B4TTC#A=V^IS)Hk&
+%CZnAUEncHDBe9Lg1$6U;a)f)<G=:lHP$(o@bVcLCp5[.a2YLD:`U8Kn!cLP(bQ=<m;OT]%.,s^90N)8!BV6N"33.$$E\c25*Y!3U
+%M7\pRj$OWSL,j#NR;c@8'k]Rk$YiPB/S.0A:iG4kN$ULG"s#C$.;NW;6NScJSV$^seA!O5*`<;g:Q!du,;Wo>)df_dY!C,Z\u9UR
+%eX<`n7U]eWl!K50mRB7<>!m@tYGi_?MphE,fa4c]gTA/`_H:u8oKMp;f`ol886.1.qekpuDs1bOT>kDHh.,58UYFC5J3_q`JdB4\
+%S%X)7<H"tq3TTDR)O7_skmMb/"Du=MP07Y$eSifr%jMWapKZf<\lhg"3DfF%?h0^.WqJak@HK?M/TH\;<r6=,95;U,[Nml8I@Blt
+%o2Ac.!$05_4ieAVDRr?,7V/?k#o<PbloUl7dG2<m<l-R0@Q">/U\NN?D@dFGO5jYhD<RJZ=I8Qi#Y=@YnKH=P:s"5>%JjV+YQu==
+%jn!ST>_ffGZ6e^ak.RaO@ha%7^!*$*S4M4?&*.<`=r,0QaeQUs;00'c"[+42ouK=+A@>"rDhZ+t3@(TUb7`ZUE:J3L06&*NGZAE/
+%U^<P,qP99sc;AKn37%st*W^;;<-O#5$gu2^,\7E1J6]P+abgRD0<XrIkOc\69;1.gjb`;==)X.rpJ=N4K3/"Dn0j2kZO:@&/B;]e
+%of@=Fe5UDbbGK\EW[*h?)4@A$=euj7;`?+9dp6k>Z=U)H"+%d/;=5_(D(FFd*qbp2,@,kh=i`Nf6gumq2t>_lV\_W%*)4'ks20d,
+%Ie[9B0B>'!iQ@=cr\4l>0I^iKH^!uG-i:G5D-]?]!MjA2k_gpY?HU"0T?%S'ls7T9@>g8%B3du0O9Wr84,]bP(2fhp3[Pac/VBn=
+%R[IBe9H9e6*;M!qkX^j@3ftZ.?"pMhXtiAVH9A!/m6Fcg!s/;G/128if@0=lQDZc323kUo\,WjOV`lbSS;XLG-gln"\S0u;P065b
+%@Q?T>-eNC[.Ou,$dt2/[G2pp6J7qDA-1M,s@]&-pc#$uY5SB2o:)[bHJo!H]o.j.EH-fQm+_fABGH0lTWmS2,iM"*.FnGO69_3U1
+%%7k.*9TaS"E]cE(/W-Oj%8saD5Dj;`4'Xbm:.2n6%o8/oMPt?W,X:W7ZVn7nG$<SL;cTrtJUgtNb]K109G-1ne"s]cC(5NT1^h*e
+%-iWlmpNEos(X$2*gt<T$QCIKe51sa'*;dRtoXKZ>g[Aqk:NsjWqrj5,f/!knhT*#kDkg/[Y_GWYQ/e?sTR/b_UV4&#4OFU-Ib<:G
+%nq;Us2psp4E:B,.is+8R;i_"i7'oSp2I0g9:*7m28q+"'d;=,8XU[C8PC""$GgHG\+`aVC/7BC<![q\OVP6-j%U41h.eXJ!M^87s
+%(RP3f^>kPn?cXZF:'XI3Qs0X;kftrR8Q%G^g&]+e`iAbcOJ&NE(VY;@@U,.K+8R_Va#H#!NjN1^IUZY<U%CFJC^YH:O.C--f'foO
+%m887lXmJ,"HT>/;=ho'^Q!?DA-<k7@%%K>#j8.-Y\_0Mh</co0RcU5kM6omV405@Oggf5XTRBo%(u<WPB33VuI+b-agL[hN4L=%=
+%g3_.^6]2dCHg<I>Kg0B]I['f51"T%^V%k7a]Sn[2dL!qcpkT:0\7`$$#u0:@@7*hi3]b`G2^X_b;p`193N[_+koZ^OP'\c&W@IVW
+%T.2bF<1mmhOtGRhb10EJm"rks,+^3-cW.g%(W(Ci?[@rD0DkV#++O7dJ,[\W/Wp#s#2u135SX6r3-*b$a`Y3*^Ak;0s&:mWNP.m&
+%V";nIfOGOkd;AOCKaY]e"*\[GY2&j_/E>Ghk/S;8QI5"sZ<sk=,YdJ^&DgFAn1-(b&Asc?DGK,GVVm'J#4WohZK"%QPDN>K3_bYI
+%dp(>HYHU5aB=ctOhDY&.#KCKtO<63cfflR<NsBM?S5L71*ACD!%I;D4MQMb`WJFX?rpV/_o8T_q(&dQ[fWWu=pQ`HK"L^YCRbiKe
+%49e\uoG.5.[0"bB5GXs0\dN!Hbr[iKrij9c;efd1%,)Ku8(O>UTP<KP^"Z.LBqb`#Mk.KnW9r(A[8VSrS+,1R40TAd)Bq-eN$o74
+%;@eNr6(VjL$IWh+p93u%G3ct*;h')]BIFtm[8_Xo42Bf5B=n?:SkXb#0I)j5p$f=`3@?c"G+,R;b\p+ab583C`ddC7T)4(Xa'#hg
+%En.eV1i7QCMGZ3(Z[J:?/;_MOO<p[4p-7PkXhgBZ]F$2+Ar*D.<W(gGE4Tf"WAEC@NRfYqC2hR#CK1\]%=HhR2<</HnQ0=i+HG!2
+%_Yg`$V&HMeP[<iL/3NNo.se_%#:3Q3$jZPZ6r,lop1(N6QNU2+/CdLg+(7H-N=b$"PRSl?R7BgER@;of03oS]VPhMeK1sGtm"@SI
+%1qjuB"eXj8emrq`H;M/d_4.<GJ=a@c4/H,0(b_bC7&s=Gg4<./I-c[YCpmJq78-`46AKc;q>hd>7lNZS%YB_?APW0'Nt09p%R?$F
+%g@Z<!V<\l@]KCd]SY**(8jf34^(6]3?O3^Zq4[J[_j]Abjm*R9qF>)WfMb`[Km?$S_,VsuSO8HIo)mfo<.2$]Qtj]E9Ug/Ep^q"o
+%2F2/Fj<HOoBY>TM,mST_CJ3%AYP"15j(bI]=]dEdRa_A30-!H8PbV=`6U@S48Ei`0.m/R5AY^1-Z6+:(4sJm/!iC*%ZAZ-..V5K\
+%>+o;oG[/8nIX;O`JURU<DYCRlj]ecj[iM["*C9gsP=2O6MTXIbmi@%a`p=cr7++T,;O'i2"G@-8aY5@L:`;*i\ba'MXSQALKL,nN
+%!O7QSehm=qNnl:!J&5r^k@KXp1gk_A!sa1t$`g4i%!mPZ=jXWXlAA>PFt[0@$)Q=V$@L?LCfS4PqCVEnlEhJ1d",Pcb^4mZ33XS9
+%3Qk-7Z[9&U33)D,lQL*K,oXA]9WiIAp,Q7+n'Td%6M"/OXO%XK!/4:;16kI[U5Wt'9hE<qP!448SCXRB!Z]9/=.MU#KWgbpI3>6t
+%kS",%:IGDI9DS;GZ8r(?4F)fT8!]@6A&"@gm;6RTLo4nr7u_b2_]S=70Ii`QplA+H3\4RX5*<[Impi]H&`)f,Fl'\m$s:PgJ>!0>
+%gt'(08VVHV7cD,:8b+)a!-<GL,`4`?BjnHL/L-=-pI66`U"4-S_6H@_6RJgbqOoEQ/L1H_*A6\>,Iam[q/g8cLK.\bML)]!obG):
+%DZa!pR[3FIYtV</'L9.X<Y1DB&,$BSESf>V?5*M-R*^-/YK#B6*JVN&L>,_+c9t!j>$a=MTUonH"oSqpR]VUENZCeUEX0ded:$5h
+%8[q]GZSGPpHa:VLjM$S4M=B6Ec:ZA-D91dq%mff\1g&1n#*5(jdPTS+i;s0Pdg)R/9In*/'W8KA[X02YZ@G*d&YO4Y2S2gbcrFcL
+%TS"5Ck'[h;Aas#/mkN46lc&hU9#BqI+@sHWWKhb1Hq=Pm)t_O*7D,g,.sJ7//BVju+4e>1SB*&e%G@eaS*se]0'"<[%:;Qj&P\jJ
+%27LD^1S[e'd4b6uB%^]4gVs_jXtXi2A!nF93R_$Gg/W(75nt2e*XTX)*b+lJft/8<[,/d*0a`\5n(+KeQ?N`q-'0`F.T/?6FhY,5
+%g5C3MCEmKdc&`ZHPc%"M0E1)e55j$hs$9?E:VZ[OZ0hSRLL:)D+"nT45Q'?pR`58as7sPUs8/F;Qe_Y2-s6?oGbZqB?eQB5_lmg#
+%Rn$%1$u!"Z0KZ6k.pN%T7E7O8:/BnS_,^q7CNiQ"(O4sh\X2<P-A@g52bNJHW0=)+*.6`:?icqem`4R)\+Q>S;dO;t41[L?Mn8#&
+%*e*k?:dqb^JKqj1\Y=WYbs7M+S<U@V+3<C&??^p+71Iq1)'$7G)`2MHf$a4"[5"c"LqW$Dm`Z':*j":[J>4RpYC&9g\Vs]FDl;H(
+%.28!$l@O/Ne(.gRdT/jBU[D6l1+ET#k?f=^FD;qKnVZ?AMS)sk6I-5YFOI`bnI!ZR'X`V<F[(9J';?@[YUAn)DkNQ\%']?1d0@^r
+%=9JD_!EZ0j3B&45Z\V;c;j`]?b,df/**6dsG-c&e$DOM_JgX4fK>1XKiuEa>:cJffql0iUc,_tcoU4\_#5^JH"1)r9@IR(7$LG-_
+%W+e1,@I[S59g;Xu-t(MT#O5O[4.r$bmHpVDTXhXc'lTeQ`;Mp&4gS/O;/7V[5//qEj4`bOq:g(m=be;<-t@lE"HUf'bC*L%3qL+s
+%DS8"'9hYLb;LBLU/Z*5)mI8%3G`qr,96@[):@%2Di(7ek</<#[P4iX_j=?0jbsTshk`HI&@?h1uo;l>Ld^3&PN_(tNYq^fVn'hTq
+%/9.nZNg:d?&TNQNFdZFX?u:<^SVmjMAnfTr,%@2pAnYZ)pJ3WN0sE8ei<*h4K48nMDcU2D/okW6`=M4t?1tYFd*rt9o3WY^[tQEF
+%AD<N3a#8Im[LoNJL_#;b2@Bm'a4[+b"SnWk[cSs!#]VM>943+0!-:A0$e%jQMS^Mc@,3d&b3QV0'k?"".)aVSk%AhF>S_97SH(6L
+%eH:H\M..4dbl+*fq"isW"le+'%;Mfl"+6p]aNRDU?iYK"oJ$9@_6=ll-ibZ:/S=2G#eaV%dmRRheS<OL5XDFt[bK>UIeDu=L:2(B
+%4O@ZIgBAU.8)'^qp?G>KYbEsoW6nOX$.'1]#_*tDB-*0d>V'EBQU>E@B%E'CW/+;g4MIWoj[lH*mW,&#MK)drLf=i<H7h`Wa[<O.
+%2"Paf\HrPj>A`\)fKXPFI8n??T'e)rHb7nt"bNK'Q45HrFpB)P,&/6I"rLtS6OD!u<bg:NCto?+lDZ`)J.b]V&[-H6'@)6i'o%#A
+%=Y)lRs,E.!FoE>)SF$)nH@S?9U3*9s+RU`PB?Zn!OhrcEmokABlYMKQlZBJHaYnVEYW$Z_2K0_oG6gBV4X?C$=&"h/(sHA,7.YRN
+%aNP\#-o[TK?F_<&<uj@Z,FS[[HpeM3f,):Kn)h'_kXe$U6'b^A$r4kRa4/.<NBKf'f'<07djUlY%sYAgjPq&<8'(nIL1GhbJLF3q
+%NG1U21,Wj>l.4BINM?9>>Wp-gK_Ra,!"'X%J<e'8id37:#oOBfa(*`(a[0$Z'Gq!d,tO3ll+N(s@)7fW;b,l@NMjL@Hf'ncVagpZ
+%!$@,DXr&"<UgR5mZN6VI(>UA5MERp*"$*W](U)5d/8Fg9p"e>dX0&)m!nV?F09#82A,$EO)pFRap[3!U\[W=nknT4E\8;'G&RX"e
+%bMf9,p:.LeD$8C;n!b-2Fp9G)C)Ic(dZ=d,S`%=iCj9<]@6k@(%F^Is2Dc7#g#i>c6oel%*CJiN7SQ`eA++C(C@$N0bTNND#;*l+
+%7:_cOkm/__n*FdDH@Y>uT^YO=`dp'lR%INpe*!tlgg::lf%8JS4Ig&^TiN2-+0F>dBitGdF!DA]*'CjZ?q2tQoj)dgc_kk$;)Mjd
+%@0M_3f8*L;_&ffNf8!nGKt-<cWZB((M,.ilU^4d0eHgCpq!r4,!2$c7[2ZH(ZiQ+hE.C^Nm"N8&bPB3sKW\i6aPJ3M+.d>jemQ`T
+%@<&".,[k,t%9-+jQ])&HXrZr)'U8s/\W'2=#+c<Nl];Q=A/0hN^X5D^798Q\gurKNE2+-n`"@ecHI#.PU7$_=Tnif>BeeLuJaW>5
+%\4shQVm_H12(@^iVWp`i<lMCC;qGV(cLHLnP=^I2NnBoUXmehsIdUr)&)$(L1X;JI]_>:mI5CAdi9=Vg?3:LXW5&S>dqcCeUZr_:
+%8.2KkrDOR$DT,_0N9GZIJ^[G.@u3(E4/$@KQu8lA"[d7L?Ep1JGcW'ug5shHqD'+IJJ'cCB.uKKII]eX@%B;+2;4''S8"Cc\tLTL
+%$VP`;lH#EieQ4m3.(/.PE#o=5Kf-40K6=f1;"e?)Ts=F1mP/L%%^T-k+TRhS6qdj*Qj#E;^tAf@%LsDP-W2E72Brb..+;u,%."J8
+%3F/c68S:9nM"JePab<@q8Q^^!F]lN9*Erag>=K*#S:>]H(nS,4&-_qrCc(h&C@:Y^f)=:7BLo,Z4<mgRBK-g+m2U5Mom&7S!L:D'
+%$()JG/ERZr_h3*^Fq+jES4Qa5<oUC%M%s"/O3YjkXUZrB2&8uXP_i^bp\Mo_lfqh">k;rWQ)XoT%BsH0>;2.\P+<c1$*Oe(>@`NC
+%0)!f-5\@V'-:/XkR`4Kf%(t_\RWnGho;4%(oPURj^!*fa"T;0@,<d3H_X4e))&!4`fA(t9E^uX$1O'B[WtXtZKm[!ejV;d;Yqt.t
+%1pp:`_eHgJ7skn;FNK-'G8@hnr0^DLZo_&L<g`rfYRC5l$nSV2'Xm'(JN&WhgIYos;*1Al"IY0j9qHIjD+nS:_9=[jV97:$`@?:s
+%LS&)YlR/M_pcAtU*X]b:<I^SVq!4a?doFGQ_Doa#bp)*p\Ko`*bkS.5.:28)DP#`C2pSkD;j:$c!KkDKb$g?%Fgh@-fKc=Lb"K*h
+%m](sEr;*hGVI?2UoBW<fHF!4O0(.*uf2KWmMnh/o3go2.6li/75F_1(>t_5Y#+)45C58C[i,LS\L8S%p$-^)_Gl?=`/@#=\,*m`]
+%APWY;5YL_=bcr_\f=c_Z5i]0N$U(WKqF"b5>%k4pM4kRp)KCuMmbsIIW\-1'l:Nf;*1_k3WPnUGq:DW&(P5]QU7gj6FD6KI]@KQG
+%.,Fiel&,mP=AhC6V#m]HArFR:C+f`VkFul18Z%sB%GUk=V=kqM(ufpXnt/%a#!DmSPEP@.?gGETSU!X5j=th1fc6j)PV8.3jJb3C
+%Bg)qP,83GA#.LTXp_P\K-niSA-pR2/MH>Cd<KfEmg)W/`0l`^VH=5*r*f\Q\<BYfLfRf2E&d4n-fnQ6sKc?LkL]dB^W1AmL7]tq0
+%nKtY!FJ>oMVgO2B=.Yf70(Z]Z+UHO.dQSqkhTT6H#IWo6AW4',/-W_kH2!oDc1aWJ"@D1]>L!Bc3Obb;N[_e*DjRg%Eo[:ic39s#
+%;;fIdEe#271R\k8O_!e2**R`$>F7D:/<N85\o"cH0m+dtEfZbTSN#2=9Z<)9/UWSrMC8oJJ%g1`HOA>>S[+6_e4.(1K$+U!gZVBR
+%-Uh<Al`/XHP<"uShf4QJpuu\p&UpfQYE-?=bo>M6%o\O.KO#sf<B4`/][=4(e-%e)>B&L?<^EV=O$D%*fWd6L^FC(0$G4u2YB[UR
+%bhg6-%;1f?CabfQ?+i%\-$g'<>H9HWL86@1;7,?.3?c4mgT-_AQ56i=\6<9L3l`6r$B(ari>!R!>&54aNmXppFaNOIVeoHLARVD9
+%7uWO(<lCG=\.Y:A>7F>L,U^m2:ZcIBS]B7re-UnY_@#acU&TPEf^!&C^lgI6TX+j<]r&Ur\4S5cI!,0II-Ngn:`K%eWIrbmrloU7
+%nMG'Z@S62k1G>%@CiWF+#JS%\C5&]V*IoJ8UG)lqMQON&X?dY.o3c!OnhXqoYmRGb"M1#5#0pbk@uDA+mBZ[^%jU[m3`S@bNgf49
+%FN$&E.pL[PdA,f$VEhlOl,JCi\HdJD#3?Rh"B9Of6pm2u`_/S=!4>8e=g1#_idPgk6,`s1WP\?dTWSh`*E3a1@66@Y?6Rj#)mE,M
+%R'Ula:Si?="g#-/4(O625p]eS.Euc_4<-FrST'Jo7`.Xi">SZrY$]G?kQ$$F'l%ajdf6$1S;hL*MJ;Lg<S''n&P@eI-0KUmXi9D?
+%mlCq2A(=N%kQ<Q)Jtilf6qC^]4EbHI3Wfb^M2b6%3dl&RcI7!2Am:kBXYTg\2&7%F[0=-=peo'dGfM^[RF1:l4e)jF?!$03/On5H
+%)4NOg+$P7NDX]rs*bp9X)NLf5`MnNi#!1(b<%&iP:+WUn9.#Y[0P[<4`eliG[039-8#)&eC+7@4"OlKlpOlRGljX=mB!lpnF'YGH
+%;cB[KrkWA;-;"opU$gO)r06GYs,<InesNe@6-?kJh/-o']L.076(A^`5qgs&k=Z<@0P,RbIBMDsLDX+o4d`%=dg*=F[-W)iQ&6uM
+%5R!]N8CI_#BGnAP#:u=#Xj]PH1V=a@6o>?!L$BfP=>I.0&+\KV?X:.[8ge(6j`WS#=jnMJ*:UW-aP%BR'Z@f31?r2>D0F+q<1".g
+%ob\.=\XrF:+p'<'&@!C(hd@9])et(CK7uZal3f.DUfku+/0C>Gm'.]mAHq6Y83s*J"\?]u/G_^U-F`!`o?t"`_@GQhH4Ug]8./?t
+%U&-N@Q<SsnGg]EJjRLJN+_;mp'5)CPH`"06h;*R9GNd[FK)j9i6$C6_kJ=5eXh-G?4F*rJd[Ys!7:%M;!O[UM@N&B>/D$3,`iV)<
+%kSi$5bpFRdXaICuF:U56$]Bm"4V=?t5SP3^VE*H?gte+$%hBJ.\*pZ"9RCW27cDU>NtZ!6`D^`3g9H4Wj!"Mj",j\"04&&QDU$i7
+%V)+&VM9*'^J@N$R;`mLI]AcJ[nggk8QtPNfbRdu]Q=6d6A1ZD-hH$c/"i)c7Ad_mFh%-j@HhTW`,N6HQg&ai;4iM\,RV$-R^@Eq=
+%Y@j!?05S'CSeo-&_QuSlJg0aEpKa>7[9*S&Q.#r6Cr'.j.?t&?if!sG\.=fUB["b#a\[&OKi7WuOOPJ.I:`^uU!'+(1(;]HL8N].
+%MIJIX]'55?#O#b&Gm;F&HH!`%$b@`n-e%4>#d)$VQ'E:2Bc:s(o<g;m0:EnQgE0NV,Q,F/rF*Sn8,NBkU&Ptd%Akso`JE%'NtmUM
+%@_n'\4K.F?0XdUF\-L?jOF]@bk\6p%J_%sIY[uPrN2d9Ua2;j.0*GOiiaf8_%R'RseH6/^U)ZI<?rerB6uX%eHtP>5%bj@P*(td"
+%o>6W).4>0T-8FjWnfMU*6Zr8KLIKc`pk%#5C*5'G"_W5^cj_h!?apTCQ$`lm[WN20#!a,K.[:<lNc_.<*+ZdlPfOMe;/bb^aUb;>
+%5jnQ5n5`'@0(s61SRM44Mj7hl_Bi9jIi12\$GTRI:LQ'.fY">*is=,pn3"IsEslkTC]_p6ib7bXd.FN*ASY=:Ane68LWJ`Za!57@
+%2F^p3bmmdK'W]h&3%`p8H-h*'H*_e=<$`]uJicViS+ecTRZm-77hAhId\I:XnC.#QS:Zr=RYQC8dV[+u,IR,_?raBDg>c^)R?KV=
+%U^65F(O@pcm-)#kC/XS<@jM<O8fl+KV!BcO$`S%lfb?=*U$_9YXGsq%XcpS'X)Y#;L7ZS#Cro"gd2O%9?$7>'Gd[13T$,RiO8F#`
+%roOpE"'.!:QXIrIf->\'_K%IC1lKch5LtpZ7sdW5Bk<VGRDYE0I@%i,Ca9>1Z:d$.F"eo$M>*b?RPq&$30Q6pQg1A-%XlT"<b5Y7
+%$Ip.g3l2%G)?4VsBu4Z;NN:@KLLu,5%Ti[kYWn4GhVD40!Uu.e(8^d5[i)l]h6n*o,#%s"INYPLXk"N@]ZBXJhdEa)1-9lPNC>n$
+%f^:n&G)L",;Y!;4>bQ9i:[RXVe;_&&\<i>`.=R`.-`ip^MgnQ,5S5[qbu5nRJaT#EdoF3*/?3Y%BSY,)8',0_1KOD2G2;W$ZOB*;
+%fX;o6,OFd)YTm>X1R3&?#59F)Z&e-=,KhB]?dm/t^!J-PT_m9$N[#"+]5Qj$'>E,%!AAPCE,$0W3`W8sQB)%$5m!7qGP@Pc$afI1
+%o8%L57<Rd;k=7pE`c-D+^>m-uI>PLQ2XK$afFd=6SlU"iNa+>H/JCi`PiT"5(.B<9k,&)l*iuC6IMlA\+Wa\/@r>SDfk4_;S&!ZZ
+%/!"=aP;)O40ZdB[0rD"L<&ubcm0O'c(K+lV$_a#%Z?5f`5k^*k_JPgZ_>63H+e[2"d_sG%M]5e^"1;>$&:h>0eV?o>/Jr);N+hN4
+%Jr\B1a]][@aEZjG/j7sP`kdm7h^`nm**$qlIRi39@?6B,_dCUn0;RZM%JVijm@8V-;5T#hBqqjaX<l_kBZeSGRUa6`LiYrWVg#c+
+%Sc<0.mO)u4J^X\r^jLnc>ES*/7Vu#i`f;AM,55,'M.lB!1ARel9!12j$]K:3&Gj@Ka"jXn$F4M%B$e^B\6GEDLNBR*3"L6E<4/S&
+%M[<`\OEHJ2^Vc&bLYi+^K9baQY"tr`[BJ&4ne"pgV[^uSnd:Dp-P5)BQkt]7g5K!Ag'VLCrBt*BT4!58:.AL5oVK0agj86NS8^],
+%SMfS+C6`3W0L(NA,ZT!goO7uH8fdF:C0aI*<Tt\3fD>hD2A/@d'PHSjhZ,Ws#5n\Y8YFG,0qoVJnWbWGW\fEl6/:,@=g8WXA6*>4
+%S5KEV>f6.$`jmmP`/u?2Yi-%cBsrTu#mZ7UX9$?<__.bO33_q*dQiC%i!DjYR))s<&Tob>;Pr)=(@(#jCP-ISeBR%.&/KF8[p=k,
+%bEG3L?[S$uK^V8acDYaAe.EP*B>R=$4YdLfCC=8Omo@[HS&%Yu;E\FEbFo@XDB'+3>k^,*Ct[9kLar,r%%F("g.-t99E@j^R:f-F
+%'\Fp2d2YGn*rU`IRo@p=XS5YG(7[XI`lt!'cX>Z>a(?^6q#D!l=?l/d\/B@!p5E<>)@UCqG7V-?@\u<%Qkc7KOo11Es2c(:.Q7Ao
+%>/&a89IFH=g<?5C-4;'+4'Q8CVe$2#N^m\aKoq%5U./AT$8jUp=7h+[&G^%]SE(=h_JA;>mCRG.$JgoJ$mCWk/%oE[L(LBkOgaQ3
+%[[kW[.\M%gMoNR5Z8u"D7_TCH04G[5EgWaX/HnWh3;F2jn)N>,XR)aT2$jP$XDFd4AB-rI_[=R.P?C&/!BWWhiJa-h^)(SfL#F&c
+%:U*&F"Ua"WPa(CQ_F,L-13HFJ`XWO6d?A_r^%ShGArJm@bK,!@l"sc)rCQ!*"n6p4Xq0e(1IYN4X^e7Vm,j0^#Nd0kSo/r8\Q#<4
+%?#jQV`G^gR<HTsB"3c1>$h)\bkDOr[!8O-^Iku*a4uQ@C$&mWq]qa/ursd.:l#q'aaK?MK:M=*oct&f:aghG[S#"_c>2d\i<UDoj
+%D]WMfY)Grm)u[R`>Ui"#Xo_)<=nb$mBb(:67e^SLG`qpee.cPs)(+co9/*cYe+4/qUp:;_>NjJQ6Jqn@&2u=$7h8U'SZ)Vc%,FLR
+%%SJuR=S?cJ9HDpE4DQc-FTJ.7$!i")$fD/NU`/<d(9b@d%p7dg[\H@bHJ^V,7^+[7J:T=u=s3.6<j6Kb-WR9JRSU_FXXJR;W\!bF
+%XO0nlU1`L[U]g4ECLPM!/Tn>*,AkFukr<5@g8VeCq@.Fb$&W3[I2\*-q3"QB+JG"@.n'fL'HJ"`W:qRX#3n&<LE_F:AM/k(1oc[6
+%0I36U(i1=YA&QH'b^?c%LC0VM$/NdU>T!2#&6^!I&fKPK9Ke@6"I5nBK1AIqq>Zh/HQC@s,Y@>/qAi&!6D,5ErZ_OQ];_)a?lLYR
+%+HdZ+JdSE+H$cFCO2o@hHN=J5"dPZ@Su:R0^C_OLk%<Fu2&tO/o]`[hr^/VanKO=m7=U":U)%:I^0acT.,F(['XA!N]$u>??gS%n
+%G41K.dmpX1eiWGp\)X,b7KUi9VYW3V&.Z(8h*;6tUsIq'iN)fUXscV0npOcBF@8GX`#S'*97eTj(2,5K52hRDUJ\.`rX?Z'pE*T:
+%X(KFj3!7!2T'-pOM+\M-Ve*R:,YthR-t_ts-'-4>NIou>/i:rp]JQWmnjA<.o3n!i"'?LU(Upl2JFq"C6=_C@#jt=R_IX,&@V'Q=
+%Jld-PG[+ZZke#)oS?I%U9s[T*7qu$emp^[1fFcsu[-pT'S#M_HoH[-I5+\Ch`cj.U;D8ljdT&%N=W@/.l?q.BcCgEN^pdTu(0.M:
+%3*%%O6!I3!q]QG]:?W8so<:,i:2&B\.'/XjdIMmUIo.BEN6ogP*RS^T:4Q,ZB]h-K\m--^0Mm#5EohGcYp,%%gjfR<]Z!nXL#O:1
+%]M"FY>TiCLCS%b;[n&tIm;#pi,q`4l_K.a5cc\HpY"OWlc\6`f<nR30k)GW2RVV!3rAMns+8.n4m2+<G.9ba[Jf7XEQ>fdu]AP_o
+%aeE9[)(loLPe/5qP]i7#KSr\q<S5\f\BKZqC7[m2@1Fug07Dt.fe0rj)@B_B>3[+uC[KW6Gc<lcLpMkK[u9O1S5@rdiq7\O4)<@N
+%$LRtQVkY=Q,:D1J$=kjtL1RtkPIJr6b;WmTPIOshX!+^Xc.bJFS3i"eFO'NK<pLfnK`37mH+:kZ9G;H@c1+S7B,S;<hjDtq!17"U
+%GQu#2kNJclh$.og)In+ORo?&&]+rSL+'\k,=7cVbd?1H%)T@tV)<R=0Vf_@IitY,qT)'XbD6(JAl10\bMK[FjN[;u&d;7QsP?Q8;
+%qX?!d`ZlDS;^9Pgjmts&p2d<^R(f1Y8^'?=f/Mb\--G:48UsHg3)K;o/apo@:?jL&bjA8/Bbj#n.I1E9gioDh^CEHfGmhW^i_/>k
+%PjWL(_=,)A-OD(p$GE4SYlk`5,-7cH=?84Cc-Mor];Q_oUk!=6RY+Y_4X:k!fUmKlhJPc#?N3rd,s^0gNj4+I]kA-,U:nfN?A;6`
+%e_I';DHZ,)#9:>hn6O.JD3nnJD>JGMWNXtr6+=%i/=qH(43]b7^@.NFPFM>\!'HZFh1I"rZ'HDZd0@kl5:R6@P+GXsYA?GmQ_Xi!
+%Mjg7cgNT<.p6`.!J"_$;\?H['V4.N<phV%Q.qD.m9?nSPTTXELAWfsE<j-&.R>+a9b&3MGN1aIN!#`)Y"C^g.HP.#k$3J'#oi%4k
+%4WEcCII*JY(U)h5G&NEUD6*SHS7rGKcLN)hd'UjY<Kd:"WG4ak^-[L,NR[=K7Bq7+a[eN6)5Pu8lfF3Qhiq#Y,o)-UU,XOjIB;Di
+%+nP:l00CCN[4`]5be#^=;Vo+A1(un6`L2(=;p];A#DGk%Ng=e2O=XH<GO[b6V/Oeb(h9TAom%qOQIpQZ()sNC"CtJj8o?;`&c<o4
+%j#L7;Gj&t.O<rQl;13bJ0i(I:I2c13mLcYNOCd/nWd./=]nCFEc_ZR_.:K?k4Af;iet0q\,+t^nbdlrTK])L7%K,lt"/os`b?#gg
+%E;(IP\[i5r.O.3ZYA4@TQC^Xh">F$5*uE9r]>7rN6b#d6!*+eO+KJNP6aIn!c_HfU,3L`dZ\(1f.@ps[!In6;#@QKN:#$@KcPJcB
+%XC7kjF=8lBh8ZEp8-cXOmcDVd)o0I0qN)t3"'@o+=bSjYK<!9?WEkuU-$(uShC&"HLPAaa+O6TU83rTSL(ksa"0qSd'6u0:5Oa0e
+%*Z=(&-N_*,Z3[ro:D$EXNle,-<D[20>5Y;JPLtf(A=FN^NQR"]^S#0QqJgX$TA9!M'kp\d7W(i(!F:1-1Qe"mR]7HXh,@7&VV?-4
+%h!*67=B(O[7dfN\j`5Wre(Y,mS9H!S-8#M/.\FZJq83+^l5me@.*jKh.'IkVEob0aY.W`+,(0!IdTXS--6mX'jsK`./Rtnh'AaG4
+%kN:ql?UQg)>C$:<,uSA*It+u;C><UQ(3A7X50?/.&$eAc\`D52S?r!6=jDr`kfHrM!I>N0b&E]amM6JqW's3omjB;1VXX"+++rXf
+%c*(?4nMmRNFXfiu]5u:u^J`OsFnQOeSLN6)!h?Un(3Bp>fs^_^YV4n:DG3%ZY\'+2io;ZEPSE@=E)kU"B[!XDQ@t_eJX?3<*J+L?
+%XH2OJl7tVFc/a;rB<hC'l$'%=AYQ@SS#1OqMU@=KN@(<A=1nsqQ*C;D#r<q(G%K@o=Z0MNT=(#i8''%Jl7@P557('eRP42nbB<]*
+%CggHNe='VZ/ZLMo=E4]f=/#4&rk)c4e'\=XV"VlAqh0IVM?'2/MP%n!osiFg*BD;C8r,FLkbZ&SEEf26nmi!Y'K2,IMuBlAerP$G
+%1gYd*OP)?#*q.K5.b^o;"FSD-I;JEY<mT%mY/#mS\KFbsC@0E3N)!sa!;E+LTIAVXJ:uP`4,@cEUB2D(YZ+SJj62W;AZ)PT945>4
+%hZ/WL3Wnn(f97Uab>,ZVQQ>.Te9g_q57P&AEu++WAM/P6P#]*J)n\id",@bq#u_i`f:_k0i,D>O%S2LqJ^-DQ'>Ql@oH4pBTA":`
+%1GM^.dj-spl#-""Ng9:opLF.&(M60lEQ*de`NIi*/4ho-#4$8%r`hLU]ROb.Ijt&Gp1qhoaub2m.XHD9QK<9Not7bff$L&grSi03
+%7?+5Fq)7NXW2s!+,jhfF8j1iZ!U)%p"lCN#m$D_C/mF,EYAU9S=F6VRp4h)<A["jpTE#*37U=+ALOq%/TY0m^l-0=[r-!rRp8@&s
+%el0os>%0\&\bo=2q7>%4gF"-C7XWZ\@W''1]soaUfW'UI[$TR\>B'.6$o)MJMt@GCCC11XnKY6QC=d4*7DGRm8cm`5[OOP;$<*(T
+%kWrc_R'Wa!G@MXMN1$8(N?X2fDV)#XS&DObI]FXl=>Kepem&FaYqs9&g>GBY,us"#O<.3cl<6Vq*hC-XpL(WPlb1/!4f_:525hQV
+%GlB/bM_AK\Q]o,WCt[Z#F!#sRMN_:MXRC`<CElWhE2is7R'9VShZ\@!?IAq#*Jr5An;eI_>\:1fL8$,QYK&T,>Y]gX=?q.[XM?Cj
+%]0TV:?P3qtn/,Sj8&5P-kd8p)IB/hQ#\Yr5iAIe)=UHO0d&fM0Vk>@cfm;^q+MEMP8P@l/2QohPSEk/b<Gf9Wouqln=k*5O'Q;-j
+%\6F8rCJ".9aP7rUp6E4ClKu#t"B26+ic6*UQ-X<.8j7q\XfLNhp"+*Og,e1AG]*oX`M3pPYjKB\/4QlnooWm[*hAM,(sK<jrO7i[
+%D/,MWdJ81pQS9sHbP)g]^L;+u)VODXcW*7\&,V5MNa*Arp'-6Yc>^O*l=g7B;[s'OgV7aMQT-1n/A$h^0apmEN?od=2eMqsT#nf.
+%GG:`*\6o1?&b_g^,ZaE1]Jgm@cermaiWYJhX;#=%s-uYR<Fl37.2/6+"-$=,@%J6&LYXdZL/]>QBs*$8Fal>*IV=83KP\E^]Nn`J
+%Y05n(g=cR\A1)kim"PDeFrRk+gXgeb?BT;Qg-1(YNXr:Em[$-!P,)%[e],++oY9RTbkA[J0-YL3&8L;0*n^^YJ5MeTio=/oIt*:4
+%^TYr(Ag7S2s'5Qb77lmLp7a$QM\@3mIK&1(I5n9o](]fHZHh_0]u[*l;F`>NcuT$)/IQW59uUM4<m>\AD$80`4mKP5Xpi?5_(b*P
+%Z#`5,PF\M)6J"C'ZPUnU[''YOEK^NWig?9<=lCklr9mol!$5pTQ)#U0]'T7i27%TakrhF;IUIeU0u"MV'Ld9OX(f43"0-q7ZJESS
+%*c[.=2Y,VY%UGHCnVl3M0ig.U,KXP"+XKgW;Vllg@$[lDi6F7HV4DGm4lSs6;L7sNY?]HV5%:d*n*CJlr)&h^m/7q#%S7;Tm"&Yq
+%:#YVlC(ku_rV_8'<YKkKZ2n@$l+%_COF5u9lJ!@p*3Os+s5!#@nD5iHpe/4cro">Rl28<FXY"6q,Wi.q*Qs(%.D)`N),q.&ZB4V*
+%g2>#]$sjg!>1Z%UcWa!4,klsX(V5D!7/k<QqY]g91B!PhTe4`CP6l97$1c^Jq*4m;jh^j:1f+ZSmD'lpnkB#`aaG[r'Xk$j(jT[5
+%p>KdX0$j.Wdc]nMefWEO6KL\4)[e7XotQYT[nHn.JR"da]er=uR87:7M*h#%F*V#"-q&H.!cjk<%Z$TSd8;13Ekb=,m6qIS"+r`o
+%[)@U";(ZiBOh2`1DgT4d>YB\f6D?3!`TZT2PaG\HD2Yj9kbZ@IY&kUTa&]@4-b8$']:q9nU`JPB6Tk=)V4>0H`u]3*Ks4p!@&*ol
+%D9)\sp!&@/_Bg-B?h?_Sgj1gkDsJd(K'T`33?)?m%/hJW^84XifgYb:Qf/W_rCWn!G8L,a*kSQc$/9=2*U>h?VSFd+qNsChkM4(t
+%Xp$Ni790#IY8<bt1Jl);Fl#tkT$_TJUekE/!g-GM=?BOHf2F[les:>HSHZi)X\Xf`*`;FE\m:g@AB>DF0Cuad`g%Rs0$IuH-nR#S
+%^p'7rXhFGMPC.^Vg?*MZJS/aq#6BVIU0'iDQ1Bh![Gl!'6J@Hgr$!!&pM,0gFC+GLm'quan]2(LAVG&XI3Kub6R/u71C5!<lu?Vg
+%KlUL&c#39P'2.>p:"1\HWEHHlVAS*.A2,(uOe^\?AhR6?pia0H6nk+(kGHTF_K*#C+PS)M>gG\l+Ioue&V03m(ebCQ+-df`Np=`8
+%U5k*U"fgK\"S[\H)TeA$CB%QAE:4Lu,cF=[D8nL+F0Z,h`r[oW__c_gAlWL.`9)e]fqe$n>cYt"q>,$OVb`d@o<b+e`hLe;ZdO4(
+%BApbo9oim+ha.SPO=E,R,cG2QPU/$OY``H84#cshj-gGtdZ8nD=;lEZa@5#X6\>*rn_J37.UN""7+UARC8,R`!)'>7I7XWi6CEFr
+%S_X^WBnoUAY:e$,@B7uP8g#.L,+$,+F?/7J`s@l!cu3bHNkDN,BsNT,_pX+#'ZU+>>VZ)mru]>BVuCDZKb!M_+ui#s`ab.a;&cNn
+%9t5,B-h$@Z/%rjh84'F];a*Z>'?;aH9D?$nkX/?HP@oE[njGr,Q/Y5`lp61dMV5eCLBC3:>X4%^)/u5/E=j]YfoeKFbcV`0m<Z]g
+%9B#t/)/#-t*0%'LIj_d=F^4.g9jR0X-\QQC^c-Y+D*?kWj=oLbZP5)(3,X#p@r%YF)bGmh+(E&'2Cu1mbo!f^fHJToNPnOR%`?l@
+%KNP4G)W&@\\:pp?QVKj?[U3Ir(F(@!;("BLVn7]>WN46r^@(#;/Kb@F3BqXDR\+>O45@kg"\QH!^:aU@^bt,LFCjSbd:n%N[oNCr
+%`%fU2SMgq2qmi=+.h1:></AlraYqV'X2o4-r8uh#e6EjDe,n(%QM>ITmXFeG.p/nEVCDUuP(6O##<70BA3Zt@fsh1TO&pZ-N$gK7
+%3bQJDbt(<13f3Mo2(U-fS'>PMggXGu_g\s5`\us$R_u>i^QgKc8O]mN8Dgc@IYOP$?10?/VEL??Gp-(3$7\Ho,#Y`kGl3lQC45Cj
+%B5=B64Z/'CXj]8p80+hPX=Jmh0-*/DIB.F$S[#KH,(_="lEDOU*k[XWhJEQ:X1gaHMhU7:3Nc9[.9G1d_Ue-,jr*T+4l4b4)HP!H
+%QBET,a?4ot>;WI3ZRW)#6D7O1[t7A4N&&/.>o(\kE3Gi$>h.%:iC<?L=ZFD>gW7BgJQ2%]/-b-XUuJ*XReNEnS0`AfF*nAq@-4U)
+%=(@$WY>!Bn"^SZE9HJN//(8*KQ`^fh.Y^@+ZO8m*^I2ZdKfjKb*e&;qp:S=Zmb=4?egVRPkfE;fDC%FP9qZf,rj&*n+(UEPHgI-k
+%\]a+<]X4"D]NK_4>dR!oh9-hQ[p$kYkF=j#Gb$NA-CI)PMq<3^AAhqnO0kd!&q\Z^E=q>SN\u.2D`$U!WZbd/QE3]^C/r6aSUQ)D
+%fb\PG8oD9;E;Kr@EgZ5=\0TK&Wn3"=06Lhq=HcuOE\i>IXNmJ-MsRce-=]Mm>Lq1^-U%.^L24E91BBu7kbl52rp[g&YO?Z144ZKV
+%4RcjFnnpfN'[Q'tR:qRpdjs+b0Ib`pe4Mt<Pkq<3%mIA/g?a.C1oFN#3]?Y*B2FaF]=;GPe=s.GO.B*ni9FE6O8-hi"E4U4h%.1&
+%^&u8PC0VONT8pK_'jMMBR!'!,37m(Nfjg*ajE\Gp6-=<42hE-sG"H13R,;gdr5)#KAb@:"He9/Hg[n9k$,m>"V_^-s_rNid,q,._
+%"suVZ3\5NdfnCCfJoe#Kjo>_u2eK"4?/aldN2j=@&atPi(-S%@a_e&^gQhTOj3GqX,!X<Gqo.S+"cVH^no>,qFomPS_]#cDH]Qt%
+%Id,])NPtFLq?K6T0rYC'`A.u=`7Ft&S?*P:m*'K7ZsQh8/"3Q\3K:-a=ui!qC+DO29CW8Hffjo_,!ORRNOrZBc(]Rsdm,Q1PJn,H
+%>V51B-ji&rEWRjj2[1S&L'3]U<hs0YK"Y58/2FBh8$`jJR?]%m[>SH/[W7WC*G6BA,m(DeIqd9SGP`k%+u(=:]&u`*D5P'ZjCV:M
+%T5!J![*`%/o1TbAqGbHm1dbj/S's&WR_ccP*]YVBjim-J+deHGM7C+]dLW!>+*74=CVqt"/irbVUum!@a?KiYAi=q0m/"m2cn^;*
+%m'rF;NL(D-/BG3fT=l7%TFdt=gmU4H!SfoM#aFl2Y-c'hN3Xcb=[n=(a(,;^:e_5QZA$l4WOEU"Pum%UTYQ^S2XXi(dbN^Ao)7"1
+%/hAi%KL76T=GI?qP/[3p!)MGo&"T[k0[j"sb'rWQIJiKY@6"<#Wh.A^<&]QFaiod^P#`?bh_u325]5mSS40]k!&![JMu<=2FtXXE
+%NnSF'+A;N*P7!JL"[.@i,/Y,)lYH.,/p7i,7*#^96*4LJ/b:%c;cTKHYkjM-=!tg3#$B=Y,8/e9o)GU/QY9.!XV4kOO'>f@`<*OX
+%g@jLZT`e!cjQ393L2IfD$F]=:B)_\[mX@2%QZQ!EYA6d^;l,T=]"qp*,[cXn^H"D3SB`XZI)iOq_?,)jW[\Ygl9FY0g=6/jG1N6g
+%;kp3KmIG!6"c1[tf,J#0G:M4[-C<.PkRa&^E;(D0[*#PFXscPtrK':(al8_SM<\ml%e"P:.?jJ/*s.2Y3Yb_lEko9_>EdmI%[Q(H
+%]m.D18'AOl(1'p>6?'U2a#kk&f&u`,D-NtO]5j;apio46[i5r)\Fsmgl'%B2OKhG0"4P\@Lp]&7<aTWY3U07jO8XmM+I?n7RbGAe
+%OZVsN$]J3(F9HLGpE2n/IT7r&@FVXN#ct$l['."d1C2P5&6IRnCl?Y/cu&RacK8O//7rc__t%s<b*6!Ag4$<2dL\^Y[pVb%@7$N/
+%gK^>@fa-;n.=u-EK"_Cnq\dZ\PY(sR%[keccs;?]HFopi*r?]77*N*h-sF^8'iR#<\:A#^1e"!.8g4[\&map5JO<]V%aGK[ZZK9[
+%`piJ5?ke$bbtP3GMm]_((7S)_"a2,abbGpL808n>eJr(2c^=Jd%/12%Rua5hp-rGP?QA<2#hfnNG5U()>-prU"MgTok/XSeWA<[L
+%]an`s?sPS4GCG6pN3>M#_Z:nmBLQmm(4!I2%UhYfOV4WGpXffg_8^ik>Urp2]8@!QdSBsu-ph["Rtd@UR-c:VS%7BXEq_b!mdj4,
+%,m\D%ne_*iR$F#%F*XRN:Xp=R#7fjo4`n/2#sH/thF/l(-j'W!NJ4,[bgEIDK%;)XG\!2*frSqKB'"["X/T=)TUj=ON*I*+2Lsdl
+%Mp#q>5baj948Rt8E9q/7mZ%0e*_VqKC*Y%M5bBgQMSjW\n@Yo,ej\Ve--W:CD#%L\bRO+a6sXjSLUj!HV=&F?Dk'VI=F"3;95A8V
+%nCCIuga2p(d][ta:s%Y%*4.M"KW@b*Eg;Jhdj6Ot\dXaF(XEIHYYP].cXE)#3HrJTb`fD%Rj6F+ER:_c#gWp[HtXiaIS+YnK!#eo
+%<RK4EQo<>'I#R!qRU:,_e:XM%fCT><`l/ts1pe"(dEmpOlZ)9j+#>jOCMIH8o@i%6oo!d5WGICTE71OG:c'b]qmOsAR&D@!%MIBQ
+%>2)&`0]J87Ofm4DEr/#8UD:<%He>bTY]sY'R/9s<&nJ5>JG$*+4-@`n7.Q+!Ht3S6-p/9YfGf0jFfA.Q\;4D+_5UD13eKb@46l[*
+%V&q''.6*O`_Yu)s5QLe2V-S"ZER/8[6+CRdo2[)H+?fY4;/`YA!jFMM_R#.,8Db26$,R/e!YCUBMe$0Z<6):1qmm<M=[VE>e=c1d
+%,onUb'Xd)AqZ'RoGh#f6!mPqsZ?R"e@M.K':V/mf#!Q`XZcR8u:l]o8CsIOa0gYh>]^/G2W(Ab$Qp@pq<1^l)kTcf0(O+7YM7O7q
+%9`T+/':W]sW:^X)\U!H--$P([K*:7_"Od>\q(NH;P0>6L_>[Q%bkfisMR1iO2[%"<"#sTRd@am8$JtkA^GE<7M&9Z<:7I_^n7&:r
+%lY6/seR&MK.02j0WBfaVq$j]j=%bFC^9*$4Pb7d]j>Var6s0<.?u\g]K&-=cR]7VFB'frT4/QA[g48sSd%fO)-:f*$>p=ZtB0jFK
+%J9<?Y>eQPF2+7lH,G1F1,tJQZ[V+!RUAhu^]25%:(aE\u3Ps>!A?Ip?dI!O6!YNp`KIV6GHYhR7B(-f\1/5`)[8ZDCioXNk]5eOh
+%BW7_M9(Ln09+ektp:e&d;XCUthO,1^5D=T%/T'4KQco7\7jh%IHW=.,8\;d;C"kO=1(ro23B22F)B\\iW1?0JLC$u[WOW0-9cIO_
+%,J3`Q,HXH`-X>b-dO%(M]RD;$ZuEkX]+^^+%2Y5c3/?lSl$R307SjAn]5^O#EY#uqQT6j*>BgWe*Xpb-I*c6:l16]9N6EhiB5K_n
+%S`OWHkoW'F+VL_A^Eo"?/VU6;DoH*UrO6qX/iXBIU@liJ=agYJJtd$cY6(#Xek4I]ABe6d*JqkrhYbmkbZ'M:/kuW&FP@pWHU="j
+%<K1'M:E40=G"K7Cd]rM/Z-rEU;(c>BN/^PP52i4`&Qk`WqfQnYkLJ3BX[.]GC=)8J>u/W,/djMqA48X`9Zk":S^%*I7XG.YAqpAK
+%Ou9Qg,6bsq4^@kNQA\(2RS%N_A"*mY;H5A'a3\DVD=).+2Gn%kOtYTOBc^EeRILL7.o5+WnqtX*/89>0;9Dl1RVDVgFoB*4jguJ9
+%pTfE<dD?&<Hrr\sie1[&fjfT0g>mP7ZQrR?hi!Pn]#p?;+n2R-;&;s20Ntn#pO.I;;kh?DI%n>i9F6H,^n9qWM%[4$8YfqrWO$g6
+%0QMaPlZU"BB;>akg3HSK8:cmef<-_C')_&pqR?B+W(nDG"JSW^;bp6G3+ot1"GtBWGeHd]@r;iV8F>WtSSO6K.II4OX/lD9ZAKhS
+%<m`1Rd:g-b\;LIt?C.Wr[pkDV4_EfPI+gV1B7@/7q)&c+?mViBMd&7GMiL1tAuq"q0f!^1<ku4"';66DXK"i]E2@&6</&94]1h(X
+%Zk^X887YjRDVAjEO3nrkRX)cabf!I3No6[LB]i^EpV:Fr%IPicM2A_<j]Y:7k0r4DnM2L.@<$8gkt5bm%Dd:M"HpuqC[R@j0Z'*'
+%ESr)g[T\r3+]uZAD.u3K@GSi.X2Gn".Z1OT(`.]id)fUIqr;P.(hYP7l2jY=?L9+kk``$mR'ahZ5'5?:T^GuCl,gYEKP#2Y':=)P
+%'"c_YI:cqa`''D7Q4,ZEZ%gTT1b;^62DAQ`gVj1Zo#[Ypn1d\GA72,#oDj=C+[O4'\]aVt>CL4sbFQZR-tEo'AQ&*HdJKp0iH`*=
+%f6B<m_K_qpH9d9FVWJp!H;*Ub?qg'^8m`@5lOc&)\.a:[l$O.1Sa(S_hb4nf0Pm+lCGcFV#+aV@[F>tBL/>Ve5m5sIGtbo>1U-r)
+%S.6lZ&]D9l%7#LuZ&C&-]d0f)a=r37OIR5#N>9n>#PVHHjl$0>6nk^XO6#qp5!NBOV$LS"B%X%)';G95-"MO6hqLGb-6QPuV=F7+
+%&6.?.Shsl:rde?S:o]hsMEQm^$+e6iXEcqsW?)^8Jt1aqjY9m%l1jgk^,?e_pB#[R</@3(@DE!ZXPB>TWZ-F4fFoYG9miE!Lrn/*
+%nEG?[JCUAW(HEgU1-,IY\#e-u9Up%%G)313V/Ye^Sp-crJm$Gm!s3:joO(.WV2q$eZ>NB<`+WORN\#ZE.Zo1_Y$R147NWD<7r[nm
+%HEE-J)XEs)@2OQD*M]MC;qdm5BDViXR^m@O9>jRdHXGcfi2R85?2Kl9++f?Z7p$G[aSKHio&%H$M+3:ZM+=0G)Q.ib?26.8C$j:D
+%OA?AC.re,W:pu+V(!k,,(_s.hWN%tFG5g-TIg/.b:`6=l"Y)kBaY+ssl9Bs-ppns\+6(mJ(O2=6.N'!+]:B>ELRX.i?D'pAGIl",
+%Ol]u/Pru>2>-D^H?Or':'f>5j#8HPU`GY?mK,UudE*_/<IQqRR_^(npS-X!K`^(OCd-Dl1q2dt@UCJ?r1^R%qk]*`Uo%[b@pgKSW
+%[rW5Q'm'Me/csfAr=X_Pna1&>`_$B_e;QR?=r9QI@%9sFSAA)0e/]\L4I3eXYbEq+f)8iI.ui*LqZI2(QAU4I[:bo<M[KrYHmi*$
+%RIM,5BD-c-,VX+0WIKMl+t0OoF+sG2RqQQ.U"u#/+e<\FJnO9GjuN5YM%g_=V:[5F^9A\q',\*DBHuI$O'YH<&amp)89_L!H/V.b
+%jqL<XG6Z8cd*VLJLBrr.(oZcVj%4CW`]&\E?G,Q'0IGRpoZjU-\jSuH2c^JpTq"NrHf"GdoRSMV3[aBm7sdP+=,/iRZpp([p-GIe
+%KNGiEM+Wr08G0QsTp7uQ@q-l(=(?Le_a6$X886$9QZXLh\OS76>J:)UpA#r3%9M^nec/sU/V3r$j([kU??^/tA)Vc._n9j$@qNiW
+%AfJ_Qg&L[!eS$5]n@We60p7@'H&>'Abr\O/k#g_<Z;)R0@'oL=0\T&dRPB_nLN@'!Yd1`PhWm4jP*C=)fo/gll?ClL_4Wf2o"$Ym
+%C%I%L\31J'DGBl57\Z2L&`&:uc^*'M=]r6je=$i?4Q8,BQ-6[DFJG-<p,.%>ka@S?>=krXK_J&RVJT?,9V`9O^*PgTR[*D/T)GLe
+%S]`KNRj(Z,BeWJAh./D6#BgTZ(ja/XrRT7]OSVtV_>lpBT'M1FJ=1E.Q*(Vu6B#]BC8a/$7!Zm^nbgmCe]KYN^$8AEqt]O/[WSfF
+%MToAse+-O?htD"'*kl1V1"TEGPh;9@Hdk19+ZOAo`kagoX^&?EHpMer?S0IKoShBo)3rH<;O8oL]dLib/pGr6bU%eiXNhJY4i%]S
+%C+I+sS6g-.B.C/VcYP,Vd0#K+'+[XEasG1<[94dlpe'.aSq#91S9SWss!HPh&`8p.rN:53S[GdK,8J]7K:'0*.Sq<1\$dL2I[HI+
+%D;F"m&aTpckMjK>6EKVsGhG[@]D@;ED]ah&_O/e.h07e2C#q8UkVBDIf6=&:@^s8qPWdX\D>FK1OiJT%9g\`8,52qa%OXN,m/uUV
+%[dl4J^J]t>Jf"3Om[?MQ)&dM70[`3G1b!)PEn#C-W<"8lMH"9!>2aMmY^S63Tk,1]A[EQ`WhPJ1$S+,f)"+!Qg_VZO>hrXBRoSVt
+%$.!uI/&BRY*XktMf=0@Z[3)q"HArV]&,ts>X?,aOp[RWPRun_2"$/'3@m4K!V&7`7;%P#Ho4'Q`!7'k.Fmm"kSJWop/.9E?r:no8
+%J?W]i^_)pAl/"D<VcLBX$+qn.>p^u.,j10B&m&,;'dSM<8OoO=lZ0KbF(1`kb`+LnFM0(hd5iWlT7HHeN\?TK=q.9kXJ)<&LJDD+
+%T)^0B&N8#qV#t0s.e$m";%CF1OQF^"f1^trjanRN[--tlB(G?#l;.aZ.-2pmjC^cgaW^'7('/1M53mo@?n1$l;\deO+Ge1'<*4f3
+%5Q(^gYD1V_l&B;s9IlGR3".#I9+<)8Ot?;k6?%h3jZ^kh9Hn/KB%^f,;:g`P$Q,(3,_A@,#N#.bjVXj9h'jbJDO)B1^W^CD1^Lso
+%J(!+*Cs_EUD!ZmbRH-G-p_:!DDt1baG3@ZOj&I*(qOmuje-q*T.RD@d\DA>jPK.>NZY(@u"GOBY2OJ,2Zu6*"j]Sh0_?cAY"0j`@
+%TlH&rW:k5ToP2k5k!&dM?K=SAYRi>i0I!%cV)%B?O&98#ZYg_6HJ9Co*dn*nileM(pT=Magl4`VVqdgKb.-Rm8elf&K0du*+u444
+%=B+_P%9Re%E:jAd*`9TYl.HD5&uhPgS_,_,+"O)0'_@oK5/T-(@fFB3f8SZV=Ob32GDR[t75_.3&JP=A;S9^I:X\(C<XU%V<o$k6
+%W'U]#j?lW9+ne7$XJM6+&+$pLWke[]NJ>[c)0F3h&D*(RAM.=/_Q(/RkN@\p92uco),l%t4s`pm_bV7nWO?*-,fOo?DW3(E\[0_H
+%$4FrMpsj%1kZQAkM]FG0"lDnX@Gj^:Ef&<KfN1(V?TAkolXSJC]Q^SLWDUFbe.F?bk(c-!go=]4e-LDd/IA]VT(Ro.26">WObPDk
+%I(pK'gdudVio(sd[j3NAXB.?\]&&m+hp)r->e+L%].t9>ocUl_^&LsO^@0hc*!fPmqU\A`8*aXkbmSY@mEEP)X&SFfQI/WaCOY^.
+%=2m=q*.Q]'LbDA%0X[Ve(9;7`G>(6hcO0_KbC6p4%WfR0?PF1FVYph\fI-KLN?/lAl4PH<F%/i]Zp87"48,5am?puS\;)?o7'P7-
+%2pmZQo25[7m`9#..,u>h[Nfmpq@_k;&RhM"I:Y'SPRs;@@%ho,eXtDo>%$0D<nsk<No+8omE)[I9']\(OQ>3P/(iA%"1[TmVk;l2
+%0;X6tZ2mY`C<)O\S1TR.j2k?/"piIeTl_S*WWpt'&D&gd,X%s%P%[eFfHK>ME9=DsA8G.0!sj2R6aIFF`<[,2Phoi\n*HMSo:e1t
+%BKUGi\&$`,@5VE0OI8t,@*</;5Sd/LcB[ZDGNAMGj9pT-T0tei;UbW)V>u'[c8WSIj_d:`A$+OQ2EOZO9?4*[2t"ubeN\#Y+b+%c
+%4bC"%GWX."PLia#,#Cu'L-%Q1\\+?-e6`ES@jO1idX3q;DoHC`$2&;;O*`gPSO*mZW<a-<-u5s@GH4<WEaHYe%e]%8B^&lm,^[BF
+%o5<4894oV)9iR[PV;XhfJ9[$2=$B4)`RLpG<=c%63<m=k0a#[-;Y60rpeConlGjb=PB<SDi91S0C:9N@6*ZS$;[t1`[k-N$Y&LG:
+%U5:WuICQK3V4QC>cb&W5C-'5S5A#DQl9gih4mciN5C>RXQ&?H8pmc`&"!=X,K@Zuho-IHhM_aq32bPb';R>GG>M[hQo`LZtGH)bQ
+%+j9p$rY04ph9r7&W(W:GcIH<l^'Op4;F!*j+M&#uRA;5[m9_o_9?V"l<[hLZZ;Np1H<me*P9Tn$ZmgbfdIPq:(][=?T_\/+^EaE0
+%W(C=7(e@o6$@d%uc/PmnJ\5!ibf98K.h)IqRW%WdN>7]qV"<B>=e\6>_@H]8[p7n:j%W_BX.^L07"]_iFd2+7>Ge]QP7q0Sr#fp,
+%%)T/Z<E7PD2_`cM;!hXeh=F-A[81YHYANHIlWn\9/!'P9,+)niI+KH0_B6,0MtWD$>$eY\]GibVLrh/qIKM.CYSWW#Z/0Q-XU-2p
+%9=-Kf0ijt1Wqh]'?oui/>EmZF%H0kI9Q+s+3H@"`DY)"n6+Le7<CqSA2W-k_B1ZX3)R;Tbf[]ET+'_22$JJ'lfGfEoT0<?q*d=%n
+%%\g0O(\tP0kDLKcFC^U+S>f)XKZcoA7&WK(pO5>[qiIG-YZ5!uHHbNDY*u;1BI/`+Z"dFKfLTXa4Z4+5i(:#OB%Ot1(H$iB.;r+G
+%oNE==S&!t\#29[_Up9YD6L]et:=!]bKh!g]_$DPI3iT*_DMip!jbsG8KMkdjI1+]f!E+RV!E$iJ_=5"md$#_JM<h\4@K&g)9'fd<
+%+BnH6flkS_!ZE,US=_g":XM5I57)qtbb.sS+#d=m0\c/b1KfBXs'B#gi44Q/f"@Eh`nC+UmP19&`@"L<(7-FYPlVLOhk^$93'dl2
+%<D1?9h_qGoiA8!e>mIr04L\P#TB$Bfqdj(lU1Ul1h1I35Ya/"2o-c0k@ncNQ.E:SDY`a8_XEnmXkrp-1Q9AOrQ?Zs5h2T(2Q?u&%
+%ii<gXqJ)1baj?deLLu+@&)gC'+aW78:PbZEWO/CI6Jt9Y17"<dYW,"U#tNDUYI_WY#ShsEMAtOB[fDVOK.$-=DusT.[`VCca]95G
+%>cHf,TLk.iQcKu4Z*7L/iG<B+7IEp-C(bc,.Y1)&WG^S`if$CM.ICQ#R5/,sKQ7n*#Uu,O!W<m*/_R,An90rN^rl7daY&`DITXM^
+%)))T?-gm5Yf(ug\UmNrV#F@kkK"STeRrWj`N;@LY4n$&>qK]@h1i1j`o6Ziur_Uj'k!Btf!h3/KmI5HpaAS7YP:@(68P-YJJ.d#q
+%E7WbR:?>Dr_J1M&YCpifF1ELX,tD6]4W>cl/C3^r4umHqY.tB&^Y'`<Htn0Y2#<NAJup4c]i[[_+]"s;Cur>nq5YFl[@[>!=X>KL
+%q[pY]V*[!HH%<rAY)p=OZqlE)U3]R)Vqa%[rOKQ7I5:/DqPr&#(gt3_Ou<!GShO2(aY:-TMY7rJ/IS@;QDaJ>"u+C[cg-`<c#?Z"
+%msmJ@+hPO$cT\=Zi#"pFG-tpH4HFmK2h+.;'<OB(T3\sY4B8i0EEA_Wp]97QA3"D=Xt-c^EV&?t4M/k#&U\T)bSZ7)=l/Ki<+FUV
+%PJ:Z%Eu'*IWip(^=(/Jkj\PJf6?MX_`Wt<r5AXJQ"QUu,jlWm*/"OMB'&oi(PNRG;I8LqUEgi\nOaUC=B)R//M_uC@)d+#<i,GZ$
+%Pf"2!7m<GNg!qL`dQN.gD>,ZZ(gfqmkMY4n@U5$ITO(aD9t0/3mO^/]_-Fk[fQ"X32bBbk^[ZGJ<*/PWQbC(3#-Dq8F^#S8X))l^
+%cpt>7P5#"UCNl`e>8%"JOW)Re&nVB@qU_MF8(_D4+E%VmD_UY1r))9UrhP?DKU9AA;C6_B.6I#lG6,=0KV52,eGobE#6QOR(t?/V
+%aq4'0VPtThgUT;MViN]-"erS.^p=P4D9$T"qhfS[eN6KT.i&K.9mp9Q1.7s2^ZSd'L^/BAXEE^(hNKjVmV;2=OWq<LFn_]_WsMV-
+%,gs2^<1<22f[Jd?MNpD\VjAo@^n64$^4J@1n`KFcXE@rhq&2EZ_ct)lZ9t^;h3+_^GXf:?6CiOO!:!/7)5dDTaX2L_0E*d2X61e`
+%%](M_<QD^_XO821J#gq`%GNlNgBE2?7>0hufsE"l:`5H!q4o?NZ_\ViNbT\"53(Na<Z6:QI?_q]KkRDh,Qt,Ar,!9"foP%cSeqL9
+%+&L.0hZsQ[D?Ku&/EMs!RQ%"<DF;*#,LO1gpD\s/g3->;Y9d&6VLr*C6(6h%55Fto1%%g^X4g4uj=UUh.P]kjReFDjIPo+.,1Y8X
+%XX0C67Y,>A0s`5V]F\_ioMTH/@cdEbI77)hBum&?K6/Acl=$FZ>K?G;QGYkF:A"'?"<!0Mao^rmDa)*7?895rO1Y#Hd])=,=DXmj
+%=VaA+L7PKV7YXK,2@@]k1M+,19B2k<pt?Vqoe*rN1$89&D:FPB!NWk8fX"dIrC(.b=&6-YK#/h"<@Y]D,tK/R-7Crg(-j@KX$7AV
+%0)co_.Ek`k3%`;qTl&0S/bG>kQ^(nef)JMTi(:&I4@O"8iF?WC"1Y<kZ4;eS7sKAl>`oO&P-GA,>#uR-_ZN0L`B/2-7,H?77Qn9`
+%poNoELY[JV^pT5pIC%=UW8$%nM2aekp0sh2>7>I%qf+0UH^DNsdDIDgVI@M!@g()$UPMrF^Fkqljh&'D"W526N"MT@AiB6n7_W%N
+%'hfjNU67>Hr>L!J)S*@E$ol^$kspGHL7H6>)..as`F*EJ0PC*^I/S=AhZEu+j/'L(iU)6n$SjU#/lq"n(E`cqoP0uB>XBcY/Hr&9
+%G4SYk+0gKoU0Gi#ESp?%'&;`#*ar,kfO6Oee%,_qDU.Zo6G"l1:A,hZfF5tfQ^DA#+8-k\G7:MU^EJ4k4"[n#j>=*r5?70BZW3u/
+%XB4[df`D^hVX!/SKU),0jCH2iV#XGs^Z2.7O)@+Q_9=G$Sn$VToWf\iJuLVMG<L1.LJI2@m:e*"?A<e0V[W^1$.J2`m-KOWNOi&-
+%@pXG;3-*j:^tgq2[k4ci(3U"UbU*''A:.Gek2c\`&o573>!"aqdjh'tg;4T*JOCIN]*.ElE+d@$LtZr0d/fA)W,DFJg<-uV$^*cS
+%ZKYmG7[7(iHek".+)sr:`P*"5bD6&a1AD3Gj<'6SD4RODp\PQZ/UC[d^1U9jih0Q2ZBAf*0&!tlRH$p2%-m.r\!94N>G_%q(>mR4
+%>PBef:EFk&\tX5dc<djCK6*iNi.UPMj+"0Q2cSD9[)dSjZQcBHm5'jp%*mGGV,pfFQ7?!b!gh\$D`qpO$iDo6>1oPTUiAA=XJ6[?
+%p9@$?j+Off,*K5T,nn'',9[$a`BWr7/oQU,EdUV[r]]$TIQ3N-.(Y4Fl(!nlQB1-QM9`Ni3Cd2jZV<-9_',q\SJ>#gAfcGk2^Nb1
+%&XN"rKB`aNdb=)0DtsZhqtUY8>&#BjI@V=#p-1rap`?:F>"#t3c!3)Mp$qG!fRC)6pJnd2;_*F7O5)G/cITr*VL6OX3eAZG5#_,&
+%KV*+g@LHuXEqPX#L0"*J&i1Rf=4L(D#B5fh*P,VXhEcc\Ds>ElP6eY$eQ/"j/0;u5$ijEiE&6N0!$hZ?5Sho;(N?-!YdWlr-P3*D
+%b2.qTG%$YRe0cZON)a13[]c=Q,;i:@YCll)B.[bL:gP6L0ZM8mc$.(N6rSQ?WfVP:,uCoF8?tjnSCQ4NDh7/8TI9$>h/cMf!l\)r
+%+cqi]5th>lO;Vo(muG_&WrV3o.lCHC_f64.?Z4Nq^H@H*Om(6mC1DXc`'M+M<5FX?Wh7dY>1,Qn?#]R*/&PWFT,@"S&!c,d*8IZN
+%Za2R\95PiX([#$(WLZ>4'TOcTXXdu__Co*k>"^ak**7LArCHhcTKr_H9uQ&i_Or%p_[/,`G"CqmRlsIp$:M:8QlWg?MV])#M!'os
+%+3o"4_(EN%<En'54j#_KrKP^SDr"]])"oPS6_4rigDV&^G$i4lAeb4jDA'(/%C:CPg4`G)NLuIeYC.F[?"].TOK*"cmr,e*<;)pB
+%h*1NjL5e\D[OadSERSo;$#;m->*1l%fKN9"KP69D[6LOARD$Ft2iN=UA3]^L@,4Cpf&Y]>7NO'AF14tmd'p$D3Elh2L=0A4F1HMC
+%+cXf+n*fCYZ5+f(X'0@H^D39>T!lM8T6Qs/VSl2,#OWaaA5Bc_\4i@'58BcNl+cK?.lF1uQ=_5l.JpJ_FP:_QV`/473AF#+>S;RR
+%lmfob5s1M-(/#X87D=)uVI:dTcYOO+9+ecj8\SbY#u[O$p1`,rfG0L'WsauRR8QQo(=O]uP'A6Ul&tFsLGTs?99'rJjQ_3Zb>^6V
+%0WG--(,Sg9X!8GYRD:Qt,SU)<.;!iE(XRlHjfUDC-f_RQ_QJ+<l1.;;(X"]lZ)JdH>@VD>2(>M0K^N;fpN/7r6j%Ad3Z,%+.p:7r
+%(8=<JF0pc68sEY:DC0Hf5.+.e7]9,!j:N/[+DY;h9%LIPkH6YtTNS"MAk@8]603tO)dNWb/D=rs/>dHQ."dIL)jAg_`;;HYLGSjM
+%jWcHGU-%Qg9_^Ng0I%BoC9:C@fO/l]*:nd$fW6].P5SAR/:!O`VB-VL<c9qe`Cq(9bJ5&4AA@cs)9$4!CS[EDE&1V?`%_4rST5kb
+%*aqe*=7R0EA"H.Z265LR"j/Y\E0%QY(FlMYfg?=<@o>W`[M9$(2S5f=fnY3QArGjt@SnlLT9M-m]>1ch:S^&M_$BfO*:+C;V$'c>
+%p3bP]7B-HG+%2GrdsbKnPLsXEja)L]C@Pj\BTLgW5F0NB#]&D,$#n.LW[t8BBU2_^6T*dE[-T<D7:%C2qc]:\.TIe"T6s<aOgN.+
+%p)(9rnQBmJ1U^0I.;Qr\H4'NHkE@r`pp$S:O;Ie^dDL<!SZ_2L=9`^'^W+E)&!;KaXf2EDV`I><bdL_gHmH)HM-!#:D32NCQ&4;&
+%p0/Y9HB54`oYXc?[kY2_X!rGGQP[[\kua"S2'Nl.[&7OT8hf&,pUaf_Nt#@`JN0haB5Jg1*''g-4HY#>K/qsLG2.NeI97Hb6/bh<
+%XtYMJ4(WSt/b+7nacC:SnG/#h=*t=f1$h76U-u*;gdUW1Lq+iRjt<Goi8'_nm-kWO6GS2C$BVlh*mYSF3@Xf`U@$UtIeI`U2I!nn
+%gF_K+%bUcS+rQ7RPU)g/CMP"Vpc8.Ig+$-77X4$WflHLLZkkG\E^+H9"'*cr)UoG#!X&D+6T1=47H=*e7SeOi7H5HTOdmd"SseU$
+%&X3ZF"Cp+s?JO>ajtLjiWSX"FkAd12J=fc0A#/Y@K6GqX#Sq8$Loq+*M<*YpqZ)%15jX`>a.<a.@XNCGCta\-oE[cC^4`-4SuDRC
+%NtddtCeo^hc#Keo&QXf!qO^'b4eY_F\ZMj^LL3)ckUMm,R]gPE%U2frZ)M,IHb_JW&0kA@EGDm:/^[aU2#(i)E\1eC%h>L<USs)d
+%NZA<c5#9GV/FooF(k:YWpo^>QJnoE1,rc&Po[&W"<qk"Dk-g5P4OSAoT`%Z_ihn?<n07HQg?Ac52mgaoJ*_(o>DW9^DDGmAeas0M
+%`_Z2mpT^76Jr*0&Y(*afrU63os*1c,Nq:tQs4@;I?Tp^Sj,a65s8INIO#U2;o7+1HEN?H2jp#*A0.Wd%R`<YK%u"$TM/V;-V4/ZT
+%Hjf\YWu5dZJnAR`R$NW.3ZkEo97\JAj"i@e"F5'iaA74=:"TS*PLT`M*B\W2.NJWZdb[G"BdI*cS?i*5D=aMKh\g!WOWpq09;f_e
+%bRpb-.`0m]iWQj,qR;&*pVN<pg.O\1;aI@1,j$`_3$ut:TTj7*V_"?DZZsV1%O[#H\1'mq/icq>a$?DT\QY+NFT5J38H]67$VRI!
+%)63(;'f0)i_Bktp?:UHUcldQgaL<Ieg@"_0OY:Z^]%'l1PX2l8Wg4hs#b!=Z@FFhc!5eVfkr/tqVs9EfFFp_R^-l5&L;Dq`80"QF
+%6]Q?0OW@POZQ_=)Ms(,ijm[G+LtlBJd$>[h=qqW+@1hm!lSs8CNDeFK3j82\JkS'EDAk^O&SKX)b#J-@2XN>k_N"5&D9g63VB"OJ
+%Gm6?5mbp,j(cbnS-!:N9qj)8Qhnk]<#epAr_g'9mMS"MV_'=jU]!*/nDCn[4S/%*/(L-53"SondMG-)t!\6Ura)6Gp`\>2%=$KC_
+%H4)jNf2npPSsuFQfGZQ9kT,eDFfpLP.gE1bQspQ,H)>F/$`K__/V?b.`=(^[W@fA:X$>YC%SAo`[)r;<c5\;t78R-!o>VcAWC'a6
+%V5ndJYKs7%LV?)=>NnjBD::NdhmL1p!-_O!7buH/ek,hU.HioEs-i^4D\7'!AN0:-PmRW3,G-iNVU)EUC=8+NBbZt-=>a/,LrMP$
+%4e'J@U012<>IS))BRKB$bPu7M<]e`\OKe=RJVFDe1#*F$k3pOI-<!GDn8O/)T$F^4ldt1@.,\Ha!0NgpB1BkW,6N$7<0/<fj@]9f
+%bVT[-WpccAP#O*PLT1&%*@jB%kX>2>,<99&;<2Pd%._c4X\iO;0qVQeH"Ph&&iNeg[1Z<d;0%E>#g_k)g`5o,$&"FF8Lu2"T1:iR
+%C]dKa/\pj[>R6\mCjt\P9(kYT'1eq0g,'u9'4UtnfOWqUWN0c7X1GtZ.5=mOoR@2VM6J=>jG-F$6]m-Hk=SM+GnRQE@!=h&W/,FF
+%Mfh@tBd`k;<mB&CJr_\$CIN6kF^bYJdM@A^pe'B,"3l#Odt9,3+*o$Z+rFb"F2`U'$Ku4-gL@?0$`OC=o8'kNU]sdsqU2'Rp'UGm
+%Xc*k3KERs64G:8qNprH(YHkYZ;+dO$HG#b_V@II`R,1%",5+D!m)Wumm^8ub0J1opI'sD;;oH?Os'&0j%eH9Jhh=D<;\`9fG<a^;
+%&.b)JAs?uM;T(sjH;R3pmZOme>HAF<IK7KBrI1h+EN%6'%>^%(dWAZZF9J_BWbR^N'S8Zl4?:p.e63*'HQTGaQO?(@ggHB=G?10C
+%RQ]ENA'[6U5#_^5%WJ8V>I5nCpfmkTp5D&<.DN)Do;V!3*^_*8Vt3[pYt,/M,_4goTTfC(U,$d!1gS?Zn3jUVO]tLHEJ%ij4g,#X
+%oOa:0*H6J@#2S'_`%nO9<s7oqIKa[8/0Cs3`sS":FN'Wi:6F5OI.gLsM1hu)9\7'CbQ3UTO#e:*aF0\5++J@!Fi'7nQ[uj^`ni4m
+%^LM-LXs7B0rMcS]]Ss)cHC@R>4!>(NH+@`,iJe8h@HMD>N'SVdQ40)Y$9H4k!5S>=Q)UC=m%AcRSI=U^Asp]\Efb6G"$.k^=g!n,
+%H#\'^6S-+>?nR:fKo4kJ\_+T,&F8Z1;$E3^WC5Dpj\OS^KJ$Z4o%Gd@/TUB"nDeEsQhdOhdqfA67eK1\QRLk@[&f(*k;)QMm1qNp
+%2\_m9eU)pIk`R?G4G1JRmJF05I+bHC<B&ZjK<[:hHF*.#Y.+D#'LEAGH<3!a4%LBNqJs-)0Y7DC`tm!UYkKU"(TlA`&KUa*GY9q0
+%*.he6-qtJ"M\eba-+]f.a57kcVSgl;8_OtK(%c)9VMFXP3)%W'=9Bq!a<6OG<(?W;'u;["/*JdfCb^8Y)lZUH^YmY4N`>HO>o<15
+%^67C_<e(hh@>G3[9m6"nn?kI"a9?p:h8ikY?:jO1UN4M*4+aGdg"\Am*EF5n<'W6d01(9-'`@`q_lSa/N_Q5hXE^1X_BS%lFkQRB
+%5_Cb>he'UD1lk7]WA@dqB"$P7G0W^p*=J#j.qO>ANZZpJ+3o7,3Hh]W[j`WZXLMtsXjHC<pW>>+f0OJLS[6%jm>32s@<VjpGQl@$
+%UhF/+QmGmi/T,P7/dDhA(gTZk;/>6pZ)C(_RM#FQ>GT!s#Z:gX.c0@BTD/O1cHZ8=_>bpD&+e,](0_g4SB$2E,i&<nna/<EBT8)D
+%RXS_T^ti_3lR"!:r2J>]kYho&;3@%6[m)$ts*[Acs(C9^!hPl6aU*3d*GK9c"mFtWKuLO=Y5)W\I^GB+l28387jtko:VBo$.)MGK
+%TYB*d>9&Bt;Q;o_c,3R6W<ruK<$'h.%EXg!:[us"EfgaUI"i$LjZlf>i<5gI!O)m1_IhPfPc3HK`/1%%$'ksO-N/A'iY6WLl*k.k
+%"P%c\"1A=:!-+6?.;;WA'RY`>8[Wt];;mjtF9"TdB`D1N(20_lT%c#a'Ro7R-+:ngCt*t4.5,=N;q;Nb*4;^fr:g\RklcRG:JW;`
+%_,8GISp2M4(0&nWi]89"6/aY#Vj_A_%u[uT33qn%n?L]^.uY#9@C=[L%5;=hi8mJGiLmT]PQE&J1f-U5Md4Z&#em3dF=&`TLK>B#
+%1:Z"9$O(a.&WFldkMO!*<TqUgFp2ggle3(DE,@gnR2SjuP<OG)4!!Ni7!g?G`1Z<1J=tY>6BlCu4<.jX8KX!h=P5*S$+@g#k'Zq=
+%<\*:W/nmjZ(^Fp%-0)dX':=;?R;bPg@h1qmEhPd+;_qs`h<pLDJg!e%11G2Q85<.fokm0ZCW]m8`%gsK!aT_Cr_>,>H)37)jS]Y&
+%He?u:grcZCDRR6Vi_u5-rn/(E:@?$?hu7?BR&<To4gX4j=2hP.8'*tP6s2qnF6a1Q\>3*Cih,!R;"qOu4A!8ZZsZ>+L\i^_8W]!'
+%o0bFm&I\pbEE`YXmC^URWQ=&GB/b!^9rfmjX7&.t9ANs2)Yh5^1j#bbg&'DffLp:1]sL>F%FTqX+OR,EMjBVc'NF)n%$u_mc;ZFt
+%D.=M\p!(n8pQr*cJJZD%%\Hr*U<#$61s\+4ifOA=mD??ggj/OPl2H/!n;_3Tal,5QJ\s8Z;2JtQdgR'\r\@AE]Bq$gk"h\H8qZ:M
+%&W&g*KHHerd8r?QY/gBGJU&-fH&*4TIFZ@YI(O:C9A5&]JOOJD@4Q\h4b3tl(AYDKWuODhp[s,3rZ#65[m?!-R+4j]!%K//_.Dg:
+%0,Ic#(W[sDO&ELq#!JhI<-#L7[e1_g+4[R+Y5d1;NQA[l5j3eMqWErpnNS\^B#[VHU&-a*"/C+$%-e-UQ8NpiWlnHomG-$OMQ`.I
+%;\P_K4OLR^XNIc>lu+,]ooZlf2Apcb8DYq'5umBl)ns"Tl$<qsa^2eg]Yt&^#JnbkLeYOQW!FLsOmVbq*KKIl'MRR'Fn!<i$-j[+
+%Fgl`"bH"\AH\i=>"%rMXn^#aZ[;KVH<+rf0JcMAN*9D)KqAISk0<\jhOKEeZ_mD9.nn47mTn2",,;.E'`FNc>dK32UH7[l<Q^me)
+%#.$ooJHTj\Z<NP.7PU:.N5i[Ec0V<IN'%lherOa.]"S9,gjFqTQ%fNr>drk<IR^q1aZa\@@0.62d5_pupduR=^a2[e%'5Dk@G%+-
+%;3BXi0CLg&PFLj9Vogr-Vu619;D0YS,a:=QWaO^gaG;h\Yro09]Oa`:46hUfOU?0#in\[C[IZfo#C.&dGP3s#=Eq*o`F?ZLH',p=
+%@ntpAKq92+,M?5dMa5H<,7CYZg\+X`O&Ut+]\S`2Ye)ta*H_-&bJ<kWp66#6ba(6#HEBN<C-(.\F`UYN&fUIDqi4n$m5%Y0j-jt]
+%W#`b,fB>f]:6P^2mWl<ZgHaiCpjVQjW?+-a&d#u6/QhlC6A,S=1Z%!LTF58*/VqfQ1)uh(Ej/nA<`23nF&ZoE7F8`dOg)0V[Y5iQ
+%$;hOA&HMKFm)#Sj/o[tV51$%m1M/mQrE"fHF;A=e=#?LN!B(mp%=72,KH4k0-?fE9Wh9CL'.sfWaIj\s)fmZs6Tb5+h<b1Mnm^Uk
+%g:?5M,lqXMqZpX%#%DHb(qDFYO.`@q"cWfR,slj&:G;DHr7>+10F4.O04m*h8!gohAB<@nfM9/e$EBPmT[2QEl1<R,.U79l?V7.0
+%/GC40`!EJ^\r/]mfB!J.bE&i;SGPZ%XBYoHEM]"kMdbKoLO<V./LE&Rj"d(,!@@d^c??I*P+PEp<O3mNIXlSRiCItA7Fj7RJn?\Q
+%RXU6!U->]GUSf^TP+8L&aOI(h$YePaTOE+)aM!Tc=Y%7Y+H`RBQB)]h*2&(.+O<<=T^-kT_'p<$Gk6u(ZB-+7p4#.^Ec<qN/r9Qg
+%ps`Bld#JA_EOI6CD!3^-HY=R_ka6X;=odC',nhGJ[0.PG;e%hUGAA%a^R)6LFSbJ8ZM?TQ>B/VZGqK]X]/bd^R+P.*=8082_g,L=
+%#=VFM^h28M_*TamGi#<L7<gD$e5_bCcM?u_4e#aVJl)Fs!R\)@hS0/eh66!@gA6TA:gW3(:3]Dg=0RoFY9in-$C\9Ur=Bf9Z`l_Y
+%G9&0>7'pYRQH+2"p:U8`d*(egC.NY-a&<E7b][r@;`J,)\a/4h(%i9$N(:WFn+W\;MYQGSmT7^n@*n%pT)^VlDRZb6FE7!,g$?bD
+%O.GqX%Zgj]a)/tMNh5n5<!NLJe#Z!<^PCdU>m>A28K\VaZIu62JoG%7),0Gh!4u!t/QGH:nM'>C"pA!nk<BOo;=u]KYj6J!bGi[:
+%5)14r?p]^d`?nr>o5Y4.c'u?pP^u-noL5ue/-5`a9B2Ik)pgGWZY&W]\#X-CBV!/_O0N7/)@+e#Xc_Y,]YOmAlCW)$(/^c:-+f4I
+%&Yjq"8?p.JHJ8>DkN0XP[WXX61ng03rbT'EnK^*JM!nqMS2E5RI40qH\V5;dYgA<p#6SB&;jBc;O2'N=..%?qD#"hhk^J>g(5Xg9
+%1]8MUTI=:"c<_"cnYHd[Ms8PQW2a?hE#C!PIO4^i6G[eD:etl3O!>>6l(/iI4htbAhX(>FIn3OMqTu),)dsQM5UgP^KW6^.RV:<+
+%FgK0F9c$(4>-^>fXtZmqZa"GKDEn6EbPSQBqk_?p)@4mY(UIRD3*=1s5]a!]9nJ%mHS@i.MB?&7`>5q#nAiQ=fkS.u,[#;0R`[8P
+%`tb@1LUZTj.>]0:WSk6DembifWRDgPR`h$Y7bf^^P%JV7OOIPjkXin3:i\P`I^4DoZm(^W&J1`kc!El0_SmU#3?sM?0h0Vg<Ns/-
+%=[MQ=87h7"lV!K@h"H)X`>`_^b`4oIc\VKZfrle`m;\*s,XF4gATSMW'kqd[COkQ/0')slO<\qTQu))=Tp!G4\^Rg06&6N4WfA)R
+%g4(#)e9c8l2&AQ$raJ/K!B$N:p?>(U[tsK6F10U7d<o"uUcX?2YdiU"UHjkj:cuB$b40',UV]nV11SWOhhO/=!$%#,=JX@mq[B`[
+%:(O!,,?V(JR0-+5-E*`+:!eX*7`T5"gCus):a9PS<lfi2g<si^hR7,&%PE<5W,^ng)2uKSTJkSJ$%`W%Hkq(7\d]C]A^]7`XqC8X
+%0gJ;s7[Q1jnA<l7oMgMsa8336Wm>DoZFZ<EA\A.ml=.gKSbm_%=a6"#=\&gBn"M'b"X/b;Oodb\))Qb>ifp']7Fb'K]3<>UKeeXr
+%.jKB^TOD?;me/bn4uo[]_e`QM"0F(`GERuj6r<WU%b`61>#"I1N(mN<V4BiPN6c_Po.a#7Z+l<aart/&<hk6s.H#];C&P$A8hs^\
+%`is3+)`<sc;&L'PhE`B[W^\R;LOQnJ$eA>OO'lu%giH&[,tZSa:3Y5'6l8nh<PH0/+gKX^KDEa3aFUcX@3D2d;Y*[.\1PFHTV5Ju
+%gomb8F<4'Y#>cVLooOT`nA.J`0[JZsm]`=JWsUq3Q3;h[l]lfYWH->nYAsP[a*t.#_IS\n(%t7AoV$PqJP[Y#OBL4RTiH(MjBcI$
+%a+9/"8ced/J9U8gmRm]8_b"#S*U3.s!pL9'lF/?C'M8GG!,?2.+?,u2[G8LU$Q8,]g/AiEmns[<o4GhT&*Ij$gX8:?61Yt`J`uBb
+%r%23?:M#UPQej<2+L^Va3'b_D]P502.`4n\i-jtP*^!ETVl=dO-O_!e*@JY"DcZ_PB`QtAidMC@M(^j`nMgJMc!uMp<0?tYjH\86
+%TWj$Lb=hd<..#HgcJb+l;t+MR*W2_?d=/WB7T]f$SYEepp*lsKA7T`6G:h[]eLrZ.UbhW4j&"u"`.'4/>g#;!%N:(%:&99Sa?MM0
+%ghHL>F!B6njtm(9*@C![!^)gO4(H]`'%GA[`L)-^R_=M8,ET<5Q-/6si=]-=<eEekdfsT91Er`ZpNnoXTVbcoNW3-dlJ&RY1'gFQ
+%q>*A_bF%bu_qFDu))$.hO)Kpc'7`!M71T/=E/jg$:2N[A`EH!U0:2V>&U_7l-4RE]#i]!!.lO!&Js'Yip"obihdcTKfP1B$Fg\qb
+%MGur0WgnG>#$.oqrYeoEY#<k<N1V%uG9_!mYI]8rS,9'oZhFU=V\Y&".Nu^nXl.P&,HgJ!MaZm1)=n<M04;2Ylg)X4.Sm*OCuD!=
+%i=-^L!G]hW4_/(,Ob4c"E"5f<SJLgP#c+iO7HthJ/'74\g4)j@RA`o/#fJfgXPN&_$b'3#S+=*QGGBrIZN`!'MPWVqaO7ciK:"=B
+%cfsP'^=gl"8/q2]X0J[#)GmB"L4@#_s.us_U8)eHT'LCL%J&=^&*ja[<<e;dOI-M/e!>06bMHnJE=luOcaqc\F3\lZHkL"\/6_Y\
+%aoXuXBtf_M+"QS<h>#W%gV$c4IL+89!\8e6)Y6#3n?Qq.b_Fh]MrEc#D&<58=^*E2rT6Z)E,5Z;@9Xsr?2is<Go-?6T]FYAN5De-
+%Wdk-K`TemWU;F7O8-mjTC]R,<h"4[/ISP)']a[i;hXVFQ0RG-Z">^V^If\'-4KV#\n8A(8+M,n'ZAr$U\0m]m=P#^'9*!eh?C7>1
+%YYi<*F/X)[Fr_W*,+la%4Pu#5&7O`1e!mHUI1^$E\%,fpnB/IjVu^O_@KKWCSIpX'9ap_sl.:loQ<Uj9?lHfb#KUUTo4cI>Ef]rZ
+%E=]u(N>.6f%^_Rg;a::]Iu2eGFI;RP_;O!PG;f'UYM_,TM2J[(:ZKb%k<&QhfO-L*E\e9.HBHUWi9XOiK`MuM95N1uSNZf?Ok^;'
+%Hke>cOr>nB`4*?o;ZZ/g=Wp#J9c#ePmukXW3#S5ubjKS3q_m`K!Mfo)^1fL^qtjXO=pVS$G+3L:K'dG$!(?GC-FbQ-il-"8B5S:(
+%3+fEj95WYrSSie85.X7\,r=)(Ag&A"KUDe5A(:bgg:R%to0o+ejS-hG.6Dhu#/@h.X%B#*/7tDOI;JMt=%1kO4u602Iqp\iR5j]]
+%PCOpi)7[&NTghhHBW*^k*(&t1qS[n^rq7,@\l8WOCf?PoA?d^dQVrpa*iEF?0g)UCZU0>MGZ9c:9l(H/n:I""@HH;s?b*:fX:\W(
+%pmIUWmK%(tg/]tmcCN_A<?p<X,3QP@UA'd*%\>DJ--Hab$G3Gt_'/m"#N)V8)%c(Tp\U^A48'ZU^qF%+NC`c_lti(h,GdJMc(jN-
+%n*_SCBPE%67OD*K1oU*R;>5rl_4ul6(O=FRjjJ!Yq^@3`4\,!=U4j<.R+G"l7T"O6RaLI^#1tk:Ht:JQ5<q">pTB/7&KutNAgagk
+%5&N#0Df+]Ea[HRL(W(#A$01nQf/1-;#C"nW?3tENL.8s#@-mBDDsieUH#:4=I);%q$?hosI`RJtBrjFKl&-99rc$L9,m[@ijl=.U
+%($oP#@'d^+R)r7-FubG(:%Wt)`a$?0V&TgBg3$1VWPE7<=Rj3QTqlJ7M!E&<rtTbF_aTc(@4N&nn.hp:mad=m.XT2gVk6?s`B,o7
+%6k_uVo"<;-Y>AHT\"bKj[S-YdZ&^hc<X+>SpTo7LG*7M)\<5qt;:Daa(P=ZsN^<7NTg_9-F[KBULW7Z/^BHVeDQQrsS\)X'Y.d2#
+%n'ik5BUh*-@$6kG:+L>A-au0W@S&.ps%iF!=8)bC=_VN0I=IHG:?)9uV)7-GInZ2L1:0tJCf7(u;tj\)dH1U<UXjXPR9[)P-qsjO
+%`I/#uCaoggIb[E)\`G3ESRf"@5[Yl9-t<u<FV9k7_d^YQpqTjML_W41N-\*il[@Pi2XN#XC",nt?D%t:n/1ef.HkNSUY?pkI/s,h
+%%`:+!rDuCTNS_d"He>OGm<UMFOW(@mf4.=6mF24TeAlDd$uiD?o(gRJo*nOsIgge:<8BMS.@@O2B"?C`WccpXmsT<[<LH1+d@=H'
+%:f/7)dt`r/TF].M7BejaT:)7%AI'qFod&l@)\DgD"RMP)a-Rtb5kQg4ciVZm&U8u#Gm9+5^8)#qkndbAiF]UNpg&+bB``Mlru1N\
+%n@$74n_k*+##MP%,57;!$5)\6pU[usg)J%<AiC1qdb'l@!&h;2J%qp.]I,]ASD2K,cQAKYl_$1Crhs/DDEI?iIM's*=rL_QbWA\_
+%p:c,Ohs3%^Zhh@erSl)]'f`;\;C//O>nhY+k2l.*HOj@6Xgo#1Ra7WPm:E3Zp6&";ha:A*QqW<S)+_K-a-p7e^q!ggfB1QLj7RG?
+%O#cIj)e_IffWUt:J`ut!@j>9$`rUkC)0@c5g%OD7\Cl`s!L%B#61jQCN>+A?(pDjf5/h17l.B]Q>6mA;O=elY3.\kWNVRnU\FVfP
+%q37.ilctVjm\"PBb@J>I9cZ%u+t0BIZZ(D%'LfZ\^oo1(T]@&l&s!25pW0re38:?m3&M"L[8AE1Rt\D35s/aN>HZJclYK>2h)uUZ
+%T4#ee8s&DJPWQWB#YupCmL)IKA2N]N']Q]%mPdnaBV,)%f<tK;XpE"l8=AIEdE$e`pc4cOU<Bc,oX^T`MeVl,/lkYEZ`JTZcMUMc
+%qn<=W!ss/nK=*YGp.f'uH:d)EG=tKTrL>DHA[uQc.rgEVLuliB:IA3AX+<1OitgFA`&6_K6!p(*epMl6p/*"-a)>it+9Un48Di1S
+%Wo(Ms=Z*]f1+RP$=".-U9WOZq^l.%%\KU,%+@>)hA-E@53WFHqK,NF)kB3VOi*Uag#*#aahob6BZ!s3IfX0G<dg*I,RDiL'e8_O)
+%@GP/3=0l+"-J+FgqC]D&P'^fm*>\D&QN-pDC9VDBK6kXBo=DkFK1q[i][8eU>8b'_6snE?";=9L,J1ZHBeAJ"cDT]<^&3fbG;I=9
+%!/?RPdGq6)`QlmJ!*I4.R!'\3Wk!WW^)-4s#L%Dnqjj.JDsL*A!q_poD.'ttIiE@3"*Q#+_V]aaEuG.QG?o&7a"L&m:LJ%+(QRIZ
+%bBCXmAd#["j3udB(REpHobVkS15:X.ci8Gg9sR$LSW#)^EEGLZm!fK`&H^m3#:P1GOs\P4_sdfYLDN5_n*cU#%\VArOO5/oc4XF,
+%Nrm=R+ZeE2?ggbRTuL"6j'M`7W+NYk)g+;MBJ@%8qii[6S?;>*ObKR'H4%n:\L=SlCE2cLK%Bg?;:;2qolY?:l!j"DI-khmHY)OQ
+%9#Rukpd)(;j.;Fsi6NVk'F/KREsmMDm**RB7"ZI\SH.qkiW)X#iCY:maDTgl80R+$hj^s#?<0g.04BCE;\jheWqXuXKO1p+3S0`[
+%/;''rr\h!N/KLg,]C#=ogqT;ZHe`9@kCE!/:j$DFH.a#7G)i<;p/@oLCKN*0CB=Q4=;PY;3P8^3Q6T1X3VPm8JV6KU8d>=?&aSiD
+%%K#MpF\6]4NY=HrIXf$T\:(R-.;-^nN4K;``2q6>gY%Jq:-G6$1dMKrbg*&F7,J'$l5irRfFa?Rc(t*oLEJ,%+meh4LQStlP_9K=
+%:>Yjo1jDo!1/^NnAB/W97;>G8O?k6`>)@Y3rk_DgLRh\`Q@S@@US:4@DnE7$W@*Vok>FC6Pl8E9*"?j+UJ>f)%LBKn=c(>/?)Wl8
+%38H1j;(S>jRLc&Job_h`H3WNgJNg#/>(oIC3i(@Wr&h/W7ChKqU2ELZIsbu2FiqQO-d+=Bimq,7M=5;OmbkZ^kMGkrWOit_a2U6m
+%'8ZdQe8u(@OUTrH>kI:q!i'!]K:rdkQsce02M)/#/G].((WE&0C2JYAP[CAA*oJMMpbdqc:\"l^lG9"cN1?X+QR=K#Za8^ffOcEZ
+%haVVCJbh27Ca01H>M&O9!.Rn.gpIKG\R1#ui2^Inb+rqs_O2E=_A1j1HF]TlGn:t)fP&0Y@^-4ZbOk:((YJ1.n$P5I&^re[[\jA<
+%dh3Se\;jt6cRE:RnDfDHlWBDKF^:'_7tsj/qKe>k"W[s%QLLg:7kqf`&<B+3"apRfHUi>V=J]j87]7=PK%Xtpl`4r1FuTs^fW?`7
+%m_\D6a0(r0SMdrAP?o<ORdtK)]Sp74#;`df5]JCQ0?:Ntp^G@dkUGFl\X`I(%#e21*$CYBn0VA=Y2Dfu)&5YdN^"W?gh"!1U(IBQ
+%'E-%]mi]FRY=f%49"2D&[5(^-L0i)VQ<aou4knbUL_i'[i'V37HscjCDQRnW;Des))M-(jWP/]o#^Z*;K_G;JZhh"td_Llk:@ZPP
+%Z(&P,o+N/)GlKUY_4TMte\"rj?7^D+UuiR0.(-kGFc7u3,7K^*Fg:.7B[!2FI=YQNX\moij/'b.:_F[o*NP-Hh<mMcQ)hQL4p0oa
+%#Zkq1DrXGbWAWA%c[/9DK%pqJlIIABl=3oPQ^Ou#lfq8JI-=.'Wfl)uO/_HaZLJ?Kqe[MOf5Y0(JJqao@'Y\r4ONPZ*HTgSk@$AA
+%_0p[<:Bn4G.VSb='OT5QfUg-XAAk,ajQFKCgfH$'E<e1.@\#_p+ll5?[":IBYOg*-eNJc(`nK6IJZc.\d'I0[A0p9H.+Ifo4-#SX
+%.<HGt<2$C^0UO-P:7AAf/:L)Lh\MDiIMAXUT'5?289-(t"q9T`5skXNr]Su*bj:[KTW7fX9n%32PY\\Ib<a@]ro^-6:,;4DVlXM*
+%g4SAD!e1@us/"qWLnBUHB7,<a>_oTN&'asN&"no0)7"7_ga3g3T?]EcgYh$8o^BpIXkn4R4\\h&$I7F/bCSXND7>0^%r[89(Z?3?
+%lhV'WMJ-f<*c&+G)guQd"-',@4+mT.:IF#)f<-$?;>d#Dpc5gss0)1_?gr%6#C9>K[srk0s4dSEofrKJIsh2j=BEQCIXb9?o!5Iu
+%TDnSg>>YJ-^uTj<@/>ZXE7.1!Va>NAk"CI$?1:dBn`X"AeX6q1Y&SF2l\F,D[k82OQMGb/it"d.]G<Z?Zl;6?`GNL\`_cAEfV3DB
+%mX9RAd7HtSJg_e_\E;j2/,phRSleZH`"5k4J)KY@K#\Zh2\*Z]=:8eblGl`jrl?8BeV[j2q/4T.f6%SeJrAQO)]\8K;[O#=KYlXX
+%8oB!bBM8u1#!ad\h1P=40Qs->C]oY9MWQ-.T7:NjpieCj_/`=gC9<KR;)6q$STj$DRd!ln@]E3dra=FGB(.:%QGRP'@o8=-WdBMU
+%ii\o_cKu<thGbWmi&Pp85!SX9;u^i(K9;Fb2H;)kd7bL9nuqq"D#WA"h'!luK;Z:/g@@<YO:$R/#;]hY`)&-Gm)!`13@*%Mc[6eh
+%io7GSNG5Xj0,X8IYgDLnn[7rsac4oe-dWT:F3&].(Jt=?M#$:>BOlinN0;^4Hq:p+i@%X_ouWuH2$$K;rii2`h3ajDD"l8ll#q3?
+%0`;Y=`,I1IIi-W2)Xp44%,(\5Jt$-I+dpA<FCdW,g#RPYe/p"d%_O$rn?DY(I<ah:dma08^r_8mM_6=46G=0r(P]/=mB\U)BB\qh
+%nk$eB$K$^QjN^pHFQ6a3@HeIl<@p@%HY2B?@L[_[cgq%F@b,%gAI%Z3P&H?l!uAR&l4+/lA'hu1@VQ#Q6WcmUi2u?"iku,OB%V@e
+%9"._?%9qtip.2kN0[A^`L@O2Z\+Ff.k`\Nf*9+8_6Ns2YIg/CmeJ@&^G8JU',DVr(#la=ls.p>>_PtWq*@'(QQt-iu#^,nQb=;XZ
+%@8JpaBQVb(WT'FG?UK2e*]aUcS&]u>YLOaVU]WL!%oPk\mg-NFs5E%dkBI9[5G71&pZonI&lcO'@m7U?C_GkuZYtqH<<U]fEhCB3
+%Y<V5%C@T\7jkRDOO5SXanNI>dp@*JuhP2`BR[P=*'BXE:+kk\jjrY]H`*e4<DLA@Rlm[Xk.7uQk%KWE-pqt9aT^8GKf9BNdF?ieG
+%M1tEYSfSfm-]Gp&gUf^.r<cl7Wq\;FhBLU_8+dFqEE\?+[Op`2a=5,ODdSU)JLTX"..bY+2KqnYqFQNf<!4$hW>P@%+o99+=$BHc
+%nJW*u_#9pX&1WSO^0iar)CTGj&2af#88L0<g%rUdVH'jr']T7FeE7mdp0)#'Q"4gmWZi;+:S7R5>5IoI(B^bfAd3I^;9XY_+0",B
+%1.aB$^5b??K"HBnfN1H&,N9#V((gT-6i^_4BN/C81>UP#n/S(Oi[XB$LDPgB_fXjq-u$UB7cL,N(pWT9p\P3P%5j#&]1J2D*dr\C
+%j)V`C10C<>n/C0XXN0YO=iK8p5g`h"_Fa)nfC6jei6-4Sro+W4K&sLS5C?<L,dkg&3Au/)nU6!pb=a+9%-tsV2)B@V-<-4`/dA#=
+%CZ`26e.c5Dgk^u-H$6f8)*?qA^D?-@BtjT]>JNjp.mi%TkL!a]CjmB)W)qA]c&<h\!]/suq#Q/[`:D!HHpqnLoW#mq1^CQGO4dWI
+%V];Ff2229&q`j]\Ch9Hq.-M]o.6:lSnD&MD7o-?,$XnR`]#j+^-K?\qi`+rR5s$IO`q[G^lJ8SgLb=b+oBn0oF)212De6UImAOOS
+%/PELf-\@hsZs'M^6PQrPi=@egRVD)Di"achC5ZK,R,&of&B5fnPquBA5u)@a]h,@LJuI@NC5Ajp>7;[`4QN@ek1?Mu64@;fJXd;'
+%3I@@:;#=c#Ti3oR56r.!$0gZo6)pMc#g0XO/D.EEIm=O5L=fcN</FH1a'/)CE.bmG+dST,@kSb2cHdL-O@p?nkQ76rr"fb)g53]"
+%Z-q!#&u#go1A2.Qa>3MU7oaHD+&[#_S<L;-\hME]jL$f"0pcPC!:Yh0fDluMHL]BY#&,oN,KIm;[j$m`&<@QeK(&b.2*,-roLZ7e
+%Eb$nN:SK`]2NI&j;KuYlq+:H."PFKH@%XVG,]e=V5>o_?8*q%O!-mco`8l%JF6Jd<,C[DBe$a];'_UNX+P-9qgG/n4#EhD7DH6>q
+%nOlB-"@)YNb>#GX'Fp(G+rB>0UI7ZhYEq;N+RMAoR7<5IjeoaJo9A!X6/b_PFKi0M_F+"C=tV)6LPK:2"b`R^`dpA$co,(5A/SaK
+%;[>h13&<_r8?G@QmVCB&mJWH;6H@Vg:W#FoW&fR(k)kE=o?SC#5A_B"Zlb0T%C3,(E3\(M7]?.A7Jt[#Onkq#3LKfM0g:4sgF0lq
+%aC[VV#^3-KCZ4(J2.Z&ZW\tp04]S%=%+\j;l"`Tbb%HI;.5GNuFhN;\ls"TaJ[Z**.YW4q#/.lEW(h2'HW4LlH#j=qLMn'f2j-;_
+%5d?T7G,V#n!\+]TK??*M8PMS$%8W^pdnWH_72=NDUlJUU+LbB+KH,'\!Oo_M`mKCfUH)4aaUt>'Bf',8NrA]8\cPil/i"&di_2bW
+%%,j<\2.(E2@)r\(I@bn>^a^E8%=of00sMmXQc_VD#",5J`Ub'Yo?(R>j74!FXq?k6Cm^$*+"$NVY!g.Ch?Q9r;$g4Q[(3;)%&L\L
+%)B4*cWkFcq8Q4<ngr+6ODt#ms@pmY<:<@W$mL_n]T]U`I5!i5Wcgu![DL`.UrZDm.5homTq4u&"PM%!Dc[*>.IJMMjPE-!4YT,]+
+%Kl_AZF-RF96Vbfp%P_u0B`jl[<"^"@0#Q/(PuNc'pHFB"b!Xqh/oZA>Z8RXG\4!>mIo70`\FJqXiqnbU[Ut%DrZH&XOPooQ\&$<@
+%FRVS#qNWGFM$mM\gbp?IQ?"Z!Jqrpo*fWI3>&1LHIW%e.hiC:X5D]>X58#\UU>-[5s1T=W8bV9g`%Cbq)t?DnBJNZKob;0rppkP1
+%;HMoU0<(1c1j@J+XBkMG9Y2W5IS1U=,=d8uS<V#gp$>qAH*C0ANJDl\Y[m!G;N.n$X0(#h^^K;PoSPlGNd`a^FlmYSTjAH;^cd;%
+%cVSH9K!;A$%Y9&BcXHQBQ<96QlcD)h"E9aVrTl+l2+@2R\3:ZB,:M`j?#<-J+XBj656uVR=p8.C6(>(('Lf'@S07e2r.BLOoB>BB
+%n,VnW8TYRB8g7i0$=NicGG6YWjLE.>];LqEf'ur1]ABK]j-'ajD<g42>K^g?F+.sPXVO2/Bg>j=h3/+T^p^=ib2$TO.'>T(p!\6M
+%2Ap#M*);NeB$1H4g7k5YWOsYO!,O4`m5g[>*e6q'#qW)u0W<MMJsnOmp\-.LnZ!a%G:"]7,4ohs-Q_I;+[ON0]oI'Sn=8J04G'@@
+%"k2]MRl=I[DNMEuR6qOrM]\1+%aJN?fnE*aU_N&#%H5rGh6W1XGl48]9M%_YbP&GMVV.O(g.`tI2qZAMa8HlCO7,Wn+B$PN+Gtbp
+%#YYkY>m>KZOZV,T4mPd+;gF8>S40Q`bQl8HJ:+^NY"57@/9L1*=WFd4UY@QpUH?Cd;,$0_s314Dg$uXV5)V/$fmoR15P"3IVps>Z
+%PG[s6j2inDf6nC'HXFbdO5&W2a@2EZn,'oNcb.JtLc9-\UG4T:IV98O?IqVaOPGJiAW]j'\3\_Peg%#%6&[MGmA\op.1.oNG#,D3
+%N*VW!+Q`hk!d[!j&n\CmS$oBpBRpuTh6]S3U-Fr3&*W_Y$l4VAnKSHmn*XXd[>:k%T!6g.mY%_@DP\FtL9$;u,BSh__)uc"ap!aD
+%`Y3sY68\CO)#(-^H]3hpZR6U"YWf[2AW>5V0GHfo`Z"18$o[7:BTp.$:@&RiV%Jfjr4ILjHRYAafY946K*TIIq2VU7SEa]^A!mtU
+%XAKu;G91U!EEm)2\ZN.MYaQa)'b8D\]PhT=0:dkai^W:BWh-;_=!M<@XKlYT.occH(I^,Dn<ur]&8^o<X5uiKlrk8m)jh@ls1_oN
+%G>\!#PJgPK9t:'VJ*")J/RWW/qg%Yq2Qcu3gZs_"O!i]Js,hBZC2U1&^8WD?W73uTn&R(1gZ3'E#<$j$*tGBVAC.#3mrS^beLqKq
+%/qpW**A-*$Qk,:kD]1QH?6.\eET8*fI=C=K+>,bB*2ZMY:q7Dm?S+4Fi=@>bIro\oKa2Tb,7JquFf#pO1($I;Mcj6&XcpWm6We#e
+%g)>rG&SjnBn@6SaKL6[rLm@4GM3K8KGFQ8?WY]UZrA=iR98ZZ]'-VH"-A+("Jtu2Of%9kfU#.(*e!<$R?S>Kk*ZE)Y3UT-GU":OU
+%Zuq\2.u4'q/EL=1P)NK%*L8JH(;8%:2N?.b3\bq=+3?(M#WFk:I5e7Z!kDI5W?E2r56VDndgsf2*eClUh)'KF5jXZb*d!T`M#g<m
+%pk)3JZ%K)p9.coAgLM@L?U?Nk6gRkZk+&D&@eYjJSe6Tr=NhAb3tIJIOjS:JD_.I#9F?r>O)%>\eQo$U]?p+2_]<I_\C5;2#H_jN
+%e*A"@DjOY3F"X*Ph(^-km]j<ZrfsreOsEE+Q9Xt7k!5q([N."ED5L@u+R6O/[CO,4HTWt?,Q:N:Aq?9!(10Xe@W%94@eC0cDsoo_
+%_k!jN$pgNC2Dh?Ff`#O/(*6pa/%iR*ngG)(kf/l_Hu`/(1A;rrdV)[oh#,[<f:Q+BI)\\is.<<R4@C];'%BsMat6-^DDmGCd*8GI
+%!jNf`k">5C-X/Jo:*qS%ReSj5[.=jrFm#YN-f9t;is*7+rcnW+b4'\Z,]u^Z)+I)p3U"dVg:$`$VS&\DD>A!C^>mC"ff\bhn(L9W
+%gpo-<nCWT:L%)3.]q0nKIqI>rs*j[3,.#NR2&=g2BP;2H5Y0ei1\a"Pcb.jPk3FUbH=V=^rtG9G&(*J\a7VJ>`g2;o9_EO?;C2DT
+%Uq^gM1l^u0CS!q5=05-poOA1#-/b8@hKQgTYJlt[%Uli@2N(/<?Yd'07.JE4EEb%'S!+ko%R/Q7T['$G2Hkrro.87:1Cd7adL!i\
+%O/&JaD=YNKU"!3%(b:`RCY=U)ak*HW5D8MM5528NkNGr)rL+N:XL;8j]d@'R+\=5+0-\rb*"[2P/88t?`,X!O&H,]Z'#C,sB66a$
+%lQ.k6?YFg\r?1$$ZaCE>+'6-1?M?2i7/sJ/>MVkNE8GCE2r(,?<3tdOe_"BBd<8c`@g(J7)ZOq?On&HKW$%B8Xnabol1hG1Rbj`L
+%F:^Pk;<m3)o.@kTo[oj@3:r!_`!D80B^!:1IS''!Gnpe@o#dSpOeN[DmH>)al#MIZ\AY%E$]5rU4iBBc?\b+2VX+[-Ch]b*Ra%^9
+%F*!;U?ASC?b4IjnqKDd^MHpN]/UNUW=,nMim&=kT7)4aTEuNbir+Z@K_@j!8&XRo-;\&-naE.7$la2D0P7Y3O'MXP;B8MBhZ'%lH
+%LsLH>%t,GX%qO),9@4iX@&P)$\@HgT.c-QW3:1?44(Xj)3%1Q%'V)5h(q+SoF2"29681n]im9,]aeOE!F-ScmO-@Ir*JksXN3Alj
+%]#cT%hg+kLDT=@R--(5:/\l+h]3q&(N9>Mhmr='Hq:OBq2<mgidR)]`>#!WZGb96sp*_AhCH\,e'2+9@?f?,?*E9An&>KTt!"s7S
+%0IXa:7W_(0ebNaNf$%\ehHq&:@Q(@O'(M^$N,;,GqEW'%B^]rMTET?,TprnAg3:)T&t*$);RmK0\3IZh.`fB&.k=d+J*4c&'<Mml
+%#D^98]f/#K:)iFdqp0=b/0s2nIi/%=B>R6('l+"^+,;Y,7(kh:jdpX?h*.\H,'h_pd$0N<S!;1Ib+$QTpH*@^`V,<8erW+Lm@@^G
+%G\feYRt;G":h!GrmBEUZrDNUIlXoDa7-@QEL%2(okT0"g'*?Y'&:[M,=A-W6R;MtCT@adVK;7Er0"X93,2F:G6i1ca,>DJuefAJ+
+%46LC88[8)X:XZf`\:\Y1?K8ZS!)14QLd<4Rr8H_rn#![a[*l^VCYTNW,X+$KNSq(%A$5cEd'o7"H\e+=k$k(o+3;qJ^JY%O_,F^W
+%O8J^NT^r%pfl]ZCX]i77CO+C=aS%ggIBe%VI^'SS'S6.'q"Up`!C#28Hq4J@+YN,Il]8Op#Z<J`4btc^/Y(PV0@WOkJ^*@/$9AWZ
+%-165`;WiO:j[];(+k)d+Lu4OU#);JE=/A[3_#E-dZ'UFf`"Ft<5u#M^E>!Dnkk--Li$+K1<r%*cJC?)]Cm[AqM@8^f7nsnDG#_]s
+%q[!;/V.p8O6Nme*7W:TT28lhu8lR]jL3'KaIk2ueMk8/0X'AgjFcuVs$_ci2nJ#'B7,a*HG9*7Af`*UOn,B@jEa=GL5lq/jqNh<c
+%@_iOl!Y?6l\hj#.a@P6Weg"-H-%V"&1E[N\Gc*ujfQWctp'a)<!lofn,7am:U*,O1a%kPW1hZ9jeuh'kpGGCWi4qRq1<GraF6flJ
+%:7\E`=F70pg6.UK-DXe0V'e#EgM9E7Gupb#P^(3bD4,S:5a%%ZVbP,j3=CG`S[V4?/?[5VOlor'`WD*jC2\:>o:R((YBg%52f?EX
+%/[MZ:RAt?Ffo)Z%"!UCepd_HK.IH@A=e1dO')7&H0:r%Pc(:I=KEPW;Mu\?R[;PYH>N'65SnF5sWM$O,R^CT[lmHUF42S<A<e;[O
+%4CiG^MLk\g&Y3D;TZ<5M,L,=qL$3-ED1l`_kfgst8E4,s.5V,._DWr%@>(:VVSi;0AE+;+'B!;7Aop^u4*fdnCG9uhQI^0HX\>Dd
+%jjfOf>=sid`eta3];Ta4l4tgmS^ugto?;)!H0pJmGSO$p/U=WkD!Sqb0.n!a1C^rblVN!1=M3=+Cod8($u'+,Z7uA36Q-5d.3XGk
+%Mh1NE(3HrRnARrYAi#5JVH$BK9EILc*PUI_7T>pF?!4L<fd6_&Mfd<D*=O/AO=G6u6;:9f8UK?-dJ/>tE.5P`I^3;Dpc1M56l9IJ
+%OG`_!/PTr=`O%:o&W`[6L6f9pg1G=T>1O6cW%+a*>GO([6[.-S8I]CX/'t<^1Lb/Cr5A]A5h&K1aB([tLQtd'2Su_Y(9B%;E/DhK
+%:H3Xt[MDaPad9TrLZTM\FWcSeX*YbcVDK3);Ap&n'8os[g71SYMo(EgcB?\_mojIG3C5HtE[<JJ^j7Hs"&r7J-l;tV$%T0t+,Q[I
+%]s@"TJ_8ORQI0S;XHSCr$OL$GUh$&H,s$9?3eH#rJeA0tFU]`-eD1fL6FNs&OP4S`*?E1b)ER'r$)rM8(>Hp+d5^Ee;*qIR6lF3f
+%$p\7'd;Yq.D\@&%%;$lhWtr]:eGIm[A38_dkhB^8`/;J/WZVg8L-bT"<fE<VPX%k&C&GQ0?krfrLhhRBd=PCDC6KB_,>fSI`jm8Y
+%AT!dYc>+Y?&Vk3M*7hR(<KNChl.RNWX3kVFhhg@K0A"a!?^8D`q*D5g$.Mo%i>=Wco(L;q;G>[gkVDk(GdL=R3Q;!_B92n2/P0E"
+%qBjdj*54JJ$@8+cS5#YtT&]ac@pt7EEta:ck3*b5<W&a*h4u^/!SC#mI2->"`?no%VmOp?Ol6'f4/1$G6jJWj`SG9FACdh4GoiXR
+%AJIcD'eDVPC?=;T>945E?H@/E]l1RNWYeUB^F.mena8F<$kn^>=sIL$'08p26J!qQS;LL\0jE_hD:N#_#JgqJTp>/elt]0_NkAAP
+%9k+6gQQ;aD%cfVZMX)#IHn?/j8L@gP)F\oANo#S!cp5L^A]Pd4'\&:SDUN/Lo]4,0N3"9pq9`W&n=rt?'ZBS_Jt@BF1qGP6qj<^`
+%nVoPI2`+W"WCEXFJgZ%K'h;+X]j<&UZGXVXd1JV<:fdLp>:\BE$Y;pUoieeE3(`WLi+/+rkIqnS<l"])obPeE)@gYT.Ug<QcNAME
+%,OS1_Bh&)@&Z`p?%k2NLA'\p[;[O?\j6<45TTE9=#AB2kE1dJl\V<[F/="^*<9m)M2Z@*[J;-Oc[B].bE0El<Z$$lP!bu0hQkT\=
+%Cb!\5PdihJGt4a6+[=%'1ajF"S3_\,ng&Cs$mQM>1=[uJ]f,%I1ZXMm1?j:lQH]>ZLmr#G`b$JE:YsJlKL:GMY6`o&&43B"O_pVO
+%`A;/>)%-uD;'Kua%;eki+JgJBi9JI)nM74deXNOm3S_J@V/MR32THbJ"s<^Q%^Y=&-oc'ia-ubqV+kDP[E\re_Y@TN[_cfWUH;a&
+%6^@b3R-Vf$J"nKcLE/s#`1HlGi\!?akX;*&.!_3@Y[*k/4(sL"0XRJS7!H6Rf@\(?d3X&eJV'2m@4jV%MqMrG(M</%)EYq2XQ0!C
+%Gt@]7.mP"Y[kf0bE(dHd6NFuB^7'AFahMM#mW!Qa[KWmgTY$CeYYccXES8_Y;:;Mb8bBIbTYU2uAG!1.=+G6F3A[H22=7K-K>,:0
+%c/C@$fE#>NSqI3k8-e!OOD=?qlJ.+R/2LTQ>^MR4h8r8IDSD21AIU]?'#d"/U*jkL]L!?m>hT4XJa?J@YmME"=LId=R0AA66Cf@r
+%+7aK*HF+e4<`>\*mC+C_`E_V+E,*MJRfY>Ifr5N.E1&Ja"MGW]$_pk/fhMHR15eoqXlBRk5)ASL8[&J*,h^&L:YoM>.IDZNOu0&U
+%7Y^CGQkd#KK0r5[.WXl0R/K#<Lh?=^Y%=XDgLT,VgmK2T,M"=tHHhVE*(Fr\<fenZ=]ljf-8UF4p!DBC+,h<de4)3<JCMpaNF$fT
+%+-#P/\9*SO,*8UV2G\CK?J/o\66&Q`eB%Z$VZ@aMJ.3FkYE`J;1uTQ"lq\f`eEE$^9A`U`9m=TpPLm)F4'/j612ja*BA,VYI/n\I
+%2:doT<_'WR+R)GhU3^N)Cb1NiCP6D*@p]BZg4@i/q.g.]+jmi7jKb-dhgF1V?m/)&BnDVG!'2kg3Dfo..(/T`S5Ng6Cc>_VZ>unl
+%0#Jd-L>[g62!qcF\PFe8YKbOB[@l07?aN"cJLc)LVn5d3:-'/CN#;c@o+[aIk2Q8C+0VED>8Zuqn`adWn#Rr-@l]LPTT"UB()"(,
+%3$oU=io0$BIpPn-=UcN,Yf0-*[k-Vk%XU4dIoh^0Ycq+H,@#"abJOl\pT:UrWqDL73m`H@]N7CO$l"\`NN.92h+1s:#':^iNAk'I
+%Ji"6odRN8%SahYJ(Ie["2[YK3V.chOS>.'B*&fZ?,Mk#-:t*+`_b*dZ0PN6'm9oTqBl(+P9AG:&^0=hu,G:CC*#Lu]Q_TOZ:P5@D
+%++4DU^0qaple.BQ3&iPMs4XtTNl(:aiX$JU.=<`KW+:(F$po&)Vm[Wo4l"8@9OAHLn;R.W%Em]"=?n$V;iI0jOSnCsd0RuGSO<g=
+%=4Y(+s4EP)KiE(UF;!B0k[NS#0IA3:-$?t`;HT[^OC_RM!TU1(c&JoKqg\jsDFTV]s.oW"T5[J_5m`OQZ$E)a$+4'?'@h\u`/:F_
+%!+6F\5Hsla,8?7Sc3Xs]Z-F!1=_Y%moY<dj0oCsp9rh^(/7E(XWB0BVd8=Rk09H:1p&O+f0_%We/D8!nC*_=V6>bX_?AEX`C__G^
+%BIn!oOX\Qn3,Y6,H.,nY6`iRd=c3l.ojNYgQ*#UR`mRtR&kc0,gX?jg)O#[j@9%SD>^R`t$[gNbGIlP)b524L6VZ*Z+&uL'PoZ'n
+%/lZ(J@j+ohnlSOjjF\r0e2T]:>:aK>=5H7nS,C.*p0'P.js\6n?reUR&,IKiPK#VVSYskf2$DoMWh)`JW+\i,(Lf:fKsp'm[Vc/h
+%,j/qd^/s*jeg`)jltL?L`=*RR,a7k$l-t50!Qh"/,W^&t2`"%@.<uP\_at+V\0Gmf;2C\pPAg:Vha0=Amb[ilkATeFH2h)'gc`At
+%qWY%656(9CB0pH]p[mb"S^R-L5PXG\*ri(g`]sI`c'oNQ5Q@K3hRrdQo,#19lLf@NqYHDZ?G,-tT--5oL5c(`hu3K%msas%_cJM]
+%miT4;d:])HjdlGBZQK/@kF[.pc"H#'rSp*arVY=bc\)?WJF)nUa$4uB)-)CioY5]qU-T64IrP>'T,p]k^FONc^AHd]_qh4Gb'1oJ
+%&#TQ#8P^J@7Hdk=N.Ipll>n1L=17;M@O.7b5Tr"]D.,@/]UmNeikU91;>loq\6&Ag=/HGf6Cu<l>?'[p,(h8Dodd%N,dRulQ&*/M
+%^4HMsk*#IE[lXV=qj>f/SI>fWn0ZOAb=l=!0?MXY-m24C,mD'm7C(1IG:HD[hS'+e1EXng%U5^h3>a&tT`+k+`QQ7")N5'HU**ih
+%hHnk-bC0BVLVJpVQYYe4m]r#-,Zt'9aZGM)VSSD*aUF@k;q[>m12r&pUj&$o.S+okd$r[b.?TlVc@P^/+U5%&8Y]u]2].`XYR[IG
+%eJEJ_3kBMp%6!^O'(lnGJM=AqS>*68Lf<m&*OR`pK$4BC&nsBPgU`Y@ZX^9\Ho>&&QhQ&B<*^0l:c^:"VP$d(cHQi+BS<a+feSa%
+%K^1%J-'10#gC@5dWo8EF!bHVh;N"6J5bL6?",cZt!M3,ik"1^,W%8NAY0Jt<4W)5nmW%[E/:$L@!:.L7[j&me.%d-?VKQaiIQq9c
+%=r@_*-p'hCUAFa_F8LlH9GpURXWtc3??h>a)=>()2;;EbeTr!d#Lk>@nLKDAd^%20Lm(pA4t-M%4o272=-oug<LB!n)E%&D)(D#I
+%JPnd8igN8XjpC.Z\*')]#<`2&frF1/X%?g.lU;^RY82:K%_+O9GFCc8(/<$V!,eI^iKOWEi@\*2E<XSR031F&0R<`7;l#7u25=\]
+%Qod%7#<N/-[ibR,KOD4Cj2;bk*W$P1+pAaJ<AMb(Mi4Z=9b'g5<)?F$2'&(7!4CI=4n0+R`4rSN_mc4dqYJ1WIWis$Z_'Bd=:p>E
+%TW:EGki40,kiB!?kad]_2,ch)q$sh_c$qq9,Y+]KKVTt2TS_XKp<j>,,Cp+H9SfPGYK`l`dqb(laH!]9-'tW&2Q@9!;^X8VdYuXW
+%KC)hYRqfGe)e>LC;,Gu1PW=i*6Yf[6+JcT',bu!6N)m"@RUqYrZ"C1G>\sma9ics]A#;5`Z9K]84TH5.c_P[5fR*b>'j;p@gDTNS
+%OF`Y96Fq;h#?NSKnb0SCq<Vb@b=1[o7%&dddO%I[[2#:Z*areVe%-B/W&?86F>;.if":2/og4Z]`;rAFKbBc9g!("RXAZK/:-jDr
+%`5_mrA$1')"mq7Gqt$Yb/[G/o-7@32O;';tRdk4U$#fr82Q5S'K]AmM^JBrR.Z*,t6%Xk\_Q+,[;T?]J=Y(8tR"@n=*1ZY-)@,X3
+%a??&_S'O>Lq2@7)Nc:fERd9]>bX?Kb2Lt,ckc*3Bl8IjPBlds?JTOEb/&tb%]UXPiCsZo92u$7BD9_:S;M4"2PFK-alK-=8\>sYW
+%-Nl_nlY?d?$aHkoDmtnV>E&c]Z)'_*$6(gk3nN8uMFW:cI`#_,Z8+>YU?+],:%#t!^)E<[@S)J/4o(lZ>FS=UbOI1qOH1>gJ;LZ-
+%".g883@=#a+)l?,"LQnRi605eB6=CEhq!T2M_Fi#`S57<SF;S^)#/.Keqa?%b:]JF=LT$0k"%M6,mUHN^f$S(M/Eq"Zu<nLAYK#J
+%4B>nn+O=t!hRrrNX/RPK,I%>s0rO;,p@=q<X<!uRj1])'P5?f=dHF*_DHCm<F4s!/H/77=%^[.&fMc8h:p!VI+589cJh/e:e[dCq
+%fr;.Ja^\&0M!]83UU'dlrX0WL2/t`8WZ3D;aBbO'5gf:?@d9tE7:':Z(N/QV=4b\T(JX7,^=6b4^kqoBgNTP>H\C%jokorqm&C4=
+%Z)a=<[PX_c9lP!!?]'9klJa-ff,:sHI!#J%l][;1>VtId<(aeoY>FppMA/>Z6hl35X&JbRm.E!\eA2m!4PI@@C<!*taal<'?tog2
+%Y/KU2<AN.&C#pNUZl3(mncZ0Vjk7R.+HUH"<9m*;Io%"Yf?[99MW.kOi"?hp'au35-\-UAB"XY&dh6qZfTs%S0]/+30^Xja=G3"!
+%IdR-AIFP<!n9FiTd!.iNKJ>WJkOCqd0\sf]ZXJ*U6^:Pl1P5'f,i9Y43CqnYXJWlL/0F@U>5<q3O-\UP0s%qr,#F2aBK#67C$neN
+%ln"c.NcYO1#b&O6d,H6u_7Y\C`Zd4_gE6TQI"3>M=62>hBdPs?^J@:E?9.tpA<[Yknd&4C;uWKq9p<"4C@O[MKD-5uf<2rTI"k[i
+%f9Bl,qa4La.87Qr%rf,8:1q,62B#oIRb%Q):VT:gD3<7Fk[#6)W#@PF@MS*Wd?\Ed<[d>M+<)LE&!_+%l)SU;cu`fWF7DsE_DKi&
+%@]DWj[;KrGWtkMVHQdH/C'Nn.1H*/dhDLX+8augU+,p(IG<PFh"3BG0;B9J"P5)`)=`C-6NBs";pCYQ`Dn3755/94%V#I@IAqT4@
+%&e::Xi[PYYf02Lr@9O>#/ePmqi^1Mg,f;*1=WD[MTfYCM$DQ_U>`2(*l(Vi.e_HeZ0rX@YUj+'&Uo99:"+Z\6mH`_\%tS]q-g6c:
+%59c39*!7@6D`!Ye[(A7`gHm7qC.*VOoF?1r&.U4EdR[m&Y3k[Ll)Hg/@B$QL<"0rg2:K6npe1]_G6@@gq-l1QW:-cemTn8r>3--Q
+%h4)#sBW3gTKhJ;E6+.R+Jk@u^l*?RV"uR@pj`U/gW=$tTX;QR$)?XOjO>YQc)hf#+V4;bWYlhJ38_XfCd`1DSgr4L/Gl)QFn*IKe
+%?;bLYR!pL36[Nm3s3fLJ+jqaF67tnVIfNcBh,;JZ>=,u+OJl@YX<<j'-Vh5*'6Yq/aaAs-"S`Fk\L&eOD%deLpf:<cogUQI:=cXj
+%2J@7KK&l#u![R2UKLnS,`@ll0.2P_poe3a*n=pJXit5At*!.]RjJ`m&0LYu?Cj<`j!hcN%:^T-r;%M5pTEhCRS!rSuB;1bf,$OZ;
+%q""[C;oLX74qu1DqNVS)euB.2%Trf/r4&d>C\#HG(TruqBFIk4!Wl88)(>EY/)rWsX=kgE]QJ_ZK$GraUjc@c2"tNp@C[M.CPu#I
+%[d59`f`$WO^Y/'?EZ*1]Bftq6N:g@KEUVJ)J%YRlfKgkFMRr<[-Q1--RjqVu6.CaT5qi>TL5Mq7SXc^,@FD#^hI47Fi5E*6'5pip
+%T'V2tXW/.u#)El@@@ld6im!AAI//_#PmL8i(SuZ-]/GBPYXr5&RP[Wb+uanL3GTE%-$Jh4ZogW2Ek@ZTO9T.B9-79X8sQqTSt47s
+%ROJNu)*IA%Q[B%KLmW4jj>?pX!Vp$P'hI`f"Lsb\KOYS^d6T2BOj"lZ9EcMO0eF'0!4@GZJR\*YN4I[a(RqbiWuo\^HpY7nhuRa$
+%*+L#)^R*Qs8K!l]5TP^B\A[mX.BCd,d'0!JTbF:@niAYEVq;=qRB1YU&8fCT]rqUn8ZTiYAcm,k(O*SF^".G]aC&uu[aO;oBNX*5
+%_.g:llfflNWT!=@-?"?.O12kZfT?fZRcLTtiqOlZ"63[X+\\.2aP%9oS'hae3fAb8,@5no:m&P9^,L7R\GW14b5m6!MI/PH`mJ<W
+%FY]14)dg`^#3fm7dGnuXc`"p/_5/$pBHp[S<#DMNPjogF%1VjlH:.?aUbl*?4s7hO\O=R'UpX@?reG,f=3LJP1Je9R@:jH;?DA$g
+%_US8BSjHsJVfJUf?=kY5e#oEm+'/%G$&VXD#CO%$H()W!I;RMV=.#;/5_e"'#,ld&`O@-2'a%DJ(uBH=_3:ohpWEf#>9Ge0D'+5B
+%eH<9X\+LoS$;gUXDPX/Ph9%X]h=18$4bNML('@96Rb4K_V@5V8%dV8T42#EX@it'/g[<m9\XQR#2<)$eQ-I:<YF=i-+AgI::AGIX
+%?"g&)J]so0@TK'H1GiMl1f']uRj39d&Z&aN?+D>@8%ZLA9j9d8`lK7^@Rtt=#S71B`)DpgV2B\B>@Dlg@4fMlY4Wi\`:W=f2!g-7
+%&b6(6.sg,t.UN9U,W\m-;iCo%)9gRX>-en['99`[&cFhVS!hbKnDd'.6,p6Q"glZLO+j_^:;VIS<KrG:T].P_K!KLlGDR=7j0Bk?
+%EM$0;e8R`i"[J&#q*B.4Xk^hg.d+'f3jK(Bl&QS*pdnmp+$a$Gb+0(C*X0*==l2ei@ABX"*VJ>XP@-4V]i3_rm-GF]QRn/Hr;,Mq
+%+2;Kt`WWmV-cUqfDDn,J&KFueQD[4FGGYO_/T-PTngm?X>MlShNSBMZ'!V<;&#0G#9J(I,`XI1-DHo]u$79)O]JgeE6:>naHl0)D
+%T$WE,:$@Pe((^76H,JBCU#(er/G9&W"V?3tIEC:hP0M)8ahVbT6Wdjh)6>JnV_^oB<$IJTWgdB,F,@5a[5$`d'?d[YY19Cd9H9>B
+%W,]jTSW'5SfH+T#!quQC[W>?)Sr<\npa.>e4H!>q\H4);YirORX$!+(A:TDg+4[ht@Ip_G55BXfC,6bWCSW\ae1WEE;[(XSMF))(
+%>b2,m`nE>5%5h""!"j*C,gF3\<O#rl3hC5hX"Qcijn8GKSMia9Mo+&Q\I7R?*j"'IG.[r6![!R".#gZ3%YdW**\W*Jjk[4:i=l?b
+%HoD/dieR,'PeUGMp$%5bRMjetc,h(^7cg.oKfF:/V;mN'AqJChBjkCie^%s$44E)i(hBkQk&M%+k_!"nrU:kG@0R7<?[]JG[m0)A
+%DPH7GD%CoDPmcVRJ62r5"l?GENcDt:KR1`pk7R:<.:Yhoo\KWLK/@!6c920#p!=bs)>(%A?@s!<\h:)$RIT#tO$Lm[rV*3cX0:FT
+%>1*Gq3u['r[;FS&*%0)YDfe4pO/:quGLl0f_ch-JEci1>jV%bB<5QU8R_af\%<gm%(Fe+JY@K26<^Mt'ChK9h..kP+$Fun5`><Aq
+%gM5]p3SLLt0331.&&rO=A7k^3O96Mh7ec8modY:#]t!82-FX>^%J"VQfc!`J2*b@AiNo#uejq"g3ubB:BXUBrP(;4`O(n]6g&91R
+%Lr"qMIMd9oC>8#o\?cl+UcUmu2M9s<Ju8;C`jZ7@3-Xs+Thd#JAE?$T,FYcY-9=E:b%?B.ak?`OmZP5)MCh8(bgce)&R<f=(e4'&
+%YgfU*)5/dgigNO]:ii2o#gdOb.%sm-abEkFi"`[rI)X/&]0-?XXh@OQ=)fC0V)m%3,'m-W^c..W6/u_r.a]YC@XKbsoeMVsA1VUU
+%;hT9";^!mi,qc<em''jq"c_!`RE!lg2%hjOHs`+]'H,(^_PZ_@RdXq=CYaATN9NZ6$=aAZeA(-eZWD?/L*Oas-DR?-mskLj5#%K*
+%'2dTfJl#sY+=2u+osef<M$=(oEEJIbFrPTOI9WYm]\/7!AK50,M'"pnfkcWr+lmh;jg1H$BJeIG73@P&r#os/S;!42lmd9b86Is3
+%=U@NX3B8B-K"Aj"l\^t.=W&2Jj=6!(ls$EFL)M`b<a<]?O5_`U`3g';<AbOfCZJ2T@H:(1q,fLpjS>.CZ@][Ql?YG=fNa/.+en>/
+%dArb>p+7@-Qu*"%-=.]'@^<gM$ZatXfq!uGF,&O"S!QK4[cT/+R2I]Bh4']qAd!A.h3?Q]4bnO;C-OR,!^,DTIJN7-A(:Z2Ec!6b
+%CO@l$Ccche2ggeK_Ma$`'\>S(FqXCiZd6H./]m#.(a)0'%mS#6DB=BGN?;@k,:q8TGf!6iAkent(>u<YlXD;/L8C0@\NUY[`aVaG
+%BMV6)&l5nu9Rob,#%gZ<YsnFeIQg'Uan&;j.Um6k_+H49bkb1CpU'qVSo/V+AW6lGOko.,q^4"LUN,mm/MehSobb>[JEKD_eG0*T
+%=gH_I]afR-_R,!G9CsS1.CS.43khH>BG[l?nb*oMH0(8d)oS9;m'3>EI^8OKe+Cg;e]$2Ca(X*@S8dS%08RR`hS=Pgo'4c9D=H#T
+%j)F<"'qe,Jbk%dhARn-H<@.cVb>N7b#Y,!RDMk-gl&8?7#N22j$8J=KjFj*(Ho2\SrDPNB"K+QGEm64C^nkt'B"Y@6h^/"Xk`5(j
+%8iP-^jHh/l\oD+6ULthHB"7*`ag^FJ*T!(u/UX7hSJT_t)AqU.$Ga52rr$5$@MZ^9r>o,'8?5f1c#XZ$QNib=YucfBP>m!5gsaCg
+%\6K5DKpfAGPcP[2Nm_c!OT^;iVMTW:$6mKAh-RTfo7F!DY,*!9!9)A5k>.edmWPe^lJ%q(n.Ed>;^3<pmI,8F:rI?'.JSbJC/-[5
+%DEKM$a'5TrNk"TDg.#=`G;_rRRS]aCmh"k!!0#TBFsL=#\9!qXi8%#Prm&GT+uLi>p4*Rh7gX](bH%InKnoS\lruHH(#[BQ-_Gl_
+%:)6j=^p_T.6X7u6l0>[5dK\5*+`$aX;Q_g1T/bNl:://@QulV!"Aa%bL4sPkgKPrb@?n/NYGAVM4LW*,i"F$X>Ia7r:>CEG`[5LO
+%92":NpjA4pnE6]K#oO'lN`Fd<E"Dg1oj?$1S%2cL@T:JCQ3$U)K"M(UmS4tA:9-q.Da4U[5%F5b7#r.aNilAbXYP3fA83M>V)EmX
+%.`*I<I)WXn'->9I*uGZDba0Md!>bo2T[ibS`^!T]iH.FfPInV;Y=.TrOk*6]&VV99+e<b9g)N8qXPlfY*M@9#(X[!kEb@m^g0Q\G
+%Es;f^E7e<uSP\a:h?ErSE35nG.,>*t8+p..,7.=1Q0G$/B=J/&gtG$?1H8<-[eIiDH7)WOCFt1*8/4@=7sLB.l-oB^NhaR^9gW0M
+%HGp804D((2T#sULVfM.,4Cf]]_F1K`Pk]#SYP]qJmg(SZoOb;6#'s&`1CLY)r-C=1OGbgQS_&O@K'k&n`-8T@,k9,%a=OR=`9=3-
+%l=&@m]!D32G.JgXaik(*Q^5EMikrZ',>k_adQe@G85P;qK@=@nbqJ``JU%#\.^&2SUdS]CUrd.5_UXGAG]Ps.D;l@3kl9c]a+&N2
+%V58Yes8DZNc(B7ZF99Ea2GhbaGJl1;(>/qN[\:11%,d\1R>djde&>_B[W5L1C6i[M\Ri^7V8;Bm;o**%XRb@(AX.Bn+=8.QV"<>6
+%O8`;q<d]_FCTj"DF;:HF&/.[\>(P.I+3KtJPsLkof]Ysq7ZiGH<j14uiXqATj0/0>6h5Ce$8'E&NNnUtf4Z2+ED:aW(IdMmpiC;M
+%:_GVuOt($(Y#K6fc5Is4g-P.DfspUg4jno.7MJ7-3d&n*W[N]RM/J_9!,;+)!eN'l+%mO&Lg+p+R;@;/[!hG?d=X$1iV^8#<-X.M
+%Na@Ku@s-e4?Z.6nh/)_r4oWsAV=cZ*`P_9nUBJr[f8H9?g,>GIK,5<D^6'k"iBoo3:<W;Z+Mi`@1hN=^C-J^P,@Y0*[WS=leDdm`
+%5;$NT^_#7q%0kb1%='E.ZpU<LK/SmeX7R\sU`G(P87t'+d=u;.PY&MCiKe9$k=OS9[?,1;?g(feLR^44r]ulC4.nm3BWJ3U$UG]H
+%b1S0U]Ej@(:Uo-/7Al9^RtW(!TUW-HmoT3Z09Q9#]_e7:]hT8)Wtk34F[UU&^?jt1,L[fsU0mOU)BGc!0]6Q#$:^]P<SCAsrO&nI
+%n*=_3&%J/`m"26oBq1O$iBF@Rds@1T%O@JK[TR?InGb2Z`=&V<JBU_j[Us8,b/]?`7*T'8h@,$HNO99E#Or$qX0_Y&j.sFk\##&)
+%o"NIUMkdUPU:*d@DG!_RZD17qcr`ul8r2mpp/H%nVT5\lE2<8+n+gDX?p1lcjQq]Jp=JZ3[79F`8FX]9B&OJ]l"ai\:0Qqi/I_h,
+%;EnGXX?m>UW\9N8-D*aEJ]4]_=)a4@mg(WB.'DoK.1NDS(hM<rRQ7*g#&M-h0q=A+@*et>csk-G6dL\j<@b%Npr9XBQ-m[#WCTpn
+%gJTnr2RI'3YKq4@U'-##_IE#tM/Q#p#FG's?_t?gl#H,&j8->3M!,VfN#ilEG*U@k)NT@OfBOtC+;C7^(Mc>))Oap1_&O;81ob"U
+%V3&J/<_#)k/:hS(2,Y?.^qht'G!sS>D*0P>1b&A)NR)FdK1$fbRr\D>iSl>&Lm6n<nK?(MWZFl./0:V@=k9Uu_FBWOZ@=(goG=C,
+%.Gki_"09NdfE]'f'P??+Xgj/LCCPQO1%fcPN3aXSUO;gh9:UpfniU0"J@]T?:`5rXn;($SdpniOY^2\J6>%3<6,U:GK(Z7</k./<
+%W&rOt;G/X:HN=A'k@Z;G(/g-FI<OUT(M$mKCkWXNXZ7A=.SIET@HIj8:YM*gT^iS$Y6\$Ap?59RO_X.EJR<OqFR1HIQd)hF[_Cs^
+%"hkp&8Y>9Wj,o@i8@Oi8>7o,ULln4c9U!V`2BhV"9:*g,d'h3\Gf!i\DNLe1OD,p_Ej!C)C6cEWa@>`Wktg?&hLXcKH0VCNPr0Jn
+%Qs.=O(Je#.<pQ&B!\Fp375/RT&Qk>q2C<3-clRT=cr[.m3cqRQ\rfO&^`"GSXd6b#*#^4!)RMV3+;>/[dop6b)$(RU1NTNbGoLVf
+%)d>gBoqN.KYTT(_TS1i6%ocO5j>iVWF/_f[&0M1=gdJAgC%Q9e?rTU$[IAG^f$OaAL8Pk)V036Ro@6cCkATaO+g!f7"2!.(G]bH1
+%n0NZlPN#N""BS;0_Sb`CO?4?t_GoBOL.WY+7QNp>iP@T(QW9@0Q6]i?67$O#G\0bs,)^hRKVLj93siIEWmIR=>9K!KPqbcib!:#J
+%+j:gn^6\[]D&mG1`P6o3Dq\)K9e!>eA##BhFI?><^BB^LOP3.tO?U,q>=/hGTV1=kY7TH&]hqd`W?`:JBkrK3]!TAjPF]btj^eN?
+%kJu*TfuR?4-6&qS"e.k,*J8WYc#Ppk#A?[D/A07H;*m'E%p_4=PEBdf;\KXuZQ^q[(^&6JkL#W7XsELKXaQ,1R9*Xo8uYp;'WOa1
+%5+.R*HX%>-IVBg$.s&*-Dk$V(K:Fb`4"3gK+CII&9Kr/%+d`UmR((_nO2eTV0MJi2p9Ppd-Z*9$kdI8-dE''[]p'j9"H2g=fH7HB
+%R<?EUh5XMFQ/&7T6iVBkA8'%'WGV_=T'k<Cndq597/ls]m9tlab3tRb-e^P))t#u/gWS;,JQ*);bhYCWC-o/"HWa9(e:Ro82u>+h
+%LMF7kHnr)5-[0ZH1BKTDU0*N^7lYZgO4IrE:6:d?]/Hc(.I`nr]`))<`G\N%MV#lSF`Z7aCYHfF#89@*+1@3op1e:<'0%Nu107(G
+%@5B`gW/ZYWf_b'5-A`]b`[[$W'0_S>*bg"cY7Hn2]87\1!sMPVE#`uSMZsAncEhetLhkWb\rgn(IL3XbZ$01FL'i."YrWI05SMjR
+%Z0Xg5glc93%X"<,3pYk#'\40)#HjS0(<<MW`$JP8\:%A"3Ha?TZIBd24\aJ/:_N/9)VqH9S&$8WD`SAQJ5h%6-ojgVLB5cL\5>RE
+%PtpRWN9Mk3[5I)46[0:;R$EG9gVl_o#8r,<e[TeM)!P>U<*[qjJ,s,Sf9j#&:n7XQ&5nBsJZ(=ES<Q.F%Z3=L%_osk+J/uPj;)<?
+%F?O_`4Aht3)BjgONg3Bj47CjBQK(s'<\1.K@!kD2JQM'tGX:[MB``/<b`,HC9H+'SS)%o&0Y4A20]U@*WY0SfNN)GVc*7dfo^gKC
+%X'_Fr#E]JD7[dJK@<oSA!1d+E-4We1C9BDjYKqM5!cNqnM*L,tYJuj"[LSW[/C)bs,&%?4a80tG/lL1m=)r9#&ckYA,Sdc\_-o9<
+%r-EN&OhZkqW>X5-7CXh'HG%-6JH?H^!b<+U7dqN`pE;;6)mKW!c;mSj.kqLDM^=*65S9`>msR,a.ZLGrE.b=oa)NGWW_1GOEQ1aJ
+%PmG<R#t6aXCslEagI^O-H-k3H(<'H5&Yk^U\>B9E,m+aJ'A3K=&2SP"T9MeD(@@oYaiX"`=X;S,j[pege0[4)@jANuFjTMja"W(\
+%61LNs4tQI0Y^;74=s?s<02C=*VbQ`BMb:$d7*DW@H`t[S%_!0l[9a[f?d?W0_D&B=2W_nW8FmO#8+COu&;eWl:k`,c/>#?4I!Ak7
+%LK/-4`\hG!d7:a#enGVD`CE%hm]FDRlPkrJ%fRc0:BX<)>9i&Ug6f[kUl71W[iq7S"mUOpKO<PRN%<PBkI2g_q#t.(oJZS4h4kAl
+%<taA"+SA95QPQCD85Kh_X)fI_U`rHAnEQ)^K,qk7E&7gjY'FMr\d26J1N&Zp=dl:N-:VADnOi5]N^G5M'f7&CR?MK<E_O[I@!m^E
+%7\DEQGd!'+kM=i,qGG"rMA!__T[A2<_rN-rN4c"3=)I(SJELgh]@r2d+O[a03Z(0rb+n7k`^YQK`aG!T,9=^*]$NG*`#VS:CiJ^_
+%8\uq-5Rt`MG!kIWa"<mS?pQ:P)jiR<C1JT+,Y8UOpbBjGc.rQQ!,4_\\#9GL7-2N7DBiA.Ji7A4@uE7BJA"+`"4S\=&f^?u(Z]ma
+%LbLbp_q\'-3q!*#>'Ok^*oQ=fd#AOmglr=L"*OI0FHJ-EV'CpNe0bD0H?R93TL[-r6`rDbk:@?uedA$*(rQSD>6B,O+Kfs9"1\io
+%1_?-O/+d%3Rq!gX`sU3pT2L8lhXPGtUXh<*Ffb/gG'1["+S>>%_D`[*l:aA2a%g%^c#6bj=(QP66g!1Ph9?nL]fgkMDp`#\"P+SM
+%amhTtN_8SF&TrBgp,H<^Bcu0ep,#)`N1K7cJoOG4.S9uRO=ZWVYO\AfVC`-1n<3>nYXX1eZluFqZ%lmZ)m;.K6;s:A/`NM"Ca[t;
+%=csC\,"#9W1!T%fKp\8PNML/;"KKQTg6"p*kN*T1A)sAC@$lf0A7&6dZ9frHR2Yig>(cru#,k$D/$Qi>cp,CIdNfK]#]MrVPfq')
+%V3OQ-Rfc)'3epP>ZfML,8&s5G&L1A-;oW]7'4=r`/rabIU7D)8LG4+,FnB7/MM5*H8>u7KlJMu_aL.iVMLYbZm/58Kj,2Cnia<iI
+%4*bn[KZo*U0rTK-Wm\Ua+iG;2IF\UHN'K3uK7&t?AJ#O%>XGc"bj)_LU!/5AO]UghE:"PK12]O73,l8DP1HQW?Zsn8BhV(:NNEZs
+%Y`XjYdZP*<_U.!T;T/DUQEO+Pj5ZJ5fjmK_`$nfsE/K4[q'J&VLC+r=?.XUj94RL53k.`MEG'tUB>s-?,i5V4o33^8;VH"fX$6F;
+%3phshSP'3n_Saff>K=slCD=,Hi:!Y(KX4ETY'hXoqPOf/NXSq4c=#3,R@ntB)U&Bd@tdI=Wgn1B%m@2KfpH4/a#$uA*CIf,YRsQ$
+%,78\'iq<J=,6?KL4_LkkOEADVJN6#0`\sQJ,^+.@\;Q@FlJtn56QeSPn>1R%D`G0F1]4J"ODpCF`FK8*)C(Y)$2&r_p[dcB8V)k)
+%c5SS8pt6:e<ZVElOBNCsZoZbc"rN,Cm+>CXD9^l4XE[=O]+fHCi\:W'/H`>A/L2[%]5N*_hb!Y(^&]Y%dOl#&V+*O%6fA.a2q0>2
+%\*f_Y"Y-_/bC9H!4+C@n7H2VTqoWnCqpHi$DRU%cF'<:D8<4/89PrQ[2F!P8,6W`[M3nthmtj"`/2X3.m#36OV;\MWlPUL+:#;8m
+%m-=cSMDNF`CfF9PD%`-/QH&e-DPRdF,2R\][rGtlb9n5':4H@<`"nrKKL'gL'Vdtr?h+'DR^'lCGVSMhYldi1k8(#\`W`h-3Xjas
+%iVH;BMjf]h-c),XirXkB*Vd=1rAY7!h$g`pjQLMM#o\AV2D,5/@$W*KBP1t9:ts@S>L5<dNW@2-^n,X4qguQP0;_qZmF2_n&i$[;
+%d(30o"\0hE.qnaWJ`+!\P!MRWSt=@sXGXB5LsENZ6&/aI*e?Zm_Z2;nc>5o6Xjg?ig"a*9mr!t!1"d0?"cB?bHXe]0Io+nB3(Y;(
+%jJUNDOaT1i-^YUL7rl1E-FU2=O[%QN>?<>--=KCU;SNa.Be$GBN/=tD+V_01YtsU'1W)%QA5>/-8cFc5.^#jo@7%nkD6\*sO^&oD
+%%U*,f.7c<E@s>E.6I<[hO'4?LBT.p%U2+L,"al"8kMZu,Lm/COW-h^rS#"Qi`[8R)=H3L0!c78W_B%r&cWo/^]H\FeEAkV`a6TQ9
+%C0K(NS?R$hl+5cFjjhBDHSN&.[$\:;c'W13#D9IF@Bhk,SLbX9di$Z&;J;:O4-!=$mhkeWIIAZ8-lYZN0IPTjI)"lY:@;=Zq1Xf$
+%0O?i@HO>&n:;pL+-/NoY?t0]0+\pM@O2Yk@ja)9rKDW#unC-!mHp'Kjc&md'*$4F.<ql'Y7$0ZF*0Es-)I3='0B%.+Ns!@22)"R^
+%*@A4t*AnF(D/hi&oS^9V,"r&e"E+r1Ep\lXT#kZX`hihu@WrFQJ>*&*2_>O*<!M,35hN's`9`<0$LF[4RaUUB,-a5p>8e#bS;_OO
+%jJmbMabZn4JBPa9*P,/6d<Isa#Y;"AMc3EM>@jY[_=neGm*;II.'`:DTkQp`[#pU>1t,1qfF<n/&a%M6CNE4(D"TcU5sh!!PZ]D>
+%Od0"J`Nf&o4"5ThetH9rQt/720V:1&"&O2tSZMp%D]mOUMb%Z?"W>L$7GD6*U2@(*WHMB!<'!E/j^E;-N1oG$rq<&hlnZ`HK2niu
+%$V%@X;bC9s0.>ptno4BVLP_=#`H<%tN_aNM`M)M7MZ*_A*OXOQ6V%utJhQdV*q>]B%&aY:W^uWt1mYDH3#"jo&6n@'ZCT8T0]k\j
+%2[XD/i1qWe3ul3a*@TH:>\YnGiWd%cKu*?2IN68Cg9IF;-^#fY+I$=9+&k))k@jX^oa-4i5s'%M9QGLQBS+Y0joqVN@VOD=9#ZbJ
+%o`R\NZ?m-=V2u2CSk1)J<T?Y]U#tXgMMI!W9->W?G'*'*b4Z1.(THgKIUbt!%PB/F/0KmEX?$!IOTDaFlFm*H4ADet%Wpt9fp+Ku
+%dQWSZ'4.f)GBG;[.&Ub;,S5s"06PRGNGtuh`dO69BRgObgMDhJ?#80&cHX7'_8B1'--mVAerr`H\XhtI)*L%-8I3kJ_GHh3gd6_D
+%3O=opD05I5jJ+;[CMQEeUH#87XYGmk<u^X!4.;5dHu)]!8Y&uFPt#rT6Wgm+7iE-A*Z?j!<0i$U02eR5qmSDeTdjO0_2ec5%e"=t
+%9*b7<mM;F2!=Bmu%0Ip5g`)@K=+02O;hS*!N7o<)M],.i>H?Mp6<;dT4S[Fq)3sORXJ@M$gtR?O+[>VeB9Q85.c3g#I%Qc-A2n/X
+%lmZjWA=,5on#X$/n4<3cD-+pb1r="*D?juQTNnGu]6^bFQ9NF.Qfl1jo-?8um$hdK"LMN"7gV+,Mntna-`:;lh7r5=e(/sfh>C_K
+%h#@?s9Bk(Z't_pr-OT2lF1ce=M?umFkkGq/+&Be8-ZZNK)W%CNkqr("l(M>(7dj!#<6N[e-'V(_B</(+"-hX`k`Hthc^^$>ch41*
+%9*?oT\0Af0)&pp^+n-WAMBcM`%V;]PDMSa!P4Rh5jrd"JEX2F@l41rB-D2S&&0Vc$9VV3b30(h&@O14X-3Na.fcj%.6KC`hL%p&#
+%r%+QjeKo?,r+5;mOP6/r7)H</Br7'2>/Cn_'@ug>F.Ym:AC=LFa]2/Jkqf_Qa+jU.c'&@<W2+V5$Z*-#*?gNUA!mmtaDlDb6PY$e
+%ii9&r7*mQ0%TFpgE/:`34](Co<L3sJoZ1@lA5H08-lsn6W-YN^=rB&s0jATmV,T6*Ol-]`o]:h1;:lT:H#RP/"'OspTL8fsL[a%&
+%TJS,!=V`E$Q'p1V:E,_YRkZn&AGlQjp<IDN=[]gt_lUDSZ*=nBrAqk(hTBaU(8kNt%#,^PSU.Tu!Q",?F^=at8/qJ;.?d.SlaR6O
+%`ZPC>`i%3-J\1R<_=t(@]G:$3fmR9148a8"0i8l]\H2c(I`-Aab9Z@:7']c3V_jE/kA8/+Un?8o&-7*7Fa$'j9#RBSc]3f5%QJu%
+%YcTNDZr"Ef$FY4]kZ3_LACdj%W#*AUor1(k%!'%6XAKGoW:O!IVu!(';<B0;P&iG)(^\eH=:FHHoFk?RLKVht$TfU<eE?rf5%.3n
+%l:sEseHf,0ehbbt?i%YX7YVt`KX`'DTtoW$$bNP.e_<r-.R@WeHA30'&e-"=7g%e<66I>^UDpn:Z3-:X)gH@&c2_r/88as9poEsT
+%>_uuJI;i!6E>"/?+OWQk8*!S`iooA=8g>_q_YP;"/u<j5eHaal)B,WN".G%H,A4D]U]XkGDegVFDmgCcIMAS8da:#CJ#)GR!'5`Q
+%EeG=j7p36HRaKZ4OuP&fR+W[^i7,8CB,:-#[DOn=eLE7::t1rj/)h*il1.V]Te[ppM;ZAC7b`%AP;o7YiOLqM@Y+'M"99t7J#lX*
+%jqk<j`\blI?!&>=YiO^Ss.3)sb_;gtN0.4rj"mVn2Th[Z:`(J8;D\r?-t4cKG%&q8T'5r&3fZQfDB7:fa(^of$eCT'-rVT'=X5#I
+%nfsT&?/`IW(kT?_d,I4C0C+3M.:.^EKdne!7\8*DN`=F/aslOU[UrHCjZq_W_c94[:$6SQ-4b)pM/eQoOElC`\I'X:FlHW-/M&/^
+%Z;.7HJos:(,5gtW)3_<pL%T8#.9#bMDJ"mVf1q]E&]?q$_&6MnJ:PonA^fF2g+oIhRu!$GMFPS1CIWnH#>f<ude(4BF@khXKQ8!I
+%I.E:sC!X:]lB6>m)@)7Sg+K9a*'N5*8@N1"o-:W&526kG6i$pndk]d=N`l'RH5%j/Ak1TKku4BBLH(Zhg8!M<N/X-X%@AStDDebq
+%3p2i=?u.0,=eFd>;l[0@LuqdfdZJ:<_<7BfedZu*NN&P*TV\W"%UWA610drAT&1c"[4RbUXlF$c"*n&j#Ttd"Q5lZPO4C3W&`[R@
+%o2mLTE!G]K6ED*8E[o6,qB1Pf7fmQ;Oc=rXYAUu61(5NXhNZ[mRop&oW+t:jm4TC0RrU-S0f;'1`1h04OSrl^91eD=PN)(JKBho!
+%I&1thSeA<!!Ie#JNT+82F;!*"W[39(Ku1]KP1VKKN^>rcgUr//)<Hfn"!LWdlBeaqN"eR<DO.A"(9GYb&A+FdKmFuASRiEL-sIu<
+%VC?>[&3/.3Qo1VX=uMsh'(U&Ep?]$Ze<?t6>!hPNDRiV:caT+[HL-)-_pT[Q5\r7Z&"r5<,F!P&(&SoK59_cf]$UnWaQRBH>$De^
+%2&0Y-AQbePXm\^L`<50IAQlB?/KlVhJRV.9Um;U"d-YNV5n/J1<d%p\>SYa-/+l9-gk)CF(\7CSf$TWOp6`P_=p,a%mNUmLg.1D[
+%b\':JZU<)cX2FM%C5gU,bbX#5MZlondDV;u_a[:M^(HQAF6t^KTU)7JEFCk2TpSs">Nqe'\-?h@@90o66H+l:UFX<+?<Q<gIQ2Pe
+%!9t,Y7q5_>e@+$0]OeSVAZN#cNl6t#\gYH=Bq&M05@,-2C16MZ'+kOW<R(uJgpkmXYpGrbG7\d5JoPTs\,lNW:0;lq#lP(O36Nqj
+%CT3W3!gV@LY,<IgapWd[aLV^g4XdMpTk4'QD(K]1-$E$9(rT-/<-$jIi9Z=;p[Pb2;L%d[:E&'0<XSW+eTpY,,0+pF%OW&j70q]U
+%7l^=LJgkP1R(Aqm\+<EZL?R9bM`KS<?,t4"RYbam]&g%U@)D-#:R!4tQo/Z87Upe-`kCT2>Q3&3U=5HHNMI%aph7(T,'n"Mh_r$'
+%Wh-A(cPd4j2C$FPC.^cd4.HFOA=[+nF?b2,\\dc5<f/"snDgpfQqqiaZ<j*+!#Y:/'dZ8JM3=%B2ll^c&HX\gJe6<Zj*2/S'C!6b
+%8FrT+f4,9;>gbp"b,>a9<iW0ZZm(b"X5d.,p_[p[\npJ[oJAf59T4kj*.bahXe2AQQ#T#s32]>-6)5]+CQ6KMGm&\-J]b&fVcS+/
+%GRE^^pZ`q-KWVP,@'Yh'H=/,#a^iasR%"#,>(Wq";G#/Cg4Q5QV?%?rp!@0bMFsb6mUh/MOfI*=SP$q.p4Vn-R,SiB5ZE')"(=.)
+%8p2+50bpe[S>k(QEpl&W\_/@A+_\2\Dht,)'t0LI>f<lEc"2Ya+ZGb$+CJZ9@?E2@(Oa"%m8?A)%O!\@Ct+>Y>`%rD0HT<:)U(J/
+%I#h"t/<"J5p3;2;NKiJbm85:S5hl$ZDR&09nfEdC@Qf+>;UUR7:o0u=VIh(oe_`us%%"!gIdC-gfj!'0fH[36Qo2:h7JBE`N*gZn
+%A;R-dMK;lZE=9KmhQ*J$X_f6s8Lm`W[oC'+Bq[EG*#nll##9e[jjUfO\N68=,7+D([hUJUB'+din$+,WUK(FN-e_;WV9M0nW5QhM
+%%<7LY#a*f;(3F<.]UbMWJ"ClKX&St86C\OMert;Wj!rO\XZCBFWGqQu1`;b)6ai]TdI'\\;jei.]3/acOh?Nj.KgiW-u8:7=<Y$$
+%fqP5[M@9W;J@]'q/e`Gl:j1TN&Z7WZ\q./i5Qa]+Wjc^_U@tf$K='9r>3_%iKWF"C:t`)SmZ^Fq;?N)f\[BhsQ'3`%Ki8qiS&UVh
+%Qc;XgX1^5h^N-S=84P-dfO/PfUT61LX@=+fj@j>`2OXY<h[Gl9#tb8U@Pblr3:3c.'>ukq)CE1YULNlKXkIEG0@OH]j:Tj1P/t%"
+%hBeSQf.5++^l(r6-PcB@M==c?V#Fh;rXoNC"nVS.Z^144Cb/<pHETZ''tFRMFMn'3MUXSs&P\-nQ-#k"S/SgY'#iO+BCA^ZA-R+E
+%itQqp$+@*jr2l)&M^p6uo/Kbs`83>&o\;ZePWRCpW!t#3L<5QELKaLE@3fM4=$BW`gUX>oTiG`&*0gPD`TiORAK?aFAei9Cg;rY`
+%*cf(.41il/;FOIQ1VZ8]8--1dp(!@HUKb$:X<kJs_)U+6#T,^0^mX\t'm4G5HKA<e'_(<ZKCXK5-($_hG:eM`KTETG0XJJ>>G]6a
+%,k?ba]I_-;'@p/QmR`\b@<a9@GE%kPODI;%e)tEg#W9NH%BC5M2K/gKmVAja:uMgFGn"(aUW.%b#t.fj*ig*8W,8UTWrQ_<4kZcF
+%S&d<!QX15pTeYaAk<T[Gq(oY&E/?;,YUJi2+\Fh=%$`U:@I)i'BGJt5NKHbQTF\R'*nk?3.]DSNIe445&kB#tOs]3d)Ok3cn4/DV
+%kA,T504>uZ2dKNTIZ9dnd[7Of2?R&XorsJm08$"SCZ:YcEY=ceQ3M;Q)\+ZdSLIT+^/85g+b;r7*T.M3<4WHL"%-DgkN!j-p,"!c
+%W2l9=Q4u&0.9g,"3;s#=PtQa$jK`7<V!+r1#obnZLrK_1h?I&.2ET\p=Vt+W<K4duCZr3&]cR6K*XQ1PX=>[bH!25F!g4LE9%p')
+%8JSBRBghAYe^>cX%]WXa)`iKmO@Be1NP^*0)C`?rlsq633:LSqe$1OTQUkAiN(?THTHb3&b6)`=9eer:Y;3&.]""_U!.f';G_TH\
+%s,>?/Zbb>AC/W@/Z$%&TDM>7.ge/%`[3p4.$26GFX##Q:_SgU5.6<h%<#8Bpb\8!t]WAEbRr!a96@j$*Q'3`:%Z@_Y?R'ecQiKW(
+%l@S=-J@2#Pm%/\i?QBFn9W0O@?-!"Sb*=+h`eD5P,Qhu0>1WB)bq[q/2Kkui@J9t+&NS.$-k^j4;3M7&'KVf!5d?/+;n@#r\n3(g
+%J]i^`*LSrq?ilG!Rt;$5c&pA?c%)/O\%LZ52&rg-YAkqoQr_@0m4X^uBQZ->b"DJJJA>c<#/+D7)6+)06t9QXK*oai,P_^?o27%t
+%#H!;,G?MWuVq7Ec047;*:-:'2!'K'%aFhCkZ[h;\lY6h,/%bi:7rd3dkW)b?iBbJD83KX]1iCEW'gadJW30V`^/EKK6R1euNcFBX
+%7V^So:b=4HN<CV1f<4LRQ3C^@Z=W?lgXAd0TOp^@X[KEBR62;I[c2SW)j?9r3.eCBW24!l(R8.JDU9A]D]=9hIGKPcf"t9s!9[se
+%jBue\U#6O]6+_5dhQ%\%,J,H%%)l?uX/drD1)4FJOqV88C7O>3G=f#99&LL)H#W"jg%[TrM?>RT@\K^2D=5I1K<Z"Yn6NSJfK:)M
+%i`848\!'m^9VkUGKmNfs[Z1C2mPT&#[Z3bf#9Kn:-?6g6+jrGuRSk`i<A#PpQ,t/Ir`8"j6htZ.T^6+2DYaHs_H;jOV[;$/!$??O
+%2_s6$8m"^"C/S&gZ$`kY\9SeO3`H`98o_5+Ll@1SdQBT[\1fZWkZ1,g@%h3K#cKl/34CL4=,t'+OH<W*EPD%d,;L[^'kfq&G-oSh
+%E4*JdQ=*>#.\+S'l!+HoGMfbI[%kHg='tUY<X7/9Z5]+[CApEjX,D8W'G"Nf'L8`b235bmF+99G-JLIh[S^@1BC_:5a42(6>%9pa
+%7<'iU\b!<]-fS.nYZ,;@)C./Vi!*7D)_L1r!a(?r>Q@k13>SBkB"jju"0AKW)?oM`YrSc>GM#nhW(9pIq=)3^9_:k;UlK>8*,]BK
+%:kbo5qPi//!ZnKjiA=,k8qB2F4UEKmo(AK7psB,Rb,o//jegL>,?#hU!;t3I*kkQ&U1k&=,c3%S8(OX-NF@.nnA[;nWEZL%m?Cg\
+%6"I6q/G1pp_K@&dRUQ6@+]5N]rEb$T'R3S&rGu5/EU"d98FLB\Ls<k&8p,+:XGlK'&Zs4TqWJm[Lt!$j.e?-2YXCfFQ!kl1WE>"8
+%1.d?AobtH%3d<MQYOsW<)&sk9.Q$ADp:Zbip6A/NBnVMLpast=Sni!$&u;?=/g]KS<W:]"mg,+X\ADo;j)+?(pJ"f3;EGDDm)&#g
+%q6ds$$/G=#<B.'\=eUVHf^q$E@p1ZY/(37p`LZ3rWNr,OO4TW?qI)E9h$S#-Hck-O2pd0q]^U0XQDL^,c,=;->(YKN6n5HWA_u];
+%Ks93MA*cEW98+7ln\2%S2(+?k&L*i]9XO_Bd"^i"gb?:1A[E<mJp%Qe8l]?`V/.LS;4EO;?Q(6?\P,`;)!3TEV7,"<4P`]Y`W:EF
+%M6-Ij!glf(5/Nsm+3VG2H-'!Sn<9<b!oVpQ`0:\,_o`Sa[c>;cd$`J(`GmgO'7$*iga8FBoW8s@;Tg]KLGc@=BiG_q2$BtH#?_JB
+%#e%@-NW=SdL;r\3cEoT@b>X@Bcr3'P)d)Lq&`hb"SZA\l4!m\og&,Sq^&,FZ9CS%)PXSd!?Co=WFZ6$1qMl4.Cbp6VIDdEFdP3Z^
+%U^f"L_h@.Vl])=l`V^;"^K*=g-[2(b9Yo@-on*aDRmk1hlUW#887"u(5-0j'kftJtTH$epkfg:4):6AY0p?TkF]Udu6Zf@j:Mucd
+%;M]=`>fFF&Z:[.p>cSR*0Z,qlVm^os(eC/ZO?D5d(l[NG&(1IBXH1+LG@5%^PT,)*OkkXmN:Q[uW`s;]rK9PNB.VZSoUj?:bI`0D
+%"2eIG#&AX`.:3K+SSrE($YuM5\p%=#@OOICGFf)p3L)-j:EP,%nDS4OmIV%um)Sso_uWttFf9c<XQ]cr91S+(+Ed&Cb19FG!"r3`
+%FKQf2=*X_Qh`O]5S,/j3hc[Dpkqk"e<IKAl!j^RafO'Q9G&PBu5B56$=n`&!)4BbJs5`dT\U($k:PH#k)nRD`W>Z@Zii@$E2,UaL
+%iXR&+\"Be`?JM8u;@lMR@fm2lIRrlp%<<<PN>F5!W<5st(%7(e"$%H#@c;qrjpMd<MK;9JifP;QUGd_IpA.7MDl_WH6f^Lq&u?=*
+%*X6E.Qldogj)jJ`DE'.`$k0(Jotthm!I7HimN4:S-BLTcBPhTSgjIa?^<FTb):;uN)5W11f4tR,p[D6Sc.+cqXSC4a]Hro&=rK[M
+%5]]GfFsJo<(Hu[Q#r9Gr?T"#TL`8eO.`d,XgkL*-Z<Kj\.AF'O58kbl)E.Eq$UZ9%P#;1QiN&E099(=H^g_#%YnZF<'hbSA`=L5H
+%=i-'6eR^P<Ba$#B(TlW<DU.s$`79)rG/C7*W!4q\5t9r>:dfA71ol1K\LLd6P=9$t?QJ=l^uGXVc($</Y%Y,to3N#&G7$R(24kjf
+%NHDUH=JY'&+\jU0Z0Yegl4[k:'9OJ(Cr6deoooiL_,#UeH0kC:`on`C6[an""\!8RK^*m2?=kABi?5ZR5l9fr%;H]ICSQT+rn_.G
+%^sIB"^?k-Mjc_""c'[j+eQ"Nu+M]ar.a.m!aT??;D9RF;MN:I?-jfW]-&1hdUP3u9,MTXA*(J\;4WT!be$`e6)n$M>0kW@i8)jRQ
+%hpfsR6gX@Z6H;!+J![3Gp[km/2+SrTS#]]i&pOjS@jG1RR_F$Xl530!AiSjr1%#>bY;)0f(*SlnfMZ,VAn*TX1;+MZ9Le9*9R8PV
+%\"Fr&3p8pG#.H<Z8k67Z4.HY'V#u:LY[n]K*F(ab^,)RRBUVD2?>*?J2)Z*d&QIYb;^r&L-c634YA9,)M`+aeE-"Gj)'Z1Dm09Ep
+%lMt=e<L.q]GT/?e$5._2f[qJE>kLX\df+SiNYVm]28AD\cIg+H.LV[j]fkp!`2hX,W8,Gf<YCL^44:>:hKUU\6EeJ2/rq\fqrIl(
+%IH^@(]>?3X+l"Rr`)&8iBlt*p,-E?,Fs)GT:Q-4?@CRiP5hY)+&LB\'7)KS)*a.qq,5i<0,062IeJ>[C``<A%>dQ*2OfXR>3fHTs
+%gTF_aI][JeCY#=uf33lqrY1%7)?h.4%!h7CN'YLB5cHY#j:^iV.<Mae].,m+LQH^KKG(#'qRL-s43SGRna_,8)bB%`^jDY)FT(8@
+%0tXGGlE=/\b+aWY3]D)B-+cu/h+Jea^a=5AZIrDk[F/t"0gj6k8HbbTj&*uPeqVY+aX&6o2RdQj?.p,UDK?QFA2t[U6F&0FYu]L]
+%Wf#C[Yo90R61cki*XHS/@?3h=W>)q6E'6Trb%bT[TYVj;7aeDfP)+$S-Y>f`h#aWnlp-8&b=..VX@1>QJ[?P)@mC4*Mf=NQHh,1p
+%7cWCVdc@Z!+X`'YCNfjEA,_eUf8rPB?;mcfB*YJo=jI0BO\.HK<_W\:k+;(*f*']M,!E3E<+s\rKD7Y*JjCuq'Q3Y5@F`7SRb"Er
+%.lS:3ohO(@jeR4!Mr[>gMTI,U@jG?8eZlIP06YV0ik!CffELX?.moi/DXagM9$%O9]s3e7j`.HY'<:gHR=b*&Lur73,-7SS3(og3
+%(52gJTV<W>kqsU1dPp.U_Ed?FMlLpK:BNhkh&E@*ocrk<S)N=@Jpm$@M"f$3O,CU$XZX`I%]DE,"Bi*O=,_%7^YS76dF)_'>%rX<
+%=rTT`-YbNi[R,8ilkE)jG2nan/tP(j$]mhL0'kq.C>!34H\qu/1$<;5ZKjr$HUhARWDKu+Z3!^tE7=MCfRCjff#]1j.,Ogb2U<13
+%#;d<od0qmHKT;0OB(@<cOh0kh>uWa_fb?M?TCqkoMQ2YY`u3YA<H-*%Cd0/(L#Fq0%-Ksl<I)PuAr:mi1=Tde73/+>[2FrmLE^^h
+%1$<-1-n86%r_NpK8dKiMnr85S="?WW4@&ktL]^=?Ipj@=PF2uK\Y(0u5ZW%q,M-bN[G?Tf#Yf*i));>>Ai5H,]8hf#7;Bdljt\B(
+%>..;[!2'cYBkP^7G;^)&.^QNL%GC],8_a4.RA1c0F5[!WZ"dLM_IBKK.(gjmhiknXdnFJ;R,fVNH/-s<-)S'hD1LJNn+P"*.J38l
+%kcOV[3`*Os'R0<0mDu>"0EB'!U6f,0g,0S`?E_`;%]WprLkmMH2'(C:l4M2&BOaYNXK-=Md6*e+*I[7`*b''CYC,,[\9[blEDJN6
+%RJt]/HGFa%$[0/6*k`dF%bMF5266?-2Q)Q_+#i!jl*.gcb-9K'^TuN6+tatO6F#c+qB9>([?9#)E18X!j$r&Qri,!kFAGP9PA*4S
+%kRs(&6(mOKN#K!.hAB.La2+du*]>lTVhsMm"'P(HqZAHhH_\QP]Z#IU)VZCr>?op>?CaY##=uEao'r&kGOoDE&n\\A"E!D`/qSu>
+%*48,T$it]H-&dH"5JLcPkU-isq04gG;UdDG<E5]43!kS#^C1;.=.%\[?fquQV4/Bu6G*]7YBZBZ,Sa*;+[`B4RdmPo6PUX`<_"D&
+%N1_=KA:W*A/j?JL<eAV4>b@HYY-SVhmnZ@\2O$>X:nc_4d!Y7+!)OufW[pIGeK$D`,-YZFo*,Y%<V0u_dQdu"h11eh^Zb6^Uc"NE
+%8eYnaqbZE#S3mmWlQdH>(,N!me*6B^ckrd(6(j$,,+ru<F.\.XR]$\0'eSQ>794R,[W5C>4g`+:%*6M'UU+@D`R)WD5cYWi&QXC<
+%P=:D'EuN#67gTN*cr8XVl8o<o9^b5_9ZnUn)Hl[5'a+sr?R]QXYHOtQG2*tWUr0]"B/[)CFaspGY$/IdbUmdM?(3-*,>Sd5dW_NY
+%`![ns7dQ/?iG,M5j\SPDg32(D6[G1f@iiZ/Oo,fh=^7*.%b-%d9U6$j7_Yrl#deSd-Jli'%p,W"_cfT$hC*'Kd3_sclXp9o#$Y;G
+%g)$e2.ekp@A$I6d("bY4eU90.41nW2,<R7J6n%u!ccBJuF0&!8X%i3./Q?B=VUI-5[ZjTcJ34VujiB&thOJU_$dWXGj7@Wc>B@s:
+%2^4TGOI+/m#rr0AfT.201I65rm1-R]c;f#<23(<E\e:MR_,sdKO0%q1oSMs+YC>,qUWMj[&"<4NB0dd4\!D)6P"C!Z'ASJZ7$WFo
+%L/[AlVbK1gCVP>B>?4`O1@_WKec)pu%.?a4B+l/<;SGj^@^jNnH4E4i<CX*ZX7R_`2c=a2@XWP4K77@!qt@UE%qgQ\SWn3HrFqO7
+%=1G#^YSQ']N!OGV0#J8<UJr5t7^iuNi2j*L7KY3+Q414#&%jq[aCuZW47BQ::tqj''4_;/0",7!>+iblmpc30g?@:=NpC\<SQuQa
+%R<GC>p)V)T'=t2Z"h#1#m61(c)k?B&]&2pdSU:Kr_V$u/b?$XhZk!l[_P@FRgptfDB\/9M1\>F)O`_)!_^4<S\-B7E1fEd*D^K<K
+%<L$m\:VYS-A8)Lmerb6Nk+/cX'/-//H-p>"N'(Dbqr0Mj!M\fC4g3Oh]kK+&Cf)YJk!:BC8p7KL5+u$og*7j0gr+sm3GIf$DFLG[
+%WmK;hfj9'e\#nNEP^e,MrRYt:kHi2fT=t+!PLj0trO2.HmsXNn2g=`'s/d.+*a_)/o[ObMIsUjq++Nk1(O&ZY5(2tG]AGZPqHM!i
+%NrT.,h`Um2YDn&0adY4B?@VrE?bC[[g#k#;n($amrq,k2?bL]t?11!1A,kJ25QCAf?TnAWeP#i;#;:Pug#m$ok79fSd?!2?IJ:u6
+%YJ9lagqA48kG+Y6qr7CC5<AdRs7_^ikq3r6Pl9?,?QC/:E;[VGhSm+!hj(flhgOtjiU0Y?bO7PL;a!C'ZPj4je$FB4%hp;P8ler\
+%H`_&O-=*@gF:ldPe^aZ`iA@u&@et<"goN(&I'm@.PLn#pA$;s-R9\)8iRshC[iX.\A$\_]%J>)0h*FcroMb'j3Or-'j)c)8ae.'5
+%29,\8!N1hp#ocVaYDYE%bFs^Q"<VO->41e?Z@(hAb2[9/j-t8]IJ;"PcT_BVh)c^+nG_J.(Jiq6p#ZpuG$A_Omerb!YPpW0Nq75H
+%rVl=Oi@s!RIP/AbN4^b0ci<7bgrE0"Xi8+GB*3"MFZ4,ae9fNM@I;[89M^_I;7B$?5R,l0F^%D<Pd""bg_MZnCJh<5BAg,PY?gn1
+%NI(O3*hRlM6iXSYq!mkWht]@+J,[R=Mbiejo_ObI5C7Bd$8HoA(IY>hqsP&EoLr4t%MN4Loq)2X1W=8<VoK$<c[L*ih%)\op6Ntd
+%U]4SBVD!$13aUb75P"Z"V#S.\Gk'C8NaTZQLUtoIW^EL$43+aP6pRnX)LZK+=0FM/2U99u+s""qClZs#_*Ck`jq!_V9<;g,>B[@Y
+%L\20Z@$SabiQ+r5:V\$>hYgItWu[`WR]9k7N@]FE/lX6Y7\qUqV7P*f7gJ*",_>>Ne%$9Z<3lL0"`#S+'f3Hk?ns&iD2Y&im,g,o
+%;4[/$%sVT2:-_*G@F@k#*'un=ei8)2d67Ffk5HWVFdpL4Z:LPpHA0q+_Au@<DOg@H"GXrtW*p[r%-(1T<*2PIJPn9@D'&ht;IUH)
+%j<YFC,>#M-/L;&)W2K>9P7S&3;;9$3n!0/F)^uT%;AfRr)V*aWcE/MG#!a-E;)p)Rc0/>T@&ksrV`_C2)Q`$-d$G=u<^]>To#M_^
+%nOSS^OX"C;I#(f5.A]uE#h:b\F4k3W$m;s4W5dgR_22T[h)LhP*?15==$C!_K$sM4$<\o-KGppH,*L?5-cm:7?HZTgZ8)MKgh]t3
+%F((2aG9;+BmK\=TNuC<ppqLBeV1Q4c<;]idTi+QQh-]<g"MJHr"l`VPlrpCkN"0JbY$P6f#W>b`&#1Zl+BI5t73h(nfJN`<-aFJg
+%X'jIs,mV(C.@\Ci)kib`P>k8r:8s+24,2rO$j)6=d!fe9V%VlH93q6d?JCXEpD/>_<Lf+D)Ds@]]L*nXP7Hm(X#jK=6tsq%<cm)^
+%`Y2eG5gbd;0[D>u5)>U2K1VP@&g>jICjg/fTBiP#gs0p"2N)j%('_@[R'Z=Ng"j3-Lq*ic/ERuaBOfsD*=`Y6C9<q,1o:T5&boG5
+%VS(`>.M`1ml\]%i3m<E"39Z(eI7.SEgDsGs3=$[`6.ZJk2L04ZI@+r`H6:bLKD/NMgq(_?Z%H1u]fT/#5AiQ9ZZLp[Y1KB&qu_/f
+%$=)\:is6p<Pjfo.Fed%\EsNsW<Sa-9a=)X7"cX4lO![l+NG<fZ#XJXt]I?=lKo215"4`s*99&kOd<FG9e(0_+e_;tQIuQL7Dj&1t
+%D![XkG)"Y"G"g58RUN!=-'P;3S2&`bf##q;8%uJON63!(U'\h4Bp2)c8I/Q/(R*_$\4q(p5f0L1=(b`2M`'sX^VgUleZlm1]9)u7
+%M\s1=MY3EmW.;?tA'PO?_u0eo5%d'9CAFOgkLN<mqKt.Gf['#]iFKTIHa6*;K.F+k(MXp+X$R<7E+92OMX.Y+`:E"8<r+/-)f'[@
+%"aaGC!t_<X[imbqRpXT3D#O"^9q_U#r'KLq])J'cV'jTI07SSuA)ALVh:5$,hGI6B]_1mq,AsW`,jd[Y!6n`XZ*1k.l@%H0CDL]0
+%<TVloHh!o%CknDV[VJYMWEnr^nq3p$o6DI_4,&4R-\n!]bfOp<RJ1<@=.W$H9#MG(?K[XtoM`GCg;sk[hTfc/KC8J4o^.]<XtH&B
+%T?#c"d;GKP(N[m7qSq>s4UWT3P6KX+@D^$QfiV9bmqb*$?E%J7)*H<)UFK.^PFI?u"t0iXCdfd*ClFRs2*nHg1<hWg9f$TEj<Q&h
+%j#ENVQBR4SqbYdMXL.]<QrGgL79"-$V`66),.e_l&g"Ffd0l.=_P8IAYo1?WIba8B<0gp)/2muQnRNs[3AeXmPA*1P%<h8NXJkO'
+%]N>&EVL7S99Wc9jB=C140ptUuc,UCiAsR^c848"MB^t2q87KgNoI_+(\YbC,G)Kn<5gP;tPiQo$20*lLVUkAJ3bO:CK87,sl,?L4
+%]c^Kb:OJ"Fs1pc>1Xoh[\:_lBjGaOW,gR5b\?J/k_2]e^nj[7>jmIik3qk`;4^E@#VN8@b`6*X5ijB"C/&tq=qV/<qN;.Mdb`s9R
+%p1lmAm\uA^1\G_nZ8,'Q8p-*4OqH+8<nNH/UN9r#)OUfd"mlP<s2nNiH`O:uaho)D@RLgD78-*5jEM$(.'_cjk;^Xafo'hjQ'#q$
+%Lgdb0NfZZG_-GA/AWA<#@RIFA+aq!I8^`FiY_Sb2Upe?5HqHF.]!Xu5A4JHkPqDF#KTq1<AQtC8C2tr!@qsGZ)6%-<9c@1%\4,\Y
+%Gq`-OW1F3.6Qm21`W*;"OtC.$(0Urqn;&Z"j5AH'KtOp96(Vtk$nfS<`g*cPON\7afDS4/j`/W<hMHs[S#iYcG!1k#)K#AHX-Q-.
+%*ZZ;C?&.Hd+iV[noBRph26A%sZATCCDTeb6(2b]JnNgd@=#/5@fkMkCPpuO!;!*$DMq><jg94L0W.a4r8)iUjW6t8q$$U*Cqa/<3
+%-R>tX"N;b"Lc!`8XAJN$Y@;nUWXm9IOCW9LB8=Ga,P[cMFr&<>!X/*S1m`'_Me(F5^0P2\eC(V-%m^9]i9At'j/OKpgElQ+n_<AD
+%J#:rq1nqG-^97\:l/IqhV"P#UZnhk+!EuSjoF\SuXFAsX!N)[hbK8,;Yp%N4im(;V07uF[o9$)*+PYJuXdfi%-h@$^q7R6\l:6sU
+%2%&q`3n*s;&X-$:$4_Lj]Q]#,_01W64&sl!c#tet&J`+c(%>pnlkI?U\Il;-oP.PO0M-B=FCDt`JEknoJ@/m[;9f2c;$ZLFabWjB
+%ZP5>[$mq<u9K=UTN&+I%FQ-AhEZ2V"D&WP2T5"GeCig=f'u_sJ@8Nt5f4N4:q'cSqP&n7/g8i]50=+]%=m+RpJ.X=E?BPH'\L`PC
+%^^c]N/bRd[n$>hG]?@79EV%_jd,DO,"U-k\F1uX<eGs+2cU+4.]RFl[T.rd#nOB,I&/Q?[NK@:DToNrrrDT`76dt\NY$5"%&nUZC
+%Cmu,$3uIP=LM;"/>fgo4bjOumZG&,=NF^]#FE_]"3f9of&9,6L74^K\*;m.W&1u(nPOq4842LLH:nWGU5O'Io8>SS69-$WF$n.?W
+%o?S@%ePteS)LKRC_&!)7@oZp!qW6NtVcnJ&,cl=I]G_3Ak+<G\Uaa:"MH->==cuD+MY`PAf+pVlOLBasW<0grQ(pA&66`>1"g9=[
+%cMW3uaA\+(iR4(?/+"Ic4el(>$S^3VI&0PYqstb.^1BtGT@jX=R$n97Zifa0LZRmJRR[u`pZE+^kE(',/c`lKTJg,2'"(Rd]_>5H
+%7IM\3V`%rI=6"lAn&?p&h9i82U$cud_T'O6mLpQ,.L*ND@B?5cOB#<C_Tr!">\0L1@&p_KT1:4;_r[u+SK?s@P^mip(Jf\Bl`4[=
+%@/&nWB@l')ND&<kC).S*5J:t>k>*U\Oo28&`45h]eYR+f?_:">>cd&J1:,`CD]*\i_tGr6ise"uHVTd8J#.b`XF*/-2]YKQ.^NLg
+%;ZHn[EN^2nJYW9lhY7a9fuAH$gQ3c:![V]^@Ek%ojn@gC_L45q'U%%U\HsFM2d&pTDEID]B5UrJb'dT4oIEeM*=FBo\fDnD!IJhA
+%XE<iQ33Bj]G)WOSnAV*!8u/6Y$-=:5IGfpWTY-^u1\9[e]4`M@m'\(;<B-Lb(/8Gf9(QTLLLLTmPJb=fV3&PX_HZKHF5Q0<6^E,+
+%O]G6U_F@]Hpru93\baQ?>+,<s)en722B-?R"u[E7i<q9>eqHTGCts_KfW=$8Ek&?E(F3IrZkmsrZcO$5ibZC`>fLCC0*K=9$PqOX
+%_M;7OONhoO.$E\%/]c%f6actES,9Xe/=WEDJ1h^ViI]0f:?2K+D!pG;hcr.=$`p\FZ4#6i3P>e'FQ"DsaO''G06#>$H7p\pKqlA4
+%9:K/#&5LFK?Z;s%@)9]TXiS?\=`"1q"j+=]="F@'(>N"gY:U0gJ706[P6E2c67`L_k+S/r9tL\cCe1uLjOl5*.ibo>jNbT:%8XH"
+%9cNY@"f338G7J"tLqXVjg9?&W/@H]*:ZU:MXO%&eBE[A,(SL4uk-/[$>=`;.kcir5>Ynpj:KKc.JS0qSqBkcQ/$m_E*?L0pMUIac
+%LQ)1qY81ZjRK\`)+"J4kP[80UYf'?";#5LB,e,@jh7UJ<a*%+mj)9hF<up&F6,c'jOol*531Vq$S@^GuL-W/8htt9,J65]IklQg3
+%\hD9^nFZs,1JD$F-_MiIT*n3Rq*psJDBCaVas8"mG5I@XQ,n=B06K`<YA?bSAtP*:s#8b!h#T;#Q`N]>&R+3#Z24a@+TDU#1j;8U
+%CPi&h>=($2(O,I'pkBT#=!1"u\?TI>jiFkg#X=kJd`H)mPc*-n5j8iZQCLbJXk2a$fR/L/..u8S^2bgc]\t2h<=*.BXt'Prd*3Ng
+%]m?6>::)f),V84Vcdpe/$m'CMT#`VB$ZW5?Bp<:/4.U<02^?F!Q\gHLHhr(EqHQ<kZY=-q%$IYs6hFJP841#$Gn^'VHd'g#-m\.(
+%fhL=3ZA!!!5iMg.0u$g#0tD=K9a04p''mZ$LoA:8"Ik@cS0a^e2'aN+GV0Q7aIC6r@WatS;nLS#=]ak%\<$S87D,^1->JUCRiJ-[
+%Ib\P]cAU+%d6igDUZeoT&Pj`XF=;"?0\LWrD=V_WFr%;`7J4Z''Pb9>A'UTedG8*aaF9K/kb+'hG1ICJX1S_m9qL??[QAf3/*AQ(
+%Q)eXUNm1dr+ASbQ>is!:C)eIZ^E\7b#npk_PZH*?dp>@Y=1>HlU'+g:ErX:kqrAd9Xii.1k_=Tg;*bW<TtSIN+M!atG#.8iK`I5(
+%o#U)2iklp5lA!pn]`8lc3q/S-R=*H\Wkej]o1&Gc'^8AE03Tu$*kYB28FfJ8YUB^/2O;7dV@"fHBdeVYE?,qLj'3RON;UefUoh:_
+%0;fgY%;D4j>Xkkt5IuTG")m&9IZNcc")&nkUnrS_6H3P^V=UZ;i7\D1KG<$kM><Fm<:(W(VUn9I%3q9URR_K(oT9Cf;n;`V`h4MH
+%L(%h=LZgu(H%kSG?#4^5hFJf9:*=DS`*2DMJ>sPVZP#OTVu\HiQQuAc]WkjI'@E7J^=30'i!Pa<$]JoX0sYC6Sre@$^6g)@L-q8&
+%GHp&a)?%/-K-e#r>j[&\q&lTA5o3CZ,Z)Y9M-b![!nYdR3^cOj+u_P@_b[Qr]bFd4[oeh#&G'?dBI!hN7H\O"\rHY();r6A`K#B*
+%1f+:RL&Ih=O(co&H@jteX4,mp5bG]+dYM0l,cNaTrSir_(a5f4IsE"1/Y:pna!,g"NePmS,pc"@KR!CR)cfXZ]i55'0W0UVYgR^j
+%!Q[al..I`N43cYF0?OS2lI5=;\rZ5*2/+lE>@0cRQM0Ru)9U)AQ&@dn=kQ:'NjGF#nlB>L]M@s2)nWltXpj#%F4aRVC%r`+SCIIa
+%(],dVZ$O=EXt%1^hEe:Z*Y=4YRZj69k\,X:e/YC8?W*IYHI9p[4p6*(8XS3LVmoK]o,J%1bN,dt)mT"bD=%#\8Q).m:HlbXKCdN_
+%aOri,<DW80><eVa>cG^B>L"+Pp8StZjD,mDd?Jo5SSFDBqr)B4"alHuW0\Y3)eg!khoL85NVXHqTpC`3m$'T+_'LF<U_QAJ9P3L)
+%'W5$sH)#eD#5%n4+=bC(>aSso^_i.t_o6g7@o1J%h:6B/[s5ngDN"07g/<BV(--5JS_tWJF0ir)Ledj'nK>p7/+n9V>B*knma+JT
+%6!%QGj57mK)ng6AMn:t+iW,DX:<euHW%KB$TL+GDTtlp3XZAbP8ld`U2V_#8=WeAl[_,_4(pfue,)IH%m(4lj%%.e;Tk5C@'Fk`.
+%G]=u*>n3kNd6Co?cc8'IFL,&h-P_ec9[JqN5)EN9$L3)q7];Fo1g[kQ3&AAP+uI]h]t6X/#'6*q%m,ZVe_W<>$T_YMa*s4b@-8kM
+%/PrY[f:&k@@_jOpm^(dsoR1;.2=,k%i8-Jh)nJlo`%1aO9db[TQeI;W4c9]S,Pu;\=$p6JaS@GAYbUM:Q*jkP$=RtROu^6Li!JO`
+%Ks8];[Pn2'e_G[4[R;!87)n;t9Z$s/Bh-u:bB=32)L(sJ?"Y0$h;,`'o0$![#Z8B[O-Hl:cEF"q`f-9n?dRW#Zg3]h@--Xan#%=@
+%(b?o8$f+u8%d&>\RiN$?_r*Hi+P@=BAA5lo0CEf851$,3?Z-Nk^e4^0A[lqF%H\EC^6i@k@rj`=9,Md%`W6f)Mb`#FGp0qUZCc'A
+%3rs6&iNj?i>fZ4!5i0s!hS+?[$Tq](s#)"f/]d@G(U/7\*iRX_CbKZ7aM/?FYs#*U=FA!QSq,RC$.WkXoBWEB!4d6!kB5+[<_\0_
+%Xa@&tPZ><"<q:5g/?j-?<;4muo9s)0'Tu)&#k9beo?PZ4o*SQHXQ+mmYkDS<i_;:7pZ?=_mh*3;"8)la*a>B&r&,MM6]j\+O!eFp
+%P(]>%i^RHa]L>?5Dbsu,)a3RPf>(tYg3"%BIJ!U][Vb'=\;g)CjuSV5<7^P]O!tjg4:L(U-j.<e$mFn%'TphV.+ai0ge'+@34_0g
+%+7DD300i!*5[^2efMsf^=o::PDrYY3OQJ;:'PEgJa4V"!M,(r`XFuO#EU"M*\N8kuQL-#!i6p&r+Rm([;S,Xh=iMuQFfQa,(7iKm
+%2nDIi5jXO252XFUo8q)cAKK.E*.a)9\7+M-P38h?>oJfLT&2nJ<`Fin$aUcq\tni%gNLUE!V!YeKpQ80(-o)oNmWW<pd#/B?erdt
+%=,'h6A`m8;6*V&4ck.^\!9f(uWS7.KT]Su/aG-XI6dW"<DmfX(dekVXas.H+ZJh8FX#j`RY4(E;H06m_#HDA,]5]/'cj1%jlKh<^
+%OpJ0gA#ob!UoAkZ)T]oU05)`!pBf;tj:Ek_gek2!4elgm9)q%bU3"Ge^(Mi\2mM6^b=N/h23u1B7XH-1)@9K9Q#e8k\JB2u[^D=n
+%-pBNj5irtpOedYn$imX(>7n'JnZc^PD-=C'duE]+Bi7?(hPFZ93eqa7gC6!pgS&\gKSfS?jJb\i_le2i8Kp)#Vqk,g'*3tunk_]g
+%*he>uI.t'roQW7FaU5XI!F44jKA.uTHsV1U5n!_Y;I(ZGNmKNtG%&`[G[p#04Z09)[?\0Jo,AQqAR1%9@gK0olhe1e;gX[^=L",Z
+%$*?1m%-[o2TJ_8K.e=.8o&'CtQ)@f'gkNTsUQE0HXXB4(;rM?cf(7[pGL>s=*U8)[U=OXLP@H\gmG\VZo@KRn]@_T06MPH6[^SN[
+%h?oVX7KU8?[@65n^9)%T'm!;+2K2g,Q"W*opH$1(3#Jgej.+po?BnX&Q1tKrA?3G,cS\KT[Mfo&cd.u\W^hd\e$4+ZM;2Mj^P]9`
+%'2nl/**)?udPL)-Ca'm-q>cqoh2C#Ih]jo;(Y43#e(9`;R$$Q<5!2rDBmQC\hEYt8<7?9`8c92&XUmmV29DG(E0O?eV:`KdgOd'N
+%L>&L>OrT@(E?f*M!l,;Q\JEtp(8CNN,joU(@:W>64CQ/rPaV>e)hC=gKR#-``u-&1PdOuTmkItt:6C0s$tQo%Ho8d[D;53?!5:c5
+%H@]aQE$<8+G.cr[3)(#OC-g#&2F<ED_%DH'T:gpa,_W&JX&($gmNZ,K;3S[,/^pg1klbP0\;TYna<=.ILXqIA6nhZrRhb6Kf/sL&
+%R*IC%Ks,\/&KR[D;EH7=:LQt>eTUcA*Xk+4&'S[KHZN8J#bm7Sf[oN-QGKn52];.tjYRi_eqtTBfk.NBi`q8f]-&*]1d[Q^A3J@m
+%9iA1KI:IB+jrhj$]S)O,o!tsmA%Thlr3o0lG,1eO,'HYR7kN$%c4`/h`!dPc7RMK@Nm\Y$d@XV8eOu=k)R$^#90*dZK^Rollo<Aj
+%p3>p'AlJ=#n`s7P0AcX%`>:a#;=fs@2u\tn]HU:31>I8i*<FLm%I::U.-4IAW+!\U-!&L=.9?'0jYIPl<m^^T`mrJ:aW.?)>clD\
+%bG.V]n?>^n)<G(^K)oc40c-$ipI6I=Y,9E<l6f<b'fCB?=dbR4`gj.P6KU=deZ<snd':,.3lAkk0Mt5n@YS&CK1bGl9-Ze1O?Bus
+%>_G3Kr-UUa,JR(je7#Tl;(r3r[/b'<R_-q9SI+e$0RB+<Zm@Jfm5Bak%%KB"#&'/fQ6`u=5,Z]iX9u]aNJVWV#n.`aI7q\>@Z;NI
+%Rbc#lc%:I)#LMW[a`jl"Ca'f__Sg8-@r=#?Dpj>="+YD][;Jo..@n-,3Z0aT5"h]>:oYq[R*M]@I0lG15ZIklK8g69R)f?'"Nnkg
+%p!!c_=LZ$e0IBf*8**LInM!EN)Q-60,98G60#EWfITgb!Tn60/"Wi[t?D<n!?qlXB?@CES77Ck_VZ;PT"\1i58c3!NXpm_epL3/h
+%WU.X<"sq%h(56A5Su1"825A@o*lU.[6;8*4/a!E[hgFmNI]=nM;?>ATT-%b"Ec;%GrQZ+[P%9b?*pT)^/EW%"#Z7n-7DUH.>@dIL
+%A7A/f(R#<t8:p,@f1&C7h&CO8(rE8e]2@Gh&p*lH+b*i;eInhdBek3l_30d/DgFA]@5I32cA\3ZY(ZNPQh3=d7&7Z-7butgpUtQ`
+%%Os7I.*8#G3[;?moU[4f@_WF_f3qZZ/qD=WX7auK^UK:lC\pTp#VL$f#ul`s/V$o5b*N<XV%Ap1!`R-k&N-q)Uk6QWDo<mLEXd;L
+%WMYT^C#B#T?e\Z7i_hCmH/#"IZ?3d9"FRPZ_r%Q\B%k:&ge2Q9Ml7i6po3K8<'MU^9!)0j_>(>6pWj@CNrClnH*L\KXg5RadmPKc
+%X]/$eBItEI)PBP!0u&?ERtkfk4d_[81WCI4qdql@-AMiX6?U-(q(P[ZAsD%Y<]34PG_p<+fH%F-L_Nege[Q-omn`8tFma(4WdrUh
+%gqUeMkVLQ67T_#QQ?59aQ6dC:TWW,8J(\as%%iB6YOYm0p+n#P3g[j+,k4c,^`M46cuCSdj,6p%g[pCSh6R(jg.OqG0ZVbqbJ<OD
+%dptl2LAg_o013Q>^Nh1o+$6fB0HQ9R`GgjpPf#:U(I/I+=Z+7>IAbV'+8k?U^$*<Ts!l`WLS7rf9fMJc"@gPVXr^eb-?&^re$D8!
+%k4?Co\'<=pp4'i(mgid=q9Fo==0FhOVYaT_H/>(4Hf',=aieUPo&fUXInpO'kO3odpMk9Soq/mCrFB1f9b7-odoSb]nUpSN21KR=
+%i4EpAHMQP*lXr-Y<Xd<85.u2kl!NHOP1X+0^VN$]MdcVA[m0]A:\::=h0U6VHM-jsSVPNTs2g0pD1]oF0;S;s2-k_$H_8!!n_<sX
+%[B..7aj1Ior+J-?jLC-*5Q9no,&JK"-bU<F),PB-:*^"'R9Hl6p[@,3p>XJCf[W4c=8PY(:]**MGAR"\NrKJBdr4G,J*3"STD\Cg
+%4I0`3p<g?urR_&Ks!Rj8htfB`lg+JRJ,=$ZXag*&q>,R+f>#%bqs2#efD`IelaQkgGJ<ShHqciun%UsT?iQRDlPk?N>CZMh?dDOH
+%NV>[8hB.gYnE]kK^\2#^r7OkpnGE7-fC<)6IJE*rJ+`Anht\1>l>QU:bCB:OrXWrHS)=&\I]NJ(J+-86r."Nh++4U5ocO4mRt(!q
+%J,)lirce@J?i=o.a+*^ts5K[LPLk<R)o(s9qWeZ1rmuYi0E:Sb^Z`H'TDGs>^]+iEia;[LJ,]2WNhnK1oRH^Ms6p!\O8nkJYPo.5
+%`j`_XZ[_u#s6Ronr(hh(5P8g\I.Z=pq>^C0s60?pq5aOpj)t=ps82ilB4(Z+fC2_Rp>1;r&,s'<j+%(+DuE:X"GYD(p\mDNhE+9/
+%.U<kjlHVP*k1k$jF(V9h`u+u>MB!Ad3M;'kP;>Fr,mPAAZ,th;-0Isa,_J?R&1"8X+AjCf8<tAh+d-mp1>T_DVR?.7)B."EkMA8s
+%%rKn,pY'Ddpoa9Rn+6/g2/Z76?amrQju<(Mf4nk+);23morGgmTDf/spMAO6I0TF^@fECrqAn<G<l6P<\i+lU]7'c2or11T(B7a?
+%>3df3)VVsg]Dgoqci$Z;j"J@jA@?>SigDptr65nE`6Z*m$6*]5.Pu%j\D58QhYH'$e0=ma"nahM;kE\t1hp.'E1XQ<k-n.]Z59X;
+%qQp+oF77\]=6&,Oja$;Zs2u(hlkuQd#tn"ZYE_hc;q]=BAGbiqqBY4t1O<7#;MOHHJ+fnmX]%.Hg%T^jp<Pu'<CZ5qPtSdcH^.F3
+%Cq[i2dU(/`rdXeC++EXErP^<lX[Y`DP4^VLV`/I!Y@N3sT(od-rqrramo<E!)X5f#$ND94p3N!9mFsKNQe-QZgHWIJi\UW.F'_k\
+%B'gLJoXM'nQ]gfMp[6V4EksjZqUZP@GdH=<Djl8ZeZ)QKS=)',B_AqH*BC&sXh6^9ZYpS,]?$UocE#)lIn<1\Th<o"kqg?RWqTQZ
+%kC3G3aU4m3a"i/DCmM,il;b)kZ1d3A?G:O4d$DXL2qi%Ydd'm*+6-p^eB6kBWgM1Cr3D;d2CtDdSc2*Y7pdk*W(#1(IYoNE\6^dj
+%*FADTMP"3i4RS,uLC`iW4fdIeWHuYC.l?R^eZsM8%G#0M<iqQl_+n:EWh[9jGkU.]6XS+&=Zsa,mk:MAp$CSL=fHdtf[Elt3jgJ"
+%WP0jl.Z@JVm+U:M(D!^=db[diHa,I27h*S?REl=NTlP8pep8^Iq7QXH%6r[jc+SIAc]UROT25GLXlIJoj8(UTT+U^3nN%PI/*/e/
+%<Z&77o_mS#h!7I2O)'p6/2,N<20%cC+g"B70gG+V;R9qHj&10P?n>>ubbh]WJp6&IEW*h7jHWZe)"QXuR3OI[k3$$rQ#"bnX,32+
+%n!1q3]o[m8=uWlrJY\q:[U\JQS3<TXhAJ^6ZXNTZ]cXPRX#=\4V;P@a2i`8?\6SUNV7TH)\7jI?N;ONUcW06eI/L4W7J"0ccE+_2
+%i*D]DIF9_CY#cMMq.Rn0)?&m_B7L_73+1J,8R5!Op&"'GQQ3ON]^"@A/Q4H38c&8=%MKU1><&l\V%c'Ll*=NS?*J_5O=GPS??5Ph
+%PP:^W^L,AQH%T(p_4]ISQd$Dq,0r0'>-(.S:]FnAaq*5EH/)V>au:,hY&XL>NgVJ_`^PHYh'OfOFRdje2%&F7pj`08j<*i6T=8h'
+%2_2m+:48!s\C9G)2hKAeH#2#mnk$U1SN2#qVk;6ReLJmOa?(!F9(ZH&j2d?'9*Q[)"BVF^?U5Fh>hV'5:!u0(7cV<,/RPb.poHT=
+%a*nu8ZqC%!^@1^ij4i^>9%@_7CccS(Q/K":Sldp&WA'$@p\f(,WmBikA8qLr;c,n4D8>=i0&=0dm-?+&;S9+/n22S2#Of7th1E(l
+%F%4"?HHfR+B(`GY?*!%#ec!Z5UNT\[rgt:Hp>Gr#,ASVOcTlDZcJ<mtkSZAs[XCt0iO>/RGG"TnL5i7s%t2N%_,J\XHfSPQH7_2q
+%N7Ifl%t$++6/oaX@G%%/n6,K]YNqr2r:Y$Kae*GLB(LnZ*T%/:'DH%PJ,ZX68p!,?hfB[TlM3S9qNjqSX?!mF_Rt6aVp@.45<35t
+%nu[95Cg&rsDKm<%h\*D/IsgLWaG7IaABL4EY\)ZS]mXdRpa.LUD"Ve81NMrT>1G_6]3_R!@,[E(8+pkgebS#T2/2s^oW&.j#$mY5
+%X+%hmD]\pn@[$"(HbIZo4"nB^jZYZ5Gte.Kla3.qiS_fkqcAc8%*[TSm?.BQkfr<0*-CL0d/LR9<t9X:0\WeT8L\\$YO;@f62W)@
+%=MFP%`RB1#ogoN)is%,Bcb*u)p-0f%Xu:I@aZEU'kB>'`)qpec>C?4jq>9fegHVk/)`9N[IXfecj&^/h%7YSQK)b#0/^i*d\jgd,
+%]\R)^!F.L&D]N%DWh,[&MtR)An9'%W0Q6<KgEA>e#!H_qq)`fHn!I-'P1./km?!ocj.51A`5HtufsE?/mp`V.gp<ZC3e=:lG2oR6
+%r3"g:V`)k7'D@r?qg<_R>#*A^*E-]B53ia,lJ`.q[mF4Z@UGAf]DTGZqQM'nNN'psYI0sSj-[$>a#6\,X6--SK2s!##2YX$e'l3^
+%rl8CGp/L%`ra)<gH6k4$_$`/m\FCq_Ym6Whb]!BiWl"4CW)r*C>l.siXR$;Ll,jE=qc!"/f+6)@*9R.1k6q8P3_dE_6AbH*1oftt
+%*T-)QnX`AaW5Veq;,MW"q@e(jGND#uIXKnj!uk.q.6D"VWI*!'^5-s#k;<'qK`0<I7;KAGP>O?gJLUi3/b\T;kBD=+!mUGR^X$CP
+%r3DfiFtO`!JM/N4nuL6U],k500roRZ)a<_fPqWi0m34DlGOF+Z>e&u3DY)89F0O*U?9c*82bjKFgK?V`5KJhrDP,Uk@U)ikhZX1o
+%ou!5,Q,<rUVb2r+DZ'LteLI]4p$CJ0Gh>7'%LcrraR8K<YK!7&iO#5JoWHt2kP'H\k5A[J-pQuIW5G9ZpFY[mW:,&A<o\qbrOAuo
+%?dbBc+5!c<mEijtmJTU`j+,FcZu]8h(h-[ll!)Hg96aP+h=LM.)c?Xc=G;n'dGi9]F(X1.9X3^ZjO\;&[TW8IE?AdMlonrJs)sOr
+%E%>__hTO9`Y9-l:%>4AnqIA+u^QnSsgcK.m0'l^ffI3jbEJK=k=-Hk2]_kfVgTK5SbJu3*YLi&%FR5s?/P:_>>B.SBI/;EVc[-I`
+%KT\J7mCelhM8AZ$2braBXiUj:.W]!_D9=ZhCXq/4manj<aln-Lf<T5tN12N,>?srL^!U9)ri=EFa&WYbl*Oj<`:_/g,eY^q>F#\3
+%<3=d3n#g]Jjb#'R2(ZiE[dH4n:f\iGBT;jOa%W'Y\4ueGa]`u6f?fNGr4%%afpp$ncN!&!mA-(Ss8Ipb<FW?`D3Y]Qn%uf8rHOTM
+%1AZqJ4Wq(9ZnFUEZ,?(Q;oeO/(Rc1ZAM*l[-G4-=@!^GJFbVO+Hi@pB]5AWr4hQ0DjFEN$hW3NR]mY&NeRIK`4i^55h4m`8F`0/*
+%4+?J55qO=nJb3[6?Gc0jGK#Fr*jt">Mhs+!I:DU5ZEZ@B"Qk9ZQ8al-)-%b1J`j%DO.JCPE:^S6`XA%n%A,ao<*&+b&k`bm&<+r.
+%]`se^PTiiBY<$VWU#Y#jZ"@[;=KK[/FYnjXfDQ)h(Nd\-'e@jYjL"/]ZDti'^s0lI5F=LG:]7L1$[5`nr(c[^UFZ2,O<gUS\5`be
+%`P:d5nPo[D>tr^!MkkR4,-Z5q".Y,4(.5"GRa`^6MtDC^c6F]4*8D_nF_30gH7S0uTk3&s1p-S,eV>ct9oHK@IbHTVU;&XWYj&NZ
+%ir6K,5&,it\k&TI;eJlHoR=G!A7tQ7@+(uK<Pj_oo-HWVH>n$,a)*")NnO>_eVC=r?ZtJf_G%JUb$&gV%>cV4(Ni)$nV%lE-dJ/=
+%Ufk>rp0uS=;3T&pBrELYn+Gd<G9:)CrF'eN&*Bl`l],3Xf?E$NHY1dI?`HiUVL$;U6d'gRK9bX_G/i#Tbn?$ZSE<2:9HD\f=V912
+%CqK0ZkOQote`1PR>#*djlt6$qbMQ'p`arA&;EjlqiD4f!.i3%aEpBHO)%#'.Qg,$Mrm=-AHe#Hh*khYX9hqqJNA_kr3tp3)V&^4o
+%'A@j0O*B,u/aGtdWRlIK`:86pC%6Je.eK4DGi!Bo:23S]"uF)\SPp/F$#[ce#HgS3Mf38H^?b(`KiqA@DTflV7s0;7ET^G4cmNVC
+%SC[kte>tH@%5,n,G>G92E*qu!&XtGP(;%.jH7_fJqlW*,T*m.]/a"jljhT82gK-oKR+*%`lJ(-a4s&.RDOi,&Vm!!>E+Aq7pCc?u
+%CV/l=Rdk;9?I4WPTDIqd:4$qtbCgdUCU#c"8+^_kGW>5*qmkIBSN=JtrSfgZ/R6!\`-!X-mA#RqP2Gro)>1.ZV`"r6%NjGDjY<0k
+%n"*cCS7^[AX)o78]Q]RXPHaVq^-$H3f$2C9NugE&jQ'mDE:0@tC/D0g44D2fQS6.'n6,5.Yg;0U=Xs-r&"iTj:FT2Va7/%Nl6g\5
+%?uraI4:M/b[r:-9*R7%(%P5b_mXO+FdpUh.A!+1\rhT]I-hR>po6hG)6e;jmDaWZOhdXCbiEanGG+'/#Y!//a`l"Zla1Ntg^TSG(
+%>GY*GnCbWcNo"dUlLE\7Fre17QLDu!Bf*PrYEh=lr:!IHik#DB<f/1e(RCh7(CeK2Y=?dJmJ@;2s5DB8H[`Pt'6cslSSORph2\::
+%qIUq4mj>lh2_=Qkps0:N.u!5>fBr/72Ct:[IJW;!?``.rkK'VQG>d<7?5L)#5i]IEa"]BI%W,W%Ib(Y0.6e3?n_34PqtKI1GPKgi
+%o2fiV)/dPtn6J#f?`?8/qV2s@S&@Au.L\o)>(#/@FoCUUlSn:fbK9XQa;)&u:-U&1-8/UdZ[_fZd9"$<HM4gnIb*Od_1&3mjI.h"
+%PEhcbl4JLe=(]h%+)X8'O8N=n:TWn!N0B,$(9HE#H?Rp"d8q'!2IlWpqiB#I^K8^W4`d(q_u&IgHhM:N-n>cInP7DALTWj&Mu6q+
+%c[7g`hk\SArp\C!c*KLMFi-hH2OmGrr1<,`F7.sF]8iJtG4jq)&"?(OIBU#Fq<c0!orrgNpMX<MG5Ha6h/h>K`iTnlQUM.^4o4]@
+%F6-['G&!$#]8H@[r9,fd$feCj]4]WN^8obV097K!$@\E/`clLi8)I<maQaih3QM*Blh8`fSYHG-V$I$Hn%*^`h4U]V+`6/[A%u%b
+%k$7[n@cT'F:6WEl[JEA\on//`7h1RHc3sCH8pqcIS.25CL$s>uq1h$ar5)rH>re8GIbZj04"?:pJ)])F*4`P.>W]<%AFAiioYB!a
+%lbacKgblQ.\Gn%G0kJhU?gYaK*a:e)IV@*+oj4rmi\.fl`Ei5`IP\H;7<P3mC;Y%,NrE3fn\KpmbD%n\:Sm],ZaQBOLiN#3fA1M[
+%Q]9)U_Sb8/]g(1qk#Zi]K58Lccg+Y6&)[%P^#@.Yru*Q&J*k17AReoA7Et0CNCPPWH0WC&h",T)?Tbo:adC9T3)JQ\,8P4tn_,YM
+%)t.)n\SqGZ+\dk@3YdS&lT8b>pD8=iEH_*1W<8WU:?YTR81a"O[="mO?g^!ur>5::#C!>B5.G2"Zp*rF9H>9b2'9MBlhBR[4R(U@
+%mbPBtik*I-:@6NC<1Y/M[i4o;E93*%0&1i;\(qQQ_FJcd=>H^kdkVHO3PSap`PC0-^--N1lKt58\t&YAD?N&hh&ASN1TGdkg7o50
+%L!$e@3r=hP#C\dZou?C2p[18eh_<,sE;0'cWu'*RpjVt7cf^>Sf=FSZ]T?gSl](J;qG1>$B'\<k5Fa]YqX"#N=)Qg)Hgee'S<Rs:
+%aa%jocHY9!592hupR=lmQHpH']61O@q2SE&<2OC(@?]h+rF5H2Y;U7r2V:mD4"jjKR!`2LE:3(l+2?_-c),V6Qd)!\G"Bq[<Sr5;
+%Y``)F/mGY^f=lllNYjp.b1pR/ens3LH-=d@gCg]l>ISG*\:3!!3KqGk)pk^0HDOMXkGRU.hrg7Q<OQ.d.d<?a#7Vb4B'd%t.B[Z#
+%a,CopYZo:SQ-,s=r<5MM$5H8c;ndX5MQ*`c(!;jn?./[I#UK5$]c`oRFPEZ(9a\/1jWkNu85k)D<DpljWp&.Ljo#6lZMsUumT'<3
+%DrZ(\+@K;9fdIW+Nh,D]9l_Z4Z;Zt]gIR"#8ks0NZ@2V9D4;muQZ&ALXCGnRqe[lLUP)]IbUg[C5FhQSa`3cLOQ)MK3JEm$%bX'?
+%Ls*5TUrS%rG>]dhH5mZCDAR:5,S5O2Gi21+Q33=[j;j#s*%CHNH"2K)ChC7t/<P2Z_La0^!u"c:FW/"fV#c&\CGu8EO/oNZ,EhcK
+%o4AT\nsD/U[>5R8!NHPOJ43LtCaK;34:qTpKE@%>)ZFb/iD"?KJ-%r.$RlZa?](TU7D?ti)F!4B&Af7Ep-[+Ei)K1SM:+<siJV![
+%KH$jlY2M.p(_]`!"TYD)ch/#'K]lLITh^k'XB0jAM#]XoTZcX])TCJ>9)tsC3LZZ:+-N8B(:k"#Af3VY/;^DZ+5,sH2.2X$]H*\Q
+%#d\ZAEB[P+AD6[DJ\s"43S63b#p]VM#*DBJmii2ek_IqPJO%L+)B>=?=Ga9#!F]Dp>"_t"JUr?-*eHd-e4F:Im%?StUt-So=AUpI
+%6scC:IXoS]1RTpc(R?Bj;UZ*6QO1CRZe\/&'"s3?)GGp^H(jXd&NBjDNMB&L\fr]QM49T?:e]He16p:j.TZ$i.JF*^MaK$e\fJF7
+%T`gDD&m$M<d=@Hk0`$<n68qji&of%uUZdHR;iu/L]ZU<VP&)QuE^BfeM/CmGI(#.jn:90.&QLl$^*G`\bOh1E72XsUOpk4VYX7%_
+%i@Tos&"ram*+l&]((L1?=O)=1l\*;PMb0=R`E<8:5T\<:"/Vb;XLg[@-B>"bGU&&-a&*%LE]?DdH';![=t$]i9H2WA5kF'Zj0nHd
+%"+:SSC_H?$Ja>r^%TqoD#7<9)M+hLQ4S3?]UI5%!_T8[og?6jOQg'IY5Sc[7?*b1k(f2#X771Dg7]Sr<ZLO:_$os`'l*6--3%7qf
+%hdT%3Y\>9.Z$hp$Z&-jI33c.T-P)YJf4?uF,'W#[M(B@VC<]\T(@l=C&k)$neHKXK&pd1t4<nHdi(#&T&L\DnW<b"U63]?H4#gRE
+%-eKcl;37bKZRMh)"'64#D^[L\TZp!4/mqP?rh<F-?sF?L0.p6/f-(J@0R&PS`tokgH6X:qkGZJ8CA!Ft$^m,/DQf^WR[tQZ+8QmH
+%;Y\HN`?au88E=S@3]%t!(3VX63jLn\f`@*O<`$8B();K!F:W`-XV%Hp4miZ8RUq?P$h1Q,UpFGhWr//:?!/'X3"+U\gEi^<E\\sZ
+%6,*[q:14Um4$4jgd=M;<0RNsJ!eQK`2'(BiphEG[IgVuFN<2Ct%dIe_9j$%i[f?t3dU36M2kn;K?/coP1>\OK([f&*FRmJJ,K534
+%W%f0U@p$Ziet@Pq(%CmX4m*E$_iOEmrV)G%3E@i[qub=-r9J8CpPEEOl_CW'%]+OOYt6Cg[)^u`Q`+-N0qYDsZ1VT2Lt<V+\B^l<
+%MI(GG:@FT#2Cn6shSbIFf6m4-OfRWS"V^2dqR4IF[+DC9N?@JC=G&?gRm,[B`HmR0nsK+)BQ1-h_+G6MCA#k)'oW%6@m!Vj;_p6'
+%oV98?UR:U%/ZZm#00Op_iK"S8EKQ"#dpfS6O6FF+7F'^^2J\u)@W1BD*lQ\%&_M3Ek2:u8b!'oXr@Lo\ZWR\*I_J`Bceth]HI7`e
+%\p=Sa\/!2#oT6S1X([=>/`!6^HJdUpgobXgO_$sRLX;u?rMBuH$sEB9SLWgmJ6f4eqT.+&Q7a+KYTgc#f2ek\de(Or_k=/-/,-.6
+%_1*8<dkq`C7otC^IFO@*Ds=M74626#V2h*FQKu5X_dt/C1\oDRqqq'EDpRXu4>D-dXsP6<d#e9D]';n*m\)i0VmkEf9/1W*BK'G4
+%%(UPNn)WV[h`(Hf]gIe?-XnZ>c"kXT[b>sf2tokXn@+kBg8,XGc0'L5MLhgnQX%\X4k`-uXnIhW.>$S8k,k'-M#SNB1cP1(i:+3&
+%+,iiI&_3MeDJ:Kt]CX>F\S&p;^NH&*$c.#V,Ik\5eZ1'!TYIN[^RBN@F+nA10Q$d:2Xnaoj'r?u0AcV@48sTfM;4V>3m'*YlOU/9
+%J,HuFg_8eII(ae\,Gr*>$`\CRs%mjcnVc:HJ\PM#r@KuPFBu6=1O_pl\i[H(53;Y*\a/t&4l,&"f>?S65=%8Ve"tr=T>k;$o<.95
+%gX-'%XL@b1DXJQn8"jn?r;l&BZ6()H\uI(U]Cs6k6*^:5/+u0J]se_dV;@1+0lSQ_]_;j/fHK/8k2r6R"+O?XH6G6AaqAgIRir4,
+%00!56m^mXa,lH'Z9CU86?OiX>droul&4h8`I+VNaFo;e5\Ft3UTQ91d6jM#g[R&oW+*)GkCrXUL;m3\n:oG(gn3P*8F*;.#n(L.=
+%[Cn_r0nZ'IDBZBae[1<&EL!Vb+NOkeF)t,NMm_?]&F%)"A$Pa^n)rj"_QU#sXb4i'`qq@HiUec(<:T"H]*2,]Eb;RYmt80](RG2.
+%`m5Qj.8s=@/fas$hZ"/D(IF[AReBKmb_b8iLV[9hLQ.D0m<0HPJEco;-9ABGlPHV7luMO-mEhcgmPTDd4as-Fi"8\8HCoO.iIT`j
+%[u7ZjqKD;gAMD`d*^<H&mnH"`f,tjp^*D#SH$2K==GO#&EfZ95]39YCIfP*hhs!(H6G6L?"m6L>\@3^HIEgAM]tLU^E*';1$YHg/
+%=4A-IIseA#k,(3HhgOeM?ihdln>Gkb6UR_Hpgg[X7fA0bqS+':\ef;^@DuRPr``U3&VfZKrY+Ko%4BID-o#f9a%m%'Cp*q[gURi)
+%R=".S+(sW4mJcdf38b`ORbU4J]^D^Q5s=tY`],#u];=`J^:ocIfXcIDD],3\RSFc">FnA-3kV%Hn\^GjqH)=K%M#.=HYbp[#A1-!
+%1P[FsI\hK\lGg%e"MJP<X="ePhM/W6CVKsqY-)ORCV9.p6)pipSHf9rFSC3&j+Wo+BirQf52fkhSBB*i](;,fa,V\V&MO[kB,?Q8
+%qZ_V3Vq+bhkBt_oJ#g6mH=tO*#=70g:f#R]*\;Te<tMT3&=qF^NpRala2f?%qp7<ul5_r0kZ8GC-M4=1p8scIpL&d`^$r")&fOH3
+%P8+f,F@%Y&c+/8aC?2#]GB]?#C/8%i[qT[@jhrMZY9.>=N0TpAlc@Xg5<e@`ghTR5!]oE#h0\te^YdqM6:(p)s6/4rg>,alE?p$0
+%m-cB!$pL8t-P#d7-RL*=C`ZCEi<Q0hoDaiP?29.]Hm_^KaQI3smc,t(nTd<l3B915n0m%\cWAou$CBsYfm3CpWSB<$WL#GEE@HAJ
+%gtU'h=+d?+P@5Na\O@Ks=n746nca0L\OH1kpLYGe#6<r4^58PgQp,TcPt*uVpV71p_*L$E^#BV([lXh,e;_FQ%Hm)loFP]SSaSbD
+%(JD9<oNqH4Eg.AG3EPrKX./lLE)l;=B\VL08PktiQ]LT>4YA`O"0]l7qi"jqH2%:?#7f1)i5#?JS!K*$g&,9J]ZQXJHhHeO=7;_d
+%1D;!:r\L_WEaHdHYA5Ek^8,jfo+A`OZQohs"D>#u5keO7MY(0D-Kr1`g5:nM6pQ?'B1Wf%:_OXtKd%=Pm-_-b%>7SMceAIt@9[j@
+%g"GO:PqMU@pu5Xmmjs9"kTl(`(X\V?*ul(j/[(A5.ZH5l7:,I\Y\XDtI+$3nLd8$nK_LKKqA:?C`TP%KaZ_t/1Qn%*d-QZQ0aM)&
+%lu>Hsp,'mA`CCnGF<^aGk+`-?A!+Nf:=st6CYJki-I#S/.9jJZH'JdM8;<REmje+DHkE\q0fDWnN@],-Yfm8#ISqs_Tbooe=[XR]
+%EG\MIj]mu(5uh'R,lnH-PP&c]R*,`F-s\ZbJ^Y_,^k9W_=oQWT^!,EkTVM=IaNbU3PA:P:"$fC*K/5asIO^^TDCJ,`4Ea(!H3*Y*
+%I$^Z5K5P(q%!:p1%S=EUZ,hpfJjtVJ*`HfB!#[3:@SfD^!kP7,)?GNpV6HuK7sV94c[a$m%/msOX+2,Jk^l3$-a?hqB]-k?)`iW\
+%mR$-01IU)bjnMX`h.5l-`aAiY7#.a:_'LK*##Nj1`d6FgKg6'<JKhOS1O.j)<N>Mr^_&j"_%=k;8!T_>1dL]PUE0Pi?R2!AOt*+7
+%Q,_.>#0Maq\uXWO=bn#Ig1:^Tc^$9c%B7>I."7;?'\9i?>!82?Z"mB.3`+?s]\"Xo+;q\l_qI_aZ&8bsT:X,!JBXEu0mj2q!VAL%
+%NAsQOmJm7+0t79Jp?[A4L8T^h`AJ^4Z:b]h\4-8*SjBrL<%0^aJ0@O35'XO&0E[mP_9:*WGk`nU)Y@/EJq*tTY6EY(\k"oV$6p$t
+%cuTie(<\QIc_?,F/2!\X!$?dWOD-9&iYj-o:5Nm2SYh]I)(8?R:F8c*kRCV,T*=;(ODcunG$tr*#:+#Z!Am]M_[<W4g^tmfU'T)t
+%)k17sk_A7$%%no8gjP*p.ZNC8.%Q7KHBp2A+."a:6kS>Xd2Tr(!0kV9omaKQL8o$f!#m406&M%V5id2bjOC#8WOIGS%!<_\jBRbR
+%a;CHJ3l6O__@A'%37P!%P)gf"6XjC^ebVmCemTSB!!P?@.r^b9)^&$P6\0eZ7Mc8aXpH/m,*+^^Ee0$d)J?k716g6$/R0%tL"Sb6
+%#_O'JdD,7:^'\Q+=KJggnq)cLaYYI"8k:!K:K9su^`^uWd?jSokZ1M\JoLof@dtZ-U9(^SmHcq4!MJ.]EV%;0NRFI<2kLS#1kf'J
+%e7Do@a0qcH+?S\+X&pS(Uate40Pj2K3U!o_Jl%!E]sN?h#C4IAmV-FH5hE(oN8ZdupoFQ/7kub-PfJGqe9pKaP,k]a]O7#O/7&F2
+%cfQ_(A\eSgc1e'J%,I3AL0#^a0LhNZnc^]Pi",ql-WIbh=paXTe]\5,_))IN@#lYs+S6M>Y8iOJ-US/Q`IUG)YR8+[Tj/2T(j9DR
+%S-,h6Z?/`^H(V>fW#\Es3eV\[+XMhd"9bELd"]?#'(?\_R\Bms0np;:$hXRO/O=GN*K#^9dJ?Il]'aUA4LIJ!E=%(!;Y+W=#2N>V
+%/h;VJ"j<eoM'aZ$&m3Oi!@WW+W.A@85]Ch!a+A3M&3uU[23E^f$1D;TiMu.!);)*TpqqRCEM@>4C4)2p@6:h/aB1>s%M0a1C^P_U
+%.S2)kAk*N=,9(+#'sT$9.UlPX+PCmB6B$4GD:u(*8jW`\i/6_>PkJ'1;Gn0M5jOKL;B;Ad^Tgs]dGkkd4oqJ&'J'e'VK6lA\q5kr
+%PR.,oc>m"#!2n37(?IY,/HKZqYJRsYAA$"%"nX7)/c_e1#4GMXTGdABlGkS[n6?#eB!0,8Ub%7VW3f[g)i'q_,0Gbk>[ilgDU;0]
+%1+Y*[1ha)0.#l28.]a8oan'dS+XRX$cm.,P'u5d)/V0h\,@OQX^p?aXON*Gf2O?[Z7mUHjd".2DdNf829#tSJns)?Q,g50JK#.XD
+%Kg]Z0=M9rX(Y0pIaXZ[H4#GD+AU;uUM2C7B-/_T2$Ia)T*RRR"&$Tp(l?M7t%!o9.$Hb,ng.F:6n6E^(!YAb;-7%B4#D-6Q&iO=k
+%6lR7RW8$LF&SS02W_K%\@"jWD3Yno)gk'(56N)Lq+e!$P-O[6.GSgPc`RZodaiU-id9)D>7N=&[P(?%J#\jVS:$NOLK0&-QCmSig
+%K1$*4HS+*Y$i$6CG*YY6@ER+C'ibWpn]7GUnOjOc(#@@ChrEp6("aYr9:aF1;J^O/MkOY-Xscj5FP.D]N`]KS$#ICDL%D[F`3+`Q
+%iG0jV*Mg6=Q'oWdkib"?D+uV>[NgF]%[AAL#,M4/`C!r=^nQc'bd!IU=<$./"i!+0oE#Q"/lA=f#g:PPY@T3\,H(T+aKQ(a-U?=7
+%js#%G-hBd\OO#I/9t"V!-fXsT$tToWYooOa$js#(&P5Kup.UekVD.$0[1Le73f@C*iR/_l7KNiX7T2[[jXZm6RMnjiD6$p%00h6T
+%!u)Va0d24XD-Ab@Ymnf^!*_.cWZ?p&O@7b<EGJ)4L!ahs?Gf_dX9PeBp`_!q%&Y6'"bU>?55_Vd9UbMZdm9.Vo0mUG)TDjS"iWAl
+%Fp5%K#nYdsE!O3]<B@@81?kAQ:b>^VKk*XX6R!H[VOU9ZI$C`le"N4&!/6l%LtG$<j-tZhO/7+Z=1Vedep%Ni)0c5:%XJ=0Z\#nF
+%RpV7*d^lZfU,sT(F%GH2$'8-Y8<2@;"4Aqr!L+3;"?3)p[#?/%[]s7nTtu(0e7b_=RH;S##`68KF,S`jK6XckBfn;%3oU8'BAINP
+%Fq\OD->GT0.;1h@#,(SQ.>pYOpg0Gf&R/!O;5]j=nAn4p$nRh=@%<?b$fFFEoO)^6m1&>Pqq/3jgnS=)+B^'TH^Hr5#OSM-\t\X$
+%%3sM3O5S\j!0+r"_,TFM3FI2V$b&77]kh81au,fD_.j%ZXm2!S#-3I?HMk1%[EaPlJlpT4DkZ[mO[_2'<`_T'+m+=ogeeEK:]M(s
+%%2r(WF>?B[P6D5Lo;#->M67iTZDe)$AWs(+CX@WK)J?kK4t-DFgBF<le-PrK76Vnf%MkqfMQPN;I/^2/6:c4NXoss3F#X7c$\Gl@
+%>m.:'cOrbh<^p;JN)'I\+SY6li8er@^qs<eRKmY4p)I.'OTm_C`>^uu#QRIM@9D/6U]E$)Cc=T2el-dHf=SD*2@90)?&/u>4dV8s
+%BekVRp$F2N?CW!Kb6`r4ZouAlba\F$,((/GKm`!<5a1T7O"0($3kumbSXuTQ3mF)?,?dY#i1sb`k>P-#R97$M,QoJX=,\f?)C!%)
+%[lEA<>$H'5"F]bpMea*?/llF8aun-MPGtCBoWf9&:Y;uFK2jH[CQ&-"a%^"U5qBNo!:Qt.CeFa8KEtC!6CJP27<)T.!,c!H[NW&)
+%Hp+$J=u9RHH*i@fkZ5BgNo%Q"f(iMn$;0=l*LRl)]M=Y%+AL-@+@(XH#WONhfIHuo)3^,,H#JJp,&A"`/V'Ocp/HE[0H)r`%"_OD
+%6mm4ce!/.i9/@o.E6E!NDBt[-iJ^H2ZX>oE"s4Q":#G)$3W0<=P!:$L3Q8NoP_k4J4/Q\uo8s.:B_)O)V"o.992R4oianTlAf+T[
+%$U>o>mh-cmi@(G?m=f>d&_T=gnnQ<M-MUos3i#&<T?BT+7BS$XeV1-5cZr\V0a,s[BUiRsNJeMd4KiJc=S%fI^`gO=9%6gr$8)cs
+%bcmBjS3bRS%Z)O?5Fa::IOO#ILRA>P#dZPT]4q]lbZK6fkW@c,KJ5LEWB_Y%+qS8ela-B`Ggus^%kYbf.ij<HV3ShQhj(u6Qd'=q
+%JZ#L`*Kf+\4\:lj_Bb1T7Qr"t%.-8%3(7n@/e=j[(jlm:otV1?)^&7NFg0^K3!?(C*@L(G#2C[pcer:>VRN4"UPD*iTL0*=]n0GN
+%brdt+9S3di%AF9';!e!T`VMe>XHJX5rPsgsnKe):@]h-Y,Zp-OhBl708rC7>7s]ddqoEFc44l4c"%93fS1BH9ro[NN:Zs;-qY+>`
+%6MB+1CE2G]4^I!f'nQDYg63?6,q#OVe)TOeZLj>RL[(/I4Ln:d;rsRjmq[ajpsn8Yr=6[2NtI]n%6jSnOCPQL-)el`qd\iI7=.!"
+%$'`T2(5i2=rOG%58Wp5@6tMFN$T_GPY.Ya<!j9'Mho]1!0E1h>$P?OO^V(Ap4FP`';(*ga=!Lkb-e7nFX04uW]EfpW2>V:2r%:#5
+%%_VUn3#emB=,S!E'#.T_JDi'qD-kp[(452?R%6q1o_YRLh:!L-:o$_Z\,sF7%^>:pCVF#B'oTb+Z.aP]nL2_u*#0p=Ln?Wl[]C7X
+%jfKkH!DP[epY"@i@^/6oZ9'=F%DCiWEBLb7]G._ap40(o7]^FPTp`/fo@4X!S6sl1(2G_+GK'>NSFTGIT78X(`a[JQ9H>0#Q)luh
+%g#B7M2ZT<;i`G/qc(-Z#6<kQ8X/<p+ZG#B)RFE:e@!W&0(6c=%T>(8Zj/7^unG84C[k6tbpYo<&L@sRPGi#fZO/k3Rna*Et@Xfst
+%1'n+6:YZ\9.::pn]:lh9:S8M-Wd2;A7.W>>H9fBi$R[d_@YK3r%^-_S%Vm7bd^*`c(?aFZ0(KoSQaJlm0l"G(6S6&;H$[eEXD&uR
+%Nu+s%^J'8_7hlU0qR4cQn$Hkp!Ih:_h1mkEB(@GD,,aVRd=Ad79#<ts3@h.NXT#-\3KMq,5@B`L>ID%ca$3eRra]u4I^nn%_&0.4
+%Hq(lDEtp6+X?_kWf!o/QYuiXhUrY^qTl<ZU*P5]kd,;/io60Jf'*W^IATWTVG7Hg6E`iZ?WBTI.)*q]3/LON_oe.9(rdZ6"fSF\I
+%[g\;Im'YioPr#IF7l.+a'VWdG<<Ha->%D%62>V"(1'"eE4\<%B3U!(pS^^kgoZ!^jo2kCqR$2lD>B[AKWi!NO)t_D&9p93bm"Ebf
+%/O&""*J0#8&:",ioN9>U3PXh$$b<hBY22R[S*qP@7Bos_[QOh3]QEV^WUEka?r,q=dq?E:Ql__hkhj"!L1e5]m(#hk7[j;Jr.sjh
+%o0ll3YSmPaf67jP\F!ALEj$Nf]C73^'jo_'TI5J]Parls'jk)a7Qs$7>cd#%%2UbtVt%Uo*K)dZG9)e<Tch;,<P<'bN]n=mEarUX
+%Es/b$<Ta3I*Fd(QcAer.`MEmNkHi@$e'/P%Ko+F4LWra#\nJRDe0T!]^NNN%SYmf"ToVsDc`b#;!qea`>XD\)YEgUTZsNE:r9jH[
+%^2+I`RK*`1\ZnNg:Vg\0S8^H@UgO.FPS-Y>RZ>6:,6`RGB2?iUVf1UX_EZ>K*.-Lg1%tV0(W23HS#0f7Ji2hY!KGn6$L`Ib@Vg(4
+%+O-JE?%XT8WYK<Y8R\lB*gdhbb'J2Fi@H#S%GX&Aq2opMm*!SP`JW/`>!/+Y6V;Uhi62I,C[jk.gbIrhaID4*2>>T*5nE4M>p7cf
+%;#5AHc]69tjk:i3qYg*/.O"(<2^oTX6O2-I1H@0C$3lRA(c\[Ff3T]:3hLU;\[OK(MKS`.@_Gn;:?o^J=2c[U241ZFX"A[Y5<Sl%
+%o!Z(J[OcYfeo<dF_N0\6b9PSInZJX"*_B^ckOR^V5AqHUc6%J-DgWm7.sC>Ar('5'E1L@`3*'H2IJ(;qEHtNT[-lDjj47Oa6k7%U
+%G&E^MD"oa_HZ/Xl*q/b$@f<gpRl3L"qtK=DYY4DD.nQ:mp)Nk%E@a$H@?&0m5TnCGU\OT_!RXT0I=Cb`:Q$.3Aj8'9-MLKd=^mT@
+%i87$O7$mlgX+R<GD>j+Z,P0!iI;o%]&,4Ot3&it1/iQo>7C\sCL>r*n:S+CFDK"eOrL>WacK+0aK^7W,=AqQsK#.8ApkcUXN"2G,
+%eU$<p[[attqAF+356e6,f.:9"9[/kB*\r'5]$=*0<QrSm/\DG^:HeQJ`9Y6jO-VDf&fNp<^AEB!pH5s5pA<1i7XE4GT1?kIH1QP?
+%BY)FS`9>5=>urrXMaW5BhO'pl+Rsbs@WA_FIk*Htn'>[?F'fH=B]92Rhi.J$p;C=9erH^DMn@DM++?m5nP^sL--9,`cT^o%oX#Fc
+%F\Bq&\E\N`4TA+S&'f#4QVtH%c&s1>q*fK[+'LZc[>M!Ap>c+<*`\R42pNH"\,D6,WFFfMWqjIIhk%K,-Z:l!];PCP[:![/Nf>,M
+%!E-4;hmmO3n(PBlhnK&:I<XoMKc>7(5Bq/IcF#I?((SEeoT87t.bhU'G1UVPFmn1^c`iI3DuO@h\)2"-[q'_)Yu(8<[qY`bg"BLK
+%1E/N:U#@*RqQKCeK^bq)T3A2CIh[..7d#dt=UGkCd@s50AgQ1gCYQ4"PKkc&Q_Lr)WgMs$27p87Q;k4]"^lnRLSI./X,(\_%RsiW
+%s3kE3MFW[^ET3bjdPAoDPKcjMQY6p^8)UYdmL!h70Lu>K6ru8)Q>E09YMt4JG"+t*7">B)*DcaAKS+OC!BWXHAf-OAqTq6Oa:o=7
+%]So!MSu,b+_5g7ji-.)uj%'J%=^r6hABO[)QOt_#b\-'A]"ssZEJupkjT$ninj%f9<+d&!6%DaN\%.sH!FLjsak'-qQW_6L3&BW1
+%\-CtT&=9;Bp&k[gj>$c"_-KN1$^"_R-M@J-U,0C1o-3gJ*1Z/9MWtZO+M,q<ft,P^ED^"#lL<Ai(KCjC5WQh$HOXst/eL\O+m#Ij
+%EEV9QA#`ULjbNAOm$\%S3eX>?9.V/R]7=\B2oRpp\\=W]#eH[+3,29;].Up;!H$%8#S>-K_&a.T71=X-0*#f;["3HL`F\6;h2L?i
+%_@H`f-3M?+2NXY*#*Ks_g'`a<*Q2,mF3ksQ-dZXD9$eW3N5<7YN_E[8kOMbRZ]ZmNOLT0./A@'MLDW[Yo)oabE'>Ur/R\(E)-(fJ
+%6NMfP1'autHD;Y:+N,;98dUL#4jKci*J,6o<AjqI!B+>>FIN,=[Lm!/%#La`+V7C8#oO*ZJ4rK/EpX-]gQfQE>;0<4He"MB;DAYB
+%J?'6?0*FHoFOj;_X5LAG!(!.Udr_M*_4TL<'"=eQiNE[f\3u+)$FAd]N<D1JMsG]+?oA/8*)$rJPe>M?aL>j5.QFM>KTUVQ5QR]j
+%#g+!+HQ+]2!"NV6"NE%)>i.%#d8b.65SlKp,%XF.PdEedMB-diD?U(%H3un^I7&T3RBed*3+9dZI4kF#=VOi"SOR%VRc5t(-iadI
+%0_WhEfL,AR]?r#iNOl$c/+.1<F1M^3`'IQ<:e4CtJ;*<\HCfCK+X`*PFB"bB`!G\GA8G)0*BYQ&6s,(<n%(+pSYiQ29U3j^B>E=7
+%Fgl":#TTd[P9:i[rPF(Im[T;pq#JuW-M4_PX$P(t$H<fU)dume'c79c\M!VX"[^,r7AbJCl,OrB:e(qO@k!qTVh03q8fi."<SD+6
+%EWkqJNr&6>Q6.3IaRD;BN(Lt,(r+Y-'W_C5?I[j5(%.M'+p0[8LnT_"GYJO'+F(lZbU>(LO\q70L`Z'G-VhV5&<>(8_%dO08)["A
+%6'9h5W977a_]dAJ`9B"W4.u!e_T!DYY00,1M9d\?/JN`1&6t5JcVD"%Ko(q1%B>s24,>^/7WF1c[OjoZ%6ukmjd7Y,S:P?8l5HtP
+%#hI`#I#a;T_1B-84HLkP,V1JH2cUDA/>eB*%<4A1$3UBc,L]CX_OT89P3=8?mfngJ0`Hu5Qc1j4N)<1Oc!&P%PQ@F*Khjtr(Pq5t
+%e/OX+:jY_6:Y8U>!t`,V)htupp^6JL>7lJB*/[^I0HOFb[5_V8!luWn:Eu'\fW5f.[c7[1$"@Qba<*P,5u7X1Wj<-8e-$[e*da"T
+%'A&CT1YW[[qljdbn<`s=!?&m#=hIX*F`VMq$o%N[%OAKaBV6$ZLB=bbd5M%h<eZ>8G;nZ!E`e^Eqk5nbm*'5]AIsenf@T&<Xf[Q-
+%a>sQG,8Au!TS]D7(T;6(@3?nSTX$=q;?=Xra"ZE^*XcI43Q0Xf\.B^S.eq-D!9\S7)$4e;mb:a+rIF@5qM$+oWC,TPE&j.!_35L@
+%_*Qq.ab4&1.Y1B;#!aXJL'^F&kUIc@=@WY+&"t't#F'"UV+6dW?g`U38-3Ng9f?"q]o=a41_q7/+5!CR:*QCP0RL5,g0dW"N#SL@
+%R8F!YmQSYtgR@I6_?_Jj$+MA"R_aiCLn$.$rW3C4d4%lrAlesV(WI:KhGXGP5L0O/aF=cW&3snW73/rD!P,0>3DLhT)q`<QNgnD4
+%dKXXZfuf'b:-n5(aWO\M0N:6mic6/XLr,uB5e-l;3L8C'J\f0f0An/3$K_ss.+f\DLSE]NK+X&]gY`g2f:T:Qj4;AWAg(F&<"X14
+%m=?F$NB'ph5:qnGK'8Xo%<.t0A?iPmk!sI:k(l#lGG=C\eJ9SJ7$md)<sp@!2safi/T'_dM\nC=,d*stBqUR0"sHC^q1u-Q"@[@l
+%-:Akh*!%9-8<sDURq<pX%QF_B9#1W\LTPQXR?53*h%94T"RAIJ&%<E'"Loj22")ng,:&sY3mGb_]%"qO#*KOfSe2Yu`0:HAN);jL
+%JDD@c2F1u-g'BkI%V=:U%2Lu,[kh-dT\5nJ<1:BTs2Uh/q5qYd6msKLk64KC('l7ULI+QWG9`=dT:l3JReU-sh>^-AU^>ZA*du3V
+%Y!5(5cPuHW(B4;oYN6G.pq&X\qj6JUYJhY5o>WKH6(@h3rd)d>&_0\$)_IOLX8hi5034r>8G!o!pUi$=hss;k?GB8$V@d4cF)_rd
+%mnmKKds9kYbI$`kX$m/up9OLAjOXH1_=Bf*N)uL8X'DR:g$_AVB$^9V,X45JIf"7PV*8D"eno0Bd:'XuV1B!LA^^uVIk"?i']<A.
+%Iu]!*lU@l+8rEp&^/M3fT`D1dqN^D,@DeE^eGp`A92:;$/5iWGXg\t3_V](`UGZ#SnUBXJHL/U`UV@PI?bKk6Dsp_'/QefWG#g@/
+%?]c*Ka7Lo)Mq&e$XDofbXS-8%%c)I(^"DpfC+2?tdbVqRWKi]:XOcT24rIKJep6[g5SFh`)u7e2dMiAo/6X]4lG(K'RH%3W9Y]D5
+%fs\)N:]L"?/^nISbhD;VA11NX)cT;#pYIRBs/n=lme#Y`=i?cQhgP(>nWP>]Cms'9ZW1k#+eQUDHEB5YQ)N30&\#F-IJ2HF.B(;E
+%*P1@fm2J8134*J_Uoo]7#6X0ML7B$[>889*'g&k-`l"h%\<"Zh9[4h_j5]S]rig"SBBqc$<?!Ig7I$[eV:S1Y>G\FHl-M_F)q7O\
+%q=FJ"99Da%YP50c*c!KM3`BE&-ib-LD:GKsG(CQ7D#n,BB>AjQS$?N#q^Ji7qY?Qd'k9Zo%e!$Iq=gQ7:.A:]pTP!`k1NI\5@/RB
+%19NWTfofd?PB&'3lEc2[7K.1[*_ip2(OS6?[2:Zn!tE;n=WPWg3>D.ZLAWYGXdIl/h8Ck5cM:orU7&$(mgad7"oHhPq0k,e7JQ81
+%I9Qk4<&fjSSkBN"^2diFVj&7;HHk[5n<]=r]TX.ifl'(sX#BO4q,fFrLG:$H%18H\=XIY0l4kNW]]&6Bhn=cXm-U[/DA;\W"Sl%9
+%Z0[ATi%(rjB#3QJ_>dlB=H/&WnKFO,?ed"9kDZ7`5BLoZ0rS+i[q+G&=hVBM?fPbE>Q=MdlEOI7"mZu_(R8`3Kr0oce(:aj(&aA;
+%PP/@u[2Xs//!!fHk-MV)k"Gn'7-QFAG&3Q<?>SQ^"(1%(Q#>0'?p-r*0A>pkO@\QUhK1>.pXnP/XD6pZeneYVU!KNG9?0Dr[TL':
+%kfspL[[k%9B/mVu<?m57PoIAPmE?.;ptcX6pY7harI\\9%NSk7Wd:c.]FCo2<=G=BpnjZ9S2l$Y2ttJKT\08@X_Pp^;ec+)Q,BF8
+%<G-`@0)YV0:LChaqnslHcp/QEXrU_,B]>'_?FY7VjR(aXF'nQXhl1,AE0fnkeQ.70VN'CH"`+$l7-@_=NZJ.G=O8N\efWPNihLq<
+%*G7:T);6Vc=tj^c_9\Nr]%Il9U<%ma859'^B;][<>TT+mF2?"5oj`XKhp&i[?r:!C`pt^eqMa0SiTrT0e+DE9LFKn0.F_klq587O
+%D\&;Ip%1gAgXK>Qo$4*!UO_R8B`7Z'kHEW[i2>>?=#L\<I-J0hUH.DlhhbaOiQ$"\J!_(R3bh9jip`Pa-P"E*Lp5cHr`A!J+Yhr^
+%N6ogOPlRMgZjNJI6[o5>fi\[u9u>S[ab"A:,&j[@h!_BWIcA1tDs('^C9oW,n9+G_Idb6>";'h21P[mt_\)_4i$IuVc*t+=WNREB
+%Ce3I;(bUu^0aWGQjl#u2NmOgZI*%c-7MD]Y?_+VK^*Vt7Q>(JO'kkBA=a;kZMqhQkVEMDMOmL'`:E'L*ZcauBqn\E6h9*cE@@$c<
+%+.l9Q6<ttZ8iLEHqr9k+BC(X8`lI8YggX8l3;S_liQf_BPUouigA#Ya)nit<H<Au?P28ss%c1d[6VprFf*F(:rL32!c`.s(!0BGG
+%:r<ONc]#@ceu#ASFWFi-aPEFLY?p'C0K'#&jLH_,<4d2b=s_A:IMaGVcH-g7&Y8V]E7^'OT,r\1hu3s>(b51rhMt[F:1$4"$@$"J
+%ZI&aZ:#,o2RDUGHZQ$pq(d)[7Up`C)bKi9GYUjh`>s<8hLXYd4VjfmkhQp_B"GMHPqDg77S?%E/l_SF3T*H"@]PVb$)5oat]6kbH
+%UXu%=e)JTJoN?qj'5$srVhK,0i4r6ZH18*0G]78;LKMFdhX&93a6aP@LEo6eC<\l&chb_nI=C(om8JSAhOAX1+74+7gl["h=,]d\
+%28W@7g<T<a*r>g%oD?:+34)22pIh=-+_]VMX7i*uG3AjWS5cfKpTFM*rR%RJZke)PI(AL2Dg1WdCNjabh1,4T[6&SN?i+ipR[IIP
+%;RVFob%.mJSDC"l?er;9mkoLO\uj_rXIRtA<D%pN^92M$gNRJcpb>4&rj/g.6Bh@!Z>Dj&0i+4Z";mQNiPD>:Q=>`uPn^M-KRp;O
+%:bPIt9n6i62(F_Fa5`@r:NI5*MJ)HnYic;e8_8jP#5VP?jjf,SA9T@J$kj0PZO#S0Cgq,m[LS;la3_fGntVeL6f;KZB:Wi!i#qS=
+%)fT;Yn7"()"?;&c;kR=<?OZili0k7RPu#mPQ4["[KY1p*d]V*MiO]co&g2X\gpc2J#['Q#<e_&IOfJI11mD7Hnd-NK#?;SsCXTn8
+%A?IZGMt5jM22*KT08aZ%'D>McpC\5F_"aS_&Y+-('FSRkI$5*&)=W0`lbo"kZt-nF?"\$Z$QO+/-P_hK_=>.TR^\SZTNR"YXp!eq
+%6$+ZI#Wq+;RfQd0^;O=Y+;[OD*`HKG'(b^FJ'^$+<6J0U7)7"43IIXJ/07\lF<Jj#@;t3Jl7RDj&#:!ReRNP@q?!)t"a*Wc-D(E_
+%@tEQPi^4'1,r?t<.\a5RJOru-h*"1c#6TfK9&L=i%udX#!C=2_\b3<81G/CZLdMrV0:>0;#]WT2MJuu31G^r#OH=TZ3&cB!RUgdj
+%o^KX'6_8I?XG/\QQ9Rm5DrH3KiFj:)0&\e"<9,cT)"j<Ak`DJ!);q:>ZN85.=n.1T3hD>FC[&"m/s@Uf4(QqCj8occoNsA1ZEO%%
+%:#b:NE!A,%!-OH$[Y+&#@4qG=RFu4\")t[U,V8N!8)-Ib9@1eQlS+l%2?QO(dg@)Z[a'+&iM<cDmh\5#/33(GA=*t$JK5n)f2^'`
+%3]F9-S)!$j2A:V8R)2PZ\K]YNMS3&h5OL"IFj#Y5H397]4QVl'T%CgbNF8Bi`Fus%bbHP]Kb;UE9DGV6Ka#^'a5\maC5d^_"]'h9
+%?th:Pfd4F&A1drq"euXH/did/R\'R=+b8FjbCDP&p&tTX1ZB$=I^5T'cTi"L!M2D+I@fkLKSg8<<-`uqUTPd2#q#D+OOFm`r'HbT
+%r`J<Z!\ZB,o98@'d3V&\`i`rYLs>8lE?i?!4<F,5d($?YT+gn%>''d*!BI+l;[-;O6!PX?b>EL25ZV!QSWH-:CE4a!_KLG?g?/,c
+%NEron1uX4U78=iS%"UYDT]5BM$8k)&")]Mk:^'7G#5k1E?%BJKqiF0mP3b,>Q#86A;@-]$>mk&g!aos^hl[]qG(cmr&$nQX)4n7S
+%8M(4dE6LXi==/*cJh'lLeBA(%2uk:9%r#IG1)VhSrbbGB3:'!(/lOmY+^?(YkCR4J$:7+i@U8+T#5"<K?>ST=LT*Nm*.VNRXm#7b
+%p]Ai#=YPD\PakFB-;-*O!CI\K'*2Q%#g)*r:d<%ek;$"%#bQXu=_WKB+fKs+Li)KG;LXDsTf$CoJ;$Jl7a!$BbA?jRNZT\N2`Dm!
+%/Vi!KktZj2lrHZ'LN!pV)?>C+5mc=VBmqj*W#dL,9M"D9&S]'R8dZ\++"GHbX4T??Po*98VAVZ*L[,q)oYCO$eQXC-HU%_$T$drh
+%:n8K_NW^$:,I8T<!)`8k/5q)Y.?+9(5QY22AQp'fG^I7le%nG+aT:=6^`Jag,bQi7>H<8T6Th;gh1e5]'sK-SJF+$U%Ci((,cL_B
+%+s8#cQ2$CC#]R`$n+mA&i"QIn;G'2>MRsH3J5=OA*si3,%J0U'5eui[QsD0pGBU^(a!(7MIJl%2/,R`Gs,aF6+o`NJEE?99!\Z_'
+%^:^YRm!g\`Yl""$IN'm9/+1TAS\adp'\3&/iS@t(r>gB72ARe[3q_;9hEu0U@"lJoJ+f/*@kjac!ZbCNWY^[A?ID`.,\-o*GkMRp
+%ZsU#&`,37mX`5'Z9b>qO;pUYOqJX^#AIs4N%mf"f!J0le>'=X'8;27,f+Zkh5:S3S_0:c'.17E:*aT-+n23TUBW_/S(=2jsl1Nrr
+%0.rpOje_5[[>P.kFQ-.NYIkkPRn9Q5VSi81o@()@JfK4M?X1ZMrM3VXmPTW@^@Q6,#O2K%;!dWl(B3]m'3Sj.\4T!rfZ+?4UK"hj
+%N1SV0==e&b.Mi+`kf)G8rRJ`AY;^@M#c4Y,^0WP^@kX&r/Z!>?Hf_o+Z.R62C0+G6bHI36NhA>i/SP;NRPRbMESkW\m%*(PZ*`t#
+%'jsS%ch;7G=?<CWWf:dc(<H@fH`N)@/)BO/Ki:#fAOD/hK3N+Wjgt\JJ!@)\8;-?SB2>W62m?>t<B<-J[3i#+!2e\$/R+:']l8:9
+%qM<SeV_"7l$9k+Nco&M69oF'&K+HeMGN;-\j]CirJt-"E]620JY;p:9U8?=cVPA@5b.-"!&$8:ffMYH/2=/hf21*-qqr1Lkm\MSQ
+%2dJGE".oBoS];2YoD=uOQ`QS1SbQkJ:Yp*McHQGYZ2&\T+#U?B6gF&MV]Nq\VAK#dWnk#Ngq)d,3>7KLV=M\r$\o9@<J_=B_,5C;
+%$ZHM5(bomuYa4'+4+@]E-TV'So:nUdD!ZOlV_"In)#eK$baQZ_3fTF;>K%*\)obKm)*>9V/+sjGrpUd(n9t>0H$YG7J.:"Ap?Dh"
+%4co3M3-N0HA`)\L+.)Zb25#0*)WG_]=@IlaV^KJnR3,0KZq9;'?[k]Ij+cU6Z7E0N%X)47qgRM^p=2K5%q2uYHXOk3<L]>^_Sj$,
+%[suq`?8-MB#2RpS[s0Kbc-$B=p:pS_kC?amR.^:((JfNL8<C3X]+-I5dW]!.LcLoMlka<T@IX:]XbKiRD^)o\4+!@oAFTSVa&_i6
+%(2LQnhlbY^(4?^o*!QWIHqfSD'WkHgZ/Lp.l<)>aMn<':gN`#GV6)#I3_jZe*<./Vk<#MOH>'l:l41M?'NkX?I0S5kF6bT+*m]3B
+%h6V)lD/jW,ZWN(HNFgBe4"%$nHgb22ZhN2fER`k@G#2#1M^(&!(Y=_=0WJ&kq2Bd[76O#)<X2X^FB';bdu@Y^VlW*'^$Ft"%3K^j
+%R'/Ceig;YWCm[>%@fgYoh=KeBr,NUgN<leTT,k-'HgCU?8%[^)XQgflJ@&\XBUY?Blgg>R;'*9r'DFY]+#N0?eo>\?GHk?#+3P[O
+%j7o&TnJT8SeN_j`0HYSqFmGqW+13a@9>#"fYl7%>^?!-'P?[0kWL3<?e4%s$D*M=<qbWF;S/\C#J+ZZ>T&.ABfsAEJZMW"jCT3^R
+%mb^"9Do;L%D3E'a/P"9Mh$8A@If&QHMUV]@/Uf[+n\WC84#bCLf-Y)!PD[ei@m$YXn"Ffg0:P*Y]B'^9%SJZmn1[%dIt6k"*060>
+%Gg'[tMAt'sZ`o6cn\<>$s3fk@W7@k_)DG%0&$-*>9^j$)$0V(1kuBJh3M2a<aK/0XWG,cN2TAAa@/t]GqpL,/rtfUGo`CuRfjl*N
+%/ll`;Vj.$S.C>m!Mc@PlGplW<WEE(.E4Y(K9Gr.?k^:QqF;DgcaQ3WH[>LUs]j+GoR`(m"3rpiH6R]KZ0[i-#b[G'a$BY\\3Kf#/
+%\u\(<C^t^0-K/GOK2agQ6l(2?b4r*'O^:UV@?O&#0k:U\Ap)VZ.AP?i`j$hE]L`UTnSp!&l&qh03"$G11,tZV1Wb:2E(h-<LhjSZ
+%/gD/o8G^3^A=CYmj\7mU<]]p`q?5]XFP]mu)G1e3[e3JeR;Z\P#)qM!`6hss2FkkVaC/0Tf,+5g#s<s;BA6ep"?`oc7+38U$'Rm\
+%,R\Q(pai+hEMA]]l5nQ1$DOoGdiOH/Pdcc+J3#r1JsCL&br<0<+eMK?\f"XSYi`pd@Kk#TU+>=]e;SulQ?_%6;[QF+?j@$N'V2-9
+%gEt&CT=h<Uk8>_R.o'X=K;Kk@cE*5nfqFiU_@q1Xl/6Lg-T6-r5g6])j:;e[Ch_*fJt^fWd:22?n:!Y.P:Si\a"Al"O]0K0I$U!.
+%NE=K.n:b?P*57R<a<ZWkKBQ?eT@EMDnPm^P&DfB/*)T(YCD69id0U&8\iL4fJp5"@Q!>$D/ke"CjI>eDi/>HY#^<nT<6TAV'I$9:
+%__,Xp;CP^d_tR;b6/$r2:(EfBM?''b;=T\/.bRCGnIpqcP@1)3L;P8[Nc%@PN<q6NN*D`!GRfW/&.DZ63il%*aL2FCKlCPm9L-go
+%'=L+"O"J-oTTHJ$9"GLdfEI+dP.:f%#ZN?u&:G2Rhu`?R^J@rm>g_O8.;!\OVQ7=GLifF74QS<,*>2id/KdE.o1<]BP!o`Fk@BS9
+%<,0jK6#,fO4B/>E'Wi[>Pkru\Q*M&l[3Z(,&t;-UY(ucfRBB4H,U"<U_'\V+=+nVOlD-fm!cjU:Kg=8C;j[j.<#qIh6n&L?fYMG2
+%clXEY&82H[OffNOLg\C,aUc8#:_js2^S/QN:(ieCkRnlk<W"d0Zn^Jsp_q#HaG2b9aMqPfF*j:em)&X]#UrtXS7WWsN@'EjH#\D>
+%I-RsHe%^,e"F]PK84=1m*4hoEZWL+7EqMc&1-J+p=H#\"lJ^B0.>/611chF@Z:-kc$u&RG"IfF<6BGm-*6(#6Jm*\CQ2kfa%7cE_
+%a"Z%!#SQgoWcSXs/dp#?nc6lFN*GD""oskqGROh=GgJ6lWphm;!eOSb7P]+*he!o@a#'#q..e*(Kh\X];J(\AU&rNB8-l"X:Ml3U
+%Lt8&NK>POOifVhQ,I%fKY/[Ute/53OU\Tcf/ieI7+q8Wg/Q_EZ7!8]8/`G]pBgQ>#*7L)5#M(>n\As,.NohJA'hM6[cOl0jQeMVo
+%'J!G"6%MP4H#?Jq<Yj"ud&gD<.87Yp_$eL??f4'9eH1t-cBii?@-Ci#V\(#V@=9e7p#BHREZDq.C;S0RENFLjQj#2ai>8d@P9smm
+%LQ!)S;CcQT#!kKDW0Tk&:t'Y7@%q$PF]$la=@Q'.!/r7<6%U9?3V5Lg(pL`fOrLbr.iB[J2.M?OGRb(f)1nD)3.QXMOID>n_XMpi
+%HE<SbNCUp&ct-?M3WplmL-a"[N16VZ#_5Jb?>B9_>U_B--Hm6%k$Y-o\/6t6'!db24<_0IJ2MVC#.PL`4A!NF1o69rS&O0/[Sf9^
+%M'jtfI5f7lKc42gh7+.;F-M@\MI8b<VjVQaYHqV1Ga;;?U\Kr6`t!Hi/$rcg,<SsSeu-&p5dHfDJilo1'.+<D3V'D<8><"TU*gk.
+%bQ<F*X_CBV:j(2rVmFY(hPVObOg)4OEljIY"6ho<ckfBL7$p<KOKnkOE/h?pLo6r0"V&>7Yf!JT3hWclA#dod3_f8u>=/ZD$>6\K
+%BumETPF3TtR>0/WF&WXrgC^:L!G%8f:bp"$*Ha;nYAbRuMCtc!*0[V23j-GYJSDps-4O]g?3lW;S]r%g,D-E(/)*d/F^e0,OefcT
+%9uoTB_I9La`jLrY#!qpH&6JoVL2e\Sp0c4k.g_jH6kWq/n$>3UXb>AZ61:8.H6HBo7-eNCa?4jDmJ)Y3Zo+O9FU`r@ZJK\*c*.AL
+%*tZN9F_"Y!:T>;@<*YU/W)R"/:"#9kV9)'%nekhO'gRkL9XJ38q*"mrZ'Wk/^+JDq/=eDYWEC:+Z1t3YEn+C.c:DIm(I93Mf%<HO
+%fgniqX&3sTjV^u@N9Z)FKkE-2MAb]@C-!N)'U'4[8338S5e)@R1J8L'dh]PH"j9Ish6S+%!%<R,K$iQ9=dB@fA@+W/ljm0AKi/'Y
+%J=)[bKuJ8JAGRd]1c)uW#=@T7-b>$KAe=;HLkNc)M(Z%eU2O<HS&EgUP8-j;(.4Q:39)\0*@AC:e55<0q[BZ\SKZ8NO9f%mfk),O
+%&6M<04l]6p5n?9Q=X]to(sE`;S$3qFq52o0mKqX5_4T[74"D%[N]Q#hU=`%/`fl:iLCW"eBb)?Gq'6=L8hB?$^`$h]$C>K'U8dR9
+%)_D&6Rb5"jJAERWC64-@]&nO2jn#TRC@+n+S(9-PG,GY,i2$X9_"6n%+2S/&2Ts*4(<BXu8F=1o<.mcUODNprNtR(ZNU`R\dM[K>
+%dL,!t'i%Po'fRkpO>Bd-Nc\+b3DpZZn0-M5*`b6878k4L2]dS!%t$>:=]cHSct+OcaGhDt/D=j^$__(r$tYd-*IJZ_4TP"5.PV5G
+%RrHRm7FA!NgEo7._o(T#38Oe^D]NsZJuJ2EHjM)'4br"n&k.C3<a4]h-tCo^@>'^%-mU@707]uY8Xn`H[qfuBP6N=kjIf^^3Y[b=
+%mU@$W95F$Z.e82UZEQa*p<ZeG((QR]]OcaSA,Tk&kZSRh=QTUJm`*UZ@-lt1-$4Gs+h(F(9!X3tN?'Gd4&J?1)@?T$+EjL+&%H#a
+%%k`^;a5?:;Tn,s>T2$OiTd@\lDX`:anR4dqE$CGb(/E*q0(ts=W#Rgt%2dH[&6i(&#2Da23BYI6N+aAVK4@J@7i[bi?'VOpe?osi
+%,(j[3E!gU;b])1o\]i<TCEFp-)I)6B*!]\Dhr#LDPZ"rk_%3]g]]GI#'F0J\BO@6VX8n_kLO!CSaNb`"/1gK;l)lW.AU(5+M$R.C
+%gB\%R$MB70-,PTY[[E:!UX>GNe1ST<@B]gdR'TW93_a0N-_;S@lq/-83]qRo:(@B`BJTi3)oms!^nF:q2Fit"1d$O(a3fg0W\'t4
+%ABJS/%5OBJTtk^"3?6!nGVb6_>S^Ir\u!Mg&M)1[G7n@FdT#'5Xo8kK@VHH0LTdE9atn_OgNCF[7(UGn$f<Y+^Ck8\a:;Z<.`OaL
+%SAqY]O;:TZ5rrq1@K$j!A!l@@6RF*REaTeJLUX3r.LXhr7XJ-U#Za`bdk"iP3pL!gGbP^:hS.*1)m\Mq2k*.5W4;#SRNjD#.i1lF
+%Rh)&H,8`,&b"2(CO3^de24YAJnfCQ$,h,L_-ug%/95A3REGQUk(&PEnbMldPq]Qkl^s_YlSS!,H!^E%dBo@-]ZeGZlQtNWZ'E'=.
+%5:#fbi&2orFpPt8_lpFIU`nATliOFlW$Xo:aHG`pR48b"7LmXZ`SVIK>]O3V+`"I.YW+890Y)dXK+jCC4S04A\M3*hX")++iPGV8
+%C>sOHG(mY`N&[s]RS^^2O3eW:.7B!UfN`Sj[13R.D;)h/MKl.0)+W!W#*.,b$+-&+;74:A<EQ@\16clA(e[fXXLgO63[7]Nf=gEi
+%'mhPX!Kn?H14RpneUb^5.8hBheIrk?'J[i%\r^SE*%*/T[)l0D)(LPP3Q>J0Nd1qKOa&om;0bO'8+bS_SB6_6],[Z$%&f[J\Ml35
+%gWYR>=2*"VT`oZ(MG_sQ1_0:Kl%#!U&KSGt?1pG82J&m1kb&njCMf8o_SC\A*ChJ1!1kPQk,98XI:RN>CC,c(L26;7RO?B3;o>%.
+%fa7'TY0p;=]f>ckTIX9K<M*+pP\?7j#<Z(B/i;@.>_\+!VNt,1_[G(8R-cju$52U9_%1t0/eeRqbO[1*/^/g!'#Bdm]0]b?OH-p`
+%@G=HsY6iH9*7.2Np>H5`@>&]GTdf^>=ob90bak?T+CV2AdJ$!!WCO,NbfC=S/([5[6j"*e%rlhk`'d+,&V3RLU$('g;P74-ai@aJ
+%T95O.Vn6?G>$f-rnO1e*=P\D11N5J8Tom[(E\p>*gQ'XG0F(f<q/2m[L.!4%a(A7B+M?+m\1:%S0Pp_S2r2g^dO!:b<@Qqh:dX>D
+%$Ls?+Tp7\(KcDoWkRR=(K>loPo0b<(@&9!CF!JC/?VZ6IQKd$D&j;cq^]BoI/a?1!2)r(8aB>K3U'_<NnE"Q2FnA4'VsH`*)oQ7H
+%'KR`^(mCqJY_a>?`$+oo"kXuCEJL5<93)+DG+-PS-&TdclP]io8U-kX`a6snn"phEX*i[I!5$^f!ZCA\gUG@@gU'3nODZP0frf%q
+%3!>m^rlXPQ[3hG+2s],)C0'LU/_`06e#m2?p)TWECXt4\^T%gc)aK3:\n/V5XptCM,HNl$:pmBbmFsHJ:npV&VEo,"nW[(I"@2gp
+%+?;tA,RBN?[ap;6^-(A)6%bR:4mfPKinDU)@`"N_c%0gT5UY<`7N<E/'\)>oh$Ab+k-/nG6$11p@<a%)J9-c[Ogdq&RY9E<3JbJp
+%<Hib2B:;Yf+IEDhi1bX.Y`8^6+HS#r8-Gdre)K'0;%2'R7?%0>]E+qPPp"cLq:#qf6oYb%^^Ql'&tI+d;DV=Hi,fjN$4>l\]Ih$`
+%*!-[N@`!RXfQ#UCa$Z)j(bFbu1Vd#Qn[8`!8FU,_@VeuMRk/Sn)87Rf0EATiTads3K/"FuQ>%d<,+Q*gE&M,Hkd!FkU2tVoOFJm4
+%!Ue1rGu+2Q!%5Sm:(rS$QcCk:i$\8c1l2#;IYJ,"S,49bMeeeEQXK<+-5/\<$3p@u==")GrbZ\qJhu,40e&\'4D"X6)I-+(;Wh<L
+%WW2Y06W`:Za4B$kaN'"*#AP+aDee&O:epH.crCKl-<lofYPr&,_XQP&8gXa4&?Z\\)<RqjXtkG]\-+]+9FpUB<G;mGS4`b`BIN/`
+%S23"0qDMQk&ATr\>`":[d#iqC,soM")HA,j-nq"h)Nfj[5\@s!SuGr114UE'oHWYNi#qK=(a*eT=Wq.6Y/N%7PftM\Off!C10==Q
+%.I)(;UHM.&5naSH=!cV^:Z]QRa,qT]Ba@Fh:S^g(9l1rhHN=FEk?bCX(mZ$"[]RY;RYV'^JL&,U?$95aOdiO\-+tY9C!rBU,##G!
+%I)V?qD(jD5!%BAB(!^/S?-0QU%<ti,jS).ZXRKQe;MTIr%++ScT.bOU\HKVZS--6j8dmKU?Q43:?hoYrV.McIFPnQrFK#i[!?_fe
+%2($!:).LZV2B?/mFn"b?=8R^H6rQLq0UZN4hZsr$9u?KFbQ25Fg$rbh*_mr%5oLDDTg&O4*ll)aI5)?X(j\ercVT8D#YA1GLp@.0
+%-/9`Z_/1,3]:Q"a)4_[.K8"]3V!5p#WrsE[E!DUEkm(=B1nH]Rfr)6H-<*Jm\f^W7e[f]8-2D:*0s]GY_3uLg:,jbTAZkXm6e&G9
+%=3f%JgsM2q@QG]8"#_^*EPT2")RAlX.iI,rRM2eUr%QT"P?g."!q.#Y9]QS/26UbWM&DU*gLnSA)^`B!"Xe5E1?8'pWD$L1?s5E-
+%l(6lmJn1$SJi#S_8*gh/kWkk!/L-+NGC$:4fRcO^Z@;dTMpT-'!`nnR-;jkr[GJ:$!:15K`"89uO];FfT!mpSXs(J_4S"SMR*&-a
+%<(g>q!]e\WeI-Nb/K&BABV*IQC%QFrZ![XoRQIF`A&a2pcLql3-^pRJ](@QE9H0:T#>nDA!Y>d,bt*MI8fR9nd$LMHBJ.;cM3&mY
+%5YkIGG+98PaTX+!d@m+qYiP>J\L6[,A@aM#$b9X.#Q_Yn,qIB29S@_;R9kV]P5pot0uQu@/5`^KfGK9DBYnRSB>p,#d(r,kIY>Cn
+%%\!Ju/Z8`+N$qB\o4lQO="7=Z97fQTU:Z;G#\q=+o,V@_/?/^*c-iEI0V"9L#+)d[!-%+R'h_77J5h@DeWO`=B;KPnd6bH;XcT\)
+%c87:*J6+:lm7a"\&Oj)]'\ef@LX@K^QDRi0TA60j$^><HfotrN<%h=M=#?<U=eQ)9:;X?sbY%)8$+;1?4dR.]EVCqm24A;+d>;BF
+%-MrP_`*og_S"^%K80q*/NSGJ%=!ZDY3ljSG(faYKWiOJf`CA+2Rj_8l:L8dr&1DNWl4==K5n.KhcsZSS01Mipj;!C.9+Q'[h5V@G
+%Ii74C=oqZ]hTK;Vg8cq4a)L5BR.,E^n#FVRRMm0Ljm_m*Uqnn:jXq*TlM.q9aqk2-8Fb>$[apnq/$fpAVkF_!S'F(9fh!&8E)i'H
+%B56aK,pQ<R&eTqRFul5I;[EkDOrGBg"1?)j3C#sSiB[/AS4Lsf$:5T?f-0Q:"pNFSDa:[\_m7R$[A@kukG)j,7%U"[=6;&0$gYbH
+%@%nphC5%dqnb7X.PK+82*/"ktZt]P,)2-,'_PDmrqO0*O77n\ZE^8WG'R01ULbI-nc79G\fF$&h/OiV-WhGPHiK<%H*PTAMe-XJR
+%)"p:VbcsLJ:M<+JRML&OI&ksb^m<#5lpD3J9B-'!gH+hIR]6mC"Ouu_V=Y2@6A*arl"EE.=W0?BA9UA*_LY6kbW;8K)Mjc8N,d8L
+%4?AW0^cY!Q%#BkZPB8qWG/]2TPIJso&W"j"MKoJkL=C_p-AGG2S'>Y^L-f73mg*kR7h!/V<uDii""-TDM6j?gMng;<%9+oQeC5*K
+%mO5rI.gTG.2<b8A?*9peN6Z!N$YP:G84O2`";sthRTcR7KB2:lQWPFR(1Ea(&0t3Qn-$cSP_I4`%er=0C&m:H9cPL;9*rma,T7&6
+%OHBq_)hRgQaqQ!e+QgfY(<K(/Op+*iBJX(Y]i6HY+XmO&&e,0V1'D<TE^N5t4OKINS4ZS_.2&TKcefKEiq3U97[1lUClRF/bWfla
+%KNZ*bm<Ta1a'n'`.N'4_@1KGD7*,=\hD'`>"VZIF9S.e'>Ctcti4u]/40Rn'Z=&AbT(3l+nd*)<0i?o"b>Hk>*,d@+(9C]8i<hA'
+%0oaTimE7V(dh/52OhlR)<Z"G;l@b`Sc[nlB(FC-4d)$(iA7Q80=b3Z9Gd\f!^hGXM`ba3nP-7O2%AGQaV`^uVkC)GH:r!<0UhC6/
+%,_n<("s$[o@mD;-ZLE![LpFBH,^SO\LI=iW\0pZe,n$&:rZ96Y@^Zup!BH6`0G_NkCnm(L31nfF3AC,?(mpmM"C32S/Y%.Q.9S@8
+%2OK*!,F'\f=GPsc.?OZud0e89U<<d19b-_Q.?^bdD>X^9Kc=]GI[J9kLn<j%fCgM*&fpOt=Di]C,3p(aCf@HGP_DEn+o$]1"589e
+%:n7[n:_/qq?OFc&fU*6B$"FdF+..a,@0W=eY6&8`7k:FgM9C#8"FG.1iofdMQ$<&en&I/@<',-siJI9hC2#K&qFq;7iC&],&#u5W
+%foSc&jC"M1Q607T':^RX]I.d(O;I[6ecG^K[ENO>Ys=_#D-Ai3T'63V$6H^m=paoK_<_tX!?:iR!@'$N@5:PB06lO[L+%D/o<EFl
+%:'LP?iO/d]UPH51!i5NVVIklI]m)$ChHn,>R6h2m18Y.dL8N.o?n)M#"2u)'h5_.?&-5L]&V<7u9dH9lD&reT_,;Rq#RE2\%Qagh
+%MJ(NBFG]<^^iW*Q$p>QiU*(p_pj=6LL"HB5hP$VNAgR[iW5OXmipYFYr"G#Cad#J`c,\p0:6'>U!e@Q#1!LP#6`3q?8ONpp$$V)=
+%RQh4TZ['&GHVdPG%RKQt@(nb@2!@\^WQ7SN-#0,D8[SSj[keY!AH:I9#/S^132-U+0oV4^`F3#07,S-.N9gNE,Psr4!aQTr\Dga(
+%]+KSKoRoW%,?ck^]3M^eRY!#Ac%)_XnQcVu:B2ak-?knb$ofjTp4e6_OH&+6a2an8Jh1m12iKA>P_T?7Cj*^ipj*_rJskEH)R1gV
+%iR!+_+,()q\)EVj4,0RDWXep'acljm+d'q*$"a#F:jcI]$Z;nqD!]n?]h:B;TiF2\eAb19'LcNb!$"D8l;mtinsRfji,B78JhTa:
+%e:RrN$?(Ql3hl'Eibf1J`#sFoJjVd7MBPe)^<\tf$U"Br*WK9>bO#'ZL]kDX>d50r.+BSenoRqM!HAf4*8&3G"Rf9!^]oRo9lh$!
+%JOB86peK_U7.J.Tcs-k/LI0uU.`SNA6"c(BKb-[Jd&\4k:U:iAKa3l].km_MZ',Zj:T;fH&Bfr@'_/j\joXL,/e1D(TEuVOUY@M%
+%'[I=SFcT'#/;'=i.+,7Q?dk]<VEo)59nLIhQO<%6+$,PpYiGsi"ULScL',GGL5B<'Qr;Wl)7E)1An!PO(H5;374TODO3@N*4J<KV
+%Fc1B(Hkk!3Ip.X[2(TJL'da,#S#.W(p;@_bPOG1Qd:,Yni;a2dhOVcrC(T?UjXFdE@+7]L,]!KHn7;-DB],F.liCXrUC^,>A2#dh
+%5<@_T7$]/4>mR&l^1dl3(E?Z.^bp6ph8.g_&1L_0/>\j=HlZnM6Mp:b'U_?o*28!9m>B<m/B/GTRg57Abcq07'eTk_+_F@P1_%kh
+%;):.O]tbIm@$]%HJO9D\hc,$J9ju_lH;g1u"`^5heW':-YbIOVH2sM,er?I`+[86uE=5C-391AJ$QjqY1Y@QrDGS^dK%_&umg+g\
+%`-=<ukQ/5GRQC4\*2TF)/tpB,M4*uAE/fLnf0)!MGlBIdVM,Y*L[$&$C4bRR'$!!L0I`_]5W**lI'9M(TKZ'!kVO\Lra&OjGp=su
+%>rC[cPaPVm+M^nh>YEk-\Vs,c+p'VfLu:X@eRfA[#U5d]1hC3XalKuC_^=B$(4NPaR%8&"LL'2+Q76JB0ZkBt;#qIdgD:&GMV'6E
+%FBm`]\>@/Qb$tZIk%q]\EbWp`;9J$_AZIg+KM9`,M&$([?gpTZ)GQ.p?ULCl=MK6W*A`-/9<O/q9!4P?`9A\hWWec4MWHW&12\o$
+%`Ca_bQo.Q2KPFp`R:PkV9HmrSaD_+]%A,(`.VoJ\\<rig%e,:%_Vrli=<CQp_l0R0a5J;`Ps$RkVL>T\nW(/UC'FK2M6mN3O2Grj
+%N;5i%Qd3;X-:OZh+e+(3I9e8]I#P5Zfe"=C8iW[:kpX]I3*+.O<kW/I%$0Y:&;pUlR@R/V8,/FlM';'a('0%T"'4^fs/,-$U)sS^
+%7K*MI(%irMHO9sM\#6/;)<Hoq2KUnY9I:Gd"&Nt+/l<hp?)#/^HUS^F)?r5=6/KK0L:A!D<5%>4!@oVA,!&B/Bd$?4-BrPJ)c;Xt
+%Lq@;?:qA#_M;\>!Ya26pm73'5RafOP>'-H1*K&-pC4_j'PPnCqIc$eJ`>Bq:'Bt$$Z`q4V[%F4R%uF*:Z"%JdG8B:FFG]I@4Cb&m
+%c?3^IM-CYYCL#$os2G;O&H6Q]I"m1;)tc(PQVtKJVdT`lR!;%FOie$OI@;%'DbpL=p7ipam0IEXa]F>>O_'0<^0G,AM:;MF]pds#
+%9;pN6/=l9Y3e\J>N$1GJ1\po-%*K/!/&2uFq*f7L!ME/8+.ipFb[Y+8XDg:)n5(D+8"[]_`$NV4L,b>U"&"mIi#%oZ,%5lQ!]<7"
+%/b*Hd3u0)gVC):XNo("iTZMXlfJGSSV8P>AJM>IAKZSW4#.Om*2\)h7E?YQ:b'1s<_!uNnF2]FEXBC;&duhH`8&GlI.tAXtKG8eO
+%8%c^t3a#=%_XI"!SDgdY*"0ibggL5^B[,8j1r?"f8"b,/IKaeaV_.+)Of;8,<CS'd4^>SMVC5Ob:)s+oggA,DJ0*`i=I2U.@gONe
+%%#;)nXS7D9:L`%3#or)9ksu^IeG)Ms<csY9>S$?:l@9G9[;rbXe]?/)^_Q4:?6b;m(fiVsP73`&F=JaBf3l$?JV4'nKa:Fm$?09'
+%Xj)6<n?Rkbf5ug&e5.DP&P%`k8liglZG%#`i)'`qqQdW<!`DUm>FK@;_nt(b)!@l7$J1Kp!,-hsB$"R^QRlND#1JjST0l4i(mZ&2
+%mKLU^6)T((&*JY%=F>d!(t#E3muLc.LXLc`EU,V%bK@)+3^`caTUar5$!3X%%SB@9koN+1Bo?h`FrS@kOeiD"S^=!Cj6j55$2;]Y
+%-'WZ(Mo"nH\97;Qd&,E:8G8AC;SaA+S`G&OA3Ah,U8&U`PINrF@1?C.c".IKbM50V3aGA_U&tGJT%\CNgBtANNZ?ARn1_![+E,8h
+%Bo4;sBWX^'gm!dkIDV_r&RQ^-Ci[`'`O?,lOi]+:Yr75Y<B:/fQ6T4Ah!\eFfnmcIe#"<&J`0D*29\W9UM<]Z?;N&2_K;^m3&1eB
+%QFKi.XC*q(kQP?PANpo2#,jI]du,a/s3KPK0.)i4IDaqOE"BrH(i4ih-A)uZ3+IS^,TE4`_X<iTO8%?mQ))^jDDgA.flQinZSSto
+%8sNAjP+;4VY.d:2M3L@giV&OIk"3^6RmQ*=A/S>F7Pg+blu9m*KUdi$1E@T`TST=<m_5NBF+K]9Jj<R0jG&KOC4W5#c5A(FKn0**
+%lShF/'!rn1:fL%HA_7lL'ac-_Yq$!*BFu'lM33^X]ElG98=u1Ma9@=f60:?N;"Fp_V\m=l)"^`U/7,,jY_(b%;P?EKaiqW;:WZdr
+%91c+&Aqub:_D"Yb5;)+$6lV:cW@n]qn\hD=(RHi7TWHS.!&7k[Pa,^8gk19S"P=7`94gRib%?9iI#t.T+c;g:A#4HSM*$UK+ZPqr
+%?@U%%.V6Ok;QN(`T1,U.TG*KT/>V@4&jeFI3=]>Ndf<irC*tH.9bC+X.O@)B6ZU$Fr$44@l+ieE;6nme3C,b>!kf1]\;Cn\a&u\W
+%i(*mu)8T=0,],$nVNUfbS4-s,;,LXim-qs'e/1rf'W1ej!1(H-Q;c\`/3X,MOQ8;"#\\fDq1tPC9'H]B0PL/t#T=s>*rO,XYWkB_
+%W*:_u^GC^4/D/e`%hqUK8VTL=(]';XFCXYnp+h818]it0UAPb=!9&0)mYdm,!T,A%5tE73;:Ik"7$9B>Z=.&+P\+kN'@$W=o`S%B
+%5g;N0J&$W$R7*:R'7cJR,_@2;0.b4&?nDZl+,S280F:;G)4$9s^7<1g/\NM>-\^363*@q,8d#BQHK3qWnZ\gh5ebBo'X0uQcX9\7
+%"ElcLZfDiDSk-(;UBsdEII^i+g_`VNE.E.qKbPZaZ^c\%659S'dR5Blr!gs26a!=4bZKP2r'6R%J=%2>8tAZf*'eBX^qGqj74IIo
+%W=eXFd9AXcVm-sIH]7!>,d0Cg1k;3t@1>UoKLJS"?jqBC,#jP`_EJV>R0c=d)OHL,*QLt%_^WJ[,TS[emf>GUkX,tBI55sb7KGk(
+%8Bsc^]VlC^&qGDFJUP/_)?eh9*"epqM3>]-+]VC]@8<s5Ymh>0>h7i(-g)%#.s5"t,9XOa5[9'n71+'m8_PZI;F,c\,"up%E4cr@
+%80S"I<"A:)73mRXP[8?`h3X:L`X%rl&/r5>L2^-q:1<99A]9t&%aG_`fQ<>h3oNJ+8->:#,1;t9d`UJU$CW)'P[<g/_,;ie-We19
+%*S_lio$q,$GgDC77#4ToB8o>iTDC^H<>24AdD.T7A=F0OeLg:r1`i)B6,KONFJOpBjXKgIcB:KP2c30-JO1EqnNFZGUjJYCLmmur
+%;D'#Q'O:2K4Vj(K/Jb.^Le+S'iHU"V'>G.9%$6m,:cG3fOd7sR8pj:)Hm9oMnW"3L<+uV23Y,4fBTc>Vl4LlWP#ClC"FVGa\[2kE
+%:*:XR1h[Zfk3,b0Sba1C8p0-'Kie?O]F0/;6eW;rN<k25;_m9qZm:G6!i2dP0LU%(*28/IHjDY?90Oh5..eg.0OdI"@6/hb!c/Ic
+%9LBuFPs^FdEKOSX9BeWZ)K%!N2-/k9?'25AW+8S0\NuBP@q\gs:'V`4^e;Wq!IGQJ6K"Z,EZeH3-@R#(3`un"$_(W&LerU:PG,Y9
+%@uT>RKmKtt6:_RlAdeu%g4U'+,3<0h;S5Ft$Hg8q]AY$[#aV9Z?FWG#H!<YsRSV'o!=:O@1bij'2M#AV@Phs0qh(hM:/Gp)\H+!r
+%)I2$Z<35#5OWS9C-)4?NS[`]A'9Z+aTYrBjfoluH?:"0j'7i\2O9fi1#O!ZB,Rtq_U?n-lE&K%jG8R19.n2*AI.s"acmRcipWRZH
+%/&SJGqu5;gf<+*J2;X92DpahlOG590k1r/c*hP!s5^=k.Ti0<caS8FMa9Y9BgEO\',\Vq/#cZZo!O*HOm.%qaKUe-1I#$HGM6L)W
+%#nkk1FCDDD*Ce)*1_H#m`TV?)?8m_'%+nZ6OWFK(;C.GM;(3h3?cXUO;AI6"?g9781Ut6hdBJ!I*KLeDLO)b;O3&YEe)M]YW$/>`
+%I0'JuA4D_[VLN@S7^7)Jk'<,UN@K-krC^'D!S8W;raJi%URK!m705>T&k_FjS9H(i->*HO*n$;a'88P?W0@.8rO,h)_Tt\"q>@%q
+%,Ke1d=<!/r"\d(N%Z3G1O<NoO;,Xk:T.:cJ!\q'Ac3#BY[aEX@G"EO@(Sh)/X+TXN@5q(S'-R\/"^/;;aYHX!nuFIo`>jb,YH*5@
+%4rTH^VMl68E`WgL=(^A\Q*/`7jREGN;9B7rV_LieWX_ep*f<c!Yp`<j8i-(d$q!oT0(>;4ou'Hu%2a$YUh+2p#9*%@l)PH`RmuP2
+%UuD<Y+\1!#D``q;UNCbIHW8RU/*h@Z5==N^Q[.c;\0%#;P_M@L'q6#@_f/RqqM2"I%)LIL0LZ/bOHS-`Uk?^l0^+`%^.'1k8<OdR
+%kcou_kW<H[C.P-EctI+ZSlAQ1akIk48CsR1ig*it6"X5FF2tjhQdX><mbaEkonH\!-#&_i#(U^n.O>O6hUXIMFd[HhAB`7:A&cd!
+%nHt`7B3eT.ghZ6D^`*X$'4NdERWJoM_G=9*60f4q&V;r1@a^/@#uQG75d'ro9M,U)Qe`m\5]q+t\f4=J.J4R$])sCC>i=R7CC*R\
+%N[n7P,gZt5cVbCT`oP@;nOQbSk"9].a67XHdi0q,51=^nn?Y@#*AY:u-N8@_YJ24o:e5p&N]o<7,oQ=DoV0a#PVG[SfeZ<dAnfPb
+%)ZE++)2r6&W#pj=16YmiaWu]O<-0I%q8'HQNOpr6q+8_d+XlhRs$7Ada:'t;"X]C`7&`Ze?cYkM:I*/o.9FR^92!8mR_TQJ(8SK3
+%):Pi.9Jbpc2GN#gb'c`',ah]TKZ8asN.pmqVMK7AP`RZN!d2qAZa_P^J_lVRJ2il/G%&0j'D-u8UL-B6gl>u#([6iGdY_LG"p9FG
+%^K<hF/#g.:P+#fc>Hofj=I3I7HBN<W6%W/FPJ[EG,RYH"UK;o?aEIK?X-cj(?q<eEe+4df3#\O)l'Rm4iJ&b$V(a.VS/ImCLh%l-
+%0]V"m&b<#:HHE6t`nhZ0oN;e)A/*8_IjS'DJLZbfiYjKV9XFj/fg'oc/0"d+0jt&`ckb8)$j18)_,+=OGVIMf/EDVWkgns?m)pIp
+%E<?-!&.]?J&aO#h8*RS%#`\,b5K6+aK6\__!4t6)U?&LFH;0p2;^<e_dD8?]Lm+[T;)/LY8LC65`Fk,,-q6XOq^Wua:>d6tHD?!B
+%#Gh_63<0Jl.)-FOr[D-;O[kY'*`s^5YWfujalONL-`,9fYGE?\,0<"b&Z"/Q0N]"L3S(F5I`42dOn2>#RmLR@Yo(b&$DG$$6S)-d
+%rIbCK(<86uF59^c!^)G\Qh)iYbcZ[\8Fu_l;Ma=Fc/1..KCZN6R!&_*5_/ckEFnDGY)<m>8WYUeh@0@.=oW:qVCl5Q3NT\jZK'X!
+%A*(?]W-);(Q-4.\%Dqtr$Mg'iom5H>\2O3I2JC4tE7ioJ$*T;b/(_!:3u19`.fktIQ]FH.@]q[qYptfmU.&\$NLM]&&;:IXJ(/eQ
+%D2Zb!D@-oo[X:'1D]4bYjT+]7#;1e$Op^A9C;$g98n6YYf6])m"fZ;ZdFRjG92u6V`@-QYU@SD&NuLHm@7Xt1B`)3fA_^7#d-00t
+%^T/OSC^b[.nOd@R*e#i`N13_s.F+Ba*WJ`n:`LZV%D=?]DGBg.dAMjmi*S`+q#AG8P>"C>^K*^mY@j9W8B4U&^K=&&5Nl;GJW;JP
+%@^<rnUOS/3VFY".\Qab0R;Z3:cmqt=R1ndK,.X9?Oe+q/Pt(c^j#P.IFOc'eR^0f3E5tLK;#1O7F9A%S?KOO]SR433/]Y\[h-%9+
+%$u5`AF!\K*,5j1A`m+ot04Eh7@58V@d<(!P@d6g@j:-b)lDFjh>Y6r<fO)61>.1P?Q+qQ^W*I+^5rTKUNiFRYmALHQ7lRf.Q?4=l
+%JjYiYZV`_HKLt_<%Cn7meS@la4/[_iT*,!%U^d1k_c\!8\P$RQA`j+((27kP)5K+gd?4k)jJ\eTm.Sd_Tdh7@mU1__+M[dC"EnI@
+%D-!LU["c$7Z;S+hkr.$K?nEt2M"pGPb:tT,)H#h5BMQJ0FfR5bb$YlHP%&NJ/%k]BEJZ#W]%(+YYIIV\Wb+L$:9WS^=447:ST8R0
+%A]uGZ*&M<aWQ@!H($Ab<?#QqoeeK`;$*#LkKX3_@i;[/(P1:YsBi[rG(=inR-AtXFMXP0*.f@[4>W/(A91b.QF^,kZg;@pfO,'K(
+%bpS!D.F]7XLp"is63UPW_L8H,44Wc+B1k5TBW"a&b%N+UkWiTgkIOY\TDQMj>,A_!'`Y91oiCoh1;X7%IVq.1[d]=iqVqkOSKU&6
+%RMA.p2M_8!s%2NG)BB?dM!_k:>Ffc72.:pEXu3gK1.";'1hkHcBS=?.@lhR%)lQ!TDe6l1>.Pm8:M7cDA$gDpdFp1Y[;i8'6Yu.]
+%p#CZL.Zh.VOEo/;#qFeDU]K"9/eWt4'<@(,%E)lKFMmZk1P6/\Cb_lQ`,+G9gRN_+p8?:(ZnDAlNI/&Fr]M)rWfU)o8l+Y062.L(
+%>8qd%0MYM25;;J;7\?+NN2?O@\PX%BX2<hFq2lOZ$8_KTpg8LB00f;go:mC>/Ls`akJ*Ib=NiMSCCQ^?9G5s$Wq%VQ;Q?2rh6g2V
+%:TH4&+lEm@Y//s3%n@j$U<5uA>]3><WkV$<UX<LYkin-a.\uma37Ms\eZ!_*Z\01YggJ0-]-L>GPYJ`./.J("f[r'-gOBD'7712I
+%jh$^RYP*nP'9D>_RB"l;S^`OjQK=S'W"!#h$6NP+bgis,b(4!WrBH];W;'/j-S[gLAu#/^RnW\dK;U<F#%4/!L5iB$]9AQWgWaE[
+%D79"k;De]fN2UkY`gbER/PS?u]Km`eV>=i*p172faKI.sK7;bl2hJCl?*Xbl=age"s+c)dq**g';[oq6eL/8kCtb&*Ltl$Jd.kuc
+%0V%*jE`9@V,0/`$<2og^/tP%GAEhOYO\EjId8BX05+p1<Bg7t;,p=M3]_g@lWg1g]?TB]>1<nMYrSqaJp]'WZhRb\maAHe4R3:=%
+%-/4oKRC&\AiJ_A06`c,8>%P#uX];>!\<H;PPr"]\nSobA7h%;KD3#Y7cYE=OoAf0:15X#qC:'G3qqt!=s4^&-a6diK_if^%_*]eW
+%N;a>:"/T1F]TTCJNr7XG!<8O+a.Kfn,N0n-&S$qW)".bj61Et5Dl%1JjYgA2U"b92"qsaNCqs3+Du*75o1cGEhLp0U2teGJ21SAO
+%>''J:@>Ql!(osb:cF)#n?<\$7b)2u\epE%HVEc.04J\1^PAf$l?XtbKnmW*VEbR@u&`RbY.iX]#Hu8ib0PU1!lCg-`j2Tt$%f\.9
+%Enk@,2Kn0PP^7.1[0DA,+ofhI'?W7?c&?tfoPQe)Xq%E3_D7`u:5M!,Ep]PLb@Td):pZ27_*?9&VRUklM`X%V]o?t-3N[*qp4(#h
+%rXF;BZC'5<fJUGClXO;)O+$7^>V&L$nP<8,^Oq%"[h9ur82!F8VAKp-&0jiW=(3[P8r\>h(U^o:c2%MAo"KS\mh:0&Jb@pYiKd2"
+%ftf7Yoaa$lQ,`hns)p*d[kYSr.IZGFmFQ%HH\>WVj.QAT%TD?q[CG+)m$jQR`@ZBbmR`<'e[(mkG'hZ+6KBk*q!+pOE?jWi-\""+
+%N#4OMBXe*XbW'.SN^H8E/5i#$$?5h85/4edr2Yif0H#R4BCKY6f_f-sr]QWuot_?[#1Y$)]S!2j0'b-Hhr.t_Ie$bCXeu#'F.d54
+%D(ojIR/`GWruU=;j=nW(<6G39))^U-ro.P=J#TPld6_2iQTMprLG=Q,QQt]s63R8i:Hf^W[".j<pb<9WQVA1>I8G`-J4E.$`loe[
+%rhCiu<G'=?LF7tWD)Td%mLarDM%\5G_t-i>Q@^s@a?P!FA4Ikd7kH)L7jReH2pn!L;2FKmS*82NI_Xi0j8\>"'!<1OB,&\DCncc9
+%oL-f]6Gc1G*DQO.-]04J[=:YH(d^GBe))D>oX@];AJ5mYo;FT<bbMa!GK?O+TMbES8capQn3t?f&CEE[1H^-:JEEn77bm#':7NLX
+%h=r+T;h)Ooo8eb]&VCDC+^l<t,03'^ec@,_7NI76rdC@\gDK)Kn"W=hA]sO]*?>3$/V*\_<'Ml.GDG/t%gMX2EHP8V,)GOZ34r;1
+%@-'ri<ZVpKEA195O+&JoKl".Vc"VQfV=!K@co]]`UVFuh(^Vjf_>g(Kh!^"3qX9d$LqhQ=NK<q?2K&L(iqd#^>E[:;D"4n'HNf6)
+%L8d\eE,/([/7[fS=gg%?O!Jl**+^0gPf*Nq<(R&;TE[IAJ-9$)^d3SB77]-1hb&HL8&cN,"VtbNpOBqYc>+)g<JE^Qg?hpNb+ug^
+%X#BoiE@3],G8e?DB9Ri*>1"3/r>H2\,3%KGF]tB7UHBKC@=pf!)qLkjdONQ]?g)F.!Y"q"KtMF</i&("'gn[Nm+?PubM\$1`Smnk
+%$'q!,kT>Y?OTggN)5I"-#0$oV,%D<G!!=,QN5D'+s$QRKIl8l08.#t-<bk5,Sgs\W-AA&m*rX:Q(QB4/R1Pp=p-J_FkqD@us-=JH
+%J#>m;heuk$]9C>FETYs\NB&raokL&tdBLuI?*p+Mr^8:gLVO%V1p@[c^\dmK(5C=t\_ai,&8*sib=\bbCJT]f[d2.6KM/0g(<FL_
+%lgBIH,"@&um;06^s*HU(s8H!s4b/#4j]B.bn"*GW_Jpbij/S(d7dV`cr\^+\ZUk+/Z=KEmF!\.$c*Mf&LZ.j014A-McXSCVT9oT7
+%4Mf^MB.%\)&Yji"*nPn0`P9XVYE,m^?Xjkf:c+?RM5"t?;AorBYQ"#E9DC)@6L+#P#sSa.r[[/o=T1GXCg-<VonT)X\)##iO8jj`
+%m'RPn)5aC,6\:D-!>_KDRaKLADT.)61*8`('akTT2-H1=Or!.$STO5-oEbG.&<u(oDpD*&aS))n(A4.e''>5G=>1F"a3>XfLag;;
+%IHQ>\*3Sn+EkB6YT'O/i,>nmJI9tk[oP8<pS%bhSB;O?)ojm$\pWHpe@7sAdS.I9dN+Bk+2&Q8>DILo9aRAKL51Wq-]8B>a*^mP6
+%?Z$KWHr&AXlNA4CR-tFL`Vm_dppJmRc,Fo$d@I^F5=-V2>$3-3l&UEqo"<O>6r]A"(<FhRXX<im.)rNM<;Jt8`u0u5g[.cZ30!PA
+%N(WaqdIHMKSr)qP@i.pj0r.X?gqnGl<YR6TQG>J-\J`hea%^j7[*=A,%jN<<S*CANo^/a7Q[0$,8'k$WNm[If3BurKgL<$c8-u-G
+%,BV5q%"_'NA\`d!^chIM_f6&8!;%/4(&f21i[&@tdHZb>9NsBRJV]I+es@D$4!.CG&uVSU-_JPfEGHlpMcNbE+8U)QXb8b]eo_fn
+%=*c`<7kpSY-mn"E>N>.Dh8*/gqApq=TjN/Q55eae-&R]seuja\7MCe@h$d.%9X\"%[8KJ28imp2GmRjrPf:mj-f=K.Tl)Oc:uOrs
+%^iNmNCMbn6F@sk_NK9B?#D3V%.ggb38OA0FWHr_bOm7>Q"TCN"I+6Y6*lNt7mWMb@'b\A+_k/,-2#6?qn2K@/_e3G*Kq8>r2k@+M
+%gd5T+CA#sIot"\e/DJMfQ<UmhXJ-3sCft$rV=`U_9P0+\j.g>E[CW/=s1I*&epa`#^4+a7<u7*:k?F,c@_X51$P,mJfn-plBgq#W
+%fan%)XC/$]F0I08%9CpoXZmE:e_2qK.E,DKgpT7$H5nM@;3bWK;]`E0*BkIH'Rn`CUb.HBo4>qDg<0)ij4@6Ts8/U,j(2et/dta$
+%[F)JlBs5)mcn7<ClY>?I5!V%ml64UL3#g8rJ4<:KSQTgR<Egp[eIY77E`F:eTuuJ1g-rU#9'%#"_Du!k*GDB,lAd02[&G\nKkf/k
+%GhQqQ<Ki<?,dd$=2lrd:W#4#ILagTP.OcrtOnjR.Zn/q&fdqQ6"LP=`>&Mf?8tRC!X/fYYQ)+OM2!\nUjE3f@&!b2H$>M"A$X%%<
+%B#ZIQEgMYbknBAfL'mQSK4pOaX6$CbWeKZ%MdZ@]Y9s]h7I81SYh7K-:h4QJN(0)&1)-l?,\%/b&Rh\T5p]sW,Qe2>*['hXhgu5m
+%"L+rN7J65GY`aeM.lh;'5;)nQFOWlUKg@Gp<"]g76.4AJI\[nq_35%&6nT&])>g/C8Qm=[(.9u5\P+!BVYYW22d.jKV3P&GU7msZ
+%(B"hF.q`Ef>uJ`Y'j[rR].QQ@bK!s84oYrTjD*Ge,W`p&i);!*cpc//M4mp&)jrgYX%nVN_^qN#_\muDA4V^V]fh"aJgY#CZS3._
+%#a%oJ?iBi*#L30r+Id-=(=j8;$pi'V4rfVIL454FrD<g;nGT#CUK(L>ooL2Ef*!2pQ-<op7sfoITf)bCKjVP[j$tKkce:$SR/RA2
+%mg6:R\s'j8d\\P9S:IFV&,WKn7r($Q@hj@oX+8b(M(8/8FVhHp;B5DAG\>)3d%o2*0OG*ss7p)5#+Ls_9kuB-gQ(oEA7i]n<;&*F
+%qu6N[!rVf^&)UQSQ;p*<o:LJMJ-lG;&%H*R;qU]]rr,Cs1H[(IUlGuYk:'/h#@D[1aC\k?!%gs*>S\kO!+ESBquLIY7$<fN\97fM
+%62^+[pa]DhXd!OIFF28PCI$),aAu:PfiNudbbi<u"eW5_F%K)@i,4)jnJ?*ppQW$0L-#%GoQ^\*[g$;=_g^=8Y\MDA?b6cq*/rX'
+%5G\;:Ri\<AamV8NR):fm3R12"B^U[]0CXSGX]6AZpZT6Yq^n(Z(.Mb`BA('gYaaO#h#.1aF-B)nP>pIj(];R6Kl`B`F.]i>r7`LT
+%Ut9J]=,9('OihW$DR?^B\,M\7dLQ)>m1@10J1T!EN&LK+8Gs?'i7ZCFLrY+hGV],bc/q6lg&+E>'\LW#N(/DU=T!BtT0K1M$MmnR
+%[#"1iDPJD4@/RL/3be*'C"7u;U`H&7g=+5b[f^p0lm=.:ec$mo1JZjeOgR_:rPM(ko&S&Y#-[S^^b8SR7HR\`<b+,ndNrP$Q*]2;
+%1TPY%/*5`'2U[^?Y#$1We^#>>Q"oVLe!38+40@&F^$_,*kZANj&%R>R8o6]0hPlbE%Q5&&`faY@>I$U9_d$d=11`kmLmTkL.OkP)
+%/ZBY=D:uKdL)Z%b8Jf,$n<d&^m;(_ulE8lHO`FaeD3C2J\MD%I`C[O'lcD_.OK_acQVcmd2BC&>/(ZXtY0k:\=0>ae-)=d9Lhc4F
+%[jE1T2+!c1QY:*0Mb;Ns/N!&72N]NuIgqK/5=C,+:EZJah\4eOchaXO?W8DF7@qI>KFpL"78/Hb'p\Ti3t`1:TTuD_+.$$B3U-fk
+%UTO4#'AZH4S4a&>ZQ-2+W\kNl,]gV]R8&J-lHt1$'g`X%.rBRM@pCSS7gfBI<pI)!D9stS[AM*.^25Yp8'Q8o=X>FTe8Jf%\C'W&
+%&4M3:k!/&hFO7&@e/1c4*^$bRE0&ES&J[%Lc%4-ORalp7XIQ]tB_?&f$E\bgNm"gbg,ZM]PKKte2R5;19jRr#S[Nu]fp&@UTjM^q
+%bN!$CgM9rY]_gnN54g/_q.Y_Po0iol7D5`^)7qF6Ujctj_5EDYPub(fRj'=G)`DFoT[jGKcB;+Hfjf8/rA^u5WW$-+ruq"aIG.O%
+%BB]VrO57,?XIR$G7?["rS)[)%Gf96?N1j?j0Gl:h8p8ud80Y1X7(\/mK!Rb\V?kTmd"4*bR#8KGImu^mpL(Ch$4KGLR8&6h>mlXc
+%<\W_E^hL/.0H<?Ph[+_hb+^Om;T18_-7+dfdkZ2"8m!C[qN<U`dhUAO2!3)EaM(mI3\#gXJ[V(@cKU79e=*LZbIYBYd(m]VZ4L2$
+%JqC6YUHAB#jT_h^%>+B"[hTXXA&nnGTZOtap;uU!4dZF$Lj`H#%#QlgUN(W/ZY\338?kA,+/uun>jbAe/(h%b^F$jA4%Kbcmc%`q
+%P2[lQ*KIYQp5f_.07ZW&`#i/WrMV`6X%(?2=roOk=j<n)HOj\mc<.90Xb[q=NE'tm2FU,,[I4UZ6bAr1WgU)Li/,f9603f$6b-g0
+%%>p"b5JUmN\FA[c54)*l#&foLJ63M:BX\lA6jb`Y.&2nHXAY$t1H7glJY_>3:(WYX1`?Is_aqq/H4<H`@'_^gXO_.js55I&@6o'5
+%C,kWPD-<0umB@Ei'H%?-?#(X:;J<g8;Pnd3;St6IWGQ=Wd2N=%NO)C>UTDU1P&`CL=r\G/WN\EAPp&c,;%B6e]fYW57X>)L<Z9;Y
+%2Be>FM@QcQ>:s!Tc=a20c.8]F);$P8BJ^3.PLPIjT[:^j^WL7llqb?)C,_VNA%!ok'iO`V*_iS>HdJ,Fp(8\%8:tS2@U3(^$_f*j
+%#J72k$3ZhA-upH%'[;N8(FUVt(/q=H;s-D7RNu^kJg7!Vp58i[g7tK6US`<t:lP)rQSWOk'nKlJA)3Igao^P2`Z"lWAbW"5A0\%7
+%,HMrJj97XT3\6/<+YET+!!e[L$Ekk4R#PZgFu5mK*;OMQBT+danY?>jNQigZ,q!'U&Rq#X00Ak3\c@]r29tZ$=?f9$JnfId>72/q
+%PUe8N3`gjO)+D^KnnBC+Sru$2^gUp@NhWqAUhguHM`@ZZC_4,eEPh(t'(8HDbe$2s:;%rRVI)brVIJ[b+iSK[9?C%<b-fri_W0L)
+%(+ai:K%^Af(b4C/Q0nW6E'PPPr*MqYo0",g+R3j'j3Qn]IhlV4*6S*:S)b7.+N:TlS"A/Z[3VkS[&Cuf]%H_NRL$EqdHGYZ&TL-]
+%>8B\geBSXW2EGj.O'04]W-*G&Z;[cEgMQnGr`caoaAUt@U;a`F*U;:<"t*j#&-!W2=K9j<TW'si][cWZ6kicrS4VgPO@5N5n.3M7
+%Z`^<KJgo`fhJ$gYl5uf:UUD0EfUsF8==lIU>l3W1279i^/Z,tZPI6(4NgEXFah^S9:&]i/*tF$b%u@8t/LT:YA5u^GW"I2^JJQHG
+%28[m&F(qb;,,pYA>:<$?iTdr-56i9`I8M7*3(m^icWZe81,hToEboI4.sr#r4tqYiHpqd^[-OW6f<TDO8/3b^WaA.%O-]7\iV;_4
+%engo-bM"tB9P[t\44L:,j$p&7"dd8t[C8_+p=dNfd1gaX#5&=+d5)YZG@4i:91ABab&K%(02*W?C3dseRi?`p@m;#;A)n2p6n,.9
+%mROgp.Z:a^GG8Io3fSu'frX1Ym6;BO.p!,7JZ1-B;kL"t=e2I]]/h@@<*(BGWq.R9>$S>CN3K:a.,N&35iq5!A@7UoV.K*V@'q?1
+%+Snkn#`^%h!XV[I%E.*LUn)@FN<@83am,V.hR(ZL7i[d(4";gC.P7$+NOj(Qdcg`-Op&(-e'd8;LqhZ(UHNLCc]iK$"QOY_R]XCo
+%<b:VeNqE@6'(Ee:#kXrn[PR6\78mG'P;X_da-!R0MYGd9T4g^+&h)5;4u`"hNegbY7(f6=iYA!qYNUde746#(lA7G6'UT5]\r$UT
+%'m8#A9obs>H<JgMVDosrMGC*OF@*Zm)>2._88K7'-==S$q$N/'=)^RAJeR\i*0IG_KR<qJq8R9m=)^L?JrY5\ku#fk02('H'^$`K
+%_$ToE:<5A)7_U.OMf!<Kg'p':h2il8%6:0=O;$=W3MP>k'A<m5BfF%j,uI``5eA0[m910585Hk+NH<Nca9h6ge?k]!0A78gGUYai
+%TPuJ4hmU+R`.RD,/p1kU<$'ReH-hScU09mmTpDVj6B=/OoV`EiNuA^C]CHH14K>/sQ<-mi>".Q(g2rRKb+i,i[m"S)-QG0V7__hR
+%$JYDl!Z&])CELq:Yg#p3oE:]FXMDlU,>JM(ieW+0:'`i=OFSQN#WSP'@$ZjA?^dI7,MWDAEC.I'T[pS`[2:Xc-JFStb`(=k1)/L.
+%C2+:4:dIdqXs#A)<s>#M"jS/WSiqli,2nn&&rnstiKt8kNp0(oc;C%"KO`d_*-4H`0df(CDFTjIMi_duXU^J$L:*u'lc9]O2<(V[
+%'.2"[`)T6jX$A!XXt!Zb3UV]lj%cO5mZ<mt:8g1UULjlk<%cEic#IW9N]Wrs\=/k_n<W+Nf*Z'd=j[3toWDaO]rO'Y%l?T#!J(J[
+%qW>Z_DY5[,7/gEfZ,$4p`.,Oj5<W_fMuG4]F82;SogK?ChtQ/TiD;>d8pLX9TBYCXY[)W@Rr&kq>>HEuDd*IUopq2sRmo3ceRJ2*
+%20qj6*b5.=QY/8H?6%tE:k._$VD>dRAHqhQK\"iVmUo;`$>\\lJU:G-bFY?e]H<3fr5%N0ZuD@9^#(8M2UhKB@c]Wq,jm.l]rh7H
+%OXDmjY?u,eHq_F1&+=c<8$fs3cYSXp:(C'`PPmm`pFb\#'Sha3gVWa]0ndR<:bD*Hp):%&/2A-NWU00)#"QA]c[,<`r$mo`*XFF`
+%"5u/#?Ydpoq-<1[Kf+tjOahS.g+EPLiqhMY4ubX:ai'h/*aG;h_al0l]iXqkg/TBXc*p2l+]COlcLelBhYX4LSWd2?GknU+*_5eW
+%O;M1B*St[5ek'9n<3?u7;fAeBrGo0,NGXTSLrMtIn&*'53'F78V;"0D$%^EeC7VZ^\^i$'SDK.,__5rpWjTAPFm&[hOkm';F_gG,
+%p+_"&9m20JZ_Y+=J)p;m-K=)+NTN,2gmKFJd-`9qe">h/^H^6?530,B5*''rT<Hn<*lVK]WT2SQZd[P!M_h2.e;Lci=SMI/_sVWu
+%m2Jh(c^<O&=a5t.MQ'<NV_6;+A,AAr1=t`FYI<st@!<OZ5B#qH*VN0.Mm&8NRo/V_GO"b_\d]C\VhZUi`n&]GA,i,lV[ou)@f)n:
+%l4hKSouOi4'i*VcXLX(G8n-=m=2i5Yl9"E5fZ_hQg-*+g5L9&LT[PaER!r+b&)jFXi('=B[LK$S(<Y'#b8VD3:8?59gPFCZb6-S7
+%NF+jR<SX^]e&,???<e;6S\?/X?^l1A=qCMYcaZo?a"Z+NpWI+7UNOiLoIB%]s'G/dYr^]5pJUmi:0eo78t-'HLR7?2N]]FWMTO3K
+%Zd[H6-bb&c(GAp^L5IW;7GK?5(]@TKCS%`GH-WM?>3KYsrKc:(;(/cuo#2\mSYBH[!`.FV&*R7?!^>EA+'_5-a8ua'kHCVWe&U:k
+%=ZdflVn7[Y9<DXh\e[PP6/@7sqRN1\4k<:fNNL17R`/@7:@k1Nc'P6/;jW8_Hi0Eqr#B'K1HV_72o;G_T!g--O@c?GJPbIQO*EF,
+%Y,A,I`RCU>a6`GAA'cst[.850?Is=WHBGd%$Jh;6G1iFXKfqB6_qdJ!Vk]GUdnXi=N`N&1O4dbk6[&d5H$6+Kqh;N2X-XW7V_=BD
+%a1>#c0=9K[LM4#-dckfsoJ5Y7fUZ>rNr#*a7$uZlgMpVO:8QWKa.CG>gSE;RRo#g55@J`(\-T1I%poAAe7gmu4%3%@iC^Gcp`&V-
+%*qnn0NW8OM[Y['\2thYGm7bhmn!g9bFLn[A'K,a_mIEeA5IR>"Kp/3SO*3QIf[A$orEO^?P>8Fp_QfC=DN?/(qekWi:o!\\Y&kYF
+%k.3&[=CGo$7QN[D:'3PF\ikpU&4mOA:ZY?ZSZW(XYLNm)D,rmQEMbUXkVjI3FZPA.VPp:N86lCAbI]fO]iU%aD:RKP3pe+p](*KE
+%;p'=?f7tlMIr"cN,?0!`bZJ4$k=;U4mkq)(p;";*UO#Z#ZPD)?N?s6:C#"oUK`:;qA+e^?1&W.H+/b])^F$nDlZ_s(+19]0jf<:<
+%@VZk/qq*U)IC;!m&C%u@0AC3l=1i"I[EI)i]jt#&;=^#rD^OO\HfI2eC\q_E.k.B5@5Xn]>!JtpU_RBe^Wg\FND71EH0RJ/o<6L9
+%e=Q6]Y[['mfD)pkmE]Kl<&4FKFXq(-=C:<MotQC]Y@b2iFKa+ie#t-.AH1NYCL^2ES=-RJfBk_MhDG17aILjdVI*-;K2oa8`A2=N
+%h4HI%*A)sPH^iHR;nfX,lW3[nE^7D%K"LkX=fT1XD._;T,MUhc;Qbg9QO@Wl@ai`j9<Rk`Ki#q9hL;c;%[;,!UUL%c,@t?X:!fk%
+%]PZP*1=`Df%Pt(Xot2.keAb:UXmC"IU&"(q"*;#;ODnQ7B'.r49agCVr:QV-qt@GWhL96@h7b9:%/s9s,l!XG#>X0N+SYP@iBnu6
+%'s8h/\8tlq4ro*kf&OmGDI?Cb96TDiUA-WpXrXB0_J9'\CFq#1c.gPQo<3s@f932o`a3pThqBW+n;8Ma@*h#-lc:]8bCR'dj=%L0
+%auqm9jcCe6/r@fVqYKlOD2Us*p?]AGf&c+@iL:4\`T#MK(S5Z"E;GQ(/k@;'m%2fg=p0uEi0qj/EBVs:9!7iF\b8U(kPV+j8,q@L
+%bJYKL@1]Pi,TPRNKM"QEZ'VG%#0"q\1pT]/#5fO`>)nJtfT!!s7$'T5G\hc:GIi-DJ*\n5<[-OH,OQSq+uko,Ic'p'>N5At4SA%F
+%(\,7JIEZkZX2S7=2a#[L6H.F012Ch]O+'#3(\r:0iB=hn%IRmmVUh!ULNdjJp1V']M3<Tm%"go(-4TF4CMPRuDgBp::q.ssK?L#r
+%.be=rW/7R1SaKZr>LUF>Y*R(*WdtEpdFWcXRLd;t,;?N2AZ!?<N=\oI79\S"S-pe%nootuA)9tC]s$gH.lEh4T[OKZR#j9hr5a:S
+%hXDADU:EM2(E2CM9_'TTAqe5ll^n#$EUhNUEH;Y)9#XpdT"_ce_hu]V7/?^;r!aP&?cce7md72emN>NG)_\8+8=S9cCnT0V2IV8)
+%4Ql[*Y;r;Z)QeXS>'rZWe'$OJm=ART>0U#mmW#Ln\DEq(?8TC*p<2;9'kKSfLb@)$1JcM41p62j7k=$OIipe^6VWhUeEk#9/8kid
+%7NS'.7I;r&g1be2ImD>Zp[<,p-!3$Wqo2'd]g(ED%"kU99;[>_H*kKDZle.XBC.C$@]C\p5qSZRbZ^NVmfrXKRS9&mDD]gbH,tZ$
+%H$-R&h:Pi[%1[&fOkhuHpOS,^E0/WVf86&+2>/r5T00\6,Kn2eU_s)l\8`'@L7oU1NEo,gY8fpKTCQA4h9J#dQ\Vgb6X_eJ=UYVY
+%kiZCLn.Bb%YE'TlePHqHWlH@_&_Wrb&j$LY<tD;)nYD2R.33AQ(--6O"ap;]/Kj_J-qhXpJ4NIbjBTJp(WZ=lMV6&2aW_,VngHUp
+%k%N?^*:70]UgN0/kV["d`ea5UXE"?]F(EC[V):7oog7!VbhXp7?VY#^Rb`j]G*6Fm?<K(/9oHJu<dX2h&!^o(H!$f(amQnZ_X$I8
+%1X07.D(t^a<=X?:I:95060d`_)(V$117f;G^%;qdBJq_e'ASuc8^$qs"r3YL8;d'i%1:di%ng''O>8*GN__m<iRXTp7*)If`-fOc
+%dJII\@U=ahe`R`109$m,I!R:YVme:-gWtSG7i(LB.M%r*U0Tq@(?s?fUW!=BiKS-0<'o_08Mh_<O$jX.]4#^IHjR7HVcd\ZB0g4*
+%[X'R[Of='ZP_l0Hdj'.t,Gjcqe[ogM<.4a^K&"[9GOiT9Rr'JL!;DEj],>YqFUg#okCQmMT3/S$+[`8B=_LrFM5cWWlnp`F(2`\%
+%QcEfu8N2uR\Q@Zf9//6&4Tb*OM5=bG0e[YGo!,XYI7^RpHXDpoqNg`$8W8KO[8UeT#fV^Zc8Kq+/fI5,]XE+(WOLTc-utY"D>2HF
+%E&ks8g?dQ*T.T29.>?LP7Z"O;E;++QQo7UZVnnOm,ker0^PAYeg[H<NV5+\8$pf,J+UG"C>fNTk#-l`l/dP)Y2:c$?2cVb@*\i$A
+%TiX<YbFt:Cm+n9TkcIEfI`-PT8l*ogFm]tHbtM:qLA=MDb^o;#]j_MQhIWe@rkt&okg#*&:U)d!6juSNJb($>Ch,@NLGlI6O<-l9
+%81r6*lX\.>PTdRs#PH*3c"QM1'2tI:;du]UejKZU?V,#dT!"nZGC>nSX#l,Nlt')@k!%e$;?$4[4"FUgi(cLt6d:To_4_I$@tg:j
+%s(*s)`W3*AcHg"V?K"gCcg[aH9l6+-l;Q].HnSEZhJ>-AY0P+SFahSgNFqkce"(An(q^36lioj#gp$"+6kGb`k]r>:((YfgW?_+%
+%k$km9*sTW;_hFuLnL@8tf[Pa9mfLW=Ls+i:Lg)F'[0o^f@hocrcopg@FcQX`6uUAD?KO2`:O$/Y/fRk^GWk.m?eC'%Dr7?+K6l4p
+%C6?hrej!$W2NhPC:,FcCF2I60ZX9uuGKA&A@-^-HV\1=hm6p"-=2C!8X<C0?E;Y/J1aL*o1m]7"+:fseghj.cQ)OBemu,"u0Vp>/
+%5E5r<>cKCg%oVL<^-on@Lb9uQ"F#2"P[<;?:"`fj+UVI1>(#qO?Uq$&*\OIRn_/8e`Ksa$PfHi7IjckqAG6UP;Ehh.np<)-0O$:3
+%Z;uo-LY7,L]@1qBj'eN;hB>`HM%$DtnU8/3"$f6%T/C]c@^f*%Hf(@QPoD657]k?0[o(qL;AS$Ic+L:_!a86dB^#1*k6Dg\,F_uO
+%*L6LgiFR&JH^S@jLN<1X258]`(:gjT_VT:*?!(ESj"[:rpSJoTFP33l=LR_8D=r:=AKs;T#3GS2j6d9'L;B43/.:Y=$0LF7#a=ks
+%4N+I`I\W;o2i[V8bEKYbnb'A5HlB*Bh8eijL!/li,)80HSHD0%?Y*M%WGm7I(JZ;&:`8c.9UE1V':)3n[(7bE)'NimP/n'@#3_P*
+%7GH2n9HekHdN8iq"j:I!rG[7mn4c.?OMJC!/<3;LgoaAi!#1.-f!<Z&4RCNYq6IOQFEokAe'0)grG#OF#.8%7E6c@!+P(.oq]=F.
+%I^3U,@JOq*>klTO7:TOk?DDSDBJ5B_q'IX3a"7fl-iq5-JQ:3*)f'U=$)[)MA:TN_+br6$Nt)*L\YSB*B\E+&rU#cC#gaD/7IQV9
+%SAOmh)HWFAa0Jhe1&Om-Qo9nP7'?@M,?/`BK^e1a;>)"_J]9Ze/mSnOh,GpmMf[]3BP<>NQ4XMZ1)J-AeMA7nJN'V#rb`=QXQ;.Q
+%Wj#a5r;;Pn1;q'iogH%K>ZcuQN_jdIC.k(@F,FNdIU=-q?qFh<[X'!"Ne[bY_H&5"4FDqQq0N^YXJ`>=d`!t0F4j%ncRY==`emlA
+%H$&R]^m0/T-').tK6snbK5F>$Fr95g/6_TCSe9XoY`cXGiCKgcoPM6_\UVA1\c4SMQMY:n.WqfoCj0]PQ8lelkq.6d9AFoYNK+QK
+%b&MEY8OWNcBAYhseR_;>U\4J?g&$P`RFgnYfB]?(MlG=35-aeW=bMsDIH-tg/16Z]iu^Vro<l/'[iu`&PhY3XE@[aq:2Tcj,%&Qs
+%E7FOW^b:hpoeGiWF5.CIKIF[jm6Ifn)[4uifKou@VPbERg#j/UMGB:.F^MWH1R7A)@HMl45KsBF_b4R+ABo+^02%gWgk!;l)ka):
+%mQ`,sl40=0$PYRKP'h4eIsb;UO!+@$"K6GQj/jJW`,;ICeSi&^KuVq7"6NJ]9]e^V<nT\fqSsn$Yc_mYo3[&K^emVk.M@8S\Pt-s
+%[O,Fd,%kD4TCq524`JJ-A0,!VoeDAfjdcra\Z8\t<R0^RPoS-,K)puJ;7Vq,e+7>E28D/;eRETTYM:M3B>[tNa\eG+`?TSkY?W3L
+%R>Vq`G!&?5:#oem%ciW)J"4XV$.M4HI/Bf!B30L$5[LfD!Y5Q_CH((a<lMtD%55/up)TVcgOl/kX9[qZ8A!:$6cdptm:!D;]6:G:
+%moetOW=092DV2jBnU[@:mPtK,BWQ1CFMtGl)W8C+g0Ls;at=201jV:=gf(NT2ulG:]$n/f3RZab*ZO8]En%(?7e`7k>cDMtm/A\=
+%o[N(A5l/D'UWVP5GBsd:h\<LWS&*=FE,^S]S#tri/DYH-bk\Ms/C)6nRYtV`R-X31UC$*]oCgFV+F/]Ja)\h/>&/6`21T,"#"0[@
+%.bG^uWc=quZTlM"jM;_bQn^Re*i`[(49JuL)[erWZG&c&a^pM?2S21(Dn,Ts]Y)]Nl@eMK9A\JAo"e69e'l6>>(DpJ(+)4F]OdZN
+%RA*[dXWYg8Ksj^g-2.IE#EPqG`]6oRL:]\l,aT82RgY9dZ%*HW,PrZFJf_?*AfRqgBrNl>R"60#fX>;6S@DnE6"><nb3P]d/Qr@E
+%l(W%^*4fes+*aklSVNB9@Y(pu+e^3G;0?4-KH9[&Cq-tZ[:is9KR6.?ijsEu)3Q^H_V1buk?W_Vg"nq9CKQQdk',k:`M(uL/[A,)
+%1PURD8(L*2g=>O.7IlJm>bole"u)DXc].paYK4TJ/EgTHJR)t/kJH=jB&'A:[XEu1KJ&>5;qO4l6h'T_,[&tF?&N`5>d3uJ(;>l%
+%@h)\Lb1<>pkOS,OaJE*U:B@:p##G4jRR7qfbmW@A)!0(qqnbTQ0"<QH.dI05_NtRbjU>aJXl8-QE,Du_=rDQ?i0CjW9MWsW)S'Ku
+%M`EaR[W!SY[<;WMk(6huaE*'$OtSPOSRJ\\r/r1mmXL]4_U=s/\X<\O]$HYE92Y*0FO2IFP=$-T?t$HGi)OV3*76CIM0ADA^:mh"
+%;e]"eflY1C*#d.8.u*)kQa1)/X@J:MOn:@a@[QXVC%dWf2KHpMNGLX$h1_LN\s?is\6tIVYCcG?C]bq"p9eV;)n9K8"O1n1AF)Xr
+%7r94]Jb1ZtR[]X87uo[72o<g:UL<QVDf4so`#L'"Xg^@EH/X"'a1#KA=fZ#6bp4BGd8%rk1U>P.2r`$1a-0q_GIe+e7.D`XZ5XlD
+%*[$f)8YIIie&V'jcq5eVW"HCQYeTSe,25Nn]`@?P4p-G$"k4W5PK]6g$cqErF'2?K$_8`:9[%U>'2o_$>b58teao6R?7FV8Hh[Cb
+%98'BCV!so<9G>XZYd"W/'3[,'J1QTnj,^gV6UETgqW@<L!>=,/KuP3M%>-Es6+%bs0&$[@aoOQP%\"o;bcoL1)f<chO77UVJa&>8
+%hZ+;3jmD'=ml=t9^<HnW'tCT,\i^sU*bmF45A6'T+m=*!FLi/S_Pti:YfM]I\AH"3Y[&;3GkNmj+h0WgW-M1.!=<TU`lQ6V@^f*R
+%KRb6Ueg(gnFGZt.Zo;$9B/N=MM#jVt*aIhj18%6lS:Esg'X!Z8E+q#RMJ6<M1N/=;9XNS^;Dqob[_pd=Q4;)M.>!n:Qd*AfNOdOi
+%5n,Mc_\K`\&SC-Z_H:`/R6<LW)p)E&nL[-)Oqpcp5HJong"h'Ap.M#,Sg`+\md]92pbNJ/[`igPkYX6C)$l[;OWPjBc95iu?q2g>
+%?=^'+W-)jR@h`JWqj=5IVuWh%*u=1pWsq"TMb3OCLe1o\^C:MdHf49h3BM5G"5<EAc^7BX$]aRLJ:oi9[EOoD$'oG%Ub.HUL>g;[
+%&*I1K"jmNAlS6RO?oPhP7gVd=j9nB./-jLXC!>PTYs$tIbdW=F12hI#9Vl&bqTAe$$Xc;Es)sO?*>YN:j\MH]B7.gb["[Cd!<^si
+%W8]([+?*s*%MPAWn0lSmCj@(5K-TXcdtTHGb&VrOKIR0F0-`Ci6$b=BK$Lu1]ZKVUKW6%*P81sPOa^2GO3e^oZ-:]i/3eVG'$GGq
+%SR<p"*[X<8bh^^dEc(JDFm>otIfZg%a!$bZEiHm\nKnRLaeaaNbKCL@Lc2VLH#=-!"u#S*AJYU&HV'VQnR=(S/-G$='$KF"_t/as
+%-([aAbGsC5?`mL[)_8O4.UVrm&WqY%k3b"X8ofI[PQ8OBk,UoYaSh?af7h3lpX'hmGgafVi]ch9#BP`fptOHN%:X43S"08<0BaDM
+%BkP+Ga:M.CX*'p_plh*P$gJCHY9-#4*I7U"hG!taCX^RWAKOOEo8NkEgR,3QN_iV2=k"flcT_*-m-Jfd$*RR\`KRM+[QD2o\cUpF
+%cecDsb]dL,G-ZF2jgfC[[LhhIq"aa)QGOO5@oqX5p$f2OmDVlu]3D!,/)sGKc>W\1[I8E)%[cJf@&D9*JOJFUq,$`r2&"G%<3:ME
+%)LUR0n5-O\R;*?D[If6SFlcl"+*jegpIr!f>ipL6g2nr?IAg?D9Js*MQMs^g%`jQSq2'm,Fb>><ncKD&ldjACq2pH4Fb:nso$SV[
+%eicq`kO)I?6e+5V11[-SJVU7JcVuuO*S\CteV;\\J)m;<h/s.Ngp6:%WccWe_hp&8:c0We(*g>Us%p+@E5i\'\3\JHckg.4o";k%
+%a$\Cgn9lmoIVB<m;\6=sTNMbZfC2To?bGKp%oqp,\#/\*M`k%a5c/Kb<6YkTB&r;^"Q[iG4KaaS>kk"-?9C";6e0s"-ofHa?l`Bb
+%#0nPXGp.Dj#<7(Uf,<*-C^tNN,Au9HT'\4LHs%7J7WA(V/*87q`?IN200G_68:Z%m`ncY4387;R;`6b-_fZ@BE^=rY[F<8,Q0&dP
+%c#J'S?^0]-B6,7=(PHF:V#_7"D2c)G%+"&9B<,D<RhMC<!R<UB=RkE<3Pa=n?7fg,ZT2pf/74Y(K4f7aOIZ9'i7T+.CnhL#(nStQ
+%c??cPI#lK4fb[D.[Zc--+.g^Xc<ep,lo*d<-$.8bn8+,]UpgYg^p>&q?oTMrRff2*JZa-_2iS!df&9r%O>i.&cF0N'5'Su@D'7_=
+%bR`$S5A\-gRMB%=DDM_]Ha+;A5,1"(ME*Q-c#f<ViRsYCZ-emRkZTbLA`RX8)\NgRi!c4%!R>k?XLGd6ZNb&Xhg)\]B5;/6Ee_68
+%Hd?.=DeH+!f`oUAoldbmlr81iCj8+4CThR3cF/(NI5u4Yj4GDCTj56KBBu>AX^9=[%W!-2`T$Q,k;[5-gY);R)j^#;[P:j]"ch:[
+%f23<FrAOLWIQ`SmFF!$=lWGd3!?#P5kI4KJS05hrj8,'u)!?\p?34TkJ/%tp`;"qf13"MX\Q3NTi#9j`Jhc:MLDZWgc/BWsDM>0!
+%*b$+8OYGf[LDY5\oN.;BJJdR/*aB72mP$HLS;;16h-VX@HoW]hLD]3&-$(fZ\D#g>3Q1\ZaEhaB3"O;DEQ#A$m-%=Zj*%]&b<_(s
+%<#W`7ru>M'EqboT(jBtiho-2f$8)X%pQ$K;kJef.6B#,]U0&1?SC6%Fo<g7`j#/a&,fD\9NUPQ:72A=N0DK-B-XtkBB^mG]j!oo0
+%Ju1++0s:22r"NUFKsJ8b3Q*n4A[)BV\:YT<(I3rFYmEXI(geiK4>1069>2s9(t[3'nMXV?".9ZSY1I'2"u-UZ/+oZj5D'g9bLs9O
+%@bd[U1+-NNEi5D2od(g%+ZGYb%V>HlEG'1sc\iWQ7,7_@@XL0mAjhTa@n4cT7>r#F5`G$8C&JHLggtSUrW$D4040/41!]Z.rF1S&
+%LUkps7#WpC6S0<5^'"rQ#@^s0@a:#X`YgVAFKtcAc$TP&l%j?1$R!V_N3b970-;odpYP4V&EAf4r`k8!$b=#?`&Pk`E'NMi_5>th
+%F+`saieo&$j`jG$GJ`MP^=E(DIgRpUrIWupLiHANpeh^aMLV_QaMknF`43M"[g^3bmR=Q+6B%CH2dIb>*.-Z>T=F&GqZatuoB\+<
+%1!W,:=3V?;o:a&:Cq.[[F6IS>*:1jETu.UqZ-2`[k]#ju/.3K$_'Ass3daST&<ljNIg-pr@)H!/]QA8*1,p`C_,$`A'l:B+Z@5)]
+%\,fb4,Ns)XE$i[&V4b_kfh3t8rWG8el',d@q@RhZJdnX3`K-\0'l:C>?+CM-h!Cm+jeBX-Cq'oqGp.:>dAQUMk\tm]fJ:h4g7-$Q
+%6AO=.@(7J(\?Zp>=G8&r_bGOq91=UdfPnkCh%%fjHkG1mU;PLnh*6Z)B37_iJ.B'-=\*>;&3=(4L@b3:k!b'ONT$GWoJEt<Q[fQI
+%[L'^ar^5o=q,,K0"gb0!^b6WIY2&"frgl*I+6LVjiJP=l>d5TK_j/^:o)'Ig>bOTgVR0TM\:P06H%$5DY+.NZ1\)4CE.oKXYEggV
+%*Nk2.h)ciS7>EC(8:7X+K+:u:e)sS5-9>DJL>,*a/;+Kll7bGR%X5K;o:a((p18O5E!71u\9hL*3aC>X#0LOlk]#Vpb4toW5_gj_
+%a[C,$#p$2"@=A\,^=7NHU%VXMflAOlYK9F9=5P5Y![RUodn:c;HiM69!7^.b>VhS=;fW$%21NlHjOgnR.T:#0?cIm-VG["=^4pjC
+%ja4i+<+bU6of&E-(#t4Wk`d&Q3NZ>@O/(C3fNW<GS6_S_=W?k1W(r@=fn:T<%S>h`5_F+R`inWg6sJuBGF^_\F;Ngl2h9NCYgZ<h
+%I[I/ZH=mgOrP4aA]0'\orpa7X0.^F</f7u0$b_sEA5!tL3)aX2_-dtHM'\]NDBbHEMd313bRDm79#mI5([lH)N)nA903DF<*S&5W
+%hD`aupb\K)![?/-]Y9UHm4%H<Yh+U0pVdnED.Z\!h'.p"gP:N/>YZ[o5IImHkh>:lQ'f9?2!LAW7,dh"L^.t>l\"Ss3-sH+9Xp]G
+%rRJZHjh>DYGf7UBOBhaJV8R_Q:aFZPIS7IO0BnJG'--JSN4<ji-pu.@H.GPq!*iVI>8Ir<f<&:O=tG^:YZpmq3mF.=QU[mSgk0b\
+%G+)`3KF_t/ei:+[AP5+a/$<OPq(kd@(3pE/LR7OqR;mO:kjtBq8LrpM7ahEl9fuLT$bu#*%#MsBWN:1Ga`i\A27]iD61NbMEJ4LX
+%(YBOM6H0G*1"rqS&V7d'NaLMJ5Y]hd[Z&f'>d'f$X<k$,O)Y7Yd&s7UiV[fl/HHb)hNrDf:G6uhh"Fp,GM,[.0$?UkqfoU1C_<tS
+%1_>Ck.B44SX`#kR`cuBH*'CN-ELnq;d$XXrS.n(l)-E\nph\X%rlVK/]FIulTCZi7M_&Kp`_?[h;na)-Z:o"kOV[cAlEFK'@T,3A
+%d63i:7,,OcgLYqDBWUlIc3>22O\'qTZd57a@.M:[Qolu2Pm><2k';67,HJiOE(S^3btNGI40O7\j5#a&*ganO\%WPm.``FAXY7S"
+%_2Dk1O>,OLEPs!`Qd*<)=[5!6EhgOEVZX'\VJ395:jC:MNC%+rGlC>QJ0u;=Z'i5dikQ7L+V>a-R"Gh*,t98u#fGG;(Nu`pH`S+J
+%qoB`6gPZn'Wm&JnV1g=+e@OB2@/Zh,*A67Aq8G@-CtgA(=Y<S[91GHiN3pZK!TGZb>oBE0NXj:Oo%e?)Z6EYI^R$43CTI2UY9oaV
+%n3]^"<Lu<'`k4I3@_&pNkOH*e85mQ;T"gU;Q><PagVu=h\IRL;Y?87+OH:j%(DP&U#)dKeb7Vp2Yo'EPrRHQgZ$aS8Q9i-eLB96M
+%Eltk..[JHfDi?V"$]*nkHa1fj15hS<hT!#$B>C^_bY9#ogru#p`eiK#)_Y4ZVgM>HnWmG$l[a?HN&`HZHO'9UZ6aD"anC`+*os?p
+%liVjq)=;BirSH>^i\O<P;J/*Y0TXg]SkC^"/1R&8iBm8;_sQgHCAS9A^os6;(%jRe\D<%DQm>TsF)g8hH/NlsR]p#Pfrn2],r-Qa
+%I7NjgEjo^+[[<aW7aI>eZ1YomkLU%mjn2MuZ#pfgRZ";78]NqV)!,7L)N6U/R/Pj:G"hdCh3].'9=t2%^CaN:XBMRk2#<V+,;@>0
+%Ha@da%)?.[H`^BU:?C*hF)fZU.5@/Y`g^n-r'KQ<mdX!-Bbg'-SfrO@pBt#1N7=$J()5(IZb;#raBdS,[>MSMk9-5NSZh7l&i5=#
+%fiOeV%*61(1lBXhq(Q*fRK5I\PR+e4Zbg#AcE0678;G;G;RL,1nQmW)a5SB)hX$3)Fon8"2gffjbsZ&GPE4apiN0IbC*f%4#>aZH
+%X7##Ihjl3&n#S^c`_u,f]=#<7CJ[%GBRPg@Z-(bo>PtOIeiEYS^\Bd*<K]q?kMj&EI9R:QVsVXI<O[0nZu\FCI67#shVN9Wrm-A`
+%k@ME@Q#;Yk*Y5/Y:W9dt*f&A'X2EM-`tMYV8GaLT)RiqmX`ND!pNlij-,*aTAO=#@X5i_9WpJSi3BDA0gg]u_\!:i!%R\4^_1&=b
+%]dnhteqP!7UW\RVn[NoW(sbD>2^TKu(\M22/=FX[eiF`e5`Y"$>R89o]Ut&U61-SaMdL=0n2?_L[>MuNC2Q>S"d_`GEe2%J/J9]2
+%]=k"eWu&<um_]CrVSq3.e_tD='VW&Cr#=>XC\B7PKLk4bB)R((3/CkMmk.AECmJc.*aIUpHLAuBM0(E:.9DO)2Vot)HUtV>HI$)7
+%?<MKL\l1fnLjX>\D^TK/_i#V6?XA*T';#e!4C!RI\+-rtUiWgW'!InY1@^^K<rTUYE.=5n^$P%^pkV;/Ii#O,PG$*_/>$0ijn#N:
+%(8^bGc?LmHc5#jj&pr*`gdg`%!U\Fu21tV^:=I?!^3$4?=BVK3GU^qngE3'^OQrRuhEJ]dGP_HL<QK3#!e7$%JP<T?%d\FI@@QuH
+%J\fmCH`I`P_I>nhf@B$nQ`!XjV;o)Qpg#l/"E\)ps"3&Q/UnoBHfmc&>2)3q/[\sVXmpWtdiY/Ud&cZLiO<DRQZ]JQI]d7.\Sc7S
+%#_aVohL,:mm37bH*Y#Rc\+_1:A#FPFX/O(@G?FiSnZC<r%LK=SSo"Gt,uMltB!oP(7&UbdCHpD&/i4J^Rtp6l06HPV:T)iY$Al+R
+%g>R:Y3R.gA]o.uViU:;,NK%*'C,9jfH5R3FB:u3+`u[t\Vh_7pgh5S/d$YsC*^i-dm+H4Xjq9>]^KljTebl1uLjaV'h[Ve7;NIW(
+%B+"Zd5MV7/a)EI)no+J4s5@,"jiR3#)ZaX=#50g@rVB97Z<*Ie=>hqjH7JcGmm=`/Ge-;lG`NuAC/1InLOB!\/tVGNp;50#^(#,G
+%5+W\!eG3/?$0^:]%il6`humqBcYjIcp\&a7pu[&eND2pHA[GMDgLr!QhpM(5<(F:+O(>7<Z`V.;R2`HsDQ`(s:J5\,G:eX*O]q9l
+%8=Peb_o*qA>V#;sjq<L\r0RV_?+p!n4p&dLdTY!2=*D/OHTth*KC91Pq/+HZkURYqV_59]Vu6)TTi_%Ah%:aCZDF&,2sF,.4Ts^B
+%jf,ej'T,&n5+aU^mER]KhH>=Y1tKANjR2uc_Y8,O\EVo-MQN`C.tu":DEp#"$P@NM*FQpM1.!gaYOh'#6j_1La@23.gb%F/hBe'T
+%kbEr)l/A^G&H/)ujUg&#^(/'6SPSfPTbANBZ0'V:'0:P()CkbT<mk=E]7fnfD9:8WiHSDY5fE/2)[a2Y'D^SJ7ilSY]%p/cB<L##
+%*AicN8cIe!i^M:5mj05s[sH`[iS?GYXs%6KcpNcVI[[e]!Yr@.&4=kc?'5(3KsLC&iGJJS%^FNCZg?5[;+OlN2VPq3I\lgE3br:Z
+%F4l?Hl*:-:n=^LV_-(XKI"C\ZfYcCe+mS0s[Jl7PmVQ7jgV`PF@9hc5`LH6W?JVL5ZZ6OHpR*'scquM*PDef'B&`^8m`8H[^ACiS
+%\8JpS,CJ5C.Vs5LVeF'#EgL^!6,f9kZnD[MW9rUGS/:tsr3H';>1gr@!krt-&W6mPq1n5n>.43)8=ZP5ag.gcT0C@TmYV75UN5o'
+%p*#'QWG2Q_He,Kj8mqT[GJ6#W;1?nPRq/_*/oS%T_<_p*94H7n%N"D3pRmqF#%InCqkIET3\mNWE;Ir)2=J!Bo'NL")mJ7i@R1j7
+%kI56a\(DIC%-2VI]A?M"Y]5:b(A6cnPCj-H4*Ms,eY#`@4I[,D[Vo*;`a5X>&Qlb+na$aJAi]ti#<E9gmq)6pjFfWGk!%e&e40ld
+%%Ir[l'kC]-G-dOXAT#0FG?b8+M;1CVPAJQDXl_[8M&VHO49:(-'H5ACJ,Ha!G,.;Tn_:+B.f,oI/++HA*FWQ7InO'hdbRms2:4l8
+%"<TdgW;CtC4+'*[*'JcelIA4#Baf!glqQi\2S-ks%A[.K\*j3'])2!7HhL+fF%]u<ZiS9URb;$:H4/Cl07NOt_2B^*;CMBF#;;M(
+%a5nYU^m#ASc_j+3(/=3EO2W8Fg%3YZ(XeMf7t%0tpg:5q_<Zi3^M@u]*:W3Z>j%mYL32b**^c8gWSHKh7BIcbHF&'f*qg\]QdZj6
+%qrq/(1E[IcnRU9)^7WY.PW/^*2nEGphgM#n"t>T&NKeW87Z_*WI=&I[h99d`UQJjS\)!7cS]U'qI5jI5cYDQ77*3R7hE`m,Ibi5]
+%S?/![MA<l8XI^6ccb4>`YTIG.g-Z369q2q:O*atg?6^o-4,3@[KcN-B\j/66I2?kZX2Jee*`"`_"1jYLXj's0[eEoh0%9uYa-:/$
+%G,gtRd-)GTNVjQ]ottpZkMK:0.0etr6<rG4LD=!7as0*SpU@mV=P_U=]GH>qp9$f(\C8`&VP@;Vo[0;H`2EJ!HLUT4W-^J\8penC
+%4"N'@Qf%d3p2[V#"(kTV[pN4O8o*$K8F&WJrqR$:"+:u6-_ET00Z+H=Cj(MdH5Xiem2Z4Eq*&OE.3\uK=[QGAirnc<[hgJK&&-81
+%DmWY\I!mB)rf[XR='[AMcr&GEKH*DU_c9AX35Nt5s)+lq(C!YP>Cl9/;@oI2iTN-)J=",fZ&n_#Fli8b.A>JgTco,O2NCb3eW4Mh
+%Q!Ynt;Z6cdKe55uid*J'Fj^'06oqZ/Q38=;5[p*FfmHsn%CASSXfmjU;B$B9)0pS?G'S8?+7mgtr,umL-2\:VGOLDQmn:,dYFNlF
+%>A$7kj^p[Oe*MFkptT-Ci8'1G"N1;g;ksJ%\s'g:j#Pr,nTV=!n's/S(@/"D/,eRIC26%_>KXX/AN04_pXs'HD>MXA9GK]Jq84[k
+%.51ROLHNR;cU]-><G=81p5-bHq;+"AK5douZ0CLpYP?]'EPmYKdcF.XI2\4@GC,.QO3Xhol)1tdlpmU>;mX<[BTQ]+`3Xeu\4smW
+%g1+cs5hLmQZX;tQ!&55"3H'Or$q5Y>HolKnM>m9^eE%!`2\2"UfhNOn7q\m]:cgVXM>@.eZ1p*I`PqSr^gT3$fIc;:E`Z3%;Go&4
+%j_3X:86t;"SrjMl]-HX[]6MWCcZ,VDmAK5ub/LcT0`,Vhs%^&[3C0R9'o%Z.d9L#1md.UeRh_"XY)m)n)8D!V$6@`,nSP_g6ot?P
+%Wpn[5FDt=7hK(HKdcJt>)YQ^Tf0BD7Yn1os[R1q5Q)hn%f#EF)FYN0m/6GR@Q@#tJ$;0@J[X)1G]5cAQh(Qnm&@(,p#B;LbH8C^T
+%Lc7c@T2mIumhD7!H0ga\)FY[\ls.4>[Q\">J^)&_Cko=0r[:%AWabk<<MqL(X\%.qe(k,SPKWdfeY<);N&8gb?luHCE9&e40KB9j
+%0U1mP`cdH0I5b(^p=O&4`oFae=7IO'q0M9XU?%@3n2mt"GdtBACsl"'fM;U+ii^ek2Y;3o8jX:gJ#oF!(QlVb`E+gA=WV^JHCaU>
+%He1FR:"8l0ZZ?;A/#c%o?g.914".Yq9\'>B@ob74gWjoNWP0$)SLa,RF`m`BaE".:eh[Ks6CM\gY^9O"buI!WenT;^B;X_U%ShY3
+%>%sT9Y[U-Cl.=Kjns7cXM?BZk"bX'MYf1)9<qZE[lJV<P*K9+_c#9tdrn:^Jk%ObC"($]HBq0J\OP(3=VOrN`a6i[R1`kMmD!tot
+%;e6K37"]2u7cLNEg+KVq,$X."E84!0Mj^XF"In?A<$E44#pI:X'q'KVj5YakjqoYda%(B0pDSnRA./<3Xl?s[M(/^P]"L7U04pdY
+%2_p)nYNi/'NI;#b7HniY04sbaYe[D\4!YEpY1U9O*2YhLqMo@cB^e*iFQfCb-MlB]I89ue21uH\nJMYW`^KDU(dMI,1UIW>*UkP/
+%bUrQ>SRSaASHI3gK8O-fK6fPe(fGf\0ccG#K=X2S>7F11.YDaq,\2,?6UEW,*E8u)NEqt_C9h%0KG9`8]Y*W:(13\h6_&l\FV3oP
+%`Fd`\]A,pC(idH:3D))Z6B9HOfYcq;204%DH8K`Dc=M9P/F5=6d3jJgKUs=Zo3tfj7dn<nG(-X1'Z=7#0=up""lG$6>@"8YquebB
+%c*_BK:<_*SSI?u;3l"B`(A49Hkqh=blt,QicahN'e!-M0<3Z+*=TLBrZE.Scn"u#S[@?U5+WX;;X_]g9\5drO2_NErhGG->8[?>]
+%0@in9ZaJp_H5\"A5W^5J(Yq]N&#shp1!bqZjf-G`BM`a[$1Tb,6/bYgq:H9CqtplE#s3H7BHLp3+nak?[gr_L@F?SfO@UX5^Z')1
+%%uIY*RRF]d"*n:"cC]7B>edn+GFLJ$qb"??G=\h59QpGN1]>PO?P_tDJMK9L;U8q5_e2U)GkXphW]liCc)AU<#pmnd<%V%'W^njc
+%U3\PX;t%AH)YSkV2U#cKF0^9P(TYqA9UeIKZajSR":n:#UY%r.C::g+Y^/#eY%00/")EBk%fquB@<,TpqF[M8%ndiAG5TTu2?Us*
+%_5pd\0&Y/']#JpkNG"WX4M%FnnbrA!b@^)cf\O,1O&K];)s9baDT!iV?R_(n^KdrTb86$I7GHE&"f6"F%A[:FF^3V5RMft[m9G9k
+%g:i!K6ba)FiHh]m%O;)d;#J;G/J`9Of9[\?q`q!1T0@^dY2F4YD4]i=aNBM-NI4<Hbu3Eg>`r[eAu1mh2t%GM!A,'epUZn]p*q$Q
+%'N_UWhT?;A[\?e8Gi;-F=M,X]YGZE=dP^6tTSa!eYC'9e$?&,D&+pDkTNdRZ?%A19)h&2t11$<=[IW!lY7H!<mh5Gj2uS38gRYIP
+%HVn.TDWrcKV6q7:Lt*]>T"iWfZHW_I^p"V]bW0iJn_`r9-g`SV%p"CdYP<kOH;ipqQCO,Ds3HHORI2^&3&]3eNE@(Ng(P$.!oGV>
+%ScA="RH)"=aToMn;9XNuh[>E<V>FAk&9%kl2)-k!&47*&AkUZ37EMZHp\>"tDr=D<RuH/A-Sr9,g-sM`n)E0=f-f2sJhMcdf>2gO
+%0D0I,\JpX6:qrh7>sI$ZkrPiKHC2;<FgHY;X@"UF'&AJTdXLdJVn^L,?Jhb8Dm>KbnfE$QDPOHE(rsFm"0&h%c7(KhGHVW>r!5%8
+%4)m,<r!5$Ud-*D,@t(Dq!$"Hq%R38g,SR\F*))2TI$pj,js1/t;mP<jb97)V+gKr7b97)_RjfoFYT.*P%V*HsQ9u)Q0$0>:QkMj\
+%5re!Q#,LiP&JPX_W/18be!;jG@*[(C-r,kg/e.#E=7'ilEEK!<leT\7BrZt)\@1,3&M:e^+f7[Ac_\_XZDie\TaR?HCH4FIM7rd5
+%Q^7;@5enWF2nZ_+_pbfgZsr6;RGM<dPg6.@s5Xh:LOCSe5pp1D[D>.B0'_pKDn"pl%=.Nb^"QEY.piVqB0TPkikm:[We9^M6ROg+
+%_h9Df7BK28^bLu$B:j<l0P+Cf;jr?g\^Y:FXf:!)]0&d%L<$jUao2tI>Fmd4H4S@Ud9o8X3?2(rJD?o6rj8-e;6jOjf[>nl-5r)2
+%3/np/meN^DSgQb;8$D+n<_e1_>XGgi/r-#aU=</+K;g`INI>/jB57.hOR8Cu=24P,idW4^>NdcZ37T/=i#^ULSO+tj"u1%o>-cN&
+%R,K*a)sC_lQ:&(1*FY]8W*dndKJM(dr/p>=$"'Vc0+@UL7NQ$kLlI?4U=B%-8EfY5+usuj45cSP*C^Aq]$]hR#<-:.VA7@V1"80C
+%#2Z@(j:I+tX,L/JB:(dX^'[F9fjgaQhg$3*&6JDEmmd#oaTFr)Pm`S=+)uc&bt2t.Nn3W>)kN,EVVRSV^"K>KVR]p/+["H1rjTM*
+%8a^t#p%c>_UgLB^1Z9=U=S+RY5Q&g@H0'D!,SKak!Fi%_,'1-.l1?bR]Xi#+0sS=pil7&4Yp:J$_aO'L%^c6](,fYKd=3/rJ_Sti
+%:d7%eL>'AbD(,NtA$u+"HP[P[O(>bos#]!,m+rKrd?;-*T6Xq6^LBuW^6SR$?;:%EMr9mH4?Qu+l,pAl"T@Lq^9_t4b-gu%j6YBA
+%&gFX<,-f0j1IAEV+:5?c4[Vot=$7,d)o?h%8,-Z1c3%!>^'bemLm3PW.]V;?%7(IrU]VZ>i:&>UEZ_G"ID[RdKTEniA<Qr%>NY)o
+%`!Z$F)Is"QaFR<]'%#PpP<N9UQh%8`qi+#6Rk6Z+D<Q%al)@$?)^*;P2RJ#G`RX,B(Kk'@S.LZgeHtZZ85u*cZt?=BREACu'1qH+
+%&J<4D\c,&V1<YE*D;SZ'I)"tJ0(RD^qhT19?o6E.0@=m:)Ssb(VpQ"T\*OiB1lO4MWCYpMa.^thqZ?[UQ,V%qg-JQCqn\haG!$l?
+%N]1/h,l)Cp:QT8LdEaK(+I2$Nf_pK2&1LhY_>mmqlYS'B6:pV;@9hUCBY;HrYVf+hM5o``2]Fmj;hYJ9POk^*6Ej:YNF%.JY0`RG
+%Xl7[;1oNP1iEI&*8,\(BrJ-`ad)j[9FR((:%>MRbm5n5rJIpt.67%.U@IXmIqpUaRa@dMp`P=%^Y!/b?*H[FuH-Q&WSuJ#40k@$b
+%!MVk28ODL7n"'':e1T&*ZdV&u4q)eq-3ot[MQK8$e1Q3'J`cpKA,*PrabBJhq_\<^;5FSR@k>U(q!W7DGAD,I:$<&84!2B82K9%3
+%_/pC%I7-cD'-qLL8RoD%@X5WpW0\0/ZsiFcmPu3EFTGr>&tub\4:IeC54`I@NeFVq]U<bb&@k$&:s&&Ql7,4m)\uXD&H5ak)IkZO
+%FM*(L`_Z%b1_Lgk_n:tc]utjOd<PT--="rF*15,b91D-C0B#TQU;7C)]r=tO3.YJic#ClE%G!j\-&p34<#$s4WLgBn[L8e)3H[ef
+%j2pR]F._,g<8j=4Cd!R7cr3C^`HRNCkCK.OF<XW'LQH_/#B?qZ<nMlUN/MVNrfL#<$q109oSIq74,!7W;-;J"rBu,sl_D5NDT(dX
+%pn-aP"\_Oqkjn4@,GE*E>4+pm;X2#7kDgrIT0^R1P9csJC@CS4bL\$IUGRA;nP&ghr[PB)^M_^f*3YZ(Nh1[p+FK0\4MjrCZ:ho)
+%+Kl[29RAXuMN[ScoEk]^%noqjB0)Wsh]behTWd@n87tI!>@2`5XDXMA9VdK*8Rr_LSYi!!BSS4HUu[Z"6RC&chlnS6g_>JDlc)Vf
+%K"7fug[uS4f#$a@Gk-0JD[2jser9u+\RGo.MYk=OY/fqIe9uWP>Ib;`Gug-ZDsbP;kpeNe4qM^;nB$KLRuk/R29D24K/F8H+lp*1
+%LoZPgLUZ[9$lc_7lam[i"P$n(>n@+tl6s>8&>BL5GX&VpbF_Jr2Tbcjd6aH];"lX$4G8^h6H\Lt*`J=h;@"0m$8KqTUiu/>n]'6R
+%p8WLb7D)biiZO/>lde++$?mFUj1%npY:%)f5eEtUg3@kIp%?L<=I:Tg[aYZ%?)Dpsd)SIPQ4%\J>n7/&_`E[u<^MC[E\&2QU/>7%
+%??(W9!4K9CgFj@)fg'T0NV*]_j?HM'KQ%j&1%5`@W!]sHJrc=hok#f38ld%<pC&Q<0$hCL&7-3L&.!8S9aLFO:`"/lZ.4+j9GI$+
+%YnsHqU%V3%*t@]#9XdCZEOaLEAAA.%QmfU/[T\'j.W1u5MGZO"5),%d8Q!g/<VC"1rOq\MH1]X:\8c&qjUdcfA8<nFpXPt>fb5@Z
+%MC_RI&b]Pt*XdtcAdOaX(;lQbojTm:mN"Q;oQmst.W"79(Z%)bp3JM&(fU>D!5F>NL"a$%3UqOhi!`qBMhKffT8,tC2fA/S+=[9[
+%Pl#\TFNB;o>f+(n>0mE__O88T&r)6bL@S&FbWd-rKPdEN$+8)<0-K^3!5gCRK8!;-Q\Rpg=BIFGF$Wc)J5G6]S[(pgK>Bb"UPcUd
+%pUgSPpc')8jR6H`3[e1:fi(ko+2j9_;;)C$q9h5^%ZC<a;1r;/.LJ<HK^obakXK)7?u3$6foP#sDa%\u];9jNcZ1MmKi*J>qtA8[
+%]=HK8BcMmg$]SY5mf64jr7tUR7L&@4rW1?m'*!gTr!?0:G7$?c]nKQ#d;2BCc9TL-TS;e%5[Gjag]cQ@_.q3$.CAuZZ">Y=qGQls
+%^P)J-B')"2*T^W%;;F^,0eR\DZ<Z`;m<<JlOFVXn^l=V'[t\CtYnL*"$kcTJ_M.EA!.oN>dp(%-PFE0j-L39@[QZhS?N@#k-s5-)
+%2YIF95]ZSUS">tmA*(A=9UkjAcYT-:'LW[M$Q*]1%fdiDW#h4Y_+V1rADP?;o$?b\,0shV$o0GjfSbkeIO)KJ@e:bu>c0je\X*-p
+%Hi9LQo^"Q-h$M#^4DWa3puLF(^?FCf`j/;o!8!62$GlA9GX`rcB%)aJl(WT6D%u%+M/Rh:^'Z`j[l1(cY`C.FV#COf#fEX:7tp!p
+%987dm4A:fh<Uc)XO)[GlO,cBC2s[D5Wpd_8OIBSS)D&Vu/So.H45^AUU8ATJGoTOa@Z&-C^qttJos2]5T"$`oPRZ$l\OW`F>`C8G
+%YIDhMl\@.a(uA4/:OknGYI4'hWf8!CS30C\,tjNC=lV'd)OAg->>dJ@\-.sO7Edq^m5K59S@L^E".>WD7GK@A]j$!!SK=Y(&uW#@
+%dRi[+d<_aU/t;tuV>cA'\8e,F$^A_H\p5="hqB$",^Tui1WR;mP3<0YkCc;e%(a4TnHOf'FMC*i=_5t4RkpB@bScTA@jFM!0HDf=
+%N[5-VPXs5\NR\&Pr*"(@Zp7FafFQH@YWWc9(d'Ph5qB]Q68Wk@ZqT@r-g][&3\tH;j`Ue+#fGcr%fRi9,&#$ULCjA8#_*NGDk`J>
+%OA28=UmWA"?;ed$^%K*`+OinJRUs1uC)cL8p43knF`gt2anFWG;fj[PDK>E#1u/k,9)tN`e.DR11=Wi;0IBZ#4_mVEXQ[qYdGGJ0
+%Zf/M\JeJne9]7=6UE=#!_T1;Q1!uUciTN@"5\D<h"DoN/Vin/DCX03]<:4(_@(]Sk'@(n_%eQ[IU$hjTDQ5c#NTmf_#aX-12S+T3
+%rS=%ALqKpTYR!V9Y?Hoe-(!V"\=.9cq)*TF=9/G2hJB+[s7^]5CMb<4p'LX,+peAbA#/OYe7/*rAk31=Q9^6\#+WU9Cq):mk<Ac+
+%<@rK[4@&8DhgCj1AZ8[8?#-M;p^`-#)DjMP((U65l4nH`91@4/P>tA0gOWf%YD3=Y*KorJV&re82dXC.Ki\b25'?`Paekq*%f:jk
+%`PE#'n3F)2fkM8*Y=ge:oO6>\!D1f4)uEFo+bWVbM#77WeU?cl;;!VIVls_FS)&5:O=P60r=&QqU.mSl]X[9>m9rjs/i9NcW(ImS
+%kK1D3Ih%&4HPm!>1I2Qlb/Qrei(O[bLO.oK^u.lt"GcMUP$r;V#_I\dD\NW*"@7"rPYj+o'*Q/1Hn6->B7_6cGfhEOS-af*E$&mO
+%%*euAE3Lsi?uRFuJj[-W,@GI;#_GG=@j>B#-4#2*WuM:qo5SeI1kWQ40E?_]_'c.XPFar4jRGNT9J)P9K/5e)*(HPnL;B9##S-[8
+%&MQ2>5]H;Qp-rDF^"i%-gJipeXM.Jg%UjMqhr",BT4WRaG-1iu$:fmk-f#!j;bb<BcNeH#QAV0>Q*5hlnY(9"gJ@iqa#u*\*@O=G
+%H#o^'\gS,J=K>I[lB4m-J]?g)NJ5BAcSOC$AJZa%=-gFkZcT."N#^3^\3'!JW&[YF20/,M\-W]:m[_$#iF:MJ$1_WQ/q8-'IU\BU
+%c8[3tr'3gJ24&61S2i;kD6Mdaj5R[>g<68)Mm,9$JrV9bh/&??G"OQEgG>8CfrIpJ&BkT;gKFn6E_#T69OEm+^[h1nnbOA0-aETF
+%l*a06o;je2[g'_,GnTB8'IhD4_(19[R)40!k1<2uiVKFj3s8hKpR.tD%+\'!"<#`:29e`ITE;U[D!-3/Q?JnSIGopLL6peAl@QsH
+%,EU)e`HpeD4[^E>WE?M)UN.`gMk)f9q8RTddlkJGmS/I&@OP>#dH[?S[[oe514N5o^"2'I1ZgI-2gt_"Y>a1]#VM&.T3KLIHb$i0
+%B=\H0h9(dfk,EFG06a0Elnm86V3qN*?_r#GIRBE6[r]6)i^7moZiFI%^K`#NhdLI8BP=hSBJb`%ZNjho2g"JAWuL,K+K[2*9`3[0
+%SpLmH,ic&qrc^6]C[G<Ze\8H\jlq!&rMeV_Bsas`C+6QPgN8t'f%"':?*>@"s*cNUeXi6&et]Wd/`cU5S!t>qV07&_\'jWMk20`3
+%F2r3VgKV)O*Y)s=++>L[eY)Y!opRR#/h+Zug0<jhMj;t#lggnd6a9gs[aoqXrHXh2Z*Te?V-D7@d[Kc-(Z/O^Q&:9TZYmm+5Ptn#
+%WTb5'nd7ie/p$:Sh6$$ecrnm<b=@ukh5R+bXmNGn]6ILC3@M)l<bb5(7'E[e2<Boa);4=U;C&[KG@W@L\WAJ$N@]^.AZlUTG&nVZ
+%O51W2H:8QV<"OgJqWAY!YNt\)\a$<RJ(s@K?prHKBDJ>#Y8R9Uj^!6`V,7[4Ft>3sZL@&D01b!UXKmkG53,O+ZI_cKHM)QVr&ON9
+%NGk@McMHarJ&a15F(.lk=SPqc]qpRV(F_TImQW?;SR:V-ZT[%%[^31l:rQ8S^qhdhic6c%mZoM,F4JZoSrH),[T?B\YQ%ol.:(eI
+%bi_0^hX+\hl_a!)=uDc)![\1M_1J3_.dq*iDIIc@>qN3;j!Dh[njWF4Z[R?]]3)$#Im/f-66YJ!+hm=+IoUs+N=,<S&rSj%]f"[7
+%l<EMJSbl,n^;!.ipc?Bf]q<lGI:&SJSRnPYSKh)3I(I[[$:\E;.4eVCL$GPm./se&K>+@;gfsc%4mupNTC2HjV#P`gkga*@q955X
+%Yl36SjVS$Crl#$Z$,=^O%sOHLAe3jEm4`bR[?JnE)n!54]j/1Z=[%6II9b(E(Ar=TKPD%HlhBk^c\K_gbN_k<Di[OK3YXdXN>dCF
+%Y?sD`WGi`eB2m&1F*i3,leZ-9lM$i<VEUL"#=Qt7L[sfonX&\'m"DpsI$S+c^*BkenoQ`=;%>4jig>e,MQ%!9Jb(0oDX\Gm)l7cM
+%[mpa)bZ8`BGgGOt?Yl!)-#tV2^H&KV9Tr?WF,6T<a\d"_]_T'C2.[CH/DVLb\PucrIuE!XO,$h(MRReUhk3j_nTOV!MsZ4kH1nnG
+%Agub'I0o3;m2tJu"DXU9h82cE=1bG/mBYJ^dL.5::]Yi[*W'MYBE+;T0.>9@/p"5"no=(=2P>)_=[e4elIONpG%p?Clb14M5mA>E
+%)CqkH8\Mu3R;Y:M51cqfgb>7eVU"j5,S420.<N9B^&>&VEUPG?h4/,VKmr5%D>8(e;k\7+lVl5q+gH]5:ZfdUlClqVfum0^W*&<M
+%&70V9iKNQh,6.RUQL>,q(TM,B9rtn09)H>.l8Nm@:2Qn)#t]SuSJfHa;!W>*<k>fUqMDbqE?k"/[8M#S`.pMHc#O=L:>]oRc?gYN
+%/]34MhbA]0+:P>.^03UQIM\I/C1o!,m!Uk=[5L32FR+\<(L,_U?$DEAX3KYd[t=nm?mjX(K.e8EQB%[:3OBkQndchTci(")LX<me
+%MJYL?`A#4Z"me=G.3<-!k*C3+i<"BQYj^T$]:rX"@XkT/(L'i&L\jm>`>Sab>YV&=N]3h!4M5P&\dY-A>dK3E["jiX`8?:A%(CD/
+%YMYSN2q^!no3d/irphrOru&\"#+[X(@SoTIoB%M!ODQZFA+^"bWRC[pbT<D.)r<kL<\XEUGD]Atb]Elsba%Ed1G"Atqhr>tRt^];
+%Q0Xugo@']io#E,CdUhR@hQ+@=BQjXf1tkLEkGM/DX_-grP<fDDSREODS_7@dFF,H;HZ^EA(L+No]Wq&+Wu^0Zp<Z'%kcCCe06=8'
+%WB2MspX]7+Md2iRF?Jc%rNKKljVJiUNu;HLNV)4#g2k"R`4un[+5VFJn%./>Sa\4\J'l8M<O]W11%3IVN/hgXV9A,(b@*UE3>Edg
+%r8("Ob5-R`f2n!8$X%d_HsN3<?G/YC4m8,*l]3i<_Yac5H9/\)rbPCZ3:GGE\`ic08hG3B9LE\A:qK^XXo.RIS[3\gGP7eR\TcKH
+%/g>tqUE?NAq;6*oAVL=^9aBPO>`I)l.;U"@q($sjaLe,4i<F-Fm?Q*)f*aaeD"3b'L&O8XN:*1\Ni;*7TpEP)P]1a]l'78Xed``]
+%k6S,u.,BrQY0s7):YNH9h't(EYFL`qmZK7J#rq<TPfU*a,*=<;NtOH27V(^7?\"Y+%Rq^Qjmsm_@q.pT/"L<M,0.]Z,l!mB;'O'#
+%LlANd!_VP+(m2n'T1=_X)^DWr4Rd8;O^hlhU>gM@-$!g\8FeGJ"_C?FLkJdB)V"*GOBs0j%/WmGa2Wpoi!fW#-$!g\a@$lL@?ej<
+%0d9s+Bf6<Fm,](H8`4tNPfU*a,,&LV!7eas,;KbQ3B9@E*_X/Fru=YlfGKatYmCJ5Nl$V=gA]#UCL:ZMk:]<]HN?S]f&_1AaK[HD
+%GqRF:7#m6=BprA#6&?R#,;NI$5;^(j@RSX[_uCjP%&jrH^?8?;a2Wq2M#9bV^9>D0m!4s_jn9u;OVGd+7>W!',Efj^SjeJU)^CM$
+%fOn&*a2Wr%c/i;/,%$3>)1OF`2P8CeTGQOfNVON0Yl+m;T-Z@e@4i425>,`T92/3nr@FrDN12@Fg4#@;Hq$.Tg%MbJjth=I38+#3
+%UujJ^r\2IfZ_Z`iYeBHhrXCc'Gb8[H=]4i/!=hi4r@FrDN4e7_gWu%OcV2OR,hpY.Ra6:&4oaV^YSg9<8[b8)V"*ieq$jdZ?N0!B
+%@&"r[PANNWC-KPH9Xt$PWVHr8RrJ7-;Y-<%@l;C%Z_Z_>I[`%=p9URW1\*5`D*L[.4u<)%PAEHVC-JD:(6`T"956ZNQF)LWT-Z@e
+%@J)#'Ib&9u>Jf<fNcS'4?1mrYV5C.VfrmV(h9uPq7D=6"BN;)4eCuFm1B6&&O8eSQQ6Wa_>SeJeU/imFZ[An:bZU33CAMB_f7#8/
+%C6+@d<jhme[7I+RS]]o'd9<p$[26>radNAlp'%V==*)m@Fo`(+;RVk.TB![a:O%9T*rl4m5Bb&d1G]M(GkQ2rpYaM<amr`lZO1ar
+%rLL5]2KA%IpooI%qul7;93F@-[r^<8U/A\$KQJt1^]^Hp)-a\hC8MtXB9XM1d4.;JnoVn'^&qR5hBZ:^^";3@_\:;U*ciahO.B.d
+%3@:DGlq?)i\9Bb6PY,(NGaZAA?/eH])'OD7RZm7CWJIT?Apch=.:EHT;jkGp,i@qI6DjPrWI1=Pg(CLL"@:%/[K+:m\?><Q@=rVB
+%9&gOT[ZD-1$PII<Aft;Po<Z8e+.15VJ]il3AX'PV\eLRJ'*6R0ge&i2K<'[-q/7SXN$FQUj/=*9BDelrUo-5_<"TA."eOd`*&f)F
+%%BU=H#`$FOJHY;]c$7BR6Q5"c<gCt_5*gdK[VoY4Q_]V/1.q[!U0Nh#nK`R\PB!CRnQdg.g!CfZ97o[R_6QDPCtCc_Ju2\_4r1t7
+%9S0on7CPTk!fnUp]#qpd>];)SOtpY8.5R3HKFa,c!^+S[0U2n:IAqL?"PD'bdfSX!201NrG\]RmXfu!=6/XKBo>%)q]aTf(:P?5d
+%O'6+25sb]UY&Bo1m;O=ilq&(pF(!K8UC3B'O64"k-a6aiHn:=!ON\hskX.lSXpg[EH/bKY;A$`r>cbZ5,_h(\(A`c@juA_K:C-Pm
+%O?1krs59`L)'FG$pc8qc6?ABKB$I@@qGuB6$8=6)9FEfV6(iL_Fb!>JiFjf"0:iT*a33JQ4=f2?'O7"77QfZH,#ZdCRaGm*$^L9k
+%aT8B*#ERm_"a'sTQZRaWMmQ`)QYrS[27I!ddT=YoE.,t6g^1+0:aSV4^oR['[Us'-otePMZAp/4VEXEZNL%ZEXn^[dR.Z5%nh&p'
+%n2QdsS;QrTNP@U?8p2pmoUH>8WR/c*QuAjbAf-k$9N6"W-HJ<#qh-uLjcCUd\3u++T!0oBK&B8GSl#5P=.p`;'TFs[%`OS*Oskl+
+%M%*-Z4!$W&'>cG8/&?t!)*)lU50`h<\dc[?&7<e'588aPrIF>Laq;i\*XomTfMYAR$8U%%)i&%L)P0?1a]uCur+:reJ`f*O(2VE?
+%E?BIP7:K>L&P.:mK.?G>jFJh3ET0XUM2WHg1*@auecUR2-l*eY+9s)=#WY)r,kMSd0,uO?$_rC8K:.$,-pCZ8WWED5rij]/E7lgQ
+%Hlqm@KN2I$03n8fl+7htR$clpf7U`4NtiC%KT=aZL]l&&"0u*60.7-(">'d+-[_c$bnnggFUFcT=@3ujcru/i;?l(9='`QSJ8Ga&
+%,SA:TmmZcsYot.PO^M1r`/:]Ac&u[unQ:huVC;;'a+[=kkTaBpfUBk/%]qh4K!,sD1]@pYk/552\D4k-N0AJEEj<nD?V$"/*J0r-
+%nH=M#`tJq]^nItDe4j=0?61SWYn/CMmE3ejiZkV$0J!&LLd9sA*LW;:DD2;`;I$(n3+QU,8c7!o6('!QHj39[U]g=U,tf0C@<f:s
+%-)DET)K>J9!$O1]ERVd%o^h<RXHU$I0VX<'fuC8<eJL.dZW>L"#rWb2;Z`\T!^SIs,Ut5l;4M\ncWDh'fo[<:%Bq8??U>Te<Ru_b
+%;2C#b"-$<iOBGrs\-oMND8E68We6Xg"_RXJk<b9aOV5ITQ/I1P8O,dRE=t_Lm:>km6On-)cmUR;h2mBd6o8`^.8^Ldn=RQd*^CF,
+%5PRS?Zmj6LnG%S#5XF?n@?+st@FM<2:5rj$BP!dZ/u?Z&n9c.>es'DVaZ%!BnGM5s9b&Rs>/'LY+_*fD8WQl9Hq7:UWM)tH#ojP2
+%1L,O-&mW6(Ze$uf%uHHYB+WFa#b07r5dT^]!DoZT6bIdU#D*lcm8EKu3M.Hl34PTF#=65#F=]V`TqH%\4]8SHFmF<0(k^RcBsB$a
+%TH!#H5)7(E-H]gpA21('"J;nV$.DQ``h9sWKGpin3C;ea(_?m:\Yt@+dNM'!6UX2m+sr:Cc?L+,<PX_-AV"H)FJN\-+UFFJNN5e;
+%,0+JoC1(Ba+N\+lFkC-\)KsC`2HA!+#6D\o$D+aPD8fG*J"rqc6[,5OXu/mJ*cTaSenM_81O,'o$q<?05.scE%T@p94(fQUU#lsh
+%MsS@2^]St,?t*80P?9.kEi:J#L:/NT;2>a]2M%4c.0+H=QjZM*8!%`b?_thT'?(3'9[Pc/3MQ;+-POlAAn=&o`cpl^R]G\uE-.r[
+%<)Z:LF=F!s+fE#SH8EK@Seb@ScF$WP`s&HSVF7J!>Sq/pO^)7I*l\jGLJsQ!6,br"`=gY0C_?1&#eHHR@)D)>63eq&@T?7nYgX:_
+%80/h@NC&aJ0L\TEAJCZNN<j5^.2(&0?e^^8AsZ$(=\6%3W$qcR7rYIT8<7Qs=?`+WPoBo37G/4]("U6tQ'BVBI;ZjZ:U&&'!R\Si
+%Q1@aE;Oq?57i27eD1l^b$-f<AFN?HbTR)VI=!:s^7=oI,Sh%[HcrWo)7a;`l23O70Oj`<2-MVT?.M7VVWXDCl=nIsSdJD6eE'Bp;
+%'I3CAGcOP^/<PXrSuK^@DoqCf5adSeKNg>n4<_l!a=D657FhR)#E)"?>[O]]#Zh2,I\ijn-<9_5mR6T'$=?E(WV/*(P0Y'Zn,c/.
+%U>Zj_!MZhd0Jo-Y7*6C5a4c9V/#rP^p;A@KPH<-DjJG&j<8:tDr?r'FTgCAR)L;D>EC*6<WiRVs)^a2dE#hQ-V^_G<EGLH[:7;g!
+%Rc`%\dNpj1Pmius_&Y9f\k4J`W`<`"fkhlkUre*:1,;@HiB@M.BXC4&4ko$K.!9s@<frPCj?ksA&Gnd55o2MGosrA!A\*?KKUV.P
+%j=67tn:lNdNB%`Jl\$:I&Oc!4eCeV6O[es8\.V*)::hr%c)//aN9*V`^r`aDEYR+U&h\sa)l\Lm:!)DC^&cW[ihHAQl#r\Ukp\6@
+%5kE%te*J@1/<h8<j9.<^3_c@oOSTHVLnKIq>qRN'+PIlHG6j'A4R_+oT&+O>4SFSC.Y3WtVo-t4,YpKn4>ARZCi`_2nHBe:[R0QU
+%-E=nd\ekZ0Uf;?I)ck8$#UN5Hp-GH-ZshF?S(FkV((uTa_5?7iD]HciK1L#+K5RP?_Asr5XWd.F89#G*kU,?8[#j?iP?`1aKc;*k
+%jQGQs?oVO.7Kf$Q!&P[oN04W=Z_;=S$]0SuaI*TI@tC"\Z"P-gkX/4^OIR:9,n[CmK4se>,bDFQjYhh2$n.Dip!ZH>g4UR%MPS4S
+%5&GDh,R*Q\po[a/nn_923g/b5X;T/A:*["ZT$(nBRlJ,?Q'.jN/m;"OF1?br$T9L0/=//,QaSb62Hg,?_hG*#Cu-K*-(a0=4PKKX
+%,^S/IIiNO/>Z8@[-S`V]=CDZ_.mEVO!@<OV-L068oM)faHhZXTI2R?/(*C`mitXjHeI^'5PHs^\`h&FH-YECr'uFo1dD*WIZ5]"l
+%ks\io&sV^nY@n8MZ$h01"Jc%Fru>f9-*=r]?XB(AqY4J9%!k'N/V:).!lH-W$nH0Y<L`[+elDZeo6LB+Y5M/gGq"Hhr0?8#J6+0Q
+%*7+&d64@oElPIn!Z.;M6iAP\>UtA2lYI$_&UEP'2j(i5^i;X9IR,j1JU$O%ck0Q"dnqHtbK_,+dQ+VAM>A@I6]@-NNeF`Crl:q5M
+%?#BMB[o55VlMoA9C9)LO=FI:.iu@<]?11#mFfTS1pD6\G96C"%FQl^aomb.>&V'~>
+%AI9_PrivateDataEnd
diff --git a/doc/arm/isc-logo.pdf b/doc/arm/isc-logo.pdf
new file mode 100644
index 0000000..71d3fdd
--- /dev/null
+++ b/doc/arm/isc-logo.pdf
Binary files differ
diff --git a/doc/arm/latex-fixup.pl b/doc/arm/latex-fixup.pl
new file mode 100644
index 0000000..b133b5a
--- /dev/null
+++ b/doc/arm/latex-fixup.pl
@@ -0,0 +1,49 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2005, 2007 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: latex-fixup.pl,v 1.5 2007/06/19 23:47:13 tbox Exp $
+
+# Sadly, the final stages of generating a presentable PDF file always
+# seem to require some manual tweaking. Doesn't seem to matter what
+# typesetting tool one uses, sane forms of automation only go so far,
+# at least with present technology.
+#
+# This script is intended to be a collection of tweaks. The theory is
+# that, while we can't avoid the need for tweaking, we can at least
+# write the silly things down in a form that a program might be able
+# to execute. Undoubtedly everythig in here will break, eventually,
+# at which point it will need to be updated, but since the alternative
+# is to do the final editing by hand every time, this approach seems
+# the lesser of two evils.
+
+while (<>) {
+
+ # Fix a db2latex oops. LaTeX2e does not like having tables with
+ # duplicate names. Perhaps the dblatex project will fix this
+ # someday, but we can get by with just deleting the offending
+ # LaTeX commands for now.
+
+ s/\\addtocounter\{table\}\{-1\}//g;
+
+ # Line break in the middle of quoting one period looks weird.
+
+ s/{\\texttt{{\.\\dbz{}}}}/\\mbox{{\\texttt{{\.\\dbz{}}}}}/;
+
+ # Add any further tweaking here.
+
+ # Write out whatever we have now.
+ print;
+}
diff --git a/doc/arm/man.dig.html b/doc/arm/man.dig.html
new file mode 100644
index 0000000..6a3ff6f
--- /dev/null
+++ b/doc/arm/man.dig.html
@@ -0,0 +1,673 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.dig.html,v 1.93 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dig</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="next" href="man.host.html" title="host">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">dig</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="Bv9ARM.ch10.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.host.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.dig"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>dig &#8212; DNS lookup utility</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dig</code> [@server] [<code class="option">-b <em class="replaceable"><code>address</code></em></code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>filename</code></em></code>] [<code class="option">-k <em class="replaceable"><code>filename</code></em></code>] [<code class="option">-m</code>] [<code class="option">-p <em class="replaceable"><code>port#</code></em></code>] [<code class="option">-q <em class="replaceable"><code>name</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-x <em class="replaceable"><code>addr</code></em></code>] [<code class="option">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]name:key</code></em></code>] [<code class="option">-4</code>] [<code class="option">-6</code>] [name] [type] [class] [queryopt...]</p></div>
+<div class="cmdsynopsis"><p><code class="command">dig</code> [<code class="option">-h</code>]</p></div>
+<div class="cmdsynopsis"><p><code class="command">dig</code> [global-queryopt...] [query...]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2563841"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dig</strong></span>
+ (domain information groper) is a flexible tool
+ for interrogating DNS name servers. It performs DNS lookups and
+ displays the answers that are returned from the name server(s) that
+ were queried. Most DNS administrators use <span><strong class="command">dig</strong></span> to
+ troubleshoot DNS problems because of its flexibility, ease of use and
+ clarity of output. Other lookup tools tend to have less functionality
+ than <span><strong class="command">dig</strong></span>.
+ </p>
+<p>
+ Although <span><strong class="command">dig</strong></span> is normally used with
+ command-line
+ arguments, it also has a batch mode of operation for reading lookup
+ requests from a file. A brief summary of its command-line arguments
+ and options is printed when the <code class="option">-h</code> option is given.
+ Unlike earlier versions, the BIND 9 implementation of
+ <span><strong class="command">dig</strong></span> allows multiple lookups to be issued
+ from the
+ command line.
+ </p>
+<p>
+ Unless it is told to query a specific name server,
+ <span><strong class="command">dig</strong></span> will try each of the servers listed
+ in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+<p>
+ When no command line arguments or options are given,
+ <span><strong class="command">dig</strong></span> will perform an NS query for "." (the root).
+ </p>
+<p>
+ It is possible to set per-user defaults for <span><strong class="command">dig</strong></span> via
+ <code class="filename">${HOME}/.digrc</code>. This file is read and
+ any options in it
+ are applied before the command line arguments.
+ </p>
+<p>
+ The IN and CH class names overlap with the IN and CH top level
+ domains names. Either use the <code class="option">-t</code> and
+ <code class="option">-c</code> options to specify the type and class,
+ use the <code class="option">-q</code> the specify the domain name, or
+ use "IN." and "CH." when looking up these top level domains.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2563936"></a><h2>SIMPLE USAGE</h2>
+<p>
+ A typical invocation of <span><strong class="command">dig</strong></span> looks like:
+ </p>
+<pre class="programlisting"> dig @server name type </pre>
+<p>
+ where:
+
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">server</code></span></dt>
+<dd><p>
+ is the name or IP address of the name server to query. This can
+ be an IPv4
+ address in dotted-decimal notation or an IPv6
+ address in colon-delimited notation. When the supplied
+ <em class="parameter"><code>server</code></em> argument is a
+ hostname,
+ <span><strong class="command">dig</strong></span> resolves that name before
+ querying that name
+ server. If no <em class="parameter"><code>server</code></em>
+ argument is provided,
+ <span><strong class="command">dig</strong></span> consults <code class="filename">/etc/resolv.conf</code>
+ and queries the name servers listed there. The reply from the
+ name
+ server that responds is displayed.
+ </p></dd>
+<dt><span class="term"><code class="constant">name</code></span></dt>
+<dd><p>
+ is the name of the resource record that is to be looked up.
+ </p></dd>
+<dt><span class="term"><code class="constant">type</code></span></dt>
+<dd><p>
+ indicates what type of query is required &#8212;
+ ANY, A, MX, SIG, etc.
+ <em class="parameter"><code>type</code></em> can be any valid query
+ type. If no
+ <em class="parameter"><code>type</code></em> argument is supplied,
+ <span><strong class="command">dig</strong></span> will perform a lookup for an
+ A record.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2570805"></a><h2>OPTIONS</h2>
+<p>
+ The <code class="option">-b</code> option sets the source IP address of the query
+ to <em class="parameter"><code>address</code></em>. This must be a valid
+ address on
+ one of the host's network interfaces or "0.0.0.0" or "::". An optional
+ port
+ may be specified by appending "#&lt;port&gt;"
+ </p>
+<p>
+ The default query class (IN for internet) is overridden by the
+ <code class="option">-c</code> option. <em class="parameter"><code>class</code></em> is
+ any valid
+ class, such as HS for Hesiod records or CH for Chaosnet records.
+ </p>
+<p>
+ The <code class="option">-f</code> option makes <span><strong class="command">dig </strong></span>
+ operate
+ in batch mode by reading a list of lookup requests to process from the
+ file <em class="parameter"><code>filename</code></em>. The file contains a
+ number of
+ queries, one per line. Each entry in the file should be organized in
+ the same way they would be presented as queries to
+ <span><strong class="command">dig</strong></span> using the command-line interface.
+ </p>
+<p>
+ The <code class="option">-m</code> option enables memory usage debugging.
+
+ </p>
+<p>
+ If a non-standard port number is to be queried, the
+ <code class="option">-p</code> option is used. <em class="parameter"><code>port#</code></em> is
+ the port number that <span><strong class="command">dig</strong></span> will send its
+ queries
+ instead of the standard DNS port number 53. This option would be used
+ to test a name server that has been configured to listen for queries
+ on a non-standard port number.
+ </p>
+<p>
+ The <code class="option">-4</code> option forces <span><strong class="command">dig</strong></span>
+ to only
+ use IPv4 query transport. The <code class="option">-6</code> option forces
+ <span><strong class="command">dig</strong></span> to only use IPv6 query transport.
+ </p>
+<p>
+ The <code class="option">-t</code> option sets the query type to
+ <em class="parameter"><code>type</code></em>. It can be any valid query type
+ which is
+ supported in BIND 9. The default query type is "A", unless the
+ <code class="option">-x</code> option is supplied to indicate a reverse lookup.
+ A zone transfer can be requested by specifying a type of AXFR. When
+ an incremental zone transfer (IXFR) is required,
+ <em class="parameter"><code>type</code></em> is set to <code class="literal">ixfr=N</code>.
+ The incremental zone transfer will contain the changes made to the zone
+ since the serial number in the zone's SOA record was
+ <em class="parameter"><code>N</code></em>.
+ </p>
+<p>
+ The <code class="option">-q</code> option sets the query name to
+ <em class="parameter"><code>name</code></em>. This useful do distinguish the
+ <em class="parameter"><code>name</code></em> from other arguments.
+ </p>
+<p>
+ Reverse lookups &#8212; mapping addresses to names &#8212; are simplified by the
+ <code class="option">-x</code> option. <em class="parameter"><code>addr</code></em> is
+ an IPv4
+ address in dotted-decimal notation, or a colon-delimited IPv6 address.
+ When this option is used, there is no need to provide the
+ <em class="parameter"><code>name</code></em>, <em class="parameter"><code>class</code></em> and
+ <em class="parameter"><code>type</code></em> arguments. <span><strong class="command">dig</strong></span>
+ automatically performs a lookup for a name like
+ <code class="literal">11.12.13.10.in-addr.arpa</code> and sets the
+ query type and
+ class to PTR and IN respectively. By default, IPv6 addresses are
+ looked up using nibble format under the IP6.ARPA domain.
+ To use the older RFC1886 method using the IP6.INT domain
+ specify the <code class="option">-i</code> option. Bit string labels (RFC2874)
+ are now experimental and are not attempted.
+ </p>
+<p>
+ To sign the DNS queries sent by <span><strong class="command">dig</strong></span> and
+ their
+ responses using transaction signatures (TSIG), specify a TSIG key file
+ using the <code class="option">-k</code> option. You can also specify the TSIG
+ key itself on the command line using the <code class="option">-y</code> option;
+ <em class="parameter"><code>hmac</code></em> is the type of the TSIG, default HMAC-MD5,
+ <em class="parameter"><code>name</code></em> is the name of the TSIG key and
+ <em class="parameter"><code>key</code></em> is the actual key. The key is a
+ base-64
+ encoded string, typically generated by
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>.
+
+ Caution should be taken when using the <code class="option">-y</code> option on
+ multi-user systems as the key can be visible in the output from
+ <span class="citerefentry"><span class="refentrytitle">ps</span>(1)</span>
+ or in the shell's history file. When
+ using TSIG authentication with <span><strong class="command">dig</strong></span>, the name
+ server that is queried needs to know the key and algorithm that is
+ being used. In BIND, this is done by providing appropriate
+ <span><strong class="command">key</strong></span> and <span><strong class="command">server</strong></span> statements in
+ <code class="filename">named.conf</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2628628"></a><h2>QUERY OPTIONS</h2>
+<p><span><strong class="command">dig</strong></span>
+ provides a number of query options which affect
+ the way in which lookups are made and the results displayed. Some of
+ these set or reset flag bits in the query header, some determine which
+ sections of the answer get printed, and others determine the timeout
+ and retry strategies.
+ </p>
+<p>
+ Each query option is identified by a keyword preceded by a plus sign
+ (<code class="literal">+</code>). Some keywords set or reset an
+ option. These may be preceded
+ by the string <code class="literal">no</code> to negate the meaning of
+ that keyword. Other
+ keywords assign values to options like the timeout interval. They
+ have the form <code class="option">+keyword=value</code>.
+ The query options are:
+
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="option">+[no]tcp</code></span></dt>
+<dd><p>
+ Use [do not use] TCP when querying name servers. The default
+ behavior is to use UDP unless an AXFR or IXFR query is
+ requested, in
+ which case a TCP connection is used.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]vc</code></span></dt>
+<dd><p>
+ Use [do not use] TCP when querying name servers. This alternate
+ syntax to <em class="parameter"><code>+[no]tcp</code></em> is
+ provided for backwards
+ compatibility. The "vc" stands for "virtual circuit".
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]ignore</code></span></dt>
+<dd><p>
+ Ignore truncation in UDP responses instead of retrying with TCP.
+ By
+ default, TCP retries are performed.
+ </p></dd>
+<dt><span class="term"><code class="option">+domain=somename</code></span></dt>
+<dd><p>
+ Set the search list to contain the single domain
+ <em class="parameter"><code>somename</code></em>, as if specified in
+ a
+ <span><strong class="command">domain</strong></span> directive in
+ <code class="filename">/etc/resolv.conf</code>, and enable
+ search list
+ processing as if the <em class="parameter"><code>+search</code></em>
+ option were given.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]search</code></span></dt>
+<dd><p>
+ Use [do not use] the search list defined by the searchlist or
+ domain
+ directive in <code class="filename">resolv.conf</code> (if
+ any).
+ The search list is not used by default.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]showsearch</code></span></dt>
+<dd><p>
+ Perform [do not perform] a search showing intermediate
+ results.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]defname</code></span></dt>
+<dd><p>
+ Deprecated, treated as a synonym for <em class="parameter"><code>+[no]search</code></em>
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]aaonly</code></span></dt>
+<dd><p>
+ Sets the "aa" flag in the query.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]aaflag</code></span></dt>
+<dd><p>
+ A synonym for <em class="parameter"><code>+[no]aaonly</code></em>.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]adflag</code></span></dt>
+<dd><p>
+ Set [do not set] the AD (authentic data) bit in the query. The
+ AD bit
+ currently has a standard meaning only in responses, not in
+ queries,
+ but the ability to set the bit in the query is provided for
+ completeness.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]cdflag</code></span></dt>
+<dd><p>
+ Set [do not set] the CD (checking disabled) bit in the query.
+ This
+ requests the server to not perform DNSSEC validation of
+ responses.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]cl</code></span></dt>
+<dd><p>
+ Display [do not display] the CLASS when printing the record.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]ttlid</code></span></dt>
+<dd><p>
+ Display [do not display] the TTL when printing the record.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]recurse</code></span></dt>
+<dd><p>
+ Toggle the setting of the RD (recursion desired) bit in the
+ query.
+ This bit is set by default, which means <span><strong class="command">dig</strong></span>
+ normally sends recursive queries. Recursion is automatically
+ disabled
+ when the <em class="parameter"><code>+nssearch</code></em> or
+ <em class="parameter"><code>+trace</code></em> query options are
+ used.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]nssearch</code></span></dt>
+<dd><p>
+ When this option is set, <span><strong class="command">dig</strong></span>
+ attempts to find the
+ authoritative name servers for the zone containing the name
+ being
+ looked up and display the SOA record that each name server has
+ for the
+ zone.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]trace</code></span></dt>
+<dd><p>
+ Toggle tracing of the delegation path from the root name servers
+ for
+ the name being looked up. Tracing is disabled by default. When
+ tracing is enabled, <span><strong class="command">dig</strong></span> makes
+ iterative queries to
+ resolve the name being looked up. It will follow referrals from
+ the
+ root servers, showing the answer from each server that was used
+ to
+ resolve the lookup.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]cmd</code></span></dt>
+<dd><p>
+ Toggles the printing of the initial comment in the output
+ identifying
+ the version of <span><strong class="command">dig</strong></span> and the query
+ options that have
+ been applied. This comment is printed by default.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]short</code></span></dt>
+<dd><p>
+ Provide a terse answer. The default is to print the answer in a
+ verbose form.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]identify</code></span></dt>
+<dd><p>
+ Show [or do not show] the IP address and port number that
+ supplied the
+ answer when the <em class="parameter"><code>+short</code></em> option
+ is enabled. If
+ short form answers are requested, the default is not to show the
+ source address and port number of the server that provided the
+ answer.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]comments</code></span></dt>
+<dd><p>
+ Toggle the display of comment lines in the output. The default
+ is to
+ print comments.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]stats</code></span></dt>
+<dd><p>
+ This query option toggles the printing of statistics: when the
+ query
+ was made, the size of the reply and so on. The default
+ behavior is
+ to print the query statistics.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]qr</code></span></dt>
+<dd><p>
+ Print [do not print] the query as it is sent.
+ By default, the query is not printed.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]question</code></span></dt>
+<dd><p>
+ Print [do not print] the question section of a query when an
+ answer is
+ returned. The default is to print the question section as a
+ comment.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]answer</code></span></dt>
+<dd><p>
+ Display [do not display] the answer section of a reply. The
+ default
+ is to display it.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]authority</code></span></dt>
+<dd><p>
+ Display [do not display] the authority section of a reply. The
+ default is to display it.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]additional</code></span></dt>
+<dd><p>
+ Display [do not display] the additional section of a reply.
+ The default is to display it.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]all</code></span></dt>
+<dd><p>
+ Set or clear all display flags.
+ </p></dd>
+<dt><span class="term"><code class="option">+time=T</code></span></dt>
+<dd><p>
+
+ Sets the timeout for a query to
+ <em class="parameter"><code>T</code></em> seconds. The default
+ timeout is 5 seconds.
+ An attempt to set <em class="parameter"><code>T</code></em> to less
+ than 1 will result
+ in a query timeout of 1 second being applied.
+ </p></dd>
+<dt><span class="term"><code class="option">+tries=T</code></span></dt>
+<dd><p>
+ Sets the number of times to try UDP queries to server to
+ <em class="parameter"><code>T</code></em> instead of the default, 3.
+ If
+ <em class="parameter"><code>T</code></em> is less than or equal to
+ zero, the number of
+ tries is silently rounded up to 1.
+ </p></dd>
+<dt><span class="term"><code class="option">+retry=T</code></span></dt>
+<dd><p>
+ Sets the number of times to retry UDP queries to server to
+ <em class="parameter"><code>T</code></em> instead of the default, 2.
+ Unlike
+ <em class="parameter"><code>+tries</code></em>, this does not include
+ the initial
+ query.
+ </p></dd>
+<dt><span class="term"><code class="option">+ndots=D</code></span></dt>
+<dd><p>
+ Set the number of dots that have to appear in
+ <em class="parameter"><code>name</code></em> to <em class="parameter"><code>D</code></em> for it to be
+ considered absolute. The default value is that defined using
+ the
+ ndots statement in <code class="filename">/etc/resolv.conf</code>, or 1 if no
+ ndots statement is present. Names with fewer dots are
+ interpreted as
+ relative names and will be searched for in the domains listed in
+ the
+ <code class="option">search</code> or <code class="option">domain</code> directive in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p></dd>
+<dt><span class="term"><code class="option">+bufsize=B</code></span></dt>
+<dd><p>
+ Set the UDP message buffer size advertised using EDNS0 to
+ <em class="parameter"><code>B</code></em> bytes. The maximum and minimum sizes
+ of this buffer are 65535 and 0 respectively. Values outside
+ this range are rounded up or down appropriately.
+ Values other than zero will cause a EDNS query to be sent.
+ </p></dd>
+<dt><span class="term"><code class="option">+edns=#</code></span></dt>
+<dd><p>
+ Specify the EDNS version to query with. Valid values
+ are 0 to 255. Setting the EDNS version will cause a
+ EDNS query to be sent. <code class="option">+noedns</code> clears the
+ remembered EDNS version.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]multiline</code></span></dt>
+<dd><p>
+ Print records like the SOA records in a verbose multi-line
+ format with human-readable comments. The default is to print
+ each record on a single line, to facilitate machine parsing
+ of the <span><strong class="command">dig</strong></span> output.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]fail</code></span></dt>
+<dd><p>
+ 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.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]besteffort</code></span></dt>
+<dd><p>
+ Attempt to display the contents of messages which are malformed.
+ The default is to not display malformed answers.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]dnssec</code></span></dt>
+<dd><p>
+ Requests DNSSEC records be sent by setting the DNSSEC OK bit
+ (DO)
+ in the OPT record in the additional section of the query.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]sigchase</code></span></dt>
+<dd><p>
+ Chase DNSSEC signature chains. Requires dig be compiled with
+ -DDIG_SIGCHASE.
+ </p></dd>
+<dt><span class="term"><code class="option">+trusted-key=####</code></span></dt>
+<dd>
+<p>
+ Specifies a file containing trusted keys to be used with
+ <code class="option">+sigchase</code>. Each DNSKEY record must be
+ on its own line.
+ </p>
+<p>
+ If not specified <span><strong class="command">dig</strong></span> will look for
+ <code class="filename">/etc/trusted-key.key</code> then
+ <code class="filename">trusted-key.key</code> in the current directory.
+ </p>
+<p>
+ Requires dig be compiled with -DDIG_SIGCHASE.
+ </p>
+</dd>
+<dt><span class="term"><code class="option">+[no]topdown</code></span></dt>
+<dd><p>
+ When chasing DNSSEC signature chains perform a top-down
+ validation.
+ Requires dig be compiled with -DDIG_SIGCHASE.
+ </p></dd>
+<dt><span class="term"><code class="option">+[no]nsid</code></span></dt>
+<dd><p>
+ Include an EDNS name server ID request when sending a query.
+ </p></dd>
+</dl></div>
+<p>
+
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2629560"></a><h2>MULTIPLE QUERIES</h2>
+<p>
+ The BIND 9 implementation of <span><strong class="command">dig </strong></span>
+ supports
+ specifying multiple queries on the command line (in addition to
+ supporting the <code class="option">-f</code> batch file option). Each of those
+ queries can be supplied with its own set of flags, options and query
+ options.
+ </p>
+<p>
+ In this case, each <em class="parameter"><code>query</code></em> argument
+ represent an
+ individual query in the command-line syntax described above. Each
+ consists of any of the standard options and flags, the name to be
+ looked up, an optional query type and class and any query options that
+ should be applied to that query.
+ </p>
+<p>
+ A global set of query options, which should be applied to all queries,
+ can also be supplied. These global query options must precede the
+ first tuple of name, class, type, options, flags, and query options
+ supplied on the command line. Any global query options (except
+ the <code class="option">+[no]cmd</code> option) can be
+ overridden by a query-specific set of query options. For example:
+ </p>
+<pre class="programlisting">
+dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr
+</pre>
+<p>
+ shows how <span><strong class="command">dig</strong></span> could be used from the
+ command line
+ to make three lookups: an ANY query for <code class="literal">www.isc.org</code>, a
+ reverse lookup of 127.0.0.1 and a query for the NS records of
+ <code class="literal">isc.org</code>.
+
+ A global query option of <em class="parameter"><code>+qr</code></em> is
+ applied, so
+ that <span><strong class="command">dig</strong></span> shows the initial query it made
+ for each
+ lookup. The final query has a local query option of
+ <em class="parameter"><code>+noqr</code></em> which means that <span><strong class="command">dig</strong></span>
+ will not print the initial query when it looks up the NS records for
+ <code class="literal">isc.org</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2629782"></a><h2>IDN SUPPORT</h2>
+<p>
+ If <span><strong class="command">dig</strong></span> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <span><strong class="command">dig</strong></span> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, defines
+ the <code class="envar">IDN_DISABLE</code> environment variable.
+ The IDN support is disabled if the variable is set when
+ <span><strong class="command">dig</strong></span> runs.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2629811"></a><h2>FILES</h2>
+<p><code class="filename">/etc/resolv.conf</code>
+ </p>
+<p><code class="filename">${HOME}/.digrc</code>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2629832"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">host</span>(1)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <em class="citetitle">RFC1035</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2629938"></a><h2>BUGS</h2>
+<p>
+ There are probably too many query options.
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="Bv9ARM.ch10.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.host.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">Manual pages </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> host</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.dnssec-dsfromkey.html b/doc/arm/man.dnssec-dsfromkey.html
new file mode 100644
index 0000000..347c421
--- /dev/null
+++ b/doc/arm/man.dnssec-dsfromkey.html
@@ -0,0 +1,170 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.dnssec-dsfromkey.html,v 1.6 2008/11/09 01:11:56 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-dsfromkey</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.host.html" title="host">
+<link rel="next" href="man.dnssec-keyfromlabel.html" title="dnssec-keyfromlabel">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><span class="application">dnssec-dsfromkey</span></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.host.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.dnssec-keyfromlabel.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.dnssec-dsfromkey"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-dsfromkey</span> &#8212; DNSSEC DS RR generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-dsfromkey</code> [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-1</code>] [<code class="option">-2</code>] [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] {keyfile}</p></div>
+<div class="cmdsynopsis"><p><code class="command">dnssec-dsfromkey</code> {-s} [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-1</code>] [<code class="option">-2</code>] [<code class="option">-a <em class="replaceable"><code>alg</code></em></code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-d <em class="replaceable"><code>dir</code></em></code>] {dnsname}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2602709"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-dsfromkey</strong></span>
+ outputs the Delegation Signer (DS) resource record (RR), as defined in
+ RFC 3658 and RFC 4509, for the given key(s).
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2602723"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-1</span></dt>
+<dd><p>
+ Use SHA-1 as the digest algorithm (the default is to use
+ both SHA-1 and SHA-256).
+ </p></dd>
+<dt><span class="term">-2</span></dt>
+<dd><p>
+ Use SHA-256 as the digest algorithm.
+ </p></dd>
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd><p>
+ Select the digest algorithm. The value of
+ <code class="option">algorithm</code> must be one of SHA-1 (SHA1) or
+ SHA-256 (SHA256). These values are case insensitive.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+<dt><span class="term">-s</span></dt>
+<dd><p>
+ 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.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Specifies the DNS class (default is IN), useful only
+ in the keyset mode.
+ </p></dd>
+<dt><span class="term">-d <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Look for <code class="filename">keyset</code> files in
+ <code class="option">directory</code> as the directory, ignored when
+ not in the keyset mode.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2602989"></a><h2>EXAMPLE</h2>
+<p>
+ To build the SHA-256 DS RR from the
+ <strong class="userinput"><code>Kexample.com.+003+26160</code></strong>
+ keyfile name, the following command would be issued:
+ </p>
+<p><strong class="userinput"><code>dnssec-dsfromkey -2 Kexample.com.+003+26160</code></strong>
+ </p>
+<p>
+ The command would print something like:
+ </p>
+<p><strong class="userinput"><code>example.com. IN DS 26160 5 2 3A1EADA7A74B8D0BA86726B0C227AA85AB8BBD2B2004F41A868A54F0 C5EA0B94</code></strong>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2603026"></a><h2>FILES</h2>
+<p>
+ The keyfile can be designed by the key identification
+ <code class="filename">Knnnn.+aaa+iiiii</code> or the full file name
+ <code class="filename">Knnnn.+aaa+iiiii.key</code> as generated by
+ <span class="refentrytitle">dnssec-keygen</span>(8).
+ </p>
+<p>
+ The keyset file name is built from the <code class="option">directory</code>,
+ the string <code class="filename">keyset-</code> and the
+ <code class="option">dnsname</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2603067"></a><h2>CAVEAT</h2>
+<p>
+ A keyfile error can give a "file not found" even if the file exists.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2603418"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 3658</em>,
+ <em class="citetitle">RFC 4509</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2603454"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.host.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.dnssec-keyfromlabel.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">host </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <span class="application">dnssec-keyfromlabel</span>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.dnssec-keyfromlabel.html b/doc/arm/man.dnssec-keyfromlabel.html
new file mode 100644
index 0000000..ca9f3da
--- /dev/null
+++ b/doc/arm/man.dnssec-keyfromlabel.html
@@ -0,0 +1,210 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.dnssec-keyfromlabel.html,v 1.31 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-keyfromlabel</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.dnssec-dsfromkey.html" title="dnssec-dsfromkey">
+<link rel="next" href="man.dnssec-keygen.html" title="dnssec-keygen">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><span class="application">dnssec-keyfromlabel</span></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.dnssec-dsfromkey.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.dnssec-keygen.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.dnssec-keyfromlabel"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-keyfromlabel</span> &#8212; DNSSEC key generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-keyfromlabel</code> {-a <em class="replaceable"><code>algorithm</code></em>} {-l <em class="replaceable"><code>label</code></em>} [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-k</code>] [<code class="option">-n <em class="replaceable"><code>nametype</code></em></code>] [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] {name}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2603227"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-keyfromlabel</strong></span>
+ 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.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2603241"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+<p>
+ Selects the cryptographic algorithm. The value of
+ <code class="option">algorithm</code> must be one of RSAMD5 (RSA)
+ or RSASHA1, DSA, NSEC3RSASHA1, NSEC3DSA or DH (Diffie Hellman).
+ These values are case insensitive.
+ </p>
+<p>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended.
+ </p>
+<p>
+ Note 2: DH automatically sets the -k flag.
+ </p>
+</dd>
+<dt><span class="term">-l <em class="replaceable"><code>label</code></em></span></dt>
+<dd><p>
+ Specifies the label of keys in the crypto hardware
+ (PKCS#11 device).
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>nametype</code></em></span></dt>
+<dd><p>
+ Specifies the owner type of the key. The value of
+ <code class="option">nametype</code> 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.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </p></dd>
+<dt><span class="term">-f <em class="replaceable"><code>flag</code></em></span></dt>
+<dd><p>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">dnssec-keygen</strong></span>.
+ </p></dd>
+<dt><span class="term">-k</span></dt>
+<dd><p>
+ Generate KEY records rather than DNSKEY records.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>protocol</code></em></span></dt>
+<dd><p>
+ 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.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd><p>
+ Indicates the use of the key. <code class="option">type</code> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2603642"></a><h2>GENERATED KEY FILES</h2>
+<p>
+ When <span><strong class="command">dnssec-keyfromlabel</strong></span> completes
+ successfully,
+ it prints a string of the form <code class="filename">Knnnn.+aaa+iiiii</code>
+ to the standard output. This is an identification string for
+ the key files it has generated.
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p><code class="filename">nnnn</code> is the key name.
+ </p></li>
+<li><p><code class="filename">aaa</code> is the numeric representation
+ of the
+ algorithm.
+ </p></li>
+<li><p><code class="filename">iiiii</code> is the key identifier (or
+ footprint).
+ </p></li>
+</ul></div>
+<p><span><strong class="command">dnssec-keyfromlabel</strong></span>
+ creates two files, with names based
+ on the printed string. <code class="filename">Knnnn.+aaa+iiiii.key</code>
+ contains the public key, and
+ <code class="filename">Knnnn.+aaa+iiiii.private</code> contains the
+ private
+ key.
+ </p>
+<p>
+ The <code class="filename">.key</code> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </p>
+<p>
+ The <code class="filename">.private</code> file contains algorithm
+ specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2603873"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 2539</em>,
+ <em class="citetitle">RFC 2845</em>,
+ <em class="citetitle">RFC 4033</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2603912"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.dnssec-dsfromkey.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.dnssec-keygen.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">
+<span class="application">dnssec-dsfromkey</span> </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <span class="application">dnssec-keygen</span>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.dnssec-keygen.html b/doc/arm/man.dnssec-keygen.html
new file mode 100644
index 0000000..35fe743
--- /dev/null
+++ b/doc/arm/man.dnssec-keygen.html
@@ -0,0 +1,270 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.dnssec-keygen.html,v 1.97 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-keygen</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.dnssec-keyfromlabel.html" title="dnssec-keyfromlabel">
+<link rel="next" href="man.dnssec-signzone.html" title="dnssec-signzone">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><span class="application">dnssec-keygen</span></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.dnssec-keyfromlabel.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.dnssec-signzone.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.dnssec-keygen"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-keygen</span> &#8212; DNSSEC key generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-keygen</code> {-a <em class="replaceable"><code>algorithm</code></em>} {-b <em class="replaceable"><code>keysize</code></em>} {-n <em class="replaceable"><code>nametype</code></em>} [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-e</code>] [<code class="option">-f <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-g <em class="replaceable"><code>generator</code></em></code>] [<code class="option">-h</code>] [<code class="option">-k</code>] [<code class="option">-p <em class="replaceable"><code>protocol</code></em></code>] [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-s <em class="replaceable"><code>strength</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] {name}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2604490"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-keygen</strong></span>
+ 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.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2604504"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a <em class="replaceable"><code>algorithm</code></em></span></dt>
+<dd>
+<p>
+ Selects the cryptographic algorithm. The value of
+ <code class="option">algorithm</code> must be one of RSAMD5 (RSA) or RSASHA1,
+ DSA, NSEC3RSASHA1, NSEC3DSA, DH (Diffie Hellman), or HMAC-MD5.
+ These values are case insensitive.
+ </p>
+<p>
+ Note 1: that for DNSSEC, RSASHA1 is a mandatory to implement
+ algorithm, and DSA is recommended. For TSIG, HMAC-MD5 is
+ mandatory.
+ </p>
+<p>
+ Note 2: HMAC-MD5 and DH automatically set the -k flag.
+ </p>
+</dd>
+<dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt>
+<dd><p>
+ Specifies the number of bits in the key. The choice of key
+ size depends on the algorithm used. RSAMD5 / RSASHA1 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-MD5 keys must be
+ between 1 and 512 bits.
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>nametype</code></em></span></dt>
+<dd><p>
+ Specifies the owner type of the key. The value of
+ <code class="option">nametype</code> 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.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Indicates that the DNS record containing the key should have
+ the specified class. If not specified, class IN is used.
+ </p></dd>
+<dt><span class="term">-e</span></dt>
+<dd><p>
+ If generating an RSAMD5/RSASHA1 key, use a large exponent.
+ </p></dd>
+<dt><span class="term">-f <em class="replaceable"><code>flag</code></em></span></dt>
+<dd><p>
+ Set the specified flag in the flag field of the KEY/DNSKEY record.
+ The only recognized flag is KSK (Key Signing Key) DNSKEY.
+ </p></dd>
+<dt><span class="term">-g <em class="replaceable"><code>generator</code></em></span></dt>
+<dd><p>
+ If generating a Diffie Hellman key, use this generator.
+ Allowed values are 2 and 5. If no generator
+ is specified, a known prime from RFC 2539 will be used
+ if possible; otherwise the default is 2.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">dnssec-keygen</strong></span>.
+ </p></dd>
+<dt><span class="term">-k</span></dt>
+<dd><p>
+ Generate KEY records rather than DNSKEY records.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>protocol</code></em></span></dt>
+<dd><p>
+ 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.
+ </p></dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomdev</code></em></span></dt>
+<dd><p>
+ Specifies the source of randomness. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>strength</code></em></span></dt>
+<dd><p>
+ Specifies the strength value of the key. The strength is
+ a number between 0 and 15, and currently has no defined
+ purpose in DNSSEC.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd><p>
+ Indicates the use of the key. <code class="option">type</code> must be
+ one of AUTHCONF, NOAUTHCONF, NOAUTH, or NOCONF. The default
+ is AUTHCONF. AUTH refers to the ability to authenticate
+ data, and CONF the ability to encrypt data.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2604848"></a><h2>GENERATED KEYS</h2>
+<p>
+ When <span><strong class="command">dnssec-keygen</strong></span> completes
+ successfully,
+ it prints a string of the form <code class="filename">Knnnn.+aaa+iiiii</code>
+ to the standard output. This is an identification string for
+ the key it has generated.
+ </p>
+<div class="itemizedlist"><ul type="disc">
+<li><p><code class="filename">nnnn</code> is the key name.
+ </p></li>
+<li><p><code class="filename">aaa</code> is the numeric representation
+ of the
+ algorithm.
+ </p></li>
+<li><p><code class="filename">iiiii</code> is the key identifier (or
+ footprint).
+ </p></li>
+</ul></div>
+<p><span><strong class="command">dnssec-keygen</strong></span>
+ creates two files, with names based
+ on the printed string. <code class="filename">Knnnn.+aaa+iiiii.key</code>
+ contains the public key, and
+ <code class="filename">Knnnn.+aaa+iiiii.private</code> contains the
+ private
+ key.
+ </p>
+<p>
+ The <code class="filename">.key</code> file contains a DNS KEY record
+ that
+ can be inserted into a zone file (directly or with a $INCLUDE
+ statement).
+ </p>
+<p>
+ The <code class="filename">.private</code> file contains
+ algorithm-specific
+ fields. For obvious security reasons, this file does not have
+ general read permission.
+ </p>
+<p>
+ Both <code class="filename">.key</code> and <code class="filename">.private</code>
+ files are generated for symmetric encryption algorithms such as
+ HMAC-MD5, even though the public and private key are equivalent.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2607208"></a><h2>EXAMPLE</h2>
+<p>
+ To generate a 768-bit DSA key for the domain
+ <strong class="userinput"><code>example.com</code></strong>, the following command would be
+ issued:
+ </p>
+<p><strong class="userinput"><code>dnssec-keygen -a DSA -b 768 -n ZONE example.com</code></strong>
+ </p>
+<p>
+ The command would print a string of the form:
+ </p>
+<p><strong class="userinput"><code>Kexample.com.+003+26160</code></strong>
+ </p>
+<p>
+ In this example, <span><strong class="command">dnssec-keygen</strong></span> creates
+ the files <code class="filename">Kexample.com.+003+26160.key</code>
+ and
+ <code class="filename">Kexample.com.+003+26160.private</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2607333"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-signzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 2539</em>,
+ <em class="citetitle">RFC 2845</em>,
+ <em class="citetitle">RFC 4033</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2607364"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.dnssec-keyfromlabel.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.dnssec-signzone.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">
+<span class="application">dnssec-keyfromlabel</span> </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <span class="application">dnssec-signzone</span>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.dnssec-signzone.html b/doc/arm/man.dnssec-signzone.html
new file mode 100644
index 0000000..237d19d
--- /dev/null
+++ b/doc/arm/man.dnssec-signzone.html
@@ -0,0 +1,340 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.dnssec-signzone.html,v 1.94 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dnssec-signzone</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.dnssec-keygen.html" title="dnssec-keygen">
+<link rel="next" href="man.named-checkconf.html" title="named-checkconf">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><span class="application">dnssec-signzone</span></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.dnssec-keygen.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.named-checkconf.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.dnssec-signzone"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">dnssec-signzone</span> &#8212; DNSSEC zone signing tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">dnssec-signzone</code> [<code class="option">-a</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-d <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-e <em class="replaceable"><code>end-time</code></em></code>] [<code class="option">-f <em class="replaceable"><code>output-file</code></em></code>] [<code class="option">-g</code>] [<code class="option">-h</code>] [<code class="option">-k <em class="replaceable"><code>key</code></em></code>] [<code class="option">-l <em class="replaceable"><code>domain</code></em></code>] [<code class="option">-i <em class="replaceable"><code>interval</code></em></code>] [<code class="option">-I <em class="replaceable"><code>input-format</code></em></code>] [<code class="option">-j <em class="replaceable"><code>jitter</code></em></code>] [<code class="option">-N <em class="replaceable"><code>soa-serial-format</code></em></code>] [<code class="option">-o <em class="replaceable"><code>origin</code></em></code>] [<code class="option">-O <em class="replaceable"><code>output-format</code></em></code>] [<code class="option">-p</code>] [<code class="option">-r <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-s <em class="replaceable"><code>start-time</code></em></code>] [<code class="option">-t</code>] [<code class="option">-v <em class="replaceable"><code>level</code></em></code>] [<code class="option">-z</code>] [<code class="option">-3 <em class="replaceable"><code>salt</code></em></code>] [<code class="option">-H <em class="replaceable"><code>iterations</code></em></code>] [<code class="option">-A</code>] {zonefile} [key...]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2606153"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dnssec-signzone</strong></span>
+ 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
+ <code class="filename">keyset</code> file for each child zone.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2606172"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a</span></dt>
+<dd><p>
+ Verify all generated signatures.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Specifies the DNS class of the zone.
+ </p></dd>
+<dt><span class="term">-k <em class="replaceable"><code>key</code></em></span></dt>
+<dd><p>
+ Treat specified key as a key signing key ignoring any
+ key flags. This option may be specified multiple times.
+ </p></dd>
+<dt><span class="term">-l <em class="replaceable"><code>domain</code></em></span></dt>
+<dd><p>
+ Generate a DLV set in addition to the key (DNSKEY) and DS sets.
+ The domain is appended to the name of the records.
+ </p></dd>
+<dt><span class="term">-d <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Look for <code class="filename">keyset</code> files in
+ <code class="option">directory</code> as the directory
+ </p></dd>
+<dt><span class="term">-g</span></dt>
+<dd><p>
+ Generate DS records for child zones from keyset files.
+ Existing DS records will be removed.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>start-time</code></em></span></dt>
+<dd><p>
+ Specify the date and time when the generated RRSIG records
+ become valid. This can be either an absolute or relative
+ time. An absolute start time is indicated by a number
+ in YYYYMMDDHHMMSS notation; 20000530144500 denotes
+ 14:45:00 UTC on May 30th, 2000. A relative start time is
+ indicated by +N, which is N seconds from the current time.
+ If no <code class="option">start-time</code> is specified, the current
+ time minus 1 hour (to allow for clock skew) is used.
+ </p></dd>
+<dt><span class="term">-e <em class="replaceable"><code>end-time</code></em></span></dt>
+<dd><p>
+ Specify the date and time when the generated RRSIG records
+ expire. As with <code class="option">start-time</code>, 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 <code class="option">end-time</code> is
+ specified, 30 days from the start time is used as a default.
+ </p></dd>
+<dt><span class="term">-f <em class="replaceable"><code>output-file</code></em></span></dt>
+<dd><p>
+ The name of the output file containing the signed zone. The
+ default is to append <code class="filename">.signed</code> to
+ the
+ input filename.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">dnssec-signzone</strong></span>.
+ </p></dd>
+<dt><span class="term">-i <em class="replaceable"><code>interval</code></em></span></dt>
+<dd>
+<p>
+ When a previously-signed zone is passed as input, records
+ may be resigned. The <code class="option">interval</code> option
+ specifies the cycle interval as an offset from the current
+ time (in seconds). If a RRSIG record expires after the
+ cycle interval, it is retained. Otherwise, it is considered
+ to be expiring soon, and it will be replaced.
+ </p>
+<p>
+ The default cycle interval is one quarter of the difference
+ between the signature end and start times. So if neither
+ <code class="option">end-time</code> or <code class="option">start-time</code>
+ are specified, <span><strong class="command">dnssec-signzone</strong></span>
+ generates
+ signatures that are valid for 30 days, with a cycle
+ interval of 7.5 days. Therefore, if any existing RRSIG records
+ are due to expire in less than 7.5 days, they would be
+ replaced.
+ </p>
+</dd>
+<dt><span class="term">-I <em class="replaceable"><code>input-format</code></em></span></dt>
+<dd><p>
+ The format of the input zone file.
+ Possible formats are <span><strong class="command">"text"</strong></span> (default)
+ and <span><strong class="command">"raw"</strong></span>.
+ This option is primarily intended to be used for dynamic
+ signed zones so that the dumped zone file in a non-text
+ format containing updates can be signed directly.
+ The use of this option does not make much sense for
+ non-dynamic zones.
+ </p></dd>
+<dt><span class="term">-j <em class="replaceable"><code>jitter</code></em></span></dt>
+<dd>
+<p>
+ When signing a zone with a fixed signature lifetime, all
+ RRSIG records issued at the time of signing expires
+ simultaneously. If the zone is incrementally signed, i.e.
+ a previously-signed zone is passed as input to the signer,
+ all expired signatures have to be regenerated at about the
+ same time. The <code class="option">jitter</code> option specifies a
+ jitter window that will be used to randomize the signature
+ expire time, thus spreading incremental signature
+ regeneration over time.
+ </p>
+<p>
+ Signature lifetime jitter also to some extent benefits
+ validators and servers by spreading out cache expiration,
+ i.e. if large numbers of RRSIGs don't expire at the same time
+ from all caches there will be less congestion than if all
+ validators need to refetch at mostly the same time.
+ </p>
+</dd>
+<dt><span class="term">-n <em class="replaceable"><code>ncpus</code></em></span></dt>
+<dd><p>
+ Specifies the number of threads to use. By default, one
+ thread is started for each detected CPU.
+ </p></dd>
+<dt><span class="term">-N <em class="replaceable"><code>soa-serial-format</code></em></span></dt>
+<dd>
+<p>
+ The SOA serial number format of the signed zone.
+ Possible formats are <span><strong class="command">"keep"</strong></span> (default),
+ <span><strong class="command">"increment"</strong></span> and
+ <span><strong class="command">"unixtime"</strong></span>.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command">"keep"</strong></span></span></dt>
+<dd><p>Do not modify the SOA serial number.</p></dd>
+<dt><span class="term"><span><strong class="command">"increment"</strong></span></span></dt>
+<dd><p>Increment the SOA serial number using RFC 1982
+ arithmetics.</p></dd>
+<dt><span class="term"><span><strong class="command">"unixtime"</strong></span></span></dt>
+<dd><p>Set the SOA serial number to the number of seconds
+ since epoch.</p></dd>
+</dl></div>
+</dd>
+<dt><span class="term">-o <em class="replaceable"><code>origin</code></em></span></dt>
+<dd><p>
+ The zone origin. If not specified, the name of the zone file
+ is assumed to be the origin.
+ </p></dd>
+<dt><span class="term">-O <em class="replaceable"><code>output-format</code></em></span></dt>
+<dd><p>
+ The format of the output file containing the signed zone.
+ Possible formats are <span><strong class="command">"text"</strong></span> (default)
+ and <span><strong class="command">"raw"</strong></span>.
+ </p></dd>
+<dt><span class="term">-p</span></dt>
+<dd><p>
+ Use pseudo-random data when signing the zone. This is faster,
+ but less secure, than using real random data. This option
+ may be useful when signing large zones or when the entropy
+ source is limited.
+ </p></dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomdev</code></em></span></dt>
+<dd><p>
+ Specifies the source of randomness. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p></dd>
+<dt><span class="term">-t</span></dt>
+<dd><p>
+ Print statistics at completion.
+ </p></dd>
+<dt><span class="term">-v <em class="replaceable"><code>level</code></em></span></dt>
+<dd><p>
+ Sets the debugging level.
+ </p></dd>
+<dt><span class="term">-z</span></dt>
+<dd><p>
+ Ignore KSK flag on key when determining what to sign.
+ </p></dd>
+<dt><span class="term">-3 <em class="replaceable"><code>salt</code></em></span></dt>
+<dd><p>
+ Generate a NSEC3 chain with the given hex encoded salt.
+ A dash (<em class="replaceable"><code>salt</code></em>) can
+ be used to indicate that no salt is to be used when generating the NSEC3 chain.
+ </p></dd>
+<dt><span class="term">-H <em class="replaceable"><code>iterations</code></em></span></dt>
+<dd><p>
+ When generating a NSEC3 chain use this many interations. The
+ default is 100.
+ </p></dd>
+<dt><span class="term">-A</span></dt>
+<dd><p>
+ When generating a NSEC3 chain set the OPTOUT flag on all
+ NSEC3 records and do not generate NSEC3 records for insecure
+ delegations.
+ </p></dd>
+<dt><span class="term">zonefile</span></dt>
+<dd><p>
+ The file containing the zone to be signed.
+ </p></dd>
+<dt><span class="term">key</span></dt>
+<dd><p>
+ Specify which keys should be used to sign the zone. If
+ no keys are specified, then the zone will be examined
+ for DNSKEY records at the zone apex. If these are found and
+ there are matching private keys, in the current directory,
+ then these will be used for signing.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2657291"></a><h2>EXAMPLE</h2>
+<p>
+ The following command signs the <strong class="userinput"><code>example.com</code></strong>
+ zone with the DSA key generated by <span><strong class="command">dnssec-keygen</strong></span>
+ (Kexample.com.+003+17247). The zone's keys must be in the master
+ file (<code class="filename">db.example.com</code>). This invocation looks
+ for <code class="filename">keyset</code> files, in the current directory,
+ so that DS records can be generated from them (<span><strong class="command">-g</strong></span>).
+ </p>
+<pre class="programlisting">% dnssec-signzone -g -o example.com db.example.com \
+Kexample.com.+003+17247
+db.example.com.signed
+%</pre>
+<p>
+ In the above example, <span><strong class="command">dnssec-signzone</strong></span> creates
+ the file <code class="filename">db.example.com.signed</code>. This
+ file should be referenced in a zone statement in a
+ <code class="filename">named.conf</code> file.
+ </p>
+<p>
+ This example re-signs a previously signed zone with default parameters.
+ The private keys are assumed to be in the current directory.
+ </p>
+<pre class="programlisting">% cp db.example.com.signed db.example.com
+% dnssec-signzone -o example.com db.example.com
+db.example.com.signed
+%</pre>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2657364"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>,
+ <em class="citetitle">RFC 4033</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2657388"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.dnssec-keygen.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.named-checkconf.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">
+<span class="application">dnssec-keygen</span> </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <span class="application">named-checkconf</span>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.host.html b/doc/arm/man.host.html
new file mode 100644
index 0000000..7d1fa9e
--- /dev/null
+++ b/doc/arm/man.host.html
@@ -0,0 +1,249 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.host.html,v 1.93 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>host</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.dig.html" title="dig">
+<link rel="next" href="man.dnssec-dsfromkey.html" title="dnssec-dsfromkey">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center">host</th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.dig.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.dnssec-dsfromkey.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.host"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>host &#8212; DNS lookup utility</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">host</code> [<code class="option">-aCdlnrsTwv</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-N <em class="replaceable"><code>ndots</code></em></code>] [<code class="option">-R <em class="replaceable"><code>number</code></em></code>] [<code class="option">-t <em class="replaceable"><code>type</code></em></code>] [<code class="option">-W <em class="replaceable"><code>wait</code></em></code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-4</code>] [<code class="option">-6</code>] {name} [server]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2601862"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">host</strong></span>
+ is a simple utility for performing DNS lookups.
+ It is normally used to convert names to IP addresses and vice versa.
+ When no arguments or options are given,
+ <span><strong class="command">host</strong></span>
+ prints a short summary of its command line arguments and options.
+ </p>
+<p><em class="parameter"><code>name</code></em> is the domain name that is to be
+ looked
+ up. It can also be a dotted-decimal IPv4 address or a colon-delimited
+ IPv6 address, in which case <span><strong class="command">host</strong></span> will by
+ default
+ perform a reverse lookup for that address.
+ <em class="parameter"><code>server</code></em> is an optional argument which
+ is either
+ the name or IP address of the name server that <span><strong class="command">host</strong></span>
+ should query instead of the server or servers listed in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+<p>
+ The <code class="option">-a</code> (all) option is equivalent to setting the
+ <code class="option">-v</code> option and asking <span><strong class="command">host</strong></span> to make
+ a query of type ANY.
+ </p>
+<p>
+ When the <code class="option">-C</code> option is used, <span><strong class="command">host</strong></span>
+ will attempt to display the SOA records for zone
+ <em class="parameter"><code>name</code></em> from all the listed
+ authoritative name
+ servers for that zone. The list of name servers is defined by the NS
+ records that are found for the zone.
+ </p>
+<p>
+ The <code class="option">-c</code> option instructs to make a DNS query of class
+ <em class="parameter"><code>class</code></em>. This can be used to lookup
+ Hesiod or
+ Chaosnet class resource records. The default class is IN (Internet).
+ </p>
+<p>
+ Verbose output is generated by <span><strong class="command">host</strong></span> when
+ the
+ <code class="option">-d</code> or <code class="option">-v</code> option is used. The two
+ options are equivalent. They have been provided for backwards
+ compatibility. In previous versions, the <code class="option">-d</code> option
+ switched on debugging traces and <code class="option">-v</code> enabled verbose
+ output.
+ </p>
+<p>
+ List mode is selected by the <code class="option">-l</code> option. This makes
+ <span><strong class="command">host</strong></span> perform a zone transfer for zone
+ <em class="parameter"><code>name</code></em>. Transfer the zone printing out
+ the NS, PTR
+ and address records (A/AAAA). If combined with <code class="option">-a</code>
+ all records will be printed.
+ </p>
+<p>
+ The <code class="option">-i</code>
+ option specifies that reverse lookups of IPv6 addresses should
+ use the IP6.INT domain as defined in RFC1886.
+ The default is to use IP6.ARPA.
+ </p>
+<p>
+ The <code class="option">-N</code> option sets the number of dots that have to be
+ in <em class="parameter"><code>name</code></em> for it to be considered
+ absolute. The
+ default value is that defined using the ndots statement in
+ <code class="filename">/etc/resolv.conf</code>, or 1 if no ndots
+ statement is
+ present. Names with fewer dots are interpreted as relative names and
+ will be searched for in the domains listed in the <span class="type">search</span>
+ or <span class="type">domain</span> directive in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+<p>
+ The number of UDP retries for a lookup can be changed with the
+ <code class="option">-R</code> option. <em class="parameter"><code>number</code></em>
+ indicates
+ how many times <span><strong class="command">host</strong></span> will repeat a query
+ that does
+ not get answered. The default number of retries is 1. If
+ <em class="parameter"><code>number</code></em> is negative or zero, the
+ number of
+ retries will default to 1.
+ </p>
+<p>
+ Non-recursive queries can be made via the <code class="option">-r</code> option.
+ Setting this option clears the <span class="type">RD</span> &#8212; recursion
+ desired &#8212; bit in the query which <span><strong class="command">host</strong></span> makes.
+ This should mean that the name server receiving the query will not
+ attempt to resolve <em class="parameter"><code>name</code></em>. The
+ <code class="option">-r</code> option enables <span><strong class="command">host</strong></span>
+ to mimic
+ the behavior of a name server by making non-recursive queries and
+ expecting to receive answers to those queries that are usually
+ referrals to other name servers.
+ </p>
+<p>
+ By default <span><strong class="command">host</strong></span> uses UDP when making
+ queries. The
+ <code class="option">-T</code> option makes it use a TCP connection when querying
+ the name server. TCP will be automatically selected for queries that
+ require it, such as zone transfer (AXFR) requests.
+ </p>
+<p>
+ The <code class="option">-4</code> option forces <span><strong class="command">host</strong></span> to only
+ use IPv4 query transport. The <code class="option">-6</code> option forces
+ <span><strong class="command">host</strong></span> to only use IPv6 query transport.
+ </p>
+<p>
+ The <code class="option">-t</code> option is used to select the query type.
+ <em class="parameter"><code>type</code></em> can be any recognized query
+ type: CNAME,
+ NS, SOA, SIG, KEY, AXFR, etc. When no query type is specified,
+ <span><strong class="command">host</strong></span> automatically selects an appropriate
+ query
+ type. By default it looks for A, AAAA, and MX records, but if the
+ <code class="option">-C</code> option was given, queries will be made for SOA
+ records, and if <em class="parameter"><code>name</code></em> is a
+ dotted-decimal IPv4
+ address or colon-delimited IPv6 address, <span><strong class="command">host</strong></span> will
+ query for PTR records. If a query type of IXFR is chosen the starting
+ serial number can be specified by appending an equal followed by the
+ starting serial number (e.g. -t IXFR=12345678).
+ </p>
+<p>
+ The time to wait for a reply can be controlled through the
+ <code class="option">-W</code> and <code class="option">-w</code> options. The
+ <code class="option">-W</code> option makes <span><strong class="command">host</strong></span>
+ wait for
+ <em class="parameter"><code>wait</code></em> seconds. If <em class="parameter"><code>wait</code></em>
+ is less than one, the wait interval is set to one second. When the
+ <code class="option">-w</code> option is used, <span><strong class="command">host</strong></span>
+ will
+ effectively wait forever for a reply. The time to wait for a response
+ will be set to the number of seconds given by the hardware's maximum
+ value for an integer quantity.
+ </p>
+<p>
+ The <code class="option">-s</code> option tells <span><strong class="command">host</strong></span>
+ <span class="emphasis"><em>not</em></span> to send the query to the next nameserver
+ if any server responds with a SERVFAIL response, which is the
+ reverse of normal stub resolver behavior.
+ </p>
+<p>
+ The <code class="option">-m</code> can be used to set the memory usage debugging
+ flags
+ <em class="parameter"><code>record</code></em>, <em class="parameter"><code>usage</code></em> and
+ <em class="parameter"><code>trace</code></em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2602513"></a><h2>IDN SUPPORT</h2>
+<p>
+ If <span><strong class="command">host</strong></span> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <span><strong class="command">host</strong></span> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, defines
+ the <code class="envar">IDN_DISABLE</code> environment variable.
+ The IDN support is disabled if the variable is set when
+ <span><strong class="command">host</strong></span> runs.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2602541"></a><h2>FILES</h2>
+<p><code class="filename">/etc/resolv.conf</code>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2602555"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">dig</span>(1)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>.
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.dig.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.dnssec-dsfromkey.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">dig </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <span class="application">dnssec-dsfromkey</span>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.named-checkconf.html b/doc/arm/man.named-checkconf.html
new file mode 100644
index 0000000..5c6adcd
--- /dev/null
+++ b/doc/arm/man.named-checkconf.html
@@ -0,0 +1,134 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.named-checkconf.html,v 1.92 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named-checkconf</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.dnssec-signzone.html" title="dnssec-signzone">
+<link rel="next" href="man.named-checkzone.html" title="named-checkzone">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><span class="application">named-checkconf</span></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.dnssec-signzone.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.named-checkzone.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.named-checkconf"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">named-checkconf</span> &#8212; named configuration file syntax checking tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">named-checkconf</code> [<code class="option">-h</code>] [<code class="option">-v</code>] [<code class="option">-j</code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] {filename} [<code class="option">-z</code>]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2606791"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">named-checkconf</strong></span>
+ checks the syntax, but not the semantics, of a named
+ configuration file.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2606805"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Print the usage summary and exit.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Chroot to <code class="filename">directory</code> so that
+ include
+ directives in the configuration file are processed as if
+ run by a similarly chrooted named.
+ </p></dd>
+<dt><span class="term">-v</span></dt>
+<dd><p>
+ Print the version of the <span><strong class="command">named-checkconf</strong></span>
+ program and exit.
+ </p></dd>
+<dt><span class="term">-z</span></dt>
+<dd><p>
+ Perform a test load of all master zones found in
+ <code class="filename">named.conf</code>.
+ </p></dd>
+<dt><span class="term">-j</span></dt>
+<dd><p>
+ When loading a zonefile read the journal if it exists.
+ </p></dd>
+<dt><span class="term">filename</span></dt>
+<dd><p>
+ The name of the configuration file to be checked. If not
+ specified, it defaults to <code class="filename">/etc/named.conf</code>.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2606921"></a><h2>RETURN VALUES</h2>
+<p><span><strong class="command">named-checkconf</strong></span>
+ returns an exit status of 1 if
+ errors were detected and 0 otherwise.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2606935"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named-checkzone</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2606965"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.dnssec-signzone.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.named-checkzone.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">
+<span class="application">dnssec-signzone</span> </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <span class="application">named-checkzone</span>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.named-checkzone.html b/doc/arm/man.named-checkzone.html
new file mode 100644
index 0000000..70b029f
--- /dev/null
+++ b/doc/arm/man.named-checkzone.html
@@ -0,0 +1,300 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.named-checkzone.html,v 1.98 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named-checkzone</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.named-checkconf.html" title="named-checkconf">
+<link rel="next" href="man.named.html" title="named">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><span class="application">named-checkzone</span></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.named-checkconf.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.named.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.named-checkzone"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">named-checkzone</span>, <span class="application">named-compilezone</span> &#8212; zone file validity checking or converting tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">named-checkzone</code> [<code class="option">-d</code>] [<code class="option">-h</code>] [<code class="option">-j</code>] [<code class="option">-q</code>] [<code class="option">-v</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-f <em class="replaceable"><code>format</code></em></code>] [<code class="option">-F <em class="replaceable"><code>format</code></em></code>] [<code class="option">-i <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-k <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-m <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-M <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-n <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-o <em class="replaceable"><code>filename</code></em></code>] [<code class="option">-s <em class="replaceable"><code>style</code></em></code>] [<code class="option">-S <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-w <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-D</code>] [<code class="option">-W <em class="replaceable"><code>mode</code></em></code>] {zonename} {filename}</p></div>
+<div class="cmdsynopsis"><p><code class="command">named-compilezone</code> [<code class="option">-d</code>] [<code class="option">-j</code>] [<code class="option">-q</code>] [<code class="option">-v</code>] [<code class="option">-c <em class="replaceable"><code>class</code></em></code>] [<code class="option">-C <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-f <em class="replaceable"><code>format</code></em></code>] [<code class="option">-F <em class="replaceable"><code>format</code></em></code>] [<code class="option">-i <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-k <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-m <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-n <em class="replaceable"><code>mode</code></em></code>] [<code class="option">-o <em class="replaceable"><code>filename</code></em></code>] [<code class="option">-s <em class="replaceable"><code>style</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-w <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-D</code>] [<code class="option">-W <em class="replaceable"><code>mode</code></em></code>] {zonename} {filename}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2608388"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">named-checkzone</strong></span>
+ checks the syntax and integrity of a zone file. It performs the
+ same checks as <span><strong class="command">named</strong></span> does when loading a
+ zone. This makes <span><strong class="command">named-checkzone</strong></span> useful for
+ checking zone files before configuring them into a name server.
+ </p>
+<p>
+ <span><strong class="command">named-compilezone</strong></span> is similar to
+ <span><strong class="command">named-checkzone</strong></span>, but it always dumps the
+ zone contents to a specified file in a specified format.
+ Additionally, it applies stricter check levels by default,
+ since the dump output will be used as an actual zone file
+ loaded by <span><strong class="command">named</strong></span>.
+ When manually specified otherwise, the check levels must at
+ least be as strict as those specified in the
+ <span><strong class="command">named</strong></span> configuration file.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2608438"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-d</span></dt>
+<dd><p>
+ Enable debugging.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Print the usage summary and exit.
+ </p></dd>
+<dt><span class="term">-q</span></dt>
+<dd><p>
+ Quiet mode - exit code only.
+ </p></dd>
+<dt><span class="term">-v</span></dt>
+<dd><p>
+ Print the version of the <span><strong class="command">named-checkzone</strong></span>
+ program and exit.
+ </p></dd>
+<dt><span class="term">-j</span></dt>
+<dd><p>
+ When loading the zone file read the journal if it exists.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd><p>
+ Specify the class of the zone. If not specified "IN" is assumed.
+ </p></dd>
+<dt><span class="term">-i <em class="replaceable"><code>mode</code></em></span></dt>
+<dd>
+<p>
+ Perform post-load zone integrity checks. Possible modes are
+ <span><strong class="command">"full"</strong></span> (default),
+ <span><strong class="command">"full-sibling"</strong></span>,
+ <span><strong class="command">"local"</strong></span>,
+ <span><strong class="command">"local-sibling"</strong></span> and
+ <span><strong class="command">"none"</strong></span>.
+ </p>
+<p>
+ Mode <span><strong class="command">"full"</strong></span> checks that MX records
+ refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). Mode <span><strong class="command">"local"</strong></span> only
+ checks MX records which refer to in-zone hostnames.
+ </p>
+<p>
+ Mode <span><strong class="command">"full"</strong></span> checks that SRV records
+ refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). Mode <span><strong class="command">"local"</strong></span> only
+ checks SRV records which refer to in-zone hostnames.
+ </p>
+<p>
+ Mode <span><strong class="command">"full"</strong></span> checks that delegation NS
+ records refer to A or AAAA record (both in-zone and out-of-zone
+ hostnames). It also checks that glue address records
+ in the zone match those advertised by the child.
+ Mode <span><strong class="command">"local"</strong></span> only checks NS records which
+ refer to in-zone hostnames or that some required glue exists,
+ that is when the nameserver is in a child zone.
+ </p>
+<p>
+ Mode <span><strong class="command">"full-sibling"</strong></span> and
+ <span><strong class="command">"local-sibling"</strong></span> disable sibling glue
+ checks but are otherwise the same as <span><strong class="command">"full"</strong></span>
+ and <span><strong class="command">"local"</strong></span> respectively.
+ </p>
+<p>
+ Mode <span><strong class="command">"none"</strong></span> disables the checks.
+ </p>
+</dd>
+<dt><span class="term">-f <em class="replaceable"><code>format</code></em></span></dt>
+<dd><p>
+ Specify the format of the zone file.
+ Possible formats are <span><strong class="command">"text"</strong></span> (default)
+ and <span><strong class="command">"raw"</strong></span>.
+ </p></dd>
+<dt><span class="term">-F <em class="replaceable"><code>format</code></em></span></dt>
+<dd><p>
+ Specify the format of the output file specified.
+ Possible formats are <span><strong class="command">"text"</strong></span> (default)
+ and <span><strong class="command">"raw"</strong></span>.
+ For <span><strong class="command">named-checkzone</strong></span>,
+ this does not cause any effects unless it dumps the zone
+ contents.
+ </p></dd>
+<dt><span class="term">-k <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Perform <span><strong class="command">"check-names"</strong></span> checks with the
+ specified failure mode.
+ Possible modes are <span><strong class="command">"fail"</strong></span>
+ (default for <span><strong class="command">named-compilezone</strong></span>),
+ <span><strong class="command">"warn"</strong></span>
+ (default for <span><strong class="command">named-checkzone</strong></span>) and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">-m <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Specify whether MX records should be checked to see if they
+ are addresses. Possible modes are <span><strong class="command">"fail"</strong></span>,
+ <span><strong class="command">"warn"</strong></span> (default) and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">-M <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Check if a MX record refers to a CNAME.
+ Possible modes are <span><strong class="command">"fail"</strong></span>,
+ <span><strong class="command">"warn"</strong></span> (default) and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Specify whether NS records should be checked to see if they
+ are addresses.
+ Possible modes are <span><strong class="command">"fail"</strong></span>
+ (default for <span><strong class="command">named-compilezone</strong></span>),
+ <span><strong class="command">"warn"</strong></span>
+ (default for <span><strong class="command">named-checkzone</strong></span>) and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">-o <em class="replaceable"><code>filename</code></em></span></dt>
+<dd><p>
+ Write zone output to <code class="filename">filename</code>.
+ If <code class="filename">filename</code> is <code class="filename">-</code> then
+ write to standard out.
+ This is mandatory for <span><strong class="command">named-compilezone</strong></span>.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>style</code></em></span></dt>
+<dd><p>
+ Specify the style of the dumped zone file.
+ Possible styles are <span><strong class="command">"full"</strong></span> (default)
+ and <span><strong class="command">"relative"</strong></span>.
+ The full format is most suitable for processing
+ automatically by a separate script.
+ On the other hand, the relative format is more
+ human-readable and is thus suitable for editing by hand.
+ For <span><strong class="command">named-checkzone</strong></span>
+ this does not cause any effects unless it dumps the zone
+ contents.
+ It also does not have any meaning if the output format
+ is not text.
+ </p></dd>
+<dt><span class="term">-S <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Check if a SRV record refers to a CNAME.
+ Possible modes are <span><strong class="command">"fail"</strong></span>,
+ <span><strong class="command">"warn"</strong></span> (default) and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ Chroot to <code class="filename">directory</code> so that
+ include
+ directives in the configuration file are processed as if
+ run by a similarly chrooted named.
+ </p></dd>
+<dt><span class="term">-w <em class="replaceable"><code>directory</code></em></span></dt>
+<dd><p>
+ chdir to <code class="filename">directory</code> so that
+ relative
+ filenames in master file $INCLUDE directives work. This
+ is similar to the directory clause in
+ <code class="filename">named.conf</code>.
+ </p></dd>
+<dt><span class="term">-D</span></dt>
+<dd><p>
+ Dump zone file in canonical format.
+ This is always enabled for <span><strong class="command">named-compilezone</strong></span>.
+ </p></dd>
+<dt><span class="term">-W <em class="replaceable"><code>mode</code></em></span></dt>
+<dd><p>
+ Specify whether to check for non-terminal wildcards.
+ Non-terminal wildcards are almost always the result of a
+ failure to understand the wildcard matching algorithm (RFC 1034).
+ Possible modes are <span><strong class="command">"warn"</strong></span> (default)
+ and
+ <span><strong class="command">"ignore"</strong></span>.
+ </p></dd>
+<dt><span class="term">zonename</span></dt>
+<dd><p>
+ The domain name of the zone being checked.
+ </p></dd>
+<dt><span class="term">filename</span></dt>
+<dd><p>
+ The name of the zone file.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2658192"></a><h2>RETURN VALUES</h2>
+<p><span><strong class="command">named-checkzone</strong></span>
+ returns an exit status of 1 if
+ errors were detected and 0 otherwise.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2658205"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named-checkconf</span>(8)</span>,
+ <em class="citetitle">RFC 1035</em>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2658238"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.named-checkconf.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.named.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">
+<span class="application">named-checkconf</span> </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <span class="application">named</span>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.named.html b/doc/arm/man.named.html
new file mode 100644
index 0000000..f01124d
--- /dev/null
+++ b/doc/arm/man.named.html
@@ -0,0 +1,322 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.named.html,v 1.99 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>named</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.named-checkzone.html" title="named-checkzone">
+<link rel="next" href="man.nsupdate.html" title="nsupdate">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><span class="application">named</span></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.named-checkzone.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.nsupdate.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.named"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">named</span> &#8212; Internet domain name server</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">named</code> [<code class="option">-4</code>] [<code class="option">-6</code>] [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-d <em class="replaceable"><code>debug-level</code></em></code>] [<code class="option">-f</code>] [<code class="option">-g</code>] [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>] [<code class="option">-n <em class="replaceable"><code>#cpus</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-s</code>] [<code class="option">-S <em class="replaceable"><code>#max-socks</code></em></code>] [<code class="option">-t <em class="replaceable"><code>directory</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>] [<code class="option">-v</code>] [<code class="option">-V</code>] [<code class="option">-x <em class="replaceable"><code>cache-file</code></em></code>]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2609180"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">named</strong></span>
+ is a Domain Name System (DNS) server,
+ part of the BIND 9 distribution from ISC. For more
+ information on the DNS, see RFCs 1033, 1034, and 1035.
+ </p>
+<p>
+ When invoked without arguments, <span><strong class="command">named</strong></span>
+ will
+ read the default configuration file
+ <code class="filename">/etc/named.conf</code>, read any initial
+ data, and listen for queries.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2609211"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-4</span></dt>
+<dd><p>
+ Use IPv4 only even if the host machine is capable of IPv6.
+ <code class="option">-4</code> and <code class="option">-6</code> are mutually
+ exclusive.
+ </p></dd>
+<dt><span class="term">-6</span></dt>
+<dd><p>
+ Use IPv6 only even if the host machine is capable of IPv4.
+ <code class="option">-4</code> and <code class="option">-6</code> are mutually
+ exclusive.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>config-file</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>config-file</code></em> as the
+ configuration file instead of the default,
+ <code class="filename">/etc/named.conf</code>. To
+ ensure that reloading the configuration file continues
+ to work after the server has changed its working
+ directory due to to a possible
+ <code class="option">directory</code> option in the configuration
+ file, <em class="replaceable"><code>config-file</code></em> should be
+ an absolute pathname.
+ </p></dd>
+<dt><span class="term">-d <em class="replaceable"><code>debug-level</code></em></span></dt>
+<dd><p>
+ Set the daemon's debug level to <em class="replaceable"><code>debug-level</code></em>.
+ Debugging traces from <span><strong class="command">named</strong></span> become
+ more verbose as the debug level increases.
+ </p></dd>
+<dt><span class="term">-f</span></dt>
+<dd><p>
+ Run the server in the foreground (i.e. do not daemonize).
+ </p></dd>
+<dt><span class="term">-g</span></dt>
+<dd><p>
+ Run the server in the foreground and force all logging
+ to <code class="filename">stderr</code>.
+ </p></dd>
+<dt><span class="term">-m <em class="replaceable"><code>flag</code></em></span></dt>
+<dd><p>
+ Turn on memory usage debugging flags. Possible flags are
+ <em class="replaceable"><code>usage</code></em>,
+ <em class="replaceable"><code>trace</code></em>,
+ <em class="replaceable"><code>record</code></em>,
+ <em class="replaceable"><code>size</code></em>, and
+ <em class="replaceable"><code>mctx</code></em>.
+ These correspond to the ISC_MEM_DEBUGXXXX flags described in
+ <code class="filename">&lt;isc/mem.h&gt;</code>.
+ </p></dd>
+<dt><span class="term">-n <em class="replaceable"><code>#cpus</code></em></span></dt>
+<dd><p>
+ Create <em class="replaceable"><code>#cpus</code></em> worker threads
+ to take advantage of multiple CPUs. If not specified,
+ <span><strong class="command">named</strong></span> will try to determine the
+ number of CPUs present and create one thread per CPU.
+ If it is unable to determine the number of CPUs, a
+ single worker thread will be created.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd><p>
+ Listen for queries on port <em class="replaceable"><code>port</code></em>. If not
+ specified, the default is port 53.
+ </p></dd>
+<dt><span class="term">-s</span></dt>
+<dd>
+<p>
+ Write memory usage statistics to <code class="filename">stdout</code> on exit.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ This option is mainly of interest to BIND 9 developers
+ and may be removed or changed in a future release.
+ </p>
+</div>
+</dd>
+<dt><span class="term">-S <em class="replaceable"><code>#max-socks</code></em></span></dt>
+<dd>
+<p>
+ Allow <span><strong class="command">named</strong></span> to use up to
+ <em class="replaceable"><code>#max-socks</code></em> sockets.
+ </p>
+<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+<p>
+ This option should be unnecessary for the vast majority
+ of users.
+ The use of this option could even be harmful because the
+ specified value may exceed the limitation of the
+ underlying system API.
+ It is therefore set only when the default configuration
+ causes exhaustion of file descriptors and the
+ operational environment is known to support the
+ specified number of sockets.
+ Note also that the actual maximum number is normally a little
+ fewer than the specified value because
+ <span><strong class="command">named</strong></span> reserves some file descriptors
+ for its internal use.
+ </p>
+</div>
+</dd>
+<dt><span class="term">-t <em class="replaceable"><code>directory</code></em></span></dt>
+<dd>
+<p>Chroot
+ to <em class="replaceable"><code>directory</code></em> after
+ processing the command line arguments, but before
+ reading the configuration file.
+ </p>
+<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+<p>
+ This option should be used in conjunction with the
+ <code class="option">-u</code> option, as chrooting a process
+ running as root doesn't enhance security on most
+ systems; the way <code class="function">chroot(2)</code> is
+ defined allows a process with root privileges to
+ escape a chroot jail.
+ </p>
+</div>
+</dd>
+<dt><span class="term">-u <em class="replaceable"><code>user</code></em></span></dt>
+<dd>
+<p>Setuid
+ to <em class="replaceable"><code>user</code></em> after completing
+ privileged operations, such as creating sockets that
+ listen on privileged ports.
+ </p>
+<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Note</h3>
+<p>
+ On Linux, <span><strong class="command">named</strong></span> uses the kernel's
+ capability mechanism to drop all root privileges
+ except the ability to <code class="function">bind(2)</code> to
+ a
+ privileged port and set process resource limits.
+ Unfortunately, this means that the <code class="option">-u</code>
+ option only works when <span><strong class="command">named</strong></span> is
+ run
+ on kernel 2.2.18 or later, or kernel 2.3.99-pre3 or
+ later, since previous kernels did not allow privileges
+ to be retained after <code class="function">setuid(2)</code>.
+ </p>
+</div>
+</dd>
+<dt><span class="term">-v</span></dt>
+<dd><p>
+ Report the version number and exit.
+ </p></dd>
+<dt><span class="term">-V</span></dt>
+<dd><p>
+ Report the version number and build options, and exit.
+ </p></dd>
+<dt><span class="term">-x <em class="replaceable"><code>cache-file</code></em></span></dt>
+<dd>
+<p>
+ Load data from <em class="replaceable"><code>cache-file</code></em> into the
+ cache of the default view.
+ </p>
+<div class="warning" style="margin-left: 0.5in; margin-right: 0.5in;">
+<h3 class="title">Warning</h3>
+<p>
+ This option must not be used. It is only of interest
+ to BIND 9 developers and may be removed or changed in a
+ future release.
+ </p>
+</div>
+</dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2611108"></a><h2>SIGNALS</h2>
+<p>
+ In routine operation, signals should not be used to control
+ the nameserver; <span><strong class="command">rndc</strong></span> should be used
+ instead.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term">SIGHUP</span></dt>
+<dd><p>
+ Force a reload of the server.
+ </p></dd>
+<dt><span class="term">SIGINT, SIGTERM</span></dt>
+<dd><p>
+ Shut down the server.
+ </p></dd>
+</dl></div>
+<p>
+ The result of sending any other signals to the server is undefined.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2611158"></a><h2>CONFIGURATION</h2>
+<p>
+ The <span><strong class="command">named</strong></span> configuration file is too complex
+ to describe in detail here. A complete description is provided
+ in the
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2611177"></a><h2>FILES</h2>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="filename">/etc/named.conf</code></span></dt>
+<dd><p>
+ The default configuration file.
+ </p></dd>
+<dt><span class="term"><code class="filename">/var/run/named/named.pid</code></span></dt>
+<dd><p>
+ The default process-id file.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2611221"></a><h2>SEE ALSO</h2>
+<p><em class="citetitle">RFC 1033</em>,
+ <em class="citetitle">RFC 1034</em>,
+ <em class="citetitle">RFC 1035</em>,
+ <span class="citerefentry"><span class="refentrytitle">named-checkconf</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named-checkzone</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">lwresd</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named.conf</span>(5)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2611291"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.named-checkzone.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.nsupdate.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">
+<span class="application">named-checkzone</span> </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <span class="application">nsupdate</span>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.nsupdate.html b/doc/arm/man.nsupdate.html
new file mode 100644
index 0000000..40ab5a0
--- /dev/null
+++ b/doc/arm/man.nsupdate.html
@@ -0,0 +1,568 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.nsupdate.html,v 1.22 2008/11/09 01:11:56 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>nsupdate</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.named.html" title="named">
+<link rel="next" href="man.rndc.html" title="rndc">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><span class="application">nsupdate</span></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.named.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.rndc.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.nsupdate"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">nsupdate</span> &#8212; Dynamic DNS update utility</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">nsupdate</code> [<code class="option">-d</code>] [<code class="option">-D</code>] [[<code class="option">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]keyname:secret</code></em></code>] | [<code class="option">-k <em class="replaceable"><code>keyfile</code></em></code>]] [<code class="option">-t <em class="replaceable"><code>timeout</code></em></code>] [<code class="option">-u <em class="replaceable"><code>udptimeout</code></em></code>] [<code class="option">-r <em class="replaceable"><code>udpretries</code></em></code>] [<code class="option">-R <em class="replaceable"><code>randomdev</code></em></code>] [<code class="option">-v</code>] [filename]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2609806"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">nsupdate</strong></span>
+ 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.
+ </p>
+<p>
+ Zones that are under dynamic control via
+ <span><strong class="command">nsupdate</strong></span>
+ or a DHCP server should not be edited by hand.
+ Manual edits could
+ conflict with dynamic updates and cause data to be lost.
+ </p>
+<p>
+ The resource records that are dynamically added or removed with
+ <span><strong class="command">nsupdate</strong></span>
+ have to be in the same zone.
+ Requests are sent to the zone's master server.
+ This is identified by the MNAME field of the zone's SOA record.
+ </p>
+<p>
+ The
+ <code class="option">-d</code>
+ option makes
+ <span><strong class="command">nsupdate</strong></span>
+ operate in debug mode.
+ This provides tracing information about the update requests that are
+ made and the replies received from the name server.
+ </p>
+<p>
+ The <code class="option">-D</code> option makes <span><strong class="command">nsupdate</strong></span>
+ report additional debugging information to <code class="option">-d</code>.
+ </p>
+<p>
+ 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.
+ TSIG relies on a shared secret that should only be known to
+ <span><strong class="command">nsupdate</strong></span> 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
+ <span class="type">key</span>
+ and
+ <span class="type">server</span>
+ statements would be added to
+ <code class="filename">/etc/named.conf</code>
+ 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.
+ <span><strong class="command">nsupdate</strong></span>
+ does not read
+ <code class="filename">/etc/named.conf</code>.
+ </p>
+<p><span><strong class="command">nsupdate</strong></span>
+ uses the <code class="option">-y</code> or <code class="option">-k</code> 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
+ <code class="option">-k</code> option, <span><strong class="command">nsupdate</strong></span> reads
+ the shared secret from the file <em class="parameter"><code>keyfile</code></em>,
+ whose name is of the form
+ <code class="filename">K{name}.+157.+{random}.private</code>. For
+ historical reasons, the file
+ <code class="filename">K{name}.+157.+{random}.key</code> must also be
+ present. When the <code class="option">-y</code> option is used, a
+ signature is generated from
+ [<span class="optional"><em class="parameter"><code>hmac:</code></em></span>]<em class="parameter"><code>keyname:secret.</code></em>
+ <em class="parameter"><code>keyname</code></em> is the name of the key, and
+ <em class="parameter"><code>secret</code></em> is the base64 encoded shared
+ secret. Use of the <code class="option">-y</code> 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
+ <span class="citerefentry"><span class="refentrytitle">ps</span>(1)</span> or in a history file maintained by the user's
+ shell.
+ </p>
+<p>
+ The <code class="option">-k</code> 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.
+ </p>
+<p>
+ By default
+ <span><strong class="command">nsupdate</strong></span>
+ 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
+ <code class="option">-v</code>
+ option makes
+ <span><strong class="command">nsupdate</strong></span>
+ use a TCP connection.
+ This may be preferable when a batch of update requests is made.
+ </p>
+<p>
+ The <code class="option">-t</code> 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.
+ </p>
+<p>
+ The <code class="option">-u</code> option sets the UDP retry interval. The default
+ is
+ 3 seconds. If zero, the interval will be computed from the timeout
+ interval
+ and number of UDP retries.
+ </p>
+<p>
+ The <code class="option">-r</code> option sets the number of UDP retries. The
+ default is
+ 3. If zero, only one update request will be made.
+ </p>
+<p>
+ The <code class="option">-R <em class="replaceable"><code>randomdev</code></em></code> option
+ specifies a source of randomness. If the operating system
+ does not provide a <code class="filename">/dev/random</code> or
+ equivalent device, the default source of randomness is keyboard
+ input. <code class="filename">randomdev</code> specifies the name of
+ a character device or file containing random data to be used
+ instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard input
+ should be used. This option may be specified multiple times.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2610186"></a><h2>INPUT FORMAT</h2>
+<p><span><strong class="command">nsupdate</strong></span>
+ reads input from
+ <em class="parameter"><code>filename</code></em>
+ or standard input.
+ Each command is supplied on exactly one line of input.
+ Some commands are for administrative purposes.
+ The others are either update instructions or prerequisite checks on the
+ contents of the zone.
+ These checks set conditions that some name or set of
+ resource records (RRset) either exists or is absent from the zone.
+ These conditions must be met if the entire update request is to succeed.
+ Updates will be rejected if the tests for the prerequisite conditions
+ fail.
+ </p>
+<p>
+ Every update request consists of zero or more prerequisites
+ and zero or more updates.
+ This allows a suitably authenticated update request to proceed if some
+ specified resource records are present or missing from the zone.
+ A blank input line (or the <span><strong class="command">send</strong></span> command)
+ causes the
+ accumulated commands to be sent as one Dynamic DNS update request to the
+ name server.
+ </p>
+<p>
+ The command formats and their meaning are as follows:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term">
+ <span><strong class="command">server</strong></span>
+ {servername}
+ [port]
+ </span></dt>
+<dd><p>
+ Sends all dynamic update requests to the name server
+ <em class="parameter"><code>servername</code></em>.
+ When no server statement is provided,
+ <span><strong class="command">nsupdate</strong></span>
+ will send updates to the master server of the correct zone.
+ The MNAME field of that zone's SOA record will identify the
+ master
+ server for that zone.
+ <em class="parameter"><code>port</code></em>
+ is the port number on
+ <em class="parameter"><code>servername</code></em>
+ where the dynamic update requests get sent.
+ If no port number is specified, the default DNS port number of
+ 53 is
+ used.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">local</strong></span>
+ {address}
+ [port]
+ </span></dt>
+<dd><p>
+ Sends all dynamic update requests using the local
+ <em class="parameter"><code>address</code></em>.
+
+ When no local statement is provided,
+ <span><strong class="command">nsupdate</strong></span>
+ will send updates using an address and port chosen by the
+ system.
+ <em class="parameter"><code>port</code></em>
+ can additionally be used to make requests come from a specific
+ port.
+ If no port number is specified, the system will assign one.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">zone</strong></span>
+ {zonename}
+ </span></dt>
+<dd><p>
+ Specifies that all updates are to be made to the zone
+ <em class="parameter"><code>zonename</code></em>.
+ If no
+ <em class="parameter"><code>zone</code></em>
+ statement is provided,
+ <span><strong class="command">nsupdate</strong></span>
+ will attempt determine the correct zone to update based on the
+ rest of the input.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">class</strong></span>
+ {classname}
+ </span></dt>
+<dd><p>
+ Specify the default class.
+ If no <em class="parameter"><code>class</code></em> is specified, the
+ default class is
+ <em class="parameter"><code>IN</code></em>.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">ttl</strong></span>
+ {seconds}
+ </span></dt>
+<dd><p>
+ Specify the default time to live for records to be added.
+ The value <em class="parameter"><code>none</code></em> will clear the default
+ ttl.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">key</strong></span>
+ {name}
+ {secret}
+ </span></dt>
+<dd><p>
+ Specifies that all updates are to be TSIG-signed using the
+ <em class="parameter"><code>keyname</code></em> <em class="parameter"><code>keysecret</code></em> pair.
+ The <span><strong class="command">key</strong></span> command
+ overrides any key specified on the command line via
+ <code class="option">-y</code> or <code class="option">-k</code>.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">prereq nxdomain</strong></span>
+ {domain-name}
+ </span></dt>
+<dd><p>
+ Requires that no resource record of any type exists with name
+ <em class="parameter"><code>domain-name</code></em>.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">prereq yxdomain</strong></span>
+ {domain-name}
+ </span></dt>
+<dd><p>
+ Requires that
+ <em class="parameter"><code>domain-name</code></em>
+ exists (has as at least one resource record, of any type).
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">prereq nxrrset</strong></span>
+ {domain-name}
+ [class]
+ {type}
+ </span></dt>
+<dd><p>
+ Requires that no resource record exists of the specified
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>
+ and
+ <em class="parameter"><code>domain-name</code></em>.
+ If
+ <em class="parameter"><code>class</code></em>
+ is omitted, IN (internet) is assumed.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">prereq yxrrset</strong></span>
+ {domain-name}
+ [class]
+ {type}
+ </span></dt>
+<dd><p>
+ This requires that a resource record of the specified
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>
+ and
+ <em class="parameter"><code>domain-name</code></em>
+ must exist.
+ If
+ <em class="parameter"><code>class</code></em>
+ is omitted, IN (internet) is assumed.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">prereq yxrrset</strong></span>
+ {domain-name}
+ [class]
+ {type}
+ {data...}
+ </span></dt>
+<dd><p>
+ The
+ <em class="parameter"><code>data</code></em>
+ from each set of prerequisites of this form
+ sharing a common
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>,
+ and
+ <em class="parameter"><code>domain-name</code></em>
+ are combined to form a set of RRs. This set of RRs must
+ exactly match the set of RRs existing in the zone at the
+ given
+ <em class="parameter"><code>type</code></em>,
+ <em class="parameter"><code>class</code></em>,
+ and
+ <em class="parameter"><code>domain-name</code></em>.
+ The
+ <em class="parameter"><code>data</code></em>
+ are written in the standard text representation of the resource
+ record's
+ RDATA.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">update delete</strong></span>
+ {domain-name}
+ [ttl]
+ [class]
+ [type [data...]]
+ </span></dt>
+<dd><p>
+ Deletes any resource records named
+ <em class="parameter"><code>domain-name</code></em>.
+ If
+ <em class="parameter"><code>type</code></em>
+ and
+ <em class="parameter"><code>data</code></em>
+ is provided, only matching resource records will be removed.
+ The internet class is assumed if
+ <em class="parameter"><code>class</code></em>
+ is not supplied. The
+ <em class="parameter"><code>ttl</code></em>
+ is ignored, and is only allowed for compatibility.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">update add</strong></span>
+ {domain-name}
+ {ttl}
+ [class]
+ {type}
+ {data...}
+ </span></dt>
+<dd><p>
+ Adds a new resource record with the specified
+ <em class="parameter"><code>ttl</code></em>,
+ <em class="parameter"><code>class</code></em>
+ and
+ <em class="parameter"><code>data</code></em>.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">show</strong></span>
+ </span></dt>
+<dd><p>
+ Displays the current message, containing all of the
+ prerequisites and
+ updates specified since the last send.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">send</strong></span>
+ </span></dt>
+<dd><p>
+ Sends the current message. This is equivalent to entering a
+ blank line.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">answer</strong></span>
+ </span></dt>
+<dd><p>
+ Displays the answer.
+ </p></dd>
+<dt><span class="term">
+ <span><strong class="command">debug</strong></span>
+ </span></dt>
+<dd><p>
+ Turn on debugging.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+<p>
+ Lines beginning with a semicolon are comments and are ignored.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2659005"></a><h2>EXAMPLES</h2>
+<p>
+ The examples below show how
+ <span><strong class="command">nsupdate</strong></span>
+ could be used to insert and delete resource records from the
+ <span class="type">example.com</span>
+ zone.
+ Notice that the input in each example contains a trailing blank line so
+ that
+ a group of commands are sent as one dynamic update request to the
+ master name server for
+ <span class="type">example.com</span>.
+
+ </p>
+<pre class="programlisting">
+# nsupdate
+&gt; update delete oldhost.example.com A
+&gt; update add newhost.example.com 86400 A 172.16.1.1
+&gt; send
+</pre>
+<p>
+ </p>
+<p>
+ Any A records for
+ <span class="type">oldhost.example.com</span>
+ are deleted.
+ And an A record for
+ <span class="type">newhost.example.com</span>
+ with IP address 172.16.1.1 is added.
+ The newly-added record has a 1 day TTL (86400 seconds).
+ </p>
+<pre class="programlisting">
+# nsupdate
+&gt; prereq nxdomain nickname.example.com
+&gt; update add nickname.example.com 86400 CNAME somehost.example.com
+&gt; send
+</pre>
+<p>
+ </p>
+<p>
+ The prerequisite condition gets the name server to check that there
+ are no resource records of any type for
+ <span class="type">nickname.example.com</span>.
+
+ 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.)
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2659056"></a><h2>FILES</h2>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">/etc/resolv.conf</code></span></dt>
+<dd><p>
+ used to identify default name server
+ </p></dd>
+<dt><span class="term"><code class="constant">K{name}.+157.+{random}.key</code></span></dt>
+<dd><p>
+ base-64 encoding of HMAC-MD5 key created by
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>.
+ </p></dd>
+<dt><span class="term"><code class="constant">K{name}.+157.+{random}.private</code></span></dt>
+<dd><p>
+ base-64 encoding of HMAC-MD5 key created by
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2659125"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">RFC2136</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC3007</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC2104</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC2845</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC1034</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC2535</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">RFC2931</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2659264"></a><h2>BUGS</h2>
+<p>
+ The TSIG key is redundantly stored in two separate files.
+ This is a consequence of nsupdate using the DST library
+ for its cryptographic operations, and may change in future
+ releases.
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.named.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.rndc.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">
+<span class="application">named</span> </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <span class="application">rndc</span>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.rndc-confgen.html b/doc/arm/man.rndc-confgen.html
new file mode 100644
index 0000000..5768d6b
--- /dev/null
+++ b/doc/arm/man.rndc-confgen.html
@@ -0,0 +1,222 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.rndc-confgen.html,v 1.102 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>rndc-confgen</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.rndc.conf.html" title="rndc.conf">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><span class="application">rndc-confgen</span></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.rndc.conf.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> </td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.rndc-confgen"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">rndc-confgen</span> &#8212; rndc key generation tool</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">rndc-confgen</code> [<code class="option">-a</code>] [<code class="option">-b <em class="replaceable"><code>keysize</code></em></code>] [<code class="option">-c <em class="replaceable"><code>keyfile</code></em></code>] [<code class="option">-h</code>] [<code class="option">-k <em class="replaceable"><code>keyname</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-r <em class="replaceable"><code>randomfile</code></em></code>] [<code class="option">-s <em class="replaceable"><code>address</code></em></code>] [<code class="option">-t <em class="replaceable"><code>chrootdir</code></em></code>] [<code class="option">-u <em class="replaceable"><code>user</code></em></code>]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2623125"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">rndc-confgen</strong></span>
+ generates configuration files
+ for <span><strong class="command">rndc</strong></span>. It can be used as a
+ convenient alternative to writing the
+ <code class="filename">rndc.conf</code> file
+ and the corresponding <span><strong class="command">controls</strong></span>
+ and <span><strong class="command">key</strong></span>
+ statements in <code class="filename">named.conf</code> by hand.
+ Alternatively, it can be run with the <span><strong class="command">-a</strong></span>
+ option to set up a <code class="filename">rndc.key</code> file and
+ avoid the need for a <code class="filename">rndc.conf</code> file
+ and a <span><strong class="command">controls</strong></span> statement altogether.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2623191"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-a</span></dt>
+<dd>
+<p>
+ Do automatic <span><strong class="command">rndc</strong></span> configuration.
+ This creates a file <code class="filename">rndc.key</code>
+ in <code class="filename">/etc</code> (or whatever
+ <code class="varname">sysconfdir</code>
+ was specified as when <acronym class="acronym">BIND</acronym> was
+ built)
+ that is read by both <span><strong class="command">rndc</strong></span>
+ and <span><strong class="command">named</strong></span> on startup. The
+ <code class="filename">rndc.key</code> file defines a default
+ command channel and authentication key allowing
+ <span><strong class="command">rndc</strong></span> to communicate with
+ <span><strong class="command">named</strong></span> on the local host
+ with no further configuration.
+ </p>
+<p>
+ Running <span><strong class="command">rndc-confgen -a</strong></span> allows
+ BIND 9 and <span><strong class="command">rndc</strong></span> to be used as
+ drop-in
+ replacements for BIND 8 and <span><strong class="command">ndc</strong></span>,
+ with no changes to the existing BIND 8
+ <code class="filename">named.conf</code> file.
+ </p>
+<p>
+ If a more elaborate configuration than that
+ generated by <span><strong class="command">rndc-confgen -a</strong></span>
+ is required, for example if rndc is to be used remotely,
+ you should run <span><strong class="command">rndc-confgen</strong></span> without
+ the
+ <span><strong class="command">-a</strong></span> option and set up a
+ <code class="filename">rndc.conf</code> and
+ <code class="filename">named.conf</code>
+ as directed.
+ </p>
+</dd>
+<dt><span class="term">-b <em class="replaceable"><code>keysize</code></em></span></dt>
+<dd><p>
+ Specifies the size of the authentication key in bits.
+ Must be between 1 and 512 bits; the default is 128.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>keyfile</code></em></span></dt>
+<dd><p>
+ Used with the <span><strong class="command">-a</strong></span> option to specify
+ an alternate location for <code class="filename">rndc.key</code>.
+ </p></dd>
+<dt><span class="term">-h</span></dt>
+<dd><p>
+ Prints a short summary of the options and arguments to
+ <span><strong class="command">rndc-confgen</strong></span>.
+ </p></dd>
+<dt><span class="term">-k <em class="replaceable"><code>keyname</code></em></span></dt>
+<dd><p>
+ Specifies the key name of the rndc authentication key.
+ This must be a valid domain name.
+ The default is <code class="constant">rndc-key</code>.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd><p>
+ Specifies the command channel port where <span><strong class="command">named</strong></span>
+ listens for connections from <span><strong class="command">rndc</strong></span>.
+ The default is 953.
+ </p></dd>
+<dt><span class="term">-r <em class="replaceable"><code>randomfile</code></em></span></dt>
+<dd><p>
+ Specifies a source of random data for generating the
+ authorization. If the operating
+ system does not provide a <code class="filename">/dev/random</code>
+ or equivalent device, the default source of randomness
+ is keyboard input. <code class="filename">randomdev</code>
+ specifies
+ the name of a character device or file containing random
+ data to be used instead of the default. The special value
+ <code class="filename">keyboard</code> indicates that keyboard
+ input should be used.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>address</code></em></span></dt>
+<dd><p>
+ Specifies the IP address where <span><strong class="command">named</strong></span>
+ listens for command channel connections from
+ <span><strong class="command">rndc</strong></span>. The default is the loopback
+ address 127.0.0.1.
+ </p></dd>
+<dt><span class="term">-t <em class="replaceable"><code>chrootdir</code></em></span></dt>
+<dd><p>
+ Used with the <span><strong class="command">-a</strong></span> option to specify
+ a directory where <span><strong class="command">named</strong></span> will run
+ chrooted. An additional copy of the <code class="filename">rndc.key</code>
+ will be written relative to this directory so that
+ it will be found by the chrooted <span><strong class="command">named</strong></span>.
+ </p></dd>
+<dt><span class="term">-u <em class="replaceable"><code>user</code></em></span></dt>
+<dd><p>
+ Used with the <span><strong class="command">-a</strong></span> option to set the
+ owner
+ of the <code class="filename">rndc.key</code> file generated.
+ If
+ <span><strong class="command">-t</strong></span> is also specified only the file
+ in
+ the chroot area has its owner changed.
+ </p></dd>
+</dl></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2633066"></a><h2>EXAMPLES</h2>
+<p>
+ To allow <span><strong class="command">rndc</strong></span> to be used with
+ no manual configuration, run
+ </p>
+<p><strong class="userinput"><code>rndc-confgen -a</code></strong>
+ </p>
+<p>
+ To print a sample <code class="filename">rndc.conf</code> file and
+ corresponding <span><strong class="command">controls</strong></span> and <span><strong class="command">key</strong></span>
+ statements to be manually inserted into <code class="filename">named.conf</code>,
+ run
+ </p>
+<p><strong class="userinput"><code>rndc-confgen</code></strong>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2633942"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">rndc.conf</span>(5)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2633980"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.rndc.conf.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> </td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">
+<code class="filename">rndc.conf</code> </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> </td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.rndc.conf.html b/doc/arm/man.rndc.conf.html
new file mode 100644
index 0000000..59f915c
--- /dev/null
+++ b/doc/arm/man.rndc.conf.html
@@ -0,0 +1,255 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.rndc.conf.html,v 1.103 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>rndc.conf</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.rndc.html" title="rndc">
+<link rel="next" href="man.rndc-confgen.html" title="rndc-confgen">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><code class="filename">rndc.conf</code></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.rndc.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.rndc-confgen.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.rndc.conf"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><code class="filename">rndc.conf</code> &#8212; rndc configuration file</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">rndc.conf</code> </p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2612061"></a><h2>DESCRIPTION</h2>
+<p><code class="filename">rndc.conf</code> is the configuration file
+ for <span><strong class="command">rndc</strong></span>, the BIND 9 name server control
+ utility. This file has a similar structure and syntax to
+ <code class="filename">named.conf</code>. Statements are enclosed
+ in braces and terminated with a semi-colon. Clauses in
+ the statements are also semi-colon terminated. The usual
+ comment styles are supported:
+ </p>
+<p>
+ C style: /* */
+ </p>
+<p>
+ C++ style: // to end of line
+ </p>
+<p>
+ Unix style: # to end of line
+ </p>
+<p><code class="filename">rndc.conf</code> is much simpler than
+ <code class="filename">named.conf</code>. The file uses three
+ statements: an options statement, a server statement
+ and a key statement.
+ </p>
+<p>
+ The <code class="option">options</code> statement contains five clauses.
+ The <code class="option">default-server</code> clause is followed by the
+ name or address of a name server. This host will be used when
+ no name server is given as an argument to
+ <span><strong class="command">rndc</strong></span>. The <code class="option">default-key</code>
+ clause is followed by the name of a key which is identified by
+ a <code class="option">key</code> statement. If no
+ <code class="option">keyid</code> is provided on the rndc command line,
+ and no <code class="option">key</code> clause is found in a matching
+ <code class="option">server</code> statement, this default key will be
+ used to authenticate the server's commands and responses. The
+ <code class="option">default-port</code> clause is followed by the port
+ to connect to on the remote name server. If no
+ <code class="option">port</code> option is provided on the rndc command
+ line, and no <code class="option">port</code> clause is found in a
+ matching <code class="option">server</code> statement, this default port
+ will be used to connect.
+ The <code class="option">default-source-address</code> and
+ <code class="option">default-source-address-v6</code> clauses which
+ can be used to set the IPv4 and IPv6 source addresses
+ respectively.
+ </p>
+<p>
+ After the <code class="option">server</code> keyword, the server
+ statement includes a string which is the hostname or address
+ for a name server. The statement has three possible clauses:
+ <code class="option">key</code>, <code class="option">port</code> and
+ <code class="option">addresses</code>. The key name must match the
+ name of a key statement in the file. The port number
+ specifies the port to connect to. If an <code class="option">addresses</code>
+ clause is supplied these addresses will be used instead of
+ the server name. Each address can take an optional port.
+ If an <code class="option">source-address</code> or <code class="option">source-address-v6</code>
+ of supplied then these will be used to specify the IPv4 and IPv6
+ source addresses respectively.
+ </p>
+<p>
+ The <code class="option">key</code> statement begins with an identifying
+ string, the name of the key. The statement has two clauses.
+ <code class="option">algorithm</code> identifies the encryption algorithm
+ for <span><strong class="command">rndc</strong></span> to use; currently only HMAC-MD5
+ is
+ supported. This is followed by a secret clause which contains
+ the base-64 encoding of the algorithm's encryption key. The
+ base-64 string is enclosed in double quotes.
+ </p>
+<p>
+ There are two common ways to generate the base-64 string for the
+ secret. The BIND 9 program <span><strong class="command">rndc-confgen</strong></span>
+ can
+ be used to generate a random key, or the
+ <span><strong class="command">mmencode</strong></span> program, also known as
+ <span><strong class="command">mimencode</strong></span>, can be used to generate a
+ base-64
+ string from known input. <span><strong class="command">mmencode</strong></span> does
+ not
+ ship with BIND 9 but is available on many systems. See the
+ EXAMPLE section for sample command lines for each.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2614213"></a><h2>EXAMPLE</h2>
+<pre class="programlisting">
+ options {
+ default-server localhost;
+ default-key samplekey;
+ };
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+ server localhost {
+ key samplekey;
+ };
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+ server testserver {
+ key testkey;
+ addresses { localhost port 5353; };
+ };
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+ key samplekey {
+ algorithm hmac-md5;
+ secret "6FMfj43Osz4lyb24OIe2iGEz9lf1llJO+lz";
+ };
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+ key testkey {
+ algorithm hmac-md5;
+ secret "R3HI8P6BKw9ZwXwN3VZKuQ==";
+ };
+ </pre>
+<p>
+ </p>
+<p>
+ In the above example, <span><strong class="command">rndc</strong></span> will by
+ default use
+ the server at localhost (127.0.0.1) and the key called samplekey.
+ Commands to the localhost server will use the samplekey key, which
+ must also be defined in the server's configuration file with the
+ same name and secret. The key statement indicates that samplekey
+ uses the HMAC-MD5 algorithm and its secret clause contains the
+ base-64 encoding of the HMAC-MD5 secret enclosed in double quotes.
+ </p>
+<p>
+ If <span><strong class="command">rndc -s testserver</strong></span> is used then <span><strong class="command">rndc</strong></span> will
+ connect to server on localhost port 5353 using the key testkey.
+ </p>
+<p>
+ To generate a random secret with <span><strong class="command">rndc-confgen</strong></span>:
+ </p>
+<p><strong class="userinput"><code>rndc-confgen</code></strong>
+ </p>
+<p>
+ A complete <code class="filename">rndc.conf</code> file, including
+ the
+ randomly generated key, will be written to the standard
+ output. Commented-out <code class="option">key</code> and
+ <code class="option">controls</code> statements for
+ <code class="filename">named.conf</code> are also printed.
+ </p>
+<p>
+ To generate a base-64 secret with <span><strong class="command">mmencode</strong></span>:
+ </p>
+<p><strong class="userinput"><code>echo "known plaintext for a secret" | mmencode</code></strong>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2614403"></a><h2>NAME SERVER CONFIGURATION</h2>
+<p>
+ The name server must be configured to accept rndc connections and
+ to recognize the key specified in the <code class="filename">rndc.conf</code>
+ file, using the controls statement in <code class="filename">named.conf</code>.
+ See the sections on the <code class="option">controls</code> statement in the
+ BIND 9 Administrator Reference Manual for details.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2630812"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">rndc</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">rndc-confgen</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">mmencode</span>(1)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2630851"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.rndc.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.rndc-confgen.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">
+<span class="application">rndc</span> </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <span class="application">rndc-confgen</span>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/arm/man.rndc.html b/doc/arm/man.rndc.html
new file mode 100644
index 0000000..1c49af4
--- /dev/null
+++ b/doc/arm/man.rndc.html
@@ -0,0 +1,203 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: man.rndc.html,v 1.101 2008/11/07 04:08:43 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>rndc</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="Bv9ARM.html" title="BIND 9 Administrator Reference Manual">
+<link rel="up" href="Bv9ARM.ch10.html" title="Manual pages">
+<link rel="prev" href="man.nsupdate.html" title="nsupdate">
+<link rel="next" href="man.rndc.conf.html" title="rndc.conf">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="navheader">
+<table width="100%" summary="Navigation header">
+<tr><th colspan="3" align="center"><span class="application">rndc</span></th></tr>
+<tr>
+<td width="20%" align="left">
+<a accesskey="p" href="man.nsupdate.html">Prev</a> </td>
+<th width="60%" align="center">Manual pages</th>
+<td width="20%" align="right"> <a accesskey="n" href="man.rndc.conf.html">Next</a>
+</td>
+</tr>
+</table>
+<hr>
+</div>
+<div class="refentry" lang="en">
+<a name="man.rndc"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p><span class="application">rndc</span> &#8212; name server control utility</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="cmdsynopsis"><p><code class="command">rndc</code> [<code class="option">-b <em class="replaceable"><code>source-address</code></em></code>] [<code class="option">-c <em class="replaceable"><code>config-file</code></em></code>] [<code class="option">-k <em class="replaceable"><code>key-file</code></em></code>] [<code class="option">-s <em class="replaceable"><code>server</code></em></code>] [<code class="option">-p <em class="replaceable"><code>port</code></em></code>] [<code class="option">-V</code>] [<code class="option">-y <em class="replaceable"><code>key_id</code></em></code>] {command}</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2610666"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">rndc</strong></span>
+ controls the operation of a name
+ server. It supersedes the <span><strong class="command">ndc</strong></span> utility
+ that was provided in old BIND releases. If
+ <span><strong class="command">rndc</strong></span> is invoked with no command line
+ options or arguments, it prints a short summary of the
+ supported commands and the available options and their
+ arguments.
+ </p>
+<p><span><strong class="command">rndc</strong></span>
+ communicates with the name server
+ over a TCP connection, sending commands authenticated with
+ digital signatures. In the current versions of
+ <span><strong class="command">rndc</strong></span> and <span><strong class="command">named</strong></span>,
+ the only supported authentication algorithm is HMAC-MD5,
+ which uses a shared secret on each end of the connection.
+ This provides TSIG-style authentication for the command
+ request and the name server's response. All commands sent
+ over the channel must be signed by a key_id known to the
+ server.
+ </p>
+<p><span><strong class="command">rndc</strong></span>
+ reads a configuration file to
+ determine how to contact the name server and decide what
+ algorithm and key it should use.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2610716"></a><h2>OPTIONS</h2>
+<div class="variablelist"><dl>
+<dt><span class="term">-b <em class="replaceable"><code>source-address</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>source-address</code></em>
+ as the source address for the connection to the server.
+ Multiple instances are permitted to allow setting of both
+ the IPv4 and IPv6 source addresses.
+ </p></dd>
+<dt><span class="term">-c <em class="replaceable"><code>config-file</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>config-file</code></em>
+ as the configuration file instead of the default,
+ <code class="filename">/etc/rndc.conf</code>.
+ </p></dd>
+<dt><span class="term">-k <em class="replaceable"><code>key-file</code></em></span></dt>
+<dd><p>
+ Use <em class="replaceable"><code>key-file</code></em>
+ as the key file instead of the default,
+ <code class="filename">/etc/rndc.key</code>. The key in
+ <code class="filename">/etc/rndc.key</code> will be used to
+ authenticate
+ commands sent to the server if the <em class="replaceable"><code>config-file</code></em>
+ does not exist.
+ </p></dd>
+<dt><span class="term">-s <em class="replaceable"><code>server</code></em></span></dt>
+<dd><p><em class="replaceable"><code>server</code></em> is
+ the name or address of the server which matches a
+ server statement in the configuration file for
+ <span><strong class="command">rndc</strong></span>. If no server is supplied on the
+ command line, the host named by the default-server clause
+ in the options statement of the <span><strong class="command">rndc</strong></span>
+ configuration file will be used.
+ </p></dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd><p>
+ Send commands to TCP port
+ <em class="replaceable"><code>port</code></em>
+ instead
+ of BIND 9's default control channel port, 953.
+ </p></dd>
+<dt><span class="term">-V</span></dt>
+<dd><p>
+ Enable verbose logging.
+ </p></dd>
+<dt><span class="term">-y <em class="replaceable"><code>key_id</code></em></span></dt>
+<dd><p>
+ Use the key <em class="replaceable"><code>key_id</code></em>
+ from the configuration file.
+ <em class="replaceable"><code>key_id</code></em>
+ must be
+ known by named with the same algorithm and secret string
+ in order for control message validation to succeed.
+ If no <em class="replaceable"><code>key_id</code></em>
+ is specified, <span><strong class="command">rndc</strong></span> will first look
+ for a key clause in the server statement of the server
+ being used, or if no server statement is present for that
+ host, then the default-key clause of the options statement.
+ Note that the configuration file contains shared secrets
+ which are used to send authenticated control commands
+ to name servers. It should therefore not have general read
+ or write access.
+ </p></dd>
+</dl></div>
+<p>
+ For the complete set of commands supported by <span><strong class="command">rndc</strong></span>,
+ see the BIND 9 Administrator Reference Manual or run
+ <span><strong class="command">rndc</strong></span> without arguments to see its help
+ message.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2611692"></a><h2>LIMITATIONS</h2>
+<p><span><strong class="command">rndc</strong></span>
+ does not yet support all the commands of
+ the BIND 8 <span><strong class="command">ndc</strong></span> utility.
+ </p>
+<p>
+ There is currently no way to provide the shared secret for a
+ <code class="option">key_id</code> without using the configuration file.
+ </p>
+<p>
+ Several error messages could be clearer.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2611723"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">rndc.conf</span>(5)</span>,
+ <span class="citerefentry"><span class="refentrytitle">rndc-confgen</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named</span>(8)</span>,
+ <span class="citerefentry"><span class="refentrytitle">named.conf</span>(5)</span>,
+ <span class="citerefentry"><span class="refentrytitle">ndc</span>(8)</span>,
+ <em class="citetitle">BIND 9 Administrator Reference Manual</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2611779"></a><h2>AUTHOR</h2>
+<p><span class="corpauthor">Internet Systems Consortium</span>
+ </p>
+</div>
+</div>
+<div class="navfooter">
+<hr>
+<table width="100%" summary="Navigation footer">
+<tr>
+<td width="40%" align="left">
+<a accesskey="p" href="man.nsupdate.html">Prev</a> </td>
+<td width="20%" align="center"><a accesskey="u" href="Bv9ARM.ch10.html">Up</a></td>
+<td width="40%" align="right"> <a accesskey="n" href="man.rndc.conf.html">Next</a>
+</td>
+</tr>
+<tr>
+<td width="40%" align="left" valign="top">
+<span class="application">nsupdate</span> </td>
+<td width="20%" align="center"><a accesskey="h" href="Bv9ARM.html">Home</a></td>
+<td width="40%" align="right" valign="top"> <code class="filename">rndc.conf</code>
+</td>
+</tr>
+</table>
+</div>
+</body>
+</html>
diff --git a/doc/doxygen/Doxyfile.in b/doc/doxygen/Doxyfile.in
new file mode 100644
index 0000000..620e3b0
--- /dev/null
+++ b/doc/doxygen/Doxyfile.in
@@ -0,0 +1,1269 @@
+# $Id: Doxyfile.in,v 1.2 2006/12/22 01:44:59 marka Exp $
+
+# Doxyfile 1.4.7
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = "BIND9 Internals"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = $(BIND9_VERSION)
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH = @BIND9_TOP_BUILDDIR@/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = YES
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @BIND9_TOP_BUILDDIR@/lib/isc \
+ @BIND9_TOP_BUILDDIR@/lib/dns \
+ @BIND9_TOP_BUILDDIR@/lib/isccfg \
+ @BIND9_TOP_BUILDDIR@/lib/isccc \
+ @BIND9_TOP_BUILDDIR@/lib/bind9 \
+ @BIND9_TOP_BUILDDIR@/bin/check \
+ @BIND9_TOP_BUILDDIR@/bin/dig \
+ @BIND9_TOP_BUILDDIR@/bin/dnssec \
+ @BIND9_TOP_BUILDDIR@/bin/named \
+ @BIND9_TOP_BUILDDIR@/bin/nsupdate \
+ @BIND9_TOP_BUILDDIR@/bin/rndc \
+ @BIND9_TOP_BUILDDIR@/doc/doxygen/mainpage
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.c *.h *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS = */win32/* */lib/dns/gen* */lib/dns/rdata/*.h
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER = ./doxygen-input-filter
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER = isc-header.html
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER = isc-footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = YES
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = YES
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = YES
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = @PERL@
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 1000
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
+
+# Local Variables:
+# compile-command: "doxygen"
+# End:
diff --git a/doc/doxygen/Makefile.in b/doc/doxygen/Makefile.in
new file mode 100644
index 0000000..d7d4620
--- /dev/null
+++ b/doc/doxygen/Makefile.in
@@ -0,0 +1,38 @@
+# Copyright (C) 2006, 2007 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 2007/06/19 23:47:13 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+@BIND9_VERSION@
+
+# Until and unless we decide to ship all umptyzillion Doxygen output
+# files, distclean for this directory implies docclean.
+
+doc docclean distclean::
+ rm -rf html xml
+
+doc::
+ BIND9_VERSION='${VERSION}' @DOXYGEN@
+
+distclean::
+ rm -f Doxyfile doxygen-input-filter
diff --git a/doc/doxygen/doxygen-input-filter.in b/doc/doxygen/doxygen-input-filter.in
new file mode 100644
index 0000000..015559a
--- /dev/null
+++ b/doc/doxygen/doxygen-input-filter.in
@@ -0,0 +1,60 @@
+#!@PERL@ -w
+#
+# Copyright (C) 2006, 2007 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: doxygen-input-filter.in,v 1.4 2007/06/19 23:47:13 tbox Exp $
+
+# Input filter for feeding our source code into Doxygen.
+
+# Slurp whole file at once
+undef $/;
+$_ = <>;
+
+# It turns out that there are a lot of cases where we'd really like to
+# use what Doxygen calls "brief" documentation in a comment. Doxygen
+# has a shorthand way of doing this -- if one is writing C++. ISC
+# coding conventions require C, not C++, so we have to do it the
+# verbose way, which makes a lot of comments too long to fit on a
+# single line without violating another ISC coding standard (80
+# character line limit).
+#
+# So we use Doxygen's input filter mechanism to define our own
+# brief comment convention:
+#
+# /*% foo */
+#
+# expands to
+#
+# /*! \brief foo */
+#
+# and
+#
+# /*%< foo */
+#
+# expands to
+#
+# /*!< \brief foo */
+#
+s{/\*%(<?)}{/*!$1 \\brief }g;
+
+# Doxygen appears to strip trailing newlines when reading files
+# directly but not when reading from an input filter. Go figure.
+# Future versions of Doxygen might change this, be warned.
+#
+s{\n+\z}{};
+
+# Done, send the result to Doxygen.
+#
+print;
diff --git a/doc/doxygen/isc-footer.html b/doc/doxygen/isc-footer.html
new file mode 100644
index 0000000..1218ae1
--- /dev/null
+++ b/doc/doxygen/isc-footer.html
@@ -0,0 +1,28 @@
+<!--
+ - Copyright (C) 2006, 2007 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-footer.html,v 1.5 2007/06/19 23:47:13 tbox Exp $ -->
+
+<!-- $Id -->
+
+ <hr size="1">
+ <address style="align: right;">
+ <small>
+ Generated on $datetime by Doxygen $doxygenversion for $projectname $projectnumber
+ </small>
+ </address>
+ </body>
+</html>
diff --git a/doc/doxygen/isc-header.html b/doc/doxygen/isc-header.html
new file mode 100644
index 0000000..0773bcf
--- /dev/null
+++ b/doc/doxygen/isc-header.html
@@ -0,0 +1,26 @@
+<!--
+ - Copyright (C) 2006, 2007 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-header.html,v 1.5 2007/06/19 23:47:13 tbox Exp $ -->
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+ <title>$title</title>
+ <link href="$relpath$doxygen.css" rel="stylesheet" type="text/css">
+ <link href="$relpath$tabs.css" rel="stylesheet" type="text/css">
+ </head>
+ <body>
diff --git a/doc/doxygen/mainpage b/doc/doxygen/mainpage
new file mode 100644
index 0000000..990c4a7
--- /dev/null
+++ b/doc/doxygen/mainpage
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+// $Id: mainpage,v 1.2 2006/12/22 01:44:59 marka Exp $
+//
+// Doxygen text. Lines beginning with two slashes are comments; lines
+// beginning with three slashes are Doxygen input.
+
+/// \mainpage
+/// \section mainpage_overview Overview
+/// \par
+///
+/// This is the beginning of an internals manual for BIND9. It's
+/// still very rough in many places.
+///
+/// \li See the files in doc/doxygen for the source to this page and
+/// the Doxygen configuration that generates the rest of the manual.
+///
+/// \li See the tabs at the top of the screen to navigate through the
+/// generated documentation.
+///
+/// \li See <a href="http://www.doxygen.org/">the Doxygen web site</a>
+/// for more information about Doxygen, including its manual.
+///
+/// \section mainpage_knownissues Known Issues
+/// \par
+///
+/// Known issues with our current use of Doxygen:
+///
+/// \li In a major departure from previous attempts to use Doxygen
+/// with BIND9, this manual attempts to take the simplest approach
+/// to every choice Doxygen gives us. We don't generate fancy
+/// extra Doxygen tags files from the RFC database. We don't
+/// attempt to use Doxygen as a wrapper framework for other
+/// documentation (eg, ISC Tech Notes, the ARM, ...). We don't
+/// try to generate the list of files to document on the fly.
+/// Instead, we attempt to use Doxygen's native facilities
+/// wherever possible, on the assumption that we'll add new
+/// features later as we need them but should start as simply as
+/// we can.
+///
+/// \li Our use of \\file is wrong in many places. We probably should
+/// be marking header files with the names by which we include
+/// them (eg, "dns/resolver.h"). Doxygen reports filename
+/// conflicts in a few cases where it can't work out which of
+/// several files to use.
+///
+/// \li At the moment we're instructing Doxygen to document all
+/// functions, whether they have proper comment markup or not.
+/// This is a good way to see what's been marked up, but might not
+/// be the right approach in the long run.
+///
+/// \li See doc/doxygen/doxygen-input-filter.in for local abbreviations.
+///
+/// \li We're probably over-using the \\brief markup tag.
+///
+/// \li We may in fact be confusing Doxygen to the point where it's
+/// not finding markup comments that it should. Needs
+/// investigation.
+///
+/// \li At the moment I have all the cool "dot" stuff turned off,
+/// both because it's a distraction and because it slows down
+/// doxygen runs. Maybe after I get a faster desk machine. :)
+///
+/// \li At the moment we're producing a single "BIND9 Internals"
+/// manual. One of our previous complications was an attempt to
+/// produce separate manuals for each library, then cross-link
+/// them. We might still need separate library manuals, but, if
+/// so, it might be easier to have the BIND9 Internals manual be a
+/// superset of the library manuals (ie, reuse the same source to
+/// produce differently scoped manuals). Would certainly be
+/// simpler than the cross-linking mess, but partly it's a
+/// question of how we want to present the material.
+///
+/// \li Doxygen is slanted towards C++. It can be tuned towards plain
+/// old C, but the C++ bias still shows up in places, eg, the lack
+/// of top-level menu support for functions (in C++, the basic
+/// unit of programming is the class, which Doxygen does support
+/// directly). This is a bit annoying, but not all that
+/// critical.
+///
+/// \li If we ever get really ambitious, we might try processing
+/// Doxygen's XML output, which is basicly a dump of what Doxygen
+/// was able to scrape from the sources. This would be a major
+/// project, just something to think about if there's something we
+/// really don't like about the output Doxygen generates. Punt
+/// for now.
diff --git a/doc/draft/draft-baba-dnsext-acl-reqts-01.txt b/doc/draft/draft-baba-dnsext-acl-reqts-01.txt
new file mode 100644
index 0000000..1030e57
--- /dev/null
+++ b/doc/draft/draft-baba-dnsext-acl-reqts-01.txt
@@ -0,0 +1,336 @@
+
+
+
+
+Internet-Draft T. Baba
+Expires: March 11, 2004 NTT Data
+ September 11, 2003
+
+
+ Requirements for Access Control in Domain Name Systems
+ draft-baba-dnsext-acl-reqts-01.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is subject to all provisions
+ of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+ Distribution of this memo is unlimited.
+
+ This Internet-Draft will expire on March 11, 2004.
+
+Abstract
+
+ This document describes the requirements for access control
+ mechanisms in the Domain Name System (DNS), which authenticate
+ clients and then allow or deny access to resource records in the
+ zone according to the access control list (ACL).
+
+1. Introduction
+
+ The Domain Name System (DNS) is a hierarchical, distributed, highly
+ available database used for bi-directional mapping between domain
+ names and IP addresses, for email routing, and for other information
+ [RFC1034, 1035]. DNS security extensions (DNSSEC) have been defined
+ to authenticate the data in DNS and provide key distribution services
+ using SIG, KEY, and NXT resource records (RRs) [RFC2535].
+
+
+
+Baba Expires March 11, 2004 [Page 1]
+
+Internet-Draft DNS Access Control Requirements September 2003
+
+
+ At the 28th IETF Meeting in Houston in 1993, DNS security design team
+ started a discussion about DNSSEC and agreed to accept the assumption
+ that "DNS data is public". Accordingly, confidentiality for queries
+ or responses is not provided by DNSSEC, nor are any sort of access
+ control lists or other means to differentiate inquirers. However,
+ about ten years has passed, access control in DNS has been more
+ important than before. Currently, new RRs are proposed to add new
+ functionality to DNS such as ENUM [RFC2916]. Such new RRs may
+ contain private information. Thus, DNS access control will be
+ needed.
+
+ Furthermore, with DNS access control mechanism, access from
+ unauthorized clients can be blocked when they perform DNS name
+ resolution. Thus, for example, Denial of Service (DoS) attacks
+ against a server used by a closed user group can be prevented using
+ this mechanism if IP address of the server is not revealed by other
+ sources.
+
+ This document describes the requirements for access control
+ mechanisms in DNS.
+
+2. Terminology
+
+ AC-aware client
+ This is the client that understands the DNS access control
+ extensions. This client may be an end host which has a stub
+ resolver, or a cashing/recursive name server which has a
+ full-service resolver.
+
+ AC-aware server
+ This is the authoritative name server that understands the DNS
+ access control extensions.
+
+ ACE
+ An Access Control Entry. This is the smallest unit of access
+ control policy. It grants or denies a given set of access
+ rights to a set of principals. An ACE is a component of an ACL,
+ which is associated with a resource.
+
+ ACL
+ An Access Control List. This contains all of the access control
+ policies which are directly associated with a particular
+ resource. These policies are expressed as ACEs.
+
+ Client
+ A program or host which issues DNS requests and accepts its
+ responses. A client may be an end host or a cashing/recursive name
+ server.
+
+
+
+Baba Expires March 11, 2004 [Page 2]
+
+Internet-Draft DNS Access Control Requirements September 2003
+
+
+ RRset
+ All resource records (RRs) having the same NAME, CLASS and TYPE
+ are called a Resource Record Set (RRset).
+
+3. Requirements
+
+ This section describes the requirements for access control in DNS.
+
+3.1 Authentication
+
+3.1.1 Client Authentication Mechanism
+
+ The AC-aware server must identify AC-aware clients based on IP
+ address and/or domain name (user ID or host name), and must
+ authenticate them using strong authentication mechanism such as
+ digital signature or message authentication code (MAC).
+
+ SIG(0) RR [RFC2931] contains a domain name associated with sender's
+ public key in its signer's name field, and TSIG RR [RFC2845] also
+ contains a domain name associated with shared secret key in its key
+ name field. Each of these domain names can be a host name or a user
+ name, and can be used as a sender's identifier for access control.
+ Furthermore, SIG(0) uses digital signatures, and TSIG uses MACs for
+ message authentication. These mechanisms can be used to authenticate
+ AC-aware clients.
+
+ Server authentication may be also provided.
+
+3.1.2 End-to-End Authentication
+
+ In current DNS model, caching/recursive name servers are deployed
+ between end hosts and authoritative name servers. Although
+ authoritative servers can authenticate caching/recursive name servers
+ using SIG(0) or TSIG, they cannot authenticate end hosts behind them.
+ For end-to-end authentication, the mechanism for an end host to
+ discover the target authoritative name server and directly access to
+ it bypassing caching/recursive name servers is needed. For example,
+ an end host can get the IP addresses of the authoritative name
+ servers by retrieving NS RRs for the zone via local caching/recursive
+ name server.
+
+ In many enterprise networks, however, there are firewalls that block
+ all DNS packets other than those going to/from the particular
+ caching/recursive servers. To deal with this problem, one can
+ implement packet forwarding function on the caching/recursive servers
+ and enable end-to-end authentication via the caching/recursive
+ servers.
+
+
+
+
+Baba Expires March 11, 2004 [Page 3]
+
+Internet-Draft DNS Access Control Requirements September 2003
+
+
+3.1.3 Authentication Key Retrieval
+
+ Keys which are used to authenticate clients should be able to be
+ automatically retrieved. The KEY RR is used to store a public key
+ for a zone or a host that is associated with a domain name. SIG(0)
+ RR uses a public key in KEY RR for verifying the signature. If
+ DNSSEC is available, the KEY RR would be protected by the SIG RR.
+ KEY RR or newly defined RR can be used to automatic key retrieval.
+
+3.2 Confidentiality
+
+3.2.1 Data Encryption
+
+ To avoid disclosure to eavesdroppers, the response containing the
+ RRsets which are restricted to access from particular users should be
+ encrypted. Currently, no encryption mechanism is specified in DNS.
+ Therefore, new RRs should be defined for DNS message encryption.
+ Instead, IPsec [RFC2401] can be used to provide confidentiality if
+ name server and resolver can set up security associations dynamically
+ using IPsec API [IPSECAPI] when encryption is required.
+
+ In case encryption is applied, entire DNS message including DNS
+ header should be encrypted to hide information including error code.
+
+ Query encryption may be also provided for hiding query information.
+
+3.2.2 Key Exchange
+
+ If DNS message encryption is provided, automatic key exchange
+ mechanism should be also provided. [RFC2930] specifies a TKEY RR
+ that can be used to establish and delete shared secret keys used by
+ TSIG between a client and a server. With minor extensions, TKEY can
+ be used to establish shared secret keys used for message encryption.
+
+3.2.3 Caching
+
+ The RRset that is restricted to access from particular users must not
+ be cached. To avoid caching, the TTL of the RR that is restricted to
+ access should be set to zero during transit.
+
+3.3 Access Control
+
+3.3.1 Granularity of Access Control
+
+ Control of access on a per-user/per-host granularity must be
+ supported. Control of access to individual RRset (not just the
+ entire zone) must be also supported. However, SOA, NS, SIG, NXT,
+ KEY, and DS RRs must be publicly accessible to avoid unexpected
+ results.
+
+
+Baba Expires March 11, 2004 [Page 4]
+
+Internet-Draft DNS Access Control Requirements September 2003
+
+
+3.3.2 ACL Representation
+
+ Access Control List (ACL) format must be standardized so that both
+ the primary and secondary AC-aware servers can recognize the same
+ ACL. Although ACL may appear in or out of zone data, it must be
+ transferred to the secondary AC-aware server with associated zone
+ data. It is a good idea to contain ACL in zone data, because ACL can
+ be transferred with zone data using existing zone transfer mechanisms
+ automatically. However, ACL must not be published except for
+ authorized secondary master servers.
+
+ In zone data master files, ACL should be specified using TXT RRs or
+ newly defined RRs. In each access control entry (ACE), authorized
+ entities (host or user) must be described using domain name (host
+ name, user name, or IP address in in-addr.arpa/ip6.arpa format).
+ There may be other access control attributes such as access time.
+
+ It must be possible to create publicly readable entries, which may be
+ read even by unauthenticated clients.
+
+3.3.3 Zone/ACL Transfer
+
+ As mentioned above, ACL should be transferred from a primary AC-aware
+ server to a secondary AC-aware server with associated zone data.
+ When an AC-aware server receives a zone/ACL transfer request, the
+ server must authenticate the client, and should encrypt the zone
+ data and associated ACL during transfer.
+
+3.4 Backward/co-existence Compatibility
+
+ Any new protocols to be defined for access control in DNS must be
+ backward compatible with existing DNS protocol. AC-aware servers
+ must be able to process normal DNS query without authentication, and
+ must respond if retrieving RRset is publicly accessible.
+
+ Modifications to root/gTLD/ccTLD name servers are not allowed.
+
+4. Security Considerations
+
+ This document discusses the requirements for access control
+ mechanisms in DNS.
+
+5. Acknowledgements
+
+ This work is funded by the Telecommunications Advancement
+ Organization of Japan (TAO).
+
+ The author would like to thank the members of the NTT DATA network
+ security team for their important contribution to this work.
+
+
+Baba Expires March 11, 2004 [Page 5]
+
+Internet-Draft DNS Access Control Requirements September 2003
+
+
+6. References
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2401] Kent, S. and R. Atkinson, "Security Architecture for the
+ Internet Protocol", RFC 2401, November 1998.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC2845] Vixie, P., Gudmundsson, O., Eastlake, D. and B. Wellington,
+ "Secret Key Transaction Authentication for DNS (TSIG)",
+ RFC 2845, May 2000.
+
+ [RFC2916] Faltstrom, P., "E.164 number and DNS", RFC 2916,
+ September 2000.
+
+ [RFC2930] Eastlake, D., "Secret Key Establishment for DNS (TKEY RR)",
+ RFC 2930, September 2000.
+
+ [RFC2931] Eastlake, D., "DNS Request and Transaction Signatures
+ (SIG(0)s)", RFC 2931, September 2000.
+
+ [IPSECAPI] Sommerfeld, W., "Requirements for an IPsec API",
+ draft-ietf-ipsp-ipsec-apireq-00.txt, June 2003, Work in
+ Progress.
+
+
+Author's Address
+
+ Tatsuya Baba
+ NTT Data Corporation
+ Research and Development Headquarters
+ Kayabacho Tower, 1-21-2, Shinkawa, Chuo-ku,
+ Tokyo 104-0033, Japan
+
+ Tel: +81 3 3523 8081
+ Fax: +81 3 3523 8090
+ Email: babatt@nttdata.co.jp
+
+
+
+
+
+
+
+
+Baba Expires March 11, 2004 [Page 6]
diff --git a/doc/draft/draft-daigle-napstr-04.txt b/doc/draft/draft-daigle-napstr-04.txt
new file mode 100644
index 0000000..fffa8a5
--- /dev/null
+++ b/doc/draft/draft-daigle-napstr-04.txt
@@ -0,0 +1,1232 @@
+
+
+Network Working Group L. Daigle
+Internet-Draft A. Newton
+Expires: August 15, 2004 VeriSign, Inc.
+ February 15, 2004
+
+
+ Domain-based Application Service Location Using SRV RRs and the
+ Dynamic Delegation Discovery Service (DDDS)
+ draft-daigle-napstr-04.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on August 15, 2004.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2004). All Rights Reserved.
+
+Abstract
+
+ This memo defines a generalized mechanism for application service
+ naming that allows service location without relying on rigid domain
+ naming conventions (so-called name hacks). The proposal defines a
+ Dynamic Delegation Discovery System (DDDS) Application to map domain
+ name, application service name, and application protocol to target
+ server and port, dynamically.
+
+
+
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 1]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 2. Straightforward-NAPTR (S-NAPTR) Specification . . . . . . . 4
+ 2.1 Key Terms . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 2.2 S-NAPTR DDDS Application Usage . . . . . . . . . . . . . . . 5
+ 2.2.1 Ordering and Preference . . . . . . . . . . . . . . . . . . 5
+ 2.2.2 Matching and non-Matching NAPTR Records . . . . . . . . . . 5
+ 2.2.3 Terminal and Non-Terminal NAPTR Records . . . . . . . . . . 5
+ 2.2.4 S-NAPTR and Successive Resolution . . . . . . . . . . . . . 6
+ 2.2.5 Clients Supporting Multiple Protocols . . . . . . . . . . . 6
+ 3. Guidelines . . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 3.1 Guidelines for Application Protocol Developers . . . . . . . 7
+ 3.1.1 Registration of application service and protocol tags . . . 7
+ 3.1.2 Definition of conditions for retry/failure . . . . . . . . . 8
+ 3.1.3 Server identification and handshake . . . . . . . . . . . . 8
+ 3.2 Guidelines for Domain Administrators . . . . . . . . . . . . 8
+ 3.3 Guidelines for Client Software Writers . . . . . . . . . . . 9
+ 4. Illustrations . . . . . . . . . . . . . . . . . . . . . . . 9
+ 4.1 Use Cases . . . . . . . . . . . . . . . . . . . . . . . . . 9
+ 4.2 Service Discovery within a Domain . . . . . . . . . . . . . 10
+ 4.3 Multiple Protocols . . . . . . . . . . . . . . . . . . . . . 10
+ 4.4 Remote Hosting . . . . . . . . . . . . . . . . . . . . . . . 11
+ 4.5 Sets of NAPTR RRs . . . . . . . . . . . . . . . . . . . . . 12
+ 4.6 Sample sequence diagram . . . . . . . . . . . . . . . . . . 12
+ 5. Motivation and Discussion . . . . . . . . . . . . . . . . . 14
+ 5.1 So, why not just SRV records? . . . . . . . . . . . . . . . 15
+ 5.2 So, why not just NAPTR records? . . . . . . . . . . . . . . 15
+ 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . 16
+ 7. Security Considerations . . . . . . . . . . . . . . . . . . 16
+ 8. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 17
+ References . . . . . . . . . . . . . . . . . . . . . . . . . 17
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 18
+ A. Application Service Location Application of DDDS . . . . . . 18
+ A.1 Application Unique String . . . . . . . . . . . . . . . . . 18
+ A.2 First Well Known Rule . . . . . . . . . . . . . . . . . . . 18
+ A.3 Expected Output . . . . . . . . . . . . . . . . . . . . . . 18
+ A.4 Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
+ A.5 Service Parameters . . . . . . . . . . . . . . . . . . . . . 19
+ A.5.1 Application Services . . . . . . . . . . . . . . . . . . . . 19
+ A.5.2 Application Protocols . . . . . . . . . . . . . . . . . . . 20
+ A.6 Valid Rules . . . . . . . . . . . . . . . . . . . . . . . . 20
+ A.7 Valid Databases . . . . . . . . . . . . . . . . . . . . . . 20
+ B. Pseudo pseudocode for S-NAPTR . . . . . . . . . . . . . . . 20
+ B.1 Finding the first (best) target . . . . . . . . . . . . . . 20
+ B.2 Finding subsequent targets . . . . . . . . . . . . . . . . . 21
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . 23
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 2]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+1. Introduction
+
+ This memo defines a generalized mechanism for application service
+ naming that allows service location without relying on rigid domain
+ naming conventions (so-called name hacks). The proposal defines a
+ Dynamic Delegation Discovery System (DDDS -- see [6]) Application to
+ map domain name, application service name, and application protocol
+ to target server and port, dynamically.
+
+ As discussed in Section 5, existing approaches to using DNS records
+ to dynamically determining the current host for a given application
+ service are limited in terms of the use cases supported. To address
+ some of the limitations, this document defines a DDDS Application to
+ map service+protocol+domain to specific server addresses using both
+ NAPTR [7] and SRV ([5]) DNS resource records. This can be viewed as
+ a more general version of the use of SRV and/or a very restricted
+ application of the use of NAPTR resource records.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC2119 ([2]).
+
+2. Straightforward-NAPTR (S-NAPTR) Specification
+
+ The precise details of the specification of this DDDS application are
+ given in Appendix A. This section defines the usage of the DDDS
+ application.
+
+2.1 Key Terms
+
+ An "application service" is a generic term for some type of
+ application, indpendent of the protocol that may be used to offer it.
+ Each application service will be associated with an IANA-registered
+ tag. For example, instant messaging is a type of application
+ service, which can be implemented by many different application-layer
+ protocols, and the tag "IM" (used as an illustration here) could be
+ registered for it.
+
+ An "application protocol" is used to implement the application
+ service. These are also associated with IANA-registered tags. In
+ the case where multiple transports are available for the application,
+ separate tags should be defined for each transport.
+
+ The intention is that the combination of application service and
+ protocol tags should be specific enough that finding a known pair
+ (e.g., "IM:ProtC") is sufficient for a client to identify a server
+ with which it can communicate.
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 3]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ Some protocols support multiple application services. For example,
+ LDAP is an application protocol, and can be found supporting various
+ services (e.g., "whitepages", "directory enabled networking", etc).
+
+2.2 S-NAPTR DDDS Application Usage
+
+ As outlined in Appendix A, NAPTR records are used to store
+ application service+protocol information for a given domain.
+ Following the DDDS standard, these records are looked up, and the
+ rewrite rules (contained in the NAPTR records) are used to determine
+ the successive DNS lookups, until a desirable target is found.
+
+ For the rest of this section, refer to the set of NAPTR resource
+ records for example.com shown in the figure below.
+
+ example.com.
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 10 "" "WP:whois++" "" bunyip.example.
+ IN NAPTR 100 20 "s" "WP:ldap" "" _ldap._tcp.myldap.example.com.
+ IN NAPTR 200 10 "" "IM:protA" "" someisp.example.
+ IN NAPTR 200 30 "a" "IM:protB" "" myprotB.example.com.
+
+
+2.2.1 Ordering and Preference
+
+ A client retrieves all of the NAPTR records associated with the
+ target domain name (example.com, above). These are to be sorted in
+ terms of increasing ORDER, and increasing PREF within each ORDER.
+
+2.2.2 Matching and non-Matching NAPTR Records
+
+ Starting with the first sorted NAPTR record, the client examines the
+ SERVICE field to find a match. In the case of the S-NAPTR DDDS
+ application, that means a SERVICE field that includes the tags for
+ the desired application service and a supported application protocol.
+
+ If more than one NAPTR record matches, they are processed in
+ increasing sort order.
+
+2.2.3 Terminal and Non-Terminal NAPTR Records
+
+ A NAPTR record with an empty FLAG field is "non-terminal". That is,
+ more NAPTR RR lookups are to be performed. Thus, to process a NAPTR
+ record with an empty FLAG field in S-NAPTR, the REPLACEMENT field is
+ used as the target of the next DNS lookup -- for NAPTR RRs.
+
+ In S-NAPTR, the only terminal flags are "S" and "A". These are
+ called "terminal" NAPTR lookups because they denote the end of the
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 4]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ DDDS/NAPTR processing rules. In the case of an "S" flag, the
+ REPLACEMENT field is used as the target of a DNS query for SRV RRs,
+ and normal SRV processing is applied. In the case of an "A" flag, an
+ address record is sought for the REPLACEMENT field target (and the
+ default protocol port is assumed).
+
+2.2.4 S-NAPTR and Successive Resolution
+
+ As shown in the example NAPTR RR set above, it is possible to have
+ multiple possible targets for a single application service+protocol
+ pair. These are to be pursued in order until a server is
+ successfully contacted or all possible matching NAPTR records have
+ been successively pursued to terminal lookups and servers contacted.
+ That is, a client must backtrack and attempt other resolution paths
+ in the case of failure.
+
+ "Failure" is declared, and backtracking must be used when
+
+ o the designated remote server (host and port) fail to provide
+ appropriate security credentials for the *originating* domain
+
+ o connection to the designated remote server otherwise fails -- the
+ specifics terms of which are defined when an application protocol
+ is registered
+
+ o the S-NAPTR-designated DNS lookup fails to yield expected results
+ -- e.g., no A RR for an "A" target, no SRV record for an "S"
+ target, or no NAPTR record with appropriate application service
+ and protocol for a NAPTR lookup. Except in the case of the very
+ first NAPTR lookup, this last is a configuration error: the fact
+ that example.com has a NAPTR record pointing to "bunyip.example"
+ for the "WP:Whois++" service and protocol means the administrator
+ of example.com believes that service exists. If bunyip.example
+ has no "WP:Whois++" NAPTR record, the application client MUST
+ backtrack and try the next available "WP:Whois++" option from
+ example.com. As there is none, the whole resolution fails.
+
+ An application client first queries for the NAPTR RRs for the domain
+ of a named application service. The application client MUST select
+ one protocol to choose The PREF field of the NAPTR RRs may be used by
+ the domain administrator to The first DNS query is for the NAPTR RRs
+ in the original target domain (example.com, above).
+
+2.2.5 Clients Supporting Multiple Protocols
+
+ In the case of an application client that supports more than one
+ protocol for a given application service, it MUST pursue S-NAPTR
+ resolution completely for one protocol before trying another.j It MAY
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 5]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ choose which protocol to try first based on its own preference, or
+ from the PREF ranking in the first set of NAPTR records (i.e., those
+ for the target named domain). However, the chosen protocol MUST be
+ listed in that first NAPTR RR set.
+
+ That is, what the client MUST NOT do is start looking for one
+ protocol, observe that a successive NAPTR RR set supports another of
+ its preferred protocols, and continue the S-NAPTR resolution based on
+ that protocol. For example, even if someisp.example offers the "IM"
+ service with protocol "ProtB", there is no reason to believe it does
+ so on behalf of example.com (since there is no such pointer in
+ example.com's NAPTR RR set).
+
+3. Guidelines
+
+3.1 Guidelines for Application Protocol Developers
+
+ The purpose of S-NAPTR is to provide application standards developers
+ with a more powerful framework (than SRV RRs alone) for naming
+ service targets, without requiring each application protocol (or
+ service) standard to define a separate DDDS application.
+
+ Note that this approach is intended specifically for use when it
+ makes sense to associate services with particular domain names (e.g.,
+ e-mail addresses, SIP addresses, etc). A non-goal is having all
+ manner of label mapped into domain names in order to use this.
+
+ Specifically not addressed in this document is how to select the
+ domain for which the service+protocol is being sought. It is up to
+ other conventions to define how that might be used (e.g., instant
+ messaging standards can define what domain to use from IM URIs, how
+ to step down from foobar.example.com to example.com, and so on, if
+ that is applicable).
+
+ Although this document proposes a DDDS application that does not use
+ all the features of NAPTR resource records, it does not mean to imply
+ that DNS resolvers should fail to implement all aspects of the NAPTR
+ RR standard. A DDDS application is a client use convention.
+
+ The rest of this section outlines the specific elements that protocol
+ developers must determine and document in order to make use of S-
+ NAPTR.
+
+3.1.1 Registration of application service and protocol tags
+
+ Application protocol developers that wish to make use of S-NAPTR must
+ make provision to register any relevant application service and
+ application protocol tags, as described in Section 6.
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 6]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+3.1.2 Definition of conditions for retry/failure
+
+ One other important aspect that must be defined is the expected
+ behaviour for interacting with the servers that are reached via S-
+ NAPTR. Specifically, under what circumstances should the client
+ retry a target that was found via S-NAPTR? What should it consider a
+ failure that causes it to return to the S-NAPTR process to determine
+ the next serviceable target (a less preferred target)?
+
+ For example, if the client gets a "connection refused" from a server,
+ should it retry for some (protocol-dependent) period of time? Or,
+ should it try the next-preferred target in the S-NAPTR chain of
+ resolution? Should it only try the next-preferred target if it
+ receives a protocol-specific permanent error message?
+
+ The most important thing is to select one expected behaviour and
+ document it as part of the use of S-NAPTR.
+
+ As noted earlier, failure to provide appropriate credentials to
+ identify the server as being authoritative for the original taret
+ domain is always considered a failure condition.
+
+3.1.3 Server identification and handshake
+
+ As noted in Section 7, use of the DNS for server location increases
+ the importance of using protocol-specific handshakes to determine and
+ confirm the identity of the server that is eventually reached.
+
+ Therefore, application protocol developers using S-NAPTR should
+ identify the mechanics of the expected identification handshake when
+ the client connects to a server found through S-NAPTR.
+
+3.2 Guidelines for Domain Administrators
+
+ Although S-NAPTR aims to provide a "straightforward" application of
+ DDDS and use of NAPTR records, it is still possible to create very
+ complex chains and dependencies with the NAPTR and SRV records.
+
+ Therefore, domain administrators are called upon to use S-NAPTR with
+ as much restraint as possible, while still achieving their service
+ design goals.
+
+ The complete set of NAPTR, SRV and A RRs that are "reachable" through
+ the S-NAPTR process for a particular application service can be
+ thought of as a "tree". Each NAPTR RR retrieved points to more NAPTR
+ or SRV records; each SRV record points to several A record lookups.
+ Even though a particular client can "prune" the tree to use only
+ those records referring to application protocols supported by the
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 7]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ client, the tree could be quite deep, and retracing the tree to retry
+ other targets can become expensive if the tree has many branches.
+
+ Therefore,
+
+ o Fewer branches is better: for both NAPTR and SRV records, provide
+ different targets with varying preferences where appropriate
+ (e.g., to provide backup services, etc), but don't look for
+ reasons to provide more.
+
+ o Shallower is better: avoid using NAPTR records to "rename"
+ services within a zone. Use NAPTR records to identify services
+ hosted elsewhere (i.e., where you cannot reasonably provide the
+ SRV records in your own zone).
+
+
+3.3 Guidelines for Client Software Writers
+
+ To properly understand DDDS/NAPTR, an implementor must read [6].
+ However, the most important aspect to keep in mind is that, if one
+ target fails to work for the application, it is expected that the
+ application will continue through the S-NAPTR tree to try the (less
+ preferred) alternatives.
+
+4. Illustrations
+
+4.1 Use Cases
+
+ The basic intended use cases for which S-NAPTR has been developed
+ are:
+
+ o Service discovery within a domain. For example, this can be used
+ to find the "authoritative" server for some type of service within
+ a domain (see the specific example in Section 4.2).
+
+ o Multiple protocols. This is increasingly common as new
+ application services are defined. This includes the case of
+ instant messaging (a service) which can be offered with multiple
+ protocols (see Section 4.3).
+
+ o Remote hosting. Each of the above use cases applies within the
+ administration of a single domain. However, one domain operator
+ may elect to engage another organization to provide an application
+ service. See Section 4.4 for an example that cannot be served by
+ SRV records alone.
+
+
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 8]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+4.2 Service Discovery within a Domain
+
+ There are occasions when it is useful to be able to determine the
+ "authoritative" server for a given application service within a
+ domain. This is "discovery", because there is no a priori knowledge
+ as to whether or where the service is offered; it is therefore
+ important to determine the location and characteristics of the
+ offered service.
+
+ For example, there is growing discussion of having a generic
+ mechanism for locating the keys or certificates associated with
+ particular application (servers) operated in (or for) a particular
+ domain. Here's a hypothetical case for storing application key or
+ certificate data for a given domain. The premise is that some
+ credentials registry (CredReg) service has been defined to be a leaf
+ node service holding the keys/certs for the servers operated by (or
+ for) the domain. Furthermore, it is assumed that more than one
+ protocol is available to provide the service for a particular domain.
+ This DDDS-based approach is used to find the CredReg server that
+ holds the information.
+
+ Thus, the set of NAPTR records for thinkingcat.example might look
+ like this:
+
+ thinkingcat.example.
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 10 "" "CREDREG:ldap:iris-beep" "" theserver.thinkingcat.example.
+
+ Note that another domain, offering the same application service,
+ might offer it using a different set of application protocols:
+
+ anotherdomain.example.
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 10 "" "CREDREG:iris-lw:iris-beep" "" foo.anotherdomain.example.
+
+
+4.3 Multiple Protocols
+
+ As it stands, there are several different protocols proposed for
+ offering "instant message" services. Assuming that "IM" was
+ registered as an application service, this DDDS application could be
+ used to determine the available services for delivering to a target.
+
+ Two particular features of instant messaging should be noted:
+
+ 1. gatewaying is expected to bridge communications across protocols
+
+ 2. instant messaging servers are likely to be operated out of a
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 9]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ different domain than the instant messaging address, and servers
+ of different protocols may be offered by independent
+ organizations
+
+ For example, "thinkingcat.example" may support its own servers for
+ the "ProtA" instant messaging protocol, but rely on outsourcing from
+ "example.com" for "ProtC" and "ProtB" servers.
+
+ Using this DDDS-based approach, thinkingcat.example can indicate a
+ preference ranking for the different types of servers for the instant
+ messaging service, and yet the out-sourcer can independently rank the
+ preference and ordering of servers. This independence is not
+ achievable through the use of SRV records alone.
+
+ Thus, to find the IM services for thinkingcat.example, the NAPTR
+ records for thinkingcat.example are retrieved:
+
+ thinkingcat.example.
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 10 "s" "IM:ProtA" "" _ProtA._tcp.thinkingcat.example.
+ IN NAPTR 100 20 "s" "IM:ProtB" "" _ProtB._tcp.example.com.
+ IN NAPTR 100 30 "s" "IM:ProtC" "" _ProtC._tcp.example.com.
+
+ and then the administrators at example.com can manage the preference
+ rankings of the servers they use to support the ProtB service:
+
+ _ProtB._tcp.example.com.
+ ;; Pref Weight Port Target
+ IN SRV 10 0 10001 bigiron.example.com
+ IN SRV 20 0 10001 backup.im.example.com
+ IN SRV 30 0 10001 nuclearfallout.australia-isp.example
+
+
+4.4 Remote Hosting
+
+ In the Instant Message hosting example in Section 4.3, the service
+ owner (thinkingcat.example) had to host pointers to the hosting
+ service's SRV records in the thinkingcat.example domain.
+
+ A better way to approach this is to have one NAPTR RR in the
+ thinkingcat.example domain pointing to all the hosted services, and
+ the hosting domain has NAPTR records for each service to map them to
+ whatever local hosts it chooses (and may change from time to time).
+
+
+
+
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 10]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ thinkingcat.example.
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 10 "s" "IM:ProtA" "" _ProtA._tcp.thinkingcat.example.
+ IN NAPTR 100 20 "" "IM:ProtB:ProtC" "" thinkingcat.example.com.
+
+
+ and then the administrators at example.com can break out the
+ individual application protocols and manage the preference rankings
+ of the servers they use to support the ProtB service (as before):
+
+ thinkingcat.example.com.
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 10 "s" "IM:ProtC" "" _ProtC._tcp.example.com.
+ IN NAPTR 100 20 "s" "IM:ProtB" "" _ProtB._tcp.example.com.
+
+
+
+ _ProtC._tcp.example.com.
+ ;; Pref Weight Port Target
+ IN SRV 10 0 10001 bigiron.example.com
+ IN SRV 20 0 10001 backup.im.example.com
+ IN SRV 30 0 10001 nuclearfallout.australia-isp.example
+
+
+4.5 Sets of NAPTR RRs
+
+ Note that the above sections assumed that there was one service
+ available (via S-NAPTR) per domain. Often, that will not be the
+ case. Assuming thinkingcat.example had the CredReg service set up as
+ described in Section 4.2 and the instant messaging service set up as
+ described in Section 4.4, then a client querying for the NAPTR RR set
+ from thinkingcat.com would get the following answer:
+
+ thinkingcat.example.
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 10 "s" "IM:ProtA" "" _ProtA._tcp.thinkingcat.example.
+ IN NAPTR 100 20 "" "IM:ProtB:ProtC:" "" thinkingcat.example.com.
+ IN NAPTR 200 10 "" "CREDREG:ldap:iris-beep" "" bouncer.thinkingcat.example.
+
+ Sorting them by increasing "ORDER", the client would look through the
+ SERVICE strings to determine if there was a NAPTR RR that matched the
+ application service it was looking for, with an application protocol
+ it could use. The first (lowest PREF) record that so matched is the
+ one the client would use to continue.
+
+4.6 Sample sequence diagram
+
+ Consider the example in Section 4.3. Visually, the sequence of steps
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 11]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ required for the client to reach the final server for a "ProtB"
+ service for IM for the thinkingcat.example domain is as follows:
+
+
+ Client NS for NS for
+ thinkingcat.example example.com backup.im.example.com
+ | | |
+ 1 -------->| | |
+ 2 <--------| | |
+ 3 ------------------------------>| |
+ 4 <------------------------------| |
+ 5 ------------------------------>| |
+ 6 <------------------------------| |
+ 7 ------------------------------>| |
+ 8 <------------------------------| |
+ 9 ------------------------------------------------->|
+ 10 <-------------------------------------------------|
+ 11 ------------------------------------------------->|
+ 12 <-------------------------------------------------|
+ (...)
+
+
+
+ 1. the name server (NS) for thinkingcat.example is reached with a
+ request for all NAPTR records
+
+ 2. the server responds with the NAPTR records shown in Section 4.3.
+
+ 3. the second NAPTR record matches the desired criteria; that has an
+ "s" flag and a replacement fields of "_ProtB._tcp.example.com".
+ So, the client looks up SRV records for that target, ultimately
+ making the request of the NS for example.com.
+
+ 4. the response includes the SRV records listed in Section 4.3.
+
+ 5. the client attempts to reach the server with the lowest PREF in
+ the SRV list -- looking up the A record for the SRV record's
+ target (bigiron.example.com).
+
+ 6. the example.com NS responds with an error message -- no such
+ machine!
+
+ 7. the client attempts to reach the second server in the SRV list,
+ and looks up the A record for backup.im.example.com
+
+ 8. the client gets the A record with the IP address for
+ backup.im.example.com from example.com's NS.
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 12]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ 9. the client connects to that IP address, on port 10001 (from the
+ SRV record), using ProtB over tcp.
+
+ 10. the server responds with an "OK" message.
+
+ 11. the client uses ProtB to challenge that this server has
+ credentials to operate the service for the original domain
+ (thinkingcat.example)
+
+ 12. the server responds, and the rest is IM.
+
+
+5. Motivation and Discussion
+
+ Increasingly, application protocol standards are using domain names
+ to identify server targets, and stipulating that clients should look
+ up SRV resource records to determine the host and port providing the
+ server. This enables a distinction between naming an application
+ service target and actually hosting the server. It also increases
+ flexibility in hosting the target service:
+
+ o the server may be operated by a completely different organization
+ without having to list the details of that organization's DNS
+ setup (SRVs)
+
+ o multiple instances can be set up (e.g., for load balancing or
+ secondaries)
+
+ o it can be moved from time to time without disrupting clients'
+ access, etc.
+
+ This is quite useful, but Section 5.1 outlines some of the
+ limitations inherent in the approach.
+
+ That is, while SRV records can be used to map from a specific service
+ name and protocol for a specific domain to a specific server, SRV
+ records are limited to one layer of indirection, and are focused on
+ server administration rather than on application naming. And, while
+ the DDDS specification and use of NAPTR allows multiple levels of
+ redirection before locating the target server machine with an SRV
+ record, this proposal requires only a subset of NAPTR strictly bound
+ to domain names, without making use of the REGEXP field of NAPTR.
+ These restrictions make the client's resolution process much more
+ predictable and efficient than with some potential uses of NAPTR
+ records. This is dubbed "S-NAPTR" -- a "S"traightforward use of
+ NAPTR records.
+
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 13]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+5.1 So, why not just SRV records?
+
+ An expected question at this point is: this is so similar in
+ structure to SRV records, why are we doing this with DDDS/NAPTR?
+
+ Limitations of SRV include:
+
+ o SRV provides a single layer of indirection -- the outcome of an
+ SRV lookup is a new domain name for which the A RR is to be found.
+
+ o the purpose of SRV is focused on individual server administration,
+ not application naming: as stated in [5] "The SRV RR allows
+ administrators to use several servers for a single domain, to move
+ services from host to host with little fuss, and to designate some
+ hosts as primary servers for a service and others as backups."
+
+ o target servers by "service" (e.g., "ldap") and "protocol" (e.g.,
+ "tcp") in a given domain. The definition of these terms implies
+ specific things (e.g., that protocol should be one of UDP or TCP)
+ without being precise. Restriction to UDP and TCP is insufficient
+ for the uses described here.
+
+ The basic answer is that SRV records provide mappings from protocol
+ names to host and port. The use cases described herein require an
+ additional layer -- from some service label to servers that may in
+ fact be hosted within different administrative domains. We could
+ tweak SRV to say that the next lookup could be something other than
+ an address record, but that is more complex than is necessary for
+ most applications of SRV.
+
+5.2 So, why not just NAPTR records?
+
+ That's a trick question. NAPTR records cannot appear in the wild --
+ see [6]. They must be part of a DDDS application.
+
+ The purpose here is to define a single, common mechanism (the DDDS
+ application) to use NAPTR when all that is desired is simple DNS-
+ based location of services. This should be easy for applications to
+ use -- some simple IANA registrations and it's done.
+
+ Also, NAPTR has very powerful tools for expressing "rewrite" rules.
+ That power (==complexity) makes some protocol designers and service
+ administrators nervous. The concern is that it can translate into
+ unintelligible, noodle-like rule sets that are difficult to test and
+ administer.
+
+ This proposed DDDS application specifically uses a subset of NAPTR's
+ abilities. Only "replacement" expressions are allowed, not "regular
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 14]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ expressions".
+
+6. IANA Considerations
+
+ This document calls for 2 IANA registries: one for application
+ service tags, and one for application protocol tags.
+
+ Application service and protocol tags should be defined in an RFC
+ (unless the "x-" experimental form is used, in which case they are
+ unregistered). There are no restrictions placed on the tags other
+ than that they must conform with the syntax defined below (Appendix
+ A.5). The IANA registries should list the tags and the RFC that
+ defines their use.
+
+7. Security Considerations
+
+ The security of this approach to application service location is only
+ as good as the security of the DNS servers along the way. If any of
+ them is compromised, bogus NAPTR and SRV records could be inserted to
+ redirect clients to unintended destinations. This problem is hardly
+ unique to S-NAPTR (or NAPTR in general).
+
+ To protect against DNS-vectored attacks, applications should define
+ some form of end-to-end authentication to ensure that the correct
+ destination has been reached. Many application protocols such as
+ HTTPS, BEEP, IMAP, etc... define the necessary handshake mechansims
+ to accomplish this task.
+
+ The basic mechanism works in the following way:
+
+ 1. During some portion of the protocol handshake, the client sends
+ to the server the original name of the desired destination (i.e.
+ no transformations that may have resulted from NAPTR
+ replacements, SRV targets, or CNAME changes). In certain cases
+ where the application protocol does not have such a feature but
+ TLS may be used, it is possible to use the "server_name" TLS
+ extension.
+
+ 2. The server sends back to the client a credential with the
+ appropriate name. For X.509 certificates, the name would either
+ be in the subjectDN or subjectAltName fields. For Kerberos, the
+ name would be a service principle name.
+
+ 3. Using the matching semantics defined by the application protocol,
+ the client compares the name in the credential with the name sent
+ to the server.
+
+ 4. If the names match, there is reasonable assurance that the
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 15]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ correct end point has been reached.
+
+ It is important to note that this document does not define either the
+ handshake mechanism, the specific credenential naming fields, nor the
+ name matching semantics. Definitions of S-NAPTR for particular
+ application protocols MUST define these.
+
+8. Acknowledgements
+
+ Many thanks to Dave Blacka, Patrik Faltstrom, Sally Floyd for
+ discussion and input that has (hopefully!) provoked clarifying
+ revisions of this document.
+
+References
+
+ [1] Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource
+ Identifiers (URI): Generic Syntax", RFC 2396, August 1998.
+
+ [2] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [3] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [4] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [5] Gulbrandsen, A., Vixie, P. and L. Esibov, "A DNS RR for
+ specifying the location of services (DNS SRV)", RFC 2782,
+ February 2000.
+
+ [6] Mealling, M., "Dynamic Delegation Discovery System (DDDS) Part
+ One: The Comprehensive DDDS", RFC 3401, October 2002.
+
+ [7] Mealling, M., "Dynamic Delegation Discovery System (DDDS) Part
+ Three: The Domain Name System (DNS) Database", RFC 3403, October
+ 2002.
+
+ [8] Mealling, M., "Dynamic Delegation Discovery System (DDDS) Part
+ Four: The Uniform Resource Identifiers (URI)", RFC 3404, October
+ 2002.
+
+
+
+
+
+
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 16]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+Authors' Addresses
+
+ Leslie Daigle
+ VeriSign, Inc.
+ 21355 Ridgetop Circle
+ Dulles, VA 20166
+ US
+
+ EMail: leslie@verisignlabs.com; leslie@thinkingcat.com
+
+
+ Andrew Newton
+ VeriSign, Inc.
+ 21355 Ridgetop Circle
+ Dulles, VA 20166
+ US
+
+ EMail: anewton@verisignlabs.com
+
+Appendix A. Application Service Location Application of DDDS
+
+ This section defines the DDDS application, as described in [6].
+
+A.1 Application Unique String
+
+ The Application Unique String is domain label for which an
+ authoritative server for a particular service is sought.
+
+A.2 First Well Known Rule
+
+ The "First Well Known Rule" is identity -- that is, the output of the
+ rule is the Application Unique String, the domain label for which the
+ authoritative server for a particular service is sought.
+
+A.3 Expected Output
+
+ The expected output of this Application is the information necessary
+ to connect to authoritative server(s) (host, port, protocol) for an
+ application service within a given a given domain.
+
+A.4 Flags
+
+ This DDDS Application uses only 2 of the Flags defined for the
+ URI/URN Resolution Application ([8]): "S" and "A". No other Flags
+ are valid.
+
+ Both are for terminal lookups. This means that the Rule is the last
+ one and that the flag determines what the next stage should be. The
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 17]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ "S" flag means that the output of this Rule is a domain label for
+ which one or more SRV [5] records exist. "A" means that the output
+ of the Rule is a domain name and should be used to lookup address
+ records for that domain.
+
+ Consistent with the DDDS algorithm, if the Flag string is empty the
+ next lookup is for another NAPTR record (for the replacement target).
+
+A.5 Service Parameters
+
+ Service Parameters for this Application take the form of a string of
+ characters that follow this ABNF ([3]):
+
+ service-parms = [ [app-service] *(":" app-protocol)]
+ app-service = experimental-service / iana-registered-service
+ app-protocol = experimental-protocol / iana-registered-protocol
+ experimental-service = "x-" 1*30ALPHANUMSYM
+ experimental-protocol = "x-" 1*30ALPHANUMSYM
+ iana-registered-service = ALPHA *31ALPHANUMSYM
+ iana-registered-protocol = ALPHA *31ALPHANUM
+ ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
+ DIGIT = %x30-39 ; 0-9
+ SYM = %x2B / %x2D / %x2E ; "+" / "-" / "."
+ ALPHANUMSYM = ALPHA / DIGIT / SYM
+ ; The app-service and app-protocol tags are limited to 32
+ ; characters and must start with an alphabetic character.
+ ; The service-parms are considered case-insensitive.
+
+ Thus, the Service Parameters may consist of an empty string, just an
+ app-service, or an app-service with one or more app-protocol
+ specifications separated by the ":" symbol.
+
+ Note that this is similar to, but not the same as the syntax used in
+ the URI DDDS application ([8]). The DDDS DNS database requires each
+ DDDS application to define the syntax of allowable service strings.
+ The syntax here is expanded to allow the characters that are valid in
+ any URI scheme name (see [1]). Since "+" (the separator used in the
+ RFC3404 service parameter string) is an allowed character for URI
+ scheme names, ":" is chosen as the separator here.
+
+A.5.1 Application Services
+
+ The "app-service" must be a registered service [this will be an IANA
+ registry; this is not the IANA port registry, because we want to
+ define services for which there is no single protocol, and we don't
+ want to use up port space for nothing].
+
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 18]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+A.5.2 Application Protocols
+
+ The protocol identifiers that are valid for the "app-protocol"
+ production are any standard, registered protocols [IANA registry
+ again -- is this the list of well known/registered ports?].
+
+A.6 Valid Rules
+
+ Only substitution Rules are permitted for this application. That is,
+ no regular expressions are allowed.
+
+A.7 Valid Databases
+
+ At present only one DDDS Database is specified for this Application.
+ [7] specifies a DDDS Database that uses the NAPTR DNS resource record
+ to contain the rewrite rules. The Keys for this database are encoded
+ as domain-names.
+
+ The First Well Known Rule produces a domain name, and this is the Key
+ that is used for the first lookup -- the NAPTR records for that
+ domain are requested.
+
+ DNS servers MAY interpret Flag values and use that information to
+ include appropriate NAPTR, SRV or A records in the Additional
+ Information portion of the DNS packet. Clients are encouraged to
+ check for additional information but are not required to do so. See
+ the Additional Information Processing section of [7] for more
+ information on NAPTR records and the Additional Information section
+ of a DNS response packet.
+
+Appendix B. Pseudo pseudocode for S-NAPTR
+
+B.1 Finding the first (best) target
+
+ Assuming the client supports 1 protocol for a particular application
+ service, the following pseudocode outlines the expected process to
+ find the first (best) target for the client, using S-NAPTR.
+
+
+ target = [initial domain]
+ naptr-done = false
+
+ while (not naptr-done)
+ {
+ NAPTR-RRset = [DNSlookup of NAPTR RRs for target]
+ [sort NAPTR-RRset by ORDER, and PREF within each ORDER]
+ rr-done = false
+ cur-rr = [first NAPTR RR]
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 19]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ while (not rr-done)
+ if ([SERVICE field of cur-rr contains desired application
+ service and application protocol])
+ rr-done = true
+ target= [REPLACEMENT target of NAPTR RR]
+ else
+ cur-rr = [next rr in list]
+
+ if (not empty [FLAG in cur-rr])
+ naptr-done = true
+ }
+
+ port = -1
+
+ if ([FLAG in cur-rr is "S"])
+ {
+ SRV-RRset = [DNSlookup of SRV RRs for target]
+ [sort SRV-RRset based on PREF]
+ target = [target of first RR of SRV-RRset]
+ port = [port in first RR of SRV-RRset]
+ }
+
+ ; now, whether it was an "S" or an "A" in the NAPTR, we
+ ; have the target for an A record lookup
+
+ host = [DNSlookup of target]
+
+ return (host, port)
+
+
+
+B.2 Finding subsequent targets
+
+ The pseudocode in Appendix B is crafted to find the first, most
+ preferred, host-port pair for a particular application service an
+ protocol. If, for any reason, that host-port pair did not work
+ (connection refused, application-level error), the client is expected
+ to try the next host-port in the S-NAPTR tree.
+
+ The pseudocode above does not permit retries -- once complete, it
+ sheds all context of where in the S-NAPTR tree it finished.
+ Therefore, client software writers could
+
+ o entwine the application-specific protocol with the DNS lookup and
+ RRset processing described in the pseudocode and continue the S-
+ NAPTR processing if the application code fails to connect to a
+ located host-port pair;
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 20]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+ o use callbacks for the S-NAPTR processing;
+
+ o use an S-NAPTR resolution routine that finds *all* valid servers
+ for the required application service and protocol from the
+ originating domain, and provides them in sorted order for the
+ application to try in order.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 21]
+
+Internet-Draft draft-daigle-napstr-04 February 2004
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2004). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Daigle & Newton Expires August 15, 2004 [Page 22]
+
diff --git a/doc/draft/draft-danisch-dns-rr-smtp-03.txt b/doc/draft/draft-danisch-dns-rr-smtp-03.txt
new file mode 100644
index 0000000..4a01d91
--- /dev/null
+++ b/doc/draft/draft-danisch-dns-rr-smtp-03.txt
@@ -0,0 +1,1960 @@
+
+
+
+INTERNET-DRAFT Hadmut Danisch
+Category: Experimental Oct 2003
+Expires: Apr 1, 2004
+
+ The RMX DNS RR and method for lightweight SMTP sender authorization
+ draft-danisch-dns-rr-smtp-03.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is subject to all provisions
+ of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six
+ months and may be updated, replaced, or obsoleted by other
+ documents at any time. It is inappropriate to use Internet-Drafts
+ as reference material or to cite them other than as "work in
+ progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+Abstract
+
+ This memo introduces a new authorization scheme for SMTP e-mail
+ transport. It is designed to be a simple and robust protection
+ against e-mail fraud, spam and worms. It is based solely on
+ organisational security mechanisms and does not require but still
+ allow use of cryptography. This memo also focuses on security and
+ privacy problems and requirements in context of spam defense. In
+ contrast to prior versions of the draft a new RR type is not
+ required anymore.
+
+
+
+
+
+
+
+
+
+
+
+
+Hadmut Danisch Experimental [Page 1]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ Table of Contents
+
+
+1. General Issues . . . . . . . . . . . . . . . . . . . . . . . . . 4
+2. Problem and threat description . . . . . . . . . . . . . . . . . 4
+ 2.1. Mail sender forgery . . . . . . . . . . . . . . . . . . . 4
+ 2.1.1 Definition of sender forgery . . . . . . . . . . . 4
+ 2.1.2 Spam . . . . . . . . . . . . . . . . . . . . . . . 5
+ 2.1.3 E-Mail Worms . . . . . . . . . . . . . . . . . . . 5
+ 2.1.4 E-Mail spoofing and fraud . . . . . . . . . . . . . 5
+ 2.2. Indirect damage caused by forgery . . . . . . . . . . . . 6
+ 2.3. Technical problem analysis . . . . . . . . . . . . . . . . 6
+ 2.4. Shortcomings of cryptographical approaches . . . . . . . . 7
+3. A DNS based sender address verification . . . . . . . . . . . . 7
+ 3.1. Overview . . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 3.2. Envelope vs. header sender address . . . . . . . . . . . . 9
+ 3.3. Domain part vs. full sender address . . . . . . . . . . . 9
+4. Mapping of E-Mail addresses to DNS names . . . . . . . . . . . . 10
+ 4.1. Domain part only . . . . . . . . . . . . . . . . . . . . . 10
+ 4.2. Full address . . . . . . . . . . . . . . . . . . . . . . . 11
+ 4.3. Empty address . . . . . . . . . . . . . . . . . . . . . . 11
+5. Mandatory entry types and their syntax . . . . . . . . . . . . . 11
+ 5.1. Overall structure . . . . . . . . . . . . . . . . . . . . 11
+ 5.2. Unused . . . . . . . . . . . . . . . . . . . . . . . . . . 12
+ 5.3. IPv4 and IPv6 address ranges . . . . . . . . . . . . . . . 12
+ 5.4. DNS Hostname . . . . . . . . . . . . . . . . . . . . . . . 13
+ 5.4.1 Road warriors and DynDNS entries . . . . . . . . . 13
+ 5.5. APL Reference . . . . . . . . . . . . . . . . . . . . . . 14
+ 5.6. Domain Member . . . . . . . . . . . . . . . . . . . . . . 14
+ 5.7. Full Address Query . . . . . . . . . . . . . . . . . . . . 15
+ 5.8. DNS mapped authorization . . . . . . . . . . . . . . . . . 15
+ 5.9. RMX reference . . . . . . . . . . . . . . . . . . . . . . 16
+6. Optional and experimental entry types . . . . . . . . . . . . . 16
+ 6.1. TLS fingerprint . . . . . . . . . . . . . . . . . . . . . 16
+ 6.2. TLS and LDAP . . . . . . . . . . . . . . . . . . . . . . . 16
+ 6.3. PGP or S/MIME signature . . . . . . . . . . . . . . . . . 16
+ 6.4. Transparent Challenge/Response . . . . . . . . . . . . . . 17
+ 6.5. SASL Challenge/Response . . . . . . . . . . . . . . . . . 17
+7. Encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
+ 7.1. Alternative encoding as TXT records . . . . . . . . . . . 17
+ 7.2. RMX Records . . . . . . . . . . . . . . . . . . . . . . . 17
+ 7.2.1 Overall structure . . . . . . . . . . . . . . . . . 18
+ 7.2.2 Record encoding . . . . . . . . . . . . . . . . . . 18
+ 7.2.3 Encoding of IPv4 and IPv6 address ranges . . . . . 18
+ 7.2.4 Encoding of DNS . . . . . . . . . . . . . . . . . . 18
+ 7.2.5 Encoding of unused and full query . . . . . . . . . 19
+ 7.2.6 Additional Records . . . . . . . . . . . . . . . . 19
+8. Message Headers . . . . . . . . . . . . . . . . . . . . . . . . 19
+
+
+
+Hadmut Danisch Experimental [Page 2]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+9. SMTP error messages . . . . . . . . . . . . . . . . . . . . . . 20
+10. Message relaying and forwarding . . . . . . . . . . . . . . . . 20
+ 10.1. Problem description . . . . . . . . . . . . . . . . . . . 20
+ 10.2. Trusted relaying/forwarding . . . . . . . . . . . . . . . 21
+ 10.3. Untrusted relaying/forwarding . . . . . . . . . . . . . . 21
+11. Security Considerations . . . . . . . . . . . . . . . . . . . . 22
+ 11.1. Draft specific considerations . . . . . . . . . . . . . . 22
+ 11.1.1 Authentication strength . . . . . . . . . . . . . 22
+ 11.1.2 Where Authentication and Authorization end . . . . 22
+ 11.1.3 Vulnerability of DNS . . . . . . . . . . . . . . . 23
+ 11.1.4 Sneaking RMX attack? . . . . . . . . . . . . . . 25
+ 11.1.5 Open SMTP relays . . . . . . . . . . . . . . . . . 25
+ 11.1.6 Unforged Spam . . . . . . . . . . . . . . . . . . 25
+ 11.1.7 Reliability of Whois Entries . . . . . . . . . . . 26
+ 11.1.8 Hazards for Freedom of Speech . . . . . . . . . . 26
+ 11.2. General Considerations about spam defense . . . . . . . . 27
+ 11.2.1 Action vs. reaction . . . . . . . . . . . . . . . 27
+ 11.2.2 Content based Denial of Service attacks . . . . . 27
+12. Privacy Considerations . . . . . . . . . . . . . . . . . . . . 28
+ 12.1. Draft specific considerations . . . . . . . . . . . . . . 28
+ 12.1.1 No content leaking . . . . . . . . . . . . . . . . 28
+ 12.1.2 Message reception and sender domain . . . . . . . 28
+ 12.1.3 Network structure . . . . . . . . . . . . . . . . 29
+ 12.1.4 Owner information distribution . . . . . . . . . . 29
+ 12.2. General Considerations about spam defense . . . . . . . . 29
+ 12.2.1 Content leaking of content filters . . . . . . . . 29
+ 12.2.2 Black- and Whitelists . . . . . . . . . . . . . . 30
+13. Deployment Considerations . . . . . . . . . . . . . . . . . . . 30
+ 13.1. Compatibility . . . . . . . . . . . . . . . . . . . . . . 30
+ 13.1.1 Compatibility with old mail receivers . . . . . . 30
+ 13.1.2 Compatibility with old mail senders . . . . . . . 30
+ 13.1.3 Compatibility with old DNS clients . . . . . . . . 30
+ 13.1.4 Compatibility with old DNS servers . . . . . . . . 30
+ 13.2. Enforcement policy . . . . . . . . . . . . . . . . . . . 31
+14. General considerations about fighting spam . . . . . . . . . . 31
+ 14.1. The economical problem . . . . . . . . . . . . . . . . . 31
+ 14.2. The POP problem . . . . . . . . . . . . . . . . . . . . . 32
+ 14.3. The network structure problem . . . . . . . . . . . . . . 33
+ 14.4. The mentality problem . . . . . . . . . . . . . . . . . . 33
+ 14.5. The identity problem . . . . . . . . . . . . . . . . . . 33
+ 14.6. The multi-legislation problem . . . . . . . . . . . . . . 34
+Implementation and further Information . . . . . . . . . . . . . . . 34
+References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
+Draft History . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
+Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . . 35
+
+
+
+
+
+
+Hadmut Danisch Experimental [Page 3]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+1. General Issues
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in
+ this document are to be interpreted as described in RFC 2119 [1].
+
+2. Problem and threat description
+
+2.1. Mail sender forgery
+
+ The amount of e-mails with forged sender addresses has dramatically
+ increased. As a consequence, damages and annoyances caused by such
+ e-mails increased as well. In the majority of examined e-mails the
+ domain name of the envelope sender address was forged, and the e-
+ mail was sent from an IP address which does not belong to a network
+ used by the actual owner of the domain.
+
+2.1.1. Definition of sender forgery
+
+ As discussions, comments to prior versions of this draft, and
+ different approaches to stop forgery showed, different perceptions
+ of "mail forgery" exist. For example, there are mechanisms to
+ verify e-mail addresses for mailing lists, web servers, or to stop
+ spam, which do send a message with a random number to the given
+ address and expect the user to send a reply. Here, someone is
+ considered to be allowed to use a particular e-mail address, if and
+ only if he is able to receive informations sent to this address,
+ and is able to reply to such a message. While this definition
+ appears to be quite plausible and natural, it can't be used for a
+ simple technical solution. Sending back a challenge and expecting a
+ reply is simply too much overhead and time delay, and not every
+ authorized sender is able or willing to reply (e.g. because he went
+ offline or is not a human).
+
+ Within the scope of this memo, sender forgery means that the
+ initiator of an e-mail transfer (which is the original sender in
+ contrast to relays) uses a sender address which he was not
+ authorized to use. Being authorized to use an address means that
+ the owner (administrator) of the internet domain has given
+ permission, i.e. agrees with the use of the address by that
+ particular sender. This memo will cover both the permission of the
+ full e-mail address and the domain part only for simplicity.
+
+ Within context of Internet and SMTP, the sender address usually
+ occurs twice, once as the envelope sender address in SMTP, and once
+ as the address given in the RFC822 mail header. While the following
+ considerations apply to both addresses in principle, it is
+ important to stress that both addresses have distinct semantics and
+
+
+
+Hadmut Danisch Experimental [Page 4]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ are not neccessarily the same. The envelope address identifies the
+ initiator of the transport, while the header identifies the author
+ of the message content. Since this memo deals with the message
+ transport only and completely ignores the message content, the
+ method should naturally be applied to the envelope sender address.
+
+2.1.2. Spam
+
+ A common and well known problem is the dramatic increase of
+ unsolicited e-mail, commonly called "spam". Again, the majority of
+ examined e-mails had forged sender addresses. The abused domains
+ were mainly those of common webmailers as hotmail or yahoo, or
+ well-known companies.
+
+ Unfortunately, there is no accurate definition of spam availabe
+ yet, and neither are the concise technical criterions to filter or
+ block spam with technical mechanisms. There are efforts to design
+ content based filters, but these filters are expensive in
+ calculation time (and sometimes money), and they do not reliably
+ provide predictable results. Usually they give false positives
+ and/or require user interaction. Content filters in general suffer
+ from a design problem described later in this memo. Therefore,
+ this proposal does not use the content based approach to block
+ spam.
+
+ As analysis of spam messages showed, most of spam messages were
+ sent with forged envelope sender addresses. This has mainly three
+ reasons. The first reason is, that spam senders usually do not
+ want to be contacted by e-mail. The second reason is, that they do
+ not want to be blacklisted easily. The third reason is, that spam
+ is or is going to be unlawful in many countries, and the sender
+ does not want to reveal his identity. Therefore, spam is considered
+ to be a special case of sender forgery.
+
+2.1.3. E-Mail Worms
+
+ Another example of sender forgery is the reproduction of e-mail
+ worms. Most worms do choose random sender addresses, e.g. using
+ the addresses found in mailboxes on the infected system. In most
+ cases analyzed by the author, the e-mails sent by the reproduction
+ process can also be categorized as forged, since the infected
+ system would under normal circumstances not be authorized to send
+ e-mails with such e-mail addresses. So forgery does not require a
+ malicious human to be directly involved. This memo covers any kind
+ of e-mail sender address forgery, included those generated by
+ malicious software.
+
+2.1.4. E-Mail spoofing and fraud
+
+
+
+Hadmut Danisch Experimental [Page 5]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ Forging e-mail sender addresses for fraud or other kinds of
+ deception ("human engineering") has also dramatically increased.
+ There are many known cases where single or mass e-mails were sent
+ with wrong sender addresses, pretending to come from service
+ provider, software manufacturers etc., and asking the receiver to
+ install any software or patches, or to reply with any confidential
+ information. The Internet is becoming more and more a scene of
+ crime, and so are it's services, including e-mail. It is obvious
+ that crime based on e-mail is eased by the fact that SMTP allows
+ arbitrary sender address spoofing.
+
+2.2. Indirect damage caused by forgery
+
+ As observed by the author, mass mails and worms with forged sender
+ addresses can cause a severe damage for the real owner of the
+ abused sender addresses. If a sender A is sending an e-mail to the
+ receiver B, pretending to be C by using a sender address of C's
+ domain, then C has currently no chance to prevent this, since C's
+ machines and software are not involved in any way in the delivery
+ process between A and B. B will nevertheless send any error
+ messages (virus/spam alert, "no such user", etc.) to C, erroneously
+ assuming that the message was sent by C. The author found several
+ cases where this flood of error messages caused a severe denial of
+ service or a dramatic increase of costs, e.g. when C was
+ downloading the e-mail through expensive or low bandwidth
+ connections (e.g. modem or mobile phones), or where disk space was
+ limited. The author examined mass mailings, where several tens or
+ hundreds of thousands of messages were sent to several addresses
+ around the world, where these messages caused only annoyance. But
+ since several thousands of these addresses were invalid or didn't
+ accept the message, the owner of the DNS domain which was abused by
+ the spammer to forge sender addresses was flooded for several
+ months with thousands of error messages, jamming the e-mail system
+ and causing severe costs and damages.
+
+ As a consequence, when A sends a message to B, pretending to be C,
+ there must be any mechanism to allow C to inform B about the fact,
+ that A is not authorized to use C as a sender address. This is what
+ this memo is about.
+
+2.3. Technical problem analysis
+
+ Why does e-mail forgery actually exist? Because of the lack of the
+ Simple Mail Transfer Protocol SMTP[2] to provide any kind of sender
+ authentication, authorisation, or verification. This protocol was
+ designed at a time where security was not an issue. Efforts have
+ been made to block forged e-mails by requiring the sender address
+ domain part to be resolvable. This method provides protection from
+
+
+
+Hadmut Danisch Experimental [Page 6]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ e-mails with non-existing sender domains, and indeed, for some time
+ it blocked most spam e-mails. However, since attackers and spam
+ senders began to abuse existing domain names, this method was
+ rendered ineffective.
+
+2.4. Shortcomings of cryptographical approaches
+
+ At a first glance, the problem of sender address forgery might
+ appear to be solvable with cryptographic methods such as challenge
+ response authentications or digital signatures. A deeper analysis
+ shows that only a small, closed user group could be covered with
+ cryptographical methods. Any method used to stop spam forgery must
+ be suitable to detect forgery not only for a small number of
+ particular addresses, but for all addresses on the world. An
+ attacker does not need to know the secrets belonging to a
+ particular address. It is sufficient to be able to forge any
+ address and thus to know any secret key. Since there are several
+ hundreds of millions of users, there will always be a large amount
+ of compromised keys, thus spoiling any common cryptographic method.
+ Furthermore, cryptography has proven to be far too complicated and
+ error prone to be commonly administered and reliably implemented.
+ Many e-mail and DNS administrators do not have the knowledge
+ required to deal with cryptographic mechanisms. Many legislations
+ do not allow the general deployment of cryptography and a directory
+ service with public keys. For these reasons, cryptography is
+ applicable only to a small and closed group of users, but not to
+ all participants of the e-mail service.
+
+3. A DNS based sender address verification
+
+3.1. Overview
+
+ To gain improvement in e-mail authenticity while keeping as much
+ SMTP compatibility as possible, a method is suggested which doesn't
+ change SMTP at all.
+
+ The idea is to store informations about how to verify who is
+ authorized to transmit e-mails through SMTP with a particular
+ sender address (either full address or - for simplicity - only the
+ domain part of the address) in a directory service, which is
+ currently the DNS. To be precise, the verification consists of two
+ steps, the classical pair of authentication and authorization:
+
+ The first step is the authentication. While several methods are
+ possible to perform authentication (see below), the most important
+ and robust method is the verification of the sender's IP address.
+ This is done implicitely by TCP/IP and the TCP sequence number. The
+ authenticated identity is the IP address. It has to be stressed
+
+
+
+Hadmut Danisch Experimental [Page 7]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ that this TCP/IP "authentication" is a weak authentication and
+ vulnerable to several attacks. It is nevertheless sufficient for
+ this purpose, especially for blocking spam. It doesn't take any
+ implementation and it doesn't cost: It is already there, it is a
+ functionality of TCP/IP. An incoming SMTP connection based on
+ TCP/IP already carries the sender's IP address without any
+ modification of SMTP. See below (section Entry types) for more
+ details about authentication methods.
+
+ The second step is the authorization. It is based on the identity
+ given by the previous authentication step, e.g. the IP address of
+ the originator of the incoming SMTP connection, and on the
+ envelope sender address. The mechanism proposed in this memo
+ answers the question "Is that particular sender (IP address,...)
+ allowed to send with that sender address" by querying and
+ processing informations stored in a directory service, which is
+ DNS.
+
+ When the sender has issued the "MAIL FROM:" SMTP command, the
+ receiving mail transfer agent (MTA) can - and modern MTAs do -
+ perform some authorization checks, e.g. run a local rule database
+ or check whether the sender domain is resolvable.
+
+ The suggested method is to let the DNS server for the sender domain
+ provide informations about who - this means for example which IP
+ address - is authorized to use an address or a domain as a part of
+ it. After receiving the "MAIL FROM:" SMTP command, the receiving
+ MTA can verify, whether e. g. the IP address of the sending MTA is
+ authorized to send mails with this domain name. Therefore, a list
+ of entries with authorized IP addresses or other informations is
+ provided by the authoritative DNS server of that domain. The entry
+ types are described in the subsequent chapters. Some of these
+ methods are
+
+ - An IPv4 or IPv6 network address and mask
+ - A fully qualified domain name referring to an A record
+ - A fully qualified domain name referring to an APL record
+
+ RMX records of these types would look like this:
+
+ somedomain.de. IN RMX ipv4:10.0.0.0/8
+ rmxtest.de. IN RMX host:relay.provider.com
+ danisch.de. IN RMX apl:relays.rackland.de
+ relays.rackland.de. IN APL 1:213.133.101.23/32 1:1.2.3.0/24
+
+ where the machine with the example address 213.133.101.23 and the
+ machines in the example subnet 1.2.3.0/24 are the only machines
+ allowed to send e-mails with an envelope sender address of domain
+
+
+
+Hadmut Danisch Experimental [Page 8]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ danisch.de. Since the APL records do not necessarily belong to the
+ same domain or zone table as the RMX records, this easily allows to
+ refer to APL records defined by someone else, e.g. the internet
+ access or server hosting provider, thus reducing administrative
+ overhead to a minimum. In the example given above, the domain
+ danisch.de and several other domains are hosted by the service
+ provider Rackland. So if the relay structure of Rackland is
+ modified, only the zone of rackland.de needs to be modified. The
+ domain owners don't need to care about such details.
+
+3.2. Envelope vs. header sender address
+
+ Questions were raised why the proposed mechanism is based on the
+ envelope sender address, and not on the sender address given in the
+ message header. Technically, both can be used. Actually, it makes
+ sense to use the envelope address.
+
+ In common, the header sender address identifies the author of the
+ content, while the envelope sender tells who caused the
+ transmission. The approach proposed in this memo is transmission
+ based, not content based. We can not authorize the author of a
+ message if we don't have contact with him, if the message does not
+ already contain a signature. In contrast, the sending MTA is linked
+ to an IP address which can be used for authentication. This
+ mechanism might not be very strong, but it is available and
+ sufficient to solve today's e-mail security problems.
+
+ Some people argued that it is the header address and not the sender
+ address, which is displayed in common mail readers (MUAs), and
+ where the receiver believes the mail comes from. That's true, but
+ it doesn't help. There are many cases where the header sender
+ differs from the envelope sender for good reasons (see below in the
+ consequences chapter for the discussion about relaying). Relaying,
+ mailing lists etc. require to replace the sender address used for
+ RMX. If this were the header address, the message header would have
+ to be modified. This is undesirable.
+
+3.3. Domain part vs. full sender address
+
+ Former versions of this draft were limited to the domain part of
+ the sender address. The first reason is that it is common and MX-
+ like, to lookup only the domain part of an e-mail address in DNS.
+ The second reason is, that it was left to the private business of
+ the domain administration to handle details of user verification.
+ The idea was that the domain administration takes care to verify
+ the left part of an e-mail address with an arbitrary method of
+ their individual taste. RMX was originally designed to ignore the
+ left part of the address and to expect the domain administration to
+
+
+
+Hadmut Danisch Experimental [Page 9]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ take over responsibility for enforcing their policy. If, e.g., a
+ spam message arrived and passed the RMX mechanism, it is known to
+ be authorized by the domain administration and they can be blamed,
+ no matter what is on the left side of the sender address - it's
+ their private problem what happens on the left side of the @. By
+ far the most of the comments to prior versions of this draft agreed
+ with that. A few comments asked for a finer granularity.
+
+ And indeed, there is no technical reason against a finer
+ granularity. All it takes is a mapping from a given envelope
+ sender address to a DNS name, and the RMX lookup for that
+ particular e-mail address could be done instead of a lookup for the
+ domain part only. However, to my knowledge, most domain
+ administrators would not like to provide an RMX entry for every
+ single e-mail address. In many cases, this would also overload DNS
+ servers.
+
+ It is to be discussed how to cover both views. One method could be
+ to query the full address, and if no RMX records were found to
+ query the domain part only. A different approach would be to query
+ the domain part only, and if it's RMX record contain a special
+ entry, then a new query for the full address is triggered. A third
+ way would be to always query the full address and to leave the
+ problem to the wildcard mechanism of DNS. This still has to be
+ discussed and will be described in future versions of this draft.
+
+
+
+
+
+
+
+
+
+
+
+4. Mapping of E-Mail addresses to DNS names
+
+ To perform the RMX query, a mapping is needed from E-Mail addresses
+ to DNS fully qualified domain names.
+
+ This chapter is under development and just a first approach.
+
+4.1. Domain part only
+
+ Mapping of the domain part is trivial, since the domain part of an
+ e-mail address itself is a valid DNS name and does not need
+ translation. It might be nevertheless desirable to distinguish the
+
+
+
+Hadmut Danisch Experimental [Page 10]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ RMX entries from other entries, depending of the encoding of the
+ records. If the RMX entries are encoded in TXT record types, they
+ might collide with other uses of TXT records. It might be
+ necessary to prepend the domain part with a special prefix, e.g.
+ _rmx. So the e-mail address some.user@example.com could be mapped
+ to example.com or _rmx.example.com.
+
+4.2. Full address
+
+ Mapping a full address is slightly more difficult. The @ sign must
+ be unambiguously translated, and therefore can not be simply
+ translated into a dot. The e-mail addresses some.user@example.com
+ and some@user.example.com must have different mappings. Therefore,
+ the @ sign could be translated into _rmx, implicitely assuming that
+ this is not an allowed domain name component of normal domain
+ names. Then the rightmost _rmx in the mapped DNS name always
+ corresponds to the @ sign. some.user@example.com would e translated
+ into some.user._rmx.example.com and can be covered by a wildcard
+ entry like *._rmx.example.com.
+
+ Character encoding and character sets are still to be discussed.
+
+4.3. Empty address
+
+ Unfortunately, SMTP allows empty envelope sender addresses to be
+ used for error messages. Empty sender addresses can therefore not
+ be prohibited. As observed, a significant amount of spam was sent
+ with such an empty sender address. To solve this problem, the host
+ name given in the HELO or EHLO command is taken to lookup the RMX
+ records instead. This makes sense, since such messages were
+ generated by the machine, not a human.
+
+
+
+
+5. Mandatory entry types and their syntax
+
+ The entry types described in this section MUST be supported by any
+ implementation of this draft.
+
+5.1. Overall structure
+
+ Similar to APL, an RMX record is just a concatenation of zero or
+ more RMX entries. The entries within one record form an ordered
+ rule base as commonly usual in packet filtes and firewall rulesets,
+ i. e. they are processed one ofter another until the first entry
+ matches. This entry determines the result of the query. Once a
+ matching entry is found, the RMX processing is finished.
+
+
+
+Hadmut Danisch Experimental [Page 11]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ For any domain name there should not exist more than a single RMX
+ record. Due to the structure of DNS, it is nevertheless possible to
+ have more than a single RMX record. Multiple RMX records are
+ treated as a single record consisting of the concatenation of all
+ records. While the entries in a record are ordered, the records are
+ not ordered and may be processed in arbitrary order. If the order
+ of the entries matters, it is the zone maintainer's responsibility
+ to keep those entries in a single record. For example, there are
+ negative entries, which exclude IP addresses from authorization.
+ It is important that these entries are processed before positive
+ entries giving permission to a wider address range. Since order is
+ guaranteed only within a record, corresponding negative and
+ positive entries must be put in the same record.
+
+ An RMX record may consist of one or more entries, where the entries
+ are separated by whitespace. An entry must not contain white space.
+ Each entry consists of an optional exclamation sign, a tag, a
+ colon, and the entry data:
+
+ [!] TAG : ENTRY-SPECIFIC-DATA
+
+ If the entry starts with an exclamation sign, the entry is negated.
+ See the entry type description below for details.
+
+ The TAG is the mnemonic type identifier or the decimal number of
+ the entry. The TAG is case-insensitive. It is immediately followed
+ by a colon.
+
+ The syntax and semantics of ENTRY-SPECIFIC-DATA depends of the the
+ entry type. See description below.
+
+ Example:
+
+ danisch.de. IN RMX apl:relays.rackland.de !ipv4:1.2.3.5
+ ipv4:1.2.3.0/24
+
+5.2. Unused
+
+ This is a primitive entry which just says that this sender address
+ will never be used as a sender address under any circumstances.
+ Example:
+
+ testdomain.danisch.de IN RMX unused:
+
+5.3. IPv4 and IPv6 address ranges
+
+ These entry types contain a bit sequence representing a CIDR
+ address part. If that bit sequence matches the given IP address,
+
+
+
+Hadmut Danisch Experimental [Page 12]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ authorization is granted or denied, depending on the negation flag.
+
+ The entry is prepended with the tag "IPv4" or "IPv6". The colon is
+ followed with an IPv4 or IPv6 address in standard notation,
+ optionally followed by a slash and a mask length. If the negation
+ flag is set, then the given address range is excluded. Examples:
+
+ danisch.de IN RMX ipv4:213.133.101.23 ipv6:fe00::0
+ IN RMX ipv4:10.0.0.0/8 ipv6:fec0::0/16
+ IN RMX !ipv4:1.2.3.4
+
+ (Please note that it does not make much sense to use
+ RFC1918-Addresses in RMX records, this is just to give a syntax
+ example.)
+
+
+5.4. DNS Hostname
+
+ This entry type simply contains a regular DNS name, which is to be
+ resolved as a host name (fetch the A record or IPv6 equivalent). If
+ the given IP address matches the result, authorization is granted
+ or denied, depending on the negation flag. It is still to be
+ defined how to treat unresolvable entries.
+
+ The entry is prepended with the tag "host", followed by a colon and
+ the hostname. Examples:
+
+ danisch.de IN RMX host:relay.provider.de
+ IN RMX !host:badmachine.domain.de apl:relays.domain.de
+
+5.4.1. Road warriors and DynDNS entries
+
+ Several people argued against RMX that it would break their
+ existing installation which delivers e-mail from dynamically
+ assigned IP addresses, because their IP providers didn't assign a
+ static address, or because they are a road warrior, plugging their
+ notebook in any hotel room on the world.
+
+ RMX provides a simple solution. If such a machine has a dynamically
+ updated DNS entry (e.g. DynDNS), all it takes is an RMX entry of
+ the hostname type pointing to this dynamic DNS entry.
+
+ The cleaner solution would be to deliver mail the same way as it is
+ received: If downloaded by POP from a central relay with a static
+ address, where the MX points to, then it would be a good idea to
+ deliver e-mail the same way in reverse direction. Unfortunately,
+ plain POP does not support uploading yet.
+
+
+
+
+Hadmut Danisch Experimental [Page 13]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+5.5. APL Reference
+
+ This entry type simply contains a regular DNS name, which is to be
+ resolved as an APL record index (fetch the APL record). If the
+ given IP address positively matches the APL, authorization is
+ granted. Details of the semantic (espially when the negation bit is
+ set) are still to be defined. It is still to be defined how to
+ treat unresolvable entries.
+
+ The entry is prepended with the tag "host", followed by a colon and
+ the hostname. Example:
+
+ danisch.de IN RMX apl:relays.rackland.de
+
+5.6. Domain Member
+
+ In many cases it is desirable to cover all hosts of a given domain
+ with an RMX record without the need to duplicate the list of these
+ hosts. This entry type does it (thanks to Eric A. Hall for pointing
+ out this entry type). It contains a regular DNS name.
+
+ If this entry type is given, a reverse DNS query for the IP address
+ of the sending MTA is performed to find its official fully
+ qualified domain name. To prevent spoofing, this domain name is
+ accepted only if a subsequent address query to the given domain
+ name points to exactly the IP address of the sending MTA (the usual
+ procedure to verify PTR records).
+
+ The entry matches if the fully qualified domain name of the sending
+ MTA ends in the given domain. The negation flag works as usual.
+
+ The tag for this entry type is "domain". After the colon the domain
+ name is given, but might be empty, thus pointing to itself.
+ Example:
+
+ somedomain.org IN RMX domain:somedomain.org domain:provider.com
+
+ would authorize all machines which's hostname can be verified
+ through an PTR and A query, and which ends in "somedomain.org" or
+ "provider.com".
+
+ With such an entry, large companies with different networks can
+ easily be covered with just a single and simple RMX entry.
+ Obviously, it requires proper PTR records.
+
+ As a special shortcut, the DNS name may be empty. In this case the
+ domain name of the zone itself is taken. Thus, with a very simple
+ entry of the type
+
+
+
+Hadmut Danisch Experimental [Page 14]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ somecompany.com IN RMX domain:
+
+ a company could authorize all machines which's IP addresses map to
+ DNS names end in somecompany.com, which applies in the majority of
+ companies.
+
+
+
+
+5.7. Full Address Query
+
+ As described above, RMX records will in most cases apply to the
+ domain part of the sender address. In special cases it might be
+ desirable to query the RMX record for a particular address. An RMX
+ entry of the Full Address Query type may occur in a domain RMX
+ record only. It signals that the RMX record for the full address is
+ to be fetched and processed.
+
+ This entry type does not take arguments. The negation flag is not
+ supported. The tag is "full".
+
+ If such a full address query is to be performed, the mail address
+ must be mapped to a valid and non-ambiguos DNS name. This mapping
+ is still to be defined. It is not sufficient to simply replace the
+ @ with a dot, because of case sensitivity, character sets, etc. The
+ e-mail addresses
+
+ john.doe@example.org
+ John.Doe@example.org
+ john@doe.example.org
+
+ must all be mapped to different DNS entries. This entry type might
+ vanish in future versions of the draft, depending on the discussion
+ about whether to query the domain name part only or the full
+ address.
+
+5.8. DNS mapped authorization
+
+ As I learned from comments to prior versions of the draft and from
+ alternative proposals, many users wish to have a DNS mapped
+ authorization table, i. e. the client queries a DNS entry of the
+ form a.b.c.d.domain, where a.b.c.d is the sender's IP address.
+ Since people wish to have this, RMX will now include such a mapping
+ entry. The entry has a parameter giving the DNS domain name where
+ to look at. If the parameter is empty, then the same domain is
+ taken as for the RMX lookup.
+
+ As this is currently under construction and discussion in an IETF
+
+
+
+Hadmut Danisch Experimental [Page 15]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ group, details will be published in future versions of this draft.
+
+5.9. RMX reference
+
+ This entry type has no parameters. It means that all those machines
+ are authorized, which are pointed to by an MX record.
+
+6. Optional and experimental entry types
+
+ The following subsections roughly describe further entry types
+ which might not be supported by all implementations and might not
+ be allowed in all legislations. These methods might vanish in
+ future versions of the draft and are just considerations about what
+ to include in RMX and what to not include. The main purpose of this
+ section is to start discussion about such entry types.
+
+ The disadvantage of the following methods is that they violate the
+ basic idea of RMX, i. e. to be simple, robust, easy to implement
+ and easy to administer. I personally do not believe that it is a
+ good idea or even feasible to implement cryptography for a world
+ wide e-mail transfer network. Keep in mind that cryptographic keys
+ can be copied. If only <0.1% of cryptographic keys were revealed,
+ this completely compromises and spoils RMX. Cryptography is simply
+ the wrong tool for the problem RMX is intended to solve. I
+ nevertheless like to discuss these methods.
+
+6.1. TLS fingerprint
+
+ The sender is considered to be authorized if the message was
+ transmitted through SMTP and TLS, and the sender used a certificate
+ matching the fingerprint given in the RMX record.
+
+6.2. TLS and LDAP
+
+ This means that the receiver should perform an LDAP query for the
+ sender address (through the LDAP SRV record or given in the RMX
+ record), fetch the X.509 certificate for the sender. The sender is
+ considered to be authorized when the message was transmitted
+ through SMTP and TLS using this certificate.
+
+6.3. PGP or S/MIME signature
+
+ It would be possible to accept a message only if it was signed with
+ PGP or S/MIME with a key which's fingerprint is given in the RMX
+ record or to be fetched from LDAP or any PGP database. This is
+ just for discussion, since it violates the idea of RMX to focus on
+ the transport, not on the content. It would also allow replay
+ attacks and not cover the envelope sender address or message
+
+
+
+Hadmut Danisch Experimental [Page 16]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ header.
+
+6.4. Transparent Challenge/Response
+
+ It would also be possible to implement a challenge-response
+ mechanism without modifying the syntax of SMTP. For example, the
+ receiving MTA could issue a challenge with it's very first greeting
+ message, the sending MTA could hide the response in the HELO
+ parameter and when the receiving MTA later learns the sender
+ envelope address, it could verify the response based on
+ informations in the RMX record.
+
+6.5. SASL Challenge/Response
+
+ Modern SMTP implementations already include a SASL mechanisms,
+ which easily allows to plugin new authentication mechanisms. While
+ common SASL mechanisms require to use a previously shared password,
+ a new mechanism could perform a challenge response authentication
+ as a SASL method.
+
+
+
+
+
+
+7. Encoding
+
+7.1. Alternative encoding as TXT records
+
+ The main objection against the prior versions of this draft was
+ that it requires a new RR entry type and upgrading all DNS servers.
+
+ Therefore and alternative encoding is proposed. Instead of using a
+ new RR type, the TXT record type is used to contain the RMX record.
+ The records would simply look as described in the entry type
+ chapters above, e.g.
+
+ _rmx.danisch.de. IN TXT "apl:relays.rackland.de"
+
+ To allow smooth introduction of RMX without the need to immediately
+ upgrade all DNS servers, all clients (which have to be newly
+ installed anyway) MUST support both the TXT and the RMX records. A
+ client has to perform an ANY or a TXT and a RMX query. Servers/zone
+ tables may currently use TXT entries but SHOULD use RMX entries in
+ future.
+
+7.2. RMX Records
+
+
+
+
+Hadmut Danisch Experimental [Page 17]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+7.2.1. Overall structure
+
+ Each entry starts with an octet containting the entry type and the
+ negation flag:
+
+ +---+---+---+---+---+---+---+---+------
+ | N | Entry Type Code | Parameters...
+ +---+---+---+---+---+---+---+---+------
+
+ N If this bit (MSB) is set, an IP address
+ matching this entry is not authorized,
+ but explicitely rejected. See entry
+ type descriptions for details.
+
+ Entry Type A 7bit number simply determining the entry
+ type.
+
+
+ Currently, entries do not have an explicit length field, the entry
+ length is determined implicitely by the entry type. Applications
+ are required to abort if an unknown entry type is found, instead of
+ skipping unknown entries.
+
+7.2.2. Record encoding
+
+ A RMX record is simply a concatenation of RMX entries.
+
+7.2.3. Encoding of IPv4 and IPv6 address ranges
+
+ After the entry type tag as described above, one octet follows
+ giving the length L of the bit sequence. Then a sequence of exactly
+ as many octets follows as needed to carry L bits of information (=
+ trunc((L+7)/8) ).
+
+ +---+---+---+---+---+---+---+---+
+ | N | Entry Type Code (1 or 2) |
+ +---+---+---+---+---+---+---+---+
+ | Length Field L |
+ +---+---+---+---+---+---+---+---+
+ | Bit Field |
+ / ((L+7)/8) Octets /
+ +---+---+---+---+---+---+---+---+
+
+
+7.2.4. Encoding of DNS
+
+ After the entry type tag immediately follows a DNS encoded and
+ compressed [3] domain name.
+
+
+
+Hadmut Danisch Experimental [Page 18]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ +---+---+---+---+---+---+---+---+
+ | N | Entry Type Code (3..5) |
+ +---+---+---+---+---+---+---+---+
+ | Length Field L |
+ +---+---+---+---+---+---+---+---+
+ | Encoded DNS |
+ / Name as described in RFC1035 /
+ +---+---+---+---+---+---+---+---+
+
+ In contrast to earlier versions of this draft, the DNS name cannot
+ be compressed, since this would cause decompression errors when a
+ DNS server is part of the query chain which does not know this
+ particular RR type.
+
+7.2.5. Encoding of unused and full query
+
+ These entries do not contain parameters and does not allow the
+ negation flag. So the encoding is quite simple:
+
+ +---+---+---+---+---+---+---+---+
+ | 0 | Entry Type Code (6 or 7)|
+ +---+---+---+---+---+---+---+---+
+
+
+
+7.2.6. Additional Records
+
+ In order to avoid the need of a second query to resolve the given
+ host name, a DNS server should enclose the A record for that domain
+ name in the additional section of the additional section of the DNS
+ reply, if the server happens to be authoritative.
+
+ In order to avoid the need of a second query to resolve the given
+ host name, a DNS server should enclose the APL record for that
+ domain name in the additional section of the additional section of
+ the DNS reply, if the server happens to be authoritative.
+
+
+
+8. Message Headers
+
+ An RMX query must be followed by any kind of action depending on
+ the RMX result. One action might be to reject the message. Another
+ action might be to add a header line to the message body, thus
+ allowing MUAs and delivery programs to filter or sort messages.
+
+ In future, the RMX result might be melted into the Received: header
+ line.
+
+
+
+Hadmut Danisch Experimental [Page 19]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ The details of such entries are to be discussed. As a proposal the
+ following form is suggested:
+
+ X-RMX: RESULT addr ADDRESS by HOST on DATE mechanism MECHANISM
+
+ where
+
+ RESULT is one of "Granted", "Denied", "NotInRMX", "NoRMX",
+ "TempFail", "BadData", "Trusted".
+
+ ADDRESS is the IP address of the sending machine
+
+ HOST is the name of the machine performing the RMX query.
+
+ DATE is the date of the query.
+
+ MECHANISM is the RMX method used to authorize the sender.
+
+
+
+9. SMTP error messages
+
+ If a message is rejected because of RMX records, an error message
+ should be issued which explains the details. It is to be discussed
+ whether new SMTP error codes are to be defined.
+
+
+10. Message relaying and forwarding
+
+10.1. Problem description
+
+ Message forwarding and relaying means that an MTA which received an
+ e-mail by SMTP does not deliver it locally, but resends the message
+ - usually unchanged except for an additional Received header line
+ and maybe the recipient's address rewritten - to the next SMTP MTA.
+ Message forwarding is an essential functionality of e-mail
+ transport services, for example:
+
+ - Message transport from outer MX relay to the intranet
+ - Message forwarding and Cc-ing by .forward or .procmail-alike
+ mechanisms
+ - Mailing list processing
+ - Message reception by mail relays with low MX priority,
+ usually provided by third parties as a stand-by service
+ in case of relay failure or maintenance
+ - "Forwarding" and "Bouncing" as a MUA functionality
+
+ In all these cases a message is sent by SMTP from a host which is
+
+
+
+Hadmut Danisch Experimental [Page 20]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ not covered by the original sender domain's RMX records. While the
+ RMX records would forbid accepting this message, it still must be
+ accepted. The following subsections explain how to cope with
+ relaying.
+
+10.2. Trusted relaying/forwarding
+
+ In some cases the receiving MTA trusts the sending MTA to not fake
+ messages and to already have checked the RMX records at message
+ reception. As a typical example, a company might have an outer mail
+ relay which receives messages from the Internet and checks the RMX
+ records. This relay then forwards the messages to the different
+ department's mail servers. It does not make sense for these
+ department mail servers to check the RMX record, since the RMX
+ records have already been checked and - since the message was
+ relayed by the outer relay - always would deny the message. In this
+ case there is a trust relationship between the department relays
+ and the outer relay. So RMX checking is turned off for trusted
+ relays. In this example, the department relays would not check
+ messages from the outer relay (but for intranet security, they
+ could still check RMX records of the other departments sub-domains
+ to avoid internal forgery between departments).
+
+ Another common example are the low-priority MX relays, which
+ receive and cache e-mails when the high-priority relays are down.
+ In this case, the high-priority relay would trust the low-priority
+ relay to have verified the sender authorization and would not
+ perform another RMX verification (which would obviously fail).
+
+ When a relay forwards a message to a trusting machine, the envelope
+ sender address should remain unchanged.
+
+10.3. Untrusted relaying/forwarding
+
+ If the receiving MTA does not trust the forwarding MTA, then there
+ is no chance to leave the sender envelope address unchanged. At a
+ first glance this might appear impracticable, but this is
+ absolutely necessary. If an untrusted MTA could claim to have
+ forwarded a message from a foreign sender address, it could have
+ forged the message as well. Spammers and forgers would just have to
+ act as such a relay.
+
+ Therefore, it is required that, when performing untrusted
+ forwarding, the envelope sender address has to be replaced by the
+ sender address of someone responsible for the relaying mechanism,
+ e.g. the owner of the mailing list or the mail address of the user
+ who's .forward caused the transmission. It is important to stress
+ that untrusted relaying/forwarding means taking over responsibility
+
+
+
+Hadmut Danisch Experimental [Page 21]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ for the message. It is the idea of RMX records to tie
+ responsibility to message transmission. Untrusted relaying without
+ replacing the sender address would mean to transmit without taking
+ responsibility.
+
+ The disadvantage is that the original sender address is lost.
+ Therefore, whenever a sender address replacement happens, the
+ Received-Line must contain the old address. Many of today's MTAs
+ already insert the envelope recipient address, but not the sender
+ address into the Received header line. It seems reasonable to
+ require every Received line to include both the sender and
+ recipient address of the incoming SMTP connection.
+
+
+11. Security Considerations
+
+11.1. Draft specific considerations
+
+11.1.1. Authentication strength
+
+ It is important to stress, that the suggested method does not
+ provide high level security and does not completely prevent forged
+ e-mails or spam under any circumstances. It is a robust, but not
+ highly reliable and completely secure security mechanism. Keep in
+ mind that it is based on DNS, and DNS is not secure today.
+ Authorization is based on the IP address. The very same machine
+ with the very same IP address could be authorized to send e-mail
+ with a given sender address and sending spam at the same time.
+ Maybe because several users are logged in. Or because several
+ customers use the same relay of the same ISP, where one customer
+ could use the sender address of a different customer. It is up to
+ the ISP to prevent this or not. Machines can still be hijacked.
+ Spammers are also domain owners. They can simply use their own
+ domain and authorize themselves. You will always find people on the
+ world who do not care about security and open their relays and RMX
+ records for others to abuse them. RMX is to be considered as a
+ very cheap and simple light weight mechanism, which can
+ nevertheless provide a significant improvement in mail security
+ against a certain class of attacks, until a successor of SMTP has
+ been defined and commonly accepted.
+
+11.1.2. Where Authentication and Authorization end
+
+ Previous versions of RMX records did not cover the local part of
+ the e-mail address, i.e. what's on the left side of the @ sign.
+ This is still to be discussed. Authentication and authorization are
+ limited to the sending MTA's IP address. The authentication is
+ limited to the TCP functionality, which is sufficient for light
+
+
+
+Hadmut Danisch Experimental [Page 22]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ weight authentication. The RMX records authorize the IP address of
+ the sending host only, not the particular sender of the message. So
+ if a machine is authorized to use sender addresses of more than a
+ single domain, the authentication scheme does not prevent that any
+ user on this machine can send with any of these domains. RMX is not
+ a substitute for the host security of the involved machines.
+
+ The proposed authentication scheme can be seen as a "half way
+ authentication": It does not track back an e-mail to the effective
+ sender. It tracks only half of the way, i. e. it tracks back to the
+ domain and it's DNS administrators who authorized that particular
+ sender IP address to use it for sending e-mail. How the party
+ responsible for that domain performs user authentication, whom it
+ grants access to, how it helds people responsible for abuse, is
+ completely left as the private business of those who are in charge
+ of that domain. So this draft does not interfere with the domain's
+ individual security policy or any legislation about such policies.
+ On the other hand, the proposed authentication scheme does not give
+ any statement about the nature and quality of the domain's security
+ policy. This is an essential feature of the proposal: E-mail
+ authentication must be deployed world wide, otherwise it won't do
+ the job. Any security scheme interfering with the local
+ legislations or the domain's security policy will not be accepted
+ and can't effectively deployed. Therefore, the security policy must
+ remain the domain's private business, no matter how lousy the
+ policy might be.
+
+ In order to achieve this and to make use of the only existing world
+ wide Internet directory scheme (DNS), the approach of this proposal
+ is to just ignore the local part of the sender address (i.e. what's
+ left of the @ part) and limit view to the domain part. After all,
+ that's what we do anyway when delivering to a given address with
+ SMTP.
+
+11.1.3. Vulnerability of DNS
+
+ DNS is an essential part of the proposed authentication scheme,
+ since it requires any directory service, and DNS is currently the
+ only one available. Unfortunately, DNS is vulnerable and can be
+ spoofed and poisoned. This flaw is commonly known and weakens many
+ network services, but for reasons beyond that draft DNS has not
+ been significantly improved yet. After the first version of this
+ draft, I received several comments who asked me not to use DNS
+ because of its lack of security. I took this into consideration,
+ but came to the conclusion that this is unfeasible: Any
+ authentication scheme linked to some kind of symbolic identity (in
+ this case the domain name) needs some kind of infrastructure and
+ trusted assignment. There are basically two ways to do it: Do it
+
+
+
+Hadmut Danisch Experimental [Page 23]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ yourself and trust nobody else, or let someone else do it. There
+ are methods to do it the former way, e.g. to give someone some kind
+ of authentication information after a first successful e-mail
+ exchange, e.g. some kind of cookie or special e-mail address. This
+ is certainly interesting and powerful, but it does not solve the
+ problem on a world wide scale and is far to complicated and error
+ prone for the average user, i. e. 99% of the users.
+
+ The latter method to let someone else do the symbolic name
+ assignment and create the authentication framework is well known.
+ It context of public key cryptography, this is called a Public Key
+ Infrastructure (PKI). On of the best known facts about PKIs is
+ that, until now, we don't have any covering a significant part of
+ the Internet. And we won't have any in near future. The complexity
+ is far too high, it is too expensive, and it involves cooperation
+ of every single user, which is simply unrealistic and extremely
+ error prone. So what do we have we can use? All we have is the DNS
+ and the Whois database. And we have countries who don't allow
+ cryptography. So the proposal was designed to use DNS without
+ cryptography. It does not avoid DNS because of its vulnerability,
+ it asks for a better DNS, but accepts the DNS as it is for the
+ moment. Currently there are two main threats caused by the DNS
+ weakness:
+
+ - A spammer/forger could spoof DNS in order to gain false
+ authorization to send fake e-mails.
+
+ - An attacker could spoof DNS in order to block delivery from
+ authorized machines, i. e. perform a Denial of Service attack.
+
+ The first one is rather unrealistic, because it would require an
+ average spammer to poison a significant part of the DNS servers of
+ its victims. A spammer sending messages to one million receipients
+ would need to poison at least 1-10% which is 10,000 to 100,000
+ receipient's DNS servers. This should be unfeasible in most cases.
+
+ In contrast, the second threat is a severe one. If an attacker
+ wanted to block messages from one company to another, he just needs
+ to poison the recipients DNS server with a wrong RMX record in
+ order to make the recipient's SMTP machine reject all messages. And
+ this is feasible since the attacker needs to poison only a single
+ DNS server. But does this make SMTP more vulnerable? No. Because
+ the attacker can already do even more without RMX. By poisoning the
+ sender's DNS server with wrong MX records, the attacker can also
+ block message delivery or even redirect the messages to the
+ attacker's machine, thus preventing any delivery error messages and
+ furthermore getting access to the messages.
+
+
+
+
+Hadmut Danisch Experimental [Page 24]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ As a consequence, e-mail delivery by SMTP requires a better DNS
+ anyway. The requirements are not significantly expanded by RMX.
+
+11.1.4. Sneaking RMX attack?
+
+ While writing a test implementation, a certain kind of attack came
+ into my mind. I'm still not sure, whether this attack is possible
+ on any DNS server, but I believe it should be mentioned:
+
+ Imagine an unauthorized sender is sending a forged mail (e.g.
+ spam). At connection time, before querying the RMX record, the
+ receiving MTA usually performs a PTR query for the IP address of
+ the sending MTA. If the sender has control over the authoritative
+ name server for that particular IP address, the sender could give a
+ normal PTR answer, but could append a wrong RMX, APL, or A record
+ in the additional section of the query. A subsequent RMX query
+ could receive wrong DNS data if the DNS server used by the
+ receiving MTA accepted those forged records.
+
+11.1.5. Open SMTP relays
+
+ Open SMTP relays (i.e. machines who accept any e-mail message from
+ anyone and deliver to the world) abused by spammers are a one of
+ the main problems of spam defense and sender backtracking. In most
+ cases this problem just vanishes because foreign open relay
+ machines will not be covered by the RMX records of the forged
+ sender address. But there are two special cases:
+
+ If the spammer knows about a domain which authorizes this
+ particular machine, that domain can be used for forgery. But in
+ this case, the IP address of the relay machine and the RMX records
+ of the domain track back to the persons responsible. Both can be
+ demanded to fix the relay or remove the RMX record for this
+ machine. An open relay is a security flaw like leaving the machine
+ open for everybody to login and send random mails from inside. Once
+ the administrative persons refuse to solve the problem, they can be
+ identified as spammers and held responsible.
+
+ The second special case is when a domain authorizes all IP
+ addresses by having the network 0.0.0.0/0 in the RMX/APL record. In
+ this case, open relays don't make things worse. It's up to the
+ recipient's MTA to reject mails from domains with loose security
+ policies.
+
+11.1.6. Unforged Spam
+
+ This proposal does not prevent spam (which is, by the way, not yet
+ exactly defined), it prevents forgery. Since spam is against law
+
+
+
+Hadmut Danisch Experimental [Page 25]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ and violates the recipients rights, spam depends on untracability
+ of the sender. In practice the sender forges the sender address
+ (other cases see below). This proposal is designed to detect such
+ forgeries.
+
+ However, the RMX approach is rendered ineffective, if the sender
+ doesn't forge. If the sender uses just a normal address of it's own
+ domain, this is just a plain, normal e-mail, which needs to be let
+ through. Since it is up to the human's taste whether this is spam
+ or not, there's no technical way to reliably identify this as spam.
+ But since the sender domain is known, this domain can be
+ blacklisted or legal steps can be gone into.
+
+11.1.7. Reliability of Whois Entries
+
+ Once the RMX infrastructure gets deployed, what's the security
+ gain? It allows to determine the domain which's DNS zone
+ authorized the sending machine. What's that good for? There are
+ some immediate uses of the domain name, e.g. in black- and
+ whitelisting. But in most cases this is just the starting point of
+ further investigations, either performed automatically before
+ message acceptance, or manually after spam has been received and
+ complainted about.
+
+ The next step after determining the domain is determining the
+ people responsible for this domain. This can sometimes be achieved
+ by querying the Whois databases. Unfortunately, many whois entries
+ are useless because they are incomplete, wrong, obsolete, or in
+ uncommon languages. Furthermore, there are several formats of
+ address informations which make it difficult to automatically
+ extract the address. Sometimes the whois entry identifies the
+ provider and not the owner of the domain. Whois servers are not
+ built for high availability and sometimes unreachable.
+
+ Therefore, a mandatory standard is required about the contents and
+ the format of whois entries, and the availability of the servers.
+ After receiving the MAIL FROM SMTP command with the sender envelope
+ address, the receiving MTA could check the RMX record and Whois
+ entry. If it doesn't point to a real human, the message could be
+ rejected and an error message like "Ask your provider to fix your
+ Whois entry" could be issued. Obviously, domain providers must be
+ held responsible for wrong entries. It might still be acceptable to
+ allow anonymous domains, i. e. domains which don't point to a
+ responsible human. But it is the receivers choice to accept e-mails
+ from such domains or not.
+
+11.1.8. Hazards for Freedom of Speech
+
+
+
+
+Hadmut Danisch Experimental [Page 26]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ Currently, some governments try to enforce limitations of internet
+ traffic in order to cut unwanted content providers from the
+ network. Some of these governments try to hide a whole country
+ behind firewalls, others try to force Internet providers to poison
+ DNS servers with wrong A records for web servers, e.g. one county
+ administration in Germany tries to do so. If message reception
+ depends on DNS entries, the same governments will try to block not
+ only HTTP, but SMTP also.
+
+ However, since most MTAs already reject messages from unresolvable
+ domain names this is not a new threat.
+
+11.2. General Considerations about spam defense
+
+ After discussing security requirements of the proposal, now the
+ security advantages of the RMX approach over content based filters
+ will be explained. Basically, there are three kinds of content
+ filters:
+
+ - Those who upload the message or some digest to an external
+ third party and ask "Is this spam"?
+
+ - Those who download a set of patterns and rules from a third
+ party and apply this set to incoming messages in order to
+ determine whether it is spam.
+
+ - Those who are independent and don't contact any third party,
+ but try to learn themselves what is spam and what isn't.
+
+
+ The message filters provided by some e-mail service providers are
+ usually not a kind of their own, but a combination of the first two
+ kinds.
+
+11.2.1. Action vs. reaction
+
+ Content filters suffer from a fundamental design problem: They are
+ late. They need to see some content of the same kind before in
+ order to learn and to block further distribution.
+
+ This works for viruses and worms, which redistribute. This doesn't
+ work for spam, since spam is usually not redistributed after the
+ first delivery. When the filters have learned or downloaded new
+ pattern sets, it's too late.
+
+ This proposal does not have this problem.
+
+11.2.2. Content based Denial of Service attacks
+
+
+
+Hadmut Danisch Experimental [Page 27]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ All three kinds of content filters, but especially the second and
+ the third kind are vulnerable to content based Denial of Service
+ attacks.
+
+ If some kind of third party (e.g. non-democratic government,
+ intellectual property warriors, religious groups, military, secret
+ services, patriots, public relation agents, etc.) wants certain
+ contents not to be distributed, they could either poison the
+ pattern/rule databases or feed wrong sets to particular receivers.
+
+ Such pattern/rule sets are the perfect tool for censoring e-mail
+ traffic and denial of service attacks by governments and other
+ parties, and a similar threat are virus filters. E. g. the content
+ industry could demand to teach all virus and spam filters to delete
+ all e-mails containing the URL of an MP3 web server outside the
+ legislations. Software manufacturers could try to block all e-mails
+ containing software license keys, thus trying to make unallowed
+ distribution more difficult. Governments could try to block
+ distribution of unwanted informations.
+
+ This proposal does not have this problem.
+
+
+12. Privacy Considerations
+
+ (It was proposed on the 56th IETF meeting to have a privacy section
+ in drafts and RFCs.)
+
+12.1. Draft specific considerations
+
+12.1.1. No content leaking
+
+ Since the RMX approach doesn't touch the contents of a message in
+ any way, there is obviously no way of leaking out any information
+ about the content of the message. RMX is based solely on the
+ envelope recipient address. However, methods to fix problems not
+ covered by RMX might allow content leaking, e.g. if the acceptance
+ of a message with an empty sender address requires the reference to
+ the message id of an e-mail recently sent, this allows an attacker
+ to verify whether a certain message was delivered from there.
+
+12.1.2. Message reception and sender domain
+
+ Message delivery triggers RMX and APL requests by the recipient.
+ Thus, the admin of the DNS server or an eavesdropper could learn
+ that the given machine has just received a message with a sender
+ from this address, even if the SMTP traffic itself had been
+ encrypted.
+
+
+
+Hadmut Danisch Experimental [Page 28]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ However, most of today's MTAs do query the MX and A records of the
+ domain after the MAIL FROM command, so this is not a real new
+ threat.
+
+12.1.3. Network structure
+
+ Since RMX and its associated APL records provide a complete list of
+ all IP addresses of hosts authorized to send messages from this
+ address, they do reveal informations about the network structure
+ and maybe the lifestyle of the domain owner, since a growing number
+ of domains are owned by single persons or families. E.g. the RMX
+ records could reveal where someone has his job or spends his time
+ at weekends.
+
+ If such informations are to be kept secret, it is the user's job to
+ not sent e-mails from there and to relay them from non-compromising
+ IP addresses.
+
+12.1.4. Owner information distribution
+
+ As described above, RMX depends partly on the reliability of the
+ whois database entries. It does not make anonymous domains
+ impossible, but it requires to keep the database entries "true", i.
+ e. if a whois entry does not contain informations about the
+ responsible person, this must be unambigously labeled as anonymous.
+ It must not contain fake names and addresses to pretend a non-
+ existing person. However, since most Internet users on the world
+ feel extremely annoyed by spam, they will urge their MTA admin to
+ reject messages from anonymous domains. The domain owner will have
+ the choice to either remain anonymous but be not able to send e-
+ mail to everyone in the world, or to be able but to reveal his
+ identity to everyone on the world.
+
+ It would be possible to provide whois-like services only to
+ recipients of recent messages, but this would make things too
+ complicated to be commonly adopted.
+
+12.2. General Considerations about spam defense
+
+12.2.1. Content leaking of content filters
+
+ As described above in the Security chapter, there are spam filters
+ which inherently allow leakage of the message body. Those filters
+ upload either the message body, or in most cases just some kind of
+ checksum to a third party, which replies whether this is to be seen
+ as spam or not. The idea is to keep a databases of all digests of
+ all messages. If a message is sent more often than some threshold,
+ it is to be considered as a mass mail and therefore tagged as spam.
+
+
+
+Hadmut Danisch Experimental [Page 29]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ While the digest itself does not reveal the content of the message,
+ it perfectly reveals where a particular message has been delivered
+ to. If a government finds just a single unwanted message, if a
+ software manufacturer finds a single message with a stolen product
+ license key, if someone finds a message with unpatriotic content,
+ it takes just a single database lookup to get a list of all people
+ who received this particular message. Content filters with digest
+ upload are the perfect "Big Brother".
+
+12.2.2. Black- and Whitelists
+
+ Some proposals against spam are based on a central database of
+ white- or blacklisted IP addresses, Sender names, Message IDs or
+ whatever. Again, there is a central database which learns who has
+ received which e-mail or from which sender with every query. This
+ allows tracking relations between persons, which is also a breach
+ of privacy.
+
+
+
+13. Deployment Considerations
+
+13.1. Compatibility
+
+13.1.1. Compatibility with old mail receivers
+
+ Since the suggested extension doesn't change the SMTP protocol at
+ all, it is fully compatible with old mail receivers. They simply
+ don't ask for the RMX records and don't perform the check.
+
+13.1.2. Compatibility with old mail senders
+
+ Since the SMTP protocol is unchanged and the SMTP sender is not
+ involved in the check, the method is fully compatible with old mail
+ senders.
+
+13.1.3. Compatibility with old DNS clients
+
+ Since the RMX is a new RR, the existing DNS protocol and zone
+ informations remain completely untouched.
+
+ If RMX is provided as a TXT record instead, it must be ensured that
+ no other software is misinterpreting this entry.
+
+13.1.4. Compatibility with old DNS servers
+
+ Full compatibility: If the server does not support RMX records, RMX
+ in TXT records can be used.
+
+
+
+Hadmut Danisch Experimental [Page 30]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+13.2. Enforcement policy
+
+ Obviously, for reasons of backward compatibility and smooth
+ introduction of this scheme, RMX records can't be required
+ immediately. Domains without RMX records must temporarily be
+ treated the same way as they are treated right now, i.e. e-mail
+ must be accepted from anywhere. But once the scheme becomes
+ sufficiently widespread, mail relays can start to refuse e-mails
+ with sender addresses from domains without RMX records, thus
+ forcing the owner of the domain to include a statement of
+ authorization into the domain's zone table. Domain owners will
+ still be free to have an RMX record with a network and mask
+ 0.0.0.0/0, i.e. to allow e-mails with that domain from everywhere.
+ On the other hand, mail receivers will be free to refuse mails from
+ domains without RMX records or RMX records which are too loose.
+ Advanced MTAs might have a configuration option to set the maximum
+ number of IP addresses authorized to use a domain. E-mails from a
+ domain, which's RMX records exceed this limit, would be rejected.
+ For example, a relay could reject e-mails from domains which
+ authorize more than 8 IP addresses. That allows to accept e-mails
+ only from domains with a reasonable security policy.
+
+
+
+14. General considerations about fighting spam
+
+ Is there a concise technical solution against spam? Yes.
+
+ Will it be deployed? Certainly not.
+
+ Why not? Because of the strong non-technical interests of several
+ parties against a solution to the problem, as described below.
+ Since these are non-technical reasons, they might be beyond the
+ scope of such a draft. But since they are the main problems that
+ prevent fighting spam, it is unavoidable to address them. This
+ chapter exists temporarily only and should support the discussion
+ of solutions. It is not supposed to be included in a later RFC.
+
+14.1. The economical problem
+
+ As has been recently illustrated in the initial session of the
+ IRTF's Anti Spam Research Group (ASRG) on the 56th IETF meeting,
+ sending spam is a business with significant revenues.
+
+ But a much bigger business is selling Anti-Spam software. This is a
+ billion dollar market, and it is rapidly growing. Any simple and
+ effective solution against spam would defeat revenues and drive
+ several companies into bankrupt, would make consultants jobless.
+
+
+
+Hadmut Danisch Experimental [Page 31]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ Therefore, spam is essential for the Anti-Spam business. If there
+ is no spam, then no Anti-Spam software can be sold, similar to the
+ Anti-Virus business. There are extremely strong efforts to keep
+ this market growing. Viruses, Worms, and now spam are just perfect
+ to keep this market alive: It is not sufficient to just buy a
+ software. Databases need to be updated continuously, thus making
+ the cash flow continuously. Have a single, simple, and permanent
+ solution to the problem and - boom - this billion dollar market is
+ dead.
+
+ That's one of the reasons why people are expected to live with
+ spam. They have to live with it to make them buy Anti-Spam
+ software. Content filters are perfect products to keep this market
+ alive.
+
+14.2. The POP problem
+
+ Another problem is the history of mail delivery. Once upon a time,
+ there used to be very few SMTP relays which handled the e-mail
+ traffic of all the world, and everybody was happy with that. Then
+ odd things like Personal Computers, which are sometimes switched
+ off, portable computers, dynamicly assigned IP addresses, IP access
+ from hotel rooms, etc. was invented, and people became unhappy,
+ because SMTP does not support delivery to such machines. To make
+ them happy again, the Post Office Protocol[4] was invented, which
+ turned the last part of message delivery from SMTP's push style
+ into a pull style, thus making virtually every computer on the
+ world with any random IP address a potential receiver of mails for
+ random domains. Unfortunately, only receiving e-mail was covered,
+ but sending e-mail was left to SMTP.
+
+ The result is that today we have only very few SMTP relays pointed
+ to by MX records, but an extreme number of hosts sending e-mail
+ with SMTP from any IP address with sender addresses from any
+ domain. Mail delivery has become very asymmetric. Insecurity,
+ especially forgeability, has become an essential part of mail
+ transport.
+
+ That problem could easily be fixed: Use protocols which allow
+ uploading of messages to be delivered. If a host doesn't receive
+ messages by SMTP, it shouldn't deliver by SMTP. Mail delivery
+ should go the same way back that incoming mail went in. This is
+ not a limitation to those people on the road who plug their
+ portable computer in any hotel room's phone plug and use any
+ provider. If there is a POP server granting download access from
+ anywhere, then the same server should be ready to accept uploading
+ of outgoing messages.
+
+
+
+
+Hadmut Danisch Experimental [Page 32]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ But as I saw from the comments on the first version of this draft,
+ people religiously insist on sending e-mail with their domain from
+ any computer with any IP address in the world, e.g. when visiting a
+ friend using her computer. It appears to be impossible to convince
+ people that stopping mail forgery requires every one of them to
+ give up forging.
+
+14.3. The network structure problem
+
+ A subsequent problem is that many organisations failed to implement
+ a proper mail delivery structure and heavily based their network on
+ this asymmetry. I received harsh comments from Universities who
+ were unable to give their network a good structure. While they do
+ have a central mail relay for incoming mail to the universities
+ domain, they developed a structure where every member of the
+ University randomly sends e-mails with that University's domain as
+ a sender address from home or everywhere in the world with any
+ dynamically assigned IP address from any provider. So this domain
+ is to be used from every possible IP address on earth, and they are
+ unable to operate any authentication scheme. Furthermore, they were
+ unable to understand that such a policy heavily supports spam and
+ that they have to expect that people don't accept such e-mails
+ anymore once they become blacklisted.
+
+ As long as organisations insist on having such policies, spammers
+ will have a perfect playground.
+
+14.4. The mentality problem
+
+ Another problem is the mentality of many internet users of certain
+ countries. I received harsh comments from people who strongly
+ insisted on the freedom to send any e-mail with any sender address
+ from anywhere, and who heavily refused any kind of authentication
+ step or any limitation, because they claimed that this would
+ infringe their constitutional "Freedom of speech". They are
+ undeviatingly convinced that "Freedom of speech" guarantees their
+ right to talk to everybody with any sender address, and that is has
+ to be kept the recipient's own problem to sort out what he doesn't
+ want to read - on the recipient's expense.
+
+ It requires a clear statement that the constitutional "Freedom of
+ Speech" does not cover molesting people with unsolicited e-mail
+ with forged sender address.
+
+14.5. The identity problem
+
+ How does one fight against mail forgery? With authentication. What
+ is authentication? In simple words: Making sure that the sender's
+
+
+
+Hadmut Danisch Experimental [Page 33]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+ real identity meets the recipients idea of who is the sender, based
+ on the sender address which came with the message.
+
+ What is identity? It is the main problem. Several countries have
+ different ideas of "identity", which turn out to be somehow
+ incompatible. In some countries people have identity cards and
+ never change their name and birthday. Identities are created by
+ human birth, not by identity changes. Other countries do not have
+ such a tight idea about identity. People's temporary identity is
+ based on nothing more than a driving license and a social security
+ number. With this background, it is virtually impossible to create
+ a trustworthy PKI covering all Internet users. I learned that it is
+ extremely difficult to convince some people to give up random e-
+ mail sending.
+
+14.6. The multi-legislation problem
+
+ Many proposals about fighting spam are feasible under certain
+ legislations only, and are inacceptable under some of the
+ legislations. But a world wide applicable method is required.
+ That's why the approach to ask everone on the world to sign
+ messages with cryptographic keys is not feasible.
+
+
+Implementation and further Information
+
+ Further informations and a test implementation are available at
+
+ http://www.danisch.de/work/security/antispam.html
+ http://www.danisch.de/software/rmx/
+
+
+ Additional informations and a technology overview are also
+ available at
+
+ http://www.mikerubel.org/computers/rmx_records/
+
+
+References
+
+
+
+1. S. Bradner, "Key words for use in RFCs to Indicate Requirement Lev-
+ els," RFC 2119 (March 1997).
+
+2. J. Klensin, "Simple Mail Transfer Protocol," RFC 2821 (April 2001).
+
+
+
+
+
+Hadmut Danisch Experimental [Page 34]
+
+INTERNET-DRAFT DNS RMX RR Oct 2003
+
+
+3. P. Mockapetris, "DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION,"
+ RFC 1035 (November 1987).
+
+4. J. Myers, M. Rose, "Post Office Protocol - Version 3," RFC 1939
+ (May 1996).
+
+
+Draft History
+
+ 00 Dec 2002
+ 01 Apr 2003
+ 02 Jun 2003
+ 03 Oct 2003
+
+Author's Address
+
+ Hadmut Danisch
+
+ Tennesseeallee 58
+ 76149 Karlsruhe
+ Germany
+
+ Phone: ++49-721-843004 or ++49-351-4850477
+ E-Mail: rfc@danisch.de
+
+Comments
+
+ Please send comments to rfc@danisch.de.
+
+Expiry
+
+ This drafts expires on Apr 1, 2004.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hadmut Danisch Experimental [Page 35]
+
diff --git a/doc/draft/draft-dnsext-opcode-discover-02.txt b/doc/draft/draft-dnsext-opcode-discover-02.txt
new file mode 100644
index 0000000..7b5e8cc
--- /dev/null
+++ b/doc/draft/draft-dnsext-opcode-discover-02.txt
@@ -0,0 +1,241 @@
+
+IETF DNSEXT WG Bill Manning
+draft-dnsext-opcode-discover-02.txt ep.net
+ Paul Vixie
+ ISC
+ 13 Oct 2003
+
+
+ The DISCOVER opcode
+
+This document is an Internet-Draft and is subject to all provisions of
+Section 10 of RFC2026.
+
+Comments may be submitted to the group mailing list at "mdns@zocalo.net"
+or the authors.
+
+Distribution of this memo is unlimited.
+
+Internet-Drafts are working documents of the Internet Engineering Task
+Force (IETF), its areas, and its working groups. Note that other groups
+may also distribute working documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months and
+may be updated, replaced, or obsoleted by other documents at any time. It
+is inappropriate to use Internet-Drafts as reference material or to cite
+them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+The capitalized keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+document are to be interpreted as described in RFC 2119
+
+0. Abstract:
+
+ The QUERY opcode in the DNS is designed for unicast. With the
+ development of multicast capabilities in the DNS, it is desireable
+ to have a more robust opcode for server interactions since a single
+ request may generate replies from multiple responders. So DISCOVER
+ is defined to deal with replies from multiple responders.
+
+ As such, this document extends the core DNS specifications to allow
+ clients to have a method for coping with replies from multiple
+ responders. Use of this new opcode may facilitate DNS operations in
+ modern networking topologies. A prototype of the DISCOVER opcode
+ was developed during the TBDS project (1999-2000), funded under DARPA
+ grant F30602-99-1-0523.
+
+1. Introduction:
+
+ This document describes an experimental extension to the DNS to receive
+ multiple responses which is the likely result when using DNS that has
+ enabled multicast queries. This approach was developed as part of the
+ TBDS research project, funded under DARPA grant F30602-99-1-0523. The
+ full processing rules used by TBDS are documented here for possible
+ incorporation in a future revision of the DNS specification."
+
+2. Method:
+
+ DISCOVER works like QUERY except:
+
+ 1. it can be sent to a broadcast or multicast destination. QUERY
+ isn't defined for non-unicast, and arguably shouldn't be.
+
+ 2. the Question section, if present, has <QNAME=zonename,QTYPE=SOA>
+ tuples. TBDS tried to augment this structure as follows:
+ <QNAME=service,QTYPE=SRV>. While this worked for our purposes in
+ TBDS, it is cleaner to place the SRV question in a separate pass.
+
+ 3. if QDCOUNT equals 0 then only servers willing to do recursion should
+ answer. Other servers must silently discard the DISCOVER request.
+
+ 4. if QDCOUNT is not equal to 0 then only servers who are authoritative
+ for the zones named by some QNAME should answer.
+
+ 5. responses may echo the request's Question section or leave it blank,
+ just like QUERY.
+
+ 6. responses have standard Answer, Authority, and Additional sections.
+ e.g. the response is the same as that to a QUERY. It is desireable
+ that zero content answers not be sent to avoid badly formed or
+ unfulfilled requests. Responses should be sent to the unicast
+ address of the requester and the source address should reflect
+ the unicast address of the responder.
+
+ Example usage for gethostby{name,addr}-style requestors:
+
+ Compute the zone name of the enclosing in-addr.arpa, ip6.int, or
+ ip6.arpa domain.
+
+ DISCOVER whether anyone in-scope is authoritative for this zone.
+
+ If so, query these authoritative servers for local
+ in-addr/ip6 names.
+
+ If not, DISCOVER whether there are recursive servers available.
+
+ If so, query these recursive servers for local
+ in-addr/ip6 names.
+
+ So, a node will issue a multicast request with the DISCOVER opcode at
+ some particular multicast scope. Then determine, from the replies,
+ whether there are any DNS servers which are authoritative (or support
+ recursion) for the zone. Replies to DISCOVER requests MUST set the
+ Recursion Available (RA) flag in the DNS message header.
+
+ It is important to recognize that a requester must be prepared to
+ receive multiple replies from multiple responders. We expect that
+ there will be a single response per responder.
+
+ Once one learns a host's FQDN by the above means, repeat the process
+ for discovering the closest enclosing authoritative server of such
+ local name.
+
+ Cache all NS and A data learned in this process, respecting TTL's.
+
+ TBDS usage for SRV requestors:
+
+ Do the gethostbyaddr() and gethostbyname() on one's own link-local
+ address, using the above process.
+
+ Assume that the closest enclosing zone for which an authority server
+ answers an in-scope DISCOVER packet is "this host's parent domain".
+
+ Compute the SRV name as _service._transport.*.parentdomain.
+
+ This is a change to the definition as defined in RFC 1034.
+ A wildcard label ("*") in the QNAME used in a DNS message with
+ opcode DISCOVER SHOULD be evaluated with special rules. The
+ wildcard matches any label for which the DNS server data is
+ authoritative. For example 'x.*.example.com.' would match
+ 'x.y.example.com.' and 'x.yy.example.com.' provided that the
+ server was authoritative for 'example.com.' In this particular
+ case, we suggest the follwing considerations be made:
+
+ getservbyname() can be satisfied by issuing a request with
+ this computed SRV name. This structure can be
+ populated by values returned from a request as follows:
+
+ s_name The name of the service, "_service" without the
+ preceding underscore.
+ s_aliases The names returned in the SRV RRs in replies
+ to the query.
+ s_port The port number in the SRV RRs replies to the
+ query. If these port numbers disagree - one
+ of the port numbers is chosen, and only those
+ names which correspond are returned.
+ s_proto The transport protocol from named by the
+ "_transport" label, without the preceding
+ underscore.
+
+ Send SRV query for this name to discovered local authoritative servers.
+
+ Usage for disconnected networks with no authoritative servers:
+
+ Hosts should run a "stub server" which acts as though its FQDN is a
+ zone name. Computed SOA gives the host's FQDN as MNAME, "." as the
+ ANAME, seconds-since-1Jan2000 as the SERIAL, low constants for EXPIRE
+ and the other timers. Compute NS as the host's FQDN. Compute the
+ glue as the host's link-local address. Or Hosts may run a
+ "DNS stub server" which acts as though its FQDN is a zone name. The
+ rules governing the behavior of this stub server are given elsewhere
+ [1] [2].
+
+ Such stub servers should answer DISCOVER packets for its zone, and
+ will be found by the iterative "discover closest enclosing authority
+ server" by DISCOVER clients, either in the gethostbyname() or SRV
+ cases described above. Note that stub servers only answer with
+ zone names which exactly match QNAME's, not with zone names which
+ are owned by QNAME's.
+
+ The main deviation from the DNS[3][4] model is that a host (like, say, a
+ printer offering LPD services) has a DNS server which answers authoritatively
+ for something which hasn't been delegated to it. However, the only way that
+ such DNS servers can be discovered is with a new opcode, DISCOVER, which
+ is explicitly defined to discover undelegated zones for tightly scoped
+ purposes. Therefore this isn't officially a violation of DNS's coherency
+ principles. In some cases a responder to DISCOVER may not be traditional
+ DNS software, it could be special purpose software.
+
+3. IANA Considerations
+
+ As a new opcode, the IANA will need to assign a numeric value
+ for the memnonic. The last OPCODE assigned was "5", for UPDATE.
+ Test implementations have used OPCODE "6".
+
+4. Security Considerations
+
+ No new security considerations are known to be introduced with any new
+ opcode, however using multicast for service discovery has the potential
+ for denial of service, primarly from flooding attacks. It may also be
+ possible to enable deliberate misconfiguration of clients simply by
+ running a malicious DNS resolver that claims to be authoritative for
+ things that it is not. One possible way to mitigate this effect is by
+ use of credentials, such as CERT resource records within an RR set.
+ The TBDS project took this approach.
+
+5. Attribution:
+
+ This material was generated in discussions on the mdns mailing list
+hosted by Zocalo in March 2000. Updated by discussion in September/October
+2003. David Lawrence, Scott Rose, Stuart Cheshire, Bill Woodcock,
+Erik Guttman, Bill Manning and Paul Vixie were active contributors.
+
+6. Author's Address
+
+ Bill Manning
+ PO 12317
+ Marina del Rey, CA. 90295
+ +1.310.322.8102
+ bmanning@karoshi.com
+
+ Paul Vixie
+ Internet Software Consortium
+ 950 Charter Street
+ Redwood City, CA 94063
+ +1 650 779 7001
+ <vixie@isc.org>
+
+7. References
+
+Informational References:
+
+[1] Esibov, L., Aboba, B., Thaler, D., "Multicast DNS",
+ draft-ietf-dnsext-mdns-00.txt, November 2000. Expired
+
+[2] Woodcock, B., Manning, B., "Multicast Domain Name Service",
+ draft-manning-dnsext-mdns-00.txt, August 2000. Expired.
+
+Normative References:
+[3] Mockapetris, P., "DOMAIN NAMES - CONCEPTS AND FACILITIES",
+ RFC 1034, November 1987.
+[4] Mockapetris, P., "DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION",
+ RFC 1035, November 1987
+
+ ----------------------------EOL-----------------------
+
diff --git a/doc/draft/draft-durand-dnsop-dynreverse-00.txt b/doc/draft/draft-durand-dnsop-dynreverse-00.txt
new file mode 100644
index 0000000..224e7ad
--- /dev/null
+++ b/doc/draft/draft-durand-dnsop-dynreverse-00.txt
@@ -0,0 +1,240 @@
+Internet Engineering Task Force Alain Durand
+INTERNET-DRAFT SUN Microsystems
+Feb 21, 2003
+Expires Aug 2, 2003
+
+
+
+ Dynamic reverse DNS for IPv6
+ <draft-durand-dnsop-dynreverse-00.txt>
+
+
+
+Status of this memo
+
+
+ This memo provides information to the Internet community. It does
+ not specify an Internet standard of any kind. This memo is in full
+ conformance with all provisions of Section 10 of RFC2026 [RFC2026].
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+
+
+Abstract
+
+ This document describes a method to dynamically generate PTR records
+ and corresponding A or AAAA records when the reverse path DNS tree is
+ not populated.
+
+ A special domain dynrev.arpa. is reserved for that purpose.
+
+
+1. Introduction
+
+ In IPv4, the reverse path tree of the DNS under in-addr.arpa.
+ although not perfectly maintained, is still mostly usable and its
+ existence is important for a number of applications that relies on
+ its existence and decent status. Some applications performs some
+ (very) weak security checks based on it. Mail relays relies on it for
+ some anti-spams checks an some FTP server will not let you in unless
+ your IP address resolve properly with a PTR record.
+
+ IPv6 addresses being much longer (and cumbersome) than IPv4
+ addresses, it is to fear that the reverse path tree under ip6.arpa.
+ would not be as well maintained. Also, tools like 6to4, Isatap and
+ others have made creative use of the 128 bits of an IPv6 address to
+ automatically embed an IPv4 address to enable seamless connection to
+ the IPv6 Internet. However, no provision has been made to make sure
+ the reverse path tree gets automatically updated as well for those
+ new IPv6 addresses. One step furter, RFC3041 describes a mechanism
+ to basically use random bits in the bottom part of an IPv6 address to
+ preserver anonymity. If those addresses are to resolve in the reverse
+ path tree, it obviously has to be with anonymous data as well.
+ Another point to note is that home customer ISPs in IPv4 have a
+ current practice to pre-populate the reverse path tree with names
+ automatically derived from the IP addresses. This practice is no
+ longer possible in IPv6, where IP address allocation is not dense as
+ it is the case in IPv4. The mere size of typical customer allocation
+ (2^48 according to the recommendation of RFC3177) makes it
+ impossible.
+
+ Applications that check the existence of PTR records usually follow
+ this by checking if the name pointed by the PTR resolve in a A (or
+ AAAA for IPv6) that match the original IP address. Thus the forward
+ path tree must also include the corresponding data.
+
+ One simple approach of this problem is to simply declare the usage of
+ the reverse path DNS as described above obsolete. The author believe
+ this is too strong an approach for now.
+
+ Similarly, a completely different approach would be to deprecate the
+ usage of DNS for the reverse tree altogether and replace it by
+ something inspired from ICMP name-info messages. The author believes
+ that this approached is an important departure from the current
+ practise and thus not very realistic. Also, there are some concerns
+ about the the security implications of this method as any node could
+ easily impersonate any name. This approach would fundamentally change
+ the underlying assumption of "I trust what has been put in the DNS by
+ the local administrators" to "I trust what has been configured on
+ each machine I query directly".
+
+
+
+2. Dynamic record generation
+
+ If static pre-population of the tree is not possible anymore and data
+ still need to be returned to applications using getnameinfo(), the
+ alternative is dynamic record generation. This can be done is two
+ places: in the DNS servers responsible for the allocated space (/64
+ or /48) in the ip6.arpa. domain. or in the DNS resolvers (either the
+ sub resolver library or the recursive DNS server).
+
+ 2.1. On the resolver side.
+
+ The resolver, either in the recursive DNS server or in the stub
+ library could theoretically generate this data.
+
+ In case DNSsec is in place, the recursive DNS server would have to
+ pretend these records are authentic.
+
+ If the synthesis is done in the stub-resolver library, no record
+ needs to be actually generated, only the right information needs to
+ be passed to getnameinfo() and getaddrinfo(). If the synthesis is
+ done in the recursive DNS server, no modification is required to
+ existing stub resolvers.
+
+
+2.2. On the server side.
+
+ PTR records could be generated automatically by the server
+ responsible for the reverse path tree of an IPv6 prefix (a /64 or /48
+ prefixes or basically anything in between) when static data is not
+ available.
+
+ There could be impact on DNSsec as the zone or some parts of the zone
+ may need to be resigned each time a DNS query is made for an
+ unpopulated address. This can be seen as a DOS attack on a DNSsec
+ zone, so server side synthesis is not recommended if DNSsec is
+ deployed.
+
+
+
+3. Synthesis
+
+ The algorithm is simple: Do the normal queries. If the query returns
+ No such domain, replace this answer by the synthetized one if
+ possible.
+
+3.1. PTR synthesis
+
+ The synthetized PTR for a DNS string [X] is simply [X].dynrev.arpa.
+ where [X] is any valid DNS name.
+
+ The fact that the synthetized PTR points to the dynrev.arpa. domain
+ is an indication to the applications that this record has been
+ dynamically generated.
+
+
+3.2. A synthesis
+
+ If [X] is in the form a.b.c.d.in-addr.arpa, one can synthetized an A
+ record for the string [X].dynrev.arpa. which value is d.c.b.a. with
+ a,b,c & d being integer [0..255]
+
+
+3.3. AAAA synthesis
+
+ If [X] is in the form
+ a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.s.t.u.v.w.x.y.z.A.B.C.D.E.F.in-
+ addr.arpa, one can synthetized a AAAA record for the string
+ [X].dynrev.arpa. which value is
+ FEDC:BAzy:xwvu:tsrq:ponm:lkji:hgfe:dcba with
+ a,b,c....x,y,z,A,B,C,D,E,F being hexadecimal digits.
+
+
+3.4. Server side synthesis
+
+ If synthesis is done on the server side, PTR could be set not to use
+ the dynrev.arpa domain but the local domain name instead. It culd be
+ for instance dynrev.mydomain.com.
+
+ Note also that server side synthesis is not incompatible with
+ resolver side synthesis.
+
+
+
+4. IANA considerations
+
+ The dynrev.arpa. domain is reserved for the purpose of this document.
+
+
+
+5. Security considerations
+
+ Section 2. discusses the the interactions with DNSsec.
+
+
+
+6. Authors addresses
+
+ Alain Durand
+ SUN Microsystems, Inc
+ 17, Network Circle
+ UMPK17-202
+ Menlo Park, CA 94025
+ USA
+ Mail: Alain.Durand@sun.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/draft/draft-ietf-dnsext-2929bis-01.txt b/doc/draft/draft-ietf-dnsext-2929bis-01.txt
new file mode 100644
index 0000000..fa41e76
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-2929bis-01.txt
@@ -0,0 +1,928 @@
+
+INTERNET-DRAFT Donald E. Eastlake 3rd
+Obsoletes RFC 2929, Updates RFC 1183 Motorola Laboratories
+Expires: February 2006 August 2005
+
+
+
+ Domain Name System (DNS) IANA Considerations
+ ------ ---- ------ ----- ---- --------------
+ <draft-ietf-dnsext-2929bis-01.txt>
+
+
+
+Status of This Document
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Distribution of this draft is unlimited. It is intended to become
+ the new BCP 42 obsoleting RFC 2929. Comments should be sent to the
+ DNS Working Group mailing list <namedroppers@ops.ietf.org>.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than a "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+
+
+Abstract
+
+ Internet Assigned Number Authority (IANA) parameter assignment
+ considerations are given for the allocation of Domain Name System
+ (DNS) classes, RR types, operation codes, error codes, RR header
+ bits, and AFSDB subtypes.
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 1]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+Table of Contents
+
+ Status of This Document....................................1
+ Abstract...................................................1
+
+ Table of Contents..........................................2
+
+ 1. Introduction............................................3
+ 2. DNS Query/Response Headers..............................3
+ 2.1 One Spare Bit?.........................................4
+ 2.2 Opcode Assignment......................................4
+ 2.3 RCODE Assignment.......................................5
+ 3. DNS Resource Records....................................6
+ 3.1 RR TYPE IANA Considerations............................7
+ 3.1.1 DNS TYPE Allocation Policy...........................8
+ 3.1.2 Special Note on the OPT RR...........................9
+ 3.1.3 The AFSDB RR Subtype Field...........................9
+ 3.2 RR CLASS IANA Considerations...........................9
+ 3.3 RR NAME Considerations................................11
+ 4. Security Considerations................................11
+
+ Appendix: Changes from RFC 2929...........................12
+
+ Copyright and Disclaimer..................................13
+ Normative References......................................13
+ Informative References....................................14
+
+ Authors Addresses.........................................16
+ Expiration and File Name..................................16
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 2]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+1. Introduction
+
+ The Domain Name System (DNS) provides replicated distributed secure
+ hierarchical databases which hierarchically store "resource records"
+ (RRs) under domain names. DNS data is structured into CLASSes and
+ zones which can be independently maintained. See [RFC 1034, 1035,
+ 2136, 2181, 4033] familiarity with which is assumed.
+
+ This document provides, either directly or by reference, general IANA
+ parameter assignment considerations applying across DNS query and
+ response headers and all RRs. There may be additional IANA
+ considerations that apply to only a particular RR type or
+ query/response opcode. See the specific RFC defining that RR type or
+ query/response opcode for such considerations if they have been
+ defined, except for AFSDB RR considerations [RFC 1183] which are
+ included herein. This RFC obsoletes [RFC 2929].
+
+ IANA currently maintains a web page of DNS parameters. See
+ <http://www.iana.org/numbers.htm>.
+
+ "IETF Standards Action", "IETF Consensus", "Specification Required",
+ and "Private Use" are as defined in [RFC 2434].
+
+
+
+2. DNS Query/Response Headers
+
+ The header for DNS queries and responses contains field/bits in the
+ following diagram taken from [RFC 2136, 2929]:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ID |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QDCOUNT/ZOCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ANCOUNT/PRCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | NSCOUNT/UPCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ARCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ The ID field identifies the query and is echoed in the response so
+ they can be matched.
+
+ The QR bit indicates whether the header is for a query or a response.
+
+
+D. Eastlake 3rd [Page 3]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+ The AA, TC, RD, RA, AD, and CD bits are each theoretically meaningful
+ only in queries or only in responses, depending on the bit. However,
+ many DNS implementations copy the query header as the initial value
+ of the response header without clearing bits. Thus any attempt to
+ use a "query" bit with a different meaning in a response or to define
+ a query meaning for a "response" bit is dangerous given existing
+ implementation. Such meanings may only be assigned by an IETF
+ Standards Action.
+
+ The unsigned fields query count (QDCOUNT), answer count (ANCOUNT),
+ authority count (NSCOUNT), and additional information count (ARCOUNT)
+ express the number of records in each section for all opcodes except
+ Update. These fields have the same structure and data type for
+ Update but are instead the counts for the zone (ZOCOUNT),
+ prerequisite (PRCOUNT), update (UPCOUNT), and additional information
+ (ARCOUNT) sections.
+
+
+
+2.1 One Spare Bit?
+
+ There have been ancient DNS implementations for which the Z bit being
+ on in a query meant that only a response from the primary server for
+ a zone is acceptable. It is believed that current DNS
+ implementations ignore this bit.
+
+ Assigning a meaning to the Z bit requires an IETF Standards Action.
+
+
+
+2.2 Opcode Assignment
+
+ Currently DNS OpCodes are assigned as follows:
+
+ OpCode Name Reference
+
+ 0 Query [RFC 1035]
+ 1 IQuery (Inverse Query, Obsolete) [RFC 3425]
+ 2 Status [RFC 1035]
+ 3 available for assignment
+ 4 Notify [RFC 1996]
+ 5 Update [RFC 2136]
+ 6-15 available for assignment
+
+ New OpCode assignments require an IETF Standards Action as modified
+ by [RFC 4020].
+
+
+
+
+
+
+D. Eastlake 3rd [Page 4]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+2.3 RCODE Assignment
+
+ It would appear from the DNS header above that only four bits of
+ RCODE, or response/error code are available. However, RCODEs can
+ appear not only at the top level of a DNS response but also inside
+ OPT RRs [RFC 2671], TSIG RRs [RFC 2845], and TKEY RRs [RFC 2930].
+ The OPT RR provides an eight bit extension resulting in a 12 bit
+ RCODE field and the TSIG and TKEY RRs have a 16 bit RCODE field.
+
+ Error codes appearing in the DNS header and in these three RR types
+ all refer to the same error code space with the single exception of
+ error code 16 which has a different meaning in the OPT RR from its
+ meaning in other contexts. See table below.
+
+ RCODE Name Description Reference
+ Decimal
+ Hexadecimal
+ 0 NoError No Error [RFC 1035]
+ 1 FormErr Format Error [RFC 1035]
+ 2 ServFail Server Failure [RFC 1035]
+ 3 NXDomain Non-Existent Domain [RFC 1035]
+ 4 NotImp Not Implemented [RFC 1035]
+ 5 Refused Query Refused [RFC 1035]
+ 6 YXDomain Name Exists when it should not [RFC 2136]
+ 7 YXRRSet RR Set Exists when it should not [RFC 2136]
+ 8 NXRRSet RR Set that should exist does not [RFC 2136]
+ 9 NotAuth Server Not Authoritative for zone [RFC 2136]
+ 10 NotZone Name not contained in zone [RFC 2136]
+ 11 - 15 Available for assignment
+ 16 BADVERS Bad OPT Version [RFC 2671]
+ 16 BADSIG TSIG Signature Failure [RFC 2845]
+ 17 BADKEY Key not recognized [RFC 2845]
+ 18 BADTIME Signature out of time window [RFC 2845]
+ 19 BADMODE Bad TKEY Mode [RPC 2930]
+ 20 BADNAME Duplicate key name [RPF 2930]
+ 21 BADALG Algorithm not supported [RPF 2930]
+
+ 22 - 3,840
+ 0x0016 - 0x0F00 Available for assignment
+
+ 3,841 - 4,095
+ 0x0F01 - 0x0FFF Private Use
+
+ 4,096 - 65,534
+ 0x1000 - 0xFFFE Available for assignment
+
+ 65,535
+ 0xFFFF Reserved, can only be allocated by an IETF
+ Standards Action.
+
+
+
+D. Eastlake 3rd [Page 5]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+ Since it is important that RCODEs be understood for interoperability,
+ assignment of new RCODE listed above as "available for assignment"
+ requires an IETF Consensus.
+
+
+
+3. DNS Resource Records
+
+ All RRs have the same top level format shown in the figure below
+ taken from [RFC 1035]:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / /
+ / NAME /
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | CLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TTL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RDLENGTH |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+ / RDATA /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ NAME is an owner name, i.e., the name of the node to which this
+ resource record pertains. NAMEs are specific to a CLASS as described
+ in section 3.2. NAMEs consist of an ordered sequence of one or more
+ labels each of which has a label type [RFC 1035, 2671].
+
+ TYPE is a two octet unsigned integer containing one of the RR TYPE
+ codes. See section 3.1.
+
+ CLASS is a two octet unsigned integer containing one of the RR CLASS
+ codes. See section 3.2.
+
+ TTL is a four octet (32 bit) bit unsigned integer that specifies the
+ number of seconds that the resource record may be cached before the
+ source of the information should again be consulted. Zero is
+ interpreted to mean that the RR can only be used for the transaction
+ in progress.
+
+ RDLENGTH is an unsigned 16 bit integer that specifies the length in
+
+
+D. Eastlake 3rd [Page 6]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+ octets of the RDATA field.
+
+ RDATA is a variable length string of octets that constitutes the
+ resource. The format of this information varies according to the TYPE
+ and in some cases the CLASS of the resource record.
+
+
+
+3.1 RR TYPE IANA Considerations
+
+ There are three subcategories of RR TYPE numbers: data TYPEs, QTYPEs,
+ and MetaTYPEs.
+
+ Data TYPEs are the primary means of storing data. QTYPES can only be
+ used in queries. Meta-TYPEs designate transient data associated with
+ an particular DNS message and in some cases can also be used in
+ queries. Thus far, data TYPEs have been assigned from 1 upwards plus
+ the block from 100 through 103 while Q and Meta Types have been
+ assigned from 255 downwards except for the OPT Meta-RR which is
+ assigned TYPE 41. There have been DNS implementations which made
+ caching decisions based on the top bit of the bottom byte of the RR
+ TYPE.
+
+ There are currently three Meta-TYPEs assigned: OPT [RFC 2671], TSIG
+ [RFC 2845], and TKEY [RFC 2930].
+
+ There are currently five QTYPEs assigned: * (all), MAILA, MAILB,
+ AXFR, and IXFR.
+
+ Considerations for the allocation of new RR TYPEs are as follows:
+
+ Decimal
+ Hexadecimal
+
+ 0
+ 0x0000 - TYPE zero is used as a special indicator for the SIG RR [RFC
+ 2535] and in other circumstances and must never be allocated
+ for ordinary use.
+
+ 1 - 127
+ 0x0001 - 0x007F - remaining TYPEs in this range are assigned for data
+ TYPEs by the DNS TYPE Allocation Policy as specified in
+ section 3.1.1.
+
+ 128 - 255
+ 0x0080 - 0x00FF - remaining TYPEs in this rage are assigned for Q and
+ Meta TYPEs by the DNS TYPE Allocation Policy as specified in
+ section 3.1.1.
+
+
+
+
+D. Eastlake 3rd [Page 7]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+ 256 - 32,767
+ 0x0100 - 0x7FFF - assigned for data, Q, or Meta TYPE use by the DNS
+ TYPE Allocation Policy as specified in section 3.1.1.
+
+ 32,768 - 65,279
+ 0x8000 - 0xFEFF - Specification Required as defined in [RFC 2434].
+
+ 65,280 - 65534
+ 0xFF00 - 0xFFFE - Private Use.
+
+ 65,535
+ 0xFFFF - Reserved, can only be assigned by an IETF Standards Action.
+
+
+
+3.1.1 DNS TYPE Allocation Policy
+
+ Parameter values specified above as assigned based on DNS TYPE
+ Allocation Policy. That is, Expert Review with the additional
+ requirement that the review be based on a complete template as
+ specified below which has been posted for three weeks to the
+ namedroppers@ops.ietf.org mailing list.
+
+ Partial or draft templates may be posted with the intend of
+ soliciting feedback.
+
+
+ DNS RR TYPE PARAMETER ALLOCATION TEMPLATE
+
+ Date:
+
+ Name and email of originator:
+
+ Pointer to internet-draft or other document giving a detailed
+ description of the protocol use of the new RR Type:
+
+ What need is the new RR TYPE intended to fix?
+
+ What existing RR TYPE(s) come closest to filling that need and why are
+ they unsatisfactory?
+
+ Does the proposed RR TYPR require special handling within the DNS
+ different from an Unknown RR TYPE?
+
+ Comments:
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 8]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+3.1.2 Special Note on the OPT RR
+
+ The OPT (OPTion) RR, number 41, is specified in [RFC 2671]. Its
+ primary purpose is to extend the effective field size of various DNS
+ fields including RCODE, label type, OpCode, flag bits, and RDATA
+ size. In particular, for resolvers and servers that recognize it, it
+ extends the RCODE field from 4 to 12 bits.
+
+
+
+3.1.3 The AFSDB RR Subtype Field
+
+ The AFSDB RR [RFC 1183] is a CLASS insensitive RR that has the same
+ RDATA field structure as the MX RR but the 16 bit unsigned integer
+ field at the beginning of the RDATA is interpreted as a subtype as
+ follows:
+
+ Decimal
+ Hexadecimal
+
+ 0
+ 0x0000 - Allocation requires IETF Standards Action.
+
+ 1
+ 0x0001 - Andrews File Service v3.0 Location Service [RFC 1183].
+
+ 2
+ 0x0002 - DCE/NCA root cell directory node [RFC 1183].
+
+ 3 - 65,279
+ 0x0003 - 0xFEFF - Allocation by IETF Consensus.
+
+ 65,280 - 65,534
+ 0xFF00 - 0xFFFE - Private Use.
+
+ 65,535
+ 0xFFFF - Reserved, allocation requires IETF Standards Action.
+
+
+
+3.2 RR CLASS IANA Considerations
+
+ DNS CLASSes have been little used but constitute another dimension of
+ the DNS distributed database. In particular, there is no necessary
+ relationship between the name space or root servers for one CLASS and
+ those for another CLASS. The same name can have completely different
+ meanings in different CLASSes; however, the label types are the same
+ and the null label is usable only as root in every CLASS. However,
+ as global networking and DNS have evolved, the IN, or Internet, CLASS
+ has dominated DNS use.
+
+
+D. Eastlake 3rd [Page 9]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+ There are two subcategories of DNS CLASSes: normal data containing
+ classes and QCLASSes that are only meaningful in queries or updates.
+
+ The current CLASS assignments and considerations for future
+ assignments are as follows:
+
+ Decimal
+ Hexadecimal
+
+ 0
+ 0x0000 - Reserved, assignment requires an IETF Standards Action.
+
+ 1
+ 0x0001 - Internet (IN).
+
+ 2
+ 0x0002 - Available for assignment by IETF Consensus as a data CLASS.
+
+ 3
+ 0x0003 - Chaos (CH) [Moon 1981].
+
+ 4
+ 0x0004 - Hesiod (HS) [Dyer 1987].
+
+ 5 - 127
+ 0x0005 - 0x007F - available for assignment by IETF Consensus for data
+ CLASSes only.
+
+ 128 - 253
+ 0x0080 - 0x00FD - available for assignment by IETF Consensus for
+ QCLASSes only.
+
+ 254
+ 0x00FE - QCLASS None [RFC 2136].
+
+ 255
+ 0x00FF - QCLASS Any [RFC 1035].
+
+ 256 - 32,767
+ 0x0100 - 0x7FFF - Assigned by IETF Consensus.
+
+ 32,768 - 65,279
+ 0x8000 - 0xFEFF - Assigned based on Specification Required as defined
+ in [RFC 2434].
+
+ 65,280 - 65,534
+ 0xFF00 - 0xFFFE - Private Use.
+
+ 65,535
+ 0xFFFF - Reserved, can only be assigned by an IETF Standards Action.
+
+
+D. Eastlake 3rd [Page 10]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+3.3 RR NAME Considerations
+
+ DNS NAMEs are sequences of labels [RFC 1035]. The last label in each
+ NAME is "ROOT" which is the zero length label. By definition, the
+ null or ROOT label can not be used for any other NAME purpose.
+
+ At the present time, there are two categories of label types, data
+ labels and compression labels. Compression labels are pointers to
+ data labels elsewhere within an RR or DNS message and are intended to
+ shorten the wire encoding of NAMEs. The two existing data label
+ types are sometimes referred to as Text and Binary. Text labels can,
+ in fact, include any octet value including zero value octets but most
+ current uses involve only [US-ASCII]. For retrieval, Text labels are
+ defined to treat ASCII upper and lower case letter codes as matching
+ [insensitive]. Binary labels are bit sequences [RFC 2673]. The
+ Binary label type is Experimental [RFC 3363].
+
+ IANA considerations for label types are given in [RFC 2671].
+
+ NAMEs are local to a CLASS. The Hesiod [Dyer 1987] and Chaos [Moon
+ 1981] CLASSes are essentially for local use. The IN or Internet
+ CLASS is thus the only DNS CLASS in global use on the Internet at
+ this time.
+
+ A somewhat out-of-date description of name allocation in the IN Class
+ is given in [RFC 1591]. Some information on reserved top level
+ domain names is in BCP 32 [RFC 2606].
+
+
+
+4. Security Considerations
+
+ This document addresses IANA considerations in the allocation of
+ general DNS parameters, not security. See [RFC 4033, 4034, 4035] for
+ secure DNS considerations.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 11]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+Appendix: Changes from RFC 2929
+
+ RFC Editor: This Appendix should be deleted for publication.
+
+ Changes from RFC 2929 to this draft:
+
+ 1. Changed many "IETF Consensus" for RR TYPEs to be "DNS TYPE
+ Allocation Policy" and add the specification of that policy. Change
+ some remaining "IETF Standards Action" allocation requirements to say
+ "as modified by [RFC 4020]".
+
+ 2. Updated various RFC references.
+
+ 3. Mentioned that the Binary label type is now Experimental and
+ IQuery is Obsolete.
+
+ 4. Changed allocation status of RR Type 0xFFFF and RCODE 0xFFFF to be
+ IETF Standards Action required.
+
+ 5. Add an IANA allocation policy for the AFSDB RR Subtype field.
+
+ 6. Addition of reference to case insensitive draft.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 12]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+Copyright and Disclaimer
+
+ Copyright (C) The Internet Society (2005). This document is subject to
+ the rights, licenses and restrictions contained in BCP 78, and except
+ as set forth therein, the authors retain all their rights.
+
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+Normative References
+
+ [RFC 1034] - Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC 1035] - Mockapetris, P., "Domain Names - Implementation and
+ Specifications", STD 13, RFC 1035, November 1987.
+
+ [RFC 1183] - Everhart, C., Mamakos, L., Ullmann, R., and P.
+ Mockapetris, "New DNS RR Definitions", RFC 1183, October 1990.
+
+ [RFC 1996] - Vixie, P., "A Mechanism for Prompt Notification of Zone
+ Changes (DNS NOTIFY)", RFC 1996, August 1996.
+
+ [RFC 2136] - Vixie, P., Thomson, S., Rekhter, Y. and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)", RFC 2136,
+ April 1997.
+
+ [RFC 2181] - Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC 2434] - Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434, October 1998.
+
+ [RFC 2671] - Vixie, P., "Extension mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [RFC 2673] - Crawford, M., "Binary Labels in the Domain Name System",
+ RFC 2673, August 1999.
+
+ [RFC 2845] - Vixie, P., Gudmundsson, O., Eastlake, D. and B.
+ Wellington, "Secret Key Transaction Authentication for DNS (TSIG)",
+ RFC 2845, May 2000.
+
+
+D. Eastlake 3rd [Page 13]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+ [RFC 2930] - Eastlake, D., "Secret Key Establishment for DNS (TKEY
+ RR)", September 2000.
+
+ [RFC 3363] - Bush, R., Durand, A., Fink, B., Gudmundsson, O., and T.
+ Hain, "Representing Internet Protocol version 6 (IPv6) Addresses in
+ the Domain Name System (DNS)", RFC 3363, August 2002.
+
+ [RFC 3425] - Lawrence, D., "Obsoleting IQUERY", RFC 3425, November
+ 2002.
+
+ [RFC 4020] - Kompella, K. and A. Zinin, "Early IANA Allocation of
+ Standards Track Code Points", BCP 100, RFC 4020, February 2005.
+
+ [RFC 4033] - Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements", RFC 4033, March
+ 2005.
+
+ [RFC 4034] - Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+ [RFC 4044] - Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security Extensions", RFC
+ 4035, March 2005.
+
+ [US-ASCII] - ANSI, "USA Standard Code for Information Interchange",
+ X3.4, American National Standards Institute: New York, 1968.
+
+
+
+Informative References
+
+ [Dyer 1987] - Dyer, S., and F. Hsu, "Hesiod", Project Athena
+ Technical Plan - Name Service, April 1987,
+
+ [Moon 1981] - D. Moon, "Chaosnet", A.I. Memo 628, Massachusetts
+ Institute of Technology Artificial Intelligence Laboratory, June
+ 1981.
+
+ [RFC 1591] - Postel, J., "Domain Name System Structure and
+ Delegation", RFC 1591, March 1994.
+
+ [RFC 2929] - Eastlake 3rd, D., Brunner-Williams, E., and B. Manning,
+ "Domain Name System (DNS) IANA Considerations", BCP 42, RFC 2929,
+ September 2000.
+
+ [RFC 2606] - Eastlake, D. and A. Panitz, "Reserved Top Level DNS
+ Names", RFC 2606, June 1999.
+
+ [insensitive] - Eastlake, D., "Domain Name System (DNS) Case
+
+
+D. Eastlake 3rd [Page 14]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+ Insensitivity Clarification", draft-ietf-dnsext-insensitive-*.txt,
+ work in progress.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 15]
+
+
+INTERNET-DRAFT DNS IANA Considerations August 2005
+
+
+Authors Addresses
+
+ Donald E. Eastlake 3rd
+ Motorola Laboratories
+ 155 Beaver Street
+ Milford, MA 01757 USA
+
+ Telephone: +1-508-786-7554 (w)
+ email: Donald.Eastlake@motorola.com
+
+
+
+Expiration and File Name
+
+ This draft expires February 2006.
+
+ Its file name is draft-ietf-dnsext-2929bis-01.txt.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 16]
+
diff --git a/doc/draft/draft-ietf-dnsext-axfr-clarify-09.txt b/doc/draft/draft-ietf-dnsext-axfr-clarify-09.txt
new file mode 100644
index 0000000..94c08ec
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-axfr-clarify-09.txt
@@ -0,0 +1,992 @@
+INTERNET-DRAFT Edward Lewis
+draft-ietf-dnsext-axfr-clarify-09.txt NeuStar, Inc.
+DNSEXT WG July 2008
+Updates: 1034, 1035 (if approved) Intended status: Standards Track
+
+ DNS Zone Transfer Protocol (AXFR)
+Status of this Memo
+
+By submitting this Internet-Draft, each author represents that any
+applicable patent or other IPR claims of which he or she is aware
+have been or will be disclosed, and any of which he or she becomes
+aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+Internet-Drafts are working documents of the Internet Engineering
+Task Force (IETF), its areas, and its working groups. Note that
+other groups may also distribute working documents as Internet-
+Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any
+time. It is inappropriate to use Internet-Drafts as reference
+material or to cite them other than as "work in progress."
+
+The list of current Internet-Drafts can be accessed at
+http://www.ietf.org/ietf/1id-abstracts.txt.
+
+The list of Internet-Draft Shadow Directories can be accessed at
+http://www.ietf.org/shadow.html.
+
+This Internet-Draft will expire on December 31, 2008.
+
+Copyright Notice
+
+Copyright (C) The IETF Trust (2008).
+
+Abstract
+
+The Domain Name System standard mechanisms for maintaining coherent
+servers for a zone consist of three elements. One mechanism is the
+Authoritative Transfer (AXFR) is defined in RFC 1034 and RFC 1035.
+The definition of AXFR, has proven insufficient in detail, forcing
+implementations intended to be compliant to make assumptions, impeding
+interoperability. Yet today we have a satisfactory set of
+implementations that do interoperate. This document is a new
+definition of the AXFR, new in the sense that is it recording an
+accurate definition of an interoperable AXFR mechanism.
+
+1 Introduction
+
+The Domain Name System standard facilities for maintaining coherent
+servers for a zone consist of three elements. Authoritative
+Transfer (AXFR) is defined in "Domain Names - Concepts and Facilities"
+[RFC1034] (referred to in this document as RFC 1034) and "Domain Names
+- Implementation and Specification" [RFC1035] (aka RFC 1035).
+Incremental Zone Transfer (IXFR) is defined in "Incremental Zone
+Transfer in DNS" [RFC1995]. A mechanism for prompt notification of
+zone changes (NOTIFY) is defined in "A Mechanism for Prompt
+Notification of Zone Changes (DNS NOTIFY)" [RFC1996]. The goal of
+these mechanisms is to enable a set of DNS name servers to remain
+coherently authoritative for a given zone.
+
+Comments on this draft ought to be addressed to the editor or to
+namedroppers@ops.ietf.org.
+
+1.1 Definition of Terms
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+document are to be interpreted as described in "Key words for use in
+RFCs to Indicate Requirement Levels" [BCP14].
+
+"Newer"/"New" DNS and "older"/"old" DNS refers to implementations
+written after and prior to the publication of this document.
+
+1.2 Scope
+
+In the greater context there are many ways to achieve coherency among
+a set of name servers. The AXFR, IXFR and NOTIFY mechanisms form
+just one, the one defined in the RFCs cited. For example, there are
+DNS implementations that assemble answers from data stored in
+relational databases (as opposed to master files) relying on the
+database's non-DNS means to synchronize the database instances. Some
+of these non-DNS solutions interoperate in some fashion. As far as
+it is known, AXFR, IXFR and NOTIFY are the only in-band mechanisms
+that provide an interoperable solution to the desire for coherency
+within the definition of DNS, they certainly are the only mechanisms
+documented by the IETF.
+
+This document does not cover incoherent DNS situations. There are
+applications of the DNS in which servers for a zone are designed to be
+incoherent. For these configurations, a coherency mechanism as
+described here would be unsuitable.
+
+"General purpose DNS implementation" refers to DNS software developed
+for wide-spread use. This includes resolvers and servers freely
+accessible as libraries and standalone processes. This also includes
+proprietary implementations used only in support of DNS service
+offerings.
+
+"Turnkey DNS implementation" refers to custom made, single use
+implementations of DNS. Such implementations consist of software
+that employs the DNS protocol message format yet do not conform to
+the entire range of DNS functionality.
+
+A DNS implementation is not required to support AXFR, IXFR and NOTIFY.
+A DNS implementation SHOULD have some means for maintaining name server
+coherency. A general purpose DNS implementation SHOULD include AXFR
+(and in the same vein IXFR and NOTIFY), but turnkey DNS implementations
+MAY exist without AXFR. (An editorial note to readers of this section.
+The mention of IXFR and NOTIFY is for context and illustration, this
+document does not make any normative comments on those mechanisms.)
+
+1.3 Context
+
+Besides describing the mechanisms themselves, there is the context in
+which they operate to consider. When AXFR, IXFR and NOTIFY were
+defined, there was little consideration given to security and privacy
+issues. Since the original definition of AXFR, new opinions have
+appeared on the access to an entire zone's contents. In this document,
+the basic mechanisms will be discussed separately from the permission
+to use these mechanisms.
+
+1.4 Coverage
+
+This document concentrates on just the definition of AXFR. Any effort
+to update the IXFR or NOTIFY mechanisms would be done in different
+documents. This is not strictly a clarification of the definition in
+RFC 1034 and RFC 1035. This document will update those sections, and
+invalidate at least one part of that definition. The goal of this
+document is to define AXFR as it exists, or is supposed to exist,
+currently.
+
+1.4 Coverage and Relationship to Original AXFR Specification
+
+This document concentrates on just the definition of AXFR. Any effort
+to update the IXFR or NOTIFY mechanisms would be done in different
+documents.
+
+The original "specification" of the AXFR sub-protocol is scattered
+through RFC 1034 and RFC 1035. Section 2.2 of RFC 1035 on page 5
+depicts the scenario for which AXFR has been designed. Section 4.3.5
+of RFC 1034 describes the zone synchronisation strategies in general
+and rules for the invocation of a full zone transfer via AXFR; the
+fifth paragraph of that section contains a very short sketch of the
+AXFR protocol. Section 3.2.3 of RFC 1035 has assigned the code point
+for the AXFR QTYPE (see section 2.1.2 below for more details).
+Section 4.2 of RFC 1035 discusses the transport layer use of DNS and
+shortly explains why UDP transport is deemed inappropriate for AXFR;
+the last paragraph of Section 4.2.2 gives details for the TCP
+connection management with AXFR. Finally, the second paragraph of
+Section 6.3 in RFC 1035 mandates server behavior when zone data
+changes occur during an ongoing zone transfer using AXFR.
+
+This document will update the specification of AXFR in fully
+specifying the record formats and processing rules for AXFR, largely
+expanding on paragraph 5 of Section 4.3.5 of RFC 1034, and detailing
+the transport considerations for AXFR, thus amending Section 4.2.2 of
+RFC 1035. Furthermore, it discusses backward compatibility issues
+and provides policy/management considerations as well as specific
+Security Considerations for AXFR. The goal of this document is to
+define AXFR as it exists, or is supposed to exist, currently.
+
+2 AXFR Messages
+
+An AXFR message exchange (or session) consists of an AXFR query message
+and a set of AXFR response messages. In this document, AXFR client is
+the sender of the AXFR query and the AXFR server is the responder.
+(Use of terms such as master, slave, primary, secondary are not
+important to defining the AXFR exchange.) The reason for the imbalance
+in number of messages derives from large zones whose contents cannot be
+fit into the limited permissible size of a DNS message.
+
+An important aspect to keep in mind is that the definition of AXFR is
+restricted to TCP [RFC0793]. The design of the AXFR process has
+certain inherent features that are not easily ported to UDP [RFC0768].
+
+The basic format of an AXFR message is the DNS message as defined in
+RFC 1035, Section 4 ("MESSAGES") [RFC1035], updated by the following:
+- "A Mechanism for Prompt Notification of Zone Changes (...)" [RFC1996]
+- "Domain Name System (DNS) IANA Considerations" [RFC2929]
+- "Dynamic Updates in the Domain Name System (DNS UPDATE)" [RFC2136]
+- "Extension Mechanisms for DNS (EDNS0)" [RFC2671]
+- "Secret Key Transaction Authentication for DNS (TSIG)" [RFC2845]
+- "Secret Key Establishment for DNS (TKEY RR)" [RFC2930]
+- "Obsoleting IQUERY" [RFC3425]
+- "Handling of Unknown DNS Resource Record (RR) Types" [RFC3597]
+- "Protocol Modifications for the DNS Security Extensions" [RFC4035]
+- "HMAC SHA TSIG Algorithm Identifiers" [RFC4635]
+
+The upper limit on the permissible size of a DNS message over TCP is
+defined in RFC 1035, section 4.2.2. Unlike DNS messages over UDP,
+this limit is not changed by EDNS0.
+
+Field names used in this document will correspond to the names as they
+appear in the IANA registry for DNS Header Flags [DNSFLGS].
+
+2.1 AXFR query
+
+An AXFR query is sent by a client whenever there is a reason to ask.
+This might be because of zone maintenance activities or as a result of
+a command line request, say for debugging.
+
+2.1.1 Header Values
+
+These are the DNS message header values for an AXFR query.
+
+ID See note 2.1.1.a
+QR MUST be 0 (Query)
+OPCODE MUST be 0 (Standard Query)
+AA See note 2.1.1.b
+TC See note 2.1.1.b
+RD See note 2.1.1.b
+RA See note 2.1.1.b
+Z See note 2.1.1.c
+AD See note 2.1.1.b
+CD See note 2.1.1.b
+RCODE MUST be 0 (No error)
+QDCOUNT MUST be 1
+ANCOUNT MUST be 0
+NSCOUNT MUST be 0
+ARCOUNT See note 2.1.1.d
+
+Note 2.1.1.a Set to any value that the client is not already using
+with the same server. There is no specific means for selecting the
+value in this field. (Recall that AXFR is done only via TCP
+connections.)
+
+A server MUST reply using messages that use the same message ID to
+allow a client to meaningfully have multiple AXFR queries outstanding.
+
+Note 2.1.1.b The value in this field has no meaning in the context of
+AXFR query messages. For the client, it is RECOMMENDED that the
+value be zero. The server MUST ignore this value.
+
+Note 2.1.1.c The client MUST set this bit to 0, the server MUST ignore
+it.
+
+Note 2.1.1.d The client MUST set this field to be the number of
+resource records appearing in the additional section. See Section
+2.1.5 "Additional Section" for details.
+
+The value MAY be 0, 1 or 2. If it is 2, the additional
+section MUST contain both an EDNS0 [RFC2671] OPT resource record and
+a record carrying transaction integrity and authentication data,
+currently a choice of TSIG [RFC2845] and SIG(0) [RFC2931]. If the
+value is 1, then the additional section MUST contain either only an
+EDNS0 OPT resource record or a record carrying transaction integrity
+and authentication data. If the value is 0, the additional section
+MUST be empty.
+
+2.1.2 Query Section
+
+The Query section of the AXFR query MUST conform to section 4.1.2 of
+RFC 1035, and contain the following values:
+
+QNAME the name of the zone requested
+QTYPE AXFR(= 252), the pseudo-RR type for zone transfer [DNSVALS]
+QCLASS the class of the zone requested
+
+2.1.3 Answer Section
+
+MUST be empty.
+
+2.1.4 Authority Section
+
+MUST be empty.
+
+2.1.5 Additional Section
+
+The client MAY include an EDNS0 OPT [RFC2671] resource record. If the
+server has indicated that it does not support EDNS0, the client MUST
+send this section without an EDNS0 OPT resource record if there is a
+retry. Indication that a server does not support EDNS0 is not an
+explicit element in the protocol, it is up to the client to interpret.
+Most likely, the server will return a FORMERR which might be related to
+the OPT resource record.
+
+The client MAY include a transaction integrity and authentication
+resource record, currently a choice of TSIG [RFC2845] or SIG(0)
+[RFC2931]. If the server has indicated that it does not recognize the
+resource record, and that the error is indeed caused by the resource
+record, the client probably ought not try again. Removing the security
+data in the face of an obstacle ought to only be done with full
+awareness of the implication of doing so.
+
+In general, if an AXFR client is aware that an AXFR server does not
+support a particular mechanism, the client SHOULD NOT attempt to engage
+the server using the mechanism (or at all). A client could become
+aware of a server's abilities via a configuration setting or via some
+other (as yet) undefined means.
+
+The range of permissible resource records that MAY appear in the
+additional section might change over time. If either a change to an
+existing resource record (like the OPT RR for EDNS0) is made or
+a new additional section record is created, the new definitions ought
+to include a discussion on the impact upon AXFR. Although this is not
+predictale, future additional section residing records may have an
+effect that is orthogonal to AXFR, so can ride through the session as
+opaque data. In this case, a "wise" implementation ought to be able
+to pass these records through without disruption.
+
+2.2 AXFR response
+
+The AXFR response will consist of 0 or more messages. A "0 message"
+response is covered in section 2.2.1.
+
+An AXFR response that is transferring the zone's contents will consist
+of a series (which could be a series of length 1) of DNS messages.
+In such a series, the first message MUST begin with the SOA
+resource record of the zone, the last message MUST conclude with the
+same SOA resource record. Intermediate messages MUST NOT contain the
+SOA resource record. The first message MUST copy the Query Section
+from the corresponding AXFR query message in to the first response
+message's query section. Subsequent messages MAY do the same.
+
+An AXFR response that is indicating an error MUST consist of a single
+DNS message with the return code set to the appropriate value for the
+condition encountered - once the error condition is detected. Such
+a message MUST copy the AXFR query Query Section into its Query
+Section. The inclusion of the terminating SOA resource record is not
+necessary.
+
+An AXFR client might receive a number of AXFR response messages
+free of an error condition before the message indicating an error
+is received. But once an error is reported, the AXFR client can
+assume that the error reporting message is the last.
+
+2.2.1 "0 Message" Response
+
+A legitimate "0 message" response, i.e., the client sees no response
+whatsoever, is very exceptional and controversial. Unquestionably it
+is unhealthy for there to be 0 responses in a protocol that is designed
+around a query - response paradigm over an unreliable transport. The
+lack of a response could be a sign of underlying network problems and
+cause the protocol state machine to react accordingly. However, AXFR
+uses TCP and not UDP, eliminating undetected network errors.
+
+A "0 message response" is reserved for situations in which the server
+has a reason to suspect that the query is sent for the purpose of
+abuse. Due to the use of this being so controversial, a "0 message
+response" is not being defined as a legitimate part of the protocol
+but the use of it is being acknowledge as a warning to AXFR client
+implementations. Any earnest query has the expectation of some
+response but may not get one.
+
+If an AXFR client sends a query on a TCP connection and the connection
+is closed at any point, the AXFR client MUST consider the session
+terminated. The message ID MAY be used again on a new connection,
+even if the question and AXFR server are the same. Facing a dropped
+connection a client SHOULD try to make some determination whether the
+connection closure was the result of network activity or a decision
+by the AXFR server. This determination is not an exact science. It
+is up to the AXFR client implementor to react, but the reaction
+SHOULD NOT be an endless cycle of retires nor an increasing (in
+frequency) retry rate.
+
+An AXFR server implementor SHOULD take into consideration what this
+dilemma described above when a connection is closed with an outstanding
+query in the pipeline. For this reason, a server ought to reserve
+this course of action for situations in which it believes beyond a
+doubt that the AXFR client is attemping abusive behavior.
+
+2.2.2 Header Values
+
+ID See note 2.2.2.a
+QR MUST be 1 (Response)
+OPCODE MUST be 0 (Standard Query)
+AA See note 2.2.2.b
+TC MUST be 0 (Not truncated)
+RD RECOMMENDED copy request's value, MAY be set to 0
+RA See note 2.2.2.c
+Z See note 2.2.2.d
+AD See note 2.2.2.e
+CD See note 2.2.2.e
+RCODE See note 2.2.2.f
+QDCOUNT MUST be 1 in the first message; MUST be 0 or 1 in all
+ following
+ANCOUNT See note 2.2.2.g
+NSCOUNT MUST be 0
+ARCOUNT See note 2.2.2.h
+
+Note 2.2.2.a Because some old implementations behave differently than
+is now desired, the requirement on this field is stated in detail.
+New DNS servers MUST set this field to the value of the AXFR query
+ID in each AXFR response message for the session. AXFR clients MUST
+be able to manage sessions resulting from the issuance of multiple
+outstanding queries, whether AXFR queries or other DNS queries. A
+client SHOULD discard responses that do not correspond (via the
+message ID) to any outstanding queries.
+
+Unless the client is sure that the server will consistently set the ID
+field to the query's ID, the client is NOT RECOMMENDED to issue any
+other queries until the end of the zone transfer. A client MAY become
+aware of a server's abilities via a configuration setting.
+
+Note 2.2.2.b If the RCODE is 0 (no error), then the AA bit MUST be 1.
+For any other value of RCODE, the AA bit MUST be set according to rules
+for that error code. If in doubt, it is RECOMMENDED that it be set
+to 1. It is RECOMMENDED that the value be ignored by the AXFR client.
+
+Note 2.2.2.c It is RECOMMENDED that the server set the value to 0,
+the client MUST ignore this value.
+
+The server MAY set this value according to the local policy regarding
+recursive service, but doing so might confuse the interpretation of the
+response as AXFR can not be retrieved recursively. A client MAY note
+the server's policy regarding recursive service from this value, but
+SHOULD NOT conclude that the AXFR response was obtained recursively
+even if the RD bit was 1 in the query.
+
+Note 2.2.2.d The server MUST set this bit to 0, the client MUST ignore
+it.
+
+Note 2.2.2.e If the implementation supports the DNS Security Extensions
+(see below) then this value MUST be set according to the rules in RFC
+4035, section 3.1.6, "The AD and CD Bits in an Authoritative Response".
+If the implementation does not support the DNS Security Extensions,
+then this value MUST be set to 0 and MUST be ignored upon receipt.
+
+The DNS Security Extensions (DNSSEC) is defined in these base
+documents:
+- "DNS Security Introduction and Requirements" [RFC4033]
+- "Resource Records for the DNS Security Extensions" [RFC4034]
+- "Protocol Modifications for the DNS Security Extensions" [RFC4035]
+
+Note 2.2.2.f In the absence of an error, the server MUST set the value
+of this field to NoError. If a server is not authoritative for the
+queried zone, the server SHOULD set the value to NotAuth. (Reminder,
+consult the appropriate IANA registry [DNSVALS].) If a client
+receives any other value in response, it MUST act according to the
+error. For example, a malformed AXFR query or the presence of an EDNS0
+OPT resource record sent to an old server will garner a FormErr value.
+This value is not set as part of the AXFR response processing. The
+same is true for other error-indicating values.
+
+Note 2.2.2.g The count of answer records MUST equal the number of
+resource records in the AXFR Answer Section. When a server is aware
+that a client will only accept one resource record per response
+message, then the value MUST be 1. A server MAY be made aware of a
+client's limitations via configuration data.
+
+Note 2.2.2.h The client MUST set this field to be the number of
+resource records appearing in the additional section. See Section
+2.1.5 "Additional Section" for details.
+
+2.2.3 Query Section
+
+In the first response message, this section MUST be copied from the
+query. In subsequent messages this section MAY be copied from the
+query, MAY be empty. The content of this section MAY be used to
+determine the context of the message, that is, the name of the zone
+being transferred.
+
+2.2.4 Answer Section
+
+MUST be populated with the zone contents. See later section on
+encoding zone contents.
+
+2.2.5 Authority Section
+
+MUST be empty.
+
+2.2.5 Additional Section
+
+The contents of this section MUST follow the guidelines for EDNS0,
+TSIG, SIG(0), or what ever other future record is possible here. The
+contents of section 2.1.5 apply here as well.
+
+Note that TSIG and SIG(0), if in use, will treat each individual
+AXFR response message within a session as a unit of data. That is,
+each message will have a TSIG or SIG(0) (if in use) and the
+crytpographic check will cover just that message. The same rule
+will apply to future alternatives and documents covering them ought
+to consider the impact on AXFR response messages.
+
+3 Zone Contents
+
+The objective of the AXFR session is to request and transfer the
+contents of a zone. The objective is to permit the client to
+reconstruct the zone as it exists at the server for the given zone
+serial number. Over time the definition of a zone has evolved from a
+static set of records to a dynamically updated set of records to a
+continually regenerated set of records.
+
+3.1 Records to Include
+
+In the answer section of AXFR response messages the resource records
+within a zone for the given serial number MUST appear. The definition
+of what belongs in a zone is described in RFC 1034, Section 4.2, "How
+the database is divided into zones", and in particular, section 4.2.1,
+"Technical considerations".
+
+Unless the AXFR server knows that the AXFR client expects just one
+resource record per AXFR response message, an AXFR server SHOULD
+populate an AXFR response message with as many complete resource
+records as will fit within a DNS message.
+
+Zones for which it is impractical to list the entire zones for a serial
+number (because changes happen too quickly) are not suitable for AXFR
+retrieval.
+
+3.2 Delegation Records
+
+In RFC 1034, section 4.2.1, this text appears (keep in mind that the
+"should" in the quotation predates [BCP14], cf. section 1.1) "The RRs
+that describe cuts ... should be exactly the same as the corresponding
+RRs in the top node of the subzone." There has been some controversy
+over this statement and the impact on which NS resource records are
+included in a zone transfer.
+
+The phrase "that describe cuts" is a reference to the NS set and
+applicable glue records. It does not mean that the cut points and the
+apex resource records are identical. For example, the SOA resource
+record is only found at the apex, as well as a slew of DNSSEC resource
+records. There are also some DNSSEC resource record sets that are
+explicitly different between the cut point and the apex. The
+discussion here is restricted to just the NS resource record set and
+glue as these "describe cuts."
+
+The issue is that in operations there are times when the NS resource
+records for a zone might be different at a cut point in the parent and
+at the apex of a zone. Sometimes this is the result of an error and
+sometimes it is part of an ongoing change in name servers. The DNS
+protocol is robust enough to overcome inconsistencies up to (but not
+including) there being no parent indicated NS resource record
+referencing a server that is able to serve the child zone. This
+robustness is one quality that has fueled the success of the DNS.
+Still, the inconsistency is a error state and steps need to be taken
+to make it apparent (if it is unplanned) and to make it clear once
+the inconsistency has been removed.
+
+Another issue is that the AXFR server could be authoritative for a
+different set of zones than the AXFR client. It is possible that the
+AXFR server be authoritative for both halves of an inconsistent cut
+point and that the AXFR client is authoritative for just the parent of
+the cut point.
+
+The question that arises is, when facing a situation in which a cut
+point's NS resource records do not match the authoritative set, whether
+an AXFR server responds with the NS resource record set that is in the
+zone or is at the authoritative location.
+
+The AXFR response MUST contain the cut point NS resource record set
+registered with the zone whether it agrees with the authoritative set
+or not. "Registered with" can be widely interpreted to include data
+residing in the zone file of the zone for the particular serial
+number (in zone file environments) or as any data configured to be in
+the zone (database), statically or dynamically.
+
+The reasons for this requirement are:
+
+1) The AXFR server might not be able to determine that there is an
+inconsistency given local data, hence requiring consistency would mean
+a lot more needed work and even network retrieval of data. An
+authoritative server ought not be required to perform any queries.
+
+2) By transferring the inconsistent NS resource records from a server
+that is authoritative for both the cut point and the apex to a client
+that is not authoritative for both, the error is exposed. For example,
+an authorized administrator can manually request the AXFR and inspect
+the results to see the inconsistent records. (A server authoritative
+for both halves would otherwise always answer from the more
+authoritative set, concealing the error.)
+
+3) The inconsistent NS resource record set might indicate a problem
+in a registration database.
+
+4) Beginning with an error state of two servers for a zone having
+inconsistent zone contents for a given zone serial number, if a client
+requests and recieves an IXFR transfer from one server followed by
+another IXFR transfer from the other server, the client can encounter
+an IXFR protocol error state where an attempt is made to incrementally
+add a record that already exists or to delete a record that does not
+exist.
+
+(Editorial note, the 4th reason was suggested, but I don't see how
+it relates. A nudge for updated text on this.)
+
+3.3 Glue Records
+
+As quoted in the previous section, RFC 1034, section 4.2.1, provides
+guidance and rationale for the inclusion of glue records as part of
+an AXFR transfer. And, as also argued in the previous section of this
+document, even when there is an inconsistency between the address in a
+glue record and the authoritative copy of the name server's address,
+the glue resource record that is registered as part of the zone for
+that serial number is to be included.
+
+This applies for glue records for any address family.
+
+The AXFR response MUST contain the appropriate glue records as
+registered with the zone. The interpretation of "registered with"
+in the previous section applies here. Inconsistent glue records are
+an operational matter.
+
+3.4 Name Compression
+
+Compression of names in DNS messages is described in RFC 1035, section
+4.1.4, "Message compression". The issue highlighted here relates to a
+comment made in RFC 1034, section 3.1, "Name space specifications and
+terminology" which says "When you receive a domain name or label, you
+should preserve its case." ("Should" in the quote predates [BCP14].)
+
+Name compression in an AXFR message MUST preserve the case of the
+original domain name. That is, although when comparing a domain name,
+"a" equals "A", when comparing for the purposes of message compression,
+"a" is not equal to "A". Note that this is not the usual definition
+of name comparison in the DNS protocol and represents a new
+requirement on AXFR servers.
+
+Rules governing name compression of RDATA in an AXFR message MUST
+abide by the specification in "Handling of Unknown DNS Resource Record
+(RR) Types" [RFC3597], specifically, section 4 on "Domain Name
+Compression."
+
+3.5 Occluded Names
+
+Dynamic Update [RFC2136] (and including DNAME [2672]) operations can
+have a side effect of occluding names in a zone. The addition of a
+delegation point via dynamic update will render all subordinate domain
+names to be in a limbo, still part of the zone but not available for to
+the look up process. The addition of a DNAME resource record set has
+the same impact. The subordinate names are said to be "occluded."
+
+Occluded names MUST be included in AXFR responses. An AXFR client MUST
+be able to identify and handle occluded names. The rationale for this
+action is based on a speedy recovery if the dynamic update operation
+was in error and is to be undone.
+
+4 Transport
+
+AXFR sessions are currently restricted to TCP by section 4.3.5 of RFC
+1034 that states: "Because accuracy is essential, TCP or some other
+reliable protocol must be used for AXFR requests." The most common
+scenario is for an AXFR client to open a TCP connection to the AXFR
+server, send an AXFR query, receive the AXFR response, and then
+close the connection. There are variations on this, such as a query
+for the zone's SOA resource record first, and so on.
+
+Two issues have emerged since the original specification of AXFR.
+One is that lack of specificity has yielded some implementations
+that assume the TCP connection is dedicated to the single AXFR
+session, which has led to implementation choices that prevent either
+multiple concurrent zone transfers or the use of the open connection
+for other queries. The other issue is the prospect of using UDP as a
+transport has come to look promising because of trends in the past
+two decades.
+
+Being able to have multiple concurrent zone transfers is considered
+desirable by operators who have sets of name servers that are
+authoritative for a common set of zones. It would be desirable
+if the name server implementations did not have to wait for one
+zone to transfer before the next could begin. The desire here is to
+tighten the specification, not a change, but adding words to the
+unclear areas, to define what is needed to permit two servers to
+share a TCP connection among concurrent AXFR sessions. The challenge
+is to design this in a way that can fall back to the old behavior if
+either the AXFR client or AXFR server is incapable of performing
+multiple concurrent AXFR sessions.
+
+With the addition of EDNS0 and applications which require many
+small zones such as in web hosting and some ENUM scenarios, AXFR
+sessions on UDP are now possible and desirable. However, there
+are still some aspects of the AXFR session that are not easily
+translated to UDP. This document leaves AXFR over UDP undefined.
+
+4.1 TCP
+
+In the original definition there is an implicit assumption (probably
+unintentional) that a TCP connection is used for one and only one
+AXFR session. This is evidenced in no requirement to copy neither
+the Query Section nor the message ID in responses, no explicit
+ordering information within the AXFR response messages and the lack
+of an explicit notice indicating that a zone transfer continues in the
+next message.
+
+The guidance given here is intended to enable better performance of
+the AXFR exchange as well as guidelines on interactions with older
+software. Better performance includes being able to multiplex DNS
+message exchanges including zone transfer sessions. Guidelines for
+interacting with older software are generally applicable to AXFR
+clients as reversing the situation, older AXFR client and newer
+AXFR server ought to induce the server to operate within the
+specification for an older server.
+
+4.1.1 AXFR client TCP
+
+An AXFR client MAY request an connection to an AXFR server for any
+reason. An AXFR client SHOULD close the connection when there is
+no apparent need to use the connection for some time period. The
+AXFR server ought not have to maintain idle connections, the burden
+of connection closure ought to be on the client. Apparent need for
+the connection is a judgement for the AXFR client and the DNS
+client. If the connection is used for multiple sessions, or it is
+known sessions will be coming or is there is other query/response
+traffic on the open connection, that is "apparent need."
+
+An AXFR client MAY cancel delivery of a zone only by closing the
+connection. However, this action will also cancel all other outstanding
+activity using the connection. There is no other mechanism by which
+an AXFR response can be cancelled.
+
+When a TCP connection is closed remotely (relative to the client),
+whether by the AXFR server or due to a network event, the AXFR client
+MUST cancel all outstanding sessions. Recovery from this situation
+is not straightforward. If the disruption was a spurious event,
+attempting to restart the connection would be proper. If the
+disruption was caused by a medium or long term disruption, the AXFR
+client would be wise to not spend too many resources trying to rebuild
+the connection. Finally, if the connection was dropped because of a
+policy at the AXFR server (as can be the case with older AXFR servers),
+the AXFR client would be wise to not retry the connection.
+Unfortunately, knowing which of the three cases above applies is not
+clear (momentary disruption, failure, policy).
+
+An AXFR client MAY use an already opened TCP connection to start an
+AXFR session. Using an existing open connection is RECOMMENDED over
+opening a new connection. (Non-AXFR session traffic can also use an
+open connection.) If in doing so the AXFR client realizes that
+the responses cannot be properly differentiated (lack of matching
+query IDs for example) or the connection is terminated for a remote
+reason, then the AXFR client SHOULD not attempt to reuse an open
+connection with the specific AXFR server until the AXFR server is
+updated (which is of course, not an event captured in the DNS
+protocol).
+
+4.1.2 AXFR server TCP
+
+An AXFR server MUST be able to handle multiple AXFR sessions on a
+single TCP connection, as well as handle other query/response sessions.
+
+If a TCP connection is closed remotely, the AXFR server MUST cancel
+all AXFR sessions in place. No retry activity is necessary, that is
+initiated by the AXFR client.
+
+Local policy MAY dictate that a TCP connection is to be closed. Such
+as action SHOULD be in reaction to limits such as those placed on
+the number of outstanding open connections. Closing a connection in
+response to a suspected security event SHOULD be done only in extreme
+cases, when the server is certain the action is warranted. An
+isolated request for a zone not on the AXFR server SHOULD receive
+a response with the appropriate return code and not see the connection
+broken.
+
+4.2 UDP
+
+AXFR sessions over UDP transport are not defined.
+
+5 Authorization
+
+A zone administrator has the option to restrict AXFR access to a zone.
+This was not envisioned in the original design of the DNS but has
+emerged as a requirement as the DNS has evolved. Restrictions on AXFR
+could be for various reasons including a desire (or in some instances,
+having a legal requirement) to keep the bulk version of the zone
+concealed or to prevent the servers from handling the load incurred in
+serving AXFR. All reasons are arguable, but the fact remains that
+there is a requirement to provide mechanisms to restrict AXFR.
+
+A DNS implementation SHOULD provide means to restrict AXFR sessions to
+specific clients. By default, a DNS implementation SHOULD only allow
+the designated authoritative servers to have access to the zone.
+
+An implementation SHOULD allow access to be granted to Internet
+Protocol addresses and ranges, regardless of whether a source address
+could be spoofed. Combining this with techniques such as Virtual
+Private Networks (VPN) [RFC2764] or Virtual LANs has proven to be
+effective.
+
+A general purpose implementation is RECOMMENDED to implement access
+controls based upon "Secret Key Transaction Authentication for DNS"
+[RFC2845] and/or "DNS Request and Transaction Signatures ( SIG(0)s )"
+[RFC2931].
+
+A general purpose implementation SHOULD allow access to be open to
+all AXFR requests. I.e., an operator ought to be able to allow any
+AXFR query to be granted.
+
+A general purpose implementation SHOULD NOT have a default policy
+for AXFR requests to be "open to all."
+
+6 Zone Integrity
+
+Ensuring that an AXFR client does not accept a forged copy of a zone is
+important to the security of a zone. If a zone operator has the
+opportunity, protection can be afforded via dedicated links, physical
+or virtual via a VPN among the authoritative servers. But there are
+instances in which zone operators have no choice but to run AXFR
+sessions over the global public Internet.
+
+Besides best attempts at securing TCP sessions, DNS implementations
+SHOULD provide means to make use of "Secret Key Transaction
+Authentication for DNS" [RFC2845] and/or "DNS Request and Transaction
+Signatures ( SIG(0)s )" [RFC2931] to allow AXFR clients to verify the
+contents. These techniques MAY also be used for authorization.
+
+7 Backwards Compatibility
+
+Describing backwards compatibility is difficult because of the lack of
+specifics in the original definition. In this section some hints at
+building in backwards compatibility are given, mostly repeated from the
+earlier sections.
+
+Backwards compatibility is not necessary, but the greater extent of an
+implementation's compatibility increases it's interoperability. For
+turnkey implementations this is not usually a concern. For general
+purpose implementations this takes on varying levels of importance
+depending on the implementer's desire to maintain interoperability.
+
+It is unfortunate that a need to fall back to older behavior cannot be
+discovered, hence needs to be noted in a configuration file. An
+implementation SHOULD, in it's documentation, encourage operators to
+periodically review AXFR clients and servers it has made notes about as
+old software periodically gets updated.
+
+7.1 Server
+
+An AXFR server has the luxury of being able to react to an AXFR
+client's abilities with the exception of knowing if the client can
+accept multiple resource records per AXFR response message. The
+knowledge that a client is so restricted apparently cannot be
+discovered, hence it has to be set by configuration.
+
+An implementation of an AXFR server SHOULD permit configuring, on a per
+AXFR client basis, a need to revert to single resource record per
+message. The default SHOULD be to use multiple records per message.
+
+7.2 Client
+
+An AXFR client has the opportunity to try extensions when querying
+an AXFR server.
+
+Attempting to issue multiple DNS queries over a TCP transport for an
+AXFR session SHOULD be aborted if it interrupts the original request
+and SHOULD take into consideration whether the AXFR server intends to
+close the connection immediately upon completion of the original
+(connection-causing) zone transfer.
+
+8 Security Considerations
+
+Concerns regarding authorization, traffic flooding, and message
+integrity are mentioned in "Authorization" (section 5), "TCP" (section
+4.2) and Zone Integrity (section 6).
+
+9 IANA Considerations
+
+No new registries or new registrations are included in this document.
+
+10 Internationalization Considerations
+
+It is assumed that supporting of international domain names has been
+solved via "Internationalizing Domain Names in Applications (IDNA)"
+[RFC3490].
+
+11 Acknowledgements
+
+Earlier editions of this document have been edited by Andreas
+Gustafsson. In his latest version, this acknowledgement appeared.
+
+"Many people have contributed input and commentary to earlier versions
+of this document, including but not limited to Bob Halley, Dan
+Bernstein, Eric A. Hall, Josh Littlefield, Kevin Darcy, Robert Elz,
+Levon Esibov, Mark Andrews, Michael Patton, Peter Koch, Sam Trenholme,
+and Brian Wellington."
+
+Comments since the -05 version have come from these individuals:
+Alfred Hoenes, Mark Andrews, Paul Vixie, Wouter Wijngaards, Iain
+Calder, Tony Finch, Ian Jackson, Andreas Gustafsson, Brian Wellington,
+...
+
+12 References
+
+All references prefixed by "RFC" can be obtained from the RFC Editor,
+information regarding this organization can be found at the following
+URL:
+ http://rfc-editor.org/
+Additionally, these documents can be obtained via the IETF web site.
+
+12.1 Normative
+
+[RFC0793] Postel, J., "Transmission Control Protocol", STD 7, RFC 793,
+ September 1981.
+[RFC0768] Postel, J., "User Datagram Protocol", STD 6, RFC 768, August
+ 1980.
+[RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+[RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+[RFC1995] Ohta, M., "Incremental Zone Transfer in DNS", RFC 1995,
+ August 1996.
+[RFC1996] Vixie, P., "A Mechanism for Prompt Notification of Zone
+ Changes (DNS NOTIFY)", RFC 1996, August 1996.
+[RFC2136] Vixie, P., Ed., Thomson, S., Rekhter, Y., and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)", RFC
+ 2136, April 1997.
+[RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC 2671,
+ August 1999.
+[RFC2672] Crawford, M., "Non-Terminal DNS Name Redirection", RFC 2672,
+ August 1999.
+[RFC2845] Vixie, P., Gudmundsson, O., Eastlake 3rd, D., and B.
+ Wellington, "Secret Key Transaction Authentication for DNS
+ (TSIG)", RFC 2845, May 2000.
+[RFC2929] Eastlake 3rd, D., Brunner-Williams, E., and B. Manning,
+ "Domain Name System (DNS) IANA Considerations", BCP 42, RFC
+ 2929, September 2000.
+[RFC2930] Eastlake 3rd, D., "Secret Key Establishment for DNS (TKEY
+ RR)", RFC 2930, September 2000.
+[RFC2931] Eastlake 3rd, D., "DNS Request and Transaction Signatures
+ ( SIG(0)s )", RFC 2931, September 2000.
+[RFC3425] Lawrence, D., "Obsoleting IQUERY", RFC 3425, November 2002.
+[RFC3597] Gustafsson, A., "Handling of Unknown DNS Resource Record
+ (RR) Types", RFC 3597, September 2003.
+[RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements", RFC 4033,
+ March 2005.
+[RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security Extensions",
+ RFC 4034, March 2005.
+[RFC4035] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security
+ Extensions", RFC 4035, March 2005.
+[RFC4635] Eastlake 3rd, D., "HMAC SHA (Hashed Message Authentication
+ Code, Secure Hash Algorithm) TSIG Algorithm Identifiers",
+ RFC 4635, August 2006.
+[DNSFLGS] http://www.iana.org/assignments/dns-header-flags
+[DNSVALS] http://www.iana.org/assignments/dns-parameters
+
+12.2 Informative
+
+[BCP14] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+[RFC2764] Gleeson, B., Lin, A., Heinanen, J., Armitage, G., and A.
+ Malis, "A Framework for IP Based Virtual Private Networks",
+ RFC 2764, February 2000.
+[RFC3490] Faltstrom, P., Hoffman, P., and A. Costello,
+ "Internationalizing Domain Names in Applications (IDNA)", RFC
+ 3490, March 2003.
+
+13 Editor's Address
+
+Edward Lewis
+46000 Center Oak Plaza
+Sterling, VA, 22033, US
++1-571-434-5468
+ed.lewis@neustar.biz
+
+Full Copyright Statement
+
+Copyright (C) The IETF Trust (2008).
+
+This document is subject to the rights, licenses and restrictions
+contained in BCP 78, and except as set forth therein, the authors
+retain all their rights.
+
+This document and the information contained herein are provided on an
+"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+The IETF takes no position regarding the validity or scope of any
+Intellectual Property Rights or other rights that might be claimed to
+pertain to the implementation or use of the technology described in
+this document or the extent to which any license under such rights
+might or might not be available; nor does it represent that it has
+made any independent effort to identify any such rights. Information
+on the procedures with respect to rights in RFC documents can be
+found in BCP 78 and BCP 79.
+
+Copies of IPR disclosures made to the IETF Secretariat and any
+assurances of licenses to be made available, or the result of an
+attempt made to obtain a general license or permission for the use of
+such proprietary rights by implementers or users of this
+specification can be obtained from the IETF on-line IPR repository at
+http://www.ietf.org/ipr.
+
+The IETF invites any interested party to bring to its attention any
+copyrights, patents or patent applications, or other proprietary
+rights that may cover technology that may be required to implement
+this standard. Please address the information to the IETF at
+ietf-ipr@ietf.org.
+
+Acknowledgment
+
+Funding for the RFC Editor function is provided by the IETF
+Administrative Support Activity (IASA).
+
+
diff --git a/doc/draft/draft-ietf-dnsext-dns-name-p-s-00.txt b/doc/draft/draft-ietf-dnsext-dns-name-p-s-00.txt
new file mode 100644
index 0000000..438e800
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-dns-name-p-s-00.txt
@@ -0,0 +1,1397 @@
+DNS Extensions Working Group G. Sisson
+Internet-Draft B. Laurie
+Expires: January 11, 2006 Nominet
+ July 10, 2005
+
+
+ Derivation of DNS Name Predecessor and Successor
+ draft-ietf-dnsext-dns-name-p-s-00
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on January 11, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document describes two methods for deriving the canonically-
+ ordered predecessor and successor of a DNS name. These methods may
+ be used for dynamic NSEC resource record synthesis, enabling
+ security-aware name servers to provide authenticated denial of
+ existence without disclosing other owner names in a DNSSEC-secured
+ zone.
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 1]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Notational Conventions . . . . . . . . . . . . . . . . . . . . 3
+ 3. Absolute Method . . . . . . . . . . . . . . . . . . . . . . . 4
+ 3.1. Derivation of DNS Name Predecessor . . . . . . . . . . . . 4
+ 3.2. Derivation of DNS Name Successor . . . . . . . . . . . . . 4
+ 4. Modified Method . . . . . . . . . . . . . . . . . . . . . . . 5
+ 4.1. Derivation of DNS Name Predecessor . . . . . . . . . . . . 6
+ 4.2. Derivation of DNS Name Successor . . . . . . . . . . . . . 6
+ 5. Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 5.1. Case Considerations . . . . . . . . . . . . . . . . . . . 7
+ 5.2. Choice of Range . . . . . . . . . . . . . . . . . . . . . 7
+ 5.3. Wild Card Considerations . . . . . . . . . . . . . . . . . 8
+ 5.4. Possible Modifications . . . . . . . . . . . . . . . . . . 8
+ 5.4.1. Restriction of Effective Maximum DNS Name Length . . . 8
+ 5.4.2. Use of Modified Method With Zones Containing
+ SRV RRs . . . . . . . . . . . . . . . . . . . . . . . 9
+ 6. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 6.1. Examples of Immediate Predecessors Using Absolute
+ Method . . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 6.2. Examples of Immediate Successors Using Absolute Method . . 13
+ 6.3. Examples of Predecessors Using Modified Method . . . . . . 19
+ 6.4. Examples of Successors Using Modified Method . . . . . . . 20
+ 7. Security Considerations . . . . . . . . . . . . . . . . . . . 21
+ 8. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 21
+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . . 22
+ 10.1. Normative References . . . . . . . . . . . . . . . . . . . 22
+ 10.2. Informative References . . . . . . . . . . . . . . . . . . 22
+ 9. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 21
+ Appendix A. Change History . . . . . . . . . . . . . . . . . . . 22
+ A.1. Changes from sisson-02 to ietf-00 . . . . . . . . . . . . 22
+ A.2. Changes from sisson-01 to sisson-02 . . . . . . . . . . . 23
+ A.3. Changes from sisson-00 to sisson-01 . . . . . . . . . . . 23
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 24
+ Intellectual Property and Copyright Statements . . . . . . . . . . 25
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 2]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+1. Introduction
+
+ One of the proposals for avoiding the exposure of zone information
+ during the deployment DNSSEC is dynamic NSEC resource record (RR)
+ synthesis. This technique is described in [I-D.ietf-dnsext-dnssec-
+ trans] and [I-D.ietf-dnsext-dnssec-online-signing], and involves the
+ generation of NSEC RRs that just span the query name for non-existent
+ owner names. In order to do this, the DNS names which would occur
+ just prior to and just following a given query name must be
+ calculated in real time, as maintaining a list of all possible owner
+ names that might occur in a zone would be impracticable.
+
+ Section 6.1 of [RFC4034] defines canonical DNS name order. This
+ document does not amend or modify this definition. However, the
+ derivation of immediate predecessor and successor, while trivial, is
+ non-obvious. Accordingly, several methods are described here as an
+ aid to implementors and a reference to other interested parties.
+
+ This document describes two methods:
+
+ 1. An ``absolute method'', which returns the immediate predecessor
+ or successor of a domain name such that no valid DNS name could
+ exist between that DNS name and the predecessor or successor.
+
+ 2. A ``modified method'', which returns a predecessor and successor
+ which are more economical in size and computation. This method
+ is restricted to use with zones consisting only of single-label
+ owner names where a maximum-length owner name would not result in
+ a DNS name exceeding the maximum DNS name length. This is,
+ however, the type of zone for which the technique of online-
+ signing is most likely to be used.
+
+
+2. Notational Conventions
+
+ The following notational conventions are used in this document for
+ economy of expression:
+
+ N: An unspecified DNS name.
+
+ P(N): Immediate predecessor to N (absolute method).
+
+ S(N): Immediate successor to N (absolute method).
+
+ P'(N): Predecessor to N (modified method).
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 3]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ S'(N): Successor to N (modified method).
+
+
+3. Absolute Method
+
+ These derivations assume that all uppercase US-ASCII letters in N
+ have already been replaced by their corresponding lowercase
+ equivalents. Unless otherwise specified, processing stops after the
+ first step in which a condition is met.
+
+3.1. Derivation of DNS Name Predecessor
+
+ To derive P(N):
+
+ 1. If N is the same as the owner name of the zone apex, prepend N
+ repeatedly with labels of the maximum length possible consisting
+ of octets of the maximum sort value (e.g. 0xff) until N is the
+ maximum length possible; otherwise continue to the next step.
+
+ 2. If the least significant (left-most) label of N consists of a
+ single octet of the minimum sort value (e.g. 0x00), remove that
+ label; otherwise continue to the next step.
+
+ 3. If the least significant (right-most) octet in the least
+ significant (left-most) label of N is the minimum sort value,
+ remove the least significant octet and continue with step 5.
+
+ 4. Decrement the value of the least significant (right-most) octet,
+ skipping any values that correspond to uppercase US-ASCII
+ letters, and then append the label with as many octets as
+ possible of the maximum sort value. Continue to the next step.
+
+ 5. Prepend N repeatedly with labels of as long a length as possible
+ consisting of octets of the maximum sort value until N is the
+ maximum length possible.
+
+3.2. Derivation of DNS Name Successor
+
+ To derive S(N):
+
+ 1. If N is two or more octets shorter than the maximum DNS name
+ length, prepend N with a label containing a single octet of the
+ minimum sort value (e.g. 0x00); otherwise continue to the next
+ step.
+
+ 2. If N is one or more octets shorter than the maximum DNS name
+ length and the least significant (left-most) label is one or more
+ octets shorter than the maximum label length, append an octet of
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 4]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ the minimum sort value to the least significant label; otherwise
+ continue to the next step.
+
+ 3. Increment the value of the least significant (right-most) octet
+ in the least significant (left-most) label that is less than the
+ maximum sort value (e.g. 0xff), skipping any values that
+ correspond to uppercase US-ASCII letters, and then remove any
+ octets to the right of that one. If all octets in the label are
+ the maximum sort value, then continue to the next step.
+
+ 4. Remove the least significant (left-most) label. If N is now the
+ same as the owner name of the zone apex, do nothing. (This will
+ occur only if N is the maximum possible name in canonical DNS
+ name order, and thus has wrapped to the owner name of zone apex.)
+ Otherwise repeat starting at step 2.
+
+
+4. Modified Method
+
+ This method is for use with zones consisting only of single-label
+ owner names where an owner name consisting of label of maximum length
+ would not result in a DNS name which exceeded the maximum DNS name
+ length. This method is computationally simpler and returns values
+ which are more economical in size than the absolute method. It
+ differs from the absolute method detailed above in the following
+ ways:
+
+ 1. Step 1 of the derivation P(N) has been omitted as the existence
+ of the owner name of the zone apex never requires denial.
+
+ 2. A new step 1 has been introduced which removes unnecessary
+ labels.
+
+ 3. Step 4 of the derivation P(N) has been omitted as it is only
+ necessary for zones containing owner names consisting of more
+ than one label. This omission generally results in a significant
+ reduction of the length of derived predecessors.
+
+ 4. Step 1 of the derivation S(N) had been omitted as it is only
+ necessary for zones containing owner names consisting of more
+ than one label. This omission results in a tiny reduction of the
+ length of derived successors, and maintains consistency with the
+ modification of step 4 of the derivation P(N) described above.
+
+ 5. Steps 2 and 4 of the derivation S(N) have been modified to
+ eliminate checks for maximum DNS name length, as it is an
+ assumption of this method that no DNS name in the zone can exceed
+ the maximum DNS name length.
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 5]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ These derivations assume that all uppercase US-ASCII letters in N
+ have already been replaced by their corresponding lowercase
+ equivalents. Unless otherwise specified, processing stops after the
+ first step in which a condition is met.
+
+4.1. Derivation of DNS Name Predecessor
+
+ To derive P'(N):
+
+ 1. If N has more labels than the number of labels in the owner name
+ of the apex + 1, repeatedly remove the least significant (left-
+ most) label until N has no more labels than the number of labels
+ in the owner name of the apex + 1; otherwise continue to next
+ step.
+
+ 2. If the least significant (left-most) label of N consists of a
+ single octet of the minimum sort value (e.g. 0x00), remove that
+ label; otherwise continue to the next step.
+
+ 3. If the least significant (right-most) octet in the least
+ significant (left-most) label of N is the minimum sort value,
+ remove the least significant octet.
+
+ 4. Decrement the value of the least significant (right-most) octet,
+ skipping any values which correspond to uppercase US-ASCII
+ letters, and then append the label with as many octets as
+ possible of the maximum sort value.
+
+4.2. Derivation of DNS Name Successor
+
+ To derive S'(N):
+
+ 1. If N has more labels than the number of labels in the owner name
+ of the apex + 1, repeatedly remove the least significant (left-
+ most) label until N has no more labels than the number of labels
+ in the owner name of the apex + 1. Continue to next step.
+
+ 2. If the least significant (left-most) label of N is one or more
+ octets shorter than the maximum label length, append an octet of
+ the minimum sort value to the least significant label; otherwise
+ continue to the next step.
+
+ 3. Increment the value of the least significant (right-most) octet
+ in the least significant (left-most) label that is less than the
+ maximum sort value (e.g. 0xff), skipping any values which
+ correspond to uppercase US-ASCII letters, and then remove any
+ octets to the right of that one. If all octets in the label are
+ the maximum sort value, then continue to the next step.
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 6]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ 4. Remove the least significant (left-most) label. (This will occur
+ only if the least significant label is the maximum label length
+ and consists entirely of octets of the maximum sort value, and
+ thus has wrapped to the owner name of the zone apex.)
+
+
+5. Notes
+
+5.1. Case Considerations
+
+ Section 3.5 of [RFC1034] specifies that "while upper and lower case
+ letters are allowed in [DNS] names, no significance is attached to
+ the case". Additionally, Section 6.1 of [RFC4034] states that when
+ determining canonical DNS name order, "uppercase US-ASCII letters are
+ treated as if they were lowercase US-ASCII letters". Consequently,
+ values corresponding to US-ASCII uppercase letters must be skipped
+ when decrementing and incrementing octets in the derivations
+ described in Section 3.1 and Section 3.2.
+
+ The following pseudo-code is illustrative:
+
+ Decrement the value of an octet:
+
+ if (octet == '[') // '[' is just after uppercase 'Z'
+ octet = '@'; // '@' is just prior to uppercase 'A'
+ else
+ octet--;
+
+ Increment the value of an octet:
+
+ if (octet == '@') // '@' is just prior to uppercase 'A'
+ octet = '['; // '[' is just after uppercase 'Z'
+ else
+ octet++;
+
+5.2. Choice of Range
+
+ [RFC2181] makes the clarification that "any binary string whatever
+ can be used as the label of any resource record". Consequently the
+ minimum sort value may be set as 0x00 and the maximum sort value as
+ 0xff, and the range of possible values will be any DNS name which
+ contains octets of any value other than those corresponding to
+ uppercase US-ASCII letters.
+
+ However, if all owner names in a zone are in the letter-digit-hyphen,
+ or LDH, format specified in [RFC1034], it may be desirable to
+ restrict the range of possible values to DNS names containing only
+ LDH values. This has the effect of:
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 7]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ 1. making the output of tools such as `dig' and `nslookup' less
+ subject to confusion;
+
+ 2. minimising the impact that NSEC RRs containing DNS names with
+ non-LDH values (or non-printable values) might have on faulty DNS
+ resolver implementations; and
+
+ 3. preventing the possibility of results which are wildcard DNS
+ names (see Section 5.3).
+
+ This may be accomplished by using a minimum sort value of 0x1f (US-
+ ASCII character `-') and a maximum sort value of 0x7a (US-ASCII
+ character lowercase `z'), and then skipping non-LDH, non-lowercase
+ values when incrementing or decrementing octets.
+
+5.3. Wild Card Considerations
+
+ Neither derivation avoids the possibility that the result may be a
+ DNS name containing a wildcard label, i.e. a label containing a
+ single octet with the value 0x2a (US-ASCII character `*'). With
+ additional tests, wildcard DNS names may be explicitly avoided;
+ alternatively, if the range of octet values can be restricted to
+ those corresponding to letter-digit-hyphen, or LDH, characters (see
+ Section 5.2), such DNS names will not occur.
+
+ Note that it is improbable that a result which is a wildcard DNS name
+ will occur unintentionally; even if one does occur either as the
+ owner name of, or in the RDATA of an NSEC RR, it is treated as a
+ literal DNS name with no special meaning.
+
+5.4. Possible Modifications
+
+5.4.1. Restriction of Effective Maximum DNS Name Length
+
+ [RFC1034] specifies that "the total number of octets that represent a
+ [DNS] name (i.e., the sum of all label octets and label lengths) is
+ limited to 255", including the null (zero-length) label which
+ represents the root. For the purpose of deriving predecessors and
+ successors during NSEC RR synthesis, the maximum DNS name length may
+ be effectively restricted to the length of the longest DNS name in
+ the zone. This will minimise the size of responses containing
+ synthesised NSEC RRs but, especially in the case of the modified
+ method, may result in some additional computational complexity.
+
+ Note that this modification will have the effect of revealing
+ information about the longest name in the zone. Moreover, when the
+ contents of the zone changes, e.g. during dynamic updates and zone
+ transfers, care must be taken to ensure that the effective maximum
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 8]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ DNS name length agrees with the new contents.
+
+5.4.2. Use of Modified Method With Zones Containing SRV RRs
+
+ Normally the modified method cannot be used in zones that contain
+ SRV RRs [RFC2782], as SRV RRs have owner names which contain multiple
+ labels. However the use of SRV RRs can be accommodated by various
+ techniques. There are at least four possible ways to do this:
+
+ 1. Use conventional NSEC RRs for the region of the zone that
+ contains first-level labels beginning with the underscore (`_')
+ character. For the purposes of generating these NSEC RRs, the
+ existence of (possibly fictional) ownernames `9{63}' and `a'
+ could be assumed, providing a lower and upper bound for this
+ region. Then all queries where the QNAME doesn't exist but
+ contains a first-level label beginning with an underscore could
+ be handled using the normal DNSSEC protocol.
+
+ This approach would make it possible to enumerate all DNS names
+ in the zone containing a first-level label beginning with
+ underscore, including all SRV RRs, but this may be of less a
+ concern to the zone administrator than incurring the overhead of
+ the absolute method or of the following variants of the modified
+ method.
+
+ 2. The absolute method could be used for synthesising NSEC RRs for
+ all queries where the QNAME contains a leading underscore.
+ However this re-introduces the susceptibility of the absolute
+ method to denial of service activity, as an attacker could send
+ queries for an effectively inexhaustible supply of domain names
+ beginning with a leading underscore.
+
+ 3. A variant of the modified method could be used for synthesising
+ NSEC RRs for all queries where the QNAME contains a leading
+ underscore. This variant would assume that all predecessors and
+ successors to queries where the QNAME contains a leading
+ underscore may consist of two lablels rather than only one. This
+ introduces a little additional complexity without incurring the
+ full increase in response size and computational complexity as
+ the absolute method.
+
+ 4. Finally, a variant the modified method which assumes that all
+ owner names in the zone consist of one or two labels could be
+ used. However this negates much of the reduction in response
+ size of the modified method and may be nearly as computationally
+ complex as the absolute method.
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 9]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+6. Examples
+
+ In the following examples:
+
+ the owner name of the zone apex is "example.com.";
+
+ the range of octet values is 0x00 - 0xff excluding values
+ corresponding to uppercase US-ASCII letters; and
+
+ non-printable octet values are expressed as three-digit decimal
+ numbers preceded by a backslash (as specified in Section 5.1 of
+ [RFC1035]).
+
+6.1. Examples of Immediate Predecessors Using Absolute Method
+
+ Example of typical case:
+
+ P(foo.example.com.) =
+
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255.\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255.\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255.fon\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255.example.com.
+
+ or, in alternate notation:
+
+ \255{49}.\255{63}.\255{63}.fon\255{60}.example.com.
+
+ where {n} represents the number of repetitions of an octet.
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 10]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where least significant (left-most) label of DNS name
+ consists of a single octet of the minimum sort value:
+
+ P(\000.foo.example.com.) = foo.example.com.
+
+ Example where least significant (right-most) octet of least
+ significant (left-most) label has the minimum sort value:
+
+ P(foo\000.example.com.) =
+
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255.\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255.\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255.\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255.foo.example.com.
+
+ or, in alternate notation:
+
+ \255{45}.\255{63}.\255{63}.\255{63}.foo.example.com.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 11]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where DNS name contains an octet which must be decremented by
+ skipping values corresponding to US-ASCII uppercase letters:
+
+ P(fo\[.example.com.) =
+
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255.\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255.\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255.fo\@\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255.example.com.
+
+ or, in alternate notation:
+
+ \255{49}.\255{63}.\255{63}.fo\@\255{60}.example.com.
+
+ where {n} represents the number of repetitions of an octet.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 12]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where DNS name is the owner name of the zone apex, and
+ consequently wraps to the DNS name with the maximum possible sort
+ order in the zone:
+
+ P(example.com.) =
+
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255.\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255.\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255.\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255.example.com.
+
+ or, in alternate notation:
+
+ \255{49}.\255{63}.\255{63}.\255{63}.example.com.
+
+6.2. Examples of Immediate Successors Using Absolute Method
+
+ Example of typical case:
+
+ S(foo.example.com.) = \000.foo.example.com.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 13]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where DNS name is one octet short of the maximum DNS name
+ length:
+
+ N = fooooooooooooooooooooooooooooooooooooooooooooooo
+ .ooooooooooooooooooooooooooooooooooooooooooooooo
+ oooooooooooooooo.ooooooooooooooooooooooooooooooo
+ oooooooooooooooooooooooooooooooo.ooooooooooooooo
+ oooooooooooooooooooooooooooooooooooooooooooooooo.example.com.
+
+ or, in alternate notation:
+
+ fo{47}.o{63}.o{63}.o{63}.example.com.
+
+ S(N) =
+
+ fooooooooooooooooooooooooooooooooooooooooooooooo
+ \000.ooooooooooooooooooooooooooooooooooooooooooo
+ oooooooooooooooooooo.ooooooooooooooooooooooooooo
+ oooooooooooooooooooooooooooooooooooo.ooooooooooo
+ oooooooooooooooooooooooooooooooooooooooooooooooo
+ oooo.example.com.
+
+ or, in alternate notation:
+
+ fo{47}\000.o{63}.o{63}.o{63}.example.com.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 14]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where DNS name is the maximum DNS name length:
+
+ N = fooooooooooooooooooooooooooooooooooooooooooooooo
+ o.oooooooooooooooooooooooooooooooooooooooooooooo
+ ooooooooooooooooo.oooooooooooooooooooooooooooooo
+ ooooooooooooooooooooooooooooooooo.oooooooooooooo
+ oooooooooooooooooooooooooooooooooooooooooooooooo
+ o.example.com.
+
+ or, in alternate notation:
+
+ fo{48}.o{63}.o{63}.o{63}.example.com.
+
+ S(N) =
+
+ fooooooooooooooooooooooooooooooooooooooooooooooo
+ p.oooooooooooooooooooooooooooooooooooooooooooooo
+ ooooooooooooooooo.oooooooooooooooooooooooooooooo
+ ooooooooooooooooooooooooooooooooo.oooooooooooooo
+ oooooooooooooooooooooooooooooooooooooooooooooooo
+ o.example.com.
+
+ or, in alternate notation:
+
+ fo{47}p.o{63}.o{63}.o{63}.example.com.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 15]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where DNS name is the maximum DNS name length and the least
+ significant (left-most) label has the maximum sort value:
+
+ N = \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255.ooooooooooooooooooooooooooooooooooooooooooo
+ oooooooooooooooooooo.ooooooooooooooooooooooooooo
+ oooooooooooooooooooooooooooooooooooo.ooooooooooo
+ oooooooooooooooooooooooooooooooooooooooooooooooo
+ oooo.example.com.
+
+ or, in alternate notation:
+
+ \255{49}.o{63}.o{63}.o{63}.example.com.
+
+ S(N) =
+
+ oooooooooooooooooooooooooooooooooooooooooooooooo
+ oooooooooooooop.oooooooooooooooooooooooooooooooo
+ ooooooooooooooooooooooooooooooo.oooooooooooooooo
+ ooooooooooooooooooooooooooooooooooooooooooooooo.
+ example.com.
+
+ or, in alternate notation:
+
+ o{62}p.o{63}.o{63}.example.com.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 16]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where DNS name is the maximum DNS name length and the eight
+ least significant (right-most) octets of the least significant (left-
+ most) label have the maximum sort value:
+
+ N = foooooooooooooooooooooooooooooooooooooooo\255
+ \255\255\255\255\255\255\255.ooooooooooooooooooo
+ oooooooooooooooooooooooooooooooooooooooooooo.ooo
+ oooooooooooooooooooooooooooooooooooooooooooooooo
+ oooooooooooo.ooooooooooooooooooooooooooooooooooo
+ oooooooooooooooooooooooooooo.example.com.
+
+ or, in alternate notation:
+
+ fo{40}\255{8}.o{63}.o{63}.o{63}.example.com.
+
+ S(N) =
+
+ fooooooooooooooooooooooooooooooooooooooop.oooooo
+ oooooooooooooooooooooooooooooooooooooooooooooooo
+ ooooooooo.oooooooooooooooooooooooooooooooooooooo
+ ooooooooooooooooooooooooo.oooooooooooooooooooooo
+ ooooooooooooooooooooooooooooooooooooooooo.example.com.
+
+ or, in alternate notation:
+
+ fo{39}p.o{63}.o{63}.o{63}.example.com.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 17]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where DNS name is the maximum DNS name length and contains an
+ octet which must be incremented by skipping values corresponding to
+ US-ASCII uppercase letters:
+
+ N = fooooooooooooooooooooooooooooooooooooooooooooooo
+ \@.ooooooooooooooooooooooooooooooooooooooooooooo
+ oooooooooooooooooo.ooooooooooooooooooooooooooooo
+ oooooooooooooooooooooooooooooooooo.ooooooooooooo
+ oooooooooooooooooooooooooooooooooooooooooooooooo
+ oo.example.com.
+
+ or, in alternate notation:
+
+ fo{47}\@.o{63}.o{63}.o{63}.example.com.
+
+ S(N) =
+
+ fooooooooooooooooooooooooooooooooooooooooooooooo
+ \[.ooooooooooooooooooooooooooooooooooooooooooooo
+ oooooooooooooooooo.ooooooooooooooooooooooooooooo
+ oooooooooooooooooooooooooooooooooo.ooooooooooooo
+ oooooooooooooooooooooooooooooooooooooooooooooooo
+ oo.example.com.
+
+ or, in alternate notation:
+
+ fo{47}\[.o{63}.o{63}.o{63}.example.com.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 18]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where DNS name has the maximum possible sort order in the
+ zone, and consequently wraps to the owner name of the zone apex:
+
+ N = \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255.\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255.\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255.\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255.example.com.
+
+ or, in alternate notation:
+
+ \255{49}.\255{63}.\255{63}.\255{63}.example.com.
+
+ S(N) = example.com.
+
+6.3. Examples of Predecessors Using Modified Method
+
+ Example of typical case:
+
+ P'(foo.example.com.) =
+
+ fon\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255.example.com.
+
+ or, in alternate notation:
+
+ fon\255{60}.example.com.
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 19]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where DNS name contains more labels than DNS names in the
+ zone:
+
+ P'(bar.foo.example.com.) = foo.example.com.
+
+ Example where least significant (right-most) octet of least
+ significant (left-most) label has the minimum sort value:
+
+ P'(foo\000.example.com.) = foo.example.com.
+
+ Example where least significant (left-most) label has the minimum
+ sort value:
+
+ P'(\000.example.com.) = example.com.
+
+ Example where DNS name is the owner name of the zone apex, and
+ consequently wraps to the DNS name with the maximum possible sort
+ order in the zone:
+
+ P'(example.com.) =
+
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255.example.com.
+
+ or, in alternate notation:
+
+ \255{63}.example.com.
+
+6.4. Examples of Successors Using Modified Method
+
+ Example of typical case:
+
+ S'(foo.example.com.) = foo\000.example.com.
+
+ Example where DNS name contains more labels than DNS names in the
+ zone:
+
+ S'(bar.foo.example.com.) = foo\000.example.com.
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 20]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+ Example where least significant (left-most) label has the maximum
+ sort value, and consequently wraps to the owner name of the zone
+ apex:
+
+ N = \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255.example.com.
+
+ or, in alternate notation:
+
+ \255{63}.example.com.
+
+ S'(N) = example.com.
+
+
+7. Security Considerations
+
+ The derivation of some predecessors/successors requires the testing
+ of more conditions than others. Consequently the effectiveness of a
+ denial-of-service attack may be enhanced by sending queries that
+ require more conditions to be tested. The modified method involves
+ the testing of fewer conditions than the absolute method and
+ consequently is somewhat less susceptible to this exposure.
+
+
+8. IANA Considerations
+
+ This document has no IANA actions.
+
+ Note to RFC Editor: This section is included to make it clear during
+ pre-publication review that this document has no IANA actions. It
+ may therefore be removed should it be published as an RFC.
+
+
+9. Acknowledgments
+
+ The authors would like to thank Olaf Kolkman, Olafur Gudmundsson and
+ Niall O'Reilly for their review and input.
+
+
+10. References
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 21]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+10.1 Normative References
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for
+ specifying the location of services (DNS SRV)", RFC 2782,
+ February 2000.
+
+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security Extensions",
+ RFC 4034, March 2005.
+
+10.2 Informative References
+
+ [I-D.ietf-dnsext-dnssec-online-signing]
+ Ihren, J. and S. Weiler, "Minimally Covering NSEC Records
+ and DNSSEC On-line Signing",
+ draft-ietf-dnsext-dnssec-online-signing-00 (work in
+ progress), May 2005.
+
+ [I-D.ietf-dnsext-dnssec-trans]
+ Arends, R., Koch, P., and J. Schlyter, "Evaluating DNSSEC
+ Transition Mechanisms",
+ draft-ietf-dnsext-dnssec-trans-02 (work in progress),
+ February 2005.
+
+
+Appendix A. Change History
+
+A.1. Changes from sisson-02 to ietf-00
+
+ o Added notes on use of SRV RRs with modified method.
+
+ o Changed reference from weiler-dnssec-online-signing to ietf-
+ dnsext-dnssec-online-signing.
+
+ o Changed reference from ietf-dnsext-dnssec-records to RFC 4034.
+
+ o Miscellaneous minor changes to text.
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 22]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+A.2. Changes from sisson-01 to sisson-02
+
+ o Added modified version of derivation (with supporting examples).
+
+ o Introduced notational conventions N, P(N), S(N), P'(N) and S'(N).
+
+ o Added clarification to derivations about when processing stops.
+
+ o Miscellaneous minor changes to text.
+
+A.3. Changes from sisson-00 to sisson-01
+
+ o Split step 3 of derivation of DNS name predecessor into two
+ distinct steps for clarity.
+
+ o Added clarifying text and examples related to the requirement to
+ avoid uppercase characters when decrementing or incrementing
+ octets.
+
+ o Added optimisation using restriction of effective maximum DNS name
+ length.
+
+ o Changed examples to use decimal rather than octal notation as per
+ [RFC1035].
+
+ o Corrected DNS name length of some examples.
+
+ o Added reference to weiler-dnssec-online-signing.
+
+ o Miscellaneous minor changes to text.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 23]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+Authors' Addresses
+
+ Geoffrey Sisson
+ Nominet
+ Sandford Gate
+ Sandy Lane West
+ Oxford
+ OX4 6LB
+ GB
+
+ Phone: +44 1865 332339
+ Email: geoff@nominet.org.uk
+
+
+ Ben Laurie
+ Nominet
+ 17 Perryn Road
+ London
+ W3 7LR
+ GB
+
+ Phone: +44 20 8735 0686
+ Email: ben@algroup.co.uk
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 24]
+
+Internet-Draft DNS Name Predecessor and Successor July 2005
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2005). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Sisson & Laurie Expires January 11, 2006 [Page 25]
+
diff --git a/doc/draft/draft-ietf-dnsext-dnssec-2535typecode-change-06.txt b/doc/draft/draft-ietf-dnsext-dnssec-2535typecode-change-06.txt
new file mode 100644
index 0000000..bcc2b4e
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-dnssec-2535typecode-change-06.txt
@@ -0,0 +1,442 @@
+
+
+INTERNET-DRAFT Samuel Weiler
+Expires: June 2004 December 15, 2003
+Updates: RFC 2535, [DS]
+
+ Legacy Resolver Compatibility for Delegation Signer
+ draft-ietf-dnsext-dnssec-2535typecode-change-06.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is subject to all provisions
+ of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as
+ Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six
+ months and may be updated, replaced, or obsoleted by other
+ documents at any time. It is inappropriate to use Internet-Drafts
+ as reference material or to cite them other than as "work in
+ progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+ Comments should be sent to the author or to the DNSEXT WG mailing
+ list: namedroppers@ops.ietf.org
+
+Abstract
+
+ As the DNS Security (DNSSEC) specifications have evolved, the
+ syntax and semantics of the DNSSEC resource records (RRs) have
+ changed. Many deployed nameservers understand variants of these
+ semantics. Dangerous interactions can occur when a resolver that
+ understands an earlier version of these semantics queries an
+ authoritative server that understands the new delegation signer
+ semantics, including at least one failure scenario that will cause
+ an unsecured zone to be unresolvable. This document changes the
+ type codes and mnemonics of the DNSSEC RRs (SIG, KEY, and NXT) to
+ avoid those interactions.
+
+Changes between 05 and 06:
+
+ Signifigantly reworked the IANA section -- went back to one
+ algorithm registry.
+
+ Removed Diffie-Hellman from the list of zone-signing algorithms
+ (leaving only DSA, RSA/SHA-1, and private algorithms).
+
+ Added a DNSKEY flags field registry.
+
+Changes between 04 and 05:
+
+ IESG approved publication.
+
+ Cleaned up an internal reference in the acknowledgements section.
+
+ Retained KEY and SIG for TKEY, too. Added TKEY (2930) reference.
+
+ Changed the names of both new registries. Added algorithm
+ mnemonics to the new zone signing algorithm registry. Minor
+ rewording in the IANA section for clarity.
+
+ Cleaned up formatting of references. Replaced unknown-rr draft
+ references with RFC3597. Bumped DS version number.
+
+Changes between 03 and 04:
+
+ Clarified that RRSIG(0) may be defined by standards action.
+
+ Created a new algorithm registry and renamed the old algorithm
+ registry for SIG(0) only. Added references to the appropriate
+ crypto algorithm and format specifications.
+
+ Several minor rephrasings.
+
+Changes between 02 and 03:
+
+ KEY (as well as SIG) retained for SIG(0) use only.
+
+Changes between 01 and 02:
+
+ SIG(0) still uses SIG, not RRSIG. Added 2931 reference.
+
+ Domain names embedded in NSECs and RRSIGs are not compressible and
+ are not downcased. Added unknown-rrs reference (as informative).
+
+ Simplified the last paragraph of section 3 (NSEC doesn't always
+ signal a negative answer).
+
+ Changed the suggested type code assignments.
+
+ Added 2119 reference.
+
+ Added definitions of "unsecure delegation" and "unsecure referral",
+ since they're not clearly defined elsewhere.
+
+ Moved 2065 to informative references, not normative.
+
+1. Introduction
+
+ The DNSSEC protocol has been through many iterations whose syntax
+ and semantics are not completely compatible. This has occurred as
+ part of the ordinary process of proposing a protocol, implementing
+ it, testing it in the increasingly complex and diverse environment
+ of the Internet, and refining the definitions of the initial
+ Proposed Standard. In the case of DNSSEC, the process has been
+ complicated by DNS's criticality and wide deployment and the need
+ to add security while minimizing daily operational complexity.
+
+ A weak area for previous DNS specifications has been lack of detail
+ in specifying resolver behavior, leaving implementors largely on
+ their own to determine many details of resolver function. This,
+ combined with the number of iterations the DNSSEC spec has been
+ through, has resulted in fielded code with a wide variety of
+ behaviors. This variety makes it difficult to predict how a
+ protocol change will be handled by all deployed resolvers. The
+ risk that a change will cause unacceptable or even catastrophic
+ failures makes it difficult to design and deploy a protocol change.
+ One strategy for managing that risk is to structure protocol
+ changes so that existing resolvers can completely ignore input that
+ might confuse them or trigger undesirable failure modes.
+
+ This document addresses a specific problem caused by Delegation
+ Signer's [DS] introduction of new semantics for the NXT RR that are
+ incompatible with the semantics in RFC 2535 [RFC2535]. Answers
+ provided by DS-aware servers can trigger an unacceptable failure
+ mode in some resolvers that implement RFC 2535, which provides a
+ great disincentive to sign zones with DS. The changes defined in
+ this document allow for the incremental deployment of DS.
+
+1.1 Terminology
+
+ In this document, the term "unsecure delegation" means any
+ delegation for which no DS record appears at the parent. An
+ "unsecure referral" is an answer from the parent containing an NS
+ RRset and a proof that no DS record exists for that name.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+1.2 The Problem
+
+ Delegation Signer introduces new semantics for the NXT RR that are
+ incompatible with the semantics in RFC 2535. In RFC 2535, NXT
+ records were only required to be returned as part of a
+ non-existence proof. With DS, an unsecure referral returns, in
+ addition to the NS, a proof of non-existence of a DS RR in the form
+ of an NXT and SIG(NXT). RFC 2535 didn't specify how a resolver was
+ to interpret a response with both an NS and an NXT in the authority
+ section, RCODE=0, and AA=0. Some widely deployed 2535-aware
+ resolvers interpret any answer with an NXT as a proof of
+ non-existence of the requested record. This results in unsecure
+ delegations being invisible to 2535-aware resolvers and violates
+ the basic architectural principle that DNSSEC must do no harm --
+ the signing of zones must not prevent the resolution of unsecured
+ delegations.
+
+2. Possible Solutions
+
+ This section presents several solutions that were considered.
+ Section 3 describes the one selected.
+
+2.1. Change SIG, KEY, and NXT type codes
+
+ To avoid the problem described above, legacy (RFC2535-aware)
+ resolvers need to be kept from seeing unsecure referrals that
+ include NXT records in the authority section. The simplest way to
+ do that is to change the type codes for SIG, KEY, and NXT.
+
+ The obvious drawback to this is that new resolvers will not be able
+ to validate zones signed with the old RRs. This problem already
+ exists, however, because of the changes made by DS, and resolvers
+ that understand the old RRs (and have compatibility issues with DS)
+ are far more prevalent than 2535-signed zones.
+
+2.2. Change a subset of type codes
+
+ The observed problem with unsecure referrals could be addressed by
+ changing only the NXT type code or another subset of the type codes
+ that includes NXT. This has the virtue of apparent simplicity, but
+ it risks introducing new problems or not going far enough. It's
+ quite possible that more incompatibilities exist between DS and
+ earlier semantics. Legacy resolvers may also be confused by seeing
+ records they recognize (SIG and KEY) while being unable to find
+ NXTs. Although it may seem unnecessary to fix that which is not
+ obviously broken, it's far cleaner to change all of the type codes
+ at once. This will leave legacy resolvers and tools completely
+ blinded to DNSSEC -- they will see only unknown RRs.
+
+2.3. Replace the DO bit
+
+ Another way to keep legacy resolvers from ever seeing DNSSEC
+ records with DS semantics is to have authoritative servers only
+ send that data to DS-aware resolvers. It's been proposed that
+ assigning a new EDNS0 flag bit to signal DS-awareness (tentatively
+ called "DA"), and having authoritative servers send DNSSEC data
+ only in response to queries with the DA bit set, would accomplish
+ this. This bit would presumably supplant the DO bit described in
+ RFC 3225.
+
+ This solution is sufficient only if all 2535-aware resolvers zero
+ out EDNS0 flags that they don't understand. If one passed through
+ the DA bit unchanged, it would still see the new semantics, and it
+ would probably fail to see unsecure delegations. Since it's
+ impractical to know how every DNS implementation handles unknown
+ EDNS0 flags, this is not a universal solution. It could, though,
+ be considered in addition to changing the RR type codes.
+
+2.4. Increment the EDNS version
+
+ Another possible solution is to increment the EDNS version number
+ as defined in RFC 2671 [RFC2671], on the assumption that all
+ existing implementations will reject higher versions than they
+ support, and retain the DO bit as the signal for DNSSEC awareness.
+ This approach has not been tested.
+
+2.5. Do nothing
+
+ There is a large deployed base of DNS resolvers that understand
+ DNSSEC as defined by the standards track RFC 2535 and RFC 2065
+ and, due to under specification in those documents, interpret any
+ answer with an NXT as a non-existence proof. So long as that is
+ the case, zone owners will have a strong incentive to not sign any
+ zones that contain unsecure delegations, lest those delegations be
+ invisible to such a large installed base. This will dramatically
+ slow DNSSEC adoption.
+
+ Unfortunately, without signed zones there's no clear incentive for
+ operators of resolvers to upgrade their software to support the new
+ version of DNSSEC, as defined in [DS]. Historical data suggests
+ that resolvers are rarely upgraded, and that old nameserver code
+ never dies.
+
+ Rather than wait years for resolvers to be upgraded through natural
+ processes before signing zones with unsecure delegations,
+ addressing this problem with a protocol change will immediately
+ remove the disincentive for signing zones and allow widespread
+ deployment of DNSSEC.
+
+3. Protocol changes
+
+ This document changes the type codes of SIG, KEY, and NXT. This
+ approach is the cleanest and safest of those discussed above,
+ largely because the behavior of resolvers that receive unknown type
+ codes is well understood. This approach has also received the most
+ testing.
+
+ To avoid operational confusion, it's also necessary to change the
+ mnemonics for these RRs. DNSKEY will be the replacement for KEY,
+ with the mnemonic indicating that these keys are not for
+ application use, per [RFC3445]. RRSIG (Resource Record SIGnature)
+ will replace SIG, and NSEC (Next SECure) will replace NXT. These
+ new types completely replace the old types, except that SIG(0)
+ [RFC2931] and TKEY [RFC2930] will continue to use SIG and KEY.
+
+ The new types will have exactly the same syntax and semantics as
+ specified for SIG, KEY, and NXT in RFC 2535 and [DS] except for
+ the following:
+
+ 1) Consistent with [RFC3597], domain names embedded in
+ RRSIG and NSEC RRs MUST NOT be compressed,
+
+ 2) Embedded domain names in RRSIG and NSEC RRs are not downcased
+ for purposes of DNSSEC canonical form and ordering nor for
+ equality comparison, and
+
+ 3) An RRSIG with a type-covered field of zero has undefined
+ semantics. The meaning of such a resource record may only be
+ defined by IETF Standards Action.
+
+ If a resolver receives the old types, it SHOULD treat them as
+ unknown RRs and SHOULD NOT assign any special meaning to them or
+ give them any special treatment. It MUST NOT use them for DNSSEC
+ validations or other DNS operational decision making. For example,
+ a resolver MUST NOT use DNSKEYs to validate SIGs or use KEYs to
+ validate RRSIGs. If SIG, KEY, or NXT RRs are included in a zone,
+ they MUST NOT receive special treatment. As an example, if a SIG
+ is included in a signed zone, there MUST be an RRSIG for it.
+ Authoritative servers may wish to give error messages when loading
+ zones containing SIG or NXT records (KEY records may be included
+ for SIG(0) or TKEY).
+
+ As a clarification to previous documents, some positive responses,
+ particularly wildcard proofs and unsecure referrals, will contain
+ NSEC RRs. Resolvers MUST NOT treat answers with NSEC RRs as
+ negative answers merely because they contain an NSEC.
+
+4. IANA Considerations
+
+4.1 DNS Resource Record Types
+
+ This document updates the IANA registry for DNS Resource Record
+ Types by assigning types 46, 47, and 48 to the RRSIG, NSEC, and
+ DNSKEY RRs, respectively.
+
+ Types 24 and 25 (SIG and KEY) are retained for SIG(0) [RFC2931] and
+ TKEY [RFC2930] use only.
+
+ Type 30 (NXT) should be marked as Obsolete.
+
+4.2 DNS Security Algorithm Numbers
+
+ To allow zone signing (DNSSEC) and transaction security mechanisms
+ (SIG(0) and TKEY) to use different sets of algorithms, the existing
+ "DNS Security Algorithm Numbers" registry is modified to include
+ the applicability of each algorithm. Specifically, two new columns
+ are added to the registry, showing whether each algorithm may be
+ used for zone signing, transaction security mechanisms, or both.
+ Only algorithms usable for zone signing may be used in DNSKEY,
+ RRSIG, and DS RRs. Only algorithms usable for SIG(0) and/or TSIG
+ may be used in SIG and KEY RRs.
+
+ All currently defined algorithms remain usable for transaction
+ security mechanisms. Only RSA/SHA-1, DSA/SHA-1, and private
+ algorithms (types 253 and 254) may be used for zone signing. Note
+ that the registry does not contain the requirement level of each
+ algorithm, only whether or not an algorithm may be used for the
+ given purposes. For example, RSA/MD5, while allowed for
+ transaction security mechanisms, is NOT RECOMMENDED, per RFC3110.
+
+ Additionally, the presentation format algorithm mnemonics from
+ RFC2535 Section 7 are added to the registry. This document assigns
+ RSA/SHA-1 the mnemonic RSASHA1.
+
+ As before, assignment of new algorithms in this registry requires
+ IETF Standards Action. Additionally, modification of algorithm
+ mnemonics or applicability requires IETF Standards Action.
+ Documents defining a new algorithm must address the applicability
+ of the algorithm and should assign a presentation mnemonic to the
+ algorithm.
+
+4.3 DNSKEY Flags
+
+ Like the KEY resource record, DNSKEY contains a 16-bit flags field.
+ This document creates a new registry for the DNSKEY flags field.
+
+ Initially, this registry only contains an assignment for bit 7 (the
+ ZONE bit). Bits 0-6 and 8-15 are available for assignment by IETF
+ Standards Action.
+
+4.4 DNSKEY Protocol Octet
+
+ Like the KEY resource record, DNSKEY contains an eight bit protocol
+ field. The only defined value for this field is 3 (DNSSEC). No
+ other values are allowed, hence no IANA registry is needed for this
+ field.
+
+5. Security Considerations
+
+ The changes introduced here do not materially affect security.
+ The implications of trying to use both new and legacy types
+ together are not well understood, and attempts to do so would
+ probably lead to unintended and dangerous results.
+
+ Changing type codes will leave code paths in legacy resolvers that
+ are never exercised. Unexercised code paths are a frequent source
+ of security holes, largely because those code paths do not get
+ frequent scrutiny.
+
+ Doing nothing, as described in section 2.5, will slow DNSSEC
+ deployment. While this does not decrease security, it also fails
+ to increase it.
+
+6. Normative references
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [DS] Gudmundsson, O., "Delegation Signer Resource Record",
+ draft-ietf-dnsext-delegation-signer-15.txt, work in
+ progress, June 2003.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2931] Eastlake, D., "DNS Request and Transaction Signatures
+ (SIG(0)s)", RFC 2931, September 2000.
+
+ [RFC2930] Eastlake, D., "Secret Key Establishment for DNS (TKEY
+ RR)", RFC 2930, September 2000.
+
+ [RFC2536] Eastlake, D., "DSA KEYs and SIGs in the Domain Name
+ System (DNS)", RFC 2436, March 1999.
+
+ [RFC2539] Eastlake, D., "Storage of Diffie-Hellman Keys in the
+ Domain Name System (DNS)", RFC 2539, March 1999.
+
+ [RFC3110] Eastlake, D., "RSA/SHA-1 SIGs and RSA KEYs in the
+ Domain Name System (DNS)", RFC 3110, May 2001.
+
+7. Informative References
+
+ [RFC2065] Eastlake, D. and C. Kaufman, "Domain Name System Security
+ Extensions", RFC 2065, January 1997.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [RFC3225] Conrad, D., "Indicating Resolver Support of DNSSEC", RFC
+ 3225, December 2001.
+
+ [RFC2929] Eastlake, D., E. Brunner-Williams, and B. Manning,
+ "Domain Name System (DNS) IANA Considerations", BCP 42,
+ RFC 2929, September 2000.
+
+ [RFC3445] Massey, D., and S. Rose, "Limiting the Scope of the KEY
+ Resource Record (RR)", RFC 3445, December 2002.
+
+ [RFC3597] Gustafsson, A., "Handling of Unknown DNS Resource
+ Record (RR) Types", RFC 3597, September 2003.
+
+8. Acknowledgments
+
+ The changes introduced here and the analysis of alternatives had
+ many contributors. With apologies to anyone overlooked, those
+ include: Micheal Graff, John Ihren, Olaf Kolkman, Mark Kosters, Ed
+ Lewis, Bill Manning, and Suzanne Woolf.
+
+ Thanks to Jakob Schlyter and Mark Andrews for identifying the
+ incompatibility described in section 1.2.
+
+ In addition to the above, the author would like to thank Scott
+ Rose, Olafur Gudmundsson, and Sandra Murphy for their substantive
+ comments.
+
+9. Author's Address
+
+ Samuel Weiler
+ SPARTA, Inc.
+ 7075 Samuel Morse Drive
+ Columbia, MD 21046
+ USA
+ weiler@tislabs.com
+
diff --git a/doc/draft/draft-ietf-dnsext-dnssec-bis-updates-01.txt b/doc/draft/draft-ietf-dnsext-dnssec-bis-updates-01.txt
new file mode 100644
index 0000000..3a800f9
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-dnssec-bis-updates-01.txt
@@ -0,0 +1,616 @@
+
+
+
+Network Working Group S. Weiler
+Internet-Draft SPARTA, Inc
+Updates: 4034, 4035 (if approved) May 23, 2005
+Expires: November 24, 2005
+
+
+ Clarifications and Implementation Notes for DNSSECbis
+ draft-ietf-dnsext-dnssec-bis-updates-01
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on November 24, 2005.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document is a collection of minor technical clarifications to
+ the DNSSECbis document set. It is meant to serve as a resource to
+ implementors as well as an interim repository of possible DNSSECbis
+ errata.
+
+
+
+
+
+
+
+Weiler Expires November 24, 2005 [Page 1]
+
+Internet-Draft DNSSECbis Implementation Notes May 2005
+
+
+Proposed additions in future versions
+
+ An index sorted by the section of DNSSECbis being clarified.
+
+ A list of proposed protocol changes being made in other documents,
+ such as NSEC3 and Epsilon. This document would not make those
+ changes, merely provide an index into the documents that are making
+ changes.
+
+Changes between -00 and -01
+
+ Document significantly restructured.
+
+ Added section on QTYPE=ANY.
+
+Changes between personal submission and first WG draft
+
+ Added Section 2.1 based on namedroppers discussions from March 9-10,
+ 2005.
+
+ Added Section 3.4, Section 3.3, Section 4.3, and Section 2.2.
+
+ Added the DNSSECbis RFC numbers.
+
+ Figured out the confusion in Section 4.1.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Weiler Expires November 24, 2005 [Page 2]
+
+Internet-Draft DNSSECbis Implementation Notes May 2005
+
+
+Table of Contents
+
+ 1. Introduction and Terminology . . . . . . . . . . . . . . . . . 4
+ 1.1 Structure of this Document . . . . . . . . . . . . . . . . 4
+ 1.2 Terminology . . . . . . . . . . . . . . . . . . . . . . . 4
+ 2. Significant Concerns . . . . . . . . . . . . . . . . . . . . . 4
+ 2.1 Clarifications on Non-Existence Proofs . . . . . . . . . . 4
+ 2.2 Empty Non-Terminal Proofs . . . . . . . . . . . . . . . . 5
+ 2.3 Validating Responses to an ANY Query . . . . . . . . . . . 5
+ 3. Interoperability Concerns . . . . . . . . . . . . . . . . . . 5
+ 3.1 Unknown DS Message Digest Algorithms . . . . . . . . . . . 5
+ 3.2 Private Algorithms . . . . . . . . . . . . . . . . . . . . 6
+ 3.3 Caution About Local Policy and Multiple RRSIGs . . . . . . 6
+ 3.4 Key Tag Calculation . . . . . . . . . . . . . . . . . . . 7
+ 4. Minor Corrections and Clarifications . . . . . . . . . . . . . 7
+ 4.1 Finding Zone Cuts . . . . . . . . . . . . . . . . . . . . 7
+ 4.2 Clarifications on DNSKEY Usage . . . . . . . . . . . . . . 7
+ 4.3 Errors in Examples . . . . . . . . . . . . . . . . . . . . 8
+ 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 8
+ 6. Security Considerations . . . . . . . . . . . . . . . . . . . 8
+ 7. References . . . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 7.1 Normative References . . . . . . . . . . . . . . . . . . . 8
+ 7.2 Informative References . . . . . . . . . . . . . . . . . . 9
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . 9
+ A. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 9
+ Intellectual Property and Copyright Statements . . . . . . . . 11
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Weiler Expires November 24, 2005 [Page 3]
+
+Internet-Draft DNSSECbis Implementation Notes May 2005
+
+
+1. Introduction and Terminology
+
+ This document lists some minor clarifications and corrections to
+ DNSSECbis, as described in [1], [2], and [3].
+
+ It is intended to serve as a resource for implementors and as a
+ repository of items that need to be addressed when advancing the
+ DNSSECbis documents from Proposed Standard to Draft Standard.
+
+ In this version (-01 of the WG document), feedback is particularly
+ solicited on the structure of the document and whether the text in
+ the recently added sections is correct and sufficient.
+
+ Proposed substantive additions to this document should be sent to the
+ namedroppers mailing list as well as to the editor of this document.
+ The editor would greatly prefer text suitable for direct inclusion in
+ this document.
+
+1.1 Structure of this Document
+
+ The clarifications to DNSSECbis are sorted according to the editor's
+ impression of their importance, starting with ones which could, if
+ ignored, lead to security and stability problems and progressing down
+ to clarifications that are likely to have little operational impact.
+ Mere typos and awkward phrasings are not addressed unless they could
+ lead to misinterpretation of the DNSSECbis documents.
+
+1.2 Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [4].
+
+2. Significant Concerns
+
+ This section provides clarifications that, if overlooked, could lead
+ to security issues or major interoperability problems.
+
+2.1 Clarifications on Non-Existence Proofs
+
+ RFC4035 Section 5.4 slightly underspecifies the algorithm for
+ checking non-existence proofs. In particular, the algorithm there
+ might incorrectly allow the NSEC from the parent side of a zone cut
+ to prove the non-existence of either other RRs at that name in the
+ child zone or other names in the child zone. It might also allow a
+ NSEC at the same name as a DNAME to prove the non-existence of names
+ beneath that DNAME.
+
+
+
+
+Weiler Expires November 24, 2005 [Page 4]
+
+Internet-Draft DNSSECbis Implementation Notes May 2005
+
+
+ A parent-side delegation NSEC (one with the NS bit set, but no SOA
+ bit set, and with a singer field that's shorter than the owner name)
+ must not be used to assume non-existence of any RRs below that zone
+ cut (both RRs at that ownername and at ownernames with more leading
+ labels, no matter their content). Similarly, an NSEC with the DNAME
+ bit set must not be used to assume the non-existence of any
+ descendant of that NSEC's owner name.
+
+2.2 Empty Non-Terminal Proofs
+
+ To be written, based on Roy Arends' May 11th message to namedroppers.
+
+2.3 Validating Responses to an ANY Query
+
+ RFC4035 does not address now to validate responses when QTYPE=*. As
+ described in Section 6.2.2 of RFC1034, a proper response to QTYPE=*
+ may include a subset of the RRsets at a given name -- it is not
+ necessary to include all RRsets at the QNAME in the response.
+
+ When validating a response to QTYPE=*, validate all received RRsets
+ that match QNAME and QCLASS. If any of those RRsets fail validation,
+ treat the answer as Bogus. If there are no RRsets matching QNAME and
+ QCLASS, validate that fact using the rules in RFC4035 Section 5.4 (as
+ clarified in this document). To be clear, a validator must not
+ insist on receiving all records at the QNAME in response to QTYPE=*.
+
+3. Interoperability Concerns
+
+3.1 Unknown DS Message Digest Algorithms
+
+ Section 5.2 of RFC4035 includes rules for how to handle delegations
+ to zones that are signed with entirely unsupported algorithms, as
+ indicated by the algorithms shown in those zone's DS RRsets. It does
+ not explicitly address how to handle DS records that use unsupported
+ message digest algorithms. In brief, DS records using unknown or
+ unsupported message digest algorithms MUST be treated the same way as
+ DS records referring to DNSKEY RRs of unknown or unsupported
+ algorithms.
+
+ The existing text says:
+
+ If the validator does not support any of the algorithms listed
+ in an authenticated DS RRset, then the resolver has no supported
+ authentication path leading from the parent to the child. The
+ resolver should treat this case as it would the case of an
+ authenticated NSEC RRset proving that no DS RRset exists, as
+ described above.
+
+
+
+
+Weiler Expires November 24, 2005 [Page 5]
+
+Internet-Draft DNSSECbis Implementation Notes May 2005
+
+
+ To paraphrase the above, when determining the security status of a
+ zone, a validator discards (for this purpose only) any DS records
+ listing unknown or unsupported algorithms. If none are left, the
+ zone is treated as if it were unsigned.
+
+ Modified to consider DS message digest algorithms, a validator also
+ discards any DS records using unknown or unsupported message digest
+ algorithms.
+
+3.2 Private Algorithms
+
+ As discussed above, section 5.2 of RFC4035 requires that validators
+ make decisions about the security status of zones based on the public
+ key algorithms shown in the DS records for those zones. In the case
+ of private algorithms, as described in RFC4034 Appendix A.1.1, the
+ eight-bit algorithm field in the DS RR is not conclusive about what
+ algorithm(s) is actually in use.
+
+ If no private algorithms appear in the DS set or if any supported
+ algorithm appears in the DS set, no special processing will be
+ needed. In the remaining cases, the security status of the zone
+ depends on whether or not the resolver supports any of the private
+ algorithms in use (provided that these DS records use supported hash
+ functions, as discussed in Section 3.1). In these cases, the
+ resolver MUST retrieve the corresponding DNSKEY for each private
+ algorithm DS record and examine the public key field to determine the
+ algorithm in use. The security-aware resolver MUST ensure that the
+ hash of the DNSKEY RR's owner name and RDATA matches the digest in
+ the DS RR. If they do not match, and no other DS establishes that
+ the zone is secure, the referral should be considered BAD data, as
+ discussed in RFC4035.
+
+ This clarification facilitates the broader use of private algorithms,
+ as suggested by [5].
+
+3.3 Caution About Local Policy and Multiple RRSIGs
+
+ When multiple RRSIGs cover a given RRset, RFC4035 Section 5.3.3
+ suggests that "the local resolver security policy determines whether
+ the resolver also has to test these RRSIG RRs and how to resolve
+ conflicts if these RRSIG RRs lead to differing results." In most
+ cases, a resolver would be well advised to accept any valid RRSIG as
+ sufficient. If the first RRSIG tested fails validation, a resolver
+ would be well advised to try others, giving a successful validation
+ result if any can be validated and giving a failure only if all
+ RRSIGs fail validation.
+
+ If a resolver adopts a more restrictive policy, there's a danger that
+
+
+
+Weiler Expires November 24, 2005 [Page 6]
+
+Internet-Draft DNSSECbis Implementation Notes May 2005
+
+
+ properly-signed data might unnecessarily fail validation, perhaps
+ because of cache timing issues. Furthermore, certain zone management
+ techniques, like the Double Signature Zone-signing Key Rollover
+ method described in section 4.2.1.2 of [6] might not work reliably.
+
+3.4 Key Tag Calculation
+
+ RFC4034 Appendix B.1 incorrectly defines the Key Tag field
+ calculation for algorithm 1. It correctly says that the Key Tag is
+ the most significant 16 of the least significant 24 bits of the
+ public key modulus. However, RFC4034 then goes on to incorrectly say
+ that this is 4th to last and 3rd to last octets of the public key
+ modulus. It is, in fact, the 3rd to last and 2nd to last octets.
+
+4. Minor Corrections and Clarifications
+
+4.1 Finding Zone Cuts
+
+ Appendix C.8 of RFC4035 discusses sending DS queries to the servers
+ for a parent zone. To do that, a resolver may first need to apply
+ special rules to discover what those servers are.
+
+ As explained in Section 3.1.4.1 of RFC4035, security-aware name
+ servers need to apply special processing rules to handle the DS RR,
+ and in some situations the resolver may also need to apply special
+ rules to locate the name servers for the parent zone if the resolver
+ does not already have the parent's NS RRset. Section 4.2 of RFC4035
+ specifies a mechanism for doing that.
+
+4.2 Clarifications on DNSKEY Usage
+
+ Questions of the form "can I use a different DNSKEY for signing the
+ X" have occasionally arisen.
+
+ The short answer is "yes, absolutely". You can even use a different
+ DNSKEY for each RRset in a zone, subject only to practical limits on
+ the size of the DNSKEY RRset. However, be aware that there is no way
+ to tell resolvers what a particularly DNSKEY is supposed to be used
+ for -- any DNSKEY in the zone's signed DNSKEY RRset may be used to
+ authenticate any RRset in the zone. For example, if a weaker or less
+ trusted DNSKEY is being used to authenticate NSEC RRsets or all
+ dynamically updated records, that same DNSKEY can also be used to
+ sign any other RRsets from the zone.
+
+ Furthermore, note that the SEP bit setting has no effect on how a
+ DNSKEY may be used -- the validation process is specifically
+ prohibited from using that bit by RFC4034 section 2.1.2. It possible
+ to use a DNSKEY without the SEP bit set as the sole secure entry
+
+
+
+Weiler Expires November 24, 2005 [Page 7]
+
+Internet-Draft DNSSECbis Implementation Notes May 2005
+
+
+ point to the zone, yet use a DNSKEY with the SEP bit set to sign all
+ RRsets in the zone (other than the DNSKEY RRset). It's also possible
+ to use a single DNSKEY, with or without the SEP bit set, to sign the
+ entire zone, including the DNSKEY RRset itself.
+
+4.3 Errors in Examples
+
+ The text in RFC4035 Section C.1 refers to the examples in B.1 as
+ "x.w.example.com" while B.1 uses "x.w.example". This is painfully
+ obvious in the second paragraph where it states that the RRSIG labels
+ field value of 3 indicates that the answer was not the result of
+ wildcard expansion. This is true for "x.w.example" but not for
+ "x.w.example.com", which of course has a label count of 4
+ (antithetically, a label count of 3 would imply the answer was the
+ result of a wildcard expansion).
+
+ The first paragraph of RFC4035 Section C.6 also has a minor error:
+ the reference to "a.z.w.w.example" should instead be "a.z.w.example",
+ as in the previous line.
+
+5. IANA Considerations
+
+ This document specifies no IANA Actions.
+
+6. Security Considerations
+
+ This document does not make fundamental changes to the DNSSEC
+ protocol, as it was generally understood when DNSSECbis was
+ published. It does, however, address some ambiguities and omissions
+ in those documents that, if not recognized and addressed in
+ implementations, could lead to security failures. In particular, the
+ validation algorithm clarifications in Section 2 are critical for
+ preserving the security properties DNSSEC offers. Furthermore,
+ failure to address some of the interoperability concerns in Section 3
+ could limit the ability to later change or expand DNSSEC, including
+ by adding new algorithms.
+
+7. References
+
+7.1 Normative References
+
+ [1] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033,
+ March 2005.
+
+ [2] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+
+
+Weiler Expires November 24, 2005 [Page 8]
+
+Internet-Draft DNSSECbis Implementation Notes May 2005
+
+
+ [3] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Protocol Modifications for the DNS Security Extensions",
+ RFC 4035, March 2005.
+
+ [4] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+7.2 Informative References
+
+ [5] Blacka, D., "DNSSEC Experiments",
+ draft-blacka-dnssec-experiments-00 (work in progress),
+ December 2004.
+
+ [6] Gieben, R. and O. Kolkman, "DNSSEC Operational Practices",
+ draft-ietf-dnsop-dnssec-operational-practices-04 (work in
+ progress), May 2005.
+
+
+Author's Address
+
+ Samuel Weiler
+ SPARTA, Inc
+ 7075 Samuel Morse Drive
+ Columbia, Maryland 21046
+ US
+
+ Email: weiler@tislabs.com
+
+Appendix A. Acknowledgments
+
+ The editor is extremely grateful to those who, in addition to finding
+ errors and omissions in the DNSSECbis document set, have provided
+ text suitable for inclusion in this document.
+
+ The lack of specificity about handling private algorithms, as
+ described in Section 3.2, and the lack of specificity in handling ANY
+ queries, as described in Section 2.3, were discovered by David
+ Blacka.
+
+ The error in algorithm 1 key tag calculation, as described in
+ Section 3.4, was found by Abhijit Hayatnagarkar. Donald Eastlake
+ contributed text for Section 3.4.
+
+ The bug relating to delegation NSEC RR's in Section 2.1 was found by
+ Roy Badami. Roy Arends found the related problem with DNAME.
+
+ The errors in the RFC4035 examples were found by Roy Arends, who also
+ contributed text for Section 4.3 of this document.
+
+
+
+Weiler Expires November 24, 2005 [Page 9]
+
+Internet-Draft DNSSECbis Implementation Notes May 2005
+
+
+ The editor would like to thank Olafur Gudmundsson and Scott Rose for
+ their substantive comments on the text of this document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Weiler Expires November 24, 2005 [Page 10]
+
+Internet-Draft DNSSECbis Implementation Notes May 2005
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2005). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Weiler Expires November 24, 2005 [Page 11]
+
diff --git a/doc/draft/draft-ietf-dnsext-dnssec-experiments-03.txt b/doc/draft/draft-ietf-dnsext-dnssec-experiments-03.txt
new file mode 100644
index 0000000..c8db709
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-dnssec-experiments-03.txt
@@ -0,0 +1,840 @@
+
+
+
+DNSEXT D. Blacka
+Internet-Draft VeriSign, Inc.
+Intended status: Standards Track April 7, 2006
+Expires: October 9, 2006
+
+
+ DNSSEC Experiments
+ draft-ietf-dnsext-dnssec-experiments-03
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on October 9, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 1]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+Abstract
+
+ This document describes a methodology for deploying alternate, non-
+ backwards-compatible, DNSSEC methodologies in an experimental fashion
+ without disrupting the deployment of standard DNSSEC.
+
+
+Table of Contents
+
+ 1. Definitions and Terminology . . . . . . . . . . . . . . . . . 3
+ 2. Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 3. Experiments . . . . . . . . . . . . . . . . . . . . . . . . . 5
+ 4. Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 5. Defining an Experiment . . . . . . . . . . . . . . . . . . . . 8
+ 6. Considerations . . . . . . . . . . . . . . . . . . . . . . . . 9
+ 7. Use in Non-Experiments . . . . . . . . . . . . . . . . . . . . 10
+ 8. Security Considerations . . . . . . . . . . . . . . . . . . . 11
+ 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 12
+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . . 13
+ 10.1. Normative References . . . . . . . . . . . . . . . . . . 13
+ 10.2. Informative References . . . . . . . . . . . . . . . . . 13
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 14
+ Intellectual Property and Copyright Statements . . . . . . . . . . 15
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 2]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+1. Definitions and Terminology
+
+ Throughout this document, familiarity with the DNS system (RFC 1035
+ [5]) and the DNS security extensions ([2], [3], and [4] is assumed.
+
+ The key words "MUST, "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY, and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [1].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 3]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+2. Overview
+
+ Historically, experimentation with DNSSEC alternatives has been a
+ problematic endeavor. There has typically been a desire to both
+ introduce non-backwards-compatible changes to DNSSEC and to try these
+ changes on real zones in the public DNS. This creates a problem when
+ the change to DNSSEC would make all or part of the zone using those
+ changes appear bogus (bad) or otherwise broken to existing security-
+ aware resolvers.
+
+ This document describes a standard methodology for setting up DNSSEC
+ experiments. This methodology addresses the issue of co-existence
+ with standard DNSSEC and DNS by using unknown algorithm identifiers
+ to hide the experimental DNSSEC protocol modifications from standard
+ security-aware resolvers.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 4]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+3. Experiments
+
+ When discussing DNSSEC experiments, it is necessary to classify these
+ experiments into two broad categories:
+
+ Backwards-Compatible: describes experimental changes that, while not
+ strictly adhering to the DNSSEC standard, are nonetheless
+ interoperable with clients and servers that do implement the
+ DNSSEC standard.
+
+ Non-Backwards-Compatible: describes experiments that would cause a
+ standard security-aware resolver to (incorrectly) determine that
+ all or part of a zone is bogus, or to otherwise not interoperate
+ with standard DNSSEC clients and servers.
+
+ Not included in these terms are experiments with the core DNS
+ protocol itself.
+
+ The methodology described in this document is not necessary for
+ backwards-compatible experiments, although it certainly may be used
+ if desired.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 5]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+4. Method
+
+ The core of the methodology is the use of strictly unknown algorithm
+ identifiers when signing the experimental zone, and more importantly,
+ having only unknown algorithm identifiers in the DS records for the
+ delegation to the zone at the parent.
+
+ This technique works because of the way DNSSEC-compliant validators
+ are expected to work in the presence of a DS set with only unknown
+ algorithm identifiers. From [4], Section 5.2:
+
+ If the validator does not support any of the algorithms listed in
+ an authenticated DS RRset, then the resolver has no supported
+ authentication path leading from the parent to the child. The
+ resolver should treat this case as it would the case of an
+ authenticated NSEC RRset proving that no DS RRset exists, as
+ described above.
+
+ And further:
+
+ If the resolver does not support any of the algorithms listed in
+ an authenticated DS RRset, then the resolver will not be able to
+ verify the authentication path to the child zone. In this case,
+ the resolver SHOULD treat the child zone as if it were unsigned.
+
+ While this behavior isn't strictly mandatory (as marked by MUST), it
+ is likely that a validator would implement this behavior, or, more to
+ the point, it would handle this situation in a safe way (see below
+ (Section 6).)
+
+ Because we are talking about experiments, it is RECOMMENDED that
+ private algorithm numbers be used (see [3], appendix A.1.1. Note
+ that secure handling of private algorithms requires special handing
+ by the validator logic. See [6] for further details.) Normally,
+ instead of actually inventing new signing algorithms, the recommended
+ path is to create alternate algorithm identifiers that are aliases
+ for the existing, known algorithms. While, strictly speaking, it is
+ only necessary to create an alternate identifier for the mandatory
+ algorithms, it is suggested that all optional defined algorithms be
+ aliased as well.
+
+ It is RECOMMENDED that for a particular DNSSEC experiment, a
+ particular domain name base is chosen for all new algorithms, then
+ the algorithm number (or name) is prepended to it. For example, for
+ experiment A, the base name of "dnssec-experiment-a.example.com" is
+ chosen. Then, aliases for algorithms 3 (DSA) and 5 (RSASHA1) are
+ defined to be "3.dnssec-experiment-a.example.com" and
+ "5.dnssec-experiment-a.example.com". However, any unique identifier
+
+
+
+Blacka Expires October 9, 2006 [Page 6]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+ will suffice.
+
+ Using this method, resolvers (or, more specifically, DNSSEC
+ validators) essentially indicate their ability to understand the
+ DNSSEC experiment's semantics by understanding what the new algorithm
+ identifiers signify.
+
+ This method creates two classes of security-aware servers and
+ resolvers: servers and resolvers that are aware of the experiment
+ (and thus recognize the experiment's algorithm identifiers and
+ experimental semantics), and servers and resolvers that are unaware
+ of the experiment.
+
+ This method also precludes any zone from being both in an experiment
+ and in a classic DNSSEC island of security. That is, a zone is
+ either in an experiment and only experimentally validatable, or it is
+ not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 7]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+5. Defining an Experiment
+
+ The DNSSEC experiment MUST define the particular set of (previously
+ unknown) algorithm identifiers that identify the experiment, and
+ define what each unknown algorithm identifier means. Typically,
+ unless the experiment is actually experimenting with a new DNSSEC
+ algorithm, this will be a mapping of private algorithm identifiers to
+ existing, known algorithms.
+
+ Normally the experiment will choose a DNS name as the algorithm
+ identifier base. This DNS name SHOULD be under the control of the
+ authors of the experiment. Then the experiment will define a mapping
+ between known mandatory and optional algorithms into this private
+ algorithm identifier space. Alternately, the experiment MAY use the
+ OID private algorithm space instead (using algorithm number 254), or
+ MAY choose non-private algorithm numbers, although this would require
+ an IANA allocation.
+
+ For example, an experiment might specify in its description the DNS
+ name "dnssec-experiment-a.example.com" as the base name, and declare
+ that "3.dnssec-experiment-a.example.com" is an alias of DNSSEC
+ algorithm 3 (DSA), and that "5.dnssec-experiment-a.example.com" is an
+ alias of DNSSEC algorithm 5 (RSASHA1).
+
+ Resolvers MUST only recognize the experiment's semantics when present
+ in a zone signed by one or more of these algorithm identifiers. This
+ is necessary to isolate the semantics of one experiment from any
+ others that the resolver might understand.
+
+ In general, resolvers involved in the experiment are expected to
+ understand both standard DNSSEC and the defined experimental DNSSEC
+ protocol, although this isn't required.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 8]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+6. Considerations
+
+ There are a number of considerations with using this methodology.
+
+ 1. Under some circumstances, it may be that the experiment will not
+ be sufficiently masked by this technique and may cause resolution
+ problem for resolvers not aware of the experiment. For instance,
+ the resolver may look at a non-validatable response and conclude
+ that the response is bogus, either due to local policy or
+ implementation details. This is not expected to be a common
+ case, however.
+
+ 2. It will not be possible for security-aware resolvers unaware of
+ the experiment to build a chain of trust through an experimental
+ zone.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 9]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+7. Use in Non-Experiments
+
+ This general methodology MAY be used for non-backwards compatible
+ DNSSEC protocol changes that start out as or become standards. In
+ this case:
+
+ o The protocol change SHOULD use public IANA allocated algorithm
+ identifiers instead of private algorithm identifiers. This will
+ help identify the protocol change as a standard, rather than an
+ experiment.
+
+ o Resolvers MAY recognize the protocol change in zones not signed
+ (or not solely signed) using the new algorithm identifiers.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 10]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+8. Security Considerations
+
+ Zones using this methodology will be considered insecure by all
+ resolvers except those aware of the experiment. It is not generally
+ possible to create a secure delegation from an experimental zone that
+ will be followed by resolvers unaware of the experiment.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 11]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+9. IANA Considerations
+
+ This document has no IANA actions.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 12]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+10. References
+
+10.1. Normative References
+
+ [1] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [2] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033,
+ March 2005.
+
+ [3] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+ [4] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Protocol Modifications for the DNS Security Extensions",
+ RFC 4035, March 2005.
+
+10.2. Informative References
+
+ [5] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [6] Austein, R. and S. Weiler, "Clarifications and Implementation
+ Notes for DNSSECbis", draft-ietf-dnsext-dnssec-bis-updates-02
+ (work in progress), January 2006.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 13]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+Author's Address
+
+ David Blacka
+ VeriSign, Inc.
+ 21355 Ridgetop Circle
+ Dulles, VA 20166
+ US
+
+ Phone: +1 703 948 3200
+ Email: davidb@verisign.com
+ URI: http://www.verisignlabs.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 14]
+
+Internet-Draft DNSSEC Experiments April 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+Blacka Expires October 9, 2006 [Page 15]
+
diff --git a/doc/draft/draft-ietf-dnsext-dnssec-online-signing-02.txt b/doc/draft/draft-ietf-dnsext-dnssec-online-signing-02.txt
new file mode 100644
index 0000000..7503c66
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-dnssec-online-signing-02.txt
@@ -0,0 +1,616 @@
+
+
+
+Network Working Group S. Weiler
+Internet-Draft SPARTA, Inc
+Updates: 4034, 4035 (if approved) J. Ihren
+Expires: July 24, 2006 Autonomica AB
+ January 20, 2006
+
+
+ Minimally Covering NSEC Records and DNSSEC On-line Signing
+ draft-ietf-dnsext-dnssec-online-signing-02
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on July 24, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ This document describes how to construct DNSSEC NSEC resource records
+ that cover a smaller range of names than called for by RFC4034. By
+ generating and signing these records on demand, authoritative name
+ servers can effectively stop the disclosure of zone contents
+ otherwise made possible by walking the chain of NSEC records in a
+ signed zone.
+
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 1]
+
+Internet-Draft NSEC Epsilon January 2006
+
+
+Changes from ietf-01 to ietf-02
+
+ Clarified that a generated NSEC RR's type bitmap MUST have the RRSIG
+ and NSEC bits set, to be consistent with DNSSECbis -- previous text
+ said SHOULD.
+
+ Made the applicability statement a little less oppressive.
+
+Changes from ietf-00 to ietf-01
+
+ Added an applicability statement, making reference to ongoing work on
+ NSEC3.
+
+ Added the phrase "epsilon functions", which has been commonly used to
+ describe the technique and already appeared in the header of each
+ page, in place of "increment and decrement functions". Also added an
+ explanatory sentence.
+
+ Corrected references from 4034 section 6.2 to section 6.1.
+
+ Fixed an out-of-date reference to [-bis] and other typos.
+
+ Replaced IANA Considerations text.
+
+ Escaped close parentheses in examples.
+
+ Added some more acknowledgements.
+
+Changes from weiler-01 to ietf-00
+
+ Inserted RFC numbers for 4033, 4034, and 4035.
+
+ Specified contents of bitmap field in synthesized NSEC RR's, pointing
+ out that this relaxes a constraint in 4035. Added 4035 to the
+ Updates header.
+
+Changes from weiler-00 to weiler-01
+
+ Clarified that this updates RFC4034 by relaxing requirements on the
+ next name field.
+
+ Added examples covering wildcard names.
+
+ In the 'better functions' section, reiterated that perfect functions
+ aren't needed.
+
+ Added a reference to RFC 2119.
+
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 2]
+
+Internet-Draft NSEC Epsilon January 2006
+
+
+Table of Contents
+
+ 1. Introduction and Terminology . . . . . . . . . . . . . . . . . 4
+ 2. Applicability of This Technique . . . . . . . . . . . . . . . 4
+ 3. Minimally Covering NSEC Records . . . . . . . . . . . . . . . 5
+ 4. Better Epsilon Functions . . . . . . . . . . . . . . . . . . . 6
+ 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 7
+ 6. Security Considerations . . . . . . . . . . . . . . . . . . . 7
+ 7. Normative References . . . . . . . . . . . . . . . . . . . . . 8
+ Appendix A. Acknowledgments . . . . . . . . . . . . . . . . . . . 8
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 10
+ Intellectual Property and Copyright Statements . . . . . . . . . . 11
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 3]
+
+Internet-Draft NSEC Epsilon January 2006
+
+
+1. Introduction and Terminology
+
+ With DNSSEC [1], an NSEC record lists the next instantiated name in
+ its zone, proving that no names exist in the "span" between the
+ NSEC's owner name and the name in the "next name" field. In this
+ document, an NSEC record is said to "cover" the names between its
+ owner name and next name.
+
+ Through repeated queries that return NSEC records, it is possible to
+ retrieve all of the names in the zone, a process commonly called
+ "walking" the zone. Some zone owners have policies forbidding zone
+ transfers by arbitrary clients; this side-effect of the NSEC
+ architecture subverts those policies.
+
+ This document presents a way to prevent zone walking by constructing
+ NSEC records that cover fewer names. These records can make zone
+ walking take approximately as many queries as simply asking for all
+ possible names in a zone, making zone walking impractical. Some of
+ these records must be created and signed on demand, which requires
+ on-line private keys. Anyone contemplating use of this technique is
+ strongly encouraged to review the discussion of the risks of on-line
+ signing in Section 6.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [4].
+
+
+2. Applicability of This Technique
+
+ The technique presented here may be useful to a zone owner that wants
+ to use DNSSEC, is concerned about exposure of its zone contents via
+ zone walking, and is willing to bear the costs of on-line signing.
+
+ As discussed in Section 6, on-line signing has several security
+ risks, including an increased likelihood of private keys being
+ disclosed and an increased risk of denial of service attack. Anyone
+ contemplating use of this technique is strongly encouraged to review
+ the discussion of the risks of on-line signing in Section 6.
+
+ Furthermore, at the time this document was published, the DNSEXT
+ working group was actively working on a mechanism to prevent zone
+ walking that does not require on-line signing (tentatively called
+ NSEC3). The new mechanism is likely to expose slightly more
+ information about the zone than this technique (e.g. the number of
+ instantiated names), but it may be preferable to this technique.
+
+
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 4]
+
+Internet-Draft NSEC Epsilon January 2006
+
+
+3. Minimally Covering NSEC Records
+
+ This mechanism involves changes to NSEC records for instantiated
+ names, which can still be generated and signed in advance, as well as
+ the on-demand generation and signing of new NSEC records whenever a
+ name must be proven not to exist.
+
+ In the 'next name' field of instantiated names' NSEC records, rather
+ than list the next instantiated name in the zone, list any name that
+ falls lexically after the NSEC's owner name and before the next
+ instantiated name in the zone, according to the ordering function in
+ RFC4034 [2] section 6.1. This relaxes the requirement in section
+ 4.1.1 of RFC4034 that the 'next name' field contains the next owner
+ name in the zone. This change is expected to be fully compatible
+ with all existing DNSSEC validators. These NSEC records are returned
+ whenever proving something specifically about the owner name (e.g.
+ that no resource records of a given type appear at that name).
+
+ Whenever an NSEC record is needed to prove the non-existence of a
+ name, a new NSEC record is dynamically produced and signed. The new
+ NSEC record has an owner name lexically before the QNAME but
+ lexically following any existing name and a 'next name' lexically
+ following the QNAME but before any existing name.
+
+ The generated NSEC record's type bitmap MUST have the RRSIG and NSEC
+ bits set and SHOULD NOT have any other bits set. This relaxes the
+ requirement in Section 2.3 of RFC4035 that NSEC RRs not appear at
+ names that did not exist before the zone was signed.
+
+ The functions to generate the lexically following and proceeding
+ names need not be perfect nor consistent, but the generated NSEC
+ records must not cover any existing names. Furthermore, this
+ technique works best when the generated NSEC records cover as few
+ names as possible. In this document, the functions that generate the
+ nearby names are called 'epsilon' functions, a reference to the
+ mathematical convention of using the greek letter epsilon to
+ represent small deviations.
+
+ An NSEC record denying the existence of a wildcard may be generated
+ in the same way. Since the NSEC record covering a non-existent
+ wildcard is likely to be used in response to many queries,
+ authoritative name servers using the techniques described here may
+ want to pregenerate or cache that record and its corresponding RRSIG.
+
+ For example, a query for an A record at the non-instantiated name
+ example.com might produce the following two NSEC records, the first
+ denying the existence of the name example.com and the second denying
+ the existence of a wildcard:
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 5]
+
+Internet-Draft NSEC Epsilon January 2006
+
+
+ exampld.com 3600 IN NSEC example-.com ( RRSIG NSEC )
+
+ \).com 3600 IN NSEC +.com ( RRSIG NSEC )
+
+ Before answering a query with these records, an authoritative server
+ must test for the existence of names between these endpoints. If the
+ generated NSEC would cover existing names (e.g. exampldd.com or
+ *bizarre.example.com), a better epsilon function may be used or the
+ covered name closest to the QNAME could be used as the NSEC owner
+ name or next name, as appropriate. If an existing name is used as
+ the NSEC owner name, that name's real NSEC record MUST be returned.
+ Using the same example, assuming an exampldd.com delegation exists,
+ this record might be returned from the parent:
+
+ exampldd.com 3600 IN NSEC example-.com ( NS DS RRSIG NSEC )
+
+ Like every authoritative record in the zone, each generated NSEC
+ record MUST have corresponding RRSIGs generated using each algorithm
+ (but not necessarily each DNSKEY) in the zone's DNSKEY RRset, as
+ described in RFC4035 [3] section 2.2. To minimize the number of
+ signatures that must be generated, a zone may wish to limit the
+ number of algorithms in its DNSKEY RRset.
+
+
+4. Better Epsilon Functions
+
+ Section 6.1 of RFC4034 defines a strict ordering of DNS names.
+ Working backwards from that definition, it should be possible to
+ define epsilon functions that generate the immediately following and
+ preceding names, respectively. This document does not define such
+ functions. Instead, this section presents functions that come
+ reasonably close to the perfect ones. As described above, an
+ authoritative server should still ensure than no generated NSEC
+ covers any existing name.
+
+ To increment a name, add a leading label with a single null (zero-
+ value) octet.
+
+ To decrement a name, decrement the last character of the leftmost
+ label, then fill that label to a length of 63 octets with octets of
+ value 255. To decrement a null (zero-value) octet, remove the octet
+ -- if an empty label is left, remove the label. Defining this
+ function numerically: fill the left-most label to its maximum length
+ with zeros (numeric, not ASCII zeros) and subtract one.
+
+ In response to a query for the non-existent name foo.example.com,
+ these functions produce NSEC records of:
+
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 6]
+
+Internet-Draft NSEC Epsilon January 2006
+
+
+ fon\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255.example.com 3600 IN NSEC \000.foo.example.com ( NSEC RRSIG )
+
+ \)\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255.example.com 3600 IN NSEC \000.*.example.com ( NSEC RRSIG )
+
+ The first of these NSEC RRs proves that no exact match for
+ foo.example.com exists, and the second proves that there is no
+ wildcard in example.com.
+
+ Both of these functions are imperfect: they don't take into account
+ constraints on number of labels in a name nor total length of a name.
+ As noted in the previous section, though, this technique does not
+ depend on the use of perfect epsilon functions: it is sufficient to
+ test whether any instantiated names fall into the span covered by the
+ generated NSEC and, if so, substitute those instantiated owner names
+ for the NSEC owner name or next name, as appropriate.
+
+
+5. IANA Considerations
+
+ This document specifies no IANA Actions.
+
+
+6. Security Considerations
+
+ This approach requires on-demand generation of RRSIG records. This
+ creates several new vulnerabilities.
+
+ First, on-demand signing requires that a zone's authoritative servers
+ have access to its private keys. Storing private keys on well-known
+ internet-accessible servers may make them more vulnerable to
+ unintended disclosure.
+
+ Second, since generation of digital signatures tends to be
+ computationally demanding, the requirement for on-demand signing
+ makes authoritative servers vulnerable to a denial of service attack.
+
+ Lastly, if the epsilon functions are predictable, on-demand signing
+ may enable a chosen-plaintext attack on a zone's private keys. Zones
+ using this approach should attempt to use cryptographic algorithms
+ that are resistant to chosen-plaintext attacks. It's worth noting
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 7]
+
+Internet-Draft NSEC Epsilon January 2006
+
+
+ that while DNSSEC has a "mandatory to implement" algorithm, that is a
+ requirement on resolvers and validators -- there is no requirement
+ that a zone be signed with any given algorithm.
+
+ The success of using minimally covering NSEC record to prevent zone
+ walking depends greatly on the quality of the epsilon functions
+ chosen. An increment function that chooses a name obviously derived
+ from the next instantiated name may be easily reverse engineered,
+ destroying the value of this technique. An increment function that
+ always returns a name close to the next instantiated name is likewise
+ a poor choice. Good choices of epsilon functions are the ones that
+ produce the immediately following and preceding names, respectively,
+ though zone administrators may wish to use less perfect functions
+ that return more human-friendly names than the functions described in
+ Section 4 above.
+
+ Another obvious but misguided concern is the danger from synthesized
+ NSEC records being replayed. It's possible for an attacker to replay
+ an old but still validly signed NSEC record after a new name has been
+ added in the span covered by that NSEC, incorrectly proving that
+ there is no record at that name. This danger exists with DNSSEC as
+ defined in [3]. The techniques described here actually decrease the
+ danger, since the span covered by any NSEC record is smaller than
+ before. Choosing better epsilon functions will further reduce this
+ danger.
+
+7. Normative References
+
+ [1] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033,
+ March 2005.
+
+ [2] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+ [3] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Protocol Modifications for the DNS Security Extensions",
+ RFC 4035, March 2005.
+
+ [4] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+
+Appendix A. Acknowledgments
+
+ Many individuals contributed to this design. They include, in
+ addition to the authors of this document, Olaf Kolkman, Ed Lewis,
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 8]
+
+Internet-Draft NSEC Epsilon January 2006
+
+
+ Peter Koch, Matt Larson, David Blacka, Suzanne Woolf, Jaap Akkerhuis,
+ Jakob Schlyter, Bill Manning, and Joao Damas.
+
+ In addition, the editors would like to thank Ed Lewis, Scott Rose,
+ and David Blacka for their careful review of the document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 9]
+
+Internet-Draft NSEC Epsilon January 2006
+
+
+Authors' Addresses
+
+ Samuel Weiler
+ SPARTA, Inc
+ 7075 Samuel Morse Drive
+ Columbia, Maryland 21046
+ US
+
+ Email: weiler@tislabs.com
+
+
+ Johan Ihren
+ Autonomica AB
+ Bellmansgatan 30
+ Stockholm SE-118 47
+ Sweden
+
+ Email: johani@autonomica.se
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 10]
+
+Internet-Draft NSEC Epsilon January 2006
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2006). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Weiler & Ihren Expires July 24, 2006 [Page 11]
+
diff --git a/doc/draft/draft-ietf-dnsext-dnssec-opt-in-07.txt b/doc/draft/draft-ietf-dnsext-dnssec-opt-in-07.txt
new file mode 100644
index 0000000..17e28e8
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-dnssec-opt-in-07.txt
@@ -0,0 +1,896 @@
+
+
+
+DNSEXT R. Arends
+Internet-Draft Telematica Instituut
+Expires: January 19, 2006 M. Kosters
+ D. Blacka
+ Verisign, Inc.
+ July 18, 2005
+
+
+ DNSSEC Opt-In
+ draft-ietf-dnsext-dnssec-opt-in-07
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on January 19, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ In the DNS security extensions (DNSSEC, defined in RFC 4033 [3], RFC
+ 4034 [4], and RFC 4035 [5]), delegations to unsigned subzones are
+ cryptographically secured. Maintaining this cryptography is not
+ practical or necessary. This document describes an experimental
+ "Opt-In" model that allows administrators to omit this cryptography
+ and manage the cost of adopting DNSSEC with large zones.
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 1]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+Table of Contents
+
+ 1. Definitions and Terminology . . . . . . . . . . . . . . . . . 3
+ 2. Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 3. Experimental Status . . . . . . . . . . . . . . . . . . . . . 4
+ 4. Protocol Additions . . . . . . . . . . . . . . . . . . . . . . 4
+ 4.1 Server Considerations . . . . . . . . . . . . . . . . . . 5
+ 4.1.1 Delegations Only . . . . . . . . . . . . . . . . . . . 5
+ 4.1.2 Insecure Delegation Responses . . . . . . . . . . . . 6
+ 4.1.3 Wildcards and Opt-In . . . . . . . . . . . . . . . . . 6
+ 4.1.4 Dynamic Update . . . . . . . . . . . . . . . . . . . . 7
+ 4.2 Client Considerations . . . . . . . . . . . . . . . . . . 7
+ 4.2.1 Delegations Only . . . . . . . . . . . . . . . . . . . 7
+ 4.2.2 Validation Process Changes . . . . . . . . . . . . . . 7
+ 4.2.3 NSEC Record Caching . . . . . . . . . . . . . . . . . 8
+ 4.2.4 Use of the AD bit . . . . . . . . . . . . . . . . . . 8
+ 5. Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 6. Example . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
+ 7. Transition Issues . . . . . . . . . . . . . . . . . . . . . . 10
+ 8. Security Considerations . . . . . . . . . . . . . . . . . . . 11
+ 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 12
+ 10. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . 12
+ 11. References . . . . . . . . . . . . . . . . . . . . . . . . . 13
+ 11.1 Normative References . . . . . . . . . . . . . . . . . . . 13
+ 11.2 Informative References . . . . . . . . . . . . . . . . . . 13
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 14
+ A. Implementing Opt-In using "Views" . . . . . . . . . . . . . . 14
+ Intellectual Property and Copyright Statements . . . . . . . . 16
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 2]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+1. Definitions and Terminology
+
+ Throughout this document, familiarity with the DNS system (RFC 1035
+ [1]), DNS security extensions ([3], [4], and [5], referred to in this
+ document as "standard DNSSEC"), and DNSSEC terminology (RFC 3090
+ [10]) is assumed.
+
+ The following abbreviations and terms are used in this document:
+
+ RR: is used to refer to a DNS resource record.
+ RRset: refers to a Resource Record Set, as defined by [8]. In this
+ document, the RRset is also defined to include the covering RRSIG
+ records, if any exist.
+ signed name: refers to a DNS name that has, at minimum, a (signed)
+ NSEC record.
+ unsigned name: refers to a DNS name that does not (at least) have a
+ NSEC record.
+ covering NSEC record/RRset: is the NSEC record used to prove
+ (non)existence of a particular name or RRset. This means that for
+ a RRset or name 'N', the covering NSEC record has the name 'N', or
+ has an owner name less than 'N' and "next" name greater than 'N'.
+ delegation: refers to a NS RRset with a name different from the
+ current zone apex (non-zone-apex), signifying a delegation to a
+ subzone.
+ secure delegation: refers to a signed name containing a delegation
+ (NS RRset), and a signed DS RRset, signifying a delegation to a
+ signed subzone.
+ insecure delegation: refers to a signed name containing a delegation
+ (NS RRset), but lacking a DS RRset, signifying a delegation to an
+ unsigned subzone.
+ Opt-In insecure delegation: refers to an unsigned name containing
+ only a delegation NS RRset. The covering NSEC record uses the
+ Opt-In methodology described in this document.
+
+ The key words "MUST, "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY, and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [7].
+
+2. Overview
+
+ The cost to cryptographically secure delegations to unsigned zones is
+ high for large delegation-centric zones and zones where insecure
+ delegations will be updated rapidly. For these zones, the costs of
+ maintaining the NSEC record chain may be extremely high relative to
+ the gain of cryptographically authenticating existence of unsecured
+ zones.
+
+ This document describes an experimental method of eliminating the
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 3]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+ superfluous cryptography present in secure delegations to unsigned
+ zones. Using "Opt-In", a zone administrator can choose to remove
+ insecure delegations from the NSEC chain. This is accomplished by
+ extending the semantics of the NSEC record by using a redundant bit
+ in the type map.
+
+3. Experimental Status
+
+ This document describes an EXPERIMENTAL extension to DNSSEC. It
+ interoperates with non-experimental DNSSEC using the technique
+ described in [6]. This experiment is identified with the following
+ private algorithms (using algorithm 253):
+
+ "3.optin.verisignlabs.com": is an alias for DNSSEC algorithm 3, DSA,
+ and
+ "5.optin.verisignlabs.com": is an alias for DNSSEC algorithm 5,
+ RSASHA1.
+
+ Servers wishing to sign and serve zones that utilize Opt-In MUST sign
+ the zone with only one or more of these private algorithms. This
+ requires the signing tools and servers to support private algorithms,
+ as well as Opt-In.
+
+ Resolvers wishing to validate Opt-In zones MUST only do so when the
+ zone is only signed using one or more of these private algorithms.
+
+ The remainder of this document assumes that the servers and resolvers
+ involved are aware of and are involved in this experiment.
+
+4. Protocol Additions
+
+ In DNSSEC, delegation NS RRsets are not signed, but are instead
+ accompanied by a NSEC RRset of the same name and (possibly) a DS
+ record. The security status of the subzone is determined by the
+ presence or absence of the DS RRset, cryptographically proven by the
+ NSEC record. Opt-In expands this definition by allowing insecure
+ delegations to exist within an otherwise signed zone without the
+ corresponding NSEC record at the delegation's owner name. These
+ insecure delegations are proven insecure by using a covering NSEC
+ record.
+
+ Since this represents a change of the interpretation of NSEC records,
+ resolvers must be able to distinguish between RFC standard DNSSEC
+ NSEC records and Opt-In NSEC records. This is accomplished by
+ "tagging" the NSEC records that cover (or potentially cover) insecure
+ delegation nodes. This tag is indicated by the absence of the NSEC
+ bit in the type map. Since the NSEC bit in the type map merely
+ indicates the existence of the record itself, this bit is redundant
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 4]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+ and safe for use as a tag.
+
+ An Opt-In tagged NSEC record does not assert the (non)existence of
+ the delegations that it covers (except for a delegation with the same
+ name). This allows for the addition or removal of these delegations
+ without recalculating or resigning records in the NSEC chain.
+ However, Opt-In tagged NSEC records do assert the (non)existence of
+ other RRsets.
+
+ An Opt-In NSEC record MAY have the same name as an insecure
+ delegation. In this case, the delegation is proven insecure by the
+ lack of a DS bit in type map and the signed NSEC record does assert
+ the existence of the delegation.
+
+ Zones using Opt-In MAY contain a mixture of Opt-In tagged NSEC
+ records and standard DNSSEC NSEC records. If a NSEC record is not
+ Opt-In, there MUST NOT be any insecure delegations (or any other
+ records) between it and the RRsets indicated by the 'next domain
+ name' in the NSEC RDATA. If it is Opt-In, there MUST only be
+ insecure delegations between it and the next node indicated by the
+ 'next domain name' in the NSEC RDATA.
+
+ In summary,
+
+ o An Opt-In NSEC type is identified by a zero-valued (or not-
+ specified) NSEC bit in the type bit map of the NSEC record.
+ o A RFC2535bis NSEC type is identified by a one-valued NSEC bit in
+ the type bit map of the NSEC record.
+
+ and,
+
+ o An Opt-In NSEC record does not assert the non-existence of a name
+ between its owner name and "next" name, although it does assert
+ that any name in this span MUST be an insecure delegation.
+ o An Opt-In NSEC record does assert the (non)existence of RRsets
+ with the same owner name.
+
+4.1 Server Considerations
+
+ Opt-In imposes some new requirements on authoritative DNS servers.
+
+4.1.1 Delegations Only
+
+ This specification dictates that only insecure delegations may exist
+ between the owner and "next" names of an Opt-In tagged NSEC record.
+ Signing tools SHOULD NOT generate signed zones that violate this
+ restriction. Servers SHOULD refuse to load and/or serve zones that
+ violate this restriction. Servers also SHOULD reject AXFR or IXFR
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 5]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+ responses that violate this restriction.
+
+4.1.2 Insecure Delegation Responses
+
+ When returning an Opt-In insecure delegation, the server MUST return
+ the covering NSEC RRset in the Authority section.
+
+ In standard DNSSEC, NSEC records already must be returned along with
+ the insecure delegation. The primary difference that this proposal
+ introduces is that the Opt-In tagged NSEC record will have a
+ different owner name from the delegation RRset. This may require
+ implementations to search for the covering NSEC RRset.
+
+4.1.3 Wildcards and Opt-In
+
+ Standard DNSSEC describes the practice of returning NSEC records to
+ prove the non-existence of an applicable wildcard in non-existent
+ name responses. This NSEC record can be described as a "negative
+ wildcard proof". The use of Opt-In NSEC records changes the
+ necessity for this practice. For non-existent name responses when
+ the query name (qname) is covered by an Opt-In tagged NSEC record,
+ servers MAY choose to omit the wildcard proof record, and clients
+ MUST NOT treat the absence of this NSEC record as a validation error.
+
+ The intent of the standard DNSSEC negative wildcard proof requirement
+ is to prevent malicious users from undetectably removing valid
+ wildcard responses. In order for this cryptographic proof to work,
+ the resolver must be able to prove:
+
+ 1. The exact qname does not exist. This is done by the "normal"
+ NSEC record.
+ 2. No applicable wildcard exists. This is done by returning a NSEC
+ record proving that the wildcard does not exist (this is the
+ negative wildcard proof).
+
+ However, if the NSEC record covering the exact qname is an Opt-In
+ NSEC record, the resolver will not be able to prove the first part of
+ this equation, as the qname might exist as an insecure delegation.
+ Thus, since the total proof cannot be completed, the negative
+ wildcard proof NSEC record is not useful.
+
+ The negative wildcard proof is also not useful when returned as part
+ of an Opt-In insecure delegation response for a similar reason: the
+ resolver cannot prove that the qname does or does not exist, and
+ therefore cannot prove that a wildcard expansion is valid.
+
+ The presence of an Opt-In tagged NSEC record does not change the
+ practice of returning a NSEC along with a wildcard expansion. Even
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 6]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+ though the Opt-In NSEC will not be able to prove that the wildcard
+ expansion is valid, it will prove that the wildcard expansion is not
+ masking any signed records.
+
+4.1.4 Dynamic Update
+
+ Opt-In changes the semantics of Secure DNS Dynamic Update [9]. In
+ particular, it introduces the need for rules that describe when to
+ add or remove a delegation name from the NSEC chain. This document
+ does not attempt to define these rules. Until these rules are
+ defined, servers MUST NOT process DNS Dynamic Update requests against
+ zones that use Opt-In NSEC records. Servers SHOULD return responses
+ to update requests with RCODE=REFUSED.
+
+4.2 Client Considerations
+
+ Opt-In imposes some new requirements on security-aware resolvers
+ (caching or otherwise).
+
+4.2.1 Delegations Only
+
+ As stated in the "Server Considerations" section above, this
+ specification restricts the namespace covered by Opt-In tagged NSEC
+ records to insecure delegations only. Thus, resolvers MUST reject as
+ invalid any records that fall within an Opt-In NSEC record's span
+ that are not NS records or corresponding glue records.
+
+4.2.2 Validation Process Changes
+
+ This specification does not change the resolver's resolution
+ algorithm. However, it does change the DNSSEC validation process.
+ Resolvers MUST be able to use Opt-In tagged NSEC records to
+ cryptographically prove the validity and security status (as
+ insecure) of a referral. Resolvers determine the security status of
+ the referred-to zone as follows:
+
+ o In standard DNSSEC, the security status is proven by the existence
+ or absence of a DS RRset at the same name as the delegation. The
+ existence of the DS RRset indicates that the referred-to zone is
+ signed. The absence of the DS RRset is proven using a verified
+ NSEC record of the same name that does not have the DS bit set in
+ the type map. This NSEC record MAY also be tagged as Opt-In.
+ o Using Opt-In, the security status is proven by the existence of a
+ DS record (for signed) or the presence of a verified Opt-In tagged
+ NSEC record that covers the delegation name. That is, the NSEC
+ record does not have the NSEC bit set in the type map, and the
+ delegation name falls between the NSEC's owner and "next" name.
+
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 7]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+ Using Opt-In does not substantially change the nature of following
+ referrals within DNSSEC. At every delegation point, the resolver
+ will have cryptographic proof that the referred-to subzone is signed
+ or unsigned.
+
+ When receiving either an Opt-In insecure delegation response or a
+ non-existent name response where that name is covered by an Opt-In
+ tagged NSEC record, the resolver MUST NOT require proof (in the form
+ of a NSEC record) that a wildcard did not exist.
+
+4.2.3 NSEC Record Caching
+
+ Caching resolvers MUST be able to retrieve the appropriate covering
+ Opt-In NSEC record when returning referrals that need them. This
+ requirement differs from standard DNSSEC in that the covering NSEC
+ will not have the same owner name as the delegation. Some
+ implementations may have to use new methods for finding these NSEC
+ records.
+
+4.2.4 Use of the AD bit
+
+ The AD bit, as defined by [2] and [5], MUST NOT be set when:
+
+ o sending a Name Error (RCODE=3) response where the covering NSEC is
+ tagged as Opt-In.
+ o sending an Opt-In insecure delegation response, unless the
+ covering (Opt-In) NSEC record's owner name equals the delegation
+ name.
+
+ This rule is based on what the Opt-In NSEC record actually proves:
+ for names that exist between the Opt-In NSEC record's owner and
+ "next" names, the Opt-In NSEC record cannot prove the non-existence
+ or existence of the name. As such, not all data in the response has
+ been cryptographically verified, so the AD bit cannot be set.
+
+5. Benefits
+
+ Using Opt-In allows administrators of large and/or changing
+ delegation-centric zones to minimize the overhead involved in
+ maintaining the security of the zone.
+
+ Opt-In accomplishes this by eliminating the need for NSEC records for
+ insecure delegations. This, in a zone with a large number of
+ delegations to unsigned subzones, can lead to substantial space
+ savings (both in memory and on disk). Additionally, Opt-In allows
+ for the addition or removal of insecure delegations without modifying
+ the NSEC record chain. Zones that are frequently updating insecure
+ delegations (e.g., TLDs) can avoid the substantial overhead of
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 8]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+ modifying and resigning the affected NSEC records.
+
+6. Example
+
+ Consider the zone EXAMPLE, shown below. This is a zone where all of
+ the NSEC records are tagged as Opt-In.
+
+ Example A: Fully Opt-In Zone.
+
+ EXAMPLE. SOA ...
+ EXAMPLE. RRSIG SOA ...
+ EXAMPLE. NS FIRST-SECURE.EXAMPLE.
+ EXAMPLE. RRSIG NS ...
+ EXAMPLE. DNSKEY ...
+ EXAMPLE. RRSIG DNSKEY ...
+ EXAMPLE. NSEC FIRST-SECURE.EXAMPLE. (
+ SOA NS RRSIG DNSKEY )
+ EXAMPLE. RRSIG NSEC ...
+
+ FIRST-SECURE.EXAMPLE. A ...
+ FIRST-SECURE.EXAMPLE. RRSIG A ...
+ FIRST-SECURE.EXAMPLE. NSEC NOT-SECURE-2.EXAMPLE. A RRSIG
+ FIRST-SECURE.EXAMPLE. RRSIG NSEC ...
+
+ NOT-SECURE.EXAMPLE. NS NS.NOT-SECURE.EXAMPLE.
+ NS.NOT-SECURE.EXAMPLE. A ...
+
+ NOT-SECURE-2.EXAMPLE. NS NS.NOT-SECURE.EXAMPLE.
+ NOT-SECURE-2.EXAMPLE NSEC SECOND-SECURE.EXAMPLE NS RRSIG
+ NOT-SECURE-2.EXAMPLE RRSIG NSEC ...
+
+ SECOND-SECURE.EXAMPLE. NS NS.ELSEWHERE.
+ SECOND-SECURE.EXAMPLE. DS ...
+ SECOND-SECURE.EXAMPLE. RRSIG DS ...
+ SECOND-SECURE.EXAMPLE. NSEC EXAMPLE. NS RRSIG DNSKEY
+ SECOND-SECURE.EXAMPLE. RRSIG NSEC ...
+
+ UNSIGNED.EXAMPLE. NS NS.UNSIGNED.EXAMPLE.
+ NS.UNSIGNED.EXAMPLE. A ...
+
+
+ In this example, a query for a signed RRset (e.g., "FIRST-
+ SECURE.EXAMPLE A"), or a secure delegation ("WWW.SECOND-
+ SECURE.EXAMPLE A") will result in a standard DNSSEC response.
+
+ A query for a nonexistent RRset will result in a response that
+ differs from standard DNSSEC by: the NSEC record will be tagged as
+ Opt-In, there may be no NSEC record proving the non-existence of a
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 9]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+ matching wildcard record, and the AD bit will not be set.
+
+ A query for an insecure delegation RRset (or a referral) will return
+ both the answer (in the Authority section) and the corresponding
+ Opt-In NSEC record to prove that it is not secure.
+
+ Example A.1: Response to query for WWW.UNSIGNED.EXAMPLE. A
+
+
+ RCODE=NOERROR, AD=0
+
+ Answer Section:
+
+ Authority Section:
+ UNSIGNED.EXAMPLE. NS NS.UNSIGNED.EXAMPLE
+ SECOND-SECURE.EXAMPLE. NSEC EXAMPLE. NS RRSIG DS
+ SECOND-SECURE.EXAMPLE. RRSIG NSEC ...
+
+ Additional Section:
+ NS.UNSIGNED.EXAMPLE. A ...
+
+ In the Example A.1 zone, the EXAMPLE. node MAY use either style of
+ NSEC record, because there are no insecure delegations that occur
+ between it and the next node, FIRST-SECURE.EXAMPLE. In other words,
+ Example A would still be a valid zone if the NSEC record for EXAMPLE.
+ was changed to the following RR:
+
+ EXAMPLE. NSEC FIRST-SECURE.EXAMPLE. (SOA NS
+ RRSIG DNSKEY NSEC )
+
+ However, the other NSEC records (FIRST-SECURE.EXAMPLE. and SECOND-
+ SECURE.EXAMPLE.) MUST be tagged as Opt-In because there are insecure
+ delegations in the range they define. (NOT-SECURE.EXAMPLE. and
+ UNSIGNED.EXAMPLE., respectively).
+
+ NOT-SECURE-2.EXAMPLE. is an example of an insecure delegation that is
+ part of the NSEC chain and also covered by an Opt-In tagged NSEC
+ record. Because NOT-SECURE-2.EXAMPLE. is a signed name, it cannot be
+ removed from the zone without modifying and resigning the prior NSEC
+ record. Delegations with names that fall between NOT-SECURE-
+ 2.EXAMPLE. and SECOND-SECURE.EXAMPLE. may be added or removed without
+ resigning any NSEC records.
+
+7. Transition Issues
+
+ Opt-In is not backwards compatible with standard DNSSEC and is
+ considered experimental. Standard DNSSEC compliant implementations
+ would not recognize Opt-In tagged NSEC records as different from
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 10]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+ standard NSEC records. Because of this, standard DNSSEC
+ implementations, if they were to validate Opt-In style responses,
+ would reject all Opt-In insecure delegations within a zone as
+ invalid. However, by only signing with private algorithms, standard
+ DNSSEC implementations will treat Opt-In responses as unsigned.
+
+ It should be noted that all elements in the resolution path between
+ (and including) the validator and the authoritative name server must
+ be aware of the Opt-In experiment and implement the Opt-In semantics
+ for successful validation to be possible. In particular, this
+ includes any caching middleboxes between the validator and
+ authoritative name server.
+
+8. Security Considerations
+
+ Opt-In allows for unsigned names, in the form of delegations to
+ unsigned subzones, to exist within an otherwise signed zone. All
+ unsigned names are, by definition, insecure, and their validity or
+ existence cannot by cryptographically proven.
+
+ In general:
+
+ o Records with unsigned names (whether existing or not) suffer from
+ the same vulnerabilities as records in an unsigned zone. These
+ vulnerabilities are described in more detail in [12] (note in
+ particular sections 2.3, "Name Games" and 2.6, "Authenticated
+ Denial").
+ o Records with signed names have the same security whether or not
+ Opt-In is used.
+
+ Note that with or without Opt-In, an insecure delegation may have its
+ contents undetectably altered by an attacker. Because of this, the
+ primary difference in security that Opt-In introduces is the loss of
+ the ability to prove the existence or nonexistence of an insecure
+ delegation within the span of an Opt-In NSEC record.
+
+ In particular, this means that a malicious entity may be able to
+ insert or delete records with unsigned names. These records are
+ normally NS records, but this also includes signed wildcard
+ expansions (while the wildcard record itself is signed, its expanded
+ name is an unsigned name).
+
+ For example, if a resolver received the following response from the
+ example zone above:
+
+
+
+
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 11]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+ Example S.1: Response to query for WWW.DOES-NOT-EXIST.EXAMPLE. A
+
+ RCODE=NOERROR
+
+ Answer Section:
+
+ Authority Section:
+ DOES-NOT-EXIST.EXAMPLE. NS NS.FORGED.
+ EXAMPLE. NSEC FIRST-SECURE.EXAMPLE. SOA NS \
+ RRSIG DNSKEY
+ EXAMPLE. RRSIG NSEC ...
+
+ Additional Section:
+
+
+ The resolver would have no choice but to believe that the referral to
+ NS.FORGED. is valid. If a wildcard existed that would have been
+ expanded to cover "WWW.DOES-NOT-EXIST.EXAMPLE.", an attacker could
+ have undetectably removed it and replaced it with the forged
+ delegation.
+
+ Note that being able to add a delegation is functionally equivalent
+ to being able to add any record type: an attacker merely has to forge
+ a delegation to nameserver under his/her control and place whatever
+ records needed at the subzone apex.
+
+ While in particular cases, this issue may not present a significant
+ security problem, in general it should not be lightly dismissed.
+ Therefore, it is strongly RECOMMENDED that Opt-In be used sparingly.
+ In particular, zone signing tools SHOULD NOT default to Opt-In, and
+ MAY choose to not support Opt-In at all.
+
+9. IANA Considerations
+
+ None.
+
+10. Acknowledgments
+
+ The contributions, suggestions and remarks of the following persons
+ (in alphabetic order) to this draft are acknowledged:
+
+ Mats Dufberg, Miek Gieben, Olafur Gudmundsson, Bob Halley, Olaf
+ Kolkman, Edward Lewis, Ted Lindgreen, Rip Loomis, Bill Manning,
+ Dan Massey, Scott Rose, Mike Schiraldi, Jakob Schlyter, Brian
+ Wellington.
+
+11. References
+
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 12]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+11.1 Normative References
+
+ [1] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [2] Wellington, B. and O. Gudmundsson, "Redefinition of DNS
+ Authenticated Data (AD) bit", RFC 3655, November 2003.
+
+ [3] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033,
+ March 2005.
+
+ [4] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+ [5] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Protocol Modifications for the DNS Security Extensions",
+ RFC 4035, March 2005.
+
+ [6] Blacka, D., "DNSSEC Experiments",
+ draft-ietf-dnsext-dnssec-experiments-01 (work in progress),
+ July 2005.
+
+11.2 Informative References
+
+ [7] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [8] Elz, R. and R. Bush, "Clarifications to the DNS Specification",
+ RFC 2181, July 1997.
+
+ [9] Eastlake, D., "Secure Domain Name System Dynamic Update",
+ RFC 2137, April 1997.
+
+ [10] Lewis, E., "DNS Security Extension Clarification on Zone
+ Status", RFC 3090, March 2001.
+
+ [11] Conrad, D., "Indicating Resolver Support of DNSSEC", RFC 3225,
+ December 2001.
+
+ [12] Atkins, D. and R. Austein, "Threat Analysis of the Domain Name
+ System (DNS)", RFC 3833, August 2004.
+
+
+
+
+
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 13]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+Authors' Addresses
+
+ Roy Arends
+ Telematica Instituut
+ Drienerlolaan 5
+ 7522 NB Enschede
+ NL
+
+ Email: roy.arends@telin.nl
+
+
+ Mark Kosters
+ Verisign, Inc.
+ 21355 Ridgetop Circle
+ Dulles, VA 20166
+ US
+
+ Phone: +1 703 948 3200
+ Email: markk@verisign.com
+ URI: http://www.verisignlabs.com
+
+
+ David Blacka
+ Verisign, Inc.
+ 21355 Ridgetop Circle
+ Dulles, VA 20166
+ US
+
+ Phone: +1 703 948 3200
+ Email: davidb@verisign.com
+ URI: http://www.verisignlabs.com
+
+Appendix A. Implementing Opt-In using "Views"
+
+ In many cases, it may be convenient to implement an Opt-In zone by
+ combining two separately maintained "views" of a zone at request
+ time. In this context, "view" refers to a particular version of a
+ zone, not to any specific DNS implementation feature.
+
+ In this scenario, one view is the secure view, the other is the
+ insecure (or legacy) view. The secure view consists of an entirely
+ signed zone using Opt-In tagged NSEC records. The insecure view
+ contains no DNSSEC information. It is helpful, although not
+ necessary, for the secure view to be a subset (minus DNSSEC records)
+ of the insecure view.
+
+ In addition, the only RRsets that may solely exist in the insecure
+ view are non-zone-apex NS RRsets. That is, all non-NS RRsets (and
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 14]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+ the zone apex NS RRset) MUST be signed and in the secure view.
+
+ These two views may be combined at request time to provide a virtual,
+ single Opt-In zone. The following algorithm is used when responding
+ to each query:
+ V_A is the secure view as described above.
+ V_B is the insecure view as described above.
+ R_A is a response generated from V_A, following RFC 2535bis.
+ R_B is a response generated from V_B, following DNS resolution as
+ per RFC 1035 [1].
+ R_C is the response generated by combining R_A with R_B, as
+ described below.
+ A query is DNSSEC-aware if it either has the DO bit [11] turned
+ on, or is for a DNSSEC-specific record type.
+
+
+
+ 1. If V_A is a subset of V_B and the query is not DNSSEC-aware,
+ generate and return R_B, otherwise
+ 2. Generate R_A.
+ 3. If R_A's RCODE != NXDOMAIN, return R_A, otherwise
+ 4. Generate R_B and combine it with R_A to form R_C:
+ For each section (ANSWER, AUTHORITY, ADDITIONAL), copy the
+ records from R_A into R_B, EXCEPT the AUTHORITY section SOA
+ record, if R_B's RCODE = NOERROR.
+ 5. Return R_C.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 15]
+
+Internet-Draft DNSSEC Opt-In July 2005
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2005). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Arends, et al. Expires January 19, 2006 [Page 16]
+
diff --git a/doc/draft/draft-ietf-dnsext-dnssec-rsasha256-06.txt b/doc/draft/draft-ietf-dnsext-dnssec-rsasha256-06.txt
new file mode 100644
index 0000000..1dc9070
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-dnssec-rsasha256-06.txt
@@ -0,0 +1,504 @@
+
+
+
+DNS Extensions working group J. Jansen
+Internet-Draft NLnet Labs
+Intended status: Standards Track October 23, 2008
+Expires: April 26, 2009
+
+
+ Use of SHA-2 algorithms with RSA in DNSKEY and RRSIG Resource Records
+ for DNSSEC
+ draft-ietf-dnsext-dnssec-rsasha256-06
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on April 26, 2009.
+
+Abstract
+
+ This document describes how to produce RSA/SHA-256 and RSA/SHA-512
+ DNSKEY and RRSIG resource records for use in the Domain Name System
+ Security Extensions (DNSSEC, RFC 4033, RFC 4034, and RFC 4035).
+
+
+
+
+
+
+
+
+
+
+
+Jansen Expires April 26, 2009 [Page 1]
+
+Internet-Draft DNSSEC RSA/SHA-2 October 2008
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. DNSKEY Resource Records . . . . . . . . . . . . . . . . . . . . 3
+ 2.1. RSA/SHA-256 DNSKEY Resource Records . . . . . . . . . . . . 3
+ 2.2. RSA/SHA-512 DNSKEY Resource Records . . . . . . . . . . . . 3
+ 3. RRSIG Resource Records . . . . . . . . . . . . . . . . . . . . 4
+ 3.1. RSA/SHA-256 RRSIG Resource Records . . . . . . . . . . . . 4
+ 3.2. RSA/SHA-512 RRSIG Resource Records . . . . . . . . . . . . 5
+ 4. Deployment Considerations . . . . . . . . . . . . . . . . . . . 5
+ 4.1. Key Sizes . . . . . . . . . . . . . . . . . . . . . . . . . 5
+ 4.2. Signature Sizes . . . . . . . . . . . . . . . . . . . . . . 5
+ 5. Implementation Considerations . . . . . . . . . . . . . . . . . 5
+ 5.1. Support for SHA-2 signatures . . . . . . . . . . . . . . . 5
+ 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 5
+ 7. Security Considerations . . . . . . . . . . . . . . . . . . . . 6
+ 7.1. SHA-1 versus SHA-2 Considerations for RRSIG Resource
+ Records . . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 7.2. Signature Type Downgrade Attacks . . . . . . . . . . . . . 6
+ 8. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 9.1. Normative References . . . . . . . . . . . . . . . . . . . 7
+ 9.2. Informative References . . . . . . . . . . . . . . . . . . 7
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 8
+ Intellectual Property and Copyright Statements . . . . . . . . . . 9
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jansen Expires April 26, 2009 [Page 2]
+
+Internet-Draft DNSSEC RSA/SHA-2 October 2008
+
+
+1. Introduction
+
+ The Domain Name System (DNS) is the global hierarchical distributed
+ database for Internet Naming. The DNS has been extended to use
+ cryptographic keys and digital signatures for the verification of the
+ authenticity and integrity of its data. RFC 4033 [RFC4033], RFC 4034
+ [RFC4034], and RFC 4035 [RFC4035] describe these DNS Security
+ Extensions, called DNSSEC.
+
+ RFC 4034 describes how to store DNSKEY and RRSIG resource records,
+ and specifies a list of cryptographic algorithms to use. This
+ document extends that list with the algorithms RSA/SHA-256 and RSA/
+ SHA-512, and specifies how to store DNSKEY data and how to produce
+ RRSIG resource records with these hash algorithms.
+
+ Familiarity with DNSSEC, RSA and the SHA-2 [FIPS.180-2.2002] family
+ of algorithms is assumed in this document.
+
+ To refer to both SHA-256 and SHA-512, this document will use the name
+ SHA-2. This is done to improve readability. When a part of text is
+ specific for either SHA-256 or SHA-512, their specific names are
+ used. The same goes for RSA/SHA-256 and RSA/SHA-512, which will be
+ grouped using the name RSA/SHA-2.
+
+
+2. DNSKEY Resource Records
+
+ The format of the DNSKEY RR can be found in RFC 4034 [RFC4034], RFC
+ 3110 [RFC3110] describes the use of RSA/SHA-1 for DNSSEC signatures.
+
+2.1. RSA/SHA-256 DNSKEY Resource Records
+
+ RSA public keys for use with RSA/SHA-256 are stored in DNSKEY
+ resource records (RRs) with the algorithm number {TBA1}.
+
+ For use with NSEC3 [RFC5155], the algorithm number for RSA/SHA-256
+ will be {TBA2}. The use of a different algorithm number to
+ differentiate between the use of NSEC and NSEC3 is in keeping with
+ the approach adopted in RFC5155.
+
+ For interoperability, as in RFC 3110 [RFC3110], the key size of RSA/
+ SHA-256 keys MUST NOT be less than 512 bits, and MUST NOT be more
+ than 4096 bits.
+
+2.2. RSA/SHA-512 DNSKEY Resource Records
+
+ RSA public keys for use with RSA/SHA-512 are stored in DNSKEY
+ resource records (RRs) with the algorithm number {TBA3}.
+
+
+
+Jansen Expires April 26, 2009 [Page 3]
+
+Internet-Draft DNSSEC RSA/SHA-2 October 2008
+
+
+ For use with NSEC3, the algorithm number for RSA/SHA-512 will be
+ {TBA4}. The use of a different algorithm number to differentiate
+ between the use of NSEC and NSEC3 is in keeping with the approach
+ adopted in RFC5155.
+
+ The key size of RSA/SHA-512 keys MUST NOT be less than 1024 bits, and
+ MUST NOT be more than 4096 bits.
+
+
+3. RRSIG Resource Records
+
+ The value of the signature field in the RRSIG RR follows the RSASSA-
+ PKCS1-v1_5 signature scheme, and is calculated as follows. The
+ values for the RDATA fields that precede the signature data are
+ specified in RFC 4034 [RFC4034].
+
+ hash = SHA-XXX(data)
+
+ Here XXX is either 256 or 512, depending on the algorithm used, as
+ specified in FIPS PUB 180-2 [FIPS.180-2.2002], and "data" is the wire
+ format data of the resource record set that is signed, as specified
+ in RFC 4034 [RFC4034].
+
+ signature = ( 00 | 01 | FF* | 00 | prefix | hash ) ** e (mod n)
+
+ Here "|" is concatenation, "00", "01", "FF" and "00" are fixed octets
+ of corresponding hexadecimal value, "e" is the private exponent of
+ the signing RSA key, and "n" is the public modulus of the signing
+ key. The FF octet MUST be repeated the exact number of times so that
+ the total length of the concatenated term in parentheses equals the
+ length of the modulus of the signer's public key ("n").
+
+ The "prefix" is intended to make the use of standard cryptographic
+ libraries easier. These specifications are taken directly from the
+ specifications of RSASSA-PKCS1-v1_5 in PKCS #1 v2.1 section 8.2
+ [RFC3447], and EMSA-PKCS1-v1_5 encoding in PKCS #1 v2.1 section 9.2
+ [RFC3447]. The prefixes for the different algorithms are specified
+ below.
+
+3.1. RSA/SHA-256 RRSIG Resource Records
+
+ RSA/SHA-256 signatures are stored in the DNS using RRSIG resource
+ records (RRs) with algorithm number {TBA1} for use with NSEC, or
+ {TBA2} for use with NSEC3.
+
+ The prefix is the ASN.1 BER SHA-256 algorithm designator prefix as
+ specified in PKCS #1 v2.1 [RFC3447]:
+
+
+
+
+Jansen Expires April 26, 2009 [Page 4]
+
+Internet-Draft DNSSEC RSA/SHA-2 October 2008
+
+
+ hex 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20
+
+3.2. RSA/SHA-512 RRSIG Resource Records
+
+ RSA/SHA-512 signatures are stored in the DNS using RRSIG resource
+ records (RRs) with algorithm number {TBA3} for use with NSEC, or
+ {TBA4} for use with NSEC3.
+
+ The prefix is the ASN.1 BER SHA-512 algorithm designator prefix as
+ specified in PKCS #1 v2.1 [RFC3447]:
+
+ hex 30 51 30 0d 06 09 60 86 48 01 65 03 04 02 03 05 00 04 40
+
+
+4. Deployment Considerations
+
+4.1. Key Sizes
+
+ Apart from the restrictions specified in section 2, this document
+ will not specify what size of keys to use. That is an operational
+ issue and depends largely on the environment and intended use. A
+ good starting point for more information would be NIST SP 800-57
+ [NIST800-57].
+
+4.2. Signature Sizes
+
+ In this family of signing algorithms, the size of signatures is
+ related to the size of the key, and not the hashing algorithm used in
+ the signing process. Therefore, RRSIG resource records produced with
+ RSA/SHA256 or RSA/SHA512 will have the same size as those produced
+ with RSA/SHA1, if the keys have the same length.
+
+
+5. Implementation Considerations
+
+5.1. Support for SHA-2 signatures
+
+ DNSSEC aware implementations SHOULD be able to support RRSIG resource
+ records with the RSA/SHA-2 algorithms.
+
+
+6. IANA Considerations
+
+ IANA has assigned DNS Security Algorithm Numbers {TBA1} for RSA/
+ SHA-256 with NSEC, {TBA2} for RSA/SHA-256 with NSEC3, {TBA3} for RSA/
+ SHA-512 with NSEC, and {TBA4} for RSA/SHA-512 with NSEC3.
+
+ The algorithm list from RFC 4034 Appendix A.1 [RFC4034] is extended
+
+
+
+Jansen Expires April 26, 2009 [Page 5]
+
+Internet-Draft DNSSEC RSA/SHA-2 October 2008
+
+
+ with the following entries:
+
+ Zone
+ Value Algorithm [Mnemonic] Signing References
+ {TBA1} RSA/SHA-256 RSASHA256 y {this memo}
+ {TBA2} RSA/SHA-256-NSEC3 RSASHA256NSEC3 y {this memo}
+ {TBA3} RSA/SHA-512 RSASHA512 y {this memo}
+ {TBA4} RSA/SHA-512-NSEC3 RSASHA512NSEC3 y {this memo}
+
+
+
+7. Security Considerations
+
+7.1. SHA-1 versus SHA-2 Considerations for RRSIG Resource Records
+
+ Users of DNSSEC are encouraged to deploy SHA-2 as soon as software
+ implementations allow for it. SHA-2 is widely believed to be more
+ resilient to attack than SHA-1, and confidence in SHA-1's strength is
+ being eroded by recently-announced attacks. Regardless of whether or
+ not the attacks on SHA-1 will affect DNSSEC, it is believed (at the
+ time of this writing) that SHA-2 is the better choice for use in
+ DNSSEC records.
+
+ SHA-2 is considered sufficiently strong for the immediate future, but
+ predictions about future development in cryptography and
+ cryptanalysis are beyond the scope of this document.
+
+ The signature scheme RSASSA-PKCS1-v1_5 is chosen to match the one
+ used for RSA/SHA-1 signatures. This should ease implementation of
+ the new hashing algorithms in DNSSEC software.
+
+7.2. Signature Type Downgrade Attacks
+
+ Since each RRSet MUST be signed with each algorithm present in the
+ DNSKEY RRSet at the zone apex (see [RFC4035] Section 2.2), a
+ malicious party cannot filter out the RSA/SHA-2 RRSIG, and force the
+ validator to use the RSA/SHA-1 signature if both are present in the
+ zone. This should provide resilience against algorithm downgrade
+ attacks, if the validator supports RSA/SHA-2.
+
+
+8. Acknowledgments
+
+ This document is a minor extension to RFC 4034 [RFC4034]. Also, we
+ try to follow the documents RFC 3110 [RFC3110] and RFC 4509 [RFC4509]
+ for consistency. The authors of and contributors to these documents
+ are gratefully acknowledged for their hard work.
+
+
+
+
+Jansen Expires April 26, 2009 [Page 6]
+
+Internet-Draft DNSSEC RSA/SHA-2 October 2008
+
+
+ The following people provided additional feedback and text: Jaap
+ Akkerhuis, Roy Arends, Rob Austein, Francis Dupont, Miek Gieben,
+ Alfred Hoenes, Paul Hoffman, Peter Koch, Michael St. Johns, Scott
+ Rose and Wouter Wijngaards.
+
+
+9. References
+
+9.1. Normative References
+
+ [FIPS.180-2.2002]
+ National Institute of Standards and Technology, "Secure
+ Hash Standard", FIPS PUB 180-2, August 2002.
+
+ [RFC3110] Eastlake, D., "RSA/SHA-1 SIGs and RSA KEYs in the Domain
+ Name System (DNS)", RFC 3110, May 2001.
+
+ [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements",
+ RFC 4033, March 2005.
+
+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security Extensions",
+ RFC 4034, March 2005.
+
+ [RFC4035] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security
+ Extensions", RFC 4035, March 2005.
+
+9.2. Informative References
+
+ [NIST800-57]
+ Barker, E., Barker, W., Burr, W., Polk, W., and M. Smid,
+ "Recommendations for Key Management", NIST SP 800-57,
+ March 2007.
+
+ [RFC3447] Jonsson, J. and B. Kaliski, "Public-Key Cryptography
+ Standards (PKCS) #1: RSA Cryptography Specifications
+ Version 2.1", RFC 3447, February 2003.
+
+ [RFC4509] Hardaker, W., "Use of SHA-256 in DNSSEC Delegation Signer
+ (DS) Resource Records (RRs)", RFC 4509, May 2006.
+
+ [RFC5155] Laurie, B., Sisson, G., Arends, R., and D. Blacka, "DNS
+ Security (DNSSEC) Hashed Authenticated Denial of
+ Existence", RFC 5155, March 2008.
+
+
+
+
+
+Jansen Expires April 26, 2009 [Page 7]
+
+Internet-Draft DNSSEC RSA/SHA-2 October 2008
+
+
+Author's Address
+
+ Jelte Jansen
+ NLnet Labs
+ Kruislaan 419
+ Amsterdam 1098VA
+ NL
+
+ Email: jelte@NLnetLabs.nl
+ URI: http://www.nlnetlabs.nl/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jansen Expires April 26, 2009 [Page 8]
+
+Internet-Draft DNSSEC RSA/SHA-2 October 2008
+
+
+Full Copyright Statement
+
+ Copyright (C) The IETF Trust (2008).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+
+
+
+
+
+
+
+
+
+Jansen Expires April 26, 2009 [Page 9]
+
diff --git a/doc/draft/draft-ietf-dnsext-dnssec-trans-02.txt b/doc/draft/draft-ietf-dnsext-dnssec-trans-02.txt
new file mode 100644
index 0000000..dd8cbf0
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-dnssec-trans-02.txt
@@ -0,0 +1,839 @@
+
+DNS Extensions Working Group R. Arends
+Internet-Draft Telematica Instituut
+Expires: August 25, 2005 P. Koch
+ DENIC eG
+ J. Schlyter
+ NIC-SE
+ February 21, 2005
+
+
+ Evaluating DNSSEC Transition Mechanisms
+ draft-ietf-dnsext-dnssec-trans-02.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is subject to all provisions
+ of Section 3 of RFC 3667. By submitting this Internet-Draft, each
+ author represents that any applicable patent or other IPR claims of
+ which he or she is aware have been or will be disclosed, and any of
+ which he or she become aware will be disclosed, in accordance with
+ RFC 3668.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as
+ Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on August 25, 2005.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document collects and summarizes different proposals for
+ alternative and additional strategies for authenticated denial in DNS
+ responses, evaluates these proposals and gives a recommendation for a
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 1]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+ way forward.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Transition Mechanisms . . . . . . . . . . . . . . . . . . . . 3
+ 2.1 Mechanisms With Need of Updating DNSSEC-bis . . . . . . . 4
+ 2.1.1 Dynamic NSEC Synthesis . . . . . . . . . . . . . . . . 4
+ 2.1.2 Add Versioning/Subtyping to Current NSEC . . . . . . . 5
+ 2.1.3 Type Bit Map NSEC Indicator . . . . . . . . . . . . . 6
+ 2.1.4 New Apex Type . . . . . . . . . . . . . . . . . . . . 6
+ 2.1.5 NSEC White Lies . . . . . . . . . . . . . . . . . . . 7
+ 2.1.6 NSEC Optional via DNSSKEY Flag . . . . . . . . . . . . 8
+ 2.1.7 New Answer Pseudo RR Type . . . . . . . . . . . . . . 9
+ 2.1.8 SIG(0) Based Authenticated Denial . . . . . . . . . . 9
+ 2.2 Mechanisms Without Need of Updating DNSSEC-bis . . . . . . 10
+ 2.2.1 Partial Type-code and Signal Rollover . . . . . . . . 10
+ 2.2.2 A Complete Type-code and Signal Rollover . . . . . . . 11
+ 2.2.3 Unknown Algorithm in RRSIG . . . . . . . . . . . . . . 11
+ 3. Recommendation . . . . . . . . . . . . . . . . . . . . . . . . 12
+ 4. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 13
+ 5. References . . . . . . . . . . . . . . . . . . . . . . . . . . 13
+ 5.1 Normative References . . . . . . . . . . . . . . . . . . . 13
+ 5.2 Informative References . . . . . . . . . . . . . . . . . . 13
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 14
+ Intellectual Property and Copyright Statements . . . . . . . . 15
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 2]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+1. Introduction
+
+ This report shall document the process of dealing with the NSEC
+ walking problem late in the Last Call for
+ [I-D.ietf-dnsext-dnssec-intro, I-D.ietf-dnsext-dnssec-protocol,
+ I-D.ietf-dnsext-dnssec-records]. It preserves some of the discussion
+ that took place in the DNSEXT WG during the first half of June 2004
+ as well as some additional ideas that came up subsequently.
+
+ This is an edited excerpt of the chairs' mail to the WG:
+ The working group consents on not including NSEC-alt in the
+ DNSSEC-bis documents. The working group considers to take up
+ "prevention of zone enumeration" as a work item.
+ There may be multiple mechanisms to allow for co-existence with
+ DNSSEC-bis. The chairs allow the working group a little over a
+ week (up to June 12, 2004) to come to consensus on a possible
+ modification to the document to enable gentle rollover. If that
+ consensus cannot be reached the DNSSEC-bis documents will go out
+ as-is.
+
+ To ease the process of getting consensus, a summary of the proposed
+ solutions and analysis of the pros and cons were written during the
+ weekend.
+
+ This summary includes:
+
+ An inventory of the proposed mechanisms to make a transition to
+ future work on authenticated denial of existence.
+ List the known Pros and Cons, possibly provide new arguments, and
+ possible security considerations of these mechanisms.
+ Provide a recommendation on a way forward that is least disruptive
+ to the DNSSEC-bis specifications as they stand and keep an open
+ path to other methods for authenticated denial of existence.
+
+ The descriptions of the proposals in this document are coarse and do
+ not cover every detail necessary for implementation. In any case,
+ documentation and further study is needed before implementaion and/or
+ deployment, including those which seem to be solely operational in
+ nature.
+
+2. Transition Mechanisms
+
+ In the light of recent discussions and past proposals, we have found
+ several ways to allow for transition to future expansion of
+ authenticated denial. We tried to illuminate the paths and pitfalls
+ in these ways forward. Some proposals lead to a versioning of
+ DNSSEC, where DNSSEC-bis may co-exist with DNSSEC-ter, other
+ proposals are 'clean' but may cause delay, while again others may be
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 3]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+ plain hacks.
+
+ Some paths do not introduce versioning, and might require the current
+ DNSSEC-bis documents to be fully updated to allow for extensions to
+ authenticated denial mechanisms. Other paths introduce versioning
+ and do not (or minimally) require DNSSEC-bis documents to be updated,
+ allowing DNSSEC-bis to be deployed, while future versions can be
+ drafted independent from or partially depending on DNSSEC-bis.
+
+2.1 Mechanisms With Need of Updating DNSSEC-bis
+
+ Mechanisms in this category demand updates to the DNSSEC-bis document
+ set.
+
+2.1.1 Dynamic NSEC Synthesis
+
+ This proposal assumes that NSEC RRs and the authenticating RRSIG will
+ be generated dynamically to just cover the (non existent) query name.
+ The owner name is (the) one preceding the name queried for, the Next
+ Owner Name Field has the value of the Query Name Field + 1 (first
+ successor in canonical ordering). A separate key (the normal ZSK or
+ a separate ZSK per authoritative server) would be used for RRSIGs on
+ NSEC RRs. This is a defense against enumeration, though it has the
+ presumption of online signing.
+
+2.1.1.1 Coexistence and Migration
+
+ There is no change in interpretation other then that the next owner
+ name might or might not exist.
+
+2.1.1.2 Limitations
+
+ This introduces an unbalanced cost between query and response
+ generation due to dynamic generation of signatures.
+
+2.1.1.3 Amendments to DNSSEC-bis
+
+ The current DNSSEC-bis documents might need to be updated to indicate
+ that the next owner name might not be an existing name in the zone.
+ This is not a real change to the spec since implementers have been
+ warned not to synthesize with previously cached NSEC records. A
+ specific bit to identify the dynamic signature generating key might
+ be useful as well, to prevent it from being used to fake positive
+ data.
+
+2.1.1.4 Cons
+
+ Unbalanced cost is a ground for DDoS. Though this protects against
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 4]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+ enumeration, it is not really a path for versioning.
+
+2.1.1.5 Pros
+
+ Hardly any amendments to DNSSEC-bis.
+
+2.1.2 Add Versioning/Subtyping to Current NSEC
+
+ This proposal introduces versioning for the NSEC RR type (a.k.a.
+ subtyping) by adding a (one octet) version field to the NSEC RDATA.
+ Version number 0 is assigned to the current (DNSSEC-bis) meaning,
+ making this an 'Must Be Zero' (MBZ) for the to be published docset.
+
+2.1.2.1 Coexistence and Migration
+
+ Since the versioning is done inside the NSEC RR, different versions
+ may coexist. However, depending on future methods, that may or may
+ not be useful inside a single zone. Resolvers cannot ask for
+ specific NSEC versions but may be able to indicate version support by
+ means of a to be defined EDNS option bit.
+
+2.1.2.2 Limitations
+
+ There are no technical limitations, though it will cause delay to
+ allow testing of the (currently unknown) new NSEC interpretation.
+
+ Since the versioning and signaling is done inside the NSEC RR, future
+ methods will likely be restricted to a single RR type authenticated
+ denial (as opposed to e.g. NSEC-alt, which currently proposes three
+ RR types).
+
+2.1.2.3 Amendments to DNSSEC-bis
+
+ Full Update of the current DNSSEC-bis documents to provide for new
+ fields in NSEC, while specifying behavior in case of unknown field
+ values.
+
+2.1.2.4 Cons
+
+ Though this is a clean and clear path without versioning DNSSEC, it
+ takes some time to design, gain consensus, update the current
+ dnssec-bis document, test and implement a new authenticated denial
+ record.
+
+2.1.2.5 Pros
+
+ Does not introduce an iteration to DNSSEC while providing a clear and
+ clean migration strategy.
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 5]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+2.1.3 Type Bit Map NSEC Indicator
+
+ Bits in the type-bit-map are reused or allocated to signify the
+ interpretation of NSEC.
+
+ This proposal assumes that future extensions make use of the existing
+ NSEC RDATA syntax, while it may need to change the interpretation of
+ the RDATA or introduce an alternative denial mechanism, invoked by
+ the specific type-bit-map-bits.
+
+2.1.3.1 Coexistence and migration
+
+ Old and new NSEC meaning could coexist, depending how the signaling
+ would be defined. The bits for NXT, NSEC, RRSIG or other outdated RR
+ types are available as well as those covering meta/query types or
+ types to be specifically allocated.
+
+2.1.3.2 Limitations
+
+ This mechanism uses an NSEC field that was not designed for that
+ purpose. Similar methods were discussed during the Opt-In discussion
+ and the Silly-State discussion.
+
+2.1.3.3 Amendments to DNSSEC-bis
+
+ The specific type-bit-map-bits must be allocated and they need to be
+ specified as 'Must Be Zero' (MBZ) when used for standard (dnssec-bis)
+ interpretation. Also, behaviour of the resolver and validator must
+ be documented in case unknown values are encountered for the MBZ
+ field. Currently the protocol document specifies that the validator
+ MUST ignore the setting of the NSEC and the RRSIG bits, while other
+ bits are only used for the specific purpose of the type-bit-map field
+
+2.1.3.4 Cons
+
+ The type-bit-map was not designed for this purpose. It is a
+ straightforward hack. Text in protocol section 5.4 was put in
+ specially to defend against this usage.
+
+2.1.3.5 Pros
+
+ No change needed to the on-the-wire protocol as specified in the
+ current docset.
+
+2.1.4 New Apex Type
+
+ This introduces a new Apex type (parallel to the zone's SOA)
+ indicating the DNSSEC version (or authenticated denial) used in or
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 6]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+ for this zone.
+
+2.1.4.1 Coexistence and Migration
+
+ Depending on the design of this new RR type multiple denial
+ mechanisms may coexist in a zone. Old validators will not understand
+ and thus ignore the new type, so interpretation of the new NSEC
+ scheme may fail, negative responses may appear 'bogus'.
+
+2.1.4.2 Limitations
+
+ A record of this kind is likely to carry additional
+ feature/versioning indications unrelated to the current question of
+ authenticated denial.
+
+2.1.4.3 Amendments to DNSSEC-bis
+
+ The current DNSSEC-bis documents need to be updated to indicate that
+ the absence of this type indicates dnssec-bis, and that the (mere)
+ presence of this type indicated unknown versions.
+
+2.1.4.4 Cons
+
+ The only other 'zone' or 'apex' record is the SOA record. Though
+ this proposal is not new, it is yet unknown how it might fulfill
+ authenticated denial extensions. This new RR type would only provide
+ for a generalized signaling mechanism, not the new authenticated
+ denial scheme. Since it is likely to be general in nature, due to
+ this generality consensus is not to be reached soon.
+
+2.1.4.5 Pros
+
+ This approach would allow for a lot of other per zone information to
+ be transported or signaled to both (slave) servers and resolvers.
+
+2.1.5 NSEC White Lies
+
+ This proposal disables one part of NSEC (the pointer part) by means
+ of a special target (root, apex, owner, ...), leaving intact only the
+ ability to authenticate denial of existence of RR sets, not denial of
+ existence of domain names (NXDOMAIN). It may be necessary to have
+ one working NSEC to prove the absence of a wildcard.
+
+2.1.5.1 Coexistence and Migration
+
+ The NSEC target can be specified per RR, so standard NSEC and 'white
+ lie' NSEC can coexist in a zone. There is no need for migration
+ because no versioning is introduced or intended.
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 7]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+2.1.5.2 Limitations
+
+ This proposal breaks the protocol and is applicable to certain types
+ of zones only (no wildcard, no deep names, delegation only). Most of
+ the burden is put on the resolver side and operational consequences
+ are yet to be studied.
+
+2.1.5.3 Amendments to DNSSEC-bis
+
+ The current DNSSEC-bis documents need to be updated to indicate that
+ the NXDOMAIN responses may be insecure.
+
+2.1.5.4 Cons
+
+ Strictly speaking this breaks the protocol and doesn't fully fulfill
+ the requirements for authenticated denial of existence. Security
+ implications need to be carefully documented: search path problems
+ (forged denial of existence may lead to wrong expansion of non-FQDNs
+ [RFC1535]) and replay attacks to deny existence of records.
+
+2.1.5.5 Pros
+
+ Hardly any amendments to DNSSEC-bis. Operational "trick" that is
+ available anyway.
+
+2.1.6 NSEC Optional via DNSSKEY Flag
+
+ A new DNSKEY may be defined to declare NSEC optional per zone.
+
+2.1.6.1 Coexistence and Migration
+
+ Current resolvers/validators will not understand the Flag bit and
+ will have to treat negative responses as bogus. Otherwise, no
+ migration path is needed since NSEC is simply turned off.
+
+2.1.6.2 Limitations
+
+ NSEC can only be made completely optional at the cost of being unable
+ to prove unsecure delegations (absence of a DS RR [RFC3658]). A next
+ to this approach would just disable authenticated denial for
+ non-existence of nodes.
+
+2.1.6.3 Amendments to DNSSEC-bis
+
+ New DNSKEY Flag to be defined. Resolver/Validator behaviour needs to
+ be specified in the light of absence of authenticated denial.
+
+
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 8]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+2.1.6.4 Cons
+
+ Doesn't fully meet requirements. Operational consequences to be
+ studied.
+
+2.1.6.5 Pros
+
+ Official version of the "trick" presented in (8). Operational
+ problems can be addressed during future work on validators.
+
+2.1.7 New Answer Pseudo RR Type
+
+ A new pseudo RR type may be defined that will be dynamically created
+ (and signed) by the responding authoritative server. The RR in the
+ response will cover the QNAME, QCLASS and QTYPE and will authenticate
+ both denial of existence of name (NXDOMAIN) or RRset.
+
+2.1.7.1 Coexistence and Migration
+
+ Current resolvers/validators will not understand the pseudo RR and
+ will thus not be able to process negative responses so testified. A
+ signaling or solicitation method would have to be specified.
+
+2.1.7.2 Limitations
+
+ This method can only be used with online keys and online signing
+ capacity.
+
+2.1.7.3 Amendments to DNSSEC-bis
+
+ Signaling method needs to be defined.
+
+2.1.7.4 Cons
+
+ Keys have to be held and processed online with all security
+ implications. An additional flag for those keys identifying them as
+ online or negative answer only keys should be considered.
+
+2.1.7.5 Pros
+
+ Expands DNSSEC authentication to the RCODE.
+
+2.1.8 SIG(0) Based Authenticated Denial
+
+
+2.1.8.1 Coexistence and Migration
+
+
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 9]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+2.1.8.2 Limitations
+
+
+2.1.8.3 Amendments to DNSSEC-bis
+
+
+2.1.8.4 Cons
+
+
+2.1.8.5 Pros
+
+
+2.2 Mechanisms Without Need of Updating DNSSEC-bis
+
+2.2.1 Partial Type-code and Signal Rollover
+
+ Carefully crafted type code/signal rollover to define a new
+ authenticated denial space that extends/replaces DNSSEC-bis
+ authenticated denial space. This particular path is illuminated by
+ Paul Vixie in a Message-Id <20040602070859.0F50913951@sa.vix.com>
+ posted to <namedroppers@ops.ietf.org> 2004-06-02.
+
+2.2.1.1 Coexistence and Migration
+
+ To protect the current resolver for future versions, a new DNSSEC-OK
+ bit must be allocated to make clear it does or does not understand
+ the future version. Also, a new DS type needs to be allocated to
+ allow differentiation between a current signed delegation and a
+ 'future' signed delegation. Also, current NSEC needs to be rolled
+ into a new authenticated denial type.
+
+2.2.1.2 Limitations
+
+ None.
+
+2.2.1.3 Amendments to DNSSEC-bis
+
+ None.
+
+2.2.1.4 Cons
+
+ It is cumbersome to carefully craft an TCR that 'just fits'. The
+ DNSSEC-bis protocol has many 'borderline' cases that needs special
+ consideration. It might be easier to do a full TCR, since a few of
+ the types and signals need upgrading anyway.
+
+
+
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 10]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+2.2.1.5 Pros
+
+ Graceful adoption of future versions of NSEC, while there are no
+ amendments to DNSSEC-bis.
+
+2.2.2 A Complete Type-code and Signal Rollover
+
+ A new DNSSEC space is defined which can exist independent of current
+ DNSSEC-bis space.
+
+ This proposal assumes that all current DNSSEC type-codes
+ (RRSIG/DNSKEY/NSEC/DS) and signals (DNSSEC-OK) are not used in any
+ future versions of DNSSEC. Any future version of DNSSEC has its own
+ types to allow for keys, signatures, authenticated denial, etcetera.
+
+2.2.2.1 Coexistence and Migration
+
+ Both spaces can co-exist. They can be made completely orthogonal.
+
+2.2.2.2 Limitations
+
+ None.
+
+2.2.2.3 Amendments to DNSSEC-bis
+
+ None.
+
+2.2.2.4 Cons
+
+ With this path we abandon the current DNSSEC-bis. Though it is easy
+ to role specific well-known and well-tested parts into the re-write,
+ once deployment has started this path is very expensive for
+ implementers, registries, registrars and registrants as well as
+ resolvers/users. A TCR is not to be expected to occur frequently, so
+ while a next generation authenticated denial may be enabled by a TCR,
+ it is likely that that TCR will only be agreed upon if it serves a
+ whole basket of changes or additions. A quick introduction of
+ NSEC-ng should not be expected from this path.
+
+2.2.2.5 Pros
+
+ No amendments/changes to current DNSSEC-bis docset needed. It is
+ always there as last resort.
+
+2.2.3 Unknown Algorithm in RRSIG
+
+ This proposal assumes that future extensions make use of the existing
+ NSEC RDATA syntax, while it may need to change the interpretation of
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 11]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+ the RDATA or introduce an alternative denial mechanism, invoked by
+ the specific unknown signing algorithm. The different interpretation
+ would be signaled by use of different signature algorithms in the
+ RRSIG records covering the NSEC RRs.
+
+ When an entire zone is signed with a single unknown algorithm, it
+ will cause implementations that follow current dnssec-bis documents
+ to treat individual RRsets as unsigned.
+
+2.2.3.1 Coexistence and migration
+
+ Old and new NSEC RDATA interpretation or known and unknown Signatures
+ can NOT coexist in a zone since signatures cover complete (NSEC)
+ RRSets.
+
+2.2.3.2 Limitations
+
+ Validating resolvers agnostic of new interpretation will treat the
+ NSEC RRset as "not signed". This affects wildcard and non-existence
+ proof, as well as proof for (un)secured delegations. Also, all
+ positive signatures (RRSIGs on RRSets other than DS, NSEC) appear
+ insecure/bogus to an old validator.
+
+ The algorithm version space is split for each future version of
+ DNSSEC. Violation of the 'modular components' concept. We use the
+ 'validator' to protect the 'resolver' from unknown interpretations.
+
+2.2.3.3 Amendments to DNSSEC-bis
+
+ None.
+
+2.2.3.4 Cons
+
+ The algorithm field was not designed for this purpose. This is a
+ straightforward hack.
+
+2.2.3.5 Pros
+
+ No amendments/changes to current DNSSEC-bis docset needed.
+
+3. Recommendation
+
+ The authors recommend that the working group commits to and starts
+ work on a partial TCR, allowing graceful transition towards a future
+ version of NSEC. Meanwhile, to accomodate the need for an
+ immediately, temporary, solution against zone-traversal, we recommend
+ On-Demand NSEC synthesis.
+
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 12]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+ This approach does not require any mandatory changes to DNSSEC-bis,
+ does not violate the protocol and fulfills the requirements. As a
+ side effect, it moves the cost of implementation and deployment to
+ the users (zone owners) of this mechanism.
+
+4. Acknowledgements
+
+ The authors would like to thank Sam Weiler and Mark Andrews for their
+ input and constructive comments.
+
+5. References
+
+5.1 Normative References
+
+ [I-D.ietf-dnsext-dnssec-intro]
+ Arends, R., Austein, R., Massey, D., Larson, M. and S.
+ Rose, "DNS Security Introduction and Requirements",
+ Internet-Draft draft-ietf-dnsext-dnssec-intro-13, October
+ 2004.
+
+ [I-D.ietf-dnsext-dnssec-protocol]
+ Arends, R., "Protocol Modifications for the DNS Security
+ Extensions",
+ Internet-Draft draft-ietf-dnsext-dnssec-protocol-09,
+ October 2004.
+
+ [I-D.ietf-dnsext-dnssec-records]
+ Arends, R., "Resource Records for the DNS Security
+ Extensions",
+ Internet-Draft draft-ietf-dnsext-dnssec-records-11,
+ October 2004.
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2931] Eastlake, D., "DNS Request and Transaction Signatures (
+ SIG(0)s)", RFC 2931, September 2000.
+
+5.2 Informative References
+
+ [RFC1535] Gavron, E., "A Security Problem and Proposed Correction
+ With Widely Deployed DNS Software", RFC 1535, October
+ 1993.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions",
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 13]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+ RFC 2535, March 1999.
+
+ [RFC2629] Rose, M., "Writing I-Ds and RFCs using XML", RFC 2629,
+ June 1999.
+
+ [RFC3658] Gudmundsson, O., "Delegation Signer (DS) Resource Record
+ (RR)", RFC 3658, December 2003.
+
+
+Authors' Addresses
+
+ Roy Arends
+ Telematica Instituut
+ Brouwerijstraat 1
+ Enschede 7523 XC
+ The Netherlands
+
+ Phone: +31 53 4850485
+ Email: roy.arends@telin.nl
+
+
+ Peter Koch
+ DENIC eG
+ Wiesenh"uttenplatz 26
+ Frankfurt 60329
+ Germany
+
+ Phone: +49 69 27235 0
+ Email: pk@DENIC.DE
+
+
+ Jakob Schlyter
+ NIC-SE
+ Box 5774
+ Stockholm SE-114 87
+ Sweden
+
+ Email: jakob@nic.se
+ URI: http://www.nic.se/
+
+
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 14]
+
+Internet-Draft Evaluating DNSSEC Transition Mechanisms February 2005
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2005). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Arends, et al. Expires August 25, 2005 [Page 15]
+
+
diff --git a/doc/draft/draft-ietf-dnsext-ds-sha256-05.txt b/doc/draft/draft-ietf-dnsext-ds-sha256-05.txt
new file mode 100644
index 0000000..2460cb6
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-ds-sha256-05.txt
@@ -0,0 +1,504 @@
+
+
+
+Network Working Group W. Hardaker
+Internet-Draft Sparta
+Expires: August 25, 2006 February 21, 2006
+
+
+ Use of SHA-256 in DNSSEC Delegation Signer (DS) Resource Records (RRs)
+ draft-ietf-dnsext-ds-sha256-05.txt
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on August 25, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ This document specifies how to use the SHA-256 digest type in DNS
+ Delegation Signer (DS) Resource Records (RRs). DS records, when
+ stored in a parent zone, point to key signing DNSKEY key(s) in a
+ child zone.
+
+
+
+
+
+
+
+
+Hardaker Expires August 25, 2006 [Page 1]
+
+Internet-Draft Use of SHA-256 in DNSSEC DS RRs February 2006
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Implementing the SHA-256 algorithm for DS record support . . . 3
+ 2.1. DS record field values . . . . . . . . . . . . . . . . . . 3
+ 2.2. DS Record with SHA-256 Wire Format . . . . . . . . . . . . 3
+ 2.3. Example DS Record Using SHA-256 . . . . . . . . . . . . . . 4
+ 3. Implementation Requirements . . . . . . . . . . . . . . . . . . 4
+ 4. Deployment Considerations . . . . . . . . . . . . . . . . . . . 4
+ 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 5
+ 6. Security Considerations . . . . . . . . . . . . . . . . . . . . 5
+ 6.1. Potential Digest Type Downgrade Attacks . . . . . . . . . . 5
+ 6.2. SHA-1 vs SHA-256 Considerations for DS Records . . . . . . 6
+ 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 8. References . . . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 8.1. Normative References . . . . . . . . . . . . . . . . . . . 7
+ 8.2. Informative References . . . . . . . . . . . . . . . . . . 7
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 8
+ Intellectual Property and Copyright Statements . . . . . . . . . . 9
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hardaker Expires August 25, 2006 [Page 2]
+
+Internet-Draft Use of SHA-256 in DNSSEC DS RRs February 2006
+
+
+1. Introduction
+
+ The DNSSEC [RFC4033] [RFC4034] [RFC4035] DS RR is published in parent
+ zones to distribute a cryptographic digest of a child's Key Signing
+ Key (KSK) DNSKEY RR. The DS RRset is signed by at least one of the
+ parent zone's private zone data signing keys for each algorithm in
+ use by the parent. Each signature is published in an RRSIG resource
+ record, owned by the same domain as the DS RRset and with a type
+ covered of DS.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+
+2. Implementing the SHA-256 algorithm for DS record support
+
+ This document specifies that the digest type code [XXX: To be
+ assigned by IANA; likely 2] is to be assigned to SHA-256 [SHA256]
+ [SHA256CODE] for use within DS records. The results of the digest
+ algorithm MUST NOT be truncated and the entire 32 byte digest result
+ is to be published in the DS record.
+
+2.1. DS record field values
+
+ Using the SHA-256 digest algorithm within a DS record will make use
+ of the following DS-record fields:
+
+ Digest type: [XXX: To be assigned by IANA; likely 2]
+
+ Digest: A SHA-256 bit digest value calculated by using the following
+ formula ("|" denotes concatenation). The resulting value is not
+ truncated and the entire 32 byte result is to used in the
+ resulting DS record and related calculations.
+
+ digest = SHA_256(DNSKEY owner name | DNSKEY RDATA)
+
+ where DNSKEY RDATA is defined by [RFC4034] as:
+
+ DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key
+
+ The Key Tag field and Algorithm fields remain unchanged by this
+ document and are specified in the [RFC4034] specification.
+
+2.2. DS Record with SHA-256 Wire Format
+
+ The resulting on-the-wire format for the resulting DS record will be
+ [XXX: IANA assignment should replace the 2 below]:
+
+
+
+Hardaker Expires August 25, 2006 [Page 3]
+
+Internet-Draft Use of SHA-256 in DNSSEC DS RRs February 2006
+
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Key Tag | Algorithm | DigestType=2 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / /
+ / Digest (length for SHA-256 is 32 bytes) /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+
+2.3. Example DS Record Using SHA-256
+
+ The following is an example DNSKEY and matching DS record. This
+ DNSKEY record comes from the example DNSKEY/DS records found in
+ section 5.4 of [RFC4034].
+
+ The DNSKEY record:
+
+ dskey.example.com. 86400 IN DNSKEY 256 3 5 ( AQOeiiR0GOMYkDshWoSKz9Xz
+ fwJr1AYtsmx3TGkJaNXVbfi/
+ 2pHm822aJ5iI9BMzNXxeYCmZ
+ DRD99WYwYqUSdjMmmAphXdvx
+ egXd/M5+X7OrzKBaMbCVdFLU
+ Uh6DhweJBjEVv5f2wwjM9Xzc
+ nOf+EPbtG9DMBmADjFDc2w/r
+ ljwvFw==
+ ) ; key id = 60485
+
+ The resulting DS record covering the above DNSKEY record using a SHA-
+ 256 digest: [RFC Editor: please replace XXX with the assigned digest
+ type (likely 2):]
+
+ dskey.example.com. 86400 IN DS 60485 5 XXX ( D4B7D520E7BB5F0F67674A0C
+ CEB1E3E0614B93C4F9E99B83
+ 83F6A1E4469DA50A )
+
+
+3. Implementation Requirements
+
+ Implementations MUST support the use of the SHA-256 algorithm in DS
+ RRs. Validator implementations SHOULD ignore DS RRs containing SHA-1
+ digests if DS RRs with SHA-256 digests are present in the DS RRset.
+
+
+4. Deployment Considerations
+
+ If a validator does not support the SHA-256 digest type and no other
+ DS RR exists in a zone's DS RRset with a supported digest type, then
+
+
+
+Hardaker Expires August 25, 2006 [Page 4]
+
+Internet-Draft Use of SHA-256 in DNSSEC DS RRs February 2006
+
+
+ the validator has no supported authentication path leading from the
+ parent to the child. The resolver should treat this case as it would
+ the case of an authenticated NSEC RRset proving that no DS RRset
+ exists, as described in [RFC4035], section 5.2.
+
+ Because zone administrators can not control the deployment speed of
+ support for SHA-256 in validators that may be referencing any of
+ their zones, zone operators should consider deploying both SHA-1 and
+ SHA-256 based DS records. This should be done for every DNSKEY for
+ which DS records are being generated. Whether to make use of both
+ digest types and for how long is a policy decision that extends
+ beyond the scope of this document.
+
+
+5. IANA Considerations
+
+ Only one IANA action is required by this document:
+
+ The Digest Type to be used for supporting SHA-256 within DS records
+ needs to be assigned by IANA. This document requests that the Digest
+ Type value of 2 be assigned to the SHA-256 digest algorithm.
+
+ At the time of this writing, the current digest types assigned for
+ use in DS records are as follows:
+
+ VALUE Digest Type Status
+ 0 Reserved -
+ 1 SHA-1 MANDATORY
+ 2 SHA-256 MANDATORY
+ 3-255 Unassigned -
+
+
+6. Security Considerations
+
+6.1. Potential Digest Type Downgrade Attacks
+
+ A downgrade attack from a stronger digest type to a weaker one is
+ possible if all of the following are true:
+
+ o A zone includes multiple DS records for a given child's DNSKEY,
+ each of which use a different digest type.
+
+ o A validator accepts a weaker digest even if a stronger one is
+ present but invalid.
+
+ For example, if the following conditions are all true:
+
+
+
+
+
+Hardaker Expires August 25, 2006 [Page 5]
+
+Internet-Draft Use of SHA-256 in DNSSEC DS RRs February 2006
+
+
+ o Both SHA-1 and SHA-256 based digests are published in DS records
+ within a parent zone for a given child zone's DNSKEY.
+
+ o The DS record with the SHA-1 digest matches the digest computed
+ using the child zone's DNSKEY.
+
+ o The DS record with the SHA-256 digest fails to match the digest
+ computed using the child zone's DNSKEY.
+
+ Then if the validator accepts the above situation as secure then this
+ can be used as a downgrade attack since the stronger SHA-256 digest
+ is ignored.
+
+6.2. SHA-1 vs SHA-256 Considerations for DS Records
+
+ Users of DNSSEC are encouraged to deploy SHA-256 as soon as software
+ implementations allow for it. SHA-256 is widely believed to be more
+ resilient to attack than SHA-1, and confidence in SHA-1's strength is
+ being eroded by recently-announced attacks. Regardless of whether or
+ not the attacks on SHA-1 will affect DNSSEC, it is believed (at the
+ time of this writing) that SHA-256 is the better choice for use in DS
+ records.
+
+ At the time of this publication, the SHA-256 digest algorithm is
+ considered sufficiently strong for the immediate future. It is also
+ considered sufficient for use in DNSSEC DS RRs for the immediate
+ future. However, future published attacks may weaken the usability
+ of this algorithm within the DS RRs. It is beyond the scope of this
+ document to speculate extensively on the cryptographic strength of
+ the SHA-256 digest algorithm.
+
+ Likewise, it is also beyond the scope of this document to specify
+ whether or for how long SHA-1 based DS records should be
+ simultaneously published alongside SHA-256 based DS records.
+
+
+7. Acknowledgments
+
+ This document is a minor extension to the existing DNSSEC documents
+ and those authors are gratefully appreciated for the hard work that
+ went into the base documents.
+
+ The following people contributed to portions of this document in some
+ fashion: Mark Andrews, Roy Arends, Olafur Gudmundsson, Paul Hoffman,
+ Olaf M. Kolkman, Edward Lewis, Scott Rose, Stuart E. Schechter, Sam
+ Weiler.
+
+
+
+
+
+Hardaker Expires August 25, 2006 [Page 6]
+
+Internet-Draft Use of SHA-256 in DNSSEC DS RRs February 2006
+
+
+8. References
+
+8.1. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements",
+ RFC 4033, March 2005.
+
+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security Extensions",
+ RFC 4034, March 2005.
+
+ [RFC4035] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security
+ Extensions", RFC 4035, March 2005.
+
+ [SHA256] National Institute of Standards and Technology, "Secure
+ Hash Algorithm. NIST FIPS 180-2", August 2002.
+
+8.2. Informative References
+
+ [SHA256CODE]
+ Eastlake, D., "US Secure Hash Algorithms (SHA)",
+ June 2005.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hardaker Expires August 25, 2006 [Page 7]
+
+Internet-Draft Use of SHA-256 in DNSSEC DS RRs February 2006
+
+
+Author's Address
+
+ Wes Hardaker
+ Sparta
+ P.O. Box 382
+ Davis, CA 95617
+ US
+
+ Email: hardaker@tislabs.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hardaker Expires August 25, 2006 [Page 8]
+
+Internet-Draft Use of SHA-256 in DNSSEC DS RRs February 2006
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2006). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Hardaker Expires August 25, 2006 [Page 9]
+
diff --git a/doc/draft/draft-ietf-dnsext-ecc-key-07.txt b/doc/draft/draft-ietf-dnsext-ecc-key-07.txt
new file mode 100644
index 0000000..2cdcdb1
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-ecc-key-07.txt
@@ -0,0 +1,928 @@
+
+INTERNET-DRAFT ECC Keys in the DNS
+Expires: January 2006 July 2005
+
+
+
+ Elliptic Curve KEYs in the DNS
+ -------- ----- ---- -- --- ---
+ <draft-ietf-dnsext-ecc-key-07.txt>
+
+ Richard C. Schroeppel
+ Donald Eastlake 3rd
+
+
+Status of This Document
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ This draft is intended to be become a Proposed Standard RFC.
+ Distribution of this document is unlimited. Comments should be sent
+ to the DNS mailing list <namedroppers@ops.ietf.org>.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than a "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+
+Abstract
+
+ The standard method for storing elliptic curve cryptographic keys and
+ signatures in the Domain Name System is specified.
+
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005). All Rights Reserved.
+
+
+
+
+
+R. Schroeppel, et al [Page 1]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+Acknowledgement
+
+ The assistance of Hilarie K. Orman in the production of this document
+ is greatfully acknowledged.
+
+
+
+Table of Contents
+
+ Status of This Document....................................1
+ Abstract...................................................1
+ Copyright Notice...........................................1
+
+ Acknowledgement............................................2
+ Table of Contents..........................................2
+
+ 1. Introduction............................................3
+ 2. Elliptic Curve Data in Resource Records.................3
+ 3. The Elliptic Curve Equation.............................9
+ 4. How do I Compute Q, G, and Y?..........................10
+ 5. Elliptic Curve SIG Resource Records....................11
+ 6. Performance Considerations.............................13
+ 7. Security Considerations................................13
+ 8. IANA Considerations....................................13
+ Copyright and Disclaimer..................................14
+
+ Informational References..................................15
+ Normative Refrences.......................................15
+
+ Author's Addresses........................................16
+ Expiration and File Name..................................16
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+R. Schroeppel, et al [Page 2]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+1. Introduction
+
+ The Domain Name System (DNS) is the global hierarchical replicated
+ distributed database system for Internet addressing, mail proxy, and
+ other information. The DNS has been extended to include digital
+ signatures and cryptographic keys as described in [RFC 4033, 4034,
+ 4035].
+
+ This document describes how to store elliptic curve cryptographic
+ (ECC) keys and signatures in the DNS so they can be used for a
+ variety of security purposes. Familiarity with ECC cryptography is
+ assumed [Menezes].
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC 2119].
+
+
+
+2. Elliptic Curve Data in Resource Records
+
+ Elliptic curve public keys are stored in the DNS within the RDATA
+ portions of key RRs, such as RRKEY and KEY [RFC 4034] RRs, with the
+ structure shown below.
+
+ The research world continues to work on the issue of which is the
+ best elliptic curve system, which finite field to use, and how to
+ best represent elements in the field. So, representations are
+ defined for every type of finite field, and every type of elliptic
+ curve. The reader should be aware that there is a unique finite
+ field with a particular number of elements, but many possible
+ representations of that field and its elements. If two different
+ representations of a field are given, they are interconvertible with
+ a tedious but practical precomputation, followed by a fast
+ computation for each field element to be converted. It is perfectly
+ reasonable for an algorithm to work internally with one field
+ representation, and convert to and from a different external
+ representation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+R. Schroeppel, et al [Page 3]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |S M -FMT- A B Z|
+ +-+-+-+-+-+-+-+-+
+ | LP |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | P (length determined from LP) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | LF |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | F (length determined from LF) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | DEG |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | DEGH |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | DEGI |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | DEGJ |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | TRDV |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |S| LH |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | H (length determined from LH) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |S| LK |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | K (length determined from LK) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | LQ |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Q (length determined from LQ) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | LA |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | A (length determined from LA) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | ALTA |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | LB |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | B (length determined from LB) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | LC |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | C (length determined from LC) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | LG |
+
+
+R. Schroeppel, et al [Page 4]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | G (length determined from LG) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | LY |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Y (length determined from LY) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ SMFMTABZ is a flags octet as follows:
+
+ S = 1 indicates that the remaining 7 bits of the octet selects
+ one of 128 predefined choices of finite field, element
+ representation, elliptic curve, and signature parameters.
+ MFMTABZ are omitted, as are all parameters from LP through G.
+ LY and Y are retained.
+
+ If S = 0, the remaining parameters are as in the picture and
+ described below.
+
+ M determines the type of field underlying the elliptic curve.
+
+ M = 0 if the field is a GF[2^N] field;
+
+ M = 1 if the field is a (mod P) or GF[P^D] field with P>2.
+
+ FMT is a three bit field describing the format of the field
+ representation.
+
+ FMT = 0 for a (mod P) field.
+ > 0 for an extension field, either GF[2^D] or GF[P^D].
+ The degree D of the extension, and the field polynomial
+ must be specified. The field polynomial is always monic
+ (leading coefficient 1.)
+
+ FMT = 1 The field polynomial is given explicitly; D is implied.
+
+ If FMT >=2, the degree D is given explicitly.
+
+ = 2 The field polynomial is implicit.
+ = 3 The field polynomial is a binomial. P>2.
+ = 4 The field polynomial is a trinomial.
+ = 5 The field polynomial is the quotient of a trinomial by a
+ short polynomial. P=2.
+ = 6 The field polynomial is a pentanomial. P=2.
+
+ Flags A and B apply to the elliptic curve parameters.
+
+
+
+
+
+
+R. Schroeppel, et al [Page 5]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ A = 1 When P>=5, the curve parameter A is negated. If P=2, then
+ A=1 indicates that the A parameter is special. See the
+ ALTA parameter below, following A. The combination A=1,
+ P=3 is forbidden.
+
+ B = 1 When P>=5, the curve parameter B is negated. If P=2 or 3,
+ then B=1 indicates an alternate elliptic curve equation is
+ used. When P=2 and B=1, an additional curve parameter C
+ is present.
+
+ The Z bit SHOULD be set to zero on creation of an RR and MUST be
+ ignored when processing an RR (when S=0).
+
+ Most of the remaining parameters are present in some formats and
+ absent in others. The presence or absence of a parameter is
+ determined entirely by the flags. When a parameter occurs, it is in
+ the order defined by the picture.
+
+ Of the remaining parameters, PFHKQABCGY are variable length. When
+ present, each is preceded by a one-octet length field as shown in the
+ diagram above. The length field does not include itself. The length
+ field may have values from 0 through 110. The parameter length in
+ octets is determined by a conditional formula: If LL<=64, the
+ parameter length is LL. If LL>64, the parameter length is 16 times
+ (LL-60). In some cases, a parameter value of 0 is sensible, and MAY
+ be represented by an LL value of 0, with the data field omitted. A
+ length value of 0 represents a parameter value of 0, not an absent
+ parameter. (The data portion occupies 0 space.) There is no
+ requirement that a parameter be represented in the minimum number of
+ octets; high-order 0 octets are allowed at the front end. Parameters
+ are always right adjusted, in a field of length defined by LL. The
+ octet-order is always most-significant first, least-significant last.
+ The parameters H and K may have an optional sign bit stored in the
+ unused high-order bit of their length fields.
+
+ LP defines the length of the prime P. P must be an odd prime. The
+ parameters LP,P are present if and only if the flag M=1. If M=0, the
+ prime is 2.
+
+ LF,F define an explicit field polynomial. This parameter pair is
+ present only when FMT = 1. The length of a polynomial coefficient is
+ ceiling(log2 P) bits. Coefficients are in the numerical range
+ [0,P-1]. The coefficients are packed into fixed-width fields, from
+ higher order to lower order. All coefficients must be present,
+ including any 0s and also the leading coefficient (which is required
+ to be 1). The coefficients are right justified into the octet string
+ of length specified by LF, with the low-order "constant" coefficient
+ at the right end. As a concession to storage efficiency, the higher
+ order bits of the leading coefficient may be elided, discarding high-
+ order 0 octets and reducing LF. The degree is calculated by
+
+
+R. Schroeppel, et al [Page 6]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ determining the bit position of the left most 1-bit in the F data
+ (counting the right most bit as position 0), and dividing by
+ ceiling(log2 P). The division must be exact, with no remainder. In
+ this format, all of the other degree and field parameters are
+ omitted. The next parameters will be LQ,Q.
+
+ If FMT>=2, the degree of the field extension is specified explicitly,
+ usually along with other parameters to define the field polynomial.
+
+ DEG is a two octet field that defines the degree of the field
+ extension. The finite field will have P^DEG elements. DEG is
+ present when FMT>=2.
+
+ When FMT=2, the field polynomial is specified implicitly. No other
+ parameters are required to define the field; the next parameters
+ present will be the LQ,Q pair. The implicit field poynomial is the
+ lexicographically smallest irreducible (mod P) polynomial of the
+ correct degree. The ordering of polynomials is by highest-degree
+ coefficients first -- the leading coefficient 1 is most important,
+ and the constant term is least important. Coefficients are ordered
+ by sign-magnitude: 0 < 1 < -1 < 2 < -2 < ... The first polynomial of
+ degree D is X^D (which is not irreducible). The next is X^D+1, which
+ is sometimes irreducible, followed by X^D-1, which isn't. Assuming
+ odd P, this series continues to X^D - (P-1)/2, and then goes to X^D +
+ X, X^D + X + 1, X^D + X - 1, etc.
+
+ When FMT=3, the field polynomial is a binomial, X^DEG + K. P must be
+ odd. The polynomial is determined by the degree and the low order
+ term K. Of all the field parameters, only the LK,K parameters are
+ present. The high-order bit of the LK octet stores on optional sign
+ for K; if the sign bit is present, the field polynomial is X^DEG - K.
+
+ When FMT=4, the field polynomial is a trinomial, X^DEG + H*X^DEGH +
+ K. When P=2, the H and K parameters are implicitly 1, and are
+ omitted from the representation. Only DEG and DEGH are present; the
+ next parameters are LQ,Q. When P>2, then LH,H and LK,K are
+ specified. Either or both of LH, LK may contain a sign bit for its
+ parameter.
+
+ When FMT=5, then P=2 (only). The field polynomial is the exact
+ quotient of a trinomial divided by a small polynomial, the trinomial
+ divisor. The small polynomial is right-adjusted in the two octet
+ field TRDV. DEG specifies the degree of the field. The degree of
+ TRDV is calculated from the position of the high-order 1 bit. The
+ trinomial to be divided is X^(DEG+degree(TRDV)) + X^DEGH + 1. If
+ DEGH is 0, the middle term is omitted from the trinomial. The
+ quotient must be exact, with no remainder.
+
+ When FMT=6, then P=2 (only). The field polynomial is a pentanomial,
+ with the degrees of the middle terms given by the three 2-octet
+
+
+R. Schroeppel, et al [Page 7]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ values DEGH, DEGI, DEGJ. The polynomial is X^DEG + X^DEGH + X^DEGI +
+ X^DEGJ + 1. The values must satisfy the inequality DEG > DEGH > DEGI
+ > DEGJ > 0.
+
+ DEGH, DEGI, DEGJ are two-octet fields that define the degree of
+ a term in a field polynomial. DEGH is present when FMT = 4,
+ 5, or 6. DEGI and DEGJ are present only when FMT = 6.
+
+ TRDV is a two-octet right-adjusted binary polynomial of degree <
+ 16. It is present only for FMT=5.
+
+ LH and H define the H parameter, present only when FMT=4 and P
+ is odd. The high bit of LH is an optional sign bit for H.
+
+ LK and K define the K parameter, present when FMT = 3 or 4, and
+ P is odd. The high bit of LK is an optional sign bit for K.
+
+ The remaining parameters are concerned with the elliptic curve and
+ the signature algorithm.
+
+ LQ defines the length of the prime Q. Q is a prime > 2^159.
+
+ In all 5 of the parameter pairs LA+A,LB+B,LC+C,LG+G,LY+Y, the data
+ member of the pair is an element from the finite field defined
+ earlier. The length field defines a long octet string. Field
+ elements are represented as (mod P) polynomials of degree < DEG, with
+ DEG or fewer coefficients. The coefficients are stored from left to
+ right, higher degree to lower, with the constant term last. The
+ coefficients are represented as integers in the range [0,P-1]. Each
+ coefficient is allocated an area of ceiling(log2 P) bits. The field
+ representation is right-justified; the "constant term" of the field
+ element ends at the right most bit. The coefficients are fitted
+ adjacently without regard for octet boundaries. (Example: if P=5,
+ three bits are used for each coefficient. If the field is GF[5^75],
+ then 225 bits are required for the coefficients, and as many as 29
+ octets may be needed in the data area. Fewer octets may be used if
+ some high-order coefficients are 0.) If a flag requires a field
+ element to be negated, each non-zero coefficient K is replaced with
+ P-K. To save space, 0 bits may be removed from the left end of the
+ element representation, and the length field reduced appropriately.
+ This would normally only happen with A,B,C, because the designer
+ chose curve parameters with some high-order 0 coefficients or bits.
+
+ If the finite field is simply (mod P), then the field elements are
+ simply numbers (mod P), in the usual right-justified notation. If
+ the finite field is GF[2^D], the field elements are the usual right-
+ justified polynomial basis representation.
+
+
+
+
+
+R. Schroeppel, et al [Page 8]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ LA,A is the first parameter of the elliptic curve equation.
+ When P>=5, the flag A = 1 indicates A should be negated (mod
+ P). When P=2 (indicated by the flag M=0), the flag A = 1
+ indicates that the parameter pair LA,A is replaced by the two
+ octet parameter ALTA. In this case, the parameter A in the
+ curve equation is x^ALTA, where x is the field generator.
+ Parameter A often has the value 0, which may be indicated by
+ LA=0 (with no A data field), and sometimes A is 1, which may
+ be represented with LA=1 and a data field of 1, or by setting
+ the A flag and using an ALTA value of 0.
+
+ LB,B is the second parameter of the elliptic curve equation.
+ When P>=5, the flag B = 1 indicates B should be negated (mod
+ P). When P=2 or 3, the flag B selects an alternate curve
+ equation.
+
+ LC,C is the third parameter of the elliptic curve equation,
+ present only when P=2 (indicated by flag M=0) and flag B=1.
+
+ LG,G defines a point on the curve, of order Q. The W-coordinate
+ of the curve point is given explicitly; the Z-coordinate is
+ implicit.
+
+ LY,Y is the user's public signing key, another curve point of
+ order Q. The W-coordinate is given explicitly; the Z-
+ coordinate is implicit. The LY,Y parameter pair is always
+ present.
+
+
+
+3. The Elliptic Curve Equation
+
+ (The coordinates of an elliptic curve point are named W,Z instead of
+ the more usual X,Y to avoid confusion with the Y parameter of the
+ signing key.)
+
+ The elliptic curve equation is determined by the flag octet, together
+ with information about the prime P. The primes 2 and 3 are special;
+ all other primes are treated identically.
+
+ If M=1, the (mod P) or GF[P^D] case, the curve equation is Z^2 = W^3
+ + A*W + B. Z,W,A,B are all numbers (mod P) or elements of GF[P^D].
+ If A and/or B is negative (i.e., in the range from P/2 to P), and
+ P>=5, space may be saved by putting the sign bit(s) in the A and B
+ bits of the flags octet, and the magnitude(s) in the parameter
+ fields.
+
+ If M=1 and P=3, the B flag has a different meaning: it specifies an
+ alternate curve equation, Z^2 = W^3 + A*W^2 + B. The middle term of
+ the right-hand-side is different. When P=3, this equation is more
+
+
+R. Schroeppel, et al [Page 9]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ commonly used.
+
+ If M=0, the GF[2^N] case, the curve equation is Z^2 + W*Z = W^3 +
+ A*W^2 + B. Z,W,A,B are all elements of the field GF[2^N]. The A
+ parameter can often be 0 or 1, or be chosen as a single-1-bit value.
+ The flag B is used to select an alternate curve equation, Z^2 + C*Z =
+ W^3 + A*W + B. This is the only time that the C parameter is used.
+
+
+
+4. How do I Compute Q, G, and Y?
+
+ The number of points on the curve is the number of solutions to the
+ curve equation, + 1 (for the "point at infinity"). The prime Q must
+ divide the number of points. Usually the curve is chosen first, then
+ the number of points is determined with Schoof's algorithm. This
+ number is factored, and if it has a large prime divisor, that number
+ is taken as Q.
+
+ G must be a point of order Q on the curve, satisfying the equation
+
+ Q * G = the point at infinity (on the elliptic curve)
+
+ G may be chosen by selecting a random [RFC 1750] curve point, and
+ multiplying it by (number-of-points-on-curve/Q). G must not itself
+ be the "point at infinity"; in this astronomically unlikely event, a
+ new random curve point is recalculated.
+
+ G is specified by giving its W-coordinate. The Z-coordinate is
+ calculated from the curve equation. In general, there will be two
+ possible Z values. The rule is to choose the "positive" value.
+
+ In the (mod P) case, the two possible Z values sum to P. The smaller
+ value is less than P/2; it is used in subsequent calculations. In
+ GF[P^D] fields, the highest-degree non-zero coefficient of the field
+ element Z is used; it is chosen to be less than P/2.
+
+ In the GF[2^N] case, the two possible Z values xor to W (or to the
+ parameter C with the alternate curve equation). The numerically
+ smaller Z value (the one which does not contain the highest-order 1
+ bit of W (or C)) is used in subsequent calculations.
+
+ Y is specified by giving the W-coordinate of the user's public
+ signature key. The Z-coordinate value is determined from the curve
+ equation. As with G, there are two possible Z values; the same rule
+ is followed for choosing which Z to use.
+
+
+
+
+
+
+R. Schroeppel, et al [Page 10]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ During the key generation process, a random [RFC 1750] number X must
+ be generated such that 1 <= X <= Q-1. X is the private key and is
+ used in the final step of public key generation where Y is computed
+ as
+
+ Y = X * G (as points on the elliptic curve)
+
+ If the Z-coordinate of the computed point Y is wrong (i.e., Z > P/2
+ in the (mod P) case, or the high-order non-zero coefficient of Z >
+ P/2 in the GF[P^D] case, or Z sharing a high bit with W(C) in the
+ GF[2^N] case), then X must be replaced with Q-X. This will
+ correspond to the correct Z-coordinate.
+
+
+
+5. Elliptic Curve SIG Resource Records
+
+ The signature portion of an RR RDATA area when using the EC
+ algorithm, for example in the RRSIG and SIG [RFC records] RRs is
+ shown below.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | R, (length determined from LQ) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | S, (length determined from LQ) .../
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ R and S are integers (mod Q). Their length is specified by the LQ
+ field of the corresponding KEY RR and can also be calculated from the
+ SIG RR's RDLENGTH. They are right justified, high-order-octet first.
+ The same conditional formula for calculating the length from LQ is
+ used as for all the other length fields above.
+
+ The data signed is determined as specified in [RFC 2535]. Then the
+ following steps are taken where Q, P, G, and Y are as specified in
+ the public key [Schneier]:
+
+ hash = SHA-1 ( data )
+
+ Generate random [RFC 4086] K such that 0 < K < Q. (Never sign two
+ different messages with the same K. K should be chosen from a
+ very large space: If an opponent learns a K value for a single
+ signature, the user's signing key is compromised, and a forger
+ can sign arbitrary messages. There is no harm in signing the
+ same message multiple times with the same key or different
+ keys.)
+
+ R = (the W-coordinate of ( K*G on the elliptic curve )) interpreted
+
+
+R. Schroeppel, et al [Page 11]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ as an integer, and reduced (mod Q). (R must not be 0. In
+ this astronomically unlikely event, generate a new random K
+ and recalculate R.)
+
+ S = ( K^(-1) * (hash + X*R) ) mod Q.
+
+ S must not be 0. In this astronomically unlikely event, generate a
+ new random K and recalculate R and S.
+
+ If S > Q/2, set S = Q - S.
+
+ The pair (R,S) is the signature.
+
+ Another party verifies the signature as follows:
+
+ Check that 0 < R < Q and 0 < S < Q/2. If not, it can not be a
+ valid EC sigature.
+
+ hash = SHA-1 ( data )
+
+ Sinv = S^(-1) mod Q.
+
+ U1 = (hash * Sinv) mod Q.
+
+ U2 = (R * Sinv) mod Q.
+
+ (U1 * G + U2 * Y) is computed on the elliptic curve.
+
+ V = (the W-coordinate of this point) interpreted as an integer
+ and reduced (mod Q).
+
+ The signature is valid if V = R.
+
+ The reason for requiring S < Q/2 is that, otherwise, both (R,S) and
+ (R,Q-S) would be valid signatures for the same data. Note that a
+ signature that is valid for hash(data) is also valid for
+ hash(data)+Q or hash(data)-Q, if these happen to fall in the range
+ [0,2^160-1]. It's believed to be computationally infeasible to
+ find data that hashes to an assigned value, so this is only a
+ cosmetic blemish. The blemish can be eliminated by using Q >
+ 2^160, at the cost of having slightly longer signatures, 42 octets
+ instead of 40.
+
+ We must specify how a field-element E ("the W-coordinate") is to be
+ interpreted as an integer. The field-element E is regarded as a
+ radix-P integer, with the digits being the coefficients in the
+ polynomial basis representation of E. The digits are in the ragne
+ [0,P-1]. In the two most common cases, this reduces to "the
+ obvious thing". In the (mod P) case, E is simply a residue mod P,
+ and is taken as an integer in the range [0,P-1]. In the GF[2^D]
+
+
+R. Schroeppel, et al [Page 12]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ case, E is in the D-bit polynomial basis representation, and is
+ simply taken as an integer in the range [0,(2^D)-1]. For other
+ fields GF[P^D], it's necessary to do some radix conversion
+ arithmetic.
+
+
+
+ 6. Performance Considerations
+
+ Elliptic curve signatures use smaller moduli or field sizes than
+ RSA and DSA. Creation of a curve is slow, but not done very often.
+ Key generation is faster than RSA or DSA.
+
+ DNS implementations have been optimized for small transfers,
+ typically less than 512 octets including DNS overhead. Larger
+ transfers will perform correctly and and extensions have been
+ standardized to make larger transfers more efficient [RFC 2671].
+ However, it is still advisable at this time to make reasonable
+ efforts to minimize the size of RR sets stored within the DNS
+ consistent with adequate security.
+
+
+
+ 7. Security Considerations
+
+ Keys retrieved from the DNS should not be trusted unless (1) they
+ have been securely obtained from a secure resolver or independently
+ verified by the user and (2) this secure resolver and secure
+ obtainment or independent verification conform to security policies
+ acceptable to the user. As with all cryptographic algorithms,
+ evaluating the necessary strength of the key is essential and
+ dependent on local policy.
+
+ Some specific key generation considerations are given in the body
+ of this document.
+
+
+
+ 8. IANA Considerations
+
+ The key and signature data structures defined herein correspond to
+ the value 4 in the Algorithm number field of the IANA registry
+
+ Assignment of meaning to the remaining ECC data flag bits or to
+ values of ECC fields outside the ranges for which meaning in
+ defined in this document requires an IETF consensus as defined in
+ [RFC 2434].
+
+
+
+
+
+R. Schroeppel, et al [Page 13]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ Copyright and Disclaimer
+
+ Copyright (C) The Internet Society 2005. This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+ This document and the information contained herein are provided on
+ an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE
+ REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT
+ THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR
+ ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
+ PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+R. Schroeppel, et al [Page 14]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ Informational References
+
+ [RFC 1034] - P. Mockapetris, "Domain names - concepts and
+ facilities", 11/01/1987.
+
+ [RFC 1035] - P. Mockapetris, "Domain names - implementation and
+ specification", 11/01/1987.
+
+ [RFC 2671] - P. Vixie, "Extension Mechanisms for DNS (EDNS0)",
+ August 1999.
+
+ [RFC 4033] - Arends, R., Austein, R., Larson, M., Massey, D., and
+ S. Rose, "DNS Security Introduction and Requirements", RFC 4033,
+ March 2005.
+
+ [RFC 4035] - Arends, R., Austein, R., Larson, M., Massey, D., and
+ S. Rose, "Protocol Modifications for the DNS Security Extensions",
+ RFC 4035, March 2005.
+
+ [RFC 4086] - Eastlake, D., 3rd, Schiller, J., and S. Crocker,
+ "Randomness Requirements for Security", BCP 106, RFC 4086, June
+ 2005.
+
+ [Schneier] - Bruce Schneier, "Applied Cryptography: Protocols,
+ Algorithms, and Source Code in C", 1996, John Wiley and Sons
+
+ [Menezes] - Alfred Menezes, "Elliptic Curve Public Key
+ Cryptosystems", 1993 Kluwer.
+
+ [Silverman] - Joseph Silverman, "The Arithmetic of Elliptic
+ Curves", 1986, Springer Graduate Texts in mathematics #106.
+
+
+
+ Normative Refrences
+
+ [RFC 2119] - S. Bradner, "Key words for use in RFCs to Indicate
+ Requirement Levels", March 1997.
+
+ [RFC 2434] - T. Narten, H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", October 1998.
+
+ [RFC 4034] - Arends, R., Austein, R., Larson, M., Massey, D., and
+ S. Rose, "Resource Records for the DNS Security Extensions", RFC
+ 4034, March 2005.
+
+
+
+
+
+
+
+R. Schroeppel, et al [Page 15]
+
+
+INTERNET-DRAFT ECC Keys in the DNS
+
+
+ Author's Addresses
+
+ Rich Schroeppel
+ 500 S. Maple Drive
+ Woodland Hills, UT 84653 USA
+
+ Telephone: +1-505-844-9079(w)
+ Email: rschroe@sandia.gov
+
+
+ Donald E. Eastlake 3rd
+ Motorola Laboratories
+ 155 Beaver Street
+ Milford, MA 01757 USA
+
+ Telephone: +1 508-786-7554 (w)
+ EMail: Donald.Eastlake@motorola.com
+
+
+
+ Expiration and File Name
+
+ This draft expires in January 2006.
+
+ Its file name is draft-ietf-dnsext-ecc-key-07.txt.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+R. Schroeppel, et al [Page 16]
+
diff --git a/doc/draft/draft-ietf-dnsext-forgery-resilience-02.txt b/doc/draft/draft-ietf-dnsext-forgery-resilience-02.txt
new file mode 100644
index 0000000..87bce00
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-forgery-resilience-02.txt
@@ -0,0 +1,17 @@
+
+This Internet-Draft, draft-ietf-dnsext-forgery-resilience-01.txt, has expired, and has been deleted
+from the Internet-Drafts directory. An Internet-Draft expires 185 days from
+the date that it is posted unless it is replaced by an updated version, or the
+Secretariat has been notified that the document is under official review by the
+IESG or has been passed to the RFC Editor for review and/or publication as an
+RFC. This Internet-Draft was not published as an RFC.
+
+Internet-Drafts are not archival documents, and copies of Internet-Drafts that have
+been deleted from the directory are not available. The Secretariat does not have
+any information regarding the future plans of the author(s) or working group, if
+applicable, with respect to this deleted Internet-Draft. For more information, or
+to request a copy of the document, please contact the author(s) directly.
+
+Draft Author(s):
+Remco van Mook <remco@virtu.nl>,
+Bert Hubert <bert.hubert@netherlabs.nl>
diff --git a/doc/draft/draft-ietf-dnsext-interop3597-02.txt b/doc/draft/draft-ietf-dnsext-interop3597-02.txt
new file mode 100644
index 0000000..160afc3
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-interop3597-02.txt
@@ -0,0 +1,334 @@
+DNS Extensions Working Group J. Schlyter
+Internet-Draft May 19, 2005
+Expires: November 20, 2005
+
+
+ RFC 3597 Interoperability Report
+ draft-ietf-dnsext-interop3597-02.txt
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on November 20, 2005.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This memo documents the result from the RFC 3597 (Handling of Unknown
+ DNS Resource Record Types) interoperability testing.
+
+
+
+
+
+
+
+
+
+
+Schlyter Expires November 20, 2005 [Page 1]
+
+Internet-Draft RFC 3597 Interoperability Report May 2005
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Implementations . . . . . . . . . . . . . . . . . . . . . . . 3
+ 3. Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 3.1 Authoritative Primary Name Server . . . . . . . . . . . . 3
+ 3.2 Authoritative Secondary Name Server . . . . . . . . . . . 3
+ 3.3 Full Recursive Resolver . . . . . . . . . . . . . . . . . 4
+ 3.4 Stub Resolver . . . . . . . . . . . . . . . . . . . . . . 4
+ 3.5 DNSSEC Signer . . . . . . . . . . . . . . . . . . . . . . 4
+ 4. Problems found . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 5. Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 6. Normative References . . . . . . . . . . . . . . . . . . . . . 4
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . 4
+ A. Test zone data . . . . . . . . . . . . . . . . . . . . . . . . 5
+ Intellectual Property and Copyright Statements . . . . . . . . 6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Schlyter Expires November 20, 2005 [Page 2]
+
+Internet-Draft RFC 3597 Interoperability Report May 2005
+
+
+1. Introduction
+
+ This memo documents the result from the RFC 3597 (Handling of Unknown
+ DNS Resource Record Types) interoperability testing. The test was
+ performed during June and July 2004 by request of the IETF DNS
+ Extensions Working Group.
+
+2. Implementations
+
+ The following is a list, in alphabetic order, of implementations
+ tested for compliance with RFC 3597:
+
+ DNSJava 1.6.4
+ ISC BIND 8.4.5
+ ISC BIND 9.3.0
+ NSD 2.1.1
+ Net::DNS 0.47 patchlevel 1
+ Nominum ANS 2.2.1.0.d
+
+ These implementations covers the following functions (number of
+ implementations tested for each function in paranthesis):
+
+ Authoritative Name Servers (4)
+ Full Recursive Resolver (2)
+ Stub Resolver (4)
+ DNSSEC Zone Signers (2)
+
+ All listed implementations are genetically different.
+
+3. Tests
+
+ The following tests was been performed to validate compliance with
+ RFC 3597 section 3 ("Transparency"), 4 ("Domain Name Compression")
+ and 5 ("Text Representation").
+
+3.1 Authoritative Primary Name Server
+
+ The test zone data (Appendix A) was loaded into the name server
+ implementation and the server was queried for the loaded information.
+
+3.2 Authoritative Secondary Name Server
+
+ The test zone data (Appendix A) was transferred using AXFR from
+ another name server implementation and the server was queried for the
+ transferred information.
+
+
+
+
+
+
+Schlyter Expires November 20, 2005 [Page 3]
+
+Internet-Draft RFC 3597 Interoperability Report May 2005
+
+
+3.3 Full Recursive Resolver
+
+ A recursive resolver was queried for resource records from a domain
+ with the test zone data (Appendix A).
+
+3.4 Stub Resolver
+
+ A stub resolver was used to query resource records from a domain with
+ the test zone data (Appendix A).
+
+3.5 DNSSEC Signer
+
+ A DNSSEC signer was used to sign a zone with test zone data
+ (Appendix A).
+
+4. Problems found
+
+ Two implementations had problems with text presentation of zero
+ length RDATA.
+
+ One implementation had problems with text presentation of RR type
+ code and classes >= 4096.
+
+ Bug reports were filed for problems found.
+
+5. Summary
+
+ Unknown type codes works in the tested authoritative servers,
+ recursive resolvers and stub clients.
+
+ No changes are needed to advance RFC 3597 to draft standard.
+
+6. Normative References
+
+ [1] Gustafsson, A., "Handling of Unknown DNS Resource Record (RR)
+ Types", RFC 3597, September 2003.
+
+
+Author's Address
+
+ Jakob Schlyter
+
+ Email: jakob@rfc.se
+
+
+
+
+
+
+
+
+Schlyter Expires November 20, 2005 [Page 4]
+
+Internet-Draft RFC 3597 Interoperability Report May 2005
+
+
+Appendix A. Test zone data
+
+ ; A-record encoded as TYPE1
+ a TYPE1 \# 4 7f000001
+ a TYPE1 192.0.2.1
+ a A \# 4 7f000002
+
+ ; draft-ietf-secsh-dns-05.txt
+ sshfp TYPE44 \# 22 01 01 c691e90714a1629d167de8e5ee0021f12a7eaa1e
+
+ ; bogus test record (from RFC 3597)
+ type731 TYPE731 \# 6 abcd (
+ ef 01 23 45 )
+
+ ; zero length RDATA (from RFC 3597)
+ type62347 TYPE62347 \# 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Schlyter Expires November 20, 2005 [Page 5]
+
+Internet-Draft RFC 3597 Interoperability Report May 2005
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2005). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Schlyter Expires November 20, 2005 [Page 6]
+
+
diff --git a/doc/draft/draft-ietf-dnsext-keyrr-key-signing-flag-12.txt b/doc/draft/draft-ietf-dnsext-keyrr-key-signing-flag-12.txt
new file mode 100644
index 0000000..6bffb70
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-keyrr-key-signing-flag-12.txt
@@ -0,0 +1,560 @@
+
+DNS Extensions O. Kolkman
+Internet-Draft RIPE NCC
+Expires: June 17, 2004 J. Schlyter
+
+ E. Lewis
+ ARIN
+ December 18, 2003
+
+
+ DNSKEY RR Secure Entry Point Flag
+ draft-ietf-dnsext-keyrr-key-signing-flag-12
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that other
+ groups may also distribute working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at http://
+ www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on June 17, 2004.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ With the Delegation Signer (DS) resource record the concept of a
+ public key acting as a secure entry point has been introduced. During
+ exchanges of public keys with the parent there is a need to
+ differentiate secure entry point keys from other public keys in the
+ DNSKEY resource record (RR) set. A flag bit in the DNSKEY RR is
+ defined to indicate that DNSKEY is to be used as a secure entry
+ point. The flag bit is intended to assist in operational procedures
+ to correctly generate DS resource records, or to indicate what
+ DNSKEYs are intended for static configuration. The flag bit is not to
+
+
+
+Kolkman, et al. Expires June 17, 2004 [Page 1]
+
+Internet-Draft DNSKEY RR Secure Entry Point Flag December 2003
+
+
+ be used in the DNS verification protocol. This document updates RFC
+ 2535 and RFC 3445.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. The Secure Entry Point (SEP) Flag . . . . . . . . . . . . . . . 4
+ 3. DNSSEC Protocol Changes . . . . . . . . . . . . . . . . . . . . 5
+ 4. Operational Guidelines . . . . . . . . . . . . . . . . . . . . . 5
+ 5. Security Considerations . . . . . . . . . . . . . . . . . . . . 6
+ 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 6
+ 7. Internationalization Considerations . . . . . . . . . . . . . . 6
+ 8. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . 6
+ Normative References . . . . . . . . . . . . . . . . . . . . . . 7
+ Informative References . . . . . . . . . . . . . . . . . . . . . 7
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 7
+ Intellectual Property and Copyright Statements . . . . . . . . . 9
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kolkman, et al. Expires June 17, 2004 [Page 2]
+
+Internet-Draft DNSKEY RR Secure Entry Point Flag December 2003
+
+
+1. Introduction
+
+ "All keys are equal but some keys are more equal than others" [6]
+
+ With the definition of the Delegation Signer Resource Record (DS RR)
+ [5] it has become important to differentiate between the keys in the
+ DNSKEY RR set that are (to be) pointed to by parental DS RRs and the
+ other keys in the DNSKEY RR set. We refer to these public keys as
+ Secure Entry Point (SEP) keys. A SEP key either used to generate a
+ DS RR or is distributed to resolvers that use the key as the root of
+ a trusted subtree[3].
+
+ In early deployment tests, the use of two (kinds of) key pairs for
+ each zone has been prevalent. For one kind of key pair the private
+ key is used to sign just the zone's DNSKEY resource record (RR) set.
+ Its public key is intended to be referenced by a DS RR at the parent
+ or configured statically in a resolver. The private key of the other
+ kind of key pair is used to sign the rest of the zone's data sets.
+ The former key pair is called a key-signing key (KSK) and the latter
+ is called a zone-signing key (ZSK). In practice there have been
+ usually one of each kind of key pair, but there will be multiples of
+ each at times.
+
+ It should be noted that division of keys pairs into KSK's and ZSK's
+ is not mandatory in any definition of DNSSEC, not even with the
+ introduction of the DS RR. But, in testing, this distinction has
+ been helpful when designing key roll over (key super-cession)
+ schemes. Given that the distinction has proven helpful, the labels
+ KSK and ZSK have begun to stick.
+
+ There is a need to differentiate the public keys for the key pairs
+ that are used for key signing from keys that are not used key signing
+ (KSKs vs ZSKs). This need is driven by knowing which DNSKEYs are to
+ be sent for generating DS RRs, which DNSKEYs are to be distributed to
+ resolvers, and which keys are fed to the signer application at the
+ appropriate time.
+
+ In other words, the SEP bit provides an in-band method to communicate
+ a DNSKEY RR's intended use to third parties. As an example we present
+ 3 use cases in which the bit is useful:
+
+ The parent is a registry, the parent and the child use secured DNS
+ queries and responses, with a preexisting trust-relation, or plain
+ DNS over a secured channel to exchange the child's DNSKEY RR
+ sets. Since a DNSKEY RR set will contain a complete DNSKEY RRset
+ the SEP bit can be used to isolate the DNSKEYs for which a DS RR
+ needs to be created.
+
+
+
+
+Kolkman, et al. Expires June 17, 2004 [Page 3]
+
+Internet-Draft DNSKEY RR Secure Entry Point Flag December 2003
+
+
+ An administrator has configured a DNSKEY as root for a trusted
+ subtree into security aware resolver. Using a special purpose tool
+ that queries for the KEY RRs from that domain's apex, the
+ administrator will be able to notice the roll over of the trusted
+ anchor by a change of the subset of KEY RRs with the DS flag set.
+
+ A signer might use the SEP bit on the public key to determine
+ which private key to use to exclusively sign the DNSKEY RRset and
+ which private key to use to sign the other RRsets in the zone.
+
+ As demonstrated in the above examples it is important to be able to
+ differentiate the SEP keys from the other keys in a DNSKEY RR set in
+ the flow between signer and (parental) key-collector and in the flow
+ between the signer and the resolver configuration. The SEP flag is to
+ be of no interest to the flow between the verifier and the
+ authoritative data store.
+
+ The reason for the term "SEP" is a result of the observation that the
+ distinction between KSK and ZSK key pairs is made by the signer, a
+ key pair could be used as both a KSK and a ZSK at the same time. To
+ be clear, the term SEP was coined to lessen the confusion caused by
+ the overlap. ( Once this label was applied, it had the side effect of
+ removing the temptation to have both a KSK flag bit and a ZSK flag
+ bit.)
+
+ The key words "MAY","MAY NOT", "MUST", "MUST NOT", "REQUIRED",
+ "RECOMMENDED", "SHOULD", and "SHOULD NOT" in this document are to be
+ interpreted as described in RFC2119 [1].
+
+2. The Secure Entry Point (SEP) Flag
+
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | flags |S| protocol | algorithm |
+ | |E| | |
+ | |P| | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | /
+ / public key /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ DNSKEY RR Format
+
+
+
+
+
+
+Kolkman, et al. Expires June 17, 2004 [Page 4]
+
+Internet-Draft DNSKEY RR Secure Entry Point Flag December 2003
+
+
+ This document assigns the 15'th bit in the flags field as the secure
+ entry point (SEP) bit. If the the bit is set to 1 the key is
+ intended to be used as secure entry point key. One SHOULD NOT assign
+ special meaning to the key if the bit is set to 0. Operators can
+ recognize the secure entry point key by the even or odd-ness of the
+ decimal representation of the flag field.
+
+3. DNSSEC Protocol Changes
+
+ The bit MUST NOT be used during the resolving and verification
+ process. The SEP flag is only used to provide a hint about the
+ different administrative properties of the key and therefore the use
+ of the SEP flag does not change the DNS resolution protocol or the
+ resolution process.
+
+4. Operational Guidelines
+
+ The SEP bit is set by the key-pair-generator and MAY be used by the
+ zone signer to decide whether the public part of the key pair is to
+ be prepared for input to a DS RR generation function. The SEP bit is
+ recommended to be set (to 1) whenever the public key of the key pair
+ will be distributed to the parent zone to build the authentication
+ chain or if the public key is to be distributed for static
+ configuration in verifiers.
+
+ When a key pair is created, the operator needs to indicate whether
+ the SEP bit is to be set in the DNSKEY RR. As the SEP bit is within
+ the data that is used to compute the 'key tag field' in the SIG RR,
+ changing the SEP bit will change the identity of the key within DNS.
+ In other words, once a key is used to generate signatures, the
+ setting of the SEP bit is to remain constant. If not, a verifier will
+ not be able to find the relevant KEY RR.
+
+ When signing a zone, it is intended that the key(s) with the SEP bit
+ set (if such keys exist) are used to sign the KEY RR set of the zone.
+ The same key can be used to sign the rest of the zone data too. It
+ is conceivable that not all keys with a SEP bit set will sign the
+ DNSKEY RR set, such keys might be pending retirement or not yet in
+ use.
+
+ When verifying a RR set, the SEP bit is not intended to play a role.
+ How the key is used by the verifier is not intended to be a
+ consideration at key creation time.
+
+ Although the SEP flag provides a hint on which public key is to be
+ used as trusted root, administrators can choose to ignore the fact
+ that a DNSKEY has its SEP bit set or not when configuring a trusted
+ root for their resolvers.
+
+
+
+Kolkman, et al. Expires June 17, 2004 [Page 5]
+
+Internet-Draft DNSKEY RR Secure Entry Point Flag December 2003
+
+
+ Using the SEP flag a key roll over can be automated. The parent can
+ use an existing trust relation to verify DNSKEY RR sets in which a
+ new DNSKEY RR with the SEP flag appears.
+
+5. Security Considerations
+
+ As stated in Section 3 the flag is not to be used in the resolution
+ protocol or to determine the security status of a key. The flag is to
+ be used for administrative purposes only.
+
+ No trust in a key should be inferred from this flag - trust MUST be
+ inferred from an existing chain of trust or an out-of-band exchange.
+
+ Since this flag might be used for automating public key exchanges, we
+ think the following consideration is in place.
+
+ Automated mechanisms for roll over of the DS RR might be vulnerable
+ to a class of replay attacks. This might happen after a public key
+ exchange where a DNSKEY RR set, containing two DNSKEY RRs with the
+ SEP flag set, is sent to the parent. The parent verifies the DNSKEY
+ RR set with the existing trust relation and creates the new DS RR
+ from the DNSKEY RR that the current DS RR is not pointing to. This
+ key exchange might be replayed. Parents are encouraged to implement a
+ replay defense. A simple defense can be based on a registry of keys
+ that have been used to generate DS RRs during the most recent roll
+ over. These same considerations apply to entities that configure keys
+ in resolvers.
+
+6. IANA Considerations
+
+ The flag bits in the DNSKEY RR are assigned by IETF consensus and
+ registered in the DNSKEY Flags registry (created by [4]). This
+ document assigns the 15th bit in the DNSKEY RR as the Secure Entry
+ Point (SEP) bit.
+
+7. Internationalization Considerations
+
+ Although SEP is a popular acronym in many different languages, there
+ are no internationalization considerations.
+
+8. Acknowledgments
+
+ The ideas documented in this document are inspired by communications
+ we had with numerous people and ideas published by other folk. Among
+ others Mark Andrews, Rob Austein, Miek Gieben, Olafur Gudmundsson,
+ Daniel Karrenberg, Dan Massey, Scott Rose, Marcos Sanz and Sam Weiler
+ have contributed ideas and provided feedback.
+
+
+
+
+Kolkman, et al. Expires June 17, 2004 [Page 6]
+
+Internet-Draft DNSKEY RR Secure Entry Point Flag December 2003
+
+
+ This document saw the light during a workshop on DNSSEC operations
+ hosted by USC/ISI in August 2002.
+
+Normative References
+
+ [1] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [2] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [3] Lewis, E., "DNS Security Extension Clarification on Zone
+ Status", RFC 3090, March 2001.
+
+ [4] Weiler, S., "Legacy Resolver Compatibility for Delegation
+ Signer", draft-ietf-dnsext-dnssec-2535typecode-change-05 (work
+ in progress), October 2003.
+
+Informative References
+
+ [5] Gudmundsson, O., "Delegation Signer Resource Record",
+ draft-ietf-dnsext-delegation-signer-15 (work in progress), June
+ 2003.
+
+ [6] Orwell, G. and R. Steadman (illustrator), "Animal Farm; a Fairy
+ Story", ISBN 0151002177 (50th anniversary edition), April 1996.
+
+
+Authors' Addresses
+
+ Olaf M. Kolkman
+ RIPE NCC
+ Singel 256
+ Amsterdam 1016 AB
+ NL
+
+ Phone: +31 20 535 4444
+ EMail: olaf@ripe.net
+ URI: http://www.ripe.net/
+
+
+ Jakob Schlyter
+ Karl Gustavsgatan 15
+ Goteborg SE-411 25
+ Sweden
+
+ EMail: jakob@schlyter.se
+
+
+
+
+Kolkman, et al. Expires June 17, 2004 [Page 7]
+
+Internet-Draft DNSKEY RR Secure Entry Point Flag December 2003
+
+
+ Edward P. Lewis
+ ARIN
+ 3635 Concorde Parkway Suite 200
+ Chantilly, VA 20151
+ US
+
+ Phone: +1 703 227 9854
+ EMail: edlewis@arin.net
+ URI: http://www.arin.net/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kolkman, et al. Expires June 17, 2004 [Page 8]
+
+Internet-Draft DNSKEY RR Secure Entry Point Flag December 2003
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+
+
+
+Kolkman, et al. Expires June 17, 2004 [Page 9]
+
+Internet-Draft DNSKEY RR Secure Entry Point Flag December 2003
+
+
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kolkman, et al. Expires June 17, 2004 [Page 10]
+
+
diff --git a/doc/draft/draft-ietf-dnsext-mdns-46.txt b/doc/draft/draft-ietf-dnsext-mdns-46.txt
new file mode 100644
index 0000000..63d0b23
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-mdns-46.txt
@@ -0,0 +1,1801 @@
+
+
+
+
+
+
+DNSEXT Working Group Bernard Aboba
+INTERNET-DRAFT Dave Thaler
+Category: Standards Track Levon Esibov
+<draft-ietf-dnsext-mdns-46.txt> Microsoft Corporation
+16 April 2006
+
+ Linklocal Multicast Name Resolution (LLMNR)
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on October 15, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society 2006.
+
+Abstract
+
+ The goal of Link-Local Multicast Name Resolution (LLMNR) is to enable
+ name resolution in scenarios in which conventional DNS name
+ resolution is not possible. LLMNR supports all current and future
+ DNS formats, types and classes, while operating on a separate port
+ from DNS, and with a distinct resolver cache. Since LLMNR only
+ operates on the local link, it cannot be considered a substitute for
+ DNS.
+
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 1]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+Table of Contents
+
+1. Introduction .......................................... 3
+ 1.1 Requirements .................................... 4
+ 1.2 Terminology ..................................... 4
+2. Name Resolution Using LLMNR ........................... 4
+ 2.1 LLMNR Packet Format ............................. 5
+ 2.2 Sender Behavior ................................. 8
+ 2.3 Responder Behavior .............................. 8
+ 2.4 Unicast Queries and Responses ................... 11
+ 2.5 Off-link Detection .............................. 11
+ 2.6 Responder Responsibilities ...................... 12
+ 2.7 Retransmission and Jitter ....................... 13
+ 2.8 DNS TTL ......................................... 14
+ 2.9 Use of the Authority and Additional Sections .... 14
+3. Usage model ........................................... 15
+ 3.1 LLMNR Configuration ............................. 16
+4. Conflict Resolution ................................... 18
+ 4.1 Uniqueness Verification ......................... 18
+ 4.2 Conflict Detection and Defense .................. 19
+ 4.3 Considerations for Multiple Interfaces .......... 20
+ 4.4 API issues ...................................... 22
+5. Security Considerations ............................... 22
+ 5.1 Denial of Service ............................... 22
+ 5.2 Spoofing ...............,........................ 23
+ 5.3 Authentication .................................. 24
+ 5.4 Cache and Port Separation ....................... 24
+6. IANA considerations ................................... 25
+7. Constants ............................................. 25
+8. References ............................................ 26
+ 8.1 Normative References ............................ 26
+ 8.2 Informative References .......................... 26
+Acknowledgments .............................................. 28
+Authors' Addresses ........................................... 28
+Intellectual Property Statement .............................. 29
+Disclaimer of Validity ....................................... 29
+Copyright Statement .......................................... 29
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 2]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+1. Introduction
+
+ This document discusses Link Local Multicast Name Resolution (LLMNR),
+ which is based on the DNS packet format and supports all current and
+ future DNS formats, types and classes. LLMNR operates on a separate
+ port from the Domain Name System (DNS), with a distinct resolver
+ cache.
+
+ Since LLMNR only operates on the local link, it cannot be considered
+ a substitute for DNS. Link-scope multicast addresses are used to
+ prevent propagation of LLMNR traffic across routers, potentially
+ flooding the network. LLMNR queries can also be sent to a unicast
+ address, as described in Section 2.4.
+
+ Propagation of LLMNR packets on the local link is considered
+ sufficient to enable name resolution in small networks. In such
+ networks, if a network has a gateway, then typically the network is
+ able to provide DNS server configuration. Configuration issues are
+ discussed in Section 3.1.
+
+ In the future, it may be desirable to consider use of multicast name
+ resolution with multicast scopes beyond the link-scope. This could
+ occur if LLMNR deployment is successful, the need arises for
+ multicast name resolution beyond the link-scope, or multicast routing
+ becomes ubiquitous. For example, expanded support for multicast name
+ resolution might be required for mobile ad-hoc networks.
+
+ Once we have experience in LLMNR deployment in terms of
+ administrative issues, usability and impact on the network, it will
+ be possible to reevaluate which multicast scopes are appropriate for
+ use with multicast name resolution. IPv4 administratively scoped
+ multicast usage is specified in "Administratively Scoped IP
+ Multicast" [RFC2365].
+
+ Service discovery in general, as well as discovery of DNS servers
+ using LLMNR in particular, is outside of the scope of this document,
+ as is name resolution over non-multicast capable media.
+
+1.1. Requirements
+
+ In this document, several words are used to signify the requirements
+ of the specification. The key words "MUST", "MUST NOT", "REQUIRED",
+ "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
+ and "OPTIONAL" in this document are to be interpreted as described in
+ [RFC2119].
+
+
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 3]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+1.2. Terminology
+
+ This document assumes familiarity with DNS terminology defined in
+ [RFC1035]. Other terminology used in this document includes:
+
+Routable Address
+ An address other than a Link-Local address. This includes globally
+ routable addresses, as well as private addresses.
+
+Reachable
+ An LLMNR responder considers one of its addresses reachable over a
+ link if it will respond to an ARP or Neighbor Discovery query for
+ that address received on that link.
+
+Responder
+ A host that listens to LLMNR queries, and responds to those for
+ which it is authoritative.
+
+Sender
+ A host that sends an LLMNR query.
+
+UNIQUE
+ There are some scenarios when multiple responders may respond to
+ the same query. There are other scenarios when only one responder
+ may respond to a query. Names for which only a single responder is
+ anticipated are referred to as UNIQUE. Name uniqueness is
+ configured on the responder, and therefore uniqueness verification
+ is the responder's responsibility.
+
+2. Name Resolution Using LLMNR
+
+ LLMNR queries are sent to and received on port 5355. The IPv4 link-
+ scope multicast address a given responder listens to, and to which a
+ sender sends queries, is 224.0.0.252. The IPv6 link-scope multicast
+ address a given responder listens to, and to which a sender sends all
+ queries, is FF02:0:0:0:0:0:1:3.
+
+ Typically a host is configured as both an LLMNR sender and a
+ responder. A host MAY be configured as a sender, but not a
+ responder. However, a host configured as a responder MUST act as a
+ sender, if only to verify the uniqueness of names as described in
+ Section 4. This document does not specify how names are chosen or
+ configured. This may occur via any mechanism, including DHCPv4
+ [RFC2131] or DHCPv6 [RFC3315].
+
+ A typical sequence of events for LLMNR usage is as follows:
+
+ [a] An LLMNR sender sends an LLMNR query to the link-scope
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 4]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ multicast address(es), unless a unicast query is indicated,
+ as specified in Section 2.4.
+
+ [b] A responder responds to this query only if it is authoritative
+ for the name in the query. A responder responds to a
+ multicast query by sending a unicast UDP response to the sender.
+ Unicast queries are responded to as indicated in Section 2.4.
+
+ [c] Upon reception of the response, the sender processes it.
+
+ The sections that follow provide further details on sender and
+ responder behavior.
+
+2.1. LLMNR Packet Format
+
+ LLMNR is based on the DNS packet format defined in [RFC1035] Section
+ 4 for both queries and responses. LLMNR implementations SHOULD send
+ UDP queries and responses only as large as are known to be
+ permissible without causing fragmentation. When in doubt a maximum
+ packet size of 512 octets SHOULD be used. LLMNR implementations MUST
+ accept UDP queries and responses as large as the smaller of the link
+ MTU or 9194 octets (Ethernet jumbo frame size of 9KB (9216) minus 22
+ octets for the header, VLAN tag and CRC).
+
+2.1.1. LLMNR Header Format
+
+ LLMNR queries and responses utilize the DNS header format defined in
+ [RFC1035] with exceptions noted below:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ID |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ |QR| Opcode | C|TC| T| Z| Z| Z| Z| RCODE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QDCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ANCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | NSCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ARCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ where:
+
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 5]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ID A 16 bit identifier assigned by the program that generates any kind
+ of query. This identifier is copied from the query to the response
+ and can be used by the sender to match responses to outstanding
+ queries. The ID field in a query SHOULD be set to a pseudo-random
+ value. For advice on generation of pseudo-random values, please
+ consult [RFC1750].
+
+QR Query/Response. A one bit field, which if set indicates that the
+ message is an LLMNR response; if clear then the message is an LLMNR
+ query.
+
+OPCODE
+ A four bit field that specifies the kind of query in this message.
+ This value is set by the originator of a query and copied into the
+ response. This specification defines the behavior of standard
+ queries and responses (opcode value of zero). Future
+ specifications may define the use of other opcodes with LLMNR.
+ LLMNR senders and responders MUST support standard queries (opcode
+ value of zero). LLMNR queries with unsupported OPCODE values MUST
+ be silently discarded by responders.
+
+C Conflict. When set within a request, the 'C'onflict bit indicates
+ that a sender has received multiple LLMNR responses to this query.
+ In an LLMNR response, if the name is considered UNIQUE, then the
+ 'C' bit is clear, otherwise it is set. LLMNR senders do not
+ retransmit queries with the 'C' bit set. Responders MUST NOT
+ respond to LLMNR queries with the 'C' bit set, but may start the
+ uniqueness verification process, as described in Section 4.2.
+
+TC TrunCation - specifies that this message was truncated due to
+ length greater than that permitted on the transmission channel.
+ The TC bit MUST NOT be set in an LLMNR query and if set is ignored
+ by an LLMNR responder. If the TC bit is set in an LLMNR response,
+ then the sender SHOULD resend the LLMNR query over TCP using the
+ unicast address of the responder as the destination address. If
+ the sender receives a response to the TCP query, then it SHOULD
+ discard the UDP response with the TC bit set. See [RFC2181] and
+ Section 2.4 of this specification for further discussion of the TC
+ bit.
+
+T Tentative. The 'T'entative bit is set in a response if the
+ responder is authoritative for the name, but has not yet verified
+ the uniqueness of the name. A responder MUST ignore the 'T' bit in
+ a query, if set. A response with the 'T' bit set is silently
+ discarded by the sender, except if it is a uniqueness query, in
+ which case a conflict has been detected and a responder MUST
+ resolve the conflict as described in Section 4.1.
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 6]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+Z Reserved for future use. Implementations of this specification
+ MUST set these bits to zero in both queries and responses. If
+ these bits are set in a LLMNR query or response, implementations of
+ this specification MUST ignore them. Since reserved bits could
+ conceivably be used for different purposes than in DNS,
+ implementors are advised not to enable processing of these bits in
+ an LLMNR implementation starting from a DNS code base.
+
+RCODE
+ Response code -- this 4 bit field is set as part of LLMNR
+ responses. In an LLMNR query, the sender MUST set RCODE to zero;
+ the responder ignores the RCODE and assumes it to be zero. The
+ response to a multicast LLMNR query MUST have RCODE set to zero. A
+ sender MUST silently discard an LLMNR response with a non-zero
+ RCODE sent in response to a multicast query.
+
+ If an LLMNR responder is authoritative for the name in a multicast
+ query, but an error is encountered, the responder SHOULD send an
+ LLMNR response with an RCODE of zero, no RRs in the answer section,
+ and the TC bit set. This will cause the query to be resent using
+ TCP, and allow the inclusion of a non-zero RCODE in the response to
+ the TCP query. Responding with the TC bit set is preferable to not
+ sending a response, since it enables errors to be diagnosed. This
+ may be required, for example, when an LLMNR query includes a TSIG
+ RR in the additional section, and the responder encounters a
+ problem that requires returning a non-zero RCODE. TSIG error
+ conditions defined in [RFC2845] include a TSIG RR in an
+ unacceptable position (RCODE=1) or a TSIG RR which does not
+ validate (RCODE=9 with TSIG ERROR 17 (BADKEY) or 16 (BADSIG)).
+
+ Since LLMNR responders only respond to LLMNR queries for names for
+ which they are authoritative, LLMNR responders MUST NOT respond
+ with an RCODE of 3; instead, they should not respond at all.
+
+ LLMNR implementations MUST support EDNS0 [RFC2671] and extended
+ RCODE values.
+
+QDCOUNT
+ An unsigned 16 bit integer specifying the number of entries in the
+ question section. A sender MUST place only one question into the
+ question section of an LLMNR query. LLMNR responders MUST silently
+ discard LLMNR queries with QDCOUNT not equal to one. LLMNR senders
+ MUST silently discard LLMNR responses with QDCOUNT not equal to
+ one.
+
+ANCOUNT
+ An unsigned 16 bit integer specifying the number of resource
+ records in the answer section. LLMNR responders MUST silently
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 7]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ discard LLMNR queries with ANCOUNT not equal to zero.
+
+NSCOUNT
+ An unsigned 16 bit integer specifying the number of name server
+ resource records in the authority records section. Authority
+ record section processing is described in Section 2.9. LLMNR
+ responders MUST silently discard LLMNR queries with NSCOUNT not
+ equal to zero.
+
+ARCOUNT
+ An unsigned 16 bit integer specifying the number of resource
+ records in the additional records section. Additional record
+ section processing is described in Section 2.9.
+
+2.2. Sender Behavior
+
+ A sender MAY send an LLMNR query for any legal resource record type
+ (e.g., A, AAAA, PTR, SRV, etc.) to the link-scope multicast address.
+ As described in Section 2.4, a sender MAY also send a unicast query.
+
+ The sender MUST anticipate receiving no replies to some LLMNR
+ queries, in the event that no responders are available within the
+ link-scope. If no response is received, a resolver treats it as a
+ response that the name does not exist (RCODE=3 is returned). A
+ sender can handle duplicate responses by discarding responses with a
+ source IP address and ID field that duplicate a response already
+ received.
+
+ When multiple valid LLMNR responses are received with the 'C' bit
+ set, they SHOULD be concatenated and treated in the same manner that
+ multiple RRs received from the same DNS server would be. However,
+ responses with the 'C' bit set SHOULD NOT be concatenated with
+ responses with the 'C' bit clear; instead, only the responses with
+ the 'C' bit set SHOULD be returned. If valid LLMNR response(s) are
+ received along with error response(s), then the error responses are
+ silently discarded.
+
+ Since the responder may order the RRs in the response so as to
+ indicate preference, the sender SHOULD preserve ordering in the
+ response to the querying application.
+
+2.3. Responder Behavior
+
+ An LLMNR response MUST be sent to the sender via unicast.
+
+ Upon configuring an IP address, responders typically will synthesize
+ corresponding A, AAAA and PTR RRs so as to be able to respond to
+ LLMNR queries for these RRs. An SOA RR is synthesized only when a
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 8]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ responder has another RR in addition to the SOA RR; the SOA RR MUST
+ NOT be the only RR that a responder has. However, in general whether
+ RRs are manually or automatically created is an implementation
+ decision.
+
+ For example, a host configured to have computer name "host1" and to
+ be a member of the "example.com" domain, and with IPv4 address
+ 192.0.2.1 and IPv6 address 2001:0DB8::1:2:3:FF:FE:4:5:6 might be
+ authoritative for the following records:
+
+ host1. IN A 192.0.2.1
+ IN AAAA 2001:0DB8::1:2:3:FF:FE:4:5:6
+
+ host1.example.com. IN A 192.0.2.1
+ IN AAAA 2001:0DB8::1:2:3:FF:FE:4:5:6
+
+ 1.2.0.192.in-addr.arpa. IN PTR host1.
+ IN PTR host1.example.com.
+
+ 6.0.5.0.4.0.E.F.F.F.3.0.2.0.1.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.
+ ip6.arpa IN PTR host1. (line split for formatting reasons)
+ IN PTR host1.example.com.
+
+ An LLMNR responder might be further manually configured with the name
+ of a local mail server with an MX RR included in the "host1." and
+ "host1.example.com." records.
+
+ In responding to queries:
+
+[a] Responders MUST listen on UDP port 5355 on the link-scope multicast
+ address(es) defined in Section 2, and on TCP port 5355 on the
+ unicast address(es) that could be set as the source address(es)
+ when the responder responds to the LLMNR query.
+
+[b] Responders MUST direct responses to the port from which the query
+ was sent. When queries are received via TCP this is an inherent
+ part of the transport protocol. For queries received by UDP the
+ responder MUST take note of the source port and use that as the
+ destination port in the response. Responses MUST always be sent
+ from the port to which they were directed.
+
+[c] Responders MUST respond to LLMNR queries for names and addresses
+ they are authoritative for. This applies to both forward and
+ reverse lookups, with the exception of queries with the 'C' bit
+ set, which do not elicit a response.
+
+[d] Responders MUST NOT respond to LLMNR queries for names they are not
+ authoritative for.
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 9]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+[e] Responders MUST NOT respond using data from the LLMNR or DNS
+ resolver cache.
+
+[f] If a DNS server is running on a host that supports LLMNR, the DNS
+ server MUST respond to LLMNR queries only for the RRSets relating
+ to the host on which the server is running, but MUST NOT respond
+ for other records for which the server is authoritative. DNS
+ servers also MUST NOT send LLMNR queries in order to resolve DNS
+ queries.
+
+[g] If a responder is authoritative for a name, it MUST respond with
+ RCODE=0 and an empty answer section, if the type of query does not
+ match a RR that the responder has.
+
+ As an example, a host configured to respond to LLMNR queries for the
+ name "foo.example.com." is authoritative for the name
+ "foo.example.com.". On receiving an LLMNR query for an A RR with the
+ name "foo.example.com." the host authoritatively responds with A
+ RR(s) that contain IP address(es) in the RDATA of the resource
+ record. If the responder has a AAAA RR, but no A RR, and an A RR
+ query is received, the responder would respond with RCODE=0 and an
+ empty answer section.
+
+ In conventional DNS terminology a DNS server authoritative for a zone
+ is authoritative for all the domain names under the zone apex except
+ for the branches delegated into separate zones. Contrary to
+ conventional DNS terminology, an LLMNR responder is authoritative
+ only for the zone apex.
+
+ For example the host "foo.example.com." is not authoritative for the
+ name "child.foo.example.com." unless the host is configured with
+ multiple names, including "foo.example.com." and
+ "child.foo.example.com.". As a result, "foo.example.com." cannot
+ reply to an LLMNR query for "child.foo.example.com." with RCODE=3
+ (authoritative name error). The purpose of limiting the name
+ authority scope of a responder is to prevent complications that could
+ be caused by coexistence of two or more hosts with the names
+ representing child and parent (or grandparent) nodes in the DNS tree,
+ for example, "foo.example.com." and "child.foo.example.com.".
+
+ Without the restriction on authority an LLMNR query for an A resource
+ record for the name "child.foo.example.com." would result in two
+ authoritative responses: RCODE=3 (authoritative name error) received
+ from "foo.example.com.", and a requested A record - from
+ "child.foo.example.com.". To prevent this ambiguity, LLMNR enabled
+ hosts could perform a dynamic update of the parent (or grandparent)
+ zone with a delegation to a child zone; for example a host
+ "child.foo.example.com." could send a dynamic update for the NS and
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 10]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ glue A record to "foo.example.com.". However, this approach
+ significantly complicates implementation of LLMNR and would not be
+ acceptable for lightweight hosts.
+
+2.4. Unicast Queries and Responses
+
+ Unicast queries SHOULD be sent when:
+
+ [a] A sender repeats a query after it received a response
+ with the TC bit set to the previous LLMNR multicast query, or
+
+ [b] The sender queries for a PTR RR of a fully formed IP address
+ within the "in-addr.arpa" or "ip6.arpa" zones.
+
+ Unicast LLMNR queries MUST be done using TCP and the responses MUST
+ be sent using the same TCP connection as the query. Senders MUST
+ support sending TCP queries, and responders MUST support listening
+ for TCP queries. If the sender of a TCP query receives a response to
+ that query not using TCP, the response MUST be silently discarded.
+
+ Unicast UDP queries MUST be silently discarded.
+
+ A unicast PTR RR query for an off-link address will not elicit a
+ response, but instead an ICMP TTL or Hop Limit exceeded message will
+ be received. An implementation receiving an ICMP message in response
+ to a TCP connection setup attempt can return immediately, treating
+ this as a response that no such name exists (RCODE=3 is returned).
+ An implementation that cannot process ICMP messages MAY send
+ multicast UDP queries for PTR RRs. Since TCP implementations will
+ not retransmit prior to RTOmin, a considerable period will elapse
+ before TCP retransmits multiple times, resulting in a long timeout
+ for TCP PTR RR queries sent to an off-link destination.
+
+2.5. "Off link" Detection
+
+ A sender MUST select a source address for LLMNR queries that is
+ assigned on the interface on which the query is sent. The
+ destination address of an LLMNR query MUST be a link-scope multicast
+ address or a unicast address.
+
+ A responder MUST select a source address for responses that is
+ assigned on the interface on which the query was received. The
+ destination address of an LLMNR response MUST be a unicast address.
+
+ On receiving an LLMNR query, the responder MUST check whether it was
+ sent to a LLMNR multicast addresses defined in Section 2. If it was
+ sent to another multicast address, then the query MUST be silently
+ discarded.
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 11]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ Section 2.4 discusses use of TCP for LLMNR queries and responses. In
+ composing an LLMNR query using TCP, the sender MUST set the Hop Limit
+ field in the IPv6 header and the TTL field in the IPv4 header of the
+ response to one (1). The responder SHOULD set the TTL or Hop Limit
+ settings on the TCP listen socket to one (1) so that SYN-ACK packets
+ will have TTL (IPv4) or Hop Limit (IPv6) set to one (1). This
+ prevents an incoming connection from off-link since the sender will
+ not receive a SYN-ACK from the responder.
+
+ For UDP queries and responses, the Hop Limit field in the IPv6 header
+ and the TTL field in the IPV4 header MAY be set to any value.
+ However, it is RECOMMENDED that the value 255 be used for
+ compatibility with early implementations of [RFC3927].
+
+ Implementation note:
+
+ In the sockets API for IPv4 [POSIX], the IP_TTL and
+ IP_MULTICAST_TTL socket options are used to set the TTL of
+ outgoing unicast and multicast packets. The IP_RECVTTL socket
+ option is available on some platforms to retrieve the IPv4 TTL of
+ received packets with recvmsg(). [RFC2292] specifies similar
+ options for setting and retrieving the IPv6 Hop Limit.
+
+2.6. Responder Responsibilities
+
+ It is the responsibility of the responder to ensure that RRs returned
+ in LLMNR responses MUST only include values that are valid on the
+ local interface, such as IPv4 or IPv6 addresses valid on the local
+ link or names defended using the mechanism described in Section 4.
+ IPv4 Link-Local addresses are defined in [RFC3927]. IPv6 Link-Local
+ addresses are defined in [RFC2373]. In particular:
+
+ [a] If a link-scope IPv6 address is returned in a AAAA RR,
+ that address MUST be valid on the local link over which
+ LLMNR is used.
+
+ [b] If an IPv4 address is returned, it MUST be reachable
+ through the link over which LLMNR is used.
+
+ [c] If a name is returned (for example in a CNAME, MX
+ or SRV RR), the name MUST be resolvable on the local
+ link over which LLMNR is used.
+
+ Where multiple addresses represent valid responses to a query, the
+ order in which the addresses are returned is as follows:
+
+ [d] If the source address of the query is a link-scope address,
+ then the responder SHOULD include a link-scope address first
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 12]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ in the response, if available.
+
+ [e] If the source address of the query is a routable address,
+ then the responder MUST include a routable address first
+ in the response, if available.
+
+2.7. Retransmission and Jitter
+
+ An LLMNR sender uses the timeout interval LLMNR_TIMEOUT to determine
+ when to retransmit an LLMNR query. An LLMNR sender SHOULD either
+ estimate the LLMNR_TIMEOUT for each interface, or set a reasonably
+ high initial timeout. Suggested constants are described in Section
+ 7.
+
+ If an LLMNR query sent over UDP is not resolved within LLMNR_TIMEOUT,
+ then a sender SHOULD repeat the transmission of the query in order to
+ assure that it was received by a host capable of responding to it.
+ An LLMNR query SHOULD NOT be sent more than three times.
+
+ Where LLMNR queries are sent using TCP, retransmission is handled by
+ the transport layer. Queries with the 'C' bit set MUST be sent using
+ multicast UDP and MUST NOT be retransmitted.
+
+ An LLMNR sender cannot know in advance if a query sent using
+ multicast will receive no response, one response, or more than one
+ response. An LLMNR sender MUST wait for LLMNR_TIMEOUT if no response
+ has been received, or if it is necessary to collect all potential
+ responses, such as if a uniqueness verification query is being made.
+ Otherwise an LLMNR sender SHOULD consider a multicast query answered
+ after the first response is received, if that response has the 'C'
+ bit clear.
+
+ However, if the first response has the 'C' bit set, then the sender
+ SHOULD wait for LLMNR_TIMEOUT + JITTER_INTERVAL in order to collect
+ all possible responses. When multiple valid answers are received,
+ they may first be concatenated, and then treated in the same manner
+ that multiple RRs received from the same DNS server would. A unicast
+ query sender considers the query answered after the first response is
+ received.
+
+ Since it is possible for a response with the 'C' bit clear to be
+ followed by a response with the 'C' bit set, an LLMNR sender SHOULD
+ be prepared to process additional responses for the purposes of
+ conflict detection, even after it has considered a query answered.
+
+ In order to avoid synchronization, the transmission of each LLMNR
+ query and response SHOULD delayed by a time randomly selected from
+ the interval 0 to JITTER_INTERVAL. This delay MAY be avoided by
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 13]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ responders responding with names which they have previously
+ determined to be UNIQUE (see Section 4 for details).
+
+2.8. DNS TTL
+
+ The responder should insert a pre-configured TTL value in the records
+ returned in an LLMNR response. A default value of 30 seconds is
+ RECOMMENDED. In highly dynamic environments (such as mobile ad-hoc
+ networks), the TTL value may need to be reduced.
+
+ Due to the TTL minimalization necessary when caching an RRset, all
+ TTLs in an RRset MUST be set to the same value.
+
+2.9. Use of the Authority and Additional Sections
+
+ Unlike the DNS, LLMNR is a peer-to-peer protocol and does not have a
+ concept of delegation. In LLMNR, the NS resource record type may be
+ stored and queried for like any other type, but it has no special
+ delegation semantics as it does in the DNS. Responders MAY have NS
+ records associated with the names for which they are authoritative,
+ but they SHOULD NOT include these NS records in the authority
+ sections of responses.
+
+ Responders SHOULD insert an SOA record into the authority section of
+ a negative response, to facilitate negative caching as specified in
+ [RFC2308]. The TTL of this record is set from the minimum of the
+ MINIMUM field of the SOA record and the TTL of the SOA itself, and
+ indicates how long a resolver may cache the negative answer. The
+ owner name of the SOA record (MNAME) MUST be set to the query name.
+ The RNAME, SERIAL, REFRESH, RETRY and EXPIRE values MUST be ignored
+ by senders. Negative responses without SOA records SHOULD NOT be
+ cached.
+
+ In LLMNR, the additional section is primarily intended for use by
+ EDNS0, TSIG and SIG(0). As a result, unless the 'C' bit is set,
+ senders MAY only include pseudo RR-types in the additional section of
+ a query; unless the 'C' bit is set, responders MUST ignore the
+ additional section of queries containing other RR types.
+
+ In queries where the 'C' bit is set, the sender SHOULD include the
+ conflicting RRs in the additional section. Since conflict
+ notifications are advisory, responders SHOULD log information from
+ the additional section, but otherwise MUST ignore the additional
+ section.
+
+ Senders MUST NOT cache RRs from the authority or additional section
+ of a response as answers, though they may be used for other purposes
+ such as negative caching.
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 14]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+3. Usage Model
+
+ LLMNR is a peer-to-peer name resolution protocol that is not intended
+ as a replacement for DNS; rather, it enables name resolution in
+ scenarios in which conventional DNS name resolution is not possible.
+ This includes situations in which hosts are not configured with the
+ address of a DNS server; where the DNS server is unavailable or
+ unreachable; where there is no DNS server authoritative for the name
+ of a host, or where the authoritative DNS server does not have the
+ desired RRs.
+
+ By default, an LLMNR sender SHOULD send LLMNR queries only for
+ single-label names. In order to reduce unnecessary DNS queries, stub
+ resolvers supporting both DNS and LLMNR SHOULD avoid sending DNS
+ queries for single-label names. An LLMNR sender SHOULD NOT be
+ enabled to send a query for any name, except where security
+ mechanisms (described in Section 5.3) can be utilized.
+
+ Regardless of whether security mechanisms can be utilized, LLMNR
+ queries SHOULD NOT be sent unless one of the following conditions are
+ met:
+
+ [1] No manual or automatic DNS configuration has been performed.
+ If DNS server address(es) have been configured, a
+ host SHOULD attempt to reach DNS servers over all protocols
+ on which DNS server address(es) are configured, prior to sending
+ LLMNR queries. For dual stack hosts configured with DNS server
+ address(es) for one protocol but not another, this implies that
+ DNS queries SHOULD be sent over the protocol configured with
+ a DNS server, prior to sending LLMNR queries.
+
+ [2] All attempts to resolve the name via DNS on all interfaces
+ have failed after exhausting the searchlist. This can occur
+ because DNS servers did not respond, or because they
+ responded to DNS queries with RCODE=3 (Authoritative Name
+ Error) or RCODE=0, and an empty answer section. Where a
+ single resolver call generates DNS queries for A and AAAA RRs,
+ an implementation MAY choose not to send LLMNR queries if any
+ of the DNS queries is successful. An LLMNR query SHOULD only
+ be sent for the originally requested name; a searchlist
+ is not used to form additional LLMNR queries.
+
+ Since LLMNR is a secondary name resolution mechanism, its usage is in
+ part determined by the behavior of DNS implementations. In general,
+ robust DNS resolver implementations are more likely to avoid
+ unnecessary LLMNR queries.
+
+ As noted in [DNSPerf], even when DNS servers are configured, a
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 15]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ significant fraction of DNS queries do not receive a response, or
+ result in negative responses due to missing inverse mappings or NS
+ records that point to nonexistent or inappropriate hosts. This has
+ the potential to result in a large number of unnecessary LLMNR
+ queries.
+
+ [RFC1536] describes common DNS implementation errors and fixes. If
+ the proposed fixes are implemented, unnecessary LLMNR queries will be
+ reduced substantially, and so implementation of [RFC1536] is
+ recommended.
+
+ For example, [RFC1536] Section 1 describes issues with retransmission
+ and recommends implementation of a retransmission policy based on
+ round trip estimates, with exponential back-off. [RFC1536] Section 4
+ describes issues with failover, and recommends that resolvers try
+ another server when they don't receive a response to a query. These
+ policies are likely to avoid unnecessary LLMNR queries.
+
+ [RFC1536] Section 3 describes zero answer bugs, which if addressed
+ will also reduce unnecessary LLMNR queries.
+
+ [RFC1536] Section 6 describes name error bugs and recommended
+ searchlist processing that will reduce unnecessary RCODE=3
+ (authoritative name) errors, thereby also reducing unnecessary LLMNR
+ queries.
+
+ If error responses are received from both DNS and LLMNR, then the
+ lowest RCODE value should be returned. For example, if either DNS or
+ LLMNR receives a response with RCODE=0, then this should returned to
+ the caller.
+
+3.1. LLMNR Configuration
+
+ LLMNR usage MAY be configured manually or automatically on a per
+ interface basis. By default, LLMNR responders SHOULD be enabled on
+ all interfaces, at all times. Enabling LLMNR for use in situations
+ where a DNS server has been configured will result in a change in
+ default behavior without a simultaneous update to configuration
+ information. Where this is considered undesirable, LLMNR SHOULD NOT
+ be enabled by default, so that hosts will neither listen on the link-
+ scope multicast address, nor will they send queries to that address.
+
+ Since IPv4 and IPv6 utilize distinct configuration mechanisms, it is
+ possible for a dual stack host to be configured with the address of a
+ DNS server over IPv4, while remaining unconfigured with a DNS server
+ suitable for use over IPv6.
+
+ In these situations, a dual stack host will send AAAA queries to the
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 16]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ configured DNS server over IPv4. However, an IPv6-only host
+ unconfigured with a DNS server suitable for use over IPv6 will be
+ unable to resolve names using DNS. Automatic IPv6 DNS configuration
+ mechanisms (such as [RFC3315] and [DNSDisc]) are not yet widely
+ deployed, and not all DNS servers support IPv6. Therefore lack of
+ IPv6 DNS configuration may be a common problem in the short term, and
+ LLMNR may prove useful in enabling link-local name resolution over
+ IPv6.
+
+ Where a DHCPv4 server is available but not a DHCPv6 server [RFC3315],
+ IPv6-only hosts may not be configured with a DNS server. Where there
+ is no DNS server authoritative for the name of a host or the
+ authoritative DNS server does not support dynamic client update over
+ IPv6 or DHCPv6-based dynamic update, then an IPv6-only host will not
+ be able to do DNS dynamic update, and other hosts will not be able to
+ resolve its name.
+
+ For example, if the configured DNS server responds to a AAAA RR query
+ sent over IPv4 or IPv6 with an authoritative name error (RCODE=3) or
+ RCODE=0 and an empty answer section, then a AAAA RR query sent using
+ LLMNR over IPv6 may be successful in resolving the name of an
+ IPv6-only host on the local link.
+
+ Similarly, if a DHCPv4 server is available providing DNS server
+ configuration, and DNS server(s) exist which are authoritative for
+ the A RRs of local hosts and support either dynamic client update
+ over IPv4 or DHCPv4-based dynamic update, then the names of local
+ IPv4 hosts can be resolved over IPv4 without LLMNR. However, if no
+ DNS server is authoritative for the names of local hosts, or the
+ authoritative DNS server(s) do not support dynamic update, then LLMNR
+ enables linklocal name resolution over IPv4.
+
+ Where DHCPv4 or DHCPv6 is implemented, DHCP options can be used to
+ configure LLMNR on an interface. The LLMNR Enable Option, described
+ in [LLMNREnable], can be used to explicitly enable or disable use of
+ LLMNR on an interface. The LLMNR Enable Option does not determine
+ whether or in which order DNS itself is used for name resolution.
+ The order in which various name resolution mechanisms should be used
+ can be specified using the Name Service Search Option (NSSO) for DHCP
+ [RFC2937], using the LLMNR Enable Option code carried in the NSSO
+ data.
+
+ It is possible that DNS configuration mechanisms will go in and out
+ of service. In these circumstances, it is possible for hosts within
+ an administrative domain to be inconsistent in their DNS
+ configuration.
+
+ For example, where DHCP is used for configuring DNS servers, one or
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 17]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ more DHCP servers can fail. As a result, hosts configured prior to
+ the outage will be configured with a DNS server, while hosts
+ configured after the outage will not. Alternatively, it is possible
+ for the DNS configuration mechanism to continue functioning while
+ configured DNS servers fail.
+
+ An outage in the DNS configuration mechanism may result in hosts
+ continuing to use LLMNR even once the outage is repaired. Since
+ LLMNR only enables linklocal name resolution, this represents a
+ degradation in capabilities. As a result, hosts without a configured
+ DNS server may wish to periodically attempt to obtain DNS
+ configuration if permitted by the configuration mechanism in use. In
+ the absence of other guidance, a default retry interval of one (1)
+ minute is RECOMMENDED.
+
+4. Conflict Resolution
+
+ By default, a responder SHOULD be configured to behave as though its
+ name is UNIQUE on each interface on which LLMNR is enabled. However,
+ it is also possible to configure multiple responders to be
+ authoritative for the same name. For example, multiple responders
+ MAY respond to a query for an A or AAAA type record for a cluster
+ name (assigned to multiple hosts in the cluster).
+
+ To detect duplicate use of a name, an administrator can use a name
+ resolution utility which employs LLMNR and lists both responses and
+ responders. This would allow an administrator to diagnose behavior
+ and potentially to intervene and reconfigure LLMNR responders who
+ should not be configured to respond to the same name.
+
+4.1. Uniqueness Verification
+
+ Prior to sending an LLMNR response with the 'T' bit clear, a
+ responder configured with a UNIQUE name MUST verify that there is no
+ other host within the scope of LLMNR query propagation that is
+ authoritative for the same name on that interface.
+
+ Once a responder has verified that its name is UNIQUE, if it receives
+ an LLMNR query for that name, with the 'C' bit clear, it MUST
+ respond, with the 'T' bit clear. Prior to verifying that its name is
+ UNIQUE, a responder MUST set the 'T' bit in responses.
+
+ Uniqueness verification is carried out when the host:
+
+ - starts up or is rebooted
+ - wakes from sleep (if the network interface was inactive
+ during sleep)
+ - is configured to respond to LLMNR queries on an interface
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 18]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ enabled for transmission and reception of IP traffic
+ - is configured to respond to LLMNR queries using additional
+ UNIQUE resource records
+ - verifies the acquisition of a new IP address and configuration
+ on an interface
+
+ To verify uniqueness, a responder MUST send an LLMNR query with the
+ 'C' bit clear, over all protocols on which it responds to LLMNR
+ queries (IPv4 and/or IPv6). It is RECOMMENDED that responders verify
+ uniqueness of a name by sending a query for the name with type='ANY'.
+
+ If no response is received, the sender retransmits the query, as
+ specified in Section 2.7. If a response is received, the sender MUST
+ check if the source address matches the address of any of its
+ interfaces; if so, then the response is not considered a conflict,
+ since it originates from the sender. To avoid triggering conflict
+ detection, a responder that detects that it is connected to the same
+ link on multiple interfaces SHOULD set the 'C' bit in responses.
+
+ If a response is received with the 'T' bit clear, the responder MUST
+ NOT use the name in response to LLMNR queries received over any
+ protocol (IPv4 or IPv6). If a response is received with the 'T' bit
+ set, the responder MUST check if the source IP address in the
+ response, interpreted as an unsigned integer, is less than the source
+ IP address in the query. If so, the responder MUST NOT use the name
+ in response to LLMNR queries received over any protocol (IPv4 or
+ IPv6). For the purpose of uniqueness verification, the contents of
+ the answer section in a response is irrelevant.
+
+ Periodically carrying out uniqueness verification in an attempt to
+ detect name conflicts is not necessary, wastes network bandwidth, and
+ may actually be detrimental. For example, if network links are
+ joined only briefly, and are separated again before any new
+ communication is initiated, temporary conflicts are benign and no
+ forced reconfiguration is required. LLMNR responders SHOULD NOT
+ periodically attempt uniqueness verification.
+
+4.2. Conflict Detection and Defense
+
+ Hosts on disjoint network links may configure the same name for use
+ with LLMNR. If these separate network links are later joined or
+ bridged together, then there may be multiple hosts which are now on
+ the same link, trying to use the same name.
+
+ In order to enable ongoing detection of name conflicts, when an LLMNR
+ sender receives multiple LLMNR responses to a query, it MUST check if
+ the 'C' bit is clear in any of the responses. If so, the sender
+ SHOULD send another query for the same name, type and class, this
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 19]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ time with the 'C' bit set, with the potentially conflicting resource
+ records included in the additional section.
+
+ Queries with the 'C' bit set are considered advisory and responders
+ MUST verify the existence of a conflict before acting on it. A
+ responder receiving a query with the 'C' bit set MUST NOT respond.
+
+ If the query is for a UNIQUE name, then the responder MUST send its
+ own query for the same name, type and class, with the 'C' bit clear.
+ If a response is received, the sender MUST check if the source
+ address matches the address of any of its interfaces; if so, then the
+ response is not considered a conflict, since it originates from the
+ sender. To avoid triggering conflict detection, a responder that
+ detects that it is connected to the same link on multiple interfaces
+ SHOULD set the 'C' bit in responses.
+
+ An LLMNR responder MUST NOT ignore conflicts once detected and SHOULD
+ log them. Upon detecting a conflict, an LLMNR responder MUST
+ immediately stop using the conflicting name in response to LLMNR
+ queries received over any supported protocol, if the source IP
+ address in the response, interpreted as an unsigned integer, is less
+ than the source IP address in the uniqueness verification query.
+
+ After stopping the use of a name, the responder MAY elect to
+ configure a new name. However, since name reconfiguration may be
+ disruptive, this is not required, and a responder may have been
+ configured to respond to multiple names so that alternative names may
+ already be available. A host that has stopped the use of a name may
+ attempt uniqueness verification again after the expiration of the TTL
+ of the conflicting response.
+
+4.3. Considerations for Multiple Interfaces
+
+ A multi-homed host may elect to configure LLMNR on only one of its
+ active interfaces. In many situations this will be adequate.
+ However, should a host need to configure LLMNR on more than one of
+ its active interfaces, there are some additional precautions it MUST
+ take. Implementers who are not planning to support LLMNR on multiple
+ interfaces simultaneously may skip this section.
+
+ Where a host is configured to issue LLMNR queries on more than one
+ interface, each interface maintains its own independent LLMNR
+ resolver cache, containing the responses to LLMNR queries.
+
+ A multi-homed host checks the uniqueness of UNIQUE records as
+ described in Section 4. The situation is illustrated in figure 1.
+
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 20]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ ---------- ----------
+ | | | |
+ [A] [myhost] [myhost]
+
+ Figure 1. Link-scope name conflict
+
+ In this situation, the multi-homed myhost will probe for, and defend,
+ its host name on both interfaces. A conflict will be detected on one
+ interface, but not the other. The multi-homed myhost will not be
+ able to respond with a host RR for "myhost" on the interface on the
+ right (see Figure 1). The multi-homed host may, however, be
+ configured to use the "myhost" name on the interface on the left.
+
+ Since names are only unique per-link, hosts on different links could
+ be using the same name. If an LLMNR client sends requests over
+ multiple interfaces, and receives replies from more than one, the
+ result returned to the client is defined by the implementation. The
+ situation is illustrated in figure 2.
+
+ ---------- ----------
+ | | | |
+ [A] [myhost] [A]
+
+
+ Figure 2. Off-segment name conflict
+
+ If host myhost is configured to use LLMNR on both interfaces, it will
+ send LLMNR queries on both interfaces. When host myhost sends a
+ query for the host RR for name "A" it will receive a response from
+ hosts on both interfaces.
+
+ Host myhost cannot distinguish between the situation shown in Figure
+ 2, and that shown in Figure 3 where no conflict exists.
+
+ [A]
+ | |
+ ----- -----
+ | |
+ [myhost]
+
+ Figure 3. Multiple paths to same host
+
+ This illustrates that the proposed name conflict resolution mechanism
+ does not support detection or resolution of conflicts between hosts
+ on different links. This problem can also occur with DNS when a
+ multi-homed host is connected to two different networks with
+ separated name spaces. It is not the intent of this document to
+ address the issue of uniqueness of names within DNS.
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 21]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+4.4. API Issues
+
+ [RFC2553] provides an API which can partially solve the name
+ ambiguity problem for applications written to use this API, since the
+ sockaddr_in6 structure exposes the scope within which each scoped
+ address exists, and this structure can be used for both IPv4 (using
+ v4-mapped IPv6 addresses) and IPv6 addresses.
+
+ Following the example in Figure 2, an application on 'myhost' issues
+ the request getaddrinfo("A", ...) with ai_family=AF_INET6 and
+ ai_flags=AI_ALL|AI_V4MAPPED. LLMNR requests will be sent from both
+ interfaces and the resolver library will return a list containing
+ multiple addrinfo structures, each with an associated sockaddr_in6
+ structure. This list will thus contain the IPv4 and IPv6 addresses
+ of both hosts responding to the name 'A'. Link-local addresses will
+ have a sin6_scope_id value that disambiguates which interface is used
+ to reach the address. Of course, to the application, Figures 2 and 3
+ are still indistinguishable, but this API allows the application to
+ communicate successfully with any address in the list.
+
+5. Security Considerations
+
+ LLMNR is a peer-to-peer name resolution protocol designed for use on
+ the local link. While LLMNR limits the vulnerability of responders
+ to off-link senders, it is possible for an off-link responder to
+ reach a sender.
+
+ In scenarios such as public "hotspots" attackers can be present on
+ the same link. These threats are most serious in wireless networks
+ such as 802.11, since attackers on a wired network will require
+ physical access to the network, while wireless attackers may mount
+ attacks from a distance. Link-layer security such as [IEEE-802.11i]
+ can be of assistance against these threats if it is available.
+
+ This section details security measures available to mitigate threats
+ from on and off-link attackers.
+
+5.1. Denial of Service
+
+ Attackers may take advantage of LLMNR conflict detection by
+ allocating the same name, denying service to other LLMNR responders
+ and possibly allowing an attacker to receive packets destined for
+ other hosts. By logging conflicts, LLMNR responders can provide
+ forensic evidence of these attacks.
+
+ An attacker may spoof LLMNR queries from a victim's address in order
+ to mount a denial of service attack. Responders setting the IPv6 Hop
+ Limit or IPv4 TTL field to a value larger than one in an LLMNR UDP
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 22]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ response may be able to reach the victim across the Internet.
+
+ While LLMNR responders only respond to queries for which they are
+ authoritative and LLMNR does not provide wildcard query support, an
+ LLMNR response may be larger than the query, and an attacker can
+ generate multiple responses to a query for a name used by multiple
+ responders. A sender may protect itself against unsolicited
+ responses by silently discarding them as rapidly as possible.
+
+5.2. Spoofing
+
+ LLMNR is designed to prevent reception of queries sent by an off-link
+ attacker. LLMNR requires that responders receiving UDP queries check
+ that they are sent to a link-scope multicast address. However, it is
+ possible that some routers may not properly implement link-scope
+ multicast, or that link-scope multicast addresses may leak into the
+ multicast routing system. To prevent successful setup of TCP
+ connections by an off-link sender, responders receiving a TCP SYN
+ reply with a TCP SYN-ACK with TTL set to one (1).
+
+ While it is difficult for an off-link attacker to send an LLMNR query
+ to a responder, it is possible for an off-link attacker to spoof a
+ response to a query (such as an A or AAAA query for a popular
+ Internet host), and by using a TTL or Hop Limit field larger than one
+ (1), for the forged response to reach the LLMNR sender. Since the
+ forged response will only be accepted if it contains a matching ID
+ field, choosing a pseudo-random ID field within queries provides some
+ protection against off-link responders.
+
+ Since LLMNR queries can be sent when DNS server(s) do not respond, an
+ attacker can execute a denial of service attack on the DNS server(s)
+ and then poison the LLMNR cache by responding to an LLMNR query with
+ incorrect information. As noted in "Threat Analysis of the Domain
+ Name System (DNS)" [RFC3833] these threats also exist with DNS, since
+ DNS response spoofing tools are available that can allow an attacker
+ to respond to a query more quickly than a distant DNS server.
+ However, while switched networks or link layer security may make it
+ difficult for an on-link attacker to snoop unicast DNS queries,
+ multicast LLMNR queries are propagated to all hosts on the link,
+ making it possible for an on-link attacker to spoof LLMNR responses
+ without having to guess the value of the ID field in the query.
+
+ Since LLMNR queries are sent and responded to on the local-link, an
+ attacker will need to respond more quickly to provide its own
+ response prior to arrival of the response from a legitimate
+ responder. If an LLMNR query is sent for an off-link host, spoofing
+ a response in a timely way is not difficult, since a legitimate
+ response will never be received.
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 23]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ This vulnerability can be reduced by limiting use of LLMNR to
+ resolution of single-label names as described in Section 3, or by
+ implementation of authentication (see Section 5.3).
+
+5.3. Authentication
+
+ LLMNR is a peer-to-peer name resolution protocol, and as a result,
+ it is often deployed in situations where no trust model can be
+ assumed. Where a pre-arranged security configuration is possible,
+ the following security mechanisms may be used:
+
+[a] LLMNR implementations MAY support TSIG [RFC2845] and/or SIG(0)
+ [RFC2931] security mechanisms. "DNS Name Service based on Secure
+ Multicast DNS for IPv6 Mobile Ad Hoc Networks" [LLMNRSec] describes
+ the use of TSIG to secure LLMNR, based on group keys. While group
+ keys can be used to demonstrate membership in a group, they do not
+ protect against forgery by an attacker that is a member of the
+ group.
+
+[b] IPsec ESP with a null-transform MAY be used to authenticate unicast
+ LLMNR queries and responses or LLMNR responses to multicast
+ queries. In a small network without a certificate authority, this
+ can be most easily accomplished through configuration of a group
+ pre-shared key for trusted hosts. As with TSIG, this does not
+ protect against forgery by an attacker with access to the group
+ pre-shared key.
+
+[c] LLMNR implementations MAY support DNSSEC [RFC4033]. In order to
+ support DNSSEC, LLMNR implementations MAY be configured with trust
+ anchors, or they MAY make use of keys obtained from DNS queries.
+ Since LLMNR does not support "delegated trust" (CD or AD bits),
+ LLMNR implementations cannot make use of DNSSEC unless they are
+ DNSSEC-aware and support validation. Unlike approaches [a] or [b],
+ DNSSEC permits a responder to demonstrate ownership of a name, not
+ just membership within a trusted group. As a result, it enables
+ protection against forgery.
+
+5.4. Cache and Port Separation
+
+ In order to prevent responses to LLMNR queries from polluting the DNS
+ cache, LLMNR implementations MUST use a distinct, isolated cache for
+ LLMNR on each interface. The use of separate caches is most
+ effective when LLMNR is used as a name resolution mechanism of last
+ resort, since this minimizes the opportunities for poisoning the
+ LLMNR cache, and decreases reliance on it.
+
+ LLMNR operates on a separate port from DNS, reducing the likelihood
+ that a DNS server will unintentionally respond to an LLMNR query.
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 24]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+ If LLMNR is given higher priority than DNS among the enabled name
+ resolution mechanisms, a denial of service attack on the DNS server
+ would not be necessary in order to poison the LLMNR cache, since
+ LLMNR queries would be sent even when the DNS server is available.
+ In addition, the LLMNR cache, once poisoned, would take precedence
+ over the DNS cache, eliminating the benefits of cache separation. As
+ a result, LLMNR SHOULD NOT be used as a primary name resolution
+ mechanism.
+
+6. IANA Considerations
+
+ LLMNR requires allocation of port 5355 for both TCP and UDP.
+
+ LLMNR requires allocation of link-scope multicast IPv4 address
+ 224.0.0.252, as well as link-scope multicast IPv6 address
+ FF02:0:0:0:0:0:1:3.
+
+ This specification creates two new name spaces: the LLMNR namespace
+ and the reserved bits in the LLMNR header. The reserved bits in the
+ LLMNR header are allocated by IETF Consensus, in accordance with BCP
+ 26 [RFC2434].
+
+ In order to to avoid creating any new administrative procedures,
+ administration of the LLMNR namespace will piggyback on the
+ administration of the DNS namespace.
+
+ The rights to use a fully qualified domain name (FQDN) within LLMNR
+ are obtained coincident with acquiring the rights to use that name
+ within DNS. Those wishing to use a FQDN within LLMNR should first
+ acquire the rights to use the corresponding FQDN within DNS. Using a
+ FQDN within LLMNR without ownership of the corresponding name in DNS
+ creates the possibility of conflict and therefore is discouraged.
+
+ LLMNR responders may self-allocate a name within the single-label
+ name space, first defined in [RFC1001]. Since single-label names are
+ not unique, no registration process is required.
+
+7. Constants
+
+ The following timing constants are used in this protocol; they are
+ not intended to be user configurable.
+
+ JITTER_INTERVAL 100 ms
+ LLMNR_TIMEOUT 1 second (if set statically on all interfaces)
+ 100 ms (IEEE 802 media, including IEEE 802.11)
+
+
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 25]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+8. References
+
+8.1. Normative References
+
+[RFC1001] Auerbach, K. and A. Aggarwal, "Protocol Standard for a NetBIOS
+ Service on a TCP/UDP Transport: Concepts and Methods", RFC
+ 1001, March 1987.
+
+[RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", RFC 1035, November 1987.
+
+[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+[RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+[RFC2308] Andrews, M., "Negative Caching of DNS Queries (DNS NCACHE)",
+ RFC 2308, March 1998.
+
+[RFC2373] Hinden, R. and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 2373, July 1998.
+
+[RFC2434] Alvestrand, H. and T. Narten, "Guidelines for Writing an IANA
+ Considerations Section in RFCs", BCP 26, RFC 2434, October
+ 1998.
+
+[RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC 2671,
+ August 1999.
+
+[RFC2845] Vixie, P., Gudmundsson, O., Eastlake, D. and B. Wellington,
+ "Secret Key Transaction Authentication for DNS (TSIG)", RFC
+ 2845, May 2000.
+
+[RFC2931] Eastlake, D., "DNS Request and Transaction Signatures
+ (SIG(0)s)", RFC 2931, September 2000.
+
+8.2. Informative References
+
+[DNSPerf] Jung, J., et al., "DNS Performance and the Effectiveness of
+ Caching", IEEE/ACM Transactions on Networking, Volume 10,
+ Number 5, pp. 589, October 2002.
+
+[DNSDisc] Durand, A., Hagino, I. and D. Thaler, "Well known site local
+ unicast addresses to communicate with recursive DNS servers",
+ Internet draft (work in progress), draft-ietf-ipv6-dns-
+ discovery-07.txt, October 2002.
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 26]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+[IEEE-802.11i]
+ Institute of Electrical and Electronics Engineers, "Supplement
+ to Standard for Telecommunications and Information Exchange
+ Between Systems - LAN/MAN Specific Requirements - Part 11:
+ Wireless LAN Medium Access Control (MAC) and Physical Layer
+ (PHY) Specifications: Specification for Enhanced Security",
+ IEEE 802.11i, July 2004.
+
+[LLMNREnable]
+ Guttman, E., "DHCP LLMNR Enable Option", Internet draft (work
+ in progress), draft-guttman-mdns-enable-02.txt, April 2002.
+
+[LLMNRSec]
+ Jeong, J., Park, J. and H. Kim, "DNS Name Service based on
+ Secure Multicast DNS for IPv6 Mobile Ad Hoc Networks", ICACT
+ 2004, Phoenix Park, Korea, February 9-11, 2004.
+
+[POSIX] IEEE Std. 1003.1-2001 Standard for Information Technology --
+ Portable Operating System Interface (POSIX). Open Group
+ Technical Standard: Base Specifications, Issue 6, December
+ 2001. ISO/IEC 9945:2002. http://www.opengroup.org/austin
+
+[RFC1536] Kumar, A., et. al., "DNS Implementation Errors and Suggested
+ Fixes", RFC 1536, October 1993.
+
+[RFC1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness
+ Recommendations for Security", RFC 1750, December 1994.
+
+[RFC2131] Droms, R., "Dynamic Host Configuration Protocol", RFC 2131,
+ March 1997.
+
+[RFC2292] Stevens, W. and M. Thomas, "Advanced Sockets API for IPv6",
+ RFC 2292, February 1998.
+
+[RFC2365] Meyer, D., "Administratively Scoped IP Multicast", BCP 23, RFC
+ 2365, July 1998.
+
+[RFC2553] Gilligan, R., Thomson, S., Bound, J. and W. Stevens, "Basic
+ Socket Interface Extensions for IPv6", RFC 2553, March 1999.
+
+[RFC2937] Smith, C., "The Name Service Search Option for DHCP", RFC
+ 2937, September 2000.
+
+[RFC3315] Droms, R., et al., "Dynamic Host Configuration Protocol for
+ IPv6 (DHCPv6)", RFC 3315, July 2003.
+
+[RFC3833] Atkins, D. and R. Austein, "Threat Analysis of the Domain Name
+ System (DNS)", RFC 3833, August 2004.
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 27]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+[RFC3927] Cheshire, S., Aboba, B. and E. Guttman, "Dynamic Configuration
+ of Link-Local IPv4 Addresses", RFC 3927, October 2004.
+
+[RFC4033] Arends, R., Austein, R., Larson, M., Massey, D. and S. Rose,
+ "DNS Security Introduction and Requirement", RFC 4033, March
+ 2005.
+
+Acknowledgments
+
+ This work builds upon original work done on multicast DNS by Bill
+ Manning and Bill Woodcock. Bill Manning's work was funded under
+ DARPA grant #F30602-99-1-0523. The authors gratefully acknowledge
+ their contribution to the current specification. Constructive input
+ has also been received from Mark Andrews, Rob Austein, Randy Bush,
+ Stuart Cheshire, Ralph Droms, Robert Elz, James Gilroy, Olafur
+ Gudmundsson, Andreas Gustafsson, Erik Guttman, Myron Hattig,
+ Christian Huitema, Olaf Kolkman, Mika Liljeberg, Keith Moore,
+ Tomohide Nagashima, Thomas Narten, Erik Nordmark, Markku Savela, Mike
+ St. Johns, Sander Van-Valkenburg, and Brian Zill.
+
+Authors' Addresses
+
+ Bernard Aboba
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+
+ Phone: +1 425 706 6605
+ EMail: bernarda@microsoft.com
+
+ Dave Thaler
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+
+ Phone: +1 425 703 8835
+ EMail: dthaler@microsoft.com
+
+ Levon Esibov
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+
+ EMail: levone@microsoft.com
+
+
+
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 28]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2006). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 29]
+
+
+
+
+
+INTERNET-DRAFT LLMNR 16 April 2006
+
+
+Open Issues
+
+ Open issues with this specification are tracked on the following web
+ site:
+
+ http://www.drizzle.com/~aboba/DNSEXT/llmnrissues.html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba, Thaler & Esibov Standards Track [Page 30]
+
+
+
diff --git a/doc/draft/draft-ietf-dnsext-nsid-01.txt b/doc/draft/draft-ietf-dnsext-nsid-01.txt
new file mode 100644
index 0000000..90d1a06
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-nsid-01.txt
@@ -0,0 +1,840 @@
+
+
+
+Network Working Group R. Austein
+Internet-Draft ISC
+Expires: July 15, 2006 January 11, 2006
+
+
+ DNS Name Server Identifier Option (NSID)
+ draft-ietf-dnsext-nsid-01
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on July 15, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ With the increased use of DNS anycast, load balancing, and other
+ mechanisms allowing more than one DNS name server to share a single
+ IP address, it is sometimes difficult to tell which of a pool of name
+ servers has answered a particular query. While existing ad-hoc
+ mechanism allow an operator to send follow-up queries when it is
+ necessary to debug such a configuration, the only completely reliable
+ way to obtain the identity of the name server which responded is to
+ have the name server include this information in the response itself.
+ This note defines a protocol extension to support this functionality.
+
+
+
+Austein Expires July 15, 2006 [Page 1]
+
+Internet-Draft DNS NSID January 2006
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1. Reserved Words . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 2.1. Resolver Behavior . . . . . . . . . . . . . . . . . . . . 4
+ 2.2. Name Server Behavior . . . . . . . . . . . . . . . . . . . 4
+ 2.3. The NSID Option . . . . . . . . . . . . . . . . . . . . . 4
+ 2.4. Presentation Format . . . . . . . . . . . . . . . . . . . 5
+ 3. Discussion . . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 3.1. The NSID Payload . . . . . . . . . . . . . . . . . . . . . 6
+ 3.2. NSID Is Not Transitive . . . . . . . . . . . . . . . . . . 8
+ 3.3. User Interface Issues . . . . . . . . . . . . . . . . . . 8
+ 3.4. Truncation . . . . . . . . . . . . . . . . . . . . . . . . 9
+ 4. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 10
+ 5. Security Considerations . . . . . . . . . . . . . . . . . . . 11
+ 6. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 12
+ 7. References . . . . . . . . . . . . . . . . . . . . . . . . . . 13
+ 7.1. Normative References . . . . . . . . . . . . . . . . . . . 13
+ 7.2. Informative References . . . . . . . . . . . . . . . . . . 13
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 14
+ Intellectual Property and Copyright Statements . . . . . . . . . . 15
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Expires July 15, 2006 [Page 2]
+
+Internet-Draft DNS NSID January 2006
+
+
+1. Introduction
+
+ With the increased use of DNS anycast, load balancing, and other
+ mechanisms allowing more than one DNS name server to share a single
+ IP address, it is sometimes difficult to tell which of a pool of name
+ servers has answered a particular query.
+
+ Existing ad-hoc mechanisms allow an operator to send follow-up
+ queries when it is necessary to debug such a configuration, but there
+ are situations in which this is not a totally satisfactory solution,
+ since anycast routing may have changed, or the server pool in
+ question may be behind some kind of extremely dynamic load balancing
+ hardware. Thus, while these ad-hoc mechanisms are certainly better
+ than nothing (and have the advantage of already being deployed), a
+ better solution seems desirable.
+
+ Given that a DNS query is an idempotent operation with no retained
+ state, it would appear that the only completely reliable way to
+ obtain the identity of the name server which responded to a
+ particular query is to have that name server include identifying
+ information in the response itself. This note defines a protocol
+ enhancement to achieve this.
+
+1.1. Reserved Words
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Expires July 15, 2006 [Page 3]
+
+Internet-Draft DNS NSID January 2006
+
+
+2. Protocol
+
+ This note uses an EDNS [RFC2671] option to signal the resolver's
+ desire for information identifying the name server and to hold the
+ name server's response, if any.
+
+2.1. Resolver Behavior
+
+ A resolver signals its desire for information identifying a name
+ server by sending an empty NSID option (Section 2.3) in an EDNS OPT
+ pseudo-RR in the query message.
+
+ The resolver MUST NOT include any NSID payload data in the query
+ message.
+
+ The semantics of an NSID request are not transitive. That is: the
+ presence of an NSID option in a query is a request that the name
+ server which receives the query identify itself. If the name server
+ side of a recursive name server receives an NSID request, the client
+ is asking the recursive name server to identify itself; if the
+ resolver side of the recursive name server wishes to receive
+ identifying information, it is free to add NSID requests in its own
+ queries, but that is a separate matter.
+
+2.2. Name Server Behavior
+
+ A name server which understands the NSID option and chooses to honor
+ a particular NSID request responds by including identifying
+ information in a NSID option (Section 2.3) in an EDNS OPT pseudo-RR
+ in the response message.
+
+ The name server MUST ignore any NSID payload data that might be
+ present in the query message.
+
+ The NSID option is not transitive. A name server MUST NOT send an
+ NSID option back to a resolver which did not request it. In
+ particular, while a recursive name server may choose to add an NSID
+ option when sending a query, this has no effect on the presence or
+ absence of the NSID option in the recursive name server's response to
+ the original client.
+
+ As stated in Section 2.1, this mechanism is not restricted to
+ authoritative name servers; the semantics are intended to be equally
+ applicable to recursive name servers.
+
+2.3. The NSID Option
+
+ The OPTION-CODE for the NSID option is [TBD].
+
+
+
+Austein Expires July 15, 2006 [Page 4]
+
+Internet-Draft DNS NSID January 2006
+
+
+ The OPTION-DATA for the NSID option is an opaque byte string the
+ semantics of which are deliberately left outside the protocol. See
+ Section 3.1 for discussion.
+
+2.4. Presentation Format
+
+ User interfaces MUST read and write the content of the NSID option as
+ a sequence of hexadecimal digits, two digits per payload octet.
+
+ The NSID payload is binary data. Any comparison between NSID
+ payloads MUST be a comparison of the raw binary data. Copy
+ operations MUST NOT assume that the raw NSID payload is null-
+ terminated. Any resemblance between raw NSID payload data and any
+ form of text is purely a convenience, and does not change the
+ underlying nature of the payload data.
+
+ See Section 3.3 for discussion.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Expires July 15, 2006 [Page 5]
+
+Internet-Draft DNS NSID January 2006
+
+
+3. Discussion
+
+ This section discusses certain aspects of the protocol and explains
+ considerations that led to the chosen design.
+
+3.1. The NSID Payload
+
+ The syntax and semantics of the content of the NSID option is
+ deliberately left outside the scope of this specification. This
+ section describe some of the kinds of data that server administrators
+ might choose to provide as the content of the NSID option, and
+ explains the reasoning behind choosing a simple opaque byte string.
+
+ There are several possibilities for the payload of the NSID option:
+
+ o It could be the "real" name of the specific name server within the
+ name server pool.
+
+ o It could be the "real" IP address (IPv4 or IPv6) of the name
+ server within the name server pool.
+
+ o It could be some sort of pseudo-random number generated in a
+ predictable fashion somehow using the server's IP address or name
+ as a seed value.
+
+ o It could be some sort of probabilisticly unique identifier
+ initially derived from some sort of random number generator then
+ preserved across reboots of the name server.
+
+ o It could be some sort of dynamicly generated identifier so that
+ only the name server operator could tell whether or not any two
+ queries had been answered by the same server.
+
+ o It could be a blob of signed data, with a corresponding key which
+ might (or might not) be available via DNS lookups.
+
+ o It could be a blob of encrypted data, the key for which could be
+ restricted to parties with a need to know (in the opinion of the
+ server operator).
+
+ o It could be an arbitrary string of octets chosen at the discretion
+ of the name server operator.
+
+ Each of these options has advantages and disadvantages:
+
+ o Using the "real" name is simple, but the name server may not have
+ a "real" name.
+
+
+
+
+Austein Expires July 15, 2006 [Page 6]
+
+Internet-Draft DNS NSID January 2006
+
+
+ o Using the "real" address is also simple, and the name server
+ almost certainly does have at least one non-anycast IP address for
+ maintenance operations, but the operator of the name server may
+ not be willing to divulge its non-anycast address.
+
+ o Given that one common reason for using anycast DNS techniques is
+ an attempt to harden a critical name server against denial of
+ service attacks, some name server operators are likely to want an
+ identifier other than the "real" name or "real" address of the
+ name server instance.
+
+ o Using a hash or pseudo-random number can provide a fixed length
+ value that the resolver can use to tell two name servers apart
+ without necessarily being able to tell where either one of them
+ "really" is, but makes debugging more difficult if one happens to
+ be in a friendly open environment. Furthermore, hashing might not
+ add much value, since a hash based on an IPv4 address still only
+ involves a 32-bit search space, and DNS names used for servers
+ that operators might have to debug at 4am tend not to be very
+ random.
+
+ o Probabilisticly unique identifiers have similar properties to
+ hashed identifiers, but (given a sufficiently good random number
+ generator) are immune to the search space issues. However, the
+ strength of this approach is also its weakness: there is no
+ algorithmic transformation by which even the server operator can
+ associate name server instances with identifiers while debugging,
+ which might be annoying. This approach also requires the name
+ server instance to preserve the probabilisticly unique identifier
+ across reboots, but this does not appear to be a serious
+ restriction, since authoritative nameservers almost always have
+ some form of nonvolatile storage in any case, and in the rare case
+ of a name server that does not have any way to store such an
+ identifier, nothing terrible will happen if the name server just
+ generates a new identifier every time it reboots.
+
+ o Using an arbitrary octet string gives name server operators yet
+ another thing to configure, or mis-configure, or forget to
+ configure. Having all the nodes in an anycast name server
+ constellation identify themselves as "My Name Server" would not be
+ particularly useful.
+
+ Given all of the issues listed above, there does not appear to be a
+ single solution that will meet all needs. Section 2.3 therefore
+ defines the NSID payload to be an opaque byte string and leaves the
+ choice up to the implementor and name server operator. The following
+ guidelines may be useful to implementors and server operators:
+
+
+
+
+Austein Expires July 15, 2006 [Page 7]
+
+Internet-Draft DNS NSID January 2006
+
+
+ o Operators for whom divulging the unicast address is an issue could
+ use the raw binary representation of a probabilisticly unique
+ random number. This should probably be the default implementation
+ behavior.
+
+ o Operators for whom divulging the unicast address is not an issue
+ could just use the raw binary representation of a unicast address
+ for simplicity. This should only be done via an explicit
+ configuration choice by the operator.
+
+ o Operators who really need or want the ability to set the NSID
+ payload to an arbitrary value could do so, but this should only be
+ done via an explicit configuration choice by the operator.
+
+ This approach appears to provide enough information for useful
+ debugging without unintentionally leaking the maintenance addresses
+ of anycast name servers to nogoodniks, while also allowing name
+ server operators who do not find such leakage threatening to provide
+ more information at their own discretion.
+
+3.2. NSID Is Not Transitive
+
+ As specified in Section 2.1 and Section 2.2, the NSID option is not
+ transitive. This is strictly a hop-by-hop mechanism.
+
+ Most of the discussion of name server identification to date has
+ focused on identifying authoritative name servers, since the best
+ known cases of anycast name servers are a subset of the name servers
+ for the root zone. However, given that anycast DNS techniques are
+ also applicable to recursive name servers, the mechanism may also be
+ useful with recursive name servers. The hop-by-hop semantics support
+ this.
+
+ While there might be some utility in having a transitive variant of
+ this mechanism (so that, for example, a stub resolver could ask a
+ recursive server to tell it which authoritative name server provided
+ a particular answer to the recursive name server), the semantics of
+ such a variant would be more complicated, and are left for future
+ work.
+
+3.3. User Interface Issues
+
+ Given the range of possible payload contents described in
+ Section 3.1, it is not possible to define a single presentation
+ format for the NSID payload that is efficient, convenient,
+ unambiguous, and aesthetically pleasing. In particular, while it is
+ tempting to use a presentation format that uses some form of textual
+ strings, attempting to support this would significantly complicate
+
+
+
+Austein Expires July 15, 2006 [Page 8]
+
+Internet-Draft DNS NSID January 2006
+
+
+ what's intended to be a very simple debugging mechanism.
+
+ In some cases the content of the NSID payload may be binary data
+ meaningful only to the name server operator, and may not be
+ meaningful to the user or application, but the user or application
+ must be able to capture the entire content anyway in order for it to
+ be useful. Thus, the presentation format must support arbitrary
+ binary data.
+
+ In cases where the name server operator derives the NSID payload from
+ textual data, a textual form such as US-ASCII or UTF-8 strings might
+ at first glance seem easier for a user to deal with. There are,
+ however, a number of complex issues involving internationalized text
+ which, if fully addressed here, would require a set of rules
+ significantly longer than the rest of this specification. See
+ [RFC2277] for an overview of some of these issues.
+
+ It is much more important for the NSID payload data to be passed
+ unambiguously from server administrator to user and back again than
+ it is for the payload data data to be pretty while in transit. In
+ particular, it's critical that it be straightforward for a user to
+ cut and paste an exact copy of the NSID payload output by a debugging
+ tool into other formats such as email messages or web forms without
+ distortion. Hexadecimal strings, while ugly, are also robust.
+
+3.4. Truncation
+
+ In some cases, adding the NSID option to a response message may
+ trigger message truncation. This specification does not change the
+ rules for DNS message truncation in any way, but implementors will
+ need to pay attention to this issue.
+
+ Including the NSID option in a response is always optional, so this
+ specification never requires name servers to truncate response
+ messages.
+
+ By definition, a resolver that requests NSID responses also supports
+ EDNS, so a resolver that requests NSID responses can also use the
+ "sender's UDP payload size" field of the OPT pseudo-RR to signal a
+ receive buffer size large enough to make truncation unlikely.
+
+
+
+
+
+
+
+
+
+
+
+Austein Expires July 15, 2006 [Page 9]
+
+Internet-Draft DNS NSID January 2006
+
+
+4. IANA Considerations
+
+ This mechanism requires allocation of one ENDS option code for the
+ NSID option (Section 2.3).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Expires July 15, 2006 [Page 10]
+
+Internet-Draft DNS NSID January 2006
+
+
+5. Security Considerations
+
+ This document describes a channel signaling mechanism, intended
+ primarily for debugging. Channel signaling mechanisms are outside
+ the scope of DNSSEC per se. Applications that require integrity
+ protection for the data being signaled will need to use a channel
+ security mechanism such as TSIG [RFC2845].
+
+ Section 3.1 discusses a number of different kinds of information that
+ a name server operator might choose to provide as the value of the
+ NSID option. Some of these kinds of information are security
+ sensitive in some environments. This specification deliberately
+ leaves the syntax and semantics of the NSID option content up to the
+ implementation and the name server operator.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Expires July 15, 2006 [Page 11]
+
+Internet-Draft DNS NSID January 2006
+
+
+6. Acknowledgements
+
+ Joe Abley, Harald Alvestrand, Mark Andrews, Roy Arends, Steve
+ Bellovin, Randy Bush, David Conrad, Johan Ihren, Daniel Karrenberg,
+ Peter Koch, Mike Patton, Mike StJohns, Paul Vixie, Sam Weiler, and
+ Suzanne Woolf. Apologies to anyone inadvertently omitted from the
+ above list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Expires July 15, 2006 [Page 12]
+
+Internet-Draft DNS NSID January 2006
+
+
+7. References
+
+7.1. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", RFC 2119, BCP 14, March 1997.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)",
+ RFC 2671, August 1999.
+
+ [RFC2845] Vixie, P., Gudmundsson, O., Eastlake 3rd, D., and B.
+ Wellington, "Secret Key Transaction Authentication for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+7.2. Informative References
+
+ [RFC2277] Alvestrand, H., "IETF Policy on Character Sets and
+ Languages", RFC 2277, BCP 18, January 1998.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Expires July 15, 2006 [Page 13]
+
+Internet-Draft DNS NSID January 2006
+
+
+Author's Address
+
+ Rob Austein
+ ISC
+ 950 Charter Street
+ Redwood City, CA 94063
+ USA
+
+ Email: sra@isc.org
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Expires July 15, 2006 [Page 14]
+
+Internet-Draft DNS NSID January 2006
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2006). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Austein Expires July 15, 2006 [Page 15]
+
diff --git a/doc/draft/draft-ietf-dnsext-rfc2536bis-dsa-07.txt b/doc/draft/draft-ietf-dnsext-rfc2536bis-dsa-07.txt
new file mode 100644
index 0000000..e169da8
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-rfc2536bis-dsa-07.txt
@@ -0,0 +1,464 @@
+
+INTERNET-DRAFT DSA Information in the DNS
+OBSOLETES: RFC 2536 Donald E. Eastlake 3rd
+ Motorola Laboratories
+Expires: September 2006 March 2006
+
+
+ DSA Keying and Signature Information in the DNS
+ --- ------ --- --------- ----------- -- --- ---
+ <draft-ietf-dnsext-rfc2536bis-dsa-07.txt>
+ Donald E. Eastlake 3rd
+
+
+Status of This Document
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Distribution of this document is unlimited. Comments should be sent
+ to the DNS extensions working group mailing list
+ <namedroppers@ops.ietf.org>.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+
+
+Abstract
+
+ The standard method of encoding US Government Digital Signature
+ Algorithm keying and signature information for use in the Domain Name
+ System is specified.
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 1]
+
+
+INTERNET-DRAFT DSA Information in the DNS
+
+
+Table of Contents
+
+ Status of This Document....................................1
+ Abstract...................................................1
+
+ Table of Contents..........................................2
+
+ 1. Introduction............................................3
+ 2. DSA Keying Information..................................3
+ 3. DSA Signature Information...............................4
+ 4. Performance Considerations..............................4
+ 5. Security Considerations.................................5
+ 6. IANA Considerations.....................................5
+ Copyright, Disclaimer, and Additional IPR Provisions.......5
+
+ Normative References.......................................7
+ Informative References.....................................7
+
+ Author's Address...........................................8
+ Expiration and File Name...................................8
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 2]
+
+
+INTERNET-DRAFT DSA Information in the DNS
+
+
+1. Introduction
+
+ The Domain Name System (DNS) is the global hierarchical replicated
+ distributed database system for Internet addressing, mail proxy, and
+ other information [RFC 1034, 1035]. The DNS has been extended to
+ include digital signatures and cryptographic keys as described in
+ [RFC 4033, 4034, 4035] and additional work is underway which would
+ require the storage of keying and signature information in the DNS.
+
+ This document describes how to encode US Government Digital Signature
+ Algorithm (DSA) keys and signatures in the DNS. Familiarity with the
+ US Digital Signature Algorithm is assumed [FIPS 186-2, Schneier].
+
+
+
+2. DSA Keying Information
+
+ When DSA public keys are stored in the DNS, the structure of the
+ relevant part of the RDATA part of the RR being used is the fields
+ listed below in the order given.
+
+ The period of key validity is not included in this data but is
+ indicated separately, for example by an RR such as RRSIG which signs
+ and authenticates the RR containing the keying information.
+
+ Field Size
+ ----- ----
+ T 1 octet
+ Q 20 octets
+ P 64 + T*8 octets
+ G 64 + T*8 octets
+ Y 64 + T*8 octets
+
+ As described in [FIPS 186-2] and [Schneier], T is a key size
+ parameter chosen such that 0 <= T <= 8. (The meaning if the T octet
+ is greater than 8 is reserved and the remainder of the data may have
+ a different format in that case.) Q is a prime number selected at
+ key generation time such that 2**159 < Q < 2**160. Thus Q is always
+ 20 octets long and, as with all other fields, is stored in "big-
+ endian" network order. P, G, and Y are calculated as directed by the
+ [FIPS 186-2] key generation algorithm [Schneier]. P is in the range
+ 2**(511+64T) < P < 2**(512+64T) and thus is 64 + 8*T octets long. G
+ and Y are quantities modulo P and so can be up to the same length as
+ P and are allocated fixed size fields with the same number of octets
+ as P.
+
+ During the key generation process, a random number X must be
+ generated such that 1 <= X <= Q-1. X is the private key and is used
+ in the final step of public key generation where Y is computed as
+
+
+
+D. Eastlake 3rd [Page 3]
+
+
+INTERNET-DRAFT DSA Information in the DNS
+
+
+ Y = G**X mod P
+
+
+
+3. DSA Signature Information
+
+ The portion of the RDATA area used for US Digital Signature Algorithm
+ signature information is shown below with fields in the order they
+ are listed and the contents of each multi-octet field in "big-endian"
+ network order.
+
+ Field Size
+ ----- ----
+ T 1 octet
+ R 20 octets
+ S 20 octets
+
+ First, the data signed must be determined. Then the following steps
+ are taken, as specified in [FIPS 186-2], where Q, P, G, and Y are as
+ specified in the public key [Schneier]:
+
+ hash = SHA-1 ( data )
+
+ Generate a random K such that 0 < K < Q.
+
+ R = ( G**K mod P ) mod Q
+
+ S = ( K**(-1) * (hash + X*R) ) mod Q
+
+ For information on the SHA-1 hash function see [FIPS 180-2] and [RFC
+ 3174].
+
+ Since Q is 160 bits long, R and S can not be larger than 20 octets,
+ which is the space allocated.
+
+ T is copied from the public key. It is not logically necessary in
+ the SIG but is present so that values of T > 8 can more conveniently
+ be used as an escape for extended versions of DSA or other algorithms
+ as later standardized.
+
+
+
+4. Performance Considerations
+
+ General signature generation speeds are roughly the same for RSA [RFC
+ 3110] and DSA. With sufficient pre-computation, signature generation
+ with DSA is faster than RSA. Key generation is also faster for DSA.
+ However, signature verification is an order of magnitude slower than
+ RSA when the RSA public exponent is chosen to be small, as is
+ recommended for some applications.
+
+
+D. Eastlake 3rd [Page 4]
+
+
+INTERNET-DRAFT DSA Information in the DNS
+
+
+ Current DNS implementations are optimized for small transfers,
+ typically less than 512 bytes including DNS overhead. Larger
+ transfers will perform correctly and extensions have been
+ standardized [RFC 2671] to make larger transfers more efficient, it
+ is still advisable at this time to make reasonable efforts to
+ minimize the size of RR sets containing keying and/or signature
+ inforamtion consistent with adequate security.
+
+
+
+5. Security Considerations
+
+ Keys retrieved from the DNS should not be trusted unless (1) they
+ have been securely obtained from a secure resolver or independently
+ verified by the user and (2) this secure resolver and secure
+ obtainment or independent verification conform to security policies
+ acceptable to the user. As with all cryptographic algorithms,
+ evaluating the necessary strength of the key is essential and
+ dependent on local policy.
+
+ The key size limitation of a maximum of 1024 bits ( T = 8 ) in the
+ current DSA standard may limit the security of DSA. For particular
+ applications, implementors are encouraged to consider the range of
+ available algorithms and key sizes.
+
+ DSA assumes the ability to frequently generate high quality random
+ numbers. See [random] for guidance. DSA is designed so that if
+ biased rather than random numbers are used, high bandwidth covert
+ channels are possible. See [Schneier] and more recent research. The
+ leakage of an entire DSA private key in only two DSA signatures has
+ been demonstrated. DSA provides security only if trusted
+ implementations, including trusted random number generation, are
+ used.
+
+
+
+6. IANA Considerations
+
+ Allocation of meaning to values of the T parameter that are not
+ defined herein (i.e., > 8 ) requires an IETF standards actions. It
+ is intended that values unallocated herein be used to cover future
+ extensions of the DSS standard.
+
+
+
+Copyright, Disclaimer, and Additional IPR Provisions
+
+ Copyright (C) The Internet Society (2006). This document is subject to
+ the rights, licenses and restrictions contained in BCP 78, and except
+ as set forth therein, the authors retain all their rights.
+
+
+D. Eastlake 3rd [Page 5]
+
+
+INTERNET-DRAFT DSA Information in the DNS
+
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 6]
+
+
+INTERNET-DRAFT DSA Information in the DNS
+
+
+Normative References
+
+ [FIPS 186-2] - U.S. Federal Information Processing Standard: Digital
+ Signature Standard, 27 January 2000.
+
+ [RFC 4034] - Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+
+
+Informative References
+
+ [RFC 1034] - "Domain names - concepts and facilities", P.
+ Mockapetris, 11/01/1987.
+
+ [RFC 1035] - "Domain names - implementation and specification", P.
+ Mockapetris, 11/01/1987.
+
+ [RFC 2671] - "Extension Mechanisms for DNS (EDNS0)", P. Vixie, August
+ 1999.
+
+ [RFC 3110] - "RSA/SHA-1 SIGs and RSA KEYs in the Domain Name System
+ (DNS)", D. Eastlake 3rd. May 2001.
+
+ [RFC 3174] - "US Secure Hash Algorithm 1 (SHA1)", D. Eastlake, P.
+ Jones, September 2001.
+
+ [RFC 4033] - Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements", RFC 4033, March
+ 2005.
+
+ [RFC 4035] - Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security Extensions", RFC
+ 4035, March 2005.
+
+ [RFC 4086] - Eastlake, D., 3rd, Schiller, J., and S. Crocker,
+ "Randomness Requirements for Security", BCP 106, RFC 4086, June 2005.
+
+ [Schneier] - "Applied Cryptography Second Edition: protocols,
+ algorithms, and source code in C" (second edition), Bruce Schneier,
+ 1996, John Wiley and Sons, ISBN 0-471-11709-9.
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 7]
+
+
+INTERNET-DRAFT DSA Information in the DNS
+
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ Motorola Labortories
+ 155 Beaver Street
+ Milford, MA 01757 USA
+
+ Telephone: +1-508-786-7554(w)
+ EMail: Donald.Eastlake@motorola.com
+
+
+
+Expiration and File Name
+
+ This draft expires in September 2006.
+
+ Its file name is draft-ietf-dnsext-rfc2536bis-dsa-07.txt.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 8]
+
diff --git a/doc/draft/draft-ietf-dnsext-rfc2539bis-dhk-07.txt b/doc/draft/draft-ietf-dnsext-rfc2539bis-dhk-07.txt
new file mode 100644
index 0000000..f6e8588
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-rfc2539bis-dhk-07.txt
@@ -0,0 +1,580 @@
+
+INTERNET-DRAFT Diffie-Hellman Information in the DNS
+OBSOLETES: RFC 2539 Donald E. Eastlake 3rd
+ Motorola Laboratories
+Expires: September 2006 March 2006
+
+
+
+
+ Storage of Diffie-Hellman Keying Information in the DNS
+ ------- -- -------------- ------ ----------- -- --- ---
+ <draft-ietf-dnsext-rfc2539bis-dhk-07.txt>
+
+
+
+Status of This Document
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Distribution of this document is unlimited. Comments should be sent
+ to the DNS extensions working group mailing list
+ <namedroppers@ops.ietf.org>.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+
+Abstract
+
+ The standard method for encoding Diffie-Hellman keys in the Domain
+ Name System is specified.
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 1]
+
+
+INTERNET-DRAFT Diffie-Hellman Information in the DNS
+
+
+Acknowledgements
+
+ Part of the format for Diffie-Hellman keys and the description
+ thereof was taken from a work in progress by Ashar Aziz, Tom Markson,
+ and Hemma Prafullchandra. In addition, the following persons
+ provided useful comments that were incorporated into the predecessor
+ of this document: Ran Atkinson, Thomas Narten.
+
+
+
+Table of Contents
+
+ Status of This Document....................................1
+ Abstract...................................................1
+
+ Acknowledgements...........................................2
+ Table of Contents..........................................2
+
+ 1. Introduction............................................3
+ 1.1 About This Document....................................3
+ 1.2 About Diffie-Hellman...................................3
+ 2. Encoding Diffie-Hellman Keying Information..............4
+ 3. Performance Considerations..............................5
+ 4. IANA Considerations.....................................5
+ 5. Security Considerations.................................5
+ Copyright, Disclaimer, and Additional IPR Provisions.......5
+
+ Normative References.......................................7
+ Informative Refences.......................................7
+
+ Author's Address...........................................8
+ Expiration and File Name...................................8
+
+ Appendix A: Well known prime/generator pairs...............9
+ A.1. Well-Known Group 1: A 768 bit prime..................9
+ A.2. Well-Known Group 2: A 1024 bit prime.................9
+ A.3. Well-Known Group 3: A 1536 bit prime................10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 2]
+
+
+INTERNET-DRAFT Diffie-Hellman Information in the DNS
+
+
+1. Introduction
+
+ The Domain Name System (DNS) is the global hierarchical replicated
+ distributed database system for Internet addressing, mail proxy, and
+ similar information [RFC 1034, 1035]. The DNS has been extended to
+ include digital signatures and cryptographic keys as described in
+ [RFC 4033, 4034, 4035] and additonal work is underway which would use
+ the storage of keying information in the DNS.
+
+
+
+1.1 About This Document
+
+ This document describes how to store Diffie-Hellman keys in the DNS.
+ Familiarity with the Diffie-Hellman key exchange algorithm is assumed
+ [Schneier, RFC 2631].
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119.
+
+
+
+1.2 About Diffie-Hellman
+
+ Diffie-Hellman requires two parties to interact to derive keying
+ information which can then be used for authentication. Thus Diffie-
+ Hellman is inherently a key agreement algorithm. As a result, no
+ format is defined for Diffie-Hellman "signature information". For
+ example, assume that two parties have local secrets "i" and "j".
+ Assume they each respectively calculate X and Y as follows:
+
+ X = g**i ( mod p )
+
+ Y = g**j ( mod p )
+
+ They exchange these quantities and then each calculates a Z as
+ follows:
+
+ Zi = Y**i ( mod p )
+
+ Zj = X**j ( mod p )
+
+ Zi and Zj will both be equal to g**(i*j)(mod p) and will be a shared
+ secret between the two parties that an adversary who does not know i
+ or j will not be able to learn from the exchanged messages (unless
+ the adversary can derive i or j by performing a discrete logarithm
+ mod p which is hard for strong p and g).
+
+ The private key for each party is their secret i (or j). The public
+
+
+D. Eastlake 3rd [Page 3]
+
+
+INTERNET-DRAFT Diffie-Hellman Information in the DNS
+
+
+ key is the pair p and g, which is the same for both parties, and
+ their individual X (or Y).
+
+ For further information about Diffie-Hellman and precautions to take
+ in deciding on a p and g, see [RFC 2631].
+
+
+
+2. Encoding Diffie-Hellman Keying Information
+
+ When Diffie-Hellman keys appear within the RDATA portion of a RR,
+ they are encoded as shown below.
+
+ The period of key validity is not included in this data but is
+ indicated separately, for example by an RR such as RRSIG which signs
+ and authenticates the RR containing the keying information.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | KEY flags | protocol | algorithm=2 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | prime length (or flag) | prime (p) (or special) /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / prime (p) (variable length) | generator length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | generator (g) (variable length) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | public value length | public value (variable length)/
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / public value (g^i mod p) (variable length) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Prime length is the length of the Diffie-Hellman prime (p) in bytes
+ if it is 16 or greater. Prime contains the binary representation of
+ the Diffie-Hellman prime with most significant byte first (i.e., in
+ network order). If "prime length" field is 1 or 2, then the "prime"
+ field is actually an unsigned index into a table of 65,536
+ prime/generator pairs and the generator length SHOULD be zero. See
+ Appedix A for defined table entries and Section 4 for information on
+ allocating additional table entries. The meaning of a zero or 3
+ through 15 value for "prime length" is reserved.
+
+ Generator length is the length of the generator (g) in bytes.
+ Generator is the binary representation of generator with most
+ significant byte first. PublicValueLen is the Length of the Public
+ Value (g**i (mod p)) in bytes. PublicValue is the binary
+ representation of the DH public value with most significant byte
+ first.
+
+
+
+D. Eastlake 3rd [Page 4]
+
+
+INTERNET-DRAFT Diffie-Hellman Information in the DNS
+
+
+3. Performance Considerations
+
+ Current DNS implementations are optimized for small transfers,
+ typically less than 512 bytes including DNS overhead. Larger
+ transfers will perform correctly and extensions have been
+ standardized [RFC 2671] to make larger transfers more efficient. But
+ it is still advisable at this time to make reasonable efforts to
+ minimize the size of RR sets containing keying information consistent
+ with adequate security.
+
+
+
+4. IANA Considerations
+
+ Assignment of meaning to Prime Lengths of 0 and 3 through 15 requires
+ an IETF consensus as defined in [RFC 2434].
+
+ Well known prime/generator pairs number 0x0000 through 0x07FF can
+ only be assigned by an IETF standards action. [RFC 2539], the
+ Proposed Standard predecessor of this document, assigned 0x0001
+ through 0x0002. This document additionally assigns 0x0003. Pairs
+ number 0s0800 through 0xBFFF can be assigned based on RFC
+ documentation. Pairs number 0xC000 through 0xFFFF are available for
+ private use and are not centrally coordinated. Use of such private
+ pairs outside of a closed environment may result in conflicts and/or
+ security failures.
+
+
+
+5. Security Considerations
+
+ Keying information retrieved from the DNS should not be trusted
+ unless (1) it has been securely obtained from a secure resolver or
+ independently verified by the user and (2) this secure resolver and
+ secure obtainment or independent verification conform to security
+ policies acceptable to the user. As with all cryptographic
+ algorithms, evaluating the necessary strength of the key is important
+ and dependent on security policy.
+
+ In addition, the usual Diffie-Hellman key strength considerations
+ apply. (p-1)/2 SHOULD also be prime, g SHOULD be primitive mod p, p
+ SHOULD be "large", etc. See [RFC 2631, Schneier].
+
+
+
+Copyright, Disclaimer, and Additional IPR Provisions
+
+ Copyright (C) The Internet Society (2006). This document is subject to
+ the rights, licenses and restrictions contained in BCP 78, and except
+ as set forth therein, the authors retain all their rights.
+
+
+D. Eastlake 3rd [Page 5]
+
+
+INTERNET-DRAFT Diffie-Hellman Information in the DNS
+
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 6]
+
+
+INTERNET-DRAFT Diffie-Hellman Information in the DNS
+
+
+Normative References
+
+ [RFC 2119] - Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC 2434] - "Guidelines for Writing an IANA Considerations Section
+ in RFCs", T. Narten, H. Alvestrand, October 1998.
+
+ [RFC 2631] - "Diffie-Hellman Key Agreement Method", E. Rescorla, June
+ 1999.
+
+ [RFC 4034] - Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+
+
+Informative Refences
+
+ [RFC 1034] - "Domain names - concepts and facilities", P.
+ Mockapetris, November 1987.
+
+ [RFC 1035] - "Domain names - implementation and specification", P.
+ Mockapetris, November 1987.
+
+ [RFC 2539] - "Storage of Diffie-Hellman Keys in the Domain Name
+ System (DNS)", D. Eastlake, March 1999, obsoleted by this RFC.
+
+ [RFC 2671] - "Extension Mechanisms for DNS (EDNS0)", P. Vixie, August
+ 1999.
+
+ [RFC 4033] - Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements", RFC 4033, March
+ 2005.
+
+ [RFC 4035] - Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security Extensions", RFC
+ 4035, March 2005.
+
+ [Schneier] - Bruce Schneier, "Applied Cryptography: Protocols,
+ Algorithms, and Source Code in C" (Second Edition), 1996, John Wiley
+ and Sons.
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 7]
+
+
+INTERNET-DRAFT Diffie-Hellman Information in the DNS
+
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ Motorola Laboratories
+ 155 Beaver Street
+ Milford, MA 01757 USA
+
+ Telephone: +1-508-786-7554
+ EMail: Donald.Eastlake@motorola.com
+
+
+
+Expiration and File Name
+
+ This draft expires in September 2006.
+
+ Its file name is draft-ietf-dnsext-rfc2539bis-dhk-07.txt.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 8]
+
+
+INTERNET-DRAFT Diffie-Hellman Information in the DNS
+
+
+Appendix A: Well known prime/generator pairs
+
+ These numbers are copied from the IPSEC effort where the derivation
+ of these values is more fully explained and additional information is
+ available. Richard Schroeppel performed all the mathematical and
+ computational work for this appendix.
+
+
+
+A.1. Well-Known Group 1: A 768 bit prime
+
+ The prime is 2^768 - 2^704 - 1 + 2^64 * { [2^638 pi] + 149686 }. Its
+ decimal value is
+ 155251809230070893513091813125848175563133404943451431320235
+ 119490296623994910210725866945387659164244291000768028886422
+ 915080371891804634263272761303128298374438082089019628850917
+ 0691316593175367469551763119843371637221007210577919
+
+ Prime modulus: Length (32 bit words): 24, Data (hex):
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+ 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+ EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+ E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF
+
+ Generator: Length (32 bit words): 1, Data (hex): 2
+
+
+
+A.2. Well-Known Group 2: A 1024 bit prime
+
+ The prime is 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
+ Its decimal value is
+ 179769313486231590770839156793787453197860296048756011706444
+ 423684197180216158519368947833795864925541502180565485980503
+ 646440548199239100050792877003355816639229553136239076508735
+ 759914822574862575007425302077447712589550957937778424442426
+ 617334727629299387668709205606050270810842907692932019128194
+ 467627007
+
+ Prime modulus: Length (32 bit words): 32, Data (hex):
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+ 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+ EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+ E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
+ EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381
+ FFFFFFFF FFFFFFFF
+
+ Generator: Length (32 bit words): 1, Data (hex): 2
+
+
+
+
+D. Eastlake 3rd [Page 9]
+
+
+INTERNET-DRAFT Diffie-Hellman Information in the DNS
+
+
+A.3. Well-Known Group 3: A 1536 bit prime
+
+ The prime is 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }.
+ Its decimal value is
+ 241031242692103258855207602219756607485695054850245994265411
+ 694195810883168261222889009385826134161467322714147790401219
+ 650364895705058263194273070680500922306273474534107340669624
+ 601458936165977404102716924945320037872943417032584377865919
+ 814376319377685986952408894019557734611984354530154704374720
+ 774996976375008430892633929555996888245787241299381012913029
+ 459299994792636526405928464720973038494721168143446471443848
+ 8520940127459844288859336526896320919633919
+
+ Prime modulus Length (32 bit words): 48, Data (hex):
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+ 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+ EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+ E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
+ EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
+ C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
+ 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
+ 670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF
+
+ Generator: Length (32 bit words): 1, Data (hex): 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 10]
+
diff --git a/doc/draft/draft-ietf-dnsext-rfc2671bis-edns0-01.txt b/doc/draft/draft-ietf-dnsext-rfc2671bis-edns0-01.txt
new file mode 100644
index 0000000..8f84fd4
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-rfc2671bis-edns0-01.txt
@@ -0,0 +1,480 @@
+
+
+
+
+
+
+DNSEXT Working Group Paul Vixie, ISC
+INTERNET-DRAFT
+<draft-ietf-dnsext-rfc2671bis-edns0-01.txt> March 17, 2008
+
+Intended Status: Standards Track
+Obsoletes: 2671 (if approved)
+
+
+ Revised extension mechanisms for DNS (EDNS0)
+
+
+Status of this Memo
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+Copyright Notice
+
+ Copyright (C) The IETF Trust (2007).
+
+
+ Abstract
+
+ The Domain Name System's wire protocol includes a number of fixed
+ fields whose range has been or soon will be exhausted and does not
+ allow clients to advertise their capabilities to servers. This
+ document describes backward compatible mechanisms for allowing the
+ protocol to grow.
+
+
+
+Expires September 2008 [Page 1]
+
+INTERNET-DRAFT EDNS0 March 2008
+
+
+1 - Introduction
+
+1.1. DNS (see [RFC1035]) specifies a Message Format and within such
+messages there are standard formats for encoding options, errors, and
+name compression. The maximum allowable size of a DNS Message is fixed.
+Many of DNS's protocol limits are too small for uses which are or which
+are desired to become common. There is no way for implementations to
+advertise their capabilities.
+
+1.2. Unextended agents will not know how to interpret the protocol
+extensions detailed here. In practice, these clients will be upgraded
+when they have need of a new feature, and only new features will make
+use of the extensions. Extended agents must be prepared for behaviour
+of unextended clients in the face of new protocol elements, and fall
+back gracefully to unextended DNS. RFC 2671 originally has proposed
+extensions to the basic DNS protocol to overcome these deficiencies.
+This memo refines that specification and obsoletes RFC 2671.
+
+1.3. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+document are to be interpreted as described in RFC 2119 [RFC2119].
+
+2 - Affected Protocol Elements
+
+2.1. The DNS Message Header's (see [RFC1035 4.1.1]) second full 16-bit
+word is divided into a 4-bit OPCODE, a 4-bit RCODE, and a number of
+1-bit flags. The original reserved Z bits have been allocated to
+various purposes, and most of the RCODE values are now in use. More
+flags and more possible RCODEs are needed. The OPT pseudo-RR specified
+in Section 4 contains subfields that carry a bit field extension of the
+RCODE field and additional flag bits, respectively; for details see
+Section 4.6 below.
+
+2.2. The first two bits of a wire format domain label are used to denote
+the type of the label. [RFC1035 4.1.4] allocates two of the four
+possible types and reserves the other two. Proposals for use of the
+remaining types far outnumber those available. More label types were
+needed, and an extension mechanism was proposed in RFC 2671 [RFC2671
+Section 3]. Section 3 of this document reserves DNS labels with a first
+octet in the range of 64-127 decimal (label type 01) for future
+standardization of Extended DNS Labels.
+
+
+
+
+
+
+
+Expires September 2008 [Page 2]
+
+INTERNET-DRAFT EDNS0 March 2008
+
+
+2.3. DNS Messages are limited to 512 octets in size when sent over UDP.
+While the minimum maximum reassembly buffer size still allows a limit of
+512 octets of UDP payload, most of the hosts now connected to the
+Internet are able to reassemble larger datagrams. Some mechanism must
+be created to allow requestors to advertise larger buffer sizes to
+responders. To this end, the OPT pseudo-RR specified in Section 4
+contains a maximum payload size field; for details see Section 4.5
+below.
+
+3 - Extended Label Types
+
+The first octet in the on-the-wire representation of a DNS label
+specifies the label type; the basic DNS specification [RFC1035]
+dedicates the two most significant bits of that octet for this purpose.
+
+This document reserves DNS label type 0b01 for use as an indication for
+Extended Label Types. A specific extended label type is selected by the
+6 least significant bits of the first octet. Thus, Extended Label Types
+are indicated by the values 64-127 (0b01xxxxxx) in the first octet of
+the label.
+
+Allocations from this range are to be made for IETF documents fully
+describing the syntax and semantics as well as the applicability of the
+particular Extended Label Type.
+
+This document does not describe any specific Extended Label Type.
+
+4 - OPT pseudo-RR
+
+4.1. One OPT pseudo-RR (RR type 41) MAY be added to the additional data
+section of a request, and to responses to such requests. An OPT is
+called a pseudo-RR because it pertains to a particular transport level
+message and not to any actual DNS data. OPT RRs MUST NOT be cached,
+forwarded, or stored in or loaded from master files. The quantity of
+OPT pseudo-RRs per message MUST be either zero or one, but not greater.
+
+4.2. An OPT RR has a fixed part and a variable set of options expressed
+as {attribute, value} pairs. The fixed part holds some DNS meta data
+and also a small collection of new protocol elements which we expect to
+be so popular that it would be a waste of wire space to encode them as
+{attribute, value} pairs.
+
+
+
+
+
+
+
+Expires September 2008 [Page 3]
+
+INTERNET-DRAFT EDNS0 March 2008
+
+
+4.3. The fixed part of an OPT RR is structured as follows:
+
+Field Name Field Type Description
+------------------------------------------------------
+NAME domain name empty (root domain)
+TYPE u_int16_t OPT (41)
+CLASS u_int16_t sender's UDP payload size
+TTL u_int32_t extended RCODE and flags
+RDLEN u_int16_t describes RDATA
+RDATA octet stream {attribute,value} pairs
+
+
+4.4. The variable part of an OPT RR is encoded in its RDATA and is
+structured as zero or more of the following:
+
+ : +0 (MSB) : +1 (LSB) :
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 0: | OPTION-CODE |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 2: | OPTION-LENGTH |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 4: | |
+ / OPTION-DATA /
+ / /
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+
+
+OPTION-CODE (Assigned by IANA.)
+
+OPTION-LENGTH Size (in octets) of OPTION-DATA.
+
+OPTION-DATA Varies per OPTION-CODE.
+
+4.4.1. Order of appearance of option tuples is never relevant. Any
+option whose meaning is affected by other options is so affected no
+matter which one comes first in the OPT RDATA.
+
+4.4.2. Any OPTION-CODE values not understood by a responder or requestor
+MUST be ignored. So, specifications of such options might wish to
+include some kind of signalled acknowledgement. For example, an option
+specification might say that if a responder sees option XYZ, it SHOULD
+include option XYZ in its response.
+
+
+
+
+
+
+Expires September 2008 [Page 4]
+
+INTERNET-DRAFT EDNS0 March 2008
+
+
+4.5. The sender's UDP payload size (which OPT stores in the RR CLASS
+field) is the number of octets of the largest UDP payload that can be
+reassembled and delivered in the sender's network stack. Note that path
+MTU, with or without fragmentation, may be smaller than this. Values
+lower than 512 are undefined, and may be treated as format errors, or
+may be treated as equal to 512, at the implementor's discretion.
+
+4.5.1. Note that a 512-octet UDP payload requires a 576-octet IP
+reassembly buffer. Choosing 1280 on an Ethernet connected requestor
+would be reasonable. The consequence of choosing too large a value may
+be an ICMP message from an intermediate gateway, or even a silent drop
+of the response message.
+
+4.5.2. Both requestors and responders are advised to take account of the
+path's discovered MTU (if already known) when considering message sizes.
+
+4.5.3. The requestor's maximum payload size can change over time, and
+therefore MUST NOT be cached for use beyond the transaction in which it
+is advertised.
+
+4.5.4. The responder's maximum payload size can change over time, but
+can be reasonably expected to remain constant between two sequential
+transactions; for example, a meaningless QUERY to discover a responder's
+maximum UDP payload size, followed immediately by an UPDATE which takes
+advantage of this size. (This is considered preferrable to the outright
+use of TCP for oversized requests, if there is any reason to suspect
+that the responder implements EDNS, and if a request will not fit in the
+default 512 payload size limit.)
+
+4.5.5. Due to transaction overhead, it is unwise to advertise an
+architectural limit as a maximum UDP payload size. Just because your
+stack can reassemble 64KB datagrams, don't assume that you want to spend
+more than about 4KB of state memory per ongoing transaction.
+
+4.6. The extended RCODE and flags (which OPT stores in the RR TTL field)
+are structured as follows:
+
+ : +0 (MSB) : +1 (LSB) :
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 0: | EXTENDED-RCODE | VERSION |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 2: | DO| Z |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+
+
+
+
+
+Expires September 2008 [Page 5]
+
+INTERNET-DRAFT EDNS0 March 2008
+
+
+EXTENDED-RCODE Forms upper 8 bits of extended 12-bit RCODE. Note that
+ EXTENDED-RCODE value zero (0) indicates that an
+ unextended RCODE is in use (values zero (0) through
+ fifteen (15)).
+
+VERSION Indicates the implementation level of whoever sets it.
+ Full conformance with this specification is indicated by
+ version zero (0). Requestors are encouraged to set this
+ to the lowest implemented level capable of expressing a
+ transaction, to minimize the responder and network load
+ of discovering the greatest common implementation level
+ between requestor and responder. A requestor's version
+ numbering strategy should ideally be a run time
+ configuration option.
+
+ If a responder does not implement the VERSION level of
+ the request, then it answers with RCODE=BADVERS. All
+ responses MUST be limited in format to the VERSION level
+ of the request, but the VERSION of each response MUST be
+ the highest implementation level of the responder. In
+ this way a requestor will learn the implementation level
+ of a responder as a side effect of every response,
+ including error responses, including RCODE=BADVERS.
+
+DO DNSSEC OK bit [RFC3225].
+
+Z Set to zero by senders and ignored by receivers, unless
+ modified in a subsequent specification [IANAFLAGS].
+
+5 - Transport Considerations
+
+5.1. The presence of an OPT pseudo-RR in a request is an indication that
+the requestor fully implements the given version of EDNS, and can
+correctly understand any response that conforms to that feature's
+specification.
+
+5.2. Lack of use of these features in a request is an indication that
+the requestor does not implement any part of this specification and that
+the responder SHOULD NOT use any protocol extension described here in
+its response.
+
+5.3. Responders who do not understand these protocol extensions are
+expected to send a response with RCODE NOTIMPL, FORMERR, or SERVFAIL, or
+to appear to "time out" due to inappropriate action by a "middle box"
+such as a NAT, or to ignore extensions and respond only to unextended
+
+
+
+Expires September 2008 [Page 6]
+
+INTERNET-DRAFT EDNS0 March 2008
+
+
+protocol elements. Therefore use of extensions SHOULD be "probed" such
+that a responder who isn't known to support them be allowed a retry with
+no extensions if it responds with such an RCODE, or does not respond.
+If a responder's capability level is cached by a requestor, a new probe
+SHOULD be sent periodically to test for changes to responder capability.
+
+5.4. If EDNS is used in a request, and the response arrives with TC set
+and with no EDNS OPT RR, a requestor should assume that truncation
+prevented the OPT RR from being appended by the responder, and further,
+that EDNS is not used in the response. Correspondingly, an EDNS
+responder who cannot fit all necessary elements (including an OPT RR)
+into a response, should respond with a normal (unextended) DNS response,
+possibly setting TC if the response will not fit in the unextended
+response message's 512-octet size.
+
+6 - Security Considerations
+
+Requestor-side specification of the maximum buffer size may open a new
+DNS denial of service attack if responders can be made to send messages
+which are too large for intermediate gateways to forward, thus leading
+to potential ICMP storms between gateways and responders.
+
+7 - IANA Considerations
+
+IANA has allocated RR type code 41 for OPT.
+
+This document controls the following IANA sub-registries in registry
+"DOMAIN NAME SYSTEM PARAMETERS":
+
+ "EDNS Extended Label Type"
+ "EDNS Option Codes"
+ "EDNS Version Numbers"
+ "Domain System Response Code"
+
+IANA is advised to re-parent these subregistries to this document.
+
+This document assigns label type 0b01xxxxxx as "EDNS Extended Label
+Type." We request that IANA record this assignment.
+
+This document assigns option code 65535 to "Reserved for future
+expansion."
+
+This document assigns EDNS Extended RCODE "16" to "BADVERS".
+
+
+
+
+
+Expires September 2008 [Page 7]
+
+INTERNET-DRAFT EDNS0 March 2008
+
+
+IESG approval is required to create new entries in the EDNS Extended
+Label Type or EDNS Version Number registries, while any published RFC
+(including Informational, Experimental, or BCP) is grounds for
+allocation of an EDNS Option Code.
+
+8 - Acknowledgements
+
+Paul Mockapetris, Mark Andrews, Robert Elz, Don Lewis, Bob Halley,
+Donald Eastlake, Rob Austein, Matt Crawford, Randy Bush, Thomas Narten,
+Alfred Hoenes and Markku Savela were each instrumental in creating and
+refining this specification.
+
+9 - References
+
+[RFC1035] P. Mockapetris, "Domain Names - Implementation and
+ Specification," RFC 1035, USC/Information Sciences
+ Institute, November 1987.
+
+[RFC2119] S. Bradner, "Key words for use in RFCs to Indicate
+ Requirement Levels," RFC 2119, Harvard University, March
+ 1997.
+
+[RFC2671] P. Vixie, "Extension mechanisms for DNS (EDNS0)," RFC 2671,
+ Internet Software Consortium, August 1999.
+
+[RFC3225] D. Conrad, "Indicating Resolver Support of DNSSEC," RFC
+ 3225, Nominum Inc., December 2001.
+
+[IANAFLAGS] IANA, "DNS Header Flags and EDNS Header Flags," web site
+ http://www.iana.org/assignments/dns-header-flags, as of
+ June 2005 or later.
+
+10 - Author's Address
+
+Paul Vixie
+ Internet Systems Consortium
+ 950 Charter Street
+ Redwood City, CA 94063
+ +1 650 423 1301
+ EMail: vixie@isc.org
+
+
+
+
+
+
+
+
+Expires September 2008 [Page 8]
+
+INTERNET-DRAFT EDNS0 March 2008
+
+
+Full Copyright Statement
+
+Copyright (C) IETF Trust (2007).
+
+This document is subject to the rights, licenses and restrictions
+contained in BCP 78, and except as set forth therein, the authors retain
+all their rights.
+
+This document and the information contained herein are provided on an
+"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR
+IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND THE
+INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+The IETF takes no position regarding the validity or scope of any
+Intellectual Property Rights or other rights that might be claimed to
+pertain to the implementation or use of the technology described in this
+document or the extent to which any license under such rights might or
+might not be available; nor does it represent that it has made any
+independent effort to identify any such rights. Information on the
+procedures with respect to rights in RFC documents can be found in BCP
+78 and BCP 79.
+
+Copies of IPR disclosures made to the IETF Secretariat and any
+assurances of licenses to be made available, or the result of an attempt
+made to obtain a general license or permission for the use of such
+proprietary rights by implementers or users of this specification can be
+obtained from the IETF on-line IPR repository at
+http://www.ietf.org/ipr.
+
+The IETF invites any interested party to bring to its attention any
+copyrights, patents or patent applications, or other proprietary rights
+that may cover technology that may be required to implement this
+standard. Please address the information to the IETF at
+ietf-ipr@ietf.org.
+
+Acknowledgement
+
+Funding for the RFC Editor function is provided by the IETF
+Administrative Support Activity (IASA).
+
+
+
+
+Expires September 2008 [Page 9]
+ \ No newline at end of file
diff --git a/doc/draft/draft-ietf-dnsext-rfc2672bis-dname-13.txt b/doc/draft/draft-ietf-dnsext-rfc2672bis-dname-13.txt
new file mode 100644
index 0000000..13195bb
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-rfc2672bis-dname-13.txt
@@ -0,0 +1,952 @@
+
+
+
+DNS Extensions Working Group S. Rose
+Internet-Draft NIST
+Obsoletes: 2672 (if approved) W. Wijngaards
+Updates: 3363,4294 NLnet Labs
+(if approved) May 2, 2008
+Intended status: Standards Track
+Expires: November 3, 2008
+
+
+ Update to DNAME Redirection in the DNS
+ draft-ietf-dnsext-rfc2672bis-dname-13
+
+Status of This Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on November 3, 2008.
+
+Copyright Notice
+
+ Copyright (C) The IETF Trust (2008).
+
+Abstract
+
+ The DNAME record provides redirection for a sub-tree of the domain
+ name tree in the DNS system. That is, all names that end with a
+ particular suffix are redirected to another part of the DNS. This is
+ an update of the original specification in RFC 2672, also aligning
+ RFC 3363 and RFC 4294 with this revision.
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 1]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+Requirements Language
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [RFC2119].
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+
+ 2. The DNAME Resource Record . . . . . . . . . . . . . . . . . . 3
+ 2.1. Format . . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2.2. The DNAME Substitution . . . . . . . . . . . . . . . . . . 4
+ 2.3. DNAME Apex not Redirected itself . . . . . . . . . . . . . 5
+ 2.4. Names Next to and Below a DNAME Record . . . . . . . . . . 6
+ 2.5. Compression of the DNAME record. . . . . . . . . . . . . . 6
+
+ 3. Processing . . . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 3.1. CNAME synthesis and UD bit . . . . . . . . . . . . . . . . 7
+ 3.2. Server algorithm . . . . . . . . . . . . . . . . . . . . . 8
+ 3.3. Wildcards . . . . . . . . . . . . . . . . . . . . . . . . 9
+ 3.4. Acceptance and Intermediate Storage . . . . . . . . . . . 10
+
+ 4. DNAME Discussions in Other Documents . . . . . . . . . . . . . 10
+
+ 5. Other Issues with DNAME . . . . . . . . . . . . . . . . . . . 12
+ 5.1. Canonical hostnames cannot be below DNAME owners . . . . . 12
+ 5.2. Dynamic Update and DNAME . . . . . . . . . . . . . . . . . 12
+ 5.3. DNSSEC and DNAME . . . . . . . . . . . . . . . . . . . . . 12
+ 5.3.1. DNAME bit in NSEC type map . . . . . . . . . . . . . . 12
+ 5.3.2. Validators Must Understand DNAME . . . . . . . . . . . 12
+ 5.3.2.1. DNAME in Bitmap Causes Invalid Name Error . . . . 13
+ 5.3.2.2. Valid Name Error Response Involving DNAME in
+ Bitmap . . . . . . . . . . . . . . . . . . . . . . 13
+ 5.3.2.3. Response With Synthesized CNAME . . . . . . . . . 13
+
+ 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 14
+
+ 7. Security Considerations . . . . . . . . . . . . . . . . . . . 14
+
+ 8. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 14
+
+ 9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 14
+ 9.1. Normative References . . . . . . . . . . . . . . . . . . . 14
+ 9.2. Informative References . . . . . . . . . . . . . . . . . . 15
+
+
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 2]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+1. Introduction
+
+ DNAME is a DNS Resource Record type originally defined in RFC 2672
+ [RFC2672]. DNAME provides redirection from a part of the DNS name
+ tree to another part of the DNS name tree.
+
+ The DNAME RR and the CNAME RR [RFC1034] cause a lookup to
+ (potentially) return data corresponding to a domain name different
+ from the queried domain name. The difference between the two
+ resource records is that the CNAME RR directs the lookup of data at
+ its owner to another single name, a DNAME RR directs lookups for data
+ at descendents of its owner's name to corresponding names under a
+ different (single) node of the tree.
+
+ Take for example, looking through a zone (see RFC 1034 [RFC1034],
+ section 4.3.2, step 3) for the domain name "foo.example.com" and a
+ DNAME resource record is found at "example.com" indicating that all
+ queries under "example.com" be directed to "example.net". The lookup
+ process will return to step 1 with the new query name of
+ "foo.example.net". Had the query name been "www.foo.example.com" the
+ new query name would be "www.foo.example.net".
+
+ This document is an update of the original specification of DNAME in
+ RFC 2672 [RFC2672]. DNAME was conceived to help with the problem of
+ maintaining address-to-name mappings in a context of network
+ renumbering. With a careful set-up, a renumbering event in the
+ network causes no change to the authoritative server that has the
+ address-to-name mappings. Examples in practice are classless reverse
+ address space delegations.
+
+ Another usage of DNAME lies in redirection of name spaces. For
+ example, a zone administrator may want sub-trees of the DNS to
+ contain the same information. Examples include punycode alternates
+ for domain spaces. DNAME is also used for the redirection of ENUM
+ domains to another maintaining party.
+
+ This update to DNAME does not change the wire format or the handling
+ of DNAME Resource Records by existing software. A new UD (Understand
+ DNAME) bit in the EDNS flags field can be used to signal that CNAME
+ synthesis is not needed. Discussion is added on problems that may be
+ encountered when using DNAME.
+
+2. The DNAME Resource Record
+
+2.1. Format
+
+ The DNAME RR has mnemonic DNAME and type code 39 (decimal). It is
+ not class-sensitive.
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 3]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+ Its RDATA is comprised of a single field, <target>, which contains a
+ fully qualified domain name that must be sent in uncompressed form
+ [RFC1035], [RFC3597]. The <target> field MUST be present. The
+ presentation format of <target> is that of a domain name [RFC1035].
+
+ <owner> <ttl> <class> DNAME <target>
+
+ The effect of the DNAME RR is the substitution of the record's
+ <target> for its owner name, as a suffix of a domain name. This
+ substitution has to be applied for every DNAME RR found in the
+ resolution process, which allows fairly lengthy valid chains of DNAME
+ RRs.
+
+ Details of the substitution process, methods to avoid conflicting
+ resource records, and rules for specific corner cases are given in
+ the following subsections.
+
+2.2. The DNAME Substitution
+
+ When following RFC 1034 [RFC1034], section 4.3.2's algorithm's third
+ step, "start matching down, label by label, in the zone" and a node
+ is found to own a DNAME resource record a DNAME substitution occurs.
+ The name being sought may be the original query name or a name that
+ is the result of a CNAME resource record being followed or a
+ previously encountered DNAME. As is the case of finding a CNAME
+ resource record or NS resource record set, the processing of a DNAME
+ will happen prior to finding the desired domain name.
+
+ A DNAME substitution is performed by replacing the suffix labels of
+ the name being sought matching the owner name of the DNAME resource
+ record with the string of labels in the RDATA field. The matching
+ labels end with the root label in all cases. Only whole labels are
+ replaced. See the table of examples for common cases and corner
+ cases.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 4]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+ In the table below, the QNAME refers to the query name. The owner is
+ the DNAME owner domain name, and the target refers to the target of
+ the DNAME record. The result is the resulting name after performing
+ the DNAME substitution on the query name. "no match" means that the
+ query did not match the DNAME and thus no substitution is performed
+ and a possible error message is returned (if no other result is
+ possible). In the examples below, 'cyc' and 'shortloop' contain
+ loops.
+
+ QNAME owner DNAME target result
+ ---------------- -------------- -------------- -----------------
+ com. example.com. example.net. <no match>
+ example.com. example.com. example.net. <no match>
+ a.example.com. example.com. example.net. a.example.net.
+ a.b.example.com. example.com. example.net. a.b.example.net.
+ ab.example.com. b.example.com. example.net. <no match>
+ foo.example.com. example.com. example.net. foo.example.net.
+ a.x.example.com. x.example.com. example.net. a.example.net.
+ a.example.com. example.com. y.example.net. a.y.example.net.
+ cyc.example.com. example.com. example.com. cyc.example.com.
+ cyc.example.com. example.com. c.example.com. cyc.c.example.com.
+ shortloop.x.x. x. . shortloop.x.
+ shortloop.x. x. . shortloop.
+
+ Table 1. DNAME Substitution Examples.
+
+ It is possible for DNAMEs to form loops, just as CNAMEs can form
+ loops. DNAMEs and CNAMEs can chain together to form loops. A single
+ corner case DNAME can form a loop. Resolvers and servers should be
+ cautious in devoting resources to a query, but be aware that fairly
+ long chains of DNAMEs may be valid. Zone content administrators
+ should take care to insure that there are no loops that could occur
+ when using DNAME or DNAME/CNAME redirection.
+
+ The domain name can get too long during substitution. For example,
+ suppose the target name of the DNAME RR is 250 octets in length
+ (multiple labels), if an incoming QNAME that has a first label over 5
+ octets in length, the result of the result would be a name over 255
+ octets. If this occurs the server returns an RCODE of YXDOMAIN
+ [RFC2136]. The DNAME record and its signature (if the zone is
+ signed) are included in the answer as proof for the YXDOMAIN (value
+ 6) RCODE.
+
+2.3. DNAME Apex not Redirected itself
+
+ Unlike a CNAME RR, a DNAME RR redirects DNS names subordinate to its
+ owner name; the owner name of a DNAME is not redirected itself. The
+ domain name that owns a DNAME record is allowed to have other
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 5]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+ resource record types at that domain name, except DNAMEs or CNAMEs.
+ This means that DNAME RRs are not allowed at the parent side of a
+ delegation point but are allowed at a zone apex.
+
+ The reason for this decision was that one can have a DNAME at the
+ zone apex. There still is a need to have the customary SOA and NS
+ resource records at the zone apex. This means that DNAME does not
+ mirror a zone completely, as it does not mirror the zone apex.
+
+ These rules also allow DNAME records to be queried through RFC 1034
+ [RFC1034] compliant, DNAME-unaware caches.
+
+2.4. Names Next to and Below a DNAME Record
+
+ Resource records MUST NOT exist at any domain name subordinate to the
+ owner of a DNAME RR. To get the contents for names subordinate to
+ that owner, the DNAME redirection must be invoked and the resulting
+ target queried. A server MAY refuse to load a zone that has data at
+ a domain name subordinate to a domain name owning a DNAME RR. If the
+ server does load the zone, those names below the DNAME RR will be
+ occluded, RFC 2136 [RFC2136], section 7.18. Also a server SHOULD
+ refuse to load a zone subordinate to the owner of a DNAME record in
+ the ancestor zone. See Section 5.2 for further discussion related to
+ dynamic update.
+
+ DNAME is a singleton type, meaning only one DNAME is allowed per
+ name. The owner name of a DNAME can only have one DNAME RR, and no
+ CNAME RRs can exist at that name. These rules make sure that for a
+ single domain name only one redirection exists, and thus no confusion
+ which one to follow. A server SHOULD refuse to load a zone that
+ violates these rules.
+
+2.5. Compression of the DNAME record.
+
+ The DNAME owner name can be compressed like any other owner name.
+ The DNAME RDATA target name MUST NOT be sent out in compressed form,
+ so that a DNAME RR can be treated as an unknown type [RFC3597].
+
+ Although the previous DNAME specification [RFC2672] (that is
+ obsoleted by this specification) talked about signaling to allow
+ compression of the target name, such signaling is not specified.
+
+ RFC 2672 stated that the EDNS version had a meaning for understanding
+ of DNAME and DNAME target name compression. This document updates
+ RFC 2672, in that there is no EDNS version signaling for DNAME.
+ However, the flags section of EDNS(0) is updated with a Understand-
+ DNAME flag by this document (See Section 3.3).
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 6]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+3. Processing
+
+ The DNAME RR causes type NS additional section processing.
+
+3.1. CNAME synthesis and UD bit
+
+ When preparing an response, a server upon performing a DNAME
+ substitution will in all cases include the DNAME RR used in the
+ answer section. A CNAME RR record with TTL equal to the
+ corresponding DNAME RR is synthesized and included in the answer
+ section for old resolvers. The owner name of the CNAME is the QNAME
+ of the query. DNSSEC [RFC4033], [RFC4034], [RFC4035] says that the
+ synthesized CNAME does not have to be signed. The DNAME has an RRSIG
+ and a validating resolver can check the CNAME against the DNAME
+ record and validate the DNAME record.
+
+ Resolvers MUST be able to handle a synthesized CNAME TTL of zero or
+ equal to the TTL of the corresponding DNAME record. A TTL of zero
+ means that the CNAME can be discarded immediately after processing
+ the answer. DNAME aware resolvers can set the Understand-DNAME (UD
+ bit) to receive a response with only the DNAME RR and no synthesized
+ CNAMEs.
+
+ The UD bit is part of the EDNS [RFC2671] extended RCODE and Flags
+ field. It is used to omit server processing, transmission and
+ resolver processing of unsigned synthesized CNAMEs. Resolvers can
+ set this in a query to request omission of the synthesized CNAMEs.
+ Servers copy the UD bit to the response, and can omit synthesized
+ CNAMEs from the answer. Older resolvers do not set the UD bit, and
+ older servers do not copy the UD bit to the answer, and will not omit
+ synthesized CNAMEs.
+
+ Updated EDNS extended RCODE and Flags field.
+
+ +0 (MSB) +1 (LSB)
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 0: | EXTENDED-RCODE | VERSION |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 2: |DO|UD| Z |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ Servers MUST be able to answer a query for a synthesized CNAME. Like
+ other query types this invokes the DNAME, and synthesizes the CNAME
+ into the answer.
+
+
+
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 7]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+3.2. Server algorithm
+
+ Below the server algorithm, which appeared in RFC 2672 Section 4.1,
+ is expanded to handle the UD (Understand DNAME) bit.
+
+ 1. Set or clear the value of recursion available in the response
+ depending on whether the name server is willing to provide
+ recursive service. If recursive service is available and
+ requested via the RD bit in the query, go to step 5, otherwise
+ step 2.
+
+ 2. Search the available zones for the zone which is the nearest
+ ancestor to QNAME. If such a zone is found, go to step 3,
+ otherwise step 4.
+
+ 3. Start matching down, label by label, in the zone. The matching
+ process can terminate several ways:
+
+ A. If the whole of QNAME is matched, we have found the node.
+
+ If the data at the node is a CNAME, and QTYPE does not match
+ CNAME, copy the CNAME RR into the answer section of the
+ response, change QNAME to the canonical name in the CNAME RR,
+ and go back to step 1.
+
+ Otherwise, copy all RRs which match QTYPE into the answer
+ section and go to step 6.
+
+ B. If a match would take us out of the authoritative data, we
+ have a referral. This happens when we encounter a node with
+ NS RRs marking cuts along the bottom of a zone.
+
+ Copy the NS RRs for the sub-zone into the authority section
+ of the reply. Put whatever addresses are available into the
+ additional section, using glue RRs if the addresses are not
+ available from authoritative data or the cache. Go to step
+ 4.
+
+ C. If at some label, a match is impossible (i.e., the
+ corresponding label does not exist), look to see whether the
+ last label matched has a DNAME record.
+
+ If a DNAME record exists at that point, copy that record into
+ the answer section. If substitution of its <target> for its
+ <owner> in QNAME would overflow the legal size for a <domain-
+ name>, set RCODE to YXDOMAIN [RFC2136] and exit; otherwise
+ perform the substitution and continue. If the EDNS OPT
+ record is present in the query and the UD bit is set, the
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 8]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+ server MAY copy the UD bit to the answer EDNS OPT record, and
+ omit CNAME synthesis. Else the server MUST synthesize a
+ CNAME record as described above and include it in the answer
+ section. Go back to step 1.
+
+ If there was no DNAME record, look to see if the "*" label
+ exists.
+
+ If the "*" label does not exist, check whether the name we
+ are looking for is the original QNAME in the query or a name
+ we have followed due to a CNAME or DNAME. If the name is
+ original, set an authoritative name error in the response and
+ exit. Otherwise just exit.
+
+ If the "*" label does exist, match RRs at that node against
+ QTYPE. If any match, copy them into the answer section, but
+ set the owner of the RR to be QNAME, and not the node with
+ the "*" label. If the data at the node with the "*" label is
+ a CNAME, and QTYPE doesn't match CNAME, copy the CNAME RR
+ into the answer section of the response changing the owner
+ name to the QNAME, change QNAME to the canonical name in the
+ CNAME RR, and go back to step 1. Otherwise, Go to step 6.
+
+ 4. Start matching down in the cache. If QNAME is found in the
+ cache, copy all RRs attached to it that match QTYPE into the
+ answer section. If QNAME is not found in the cache but a DNAME
+ record is present at an ancestor of QNAME, copy that DNAME record
+ into the answer section. If there was no delegation from
+ authoritative data, look for the best one from the cache, and put
+ it in the authority section. Go to step 6.
+
+ 5. Use the local resolver or a copy of its algorithm to answer the
+ query. Store the results, including any intermediate CNAMEs and
+ DNAMEs, in the answer section of the response.
+
+ 6. Using local data only, attempt to add other RRs which may be
+ useful to the additional section of the query. Exit.
+
+ Note that there will be at most one ancestor with a DNAME as
+ described in step 4 unless some zone's data is in violation of the
+ no-descendants limitation in section 3. An implementation might take
+ advantage of this limitation by stopping the search of step 3c or
+ step 4 when a DNAME record is encountered.
+
+3.3. Wildcards
+
+ The use of DNAME in conjunction with wildcards is discouraged
+ [RFC4592]. Thus records of the form "*.example.com DNAME
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 9]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+ example.net" SHOULD NOT be used.
+
+ The interaction between the expansion of the wildcard and the
+ redirection of the DNAME is non-deterministic. Because the
+ processing is non-deterministic, DNSSEC validating resolvers may not
+ be able to validate a wildcarded DNAME.
+
+ A server MAY give a warning that the behavior is unspecified if such
+ a wildcarded DNAME is loaded. The server MAY refuse it, refuse to
+ load or refuse dynamic update.
+
+3.4. Acceptance and Intermediate Storage
+
+ DNS caches can encounter data at names below the owner name of a
+ DNAME RR, due to a change at the authoritative server where data from
+ before and after the change resides in the cache. This conflict
+ situation is a transitional phase, that ends when the old data times
+ out. The cache can opt to store both old and new data and treat each
+ as if the other did not exist, or drop the old data, or drop the
+ longer domain name. In any approach, consistency returns after the
+ older data TTL times out.
+
+ DNS caches MUST perform CNAME synthesis on behalf of DNAME-ignorant
+ clients. A DNS cache that understands DNAMEs can send out queries on
+ behalf of clients with the UD bit set (See Section 3.1). After
+ receiving the answers the DNS cache sends replies to DNAME ignorant
+ clients that include DNAMEs and synthesized CNAMEs.
+
+4. DNAME Discussions in Other Documents
+
+ In [RFC2181], in Section 10.3., the discussion on MX and NS records
+ touches on redirection by CNAMEs, but this also holds for DNAMEs.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 10]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+ Excerpt from 10.3. MX and NS records (in RFC 2181).
+
+ The domain name used as the value of a NS resource record,
+ or part of the value of a MX resource record must not be
+ an alias. Not only is the specification clear on this
+ point, but using an alias in either of these positions
+ neither works as well as might be hoped, nor well fulfills
+ the ambition that may have led to this approach. This
+ domain name must have as its value one or more address
+ records. Currently those will be A records, however in
+ the future other record types giving addressing
+ information may be acceptable. It can also have other
+ RRs, but never a CNAME RR.
+
+ The DNAME RR is discussed in RFC 3363, section 4, on A6 and DNAME.
+ The opening premise of this section is demonstrably wrong, and so the
+ conclusion based on that premise is wrong. In particular, [RFC3363]
+ deprecates the use of DNAME in the IPv6 reverse tree, which is then
+ carried forward as a recommendation in [RFC4294]. Based on the
+ experience gained in the meantime, [RFC3363] should be revised,
+ dropping all constraints on having DNAME RRs in these zones. This
+ would greatly improve the manageability of the IPv6 reverse tree.
+ These changes are made explicit below.
+
+ In [RFC3363], the paragraph
+
+ "The issues for DNAME in the reverse mapping tree appears to be
+ closely tied to the need to use fragmented A6 in the main tree: if
+ one is necessary, so is the other, and if one isn't necessary, the
+ other isn't either. Therefore, in moving RFC 2874 to experimental,
+ the intent of this document is that use of DNAME RRs in the reverse
+ tree be deprecated."
+
+ is to be replaced with the word "DELETED".
+
+ In [RFC4294], the reference to DNAME was left in as an editorial
+ oversight. The paragraph
+
+ "Those nodes are NOT RECOMMENDED to support the experimental A6 and
+ DNAME Resource Records [RFC3363]."
+
+ is to be replaced by
+
+ "Those nodes are NOT RECOMMENDED to support the experimental
+ A6 Resource Record [RFC3363]."
+
+
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 11]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+5. Other Issues with DNAME
+
+ There are several issues to be aware of about the use of DNAME.
+
+5.1. Canonical hostnames cannot be below DNAME owners
+
+ The names listed as target names of MX, NS, PTR and SRV [RFC2782]
+ records must be canonical hostnames. This means no CNAME or DNAME
+ redirection may be present during DNS lookup of the address records
+ for the host. This is discussed in RFC 2181 [RFC2181], section 10.3,
+ and RFC 1912 [RFC1912], section 2.4. For SRV see RFC 2782 [RFC2782]
+ page 4.
+
+ The upshot of this is that although the lookup of a PTR record can
+ involve DNAMEs, the name listed in the PTR record can not fall under
+ a DNAME. The same holds for NS, SRV and MX records. For example,
+ when punycode alternates for a zone use DNAME then the NS, MX, SRV
+ and PTR records that point to that zone must use names without
+ punycode in their RDATA. What must be done then is to have the
+ domain names with DNAME substitution already applied to it as the MX,
+ NS, PTR, SRV data. These are valid canonical hostnames.
+
+5.2. Dynamic Update and DNAME
+
+ DNAME records can be added, changed and removed in a zone using
+ dynamic update transactions. Adding a DNAME RR to a zone occludes
+ any domain names that may exist under the added DNAME.
+
+ A server MUST ignore a dynamic update message that attempts to add a
+ DNAME RR at a name that already has a CNAME RR or another DNAME RR
+ associated with that name.
+
+5.3. DNSSEC and DNAME
+
+5.3.1. DNAME bit in NSEC type map
+
+ When a validator checks the NSEC RRs returned on a name error
+ response, it SHOULD check that the DNAME bit is not set. If the
+ DNAME bit is set then the DNAME substitution should have been done,
+ but has not.
+
+5.3.2. Validators Must Understand DNAME
+
+ Examples of why DNSSEC validators MUST understand DNAME.
+
+
+
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 12]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+5.3.2.1. DNAME in Bitmap Causes Invalid Name Error
+
+ ;; Header: QR AA DO RCODE=3(NXDOMAIN)
+ ;; Question
+ foo.bar.example.com. IN A
+ ;; Answer
+ bar.example.com. NSEC dub.example.com. A DNAME
+ bar.example.com. RRSIG NSEC [valid signature]
+
+ If this is the response, then only by understanding that the DNAME
+ bit means that foo.bar.example.com needed to have been redirected by
+ the DNAME, the validator can see that it is a BOGUS reply from an
+ attacker that collated existing records from the DNS to create a
+ confusing reply.
+
+ If the DNAME bit had not been set in the NSEC record above then the
+ answer would have validated as a correct name error response.
+
+5.3.2.2. Valid Name Error Response Involving DNAME in Bitmap
+
+ ;; Header: QR AA DO RCODE=3(NXDOMAIN)
+ ;; Question
+ cee.example.com. IN A
+ ;; Answer
+ bar.example.com. NSEC dub.example.com. A DNAME
+ bar.example.com. RRSIG NSEC [valid signature]
+
+ This reply has the same NSEC records as the example above, but with
+ this query name (cee.example.com), the answer is validated, because
+ 'cee' does not get redirected by the DNAME at 'bar'.
+
+5.3.2.3. Response With Synthesized CNAME
+
+ ;; Header: QR AA DO RCODE=0(NOERROR)
+ ;; Question
+ foo.bar.example.com. IN A
+ ;; Answer
+ bar.example.com. DNAME bar.example.net.
+ bar.example.com. RRSIG DNAME [valid signature]
+ foo.bar.example.com. CNAME foo.bar.example.net.
+
+ The answer shown above has the synthesized CNAME included. However,
+ the CNAME has no signature, since the server does not sign online.
+ So it cannot be trusted. It could be altered by an attacker to be
+ foo.bar.example.com CNAME bla.bla.example. The DNAME record does
+ have its signature included, since it does not change for every query
+ name. The validator must verify the DNAME signature and then
+ recursively resolve further to query for the foo.bar.example.net A
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 13]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+ record.
+
+6. IANA Considerations
+
+ The DNAME Resource Record type code 39 (decimal) originally has been
+ registered by [RFC2672]. IANA should update the DNS resource record
+ registry to point to this document for RR type 39.
+
+ This draft requests the second highest bit in the EDNS flags field
+ for the Understand-DNAME (UD) flag.
+
+7. Security Considerations
+
+ DNAME redirects queries elsewhere, which may impact security based on
+ policy and the security status of the zone with the DNAME and the
+ redirection zone's security status.
+
+ If a validating resolver accepts wildcarded DNAMEs, this creates
+ security issues. Since the processing of a wildcarded DNAME is non-
+ deterministic and the CNAME that was substituted by the server has no
+ signature, the resolver may choose a different result than what the
+ server meant, and consequently end up at the wrong destination. Use
+ of wildcarded DNAMEs is discouraged in any case [RFC4592].
+
+ A validating resolver MUST understand DNAME, according to [RFC4034].
+ In Section 5.3.2 examples are given that illustrate this need.
+
+8. Acknowledgments
+
+ The authors of this draft would like to acknowledge Matt Larson for
+ beginning this effort to address the issues related to the DNAME RR
+ type. The authors would also like to acknowledge Paul Vixie, Ed
+ Lewis, Mark Andrews, Mike StJohns, Niall O'Reilly, Sam Weiler, Alfred
+ Hines and Kevin Darcy for their review and comments on this document.
+
+9. References
+
+9.1. Normative References
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 14]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+ [RFC2136] Vixie, P., Thomson, S., Rekhter, Y., and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)",
+ RFC 2136, April 1997.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)",
+ RFC 2671, August 1999.
+
+ [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for
+ specifying the location of services (DNS SRV)", RFC 2782,
+ February 2000.
+
+ [RFC3597] Gustafsson, A., "Handling of Unknown DNS Resource Record
+ (RR) Types", RFC 3597, September 2003.
+
+ [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements",
+ RFC 4033, March 2005.
+
+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security Extensions",
+ RFC 4034, March 2005.
+
+ [RFC4035] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security
+ Extensions", RFC 4035, March 2005.
+
+ [RFC4592] Lewis, E., "The Role of Wildcards in the Domain Name
+ System", RFC 4592, July 2006.
+
+9.2. Informative References
+
+ [RFC1912] Barr, D., "Common DNS Operational and Configuration
+ Errors", RFC 1912, February 1996.
+
+ [RFC2672] Crawford, M., "Non-Terminal DNS Name Redirection",
+ RFC 2672, August 1999.
+
+ [RFC3363] Bush, R., Durand, A., Fink, B., Gudmundsson, O., and T.
+ Hain, "Representing Internet Protocol version 6 (IPv6)
+ Addresses in the Domain Name System (DNS)", RFC 3363,
+ August 2002.
+
+ [RFC4294] Loughney, J., "IPv6 Node Requirements", RFC 4294,
+ April 2006.
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 15]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+Authors' Addresses
+
+ Scott Rose
+ NIST
+ 100 Bureau Dr.
+ Gaithersburg, MD 20899
+ USA
+
+ Phone: +1-301-975-8439
+ Fax: +1-301-975-6238
+ EMail: scottr@nist.gov
+
+
+ Wouter Wijngaards
+ NLnet Labs
+ Kruislaan 419
+ Amsterdam 1098 VA
+ The Netherlands
+
+ Phone: +31-20-888-4551
+ EMail: wouter@nlnetlabs.nl
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 16]
+
+Internet-Draft DNAME Redirection May 2008
+
+
+Full Copyright Statement
+
+ Copyright (C) The IETF Trust (2008).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Rose & Wijngaards Expires November 3, 2008 [Page 17]
+
diff --git a/doc/draft/draft-ietf-dnsext-signed-nonexistence-requirements-01.txt b/doc/draft/draft-ietf-dnsext-signed-nonexistence-requirements-01.txt
new file mode 100644
index 0000000..0af13c6
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-signed-nonexistence-requirements-01.txt
@@ -0,0 +1,755 @@
+
+
+Network Working Group B. Laurie
+Internet-Draft Nominet
+Expires: March 2, 2005 R. Loomis
+ SAIC
+ September 2004
+
+
+
+ Requirements related to DNSSEC Signed Proof of Non-Existence
+ draft-ietf-dnsext-signed-nonexistence-requirements-01
+
+
+Status of this Memo
+
+
+ This document is an Internet-Draft and is subject to all provisions
+ of section 3 of RFC 3667. By submitting this Internet-Draft, each
+ author represents that any applicable patent or other IPR claims of
+ which he or she is aware have been or will be disclosed, and any of
+ which he or she become aware will be disclosed, in accordance with
+ RFC 3668.
+
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as
+ Internet-Drafts.
+
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+
+ This Internet-Draft will expire on March 2, 2005.
+
+
+Copyright Notice
+
+
+ Copyright (C) The Internet Society (2004).
+
+
+Abstract
+
+
+ DNSSEC-bis uses the NSEC record to provide authenticated denial of
+ existence of RRsets. NSEC also has the side-effect of permitting
+ zone enumeration, even if zone transfers have been forbidden.
+ Because some see this as a problem, this document has been assembled
+ to detail the possible requirements for denial of existence A/K/A
+ signed proof of non-existence.
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 1]
+Internet-Draft signed-nonexistence-requirements September 2004
+
+
+
+Table of Contents
+
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Non-purposes . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 3. Zone Enumeration . . . . . . . . . . . . . . . . . . . . . . 3
+ 4. Zone Enumeration II . . . . . . . . . . . . . . . . . . . . 4
+ 5. Zone Enumeration III . . . . . . . . . . . . . . . . . . . . 4
+ 6. Exposure of Contents . . . . . . . . . . . . . . . . . . . . 4
+ 7. Zone Size . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 8. Single Method . . . . . . . . . . . . . . . . . . . . . . . 5
+ 9. Empty Non-terminals . . . . . . . . . . . . . . . . . . . . 5
+ 10. Prevention of Precomputed Dictionary Attacks . . . . . . . . 6
+ 11. DNSSEC-Adoption and Zone-Growth Relationship . . . . . . . . 6
+ 12. Non-overlap of denial records with possible zone records . . 7
+ 13. Exposure of Private Keys . . . . . . . . . . . . . . . . . . 7
+ 14. Minimisation of Zone Signing Cost . . . . . . . . . . . . . 8
+ 15. Minimisation of Asymmetry . . . . . . . . . . . . . . . . . 8
+ 16. Minimisation of Client Complexity . . . . . . . . . . . . . 8
+ 17. Completeness . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 18. Purity of Namespace . . . . . . . . . . . . . . . . . . . . 8
+ 19. Replay Attacks . . . . . . . . . . . . . . . . . . . . . . . 8
+ 20. Compatibility with NSEC . . . . . . . . . . . . . . . . . . 8
+ 21. Compatibility with NSEC II . . . . . . . . . . . . . . . . . 9
+ 22. Compatibility with NSEC III . . . . . . . . . . . . . . . . 9
+ 23. Coexistence with NSEC . . . . . . . . . . . . . . . . . . . 9
+ 24. Coexistence with NSEC II . . . . . . . . . . . . . . . . . . 9
+ 25. Protocol Design . . . . . . . . . . . . . . . . . . . . . . 9
+ 26. Process . . . . . . . . . . . . . . . . . . . . . . . . . . 9
+ 27. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 9
+ 28. Requirements notation . . . . . . . . . . . . . . . . . . . 9
+ 29. Security Considerations . . . . . . . . . . . . . . . . . . 10
+ 30. References . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 30.1 Normative References . . . . . . . . . . . . . . . . . . . 10
+ 30.2 Informative References . . . . . . . . . . . . . . . . . . 10
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 10
+ Intellectual Property and Copyright Statements . . . . . . . 11
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 2]
+Internet-Draft signed-nonexistence-requirements September 2004
+
+
+
+1. Introduction
+
+
+ NSEC records allow trivial enumeration of zones - a situation that
+ has existed for several years but which has recently been raised as a
+ significant concern for DNSSECbis deployment in several zones.
+ Alternate proposals have been made that make zone enumeration more
+ difficult, and some previous proposals to modify DNSSEC had related
+ requirements/desirements that are relevant to the discussion. In
+ addition the original designs for NSEC/NXT records were based on
+ working group discussions and the choices made were not always
+ documented with context and requirements-- so some of those choices
+ may need to be restated as requirements. Overall, the working group
+ needs to better understand the requirements for denial of existence
+ (and certain other requirements related to DNSSECbis deployment) in
+ order to evaluate the proposals that may replace NSEC.
+
+
+ In the remainder of this document, "NSEC++" is used as shorthand for
+ "a denial of existence proof that will replace NSEC". "NSECbis" has
+ also been used as shorthand for this, but we avoid that usage since
+ NSECbis will not be part of DNSSECbis and therefore there might be
+ some confusion.
+
+
+2. Non-purposes
+
+
+ This document does not currently document the reasons why zone
+ enumeration might be "bad" from a privacy, security, business, or
+ other perspective--except insofar as those reasons result in
+ requirements. Once the list of requirements is complete and vaguely
+ coherent, the trade-offs (reducing zone enumeration will have X cost,
+ while providing Y benefit) may be revisited. The editors of this
+ compendium received inputs on the potential reasons why zone
+ enumeration is bad (and there was significant discussion on the
+ DNSEXT WG mailing list) but that information fell outside the scope
+ of this document.
+
+
+ Note also that this document does not assume that NSEC *must* be
+ replaced with NSEC++, if the requirements can be met through other
+ methods (e.g., "white lies" with the current NSEC). As is stated
+ above, this document is focused on requirements collection and
+ (ideally) prioritization rather than on the actual implementation.
+
+
+3. Zone Enumeration
+
+
+ Authenticated denial should not permit trivial zone enumeration.
+
+
+ Additional discussion: NSEC (and NXT before it) provide a linked
+ list that could be "walked" to trivially enumerate all the signed
+ records in a zone. This requirement is primarily (though not
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 3]
+Internet-Draft signed-nonexistence-requirements September 2004
+
+
+
+ exclusively) important for zones that either are delegation-only/
+ -mostly or do not have reverse lookup (PTR) records configured, since
+ enterprises that have PTR records for all A records have already
+ provided a similar capability to enumerate the contents of DNS zones.
+
+
+ Contributor: various
+
+
+4. Zone Enumeration II
+
+
+ Zone enumeration should be at least as difficult as it would be to
+ effect a dictionary attack using simple DNS queries to do the same in
+ an unsecured zone.
+
+
+ (Editor comment: it is not clear how to measure difficulty in this
+ case. Some examples could be monetary cost, bandwidth, processing
+ power or some combination of these. It has also been suggested that
+ the requirement is that the graph of difficulty of enumeration vs.
+ the fraction of the zone enumerated should be approximately the same
+ shape in the two cases)
+
+
+ Contributor: Nominet
+
+
+5. Zone Enumeration III
+
+
+ Enumeration of a zone with random contents should computationally
+ infeasible.
+
+
+ Editor comment: this is proposed as a way of evaluating the
+ effectiveness of a proposal rather than as a requirement anyone would
+ actually have in practice.
+
+
+ Contributor: Alex Bligh
+
+
+6. Exposure of Contents
+
+
+ NSEC++ should not expose any of the contents of the zone (apart from
+ the NSEC++ records themselves, of course).
+
+
+ Editor comment: this is a weaker requirement than prevention of
+ enumeration, but certainly any zone that satisfied this requirement
+ would also satisfy the trivial prevention of enumeration requirement.
+
+
+ Contributor: Ed Lewis
+
+
+7. Zone Size
+
+
+ Requirement: NSEC++ should make it possible to take precautions
+ against trivial zone size estimates. Since not all zone owners care
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 4]
+Internet-Draft signed-nonexistence-requirements September 2004
+
+
+
+ about others estimation of the size of a zone, it is not always
+ necessary to prohibit trivial estimation of the size of the zone but
+ NSEC++ should allow such measures.
+
+
+ Additional Discussion: Even with proposals based on obfuscating names
+ with hashes it is trivial to give very good estimates of the number
+ of domains in a certain zone. Just send 10 random queries and look
+ at the range between the two hash values returned in each NSEC++. As
+ hash output can be assumed to follow a rectangular random
+ distribution, using the mean difference between the two values, you
+ can estimate the total number of records. It is probably sufficient
+ to look at even one NSEC++, since the two hash values should follow a
+ (I believe) Poisson distribution.
+
+
+ The concern is motivated by some wording remembered from NSEC, which
+ stated that NSEC MUST only be present for existing owner names in the
+ zone, and MUST NOT be present for non-existing owner names. If
+ similar wording were carried over to NSEC++, introducing bogus owner
+ names in the hash chain (an otherwise simple solution to guard
+ against trivial estimates of zone size) wouldn't be allowed.
+
+
+ One simple attempt at solving this is to describe in the
+ specifications how zone signer tools can add a number of random
+ "junk" records.
+
+
+ Editor's comment: it is interesting that obfuscating names might
+ actually make it easier to estimate zone size.
+
+
+ Contributor: Simon Josefsson.
+
+
+8. Single Method
+
+
+ Requirement: A single NSEC++ method must be able to carry both
+ old-style denial (i.e. plain labels) and whatever the new style
+ looks like. Having two separate denial methods could result in
+ cornercases where one method can deny the other and vice versa.
+
+
+ Additional discussion: This requirement can help -bis folks to a
+ smooth upgrade to -ter. First they'd change the method while the
+ content is the same, then they can change content of the method.
+
+
+ Contributor: Roy Arends.
+
+
+9. Empty Non-terminals
+
+
+ Requirement: Empty-non-terminals (ENT) should remain empty. In
+ other words, adding NSEC++ records to an existing DNS structure
+ should not cause the creation of NSEC++ records (or related records)
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 5]
+Internet-Draft signed-nonexistence-requirements September 2004
+
+
+
+ at points that are otherwise ENT.
+
+
+ Additional discussion: Currently NSEC complies with ENT requirement:
+ b.example.com NSEC a.c.example.com implies the existence of an ENT
+ with ownername c.example.com. NSEC2 breaks that requirement, since
+ the ownername is entirely hashed causing the structure to disappear.
+ This is why EXIST was introduced. But EXIST causes ENT to be
+ non-empty-terminals. Next to the dissappearance of ENT, it causes
+ (some) overhead since an EXIST record needs a SIG, NSEC2 and
+ SIG(NSEC2). DNSNR honours this requirement by hashing individual
+ labels instead of ownernames. However this causes very long labels.
+ Truncation is a measure against very long ownernames, but that is
+ controversial. There is a fair discussion of the validity of
+ truncation in the DNSNR draft, but that hasn't got proper review yet.
+
+
+ Contributor: Roy Arends.
+
+
+ (Editor comment: it is not clear to us that an EXIST record needs an
+ NSEC2 record, since it is a special purpose record only used for
+ denial of existence)
+
+
+10. Prevention of Precomputed Dictionary Attacks
+
+
+ Requirement: NSEC++ needs to provide a method to reduce the
+ effectiveness of precomputed dictionary attacks.
+
+
+ Additional Discussion: Salt is a measure against dictionary attacks.
+ There are other possible measures (such as iterating hashes in
+ NSEC2). The salt needs to be communicated in every response, since
+ it is needed in every verification. Some have suggested to move the
+ salt to a special record instead of the denial record. I think this
+ is not wise. Response size has more priority over zone size. An
+ extra record causes a larger response than a larger existing record.
+
+
+ Contributor: Roy Arends.
+
+
+ (Editor comment: the current version of NSEC2 also has the salt in
+ every NSEC2 record)
+
+
+11. DNSSEC-Adoption and Zone-Growth Relationship
+
+
+ Background: Currently with NSEC, when a delegation centric zone
+ deploys DNSSEC, the zone-size multiplies by a non-trivial factor even
+ when the DNSSEC-adoption rate of the subzones remains low--because
+ each delegation point creates at least one NSEC record and
+ corresponding signature in the parent even if the child is not
+ signed.
+
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 6]
+Internet-Draft signed-nonexistence-requirements September 2004
+
+
+
+ Requirements: A delegation-only (or delegation-mostly) zone that is
+ signed but which has no signed child zones should initially need only
+ to add SIG(SOA), DNSKEY, and SIG(DNSKEY) at the apex, along with some
+ minimal set of NSEC++ records to cover zone contents. Further,
+ during the transition of a delegation-only zone from 0% signed
+ children to 100% signed children, the growth in the delegation-only
+ zone should be roughly proportional to the percentage of signed child
+ zones.
+
+
+ Additional Discussion: This is why DNSNR has the Authoritative Only
+ bit. This is similar to opt-in for delegations only. This (bit) is
+ currently the only method to help delegation-centric zone cope with
+ zone-growth due to DNSSEC adoption. As an example, A delegation only
+ zone which deploys DNSSEC with the help of this bit, needs to add
+ SIG(SOA), DNSKEY, SIG(DNSKEY), DNSNR, SIG(DNSNR) at the apex. No
+ more than that.
+
+
+ Contributor: Roy Arends.
+
+
+12. Non-overlap of denial records with possible zone records
+
+
+ Requirement: NSEC++ records should in some way be differentiated
+ from regular zone records, so that there is no possibility that a
+ record in the zone could be duplicated by a non-existence proof
+ (NSEC++) record.
+
+
+ Additional discussion: This requirement is derived from a discussion
+ on the DNSEXT mailing list related to copyrights and domain names.
+ As was outlined there, one solution is to put NSEC++ records in a
+ separate namespace, e.g.: $ORIGIN co.uk.
+ 873bcdba87401b485022b8dcd4190e3e IN NS jim.rfc1035.com ; your
+ delegation 873bcdba87401b485022b8dcd4190e3e._no IN NSEC++ 881345...
+ ; for amazon.co.uk.
+
+
+ Contributor: various
+
+
+ (Editor comment: One of us still does not see why a conflict
+ matters. Even if there is an apparent conflict or overlap, the
+ "conflicting" NSEC2 name _only_ appears in NSEC2 records, and the
+ other name _never_ appears in NSEC2 records.)
+
+
+13. Exposure of Private Keys
+
+
+ Private keys associated with the public keys in the DNS should be
+ exposed as little as possible. It is highly undesirable for private
+ keys to be distributed to nameservers, or to otherwise be available
+ in the run-time environment of nameservers.
+
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 7]
+Internet-Draft signed-nonexistence-requirements September 2004
+
+
+
+ Contributors: Nominet, Olaf Kolkman, Ed Lewis
+
+
+14. Minimisation of Zone Signing Cost
+
+
+ The additional cost of creating an NSEC++ signed zone should not
+ significantly exceed the cost of creating an ordinary signed zone.
+
+
+ Contributor: Nominet
+
+
+15. Minimisation of Asymmetry
+
+
+ Nameservers should have to do as little additional work as necessary.
+ More precisely, it is desirable for any increase in cost incurred by
+ the nameservers to be offset by a proportionate increase in cost to
+ DNS `clients', e.g. stub and/or `full-service' resolvers.
+
+
+ Contributor: Nominet
+
+
+16. Minimisation of Client Complexity
+
+
+ Caching, wildcards, CNAMEs, DNAMEs should continue to work without
+ adding too much complexity at the client side.
+
+
+ Contributor: Olaf Kolkman
+
+
+17. Completeness
+
+
+ A proof of nonexistence should be possible for all nonexistent data
+ in the zone.
+
+
+ Contributor: Olaf Kolkman
+
+
+18. Purity of Namespace
+
+
+ The name space should not be muddied with fake names or data sets.
+
+
+ Contributor: Ed Lewis
+
+
+19. Replay Attacks
+
+
+ NSEC++ should not allow a replay to be used to deny existence of an
+ RR that actually exists.
+
+
+ Contributor: Ed Lewis
+
+
+20. Compatibility with NSEC
+
+
+ NSEC++ should not introduce changes incompatible with NSEC.
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 8]
+Internet-Draft signed-nonexistence-requirements September 2004
+
+
+
+ Contributor: Ed Lewis
+
+
+21. Compatibility with NSEC II
+
+
+ NSEC++ should differ from NSEC in a way that is transparent to the
+ resolver or validator.
+
+
+ Contributor: Ed Lewis
+
+
+22. Compatibility with NSEC III
+
+
+ NSEC++ should differ from NSEC as little as possible whilst achieving
+ other requirements.
+
+
+ Contributor: Alex Bligh
+
+
+23. Coexistence with NSEC
+
+
+ NSEC++ should be optional, allowing NSEC to be used instead.
+
+
+ Contributor: Ed Lewis, Alex Bligh
+
+
+24. Coexistence with NSEC II
+
+
+ NSEC++ should not impose extra work on those content with NSEC.
+
+
+ Contributor: Ed Lewis
+
+
+25. Protocol Design
+
+
+ A good security protocol would allow signing the nonexistence of some
+ selected names without revealing anything about other names.
+
+
+ Contributor: Dan Bernstein
+
+
+26. Process
+
+
+ Clearly not all of these requirements can be met. Therefore the next
+ phase of this document will be to either prioritise them or narrow
+ them down to a non-contradictory set, which should then allow us to
+ judge proposals on the basis of their fit.
+
+
+27. Acknowledgements
+
+
+28. Requirements notation
+
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 9]
+Internet-Draft signed-nonexistence-requirements September 2004
+
+
+
+ document are to be interpreted as described in [RFC2119].
+
+
+29. Security Considerations
+
+
+ There are currently no security considerations called out in this
+ draft. There will be security considerations in the choice of which
+ requirements will be implemented, but there are no specific security
+ requirements during the requirements collection process.
+
+
+30. References
+
+
+30.1 Normative References
+
+
+ [dnssecbis-protocol]
+ "DNSSECbis Protocol Definitions", BCP XX, RFC XXXX, Some
+ Month 2004.
+
+
+30.2 Informative References
+
+
+ [RFC2026] Bradner, S., "The Internet Standards Process -- Revision
+ 3", BCP 9, RFC 2026, October 1996.
+
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+
+ [RFC2418] Bradner, S., "IETF Working Group Guidelines and
+ Procedures", BCP 25, RFC 2418, September 1998.
+
+
+
+Authors' Addresses
+
+
+ Ben Laurie
+ Nominet
+ 17 Perryn Road
+ London W3 7LR
+ England
+
+
+ Phone: +44 (20) 8735 0686
+ EMail: ben@algroup.co.uk
+
+
+
+ Rip Loomis
+ Science Applications International Corporation
+ 7125 Columbia Gateway Drive, Suite 300
+ Columbia, MD 21046
+ US
+
+
+ EMail: gilbert.r.loomis@saic.com
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 10]
+Internet-Draft signed-nonexistence-requirements September 2004
+
+
+
+Intellectual Property Statement
+
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+
+Disclaimer of Validity
+
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+Copyright Statement
+
+
+ Copyright (C) The Internet Society (2004). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+
+Acknowledgment
+
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+Laurie & Loomis Expires March 2, 2005 [Page 11] \ No newline at end of file
diff --git a/doc/draft/draft-ietf-dnsext-tkey-renewal-mode-05.txt b/doc/draft/draft-ietf-dnsext-tkey-renewal-mode-05.txt
new file mode 100644
index 0000000..9c73c68
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-tkey-renewal-mode-05.txt
@@ -0,0 +1,1292 @@
+
+
+
+
+
+DNS Extensions Yuji Kamite
+Internet-Draft NTT Communications
+Expires: April 15, 2005 Masaya Nakayama
+ The University of Tokyo
+ October 14, 2004
+
+
+
+ TKEY Secret Key Renewal Mode
+ draft-ietf-dnsext-tkey-renewal-mode-05
+
+
+Status of this Memo
+
+ This document is an Internet-Draft and is subject to all provisions
+ of section 3 of RFC 3667. By submitting this Internet-Draft, each
+ author represents that any applicable patent or other IPR claims of
+ which he or she is aware have been or will be disclosed, and any of
+ which he or she become aware will be disclosed, in accordance with
+ RFC 3668.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as
+ Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on April 15, 2005.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2004).
+
+Abstract
+
+ This document defines a new mode in TKEY and proposes an atomic
+ method for changing secret keys used for TSIG periodically.
+ Originally, TKEY provides methods of setting up shared secrets other
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 1]
+
+INTERNET-DRAFT October 2004
+
+
+ than manual exchange, but it cannot control timing of key renewal
+ very well though it can add or delete shared keys separately. This
+ proposal is a systematical key renewal procedure intended for
+ preventing signing DNS messages with old and non-safe keys
+ permanently.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1 Defined Words . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.2 New Format and Assigned Numbers . . . . . . . . . . . . . 4
+ 1.3 Overview of Secret Key Renewal Mode . . . . . . . . . . . 4
+ 2. Shared Secret Key Renewal . . . . . . . . . . . . . . . . . . 5
+ 2.1 Key Usage Time Check . . . . . . . . . . . . . . . . . . . 5
+ 2.2 Partial Revocation . . . . . . . . . . . . . . . . . . . . 6
+ 2.3 Key Renewal Message Exchange . . . . . . . . . . . . . . . 7
+ 2.3.1 Query for Key Renewal . . . . . . . . . . . . . . . . 7
+ 2.3.2 Response for Key Renewal . . . . . . . . . . . . . . . 7
+ 2.3.3 Attributes of Generated Key . . . . . . . . . . . . . 8
+ 2.3.4 TKEY RR structure . . . . . . . . . . . . . . . . . . 8
+ 2.4 Key Adoption . . . . . . . . . . . . . . . . . . . . . . . 10
+ 2.4.1 Query for Key Adoption . . . . . . . . . . . . . . . . 10
+ 2.4.2 Response for Key Adoption . . . . . . . . . . . . . . 10
+ 2.5 Keying Schemes . . . . . . . . . . . . . . . . . . . . . . 11
+ 2.5.1 DH Exchange for Key Renewal . . . . . . . . . . . . . 11
+ 2.5.2 Server Assigned Keying for Key Renewal . . . . . . . . 12
+ 2.5.3 Resolver Assigned Keying for Key Renewal . . . . . . . 13
+ 2.6 Considerations about Non-compliant Hosts . . . . . . . . . 14
+ 3. Secret Storage . . . . . . . . . . . . . . . . . . . . . . . . 15
+ 4. Compulsory Key Revocation . . . . . . . . . . . . . . . . . . 15
+ 4.1 Compulsory Key Revocation by Server . . . . . . . . . . . 15
+ 4.2 Authentication Methods Considerations . . . . . . . . . . 15
+ 5. Special Considerations for Two Servers' Case . . . . . . . . 16
+ 5.1 To Cope with Collisions of Renewal Requests . . . . . . . 16
+ 6. Key Name Considerations . . . . . . . . . . . . . . . . . . . 17
+ 7. Example Usage of Secret Key Renewal Mode . . . . . . . . . . 17
+ 8. Security Considerations . . . . . . . . . . . . . . . . . . . 20
+ 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 20
+ 10. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 21
+ 11. References . . . . . . . . . . . . . . . . . . . . . . . . . . 21
+ 11.1 Normative References . . . . . . . . . . . . . . . . . . . 21
+ 11.2 Informative References . . . . . . . . . . . . . . . . . . 21
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 22
+ Intellectual Property and Copyright Statements . . . . . . . . 23
+
+
+
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 2]
+
+INTERNET-DRAFT October 2004
+
+
+1. Introduction
+
+ TSIG [RFC2845] provides DNS message integrity and the
+ request/transaction authentication by means of message authentication
+ codes (MAC). TSIG is a practical solution in view of calculation
+ speed and availability. However, TSIG does not have exchanging
+ mechanism of shared secret keys between server and resolver, and
+ administrators might have to exchange secret keys manually. TKEY
+ [RFC2930] is introduced to solve such problem and it can exchange
+ secrets for TSIG via networks.
+
+ In various modes of TKEY, a server and a resolver can add or delete a
+ secret key be means of TKEY message exchange. However, the existing
+ TKEY does not care fully about the management of keys which became
+ too old, or dangerous after long time usage.
+
+ It is ideal that the number of secret which a pair of hosts share
+ should be limited only one, because having too many keys for the same
+ purpose might not only be a burden to resolvers for managing and
+ distinguishing according to servers to query, but also does not seem
+ to be safe in terms of storage and protection against attackers.
+ Moreover, perhaps holding old keys long time might give attackers
+ chances to compromise by scrupulous calculation.
+
+ Therefore, when a new shared secret is established by TKEY, the
+ previous old secret should be revoked immediately. To accomplish
+ this, DNS servers must support a protocol for key renewal. This
+ document specifies procedure to refresh secret keys between two hosts
+ which is defined within the framework of TKEY, and it is called "TKEY
+ Secret Key Renewal Mode".
+
+ The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", "MAY" and
+ "OPTIONAL" in this document are to be interpreted as described in
+ [RFC2119].
+
+
+1.1. Defined Words
+
+ * Inception Time: Beginning of the shared secret key lifetime. This
+ value is determined when the key is generated.
+
+ * Expiry Limit: Time limit of the key's validity. This value is
+ determined when a new key is generated. After Expiry Limit, server
+ and client (resolver) must not authenticate TSIG signed with the key.
+ Therefore, Renewal to the next key should be carried out before
+ Expiry Limit.
+
+ * Partial Revocation Time: Time when server judges the key is too old
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 3]
+
+INTERNET-DRAFT October 2004
+
+
+ and must be updated. It must be between Inception Time and Expiry
+ Limit. This value is determined by server freely following its
+ security policy. e.g., If the time from Inception to Partial
+ Revocation is short, renewal will be carried out more often, which
+ might be safer.
+
+ * Revocation Time: Time when the key becomes invalid and can be
+ removed. This value is not determined in advance because it is the
+ actual time when revocation is completed.
+
+ * Adoption Time: Time when the new key is adopted as the next key
+ formally. After Adoption, the key is valid and server and client can
+ generate or verify TSIG making use of it. Adoption Time also means
+ the time when it becomes possible to remove the previous key, so
+ Revocation and Adoption are usually done at the same time.
+
+
+ Partial
+ Inception Revocation Revocation Expiry Limit
+ | | | |
+ |----------------|- - - - - - >>|- (revoked) -|
+ | | | |
+ previous key | | |
+ |- - - -|-------------------->> time
+ | | new key
+ Inception Adoption
+
+
+1.2. New Format and Assigned Numbers
+
+ TSIG
+ ERROR = (PartialRevoke), TBD
+
+ TKEY
+ Mode = (server assignment for key renewal), TBD
+ Mode = (Diffie-Hellman exchange for key renewal), TBD
+ Mode = (resolver assignment for key renewal), TBD
+ Mode = (key adoption), TBD
+
+
+1.3. Overview of Secret Key Renewal Mode
+
+ When a server receives a query from a client signed with a TSIG key,
+ It always checks if the present time is within the range of usage
+ duration it considers safe. If it is judged that the key is too old,
+ i.e., after Partial Revocation Time, the server comes to be in
+ Partial Revocation state about the key, and this key is called
+ partially revoked.
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 4]
+
+INTERNET-DRAFT October 2004
+
+
+ In this state, if a client sends a normal query (e.g., question about
+ A RR) other than TKEY Renewal request with TSIG signed with the old
+ key, the server returns an error message to notify that the time to
+ renew has come. This is called "PartialRevoke" error message. It is
+ server's choice whether it returns PartialRevoke or not. If and only
+ if the server is ready for changing its own key, it decides to return
+ PartialRevoke.
+
+ The client which got this error is able to notice that it is
+ necessary to refresh the secret. To make a new shared secret, it
+ sends a TKEY Renewal request, in which several keying methods are
+ available. It can make use of TSIG authentication signed with the
+ partially revoked key mentioned above.
+
+ After new secret establishment, the client sends a TKEY Adoption
+ request for renewal confirmation. This can also be authenticated with
+ the partially revoked key. If this is admitted by the server, the new
+ key is formally adopted, and at the same time the corresponding old
+ secret is invalidated. Then the client can send the first query again
+ signed with the new key.
+
+ Key renewal procedure is executed based on two-phase commit
+ mechanism. The first phase is the TKEY Renewal request and its
+ response, which means preparatory confirmation for key update. The
+ second phase is Adoption request and its response. If the server gets
+ request and client receives the response successfully, they can
+ finish renewal process. If any error happens and renewal process
+ fails during these phases, client should roll back to the beginning
+ of the first phase, and send TKEY Renewal request again. This
+ rollback can be done until the Expiry Limit of the key.
+
+
+2. Shared Secret Key Renewal
+
+ Suppose a server and a client agree to change their TSIG keys
+ periodically. Key renewal procedure is defined between two hosts.
+
+2.1. Key Usage Time Check
+
+ Whenever a server receives a query with TSIG and can find a key that
+ is used for signing it, the server checks its Inception Time, Partial
+ Revocation Time and Expiry Limit (this information is usually
+ memorized by the server).
+
+ When the present time is before Inception Time, the server MUST NOT
+ verify TSIG with the key, and server acts the same way as when the
+ key used by the client is not recognized. It follows [RFC2845] 4.5.1.
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 5]
+
+INTERNET-DRAFT October 2004
+
+
+ When the present time is equal to Inception Time, or between
+ Inception Time and Partial Revocation Time, the behavior of the
+ server is the same as when a valid key is found. It follows [RFC2845]
+ 4.5.2 and 4.5.3.
+
+ When the present time is the same as the Partial Revocation Time, or
+ between the Partial Revocation Time and Expiry Limit, the server
+ comes to be in Partial Revocation state about the TSIG key and
+ behaves according to the next section.
+
+ When the present time is the same as the Expiry Time or after it, the
+ server MUST NOT verify TSIG with the key, and returns error messages
+ in the same way as when the key used by the client is not recognized.
+ It follows [RFC2845] 4.5.1.
+
+
+2.2. Partial Revocation
+
+ In Partial Revocation state, we say the server has partially revoked
+ the key and the key has become a "partially revoked key".
+
+ If server has received a query signed with the partially revoked key
+ for TKEY Renewal request (See section 2.3.) or Key Adoption request
+ (See section 2.4.), then server does proper process following each
+ specification. If it is for TKEY key deletion request ([RFC2930]
+ 4.2), server MAY process usual deletion operation defined therein.
+
+ If server receives other types of query signed with the partially
+ revoked key, and both the corresponding MAC and signed TIME are
+ verified, then server begins returning answer whose TSIG error code
+ is "PartialRevoke" (See section 9.). Server MUST randomly but with
+ increasing frequency return PartialRevoke when in the Partial
+ Revocation state.
+
+ Server can decide when it actually sends PartialRevoke, checking if
+ it is appropriate time for renewal. Server MUST NOT return
+ PartialRevoke if this is apart long lived TSIG transaction (such as
+ AXFR) that started before the Partial Revocation Time.
+
+ If the client receives PartialRevoke and understands it, then it MUST
+ retry the query with the old key unless a new key has been adopted.
+ Client SHOULD start the process to renew the TSIG key. For key
+ renewal procedure, see details in Section 2.3 and 2.4.
+
+ PartialRevoke period (i.e., time while server returns PartialRevoke
+ randomely) SHOULD be small, say 2-5% of key lifetime. This is
+ server's choice.
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 6]
+
+INTERNET-DRAFT October 2004
+
+
+ Server MUST keep track of clients ignoring PartialRevoke, thus
+ indicating ignorance of this TKEY mode.
+
+ PartialRevoke error messages have the role to inform clients of the
+ keys' partial revocation and urge them to send TKEY Renewal requests.
+ These error responses MUST be signed with those partial revoked keys
+ if the queries are signed with them. They are sent only when the
+ signing keys are found to be partially revoked. If the MAC of TSIG
+ cannot be verified with the partially revoked keys, servers MUST NOT
+ return PartialRevoke error with MAC, but MUST return another error
+ such as "BADSIG" without MAC (following [RFC2845] 4.5.3); in other
+ words, a server informs its key's partial revocation only when the
+ MAC in the received query is valid.
+
+
+2.3. Key Renewal Message Exchange
+
+2.3.1. Query for Key Renewal
+
+ If a client has received a PartialRevoke error and authenticated the
+ response based on TSIG MAC, it sends a TKEY query for Key Renewal (in
+ this document, we call it Renewal request, too.) to the server. The
+ request MUST be signed with TSIG or SIG(0) [RFC2931] for
+ authentication. If TSIG is selected, the client can sign it with the
+ partial revoked key.
+
+ Key Renewal can use one of several keying methods which is indicated
+ in "Mode" field of TKEY RR, and its message structure is dependent on
+ that method.
+
+
+2.3.2. Response for Key Renewal
+
+ The server which has received Key Renewal request first tries to
+ verify TSIG or SIG(0) accompanying it. If the TSIG is signed and
+ verified with the partially revoked key, the request MUST be
+ authenticated.
+
+ After authentication, server must check existing old key's validity.
+ If the partially revoked key indicated in the request TKEY's OldName
+ and OldAlgorithm field (See section 2.3.4.) does not exist at the
+ server, "BADKEY" [RFC2845] is given in Error field for response. If
+ any other error happens, server returns appropriate error messages
+ following the specification described in section 2.5. If there are no
+ errors, server returns a Key Renewal answer. This answer MUST be
+ signed with TSIG or SIG(0) for authentication.
+
+ When this answer is successfully returned and no error is detected by
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 7]
+
+INTERNET-DRAFT October 2004
+
+
+ client, a new shared secret can be established. The details of
+ concrete keying procedure are given in the section 2.5.
+
+ Note:
+ Sometimes Adoption message and new Renewal request will cross on
+ the wire. In this case the newly generated key Adoption message is
+ resent.
+
+
+2.3.3. Attributes of Generated Key
+
+ As a result of this message exchange, client comes to know the newly
+ generated key's attributes such as key's name, Inception Time and
+ Expiry Limit. They are decided by the server and told to the client;
+ in particular, however, once the server has decided Expiry Limit and
+ returned a response, it should obey the decision as far as it can. In
+ other words, they SHOULD NOT change time values for checking Expiry
+ Limit in the future without any special reason, such as security
+ issue like "Emergency Compulsory Revocation" described in section 8.
+
+ On the other hand, Partial Revocation Time of this generated key is
+ not decided based on the request, and not informed to the client. The
+ server can determine any value as long as it is between Inception
+ Time and Expiry Limit. However, the period from Inception to Partial
+ Revocation SHOULD be fixed as the server side's configuration or be
+ set the same as the corresponding old key's one.
+
+ Note:
+ Even if client sends Key Renewal request though the key described
+ in OldName has not been partially revoked yet, server does renewal
+ processes. At the moment when the server accepts such requests
+ with valid authentication, it MUST forcibly consider the key is
+ already partially revoked, that is, the key's Partial Revocation
+ Time must be changed into the present time (i.e., the time when
+ the server receives the request).
+
+
+2.3.4. TKEY RR structure
+
+ TKEY RR for Key Renewal message has the structure given below. In
+ principle, format and definition for each field follows [RFC2930].
+ Note that each keying scheme sometimes needs different interpretation
+ of RDATA field; for detail, see section 2.5.
+
+ Field Type Comment
+ ------- ------ -------
+ NAME domain used for a new key, see below
+ TYPE u_int16_t (defined in [RFC2930])
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 8]
+
+INTERNET-DRAFT October 2004
+
+
+ CLASS u_int16_t (defined in [RFC2930])
+ TTL u_int32_t (defined in [RFC2930])
+ RDLEN u_int16_t (defined in [RFC2930])
+ RDATA:
+ Algorithm: domain algorithm for a new key
+ Inception: u_int32_t about the keying material
+ Expiration: u_int32_t about the keying material
+ Mode: u_int16_t scheme for key agreement
+ see section 9.
+ Error: u_int16_t see description below
+ Key Size: u_int16_t see description below
+ Key Data: octet-stream
+ Other Size: u_int16_t (defined in [RFC2930])
+ size of other data
+ Other Data: newly defined: see description below
+
+
+ For "NAME" field, both non-root and root name are allowed. It may
+ be used for a new key's name in the same manner as [RFC2930] 2.1.
+
+ "Algorithm" specifies which algorithm is used for agreed keying
+ material, which is used for identification of the next key.
+
+ "Inception" and "Expiration" are used for the valid period of
+ keying material. The meanings differ somewhat according to whether
+ the message is request or answer, and its keying scheme.
+
+ "Key Data" has different meanings according to keying schemes.
+
+ "Mode" field stores the value in accordance with the keying method,
+ and see section 2.5. Servers and clients supporting TKEY Renewal
+ method MUST implement "Diffie-Hellman exchange for key renewal"
+ scheme. All other modes are OPTIONAL.
+
+ "Error" is an extended RCODE which includes "PartialRevoke" value
+ too. See section 9.
+
+ "Other Data" field has the structure given below. They describe
+ attributes of the key to be renewed.
+
+ in Other Data filed:
+
+ Field Type Comment
+ ------- ------ -------
+ OldNAME domain name of the old key
+ OldAlgorithm domain algorithm of the old key
+
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 9]
+
+INTERNET-DRAFT October 2004
+
+
+ "OldName" indicates the name of the previous key (usually,
+ this is partially revoked key's name that client noticed by
+ PartialRevoke answer from server), and "OldAlogirthm"
+ indicates its algorithm.
+
+
+2.4. Key Adoption
+
+2.4.1. Query for Key Adoption
+
+ After receiving a TKEY Renewal answer, the client gets the same
+ secret as the server. Then, it sends a TKEY Adoption request. The
+ request's question section's QNAME field is the same as the NAME
+ filed of TKEY written below. In additional section, there is one TKEY
+ RR that has the structure and values described below.
+
+ "NAME" field is the new key's name to be adopted which was already
+ generated by Renewal message exchange. "Algorithm" is its
+ algorithm. "Inception" means the key's Inception Time, and
+ "Expiration" means Expiry Limit.
+
+ "Mode" field is the value of "key adoption". See section 9.
+
+ "Other Data" field in Adoption has the same structure as that of
+ Renewal request message. "OldName" means the previous old key, and
+ "OldAlogirthm" means its algorithm.
+
+ Key Adoption request MUST be signed with TSIG or SIG(0) for
+ authentication. The client can sign TSIG with the previous key. Note
+ that until Adoption is finished, the new key is treated as invalid,
+ thus it cannot be used for authentication immediately.
+
+
+2.4.2. Response for Key Adoption
+
+ The server which has received Adoption request, it verifies TSIG or
+ SIG(0) accompanying it. If the TSIG is signed with the partially
+ revoked key and can be verified, the message MUST be authenticated.
+
+ If the next new key indicated by the request TKEY's "NAME" is not
+ present at the server, BADNAME [RFC2845] is given in Error field and
+ the error message is returned.
+
+ If the next key exists but it has not been adopted formally yet, the
+ server confirms the previous key's existence indicated by the
+ "OldName" and "OldAlgorithm" field. If it succeeds, the server
+ executes Adoption of the next key and Revocation of the previous key.
+ Response message duplicates the request's TKEY RR with NOERROR,
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 10]
+
+INTERNET-DRAFT October 2004
+
+
+ including "OldName" and "OldAlgorithm" that indicate the revoked key.
+
+ If the next key exists but it is already adopted, the server returns
+ a response message regardless of the substance of the request TKEY's
+ "OldName". In this response, Response TKEY RR has the same data as
+ the request's one except as to its "Other Data" that is changed into
+ null (i.e., "Other Size" is zero), which is intended for telling the
+ client that the previous key name was ignored, and the new key is
+ already available.
+
+ Client sometimes has to retry Adoption request. Suppose the client
+ sent request signed with the partially revoked key, but its response
+ did not return successfully (e.g., due to the drop of UDP packet).
+ Client will probably retry Adoption request; however, the request
+ will be refused in the form of TSIG "BADKEY" error because the
+ previous key was already revoked. In this case, client will
+ retransmit Adoption request signed with the next key, and expect a
+ response which has null "Other Data" for confirming the completion of
+ renewal.
+
+
+2.5. Keying Schemes
+
+ In Renewal message exchanges, there are no limitations as to which
+ keying method is actually used. The specification of keying
+ algorithms is independent of the general procedure of Renewal that is
+ described in section 2.3.
+
+ Now this document specifies three algorithms in this section, but
+ other future documents can make extensions defining other methods.
+
+
+2.5.1. DH Exchange for Key Renewal
+
+ This scheme is defined as an extended method of [RFC2930] 4.1. This
+ specification only describes the difference from it and special
+ notice; assume that all other points, such as keying material
+ computation, are the exactly same as the specification of [RFC2930]
+ 4.1.
+
+ Query
+ In Renewal request for type TKEY with this mode, there is one TKEY
+ RR and one KEY RR in the additional information section. KEY RR is
+ the client's Diffie-Hellman public key [RFC2539].
+
+ QNAME in question section is the same as that of "NAME" field in
+ TKEY RR, i.e., it means the requested new key's name.
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 11]
+
+INTERNET-DRAFT October 2004
+
+
+ TKEY "Mode" field stores the value of "DH exchange for key
+ renewal". See section 9.
+
+ TKEY "Inception" and "Expiration" are those requested for the
+ keying material, that is, requested usage period of a new key.
+
+ TKEY "Key Data" is used as a random, following [RFC2930] 4.1.
+
+ Response
+ The server which received this request first verifies the TSIG,
+ SIG(0) or DNSSEC lookup of KEY RR used. After authentication, the
+ old key's existence validity is checked, following section 2.3. If
+ any incompatible DH key is found in the request, "BADKEY"
+ [RFC2845] is given in Error field for response. "FORMERR" is given
+ if the query included no DH KEY.
+
+ If there are no errors, the server processes a response according
+ to Diffie-Hellman algorithm and returns the answer. In this
+ answer, there is one TKEY RR in answer section and KEY RR(s) in
+ additional section.
+
+ As long as no error has occurred, all values of TKEY are equal to
+ that of the request message except TKEY NAME, TKEY RDLEN, RDATA's
+ Inception, Expiration, Key Size and Key Data.
+
+ TKEY "NAME" field in the answer specifies the name of newly
+ produced key which the client MUST use.
+
+ TKEY "Inception" and "Expiration" mean the periods of the produced
+ key usage. "Inception" is set to be the time when the new key is
+ actually generated or the time before it, and it will be regarded
+ as Inception Time. "Expiration" is determined by the server, and
+ it will be regarded as Expiry Limit.
+
+ TKEY "Key Data" is used as an additional nonce, following
+ [RFC2930] 4.1.
+
+ The resolver supplied Diffie-Hellman KEY RR SHOULD be echoed in
+ the additional section and a server Diffie-Hellman KEY RR will
+ also be present in the answer section, following [RFC2930] 4.1.
+
+
+2.5.2. Server Assigned Keying for Key Renewal
+
+ This scheme is defined as an extended method of [RFC2930] 4.4. This
+ specification only describes the difference from it and special
+ notice; assume that all other points, such as secret encrypting
+ method, are the exactly same as the specification of [RFC2930] 4.4.
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 12]
+
+INTERNET-DRAFT October 2004
+
+
+ Query
+ In Renewal request for type TKEY with this mode, there is one TKEY
+ RR and one KEY RR in the additional information section. KEY RR is
+ used in encrypting the response.
+
+ QNAME in question section is the same as that of "NAME" field in
+ TKEY RR, i.e., it means the requested new key's name.
+
+ TKEY "Mode" field stores the value of "server assignment for key
+ renewal". See section 9.
+
+ TKEY "Inception" and "Expiration" are those requested for the
+ keying material, that is, requested usage period of a new key.
+
+ TKEY "Key Data" is provided following the specification of
+ [RFC2930] 4.4.
+
+ Response
+ The server which received this request first verifies the TSIG,
+ SIG(0) or DNSSEC lookup of KEY RR used. After authentication, the
+ old key's existence validity is checked, following section 2.3.
+ "FORMERR" is given if the query specified no encryption key.
+
+ If there are no errors, the server response contains one TKEY RR
+ in the answer section, and echoes the KEY RR provided in the query
+ in the additional information section.
+
+ TKEY "NAME" field in the answer specifies the name of newly
+ produced key which the client MUST use.
+
+ TKEY "Inception" and "Expiration" mean the periods of the produced
+ key usage. "Inception" is set to be the time when the new key is
+ actually generated or the time before it, and it will be regarded
+ as Inception Time. "Expiration" is determined by the server, and
+ it will be regarded as Expiry Limit.
+
+ TKEY "Key Data" is the assigned keying data encrypted under the
+ public key in the resolver provided KEY RR, which is the same as
+ [RFC2930] 4.4.
+
+
+2.5.3. Resolver Assigned Keying for Key Renewal
+
+ This scheme is defined as an extended method of [RFC2930] 4.5. This
+ specification only describes the difference from it and special
+ notice; assume that all other points, such as secret encrypting
+ method, are the exactly same as the specification of [RFC2930] 4.5.
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 13]
+
+INTERNET-DRAFT October 2004
+
+
+ Query
+ In Renewal request for type TKEY with this mode, there is one TKEY
+ RR and one KEY RR in the additional information section. TKEY RR
+ has the encrypted keying material and KEY RR is the server public
+ key used to encrypt the data.
+
+ QNAME in question section is the same as that of "NAME" field in
+ TKEY RR, i.e., it means the requested new key's name.
+
+ TKEY "Mode" field stores the value of "resolver assignment for key
+ renewal". See section 9.
+
+ TKEY "Inception" and "Expiration" are those requested for the
+ keying material, that is, requested usage period of a new key.
+
+ TKEY "Key Data" is the encrypted keying material.
+
+ Response
+ The server which received this request first verifies the TSIG,
+ SIG(0) or DNSSEC lookup of KEY RR used. After authentication, the
+ old key's existence validity is checked, following section 2.3.
+ "FORMERR" is given if the server does not have the corresponding
+ private key for the KEY RR that was shown sin the request.
+
+ If there are no errors, the server returns a response. The
+ response contains a TKEY RR in the answer section to tell the
+ shared key's name and its usage time values.
+
+ TKEY "NAME" field in the answer specifies the name of newly
+ produced key which the client MUST use.
+
+ TKEY "Inception" and "Expiration" mean the periods of the produced
+ key usage. "Inception" is set to be the time when the new key is
+ actually generated or the time before it, and it will be regarded
+ as Inception Time. "Expiration" is determined by the server, and
+ it will be regarded as Expiry Limit.
+
+
+2.6. Considerations about Non-compliant Hosts
+
+ Key Renewal requests and responses must be exchanged between hosts
+ which can understand them and do proper processes. PartialRevoke
+ error messages will be only ignored if they should be returned to
+ non-compliant hosts.
+
+ Note that server does not inform actively the necessity of renewal to
+ clients, but inform it as responses invoked by client's query.
+ Server needs not care whether the PartialRevoke errors has reached
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 14]
+
+INTERNET-DRAFT October 2004
+
+
+ client or not. If client has not received yet because of any reasons
+ such as packet drops, it will resend the queries, and finally will be
+ able to get PartialRevoke information.
+
+
+3. Secret Storage
+
+ Every server keeps all secrets and attached information, e.g.,
+ Inception Time, Expiry Limit, etc. safely to be able to recover from
+ unexpected stop. To accomplish this, formally adopted keys SHOULD be
+ memorized not only on memory, but also be stored in the form of some
+ files. It will become more secure if they are stored in ecrypted
+ form.
+
+
+4. Compulsory Key Revocation
+
+4.1. Compulsory Key Revocation by Server
+
+ There is a rare but possible case that although servers have already
+ partially revoked keys, clients do not try to send any Renewal
+ requests. If this state continues, in the future it will become the
+ time of Expiry Limit. After Expiry Limit, the keys will be expired
+ and completely removed, so this is called Compulsory Key Revocation
+ by server.
+
+ If Expiry Limit is too distant from the Partial Revocation Time, then
+ even though very long time passes, clients will be able to refresh
+ secrets only if they add TSIG signed with those old partially revoked
+ keys into requests, which is not safe.
+
+ On the other hand, if Expiry Limit is too close to Partial Revocation
+ Time, perhaps clients might not be able to notice their keys' Partial
+ Revocation by getting "PartialRevoke" errors.
+
+ Therefore, servers should set proper Expiry Limit to their keys,
+ considering both their keys' safety, and enough time for clients to
+ send requests and process renewal.
+
+
+4.2. Authentication Methods Considerations
+
+ It might be ideal to provide both SIG(0) and TSIG as authentication
+ methods. For example:
+
+ A client and a server start SIG(0) authentication at first, to
+ establish TSIG shared keys by means of "Query for Diffie-Hellman
+ Exchanged Keying" as described in [RFC2930] 4.1. Once they get
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 15]
+
+INTERNET-DRAFT October 2004
+
+
+ shared secret, they keep using TSIG for queries and responses.
+ After a while the server returns a "ParitalRevoke" error and they
+ begin a key renewal process. Both TSIG signed with partially
+ revoked keys and SIG(0) are okay for authentication, but TSIG would
+ be easier to use considering calculation efficiency.
+
+ Suppose now client is halted for long time with some reason.
+ Because server does not execute any renewal process, it will
+ finally do Compulsory Revocation. Even if client restarts and sends
+ a key Renewal request, it will fail because old key is already
+ deleted at server.
+
+ At this moment, however, if client also uses SIG(0) as another
+ authentication method, it can make a new shared key again and
+ recover successfully by sending "Query for Diffie-Hellman Exchanged
+ Keying" with SIG(0).
+
+
+5. Special Considerations for Two servers' Case
+
+ This section refers to the case where both hosts are DNS servers
+ which can act as full resolvers as well and using one shared key
+ only. If one server (called Server A) wants to refresh a shared key
+ (called "Key A-B"), it will await a TKEY Renewal request from the
+ other server (called Server B). However, perhaps Server A wants to
+ refresh the key right now.
+
+ In this case, Server A is allowed to send a Renewal request to Server
+ B, if Server A knows the Key A-B is too old and wants to renew it
+ immediately.
+
+ Note that the initiative in key renewal belongs to Server A because
+ it can notice the Partial Revocation Time and decide key renewal. If
+ Server B has information about Partial Revocation Time as well, it
+ can also decide for itself to send Renewal request to Server A.
+ However, it is not essential for both two servers have information
+ about key renewal timing.
+
+5.1. To Cope with Collisions of Renewal Requests
+
+ At least one of two hosts which use Key Renewal must know their key
+ renewal information such as Partial Revocation Time. It is okay that
+ both hosts have it.
+
+ Provided that both two servers know key renewal timing information,
+ there is possibility for them to begin partial revocation and sending
+ Renewal requests to each other at the same time. Such collisions will
+ not happen so often because Renewal requests are usually invoked when
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 16]
+
+INTERNET-DRAFT October 2004
+
+
+ hosts want to send queries, but it is possible.
+
+ When one of two servers tries to send Renewal requests, it MUST
+ protect old secrets that it has partially revoked and prevent it from
+ being refreshed by any requests from the other server (i.e., it must
+ lock the old secret during the process of renewal). While the server
+ is sending Renewal requests and waiting responses, it ignores the
+ other server's Renewal requests.
+
+ Therefore, servers might fail to change secrets by means of their own
+ requests to others. After failure they will try to resend, but they
+ should wait for random delays by the next retries. If they get any
+ Renewal requests from others while they are waiting, their shared
+ keys may be refreshed, then they do not need to send any Renewal
+ requests now for themselves.
+
+
+6. Key Name Considerations
+
+ Since both servers and clients have only to distinguish new secrets
+ and old ones, keys' names do not need to be specified strictly.
+ However, it is recommended that some serial number or key generation
+ time be added to the name and that the names of keys between the same
+ pair of hosts should have some common labels among their keys. For
+ example, suppose A.example.com. and B.example.com. share the key
+ "<serial number>.A.example.com.B.example.com." such as
+ "10010.A.example.com.B.example.com.". After key renewal, they change
+ their secret and name into "10011.A.example.com.B.example.com."
+
+ Servers and clients must be able to use keys properly for each query.
+ Because TSIG secret keys themselves do not have any particular IDs to
+ be distinguished and would be identified by their names and
+ algorithm, it must be understood correctly what keys are refreshed.
+
+
+7. Example Usage of Secret Key Renewal Mode
+
+ This is an example of Renewal mode usage where a Server,
+ server.example.com, and a Client, client.exmple.com have an initial
+ shared secret key named "00.client.example.com.server.example.com".
+
+ (1) The time values for key
+ "00.client.example.com.server.example.com" was set as follows:
+ Inception Time is at 1:00, Expiry Limit is at 21:00.
+
+ (2) At Server, renewal time has been set: Partial Revocation Time
+ is at 20:00.
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 17]
+
+INTERNET-DRAFT October 2004
+
+
+ (3) Suppose the present time is 19:55. If Client sends a query
+ signed with key "00.client.example.com.server.example.com" to ask
+ the IP address of "www.example.com", finally it will get a proper
+ answer from Server with valid TSIG (NOERROR).
+
+ (4) At 20:05. Client sends a query to ask the IP address of
+ "www2.example.com". It is signed with key
+ "00.client.example.com.server.example.com". Server returns an
+ answer for the IP address. However, server has begun retuning
+ PartialRevoke Error randomely. This answer includes valid TSIG MAC
+ signed with "00.client.example.com.server.example.com", and its
+ Error Code indicates PartialRevoke. Client understands that the
+ current key is partially revoked.
+
+ (5) At 20:06. Client sends a Renewal request to Server. This
+ request is signed with key
+ "00.client.example.com.server.example.com". It includes data such
+ as:
+
+ Question Section:
+ QNAME = 01.client.example.com. (Client can set this freely)
+ TYPE = TKEY
+
+ Additional Section:
+ 01.client.example.com. TKEY
+ Algorithm = hmac-md5-sig-alg.reg.int.
+ Inception = (value meaning 20:00)
+ Expiration = (value meaning next day's 16:00)
+ Mode = (DH exchange for key renewal)
+ OldName = 00.client.example.com.server.example.com.
+ OldAlgorithm = hmac-md5-sig-alg.reg.int.
+
+ Additional Section also contains a KEY RR for DH and a TSIG RR.
+
+ (6) As soon as Server receives this request, it verifies TSIG. It
+ is signed with the partially revoked key
+ "00.client.example.com.server.example.com". and Server accepts the
+ request. It creates a new key by Diffie-Hellman calculation and
+ returns an answer which includes data such as:
+
+ Answer Section:
+ 01.client.example.com.server.example.com. TKEY
+ Algorithm = hmac-md5-sig-alg.reg.int.
+ Inception = (value meaning 20:00)
+ Expiration = (value meaning next day's 16:00)
+ Mode = (DH exchange for key renewal)
+ OldName = 00.client.example.com.server.example.com.
+ OldAlgorithm = hmac-md5-sig-alg.reg.int.
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 18]
+
+INTERNET-DRAFT October 2004
+
+
+ Answer Section also contains KEY RRs for DH.
+
+ Additional Section also contains a TSIG RR.
+ This response is signed with key
+ "00.client.example.com.server.example.com" without error.
+
+ At the same time, Server decides to set the Partial Revocation Time
+ of this new key "01.client.example.com.server.example.com." as next
+ day's 15:00.
+
+ (7) Client gets the response and checks TSIG MAC, and calculates
+ Diffie-Hellman. It will get a new key, and it has been named
+ "01.client.example.com.server.example.com" by Server.
+
+ (8) At 20:07. Client sends an Adoption request to Server. This
+ request is signed with the previous key
+ "00.client.example.com.server.example.com". It includes:
+
+ Question Section:
+ QNAME = 01.client.example.com.server.example.com.
+ TYPE = TKEY
+
+ Additional Section:
+ 01.client.example.com.server.example.com. TKEY
+ Algorithm = hmac-md5-sig-alg.reg.int.
+ Inception = (value meaning 20:00)
+ Expiration = (value meaning next day's 16:00)
+ Mode = (key adoption)
+ OldName = 00.client.example.com.server.example.com.
+ OldAlgorithm = hmac-md5-sig-alg.reg.int.
+
+ Additional Section also contains a TSIG RR.
+
+ (9) Server verifies the query's TSIG. It is signed with the
+ previous key and authenticated. It returns a response whose TKEY RR
+ is the same as the request's one. The response is signed with key
+ "00.client.example.com.server.example.com.". As soon as the
+ response is sent, Server revokes and removes the previous key. At
+ the same time, key "01.client.example.com.server.example.com." is
+ validated.
+
+ (10) Client acknowledges the success of Adoption by receiving the
+ response. Then, it retries to send an original question about
+ "www2.example.com". It is signed with the adopted key
+ "01.client.example.com.server.example.com", so Server authenticates
+ it and returns an answer.
+
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 19]
+
+INTERNET-DRAFT October 2004
+
+
+ (11) This key is used until next day's 15:00. After that, it will
+ be partially revoked again.
+
+
+8. Security Considerations
+
+ This document considers about how to refresh shared secret. Secret
+ changed by this method is used at servers in support of TSIG
+ [RFC2845].
+
+ [RFC2104] says that current attacks to HMAC do not indicate a
+ specific recommended frequency for key changes but periodic key
+ refreshment is a fundamental security practice that helps against
+ potential weaknesses of the function and keys, and limits the damage
+ of an exposed key. TKEY Secret Key Renewal provides the method of
+ periodical key refreshment.
+
+ In TKEY Secret Key Renewal, clients need to send two requests
+ (Renewal and Adoption) and spend time to finish their key renewal
+ processes. Thus the usage period of secrets should be considered
+ carefully based on both TKEY processing performance and security.
+
+ This document specifies the procedure of periodical key renewal, but
+ actually there is possibility for servers to have no choice other
+ than revoking their secret keys immediately especially when the keys
+ are found to be compromised by attackers. This is called "Emergency
+ Compulsory Revocation". For example, suppose the original Expiry
+ Limit was set at 21:00, Partial Revocation Time at 20:00 and
+ Inception Time at 1:00. if at 11:00 the key is found to be
+ compromised, the server sets Expiry Limit forcibly to be 11:00 or
+ before it.
+
+ Consequently, once Compulsory Revocation (See section 4.) is carried
+ out, normal renewal process described in this document cannot be done
+ any more as far as the key is concerned. However, after such
+ accidents happened, the two hosts are able to establish secret keys
+ and begin renewal procedure only if they have other (non-compromised)
+ shared TSIG keys or safe SIG(0) keys for the authentication of
+ initial secret establishment such as Diffie-Hellman Exchanged Keying.
+
+
+9. IANA Considerations
+
+ IANA needs to allocate a value for "DH exchange for key renewal",
+ "server assignment for key renewal", "resolver assignment for key
+ renewal" and "key adoption" in the mode filed of TKEY. It also needs
+ to allocate a value for "PartialRevoke" from the extended RCODE
+ space.
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 20]
+
+INTERNET-DRAFT October 2004
+
+
+10. Acknowledgements
+
+ The authors would like to thank Olafur Gudmundsson, whose helpful
+ input and comments contributed greatly to this document.
+
+
+11. References
+
+11.1. Normative References
+
+[RFC2119]
+ Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", RFC 2119, March 1997.
+
+[RFC2539]
+ D. Eastlake 3rd, "Storage of Diffie-Hellman Keys in the Domain Name
+ System (DNS)", RFC 2539, March 1999.
+
+[RFC2845]
+ Vixie, P., Gudmundsson, O., Eastlake, D. and B. Wellington,
+ "Secret Key Transaction Authentication for DNS (TSIG)", RFC 2845,
+ May 2000.
+
+[RFC2930]
+ D. Eastlake 3rd, ``Secret Key Establishment for DNS (TKEY RR)'',
+ RFC 2930, September 2000.
+
+[RFC2931]
+ D. Eastlake 3rd, "DNS Request and Transaction Signatures (SIG(0)s
+ )", RFC 2931, September 2000.
+
+11.2. Informative References
+
+[RFC2104]
+ H. Krawczyk, M.Bellare, R. Canetti, "Keyed-Hashing for Message
+ Authentication", RFC2104, February 1997.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 21]
+
+INTERNET-DRAFT October 2004
+
+
+Authors' Addresses
+
+ Yuji Kamite
+ NTT Communications Corporation
+ Tokyo Opera City Tower
+ 3-20-2 Nishi Shinjuku, Shinjuku-ku, Tokyo
+ 163-1421, Japan
+ EMail: y.kamite@ntt.com
+
+
+ Masaya Nakayama
+ Information Technology Center, The University of Tokyo
+ 2-11-16 Yayoi, Bunkyo-ku, Tokyo
+ 113-8658, Japan
+ EMail: nakayama@nc.u-tokyo.ac.jp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 22]
+
+INTERNET-DRAFT October 2004
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2004). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Kamite, et. al. Expires April 15, 2005 [Page 23]
+
+
+
diff --git a/doc/draft/draft-ietf-dnsext-trustupdate-threshold-00.txt b/doc/draft/draft-ietf-dnsext-trustupdate-threshold-00.txt
new file mode 100644
index 0000000..eaf6865
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-trustupdate-threshold-00.txt
@@ -0,0 +1,1501 @@
+Network Working Group J. Ihren
+Internet-Draft Autonomica AB
+Expires: April 18, 2005 O. Kolkman
+ RIPE NCC
+ B. Manning
+ EP.net
+ October 18, 2004
+
+
+
+ An In-Band Rollover Mechanism and an Out-Of-Band Priming Method for
+ DNSSEC Trust Anchors.
+ draft-ietf-dnsext-trustupdate-threshold-00
+
+
+Status of this Memo
+
+
+ By submitting this Internet-Draft, I certify that any applicable
+ patent or other IPR claims of which I am aware have been disclosed,
+ and any of which I become aware will be disclosed, in accordance with
+ RFC 3668.
+
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as
+ Internet-Drafts.
+
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+
+ This Internet-Draft will expire on April 18, 2005.
+
+
+Copyright Notice
+
+
+ Copyright (C) The Internet Society (2004). All Rights Reserved.
+
+
+Abstract
+
+
+ The DNS Security Extensions (DNSSEC) works by validating so called
+ chains of authority. The start of these chains of authority are
+ usually public keys that are anchored in the DNS clients. These keys
+ are known as the so called trust anchors.
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 1]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ This memo describes a method how these client trust anchors can be
+ replaced using the DNS validation and querying mechanisms (in-band)
+ when the key pairs used for signing by zone owner are rolled.
+
+
+ This memo also describes a method to establish the validity of trust
+ anchors for initial configuration, or priming, using out of band
+ mechanisms.
+
+
+Table of Contents
+
+
+ 1. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1 Key Signing Keys, Zone Signing Keys and Secure Entry
+ Points . . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Introduction and Background . . . . . . . . . . . . . . . . . 5
+ 2.1 Dangers of Stale Trust Anchors . . . . . . . . . . . . . . 5
+ 3. Threshold-based Trust Anchor Rollover . . . . . . . . . . . . 7
+ 3.1 The Rollover . . . . . . . . . . . . . . . . . . . . . . . 7
+ 3.2 Threshold-based Trust Update . . . . . . . . . . . . . . . 8
+ 3.3 Possible Trust Update States . . . . . . . . . . . . . . . 9
+ 3.4 Implementation notes . . . . . . . . . . . . . . . . . . . 10
+ 3.5 Possible transactions . . . . . . . . . . . . . . . . . . 11
+ 3.5.1 Single DNSKEY replaced . . . . . . . . . . . . . . . . 12
+ 3.5.2 Addition of a new DNSKEY (no removal) . . . . . . . . 12
+ 3.5.3 Removal of old DNSKEY (no addition) . . . . . . . . . 12
+ 3.5.4 Multiple DNSKEYs replaced . . . . . . . . . . . . . . 12
+ 3.6 Removal of trust anchors for a trust point . . . . . . . . 12
+ 3.7 No need for resolver-side overlap of old and new keys . . 13
+ 4. Bootstrapping automatic rollovers . . . . . . . . . . . . . . 14
+ 4.1 Priming Keys . . . . . . . . . . . . . . . . . . . . . . . 14
+ 4.1.1 Bootstrapping trust anchors using a priming key . . . 14
+ 4.1.2 Distribution of priming keys . . . . . . . . . . . . . 15
+ 5. The Threshold Rollover Mechanism vs Priming . . . . . . . . . 16
+ 6. Security Considerations . . . . . . . . . . . . . . . . . . . 17
+ 6.1 Threshold-based Trust Update Security Considerations . . . 17
+ 6.2 Priming Key Security Considerations . . . . . . . . . . . 17
+ 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 19
+ 8. References . . . . . . . . . . . . . . . . . . . . . . . . . . 20
+ 8.1 Normative References . . . . . . . . . . . . . . . . . . . . 20
+ 8.2 Informative References . . . . . . . . . . . . . . . . . . . 20
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 20
+ A. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 22
+ B. Document History . . . . . . . . . . . . . . . . . . . . . . . 23
+ B.1 prior to version 00 . . . . . . . . . . . . . . . . . . . 23
+ B.2 version 00 . . . . . . . . . . . . . . . . . . . . . . . . 23
+ Intellectual Property and Copyright Statements . . . . . . . . 24
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 2]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+1. Terminology
+
+
+ The key words "MUST", "SHALL", "REQUIRED", "SHOULD", "RECOMMENDED",
+ and "MAY" in this document are to be interpreted as described in
+ RFC2119 [1].
+
+
+ The term "zone" refers to the unit of administrative control in the
+ Domain Name System. In this document "name server" denotes a DNS
+ name server that is authoritative (i.e. knows all there is to know)
+ for a DNS zone. A "zone owner" is the entity responsible for signing
+ and publishing a zone on a name server. The terms "authentication
+ chain", "bogus", "trust anchors" and "Island of Security" are defined
+ in [4]. Throughout this document we use the term "resolver" to mean
+ "Validating Stub Resolvers" as defined in [4].
+
+
+ We use the term "security apex" as the zone for which a trust anchor
+ has been configured (by validating clients) and which is therefore,
+ by definition, at the root of an island of security. The
+ configuration of trust anchors is a client side issue. Therefore a
+ zone owner may not always know if their zone has become a security
+ apex.
+
+
+ A "stale anchor" is a trust anchor (a public key) that relates to a
+ key that is not used for signing. Since trust anchors indicate that
+ a zone is supposed to be secure a validator will mark the all data in
+ an island of security as bogus when all trust anchors become stale.
+
+
+ It is assumed that the reader is familiar with public key
+ cryptography concepts [REF: Schneier Applied Cryptography] and is
+ able to distinguish between the private and public parts of a key
+ based on the context in which we use the term "key". If there is a
+ possible ambiguity we will explicitly mention if a private or a
+ public part of a key is used.
+
+
+ The term "administrator" is used loosely throughout the text. In
+ some cases an administrator is meant to be a person, in other cases
+ the administrator may be a process that has been delegated certain
+ responsibilities.
+
+
+1.1 Key Signing Keys, Zone Signing Keys and Secure Entry Points
+
+
+ Although the DNSSEC protocol does not make a distinction between
+ different keys the operational practice is that a distinction is made
+ between zone signing keys and key signing keys. A key signing key is
+ used to exclusively sign the DNSKEY Resource Record (RR) set at the
+ apex of a zone and the zone signing keys sign all the data in the
+ zone (including the DNSKEY RRset at the apex).
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 3]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ Keys that are intended to be used as the start of the authentication
+ chain for a particular zone, either because they are pointed to by a
+ parental DS RR or because they are configured as a trust anchor, are
+ called Secure Entry Point (SEP) keys. In practice these SEP keys
+ will be key signing keys.
+
+
+ In order for the mechanism described herein to work the keys that are
+ intended to be used as secure entry points MUST have the SEP [2] flag
+ set. In the examples it is assumed that keys with the SEP flag set
+ are used as key signing keys and thus exclusively sign the DNSKEY
+ RRset published at the apex of the zone.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 4]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+2. Introduction and Background
+
+
+ When DNSSEC signatures are validated the resolver constructs a chain
+ of authority from a pre-configured trust anchor to the DNSKEY
+ Resource Record (RR), which contains the public key that validates
+ the signature stored in an RRSIG RR. DNSSEC is designed so that the
+ administrator of a resolver can validate data in multiple islands of
+ security by configuring multiple trust anchors.
+
+
+ It is expected that resolvers will have more than one trust anchor
+ configured. Although there is no deployment experience it is not
+ unreasonable to expect resolvers to be configured with a number of
+ trust anchors that varies between order 1 and order 1000. Because
+ zone owners are expected to roll their keys, trust anchors will have
+ to be maintained (in the resolver end) in order not to become stale.
+
+
+ Since there is no global key maintenance policy for zone owners and
+ there are no mechanisms in the DNS to signal the key maintenance
+ policy it may be very hard for resolvers administrators to keep their
+ set of trust anchors up to date. For instance, if there is only one
+ trust anchor configured and the key maintenance policy is clearly
+ published, through some out of band trusted channel, then a resolver
+ administrator can probably keep track of key rollovers and update the
+ trust anchor manually. However, with an increasing number of trust
+ anchors all rolled according to individual policies that are all
+ published through different channels this soon becomes an
+ unmanageable problem.
+
+
+2.1 Dangers of Stale Trust Anchors
+
+
+ Whenever a SEP key at a security apex is rolled there exists a danger
+ that "stale anchors" are created. A stale anchor is a trust anchor
+ (i.e. a public key configured in a validating resolver) that relates
+ to a private key that is no longer used for signing.
+
+
+ The problem with a stale anchors is that they will (from the
+ validating resolvers point of view) prove data to be false even
+ though it is actually correct. This is because the data is either
+ signed by a new key or is no longer signed and the resolver expects
+ data to be signed by the old (now stale) key.
+
+
+ This situation is arguably worse than not having a trusted key
+ configured for the secure entry point, since with a stale key no
+ lookup is typically possible (presuming that the default
+ configuration of a validating recursive nameserver is to not give out
+ data that is signed but failed to verify.
+
+
+ The danger of making configured trust anchors become stale anchors
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 5]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ may be a reason for zone owners not to roll their keys. If a
+ resolver is configured with many trust anchors that need manual
+ maintenance it may be easy to not notice a key rollover at a security
+ apex, resulting in a stale anchor.
+
+
+ In Section 3 this memo sets out a lightweight, in-DNS, mechanism to
+ track key rollovers and modify the configured trust anchors
+ accordingly. The mechanism is stateless and does not need protocol
+ extensions. The proposed design is that this mechanism is
+ implemented as a "trust updating machine" that is run entirely
+ separate from the validating resolver except that the trust updater
+ will have influence over the trust anchors used by the latter.
+
+
+ In Section 4 we describe a method [Editors note: for now only the
+ frame work and a set of requirements] to install trust anchors. This
+ method can be used at first configuration or when the trust anchors
+ became stale (typically due to a failure to track several rollover
+ events).
+
+
+ The choice for which domains trust anchors are to be configured is a
+ local policy issue. So is the choice which trust anchors has
+ prevalence if there are multiple chains of trust to a given piece of
+ DNS data (e.g. when a parent zone and its child both have trust
+ anchors configured). Both issues are out of the scope of this
+ document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 6]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+3. Threshold-based Trust Anchor Rollover
+
+
+3.1 The Rollover
+
+
+ When a key pair is replaced all signatures (in DNSSEC these are the
+ RRSIG records) created with the old key will be replaced by new
+ signatures created by the new key. Access to the new public key is
+ needed to verify these signatures.
+
+
+ Since zone signing keys are in "the middle" of a chain of authority
+ they can be verified using the signature made by a key signing key.
+ Rollover of zone signing keys is therefore transparent to validators
+ and requires no action in the validator end.
+
+
+ But if a key signing key is rolled a resolver can determine its
+ authenticity by either following the authorization chain from the
+ parents DS record, an out-of-DNS authentication mechanism or by
+ relying on other trust anchors known for the zone in which the key is
+ rolled.
+
+
+ The threshold trust anchor rollover mechanism (or trust update),
+ described below, is based on using existing trust anchors to verify a
+ subset of the available signatures. This is then used as the basis
+ for a decision to accept the new keys as valid trust anchors.
+
+
+ Our example pseudo zone below contains a number of key signing keys
+ numbered 1 through Y and two zone signing keys A and B. During a key
+ rollover key 2 is replaced by key Y+1. The zone content changes
+ from:
+
+
+ example.com. DNSKEY key1
+ example.com. DNSKEY key2
+ example.com. DNSKEY key3
+ ...
+ example.com. DNSKEY keyY
+
+
+ example.com. DNSKEY keyA
+ example.com. DNSKEY keyB
+
+
+ example.com. RRSIG DNSKEY ... (key1)
+ example.com. RRSIG DNSKEY ... (key2)
+ example.com. RRSIG DNSKEY ... (key3)
+ ...
+ example.com. RRSIG DNSKEY ... (keyY)
+ example.com. RRSIG DNSKEY ... (keyA)
+ example.com. RRSIG DNSKEY ... (keyB)
+
+
+ to:
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 7]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ example.com. DNSKEY key1
+ example.com. DNSKEY key3
+ ...
+ example.com. DNSKEY keyY
+ example.com. DNSKEY keyY+1
+
+
+ example.com. RRSIG DNSKEY ... (key1)
+ example.com. RRSIG DNSKEY ... (key3)
+ ...
+ example.com. RRSIG DNSKEY ... (keyY)
+ example.com. RRSIG DNSKEY ... (keyY+1)
+ example.com. RRSIG DNSKEY ... (keyA)
+ example.com. RRSIG DNSKEY ... (keyB)
+
+
+ When the rollover becomes visible to the verifying stub resolver it
+ will be able to verify the RRSIGs associated with key1, key3 ...
+ keyY. There will be no RRSIG by key2 and the RRSIG by keyY+1 will
+ not be used for validation, since that key is previously unknown and
+ therefore not trusted.
+
+
+ Note that this example is simplified. Because of operational
+ considerations described in [5] having a period during which the two
+ key signing keys are both available is necessary.
+
+
+3.2 Threshold-based Trust Update
+
+
+ The threshold-based trust update algorithm applies as follows. If
+ for a particular secure entry point
+ o if the DNSKEY RRset in the zone has been replaced by a more recent
+ one (as determined by comparing the RRSIG inception dates)
+ and
+ o if at least M configured trust anchors directly verify the related
+ RRSIGs over the new DNSKEY RRset
+ and
+ o the number of configured trust anchors that verify the related
+ RRSIGs over the new DNSKEY RRset exceed a locally defined minimum
+ number that should be greater than one
+ then all the trust anchors for the particular secure entry point are
+ replaced by the set of keys from the zones DNSKEY RRset that have the
+ SEP flag set.
+
+
+ The choices for the rollover acceptance policy parameter M is left to
+ the administrator of the resolver. To be certain that a rollover is
+ accepted up by resolvers using this mechanism zone owners should roll
+ as few SEP keys at a time as possible (preferably just one). That
+ way they comply to the most strict rollover acceptance policy of
+ M=N-1.
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 8]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ The value of M has an upper bound, limited by the number of of SEP
+ keys a zone owner publishes (i.e. N). But there is also a lower
+ bound, since it will not be safe to base the trust in too few
+ signatures. The corner case is M=1 when any validating RRSIG will be
+ sufficient for a complete replacement of the trust anchors for that
+ secure entry point. This is not a recommended configuration, since
+ that will allow an attacker to initiate rollover of the trust anchors
+ himself given access to just one compromised key. Hence M should in
+ be strictly larger than 1 as shown by the third requirement above.
+
+
+ If the rollover acceptance policy is M=1 then the result for the
+ rollover in our example above should be that the local database of
+ trust anchors is updated by removing key "key2" from and adding key
+ "keyY+1" to the key store.
+
+
+3.3 Possible Trust Update States
+
+
+ We define five states for trust anchor configuration at the client
+ side.
+ PRIMING: There are no trust anchors configured. There may be priming
+ keys available for initial priming of trust anchors.
+ IN-SYNC: The set of trust anchors configured exactly matches the set
+ of SEP keys used by the zone owner to sign the zone.
+ OUT-OF-SYNC: The set of trust anchors is not exactly the same as the
+ set of SEP keys used by the zone owner to sign the zone but there
+ are enough SEP key in use by the zone owner that is also in the
+ trust anchor configuration.
+ UNSYNCABLE: There is not enough overlap between the configured trust
+ anchors and the set of SEP keys used to sign the zone for the new
+ set to be accepted by the validator (i.e. the number of
+ signatures that verify is not sufficient).
+ STALE: There is no overlap between the configured trust anchors and
+ the set of SEP keys used to sign the zone. Here validation of
+ data is no longer possible and hence we are in a situation where
+ the trust anchors are stale.
+
+
+ Of these five states only two (IN-SYNC and OUT-OF-SYNC) are part of
+ the automatic trust update mechanism. The PRIMING state is where a
+ validator is located before acquiring an up-to-date set of trust
+ anchors. The transition from PRIMING to IN-SYNC is manual (see
+ Section 4 below).
+
+
+ Example: assume a secure entry point with four SEP keys and a
+ validator with the policy that it will accept any update to the set
+ of trust anchors as long as no more than two signatures fail to
+ validate (i.e. M >= N-2) and at least two signature does validate
+ (i.e. M >= 2). In this case the rollover of a single key will move
+ the validator from IN-SYNC to OUT-OF-SYNC. When the trust update
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 9]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ state machine updates the trust anchors it returns to state IN-SYNC.
+
+
+ If if for some reason it fails to update the trust anchors then the
+ next rollover (of a different key) will move the validator from
+ OUT-OF-SYNC to OUT-OF-SYNC (again), since there are still two keys
+ that are configured as trust anchors and that is sufficient to accpt
+ an automatic update of the trust anchors.
+
+
+ The UNSYNCABLE state is where a validator is located if it for some
+ reason fails to incorporate enough updates to the trust anchors to be
+ able to accept new updates according to its local policy. In this
+ example (i.e. with the policy specified above) this will either be
+ because M < N-2 or M < 2, which does not suffice to authenticate a
+ successful update of trust anchors.
+
+
+ Continuing with the previous example where two of the four SEP keys
+ have already rolled, but the validator has failed to update the set
+ of trust anchors. When the third key rolls over there will only be
+ one trust anchor left that can do successful validation. This is not
+ sufficient to enable automatic update of the trust anchors, hence the
+ new state is UNSYNCABLE. Note, however, that the remaining
+ up-to-date trust anchor is still enough to do successful validation
+ so the validator is still "working" from a DNSSEC point of view.
+
+
+ The STALE state, finally, is where a validator ends up when it has
+ zero remaining current trust anchors. This is a dangerous state,
+ since the stale trust anchors will cause all validation to fail. The
+ escape is to remove the stale trust anchors and thereby revert to the
+ PRIMING state.
+
+
+3.4 Implementation notes
+
+
+ The DNSSEC protocol specification ordains that a DNSKEY to which a DS
+ record points should be self-signed. Since the keys that serve as
+ trust anchors and the keys that are pointed to by DS records serve
+ the same purpose, they are both secure entry points, we RECOMMEND
+ that zone owners who want to facilitate the automated rollover scheme
+ documented herein self-sign DNSKEYs with the SEP bit set and that
+ implementation check that DNSKEYs with the SEP bit set are
+ self-signed.
+
+
+ In order to maintain a uniform way of determining that a keyset in
+ the zone has been replaced by a more recent set the automatic trust
+ update machine SHOULD only accept new DNSKEY RRsets if the
+ accompanying RRSIGs show a more recent inception date than the
+ present set of trust anchors. This is also needed as a safe guard
+ against possible replay attacks where old updates are replayed
+ "backwards" (i.e. one change at a time, but going in the wrong
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 10]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ direction, thereby luring the validator into the UNSYNCABLE and
+ finally STALE states).
+
+
+ In order to be resilient against failures the implementation should
+ collect the DNSKEY RRsets from (other) authoritative servers if
+ verification of the self signatures fails.
+
+
+ The threshold-based trust update mechanism SHOULD only be applied to
+ algorithms, as represented in the algorithm field in the DNSKEY/RRSIG
+ [3], that the resolver is aware of. In other words the SEP keys of
+ unknown algorithms should not be used when counting the number of
+ available signatures (the N constant) and the SEP keys of unknown
+ algorithm should not be entered as trust anchors.
+
+
+ When in state UNSYNCABLE or STALE manual intervention will be needed
+ to return to the IN-SYNC state. These states should be flagged. The
+ most appropriate action is human audit possibly followed by
+ re-priming (Section 4) the keyset (i.e. manual transfer to the
+ PRIMING state through removal of the configured trust anchors).
+
+
+ An implementation should regularly probe the the authoritative
+ nameservers for new keys. Since there is no mechanism to publish
+ rollover frequencies this document RECOMMENDS zone owners not to roll
+ their key signing keys more often than once per month and resolver
+ administrators to probe for key rollsovers (and apply the threshold
+ criterion for acceptance of trust update) not less often than once
+ per month. If the rollover frequency is higher than the probing
+ frequency then trust anchors may become stale. The exact relation
+ between the frequencies depends on the number of SEP keys rolled by
+ the zone owner and the value M configured by the resolver
+ administrator.
+
+
+ In all the cases below a transaction where the threshold criterion is
+ not satisfied should be considered bad (i.e. possibly spoofed or
+ otherwise corrupted data). The most appropriate action is human
+ audit.
+
+
+ There is one case where a "bad" state may be escaped from in an
+ automated fashion. This is when entering the STALE state where all
+ DNSSEC validation starts to fail. If this happens it is concievable
+ that it is better to completely discard the stale trust anchors
+ (thereby reverting to the PRIMING state where validation is not
+ possible). A local policy that automates removal of stale trust
+ anchors is therefore suggested.
+
+
+3.5 Possible transactions
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 11]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+3.5.1 Single DNSKEY replaced
+
+
+ This is probably the most typical transaction on the zone owners
+ part. The result should be that if the threshold criterion is
+ satisfied then the key store is updated by removal of the old trust
+ anchor and addition of the new key as a new trust anchor. Note that
+ if the DNSKEY RRset contains exactly M keys replacement of keys is
+ not possible, i.e. for automatic rollover to work M must be stricly
+ less than N.
+
+
+3.5.2 Addition of a new DNSKEY (no removal)
+
+
+ If the threshold criterion is satisfied then the new key is added as
+ a configured trust anchor. Not more than N-M keys can be added at
+ once, since otherwise the algorithm will fail.
+
+
+3.5.3 Removal of old DNSKEY (no addition)
+
+
+ If the threshold criterion is satisfied then the old key is removed
+ from being a configured trust anchor. Note that it is not possible
+ to reduce the size of the DNSKEY RRset to a size smaller than the
+ minimum required value for M.
+
+
+3.5.4 Multiple DNSKEYs replaced
+
+
+ Arguably it is not a good idea for the zone administrator to replace
+ several keys at the same time, but from the resolver point of view
+ this is exactly what will happen if the validating resolver for some
+ reason failed to notice a previous rollover event.
+
+
+ Not more than N-M keys can be replaced at one time or the threshold
+ criterion will not be satisfied. Or, expressed another way: as long
+ as the number of changed keys is less than or equal to N-M the
+ validator is in state OUT-OF-SYNC. When the number of changed keys
+ becomes greater than N-M the state changes to UNSYNCABLE and manual
+ action is needed.
+
+
+3.6 Removal of trust anchors for a trust point
+
+
+ If the parent of a secure entry point gets signed and it's trusted
+ keys get configured in the key store of the validating resolver then
+ the configured trust anchors for the child should be removed entirely
+ unless explicitly configured (in the utility configuration) to be an
+ exception.
+
+
+ The reason for such a configuration would be that the resolver has a
+ local policy that requires maintenance of trusted keys further down
+ the tree hierarchy than strictly needed from the point of view.
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 12]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ The default action when the parent zone changes from unsigned to
+ signed should be to remove the configured trust anchors for the
+ child. This form of "garbage collect" will ensure that the automatic
+ rollover machinery scales as DNSSEC deployment progresses.
+
+
+3.7 No need for resolver-side overlap of old and new keys
+
+
+ It is worth pointing out that there is no need for the resolver to
+ keep state about old keys versus new keys, beyond the requirement of
+ tracking signature inception time for the covering RRSIGs as
+ described in Section 3.4.
+
+
+ From the resolver point of view there are only trusted and not
+ trusted keys. The reason is that the zone owner needs to do proper
+ maintenance of RRSIGs regardless of the resolver rollover mechanism
+ and hence must ensure that no key rolled out out the DNSKEY set until
+ there cannot be any RRSIGs created by this key still legally cached.
+
+
+ Hence the rollover mechanism is entirely stateless with regard to the
+ keys involved: as soon as the resolver (or in this case the rollover
+ tracking utility) detects a change in the DNSKEY RRset (i.e. it is
+ now in the state OUT-OF-SYNC) with a sufficient number of matching
+ RRSIGs the configured trust anchors are immediately updated (and
+ thereby the machine return to state IN-SYNC). I.e. the rollover
+ machine changes states (mostly oscillating between IN-SYNC and
+ OUT-OF-SYNC), but the status of the DNSSEC keys is stateless.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 13]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+4. Bootstrapping automatic rollovers
+
+
+ It is expected that with the ability to automatically roll trust
+ anchors at trust points will follow a diminished unwillingness to
+ roll these keys, since the risks associated with stale keys are
+ minimized.
+
+
+ The problem of "priming" the trust anchors, or bringing them into
+ sync (which could happen if a resolver is off line for a long period
+ in which a set of SEP keys in a zone 'evolve' away from its trust
+ anchor configuration) remains.
+
+
+ For (re)priming we can rely on out of band technology and we propose
+ the following framework.
+
+
+4.1 Priming Keys
+
+
+ If all the trust anchors roll somewhat frequently (on the order of
+ months or at most about a year) then it will not be possible to
+ design a device, or a software distribution that includes trust
+ anchors, that after being manufactured is put on a shelf for several
+ key rollover periods before being brought into use (since no trust
+ anchors that were known at the time of manufacture remain active).
+
+
+ To alleviate this we propose the concept of "priming keys". Priming
+ keys are ordinary DNSSEC Key Signing Keys with the characteristic
+ that
+ o The private part of a priming key signs the DNSKEY RRset at the
+ security apex, i.e. at least one RRSIG DNSKEY is created by a
+ priming key rather than by an "ordinary" trust anchor
+ o the public parts of priming keys are not included in the DNSKEY
+ RRset. Instead the public parts of priming keys are only
+ available out-of-band.
+ o The public parts of the priming keys have a validity period.
+ Within this period they can be used to obtain trust anchors.
+ o The priming key pairs are long lived (relative to the key rollover
+ period.)
+
+
+4.1.1 Bootstrapping trust anchors using a priming key
+
+
+ To install the trust anchors for a particular security apex an
+ administrator of a validating resolver will need to:
+ o query for the DNSKEY RRset of the zone at the security apex;
+ o verify the self signatures of all DNSKEYs in the RRset;
+ o verify the signature of the RRSIG made with a priming key --
+ verification using one of the public priming keys that is valid at
+ that moment is sufficient;
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 14]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ o create the trust anchors by extracting the DNSKEY RRs with the SEP
+ flag set.
+ The SEP keys with algorithms unknown to the validating resolver
+ SHOULD be ignored during the creation of the trust anchors.
+
+
+4.1.2 Distribution of priming keys
+
+
+ The public parts of the priming keys SHOULD be distributed
+ exclusively through out-of-DNS mechanisms. The requirements for a
+ distribution mechanism are:
+ o it can carry the "validity" period for the priming keys;
+ o it can carry the self-signature of the priming keys;
+ o and it allows for verification using trust relations outside the
+ DNS.
+ A distribution mechanism would benefit from:
+ o the availability of revocation lists;
+ o the ability of carrying zone owners policy information such as
+ recommended values for "M" and "N" and a rollover frequency;
+ o and the technology on which is based is readily available.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 15]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+5. The Threshold Rollover Mechanism vs Priming
+
+
+ There is overlap between the threshold-based trust updater and the
+ Priming method. One could exclusively use the Priming method for
+ maintaining the trust anchors. However the priming method probably
+ relies on "non-DNS' technology and may therefore not be available for
+ all devices that have a resolver.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 16]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+6. Security Considerations
+
+
+6.1 Threshold-based Trust Update Security Considerations
+
+
+ A clear issue for resolvers will be how to ensure that they track all
+ rollover events for the zones they have configure trust anchors for.
+ Because of temporary outages validating resolvers may have missed a
+ rollover of a KSK. The parameters that determine the robustness
+ against failures are: the length of the period between rollovers
+ during which the KSK set is stable and validating resolvers can
+ actually notice the change; the number of available KSKs (i.e. N)
+ and the number of signatures that may fail to validate (i.e. N-M).
+
+
+ With a large N (i.e. many KSKs) and a small value of M this
+ operation becomes more robust since losing one key, for whatever
+ reason, will not be crucial. Unfortunately the choice for the number
+ of KSKs is a local policy issue for the zone owner while the choice
+ for the parameter M is a local policy issue for the resolver
+ administrator.
+
+
+ Higher values of M increase the resilience against attacks somewhat;
+ more signatures need to verify for a rollover to be approved. On the
+ other hand the number of rollover events that may pass unnoticed
+ before the resolver reaches the UNSYNCABLE state goes down.
+
+
+ The threshold-based trust update intentionally does not provide a
+ revocation mechanism. In the case that a sufficient number of
+ private keys of a zone owner are simultaneously compromised the the
+ attacker may use these private keys to roll the trust anchors of (a
+ subset of) the resolvers. This is obviously a bad situation but it
+ is not different from most other public keys systems.
+
+
+ However, it is important to point out that since any reasonable trust
+ anchor rollover policy (in validating resolvers) will require more
+ than one RRSIG to validate this proposal does provide security
+ concious zone administrators with the option of not storing the
+ individual private keys in the same location and thereby decreasing
+ the likelihood of simultaneous compromise.
+
+
+6.2 Priming Key Security Considerations
+
+
+ Since priming keys are not included in the DNSKEY RR set they are
+ less sensitive to packet size constraints and can be chosen
+ relatively large. The private parts are only needed to sign the
+ DNSKEY RR set during the validity period of the particular priming
+ key pair. Note that the private part of the priming key is used each
+ time when a DNSKEY RRset has to be resigned. In practice there is
+ therefore little difference between the usage pattern of the private
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 17]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ part of key signing keys and priming keys.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 18]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+7. IANA Considerations
+
+
+ NONE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 19]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+8. References
+
+
+8.1 Normative References
+
+
+ [1] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+
+ [2] Kolkman, O., Schlyter, J. and E. Lewis, "Domain Name System KEY
+ (DNSKEY) Resource Record (RR) Secure Entry Point (SEP) Flag",
+ RFC 3757, May 2004.
+
+
+ [3] Arends, R., "Resource Records for the DNS Security Extensions",
+ draft-ietf-dnsext-dnssec-records-10 (work in progress),
+ September 2004.
+
+
+8.2 Informative References
+
+
+ [4] Arends, R., Austein, R., Massey, D., Larson, M. and S. Rose,
+ "DNS Security Introduction and Requirements",
+ draft-ietf-dnsext-dnssec-intro-12 (work in progress), September
+ 2004.
+
+
+ [5] Kolkman, O., "DNSSEC Operational Practices",
+ draft-ietf-dnsop-dnssec-operational-practices-01 (work in
+ progress), May 2004.
+
+
+ [6] Housley, R., Ford, W., Polk, T. and D. Solo, "Internet X.509
+ Public Key Infrastructure Certificate and CRL Profile", RFC
+ 2459, January 1999.
+
+
+
+Authors' Addresses
+
+
+ Johan Ihren
+ Autonomica AB
+ Bellmansgatan 30
+ Stockholm SE-118 47
+ Sweden
+
+
+ EMail: johani@autonomica.se
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 20]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+ Olaf M. Kolkman
+ RIPE NCC
+ Singel 256
+ Amsterdam 1016 AB
+ NL
+
+
+ Phone: +31 20 535 4444
+ EMail: olaf@ripe.net
+ URI: http://www.ripe.net/
+
+
+
+ Bill Manning
+ EP.net
+ Marina del Rey, CA 90295
+ USA
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 21]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+Appendix A. Acknowledgments
+
+
+ The present design for in-band automatic rollovers of DNSSEC trust
+ anchors is the result of many conversations and it is no longer
+ possible to remember exactly who contributed what.
+
+
+ In addition we've also had appreciated help from (in no particular
+ order) Paul Vixie, Sam Weiler, Suzanne Woolf, Steve Crocker, Matt
+ Larson and Mark Kosters.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 22]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+Appendix B. Document History
+
+
+ This appendix will be removed if and when the document is submitted
+ to the RFC editor.
+
+
+ The version you are reading is tagged as $Revision: 1.1 $.
+
+
+ Text between square brackets, other than references, are editorial
+ comments and will be removed.
+
+
+B.1 prior to version 00
+
+
+ This draft was initially published as a personal submission under the
+ name draft-kolkman-dnsext-dnssec-in-band-rollover-00.txt.
+
+
+ Kolkman documented the ideas provided by Ihren and Manning. In the
+ process of documenting (and prototyping) Kolkman changed some of the
+ details of the M-N algorithms working. Ihren did not have a chance
+ to review the draft before Kolkman posted;
+
+
+ Kolkman takes responsibilities for omissions, fuzzy definitions and
+ mistakes.
+
+
+B.2 version 00
+ o The name of the draft was changed as a result of the draft being
+ adopted as a working group document.
+ o A small section on the concept of stale trust anchors was added.
+ o The different possible states are more clearly defined, including
+ examples of transitions between states.
+ o The terminology is changed throughout the document. The old term
+ "M-N" is replaced by "threshold" (more or less). Also the
+ interpretation of the constants M and N is significantly
+ simplified to bring the usage more in line with "standard"
+ threshold terminlogy.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 23]
+Internet-Draft DNSSEC Threshold-based Trust Update October 2004
+
+
+
+Intellectual Property Statement
+
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+
+Disclaimer of Validity
+
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+Copyright Statement
+
+
+ Copyright (C) The Internet Society (2004). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+
+Acknowledgment
+
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Ihren, et al. Expires April 18, 2005 [Page 24] \ No newline at end of file
diff --git a/doc/draft/draft-ietf-dnsext-trustupdate-timers-05.txt b/doc/draft/draft-ietf-dnsext-trustupdate-timers-05.txt
new file mode 100644
index 0000000..0285259
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-trustupdate-timers-05.txt
@@ -0,0 +1,729 @@
+
+
+
+Network Working Group M. StJohns
+Internet-Draft Nominum, Inc.
+Intended status: Informational November 29, 2006
+Expires: June 2, 2007
+
+
+ Automated Updates of DNSSEC Trust Anchors
+ draft-ietf-dnsext-trustupdate-timers-05
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on June 2, 2007.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ This document describes a means for automated, authenticated and
+ authorized updating of DNSSEC "trust anchors". The method provides
+ protection against N-1 key compromises of N keys in the trust point
+ key set. Based on the trust established by the presence of a current
+ anchor, other anchors may be added at the same place in the
+ hierarchy, and, ultimately, supplant the existing anchor(s).
+
+ This mechanism will require changes to resolver management behavior
+
+
+
+StJohns Expires June 2, 2007 [Page 1]
+
+Internet-Draft trustanchor-update November 2006
+
+
+ (but not resolver resolution behavior), and the addition of a single
+ flag bit to the DNSKEY record.
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1. Compliance Nomenclature . . . . . . . . . . . . . . . . . 3
+ 2. Theory of Operation . . . . . . . . . . . . . . . . . . . . . 4
+ 2.1. Revocation . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 2.2. Add Hold-Down . . . . . . . . . . . . . . . . . . . . . . 5
+ 2.3. Active Refresh . . . . . . . . . . . . . . . . . . . . . . 5
+ 2.4. Resolver Parameters . . . . . . . . . . . . . . . . . . . 6
+ 2.4.1. Add Hold-Down Time . . . . . . . . . . . . . . . . . . 6
+ 2.4.2. Remove Hold-Down Time . . . . . . . . . . . . . . . . 6
+ 2.4.3. Minimum Trust Anchors per Trust Point . . . . . . . . 6
+ 3. Changes to DNSKEY RDATA Wire Format . . . . . . . . . . . . . 6
+ 4. State Table . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 4.1. Events . . . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 4.2. States . . . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 5. Trust Point Deletion . . . . . . . . . . . . . . . . . . . . . 8
+ 6. Scenarios - Informative . . . . . . . . . . . . . . . . . . . 9
+ 6.1. Adding a Trust Anchor . . . . . . . . . . . . . . . . . . 9
+ 6.2. Deleting a Trust Anchor . . . . . . . . . . . . . . . . . 9
+ 6.3. Key Roll-Over . . . . . . . . . . . . . . . . . . . . . . 10
+ 6.4. Active Key Compromised . . . . . . . . . . . . . . . . . . 10
+ 6.5. Stand-by Key Compromised . . . . . . . . . . . . . . . . . 10
+ 6.6. Trust Point Deletion . . . . . . . . . . . . . . . . . . . 10
+ 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 11
+ 8. Security Considerations . . . . . . . . . . . . . . . . . . . 11
+ 8.1. Key Ownership vs Acceptance Policy . . . . . . . . . . . . 11
+ 8.2. Multiple Key Compromise . . . . . . . . . . . . . . . . . 11
+ 8.3. Dynamic Updates . . . . . . . . . . . . . . . . . . . . . 11
+ 9. Normative References . . . . . . . . . . . . . . . . . . . . . 12
+ Editorial Comments . . . . . . . . . . . . . . . . . . . . . . . .
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 12
+ Intellectual Property and Copyright Statements . . . . . . . . . . 13
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+StJohns Expires June 2, 2007 [Page 2]
+
+Internet-Draft trustanchor-update November 2006
+
+
+1. Introduction
+
+ As part of the reality of fielding DNSSEC (Domain Name System
+ Security Extensions) [RFC4033] [RFC4034] [RFC4035], the community has
+ come to the realization that there will not be one signed name space,
+ but rather islands of signed name space each originating from
+ specific points (i.e. 'trust points') in the DNS tree. Each of those
+ islands will be identified by the trust point name, and validated by
+ at least one associated public key. For the purpose of this document
+ we'll call the association of that name and a particular key a 'trust
+ anchor'. A particular trust point can have more than one key
+ designated as a trust anchor.
+
+ For a DNSSEC-aware resolver to validate information in a DNSSEC
+ protected branch of the hierarchy, it must have knowledge of a trust
+ anchor applicable to that branch. It may also have more than one
+ trust anchor for any given trust point. Under current rules, a chain
+ of trust for DNSSEC-protected data that chains its way back to ANY
+ known trust anchor is considered 'secure'.
+
+ Because of the probable balkanization of the DNSSEC tree due to
+ signing voids at key locations, a resolver may need to know literally
+ thousands of trust anchors to perform its duties. (e.g. Consider an
+ unsigned ".COM".) Requiring the owner of the resolver to manually
+ manage this many relationships is problematic. It's even more
+ problematic when considering the eventual requirement for key
+ replacement/update for a given trust anchor. The mechanism described
+ herein won't help with the initial configuration of the trust anchors
+ in the resolvers, but should make trust point key replacement/
+ rollover more viable.
+
+ As mentioned above, this document describes a mechanism whereby a
+ resolver can update the trust anchors for a given trust point, mainly
+ without human intervention at the resolver. There are some corner
+ cases discussed (e.g. multiple key compromise) that may require
+ manual intervention, but they should be few and far between. This
+ document DOES NOT discuss the general problem of the initial
+ configuration of trust anchors for the resolver.
+
+1.1. Compliance Nomenclature
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, [RFC2119].
+
+
+
+
+
+
+
+StJohns Expires June 2, 2007 [Page 3]
+
+Internet-Draft trustanchor-update November 2006
+
+
+2. Theory of Operation
+
+ The general concept of this mechanism is that existing trust anchors
+ can be used to authenticate new trust anchors at the same point in
+ the DNS hierarchy. When a zone operator adds a new SEP key (i.e. a
+ DNSKEY with the Secure Entry Point bit set) (see [RFC4034]section
+ 2.1.1) to a trust point DNSKEY RRSet, and when that RRSet is
+ validated by an existing trust anchor, then the resolver can add the
+ new key to its valid set of trust anchors for that trust point.
+
+ There are some issues with this approach which need to be mitigated.
+ For example, a compromise of one of the existing keys could allow an
+ attacker to add their own 'valid' data. This implies a need for a
+ method to revoke an existing key regardless of whether or not that
+ key is compromised. As another example, assuming a single key
+ compromise, we need to prevent an attacker from adding a new key and
+ revoking all the other old keys.
+
+2.1. Revocation
+
+ Assume two trust anchor keys A and B. Assume that B has been
+ compromised. Without a specific revocation bit, B could invalidate A
+ simply by sending out a signed trust point key set which didn't
+ contain A. To fix this, we add a mechanism which requires knowledge
+ of the private key of a DNSKEY to revoke that DNSKEY.
+
+ A key is considered revoked when the resolver sees the key in a self-
+ signed RRSet and the key has the REVOKE bit (see Section 7 below) set
+ to '1'. Once the resolver sees the REVOKE bit, it MUST NOT use this
+ key as a trust anchor or for any other purposes except validating the
+ RRSIG it signed over the DNSKEY RRSet specifically for the purpose of
+ validating the revocation. Unlike the 'Add' operation below,
+ revocation is immediate and permanent upon receipt of a valid
+ revocation at the resolver.
+
+ A self-signed RRSet is a DNSKEY RRSet which contains the specific
+ DNSKEY and for which there is a corresponding validated RRSIG record.
+ It's not a special DNSKEY RRSet, just a way of describing the
+ validation requirements for that RRSet.
+
+ N.B. A DNSKEY with the REVOKE bit set has a different fingerprint
+ than one without the bit set. This affects the matching of a DNSKEY
+ to DS records in the parent, or the fingerprint stored at a resolver
+ used to configure a trust point.
+
+ In the given example, the attacker could revoke B because it has
+ knowledge of B's private key, but could not revoke A.
+
+
+
+
+StJohns Expires June 2, 2007 [Page 4]
+
+Internet-Draft trustanchor-update November 2006
+
+
+2.2. Add Hold-Down
+
+ Assume two trust point keys A and B. Assume that B has been
+ compromised. An attacker could generate and add a new trust anchor
+ key - C (by adding C to the DNSKEY RRSet and signing it with B), and
+ then invalidate the compromised key. This would result in both the
+ attacker and owner being able to sign data in the zone and have it
+ accepted as valid by resolvers.
+
+ To mitigate but not completely solve this problem, we add a hold-down
+ time to the addition of the trust anchor. When the resolver sees a
+ new SEP key in a validated trust point DNSKEY RRSet, the resolver
+ starts an acceptance timer, and remembers all the keys that validated
+ the RRSet. If the resolver ever sees the DNSKEY RRSet without the
+ new key but validly signed, it stops the acceptance process for that
+ key and resets the acceptance timer. If all of the keys which were
+ originally used to validate this key are revoked prior to the timer
+ expiring, the resolver stops the acceptance process and resets the
+ timer.
+
+ Once the timer expires, the new key will be added as a trust anchor
+ the next time the validated RRSet with the new key is seen at the
+ resolver. The resolver MUST NOT treat the new key as a trust anchor
+ until the hold down time expires AND it has retrieved and validated a
+ DNSKEY RRSet after the hold down time which contains the new key.
+
+ N.B.: Once the resolver has accepted a key as a trust anchor, the key
+ MUST be considered a valid trust anchor by that resolver until
+ explictly revoked as described above.
+
+ In the given example, the zone owner can recover from a compromise by
+ revoking B and adding a new key D and signing the DNSKEY RRSet with
+ both A and B.
+
+ The reason this does not completely solve the problem has to do with
+ the distributed nature of DNS. The resolver only knows what it sees.
+ A determined attacker who holds one compromised key could keep a
+ single resolver from realizing that key had been compromised by
+ intercepting 'real' data from the originating zone and substituting
+ their own (e.g. using the example, signed only by B). This is no
+ worse than the current situation assuming a compromised key.
+
+2.3. Active Refresh
+
+ A resolver which has been configured for automatic update of keys
+ from a particular trust point MUST query that trust point (e.g. do a
+ lookup for the DNSKEY RRSet and related RRSIG records) no less often
+ than the lesser of 15 days or half the original TTL for the DNSKEY
+
+
+
+StJohns Expires June 2, 2007 [Page 5]
+
+Internet-Draft trustanchor-update November 2006
+
+
+ RRSet or half the RRSIG expiration interval and no more often than
+ once per hour. The expiration interval is the amount of time from
+ when the RRSIG was last retrieved until the expiration time in the
+ RRSIG.
+
+ If the query fails, the resolver MUST repeat the query until
+ satisfied no more often than once an hour and no less often than the
+ lesser of 1 day or 10% of the original TTL or 10% of the original
+ expiration interval. I.e.: retryTime = MAX (1 hour, MIN (1 day, .1 *
+ origTTL, .1 * expireInterval)).
+
+2.4. Resolver Parameters
+
+2.4.1. Add Hold-Down Time
+
+ The add hold-down time is 30 days or the expiration time of the
+ original TTL of the first trust point DNSKEY RRSet which contained
+ the new key, whichever is greater. This ensures that at least two
+ validated DNSKEY RRSets which contain the new key MUST be seen by the
+ resolver prior to the key's acceptance.
+
+2.4.2. Remove Hold-Down Time
+
+ The remove hold-down time is 30 days. This parameter is solely a key
+ management database bookeeping parameter. Failure to remove
+ information about the state of defunct keys from the database will
+ not adversely impact the security of this protocol, but may end up
+ with a database cluttered with obsolete key information.
+
+2.4.3. Minimum Trust Anchors per Trust Point
+
+ A compliant resolver MUST be able to manage at least five SEP keys
+ per trust point.
+
+
+3. Changes to DNSKEY RDATA Wire Format
+
+ Bit n [msj2]of the DNSKEY Flags field is designated as the 'REVOKE'
+ flag. If this bit is set to '1', AND the resolver sees an
+ RRSIG(DNSKEY) signed by the associated key, then the resolver MUST
+ consider this key permanently invalid for all purposes except for
+ validating the revocation.
+
+
+4. State Table
+
+ The most important thing to understand is the resolver's view of any
+ key at a trust point. The following state table describes that view
+
+
+
+StJohns Expires June 2, 2007 [Page 6]
+
+Internet-Draft trustanchor-update November 2006
+
+
+ at various points in the key's lifetime. The table is a normative
+ part of this specification. The initial state of the key is 'Start'.
+ The resolver's view of the state of the key changes as various events
+ occur.
+
+ This is the state of a trust point key as seen from the resolver.
+ The column on the left indicates the current state. The header at
+ the top shows the next state. The intersection of the two shows the
+ event that will cause the state to transition from the current state
+ to the next.
+
+
+ NEXT STATE
+ --------------------------------------------------
+ FROM |Start |AddPend |Valid |Missing|Revoked|Removed|
+ ----------------------------------------------------------
+ Start | |NewKey | | | | |
+ ----------------------------------------------------------
+ AddPend |KeyRem | |AddTime| | |
+ ----------------------------------------------------------
+ Valid | | | |KeyRem |Revbit | |
+ ----------------------------------------------------------
+ Missing | | |KeyPres| |Revbit | |
+ ----------------------------------------------------------
+ Revoked | | | | | |RemTime|
+ ----------------------------------------------------------
+ Removed | | | | | | |
+ ----------------------------------------------------------
+
+
+ State Table
+
+4.1. Events
+ NewKey The resolver sees a valid DNSKEY RRSet with a new SEP key.
+ That key will become a new trust anchor for the named trust point
+ after it's been present in the RRSet for at least 'add time'.
+ KeyPres The key has returned to the valid DNSKEY RRSet.
+ KeyRem The resolver sees a valid DNSKEY RRSet that does not contain
+ this key.
+ AddTime The key has been in every valid DNSKEY RRSet seen for at
+ least the 'add time'.
+ RemTime A revoked key has been missing from the trust point DNSKEY
+ RRSet for sufficient time to be removed from the trust set.
+ RevBit The key has appeared in the trust anchor DNSKEY RRSet with
+ its "REVOKED" bit set, and there is an RRSig over the DNSKEY RRSet
+ signed by this key.
+
+
+
+
+
+StJohns Expires June 2, 2007 [Page 7]
+
+Internet-Draft trustanchor-update November 2006
+
+
+4.2. States
+ Start The key doesn't yet exist as a trust anchor at the resolver.
+ It may or may not exist at the zone server, but either hasn't yet
+ been seen at the resolver or was seen but was absent from the last
+ DNSKEY RRSet (e.g. KeyRem event).
+ AddPend The key has been seen at the resolver, has its 'SEP' bit
+ set, and has been included in a validated DNSKEY RRSet. There is
+ a hold-down time for the key before it can be used as a trust
+ anchor.
+ Valid The key has been seen at the resolver and has been included in
+ all validated DNSKEY RRSets from the time it was first seen up
+ through the hold-down time. It is now valid for verifying RRSets
+ that arrive after the hold down time. Clarification: The DNSKEY
+ RRSet does not need to be continuously present at the resolver
+ (e.g. its TTL might expire). If the RRSet is seen, and is
+ validated (i.e. verifies against an existing trust anchor), this
+ key MUST be in the RRSet otherwise a 'KeyRem' event is triggered.
+ Missing This is an abnormal state. The key remains as a valid trust
+ point key, but was not seen at the resolver in the last validated
+ DNSKEY RRSet. This is an abnormal state because the zone operator
+ should be using the REVOKE bit prior to removal.
+ Revoked This is the state a key moves to once the resolver sees an
+ RRSIG(DNSKEY) signed by this key where that DNSKEY RRSet contains
+ this key with its REVOKE bit set to '1'. Once in this state, this
+ key MUST permanently be considered invalid as a trust anchor.
+ Removed After a fairly long hold-down time, information about this
+ key may be purged from the resolver. A key in the removed state
+ MUST NOT be considered a valid trust anchor. (Note: this state is
+ more or less equivalent to the "Start" state, except that it's bad
+ practice to re-introduce previously used keys - think of this as
+ the holding state for all the old keys for which the resolver no
+ longer needs to track state.)
+
+
+5. Trust Point Deletion
+
+ A trust point which has all of its trust anchors revoked is
+ considered deleted and is treated as if the trust point was never
+ configured. If there are no superior configured trust points, data
+ at and below the deleted trust point are considered insecure by the
+ resolver. If there ARE superior configured trust points, data at and
+ below the deleted trust point are evaluated with respect to the
+ superior trust point(s).
+
+ Alternately, a trust point which is subordinate to another configured
+ trust point MAY be deleted by a resolver after 180 days where such
+ subordinate trust point validly chains to a superior trust point.
+ The decision to delete the subordinate trust anchor is a local
+
+
+
+StJohns Expires June 2, 2007 [Page 8]
+
+Internet-Draft trustanchor-update November 2006
+
+
+ configuration decision. Once the subordinate trust point is deleted,
+ validation of the subordinate zone is dependent on validating the
+ chain of trust to the superior trust point.
+
+
+6. Scenarios - Informative
+
+ The suggested model for operation is to have one active key and one
+ stand-by key at each trust point. The active key will be used to
+ sign the DNSKEY RRSet. The stand-by key will not normally sign this
+ RRSet, but the resolver will accept it as a trust anchor if/when it
+ sees the signature on the trust point DNSKEY RRSet.
+
+ Since the stand-by key is not in active signing use, the associated
+ private key may (and should) be provided with additional protections
+ not normally available to a key that must be used frequently. E.g.
+ locked in a safe, split among many parties, etc. Notionally, the
+ stand-by key should be less subject to compromise than an active key,
+ but that will be dependent on operational concerns not addressed
+ here.
+
+6.1. Adding a Trust Anchor
+
+ Assume an existing trust anchor key 'A'.
+ 1. Generate a new key pair.
+ 2. Create a DNSKEY record from the key pair and set the SEP and Zone
+ Key bits.
+ 3. Add the DNSKEY to the RRSet.
+ 4. Sign the DNSKEY RRSet ONLY with the existing trust anchor key -
+ 'A'.
+ 5. Wait a while (i.e. for various resolvers timers to go off and for
+ them to retrieve the new DNSKEY RRSet and signatures).
+ 6. The new trust anchor will be populated at the resolvers on the
+ schedule described by the state table and update algorithm - see
+ Section 2 above
+
+6.2. Deleting a Trust Anchor
+
+ Assume existing trust anchors 'A' and 'B' and that you want to revoke
+ and delete 'A'.
+ 1. Set the revocation bit on key 'A'.
+ 2. Sign the DNSKEY RRSet with both 'A' and 'B'.
+ 'A' is now revoked. The operator should include the revoked 'A' in
+ the RRSet for at least the remove hold-down time, but then may remove
+ it from the DNSKEY RRSet.
+
+
+
+
+
+
+StJohns Expires June 2, 2007 [Page 9]
+
+Internet-Draft trustanchor-update November 2006
+
+
+6.3. Key Roll-Over
+
+ Assume existing keys A and B. 'A' is actively in use (i.e. has been
+ signing the DNSKEY RRSet.) 'B' was the stand-by key. (i.e. has been
+ in the DNSKEY RRSet and is a valid trust anchor, but wasn't being
+ used to sign the RRSet.)
+ 1. Generate a new key pair 'C'.
+ 2. Add 'C' to the DNSKEY RRSet.
+ 3. Set the revocation bit on key 'A'.
+ 4. Sign the RRSet with 'A' and 'B'.
+ 'A' is now revoked, 'B' is now the active key, and 'C' will be the
+ stand-by key once the hold-down expires. The operator should include
+ the revoked 'A' in the RRSet for at least the remove hold-down time,
+ but may then remove it from the DNSKEY RRSet.
+
+6.4. Active Key Compromised
+
+ This is the same as the mechanism for Key Roll-Over (Section 6.3)
+ above assuming 'A' is the active key.
+
+6.5. Stand-by Key Compromised
+
+ Using the same assumptions and naming conventions as Key Roll-Over
+ (Section 6.3) above:
+ 1. Generate a new key pair 'C'.
+ 2. Add 'C' to the DNSKEY RRSet.
+ 3. Set the revocation bit on key 'B'.
+ 4. Sign the RRSet with 'A' and 'B'.
+ 'B' is now revoked, 'A' remains the active key, and 'C' will be the
+ stand-by key once the hold-down expires. 'B' should continue to be
+ included in the RRSet for the remove hold-down time.
+
+6.6. Trust Point Deletion
+
+ To delete a trust point which is subordinate to another configured
+ trust point (e.g. example.com to .com) requires some juggling of the
+ data. The specific process is:
+ 1. Generate a new DNSKEY and DS record and provide the DS record to
+ the parent along with DS records for the old keys
+ 2. Once the parent has published the DSs, add the new DNSKEY to the
+ RRSet and revoke ALL of the old keys at the same time while
+ signing the DNSKEY RRSet with all of the old and new keys.
+ 3. After 30 days stop publishing the old, revoked keys and remove
+ any corresponding DS records in the parent.
+ Revoking the old trust point keys at the same time as adding new keys
+ that chain to a superior trust prevents the resolver from adding the
+ new keys as trust anchors. Adding DS records for the old keys avoids
+ a race condition where either the subordinate zone becomes unsecure
+
+
+
+StJohns Expires June 2, 2007 [Page 10]
+
+Internet-Draft trustanchor-update November 2006
+
+
+ (because the trust point was deleted) or becomes bogus (because it
+ didn't chain to the superior zone).
+
+
+7. IANA Considerations
+
+ The IANA will need to assign a bit in the DNSKEY flags field (see
+ section 4.3 of [RFC3755]) for the REVOKE bit. There are no other
+ IANA actions required.
+
+
+8. Security Considerations
+
+ In addition to the following sections, see also Theory of Operation
+ above and especially Section 2.2 for related discussions.
+
+8.1. Key Ownership vs Acceptance Policy
+
+ The reader should note that, while the zone owner is responsible for
+ creating and distributing keys, it's wholly the decision of the
+ resolver owner as to whether to accept such keys for the
+ authentication of the zone information. This implies the decision to
+ update trust anchor keys based on trust for a current trust anchor
+ key is also the resolver owner's decision.
+
+ The resolver owner (and resolver implementers) MAY choose to permit
+ or prevent key status updates based on this mechanism for specific
+ trust points. If they choose to prevent the automated updates, they
+ will need to establish a mechanism for manual or other out-of-band
+ updates outside the scope of this document.
+
+8.2. Multiple Key Compromise
+
+ This scheme permits recovery as long as at least one valid trust
+ anchor key remains uncompromised. E.g. if there are three keys, you
+ can recover if two of them are compromised. The zone owner should
+ determine their own level of comfort with respect to the number of
+ active valid trust anchors in a zone and should be prepared to
+ implement recovery procedures once they detect a compromise. A
+ manual or other out-of-band update of all resolvers will be required
+ if all trust anchor keys at a trust point are compromised.
+
+8.3. Dynamic Updates
+
+ Allowing a resolver to update its trust anchor set based on in-band
+ key information is potentially less secure than a manual process.
+ However, given the nature of the DNS, the number of resolvers that
+ would require update if a trust anchor key were compromised, and the
+
+
+
+StJohns Expires June 2, 2007 [Page 11]
+
+Internet-Draft trustanchor-update November 2006
+
+
+ lack of a standard management framework for DNS, this approach is no
+ worse than the existing situation.
+
+
+9. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC3755] Weiler, S., "Legacy Resolver Compatibility for Delegation
+ Signer (DS)", RFC 3755, May 2004.
+
+ [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements",
+ RFC 4033, March 2005.
+
+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security Extensions",
+ RFC 4034, March 2005.
+
+ [RFC4035] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security
+ Extensions", RFC 4035, March 2005.
+
+Editorial Comments
+
+ [msj2] msj: To be assigned.
+
+
+Author's Address
+
+ Michael StJohns
+ Nominum, Inc.
+ 2385 Bay Road
+ Redwood City, CA 94063
+ USA
+
+ Phone: +1-301-528-4729
+ Email: Mike.StJohns@nominum.com
+ URI: www.nominum.com
+
+
+
+
+
+
+
+
+
+
+
+StJohns Expires June 2, 2007 [Page 12]
+
+Internet-Draft trustanchor-update November 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+StJohns Expires June 2, 2007 [Page 13]
+
+
diff --git a/doc/draft/draft-ietf-dnsext-tsig-sha-06.txt b/doc/draft/draft-ietf-dnsext-tsig-sha-06.txt
new file mode 100644
index 0000000..00476ae
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-tsig-sha-06.txt
@@ -0,0 +1,522 @@
+
+INTERNET-DRAFT Donald E. Eastlake 3rd
+UPDATES RFC 2845 Motorola Laboratories
+Expires: July 2006 January 2006
+
+ HMAC SHA TSIG Algorithm Identifiers
+ ---- --- ---- --------- -----------
+ <draft-ietf-dnsext-tsig-sha-06.txt>
+
+
+Status of This Document
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ This draft is intended to be become a Proposed Standard RFC.
+ Distribution of this document is unlimited. Comments should be sent
+ to the DNSEXT working group mailing list <namedroppers@ops.ietf.org>.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+
+Abstract
+
+ Use of the Domain Name System TSIG resource record requires
+ specification of a cryptographic message authentication code.
+ Currently identifiers have been specified only for the HMAC MD5
+ (Message Digest) and GSS (Generic Security Service) TSIG algorithms.
+ This document standardizes identifiers and implementation
+ requirements for additional HMAC SHA (Secure Hash Algorithm) TSIG
+ algorithms and standardizes how to specify and handle the truncation
+ of HMAC values in TSIG.
+
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+
+
+D. Eastlake 3rd [Page 1]
+
+
+INTERNET-DRAFT HMAC-SHA TSIG Identifiers
+
+
+Table of Contents
+
+ Status of This Document....................................1
+ Abstract...................................................1
+ Copyright Notice...........................................1
+
+ Table of Contents..........................................2
+
+ 1. Introduction............................................3
+
+ 2. Algorithms and Identifiers..............................4
+
+ 3. Specifying Truncation...................................5
+ 3.1 Truncation Specification...............................5
+
+ 4. TSIG Truncation Policy and Error Provisions.............6
+
+ 5. IANA Considerations.....................................7
+ 6. Security Considerations.................................7
+ 7. Copyright and Disclaimer................................7
+
+ 8. Normative References....................................8
+ 9. Informative References..................................8
+
+ Author's Address...........................................9
+ Additional IPR Provisions..................................9
+ Expiration and File Name...................................9
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 2]
+
+
+INTERNET-DRAFT HMAC-SHA TSIG Identifiers
+
+
+1. Introduction
+
+ [RFC 2845] specifies a TSIG Resource Record (RR) that can be used to
+ authenticate DNS (Domain Name System [STD 13]) queries and responses.
+ This RR contains a domain name syntax data item which names the
+ authentication algorithm used. [RFC 2845] defines the HMAC-MD5.SIG-
+ ALG.REG.INT name for authentication codes using the HMAC [RFC 2104]
+ algorithm with the MD5 [RFC 1321] hash algorithm. IANA has also
+ registered "gss-tsig" as an identifier for TSIG authentication where
+ the cryptographic operations are delegated to the Generic Security
+ Service (GSS) [RFC 3645].
+
+ It should be noted that use of TSIG presumes prior agreement, between
+ the resolver and server involved, as to the algorithm and key to be
+ used.
+
+ In Section 2, this document specifies additional names for TSIG
+ authentication algorithms based on US NIST SHA (United States,
+ National Institute of Science and Technology, Secure Hash Algorithm)
+ algorithms and HMAC and specifies the implementation requirements for
+ those algorithms.
+
+ In Section 3, this document specifies the effect of inequality
+ between the normal output size of the specified hash function and the
+ length of MAC (message authentication code) data given in the TSIG
+ RR. In particular, it specifies that a shorter length field value
+ specifies truncation and a longer length field is an error.
+
+ In Section 4, policy restrictions and implications related to
+ truncation and a new error code to indicate truncation shorter than
+ permitted by policy are described and specified.
+
+ The use herein of MUST, SHOULD, MAY, MUST NOT, and SHOULD NOT is as
+ defined in [RFC 2119].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 3]
+
+
+INTERNET-DRAFT HMAC-SHA TSIG Identifiers
+
+
+2. Algorithms and Identifiers
+
+ TSIG Resource Records (RRs) [RFC 2845] are used to authenticate DNS
+ queries and responses. They are intended to be efficient symmetric
+ authentication codes based on a shared secret. (Asymmetric signatures
+ can be provided using the SIG RR [RFC 2931]. In particular, SIG(0)
+ can be used for transaction signatures.) Used with a strong hash
+ function, HMAC [RFC 2104] provides a way to calculate such symmetric
+ authentication codes. The only specified HMAC based TSIG algorithm
+ identifier has been HMAC-MD5.SIG-ALG.REG.INT based on MD5 [RFC 1321].
+
+ The use of SHA-1 [FIPS 180-2, RFC 3174], which is a 160 bit hash, as
+ compared with the 128 bits for MD5, and additional hash algorithms in
+ the SHA family [FIPS 180-2, RFC 3874, SHA2draft] with 224, 256, 384,
+ and 512 bits, may be preferred in some cases particularly since
+ increasingly successful cryptanalytic attacks are being made on the
+ shorter hashes.
+
+ Use of TSIG between a DNS resolver and server is by mutual agreement.
+ That agreement can include the support of additional algorithms and
+ criteria as to which algorithms and truncations are acceptable,
+ subject to the restriction and guidelines in Section 3 and 4 below.
+ Key agreement can be by the TKEY mechanism [RFC 2930] or other
+ mutually agreeable method.
+
+ The current HMAC-MD5.SIG-ALG.REG.INT and gss-tsig identifiers are
+ included in the table below for convenience. Implementations which
+ support TSIG MUST also implement HMAC SHA1 and HMAC SHA256 and MAY
+ implement gss-tsig and the other algorithms listed below.
+
+ Mandatory HMAC-MD5.SIG-ALG.REG.INT
+ Optional gss-tsig
+ Mandatory hmac-sha1
+ Optional hmac-sha224
+ Mandatory hmac-sha256
+ Optional hamc-sha384
+ Optional hmac-sha512
+
+ SHA-1 truncated to 96 bits (12 octets) SHOULD be implemented.
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 4]
+
+
+INTERNET-DRAFT HMAC-SHA TSIG Identifiers
+
+
+3. Specifying Truncation
+
+ When space is at a premium and the strength of the full length of an
+ HMAC is not needed, it is reasonable to truncate the HMAC output and
+ use the truncated value for authentication. HMAC SHA-1 truncated to
+ 96 bits is an option available in several IETF protocols including
+ IPSEC and TLS.
+
+ The TSIG RR [RFC 2845] includes a "MAC size" field, which gives the
+ size of the MAC field in octets. But [RFC 2845] does not specify what
+ to do if this MAC size differs from the length of the output of HMAC
+ for a particular hash function. Truncation is indicated by a MAC size
+ less than the HMAC size as specified below.
+
+
+
+3.1 Truncation Specification
+
+ The specification for TSIG handling is changed as follows:
+
+ 1. If "MAC size" field is greater than HMAC output length:
+ This case MUST NOT be generated and if received MUST cause the
+ packet to be dropped and RCODE 1 (FORMERR) to be returned.
+
+ 2. If "MAC size" field equals HMAC output length:
+ Operation is as described in [RFC 2845] with the entire output
+ HMAC output present.
+
+ 3. "MAC size" field is less than HMAC output length but greater than
+ that specified in case 4 below:
+ This is sent when the signer has truncated the HMAC output to
+ an allowable length, as described in RFC 2104, taking initial
+ octets and discarding trailing octets. TSIG truncation can only be
+ to an integral number of octets. On receipt of a packet with
+ truncation thus indicated, the locally calculated MAC is similarly
+ truncated and only the truncated values compared for
+ authentication. The request MAC used when calculating the TSIG MAC
+ for a reply is the truncated request MAC.
+
+ 4. "MAC size" field is less than the larger of 10 (octets) and half
+ the length of the hash function in use:
+ With the exception of certain TSIG error messages described in
+ RFC 2845 section 3.2 where it is permitted that the MAC size be
+ zero, this case MUST NOT be generated and if received MUST cause
+ the packet to be dropped and RCODE 1 (FORMERR) to be returned. The
+ size limit for this case can also, for the hash functions
+ mentioned in this document, be stated as less than half the hash
+ function length for hash functions other than MD5 and less than 10
+ octets for MD5.
+
+
+
+D. Eastlake 3rd [Page 5]
+
+
+INTERNET-DRAFT HMAC-SHA TSIG Identifiers
+
+
+4. TSIG Truncation Policy and Error Provisions
+
+ Use of TSIG is by mutual agreement between a resolver and server.
+ Implicit in such "agreement" are criterion as to acceptable keys and
+ algorithms and, with the extensions in this document, truncations.
+ Note that it is common for implementations to bind the TSIG secret
+ key or keys that may be in place at a resolver and server to
+ particular algorithms. Thus such implementations only permit the use
+ of an algorithm if there is an associated key in place. Receipt of an
+ unknown, unimplemented, or disabled algorithm typically results in a
+ BADKEY error.
+
+ Local policies MAY require the rejection of TSIGs even though they
+ use an algorithm for which implementation is mandatory.
+
+ When a local policy permits acceptance of a TSIG with a particular
+ algorithm and a particular non-zero amount of truncation it SHOULD
+ also permit the use of that algorithm with lesser truncation (a
+ longer MAC) up to the full HMAC output.
+
+ Regardless of a lower acceptable truncated MAC length specified by
+ local policy, a reply SHOULD be sent with a MAC at least as long as
+ that in the corresponding request unless the request specified a MAC
+ length longer than the HMAC output.
+
+ Implementations permitting multiple acceptable algorithms and/or
+ truncations SHOULD permit this list to be ordered by presumed
+ strength and SHOULD allow different truncations for the same
+ algorithm to be treated as separate entities in this list. When so
+ implemented, policies SHOULD accept a presumed stronger algorithm and
+ truncation than the minimum strength required by the policy.
+
+ If a TSIG is received with truncation which is permitted under
+ Section 3 above but the MAC is too short for the local policy in
+ force, an RCODE of TBA [22 suggested](BADTRUNC) MUST be returned.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 6]
+
+
+INTERNET-DRAFT HMAC-SHA TSIG Identifiers
+
+
+5. IANA Considerations
+
+ This document, on approval for publication as a standards track RFC,
+ (1) registers the new TSIG algorithm identifiers listed in Section 2
+ with IANA and (2) allocates the BADTRUNC RCODE TBA [22 suggested] in
+ Section 4. [RFC 2845]
+
+
+
+6. Security Considerations
+
+ For all of the message authentication code algorithms listed herein,
+ those producing longer values are believed to be stronger; however,
+ while there have been some arguments that mild truncation can
+ strengthen a MAC by reducing the information available to an
+ attacker, excessive truncation clearly weakens authentication by
+ reducing the number of bits an attacker has to try to break the
+ authentication by brute force [RFC 2104].
+
+ Significant progress has been made recently in cryptanalysis of hash
+ function of the type used herein, all of which ultimately derive from
+ the design of MD4. While the results so far should not effect HMAC,
+ the stronger SHA-1 and SHA-256 algorithms are being made mandatory
+ due to caution.
+
+ See the Security Considerations section of [RFC 2845]. See also the
+ Security Considerations section of [RFC 2104] from which the limits
+ on truncation in this RFC were taken.
+
+
+
+7. Copyright and Disclaimer
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+D. Eastlake 3rd [Page 7]
+
+
+INTERNET-DRAFT HMAC-SHA TSIG Identifiers
+
+
+8. Normative References
+
+ [FIPS 180-2] - "Secure Hash Standard", (SHA-1/224/256/384/512) US
+ Federal Information Processing Standard, with Change Notice 1,
+ February 2004.
+
+ [RFC 1321] - Rivest, R., "The MD5 Message-Digest Algorithm ", RFC
+ 1321, April 1992.
+
+ [RFC 2104] - Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
+ Hashing for Message Authentication", RFC 2104, February 1997.
+
+ [RFC 2119] - Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC 2845] - Vixie, P., Gudmundsson, O., Eastlake 3rd, D., and B.
+ Wellington, "Secret Key Transaction Authentication for DNS (TSIG)",
+ RFC 2845, May 2000.
+
+ [RFC 3174] - Eastlake 3rd, D. and P. Jones, "US Secure Hash Algorithm
+ 1 (SHA1)", RFC 3174, September 2001.
+
+ [RFC 3874] - R. Housely, "A 224-bit One-way Hash Function: SHA-224",
+ September 2004,
+
+ [SHA2draft] - Eastlake, D., T. Hansen, "US Secure Hash Algorithms
+ (SHA)", draft-eastlake-sha2-*.txt, work in progress.
+
+ [STD 13]
+ Mockapetris, P., "Domain names - concepts and facilities", STD
+ 13, RFC 1034, November 1987.
+
+ Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+
+
+9. Informative References.
+
+ [RFC 2930] - Eastlake 3rd, D., "Secret Key Establishment for DNS
+ (TKEY RR)", RFC 2930, September 2000.
+
+ [RFC 2931] - Eastlake 3rd, D., "DNS Request and Transaction
+ Signatures ( SIG(0)s )", RFC 2931, September 2000.
+
+ [RFC 3645] - Kwan, S., Garg, P., Gilroy, J., Esibov, L., Westhead,
+ J., and R. Hall, "Generic Security Service Algorithm for Secret Key
+ Transaction Authentication for DNS (GSS-TSIG)", RFC 3645, October
+ 2003.
+
+
+
+D. Eastlake 3rd [Page 8]
+
+
+INTERNET-DRAFT HMAC-SHA TSIG Identifiers
+
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ Motorola Laboratories
+ 155 Beaver Street
+ Milford, MA 01757 USA
+
+ Telephone: +1-508-786-7554 (w)
+
+ EMail: Donald.Eastlake@motorola.com
+
+
+
+Additional IPR Provisions
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed
+ to pertain to the implementation or use of the technology
+ described in this document or the extent to which any license
+ under such rights might or might not be available; nor does it
+ represent that it has made any independent effort to identify any
+ such rights. Information on the procedures with respect to
+ rights in RFC documents can be found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use
+ of such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository
+ at http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention
+ any copyrights, patents or patent applications, or other
+ proprietary rights that may cover technology that may be required
+ to implement this standard. Please address the information to the
+ IETF at ietf-ipr@ietf.org.
+
+
+
+Expiration and File Name
+
+ This draft expires in July 2006.
+
+ Its file name is draft-ietf-dnsext-tsig-sha-06.txt
+
+
+
+
+
+
+
+
+D. Eastlake 3rd [Page 9]
+
diff --git a/doc/draft/draft-ietf-dnsext-wcard-clarify-10.txt b/doc/draft/draft-ietf-dnsext-wcard-clarify-10.txt
new file mode 100644
index 0000000..9cf88a5
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsext-wcard-clarify-10.txt
@@ -0,0 +1,1063 @@
+Internet-Draft dnsext-wcard January 9, 2006
+
+DNSEXT Working Group E. Lewis
+INTERNET DRAFT NeuStar
+Expiration Date: July 9, 2006 January 9, 2006
+Updates RFC 1034, RFC 2672
+
+ The Role of Wildcards
+ in the Domain Name System
+ draft-ietf-dnsext-wcard-clarify-10.txt
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that
+ any applicable patent or other IPR claims of which he or she is
+ aware have been or will be disclosed, and any of which he or she
+ becomes aware will be disclosed, in accordance with Section 6 of
+ BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six
+ months and may be updated, replaced, or obsoleted by other
+ documents at any time. It is inappropriate to use Internet-Drafts
+ as reference material or to cite them other than as "work in
+ progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+ This Internet-Draft will expire on July 9, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ This is an update to the wildcard definition of RFC 1034. The
+ interaction with wildcards and CNAME is changed, an error
+ condition removed, and the words defining some concepts central
+ to wildcards are changed. The overall goal is not to change
+ wildcards, but to refine the definition of RFC 1034.
+
+
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 1]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+Table of Contents
+
+1. Introduction . . . . . . . . . . . . . . . . 3
+1 1 Motivation 3
+1 2 The Original Definition 3
+1 3 Roadmap to This Document 4
+1 3 1 New Terms 4
+1.3.2 Changed Text 5
+1.3.3 Considerations with Special Types 5
+1.4 Standards Terminology 5
+2. Wildcard Syntax . . . . . . . . . . . . . . . 6
+2.1 Identifying a Wildcard 6
+2.1.1 Wild Card Domain Name and Asterisk Label 6
+2.1.2 Asterisks and Other Characters 6
+2.1.3 Non-terminal Wild Card Domain Names 6
+2.2 Existence Rules 7
+2.2.1 An Example 7
+2.2.2 Empty Non-terminals 9
+2.2.3 Yet Another Definition of Existence 10
+2.3 When is a Wild Card Domain Name Not Special 10
+3. Impact of a Wild Card Domain Name On a Response . . . . . 10
+3.1 Step 2 10
+3.2 Step 3 11
+3.3 Part 'c' 11
+3.3.1 Closest Encloser and the Source of Synthesis 12
+3.3.2 Closest Encloser and Source of Synthesis Examples 12
+3.3.3 Type Matching 13
+4. Considerations with Special Types . . . . . . . . . 13
+4.1 SOA RRSet at a Wild Card Domain Name 13
+4.2 NS RRSet at a Wild Card Domain Name 14
+4.2.1 Discarded Notions 14
+4.3 CNAME RRSet at a Wild Card Domain Name 15
+4.4 DNAME RRSet at a Wild Card Domain Name 15
+4.5 SRV RRSet at a Wild Card Domain Name 16
+4.6 DS RRSet at a Wild Card Domain Name 16
+4.7 NSEC RRSet at a Wild Card Domain Name 17
+4.8 RRSIG at a Wild Card Domain Name 17
+4.9 Empty Non-terminal Wild Card Domain Name 17
+5. Security Considerations . . . . . . . . . . . . . 17
+6. IANA Considerations . . . . . . . . . . . . . 17
+7. References . . . . . . . . . . . . . 17
+8. Editor . . . . . . . . . . . . . 18
+9. Others Contributing to the Document . . . . . . . . 18
+10. Trailing Boilerplate . . . . . . . . . . . . . 19
+
+
+
+
+
+
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 2]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+1. Introduction
+
+ In RFC 1034 [RFC1034], sections 4.3.2 and 4.3.3 describe the
+ synthesis of answers from special resource records called
+ wildcards. The definition in RFC 1034 is incomplete and has
+ proven to be confusing. This document describes the wildcard
+ synthesis by adding to the discussion and making limited
+ modifications. Modifications are made to close inconsistencies
+ that have led to interoperability issues. This description
+ does not expand the service intended by the original definition.
+
+ Staying within the spirit and style of the original documents,
+ this document avoids specifying rules for DNS implementations
+ regarding wildcards. The intention is to only describe what is
+ needed for interoperability, not restrict implementation choices.
+ In addition, consideration is given to minimize any backwards
+ compatibility issues with implementations that comply with RFC
+ 1034's definition.
+
+ This document is focused on the concept of wildcards as defined
+ in RFC 1034. Nothing is implied regarding alternative means of
+ synthesizing resource record sets, nor are alternatives discussed.
+
+1.1 Motivation
+
+ Many DNS implementations diverge, in different ways, from the
+ original definition of wildcards. Although there is clearly a
+ need to clarify the original documents in light of this alone,
+ the impetus for this document lay in the engineering of the DNS
+ security extensions [RFC4033]. With an unclear definition of
+ wildcards the design of authenticated denial became entangled.
+
+ This document is intended to limit its changes, documenting only
+ those based on implementation experience, and to remain as close
+ to the original document as possible. To reinforce that this
+ document is meant to clarify and adjust and not redefine wildcards,
+ relevant sections of RFC 1034 are repeated verbatim to facilitate
+ comparison of the old and new text.
+
+1.2 The Original Definition
+
+ The definition of the wildcard concept is comprised by the
+ documentation of the algorithm by which a name server prepares
+ a response (in RFC 1034's section 4.3.2) and the way in which
+ a resource record (set) is identified as being a source of
+ synthetic data (section 4.3.3).
+
+ This is the definition of the term "wildcard" as it appears in
+ RFC 1034, section 4.3.3.
+
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 3]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+# In the previous algorithm, special treatment was given to RRs with
+# owner names starting with the label "*". Such RRs are called
+# wildcards. Wildcard RRs can be thought of as instructions for
+# synthesizing RRs. When the appropriate conditions are met, the name
+# server creates RRs with an owner name equal to the query name and
+# contents taken from the wildcard RRs.
+
+ This passage follows the algorithm in which the term wildcard
+ is first used. In this definition, wildcard refers to resource
+ records. In other usage, wildcard has referred to domain names,
+ and it has been used to describe the operational practice of
+ relying on wildcards to generate answers. It is clear from this
+ that there is a need to define clear and unambiguous terminology
+ in the process of discussing wildcards.
+
+ The mention of the use of wildcards in the preparation of a
+ response is contained in step 3c of RFC 1034's section 4.3.2
+ entitled "Algorithm." Note that "wildcard" does not appear in
+ the algorithm, instead references are made to the "*" label.
+ The portion of the algorithm relating to wildcards is
+ deconstructed in detail in section 3 of this document, this is
+ the beginning of the relevant portion of the "Algorithm."
+
+# c. If at some label, a match is impossible (i.e., the
+# corresponding label does not exist), look to see if [...]
+# the "*" label exists.
+
+ The scope of this document is the RFC 1034 definition of
+ wildcards and the implications of updates to those documents,
+ such as DNSSEC. Alternate schemes for synthesizing answers are
+ not considered. (Note that there is no reference listed. No
+ document is known to describe any alternate schemes, although
+ there has been some mention of them in mailing lists.)
+
+1.3 Roadmap to This Document
+
+ This document accomplishes these three items.
+ o Defines new terms
+ o Makes minor changes to avoid conflicting concepts
+ o Describes the actions of certain resource records as wildcards
+
+1.3.1 New Terms
+
+ To help in discussing what resource records are wildcards, two
+ terms will be defined - "asterisk label" and "wild card domain
+ name". These are defined in section 2.1.1.
+
+ To assist in clarifying the role of wildcards in the name server
+ algorithm in RFC 1034, 4.3.2, "source of synthesis" and "closest
+ encloser" are defined. These definitions are in section 3.3.2.
+ "Label match" is defined in section 3.2.
+
+DNSEXT Working Group Expires July 9, 2006 [Page 4]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+ The new terms are used to make discussions of wildcards clearer.
+ Terminology doesn't directly have an impact on implementations.
+
+1.3.2 Changed Text
+
+ The definition of "existence" is changed superficially. This
+ change will not be apparent to implementations; it is needed to
+ make descriptions more precise. The change appears in section
+ 2.2.3.
+
+ RFC 1034, section 4.3.3., seems to prohibit having two asterisk
+ labels in a wildcard owner name. With this document the
+ restriction is removed entirely. This change and its implications
+ are in section 2.1.3.
+
+ The actions when a source of synthesis owns a CNAME RR are
+ changed to mirror the actions if an exact match name owns a
+ CNAME RR. This is an addition to the words in RFC 1034,
+ section 4.3.2, step 3, part c. The discussion of this is in
+ section 3.3.3.
+
+ Only the latter change represents an impact to implementations.
+ The definition of existence is not a protocol impact. The change
+ to the restriction on names is unlikely to have an impact, as
+ RFC 1034 contained no specification on when and how to enforce the
+ restriction.
+
+1.3.3 Considerations with Special Types
+
+ This document describes semantics of wildcard RRSets for
+ "interesting" types as well as empty non-terminal wildcards.
+ Understanding these situations in the context of wildcards has
+ been clouded because these types incur special processing if
+ they are the result of an exact match. This discussion is in
+ section 4.
+
+ These discussions do not have an implementation impact, they cover
+ existing knowledge of the types, but to a greater level of detail.
+
+1.4 Standards Terminology
+
+ This document does not use terms as defined in "Key words for use
+ in RFCs to Indicate Requirement Levels." [RFC2119]
+
+ Quotations of RFC 1034 are denoted by a '#' in the leftmost
+ column. References to section "4.3.2" are assumed to refer
+ to RFC 1034's section 4.3.2, simply titled "Algorithm."
+
+
+
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 5]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+2. Wildcard Syntax
+
+ The syntax of a wildcard is the same as any other DNS resource
+ record, across all classes and types. The only significant
+ feature is the owner name.
+
+ Because wildcards are encoded as resource records with special
+ names, they are included in zone transfers and incremental zone
+ transfers[RFC1995] just as non-wildcard resource records are.
+ This feature has been under appreciated until discussions on
+ alternative approaches to wildcards appeared on mailing lists.
+
+2.1 Identifying a Wildcard
+
+ To provide a more accurate description of wildcards, the
+ definition has to start with a discussion of the domain names
+ that appear as owners. Two new terms are needed, "Asterisk
+ Label" and "Wild Card Domain Name."
+
+2.1.1 Wild Card Domain Name and Asterisk Label
+
+ A "wild card domain name" is defined by having its initial
+ (i.e., left-most or least significant) label be, in binary format:
+
+ 0000 0001 0010 1010 (binary) = 0x01 0x2a (hexadecimal)
+
+ The first octet is the normal label type and length for a 1 octet
+ long label, the second octet is the ASCII representation [RFC20]
+ for the '*' character.
+
+ A descriptive name of a label equaling that value is an "asterisk
+ label."
+
+ RFC 1034's definition of wildcard would be "a resource record
+ owned by a wild card domain name."
+
+2.1.2 Asterisks and Other Characters
+
+ No label values other than that in section 2.1.1 are asterisk
+ labels, hence names beginning with other labels are never wild
+ card domain names. Labels such as 'the*' and '**' are not
+ asterisk labels so these labels do not start wild card domain
+ names.
+
+2.1.3 Non-terminal Wild Card Domain Names
+
+ In section 4.3.3, the following is stated:
+
+# .......................... The owner name of the wildcard RRs is of
+# the form "*.<anydomain>", where <anydomain> is any domain name.
+# <anydomain> should not contain other * labels......................
+
+DNSEXT Working Group Expires July 9, 2006 [Page 6]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+ The restriction is now removed. The original documentation of it
+ is incomplete and the restriction does not serve any purpose
+ given years of operational experience.
+
+ There are three possible reasons for putting the restriction in
+ place, but none of the three has held up over time. One is
+ that the restriction meant that there would never be subdomains
+ of wild card domain names, but the restriciton as stated still
+ permits "example.*.example." for instance. Another is that
+ wild card domain names are not intended to be empty non-terminals,
+ but this situation does not disrupt the algorithm in 4.3.2.
+ Finally, "nested" wild card domain names are not ambiguous once
+ the concept of the closest encloser had been documented.
+
+ A wild card domain name can have subdomains. There is no need
+ to inspect the subdomains to see if there is another asterisk
+ label in any subdomain.
+
+ A wild card domain name can be an empty non-terminal. (See the
+ upcoming sections on empty non-terminals.) In this case, any
+ lookup encountering it will terminate as would any empty
+ non-terminal match.
+
+2.2 Existence Rules
+
+ The notion that a domain name 'exists' is mentioned in the
+ definition of wildcards. In section 4.3.3 of RFC 1034:
+
+# Wildcard RRs do not apply:
+#
+...
+# - When the query name or a name between the wildcard domain and
+# the query name is know[n] to exist. For example, if a wildcard
+
+ "Existence" is therefore an important concept in the understanding
+ of wildcards. Unfortunately, the definition of what exists, in RFC
+ 1034, is unclear. So, in sections 2.2.2. and 2.2.3, another look is
+ taken at the definition of existence.
+
+2.2.1 An Example
+
+ To illustrate what is meant by existence consider this complete
+ zone:
+
+
+
+
+
+
+
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 7]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+ $ORIGIN example.
+ example. 3600 IN SOA <SOA RDATA>
+ example. 3600 NS ns.example.com.
+ example. 3600 NS ns.example.net.
+ *.example. 3600 TXT "this is a wild card"
+ *.example. 3600 MX 10 host1.example.
+ sub.*.example. 3600 TXT "this is not a wild card"
+ host1.example. 3600 A 192.0.4.1
+ _ssh._tcp.host1.example. 3600 SRV <SRV RDATA>
+ _ssh._tcp.host2.example. 3600 SRV <SRV RDATA>
+ subdel.example. 3600 NS ns.example.com.
+ subdel.example. 3600 NS ns.example.net.
+
+ A look at the domain names in a tree structure is helpful:
+
+ |
+ -------------example------------
+ / / \ \
+ / / \ \
+ / / \ \
+ * host1 host2 subdel
+ | | |
+ | | |
+ sub _tcp _tcp
+ | |
+ | |
+ _ssh _ssh
+
+ The following responses would be synthesized from one of the
+ wildcards in the zone:
+
+ QNAME=host3.example. QTYPE=MX, QCLASS=IN
+ the answer will be a "host3.example. IN MX ..."
+
+ QNAME=host3.example. QTYPE=A, QCLASS=IN
+ the answer will reflect "no error, but no data"
+ because there is no A RR set at '*.example.'
+
+ QNAME=foo.bar.example. QTYPE=TXT, QCLASS=IN
+ the answer will be "foo.bar.example. IN TXT ..."
+ because bar.example. does not exist, but the wildcard
+ does.
+
+ The following responses would not be synthesized from any of the
+ wildcards in the zone:
+
+ QNAME=host1.example., QTYPE=MX, QCLASS=IN
+ because host1.example. exists
+
+ QNAME=sub.*.example., QTYPE=MX, QCLASS=IN
+ because sub.*.example. exists
+
+DNSEXT Working Group Expires July 9, 2006 [Page 8]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+ QNAME=_telnet._tcp.host1.example., QTYPE=SRV, QCLASS=IN
+ because _tcp.host1.example. exists (without data)
+
+ QNAME=host.subdel.example., QTYPE=A, QCLASS=IN
+ because subdel.example. exists (and is a zone cut)
+
+ QNAME=ghost.*.example., QTYPE=MX, QCLASS=IN
+ because *.example. exists
+
+ The final example highlights one common misconception about
+ wildcards. A wildcard "blocks itself" in the sense that a
+ wildcard does not match its own subdomains. I.e. "*.example."
+ does not match all names in the "example." zone, it fails to
+ match the names below "*.example." To cover names under
+ "*.example.", another wild card domain name is needed -
+ "*.*.example." - which covers all but it's own subdomains.
+
+2.2.2 Empty Non-terminals
+
+ Empty non-terminals [RFC2136, Section 7.16] are domain names
+ that own no resource records but have subdomains that do. In
+ section 2.2.1, "_tcp.host1.example." is an example of a empty
+ non-terminal name. Empty non-terminals are introduced by this
+ text in section 3.1 of RFC 1034:
+
+# The domain name space is a tree structure. Each node and leaf on
+# the tree corresponds to a resource set (which may be empty). The
+# domain system makes no distinctions between the uses of the
+# interior nodes and leaves, and this memo uses the term "node" to
+# refer to both.
+
+ The parenthesized "which may be empty" specifies that empty non-
+ terminals are explicitly recognized, and that empty non-terminals
+ "exist."
+
+ Pedantically reading the above paragraph can lead to an
+ interpretation that all possible domains exist - up to the
+ suggested limit of 255 octets for a domain name [RFC1035].
+ For example, www.example. may have an A RR, and as far as is
+ practically concerned, is a leaf of the domain tree. But the
+ definition can be taken to mean that sub.www.example. also
+ exists, albeit with no data. By extension, all possible domains
+ exist, from the root on down.
+
+ As RFC 1034 also defines "an authoritative name error indicating
+ that the name does not exist" in section 4.3.1, so this apparently
+ is not the intent of the original definition, justifying the
+ need for an updated definition in the next section.
+
+
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 9]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+2.2.3 Yet Another Definition of Existence
+
+ RFC1034's wording is fixed by the following paragraph:
+
+ The domain name space is a tree structure. Nodes in the tree
+ either own at least one RRSet and/or have descendants that
+ collectively own at least one RRSet. A node may exist with no
+ RRSets only if it has descendents that do, this node is an empty
+ non-terminal.
+
+ A node with no descendants is a leaf node. Empty leaf nodes do
+ not exist.
+
+ Note that at a zone boundary, the domain name owns data,
+ including the NS RR set. In the delegating zone, the NS RR
+ set is not authoritative, but that is of no consequence here.
+ The domain name owns data, therefore, it exists.
+
+2.3 When is a Wild Card Domain Name Not Special
+
+ When a wild card domain name appears in a message's query section,
+ no special processing occurs. An asterisk label in a query name
+ only matches a single, corresponding asterisk label in the
+ existing zone tree when the 4.3.2 algorithm is being followed.
+
+ When a wild card domain name appears in the resource data of a
+ record, no special processing occurs. An asterisk label in that
+ context literally means just an asterisk.
+
+3. Impact of a Wild Card Domain Name On a Response
+
+ RFC 1034's description of how wildcards impact response
+ generation is in its section 4.3.2. That passage contains the
+ algorithm followed by a server in constructing a response.
+ Within that algorithm, step 3, part 'c' defines the behavior of
+ the wildcard.
+
+ The algorithm in section 4.3.2. is not intended to be pseudo-code,
+ i.e., its steps are not intended to be followed in strict order.
+ The "algorithm" is a suggested means of implementing the
+ requirements. As such, in step 3, parts a, b, and c, do not have
+ to be implemented in that order, provided that the result of the
+ implemented code is compliant with the protocol's specification.
+
+3.1 Step 2
+
+ Step 2 of section 4.3.2 reads:
+
+# 2. Search the available zones for the zone which is the nearest
+# ancestor to QNAME. If such a zone is found, go to step 3,
+# otherwise step 4.
+
+DNSEXT Working Group Expires July 9, 2006 [Page 10]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+ In this step, the most appropriate zone for the response is
+ chosen. The significance of this step is that it means all of
+ step 3 is being performed within one zone. This has significance
+ when considering whether or not an SOA RR can be ever be used for
+ synthesis.
+
+3.2 Step 3
+
+ Step 3 is dominated by three parts, labelled 'a', 'b', and 'c'.
+ But the beginning of the step is important and needs explanation.
+
+# 3. Start matching down, label by label, in the zone. The
+# matching process can terminate several ways:
+
+ The word 'matching' refers to label matching. The concept
+ is based in the view of the zone as the tree of existing names.
+ The query name is considered to be an ordered sequence of
+ labels - as if the name were a path from the root to the owner
+ of the desired data. (Which it is - 3rd paragraph of RFC 1034,
+ section 3.1.)
+
+ The process of label matching a query name ends in exactly one of
+ three choices, the parts 'a', 'b', and 'c'. Either the name is
+ found, the name is below a cut point, or the name is not found.
+
+ Once one of the parts is chosen, the other parts are not
+ considered. (E.g., do not execute part 'c' and then change
+ the execution path to finish in part 'b'.) The process of label
+ matching is also done independent of the query type (QTYPE).
+
+ Parts 'a' and 'b' are not an issue for this clarification as they
+ do not relate to record synthesis. Part 'a' is an exact match
+ that results in an answer, part 'b' is a referral.
+
+3.3 Part 'c'
+
+ The context of part 'c' is that the process of label matching the
+ labels of the query name has resulted in a situation in which
+ there is no corresponding label in the tree. It is as if the
+ lookup has "fallen off the tree."
+
+# c. If at some label, a match is impossible (i.e., the
+# corresponding label does not exist), look to see if [...]
+# the "*" label exists.
+
+ To help describe the process of looking 'to see if [...] the "*"
+ label exists' a term has been coined to describe the last domain
+ (node) matched. The term is "closest encloser."
+
+
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 11]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+3.3.1 Closest Encloser and the Source of Synthesis
+
+ The closest encloser is the node in the zone's tree of existing
+ domain names that has the most labels matching the query name
+ (consecutively, counting from the root label downward). Each match
+ is a "label match" and the order of the labels is the same.
+
+ The closest encloser is, by definition, an existing name in the
+ zone. The closest encloser might be an empty non-terminal or even
+ be a wild card domain name itself. In no circumstances is the
+ closest encloser to be used to synthesize records for the current
+ query.
+
+ The source of synthesis is defined in the context of a query
+ process as that wild card domain name immediately descending
+ from the closest encloser, provided that this wild card domain
+ name exists. "Immediately descending" means that the source
+ of synthesis has a name of the form:
+ <asterisk label>.<closest encloser>.
+ A source of synthesis does not guarantee having a RRSet to use
+ for synthesis. The source of synthesis could be an empty
+ non-terminal.
+
+ If the source of synthesis does not exist (not on the domain
+ tree), there will be no wildcard synthesis. There is no search
+ for an alternate.
+
+ The important concept is that for any given lookup process, there
+ is at most one place at which wildcard synthetic records can be
+ obtained. If the source of synthesis does not exist, the lookup
+ terminates, the lookup does not look for other wildcard records.
+
+3.3.2 Closest Encloser and Source of Synthesis Examples
+
+ To illustrate, using the example zone in section 2.2.1 of this
+ document, the following chart shows QNAMEs and the closest
+ enclosers.
+
+ QNAME Closest Encloser Source of Synthesis
+ host3.example. example. *.example.
+ _telnet._tcp.host1.example. _tcp.host1.example. no source
+ _telnet._tcp.host2.example. host2.example. no source
+ _telnet._tcp.host3.example. example. *.example.
+ _chat._udp.host3.example. example. *.example.
+ foobar.*.example. *.example. no source
+
+
+
+
+
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 12]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+3.3.3 Type Matching
+
+ RFC 1034 concludes part 'c' with this:
+
+# If the "*" label does not exist, check whether the name
+# we are looking for is the original QNAME in the query
+# or a name we have followed due to a CNAME. If the name
+# is original, set an authoritative name error in the
+# response and exit. Otherwise just exit.
+#
+# If the "*" label does exist, match RRs at that node
+# against QTYPE. If any match, copy them into the answer
+# section, but set the owner of the RR to be QNAME, and
+# not the node with the "*" label. Go to step 6.
+
+ The final paragraph covers the role of the QTYPE in the lookup
+ process.
+
+ Based on implementation feedback and similarities between step
+ 'a' and step 'c' a change to this passage has been made.
+
+ The change is to add the following text to step 'c' prior to the
+ instructions to "go to step 6":
+
+ If the data at the source of synthesis is a CNAME, and
+ QTYPE doesn't match CNAME, copy the CNAME RR into the
+ answer section of the response changing the owner name
+ to the QNAME, change QNAME to the canonical name in the
+ CNAME RR, and go back to step 1.
+
+ This is essentially the same text in step a covering the
+ processing of CNAME RRSets.
+
+4. Considerations with Special Types
+
+ Sections 2 and 3 of this document discuss wildcard synthesis
+ with respect to names in the domain tree and ignore the impact
+ of types. In this section, the implication of wildcards of
+ specific types are discussed. The types covered are those
+ that have proven to be the most difficult to understand. The
+ types are SOA, NS, CNAME, DNAME, SRV, DS, NSEC, RRSIG and
+ "none," i.e., empty non-terminal wild card domain names.
+
+4.1 SOA RRSet at a Wild Card Domain Name
+
+ A wild card domain name owning an SOA RRSet means that the
+ domain is at the root of the zone (apex). The domain can not
+ be a source of synthesis because that is, by definition, a
+ descendent node (of the closest encloser) and a zone apex is
+ at the top of the zone.
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 13]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+ Although a wild card domain name owning an SOA RRSet can never
+ be a source of synthesis, there is no reason to forbid the
+ ownership of an SOA RRSet.
+
+ E.g., given this zone:
+ $ORIGIN *.example.
+ @ 3600 IN SOA <SOA RDATA>
+ 3600 NS ns1.example.com.
+ 3600 NS ns1.example.net.
+ www 3600 TXT "the www txt record"
+
+ A query for www.*.example.'s TXT record would still find the
+ "the www txt record" answer. The asterisk label only becomes
+ significant when section 4.3.2, step 3 part 'c' is in effect.
+
+ Of course, there would need to be a delegation in the parent
+ zone, "example." for this to work too. This is covered in the
+ next section.
+
+4.2 NS RRSet at a Wild Card Domain Name
+
+ With the definition of DNSSEC [RFC4033, RFC4034, RFC4035] now
+ in place, the semantics of a wild card domain name owning an
+ NS RRSet has come to be poorly defined. The dilemma relates to
+ a conflict between the rules for synthesis in part 'c' and the
+ fact that the resulting synthesis generates a record for which
+ the zone is not authoritative. In a DNSSEC signed zone, the
+ mechanics of signature management (generation and inclusion
+ in a message) have become unclear.
+
+ Salient points of the working group discussion on this topic is
+ summarized in section 4.2.1.
+
+ As a result of these discussion, there is no definition given for
+ wild card domain names owning an NS RRSet. The semantics are
+ left undefined until there is a clear need to have a set defined,
+ and until there is a clear direction to proceed. Operationally,
+ inclusion of wild card NS RRSets in a zone is discouraged, but
+ not barred.
+
+4.2.1 Discarded Notions
+
+ Prior to DNSSEC, a wild card domain name owning a NS RRSet
+ appeared to be workable, and there are some instances in which
+ it is found in deployments using implementations that support
+ this. Continuing to allow this in the specification is not
+ tenable with DNSSEC. The reason is that the synthesis of the
+ NS RRSet is being done in a zone that has delegated away the
+ responsibility for the name. This "unauthorized" synthesis is
+ not a problem for the base DNS protocol, but DNSSEC, in affirming
+ the authorization model for DNS exposes the problem.
+
+DNSEXT Working Group Expires July 9, 2006 [Page 14]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+ Outright banning of wildcards of type NS is also untenable as
+ the DNS protocol does not define how to handle "illegal" data.
+ Implementations may choose not to load a zone, but there is no
+ protocol definition. The lack of the definition is complicated
+ by having to cover dynamic update [RFC 2136], zone transfers,
+ as well as loading at the master server. The case of a client
+ (resolver, caching server) getting a wildcard of type NS in
+ a reply would also have to be considered.
+
+ Given the daunting challenge of a complete definition of how to
+ ban such records, dealing with existing implementations that
+ permit the records today is a further complication. There are
+ uses of wild card domain name owning NS RRSets.
+
+ One compromise proposed would have redefined wildcards of type
+ NS to not be used in synthesis, this compromise fell apart
+ because it would have required significant edits to the DNSSEC
+ signing and validation work. (Again, DNSSEC catches
+ unauthorized data.)
+
+ With no clear consensus forming on the solution to this dilemma,
+ and the realization that wildcards of type NS are a rarity in
+ operations, the best course of action is to leave this open-ended
+ until "it matters."
+
+4.3 CNAME RRSet at a Wild Card Domain Name
+
+ The issue of a CNAME RRSet owned by a wild card domain name has
+ prompted a suggested change to the last paragraph of step 3c of
+ the algorithm in 4.3.2. The changed text appears in section
+ 3.3.3 of this document.
+
+4.4 DNAME RRSet at a Wild Card Domain Name
+
+ Ownership of a DNAME [RFC2672] RRSet by a wild card domain name
+ represents a threat to the coherency of the DNS and is to be
+ avoided or outright rejected. Such a DNAME RRSet represents
+ non-deterministic synthesis of rules fed to different caches.
+ As caches are fed the different rules (in an unpredictable
+ manner) the caches will cease to be coherent. ("As caches
+ are fed" refers to the storage in a cache of records obtained
+ in responses by recursive or iterative servers.)
+
+ For example, assume one cache, responding to a recursive
+ request, obtains the record:
+ "a.b.example. DNAME foo.bar.example.net."
+ and another cache obtains:
+ "b.example. DNAME foo.bar.example.net."
+ both generated from the record:
+ "*.example. DNAME foo.bar.example.net."
+ by an authoritative server.
+
+DNSEXT Working Group Expires July 9, 2006 [Page 15]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+ The DNAME specification is not clear on whether DNAME records
+ in a cache are used to rewrite queries. In some interpretations,
+ the rewrite occurs, in some, it is not. Allowing for the
+ occurrence of rewriting, queries for "sub.a.b.example. A" may
+ be rewritten as "sub.foo.bar.tld. A" by the former caching
+ server and may be rewritten as "sub.a.foo.bar.tld. A" by the
+ latter. Coherency is lost, an operational nightmare ensues.
+
+ Another justification for banning or avoiding wildcard DNAME
+ records is the observation that such a record could synthesize
+ a DNAME owned by "sub.foo.bar.example." and "foo.bar.example."
+ There is a restriction in the DNAME definition that no domain
+ exist below a DNAME-owning domain, hence, the wildcard DNAME
+ is not to be permitted.
+
+4.5 SRV RRSet at a Wild Card Domain Name
+
+ The definition of the SRV RRset is RFC 2782 [RFC2782]. In the
+ definition of the record, there is some confusion over the term
+ "Name." The definition reads as follows:
+
+# The format of the SRV RR
+...
+# _Service._Proto.Name TTL Class SRV Priority Weight Port Target
+...
+# Name
+# The domain this RR refers to. The SRV RR is unique in that the
+# name one searches for is not this name; the example near the end
+# shows this clearly.
+
+ Do not confuse the definition "Name" with the owner name. I.e.,
+ once removing the _Service and _Proto labels from the owner name
+ of the SRV RRSet, what remains could be a wild card domain name
+ but this is immaterial to the SRV RRSet.
+
+ E.g., If an SRV record is:
+ _foo._udp.*.example. 10800 IN SRV 0 1 9 old-slow-box.example.
+
+ *.example is a wild card domain name and although it is the Name
+ of the SRV RR, it is not the owner (domain name). The owner
+ domain name is "_foo._udp.*.example." which is not a wild card
+ domain name.
+
+ The confusion is likely based on the mixture of the specification
+ of the SRV RR and the description of a "use case."
+
+4.6 DS RRSet at a Wild Card Domain Name
+
+ A DS RRSet owned by a wild card domain name is meaningless and
+ harmless. This statement is made in the context that an NS RRSet
+ at a wild card domain name is undefined. At a non-delegation
+
+DNSEXT Working Group Expires July 9, 2006 [Page 16]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+ point, a DS RRSet has no value (no corresponding DNSKEY RRSet
+ will be used in DNSSEC validation). If there is a synthesized
+ DS RRSet, it alone will not be very useful as it exists in the
+ context of a delegation point.
+
+4.7 NSEC RRSet at a Wild Card Domain Name
+
+ Wild card domain names in DNSSEC signed zones will have an NSEC
+ RRSet. Synthesis of these records will only occur when the
+ query exactly matches the record. Synthesized NSEC RR's will not
+ be harmful as they will never be used in negative caching or to
+ generate a negative response. [RFC2308]
+
+4.8 RRSIG at a Wild Card Domain Name
+
+ RRSIG records will be present at a wild card domain name in a
+ signed zone, and will be synthesized along with data sought in a
+ query. The fact that the owner name is synthesized is not a
+ problem as the label count in the RRSIG will instruct the
+ verifying code to ignore it.
+
+4.9 Empty Non-terminal Wild Card Domain Name
+
+ If a source of synthesis is an empty non-terminal, then the
+ response will be one of no error in the return code and no RRSet
+ in the answer section.
+
+5. Security Considerations
+
+ This document is refining the specifications to make it more
+ likely that security can be added to DNS. No functional
+ additions are being made, just refining what is considered
+ proper to allow the DNS, security of the DNS, and extending
+ the DNS to be more predictable.
+
+6. IANA Considerations
+
+ None.
+
+7. References
+
+ Normative References
+
+ [RFC20] ASCII Format for Network Interchange, V.G. Cerf,
+ Oct-16-1969
+
+ [RFC1034] Domain Names - Concepts and Facilities,
+ P.V. Mockapetris, Nov-01-1987
+
+ [RFC1035] Domain Names - Implementation and Specification, P.V
+ Mockapetris, Nov-01-1987
+
+DNSEXT Working Group Expires July 9, 2006 [Page 17]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+ [RFC1995] Incremental Zone Transfer in DNS, M. Ohta, August 1996
+
+ [RFC2119] Key Words for Use in RFCs to Indicate Requirement
+ Levels, S Bradner, March 1997
+
+ [RFC2308] Negative Caching of DNS Queries (DNS NCACHE),
+ M. Andrews, March 1998
+
+ [RFC2672] Non-Terminal DNS Name Redirection, M. Crawford,
+ August 1999.
+
+ [RFC2782] A DNS RR for specifying the location of services (DNS
+ SRV), A. Gulbrandsen, et.al., February 2000
+
+ [RFC4033] DNS Security Introduction and Requirements, R. Arends,
+ et.al., March 2005
+
+ [RFC4034] Resource Records for the DNS Security Extensions,
+ R. Arends, et.al., March 2005
+
+ [RFC4035] Protocol Modifications for the DNS Security Extensions,
+ R. Arends, et.al., March 2005
+
+ Informative References
+
+ [RFC2136] Dynamic Updates in the Domain Name System (DNS UPDATE),
+ P. Vixie, Ed., S. Thomson, Y. Rekhter, J. Bound,
+ April 1997
+
+8. Editor
+
+ Name: Edward Lewis
+ Affiliation: NeuStar
+ Address: 46000 Center Oak Plaza, Sterling, VA, 20166, US
+ Phone: +1-571-434-5468
+ Email: ed.lewis@neustar.biz
+
+ Comments on this document can be sent to the editor or the mailing
+ list for the DNSEXT WG, namedroppers@ops.ietf.org.
+
+9. Others Contributing to the Document
+
+ This document represents the work of a large working group. The
+ editor merely recorded the collective wisdom of the working group.
+
+
+
+
+
+
+
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 17]
+
+Internet-Draft dnsext-wcard January 9, 2006
+
+10. Trailing Boilerplate
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided
+ on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION
+ HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET
+ SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL
+ WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+ ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT
+ INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of
+ any Intellectual Property Rights or other rights that might
+ be claimed to pertain to the implementation or use of the
+ technology described in this document or the extent to which
+ any license under such rights might or might not be available;
+ nor does it represent that it has made any independent effort
+ to identify any such rights. Information on the procedures
+ with respect to rights in RFC documents can be found in BCP 78
+ and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the
+ use of such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR
+ repository at http://www.ietf.org/ipr. The IETF invites any
+ interested party to bring to its attention any copyrights,
+ patents or patent applications, or other proprietary rights
+ that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+Expiration
+
+ This document expires on or about July 9, 2006.
+
+
+
+DNSEXT Working Group Expires July 9, 2006 [Page 19]
diff --git a/doc/draft/draft-ietf-dnsop-bad-dns-res-05.txt b/doc/draft/draft-ietf-dnsop-bad-dns-res-05.txt
new file mode 100644
index 0000000..0855ba3
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsop-bad-dns-res-05.txt
@@ -0,0 +1,1232 @@
+
+
+
+DNS Operations M. Larson
+Internet-Draft P. Barber
+Expires: August 14, 2006 VeriSign
+ February 10, 2006
+
+
+ Observed DNS Resolution Misbehavior
+ draft-ietf-dnsop-bad-dns-res-05
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on August 14, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ This memo describes DNS iterative resolver behavior that results in a
+ significant query volume sent to the root and top-level domain (TLD)
+ name servers. We offer implementation advice to iterative resolver
+ developers to alleviate these unnecessary queries. The
+ recommendations made in this document are a direct byproduct of
+ observation and analysis of abnormal query traffic patterns seen at
+ two of the thirteen root name servers and all thirteen com/net TLD
+ name servers.
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 1]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [1].
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1. A note about terminology in this memo . . . . . . . . . . 3
+ 2. Observed iterative resolver misbehavior . . . . . . . . . . . 5
+ 2.1. Aggressive requerying for delegation information . . . . . 5
+ 2.1.1. Recommendation . . . . . . . . . . . . . . . . . . . . 6
+ 2.2. Repeated queries to lame servers . . . . . . . . . . . . . 7
+ 2.2.1. Recommendation . . . . . . . . . . . . . . . . . . . . 7
+ 2.3. Inability to follow multiple levels of indirection . . . . 8
+ 2.3.1. Recommendation . . . . . . . . . . . . . . . . . . . . 9
+ 2.4. Aggressive retransmission when fetching glue . . . . . . . 9
+ 2.4.1. Recommendation . . . . . . . . . . . . . . . . . . . . 10
+ 2.5. Aggressive retransmission behind firewalls . . . . . . . . 10
+ 2.5.1. Recommendation . . . . . . . . . . . . . . . . . . . . 11
+ 2.6. Misconfigured NS records . . . . . . . . . . . . . . . . . 11
+ 2.6.1. Recommendation . . . . . . . . . . . . . . . . . . . . 12
+ 2.7. Name server records with zero TTL . . . . . . . . . . . . 12
+ 2.7.1. Recommendation . . . . . . . . . . . . . . . . . . . . 13
+ 2.8. Unnecessary dynamic update messages . . . . . . . . . . . 13
+ 2.8.1. Recommendation . . . . . . . . . . . . . . . . . . . . 14
+ 2.9. Queries for domain names resembling IPv4 addresses . . . . 14
+ 2.9.1. Recommendation . . . . . . . . . . . . . . . . . . . . 14
+ 2.10. Misdirected recursive queries . . . . . . . . . . . . . . 15
+ 2.10.1. Recommendation . . . . . . . . . . . . . . . . . . . . 15
+ 2.11. Suboptimal name server selection algorithm . . . . . . . . 15
+ 2.11.1. Recommendation . . . . . . . . . . . . . . . . . . . . 16
+ 3. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 17
+ 4. IANA considerations . . . . . . . . . . . . . . . . . . . . . 18
+ 5. Security considerations . . . . . . . . . . . . . . . . . . . 19
+ 6. Internationalization considerations . . . . . . . . . . . . . 20
+ 7. Informative References . . . . . . . . . . . . . . . . . . . . 20
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 21
+ Intellectual Property and Copyright Statements . . . . . . . . . . 22
+
+
+
+
+
+
+
+
+
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 2]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+1. Introduction
+
+ Observation of query traffic received by two root name servers and
+ the thirteen com/net TLD name servers has revealed that a large
+ proportion of the total traffic often consists of "requeries". A
+ requery is the same question (<QNAME, QTYPE, QCLASS>) asked
+ repeatedly at an unexpectedly high rate. We have observed requeries
+ from both a single IP address and multiple IP addresses (i.e., the
+ same query received simultaneously from multiple IP addresses).
+
+ By analyzing requery events we have found that the cause of the
+ duplicate traffic is almost always a deficient iterative resolver,
+ stub resolver or application implementation combined with an
+ operational anomaly. The implementation deficiencies we have
+ identified to date include well-intentioned recovery attempts gone
+ awry, insufficient caching of failures, early abort when multiple
+ levels of indirection must be followed, and aggressive retry by stub
+ resolvers or applications. Anomalies that we have seen trigger
+ requery events include lame delegations, unusual glue records, and
+ anything that makes all authoritative name servers for a zone
+ unreachable (DoS attacks, crashes, maintenance, routing failures,
+ congestion, etc.).
+
+ In the following sections, we provide a detailed explanation of the
+ observed behavior and recommend changes that will reduce the requery
+ rate. None of the changes recommended affects the core DNS protocol
+ specification; instead, this document consists of guidelines to
+ implementors of iterative resolvers.
+
+1.1. A note about terminology in this memo
+
+ To recast an old saying about standards, the nice thing about DNS
+ terms is that there are so many of them to choose from. Writing or
+ talking about DNS can be difficult and cause confusion resulting from
+ a lack of agreed-upon terms for its various components. Further
+ complicating matters are implementations that combine multiple roles
+ into one piece of software, which makes naming the result
+ problematic. An example is the entity that accepts recursive
+ queries, issues iterative queries as necessary to resolve the initial
+ recursive query, caches responses it receives, and which is also able
+ to answer questions about certain zones authoritatively. This entity
+ is an iterative resolver combined with an authoritative name server
+ and is often called a "recursive name server" or a "caching name
+ server".
+
+ This memo is concerned principally with the behavior of iterative
+ resolvers, which are typically found as part of a recursive name
+ server. This memo uses the more precise term "iterative resolver",
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 3]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ because the focus is usually on that component. In instances where
+ the name server role of this entity requires mentioning, this memo
+ uses the term "recursive name server". As an example of the
+ difference, the name server component of a recursive name server
+ receives DNS queries and the iterative resolver component sends
+ queries.
+
+ The advent of IPv6 requires mentioning AAAA records as well as A
+ records when discussing glue. To avoid continuous repetition and
+ qualification, this memo uses the general term "address record" to
+ encompass both A and AAAA records when a particular situation is
+ relevant to both types.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 4]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+2. Observed iterative resolver misbehavior
+
+2.1. Aggressive requerying for delegation information
+
+ There can be times when every name server in a zone's NS RRset is
+ unreachable (e.g., during a network outage), unavailable (e.g., the
+ name server process is not running on the server host) or
+ misconfigured (e.g., the name server is not authoritative for the
+ given zone, also known as "lame"). Consider an iterative resolver
+ that attempts to resolve a query for a domain name in such a zone and
+ discovers that none of the zone's name servers can provide an answer.
+ We have observed a recursive name server implementation whose
+ iterative resolver then verifies the zone's NS RRset in its cache by
+ querying for the zone's delegation information: it sends a query for
+ the zone's NS RRset to one of the parent zone's name servers. (Note
+ that queries with QTYPE=NS are not required by the standard
+ resolution algorithm described in section 4.3.2 of RFC 1034 [2].
+ These NS queries represent this implementation's addition to that
+ algorithm.)
+
+ For example, suppose that "example.com" has the following NS RRset:
+
+ example.com. IN NS ns1.example.com.
+ example.com. IN NS ns2.example.com.
+
+ Upon receipt of a query for "www.example.com" and assuming that
+ neither "ns1.example.com" nor "ns2.example.com" can provide an
+ answer, this iterative resolver implementation immediately queries a
+ "com" zone name server for the "example.com" NS RRset to verify it
+ has the proper delegation information. This implementation performs
+ this query to a zone's parent zone for each recursive query it
+ receives that fails because of a completely unresponsive set of name
+ servers for the target zone. Consider the effect when a popular zone
+ experiences a catastrophic failure of all its name servers: now every
+ recursive query for domain names in that zone sent to this recursive
+ name server implementation results in a query to the failed zone's
+ parent name servers. On one occasion when several dozen popular
+ zones became unreachable, the query load on the com/net name servers
+ increased by 50%.
+
+ We believe this verification query is not reasonable. Consider the
+ circumstances: When an iterative resolver is resolving a query for a
+ domain name in a zone it has not previously searched, it uses the
+ list of name servers in the referral from the target zone's parent.
+ If on its first attempt to search the target zone, none of the name
+ servers in the referral is reachable, a verification query to the
+ parent would be pointless: this query to the parent would come so
+ quickly on the heels of the referral that it would be almost certain
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 5]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ to contain the same list of name servers. The chance of discovering
+ any new information is slim.
+
+ The other possibility is that the iterative resolver successfully
+ contacts one of the target zone's name servers and then caches the NS
+ RRset from the authority section of a response, the proper behavior
+ according to section 5.4.1 of RFC 2181 [3], because the NS RRset from
+ the target zone is more trustworthy than delegation information from
+ the parent zone. If, while processing a subsequent recursive query,
+ the iterative resolver discovers that none of the name servers
+ specified in the cached NS RRset is available or authoritative,
+ querying the parent would be wrong. An NS RRset from the parent zone
+ would now be less trustworthy than data already in the cache.
+
+ For this query of the parent zone to be useful, the target zone's
+ entire set of name servers would have to change AND the former set of
+ name servers would have to be deconfigured or decommissioned AND the
+ delegation information in the parent zone would have to be updated
+ with the new set of name servers, all within the TTL of the target
+ zone's NS RRset. We believe this scenario is uncommon:
+ administrative best practices dictate that changes to a zone's set of
+ name servers happen gradually when at all possible, with servers
+ removed from the NS RRset left authoritative for the zone as long as
+ possible. The scenarios that we can envision that would benefit from
+ the parent requery behavior do not outweigh its damaging effects.
+
+ This section should not be understood to claim that all queries to a
+ zone's parent are bad. In some cases, such queries are not only
+ reasonable but required. Consider the situation when required
+ information, such as the address of a name server (i.e., the address
+ record corresponding to the RDATA of an NS record), has timed out of
+ an iterative resolver's cache before the corresponding NS record. If
+ the name of the name server is below the apex of the zone, then the
+ name server's address record is only available as glue in the parent
+ zone. For example, consider this NS record:
+
+ example.com. IN NS ns.example.com.
+
+ If a cache has this NS record but not the address record for
+ "ns.example.com", it is unable to contact the "example.com" zone
+ directly and must query the "com" zone to obtain the address record.
+ Note, however, that such a query would not have QTYPE=NS according to
+ the standard resolution algorithm.
+
+2.1.1. Recommendation
+
+ An iterative resolver MUST NOT send a query for the NS RRset of a
+ non-responsive zone to any of the name servers for that zone's parent
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 6]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ zone. For the purposes of this injunction, a non-responsive zone is
+ defined as a zone for which every name server listed in the zone's NS
+ RRset:
+
+ 1. is not authoritative for the zone (i.e., lame), or,
+
+ 2. returns a server failure response (RCODE=2), or,
+
+ 3. is dead or unreachable according to section 7.2 of RFC 2308 [4].
+
+2.2. Repeated queries to lame servers
+
+ Section 2.1 describes a catastrophic failure: when every name server
+ for a zone is unable to provide an answer for one reason or another.
+ A more common occurrence is when a subset of a zone's name servers
+ are unavailable or misconfigured. Different failure modes have
+ different expected durations. Some symptoms indicate problems that
+ are potentially transient; for example, various types of ICMP
+ unreachable messages because a name server process is not running or
+ a host or network is unreachable, or a complete lack of a response to
+ a query. Such responses could be the result of a host rebooting or
+ temporary outages; these events don't necessarily require any human
+ intervention and can be reasonably expected to be temporary.
+
+ Other symptoms clearly indicate a condition requiring human
+ intervention, such as lame server: if a name server is misconfigured
+ and not authoritative for a zone delegated to it, it is reasonable to
+ assume that this condition has potential to last longer than
+ unreachability or unresponsiveness. Consequently, repeated queries
+ to known lame servers are not useful. In this case of a condition
+ with potential to persist for a long time, a better practice would be
+ to maintain a list of known lame servers and avoid querying them
+ repeatedly in a short interval.
+
+ It should also be noted, however, that some authoritative name server
+ implementations appear to be lame only for queries of certain types
+ as described in RFC 4074 [5]. In this case, it makes sense to retry
+ the "lame" servers for other types of queries, particularly when all
+ known authoritative name servers appear to be "lame".
+
+2.2.1. Recommendation
+
+ Iterative resolvers SHOULD cache name servers that they discover are
+ not authoritative for zones delegated to them (i.e. lame servers).
+ If this caching is performed, lame servers MUST be cached against the
+ specific query tuple <zone name, class, server IP address>. Zone
+ name can be derived from the owner name of the NS record that was
+ referenced to query the name server that was discovered to be lame.
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 7]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ Implementations that perform lame server caching MUST refrain from
+ sending queries to known lame servers based on a time interval from
+ when the server is discovered to be lame. A minimum interval of
+ thirty minutes is RECOMMENDED.
+
+ An exception to this recommendation occurs if all name servers for a
+ zone are marked lame. In that case, the iterative resolver SHOULD
+ temporarily ignore the servers' lameness status and query one or more
+ servers. This behavior is a workaround for the type-specific
+ lameness issue described in the previous section.
+
+ Implementors should take care not to make lame server avoidance logic
+ overly broad: note that a name server could be lame for a parent zone
+ but not a child zone, e.g., lame for "example.com" but properly
+ authoritative for "sub.example.com". Therefore a name server should
+ not be automatically considered lame for subzones. In the case
+ above, even if a name server is known to be lame for "example.com",
+ it should be queried for QNAMEs at or below "sub.example.com" if an
+ NS record indicates it should be authoritative for that zone.
+
+2.3. Inability to follow multiple levels of indirection
+
+ Some iterative resolver implementations are unable to follow
+ sufficient levels of indirection. For example, consider the
+ following delegations:
+
+ foo.example. IN NS ns1.example.com.
+ foo.example. IN NS ns2.example.com.
+
+ example.com. IN NS ns1.test.example.net.
+ example.com. IN NS ns2.test.example.net.
+
+ test.example.net. IN NS ns1.test.example.net.
+ test.example.net. IN NS ns2.test.example.net.
+
+ An iterative resolver resolving the name "www.foo.example" must
+ follow two levels of indirection, first obtaining address records for
+ "ns1.test.example.net" or "ns2.test.example.net" in order to obtain
+ address records for "ns1.example.com" or "ns2.example.com" in order
+ to query those name servers for the address records of
+ "www.foo.example". While this situation may appear contrived, we
+ have seen multiple similar occurrences and expect more as new generic
+ top-level domains (gTLDs) become active. We anticipate many zones in
+ new gTLDs will use name servers in existing gTLDs, increasing the
+ number of delegations using out-of-zone name servers.
+
+
+
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 8]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+2.3.1. Recommendation
+
+ Clearly constructing a delegation that relies on multiple levels of
+ indirection is not a good administrative practice. However, the
+ practice is widespread enough to require that iterative resolvers be
+ able to cope with it. Iterative resolvers SHOULD be able to handle
+ arbitrary levels of indirection resulting from out-of-zone name
+ servers. Iterative resolvers SHOULD implement a level-of-effort
+ counter to avoid loops or otherwise performing too much work in
+ resolving pathological cases.
+
+ A best practice that avoids this entire issue of indirection is to
+ name one or more of a zone's name servers in the zone itself. For
+ example, if the zone is named "example.com", consider naming some of
+ the name servers "ns{1,2,...}.example.com" (or similar).
+
+2.4. Aggressive retransmission when fetching glue
+
+ When an authoritative name server responds with a referral, it
+ includes NS records in the authority section of the response.
+ According to the algorithm in section 4.3.2 of RFC 1034 [2], the name
+ server should also "put whatever addresses are available into the
+ additional section, using glue RRs if the addresses are not available
+ from authoritative data or the cache." Some name server
+ implementations take this address inclusion a step further with a
+ feature called "glue fetching". A name server that implements glue
+ fetching attempts to include address records for every NS record in
+ the authority section. If necessary, the name server issues multiple
+ queries of its own to obtain any missing address records.
+
+ Problems with glue fetching can arise in the context of
+ "authoritative-only" name servers, which only serve authoritative
+ data and ignore requests for recursion. Such an entity will not
+ normally generate any queries of its own. Instead it answers non-
+ recursive queries from iterative resolvers looking for information in
+ zones it serves. With glue fetching enabled, however, an
+ authoritative server invokes an iterative resolver to look up an
+ unknown address record to complete the additional section of a
+ response.
+
+ We have observed situations where the iterative resolver of a glue-
+ fetching name server can send queries that reach other name servers,
+ but is apparently prevented from receiving the responses. For
+ example, perhaps the name server is authoritative-only and therefore
+ its administrators expect it to receive only queries and not
+ responses. Perhaps unaware of glue fetching and presuming that the
+ name server's iterative resolver will generate no queries, its
+ administrators place the name server behind a network device that
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 9]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ prevents it from receiving responses. If this is the case, all glue-
+ fetching queries will go answered.
+
+ We have observed name server implementations whose iterative
+ resolvers retry excessively when glue-fetching queries are
+ unanswered. A single com/net name server has received hundreds of
+ queries per second from a single such source. Judging from the
+ specific queries received and based on additional analysis, we
+ believe these queries result from overly aggressive glue fetching.
+
+2.4.1. Recommendation
+
+ Implementers whose name servers support glue fetching SHOULD take
+ care to avoid sending queries at excessive rates. Implementations
+ SHOULD support throttling logic to detect when queries are sent but
+ no responses are received.
+
+2.5. Aggressive retransmission behind firewalls
+
+ A common occurrence and one of the largest sources of repeated
+ queries at the com/net and root name servers appears to result from
+ resolvers behind misconfigured firewalls. In this situation, an
+ iterative resolver is apparently allowed to send queries through a
+ firewall to other name servers, but not receive the responses. The
+ result is more queries than necessary because of retransmission, all
+ of which are useless because the responses are never received. Just
+ as with the glue-fetching scenario described in Section 2.4, the
+ queries are sometimes sent at excessive rates. To make matters
+ worse, sometimes the responses, sent in reply to legitimate queries,
+ trigger an alarm on the originator's intrusion detection system. We
+ are frequently contacted by administrators responding to such alarms
+ who believe our name servers are attacking their systems.
+
+ Not only do some resolvers in this situation retransmit queries at an
+ excessive rate, but they continue to do so for days or even weeks.
+ This scenario could result from an organization with multiple
+ recursive name servers, only a subset of whose iterative resolvers'
+ traffic is improperly filtered in this manner. Stub resolvers in the
+ organization could be configured to query multiple recursive name
+ servers. Consider the case where a stub resolver queries a filtered
+ recursive name server first. The iterative resolver of this
+ recursive name server sends one or more queries whose replies are
+ filtered, so it can't respond to the stub resolver, which times out.
+ Then the stub resolver retransmits to a recursive name server that is
+ able to provide an answer. Since resolution ultimately succeeds the
+ underlying problem might not be recognized or corrected. A popular
+ stub resolver implementation has a very aggressive retransmission
+ schedule, including simultaneous queries to multiple recursive name
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 10]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ servers, which could explain how such a situation could persist
+ without being detected.
+
+2.5.1. Recommendation
+
+ The most obvious recommendation is that administrators SHOULD take
+ care not to place iterative resolvers behind a firewall that allows
+ queries to pass through but not the resulting replies.
+
+ Iterative resolvers SHOULD take care to avoid sending queries at
+ excessive rates. Implementations SHOULD support throttling logic to
+ detect when queries are sent but no responses are received.
+
+2.6. Misconfigured NS records
+
+ Sometimes a zone administrator forgets to add the trailing dot on the
+ domain names in the RDATA of a zone's NS records. Consider this
+ fragment of the zone file for "example.com":
+
+ $ORIGIN example.com.
+ example.com. 3600 IN NS ns1.example.com ; Note missing
+ example.com. 3600 IN NS ns2.example.com ; trailing dots
+
+ The zone's authoritative servers will parse the NS RDATA as
+ "ns1.example.com.example.com" and "ns2.example.com.example.com" and
+ return NS records with this incorrect RDATA in responses, including
+ typically the authority section of every response containing records
+ from the "example.com" zone.
+
+ Now consider a typical sequence of queries. An iterative resolver
+ attempting to resolve address records for "www.example.com" with no
+ cached information for this zone will query a "com" authoritative
+ server. The "com" server responds with a referral to the
+ "example.com" zone, consisting of NS records with valid RDATA and
+ associated glue records. (This example assumes that the
+ "example.com" zone delegation information is correct in the "com"
+ zone.) The iterative resolver caches the NS RRset from the "com"
+ server and follows the referral by querying one of the "example.com"
+ authoritative servers. This server responds with the
+ "www.example.com" address record in the answer section and,
+ typically, the "example.com" NS records in the authority section and,
+ if space in the message remains, glue address records in the
+ additional section. According to Section 5.4 of RFC 2181 [3], NS
+ records in the authority section of an authoritative answer are more
+ trustworthy than NS records from the authority section of a non-
+ authoritative answer. Thus the "example.com" NS RRset just received
+ from the "example.com" authoritative server overrides the
+ "example.com" NS RRset received moments ago from the "com"
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 11]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ authoritative server.
+
+ But the "example.com" zone contains the erroneous NS RRset as shown
+ in the example above. Subsequent queries for names in "example.com"
+ will cause the iterative resolver to attempt to use the incorrect NS
+ records and so it will try to resolve the nonexistent names
+ "ns1.example.com.example.com" and "ns2.example.com.example.com". In
+ this example, since all of the zone's name servers are named in the
+ zone itself (i.e., "ns1.example.com.example.com" and
+ "ns2.example.com.example.com" both end in "example.com") and all are
+ bogus, the iterative resolver cannot reach any "example.com" name
+ servers. Therefore attempts to resolve these names result in address
+ record queries to the "com" authoritative servers. Queries for such
+ obviously bogus glue address records occur frequently at the com/net
+ name servers.
+
+2.6.1. Recommendation
+
+ An authoritative server can detect this situation. A trailing dot
+ missing from an NS record's RDATA always results by definition in a
+ name server name that exists somewhere under the apex of the zone the
+ NS record appears in. Note that further levels of delegation are
+ possible, so a missing trailing dot could inadvertently create a name
+ server name that actually exists in a subzone.
+
+ An authoritative name server SHOULD issue a warning when one of a
+ zone's NS records references a name server below the zone's apex when
+ a corresponding address record does not exist in the zone AND there
+ are no delegated subzones where the address record could exist.
+
+2.7. Name server records with zero TTL
+
+ Sometimes a popular com/net subdomain's zone is configured with a TTL
+ of zero on the zone's NS records, which prohibits these records from
+ being cached and will result in a higher query volume to the zone's
+ authoritative servers. The zone's administrator should understand
+ the consequences of such a configuration and provision resources
+ accordingly. A zero TTL on the zone's NS RRset, however, carries
+ additional consequences beyond the zone itself: if an iterative
+ resolver cannot cache a zone's NS records because of a zero TTL, it
+ will be forced to query that zone's parent's name servers each time
+ it resolves a name in the zone. The com/net authoritative servers do
+ see an increased query load when a popular com/net subdomain's zone
+ is configured with a TTL of zero on the zone's NS records.
+
+ A zero TTL on an RRset expected to change frequently is extreme but
+ permissible. A zone's NS RRset is a special case, however, because
+ changes to it must be coordinated with the zone's parent. In most
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 12]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ zone parent/child relationships we are aware of, there is typically
+ some delay involved in effecting changes. Further, changes to the
+ set of a zone's authoritative name servers (and therefore to the
+ zone's NS RRset) are typically relatively rare: providing reliable
+ authoritative service requires a reasonably stable set of servers.
+ Therefore an extremely low or zero TTL on a zone's NS RRset rarely
+ makes sense, except in anticipation of an upcoming change. In this
+ case, when the zone's administrator has planned a change and does not
+ want iterative resolvers throughout the Internet to cache the NS
+ RRset for a long period of time, a low TTL is reasonable.
+
+2.7.1. Recommendation
+
+ Because of the additional load placed on a zone's parent's
+ authoritative servers resulting from a zero TTL on a zone's NS RRset,
+ under such circumstances authoritative name servers SHOULD issue a
+ warning when loading a zone.
+
+2.8. Unnecessary dynamic update messages
+
+ The UPDATE message specified in RFC 2136 [6] allows an authorized
+ agent to update a zone's data on an authoritative name server using a
+ DNS message sent over the network. Consider the case of an agent
+ desiring to add a particular resource record. Because of zone cuts,
+ the agent does not necessarily know the proper zone to which the
+ record should be added. The dynamic update process requires that the
+ agent determine the appropriate zone so the UPDATE message can be
+ sent to one of the zone's authoritative servers (typically the
+ primary master as specified in the zone's SOA MNAME field).
+
+ The appropriate zone to update is the closest enclosing zone, which
+ cannot be determined only by inspecting the domain name of the record
+ to be updated, since zone cuts can occur anywhere. One way to
+ determine the closest enclosing zone entails walking up the name
+ space tree by sending repeated UPDATE messages until success. For
+ example, consider an agent attempting to add an address record with
+ the name "foo.bar.example.com". The agent could first attempt to
+ update the "foo.bar.example.com" zone. If the attempt failed, the
+ update could be directed to the "bar.example.com" zone, then the
+ "example.com" zone, then the "com" zone, and finally the root zone.
+
+ A popular dynamic agent follows this algorithm. The result is many
+ UPDATE messages received by the root name servers, the com/net
+ authoritative servers, and presumably other TLD authoritative
+ servers. A valid question is why the algorithm proceeds to send
+ updates all the way to TLD and root name servers. This behavior is
+ not entirely unreasonable: in enterprise DNS architectures with an
+ "internal root" design, there could conceivably be private, non-
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 13]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ public TLD or root zones that would be the appropriate targets for a
+ dynamic update.
+
+ A significant deficiency with this algorithm is that knowledge of a
+ given UPDATE message's failure is not helpful in directing future
+ UPDATE messages to the appropriate servers. A better algorithm would
+ be to find the closest enclosing zone by walking up the name space
+ with queries for SOA or NS rather than "probing" with UPDATE
+ messages. Once the appropriate zone is found, an UPDATE message can
+ be sent. In addition, the results of these queries can be cached to
+ aid in determining closest enclosing zones for future updates. Once
+ the closest enclosing zone is determined with this method, the update
+ will either succeed or fail and there is no need to send further
+ updates to higher-level zones. The important point is that walking
+ up the tree with queries yields cacheable information, whereas
+ walking up the tree by sending UPDATE messages does not.
+
+2.8.1. Recommendation
+
+ Dynamic update agents SHOULD send SOA or NS queries to progressively
+ higher-level names to find the closest enclosing zone for a given
+ name to update. Only after the appropriate zone is found should the
+ client send an UPDATE message to one of the zone's authoritative
+ servers. Update clients SHOULD NOT "probe" using UPDATE messages by
+ walking up the tree to progressively higher-level zones.
+
+2.9. Queries for domain names resembling IPv4 addresses
+
+ The root name servers receive a significant number of A record
+ queries where the QNAME looks like an IPv4 address. The source of
+ these queries is unknown. It could be attributed to situations where
+ a user believes an application will accept either a domain name or an
+ IP address in a given configuration option. The user enters an IP
+ address, but the application assumes any input is a domain name and
+ attempts to resolve it, resulting in an A record lookup. There could
+ also be applications that produce such queries in a misguided attempt
+ to reverse map IP addresses.
+
+ These queries result in Name Error (RCODE=3) responses. An iterative
+ resolver can negatively cache such responses, but each response
+ requires a separate cache entry, i.e., a negative cache entry for the
+ domain name "192.0.2.1" does not prevent a subsequent query for the
+ domain name "192.0.2.2".
+
+2.9.1. Recommendation
+
+ It would be desirable for the root name servers not to have to answer
+ these queries: they unnecessarily consume CPU resources and network
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 14]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ bandwidth. A possible solution is to delegate these numeric TLDs
+ from the root zone to a separate set of servers to absorb the
+ traffic. The "black hole servers" used by the AS 112 Project [8],
+ which are currently delegated the in-addr.arpa zones corresponding to
+ RFC 1918 [7] private use address space, would be a possible choice to
+ receive these delegations. Of course, the proper and usual root zone
+ change procedures would have to be followed to make such a change to
+ the root zone.
+
+2.10. Misdirected recursive queries
+
+ The root name servers receive a significant number of recursive
+ queries (i.e., queries with the RD bit set in the header). Since
+ none of the root servers offers recursion, the servers' response in
+ such a situation ignores the request for recursion and the response
+ probably does not contain the data the querier anticipated. Some of
+ these queries result from users configuring stub resolvers to query a
+ root server. (This situation is not hypothetical: we have received
+ complaints from users when this configuration does not work as
+ hoped.) Of course, users should not direct stub resolvers to use
+ name servers that do not offer recursion, but we are not aware of any
+ stub resolver implementation that offers any feedback to the user
+ when so configured, aside from simply "not working".
+
+2.10.1. Recommendation
+
+ When the IP address of a name server that supposedly offers recursion
+ is configured in a stub resolver using an interactive user interface,
+ the resolver could send a test query to verify that the server indeed
+ supports recursion (i.e., verify that the response has the RA bit set
+ in the header). The user could be immediately notified if the server
+ is non-recursive.
+
+ The stub resolver could also report an error, either through a user
+ interface or in a log file, if the queried server does not support
+ recursion. Error reporting SHOULD be throttled to avoid a
+ notification or log message for every response from a non-recursive
+ server.
+
+2.11. Suboptimal name server selection algorithm
+
+ An entire document could be devoted to the topic of problems with
+ different implementations of the recursive resolution algorithm. The
+ entire process of recursion is woefully under specified, requiring
+ each implementor to design an algorithm. Sometimes implementors make
+ poor design choices that could be avoided if a suggested algorithm
+ and best practices were documented, but that is a topic for another
+ document.
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 15]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+ Some deficiencies cause significant operational impact and are
+ therefore worth mentioning here. One of these is name server
+ selection by an iterative resolver. When an iterative resolver wants
+ to contact one of a zone's authoritative name servers, how does it
+ choose from the NS records listed in the zone's NS RRset? If the
+ selection mechanism is suboptimal, queries are not spread evenly
+ among a zone's authoritative servers. The details of the selection
+ mechanism are up to the implementor, but we offer some suggestions.
+
+2.11.1. Recommendation
+
+ This list is not conclusive, but reflects the changes that would
+ produce the most impact in terms of reducing disproportionate query
+ load among a zone's authoritative servers. I.e., these changes would
+ help spread the query load evenly.
+
+ o Do not make assumptions based on NS RRset order: all NS RRs SHOULD
+ be treated equally. (In the case of the "com" zone, for example,
+ most of the root servers return the NS record for "a.gtld-
+ servers.net" first in the authority section of referrals.
+ Apparently as a result, this server receives disproportionately
+ more traffic than the other 12 authoritative servers for "com".)
+
+ o Use all NS records in an RRset. (For example, we are aware of
+ implementations that hard-coded information for a subset of the
+ root servers.)
+
+ o Maintain state and favor the best-performing of a zone's
+ authoritative servers. A good definition of performance is
+ response time. Non-responsive servers can be penalized with an
+ extremely high response time.
+
+ o Do not lock onto the best-performing of a zone's name servers. An
+ iterative resolver SHOULD periodically check the performance of
+ all of a zone's name servers to adjust its determination of the
+ best-performing one.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 16]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+3. Acknowledgments
+
+ The authors would like to thank the following people for their
+ comments that improved this document: Andras Salamon, Dave Meyer,
+ Doug Barton, Jaap Akkerhuis, Jinmei Tatuya, John Brady, Kevin Darcy,
+ Olafur Gudmundsson, Pekka Savola, Peter Koch and Rob Austein. We
+ apologize if we have omitted anyone; any oversight was unintentional.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 17]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+4. IANA considerations
+
+ There are no new IANA considerations introduced by this memo.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 18]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+5. Security considerations
+
+ The iterative resolver misbehavior discussed in this document exposes
+ the root and TLD name servers to increased risk of both intentional
+ and unintentional denial of service attacks.
+
+ We believe that implementation of the recommendations offered in this
+ document will reduce the amount of unnecessary traffic seen at root
+ and TLD name servers, thus reducing the opportunity for an attacker
+ to use such queries to his or her advantage.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 19]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+6. Internationalization considerations
+
+ There are no new internationalization considerations introduced by
+ this memo.
+
+7. Informative References
+
+ [1] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [2] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [3] Elz, R. and R. Bush, "Clarifications to the DNS Specification",
+ RFC 2181, July 1997.
+
+ [4] Andrews, M., "Negative Caching of DNS Queries (DNS NCACHE)",
+ RFC 2308, March 1998.
+
+ [5] Morishita, Y. and T. Jinmei, "Common Misbehavior Against DNS
+ Queries for IPv6 Addresses", RFC 4074, May 2005.
+
+ [6] Vixie, P., Thomson, S., Rekhter, Y., and J. Bound, "Dynamic
+ Updates in the Domain Name System (DNS UPDATE)", RFC 2136,
+ April 1997.
+
+ [7] Rekhter, Y., Moskowitz, R., Karrenberg, D., Groot, G., and E.
+ Lear, "Address Allocation for Private Internets", BCP 5,
+ RFC 1918, February 1996.
+
+ [8] <http://www.as112.net>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 20]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+Authors' Addresses
+
+ Matt Larson
+ VeriSign, Inc.
+ 21345 Ridgetop Circle
+ Dulles, VA 20166-6503
+ USA
+
+ Email: mlarson@verisign.com
+
+
+ Piet Barber
+ VeriSign, Inc.
+ 21345 Ridgetop Circle
+ Dulles, VA 20166-6503
+ USA
+
+ Email: pbarber@verisign.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 21]
+
+Internet-Draft Observed DNS Resolution Misbehavior February 2006
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2006). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Larson & Barber Expires August 14, 2006 [Page 22]
+
diff --git a/doc/draft/draft-ietf-dnsop-default-local-zones-05.txt b/doc/draft/draft-ietf-dnsop-default-local-zones-05.txt
new file mode 100644
index 0000000..230c036
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsop-default-local-zones-05.txt
@@ -0,0 +1,672 @@
+
+
+
+Network Working Group M. Andrews
+Internet-Draft ISC
+Intended status: BCP June 5, 2008
+Expires: December 7, 2008
+
+
+ Locally-served DNS Zones
+ draft-ietf-dnsop-default-local-zones-05
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on December 7, 2008.
+
+Abstract
+
+ Experience has shown that there are a number of DNS zones all
+ iterative resolvers and recursive nameservers should, unless
+ configured otherwise, automatically serve. RFC 4193 specifies that
+ this should occur for D.F.IP6.ARPA. This document extends the
+ practice to cover the IN-ADDR.ARPA zones for RFC 1918 address space
+ and other well known zones with similar characteristics.
+
+
+
+
+
+
+
+
+
+Andrews Expires December 7, 2008 [Page 1]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1. Reserved Words . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Effects on sites using RFC 1918 addresses. . . . . . . . . . . 4
+ 3. Changes to Iterative Resolver Behaviour. . . . . . . . . . . . 4
+ 4. Lists Of Zones Covered . . . . . . . . . . . . . . . . . . . . 5
+ 4.1. RFC 1918 Zones . . . . . . . . . . . . . . . . . . . . . . 5
+ 4.2. RFC 3330 Zones . . . . . . . . . . . . . . . . . . . . . . 6
+ 4.3. Local IPv6 Unicast Addresses . . . . . . . . . . . . . . . 6
+ 4.4. IPv6 Locally Assigned Local Addresses . . . . . . . . . . 6
+ 4.5. IPv6 Link Local Addresses . . . . . . . . . . . . . . . . 7
+ 5. Zones that are Out-Of-Scope . . . . . . . . . . . . . . . . . 7
+ 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 8
+ 7. Security Considerations . . . . . . . . . . . . . . . . . . . 8
+ 8. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 8
+ 9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 9.1. Normative References . . . . . . . . . . . . . . . . . . . 8
+ 9.2. Informative References . . . . . . . . . . . . . . . . . . 10
+ Appendix A. Change History [To Be Removed on Publication] . . . . 10
+ A.1. draft-ietf-dnsop-default-local-zones-05.txt . . . . . . . 10
+ A.2. draft-ietf-dnsop-default-local-zones-04.txt . . . . . . . 10
+ A.3. draft-ietf-dnsop-default-local-zones-03.txt . . . . . . . 10
+ A.4. draft-ietf-dnsop-default-local-zones-02.txt . . . . . . . 10
+ A.5. draft-ietf-dnsop-default-local-zones-01.txt . . . . . . . 11
+ A.6. draft-ietf-dnsop-default-local-zones-00.txt . . . . . . . 11
+ A.7. draft-andrews-full-service-resolvers-03.txt . . . . . . . 11
+ A.8. draft-andrews-full-service-resolvers-02.txt . . . . . . . 11
+ Appendix B. Proposed Status [To Be Removed on Publication] . . . 11
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ Intellectual Property and Copyright Statements . . . . . . . . . . 12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Andrews Expires December 7, 2008 [Page 2]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+1. Introduction
+
+ Experience has shown that there are a number of DNS [RFC 1034] [RFC
+ 1035] zones that all iterative resolvers and recursive nameservers
+ SHOULD, unless intentionally configured otherwise, automatically
+ serve. These zones include, but are not limited to, the IN-ADDR.ARPA
+ zones for the address space allocated by [RFC 1918] and the IP6.ARPA
+ zones for locally assigned unique local IPv6 addresses, [RFC 4193].
+
+ This recommendation is made because data has shown that significant
+ leakage of queries for these name spaces is occurring, despite
+ instructions to restrict them, and because it has therefore become
+ necessary to deploy sacrificial name servers to protect the immediate
+ parent name servers for these zones from excessive, unintentional,
+ query load [AS112] [I-D.draft-ietf-dnsop-as112-ops]
+ [I-D.draft-ietf-dnsop-as112-under-attack-help-help]. There is every
+ expectation that the query load will continue to increase unless
+ steps are taken as outlined here.
+
+ Additionally, queries from clients behind badly configured firewalls
+ that allow outgoing queries for these name spaces but drop the
+ responses, put a significant load on the root servers (forward but no
+ reverse zones configured). They also cause operational load for the
+ root server operators as they have to reply to enquiries about why
+ the root servers are "attacking" these clients. Changing the default
+ configuration will address all these issues for the zones listed in
+ Section 4.
+
+ [RFC 4193] recommends that queries for D.F.IP6.ARPA be handled
+ locally. This document extends the recommendation to cover the IN-
+ ADDR.ARPA zones for [RFC 1918] and other well known IN-ADDR.ARPA and
+ IP6.ARPA zones for which queries should not appear on the public
+ Internet.
+
+ It is hoped that by doing this the number of sacrificial servers
+ [AS112] will not have to be increased, and may in time be reduced.
+
+ This recommendation should also help DNS responsiveness for sites
+ which are using [RFC 1918] addresses but do not follow the last
+ paragraph in Section 3 of [RFC 1918].
+
+1.1. Reserved Words
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC 2119].
+
+
+
+
+
+Andrews Expires December 7, 2008 [Page 3]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+2. Effects on sites using RFC 1918 addresses.
+
+ For most sites using [RFC 1918] addresses, the changes here will have
+ little or no detrimental effect. If the site does not already have
+ the reverse tree populated the only effect will be that the name
+ error responses will be generated locally rather than remotely.
+
+ For sites that do have the reverse tree populated, most will either
+ have a local copy of the zones or will be forwarding the queries to
+ servers which have local copies of the zone. Therefore this
+ recommendation will not be relevant.
+
+ The most significant impact will be felt at sites that make use of
+ delegations for [RFC 1918] addresses and have populated these zones.
+ These sites will need to override the default configuration expressed
+ in this document to allow resolution to continue. Typically, such
+ sites will be fully disconnected from the Internet and have their own
+ root servers for their own non-Internet DNS tree.
+
+
+3. Changes to Iterative Resolver Behaviour.
+
+ Unless configured otherwise, an iterative resolver will now return
+ authoritatively (aa=1) name errors (RCODE=3) for queries within the
+ zones in Section 4, with the obvious exception of queries for the
+ zone name itself where SOA, NS and "no data" responses will be
+ returned as appropriate to the query type. One common way to do this
+ is to serve empty (SOA and NS only) zones.
+
+ An implementation of this recommendation MUST provide a mechanism to
+ disable this new behaviour, and SHOULD allow this decision on a zone
+ by zone basis.
+
+ If using empty zones one SHOULD NOT use the same NS and SOA records
+ as used on the public Internet servers as that will make it harder to
+ detect the origin of the responses and thus any leakage to the public
+ Internet servers. This document recommends that the NS record
+ defaults to the name of the zone and the SOA MNAME defaults to the
+ name of the only NS RR's target. The SOA RNAME should default to
+ "nobody.invalid." [RFC 2606]. Implementations SHOULD provide a
+ mechanism to set these values. No address records need to be
+ provided for the name server.
+
+ Below is an example of a generic empty zone in master file format.
+ It will produce a negative cache TTL of 3 hours.
+
+ @ 10800 IN SOA @ nobody.invalid. 1 3600 1200 604800 10800
+ @ 10800 IN NS @
+
+
+
+Andrews Expires December 7, 2008 [Page 4]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+ The SOA RR is needed to support negative caching [RFC 2308] of name
+ error responses and to point clients to the primary master for DNS
+ dynamic updates.
+
+ SOA values of particular importance are the MNAME, the SOA RR's TTL
+ and the negTTL value. Both TTL values SHOULD match. The rest of the
+ SOA timer values MAY be chosen arbitrarily since they are not
+ intended to control any zone transfer activity.
+
+ The NS RR is needed as some UPDATE [RFC 2136] clients use NS queries
+ to discover the zone to be updated. Having no address records for
+ the name server is expected to abort UPDATE processing in the client.
+
+
+4. Lists Of Zones Covered
+
+ The following subsections are intended to seed the IANA registry as
+ requested in the IANA Considerations Section. The zone name is the
+ entity to be registered.
+
+4.1. RFC 1918 Zones
+
+ The following zones correspond to the IPv4 address space reserved in
+ [RFC 1918].
+
+ +----------------------+
+ | Zone |
+ +----------------------+
+ | 10.IN-ADDR.ARPA |
+ | 16.172.IN-ADDR.ARPA |
+ | 17.172.IN-ADDR.ARPA |
+ | 18.172.IN-ADDR.ARPA |
+ | 19.172.IN-ADDR.ARPA |
+ | 20.172.IN-ADDR.ARPA |
+ | 21.172.IN-ADDR.ARPA |
+ | 22.172.IN-ADDR.ARPA |
+ | 23.172.IN-ADDR.ARPA |
+ | 24.172.IN-ADDR.ARPA |
+ | 25.172.IN-ADDR.ARPA |
+ | 26.172.IN-ADDR.ARPA |
+ | 27.172.IN-ADDR.ARPA |
+ | 28.172.IN-ADDR.ARPA |
+ | 29.172.IN-ADDR.ARPA |
+ | 30.172.IN-ADDR.ARPA |
+ | 31.172.IN-ADDR.ARPA |
+ | 168.192.IN-ADDR.ARPA |
+ +----------------------+
+
+
+
+
+Andrews Expires December 7, 2008 [Page 5]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+4.2. RFC 3330 Zones
+
+ The following zones correspond to those address ranges from [RFC
+ 3330] that are not expected to appear as source or destination
+ addresses on the public Internet and to not have a unique name to
+ associate with.
+
+ The recommendation to serve an empty zone 127.IN-ADDR.ARPA is not a
+ attempt to discourage any practice to provide a PTR RR for
+ 1.0.0.127.IN-ADDR.ARPA locally. In fact, a meaningful reverse
+ mapping should exist, but the exact setup is out of the scope of this
+ document. Similar logic applies to the reverse mapping for ::1
+ (Section 4.3). The recommendations made here simply assume no other
+ coverage for these domains exists.
+
+ +------------------------------+------------------------+
+ | Zone | Description |
+ +------------------------------+------------------------+
+ | 0.IN-ADDR.ARPA | IPv4 "THIS" NETWORK |
+ | 127.IN-ADDR.ARPA | IPv4 LOOP-BACK NETWORK |
+ | 254.169.IN-ADDR.ARPA | IPv4 LINK LOCAL |
+ | 2.0.192.IN-ADDR.ARPA | IPv4 TEST NET |
+ | 255.255.255.255.IN-ADDR.ARPA | IPv4 BROADCAST |
+ +------------------------------+------------------------+
+
+4.3. Local IPv6 Unicast Addresses
+
+ The reverse mappings ([RFC 3596], Section 2.5 IP6.ARPA Domain) for
+ the IPv6 Unspecified (::) and Loopback (::1) addresses ([RFC 4291],
+ Sections 2.4, 2.5.2 and 2.5.3) are covered by these two zones:
+
+ +-------------------------------------------+
+ | Zone |
+ +-------------------------------------------+
+ | 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.\ |
+ | 0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA |
+ | 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.\ |
+ | 0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA |
+ +-------------------------------------------+
+
+ Note: Line breaks and a escapes '\' have been inserted above for
+ readability and to adhere to line width constraints. They are not
+ parts of the zone names.
+
+4.4. IPv6 Locally Assigned Local Addresses
+
+ Section 4.4 of [RFC 4193] already required special treatment of:
+
+
+
+
+Andrews Expires December 7, 2008 [Page 6]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+ +--------------+
+ | Zone |
+ +--------------+
+ | D.F.IP6.ARPA |
+ +--------------+
+
+4.5. IPv6 Link Local Addresses
+
+ IPv6 Link-Local Addresses as of [RFC 4291], Section 2.5.6 are covered
+ by four distinct reverse DNS zones:
+
+ +----------------+
+ | Zone |
+ +----------------+
+ | 8.E.F.IP6.ARPA |
+ | 9.E.F.IP6.ARPA |
+ | A.E.F.IP6.ARPA |
+ | B.E.F.IP6.ARPA |
+ +----------------+
+
+
+5. Zones that are Out-Of-Scope
+
+ IPv6 site-local addresses, [RFC 4291] Sections 2.4 and 2.5.7, and
+ IPv6 Non-Locally Assigned Local addresses [RFC 4193] are not covered
+ here. It is expected that IPv6 site-local addresses will be self
+ correcting as IPv6 implementations remove support for site-local
+ addresses. However, sacrificial servers for C.E.F.IP6.ARPA through
+ F.E.F.IP6.ARPA may still need to be deployed in the short term if the
+ traffic becomes excessive.
+
+ For IPv6 Non-Locally Assigned Local addresses (L = 0) [RFC 4193],
+ there has been no decision made about whether the Regional Internet
+ Registries (RIRs) will provide delegations in this space or not. If
+ they don't, then C.F.IP6.ARPA will need to be added to the list in
+ Section 4.4. If they do, then registries will need to take steps to
+ ensure that name servers are provided for these addresses.
+
+ This document also ignores IP6.INT. IP6.INT has been wound up with
+ only legacy resolvers now generating reverse queries under IP6.INT
+ [RFC 4159].
+
+ This document has also deliberately ignored names immediately under
+ the root domain. While there is a subset of queries to the root name
+ servers which could be addressed using the techniques described here
+ (e.g. .local, .workgroup and IPv4 addresses), there is also a vast
+ amount of traffic that requires a different strategy (e.g. lookups
+ for unqualified hostnames, IPv6 addresses).
+
+
+
+Andrews Expires December 7, 2008 [Page 7]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+6. IANA Considerations
+
+ This document requests that IANA establish a registry of zones which
+ require this default behaviour. The initial contents of which are in
+ Section 4. Implementors are encouraged to check this registry and
+ adjust their implementations to reflect changes therein.
+
+ This registry can be amended through "IETF Consensus" as per [RFC
+ 2434].
+
+ IANA should co-ordinate with the RIRs to ensure that, as DNSSEC is
+ deployed in the reverse tree, delegations for these zones are made in
+ the manner described in Section 7.
+
+
+7. Security Considerations
+
+ During the initial deployment phase, particularly where [RFC 1918]
+ addresses are in use, there may be some clients that unexpectedly
+ receive a name error rather than a PTR record. This may cause some
+ service disruption until their recursive name server(s) have been re-
+ configured.
+
+ As DNSSEC is deployed within the IN-ADDR.ARPA and IP6.ARPA
+ namespaces, the zones listed above will need to be delegated as
+ insecure delegations, or be within insecure zones. This will allow
+ DNSSEC validation to succeed for queries in these spaces despite not
+ being answered from the delegated servers.
+
+ It is recommended that sites actively using these namespaces secure
+ them using DNSSEC [RFC 4035] by publishing and using DNSSEC trust
+ anchors. This will protect the clients from accidental import of
+ unsigned responses from the Internet.
+
+
+8. Acknowledgements
+
+ This work was supported by the US National Science Foundation
+ (research grant SCI-0427144) and DNS-OARC.
+
+
+9. References
+
+9.1. Normative References
+
+ [RFC 1034]
+ Mockapetris, P., "DOMAIN NAMES - CONCEPTS AND FACILITIES",
+ STD 13, RFC 1034, November 1987.
+
+
+
+Andrews Expires December 7, 2008 [Page 8]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+ [RFC 1035]
+ Mockapetris, P., "DOMAIN NAMES - IMPLEMENTATION AND
+ SPECIFICATION", STD 13, RFC 1035, November 1987.
+
+ [RFC 1918]
+ Rekhter, Y., Moskowitz, B., Karrenberg, D., de Groot, G.,
+ and E. Lear, "Address Allocation for Private Internets",
+ BCP 5, RFC 1918, February 1996.
+
+ [RFC 2119]
+ Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC 2136]
+ Vixie, P., Thomson, A., Rekhter, Y., and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)",
+ RFC 2136, April 1997.
+
+ [RFC 2308]
+ Andrews, M., "Negative Caching of DNS Queries (DNS
+ NCACHE)", RFC 2398, March 1998.
+
+ [RFC 2434]
+ Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+ [RFC 2606]
+ Eastlake, D. and A. Panitz, "Reserved Top Level DNS
+ Names", BCP 32, RFC 2606, June 1999.
+
+ [RFC 3596]
+ Thomson, S., Huitema, C., Ksinant, V., and M. Souissi,
+ "DNS Extensions to Support IPv6", RFC 3596, October 2003.
+
+ [RFC 4035]
+ Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security
+ Extensions", RFC 4035, March 2005.
+
+ [RFC 4159]
+ Huston, G., "Deprecation of "ip6.int"", BCP 109, RFC 4159,
+ August 2005.
+
+ [RFC 4193]
+ Hinden, R. and B. Haberman, "Unique Local IPv6 Unicast
+ Addresses", RFC 4193, October 2005.
+
+
+
+
+Andrews Expires December 7, 2008 [Page 9]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+ [RFC 4291]
+ Hinden, R. and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 4291, February 2006.
+
+9.2. Informative References
+
+ [AS112] "AS112 Project", <http://www.as112.net/>.
+
+ [I-D.draft-ietf-dnsop-as112-ops]
+ Abley, J. and W. Maton, "AS112 Nameserver Operations",
+ draft-ietf-dnsop-as112-ops-00 (work in progress),
+ February 2007.
+
+ [I-D.draft-ietf-dnsop-as112-under-attack-help-help]
+ Abley, J. and W. Maton, "I'm Being Attacked by
+ PRISONER.IANA.ORG!",
+ draft-ietf-dnsop-as112-under-attack-help-help-00 (work in
+ progress), February 2007.
+
+ [RFC 3330]
+ "Special-Use IPv4 Addresses", RFC 3330, September 2002.
+
+
+Appendix A. Change History [To Be Removed on Publication]
+
+A.1. draft-ietf-dnsop-default-local-zones-05.txt
+
+ none, expiry prevention
+
+A.2. draft-ietf-dnsop-default-local-zones-04.txt
+
+ Centrally Assigned Local addresses -> Non-Locally Assigned Local
+ address
+
+A.3. draft-ietf-dnsop-default-local-zones-03.txt
+
+ expanded section 4 descriptions
+
+ Added references [RFC 2136], [RFC 3596],
+ [I-D.draft-ietf-dnsop-as112-ops] and
+ [I-D.draft-ietf-dnsop-as112-under-attack-help-help].
+
+ Revised language.
+
+A.4. draft-ietf-dnsop-default-local-zones-02.txt
+
+ RNAME now "nobody.invalid."
+
+
+
+
+Andrews Expires December 7, 2008 [Page 10]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+ Revised language.
+
+A.5. draft-ietf-dnsop-default-local-zones-01.txt
+
+ Revised impact description.
+
+ Updated to reflect change in IP6.INT status.
+
+A.6. draft-ietf-dnsop-default-local-zones-00.txt
+
+ Adopted by DNSOP.
+
+ "Author's Note" re-titled "Zones that are Out-Of-Scope"
+
+ Add note that these zone are expected to seed the IANA registry.
+
+ Title changed.
+
+A.7. draft-andrews-full-service-resolvers-03.txt
+
+ Added "Proposed Status".
+
+A.8. draft-andrews-full-service-resolvers-02.txt
+
+ Added 0.IN-ADDR.ARPA.
+
+
+Appendix B. Proposed Status [To Be Removed on Publication]
+
+ This Internet-Draft is being submitted for eventual publication as an
+ RFC with a proposed status of Best Current Practice.
+
+
+Author's Address
+
+ Mark P. Andrews
+ Internet Systems Consortium
+ 950 Charter Street
+ Redwood City, CA 94063
+ US
+
+ Email: Mark_Andrews@isc.org
+
+
+
+
+
+
+
+
+
+Andrews Expires December 7, 2008 [Page 11]
+
+Internet-Draft Locally-served DNS Zones June 2008
+
+
+Full Copyright Statement
+
+ Copyright (C) The IETF Trust (2008).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+
+
+
+
+
+
+
+
+
+Andrews Expires December 7, 2008 [Page 12]
+
diff --git a/doc/draft/draft-ietf-dnsop-inaddr-required-07.txt b/doc/draft/draft-ietf-dnsop-inaddr-required-07.txt
new file mode 100644
index 0000000..bcd0d14
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsop-inaddr-required-07.txt
@@ -0,0 +1,396 @@
+
+
+
+
+
+
+INTERNET-DRAFT D. Senie
+Category: BCP Amaranth Networks Inc.
+Expires in six months July 2005
+
+ Encouraging the use of DNS IN-ADDR Mapping
+ draft-ietf-dnsop-inaddr-required-07.txt
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+Abstract
+
+ Mapping of addresses to names has been a feature of DNS. Many sites,
+ implement it, many others don't. Some applications attempt to use it
+ as a part of a security strategy. The goal of this document is to
+ encourage proper deployment of address to name mappings, and provide
+ guidance for their use.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society. (2005)
+
+1. Introduction
+
+ The Domain Name Service has provision for providing mapping of IP
+ addresses to host names. It is common practice to ensure both name to
+ address, and address to name mappings are provided for networks. This
+ practice, while documented, has never been required, though it is
+ generally encouraged. This document both encourages the presence of
+
+
+
+Senie [Page 1]
+
+Internet-Draft Encouraging the use of DNS IN-ADDR Mapping July 2005
+
+
+ these mappings and discourages reliance on such mappings for security
+ checks.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [RFC2119].
+
+2. Discussion
+
+
+ From the early days of the Domain Name Service [RFC883] a special
+ domain has been set aside for resolving mappings of IP addresses to
+ domain names. This was refined in [RFC1035], describing the .IN-
+ ADDR.ARPA in use today. For the in the IPv6 address space, .IP6.ARPA
+ was added [RFC3152]. This document uses IPv4 CIDR block sizes and
+ allocation strategy where there are differences and uses IPv4
+ terminology. Aside from these differences, this document can and
+ should be applied to both address spaces.
+
+ The assignment of blocks of IP address space was delegated to three
+ regional registries. Guidelines for the registries are specified in
+ [RFC2050], which requires regional registries to maintain IN-ADDR
+ records on the large blocks of space issued to ISPs and others.
+
+ ARIN's policy requires ISPs to maintain IN-ADDR for /16 or larger
+ allocations. For smaller allocations, ARIN can provide IN-ADDR for
+ /24 and shorter prefixes. [ARIN]. APNIC provides methods for ISPs to
+ update IN-ADDR, however the present version of its policy document
+ for IPv4 [APNIC] dropped the IN-ADDR requirements that were in draft
+ copies of this document. As of this writing, it appears APNIC has no
+ actual policy on IN-ADDR. RIPE appears to have the strongest policy
+ in this area [RIPE302] indicating Local Internet Registries should
+ provide IN-ADDR services, and delegate those as appropriate when
+ address blocks are delegated.
+
+ As we can see, the regional registries have their own policies for
+ recommendations and/or requirements for IN-ADDR maintenance. It
+ should be noted, however, that many address blocks were allocated
+ before the creation of the regional registries, and thus it is
+ unclear whether any of the policies of the registries are binding on
+ those who hold blocks from that era.
+
+ Registries allocate address blocks on CIDR [RFC1519] boundaries.
+ Unfortunately the IN-ADDR zones are based on classful allocations.
+ Guidelines [RFC2317] for delegating on non-octet-aligned boundaries
+ exist, but are not always implemented.
+
+3. Examples of impact of missing IN-ADDR
+
+
+
+Senie [Page 2]
+
+Internet-Draft Encouraging the use of DNS IN-ADDR Mapping July 2005
+
+
+ These are some examples of problems that may be introduced by
+ reliance on IN-ADDR.
+
+ Some applications use DNS lookups for security checks. To ensure
+ validity of claimed names, some applications will look up IN-ADDR
+ records to get names, and then look up the resultant name to see if
+ it maps back to the address originally known. Failure to resolve
+ matching names is seen as a potential security concern.
+
+ Some FTP sites will flat-out reject users, even for anonymous FTP, if
+ the IN-ADDR lookup fails or if the result of the IN-ADDR lookup when
+ itself resolved, does not match. Some Telnet servers also implement
+ this check.
+
+ Web sites are in some cases using IN-ADDR checks to verify whether
+ the client is located within a certain geopolitical entity. This
+ approach has been employed for downloads of crypto software, for
+ example, where export of that software is prohibited to some locales.
+ Credit card anti-fraud systems also use these methods for geographic
+ placement purposes.
+
+ The popular TCP Wrappers program found on most Unix and Linux systems
+ has options to enforce IN-ADDR checks and to reject any client that
+ does not resolve. This program also has a way to check to see that
+ the name given by a PTR record then resolves back to the same IP
+ address. This method provdes more comfort but no appreciable
+ additional security.
+
+ Some anti-spam (anti junk email) systems use IN-ADDR to verify the
+ presence of a PTR record, or validate the PTR value points back to
+ the same address.
+
+ Many web servers look up the IN-ADDR of visitors to be used in log
+ analysis. This adds to the server load, but in the case of IN-ADDR
+ unavailability, it can lead to delayed responses for users.
+
+ Traceroutes with descriptive IN-ADDR naming proves useful when
+ debugging problems spanning large areas. When this information is
+ missing, the traceroutes take longer, and it takes additional steps
+ to determine that network is the cause of problems.
+
+ Wider-scale implementation of IN-ADDR on dialup, wireless access and
+ other such client-oriented portions of the Internet would result in
+ lower latency for queries (due to lack of negative caching), and
+ lower name server load and DNS traffic.
+
+4. Recommendations
+
+
+
+
+Senie [Page 3]
+
+Internet-Draft Encouraging the use of DNS IN-ADDR Mapping July 2005
+
+
+ 4.1 Delegation Recommendations
+
+
+ Regional Registries and any Local Registries to whom they delegate
+ should establish and convey a policy to those to whom they delegate
+ blocks that IN-ADDR mappings are recommended. Policies should
+ recommend those receiving delegations to provide IN-ADDR service
+ and/or delegate to downstream customers.
+
+ Network operators should define and implement policies and procedures
+ which delegate IN-ADDR to their clients who wish to run their own IN-
+ ADDR DNS services, and provide IN-ADDR services for those who do not
+ have the resources to do it themselves. Delegation mechanisms should
+ permit the downstream customer to implement and comply with IETF
+ recommendations application of IN-ADDR to CIDR [RFC2317].
+
+ All IP address space assigned and in use should be resolved by IN-
+ ADDR records. All PTR records must use canonical names.
+
+ All IP addresses in use within a block should have an IN-ADDR
+ mapping. Those addresses not in use, and those that are not valid for
+ use (zeros or ones broadcast addresses within a CIDR block) need not
+ have mappings.
+
+ It should be noted that due to CIDR, many addresses that appear to be
+ otherwise valid host addresses may actually be zeroes or ones
+ broadcast addresses. As such, attempting to audit a site's degree of
+ compliance may only be done with knowledge of the internal subnet
+ architecture of the site. It can be assumed, however, any host that
+ originates an IP packet necessarily will have a valid host address,
+ and must therefore have an IN-ADDR mapping.
+
+4.2 Application Recommendations
+
+
+ Applications SHOULD NOT rely on IN-ADDR for proper operation. The use
+ of IN-ADDR, sometimes in conjunction with a lookup of the name
+ resulting from the PTR record provides no real security, can lead to
+ erroneous results and generally just increases load on DNS servers.
+ Further, in cases where address block holders fail to properly
+ configure IN-ADDR, users of those blocks are penalized.
+
+5. Security Considerations
+
+ This document has no negative impact on security. While it could be
+ argued that lack of PTR record capabilities provides a degree of
+ anonymity, this is really not valid. Trace routes, whois lookups and
+ other sources will still provide methods for discovering identity.
+
+
+
+Senie [Page 4]
+
+Internet-Draft Encouraging the use of DNS IN-ADDR Mapping July 2005
+
+
+ By recommending applications avoid using IN-ADDR as a security
+ mechanism this document points out that this practice, despite its
+ use by many applications, is an ineffective form of security.
+ Applications should use better mechanisms of authentication.
+
+6. IANA Considerations
+
+ There are no IANA considerations for this document.
+
+7. References
+
+7.1 Normative References
+
+ [RFC883] P.V. Mockapetris, "Domain names: Implementation
+ specification," RFC883, November 1983.
+
+ [RFC1035] P.V. Mockapetris, "Domain Names: Implementation
+ Specification," RFC 1035, November 1987.
+
+ [RFC1519] V. Fuller, et. al., "Classless Inter-Domain Routing (CIDR):
+ an Address Assignment and Aggregation Strategy," RFC 1519, September
+ 1993.
+
+ [RFC2026] S. Bradner, "The Internet Standards Process -- Revision 3",
+ RFC 2026, BCP 9, October 1996.
+
+ [RFC2119] S. Bradner, "Key words for use in RFCs to Indicate
+ Requirement Levels", RFC 2119, BCP 14, March 1997.
+
+ [RFC2050] K. Hubbard, et. al., "Internet Registry IP Allocation
+ Guidelines", RFC2050, BCP 12, Novebmer 1996.
+
+ [RFC2317] H. Eidnes, et. al., "Classless IN-ADDR.ARPA delegation,"
+ RFC 2317, March 1998.
+
+ [RFC3152] R. Bush, "Delegation of IP6.ARPA," RFC 3152, BCP 49, August
+ 2001.
+
+7.2 Informative References
+
+ [ARIN] "ISP Guidelines for Requesting Initial IP Address Space," date
+ unknown, http://www.arin.net/regserv/initial-isp.html
+
+ [APNIC] "Policies For IPv4 Address Space Management in the Asia
+ Pacific Region," APNIC-086, 13 January 2003.
+
+ [RIPE302] "Policy for Reverse Address Delegation of IPv4 and IPv6
+ Address Space in the RIPE NCC Service Region", RIPE-302, April 26,
+
+
+
+Senie [Page 5]
+
+Internet-Draft Encouraging the use of DNS IN-ADDR Mapping July 2005
+
+
+ 2004. http://www.ripe.net//ripe/docs/rev-del.html
+
+
+
+8. Acknowledgements
+
+ Thanks to Peter Koch and Gary Miller for their input, and to many
+ people who encouraged me to write this document.
+
+9. Author's Address
+
+ Daniel Senie
+ Amaranth Networks Inc.
+ 324 Still River Road
+ Bolton, MA 01740
+
+ Phone: (978) 779-5100
+
+ EMail: dts@senie.com
+
+10. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided
+ on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE
+ REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT
+ THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR
+ ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
+ PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed
+ to pertain to the implementation or use of the technology
+ described in this document or the extent to which any license
+ under such rights might or might not be available; nor does it
+ represent that it has made any independent effort to identify any
+ such rights. Information on the procedures with respect to
+ rights in RFC documents can be found in BCP 78 and BCP 79.
+
+
+
+
+Senie [Page 6]
+
+Internet-Draft Encouraging the use of DNS IN-ADDR Mapping July 2005
+
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use
+ of such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository
+ at http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention
+ any copyrights, patents or patent applications, or other
+ proprietary rights that may cover technology that may be required
+ to implement this standard. Please address the information to the
+ IETF at ietf-ipr@ietf.org.
+
+ Internet-Drafts are working documents of the
+ Internet Engineering Task Force (IETF), its areas, and its
+ working groups. Note that other groups may also distribute
+ working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of
+ six months and may be updated, replaced, or obsoleted by
+ other documents at any time. It is inappropriate to use
+ Internet-Drafts as reference material or to cite them other
+ than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html
+
+ The list of Internet-Draft Shadow Directories can be
+ accessed at http://www.ietf.org/shadow.html
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Senie [Page 7]
+
diff --git a/doc/draft/draft-ietf-dnsop-ipv6-dns-configuration-06.txt b/doc/draft/draft-ietf-dnsop-ipv6-dns-configuration-06.txt
new file mode 100644
index 0000000..bf2afcd
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsop-ipv6-dns-configuration-06.txt
@@ -0,0 +1,1848 @@
+
+
+
+DNS Operations WG J. Jeong, Ed.
+Internet-Draft ETRI/University of Minnesota
+Expires: November 6, 2005 May 5, 2005
+
+
+ IPv6 Host Configuration of DNS Server Information Approaches
+ draft-ietf-dnsop-ipv6-dns-configuration-06.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is subject to all provisions
+ of Section 3 of RFC 3667. By submitting this Internet-Draft, each
+ author represents that any applicable patent or other IPR claims of
+ which he or she is aware have been or will be disclosed, and any of
+ which he or she become aware will be disclosed, in accordance with
+ RFC 3668.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on November 6, 2005.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document describes three approaches for IPv6 recursive DNS
+ server address configuration. It details the operational attributes
+ of three solutions: RA option, DHCPv6 option, and Well-known anycast
+ addresses for recursive DNS servers. Additionally, it suggests the
+ deployment scenarios in four kinds of networks, such as ISP,
+ Enterprise, 3GPP, and Unmanaged networks, considering multi-solution
+ resolution. Therefore, this document will give the audience a
+
+
+
+Jeong Expires November 6, 2005 [Page 1]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ guideline for IPv6 host DNS configuration.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 2]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 5
+ 2. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 3. IPv6 DNS Configuration Approaches . . . . . . . . . . . . . . 7
+ 3.1 RA Option . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 3.1.1 Advantages . . . . . . . . . . . . . . . . . . . . . . 8
+ 3.1.2 Disadvantages . . . . . . . . . . . . . . . . . . . . 8
+ 3.1.3 Observations . . . . . . . . . . . . . . . . . . . . . 9
+ 3.2 DHCPv6 Option . . . . . . . . . . . . . . . . . . . . . . 9
+ 3.2.1 Advantages . . . . . . . . . . . . . . . . . . . . . . 11
+ 3.2.2 Disadvantages . . . . . . . . . . . . . . . . . . . . 12
+ 3.2.3 Observations . . . . . . . . . . . . . . . . . . . . . 12
+ 3.3 Well-known Anycast Addresses . . . . . . . . . . . . . . . 12
+ 3.3.1 Advantages . . . . . . . . . . . . . . . . . . . . . . 13
+ 3.3.2 Disadvantages . . . . . . . . . . . . . . . . . . . . 14
+ 3.3.3 Observations . . . . . . . . . . . . . . . . . . . . . 14
+ 4. Interworking among IPv6 DNS Configuration Approaches . . . . . 15
+ 5. Deployment Scenarios . . . . . . . . . . . . . . . . . . . . . 16
+ 5.1 ISP Network . . . . . . . . . . . . . . . . . . . . . . . 16
+ 5.1.1 RA Option Approach . . . . . . . . . . . . . . . . . . 16
+ 5.1.2 DHCPv6 Option Approach . . . . . . . . . . . . . . . . 17
+ 5.1.3 Well-known Anycast Addresses Approach . . . . . . . . 17
+ 5.2 Enterprise Network . . . . . . . . . . . . . . . . . . . . 17
+ 5.3 3GPP Network . . . . . . . . . . . . . . . . . . . . . . . 18
+ 5.3.1 Currently Available Mechanisms and Recommendations . . 19
+ 5.3.2 RA Extension . . . . . . . . . . . . . . . . . . . . . 19
+ 5.3.3 Stateless DHCPv6 . . . . . . . . . . . . . . . . . . . 20
+ 5.3.4 Well-known Addresses . . . . . . . . . . . . . . . . . 21
+ 5.3.5 Recommendations . . . . . . . . . . . . . . . . . . . 21
+ 5.4 Unmanaged Network . . . . . . . . . . . . . . . . . . . . 22
+ 5.4.1 Case A: Gateway does not provide IPv6 at all . . . . . 22
+ 5.4.2 Case B: A dual-stack gateway connected to a
+ dual-stack ISP . . . . . . . . . . . . . . . . . . . . 22
+ 5.4.3 Case C: A dual-stack gateway connected to an
+ IPv4-only ISP . . . . . . . . . . . . . . . . . . . . 22
+ 5.4.4 Case D: A gateway connected to an IPv6-only ISP . . . 23
+ 6. Security Considerations . . . . . . . . . . . . . . . . . . . 24
+ 6.1 RA Option . . . . . . . . . . . . . . . . . . . . . . . . 25
+ 6.2 DHCPv6 Option . . . . . . . . . . . . . . . . . . . . . . 25
+ 6.3 Well-known Anycast Addresses . . . . . . . . . . . . . . . 25
+ 7. Contributors . . . . . . . . . . . . . . . . . . . . . . . . . 26
+ 8. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 28
+ 9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 29
+ 9.1 Normative References . . . . . . . . . . . . . . . . . . . 29
+ 9.2 Informative References . . . . . . . . . . . . . . . . . . 29
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . 31
+ A. Link-layer Multicast Acknowledgements for RA Option . . . . . 32
+
+
+
+Jeong Expires November 6, 2005 [Page 3]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ Intellectual Property and Copyright Statements . . . . . . . . 33
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 4]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+1. Introduction
+
+ Neighbor Discovery (ND) for IP Version 6 and IPv6 Stateless Address
+ Autoconfiguration provide the ways to configure either fixed or
+ mobile nodes with one or more IPv6 addresses, default routes and some
+ other parameters [3][4]. To support the access to additional
+ services in the Internet that are identified by a DNS name, such as a
+ web server, the configuration of at least one recursive DNS server is
+ also needed for DNS name resolution.
+
+ This document describes three approaches of recursive DNS server
+ address configuration for IPv6 host: (a) RA option [8], (b) DHCPv6
+ option [5]-[7], and (c) Well-known anycast addresses for recursive
+ DNS servers [9]. Also, it suggests the applicable scenarios for four
+ kinds of networks: (a) ISP network, (b) Enterprise network, (c) 3GPP
+ network, and (d) Unmanaged network.
+
+ This document is just an analysis of each possible approach, and does
+ not make any recommendation on a particular one or on a combination
+ of particular ones. Some approaches may even not be adopted at all
+ as a result of further discussion.
+
+ Therefore, the objective of this document is to help the audience
+ select the approaches suitable for IPv6 host configuration of
+ recursive DNS servers.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 5]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+2. Terminology
+
+ This document uses the terminology described in [3]-[9]. In
+ addition, a new term is defined below:
+
+ o Recursive DNS Server (RDNSS): A Recursive DNS Server is a name
+ server that offers the recursive service of DNS name resolution.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 6]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+3. IPv6 DNS Configuration Approaches
+
+ In this section, the operational attributes of the three solutions
+ are described in detail.
+
+3.1 RA Option
+
+ The RA approach is to define a new ND option called the RDNSS option
+ that contains a recursive DNS server address. Existing ND transport
+ mechanisms (i.e., advertisements and solicitations) are used. This
+ works in the same way that nodes learn about routers and prefixes.
+ An IPv6 host can configure the IPv6 addresses of one or more RDNSSes
+ via RA message periodically sent by a router or solicited by a Router
+ Solicitation (RS) [8].
+
+ This approach needs RDNSS information to be configured in the routers
+ doing the advertisements. The configuration of RDNSS addresses can
+ be performed manually by an operator or other ways, such as automatic
+ configuration through a DHCPv6 client running on the router. When
+ advertising more than one RDNSS option, an RA message includes as
+ many RDNSS options as RDNSSes.
+
+ Through the ND protocol and RDNSS option along with a prefix
+ information option, an IPv6 host can perform its network
+ configuration of its IPv6 address and RDNSS simultaneously [3][4].
+ The RA option for RDNSS can be used on any network that supports the
+ use of ND.
+
+ However, it is worth noting that some link layers, such as Wireless
+ LANs (e.g., IEEE 802.11 a/b/g), do not support reliable multicast,
+ which means that they cannot guarantee the timely delivery of RA
+ messages [25]-[28]. This is discussed in Appendix A.
+
+ The RA approach is useful in some mobile environments where the
+ addresses of the RDNSSes are changing because the RA option includes
+ a lifetime field that allows client to use RDNSSes nearer to the
+ client. This can be configured to a value that will require the
+ client to time out the entry and switch over to another RDNSS address
+ [8]. However, from the viewpoint of implementation, the lifetime
+ field would seem to make matters a bit more complex. Instead of just
+ writing to a DNS configuration file, such as resolv.conf for the list
+ of RDNSS addresses, we have to have a daemon around (or a program
+ that is called at the defined intervals) that keeps monitoring the
+ lifetime of RDNSSes all the time.
+
+ The preference value of RDNSS, included in the RDNSS option, allows
+ IPv6 hosts to select primary RDNSS among several RDNSSes; this can be
+ used for the load balancing of RDNSSes [8].
+
+
+
+Jeong Expires November 6, 2005 [Page 7]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+3.1.1 Advantages
+
+ The RA option for RDNSS has a number of advantages. These include:
+
+ 1. The RA option is an extension of existing ND/Autoconfig
+ mechanisms [3][4], and does not require a change in the base ND
+ protocol.
+
+ 2. This approach, like ND, works well on a variety of link types
+ including point-to-point links, point-to-multipoint, and
+ multipoint-to-multipoint (i.e., Ethernet LANs), etc. RFC 2461
+ [3] states, however, that there may be some link types on which
+ ND is not feasible; on such links, some other mechanisms will be
+ needed for DNS configuration.
+
+ 3. All of the information a host needs to run the basic Internet
+ applications such as the email, web, ftp, etc., can be obtained
+ with the addition of this option to ND and address
+ autoconfiguration. The use of a single mechanism is more
+ reliable and easier to provide than when the RDNSS information is
+ learned via another protocol mechanism. Debugging problems when
+ multiple protocol mechanisms are being used is harder and much
+ more complex.
+
+ 4. This mechanism works over a broad range of scenarios and
+ leverages IPv6 ND. This works well on links that support
+ broadcast reliably (e.g., Ethernet LANs) but not necessarily on
+ other links (e.g., Wireless LANs): Refer to Appendix A. Also,
+ this works well on links that are high performance (e.g.,
+ Ethernet LANs) and low performance (e.g., Cellular networks). In
+ the latter case, by combining the RDNSS information with the
+ other information in the RA, the host can learn all of the
+ information needed to use most Internet applications, such as the
+ web in a single packet. This not only saves bandwidth where this
+ is an issue, but also minimizes the delay needed to learn the
+ RDNSS information.
+
+ 5. The RA approach could be used as a model for other similar types
+ of configuration information. New RA options for other server
+ addresses, such as NTP server address, that are common to all
+ clients on a subnet would be easy to define.
+
+
+3.1.2 Disadvantages
+
+ 1. ND is mostly implemented in the kernel of operating system.
+ Therefore, if ND supports the configuration of some additional
+ services, such as DNS servers, ND should be extended in the
+
+
+
+Jeong Expires November 6, 2005 [Page 8]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ kernel, and complemented by a user-land process. DHCPv6,
+ however, has more flexibility for the extension of service
+ discovery because it is an application layer protocol.
+
+ 2. The current ND framework should be modified to facilitate the
+ synchronization between another ND cache for RDNSSes in the
+ kernel space and the DNS configuration file in the user space.
+ Because it is unacceptable to write and rewrite to the DNS
+ configuration file (e.g., resolv.conf) from the kernel, another
+ approach is needed. One simple approach to solve this is to have
+ a daemon listening to what the kernel conveys, and to have the
+ daemon do these steps, but such a daemon is not needed with the
+ current ND framework.
+
+ 3. It is necessary to configure RDNSS addresses at least at one
+ router on every link where this information needs to be
+ configured via the RA option.
+
+
+3.1.3 Observations
+
+ The proposed RDNSS RA option along with the IPv6 ND and
+ Autoconfiguration allows a host to obtain all of the information it
+ needs to access the basic Internet services like the web, email, ftp,
+ etc. This is preferable in the environments where hosts use RAs to
+ autoconfigure their addresses and all the hosts on the subnet share
+ the same router and server addresses. If the configuration
+ information can be obtained from a single mechanism, it is preferable
+ because it does not add additional delay, and it uses a minimum of
+ bandwidth. The environments like this include the homes, public
+ cellular networks, and enterprise environments where no per host
+ configuration is needed, but exclude public WLAN hot spots.
+
+ DHCPv6 is preferable where it is being used for address configuration
+ and if there is a need for host specific configuration [5]-[7]. The
+ environments like this are most likely to be the enterprise
+ environments where the local administration chooses to have per host
+ configuration control.
+
+Note
+
+ The observation section is based on what the proponents of each
+ approach think makes a good overall solution.
+
+3.2 DHCPv6 Option
+
+ DHCPv6 [5] includes the "DNS Recursive Name Server" option, through
+ which a host can obtain a list of IP addresses of recursive DNS
+
+
+
+Jeong Expires November 6, 2005 [Page 9]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ servers [7]. The DNS Recursive Name Server option carries a list of
+ IPv6 addresses of RDNSSes to which the host may send DNS queries.
+ The DNS servers are listed in the order of preference for use by the
+ DNS resolver on the host.
+
+ The DNS Recursive Name Server option can be carried in any DHCPv6
+ Reply message, in response to either a Request or an Information
+ request message. Thus, the DNS Recursive Name Server option can be
+ used either when DHCPv6 is used for address assignment, or when
+ DHCPv6 is used only for other configuration information as stateless
+ DHCPv6 [6].
+
+ Stateless DHCPv6 can be deployed either using DHCPv6 servers running
+ on general-purpose computers, or on router hardware. Several router
+ vendors currently implement stateless DHCPv6 servers. Deploying
+ stateless DHCPv6 in routers has the advantage that no special
+ hardware is required, and should work well for networks where DHCPv6
+ is needed for very straightforward configuration of network devices.
+
+ However, routers can also act as DHCPv6 relay agents. In this case,
+ the DHCPv6 server need not be on the router - it can be on a general
+ purpose computer. This has the potential to give the operator of the
+ DHCPv6 server more flexibility in how the DHCPv6 server responds to
+ individual clients - clients can easily be given different
+ configuration information based on their identity, or for any other
+ reason. Nothing precludes adding this flexibility to a router, but
+ generally in current practice, DHCP servers running on general-
+ purpose hosts tend to have more configuration options than those that
+ are embedded in routers.
+
+ DHCPv6 currently provides a mechanism for reconfiguring DHCPv6
+ clients that use a stateful configuration assignment. To do this,
+ the DHCPv6 server sends a Reconfigure message to the client. The
+ client validates the Reconfigure message, and then contacts the
+ DHCPv6 server to obtain updated configuration information. Using
+ this mechanism, it is currently possible to propagate new
+ configuration information to DHCPv6 clients as this information
+ changes.
+
+ The DHC Working Group is currently studying an additional mechanism
+ through which configuration information, including the list of
+ RDNSSes, can be updated. The lifetime option for DHCPv6 [10] assigns
+ a lifetime to configuration information obtained through DHCPv6. At
+ the expiration of the lifetime, the host contacts the DHCPv6 server
+ to obtain updated configuration information, including the list of
+ RDNSSes. This lifetime gives the network administrator another
+ mechanism to configure hosts with new RDNSSes by controlling the time
+ at which the host refreshes the list.
+
+
+
+Jeong Expires November 6, 2005 [Page 10]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ The DHC Working Group has also discussed the possibility of defining
+ an extension to DHCPv6 that would allow the use of multicast to
+ provide configuration information to multiple hosts with a single
+ DHCPv6 message. Because of the lack of deployment experience, the WG
+ has deferred consideration of multicast DHCPv6 configuration at this
+ time. Experience with DHCPv4 has not identified a requirement for
+ multicast message delivery, even in large service provider networks
+ with tens of thousands of hosts that may initiate a DHCPv4 message
+ exchange simultaneously.
+
+3.2.1 Advantages
+
+ The DHCPv6 option for RDNSS has a number of advantages. These
+ include:
+
+ 1. DHCPv6 currently provides a general mechanism for conveying
+ network configuration information to clients. So configuring
+ DHCPv6 servers allows the network administrator to configure
+ RDNSSes along with the addresses of other network services, as
+ well as location-specific information like time zones.
+
+ 2. As a consequence, when the network administrator goes to
+ configure DHCPv6, all the configuration information can be
+ managed through a single service, typically with a single user
+ interface and a single configuration database.
+
+ 3. DHCPv6 allows for the configuration of a host with information
+ specific to that host, so that hosts on the same link can be
+ configured with different RDNSSes as well as with other
+ configuration information. This capability is important in some
+ network deployments such as service provider networks or WiFi hot
+ spots.
+
+ 4. A mechanism exists for extending DHCPv6 to support the
+ transmission of additional configuration that has not yet been
+ anticipated.
+
+ 5. Hosts that require other configuration information such as the
+ addresses of SIP servers and NTP servers are likely to need
+ DHCPv6 for other configuration information.
+
+ 6. The specification for configuration of RDNSSes through DHCPv6 is
+ available as an RFC. No new protocol extensions such as new
+ options are necessary.
+
+ 7. Interoperability among independent implementations has been
+ demonstrated.
+
+
+
+
+Jeong Expires November 6, 2005 [Page 11]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+3.2.2 Disadvantages
+
+ The DHCPv6 option for RDNSS has a few disadvantages. These include:
+
+ 1. Update currently requires message from server (however, see
+ [10]).
+
+ 2. Because DNS information is not contained in RA messages, the host
+ must receive two messages from the router, and must transmit at
+ least one message to the router. On networks where bandwidth is
+ at a premium, this is a disadvantage, although on most networks
+ it is not a practical concern.
+
+ 3. Increased latency for initial configuration - in addition to
+ waiting for an RA message, the client must now exchange packets
+ with a DHCPv6 server; even if it is locally installed on a
+ router, this will slightly extend the time required to configure
+ the client. For clients that are moving rapidly from one network
+ to another, this will be a disadvantage.
+
+
+3.2.3 Observations
+
+ In the general case, on general-purpose networks, stateless DHCPv6
+ provides significant advantages and no significant disadvantages.
+ Even in the case where bandwidth is at a premium and low latency is
+ desired, if hosts require other configuration information in addition
+ to a list of RDNSSes or if hosts must be configured selectively,
+ those hosts will use DHCPv6 and the use of the DHCPv6 DNS recursive
+ name server option will be advantageous.
+
+ However, we are aware of some applications where it would be
+ preferable to put the RDNSS information into an RA packet; for
+ example, on a cell phone network, where bandwidth is at a premium and
+ extremely low latency is desired. The final DNS configuration draft
+ should be written so as to allow these special applications to be
+ handled using DNS information in the RA packet.
+
+3.3 Well-known Anycast Addresses
+
+ Anycast uses the same routing system as unicast [11]. However,
+ administrative entities are local ones. The local entities may
+ accept unicast routes (including default routes) to anycast servers
+ from adjacent entities. The administrative entities should not
+ advertise their peers routes to their internal anycast servers, if
+ they want to prohibit external access from some peers to the servers.
+ If some advertisement is inevitable (such as the case with default
+ routes), the packets to the servers should be blocked at the boundary
+
+
+
+Jeong Expires November 6, 2005 [Page 12]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ of the entities. Thus, for this anycast, not only unicast routing
+ but also unicast ND protocols can be used as is.
+
+ First of all, the well-known anycast addresses approach is much
+ different from that discussed at IPv6 Working Group in the past [9].
+ It should be noted that "anycast" in this memo is simpler than that
+ of RFC 1546 [11] and RFC 3513 [12] where it is assumed to be
+ prohibited to have multiple servers on a single link sharing an
+ anycast address. That is, on a link, an anycast address is assumed
+ to be unique. DNS clients today already have redundancy by having
+ multiple well-known anycast addresses configured as RDNSS addresses.
+ There is no point in having multiple RDNSSes sharing an anycast
+ address on a single link.
+
+ The approach with well-known anycast addresses is to set multiple
+ well-known anycast addresses in clients' resolver configuration files
+ from the beginning, say, as factory default. Thus, there is no
+ transport mechanism and no packet format [9].
+
+ An anycast address is an address shared by multiple servers (in this
+ case, the servers are RDNSSes). A request from a client to the
+ anycast address is routed to a server selected by the routing system.
+ However, it is a bad idea to mandate "site" boundary on anycast
+ addresses, because most users just do not have their own servers and
+ want to access their ISPs' across their site boundaries. Larger
+ sites may also depend on their ISPs or may have their own RDNSSes
+ within "site" boundaries.
+
+3.3.1 Advantages
+
+ The basic advantage of the well-known addresses approach is that it
+ uses no transport mechanism. Thus,
+
+ 1. There is no delay to get the response and no further delay by
+ packet losses.
+
+ 2. The approach can be combined with any other configuration
+ mechanisms, such as the RA-based approach and DHCP based
+ approach, as well as the factory default configuration.
+
+ 3. The approach works over any environment where DNS works.
+
+ Another advantage is that the approach needs to configure DNS servers
+ as a router, but nothing else. Considering that DNS servers do need
+ configuration, the amount of overall configuration effort is
+ proportional to the number of the DNS servers and scales linearly.
+ It should be noted that, in the simplest case where a subscriber to
+ an ISP does not have any DNS server, the subscriber naturally
+
+
+
+Jeong Expires November 6, 2005 [Page 13]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ accesses DNS servers of the ISP even though the subscriber and the
+ ISP do nothing and there is no protocol to exchange DNS server
+ information between the subscriber and the ISP.
+
+3.3.2 Disadvantages
+
+ Well-known anycast addresses approach requires that DNS servers (or
+ routers near it as a proxy) act as routers to advertise their anycast
+ addresses to the routing system, which requires some configuration
+ (see the last paragraph of the previous section on the scalability of
+ the effort).
+
+3.3.3 Observations
+
+ If other approaches are used in addition, the well-known anycast
+ addresses should also be set in RA or DHCP configuration files to
+ reduce the configuration effort of users.
+
+ The redundancy by multiple RDNSSes is better provided by multiple
+ servers having different anycast addresses than multiple servers
+ sharing the same anycast address because the former approach allows
+ stale servers to still generate routes to their anycast addresses.
+ Thus, in a routing domain (or domains sharing DNS servers), there
+ will be only one server having an anycast address unless the domain
+ is so large that load distribution is necessary.
+
+ Small ISPs will operate one RDNSS at each anycast address which is
+ shared by all the subscribers. Large ISPs may operate multiple
+ RDNSSes at each anycast address to distribute and reduce load, where
+ the boundary between RDNSSes may be fixed (redundancy is still
+ provided by multiple addresses) or change dynamically. DNS packets
+ with the well-known anycast addresses are not expected (though not
+ prohibited) to cross ISP boundaries, as ISPs are expected to be able
+ to take care of themselves.
+
+ Because "anycast" in this memo is simpler than that of RFC 1546 [11]
+ and RFC 3513 [12] where it is assumed to be administratively
+ prohibited to have multiple servers on a single link sharing an
+ anycast address, anycast in this memo should be implemented as
+ UNICAST of RFC 2461 [3] and RFC 3513 [12]. As a result, ND-related
+ instability disappears. Thus, anycast in well-known anycast
+ addresses approach can and should use the anycast address as a source
+ unicast (according to RFC 3513 [12]) address of packets of UDP and
+ TCP responses. With TCP, if a route flips and packets to an anycast
+ address are routed to a new server, it is expected that the flip is
+ detected by ICMP or sequence number inconsistency and the TCP
+ connection is reset and retried.
+
+
+
+
+Jeong Expires November 6, 2005 [Page 14]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+4. Interworking among IPv6 DNS Configuration Approaches
+
+ Three approaches can work together for IPv6 host configuration of
+ RDNSS. This section shows a consideration on how these approaches
+ can interwork each other.
+
+ For ordering between RA and DHCP approaches, the O (Other stateful
+ configuration) flag in RA message can be used [8][32]. If no RDNSS
+ option is included, an IPv6 host may perform DNS configuration
+ through DHCPv6 [5]-[7] regardless of whether the O flag is set or
+ not.
+
+ The well-known anycast addresses approach fully interworks with the
+ other approaches. That is, the other approaches can remove the
+ configuration effort on servers by using the well-known addresses as
+ the default configuration. Moreover, the clients preconfigured with
+ the well-known anycast addresses can be further configured to use
+ other approaches to override the well-known addresses, if the
+ configuration information from other approaches is available.
+ Otherwise, all the clients need to have the well-known anycast
+ addresses preconfigured. In order to use the anycast approach along
+ with two other approaches, there are three choices as follows:
+
+ 1. The first choice is that well-known addresses are used as last
+ resort, when an IPv6 host cannot get RDNSS information through RA
+ and DHCP. The well-known anycast addresses have to be
+ preconfigured in all of IPv6 hosts' resolver configuration files.
+
+ 2. The second is that an IPv6 host can configure well-known
+ addresses as the most preferable in its configuration file even
+ though either an RA option or DHCP option is available.
+
+ 3. The last is that the well-known anycast addresses can be set in
+ RA or DHCP configuration to reduce the configuration effort of
+ users. According to either the RA or DHCP mechanism, the well-
+ known addresses can be obtained by an IPv6 host. Because this
+ approach is the most convenient for users, the last option is
+ recommended.
+
+
+Note
+
+ This section does not necessarily mean this document suggests
+ adopting all these three approaches and making them interwork in the
+ way described here. In fact, some approaches may even not be adopted
+ at all as a result of further discussion.
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 15]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+5. Deployment Scenarios
+
+ Regarding the DNS configuration on the IPv6 host, several mechanisms
+ are being considered at the DNSOP Working Group such as RA option,
+ DHCPv6 option and well-known preconfigured anycast addresses as of
+ today, and this document is a final result from the long thread. In
+ this section, we suggest four applicable scenarios of three
+ approaches for IPv6 DNS configuration.
+
+Note
+
+ In the applicable scenarios, authors do not implicitly push any
+ specific approaches into the restricted environments. No enforcement
+ is in each scenario and all mentioned scenarios are probable. The
+ main objective of this work is to provide a useful guideline for IPv6
+ DNS configuration.
+
+5.1 ISP Network
+
+ A characteristic of ISP network is that multiple Customer Premises
+ Equipment (CPE) devices are connected to IPv6 PE (Provider Edge)
+ routers and each PE connects multiple CPE devices to the backbone
+ network infrastructure [13]. The CPEs may be hosts or routers.
+
+ In the case where the CPE is a router, there is a customer network
+ that is connected to the ISP backbone through the CPE. Typically,
+ each customer network gets a different IPv6 prefix from an IPv6 PE
+ router, but the same RDNSS configuration will be distributed.
+
+ This section discusses how the different approaches to distributing
+ DNS information are compared in an ISP network.
+
+5.1.1 RA Option Approach
+
+ When the CPE is a host, the RA option for RDNSS can be used to allow
+ the CPE to get RDNSS information as well as /64 prefix information
+ for stateless address autoconfiguration at the same time when the
+ host is attached to a new subnet [8]. Because an IPv6 host must
+ receive at least one RA message for stateless address
+ autoconfiguration and router configuration, the host could receive
+ RDNSS configuration information in that RA without the overhead of an
+ additional message exchange.
+
+ When the CPE is a router, the CPE may accept the RDNSS information
+ from the RA on the interface connected to the ISP, and copy that
+ information into the RAs advertised in the customer network.
+
+ This approach is more valuable in the mobile host scenario, in which
+
+
+
+Jeong Expires November 6, 2005 [Page 16]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ the host must receive at least an RA message for detecting a new
+ network, than in other scenarios generally although administrator
+ should configure RDNSS information on the routers. Secure ND [14]
+ can provide extended security when using RA messages.
+
+5.1.2 DHCPv6 Option Approach
+
+ DHCPv6 can be used for RDNSS configuration through the use of the DNS
+ option, and can provide other configuration information in the same
+ message with RDNSS configuration [5]-[7]. The DHCPv6 DNS option is
+ already in place for DHCPv6 as RFC 3646 [7] and DHCPv6-lite or
+ stateless DHCP [6] is nowhere as complex as a full DHCPv6
+ implementation. DHCP is a client-server model protocol, so ISPs can
+ handle user identification on its network intentionally, and also
+ authenticated DHCP [15] can be used for secure message exchange.
+
+ The expected model for deployment of IPv6 service by ISPs is to
+ assign a prefix to each customer, which will be used by the customer
+ gateway to assign a /64 prefix to each network in the customer's
+ network. Prefix delegation with DHCP (DHCPv6 PD) has already been
+ adopted by ISPs for automating the assignment of the customer prefix
+ to the customer gateway [17]. DNS configuration can be carried in
+ the same DHCPv6 message exchange used for DHCPv6 to efficiently
+ provide that information, along with any other configuration
+ information needed by the customer gateway or customer network. This
+ service model can be useful to Home or SOHO subscribers. The Home or
+ SOHO gateway, which is a customer gateway for ISP, can then pass that
+ RDNSS configuration information to the hosts in the customer network
+ through DHCP.
+
+5.1.3 Well-known Anycast Addresses Approach
+
+ The well-known anycast addresses approach is also a feasible and
+ simple mechanism for ISP [9]. The use of well-known anycast
+ addresses avoids some of the security risks in rogue messages sent
+ through an external protocol like RA or DHCPv6. The configuration of
+ hosts for the use of well-known anycast addresses requires no
+ protocol or manual configuration, but the configuration of routing
+ for the anycast addresses requires intervention on the part of the
+ network administrator. Also, the number of special addresses would
+ be equal to the number of RDNSSes that could be made available to
+ subscribers.
+
+5.2 Enterprise Network
+
+ Enterprise network is defined as a network that has multiple internal
+ links, one or more router connections, to one or more Providers and
+ is actively managed by a network operations entity [16]. An
+
+
+
+Jeong Expires November 6, 2005 [Page 17]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ enterprise network can get network prefixes from an ISP by either
+ manual configuration or prefix delegation [17]. In most cases,
+ because an enterprise network manages its own DNS domains, it
+ operates its own DNS servers for the domains. These DNS servers
+ within enterprise network process recursive DNS name resolution
+ requests from IPv6 hosts as RDNSSes. The RDNSS configuration in the
+ enterprise network can be performed like in Section 4, in which three
+ approaches can be used together as follows:
+
+ 1. An IPv6 host can decide which approach is or may be used in its
+ subnet with the O flag in RA message [8][32]. As the first
+ choice in Section 4, well-known anycast addresses can be used as
+ a last resort when RDNSS information cannot be obtained through
+ either an RA option or DHCP option. This case needs IPv6 hosts
+ to preconfigure the well-known anycast addresses in their DNS
+ configuration files.
+
+ 2. When the enterprise prefers the well-known anycast approach to
+ others, IPv6 hosts should preconfigure the well-known anycast
+ addresses like in the first choice.
+
+ 3. The last choice, a more convenient and transparent way, does not
+ need IPv6 hosts to preconfigure the well-known anycast addresses
+ because the addresses are delivered to IPv6 hosts via either the
+ RA option or DHCPv6 option as if they were unicast addresses.
+ This way is most recommended for the sake of user's convenience.
+
+
+5.3 3GPP Network
+
+ The IPv6 DNS configuration is a missing part of IPv6
+ autoconfiguration and an important part of the basic IPv6
+ functionality in the 3GPP User Equipment (UE). The higher level
+ description of the 3GPP architecture can be found in [18], and
+ transition to IPv6 in 3GPP networks is analyzed in [19] and [20].
+
+ In the 3GPP architecture, there is a dedicated link between the UE
+ and the GGSN called the Packet Data Protocol (PDP) Context. This
+ link is created through the PDP Context activation procedure [21].
+ There is a separate PDP context type for IPv4 and IPv6 traffic. If a
+ 3GPP UE user is communicating using IPv6 (having an active IPv6 PDP
+ context), it cannot be assumed that (s)he has simultaneously an
+ active IPv4 PDP context, and DNS queries could be done using IPv4. A
+ 3GPP UE can thus be an IPv6 node, and it needs to somehow discover
+ the address of the RDNSS. Before IP-based services (e.g., web
+ browsing or e-mail) can be used, the IPv6 (and IPv4) RDNSS addresses
+ need to be discovered in the 3GPP UE.
+
+
+
+
+Jeong Expires November 6, 2005 [Page 18]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ Section 5.3.1 briefly summarizes currently available mechanisms in
+ 3GPP networks and recommendations. 5.3.2 analyzes the Router
+ Advertisement based solution, 5.3.3 analyzes the Stateless DHCPv6
+ mechanism, and 5.3.4 analyzes the Well-known addresses approach.
+ Section 5.3.5 finally summarizes the recommendations.
+
+5.3.1 Currently Available Mechanisms and Recommendations
+
+ 3GPP has defined a mechanism, in which RDNSS addresses can be
+ received in the PDP context activation (a control plane mechanism).
+ That is called the Protocol Configuration Options Information Element
+ (PCO-IE) mechanism [22]. The RDNSS addresses can also be received
+ over the air (using text messages), or typed in manually in the UE.
+ Note that the two last mechanisms are not very well scalable. The UE
+ user most probably does not want to type IPv6 RDNSS addresses
+ manually in his/her UE. The use of well-known addresses is briefly
+ discussed in section 5.3.4.
+
+ It is seen that the mechanisms above most probably are not sufficient
+ for the 3GPP environment. IPv6 is intended to operate in a zero-
+ configuration manner, no matter what the underlying network
+ infrastructure is. Typically, the RDNSS address is needed to make an
+ IPv6 node operational - and the DNS configuration should be as simple
+ as the address autoconfiguration mechanism. It must also be noted
+ that there will be additional IP interfaces in some near future 3GPP
+ UEs, e.g., WLAN, and 3GPP-specific DNS configuration mechanisms (such
+ as PCO-IE [22]) do not work for those IP interfaces. In other words,
+ a good IPv6 DNS configuration mechanism should also work in a multi-
+ access network environment.
+
+ From a 3GPP point of view, the best IPv6 DNS configuration solution
+ is feasible for a very large number of IPv6-capable UEs (can be even
+ hundreds of millions in one operator's network), is automatic and
+ thus requires no user action. It is suggested to standardize a
+ lightweight, stateless mechanism that works in all network
+ environments. The solution could then be used for 3GPP, 3GPP2, WLAN
+ and other access network technologies. A light, stateless IPv6 DNS
+ configuration mechanism is thus not only needed in 3GPP networks, but
+ also 3GPP networks and UEs would certainly benefit from the new
+ mechanism.
+
+5.3.2 RA Extension
+
+ Router Advertisement extension [8] is a lightweight IPv6 DNS
+ configuration mechanism that requires minor changes in the 3GPP UE
+ IPv6 stack and Gateway GPRS Support Node (GGSN, the default router in
+ the 3GPP architecture) IPv6 stack. This solution can be specified in
+ the IETF (no action needed in the 3GPP) and taken in use in 3GPP UEs
+
+
+
+Jeong Expires November 6, 2005 [Page 19]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ and GGSNs
+
+ In this solution, an IPv6-capable UE configures DNS information via
+ RA message sent by its default router (GGSN), i.e., RDNSS option for
+ recursive DNS server is included in the RA message. This solution is
+ easily scalable for a very large number of UEs. The operator can
+ configure the RDNSS addresses in the GGSN as a part of normal GGSN
+ configuration. The IPv6 RDNSS address is received in the Router
+ Advertisement, and an extra Round Trip Time (RTT) for asking RDNSS
+ addresses can be avoided.
+
+ If thinking about the cons, this mechanism still requires
+ standardization effort in the IETF, and the end nodes and routers
+ need to support this mechanism. The equipment software update
+ should, however, be pretty straightforward, and new IPv6 equipment
+ could support RA extension already from the beginning.
+
+5.3.3 Stateless DHCPv6
+
+ DHCPv6-based solution needs the implementation of Stateless DHCP [6]
+ and DHCPv6 DNS options [7] in the UE, and a DHCPv6 server in the
+ operator's network. A possible configuration is such that the GGSN
+ works as a DHCP relay.
+
+ Pros for Stateless DHCPv6-based solution are
+
+ 1. Stateless DHCPv6 is a standardized mechanism.
+
+ 2. DHCPv6 can be used for receiving other configuration information
+ than RDNSS addresses, e.g., SIP server addresses.
+
+ 3. DHCPv6 works in different network environments.
+
+ 4. When DHCPv6 service is deployed through a single, centralized
+ server, the RDNSS configuration information can be updated by the
+ network administrator at a single source.
+
+ Some issues with DHCPv6 in 3GPP networks are listed below:
+
+ 1. DHCPv6 requires an additional server in the network unless the
+ (Stateless) DHCPv6 functionality is integrated into a router
+ already existing, and that means one box more to be maintained.
+
+ 2. DHCPv6 is not necessarily needed for 3GPP UE IPv6 addressing
+ (3GPP Stateless Address Autoconfiguration is typically used), and
+ not automatically implemented in 3GPP IPv6 UEs.
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 20]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ 3. Scalability and reliability of DHCPv6 in very large 3GPP networks
+ (with tens or hundreds of millions of UEs) may be an issue, at
+ least the redundancy needs to be taken care of. However, if the
+ DHCPv6 service is integrated into the network elements, such as a
+ router operating system, scalability and reliability is
+ comparable with other DNS configuration approaches.
+
+ 4. It is sub-optimal to utilize the radio resources in 3GPP networks
+ for DHCPv6 messages if there is a simpler alternative available.
+
+ * The use of Stateless DHCPv6 adds one round trip delay to the
+ case in which the UE can start transmitting data right after
+ the Router Advertisement.
+
+ 5. If the DNS information (suddenly) changes, Stateless DHCPv6 can
+ not automatically update the UE, see [23].
+
+
+5.3.4 Well-known Addresses
+
+ Using well-known addresses is also a feasible and a light mechanism
+ for 3GPP UEs. Those well-known addresses can be preconfigured in the
+ UE software and the operator makes the corresponding configuration on
+ the network side. So this is a very easy mechanism for the UE, but
+ requires some configuration work in the network. When using well-
+ known addresses, UE forwards queries to any of the preconfigured
+ addresses. In the current proposal [9], IPv6 anycast addresses are
+ suggested.
+
+Note
+
+ The IPv6 DNS configuration proposal based on the use of well-known
+ site-local addresses developed at the IPv6 Working Group was seen as
+ a feasible mechanism for 3GPP UEs, but opposition by some people in
+ the IETF and finally deprecating IPv6 site-local addresses made it
+ impossible to standardize it. Note that this mechanism is
+ implemented in some existing operating systems today (also in some
+ 3GPP UEs) as a last resort of IPv6 DNS configuration.
+
+5.3.5 Recommendations
+
+ It is suggested that a lightweight, stateless DNS configuration
+ mechanism is specified as soon as possible. From a 3GPP UE and
+ network point of view, the Router Advertisement based mechanism looks
+ most promising. The sooner a light, stateless mechanism is
+ specified, the sooner we can get rid of using well-known site-local
+ addresses for IPv6 DNS configuration.
+
+
+
+
+Jeong Expires November 6, 2005 [Page 21]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+5.4 Unmanaged Network
+
+ There are 4 deployment scenarios of interest in unmanaged networks
+ [24]:
+
+ 1. A gateway which does not provide IPv6 at all;
+
+ 2. A dual-stack gateway connected to a dual-stack ISP;
+
+ 3. A dual-stack gateway connected to an IPv4-only ISP; and
+
+ 4. A gateway connected to an IPv6-only ISP.
+
+
+5.4.1 Case A: Gateway does not provide IPv6 at all
+
+ In this case, the gateway does not provide IPv6; the ISP may or may
+ not provide IPv6. Automatic or Configured tunnels are the
+ recommended transition mechanisms for this scenario.
+
+ The case where dual-stack hosts behind an NAT, that need access to an
+ IPv6 RDNSS, cannot be entirely ruled out. The DNS configuration
+ mechanism has to work over the tunnel, and the underlying tunneling
+ mechanism could be implementing NAT traversal. The tunnel server
+ assumes the role of a relay (both for DHCP and Well-known anycast
+ addresses approaches).
+
+ RA-based mechanism is relatively straightforward in its operation,
+ assuming the tunnel server is also the IPv6 router emitting RAs.
+ Well-known anycast addresses approach seems also simple in operation
+ across the tunnel, but the deployment model using Well-known anycast
+ addresses in a tunneled environment is unclear or not well
+ understood.
+
+5.4.2 Case B: A dual-stack gateway connected to a dual-stack ISP
+
+ This is similar to a typical IPv4 home user scenario, where DNS
+ configuration parameters are obtained using DHCP. Except that
+ Stateless DHCPv6 is used, as opposed to the IPv4 scenario where the
+ DHCP server is stateful (maintains the state for clients).
+
+5.4.3 Case C: A dual-stack gateway connected to an IPv4-only ISP
+
+ This is similar to Case B. If a gateway provides IPv6 connectivity by
+ managing tunnels, then it is also supposed to provide access to an
+ RDNSS. Like this, the tunnel for IPv6 connectivity originates from
+ the dual-stack gateway instead of the host.
+
+
+
+
+Jeong Expires November 6, 2005 [Page 22]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+5.4.4 Case D: A gateway connected to an IPv6-only ISP
+
+ This is similar to Case B.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 23]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+6. Security Considerations
+
+ As security requirements depend solely on applications and are
+ different application by application, there can be no generic
+ requirement defined at IP or application layer for DNS.
+
+ However, it should be noted that cryptographic security requires
+ configured secret information that full autoconfiguration and
+ cryptographic security are mutually exclusive. People insisting on
+ secure full autoconfiguration will get false security, false
+ autoconfiguration or both.
+
+ In some deployment scenarios [19], where cryptographic security is
+ required for applications, the secret information for the
+ cryptographic security is preconfigured through which application
+ specific configuration data, including those for DNS, can be securely
+ configured. It should be noted that if applications requiring
+ cryptographic security depend on DNS, the applications also require
+ cryptographic security to DNS. Therefore, the full autoconfiguration
+ of DNS is not acceptable.
+
+ However, with full autoconfiguration, weaker but still reasonable
+ security is being widely accepted and will continue to be acceptable.
+ That is, with full autoconfiguration, which means there is no
+ cryptographic security for the autoconfiguration, it is already
+ assumed that the local environment is secure enough that the
+ information from the local autoconfiguration server has acceptable
+ security even without cryptographic security. Thus, the
+ communication between the local DNS client and local DNS server has
+ acceptable security.
+
+ In autoconfiguring recursive servers, DNSSEC may be overkill, because
+ DNSSEC [29] needs the configuration and reconfiguration of clients at
+ root key roll-over [30][31]. Even if additional keys for secure key
+ roll-over are added at the initial configuration, they are as
+ vulnerable as the original keys to some forms of attacks, such as
+ social hacking. Another problem of using DNSSEC and
+ autoconfiguration together is that DNSSEC requires secure time, which
+ means secure communication with autoconfigured time servers, which
+ requires configured secret information. Therefore, in order that the
+ autoconfiguration may be secure, it requires configured secret
+ information.
+
+ If DNSSEC [29] is used and the signatures are verified on the client
+ host, the misconfiguration of a DNS server may be simply denial of
+ service. Also, if local routing environment is not reliable, clients
+ may be directed to a false resolver with the same IP address as the
+ true one.
+
+
+
+Jeong Expires November 6, 2005 [Page 24]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+6.1 RA Option
+
+ The security of RA option for RDNSS is the same as the ND protocol
+ security [3][8]. The RA option does not add any new vulnerability.
+
+ It should be noted that the vulnerability of ND is not worse and is a
+ subset of the attacks that any node attached to a LAN can do
+ independently of ND. A malicious node on a LAN can promiscuously
+ receive packets for any router's MAC address and send packets with
+ the router's MAC address as the source MAC address in the L2 header.
+ As a result, the L2 switches send packets addressed to the router to
+ the malicious node. Also, this attack can send redirects that tell
+ the hosts to send their traffic somewhere else. The malicious node
+ can send unsolicited RA or NA replies, answer RS or NS requests, etc.
+ All of this can be done independently of implementing ND. Therefore,
+ the RA option for RDNSS does not add to the vulnerability.
+
+ Security issues regarding the ND protocol were discussed at IETF SEND
+ (Securing Neighbor Discovery) Working Group and RFC 3971 for the ND
+ security has been published [14].
+
+6.2 DHCPv6 Option
+
+ The DNS Recursive Name Server option may be used by an intruder DHCP
+ server to cause DHCP clients to send DNS queries to an intruder DNS
+ recursive name server [7]. The results of these misdirected DNS
+ queries may be used to spoof DNS names.
+
+ To avoid attacks through the DNS Recursive Name Server option, the
+ DHCP client SHOULD require DHCP authentication (see section
+ "Authentication of DHCP messages" in RFC 3315 [5]) before installing
+ a list of DNS recursive name servers obtained through authenticated
+ DHCP.
+
+6.3 Well-known Anycast Addresses
+
+ Well-known anycast addresses does not require configuration security
+ since there is no protocol [9].
+
+ The DNS server with the preconfigured addresses are still reasonably
+ reliable, if local environment is reasonably secure, that is, there
+ is no active attackers receiving queries to the anycast addresses of
+ the servers and reply to them.
+
+
+
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 25]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+7. Contributors
+
+ Ralph Droms
+ Cisco Systems, Inc.
+ 1414 Massachusetts Ave.
+ Boxboro, MA 01719
+ US
+
+ Phone: +1 978 936 1674
+ Email: rdroms@cisco.com
+
+
+ Robert M. Hinden
+ Nokia
+ 313 Fairchild Drive
+ Mountain View, CA 94043
+ US
+
+ Phone: +1 650 625 2004
+ Email: bob.hinden@nokia.com
+
+
+ Ted Lemon
+ Nominum, Inc.
+ 950 Charter Street
+ Redwood City, CA 94043
+ US
+
+ Email: Ted.Lemon@nominum.com
+
+
+ Masataka Ohta
+ Tokyo Institute of Technology
+ 2-12-1, O-okayama, Meguro-ku
+ Tokyo 152-8552
+ Japan
+
+ Phone: +81 3 5734 3299
+ Fax: +81 3 5734 3299
+ Email: mohta@necom830.hpcl.titech.ac.jp
+
+
+ Soohong Daniel Park
+ Mobile Platform Laboratory, SAMSUNG Electronics
+ 416 Maetan-3dong, Yeongtong-Gu
+ Suwon, Gyeonggi-Do 443-742
+ Korea
+
+
+
+
+Jeong Expires November 6, 2005 [Page 26]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ Phone: +82 31 200 4508
+ Email: soohong.park@samsung.com
+
+
+ Suresh Satapati
+ Cisco Systems, Inc.
+ San Jose, CA 95134
+ US
+
+ Email: satapati@cisco.com
+
+
+ Juha Wiljakka
+ Nokia
+ Visiokatu 3
+ FIN-33720, TAMPERE
+ Finland
+
+ Phone: +358 7180 48372
+ Email: juha.wiljakka@nokia.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 27]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+8. Acknowledgements
+
+ This draft has greatly benefited from inputs by David Meyer, Rob
+ Austein, Tatuya Jinmei, Pekka Savola, Tim Chown, Luc Beloeil,
+ Christian Huitema, Thomas Narten, Pascal Thubert, and Greg Daley.
+ Also, Tony Bonanno proofread this draft. The authors appreciate
+ their contribution.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 28]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+9. References
+
+9.1 Normative References
+
+ [1] Bradner, S., "IETF Rights in Contributions", RFC 3667,
+ February 2004.
+
+ [2] Bradner, S., "Intellectual Property Rights in IETF Technology",
+ RFC 3668, February 2004.
+
+ [3] Narten, T., Nordmark, E., and W. Simpson, "Neighbor Discovery
+ for IP Version 6 (IPv6)", RFC 2461, December 1998.
+
+ [4] Thomson, S. and T. Narten, "IPv6 Stateless Address
+ Autoconfiguration", RFC 2462, December 1998.
+
+ [5] Droms, R., Ed., "Dynamic Host Configuration Protocol for IPv6
+ (DHCPv6)", RFC 3315, July 2003.
+
+ [6] Droms, R., "Stateless Dynamic Host Configuration Protocol (DHCP)
+ Service for IPv6", RFC 3736, April 2004.
+
+ [7] Droms, R., Ed., "DNS Configuration options for Dynamic Host
+ Configuration Protocol for IPv6 (DHCPv6)", RFC 3646,
+ December 2003.
+
+9.2 Informative References
+
+ [8] Jeong, J., Park, S., Beloeil, L., and S. Madanapalli, "IPv6 DNS
+ Discovery based on Router Advertisement",
+ draft-jeong-dnsop-ipv6-dns-discovery-04.txt (Work in Progress),
+ February 2005.
+
+ [9] Ohta, M., "Preconfigured DNS Server Addresses",
+ draft-ohta-preconfigured-dns-01.txt (Work in Progress),
+ February 2004.
+
+ [10] Venaas, S., Chown, T., and B. Volz, "Information Refresh Time
+ Option for DHCPv6", draft-ietf-dhc-lifetime-03.txt (Work in
+ Progress), January 2005.
+
+ [11] Partridge, C., Mendez, T., and W. Milliken, "Host Anycasting
+ Service", RFC 1546, November 1993.
+
+ [12] Hinden, R. and S. Deering, "Internet Protocol Version 6 (IPv6)
+ Addressing Architecture", RFC 3513, April 2003.
+
+ [13] Lind, M., Ed., "Scenarios and Analysis for Introduction IPv6
+
+
+
+Jeong Expires November 6, 2005 [Page 29]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ into ISP Networks", RFC 4029, March 2005.
+
+ [14] Arkko, J., Ed., "SEcure Neighbor Discovery (SEND)", RFC 3971,
+ March 2005.
+
+ [15] Droms, R. and W. Arbaugh, "Authentication for DHCP Messages",
+ RFC 3118, June 2001.
+
+ [16] Bound, J., Ed., "IPv6 Enterprise Network Scenarios",
+ draft-ietf-v6ops-ent-scenarios-05.txt (Work in Progress),
+ July 2004.
+
+ [17] Troan, O. and R. Droms, "IPv6 Prefix Options for Dynamic Host
+ Configuration Protocol (DHCP) version 6", RFC 3633,
+ December 2003.
+
+ [18] Wasserman, M., Ed., "Recommendations for IPv6 in 3GPP
+ Standards", RFC 3314, September 2002.
+
+ [19] Soininen, J., Ed., "Transition Scenarios for 3GPP Networks",
+ RFC 3574, August 2003.
+
+ [20] Wiljakka, J., Ed., "Analysis on IPv6 Transition in 3GPP
+ Networks", draft-ietf-v6ops-3gpp-analysis-11.txt (Work in
+ Progress), October 2004.
+
+ [21] 3GPP TS 23.060 V5.4.0, "General Packet Radio Service (GPRS);
+ Service description; Stage 2 (Release 5)", December 2002.
+
+ [22] 3GPP TS 24.008 V5.8.0, "Mobile radio interface Layer 3
+ specification; Core network protocols; Stage 3 (Release 5)",
+ June 2003.
+
+ [23] Chown, T., Venaas, S., and A. Vijayabhaskar, "Renumbering
+ Requirements for Stateless DHCPv6",
+ draft-ietf-dhc-stateless-dhcpv6-renumbering-02.txt (Work in
+ Progress), October 2004.
+
+ [24] Huitema, C., Ed., "Unmanaged Networks IPv6 Transition
+ Scenarios", RFC 3750, April 2004.
+
+ [25] ANSI/IEEE Std 802.11, "Part 11: Wireless LAN Medium Access
+ Control (MAC) and Physical Layer (PHY) Specifications",
+ March 1999.
+
+ [26] IEEE Std 802.11a, "Part 11: Wireless LAN Medium Access Control
+ (MAC) and Physical Layer (PHY) specifications: High-speed
+ Physical Layer in the 5 GHZ Band", September 1999.
+
+
+
+Jeong Expires November 6, 2005 [Page 30]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+ [27] IEEE Std 802.11b, "Part 11: Wireless LAN Medium Access Control
+ (MAC) and Physical Layer (PHY) specifications: Higher-Speed
+ Physical Layer Extension in the 2.4 GHz Band", September 1999.
+
+ [28] IEEE P802.11g/D8.2, "Part 11: Wireless LAN Medium Access
+ Control (MAC) and Physical Layer (PHY) specifications: Further
+ Higher Data Rate Extension in the 2.4 GHz Band", April 2003.
+
+ [29] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [30] Kolkman, O. and R. Gieben, "DNSSEC Operational Practices",
+ draft-ietf-dnsop-dnssec-operational-practices-03.txt (Work in
+ Progress), December 2004.
+
+ [31] Guette, G. and O. Courtay, "Requirements for Automated Key
+ Rollover in DNSSEC",
+ draft-ietf-dnsop-key-rollover-requirements-02.txt (Work in
+ Progress), January 2005.
+
+ [32] Park, S., Madanapalli, S., and T. Jinmei, "Considerations on M
+ and O Flags of IPv6 Router Advertisement",
+ draft-ietf-ipv6-ra-mo-flags-01.txt (Work in Progress),
+ March 2005.
+
+
+Author's Address
+
+ Jaehoon Paul Jeong (editor)
+ ETRI/Department of Computer Science and Engineering
+ University of Minnesota
+ 117 Pleasant Street SE
+ Minneapolis, MN 55455
+ US
+
+ Phone: +1 651 587 7774
+ Fax: +1 612 625 2002
+ Email: jjeong@cs.umn.edu
+ URI: http://www.cs.umn.edu/~jjeong/
+
+
+
+
+
+
+
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 31]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+Appendix A. Link-layer Multicast Acknowledgements for RA Option
+
+ One benefit of an RA option [8] is to be able to multicast the
+ advertisements, reducing the need for duplicated unicast
+ communications.
+
+ However, some link-layers may not support this as well as others.
+ Consider, for example, WLAN networks where multicast is unreliable.
+ The unreliability problem is caused by lack of ACK for multicast,
+ especially on the path from the Access Point (AP) to the Station
+ (STA), which is specific to CSMA/CA of WLAN, such as IEEE 802.11
+ a/b/g [25]-[28]. That is, a multicast packet is unacknowledged on
+ the path from the AP to the STA, but acknowledged in the reverse
+ direction from the STA to the AP [25]. For example, when a router is
+ placed at wired network connected to an AP, a host may sometimes not
+ receive RA message advertised through the AP. Therefore, the RA
+ option solution might not work well on a congested medium that uses
+ unreliable multicast for RA.
+
+ The fact that this problem has not been addressed in Neighbor
+ Discovery [3] indicates that the extra link-layer acknowledgements
+ have not been considered a serious problem till now.
+
+ A possible mitigation technique could be to map all-nodes link- local
+ multicast address to the link-layer broadcast address, and to rely on
+ the ND retransmissions for message delivery in order to achieve more
+ reliability.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Jeong Expires November 6, 2005 [Page 32]
+
+Internet-Draft IPv6 Host Configuration of DNS Server May 2005
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2005). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Jeong Expires November 6, 2005 [Page 33]
+
diff --git a/doc/draft/draft-ietf-dnsop-ipv6-dns-issues-11.txt b/doc/draft/draft-ietf-dnsop-ipv6-dns-issues-11.txt
new file mode 100644
index 0000000..1276f9f
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsop-ipv6-dns-issues-11.txt
@@ -0,0 +1,1682 @@
+
+
+
+
+DNS Operations WG A. Durand
+Internet-Draft SUN Microsystems, Inc.
+Expires: January 17, 2006 J. Ihren
+ Autonomica
+ P. Savola
+ CSC/FUNET
+ July 16, 2005
+
+
+ Operational Considerations and Issues with IPv6 DNS
+ draft-ietf-dnsop-ipv6-dns-issues-11.txt
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on January 17, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This memo presents operational considerations and issues with IPv6
+ Domain Name System (DNS), including a summary of special IPv6
+ addresses, documentation of known DNS implementation misbehaviour,
+ recommendations and considerations on how to perform DNS naming for
+ service provisioning and for DNS resolver IPv6 support,
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 1]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ considerations for DNS updates for both the forward and reverse
+ trees, and miscellaneous issues. This memo is aimed to include a
+ summary of information about IPv6 DNS considerations for those who
+ have experience with IPv4 DNS.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.1 Representing IPv6 Addresses in DNS Records . . . . . . . . 4
+ 1.2 Independence of DNS Transport and DNS Records . . . . . . 4
+ 1.3 Avoiding IPv4/IPv6 Name Space Fragmentation . . . . . . . 5
+ 1.4 Query Type '*' and A/AAAA Records . . . . . . . . . . . . 5
+ 2. DNS Considerations about Special IPv6 Addresses . . . . . . . 5
+ 2.1 Limited-scope Addresses . . . . . . . . . . . . . . . . . 6
+ 2.2 Temporary Addresses . . . . . . . . . . . . . . . . . . . 6
+ 2.3 6to4 Addresses . . . . . . . . . . . . . . . . . . . . . . 6
+ 2.4 Other Transition Mechanisms . . . . . . . . . . . . . . . 6
+ 3. Observed DNS Implementation Misbehaviour . . . . . . . . . . . 7
+ 3.1 Misbehaviour of DNS Servers and Load-balancers . . . . . . 7
+ 3.2 Misbehaviour of DNS Resolvers . . . . . . . . . . . . . . 7
+ 4. Recommendations for Service Provisioning using DNS . . . . . . 7
+ 4.1 Use of Service Names instead of Node Names . . . . . . . . 8
+ 4.2 Separate vs the Same Service Names for IPv4 and IPv6 . . . 8
+ 4.3 Adding the Records Only when Fully IPv6-enabled . . . . . 9
+ 4.4 The Use of TTL for IPv4 and IPv6 RRs . . . . . . . . . . . 10
+ 4.4.1 TTL With Courtesy Additional Data . . . . . . . . . . 10
+ 4.4.2 TTL With Critical Additional Data . . . . . . . . . . 10
+ 4.5 IPv6 Transport Guidelines for DNS Servers . . . . . . . . 11
+ 5. Recommendations for DNS Resolver IPv6 Support . . . . . . . . 11
+ 5.1 DNS Lookups May Query IPv6 Records Prematurely . . . . . . 11
+ 5.2 Obtaining a List of DNS Recursive Resolvers . . . . . . . 13
+ 5.3 IPv6 Transport Guidelines for Resolvers . . . . . . . . . 13
+ 6. Considerations about Forward DNS Updating . . . . . . . . . . 13
+ 6.1 Manual or Custom DNS Updates . . . . . . . . . . . . . . . 14
+ 6.2 Dynamic DNS . . . . . . . . . . . . . . . . . . . . . . . 14
+ 7. Considerations about Reverse DNS Updating . . . . . . . . . . 15
+ 7.1 Applicability of Reverse DNS . . . . . . . . . . . . . . . 15
+ 7.2 Manual or Custom DNS Updates . . . . . . . . . . . . . . . 16
+ 7.3 DDNS with Stateless Address Autoconfiguration . . . . . . 16
+ 7.4 DDNS with DHCP . . . . . . . . . . . . . . . . . . . . . . 18
+ 7.5 DDNS with Dynamic Prefix Delegation . . . . . . . . . . . 18
+ 8. Miscellaneous DNS Considerations . . . . . . . . . . . . . . . 19
+ 8.1 NAT-PT with DNS-ALG . . . . . . . . . . . . . . . . . . . 19
+ 8.2 Renumbering Procedures and Applications' Use of DNS . . . 19
+ 9. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 20
+ 10. Security Considerations . . . . . . . . . . . . . . . . . . 20
+ 11. References . . . . . . . . . . . . . . . . . . . . . . . . . 20
+ 11.1 Normative References . . . . . . . . . . . . . . . . . . . 20
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 2]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ 11.2 Informative References . . . . . . . . . . . . . . . . . . 22
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 24
+ A. Unique Local Addressing Considerations for DNS . . . . . . . . 25
+ B. Behaviour of Additional Data in IPv4/IPv6 Environments . . . . 25
+ B.1 Description of Additional Data Scenarios . . . . . . . . . 26
+ B.2 Which Additional Data to Keep, If Any? . . . . . . . . . . 27
+ B.3 Discussion of the Potential Problems . . . . . . . . . . . 28
+ Intellectual Property and Copyright Statements . . . . . . . . 30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 3]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+1. Introduction
+
+ This memo presents operational considerations and issues with IPv6
+ DNS; it is meant to be an extensive summary and a list of pointers
+ for more information about IPv6 DNS considerations for those with
+ experience with IPv4 DNS.
+
+ The purpose of this document is to give information about various
+ issues and considerations related to DNS operations with IPv6; it is
+ not meant to be a normative specification or standard for IPv6 DNS.
+
+ The first section gives a brief overview of how IPv6 addresses and
+ names are represented in the DNS, how transport protocols and
+ resource records (don't) relate, and what IPv4/IPv6 name space
+ fragmentation means and how to avoid it; all of these are described
+ at more length in other documents.
+
+ The second section summarizes the special IPv6 address types and how
+ they relate to DNS. The third section describes observed DNS
+ implementation misbehaviours which have a varying effect on the use
+ of IPv6 records with DNS. The fourth section lists recommendations
+ and considerations for provisioning services with DNS. The fifth
+ section in turn looks at recommendations and considerations about
+ providing IPv6 support in the resolvers. The sixth and seventh
+ sections describe considerations with forward and reverse DNS
+ updates, respectively. The eighth section introduces several
+ miscellaneous IPv6 issues relating to DNS for which no better place
+ has been found in this memo. Appendix A looks briefly at the
+ requirements for unique local addressing.
+
+1.1 Representing IPv6 Addresses in DNS Records
+
+ In the forward zones, IPv6 addresses are represented using AAAA
+ records. In the reverse zones, IPv6 address are represented using
+ PTR records in the nibble format under the ip6.arpa. tree. See
+ [RFC3596] for more about IPv6 DNS usage, and [RFC3363] or [RFC3152]
+ for background information.
+
+ In particular one should note that the use of A6 records in the
+ forward tree or Bitlabels in the reverse tree is not recommended
+ [RFC3363]. Using DNAME records is not recommended in the reverse
+ tree in conjunction with A6 records; the document did not mean to
+ take a stance on any other use of DNAME records [RFC3364].
+
+1.2 Independence of DNS Transport and DNS Records
+
+ DNS has been designed to present a single, globally unique name space
+ [RFC2826]. This property should be maintained, as described here and
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 4]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ in Section 1.3.
+
+ The IP version used to transport the DNS queries and responses is
+ independent of the records being queried: AAAA records can be queried
+ over IPv4, and A records over IPv6. The DNS servers must not make
+ any assumptions about what data to return for Answer and Authority
+ sections based on the underlying transport used in a query.
+
+ However, there is some debate whether the addresses in Additional
+ section could be selected or filtered using hints obtained from which
+ transport was being used; this has some obvious problems because in
+ many cases the transport protocol does not correlate with the
+ requests, and because a "bad" answer is in a way worse than no answer
+ at all (consider the case where the client is led to believe that a
+ name received in the additional record does not have any AAAA records
+ at all).
+
+ As stated in [RFC3596]:
+
+ The IP protocol version used for querying resource records is
+ independent of the protocol version of the resource records; e.g.,
+ IPv4 transport can be used to query IPv6 records and vice versa.
+
+
+1.3 Avoiding IPv4/IPv6 Name Space Fragmentation
+
+ To avoid the DNS name space from fragmenting into parts where some
+ parts of DNS are only visible using IPv4 (or IPv6) transport, the
+ recommendation is to always keep at least one authoritative server
+ IPv4-enabled, and to ensure that recursive DNS servers support IPv4.
+ See DNS IPv6 transport guidelines [RFC3901] for more information.
+
+1.4 Query Type '*' and A/AAAA Records
+
+ QTYPE=* is typically only used for debugging or management purposes;
+ it is worth keeping in mind that QTYPE=* ("ANY" queries) only return
+ any available RRsets, not *all* the RRsets, because the caches do not
+ necessarily have all the RRsets and have no way of guaranteeing that
+ they have all the RRsets. Therefore, to get both A and AAAA records
+ reliably, two separate queries must be made.
+
+2. DNS Considerations about Special IPv6 Addresses
+
+ There are a couple of IPv6 address types which are somewhat special;
+ these are considered here.
+
+
+
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 5]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+2.1 Limited-scope Addresses
+
+ The IPv6 addressing architecture [RFC3513] includes two kinds of
+ local-use addresses: link-local (fe80::/10) and site-local
+ (fec0::/10). The site-local addresses have been deprecated [RFC3879]
+ but are discussed with unique local addresses in Appendix A.
+
+ Link-local addresses should never be published in DNS (whether in
+ forward or reverse tree), because they have only local (to the
+ connected link) significance [I-D.durand-dnsop-dont-publish].
+
+2.2 Temporary Addresses
+
+ Temporary addresses defined in RFC3041 [RFC3041] (sometimes called
+ "privacy addresses") use a random number as the interface identifier.
+ Having DNS AAAA records that are updated to always contain the
+ current value of a node's temporary address would defeat the purpose
+ of the mechanism and is not recommended. However, it would still be
+ possible to return a non-identifiable name (e.g., the IPv6 address in
+ hexadecimal format), as described in [RFC3041].
+
+2.3 6to4 Addresses
+
+ 6to4 [RFC3056] specifies an automatic tunneling mechanism which maps
+ a public IPv4 address V4ADDR to an IPv6 prefix 2002:V4ADDR::/48.
+
+ If the reverse DNS population would be desirable (see Section 7.1 for
+ applicability), there are a number of possible ways to do so.
+
+ The main proposal [I-D.huston-6to4-reverse-dns] aims to design an
+ autonomous reverse-delegation system that anyone being capable of
+ communicating using a specific 6to4 address would be able to set up a
+ reverse delegation to the corresponding 6to4 prefix. This could be
+ deployed by e.g., Regional Internet Registries (RIRs). This is a
+ practical solution, but may have some scalability concerns.
+
+2.4 Other Transition Mechanisms
+
+ 6to4 is mentioned as a case of an IPv6 transition mechanism requiring
+ special considerations. In general, mechanisms which include a
+ special prefix may need a custom solution; otherwise, for example
+ when IPv4 address is embedded as the suffix or not embedded at all,
+ special solutions are likely not needed.
+
+ Note that it does not seem feasible to provide reverse DNS with
+ another automatic tunneling mechanism, Teredo [I-D.huitema-v6ops-
+ teredo]; this is because the IPv6 address is based on the IPv4
+ address and UDP port of the current NAT mapping which is likely to be
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 6]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ relatively short-lived.
+
+3. Observed DNS Implementation Misbehaviour
+
+ Several classes of misbehaviour in DNS servers, load-balancers and
+ resolvers have been observed. Most of these are rather generic, not
+ only applicable to IPv6 -- but in some cases, the consequences of
+ this misbehaviour are extremely severe in IPv6 environments and
+ deserve to be mentioned.
+
+3.1 Misbehaviour of DNS Servers and Load-balancers
+
+ There are several classes of misbehaviour in certain DNS servers and
+ load-balancers which have been noticed and documented [RFC4074]: some
+ implementations silently drop queries for unimplemented DNS records
+ types, or provide wrong answers to such queries (instead of a proper
+ negative reply). While typically these issues are not limited to
+ AAAA records, the problems are aggravated by the fact that AAAA
+ records are being queried instead of (mainly) A records.
+
+ The problems are serious because when looking up a DNS name, typical
+ getaddrinfo() implementations, with AF_UNSPEC hint given, first try
+ to query the AAAA records of the name, and after receiving a
+ response, query the A records. This is done in a serial fashion --
+ if the first query is never responded to (instead of properly
+ returning a negative answer), significant timeouts will occur.
+
+ In consequence, this is an enormous problem for IPv6 deployments, and
+ in some cases, IPv6 support in the software has even been disabled
+ due to these problems.
+
+ The solution is to fix or retire those misbehaving implementations,
+ but that is likely not going to be effective. There are some
+ possible ways to mitigate the problem, e.g., by performing the
+ lookups somewhat in parallel and reducing the timeout as long as at
+ least one answer has been received; but such methods remain to be
+ investigated; slightly more on this is included in Section 5.
+
+3.2 Misbehaviour of DNS Resolvers
+
+ Several classes of misbehaviour have also been noticed in DNS
+ resolvers [I-D.ietf-dnsop-bad-dns-res]. However, these do not seem
+ to directly impair IPv6 use, and are only referred to for
+ completeness.
+
+4. Recommendations for Service Provisioning using DNS
+
+ When names are added in the DNS to facilitate a service, there are
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 7]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ several general guidelines to consider to be able to do it as
+ smoothly as possible.
+
+4.1 Use of Service Names instead of Node Names
+
+ It makes sense to keep information about separate services logically
+ separate in the DNS by using a different DNS hostname for each
+ service. There are several reasons for doing this, for example:
+
+ o It allows more flexibility and ease for migration of (only a part
+ of) services from one node to another,
+
+ o It allows configuring different properties (e.g., TTL) for each
+ service, and
+
+ o It allows deciding separately for each service whether to publish
+ the IPv6 addresses or not (in cases where some services are more
+ IPv6-ready than others).
+
+ Using SRV records [RFC2782] would avoid these problems.
+ Unfortunately, those are not sufficiently widely used to be
+ applicable in most cases. Hence an operation technique is to use
+ service names instead of node names (or, "hostnames"). This
+ operational technique is not specific to IPv6, but required to
+ understand the considerations described in Section 4.2 and
+ Section 4.3.
+
+ For example, assume a node named "pobox.example.com" provides both
+ SMTP and IMAP service. Instead of configuring the MX records to
+ point at "pobox.example.com", and configuring the mail clients to
+ look up the mail via IMAP from "pobox.example.com", one could use
+ e.g., "smtp.example.com" for SMTP (for both message submission and
+ mail relaying between SMTP servers) and "imap.example.com" for IMAP.
+ Note that in the specific case of SMTP relaying, the server itself
+ must typically also be configured to know all its names to ensure
+ loops do not occur. DNS can provide a layer of indirection between
+ service names and where the service actually is, and using which
+ addresses. (Obviously, when wanting to reach a specific node, one
+ should use the hostname rather than a service name.)
+
+4.2 Separate vs the Same Service Names for IPv4 and IPv6
+
+ The service naming can be achieved in basically two ways: when a
+ service is named "service.example.com" for IPv4, the IPv6-enabled
+ service could either be added to "service.example.com", or added
+ separately under a different name, e.g., in a sub-domain, like,
+ "service.ipv6.example.com".
+
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 8]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ These two methods have different characteristics. Using a different
+ name allows for easier service piloting, minimizing the disturbance
+ to the "regular" users of IPv4 service; however, the service would
+ not be used transparently, without the user/application explicitly
+ finding it and asking for it -- which would be a disadvantage in most
+ cases. When the different name is under a sub-domain, if the
+ services are deployed within a restricted network (e.g., inside an
+ enterprise), it's possible to prefer them transparently, at least to
+ a degree, by modifying the DNS search path; however, this is a
+ suboptimal solution. Using the same service name is the "long-term"
+ solution, but may degrade performance for those clients whose IPv6
+ performance is lower than IPv4, or does not work as well (see
+ Section 4.3 for more).
+
+ In most cases, it makes sense to pilot or test a service using
+ separate service names, and move to the use of the same name when
+ confident enough that the service level will not degrade for the
+ users unaware of IPv6.
+
+4.3 Adding the Records Only when Fully IPv6-enabled
+
+ The recommendation is that AAAA records for a service should not be
+ added to the DNS until all of following are true:
+
+ 1. The address is assigned to the interface on the node.
+
+ 2. The address is configured on the interface.
+
+ 3. The interface is on a link which is connected to the IPv6
+ infrastructure.
+
+ In addition, if the AAAA record is added for the node, instead of
+ service as recommended, all the services of the node should be IPv6-
+ enabled prior to adding the resource record.
+
+ For example, if an IPv6 node is isolated from an IPv6 perspective
+ (e.g., it is not connected to IPv6 Internet) constraint #3 would mean
+ that it should not have an address in the DNS.
+
+ Consider the case of two dual-stack nodes, which both have IPv6
+ enabled, but the server does not have (global) IPv6 connectivity. As
+ the client looks up the server's name, only A records are returned
+ (if the recommendations above are followed), and no IPv6
+ communication, which would have been unsuccessful, is even attempted.
+
+ The issues are not always so black-and-white. Usually it's important
+ that the service offered using both protocols is of roughly equal
+ quality, using the appropriate metrics for the service (e.g.,
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 9]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ latency, throughput, low packet loss, general reliability, etc.) --
+ this is typically very important especially for interactive or real-
+ time services. In many cases, the quality of IPv6 connectivity may
+ not yet be equal to that of IPv4, at least globally -- this has to be
+ taken into consideration when enabling services.
+
+4.4 The Use of TTL for IPv4 and IPv6 RRs
+
+ The behaviour of DNS caching when different TTL values are used for
+ different RRsets of the same name calls for explicit discussion. For
+ example, let's consider two unrelated zone fragments:
+
+ example.com. 300 IN MX foo.example.com.
+ foo.example.com. 300 IN A 192.0.2.1
+ foo.example.com. 100 IN AAAA 2001:db8::1
+
+ ...
+
+ child.example.com. 300 IN NS ns.child.example.com.
+ ns.child.example.com. 300 IN A 192.0.2.1
+ ns.child.example.com. 100 IN AAAA 2001:db8::1
+
+ In the former case, we have "courtesy" additional data; in the
+ latter, we have "critical" additional data. See more extensive
+ background discussion of additional data handling in Appendix B.
+
+4.4.1 TTL With Courtesy Additional Data
+
+ When a caching resolver asks for the MX record of example.com, it
+ gets back "foo.example.com". It may also get back either one or both
+ of the A and AAAA records in the additional section. The resolver
+ must explicitly query for both A and AAAA records [RFC2821].
+
+ After 100 seconds, the AAAA record is removed from the cache(s)
+ because its TTL expired. It could be argued to be useful for the
+ caching resolvers to discard the A record when the shorter TTL (in
+ this case, for the AAAA record) expires; this would avoid the
+ situation where there would be a window of 200 seconds when
+ incomplete information is returned from the cache. Further argument
+ for discarding is that in the normal operation, the TTL values are so
+ high that very likely the incurred additional queries would not be
+ noticeable, compared to the obtained performance optimization. The
+ behaviour in this scenario is unspecified.
+
+4.4.2 TTL With Critical Additional Data
+
+ The difference to courtesy additional data is that the A/AAAA records
+ served by the parent zone cannot be queried explicitly. Therefore
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 10]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ after 100 seconds the AAAA record is removed from the cache(s), but
+ the A record remains. Queries for the remaining 200 seconds
+ (provided that there are no further queries from the parent which
+ could refresh the caches) only return the A record, leading to a
+ potential opererational situation with unreachable servers.
+
+ Similar cache flushing strategies apply in this scenario; the record.
+
+4.5 IPv6 Transport Guidelines for DNS Servers
+
+ As described in Section 1.3 and [RFC3901], there should continue to
+ be at least one authoritative IPv4 DNS server for every zone, even if
+ the zone has only IPv6 records. (Note that obviously, having more
+ servers with robust connectivity would be preferable, but this is the
+ minimum recommendation; also see [RFC2182].)
+
+5. Recommendations for DNS Resolver IPv6 Support
+
+ When IPv6 is enabled on a node, there are several things to consider
+ to ensure that the process is as smooth as possible.
+
+5.1 DNS Lookups May Query IPv6 Records Prematurely
+
+ The system library that implements the getaddrinfo() function for
+ looking up names is a critical piece when considering the robustness
+ of enabling IPv6; it may come in basically three flavours:
+
+ 1. The system library does not know whether IPv6 has been enabled in
+ the kernel of the operating system: it may start looking up AAAA
+ records with getaddrinfo() and AF_UNSPEC hint when the system is
+ upgraded to a system library version which supports IPv6.
+
+ 2. The system library might start to perform IPv6 queries with
+ getaddrinfo() only when IPv6 has been enabled in the kernel.
+ However, this does not guarantee that there exists any useful
+ IPv6 connectivity (e.g., the node could be isolated from the
+ other IPv6 networks, only having link-local addresses).
+
+ 3. The system library might implement a toggle which would apply
+ some heuristics to the "IPv6-readiness" of the node before
+ starting to perform queries; for example, it could check whether
+ only link-local IPv6 address(es) exists, or if at least one
+ global IPv6 address exists.
+
+ First, let us consider generic implications of unnecessary queries
+ for AAAA records: when looking up all the records in the DNS, AAAA
+ records are typically tried first, and then A records. These are
+ done in serial, and the A query is not performed until a response is
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 11]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ received to the AAAA query. Considering the misbehaviour of DNS
+ servers and load-balancers, as described in Section 3.1, the look-up
+ delay for AAAA may incur additional unnecessary latency, and
+ introduce a component of unreliability.
+
+ One option here could be to do the queries partially in parallel; for
+ example, if the final response to the AAAA query is not received in
+ 0.5 seconds, start performing the A query while waiting for the
+ result (immediate parallelism might be unoptimal, at least without
+ information sharing between the look-up threads, as that would
+ probably lead to duplicate non-cached delegation chain lookups).
+
+ An additional concern is the address selection, which may, in some
+ circumstances, prefer AAAA records over A records even when the node
+ does not have any IPv6 connectivity [I-D.ietf-v6ops-v6onbydefault].
+ In some cases, the implementation may attempt to connect or send a
+ datagram on a physical link [I-D.ietf-v6ops-onlinkassumption],
+ incurring very long protocol timeouts, instead of quickly failing
+ back to IPv4.
+
+ Now, we can consider the issues specific to each of the three
+ possibilities:
+
+ In the first case, the node performs a number of completely useless
+ DNS lookups as it will not be able to use the returned AAAA records
+ anyway. (The only exception is where the application desires to know
+ what's in the DNS, but not use the result for communication.) One
+ should be able to disable these unnecessary queries, for both latency
+ and reliability reasons. However, as IPv6 has not been enabled, the
+ connections to IPv6 addresses fail immediately, and if the
+ application is programmed properly, the application can fall
+ gracefully back to IPv4 [RFC4038].
+
+ The second case is similar to the first, except it happens to a
+ smaller set of nodes when IPv6 has been enabled but connectivity has
+ not been provided yet; similar considerations apply, with the
+ exception that IPv6 records, when returned, will be actually tried
+ first which may typically lead to long timeouts.
+
+ The third case is a bit more complex: optimizing away the DNS lookups
+ with only link-locals is probably safe (but may be desirable with
+ different lookup services which getaddrinfo() may support), as the
+ link-locals are typically automatically generated when IPv6 is
+ enabled, and do not indicate any form of IPv6 connectivity. That is,
+ performing DNS lookups only when a non-link-local address has been
+ configured on any interface could be beneficial -- this would be an
+ indication that either the address has been configured either from a
+ router advertisement, DHCPv6 [RFC3315], or manually. Each would
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 12]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ indicate at least some form of IPv6 connectivity, even though there
+ would not be guarantees of it.
+
+ These issues should be analyzed at more depth, and the fixes found
+ consensus on, perhaps in a separate document.
+
+5.2 Obtaining a List of DNS Recursive Resolvers
+
+ In scenarios where DHCPv6 is available, a host can discover a list of
+ DNS recursive resolvers through DHCPv6 "DNS Recursive Name Server"
+ option [RFC3646]. This option can be passed to a host through a
+ subset of DHCPv6 [RFC3736].
+
+ The IETF is considering the development of alternative mechanisms for
+ obtaining the list of DNS recursive name servers when DHCPv6 is
+ unavailable or inappropriate. No decision about taking on this
+ development work has been reached as of this writing (Aug 2004)
+ [I-D.ietf-dnsop-ipv6-dns-configuration].
+
+ In scenarios where DHCPv6 is unavailable or inappropriate, mechanisms
+ under consideration for development include the use of well-known
+ addresses [I-D.ohta-preconfigured-dns] and the use of Router
+ Advertisements to convey the information [I-D.jeong-dnsop-ipv6-dns-
+ discovery].
+
+ Note that even though IPv6 DNS resolver discovery is a recommended
+ procedure, it is not required for dual-stack nodes in dual-stack
+ networks as IPv6 DNS records can be queried over IPv4 as well as
+ IPv6. Obviously, nodes which are meant to function without manual
+ configuration in IPv6-only networks must implement the DNS resolver
+ discovery function.
+
+5.3 IPv6 Transport Guidelines for Resolvers
+
+ As described in Section 1.3 and [RFC3901], the recursive resolvers
+ should be IPv4-only or dual-stack to be able to reach any IPv4-only
+ DNS server. Note that this requirement is also fulfilled by an IPv6-
+ only stub resolver pointing to a dual-stack recursive DNS resolver.
+
+6. Considerations about Forward DNS Updating
+
+ While the topic of how to enable updating the forward DNS, i.e., the
+ mapping from names to the correct new addresses, is not specific to
+ IPv6, it should be considered especially due to the advent of
+ Stateless Address Autoconfiguration [RFC2462].
+
+ Typically forward DNS updates are more manageable than doing them in
+ the reverse DNS, because the updater can often be assumed to "own" a
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 13]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ certain DNS name -- and we can create a form of security relationship
+ with the DNS name and the node which is allowed to update it to point
+ to a new address.
+
+ A more complex form of DNS updates -- adding a whole new name into a
+ DNS zone, instead of updating an existing name -- is considered out
+ of scope for this memo as it could require zone-wide authentication.
+ Adding a new name in the forward zone is a problem which is still
+ being explored with IPv4, and IPv6 does not seem to add much new in
+ that area.
+
+6.1 Manual or Custom DNS Updates
+
+ The DNS mappings can also be maintained by hand, in a semi-automatic
+ fashion or by running non-standardized protocols. These are not
+ considered at more length in this memo.
+
+6.2 Dynamic DNS
+
+ Dynamic DNS updates (DDNS) [RFC2136] [RFC3007] is a standardized
+ mechanism for dynamically updating the DNS. It works equally well
+ with stateless address autoconfiguration (SLAAC), DHCPv6 or manual
+ address configuration. It is important to consider how each of these
+ behave if IP address-based authentication, instead of stronger
+ mechanisms [RFC3007], was used in the updates.
+
+ 1. manual addresses are static and can be configured
+
+ 2. DHCPv6 addresses could be reasonably static or dynamic, depending
+ on the deployment, and could or could not be configured on the
+ DNS server for the long term
+
+ 3. SLAAC addresses are typically stable for a long time, but could
+ require work to be configured and maintained.
+
+ As relying on IP addresses for Dynamic DNS is rather insecure at
+ best, stronger authentication should always be used; however, this
+ requires that the authorization keying will be explicitly configured
+ using unspecified operational methods.
+
+ Note that with DHCP it is also possible that the DHCP server updates
+ the DNS, not the host. The host might only indicate in the DHCP
+ exchange which hostname it would prefer, and the DHCP server would
+ make the appropriate updates. Nonetheless, while this makes setting
+ up a secure channel between the updater and the DNS server easier, it
+ does not help much with "content" security, i.e., whether the
+ hostname was acceptable -- if the DNS server does not include
+ policies, they must be included in the DHCP server (e.g., a regular
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 14]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ host should not be able to state that its name is "www.example.com").
+ DHCP-initiated DDNS updates have been extensively described in
+ [I-D.ietf-dhc-ddns-resolution], [I-D.ietf-dhc-fqdn-option] and
+ [I-D.ietf-dnsext-dhcid-rr].
+
+ The nodes must somehow be configured with the information about the
+ servers where they will attempt to update their addresses, sufficient
+ security material for authenticating themselves to the server, and
+ the hostname they will be updating. Unless otherwise configured, the
+ first could be obtained by looking up the authoritative name servers
+ for the hostname; the second must be configured explicitly unless one
+ chooses to trust the IP address-based authentication (not a good
+ idea); and lastly, the nodename is typically pre-configured somehow
+ on the node, e.g., at install time.
+
+ Care should be observed when updating the addresses not to use longer
+ TTLs for addresses than are preferred lifetimes for the addresses, so
+ that if the node is renumbered in a managed fashion, the amount of
+ stale DNS information is kept to the minimum. That is, if the
+ preferred lifetime of an address expires, the TTL of the record needs
+ be modified unless it was already done before the expiration. For
+ better flexibility, the DNS TTL should be much shorter (e.g., a half
+ or a third) than the lifetime of an address; that way, the node can
+ start lowering the DNS TTL if it seems like the address has not been
+ renewed/refreshed in a while. Some discussion on how an
+ administrator could manage the DNS TTL is included in [I-D.ietf-
+ v6ops-renumbering-procedure]; this could be applied to (smart) hosts
+ as well.
+
+7. Considerations about Reverse DNS Updating
+
+ Updating the reverse DNS zone may be difficult because of the split
+ authority over an address. However, first we have to consider the
+ applicability of reverse DNS in the first place.
+
+7.1 Applicability of Reverse DNS
+
+ Today, some applications use reverse DNS to either look up some hints
+ about the topological information associated with an address (e.g.
+ resolving web server access logs), or as a weak form of a security
+ check, to get a feel whether the user's network administrator has
+ "authorized" the use of the address (on the premises that adding a
+ reverse record for an address would signal some form of
+ authorization).
+
+ One additional, maybe slightly more useful usage is ensuring that the
+ reverse and forward DNS contents match (by looking up the pointer to
+ the name by the IP address from the reverse tree, and ensuring that a
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 15]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ record under the name in the forward tree points to the IP address)
+ and correspond to a configured name or domain. As a security check,
+ it is typically accompanied by other mechanisms, such as a user/
+ password login; the main purpose of the reverse+forward DNS check is
+ to weed out the majority of unauthorized users, and if someone
+ managed to bypass the checks, he would still need to authenticate
+ "properly".
+
+ It may also be desirable to store IPsec keying material corresponding
+ to an IP address in the reverse DNS, as justified and described in
+ [RFC4025].
+
+ It is not clear whether it makes sense to require or recommend that
+ reverse DNS records be updated. In many cases, it would just make
+ more sense to use proper mechanisms for security (or topological
+ information lookup) in the first place. At minimum, the applications
+ which use it as a generic authorization (in the sense that a record
+ exists at all) should be modified as soon as possible to avoid such
+ lookups completely.
+
+ The applicability is discussed at more length in [I-D.ietf-dnsop-
+ inaddr-required].
+
+7.2 Manual or Custom DNS Updates
+
+ Reverse DNS can of course be updated using manual or custom methods.
+ These are not further described here, except for one special case.
+
+ One way to deploy reverse DNS would be to use wildcard records, for
+ example, by configuring one name for a subnet (/64) or a site (/48).
+ As a concrete example, a site (or the site's ISP) could configure the
+ reverses of the prefix 2001:db8:f00::/48 to point to one name using a
+ wildcard record like "*.0.0.f.0.8.b.d.0.1.0.0.2.ip6.arpa. IN PTR
+ site.example.com." Naturally, such a name could not be verified from
+ the forward DNS, but would at least provide some form of "topological
+ information" or "weak authorization" if that is really considered to
+ be useful. Note that this is not actually updating the DNS as such,
+ as the whole point is to avoid DNS updates completely by manually
+ configuring a generic name.
+
+7.3 DDNS with Stateless Address Autoconfiguration
+
+ Dynamic reverse DNS with SLAAC is simpler than forward DNS updates in
+ some regard, while being more difficult in another, as described
+ below.
+
+ The address space administrator decides whether the hosts are trusted
+ to update their reverse DNS records or not. If they are trusted and
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 16]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ deployed at the same site (e.g., not across the Internet), a simple
+ address-based authorization is typically sufficient (i.e., check that
+ the DNS update is done from the same IP address as the record being
+ updated); stronger security can also be used [RFC3007]. If they
+ aren't allowed to update the reverses, no update can occur. However,
+ such address-based update authorization operationally requires that
+ ingress filtering [RFC3704] has been set up at the border of the site
+ where the updates occur, and as close to the updater as possible.
+
+ Address-based authorization is simpler with reverse DNS (as there is
+ a connection between the record and the address) than with forward
+ DNS. However, when a stronger form of security is used, forward DNS
+ updates are simpler to manage because the host can be assumed to have
+ an association with the domain. Note that the user may roam to
+ different networks, and does not necessarily have any association
+ with the owner of that address space -- so, assuming stronger form of
+ authorization for reverse DNS updates than an address association is
+ generally infeasible.
+
+ Moreover, the reverse zones must be cleaned up by an unspecified
+ janitorial process: the node does not typically know a priori that it
+ will be disconnected, and cannot send a DNS update using the correct
+ source address to remove a record.
+
+ A problem with defining the clean-up process is that it is difficult
+ to ensure that a specific IP address and the corresponding record are
+ no longer being used. Considering the huge address space, and the
+ unlikelihood of collision within 64 bits of the interface
+ identifiers, a process which would remove the record after no traffic
+ has been seen from a node in a long period of time (e.g., a month or
+ year) might be one possible approach.
+
+ To insert or update the record, the node must discover the DNS server
+ to send the update to somehow, similar to as discussed in
+ Section 6.2. One way to automate this is looking up the DNS server
+ authoritative (e.g., through SOA record) for the IP address being
+ updated, but the security material (unless the IP address-based
+ authorization is trusted) must also be established by some other
+ means.
+
+ One should note that Cryptographically Generated Addresses [RFC3972]
+ (CGAs) may require a slightly different kind of treatment. CGAs are
+ addresses where the interface identifier is calculated from a public
+ key, a modifier (used as a nonce), the subnet prefix, and other data.
+ Depending on the usage profile, CGAs might or might not be changed
+ periodically due to e.g., privacy reasons. As the CGA address is not
+ predicatable, a reverse record can only reasonably be inserted in the
+ DNS by the node which generates the address.
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 17]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+7.4 DDNS with DHCP
+
+ With DHCPv4, the reverse DNS name is typically already inserted to
+ the DNS that reflects to the name (e.g., "dhcp-67.example.com"). One
+ can assume similar practice may become commonplace with DHCPv6 as
+ well; all such mappings would be pre-configured, and would require no
+ updating.
+
+ If a more explicit control is required, similar considerations as
+ with SLAAC apply, except for the fact that typically one must update
+ a reverse DNS record instead of inserting one (if an address
+ assignment policy that reassigns disused addresses is adopted) and
+ updating a record seems like a slightly more difficult thing to
+ secure. However, it is yet uncertain how DHCPv6 is going to be used
+ for address assignment.
+
+ Note that when using DHCP, either the host or the DHCP server could
+ perform the DNS updates; see the implications in Section 6.2.
+
+ If disused addresses were to be reassigned, host-based DDNS reverse
+ updates would need policy considerations for DNS record modification,
+ as noted above. On the other hand, if disused address were not to be
+ assigned, host-based DNS reverse updates would have similar
+ considerations as SLAAC in Section 7.3. Server-based updates have
+ similar properties except that the janitorial process could be
+ integrated with DHCP address assignment.
+
+7.5 DDNS with Dynamic Prefix Delegation
+
+ In cases where a prefix, instead of an address, is being used and
+ updated, one should consider what is the location of the server where
+ DDNS updates are made. That is, where the DNS server is located:
+
+ 1. At the same organization as the prefix delegator.
+
+ 2. At the site where the prefixes are delegated to. In this case,
+ the authority of the DNS reverse zone corresponding to the
+ delegated prefix is also delegated to the site.
+
+ 3. Elsewhere; this implies a relationship between the site and where
+ DNS server is located, and such a relationship should be rather
+ straightforward to secure as well. Like in the previous case,
+ the authority of the DNS reverse zone is also delegated.
+
+ In the first case, managing the reverse DNS (delegation) is simpler
+ as the DNS server and the prefix delegator are in the same
+ administrative domain (as there is no need to delegate anything at
+ all); alternatively, the prefix delegator might forgo DDNS reverse
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 18]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ capability altogether, and use e.g., wildcard records (as described
+ in Section 7.2). In the other cases, it can be slighly more
+ difficult, particularly as the site will have to configure the DNS
+ server to be authoritative for the delegated reverse zone, implying
+ automatic configuration of the DNS server -- as the prefix may be
+ dynamic.
+
+ Managing the DDNS reverse updates is typically simple in the second
+ case, as the updated server is located at the local site, and
+ arguably IP address-based authentication could be sufficient (or if
+ not, setting up security relationships would be simpler). As there
+ is an explicit (security) relationship between the parties in the
+ third case, setting up the security relationships to allow reverse
+ DDNS updates should be rather straightforward as well (but IP
+ address-based authentication might not be acceptable). In the first
+ case, however, setting up and managing such relationships might be a
+ lot more difficult.
+
+8. Miscellaneous DNS Considerations
+
+ This section describes miscellaneous considerations about DNS which
+ seem related to IPv6, for which no better place has been found in
+ this document.
+
+8.1 NAT-PT with DNS-ALG
+
+ The DNS-ALG component of NAT-PT mangles A records to look like AAAA
+ records to the IPv6-only nodes. Numerous problems have been
+ identified with DNS-ALG [I-D.ietf-v6ops-natpt-to-exprmntl]. This is
+ a strong reason not to use NAT-PT in the first place.
+
+8.2 Renumbering Procedures and Applications' Use of DNS
+
+ One of the most difficult problems of systematic IP address
+ renumbering procedures [I-D.ietf-v6ops-renumbering-procedure] is that
+ an application which looks up a DNS name disregards information such
+ as TTL, and uses the result obtained from DNS as long as it happens
+ to be stored in the memory of the application. For applications
+ which run for a long time, this could be days, weeks or even months;
+ some applications may be clever enough to organize the data
+ structures and functions in such a manner that look-ups get refreshed
+ now and then.
+
+ While the issue appears to have a clear solution, "fix the
+ applications", practically this is not reasonable immediate advice;
+ the TTL information is not typically available in the APIs and
+ libraries (so, the advice becomes "fix the applications, APIs and
+ libraries"), and a lot more analysis is needed on how to practically
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 19]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ go about to achieve the ultimate goal of avoiding using the names
+ longer than expected.
+
+9. Acknowledgements
+
+ Some recommendations (Section 4.3, Section 5.1) about IPv6 service
+ provisioning were moved here from [I-D.ietf-v6ops-mech-v2] by Erik
+ Nordmark and Bob Gilligan. Havard Eidnes and Michael Patton provided
+ useful feedback and improvements. Scott Rose, Rob Austein, Masataka
+ Ohta, and Mark Andrews helped in clarifying the issues regarding
+ additional data and the use of TTL. Jefsey Morfin, Ralph Droms,
+ Peter Koch, Jinmei Tatuya, Iljitsch van Beijnum, Edward Lewis, and
+ Rob Austein provided useful feedback during the WG last call. Thomas
+ Narten provided extensive feedback during the IESG evaluation.
+
+10. Security Considerations
+
+ This document reviews the operational procedures for IPv6 DNS
+ operations and does not have security considerations in itself.
+
+ However, it is worth noting that in particular with Dynamic DNS
+ Updates, security models based on the source address validation are
+ very weak and cannot be recommended -- they could only be considered
+ in the environments where ingress filtering [RFC3704] has been
+ deployed. On the other hand, it should be noted that setting up an
+ authorization mechanism (e.g., a shared secret, or public-private
+ keys) between a node and the DNS server has to be done manually, and
+ may require quite a bit of time and expertise.
+
+ To re-emphasize what was already stated, the reverse+forward DNS
+ check provides very weak security at best, and the only
+ (questionable) security-related use for them may be in conjunction
+ with other mechanisms when authenticating a user.
+
+11. References
+
+11.1 Normative References
+
+ [I-D.ietf-dnsop-ipv6-dns-configuration]
+ Jeong, J., "IPv6 Host Configuration of DNS Server
+ Information Approaches",
+ draft-ietf-dnsop-ipv6-dns-configuration-06 (work in
+ progress), May 2005.
+
+ [I-D.ietf-ipv6-unique-local-addr]
+ Hinden, R. and B. Haberman, "Unique Local IPv6 Unicast
+ Addresses", draft-ietf-ipv6-unique-local-addr-09 (work in
+ progress), January 2005.
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 20]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ [I-D.ietf-v6ops-renumbering-procedure]
+ Baker, F., "Procedures for Renumbering an IPv6 Network
+ without a Flag Day",
+ draft-ietf-v6ops-renumbering-procedure-05 (work in
+ progress), March 2005.
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC2136] Vixie, P., Thomson, S., Rekhter, Y., and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)",
+ RFC 2136, April 1997.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC2182] Elz, R., Bush, R., Bradner, S., and M. Patton, "Selection
+ and Operation of Secondary DNS Servers", BCP 16, RFC 2182,
+ July 1997.
+
+ [RFC2462] Thomson, S. and T. Narten, "IPv6 Stateless Address
+ Autoconfiguration", RFC 2462, December 1998.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)",
+ RFC 2671, August 1999.
+
+ [RFC2821] Klensin, J., "Simple Mail Transfer Protocol", RFC 2821,
+ April 2001.
+
+ [RFC3007] Wellington, B., "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+ [RFC3041] Narten, T. and R. Draves, "Privacy Extensions for
+ Stateless Address Autoconfiguration in IPv6", RFC 3041,
+ January 2001.
+
+ [RFC3056] Carpenter, B. and K. Moore, "Connection of IPv6 Domains
+ via IPv4 Clouds", RFC 3056, February 2001.
+
+ [RFC3152] Bush, R., "Delegation of IP6.ARPA", BCP 49, RFC 3152,
+ August 2001.
+
+ [RFC3315] Droms, R., Bound, J., Volz, B., Lemon, T., Perkins, C.,
+ and M. Carney, "Dynamic Host Configuration Protocol for
+ IPv6 (DHCPv6)", RFC 3315, July 2003.
+
+ [RFC3363] Bush, R., Durand, A., Fink, B., Gudmundsson, O., and T.
+ Hain, "Representing Internet Protocol version 6 (IPv6)
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 21]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ Addresses in the Domain Name System (DNS)", RFC 3363,
+ August 2002.
+
+ [RFC3364] Austein, R., "Tradeoffs in Domain Name System (DNS)
+ Support for Internet Protocol version 6 (IPv6)", RFC 3364,
+ August 2002.
+
+ [RFC3513] Hinden, R. and S. Deering, "Internet Protocol Version 6
+ (IPv6) Addressing Architecture", RFC 3513, April 2003.
+
+ [RFC3596] Thomson, S., Huitema, C., Ksinant, V., and M. Souissi,
+ "DNS Extensions to Support IP Version 6", RFC 3596,
+ October 2003.
+
+ [RFC3646] Droms, R., "DNS Configuration options for Dynamic Host
+ Configuration Protocol for IPv6 (DHCPv6)", RFC 3646,
+ December 2003.
+
+ [RFC3736] Droms, R., "Stateless Dynamic Host Configuration Protocol
+ (DHCP) Service for IPv6", RFC 3736, April 2004.
+
+ [RFC3879] Huitema, C. and B. Carpenter, "Deprecating Site Local
+ Addresses", RFC 3879, September 2004.
+
+ [RFC3901] Durand, A. and J. Ihren, "DNS IPv6 Transport Operational
+ Guidelines", BCP 91, RFC 3901, September 2004.
+
+ [RFC4038] Shin, M-K., Hong, Y-G., Hagino, J., Savola, P., and E.
+ Castro, "Application Aspects of IPv6 Transition",
+ RFC 4038, March 2005.
+
+ [RFC4074] Morishita, Y. and T. Jinmei, "Common Misbehavior Against
+ DNS Queries for IPv6 Addresses", RFC 4074, May 2005.
+
+11.2 Informative References
+
+ [I-D.durand-dnsop-dont-publish]
+ Durand, A. and T. Chown, "To publish, or not to publish,
+ that is the question.", draft-durand-dnsop-dont-publish-00
+ (work in progress), February 2005.
+
+ [I-D.huitema-v6ops-teredo]
+ Huitema, C., "Teredo: Tunneling IPv6 over UDP through
+ NATs", draft-huitema-v6ops-teredo-05 (work in progress),
+ April 2005.
+
+ [I-D.huston-6to4-reverse-dns]
+ Huston, G., "6to4 Reverse DNS Delegation",
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 22]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ draft-huston-6to4-reverse-dns-03 (work in progress),
+ October 2004.
+
+ [I-D.ietf-dhc-ddns-resolution]
+ Stapp, M. and B. Volz, "Resolution of FQDN Conflicts among
+ DHCP Clients", draft-ietf-dhc-ddns-resolution-09 (work in
+ progress), June 2005.
+
+ [I-D.ietf-dhc-fqdn-option]
+ Stapp, M. and Y. Rekhter, "The DHCP Client FQDN Option",
+ draft-ietf-dhc-fqdn-option-10 (work in progress),
+ February 2005.
+
+ [I-D.ietf-dnsext-dhcid-rr]
+ Stapp, M., Lemon, T., and A. Gustafsson, "A DNS RR for
+ encoding DHCP information (DHCID RR)",
+ draft-ietf-dnsext-dhcid-rr-09 (work in progress),
+ February 2005.
+
+ [I-D.ietf-dnsop-bad-dns-res]
+ Larson, M. and P. Barber, "Observed DNS Resolution
+ Misbehavior", draft-ietf-dnsop-bad-dns-res-03 (work in
+ progress), October 2004.
+
+ [I-D.ietf-dnsop-inaddr-required]
+ Senie, D., "Encouraging the use of DNS IN-ADDR Mapping",
+ draft-ietf-dnsop-inaddr-required-06 (work in progress),
+ February 2005.
+
+ [I-D.ietf-v6ops-3gpp-analysis]
+ Wiljakka, J., "Analysis on IPv6 Transition in 3GPP
+ Networks", draft-ietf-v6ops-3gpp-analysis-11 (work in
+ progress), October 2004.
+
+ [I-D.ietf-v6ops-mech-v2]
+ Nordmark, E. and R. Gilligan, "Basic Transition Mechanisms
+ for IPv6 Hosts and Routers", draft-ietf-v6ops-mech-v2-07
+ (work in progress), March 2005.
+
+ [I-D.ietf-v6ops-natpt-to-exprmntl]
+ Aoun, C. and E. Davies, "Reasons to Move NAT-PT to
+ Experimental", draft-ietf-v6ops-natpt-to-exprmntl-01 (work
+ in progress), July 2005.
+
+ [I-D.ietf-v6ops-onlinkassumption]
+ Roy, S., "IPv6 Neighbor Discovery On-Link Assumption
+ Considered Harmful", draft-ietf-v6ops-onlinkassumption-03
+ (work in progress), May 2005.
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 23]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ [I-D.ietf-v6ops-v6onbydefault]
+ Roy, S., Durand, A., and J. Paugh, "Issues with Dual Stack
+ IPv6 on by Default", draft-ietf-v6ops-v6onbydefault-03
+ (work in progress), July 2004.
+
+ [I-D.jeong-dnsop-ipv6-dns-discovery]
+ Jeong, J., "IPv6 DNS Configuration based on Router
+ Advertisement", draft-jeong-dnsop-ipv6-dns-discovery-04
+ (work in progress), February 2005.
+
+ [I-D.ohta-preconfigured-dns]
+ Ohta, M., "Preconfigured DNS Server Addresses",
+ draft-ohta-preconfigured-dns-01 (work in progress),
+ February 2004.
+
+ [RFC2766] Tsirtsis, G. and P. Srisuresh, "Network Address
+ Translation - Protocol Translation (NAT-PT)", RFC 2766,
+ February 2000.
+
+ [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for
+ specifying the location of services (DNS SRV)", RFC 2782,
+ February 2000.
+
+ [RFC2826] Internet Architecture Board, "IAB Technical Comment on the
+ Unique DNS Root", RFC 2826, May 2000.
+
+ [RFC3704] Baker, F. and P. Savola, "Ingress Filtering for Multihomed
+ Networks", BCP 84, RFC 3704, March 2004.
+
+ [RFC3972] Aura, T., "Cryptographically Generated Addresses (CGA)",
+ RFC 3972, March 2005.
+
+ [RFC4025] Richardson, M., "A Method for Storing IPsec Keying
+ Material in DNS", RFC 4025, March 2005.
+
+
+Authors' Addresses
+
+ Alain Durand
+ SUN Microsystems, Inc.
+ 17 Network circle UMPL17-202
+ Menlo Park, CA 94025
+ USA
+
+ Email: Alain.Durand@sun.com
+
+
+
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 24]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ Johan Ihren
+ Autonomica
+ Bellmansgatan 30
+ SE-118 47 Stockholm
+ Sweden
+
+ Email: johani@autonomica.se
+
+
+ Pekka Savola
+ CSC/FUNET
+ Espoo
+ Finland
+
+ Email: psavola@funet.fi
+
+Appendix A. Unique Local Addressing Considerations for DNS
+
+ Unique local addresses [I-D.ietf-ipv6-unique-local-addr] have
+ replaced the now-deprecated site-local addresses [RFC3879]. From the
+ perspective of the DNS, the locally generated unique local addresses
+ (LUL) and site-local addresses have similar properties.
+
+ The interactions with DNS come in two flavors: forward and reverse
+ DNS.
+
+ To actually use local addresses within a site, this implies the
+ deployment of a "split-faced" or a fragmented DNS name space, for the
+ zones internal to the site, and the outsiders' view to it. The
+ procedures to achieve this are not elaborated here. The implication
+ is that local addresses must not be published in the public DNS.
+
+ To faciliate reverse DNS (if desired) with local addresses, the stub
+ resolvers must look for DNS information from the local DNS servers,
+ not e.g. starting from the root servers, so that the local
+ information may be provided locally. Note that the experience of
+ private addresses in IPv4 has shown that the root servers get loaded
+ for requests for private address lookups in any case. This
+ requirement is discussed in [I-D.ietf-ipv6-unique-local-addr].
+
+Appendix B. Behaviour of Additional Data in IPv4/IPv6 Environments
+
+ DNS responses do not always fit in a single UDP packet. We'll
+ examine the cases which happen when this is due to too much data in
+ the Additional Section.
+
+
+
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 25]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+B.1 Description of Additional Data Scenarios
+
+ There are two kinds of additional data:
+
+ 1. "critical" additional data; this must be included in all
+ scenarios, with all the RRsets, and
+
+ 2. "courtesy" additional data; this could be sent in full, with only
+ a few RRsets, or with no RRsets, and can be fetched separately as
+ well, but at the cost of additional queries.
+
+ The responding server can algorithmically determine which type the
+ additional data is by checking whether it's at or below a zone cut.
+
+ Only those additional data records (even if sometimes carelessly
+ termed "glue") are considered "critical" or real "glue" if and only
+ if they meet the abovementioned condition, as specified in Section
+ 4.2.1 of [RFC1034].
+
+ Remember that resource record sets (RRsets) are never "broken up", so
+ if a name has 4 A records and 5 AAAA records, you can either return
+ all 9, all 4 A records, all 5 AAAA records or nothing. In
+ particular, notice that for the "critical" additional data getting
+ all the RRsets can be critical.
+
+ In particular, [RFC2181] specifies (in Section 9) that:
+
+ a. if all the "critical" RRsets do not fit, the sender should set
+ the TC bit, and the recipient should discard the whole response
+ and retry using mechanism allowing larger responses such as TCP.
+
+ b. "courtesy" additional data should not cause the setting of TC
+ bit, but instead all the non-fitting additional data RRsets
+ should be removed.
+
+ An example of the "courtesy" additional data is A/AAAA records in
+ conjunction with MX records as shown in Section 4.4; an example of
+ the "critical" additional data is shown below (where getting both the
+ A and AAAA RRsets is critical w.r.t. to the NS RR):
+
+ child.example.com. IN NS ns.child.example.com.
+ ns.child.example.com. IN A 192.0.2.1
+ ns.child.example.com. IN AAAA 2001:db8::1
+
+ When there is too much "courtesy" additional data, at least the non-
+ fitting RRsets should be removed [RFC2181]; however, as the
+ additional data is not critical, even all of it could be safely
+ removed.
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 26]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ When there is too much "critical" additional data, TC bit will have
+ to be set, and the recipient should ignore the response and retry
+ using TCP; if some data were to be left in the UDP response, the
+ issue is which data could be retained.
+
+ Failing to discard the response with TC bit or omitting critical
+ information but not setting TC bit lead to an unrecoverable problem.
+ Omitting only some of the RRsets if all would not fit (but not
+ setting TC bit) leads to a performance problem. These are discussed
+ in the next two subsections.
+
+B.2 Which Additional Data to Keep, If Any?
+
+ If the implementation decides to keep as much data (whether
+ "critical" or "courtesy") as possible in the UDP responses, it might
+ be tempting to use the transport of the DNS query as a hint in either
+ of these cases: return the AAAA records if the query was done over
+ IPv6, or return the A records if the query was done over IPv4.
+ However, this breaks the model of independence of DNS transport and
+ resource records, as noted in Section 1.2.
+
+ With courtesy additional data, as long as enough RRsets will be
+ removed so that TC will not be set, it is allowed to send as many
+ complete RRsets as the implementations prefers. However, the
+ implementations are also free to omit all such RRsets, even if
+ complete. Omitting all the RRsets (when removing only some would
+ suffice) may create a performance penalty, whereby the client may
+ need to issue one or more additional queries to obtain necessary
+ and/or consistent information.
+
+ With critical additional data, the alternatives are either returning
+ nothing (and absolutely requiring a retry with TCP) or returning
+ something (working also in the case if the recipient does not discard
+ the response and retry using TCP) in addition to setting the TC bit.
+ If the process for selecting "something" from the critical data would
+ otherwise be practically "flipping the coin" between A and AAAA
+ records, it could be argued that if one looked at the transport of
+ the query, it would have a larger possibility of being right than
+ just 50/50. In other words, if the returned critical additional data
+ would have to be selected somehow, using something more sophisticated
+ than a random process would seem justifiable.
+
+ That is, leaving in some intelligently selected critical additional
+ data is a tradeoff between creating an optimization for those
+ resolvers which ignore the "should discard" recommendation, and
+ causing a protocol problem by propagating inconsistent information
+ about "critical" records in the caches.
+
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 27]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ Similarly, leaving in the complete courtesy additional data RRsets
+ instead of removing all the RRsets is a performance tradeoff as
+ described in the next section.
+
+B.3 Discussion of the Potential Problems
+
+ As noted above, the temptation for omitting only some of the
+ additional data could be problematic. This is discussed more below.
+
+ For courtesy additional data, this causes a potential performance
+ problem as this requires that the clients issue re-queries for the
+ potentially omitted RRsets. For critical additional data, this
+ causes a potential unrecoverable problem if the response is not
+ discarded and the query not re-tried with TCP, as the nameservers
+ might be reachable only through the omitted RRsets.
+
+ If an implementation would look at the transport used for the query,
+ it is worth remembering that often the host using the records is
+ different from the node requesting them from the authoritative DNS
+ server (or even a caching resolver). So, whichever version the
+ requestor (e.g., a recursive server in the middle) uses makes no
+ difference to the ultimate user of the records, whose transport
+ capabilities might differ from those of the requestor. This might
+ result in e.g., inappropriately returning A records to an IPv6-only
+ node, going through a translation, or opening up another IP-level
+ session (e.g., a PDP context [I-D.ietf-v6ops-3gpp-analysis]).
+ Therefore, at least in many scenarios, it would be very useful if the
+ information returned would be consistent and complete -- or if that
+ is not feasible, return no misleading information but rather leave it
+ to the client to query again.
+
+ The problem of too much additional data seems to be an operational
+ one: the zone administrator entering too many records which will be
+ returned either truncated (or missing some RRsets, depending on
+ implementations) to the users. A protocol fix for this is using
+ EDNS0 [RFC2671] to signal the capacity for larger UDP packet sizes,
+ pushing up the relevant threshold. Further, DNS server
+ implementations should rather omit courtesy additional data
+ completely rather than including only some RRsets [RFC2181]. An
+ operational fix for this is having the DNS server implementations
+ return a warning when the administrators create zones which would
+ result in too much additional data being returned. Further, DNS
+ server implementations should warn of or disallow such zone
+ configurations which are recursive or otherwise difficult to manage
+ by the protocol.
+
+ Additionally, to avoid the case where an application would not get an
+ address at all due to some of courtesy additional data being omitted,
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 28]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+ the resolvers should be able to query the specific records of the
+ desired protocol, not just rely on getting all the required RRsets in
+ the additional section.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 29]
+
+Internet-Draft Considerations with IPv6 DNS July 2005
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2005). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Durand, et al. Expires January 17, 2006 [Page 30]
+
+
diff --git a/doc/draft/draft-ietf-dnsop-ipv6-transport-guidelines-01.txt b/doc/draft/draft-ietf-dnsop-ipv6-transport-guidelines-01.txt
new file mode 100644
index 0000000..b2e2341
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsop-ipv6-transport-guidelines-01.txt
@@ -0,0 +1,300 @@
+Internet Engineering Task Force A.Durand
+INTERNET-DRAFT SUN Microsystems,inc.
+November, 24, 2003 J. Ihren
+Expires May 25, 2004 Autonomica
+
+
+ DNS IPv6 transport operational guidelines
+ <draft-ietf-dnsop-ipv6-transport-guidelines-01.txt>
+
+
+
+Status of this Memo
+
+ This memo provides information to the Internet community. It does not
+ specify an Internet standard of any kind. This memo is in full
+ conformance with all provisions of Section 10 of RFC2026
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet- Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/1id-abstracts.html
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html
+
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+
+Abstract
+
+ This memo provides guidelines and Best Current Practice to operate
+ DNS in a world where queries and responses are carried in a mixed
+ environment of IPv4 and IPv6 networks.
+
+
+Acknowledgment
+
+ This document is the result of many conversations that happened in
+ the DNS community at IETF and elsewhere since 2001. During that
+ period of time, a number of Internet drafts have been published to
+ clarify various aspects of the issues at stake. This document focuses
+ on the conclusion of those discussions.
+
+ The authors would like to acknowledge the role of Pekka Savola in his
+ thorough review of the document.
+
+
+1. Terminology
+
+ The phrase "IPv4 name server" indicates a name server available over
+ IPv4 transport. It does not imply anything about what DNS data is
+ served. Likewise, "IPv6 name server" indicates a name server
+ available over IPv6 transport. The phrase "dual-stack DNS server"
+ indicates a DNS server that is actually configured to run both
+ protocols, IPv4 and IPv6, and not merely a server running on a system
+ capable of running both but actually configured to run only one.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [2119].
+
+
+2. Introduction to the Problem of Name Space Fragmentation:
+ following the referral chain
+
+ The caching resolver that tries to look up a name starts out at the
+ root, and follows referrals until it is referred to a nameserver that
+ is authoritative for the name. If somewhere down the chain of
+ referrals it is referred to a nameserver that is only accessible over
+ an unavailable type of transport, a traditional nameserver is unable
+ to finish the task.
+
+ When the Internet moves from IPv4 to a mixture of IPv4 and IPv6 it is
+ only a matter of time until this starts to happen. The complete DNS
+ hierarchy then starts to fragment into a graph where authoritative
+ nameservers for certain nodes are only accessible over a certain
+ transport. What is feared is that a node using only a particular
+ version of IP, querying information about another node using the same
+ version of IP can not do it because, somewhere in the chain of
+ servers accessed during the resolution process, one or more of them
+ will only be accessible with the other version of IP.
+
+ With all DNS data only available over IPv4 transport everything is
+ simple. IPv4 resolvers can use the intended mechanism of following
+ referrals from the root and down while IPv6 resolvers have to work
+ through a "translator", i.e. they have to use a second name server on
+ a so-called "dual stack" host as a "forwarder" since they cannot
+ access the DNS data directly.
+
+ With all DNS data only available over IPv6 transport everything would
+ be equally simple, with the exception of old legacy IPv4 name servers
+ having to switch to a forwarding configuration.
+
+ However, the second situation will not arise in a foreseeable time.
+ Instead, it is expected that the transition will be from IPv4 only to
+ a mixture of IPv4 and IPv6, with DNS data of theoretically three
+ categories depending on whether it is available only over IPv4
+ transport, only over IPv6 or both.
+
+ Having DNS data available on both transports is the best situation.
+ The major question is how to ensure that it as quickly as possible
+ becomes the norm. However, while it is obvious that some DNS data
+ will only be available over v4 transport for a long time it is also
+ obvious that it is important to avoid fragmenting the name space
+ available to IPv4 only hosts. I.e. during transition it is not
+ acceptable to break the name space that we presently have available
+ for IPv4-only hosts.
+
+
+3. Policy Based Avoidance of Name Space Fragmentation
+
+ Today there are only a few DNS "zones" on the public Internet that
+ are available over IPv6 transport, and most of them can be regarded
+ as "experimental". However, as soon as the root and top level domains
+ are available over IPv6 transport, it is reasonable to expect that it
+ will become more common to have zones served by IPv6 servers.
+
+ Having those zones served only by IPv6-only name server would not be
+ a good development, since this will fragment the previously
+ unfragmented IPv4 name space and there are strong reasons to find a
+ mechanism to avoid it.
+
+ The RECOMMENDED approach to maintain name space continuity is to use
+ administrative policies, as described in the next section.
+
+
+4. DNS IPv6 Transport RECOMMENDED Guidelines
+
+ In order to preserve name space continuity, the following administrative
+ policies are RECOMMENDED:
+ - every recursive DNS server SHOULD be either IPv4-only or dual
+ stack,
+ - every single DNS zone SHOULD be served by at least one IPv4
+ reachable DNS server.
+
+ This rules out IPv6-only DNS servers performing full recursion and
+ DNS zones served only by IPv6-only DNS servers. However, one could
+ very well design a configuration where a chain of IPv6 only DNS
+ servers forward queries to a set of dual stack DNS servers actually
+ performing those recursive queries. This approach could be revisited
+ if/when translation techniques between IPv4 and IPv6 were to be
+ widely deployed.
+
+ In order to help enforcing the second point, the optional operational
+ zone validation processes SHOULD ensure that there is at least one
+ IPv4 address record available for the name servers of any child
+ delegations within the zone.
+
+
+5. Security Considerations
+
+ Being a critical piece of the Internet infrastructure, the DNS is a
+ potential value target and thus should be protected. Great care
+ should be taken not to weaken the security of DNS while introducing
+ IPv6 operation.
+
+ Keeping the DNS name space from fragmenting is a critical thing for
+ the availability and the operation of the Internet; this memo
+ addresses this issue by clear and simple operational guidelines.
+
+ The RECOMMENDED guidelines are compatible with the operation of
+ DNSSEC and do not introduce any new security issues.
+
+
+6. Author Addresses
+
+ Alain Durand
+ SUN Microsystems, Inc
+ 17 Network circle UMPK17-202
+ Menlo Park, CA, 94025
+ USA
+ Mail: Alain.Durand@sun.com
+
+ Johan Ihren
+ Autonomica
+ Bellmansgatan 30
+ SE-118 47 Stockholm, Sweden
+ Mail: johani@autonomica.se
+
+
+7. Normative References
+
+ [2119] Bradner, S., "Key Words for Use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+
+8. Full Copyright Statement
+
+ "Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/draft/draft-ietf-dnsop-key-rollover-requirements-02.txt b/doc/draft/draft-ietf-dnsop-key-rollover-requirements-02.txt
new file mode 100644
index 0000000..6bece56
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsop-key-rollover-requirements-02.txt
@@ -0,0 +1,389 @@
+
+DNSOP G. Guette
+Internet-Draft IRISA / INRIA
+Expires: July 19, 2005 O. Courtay
+ Thomson R&D
+ January 18, 2005
+
+ Requirements for Automated Key Rollover in DNSSEC
+ draft-ietf-dnsop-key-rollover-requirements-02.txt
+
+Status of this Memo
+
+ By submitting this Internet-Draft, I certify that any applicable
+ patent or other IPR claims of which I am aware have been disclosed,
+ and any of which I become aware will be disclosed, in accordance with
+ RFC 3668.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as
+ Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on July 19, 2005.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005). All Rights Reserved.
+
+Abstract
+
+ This document describes problems that appear during an automated
+ rollover and gives the requirements for the design of communication
+ between parent zone and child zone during an automated rollover
+ process. This document is essentially about in-band key rollover.
+
+
+
+
+Guette & Courtay Expires July 19, 2005 [Page 1]
+Internet-Draft Automated Rollover Requirements January 2005
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. The Key Rollover Process . . . . . . . . . . . . . . . . . . . 3
+ 3. Basic Requirements . . . . . . . . . . . . . . . . . . . . . . 4
+ 4. Messages authentication and information exchanged . . . . . . 5
+ 5. Emergency Rollover . . . . . . . . . . . . . . . . . . . . . . 5
+ 6. Security consideration . . . . . . . . . . . . . . . . . . . . 6
+ 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 6
+ 8. Normative References . . . . . . . . . . . . . . . . . . . . . 6
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 7
+ A. Documents details and changes . . . . . . . . . . . . . . . . 7
+ Intellectual Property and Copyright Statements . . . . . . . . 8
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Guette & Courtay Expires July 19, 2005 [Page 2]
+Internet-Draft Automated Rollover Requirements January 2005
+
+1. Introduction
+
+ The DNS security extensions (DNSSEC) [4][6][5][7] uses public-key
+ cryptography and digital signatures. It stores the public part of
+ keys in DNSKEY Resource Records (RRs). Because old keys and
+ frequently used keys are vulnerable, they must be renewed
+ periodically. In DNSSEC, this is the case for Zone Signing Keys
+ (ZSKs) and Key Signing Keys (KSKs) [1][2]. Automation of key
+ exchanges between parents and children is necessary for large zones
+ because there are too many changes to handle.
+
+ Let us consider for example a zone with 100000 secure delegations.
+ If the child zones change their keys once a year on average, that
+ implies 300 changes per day for the parent zone. This amount of
+ changes is hard to manage manually.
+
+ Automated rollover is optional and resulting from an agreement
+ between the administrator of the parent zone and the administrator of
+ the child zone. Of course, key rollover can also be done manually by
+ administrators.
+
+ This document describes the requirements for a protocol to perform
+ the automated key rollover process and focusses on interaction
+ between parent and child zone.
+
+2. The Key Rollover Process
+
+ Key rollover consists of renewing the DNSSEC keys used to sign
+ resource records in a given DNS zone file. There are two types of
+ rollover, ZSK rollovers and KSK rollovers.
+
+ During a ZSK rollover, all changes are local to the zone that renews
+ its key: there is no need to contact other zones administrators to
+ propagate the performed changes because a ZSK has no associated DS
+ record in the parent zone.
+
+ During a KSK rollover, new DS RR(s) must be created and stored in the
+ parent zone. In consequence, data must be exchanged between child
+ and parent zones.
+
+ The key rollover is built from two parts of different nature:
+ o An algorithm that generates new keys and signs the zone file. It
+ can be local to the zone,
+ o the interaction between parent and child zones.
+
+ One example of manual key rollover [3] is:
+ o The child zone creates a new KSK,
+
+
+Guette & Courtay Expires July 19, 2005 [Page 3]
+Internet-Draft Automated Rollover Requirements January 2005
+
+ o the child zone waits for the creation of the DS RR in its parent
+ zone,
+ o the child zone deletes the old key,
+ o the parent zone deletes the old DS RR.
+
+ This document concentrates on defining interactions between entities
+ present in key rollover process.
+
+3. Basic Requirements
+
+ This section provides the requirements for automated key rollover in
+ case of normal use. Exceptional case like emergency rollover is
+ specifically described later in this document.
+
+ The main condition during a key rollover is that the chain of trust
+ must be preserved to every validating DNS client. No matter if this
+ client retrieves some of the RRs from recursive caching name server
+ or from the authoritative servers for the zone involved in the
+ rollover.
+
+ Automated key rollover solution may be interrupted by a manual
+ intervention. This manual intervention should not compromise the
+ security state of the chain of trust. If the chain is safe before
+ the manual intervention, the chain of trust must remain safe during
+ and after the manual intervention
+
+ Two entities act during a KSK rollover: the child zone and its parent
+ zone. These zones are generally managed by different administrators.
+ These administrators should agree on some parameters like
+ availability of automated rollover, the maximum delay between
+ notification of changes in the child zone and the resigning of the
+ parent zone. The child zone needs to know this delay to schedule its
+ changes and/or to verify that the changes had been taken into account
+ in the parent zone. Hence, the child zone can also avoid some
+ critical cases where all child key are changed prior to the DS RR
+ creation.
+
+ By keeping some resource records during a given time, the recursive
+ cache servers can act on the automated rollover. The existence of
+ recursive cache servers must be taken into account by automated
+ rollover solution.
+
+ Indeed, during an automated key rollover a name server could have to
+ retrieve some DNSSEC data. An automated key rollover solution must
+ ensure that these data are not old DNSSEC material retrieved from a
+ recursive name server.
+
+
+
+Guette & Courtay Expires July 19, 2005 [Page 4]
+Internet-Draft Automated Rollover Requirements January 2005
+
+4. Messages authentication and information exchanged
+
+ This section addresses in-band rollover, security of out-of-band
+ mechanisms is out of scope of this document.
+
+ The security provided by DNSSEC must not be compromised by the key
+ rollover, thus every exchanged message must be authenticated to avoid
+ fake rollover messages from malicious parties.
+
+ Once the changes related to a KSK are made in a child zone, there are
+ two ways for the parent zone to take this changes into account:
+ o the child zone notify directly or not directly its parent zone in
+ order to create the new DS RR and store this DS RR in parent zone
+ file,
+ o or the parent zone poll the child zone.
+
+ In both cases, the parent zone must receive all the child keys that
+ need the creation of associated DS RRs in the parent zone.
+
+ Because errors could occur during the transmission of keys between
+ child and parent, the key exchange protocol must be fault tolerant.
+ Should an error occured during the automated key rollover, an
+ automated key rollover solution must be able to keep the zone files
+ in a consistent state.
+
+5. Emergency Rollover
+
+ Emergency key rollover is a special case of rollover decided by the
+ zone administrator generally for security reasons. In consequence,
+ emergency key rollover can break some of the requirement described
+ above.
+
+ A zone key might be compromised and an attacker can use the
+ compromised key to create and sign fake records. To avoid this, the
+ zone administrator may change the compromised key or all its keys as
+ soon as possible, without waiting for the creation of new DS RRs in
+ its parent zone.
+
+ Fast changes may break the chain of trust. The part of DNS tree
+ having this zone as apex can become unverifiable, but the break of
+ the chain of trust is necessary if the administrator wants to prevent
+ the compromised key from being used (to spoof DNS data).
+
+ Parent and child zones sharing an automated rollover mechanism,
+ should have an out-of-band way to re-establish a consistent state at
+ the delegation point (DS and DNSKEY RRs). This allows to avoid that
+ a malicious party uses the compromised key to roll the zone keys.
+
+
+Guette & Courtay Expires July 19, 2005 [Page 5]
+Internet-Draft Automated Rollover Requirements January 2005
+
+6. Security consideration
+
+ The automated key rollover process in DNSSEC allows automated renewal
+ of any kind of DNS key (ZSK or KSK). It is essential that parent
+ side and child side can do mutual authentication. Moreover,
+ integrity of the material exchanged between the parent and child zone
+ must be provided to ensure the right DS are created.
+
+ As in any application using public key cryptography, in DNSSEC a key
+ may be compromised. What to do in such a case can be describe in the
+ zone local policy and can violate some requirements described in this
+ draft. The emergency rollover can break the chain of trust in order
+ to protect the zone against the use of the compromised key.
+
+7. Acknowledgments
+
+ The authors want to thank members of IDsA project for their
+ contribution to this document.
+
+8 Normative References
+
+ [1] Gudmundsson, O., "Delegation Signer (DS) Resource Record (RR)",
+ RFC 3658, December 2003.
+
+ [2] Kolkman, O., Schlyter, J. and E. Lewis, "Domain Name System KEY
+ (DNSKEY) Resource Record (RR) Secure Entry Point (SEP) Flag",
+ RFC 3757, May 2004.
+
+ [3] Kolkman, O., "DNSSEC Operational Practices",
+ draft-ietf-dnsop-dnssec-operational-practice-01 (work in
+ progress), May 2004.
+
+ [4] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [5] Arends, R., Austein, R., Larson, M., Massey, D. and S. Rose,
+ "Resource Records for the DNS Security Extensions",
+ draft-ietf-dnsext-dnssec-records-11 (work in progress), October
+ 2004.
+
+ [6] Arends, R., Austein, R., Larson, M., Massey, D. and S. Rose,
+ "DNS Security Introduction and Requirements",
+ draft-ietf-dnsext-dnssec-intro-13 (work in progress), October
+ 2004.
+
+ [7] Arends, R., Austein, R., Larson, M., Massey, D. and S. Rose,
+ "Protocol Modifications for the DNS Security Extensions",
+ draft-ietf-dnsext-dnssec-protocol-09 (work in progress), October
+
+
+Guette & Courtay Expires July 19, 2005 [Page 6]
+Internet-Draft Automated Rollover Requirements January 2005
+
+ 2004.
+
+Authors' Addresses
+
+ Gilles Guette
+ IRISA / INRIA
+ Campus de Beaulieu
+ 35042 Rennes CEDEX
+ FR
+
+ EMail: gilles.guette@irisa.fr
+ URI: http://www.irisa.fr
+
+ Olivier Courtay
+ Thomson R&D
+ 1, avenue Belle Fontaine
+ 35510 Cesson S?vign? CEDEX
+ FR
+
+ EMail: olivier.courtay@thomson.net
+
+Appendix A. Documents details and changes
+
+ This section is to be removed by the RFC editor if and when the
+ document is published.
+
+ Section about NS RR rollover has been removed
+
+ Remarks from Samuel Weiler and Rip Loomis added
+
+ Clarification about in-band rollover and in emergency section
+
+ Section 3, details about recursive cache servers added
+
+
+
+
+
+
+
+
+Guette & Courtay Expires July 19, 2005 [Page 7]
+Internet-Draft Automated Rollover Requirements January 2005
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described
+ in this document or the extent to which any license under such
+ rights might or might not be available; neither does it represent
+ that it has made any effort to identify any such rights.
+ Information on the IETF's procedures with respect to rights in
+ IETF Documents can be found in BCP 78 and 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use
+ of such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository
+ at http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention
+ any copyrights, patents or patent applications, or other
+ proprietary rights which may cover technology that may be required
+ to implement this standard. Please address the information to the
+ IETF at ietf-ipr.org.
+
+
+ Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+ Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+Guette & Courtay Expires July 19, 2005 [Page 8]
diff --git a/doc/draft/draft-ietf-dnsop-name-server-management-reqs-01.txt b/doc/draft/draft-ietf-dnsop-name-server-management-reqs-01.txt
new file mode 100644
index 0000000..8298bb2
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsop-name-server-management-reqs-01.txt
@@ -0,0 +1,1008 @@
+
+
+
+DNSOP W. Hardaker
+Internet-Draft Sparta, Inc.
+Intended status: Informational September 3, 2008
+Expires: March 7, 2009
+
+
+ Requirements for Management of Name Servers for the DNS
+ draft-ietf-dnsop-name-server-management-reqs-01.txt
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on March 7, 2009.
+
+Abstract
+
+ Management of name servers for the Domain Name Service (DNS) has
+ traditionally been done using vendor-specific monitoring,
+ configuration and control methods. Although some service monitoring
+ platforms can test the functionality of the DNS itself there is not a
+ interoperable way to manage (monitor, control and configure) the
+ internal aspects of a name server itself.
+
+ This document discusses the requirements of a management system for
+ DNS name servers. A management solution that is designed to manage
+ the DNS can use this document as a shopping list of needed features.
+
+
+
+
+
+Hardaker Expires March 7, 2009 [Page 1]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.1. Requirements notation . . . . . . . . . . . . . . . . . . 4
+ 1.1.1. Terminology . . . . . . . . . . . . . . . . . . . . . 5
+ 1.1.2. Document Layout and Requirements . . . . . . . . . . . 5
+ 2. Management Architecture Requirements . . . . . . . . . . . . . 5
+ 2.1. Expected Deployment Scenarios . . . . . . . . . . . . . . 5
+ 2.1.1. Zone Size Constraints . . . . . . . . . . . . . . . . 5
+ 2.1.2. Name Server Discovery . . . . . . . . . . . . . . . . 6
+ 2.1.3. Configuration Data Volatility . . . . . . . . . . . . 6
+ 2.1.4. Protocol Selection . . . . . . . . . . . . . . . . . . 6
+ 2.1.5. Common Data Model . . . . . . . . . . . . . . . . . . 6
+ 2.1.6. Operational Impact . . . . . . . . . . . . . . . . . . 7
+ 2.2. Name Server Types . . . . . . . . . . . . . . . . . . . . 7
+ 3. Management Operation Types . . . . . . . . . . . . . . . . . . 7
+ 3.1. Control Requirements . . . . . . . . . . . . . . . . . . . 8
+ 3.1.1. Needed Control Operations . . . . . . . . . . . . . . 8
+ 3.1.2. Asynchronous Status Notifications . . . . . . . . . . 8
+ 3.2. Configuration Requirements . . . . . . . . . . . . . . . . 9
+ 3.2.1. Served Zone Modification . . . . . . . . . . . . . . . 9
+ 3.2.2. Trust Anchor Management . . . . . . . . . . . . . . . 9
+ 3.2.3. Security Expectations . . . . . . . . . . . . . . . . 9
+ 3.2.4. TSIG Key Management . . . . . . . . . . . . . . . . . 9
+ 3.2.5. DNS Protocol Authorization Management . . . . . . . . 9
+ 3.3. Monitoring Requirements . . . . . . . . . . . . . . . . . 10
+ 3.4. Alarm and Event Requirements . . . . . . . . . . . . . . . 10
+ 4. Security Requirements . . . . . . . . . . . . . . . . . . . . 11
+ 4.1. Authentication . . . . . . . . . . . . . . . . . . . . . . 11
+ 4.2. Integrity Protection . . . . . . . . . . . . . . . . . . . 11
+ 4.3. Confidentiality . . . . . . . . . . . . . . . . . . . . . 11
+ 4.4. Authorization . . . . . . . . . . . . . . . . . . . . . . 11
+ 4.5. Solution Impacts on Security . . . . . . . . . . . . . . . 12
+ 5. Other Requirements . . . . . . . . . . . . . . . . . . . . . . 12
+ 5.1. Extensibility . . . . . . . . . . . . . . . . . . . . . . 12
+ 5.1.1. Vendor Extensions . . . . . . . . . . . . . . . . . . 13
+ 5.1.2. Extension Identification . . . . . . . . . . . . . . . 13
+ 5.1.3. Namespace Collision Protection . . . . . . . . . . . . 13
+ 6. Security Considerations . . . . . . . . . . . . . . . . . . . 13
+ 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 13
+ 8. Document History . . . . . . . . . . . . . . . . . . . . . . . 13
+ 9. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 14
+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . . 14
+ 10.1. Normative References . . . . . . . . . . . . . . . . . . . 14
+ 10.2. Informative References . . . . . . . . . . . . . . . . . . 15
+ Appendix A. Deployment Scenarios . . . . . . . . . . . . . . . . 15
+ A.1. Non-Standard Zones . . . . . . . . . . . . . . . . . . . . 16
+ A.2. Redundancy Sharing . . . . . . . . . . . . . . . . . . . . 16
+
+
+
+Hardaker Expires March 7, 2009 [Page 2]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ A.3. DNSSEC Management . . . . . . . . . . . . . . . . . . . . 16
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 17
+ Intellectual Property and Copyright Statements . . . . . . . . . . 18
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hardaker Expires March 7, 2009 [Page 3]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+1. Introduction
+
+ Management of name servers for the Domain Name Service (DNS)
+ [RFC1034] [RFC1035] has traditionally been done using vendor-specific
+ monitoring, configuration and control methods. Although some service
+ monitoring platforms can test the functionality of the DNS itself
+ there is not a interoperable way to manage (monitor, control and
+ configure) the internal aspects of a name server itself.
+
+ Previous standardization work within the IETF resulted in the
+ creation of two SNMP MIB modules [RFC1611] [RFC1612] but they failed
+ to achieve significant implementation and deployment. The perceived
+ reasons behind the failure for the two MIB modules are further
+ documented in [RFC3197].
+
+ This document discusses the requirements of a management system for
+ DNS name servers. A management solution that is designed to manage
+ the DNS can use this document as a shopping list of needed features.
+
+ Specifically out of scope for this document are requirements
+ associated with management of stub resolvers. It is not the intent
+ of this document to document stub resolver requirements, although
+ some of the requirements listed are applicable to stub resolvers as
+ well.
+
+ Also out of scope for this document is management of the host or
+ other components of the host upon which the name server software is
+ running. This document only discusses requirements for managing the
+ name server component of a system.
+
+ The task of creating a management system for managing DNS servers is
+ not expected to be a small one. It is likely that components of the
+ solution will need to be designed in parts over time and these
+ requirements take this into consideration. In particular,
+ Section 5.1 discusses the need for future extensibility of the base
+ management solution. This document is intended to be a road-map
+ towards a desired outcome and is not intended to define an "all-or-
+ nothing" system. Successful interoperable management of name servers
+ even in part is expected to be beneficial to network operators
+ compared to the entirely custom solutions that are used at the time
+ of this writing.
+
+1.1. Requirements notation
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+
+
+
+Hardaker Expires March 7, 2009 [Page 4]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+1.1.1. Terminology
+
+ This document is consistent with the terminology defined in Section 2
+ of [RFC4033]. Additional terminology needed for this document is
+ described below:
+
+ Name Server: When we are discussing servers that don't fall into a
+ more specific type of server category defined in other documents,
+ this document will refer to them generically as "name servers".
+ In particular "name servers" can be considered to be any valid
+ combination of authoritative, recursive, validating, or security-
+ aware. The more specific name server labels will be used when
+ this document refers only to a specific type of server. However,
+ the term "name server", in this document, will not include stub
+ resolvers.
+
+1.1.2. Document Layout and Requirements
+
+ The document is written so that each numbered section will contain
+ only a single requirement if it contains one at all. Each
+ requirement will contain needed wording from the terminology
+ described in Section 1.1. Subsections, however, might exist with
+ additional related requirements. The document is laid out in this
+ way so that a specific requirement can be uniquely referred to using
+ the section number itself and the document version from which it
+ came.
+
+
+2. Management Architecture Requirements
+
+ This section discusses requirements that reflect the needs of the
+ expected deployment environments.
+
+2.1. Expected Deployment Scenarios
+
+ DNS zones vary greatly in the type of content published within them.
+ Name Servers, too, are deployed with a wide variety of configurations
+ to support the diversity of the deployed content. It is important
+ that a management solution trying to meet the criteria specified in
+ this document consider supporting the largest number of potential
+ deployment cases as possible. Further deployment scenarios that are
+ not used as direct examples of specific requirements are listed in
+ Appendix A.
+
+2.1.1. Zone Size Constraints
+
+ The management solution MUST support both name servers that are
+ serving a small number of potentially very large zones (e.g. Top
+
+
+
+Hardaker Expires March 7, 2009 [Page 5]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ Level Domains (TLDs)) as well as name servers that are serving a very
+ large number of small zones. These scenarios are both commonly seen
+ deployments.
+
+2.1.2. Name Server Discovery
+
+ Large enterprise network deployments may contain multiple name
+ servers operating within the boundaries of the enterprise network.
+ These name servers may each be serving multiple zones both in and out
+ of the parent enterprise's zone. Finding and managing large
+ quantities of name servers would be a useful feature of the resulting
+ management solution. The management solution MAY support the ability
+ to discover previously unknown instances of name servers operating
+ within a deployed network.
+
+2.1.3. Configuration Data Volatility
+
+ Configuration data is defined as data that relates only to the
+ configuration of a server and the zones it serves. It specifically
+ does not include data from the zone contents that is served through
+ DNS itself. The solution MUST support servers that remain fairly
+ statically configured over time as well as servers that have numerous
+ zones being added and removed within an hour. Both of these
+ scenarios are also commonly seen deployments.
+
+2.1.4. Protocol Selection
+
+ There are many requirements in this document for many different types
+ of management operations (see Section 3 for further details). It is
+ possible that no one protocol will ideally fill all the needs of the
+ requirements listed in this document and thus multiple protocols
+ might be needed to produce a completely functional management system.
+ Multiple protocols might be used to create the complete management
+ solution, but the number of protocols used SHOULD be reduced to a
+ reasonable minimum number.
+
+2.1.5. Common Data Model
+
+ Defining a standardized protocol (or set of protocols) to use for
+ managing name servers would be a step forward in achieving an
+ interoperable management solution. However, just defining a protocol
+ to use by itself would not achieve the complete end goal of a
+ complete interoperable management solution. Devices also need to
+ represent their internal management interface using a common
+ management data model. The solution MUST create a common data model
+ that management stations can make use of when sending or collecting
+ data from a managed device so it can successfully manage equipment
+ from vendors as if they were generic DNS servers. This common data
+
+
+
+Hardaker Expires March 7, 2009 [Page 6]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ model is needed for of the operations discussion in Section 3. Note
+ that this does not preclude the fact that name server vendors might
+ provide additional management infrastructure beyond a base management
+ specification, as discussed further in Section 5.1.
+
+2.1.6. Operational Impact
+
+ It is impossible to add new features to an existing server (such as
+ the inclusion of a management infrastructure) and not impact the
+ existing service and/or server in some fashion. At a minimum, for
+ example, more memory, disk and/or CPU resources will be required to
+ implement a new management system. However, the impact to the
+ existing DNS service MUST be minimized since the DNS service itself
+ is still the primary service to be offered by the modified name
+ server.
+
+2.2. Name Server Types
+
+ There are multiple ways in which name servers can be deployed. Name
+ servers can take on any of the following roles:
+
+ o Master Servers
+
+ o Slave Servers
+
+ o Recursive Servers
+
+ The management solution SHOULD support all of these types of name
+ servers as they are all equally important. Note that "Recursive
+ Servers" can be further broken down by the security sub-roles they
+ might implement, as defined in section 2 of [RFC4033]. These sub-
+ roles are also important to support within any management solution.
+
+ The requirements in this document explicitly exclude dealing with
+ management of stub resolvers. Management of stub resolvers is
+ considered specifically out of scope of this document.
+
+
+3. Management Operation Types
+
+ Management operations can traditionally be broken into four
+ categories:
+
+ o Control
+
+ o Configuration
+
+
+
+
+
+Hardaker Expires March 7, 2009 [Page 7]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ o Health and Monitoring
+
+ o Alarms and Events
+
+ This section discusses requirements for each of these four management
+ types in detail.
+
+3.1. Control Requirements
+
+ The management solution MUST be capable of performing basic service
+ control operations.
+
+3.1.1. Needed Control Operations
+
+ These operations SHOULD include, at a minimum, the following
+ operations:
+
+ o Starting the name server
+
+ o Reloading the service configuration
+
+ o Reloading zone data
+
+ o Restarting the name server
+
+ o Stopping the name server
+
+ Note that no restriction is placed on how the management system
+ implements these operations. In particular, at least "starting the
+ name server" will require a minimal management system component to
+ exist independently of the name server itself.
+
+3.1.2. Asynchronous Status Notifications
+
+ Some control operations might take a long time to complete. As an
+ example, some name servers take a long time to perform reloads of
+ large zones. Because of these timing issues, the management solution
+ SHOULD take this into consideration and offer a mechanism to ease the
+ burden associated with awaiting the status of a long-running command.
+ This could, for example, result in the use of asynchronous
+ notifications for returning the status of a long-running task or it
+ might require the management station to poll for the status of a
+ given task using monitoring commands. These and other potential
+ solutions need to be evaluated carefully to select one that balances
+ the result delivery needs with the perceived implementation costs.
+
+ Also, see the related discussion in Section 3.4 on notification
+ messages for supporting delivery of alarm and event messages.
+
+
+
+Hardaker Expires March 7, 2009 [Page 8]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+3.2. Configuration Requirements
+
+ Many features of name servers need to be configured before the server
+ can be considered functional. The management solution MUST be able
+ to provide name servers with configuration data. The most important
+ data to be configured, for example, is the served zone data itself.
+
+3.2.1. Served Zone Modification
+
+ The ability to add, modify and delete zones being served by name
+ servers is needed. Although there are already solutions for zone
+ content modification (such as Dynamic DNS (DDNS) [RFC2136] [RFC3007],
+ AXFR [RFC1035], and incremental zone transfer (IXFR) [RFC1995]) that
+ might be used as part of the final management solution, the
+ management system SHOULD still be able to natively create a new zone
+ (with enough minimal data to allow the other mechanisms to function
+ as well) as well as delete a zone. This might be, for example, a
+ management operation that at least allows for the creation of the
+ initial SOA record for a new zone as that's the minimum amount of
+ zone data needed for the other operations to function.
+
+3.2.2. Trust Anchor Management
+
+ The solution SHOULD support the ability to add, modify and delete
+ trust anchors that are used by DNS Security (DNSSEC) [RFC4033]
+ [RFC4034] [RFC4035] [RFC4509] [RFC5011] [RFC5155]. These trust
+ anchors might be configured using the data from the DNSKEY Resource
+ Records (RRs) themselves or by using Delegation Signer (DS)
+ fingerprints.
+
+3.2.3. Security Expectations
+
+ DNSSEC Validating resolvers need to make policy decisions about the
+ requests being processed. For example, they need to be configured
+ with a list of zones expected to be secured by DNSSEC. The
+ management solution SHOULD be able to add, modify and delete
+ attributes of DNSSEC security policies.
+
+3.2.4. TSIG Key Management
+
+ TSIG [RFC2845] allows transaction level authentication of DNS
+ traffic. The management solution SHOULD be able to add, modify and
+ delete TSIG keys known to the name server.
+
+3.2.5. DNS Protocol Authorization Management
+
+ The management solution SHOULD have the ability to add, modify and
+ delete authorization settings for the DNS protocols itself. Do not
+
+
+
+Hardaker Expires March 7, 2009 [Page 9]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ confuse this with the ability to manage the authorization associated
+ with the management protocol itself, which is discussed later in
+ Section 4.4. There are a number of authorization settings that are
+ used by a name server. Example authorization settings that the
+ solution might need to cover are:
+
+ o Access to operations on zone data (e.g. DDNS)
+
+ o Access to certain zone data from certain sources (e.g. from
+ particular network subnets)
+
+ o Access to specific DNS protocol services (e.g. recursive service)
+
+ Note: the above list is expected to be used as a collection of
+ examples and is not a complete list of needed authorization
+ protections.
+
+3.3. Monitoring Requirements
+
+ Monitoring is the process of collecting aspects of the internal state
+ of a name server at a given moment in time. The solution MUST be
+ able to monitor the health of a name server to determine its
+ operational status, load and other internal attributes. Example
+ management tasks that the solution might need to cover are:
+
+ o Number of requests sent, responses sent, average response latency
+ and other performance counters
+
+ o Server status (e.g. "serving data", "starting up", "shutting
+ down", ...)
+
+ o Access control violations
+
+ o List of zones being served
+
+ o Detailed statistics about clients interacting with the name server
+ (e.g. top 10 clients requesting data).
+
+ Note: the above list is expected to be used as a collection of
+ examples and is not a complete list of needed monitoring operations.
+ In particular, some monitoring statistics are expected to be
+ computationally or resource expensive and are considered to be "nice
+ to haves" as opposed to "necessary to have".
+
+3.4. Alarm and Event Requirements
+
+ Events occurring at the name server that trigger alarm notifications
+ can quickly inform a management station about critical issues. A
+
+
+
+Hardaker Expires March 7, 2009 [Page 10]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ management solution SHOULD include support for delivery of alarm
+ conditions.
+
+ Example alarm conditions might include:
+
+ o The server's status is changing. (e.g it is starting up, reloading
+ configuration, restarting or shutting down)
+
+ o A needed resource (e.g. memory or disk space) is exhausted or
+ nearing exhaustion
+
+ o An authorization violation was detected
+
+ o The server has not received any data traffic (e.g. DNS requests
+ or NOTIFYs) recently (AKA the "lonely warning"). This condition
+ might indicate a problem with its deployment.
+
+
+4. Security Requirements
+
+ The management solution will need to be appropriately secured against
+ attacks on the management infrastructure.
+
+4.1. Authentication
+
+ The solution MUST support mutual authentication. The management
+ client needs to be assured that the management operations are being
+ transferred to and from the correct name server. The managed name
+ server needs to authenticate the system that is accessing the
+ management infrastructure within itself.
+
+4.2. Integrity Protection
+
+ Management operations MUST be protected from modification while in
+ transit from the management client to the server.
+
+4.3. Confidentiality
+
+ The management solution MUST support message confidentiality. The
+ potential transfer of sensitive configuration is expected (such as
+ TSIG keys or security policies). The solution does not, however,
+ necessarily need to provide confidentiality to data that would
+ normally be carried without confidentiality by the DNS system itself.
+
+4.4. Authorization
+
+ The solution SHOULD be capable of providing a fine-grained
+ authorization model for any management protocols it introduces to the
+
+
+
+Hardaker Expires March 7, 2009 [Page 11]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ completed system. This authorization differs from the authorization
+ previously discussed in Section 3.2.5 in that this requirement is
+ concerned solely with authorization of the management system itself.
+
+ There are a number of authorization settings that might be used by a
+ managed system to determine whether the managing entity has
+ authorization to perform the given management task. Example
+ authorization settings that the solution might need to cover are:
+
+ o Access to the configuration that specifies which zones are to be
+ served
+
+ o Access to the management system infrastructure
+
+ o Access to other control operations
+
+ o Access to other configuration operations
+
+ o Access to monitoring operations
+
+ Note: the above list is expected to be used as a collection of
+ examples and is not a complete list of needed authorization
+ protections.
+
+4.5. Solution Impacts on Security
+
+ The solution MUST minimize the security risks introduced to the
+ complete name server system. It is impossible to add new
+ infrastructure to a server and not impact the security in some
+ fashion as the introduction of a management protocol alone will
+ provide a new avenue for potential attack. Although the added
+ management benefits will be worth the increased risks, the solution
+ still needs to minimize this impact as much as possible.
+
+
+5. Other Requirements
+
+5.1. Extensibility
+
+ The management solution is expected to change and expand over time as
+ lessons are learned and new DNS features are deployed. Thus, the
+ solution MUST be flexible and be able to accommodate new future
+ management operations. The solution might, for example, make use of
+ protocol versioning or capability description exchanges to ensure
+ that management stations and name servers that weren't written to the
+ same specification version can still interoperate to the best of
+ their combined ability.
+
+
+
+
+Hardaker Expires March 7, 2009 [Page 12]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+5.1.1. Vendor Extensions
+
+ It MUST be possible for vendors to extend the standardized management
+ model with vendor-specific extensions to support additional features
+ offered by their products.
+
+5.1.2. Extension Identification
+
+ It MUST be possible for a management station to understand which
+ parts of returned data are specific to a given vendor or other
+ standardized extension. The data returned needs to be appropriately
+ marked through the use of name spaces or similar mechanisms to ensure
+ that the base management model data can be logically separated from
+ extension data without needing to understand the extension data
+ itself.
+
+5.1.3. Namespace Collision Protection
+
+ It MUST be possible to protect against multiple extensions
+ conflicting with each other. The use of name-space protection
+ mechanisms for communicated management variables is common practice
+ to protect against problems. Name-space identification techniques
+ also frequently solve the "Extension Identification" requirement
+ discussed in Section 5.1.2 as well.
+
+
+6. Security Considerations
+
+ Any management protocol that meets the criteria discussed in this
+ document needs to support the criteria discussed in Section 4 in
+ order to protect the management infrastructure itself. The DNS is a
+ core Internet service and management traffic that protects it could
+ be the target of attacks designed to subvert that service. Because
+ the management infrastructure will be adding additional interfaces to
+ that service, it is critical that the management infrastructure
+ support adequate protections against network attacks.
+
+
+7. IANA Considerations
+
+ No action is required from IANA for this document.
+
+
+8. Document History
+
+ A requirement gathering discussion was held at the December 2007 IETF
+ meeting in Vancouver, BC, Canada and a follow up meeting was held at
+ the March 2008 IETF meeting in Philadelphia. This document is a
+
+
+
+Hardaker Expires March 7, 2009 [Page 13]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ compilation of the results of those discussions as well as
+ discussions on the DCOMA mailing list.
+
+
+9. Acknowledgments
+
+ This draft is the result of discussions within the DCOMA design team
+ chaired by Jaap Akkerhuis. This team consisted of a large number of
+ people all of whom provided valuable insight and input into the
+ discussions surrounding name server management. The text of this
+ document was written from notes taken during meetings as well as from
+ contributions sent to the DCOMA mailing list. This work documents
+ the consensus of the DCOMA design team.
+
+ In particular, the following team members contributed significantly
+ to the text in the document:
+
+ Stephane Bortzmeyer
+
+ Stephen Morris
+
+ Phil Regnauld
+
+ Further editing contributions and wording suggestions were made by:
+ Alfred Hines.
+
+
+10. References
+
+10.1. Normative References
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC1995] Ohta, M., "Incremental Zone Transfer in DNS", RFC 1995,
+ August 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2136] Vixie, P., Thomson, S., Rekhter, Y., and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)",
+ RFC 2136, April 1997.
+
+ [RFC2845] Vixie, P., Gudmundsson, O., Eastlake, D., and B.
+
+
+
+Hardaker Expires March 7, 2009 [Page 14]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ Wellington, "Secret Key Transaction Authentication for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+ [RFC3007] Wellington, B., "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+ [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements",
+ RFC 4033, March 2005.
+
+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security Extensions",
+ RFC 4034, March 2005.
+
+ [RFC4035] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security
+ Extensions", RFC 4035, March 2005.
+
+ [RFC4509] Hardaker, W., "Use of SHA-256 in DNSSEC Delegation Signer
+ (DS) Resource Records (RRs)", RFC 4509, May 2006.
+
+ [RFC5011] StJohns, M., "Automated Updates of DNS Security (DNSSEC)
+ Trust Anchors", RFC 5011, September 2007.
+
+ [RFC5155] Laurie, B., Sisson, G., Arends, R., and D. Blacka, "DNS
+ Security (DNSSEC) Hashed Authenticated Denial of
+ Existence", RFC 5155, March 2008.
+
+10.2. Informative References
+
+ [RFC1611] Austein, R. and J. Saperia, "DNS Server MIB Extensions",
+ RFC 1611, May 1994.
+
+ [RFC1612] Austein, R. and J. Saperia, "DNS Resolver MIB Extensions",
+ RFC 1612, May 1994.
+
+ [RFC2182] Elz, R., Bush, R., Bradner, S., and M. Patton, "Selection
+ and Operation of Secondary DNS Servers", BCP 16, RFC 2182,
+ July 1997.
+
+ [RFC3197] Austein, R., "Applicability Statement for DNS MIB
+ Extensions", RFC 3197, November 2001.
+
+
+Appendix A. Deployment Scenarios
+
+ This appendix documents some additional deployment scenarios that
+ have been traditionally difficult to manage. They are provided as
+
+
+
+Hardaker Expires March 7, 2009 [Page 15]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ guidance to protocol developers as data points of real-world name
+ server management problems.
+
+A.1. Non-Standard Zones
+
+ If an organization uses non-standard zones (for example a purely-
+ local TLD), synchronizing all the nameservers for these zones is
+ usually a time-consuming task. It is made worse when two
+ organizations with conflicting zones merge. This situation is not a
+ recommended deployment scenario (and is even heavily discouraged) but
+ it is, unfortunately, seen in the wild.
+
+ It is typically implemented using "forwarding" zones. But there is
+ no way to ensure automatically that all the resolvers have the same
+ set of zones to forward at any given time. New zones might be added
+ to a local forwarding recursive server, for example, without
+ modifying the rest of the deployed forwarding servers. It is hoped
+ that a management solution which could handle the configuration of
+ zone forwarding would finally allow management of servers deployed in
+ this fashion.
+
+A.2. Redundancy Sharing
+
+ For reliability reasons it is recommended that zone operators follow
+ the guidelines documented in [RFC2182] which recommends that multiple
+ name servers be configured for each zone and that the name servers
+ are separated both physically and via connectivity routes. A common
+ solution is to establish DNS-serving partnerships: "I'll host your
+ zones and you'll host mine". Both entities benefit from increased
+ DNS reliability via the wider service distribution. This frequently
+ occurs between cooperating but otherwise unrelated entities (such as
+ between two distinct companies) as well as between affiliated
+ organizations (such as between branch offices within a single
+ company).
+
+ The configuration of these relationships are currently required to be
+ manually configured and maintained. Changes to the list of zones
+ that are cross-hosted are manually negotiated between the cooperating
+ network administrators and configured by hand. A management protocol
+ with the ability to provide selective authorization, as discussed in
+ Section 4.4, would solve many of the management difficulties between
+ cooperating organizations.
+
+A.3. DNSSEC Management
+
+ There are many different DNSSEC deployment strategies that may be
+ used for mission-critical zones. The following list describes some
+ example deployment scenarios that might warrant different management
+
+
+
+Hardaker Expires March 7, 2009 [Page 16]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+ strategies.
+
+ All contents and DNSSEC keying information controlled and operated
+ by a single organization
+
+ Zone contents controlled and operated by one organization, all
+ DNSSEC keying information controlled and operated by a second
+ organization.
+
+ Zone contents controlled and operated by one organization, zone
+ signing keys (ZSKs) controlled and operated by a second
+ organization, and key signing keys (KSKs) controlled and operated
+ by a third organization.
+
+ Although this list is not exhaustive in the potential ways that zone
+ data can be divided up, it should be sufficient to illustrate the
+ potential ways in which zone data can be controlled by multiple
+ entities.
+
+ The end result of all of these strategies, however, will be the same:
+ a live zone containing DNSSEC related resource records. Many of the
+ above strategies are merely different ways of preparing a zone for
+ serving. A management solution that includes support for managing
+ DNSSEC zone data may wish to take into account these potential
+ management scenarios.
+
+
+Author's Address
+
+ Wes Hardaker
+ Sparta, Inc.
+ P.O. Box 382
+ Davis, CA 95617
+ US
+
+ Phone: +1 530 792 1913
+ Email: ietf@hardakers.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hardaker Expires March 7, 2009 [Page 17]
+
+Internet-Draft Name Server Management Requirements September 2008
+
+
+Full Copyright Statement
+
+ Copyright (C) The IETF Trust (2008).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+
+
+
+
+
+
+
+
+
+Hardaker Expires March 7, 2009 [Page 18]
+
diff --git a/doc/draft/draft-ietf-dnsop-respsize-06.txt b/doc/draft/draft-ietf-dnsop-respsize-06.txt
new file mode 100644
index 0000000..b041925
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsop-respsize-06.txt
@@ -0,0 +1,640 @@
+
+
+
+
+
+
+ DNSOP Working Group Paul Vixie, ISC
+ INTERNET-DRAFT Akira Kato, WIDE
+ <draft-ietf-dnsop-respsize-06.txt> August 2006
+
+ DNS Referral Response Size Issues
+
+ Status of this Memo
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ Copyright Notice
+
+ Copyright (C) The Internet Society (2006). All Rights Reserved.
+
+
+
+
+ Abstract
+
+ With a mandated default minimum maximum message size of 512 octets,
+ the DNS protocol presents some special problems for zones wishing to
+ expose a moderate or high number of authority servers (NS RRs). This
+ document explains the operational issues caused by, or related to
+ this response size limit, and suggests ways to optimize the use of
+ this limited space. Guidance is offered to DNS server implementors
+ and to DNS zone operators.
+
+
+
+
+ Expires January 2007 [Page 1]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ 1 - Introduction and Overview
+
+ 1.1. The DNS standard (see [RFC1035 4.2.1]) limits message size to 512
+ octets. Even though this limitation was due to the required minimum IP
+ reassembly limit for IPv4, it became a hard DNS protocol limit and is
+ not implicitly relaxed by changes in transport, for example to IPv6.
+
+ 1.2. The EDNS0 protocol extension (see [RFC2671 2.3, 4.5]) permits
+ larger responses by mutual agreement of the requester and responder.
+ The 512 octet message size limit will remain in practical effect until
+ there is widespread deployment of EDNS0 in DNS resolvers on the
+ Internet.
+
+ 1.3. Since DNS responses include a copy of the request, the space
+ available for response data is somewhat less than the full 512 octets.
+ Negative responses are quite small, but for positive and delegation
+ responses, every octet must be carefully and sparingly allocated. This
+ document specifically addresses delegation response sizes.
+
+ 2 - Delegation Details
+
+ 2.1. RELEVANT PROTOCOL ELEMENTS
+
+ 2.1.1. A delegation response will include the following elements:
+
+ Header Section: fixed length (12 octets)
+ Question Section: original query (name, class, type)
+ Answer Section: empty, or a CNAME/DNAME chain
+ Authority Section: NS RRset (nameserver names)
+ Additional Section: A and AAAA RRsets (nameserver addresses)
+
+ 2.1.2. If the total response size exceeds 512 octets, and if the data
+ that does not fit was "required", then the TC bit will be set
+ (indicating truncation). This will usually cause the requester to retry
+ using TCP, depending on what information was desired and what
+ information was omitted. For example, truncation in the authority
+ section is of no interest to a stub resolver who only plans to consume
+ the answer section. If a retry using TCP is needed, the total cost of
+ the transaction is much higher. See [RFC1123 6.1.3.2] for details on
+ the requirement that UDP be attempted before falling back to TCP.
+
+ 2.1.3. RRsets are never sent partially unless TC bit set to indicate
+ truncation. When TC bit is set, the final apparent RRset in the final
+ non-empty section must be considered "possibly damaged" (see [RFC1035
+ 6.2], [RFC2181 9]).
+
+
+
+ Expires January 2007 [Page 2]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ 2.1.4. With or without truncation, the glue present in the additional
+ data section should be considered "possibly incomplete", and requesters
+ should be prepared to re-query for any damaged or missing RRsets. Note
+ that truncation of the additional data section might not be signalled
+ via the TC bit since additional data is often optional (see discussion
+ in [RFC4472 B]).
+
+ 2.1.5. DNS label compression allows a domain name to be instantiated
+ only once per DNS message, and then referenced with a two-octet
+ "pointer" from other locations in that same DNS message (see [RFC1035
+ 4.1.4]). If all nameserver names in a message share a common parent
+ (for example, all ending in ".ROOT-SERVERS.NET"), then more space will
+ be available for incompressable data (such as nameserver addresses).
+
+ 2.1.6. The query name can be as long as 255 octets of network data. In
+ this worst case scenario, the question section will be 259 octets in
+ size, which would leave only 240 octets for the authority and additional
+ sections (after deducting 12 octets for the fixed length header.)
+
+ 2.2. ADVICE TO ZONE OWNERS
+
+ 2.2.1. Average and maximum question section sizes can be predicted by
+ the zone owner, since they will know what names actually exist, and can
+ measure which ones are queried for most often. Note that if the zone
+ contains any wildcards, it is possible for maximum length queries to
+ require positive responses, but that it is reasonable to expect
+ truncation and TCP retry in that case. For cost and performance
+ reasons, the majority of requests should be satisfied without truncation
+ or TCP retry.
+
+ 2.2.2. Some queries to non-existing names can be large, but this is not
+ a problem because negative responses need not contain any answer,
+ authority or additional records. See [RFC2308 2.1] for more information
+ about the format of negative responses.
+
+ 2.2.3. The minimum useful number of name servers is two, for redundancy
+ (see [RFC1034 4.1]). A zone's name servers should be reachable by all
+ IP transport protocols (e.g., IPv4 and IPv6) in common use.
+
+ 2.2.4. The best case is no truncation at all. This is because many
+ requesters will retry using TCP immediately, or will automatically re-
+ query for RRsets that are possibly truncated, without considering
+ whether the omitted data was actually necessary.
+
+
+
+
+
+ Expires January 2007 [Page 3]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ 2.3. ADVICE TO SERVER IMPLEMENTORS
+
+ 2.3.1. In case of multi-homed name servers, it is advantageous to
+ include an address record from each of several name servers before
+ including several address records for any one name server. If address
+ records for more than one transport (for example, A and AAAA) are
+ available, then it is advantageous to include records of both types
+ early on, before the message is full.
+
+ 2.3.2. Each added NS RR for a zone will add 12 fixed octets (name, type,
+ class, ttl, and rdlen) plus 2 to 255 variable octets (for the NSDNAME).
+ Each A RR will require 16 octets, and each AAAA RR will require 28
+ octets.
+
+ 2.3.3. While DNS distinguishes between necessary and optional resource
+ records, this distinction is according to protocol elements necessary to
+ signify facts, and takes no official notice of protocol content
+ necessary to ensure correct operation. For example, a nameserver name
+ that is in or below the zone cut being described by a delegation is
+ "necessary content," since there is no way to reach that zone unless the
+ parent zone's delegation includes "glue records" describing that name
+ server's addresses.
+
+ 2.3.4. It is also necessary to distinguish between "explicit truncation"
+ where a message could not contain enough records to convey its intended
+ meaning, and so the TC bit has been set, and "silent truncation", where
+ the message was not large enough to contain some records which were "not
+ required", and so the TC bit was not set.
+
+ 2.3.5. A delegation response should prioritize glue records as follows.
+
+ first
+ All glue RRsets for one name server whose name is in or below the
+ zone being delegated, or which has multiple address RRsets (currently
+ A and AAAA), or preferably both;
+
+ second
+ Alternate between adding all glue RRsets for any name servers whose
+ names are in or below the zone being delegated, and all glue RRsets
+ for any name servers who have multiple address RRsets (currently A
+ and AAAA);
+
+ thence
+ All other glue RRsets, in any order.
+
+
+
+
+ Expires January 2007 [Page 4]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ Whenever there are multiple candidates for a position in this priority
+ scheme, one should be chosen on a round-robin or fully random basis.
+
+ The goal of this priority scheme is to offer "necessary" glue first,
+ avoiding silent truncation for this glue if possible.
+
+ 2.3.6. If any "necessary content" is silently truncated, then it is
+ advisable that the TC bit be set in order to force a TCP retry, rather
+ than have the zone be unreachable. Note that a parent server's proper
+ response to a query for in-child glue or below-child glue is a referral
+ rather than an answer, and that this referral MUST be able to contain
+ the in-child or below-child glue, and that in outlying cases, only EDNS
+ or TCP will be large enough to contain that data.
+
+ 3 - Analysis
+
+ 3.1. An instrumented protocol trace of a best case delegation response
+ follows. Note that 13 servers are named, and 13 addresses are given.
+ This query was artificially designed to exactly reach the 512 octet
+ limit.
+
+ ;; flags: qr rd; QUERY: 1, ANS: 0, AUTH: 13, ADDIT: 13
+ ;; QUERY SECTION:
+ ;; [23456789.123456789.123456789.\
+ 123456789.123456789.123456789.com A IN] ;; @80
+
+ ;; AUTHORITY SECTION:
+ com. 86400 NS E.GTLD-SERVERS.NET. ;; @112
+ com. 86400 NS F.GTLD-SERVERS.NET. ;; @128
+ com. 86400 NS G.GTLD-SERVERS.NET. ;; @144
+ com. 86400 NS H.GTLD-SERVERS.NET. ;; @160
+ com. 86400 NS I.GTLD-SERVERS.NET. ;; @176
+ com. 86400 NS J.GTLD-SERVERS.NET. ;; @192
+ com. 86400 NS K.GTLD-SERVERS.NET. ;; @208
+ com. 86400 NS L.GTLD-SERVERS.NET. ;; @224
+ com. 86400 NS M.GTLD-SERVERS.NET. ;; @240
+ com. 86400 NS A.GTLD-SERVERS.NET. ;; @256
+ com. 86400 NS B.GTLD-SERVERS.NET. ;; @272
+ com. 86400 NS C.GTLD-SERVERS.NET. ;; @288
+ com. 86400 NS D.GTLD-SERVERS.NET. ;; @304
+
+
+
+
+
+
+
+
+ Expires January 2007 [Page 5]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ ;; ADDITIONAL SECTION:
+ A.GTLD-SERVERS.NET. 86400 A 192.5.6.30 ;; @320
+ B.GTLD-SERVERS.NET. 86400 A 192.33.14.30 ;; @336
+ C.GTLD-SERVERS.NET. 86400 A 192.26.92.30 ;; @352
+ D.GTLD-SERVERS.NET. 86400 A 192.31.80.30 ;; @368
+ E.GTLD-SERVERS.NET. 86400 A 192.12.94.30 ;; @384
+ F.GTLD-SERVERS.NET. 86400 A 192.35.51.30 ;; @400
+ G.GTLD-SERVERS.NET. 86400 A 192.42.93.30 ;; @416
+ H.GTLD-SERVERS.NET. 86400 A 192.54.112.30 ;; @432
+ I.GTLD-SERVERS.NET. 86400 A 192.43.172.30 ;; @448
+ J.GTLD-SERVERS.NET. 86400 A 192.48.79.30 ;; @464
+ K.GTLD-SERVERS.NET. 86400 A 192.52.178.30 ;; @480
+ L.GTLD-SERVERS.NET. 86400 A 192.41.162.30 ;; @496
+ M.GTLD-SERVERS.NET. 86400 A 192.55.83.30 ;; @512
+
+ ;; MSG SIZE sent: 80 rcvd: 512
+
+ 3.2. For longer query names, the number of address records supplied will
+ be lower. Furthermore, it is only by using a common parent name (which
+ is GTLD-SERVERS.NET in this example) that all 13 addresses are able to
+ fit, due to the use of DNS compression pointers in the last 12
+ occurances of the parent domain name. The following output from a
+ response simulator demonstrates these properties.
+
+ % perl respsize.pl a.dns.br b.dns.br c.dns.br d.dns.br
+ a.dns.br requires 10 bytes
+ b.dns.br requires 4 bytes
+ c.dns.br requires 4 bytes
+ d.dns.br requires 4 bytes
+ # of NS: 4
+ For maximum size query (255 byte):
+ only A is considered: # of A is 4 (green)
+ A and AAAA are considered: # of A+AAAA is 3 (yellow)
+ preferred-glue A is assumed: # of A is 4, # of AAAA is 3 (yellow)
+ For average size query (64 byte):
+ only A is considered: # of A is 4 (green)
+ A and AAAA are considered: # of A+AAAA is 4 (green)
+ preferred-glue A is assumed: # of A is 4, # of AAAA is 4 (green)
+
+
+
+
+
+
+
+
+
+
+ Expires January 2007 [Page 6]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ % perl respsize.pl ns-ext.isc.org ns.psg.com ns.ripe.net ns.eu.int
+ ns-ext.isc.org requires 16 bytes
+ ns.psg.com requires 12 bytes
+ ns.ripe.net requires 13 bytes
+ ns.eu.int requires 11 bytes
+ # of NS: 4
+ For maximum size query (255 byte):
+ only A is considered: # of A is 4 (green)
+ A and AAAA are considered: # of A+AAAA is 3 (yellow)
+ preferred-glue A is assumed: # of A is 4, # of AAAA is 2 (yellow)
+ For average size query (64 byte):
+ only A is considered: # of A is 4 (green)
+ A and AAAA are considered: # of A+AAAA is 4 (green)
+ preferred-glue A is assumed: # of A is 4, # of AAAA is 4 (green)
+
+ (Note: The response simulator program is shown in Section 5.)
+
+ Here we use the term "green" if all address records could fit, or
+ "yellow" if two or more could fit, or "orange" if only one could fit, or
+ "red" if no address record could fit. It's clear that without a common
+ parent for nameserver names, much space would be lost. For these
+ examples we use an average/common name size of 15 octets, befitting our
+ assumption of GTLD-SERVERS.NET as our common parent name.
+
+ We're assuming a medium query name size of 64 since that is the typical
+ size seen in trace data at the time of this writing. If
+ Internationalized Domain Name (IDN) or any other technology which
+ results in larger query names be deployed significantly in advance of
+ EDNS, then new measurements and new estimates will have to be made.
+
+ 4 - Conclusions
+
+ 4.1. The current practice of giving all nameserver names a common parent
+ (such as GTLD-SERVERS.NET or ROOT-SERVERS.NET) saves space in DNS
+ responses and allows for more nameservers to be enumerated than would
+ otherwise be possible, since the common parent domain name only appears
+ once in a DNS message and is referred to via "compression pointers"
+ thereafter.
+
+ 4.2. If all nameserver names for a zone share a common parent, then it
+ is operationally advisable to make all servers for the zone thus served
+ also be authoritative for the zone of that common parent. For example,
+ the root name servers (?.ROOT-SERVERS.NET) can answer authoritatively
+ for the ROOT-SERVERS.NET. This is to ensure that the zone's servers
+ always have the zone's nameservers' glue available when delegating, and
+
+
+
+ Expires January 2007 [Page 7]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ will be able to respond with answers rather than referrals if a
+ requester who wants that glue comes back asking for it. In this case
+ the name server will likely be a "stealth server" -- authoritative but
+ unadvertised in the glue zone's NS RRset. See [RFC1996 2] for more
+ information about stealth servers.
+
+ 4.3. Thirteen (13) is the effective maximum number of nameserver names
+ usable traditional (non-extended) DNS, assuming a common parent domain
+ name, and given that implicit referral response truncation is
+ undesirable in the average case.
+
+ 4.4. Multi-homing of name servers within a protocol family is
+ inadvisable since the necessary glue RRsets (A or AAAA) are atomically
+ indivisible, and will be larger than a single resource record. Larger
+ RRsets are more likely to lead to or encounter truncation.
+
+ 4.5. Multi-homing of name servers across protocol families is less
+ likely to lead to or encounter truncation, partly because multiprotocol
+ clients are more likely to speak EDNS which can use a larger response
+ size limit, and partly because the resource records (A and AAAA) are in
+ different RRsets and are therefore divisible from each other.
+
+ 4.6. Name server names which are at or below the zone they serve are
+ more sensitive to referral response truncation, and glue records for
+ them should be considered "less optional" than other glue records, in
+ the assembly of referral responses.
+
+ 4.7. If a zone is served by thirteen (13) name servers having a common
+ parent name (such as ?.ROOT-SERVERS.NET) and each such name server has a
+ single address record in some protocol family (e.g., an A RR), then all
+ thirteen name servers or any subset thereof could multi-home in a second
+ protocol family by adding a second address record (e.g., an AAAA RR)
+ without reducing the reachability of the zone thus served.
+
+ 5 - Source Code
+
+ #!/usr/bin/perl
+ #
+ # SYNOPSIS
+ # repsize.pl [ -z zone ] fqdn_ns1 fqdn_ns2 ...
+ # if all queries are assumed to have a same zone suffix,
+ # such as "jp" in JP TLD servers, specify it in -z option
+ #
+ use strict;
+ use Getopt::Std;
+
+
+
+ Expires January 2007 [Page 8]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ my ($sz_msg) = (512);
+ my ($sz_header, $sz_ptr, $sz_rr_a, $sz_rr_aaaa) = (12, 2, 16, 28);
+ my ($sz_type, $sz_class, $sz_ttl, $sz_rdlen) = (2, 2, 4, 2);
+ my (%namedb, $name, $nssect, %opts, $optz);
+ my $n_ns = 0;
+
+ getopt('z', %opts);
+ if (defined($opts{'z'})) {
+ server_name_len($opts{'z'}); # just register it
+ }
+
+ foreach $name (@ARGV) {
+ my $len;
+ $n_ns++;
+ $len = server_name_len($name);
+ print "$name requires $len bytes\n";
+ $nssect += $sz_ptr + $sz_type + $sz_class + $sz_ttl
+ + $sz_rdlen + $len;
+ }
+ print "# of NS: $n_ns\n";
+ arsect(255, $nssect, $n_ns, "maximum");
+ arsect(64, $nssect, $n_ns, "average");
+
+ sub server_name_len {
+ my ($name) = @_;
+ my (@labels, $len, $n, $suffix);
+
+ $name =~ tr/A-Z/a-z/;
+ @labels = split(/\./, $name);
+ $len = length(join('.', @labels)) + 2;
+ for ($n = 0; $#labels >= 0; $n++, shift @labels) {
+ $suffix = join('.', @labels);
+ return length($name) - length($suffix) + $sz_ptr
+ if (defined($namedb{$suffix}));
+ $namedb{$suffix} = 1;
+ }
+ return $len;
+ }
+
+ sub arsect {
+ my ($sz_query, $nssect, $n_ns, $cond) = @_;
+ my ($space, $n_a, $n_a_aaaa, $n_p_aaaa, $ansect);
+ $ansect = $sz_query + 1 + $sz_type + $sz_class;
+ $space = $sz_msg - $sz_header - $ansect - $nssect;
+ $n_a = atmost(int($space / $sz_rr_a), $n_ns);
+
+
+
+ Expires January 2007 [Page 9]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ $n_a_aaaa = atmost(int($space
+ / ($sz_rr_a + $sz_rr_aaaa)), $n_ns);
+ $n_p_aaaa = atmost(int(($space - $sz_rr_a * $n_ns)
+ / $sz_rr_aaaa), $n_ns);
+ printf "For %s size query (%d byte):\n", $cond, $sz_query;
+ printf " only A is considered: ";
+ printf "# of A is %d (%s)\n", $n_a, &judge($n_a, $n_ns);
+ printf " A and AAAA are considered: ";
+ printf "# of A+AAAA is %d (%s)\n",
+ $n_a_aaaa, &judge($n_a_aaaa, $n_ns);
+ printf " preferred-glue A is assumed: ";
+ printf "# of A is %d, # of AAAA is %d (%s)\n",
+ $n_a, $n_p_aaaa, &judge($n_p_aaaa, $n_ns);
+ }
+
+ sub judge {
+ my ($n, $n_ns) = @_;
+ return "green" if ($n >= $n_ns);
+ return "yellow" if ($n >= 2);
+ return "orange" if ($n == 1);
+ return "red";
+ }
+
+ sub atmost {
+ my ($a, $b) = @_;
+ return 0 if ($a < 0);
+ return $b if ($a > $b);
+ return $a;
+ }
+
+ 6 - Security Considerations
+
+ The recommendations contained in this document have no known security
+ implications.
+
+ 7 - IANA Considerations
+
+ This document does not call for changes or additions to any IANA
+ registry.
+
+ 8 - Acknowledgement
+
+ The authors thank Peter Koch, Rob Austein, Joe Abley, and Mark Andrews
+ for their valuable comments and suggestions.
+
+
+
+
+ Expires January 2007 [Page 10]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ This work was supported by the US National Science Foundation (research
+ grant SCI-0427144) and DNS-OARC.
+
+ 9 - References
+
+ [RFC1034] Mockapetris, P.V., "Domain names - Concepts and Facilities",
+ RFC1034, November 1987.
+
+ [RFC1035] Mockapetris, P.V., "Domain names - Implementation and
+ Specification", RFC1035, November 1987.
+
+ [RFC1123] Braden, R., Ed., "Requirements for Internet Hosts -
+ Application and Support", RFC1123, October 1989.
+
+ [RFC1996] Vixie, P., "A Mechanism for Prompt Notification of Zone
+ Changes (DNS NOTIFY)", RFC1996, August 1996.
+
+ [RFC2181] Elz, R., Bush, R., "Clarifications to the DNS Specification",
+ RFC2181, July 1997.
+
+ [RFC2308] Andrews, M., "Negative Caching of DNS Queries (DNS NCACHE)",
+ RFC2308, March 1998.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC2671,
+ August 1999.
+
+ [RFC4472] Durand, A., Ihren, J., Savola, P., "Operational Consideration
+ and Issues with IPV6 DNS", April 2006.
+
+ 10 - Authors' Addresses
+
+ Paul Vixie
+ Internet Systems Consortium, Inc.
+ 950 Charter Street
+ Redwood City, CA 94063
+ +1 650 423 1301
+ vixie@isc.org
+
+ Akira Kato
+ University of Tokyo, Information Technology Center
+ 2-11-16 Yayoi Bunkyo
+ Tokyo 113-8658, JAPAN
+ +81 3 5841 2750
+ kato@wide.ad.jp
+
+
+
+
+ Expires January 2007 [Page 11]
+
+ INTERNET-DRAFT August 2006 RESPSIZE
+
+
+ Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors retain
+ all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR
+ IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+ Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in this
+ document or the extent to which any license under such rights might or
+ might not be available; nor does it represent that it has made any
+ independent effort to identify any such rights. Information on the
+ procedures with respect to rights in RFC documents can be found in BCP
+ 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an attempt
+ made to obtain a general license or permission for the use of such
+ proprietary rights by implementers or users of this specification can be
+ obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary rights
+ that may cover technology that may be required to implement this
+ standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+ Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+ Expires January 2007 [Page 12]
+
+
diff --git a/doc/draft/draft-ietf-dnsop-serverid-06.txt b/doc/draft/draft-ietf-dnsop-serverid-06.txt
new file mode 100644
index 0000000..c6ec7e4
--- /dev/null
+++ b/doc/draft/draft-ietf-dnsop-serverid-06.txt
@@ -0,0 +1,618 @@
+
+
+
+
+Network Working Group S. Woolf
+Internet-Draft Internet Systems Consortium, Inc.
+Expires: September 6, 2006 D. Conrad
+ Nominum, Inc.
+ March 5, 2006
+
+
+ Requirements for a Mechanism Identifying a Name Server Instance
+ draft-ietf-dnsop-serverid-06
+
+Status of this Memo
+
+ By submitting this Internet-Draft, each author represents that any
+ applicable patent or other IPR claims of which he or she is aware
+ have been or will be disclosed, and any of which he or she becomes
+ aware will be disclosed, in accordance with Section 6 of BCP 79.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on September 6, 2006.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ With the increased use of DNS anycast, load balancing, and other
+ mechanisms allowing more than one DNS name server to share a single
+ IP address, it is sometimes difficult to tell which of a pool of name
+ servers has answered a particular query. A standardized mechanism to
+ determine the identity of a name server responding to a particular
+ query would be useful, particularly as a diagnostic aid for
+ administrators. Existing ad hoc mechanisms for addressing this need
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 1]
+
+Internet-Draft Serverid March 2006
+
+
+ have some shortcomings, not the least of which is the lack of prior
+ analysis of exactly how such a mechanism should be designed and
+ deployed. This document describes the existing convention used in
+ some widely deployed implementations of the DNS protocol, including
+ advantages and disadvantages, and discusses some attributes of an
+ improved mechanism.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 2]
+
+Internet-Draft Serverid March 2006
+
+
+1. Introduction and Rationale
+
+ Identifying which name server is responding to queries is often
+ useful, particularly in attempting to diagnose name server
+ difficulties. This is most obviously useful for authoritative
+ nameservers in the attempt to diagnose the source or prevalence of
+ inaccurate data, but can also conceivably be useful for caching
+ resolvers in similar and other situations. Furthermore, the ability
+ to identify which server is responding to a query has become more
+ useful as DNS has become more critical to more Internet users, and as
+ network and server deployment topologies have become more complex.
+
+ The traditional means for determining which of several possible
+ servers is answering a query has traditionally been based on the use
+ of the server's IP address as a unique identifier. However, the
+ modern Internet has seen the deployment of various load balancing,
+ fault-tolerance, or attack-resistance schemes such as shared use of
+ unicast IP addresses as documented in [RFC3258]. An unfortunate side
+ effect of these schemes has been to make the use of IP addresses as
+ identifiers somewhat problematic. Specifically, a dedicated DNS
+ query may not go to the same server as answered a previous query,
+ even though sent to the same IP address. Non-DNS methods such as
+ ICMP ping, TCP connections, or non-DNS UDP packets (such as those
+ generated by tools like "traceroute"), etc., may well be even less
+ certain to reach the same server as the one which receives the DNS
+ queries.
+
+ There is a well-known and frequently-used technique for determining
+ an identity for a nameserver more specific than the possibly-non-
+ unique "server that answered the query I sent to IP address XXX".
+ The widespread use of the existing convention suggests a need for a
+ documented, interoperable means of querying the identity of a
+ nameserver that may be part of an anycast or load-balancing cluster.
+ At the same time, however, it also has some drawbacks that argue
+ against standardizing it as it's been practiced so far.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 3]
+
+Internet-Draft Serverid March 2006
+
+
+2. Existing Conventions
+
+ For some time, the commonly deployed Berkeley Internet Name Domain
+ implementation of the DNS protocol suite from the Internet Systems
+ Consortium [BIND] has supported a way of identifying a particular
+ server via the use of a standards-compliant, if somewhat unusual, DNS
+ query. Specifically, a query to a recent BIND server for a TXT
+ resource record in class 3 (CHAOS) for the domain name
+ "HOSTNAME.BIND." will return a string that can be configured by the
+ name server administrator to provide a unique identifier for the
+ responding server. (The value defaults to the result of a
+ gethostname() call). This mechanism, which is an extension of the
+ BIND convention of using CHAOS class TXT RR queries to sub-domains of
+ the "BIND." domain for version information, has been copied by
+ several name server vendors.
+
+ A refinement to the BIND-based mechanism, which dropped the
+ implementation-specific string, replaces ".BIND" with ".SERVER".
+ Thus the query string to learn the unique name of a server may be
+ queried as "ID.SERVER".
+
+ (For reference, the other well-known name used by recent versions of
+ BIND within the CHAOS class "BIND." domain is "VERSION.BIND." A
+ query for a CHAOS TXT RR for this name will return an
+ administratively defined string which defaults to the version of the
+ server responding. This is, however, not generally implemented by
+ other vendors.)
+
+2.1. Advantages
+
+ There are several valuable attributes to this mechanism, which
+ account for its usefulness.
+
+ 1. The "HOSTNAME.BIND" or "ID.SERVER" query response mechanism is
+ within the DNS protocol itself. An identification mechanism that
+ relies on the DNS protocol is more likely to be successful
+ (although not guaranteed) in going to the same system as a
+ "normal" DNS query.
+
+ 2. Since the identity information is requested and returned within
+ the DNS protocol, it doesn't require allowing any other query
+ mechanism to the server, such as holes in firewalls for
+ otherwise-unallowed ICMP Echo requests. Thus it is likely to
+ reach the same server over a path subject to the same routing,
+ resource, and security policy as the query, without any special
+ exceptions to site security policy.
+
+
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 4]
+
+Internet-Draft Serverid March 2006
+
+
+ 3. It is simple to configure. An administrator can easily turn on
+ this feature and control the results of the relevant query.
+
+ 4. It allows the administrator complete control of what information
+ is given out in the response, minimizing passive leakage of
+ implementation or configuration details. Such details are often
+ considered sensitive by infrastructure operators.
+
+ 5. Hypothetically, since it's an ordinary DNS record and the
+ relevant DNSSEC RRs are class independent, the id.server response
+ RR could be signed, which has the advantages described in
+ [RFC4033].
+
+2.2. Disadvantages
+
+ At the same time, there are some serious drawbacks to the CHAOS/TXT
+ query mechanism that argue against standardizing it as it currently
+ operates.
+
+ 1. It requires an additional query to correlate between the answer
+ to a DNS query under normal conditions and the supposed identity
+ of the server receiving the query. There are a number of
+ situations in which this simply isn't reliable.
+
+ 2. It reserves an entire class in the DNS (CHAOS) for what amounts
+ to one zone. While CHAOS class is defined in [RFC1034] and
+ [RFC1035], it's not clear that supporting it solely for this
+ purpose is a good use of the namespace or of implementation
+ effort.
+
+ 3. The initial and still common form, using .BIND, is implementation
+ specific. BIND is one DNS implementation. At the time of this
+ writing, it is probably the most prevalent for authoritative
+ servers. This does not justify standardizing on its ad hoc
+ solution to a problem shared across many operators and
+ implementors. Meanwhile, the proposed refinement changes the
+ string but preserves the ad hoc CHAOS/TXT mechanism.
+
+ 4. There is no convention or shared understanding of what
+ information an answer to such a query for a server identity could
+ or should include, including a possible encoding or
+ authentication mechanism.
+
+ The first of the listed disadvantages may be technically the most
+ serious. It argues for an attempt to design a good answer to the
+ problem that "I need to know what nameserver is answering my
+ queries", not simply a convenient one.
+
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 5]
+
+Internet-Draft Serverid March 2006
+
+
+2.3. Characteristics of an Implementation Neutral Convention
+
+ The discussion above of advantages and disadvantages to the
+ HOSTNAME.BIND mechanism suggest some requirements for a better
+ solution to the server identification problem. These are summarized
+ here as guidelines for any effort to provide appropriate protocol
+ extensions:
+
+ 1. The mechanism adopted must be in-band for the DNS protocol. That
+ is, it needs to allow the query for the server's identifying
+ information to be part of a normal, operational query. It should
+ also permit a separate, dedicated query for the server's
+ identifying information. But it should preserve the ability of
+ the CHAOS/TXT query-based mechanism to work through firewalls and
+ in other situations where only DNS can be relied upon to reach
+ the server of interest.
+
+ 2. The new mechanism should not require dedicated namespaces or
+ other reserved values outside of the existing protocol mechanisms
+ for these, i.e. the OPT pseudo-RR. In particular, it should not
+ propagate the existing drawback of requiring support for a CLASS
+ and top level domain in the authoritative server (or the querying
+ tool) to be useful.
+
+ 3. Support for the identification functionality should be easy to
+ implement and easy to enable. It must be easy to disable and
+ should lend itself to access controls on who can query for it.
+
+ 4. It should be possible to return a unique identifier for a server
+ without requiring the exposure of information that may be non-
+ public and considered sensitive by the operator, such as a
+ hostname or unicast IP address maintained for administrative
+ purposes.
+
+ 5. It should be possible to authenticate the received data by some
+ mechanism analogous to those provided by DNSSEC. In this
+ context, the need could be met by including encryption options in
+ the specification of a new mechanism.
+
+ 6. The identification mechanism should not be implementation-
+ specific.
+
+
+
+
+
+
+
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 6]
+
+Internet-Draft Serverid March 2006
+
+
+3. IANA Considerations
+
+ This document proposes no specific IANA action. Protocol extensions,
+ if any, to meet the requirements described are out of scope for this
+ document. A proposed extension, specified and adopted by normal IETF
+ process, is described in [NSID], including relevant IANA action.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 7]
+
+Internet-Draft Serverid March 2006
+
+
+4. Security Considerations
+
+ Providing identifying information as to which server is responding to
+ a particular query from a particular location in the Internet can be
+ seen as information leakage and thus a security risk. This motivates
+ the suggestion above that a new mechanism for server identification
+ allow the administrator to disable the functionality altogether or
+ partially restrict availability of the data. It also suggests that
+ the serverid data should not be readily correlated with a hostname or
+ unicast IP address that may be considered private to the nameserver
+ operator's management infrastructure.
+
+ Propagation of protocol or service meta-data can sometimes expose the
+ application to denial of service or other attack. As DNS is a
+ critically important infrastructure service for the production
+ Internet, extra care needs to be taken against this risk for
+ designers, implementors, and operators of a new mechanism for server
+ identification.
+
+ Both authentication and confidentiality of serverid data are
+ potentially of interest to administrators-- that is, operators may
+ wish to make serverid data available and reliable to themselves and
+ their chosen associates only. This would imply both an ability to
+ authenticate it to themselves and keep it private from arbitrary
+ other parties. This led to Characteristics 4 and 5 of an improved
+ solution.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 8]
+
+Internet-Draft Serverid March 2006
+
+
+5. Acknowledgements
+
+ The technique for host identification documented here was initially
+ implemented by Paul Vixie of the Internet Software Consortium in the
+ Berkeley Internet Name Daemon package. Comments and questions on
+ earlier drafts were provided by Bob Halley, Brian Wellington, Andreas
+ Gustafsson, Ted Hardie, Chris Yarnell, Randy Bush, and members of the
+ ICANN Root Server System Advisory Committee. The newest version
+ takes a significantly different direction from previous versions,
+ owing to discussion among contributors to the DNSOP working group and
+ others, particularly Olafur Gudmundsson, Ed Lewis, Bill Manning, Sam
+ Weiler, and Rob Austein.
+
+6. References
+
+ [1] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ RFC 1034, STD 0013, November 1987.
+
+ [2] Mockapetris, P., "Domain Names - Implementation and
+ Specification", RFC 1035, STD 0013, November 1987.
+
+ [3] Hardie, T., "Distributing Authoritative Name Servers via Shared
+ Unicast Addresses", RFC 3258, April 2002.
+
+ [4] ISC, "BIND 9 Configuration Reference".
+
+ [5] Austein, S., "DNS Name Server Identifier Option (NSID)",
+ Internet Drafts http://www.ietf.org/internet-drafts/
+ draft-ietf-dnsext-nsid-01.txt, January 2006.
+
+ [6] Arends, R., Austein, S., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033,
+ March 2005.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 9]
+
+Internet-Draft Serverid March 2006
+
+
+Authors' Addresses
+
+ Suzanne Woolf
+ Internet Systems Consortium, Inc.
+ 950 Charter Street
+ Redwood City, CA 94063
+ US
+
+ Phone: +1 650 423-1333
+ Email: woolf@isc.org
+ URI: http://www.isc.org/
+
+
+ David Conrad
+ Nominum, Inc.
+ 2385 Bay Road
+ Redwood City, CA 94063
+ US
+
+ Phone: +1 1 650 381 6003
+ Email: david.conrad@nominum.com
+ URI: http://www.nominum.com/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 10]
+
+Internet-Draft Serverid March 2006
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+Disclaimer of Validity
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Copyright Statement
+
+ Copyright (C) The Internet Society (2006). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+
+Acknowledgment
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+Woolf & Conrad Expires September 6, 2006 [Page 11]
+
+
diff --git a/doc/draft/draft-ietf-enum-e164-gstn-np-05.txt b/doc/draft/draft-ietf-enum-e164-gstn-np-05.txt
new file mode 100644
index 0000000..3353b3b
--- /dev/null
+++ b/doc/draft/draft-ietf-enum-e164-gstn-np-05.txt
@@ -0,0 +1,1588 @@
+
+ Mark Foster
+Internet Draft Tom McGarry
+Document: <draft-ietf-enum-e164-gstn-np-05.txt> James Yu
+ NeuStar, Inc.
+Category: Informational June 24, 2002
+
+
+ Number Portability in the GSTN: An Overview
+
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026 [RFC].
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts. Internet-Drafts are draft documents valid for a maximum of
+ six months and may be updated, replaced, or obsoleted by other
+ documents at any time. It is inappropriate to use Internet- Drafts
+ as reference material or to cite them other than as "work in
+ progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+
+ Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All rights reserved.
+
+
+ Abstract
+
+ This document provides an overview of E.164 telephone number
+ portability (NP) in the Global Switched Telephone Network (GSTN).
+ NP is a regulatory imperative seeking to liberalize local telephony
+ service competition, by enabling end-users to retain telephone
+ numbers while changing service providers. NP changes the
+ fundamental nature of a dialed E.164 number from a hierarchical
+ physical routing address to a virtual address, thereby requiring the
+ transparent translation of the later to the former. In addition,
+ there are various regulatory constraints that establish relevant
+ parameters for NP implementation, most of which are not network
+ technology specific. Consequently, the implementation of NP
+ behavior consistent with applicable regulatory constraints, as well
+ as the need for interoperation with the existing GSTN NP
+ implementations, are relevant topics for numerous areas of IP
+ telephony work-in-progress at IETF.
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 1]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+
+ Table of Contents
+
+ 1. Introduction ............................................... 2
+ 2. Abbreviations and Acronyms ................................. 4
+ 3. Types of Number Portability ................................ 5
+ 4. Service Provider Number Portability Schemes ................ 7
+ 4.1 All Call Query (ACQ) .................................. 7
+ 4.2 Query on Release (QoR) ................................ 8
+ 4.3 Call Dropback ......................................... 9
+ 4.4 Onward Routing (OR) ................................... 9
+ 4.5 Comparisons of the Four Schemes ....................... 10
+ 5. Database Queries in the NP Environment ..................... 11
+ 5.1 U.S. and Canada ....................................... 12
+ 5.2 Europe ................................................ 13
+ 6. Call Routing in the NP Environment ......................... 14
+ 6.1 U.S. and Canada ....................................... 14
+ 6.2 Europe ................................................ 15
+ 7. NP Implementations for Geographic E.164 Numbers ............ 17
+ 8. Number Conservation Method Enabled By NP ................... 20
+ 8.1 Block Pooling ......................................... 20
+ 8.2 ITN Pooling ........................................... 21
+ 9. Potential Implications ..................................... 21
+ 10. Security Considerations .................................... 24
+ 11. IANA Considerations ........................................ 24
+ 12. Normative References ....................................... 24
+ 13. Informative References ..................................... 25
+ 14. Acknowledgement ............................................ 25
+ 15. AuthorsË Addresses ......................................... 25
+
+
+
+1. Introduction
+
+ This document provides an overview of E.164 telephone number
+ portability in the Global Switched Telephone Network (GSTN). There
+ are considered to be three types of number portability (NP): service
+ provider portability (SPNP), location portability (not to be
+ confused with terminal mobility), and service portability.
+
+ Service provider portability (SPNP), the focus of the present draft,
+ is a regulatory imperative in many countries seeking to liberalize
+ telephony service competition, especially local service.
+ Historically, local telephony service (as compared to long distance
+ or international service) has been regulated as a utility-like form
+ of service. While a number of countries had begun liberalization
+ (e.g. privatization, de-regulation, or re-regulation) some years
+ ago, the advent of NP is relatively recent (since ~1995).
+
+ E.164 numbers can be non-geographic and geographic numbers. Non-
+ geographic numbers do not reveal the locations information of those
+ numbers. Geographic E.164 numbers were intentionally designed as
+ hierarchical routing addresses which could systematically be digit-
+ analyzed to ascertain the country, serving network provider, serving
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 2]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ end-office switch, and specific line of the called party. As such,
+ without NP a subscriber wishing to change service providers would
+ incur a number change as a consequence of being served off of a
+ different end-office switch operated by the new service provider.
+ The cost and convenience impact to the subscriber of changing
+ numbers is seen as barrier to competition. Hence NP has become
+ associated with GSTN infrastructure enhancements associated with a
+ competitive environment driven by regulatory directives.
+
+ Forms of SPNP have been deployed or are being deployed widely in the
+ GSTN in various parts of the world, including the U.S., Canada,
+ Western Europe, Australia, and the Pacific Rim (e.g. Hong Kong).
+ Other regions, such as South America (e.g. Brazil) are actively
+ considering it.
+
+ Implementation of NP within a national telephony infrastructure
+ entails potentially significant changes to numbering administration,
+ network element signaling, call routing and processing, billing,
+ service management, and other functions.
+
+ NP changes the fundamental nature of a dialed E.164 number from a
+ hierarchical physical routing address to a virtual address. NP
+ implementations attempt to encapsulate the impacts to the GSTN and
+ make NP transparent to subscribers by incorporating a translation
+ function to map a dialed, potentially ported E.164 address, into a
+ network routing address (either a number prefix or another E.164
+ address) which can be hierarchically routed.
+
+ This is roughly analogous to the use of network address translation
+ on IP addresses to enable IP address portability by containing the
+ impact of the address change to the edge of the network and retain
+ the use of CIDR blocks in the core which can be route aggregated by
+ the network service provider to the rest of the internet.
+
+ NP bifurcates the historical role of a subscriberËs E.164 address
+ into two or more data elements (a dialed or virtual address, and a
+ network routing address) that must be made available to network
+ elements through an NP translations database, carried by forward
+ call signaling, and recorded on call detail records. Not only is
+ call processing and routing affected, but also so is SS7/C7
+ messaging. A number of TCAP-based SS7 messaging sets utilize an
+ E.164 address as an application-level network element address in the
+ global title address (GTA) field of the SCCP message header.
+ Consequently, SS7/C7 signaling transfer points (STPs) and gateways
+ need to be able to perform n-digit global title translation (GTT) to
+ translate a dialed E.164 address into its network address
+ counterpart via the NP database.
+
+ In addition, there are various national regulatory constraints that
+ establish relevant parameters for NP implementation, most of which
+ are not network technology specific. Consequently, implementations
+ of NP behavior in IP telephony consistent with applicable regulatory
+ constraints, as well as the need for interoperation with the
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 3]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ existing GSTN NP implementations, are relevant topics for numerous
+ areas of IP telephony work-in-progress at IETF.
+
+ This document describes three types of number portability and the
+ four schemes that have been standardized to support SPNP for
+ geographic E.164 numbersspecifically. Following that, specific
+ information regarding the call routing and database query
+ implementations are described for several regions (North American
+ and Europe) and industries (wireless vs. wireline). The Number
+ Portability Database (NPDB) interfaces and the call routing schemes
+ that are used in the North America and Europe are described to show
+ the variety of standards that may be implemented worldwide. A
+ glance of the NP implementations worldwide is provided. Number
+ pooling is briefly discussed to show how NP is being enhanced in the
+ U.S. to conserve North American area codes. The conclusion briefly
+ touches the potential impacts of NP on IP & Telecommunications
+ Interoperability. Appendix A provides some specific technical and
+ regulatory information on NP in North America. Appendix B describes
+ the number portability administration process that manages the
+ number portability database in North America.
+
+
+2. Abbreviations and Acronyms
+
+ ACQ All Call Query
+ AIN Advanced Intelligent Network
+ AMPS Advanced Mobile Phone System
+ ANSI American National Standards Institute
+ CDMA Code Division Multiple Access
+ CdPA Called Party Address
+ CdPN Called Party Number
+ CH Code Holder
+ CMIP Common Management Information Protocol
+ CS1 Capability Set 1
+ CS2 Capability Set 2
+ DN Directory Number
+ DNS Domain Name System
+ ETSI European Technical Standards Institute
+ FCI Forward Call Indicator
+ GAP Generic Address Parameter
+ GMSC Gateway Mobile Services Switching Center or Gateway Mobile
+ Switching Center
+ GSM Global System for Mobile Communications
+ GSTN Global Switched Telephone Network
+ GW Gateways
+ HLR Home Location Register
+ IAM Initial Address Message
+ IETF Internet Engineering Task Force
+ ILNP Interim LNP
+ IN Intelligent Network
+ INAP Intelligent Network Application Part
+ INP Interim NP
+ IP Internet Protocol
+ IS-41 Interim Standards Number 41
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 4]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ ISDN Integrated Services Digital Network
+ ISUP ISDN User Part
+ ITN Individual Telephony Number
+ ITU International Telecommunication Union
+ ITU-TS ITU-Telecommunication Sector
+ LDAP Lightweight Directory Access Protocol
+ LEC Local Exchange Carrier
+ LERG Local Exchange Routing Guide
+ LNP Local Number Portability
+ LRN Location Routing Number
+ MAP Mobile Application Part
+ MNP Mobile Number Portability
+ MSRN Mobile Station Roaming Number
+ MTP Message Transfer Part
+ NANP North American Numbering Plan
+ NP Number Portability
+ NPDB Number Portability Database
+ NRN Network Routing Number
+ OR Onward Routing
+ OSS Operation Support System
+ PCS Personal Communication Services
+ PNTI Ported Number Translation Indicator
+ PODP Public Office Dialing Plan
+ PUC Public Utility Commission
+ QoR Query on Release
+ RN Routing Number
+ RTP Return to Pivot
+ SCCP Signaling Connection Control Part
+ SCP Service Control Point
+ SIP Session Initiation Protocol
+ SMR Special Mobile Radio
+ SMS Service Management System
+ SPNP Service Provider Number Portability
+ SRF Signaling Relaying Function
+ SRI Send Routing Information
+ SS7 Signaling System Number 7
+ STP Signaling Transfer Point
+ TCAP Transaction Capabilities Application Part
+ TDMA Time Division Multiple Access
+ TN Telephone Number
+ TRIP Telephony Routing Information Protocol
+ URL Universal Resource Locator
+ U.S. United States
+
+
+3. Types of Number Portability
+
+ As there are several types of E.164 numbers (telephone numbers, or
+ just TN) in the GSTN, there are correspondingly several types of
+ E.164 NP in the GSTN. First there are so-call non-geographic E.164
+ numbers, commonly used for service-specific applications such as
+ freephone (800 or 0800). Portability of these numbers is called
+ non-geographic number portability (NGNP). NGNP, for example, was
+ deployed in the U.S. in 1986-92.
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 5]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+
+ Geographic number portability, which includes traditional fixed or
+ wireline numbers as well as mobile numbers which are allocated out
+ of geographic number range prefixes, is called NP or GNP or in the
+ U.S. local number portability (LNP).
+
+ Number portability allows the telephony subscribers in the Global
+ Switched Telephone Network (GSTN) to keep their phone numbers when
+ they change their service providers or subscribed services, or when
+ they move to a new location.
+
+ The ability to change the service provider while keeping the same
+ phone number is called service provider portability (SPNP) also
+ known as "operator portability."
+
+ The ability to change the subscriberËs fixed service location while
+ keeping the same phone number is called location portability.
+
+ The ability to change the subscribed services (e.g., from the plain
+ old telephone service to Integrated Services Digital Network (ISDN)
+ services) while keeping the same phone number is called service
+ portability. Another aspect of service portability is to allow the
+ subscribers to enjoy the subscribed services in the same way when
+ they roam outside their home networks as is supported by the
+ cellular/wireless networks.
+
+ In addition, mobile number portability (MNP) refers to specific NP
+ implementation in mobile networks either as part of a broader NP
+ implementation in the GSTN or on a stand-alone basis. Where
+ interoperation of LNP and MNP is supported, service portability
+ between fixed and mobile service types is possible.
+
+ At present, SPNP has been the primary form of NP deployed due to its
+ relevance in enabling local service competition.
+
+ Also in use in the GSTN are the terms interim NP (INP) or Interim
+ LNP (ILNP) and true NP. Interim NP usually refers to the use of
+ remote call forwarding-like measures to forward calls to ported
+ numbers through the donor network to the new service network. These
+ are considered interim relative to true NP, which seeks to remove
+ the donor network or old service provider from the call or signaling
+ path altogether. Often the distinction between interim and true NP
+ is a national regulatory matter relative to the
+ technical/operational requirements imposed on NP in that country.
+
+ Implementations of true NP in certain countries (e.g. U.S., Canada,
+ Spain, Belgium, Denmark) may pose specific requirements for IP
+ telephony implementations as a result of regulatory and industry
+ requirements for providing call routing and signaling independent of
+ the donor network or last previous serving network.
+
+
+
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 6]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+
+4. Service Provider Number Portability Schemes
+
+ Four schemes can be used to support service provider portability and
+ are briefly described below. But first, some further terms are
+ introduced.
+
+ The donor network is the network that first assigned a telephone
+ number (e.g., TN +1-202-533-1234) to a subscriber, out of a number
+ range administratively (e.g., +1 202-533) assigned to it. The
+ current service provider (new SP) or new serving network is the
+ network that currently serves the ported number. The old serving
+ network (or old SP) is the network that previously served the ported
+ number before the number was ported to the new serving network.
+ Since a TN can port a number of times, the old SP is not necessarily
+ the same as the donor network, except for the first time the TN
+ ports away, or if the TN ports back into the donor network and away
+ again. While the new SP and old SP roles are transitory as a TN
+ ports around, the donor network is always the same for any
+ particular TN based on the service provider to whom the subtending
+ number range was administratively assigned. See the discussion
+ below on number pooling, as this enhancement to NP further
+ bifurcates the role of donor network into two (the number range or
+ code holder network, and the block holder network).
+
+ To simplify the illustration, all the transit networks are ignored,
+ the originating or donor network is the one that performs the
+ database queries or call redirection, and the dialed directory
+ number (TN) has been ported out of the donor network before.
+
+ It is assumed that the old serving network, the new serving network
+ and the donor network are different networks so as to show which
+ networks are involved in call handling and routing and database
+ queries in each of four schemes. Please note that the port of the
+ number (process of moving it from one network to another) happened
+ prior to the call setup and is not included in the call steps.
+ Information carried in the signaling messages to support each of the
+ four schemes is not discussed to simplify the explanation.
+
+
+4.1 All Call Query (ACQ)
+
+ Figure 1 shows the call steps for the ACQ scheme. Those call steps
+ are as follows:
+
+ (1) The Originating Network receives a call from the caller and
+ sends a query to a centrally administered Number Portability
+ Database (NPDB), a copy of which is usually resident on a
+ network element within its network or through a third party
+ provider.
+ (2) The NPDB returns the routing number associated with the dialed
+ directory number. The routing number is discussed later in
+ Section 6.
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 7]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ (3) The Originating Network uses the routing number to route the
+ call to the new serving network.
+
+
+ +-------------+ +-----------+ Number +-----------+
+ | Centralized | | New Serv. | ported | Old Serv. |
+ | NPDB | +-------->| Network |<------------| Network |
+ +-------------+ | +-----------+ +-----------+
+ ^ | |
+ | | |
+ 1| | 3.|
+ | | 2. |
+ | | |
+ | v |
+ +----------+ | +----------+ +----------+
+ | Orig. |------+ | Donor | | Internal |
+ | Network | | Network | | NPDB |
+ +----------+ +----------+ +----------+
+
+
+ Figure 1 - All Call Query (ACQ) Scheme.
+
+
+4.2 Query on Release (QoR)
+
+ Figure 2 shows the call steps for the QoR scheme. Those call steps
+ are as follows:
+
+
+ +-------------+ +-----------+ Number +-----------+
+ | Centralized | | New Serv. | ported | Old Serv. |
+ | NPDB | | Network |<------------| Network |
+ +-------------+ +-----------+ +-----------+
+ ^ | ^
+ | | 4. |
+ 3.| | 5. |
+ | | +----------------------+
+ | | |
+ | v |
+ +----------+ 2. +----------+ +----------+
+ | Orig. |<---------------| Donor | | Internal |
+ | Network |--------------->| Network | | NPDB |
+ +----------+ 1. +----------+ +----------+
+
+
+ Figure 2 - Query on Release (QoR) Scheme.
+
+ (1) The Originating Network receives a call from the caller and
+ routes the call to the donor network.
+ (2) The donor network releases the call and indicates that the
+ dialed directory number has been ported out of that switch.
+ (3) The Originating Network sends a query to its copy of the
+ centrally administered NPDB.
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 8]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ (4) The NPDB returns the routing number associated with the dialed
+ directory number.
+ (5) The Originating Network uses the routing number to route the
+ call to the new serving network.
+
+
+4.3 Call Dropback
+
+ Figure 3 shows the call steps for the Dropback scheme. This scheme
+ is also known as "Return to Pivot (RTP)." Those call steps are as
+ follows:
+
+ (1) The Originating Network receives a call from the caller and
+ routes the call to the donor network.
+ (2) The donor network detects that the dialed directory number has
+ been ported out of the donor switch and checks with an internal
+ network-specific NPDB.
+ (3) The internal NPDB returns the routing number associated with the
+ dialed directory number.
+ (4) The donor network releases the call by providing the routing
+ number.
+ (5) The Originating Network uses the routing number to route the
+ call to the new serving network.
+
+ +-------------+ +-----------+ Number +-----------+
+ | Centralized | | New Serv. | porting | Old Serv. |
+ | NPDB | | Network |<------------| Network |
+ +-------------+ +-----------+ +-----------+
+ /\
+ |
+ 5. |
+ +------------------------+
+ |
+ |
+ +----------+ 4. +----------+ 3. +----------+
+ | Orig. |<---------------| Donor |<----------| Internal |
+ | Network |--------------->| Network |---------->| NPDB |
+ +----------+ 1. +----------+ 2. +----------+
+
+
+ Figure 3 - Dropback Scheme.
+
+
+4.4 Onward Routing (OR)
+
+ Figure 4 shows the call steps for the OR scheme. Those call steps
+ are as follows:
+
+ (1) The Originating Network receives a call from the caller and
+ routes the call to the donor network.
+ (2) The donor network detects that the dialed directory number has
+ been ported out of the donor switch and checks with an internal
+ network-specific NPDB.
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 9]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ (3) The internal NPDB returns the routing number associated with the
+ dialed directory number.
+ (4) The donor network uses the routing number to route the call to
+ the new serving network.
+
+
+ +-------------+ +-----------+ Number +-----------+
+ | Centralized | | New Serv. | porting | Old Serv. |
+ | NPDB | | Network |<------------| Network |
+ +-------------+ +-----------+ +-----------+
+ /\
+ |
+ 4.|
+ |
+ +----------+ +----------+ 3. +----------+
+ | Orig. | | Donor |<----------| Internal |
+ | Network |--------------->| Network |---------->| NPDB |
+ +----------+ 1. +----------+ 2. +----------+
+
+
+ Figure 4 - Onward Routing (OR) Scheme.
+
+4.5 Comparisons of the Four Schemes
+
+ Only the ACQ scheme does not involve the donor network when routing
+ the call to the new serving network of the dialed ported number.
+ The other three schemes involve call setup to or signaling with the
+ donor network.
+
+ Only the OR scheme requires the setup of two physical call segments,
+ one from the Originating Network to the donor network and the other
+ from the donor network to the new serving network. The OR scheme is
+ the least efficient in terms of using the network transmission
+ facilities. The QoR and Dropback schemes set up calls to the donor
+ network first but release the call back to the Originating Network
+ that then initiates a new call to the Current Serving Network. For
+ the QoR and Dropback schemes, circuits are still reserved one by one
+ between the Originating Network and the donor network when the
+ Originating Network sets up the call towards the donor network.
+ Those circuits are released one by one when the call is released
+ from the donor network back to the Originating Network. The ACQ
+ scheme is the most efficient in terms of using the switching and
+ transmission facilities for the call.
+
+ Both the ACQ and QoR schemes involve Centralized NPDBs for the
+ Originating Network to retrieve the routing information.
+ Centralized NPDB means that the NPDB contains ported number
+ information from multiple networks. This is in contrast to the
+ internal network-specific NPDB that is used for the Dropback and OR
+ schemes. The internal NPDB only contains information about the
+ numbers that were ported out of the donor network. The internal
+ NPDB can be a stand-alone database that contains information about
+ all or some ported-out numbers from the donor network. It can also
+ reside on the donor switch and only contains information about those
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 10]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ numbers ported out of the donor switch. In that case, no query to a
+ stand-alone internal NPDB is required. The donor switch for a
+ particular phone number is the switch to which the number range is
+ assigned from which that phone number was originally assigned.
+
+ For example, number ranges in the North American Numbering Plan
+ (NANP) are usually assigned in the form of central office codes (CO
+ codes) comprising a six-digit prefix formatted as a NPA+NXX. Thus a
+ switch serving +1-202-533 would typically serve +1-202-533-0000
+ through +1-202-533-9999. In major cities, switches usually host
+ several CO codes. NPA stands for Numbering Plan Area that is also
+ known as the area code. It is three-digit long and has the format
+ of NXX where N is any digit from 2 to 9 and X is any digit from 0 to
+ 9. NXX in the NPA+NXX format is known as the office code that has
+ the same format as the NPA. When a NPA+NXX code is set as
+ Ÿportable÷ in the Local Exchange Routing Guide (LERG), it becomes a
+ "portable NPA+NXX" code.
+
+ Similarly, in other national E.164 numbering plans, number ranges
+ cover a contiguous range of numbers within that range. Once a
+ number within that range has ported away from the donor network, all
+ numbers in that range are considered potentially ported and should
+ be queried in the NPDB.
+
+ The ACQ scheme has two versions. One version is for the Originating
+ Network to always query the NPDB when a call is received from the
+ caller regardless whether the dialed directory number belongs to any
+ number range that is portable or has at least one number ported out.
+ The other version is to check whether the dialed directory number
+ belongs to any number range that is portable or has at least one
+ number ported out. If yes, an NPDB query is sent. If not, no NPDB
+ query is sent. The former performs better when there are many
+ portable number ranges. The latter performs better when there are
+ not too many portable number ranges at the expense of checking every
+ call to see whether NPDB query is needed. The latter ACQ scheme is
+ similar to the QoR scheme except that the QoR scheme uses call setup
+ and relies on the donor network to indicate "number ported out"
+ before launching the NPDB query.
+
+
+5. Database Queries in the NP Environment
+
+ As indicated earlier, the ACQ and QoR schemes require that a switch
+ query the NPDB for routing information. Various standards have been
+ defined for the switch-to-NPDB interface. Those interfaces with
+ their protocol stacks are briefly described below. The term "NPDB"
+ is used for a stand-alone database that may support just one or some
+ or all of the interfaces mentioned below. The NPDB query contains
+ the dialed directory number and the NPDB response contains the
+ routing number. There are certainly other information that is sent
+ in the query and response. The primary interest is to get the
+ routing number from the NPDB to the switch for call routing.
+
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 11]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+5.1 U.S. and Canada
+
+ One of the following five NPDB interfaces can be used to query an
+ NPDB:
+
+ (a) Advanced Intelligent Network (AIN) using the American National
+ Standards Institute (ANSI) version of the Intelligent Network
+ Application Part (INAP) [ANSI SS] [ANSI DB]. The INAP is
+ carried on top of the protocol stack that includes the (ANSI)
+ Message Transfer Part (MTP) Levels 1 through 3, ANSI Signaling
+ Connection Control Part (SCCP), and ANSI Transaction
+ Capabilities Application Part (TCAP). This interface can be
+ used by the wireline or wireless switches, is specific to the NP
+ implementation in North America, and is modeled on the Public
+ Office Dialing Plan (PODP) trigger defined in the Advanced
+ Intelligent Network (AIN) 0.1 call model.
+
+ (b) Intelligent Network (IN), which is similar to the one used for
+ querying the 800 databases. The IN protocol is carried on top
+ of the protocol stack that includes the ANSI MTP Levels 1
+ through 3, ANSI SCCP, and ANSI TCAP. This interface can be used
+ by the wireline or wireless switches.
+
+ (c) ANSI IS-41 [IS41] [ISNP], which is carried on top of the
+ protocol stack that includes the ANSI MTP Levels 1 through 3,
+ ANSI SCCP, and ANSI TCAP. This interface can be used by the IS-
+ 41 based cellular/Personal Communication Services (PCS) wireless
+ switches (e.g., AMPS, TDMA and CDMA). Cellular systems use
+ spectrum at 800 MHz range and PCS systems use spectrum at 1900
+ MHz range.
+
+ (d) Global System for Mobile Communication Mobile Application Part
+ (GSM MAP) [GSM], which is carried on top of the protocol stack
+ that includes the ANSI MTP Levels 1 through 3, ANSI SCCP, and
+ International Telecommunication Union - Telecommunication Sector
+ (ITU-TS) TCAP. It can be used by the PCS1900 wireless switches
+ that are based on the GSM technologies. GSM is a series of
+ wireless standards defined by the European Telecommunications
+ Standards Institute (ETSI).
+
+ (e) ISUP triggerless translation. NP translations are performed
+ transparently to the switching network by the signaling network
+ (e.g. Signaling Transfer Points (STPs) or signaling gateways).
+ ISUP IAM messages are examined to determine if the CdPN field
+ has already been translated, and if not, an NPDB query is
+ performed, and the appropriate parameters in the IAM message
+ modified to reflect the results of the translation. The
+ modified IAM message is forwarded by the signaling node on to
+ the designated DPC in a transparent manner to continue call
+ setup. The NPDB can be integrated with the signaling node or be
+ accessed via an API locally or by a query to a remote NPDB using
+ a proprietary protocol or the schemes described above.
+
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 12]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ Wireline switches have the choice of using either (a), (b), or (e).
+ IS-41 based wireless switches have the choice of using (a), (b),
+ (c), or (e). PCS1900 wireless switches have the choice of using
+ (a), (b), (d), or (e). In the United States, service provider
+ portability will be supported by both the wireline and wireless
+ systems, not only within the wireline or wireless domain but also
+ across the wireline/wireless boundary. However, this is not true in
+ Europe where service provider portability is usually supported only
+ within the wireline or wireless domain, not across the
+ wireline/wireless boundary due to explicit use of service-specific
+ number range prefixes. The reason is to avoid caller confusion
+ about the call charge. GSM systems in Europe are assigned
+ distinctive destination network codes, and the caller pays a higher
+ charge when calling a GSM directory number.
+
+
+5.2 Europe
+
+ One of the following two interfaces can be used to query an NPDB:
+
+ (a) Capability Set 1 (CS1) of the ITU-TS INAP [CS1], which is
+ carried on top of the protocol stack that includes the ITU-TS
+ MTP Levels 1 through 3, ITU-TS SCCP, and ITU-TS TCAP.
+
+ (b) Capability Set 2 (CS2) of the ITU-TS INAP [CS2], which is
+ carried on top of the protocol stack that includes the ITU-TS
+ MTP Levels 1 through ITU-TS MTP Levels 1 through 3, ITU-TS SCCP,
+ and ITU-TS TCAP.
+
+ Wireline switches have the choice of using either (a) or (b);
+ however, all the implementations in Europe so far are based on CS1.
+ As indicated earlier that number portability in Europe does not go
+ across the wireline/wireless boundary. The wireless switches can
+ also use (a) or (b) to query the NPDBs if those NPDBs contains
+ ported wireless directory numbers. The term "Mobile Number
+ Portability (MNP)" is used for the support of service provider
+ portability by the GSM networks in Europe.
+
+ In most, if not all, cases in Europe, the calls to the wireless
+ directory numbers are routed to the wireless donor network first.
+ Over there, an internal NPDB is queried to determine whether the
+ dialed wireless directory number has been ported out or not. In
+ this case, the interface to the internal NPDB is not subject to
+ standardization.
+
+ MNP in Europe can also be supported via MNP Signaling Relay Function
+ (MNP-SRF). Again, an internal NPDB or a database integrated at the
+ MNP-SRF is used to modify the SCCP Called Party Address parameter in
+ the GSM MAP messages so that they can be re-directed to the wireless
+ serving network. Call routing involving MNP will be explained in
+ Section 6.2.
+
+
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 13]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+6. Call Routing in the NP Environment
+
+ This section discusses the call routing after the routing
+ information has been retrieved either through an NPDB query or an
+ internal database lookup at the donor switch, or from the Integrated
+ Services Digital Network User Part (ISUP) signaling message (e.g.,
+ for the Dropback scheme). For the ACQ, QoR and Dropback schemes, it
+ is the Originating Network that has the routing information and is
+ ready to route the call. For the OR scheme, it is the donor network
+ that has the routing information and is ready to route the call.
+
+ A number of triggering schemes may be employed that determine where
+ in the call path the NPDB query is performed. In the U.S. an ŸN-1÷
+ policy is used, which essentially says that for domestic calls, the
+ originating local carriers performs the query, otherwise, the long
+ distance carrier is expected to. To ensure independence of the
+ actual trigger policy employed in any one carrier, forward call
+ signaling is used to flag that an NPDB query has already been
+ performed and to therefore suppress any subsequent NP triggers that
+ may be encountered in downstream switches, in downstream networks.
+ This allows the earliest able network in the call path to perform
+ the query without introducing additional costs and call setup delays
+ were redundant queries performed downstream.
+
+
+6.1 U.S. and Canada
+
+ In the U.S. and Canada, a ten-digit North American Numbering Plan
+ (NANP) number called Location Routing Number (LRN) is assigned to
+ every switch involved in NP. In the NANP, a switch is not reachable
+ unless it has a unique number range (CO code) assigned to it.
+ Consequently, the LRN for a switch is always assigned out of a CO
+ code that is assigned to that switch.
+
+ The LRN assigned to a switch currently serving a particular ported
+ telephone number is returned as the network routing address in the
+ NPDB response. The service portability scheme that was adopted in
+ the North America is very often referred to as the LRN scheme or
+ method.
+
+ LRN serves as a network address for terminating calls served off
+ that switch using ported numbers. The LRN is assigned by the switch
+ operator using any of the unique CO codes (NPA+NXX) assigned to that
+ switch. The LRN is considered a non-dialable address, as the same
+ 10-digit number value may be assigned to a line on that switch. A
+ switch may have more than one LRN.
+
+ During call routing/processing, a switch performs an NPDB query to
+ obtain the LRN associated with the dialed directory number. NPDB
+ queries are performed for all the dialed directory numbers whose
+ NPA+NXX codes are marked as portable NPA+NXX at that switch. When
+ formulating the ISUP Initial Address Message (IAM) to be sent to the
+ next switch, the switch puts the ten-digit LRN in the ISUP Called
+ Party Number (CdPN) parameter and the originally dialed directory
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 14]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ number in the ISUP Generic Address parameter (GAP). A new code in
+ the GAP was defined to indicate that the address information in the
+ GAP is the dialed directory number. A new bit in the ISUP Forward
+ Call Indicator (FCI) parameter, the Ported Number Translation
+ Indicator (PNTI) bit, is set to imply that NPDB query has already
+ been performed. All the switches in the downstream will not perform
+ the NPDB query if the PNTI bit is set.
+
+ When the terminating switch receives the IAM and sees the PNTI bit
+ in the FCI parameter set and its own LRN in the CdPN parameter, it
+ retrieves the originally dialed directory number from the GAP and
+ uses the dialed directory number to terminate the call.
+
+ A dialed directory number with a portable NPA+NXX does not imply
+ that directory number has been ported. The NPDBs currently do not
+ store records for non-ported directory numbers. In that case, the
+ NPDB will return the same dialed directory number instead of the
+ LRN. The switch will then set the PNTI bit but keep the dialed
+ directory number in the CdPN parameter.
+
+ In the real world environment, the Originating Network is not always
+ the one that performs the NPDB query. For example, it is usually
+ the long distance carriers that query the NPDBs for long distance
+ calls. In that case, the Originating Network operated by the local
+ exchange carrier (LEC) simply routes the call to the long distance
+ carrier that is to handle that call. A wireless network acting as
+ the Originating Network can also route the call to the
+ interconnected local exchange carrier network if it does not want to
+ support the NPDB interface at its mobile switches.
+
+
+6.2 Europe
+
+ In some European countries, a routing number is prefixed to the
+ dialed directory number. The ISUP CdPN parameter in the IAM will
+ contain the routing prefix and the dialed directory number. For
+ example, United Kingdom uses routing prefixes with the format of
+ 5XXXXX and Italy uses C600XXXXX as the routing prefix. The networks
+ use the information in the ISUP CdPN parameter to route the call to
+ the New/Current Serving Network.
+
+ The routing prefix can identify the Current Serving Network or the
+ Current Serving Switch of a ported number. For the former case,
+ another query to the "internal" NPDB at the Current Serving Network
+ is required to identify the Current Serving Switch before routing
+ the call to that switch. This shields the Current Serving Switch
+ information for a ported number from the other networks at the
+ expense of an additional NPDB query. Another routing number, may be
+ meaningful within the Current Serving Network, will replace the
+ previously prefixed routing number in the ISUP CdPN parameter. For
+ the latter case, the call is routed to the Current Serving Switch
+ without an additional NPDB query.
+
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 15]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ When the terminating switch receives the IAM and sees its own
+ routing prefix in the CdPN parameter, it retrieves the originally
+ dialed directory number after the routing prefix, and uses the
+ dialed directory number to terminate the call.
+
+ The call routing example described above shows one of the three
+ methods that can be used to transport the Directory Number (DN) and
+ the Routing Number (RN) in the ISUP IAM message. In addition, some
+ other information may be added/modified as is listed in the ETSI 302
+ 097 document [ETSIISUP], which is based on the ITU-T Recommendation
+ Q.769.1 [ITUISUP]. The three methods and the enhancements in the
+ ISUP to support number portability are briefly described below
+
+ (a) Two separate parameters with the CdPN parameter containing the
+ RN and a new Called Directory Number (CdDN) parameter containing
+ the DN. A new value for the Nature of Address (NOA) indicator in
+ the CdPN parameter is defined to indicate that the RN is in the
+ CdPN parameter. The switches use the CdPN parameter to route the
+ call as is done today.
+
+ (b) Two separate parameters with the CdPN parameter containing the
+ DN and a new Network Routing Number (NRN) parameter containing
+ the RN. This method requires that the switches use the NRN
+ parameter to route the call.
+
+ (c) Concatenated parameter with the CdPN parameter containing the RN
+ plus the DN. A new Nature of Address (NOA) indicator in the CdPN
+ parameter is defined to indicate that the RN is concatenated with
+ the DN in the CdPN parameter. Some countries may not use new NOA
+ value because the routing prefix does not overlap with the dialed
+ directory numbers. But if the routing prefix overlaps with the
+ dialed directory numbers, a new NOA value must be assigned. For
+ example, Spain uses "XXXXXX" as the routing prefix to identify
+ the new serving network and uses a new NOA value of 126.
+
+ There is also a network option to add a new ISUP parameter called
+ Number Portability Forwarding Information parameter. This parameter
+ has a four-bit Number Portability Status Indicator field that can
+ provide an indication whether number portability query is done for
+ the called directory number and whether the called directory number
+ is ported or not if the number portability query is done.
+
+ Please note that all those NP enhancements for a ported number can
+ only be used in the country that defined them. This is because
+ number portability is supported within a nation. Within each
+ nation, the telecommunications industry or the regulatory bodies can
+ decide which method or methods to use. Number portability related
+ parameters and coding are usually not passed across the national
+ boundaries unless the interconnection agreements allow that. For
+ example, a UK routing prefix can only be used in UK, and would cause
+ routing problem if it appears outside UK.
+
+
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 16]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ As indicated earlier, an originating wireless network can query the
+ NPDB and concatenate the RN with DN in the CdPN parameter and route
+ the call directly to the Current Serving Network.
+
+ If NPDBs do not contain information about the wireless directory
+ numbers, the call, originated from either a wireline or a wireless
+ network, will be routed to the Wireless donor network. Over there,
+ an internal NPDB is queried to retrieve the RN that then is
+ concatenated with the DN in the CdPN parameter.
+
+ There are several ways of realizing MNP. When MNP-SRF is supported,
+ the Gateway Mobile Services Switching Center (GMSC) at the wireless
+ donor network, when receiving a call from the wireline network, can
+ send the GSM MAP Send Routing Information (SRI) message to the MNP-
+ SRF. The MNP-SRF interrogates an internal or integrated NPDB for
+ the RN of the MNP-SRF of the wireless Current Serving Network and
+ prefixes the RN to the dialed wireless directory number in the
+ global title address information in the SCCP Called Party Address
+ (CdPA) parameter. This SRI message will be routed to the MNP-SRF of
+ the wireless Current Serving Network, which then responds with an
+ acknowledgement by providing the RN plus the dialed wireless
+ directory number as the Mobile Station Roaming Number (MSRN). The
+ GMSC of the wireless donor network formulates the ISUP IAM with the
+ RN plus the dialed wireless directory number in the CdPN parameter
+ and routes the call to the wireless Current Serving Network. A GMSC
+ of the wireless Current Serving Network receives the call and sends
+ an SRI message to the associated MNP-SRF where the global title
+ address information of the SCCP CdPA parameter contains only the
+ dialed wireless directory number. The MNP-SRF then replaces the
+ global title address information in the SCCP CdPA parameter with the
+ address information associated with a Home Location Register (HLR)
+ that hosts the dialed wireless directory number and forwards the
+ message to that HLR after verifying that the dialed wireless
+ directory number is a ported-in number. The HLR then returns an
+ acknowledgement by providing an MSRN for the GMSC to route the call
+ to the MSC that currently serves the mobile station that is
+ associated with the dialed wireless directory number. Please see
+ [MNP] for details and additional scenarios.
+
+
+7. NP Implementations for Geographic E.164 Numbers
+
+ This section shows the known SPNP implementations worldwide.
+
+ +-------------+----------------------------------------------------+
+ + Country + SPNP Implementation +
+ +-------------+----------------------------------------------------+
+ + Argentina + Analyzing operative viability now. Will determine +
+ + + whether portability should be made obligatory +
+ + + after a technical solution has been determined. +
+ +-------------+----------------------------------------------------+
+ + Australia + NP supported by wireline operators since 11/30/99. +
+ + + NP among wireless operators in March/April 2000, +
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 17]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ + + but may be delayed to 1Q01. The access provider +
+ + + or long distance provider has the obligation to +
+ + + route the call to the correct destination. The +
+ + + donor network is obligated to maintain and make +
+ + + available a register of numbers ported away from +
+ + + its network. Telstra uses onward routing via an +
+ + + on-switch solution. +
+ +-------------+----------------------------------------------------+
+ + Austria + Uses onward routing at the donor network. Routing +
+ + + prefix is "86xx" where "xx" identifies the +
+ + + recipient network. +
+ +-------------+----------------------------------------------------+
+ + Belgium + ACQ selected by the industry. Routing prefix is +
+ + + "Cxxxx" where "xxxx" identifies the recipient +
+ + + switch. Another routing prefix is "C00xx" with "xx"+
+ + + identifying the recipient network. Plan to use NOA+
+ + + to identify concatenated numbers and abandon the +
+ + + hexadecimal routing prefix. +
+ +-------------+----------------------------------------------------+
+ + Brazil + Considering NP for wireless users. +
+ +-------------+----------------------------------------------------+
+ + Chile + There has been discussions lately on NP. +
+ +-------------+----------------------------------------------------+
+ + Colombia + There was an Article 3.1 on NP to support NP prior +
+ + + to December 31, 1999 when NP became technically +
+ + + possible. Regulator has not yet issued regulations +
+ + + concerning this matter. +
+ +-------------+----------------------------------------------------+
+ + Denmark + Uses ACQ. Routing number not passed between +
+ + + operators; however, NOA is set to "112" to +
+ + + indicate "ported number." QoR can be used based +
+ + + on bilateral agreements. +
+ +-------------+----------------------------------------------------+
+ + Finland + Uses ACQ. Routing prefix is "1Dxxy" where "xxy" +
+ + + identifies the recipient network and service type. +
+ +-------------+----------------------------------------------------+
+ + France + Uses onward routing. Routing prefix is "Z0xxx" +
+ + + where "xxx" identifies the recipient switch. +
+ +-------------+----------------------------------------------------+
+ + Germany + The originating network needs to do necessary +
+ + + rerouting. Operators decide their own solution(s).+
+ + + Deutsche Telekom uses ACQ. Routing prefix is +
+ + + "Dxxx" where "xxx" identifies the recipient +
+ + + network. +
+ +-------------+----------------------------------------------------+
+ + Hong Kong + Recipient network informs other networks about +
+ + + ported-in numbers. Routing prefix is "14x" where +
+ + + "14x" identifies the recipient network, or a +
+ + + routing number of "4x" plus 7 or 8 digits is used +
+ + + where "4x" identifies the recipient network and +
+ + + the rest of digits identify the called party. +
+ +-------------+----------------------------------------------------+
+ + Ireland + Operators choose their own solution but use onward +
+ + + routing now. Routing prefix is "1750" as the intra-+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 18]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ + + network routing code (network-specific) and +
+ + + "1752xxx" to "1759xxx" for GNP where "xxx" +
+ + + identifies the recipient switch. +
+ +-------------+----------------------------------------------------+
+ + Italy + Uses onward routing. Routing prefix is "C600xxxxx" +
+ + + where "xxxxx" identifies the recipient switch. +
+ + + Telecom Italia uses IN solution and other operators+
+ + + use on-switch solution. +
+ +-------------+----------------------------------------------------+
+ + Japan + Uses onward routing. Donor switch uses IN to get +
+ + + routing number. +
+ +-------------+----------------------------------------------------+
+ + Mexico + NP is considered in the Telecom law; however, the +
+ + + regulator (Cofetel) or the new local entrants have +
+ + + started no initiatives on this process. +
+ +-------------+----------------------------------------------------+
+ + Netherlands + Operators decide NP scheme to use. Operators have +
+ + + chosen ACQ or QoR. KPN implemented IN solution +
+ + + similar to U.S. solution. Routing prefix is not +
+ + + passed between operators. +
+ +-------------+----------------------------------------------------+
+ + Norway + OR for short-term and ACQ for long-term. QoR is +
+ + + optional. Routing prefix can be "xxx" with NOA=8, +
+ + + or "142xx" with NOA=3 where "xxx" or "xx" +
+ + + identifies the recipient network. +
+ +------------ +----------------------------------------------------+
+ + Peru + Wireline NP may be supported in 2001. +
+ +-------------+----------------------------------------------------+
+ + Portugal + No NP today. +
+ +-------------+----------------------------------------------------+
+ + Spain + Uses ACQ. Telefonica uses QoR within its network. +
+ + + Routing prefix is "xxyyzz" where "xxyyzz" +
+ + + identifies the recipient network. NOA is set to +
+ + + 126. +
+ +-------------+----------------------------------------------------+
+ + Sweden + Standardized the ACQ but OR for operators without +
+ + + IN. Routing prefix is "xxx" with NOA=8 or "394xxx" +
+ + + with NOA=3 where "xxx" identifies the recipient +
+ + + network. But operators decide NP scheme to use. +
+ + + Telia uses onward routing between operators. +
+ +-------------+----------------------------------------------------+
+ + Switzerland + Uses OR now and QoR in 2001. Routing prefix is +
+ + + "980xxx" where "xxx" identifies the recipient +
+ + + network. +
+ +-------------+----------------------------------------------------+
+ + UK + Uses onward routing. Routing prefix is "5xxxxx" +
+ + + where "xxxxx" identifies the recipient switch. NOA +
+ + + is 126. BT uses the dropback scheme in some parts +
+ + + of its network. +
+ +-------------+----------------------------------------------------+
+ + US + Uses ACQ. "Location Routing Number (LRN)" is used +
+ + + in the Called Party Number parameter. Called party+
+ + + number is carried in the Generic Address Parameter +
+ + + Use a PNTI indicator in the Forward Call Indicator +
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 19]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ + + parameter to indicate that NPDB dip has been +
+ + + performed. +
+ +-------------+----------------------------------------------------+
+
+
+8. Number Conservation Methods Enabled by NP
+
+ In addition to porting numbers NP provides the ability for number
+ administrators to assign numbering resources to operators in smaller
+ increments. Today it is common for numbering resources to be
+ assigned to telephone operators in a large block of consecutive
+ telephone numbers (TNs). For example, in North America each of
+ these blocks contains 10,000 TNs and is of the format NXX+0000 to
+ NXX+9999. Operators are assigned a specific NXX, or block. That
+ operator is referred to as the block holder. In that block there
+ are 10,000 TNs with line numbers ranging from 0000 to 9999.
+
+ Instead of assigning an entire block to the operator NP allows the
+ administrator to assign a sub-block or even an individual telephone
+ number. This is referred to as block pooling and individual
+ telephone number (ITN) pooling, respectively.
+
+
+8.1 Block Pooling
+
+ Block Pooling refers to the process whereby the number administrator
+ assigns a range of numbers defined by a logical sub-block of the
+ existing block. Using North America as an example, block pooling
+ would allow the administrator to assign sub-blocks of 1,000 TNs to
+ multiple operators. That is, NXX+0000 to NXX+0999 can be assigned
+ to operator A, NXX+1000 to NXX+1999 can be assigned to operator B,
+ NXX-2000 to 2999 can be assigned to operator C, etc. In this
+ example block pooling divides one block of 10,000 TNs into ten
+ blocks of 1,000 TNs.
+
+ Porting the sub-blocks from the block holder enables block pooling.
+ Using the example above operator A is the block holder, as well as,
+ the holder of the first sub-block, NXX+0000 to NXX+0999. The second
+ sub-block, NXX+1000 to NXX+1999, is ported from operator A to
+ operator B. The third sub-block, NXX+2000 to NXX+2999, is ported
+ from operator A to operator C, and so on. NP administrative
+ processes and call processing will enable proper and efficient
+ routing.
+
+ From a number administration and NP administration perspective block
+ pooling introduces a new concept, that of the sub-block holder.
+ Block pooling requires coordination between the number
+ administrator, the NP administrator, the block holder, and the sub-
+ block holder. Block pooling must be implemented in a manner that
+ allows for NP within the sub-blocks. Each TN can have a different
+ serving operator, sub-block holder, and block holder.
+
+
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 20]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+8.2 ITN Pooling
+
+ ITN pooling refers to the process whereby the number administrator
+ assigns individual telephone numbers to operators. Using the North
+ American example, one block of 10,000 TNs can be divided into 10,000
+ ITNs. ITN is more commonly deployed in freephone services.
+
+ In ITN the block is not assigned to an operator but to a central
+ administrator. The administrator then assigns ITNs to operators.
+ NP administrative processes and call processing will enable proper
+ and efficient routing.
+
+
+9. Potential Implications
+
+ There are three general areas of impact to IP telephony work-in-
+ progress at IETF:
+
+ - Interoperation between NP in GSTN and IP telephony
+ - NP implementation or emulation in IP telephony
+ - Interconnection to NP administrative environment
+
+ A good understanding of how number portability is supported in the
+ GSTN is important when addressing the interworking issues between
+ IP-based networks and the GSTN. This is especially important when
+ the IP-based network needs to route the calls to the GSTN. As shown
+ in Section 5, there are a variety of standards with various protocol
+ stacks for the switch-to-NPDB interface. Not only that, the
+ national variations of the protocol standards make it very
+ complicated to deal with in a global environment. If an entity in
+ the IP-based network needs to query those existing NPDBs for routing
+ number information to terminate the calls to the destination GSTN,
+ it would be impractical, if not an impossible, job for that entity
+ to support all those interface standards to access the NPDBs in many
+ countries.
+
+ Several alternatives may address this particular problem. One
+ alternative is to use certain entities in the IP-based networks for
+ dealing with NP query, similar to the International Switches that
+ are used in the GSTN to interwork different national ISUP
+ variations. This will force signaling information associated with
+ the calls to certain NP-capable networks in the terminating GSTN to
+ be routed to those IP entities that support the NP functions. Those
+ IP entities then query the NPDBs in the terminating country. This
+ will limit the number of NPDB interfaces that certain IP entities
+ need to support. Another alternative can be to define a "common"
+ interface to be supported by all the NPDBs so that all the IP
+ entities use that standardized protocol to query them. The
+ existing NPDBs can support this additional interface, or new NPDBs
+ can be deployed that contain the same information but support the
+ common IP interface. The candidates for such a common interface
+ include Lightweight Directory Access Protocol (LDAP) and SIP
+ [SIP](e.g., using the SIP redirection capability). Certainly
+
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 21]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ another possibility is to use interworking function to convert from
+ one protocol to another.
+
+ IP-based networks can handle the domestic calls between two GSTNs.
+ If the originating GSTN has performed NPDB query, SIP will need to
+ transport and make use of some of the ISUP signaling information
+ even if ISUP signaling may be encapsulated in SIP. Also, IP-based
+ networks may perform the NPDB queries, as the N-1 carrier. In that
+ case, SIP also needs to transport the NP related information while
+ the call is being routed to the destination GSTN. There are three
+ pieces of NP related information that SIP needs to transport. They
+ are 1) the called directory number, 2) a routing number, and 3) a
+ NPDB dip indicator. The NPDB dip indicator is needed so that the
+ terminating GSTN will not perform another NPDB dip. The routing
+ number is needed so that it is used to route the call to the
+ destination network or switch in the destination GSTN. The called
+ directory number is needed so that the terminating GSTN switch can
+ terminate the call. When the routing number is present, the NPDB
+ dip indicator may not be present because there are cases where
+ routing number is added for routing the call even if NP is not
+ involved. One issue is how to transport the NP related information
+ via SIP. The SIP Universal Resource Locator (URL) is one mechanism.
+ Another better choice may be to add an extension to the "tel" URL
+ [TEL] that is also supported by SIP. Please see [TELNP] for the
+ proposed extensions to the "tel" URL to support NP and freephone
+ service. Those extensions to the "tel" URL will be automatically
+ supported by SIP because they can be carried as the optional
+ parameters in the user portion of the "sip" URL.
+
+ For a called directory number that belongs to a country that
+ supports NP, and if the IP-based network is to perform the NPDB
+ query, the logical step is to perform the NPDB dip first to retrieve
+ the routing number and use that routing number to select the correct
+ IP telephony gateways that can reach the serving switch that serves
+ the called directory number. Therefore, if the "rn" parameter is
+ present in the "tel" URL or sip URL in the SIP INVITE message, it
+ instead of the called directory number should be used for making
+ routing decisions assuming that no other higher priority routing-
+ related parameters such as the Ÿcic÷ are present. If "rn" is not
+ present, then the dialed directory number can be used as the routing
+ number for making routing decisions.
+
+ Telephony Routing Information Protocol (TRIP) [TRIP] is a policy
+ driven inter-administrative domain protocol for advertising the
+ reachability of telephony destinations between location servers, and
+ for advertising attributes of the routes to those destinations.
+ With the NP in mind, it is very important to know that it is the
+ routing number, if present, not the called directory number that
+ should be used to check against the TRIP tables for making the
+ routing decisions.
+
+ Overlap signaling exists in the GSTN today. For a call routing from
+ the originating GSTN to the IP-based network that involves overlap
+ signaling, NP will impact the call processing within the IP-based
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 22]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ networks if they must deal with the overlap signaling. The entities
+ in the IP-based networks that are to retrieve the NP information
+ (e.g., the routing number) must collect a complete called directory
+ number information before retrieving the NP information for a ported
+ number. Otherwise, the information retrieval won't be successful.
+ This is an issue for the IP-based networks if the originating GSTN
+ does not handle the overlap signaling by collecting the complete
+ called directory number.
+
+ The IETF enum working group is defining the use of Domain Name
+ System (DNS) for identifying available services associated with a
+ particular E.164 number [ENUM]. [ENUMPO] outlines the principles
+ for the operation of a telephone number service that resolves
+ telephone numbers into Internet domain name addresses and service-
+ specific directory discovery. [ENUMPO] implements a three-level
+ approach where the first level is the mapping of the telephone
+ number delegation tree to the authority to which the number has been
+ delegated, the second level is the provision of the requested DNS
+ resource records from a service registrar, and the third level is
+ the provision of service specific data from the service provider
+ itself. NP certainly must be considered at the first level because
+ the telephony service providers do not "own" or control the
+ telephone numbers under the NP environment; therefore, they may not
+ be the proper entities to have the authority for a given E.164
+ number. Not only that, there is a regulatory requirement on NP in
+ some countries that the donor network should not be relied on to
+ reach the delegated authority during the DNS process . The
+ delegated authority for a given E.164 number is likely to be an
+ entity designated by the end user that owns/controls a specific
+ telephone number or one that is designated by the service registrar.
+
+ Since the telephony service providers may have the need to use ENUM
+ for their network-related services (e.g., map an E.164 number to a
+ HLR Identifier in the wireless networks), their ENUM records must be
+ collocated with those of the telephony subscribers. If that is the
+ case, NP will impact ENUM when a telephony subscriber who has ENUM
+ service changes the telephony service provider. This is because
+ that the ENUM records from the new telephony service provider must
+ replace those from the old telephony service provider. To avoid the
+ NP impact on ENUM, it is recommended that the telephony service
+ providers use a different domain tree for their network-related
+ service. For example, if e164.arpa is chosen for Ÿend user÷ ENUM, a
+ domain tree different from e164.arpa should be used for Ÿcarrier÷
+ ENUM.
+
+ The IP-based networks also may need to support some forms of number
+ portability in the future if E.164 numbers [E164] are assigned to
+ the IP-based end users. One method is to assign a GSTN routing
+ number for each IP-based network domain or entity in a NP-capable
+ country. This may increase the number of digits in the routing
+ number to incorporate the IP entities and impact the existing
+ routing in the GSTN. Another method is to associate each IP entity
+ with a particular GSTN gateway. At that particular GSTN gateway,
+ the called directory number then is used to locate the IP-entity
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 23]
+
+Number Portability in the GSTN: An Overview June 24, 2002
+
+ that serves that dialed directory number. Yet, another method can
+ be to assign a special routing number so that the call to an end
+ user currently served by an IP entity is routed to the nearest GSTN
+ gateway. The called directory number then is used to locate the IP-
+ entity that serves that dialed directory number. A mechanism can be
+ developed or used for the IP-based network to locate the IP entity
+ that serves a particular dialed directory number. Many other types
+ of networks use E.164 numbers to identify the end users or terminals
+ in those networks. Number portability among GSTN, IP-based network
+ and those various types of networks may also need to be supported in
+ the future.
+
+
+10. Security Considerations
+
+ This document does not raise any security issues.
+
+
+11. IANA Considerations
+
+ This document introduces no new values for IANA registration.
+
+
+12. Normative References
+
+ [ANSI OSS] ANSI Technical Requirements No. 1, "Number Portability -
+ Operator Services Switching Systems," April 1999.
+
+ [ANSI SS] ANSI Technical Requirements No. 2, "Number Portability -
+ Switching Systems," April 1999.
+
+ [ANSI DB] ANSI Technical Requirements No. 3, "Number Portability
+ Database and Global Title Translation," April 1999.
+
+ [CS1] ITU-T Q-series Recommendations - Supplement 4, "Number
+ portability Capability set 1 requirements for service provider
+ portability (All call query and onward routing)," May 1998.
+
+ [CS2] ITU-T Q-series Recommendations - Supplement 5, "Number
+ portability -Capability set 2 requirements for service provider
+ portability (Query on release and Dropback)," March 1999.
+
+ [E164] ITU-T Recommendation E.164, "The International Public
+ Telecommunications Numbering Plan," 1997.
+
+ [ENUM] P. Falstrom, "E.164 number and DNS," RFC 2916.
+
+ [ETSIISUP] ETSI EN 302 097 V.1.2.2, ŸIntegrated Services Digital
+ Network (ISDN); Signalling System No.7 (SS7); ISDN User Part
+ (ISUP); Enhancement for support of Number Portability (NP)
+ [ITU-T Recommendation Q.769.1 (2000), modified]
+
+ [GSM] GSM 09.02: "Digital cellular telecommunications system (Phase
+ 2+); Mobile Application Part (MAP) specification".
+
+Foster,McGarry,Yu Expired on December 23, 2002 [Page 24]
+
+Number Portability in the GSTN: An Overview March 1, 2002
+
+
+
+ [IS41] TIA/EIA IS-756 Rev. A, "TIA/EIA-41-D Enhancements for
+ Wireless Number Portability Phase II (December 1998)"Number
+ Portability Network Support," April 1998.
+
+ [ITUISUP] ITU-T Recommendation Q.769.1, "Signaling System No. 7 -
+ ISDN User Part Enhancements for the Support of Number
+ Portability," December 1999.
+
+ [MNP] ETSI EN 301 716 (2000-10) European Standard
+ (Telecommunications series) Digital cellular telecommunications
+ system (Phase 2+); Support of Mobile Number Portability (MNP);
+ Technical Realisation; Stage 2; (GSM 03.66 Version 7.2.0
+ Release 1998).
+
+ [RFC] Scott Bradner, RFC2026, "The Internet Standards Process --
+ Revision 3," October 1996.
+
+
+13. Informative References
+
+ [ENUMPO] A. Brown and G. Vaudreuil, "ENUM Service Specific
+ Provisioning: Principles of Operations," draft-ietf-enum-
+ operation-02.txt, February 23, 2001.
+
+ [SIP] J. Rosenberg, et al., draft-ietf-sip-rfc2543bis-09.txt, "SIP:
+ Session Initiation Protocol," February 27, 2002.
+
+ [TEL] H. Schulzrinne and A. Vaha-Sipila, draft-antti-rfc2806bis-
+ 04.txt, "URIs for Telephone Calls," May 24, 2002.
+
+ [TELNP] J. Yu, draft-yu-tel-url-05.txt, "Extensions to the "tel" URL
+ to support Number Portability and Freephone Service," June 14,
+ 2002.
+
+ [TRIP] J. Rosenberg, H. Salama and M. Squire, RFC 3219, "Telephony
+ Routing Information Protocol (TRIP)," January 2002.
+
+
+14. Acknowledgment
+
+ The authors would like to thank Monika Muench for providing
+ information on ISUP and MNP.
+
+
+15. Authors' Addresses
+
+ Mark D. Foster
+ NeuStar, Inc.
+ 1120 Vermont Avenue, NW,
+ Suite 400
+ Washington, D.C. 20005
+ United States
+
+Foster,McGarry,Yu Expired on August 31, 2002 [Page 25]
+
+Number Portability in the GSTN: An Overview March 1, 2002
+
+
+
+ Phone: +1-202-533-2800
+ Fax: +1-202-533-2987
+ Email: mark.foster@neustar.biz
+
+ Tom McGarry
+ NeuStar, Inc.
+ 1120 Vermont Avenue, NW,
+ Suite 400
+ Washington, D.C. 20005
+ United States
+
+ Phone: +1-202-533-2810
+ Fax: +1-202-533-2987
+ Email: tom.mcgarry@neustar.biz
+
+ James Yu
+ NeuStar, Inc.
+ 1120 Vermont Avenue, NW,
+ Suite 400
+ Washington, D.C. 20005
+ United States
+
+ Phone: +1-202-533-2814
+ Fax: +1-202-533-2987
+ Email: james.yu@neustar.biz
+
+
+
+Full Copyright Statement
+
+ "Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph
+ are included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+
+
+Foster,McGarry,Yu Expired on August 31, 2002 [Page 26]
+
+Number Portability in the GSTN: An Overview March 1, 2002
+
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Foster,McGarry,Yu Expired on August 31, 2002 [Page 27]
+ \ No newline at end of file
diff --git a/doc/draft/draft-ietf-ipv6-node-requirements-08.txt b/doc/draft/draft-ietf-ipv6-node-requirements-08.txt
new file mode 100644
index 0000000..2d5c87e
--- /dev/null
+++ b/doc/draft/draft-ietf-ipv6-node-requirements-08.txt
@@ -0,0 +1,1200 @@
+
+
+
+
+
+
+IPv6 Working Group John Loughney (ed)
+Internet-Draft Nokia
+ January 14, 2004
+
+Expires: July 14, 2004
+
+
+
+ IPv6 Node Requirements
+ draft-ietf-ipv6-node-requirements-08.txt
+
+
+
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as Internet-
+ Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ This document defines requirements for IPv6 nodes. It is expected
+ that IPv6 will be deployed in a wide range of devices and situations.
+ Specifying the requirements for IPv6 nodes allows IPv6 to function
+ well and interoperate in a large number of situations and
+ deployments.
+
+
+
+
+
+Loughney (editor) February 16, 2004 [Page 1]
+
+
+
+
+
+Internet-Draft
+
+
+Table of Contents
+
+ 1. Introduction
+ 1.1 Requirement Language
+ 1.2 Scope of this Document
+ 1.3 Description of IPv6 Nodes
+ 2. Abbreviations Used in This Document
+ 3. Sub-IP Layer
+ 3.1 Transmission of IPv6 Packets over Ethernet Networks - RFC2464
+ 3.2 IP version 6 over PPP - RFC2472
+ 3.3 IPv6 over ATM Networks - RFC2492
+ 4. IP Layer
+ 4.1 Internet Protocol Version 6 - RFC2460
+ 4.2 Neighbor Discovery for IPv6 - RFC2461
+ 4.3 Path MTU Discovery & Packet Size
+ 4.4 ICMP for the Internet Protocol Version 6 (IPv6) - RFC2463
+ 4.5 Addressing
+ 4.6 Multicast Listener Discovery (MLD) for IPv6 - RFC2710
+ 5. Transport and DNS
+ 5.1 Transport Layer
+ 5.2 DNS
+ 5.3 Dynamic Host Configuration Protocol for IPv6 (DHCPv6)
+ 6. IPv4 Support and Transition
+ 6.1 Transition Mechanisms
+ 7. Mobility
+ 8. Security
+ 8.1 Basic Architecture
+ 8.2 Security Protocols
+ 8.3 Transforms and Algorithms
+ 8.4 Key Management Methods
+ 9. Router Functionality
+ 9.1 General
+ 10. Network Management
+ 10.1 MIBs
+ 11. Security Considerations
+ 12. References
+ 12.1 Normative
+ 12.2 Non-Normative
+ 13. Authors and Acknowledgements
+ 14. Editor's Address
+ Notices
+
+
+
+
+
+
+
+
+
+
+Loughney (editor) February 16, 2004 [Page 2]
+
+
+
+
+
+Internet-Draft
+
+
+1. Introduction
+
+ The goal of this document is to define the common functionality
+ required from both IPv6 hosts and routers. Many IPv6 nodes will
+ implement optional or additional features, but all IPv6 nodes can be
+ expected to implement the mandatory requirements listed in this
+ document.
+
+ This document tries to avoid discussion of protocol details, and
+ references RFCs for this purpose. In case of any conflicting text,
+ this document takes less precedence than the normative RFCs, unless
+ additional clarifying text is included in this document.
+
+ Although the document points to different specifications, it should
+ be noted that in most cases, the granularity of requirements are
+ smaller than a single specification, as many specifications define
+ multiple, independent pieces, some of which may not be mandatory.
+
+ As it is not always possible for an implementer to know the exact
+ usage of IPv6 in a node, an overriding requirement for IPv6 nodes is
+ that they should adhere to Jon Postel's Robustness Principle:
+
+ Be conservative in what you do, be liberal in what you accept from
+ others [RFC-793].
+
+1.1 Requirement Language
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [RFC-2119].
+
+1.2 Scope of this Document
+
+ IPv6 covers many specifications. It is intended that IPv6 will be
+ deployed in many different situations and environments. Therefore,
+ it is important to develop the requirements for IPv6 nodes, in order
+ to ensure interoperability.
+
+ This document assumes that all IPv6 nodes meet the minimum
+ requirements specified here.
+
+1.3 Description of IPv6 Nodes
+
+ From Internet Protocol, Version 6 (IPv6) Specification [RFC-2460] we
+ have the following definitions:
+
+ Description of an IPv6 Node
+
+
+
+
+Loughney (editor) February 16, 2004 [Page 3]
+
+
+
+
+
+Internet-Draft
+
+
+ - a device that implements IPv6
+
+ Description of an IPv6 router
+
+ - a node that forwards IPv6 packets not explicitly addressed to
+ itself.
+
+ Description of an IPv6 Host
+
+ - any node that is not a router.
+
+2. Abbreviations Used in This Document
+
+ ATM Asynchronous Transfer Mode
+
+ AH Authentication Header
+
+ DAD Duplicate Address Detection
+
+ ESP Encapsulating Security Payload
+
+ ICMP Internet Control Message Protocol
+
+ IKE Internet Key Exchange
+
+ MIB Management Information Base
+
+ MLD Multicast Listener Discovery
+
+ MTU Maximum Transfer Unit
+
+ NA Neighbor Advertisement
+
+ NBMA Non-Broadcast Multiple Access
+
+ ND Neighbor Discovery
+
+ NS Neighbor Solicitation
+
+ NUD Neighbor Unreachability Detection
+
+ PPP Point-to-Point Protocol
+
+ PVC Permanent Virtual Circuit
+
+ SVC Switched Virtual Circuit
+
+3. Sub-IP Layer
+
+
+
+Loughney (editor) February 16, 2004 [Page 4]
+
+
+
+
+
+Internet-Draft
+
+
+ An IPv6 node must include support for one or more IPv6 link-layer
+ specifications. Which link-layer specifications are included will
+ depend upon what link-layers are supported by the hardware available
+ on the system. It is possible for a conformant IPv6 node to support
+ IPv6 on some of its interfaces and not on others.
+
+ As IPv6 is run over new layer 2 technologies, it is expected that new
+ specifications will be issued. This section highlights some major
+ layer 2 technologies and is not intended to be complete.
+
+3.1 Transmission of IPv6 Packets over Ethernet Networks - RFC2464
+
+ Nodes supporting IPv6 over Ethernet interfaces MUST implement
+ Transmission of IPv6 Packets over Ethernet Networks [RFC-2464].
+
+3.2 IP version 6 over PPP - RFC2472
+
+ Nodes supporting IPv6 over PPP MUST implement IPv6 over PPP [RFC-
+ 2472].
+
+3.3 IPv6 over ATM Networks - RFC2492
+
+ Nodes supporting IPv6 over ATM Networks MUST implement IPv6 over ATM
+ Networks [RFC-2492]. Additionally, RFC 2492 states:
+
+ A minimally conforming IPv6/ATM driver SHALL support the PVC mode
+ of operation. An IPv6/ATM driver that supports the full SVC mode
+ SHALL also support PVC mode of operation.
+
+4. IP Layer
+
+4.1 Internet Protocol Version 6 - RFC2460
+
+ The Internet Protocol Version 6 is specified in [RFC-2460]. This
+ specification MUST be supported.
+
+ Unrecognized options in Hop-by-Hop Options or Destination Options
+ extensions MUST be processed as described in RFC 2460.
+
+ The node MUST follow the packet transmission rules in RFC 2460.
+
+ Nodes MUST always be able to send, receive and process fragment
+ headers. All conformant IPv6 implementations MUST be capable of
+ sending and receving IPv6 packets; forwarding functionality MAY be
+ supported
+
+ RFC 2460 specifies extension headers and the processing for these
+ headers.
+
+
+
+Loughney (editor) February 16, 2004 [Page 5]
+
+
+
+
+
+Internet-Draft
+
+
+ A full implementation of IPv6 includes implementation of the
+ following extension headers: Hop-by-Hop Options, Routing (Type 0),
+ Fragment, Destination Options, Authentication and Encapsulating
+ Security Payload. [RFC-2460]
+
+ An IPv6 node MUST be able to process these headers. It should be
+ noted that there is some discussion about the use of Routing Headers
+ and possible security threats [IPv6-RH] caused by them.
+
+4.2 Neighbor Discovery for IPv6 - RFC2461
+
+ Neighbor Discovery SHOULD be supported. RFC 2461 states:
+
+ "Unless specified otherwise (in a document that covers operating
+ IP over a particular link type) this document applies to all link
+ types. However, because ND uses link-layer multicast for some of
+ its services, it is possible that on some link types (e.g., NBMA
+ links) alternative protocols or mechanisms to implement those
+ services will be specified (in the appropriate document covering
+ the operation of IP over a particular link type). The services
+ described in this document that are not directly dependent on
+ multicast, such as Redirects, Next-hop determination, Neighbor
+ Unreachability Detection, etc., are expected to be provided as
+ specified in this document. The details of how one uses ND on
+ NBMA links is an area for further study."
+
+ Some detailed analysis of Neighbor Discovery follows:
+
+ Router Discovery is how hosts locate routers that reside on an
+ attached link. Router Discovery MUST be supported for
+ implementations.
+
+ Prefix Discovery is how hosts discover the set of address prefixes
+ that define which destinations are on-link for an attached link.
+ Prefix discovery MUST be supported for implementations. Neighbor
+ Unreachability Detection (NUD) MUST be supported for all paths
+ between hosts and neighboring nodes. It is not required for paths
+ between routers. However, when a node receives a unicast Neighbor
+ Solicitation (NS) message (that may be a NUD's NS), the node MUST
+ respond to it (i.e. send a unicast Neighbor Advertisement).
+
+ Duplicate Address Detection MUST be supported on all links supporting
+ link-layer multicast (RFC2462 section 5.4 specifies DAD MUST take
+ place on all unicast addresses).
+
+ A host implementation MUST support sending Router Solicitations.
+
+ Receiving and processing Router Advertisements MUST be supported for
+
+
+
+Loughney (editor) February 16, 2004 [Page 6]
+
+
+
+
+
+Internet-Draft
+
+
+ host implementations. The ability to understand specific Router
+ Advertisement options is dependent on supporting the specification
+ where the RA is specified.
+
+ Sending and Receiving Neighbor Solicitation (NS) and Neighbor
+ Advertisement (NA) MUST be supported. NS and NA messages are required
+ for Duplicate Address Detection (DAD).
+
+ Redirect functionality SHOULD be supported. If the node is a router,
+ Redirect functionality MUST be supported.
+
+4.3 Path MTU Discovery & Packet Size
+
+4.3.1 Path MTU Discovery - RFC1981
+
+ Path MTU Discovery [RFC-1981] SHOULD be supported, though minimal
+ implementations MAY choose to not support it and avoid large packets.
+ The rules in RFC 2460 MUST be followed for packet fragmentation and
+ reassembly.
+
+4.3.2 IPv6 Jumbograms - RFC2675
+
+ IPv6 Jumbograms [RFC-2675] MAY be supported.
+
+4.4 ICMP for the Internet Protocol Version 6 (IPv6) - RFC2463
+
+ ICMPv6 [RFC-2463] MUST be supported.
+
+4.5 Addressing
+
+4.5.1 IP Version 6 Addressing Architecture - RFC3513
+
+ The IPv6 Addressing Architecture [RFC-3513] MUST be supported.
+
+4.5.2 IPv6 Stateless Address Autoconfiguration - RFC2462
+
+ IPv6 Stateless Address Autoconfiguration is defined in [RFC-2462].
+ This specification MUST be supported for nodes that are hosts.
+
+ Nodes that are routers MUST be able to generate link local addresses
+ as described in RFC 2462 [RFC-2462].
+
+ From 2462:
+
+ The autoconfiguration process specified in this document applies
+ only to hosts and not routers. Since host autoconfiguration uses
+ information advertised by routers, routers will need to be
+ configured by some other means. However, it is expected that
+
+
+
+Loughney (editor) February 16, 2004 [Page 7]
+
+
+
+
+
+Internet-Draft
+
+
+ routers will generate link-local addresses using the mechanism
+ described in this document. In addition, routers are expected to
+ successfully pass the Duplicate Address Detection procedure
+ described in this document on all addresses prior to assigning
+ them to an interface.
+
+ Duplicate Address Detection (DAD) MUST be supported.
+
+4.5.3 Privacy Extensions for Address Configuration in IPv6 - RFC3041
+
+ Privacy Extensions for Stateless Address Autoconfiguration [RFC-3041]
+ SHOULD be supported. It is recommended that this behavior be
+ configurable on a connection basis within each application when
+ available. It is noted that a number of applications do not work
+ with addresses generated with this method, while other applications
+ work quite well with them.
+
+4.5.4 Default Address Selection for IPv6 - RFC3484
+
+ The rules specified in the Default Address Selection for IPv6 [RFC-
+ 3484] document MUST be implemented. It is expected that IPv6 nodes
+ will need to deal with multiple addresses.
+
+4.5.5 Stateful Address Autoconfiguration
+
+ Stateful Address Autoconfiguration MAY be supported. DHCPv6 [RFC-
+ 3315] is the standard stateful address configuration protocol; see
+ section 5.3 for DHCPv6 support.
+
+ Nodes which do not support Stateful Address Autoconfiguration may be
+ unable to obtain any IPv6 addresses aside from link-local addresses
+ when it receives a router advertisement with the 'M' flag (Managed
+ address configuration) set and which contains no prefixes advertised
+ for Stateless Address Autoconfiguration (see section 4.5.2).
+ Additionally, such nodes will be unable to obtain other configuration
+ information such as the addresses of DNS servers when it is connected
+ to a link over which the node receives a router advertisement in
+ which the 'O' flag ("Other stateful configuration") is set.
+
+4.6 Multicast Listener Discovery (MLD) for IPv6 - RFC2710
+
+ Nodes that need to join multicast groups SHOULD implement MLDv2
+ [MLDv2]. However, if the node has applications, which only need
+ support for Any- Source Multicast [RFC3569], the node MAY implement
+ MLDv1 [MLDv1] instead. If the node has applications, which need
+ support for Source- Specific Multicast [RFC3569, SSMARCH], the node
+ MUST support MLDv2 [MLDv2].
+
+
+
+
+Loughney (editor) February 16, 2004 [Page 8]
+
+
+
+
+
+Internet-Draft
+
+
+ When MLD is used, the rules in "Source Address Selection for the
+ Multicast Listener Discovery (MLD) Protocol" [RFC-3590] MUST be
+ followed.
+
+5. Transport Layer and DNS
+
+5.1 Transport Layer
+
+5.1.1 TCP and UDP over IPv6 Jumbograms - RFC2147
+
+ This specification MUST be supported if jumbograms are implemented
+ [RFC- 2675].
+
+5.2 DNS
+
+ DNS, as described in [RFC-1034], [RFC-1035], [RFC-3152], [RFC-3363]
+ and [RFC-3596] MAY be supported. Not all nodes will need to resolve
+ names. All nodes that need to resolve names SHOULD implement stub-
+ resolver [RFC-1034] functionality, in RFC 1034 section 5.3.1 with
+ support for:
+
+ - AAAA type Resource Records [RFC-3596];
+ - reverse addressing in ip6.arpa using PTR records [RFC-3152];
+ - EDNS0 [RFC-2671] to allow for DNS packet sizes larger than 512
+ octets.
+
+ Those nodes are RECOMMENDED to support DNS security extentions
+ [DNSSEC- INTRO], [DNSSEC-REC] and [DNSSEC-PROT].
+
+ Those nodes are NOT RECOMMENDED to support the experimental A6 and
+ DNAME Resource Records [RFC-3363].
+
+5.2.2 Format for Literal IPv6 Addresses in URL's - RFC2732
+
+ RFC 2732 MUST be supported if applications on the node use URL's.
+
+5.3 Dynamic Host Configuration Protocol for IPv6 (DHCPv6) - RFC3315
+
+5.3.1 Managed Address Configuration
+
+ Those IPv6 Nodes that use DHCP for address assignment initiate DHCP
+ to obtain IPv6 addresses and other configuration information upon
+ receipt of a Router Advertisement with the 'M' flag set, as described
+ in section 5.5.3 of RFC 2462. In addition, in the absence of a
+ router, those IPv6 Nodes that use DHCP for address assignment MUST
+ initiate DHCP to obtain IPv6 addresses and other configuration
+ information, as described in section 5.5.2 of RFC 2462. Those IPv6
+ nodes that do not use DHCP for address assignment can ignore the 'M'
+
+
+
+Loughney (editor) February 16, 2004 [Page 9]
+
+
+
+
+
+Internet-Draft
+
+
+ flag in Router Advertisements.
+
+5.3.2 Other Configuration Information
+
+ Those IPv6 Nodes that use DHCP to obtain other configuration
+ information initiate DHCP for other configuration information upon
+ receipt of a Router Advertisement with the 'O' flag set, as described
+ in section 5.5.3 of RFC 2462. Those IPv6 nodes that do not use DHCP
+ for other configuration information can ignore the 'O' flag in Router
+ Advertisements.
+
+ An IPv6 Node can use the subset of DHCP described in [DHCPv6-SL] to
+ obtain other configuration information.
+
+6. IPv4 Support and Transition
+
+ IPv6 nodes MAY support IPv4.
+
+6.1 Transition Mechanisms
+
+6.1.1 Transition Mechanisms for IPv6 Hosts and Routers - RFC2893
+
+ If an IPv6 node implements dual stack and tunneling, then RFC2893
+ MUST be supported.
+
+ RFC 2893 is currently being updated.
+
+7. Mobile IP
+
+ The Mobile IPv6 [MIPv6] specification defines requirements for the
+ following types of nodes:
+
+ - mobile nodes
+ - correspondent nodes with support for route optimization
+ - home agents
+ - all IPv6 routers
+
+ Hosts MAY support mobile node functionality described in Section 8.5
+ of [MIPv6], including support of generic packet tunneling [RFC-2473]
+ and secure home agent communications [MIPv6-HASEC].
+
+ Hosts SHOULD support route optimization requirements for
+ correspondent nodes described in Section 8.2 of [MIPv6].
+
+ Routers SHOULD support the generic mobility-related requirements for
+ all IPv6 routers described in Section 8.3 of [MIPv6]. Routers MAY
+ support the home agent functionality described in Section 8.4 of
+ [MIPv6], including support of [RFC-2473] and [MIPv6-HASEC].
+
+
+
+Loughney (editor) February 16, 2004 [Page 10]
+
+
+
+
+
+Internet-Draft
+
+
+8. Security
+
+ This section describes the specification of IPsec for the IPv6 node.
+
+8.1 Basic Architecture
+
+ Security Architecture for the Internet Protocol [RFC-2401] MUST be
+ supported. RFC-2401 is being updated by the IPsec Working Group.
+
+8.2 Security Protocols
+
+ ESP [RFC-2406] MUST be supported. AH [RFC-2402] MUST be supported.
+ RFC- 2406 and RFC 2402 are being updated by the IPsec Working Group.
+
+
+8.3 Transforms and Algorithms
+
+ Current IPsec RFCs specify the support of certain transforms and
+ algorithms, NULL encryption, DES-CBC, HMAC-SHA-1-96, and HMAC-MD5-96.
+ The requirements for these are discussed first, and then additional
+ algorithms 3DES-CBC, AES-128-CBC and HMAC-SHA-256-96 are discussed.
+
+ NULL encryption algorithm [RFC-2410] MUST be supported for providing
+ integrity service and also for debugging use.
+
+ The "ESP DES-CBC Cipher Algorithm With Explicit IV" [RFC-2405] SHOULD
+ NOT be supported. Security issues related to the use of DES are
+ discussed in [DESDIFF], [DESINT], [DESCRACK]. It is still listed as
+ required by the existing IPsec RFCs, but as it is currently viewed as
+ an inherently weak algorithm, and no longer fulfills its intended
+ role.
+
+ The NULL authentication algorithm [RFC-2406] MUST be supported within
+ ESP. The use of HMAC-SHA-1-96 within AH and ESP, described in [RFC-
+ 2404] MUST be supported. The use of HMAC-MD5-96 within AH and ESP,
+ described in [RFC-2403] MUST be supported. An implementer MUST refer
+ to Keyed- Hashing for Message Authentication [RFC-2104].
+
+ 3DES-CBC does not suffer from the issues related to DES-CBC. 3DES-CBC
+ and ESP CBC-Mode Cipher Algorithms [RFC-2451] MAY be supported. AES-
+ CBC Cipher Algorithm [RFC-3602] MUST be supported, as it is expected
+ to be a widely available, secure algorithm that is required for
+ interoperability. It is not required by the current IPsec RFCs, but
+ is expected to become required in the future.
+
+ In addition to the above requirements, "Cryptographic Algorithm
+ Implementation Requirements For ESP And AH" [CRYPTREQ] contains the
+ current set of mandatory to implement algorithms for ESP and AH as
+
+
+
+Loughney (editor) February 16, 2004 [Page 11]
+
+
+
+
+
+Internet-Draft
+
+
+ well as specifying algorithms that should be implemented because they
+ may be promoted to mandatory at some future time. It is RECOMMENDED
+ that IPv6 nodes conform to the requirements in this document.
+
+8.4 Key Management Methods
+
+ Manual keying MUST be supported.
+
+ IKE [RFC-2407] [RFC-2408] [RFC-2409] MAY be supported for unicast
+ traffic. Where key refresh, anti-replay features of AH and ESP, or
+ on- demand creation of Security Associations (SAs) is required,
+ automated keying MUST be supported. Note that the IPsec WG is working
+ on the successor to IKE [IKE2]. Key management methods for multicast
+ traffic are also being worked on by the MSEC WG.
+
+ "Cryptographic Algorithms for use in the Internet Key Exchange
+ Version 2" [IKEv2ALGO] defines the current set of mandatory to
+ implement algorithms for use of IKEv2 as well as specifying
+ algorithms that should be implemented because they made be promoted
+ to mandatory at some future time. It is RECOMMENDED that IPv6 nodes
+ implementing IKEv2 conform to the requirements in this
+ document.
+
+9. Router-Specific Functionality
+
+ This section defines general host considerations for IPv6 nodes that
+ act as routers. Currently, this section does not discuss routing-
+ specific requirements.
+
+9.1 General
+
+9.1.1 IPv6 Router Alert Option - RFC2711
+
+
+ The IPv6 Router Alert Option [RFC-2711] is an optional IPv6 Hop-by-
+ Hop Header that is used in conjunction with some protocols (e.g.,
+ RSVP [RFC- 2205], or MLD [RFC-2710]). The Router Alert option will
+ need to be implemented whenever protocols that mandate its usage are
+ implemented. See Section 4.6.
+
+9.1.2 Neighbor Discovery for IPv6 - RFC2461
+
+ Sending Router Advertisements and processing Router Solicitation MUST
+ be supported.
+
+10. Network Management
+
+ Network Management MAY be supported by IPv6 nodes. However, for IPv6
+
+
+
+Loughney (editor) February 16, 2004 [Page 12]
+
+
+
+
+
+Internet-Draft
+
+
+ nodes that are embedded devices, network management may be the only
+ possibility to control these nodes.
+
+10.1 Management Information Base Modules (MIBs)
+
+ The following two MIBs SHOULD be supported by nodes that support an
+ SNMP agent.
+
+10.1.1 IP Forwarding Table MIB
+
+ IP Forwarding Table MIB [RFC-2096BIS] SHOULD be supported by nodes
+ that support an SNMP agent.
+
+10.1.2 Management Information Base for the Internet Protocol (IP)
+
+ IP MIB [RFC-2011BIS] SHOULD be supported by nodes that support an
+ SNMP agent.
+
+11. Security Considerations
+
+ This draft does not affect the security of the Internet, but
+ implementations of IPv6 are expected to support a minimum set of
+ security features to ensure security on the Internet. "IP Security
+ Document Roadmap" [RFC-2411] is important for everyone to read.
+
+ The security considerations in RFC2460 describe the following:
+
+ The security features of IPv6 are described in the Security
+ Architecture for the Internet Protocol [RFC-2401].
+
+12. References
+
+12.1 Normative
+
+ [CRYPTREQ] D. Eastlake 3rd, "Cryptographic Algorithm Implementa-
+ tion Requirements For ESP And AH", draft-ietf-ipsec-
+ esp-ah-algorithms-01.txt, January 2004.
+
+ [IKEv2ALGO] J. Schiller, "Cryptographic Algorithms for use in the
+ Internet Key Exchange Version 2", draft-ietf-ipsec-
+ ikev2-algorithms-04.txt, Work in Progress.
+
+ [DHCPv6-SL] R. Droms, "A Guide to Implementing Stateless DHCPv6
+ Service", draft- ietf-dhc-dhcpv6-stateless-00.txt,
+ Work in Progress.
+
+ [MIPv6] J. Arkko, D. Johnson and C. Perkins, "Mobility Support
+ in IPv6", draft- ietf-mobileip-ipv6-24.txt, Work in
+
+
+
+Loughney (editor) February 16, 2004 [Page 13]
+
+
+
+
+
+Internet-Draft
+
+
+ progress.
+
+ [MIPv6-HASEC] J. Arkko, V. Devarapalli and F. Dupont, "Using IPsec
+ to Protect Mobile IPv6 Signaling between Mobile Nodes
+ and Home Agents", draft-ietf- mobileip-mipv6-ha-
+ ipsec-06.txt, Work in Progress.
+
+ [MLDv2] Vida, R. et al., "Multicast Listener Discovery Version
+ 2 (MLDv2) for IPv6", draft-vida-mld-v2-07.txt, Work in
+ Progress.
+
+ [RFC-1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC-1981] McCann, J., Mogul, J. and Deering, S., "Path MTU
+ Discovery for IP version 6", RFC 1981, August 1996.
+
+ [RFC-2096BIS] Haberman, B. and Wasserman, M., "IP Forwarding Table
+ MIB", draft-ietf- ipv6-rfc2096-update-07.txt, Work in
+ Progress.
+
+ [RFC-2011BIS] Routhier, S (ed), "Management Information Base for the
+ Internet Protocol (IP)", draft-ietf-ipv6-rfc2011-
+ update-07.txt, Work in progress.
+
+ [RFC-2104] Krawczyk, K., Bellare, M., and Canetti, R., "HMAC:
+ Keyed-Hashing for Message Authentication", RFC 2104,
+ February 1997.
+
+ [RFC-2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC-2401] Kent, S. and Atkinson, R., "Security Architecture for
+ the Internet Protocol", RFC 2401, November 1998.
+
+ [RFC-2402] Kent, S. and Atkinson, R., "IP Authentication
+ Header", RFC 2402, November 1998.
+
+ [RFC-2403] Madson, C., and Glenn, R., "The Use of HMAC-MD5 within
+ ESP and AH", RFC 2403, November 1998.
+
+ [RFC-2404] Madson, C., and Glenn, R., "The Use of HMAC-SHA-1
+ within ESP and AH", RFC 2404, November 1998.
+
+ [RFC-2405] Madson, C. and Doraswamy, N., "The ESP DES-CBC Cipher
+ Algorithm With Explicit IV", RFC 2405, November 1998.
+
+ [RFC-2406] Kent, S. and Atkinson, R., "IP Encapsulating Security
+
+
+
+Loughney (editor) February 16, 2004 [Page 14]
+
+
+
+
+
+Internet-Draft
+
+
+ Protocol (ESP)", RFC 2406, November 1998.
+
+ [RFC-2407] Piper, D., "The Internet IP Security Domain of
+ Interpretation for ISAKMP", RFC 2407, November 1998.
+
+ [RFC-2408] Maughan, D., Schertler, M., Schneider, M., and Turner,
+ J., "Internet Security Association and Key Management
+ Protocol (ISAKMP)", RFC 2408, November 1998.
+
+ [RFC-2409] Harkins, D., and Carrel, D., "The Internet Key
+ Exchange (IKE)", RFC 2409, November 1998.
+
+ [RFC-2410] Glenn, R. and Kent, S., "The NULL Encryption Algorithm
+ and Its Use With IPsec", RFC 2410, November 1998.
+
+ [RFC-2451] Pereira, R. and Adams, R., "The ESP CBC-Mode Cipher
+ Algorithms", RFC 2451, November 1998.
+
+ [RFC-2460] Deering, S. and Hinden, R., "Internet Protocol, Ver-
+ sion 6 (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC-2461] Narten, T., Nordmark, E. and Simpson, W., "Neighbor
+ Discovery for IP Version 6 (IPv6)", RFC 2461, December
+ 1998.
+
+ [RFC-2462] Thomson, S. and Narten, T., "IPv6 Stateless Address
+ Autoconfiguration", RFC 2462.
+
+ [RFC-2463] Conta, A. and Deering, S., "ICMP for the Internet Pro-
+ tocol Version 6 (IPv6)", RFC 2463, December 1998.
+
+ [RFC-2472] Haskin, D. and Allen, E., "IP version 6 over PPP", RFC
+ 2472, December 1998.
+
+ [RFC-2473] Conta, A. and Deering, S., "Generic Packet Tunneling
+ in IPv6 Specification", RFC 2473, December 1998. Xxx
+ add
+
+ [RFC-2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [RFC-2710] Deering, S., Fenner, W. and Haberman, B., "Multicast
+ Listener Discovery (MLD) for IPv6", RFC 2710, October
+ 1999.
+
+ [RFC-2711] Partridge, C. and Jackson, A., "IPv6 Router Alert
+ Option", RFC 2711, October 1999.
+
+
+
+
+Loughney (editor) February 16, 2004 [Page 15]
+
+
+
+
+
+Internet-Draft
+
+
+ [RFC-3041] Narten, T. and Draves, R., "Privacy Extensions for
+ Stateless Address Autoconfiguration in IPv6", RFC
+ 3041, January 2001.
+
+ [RFC-3152] Bush, R., "Delegation of IP6.ARPA", RFC 3152, August
+ 2001.
+
+ [RFC-3315] Bound, J. et al., "Dynamic Host Configuration Protocol
+ for IPv6 (DHCPv6)", RFC 3315, July 2003.
+
+ [RFC-3363] Bush, R., et al., "Representing Internet Protocol ver-
+ sion 6 (IPv6) Addresses in the Domain Name System
+ (DNS)", RFC 3363, August 2002.
+
+ [RFC-3484] Draves, R., "Default Address Selection for IPv6", RFC
+ 3484, February 2003.
+
+ [RFC-3513] Hinden, R. and Deering, S. "IP Version 6 Addressing
+ Architecture", RFC 3513, April 2003.
+
+ [RFC-3590] Haberman, B., "Source Address Selection for the Multi-
+ cast Listener Discovery (MLD) Protocol", RFC 3590,
+ September 2003.
+
+ [RFC-3596] Thomson, S., et al., "DNS Extensions to support IP
+ version 6", RFC 3596, October 2003.
+
+ [RFC-3602] S. Frankel, "The AES-CBC Cipher Algorithm and Its Use
+ with IPsec", RFC 3602, September 2003.
+
+12.2 Non-Normative
+
+ [ANYCAST] Hagino, J and Ettikan K., "An Analysis of IPv6 Anycast",
+ draft-ietf- ipngwg-ipv6-anycast-analysis-02.txt, Work in
+ Progress.
+
+ [DESDIFF] Biham, E., Shamir, A., "Differential Cryptanalysis of
+ DES-like cryptosystems", Journal of Cryptology Vol 4, Jan
+ 1991.
+
+ [DESCRACK] Cracking DES, O'Reilly & Associates, Sebastapol, CA 2000.
+
+ [DESINT] Bellovin, S., "An Issue With DES-CBC When Used Without
+ Strong Integrity", Proceedings of the 32nd IETF, Danvers,
+ MA, April 1995.
+
+ [DHCPv6-SL] Droms, R., "A Guide to Implementing Stateless DHCPv6 Ser-
+ vice", draft- ietf-dhc-dhcpv6-stateless-02.txt, Work in
+
+
+
+Loughney (editor) February 16, 2004 [Page 16]
+
+
+
+
+
+Internet-Draft
+
+
+ Progress.
+
+ [DNSSEC-INTRO] Arends, R., Austein, R., Larson, M., Massey, D. and Rose,
+ S., "DNS Security Introduction and Requirements" draft-
+ ietf-dnsext-dnssec-intro- 06.txt, Work in Progress.
+
+ [DNSSEC-REC] Arends, R., Austein, R., Larson, M., Massey, D. and Rose,
+ S., "Resource Records for the DNS Security Extensions",
+ draft-ietf-dnsext-dnssec- records-04.txt, Work in Pro-
+ gress.
+
+ [DNSSEC-PROT] Arends, R., Austein, R., Larson, M., Massey, D. and Rose,
+ S., "Protocol Modifications for the DNS Security Exten-
+ sions", draft-ietf-dnsext- dnssec-protocol-02.txt, Work
+ in Progress.
+
+ [IKE2] Kaufman, C. (ed), "Internet Key Exchange (IKEv2) Proto-
+ col", draft-ietf- ipsec-ikev2-10.txt, Work in Progress.
+
+ [IPv6-RH] P. Savola, "Security of IPv6 Routing Header and Home
+ Address Options", draft-savola-ipv6-rh-ha-security-
+ 03.txt, Work in Progress, March 2002.
+
+ [MC-THREAT] Ballardie A. and Crowcroft, J.; Multicast-Specific Secu-
+ rity Threats and Counter-Measures; In Proceedings "Sympo-
+ sium on Network and Distributed System Security", Febru-
+ ary 1995, pp.2-16.
+
+ [RFC-793] Postel, J., "Transmission Control Protocol", RFC 793,
+ August 1980.
+
+ [RFC-1034] Mockapetris, P., "Domain names - concepts and facili-
+ ties", RFC 1034, November 1987.
+
+ [RFC-2147] Borman, D., "TCP and UDP over IPv6 Jumbograms", RFC 2147,
+ May 1997.
+
+ [RFC-2205] Braden, B. (ed.), Zhang, L., Berson, S., Herzog, S. and
+ S. Jamin, "Resource ReSerVation Protocol (RSVP)", RFC
+ 2205, September 1997.
+
+ [RFC-2464] Crawford, M., "Transmission of IPv6 Packets over Ethernet
+ Networks", RFC 2462, December 1998.
+
+ [RFC-2492] G. Armitage, M. Jork, P. Schulter, G. Harter, IPv6 over
+ ATM Networks", RFC 2492, January 1999.
+
+ [RFC-2675] Borman, D., Deering, S. and Hinden, B., "IPv6
+
+
+
+Loughney (editor) February 16, 2004 [Page 17]
+
+
+
+
+
+Internet-Draft
+
+
+ Jumbograms", RFC 2675, August 1999.
+
+ [RFC-2732] R. Hinden, B. Carpenter, L. Masinter, "Format for Literal
+ IPv6 Addresses in URL's", RFC 2732, December 1999.
+
+ [RFC-2851] M. Daniele, B. Haberman, S. Routhier, J. Schoenwaelder,
+ "Textual Conventions for Internet Network Addresses", RFC
+ 2851, June 2000.
+
+ [RFC-2893] Gilligan, R. and Nordmark, E., "Transition Mechanisms for
+ IPv6 Hosts and Routers", RFC 2893, August 2000.
+
+ [RFC-3569] S. Bhattacharyya, Ed., "An Overview of Source-Specific
+ Multicast (SSM)", RFC 3569, July 2003.
+
+ [SSM-ARCH] H. Holbrook, B. Cain, "Source-Specific Multicast for IP",
+ draft-ietf- ssm-arch-03.txt, Work in Progress.
+
+13. Authors and Acknowledgements
+
+ This document was written by the IPv6 Node Requirements design team:
+
+ Jari Arkko
+ [jari.arkko@ericsson.com]
+
+ Marc Blanchet
+ [marc.blanchet@viagenie.qc.ca]
+
+ Samita Chakrabarti
+ [samita.chakrabarti@eng.sun.com]
+
+ Alain Durand
+ [alain.durand@sun.com]
+
+ Gerard Gastaud
+ [gerard.gastaud@alcatel.fr]
+
+ Jun-ichiro itojun Hagino
+ [itojun@iijlab.net]
+
+ Atsushi Inoue
+ [inoue@isl.rdc.toshiba.co.jp]
+
+ Masahiro Ishiyama
+ [masahiro@isl.rdc.toshiba.co.jp]
+
+ John Loughney
+ [john.loughney@nokia.com]
+
+
+
+Loughney (editor) February 16, 2004 [Page 18]
+
+
+
+
+
+Internet-Draft
+
+
+ Rajiv Raghunarayan
+ [raraghun@cisco.com]
+
+ Shoichi Sakane
+ [shouichi.sakane@jp.yokogawa.com]
+
+ Dave Thaler
+ [dthaler@windows.microsoft.com]
+
+ Juha Wiljakka
+ [juha.wiljakka@Nokia.com]
+
+ The authors would like to thank Ran Atkinson, Jim Bound, Brian Car-
+ penter, Ralph Droms, Christian Huitema, Adam Machalek, Thomas Narten,
+ Juha Ollila and Pekka Savola for their comments.
+
+14. Editor's Contact Information
+
+ Comments or questions regarding this document should be sent to the
+ IPv6 Working Group mailing list (ipv6@ietf.org) or to:
+
+ John Loughney
+ Nokia Research Center
+ Itamerenkatu 11-13
+ 00180 Helsinki
+ Finland
+
+ Phone: +358 50 483 6242
+ Email: John.Loughney@Nokia.com
+
+Notices
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to per-
+ tain to the implementation or use of the technology described in this
+ document or the extent to which any license under such rights might
+ or might not be available; neither does it represent that it has made
+ any effort to identify any such rights. Information on the IETF's
+ procedures with respect to rights in standards-track and standards-
+ related documentation can be found in BCP-11. Copies of claims of
+ rights made available for publication and any assurances of licenses
+ to be made available, or the result of an attempt made to obtain a
+ general license or permission for the use of such proprietary rights
+ by implementors or users of this specification can be obtained from
+ the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+
+
+
+Loughney (editor) February 16, 2004 [Page 19]
+
+
+
+
+
+Internet-Draft
+
+
+ rights, which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Loughney (editor) February 16, 2004 [Page 20]
+
+
diff --git a/doc/draft/draft-ietf-secsh-dns-05.txt b/doc/draft/draft-ietf-secsh-dns-05.txt
new file mode 100644
index 0000000..a272d81
--- /dev/null
+++ b/doc/draft/draft-ietf-secsh-dns-05.txt
@@ -0,0 +1,614 @@
+Secure Shell Working Group J. Schlyter
+Internet-Draft OpenSSH
+Expires: March 5, 2004 W. Griffin
+ SPARTA
+ September 5, 2003
+
+
+ Using DNS to Securely Publish SSH Key Fingerprints
+ draft-ietf-secsh-dns-05.txt
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that other
+ groups may also distribute working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six months
+ and may be updated, replaced, or obsoleted by other documents at any
+ time. It is inappropriate to use Internet-Drafts as reference
+ material or to cite them other than as "work in progress."
+
+ The list of current Internet-Drafts can be accessed at http://
+ www.ietf.org/ietf/1id-abstracts.txt.
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+ This Internet-Draft will expire on March 5, 2004.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ This document describes a method to verify SSH host keys using
+ DNSSEC. The document defines a new DNS resource record that contains
+ a standard SSH key fingerprint.
+
+
+
+
+
+
+
+
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 1]
+
+Internet-Draft DNS and SSH Fingerprints September 2003
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2. SSH Host Key Verification . . . . . . . . . . . . . . . . . 3
+ 2.1 Method . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2.2 Implementation Notes . . . . . . . . . . . . . . . . . . . . 3
+ 2.3 Fingerprint Matching . . . . . . . . . . . . . . . . . . . . 4
+ 2.4 Authentication . . . . . . . . . . . . . . . . . . . . . . . 4
+ 3. The SSHFP Resource Record . . . . . . . . . . . . . . . . . 4
+ 3.1 The SSHFP RDATA Format . . . . . . . . . . . . . . . . . . . 5
+ 3.1.1 Algorithm Number Specification . . . . . . . . . . . . . . . 5
+ 3.1.2 Fingerprint Type Specification . . . . . . . . . . . . . . . 5
+ 3.1.3 Fingerprint . . . . . . . . . . . . . . . . . . . . . . . . 5
+ 3.2 Presentation Format of the SSHFP RR . . . . . . . . . . . . 6
+ 4. Security Considerations . . . . . . . . . . . . . . . . . . 6
+ 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . 7
+ Normative References . . . . . . . . . . . . . . . . . . . . 8
+ Informational References . . . . . . . . . . . . . . . . . . 8
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 9
+ A. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 9
+ Intellectual Property and Copyright Statements . . . . . . . 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 2]
+
+Internet-Draft DNS and SSH Fingerprints September 2003
+
+
+1. Introduction
+
+ The SSH [6] protocol provides secure remote login and other secure
+ network services over an insecure network. The security of the
+ connection relies on the server authenticating itself to the client
+ as well as the user authenticating itself to the server.
+
+ If a connection is established to a server whose public key is not
+ already known to the client, a fingerprint of the key is presented to
+ the user for verification. If the user decides that the fingerprint
+ is correct and accepts the key, the key is saved locally and used for
+ verification for all following connections. While some
+ security-conscious users verify the fingerprint out-of-band before
+ accepting the key, many users blindly accept the presented key.
+
+ The method described here can provide out-of-band verification by
+ looking up a fingerprint of the server public key in the DNS [1][2]
+ and using DNSSEC [5] to verify the lookup.
+
+ In order to distribute the fingerprint using DNS, this document
+ defines a new DNS resource record, "SSHFP", to carry the fingerprint.
+
+ Basic understanding of the DNS system [1][2] and the DNS security
+ extensions [5] is assumed by this document.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [3].
+
+2. SSH Host Key Verification
+
+2.1 Method
+
+ Upon connection to a SSH server, the SSH client MAY look up the SSHFP
+ resource record(s) for the host it is connecting to. If the
+ algorithm and fingerprint of the key received from the SSH server
+ match the algorithm and fingerprint of one of the SSHFP resource
+ record(s) returned from DNS, the client MAY accept the identity of
+ the server.
+
+2.2 Implementation Notes
+
+ Client implementors SHOULD provide a configurable policy used to
+ select the order of methods used to verify a host key. This document
+ defines one method: Fingerprint storage in DNS. Another method
+ defined in the SSH Architecture [6] uses local files to store keys
+ for comparison. Other methods that could be defined in the future
+ might include storing fingerprints in LDAP or other databases. A
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 3]
+
+Internet-Draft DNS and SSH Fingerprints September 2003
+
+
+ configurable policy will allow administrators to determine which
+ methods they want to use and in what order the methods should be
+ prioritized. This will allow administrators to determine how much
+ trust they want to place in the different methods.
+
+ One specific scenario for having a configurable policy is where
+ clients do not use fully qualified host names to connect to servers.
+ In this scenario, the implementation SHOULD verify the host key
+ against a local database before verifying the key via the fingerprint
+ returned from DNS. This would help prevent an attacker from injecting
+ a DNS search path into the local resolver and forcing the client to
+ connect to a different host.
+
+2.3 Fingerprint Matching
+
+ The public key and the SSHFP resource record are matched together by
+ comparing algorithm number and fingerprint.
+
+ The public key algorithm and the SSHFP algorithm number MUST
+ match.
+
+ A message digest of the public key, using the message digest
+ algorithm specified in the SSHFP fingerprint type, MUST match the
+ SSHFP fingerprint.
+
+
+2.4 Authentication
+
+ A public key verified using this method MUST NOT be trusted if the
+ SSHFP resource record (RR) used for verification was not
+ authenticated by a trusted SIG RR.
+
+ Clients that do validate the DNSSEC signatures themselves SHOULD use
+ standard DNSSEC validation procedures.
+
+ Clients that do not validate the DNSSEC signatures themselves MUST
+ use a secure transport, e.g. TSIG [9], SIG(0) [10] or IPsec [8],
+ between themselves and the entity performing the signature
+ validation.
+
+3. The SSHFP Resource Record
+
+ The SSHFP resource record (RR) is used to store a fingerprint of a
+ SSH public host key that is associated with a Domain Name System
+ (DNS) name.
+
+ The RR type code for the SSHFP RR is TBA.
+
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 4]
+
+Internet-Draft DNS and SSH Fingerprints September 2003
+
+
+3.1 The SSHFP RDATA Format
+
+ The RDATA for a SSHFP RR consists of an algorithm number, fingerprint
+ type and the fingerprint of the public host key.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | algorithm | fp type | /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
+ / /
+ / fingerprint /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+3.1.1 Algorithm Number Specification
+
+ This algorithm number octet describes the algorithm of the public
+ key. The following values are assigned:
+
+ Value Algorithm name
+ ----- --------------
+ 0 reserved
+ 1 RSA
+ 2 DSS
+
+ Reserving other types requires IETF consensus [4].
+
+3.1.2 Fingerprint Type Specification
+
+ The fingerprint type octet describes the message-digest algorithm
+ used to calculate the fingerprint of the public key. The following
+ values are assigned:
+
+ Value Fingerprint type
+ ----- ----------------
+ 0 reserved
+ 1 SHA-1
+
+ Reserving other types requires IETF consensus [4].
+
+ For interoperability reasons, as few fingerprint types as possible
+ should be reserved. The only reason to reserve additional types is
+ to increase security.
+
+3.1.3 Fingerprint
+
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 5]
+
+Internet-Draft DNS and SSH Fingerprints September 2003
+
+
+ The fingerprint is calculated over the public key blob as described
+ in [7].
+
+ The message-digest algorithm is presumed to produce an opaque octet
+ string output which is placed as-is in the RDATA fingerprint field.
+
+3.2 Presentation Format of the SSHFP RR
+
+ The RDATA of the presentation format of the SSHFP resource record
+ consists of two numbers (algorithm and fingerprint type) followed by
+ the fingerprint itself presented in hex, e.g:
+
+ host.example. SSHFP 2 1 123456789abcdef67890123456789abcdef67890
+
+ The use of mnemonics instead of numbers is not allowed.
+
+4. Security Considerations
+
+ Currently, the amount of trust a user can realistically place in a
+ server key is proportional to the amount of attention paid to
+ verifying that the public key presented actually corresponds to the
+ private key of the server. If a user accepts a key without verifying
+ the fingerprint with something learned through a secured channel, the
+ connection is vulnerable to a man-in-the-middle attack.
+
+ The overall security of using SSHFP for SSH host key verification is
+ dependent on the security policies of the SSH host administrator and
+ DNS zone administrator (in transferring the fingerprint), detailed
+ aspects of how verification is done in the SSH implementation, and in
+ the client's diligence in accessing the DNS in a secure manner.
+
+ One such aspect is in which order fingerprints are looked up (e.g.
+ first checking local file and then SSHFP). We note that in addition
+ to protecting the first-time transfer of host keys, SSHFP can
+ optionally be used for stronger host key protection.
+
+ If SSHFP is checked first, new SSH host keys may be distributed by
+ replacing the corresponding SSHFP in DNS.
+
+ If SSH host key verification can be configured to require SSHFP,
+ SSH host key revocation can be implemented by removing the
+ corresponding SSHFP from DNS.
+
+ As stated in Section 2.2, we recommend that SSH implementors provide
+ a policy mechanism to control the order of methods used for host key
+ verification. One specific scenario for having a configurable policy
+ is where clients use unqualified host names to connect to servers. In
+ this case, we recommend that SSH implementations check the host key
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 6]
+
+Internet-Draft DNS and SSH Fingerprints September 2003
+
+
+ against a local database before verifying the key via the fingerprint
+ returned from DNS. This would help prevent an attacker from injecting
+ a DNS search path into the local resolver and forcing the client to
+ connect to a different host.
+
+ A different approach to solve the DNS search path issue would be for
+ clients to use a trusted DNS search path, i.e., one not acquired
+ through DHCP or other autoconfiguration mechanisms. Since there is no
+ way with current DNS lookup APIs to tell whether a search path is
+ from a trusted source, the entire client system would need to be
+ configured with this trusted DNS search path.
+
+ Another dependency is on the implementation of DNSSEC itself. As
+ stated in Section 2.4, we mandate the use of secure methods for
+ lookup and that SSHFP RRs are authenticated by trusted SIG RRs. This
+ is especially important if SSHFP is to be used as a basis for host
+ key rollover and/or revocation, as described above.
+
+ Since DNSSEC only protects the integrity of the host key fingerprint
+ after it is signed by the DNS zone administrator, the fingerprint
+ must be transferred securely from the SSH host administrator to the
+ DNS zone administrator. This could be done manually between the
+ administrators or automatically using secure DNS dynamic update [11]
+ between the SSH server and the nameserver. We note that this is no
+ different from other key enrollment situations, e.g. a client sending
+ a certificate request to a certificate authority for signing.
+
+5. IANA Considerations
+
+ IANA needs to allocate a RR type code for SSHFP from the standard RR
+ type space (type 44 requested).
+
+ IANA needs to open a new registry for the SSHFP RR type for public
+ key algorithms. Defined types are:
+
+ 0 is reserved
+ 1 is RSA
+ 2 is DSA
+
+ Adding new reservations requires IETF consensus [4].
+
+ IANA needs to open a new registry for the SSHFP RR type for
+ fingerprint types. Defined types are:
+
+ 0 is reserved
+ 1 is SHA-1
+
+ Adding new reservations requires IETF consensus [4].
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 7]
+
+Internet-Draft DNS and SSH Fingerprints September 2003
+
+
+Normative References
+
+ [1] Mockapetris, P., "Domain names - concepts and facilities", STD
+ 13, RFC 1034, November 1987.
+
+ [2] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [3] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [4] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA
+ Considerations Section in RFCs", BCP 26, RFC 2434, October 1998.
+
+ [5] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [6] Ylonen, T., Kivinen, T., Saarinen, M., Rinne, T. and S.
+ Lehtinen, "SSH Protocol Architecture",
+ draft-ietf-secsh-architecture-14 (work in progress), July 2003.
+
+ [7] Ylonen, T., Kivinen, T., Saarinen, M., Rinne, T. and S.
+ Lehtinen, "SSH Transport Layer Protocol",
+ draft-ietf-secsh-transport-16 (work in progress), July 2003.
+
+Informational References
+
+ [8] Thayer, R., Doraswamy, N. and R. Glenn, "IP Security Document
+ Roadmap", RFC 2411, November 1998.
+
+ [9] Vixie, P., Gudmundsson, O., Eastlake, D. and B. Wellington,
+ "Secret Key Transaction Authentication for DNS (TSIG)", RFC
+ 2845, May 2000.
+
+ [10] Eastlake, D., "DNS Request and Transaction Signatures (
+ SIG(0)s)", RFC 2931, September 2000.
+
+ [11] Wellington, B., "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+
+
+
+
+
+
+
+
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 8]
+
+Internet-Draft DNS and SSH Fingerprints September 2003
+
+
+Authors' Addresses
+
+ Jakob Schlyter
+ OpenSSH
+ 812 23rd Avenue SE
+ Calgary, Alberta T2G 1N8
+ Canada
+
+ EMail: jakob@openssh.com
+ URI: http://www.openssh.com/
+
+
+ Wesley Griffin
+ SPARTA
+ 7075 Samuel Morse Drive
+ Columbia, MD 21046
+ USA
+
+ EMail: wgriffin@sparta.com
+ URI: http://www.sparta.com/
+
+Appendix A. Acknowledgements
+
+ The authors gratefully acknowledge, in no particular order, the
+ contributions of the following persons:
+
+ Martin Fredriksson
+
+ Olafur Gudmundsson
+
+ Edward Lewis
+
+ Bill Sommerfeld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 9]
+
+Internet-Draft DNS and SSH Fingerprints September 2003
+
+
+Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 10]
+
+Internet-Draft DNS and SSH Fingerprints September 2003
+
+
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Schlyter & Griffin Expires March 5, 2004 [Page 11]
+
diff --git a/doc/draft/draft-ihren-dnsext-threshold-validation-00.txt b/doc/draft/draft-ihren-dnsext-threshold-validation-00.txt
new file mode 100644
index 0000000..3578d2a
--- /dev/null
+++ b/doc/draft/draft-ihren-dnsext-threshold-validation-00.txt
@@ -0,0 +1,519 @@
+
+Internet Draft Johan Ihren
+draft-ihren-dnsext-threshold-validation-00.txt Autonomica
+February 2003
+Expires in six months
+
+
+ Threshold Validation:
+
+ A Mechanism for Improved Trust and Redundancy for DNSSEC Keys
+
+
+Status of this Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as
+ Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six
+ months and may be updated, replaced, or obsoleted by other
+ documents at any time. It is inappropriate to use Internet-Drafts
+ as reference material or to cite them other than as "work in
+ progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+
+Abstract
+
+ This memo documents a proposal for a different method of validation
+ for DNSSEC aware resolvers. The key change is that by changing from
+ a model of one Key Signing Key, KSK, at a time to multiple KSKs it
+ will be possible to increase the aggregated trust in the signed
+ keys by leveraging from the trust associated with the different
+ signees.
+
+ By having multiple keys to chose from validating resolvers get the
+ opportunity to use local policy to reflect actual trust in
+ different keys. For instance, it is possible to trust a single,
+ particular key ultimately, while requiring multiple valid
+ signatures by less trusted keys for validation to succeed.
+ Furthermore, with multiple KSKs there are additional redundancy
+ benefits available since it is possible to roll over different KSKs
+ at different times which may make rollover scenarios easier to
+ manage.
+
+Contents
+
+ 1. Terminology
+ 2. Introduction and Background
+
+ 3. Trust in DNSSEC Keys
+ 3.1. Key Management, Split Keys and Trust Models
+ 3.2. Trust Expansion: Authentication versus Authorization
+
+ 4. Proposed Semantics for Signing the KEY Resource Record
+ Set
+ 4.1. Packet Size Considerations
+
+ 5. Proposed Use of Multiple "Trusted Keys" in a Validating
+ Resolver
+ 5.1. Not All Possible KSKs Need to Be Trusted
+ 5.2. Possible to do Threshold Validation
+ 5.3. Not All Trusted Keys Will Be Available
+
+ 6. Additional Benefits from Having Multiple KSKs
+ 6.1. More Robust Key Rollovers
+ 6.2. Evaluation of Multiple Key Distribution Mechanisms
+
+ 7. Security Considerations
+ 8. IANA Considerations.
+ 9. References
+ 9.1. Normative.
+ 9.2. Informative.
+ 10. Acknowledgments.
+ 11. Authors' Address
+
+
+1. Terminology
+
+ The key words "MUST", "SHALL", "REQUIRED", "SHOULD", "RECOMMENDED",
+ and "MAY" in this document are to be interpreted as described in
+ RFC 2119.
+
+ The term "zone" refers to the unit of administrative control in the
+ Domain Name System. "Name server" denotes a DNS name server that is
+ authoritative (i.e. knows all there is to know) for a DNS zone,
+ typically the root zone. A "resolver", is a DNS "client", i.e. an
+ entity that sends DNS queries to authoritative nameservers and
+ interpret the results. A "validating resolver" is a resolver that
+ attempts to perform DNSSEC validation on data it retrieves by doing
+ DNS lookups.
+
+
+2. Introduction and Background
+
+ From a protocol perspective there is no real difference between
+ different keys in DNSSEC. They are all just keys. However, in
+ actual use there is lots of difference. First and foremost, most
+ DNSSEC keys have in-band verification. I.e. the keys are signed by
+ some other key, and this other key is in its turn also signed by
+ yet another key. This way a "chain of trust" is created. Such
+ chains have to end in what is referred to as a "trusted key" for
+ validation of DNS lookups to be possible.
+
+ A "trusted key" is a the public part of a key that the resolver
+ acquired by some other means than by looking it up in DNS. The
+ trusted key has to be explicitly configured.
+
+ A node in the DNS hierarchy that issues such out-of-band "trusted
+ keys" is called a "security apex" and the trusted key for that apex
+ is the ultimate source of trust for all DNS lookups within that
+ entire subtree.
+
+ DNSSEC is designed to be able to work with more than on security
+ apex. These apexes will all share the problem of how to distribute
+ their "trusted keys" in a way that provides validating resolvers
+ confidence in the distributed keys.
+
+ Maximizing that confidence is crucial to the usefulness of DNSSEC
+ and this document tries to address this issue.
+
+
+3. Trust in DNSSEC Keys
+
+ In the end the trust that a validating resolver will be able to put
+ in a key that it cannot validate within DNSSEC will have to be a
+ function of
+
+ * trust in the key issuer, aka the KSK holder
+
+ * trust in the distribution method
+
+ * trust in extra, out-of-band verification
+
+ The KSK holder needs to be trusted not to accidentally lose private
+ keys in public places. Furthermore it needs to be trusted to
+ perform correct identification of the ZSK holders in case they are
+ separate from the KSK holder itself.
+
+ The distribution mechanism can be more or less tamper-proof. If the
+ key holder publishes the public key, or perhaps just a secure
+ fingerprint of the key in a major newspaper it may be rather
+ difficult to tamper with. A key acquired that way may be easier to
+ trust than if it had just been downloaded from a web page.
+
+ Out-of-band verification can for instance be the key being signed
+ by a certificate issued by a known Certificate Authority that the
+ resolver has reason to trust.
+
+3.1. Simplicity vs Trust
+
+ The fewer keys that are in use the simpler the key management
+ becomes. Therefore increasing the number of keys should only be
+ considered when the complexity is not the major concern. A perfect
+ example of this is the distinction between so called Key Signing
+ Keys, KSK, and Zone Signing Keys, ZSK. This distinction adds
+ overall complexity but simplifies real life operations and was an
+ overall gain since operational simplification was considered to be
+ a more crucial issue than the added complexity.
+
+ In the case of a security apex there are additional issues to
+ consider, among them
+
+ * maximizing trust in the KSK received out-of-band
+
+ * authenticating the legitimacy of the ZSKs used
+
+ In some cases this will be easy, since the same entity will manage
+ both ZSKs and KSKs (i.e. it will authenticate itself, somewhat
+ similar to a self-signed certificate). In some environments it will
+ be possible to get the trusted key installed in the resolver end by
+ decree (this would seem to be a likely method within corporate and
+ government environments).
+
+ In other cases, however, this will possibly not be sufficient. In
+ the case of the root zone this is obvious, but there may well be
+ other cases.
+
+3.2. Expanding the "Trust Base"
+
+ For a security apex where the ZSKs and KSK are not held by the same
+ entity the KSK will effectively authenticate the identity of
+ whoever does real operational zone signing. The amount of trust
+ that the data signed by a ZSK will get is directly dependent on
+ whether the end resolver trusts the KSK or not, since the resolver
+ has no OOB access to the public part of the ZSKs (for practical
+ reasons).
+
+ Since the KSK holder is distinct from the ZSK holder the obvious
+ question is whether it would then be possible to further improve
+ the situation by using multiple KSK holders and thereby expanding
+ the trust base to the union of that available to each individual
+ KSK holder. "Trust base" is an invented term intended to signify
+ the aggregate of Internet resolvers that will eventually choose to
+ trust a key issued by a particular KSK holder.
+
+ A crucial issue when considering trust expansion through addition
+ of multiple KSK holders is that the KSK holders are only used to
+ authenticate the ZSKs used for signing the zone. I.e. the function
+ performed by the KSK is basically:
+
+ "This is indeed the official ZSK holder for this zone,
+ I've verified this fact to the best of my abilitites."
+
+ Which can be thought of as similar to the service of a public
+ notary. I.e. the point with adding more KSK holders is to improve
+ the public trust in data signed by the ZSK holders by improving the
+ strength of available authentication.
+
+ Therefore adding more KSK holders, each with their own trust base,
+ is by definition a good thing. More authentication is not
+ controversial. On the contrary, when it comes to authentication,
+ the more the merrier.
+
+
+4. Proposed Semantics for Signing the KEY Resource Record Set
+
+ In DNSSEC according to RFC2535 all KEY Resource Records are used to
+ sign all authoritative data in the zone, including the KEY RRset
+ itself, since RFC2535 makes no distinction between Key Signing
+ Keys, KSK, and Zone Signing Keys, ZSK. With Delegation Signer [DS]
+ it is possible to change this to the KEY RRset being signed with
+ all KSKs and ZSKs but the rest of the zone only being signed by the
+ ZSKs.
+
+ This proposal changes this one step further, by recommending that
+ the KEY RRset is only signed by the Key Signing Keys, KSK, and
+ explicitly not by the Zone Signing Keys, ZSK. The reason for this
+ is to maximize the amount of space in the DNS response packet that
+ is available for additional KSKs and signatures thereof. The rest
+ of the authoritative zone contents are as previously signed by only
+ the ZSKs.
+
+4.1. Packet Size Considerations
+
+ The reason for the change is to keep down the size of the aggregate
+ of KEY RRset plus SIG(KEY) that resolvers will need to acquire to
+ perform validation of data below a security apex. For DNSSEC data
+ to be returned the DNSSEC OK bit in the EDNS0 OPT Record has to be
+ set, and therefore the allowed packet size can be assumed to be at
+ least the EDNS0 minimum of 4000 bytes.
+
+ When querying for KEY + SIG(KEY) for "." (the case that is assumed
+ to be most crucial) the size of the response packet after the
+ change to only sign the KEY RR with the KSKs break down into a
+ rather large space of possibilities. Here are a few examples for
+ the possible alternatives for different numbers of KSKs and ZSKs
+ for some different key lengths (all RSA keys, with a public
+ exponent that is < 254). This is all based upon the size of the
+ response for the particular example of querying for
+
+ ". KEY IN"
+
+ with a response of entire KEY + SIG(KEY) with the authority and
+ additional sections empty:
+
+ ZSK/768 and KSK/1024 (real small)
+ Max 12 KSK + 3 ZSK at 3975
+ 10 KSK + 8 ZSK at 3934
+ 8 KSK + 13 ZSK at 3893
+
+ ZSK/768 + KSK/1280
+ MAX 10 KSK + 2 ZSK at 3913
+ 8 KSK + 9 ZSK at 3970
+ 6 KSK + 15 ZSK at 3914
+
+ ZSK/768 + KSK/1536
+ MAX 8 KSK + 4 ZSK at 3917
+ 7 KSK + 8 ZSK at 3938
+ 6 KSK + 12 ZSK at 3959
+
+ ZSK/768 + KSK/2048
+ MAX 6 KSK + 5 ZSK at 3936
+ 5 KSK + 10 ZSK at 3942
+
+ ZSK/1024 + KSK/1024
+ MAX 12 KSK + 2 ZSK at 3943
+ 11 KSK + 4 ZSK at 3930
+ 10 KSK + 6 ZSK at 3917
+ 8 KSK + 10 ZSK at 3891
+
+ ZSK/1024 + KSK/1536
+ MAX 8 KSK + 3 ZSK at 3900
+ 7 KSK + 6 ZSK at 3904
+ 6 KSK + 9 ZSK at 3908
+
+ ZSK/1024 + KSK/2048
+ MAX 6 KSK + 4 ZSK at 3951
+ 5 KSK + 8 ZSK at 3972
+ 4 KSK + 12 ZSK at 3993
+
+ Note that these are just examples and this document is not making
+ any recommendations on suitable choices of either key lengths nor
+ number of different keys employed at a security apex.
+
+ This document does however, based upon the above figures, make the
+ recommendation that at a security apex that expects to distribute
+ "trusted keys" the KEY RRset should only be signed with the KSKs
+ and not with the ZSKs to keep the size of the response packets
+ down.
+
+
+5. Proposed Use of Multiple "Trusted Keys" in a Validating Resolver
+
+ In DNSSEC according to RFC2535[RFC2535] validation is the process
+ of tracing a chain of signatures (and keys) upwards through the DNS
+ hierarchy until a "trusted key" is reached. If there is a known
+ trusted key present at a security apex above the starting point
+ validation becomes an exercise with a binary outcome: either the
+ validation succeeds or it fails. No intermediate states are
+ possible.
+
+ With multiple "trusted keys" (i.e. the KEY RRset for the security
+ apex signed by multiple KSKs) this changes into a more complicated
+ space of alternatives. From the perspective of complexity that may
+ be regarded as a change for the worse. However, from a perspective
+ of maximizing available trust the multiple KSKs add value to the
+ system.
+
+5.1. Possible to do Threshold Validation
+
+ With multiple KSKs a new option that opens for the security
+ concious resolver is to not trust a key individually. Instead the
+ resolver may decide to require the validated signatures to exceed a
+ threshold. For instance, given M trusted keys it is possible for
+ the resolver to require N-of-M signatures to treat the data as
+ validated.
+
+ I.e. with the following pseudo-configuration in a validating
+ resolver
+
+ security-apex "." IN {
+ keys { ksk-1 .... ;
+ ksk-2 .... ;
+ ksk-3 .... ;
+ ksk-4 .... ;
+ ksk-5 .... ;
+ };
+ validation {
+ # Note that ksk-4 is not present below
+ keys { ksk-1; ksk-2; ksk-3; ksk-5; };
+ # 3 signatures needed with 4 possible keys, aka 75%
+ needed-signatures 3;
+ };
+ };
+
+ we configure five trusted keys for the root zone, but require two
+ valid signatures for the top-most KEY for validation to
+ succeed. I.e. threshold validation does not force multiple
+ signatures on the entire signature chain, only on the top-most
+ signature, closest to the security apex for which the resolver has
+ trusted keys.
+
+5.2. Not All Trusted Keys Will Be Available
+
+ With multiple KSKs held and managed by separate entities the end
+ resolvers will not always manage to get access to all possible
+ trusted keys. In the case of just a single KSK this would be fatal
+ to validation and necessary to avoid at whatever cost. But with
+ several fully trusted keys available the resolver can decide to
+ trust several of them individually. An example based upon more
+ pseudo-configuration:
+
+ security-apex "." IN {
+ keys { ksk-1 .... ;
+ ksk-2 .... ;
+ ksk-3 .... ;
+ ksk-4 .... ;
+ ksk-5 .... ;
+ };
+ validation {
+ # Only these two keys are trusted independently
+ keys { ksk-1; ksk-4; };
+ # With these keys a single signature is sufficient
+ needed-signatures 1;
+ };
+ };
+
+ Here we have the same five keys and instruct the validating
+ resolver to fully trust data that ends up with just one signature
+ from by a fully trusted key.
+
+ The typical case where this will be useful is for the case where
+ there is a risk of the resolver not catching a rollover event by
+ one of the KSKs. By doing rollovers of different KSKs with
+ different schedules it is possible for a resolver to "survive"
+ missing a rollover without validation breaking. This improves
+ overall robustness from a management point of view.
+
+5.3. Not All Possible KSKs Need to Be Trusted
+
+ With just one key available it simply has to be trusted, since that
+ is the only option available. With multiple KSKs the validating
+ resolver immediately get the option of implementing a local policy
+ of only trusting some of the possible keys.
+
+ This local policy can be implemented either by simply not
+ configuring keys that are not trusted or, possibly, configure them
+ but specify to the resolver that certain keys are not to be
+ ultimately trusted alone.
+
+
+6. Additional Benefits from Having Multiple KSKs
+
+6.1. More Robust Key Rollovers
+
+ With only one KSK the rollover operation will be a delicate
+ operation since the new trusted key needs to reach every validating
+ resolver before the old key is retired. For this reason it is
+ expected that long periods of overlap will be needed.
+
+ With multiple KSKs this changes into a system where different
+ "series" of KSKs can have different rollover schedules, thereby
+ changing from one "big" rollover to several "smaller" rollovers.
+
+ If the resolver trusts several of the available keys individually
+ then even a failure to track a certain rollover operation within
+ the overlap period will not be fatal to validation since the other
+ available trusted keys will be sufficient.
+
+6.2. Evaluation of Multiple Key Distribution Mechanisms
+
+ Distribution of the trusted keys for the DNS root zone is
+ recognized to be a difficult problem that ...
+
+ With only one trusted key, from one single "source" to distribute
+ it will be difficult to evaluate what distribution mechanism works
+ best. With multiple KSKs, held by separate entitites it will be
+ possible to measure how large fraction of the resolver population
+ that is trusting what subsets of KSKs.
+
+
+7. Security Considerations
+
+ From a systems perspective the simplest design is arguably the
+ best, i.e. one single holder of both KSK and ZSKs. However, if that
+ is not possible in all cases a more complex scheme is needed where
+ additional trust is injected by using multiple KSK holders, each
+ contributing trust, then there are only two alternatives
+ available. The first is so called "split keys", where a single key
+ is split up among KSK holders, each contributing trust. The second
+ is the multiple KSK design outlined in this proposal.
+
+ Both these alternatives provide for threshold mechanisms. However
+ split keys makes the threshold integral to the key generating
+ mechanism (i.e. it will be a property of the keys how many
+ signatures are needed). In the case of multiple KSKs the threshold
+ validation is not a property of the keys but rather local policy in
+ the validating resolver. A benefit from this is that it is possible
+ for different resolvers to use different trust policies. Some may
+ configure threshold validation requiring multiple signatures and
+ specific keys (optimizing for security) while others may choose to
+ accept a single signature from a larger set of keys (optimizing for
+ redundancy). Since the security requirements are different it would
+ seem to be a good idea to make this choice local policy rather than
+ global policy.
+
+ Furthermore, a clear issue for validating resolvers will be how to
+ ensure that they track all rollover events for keys they
+ trust. Even with operlap during the rollover (which is clearly
+ needed) there is still a need to be exceedingly careful not to miss
+ any rollovers (or fail to acquire a new key) since without this
+ single key validation will fail. With multiple KSKs this operation
+ becomes more robust, since different KSKs may roll at different
+ times according to different rollover schedules and losing one key,
+ for whatever reason, will not be crucial unless the resolver
+ intentionally chooses to be completely dependent on that exact key.
+
+8. IANA Considerations.
+
+ NONE.
+
+
+9. References
+
+9.1. Normative.
+
+ [RFC2535] Domain Name System Security Extensions. D. Eastlake.
+ March 1999.
+
+ [RFC3090] DNS Security Extension Clarification on Zone Status.
+ E. Lewis. March 2001.
+
+
+9.2. Informative.
+
+ [RFC3110] RSA/SHA-1 SIGs and RSA KEYs in the Domain Name System
+ (DNS). D. Eastlake 3rd. May 2001.
+
+ [RFC3225] Indicating Resolver Support of DNSSEC. D. Conrad.
+ December 2001.
+
+ [DS] Delegation Signer Resource Record.
+ O. Gudmundsson. October 2002. Work In Progress.
+
+10. Acknowledgments.
+
+ Bill Manning came up with the original idea of moving complexity
+ from the signing side down to the resolver in the form of threshold
+ validation. I've also had much appreciated help from (in no
+ particular order) Jakob Schlyter, Paul Vixie, Olafur Gudmundson and
+ Olaf Kolkman.
+
+
+11. Authors' Address
+Johan Ihren
+Autonomica AB
+Bellmansgatan 30
+SE-118 47 Stockholm, Sweden
+johani@autonomica.se
diff --git a/doc/draft/draft-kato-dnsop-local-zones-00.txt b/doc/draft/draft-kato-dnsop-local-zones-00.txt
new file mode 100644
index 0000000..d857cd9
--- /dev/null
+++ b/doc/draft/draft-kato-dnsop-local-zones-00.txt
@@ -0,0 +1,295 @@
+
+
+
+Internet Engineering Task Force Akira Kato, WIDE
+INTERNET-DRAFT Paul Vixie, ISC
+Expires: August 24, 2003 February 24, 2003
+
+
+ Operational Guidelines for "local" zones in the DNS
+ draft-kato-dnsop-local-zones-00.txt
+
+Status of this Memo
+
+
+This document is an Internet-Draft and is in full conformance with all
+provisions of Section 10 of RFC2026.
+
+Internet-Drafts are working documents of the Internet Engineering Task
+Force (IETF), its areas, and its working groups. Note that other groups
+may also distribute working documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any
+time. It is inappropriate to use Internet-Drafts as reference material
+or to cite them other than as ``work in progress.''
+
+To view the list Internet-Draft Shadow Directories, see
+http://www.ietf.org/shadow.html.
+
+Distribution of this memo is unlimited.
+
+The internet-draft will expire in 6 months. The date of expiration will
+be August 24, 2003.
+
+
+Abstract
+
+A large number of DNS queries regarding to the "local" zones are sent
+over the Internet in every second. This memo describes operational
+guidelines to reduce the unnecessary DNS traffic as well as the load of
+the Root DNS Servers.
+
+1. Introduction
+
+While it has yet been described in a RFC, .local is used to provide a
+local subspace of the DNS tree. Formal delegation process has not been
+completed for this TLD. In spite of this informal status, .local has
+been used in many installations regardless of the awareness of the
+users. Usually, the local DNS servers are not authoritative to the
+.local domain, they end up to send queries to the Root DNS Servers.
+
+There are several other DNS zones which describe the "local"
+information. .localhost has been used to describe the localhost for
+more than a couple of decades and virtually all of the DNS servers are
+configured authoritative for .localhost and its reverse zone .127.in-
+
+
+KATO Expires: August 24, 2003 [Page 1]
+
+
+DRAFT DNS local zones February 2003
+
+addr.arpa. However, there are other "local" zones currently used in the
+Internet or Intranets connected to the Internet through NATs or similar
+devices.
+
+At a DNS server of an university in Japan, half of the DNS queries sent
+to one of the 13 Root DNS Servers were regarding to the .local. At
+another DNS Server running in one of the Major ISPs in Japan, the 1/4
+were .local. If those "local" queries are able to direct other DNS
+servers than Root, or they can be resolved locally, it contributes the
+reduction of the Root DNS Servers.
+
+2. Rationale
+
+Any DNS queries regarding to "local" names should not be sent to the DNS
+servers on the Internet.
+
+3. Operational Guidelines
+
+Those queries should be processed at the DNS servers internal to each
+site so that the severs respond with NXDOMAIN rather than sending
+queries to the DNS servers outside.
+
+The "local" names have common DNS suffixes which are listed below:
+
+3.1. Local host related zones:
+
+Following two zones are described in [Barr, 1996] and .localhost is also
+defined in [Eastlake, 1999] .
+
+ o .localhost
+ o .127.in-addr.arpa
+
+
+Following two zones are for the loopback address in IPv6 [Hinden, 1998]
+. While the TLD for IPv6 reverse lookup is .arpa as defined in [Bush,
+2001] , the old TLD .int has been used for this purpose for years
+[Thomson, 1995] and many implementations still use .int. So it is
+suggested that both zones should be provided for each IPv6 reverse
+lookup zone for a while.
+
+ o 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.int
+ o 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa
+
+
+3.2. Locally created name space
+
+While the use of .local has been proposed in several Internet-Drafts, it
+has not been described in any Internet documents with formal status.
+However, the amount of the queries for .local is much larger than
+others, it is suggested to resolve the following zone locally:
+
+
+
+
+KATO Expires: August 24, 2003 [Page 2]
+
+
+DRAFT DNS local zones February 2003
+
+ o .local
+
+
+
+3.3. Private or site-local addresses
+
+The following IPv4 "private" addresses [Rekhter, 1996] and IPv6 site-
+local addresses [Hinden, 1998] should be resolved locally:
+
+ o 10.in-addr.arpa
+ o 16.172.in-addr.arpa
+ o 17.172.in-addr.arpa
+ o 18.172.in-addr.arpa
+ o 19.172.in-addr.arpa
+ o 20.172.in-addr.arpa
+ o 21.172.in-addr.arpa
+ o 22.172.in-addr.arpa
+ o 23.172.in-addr.arpa
+ o 24.172.in-addr.arpa
+ o 25.172.in-addr.arpa
+ o 26.172.in-addr.arpa
+ o 27.172.in-addr.arpa
+ o 28.172.in-addr.arpa
+ o 29.172.in-addr.arpa
+ o 30.172.in-addr.arpa
+ o 31.172.in-addr.arpa
+ o 168.192.in-addr.arpa
+ o c.e.f.ip6.int
+ o d.e.f.ip6.int
+ o e.e.f.ip6.int
+ o f.e.f.ip6.int
+ o c.e.f.ip6.arpa
+ o d.e.f.ip6.arpa
+ o e.e.f.ip6.arpa
+ o f.e.f.ip6.arpa
+
+
+3.4. Link-local addresses
+
+The link-local address blocks for IPv4 [IANA, 2002] and IPv6 [Hinden,
+1998] should be resolved locally:
+
+ o 254.169.in-addr.arpa
+ o 8.e.f.ip6.int
+ o 9.e.f.ip6.int
+ o a.e.f.ip6.int
+ o b.e.f.ip6.int
+ o 8.e.f.ip6.arpa
+ o 9.e.f.ip6.arpa
+ o a.e.f.ip6.arpa
+ o b.e.f.ip6.arpa
+
+
+
+KATO Expires: August 24, 2003 [Page 3]
+
+
+DRAFT DNS local zones February 2003
+
+4. Suggestions to developers
+
+4.1. Suggestions to DNS software implementors
+
+In order to avoid unnecessary traffic, it is suggested that DNS software
+implementors provide configuration templates or default configurations
+so that the names described in the previous section are resolved locally
+rather than sent to other DNS servers in the Internet.
+
+4.2. Suggestions to developers of NATs or similar devices
+
+There are many NAT or similar devices available in the market.
+Regardless of the availability of DNS Servers in those devices, it is
+suggested that those devices are able to filter the DNS traffic or
+respond to the DNS traffic related to "local" zones by configuration
+regardless of its ability of DNS service. It is suggested that this
+functionality is activated by default.
+
+5. IANA Consideration
+
+While .local TLD has yet defined officially, there are substantial
+queries to the Root DNS Servers as of writing. About 1/4 to 1/2% of the
+traffic sent to the Root DNS Servers are related to the .local zone.
+Therefore, while it is not formally defined, it is suggested that IANA
+delegates .local TLD to an organization.
+
+The AS112 Project [Vixie, ] serves authoritative DNS service for RFC1918
+address and the link-local address. It has several DNS server instances
+around the world by using BGP Anycast [Hardie, 2002] . So the AS112
+Project is one of the candidates to host the .local TLD.
+
+Authors' addresses
+
+ Akira Kato
+ The University of Tokyo, Information Technology Center
+ 2-11-16 Yayoi Bunkyo
+ Tokyo 113-8658, JAPAN
+ Tel: +81 3-5841-2750
+ Email: kato@wide.ad.jp
+
+
+ Paul Vixie
+ Internet Software Consortium
+ 950 Charter Street
+ Redwood City, CA 94063, USA
+ Tel: +1 650-779-7001
+ Email: vixie@isc.org
+
+
+
+
+
+
+
+KATO Expires: August 24, 2003 [Page 4]
+
+
+DRAFT DNS local zones February 2003
+
+References
+
+To be filled
+
+References
+
+Barr, 1996.
+D. Barr, "Common DNS Operational and Configuration Errors" in RFC1912
+(February 1996).
+
+Eastlake, 1999.
+D. Eastlake, "Reserved Top Level DNS Names" in RFC2606 (June 1999).
+
+Hinden, 1998.
+R. Hinden and S. Deering, "IP Version 6 Addressing Architecture" in
+RFC2373 (July 1998).
+
+Bush, 2001.
+R. Bush, "Delegation of IP6.ARPA" in RFC3152 (August 2001).
+
+Thomson, 1995.
+S. Thomson and C. Huitema, "DNS Extensions to support IP version 6" in
+RFC1886 (December 1995).
+
+Rekhter, 1996.
+Y. Rekhter, B. Moskowitz, D. Karrenberg, G. J. de Groot, and E. Lear,
+"Address Allocation for Private Internets" in RFC1918 (February 1996).
+
+IANA, 2002.
+IANA, "Special-Use IPv4 Addresses" in RFC3330 (September 2002).
+
+Vixie, .
+P. Vixie, "AS112 Project" in AS112. http://www.as112.net/.
+
+Hardie, 2002.
+T. Hardie, "Distributing Authoritative Name Servers via Shared Unicast
+Addresses" in RFC3258 (April 2002).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+KATO Expires: August 24, 2003 [Page 5]
+
diff --git a/doc/draft/draft-park-ipv6-extensions-dns-pnp-00.txt b/doc/draft/draft-park-ipv6-extensions-dns-pnp-00.txt
new file mode 100644
index 0000000..f9eaf26
--- /dev/null
+++ b/doc/draft/draft-park-ipv6-extensions-dns-pnp-00.txt
@@ -0,0 +1,1830 @@
+
+
+
+ INTERNET-DRAFT S. Daniel Park
+ Expires: October 2003 Syam Madanapalli
+ File: SAMSUNG Electronics
+ draft-park-ipv6-extensions-dns-pnp-00.txt April 2003
+
+
+
+
+ IPv6 Extensions for DNS Plug and Play
+
+
+
+ Status of This Memo
+
+ This document is an Internet-Draft and is in full conformance with
+ all provisions of Section 10 of RFC2026.
+
+ Internet-Drafts are working documents of the Internet Engineering
+ Task Force (IETF), its areas, and its working groups. Note that
+ other groups may also distribute working documents as
+ Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six
+ months and may be updated, replaced, or obsoleted by other
+ documents at any time. It is inappropriate to use Internet-Drafts
+ as reference material or to cite them other than as "work in
+ progress."
+
+ The list of current Internet-Drafts can be accessed at
+ http://www.ietf.org/ietf/1id-abstracts.txt
+
+ The list of Internet-Draft Shadow Directories can be accessed at
+ http://www.ietf.org/shadow.html.
+
+
+
+ Abstract
+
+ This document proposes automatic configuration of domain name (FQDN)
+ for IPv6 nodes using Domain Name Auto-Configuration (called 6DNAC) as
+ a part of IPv6 plug and play feature. 6DNAC allows the automatic
+ registration of domain name and corresponding IPv6 Addresses with
+ the DNS server. In order to provide 6DNAC function, Neighbor Discovery
+ Protocol [2461] will be used. Moreover, 6DNAC does not require any
+ changes to the existing DNS system.
+
+
+ Table of Contents
+
+ 1. Introduction ............................................. 3
+ 2. Terminology .............................................. 3
+ 3. 6DNAC Design Principles .................................. 4
+ 4. 6DNAC Overview ........................................... 4
+ 5. 6DNAC Requirements ....................................... 5
+ 5.1. 6DANR Client Requirements ................................ 5
+ 5.2. 6DNAC Server Requirements ................................ 6
+
+Park & Madanapalli Expires October 2003 [Page 1]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ 6. 6DNAC Messages and Option Formats ........................ 6
+ 6.1. Router Advertisement (RA) Message Format ................. 6
+ 6.2. Neighbor Solicitation (NS) Message Format ................ 7
+ 6.3. Neighbor Advertisement (NA) Message Format ............... 8
+ 6.4. Option Formats ........................................... 8
+ 6.4.1. DNS Zone Suffix Information Option Format ................ 8
+ 6.4.2. Domain Name (FQDN) Option Format ......................... 9
+ 6.4.3. Router Alert Option for 6DNAC ............................ 10
+ 7. 6DNAC Operation .......................................... 10
+ 7.1. 6DNAC Network Topology ................................... 11
+ 7.2. 6DNAC Operational Scenarios .............................. 12
+ 7.2.1. Domain Name Registration-Success Case .................... 12
+ 7.2.2. Domain Name Registration-with DupAddrDetectTransmits=2.... 14
+ 7.2.3. Domain Name Registration-Defend Case ..................... 16
+ 7.2.4. Domain Name Registration in Retry Mode ................... 19
+ 7.2.5. Domain Name Registration when DAD Fails .................. 20
+ 7.3. DNS Zone Suffix Discovery and FQDN Construction .......... 22
+ 7.3.1. Sending Router Advertisement Messages .................... 22
+ 7.3.2. Processing Router Advertisement Messages ................. 22
+ 7.3.3. FQDN Lifetime expiry ..................................... 23
+ 7.3.4. Host Naming Algorithm .................................... 23
+ 7.4. Duplicate Domain Name Detection .......................... 23
+ 7.4.1. DAD with All Nodes Multicast Address ..................... 24
+ 7.4.1.1. Sending Neighbor Solicitation Messages ................... 24
+ 7.4.1.2. Processing Neighbor Solicitation Messages ................ 24
+ 7.4.1.3. Sending Neighbor Advertisement Messages .................. 25
+ 7.4.1.4. Processing Neighbor Advertisement Messages ............... 25
+ 7.4.1.5. Pros and Cons ............................................ 25
+ 7.4.2. DAD with Router Alert Option for 6DNAC ................... 25
+ 7.4.2.1. Sending Neighbor Solicitation Messages ................... 25
+ 7.4.2.2. Processing Neighbor Solicitation Messages ................ 26
+ 7.4.2.3. Sending Neighbor Advertisement Messages .................. 26
+ 7.4.2.4. Processing Neighbor Advertisement Messages ............... 26
+ 7.4.2.5. Pros and Cons ............................................ 26
+ 7.4.3. Explicit Detection of Duplicate Domain Name .............. 26
+ 7.4.3.1. Sending Neighbor Solicitation Messages ................... 26
+ 7.4.3.2. Processing Neighbor Solicitation Messages ................ 26
+ 7.4.3.3. Sending Neighbor Advertisement Messages .................. 27
+ 7.4.3.4. Processing Neighbor Advertisement Messages ............... 27
+ 7.4.3.5. Pros and Cons ............................................ 27
+ 7.4.4. Retry Mode for Re-registering Domain Name ................ 27
+ 7.5. Domain Name Registration ................................. 27
+ 8. Security Consideration ................................... 27
+ 9. IANA Consideration ....................................... 28
+ 10. Acknowledgement .......................................... 28
+ 11. Intellectual Property .................................... 28
+ 12. Copyright ................................................ 28
+ 13. References ............................................... 29
+ 14. Author's Addresses ....................................... 30
+
+
+
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 2]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ 1. Introduction
+
+ Today, most networks use DNS[1034][1035] for convenience. In case of
+ IPv6, DNS is more important element because of IPv6 long addresses
+ which are difficult to remember. In addition, small networks like home
+ networks using IPv6, should be able to make network easily without
+ manual configuration. Also, these small networks may not have DHCP
+ Server, DNS Server etc. that are used to configure the network. This
+ document discusses IPv6 Domain Name Auto-Configuration(6DNAC) procedure
+ for generating and registering the Domain Name and IPv6 addresses with
+ the DNS Server automatically. In order to use 6DNAC, IPv6 nodes are
+ required to implement lightweight functions specified in this document.
+ 6DNAC can be applied to all defined IPv6 unicast addresses except Link
+ local IPv6 addresses, viz: Site-local and Global addresses.
+
+ 6DNAC uses Neighbor Discovery Protocol [2461] with new additions
+ (defined in section 6) and DAD procedures for generating and
+ registering the Domain Name with the DNS server automatically.
+
+
+ 2. Terminology
+
+ 6DNAC - IPv6 Domain Name Auto Configuration. It can provide
+ IPv6 hosts with Domain Name Generation and
+ Registration automatically.
+
+ 6DNAC Client - An IPv6 node that can generate its own unique Domain
+ Name. Section 3 identifies the new requirements that
+ 6DNAC places on an IPv6 node to be a 6DNAC node.
+
+ 6DNAC Server - An IPv6 node that can collect and registrate Domain
+ Name and IPv6 addresses automatically. 6DNAC server
+ uses the information from the DAD operation messages
+ with newly defined options for the registration of the
+ Domain Name and IPv6 Addresses. Section 3 identifies
+ the new requirements that 6DNAC places on an IPv6
+ node to be a 6DNAC server. Also 6DNAC server can have
+ various other functions depending on network
+ environment and the network operator. For instance
+ 6DNAC Server can acts as a Gateway as well Home Server
+ in Home Networks.
+
+ DAD - Duplicate Address Detection (is defined [2461])
+
+ DFQDND - Duplicate Domain Name Detection
+
+ FQDN - Fully Qualified Domain Name - FQDN and Domain Name are
+ used interchangeably in this document.
+
+ NA - Neighbor Advertisement message (is defined [2461])
+
+ NS - Neighbor Solicitation message (is defined [2461])
+
+ RA - Router Advertisement message (is defined [2461])
+
+ SLAAC - Stateless Address Autoconfiguration [2462].
+
+Park & Madanapalli Expires October 2003 [Page 3]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ 3. 6DNAC Design Principles
+
+ This section discusses the design principles of 6DNAC mechanism.
+
+ 1. The new procedures for plug and play DNS should not cause changes
+ to existing DNS system. 6DNAC requires lightweight functions to be
+ implemented only at the client side of the DNS system, and uses the
+ existing DDNS UPDATE [2136] to communicate with DNS Servers.
+
+ 2. Introducing a new protocol will always introduce new problems.
+ 6DNAC uses the existing protocols NDP [2461] with minor extensions
+ for generating and registering the domain name automatically
+ without defining a new protocol
+
+ 3. Reusing proven and well understood design principles/patterns
+ will always yield a robust system. 6DNAC is based on IPv6 Address
+ Auotoconfiguration principle, where routers advertise the prefix
+ and host adds the interface ID to the prefix and forms the IPv6
+ address. Domain Name (FQDN) also contains two parts: host name
+ and DNS zone suffix. Routers can advertise the DNS zone suffix
+ on a particular link in Router Advertisements (RA Messages) and
+ hosts can prefix their preferred host name to the DNS zone suffix
+ and form the fully qualified domain name. Also the detection of
+ duplicate domain name is similar to Duplicate Address Detection
+ (DAD) and can be part of DAD operation itself.
+
+
+ 4. 6DNAC Overview
+
+ 6DNAC proposes minor extensions to NDP [2461] for automatic generation
+ and registration of domain name with the DNS server. It introduces two
+ new options: DNS Zone Suffix and Fully Qualified Domain Name. DNS Zone
+ Suffix option is carried in Router Advertisement (RA) messages for
+ notifying IPv6 nodes about the valid DNS Zone Suffix on the link and
+ FQDN option in Neighbor Solicitation (NS) and Neighbor Advertisement
+ (NA) messages to detect duplicate domain name. 6DNAC consists of two
+ components: 6DNAC Client and 6DNAC Server. 6DNAC Clients generate the
+ domain name based on DNS Zone Suffix using Host Naming Algorithm (see
+ section 7.3.1) and 6DNAC Server collects and registers the DNS
+ information with the DNS Server on behalf of 6DNAC Clients.
+
+ The automatic configuration of domain name using 6DNAC consists of
+ three parts.
+
+ - DNS Zone Suffix Discovery and FQDN Construction:
+
+ IPv6 Nodes collect DNS Zone Suffix information from Router
+ Advertisements and constructs FQDN by prefixing host name to the
+ DNS Zone Suffix. The IPv6 Nodes are required to implement Host
+ Naming Algorithm for generating host part of the FQDN in the
+ absence of administrator.
+
+ Generation of node's FQDN within the node itself has advantages. Nodes
+ can provide forward and reverse name lookups independent of the DNS
+ System by sending queries directly to IPv6 nodes [NIQ]. Moreover Domain
+ Name is some thing that is owned by the node.
+
+Park & Madanapalli Expires October 2003 [Page 4]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ - Duplicate Domain Name Detection
+
+ All nodes are expected to go for DAD for all new IPv6 unicast
+ addresses, regardless of whether they are obtained through
+ stateful, stateless or manual configuration. 6DNAC uses the DAD
+ messages with new option for carrying the Domain Name along with
+ the new IPv6 Address. 6DNAC Server captures this information and
+ updates DNS Server provided that the IPv6 Address and its domain
+ name are not duplicate. If the domain name is already in use,
+ the 6DNAC server replies to the sender with FQDN Option in NA
+ message indicating that the domain name is duplicate. Then the
+ node is expected to generate another domain name using host
+ naming algorithm and go for DAD. This time the DAD is only for
+ duplicate domain name detection (DFQDND). In order to avoid
+ confusion with the normal NDP processing, the target address
+ field of the NS message must carry the unspecified address
+ in retry mode. This can be repeated depending on number of
+ retries defined by the administrator in the host naming algorithm.
+
+
+ - Domain Name Registration
+
+ 6DNAC Server detects the DNS information (IPv6 Address and
+ corresponding FQDN) from DAD/DFQDND messages and updates DNS
+ Server using existing protocol DDNS UPDATE [2136] provided that
+ the IPv6 Address and its domain name are not duplicate.
+
+ If an IPv6 Address is duplicate, the IPv6 node cannot perform
+ stateless address autoconfiguration repeatedly. Unlike IPv6 stateless
+ address autoconfiguration, 6DNAC allows the automatic configuration of
+ domain name repeatedly if the domain name is duplicate depending on
+ number of retries defined by the administrator in the host naming
+ algorithm.
+
+
+ 5. 6DNAC Requirements
+
+ Depending on the 6DNAC functionality, the IPv6 nodes implement, they
+ are called either 6DNAC Clients or 6DNAC Servers. The following
+ sections lists the requirements that the 6DNAC Client and 6DNAC server
+ must support.
+
+
+ 5.1. 6DANC Client Requirements
+
+ - 6DNAC Client must recognize and process the following NDP
+ extensions
+
+ - DNS Zone Suffix option in RA messages for generating its
+ domain name (FQDN).
+
+ - Domain Name option in NS and NA messages for detecting
+ the duplicate domain name
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 5]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ - It must generate its domain name (FQDN) based on the DNS
+ suffix that it got from the router advertisement. And it must
+ have a host naming algorithm for generating the host part of
+ the FQDN.
+
+ - If NA message is received with unspecified target address and
+ FQDN option, then the node must treat that the domain is
+ duplicate.
+
+
+ 5.2. 6DNAC Server Requirements
+
+ - 6DNAC Server must recognize and process the following NDP
+ extensions
+
+ - If the 6DNAC Server is a router on the link, then it
+ must advertise DNS Zone Suffix option in RA messages
+ for hosts to generate their domain name (FQDN).
+
+ - FQDN option in NS messages for detecting new DNS
+ information for of nodes on the link for which it
+ must update the AAAA RR and PTR RR in DNS Server.
+
+ - FQDN option in NA messages for notifying duplicate
+ domain name with unspecified target address.
+
+ - 6DNAC server must update the DNS Server (both AAAA RR and
+ PTR RR) dynamically using DDNS UPDATE [2136].
+
+ - 6DNAC server must cache this (newly detected) FQDN, Link
+ Layer Address, and IPv6 Address information, so that it can
+ decide whether it really needs to update DNS Server or not,
+ to avoid redundant updates. This information will also be
+ used for notifying the duplicate domain name.
+
+
+ 6. 6DNAC Messages and Option Formats
+
+ In order to achieve the plug and play DNS, 6DNAC proposes new
+ extensions to the NDP [2461]. This section specifies the new
+ additions to NDP messages and formats of new options.
+
+
+ 6.1. Router Advertisement (RA) Message Format
+
+ Routers send out Router Advertisement (RA) message periodically, or
+ in response to a Router Solicitation. 6DNAC does not modify the format
+ of the RA message, but proposes new option (DNS Zone Suffix Information)
+ to be carried in RA messages.
+
+
+
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 6]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Cur Hop Limit |M|O| Reserved | Router Lifetime |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reachable Time |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Retrans Timer |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options ... |
+ / /
+ | DNS Zone Suffix Information |
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ <Figure: 1 RA message>
+
+
+
+ 6.2. Neighbor Solicitation (NS) Message Format
+
+ 6DNAC does not modify the format of the Neighbor Solicitation (NS)
+ message, but proposes new option (FQDN Option) to be carried in NS
+ messages. When a node is going for DAD, the node must include FQDN
+ option in NS message to participate in plug and play DNS. If the
+ node is going for Explicit Detection of Duplicate Domain Name, the
+ node must use FQDN option in NS message and unspecified address in
+ the target address field.
+
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Target Address +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options ... |
+ / /
+ | Domain Name |
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ <Figure: 2 NS message>
+
+Park & Madanapalli Expires October 2003 [Page 7]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ 6.3. Neighbor Advertisement (NA) Message Format
+
+ 6DNAC does not modify the format of the Neighbor Advertisement (NA)
+ message, but proposes new option (FQDN Option) to be carried in NA
+ messages. 6DNAC Server sends NA message with FQDN option to 6DNAC
+ Client that is performing duplicate domain name detection in case
+ the domain name found to be duplicate.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |R|S|O| Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Target Address +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options ... |
+ / /
+ | FQDN Option |
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ <Figure: 3 NA message>
+
+
+ 6.4 Option Formats
+
+ 6.4.1. DNS Zone Suffix Information Option Format
+
+ IPv6 nodes require DNS Zone Suffix for constructing their FQDN.
+ 6DNAC introduces new option for routers to advertise the DNS Zone
+ Suffix Information for IPv6 nodes on the link. The suffix information
+ should be configured into routers manually.
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Valid Lifetime |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ / DNS Zone Suffix /
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ <Figure: 4 DNS Zone Suffix Information>
+
+Park & Madanapalli Expires October 2003 [Page 8]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ Type [TBD]
+
+ Length 8-bit unsigned integer. The length of the option
+ (including the type and length fields) in units of
+ 8 octets.
+
+ Reserved This field is unused. It must be initialized to zero
+ by the sender and must be ignored by the receiver.
+
+ Valid Life Time 32-bit signed integer. The maximum time, in
+ seconds, over which this suffix is valid. Nodes
+ should treat this as the life time for their domain
+ name. Nodes should contact the source of this
+ information before expiry of this time interval.
+ A value of all one bits (0xFFFFFFFF) represents
+ infinity.
+
+ DNS Zone Suffix The suffix part of the FQDN. The data in the DNS
+ Zone Suffix field should be encoded according to
+ DNS encoding rules specified in [1035].
+
+
+
+ 6.4.2. Domain Name (FQDN) Option Format
+
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Length | Reserved |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Valid Lifetime |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + FQDN Target Address +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ / Domain Name /
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+ <Figure: 5 FQDN Information>
+
+ Type [TBD]
+
+ Length 8-bit unsigned integer. The length of the option
+ (including the type and length fields) in units
+ of 8 octets. It must be greater than 3.
+
+
+
+Park & Madanapalli Expires October 2003 [Page 9]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ Reserved This field is unused. It must be initialized to
+ zero by the sender and must be ignored by the
+ receiver.
+
+ Valid Life Time 32-bit signed integer. The maximum time, in
+ seconds, over which this domain name is valid
+ 6DNAC should deregister this domain name at
+ the expiry of this interval. 6DNAC clients
+ should send updates by the expiry of this
+ interval. A value of all one bits (0xFFFFFFFF)
+ represents infinity.
+
+ FQDN Target Address The Address for which the FQDN maps to. It
+ should be same as Target Address field of the
+ NS message in case of DAD & duplicate FQDN are
+ running in parallel.
+
+ Domain Name The domain name (FQDN) of the node. The data in
+ the domain name should be encoded according to
+ DNS encoding rules specified in [1035].
+
+
+ 6.4.3. Router Alert Option for 6DNAC
+
+ Router Alert Option for 6DNAC is new option within the IPv6 Hop-by-Hop
+ Header for using in NDP messages. The presence of this option in NS
+ message informs the router that this NS message is carrying Domain
+ Name information and must be processed by the 6DNAC Server on the router.
+ 6DNAC Clients can use this option for sending DAD packets instead
+ of addressing the DAD packets to the all-nodes multicast address
+ when 6DNAC Server is implemented on router.
+
+ The Router Alert option has the following format:
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |0 0 0|0 0 1 0 1|0 0 0 0 0 0 1 0| Value (2 octets) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ Length = 2
+
+ Values are registered and maintained by the IANA. For 6DNAC, the
+ value has to be assigned by IANA.
+
+ Further information about this option can be obtained from
+ IPv6 Router Alert Option [2711].
+
+
+ 7. 6DNAC Operation
+
+ 6DNAC provides mechanisms for automatic generation of domain name
+ and registering it with the DNS Server for IPv6 nodes. 6DNAC consists
+ of two components: 6DNAC Client and 6DNAC Server. All nodes that want
+ to participate in plug and play DNS are required to implement 6DNAC
+ Client functionality, and one of the IPv6 nodes is required to
+ implement 6DNAC Server functionality. The IPv6 node that implements
+ the 6DNAC Server functionality must know the location of the DNS
+ Server and must be a trusted node to send DDNS UPDATE [2136] messages.
+
+Park & Madanapalli Expires October 2003 [Page 10]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ 7.1. 6DNAC Network Topology
+
+ This section identifies the possible locations for the 6DNAC Server.
+ Note that, all nodes are required to implement 6DNAC Client
+ functionality for constructing the domain name from the DNS Zone
+ Suffix Information advertised by the router. Figure 6 illustrates
+ IPv6 host (H4) implementing 6DNAC Server functionality. In this case
+ H4 can serve only one link (that it belongs to) for automatic
+ registration of domain name. H4 must observe the DAD packets on the
+ link to detect the DNS information, this requires all nodes on the
+ link must belong to same solicited node multicast address. In general,
+ this may not be the case. So the node that is going for DAD must use
+ all nodes multicast address for DAD packets, so that the 6DNAC Server
+ (H4) can observe the DAD packets, detects IPv6 address and
+ corresponding domain name, checks if this domain name is duplicate
+ and finally registers the domain name with the DNS Server.
+
+
+ 6DNAC Server
+ +---+ +---+ +----------+
+ | H1| | H4|<--- DDNS UPDATE --->|DNS Server|
+ +-+-+ +-+-+ +----+-----+
+ | | +----+ +---/
+ | | | | /
+ ---+-----+-----------+-----+-----------+ R1 +-----+
+ | | | |
+ | | +----+
+ +-+-+ +-+-+
+ | H2| | H3|
+ +---+ +---+
+
+
+ H1, H2, H3 - 6DNAC Clients
+ H4 - 6DNAC Server
+ R1 - Router
+
+
+ <Figure: 6 Example of 6DNAC Topology>
+
+
+ Figure 7 shows the 6DNAC Server implemented on a router R1. In this
+ case a single 6DNAC server can serve multiple links for automatic
+ configuration of the domain name. This topology also has flexibility
+ of using DAD packets with Router Alert option instead of sending DAD
+ packets to all nodes multicast address. The routers are required to
+ process all the packets with Router Alert option as per [2711].
+
+ In case of Home Networks, R1 is will acts as a Home Gateway (CPE)
+ connected to ISP. R1 delegates the prefix from the ISP edge router.
+ After delegating the prefix the CPE can advertise the DNS Zone suffix
+ along with the prefix information to the nodes on the links to which
+ the router is connected to. Note that the R1 must be configured with
+ the DNS Zone suffix Information manually.
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 11]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ +---+ +---+
+ | H3+ | H4|
+ +-+-+ +-+-+
+ | |
+ | LINK2 |
+ +---+ ---+--------+--+-- +----------+
+ | H1| | |DNS Server|
+ +-+-+ | +----+-----+
+ | +--+-+ -------/
+ | LINK 1 | | /
+ ---+-----+------------------+ R1 +---------+
+ | | | DDNS UPDATE
+ | +----+
+ +-+-+ 6DNAC Server
+ | H2|
+ +---+
+
+
+ H1, H2 - 6DNAC Clients on Link1
+ H3, H4 - 6DNAC Clients on Link2
+ R1 - Router with 6DNAC Server, serving both Link1 and Link2
+
+
+ <Figure: 7 Example of 6DNAC Server serving multiple links>
+
+
+ 7.2. 6DNAC Operational Scenarios
+
+ This section provides message sequence charts for various 6DNAC
+ operational scenarios assuming that the 6DNAC Server is implemented
+ on a router. All the scenarios assume that the normal boot up time
+ stateless address autoconfiguration of Link Local address derived
+ from the Interface Identifier has been completed successfully. And
+ it is also assumed that the router is already configured with the
+ DNS Zone Suffix Information.
+
+
+ Legend:
+
+ 6DNAC-A, B, C : 6DNAC Clients
+ 6DNAC-S : 6DNAC Server/Router
+ DAD : Duplicate Address Detection
+ DFQDND : Duplicate Domain Name Detection
+ DNS-S : DNS Server
+
+
+ 7.2.1. Domain Name Registration-Successful Case
+
+ This scenario starts when a 6DNAC Client receives RA message with
+ DNS Zone Suffix and other parameters including address prefix as
+ specified in NDP [2461] and wants configure its IPv6 address (Global
+ or Site Local) and domain name. It is Assumed that the
+ DupAddrDetectTransmits is set to 1.
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 12]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ +---------+ +---------+ +---------+
+ | 6DNAC-C | | 6DNAC-S | | DNS-S |
+ +----+----+ +----+----+ +----+----+
+ | | |
+ | RA with | |
+ | DNS Suffix Opt | |
+ |<---------------| |
+ | #1 | |
+ |---+ | |
+ Construct |#2 | |
+ FQDN | | |
+ |<--+ | |
+DAD/DFQDND Starts | |
+ | | |
+ | | |
+ | NS With | |
+ | FQDN Opt | |
+ |--------------->| |
+ | #3 | |
+ | | |
+ | |------+ |
+ | Create FQDN | #4 |
+ | <FQDN,C> | |
+ | |<-----+ |
+ | | |
+ | | Register FQDN |
+ | |--------------->|
+ | | #5 |
+ | #6 | |
+ |--------+ | |
+ No Response | | |
+ DFQDND-Success | | |
+ |<-------+ | |
+ | | |
+ | | |
+ v V v
+
+
+ <Figure: 8 Domain Name Generation and Registration>
+
+
+ #1. 6DNAC Server (Router) sends out router advertisement with DNS
+ Suffix information along with other parameters as specified in
+ NDP [2461].
+
+ #2. 6DNAC Client processes the router advertisement and constructs
+ the FQDN by prefixing hostname to the DNS Zone Suffix. It also
+ constructs IPv6 address from the autoconfiguration prefix
+ information option.
+
+ #3. 6DNAC Client starts duplicate address & FQDN detection for the
+ IPv6 address & FQDN constructed and sends out a Neighbor
+ Solicitation message with FQDN option.
+
+ Note that the DAD packets must be addressed to all nodes multicast
+ address if Router Alert option is not used.
+
+Park & Madanapalli Expires October 2003 [Page 13]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ #4. 6DNAC Server processes the Neighbor Solicitation message sent by
+ 6DNAC Client as part of duplicate FQDN detection procedure and
+ creates a FQDN entry in its FQDN Cache (assuming that there is no
+ entry <FQDN,C>), where C is Link Layer Address of the 6DNAC Client.
+
+ #5. 6DNAC Server then registers FQDN and corresponding IPv6 address
+ through the existing protocol DDNS UPDATE.
+
+ #6. 6DNAC Client times out and observes that there is no response to
+ defend its duplicate FQDN detection procedure and the node is
+ successful in configuring its domain name.
+
+ Note that, Stateless Address Autoconfiguration DAD procedure is not
+ depicted in the following message sequence chart, which simultaneously
+ happens along with duplicate FQDN detection.
+
+
+ 7.2.2. Domain Name Registration-with DupAddrDetectTransmits=2
+
+ This scenario starts when a 6DNAC Client receives RA message with
+ DNS Zone Suffix and other parameters including address prefix as
+ specified in NDP [2461] and wants configure its IPv6 address (Global
+ or Site Local) and domain name. The node is configured with
+ DupAddrDetectTransmits = 2 for reliability in delivering DAD messages.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 14]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ +---------+ +---------+ +---------+
+ | 6DNAC-C | | 6DNAC-S | | DNS-S |
+ +----+----+ +----+----+ +----+----+
+ | | |
+ | RA with | |
+ | DNS Suffix Opt | |
+ |<---------------| |
+ | #1 | |
+ |---+ | |
+ Construct |#2 | |
+ FQDN | | |
+ |<--+ | |
+DAD/DFQDND Starts | |
+ | | |
+ | | |
+ | NS With | |
+ | FQDN Opt | |
+ |--------------->| |
+ | #3 | |
+ | | |
+ | |------+ |
+ | Create FQDN | #4 |
+ | <FQDN,C> | |
+ | |<-----+ |
+ | | |
+ | | Register FQDN |
+ | |--------------->|
+ | | #5 |
+ | NS With | |
+ | FQDN Opt | |
+ |--------------->| |
+ | #6 | |
+ | | |
+ | Lookup FQDN |
+ | Entry exists |
+ | |------+ |
+ | Ignore | #7 |
+ | |<-----+ |
+ | #8 | |
+ |--------+ | |
+ No Response | | |
+ DFQDND-Success | | |
+ |<-------+ | |
+ | | |
+ | | |
+ v V v
+
+
+
+ <Figure: 9 Verification of duplicated Domain Name>
+
+
+ Steps from #1 to #5 are same as that of scenario.7.2.1.
+
+ #6. 6DNAC Client sends out second Neighbor Solicitation message with
+ FQDN option as part of duplicate FQDN detection.
+
+Park & Madanapalli Expires October 2003 [Page 15]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ #7. 6DNAC Server receives and observes that the FQDN Cache exactly
+ matches with that of the NS information and ignores the NS message.
+
+ #8. 6DNAC Client times out and observes that there is no response to
+ defend its duplicate FQDN detection procedure and the node is
+ successful in configuring its domain name..
+
+
+ 7.2.3. Domain Name Registration-Defend Case
+
+ This scenario starts when two 6DNAC Client receive RA message with
+ DNS Zone Suffix and other parameters including address prefix as
+ specified in NDP [2461] and both the nodes want configure their IPv6
+ address (Global or Site Local) and domain name. In this scenario both
+ the nodes want to have same domain name.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 16]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+
+
+ +---------+ +---------+ +---------+ +---------+
+ | 6DNAC-A | | 6DNAC-S | | 6DNAC-B | | DNS-S |
+ +----+----+ +----+----+ +----+----+ +----+----+
+ | | | |
+ | RA with | RA with | |
+ | DNS Suffix Opt | DNS Suffix Opt | |
+ |<---------------|--------------->| |
+ | #1 | #1 | |
+ |---+ | |---+ |
+ Construct | #2 | Construct | #2 |
+ FQDN | | FQDN | |
+ |<--+ | |<--+ |
+ DAD/DFQDND Starts | DAD/DFQDND Starts |
+ | | <DELAYED> |
+ | | | |
+ | NS with | | |
+ | FQDN Opt | | |
+ |--------------->| | |
+ | #3 | | |
+ | No Entry | |
+ | |------+ | |
+ | Create FQDN | #4 | |
+ | <FQDN,A> | | |
+ | |<-----+ | |
+ | | | |
+ | | Register FQDN #5 |
+ | |-------------------------------->|
+ | | | |
+ | | NS with | |
+ | | FQDN Opt | |
+ | |<---------------| |
+ | | #6 | |
+ | |------+ | |
+ | FQDN is in use| | |
+ | Defend DFQDND| #7 | |
+ | |<-----+ | |
+ | | | |
+ | | NA with | |
+ | | D-flag Set | |
+ | |--------------->| |
+ | | #8 | |
+ |------+ | |---+ |
+ No Response | #9 | Enter | #10 |
+ DFQDND Success| | Retry Mode| |
+ |<-----+ | |<--+ |
+ | | | |
+ v v v v
+
+
+ <Figure: 10 Multiple Hosts Requesting Same Domain Name>
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 17]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ #1. 6DNAC Server (Router) sends out router advertisement with DNS
+ Suffix information.
+
+ #2. 6DNAC Clients A&B process the router advertisement and construct
+ their FQDN by prefixing hostname to the DNS Zone Suffix. They
+ also construct IPv6 address from the autoconfiguration prefix
+ information option.
+
+ When each host is trying to go for DAD, all hosts must have
+ random delay to avoid the traffic congestion according to [2461].
+ So here it is assumed that 6DNAC Client-A starts DAD first and
+ 6DNAC Client-B starts DAD later.
+
+ #3. 6DNAC Client-A starts duplicate address & FQDN detection for the
+ IPv6 address & FQDN constructed and sends out a Neighbor
+ Solicitation message with FQDN option.
+
+ #4. 6DNAC Server processes the Neighbor Solicitation message sent by
+ 6DNAC Client-A as part of duplicate FQDN detection procedure and
+ creates a FQDN entry in its FQDN Cache (assuming that there is no
+ entry <FQDN,A>), where A is Link Layer Address of the 6DNAC Client-A.
+
+ #5. 6DNAC Server then registers FQDN and corresponding IPv6 address
+ through the existing protocol DDNS UPDATE.
+
+ #6. 6DNAC Client-B starts duplicate address & FQDN detection for the
+ IPv6 address & FQDN constructed and sends out a Neighbor Solicitation
+ message with FQDN option.
+
+ #7. 6DNAC Server processes the Neighbor Solicitation message sent by
+ 6DNAC Client-B as part of duplicate FQDN detection procedure and
+ finds that the domain name is already in use by the 6DNAC Client-A.
+ Hence, concludes to defend the duplicate FQDN detection of 6DNAC
+ Client-B.
+
+ #8. 6DNAC Server sends out Neighbor Advertisement message with FQDN
+ option to 6DNAC Client-B to defend its duplicate FQDN detection.
+
+ #9. 6DNAC Client-A times out and observes that there is no response to
+ defend its duplicate FQDN detection procedure and the node is
+ successful in configuring its domain name.
+
+ #10. 6DNAC Client-B observes that there is a NA with FQDN option
+ indicating that the domain name is duplicate and enters Retry
+ Mode. In retry mode, 6DNAC Client constructs another FQDN based
+ on Host Naming Algorithm. The number of retries is defined by the
+ administrator and must be a configurable value.
+
+
+
+
+
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 18]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ 7.2.4. Domain Name Registration in Retry Mode
+
+ Pre-Conditions:
+
+ 1. Duplicate Address Detection has succeeded
+ 2. Duplicate FQDN Detection FAILED
+ 3. FQDN is the first FQDN one constructed and FAILED
+ 4. FQDN2 is the second FQDN to be constructed
+ 5. The Neighbor Solicitation in the 'Retry Mode'
+ carries unspecified address in its target field (NS*).
+
+ +---------+ +---------+ +---------+
+ | 6DNAC-C | | 6DNAC-S | | DNS-S |
+ +----+----+ +----+----+ +----+----+
+ | | |
+ |--------+ | |
+ Construct | #1 | |
+ new FQDN2 | | |
+ |<-------+ | |
+ | | |
+ DFQDND Restarts | |
+ | | |
+ | | |
+ | NS* With | |
+ | FQDN Opt | |
+ |--------------->| |
+ | #2 | |
+ | | |
+ | No Entry |
+ | |------+ |
+ | Create FQDN | #3 |
+ | <FQDN2,C> | |
+ | |<-----+ |
+ | | |
+ | | Register FQDN2 |
+ | |--------------->|
+ | | #4 |
+ | | |
+ |--------+ | |
+ No Response | #5 | |
+ DFQDND-Success | | |
+ |<-------+ | |
+ | | |
+ v V v
+
+
+ <Figure: 11 Regeneration of Domain Name>
+
+
+
+
+
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 19]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ #1. 6DNAC Client constructs the FQDN again as per Host Naming Algorithm,
+ the DNS Zone Suffix, and it is FQDN2.
+ #2. It then starts Duplicate Detection only for Domain Name. 6DNAC
+ Client sends out NS with FQDN option and unspecified target
+ address.
+
+ #3. 6DNAC Server processes the Retry Mode NS message and finds that
+ the FQDN2 is not in use and creates Cache entry as <FQDN2, C>.
+
+ #4. It then starts registration procedures with the DNS Server.
+
+ #5. Meanwhile, 6DNAC Client timesout and observes that there is no
+ defending NA for its DFQDND NS sent out and successfully
+ configures its domain name.
+
+
+ 7.2.5. Domain Name Registration when DAD Fails
+
+ Duplicate domain name detection and subsequent registration starts
+ if and only if the DAD for IPv6 address succeeds. If the DAD for
+ IPv6 address fails then no actions are taken for domain name. When
+ DAD fails for stateless address autoconfiguration, then the domain
+ configuration starts only when the address has been configured using
+ Stateful Address Configuration methods and the node is going on DAD
+ for this address.
+
+ This scenario starts when a 6DNAC Client receives RA message with
+ DNS Zone Suffix and other parameters including address prefix as
+ specified in NDP [2461] and wants configure its IPv6 address (Global
+ or Site Local) and domain name.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 20]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ +---------+ +---------+ +---------+ +---------+
+ | 6DNAC-A | | 6DNAC-S | | 6DNAC-B | | DNS-S |
+ +----+----+ +----+----+ +----+----+ +----+----+
+ | | | |
+ | | | |
+ | RA with | | |
+ | DNS Suffix Opt | | |
+ |<---------------| | |
+ | #1 | | |
+ |-----+ | | |
+ Construct | | | |
+ FQDN& | #2 | | |
+ IPv6 Addr | | | |
+ |<----+ | | |
+ DAD/DFQDND Starts | | |
+ | | | |
+ | | | |
+ | NS with | | |
+ | FQDN Opt | | |
+ |--------------->+--------------->| |
+ | #3 | #3 | |
+ | No Entry | |
+ | |------+ | |
+ | Create FQDN | | |
+ | <FQDN,A> | #4 | |
+ | |<-----+ | |
+ | | | |
+ | | |------+ |
+ | | My IPv6 Addr| #5 |
+ | | |<-----+ |
+ | | Defend DAD | |
+ | | with NA | |
+ |<---------------+<---------------| |
+ | #6 | #6 | |
+ | Entry | |
+ | |------+ | |
+ | Delete FQDN | #7 | |
+ | |<-----+ | |
+ | | | |
+ |----+ | | |
+ DAD Failed | #8 | | |
+ Stop DFQDND | | | |
+ |<---+ | | |
+ | | | |
+ v v v v
+
+ <Figure: 12 DAD failure>
+
+ #1. 6DNAC Server sends out Router Advertisement to 6DNAC Client-A.
+
+ #2. 6DNAC Client-A constructs IPv6 Address based on the prefix and
+ FQDN as per Host Naming Algorithm.
+
+ #3. It then starts Duplicate address & FQDN Detection, for the newly
+ constructed IPv6 address and FQDN, and sends out DAD/DFQDND NS
+ with FQDN option.
+
+Park & Madanapalli Expires October 2003 [Page 21]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+ #4. 6DNAC Server processes the DAD/DFQDND NS message and finds
+ that there is no entry for the FQDN in its cache. And,
+ creates Cache entry as <FQDN, A> and starts a Registration
+ timer with RegistrationWaitTime seconds.
+
+ #5. 6DNAC Client-B finds that the DAD/DFQDND-NS target address is
+ in its unicast address list.
+
+ #6. It then starts defending DAD by sending NA to all-nodes multicast.
+
+ #7. 6DNAC Server finds that the DAD has failed for 6DNAC Client-A.
+ And, deletes its FQDN Cache entry <FQDN,A>.
+
+ #8. 6DNAC Client gets defending DAD-NA and desists from DAD.
+ And also, stops Duplicate FQDN Detection as well.
+ At this point the address must be configured using stateful
+ methods and the domain name registration starts with the DAD
+ for the newly constructed IPv6 address.
+
+ 7.3. DNS Zone Suffix Discovery and FQDN Construction
+
+ 7.3.1. Sending Router Advertisement Messages
+
+ Routers send out Router Advertisement message periodically,
+ or in response to a Router Solicitation. Router should include
+ the DNS Zone Suffix Option in their advertisements. If the DNS
+ Zone Suffix changes (similar to Site Renumbering), then it should
+ advertise the Old Zone Suffix with zero Valid Lifetime and New
+ Zone Suffix with proper non-zero Valid Lifetime. In any other
+ case, a router should not send this option twice in a single
+ router advertisement.
+
+ 7.3.2. Processing Router Advertisement Messages
+
+ For each DNS Zone Suffix Option in Router Advertisement,
+
+ a. 6DNAC node stores the Zone Suffix information in its local
+ database. Also, constructs FQDN as per Host Naming Algorithm.
+
+ b. If the node has not configured FQDN yet,
+
+ 1. If the node is going to perform DAD for either Site local or
+ Global Address, then it should include FQDN option to perform
+ Duplicate FQDN Detection in parallel with DAD.
+
+ 2. If the node has already got either Site local or Global
+ address, then it should send out NS with FQDN option and
+ unspecified target address to perform Duplicate FQDN
+ Detection.
+
+ c. If the node has already configured FQDN, and if the
+ advertisement carries two DNS Zone Suffix Options,
+ First DNS Zone Suffix should match with the configured FQDN
+ Suffix and its Valid Lifetime must be zero. Second DNS Zone
+
+
+
+Park & Madanapalli Expires October 2003 [Page 22]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+
+ Suffix should have non-zero Valid Lifetime. In this case, the
+ node constructs new FQDN based on the new DNS Zone Suffix (from
+ second DNS Zone Suffix option), and perform Duplicate FQDN
+ Detection with unspecified target address. Also, it should
+ overwrite the old FQDN with the newly constructed FQDN.
+
+
+ 7.3.3. FQDN Lifetime expiry
+
+ 6DNAC Server:
+ It should delete the FQDN cache entry and should de-register from
+ the DNS Server.
+
+ 6DNAC Client:
+ It should send update to 6DNAC Server by restarting the Duplicate
+ FQDN Detection.
+
+ 7.3.4. Host Naming Algorithm
+
+ A node constructs FQDN by combining DNS Zone Suffix and the hostname
+ as depicted in the following diagram.
+
+ +------------------+----------------------------------+
+ | Host Name | Advertised Suffix |
+ +------------------+----------------------------------+
+
+ <Figure 13: Fully Qualified Domain Name format>
+
+ A node can choose Host Name using any of the following methods:
+
+ a. String form of random number generated from the Interface
+ Identifier.
+
+ b. List of configured Host Names provided by the administrator.
+
+
+ The number of retries must be specified in this algorithm in
+ case of domain name duplication.
+
+
+ 7.4. Duplicate Domain Name Detection
+
+ The procedure for detecting duplicated FQDNs uses Neighbor
+ Solicitation and Advertisement messages as described below.
+
+ If a duplicate FQDN is detected during the procedure, the
+ FQDN cannot be assigned to the node.
+
+ An FQDN on which the DFQDND Procedure is applied is said
+ to be tentative until the procedure has completed successfully.
+ A tentative FQDN is not considered "assigned to the node" in the
+ traditional sense. That is, the node must accept Neighbor
+ Advertisement message containing the tentative FQDN in the FQDN
+ Option.
+
+
+Park & Madanapalli Expires October 2003 [Page 23]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+
+ It should also be noted that DFQDN must be performed prior to
+ registering with DNS Server to prevent multiple nodes from using
+ the same FQDN simultaneously. All the Duplicate Address Detection
+ Neighbor Solicitation messages must carry Source Link Layer Address
+ Option as specified in NDP [2461].
+
+ The detection of duplicate FQDN can be achieved through one of the
+ following three types of procedures.
+
+ 1. DAD with All Nodes Multicast Address
+ 2. DAD with Router Alert Option for 6DNAC.
+ 3. Explicit Detection of Duplicate Domain Name
+
+ Even though three solutions are listed, authors prefer only one
+ procedure to be followed in future based on further analysis and
+ comments received from others.
+
+ 7.4.1. DAD with All Nodes Multicast Address
+
+ 7.4.1.1. Sending Neighbor Solicitation Messages
+
+ 6DNAC Client sends Neighbor Solicitation Messages as part
+ of Duplicate Address Detection SLAAC [2462] with the following
+ extra information and modifications:
+
+ a. Include FQDN Option in the DAD Neighbor Solicitation Message
+ b. Destination Address is set to All Nodes Multicast Address
+
+ There may be a case where DAD has succeeded but DFQDND is in Retry
+ Mode. In such case, the Neighbor Solicitation must carry unspecified
+ address in the ICMP target address field and new domain name in FQDN
+ option to re-try the registration of the domain name.
+
+ 7.4.1.2. Processing Neighbor Solicitation Messages
+
+ 6DNAC Clients must ignore the FQDN option found in any of the
+ neighbor solicitation messages.
+
+ 6DNAC Server processes FQDN Option found in the Duplicate Address
+ Detection Neighbor Solicitation Messages as described below:
+
+ Lookup FQDN Cache for the domain name in FQDN Option.
+
+ If the entry exists and
+ i. Link Layer Address matches with SLLA option, this is the case,
+ where node has changed its IPv6 address or updating the valid
+ life time. 6DNAC Server updates its cache and also updates DNS
+ Server using DDNS-UPDATE. If there is no change in IPv6 address
+ or life time then no updates are sent to the DNS server.
+
+ ii. Link Layer Address differs with SLLA option, defend the duplicate
+ FQDN Detection by sending Neighbor Advertisement Message as
+ described in $7.4.1.3$.
+
+
+
+Park & Madanapalli Expires October 2003 [Page 24]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+
+ else,
+ Lookup FQDN Cache for the Link Layer Address in SLLA Option.
+
+ If the entry exists, update the FQDN Cache and update DNS Server
+ using DDNS-UPDATE. This is the case, where node has changed its
+ domain name (similar to Site Re-numbering).
+
+ If then entry does not exists, then it means that this is the new
+ registration. It must create a cache entry and start Registration
+
+ timer with RegistrationWaitTime. At the expiry of the Registration
+ timer, it should update DNS Server with DDNS-UPDATE.
+
+ 7.4.1.3. Sending Neighbor Advertisement Messages
+
+ 6DNAC Server sends Neighbor Advertisement Messages as part
+ of Duplicate Address Detection SLAAC [2462] with the FQDN Option
+ in Neighbor Advertisement message to defend duplicate FQDN
+ detection.
+
+ There may be the case where defending of duplicate address detection
+ is not required but defending of FQDN is required. In such instance,
+ the defending Neighbor Advertisement must carry FQDN and unspecified
+ address in the ICMP target address field.
+
+ 7.4.1.4. Processing Neighbor Advertisement Messages
+
+ 6DNAC Server must ignore the any FQDN option found any of
+ the neighbor advertisement messages. If the Neighbor Advertisement
+ is a DAD defending, then it must delete its FQDN Cache entry created
+ on the reception of DAD Neighbor Solicitation message.
+
+ When 6DNAC Clients gets the duplicate address detection neighbor
+ advertisement messages with FQDN option set it means that its
+ duplicate FQDN detection failed and enters Retry Mode.
+
+ 7.4.1.5. Pros and Cons
+
+ The advantage of this procedure is that it does not need any
+ extension header options to be included. The disadvantage of this
+ procedure is that, it needs change in the existing DAD procedure.
+ The change is only that the DAD neighbor solicitations are to be
+ addressed to all nodes multicast address instead of solicited
+ node multicast address. The another disadvantage is that, it needs
+ the existence of Duplicate Address Detection Procedure to
+ perform duplicate FQDN detection.
+
+ 7.4.2. DAD with Router Alert Option for 6DNAC
+
+ 7.4.2.1. Sending Neighbor Solicitation Messages
+
+ 6DNAC Client sends Neighbor Solicitation Messages as part
+ of Duplicate Address Detection SLAAC [2462] with the following
+ extra information:
+
+
+Park & Madanapalli Expires October 2003 [Page 25]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+
+ a. Include Hop-by-Hop extension Header with Router Alert Option
+ for 6DNAC as described in IPv6 Router Alert Option[2711].
+
+ b. Include FQDN Option in the DAD Neighbor Solicitation Message
+
+ 7.4.2.2. Processing Neighbor Solicitation Messages
+
+ This is same as described in $7.4.1.2$.
+
+ 7.4.2.3. Sending Neighbor Advertisement Messages
+
+ This is same as described in $7.4.1.3$.
+
+ 7.4.2.4. Processing Neighbor Advertisement Messages
+
+ This is same as described in $7.4.1.4$.
+
+ 7.4.2.5. Pros and Cons
+
+ The advantage of this procedure is that it does not disturb
+ the existing implementation and their way of processing the
+ packets. The disadvantage is that, it needs the existence
+ of Duplicate Address Detection Procedure to perform duplicate
+ FQDN detection. Another disadvantage is that this procedure
+ requires 6DNAC Server functionality to be implemented on Router.
+ However, in this case 6DNAC Server can serve multiple links.
+
+ 7.4.3. Explicit Detection of Duplicate Domain Name
+
+ In this procedure Duplicate FQDN Detection starts after completion
+ of successful Site local or Global Address configuration.
+
+ 7.4.3.1. Sending Neighbor Solicitation Messages
+
+ 6DNAC Client sends Neighbor Solicitation Messages as part
+ of Duplicate FQDN Detection with the following information:
+
+ a. Include FQDN Option in the Neighbor Solicitation Message
+
+ b. Destination Address is set to All Nodes Multicast Address
+ or uses Router Alert Option for 6DNAC, when 6DNAC Server is
+ implemented on router.
+
+ c. Target Address is set to Unspecified Address
+
+ d. Other fields are set as per DAD SLAAC [2462].
+
+ 7.4.3.2. Processing Neighbor Solicitation Messages
+
+ This is same as described in $7.4.1.2$.
+
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 26]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+
+ 7.4.3.3. Sending Neighbor Advertisement Messages
+
+ This is same as described in $7.4.1.3$.
+
+ 7.4.3.4. Processing Neighbor Advertisement Messages
+
+ This is same as described in $7.4.1.4$.
+
+ 7.4.3.5. Pros and Cons
+
+ The advantage of this procedure is that it does not need the
+ existing duplicate address detection procedure. This is introduced
+ as the DAD procedure is found to be redundant in when IPv6 addresses
+ are constructed from the interface ID [DIID].
+
+ Note that, if 6DNAC Clients know the address of 6DNAC Server then
+ they can directly send DFQDND-NS to 6DNAC Server.
+
+ 7.4.4. Retry Mode for Re-registering Domain Name
+
+ In retry mode, nodes construct new FQDN as per Host Naming Algorithm.
+ Then they restart Duplicate FQDN Detection as described in $7.4.3$.
+
+
+ 7.5. Domain Name Registration
+
+ 6DNAC Server must be an authenticated to update the DNS Server.
+ 6DNAC Server must also be configured with the DNS Server
+ information.
+
+ 6DNAC Server detects the DNS information (IPv6 Address and
+ corresponding FQDN) from DAD/DFQDND messages and caches the
+ information. It also have an associated Registration Timer with
+ RegistrationWaitTime to wait for the successful completion of
+ DFQDND and update DNS Server using existing protocol DDNS UPDATE
+ [2136].
+
+
+ 8. Security Consideration
+
+ If someone wants to hijack correct Domain Name registration, they
+ could send a NS message with incorrect or same Domain Name to the
+ 6DNAC server repeatedly and server would start the Domain Name
+ registration through above mechanism, which is a security hole.
+ As described in [2461], a host can check validity of NDP messages.
+ If the NDP message include an IP Authentication Header, the message
+ authenticates correctly. For DNS UPDATE processing, secure DNS
+ Dynamic Update is described in [3007].
+
+
+
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 27]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+
+ 9. IANA Consideration
+
+ Values in the Router Alert Option are registered and maintained by
+ IANA. For 6DNAC, the value has to be assigned by IANA. Also IANA is
+ required to assign the Type values for DNS Zone Suffix Information
+ option and FADN option.
+
+
+ 10. Acknowledgement
+
+ Special thanks are due to Badrinarayana N.S. and Christian Huitema for
+ many helpful suggestions and revisions.
+
+
+ 11. Intellectual Property
+
+ The following notice is copied from RFC 2026 [Bradner, 1996],
+ Section 10.4, and describes the position of the IETF concerning
+ intellectual property claims made against this document.
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use other technology described in
+
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances
+ of licenses to be made available, or the result of an attempt made
+ to obtain a general license or permission for the use of such
+ proprietary rights by implementers or users of this specification
+ can be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+
+ 12. Copyright
+
+ The following copyright notice is copied from RFC 2026 [Bradner,
+ 1996], Section 10.4, and describes the applicable copyright for this
+ document.
+
+ Copyright (C) The Internet Society July 12, 2001. All Rights
+ Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+
+Park & Madanapalli Expires October 2003 [Page 28]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph
+ are included on all such copies and derivative works. However, this
+
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+ 13. References
+
+ [2373] Hinden, R. and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 2373, July 1998.
+
+ [2460] Deering, S. abd R. Hinden, "Internet Protocol,
+ Version 6 (IPv6) Specification", RFC 2460,
+ December 1998.
+
+ [2461] Narten, T., Nordmark, E. and W. Simpson, "Neighbor
+ Discovery for IP version 6(IPv6)", RFC 2461, December
+ 1998.
+
+ [2462] S. Thomson and Narten T, "IPv6 Stateless Address Auto-
+ Configuration", RFC 2462, December 1998.
+
+ [2711] C. Patridge and A.Jackson, "IPv6 Router Alert Option",
+ RFC 2711, October 1999.
+
+ [1034] P. Mockapetris, "DOMAIN NAMES - CONCEPTS AND
+ FACILITIES", RFC 1034, November 1987.
+
+ [1035] P. Mockapetris, "Domain Names - Implementation and
+ Specification" RFC 1035, November 1987.
+
+ [2136] P. Vixie et al., "Dynamic Updates in the Domain Name
+ System (DNS UPDATE)", RFC2136, April 1997.
+
+ [3007] B. Wellington, "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+
+
+Park & Madanapalli Expires October 2003 [Page 29]
+
+INTERNET-DRAFT IPv6 Extensions for DNS Plug and Play April 2003
+
+
+ [DIID] yokohama-dad-vs-diid.pdf
+ at http://playground.sun.com/ipng/presentations/July2002/
+
+ [DNSISSUES] Durand, A., "IPv6 DNS transition issues", draft-ietf-
+ dnsop-ipv6-dns-issues-00.txt, work in progress.
+
+ [PREFIX] S. Miyakawa, R. Droms, "Requirements for IPv6 prefix
+ delegation", draft-ietf-ipv6-prefix-delegation-
+ requirement-01.txt, work in progress.
+
+ [Autoreg] H. Kitamura, "Domain Name Auto-Registration for
+ Plugged-in IPv6 Nodes", draft-ietf-dnsext-ipv6-name-
+ auto-reg-00.txt, work in progress.
+
+ [NIQ] Matt Crawford, "IPv6 Node Information Queries", <draft-
+ ietf-ipngwg-icmp-name-lookups-09.txt>, work in progress.
+
+
+ 14. Author's Addresses
+
+ Soohong Daniel Park
+ Mobile Platform Laboratory, SAMSUNG Electronics, KOREA
+ Phone: +82-31-200-3728
+ Email:soohong.park@samsung.com
+
+ Syam Madanapalli
+ Network Systems Division, SAMSUNG India Software Operations, INDIA
+ Phone: +91-80-5550555
+ Email:syam@samsung.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Park & Madanapalli Expires October 2003 [Page 30]
diff --git a/doc/draft/update b/doc/draft/update
new file mode 100644
index 0000000..6ac2090
--- /dev/null
+++ b/doc/draft/update
@@ -0,0 +1,46 @@
+#!/bin/sh
+commit=
+for i
+do
+ z=`expr "$i" : 'http://www.ietf.org/internet-drafts/\(.*\)'`
+ if test -n "$z"
+ then
+ i="$z"
+ fi
+ if test -f "$i"
+ then
+ continue
+ fi
+ pat=`echo "$i" | sed 's/...txt/??.txt/'`
+ old=`echo $pat 2> /dev/null`
+ if test "X$old" != "X$pat"
+ then
+ newer=0
+ for j in $old
+ do
+ if test $j ">" $i
+ then
+ newer=1
+ fi
+ done
+ if test $newer = 1
+ then
+ continue;
+ fi
+ fi
+ if fetch "http://www.ietf.org/internet-drafts/$i"
+ then
+ cvs add "$i"
+ if test "X$old" != "X$pat"
+ then
+ rm $old
+ cvs delete $old
+ commit="$commit $old"
+ fi
+ commit="$commit $i"
+ fi
+done
+if test -n "$commit"
+then
+ cvs commit -m "new draft" $commit
+fi
diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in
new file mode 100644
index 0000000..501e3be
--- /dev/null
+++ b/doc/misc/Makefile.in
@@ -0,0 +1,48 @@
+# 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.7 2007/09/24 04:21:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_RULES@
+
+PERL = @PERL@
+
+MANOBJS = options
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f options
+
+# Do not make options depend on ../../bin/tests/cfg_test, doing so
+# will cause excessively clever versions of make to attempt to build
+# that program right here, right now, if it is missing, which will
+# cause make doc to bomb.
+
+CFG_TEST = ../../bin/tests/cfg_test
+
+options: FORCE
+ if test -x ${CFG_TEST} && \
+ ${CFG_TEST} --named --grammar | \
+ ${PERL} ${srcdir}/sort-options.pl | \
+ ${PERL} ${srcdir}/format-options.pl >$@.new ; then \
+ mv -f $@.new $@ ; \
+ else \
+ rm -f $@.new ; \
+ fi
diff --git a/doc/misc/dnssec b/doc/misc/dnssec
new file mode 100644
index 0000000..4451e6c
--- /dev/null
+++ b/doc/misc/dnssec
@@ -0,0 +1,84 @@
+Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2000-2002 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+DNSSEC Release Notes
+
+This document summarizes the state of the DNSSEC implementation in
+this release of BIND9.
+
+
+OpenSSL Library Required
+
+To support DNSSEC, BIND 9 must be linked with version 0.9.6e or newer of
+the OpenSSL library. As of BIND 9.2, the library is no longer
+included in the distribution - it must be provided by the operating
+system or installed separately.
+
+To build BIND 9 with OpenSSL, use "configure --with-openssl". If
+the OpenSSL library is installed in a nonstandard location, you can
+specify a path as in "configure --with-openssl=/var".
+
+
+Key Generation and Signing
+
+The tools for generating DNSSEC keys and signatures are now in the
+bin/dnssec directory. Documentation for these programs can be found
+in doc/arm/Bv9ARM.4.html and the man pages.
+
+The random data used in generating DNSSEC keys and signatures comes
+from either /dev/random (if the OS supports it) or keyboard input.
+Alternatively, a device or file containing entropy/random data can be
+specified.
+
+
+Serving Secure Zones
+
+When acting as an authoritative name server, BIND9 includes KEY, SIG
+and NXT records in responses as specified in RFC2535 when the request
+has the DO flag set in the query.
+
+
+Secure Resolution
+
+Basic support for validation of DNSSEC signatures in responses has
+been implemented but should still be considered experimental.
+
+When acting as a caching name server, BIND9 is capable of performing
+basic DNSSEC validation of positive as well as nonexistence responses.
+This functionality is enabled by including a "trusted-keys" clause
+in the configuration file, containing the top-level zone key of the
+the DNSSEC tree.
+
+Validation of wildcard responses is not currently supported. In
+particular, a "name does not exist" response will validate
+successfully even if it does not contain the NXT records to prove the
+nonexistence of a matching wildcard.
+
+Proof of insecure status for insecure zones delegated from secure
+zones works when the zones are completely insecure. Privately
+secured zones delegated from secure zones will not work in all cases,
+such as when the privately secured zone is served by the same server
+as an ancestor (but not parent) zone.
+
+Handling of the CD bit in queries is now fully implemented. Validation
+is not attempted for recursive queries if CD is set.
+
+
+Secure Dynamic Update
+
+Dynamic update of secure zones has been implemented, but may not be
+complete. Affected NXT and SIG records are updated by the server when
+an update occurs. Advanced access control is possible using the
+"update-policy" statement in the zone definition.
+
+
+Secure Zone Transfers
+
+BIND 9 does not implement the zone transfer security mechanisms of
+RFC2535 section 5.6, and we have no plans to implement them in the
+future as we consider them inferior to the use of TSIG or SIG(0) to
+ensure the integrity of zone transfers.
+
+
+$Id: dnssec,v 1.19 2004/03/05 05:04:53 marka Exp $
diff --git a/doc/misc/format-options.pl b/doc/misc/format-options.pl
new file mode 100644
index 0000000..b0b8d52
--- /dev/null
+++ b/doc/misc/format-options.pl
@@ -0,0 +1,49 @@
+#!/usr/bin/perl
+#
+# 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: format-options.pl,v 1.5 2007/09/24 04:21:59 marka Exp $
+
+print <<END;
+
+This is a summary of the named.conf options supported by
+this version of BIND 9.
+
+END
+
+# Break long lines
+while (<>) {
+ chomp;
+ s/\t/ /g;
+ my $line = $_;
+ m!^( *)!;
+ my $indent = $1;
+ my $comment = "";
+ if ( $line =~ m!//.*! ) {
+ $comment = $&;
+ $line =~ s!//.*!!;
+ }
+ my $start = "";
+ while (length($line) >= 79 - length($comment)) {
+ $_ = $line;
+ # this makes sure that the comment has something in front of it
+ $len = 75 - length($comment);
+ m!^(.{0,$len}) (.*)$!;
+ $start = $start.$1."\n";
+ $line = $indent." ".$2;
+ }
+ print $start.$line.$comment."\n";
+}
diff --git a/doc/misc/ipv6 b/doc/misc/ipv6
new file mode 100644
index 0000000..4060bc3
--- /dev/null
+++ b/doc/misc/ipv6
@@ -0,0 +1,113 @@
+Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2000, 2001 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+Currently, there are multiple interesting problems with ipv6
+implementations on various platforms. These problems range from not
+being able to use ipv6 with bind9 (or in particular the ISC socket
+library, contained in libisc) to listen-on lists not being respected,
+to strange warnings but seemingly correct behavior of named.
+
+COMPILE-TIME ISSUES
+-------------------
+
+The socket library requires a certain level of support from the
+operating system. In particular, it must follow the advanced ipv6
+socket API to be usable. The systems which do not follow this will
+currently not get any warnings or errors, but ipv6 will simply not
+function on them.
+
+These systems currently include, but are not limited to:
+
+ AIX 3.4 (with ipv6 patches)
+
+
+RUN-TIME ISSUES
+---------------
+
+In the original drafts of the ipv6 RFC documents, binding an ipv6
+socket to the ipv6 wildcard address would also cause the socket to
+accept ipv4 connections and datagrams. When an ipv4 packet is
+received on these systems, it is mapped into an ipv6 address. For
+example, 1.2.3.4 would be mapped into ::ffff:1.2.3.4. The intent of
+this mapping was to make transition from an ipv4-only application into
+ipv6 easier, by only requiring one socket to be open on a given port.
+
+Later, it was discovered that this was generally a bad idea. For one,
+many firewalls will block connection to 1.2.3.4, but will let through
+::ffff:1.2.3.4. This, of course, is bad. Also, access control lists
+written to accept only ipv4 addresses were suddenly ignored unless
+they were rewritten to handle the ipv6 mapped addresses as well.
+
+Partly because of these problems, the latest IPv6 API introduces an
+explicit knob (the "IPV6_V6ONLY" socket option ) to turn off the ipv6
+mapped address usage.
+
+In bind9, we first check if both the advanced API and the IPV6_V6ONLY
+socket option are available. If both of them are available, bind9
+named will bind to the ipv6 wildcard port for both TCP and UDP.
+Otherwise named will make a warning and try to bind to all available
+ipv6 addresses separately.
+
+In any case, bind9 named binds to specific addresses for ipv4 sockets.
+
+The followings are historical notes when we always bound to the ipv6
+wildcard port regardless of the availability of the API support.
+These problems should not happen with the closer checks above.
+
+
+IPV6 Sockets Accept IPV4, Specific IPV4 Addresses Bindings Fail
+---------------------------------------------------------------
+
+The only OS which seems to do this is (some kernel versions of) linux.
+If an ipv6 socket is bound to the ipv6 wildcard socket, and a specific
+ipv4 socket is later bound (say, to 1.2.3.4 port 53) the ipv4 binding
+will fail.
+
+What this means to bind9 is that the application will log warnings
+about being unable to bind to a socket because the address is already
+in use. Since the ipv6 socket will accept ipv4 packets and map them,
+however, the ipv4 addresses continue to function.
+
+The effect is that the config file listen-on directive will not be
+respected on these systems.
+
+
+IPV6 Sockets Accept IPV4, Specific IPV4 Address Bindings Succeed
+----------------------------------------------------------------
+
+In this case, the system allows opening an ipv6 wildcard address
+socket and then binding to a more specific ipv4 address later. An
+example of this type of system is Digital Unix with ipv6 patches
+applied.
+
+What this means to bind9 is that the application will respect
+listen-on in regards to ipv4 sockets, but it will use mapped ipv6
+addresses for any that do not match the listen-on list. This, in
+effect, makes listen-on useless for these machines as well.
+
+
+IPV6 Sockets Do Not Accept IPV4
+-------------------------------
+
+On these systems, opening an IPV6 socket does not implicitly open any
+ipv4 sockets. An example of these systems are NetBSD-current with the
+latest KAME patch, and other systems which use the latest KAME patches
+as their ipv6 implementation.
+
+On these systems, listen-on is fully functional, as the ipv6 socket
+only accepts ipv6 packets, and the ipv4 sockets will handle the ipv4
+packets.
+
+
+RELEVANT RFCs
+-------------
+
+3513: Internet Protocol Version 6 (IPv6) Addressing Architecture
+
+3493: Basic Socket Interface Extensions for IPv6
+
+3542: Advanced Sockets Application Program Interface (API) for IPv6
+
+
+$Id: ipv6,v 1.9 2004/08/10 04:27:51 jinmei Exp $
diff --git a/doc/misc/migration b/doc/misc/migration
new file mode 100644
index 0000000..21856bf
--- /dev/null
+++ b/doc/misc/migration
@@ -0,0 +1,267 @@
+Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+ BIND 8 to BIND 9 Migration Notes
+
+BIND 9 is designed to be mostly upwards compatible with BIND 8, but
+there is still a number of caveats you should be aware of when
+upgrading an existing BIND 8 installation to use BIND 9.
+
+
+1. Configuration File Compatibility
+
+1.1. Unimplemented Options and Changed Defaults
+
+BIND 9 supports most, but not all of the named.conf options of BIND 8.
+For a complete list of implemented options, see doc/misc/options.
+
+If your named.conf file uses an unimplemented option, named will log a
+warning message. A message is also logged about each option whose
+default has changed unless the option is set explicitly in named.conf.
+
+The default of the "transfer-format" option has changed from
+"one-answer" to "many-answers". If you have slave servers that do not
+understand the many-answers zone transfer format (e.g., BIND 4.9.5 or
+older) you need to explicitly specify "transfer-format one-answer;" in
+either the options block or a server statement.
+
+BIND 9.4 onwards implements "allow-query-cache". The "allow-query"
+option is no longer used to specify access to the cache. The
+"allow-query" option continues to specify which hosts are allowed
+to ask ordinary DNS questions. The new "allow-query-cache" option
+is used to specify which hosts are allowed to get answers from the
+cache. Since BIND 9.4.1, if "allow-query-cache" is not set then
+"allow-recursion" is used if it is set, otherwise "allow-query" is
+used if it is set, otherwise the default localnets and localhost
+is used.
+
+1.2. Handling of Configuration File Errors
+
+In BIND 9, named refuses to start if it detects an error in
+named.conf. Earlier versions would start despite errors, causing the
+server to run with a partial configuration. Errors detected during
+subsequent reloads do not cause the server to exit.
+
+Errors in master files do not cause the server to exit, but they
+do cause the zone not to load.
+
+1.3. Logging
+
+The set of logging categories in BIND 9 is different from that
+in BIND 8. If you have customised your logging on a per-category
+basis, you need to modify your logging statement to use the
+new categories.
+
+Another difference is that the "logging" statement only takes effect
+after the entire named.conf file has been read. This means that when
+the server starts up, any messages about errors in the configuration
+file are always logged to the default destination (syslog) when the
+server first starts up, regardless of the contents of the "logging"
+statement. In BIND 8, the new logging configuration took effect
+immediately after the "logging" statement was read.
+
+1.4. Notify messages and Refresh queries
+
+The source address and port for these is now controlled by
+"notify-source" and "transfer-source", respectively, rather that
+query-source as in BIND 8.
+
+1.5. Multiple Classes.
+
+Multiple classes have to be put into explicit views for each class.
+
+
+2. Zone File Compatibility
+
+2.1. Strict RFC1035 Interpretation of TTLs in Zone Files
+
+BIND 9 strictly complies with the RFC1035 and RFC2308 rules regarding
+omitted TTLs in zone files. Omitted TTLs are replaced by the value
+specified with the $TTL directive, or by the previous explicit TTL if
+there is no $TTL directive.
+
+If there is no $TTL directive and the first RR in the file does not
+have an explicit TTL field, the zone file is illegal according to
+RFC1035 since the TTL of the first RR is undefined. Unfortunately,
+BIND 4 and many versions of BIND 8 accept such files without warning
+and use the value of the SOA MINTTL field as a default for missing TTL
+values.
+
+BIND 9.0 and 9.1 completely refused to load such files. BIND 9.2
+emulates the nonstandard BIND 4/8 SOA MINTTL behaviour and loads the
+files anyway (provided the SOA is the first record in the file), but
+will issue the warning message "no TTL specified; using SOA MINTTL
+instead".
+
+To avoid problems, we recommend that you use a $TTL directive in each
+zone file.
+
+2.2. Periods in SOA Serial Numbers Deprecated
+
+Some versions of BIND allow SOA serial numbers with an embedded
+period, like "3.002", and convert them into integers in a rather
+unintuitive way. This feature is not supported by BIND 9; serial
+numbers must be integers.
+
+2.3. Handling of Unbalanced Quotes
+
+TXT records with unbalanced quotes, like 'host TXT "foo', were not
+treated as errors in some versions of BIND. If your zone files
+contain such records, you will get potentially confusing error
+messages like "unexpected end of file" because BIND 9 will interpret
+everything up to the next quote character as a literal string.
+
+2.4. Handling of Line Breaks
+
+Some versions of BIND accept RRs containing line breaks that are not
+properly quoted with parentheses, like the following SOA:
+
+ @ IN SOA ns.example. hostmaster.example.
+ ( 1 3600 1800 1814400 3600 )
+
+This is not legal master file syntax and will be treated as an error
+by BIND 9. The fix is to move the opening parenthesis to the first
+line.
+
+2.5. Unimplemented BIND 8 Extensions
+
+$GENERATE: The "$$" construct for getting a literal $ into a domain
+name is deprecated. Use \$ instead.
+
+2.6. TXT records are no longer automatically split.
+
+Some versions of BIND accepted strings in TXT RDATA consisting of more
+than 255 characters and silently split them to be able to encode the
+strings in a protocol conformant way. You may now see errors like this
+ dns_rdata_fromtext: local.db:119: ran out of space
+if you have TXT RRs with too longs strings. Make sure to split the
+string in the zone data file at or before a single one reaches 255
+characters.
+
+3. Interoperability Impact of New Protocol Features
+
+3.1. EDNS0
+
+BIND 9 uses EDNS0 (RFC2671) to advertise its receive buffer size. It
+also sets DO EDNS flag bit in queries to indicate that it wishes to
+receive DNSSEC responses.
+
+Most older servers that do not support EDNS0, including prior versions
+of BIND, will send a FORMERR or NOTIMP response to these queries.
+When this happens, BIND 9 will automatically retry the query without
+EDNS0.
+
+Unfortunately, there exists at least one non-BIND name server
+implementation that silently ignores these queries instead of sending
+an error response. Resolving names in zones where all or most
+authoritative servers use this server will be very slow or fail
+completely. We have contacted the manufacturer of the name server in
+case, and they are working on a solution.
+
+When BIND 9 communicates with a server that does support EDNS0, such as
+another BIND 9 server, responses of up to 4096 bytes may be
+transmitted as a single UDP datagram which is subject to fragmentation
+at the IP level. If a firewall incorrectly drops IP fragments, it can
+cause resolution to slow down dramatically or fail.
+
+3.2. Zone Transfers
+
+Outgoing zone transfers now use the "many-answers" format by default.
+This format is not understood by certain old versions of BIND 4.
+You can work around this problem using the option "transfer-format
+one-answer;", but since these old versions all have known security
+problems, the correct fix is to upgrade the slave servers.
+
+Zone transfers to Windows 2000 DNS servers sometimes fail due to a
+bug in the Windows 2000 DNS server where DNS messages larger than
+16K are not handled properly. Obtain the latest service pack for
+Windows 2000 from Microsoft to address this issue. In the meantime,
+the problem can be worked around by setting "transfer-format one-answer;".
+http://support.microsoft.com/default.aspx?scid=kb;en-us;297936
+
+4. Unrestricted Character Set
+
+ BIND 9.2 only
+
+BIND 9 does not restrict the character set of domain names - it is
+fully 8-bit clean in accordance with RFC2181 section 11.
+
+It is strongly recommended that hostnames published in the DNS follow
+the RFC952 rules, but BIND 9 will not enforce this restriction.
+
+Historically, some applications have suffered from security flaws
+where data originating from the network, such as names returned by
+gethostbyaddr(), are used with insufficient checking and may cause a
+breach of security when containing unexpected characters; see
+<http://www.cert.org/advisories/CA-96.04.corrupt_info_from_servers.html>
+for details. Some earlier versions of BIND attempt to protect these
+flawed applications from attack by discarding data containing
+characters deemed inappropriate in host names or mail addresses, under
+the control of the "check-names" option in named.conf and/or "options
+no-check-names" in resolv.conf. BIND 9 provides no such protection;
+if applications with these flaws are still being used, they should
+be upgraded.
+
+ BIND 9.3 onwards implements check-names.
+
+5. Server Administration Tools
+
+5.1 Ndc Replaced by Rndc
+
+The "ndc" program has been replaced by "rndc", which is capable of
+remote operation. Unlike ndc, rndc requires a configuration file.
+The easiest way to generate a configuration file is to run
+"rndc-confgen -a"; see the man pages for rndc(8), rndc-confgen(8),
+and rndc.conf(5) for details.
+
+5.2. Nsupdate Differences
+
+The BIND 8 implementation of nsupdate had an undocumented feature
+where an update request would be broken down into multiple requests
+based upon the discovered zones that contained the records. This
+behaviour has not been implemented in BIND 9. Each update request
+must pertain to a single zone, but it is still possible to do multiple
+updates in a single invocation of nsupdate by terminating each update
+with an empty line or a "send" command.
+
+
+6. No Information Leakage between Zones
+
+BIND 9 stores the authoritative data for each zone in a separate data
+structure, as recommended in RFC1035 and as required by DNSSEC and
+IXFR. When a BIND 9 server is authoritative for both a child zone and
+its parent, it will have two distinct sets of NS records at the
+delegation point: the authoritative NS records at the child's apex,
+and a set of glue NS records in the parent.
+
+BIND 8 was unable to properly distinguish between these two sets of NS
+records and would "leak" the child's NS records into the parent,
+effectively causing the parent zone to be silently modified: responses
+and zone transfers from the parent contained the child's NS records
+rather than the glue configured into the parent (if any). In the case
+of children of type "stub", this behaviour was documented as a feature,
+allowing the glue NS records to be omitted from the parent
+configuration.
+
+Sites that were relying on this BIND 8 behaviour need to add any
+omitted glue NS records, and any necessary glue A records, to the
+parent zone.
+
+Although stub zones can no longer be used as a mechanism for injecting
+NS records into their parent zones, they are still useful as a way of
+directing queries for a given domain to a particular set of name
+servers.
+
+
+7. Umask not Modified
+
+The BIND 8 named unconditionally sets the umask to 022. BIND 9 does
+not; the umask inherited from the parent process remains in effect.
+This may cause files created by named, such as journal files, to be
+created with different file permissions than they did in BIND 8. If
+necessary, the umask should be set explicitly in the script used to
+start the named process.
+
+
+$Id: migration,v 1.49 2008/03/18 15:42:53 jreed Exp $
diff --git a/doc/misc/migration-4to9 b/doc/misc/migration-4to9
new file mode 100644
index 0000000..008cbed
--- /dev/null
+++ b/doc/misc/migration-4to9
@@ -0,0 +1,57 @@
+Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2001 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+$Id: migration-4to9,v 1.4 2004/03/05 05:04:53 marka Exp $
+
+ BIND 4 to BIND 9 Migration Notes
+
+To transition from BIND 4 to BIND 9 you first need to convert your
+configuration file to the new format. There is a conversion tool in
+contrib/named-bootconf that allows you to do this.
+
+ named-bootconf.sh < /etc/named.boot > /etc/named.conf
+
+BIND 9 uses a system assigned port for the UDP queries it makes rather
+than port 53 that BIND 4 uses. This may conflict with some firewalls.
+The following directives in /etc/named.conf allows you to specify
+a port to use.
+
+ query-source address * port 53;
+ transfer-source * port 53;
+ notify-source * port 53;
+
+BIND 9 no longer uses the minimum field to specify the TTL of records
+without a explicit TTL. Use the $TTL directive to specify a default TTL
+before the first record without a explicit TTL.
+
+ $TTL 3600
+ @ IN SOA ns1.example.com. hostmaster.example.com. (
+ 2001021100
+ 7200
+ 1200
+ 3600000
+ 7200 )
+
+BIND 9 does not support multiple CNAMEs with the same owner name.
+
+ Illegal:
+ www.example.com. CNAME host1.example.com.
+ www.example.com. CNAME host2.example.com.
+
+BIND 9 does not support "CNAMEs with other data" with the same owner name,
+ignoring the DNSSEC records (SIG, NXT, KEY) that BIND 4 did not support.
+
+ Illegal:
+ www.example.com. CNAME host1.example.com.
+ www.example.com. MX 10 host2.example.com.
+
+BIND 9 is less tolerant of errors in master files, so check your logs and
+fix any errors reported. The named-checkzone program can also be to check
+master files.
+
+Outgoing zone transfers now use the "many-answers" format by default.
+This format is not understood by certain old versions of BIND 4.
+You can work around this problem using the option "transfer-format
+one-answer;", but since these old versions all have known security
+problems, the correct fix is to upgrade the slave servers.
diff --git a/doc/misc/options b/doc/misc/options
new file mode 100644
index 0000000..3416a3b
--- /dev/null
+++ b/doc/misc/options
@@ -0,0 +1,537 @@
+
+This is a summary of the named.conf options supported by
+this version of BIND 9.
+
+acl <string> { <address_match_element>; ... };
+
+controls {
+ inet ( <ipv4_address> | <ipv6_address> | * ) [ port ( <integer> | *
+ ) ] allow { <address_match_element>; ... } [ keys { <string>;
+ ... } ];
+ unix <quoted_string> perm <integer> owner <integer> group <integer>
+ [ keys { <string>; ... } ];
+};
+
+dlz <string> {
+ database <string>;
+};
+
+key <string> {
+ algorithm <string>;
+ secret <string>;
+};
+
+logging {
+ category <string> { <string>; ... };
+ channel <string> {
+ file <quoted_string> [ versions ( "unlimited" | <integer> )
+ ] [ size <size> ];
+ null;
+ print-category <boolean>;
+ print-severity <boolean>;
+ print-time <boolean>;
+ severity <log_severity>;
+ stderr;
+ syslog <optional_facility>;
+ };
+};
+
+lwres {
+ listen-on [ port <integer> ] { ( <ipv4_address> | <ipv6_address> )
+ [ port <integer> ]; ... };
+ ndots <integer>;
+ search { <string>; ... };
+ view <string> <optional_class>;
+};
+
+masters <string> [ port <integer> ] { ( <masters> | <ipv4_address> [ port
+ <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ]; ... };
+
+options {
+ acache-cleaning-interval <integer>;
+ acache-enable <boolean>;
+ additional-from-auth <boolean>;
+ additional-from-cache <boolean>;
+ allow-notify { <address_match_element>; ... };
+ allow-query { <address_match_element>; ... };
+ allow-query-cache { <address_match_element>; ... };
+ allow-query-cache-on { <address_match_element>; ... };
+ allow-query-on { <address_match_element>; ... };
+ allow-recursion { <address_match_element>; ... };
+ allow-recursion-on { <address_match_element>; ... };
+ allow-transfer { <address_match_element>; ... };
+ allow-update { <address_match_element>; ... };
+ allow-update-forwarding { <address_match_element>; ... };
+ allow-v6-synthesis { <address_match_element>; ... }; // obsolete
+ also-notify [ port <integer> ] { ( <ipv4_address> | <ipv6_address>
+ ) [ port <integer> ]; ... };
+ alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ alt-transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> |
+ * ) ];
+ auth-nxdomain <boolean>; // default changed
+ avoid-v4-udp-ports { <portrange>; ... };
+ avoid-v6-udp-ports { <portrange>; ... };
+ blackhole { <address_match_element>; ... };
+ cache-file <quoted_string>;
+ check-integrity <boolean>;
+ check-mx ( fail | warn | ignore );
+ check-mx-cname ( fail | warn | ignore );
+ check-names ( master | slave | response ) ( fail | warn | ignore );
+ check-sibling <boolean>;
+ check-srv-cname ( fail | warn | ignore );
+ check-wildcard <boolean>;
+ cleaning-interval <integer>;
+ clients-per-query <integer>;
+ coresize <size>;
+ datasize <size>;
+ deallocate-on-exit <boolean>; // obsolete
+ dialup <dialuptype>;
+ directory <quoted_string>;
+ disable-algorithms <string> { <string>; ... };
+ disable-empty-zone <string>;
+ dnssec-accept-expired <boolean>;
+ dnssec-enable <boolean>;
+ dnssec-lookaside <string> trust-anchor <string>;
+ dnssec-must-be-secure <string> <boolean>;
+ dnssec-validation <boolean>;
+ dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
+ <integer> ] | <ipv4_address> [ port <integer> ] |
+ <ipv6_address> [ port <integer> ] ); ... };
+ dump-file <quoted_string>;
+ edns-udp-size <integer>;
+ empty-contact <string>;
+ empty-server <string>;
+ empty-zones-enable <boolean>;
+ fake-iquery <boolean>; // obsolete
+ fetch-glue <boolean>; // obsolete
+ files <size>;
+ flush-zones-on-shutdown <boolean>;
+ forward ( first | only );
+ forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> )
+ [ port <integer> ]; ... };
+ has-old-clients <boolean>; // obsolete
+ heartbeat-interval <integer>;
+ host-statistics <boolean>; // not implemented
+ host-statistics-max <integer>; // not implemented
+ hostname ( <quoted_string> | none );
+ interface-interval <integer>;
+ ixfr-from-differences <ixfrdiff>;
+ key-directory <quoted_string>;
+ lame-ttl <integer>;
+ listen-on [ port <integer> ] { <address_match_element>; ... };
+ listen-on-v6 [ port <integer> ] { <address_match_element>; ... };
+ maintain-ixfr-base <boolean>; // obsolete
+ masterfile-format ( text | raw );
+ match-mapped-addresses <boolean>;
+ max-acache-size <size_no_default>;
+ max-cache-size <size_no_default>;
+ max-cache-ttl <integer>;
+ max-clients-per-query <integer>;
+ max-ixfr-log-size <size>; // obsolete
+ max-journal-size <size_no_default>;
+ max-ncache-ttl <integer>;
+ max-refresh-time <integer>;
+ max-retry-time <integer>;
+ max-transfer-idle-in <integer>;
+ max-transfer-idle-out <integer>;
+ max-transfer-time-in <integer>;
+ max-transfer-time-out <integer>;
+ max-udp-size <integer>;
+ memstatistics <boolean>;
+ memstatistics-file <quoted_string>;
+ min-refresh-time <integer>;
+ min-retry-time <integer>;
+ min-roots <integer>; // not implemented
+ minimal-responses <boolean>;
+ multi-master <boolean>;
+ multiple-cnames <boolean>; // obsolete
+ named-xfer <quoted_string>; // obsolete
+ notify <notifytype>;
+ notify-delay <integer>;
+ notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+ notify-to-soa <boolean>;
+ nsec3-test-zone <boolean>; // test only
+ pid-file ( <quoted_string> | none );
+ port <integer>;
+ preferred-glue <string>;
+ provide-ixfr <boolean>;
+ query-source <querysource4>;
+ query-source-v6 <querysource6>;
+ querylog <boolean>;
+ queryport-pool-ports <integer>; // obsolete
+ queryport-pool-updateinterval <integer>; // obsolete
+ random-device <quoted_string>;
+ recursing-file <quoted_string>;
+ recursion <boolean>;
+ recursive-clients <integer>;
+ request-ixfr <boolean>;
+ request-nsid <boolean>;
+ reserved-sockets <integer>;
+ rfc2308-type1 <boolean>; // not yet implemented
+ root-delegation-only [ exclude { <quoted_string>; ... } ];
+ rrset-order { [ class <string> ] [ type <string> ] [ name
+ <quoted_string> ] <string> <string>; ... };
+ serial-queries <integer>; // obsolete
+ serial-query-rate <integer>;
+ server-id ( <quoted_string> | none |;
+ sig-signing-nodes <integer>;
+ sig-signing-signatures <integer>;
+ sig-signing-type <integer>;
+ sig-validity-interval <integer> [ <integer> ];
+ sortlist { <address_match_element>; ... };
+ stacksize <size>;
+ statistics-file <quoted_string>;
+ statistics-interval <integer>; // not yet implemented
+ suppress-initial-notify <boolean>; // not yet implemented
+ tcp-clients <integer>;
+ tcp-listen-queue <integer>;
+ tkey-dhkey <quoted_string> <integer>;
+ tkey-domain <quoted_string>;
+ tkey-gssapi-credential <quoted_string>;
+ topology { <address_match_element>; ... }; // not implemented
+ transfer-format ( many-answers | one-answer );
+ transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+ transfers-in <integer>;
+ transfers-out <integer>;
+ transfers-per-ns <integer>;
+ treat-cr-as-space <boolean>; // obsolete
+ try-tcp-refresh <boolean>;
+ update-check-ksk <boolean>;
+ use-alt-transfer-source <boolean>;
+ use-id-pool <boolean>; // obsolete
+ use-ixfr <boolean>;
+ use-queryport-pool <boolean>; // obsolete
+ use-v4-udp-ports { <portrange>; ... };
+ use-v6-udp-ports { <portrange>; ... };
+ version ( <quoted_string> | none );
+ zero-no-soa-ttl <boolean>;
+ zero-no-soa-ttl-cache <boolean>;
+ zone-statistics <boolean>;
+};
+
+server <netprefix> {
+ bogus <boolean>;
+ edns <boolean>;
+ edns-udp-size <integer>;
+ keys <server_key>;
+ max-udp-size <integer>;
+ notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+ provide-ixfr <boolean>;
+ query-source <querysource4>;
+ query-source-v6 <querysource6>;
+ request-ixfr <boolean>;
+ support-ixfr <boolean>; // obsolete
+ transfer-format ( many-answers | one-answer );
+ transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+ transfers <integer>;
+};
+
+statistics-channels {
+ inet ( <ipv4_address> | <ipv6_address> | * ) [ port ( <integer> | *
+ ) ] [ allow { <address_match_element>; ... } ];
+};
+
+trusted-keys { <string> <integer> <integer> <integer> <quoted_string>; ... };
+
+view <string> <optional_class> {
+ acache-cleaning-interval <integer>;
+ acache-enable <boolean>;
+ additional-from-auth <boolean>;
+ additional-from-cache <boolean>;
+ allow-notify { <address_match_element>; ... };
+ allow-query { <address_match_element>; ... };
+ allow-query-cache { <address_match_element>; ... };
+ allow-query-cache-on { <address_match_element>; ... };
+ allow-query-on { <address_match_element>; ... };
+ allow-recursion { <address_match_element>; ... };
+ allow-recursion-on { <address_match_element>; ... };
+ allow-transfer { <address_match_element>; ... };
+ allow-update { <address_match_element>; ... };
+ allow-update-forwarding { <address_match_element>; ... };
+ allow-v6-synthesis { <address_match_element>; ... }; // obsolete
+ also-notify [ port <integer> ] { ( <ipv4_address> | <ipv6_address>
+ ) [ port <integer> ]; ... };
+ alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ alt-transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> |
+ * ) ];
+ auth-nxdomain <boolean>; // default changed
+ cache-file <quoted_string>;
+ check-integrity <boolean>;
+ check-mx ( fail | warn | ignore );
+ check-mx-cname ( fail | warn | ignore );
+ check-names ( master | slave | response ) ( fail | warn | ignore );
+ check-sibling <boolean>;
+ check-srv-cname ( fail | warn | ignore );
+ check-wildcard <boolean>;
+ cleaning-interval <integer>;
+ clients-per-query <integer>;
+ database <string>;
+ dialup <dialuptype>;
+ disable-algorithms <string> { <string>; ... };
+ disable-empty-zone <string>;
+ dlz <string> {
+ database <string>;
+ };
+ dnssec-accept-expired <boolean>;
+ dnssec-enable <boolean>;
+ dnssec-lookaside <string> trust-anchor <string>;
+ dnssec-must-be-secure <string> <boolean>;
+ dnssec-validation <boolean>;
+ dual-stack-servers [ port <integer> ] { ( <quoted_string> [ port
+ <integer> ] | <ipv4_address> [ port <integer> ] |
+ <ipv6_address> [ port <integer> ] ); ... };
+ edns-udp-size <integer>;
+ empty-contact <string>;
+ empty-server <string>;
+ empty-zones-enable <boolean>;
+ fetch-glue <boolean>; // obsolete
+ forward ( first | only );
+ forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> )
+ [ port <integer> ]; ... };
+ ixfr-from-differences <ixfrdiff>;
+ key <string> {
+ algorithm <string>;
+ secret <string>;
+ };
+ key-directory <quoted_string>;
+ lame-ttl <integer>;
+ maintain-ixfr-base <boolean>; // obsolete
+ masterfile-format ( text | raw );
+ match-clients { <address_match_element>; ... };
+ match-destinations { <address_match_element>; ... };
+ match-recursive-only <boolean>;
+ max-acache-size <size_no_default>;
+ max-cache-size <size_no_default>;
+ max-cache-ttl <integer>;
+ max-clients-per-query <integer>;
+ max-ixfr-log-size <size>; // obsolete
+ max-journal-size <size_no_default>;
+ max-ncache-ttl <integer>;
+ max-refresh-time <integer>;
+ max-retry-time <integer>;
+ max-transfer-idle-in <integer>;
+ max-transfer-idle-out <integer>;
+ max-transfer-time-in <integer>;
+ max-transfer-time-out <integer>;
+ max-udp-size <integer>;
+ min-refresh-time <integer>;
+ min-retry-time <integer>;
+ min-roots <integer>; // not implemented
+ minimal-responses <boolean>;
+ multi-master <boolean>;
+ notify <notifytype>;
+ notify-delay <integer>;
+ notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+ notify-to-soa <boolean>;
+ nsec3-test-zone <boolean>; // test only
+ preferred-glue <string>;
+ provide-ixfr <boolean>;
+ query-source <querysource4>;
+ query-source-v6 <querysource6>;
+ queryport-pool-ports <integer>; // obsolete
+ queryport-pool-updateinterval <integer>; // obsolete
+ recursion <boolean>;
+ request-ixfr <boolean>;
+ request-nsid <boolean>;
+ rfc2308-type1 <boolean>; // not yet implemented
+ root-delegation-only [ exclude { <quoted_string>; ... } ];
+ rrset-order { [ class <string> ] [ type <string> ] [ name
+ <quoted_string> ] <string> <string>; ... };
+ server <netprefix> {
+ bogus <boolean>;
+ edns <boolean>;
+ edns-udp-size <integer>;
+ keys <server_key>;
+ max-udp-size <integer>;
+ notify-source ( <ipv4_address> | * ) [ port ( <integer> | *
+ ) ];
+ notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer>
+ | * ) ];
+ provide-ixfr <boolean>;
+ query-source <querysource4>;
+ query-source-v6 <querysource6>;
+ request-ixfr <boolean>;
+ support-ixfr <boolean>; // obsolete
+ transfer-format ( many-answers | one-answer );
+ transfer-source ( <ipv4_address> | * ) [ port ( <integer> |
+ * ) ];
+ transfer-source-v6 ( <ipv6_address> | * ) [ port (
+ <integer> | * ) ];
+ transfers <integer>;
+ };
+ sig-signing-nodes <integer>;
+ sig-signing-signatures <integer>;
+ sig-signing-type <integer>;
+ sig-validity-interval <integer> [ <integer> ];
+ sortlist { <address_match_element>; ... };
+ suppress-initial-notify <boolean>; // not yet implemented
+ topology { <address_match_element>; ... }; // not implemented
+ transfer-format ( many-answers | one-answer );
+ transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+ trusted-keys { <string> <integer> <integer> <integer>
+ <quoted_string>; ... };
+ try-tcp-refresh <boolean>;
+ update-check-ksk <boolean>;
+ use-alt-transfer-source <boolean>;
+ use-queryport-pool <boolean>; // obsolete
+ zero-no-soa-ttl <boolean>;
+ zero-no-soa-ttl-cache <boolean>;
+ zone <string> <optional_class> {
+ allow-notify { <address_match_element>; ... };
+ 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>; ... };
+ also-notify [ port <integer> ] { ( <ipv4_address> |
+ <ipv6_address> ) [ port <integer> ]; ... };
+ alt-transfer-source ( <ipv4_address> | * ) [ port (
+ <integer> | * ) ];
+ alt-transfer-source-v6 ( <ipv6_address> | * ) [ port (
+ <integer> | * ) ];
+ check-integrity <boolean>;
+ check-mx ( fail | warn | ignore );
+ check-mx-cname ( fail | warn | ignore );
+ check-names ( fail | warn | ignore );
+ check-sibling <boolean>;
+ check-srv-cname ( fail | warn | ignore );
+ check-wildcard <boolean>;
+ database <string>;
+ delegation-only <boolean>;
+ dialup <dialuptype>;
+ file <quoted_string>;
+ forward ( first | only );
+ forwarders [ port <integer> ] { ( <ipv4_address> |
+ <ipv6_address> ) [ port <integer> ]; ... };
+ ixfr-base <quoted_string>; // obsolete
+ ixfr-from-differences <boolean>;
+ ixfr-tmp-file <quoted_string>; // obsolete
+ journal <quoted_string>;
+ key-directory <quoted_string>;
+ maintain-ixfr-base <boolean>; // obsolete
+ masterfile-format ( text | raw );
+ masters [ port <integer> ] { ( <masters> | <ipv4_address> [
+ port <integer> ] | <ipv6_address> [ port <integer> ] )
+ [ key <string> ]; ... };
+ max-ixfr-log-size <size>; // obsolete
+ max-journal-size <size_no_default>;
+ max-refresh-time <integer>;
+ max-retry-time <integer>;
+ max-transfer-idle-in <integer>;
+ max-transfer-idle-out <integer>;
+ max-transfer-time-in <integer>;
+ max-transfer-time-out <integer>;
+ min-refresh-time <integer>;
+ min-retry-time <integer>;
+ multi-master <boolean>;
+ notify <notifytype>;
+ notify-delay <integer>;
+ notify-source ( <ipv4_address> | * ) [ port ( <integer> | *
+ ) ];
+ notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer>
+ | * ) ];
+ notify-to-soa <boolean>;
+ nsec3-test-zone <boolean>; // test only
+ pubkey <integer> <integer> <integer>
+ <quoted_string>; // obsolete
+ sig-signing-nodes <integer>;
+ sig-signing-signatures <integer>;
+ sig-signing-type <integer>;
+ sig-validity-interval <integer> [ <integer> ];
+ transfer-source ( <ipv4_address> | * ) [ port ( <integer> |
+ * ) ];
+ transfer-source-v6 ( <ipv6_address> | * ) [ port (
+ <integer> | * ) ];
+ try-tcp-refresh <boolean>;
+ type ( master | slave | stub | hint | forward |
+ delegation-only );
+ update-check-ksk <boolean>;
+ update-policy { ( grant | deny ) <string> ( name |
+ subdomain | wildcard | self | selfsub | selfwild |
+ krb5-self | ms-self | krb5-subdomain | ms-subdomain |
+ tcp-self | 6to4-self ) <string> <rrtypelist>; ... };
+ use-alt-transfer-source <boolean>;
+ zero-no-soa-ttl <boolean>;
+ zone-statistics <boolean>;
+ };
+ zone-statistics <boolean>;
+};
+
+zone <string> <optional_class> {
+ allow-notify { <address_match_element>; ... };
+ 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>; ... };
+ also-notify [ port <integer> ] { ( <ipv4_address> | <ipv6_address>
+ ) [ port <integer> ]; ... };
+ alt-transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ alt-transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> |
+ * ) ];
+ check-integrity <boolean>;
+ check-mx ( fail | warn | ignore );
+ check-mx-cname ( fail | warn | ignore );
+ check-names ( fail | warn | ignore );
+ check-sibling <boolean>;
+ check-srv-cname ( fail | warn | ignore );
+ check-wildcard <boolean>;
+ database <string>;
+ delegation-only <boolean>;
+ dialup <dialuptype>;
+ file <quoted_string>;
+ forward ( first | only );
+ forwarders [ port <integer> ] { ( <ipv4_address> | <ipv6_address> )
+ [ port <integer> ]; ... };
+ ixfr-base <quoted_string>; // obsolete
+ ixfr-from-differences <boolean>;
+ ixfr-tmp-file <quoted_string>; // obsolete
+ journal <quoted_string>;
+ key-directory <quoted_string>;
+ maintain-ixfr-base <boolean>; // obsolete
+ masterfile-format ( text | raw );
+ masters [ port <integer> ] { ( <masters> | <ipv4_address> [ port
+ <integer> ] | <ipv6_address> [ port <integer> ] ) [ key
+ <string> ]; ... };
+ max-ixfr-log-size <size>; // obsolete
+ max-journal-size <size_no_default>;
+ max-refresh-time <integer>;
+ max-retry-time <integer>;
+ max-transfer-idle-in <integer>;
+ max-transfer-idle-out <integer>;
+ max-transfer-time-in <integer>;
+ max-transfer-time-out <integer>;
+ min-refresh-time <integer>;
+ min-retry-time <integer>;
+ multi-master <boolean>;
+ notify <notifytype>;
+ notify-delay <integer>;
+ notify-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ notify-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+ notify-to-soa <boolean>;
+ nsec3-test-zone <boolean>; // test only
+ pubkey <integer> <integer> <integer> <quoted_string>; // obsolete
+ sig-signing-nodes <integer>;
+ sig-signing-signatures <integer>;
+ sig-signing-type <integer>;
+ sig-validity-interval <integer> [ <integer> ];
+ transfer-source ( <ipv4_address> | * ) [ port ( <integer> | * ) ];
+ transfer-source-v6 ( <ipv6_address> | * ) [ port ( <integer> | * ) ];
+ try-tcp-refresh <boolean>;
+ type ( master | slave | stub | hint | forward | delegation-only );
+ update-check-ksk <boolean>;
+ update-policy { ( grant | deny ) <string> ( name | subdomain |
+ wildcard | self | selfsub | selfwild | krb5-self | ms-self |
+ krb5-subdomain | ms-subdomain | tcp-self | 6to4-self ) <string>
+ <rrtypelist>; ... };
+ use-alt-transfer-source <boolean>;
+ zero-no-soa-ttl <boolean>;
+ zone-statistics <boolean>;
+};
+
diff --git a/doc/misc/rfc-compliance b/doc/misc/rfc-compliance
new file mode 100644
index 0000000..4c87c66
--- /dev/null
+++ b/doc/misc/rfc-compliance
@@ -0,0 +1,62 @@
+Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2001 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+$Id: rfc-compliance,v 1.4 2004/03/05 05:04:53 marka Exp $
+
+BIND 9 is striving for strict compliance with IETF standards. We
+believe this release of BIND 9 complies with the following RFCs, with
+the caveats and exceptions listed in the numbered notes below. Note
+that a number of these RFCs do not have the status of Internet
+standards but are proposed or draft standards, experimental RFCs,
+or Best Current Practice (BCP) documents.
+
+ RFC1034
+ RFC1035 [1] [2]
+ RFC1123
+ RFC1183
+ RFC1535
+ RFC1536
+ RFC1706
+ RFC1712
+ RFC1750
+ RFC1876
+ RFC1982
+ RFC1995
+ RFC1996
+ RFC2136
+ RFC2163
+ RFC2181
+ RFC2230
+ RFC2308
+ RFC2535 [3] [4]
+ RFC2536
+ RFC2537
+ RFC2538
+ RFC2539
+ RFC2671
+ RFC2672
+ RFC2673
+ RFC2782
+ RFC2915
+ RFC2930
+ RFC2931 [5]
+ RFC3007
+
+
+[1] Queries to zones that have failed to load return SERVFAIL rather
+than a non-authoritative response. This is considered a feature.
+
+[2] CLASS ANY queries are not supported. This is considered a feature.
+
+[3] Wildcard records are not supported in DNSSEC secure zones.
+
+[4] Servers authoritative for secure zones being resolved by BIND 9
+must support EDNS0 (RFC2671), and must return all relevant SIGs and
+NXTs in responses rather than relying on the resolving server to
+perform separate queries for missing SIGs and NXTs.
+
+[5] When receiving a query signed with a SIG(0), the server will only
+be able to verify the signature if it has the key in its local
+authoritative data; it will not do recursion or validation to
+retrieve unknown keys.
diff --git a/doc/misc/roadmap b/doc/misc/roadmap
new file mode 100644
index 0000000..f63a469
--- /dev/null
+++ b/doc/misc/roadmap
@@ -0,0 +1,47 @@
+Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2000, 2001 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+$Id: roadmap,v 1.2 2004/03/05 05:04:54 marka Exp $
+
+Road Map to the BIND 9 Source Tree
+
+bin/named The name server. This relies heavily on the
+ libraries in lib/isc and lib/dns.
+ client.c Handling of incoming client requests
+ query.c Query processing
+bin/rndc The remote name daemon control program
+bin/dig The "dig" program
+bin/dnssec The DNSSEC signer and other DNSSEC tools
+bin/nsupdate The "nsupdate" program
+bin/tests Test suites and miscellaneous test programs
+bin/tests/system System tests; see bin/tests/system/README
+lib/dns The DNS library
+ resolver.c The "full resolver" (performs recursive lookups)
+ validator.c The DNSSEC validator
+ db.c The database interface
+ sdb.c The simple database interface
+ rbtdb.c The red-black tree database
+lib/dns/rdata Routines for handling the various RR types
+lib/dns/sec Cryptographic libraries for DNSSEC
+lib/isc The ISC library
+ task.c Task library
+ unix/socket.c Unix implementation of socket library
+lib/isccfg Routines for reading and writing ISC-style
+ configuration files like named.conf and rndc.conf
+lib/isccc The command channel library, used by rndc.
+lib/tests Support code for the test suites.
+lib/lwres The lightweight resolver library.
+doc/draft Current internet-drafts pertaining to the DNS
+doc/rfc RFCs pertaining to the DNS
+doc/misc Miscellaneous documentation
+doc/arm The BIND 9 Administrator Reference Manual
+doc/man Man pages
+contrib Contributed and other auxiliary code
+contrib/idn/mdnkit The multilingual domain name evaluation kit
+contrib/sdb Sample drivers for the simple database interface
+make Makefile fragments, used by configure
+
+The library interfaces are mainly documented in the form of comments
+in the header files. For example, the task subsystem is documented in
+lib/isc/include/isc/task.h
diff --git a/doc/misc/sdb b/doc/misc/sdb
new file mode 100644
index 0000000..552028a
--- /dev/null
+++ b/doc/misc/sdb
@@ -0,0 +1,169 @@
+Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2000, 2001 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+Using the BIND 9 Simplified Database Interface
+
+This document describes the care and feeding of the BIND 9 Simplified
+Database Interface, which allows you to extend BIND 9 with new ways
+of obtaining the data that is published as DNS zones.
+
+
+The Original BIND 9 Database Interface
+
+BIND 9 has a well-defined "back-end database interface" that makes it
+possible to replace the component of the name server responsible for
+the storage and retrieval of zone data, called the "database", on a
+per-zone basis. The default database is an in-memory, red-black-tree
+data structure commonly referred to as "rbtdb", but it is possible to
+write drivers to support any number of alternative database
+technologies such as in-memory hash tables, application specific
+persistent on-disk databases, object databases, or relational
+databases.
+
+The original BIND 9 database interface defined in <dns/db.h> is
+designed to efficiently support the full set of database functionality
+needed by a name server that implements the complete DNS protocols,
+including features such as zone transfers, dynamic update, and DNSSEC.
+Each of these aspects of name server operations places its own set of
+demands on the data store, with the result that the database API is
+quite complex and contains operations that are highly specific to the
+DNS. For example, data are stored in a binary format, the name space
+is tree structured, and sets of data records are conceptually
+associated with DNSSEC signature sets. For these reasons, writing a
+driver using this interface is a highly nontrivial undertaking.
+
+
+The Simplified Database Interface
+
+Many BIND users wish to provide access to various data sources through
+the DNS, but are not necessarily interested in completely replacing
+the in-memory "rbt" database or in supporting features like dynamic
+update, DNSSEC, or even zone transfers.
+
+Often, all you want is limited, read-only DNS access to an existing
+system. For example, you may have an existing relational database
+containing hostname/address mappings and wish to provide forvard and
+reverse DNS lookups based on this information. Or perhaps you want to
+set up a simple DNS-based load balancing system where the name server
+answers queries about a single DNS name with a dynamically changing
+set of A records.
+
+BIND 9.1 introduced a new, simplified database interface, or "sdb",
+which greatly simplifies the writing of drivers for these kinds of
+applications.
+
+
+The sdb Driver
+
+An sdb driver is an object module, typically written in C, which is
+linked into the name server and registers itself with the sdb
+subsystem. It provides a set of callback functions, which also serve
+to advertise its capabilities. When the name server receives DNS
+queries, invokes the callback functions to obtain the data to respond
+with.
+
+Unlike the full database interface, the sdb interface represents all
+domain names and resource records as ASCII text.
+
+
+Writing an sdb Driver
+
+When a driver is registered, it specifies its name, a list of callback
+functions, and flags.
+
+The flags specify whether the driver wants to use relative domain
+names where possible.
+
+The callback functions are as follows. The only one that must be
+defined is lookup().
+
+ - create(zone, argc, argv, driverdata, dbdata)
+ Create a database object for "zone".
+
+ - destroy(zone, driverdata, dbdata)
+ Destroy the database object for "zone".
+
+ - lookup(zone, name, dbdata, lookup)
+ Return all the records at the domain name "name".
+
+ - authority(zone, dbdata, lookup)
+ Return the SOA and NS records at the zone apex.
+
+ - allnodes(zone, dbdata, allnodes)
+ Return all data in the zone, for zone transfers.
+
+For more detail about these functions and their parameters, see
+bind9/lib/dns/include/dns/sdb.h. For example drivers, see
+bind9/contrib/sdb.
+
+
+Rebuilding the Server
+
+The driver module and header file must be copied to (or linked into)
+the bind9/bin/named and bind9/bin/named/include directories
+respectively, and must be added to the DBDRIVER_OBJS and DBDRIVER_SRCS
+lines in bin/named/Makefile.in (e.g. for the timedb sample sdb driver,
+add timedb.c to DBDRIVER_SRCS and timedb.@O@ to DBDRIVER_OBJS). If
+the driver needs additional header files or libraries in nonstandard
+places, the DBDRIVER_INCLUDES and DBDRIVER_LIBS lines should also be
+updated.
+
+Calls to dns_sdb_register() and dns_sdb_unregister() (or wrappers,
+e.g. timedb_init() and timedb_clear() for the timedb sample sdb
+driver) must be inserted into the server, in bind9/bin/named/main.c.
+Registration should be in setup(), before the call to
+ns_server_create(). Unregistration should be in cleanup(),
+after the call to ns_server_destroy(). A #include should be added
+corresponding to the driver header file.
+
+You should try doing this with one or more of the sample drivers
+before attempting to write a driver of your own.
+
+
+Configuring the Server
+
+To make a zone use a new database driver, specify a "database" option
+in its "zone" statement in named.conf. For example, if the driver
+registers itself under the name "acmedb", you might say
+
+ zone "foo.com" {
+ database "acmedb";
+ };
+
+You can pass arbitrary arguments to the create() function of the
+driver by adding any number of whitespace-separated words after the
+driver name:
+
+ zone "foo.com" {
+ database "acmedb -mode sql -connect 10.0.0.1";
+ };
+
+
+Hints for Driver Writers
+
+ - If a driver is generating data on the fly, it probably should
+ not implement the allnodes() function, since a zone transfer
+ will not be meaningful. The allnodes() function is more relevant
+ with data from a database.
+
+ - The authority() function is necessary if and only if the lookup()
+ function will not add SOA and NS records at the zone apex. If
+ SOA and NS records are provided by the lookup() function,
+ the authority() function should be NULL.
+
+ - When a driver is registered, an opaque object can be provided. This
+ object is passed into the database create() and destroy() functions.
+
+ - When a database is created, an opaque object can be created that
+ is associated with that database. This object is passed into the
+ lookup(), authority(), and allnodes() functions, and is
+ destroyed by the destroy() function.
+
+
+Future Directions
+
+A future release may support dynamic loading of sdb drivers.
+
+
+$Id: sdb,v 1.6 2004/03/05 05:04:54 marka Exp $
diff --git a/doc/misc/sort-options.pl b/doc/misc/sort-options.pl
new file mode 100644
index 0000000..4251521
--- /dev/null
+++ b/doc/misc/sort-options.pl
@@ -0,0 +1,50 @@
+#!/bin/perl
+#
+# Copyright (C) 2007 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: sort-options.pl,v 1.3 2007/09/24 23:46:48 tbox Exp $
+
+sub sortlevel() {
+ my @options = ();
+ my $fin = "";
+ my $i = 0;
+ while (<>) {
+ if (/^\s*};$/) {
+ $fin = $_;
+ # print 2, $_;
+ last;
+ }
+ next if (/^$/);
+ if (/{$/) {
+ # print 3, $_;
+ my $sec = $_;
+ push(@options, $sec . sortlevel());
+ } else {
+ push(@options, $_);
+ # print 1, $_;
+ }
+ $i++;
+ }
+ my $result = "";
+ foreach my $i (sort @options) {
+ $result = ${result}.${i};
+ $result = $result."\n" if ($i =~ /^[a-z]/i);
+ # print 5, ${i};
+ }
+ $result = ${result}.${fin};
+ return ($result);
+}
+
+print sortlevel();
diff --git a/doc/rfc/fetch b/doc/rfc/fetch
new file mode 100755
index 0000000..17ce40f
--- /dev/null
+++ b/doc/rfc/fetch
@@ -0,0 +1,6 @@
+#!/bin/sh -f
+for i in $*
+do
+ i=`echo $i | sed -e 's/^rfc//' -e 's/\.txt$//'`
+ fetch "http://www.ietf.org/rfc/rfc${i}.txt"
+done
diff --git a/doc/rfc/index b/doc/rfc/index
new file mode 100644
index 0000000..fea5f71
--- /dev/null
+++ b/doc/rfc/index
@@ -0,0 +1,119 @@
+ 952: DOD INTERNET HOST TABLE SPECIFICATION
+1032: DOMAIN ADMINISTRATORS GUIDE
+1033: DOMAIN ADMINISTRATORS OPERATIONS GUIDE
+1034: DOMAIN NAMES - CONCEPTS AND FACILITIES
+1035: DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION
+1101: DNS Encoding of Network Names and Other Types
+1122: Requirements for Internet Hosts -- Communication Layers
+1123: Requirements for Internet Hosts -- Application and Support
+1183: New DNS RR Definitions (AFSDB, RP, X25, ISDN and RT)
+1348: DNS NSAP RRs
+1535: A Security Problem and Proposed Correction
+ With Widely Deployed DNS Software
+1536: Common DNS Implementation Errors and Suggested Fixes
+1537: Common DNS Data File Configuration Errors
+1591: Domain Name System Structure and Delegation
+1611: DNS Server MIB Extensions
+1612: DNS Resolver MIB Extensions
+1706: DNS NSAP Resource Records
+1712: DNS Encoding of Geographical Location
+1750: Randomness Recommendations for Security
+1876: A Means for Expressing Location Information in the Domain Name System
+1886: DNS Extensions to support IP version 6
+1982: Serial Number Arithmetic
+1995: Incremental Zone Transfer in DNS
+1996: A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY)
+2052: A DNS RR for specifying the location of services (DNS SRV)
+2104: HMAC: Keyed-Hashing for Message Authentication
+2119: Key words for use in RFCs to Indicate Requirement Levels
+2133: Basic Socket Interface Extensions for IPv6
+2136: Dynamic Updates in the Domain Name System (DNS UPDATE)
+2137: Secure Domain Name System Dynamic Update
+2163: Using the Internet DNS to Distribute MIXER
+ Conformant Global Address Mapping (MCGAM)
+2168: Resolution of Uniform Resource Identifiers using the Domain Name System
+2181: Clarifications to the DNS Specification
+2230: Key Exchange Delegation Record for the DNS
+2308: Negative Caching of DNS Queries (DNS NCACHE)
+2317: Classless IN-ADDR.ARPA delegation
+2373: IP Version 6 Addressing Architecture
+2374: An IPv6 Aggregatable Global Unicast Address Format
+2375: IPv6 Multicast Address Assignments
+2418: IETF Working Group Guidelines and Procedures
+2535: Domain Name System Security Extensions
+2536: DSA KEYs and SIGs in the Domain Name System (DNS)
+2537: RSA/MD5 KEYs and SIGs in the Domain Name System (DNS)
+2538: Storing Certificates in the Domain Name System (DNS)
+2539: Storage of Diffie-Hellman Keys in the Domain Name System (DNS)
+2540: Detached Domain Name System (DNS) Information
+2541: DNS Security Operational Considerations
+2553: Basic Socket Interface Extensions for IPv6
+2671: Extension Mechanisms for DNS (EDNS0)
+2672: Non-Terminal DNS Name Redirection
+2673: Binary Labels in the Domain Name System
+2782: A DNS RR for specifying the location of services (DNS SRV)
+2825: A Tangled Web: Issues of I18N, Domain Names, and the
+ Other Internet protocols
+2826: IAB Technical Comment on the Unique DNS Root
+2845: Secret Key Transaction Authentication for DNS (TSIG)
+2874: DNS Extensions to Support IPv6 Address Aggregation and Renumbering
+2915: The Naming Authority Pointer (NAPTR) DNS Resource Record
+2929: Domain Name System (DNS) IANA Considerations
+2930: Secret Key Establishment for DNS (TKEY RR)
+2931: DNS Request and Transaction Signatures ( SIG(0)s )
+3007: Secure Domain Name System (DNS) Dynamic Update
+3008: Domain Name System Security (DNSSEC) Signing Authority
+3056: Connection of IPv6 Domains via IPv4 Clouds
+3071: Reflections on the DNS, RFC 1591, and Categories of Domains
+3090: DNS Security Extension Clarification on Zone Status
+3110: RSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS)
+3123: A DNS RR Type for Lists of Address Prefixes (APL RR)
+3152: Delegation of IP6.ARPA
+3197: Applicability Statement for DNS MIB Extensions
+3225: Indicating Resolver Support of DNSSEC
+3226: DNSSEC and IPv6 A6 aware server/resolver message size requirements
+3258: Distributing Authoritative Name Servers via Shared Unicast Addresses
+3363: Representing Internet Protocol version 6 (IPv6)
+ Addresses in the Domain Name System (DNS)
+3364: Tradeoffs in Domain Name System (DNS) Support
+ for Internet Protocol version 6 (IPv6)
+3425: Obsoleting IQUERY
+3445: Limiting the Scope of the KEY Resource Record (RR)
+3490: Internationalizing Domain Names In Applications (IDNA)
+3491: Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN)
+3492: Punycode:A Bootstring encoding of Unicode for
+ Internationalized Domain Names in Applications (IDNA)
+3493: Basic Socket Interface Extensions for IPv6
+3513: Internet Protocol Version 6 (IPv6) Addressing Architecture
+3596: DNS Extensions to Support IP Version 6
+3597: Handling of Unknown DNS Resource Record (RR) Types
+3645: Generic Security Service Algorithm for
+ Secret Key Transaction Authentication for DNS (GSS-TSIG)
+3655: Redefinition of DNS Authenticated Data (AD) bit
+3658: Delegation Signer (DS) Resource Record (RR)
+3757: Domain Name System KEY (DNSKEY) Resource Record (RR)
+ Secure Entry Point (SEP) Flag
+3833: Threat Analysis of the Domain Name System (DNS)
+3845: DNS Security (DNSSEC) NextSECure (NSEC) RDATA Format
+3901: DNS IPv6 Transport Operational Guidelines
+4025: A Method for Storing IPsec Keying Material in DNS
+4033: DNS Security Introduction and Requirements
+4034: Resource Records for the DNS Security Extensions
+4035: Protocol Modifications for the DNS Security Extensions
+4074: Common Misbehavior Against DNS Queries for IPv6 Addresses
+4159: Deprecation of "ip6.int"
+4193: Unique Local IPv6 Unicast Addresses
+4255: Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
+4343: Domain Name System (DNS) Case Insensitivity Clarification
+4367: What's in a Name: False Assumptions about DNS Names
+4398: Storing Certificates in the Domain Name System (DNS)
+4431: The DNSSEC Lookaside Validation (DLV) DNS Resource Record
+4408: Sender Policy Framework (SPF) for Authorizing Use of Domains
+ in E-Mail, Version 1
+4470: Minimally Covering NSEC Records and DNSSEC On-line Signing
+4634: US Secure Hash Algorithms (SHA and HMAC-SHA)
+4641: DNSSEC Operational Practices
+4648: The Base16, Base32, and Base64 Data Encodings
+4701: A DNS Resource Record (RR) for Encoding
+ Dynamic Host Configuration Protocol (DHCP) Information (DHCID RR)
+5155: DNS Security (DNSSEC) Hashed Authenticated Denial of Existence
diff --git a/doc/rfc/rfc1032.txt b/doc/rfc/rfc1032.txt
new file mode 100644
index 0000000..0e82721
--- /dev/null
+++ b/doc/rfc/rfc1032.txt
@@ -0,0 +1,781 @@
+Network Working Group M. Stahl
+Request for Comments: 1032 SRI International
+ November 1987
+
+
+ DOMAIN ADMINISTRATORS GUIDE
+
+
+STATUS OF THIS MEMO
+
+ This memo describes procedures for registering a domain with the
+ Network Information Center (NIC) of Defense Data Network (DDN), and
+ offers guidelines on the establishment and administration of a domain
+ in accordance with the requirements specified in RFC-920. It is
+ intended for use by domain administrators. This memo should be used
+ in conjunction with RFC-920, which is an official policy statement of
+ the Internet Activities Board (IAB) and the Defense Advanced Research
+ Projects Agency (DARPA). Distribution of this memo is unlimited.
+
+BACKGROUND
+
+ Domains are administrative entities that provide decentralized
+ management of host naming and addressing. The domain-naming system
+ is distributed and hierarchical.
+
+ The NIC is designated by the Defense Communications Agency (DCA) to
+ provide registry services for the domain-naming system on the DDN and
+ DARPA portions of the Internet.
+
+ As registrar of top-level and second-level domains, as well as
+ administrator of the root domain name servers on behalf of DARPA and
+ DDN, the NIC is responsible for maintaining the root server zone
+ files and their binary equivalents. In addition, the NIC is
+ responsible for administering the top-level domains of "ARPA," "COM,"
+ "EDU," "ORG," "GOV," and "MIL" on behalf of DCA and DARPA until it
+ becomes feasible for other appropriate organizations to assume those
+ responsibilities.
+
+ It is recommended that the guidelines described in this document be
+ used by domain administrators in the establishment and control of
+ second-level domains.
+
+THE DOMAIN ADMINISTRATOR
+
+ The role of the domain administrator (DA) is that of coordinator,
+ manager, and technician. If his domain is established at the second
+ level or lower in the tree, the DA must register by interacting with
+ the management of the domain directly above his, making certain that
+
+
+
+Stahl [Page 1]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+ his domain satisfies all the requirements of the administration under
+ which his domain would be situated. To find out who has authority
+ over the name space he wishes to join, the DA can ask the NIC
+ Hostmaster. Information on contacts for the top-level and second-
+ level domains can also be found on line in the file NETINFO:DOMAIN-
+ CONTACTS.TXT, which is available from the NIC via anonymous FTP.
+
+ The DA should be technically competent; he should understand the
+ concepts and procedures for operating a domain server, as described
+ in RFC-1034, and make sure that the service provided is reliable and
+ uninterrupted. It is his responsibility or that of his delegate to
+ ensure that the data will be current at all times. As a manager, the
+ DA must be able to handle complaints about service provided by his
+ domain name server. He must be aware of the behavior of the hosts in
+ his domain, and take prompt action on reports of problems, such as
+ protocol violations or other serious misbehavior. The administrator
+ of a domain must be a responsible person who has the authority to
+ either enforce these actions himself or delegate them to someone
+ else.
+
+ Name assignments within a domain are controlled by the DA, who should
+ verify that names are unique within his domain and that they conform
+ to standard naming conventions. He furnishes access to names and
+ name-related information to users both inside and outside his domain.
+ He should work closely with the personnel he has designated as the
+ "technical and zone" contacts for his domain, for many administrative
+ decisions will be made on the basis of input from these people.
+
+THE DOMAIN TECHNICAL AND ZONE CONTACT
+
+ A zone consists of those contiguous parts of the domain tree for
+ which a domain server has complete information and over which it has
+ authority. A domain server may be authoritative for more than one
+ zone. The domain technical/zone contact is the person who tends to
+ the technical aspects of maintaining the domain's name server and
+ resolver software, and database files. He keeps the name server
+ running, and interacts with technical people in other domains and
+ zones to solve problems that affect his zone.
+
+POLICIES
+
+ Domain or host name choices and the allocation of domain name space
+ are considered to be local matters. In the event of conflicts, it is
+ the policy of the NIC not to get involved in local disputes or in the
+ local decision-making process. The NIC will not act as referee in
+ disputes over such matters as who has the "right" to register a
+ particular top-level or second-level domain for an organization. The
+ NIC considers this a private local matter that must be settled among
+
+
+
+Stahl [Page 2]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+ the parties involved prior to their commencing the registration
+ process with the NIC. Therefore, it is assumed that the responsible
+ person for a domain will have resolved any local conflicts among the
+ members of his domain before registering that domain with the NIC.
+ The NIC will give guidance, if requested, by answering specific
+ technical questions, but will not provide arbitration in disputes at
+ the local level. This policy is also in keeping with the distributed
+ hierarchical nature of the domain-naming system in that it helps to
+ distribute the tasks of solving problems and handling questions.
+
+ Naming conventions for hosts should follow the rules specified in
+ RFC-952. From a technical standpoint, domain names can be very long.
+ Each segment of a domain name may contain up to 64 characters, but
+ the NIC strongly advises DAs to choose names that are 12 characters
+ or fewer, because behind every domain system there is a human being
+ who must keep track of the names, addresses, contacts, and other data
+ in a database. The longer the name, the more likely the data
+ maintainer is to make a mistake. Users also will appreciate shorter
+ names. Most people agree that short names are easier to remember and
+ type; most domain names registered so far are 12 characters or fewer.
+
+ Domain name assignments are made on a first-come-first-served basis.
+ The NIC has chosen not to register individual hosts directly under
+ the top-level domains it administers. One advantage of the domain
+ naming system is that administration and data maintenance can be
+ delegated down a hierarchical tree. Registration of hosts at the
+ same level in the tree as a second-level domain would dilute the
+ usefulness of this feature. In addition, the administrator of a
+ domain is responsible for the actions of hosts within his domain. We
+ would not want to find ourselves in the awkward position of policing
+ the actions of individual hosts. Rather, the subdomains registered
+ under these top-level domains retain the responsibility for this
+ function.
+
+ Countries that wish to be registered as top-level domains are
+ required to name themselves after the two-letter country code listed
+ in the international standard ISO-3166. In some cases, however, the
+ two-letter ISO country code is identical to a state code used by the
+ U.S. Postal Service. Requests made by countries to use the three-
+ letter form of country code specified in the ISO-3166 standard will
+ be considered in such cases so as to prevent possible conflicts and
+ confusion.
+
+
+
+
+
+
+
+
+
+Stahl [Page 3]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+HOW TO REGISTER
+
+ Obtain a domain questionnaire from the NIC hostmaster, or FTP the
+ file NETINFO:DOMAIN-TEMPLATE.TXT from host SRI-NIC.ARPA.
+
+ Fill out the questionnaire completely. Return it via electronic mail
+ to HOSTMASTER@SRI-NIC.ARPA.
+
+ The APPENDIX to this memo contains the application form for
+ registering a top-level or second-level domain with the NIC. It
+ supersedes the version of the questionnaire found in RFC-920. The
+ application should be submitted by the person administratively
+ responsible for the domain, and must be filled out completely before
+ the NIC will authorize establishment of a top-level or second-level
+ domain. The DA is responsible for keeping his domain's data current
+ with the NIC or with the registration agent with which his domain is
+ registered. For example, the CSNET and UUCP managements act as
+ domain filters, processing domain applications for their own
+ organizations. They pass pertinent information along periodically to
+ the NIC for incorporation into the domain database and root server
+ files. The online file NETINFO:ALTERNATE-DOMAIN-PROCEDURE.TXT
+ outlines this procedure. It is highly recommended that the DA review
+ this information periodically and provide any corrections or
+ additions. Corrections should be submitted via electronic mail.
+
+WHICH DOMAIN NAME?
+
+ The designers of the domain-naming system initiated several general
+ categories of names as top-level domain names, so that each could
+ accommodate a variety of organizations. The current top-level
+ domains registered with the DDN Network Information Center are ARPA,
+ COM, EDU, GOV, MIL, NET, and ORG, plus a number of top-level country
+ domains. To join one of these, a DA needs to be aware of the purpose
+ for which it was intended.
+
+ "ARPA" is a temporary domain. It is by default appended to the
+ names of hosts that have not yet joined a domain. When the system
+ was begun in 1984, the names of all hosts in the Official DoD
+ Internet Host Table maintained by the NIC were changed by adding
+ of the label ".ARPA" in order to accelerate a transition to the
+ domain-naming system. Another reason for the blanket name changes
+ was to force hosts to become accustomed to using the new style
+ names and to modify their network software, if necessary. This
+ was done on a network-wide basis and was directed by DCA in DDN
+ Management Bulletin No. 22. Hosts that fall into this domain will
+ eventually move to other branches of the domain tree.
+
+
+
+
+
+Stahl [Page 4]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+ "COM" is meant to incorporate subdomains of companies and
+ businesses.
+
+ "EDU" was initiated to accommodate subdomains set up by
+ universities and other educational institutions.
+
+ "GOV" exists to act as parent domain for subdomains set up by
+ government agencies.
+
+ "MIL" was initiated to act as parent to subdomains that are
+ developed by military organizations.
+
+ "NET" was introduced as a parent domain for various network-type
+ organizations. Organizations that belong within this top-level
+ domain are generic or network-specific, such as network service
+ centers and consortia. "NET" also encompasses network
+ management-related organizations, such as information centers and
+ operations centers.
+
+ "ORG" exists as a parent to subdomains that do not clearly fall
+ within the other top-level domains. This may include technical-
+ support groups, professional societies, or similar organizations.
+
+ One of the guidelines in effect in the domain-naming system is that a
+ host should have only one name regardless of what networks it is
+ connected to. This implies, that, in general, domain names should
+ not include routing information or addresses. For example, a host
+ that has one network connection to the Internet and another to BITNET
+ should use the same name when talking to either network. For a
+ description of the syntax of domain names, please refer to Section 3
+ of RFC-1034.
+
+VERIFICATION OF DATA
+
+ The verification process can be accomplished in several ways. One of
+ these is through the NIC WHOIS server. If he has access to WHOIS,
+ the DA can type the command "whois domain <domain name><return>".
+ The reply from WHOIS will supply the following: the name and address
+ of the organization "owning" the domain; the name of the domain; its
+ administrative, technical, and zone contacts; the host names and
+ network addresses of sites providing name service for the domain.
+
+
+
+
+
+
+
+
+
+
+Stahl [Page 5]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+ Example:
+
+ @whois domain rice.edu<Return>
+
+ Rice University (RICE-DOM)
+ Advanced Studies and Research
+ Houston, TX 77001
+
+ Domain Name: RICE.EDU
+
+ Administrative Contact:
+ Kennedy, Ken (KK28) Kennedy@LLL-CRG.ARPA (713) 527-4834
+ Technical Contact, Zone Contact:
+ Riffle, Vicky R. (VRR) rif@RICE.EDU
+ (713) 527-8101 ext 3844
+
+ Domain servers:
+
+ RICE.EDU 128.42.5.1
+ PENDRAGON.CS.PURDUE.EDU 128.10.2.5
+
+
+ Alternatively, the DA can send an electronic mail message to
+ SERVICE@SRI-NIC.ARPA. In the subject line of the message header, the
+ DA should type "whois domain <domain name>". The requested
+ information will be returned via electronic mail. This method is
+ convenient for sites that do not have access to the NIC WHOIS
+ service.
+
+ The initial application for domain authorization should be submitted
+ via electronic mail, if possible, to HOSTMASTER@SRI-NIC.ARPA. The
+ questionnaire described in the appendix may be used or a separate
+ application can be FTPed from host SRI-NIC.ARPA. The information
+ provided by the administrator will be reviewed by hostmaster
+ personnel for completeness. There will most likely be a few
+ exchanges of correspondence via electronic mail, the preferred method
+ of communication, prior to authorization of the domain.
+
+HOW TO GET MORE INFORMATION
+
+ An informational table of the top-level domains and their root
+ servers is contained in the file NETINFO:DOMAINS.TXT online at SRI-
+ NIC.ARPA. This table can be obtained by FTPing the file.
+ Alternatively, the information can be acquired by opening a TCP or
+ UDP connection to the NIC Host Name Server, port 101 on SRI-NIC.ARPA,
+ and invoking the command "ALL-DOM".
+
+
+
+
+
+Stahl [Page 6]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+ The following online files, all available by FTP from SRI-NIC.ARPA,
+ contain pertinent domain information:
+
+ - NETINFO:DOMAINS.TXT, a table of all top-level domains and the
+ network addresses of the machines providing domain name
+ service for them. It is updated each time a new top-level
+ domain is approved.
+
+ - NETINFO:DOMAIN-INFO.TXT contains a concise list of all
+ top-level and second-level domain names registered with the
+ NIC and is updated monthly.
+
+ - NETINFO:DOMAIN-CONTACTS.TXT also contains a list of all the
+ top level and second-level domains, but includes the
+ administrative, technical and zone contacts for each as well.
+
+ - NETINFO:DOMAIN-TEMPLATE.TXT contains the questionnaire to be
+ completed before registering a top-level or second-level
+ domain.
+
+ For either general or specific information on the domain system, do
+ one or more of the following:
+
+ 1. Send electronic mail to HOSTMASTER@SRI-NIC.ARPA
+
+ 2. Call the toll-free NIC hotline at (800) 235-3155
+
+ 3. Use FTP to get background RFCs and other files maintained
+ online at the NIC. Some pertinent RFCs are listed below in
+ the REFERENCES section of this memo.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stahl [Page 7]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+REFERENCES
+
+ The references listed here provide important background information
+ on the domain-naming system. Path names of the online files
+ available via anonymous FTP from the SRI-NIC.ARPA host are noted in
+ brackets.
+
+ 1. Defense Communications Agency DDN Defense Communications
+ System, DDN Management Bulletin No. 22, Domain Names
+ Transition, March 1984.
+ [ DDN-NEWS:DDN-MGT-BULLETIN-22.TXT ]
+
+ 2. Defense Communications Agency DDN Defense Communications
+ System, DDN Management Bulletin No. 32, Phase I of the Domain
+ Name Implementation, January 1987.
+ [ DDN-NEWS:DDN-MGT-BULLETIN-32.TXT ]
+
+ 3. Harrenstien, K., M. Stahl, and E. Feinler, "Hostname
+ Server", RFC-953, DDN Network Information Center, SRI
+ International, October 1985. [ RFC:RFC953.TXT ]
+
+ 4. Harrenstien, K., M. Stahl, and E. Feinler, "Official DoD
+ Internet Host Table Specification", RFC-952, DDN Network
+ Information Center, SRI International, October 1985.
+ [ RFC:RFC952.TXT ]
+
+ 5. ISO, "Codes for the Representation of Names of Countries",
+ ISO-3166, International Standards Organization, May 1981.
+ [ Not online ]
+
+ 6. Lazear, W.D., "MILNET Name Domain Transition", RFC-1031,
+ Mitre Corporation, October 1987. [ RFC:RFC1031.TXT ]
+
+ 7. Lottor, M.K., "Domain Administrators Operations Guide",
+ RFC-1033, DDN Network Information Center, SRI International,
+ July 1987. [ RFC:RFC1033.TXT ]
+
+ 8. Mockapetris, P., "Domain Names - Concepts and Facilities",
+ RFC-1034, USC Information Sciences Institute, October 1987.
+ [ RFC:RFC1034.TXT ]
+
+ 9. Mockapetris, P., "Domain Names - Implementation and
+ Specification", RFC-1035, USC Information Sciences Institute,
+ October 1987. [ RFC:RFC1035.TXT ]
+
+ 10. Mockapetris, P., "The Domain Name System", Proceedings of the
+ IFIP 6.5 Working Conference on Computer Message Services,
+ Nottingham, England, May 1984. Also as ISI/RS-84-133, June
+
+
+
+Stahl [Page 8]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+ 1984. [ Not online ]
+
+ 11. Mockapetris, P., J. Postel, and P. Kirton, "Name Server
+ Design for Distributed Systems", Proceedings of the Seventh
+ International Conference on Computer Communication, October
+ 30 to November 3 1984, Sidney, Australia. Also as
+ ISI/RS-84-132, June 1984. [ Not online ]
+
+ 12. Partridge, C., "Mail Routing and the Domain System", RFC-974,
+ CSNET-CIC, BBN Laboratories, January 1986.
+ [ RFC:RFC974.TXT ]
+
+ 13. Postel, J., "The Domain Names Plan and Schedule", RFC-881,
+ USC Information Sciences Institute, November 1983.
+ [ RFC:RFC881.TXT ]
+
+ 14. Reynolds, J., and Postel, J., "Assigned Numbers", RFC-1010
+ USC Information Sciences Institute, May 1986.
+ [ RFC:RFC1010.TXT ]
+
+ 15. Romano, S., and Stahl, M., "Internet Numbers", RFC-1020,
+ SRI, November 1987.
+ [ RFC:RFC1020.TXT ]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stahl [Page 9]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+APPENDIX
+
+ The following questionnaire may be FTPed from SRI-NIC.ARPA as
+ NETINFO:DOMAIN-TEMPLATE.TXT.
+
+ ---------------------------------------------------------------------
+
+ To establish a domain, the following information must be sent to the
+ NIC Domain Registrar (HOSTMASTER@SRI-NIC.ARPA):
+
+ NOTE: The key people must have electronic mailboxes and NIC
+ "handles," unique NIC database identifiers. If you have access to
+ "WHOIS", please check to see if you are registered and if so, make
+ sure the information is current. Include only your handle and any
+ changes (if any) that need to be made in your entry. If you do not
+ have access to "WHOIS", please provide all the information indicated
+ and a NIC handle will be assigned.
+
+ (1) The name of the top-level domain to join.
+
+ For example: COM
+
+ (2) The NIC handle of the administrative head of the organization.
+ Alternately, the person's name, title, mailing address, phone number,
+ organization, and network mailbox. This is the contact point for
+ administrative and policy questions about the domain. In the case of
+ a research project, this should be the principal investigator.
+
+ For example:
+
+ Administrator
+
+ Organization The NetWorthy Corporation
+ Name Penelope Q. Sassafrass
+ Title President
+ Mail Address The NetWorthy Corporation
+ 4676 Andrews Way, Suite 100
+ Santa Clara, CA 94302-1212
+ Phone Number (415) 123-4567
+ Net Mailbox Sassafrass@ECHO.TNC.COM
+ NIC Handle PQS
+
+ (3) The NIC handle of the technical contact for the domain.
+ Alternately, the person's name, title, mailing address, phone number,
+ organization, and network mailbox. This is the contact point for
+ problems concerning the domain or zone, as well as for updating
+ information about the domain or zone.
+
+
+
+
+Stahl [Page 10]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+ For example:
+
+ Technical and Zone Contact
+
+ Organization The NetWorthy Corporation
+ Name Ansel A. Aardvark
+ Title Executive Director
+ Mail Address The NetWorthy Corporation
+ 4676 Andrews Way, Suite 100
+ Santa Clara, CA. 94302-1212
+ Phone Number (415) 123-6789
+ Net Mailbox Aardvark@ECHO.TNC.COM
+ NIC Handle AAA2
+
+ (4) The name of the domain (up to 12 characters). This is the name
+ that will be used in tables and lists associating the domain with the
+ domain server addresses. [While, from a technical standpoint, domain
+ names can be quite long (programmers beware), shorter names are
+ easier for people to cope with.]
+
+ For example: TNC
+
+ (5) A description of the servers that provide the domain service for
+ translating names to addresses for hosts in this domain, and the date
+ they will be operational.
+
+ A good way to answer this question is to say "Our server is
+ supplied by person or company X and does whatever their standard
+ issue server does."
+
+ For example: Our server is a copy of the one operated by
+ the NIC; it will be installed and made operational on
+ 1 November 1987.
+
+ (6) Domains must provide at least two independent servers for the
+ domain. Establishing the servers in physically separate locations
+ and on different PSNs is strongly recommended. A description of the
+ server machine and its backup, including
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stahl [Page 11]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+ (a) Hardware and software (using keywords from the Assigned
+ Numbers RFC).
+
+ (b) Host domain name and network addresses (which host on which
+ network for each connected network).
+
+ (c) Any domain-style nicknames (please limit your domain-style
+ nickname request to one)
+
+ For example:
+
+ - Hardware and software
+
+ VAX-11/750 and UNIX, or
+ IBM-PC and MS-DOS, or
+ DEC-1090 and TOPS-20
+
+ - Host domain names and network addresses
+
+ BAR.FOO.COM 10.9.0.193 on ARPANET
+
+ - Domain-style nickname
+
+ BR.FOO.COM (same as BAR.FOO.COM 10.9.0.13 on ARPANET)
+
+ (7) Planned mapping of names of any other network hosts, other than
+ the server machines, into the new domain's naming space.
+
+ For example:
+
+ BAR-FOO2.ARPA (10.8.0.193) -> FOO2.BAR.COM
+ BAR-FOO3.ARPA (10.7.0.193) -> FOO3.BAR.COM
+ BAR-FOO4.ARPA (10.6.0.193) -> FOO4.BAR.COM
+
+
+ (8) An estimate of the number of hosts that will be in the domain.
+
+ (a) Initially
+ (b) Within one year
+ (c) Two years
+ (d) Five years.
+
+ For example:
+
+ (a) Initially = 50
+ (b) One year = 100
+ (c) Two years = 200
+ (d) Five years = 500
+
+
+
+Stahl [Page 12]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+ (9) The date you expect the fully qualified domain name to become
+ the official host name in HOSTS.TXT.
+
+ Please note: If changing to a fully qualified domain name (e.g.,
+ FOO.BAR.COM) causes a change in the official host name of an
+ ARPANET or MILNET host, DCA approval must be obtained beforehand.
+ Allow 10 working days for your requested changes to be processed.
+
+ ARPANET sites should contact ARPANETMGR@DDN1.ARPA. MILNET sites
+ should contact HOSTMASTER@SRI-NIC.ARPA, 800-235-3155, for
+ further instructions.
+
+ (10) Please describe your organization briefly.
+
+ For example: The NetWorthy Corporation is a consulting
+ organization of people working with UNIX and the C language in an
+ electronic networking environment. It sponsors two technical
+ conferences annually and distributes a bimonthly newsletter.
+
+ ---------------------------------------------------------------------
+
+ This example of a completed application corresponds to the examples
+ found in the companion document RFC-1033, "Domain Administrators
+ Operations Guide."
+
+ (1) The name of the top-level domain to join.
+
+ COM
+
+ (2) The NIC handle of the administrative contact person.
+
+ NIC Handle JAKE
+
+ (3) The NIC handle of the domain's technical and zone
+ contact person.
+
+ NIC Handle DLE6
+
+ (4) The name of the domain.
+
+ SRI
+
+ (5) A description of the servers.
+
+ Our server is the TOPS20 server JEEVES supplied by ISI; it
+ will be installed and made operational on 1 July 1987.
+
+
+
+
+
+Stahl [Page 13]
+
+RFC 1032 DOMAIN ADMINISTRATORS GUIDE November 1987
+
+
+ (6) A description of the server machine and its backup:
+
+ (a) Hardware and software
+
+ DEC-1090T and TOPS20
+ DEC-2065 and TOPS20
+
+ (b) Host domain name and network address
+
+ KL.SRI.COM 10.1.0.2 on ARPANET, 128.18.10.6 on SRINET
+ STRIPE.SRI.COM 10.4.0.2 on ARPANET, 128.18.10.4 on SRINET
+
+ (c) Domain-style nickname
+
+ None
+
+ (7) Planned mapping of names of any other network hosts, other than
+ the server machines, into the new domain's naming space.
+
+ SRI-Blackjack.ARPA (128.18.2.1) -> Blackjack.SRI.COM
+ SRI-CSL.ARPA (192.12.33.2) -> CSL.SRI.COM
+
+ (8) An estimate of the number of hosts that will be directly within
+ this domain.
+
+ (a) Initially = 50
+ (b) One year = 100
+ (c) Two years = 200
+ (d) Five years = 500
+
+ (9) A date when you expect the fully qualified domain name to become
+ the official host name in HOSTS.TXT.
+
+ 31 September 1987
+
+ (10) Brief description of organization.
+
+ SRI International is an independent, nonprofit, scientific
+ research organization. It performs basic and applied research
+ for government and commercial clients, and contributes to
+ worldwide economic, scientific, industrial, and social progress
+ through research and related services.
+
+
+
+
+
+
+
+
+
+Stahl [Page 14]
+
diff --git a/doc/rfc/rfc1033.txt b/doc/rfc/rfc1033.txt
new file mode 100644
index 0000000..37029fd
--- /dev/null
+++ b/doc/rfc/rfc1033.txt
@@ -0,0 +1,1229 @@
+Network Working Group M. Lottor
+Request For Comments: 1033 SRI International
+ November 1987
+
+
+ DOMAIN ADMINISTRATORS OPERATIONS GUIDE
+
+
+
+STATUS OF THIS MEMO
+
+ This RFC provides guidelines for domain administrators in operating a
+ domain server and maintaining their portion of the hierarchical
+ database. Familiarity with the domain system is assumed.
+ Distribution of this memo is unlimited.
+
+ACKNOWLEDGMENTS
+
+ This memo is a formatted collection of notes and excerpts from the
+ references listed at the end of this document. Of particular mention
+ are Paul Mockapetris and Kevin Dunlap.
+
+INTRODUCTION
+
+ A domain server requires a few files to get started. It will
+ normally have some number of boot/startup files (also known as the
+ "safety belt" files). One section will contain a list of possible
+ root servers that the server will use to find the up-to-date list of
+ root servers. Another section will list the zone files to be loaded
+ into the server for your local domain information. A zone file
+ typically contains all the data for a particular domain. This guide
+ describes the data formats that can be used in zone files and
+ suggested parameters to use for certain fields. If you are
+ attempting to do anything advanced or tricky, consult the appropriate
+ domain RFC's for more details.
+
+ Note: Each implementation of domain software may require different
+ files. Zone files are standardized but some servers may require
+ other startup files. See the appropriate documentation that comes
+ with your software. See the appendix for some specific examples.
+
+ZONES
+
+ A zone defines the contents of a contiguous section of the domain
+ space, usually bounded by administrative boundaries. There will
+ typically be a separate data file for each zone. The data contained
+ in a zone file is composed of entries called Resource Records (RRs).
+
+
+
+
+Lottor [Page 1]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ You may only put data in your domain server that you are
+ authoritative for. You must not add entries for domains other than
+ your own (except for the special case of "glue records").
+
+ A domain server will probably read a file on start-up that lists the
+ zones it should load into its database. The format of this file is
+ not standardized and is different for most domain server
+ implementations. For each zone it will normally contain the domain
+ name of the zone and the file name that contains the data to load for
+ the zone.
+
+ROOT SERVERS
+
+ A resolver will need to find the root servers when it first starts.
+ When the resolver boots, it will typically read a list of possible
+ root servers from a file.
+
+ The resolver will cycle through the list trying to contact each one.
+ When it finds a root server, it will ask it for the current list of
+ root servers. It will then discard the list of root servers it read
+ from the data file and replace it with the current list it received.
+
+ Root servers will not change very often. You can get the names of
+ current root servers from the NIC.
+
+ FTP the file NETINFO:ROOT-SERVERS.TXT or send a mail request to
+ NIC@SRI-NIC.ARPA.
+
+ As of this date (June 1987) they are:
+
+ SRI-NIC.ARPA 10.0.0.51 26.0.0.73
+ C.ISI.EDU 10.0.0.52
+ BRL-AOS.ARPA 192.5.25.82 192.5.22.82 128.20.1.2
+ A.ISI.EDU 26.3.0.103
+
+RESOURCE RECORDS
+
+ Records in the zone data files are called resource records (RRs).
+ They are specified in RFC-883 and RFC-973. An RR has a standard
+ format as shown:
+
+ <name> [<ttl>] [<class>] <type> <data>
+
+ The record is divided into fields which are separated by white space.
+
+ <name>
+
+ The name field defines what domain name applies to the given
+
+
+
+Lottor [Page 2]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ RR. In some cases the name field can be left blank and it will
+ default to the name field of the previous RR.
+
+ <ttl>
+
+ TTL stands for Time To Live. It specifies how long a domain
+ resolver should cache the RR before it throws it out and asks a
+ domain server again. See the section on TTL's. If you leave
+ the TTL field blank it will default to the minimum time
+ specified in the SOA record (described later).
+
+ <class>
+
+ The class field specifies the protocol group. If left blank it
+ will default to the last class specified.
+
+ <type>
+
+ The type field specifies what type of data is in the RR. See
+ the section on types.
+
+ <data>
+
+ The data field is defined differently for each type and class
+ of data. Popular RR data formats are described later.
+
+ The domain system does not guarantee to preserve the order of
+ resource records. Listing RRs (such as multiple address records) in
+ a certain order does not guarantee they will be used in that order.
+
+ Case is preserved in names and data fields when loaded into the name
+ server. All comparisons and lookups in the name server are case
+ insensitive.
+
+ Parenthesis ("(",")") are used to group data that crosses a line
+ boundary.
+
+ A semicolon (";") starts a comment; the remainder of the line is
+ ignored.
+
+ The asterisk ("*") is used for wildcarding.
+
+ The at-sign ("@") denotes the current default domain name.
+
+
+
+
+
+
+
+
+Lottor [Page 3]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+NAMES
+
+ A domain name is a sequence of labels separated by dots.
+
+ Domain names in the zone files can be one of two types, either
+ absolute or relative. An absolute name is the fully qualified domain
+ name and is terminated with a period. A relative name does not
+ terminate with a period, and the current default domain is appended
+ to it. The default domain is usually the name of the domain that was
+ specified in the boot file that loads each zone.
+
+ The domain system allows a label to contain any 8-bit character.
+ Although the domain system has no restrictions, other protocols such
+ as SMTP do have name restrictions. Because of other protocol
+ restrictions, only the following characters are recommended for use
+ in a host name (besides the dot separator):
+
+ "A-Z", "a-z", "0-9", dash and underscore
+
+TTL's (Time To Live)
+
+ It is important that TTLs are set to appropriate values. The TTL is
+ the time (in seconds) that a resolver will use the data it got from
+ your server before it asks your server again. If you set the value
+ too low, your server will get loaded down with lots of repeat
+ requests. If you set it too high, then information you change will
+ not get distributed in a reasonable amount of time. If you leave the
+ TTL field blank, it will default to what is specified in the SOA
+ record for the zone.
+
+ Most host information does not change much over long time periods. A
+ good way to set up your TTLs would be to set them at a high value,
+ and then lower the value if you know a change will be coming soon.
+ You might set most TTLs to anywhere between a day (86400) and a week
+ (604800). Then, if you know some data will be changing in the near
+ future, set the TTL for that RR down to a lower value (an hour to a
+ day) until the change takes place, and then put it back up to its
+ previous value.
+
+ Also, all RRs with the same name, class, and type should have the
+ same TTL value.
+
+CLASSES
+
+ The domain system was designed to be protocol independent. The class
+ field is used to identify the protocol group that each RR is in.
+
+ The class of interest to people using TCP/IP software is the class
+
+
+
+Lottor [Page 4]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ "Internet". Its standard designation is "IN".
+
+ A zone file should only contain RRs of the same class.
+
+TYPES
+
+ There are many defined RR types. For a complete list, see the domain
+ specification RFCs. Here is a list of current commonly used types.
+ The data for each type is described in the data section.
+
+ Designation Description
+ ==========================================
+ SOA Start Of Authority
+ NS Name Server
+
+ A Internet Address
+ CNAME Canonical Name (nickname pointer)
+ HINFO Host Information
+ WKS Well Known Services
+
+ MX Mail Exchanger
+
+ PTR Pointer
+
+SOA (Start Of Authority)
+
+ <name> [<ttl>] [<class>] SOA <origin> <person> (
+ <serial>
+ <refresh>
+ <retry>
+ <expire>
+ <minimum> )
+
+ The Start Of Authority record designates the start of a zone. The
+ zone ends at the next SOA record.
+
+ <name> is the name of the zone.
+
+ <origin> is the name of the host on which the master zone file
+ resides.
+
+ <person> is a mailbox for the person responsible for the zone. It is
+ formatted like a mailing address but the at-sign that normally
+ separates the user from the host name is replaced with a dot.
+
+ <serial> is the version number of the zone file. It should be
+ incremented anytime a change is made to data in the zone.
+
+
+
+
+Lottor [Page 5]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ <refresh> is how long, in seconds, a secondary name server is to
+ check with the primary name server to see if an update is needed. A
+ good value here would be one hour (3600).
+
+ <retry> is how long, in seconds, a secondary name server is to retry
+ after a failure to check for a refresh. A good value here would be
+ 10 minutes (600).
+
+ <expire> is the upper limit, in seconds, that a secondary name server
+ is to use the data before it expires for lack of getting a refresh.
+ You want this to be rather large, and a nice value is 3600000, about
+ 42 days.
+
+ <minimum> is the minimum number of seconds to be used for TTL values
+ in RRs. A minimum of at least a day is a good value here (86400).
+
+ There should only be one SOA record per zone. A sample SOA record
+ would look something like:
+
+ @ IN SOA SRI-NIC.ARPA. HOSTMASTER.SRI-NIC.ARPA. (
+ 45 ;serial
+ 3600 ;refresh
+ 600 ;retry
+ 3600000 ;expire
+ 86400 ) ;minimum
+
+
+NS (Name Server)
+
+ <domain> [<ttl>] [<class>] NS <server>
+
+ The NS record lists the name of a machine that provides domain
+ service for a particular domain. The name associated with the RR is
+ the domain name and the data portion is the name of a host that
+ provides the service. If machines SRI-NIC.ARPA and C.ISI.EDU provide
+ name lookup service for the domain COM then the following entries
+ would be used:
+
+ COM. NS SRI-NIC.ARPA.
+ NS C.ISI.EDU.
+
+ Note that the machines providing name service do not have to live in
+ the named domain. There should be one NS record for each server for
+ a domain. Also note that the name "COM" defaults for the second NS
+ record.
+
+ NS records for a domain exist in both the zone that delegates the
+ domain, and in the domain itself.
+
+
+
+Lottor [Page 6]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+GLUE RECORDS
+
+ If the name server host for a particular domain is itself inside the
+ domain, then a 'glue' record will be needed. A glue record is an A
+ (address) RR that specifies the address of the server. Glue records
+ are only needed in the server delegating the domain, not in the
+ domain itself. If for example the name server for domain SRI.COM was
+ KL.SRI.COM, then the NS record would look like this, but you will
+ also need to have the following A record.
+
+ SRI.COM. NS KL.SRI.COM.
+ KL.SRI.COM. A 10.1.0.2
+
+
+A (Address)
+
+ <host> [<ttl>] [<class>] A <address>
+
+ The data for an A record is an internet address in dotted decimal
+ form. A sample A record might look like:
+
+ SRI-NIC.ARPA. A 10.0.0.51
+
+ There should be one A record for each address of a host.
+
+CNAME ( Canonical Name)
+
+ <nickname> [<ttl>] [<class>] CNAME <host>
+
+ The CNAME record is used for nicknames. The name associated with the
+ RR is the nickname. The data portion is the official name. For
+ example, a machine named SRI-NIC.ARPA may want to have the nickname
+ NIC.ARPA. In that case, the following RR would be used:
+
+ NIC.ARPA. CNAME SRI-NIC.ARPA.
+
+ There must not be any other RRs associated with a nickname of the
+ same class.
+
+ Nicknames are also useful when a host changes it's name. In that
+ case, it is usually a good idea to have a CNAME pointer so that
+ people still using the old name will get to the right place.
+
+
+
+
+
+
+
+
+
+Lottor [Page 7]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+HINFO (Host Info)
+
+ <host> [<ttl>] [<class>] HINFO <hardware> <software>
+
+ The HINFO record gives information about a particular host. The data
+ is two strings separated by whitespace. The first string is a
+ hardware description and the second is software. The hardware is
+ usually a manufacturer name followed by a dash and model designation.
+ The software string is usually the name of the operating system.
+
+ Official HINFO types can be found in the latest Assigned Numbers RFC,
+ the latest of which is RFC-1010. The Hardware type is called the
+ Machine name and the Software type is called the System name.
+
+ Some sample HINFO records:
+
+ SRI-NIC.ARPA. HINFO DEC-2060 TOPS20
+ UCBARPA.Berkeley.EDU. HINFO VAX-11/780 UNIX
+
+
+WKS (Well Known Services)
+
+ <host> [<ttl>] [<class>] WKS <address> <protocol> <services>
+
+ The WKS record is used to list Well Known Services a host provides.
+ WKS's are defined to be services on port numbers below 256. The WKS
+ record lists what services are available at a certain address using a
+ certain protocol. The common protocols are TCP or UDP. A sample WKS
+ record for a host offering the same services on all address would
+ look like:
+
+ Official protocol names can be found in the latest Assigned Numbers
+ RFC, the latest of which is RFC-1010.
+
+ SRI-NIC.ARPA. WKS 10.0.0.51 TCP TELNET FTP SMTP
+ WKS 10.0.0.51 UDP TIME
+ WKS 26.0.0.73 TCP TELNET FTP SMTP
+ WKS 26.0.0.73 UDP TIME
+
+MX (Mail Exchanger) (See RFC-974 for more details.)
+
+ <name> [<ttl>] [<class>] MX <preference> <host>
+
+ MX records specify where mail for a domain name should be delivered.
+ There may be multiple MX records for a particular name. The
+ preference value specifies the order a mailer should try multiple MX
+ records when delivering mail. Zero is the highest preference.
+ Multiple records for the same name may have the same preference.
+
+
+
+Lottor [Page 8]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ A host BAR.FOO.COM may want its mail to be delivered to the host
+ PO.FOO.COM and would then use the MX record:
+
+ BAR.FOO.COM. MX 10 PO.FOO.COM.
+
+ A host BAZ.FOO.COM may want its mail to be delivered to one of three
+ different machines, in the following order:
+
+ BAZ.FOO.COM. MX 10 PO1.FOO.COM.
+ MX 20 PO2.FOO.COM.
+ MX 30 PO3.FOO.COM.
+
+ An entire domain of hosts not connected to the Internet may want
+ their mail to go through a mail gateway that knows how to deliver
+ mail to them. If they would like mail addressed to any host in the
+ domain FOO.COM to go through the mail gateway they might use:
+
+ FOO.COM. MX 10 RELAY.CS.NET.
+ *.FOO.COM. MX 20 RELAY.CS.NET.
+
+ Note that you can specify a wildcard in the MX record to match on
+ anything in FOO.COM, but that it won't match a plain FOO.COM.
+
+IN-ADDR.ARPA
+
+ The structure of names in the domain system is set up in a
+ hierarchical way such that the address of a name can be found by
+ tracing down the domain tree contacting a server for each label of
+ the name. Because of this 'indexing' based on name, there is no easy
+ way to translate a host address back into its host name.
+
+ In order to do the reverse translation easily, a domain was created
+ that uses hosts' addresses as part of a name that then points to the
+ data for that host. In this way, there is now an 'index' to hosts'
+ RRs based on their address. This address mapping domain is called
+ IN-ADDR.ARPA. Within that domain are subdomains for each network,
+ based on network number. Also, for consistency and natural
+ groupings, the 4 octets of a host number are reversed.
+
+ For example, the ARPANET is net 10. That means there is a domain
+ called 10.IN-ADDR.ARPA. Within this domain there is a PTR RR at
+ 51.0.0.10.IN-ADDR that points to the RRs for the host SRI-NIC.ARPA
+ (who's address is 10.0.0.51). Since the NIC is also on the MILNET
+ (Net 26, address 26.0.0.73), there is also a PTR RR at 73.0.0.26.IN-
+ ADDR.ARPA that points to the same RR's for SRI-NIC.ARPA. The format
+ of these special pointers is defined below along with the examples
+ for the NIC.
+
+
+
+
+Lottor [Page 9]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+PTR
+
+ <special-name> [<ttl>] [<class>] PTR <name>
+
+ The PTR record is used to let special names point to some other
+ location in the domain tree. They are mainly used in the IN-
+ ADDR.ARPA records for translation of addresses to names. PTR's
+ should use official names and not aliases.
+
+ For example, host SRI-NIC.ARPA with addresses 10.0.0.51 and 26.0.0.73
+ would have the following records in the respective zone files for net
+ 10 and net 26:
+
+ 51.0.0.10.IN-ADDR.ARPA. PTR SRI-NIC.ARPA.
+ 73.0.0.26.IN-ADDR.ARPA. PTR SRI-NIC.ARPA.
+
+GATEWAY PTR's
+
+ The IN-ADDR tree is also used to locate gateways on a particular
+ network. Gateways have the same kind of PTR RRs as hosts (as above)
+ but in addition they have other PTRs used to locate them by network
+ number alone. These records have only 1, 2, or 3 octets as part of
+ the name depending on whether they are class A, B, or C networks,
+ respectively.
+
+ Lets take the SRI-CSL gateway for example. It connects 3 different
+ networks, one class A, one class B and one class C. It will have the
+ standard RR's for a host in the CSL.SRI.COM zone:
+
+ GW.CSL.SRI.COM. A 10.2.0.2
+ A 128.18.1.1
+ A 192.12.33.2
+
+ Also, in 3 different zones (one for each network), it will have one
+ of the following number to name translation pointers:
+
+ 2.0.2.10.IN-ADDR.ARPA. PTR GW.CSL.SRI.COM.
+ 1.1.18.128.IN-ADDR.ARPA. PTR GW.CSL.SRI.COM.
+ 1.33.12.192.IN-ADDR.ARPA. PTR GW.CSL.SRI.COM.
+
+ In addition, in each of the same 3 zones will be one of the following
+ gateway location pointers:
+
+ 10.IN-ADDR.ARPA. PTR GW.CSL.SRI.COM.
+ 18.128.IN-ADDR.ARPA. PTR GW.CSL.SRI.COM.
+ 33.12.192.IN-ADDR.ARPA. PTR GW.CSL.SRI.COM.
+
+
+
+
+
+Lottor [Page 10]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+INSTRUCTIONS
+
+ Adding a subdomain.
+
+ To add a new subdomain to your domain:
+
+ Setup the other domain server and/or the new zone file.
+
+ Add an NS record for each server of the new domain to the zone
+ file of the parent domain.
+
+ Add any necessary glue RRs.
+
+ Adding a host.
+
+ To add a new host to your zone files:
+
+ Edit the appropriate zone file for the domain the host is in.
+
+ Add an entry for each address of the host.
+
+ Optionally add CNAME, HINFO, WKS, and MX records.
+
+ Add the reverse IN-ADDR entry for each host address in the
+ appropriate zone files for each network the host in on.
+
+ Deleting a host.
+
+ To delete a host from the zone files:
+
+ Remove all the hosts' resource records from the zone file of
+ the domain the host is in.
+
+ Remove all the hosts' PTR records from the IN-ADDR zone files
+ for each network the host was on.
+
+ Adding gateways.
+
+ Follow instructions for adding a host.
+
+ Add the gateway location PTR records for each network the
+ gateway is on.
+
+ Deleting gateways.
+
+ Follow instructions for deleting a host.
+
+ Also delete the gateway location PTR records for each network
+
+
+
+Lottor [Page 11]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ the gateway was on.
+
+COMPLAINTS
+
+ These are the suggested steps you should take if you are having
+ problems that you believe are caused by someone else's name server:
+
+
+ 1. Complain privately to the responsible person for the domain. You
+ can find their mailing address in the SOA record for the domain.
+
+ 2. Complain publicly to the responsible person for the domain.
+
+ 3. Ask the NIC for the administrative person responsible for the
+ domain. Complain. You can also find domain contacts on the NIC in
+ the file NETINFO:DOMAIN-CONTACTS.TXT
+
+ 4. Complain to the parent domain authorities.
+
+ 5. Ask the parent authorities to excommunicate the domain.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 12]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+EXAMPLE DOMAIN SERVER DATABASE FILES
+
+ The following examples show how zone files are set up for a typical
+ organization. SRI will be used as the example organization. SRI has
+ decided to divided their domain SRI.COM into a few subdomains, one
+ for each group that wants one. The subdomains are CSL and ISTC.
+
+ Note the following interesting items:
+
+ There are both hosts and domains under SRI.COM.
+
+ CSL.SRI.COM is both a domain name and a host name.
+
+ All the domains are serviced by the same pair of domain servers.
+
+ All hosts at SRI are on net 128.18 except hosts in the CSL domain
+ which are on net 192.12.33. Note that a domain does not have to
+ correspond to a physical network.
+
+ The examples do not necessarily correspond to actual data in use
+ by the SRI domain.
+
+ SRI Domain Organization
+
+ +-------+
+ | COM |
+ +-------+
+ |
+ +-------+
+ | SRI |
+ +-------+
+ |
+ +----------++-----------+
+ | | |
+ +-------+ +------+ +-------+
+ | CSL | | ISTC | | Hosts |
+ +-------+ +------+ +-------+
+ | |
+ +-------+ +-------+
+ | Hosts | | Hosts |
+ +-------+ +-------+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 13]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ [File "CONFIG.CMD". Since bootstrap files are not standardized, this
+ file is presented using a pseudo configuration file syntax.]
+
+ load root server list from file ROOT.SERVERS
+ load zone SRI.COM. from file SRI.ZONE
+ load zone CSL.SRI.COM. from file CSL.ZONE
+ load zone ISTC.SRI.COM. from file ISTC.ZONE
+ load zone 18.128.IN-ADDR.ARPA. from file SRINET.ZONE
+ load zone 33.12.192.IN-ADDR.ARPA. from file SRI-CSL-NET.ZONE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 14]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ [File "ROOT.SERVERS". Again, the format of this file is not
+ standardized.]
+
+ ;list of possible root servers
+ SRI-NIC.ARPA 10.0.0.51 26.0.0.73
+ C.ISI.EDU 10.0.0.52
+ BRL-AOS.ARPA 192.5.25.82 192.5.22.82 128.20.1.2
+ A.ISI.EDU 26.3.0.103
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 15]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ [File "SRI.ZONE"]
+
+ SRI.COM. IN SOA KL.SRI.COM. DLE.STRIPE.SRI.COM. (
+ 870407 ;serial
+ 1800 ;refresh every 30 minutes
+ 600 ;retry every 10 minutes
+ 604800 ;expire after a week
+ 86400 ;default of an hour
+ )
+
+ SRI.COM. NS KL.SRI.COM.
+ NS STRIPE.SRI.COM.
+ MX 10 KL.SRI.COM.
+
+ ;SRI.COM hosts
+
+ KL A 10.1.0.2
+ A 128.18.10.6
+ MX 10 KL.SRI.COM.
+
+ STRIPE A 10.4.0.2
+ STRIPE A 128.18.10.4
+ MX 10 STRIPE.SRI.COM.
+
+ NIC CNAME SRI-NIC.ARPA.
+
+ Blackjack A 128.18.2.1
+ HINFO VAX-11/780 UNIX
+ WKS 128.18.2.1 TCP TELNET FTP
+
+ CSL A 192.12.33.2
+ HINFO FOONLY-F4 TOPS20
+ WKS 192.12.33.2 TCP TELNET FTP SMTP FINGER
+ MX 10 CSL.SRI.COM.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 16]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ [File "CSL.ZONE"]
+
+ CSL.SRI.COM. IN SOA KL.SRI.COM. DLE.STRIPE.SRI.COM. (
+ 870330 ;serial
+ 1800 ;refresh every 30 minutes
+ 600 ;retry every 10 minutes
+ 604800 ;expire after a week
+ 86400 ;default of a day
+ )
+
+ CSL.SRI.COM. NS KL.SRI.COM.
+ NS STRIPE.SRI.COM.
+ A 192.12.33.2
+
+ ;CSL.SRI.COM hosts
+
+ A CNAME CSL.SRI.COM.
+ B A 192.12.33.3
+ HINFO FOONLY-F4 TOPS20
+ WKS 192.12.33.3 TCP TELNET FTP SMTP
+ GW A 10.2.0.2
+ A 192.12.33.1
+ A 128.18.1.1
+ HINFO PDP-11/23 MOS
+ SMELLY A 192.12.33.4
+ HINFO IMAGEN IMAGEN
+ SQUIRREL A 192.12.33.5
+ HINFO XEROX-1100 INTERLISP
+ VENUS A 192.12.33.7
+ HINFO SYMBOLICS-3600 LISPM
+ HELIUM A 192.12.33.30
+ HINFO SUN-3/160 UNIX
+ ARGON A 192.12.33.31
+ HINFO SUN-3/75 UNIX
+ RADON A 192.12.33.32
+ HINFO SUN-3/75 UNIX
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 17]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ [File "ISTC.ZONE"]
+
+ ISTC.SRI.COM. IN SOA KL.SRI.COM. roemers.JOYCE.ISTC.SRI.COM. (
+ 870406 ;serial
+ 1800 ;refresh every 30 minutes
+ 600 ;retry every 10 minutes
+ 604800 ;expire after a week
+ 86400 ;default of a day
+ )
+
+ ISTC.SRI.COM. NS KL.SRI.COM.
+ NS STRIPE.SRI.COM.
+ MX 10 SPAM.ISTC.SRI.COM.
+
+ ; ISTC hosts
+
+ joyce A 128.18.4.2
+ HINFO VAX-11/750 UNIX
+ bozo A 128.18.0.6
+ HINFO SUN UNIX
+ sundae A 128.18.0.11
+ HINFO SUN UNIX
+ tsca A 128.18.0.201
+ A 10.3.0.2
+ HINFO VAX-11/750 UNIX
+ MX 10 TSCA.ISTC.SRI.COM.
+ tsc CNAME tsca
+ prmh A 128.18.0.203
+ A 10.2.0.51
+ HINFO PDP-11/44 UNIX
+ spam A 128.18.4.3
+ A 10.2.0.107
+ HINFO VAX-11/780 UNIX
+ MX 10 SPAM.ISTC.SRI.COM.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 18]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ [File "SRINET.ZONE"]
+
+ 18.128.IN-ADDR.ARPA. IN SOA KL.SRI.COM DLE.STRIPE.SRI.COM. (
+ 870406 ;serial
+ 1800 ;refresh every 30 minutes
+ 600 ;retry every 10 minutes
+ 604800 ;expire after a week
+ 86400 ;default of a day
+ )
+
+ 18.128.IN-ADDR.ARPA. NS KL.SRI.COM.
+ NS STRIPE.SRI.COM.
+ PTR GW.CSL.SRI.COM.
+
+ ; SRINET [128.18.0.0] Address Translations
+
+ ; SRI.COM Hosts
+ 1.2.18.128.IN-ADDR.ARPA. PTR Blackjack.SRI.COM.
+
+ ; ISTC.SRI.COM Hosts
+ 2.4.18.128.IN-ADDR.ARPA. PTR joyce.ISTC.SRI.COM.
+ 6.0.18.128.IN-ADDR.ARPA. PTR bozo.ISTC.SRI.COM.
+ 11.0.18.128.IN-ADDR.ARPA. PTR sundae.ISTC.SRI.COM.
+ 201.0.18.128.IN-ADDR.ARPA. PTR tsca.ISTC.SRI.COM.
+ 203.0.18.128.IN-ADDR.ARPA. PTR prmh.ISTC.SRI.COM.
+ 3.4.18.128.IN-ADDR.ARPA. PTR spam.ISTC.SRI.COM.
+
+ ; CSL.SRI.COM Hosts
+ 1.1.18.128.IN-ADDR.ARPA. PTR GW.CSL.SRI.COM.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 19]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+ [File "SRI-CSL-NET.ZONE"]
+
+ 33.12.192.IN-ADDR.ARPA. IN SOA KL.SRI.COM DLE.STRIPE.SRI.COM. (
+ 870404 ;serial
+ 1800 ;refresh every 30 minutes
+ 600 ;retry every 10 minutes
+ 604800 ;expire after a week
+ 86400 ;default of a day
+ )
+
+ 33.12.192.IN-ADDR.ARPA. NS KL.SRI.COM.
+ NS STRIPE.SRI.COM.
+ PTR GW.CSL.SRI.COM.
+
+ ; SRI-CSL-NET [192.12.33.0] Address Translations
+
+ ; SRI.COM Hosts
+ 2.33.12.192.IN-ADDR.ARPA. PTR CSL.SRI.COM.
+
+ ; CSL.SRI.COM Hosts
+ 1.33.12.192.IN-ADDR.ARPA. PTR GW.CSL.SRI.COM.
+ 3.33.12.192.IN-ADDR.ARPA. PTR B.CSL.SRI.COM.
+ 4.33.12.192.IN-ADDR.ARPA. PTR SMELLY.CSL.SRI.COM.
+ 5.33.12.192.IN-ADDR.ARPA. PTR SQUIRREL.CSL.SRI.COM.
+ 7.33.12.192.IN-ADDR.ARPA. PTR VENUS.CSL.SRI.COM.
+ 30.33.12.192.IN-ADDR.ARPA. PTR HELIUM.CSL.SRI.COM.
+ 31.33.12.192.IN-ADDR.ARPA. PTR ARGON.CSL.SRI.COM.
+ 32.33.12.192.IN-ADDR.ARPA. PTR RADON.CSL.SRI.COM.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 20]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+APPENDIX
+
+ BIND (Berkeley Internet Name Domain server) distributed with 4.3 BSD
+ UNIX
+
+ This section describes two BIND implementation specific files; the
+ boot file and the cache file. BIND has other options, files, and
+ specifications that are not described here. See the Name Server
+ Operations Guide for BIND for details.
+
+ The boot file for BIND is usually called "named.boot". This
+ corresponds to file "CONFIG.CMD" in the example section.
+
+ --------------------------------------------------------
+ cache . named.ca
+ primary SRI.COM SRI.ZONE
+ primary CSL.SRI.COM CSL.ZONE
+ primary ISTC.SRI.COM ISTC.ZONE
+ primary 18.128.IN-ADDR.ARPA SRINET.ZONE
+ primary 33.12.192.IN-ADDR.ARPA SRI-CSL-NET.ZONE
+ --------------------------------------------------------
+
+ The cache file for BIND is usually called "named.ca". This
+ corresponds to file "ROOT.SERVERS" in the example section.
+
+ -------------------------------------------------
+ ;list of possible root servers
+ . 1 IN NS SRI-NIC.ARPA.
+ NS C.ISI.EDU.
+ NS BRL-AOS.ARPA.
+ NS C.ISI.EDU.
+ ;and their addresses
+ SRI-NIC.ARPA. A 10.0.0.51
+ A 26.0.0.73
+ C.ISI.EDU. A 10.0.0.52
+ BRL-AOS.ARPA. A 192.5.25.82
+ A 192.5.22.82
+ A 128.20.1.2
+ A.ISI.EDU. A 26.3.0.103
+ -------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 21]
+
+RFC 1033 DOMAIN OPERATIONS GUIDE November 1987
+
+
+REFERENCES
+
+ [1] Dunlap, K., "Name Server Operations Guide for BIND", CSRG,
+ Department of Electrical Engineering and Computer Sciences,
+ University of California, Berkeley, California.
+
+ [2] Partridge, C., "Mail Routing and the Domain System", RFC-974,
+ CSNET CIC BBN Laboratories, January 1986.
+
+ [3] Mockapetris, P., "Domains Names - Concepts and Facilities",
+ RFC-1034, USC/Information Sciences Institute, November 1987.
+
+ [4] Mockapetris, P., "Domain Names - Implementations Specification",
+ RFC-1035, USC/Information Sciences Institute, November 1987.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lottor [Page 22]
+
diff --git a/doc/rfc/rfc1034.txt b/doc/rfc/rfc1034.txt
new file mode 100644
index 0000000..55cdb21
--- /dev/null
+++ b/doc/rfc/rfc1034.txt
@@ -0,0 +1,3077 @@
+Network Working Group P. Mockapetris
+Request for Comments: 1034 ISI
+Obsoletes: RFCs 882, 883, 973 November 1987
+
+
+ DOMAIN NAMES - CONCEPTS AND FACILITIES
+
+
+
+1. STATUS OF THIS MEMO
+
+This RFC is an introduction to the Domain Name System (DNS), and omits
+many details which can be found in a companion RFC, "Domain Names -
+Implementation and Specification" [RFC-1035]. That RFC assumes that the
+reader is familiar with the concepts discussed in this memo.
+
+A subset of DNS functions and data types constitute an official
+protocol. The official protocol includes standard queries and their
+responses and most of the Internet class data formats (e.g., host
+addresses).
+
+However, the domain system is intentionally extensible. Researchers are
+continuously proposing, implementing and experimenting with new data
+types, query types, classes, functions, etc. Thus while the components
+of the official protocol are expected to stay essentially unchanged and
+operate as a production service, experimental behavior should always be
+expected in extensions beyond the official protocol. Experimental or
+obsolete features are clearly marked in these RFCs, and such information
+should be used with caution.
+
+The reader is especially cautioned not to depend on the values which
+appear in examples to be current or complete, since their purpose is
+primarily pedagogical. Distribution of this memo is unlimited.
+
+2. INTRODUCTION
+
+This RFC introduces domain style names, their use for Internet mail and
+host address support, and the protocols and servers used to implement
+domain name facilities.
+
+2.1. The history of domain names
+
+The impetus for the development of the domain system was growth in the
+Internet:
+
+ - Host name to address mappings were maintained by the Network
+ Information Center (NIC) in a single file (HOSTS.TXT) which
+ was FTPed by all hosts [RFC-952, RFC-953]. The total network
+
+
+
+Mockapetris [Page 1]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ bandwidth consumed in distributing a new version by this
+ scheme is proportional to the square of the number of hosts in
+ the network, and even when multiple levels of FTP are used,
+ the outgoing FTP load on the NIC host is considerable.
+ Explosive growth in the number of hosts didn't bode well for
+ the future.
+
+ - The network population was also changing in character. The
+ timeshared hosts that made up the original ARPANET were being
+ replaced with local networks of workstations. Local
+ organizations were administering their own names and
+ addresses, but had to wait for the NIC to change HOSTS.TXT to
+ make changes visible to the Internet at large. Organizations
+ also wanted some local structure on the name space.
+
+ - The applications on the Internet were getting more
+ sophisticated and creating a need for general purpose name
+ service.
+
+
+The result was several ideas about name spaces and their management
+[IEN-116, RFC-799, RFC-819, RFC-830]. The proposals varied, but a
+common thread was the idea of a hierarchical name space, with the
+hierarchy roughly corresponding to organizational structure, and names
+using "." as the character to mark the boundary between hierarchy
+levels. A design using a distributed database and generalized resources
+was described in [RFC-882, RFC-883]. Based on experience with several
+implementations, the system evolved into the scheme described in this
+memo.
+
+The terms "domain" or "domain name" are used in many contexts beyond the
+DNS described here. Very often, the term domain name is used to refer
+to a name with structure indicated by dots, but no relation to the DNS.
+This is particularly true in mail addressing [Quarterman 86].
+
+2.2. DNS design goals
+
+The design goals of the DNS influence its structure. They are:
+
+ - The primary goal is a consistent name space which will be used
+ for referring to resources. In order to avoid the problems
+ caused by ad hoc encodings, names should not be required to
+ contain network identifiers, addresses, routes, or similar
+ information as part of the name.
+
+ - The sheer size of the database and frequency of updates
+ suggest that it must be maintained in a distributed manner,
+ with local caching to improve performance. Approaches that
+
+
+
+Mockapetris [Page 2]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ attempt to collect a consistent copy of the entire database
+ will become more and more expensive and difficult, and hence
+ should be avoided. The same principle holds for the structure
+ of the name space, and in particular mechanisms for creating
+ and deleting names; these should also be distributed.
+
+ - Where there tradeoffs between the cost of acquiring data, the
+ speed of updates, and the accuracy of caches, the source of
+ the data should control the tradeoff.
+
+ - The costs of implementing such a facility dictate that it be
+ generally useful, and not restricted to a single application.
+ We should be able to use names to retrieve host addresses,
+ mailbox data, and other as yet undetermined information. All
+ data associated with a name is tagged with a type, and queries
+ can be limited to a single type.
+
+ - Because we want the name space to be useful in dissimilar
+ networks and applications, we provide the ability to use the
+ same name space with different protocol families or
+ management. For example, host address formats differ between
+ protocols, though all protocols have the notion of address.
+ The DNS tags all data with a class as well as the type, so
+ that we can allow parallel use of different formats for data
+ of type address.
+
+ - We want name server transactions to be independent of the
+ communications system that carries them. Some systems may
+ wish to use datagrams for queries and responses, and only
+ establish virtual circuits for transactions that need the
+ reliability (e.g., database updates, long transactions); other
+ systems will use virtual circuits exclusively.
+
+ - The system should be useful across a wide spectrum of host
+ capabilities. Both personal computers and large timeshared
+ hosts should be able to use the system, though perhaps in
+ different ways.
+
+2.3. Assumptions about usage
+
+The organization of the domain system derives from some assumptions
+about the needs and usage patterns of its user community and is designed
+to avoid many of the the complicated problems found in general purpose
+database systems.
+
+The assumptions are:
+
+ - The size of the total database will initially be proportional
+
+
+
+Mockapetris [Page 3]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ to the number of hosts using the system, but will eventually
+ grow to be proportional to the number of users on those hosts
+ as mailboxes and other information are added to the domain
+ system.
+
+ - Most of the data in the system will change very slowly (e.g.,
+ mailbox bindings, host addresses), but that the system should
+ be able to deal with subsets that change more rapidly (on the
+ order of seconds or minutes).
+
+ - The administrative boundaries used to distribute
+ responsibility for the database will usually correspond to
+ organizations that have one or more hosts. Each organization
+ that has responsibility for a particular set of domains will
+ provide redundant name servers, either on the organization's
+ own hosts or other hosts that the organization arranges to
+ use.
+
+ - Clients of the domain system should be able to identify
+ trusted name servers they prefer to use before accepting
+ referrals to name servers outside of this "trusted" set.
+
+ - Access to information is more critical than instantaneous
+ updates or guarantees of consistency. Hence the update
+ process allows updates to percolate out through the users of
+ the domain system rather than guaranteeing that all copies are
+ simultaneously updated. When updates are unavailable due to
+ network or host failure, the usual course is to believe old
+ information while continuing efforts to update it. The
+ general model is that copies are distributed with timeouts for
+ refreshing. The distributor sets the timeout value and the
+ recipient of the distribution is responsible for performing
+ the refresh. In special situations, very short intervals can
+ be specified, or the owner can prohibit copies.
+
+ - In any system that has a distributed database, a particular
+ name server may be presented with a query that can only be
+ answered by some other server. The two general approaches to
+ dealing with this problem are "recursive", in which the first
+ server pursues the query for the client at another server, and
+ "iterative", in which the server refers the client to another
+ server and lets the client pursue the query. Both approaches
+ have advantages and disadvantages, but the iterative approach
+ is preferred for the datagram style of access. The domain
+ system requires implementation of the iterative approach, but
+ allows the recursive approach as an option.
+
+
+
+
+
+Mockapetris [Page 4]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+The domain system assumes that all data originates in master files
+scattered through the hosts that use the domain system. These master
+files are updated by local system administrators. Master files are text
+files that are read by a local name server, and hence become available
+through the name servers to users of the domain system. The user
+programs access name servers through standard programs called resolvers.
+
+The standard format of master files allows them to be exchanged between
+hosts (via FTP, mail, or some other mechanism); this facility is useful
+when an organization wants a domain, but doesn't want to support a name
+server. The organization can maintain the master files locally using a
+text editor, transfer them to a foreign host which runs a name server,
+and then arrange with the system administrator of the name server to get
+the files loaded.
+
+Each host's name servers and resolvers are configured by a local system
+administrator [RFC-1033]. For a name server, this configuration data
+includes the identity of local master files and instructions on which
+non-local master files are to be loaded from foreign servers. The name
+server uses the master files or copies to load its zones. For
+resolvers, the configuration data identifies the name servers which
+should be the primary sources of information.
+
+The domain system defines procedures for accessing the data and for
+referrals to other name servers. The domain system also defines
+procedures for caching retrieved data and for periodic refreshing of
+data defined by the system administrator.
+
+The system administrators provide:
+
+ - The definition of zone boundaries.
+
+ - Master files of data.
+
+ - Updates to master files.
+
+ - Statements of the refresh policies desired.
+
+The domain system provides:
+
+ - Standard formats for resource data.
+
+ - Standard methods for querying the database.
+
+ - Standard methods for name servers to refresh local data from
+ foreign name servers.
+
+
+
+
+
+Mockapetris [Page 5]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+2.4. Elements of the DNS
+
+The DNS has three major components:
+
+ - The DOMAIN NAME SPACE and RESOURCE RECORDS, which are
+ specifications for a tree structured name space and data
+ associated with the names. Conceptually, each node and leaf
+ of the domain name space tree names a set of information, and
+ query operations are attempts to extract specific types of
+ information from a particular set. A query names the domain
+ name of interest and describes the type of resource
+ information that is desired. For example, the Internet
+ uses some of its domain names to identify hosts; queries for
+ address resources return Internet host addresses.
+
+ - NAME SERVERS are server programs which hold information about
+ the domain tree's structure and set information. A name
+ server may cache structure or set information about any part
+ of the domain tree, but in general a particular name server
+ has complete information about a subset of the domain space,
+ and pointers to other name servers that can be used to lead to
+ information from any part of the domain tree. Name servers
+ know the parts of the domain tree for which they have complete
+ information; a name server is said to be an AUTHORITY for
+ these parts of the name space. Authoritative information is
+ organized into units called ZONEs, and these zones can be
+ automatically distributed to the name servers which provide
+ redundant service for the data in a zone.
+
+ - RESOLVERS are programs that extract information from name
+ servers in response to client requests. Resolvers must be
+ able to access at least one name server and use that name
+ server's information to answer a query directly, or pursue the
+ query using referrals to other name servers. A resolver will
+ typically be a system routine that is directly accessible to
+ user programs; hence no protocol is necessary between the
+ resolver and the user program.
+
+These three components roughly correspond to the three layers or views
+of the domain system:
+
+ - From the user's point of view, the domain system is accessed
+ through a simple procedure or OS call to a local resolver.
+ The domain space consists of a single tree and the user can
+ request information from any section of the tree.
+
+ - From the resolver's point of view, the domain system is
+ composed of an unknown number of name servers. Each name
+
+
+
+Mockapetris [Page 6]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ server has one or more pieces of the whole domain tree's data,
+ but the resolver views each of these databases as essentially
+ static.
+
+ - From a name server's point of view, the domain system consists
+ of separate sets of local information called zones. The name
+ server has local copies of some of the zones. The name server
+ must periodically refresh its zones from master copies in
+ local files or foreign name servers. The name server must
+ concurrently process queries that arrive from resolvers.
+
+In the interests of performance, implementations may couple these
+functions. For example, a resolver on the same machine as a name server
+might share a database consisting of the the zones managed by the name
+server and the cache managed by the resolver.
+
+3. DOMAIN NAME SPACE and RESOURCE RECORDS
+
+3.1. Name space specifications and terminology
+
+The domain name space is a tree structure. Each node and leaf on the
+tree corresponds to a resource set (which may be empty). The domain
+system makes no distinctions between the uses of the interior nodes and
+leaves, and this memo uses the term "node" to refer to both.
+
+Each node has a label, which is zero to 63 octets in length. Brother
+nodes may not have the same label, although the same label can be used
+for nodes which are not brothers. One label is reserved, and that is
+the null (i.e., zero length) label used for the root.
+
+The domain name of a node is the list of the labels on the path from the
+node to the root of the tree. By convention, the labels that compose a
+domain name are printed or read left to right, from the most specific
+(lowest, farthest from the root) to the least specific (highest, closest
+to the root).
+
+Internally, programs that manipulate domain names should represent them
+as sequences of labels, where each label is a length octet followed by
+an octet string. Because all domain names end at the root, which has a
+null string for a label, these internal representations can use a length
+byte of zero to terminate a domain name.
+
+By convention, domain names can be stored with arbitrary case, but
+domain name comparisons for all present domain functions are done in a
+case-insensitive manner, assuming an ASCII character set, and a high
+order zero bit. This means that you are free to create a node with
+label "A" or a node with label "a", but not both as brothers; you could
+refer to either using "a" or "A". When you receive a domain name or
+
+
+
+Mockapetris [Page 7]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+label, you should preserve its case. The rationale for this choice is
+that we may someday need to add full binary domain names for new
+services; existing services would not be changed.
+
+When a user needs to type a domain name, the length of each label is
+omitted and the labels are separated by dots ("."). Since a complete
+domain name ends with the root label, this leads to a printed form which
+ends in a dot. We use this property to distinguish between:
+
+ - a character string which represents a complete domain name
+ (often called "absolute"). For example, "poneria.ISI.EDU."
+
+ - a character string that represents the starting labels of a
+ domain name which is incomplete, and should be completed by
+ local software using knowledge of the local domain (often
+ called "relative"). For example, "poneria" used in the
+ ISI.EDU domain.
+
+Relative names are either taken relative to a well known origin, or to a
+list of domains used as a search list. Relative names appear mostly at
+the user interface, where their interpretation varies from
+implementation to implementation, and in master files, where they are
+relative to a single origin domain name. The most common interpretation
+uses the root "." as either the single origin or as one of the members
+of the search list, so a multi-label relative name is often one where
+the trailing dot has been omitted to save typing.
+
+To simplify implementations, the total number of octets that represent a
+domain name (i.e., the sum of all label octets and label lengths) is
+limited to 255.
+
+A domain is identified by a domain name, and consists of that part of
+the domain name space that is at or below the domain name which
+specifies the domain. A domain is a subdomain of another domain if it
+is contained within that domain. This relationship can be tested by
+seeing if the subdomain's name ends with the containing domain's name.
+For example, A.B.C.D is a subdomain of B.C.D, C.D, D, and " ".
+
+3.2. Administrative guidelines on use
+
+As a matter of policy, the DNS technical specifications do not mandate a
+particular tree structure or rules for selecting labels; its goal is to
+be as general as possible, so that it can be used to build arbitrary
+applications. In particular, the system was designed so that the name
+space did not have to be organized along the lines of network
+boundaries, name servers, etc. The rationale for this is not that the
+name space should have no implied semantics, but rather that the choice
+of implied semantics should be left open to be used for the problem at
+
+
+
+Mockapetris [Page 8]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+hand, and that different parts of the tree can have different implied
+semantics. For example, the IN-ADDR.ARPA domain is organized and
+distributed by network and host address because its role is to translate
+from network or host numbers to names; NetBIOS domains [RFC-1001, RFC-
+1002] are flat because that is appropriate for that application.
+
+However, there are some guidelines that apply to the "normal" parts of
+the name space used for hosts, mailboxes, etc., that will make the name
+space more uniform, provide for growth, and minimize problems as
+software is converted from the older host table. The political
+decisions about the top levels of the tree originated in RFC-920.
+Current policy for the top levels is discussed in [RFC-1032]. MILNET
+conversion issues are covered in [RFC-1031].
+
+Lower domains which will eventually be broken into multiple zones should
+provide branching at the top of the domain so that the eventual
+decomposition can be done without renaming. Node labels which use
+special characters, leading digits, etc., are likely to break older
+software which depends on more restrictive choices.
+
+3.3. Technical guidelines on use
+
+Before the DNS can be used to hold naming information for some kind of
+object, two needs must be met:
+
+ - A convention for mapping between object names and domain
+ names. This describes how information about an object is
+ accessed.
+
+ - RR types and data formats for describing the object.
+
+These rules can be quite simple or fairly complex. Very often, the
+designer must take into account existing formats and plan for upward
+compatibility for existing usage. Multiple mappings or levels of
+mapping may be required.
+
+For hosts, the mapping depends on the existing syntax for host names
+which is a subset of the usual text representation for domain names,
+together with RR formats for describing host addresses, etc. Because we
+need a reliable inverse mapping from address to host name, a special
+mapping for addresses into the IN-ADDR.ARPA domain is also defined.
+
+For mailboxes, the mapping is slightly more complex. The usual mail
+address <local-part>@<mail-domain> is mapped into a domain name by
+converting <local-part> into a single label (regardles of dots it
+contains), converting <mail-domain> into a domain name using the usual
+text format for domain names (dots denote label breaks), and
+concatenating the two to form a single domain name. Thus the mailbox
+
+
+
+Mockapetris [Page 9]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+HOSTMASTER@SRI-NIC.ARPA is represented as a domain name by
+HOSTMASTER.SRI-NIC.ARPA. An appreciation for the reasons behind this
+design also must take into account the scheme for mail exchanges [RFC-
+974].
+
+The typical user is not concerned with defining these rules, but should
+understand that they usually are the result of numerous compromises
+between desires for upward compatibility with old usage, interactions
+between different object definitions, and the inevitable urge to add new
+features when defining the rules. The way the DNS is used to support
+some object is often more crucial than the restrictions inherent in the
+DNS.
+
+3.4. Example name space
+
+The following figure shows a part of the current domain name space, and
+is used in many examples in this RFC. Note that the tree is a very
+small subset of the actual name space.
+
+ |
+ |
+ +---------------------+------------------+
+ | | |
+ MIL EDU ARPA
+ | | |
+ | | |
+ +-----+-----+ | +------+-----+-----+
+ | | | | | | |
+ BRL NOSC DARPA | IN-ADDR SRI-NIC ACC
+ |
+ +--------+------------------+---------------+--------+
+ | | | | |
+ UCI MIT | UDEL YALE
+ | ISI
+ | |
+ +---+---+ |
+ | | |
+ LCS ACHILLES +--+-----+-----+--------+
+ | | | | | |
+ XX A C VAXA VENERA Mockapetris
+
+In this example, the root domain has three immediate subdomains: MIL,
+EDU, and ARPA. The LCS.MIT.EDU domain has one immediate subdomain named
+XX.LCS.MIT.EDU. All of the leaves are also domains.
+
+3.5. Preferred name syntax
+
+The DNS specifications attempt to be as general as possible in the rules
+
+
+
+Mockapetris [Page 10]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+for constructing domain names. The idea is that the name of any
+existing object can be expressed as a domain name with minimal changes.
+However, when assigning a domain name for an object, the prudent user
+will select a name which satisfies both the rules of the domain system
+and any existing rules for the object, whether these rules are published
+or implied by existing programs.
+
+For example, when naming a mail domain, the user should satisfy both the
+rules of this memo and those in RFC-822. When creating a new host name,
+the old rules for HOSTS.TXT should be followed. This avoids problems
+when old software is converted to use domain names.
+
+The following syntax will result in fewer problems with many
+applications that use domain names (e.g., mail, TELNET).
+
+<domain> ::= <subdomain> | " "
+
+<subdomain> ::= <label> | <subdomain> "." <label>
+
+<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
+
+<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+
+<let-dig-hyp> ::= <let-dig> | "-"
+
+<let-dig> ::= <letter> | <digit>
+
+<letter> ::= any one of the 52 alphabetic characters A through Z in
+upper case and a through z in lower case
+
+<digit> ::= any one of the ten digits 0 through 9
+
+Note that while upper and lower case letters are allowed in domain
+names, no significance is attached to the case. That is, two names with
+the same spelling but different case are to be treated as if identical.
+
+The labels must follow the rules for ARPANET host names. They must
+start with a letter, end with a letter or digit, and have as interior
+characters only letters, digits, and hyphen. There are also some
+restrictions on the length. Labels must be 63 characters or less.
+
+For example, the following strings identify hosts in the Internet:
+
+A.ISI.EDU XX.LCS.MIT.EDU SRI-NIC.ARPA
+
+3.6. Resource Records
+
+A domain name identifies a node. Each node has a set of resource
+
+
+
+Mockapetris [Page 11]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+information, which may be empty. The set of resource information
+associated with a particular name is composed of separate resource
+records (RRs). The order of RRs in a set is not significant, and need
+not be preserved by name servers, resolvers, or other parts of the DNS.
+
+When we talk about a specific RR, we assume it has the following:
+
+owner which is the domain name where the RR is found.
+
+type which is an encoded 16 bit value that specifies the type
+ of the resource in this resource record. Types refer to
+ abstract resources.
+
+ This memo uses the following types:
+
+ A a host address
+
+ CNAME identifies the canonical name of an
+ alias
+
+ HINFO identifies the CPU and OS used by a host
+
+ MX identifies a mail exchange for the
+ domain. See [RFC-974 for details.
+
+ NS
+ the authoritative name server for the domain
+
+ PTR
+ a pointer to another part of the domain name space
+
+ SOA
+ identifies the start of a zone of authority]
+
+class which is an encoded 16 bit value which identifies a
+ protocol family or instance of a protocol.
+
+ This memo uses the following classes:
+
+ IN the Internet system
+
+ CH the Chaos system
+
+TTL which is the time to live of the RR. This field is a 32
+ bit integer in units of seconds, an is primarily used by
+ resolvers when they cache RRs. The TTL describes how
+ long a RR can be cached before it should be discarded.
+
+
+
+
+Mockapetris [Page 12]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+RDATA which is the type and sometimes class dependent data
+ which describes the resource:
+
+ A For the IN class, a 32 bit IP address
+
+ For the CH class, a domain name followed
+ by a 16 bit octal Chaos address.
+
+ CNAME a domain name.
+
+ MX a 16 bit preference value (lower is
+ better) followed by a host name willing
+ to act as a mail exchange for the owner
+ domain.
+
+ NS a host name.
+
+ PTR a domain name.
+
+ SOA several fields.
+
+The owner name is often implicit, rather than forming an integral part
+of the RR. For example, many name servers internally form tree or hash
+structures for the name space, and chain RRs off nodes. The remaining
+RR parts are the fixed header (type, class, TTL) which is consistent for
+all RRs, and a variable part (RDATA) that fits the needs of the resource
+being described.
+
+The meaning of the TTL field is a time limit on how long an RR can be
+kept in a cache. This limit does not apply to authoritative data in
+zones; it is also timed out, but by the refreshing policies for the
+zone. The TTL is assigned by the administrator for the zone where the
+data originates. While short TTLs can be used to minimize caching, and
+a zero TTL prohibits caching, the realities of Internet performance
+suggest that these times should be on the order of days for the typical
+host. If a change can be anticipated, the TTL can be reduced prior to
+the change to minimize inconsistency during the change, and then
+increased back to its former value following the change.
+
+The data in the RDATA section of RRs is carried as a combination of
+binary strings and domain names. The domain names are frequently used
+as "pointers" to other data in the DNS.
+
+3.6.1. 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 when stored in a name
+server or resolver. In this memo, we adopt a style similar to that used
+
+
+
+Mockapetris [Page 13]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+in master files in order to show the contents of RRs. In this format,
+most RRs are shown on a single line, although continuation lines are
+possible using parentheses.
+
+The start of the line gives the owner of the RR. If a line begins with
+a blank, then the owner is assumed to be the same as that of the
+previous RR. Blank lines are often included for readability.
+
+Following the owner, we list the TTL, type, and class of the RR. Class
+and type use the mnemonics defined above, and TTL is an integer before
+the type field. In order to avoid ambiguity in parsing, type and class
+mnemonics are disjoint, TTLs are integers, and the type mnemonic is
+always last. The IN class and TTL values are often omitted from examples
+in the interests of clarity.
+
+The resource data or RDATA section of the RR are given using knowledge
+of the typical representation for the data.
+
+For example, we might show the RRs carried in a message as:
+
+ ISI.EDU. MX 10 VENERA.ISI.EDU.
+ MX 10 VAXA.ISI.EDU.
+ VENERA.ISI.EDU. A 128.9.0.32
+ A 10.1.0.52
+ VAXA.ISI.EDU. A 10.2.0.27
+ A 128.9.0.33
+
+The MX RRs have an RDATA section which consists of a 16 bit number
+followed by a domain name. The address RRs use a standard IP address
+format to contain a 32 bit internet address.
+
+This example shows six RRs, with two RRs at each of three domain names.
+
+Similarly we might see:
+
+ XX.LCS.MIT.EDU. IN A 10.0.0.44
+ CH A MIT.EDU. 2420
+
+This example shows two addresses for XX.LCS.MIT.EDU, each of a different
+class.
+
+3.6.2. Aliases and canonical names
+
+In existing systems, hosts and other resources often have several names
+that identify the same resource. For example, the names C.ISI.EDU and
+USC-ISIC.ARPA both identify the same host. Similarly, in the case of
+mailboxes, many organizations provide many names that actually go to the
+same mailbox; for example Mockapetris@C.ISI.EDU, Mockapetris@B.ISI.EDU,
+
+
+
+Mockapetris [Page 14]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+and PVM@ISI.EDU all go to the same mailbox (although the mechanism
+behind this is somewhat complicated).
+
+Most of these systems have a notion that one of the equivalent set of
+names is the canonical or primary name and all others are aliases.
+
+The domain system provides such a feature using the canonical name
+(CNAME) RR. A CNAME RR identifies its owner name as an alias, and
+specifies the corresponding canonical name in the RDATA section of the
+RR. If a CNAME RR is present at a node, no other data should be
+present; this ensures that the data for a canonical name and its aliases
+cannot be different. This rule also insures that a cached CNAME can be
+used without checking with an authoritative server for other RR types.
+
+CNAME RRs cause special action in DNS software. When a name server
+fails to find a desired RR in the resource set associated with the
+domain name, it checks to see if the resource set consists of a CNAME
+record with a matching class. If so, the name server includes the CNAME
+record in the response and restarts the query at the domain name
+specified in the data field of the CNAME record. The one exception to
+this rule is that queries which match the CNAME type are not restarted.
+
+For example, suppose a name server was processing a query with for USC-
+ISIC.ARPA, asking for type A information, and had the following resource
+records:
+
+ USC-ISIC.ARPA IN CNAME C.ISI.EDU
+
+ C.ISI.EDU IN A 10.0.0.52
+
+Both of these RRs would be returned in the response to the type A query,
+while a type CNAME or * query should return just the CNAME.
+
+Domain names in RRs which point at another name should always point at
+the primary name and not the alias. This avoids extra indirections in
+accessing information. For example, the address to name RR for the
+above host should be:
+
+ 52.0.0.10.IN-ADDR.ARPA IN PTR C.ISI.EDU
+
+rather than pointing at USC-ISIC.ARPA. Of course, by the robustness
+principle, domain software should not fail when presented with CNAME
+chains or loops; CNAME chains should be followed and CNAME loops
+signalled as an error.
+
+3.7. Queries
+
+Queries are messages which may be sent to a name server to provoke a
+
+
+
+Mockapetris [Page 15]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+response. In the Internet, queries are carried in UDP datagrams or over
+TCP connections. The response by the name server either answers the
+question posed in the query, refers the requester to another set of name
+servers, or signals some error condition.
+
+In general, the user does not generate queries directly, but instead
+makes a request to a resolver which in turn sends one or more queries to
+name servers and deals with the error conditions and referrals that may
+result. Of course, the possible questions which can be asked in a query
+does shape the kind of service a resolver can provide.
+
+DNS queries and responses are carried in a standard message format. The
+message format has a header containing a number of fixed fields which
+are always present, and four sections which carry query parameters and
+RRs.
+
+The most important field in the header is a four bit field called an
+opcode which separates different queries. Of the possible 16 values,
+one (standard query) is part of the official protocol, two (inverse
+query and status query) are options, one (completion) is obsolete, and
+the rest are unassigned.
+
+The four sections are:
+
+Question Carries the query name and other query parameters.
+
+Answer Carries RRs which directly answer the query.
+
+Authority Carries RRs which describe other authoritative servers.
+ May optionally carry the SOA RR for the authoritative
+ data in the answer section.
+
+Additional Carries RRs which may be helpful in using the RRs in the
+ other sections.
+
+Note that the content, but not the format, of these sections varies with
+header opcode.
+
+3.7.1. Standard queries
+
+A standard query specifies a target domain name (QNAME), query type
+(QTYPE), and query class (QCLASS) and asks for RRs which match. This
+type of query makes up such a vast majority of DNS queries that we use
+the term "query" to mean standard query unless otherwise specified. The
+QTYPE and QCLASS fields are each 16 bits long, and are a superset of
+defined types and classes.
+
+
+
+
+
+Mockapetris [Page 16]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+The QTYPE field may contain:
+
+<any type> matches just that type. (e.g., A, PTR).
+
+AXFR special zone transfer QTYPE.
+
+MAILB matches all mail box related RRs (e.g. MB and MG).
+
+* matches all RR types.
+
+The QCLASS field may contain:
+
+<any class> matches just that class (e.g., IN, CH).
+
+* matches aLL RR classes.
+
+Using the query domain name, QTYPE, and QCLASS, the name server looks
+for matching RRs. In addition to relevant records, the name server may
+return RRs that point toward a name server that has the desired
+information or RRs that are expected to be useful in interpreting the
+relevant RRs. For example, a name server that doesn't have the
+requested information may know a name server that does; a name server
+that returns a domain name in a relevant RR may also return the RR that
+binds that domain name to an address.
+
+For example, a mailer tying to send mail to Mockapetris@ISI.EDU might
+ask the resolver for mail information about ISI.EDU, resulting in a
+query for QNAME=ISI.EDU, QTYPE=MX, QCLASS=IN. The response's answer
+section would be:
+
+ ISI.EDU. MX 10 VENERA.ISI.EDU.
+ MX 10 VAXA.ISI.EDU.
+
+while the additional section might be:
+
+ VAXA.ISI.EDU. A 10.2.0.27
+ A 128.9.0.33
+ VENERA.ISI.EDU. A 10.1.0.52
+ A 128.9.0.32
+
+Because the server assumes that if the requester wants mail exchange
+information, it will probably want the addresses of the mail exchanges
+soon afterward.
+
+Note that the QCLASS=* construct requires special interpretation
+regarding authority. Since a particular name server may not know all of
+the classes available in the domain system, it can never know if it is
+authoritative for all classes. Hence responses to QCLASS=* queries can
+
+
+
+Mockapetris [Page 17]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+never be authoritative.
+
+3.7.2. Inverse queries (Optional)
+
+Name servers may also support inverse queries that map a particular
+resource to a domain name or domain names that have that resource. For
+example, while a standard query might map a domain name to a SOA RR, the
+corresponding inverse query might map the SOA RR back to the domain
+name.
+
+Implementation of this service is optional in a name server, but all
+name servers must at least be able to understand an inverse query
+message and return a not-implemented error response.
+
+The domain system cannot guarantee the completeness or uniqueness of
+inverse queries because the domain system is organized by domain name
+rather than by host address or any other resource type. Inverse queries
+are primarily useful for debugging and database maintenance activities.
+
+Inverse queries may not return the proper TTL, and do not indicate cases
+where the identified RR is one of a set (for example, one address for a
+host having multiple addresses). Therefore, the RRs returned in inverse
+queries should never be cached.
+
+Inverse queries are NOT an acceptable method for mapping host addresses
+to host names; use the IN-ADDR.ARPA domain instead.
+
+A detailed discussion of inverse queries is contained in [RFC-1035].
+
+3.8. Status queries (Experimental)
+
+To be defined.
+
+3.9. Completion queries (Obsolete)
+
+The optional completion services described in RFCs 882 and 883 have been
+deleted. Redesigned services may become available in the future, or the
+opcodes may be reclaimed for other use.
+
+4. NAME SERVERS
+
+4.1. Introduction
+
+Name servers are the repositories of information that make up the domain
+database. The database is divided up into sections called zones, which
+are distributed among the name servers. While name servers can have
+several optional functions and sources of data, the essential task of a
+name server is to answer queries using data in its zones. By design,
+
+
+
+Mockapetris [Page 18]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+name servers can answer queries in a simple manner; the response can
+always be generated using only local data, and either contains the
+answer to the question or a referral to other name servers "closer" to
+the desired information.
+
+A given zone will be available from several name servers to insure its
+availability in spite of host or communication link failure. By
+administrative fiat, we require every zone to be available on at least
+two servers, and many zones have more redundancy than that.
+
+A given name server will typically support one or more zones, but this
+gives it authoritative information about only a small section of the
+domain tree. It may also have some cached non-authoritative data about
+other parts of the tree. The name server marks its responses to queries
+so that the requester can tell whether the response comes from
+authoritative data or not.
+
+4.2. How the database is divided into zones
+
+The domain database is partitioned in two ways: by class, and by "cuts"
+made in the name space between nodes.
+
+The class partition is simple. The database for any class is organized,
+delegated, and maintained separately from all other classes. Since, by
+convention, the name spaces are the same for all classes, the separate
+classes can be thought of as an array of parallel namespace trees. Note
+that the data attached to nodes will be different for these different
+parallel classes. The most common reasons for creating a new class are
+the necessity for a new data format for existing types or a desire for a
+separately managed version of the existing name space.
+
+Within a class, "cuts" in the name space can be made between any two
+adjacent nodes. After all cuts are made, each group of connected name
+space is a separate zone. The zone is said to be authoritative for all
+names in the connected region. Note that the "cuts" in the name space
+may be in different places for different classes, the name servers may
+be different, etc.
+
+These rules mean that every zone has at least one node, and hence domain
+name, for which it is authoritative, and all of the nodes in a
+particular zone are connected. Given, the tree structure, every zone
+has a highest node which is closer to the root than any other node in
+the zone. The name of this node is often used to identify the zone.
+
+It would be possible, though not particularly useful, to partition the
+name space so that each domain name was in a separate zone or so that
+all nodes were in a single zone. Instead, the database is partitioned
+at points where a particular organization wants to take over control of
+
+
+
+Mockapetris [Page 19]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+a subtree. Once an organization controls its own zone it can
+unilaterally change the data in the zone, grow new tree sections
+connected to the zone, delete existing nodes, or delegate new subzones
+under its zone.
+
+If the organization has substructure, it may want to make further
+internal partitions to achieve nested delegations of name space control.
+In some cases, such divisions are made purely to make database
+maintenance more convenient.
+
+4.2.1. Technical considerations
+
+The data that describes a zone has four major parts:
+
+ - Authoritative data for all nodes within the zone.
+
+ - Data that defines the top node of the zone (can be thought of
+ as part of the authoritative data).
+
+ - Data that describes delegated subzones, i.e., cuts around the
+ bottom of the zone.
+
+ - Data that allows access to name servers for subzones
+ (sometimes called "glue" data).
+
+All of this data is expressed in the form of RRs, so a zone can be
+completely described in terms of a set of RRs. Whole zones can be
+transferred between name servers by transferring the RRs, either carried
+in a series of messages or by FTPing a master file which is a textual
+representation.
+
+The authoritative data for a zone is simply all of the RRs attached to
+all of the nodes from the top node of the zone down to leaf nodes or
+nodes above cuts around the bottom edge of the zone.
+
+Though logically part of the authoritative data, the RRs that describe
+the top node of the zone are especially important to the zone's
+management. These RRs are of two types: name server RRs that list, one
+per RR, all of the servers for the zone, and a single SOA RR that
+describes zone management parameters.
+
+The RRs that describe cuts around the bottom of the zone are NS RRs that
+name the servers for the subzones. Since the cuts are between nodes,
+these RRs are NOT part of the authoritative data of the zone, and should
+be exactly the same as the corresponding RRs in the top node of the
+subzone. Since name servers are always associated with zone boundaries,
+NS RRs are only found at nodes which are the top node of some zone. In
+the data that makes up a zone, NS RRs are found at the top node of the
+
+
+
+Mockapetris [Page 20]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+zone (and are authoritative) and at cuts around the bottom of the zone
+(where they are not authoritative), but never in between.
+
+One of the goals of the zone structure is that any zone have all the
+data required to set up communications with the name servers for any
+subzones. That is, parent zones have all the information needed to
+access servers for their children zones. The NS RRs that name the
+servers for subzones are often not enough for this task since they name
+the servers, but do not give their addresses. In particular, if the
+name of the name server is itself in the subzone, we could be faced with
+the situation where the NS RRs tell us that in order to learn a name
+server's address, we should contact the server using the address we wish
+to learn. To fix this problem, a zone contains "glue" RRs which are not
+part of the authoritative data, and are address RRs for the servers.
+These RRs are only necessary if the name server's name is "below" the
+cut, and are only used as part of a referral response.
+
+4.2.2. Administrative considerations
+
+When some organization wants to control its own domain, the first step
+is to identify the proper parent zone, and get the parent zone's owners
+to agree to the delegation of control. While there are no particular
+technical constraints dealing with where in the tree this can be done,
+there are some administrative groupings discussed in [RFC-1032] which
+deal with top level organization, and middle level zones are free to
+create their own rules. For example, one university might choose to use
+a single zone, while another might choose to organize by subzones
+dedicated to individual departments or schools. [RFC-1033] catalogs
+available DNS software an discusses administration procedures.
+
+Once the proper name for the new subzone is selected, the new owners
+should be required to demonstrate redundant name server support. Note
+that there is no requirement that the servers for a zone reside in a
+host which has a name in that domain. In many cases, a zone will be
+more accessible to the internet at large if its servers are widely
+distributed rather than being within the physical facilities controlled
+by the same organization that manages the zone. For example, in the
+current DNS, one of the name servers for the United Kingdom, or UK
+domain, is found in the US. This allows US hosts to get UK data without
+using limited transatlantic bandwidth.
+
+As the last installation step, the delegation NS RRs and glue RRs
+necessary to make the delegation effective should be added to the parent
+zone. The administrators of both zones should insure that the NS and
+glue RRs which mark both sides of the cut are consistent and remain so.
+
+4.3. Name server internals
+
+
+
+
+Mockapetris [Page 21]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+4.3.1. Queries and responses
+
+The principal activity of name servers is to answer standard queries.
+Both the query and its response are carried in a standard message format
+which is described in [RFC-1035]. The query contains a QTYPE, QCLASS,
+and QNAME, which describe the types and classes of desired information
+and the name of interest.
+
+The way that the name server answers the query depends upon whether it
+is operating in recursive mode or not:
+
+ - The simplest mode for the server is non-recursive, since it
+ can answer queries using only local information: the response
+ contains an error, the answer, or a referral to some other
+ server "closer" to the answer. All name servers must
+ implement non-recursive queries.
+
+ - The simplest mode for the client is recursive, since in this
+ mode the name server acts in the role of a resolver and
+ returns either an error or the answer, but never referrals.
+ This service is optional in a name server, and the name server
+ may also choose to restrict the clients which can use
+ recursive mode.
+
+Recursive service is helpful in several situations:
+
+ - a relatively simple requester that lacks the ability to use
+ anything other than a direct answer to the question.
+
+ - a request that needs to cross protocol or other boundaries and
+ can be sent to a server which can act as intermediary.
+
+ - a network where we want to concentrate the cache rather than
+ having a separate cache for each client.
+
+Non-recursive service is appropriate if the requester is capable of
+pursuing referrals and interested in information which will aid future
+requests.
+
+The use of recursive mode is limited to cases where both the client and
+the name server agree to its use. The agreement is negotiated through
+the use of two bits in query and response messages:
+
+ - The recursion available, or RA bit, is set or cleared by a
+ name server in all responses. The bit is true if the name
+ server is willing to provide recursive service for the client,
+ regardless of whether the client requested recursive service.
+ That is, RA signals availability rather than use.
+
+
+
+Mockapetris [Page 22]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ - Queries contain a bit called recursion desired or RD. This
+ bit specifies specifies whether the requester wants recursive
+ service for this query. Clients may request recursive service
+ from any name server, though they should depend upon receiving
+ it only from servers which have previously sent an RA, or
+ servers which have agreed to provide service through private
+ agreement or some other means outside of the DNS protocol.
+
+The recursive mode occurs when a query with RD set arrives at a server
+which is willing to provide recursive service; the client can verify
+that recursive mode was used by checking that both RA and RD are set in
+the reply. Note that the name server should never perform recursive
+service unless asked via RD, since this interferes with trouble shooting
+of name servers and their databases.
+
+If recursive service is requested and available, the recursive response
+to a query will be one of the following:
+
+ - The answer to the query, possibly preface by one or more CNAME
+ RRs that specify aliases encountered on the way to an answer.
+
+ - A name error indicating that the name does not exist. This
+ may include CNAME RRs that indicate that the original query
+ name was an alias for a name which does not exist.
+
+ - A temporary error indication.
+
+If recursive service is not requested or is not available, the non-
+recursive response will be one of the following:
+
+ - An authoritative name error indicating that the name does not
+ exist.
+
+ - A temporary error indication.
+
+ - Some combination of:
+
+ RRs that answer the question, together with an indication
+ whether the data comes from a zone or is cached.
+
+ A referral to name servers which have zones which are closer
+ ancestors to the name than the server sending the reply.
+
+ - RRs that the name server thinks will prove useful to the
+ requester.
+
+
+
+
+
+
+Mockapetris [Page 23]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+4.3.2. Algorithm
+
+The actual algorithm used by the name server will depend on the local OS
+and data structures used to store RRs. The following algorithm assumes
+that the RRs are organized in several tree structures, one for each
+zone, and another for the cache:
+
+ 1. Set or clear the value of recursion available in the response
+ depending on whether the name server is willing to provide
+ recursive service. If recursive service is available and
+ requested via the RD bit in the query, go to step 5,
+ otherwise step 2.
+
+ 2. Search the available zones for the zone which is the nearest
+ ancestor to QNAME. If such a zone is found, go to step 3,
+ otherwise step 4.
+
+ 3. Start matching down, label by label, in the zone. The
+ matching process can terminate several ways:
+
+ a. If the whole of QNAME is matched, we have found the
+ node.
+
+ If the data at the node is a CNAME, and QTYPE doesn't
+ match CNAME, copy the CNAME RR into the answer section
+ of the response, change QNAME to the canonical name in
+ the CNAME RR, and go back to step 1.
+
+ Otherwise, copy all RRs which match QTYPE into the
+ answer section and go to step 6.
+
+ b. If a match would take us out of the authoritative data,
+ we have a referral. This happens when we encounter a
+ node with NS RRs marking cuts along the bottom of a
+ zone.
+
+ Copy the NS RRs for the subzone into the authority
+ section of the reply. Put whatever addresses are
+ available into the additional section, using glue RRs
+ if the addresses are not available from authoritative
+ data or the cache. Go to step 4.
+
+ c. If at some label, a match is impossible (i.e., the
+ corresponding label does not exist), look to see if a
+ the "*" label exists.
+
+ If the "*" label does not exist, check whether the name
+ we are looking for is the original QNAME in the query
+
+
+
+Mockapetris [Page 24]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ or a name we have followed due to a CNAME. If the name
+ is original, set an authoritative name error in the
+ response and exit. Otherwise just exit.
+
+ If the "*" label does exist, match RRs at that node
+ against QTYPE. If any match, copy them into the answer
+ section, but set the owner of the RR to be QNAME, and
+ not the node with the "*" label. Go to step 6.
+
+ 4. Start matching down in the cache. If QNAME is found in the
+ cache, copy all RRs attached to it that match QTYPE into the
+ answer section. If there was no delegation from
+ authoritative data, look for the best one from the cache, and
+ put it in the authority section. Go to step 6.
+
+ 5. Using the local resolver or a copy of its algorithm (see
+ resolver section of this memo) to answer the query. Store
+ the results, including any intermediate CNAMEs, in the answer
+ section of the response.
+
+ 6. Using local data only, attempt to add other RRs which may be
+ useful to the additional section of the query. Exit.
+
+4.3.3. Wildcards
+
+In the previous algorithm, special treatment was given to RRs with owner
+names starting with the label "*". Such RRs are called wildcards.
+Wildcard RRs can be thought of as instructions for synthesizing RRs.
+When the appropriate conditions are met, the name server creates RRs
+with an owner name equal to the query name and contents taken from the
+wildcard RRs.
+
+This facility is most often used to create a zone which will be used to
+forward mail from the Internet to some other mail system. The general
+idea is that any name in that zone which is presented to server in a
+query will be assumed to exist, with certain properties, unless explicit
+evidence exists to the contrary. Note that the use of the term zone
+here, instead of domain, is intentional; such defaults do not propagate
+across zone boundaries, although a subzone may choose to achieve that
+appearance by setting up similar defaults.
+
+The contents of the wildcard RRs follows the usual rules and formats for
+RRs. The wildcards in the zone have an owner name that controls the
+query names they will match. The owner name of the wildcard RRs is of
+the form "*.<anydomain>", where <anydomain> is any domain name.
+<anydomain> should not contain other * labels, and should be in the
+authoritative data of the zone. The wildcards potentially apply to
+descendants of <anydomain>, but not to <anydomain> itself. Another way
+
+
+
+Mockapetris [Page 25]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+to look at this is that the "*" label always matches at least one whole
+label and sometimes more, but always whole labels.
+
+Wildcard RRs do not apply:
+
+ - When the query is in another zone. That is, delegation cancels
+ the wildcard defaults.
+
+ - When the query name or a name between the wildcard domain and
+ the query name is know to exist. For example, if a wildcard
+ RR has an owner name of "*.X", and the zone also contains RRs
+ attached to B.X, the wildcards would apply to queries for name
+ Z.X (presuming there is no explicit information for Z.X), but
+ not to B.X, A.B.X, or X.
+
+A * label appearing in a query name has no special effect, but can be
+used to test for wildcards in an authoritative zone; such a query is the
+only way to get a response containing RRs with an owner name with * in
+it. The result of such a query should not be cached.
+
+Note that the contents of the wildcard RRs are not modified when used to
+synthesize RRs.
+
+To illustrate the use of wildcard RRs, suppose a large company with a
+large, non-IP/TCP, network wanted to create a mail gateway. If the
+company was called X.COM, and IP/TCP capable gateway machine was called
+A.X.COM, the following RRs might be entered into the COM zone:
+
+ X.COM MX 10 A.X.COM
+
+ *.X.COM MX 10 A.X.COM
+
+ A.X.COM A 1.2.3.4
+ A.X.COM MX 10 A.X.COM
+
+ *.A.X.COM MX 10 A.X.COM
+
+This would cause any MX query for any domain name ending in X.COM to
+return an MX RR pointing at A.X.COM. Two wildcard RRs are required
+since the effect of the wildcard at *.X.COM is inhibited in the A.X.COM
+subtree by the explicit data for A.X.COM. Note also that the explicit
+MX data at X.COM and A.X.COM is required, and that none of the RRs above
+would match a query name of XX.COM.
+
+4.3.4. Negative response caching (Optional)
+
+The DNS provides an optional service which allows name servers to
+distribute, and resolvers to cache, negative results with TTLs. For
+
+
+
+Mockapetris [Page 26]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+example, a name server can distribute a TTL along with a name error
+indication, and a resolver receiving such information is allowed to
+assume that the name does not exist during the TTL period without
+consulting authoritative data. Similarly, a resolver can make a query
+with a QTYPE which matches multiple types, and cache the fact that some
+of the types are not present.
+
+This feature can be particularly important in a system which implements
+naming shorthands that use search lists beacuse a popular shorthand,
+which happens to require a suffix toward the end of the search list,
+will generate multiple name errors whenever it is used.
+
+The method is that a name server may add an SOA RR to the additional
+section of a response when that response is authoritative. The SOA must
+be that of the zone which was the source of the authoritative data in
+the answer section, or name error if applicable. The MINIMUM field of
+the SOA controls the length of time that the negative result may be
+cached.
+
+Note that in some circumstances, the answer section may contain multiple
+owner names. In this case, the SOA mechanism should only be used for
+the data which matches QNAME, which is the only authoritative data in
+this section.
+
+Name servers and resolvers should never attempt to add SOAs to the
+additional section of a non-authoritative response, or attempt to infer
+results which are not directly stated in an authoritative response.
+There are several reasons for this, including: cached information isn't
+usually enough to match up RRs and their zone names, SOA RRs may be
+cached due to direct SOA queries, and name servers are not required to
+output the SOAs in the authority section.
+
+This feature is optional, although a refined version is expected to
+become part of the standard protocol in the future. Name servers are
+not required to add the SOA RRs in all authoritative responses, nor are
+resolvers required to cache negative results. Both are recommended.
+All resolvers and recursive name servers are required to at least be
+able to ignore the SOA RR when it is present in a response.
+
+Some experiments have also been proposed which will use this feature.
+The idea is that if cached data is known to come from a particular zone,
+and if an authoritative copy of the zone's SOA is obtained, and if the
+zone's SERIAL has not changed since the data was cached, then the TTL of
+the cached data can be reset to the zone MINIMUM value if it is smaller.
+This usage is mentioned for planning purposes only, and is not
+recommended as yet.
+
+
+
+
+
+Mockapetris [Page 27]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+4.3.5. Zone maintenance and transfers
+
+Part of the job of a zone administrator is to maintain the zones at all
+of the name servers which are authoritative for the zone. When the
+inevitable changes are made, they must be distributed to all of the name
+servers. While this distribution can be accomplished using FTP or some
+other ad hoc procedure, the preferred method is the zone transfer part
+of the DNS protocol.
+
+The general model of automatic zone transfer or refreshing is that one
+of the name servers is the master or primary for the zone. Changes are
+coordinated at the primary, typically by editing a master file for the
+zone. After editing, the administrator signals the master server to
+load the new zone. The other non-master or secondary servers for the
+zone periodically check for changes (at a selectable interval) and
+obtain new zone copies when changes have been made.
+
+To detect changes, secondaries just check the SERIAL field of the SOA
+for the zone. In addition to whatever other changes are made, the
+SERIAL field in the SOA of the zone is always advanced whenever any
+change is made to the zone. The advancing can be a simple increment, or
+could be based on the write date and time of the master file, etc. The
+purpose is to make it possible to determine which of two copies of a
+zone is more recent by comparing serial numbers. Serial number advances
+and comparisons use sequence space arithmetic, so there is a theoretic
+limit on how fast a zone can be updated, basically that old copies must
+die out before the serial number covers half of its 32 bit range. In
+practice, the only concern is that the compare operation deals properly
+with comparisons around the boundary between the most positive and most
+negative 32 bit numbers.
+
+The periodic polling of the secondary servers is controlled by
+parameters in the SOA RR for the zone, which set the minimum acceptable
+polling intervals. The parameters are called REFRESH, RETRY, and
+EXPIRE. Whenever a new zone is loaded in a secondary, the secondary
+waits REFRESH seconds before checking with the primary for a new serial.
+If this check cannot be completed, new checks are started every RETRY
+seconds. The check is a simple query to the primary for the SOA RR of
+the zone. If the serial field in the secondary's zone copy is equal to
+the serial returned by the primary, then no changes have occurred, and
+the REFRESH interval wait is restarted. If the secondary finds it
+impossible to perform a serial check for the EXPIRE interval, it must
+assume that its copy of the zone is obsolete an discard it.
+
+When the poll shows that the zone has changed, then the secondary server
+must request a zone transfer via an AXFR request for the zone. The AXFR
+may cause an error, such as refused, but normally is answered by a
+sequence of response messages. The first and last messages must contain
+
+
+
+Mockapetris [Page 28]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+the data for the top authoritative node of the zone. Intermediate
+messages carry all of the other RRs from the zone, including both
+authoritative and non-authoritative RRs. The stream of messages allows
+the secondary to construct a copy of the zone. Because accuracy is
+essential, TCP or some other reliable protocol must be used for AXFR
+requests.
+
+Each secondary server is required to perform the following operations
+against the master, but may also optionally perform these operations
+against other secondary servers. This strategy can improve the transfer
+process when the primary is unavailable due to host downtime or network
+problems, or when a secondary server has better network access to an
+"intermediate" secondary than to the primary.
+
+5. RESOLVERS
+
+5.1. Introduction
+
+Resolvers are programs that interface user programs to domain name
+servers. In the simplest case, a resolver receives a request from a
+user program (e.g., mail programs, TELNET, FTP) in the form of a
+subroutine call, system call etc., and returns the desired information
+in a form compatible with the local host's data formats.
+
+The resolver is located on the same machine as the program that requests
+the resolver's services, but it may need to consult name servers on
+other hosts. Because a resolver may need to consult several name
+servers, or may have the requested information in a local cache, the
+amount of time that a resolver will take to complete can vary quite a
+bit, from milliseconds to several seconds.
+
+A very important goal of the resolver is to eliminate network delay and
+name server load from most requests by answering them from its cache of
+prior results. It follows that caches which are shared by multiple
+processes, users, machines, etc., are more efficient than non-shared
+caches.
+
+5.2. Client-resolver interface
+
+5.2.1. Typical functions
+
+The client interface to the resolver is influenced by the local host's
+conventions, but the typical resolver-client interface has three
+functions:
+
+ 1. Host name to host address translation.
+
+ This function is often defined to mimic a previous HOSTS.TXT
+
+
+
+Mockapetris [Page 29]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ based function. Given a character string, the caller wants
+ one or more 32 bit IP addresses. Under the DNS, it
+ translates into a request for type A RRs. Since the DNS does
+ not preserve the order of RRs, this function may choose to
+ sort the returned addresses or select the "best" address if
+ the service returns only one choice to the client. Note that
+ a multiple address return is recommended, but a single
+ address may be the only way to emulate prior HOSTS.TXT
+ services.
+
+ 2. Host address to host name translation
+
+ This function will often follow the form of previous
+ functions. Given a 32 bit IP address, the caller wants a
+ character string. The octets of the IP address are reversed,
+ used as name components, and suffixed with "IN-ADDR.ARPA". A
+ type PTR query is used to get the RR with the primary name of
+ the host. For example, a request for the host name
+ corresponding to IP address 1.2.3.4 looks for PTR RRs for
+ domain name "4.3.2.1.IN-ADDR.ARPA".
+
+ 3. General lookup function
+
+ This function retrieves arbitrary information from the DNS,
+ and has no counterpart in previous systems. The caller
+ supplies a QNAME, QTYPE, and QCLASS, and wants all of the
+ matching RRs. This function will often use the DNS format
+ for all RR data instead of the local host's, and returns all
+ RR content (e.g., TTL) instead of a processed form with local
+ quoting conventions.
+
+When the resolver performs the indicated function, it usually has one of
+the following results to pass back to the client:
+
+ - One or more RRs giving the requested data.
+
+ In this case the resolver returns the answer in the
+ appropriate format.
+
+ - A name error (NE).
+
+ This happens when the referenced name does not exist. For
+ example, a user may have mistyped a host name.
+
+ - A data not found error.
+
+ This happens when the referenced name exists, but data of the
+ appropriate type does not. For example, a host address
+
+
+
+Mockapetris [Page 30]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ function applied to a mailbox name would return this error
+ since the name exists, but no address RR is present.
+
+It is important to note that the functions for translating between host
+names and addresses may combine the "name error" and "data not found"
+error conditions into a single type of error return, but the general
+function should not. One reason for this is that applications may ask
+first for one type of information about a name followed by a second
+request to the same name for some other type of information; if the two
+errors are combined, then useless queries may slow the application.
+
+5.2.2. Aliases
+
+While attempting to resolve a particular request, the resolver may find
+that the name in question is an alias. For example, the resolver might
+find that the name given for host name to address translation is an
+alias when it finds the CNAME RR. If possible, the alias condition
+should be signalled back from the resolver to the client.
+
+In most cases a resolver simply restarts the query at the new name when
+it encounters a CNAME. However, when performing the general function,
+the resolver should not pursue aliases when the CNAME RR matches the
+query type. This allows queries which ask whether an alias is present.
+For example, if the query type is CNAME, the user is interested in the
+CNAME RR itself, and not the RRs at the name it points to.
+
+Several special conditions can occur with aliases. Multiple levels of
+aliases should be avoided due to their lack of efficiency, but should
+not be signalled as an error. Alias loops and aliases which point to
+non-existent names should be caught and an error condition passed back
+to the client.
+
+5.2.3. Temporary failures
+
+In a less than perfect world, all resolvers will occasionally be unable
+to resolve a particular request. This condition can be caused by a
+resolver which becomes separated from the rest of the network due to a
+link failure or gateway problem, or less often by coincident failure or
+unavailability of all servers for a particular domain.
+
+It is essential that this sort of condition should not be signalled as a
+name or data not present error to applications. This sort of behavior
+is annoying to humans, and can wreak havoc when mail systems use the
+DNS.
+
+While in some cases it is possible to deal with such a temporary problem
+by blocking the request indefinitely, this is usually not a good choice,
+particularly when the client is a server process that could move on to
+
+
+
+Mockapetris [Page 31]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+other tasks. The recommended solution is to always have temporary
+failure as one of the possible results of a resolver function, even
+though this may make emulation of existing HOSTS.TXT functions more
+difficult.
+
+5.3. Resolver internals
+
+Every resolver implementation uses slightly different algorithms, and
+typically spends much more logic dealing with errors of various sorts
+than typical occurances. This section outlines a recommended basic
+strategy for resolver operation, but leaves details to [RFC-1035].
+
+5.3.1. Stub resolvers
+
+One option for implementing a resolver is to move the resolution
+function out of the local machine and into a name server which supports
+recursive queries. This can provide an easy method of providing domain
+service in a PC which lacks the resources to perform the resolver
+function, or can centralize the cache for a whole local network or
+organization.
+
+All that the remaining stub needs is a list of name server addresses
+that will perform the recursive requests. This type of resolver
+presumably needs the information in a configuration file, since it
+probably lacks the sophistication to locate it in the domain database.
+The user also needs to verify that the listed servers will perform the
+recursive service; a name server is free to refuse to perform recursive
+services for any or all clients. The user should consult the local
+system administrator to find name servers willing to perform the
+service.
+
+This type of service suffers from some drawbacks. Since the recursive
+requests may take an arbitrary amount of time to perform, the stub may
+have difficulty optimizing retransmission intervals to deal with both
+lost UDP packets and dead servers; the name server can be easily
+overloaded by too zealous a stub if it interprets retransmissions as new
+requests. Use of TCP may be an answer, but TCP may well place burdens
+on the host's capabilities which are similar to those of a real
+resolver.
+
+5.3.2. Resources
+
+In addition to its own resources, the resolver may also have shared
+access to zones maintained by a local name server. This gives the
+resolver the advantage of more rapid access, but the resolver must be
+careful to never let cached information override zone data. In this
+discussion the term "local information" is meant to mean the union of
+the cache and such shared zones, with the understanding that
+
+
+
+Mockapetris [Page 32]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+authoritative data is always used in preference to cached data when both
+are present.
+
+The following resolver algorithm assumes that all functions have been
+converted to a general lookup function, and uses the following data
+structures to represent the state of a request in progress in the
+resolver:
+
+SNAME the domain name we are searching for.
+
+STYPE the QTYPE of the search request.
+
+SCLASS the QCLASS of the search request.
+
+SLIST a structure which describes the name servers and the
+ zone which the resolver is currently trying to query.
+ This structure keeps track of the resolver's current
+ best guess about which name servers hold the desired
+ information; it is updated when arriving information
+ changes the guess. This structure includes the
+ equivalent of a zone name, the known name servers for
+ the zone, the known addresses for the name servers, and
+ history information which can be used to suggest which
+ server is likely to be the best one to try next. The
+ zone name equivalent is a match count of the number of
+ labels from the root down which SNAME has in common with
+ the zone being queried; this is used as a measure of how
+ "close" the resolver is to SNAME.
+
+SBELT a "safety belt" structure of the same form as SLIST,
+ which is initialized from a configuration file, and
+ lists servers which should be used when the resolver
+ doesn't have any local information to guide name server
+ selection. The match count will be -1 to indicate that
+ no labels are known to match.
+
+CACHE A structure which stores the results from previous
+ responses. Since resolvers are responsible for
+ discarding old RRs whose TTL has expired, most
+ implementations convert the interval specified in
+ arriving RRs to some sort of absolute time when the RR
+ is stored in the cache. Instead of counting the TTLs
+ down individually, the resolver just ignores or discards
+ old RRs when it runs across them in the course of a
+ search, or discards them during periodic sweeps to
+ reclaim the memory consumed by old RRs.
+
+
+
+
+
+Mockapetris [Page 33]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+5.3.3. Algorithm
+
+The top level algorithm has four steps:
+
+ 1. See if the answer is in local information, and if so return
+ it to the client.
+
+ 2. Find the best servers to ask.
+
+ 3. Send them queries until one returns a response.
+
+ 4. Analyze the response, either:
+
+ a. if the response answers the question or contains a name
+ error, cache the data as well as returning it back to
+ the client.
+
+ b. if the response contains a better delegation to other
+ servers, cache the delegation information, and go to
+ step 2.
+
+ c. if the response shows a CNAME and that is not the
+ answer itself, cache the CNAME, change the SNAME to the
+ canonical name in the CNAME RR and go to step 1.
+
+ d. if the response shows a servers failure or other
+ bizarre contents, delete the server from the SLIST and
+ go back to step 3.
+
+Step 1 searches the cache for the desired data. If the data is in the
+cache, it is assumed to be good enough for normal use. Some resolvers
+have an option at the user interface which will force the resolver to
+ignore the cached data and consult with an authoritative server. This
+is not recommended as the default. If the resolver has direct access to
+a name server's zones, it should check to see if the desired data is
+present in authoritative form, and if so, use the authoritative data in
+preference to cached data.
+
+Step 2 looks for a name server to ask for the required data. The
+general strategy is to look for locally-available name server RRs,
+starting at SNAME, then the parent domain name of SNAME, the
+grandparent, and so on toward the root. Thus if SNAME were
+Mockapetris.ISI.EDU, this step would look for NS RRs for
+Mockapetris.ISI.EDU, then ISI.EDU, then EDU, and then . (the root).
+These NS RRs list the names of hosts for a zone at or above SNAME. Copy
+the names into SLIST. Set up their addresses using local data. It may
+be the case that the addresses are not available. The resolver has many
+choices here; the best is to start parallel resolver processes looking
+
+
+
+Mockapetris [Page 34]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+for the addresses while continuing onward with the addresses which are
+available. Obviously, the design choices and options are complicated
+and a function of the local host's capabilities. The recommended
+priorities for the resolver designer are:
+
+ 1. Bound the amount of work (packets sent, parallel processes
+ started) so that a request can't get into an infinite loop or
+ start off a chain reaction of requests or queries with other
+ implementations EVEN IF SOMEONE HAS INCORRECTLY CONFIGURED
+ SOME DATA.
+
+ 2. Get back an answer if at all possible.
+
+ 3. Avoid unnecessary transmissions.
+
+ 4. Get the answer as quickly as possible.
+
+If the search for NS RRs fails, then the resolver initializes SLIST from
+the safety belt SBELT. The basic idea is that when the resolver has no
+idea what servers to ask, it should use information from a configuration
+file that lists several servers which are expected to be helpful.
+Although there are special situations, the usual choice is two of the
+root servers and two of the servers for the host's domain. The reason
+for two of each is for redundancy. The root servers will provide
+eventual access to all of the domain space. The two local servers will
+allow the resolver to continue to resolve local names if the local
+network becomes isolated from the internet due to gateway or link
+failure.
+
+In addition to the names and addresses of the servers, the SLIST data
+structure can be sorted to use the best servers first, and to insure
+that all addresses of all servers are used in a round-robin manner. The
+sorting can be a simple function of preferring addresses on the local
+network over others, or may involve statistics from past events, such as
+previous response times and batting averages.
+
+Step 3 sends out queries until a response is received. The strategy is
+to cycle around all of the addresses for all of the servers with a
+timeout between each transmission. In practice it is important to use
+all addresses of a multihomed host, and too aggressive a retransmission
+policy actually slows response when used by multiple resolvers
+contending for the same name server and even occasionally for a single
+resolver. SLIST typically contains data values to control the timeouts
+and keep track of previous transmissions.
+
+Step 4 involves analyzing responses. The resolver should be highly
+paranoid in its parsing of responses. It should also check that the
+response matches the query it sent using the ID field in the response.
+
+
+
+Mockapetris [Page 35]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+The ideal answer is one from a server authoritative for the query which
+either gives the required data or a name error. The data is passed back
+to the user and entered in the cache for future use if its TTL is
+greater than zero.
+
+If the response shows a delegation, the resolver should check to see
+that the delegation is "closer" to the answer than the servers in SLIST
+are. This can be done by comparing the match count in SLIST with that
+computed from SNAME and the NS RRs in the delegation. If not, the reply
+is bogus and should be ignored. If the delegation is valid the NS
+delegation RRs and any address RRs for the servers should be cached.
+The name servers are entered in the SLIST, and the search is restarted.
+
+If the response contains a CNAME, the search is restarted at the CNAME
+unless the response has the data for the canonical name or if the CNAME
+is the answer itself.
+
+Details and implementation hints can be found in [RFC-1035].
+
+6. A SCENARIO
+
+In our sample domain space, suppose we wanted separate administrative
+control for the root, MIL, EDU, MIT.EDU and ISI.EDU zones. We might
+allocate name servers as follows:
+
+
+ |(C.ISI.EDU,SRI-NIC.ARPA
+ | A.ISI.EDU)
+ +---------------------+------------------+
+ | | |
+ MIL EDU ARPA
+ |(SRI-NIC.ARPA, |(SRI-NIC.ARPA, |
+ | A.ISI.EDU | C.ISI.EDU) |
+ +-----+-----+ | +------+-----+-----+
+ | | | | | | |
+ BRL NOSC DARPA | IN-ADDR SRI-NIC ACC
+ |
+ +--------+------------------+---------------+--------+
+ | | | | |
+ UCI MIT | UDEL YALE
+ |(XX.LCS.MIT.EDU, ISI
+ |ACHILLES.MIT.EDU) |(VAXA.ISI.EDU,VENERA.ISI.EDU,
+ +---+---+ | A.ISI.EDU)
+ | | |
+ LCS ACHILLES +--+-----+-----+--------+
+ | | | | | |
+ XX A C VAXA VENERA Mockapetris
+
+
+
+
+Mockapetris [Page 36]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+In this example, the authoritative name server is shown in parentheses
+at the point in the domain tree at which is assumes control.
+
+Thus the root name servers are on C.ISI.EDU, SRI-NIC.ARPA, and
+A.ISI.EDU. The MIL domain is served by SRI-NIC.ARPA and A.ISI.EDU. The
+EDU domain is served by SRI-NIC.ARPA. and C.ISI.EDU. Note that servers
+may have zones which are contiguous or disjoint. In this scenario,
+C.ISI.EDU has contiguous zones at the root and EDU domains. A.ISI.EDU
+has contiguous zones at the root and MIL domains, but also has a non-
+contiguous zone at ISI.EDU.
+
+6.1. C.ISI.EDU name server
+
+C.ISI.EDU is a name server for the root, MIL, and EDU domains of the IN
+class, and would have zones for these domains. The zone data for the
+root domain might be:
+
+ . IN SOA SRI-NIC.ARPA. HOSTMASTER.SRI-NIC.ARPA. (
+ 870611 ;serial
+ 1800 ;refresh every 30 min
+ 300 ;retry every 5 min
+ 604800 ;expire after a week
+ 86400) ;minimum of a day
+ NS A.ISI.EDU.
+ NS C.ISI.EDU.
+ NS SRI-NIC.ARPA.
+
+ MIL. 86400 NS SRI-NIC.ARPA.
+ 86400 NS A.ISI.EDU.
+
+ EDU. 86400 NS SRI-NIC.ARPA.
+ 86400 NS C.ISI.EDU.
+
+ SRI-NIC.ARPA. A 26.0.0.73
+ A 10.0.0.51
+ MX 0 SRI-NIC.ARPA.
+ HINFO DEC-2060 TOPS20
+
+ ACC.ARPA. A 26.6.0.65
+ HINFO PDP-11/70 UNIX
+ MX 10 ACC.ARPA.
+
+ USC-ISIC.ARPA. CNAME C.ISI.EDU.
+
+ 73.0.0.26.IN-ADDR.ARPA. PTR SRI-NIC.ARPA.
+ 65.0.6.26.IN-ADDR.ARPA. PTR ACC.ARPA.
+ 51.0.0.10.IN-ADDR.ARPA. PTR SRI-NIC.ARPA.
+ 52.0.0.10.IN-ADDR.ARPA. PTR C.ISI.EDU.
+
+
+
+Mockapetris [Page 37]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ 103.0.3.26.IN-ADDR.ARPA. PTR A.ISI.EDU.
+
+ A.ISI.EDU. 86400 A 26.3.0.103
+ C.ISI.EDU. 86400 A 10.0.0.52
+
+This data is represented as it would be in a master file. Most RRs are
+single line entries; the sole exception here is the SOA RR, which uses
+"(" to start a multi-line RR and ")" to show the end of a multi-line RR.
+Since the class of all RRs in a zone must be the same, only the first RR
+in a zone need specify the class. When a name server loads a zone, it
+forces the TTL of all authoritative RRs to be at least the MINIMUM field
+of the SOA, here 86400 seconds, or one day. The NS RRs marking
+delegation of the MIL and EDU domains, together with the glue RRs for
+the servers host addresses, are not part of the authoritative data in
+the zone, and hence have explicit TTLs.
+
+Four RRs are attached to the root node: the SOA which describes the root
+zone and the 3 NS RRs which list the name servers for the root. The
+data in the SOA RR describes the management of the zone. The zone data
+is maintained on host SRI-NIC.ARPA, and the responsible party for the
+zone is HOSTMASTER@SRI-NIC.ARPA. A key item in the SOA is the 86400
+second minimum TTL, which means that all authoritative data in the zone
+has at least that TTL, although higher values may be explicitly
+specified.
+
+The NS RRs for the MIL and EDU domains mark the boundary between the
+root zone and the MIL and EDU zones. Note that in this example, the
+lower zones happen to be supported by name servers which also support
+the root zone.
+
+The master file for the EDU zone might be stated relative to the origin
+EDU. The zone data for the EDU domain might be:
+
+ EDU. IN SOA SRI-NIC.ARPA. HOSTMASTER.SRI-NIC.ARPA. (
+ 870729 ;serial
+ 1800 ;refresh every 30 minutes
+ 300 ;retry every 5 minutes
+ 604800 ;expire after a week
+ 86400 ;minimum of a day
+ )
+ NS SRI-NIC.ARPA.
+ NS C.ISI.EDU.
+
+ UCI 172800 NS ICS.UCI
+ 172800 NS ROME.UCI
+ ICS.UCI 172800 A 192.5.19.1
+ ROME.UCI 172800 A 192.5.19.31
+
+
+
+
+Mockapetris [Page 38]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ ISI 172800 NS VAXA.ISI
+ 172800 NS A.ISI
+ 172800 NS VENERA.ISI.EDU.
+ VAXA.ISI 172800 A 10.2.0.27
+ 172800 A 128.9.0.33
+ VENERA.ISI.EDU. 172800 A 10.1.0.52
+ 172800 A 128.9.0.32
+ A.ISI 172800 A 26.3.0.103
+
+ UDEL.EDU. 172800 NS LOUIE.UDEL.EDU.
+ 172800 NS UMN-REI-UC.ARPA.
+ LOUIE.UDEL.EDU. 172800 A 10.0.0.96
+ 172800 A 192.5.39.3
+
+ YALE.EDU. 172800 NS YALE.ARPA.
+ YALE.EDU. 172800 NS YALE-BULLDOG.ARPA.
+
+ MIT.EDU. 43200 NS XX.LCS.MIT.EDU.
+ 43200 NS ACHILLES.MIT.EDU.
+ XX.LCS.MIT.EDU. 43200 A 10.0.0.44
+ ACHILLES.MIT.EDU. 43200 A 18.72.0.8
+
+Note the use of relative names here. The owner name for the ISI.EDU. is
+stated using a relative name, as are two of the name server RR contents.
+Relative and absolute domain names may be freely intermixed in a master
+
+6.2. Example standard queries
+
+The following queries and responses illustrate name server behavior.
+Unless otherwise noted, the queries do not have recursion desired (RD)
+in the header. Note that the answers to non-recursive queries do depend
+on the server being asked, but do not depend on the identity of the
+requester.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 39]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+6.2.1. QNAME=SRI-NIC.ARPA, QTYPE=A
+
+The query would look like:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY |
+ +---------------------------------------------------+
+ Question | QNAME=SRI-NIC.ARPA., QCLASS=IN, QTYPE=A |
+ +---------------------------------------------------+
+ Answer | <empty> |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+The response from C.ISI.EDU would be:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE, AA |
+ +---------------------------------------------------+
+ Question | QNAME=SRI-NIC.ARPA., QCLASS=IN, QTYPE=A |
+ +---------------------------------------------------+
+ Answer | SRI-NIC.ARPA. 86400 IN A 26.0.0.73 |
+ | 86400 IN A 10.0.0.51 |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+The header of the response looks like the header of the query, except
+that the RESPONSE bit is set, indicating that this message is a
+response, not a query, and the Authoritative Answer (AA) bit is set
+indicating that the address RRs in the answer section are from
+authoritative data. The question section of the response matches the
+question section of the query.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 40]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+If the same query was sent to some other server which was not
+authoritative for SRI-NIC.ARPA, the response might be:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY,RESPONSE |
+ +---------------------------------------------------+
+ Question | QNAME=SRI-NIC.ARPA., QCLASS=IN, QTYPE=A |
+ +---------------------------------------------------+
+ Answer | SRI-NIC.ARPA. 1777 IN A 10.0.0.51 |
+ | 1777 IN A 26.0.0.73 |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+This response is different from the previous one in two ways: the header
+does not have AA set, and the TTLs are different. The inference is that
+the data did not come from a zone, but from a cache. The difference
+between the authoritative TTL and the TTL here is due to aging of the
+data in a cache. The difference in ordering of the RRs in the answer
+section is not significant.
+
+6.2.2. QNAME=SRI-NIC.ARPA, QTYPE=*
+
+A query similar to the previous one, but using a QTYPE of *, would
+receive the following response from C.ISI.EDU:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE, AA |
+ +---------------------------------------------------+
+ Question | QNAME=SRI-NIC.ARPA., QCLASS=IN, QTYPE=* |
+ +---------------------------------------------------+
+ Answer | SRI-NIC.ARPA. 86400 IN A 26.0.0.73 |
+ | A 10.0.0.51 |
+ | MX 0 SRI-NIC.ARPA. |
+ | HINFO DEC-2060 TOPS20 |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 41]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+If a similar query was directed to two name servers which are not
+authoritative for SRI-NIC.ARPA, the responses might be:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE |
+ +---------------------------------------------------+
+ Question | QNAME=SRI-NIC.ARPA., QCLASS=IN, QTYPE=* |
+ +---------------------------------------------------+
+ Answer | SRI-NIC.ARPA. 12345 IN A 26.0.0.73 |
+ | A 10.0.0.51 |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+and
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE |
+ +---------------------------------------------------+
+ Question | QNAME=SRI-NIC.ARPA., QCLASS=IN, QTYPE=* |
+ +---------------------------------------------------+
+ Answer | SRI-NIC.ARPA. 1290 IN HINFO DEC-2060 TOPS20 |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+Neither of these answers have AA set, so neither response comes from
+authoritative data. The different contents and different TTLs suggest
+that the two servers cached data at different times, and that the first
+server cached the response to a QTYPE=A query and the second cached the
+response to a HINFO query.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 42]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+6.2.3. QNAME=SRI-NIC.ARPA, QTYPE=MX
+
+This type of query might be result from a mailer trying to look up
+routing information for the mail destination HOSTMASTER@SRI-NIC.ARPA.
+The response from C.ISI.EDU would be:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE, AA |
+ +---------------------------------------------------+
+ Question | QNAME=SRI-NIC.ARPA., QCLASS=IN, QTYPE=MX |
+ +---------------------------------------------------+
+ Answer | SRI-NIC.ARPA. 86400 IN MX 0 SRI-NIC.ARPA.|
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | SRI-NIC.ARPA. 86400 IN A 26.0.0.73 |
+ | A 10.0.0.51 |
+ +---------------------------------------------------+
+
+This response contains the MX RR in the answer section of the response.
+The additional section contains the address RRs because the name server
+at C.ISI.EDU guesses that the requester will need the addresses in order
+to properly use the information carried by the MX.
+
+6.2.4. QNAME=SRI-NIC.ARPA, QTYPE=NS
+
+C.ISI.EDU would reply to this query with:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE, AA |
+ +---------------------------------------------------+
+ Question | QNAME=SRI-NIC.ARPA., QCLASS=IN, QTYPE=NS |
+ +---------------------------------------------------+
+ Answer | <empty> |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+The only difference between the response and the query is the AA and
+RESPONSE bits in the header. The interpretation of this response is
+that the server is authoritative for the name, and the name exists, but
+no RRs of type NS are present there.
+
+6.2.5. QNAME=SIR-NIC.ARPA, QTYPE=A
+
+If a user mistyped a host name, we might see this type of query.
+
+
+
+Mockapetris [Page 43]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+C.ISI.EDU would answer it with:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE, AA, RCODE=NE |
+ +---------------------------------------------------+
+ Question | QNAME=SIR-NIC.ARPA., QCLASS=IN, QTYPE=A |
+ +---------------------------------------------------+
+ Answer | <empty> |
+ +---------------------------------------------------+
+ Authority | . SOA SRI-NIC.ARPA. HOSTMASTER.SRI-NIC.ARPA. |
+ | 870611 1800 300 604800 86400 |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+This response states that the name does not exist. This condition is
+signalled in the response code (RCODE) section of the header.
+
+The SOA RR in the authority section is the optional negative caching
+information which allows the resolver using this response to assume that
+the name will not exist for the SOA MINIMUM (86400) seconds.
+
+6.2.6. QNAME=BRL.MIL, QTYPE=A
+
+If this query is sent to C.ISI.EDU, the reply would be:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE |
+ +---------------------------------------------------+
+ Question | QNAME=BRL.MIL, QCLASS=IN, QTYPE=A |
+ +---------------------------------------------------+
+ Answer | <empty> |
+ +---------------------------------------------------+
+ Authority | MIL. 86400 IN NS SRI-NIC.ARPA. |
+ | 86400 NS A.ISI.EDU. |
+ +---------------------------------------------------+
+ Additional | A.ISI.EDU. A 26.3.0.103 |
+ | SRI-NIC.ARPA. A 26.0.0.73 |
+ | A 10.0.0.51 |
+ +---------------------------------------------------+
+
+This response has an empty answer section, but is not authoritative, so
+it is a referral. The name server on C.ISI.EDU, realizing that it is
+not authoritative for the MIL domain, has referred the requester to
+servers on A.ISI.EDU and SRI-NIC.ARPA, which it knows are authoritative
+for the MIL domain.
+
+
+
+
+
+Mockapetris [Page 44]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+6.2.7. QNAME=USC-ISIC.ARPA, QTYPE=A
+
+The response to this query from A.ISI.EDU would be:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE, AA |
+ +---------------------------------------------------+
+ Question | QNAME=USC-ISIC.ARPA., QCLASS=IN, QTYPE=A |
+ +---------------------------------------------------+
+ Answer | USC-ISIC.ARPA. 86400 IN CNAME C.ISI.EDU. |
+ | C.ISI.EDU. 86400 IN A 10.0.0.52 |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+Note that the AA bit in the header guarantees that the data matching
+QNAME is authoritative, but does not say anything about whether the data
+for C.ISI.EDU is authoritative. This complete reply is possible because
+A.ISI.EDU happens to be authoritative for both the ARPA domain where
+USC-ISIC.ARPA is found and the ISI.EDU domain where C.ISI.EDU data is
+found.
+
+If the same query was sent to C.ISI.EDU, its response might be the same
+as shown above if it had its own address in its cache, but might also
+be:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 45]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE, AA |
+ +---------------------------------------------------+
+ Question | QNAME=USC-ISIC.ARPA., QCLASS=IN, QTYPE=A |
+ +---------------------------------------------------+
+ Answer | USC-ISIC.ARPA. 86400 IN CNAME C.ISI.EDU. |
+ +---------------------------------------------------+
+ Authority | ISI.EDU. 172800 IN NS VAXA.ISI.EDU. |
+ | NS A.ISI.EDU. |
+ | NS VENERA.ISI.EDU. |
+ +---------------------------------------------------+
+ Additional | VAXA.ISI.EDU. 172800 A 10.2.0.27 |
+ | 172800 A 128.9.0.33 |
+ | VENERA.ISI.EDU. 172800 A 10.1.0.52 |
+ | 172800 A 128.9.0.32 |
+ | A.ISI.EDU. 172800 A 26.3.0.103 |
+ +---------------------------------------------------+
+
+This reply contains an authoritative reply for the alias USC-ISIC.ARPA,
+plus a referral to the name servers for ISI.EDU. This sort of reply
+isn't very likely given that the query is for the host name of the name
+server being asked, but would be common for other aliases.
+
+6.2.8. QNAME=USC-ISIC.ARPA, QTYPE=CNAME
+
+If this query is sent to either A.ISI.EDU or C.ISI.EDU, the reply would
+be:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE, AA |
+ +---------------------------------------------------+
+ Question | QNAME=USC-ISIC.ARPA., QCLASS=IN, QTYPE=A |
+ +---------------------------------------------------+
+ Answer | USC-ISIC.ARPA. 86400 IN CNAME C.ISI.EDU. |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+Because QTYPE=CNAME, the CNAME RR itself answers the query, and the name
+server doesn't attempt to look up anything for C.ISI.EDU. (Except
+possibly for the additional section.)
+
+6.3. Example resolution
+
+The following examples illustrate the operations a resolver must perform
+for its client. We assume that the resolver is starting without a
+
+
+
+Mockapetris [Page 46]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+cache, as might be the case after system boot. We further assume that
+the system is not one of the hosts in the data and that the host is
+located somewhere on net 26, and that its safety belt (SBELT) data
+structure has the following information:
+
+ Match count = -1
+ SRI-NIC.ARPA. 26.0.0.73 10.0.0.51
+ A.ISI.EDU. 26.3.0.103
+
+This information specifies servers to try, their addresses, and a match
+count of -1, which says that the servers aren't very close to the
+target. Note that the -1 isn't supposed to be an accurate closeness
+measure, just a value so that later stages of the algorithm will work.
+
+The following examples illustrate the use of a cache, so each example
+assumes that previous requests have completed.
+
+6.3.1. Resolve MX for ISI.EDU.
+
+Suppose the first request to the resolver comes from the local mailer,
+which has mail for PVM@ISI.EDU. The mailer might then ask for type MX
+RRs for the domain name ISI.EDU.
+
+The resolver would look in its cache for MX RRs at ISI.EDU, but the
+empty cache wouldn't be helpful. The resolver would recognize that it
+needed to query foreign servers and try to determine the best servers to
+query. This search would look for NS RRs for the domains ISI.EDU, EDU,
+and the root. These searches of the cache would also fail. As a last
+resort, the resolver would use the information from the SBELT, copying
+it into its SLIST structure.
+
+At this point the resolver would need to pick one of the three available
+addresses to try. Given that the resolver is on net 26, it should
+choose either 26.0.0.73 or 26.3.0.103 as its first choice. It would
+then send off a query of the form:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 47]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY |
+ +---------------------------------------------------+
+ Question | QNAME=ISI.EDU., QCLASS=IN, QTYPE=MX |
+ +---------------------------------------------------+
+ Answer | <empty> |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+The resolver would then wait for a response to its query or a timeout.
+If the timeout occurs, it would try different servers, then different
+addresses of the same servers, lastly retrying addresses already tried.
+It might eventually receive a reply from SRI-NIC.ARPA:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE |
+ +---------------------------------------------------+
+ Question | QNAME=ISI.EDU., QCLASS=IN, QTYPE=MX |
+ +---------------------------------------------------+
+ Answer | <empty> |
+ +---------------------------------------------------+
+ Authority | ISI.EDU. 172800 IN NS VAXA.ISI.EDU. |
+ | NS A.ISI.EDU. |
+ | NS VENERA.ISI.EDU.|
+ +---------------------------------------------------+
+ Additional | VAXA.ISI.EDU. 172800 A 10.2.0.27 |
+ | 172800 A 128.9.0.33 |
+ | VENERA.ISI.EDU. 172800 A 10.1.0.52 |
+ | 172800 A 128.9.0.32 |
+ | A.ISI.EDU. 172800 A 26.3.0.103 |
+ +---------------------------------------------------+
+
+The resolver would notice that the information in the response gave a
+closer delegation to ISI.EDU than its existing SLIST (since it matches
+three labels). The resolver would then cache the information in this
+response and use it to set up a new SLIST:
+
+ Match count = 3
+ A.ISI.EDU. 26.3.0.103
+ VAXA.ISI.EDU. 10.2.0.27 128.9.0.33
+ VENERA.ISI.EDU. 10.1.0.52 128.9.0.32
+
+A.ISI.EDU appears on this list as well as the previous one, but that is
+purely coincidental. The resolver would again start transmitting and
+waiting for responses. Eventually it would get an answer:
+
+
+
+Mockapetris [Page 48]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE, AA |
+ +---------------------------------------------------+
+ Question | QNAME=ISI.EDU., QCLASS=IN, QTYPE=MX |
+ +---------------------------------------------------+
+ Answer | ISI.EDU. MX 10 VENERA.ISI.EDU. |
+ | MX 20 VAXA.ISI.EDU. |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | VAXA.ISI.EDU. 172800 A 10.2.0.27 |
+ | 172800 A 128.9.0.33 |
+ | VENERA.ISI.EDU. 172800 A 10.1.0.52 |
+ | 172800 A 128.9.0.32 |
+ +---------------------------------------------------+
+
+The resolver would add this information to its cache, and return the MX
+RRs to its client.
+
+6.3.2. Get the host name for address 26.6.0.65
+
+The resolver would translate this into a request for PTR RRs for
+65.0.6.26.IN-ADDR.ARPA. This information is not in the cache, so the
+resolver would look for foreign servers to ask. No servers would match,
+so it would use SBELT again. (Note that the servers for the ISI.EDU
+domain are in the cache, but ISI.EDU is not an ancestor of
+65.0.6.26.IN-ADDR.ARPA, so the SBELT is used.)
+
+Since this request is within the authoritative data of both servers in
+SBELT, eventually one would return:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 49]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE, AA |
+ +---------------------------------------------------+
+ Question | QNAME=65.0.6.26.IN-ADDR.ARPA.,QCLASS=IN,QTYPE=PTR |
+ +---------------------------------------------------+
+ Answer | 65.0.6.26.IN-ADDR.ARPA. PTR ACC.ARPA. |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+6.3.3. Get the host address of poneria.ISI.EDU
+
+This request would translate into a type A request for poneria.ISI.EDU.
+The resolver would not find any cached data for this name, but would
+find the NS RRs in the cache for ISI.EDU when it looks for foreign
+servers to ask. Using this data, it would construct a SLIST of the
+form:
+
+ Match count = 3
+
+ A.ISI.EDU. 26.3.0.103
+ VAXA.ISI.EDU. 10.2.0.27 128.9.0.33
+ VENERA.ISI.EDU. 10.1.0.52
+
+A.ISI.EDU is listed first on the assumption that the resolver orders its
+choices by preference, and A.ISI.EDU is on the same network.
+
+One of these servers would answer the query.
+
+7. REFERENCES and BIBLIOGRAPHY
+
+[Dyer 87] Dyer, S., and F. Hsu, "Hesiod", Project Athena
+ Technical Plan - Name Service, April 1987, version 1.9.
+
+ Describes the fundamentals of the Hesiod name service.
+
+[IEN-116] J. Postel, "Internet Name Server", IEN-116,
+ USC/Information Sciences Institute, August 1979.
+
+ A name service obsoleted by the Domain Name System, but
+ still in use.
+
+
+
+
+
+
+
+
+Mockapetris [Page 50]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+[Quarterman 86] Quarterman, J., and J. Hoskins, "Notable Computer
+ Networks",Communications of the ACM, October 1986,
+ volume 29, number 10.
+
+[RFC-742] K. Harrenstien, "NAME/FINGER", RFC-742, Network
+ Information Center, SRI International, December 1977.
+
+[RFC-768] J. Postel, "User Datagram Protocol", RFC-768,
+ USC/Information Sciences Institute, August 1980.
+
+[RFC-793] J. Postel, "Transmission Control Protocol", RFC-793,
+ USC/Information Sciences Institute, September 1981.
+
+[RFC-799] D. Mills, "Internet Name Domains", RFC-799, COMSAT,
+ September 1981.
+
+ Suggests introduction of a hierarchy in place of a flat
+ name space for the Internet.
+
+[RFC-805] J. Postel, "Computer Mail Meeting Notes", RFC-805,
+ USC/Information Sciences Institute, February 1982.
+
+[RFC-810] E. Feinler, K. Harrenstien, Z. Su, and V. White, "DOD
+ Internet Host Table Specification", RFC-810, Network
+ Information Center, SRI International, March 1982.
+
+ Obsolete. See RFC-952.
+
+[RFC-811] K. Harrenstien, V. White, and E. Feinler, "Hostnames
+ Server", RFC-811, Network Information Center, SRI
+ International, March 1982.
+
+ Obsolete. See RFC-953.
+
+[RFC-812] K. Harrenstien, and V. White, "NICNAME/WHOIS", RFC-812,
+ Network Information Center, SRI International, March
+ 1982.
+
+[RFC-819] Z. Su, and J. Postel, "The Domain Naming Convention for
+ Internet User Applications", RFC-819, Network
+ Information Center, SRI International, August 1982.
+
+ Early thoughts on the design of the domain system.
+ Current implementation is completely different.
+
+[RFC-821] J. Postel, "Simple Mail Transfer Protocol", RFC-821,
+ USC/Information Sciences Institute, August 1980.
+
+
+
+
+Mockapetris [Page 51]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+[RFC-830] Z. Su, "A Distributed System for Internet Name Service",
+ RFC-830, Network Information Center, SRI International,
+ October 1982.
+
+ Early thoughts on the design of the domain system.
+ Current implementation is completely different.
+
+[RFC-882] P. Mockapetris, "Domain names - Concepts and
+ Facilities," RFC-882, USC/Information Sciences
+ Institute, November 1983.
+
+ Superceeded by this memo.
+
+[RFC-883] P. Mockapetris, "Domain names - Implementation and
+ Specification," RFC-883, USC/Information Sciences
+ Institute, November 1983.
+
+ Superceeded by this memo.
+
+[RFC-920] J. Postel and J. Reynolds, "Domain Requirements",
+ RFC-920, USC/Information Sciences Institute
+ October 1984.
+
+ Explains the naming scheme for top level domains.
+
+[RFC-952] K. Harrenstien, M. Stahl, E. Feinler, "DoD Internet Host
+ Table Specification", RFC-952, SRI, October 1985.
+
+ Specifies the format of HOSTS.TXT, the host/address
+ table replaced by the DNS.
+
+[RFC-953] K. Harrenstien, M. Stahl, E. Feinler, "HOSTNAME Server",
+ RFC-953, SRI, October 1985.
+
+ This RFC contains the official specification of the
+ hostname server protocol, which is obsoleted by the DNS.
+ This TCP based protocol accesses information stored in
+ the RFC-952 format, and is used to obtain copies of the
+ host table.
+
+[RFC-973] P. Mockapetris, "Domain System Changes and
+ Observations", RFC-973, USC/Information Sciences
+ Institute, January 1986.
+
+ Describes changes to RFC-882 and RFC-883 and reasons for
+ them. Now obsolete.
+
+
+
+
+
+Mockapetris [Page 52]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+[RFC-974] C. Partridge, "Mail routing and the domain system",
+ RFC-974, CSNET CIC BBN Labs, January 1986.
+
+ Describes the transition from HOSTS.TXT based mail
+ addressing to the more powerful MX system used with the
+ domain system.
+
+[RFC-1001] NetBIOS Working Group, "Protocol standard for a NetBIOS
+ service on a TCP/UDP transport: Concepts and Methods",
+ RFC-1001, March 1987.
+
+ This RFC and RFC-1002 are a preliminary design for
+ NETBIOS on top of TCP/IP which proposes to base NetBIOS
+ name service on top of the DNS.
+
+[RFC-1002] NetBIOS Working Group, "Protocol standard for a NetBIOS
+ service on a TCP/UDP transport: Detailed
+ Specifications", RFC-1002, March 1987.
+
+[RFC-1010] J. Reynolds and J. Postel, "Assigned Numbers", RFC-1010,
+ USC/Information Sciences Institute, May 1987
+
+ Contains socket numbers and mnemonics for host names,
+ operating systems, etc.
+
+[RFC-1031] W. Lazear, "MILNET Name Domain Transition", RFC-1031,
+ November 1987.
+
+ Describes a plan for converting the MILNET to the DNS.
+
+[RFC-1032] M. K. Stahl, "Establishing a Domain - Guidelines for
+ Administrators", RFC-1032, November 1987.
+
+ Describes the registration policies used by the NIC to
+ administer the top level domains and delegate subzones.
+
+[RFC-1033] M. K. Lottor, "Domain Administrators Operations Guide",
+ RFC-1033, November 1987.
+
+ A cookbook for domain administrators.
+
+[Solomon 82] M. Solomon, L. Landweber, and D. Neuhengen, "The CSNET
+ Name Server", Computer Networks, vol 6, nr 3, July 1982.
+
+ Describes a name service for CSNET which is independent
+ from the DNS and DNS use in the CSNET.
+
+
+
+
+
+Mockapetris [Page 53]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+Index
+
+ A 12
+ Absolute names 8
+ Aliases 14, 31
+ Authority 6
+ AXFR 17
+
+ Case of characters 7
+ CH 12
+ CNAME 12, 13, 31
+ Completion queries 18
+
+ Domain name 6, 7
+
+ Glue RRs 20
+
+ HINFO 12
+
+ IN 12
+ Inverse queries 16
+ Iterative 4
+
+ Label 7
+
+ Mailbox names 9
+ MX 12
+
+ Name error 27, 36
+ Name servers 5, 17
+ NE 30
+ Negative caching 44
+ NS 12
+
+ Opcode 16
+
+ PTR 12
+
+ QCLASS 16
+ QTYPE 16
+
+ RDATA 13
+ Recursive 4
+ Recursive service 22
+ Relative names 7
+ Resolvers 6
+ RR 12
+
+
+
+
+Mockapetris [Page 54]
+
+RFC 1034 Domain Concepts and Facilities November 1987
+
+
+ Safety belt 33
+ Sections 16
+ SOA 12
+ Standard queries 22
+
+ Status queries 18
+ Stub resolvers 32
+
+ TTL 12, 13
+
+ Wildcards 25
+
+ Zone transfers 28
+ Zones 19
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 55]
+
diff --git a/doc/rfc/rfc1035.txt b/doc/rfc/rfc1035.txt
new file mode 100644
index 0000000..b1a9bf5
--- /dev/null
+++ b/doc/rfc/rfc1035.txt
@@ -0,0 +1,3077 @@
+Network Working Group P. Mockapetris
+Request for Comments: 1035 ISI
+ November 1987
+Obsoletes: RFCs 882, 883, 973
+
+ DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION
+
+
+1. STATUS OF THIS MEMO
+
+This RFC describes the details of the domain system and protocol, and
+assumes that the reader is familiar with the concepts discussed in a
+companion RFC, "Domain Names - Concepts and Facilities" [RFC-1034].
+
+The domain system is a mixture of functions and data types which are an
+official protocol and functions and data types which are still
+experimental. Since the domain system is intentionally extensible, new
+data types and experimental behavior should always be expected in parts
+of the system beyond the official protocol. The official protocol parts
+include standard queries, responses and the Internet class RR data
+formats (e.g., host addresses). Since the previous RFC set, several
+definitions have changed, so some previous definitions are obsolete.
+
+Experimental or obsolete features are clearly marked in these RFCs, and
+such information should be used with caution.
+
+The reader is especially cautioned not to depend on the values which
+appear in examples to be current or complete, since their purpose is
+primarily pedagogical. Distribution of this memo is unlimited.
+
+ Table of Contents
+
+ 1. STATUS OF THIS MEMO 1
+ 2. INTRODUCTION 3
+ 2.1. Overview 3
+ 2.2. Common configurations 4
+ 2.3. Conventions 7
+ 2.3.1. Preferred name syntax 7
+ 2.3.2. Data Transmission Order 8
+ 2.3.3. Character Case 9
+ 2.3.4. Size limits 10
+ 3. DOMAIN NAME SPACE AND RR DEFINITIONS 10
+ 3.1. Name space definitions 10
+ 3.2. RR definitions 11
+ 3.2.1. Format 11
+ 3.2.2. TYPE values 12
+ 3.2.3. QTYPE values 12
+ 3.2.4. CLASS values 13
+
+
+
+Mockapetris [Page 1]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 3.2.5. QCLASS values 13
+ 3.3. Standard RRs 13
+ 3.3.1. CNAME RDATA format 14
+ 3.3.2. HINFO RDATA format 14
+ 3.3.3. MB RDATA format (EXPERIMENTAL) 14
+ 3.3.4. MD RDATA format (Obsolete) 15
+ 3.3.5. MF RDATA format (Obsolete) 15
+ 3.3.6. MG RDATA format (EXPERIMENTAL) 16
+ 3.3.7. MINFO RDATA format (EXPERIMENTAL) 16
+ 3.3.8. MR RDATA format (EXPERIMENTAL) 17
+ 3.3.9. MX RDATA format 17
+ 3.3.10. NULL RDATA format (EXPERIMENTAL) 17
+ 3.3.11. NS RDATA format 18
+ 3.3.12. PTR RDATA format 18
+ 3.3.13. SOA RDATA format 19
+ 3.3.14. TXT RDATA format 20
+ 3.4. ARPA Internet specific RRs 20
+ 3.4.1. A RDATA format 20
+ 3.4.2. WKS RDATA format 21
+ 3.5. IN-ADDR.ARPA domain 22
+ 3.6. Defining new types, classes, and special namespaces 24
+ 4. MESSAGES 25
+ 4.1. Format 25
+ 4.1.1. Header section format 26
+ 4.1.2. Question section format 28
+ 4.1.3. Resource record format 29
+ 4.1.4. Message compression 30
+ 4.2. Transport 32
+ 4.2.1. UDP usage 32
+ 4.2.2. TCP usage 32
+ 5. MASTER FILES 33
+ 5.1. Format 33
+ 5.2. Use of master files to define zones 35
+ 5.3. Master file example 36
+ 6. NAME SERVER IMPLEMENTATION 37
+ 6.1. Architecture 37
+ 6.1.1. Control 37
+ 6.1.2. Database 37
+ 6.1.3. Time 39
+ 6.2. Standard query processing 39
+ 6.3. Zone refresh and reload processing 39
+ 6.4. Inverse queries (Optional) 40
+ 6.4.1. The contents of inverse queries and responses 40
+ 6.4.2. Inverse query and response example 41
+ 6.4.3. Inverse query processing 42
+
+
+
+
+
+
+Mockapetris [Page 2]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 6.5. Completion queries and responses 42
+ 7. RESOLVER IMPLEMENTATION 43
+ 7.1. Transforming a user request into a query 43
+ 7.2. Sending the queries 44
+ 7.3. Processing responses 46
+ 7.4. Using the cache 47
+ 8. MAIL SUPPORT 47
+ 8.1. Mail exchange binding 48
+ 8.2. Mailbox binding (Experimental) 48
+ 9. REFERENCES and BIBLIOGRAPHY 50
+ Index 54
+
+2. INTRODUCTION
+
+2.1. Overview
+
+The goal of domain names is to provide a mechanism for naming resources
+in such a way that the names are usable in different hosts, networks,
+protocol families, internets, and administrative organizations.
+
+From the user's point of view, domain names are useful as arguments to a
+local agent, called a resolver, which retrieves information associated
+with the domain name. Thus a user might ask for the host address or
+mail information associated with a particular domain name. To enable
+the user to request a particular type of information, an appropriate
+query type is passed to the resolver with the domain name. To the user,
+the domain tree is a single information space; the resolver is
+responsible for hiding the distribution of data among name servers from
+the user.
+
+From the resolver's point of view, the database that makes up the domain
+space is distributed among various name servers. Different parts of the
+domain space are stored in different name servers, although a particular
+data item will be stored redundantly in two or more name servers. The
+resolver starts with knowledge of at least one name server. When the
+resolver processes a user query it asks a known name server for the
+information; in return, the resolver either receives the desired
+information or a referral to another name server. Using these
+referrals, resolvers learn the identities and contents of other name
+servers. Resolvers are responsible for dealing with the distribution of
+the domain space and dealing with the effects of name server failure by
+consulting redundant databases in other servers.
+
+Name servers manage two kinds of data. The first kind of data held in
+sets called zones; each zone is the complete database for a particular
+"pruned" subtree of the domain space. This data is called
+authoritative. A name server periodically checks to make sure that its
+zones are up to date, and if not, obtains a new copy of updated zones
+
+
+
+Mockapetris [Page 3]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+from master files stored locally or in another name server. The second
+kind of data is cached data which was acquired by a local resolver.
+This data may be incomplete, but improves the performance of the
+retrieval process when non-local data is repeatedly accessed. Cached
+data is eventually discarded by a timeout mechanism.
+
+This functional structure isolates the problems of user interface,
+failure recovery, and distribution in the resolvers and isolates the
+database update and refresh problems in the name servers.
+
+2.2. Common configurations
+
+A host can participate in the domain name system in a number of ways,
+depending on whether the host runs programs that retrieve information
+from the domain system, name servers that answer queries from other
+hosts, or various combinations of both functions. The simplest, and
+perhaps most typical, configuration is shown below:
+
+ Local Host | Foreign
+ |
+ +---------+ +----------+ | +--------+
+ | | user queries | |queries | | |
+ | User |-------------->| |---------|->|Foreign |
+ | Program | | Resolver | | | Name |
+ | |<--------------| |<--------|--| Server |
+ | | user responses| |responses| | |
+ +---------+ +----------+ | +--------+
+ | A |
+ cache additions | | references |
+ V | |
+ +----------+ |
+ | cache | |
+ +----------+ |
+
+User programs interact with the domain name space through resolvers; the
+format of user queries and user responses is specific to the host and
+its operating system. User queries will typically be operating system
+calls, and the resolver and its cache will be part of the host operating
+system. Less capable hosts may choose to implement the resolver as a
+subroutine to be linked in with every program that needs its services.
+Resolvers answer user queries with information they acquire via queries
+to foreign name servers and the local cache.
+
+Note that the resolver may have to make several queries to several
+different foreign name servers to answer a particular user query, and
+hence the resolution of a user query may involve several network
+accesses and an arbitrary amount of time. The queries to foreign name
+servers and the corresponding responses have a standard format described
+
+
+
+Mockapetris [Page 4]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+in this memo, and may be datagrams.
+
+Depending on its capabilities, a name server could be a stand alone
+program on a dedicated machine or a process or processes on a large
+timeshared host. A simple configuration might be:
+
+ Local Host | Foreign
+ |
+ +---------+ |
+ / /| |
+ +---------+ | +----------+ | +--------+
+ | | | | |responses| | |
+ | | | | Name |---------|->|Foreign |
+ | Master |-------------->| Server | | |Resolver|
+ | files | | | |<--------|--| |
+ | |/ | | queries | +--------+
+ +---------+ +----------+ |
+
+Here a primary name server acquires information about one or more zones
+by reading master files from its local file system, and answers queries
+about those zones that arrive from foreign resolvers.
+
+The DNS requires that all zones be redundantly supported by more than
+one name server. Designated secondary servers can acquire zones and
+check for updates from the primary server using the zone transfer
+protocol of the DNS. This configuration is shown below:
+
+ Local Host | Foreign
+ |
+ +---------+ |
+ / /| |
+ +---------+ | +----------+ | +--------+
+ | | | | |responses| | |
+ | | | | Name |---------|->|Foreign |
+ | Master |-------------->| Server | | |Resolver|
+ | files | | | |<--------|--| |
+ | |/ | | queries | +--------+
+ +---------+ +----------+ |
+ A |maintenance | +--------+
+ | +------------|->| |
+ | queries | |Foreign |
+ | | | Name |
+ +------------------|--| Server |
+ maintenance responses | +--------+
+
+In this configuration, the name server periodically establishes a
+virtual circuit to a foreign name server to acquire a copy of a zone or
+to check that an existing copy has not changed. The messages sent for
+
+
+
+Mockapetris [Page 5]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+these maintenance activities follow the same form as queries and
+responses, but the message sequences are somewhat different.
+
+The information flow in a host that supports all aspects of the domain
+name system is shown below:
+
+ Local Host | Foreign
+ |
+ +---------+ +----------+ | +--------+
+ | | user queries | |queries | | |
+ | User |-------------->| |---------|->|Foreign |
+ | Program | | Resolver | | | Name |
+ | |<--------------| |<--------|--| Server |
+ | | user responses| |responses| | |
+ +---------+ +----------+ | +--------+
+ | A |
+ cache additions | | references |
+ V | |
+ +----------+ |
+ | Shared | |
+ | database | |
+ +----------+ |
+ A | |
+ +---------+ refreshes | | references |
+ / /| | V |
+ +---------+ | +----------+ | +--------+
+ | | | | |responses| | |
+ | | | | Name |---------|->|Foreign |
+ | Master |-------------->| Server | | |Resolver|
+ | files | | | |<--------|--| |
+ | |/ | | queries | +--------+
+ +---------+ +----------+ |
+ A |maintenance | +--------+
+ | +------------|->| |
+ | queries | |Foreign |
+ | | | Name |
+ +------------------|--| Server |
+ maintenance responses | +--------+
+
+The shared database holds domain space data for the local name server
+and resolver. The contents of the shared database will typically be a
+mixture of authoritative data maintained by the periodic refresh
+operations of the name server and cached data from previous resolver
+requests. The structure of the domain data and the necessity for
+synchronization between name servers and resolvers imply the general
+characteristics of this database, but the actual format is up to the
+local implementor.
+
+
+
+
+Mockapetris [Page 6]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+Information flow can also be tailored so that a group of hosts act
+together to optimize activities. Sometimes this is done to offload less
+capable hosts so that they do not have to implement a full resolver.
+This can be appropriate for PCs or hosts which want to minimize the
+amount of new network code which is required. This scheme can also
+allow a group of hosts can share a small number of caches rather than
+maintaining a large number of separate caches, on the premise that the
+centralized caches will have a higher hit ratio. In either case,
+resolvers are replaced with stub resolvers which act as front ends to
+resolvers located in a recursive server in one or more name servers
+known to perform that service:
+
+ Local Hosts | Foreign
+ |
+ +---------+ |
+ | | responses |
+ | Stub |<--------------------+ |
+ | Resolver| | |
+ | |----------------+ | |
+ +---------+ recursive | | |
+ queries | | |
+ V | |
+ +---------+ recursive +----------+ | +--------+
+ | | queries | |queries | | |
+ | Stub |-------------->| Recursive|---------|->|Foreign |
+ | Resolver| | Server | | | Name |
+ | |<--------------| |<--------|--| Server |
+ +---------+ responses | |responses| | |
+ +----------+ | +--------+
+ | Central | |
+ | cache | |
+ +----------+ |
+
+In any case, note that domain components are always replicated for
+reliability whenever possible.
+
+2.3. Conventions
+
+The domain system has several conventions dealing with low-level, but
+fundamental, issues. While the implementor is free to violate these
+conventions WITHIN HIS OWN SYSTEM, he must observe these conventions in
+ALL behavior observed from other hosts.
+
+2.3.1. Preferred name syntax
+
+The DNS specifications attempt to be as general as possible in the rules
+for constructing domain names. The idea is that the name of any
+existing object can be expressed as a domain name with minimal changes.
+
+
+
+Mockapetris [Page 7]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+However, when assigning a domain name for an object, the prudent user
+will select a name which satisfies both the rules of the domain system
+and any existing rules for the object, whether these rules are published
+or implied by existing programs.
+
+For example, when naming a mail domain, the user should satisfy both the
+rules of this memo and those in RFC-822. When creating a new host name,
+the old rules for HOSTS.TXT should be followed. This avoids problems
+when old software is converted to use domain names.
+
+The following syntax will result in fewer problems with many
+
+applications that use domain names (e.g., mail, TELNET).
+
+<domain> ::= <subdomain> | " "
+
+<subdomain> ::= <label> | <subdomain> "." <label>
+
+<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
+
+<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+
+<let-dig-hyp> ::= <let-dig> | "-"
+
+<let-dig> ::= <letter> | <digit>
+
+<letter> ::= any one of the 52 alphabetic characters A through Z in
+upper case and a through z in lower case
+
+<digit> ::= any one of the ten digits 0 through 9
+
+Note that while upper and lower case letters are allowed in domain
+names, no significance is attached to the case. That is, two names with
+the same spelling but different case are to be treated as if identical.
+
+The labels must follow the rules for ARPANET host names. They must
+start with a letter, end with a letter or digit, and have as interior
+characters only letters, digits, and hyphen. There are also some
+restrictions on the length. Labels must be 63 characters or less.
+
+For example, the following strings identify hosts in the Internet:
+
+A.ISI.EDU XX.LCS.MIT.EDU SRI-NIC.ARPA
+
+2.3.2. Data Transmission Order
+
+The order of transmission of the header and data described in this
+document is resolved to the octet level. Whenever a diagram shows a
+
+
+
+Mockapetris [Page 8]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+group of octets, the order of transmission of those octets is the normal
+order in which they are read in English. For example, in the following
+diagram, the octets are transmitted in the order they are numbered.
+
+ 0 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 1 | 2 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 3 | 4 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 5 | 6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+Whenever an octet represents a numeric quantity, the left most bit in
+the diagram is the high order or most significant bit. That is, the bit
+labeled 0 is the most significant bit. For example, the following
+diagram represents the value 170 (decimal).
+
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ |1 0 1 0 1 0 1 0|
+ +-+-+-+-+-+-+-+-+
+
+Similarly, whenever a multi-octet field represents a numeric quantity
+the left most bit of the whole field is the most significant bit. When
+a multi-octet quantity is transmitted the most significant octet is
+transmitted first.
+
+2.3.3. Character Case
+
+For all parts of the DNS that are part of the official protocol, all
+comparisons between character strings (e.g., labels, domain names, etc.)
+are done in a case-insensitive manner. At present, this rule is in
+force throughout the domain system without exception. However, future
+additions beyond current usage may need to use the full binary octet
+capabilities in names, so attempts to store domain names in 7-bit ASCII
+or use of special bytes to terminate labels, etc., should be avoided.
+
+When data enters the domain system, its original case should be
+preserved whenever possible. In certain circumstances this cannot be
+done. For example, if two RRs are stored in a database, one at x.y and
+one at X.Y, they are actually stored at the same place in the database,
+and hence only one casing would be preserved. The basic rule is that
+case can be discarded only when data is used to define structure in a
+database, and two names are identical when compared in a case
+insensitive manner.
+
+
+
+
+Mockapetris [Page 9]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+Loss of case sensitive data must be minimized. Thus while data for x.y
+and X.Y may both be stored under a single location x.y or X.Y, data for
+a.x and B.X would never be stored under A.x, A.X, b.x, or b.X. In
+general, this preserves the case of the first label of a domain name,
+but forces standardization of interior node labels.
+
+Systems administrators who enter data into the domain database should
+take care to represent the data they supply to the domain system in a
+case-consistent manner if their system is case-sensitive. The data
+distribution system in the domain system will ensure that consistent
+representations are preserved.
+
+2.3.4. Size limits
+
+Various objects and parameters in the DNS have size limits. They are
+listed below. Some could be easily changed, others are more
+fundamental.
+
+labels 63 octets or less
+
+names 255 octets or less
+
+TTL positive values of a signed 32 bit number.
+
+UDP messages 512 octets or less
+
+3. DOMAIN NAME SPACE AND RR DEFINITIONS
+
+3.1. Name space definitions
+
+Domain names in messages are expressed in terms of a sequence of labels.
+Each label is represented as a one octet length field followed by that
+number of octets. Since every domain name ends with the null label of
+the root, a domain name is terminated by a length byte of zero. The
+high order two bits of every length octet must be zero, and the
+remaining six bits of the length field limit the label to 63 octets or
+less.
+
+To simplify implementations, the total length of a domain name (i.e.,
+label octets and label length octets) is restricted to 255 octets or
+less.
+
+Although labels can contain any 8 bit values in octets that make up a
+label, it is strongly recommended that labels follow the preferred
+syntax described elsewhere in this memo, which is compatible with
+existing host naming conventions. Name servers and resolvers must
+compare labels in a case-insensitive manner (i.e., A=a), assuming ASCII
+with zero parity. Non-alphabetic codes must match exactly.
+
+
+
+Mockapetris [Page 10]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.2. RR definitions
+
+3.2.1. Format
+
+All RRs have the same top level format shown below:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / /
+ / NAME /
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | CLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TTL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RDLENGTH |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+ / RDATA /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+
+where:
+
+NAME an owner name, i.e., the name of the node to which this
+ resource record pertains.
+
+TYPE two octets containing one of the RR TYPE codes.
+
+CLASS two octets containing one of the RR CLASS codes.
+
+TTL a 32 bit signed integer that specifies the time interval
+ that the resource record may be cached before the source
+ of the information should again be consulted. Zero
+ values are interpreted to mean that the RR can only be
+ used for the transaction in progress, and should not be
+ cached. For example, SOA records are always distributed
+ with a zero TTL to prohibit caching. Zero values can
+ also be used for extremely volatile data.
+
+RDLENGTH an unsigned 16 bit integer that specifies the length in
+ octets of the RDATA field.
+
+
+
+Mockapetris [Page 11]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+RDATA a variable length string of octets that describes the
+ resource. The format of this information varies
+ according to the TYPE and CLASS of the resource record.
+
+3.2.2. TYPE values
+
+TYPE fields are used in resource records. Note that these types are a
+subset of QTYPEs.
+
+TYPE value and meaning
+
+A 1 a host address
+
+NS 2 an authoritative name server
+
+MD 3 a mail destination (Obsolete - use MX)
+
+MF 4 a mail forwarder (Obsolete - use MX)
+
+CNAME 5 the canonical name for an alias
+
+SOA 6 marks the start of a zone of authority
+
+MB 7 a mailbox domain name (EXPERIMENTAL)
+
+MG 8 a mail group member (EXPERIMENTAL)
+
+MR 9 a mail rename domain name (EXPERIMENTAL)
+
+NULL 10 a null RR (EXPERIMENTAL)
+
+WKS 11 a well known service description
+
+PTR 12 a domain name pointer
+
+HINFO 13 host information
+
+MINFO 14 mailbox or mail list information
+
+MX 15 mail exchange
+
+TXT 16 text strings
+
+3.2.3. QTYPE values
+
+QTYPE fields appear in the question part of a query. QTYPES are a
+superset of TYPEs, hence all TYPEs are valid QTYPEs. In addition, the
+following QTYPEs are defined:
+
+
+
+Mockapetris [Page 12]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+AXFR 252 A request for a transfer of an entire zone
+
+MAILB 253 A request for mailbox-related records (MB, MG or MR)
+
+MAILA 254 A request for mail agent RRs (Obsolete - see MX)
+
+* 255 A request for all records
+
+3.2.4. CLASS values
+
+CLASS fields appear in resource records. The following CLASS mnemonics
+and values are defined:
+
+IN 1 the Internet
+
+CS 2 the CSNET class (Obsolete - used only for examples in
+ some obsolete RFCs)
+
+CH 3 the CHAOS class
+
+HS 4 Hesiod [Dyer 87]
+
+3.2.5. QCLASS values
+
+QCLASS fields appear in the question section of a query. QCLASS values
+are a superset of CLASS values; every CLASS is a valid QCLASS. In
+addition to CLASS values, the following QCLASSes are defined:
+
+* 255 any class
+
+3.3. Standard RRs
+
+The following RR definitions are expected to occur, at least
+potentially, in all classes. In particular, NS, SOA, CNAME, and PTR
+will be used in all classes, and have the same format in all classes.
+Because their RDATA format is known, all domain names in the RDATA
+section of these RRs may be compressed.
+
+<domain-name> is a domain name represented as a series of labels, and
+terminated by a label with zero length. <character-string> is a single
+length octet followed by that number of characters. <character-string>
+is treated as binary information, and can be up to 256 characters in
+length (including the length octet).
+
+
+
+
+
+
+
+
+Mockapetris [Page 13]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.1. CNAME RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / CNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+CNAME A <domain-name> which specifies the canonical or primary
+ name for the owner. The owner name is an alias.
+
+CNAME RRs cause no additional section processing, but name servers may
+choose to restart the query at the canonical name in certain cases. See
+the description of name server logic in [RFC-1034] for details.
+
+3.3.2. HINFO RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / CPU /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / OS /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+CPU A <character-string> which specifies the CPU type.
+
+OS A <character-string> which specifies the operating
+ system type.
+
+Standard values for CPU and OS can be found in [RFC-1010].
+
+HINFO records are used to acquire general information about a host. The
+main use is for protocols such as FTP that can use special procedures
+when talking between machines or operating systems of the same type.
+
+3.3.3. MB RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MADNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MADNAME A <domain-name> which specifies a host which has the
+ specified mailbox.
+
+
+
+Mockapetris [Page 14]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+MB records cause additional section processing which looks up an A type
+RRs corresponding to MADNAME.
+
+3.3.4. MD RDATA format (Obsolete)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MADNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MADNAME A <domain-name> which specifies a host which has a mail
+ agent for the domain which should be able to deliver
+ mail for the domain.
+
+MD records cause additional section processing which looks up an A type
+record corresponding to MADNAME.
+
+MD is obsolete. See the definition of MX and [RFC-974] for details of
+the new scheme. The recommended policy for dealing with MD RRs found in
+a master file is to reject them, or to convert them to MX RRs with a
+preference of 0.
+
+3.3.5. MF RDATA format (Obsolete)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MADNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MADNAME A <domain-name> which specifies a host which has a mail
+ agent for the domain which will accept mail for
+ forwarding to the domain.
+
+MF records cause additional section processing which looks up an A type
+record corresponding to MADNAME.
+
+MF is obsolete. See the definition of MX and [RFC-974] for details ofw
+the new scheme. The recommended policy for dealing with MD RRs found in
+a master file is to reject them, or to convert them to MX RRs with a
+preference of 10.
+
+
+
+
+
+
+
+Mockapetris [Page 15]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.6. MG RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MGMNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MGMNAME A <domain-name> which specifies a mailbox which is a
+ member of the mail group specified by the domain name.
+
+MG records cause no additional section processing.
+
+3.3.7. MINFO RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / RMAILBX /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / EMAILBX /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+RMAILBX A <domain-name> which specifies a mailbox which is
+ responsible for the mailing list or mailbox. If this
+ domain name names the root, the owner of the MINFO RR is
+ responsible for itself. Note that many existing mailing
+ lists use a mailbox X-request for the RMAILBX field of
+ mailing list X, e.g., Msgroup-request for Msgroup. This
+ field provides a more general mechanism.
+
+
+EMAILBX A <domain-name> which specifies a mailbox which is to
+ receive error messages related to the mailing list or
+ mailbox specified by the owner of the MINFO RR (similar
+ to the ERRORS-TO: field which has been proposed). If
+ this domain name names the root, errors should be
+ returned to the sender of the message.
+
+MINFO records cause no additional section processing. Although these
+records can be associated with a simple mailbox, they are usually used
+with a mailing list.
+
+
+
+
+
+
+
+
+Mockapetris [Page 16]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.8. MR RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / NEWNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+NEWNAME A <domain-name> which specifies a mailbox which is the
+ proper rename of the specified mailbox.
+
+MR records cause no additional section processing. The main use for MR
+is as a forwarding entry for a user who has moved to a different
+mailbox.
+
+3.3.9. MX RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PREFERENCE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / EXCHANGE /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+PREFERENCE A 16 bit integer which specifies the preference given to
+ this RR among others at the same owner. Lower values
+ are preferred.
+
+EXCHANGE A <domain-name> which specifies a host willing to act as
+ a mail exchange for the owner name.
+
+MX records cause type A additional section processing for the host
+specified by EXCHANGE. The use of MX RRs is explained in detail in
+[RFC-974].
+
+3.3.10. NULL RDATA format (EXPERIMENTAL)
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / <anything> /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+Anything at all may be in the RDATA field so long as it is 65535 octets
+or less.
+
+
+
+
+Mockapetris [Page 17]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+NULL records cause no additional section processing. NULL RRs are not
+allowed in master files. NULLs are used as placeholders in some
+experimental extensions of the DNS.
+
+3.3.11. NS RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / NSDNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+NSDNAME A <domain-name> which specifies a host which should be
+ authoritative for the specified class and domain.
+
+NS records cause both the usual additional section processing to locate
+a type A record, and, when used in a referral, a special search of the
+zone in which they reside for glue information.
+
+The NS RR states that the named host should be expected to have a zone
+starting at owner name of the specified class. Note that the class may
+not indicate the protocol family which should be used to communicate
+with the host, although it is typically a strong hint. For example,
+hosts which are name servers for either Internet (IN) or Hesiod (HS)
+class information are normally queried using IN class protocols.
+
+3.3.12. PTR RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / PTRDNAME /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+PTRDNAME A <domain-name> which points to some location in the
+ domain name space.
+
+PTR records cause no additional section processing. These RRs are used
+in special domains to point to some other location in the domain space.
+These records are simple data, and don't imply any special processing
+similar to that performed by CNAME, which identifies aliases. See the
+description of the IN-ADDR.ARPA domain for an example.
+
+
+
+
+
+
+
+
+Mockapetris [Page 18]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.3.13. SOA RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / RNAME /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | SERIAL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | REFRESH |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RETRY |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | EXPIRE |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | MINIMUM |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+MNAME The <domain-name> of the name server that was the
+ original or primary source of data for this zone.
+
+RNAME A <domain-name> which specifies the mailbox of the
+ person responsible for this zone.
+
+SERIAL The unsigned 32 bit version number of the original copy
+ of the zone. Zone transfers preserve this value. This
+ value wraps and should be compared using sequence space
+ arithmetic.
+
+REFRESH A 32 bit time interval before the zone should be
+ refreshed.
+
+RETRY A 32 bit time interval that should elapse before a
+ failed refresh should be retried.
+
+EXPIRE A 32 bit time value that specifies the upper limit on
+ the time interval that can elapse before the zone is no
+ longer authoritative.
+
+
+
+
+
+Mockapetris [Page 19]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+MINIMUM The unsigned 32 bit minimum TTL field that should be
+ exported with any RR from this zone.
+
+SOA records cause no additional section processing.
+
+All times are in units of seconds.
+
+Most of these fields are pertinent only for name server maintenance
+operations. However, MINIMUM is used in all query operations that
+retrieve RRs from a zone. Whenever a RR is sent in a response to a
+query, the TTL field is set to the maximum of the TTL field from the RR
+and the MINIMUM field in the appropriate SOA. Thus MINIMUM is a lower
+bound on the TTL field for all RRs in a zone. Note that this use of
+MINIMUM should occur when the RRs are copied into the response and not
+when the zone is loaded from a master file or via a zone transfer. The
+reason for this provison is to allow future dynamic update facilities to
+change the SOA RR with known semantics.
+
+
+3.3.14. TXT RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / TXT-DATA /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+TXT-DATA One or more <character-string>s.
+
+TXT RRs are used to hold descriptive text. The semantics of the text
+depends on the domain where it is found.
+
+3.4. Internet specific RRs
+
+3.4.1. A RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ADDRESS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+ADDRESS A 32 bit Internet address.
+
+Hosts that have multiple Internet addresses will have multiple A
+records.
+
+
+
+
+
+Mockapetris [Page 20]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+A records cause no additional section processing. The RDATA section of
+an A line in a master file is an Internet address expressed as four
+decimal numbers separated by dots without any imbedded spaces (e.g.,
+"10.2.0.52" or "192.0.5.6").
+
+3.4.2. WKS RDATA format
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ADDRESS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PROTOCOL | |
+ +--+--+--+--+--+--+--+--+ |
+ | |
+ / <BIT MAP> /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+ADDRESS An 32 bit Internet address
+
+PROTOCOL An 8 bit IP protocol number
+
+<BIT MAP> A variable length bit map. The bit map must be a
+ multiple of 8 bits long.
+
+The WKS record is used to describe the well known services supported by
+a particular protocol on a particular internet address. The PROTOCOL
+field specifies an IP protocol number, and the bit map has one bit per
+port of the specified protocol. The first bit corresponds to port 0,
+the second to port 1, etc. If the bit map does not include a bit for a
+protocol of interest, that bit is assumed zero. The appropriate values
+and mnemonics for ports and protocols are specified in [RFC-1010].
+
+For example, if PROTOCOL=TCP (6), the 26th bit corresponds to TCP port
+25 (SMTP). If this bit is set, a SMTP server should be listening on TCP
+port 25; if zero, SMTP service is not supported on the specified
+address.
+
+The purpose of WKS RRs is to provide availability information for
+servers for TCP and UDP. If a server supports both TCP and UDP, or has
+multiple Internet addresses, then multiple WKS RRs are used.
+
+WKS RRs cause no additional section processing.
+
+In master files, both ports and protocols are expressed using mnemonics
+or decimal numbers.
+
+
+
+
+Mockapetris [Page 21]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.5. IN-ADDR.ARPA domain
+
+The Internet uses a special domain to support gateway location and
+Internet address to host mapping. Other classes may employ a similar
+strategy in other domains. The intent of this domain is to provide a
+guaranteed method to perform host address to host name mapping, and to
+facilitate queries to locate all gateways on a particular network in the
+Internet.
+
+Note that both of these services are similar to functions that could be
+performed by inverse queries; the difference is that this part of the
+domain name space is structured according to address, and hence can
+guarantee that the appropriate data can be located without an exhaustive
+search of the domain space.
+
+The domain begins at IN-ADDR.ARPA and has a substructure which follows
+the Internet addressing structure.
+
+Domain names in the IN-ADDR.ARPA domain are defined to have up to four
+labels in addition to the IN-ADDR.ARPA suffix. Each label represents
+one octet of an Internet address, and is expressed as a character string
+for a decimal value in the range 0-255 (with leading zeros omitted
+except in the case of a zero octet which is represented by a single
+zero).
+
+Host addresses are represented by domain names that have all four labels
+specified. Thus data for Internet address 10.2.0.52 is located at
+domain name 52.0.2.10.IN-ADDR.ARPA. The reversal, though awkward to
+read, allows zones to be delegated which are exactly one network of
+address space. For example, 10.IN-ADDR.ARPA can be a zone containing
+data for the ARPANET, while 26.IN-ADDR.ARPA can be a separate zone for
+MILNET. Address nodes are used to hold pointers to primary host names
+in the normal domain space.
+
+Network numbers correspond to some non-terminal nodes at various depths
+in the IN-ADDR.ARPA domain, since Internet network numbers are either 1,
+2, or 3 octets. Network nodes are used to hold pointers to the primary
+host names of gateways attached to that network. Since a gateway is, by
+definition, on more than one network, it will typically have two or more
+network nodes which point at it. Gateways will also have host level
+pointers at their fully qualified addresses.
+
+Both the gateway pointers at network nodes and the normal host pointers
+at full address nodes use the PTR RR to point back to the primary domain
+names of the corresponding hosts.
+
+For example, the IN-ADDR.ARPA domain will contain information about the
+ISI gateway between net 10 and 26, an MIT gateway from net 10 to MIT's
+
+
+
+Mockapetris [Page 22]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+net 18, and hosts A.ISI.EDU and MULTICS.MIT.EDU. Assuming that ISI
+gateway has addresses 10.2.0.22 and 26.0.0.103, and a name MILNET-
+GW.ISI.EDU, and the MIT gateway has addresses 10.0.0.77 and 18.10.0.4
+and a name GW.LCS.MIT.EDU, the domain database would contain:
+
+ 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 22.0.2.10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 103.0.0.26.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 77.0.0.10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 4.0.10.18.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+ 103.0.3.26.IN-ADDR.ARPA. PTR A.ISI.EDU.
+ 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU.
+
+Thus a program which wanted to locate gateways on net 10 would originate
+a query of the form QTYPE=PTR, QCLASS=IN, QNAME=10.IN-ADDR.ARPA. It
+would receive two RRs in response:
+
+ 10.IN-ADDR.ARPA. PTR MILNET-GW.ISI.EDU.
+ 10.IN-ADDR.ARPA. PTR GW.LCS.MIT.EDU.
+
+The program could then originate QTYPE=A, QCLASS=IN queries for MILNET-
+GW.ISI.EDU. and GW.LCS.MIT.EDU. to discover the Internet addresses of
+these gateways.
+
+A resolver which wanted to find the host name corresponding to Internet
+host address 10.0.0.6 would pursue a query of the form QTYPE=PTR,
+QCLASS=IN, QNAME=6.0.0.10.IN-ADDR.ARPA, and would receive:
+
+ 6.0.0.10.IN-ADDR.ARPA. PTR MULTICS.MIT.EDU.
+
+Several cautions apply to the use of these services:
+ - Since the IN-ADDR.ARPA special domain and the normal domain
+ for a particular host or gateway will be in different zones,
+ the possibility exists that that the data may be inconsistent.
+
+ - Gateways will often have two names in separate domains, only
+ one of which can be primary.
+
+ - Systems that use the domain database to initialize their
+ routing tables must start with enough gateway information to
+ guarantee that they can access the appropriate name server.
+
+ - The gateway data only reflects the existence of a gateway in a
+ manner equivalent to the current HOSTS.TXT file. It doesn't
+ replace the dynamic availability information from GGP or EGP.
+
+
+
+Mockapetris [Page 23]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+3.6. Defining new types, classes, and special namespaces
+
+The previously defined types and classes are the ones in use as of the
+date of this memo. New definitions should be expected. This section
+makes some recommendations to designers considering additions to the
+existing facilities. The mailing list NAMEDROPPERS@SRI-NIC.ARPA is the
+forum where general discussion of design issues takes place.
+
+In general, a new type is appropriate when new information is to be
+added to the database about an existing object, or we need new data
+formats for some totally new object. Designers should attempt to define
+types and their RDATA formats that are generally applicable to all
+classes, and which avoid duplication of information. New classes are
+appropriate when the DNS is to be used for a new protocol, etc which
+requires new class-specific data formats, or when a copy of the existing
+name space is desired, but a separate management domain is necessary.
+
+New types and classes need mnemonics for master files; the format of the
+master files requires that the mnemonics for type and class be disjoint.
+
+TYPE and CLASS values must be a proper subset of QTYPEs and QCLASSes
+respectively.
+
+The present system uses multiple RRs to represent multiple values of a
+type rather than storing multiple values in the RDATA section of a
+single RR. This is less efficient for most applications, but does keep
+RRs shorter. The multiple RRs assumption is incorporated in some
+experimental work on dynamic update methods.
+
+The present system attempts to minimize the duplication of data in the
+database in order to insure consistency. Thus, in order to find the
+address of the host for a mail exchange, you map the mail domain name to
+a host name, then the host name to addresses, rather than a direct
+mapping to host address. This approach is preferred because it avoids
+the opportunity for inconsistency.
+
+In defining a new type of data, multiple RR types should not be used to
+create an ordering between entries or express different formats for
+equivalent bindings, instead this information should be carried in the
+body of the RR and a single type used. This policy avoids problems with
+caching multiple types and defining QTYPEs to match multiple types.
+
+For example, the original form of mail exchange binding used two RR
+types one to represent a "closer" exchange (MD) and one to represent a
+"less close" exchange (MF). The difficulty is that the presence of one
+RR type in a cache doesn't convey any information about the other
+because the query which acquired the cached information might have used
+a QTYPE of MF, MD, or MAILA (which matched both). The redesigned
+
+
+
+Mockapetris [Page 24]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+service used a single type (MX) with a "preference" value in the RDATA
+section which can order different RRs. However, if any MX RRs are found
+in the cache, then all should be there.
+
+4. MESSAGES
+
+4.1. Format
+
+All communications inside of the domain protocol are carried in a single
+format called a message. The top level format of message is divided
+into 5 sections (some of which are empty in certain cases) shown below:
+
+ +---------------------+
+ | Header |
+ +---------------------+
+ | Question | the question for the name server
+ +---------------------+
+ | Answer | RRs answering the question
+ +---------------------+
+ | Authority | RRs pointing toward an authority
+ +---------------------+
+ | Additional | RRs holding additional information
+ +---------------------+
+
+The header section is always present. The header includes fields that
+specify which of the remaining sections are present, and also specify
+whether the message is a query or a response, a standard query or some
+other opcode, etc.
+
+The names of the sections after the header are derived from their use in
+standard queries. The question section contains fields that describe a
+question to a name server. These fields are a query type (QTYPE), a
+query class (QCLASS), and a query domain name (QNAME). The last three
+sections have the same format: a possibly empty list of concatenated
+resource records (RRs). The answer section contains RRs that answer the
+question; the authority section contains RRs that point toward an
+authoritative name server; the additional records section contains RRs
+which relate to the query, but are not strictly answers for the
+question.
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 25]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+4.1.1. Header section format
+
+The header contains the following fields:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ID |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QDCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ANCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | NSCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ARCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+ID A 16 bit identifier assigned by the program that
+ generates any kind of query. This identifier is copied
+ the corresponding reply and can be used by the requester
+ to match up replies to outstanding queries.
+
+QR A one bit field that specifies whether this message is a
+ query (0), or a response (1).
+
+OPCODE A four bit field that specifies kind of query in this
+ message. This value is set by the originator of a query
+ and copied into the response. The values are:
+
+ 0 a standard query (QUERY)
+
+ 1 an inverse query (IQUERY)
+
+ 2 a server status request (STATUS)
+
+ 3-15 reserved for future use
+
+AA Authoritative Answer - this bit is valid in responses,
+ and specifies that the responding name server is an
+ authority for the domain name in question section.
+
+ Note that the contents of the answer section may have
+ multiple owner names because of aliases. The AA bit
+
+
+
+Mockapetris [Page 26]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ corresponds to the name which matches the query name, or
+ the first owner name in the answer section.
+
+TC TrunCation - specifies that this message was truncated
+ due to length greater than that permitted on the
+ transmission channel.
+
+RD Recursion Desired - this bit may be set in a query and
+ is copied into the response. If RD is set, it directs
+ the name server to pursue the query recursively.
+ Recursive query support is optional.
+
+RA Recursion Available - this be is set or cleared in a
+ response, and denotes whether recursive query support is
+ available in the name server.
+
+Z Reserved for future use. Must be zero in all queries
+ and responses.
+
+RCODE Response code - this 4 bit field is set as part of
+ responses. The values have the following
+ interpretation:
+
+ 0 No error condition
+
+ 1 Format error - The name server was
+ unable to interpret the query.
+
+ 2 Server failure - The name server was
+ unable to process this query due to a
+ problem with the name server.
+
+ 3 Name Error - Meaningful only for
+ responses from an authoritative name
+ server, this code signifies that the
+ domain name referenced in the query does
+ not exist.
+
+ 4 Not Implemented - The name server does
+ not support the requested kind of query.
+
+ 5 Refused - The name server refuses to
+ perform the specified operation for
+ policy reasons. For example, a name
+ server may not wish to provide the
+ information to the particular requester,
+ or a name server may not wish to perform
+ a particular operation (e.g., zone
+
+
+
+Mockapetris [Page 27]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ transfer) for particular data.
+
+ 6-15 Reserved for future use.
+
+QDCOUNT an unsigned 16 bit integer specifying the number of
+ entries in the question section.
+
+ANCOUNT an unsigned 16 bit integer specifying the number of
+ resource records in the answer section.
+
+NSCOUNT an unsigned 16 bit integer specifying the number of name
+ server resource records in the authority records
+ section.
+
+ARCOUNT an unsigned 16 bit integer specifying the number of
+ resource records in the additional records section.
+
+4.1.2. Question section format
+
+The question section is used to carry the "question" in most queries,
+i.e., the parameters that define what is being asked. The section
+contains QDCOUNT (usually 1) entries, each of the following format:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / QNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QTYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QCLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+QNAME a domain name represented as a sequence of labels, where
+ each label consists of a length octet followed by that
+ number of octets. The domain name terminates with the
+ zero length octet for the null label of the root. Note
+ that this field may be an odd number of octets; no
+ padding is used.
+
+QTYPE a two octet code which specifies the type of the query.
+ The values for this field include all codes valid for a
+ TYPE field, together with some more general codes which
+ can match more than one type of RR.
+
+
+
+Mockapetris [Page 28]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+QCLASS a two octet code that specifies the class of the query.
+ For example, the QCLASS field is IN for the Internet.
+
+4.1.3. Resource record format
+
+The answer, authority, and additional sections all share the same
+format: a variable number of resource records, where the number of
+records is specified in the corresponding count field in the header.
+Each resource record has the following format:
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / /
+ / NAME /
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | CLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TTL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RDLENGTH |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+ / RDATA /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+where:
+
+NAME a domain name to which this resource record pertains.
+
+TYPE two octets containing one of the RR type codes. This
+ field specifies the meaning of the data in the RDATA
+ field.
+
+CLASS two octets which specify the class of the data in the
+ RDATA field.
+
+TTL a 32 bit unsigned integer that specifies the time
+ interval (in seconds) that the resource record may be
+ cached before it should be discarded. Zero values are
+ interpreted to mean that the RR can only be used for the
+ transaction in progress, and should not be cached.
+
+
+
+
+
+Mockapetris [Page 29]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+RDLENGTH an unsigned 16 bit integer that specifies the length in
+ octets of the RDATA field.
+
+RDATA a variable length string of octets that describes the
+ resource. The format of this information varies
+ according to the TYPE and CLASS of the resource record.
+ For example, the if the TYPE is A and the CLASS is IN,
+ the RDATA field is a 4 octet ARPA Internet address.
+
+4.1.4. Message compression
+
+In order to reduce the size of messages, the domain system utilizes a
+compression scheme which eliminates the repetition of domain names in a
+message. In this scheme, an entire domain name or a list of labels at
+the end of a domain name is replaced with a pointer to a prior occurance
+of the same name.
+
+The pointer takes the form of a two octet sequence:
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | 1 1| OFFSET |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+The first two bits are ones. This allows a pointer to be distinguished
+from a label, since the label must begin with two zero bits because
+labels are restricted to 63 octets or less. (The 10 and 01 combinations
+are reserved for future use.) The OFFSET field specifies an offset from
+the start of the message (i.e., the first octet of the ID field in the
+domain header). A zero offset specifies the first byte of the ID field,
+etc.
+
+The compression scheme allows a domain name in a message to be
+represented as either:
+
+ - a sequence of labels ending in a zero octet
+
+ - a pointer
+
+ - a sequence of labels ending with a pointer
+
+Pointers can only be used for occurances of a domain name where the
+format is not class specific. If this were not the case, a name server
+or resolver would be required to know the format of all RRs it handled.
+As yet, there are no such cases, but they may occur in future RDATA
+formats.
+
+If a domain name is contained in a part of the message subject to a
+length field (such as the RDATA section of an RR), and compression is
+
+
+
+Mockapetris [Page 30]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+used, the length of the compressed name is used in the length
+calculation, rather than the length of the expanded name.
+
+Programs are free to avoid using pointers in messages they generate,
+although this will reduce datagram capacity, and may cause truncation.
+However all programs are required to understand arriving messages that
+contain pointers.
+
+For example, a datagram might need to use the domain names F.ISI.ARPA,
+FOO.F.ISI.ARPA, ARPA, and the root. Ignoring the other fields of the
+message, these domain names might be represented as:
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 20 | 1 | F |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 22 | 3 | I |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 24 | S | I |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 26 | 4 | A |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 28 | R | P |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 30 | A | 0 |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 40 | 3 | F |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 42 | O | O |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 44 | 1 1| 20 |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 64 | 1 1| 26 |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 92 | 0 | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+The domain name for F.ISI.ARPA is shown at offset 20. The domain name
+FOO.F.ISI.ARPA is shown at offset 40; this definition uses a pointer to
+concatenate a label for FOO to the previously defined F.ISI.ARPA. The
+domain name ARPA is defined at offset 64 using a pointer to the ARPA
+component of the name F.ISI.ARPA at 20; note that this pointer relies on
+ARPA being the last label in the string at 20. The root domain name is
+
+
+
+Mockapetris [Page 31]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+defined by a single octet of zeros at 92; the root domain name has no
+labels.
+
+4.2. Transport
+
+The DNS assumes that messages will be transmitted as datagrams or in a
+byte stream carried by a virtual circuit. While virtual circuits can be
+used for any DNS activity, datagrams are preferred for queries due to
+their lower overhead and better performance. Zone refresh activities
+must use virtual circuits because of the need for reliable transfer.
+
+The Internet supports name server access using TCP [RFC-793] on server
+port 53 (decimal) as well as datagram access using UDP [RFC-768] on UDP
+port 53 (decimal).
+
+4.2.1. UDP usage
+
+Messages sent using UDP user server port 53 (decimal).
+
+Messages carried by UDP are restricted to 512 bytes (not counting the IP
+or UDP headers). Longer messages are truncated and the TC bit is set in
+the header.
+
+UDP is not acceptable for zone transfers, but is the recommended method
+for standard queries in the Internet. Queries sent using UDP may be
+lost, and hence a retransmission strategy is required. Queries or their
+responses may be reordered by the network, or by processing in name
+servers, so resolvers should not depend on them being returned in order.
+
+The optimal UDP retransmission policy will vary with performance of the
+Internet and the needs of the client, but the following are recommended:
+
+ - The client should try other servers and server addresses
+ before repeating a query to a specific address of a server.
+
+ - The retransmission interval should be based on prior
+ statistics if possible. Too aggressive retransmission can
+ easily slow responses for the community at large. Depending
+ on how well connected the client is to its expected servers,
+ the minimum retransmission interval should be 2-5 seconds.
+
+More suggestions on server selection and retransmission policy can be
+found in the resolver section of this memo.
+
+4.2.2. TCP usage
+
+Messages sent over TCP connections use server port 53 (decimal). The
+message is prefixed with a two byte length field which gives the message
+
+
+
+Mockapetris [Page 32]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+length, excluding the two byte length field. This length field allows
+the low-level processing to assemble a complete message before beginning
+to parse it.
+
+Several connection management policies are recommended:
+
+ - The server should not block other activities waiting for TCP
+ data.
+
+ - The server should support multiple connections.
+
+ - The server should assume that the client will initiate
+ connection closing, and should delay closing its end of the
+ connection until all outstanding client requests have been
+ satisfied.
+
+ - If the server needs to close a dormant connection to reclaim
+ resources, it should wait until the connection has been idle
+ for a period on the order of two minutes. In particular, the
+ server should allow the SOA and AXFR request sequence (which
+ begins a refresh operation) to be made on a single connection.
+ Since the server would be unable to answer queries anyway, a
+ unilateral close or reset may be used instead of a graceful
+ close.
+
+5. MASTER FILES
+
+Master files are text files that contain RRs in text form. Since the
+contents of a zone can be expressed in the form of a list of RRs a
+master file is most often used to define a zone, though it can be used
+to list a cache's contents. Hence, this section first discusses the
+format of RRs in a master file, and then the special considerations when
+a master file is used to create a zone in some name server.
+
+5.1. Format
+
+The format of these files is a sequence of entries. Entries are
+predominantly line-oriented, though parentheses can be used to continue
+a list of items across a line boundary, and text literals can contain
+CRLF within the text. Any combination of tabs and spaces act as a
+delimiter between the separate items that make up an entry. The end of
+any line in the master file can end with a comment. The comment starts
+with a ";" (semicolon).
+
+The following entries are defined:
+
+ <blank>[<comment>]
+
+
+
+
+Mockapetris [Page 33]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ $ORIGIN <domain-name> [<comment>]
+
+ $INCLUDE <file-name> [<domain-name>] [<comment>]
+
+ <domain-name><rr> [<comment>]
+
+ <blank><rr> [<comment>]
+
+Blank lines, with or without comments, are allowed anywhere in the file.
+
+Two control entries are defined: $ORIGIN and $INCLUDE. $ORIGIN is
+followed by a domain name, and resets the current origin for relative
+domain names to the stated name. $INCLUDE inserts the named file into
+the current file, and may optionally specify a domain name that sets the
+relative domain name origin for the included file. $INCLUDE may also
+have a comment. Note that a $INCLUDE entry never changes the relative
+origin of the parent file, regardless of changes to the relative origin
+made within the included file.
+
+The last two forms represent RRs. If an entry for an RR begins with a
+blank, then the RR is assumed to be owned by the last stated owner. If
+an RR entry begins with a <domain-name>, then the owner name is reset.
+
+<rr> contents take one of the following forms:
+
+ [<TTL>] [<class>] <type> <RDATA>
+
+ [<class>] [<TTL>] <type> <RDATA>
+
+The RR begins with optional TTL and class fields, followed by a type and
+RDATA field appropriate to the type and class. Class and type use the
+standard mnemonics, TTL is a decimal integer. Omitted class and TTL
+values are default to the last explicitly stated values. Since type and
+class mnemonics are disjoint, the parse is unique. (Note that this
+order is different from the order used in examples and the order used in
+the actual RRs; the given order allows easier parsing and defaulting.)
+
+<domain-name>s make up a large share of the data in the master file.
+The labels in the domain name are expressed as character strings and
+separated by dots. Quoting conventions allow arbitrary characters to be
+stored in domain names. Domain names that end in a dot are called
+absolute, and are taken as complete. Domain names which do not end in a
+dot are called relative; the actual domain name is the concatenation of
+the relative part with an origin specified in a $ORIGIN, $INCLUDE, or as
+an argument to the master file loading routine. A relative name is an
+error when no origin is available.
+
+
+
+
+
+Mockapetris [Page 34]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+<character-string> is expressed in one or two ways: as a contiguous set
+of characters without interior spaces, or as a string beginning with a "
+and ending with a ". Inside a " delimited string any character can
+occur, except for a " itself, which must be quoted using \ (back slash).
+
+Because these files are text files several special encodings are
+necessary to allow arbitrary data to be loaded. In particular:
+
+ of the root.
+
+@ A free standing @ is used to denote the current origin.
+
+\X where X is any character other than a digit (0-9), is
+ used to quote that character so that its special meaning
+ does not apply. For example, "\." can be used to place
+ a dot character in a label.
+
+\DDD where each D is a digit is the octet corresponding to
+ the decimal number described by DDD. The resulting
+ octet is assumed to be text and is not checked for
+ special meaning.
+
+( ) Parentheses are used to group data that crosses a line
+ boundary. In effect, line terminations are not
+ recognized within parentheses.
+
+; Semicolon is used to start a comment; the remainder of
+ the line is ignored.
+
+5.2. Use of master files to define zones
+
+When a master file is used to load a zone, the operation should be
+suppressed if any errors are encountered in the master file. The
+rationale for this is that a single error can have widespread
+consequences. For example, suppose that the RRs defining a delegation
+have syntax errors; then the server will return authoritative name
+errors for all names in the subzone (except in the case where the
+subzone is also present on the server).
+
+Several other validity checks that should be performed in addition to
+insuring that the file is syntactically correct:
+
+ 1. All RRs in the file should have the same class.
+
+ 2. Exactly one SOA RR should be present at the top of the zone.
+
+ 3. If delegations are present and glue information is required,
+ it should be present.
+
+
+
+Mockapetris [Page 35]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 4. Information present outside of the authoritative nodes in the
+ zone should be glue information, rather than the result of an
+ origin or similar error.
+
+5.3. Master file example
+
+The following is an example file which might be used to define the
+ISI.EDU zone.and is loaded with an origin of ISI.EDU:
+
+@ IN SOA VENERA Action\.domains (
+ 20 ; SERIAL
+ 7200 ; REFRESH
+ 600 ; RETRY
+ 3600000; EXPIRE
+ 60) ; MINIMUM
+
+ NS A.ISI.EDU.
+ NS VENERA
+ NS VAXA
+ MX 10 VENERA
+ MX 20 VAXA
+
+A A 26.3.0.103
+
+VENERA A 10.1.0.52
+ A 128.9.0.32
+
+VAXA A 10.2.0.27
+ A 128.9.0.33
+
+
+$INCLUDE <SUBSYS>ISI-MAILBOXES.TXT
+
+Where the file <SUBSYS>ISI-MAILBOXES.TXT is:
+
+ MOE MB A.ISI.EDU.
+ LARRY MB A.ISI.EDU.
+ CURLEY MB A.ISI.EDU.
+ STOOGES MG MOE
+ MG LARRY
+ MG CURLEY
+
+Note the use of the \ character in the SOA RR to specify the responsible
+person mailbox "Action.domains@E.ISI.EDU".
+
+
+
+
+
+
+
+Mockapetris [Page 36]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+6. NAME SERVER IMPLEMENTATION
+
+6.1. Architecture
+
+The optimal structure for the name server will depend on the host
+operating system and whether the name server is integrated with resolver
+operations, either by supporting recursive service, or by sharing its
+database with a resolver. This section discusses implementation
+considerations for a name server which shares a database with a
+resolver, but most of these concerns are present in any name server.
+
+6.1.1. Control
+
+A name server must employ multiple concurrent activities, whether they
+are implemented as separate tasks in the host's OS or multiplexing
+inside a single name server program. It is simply not acceptable for a
+name server to block the service of UDP requests while it waits for TCP
+data for refreshing or query activities. Similarly, a name server
+should not attempt to provide recursive service without processing such
+requests in parallel, though it may choose to serialize requests from a
+single client, or to regard identical requests from the same client as
+duplicates. A name server should not substantially delay requests while
+it reloads a zone from master files or while it incorporates a newly
+refreshed zone into its database.
+
+6.1.2. Database
+
+While name server implementations are free to use any internal data
+structures they choose, the suggested structure consists of three major
+parts:
+
+ - A "catalog" data structure which lists the zones available to
+ this server, and a "pointer" to the zone data structure. The
+ main purpose of this structure is to find the nearest ancestor
+ zone, if any, for arriving standard queries.
+
+ - Separate data structures for each of the zones held by the
+ name server.
+
+ - A data structure for cached data. (or perhaps separate caches
+ for different classes)
+
+All of these data structures can be implemented an identical tree
+structure format, with different data chained off the nodes in different
+parts: in the catalog the data is pointers to zones, while in the zone
+and cache data structures, the data will be RRs. In designing the tree
+framework the designer should recognize that query processing will need
+to traverse the tree using case-insensitive label comparisons; and that
+
+
+
+Mockapetris [Page 37]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+in real data, a few nodes have a very high branching factor (100-1000 or
+more), but the vast majority have a very low branching factor (0-1).
+
+One way to solve the case problem is to store the labels for each node
+in two pieces: a standardized-case representation of the label where all
+ASCII characters are in a single case, together with a bit mask that
+denotes which characters are actually of a different case. The
+branching factor diversity can be handled using a simple linked list for
+a node until the branching factor exceeds some threshold, and
+transitioning to a hash structure after the threshold is exceeded. In
+any case, hash structures used to store tree sections must insure that
+hash functions and procedures preserve the casing conventions of the
+DNS.
+
+The use of separate structures for the different parts of the database
+is motivated by several factors:
+
+ - The catalog structure can be an almost static structure that
+ need change only when the system administrator changes the
+ zones supported by the server. This structure can also be
+ used to store parameters used to control refreshing
+ activities.
+
+ - The individual data structures for zones allow a zone to be
+ replaced simply by changing a pointer in the catalog. Zone
+ refresh operations can build a new structure and, when
+ complete, splice it into the database via a simple pointer
+ replacement. It is very important that when a zone is
+ refreshed, queries should not use old and new data
+ simultaneously.
+
+ - With the proper search procedures, authoritative data in zones
+ will always "hide", and hence take precedence over, cached
+ data.
+
+ - Errors in zone definitions that cause overlapping zones, etc.,
+ may cause erroneous responses to queries, but problem
+ determination is simplified, and the contents of one "bad"
+ zone can't corrupt another.
+
+ - Since the cache is most frequently updated, it is most
+ vulnerable to corruption during system restarts. It can also
+ become full of expired RR data. In either case, it can easily
+ be discarded without disturbing zone data.
+
+A major aspect of database design is selecting a structure which allows
+the name server to deal with crashes of the name server's host. State
+information which a name server should save across system crashes
+
+
+
+Mockapetris [Page 38]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+includes the catalog structure (including the state of refreshing for
+each zone) and the zone data itself.
+
+6.1.3. Time
+
+Both the TTL data for RRs and the timing data for refreshing activities
+depends on 32 bit timers in units of seconds. Inside the database,
+refresh timers and TTLs for cached data conceptually "count down", while
+data in the zone stays with constant TTLs.
+
+A recommended implementation strategy is to store time in two ways: as
+a relative increment and as an absolute time. One way to do this is to
+use positive 32 bit numbers for one type and negative numbers for the
+other. The RRs in zones use relative times; the refresh timers and
+cache data use absolute times. Absolute numbers are taken with respect
+to some known origin and converted to relative values when placed in the
+response to a query. When an absolute TTL is negative after conversion
+to relative, then the data is expired and should be ignored.
+
+6.2. Standard query processing
+
+The major algorithm for standard query processing is presented in
+[RFC-1034].
+
+When processing queries with QCLASS=*, or some other QCLASS which
+matches multiple classes, the response should never be authoritative
+unless the server can guarantee that the response covers all classes.
+
+When composing a response, RRs which are to be inserted in the
+additional section, but duplicate RRs in the answer or authority
+sections, may be omitted from the additional section.
+
+When a response is so long that truncation is required, the truncation
+should start at the end of the response and work forward in the
+datagram. Thus if there is any data for the authority section, the
+answer section is guaranteed to be unique.
+
+The MINIMUM value in the SOA should be used to set a floor on the TTL of
+data distributed from a zone. This floor function should be done when
+the data is copied into a response. This will allow future dynamic
+update protocols to change the SOA MINIMUM field without ambiguous
+semantics.
+
+6.3. Zone refresh and reload processing
+
+In spite of a server's best efforts, it may be unable to load zone data
+from a master file due to syntax errors, etc., or be unable to refresh a
+zone within the its expiration parameter. In this case, the name server
+
+
+
+Mockapetris [Page 39]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+should answer queries as if it were not supposed to possess the zone.
+
+If a master is sending a zone out via AXFR, and a new version is created
+during the transfer, the master should continue to send the old version
+if possible. In any case, it should never send part of one version and
+part of another. If completion is not possible, the master should reset
+the connection on which the zone transfer is taking place.
+
+6.4. Inverse queries (Optional)
+
+Inverse queries are an optional part of the DNS. Name servers are not
+required to support any form of inverse queries. If a name server
+receives an inverse query that it does not support, it returns an error
+response with the "Not Implemented" error set in the header. While
+inverse query support is optional, all name servers must be at least
+able to return the error response.
+
+6.4.1. The contents of inverse queries and responses Inverse
+queries reverse the mappings performed by standard query operations;
+while a standard query maps a domain name to a resource, an inverse
+query maps a resource to a domain name. For example, a standard query
+might bind a domain name to a host address; the corresponding inverse
+query binds the host address to a domain name.
+
+Inverse queries take the form of a single RR in the answer section of
+the message, with an empty question section. The owner name of the
+query RR and its TTL are not significant. The response carries
+questions in the question section which identify all names possessing
+the query RR WHICH THE NAME SERVER KNOWS. Since no name server knows
+about all of the domain name space, the response can never be assumed to
+be complete. Thus inverse queries are primarily useful for database
+management and debugging activities. Inverse queries are NOT an
+acceptable method of mapping host addresses to host names; use the IN-
+ADDR.ARPA domain instead.
+
+Where possible, name servers should provide case-insensitive comparisons
+for inverse queries. Thus an inverse query asking for an MX RR of
+"Venera.isi.edu" should get the same response as a query for
+"VENERA.ISI.EDU"; an inverse query for HINFO RR "IBM-PC UNIX" should
+produce the same result as an inverse query for "IBM-pc unix". However,
+this cannot be guaranteed because name servers may possess RRs that
+contain character strings but the name server does not know that the
+data is character.
+
+When a name server processes an inverse query, it either returns:
+
+ 1. zero, one, or multiple domain names for the specified
+ resource as QNAMEs in the question section
+
+
+
+Mockapetris [Page 40]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 2. an error code indicating that the name server doesn't support
+ inverse mapping of the specified resource type.
+
+When the response to an inverse query contains one or more QNAMEs, the
+owner name and TTL of the RR in the answer section which defines the
+inverse query is modified to exactly match an RR found at the first
+QNAME.
+
+RRs returned in the inverse queries cannot be cached using the same
+mechanism as is used for the replies to standard queries. One reason
+for this is that a name might have multiple RRs of the same type, and
+only one would appear. For example, an inverse query for a single
+address of a multiply homed host might create the impression that only
+one address existed.
+
+6.4.2. Inverse query and response example The overall structure
+of an inverse query for retrieving the domain name that corresponds to
+Internet address 10.1.0.52 is shown below:
+
+ +-----------------------------------------+
+ Header | OPCODE=IQUERY, ID=997 |
+ +-----------------------------------------+
+ Question | <empty> |
+ +-----------------------------------------+
+ Answer | <anyname> A IN 10.1.0.52 |
+ +-----------------------------------------+
+ Authority | <empty> |
+ +-----------------------------------------+
+ Additional | <empty> |
+ +-----------------------------------------+
+
+This query asks for a question whose answer is the Internet style
+address 10.1.0.52. Since the owner name is not known, any domain name
+can be used as a placeholder (and is ignored). A single octet of zero,
+signifying the root, is usually used because it minimizes the length of
+the message. The TTL of the RR is not significant. The response to
+this query might be:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 41]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ +-----------------------------------------+
+ Header | OPCODE=RESPONSE, ID=997 |
+ +-----------------------------------------+
+ Question |QTYPE=A, QCLASS=IN, QNAME=VENERA.ISI.EDU |
+ +-----------------------------------------+
+ Answer | VENERA.ISI.EDU A IN 10.1.0.52 |
+ +-----------------------------------------+
+ Authority | <empty> |
+ +-----------------------------------------+
+ Additional | <empty> |
+ +-----------------------------------------+
+
+Note that the QTYPE in a response to an inverse query is the same as the
+TYPE field in the answer section of the inverse query. Responses to
+inverse queries may contain multiple questions when the inverse is not
+unique. If the question section in the response is not empty, then the
+RR in the answer section is modified to correspond to be an exact copy
+of an RR at the first QNAME.
+
+6.4.3. Inverse query processing
+
+Name servers that support inverse queries can support these operations
+through exhaustive searches of their databases, but this becomes
+impractical as the size of the database increases. An alternative
+approach is to invert the database according to the search key.
+
+For name servers that support multiple zones and a large amount of data,
+the recommended approach is separate inversions for each zone. When a
+particular zone is changed during a refresh, only its inversions need to
+be redone.
+
+Support for transfer of this type of inversion may be included in future
+versions of the domain system, but is not supported in this version.
+
+6.5. Completion queries and responses
+
+The optional completion services described in RFC-882 and RFC-883 have
+been deleted. Redesigned services may become available in the future.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 42]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+7. RESOLVER IMPLEMENTATION
+
+The top levels of the recommended resolver algorithm are discussed in
+[RFC-1034]. This section discusses implementation details assuming the
+database structure suggested in the name server implementation section
+of this memo.
+
+7.1. Transforming a user request into a query
+
+The first step a resolver takes is to transform the client's request,
+stated in a format suitable to the local OS, into a search specification
+for RRs at a specific name which match a specific QTYPE and QCLASS.
+Where possible, the QTYPE and QCLASS should correspond to a single type
+and a single class, because this makes the use of cached data much
+simpler. The reason for this is that the presence of data of one type
+in a cache doesn't confirm the existence or non-existence of data of
+other types, hence the only way to be sure is to consult an
+authoritative source. If QCLASS=* is used, then authoritative answers
+won't be available.
+
+Since a resolver must be able to multiplex multiple requests if it is to
+perform its function efficiently, each pending request is usually
+represented in some block of state information. This state block will
+typically contain:
+
+ - A timestamp indicating the time the request began.
+ The timestamp is used to decide whether RRs in the database
+ can be used or are out of date. This timestamp uses the
+ absolute time format previously discussed for RR storage in
+ zones and caches. Note that when an RRs TTL indicates a
+ relative time, the RR must be timely, since it is part of a
+ zone. When the RR has an absolute time, it is part of a
+ cache, and the TTL of the RR is compared against the timestamp
+ for the start of the request.
+
+ Note that using the timestamp is superior to using a current
+ time, since it allows RRs with TTLs of zero to be entered in
+ the cache in the usual manner, but still used by the current
+ request, even after intervals of many seconds due to system
+ load, query retransmission timeouts, etc.
+
+ - Some sort of parameters to limit the amount of work which will
+ be performed for this request.
+
+ The amount of work which a resolver will do in response to a
+ client request must be limited to guard against errors in the
+ database, such as circular CNAME references, and operational
+ problems, such as network partition which prevents the
+
+
+
+Mockapetris [Page 43]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ resolver from accessing the name servers it needs. While
+ local limits on the number of times a resolver will retransmit
+ a particular query to a particular name server address are
+ essential, the resolver should have a global per-request
+ counter to limit work on a single request. The counter should
+ be set to some initial value and decremented whenever the
+ resolver performs any action (retransmission timeout,
+ retransmission, etc.) If the counter passes zero, the request
+ is terminated with a temporary error.
+
+ Note that if the resolver structure allows one request to
+ start others in parallel, such as when the need to access a
+ name server for one request causes a parallel resolve for the
+ name server's addresses, the spawned request should be started
+ with a lower counter. This prevents circular references in
+ the database from starting a chain reaction of resolver
+ activity.
+
+ - The SLIST data structure discussed in [RFC-1034].
+
+ This structure keeps track of the state of a request if it
+ must wait for answers from foreign name servers.
+
+7.2. Sending the queries
+
+As described in [RFC-1034], the basic task of the resolver is to
+formulate a query which will answer the client's request and direct that
+query to name servers which can provide the information. The resolver
+will usually only have very strong hints about which servers to ask, in
+the form of NS RRs, and may have to revise the query, in response to
+CNAMEs, or revise the set of name servers the resolver is asking, in
+response to delegation responses which point the resolver to name
+servers closer to the desired information. In addition to the
+information requested by the client, the resolver may have to call upon
+its own services to determine the address of name servers it wishes to
+contact.
+
+In any case, the model used in this memo assumes that the resolver is
+multiplexing attention between multiple requests, some from the client,
+and some internally generated. Each request is represented by some
+state information, and the desired behavior is that the resolver
+transmit queries to name servers in a way that maximizes the probability
+that the request is answered, minimizes the time that the request takes,
+and avoids excessive transmissions. The key algorithm uses the state
+information of the request to select the next name server address to
+query, and also computes a timeout which will cause the next action
+should a response not arrive. The next action will usually be a
+transmission to some other server, but may be a temporary error to the
+
+
+
+Mockapetris [Page 44]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+client.
+
+The resolver always starts with a list of server names to query (SLIST).
+This list will be all NS RRs which correspond to the nearest ancestor
+zone that the resolver knows about. To avoid startup problems, the
+resolver should have a set of default servers which it will ask should
+it have no current NS RRs which are appropriate. The resolver then adds
+to SLIST all of the known addresses for the name servers, and may start
+parallel requests to acquire the addresses of the servers when the
+resolver has the name, but no addresses, for the name servers.
+
+To complete initialization of SLIST, the resolver attaches whatever
+history information it has to the each address in SLIST. This will
+usually consist of some sort of weighted averages for the response time
+of the address, and the batting average of the address (i.e., how often
+the address responded at all to the request). Note that this
+information should be kept on a per address basis, rather than on a per
+name server basis, because the response time and batting average of a
+particular server may vary considerably from address to address. Note
+also that this information is actually specific to a resolver address /
+server address pair, so a resolver with multiple addresses may wish to
+keep separate histories for each of its addresses. Part of this step
+must deal with addresses which have no such history; in this case an
+expected round trip time of 5-10 seconds should be the worst case, with
+lower estimates for the same local network, etc.
+
+Note that whenever a delegation is followed, the resolver algorithm
+reinitializes SLIST.
+
+The information establishes a partial ranking of the available name
+server addresses. Each time an address is chosen and the state should
+be altered to prevent its selection again until all other addresses have
+been tried. The timeout for each transmission should be 50-100% greater
+than the average predicted value to allow for variance in response.
+
+Some fine points:
+
+ - The resolver may encounter a situation where no addresses are
+ available for any of the name servers named in SLIST, and
+ where the servers in the list are precisely those which would
+ normally be used to look up their own addresses. This
+ situation typically occurs when the glue address RRs have a
+ smaller TTL than the NS RRs marking delegation, or when the
+ resolver caches the result of a NS search. The resolver
+ should detect this condition and restart the search at the
+ next ancestor zone, or alternatively at the root.
+
+
+
+
+
+Mockapetris [Page 45]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ - If a resolver gets a server error or other bizarre response
+ from a name server, it should remove it from SLIST, and may
+ wish to schedule an immediate transmission to the next
+ candidate server address.
+
+7.3. Processing responses
+
+The first step in processing arriving response datagrams is to parse the
+response. This procedure should include:
+
+ - Check the header for reasonableness. Discard datagrams which
+ are queries when responses are expected.
+
+ - Parse the sections of the message, and insure that all RRs are
+ correctly formatted.
+
+ - As an optional step, check the TTLs of arriving data looking
+ for RRs with excessively long TTLs. If a RR has an
+ excessively long TTL, say greater than 1 week, either discard
+ the whole response, or limit all TTLs in the response to 1
+ week.
+
+The next step is to match the response to a current resolver request.
+The recommended strategy is to do a preliminary matching using the ID
+field in the domain header, and then to verify that the question section
+corresponds to the information currently desired. This requires that
+the transmission algorithm devote several bits of the domain ID field to
+a request identifier of some sort. This step has several fine points:
+
+ - Some name servers send their responses from different
+ addresses than the one used to receive the query. That is, a
+ resolver cannot rely that a response will come from the same
+ address which it sent the corresponding query to. This name
+ server bug is typically encountered in UNIX systems.
+
+ - If the resolver retransmits a particular request to a name
+ server it should be able to use a response from any of the
+ transmissions. However, if it is using the response to sample
+ the round trip time to access the name server, it must be able
+ to determine which transmission matches the response (and keep
+ transmission times for each outgoing message), or only
+ calculate round trip times based on initial transmissions.
+
+ - A name server will occasionally not have a current copy of a
+ zone which it should have according to some NS RRs. The
+ resolver should simply remove the name server from the current
+ SLIST, and continue.
+
+
+
+
+Mockapetris [Page 46]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+7.4. Using the cache
+
+In general, we expect a resolver to cache all data which it receives in
+responses since it may be useful in answering future client requests.
+However, there are several types of data which should not be cached:
+
+ - When several RRs of the same type are available for a
+ particular owner name, the resolver should either cache them
+ all or none at all. When a response is truncated, and a
+ resolver doesn't know whether it has a complete set, it should
+ not cache a possibly partial set of RRs.
+
+ - Cached data should never be used in preference to
+ authoritative data, so if caching would cause this to happen
+ the data should not be cached.
+
+ - The results of an inverse query should not be cached.
+
+ - The results of standard queries where the QNAME contains "*"
+ labels if the data might be used to construct wildcards. The
+ reason is that the cache does not necessarily contain existing
+ RRs or zone boundary information which is necessary to
+ restrict the application of the wildcard RRs.
+
+ - RR data in responses of dubious reliability. When a resolver
+ receives unsolicited responses or RR data other than that
+ requested, it should discard it without caching it. The basic
+ implication is that all sanity checks on a packet should be
+ performed before any of it is cached.
+
+In a similar vein, when a resolver has a set of RRs for some name in a
+response, and wants to cache the RRs, it should check its cache for
+already existing RRs. Depending on the circumstances, either the data
+in the response or the cache is preferred, but the two should never be
+combined. If the data in the response is from authoritative data in the
+answer section, it is always preferred.
+
+8. MAIL SUPPORT
+
+The domain system defines a standard for mapping mailboxes into domain
+names, and two methods for using the mailbox information to derive mail
+routing information. The first method is called mail exchange binding
+and the other method is mailbox binding. The mailbox encoding standard
+and mail exchange binding are part of the DNS official protocol, and are
+the recommended method for mail routing in the Internet. Mailbox
+binding is an experimental feature which is still under development and
+subject to change.
+
+
+
+
+Mockapetris [Page 47]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+The mailbox encoding standard assumes a mailbox name of the form
+"<local-part>@<mail-domain>". While the syntax allowed in each of these
+sections varies substantially between the various mail internets, the
+preferred syntax for the ARPA Internet is given in [RFC-822].
+
+The DNS encodes the <local-part> as a single label, and encodes the
+<mail-domain> as a domain name. The single label from the <local-part>
+is prefaced to the domain name from <mail-domain> to form the domain
+name corresponding to the mailbox. Thus the mailbox HOSTMASTER@SRI-
+NIC.ARPA is mapped into the domain name HOSTMASTER.SRI-NIC.ARPA. If the
+<local-part> contains dots or other special characters, its
+representation in a master file will require the use of backslash
+quoting to ensure that the domain name is properly encoded. For
+example, the mailbox Action.domains@ISI.EDU would be represented as
+Action\.domains.ISI.EDU.
+
+8.1. Mail exchange binding
+
+Mail exchange binding uses the <mail-domain> part of a mailbox
+specification to determine where mail should be sent. The <local-part>
+is not even consulted. [RFC-974] specifies this method in detail, and
+should be consulted before attempting to use mail exchange support.
+
+One of the advantages of this method is that it decouples mail
+destination naming from the hosts used to support mail service, at the
+cost of another layer of indirection in the lookup function. However,
+the addition layer should eliminate the need for complicated "%", "!",
+etc encodings in <local-part>.
+
+The essence of the method is that the <mail-domain> is used as a domain
+name to locate type MX RRs which list hosts willing to accept mail for
+<mail-domain>, together with preference values which rank the hosts
+according to an order specified by the administrators for <mail-domain>.
+
+In this memo, the <mail-domain> ISI.EDU is used in examples, together
+with the hosts VENERA.ISI.EDU and VAXA.ISI.EDU as mail exchanges for
+ISI.EDU. If a mailer had a message for Mockapetris@ISI.EDU, it would
+route it by looking up MX RRs for ISI.EDU. The MX RRs at ISI.EDU name
+VENERA.ISI.EDU and VAXA.ISI.EDU, and type A queries can find the host
+addresses.
+
+8.2. Mailbox binding (Experimental)
+
+In mailbox binding, the mailer uses the entire mail destination
+specification to construct a domain name. The encoded domain name for
+the mailbox is used as the QNAME field in a QTYPE=MAILB query.
+
+Several outcomes are possible for this query:
+
+
+
+Mockapetris [Page 48]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ 1. The query can return a name error indicating that the mailbox
+ does not exist as a domain name.
+
+ In the long term, this would indicate that the specified
+ mailbox doesn't exist. However, until the use of mailbox
+ binding is universal, this error condition should be
+ interpreted to mean that the organization identified by the
+ global part does not support mailbox binding. The
+ appropriate procedure is to revert to exchange binding at
+ this point.
+
+ 2. The query can return a Mail Rename (MR) RR.
+
+ The MR RR carries new mailbox specification in its RDATA
+ field. The mailer should replace the old mailbox with the
+ new one and retry the operation.
+
+ 3. The query can return a MB RR.
+
+ The MB RR carries a domain name for a host in its RDATA
+ field. The mailer should deliver the message to that host
+ via whatever protocol is applicable, e.g., b,SMTP.
+
+ 4. The query can return one or more Mail Group (MG) RRs.
+
+ This condition means that the mailbox was actually a mailing
+ list or mail group, rather than a single mailbox. Each MG RR
+ has a RDATA field that identifies a mailbox that is a member
+ of the group. The mailer should deliver a copy of the
+ message to each member.
+
+ 5. The query can return a MB RR as well as one or more MG RRs.
+
+ This condition means the the mailbox was actually a mailing
+ list. The mailer can either deliver the message to the host
+ specified by the MB RR, which will in turn do the delivery to
+ all members, or the mailer can use the MG RRs to do the
+ expansion itself.
+
+In any of these cases, the response may include a Mail Information
+(MINFO) RR. This RR is usually associated with a mail group, but is
+legal with a MB. The MINFO RR identifies two mailboxes. One of these
+identifies a responsible person for the original mailbox name. This
+mailbox should be used for requests to be added to a mail group, etc.
+The second mailbox name in the MINFO RR identifies a mailbox that should
+receive error messages for mail failures. This is particularly
+appropriate for mailing lists when errors in member names should be
+reported to a person other than the one who sends a message to the list.
+
+
+
+Mockapetris [Page 49]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+New fields may be added to this RR in the future.
+
+
+9. REFERENCES and BIBLIOGRAPHY
+
+[Dyer 87] S. Dyer, F. Hsu, "Hesiod", Project Athena
+ Technical Plan - Name Service, April 1987, version 1.9.
+
+ Describes the fundamentals of the Hesiod name service.
+
+[IEN-116] J. Postel, "Internet Name Server", IEN-116,
+ USC/Information Sciences Institute, August 1979.
+
+ A name service obsoleted by the Domain Name System, but
+ still in use.
+
+[Quarterman 86] J. Quarterman, and J. Hoskins, "Notable Computer Networks",
+ Communications of the ACM, October 1986, volume 29, number
+ 10.
+
+[RFC-742] K. Harrenstien, "NAME/FINGER", RFC-742, Network
+ Information Center, SRI International, December 1977.
+
+[RFC-768] J. Postel, "User Datagram Protocol", RFC-768,
+ USC/Information Sciences Institute, August 1980.
+
+[RFC-793] J. Postel, "Transmission Control Protocol", RFC-793,
+ USC/Information Sciences Institute, September 1981.
+
+[RFC-799] D. Mills, "Internet Name Domains", RFC-799, COMSAT,
+ September 1981.
+
+ Suggests introduction of a hierarchy in place of a flat
+ name space for the Internet.
+
+[RFC-805] J. Postel, "Computer Mail Meeting Notes", RFC-805,
+ USC/Information Sciences Institute, February 1982.
+
+[RFC-810] E. Feinler, K. Harrenstien, Z. Su, and V. White, "DOD
+ Internet Host Table Specification", RFC-810, Network
+ Information Center, SRI International, March 1982.
+
+ Obsolete. See RFC-952.
+
+[RFC-811] K. Harrenstien, V. White, and E. Feinler, "Hostnames
+ Server", RFC-811, Network Information Center, SRI
+ International, March 1982.
+
+
+
+
+Mockapetris [Page 50]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ Obsolete. See RFC-953.
+
+[RFC-812] K. Harrenstien, and V. White, "NICNAME/WHOIS", RFC-812,
+ Network Information Center, SRI International, March
+ 1982.
+
+[RFC-819] Z. Su, and J. Postel, "The Domain Naming Convention for
+ Internet User Applications", RFC-819, Network
+ Information Center, SRI International, August 1982.
+
+ Early thoughts on the design of the domain system.
+ Current implementation is completely different.
+
+[RFC-821] J. Postel, "Simple Mail Transfer Protocol", RFC-821,
+ USC/Information Sciences Institute, August 1980.
+
+[RFC-830] Z. Su, "A Distributed System for Internet Name Service",
+ RFC-830, Network Information Center, SRI International,
+ October 1982.
+
+ Early thoughts on the design of the domain system.
+ Current implementation is completely different.
+
+[RFC-882] P. Mockapetris, "Domain names - Concepts and
+ Facilities," RFC-882, USC/Information Sciences
+ Institute, November 1983.
+
+ Superceeded by this memo.
+
+[RFC-883] P. Mockapetris, "Domain names - Implementation and
+ Specification," RFC-883, USC/Information Sciences
+ Institute, November 1983.
+
+ Superceeded by this memo.
+
+[RFC-920] J. Postel and J. Reynolds, "Domain Requirements",
+ RFC-920, USC/Information Sciences Institute,
+ October 1984.
+
+ Explains the naming scheme for top level domains.
+
+[RFC-952] K. Harrenstien, M. Stahl, E. Feinler, "DoD Internet Host
+ Table Specification", RFC-952, SRI, October 1985.
+
+ Specifies the format of HOSTS.TXT, the host/address
+ table replaced by the DNS.
+
+
+
+
+
+Mockapetris [Page 51]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+[RFC-953] K. Harrenstien, M. Stahl, E. Feinler, "HOSTNAME Server",
+ RFC-953, SRI, October 1985.
+
+ This RFC contains the official specification of the
+ hostname server protocol, which is obsoleted by the DNS.
+ This TCP based protocol accesses information stored in
+ the RFC-952 format, and is used to obtain copies of the
+ host table.
+
+[RFC-973] P. Mockapetris, "Domain System Changes and
+ Observations", RFC-973, USC/Information Sciences
+ Institute, January 1986.
+
+ Describes changes to RFC-882 and RFC-883 and reasons for
+ them.
+
+[RFC-974] C. Partridge, "Mail routing and the domain system",
+ RFC-974, CSNET CIC BBN Labs, January 1986.
+
+ Describes the transition from HOSTS.TXT based mail
+ addressing to the more powerful MX system used with the
+ domain system.
+
+[RFC-1001] NetBIOS Working Group, "Protocol standard for a NetBIOS
+ service on a TCP/UDP transport: Concepts and Methods",
+ RFC-1001, March 1987.
+
+ This RFC and RFC-1002 are a preliminary design for
+ NETBIOS on top of TCP/IP which proposes to base NetBIOS
+ name service on top of the DNS.
+
+[RFC-1002] NetBIOS Working Group, "Protocol standard for a NetBIOS
+ service on a TCP/UDP transport: Detailed
+ Specifications", RFC-1002, March 1987.
+
+[RFC-1010] J. Reynolds, and J. Postel, "Assigned Numbers", RFC-1010,
+ USC/Information Sciences Institute, May 1987.
+
+ Contains socket numbers and mnemonics for host names,
+ operating systems, etc.
+
+[RFC-1031] W. Lazear, "MILNET Name Domain Transition", RFC-1031,
+ November 1987.
+
+ Describes a plan for converting the MILNET to the DNS.
+
+[RFC-1032] M. Stahl, "Establishing a Domain - Guidelines for
+ Administrators", RFC-1032, November 1987.
+
+
+
+Mockapetris [Page 52]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ Describes the registration policies used by the NIC to
+ administer the top level domains and delegate subzones.
+
+[RFC-1033] M. Lottor, "Domain Administrators Operations Guide",
+ RFC-1033, November 1987.
+
+ A cookbook for domain administrators.
+
+[Solomon 82] M. Solomon, L. Landweber, and D. Neuhengen, "The CSNET
+ Name Server", Computer Networks, vol 6, nr 3, July 1982.
+
+ Describes a name service for CSNET which is independent
+ from the DNS and DNS use in the CSNET.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 53]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+Index
+
+ * 13
+
+ ; 33, 35
+
+ <character-string> 35
+ <domain-name> 34
+
+ @ 35
+
+ \ 35
+
+ A 12
+
+ Byte order 8
+
+ CH 13
+ Character case 9
+ CLASS 11
+ CNAME 12
+ Completion 42
+ CS 13
+
+ Hesiod 13
+ HINFO 12
+ HS 13
+
+ IN 13
+ IN-ADDR.ARPA domain 22
+ Inverse queries 40
+
+ Mailbox names 47
+ MB 12
+ MD 12
+ MF 12
+ MG 12
+ MINFO 12
+ MINIMUM 20
+ MR 12
+ MX 12
+
+ NS 12
+ NULL 12
+
+ Port numbers 32
+ Primary server 5
+ PTR 12, 18
+
+
+
+Mockapetris [Page 54]
+
+RFC 1035 Domain Implementation and Specification November 1987
+
+
+ QCLASS 13
+ QTYPE 12
+
+ RDATA 12
+ RDLENGTH 11
+
+ Secondary server 5
+ SOA 12
+ Stub resolvers 7
+
+ TCP 32
+ TXT 12
+ TYPE 11
+
+ UDP 32
+
+ WKS 12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 55]
+
diff --git a/doc/rfc/rfc1101.txt b/doc/rfc/rfc1101.txt
new file mode 100644
index 0000000..66c9d8b
--- /dev/null
+++ b/doc/rfc/rfc1101.txt
@@ -0,0 +1,787 @@
+
+
+
+
+
+
+Network Working Group P. Mockapetris
+Request for Comments: 1101 ISI
+Updates: RFCs 1034, 1035 April 1989
+
+
+ DNS Encoding of Network Names and Other Types
+
+
+1. STATUS OF THIS MEMO
+
+ This RFC proposes two extensions to the Domain Name System:
+
+ - A specific method for entering and retrieving RRs which map
+ between network names and numbers.
+
+ - Ideas for a general method for describing mappings between
+ arbitrary identifiers and numbers.
+
+ The method for mapping between network names and addresses is a
+ proposed standard, the ideas for a general method are experimental.
+
+ This RFC assumes that the reader is familiar with the DNS [RFC 1034,
+ RFC 1035] and its use. The data shown is for pedagogical use and
+ does not necessarily reflect the real Internet.
+
+ Distribution of this memo is unlimited.
+
+2. INTRODUCTION
+
+ The DNS is extensible and can be used for a virtually unlimited
+ number of data types, name spaces, etc. New type definitions are
+ occasionally necessary as are revisions or deletions of old types
+ (e.g., MX replacement of MD and MF [RFC 974]), and changes described
+ in [RFC 973]. This RFC describes changes due to the general need to
+ map between identifiers and values, and a specific need for network
+ name support.
+
+ Users wish to be able to use the DNS to map between network names and
+ numbers. This need is the only capability found in HOSTS.TXT which
+ is not available from the DNS. In designing a method to do this,
+ there were two major areas of concern:
+
+ - Several tradeoffs involving control of network names, the
+ syntax of network names, backward compatibility, etc.
+
+ - A desire to create a method which would be sufficiently
+ general to set a good precedent for future mappings,
+ for example, between TCP-port names and numbers,
+
+
+
+Mockapetris [Page 1]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+ autonomous system names and numbers, X.500 Relative
+ Distinguished Names (RDNs) and their servers, or whatever.
+
+ It was impossible to reconcile these two areas of concern for network
+ names because of the desire to unify network number support within
+ existing IP address to host name support. The existing support is
+ the IN-ADDR.ARPA section of the DNS name space. As a result this RFC
+ describes one structure for network names which builds on the
+ existing support for host names, and another family of structures for
+ future yellow pages (YP) functions such as conversions between TCP-
+ port numbers and mnemonics.
+
+ Both structures are described in following sections. Each structure
+ has a discussion of design issues and specific structure
+ recommendations.
+
+ We wish to avoid defining structures and methods which can work but
+ do not because of indifference or errors on the part of system
+ administrators when maintaining the database. The WKS RR is an
+ example. Thus, while we favor distribution as a general method, we
+ also recognize that centrally maintained tables (such as HOSTS.TXT)
+ are usually more consistent though less maintainable and timely.
+ Hence we recommend both specific methods for mapping network names,
+ addresses, and subnets, as well as an instance of the general method
+ for mapping between allocated network numbers and network names.
+ (Allocation is centrally performed by the SRI Network Information
+ Center, aka the NIC).
+
+3. NETWORK NAME ISSUES AND DISCUSSION
+
+ The issues involved in the design were the definition of network name
+ syntax, the mappings to be provided, and possible support for similar
+ functions at the subnet level.
+
+3.1. Network name syntax
+
+ The current syntax for network names, as defined by [RFC 952] is an
+ alphanumeric string of up to 24 characters, which begins with an
+ alpha, and may include "." and "-" except as first and last
+ characters. This is the format which was also used for host names
+ before the DNS. Upward compatibility with existing names might be a
+ goal of any new scheme.
+
+ However, the present syntax has been used to define a flat name
+ space, and hence would prohibit the same distributed name allocation
+ method used for host names. There is some sentiment for allowing the
+ NIC to continue to allocate and regulate network names, much as it
+ allocates numbers, but the majority opinion favors local control of
+
+
+
+Mockapetris [Page 2]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+ network names. Although it would be possible to provide a flat space
+ or a name space in which, for example, the last label of a domain
+ name captured the old-style network name, any such approach would add
+ complexity to the method and create different rules for network names
+ and host names.
+
+ For these reasons, we assume that the syntax of network names will be
+ the same as the expanded syntax for host names permitted in [HR].
+ The new syntax expands the set of names to allow leading digits, so
+ long as the resulting representations do not conflict with IP
+ addresses in decimal octet form. For example, 3Com.COM and 3M.COM
+ are now legal, although 26.0.0.73.COM is not. See [HR] for details.
+
+ The price is that network names will get as complicated as host
+ names. An administrator will be able to create network names in any
+ domain under his control, and also create network number to name
+ entries in IN-ADDR.ARPA domains under his control. Thus, the name
+ for the ARPANET might become NET.ARPA, ARPANET.ARPA or Arpa-
+ network.MIL., depending on the preferences of the owner.
+
+3.2. Mappings
+
+ The desired mappings, ranked by priority with most important first,
+ are:
+
+ - Mapping a IP address or network number to a network name.
+
+ This mapping is for use in debugging tools and status displays
+ of various sorts. The conversion from IP address to network
+ number is well known for class A, B, and C IP addresses, and
+ involves a simple mask operation. The needs of other classes
+ are not yet defined and are ignored for the rest of this RFC.
+
+ - Mapping a network name to a network address.
+
+ This facility is of less obvious application, but a
+ symmetrical mapping seems desirable.
+
+ - Mapping an organization to its network names and numbers.
+
+ This facility is useful because it may not always be possible
+ to guess the local choice for network names, but the
+ organization name is often well known.
+
+ - Similar mappings for subnets, even when nested.
+
+ The primary application is to be able to identify all of the
+ subnets involved in a particular IP address. A secondary
+
+
+
+Mockapetris [Page 3]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+ requirement is to retrieve address mask information.
+
+3.3. Network address section of the name space
+
+ The network name syntax discussed above can provide domain names
+ which will contain mappings from network names to various quantities,
+ but we also need a section of the name space, organized by network
+ and subnet number to hold the inverse mappings.
+
+ The choices include:
+
+ - The same network number slots already assigned and delegated
+ in the IN-ADDR.ARPA section of the name space.
+
+ For example, 10.IN-ADDR.ARPA for class A net 10,
+ 2.128.IN-ADDR.ARPA for class B net 128.2, etc.
+
+ - Host-zero addresses in the IN-ADDR.ARPA tree. (A host field
+ of all zero in an IP address is prohibited because of
+ confusion related to broadcast addresses, et al.)
+
+ For example, 0.0.0.10.IN-ADDR.ARPA for class A net 10,
+ 0.0.2.128.IN-ADDR.arpa for class B net 128.2, etc. Like the
+ first scheme, it uses in-place name space delegations to
+ distribute control.
+
+ The main advantage of this scheme over the first is that it
+ allows convenient names for subnets as well as networks. A
+ secondary advantage is that it uses names which are not in use
+ already, and hence it is possible to test whether an
+ organization has entered this information in its domain
+ database.
+
+ - Some new section of the name space.
+
+ While this option provides the most opportunities, it creates
+ a need to delegate a whole new name space. Since the IP
+ address space is so closely related to the network number
+ space, most believe that the overhead of creating such a new
+ space is overwhelming and would lead to the WKS syndrome. (As
+ of February, 1989, approximately 400 sections of the
+ IN-ADDR.ARPA tree are already delegated, usually at network
+ boundaries.)
+
+
+
+
+
+
+
+
+Mockapetris [Page 4]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+4. SPECIFICS FOR NETWORK NAME MAPPINGS
+
+ The proposed solution uses information stored at:
+
+ - Names in the IN-ADDR.ARPA tree that correspond to host-zero IP
+ addresses. The same method is used for subnets in a nested
+ fashion. For example, 0.0.0.10.IN-ADDR.ARPA. for net 10.
+
+ Two types of information are stored here: PTR RRs which point
+ to the network name in their data sections, and A RRs, which
+ are present if the network (or subnet) is subnetted further.
+ If a type A RR is present, then it has the address mask as its
+ data. The general form is:
+
+ <reversed-host-zero-number>.IN-ADDR.ARPA. PTR <network-name>
+ <reversed-host-zero-number>.IN-ADDR.ARPA. A <subnet-mask>
+
+ For example:
+
+ 0.0.0.10.IN-ADDR.ARPA. PTR ARPANET.ARPA.
+
+ or
+
+ 0.0.2.128.IN-ADDR.ARPA. PTR cmu-net.cmu.edu.
+ A 255.255.255.0
+
+ In general, this information will be added to an existing
+ master file for some IN-ADDR.ARPA domain for each network
+ involved. Similar RRs can be used at host-zero subnet
+ entries.
+
+ - Names which are network names.
+
+ The data stored here is PTR RRs pointing at the host-zero
+ entries. The general form is:
+
+ <network-name> ptr <reversed-host-zero-number>.IN-ADDR.ARPA
+
+ For example:
+
+ ARPANET.ARPA. PTR 0.0.0.10.IN-ADDR.ARPA.
+
+ or
+
+ isi-net.isi.edu. PTR 0.0.9.128.IN-ADDR.ARPA.
+
+ In general, this information will be inserted in the master
+ file for the domain name of the organization; this is a
+
+
+
+Mockapetris [Page 5]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+ different file from that which holds the information below
+ IN-ADDR.ARPA. Similar PTR RRs can be used at subnet names.
+
+ - Names corresponding to organizations.
+
+ The data here is one or more PTR RRs pointing at the
+ IN-ADDR.ARPA names corresponding to host-zero entries for
+ networks.
+
+ For example:
+
+ ISI.EDU. PTR 0.0.9.128.IN-ADDR.ARPA.
+
+ MCC.COM. PTR 0.167.5.192.IN-ADDR.ARPA.
+ PTR 0.168.5.192.IN-ADDR.ARPA.
+ PTR 0.169.5.192.IN-ADDR.ARPA.
+ PTR 0.0.62.128.IN-ADDR.ARPA.
+
+4.1. A simple example
+
+ The ARPANET is a Class A network without subnets. The RRs which
+ would be added, assuming the ARPANET.ARPA was selected as a network
+ name, would be:
+
+ ARPA. PTR 0.0.0.10.IN-ADDR.ARPA.
+
+ ARPANET.ARPA. PTR 0.0.0.10.IN-ADDR.ARPA.
+
+ 0.0.0.10.IN-ADDR.ARPA. PTR ARPANET.ARPA.
+
+ The first RR states that the organization named ARPA owns net 10 (It
+ might also own more network numbers, and these would be represented
+ with an additional RR per net.) The second states that the network
+ name ARPANET.ARPA. maps to net 10. The last states that net 10 is
+ named ARPANET.ARPA.
+
+ Note that all of the usual host and corresponding IN-ADDR.ARPA
+ entries would still be required.
+
+4.2. A complicated, subnetted example
+
+ The ISI network is 128.9, a class B number. Suppose the ISI network
+ was organized into two levels of subnet, with the first level using
+ an additional 8 bits of address, and the second level using 4 bits,
+ for address masks of x'FFFFFF00' and X'FFFFFFF0'.
+
+ Then the following RRs would be entered in ISI's master file for the
+ ISI.EDU zone:
+
+
+
+Mockapetris [Page 6]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+ ; Define network entry
+ isi-net.isi.edu. PTR 0.0.9.128.IN-ADDR.ARPA.
+
+ ; Define first level subnets
+ div1-subnet.isi.edu. PTR 0.1.9.128.IN-ADDR.ARPA.
+ div2-subnet.isi.edu. PTR 0.2.9.128.IN-ADDR.ARPA.
+
+ ; Define second level subnets
+ inc-subsubnet.isi.edu. PTR 16.2.9.128.IN-ADDR.ARPA.
+
+ in the 9.128.IN-ADDR.ARPA zone:
+
+ ; Define network number and address mask
+ 0.0.9.128.IN-ADDR.ARPA. PTR isi-net.isi.edu.
+ A 255.255.255.0 ;aka X'FFFFFF00'
+
+ ; Define one of the first level subnet numbers and masks
+ 0.1.9.128.IN-ADDR.ARPA. PTR div1-subnet.isi.edu.
+ A 255.255.255.240 ;aka X'FFFFFFF0'
+
+ ; Define another first level subnet number and mask
+ 0.2.9.128.IN-ADDR.ARPA. PTR div2-subnet.isi.edu.
+ A 255.255.255.240 ;aka X'FFFFFFF0'
+
+ ; Define second level subnet number
+ 16.2.9.128.IN-ADDR.ARPA. PTR inc-subsubnet.isi.edu.
+
+ This assumes that the ISI network is named isi-net.isi.edu., first
+ level subnets are named div1-subnet.isi.edu. and div2-
+ subnet.isi.edu., and a second level subnet is called inc-
+ subsubnet.isi.edu. (In a real system as complicated as this there
+ would be more first and second level subnets defined, but we have
+ shown enough to illustrate the ideas.)
+
+4.3. Procedure for using an IP address to get network name
+
+ Depending on whether the IP address is class A, B, or C, mask off the
+ high one, two, or three bytes, respectively. Reverse the octets,
+ suffix IN-ADDR.ARPA, and do a PTR query.
+
+ For example, suppose the IP address is 10.0.0.51.
+
+ 1. Since this is a class A address, use a mask x'FF000000' and
+ get 10.0.0.0.
+
+ 2. Construct the name 0.0.0.10.IN-ADDR.ARPA.
+
+ 3. Do a PTR query. Get back
+
+
+
+Mockapetris [Page 7]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+ 0.0.0.10.IN-ADDR.ARPA. PTR ARPANET.ARPA.
+
+ 4. Conclude that the network name is "ARPANET.ARPA."
+
+ Suppose that the IP address is 128.9.2.17.
+
+ 1. Since this is a class B address, use a mask of x'FFFF0000'
+ and get 128.9.0.0.
+
+ 2. Construct the name 0.0.9.128.IN-ADDR.ARPA.
+
+ 3. Do a PTR query. Get back
+
+ 0.0.9.128.IN-ADDR.ARPA. PTR isi-net.isi.edu
+
+ 4. Conclude that the network name is "isi-net.isi.edu."
+
+4.4. Procedure for finding all subnets involved with an IP address
+
+ This is a simple extension of the IP address to network name method.
+ When the network entry is located, do a lookup for a possible A RR.
+ If the A RR is found, look up the next level of subnet using the
+ original IP address and the mask in the A RR. Repeat this procedure
+ until no A RR is found.
+
+ For example, repeating the use of 128.9.2.17.
+
+ 1. As before construct a query for 0.0.9.128.IN-ADDR.ARPA.
+ Retrieve:
+
+ 0.0.9.128.IN-ADDR.ARPA. PTR isi-net.isi.edu.
+ A 255.255.255.0
+
+ 2. Since an A RR was found, repeat using mask from RR
+ (255.255.255.0), constructing a query for
+ 0.2.9.128.IN-ADDR.ARPA. Retrieve:
+
+ 0.2.9.128.IN-ADDR.ARPA. PTR div2-subnet.isi.edu.
+ A 255.255.255.240
+
+ 3. Since another A RR was found, repeat using mask
+ 255.255.255.240 (x'FFFFFFF0'). constructing a query for
+ 16.2.9.128.IN-ADDR.ARPA. Retrieve:
+
+ 16.2.9.128.IN-ADDR.ARPA. PTR inc-subsubnet.isi.edu.
+
+ 4. Since no A RR is present at 16.2.9.128.IN-ADDR.ARPA., there
+ are no more subnet levels.
+
+
+
+Mockapetris [Page 8]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+5. YP ISSUES AND DISCUSSION
+
+ The term "Yellow Pages" is used in almost as many ways as the term
+ "domain", so it is useful to define what is meant herein by YP. The
+ general problem to be solved is to create a method for creating
+ mappings from one kind of identifier to another, often with an
+ inverse capability. The traditional methods are to search or use a
+ precomputed index of some kind.
+
+ Searching is impractical when the search is too large, and
+ precomputed indexes are possible only when it is possible to specify
+ search criteria in advance, and pay for the resources necessary to
+ build the index. For example, it is impractical to search the entire
+ domain tree to find a particular address RR, so we build the IN-
+ ADDR.ARPA YP. Similarly, we could never build an Internet-wide index
+ of "hosts with a load average of less than 2" in less time than it
+ would take for the data to change, so indexes are a useless approach
+ for that problem.
+
+ Such a precomputed index is what we mean by YP, and we regard the
+ IN-ADDR.ARPA domain as the first instance of a YP in the DNS.
+ Although a single, centrally-managed YP for well-known values such as
+ TCP-port is desirable, we regard organization-specific YPs for, say,
+ locally defined TCP ports as a natural extension, as are combinations
+ of YPs using search lists to merge the two.
+
+ In examining Internet Numbers [RFC 997] and Assigned Numbers [RFC
+ 1010], it is clear that there are several mappings which might be of
+ value. For example:
+
+ <assigned-network-name> <==> <IP-address>
+ <autonomous-system-id> <==> <number>
+ <protocol-id> <==> <number>
+ <port-id> <==> <number>
+ <ethernet-type> <==> <number>
+ <public-data-net> <==> <IP-address>
+
+ Following the IN-ADDR example, the YP takes the form of a domain tree
+ organized to optimize retrieval by search key and distribution via
+ normal DNS rules. The name used as a key must include:
+
+ 1. A well known origin. For example, IN-ADDR.ARPA is the
+ current IP-address to host name YP.
+
+ 2. A "from" data type. This identifies the input type of the
+ mapping. This is necessary because we may be mapping
+ something as anonymous as a number to any number of
+ mnemonics, etc.
+
+
+
+Mockapetris [Page 9]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+ 3. A "to" data type. Since we assume several symmetrical
+ mnemonic <==> number mappings, this is also necessary.
+
+ This ordering reflects the natural scoping of control, and hence the
+ order of the components in a domain name. Thus domain names would be
+ of the form:
+
+ <from-value>.<to-data-type>.<from-data-type>.<YP-origin>
+
+ To make this work, we need to define well-know strings for each of
+ these metavariables, as well as encoding rules for converting a
+ <from-value> into a domain name. We might define:
+
+ <YP-origin> :=YP
+ <from-data-type>:=TCP-port | IN-ADDR | Number |
+ Assigned-network-number | Name
+ <to-data-type> :=<from-data-type>
+
+ Note that "YP" is NOT a valid country code under [ISO 3166] (although
+ we may want to worry about the future), and the existence of a
+ syntactically valid <to-data-type>.<from-data-type> pair does not
+ imply that a meaningful mapping exists, or is even possible.
+
+ The encoding rules might be:
+
+ TCP-port Six character alphanumeric
+
+ IN-ADDR Reversed 4-octet decimal string
+
+ Number decimal integer
+
+ Assigned-network-number
+ Reversed 4-octet decimal string
+
+ Name Domain name
+
+6. SPECIFICS FOR YP MAPPINGS
+
+6.1. TCP-PORT
+
+ $origin Number.TCP-port.YP.
+
+ 23 PTR TELNET.TCP-port.Number.YP.
+ 25 PTR SMTP.TCP-port.Number.YP.
+
+ $origin TCP-port.Number.YP.
+
+ TELNET PTR 23.Number.TCP-port.YP.
+
+
+
+Mockapetris [Page 10]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+ SMTP PTR 25.Number.TCP-port.YP.
+
+ Thus the mapping between 23 and TELNET is represented by a pair of
+ PTR RRs, one for each direction of the mapping.
+
+6.2. Assigned networks
+
+ Network numbers are assigned by the NIC and reported in "Internet
+ Numbers" RFCs. To create a YP, the NIC would set up two domains:
+
+ Name.Assigned-network-number.YP and Assigned-network-number.YP
+
+ The first would contain entries of the form:
+
+ $origin Name.Assigned-network-number.YP.
+
+ 0.0.0.4 PTR SATNET.Assigned-network-number.Name.YP.
+ 0.0.0.10 PTR ARPANET.Assigned-network-number.Name.YP.
+
+ The second would contain entries of the form:
+
+ $origin Assigned-network-number.Name.YP.
+
+ SATNET. PTR 0.0.0.4.Name.Assigned-network-number.YP.
+ ARPANET. PTR 0.0.0.10.Name.Assigned-network-number.YP.
+
+ These YPs are not in conflict with the network name support described
+ in the first half of this RFC since they map between ASSIGNED network
+ names and numbers, not those allocated by the organizations
+ themselves. That is, they document the NIC's decisions about
+ allocating network numbers but do not automatically track any
+ renaming performed by the new owners.
+
+ As a practical matter, we might want to create both of these domains
+ to enable users on the Internet to experiment with centrally
+ maintained support as well as the distributed version, or might want
+ to implement only the allocated number to name mapping and request
+ organizations to convert their allocated network names to the network
+ names described in the distributed model.
+
+6.3. Operational improvements
+
+ We could imagine that all conversion routines using these YPs might
+ be instructed to use "YP.<local-domain>" followed by "YP." as a
+ search list. Thus, if the organization ISI.EDU wished to define
+ locally meaningful TCP-PORT, it would define the domains:
+
+ <TCP-port.Number.YP.ISI.EDU> and <Number.TCP-port.YP.ISI.EDU>.
+
+
+
+Mockapetris [Page 11]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+ We could add another level of indirection in the YP lookup, defining
+ the <to-data-type>.<from-data-type>.<YP-origin> nodes to point to the
+ YP tree, rather than being the YP tree directly. This would enable
+ entries of the form:
+
+ IN-ADDR.Netname.YP. PTR IN-ADDR.ARPA.
+
+ to splice in YPs from other origins or existing spaces.
+
+ Another possibility would be to shorten the RDATA section of the RRs
+ which map back and forth by deleting the origin. This could be done
+ either by allowing the domain name in the RDATA portion to not
+ identify a real domain name, or by defining a new RR which used a
+ simple text string rather than a domain name.
+
+ Thus, we might replace
+
+ $origin Assigned-network-number.Name.YP.
+
+ SATNET. PTR 0.0.0.4.Name.Assigned-network-number.YP.
+ ARPANET. PTR 0.0.0.10.Name.Assigned-network-number.YP.
+
+ with
+
+ $origin Assigned-network-number.Name.YP.
+
+ SATNET. PTR 0.0.0.4.
+ ARPANET. PTR 0.0.0.10.
+
+ or
+
+ $origin Assigned-network-number.Name.YP.
+
+ SATNET. PTT "0.0.0.4"
+ ARPANET. PTT "0.0.0.10"
+
+ where PTT is a new type whose RDATA section is a text string.
+
+7. ACKNOWLEDGMENTS
+
+ Drew Perkins, Mark Lottor, and Rob Austein contributed several of the
+ ideas in this RFC. Numerous contributions, criticisms, and
+ compromises were produced in the IETF Domain working group and the
+ NAMEDROPPERS mailing list.
+
+
+
+
+
+
+
+Mockapetris [Page 12]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+8. REFERENCES
+
+ [HR] Braden, B., editor, "Requirements for Internet Hosts",
+ RFC in preparation.
+
+ [ISO 3166] ISO, "Codes for the Representation of Names of
+ Countries", 1981.
+
+ [RFC 882] Mockapetris, P., "Domain names - Concepts and
+ Facilities", RFC 882, USC/Information Sciences Institute,
+ November 1983.
+
+ Superseded by RFC 1034.
+
+ [RFC 883] Mockapetris, P.,"Domain names - Implementation and
+ Specification", RFC 883, USC/Information Sciences
+ Institute, November 1983.
+
+ Superceeded by RFC 1035.
+
+ [RFC 920] Postel, J. and J. Reynolds, "Domain Requirements", RFC
+ 920, October 1984.
+
+ Explains the naming scheme for top level domains.
+
+ [RFC 952] Harrenstien, K., M. Stahl, and E. Feinler, "DoD Internet
+ Host Table Specification", RFC 952, SRI, October 1985.
+
+ Specifies the format of HOSTS.TXT, the host/address table
+ replaced by the DNS
+
+ [RFC 973] Mockapetris, P., "Domain System Changes and
+ Observations", RFC 973, USC/Information Sciences
+ Institute, January 1986.
+
+ Describes changes to RFCs 882 and 883 and reasons for
+ them.
+
+ [RFC 974] Partridge, C., "Mail routing and the domain system", RFC
+ 974, CSNET CIC BBN Labs, January 1986.
+
+ Describes the transition from HOSTS.TXT based mail
+ addressing to the more powerful MX system used with the
+ domain system.
+
+
+
+
+
+
+
+Mockapetris [Page 13]
+
+RFC 1101 DNS Encoding of Network Names and Other Types April 1989
+
+
+ [RFC 997] Reynolds, J., and J. Postel, "Internet Numbers", RFC 997,
+ USC/Information Sciences Institute, March 1987
+
+ Contains network numbers, autonomous system numbers, etc.
+
+ [RFC 1010] Reynolds, J., and J. Postel, "Assigned Numbers", RFC
+ 1010, USC/Information Sciences Institute, May 1987
+
+ Contains socket numbers and mnemonics for host names,
+ operating systems, etc.
+
+
+ [RFC 1034] Mockapetris, P., "Domain names - Concepts and
+ Facilities", RFC 1034, USC/Information Sciences
+ Institute, November 1987.
+
+ Introduction/overview of the DNS.
+
+ [RFC 1035] Mockapetris, P., "Domain names - Implementation and
+ Specification", RFC 1035, USC/Information Sciences
+ Institute, November 1987.
+
+ DNS implementation instructions.
+
+Author's Address:
+
+ Paul Mockapetris
+ USC/Information Sciences Institute
+ 4676 Admiralty Way
+ Marina del Rey, CA 90292
+
+ Phone: (213) 822-1511
+
+ Email: PVM@ISI.EDU
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mockapetris [Page 14]
+ \ No newline at end of file
diff --git a/doc/rfc/rfc1122.txt b/doc/rfc/rfc1122.txt
new file mode 100644
index 0000000..c14f2e5
--- /dev/null
+++ b/doc/rfc/rfc1122.txt
@@ -0,0 +1,6844 @@
+
+
+
+
+
+
+Network Working Group Internet Engineering Task Force
+Request for Comments: 1122 R. Braden, Editor
+ October 1989
+
+
+ Requirements for Internet Hosts -- Communication Layers
+
+
+Status of This Memo
+
+ This RFC is an official specification for the Internet community. It
+ incorporates by reference, amends, corrects, and supplements the
+ primary protocol standards documents relating to hosts. Distribution
+ of this document is unlimited.
+
+Summary
+
+ This is one RFC of a pair that defines and discusses the requirements
+ for Internet host software. This RFC covers the communications
+ protocol layers: link layer, IP layer, and transport layer; its
+ companion RFC-1123 covers the application and support protocols.
+
+
+
+ Table of Contents
+
+
+
+
+ 1. INTRODUCTION ............................................... 5
+ 1.1 The Internet Architecture .............................. 6
+ 1.1.1 Internet Hosts .................................... 6
+ 1.1.2 Architectural Assumptions ......................... 7
+ 1.1.3 Internet Protocol Suite ........................... 8
+ 1.1.4 Embedded Gateway Code ............................. 10
+ 1.2 General Considerations ................................. 12
+ 1.2.1 Continuing Internet Evolution ..................... 12
+ 1.2.2 Robustness Principle .............................. 12
+ 1.2.3 Error Logging ..................................... 13
+ 1.2.4 Configuration ..................................... 14
+ 1.3 Reading this Document .................................. 15
+ 1.3.1 Organization ...................................... 15
+ 1.3.2 Requirements ...................................... 16
+ 1.3.3 Terminology ....................................... 17
+ 1.4 Acknowledgments ........................................ 20
+
+ 2. LINK LAYER .................................................. 21
+ 2.1 INTRODUCTION ........................................... 21
+
+
+
+Internet Engineering Task Force [Page 1]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ 2.2 PROTOCOL WALK-THROUGH .................................. 21
+ 2.3 SPECIFIC ISSUES ........................................ 21
+ 2.3.1 Trailer Protocol Negotiation ...................... 21
+ 2.3.2 Address Resolution Protocol -- ARP ................ 22
+ 2.3.2.1 ARP Cache Validation ......................... 22
+ 2.3.2.2 ARP Packet Queue ............................. 24
+ 2.3.3 Ethernet and IEEE 802 Encapsulation ............... 24
+ 2.4 LINK/INTERNET LAYER INTERFACE .......................... 25
+ 2.5 LINK LAYER REQUIREMENTS SUMMARY ........................ 26
+
+ 3. INTERNET LAYER PROTOCOLS .................................... 27
+ 3.1 INTRODUCTION ............................................ 27
+ 3.2 PROTOCOL WALK-THROUGH .................................. 29
+ 3.2.1 Internet Protocol -- IP ............................ 29
+ 3.2.1.1 Version Number ............................... 29
+ 3.2.1.2 Checksum ..................................... 29
+ 3.2.1.3 Addressing ................................... 29
+ 3.2.1.4 Fragmentation and Reassembly ................. 32
+ 3.2.1.5 Identification ............................... 32
+ 3.2.1.6 Type-of-Service .............................. 33
+ 3.2.1.7 Time-to-Live ................................. 34
+ 3.2.1.8 Options ...................................... 35
+ 3.2.2 Internet Control Message Protocol -- ICMP .......... 38
+ 3.2.2.1 Destination Unreachable ...................... 39
+ 3.2.2.2 Redirect ..................................... 40
+ 3.2.2.3 Source Quench ................................ 41
+ 3.2.2.4 Time Exceeded ................................ 41
+ 3.2.2.5 Parameter Problem ............................ 42
+ 3.2.2.6 Echo Request/Reply ........................... 42
+ 3.2.2.7 Information Request/Reply .................... 43
+ 3.2.2.8 Timestamp and Timestamp Reply ................ 43
+ 3.2.2.9 Address Mask Request/Reply ................... 45
+ 3.2.3 Internet Group Management Protocol IGMP ........... 47
+ 3.3 SPECIFIC ISSUES ........................................ 47
+ 3.3.1 Routing Outbound Datagrams ........................ 47
+ 3.3.1.1 Local/Remote Decision ........................ 47
+ 3.3.1.2 Gateway Selection ............................ 48
+ 3.3.1.3 Route Cache .................................. 49
+ 3.3.1.4 Dead Gateway Detection ....................... 51
+ 3.3.1.5 New Gateway Selection ........................ 55
+ 3.3.1.6 Initialization ............................... 56
+ 3.3.2 Reassembly ........................................ 56
+ 3.3.3 Fragmentation ..................................... 58
+ 3.3.4 Local Multihoming ................................. 60
+ 3.3.4.1 Introduction ................................. 60
+ 3.3.4.2 Multihoming Requirements ..................... 61
+ 3.3.4.3 Choosing a Source Address .................... 64
+ 3.3.5 Source Route Forwarding ........................... 65
+
+
+
+Internet Engineering Task Force [Page 2]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ 3.3.6 Broadcasts ........................................ 66
+ 3.3.7 IP Multicasting ................................... 67
+ 3.3.8 Error Reporting ................................... 69
+ 3.4 INTERNET/TRANSPORT LAYER INTERFACE ..................... 69
+ 3.5 INTERNET LAYER REQUIREMENTS SUMMARY .................... 72
+
+ 4. TRANSPORT PROTOCOLS ......................................... 77
+ 4.1 USER DATAGRAM PROTOCOL -- UDP .......................... 77
+ 4.1.1 INTRODUCTION ...................................... 77
+ 4.1.2 PROTOCOL WALK-THROUGH ............................. 77
+ 4.1.3 SPECIFIC ISSUES ................................... 77
+ 4.1.3.1 Ports ........................................ 77
+ 4.1.3.2 IP Options ................................... 77
+ 4.1.3.3 ICMP Messages ................................ 78
+ 4.1.3.4 UDP Checksums ................................ 78
+ 4.1.3.5 UDP Multihoming .............................. 79
+ 4.1.3.6 Invalid Addresses ............................ 79
+ 4.1.4 UDP/APPLICATION LAYER INTERFACE ................... 79
+ 4.1.5 UDP REQUIREMENTS SUMMARY .......................... 80
+ 4.2 TRANSMISSION CONTROL PROTOCOL -- TCP ................... 82
+ 4.2.1 INTRODUCTION ...................................... 82
+ 4.2.2 PROTOCOL WALK-THROUGH ............................. 82
+ 4.2.2.1 Well-Known Ports ............................. 82
+ 4.2.2.2 Use of Push .................................. 82
+ 4.2.2.3 Window Size .................................. 83
+ 4.2.2.4 Urgent Pointer ............................... 84
+ 4.2.2.5 TCP Options .................................. 85
+ 4.2.2.6 Maximum Segment Size Option .................. 85
+ 4.2.2.7 TCP Checksum ................................. 86
+ 4.2.2.8 TCP Connection State Diagram ................. 86
+ 4.2.2.9 Initial Sequence Number Selection ............ 87
+ 4.2.2.10 Simultaneous Open Attempts .................. 87
+ 4.2.2.11 Recovery from Old Duplicate SYN ............. 87
+ 4.2.2.12 RST Segment ................................. 87
+ 4.2.2.13 Closing a Connection ........................ 87
+ 4.2.2.14 Data Communication .......................... 89
+ 4.2.2.15 Retransmission Timeout ...................... 90
+ 4.2.2.16 Managing the Window ......................... 91
+ 4.2.2.17 Probing Zero Windows ........................ 92
+ 4.2.2.18 Passive OPEN Calls .......................... 92
+ 4.2.2.19 Time to Live ................................ 93
+ 4.2.2.20 Event Processing ............................ 93
+ 4.2.2.21 Acknowledging Queued Segments ............... 94
+ 4.2.3 SPECIFIC ISSUES ................................... 95
+ 4.2.3.1 Retransmission Timeout Calculation ........... 95
+ 4.2.3.2 When to Send an ACK Segment .................. 96
+ 4.2.3.3 When to Send a Window Update ................. 97
+ 4.2.3.4 When to Send Data ............................ 98
+
+
+
+Internet Engineering Task Force [Page 3]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ 4.2.3.5 TCP Connection Failures ...................... 100
+ 4.2.3.6 TCP Keep-Alives .............................. 101
+ 4.2.3.7 TCP Multihoming .............................. 103
+ 4.2.3.8 IP Options ................................... 103
+ 4.2.3.9 ICMP Messages ................................ 103
+ 4.2.3.10 Remote Address Validation ................... 104
+ 4.2.3.11 TCP Traffic Patterns ........................ 104
+ 4.2.3.12 Efficiency .................................. 105
+ 4.2.4 TCP/APPLICATION LAYER INTERFACE ................... 106
+ 4.2.4.1 Asynchronous Reports ......................... 106
+ 4.2.4.2 Type-of-Service .............................. 107
+ 4.2.4.3 Flush Call ................................... 107
+ 4.2.4.4 Multihoming .................................. 108
+ 4.2.5 TCP REQUIREMENT SUMMARY ........................... 108
+
+ 5. REFERENCES ................................................. 112
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 4]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+1. INTRODUCTION
+
+ This document is one of a pair that defines and discusses the
+ requirements for host system implementations of the Internet protocol
+ suite. This RFC covers the communication protocol layers: link
+ layer, IP layer, and transport layer. Its companion RFC,
+ "Requirements for Internet Hosts -- Application and Support"
+ [INTRO:1], covers the application layer protocols. This document
+ should also be read in conjunction with "Requirements for Internet
+ Gateways" [INTRO:2].
+
+ These documents are intended to provide guidance for vendors,
+ implementors, and users of Internet communication software. They
+ represent the consensus of a large body of technical experience and
+ wisdom, contributed by the members of the Internet research and
+ vendor communities.
+
+ This RFC enumerates standard protocols that a host connected to the
+ Internet must use, and it incorporates by reference the RFCs and
+ other documents describing the current specifications for these
+ protocols. It corrects errors in the referenced documents and adds
+ additional discussion and guidance for an implementor.
+
+ For each protocol, this document also contains an explicit set of
+ requirements, recommendations, and options. The reader must
+ understand that the list of requirements in this document is
+ incomplete by itself; the complete set of requirements for an
+ Internet host is primarily defined in the standard protocol
+ specification documents, with the corrections, amendments, and
+ supplements contained in this RFC.
+
+ A good-faith implementation of the protocols that was produced after
+ careful reading of the RFC's and with some interaction with the
+ Internet technical community, and that followed good communications
+ software engineering practices, should differ from the requirements
+ of this document in only minor ways. Thus, in many cases, the
+ "requirements" in this RFC are already stated or implied in the
+ standard protocol documents, so that their inclusion here is, in a
+ sense, redundant. However, they were included because some past
+ implementation has made the wrong choice, causing problems of
+ interoperability, performance, and/or robustness.
+
+ This document includes discussion and explanation of many of the
+ requirements and recommendations. A simple list of requirements
+ would be dangerous, because:
+
+ o Some required features are more important than others, and some
+ features are optional.
+
+
+
+Internet Engineering Task Force [Page 5]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ o There may be valid reasons why particular vendor products that
+ are designed for restricted contexts might choose to use
+ different specifications.
+
+ However, the specifications of this document must be followed to meet
+ the general goal of arbitrary host interoperation across the
+ diversity and complexity of the Internet system. Although most
+ current implementations fail to meet these requirements in various
+ ways, some minor and some major, this specification is the ideal
+ towards which we need to move.
+
+ These requirements are based on the current level of Internet
+ architecture. This document will be updated as required to provide
+ additional clarifications or to include additional information in
+ those areas in which specifications are still evolving.
+
+ This introductory section begins with a brief overview of the
+ Internet architecture as it relates to hosts, and then gives some
+ general advice to host software vendors. Finally, there is some
+ guidance on reading the rest of the document and some terminology.
+
+ 1.1 The Internet Architecture
+
+ General background and discussion on the Internet architecture and
+ supporting protocol suite can be found in the DDN Protocol
+ Handbook [INTRO:3]; for background see for example [INTRO:9],
+ [INTRO:10], and [INTRO:11]. Reference [INTRO:5] describes the
+ procedure for obtaining Internet protocol documents, while
+ [INTRO:6] contains a list of the numbers assigned within Internet
+ protocols.
+
+ 1.1.1 Internet Hosts
+
+ A host computer, or simply "host," is the ultimate consumer of
+ communication services. A host generally executes application
+ programs on behalf of user(s), employing network and/or
+ Internet communication services in support of this function.
+ An Internet host corresponds to the concept of an "End-System"
+ used in the OSI protocol suite [INTRO:13].
+
+ An Internet communication system consists of interconnected
+ packet networks supporting communication among host computers
+ using the Internet protocols. The networks are interconnected
+ using packet-switching computers called "gateways" or "IP
+ routers" by the Internet community, and "Intermediate Systems"
+ by the OSI world [INTRO:13]. The RFC "Requirements for
+ Internet Gateways" [INTRO:2] contains the official
+ specifications for Internet gateways. That RFC together with
+
+
+
+Internet Engineering Task Force [Page 6]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ the present document and its companion [INTRO:1] define the
+ rules for the current realization of the Internet architecture.
+
+ Internet hosts span a wide range of size, speed, and function.
+ They range in size from small microprocessors through
+ workstations to mainframes and supercomputers. In function,
+ they range from single-purpose hosts (such as terminal servers)
+ to full-service hosts that support a variety of online network
+ services, typically including remote login, file transfer, and
+ electronic mail.
+
+ A host is generally said to be multihomed if it has more than
+ one interface to the same or to different networks. See
+ Section 1.1.3 on "Terminology".
+
+ 1.1.2 Architectural Assumptions
+
+ The current Internet architecture is based on a set of
+ assumptions about the communication system. The assumptions
+ most relevant to hosts are as follows:
+
+ (a) The Internet is a network of networks.
+
+ Each host is directly connected to some particular
+ network(s); its connection to the Internet is only
+ conceptual. Two hosts on the same network communicate
+ with each other using the same set of protocols that they
+ would use to communicate with hosts on distant networks.
+
+ (b) Gateways don't keep connection state information.
+
+ To improve robustness of the communication system,
+ gateways are designed to be stateless, forwarding each IP
+ datagram independently of other datagrams. As a result,
+ redundant paths can be exploited to provide robust service
+ in spite of failures of intervening gateways and networks.
+
+ All state information required for end-to-end flow control
+ and reliability is implemented in the hosts, in the
+ transport layer or in application programs. All
+ connection control information is thus co-located with the
+ end points of the communication, so it will be lost only
+ if an end point fails.
+
+ (c) Routing complexity should be in the gateways.
+
+ Routing is a complex and difficult problem, and ought to
+ be performed by the gateways, not the hosts. An important
+
+
+
+Internet Engineering Task Force [Page 7]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ objective is to insulate host software from changes caused
+ by the inevitable evolution of the Internet routing
+ architecture.
+
+ (d) The System must tolerate wide network variation.
+
+ A basic objective of the Internet design is to tolerate a
+ wide range of network characteristics -- e.g., bandwidth,
+ delay, packet loss, packet reordering, and maximum packet
+ size. Another objective is robustness against failure of
+ individual networks, gateways, and hosts, using whatever
+ bandwidth is still available. Finally, the goal is full
+ "open system interconnection": an Internet host must be
+ able to interoperate robustly and effectively with any
+ other Internet host, across diverse Internet paths.
+
+ Sometimes host implementors have designed for less
+ ambitious goals. For example, the LAN environment is
+ typically much more benign than the Internet as a whole;
+ LANs have low packet loss and delay and do not reorder
+ packets. Some vendors have fielded host implementations
+ that are adequate for a simple LAN environment, but work
+ badly for general interoperation. The vendor justifies
+ such a product as being economical within the restricted
+ LAN market. However, isolated LANs seldom stay isolated
+ for long; they are soon gatewayed to each other, to
+ organization-wide internets, and eventually to the global
+ Internet system. In the end, neither the customer nor the
+ vendor is served by incomplete or substandard Internet
+ host software.
+
+ The requirements spelled out in this document are designed
+ for a full-function Internet host, capable of full
+ interoperation over an arbitrary Internet path.
+
+
+ 1.1.3 Internet Protocol Suite
+
+ To communicate using the Internet system, a host must implement
+ the layered set of protocols comprising the Internet protocol
+ suite. A host typically must implement at least one protocol
+ from each layer.
+
+ The protocol layers used in the Internet architecture are as
+ follows [INTRO:4]:
+
+
+ o Application Layer
+
+
+
+Internet Engineering Task Force [Page 8]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ The application layer is the top layer of the Internet
+ protocol suite. The Internet suite does not further
+ subdivide the application layer, although some of the
+ Internet application layer protocols do contain some
+ internal sub-layering. The application layer of the
+ Internet suite essentially combines the functions of the
+ top two layers -- Presentation and Application -- of the
+ OSI reference model.
+
+ We distinguish two categories of application layer
+ protocols: user protocols that provide service directly
+ to users, and support protocols that provide common system
+ functions. Requirements for user and support protocols
+ will be found in the companion RFC [INTRO:1].
+
+ The most common Internet user protocols are:
+
+ o Telnet (remote login)
+ o FTP (file transfer)
+ o SMTP (electronic mail delivery)
+
+ There are a number of other standardized user protocols
+ [INTRO:4] and many private user protocols.
+
+ Support protocols, used for host name mapping, booting,
+ and management, include SNMP, BOOTP, RARP, and the Domain
+ Name System (DNS) protocols.
+
+
+ o Transport Layer
+
+ The transport layer provides end-to-end communication
+ services for applications. There are two primary
+ transport layer protocols at present:
+
+ o Transmission Control Protocol (TCP)
+ o User Datagram Protocol (UDP)
+
+ TCP is a reliable connection-oriented transport service
+ that provides end-to-end reliability, resequencing, and
+ flow control. UDP is a connectionless ("datagram")
+ transport service.
+
+ Other transport protocols have been developed by the
+ research community, and the set of official Internet
+ transport protocols may be expanded in the future.
+
+ Transport layer protocols are discussed in Chapter 4.
+
+
+
+Internet Engineering Task Force [Page 9]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ o Internet Layer
+
+ All Internet transport protocols use the Internet Protocol
+ (IP) to carry data from source host to destination host.
+ IP is a connectionless or datagram internetwork service,
+ providing no end-to-end delivery guarantees. Thus, IP
+ datagrams may arrive at the destination host damaged,
+ duplicated, out of order, or not at all. The layers above
+ IP are responsible for reliable delivery service when it
+ is required. The IP protocol includes provision for
+ addressing, type-of-service specification, fragmentation
+ and reassembly, and security information.
+
+ The datagram or connectionless nature of the IP protocol
+ is a fundamental and characteristic feature of the
+ Internet architecture. Internet IP was the model for the
+ OSI Connectionless Network Protocol [INTRO:12].
+
+ ICMP is a control protocol that is considered to be an
+ integral part of IP, although it is architecturally
+ layered upon IP, i.e., it uses IP to carry its data end-
+ to-end just as a transport protocol like TCP or UDP does.
+ ICMP provides error reporting, congestion reporting, and
+ first-hop gateway redirection.
+
+ IGMP is an Internet layer protocol used for establishing
+ dynamic host groups for IP multicasting.
+
+ The Internet layer protocols IP, ICMP, and IGMP are
+ discussed in Chapter 3.
+
+
+ o Link Layer
+
+ To communicate on its directly-connected network, a host
+ must implement the communication protocol used to
+ interface to that network. We call this a link layer or
+ media-access layer protocol.
+
+ There is a wide variety of link layer protocols,
+ corresponding to the many different types of networks.
+ See Chapter 2.
+
+
+ 1.1.4 Embedded Gateway Code
+
+ Some Internet host software includes embedded gateway
+ functionality, so that these hosts can forward packets as a
+
+
+
+Internet Engineering Task Force [Page 10]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ gateway would, while still performing the application layer
+ functions of a host.
+
+ Such dual-purpose systems must follow the Gateway Requirements
+ RFC [INTRO:2] with respect to their gateway functions, and
+ must follow the present document with respect to their host
+ functions. In all overlapping cases, the two specifications
+ should be in agreement.
+
+ There are varying opinions in the Internet community about
+ embedded gateway functionality. The main arguments are as
+ follows:
+
+ o Pro: in a local network environment where networking is
+ informal, or in isolated internets, it may be convenient
+ and economical to use existing host systems as gateways.
+
+ There is also an architectural argument for embedded
+ gateway functionality: multihoming is much more common
+ than originally foreseen, and multihoming forces a host to
+ make routing decisions as if it were a gateway. If the
+ multihomed host contains an embedded gateway, it will
+ have full routing knowledge and as a result will be able
+ to make more optimal routing decisions.
+
+ o Con: Gateway algorithms and protocols are still changing,
+ and they will continue to change as the Internet system
+ grows larger. Attempting to include a general gateway
+ function within the host IP layer will force host system
+ maintainers to track these (more frequent) changes. Also,
+ a larger pool of gateway implementations will make
+ coordinating the changes more difficult. Finally, the
+ complexity of a gateway IP layer is somewhat greater than
+ that of a host, making the implementation and operation
+ tasks more complex.
+
+ In addition, the style of operation of some hosts is not
+ appropriate for providing stable and robust gateway
+ service.
+
+ There is considerable merit in both of these viewpoints. One
+ conclusion can be drawn: an host administrator must have
+ conscious control over whether or not a given host acts as a
+ gateway. See Section 3.1 for the detailed requirements.
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 11]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ 1.2 General Considerations
+
+ There are two important lessons that vendors of Internet host
+ software have learned and which a new vendor should consider
+ seriously.
+
+ 1.2.1 Continuing Internet Evolution
+
+ The enormous growth of the Internet has revealed problems of
+ management and scaling in a large datagram-based packet
+ communication system. These problems are being addressed, and
+ as a result there will be continuing evolution of the
+ specifications described in this document. These changes will
+ be carefully planned and controlled, since there is extensive
+ participation in this planning by the vendors and by the
+ organizations responsible for operations of the networks.
+
+ Development, evolution, and revision are characteristic of
+ computer network protocols today, and this situation will
+ persist for some years. A vendor who develops computer
+ communication software for the Internet protocol suite (or any
+ other protocol suite!) and then fails to maintain and update
+ that software for changing specifications is going to leave a
+ trail of unhappy customers. The Internet is a large
+ communication network, and the users are in constant contact
+ through it. Experience has shown that knowledge of
+ deficiencies in vendor software propagates quickly through the
+ Internet technical community.
+
+ 1.2.2 Robustness Principle
+
+ At every layer of the protocols, there is a general rule whose
+ application can lead to enormous benefits in robustness and
+ interoperability [IP:1]:
+
+ "Be liberal in what you accept, and
+ conservative in what you send"
+
+ Software should be written to deal with every conceivable
+ error, no matter how unlikely; sooner or later a packet will
+ come in with that particular combination of errors and
+ attributes, and unless the software is prepared, chaos can
+ ensue. In general, it is best to assume that the network is
+ filled with malevolent entities that will send in packets
+ designed to have the worst possible effect. This assumption
+ will lead to suitable protective design, although the most
+ serious problems in the Internet have been caused by
+ unenvisaged mechanisms triggered by low-probability events;
+
+
+
+Internet Engineering Task Force [Page 12]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ mere human malice would never have taken so devious a course!
+
+ Adaptability to change must be designed into all levels of
+ Internet host software. As a simple example, consider a
+ protocol specification that contains an enumeration of values
+ for a particular header field -- e.g., a type field, a port
+ number, or an error code; this enumeration must be assumed to
+ be incomplete. Thus, if a protocol specification defines four
+ possible error codes, the software must not break when a fifth
+ code shows up. An undefined code might be logged (see below),
+ but it must not cause a failure.
+
+ The second part of the principle is almost as important:
+ software on other hosts may contain deficiencies that make it
+ unwise to exploit legal but obscure protocol features. It is
+ unwise to stray far from the obvious and simple, lest untoward
+ effects result elsewhere. A corollary of this is "watch out
+ for misbehaving hosts"; host software should be prepared, not
+ just to survive other misbehaving hosts, but also to cooperate
+ to limit the amount of disruption such hosts can cause to the
+ shared communication facility.
+
+ 1.2.3 Error Logging
+
+ The Internet includes a great variety of host and gateway
+ systems, each implementing many protocols and protocol layers,
+ and some of these contain bugs and mis-features in their
+ Internet protocol software. As a result of complexity,
+ diversity, and distribution of function, the diagnosis of
+ Internet problems is often very difficult.
+
+ Problem diagnosis will be aided if host implementations include
+ a carefully designed facility for logging erroneous or
+ "strange" protocol events. It is important to include as much
+ diagnostic information as possible when an error is logged. In
+ particular, it is often useful to record the header(s) of a
+ packet that caused an error. However, care must be taken to
+ ensure that error logging does not consume prohibitive amounts
+ of resources or otherwise interfere with the operation of the
+ host.
+
+ There is a tendency for abnormal but harmless protocol events
+ to overflow error logging files; this can be avoided by using a
+ "circular" log, or by enabling logging only while diagnosing a
+ known failure. It may be useful to filter and count duplicate
+ successive messages. One strategy that seems to work well is:
+ (1) always count abnormalities and make such counts accessible
+ through the management protocol (see [INTRO:1]); and (2) allow
+
+
+
+Internet Engineering Task Force [Page 13]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ the logging of a great variety of events to be selectively
+ enabled. For example, it might useful to be able to "log
+ everything" or to "log everything for host X".
+
+ Note that different managements may have differing policies
+ about the amount of error logging that they want normally
+ enabled in a host. Some will say, "if it doesn't hurt me, I
+ don't want to know about it", while others will want to take a
+ more watchful and aggressive attitude about detecting and
+ removing protocol abnormalities.
+
+ 1.2.4 Configuration
+
+ It would be ideal if a host implementation of the Internet
+ protocol suite could be entirely self-configuring. This would
+ allow the whole suite to be implemented in ROM or cast into
+ silicon, it would simplify diskless workstations, and it would
+ be an immense boon to harried LAN administrators as well as
+ system vendors. We have not reached this ideal; in fact, we
+ are not even close.
+
+ At many points in this document, you will find a requirement
+ that a parameter be a configurable option. There are several
+ different reasons behind such requirements. In a few cases,
+ there is current uncertainty or disagreement about the best
+ value, and it may be necessary to update the recommended value
+ in the future. In other cases, the value really depends on
+ external factors -- e.g., the size of the host and the
+ distribution of its communication load, or the speeds and
+ topology of nearby networks -- and self-tuning algorithms are
+ unavailable and may be insufficient. In some cases,
+ configurability is needed because of administrative
+ requirements.
+
+ Finally, some configuration options are required to communicate
+ with obsolete or incorrect implementations of the protocols,
+ distributed without sources, that unfortunately persist in many
+ parts of the Internet. To make correct systems coexist with
+ these faulty systems, administrators often have to "mis-
+ configure" the correct systems. This problem will correct
+ itself gradually as the faulty systems are retired, but it
+ cannot be ignored by vendors.
+
+ When we say that a parameter must be configurable, we do not
+ intend to require that its value be explicitly read from a
+ configuration file at every boot time. We recommend that
+ implementors set up a default for each parameter, so a
+ configuration file is only necessary to override those defaults
+
+
+
+Internet Engineering Task Force [Page 14]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ that are inappropriate in a particular installation. Thus, the
+ configurability requirement is an assurance that it will be
+ POSSIBLE to override the default when necessary, even in a
+ binary-only or ROM-based product.
+
+ This document requires a particular value for such defaults in
+ some cases. The choice of default is a sensitive issue when
+ the configuration item controls the accommodation to existing
+ faulty systems. If the Internet is to converge successfully to
+ complete interoperability, the default values built into
+ implementations must implement the official protocol, not
+ "mis-configurations" to accommodate faulty implementations.
+ Although marketing considerations have led some vendors to
+ choose mis-configuration defaults, we urge vendors to choose
+ defaults that will conform to the standard.
+
+ Finally, we note that a vendor needs to provide adequate
+ documentation on all configuration parameters, their limits and
+ effects.
+
+
+ 1.3 Reading this Document
+
+ 1.3.1 Organization
+
+ Protocol layering, which is generally used as an organizing
+ principle in implementing network software, has also been used
+ to organize this document. In describing the rules, we assume
+ that an implementation does strictly mirror the layering of the
+ protocols. Thus, the following three major sections specify
+ the requirements for the link layer, the internet layer, and
+ the transport layer, respectively. A companion RFC [INTRO:1]
+ covers application level software. This layerist organization
+ was chosen for simplicity and clarity.
+
+ However, strict layering is an imperfect model, both for the
+ protocol suite and for recommended implementation approaches.
+ Protocols in different layers interact in complex and sometimes
+ subtle ways, and particular functions often involve multiple
+ layers. There are many design choices in an implementation,
+ many of which involve creative "breaking" of strict layering.
+ Every implementor is urged to read references [INTRO:7] and
+ [INTRO:8].
+
+ This document describes the conceptual service interface
+ between layers using a functional ("procedure call") notation,
+ like that used in the TCP specification [TCP:1]. A host
+ implementation must support the logical information flow
+
+
+
+Internet Engineering Task Force [Page 15]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ implied by these calls, but need not literally implement the
+ calls themselves. For example, many implementations reflect
+ the coupling between the transport layer and the IP layer by
+ giving them shared access to common data structures. These
+ data structures, rather than explicit procedure calls, are then
+ the agency for passing much of the information that is
+ required.
+
+ In general, each major section of this document is organized
+ into the following subsections:
+
+ (1) Introduction
+
+ (2) Protocol Walk-Through -- considers the protocol
+ specification documents section-by-section, correcting
+ errors, stating requirements that may be ambiguous or
+ ill-defined, and providing further clarification or
+ explanation.
+
+ (3) Specific Issues -- discusses protocol design and
+ implementation issues that were not included in the walk-
+ through.
+
+ (4) Interfaces -- discusses the service interface to the next
+ higher layer.
+
+ (5) Summary -- contains a summary of the requirements of the
+ section.
+
+
+ Under many of the individual topics in this document, there is
+ parenthetical material labeled "DISCUSSION" or
+ "IMPLEMENTATION". This material is intended to give
+ clarification and explanation of the preceding requirements
+ text. It also includes some suggestions on possible future
+ directions or developments. The implementation material
+ contains suggested approaches that an implementor may want to
+ consider.
+
+ The summary sections are intended to be guides and indexes to
+ the text, but are necessarily cryptic and incomplete. The
+ summaries should never be used or referenced separately from
+ the complete RFC.
+
+ 1.3.2 Requirements
+
+ In this document, the words that are used to define the
+ significance of each particular requirement are capitalized.
+
+
+
+Internet Engineering Task Force [Page 16]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ These words are:
+
+ * "MUST"
+
+ This word or the adjective "REQUIRED" means that the item
+ is an absolute requirement of the specification.
+
+ * "SHOULD"
+
+ This word or the adjective "RECOMMENDED" means that there
+ may exist valid reasons in particular circumstances to
+ ignore this item, but the full implications should be
+ understood and the case carefully weighed before choosing
+ a different course.
+
+ * "MAY"
+
+ This word or the adjective "OPTIONAL" means that this item
+ is truly optional. One vendor may choose to include the
+ item because a particular marketplace requires it or
+ because it enhances the product, for example; another
+ vendor may omit the same item.
+
+
+ An implementation is not compliant if it fails to satisfy one
+ or more of the MUST requirements for the protocols it
+ implements. An implementation that satisfies all the MUST and
+ all the SHOULD requirements for its protocols is said to be
+ "unconditionally compliant"; one that satisfies all the MUST
+ requirements but not all the SHOULD requirements for its
+ protocols is said to be "conditionally compliant".
+
+ 1.3.3 Terminology
+
+ This document uses the following technical terms:
+
+ Segment
+ A segment is the unit of end-to-end transmission in the
+ TCP protocol. A segment consists of a TCP header followed
+ by application data. A segment is transmitted by
+ encapsulation inside an IP datagram.
+
+ Message
+ In this description of the lower-layer protocols, a
+ message is the unit of transmission in a transport layer
+ protocol. In particular, a TCP segment is a message. A
+ message consists of a transport protocol header followed
+ by application protocol data. To be transmitted end-to-
+
+
+
+Internet Engineering Task Force [Page 17]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ end through the Internet, a message must be encapsulated
+ inside a datagram.
+
+ IP Datagram
+ An IP datagram is the unit of end-to-end transmission in
+ the IP protocol. An IP datagram consists of an IP header
+ followed by transport layer data, i.e., of an IP header
+ followed by a message.
+
+ In the description of the internet layer (Section 3), the
+ unqualified term "datagram" should be understood to refer
+ to an IP datagram.
+
+ Packet
+ A packet is the unit of data passed across the interface
+ between the internet layer and the link layer. It
+ includes an IP header and data. A packet may be a
+ complete IP datagram or a fragment of an IP datagram.
+
+ Frame
+ A frame is the unit of transmission in a link layer
+ protocol, and consists of a link-layer header followed by
+ a packet.
+
+ Connected Network
+ A network to which a host is interfaced is often known as
+ the "local network" or the "subnetwork" relative to that
+ host. However, these terms can cause confusion, and
+ therefore we use the term "connected network" in this
+ document.
+
+ Multihomed
+ A host is said to be multihomed if it has multiple IP
+ addresses. For a discussion of multihoming, see Section
+ 3.3.4 below.
+
+ Physical network interface
+ This is a physical interface to a connected network and
+ has a (possibly unique) link-layer address. Multiple
+ physical network interfaces on a single host may share the
+ same link-layer address, but the address must be unique
+ for different hosts on the same physical network.
+
+ Logical [network] interface
+ We define a logical [network] interface to be a logical
+ path, distinguished by a unique IP address, to a connected
+ network. See Section 3.3.4.
+
+
+
+
+Internet Engineering Task Force [Page 18]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ Specific-destination address
+ This is the effective destination address of a datagram,
+ even if it is broadcast or multicast; see Section 3.2.1.3.
+
+ Path
+ At a given moment, all the IP datagrams from a particular
+ source host to a particular destination host will
+ typically traverse the same sequence of gateways. We use
+ the term "path" for this sequence. Note that a path is
+ uni-directional; it is not unusual to have different paths
+ in the two directions between a given host pair.
+
+ MTU
+ The maximum transmission unit, i.e., the size of the
+ largest packet that can be transmitted.
+
+
+ The terms frame, packet, datagram, message, and segment are
+ illustrated by the following schematic diagrams:
+
+ A. Transmission on connected network:
+ _______________________________________________
+ | LL hdr | IP hdr | (data) |
+ |________|________|_____________________________|
+
+ <---------- Frame ----------------------------->
+ <----------Packet -------------------->
+
+
+ B. Before IP fragmentation or after IP reassembly:
+ ______________________________________
+ | IP hdr | transport| Application Data |
+ |________|____hdr___|__________________|
+
+ <-------- Datagram ------------------>
+ <-------- Message ----------->
+ or, for TCP:
+ ______________________________________
+ | IP hdr | TCP hdr | Application Data |
+ |________|__________|__________________|
+
+ <-------- Datagram ------------------>
+ <-------- Segment ----------->
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 19]
+
+
+
+
+RFC1122 INTRODUCTION October 1989
+
+
+ 1.4 Acknowledgments
+
+ This document incorporates contributions and comments from a large
+ group of Internet protocol experts, including representatives of
+ university and research labs, vendors, and government agencies.
+ It was assembled primarily by the Host Requirements Working Group
+ of the Internet Engineering Task Force (IETF).
+
+ The Editor would especially like to acknowledge the tireless
+ dedication of the following people, who attended many long
+ meetings and generated 3 million bytes of electronic mail over the
+ past 18 months in pursuit of this document: Philip Almquist, Dave
+ Borman (Cray Research), Noel Chiappa, Dave Crocker (DEC), Steve
+ Deering (Stanford), Mike Karels (Berkeley), Phil Karn (Bellcore),
+ John Lekashman (NASA), Charles Lynn (BBN), Keith McCloghrie (TWG),
+ Paul Mockapetris (ISI), Thomas Narten (Purdue), Craig Partridge
+ (BBN), Drew Perkins (CMU), and James Van Bokkelen (FTP Software).
+
+ In addition, the following people made major contributions to the
+ effort: Bill Barns (Mitre), Steve Bellovin (AT&T), Mike Brescia
+ (BBN), Ed Cain (DCA), Annette DeSchon (ISI), Martin Gross (DCA),
+ Phill Gross (NRI), Charles Hedrick (Rutgers), Van Jacobson (LBL),
+ John Klensin (MIT), Mark Lottor (SRI), Milo Medin (NASA), Bill
+ Melohn (Sun Microsystems), Greg Minshall (Kinetics), Jeff Mogul
+ (DEC), John Mullen (CMC), Jon Postel (ISI), John Romkey (Epilogue
+ Technology), and Mike StJohns (DCA). The following also made
+ significant contributions to particular areas: Eric Allman
+ (Berkeley), Rob Austein (MIT), Art Berggreen (ACC), Keith Bostic
+ (Berkeley), Vint Cerf (NRI), Wayne Hathaway (NASA), Matt Korn
+ (IBM), Erik Naggum (Naggum Software, Norway), Robert Ullmann
+ (Prime Computer), David Waitzman (BBN), Frank Wancho (USA), Arun
+ Welch (Ohio State), Bill Westfield (Cisco), and Rayan Zachariassen
+ (Toronto).
+
+ We are grateful to all, including any contributors who may have
+ been inadvertently omitted from this list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 20]
+
+
+
+
+RFC1122 LINK LAYER October 1989
+
+
+2. LINK LAYER
+
+ 2.1 INTRODUCTION
+
+ All Internet systems, both hosts and gateways, have the same
+ requirements for link layer protocols. These requirements are
+ given in Chapter 3 of "Requirements for Internet Gateways"
+ [INTRO:2], augmented with the material in this section.
+
+ 2.2 PROTOCOL WALK-THROUGH
+
+ None.
+
+ 2.3 SPECIFIC ISSUES
+
+ 2.3.1 Trailer Protocol Negotiation
+
+ The trailer protocol [LINK:1] for link-layer encapsulation MAY
+ be used, but only when it has been verified that both systems
+ (host or gateway) involved in the link-layer communication
+ implement trailers. If the system does not dynamically
+ negotiate use of the trailer protocol on a per-destination
+ basis, the default configuration MUST disable the protocol.
+
+ DISCUSSION:
+ The trailer protocol is a link-layer encapsulation
+ technique that rearranges the data contents of packets
+ sent on the physical network. In some cases, trailers
+ improve the throughput of higher layer protocols by
+ reducing the amount of data copying within the operating
+ system. Higher layer protocols are unaware of trailer
+ use, but both the sending and receiving host MUST
+ understand the protocol if it is used.
+
+ Improper use of trailers can result in very confusing
+ symptoms. Only packets with specific size attributes are
+ encapsulated using trailers, and typically only a small
+ fraction of the packets being exchanged have these
+ attributes. Thus, if a system using trailers exchanges
+ packets with a system that does not, some packets
+ disappear into a black hole while others are delivered
+ successfully.
+
+ IMPLEMENTATION:
+ On an Ethernet, packets encapsulated with trailers use a
+ distinct Ethernet type [LINK:1], and trailer negotiation
+ is performed at the time that ARP is used to discover the
+ link-layer address of a destination system.
+
+
+
+Internet Engineering Task Force [Page 21]
+
+
+
+
+RFC1122 LINK LAYER October 1989
+
+
+ Specifically, the ARP exchange is completed in the usual
+ manner using the normal IP protocol type, but a host that
+ wants to speak trailers will send an additional "trailer
+ ARP reply" packet, i.e., an ARP reply that specifies the
+ trailer encapsulation protocol type but otherwise has the
+ format of a normal ARP reply. If a host configured to use
+ trailers receives a trailer ARP reply message from a
+ remote machine, it can add that machine to the list of
+ machines that understand trailers, e.g., by marking the
+ corresponding entry in the ARP cache.
+
+ Hosts wishing to receive trailer encapsulations send
+ trailer ARP replies whenever they complete exchanges of
+ normal ARP messages for IP. Thus, a host that received an
+ ARP request for its IP protocol address would send a
+ trailer ARP reply in addition to the normal IP ARP reply;
+ a host that sent the IP ARP request would send a trailer
+ ARP reply when it received the corresponding IP ARP reply.
+ In this way, either the requesting or responding host in
+ an IP ARP exchange may request that it receive trailer
+ encapsulations.
+
+ This scheme, using extra trailer ARP reply packets rather
+ than sending an ARP request for the trailer protocol type,
+ was designed to avoid a continuous exchange of ARP packets
+ with a misbehaving host that, contrary to any
+ specification or common sense, responded to an ARP reply
+ for trailers with another ARP reply for IP. This problem
+ is avoided by sending a trailer ARP reply in response to
+ an IP ARP reply only when the IP ARP reply answers an
+ outstanding request; this is true when the hardware
+ address for the host is still unknown when the IP ARP
+ reply is received. A trailer ARP reply may always be sent
+ along with an IP ARP reply responding to an IP ARP
+ request.
+
+ 2.3.2 Address Resolution Protocol -- ARP
+
+ 2.3.2.1 ARP Cache Validation
+
+ An implementation of the Address Resolution Protocol (ARP)
+ [LINK:2] MUST provide a mechanism to flush out-of-date cache
+ entries. If this mechanism involves a timeout, it SHOULD be
+ possible to configure the timeout value.
+
+ A mechanism to prevent ARP flooding (repeatedly sending an
+ ARP Request for the same IP address, at a high rate) MUST be
+ included. The recommended maximum rate is 1 per second per
+
+
+
+Internet Engineering Task Force [Page 22]
+
+
+
+
+RFC1122 LINK LAYER October 1989
+
+
+ destination.
+
+ DISCUSSION:
+ The ARP specification [LINK:2] suggests but does not
+ require a timeout mechanism to invalidate cache entries
+ when hosts change their Ethernet addresses. The
+ prevalence of proxy ARP (see Section 2.4 of [INTRO:2])
+ has significantly increased the likelihood that cache
+ entries in hosts will become invalid, and therefore
+ some ARP-cache invalidation mechanism is now required
+ for hosts. Even in the absence of proxy ARP, a long-
+ period cache timeout is useful in order to
+ automatically correct any bad ARP data that might have
+ been cached.
+
+ IMPLEMENTATION:
+ Four mechanisms have been used, sometimes in
+ combination, to flush out-of-date cache entries.
+
+ (1) Timeout -- Periodically time out cache entries,
+ even if they are in use. Note that this timeout
+ should be restarted when the cache entry is
+ "refreshed" (by observing the source fields,
+ regardless of target address, of an ARP broadcast
+ from the system in question). For proxy ARP
+ situations, the timeout needs to be on the order
+ of a minute.
+
+ (2) Unicast Poll -- Actively poll the remote host by
+ periodically sending a point-to-point ARP Request
+ to it, and delete the entry if no ARP Reply is
+ received from N successive polls. Again, the
+ timeout should be on the order of a minute, and
+ typically N is 2.
+
+ (3) Link-Layer Advice -- If the link-layer driver
+ detects a delivery problem, flush the
+ corresponding ARP cache entry.
+
+ (4) Higher-layer Advice -- Provide a call from the
+ Internet layer to the link layer to indicate a
+ delivery problem. The effect of this call would
+ be to invalidate the corresponding cache entry.
+ This call would be analogous to the
+ "ADVISE_DELIVPROB()" call from the transport layer
+ to the Internet layer (see Section 3.4), and in
+ fact the ADVISE_DELIVPROB routine might in turn
+ call the link-layer advice routine to invalidate
+
+
+
+Internet Engineering Task Force [Page 23]
+
+
+
+
+RFC1122 LINK LAYER October 1989
+
+
+ the ARP cache entry.
+
+ Approaches (1) and (2) involve ARP cache timeouts on
+ the order of a minute or less. In the absence of proxy
+ ARP, a timeout this short could create noticeable
+ overhead traffic on a very large Ethernet. Therefore,
+ it may be necessary to configure a host to lengthen the
+ ARP cache timeout.
+
+ 2.3.2.2 ARP Packet Queue
+
+ The link layer SHOULD save (rather than discard) at least
+ one (the latest) packet of each set of packets destined to
+ the same unresolved IP address, and transmit the saved
+ packet when the address has been resolved.
+
+ DISCUSSION:
+ Failure to follow this recommendation causes the first
+ packet of every exchange to be lost. Although higher-
+ layer protocols can generally cope with packet loss by
+ retransmission, packet loss does impact performance.
+ For example, loss of a TCP open request causes the
+ initial round-trip time estimate to be inflated. UDP-
+ based applications such as the Domain Name System are
+ more seriously affected.
+
+ 2.3.3 Ethernet and IEEE 802 Encapsulation
+
+ The IP encapsulation for Ethernets is described in RFC-894
+ [LINK:3], while RFC-1042 [LINK:4] describes the IP
+ encapsulation for IEEE 802 networks. RFC-1042 elaborates and
+ replaces the discussion in Section 3.4 of [INTRO:2].
+
+ Every Internet host connected to a 10Mbps Ethernet cable:
+
+ o MUST be able to send and receive packets using RFC-894
+ encapsulation;
+
+ o SHOULD be able to receive RFC-1042 packets, intermixed
+ with RFC-894 packets; and
+
+ o MAY be able to send packets using RFC-1042 encapsulation.
+
+
+ An Internet host that implements sending both the RFC-894 and
+ the RFC-1042 encapsulations MUST provide a configuration switch
+ to select which is sent, and this switch MUST default to RFC-
+ 894.
+
+
+
+Internet Engineering Task Force [Page 24]
+
+
+
+
+RFC1122 LINK LAYER October 1989
+
+
+ Note that the standard IP encapsulation in RFC-1042 does not
+ use the protocol id value (K1=6) that IEEE reserved for IP;
+ instead, it uses a value (K1=170) that implies an extension
+ (the "SNAP") which can be used to hold the Ether-Type field.
+ An Internet system MUST NOT send 802 packets using K1=6.
+
+ Address translation from Internet addresses to link-layer
+ addresses on Ethernet and IEEE 802 networks MUST be managed by
+ the Address Resolution Protocol (ARP).
+
+ The MTU for an Ethernet is 1500 and for 802.3 is 1492.
+
+ DISCUSSION:
+ The IEEE 802.3 specification provides for operation over a
+ 10Mbps Ethernet cable, in which case Ethernet and IEEE
+ 802.3 frames can be physically intermixed. A receiver can
+ distinguish Ethernet and 802.3 frames by the value of the
+ 802.3 Length field; this two-octet field coincides in the
+ header with the Ether-Type field of an Ethernet frame. In
+ particular, the 802.3 Length field must be less than or
+ equal to 1500, while all valid Ether-Type values are
+ greater than 1500.
+
+ Another compatibility problem arises with link-layer
+ broadcasts. A broadcast sent with one framing will not be
+ seen by hosts that can receive only the other framing.
+
+ The provisions of this section were designed to provide
+ direct interoperation between 894-capable and 1042-capable
+ systems on the same cable, to the maximum extent possible.
+ It is intended to support the present situation where
+ 894-only systems predominate, while providing an easy
+ transition to a possible future in which 1042-capable
+ systems become common.
+
+ Note that 894-only systems cannot interoperate directly
+ with 1042-only systems. If the two system types are set
+ up as two different logical networks on the same cable,
+ they can communicate only through an IP gateway.
+ Furthermore, it is not useful or even possible for a
+ dual-format host to discover automatically which format to
+ send, because of the problem of link-layer broadcasts.
+
+ 2.4 LINK/INTERNET LAYER INTERFACE
+
+ The packet receive interface between the IP layer and the link
+ layer MUST include a flag to indicate whether the incoming packet
+ was addressed to a link-layer broadcast address.
+
+
+
+Internet Engineering Task Force [Page 25]
+
+
+
+
+RFC1122 LINK LAYER October 1989
+
+
+ DISCUSSION
+ Although the IP layer does not generally know link layer
+ addresses (since every different network medium typically has
+ a different address format), the broadcast address on a
+ broadcast-capable medium is an important special case. See
+ Section 3.2.2, especially the DISCUSSION concerning broadcast
+ storms.
+
+ The packet send interface between the IP and link layers MUST
+ include the 5-bit TOS field (see Section 3.2.1.6).
+
+ The link layer MUST NOT report a Destination Unreachable error to
+ IP solely because there is no ARP cache entry for a destination.
+
+ 2.5 LINK LAYER REQUIREMENTS SUMMARY
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION| | | |T|T|e
+--------------------------------------------------|-------|-|-|-|-|-|--
+ | | | | | | |
+Trailer encapsulation |2.3.1 | | |x| | |
+Send Trailers by default without negotiation |2.3.1 | | | | |x|
+ARP |2.3.2 | | | | | |
+ Flush out-of-date ARP cache entries |2.3.2.1|x| | | | |
+ Prevent ARP floods |2.3.2.1|x| | | | |
+ Cache timeout configurable |2.3.2.1| |x| | | |
+ Save at least one (latest) unresolved pkt |2.3.2.2| |x| | | |
+Ethernet and IEEE 802 Encapsulation |2.3.3 | | | | | |
+ Host able to: |2.3.3 | | | | | |
+ Send & receive RFC-894 encapsulation |2.3.3 |x| | | | |
+ Receive RFC-1042 encapsulation |2.3.3 | |x| | | |
+ Send RFC-1042 encapsulation |2.3.3 | | |x| | |
+ Then config. sw. to select, RFC-894 dflt |2.3.3 |x| | | | |
+ Send K1=6 encapsulation |2.3.3 | | | | |x|
+ Use ARP on Ethernet and IEEE 802 nets |2.3.3 |x| | | | |
+Link layer report b'casts to IP layer |2.4 |x| | | | |
+IP layer pass TOS to link layer |2.4 |x| | | | |
+No ARP cache entry treated as Dest. Unreach. |2.4 | | | | |x|
+
+
+
+
+
+Internet Engineering Task Force [Page 26]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+3. INTERNET LAYER PROTOCOLS
+
+ 3.1 INTRODUCTION
+
+ The Robustness Principle: "Be liberal in what you accept, and
+ conservative in what you send" is particularly important in the
+ Internet layer, where one misbehaving host can deny Internet
+ service to many other hosts.
+
+ The protocol standards used in the Internet layer are:
+
+ o RFC-791 [IP:1] defines the IP protocol and gives an
+ introduction to the architecture of the Internet.
+
+ o RFC-792 [IP:2] defines ICMP, which provides routing,
+ diagnostic and error functionality for IP. Although ICMP
+ messages are encapsulated within IP datagrams, ICMP
+ processing is considered to be (and is typically implemented
+ as) part of the IP layer. See Section 3.2.2.
+
+ o RFC-950 [IP:3] defines the mandatory subnet extension to the
+ addressing architecture.
+
+ o RFC-1112 [IP:4] defines the Internet Group Management
+ Protocol IGMP, as part of a recommended extension to hosts
+ and to the host-gateway interface to support Internet-wide
+ multicasting at the IP level. See Section 3.2.3.
+
+ The target of an IP multicast may be an arbitrary group of
+ Internet hosts. IP multicasting is designed as a natural
+ extension of the link-layer multicasting facilities of some
+ networks, and it provides a standard means for local access
+ to such link-layer multicasting facilities.
+
+ Other important references are listed in Section 5 of this
+ document.
+
+ The Internet layer of host software MUST implement both IP and
+ ICMP. See Section 3.3.7 for the requirements on support of IGMP.
+
+ The host IP layer has two basic functions: (1) choose the "next
+ hop" gateway or host for outgoing IP datagrams and (2) reassemble
+ incoming IP datagrams. The IP layer may also (3) implement
+ intentional fragmentation of outgoing datagrams. Finally, the IP
+ layer must (4) provide diagnostic and error functionality. We
+ expect that IP layer functions may increase somewhat in the
+ future, as further Internet control and management facilities are
+ developed.
+
+
+
+Internet Engineering Task Force [Page 27]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ For normal datagrams, the processing is straightforward. For
+ incoming datagrams, the IP layer:
+
+ (1) verifies that the datagram is correctly formatted;
+
+ (2) verifies that it is destined to the local host;
+
+ (3) processes options;
+
+ (4) reassembles the datagram if necessary; and
+
+ (5) passes the encapsulated message to the appropriate
+ transport-layer protocol module.
+
+ For outgoing datagrams, the IP layer:
+
+ (1) sets any fields not set by the transport layer;
+
+ (2) selects the correct first hop on the connected network (a
+ process called "routing");
+
+ (3) fragments the datagram if necessary and if intentional
+ fragmentation is implemented (see Section 3.3.3); and
+
+ (4) passes the packet(s) to the appropriate link-layer driver.
+
+
+ A host is said to be multihomed if it has multiple IP addresses.
+ Multihoming introduces considerable confusion and complexity into
+ the protocol suite, and it is an area in which the Internet
+ architecture falls seriously short of solving all problems. There
+ are two distinct problem areas in multihoming:
+
+ (1) Local multihoming -- the host itself is multihomed; or
+
+ (2) Remote multihoming -- the local host needs to communicate
+ with a remote multihomed host.
+
+ At present, remote multihoming MUST be handled at the application
+ layer, as discussed in the companion RFC [INTRO:1]. A host MAY
+ support local multihoming, which is discussed in this document,
+ and in particular in Section 3.3.4.
+
+ Any host that forwards datagrams generated by another host is
+ acting as a gateway and MUST also meet the specifications laid out
+ in the gateway requirements RFC [INTRO:2]. An Internet host that
+ includes embedded gateway code MUST have a configuration switch to
+ disable the gateway function, and this switch MUST default to the
+
+
+
+Internet Engineering Task Force [Page 28]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ non-gateway mode. In this mode, a datagram arriving through one
+ interface will not be forwarded to another host or gateway (unless
+ it is source-routed), regardless of whether the host is single-
+ homed or multihomed. The host software MUST NOT automatically
+ move into gateway mode if the host has more than one interface, as
+ the operator of the machine may neither want to provide that
+ service nor be competent to do so.
+
+ In the following, the action specified in certain cases is to
+ "silently discard" a received datagram. This means that the
+ datagram will be discarded without further processing and that the
+ host will not send any ICMP error message (see Section 3.2.2) as a
+ result. However, for diagnosis of problems a host SHOULD provide
+ the capability of logging the error (see Section 1.2.3), including
+ the contents of the silently-discarded datagram, and SHOULD record
+ the event in a statistics counter.
+
+ DISCUSSION:
+ Silent discard of erroneous datagrams is generally intended
+ to prevent "broadcast storms".
+
+ 3.2 PROTOCOL WALK-THROUGH
+
+ 3.2.1 Internet Protocol -- IP
+
+ 3.2.1.1 Version Number: RFC-791 Section 3.1
+
+ A datagram whose version number is not 4 MUST be silently
+ discarded.
+
+ 3.2.1.2 Checksum: RFC-791 Section 3.1
+
+ A host MUST verify the IP header checksum on every received
+ datagram and silently discard every datagram that has a bad
+ checksum.
+
+ 3.2.1.3 Addressing: RFC-791 Section 3.2
+
+ There are now five classes of IP addresses: Class A through
+ Class E. Class D addresses are used for IP multicasting
+ [IP:4], while Class E addresses are reserved for
+ experimental use.
+
+ A multicast (Class D) address is a 28-bit logical address
+ that stands for a group of hosts, and may be either
+ permanent or transient. Permanent multicast addresses are
+ allocated by the Internet Assigned Number Authority
+ [INTRO:6], while transient addresses may be allocated
+
+
+
+Internet Engineering Task Force [Page 29]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ dynamically to transient groups. Group membership is
+ determined dynamically using IGMP [IP:4].
+
+ We now summarize the important special cases for Class A, B,
+ and C IP addresses, using the following notation for an IP
+ address:
+
+ { <Network-number>, <Host-number> }
+
+ or
+ { <Network-number>, <Subnet-number>, <Host-number> }
+
+ and the notation "-1" for a field that contains all 1 bits.
+ This notation is not intended to imply that the 1-bits in an
+ address mask need be contiguous.
+
+ (a) { 0, 0 }
+
+ This host on this network. MUST NOT be sent, except as
+ a source address as part of an initialization procedure
+ by which the host learns its own IP address.
+
+ See also Section 3.3.6 for a non-standard use of {0,0}.
+
+ (b) { 0, <Host-number> }
+
+ Specified host on this network. It MUST NOT be sent,
+ except as a source address as part of an initialization
+ procedure by which the host learns its full IP address.
+
+ (c) { -1, -1 }
+
+ Limited broadcast. It MUST NOT be used as a source
+ address.
+
+ A datagram with this destination address will be
+ received by every host on the connected physical
+ network but will not be forwarded outside that network.
+
+ (d) { <Network-number>, -1 }
+
+ Directed broadcast to the specified network. It MUST
+ NOT be used as a source address.
+
+ (e) { <Network-number>, <Subnet-number>, -1 }
+
+ Directed broadcast to the specified subnet. It MUST
+ NOT be used as a source address.
+
+
+
+Internet Engineering Task Force [Page 30]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ (f) { <Network-number>, -1, -1 }
+
+ Directed broadcast to all subnets of the specified
+ subnetted network. It MUST NOT be used as a source
+ address.
+
+ (g) { 127, <any> }
+
+ Internal host loopback address. Addresses of this form
+ MUST NOT appear outside a host.
+
+ The <Network-number> is administratively assigned so that
+ its value will be unique in the entire world.
+
+ IP addresses are not permitted to have the value 0 or -1 for
+ any of the <Host-number>, <Network-number>, or <Subnet-
+ number> fields (except in the special cases listed above).
+ This implies that each of these fields will be at least two
+ bits long.
+
+ For further discussion of broadcast addresses, see Section
+ 3.3.6.
+
+ A host MUST support the subnet extensions to IP [IP:3]. As
+ a result, there will be an address mask of the form:
+ {-1, -1, 0} associated with each of the host's local IP
+ addresses; see Sections 3.2.2.9 and 3.3.1.1.
+
+ When a host sends any datagram, the IP source address MUST
+ be one of its own IP addresses (but not a broadcast or
+ multicast address).
+
+ A host MUST silently discard an incoming datagram that is
+ not destined for the host. An incoming datagram is destined
+ for the host if the datagram's destination address field is:
+
+ (1) (one of) the host's IP address(es); or
+
+ (2) an IP broadcast address valid for the connected
+ network; or
+
+ (3) the address for a multicast group of which the host is
+ a member on the incoming physical interface.
+
+ For most purposes, a datagram addressed to a broadcast or
+ multicast destination is processed as if it had been
+ addressed to one of the host's IP addresses; we use the term
+ "specific-destination address" for the equivalent local IP
+
+
+
+Internet Engineering Task Force [Page 31]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ address of the host. The specific-destination address is
+ defined to be the destination address in the IP header
+ unless the header contains a broadcast or multicast address,
+ in which case the specific-destination is an IP address
+ assigned to the physical interface on which the datagram
+ arrived.
+
+ A host MUST silently discard an incoming datagram containing
+ an IP source address that is invalid by the rules of this
+ section. This validation could be done in either the IP
+ layer or by each protocol in the transport layer.
+
+ DISCUSSION:
+ A mis-addressed datagram might be caused by a link-
+ layer broadcast of a unicast datagram or by a gateway
+ or host that is confused or mis-configured.
+
+ An architectural goal for Internet hosts was to allow
+ IP addresses to be featureless 32-bit numbers, avoiding
+ algorithms that required a knowledge of the IP address
+ format. Otherwise, any future change in the format or
+ interpretation of IP addresses will require host
+ software changes. However, validation of broadcast and
+ multicast addresses violates this goal; a few other
+ violations are described elsewhere in this document.
+
+ Implementers should be aware that applications
+ depending upon the all-subnets directed broadcast
+ address (f) may be unusable on some networks. All-
+ subnets broadcast is not widely implemented in vendor
+ gateways at present, and even when it is implemented, a
+ particular network administration may disable it in the
+ gateway configuration.
+
+ 3.2.1.4 Fragmentation and Reassembly: RFC-791 Section 3.2
+
+ The Internet model requires that every host support
+ reassembly. See Sections 3.3.2 and 3.3.3 for the
+ requirements on fragmentation and reassembly.
+
+ 3.2.1.5 Identification: RFC-791 Section 3.2
+
+ When sending an identical copy of an earlier datagram, a
+ host MAY optionally retain the same Identification field in
+ the copy.
+
+
+
+
+
+
+Internet Engineering Task Force [Page 32]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ DISCUSSION:
+ Some Internet protocol experts have maintained that
+ when a host sends an identical copy of an earlier
+ datagram, the new copy should contain the same
+ Identification value as the original. There are two
+ suggested advantages: (1) if the datagrams are
+ fragmented and some of the fragments are lost, the
+ receiver may be able to reconstruct a complete datagram
+ from fragments of the original and the copies; (2) a
+ congested gateway might use the IP Identification field
+ (and Fragment Offset) to discard duplicate datagrams
+ from the queue.
+
+ However, the observed patterns of datagram loss in the
+ Internet do not favor the probability of retransmitted
+ fragments filling reassembly gaps, while other
+ mechanisms (e.g., TCP repacketizing upon
+ retransmission) tend to prevent retransmission of an
+ identical datagram [IP:9]. Therefore, we believe that
+ retransmitting the same Identification field is not
+ useful. Also, a connectionless transport protocol like
+ UDP would require the cooperation of the application
+ programs to retain the same Identification value in
+ identical datagrams.
+
+ 3.2.1.6 Type-of-Service: RFC-791 Section 3.2
+
+ The "Type-of-Service" byte in the IP header is divided into
+ two sections: the Precedence field (high-order 3 bits), and
+ a field that is customarily called "Type-of-Service" or
+ "TOS" (low-order 5 bits). In this document, all references
+ to "TOS" or the "TOS field" refer to the low-order 5 bits
+ only.
+
+ The Precedence field is intended for Department of Defense
+ applications of the Internet protocols. The use of non-zero
+ values in this field is outside the scope of this document
+ and the IP standard specification. Vendors should consult
+ the Defense Communication Agency (DCA) for guidance on the
+ IP Precedence field and its implications for other protocol
+ layers. However, vendors should note that the use of
+ precedence will most likely require that its value be passed
+ between protocol layers in just the same way as the TOS
+ field is passed.
+
+ The IP layer MUST provide a means for the transport layer to
+ set the TOS field of every datagram that is sent; the
+ default is all zero bits. The IP layer SHOULD pass received
+
+
+
+Internet Engineering Task Force [Page 33]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ TOS values up to the transport layer.
+
+ The particular link-layer mappings of TOS contained in RFC-
+ 795 SHOULD NOT be implemented.
+
+ DISCUSSION:
+ While the TOS field has been little used in the past,
+ it is expected to play an increasing role in the near
+ future. The TOS field is expected to be used to
+ control two aspects of gateway operations: routing and
+ queueing algorithms. See Section 2 of [INTRO:1] for
+ the requirements on application programs to specify TOS
+ values.
+
+ The TOS field may also be mapped into link-layer
+ service selectors. This has been applied to provide
+ effective sharing of serial lines by different classes
+ of TCP traffic, for example. However, the mappings
+ suggested in RFC-795 for networks that were included in
+ the Internet as of 1981 are now obsolete.
+
+ 3.2.1.7 Time-to-Live: RFC-791 Section 3.2
+
+ A host MUST NOT send a datagram with a Time-to-Live (TTL)
+ value of zero.
+
+ A host MUST NOT discard a datagram just because it was
+ received with TTL less than 2.
+
+ The IP layer MUST provide a means for the transport layer to
+ set the TTL field of every datagram that is sent. When a
+ fixed TTL value is used, it MUST be configurable. The
+ current suggested value will be published in the "Assigned
+ Numbers" RFC.
+
+ DISCUSSION:
+ The TTL field has two functions: limit the lifetime of
+ TCP segments (see RFC-793 [TCP:1], p. 28), and
+ terminate Internet routing loops. Although TTL is a
+ time in seconds, it also has some attributes of a hop-
+ count, since each gateway is required to reduce the TTL
+ field by at least one.
+
+ The intent is that TTL expiration will cause a datagram
+ to be discarded by a gateway but not by the destination
+ host; however, hosts that act as gateways by forwarding
+ datagrams must follow the gateway rules for TTL.
+
+
+
+
+Internet Engineering Task Force [Page 34]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ A higher-layer protocol may want to set the TTL in
+ order to implement an "expanding scope" search for some
+ Internet resource. This is used by some diagnostic
+ tools, and is expected to be useful for locating the
+ "nearest" server of a given class using IP
+ multicasting, for example. A particular transport
+ protocol may also want to specify its own TTL bound on
+ maximum datagram lifetime.
+
+ A fixed value must be at least big enough for the
+ Internet "diameter," i.e., the longest possible path.
+ A reasonable value is about twice the diameter, to
+ allow for continued Internet growth.
+
+ 3.2.1.8 Options: RFC-791 Section 3.2
+
+ There MUST be a means for the transport layer to specify IP
+ options to be included in transmitted IP datagrams (see
+ Section 3.4).
+
+ All IP options (except NOP or END-OF-LIST) received in
+ datagrams MUST be passed to the transport layer (or to ICMP
+ processing when the datagram is an ICMP message). The IP
+ and transport layer MUST each interpret those IP options
+ that they understand and silently ignore the others.
+
+ Later sections of this document discuss specific IP option
+ support required by each of ICMP, TCP, and UDP.
+
+ DISCUSSION:
+ Passing all received IP options to the transport layer
+ is a deliberate "violation of strict layering" that is
+ designed to ease the introduction of new transport-
+ relevant IP options in the future. Each layer must
+ pick out any options that are relevant to its own
+ processing and ignore the rest. For this purpose,
+ every IP option except NOP and END-OF-LIST will include
+ a specification of its own length.
+
+ This document does not define the order in which a
+ receiver must process multiple options in the same IP
+ header. Hosts sending multiple options must be aware
+ that this introduces an ambiguity in the meaning of
+ certain options when combined with a source-route
+ option.
+
+ IMPLEMENTATION:
+ The IP layer must not crash as the result of an option
+
+
+
+Internet Engineering Task Force [Page 35]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ length that is outside the possible range. For
+ example, erroneous option lengths have been observed to
+ put some IP implementations into infinite loops.
+
+ Here are the requirements for specific IP options:
+
+
+ (a) Security Option
+
+ Some environments require the Security option in every
+ datagram; such a requirement is outside the scope of
+ this document and the IP standard specification. Note,
+ however, that the security options described in RFC-791
+ and RFC-1038 are obsolete. For DoD applications,
+ vendors should consult [IP:8] for guidance.
+
+
+ (b) Stream Identifier Option
+
+ This option is obsolete; it SHOULD NOT be sent, and it
+ MUST be silently ignored if received.
+
+
+ (c) Source Route Options
+
+ A host MUST support originating a source route and MUST
+ be able to act as the final destination of a source
+ route.
+
+ If host receives a datagram containing a completed
+ source route (i.e., the pointer points beyond the last
+ field), the datagram has reached its final destination;
+ the option as received (the recorded route) MUST be
+ passed up to the transport layer (or to ICMP message
+ processing). This recorded route will be reversed and
+ used to form a return source route for reply datagrams
+ (see discussion of IP Options in Section 4). When a
+ return source route is built, it MUST be correctly
+ formed even if the recorded route included the source
+ host (see case (B) in the discussion below).
+
+ An IP header containing more than one Source Route
+ option MUST NOT be sent; the effect on routing of
+ multiple Source Route options is implementation-
+ specific.
+
+ Section 3.3.5 presents the rules for a host acting as
+ an intermediate hop in a source route, i.e., forwarding
+
+
+
+Internet Engineering Task Force [Page 36]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ a source-routed datagram.
+
+ DISCUSSION:
+ If a source-routed datagram is fragmented, each
+ fragment will contain a copy of the source route.
+ Since the processing of IP options (including a
+ source route) must precede reassembly, the
+ original datagram will not be reassembled until
+ the final destination is reached.
+
+ Suppose a source routed datagram is to be routed
+ from host S to host D via gateways G1, G2, ... Gn.
+ There was an ambiguity in the specification over
+ whether the source route option in a datagram sent
+ out by S should be (A) or (B):
+
+ (A): {>>G2, G3, ... Gn, D} <--- CORRECT
+
+ (B): {S, >>G2, G3, ... Gn, D} <---- WRONG
+
+ (where >> represents the pointer). If (A) is
+ sent, the datagram received at D will contain the
+ option: {G1, G2, ... Gn >>}, with S and D as the
+ IP source and destination addresses. If (B) were
+ sent, the datagram received at D would again
+ contain S and D as the same IP source and
+ destination addresses, but the option would be:
+ {S, G1, ...Gn >>}; i.e., the originating host
+ would be the first hop in the route.
+
+
+ (d) Record Route Option
+
+ Implementation of originating and processing the Record
+ Route option is OPTIONAL.
+
+
+ (e) Timestamp Option
+
+ Implementation of originating and processing the
+ Timestamp option is OPTIONAL. If it is implemented,
+ the following rules apply:
+
+ o The originating host MUST record a timestamp in a
+ Timestamp option whose Internet address fields are
+ not pre-specified or whose first pre-specified
+ address is the host's interface address.
+
+
+
+
+Internet Engineering Task Force [Page 37]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ o The destination host MUST (if possible) add the
+ current timestamp to a Timestamp option before
+ passing the option to the transport layer or to
+ ICMP for processing.
+
+ o A timestamp value MUST follow the rules given in
+ Section 3.2.2.8 for the ICMP Timestamp message.
+
+
+ 3.2.2 Internet Control Message Protocol -- ICMP
+
+ ICMP messages are grouped into two classes.
+
+ *
+ ICMP error messages:
+
+ Destination Unreachable (see Section 3.2.2.1)
+ Redirect (see Section 3.2.2.2)
+ Source Quench (see Section 3.2.2.3)
+ Time Exceeded (see Section 3.2.2.4)
+ Parameter Problem (see Section 3.2.2.5)
+
+
+ *
+ ICMP query messages:
+
+ Echo (see Section 3.2.2.6)
+ Information (see Section 3.2.2.7)
+ Timestamp (see Section 3.2.2.8)
+ Address Mask (see Section 3.2.2.9)
+
+
+ If an ICMP message of unknown type is received, it MUST be
+ silently discarded.
+
+ Every ICMP error message includes the Internet header and at
+ least the first 8 data octets of the datagram that triggered
+ the error; more than 8 octets MAY be sent; this header and data
+ MUST be unchanged from the received datagram.
+
+ In those cases where the Internet layer is required to pass an
+ ICMP error message to the transport layer, the IP protocol
+ number MUST be extracted from the original header and used to
+ select the appropriate transport protocol entity to handle the
+ error.
+
+ An ICMP error message SHOULD be sent with normal (i.e., zero)
+ TOS bits.
+
+
+
+Internet Engineering Task Force [Page 38]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ An ICMP error message MUST NOT be sent as the result of
+ receiving:
+
+ * an ICMP error message, or
+
+ * a datagram destined to an IP broadcast or IP multicast
+ address, or
+
+ * a datagram sent as a link-layer broadcast, or
+
+ * a non-initial fragment, or
+
+ * a datagram whose source address does not define a single
+ host -- e.g., a zero address, a loopback address, a
+ broadcast address, a multicast address, or a Class E
+ address.
+
+ NOTE: THESE RESTRICTIONS TAKE PRECEDENCE OVER ANY REQUIREMENT
+ ELSEWHERE IN THIS DOCUMENT FOR SENDING ICMP ERROR MESSAGES.
+
+ DISCUSSION:
+ These rules will prevent the "broadcast storms" that have
+ resulted from hosts returning ICMP error messages in
+ response to broadcast datagrams. For example, a broadcast
+ UDP segment to a non-existent port could trigger a flood
+ of ICMP Destination Unreachable datagrams from all
+ machines that do not have a client for that destination
+ port. On a large Ethernet, the resulting collisions can
+ render the network useless for a second or more.
+
+ Every datagram that is broadcast on the connected network
+ should have a valid IP broadcast address as its IP
+ destination (see Section 3.3.6). However, some hosts
+ violate this rule. To be certain to detect broadcast
+ datagrams, therefore, hosts are required to check for a
+ link-layer broadcast as well as an IP-layer broadcast
+ address.
+
+ IMPLEMENTATION:
+ This requires that the link layer inform the IP layer when
+ a link-layer broadcast datagram has been received; see
+ Section 2.4.
+
+ 3.2.2.1 Destination Unreachable: RFC-792
+
+ The following additional codes are hereby defined:
+
+ 6 = destination network unknown
+
+
+
+Internet Engineering Task Force [Page 39]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ 7 = destination host unknown
+
+ 8 = source host isolated
+
+ 9 = communication with destination network
+ administratively prohibited
+
+ 10 = communication with destination host
+ administratively prohibited
+
+ 11 = network unreachable for type of service
+
+ 12 = host unreachable for type of service
+
+ A host SHOULD generate Destination Unreachable messages with
+ code:
+
+ 2 (Protocol Unreachable), when the designated transport
+ protocol is not supported; or
+
+ 3 (Port Unreachable), when the designated transport
+ protocol (e.g., UDP) is unable to demultiplex the
+ datagram but has no protocol mechanism to inform the
+ sender.
+
+ A Destination Unreachable message that is received MUST be
+ reported to the transport layer. The transport layer SHOULD
+ use the information appropriately; for example, see Sections
+ 4.1.3.3, 4.2.3.9, and 4.2.4 below. A transport protocol
+ that has its own mechanism for notifying the sender that a
+ port is unreachable (e.g., TCP, which sends RST segments)
+ MUST nevertheless accept an ICMP Port Unreachable for the
+ same purpose.
+
+ A Destination Unreachable message that is received with code
+ 0 (Net), 1 (Host), or 5 (Bad Source Route) may result from a
+ routing transient and MUST therefore be interpreted as only
+ a hint, not proof, that the specified destination is
+ unreachable [IP:11]. For example, it MUST NOT be used as
+ proof of a dead gateway (see Section 3.3.1).
+
+ 3.2.2.2 Redirect: RFC-792
+
+ A host SHOULD NOT send an ICMP Redirect message; Redirects
+ are to be sent only by gateways.
+
+ A host receiving a Redirect message MUST update its routing
+ information accordingly. Every host MUST be prepared to
+
+
+
+Internet Engineering Task Force [Page 40]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ accept both Host and Network Redirects and to process them
+ as described in Section 3.3.1.2 below.
+
+ A Redirect message SHOULD be silently discarded if the new
+ gateway address it specifies is not on the same connected
+ (sub-) net through which the Redirect arrived [INTRO:2,
+ Appendix A], or if the source of the Redirect is not the
+ current first-hop gateway for the specified destination (see
+ Section 3.3.1).
+
+ 3.2.2.3 Source Quench: RFC-792
+
+ A host MAY send a Source Quench message if it is
+ approaching, or has reached, the point at which it is forced
+ to discard incoming datagrams due to a shortage of
+ reassembly buffers or other resources. See Section 2.2.3 of
+ [INTRO:2] for suggestions on when to send Source Quench.
+
+ If a Source Quench message is received, the IP layer MUST
+ report it to the transport layer (or ICMP processing). In
+ general, the transport or application layer SHOULD implement
+ a mechanism to respond to Source Quench for any protocol
+ that can send a sequence of datagrams to the same
+ destination and which can reasonably be expected to maintain
+ enough state information to make this feasible. See Section
+ 4 for the handling of Source Quench by TCP and UDP.
+
+ DISCUSSION:
+ A Source Quench may be generated by the target host or
+ by some gateway in the path of a datagram. The host
+ receiving a Source Quench should throttle itself back
+ for a period of time, then gradually increase the
+ transmission rate again. The mechanism to respond to
+ Source Quench may be in the transport layer (for
+ connection-oriented protocols like TCP) or in the
+ application layer (for protocols that are built on top
+ of UDP).
+
+ A mechanism has been proposed [IP:14] to make the IP
+ layer respond directly to Source Quench by controlling
+ the rate at which datagrams are sent, however, this
+ proposal is currently experimental and not currently
+ recommended.
+
+ 3.2.2.4 Time Exceeded: RFC-792
+
+ An incoming Time Exceeded message MUST be passed to the
+ transport layer.
+
+
+
+Internet Engineering Task Force [Page 41]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ DISCUSSION:
+ A gateway will send a Time Exceeded Code 0 (In Transit)
+ message when it discards a datagram due to an expired
+ TTL field. This indicates either a gateway routing
+ loop or too small an initial TTL value.
+
+ A host may receive a Time Exceeded Code 1 (Reassembly
+ Timeout) message from a destination host that has timed
+ out and discarded an incomplete datagram; see Section
+ 3.3.2 below. In the future, receipt of this message
+ might be part of some "MTU discovery" procedure, to
+ discover the maximum datagram size that can be sent on
+ the path without fragmentation.
+
+ 3.2.2.5 Parameter Problem: RFC-792
+
+ A host SHOULD generate Parameter Problem messages. An
+ incoming Parameter Problem message MUST be passed to the
+ transport layer, and it MAY be reported to the user.
+
+ DISCUSSION:
+ The ICMP Parameter Problem message is sent to the
+ source host for any problem not specifically covered by
+ another ICMP message. Receipt of a Parameter Problem
+ message generally indicates some local or remote
+ implementation error.
+
+ A new variant on the Parameter Problem message is hereby
+ defined:
+ Code 1 = required option is missing.
+
+ DISCUSSION:
+ This variant is currently in use in the military
+ community for a missing security option.
+
+ 3.2.2.6 Echo Request/Reply: RFC-792
+
+ Every host MUST implement an ICMP Echo server function that
+ receives Echo Requests and sends corresponding Echo Replies.
+ A host SHOULD also implement an application-layer interface
+ for sending an Echo Request and receiving an Echo Reply, for
+ diagnostic purposes.
+
+ An ICMP Echo Request destined to an IP broadcast or IP
+ multicast address MAY be silently discarded.
+
+
+
+
+
+
+Internet Engineering Task Force [Page 42]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ DISCUSSION:
+ This neutral provision results from a passionate debate
+ between those who feel that ICMP Echo to a broadcast
+ address provides a valuable diagnostic capability and
+ those who feel that misuse of this feature can too
+ easily create packet storms.
+
+ The IP source address in an ICMP Echo Reply MUST be the same
+ as the specific-destination address (defined in Section
+ 3.2.1.3) of the corresponding ICMP Echo Request message.
+
+ Data received in an ICMP Echo Request MUST be entirely
+ included in the resulting Echo Reply. However, if sending
+ the Echo Reply requires intentional fragmentation that is
+ not implemented, the datagram MUST be truncated to maximum
+ transmission size (see Section 3.3.3) and sent.
+
+ Echo Reply messages MUST be passed to the ICMP user
+ interface, unless the corresponding Echo Request originated
+ in the IP layer.
+
+ If a Record Route and/or Time Stamp option is received in an
+ ICMP Echo Request, this option (these options) SHOULD be
+ updated to include the current host and included in the IP
+ header of the Echo Reply message, without "truncation".
+ Thus, the recorded route will be for the entire round trip.
+
+ If a Source Route option is received in an ICMP Echo
+ Request, the return route MUST be reversed and used as a
+ Source Route option for the Echo Reply message.
+
+ 3.2.2.7 Information Request/Reply: RFC-792
+
+ A host SHOULD NOT implement these messages.
+
+ DISCUSSION:
+ The Information Request/Reply pair was intended to
+ support self-configuring systems such as diskless
+ workstations, to allow them to discover their IP
+ network numbers at boot time. However, the RARP and
+ BOOTP protocols provide better mechanisms for a host to
+ discover its own IP address.
+
+ 3.2.2.8 Timestamp and Timestamp Reply: RFC-792
+
+ A host MAY implement Timestamp and Timestamp Reply. If they
+ are implemented, the following rules MUST be followed.
+
+
+
+
+Internet Engineering Task Force [Page 43]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ o The ICMP Timestamp server function returns a Timestamp
+ Reply to every Timestamp message that is received. If
+ this function is implemented, it SHOULD be designed for
+ minimum variability in delay (e.g., implemented in the
+ kernel to avoid delay in scheduling a user process).
+
+ The following cases for Timestamp are to be handled
+ according to the corresponding rules for ICMP Echo:
+
+ o An ICMP Timestamp Request message to an IP broadcast or
+ IP multicast address MAY be silently discarded.
+
+ o The IP source address in an ICMP Timestamp Reply MUST
+ be the same as the specific-destination address of the
+ corresponding Timestamp Request message.
+
+ o If a Source-route option is received in an ICMP Echo
+ Request, the return route MUST be reversed and used as
+ a Source Route option for the Timestamp Reply message.
+
+ o If a Record Route and/or Timestamp option is received
+ in a Timestamp Request, this (these) option(s) SHOULD
+ be updated to include the current host and included in
+ the IP header of the Timestamp Reply message.
+
+ o Incoming Timestamp Reply messages MUST be passed up to
+ the ICMP user interface.
+
+ The preferred form for a timestamp value (the "standard
+ value") is in units of milliseconds since midnight Universal
+ Time. However, it may be difficult to provide this value
+ with millisecond resolution. For example, many systems use
+ clocks that update only at line frequency, 50 or 60 times
+ per second. Therefore, some latitude is allowed in a
+ "standard value":
+
+ (a) A "standard value" MUST be updated at least 15 times
+ per second (i.e., at most the six low-order bits of the
+ value may be undefined).
+
+ (b) The accuracy of a "standard value" MUST approximate
+ that of operator-set CPU clocks, i.e., correct within a
+ few minutes.
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 44]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ 3.2.2.9 Address Mask Request/Reply: RFC-950
+
+ A host MUST support the first, and MAY implement all three,
+ of the following methods for determining the address mask(s)
+ corresponding to its IP address(es):
+
+ (1) static configuration information;
+
+ (2) obtaining the address mask(s) dynamically as a side-
+ effect of the system initialization process (see
+ [INTRO:1]); and
+
+ (3) sending ICMP Address Mask Request(s) and receiving ICMP
+ Address Mask Reply(s).
+
+ The choice of method to be used in a particular host MUST be
+ configurable.
+
+ When method (3), the use of Address Mask messages, is
+ enabled, then:
+
+ (a) When it initializes, the host MUST broadcast an Address
+ Mask Request message on the connected network
+ corresponding to the IP address. It MUST retransmit
+ this message a small number of times if it does not
+ receive an immediate Address Mask Reply.
+
+ (b) Until it has received an Address Mask Reply, the host
+ SHOULD assume a mask appropriate for the address class
+ of the IP address, i.e., assume that the connected
+ network is not subnetted.
+
+ (c) The first Address Mask Reply message received MUST be
+ used to set the address mask corresponding to the
+ particular local IP address. This is true even if the
+ first Address Mask Reply message is "unsolicited", in
+ which case it will have been broadcast and may arrive
+ after the host has ceased to retransmit Address Mask
+ Requests. Once the mask has been set by an Address
+ Mask Reply, later Address Mask Reply messages MUST be
+ (silently) ignored.
+
+ Conversely, if Address Mask messages are disabled, then no
+ ICMP Address Mask Requests will be sent, and any ICMP
+ Address Mask Replies received for that local IP address MUST
+ be (silently) ignored.
+
+ A host SHOULD make some reasonableness check on any address
+
+
+
+Internet Engineering Task Force [Page 45]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ mask it installs; see IMPLEMENTATION section below.
+
+ A system MUST NOT send an Address Mask Reply unless it is an
+ authoritative agent for address masks. An authoritative
+ agent may be a host or a gateway, but it MUST be explicitly
+ configured as a address mask agent. Receiving an address
+ mask via an Address Mask Reply does not give the receiver
+ authority and MUST NOT be used as the basis for issuing
+ Address Mask Replies.
+
+ With a statically configured address mask, there SHOULD be
+ an additional configuration flag that determines whether the
+ host is to act as an authoritative agent for this mask,
+ i.e., whether it will answer Address Mask Request messages
+ using this mask.
+
+ If it is configured as an agent, the host MUST broadcast an
+ Address Mask Reply for the mask on the appropriate interface
+ when it initializes.
+
+ See "System Initialization" in [INTRO:1] for more
+ information about the use of Address Mask Request/Reply
+ messages.
+
+ DISCUSSION
+ Hosts that casually send Address Mask Replies with
+ invalid address masks have often been a serious
+ nuisance. To prevent this, Address Mask Replies ought
+ to be sent only by authoritative agents that have been
+ selected by explicit administrative action.
+
+ When an authoritative agent receives an Address Mask
+ Request message, it will send a unicast Address Mask
+ Reply to the source IP address. If the network part of
+ this address is zero (see (a) and (b) in 3.2.1.3), the
+ Reply will be broadcast.
+
+ Getting no reply to its Address Mask Request messages,
+ a host will assume there is no agent and use an
+ unsubnetted mask, but the agent may be only temporarily
+ unreachable. An agent will broadcast an unsolicited
+ Address Mask Reply whenever it initializes, in order to
+ update the masks of all hosts that have initialized in
+ the meantime.
+
+ IMPLEMENTATION:
+ The following reasonableness check on an address mask
+ is suggested: the mask is not all 1 bits, and it is
+
+
+
+Internet Engineering Task Force [Page 46]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ either zero or else the 8 highest-order bits are on.
+
+ 3.2.3 Internet Group Management Protocol IGMP
+
+ IGMP [IP:4] is a protocol used between hosts and gateways on a
+ single network to establish hosts' membership in particular
+ multicast groups. The gateways use this information, in
+ conjunction with a multicast routing protocol, to support IP
+ multicasting across the Internet.
+
+ At this time, implementation of IGMP is OPTIONAL; see Section
+ 3.3.7 for more information. Without IGMP, a host can still
+ participate in multicasting local to its connected networks.
+
+ 3.3 SPECIFIC ISSUES
+
+ 3.3.1 Routing Outbound Datagrams
+
+ The IP layer chooses the correct next hop for each datagram it
+ sends. If the destination is on a connected network, the
+ datagram is sent directly to the destination host; otherwise,
+ it has to be routed to a gateway on a connected network.
+
+ 3.3.1.1 Local/Remote Decision
+
+ To decide if the destination is on a connected network, the
+ following algorithm MUST be used [see IP:3]:
+
+ (a) The address mask (particular to a local IP address for
+ a multihomed host) is a 32-bit mask that selects the
+ network number and subnet number fields of the
+ corresponding IP address.
+
+ (b) If the IP destination address bits extracted by the
+ address mask match the IP source address bits extracted
+ by the same mask, then the destination is on the
+ corresponding connected network, and the datagram is to
+ be transmitted directly to the destination host.
+
+ (c) If not, then the destination is accessible only through
+ a gateway. Selection of a gateway is described below
+ (3.3.1.2).
+
+ A special-case destination address is handled as follows:
+
+ * For a limited broadcast or a multicast address, simply
+ pass the datagram to the link layer for the appropriate
+ interface.
+
+
+
+Internet Engineering Task Force [Page 47]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ * For a (network or subnet) directed broadcast, the
+ datagram can use the standard routing algorithms.
+
+ The host IP layer MUST operate correctly in a minimal
+ network environment, and in particular, when there are no
+ gateways. For example, if the IP layer of a host insists on
+ finding at least one gateway to initialize, the host will be
+ unable to operate on a single isolated broadcast net.
+
+ 3.3.1.2 Gateway Selection
+
+ To efficiently route a series of datagrams to the same
+ destination, the source host MUST keep a "route cache" of
+ mappings to next-hop gateways. A host uses the following
+ basic algorithm on this cache to route a datagram; this
+ algorithm is designed to put the primary routing burden on
+ the gateways [IP:11].
+
+ (a) If the route cache contains no information for a
+ particular destination, the host chooses a "default"
+ gateway and sends the datagram to it. It also builds a
+ corresponding Route Cache entry.
+
+ (b) If that gateway is not the best next hop to the
+ destination, the gateway will forward the datagram to
+ the best next-hop gateway and return an ICMP Redirect
+ message to the source host.
+
+ (c) When it receives a Redirect, the host updates the
+ next-hop gateway in the appropriate route cache entry,
+ so later datagrams to the same destination will go
+ directly to the best gateway.
+
+ Since the subnet mask appropriate to the destination address
+ is generally not known, a Network Redirect message SHOULD be
+ treated identically to a Host Redirect message; i.e., the
+ cache entry for the destination host (only) would be updated
+ (or created, if an entry for that host did not exist) for
+ the new gateway.
+
+ DISCUSSION:
+ This recommendation is to protect against gateways that
+ erroneously send Network Redirects for a subnetted
+ network, in violation of the gateway requirements
+ [INTRO:2].
+
+ When there is no route cache entry for the destination host
+ address (and the destination is not on the connected
+
+
+
+Internet Engineering Task Force [Page 48]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ network), the IP layer MUST pick a gateway from its list of
+ "default" gateways. The IP layer MUST support multiple
+ default gateways.
+
+ As an extra feature, a host IP layer MAY implement a table
+ of "static routes". Each such static route MAY include a
+ flag specifying whether it may be overridden by ICMP
+ Redirects.
+
+ DISCUSSION:
+ A host generally needs to know at least one default
+ gateway to get started. This information can be
+ obtained from a configuration file or else from the
+ host startup sequence, e.g., the BOOTP protocol (see
+ [INTRO:1]).
+
+ It has been suggested that a host can augment its list
+ of default gateways by recording any new gateways it
+ learns about. For example, it can record every gateway
+ to which it is ever redirected. Such a feature, while
+ possibly useful in some circumstances, may cause
+ problems in other cases (e.g., gateways are not all
+ equal), and it is not recommended.
+
+ A static route is typically a particular preset mapping
+ from destination host or network into a particular
+ next-hop gateway; it might also depend on the Type-of-
+ Service (see next section). Static routes would be set
+ up by system administrators to override the normal
+ automatic routing mechanism, to handle exceptional
+ situations. However, any static routing information is
+ a potential source of failure as configurations change
+ or equipment fails.
+
+ 3.3.1.3 Route Cache
+
+ Each route cache entry needs to include the following
+ fields:
+
+ (1) Local IP address (for a multihomed host)
+
+ (2) Destination IP address
+
+ (3) Type(s)-of-Service
+
+ (4) Next-hop gateway IP address
+
+ Field (2) MAY be the full IP address of the destination
+
+
+
+Internet Engineering Task Force [Page 49]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ host, or only the destination network number. Field (3),
+ the TOS, SHOULD be included.
+
+ See Section 3.3.4.2 for a discussion of the implications of
+ multihoming for the lookup procedure in this cache.
+
+ DISCUSSION:
+ Including the Type-of-Service field in the route cache
+ and considering it in the host route algorithm will
+ provide the necessary mechanism for the future when
+ Type-of-Service routing is commonly used in the
+ Internet. See Section 3.2.1.6.
+
+ Each route cache entry defines the endpoints of an
+ Internet path. Although the connecting path may change
+ dynamically in an arbitrary way, the transmission
+ characteristics of the path tend to remain
+ approximately constant over a time period longer than a
+ single typical host-host transport connection.
+ Therefore, a route cache entry is a natural place to
+ cache data on the properties of the path. Examples of
+ such properties might be the maximum unfragmented
+ datagram size (see Section 3.3.3), or the average
+ round-trip delay measured by a transport protocol.
+ This data will generally be both gathered and used by a
+ higher layer protocol, e.g., by TCP, or by an
+ application using UDP. Experiments are currently in
+ progress on caching path properties in this manner.
+
+ There is no consensus on whether the route cache should
+ be keyed on destination host addresses alone, or allow
+ both host and network addresses. Those who favor the
+ use of only host addresses argue that:
+
+ (1) As required in Section 3.3.1.2, Redirect messages
+ will generally result in entries keyed on
+ destination host addresses; the simplest and most
+ general scheme would be to use host addresses
+ always.
+
+ (2) The IP layer may not always know the address mask
+ for a network address in a complex subnetted
+ environment.
+
+ (3) The use of only host addresses allows the
+ destination address to be used as a pure 32-bit
+ number, which may allow the Internet architecture
+ to be more easily extended in the future without
+
+
+
+Internet Engineering Task Force [Page 50]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ any change to the hosts.
+
+ The opposing view is that allowing a mixture of
+ destination hosts and networks in the route cache:
+
+ (1) Saves memory space.
+
+ (2) Leads to a simpler data structure, easily
+ combining the cache with the tables of default and
+ static routes (see below).
+
+ (3) Provides a more useful place to cache path
+ properties, as discussed earlier.
+
+
+ IMPLEMENTATION:
+ The cache needs to be large enough to include entries
+ for the maximum number of destination hosts that may be
+ in use at one time.
+
+ A route cache entry may also include control
+ information used to choose an entry for replacement.
+ This might take the form of a "recently used" bit, a
+ use count, or a last-used timestamp, for example. It
+ is recommended that it include the time of last
+ modification of the entry, for diagnostic purposes.
+
+ An implementation may wish to reduce the overhead of
+ scanning the route cache for every datagram to be
+ transmitted. This may be accomplished with a hash
+ table to speed the lookup, or by giving a connection-
+ oriented transport protocol a "hint" or temporary
+ handle on the appropriate cache entry, to be passed to
+ the IP layer with each subsequent datagram.
+
+ Although we have described the route cache, the lists
+ of default gateways, and a table of static routes as
+ conceptually distinct, in practice they may be combined
+ into a single "routing table" data structure.
+
+ 3.3.1.4 Dead Gateway Detection
+
+ The IP layer MUST be able to detect the failure of a "next-
+ hop" gateway that is listed in its route cache and to choose
+ an alternate gateway (see Section 3.3.1.5).
+
+ Dead gateway detection is covered in some detail in RFC-816
+ [IP:11]. Experience to date has not produced a complete
+
+
+
+Internet Engineering Task Force [Page 51]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ algorithm which is totally satisfactory, though it has
+ identified several forbidden paths and promising techniques.
+
+ * A particular gateway SHOULD NOT be used indefinitely in
+ the absence of positive indications that it is
+ functioning.
+
+ * Active probes such as "pinging" (i.e., using an ICMP
+ Echo Request/Reply exchange) are expensive and scale
+ poorly. In particular, hosts MUST NOT actively check
+ the status of a first-hop gateway by simply pinging the
+ gateway continuously.
+
+ * Even when it is the only effective way to verify a
+ gateway's status, pinging MUST be used only when
+ traffic is being sent to the gateway and when there is
+ no other positive indication to suggest that the
+ gateway is functioning.
+
+ * To avoid pinging, the layers above and/or below the
+ Internet layer SHOULD be able to give "advice" on the
+ status of route cache entries when either positive
+ (gateway OK) or negative (gateway dead) information is
+ available.
+
+
+ DISCUSSION:
+ If an implementation does not include an adequate
+ mechanism for detecting a dead gateway and re-routing,
+ a gateway failure may cause datagrams to apparently
+ vanish into a "black hole". This failure can be
+ extremely confusing for users and difficult for network
+ personnel to debug.
+
+ The dead-gateway detection mechanism must not cause
+ unacceptable load on the host, on connected networks,
+ or on first-hop gateway(s). The exact constraints on
+ the timeliness of dead gateway detection and on
+ acceptable load may vary somewhat depending on the
+ nature of the host's mission, but a host generally
+ needs to detect a failed first-hop gateway quickly
+ enough that transport-layer connections will not break
+ before an alternate gateway can be selected.
+
+ Passing advice from other layers of the protocol stack
+ complicates the interfaces between the layers, but it
+ is the preferred approach to dead gateway detection.
+ Advice can come from almost any part of the IP/TCP
+
+
+
+Internet Engineering Task Force [Page 52]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ architecture, but it is expected to come primarily from
+ the transport and link layers. Here are some possible
+ sources for gateway advice:
+
+ o TCP or any connection-oriented transport protocol
+ should be able to give negative advice, e.g.,
+ triggered by excessive retransmissions.
+
+ o TCP may give positive advice when (new) data is
+ acknowledged. Even though the route may be
+ asymmetric, an ACK for new data proves that the
+ acknowleged data must have been transmitted
+ successfully.
+
+ o An ICMP Redirect message from a particular gateway
+ should be used as positive advice about that
+ gateway.
+
+ o Link-layer information that reliably detects and
+ reports host failures (e.g., ARPANET Destination
+ Dead messages) should be used as negative advice.
+
+ o Failure to ARP or to re-validate ARP mappings may
+ be used as negative advice for the corresponding
+ IP address.
+
+ o Packets arriving from a particular link-layer
+ address are evidence that the system at this
+ address is alive. However, turning this
+ information into advice about gateways requires
+ mapping the link-layer address into an IP address,
+ and then checking that IP address against the
+ gateways pointed to by the route cache. This is
+ probably prohibitively inefficient.
+
+ Note that positive advice that is given for every
+ datagram received may cause unacceptable overhead in
+ the implementation.
+
+ While advice might be passed using required arguments
+ in all interfaces to the IP layer, some transport and
+ application layer protocols cannot deduce the correct
+ advice. These interfaces must therefore allow a
+ neutral value for advice, since either always-positive
+ or always-negative advice leads to incorrect behavior.
+
+ There is another technique for dead gateway detection
+ that has been commonly used but is not recommended.
+
+
+
+Internet Engineering Task Force [Page 53]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ This technique depends upon the host passively
+ receiving ("wiretapping") the Interior Gateway Protocol
+ (IGP) datagrams that the gateways are broadcasting to
+ each other. This approach has the drawback that a host
+ needs to recognize all the interior gateway protocols
+ that gateways may use (see [INTRO:2]). In addition, it
+ only works on a broadcast network.
+
+ At present, pinging (i.e., using ICMP Echo messages) is
+ the mechanism for gateway probing when absolutely
+ required. A successful ping guarantees that the
+ addressed interface and its associated machine are up,
+ but it does not guarantee that the machine is a gateway
+ as opposed to a host. The normal inference is that if
+ a Redirect or other evidence indicates that a machine
+ was a gateway, successful pings will indicate that the
+ machine is still up and hence still a gateway.
+ However, since a host silently discards packets that a
+ gateway would forward or redirect, this assumption
+ could sometimes fail. To avoid this problem, a new
+ ICMP message under development will ask "are you a
+ gateway?"
+
+ IMPLEMENTATION:
+ The following specific algorithm has been suggested:
+
+ o Associate a "reroute timer" with each gateway
+ pointed to by the route cache. Initialize the
+ timer to a value Tr, which must be small enough to
+ allow detection of a dead gateway before transport
+ connections time out.
+
+ o Positive advice would reset the reroute timer to
+ Tr. Negative advice would reduce or zero the
+ reroute timer.
+
+ o Whenever the IP layer used a particular gateway to
+ route a datagram, it would check the corresponding
+ reroute timer. If the timer had expired (reached
+ zero), the IP layer would send a ping to the
+ gateway, followed immediately by the datagram.
+
+ o The ping (ICMP Echo) would be sent again if
+ necessary, up to N times. If no ping reply was
+ received in N tries, the gateway would be assumed
+ to have failed, and a new first-hop gateway would
+ be chosen for all cache entries pointing to the
+ failed gateway.
+
+
+
+Internet Engineering Task Force [Page 54]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ Note that the size of Tr is inversely related to the
+ amount of advice available. Tr should be large enough
+ to insure that:
+
+ * Any pinging will be at a low level (e.g., <10%) of
+ all packets sent to a gateway from the host, AND
+
+ * pinging is infrequent (e.g., every 3 minutes)
+
+ Since the recommended algorithm is concerned with the
+ gateways pointed to by route cache entries, rather than
+ the cache entries themselves, a two level data
+ structure (perhaps coordinated with ARP or similar
+ caches) may be desirable for implementing a route
+ cache.
+
+ 3.3.1.5 New Gateway Selection
+
+ If the failed gateway is not the current default, the IP
+ layer can immediately switch to a default gateway. If it is
+ the current default that failed, the IP layer MUST select a
+ different default gateway (assuming more than one default is
+ known) for the failed route and for establishing new routes.
+
+ DISCUSSION:
+ When a gateway does fail, the other gateways on the
+ connected network will learn of the failure through
+ some inter-gateway routing protocol. However, this
+ will not happen instantaneously, since gateway routing
+ protocols typically have a settling time of 30-60
+ seconds. If the host switches to an alternative
+ gateway before the gateways have agreed on the failure,
+ the new target gateway will probably forward the
+ datagram to the failed gateway and send a Redirect back
+ to the host pointing to the failed gateway (!). The
+ result is likely to be a rapid oscillation in the
+ contents of the host's route cache during the gateway
+ settling period. It has been proposed that the dead-
+ gateway logic should include some hysteresis mechanism
+ to prevent such oscillations. However, experience has
+ not shown any harm from such oscillations, since
+ service cannot be restored to the host until the
+ gateways' routing information does settle down.
+
+ IMPLEMENTATION:
+ One implementation technique for choosing a new default
+ gateway is to simply round-robin among the default
+ gateways in the host's list. Another is to rank the
+
+
+
+Internet Engineering Task Force [Page 55]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ gateways in priority order, and when the current
+ default gateway is not the highest priority one, to
+ "ping" the higher-priority gateways slowly to detect
+ when they return to service. This pinging can be at a
+ very low rate, e.g., 0.005 per second.
+
+ 3.3.1.6 Initialization
+
+ The following information MUST be configurable:
+
+ (1) IP address(es).
+
+ (2) Address mask(s).
+
+ (3) A list of default gateways, with a preference level.
+
+ A manual method of entering this configuration data MUST be
+ provided. In addition, a variety of methods can be used to
+ determine this information dynamically; see the section on
+ "Host Initialization" in [INTRO:1].
+
+ DISCUSSION:
+ Some host implementations use "wiretapping" of gateway
+ protocols on a broadcast network to learn what gateways
+ exist. A standard method for default gateway discovery
+ is under development.
+
+ 3.3.2 Reassembly
+
+ The IP layer MUST implement reassembly of IP datagrams.
+
+ We designate the largest datagram size that can be reassembled
+ by EMTU_R ("Effective MTU to receive"); this is sometimes
+ called the "reassembly buffer size". EMTU_R MUST be greater
+ than or equal to 576, SHOULD be either configurable or
+ indefinite, and SHOULD be greater than or equal to the MTU of
+ the connected network(s).
+
+ DISCUSSION:
+ A fixed EMTU_R limit should not be built into the code
+ because some application layer protocols require EMTU_R
+ values larger than 576.
+
+ IMPLEMENTATION:
+ An implementation may use a contiguous reassembly buffer
+ for each datagram, or it may use a more complex data
+ structure that places no definite limit on the reassembled
+ datagram size; in the latter case, EMTU_R is said to be
+
+
+
+Internet Engineering Task Force [Page 56]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ "indefinite".
+
+ Logically, reassembly is performed by simply copying each
+ fragment into the packet buffer at the proper offset.
+ Note that fragments may overlap if successive
+ retransmissions use different packetizing but the same
+ reassembly Id.
+
+ The tricky part of reassembly is the bookkeeping to
+ determine when all bytes of the datagram have been
+ reassembled. We recommend Clark's algorithm [IP:10] that
+ requires no additional data space for the bookkeeping.
+ However, note that, contrary to [IP:10], the first
+ fragment header needs to be saved for inclusion in a
+ possible ICMP Time Exceeded (Reassembly Timeout) message.
+
+ There MUST be a mechanism by which the transport layer can
+ learn MMS_R, the maximum message size that can be received and
+ reassembled in an IP datagram (see GET_MAXSIZES calls in
+ Section 3.4). If EMTU_R is not indefinite, then the value of
+ MMS_R is given by:
+
+ MMS_R = EMTU_R - 20
+
+ since 20 is the minimum size of an IP header.
+
+ There MUST be a reassembly timeout. The reassembly timeout
+ value SHOULD be a fixed value, not set from the remaining TTL.
+ It is recommended that the value lie between 60 seconds and 120
+ seconds. If this timeout expires, the partially-reassembled
+ datagram MUST be discarded and an ICMP Time Exceeded message
+ sent to the source host (if fragment zero has been received).
+
+ DISCUSSION:
+ The IP specification says that the reassembly timeout
+ should be the remaining TTL from the IP header, but this
+ does not work well because gateways generally treat TTL as
+ a simple hop count rather than an elapsed time. If the
+ reassembly timeout is too small, datagrams will be
+ discarded unnecessarily, and communication may fail. The
+ timeout needs to be at least as large as the typical
+ maximum delay across the Internet. A realistic minimum
+ reassembly timeout would be 60 seconds.
+
+ It has been suggested that a cache might be kept of
+ round-trip times measured by transport protocols for
+ various destinations, and that these values might be used
+ to dynamically determine a reasonable reassembly timeout
+
+
+
+Internet Engineering Task Force [Page 57]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ value. Further investigation of this approach is
+ required.
+
+ If the reassembly timeout is set too high, buffer
+ resources in the receiving host will be tied up too long,
+ and the MSL (Maximum Segment Lifetime) [TCP:1] will be
+ larger than necessary. The MSL controls the maximum rate
+ at which fragmented datagrams can be sent using distinct
+ values of the 16-bit Ident field; a larger MSL lowers the
+ maximum rate. The TCP specification [TCP:1] arbitrarily
+ assumes a value of 2 minutes for MSL. This sets an upper
+ limit on a reasonable reassembly timeout value.
+
+ 3.3.3 Fragmentation
+
+ Optionally, the IP layer MAY implement a mechanism to fragment
+ outgoing datagrams intentionally.
+
+ We designate by EMTU_S ("Effective MTU for sending") the
+ maximum IP datagram size that may be sent, for a particular
+ combination of IP source and destination addresses and perhaps
+ TOS.
+
+ A host MUST implement a mechanism to allow the transport layer
+ to learn MMS_S, the maximum transport-layer message size that
+ may be sent for a given {source, destination, TOS} triplet (see
+ GET_MAXSIZES call in Section 3.4). If no local fragmentation
+ is performed, the value of MMS_S will be:
+
+ MMS_S = EMTU_S - <IP header size>
+
+ and EMTU_S must be less than or equal to the MTU of the network
+ interface corresponding to the source address of the datagram.
+ Note that <IP header size> in this equation will be 20, unless
+ the IP reserves space to insert IP options for its own purposes
+ in addition to any options inserted by the transport layer.
+
+ A host that does not implement local fragmentation MUST ensure
+ that the transport layer (for TCP) or the application layer
+ (for UDP) obtains MMS_S from the IP layer and does not send a
+ datagram exceeding MMS_S in size.
+
+ It is generally desirable to avoid local fragmentation and to
+ choose EMTU_S low enough to avoid fragmentation in any gateway
+ along the path. In the absence of actual knowledge of the
+ minimum MTU along the path, the IP layer SHOULD use
+ EMTU_S <= 576 whenever the destination address is not on a
+ connected network, and otherwise use the connected network's
+
+
+
+Internet Engineering Task Force [Page 58]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ MTU.
+
+ The MTU of each physical interface MUST be configurable.
+
+ A host IP layer implementation MAY have a configuration flag
+ "All-Subnets-MTU", indicating that the MTU of the connected
+ network is to be used for destinations on different subnets
+ within the same network, but not for other networks. Thus,
+ this flag causes the network class mask, rather than the subnet
+ address mask, to be used to choose an EMTU_S. For a multihomed
+ host, an "All-Subnets-MTU" flag is needed for each network
+ interface.
+
+ DISCUSSION:
+ Picking the correct datagram size to use when sending data
+ is a complex topic [IP:9].
+
+ (a) In general, no host is required to accept an IP
+ datagram larger than 576 bytes (including header and
+ data), so a host must not send a larger datagram
+ without explicit knowledge or prior arrangement with
+ the destination host. Thus, MMS_S is only an upper
+ bound on the datagram size that a transport protocol
+ may send; even when MMS_S exceeds 556, the transport
+ layer must limit its messages to 556 bytes in the
+ absence of other knowledge about the destination
+ host.
+
+ (b) Some transport protocols (e.g., TCP) provide a way to
+ explicitly inform the sender about the largest
+ datagram the other end can receive and reassemble
+ [IP:7]. There is no corresponding mechanism in the
+ IP layer.
+
+ A transport protocol that assumes an EMTU_R larger
+ than 576 (see Section 3.3.2), can send a datagram of
+ this larger size to another host that implements the
+ same protocol.
+
+ (c) Hosts should ideally limit their EMTU_S for a given
+ destination to the minimum MTU of all the networks
+ along the path, to avoid any fragmentation. IP
+ fragmentation, while formally correct, can create a
+ serious transport protocol performance problem,
+ because loss of a single fragment means all the
+ fragments in the segment must be retransmitted
+ [IP:9].
+
+
+
+
+Internet Engineering Task Force [Page 59]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ Since nearly all networks in the Internet currently
+ support an MTU of 576 or greater, we strongly recommend
+ the use of 576 for datagrams sent to non-local networks.
+
+ It has been suggested that a host could determine the MTU
+ over a given path by sending a zero-offset datagram
+ fragment and waiting for the receiver to time out the
+ reassembly (which cannot complete!) and return an ICMP
+ Time Exceeded message. This message would include the
+ largest remaining fragment header in its body. More
+ direct mechanisms are being experimented with, but have
+ not yet been adopted (see e.g., RFC-1063).
+
+ 3.3.4 Local Multihoming
+
+ 3.3.4.1 Introduction
+
+ A multihomed host has multiple IP addresses, which we may
+ think of as "logical interfaces". These logical interfaces
+ may be associated with one or more physical interfaces, and
+ these physical interfaces may be connected to the same or
+ different networks.
+
+ Here are some important cases of multihoming:
+
+ (a) Multiple Logical Networks
+
+ The Internet architects envisioned that each physical
+ network would have a single unique IP network (or
+ subnet) number. However, LAN administrators have
+ sometimes found it useful to violate this assumption,
+ operating a LAN with multiple logical networks per
+ physical connected network.
+
+ If a host connected to such a physical network is
+ configured to handle traffic for each of N different
+ logical networks, then the host will have N logical
+ interfaces. These could share a single physical
+ interface, or might use N physical interfaces to the
+ same network.
+
+ (b) Multiple Logical Hosts
+
+ When a host has multiple IP addresses that all have the
+ same <Network-number> part (and the same <Subnet-
+ number> part, if any), the logical interfaces are known
+ as "logical hosts". These logical interfaces might
+ share a single physical interface or might use separate
+
+
+
+Internet Engineering Task Force [Page 60]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ physical interfaces to the same physical network.
+
+ (c) Simple Multihoming
+
+ In this case, each logical interface is mapped into a
+ separate physical interface and each physical interface
+ is connected to a different physical network. The term
+ "multihoming" was originally applied only to this case,
+ but it is now applied more generally.
+
+ A host with embedded gateway functionality will
+ typically fall into the simple multihoming case. Note,
+ however, that a host may be simply multihomed without
+ containing an embedded gateway, i.e., without
+ forwarding datagrams from one connected network to
+ another.
+
+ This case presents the most difficult routing problems.
+ The choice of interface (i.e., the choice of first-hop
+ network) may significantly affect performance or even
+ reachability of remote parts of the Internet.
+
+
+ Finally, we note another possibility that is NOT
+ multihoming: one logical interface may be bound to multiple
+ physical interfaces, in order to increase the reliability or
+ throughput between directly connected machines by providing
+ alternative physical paths between them. For instance, two
+ systems might be connected by multiple point-to-point links.
+ We call this "link-layer multiplexing". With link-layer
+ multiplexing, the protocols above the link layer are unaware
+ that multiple physical interfaces are present; the link-
+ layer device driver is responsible for multiplexing and
+ routing packets across the physical interfaces.
+
+ In the Internet protocol architecture, a transport protocol
+ instance ("entity") has no address of its own, but instead
+ uses a single Internet Protocol (IP) address. This has
+ implications for the IP, transport, and application layers,
+ and for the interfaces between them. In particular, the
+ application software may have to be aware of the multiple IP
+ addresses of a multihomed host; in other cases, the choice
+ can be made within the network software.
+
+ 3.3.4.2 Multihoming Requirements
+
+ The following general rules apply to the selection of an IP
+ source address for sending a datagram from a multihomed
+
+
+
+Internet Engineering Task Force [Page 61]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ host.
+
+ (1) If the datagram is sent in response to a received
+ datagram, the source address for the response SHOULD be
+ the specific-destination address of the request. See
+ Sections 4.1.3.5 and 4.2.3.7 and the "General Issues"
+ section of [INTRO:1] for more specific requirements on
+ higher layers.
+
+ Otherwise, a source address must be selected.
+
+ (2) An application MUST be able to explicitly specify the
+ source address for initiating a connection or a
+ request.
+
+ (3) In the absence of such a specification, the networking
+ software MUST choose a source address. Rules for this
+ choice are described below.
+
+
+ There are two key requirement issues related to multihoming:
+
+ (A) A host MAY silently discard an incoming datagram whose
+ destination address does not correspond to the physical
+ interface through which it is received.
+
+ (B) A host MAY restrict itself to sending (non-source-
+ routed) IP datagrams only through the physical
+ interface that corresponds to the IP source address of
+ the datagrams.
+
+
+ DISCUSSION:
+ Internet host implementors have used two different
+ conceptual models for multihoming, briefly summarized
+ in the following discussion. This document takes no
+ stand on which model is preferred; each seems to have a
+ place. This ambivalence is reflected in the issues (A)
+ and (B) being optional.
+
+ o Strong ES Model
+
+ The Strong ES (End System, i.e., host) model
+ emphasizes the host/gateway (ES/IS) distinction,
+ and would therefore substitute MUST for MAY in
+ issues (A) and (B) above. It tends to model a
+ multihomed host as a set of logical hosts within
+ the same physical host.
+
+
+
+Internet Engineering Task Force [Page 62]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ With respect to (A), proponents of the Strong ES
+ model note that automatic Internet routing
+ mechanisms could not route a datagram to a
+ physical interface that did not correspond to the
+ destination address.
+
+ Under the Strong ES model, the route computation
+ for an outgoing datagram is the mapping:
+
+ route(src IP addr, dest IP addr, TOS)
+ -> gateway
+
+ Here the source address is included as a parameter
+ in order to select a gateway that is directly
+ reachable on the corresponding physical interface.
+ Note that this model logically requires that in
+ general there be at least one default gateway, and
+ preferably multiple defaults, for each IP source
+ address.
+
+ o Weak ES Model
+
+ This view de-emphasizes the ES/IS distinction, and
+ would therefore substitute MUST NOT for MAY in
+ issues (A) and (B). This model may be the more
+ natural one for hosts that wiretap gateway routing
+ protocols, and is necessary for hosts that have
+ embedded gateway functionality.
+
+ The Weak ES Model may cause the Redirect mechanism
+ to fail. If a datagram is sent out a physical
+ interface that does not correspond to the
+ destination address, the first-hop gateway will
+ not realize when it needs to send a Redirect. On
+ the other hand, if the host has embedded gateway
+ functionality, then it has routing information
+ without listening to Redirects.
+
+ In the Weak ES model, the route computation for an
+ outgoing datagram is the mapping:
+
+ route(dest IP addr, TOS) -> gateway, interface
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 63]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ 3.3.4.3 Choosing a Source Address
+
+ DISCUSSION:
+ When it sends an initial connection request (e.g., a
+ TCP "SYN" segment) or a datagram service request (e.g.,
+ a UDP-based query), the transport layer on a multihomed
+ host needs to know which source address to use. If the
+ application does not specify it, the transport layer
+ must ask the IP layer to perform the conceptual
+ mapping:
+
+ GET_SRCADDR(remote IP addr, TOS)
+ -> local IP address
+
+ Here TOS is the Type-of-Service value (see Section
+ 3.2.1.6), and the result is the desired source address.
+ The following rules are suggested for implementing this
+ mapping:
+
+ (a) If the remote Internet address lies on one of the
+ (sub-) nets to which the host is directly
+ connected, a corresponding source address may be
+ chosen, unless the corresponding interface is
+ known to be down.
+
+ (b) The route cache may be consulted, to see if there
+ is an active route to the specified destination
+ network through any network interface; if so, a
+ local IP address corresponding to that interface
+ may be chosen.
+
+ (c) The table of static routes, if any (see Section
+ 3.3.1.2) may be similarly consulted.
+
+ (d) The default gateways may be consulted. If these
+ gateways are assigned to different interfaces, the
+ interface corresponding to the gateway with the
+ highest preference may be chosen.
+
+ In the future, there may be a defined way for a
+ multihomed host to ask the gateways on all connected
+ networks for advice about the best network to use for a
+ given destination.
+
+ IMPLEMENTATION:
+ It will be noted that this process is essentially the
+ same as datagram routing (see Section 3.3.1), and
+ therefore hosts may be able to combine the
+
+
+
+Internet Engineering Task Force [Page 64]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ implementation of the two functions.
+
+ 3.3.5 Source Route Forwarding
+
+ Subject to restrictions given below, a host MAY be able to act
+ as an intermediate hop in a source route, forwarding a source-
+ routed datagram to the next specified hop.
+
+ However, in performing this gateway-like function, the host
+ MUST obey all the relevant rules for a gateway forwarding
+ source-routed datagrams [INTRO:2]. This includes the following
+ specific provisions, which override the corresponding host
+ provisions given earlier in this document:
+
+ (A) TTL (ref. Section 3.2.1.7)
+
+ The TTL field MUST be decremented and the datagram perhaps
+ discarded as specified for a gateway in [INTRO:2].
+
+ (B) ICMP Destination Unreachable (ref. Section 3.2.2.1)
+
+ A host MUST be able to generate Destination Unreachable
+ messages with the following codes:
+
+ 4 (Fragmentation Required but DF Set) when a source-
+ routed datagram cannot be fragmented to fit into the
+ target network;
+
+ 5 (Source Route Failed) when a source-routed datagram
+ cannot be forwarded, e.g., because of a routing
+ problem or because the next hop of a strict source
+ route is not on a connected network.
+
+ (C) IP Source Address (ref. Section 3.2.1.3)
+
+ A source-routed datagram being forwarded MAY (and normally
+ will) have a source address that is not one of the IP
+ addresses of the forwarding host.
+
+ (D) Record Route Option (ref. Section 3.2.1.8d)
+
+ A host that is forwarding a source-routed datagram
+ containing a Record Route option MUST update that option,
+ if it has room.
+
+ (E) Timestamp Option (ref. Section 3.2.1.8e)
+
+ A host that is forwarding a source-routed datagram
+
+
+
+Internet Engineering Task Force [Page 65]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ containing a Timestamp Option MUST add the current
+ timestamp to that option, according to the rules for this
+ option.
+
+ To define the rules restricting host forwarding of source-
+ routed datagrams, we use the term "local source-routing" if the
+ next hop will be through the same physical interface through
+ which the datagram arrived; otherwise, it is "non-local
+ source-routing".
+
+ o A host is permitted to perform local source-routing
+ without restriction.
+
+ o A host that supports non-local source-routing MUST have a
+ configurable switch to disable forwarding, and this switch
+ MUST default to disabled.
+
+ o The host MUST satisfy all gateway requirements for
+ configurable policy filters [INTRO:2] restricting non-
+ local forwarding.
+
+ If a host receives a datagram with an incomplete source route
+ but does not forward it for some reason, the host SHOULD return
+ an ICMP Destination Unreachable (code 5, Source Route Failed)
+ message, unless the datagram was itself an ICMP error message.
+
+ 3.3.6 Broadcasts
+
+ Section 3.2.1.3 defined the four standard IP broadcast address
+ forms:
+
+ Limited Broadcast: {-1, -1}
+
+ Directed Broadcast: {<Network-number>,-1}
+
+ Subnet Directed Broadcast:
+ {<Network-number>,<Subnet-number>,-1}
+
+ All-Subnets Directed Broadcast: {<Network-number>,-1,-1}
+
+ A host MUST recognize any of these forms in the destination
+ address of an incoming datagram.
+
+ There is a class of hosts* that use non-standard broadcast
+ address forms, substituting 0 for -1. All hosts SHOULD
+_________________________
+*4.2BSD Unix and its derivatives, but not 4.3BSD.
+
+
+
+
+Internet Engineering Task Force [Page 66]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ recognize and accept any of these non-standard broadcast
+ addresses as the destination address of an incoming datagram.
+ A host MAY optionally have a configuration option to choose the
+ 0 or the -1 form of broadcast address, for each physical
+ interface, but this option SHOULD default to the standard (-1)
+ form.
+
+ When a host sends a datagram to a link-layer broadcast address,
+ the IP destination address MUST be a legal IP broadcast or IP
+ multicast address.
+
+ A host SHOULD silently discard a datagram that is received via
+ a link-layer broadcast (see Section 2.4) but does not specify
+ an IP multicast or broadcast destination address.
+
+ Hosts SHOULD use the Limited Broadcast address to broadcast to
+ a connected network.
+
+
+ DISCUSSION:
+ Using the Limited Broadcast address instead of a Directed
+ Broadcast address may improve system robustness. Problems
+ are often caused by machines that do not understand the
+ plethora of broadcast addresses (see Section 3.2.1.3), or
+ that may have different ideas about which broadcast
+ addresses are in use. The prime example of the latter is
+ machines that do not understand subnetting but are
+ attached to a subnetted net. Sending a Subnet Broadcast
+ for the connected network will confuse those machines,
+ which will see it as a message to some other host.
+
+ There has been discussion on whether a datagram addressed
+ to the Limited Broadcast address ought to be sent from all
+ the interfaces of a multihomed host. This specification
+ takes no stand on the issue.
+
+ 3.3.7 IP Multicasting
+
+ A host SHOULD support local IP multicasting on all connected
+ networks for which a mapping from Class D IP addresses to
+ link-layer addresses has been specified (see below). Support
+ for local IP multicasting includes sending multicast datagrams,
+ joining multicast groups and receiving multicast datagrams, and
+ leaving multicast groups. This implies support for all of
+ [IP:4] except the IGMP protocol itself, which is OPTIONAL.
+
+
+
+
+
+
+Internet Engineering Task Force [Page 67]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ DISCUSSION:
+ IGMP provides gateways that are capable of multicast
+ routing with the information required to support IP
+ multicasting across multiple networks. At this time,
+ multicast-routing gateways are in the experimental stage
+ and are not widely available. For hosts that are not
+ connected to networks with multicast-routing gateways or
+ that do not need to receive multicast datagrams
+ originating on other networks, IGMP serves no purpose and
+ is therefore optional for now. However, the rest of
+ [IP:4] is currently recommended for the purpose of
+ providing IP-layer access to local network multicast
+ addressing, as a preferable alternative to local broadcast
+ addressing. It is expected that IGMP will become
+ recommended at some future date, when multicast-routing
+ gateways have become more widely available.
+
+ If IGMP is not implemented, a host SHOULD still join the "all-
+ hosts" group (224.0.0.1) when the IP layer is initialized and
+ remain a member for as long as the IP layer is active.
+
+ DISCUSSION:
+ Joining the "all-hosts" group will support strictly local
+ uses of multicasting, e.g., a gateway discovery protocol,
+ even if IGMP is not implemented.
+
+ The mapping of IP Class D addresses to local addresses is
+ currently specified for the following types of networks:
+
+ o Ethernet/IEEE 802.3, as defined in [IP:4].
+
+ o Any network that supports broadcast but not multicast,
+ addressing: all IP Class D addresses map to the local
+ broadcast address.
+
+ o Any type of point-to-point link (e.g., SLIP or HDLC
+ links): no mapping required. All IP multicast datagrams
+ are sent as-is, inside the local framing.
+
+ Mappings for other types of networks will be specified in the
+ future.
+
+ A host SHOULD provide a way for higher-layer protocols or
+ applications to determine which of the host's connected
+ network(s) support IP multicast addressing.
+
+
+
+
+
+
+Internet Engineering Task Force [Page 68]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ 3.3.8 Error Reporting
+
+ Wherever practical, hosts MUST return ICMP error datagrams on
+ detection of an error, except in those cases where returning an
+ ICMP error message is specifically prohibited.
+
+ DISCUSSION:
+ A common phenomenon in datagram networks is the "black
+ hole disease": datagrams are sent out, but nothing comes
+ back. Without any error datagrams, it is difficult for
+ the user to figure out what the problem is.
+
+ 3.4 INTERNET/TRANSPORT LAYER INTERFACE
+
+ The interface between the IP layer and the transport layer MUST
+ provide full access to all the mechanisms of the IP layer,
+ including options, Type-of-Service, and Time-to-Live. The
+ transport layer MUST either have mechanisms to set these interface
+ parameters, or provide a path to pass them through from an
+ application, or both.
+
+ DISCUSSION:
+ Applications are urged to make use of these mechanisms where
+ applicable, even when the mechanisms are not currently
+ effective in the Internet (e.g., TOS). This will allow these
+ mechanisms to be immediately useful when they do become
+ effective, without a large amount of retrofitting of host
+ software.
+
+ We now describe a conceptual interface between the transport layer
+ and the IP layer, as a set of procedure calls. This is an
+ extension of the information in Section 3.3 of RFC-791 [IP:1].
+
+
+ * Send Datagram
+
+ SEND(src, dst, prot, TOS, TTL, BufPTR, len, Id, DF, opt
+ => result )
+
+ where the parameters are defined in RFC-791. Passing an Id
+ parameter is optional; see Section 3.2.1.5.
+
+
+ * Receive Datagram
+
+ RECV(BufPTR, prot
+ => result, src, dst, SpecDest, TOS, len, opt)
+
+
+
+
+Internet Engineering Task Force [Page 69]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ All the parameters are defined in RFC-791, except for:
+
+ SpecDest = specific-destination address of datagram
+ (defined in Section 3.2.1.3)
+
+ The result parameter dst contains the datagram's destination
+ address. Since this may be a broadcast or multicast address,
+ the SpecDest parameter (not shown in RFC-791) MUST be passed.
+ The parameter opt contains all the IP options received in the
+ datagram; these MUST also be passed to the transport layer.
+
+
+ * Select Source Address
+
+ GET_SRCADDR(remote, TOS) -> local
+
+ remote = remote IP address
+ TOS = Type-of-Service
+ local = local IP address
+
+ See Section 3.3.4.3.
+
+
+ * Find Maximum Datagram Sizes
+
+ GET_MAXSIZES(local, remote, TOS) -> MMS_R, MMS_S
+
+ MMS_R = maximum receive transport-message size.
+ MMS_S = maximum send transport-message size.
+ (local, remote, TOS defined above)
+
+ See Sections 3.3.2 and 3.3.3.
+
+
+ * Advice on Delivery Success
+
+ ADVISE_DELIVPROB(sense, local, remote, TOS)
+
+ Here the parameter sense is a 1-bit flag indicating whether
+ positive or negative advice is being given; see the
+ discussion in Section 3.3.1.4. The other parameters were
+ defined earlier.
+
+
+ * Send ICMP Message
+
+ SEND_ICMP(src, dst, TOS, TTL, BufPTR, len, Id, DF, opt)
+ -> result
+
+
+
+Internet Engineering Task Force [Page 70]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ (Parameters defined in RFC-791).
+
+ Passing an Id parameter is optional; see Section 3.2.1.5.
+ The transport layer MUST be able to send certain ICMP
+ messages: Port Unreachable or any of the query-type
+ messages. This function could be considered to be a special
+ case of the SEND() call, of course; we describe it separately
+ for clarity.
+
+
+ * Receive ICMP Message
+
+ RECV_ICMP(BufPTR ) -> result, src, dst, len, opt
+
+ (Parameters defined in RFC-791).
+
+ The IP layer MUST pass certain ICMP messages up to the
+ appropriate transport-layer routine. This function could be
+ considered to be a special case of the RECV() call, of
+ course; we describe it separately for clarity.
+
+ For an ICMP error message, the data that is passed up MUST
+ include the original Internet header plus all the octets of
+ the original message that are included in the ICMP message.
+ This data will be used by the transport layer to locate the
+ connection state information, if any.
+
+ In particular, the following ICMP messages are to be passed
+ up:
+
+ o Destination Unreachable
+
+ o Source Quench
+
+ o Echo Reply (to ICMP user interface, unless the Echo
+ Request originated in the IP layer)
+
+ o Timestamp Reply (to ICMP user interface)
+
+ o Time Exceeded
+
+
+ DISCUSSION:
+ In the future, there may be additions to this interface to
+ pass path data (see Section 3.3.1.3) between the IP and
+ transport layers.
+
+
+
+
+
+Internet Engineering Task Force [Page 71]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ 3.5 INTERNET LAYER REQUIREMENTS SUMMARY
+
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION | | | |T|T|e
+-------------------------------------------------|--------|-|-|-|-|-|--
+ | | | | | | |
+Implement IP and ICMP |3.1 |x| | | | |
+Handle remote multihoming in application layer |3.1 |x| | | | |
+Support local multihoming |3.1 | | |x| | |
+Meet gateway specs if forward datagrams |3.1 |x| | | | |
+Configuration switch for embedded gateway |3.1 |x| | | | |1
+ Config switch default to non-gateway |3.1 |x| | | | |1
+ Auto-config based on number of interfaces |3.1 | | | | |x|1
+Able to log discarded datagrams |3.1 | |x| | | |
+ Record in counter |3.1 | |x| | | |
+ | | | | | | |
+Silently discard Version != 4 |3.2.1.1 |x| | | | |
+Verify IP checksum, silently discard bad dgram |3.2.1.2 |x| | | | |
+Addressing: | | | | | | |
+ Subnet addressing (RFC-950) |3.2.1.3 |x| | | | |
+ Src address must be host's own IP address |3.2.1.3 |x| | | | |
+ Silently discard datagram with bad dest addr |3.2.1.3 |x| | | | |
+ Silently discard datagram with bad src addr |3.2.1.3 |x| | | | |
+Support reassembly |3.2.1.4 |x| | | | |
+Retain same Id field in identical datagram |3.2.1.5 | | |x| | |
+ | | | | | | |
+TOS: | | | | | | |
+ Allow transport layer to set TOS |3.2.1.6 |x| | | | |
+ Pass received TOS up to transport layer |3.2.1.6 | |x| | | |
+ Use RFC-795 link-layer mappings for TOS |3.2.1.6 | | | |x| |
+TTL: | | | | | | |
+ Send packet with TTL of 0 |3.2.1.7 | | | | |x|
+ Discard received packets with TTL < 2 |3.2.1.7 | | | | |x|
+ Allow transport layer to set TTL |3.2.1.7 |x| | | | |
+ Fixed TTL is configurable |3.2.1.7 |x| | | | |
+ | | | | | | |
+IP Options: | | | | | | |
+ Allow transport layer to send IP options |3.2.1.8 |x| | | | |
+ Pass all IP options rcvd to higher layer |3.2.1.8 |x| | | | |
+
+
+
+Internet Engineering Task Force [Page 72]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ IP layer silently ignore unknown options |3.2.1.8 |x| | | | |
+ Security option |3.2.1.8a| | |x| | |
+ Send Stream Identifier option |3.2.1.8b| | | |x| |
+ Silently ignore Stream Identifer option |3.2.1.8b|x| | | | |
+ Record Route option |3.2.1.8d| | |x| | |
+ Timestamp option |3.2.1.8e| | |x| | |
+Source Route Option: | | | | | | |
+ Originate & terminate Source Route options |3.2.1.8c|x| | | | |
+ Datagram with completed SR passed up to TL |3.2.1.8c|x| | | | |
+ Build correct (non-redundant) return route |3.2.1.8c|x| | | | |
+ Send multiple SR options in one header |3.2.1.8c| | | | |x|
+ | | | | | | |
+ICMP: | | | | | | |
+ Silently discard ICMP msg with unknown type |3.2.2 |x| | | | |
+ Include more than 8 octets of orig datagram |3.2.2 | | |x| | |
+ Included octets same as received |3.2.2 |x| | | | |
+ Demux ICMP Error to transport protocol |3.2.2 |x| | | | |
+ Send ICMP error message with TOS=0 |3.2.2 | |x| | | |
+ Send ICMP error message for: | | | | | | |
+ - ICMP error msg |3.2.2 | | | | |x|
+ - IP b'cast or IP m'cast |3.2.2 | | | | |x|
+ - Link-layer b'cast |3.2.2 | | | | |x|
+ - Non-initial fragment |3.2.2 | | | | |x|
+ - Datagram with non-unique src address |3.2.2 | | | | |x|
+ Return ICMP error msgs (when not prohibited) |3.3.8 |x| | | | |
+ | | | | | | |
+ Dest Unreachable: | | | | | | |
+ Generate Dest Unreachable (code 2/3) |3.2.2.1 | |x| | | |
+ Pass ICMP Dest Unreachable to higher layer |3.2.2.1 |x| | | | |
+ Higher layer act on Dest Unreach |3.2.2.1 | |x| | | |
+ Interpret Dest Unreach as only hint |3.2.2.1 |x| | | | |
+ Redirect: | | | | | | |
+ Host send Redirect |3.2.2.2 | | | |x| |
+ Update route cache when recv Redirect |3.2.2.2 |x| | | | |
+ Handle both Host and Net Redirects |3.2.2.2 |x| | | | |
+ Discard illegal Redirect |3.2.2.2 | |x| | | |
+ Source Quench: | | | | | | |
+ Send Source Quench if buffering exceeded |3.2.2.3 | | |x| | |
+ Pass Source Quench to higher layer |3.2.2.3 |x| | | | |
+ Higher layer act on Source Quench |3.2.2.3 | |x| | | |
+ Time Exceeded: pass to higher layer |3.2.2.4 |x| | | | |
+ Parameter Problem: | | | | | | |
+ Send Parameter Problem messages |3.2.2.5 | |x| | | |
+ Pass Parameter Problem to higher layer |3.2.2.5 |x| | | | |
+ Report Parameter Problem to user |3.2.2.5 | | |x| | |
+ | | | | | | |
+ ICMP Echo Request or Reply: | | | | | | |
+ Echo server and Echo client |3.2.2.6 |x| | | | |
+
+
+
+Internet Engineering Task Force [Page 73]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ Echo client |3.2.2.6 | |x| | | |
+ Discard Echo Request to broadcast address |3.2.2.6 | | |x| | |
+ Discard Echo Request to multicast address |3.2.2.6 | | |x| | |
+ Use specific-dest addr as Echo Reply src |3.2.2.6 |x| | | | |
+ Send same data in Echo Reply |3.2.2.6 |x| | | | |
+ Pass Echo Reply to higher layer |3.2.2.6 |x| | | | |
+ Reflect Record Route, Time Stamp options |3.2.2.6 | |x| | | |
+ Reverse and reflect Source Route option |3.2.2.6 |x| | | | |
+ | | | | | | |
+ ICMP Information Request or Reply: |3.2.2.7 | | | |x| |
+ ICMP Timestamp and Timestamp Reply: |3.2.2.8 | | |x| | |
+ Minimize delay variability |3.2.2.8 | |x| | | |1
+ Silently discard b'cast Timestamp |3.2.2.8 | | |x| | |1
+ Silently discard m'cast Timestamp |3.2.2.8 | | |x| | |1
+ Use specific-dest addr as TS Reply src |3.2.2.8 |x| | | | |1
+ Reflect Record Route, Time Stamp options |3.2.2.6 | |x| | | |1
+ Reverse and reflect Source Route option |3.2.2.8 |x| | | | |1
+ Pass Timestamp Reply to higher layer |3.2.2.8 |x| | | | |1
+ Obey rules for "standard value" |3.2.2.8 |x| | | | |1
+ | | | | | | |
+ ICMP Address Mask Request and Reply: | | | | | | |
+ Addr Mask source configurable |3.2.2.9 |x| | | | |
+ Support static configuration of addr mask |3.2.2.9 |x| | | | |
+ Get addr mask dynamically during booting |3.2.2.9 | | |x| | |
+ Get addr via ICMP Addr Mask Request/Reply |3.2.2.9 | | |x| | |
+ Retransmit Addr Mask Req if no Reply |3.2.2.9 |x| | | | |3
+ Assume default mask if no Reply |3.2.2.9 | |x| | | |3
+ Update address mask from first Reply only |3.2.2.9 |x| | | | |3
+ Reasonableness check on Addr Mask |3.2.2.9 | |x| | | |
+ Send unauthorized Addr Mask Reply msgs |3.2.2.9 | | | | |x|
+ Explicitly configured to be agent |3.2.2.9 |x| | | | |
+ Static config=> Addr-Mask-Authoritative flag |3.2.2.9 | |x| | | |
+ Broadcast Addr Mask Reply when init. |3.2.2.9 |x| | | | |3
+ | | | | | | |
+ROUTING OUTBOUND DATAGRAMS: | | | | | | |
+ Use address mask in local/remote decision |3.3.1.1 |x| | | | |
+ Operate with no gateways on conn network |3.3.1.1 |x| | | | |
+ Maintain "route cache" of next-hop gateways |3.3.1.2 |x| | | | |
+ Treat Host and Net Redirect the same |3.3.1.2 | |x| | | |
+ If no cache entry, use default gateway |3.3.1.2 |x| | | | |
+ Support multiple default gateways |3.3.1.2 |x| | | | |
+ Provide table of static routes |3.3.1.2 | | |x| | |
+ Flag: route overridable by Redirects |3.3.1.2 | | |x| | |
+ Key route cache on host, not net address |3.3.1.3 | | |x| | |
+ Include TOS in route cache |3.3.1.3 | |x| | | |
+ | | | | | | |
+ Able to detect failure of next-hop gateway |3.3.1.4 |x| | | | |
+ Assume route is good forever |3.3.1.4 | | | |x| |
+
+
+
+Internet Engineering Task Force [Page 74]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ Ping gateways continuously |3.3.1.4 | | | | |x|
+ Ping only when traffic being sent |3.3.1.4 |x| | | | |
+ Ping only when no positive indication |3.3.1.4 |x| | | | |
+ Higher and lower layers give advice |3.3.1.4 | |x| | | |
+ Switch from failed default g'way to another |3.3.1.5 |x| | | | |
+ Manual method of entering config info |3.3.1.6 |x| | | | |
+ | | | | | | |
+REASSEMBLY and FRAGMENTATION: | | | | | | |
+ Able to reassemble incoming datagrams |3.3.2 |x| | | | |
+ At least 576 byte datagrams |3.3.2 |x| | | | |
+ EMTU_R configurable or indefinite |3.3.2 | |x| | | |
+ Transport layer able to learn MMS_R |3.3.2 |x| | | | |
+ Send ICMP Time Exceeded on reassembly timeout |3.3.2 |x| | | | |
+ Fixed reassembly timeout value |3.3.2 | |x| | | |
+ | | | | | | |
+ Pass MMS_S to higher layers |3.3.3 |x| | | | |
+ Local fragmentation of outgoing packets |3.3.3 | | |x| | |
+ Else don't send bigger than MMS_S |3.3.3 |x| | | | |
+ Send max 576 to off-net destination |3.3.3 | |x| | | |
+ All-Subnets-MTU configuration flag |3.3.3 | | |x| | |
+ | | | | | | |
+MULTIHOMING: | | | | | | |
+ Reply with same addr as spec-dest addr |3.3.4.2 | |x| | | |
+ Allow application to choose local IP addr |3.3.4.2 |x| | | | |
+ Silently discard d'gram in "wrong" interface |3.3.4.2 | | |x| | |
+ Only send d'gram through "right" interface |3.3.4.2 | | |x| | |4
+ | | | | | | |
+SOURCE-ROUTE FORWARDING: | | | | | | |
+ Forward datagram with Source Route option |3.3.5 | | |x| | |1
+ Obey corresponding gateway rules |3.3.5 |x| | | | |1
+ Update TTL by gateway rules |3.3.5 |x| | | | |1
+ Able to generate ICMP err code 4, 5 |3.3.5 |x| | | | |1
+ IP src addr not local host |3.3.5 | | |x| | |1
+ Update Timestamp, Record Route options |3.3.5 |x| | | | |1
+ Configurable switch for non-local SRing |3.3.5 |x| | | | |1
+ Defaults to OFF |3.3.5 |x| | | | |1
+ Satisfy gwy access rules for non-local SRing |3.3.5 |x| | | | |1
+ If not forward, send Dest Unreach (cd 5) |3.3.5 | |x| | | |2
+ | | | | | | |
+BROADCAST: | | | | | | |
+ Broadcast addr as IP source addr |3.2.1.3 | | | | |x|
+ Receive 0 or -1 broadcast formats OK |3.3.6 | |x| | | |
+ Config'ble option to send 0 or -1 b'cast |3.3.6 | | |x| | |
+ Default to -1 broadcast |3.3.6 | |x| | | |
+ Recognize all broadcast address formats |3.3.6 |x| | | | |
+ Use IP b'cast/m'cast addr in link-layer b'cast |3.3.6 |x| | | | |
+ Silently discard link-layer-only b'cast dg's |3.3.6 | |x| | | |
+ Use Limited Broadcast addr for connected net |3.3.6 | |x| | | |
+
+
+
+Internet Engineering Task Force [Page 75]
+
+
+
+
+RFC1122 INTERNET LAYER October 1989
+
+
+ | | | | | | |
+MULTICAST: | | | | | | |
+ Support local IP multicasting (RFC-1112) |3.3.7 | |x| | | |
+ Support IGMP (RFC-1112) |3.3.7 | | |x| | |
+ Join all-hosts group at startup |3.3.7 | |x| | | |
+ Higher layers learn i'face m'cast capability |3.3.7 | |x| | | |
+ | | | | | | |
+INTERFACE: | | | | | | |
+ Allow transport layer to use all IP mechanisms |3.4 |x| | | | |
+ Pass interface ident up to transport layer |3.4 |x| | | | |
+ Pass all IP options up to transport layer |3.4 |x| | | | |
+ Transport layer can send certain ICMP messages |3.4 |x| | | | |
+ Pass spec'd ICMP messages up to transp. layer |3.4 |x| | | | |
+ Include IP hdr+8 octets or more from orig. |3.4 |x| | | | |
+ Able to leap tall buildings at a single bound |3.5 | |x| | | |
+
+Footnotes:
+
+(1) Only if feature is implemented.
+
+(2) This requirement is overruled if datagram is an ICMP error message.
+
+(3) Only if feature is implemented and is configured "on".
+
+(4) Unless has embedded gateway functionality or is source routed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 76]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- UDP October 1989
+
+
+4. TRANSPORT PROTOCOLS
+
+ 4.1 USER DATAGRAM PROTOCOL -- UDP
+
+ 4.1.1 INTRODUCTION
+
+ The User Datagram Protocol UDP [UDP:1] offers only a minimal
+ transport service -- non-guaranteed datagram delivery -- and
+ gives applications direct access to the datagram service of the
+ IP layer. UDP is used by applications that do not require the
+ level of service of TCP or that wish to use communications
+ services (e.g., multicast or broadcast delivery) not available
+ from TCP.
+
+ UDP is almost a null protocol; the only services it provides
+ over IP are checksumming of data and multiplexing by port
+ number. Therefore, an application program running over UDP
+ must deal directly with end-to-end communication problems that
+ a connection-oriented protocol would have handled -- e.g.,
+ retransmission for reliable delivery, packetization and
+ reassembly, flow control, congestion avoidance, etc., when
+ these are required. The fairly complex coupling between IP and
+ TCP will be mirrored in the coupling between UDP and many
+ applications using UDP.
+
+ 4.1.2 PROTOCOL WALK-THROUGH
+
+ There are no known errors in the specification of UDP.
+
+ 4.1.3 SPECIFIC ISSUES
+
+ 4.1.3.1 Ports
+
+ UDP well-known ports follow the same rules as TCP well-known
+ ports; see Section 4.2.2.1 below.
+
+ If a datagram arrives addressed to a UDP port for which
+ there is no pending LISTEN call, UDP SHOULD send an ICMP
+ Port Unreachable message.
+
+ 4.1.3.2 IP Options
+
+ UDP MUST pass any IP option that it receives from the IP
+ layer transparently to the application layer.
+
+ An application MUST be able to specify IP options to be sent
+ in its UDP datagrams, and UDP MUST pass these options to the
+ IP layer.
+
+
+
+Internet Engineering Task Force [Page 77]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- UDP October 1989
+
+
+ DISCUSSION:
+ At present, the only options that need be passed
+ through UDP are Source Route, Record Route, and Time
+ Stamp. However, new options may be defined in the
+ future, and UDP need not and should not make any
+ assumptions about the format or content of options it
+ passes to or from the application; an exception to this
+ might be an IP-layer security option.
+
+ An application based on UDP will need to obtain a
+ source route from a request datagram and supply a
+ reversed route for sending the corresponding reply.
+
+ 4.1.3.3 ICMP Messages
+
+ UDP MUST pass to the application layer all ICMP error
+ messages that it receives from the IP layer. Conceptually
+ at least, this may be accomplished with an upcall to the
+ ERROR_REPORT routine (see Section 4.2.4.1).
+
+ DISCUSSION:
+ Note that ICMP error messages resulting from sending a
+ UDP datagram are received asynchronously. A UDP-based
+ application that wants to receive ICMP error messages
+ is responsible for maintaining the state necessary to
+ demultiplex these messages when they arrive; for
+ example, the application may keep a pending receive
+ operation for this purpose. The application is also
+ responsible to avoid confusion from a delayed ICMP
+ error message resulting from an earlier use of the same
+ port(s).
+
+ 4.1.3.4 UDP Checksums
+
+ A host MUST implement the facility to generate and validate
+ UDP checksums. An application MAY optionally be able to
+ control whether a UDP checksum will be generated, but it
+ MUST default to checksumming on.
+
+ If a UDP datagram is received with a checksum that is non-
+ zero and invalid, UDP MUST silently discard the datagram.
+ An application MAY optionally be able to control whether UDP
+ datagrams without checksums should be discarded or passed to
+ the application.
+
+ DISCUSSION:
+ Some applications that normally run only across local
+ area networks have chosen to turn off UDP checksums for
+
+
+
+Internet Engineering Task Force [Page 78]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- UDP October 1989
+
+
+ efficiency. As a result, numerous cases of undetected
+ errors have been reported. The advisability of ever
+ turning off UDP checksumming is very controversial.
+
+ IMPLEMENTATION:
+ There is a common implementation error in UDP
+ checksums. Unlike the TCP checksum, the UDP checksum
+ is optional; the value zero is transmitted in the
+ checksum field of a UDP header to indicate the absence
+ of a checksum. If the transmitter really calculates a
+ UDP checksum of zero, it must transmit the checksum as
+ all 1's (65535). No special action is required at the
+ receiver, since zero and 65535 are equivalent in 1's
+ complement arithmetic.
+
+ 4.1.3.5 UDP Multihoming
+
+ When a UDP datagram is received, its specific-destination
+ address MUST be passed up to the application layer.
+
+ An application program MUST be able to specify the IP source
+ address to be used for sending a UDP datagram or to leave it
+ unspecified (in which case the networking software will
+ choose an appropriate source address). There SHOULD be a
+ way to communicate the chosen source address up to the
+ application layer (e.g, so that the application can later
+ receive a reply datagram only from the corresponding
+ interface).
+
+ DISCUSSION:
+ A request/response application that uses UDP should use
+ a source address for the response that is the same as
+ the specific destination address of the request. See
+ the "General Issues" section of [INTRO:1].
+
+ 4.1.3.6 Invalid Addresses
+
+ A UDP datagram received with an invalid IP source address
+ (e.g., a broadcast or multicast address) must be discarded
+ by UDP or by the IP layer (see Section 3.2.1.3).
+
+ When a host sends a UDP datagram, the source address MUST be
+ (one of) the IP address(es) of the host.
+
+ 4.1.4 UDP/APPLICATION LAYER INTERFACE
+
+ The application interface to UDP MUST provide the full services
+ of the IP/transport interface described in Section 3.4 of this
+
+
+
+Internet Engineering Task Force [Page 79]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- UDP October 1989
+
+
+ document. Thus, an application using UDP needs the functions
+ of the GET_SRCADDR(), GET_MAXSIZES(), ADVISE_DELIVPROB(), and
+ RECV_ICMP() calls described in Section 3.4. For example,
+ GET_MAXSIZES() can be used to learn the effective maximum UDP
+ maximum datagram size for a particular {interface,remote
+ host,TOS} triplet.
+
+ An application-layer program MUST be able to set the TTL and
+ TOS values as well as IP options for sending a UDP datagram,
+ and these values must be passed transparently to the IP layer.
+ UDP MAY pass the received TOS up to the application layer.
+
+ 4.1.5 UDP REQUIREMENTS SUMMARY
+
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION | | | |T|T|e
+-------------------------------------------------|--------|-|-|-|-|-|--
+ | | | | | | |
+ UDP | | | | | | |
+-------------------------------------------------|--------|-|-|-|-|-|--
+ | | | | | | |
+UDP send Port Unreachable |4.1.3.1 | |x| | | |
+ | | | | | | |
+IP Options in UDP | | | | | | |
+ - Pass rcv'd IP options to applic layer |4.1.3.2 |x| | | | |
+ - Applic layer can specify IP options in Send |4.1.3.2 |x| | | | |
+ - UDP passes IP options down to IP layer |4.1.3.2 |x| | | | |
+ | | | | | | |
+Pass ICMP msgs up to applic layer |4.1.3.3 |x| | | | |
+ | | | | | | |
+UDP checksums: | | | | | | |
+ - Able to generate/check checksum |4.1.3.4 |x| | | | |
+ - Silently discard bad checksum |4.1.3.4 |x| | | | |
+ - Sender Option to not generate checksum |4.1.3.4 | | |x| | |
+ - Default is to checksum |4.1.3.4 |x| | | | |
+ - Receiver Option to require checksum |4.1.3.4 | | |x| | |
+ | | | | | | |
+UDP Multihoming | | | | | | |
+ - Pass spec-dest addr to application |4.1.3.5 |x| | | | |
+
+
+
+Internet Engineering Task Force [Page 80]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- UDP October 1989
+
+
+ - Applic layer can specify Local IP addr |4.1.3.5 |x| | | | |
+ - Applic layer specify wild Local IP addr |4.1.3.5 |x| | | | |
+ - Applic layer notified of Local IP addr used |4.1.3.5 | |x| | | |
+ | | | | | | |
+Bad IP src addr silently discarded by UDP/IP |4.1.3.6 |x| | | | |
+Only send valid IP source address |4.1.3.6 |x| | | | |
+UDP Application Interface Services | | | | | | |
+Full IP interface of 3.4 for application |4.1.4 |x| | | | |
+ - Able to spec TTL, TOS, IP opts when send dg |4.1.4 |x| | | | |
+ - Pass received TOS up to applic layer |4.1.4 | | |x| | |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 81]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ 4.2 TRANSMISSION CONTROL PROTOCOL -- TCP
+
+ 4.2.1 INTRODUCTION
+
+ The Transmission Control Protocol TCP [TCP:1] is the primary
+ virtual-circuit transport protocol for the Internet suite. TCP
+ provides reliable, in-sequence delivery of a full-duplex stream
+ of octets (8-bit bytes). TCP is used by those applications
+ needing reliable, connection-oriented transport service, e.g.,
+ mail (SMTP), file transfer (FTP), and virtual terminal service
+ (Telnet); requirements for these application-layer protocols
+ are described in [INTRO:1].
+
+ 4.2.2 PROTOCOL WALK-THROUGH
+
+ 4.2.2.1 Well-Known Ports: RFC-793 Section 2.7
+
+ DISCUSSION:
+ TCP reserves port numbers in the range 0-255 for
+ "well-known" ports, used to access services that are
+ standardized across the Internet. The remainder of the
+ port space can be freely allocated to application
+ processes. Current well-known port definitions are
+ listed in the RFC entitled "Assigned Numbers"
+ [INTRO:6]. A prerequisite for defining a new well-
+ known port is an RFC documenting the proposed service
+ in enough detail to allow new implementations.
+
+ Some systems extend this notion by adding a third
+ subdivision of the TCP port space: reserved ports,
+ which are generally used for operating-system-specific
+ services. For example, reserved ports might fall
+ between 256 and some system-dependent upper limit.
+ Some systems further choose to protect well-known and
+ reserved ports by permitting only privileged users to
+ open TCP connections with those port values. This is
+ perfectly reasonable as long as the host does not
+ assume that all hosts protect their low-numbered ports
+ in this manner.
+
+ 4.2.2.2 Use of Push: RFC-793 Section 2.8
+
+ When an application issues a series of SEND calls without
+ setting the PUSH flag, the TCP MAY aggregate the data
+ internally without sending it. Similarly, when a series of
+ segments is received without the PSH bit, a TCP MAY queue
+ the data internally without passing it to the receiving
+ application.
+
+
+
+Internet Engineering Task Force [Page 82]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ The PSH bit is not a record marker and is independent of
+ segment boundaries. The transmitter SHOULD collapse
+ successive PSH bits when it packetizes data, to send the
+ largest possible segment.
+
+ A TCP MAY implement PUSH flags on SEND calls. If PUSH flags
+ are not implemented, then the sending TCP: (1) must not
+ buffer data indefinitely, and (2) MUST set the PSH bit in
+ the last buffered segment (i.e., when there is no more
+ queued data to be sent).
+
+ The discussion in RFC-793 on pages 48, 50, and 74
+ erroneously implies that a received PSH flag must be passed
+ to the application layer. Passing a received PSH flag to
+ the application layer is now OPTIONAL.
+
+ An application program is logically required to set the PUSH
+ flag in a SEND call whenever it needs to force delivery of
+ the data to avoid a communication deadlock. However, a TCP
+ SHOULD send a maximum-sized segment whenever possible, to
+ improve performance (see Section 4.2.3.4).
+
+ DISCUSSION:
+ When the PUSH flag is not implemented on SEND calls,
+ i.e., when the application/TCP interface uses a pure
+ streaming model, responsibility for aggregating any
+ tiny data fragments to form reasonable sized segments
+ is partially borne by the application layer.
+
+ Generally, an interactive application protocol must set
+ the PUSH flag at least in the last SEND call in each
+ command or response sequence. A bulk transfer protocol
+ like FTP should set the PUSH flag on the last segment
+ of a file or when necessary to prevent buffer deadlock.
+
+ At the receiver, the PSH bit forces buffered data to be
+ delivered to the application (even if less than a full
+ buffer has been received). Conversely, the lack of a
+ PSH bit can be used to avoid unnecessary wakeup calls
+ to the application process; this can be an important
+ performance optimization for large timesharing hosts.
+ Passing the PSH bit to the receiving application allows
+ an analogous optimization within the application.
+
+ 4.2.2.3 Window Size: RFC-793 Section 3.1
+
+ The window size MUST be treated as an unsigned number, or
+ else large window sizes will appear like negative windows
+
+
+
+Internet Engineering Task Force [Page 83]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ and TCP will not work. It is RECOMMENDED that
+ implementations reserve 32-bit fields for the send and
+ receive window sizes in the connection record and do all
+ window computations with 32 bits.
+
+ DISCUSSION:
+ It is known that the window field in the TCP header is
+ too small for high-speed, long-delay paths.
+ Experimental TCP options have been defined to extend
+ the window size; see for example [TCP:11]. In
+ anticipation of the adoption of such an extension, TCP
+ implementors should treat windows as 32 bits.
+
+ 4.2.2.4 Urgent Pointer: RFC-793 Section 3.1
+
+ The second sentence is in error: the urgent pointer points
+ to the sequence number of the LAST octet (not LAST+1) in a
+ sequence of urgent data. The description on page 56 (last
+ sentence) is correct.
+
+ A TCP MUST support a sequence of urgent data of any length.
+
+ A TCP MUST inform the application layer asynchronously
+ whenever it receives an Urgent pointer and there was
+ previously no pending urgent data, or whenever the Urgent
+ pointer advances in the data stream. There MUST be a way
+ for the application to learn how much urgent data remains to
+ be read from the connection, or at least to determine
+ whether or not more urgent data remains to be read.
+
+ DISCUSSION:
+ Although the Urgent mechanism may be used for any
+ application, it is normally used to send "interrupt"-
+ type commands to a Telnet program (see "Using Telnet
+ Synch Sequence" section in [INTRO:1]).
+
+ The asynchronous or "out-of-band" notification will
+ allow the application to go into "urgent mode", reading
+ data from the TCP connection. This allows control
+ commands to be sent to an application whose normal
+ input buffers are full of unprocessed data.
+
+ IMPLEMENTATION:
+ The generic ERROR-REPORT() upcall described in Section
+ 4.2.4.1 is a possible mechanism for informing the
+ application of the arrival of urgent data.
+
+
+
+
+
+Internet Engineering Task Force [Page 84]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ 4.2.2.5 TCP Options: RFC-793 Section 3.1
+
+ A TCP MUST be able to receive a TCP option in any segment.
+ A TCP MUST ignore without error any TCP option it does not
+ implement, assuming that the option has a length field (all
+ TCP options defined in the future will have length fields).
+ TCP MUST be prepared to handle an illegal option length
+ (e.g., zero) without crashing; a suggested procedure is to
+ reset the connection and log the reason.
+
+ 4.2.2.6 Maximum Segment Size Option: RFC-793 Section 3.1
+
+ TCP MUST implement both sending and receiving the Maximum
+ Segment Size option [TCP:4].
+
+ TCP SHOULD send an MSS (Maximum Segment Size) option in
+ every SYN segment when its receive MSS differs from the
+ default 536, and MAY send it always.
+
+ If an MSS option is not received at connection setup, TCP
+ MUST assume a default send MSS of 536 (576-40) [TCP:4].
+
+ The maximum size of a segment that TCP really sends, the
+ "effective send MSS," MUST be the smaller of the send MSS
+ (which reflects the available reassembly buffer size at the
+ remote host) and the largest size permitted by the IP layer:
+
+ Eff.snd.MSS =
+
+ min(SendMSS+20, MMS_S) - TCPhdrsize - IPoptionsize
+
+ where:
+
+ * SendMSS is the MSS value received from the remote host,
+ or the default 536 if no MSS option is received.
+
+ * MMS_S is the maximum size for a transport-layer message
+ that TCP may send.
+
+ * TCPhdrsize is the size of the TCP header; this is
+ normally 20, but may be larger if TCP options are to be
+ sent.
+
+ * IPoptionsize is the size of any IP options that TCP
+ will pass to the IP layer with the current message.
+
+
+ The MSS value to be sent in an MSS option must be less than
+
+
+
+Internet Engineering Task Force [Page 85]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ or equal to:
+
+ MMS_R - 20
+
+ where MMS_R is the maximum size for a transport-layer
+ message that can be received (and reassembled). TCP obtains
+ MMS_R and MMS_S from the IP layer; see the generic call
+ GET_MAXSIZES in Section 3.4.
+
+ DISCUSSION:
+ The choice of TCP segment size has a strong effect on
+ performance. Larger segments increase throughput by
+ amortizing header size and per-datagram processing
+ overhead over more data bytes; however, if the packet
+ is so large that it causes IP fragmentation, efficiency
+ drops sharply if any fragments are lost [IP:9].
+
+ Some TCP implementations send an MSS option only if the
+ destination host is on a non-connected network.
+ However, in general the TCP layer may not have the
+ appropriate information to make this decision, so it is
+ preferable to leave to the IP layer the task of
+ determining a suitable MTU for the Internet path. We
+ therefore recommend that TCP always send the option (if
+ not 536) and that the IP layer determine MMS_R as
+ specified in 3.3.3 and 3.4. A proposed IP-layer
+ mechanism to measure the MTU would then modify the IP
+ layer without changing TCP.
+
+ 4.2.2.7 TCP Checksum: RFC-793 Section 3.1
+
+ Unlike the UDP checksum (see Section 4.1.3.4), the TCP
+ checksum is never optional. The sender MUST generate it and
+ the receiver MUST check it.
+
+ 4.2.2.8 TCP Connection State Diagram: RFC-793 Section 3.2,
+ page 23
+
+ There are several problems with this diagram:
+
+ (a) The arrow from SYN-SENT to SYN-RCVD should be labeled
+ with "snd SYN,ACK", to agree with the text on page 68
+ and with Figure 8.
+
+ (b) There could be an arrow from SYN-RCVD state to LISTEN
+ state, conditioned on receiving a RST after a passive
+ open (see text page 70).
+
+
+
+
+Internet Engineering Task Force [Page 86]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ (c) It is possible to go directly from FIN-WAIT-1 to the
+ TIME-WAIT state (see page 75 of the spec).
+
+
+ 4.2.2.9 Initial Sequence Number Selection: RFC-793 Section
+ 3.3, page 27
+
+ A TCP MUST use the specified clock-driven selection of
+ initial sequence numbers.
+
+ 4.2.2.10 Simultaneous Open Attempts: RFC-793 Section 3.4, page
+ 32
+
+ There is an error in Figure 8: the packet on line 7 should
+ be identical to the packet on line 5.
+
+ A TCP MUST support simultaneous open attempts.
+
+ DISCUSSION:
+ It sometimes surprises implementors that if two
+ applications attempt to simultaneously connect to each
+ other, only one connection is generated instead of two.
+ This was an intentional design decision; don't try to
+ "fix" it.
+
+ 4.2.2.11 Recovery from Old Duplicate SYN: RFC-793 Section 3.4,
+ page 33
+
+ Note that a TCP implementation MUST keep track of whether a
+ connection has reached SYN_RCVD state as the result of a
+ passive OPEN or an active OPEN.
+
+ 4.2.2.12 RST Segment: RFC-793 Section 3.4
+
+ A TCP SHOULD allow a received RST segment to include data.
+
+ DISCUSSION
+ It has been suggested that a RST segment could contain
+ ASCII text that encoded and explained the cause of the
+ RST. No standard has yet been established for such
+ data.
+
+ 4.2.2.13 Closing a Connection: RFC-793 Section 3.5
+
+ A TCP connection may terminate in two ways: (1) the normal
+ TCP close sequence using a FIN handshake, and (2) an "abort"
+ in which one or more RST segments are sent and the
+ connection state is immediately discarded. If a TCP
+
+
+
+Internet Engineering Task Force [Page 87]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ connection is closed by the remote site, the local
+ application MUST be informed whether it closed normally or
+ was aborted.
+
+ The normal TCP close sequence delivers buffered data
+ reliably in both directions. Since the two directions of a
+ TCP connection are closed independently, it is possible for
+ a connection to be "half closed," i.e., closed in only one
+ direction, and a host is permitted to continue sending data
+ in the open direction on a half-closed connection.
+
+ A host MAY implement a "half-duplex" TCP close sequence, so
+ that an application that has called CLOSE cannot continue to
+ read data from the connection. If such a host issues a
+ CLOSE call while received data is still pending in TCP, or
+ if new data is received after CLOSE is called, its TCP
+ SHOULD send a RST to show that data was lost.
+
+ When a connection is closed actively, it MUST linger in
+ TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
+ However, it MAY accept a new SYN from the remote TCP to
+ reopen the connection directly from TIME-WAIT state, if it:
+
+ (1) assigns its initial sequence number for the new
+ connection to be larger than the largest sequence
+ number it used on the previous connection incarnation,
+ and
+
+ (2) returns to TIME-WAIT state if the SYN turns out to be
+ an old duplicate.
+
+
+ DISCUSSION:
+ TCP's full-duplex data-preserving close is a feature
+ that is not included in the analogous ISO transport
+ protocol TP4.
+
+ Some systems have not implemented half-closed
+ connections, presumably because they do not fit into
+ the I/O model of their particular operating system. On
+ these systems, once an application has called CLOSE, it
+ can no longer read input data from the connection; this
+ is referred to as a "half-duplex" TCP close sequence.
+
+ The graceful close algorithm of TCP requires that the
+ connection state remain defined on (at least) one end
+ of the connection, for a timeout period of 2xMSL, i.e.,
+ 4 minutes. During this period, the (remote socket,
+
+
+
+Internet Engineering Task Force [Page 88]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ local socket) pair that defines the connection is busy
+ and cannot be reused. To shorten the time that a given
+ port pair is tied up, some TCPs allow a new SYN to be
+ accepted in TIME-WAIT state.
+
+ 4.2.2.14 Data Communication: RFC-793 Section 3.7, page 40
+
+ Since RFC-793 was written, there has been extensive work on
+ TCP algorithms to achieve efficient data communication.
+ Later sections of the present document describe required and
+ recommended TCP algorithms to determine when to send data
+ (Section 4.2.3.4), when to send an acknowledgment (Section
+ 4.2.3.2), and when to update the window (Section 4.2.3.3).
+
+ DISCUSSION:
+ One important performance issue is "Silly Window
+ Syndrome" or "SWS" [TCP:5], a stable pattern of small
+ incremental window movements resulting in extremely
+ poor TCP performance. Algorithms to avoid SWS are
+ described below for both the sending side (Section
+ 4.2.3.4) and the receiving side (Section 4.2.3.3).
+
+ In brief, SWS is caused by the receiver advancing the
+ right window edge whenever it has any new buffer space
+ available to receive data and by the sender using any
+ incremental window, no matter how small, to send more
+ data [TCP:5]. The result can be a stable pattern of
+ sending tiny data segments, even though both sender and
+ receiver have a large total buffer space for the
+ connection. SWS can only occur during the transmission
+ of a large amount of data; if the connection goes
+ quiescent, the problem will disappear. It is caused by
+ typical straightforward implementation of window
+ management, but the sender and receiver algorithms
+ given below will avoid it.
+
+ Another important TCP performance issue is that some
+ applications, especially remote login to character-at-
+ a-time hosts, tend to send streams of one-octet data
+ segments. To avoid deadlocks, every TCP SEND call from
+ such applications must be "pushed", either explicitly
+ by the application or else implicitly by TCP. The
+ result may be a stream of TCP segments that contain one
+ data octet each, which makes very inefficient use of
+ the Internet and contributes to Internet congestion.
+ The Nagle Algorithm described in Section 4.2.3.4
+ provides a simple and effective solution to this
+ problem. It does have the effect of clumping
+
+
+
+Internet Engineering Task Force [Page 89]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ characters over Telnet connections; this may initially
+ surprise users accustomed to single-character echo, but
+ user acceptance has not been a problem.
+
+ Note that the Nagle algorithm and the send SWS
+ avoidance algorithm play complementary roles in
+ improving performance. The Nagle algorithm discourages
+ sending tiny segments when the data to be sent
+ increases in small increments, while the SWS avoidance
+ algorithm discourages small segments resulting from the
+ right window edge advancing in small increments.
+
+ A careless implementation can send two or more
+ acknowledgment segments per data segment received. For
+ example, suppose the receiver acknowledges every data
+ segment immediately. When the application program
+ subsequently consumes the data and increases the
+ available receive buffer space again, the receiver may
+ send a second acknowledgment segment to update the
+ window at the sender. The extreme case occurs with
+ single-character segments on TCP connections using the
+ Telnet protocol for remote login service. Some
+ implementations have been observed in which each
+ incoming 1-character segment generates three return
+ segments: (1) the acknowledgment, (2) a one byte
+ increase in the window, and (3) the echoed character,
+ respectively.
+
+ 4.2.2.15 Retransmission Timeout: RFC-793 Section 3.7, page 41
+
+ The algorithm suggested in RFC-793 for calculating the
+ retransmission timeout is now known to be inadequate; see
+ Section 4.2.3.1 below.
+
+ Recent work by Jacobson [TCP:7] on Internet congestion and
+ TCP retransmission stability has produced a transmission
+ algorithm combining "slow start" with "congestion
+ avoidance". A TCP MUST implement this algorithm.
+
+ If a retransmitted packet is identical to the original
+ packet (which implies not only that the data boundaries have
+ not changed, but also that the window and acknowledgment
+ fields of the header have not changed), then the same IP
+ Identification field MAY be used (see Section 3.2.1.5).
+
+ IMPLEMENTATION:
+ Some TCP implementors have chosen to "packetize" the
+ data stream, i.e., to pick segment boundaries when
+
+
+
+Internet Engineering Task Force [Page 90]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ segments are originally sent and to queue these
+ segments in a "retransmission queue" until they are
+ acknowledged. Another design (which may be simpler) is
+ to defer packetizing until each time data is
+ transmitted or retransmitted, so there will be no
+ segment retransmission queue.
+
+ In an implementation with a segment retransmission
+ queue, TCP performance may be enhanced by repacketizing
+ the segments awaiting acknowledgment when the first
+ retransmission timeout occurs. That is, the
+ outstanding segments that fitted would be combined into
+ one maximum-sized segment, with a new IP Identification
+ value. The TCP would then retain this combined segment
+ in the retransmit queue until it was acknowledged.
+ However, if the first two segments in the
+ retransmission queue totalled more than one maximum-
+ sized segment, the TCP would retransmit only the first
+ segment using the original IP Identification field.
+
+ 4.2.2.16 Managing the Window: RFC-793 Section 3.7, page 41
+
+ A TCP receiver SHOULD NOT shrink the window, i.e., move the
+ right window edge to the left. However, a sending TCP MUST
+ be robust against window shrinking, which may cause the
+ "useable window" (see Section 4.2.3.4) to become negative.
+
+ If this happens, the sender SHOULD NOT send new data, but
+ SHOULD retransmit normally the old unacknowledged data
+ between SND.UNA and SND.UNA+SND.WND. The sender MAY also
+ retransmit old data beyond SND.UNA+SND.WND, but SHOULD NOT
+ time out the connection if data beyond the right window edge
+ is not acknowledged. If the window shrinks to zero, the TCP
+ MUST probe it in the standard way (see next Section).
+
+ DISCUSSION:
+ Many TCP implementations become confused if the window
+ shrinks from the right after data has been sent into a
+ larger window. Note that TCP has a heuristic to select
+ the latest window update despite possible datagram
+ reordering; as a result, it may ignore a window update
+ with a smaller window than previously offered if
+ neither the sequence number nor the acknowledgment
+ number is increased.
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 91]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ 4.2.2.17 Probing Zero Windows: RFC-793 Section 3.7, page 42
+
+ Probing of zero (offered) windows MUST be supported.
+
+ A TCP MAY keep its offered receive window closed
+ indefinitely. As long as the receiving TCP continues to
+ send acknowledgments in response to the probe segments, the
+ sending TCP MUST allow the connection to stay open.
+
+ DISCUSSION:
+ It is extremely important to remember that ACK
+ (acknowledgment) segments that contain no data are not
+ reliably transmitted by TCP. If zero window probing is
+ not supported, a connection may hang forever when an
+ ACK segment that re-opens the window is lost.
+
+ The delay in opening a zero window generally occurs
+ when the receiving application stops taking data from
+ its TCP. For example, consider a printer daemon
+ application, stopped because the printer ran out of
+ paper.
+
+ The transmitting host SHOULD send the first zero-window
+ probe when a zero window has existed for the retransmission
+ timeout period (see Section 4.2.2.15), and SHOULD increase
+ exponentially the interval between successive probes.
+
+ DISCUSSION:
+ This procedure minimizes delay if the zero-window
+ condition is due to a lost ACK segment containing a
+ window-opening update. Exponential backoff is
+ recommended, possibly with some maximum interval not
+ specified here. This procedure is similar to that of
+ the retransmission algorithm, and it may be possible to
+ combine the two procedures in the implementation.
+
+ 4.2.2.18 Passive OPEN Calls: RFC-793 Section 3.8
+
+ Every passive OPEN call either creates a new connection
+ record in LISTEN state, or it returns an error; it MUST NOT
+ affect any previously created connection record.
+
+ A TCP that supports multiple concurrent users MUST provide
+ an OPEN call that will functionally allow an application to
+ LISTEN on a port while a connection block with the same
+ local port is in SYN-SENT or SYN-RECEIVED state.
+
+ DISCUSSION:
+
+
+
+Internet Engineering Task Force [Page 92]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ Some applications (e.g., SMTP servers) may need to
+ handle multiple connection attempts at about the same
+ time. The probability of a connection attempt failing
+ is reduced by giving the application some means of
+ listening for a new connection at the same time that an
+ earlier connection attempt is going through the three-
+ way handshake.
+
+ IMPLEMENTATION:
+ Acceptable implementations of concurrent opens may
+ permit multiple passive OPEN calls, or they may allow
+ "cloning" of LISTEN-state connections from a single
+ passive OPEN call.
+
+ 4.2.2.19 Time to Live: RFC-793 Section 3.9, page 52
+
+ RFC-793 specified that TCP was to request the IP layer to
+ send TCP segments with TTL = 60. This is obsolete; the TTL
+ value used to send TCP segments MUST be configurable. See
+ Section 3.2.1.7 for discussion.
+
+ 4.2.2.20 Event Processing: RFC-793 Section 3.9
+
+ While it is not strictly required, a TCP SHOULD be capable
+ of queueing out-of-order TCP segments. Change the "may" in
+ the last sentence of the first paragraph on page 70 to
+ "should".
+
+ DISCUSSION:
+ Some small-host implementations have omitted segment
+ queueing because of limited buffer space. This
+ omission may be expected to adversely affect TCP
+ throughput, since loss of a single segment causes all
+ later segments to appear to be "out of sequence".
+
+ In general, the processing of received segments MUST be
+ implemented to aggregate ACK segments whenever possible.
+ For example, if the TCP is processing a series of queued
+ segments, it MUST process them all before sending any ACK
+ segments.
+
+ Here are some detailed error corrections and notes on the
+ Event Processing section of RFC-793.
+
+ (a) CLOSE Call, CLOSE-WAIT state, p. 61: enter LAST-ACK
+ state, not CLOSING.
+
+ (b) LISTEN state, check for SYN (pp. 65, 66): With a SYN
+
+
+
+Internet Engineering Task Force [Page 93]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ bit, if the security/compartment or the precedence is
+ wrong for the segment, a reset is sent. The wrong form
+ of reset is shown in the text; it should be:
+
+ <SEQ=0><ACK=SEG.SEQ+SEG.LEN><CTL=RST,ACK>
+
+
+ (c) SYN-SENT state, Check for SYN, p. 68: When the
+ connection enters ESTABLISHED state, the following
+ variables must be set:
+ SND.WND <- SEG.WND
+ SND.WL1 <- SEG.SEQ
+ SND.WL2 <- SEG.ACK
+
+
+ (d) Check security and precedence, p. 71: The first heading
+ "ESTABLISHED STATE" should really be a list of all
+ states other than SYN-RECEIVED: ESTABLISHED, FIN-WAIT-
+ 1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, and
+ TIME-WAIT.
+
+ (e) Check SYN bit, p. 71: "In SYN-RECEIVED state and if
+ the connection was initiated with a passive OPEN, then
+ return this connection to the LISTEN state and return.
+ Otherwise...".
+
+ (f) Check ACK field, SYN-RECEIVED state, p. 72: When the
+ connection enters ESTABLISHED state, the variables
+ listed in (c) must be set.
+
+ (g) Check ACK field, ESTABLISHED state, p. 72: The ACK is a
+ duplicate if SEG.ACK =< SND.UNA (the = was omitted).
+ Similarly, the window should be updated if: SND.UNA =<
+ SEG.ACK =< SND.NXT.
+
+ (h) USER TIMEOUT, p. 77:
+
+ It would be better to notify the application of the
+ timeout rather than letting TCP force the connection
+ closed. However, see also Section 4.2.3.5.
+
+
+ 4.2.2.21 Acknowledging Queued Segments: RFC-793 Section 3.9
+
+ A TCP MAY send an ACK segment acknowledging RCV.NXT when a
+ valid segment arrives that is in the window but not at the
+ left window edge.
+
+
+
+
+Internet Engineering Task Force [Page 94]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ DISCUSSION:
+ RFC-793 (see page 74) was ambiguous about whether or
+ not an ACK segment should be sent when an out-of-order
+ segment was received, i.e., when SEG.SEQ was unequal to
+ RCV.NXT.
+
+ One reason for ACKing out-of-order segments might be to
+ support an experimental algorithm known as "fast
+ retransmit". With this algorithm, the sender uses the
+ "redundant" ACK's to deduce that a segment has been
+ lost before the retransmission timer has expired. It
+ counts the number of times an ACK has been received
+ with the same value of SEG.ACK and with the same right
+ window edge. If more than a threshold number of such
+ ACK's is received, then the segment containing the
+ octets starting at SEG.ACK is assumed to have been lost
+ and is retransmitted, without awaiting a timeout. The
+ threshold is chosen to compensate for the maximum
+ likely segment reordering in the Internet. There is
+ not yet enough experience with the fast retransmit
+ algorithm to determine how useful it is.
+
+ 4.2.3 SPECIFIC ISSUES
+
+ 4.2.3.1 Retransmission Timeout Calculation
+
+ A host TCP MUST implement Karn's algorithm and Jacobson's
+ algorithm for computing the retransmission timeout ("RTO").
+
+ o Jacobson's algorithm for computing the smoothed round-
+ trip ("RTT") time incorporates a simple measure of the
+ variance [TCP:7].
+
+ o Karn's algorithm for selecting RTT measurements ensures
+ that ambiguous round-trip times will not corrupt the
+ calculation of the smoothed round-trip time [TCP:6].
+
+ This implementation also MUST include "exponential backoff"
+ for successive RTO values for the same segment.
+ Retransmission of SYN segments SHOULD use the same algorithm
+ as data segments.
+
+ DISCUSSION:
+ There were two known problems with the RTO calculations
+ specified in RFC-793. First, the accurate measurement
+ of RTTs is difficult when there are retransmissions.
+ Second, the algorithm to compute the smoothed round-
+ trip time is inadequate [TCP:7], because it incorrectly
+
+
+
+Internet Engineering Task Force [Page 95]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ assumed that the variance in RTT values would be small
+ and constant. These problems were solved by Karn's and
+ Jacobson's algorithm, respectively.
+
+ The performance increase resulting from the use of
+ these improvements varies from noticeable to dramatic.
+ Jacobson's algorithm for incorporating the measured RTT
+ variance is especially important on a low-speed link,
+ where the natural variation of packet sizes causes a
+ large variation in RTT. One vendor found link
+ utilization on a 9.6kb line went from 10% to 90% as a
+ result of implementing Jacobson's variance algorithm in
+ TCP.
+
+ The following values SHOULD be used to initialize the
+ estimation parameters for a new connection:
+
+ (a) RTT = 0 seconds.
+
+ (b) RTO = 3 seconds. (The smoothed variance is to be
+ initialized to the value that will result in this RTO).
+
+ The recommended upper and lower bounds on the RTO are known
+ to be inadequate on large internets. The lower bound SHOULD
+ be measured in fractions of a second (to accommodate high
+ speed LANs) and the upper bound should be 2*MSL, i.e., 240
+ seconds.
+
+ DISCUSSION:
+ Experience has shown that these initialization values
+ are reasonable, and that in any case the Karn and
+ Jacobson algorithms make TCP behavior reasonably
+ insensitive to the initial parameter choices.
+
+ 4.2.3.2 When to Send an ACK Segment
+
+ A host that is receiving a stream of TCP data segments can
+ increase efficiency in both the Internet and the hosts by
+ sending fewer than one ACK (acknowledgment) segment per data
+ segment received; this is known as a "delayed ACK" [TCP:5].
+
+ A TCP SHOULD implement a delayed ACK, but an ACK should not
+ be excessively delayed; in particular, the delay MUST be
+ less than 0.5 seconds, and in a stream of full-sized
+ segments there SHOULD be an ACK for at least every second
+ segment.
+
+ DISCUSSION:
+
+
+
+Internet Engineering Task Force [Page 96]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ A delayed ACK gives the application an opportunity to
+ update the window and perhaps to send an immediate
+ response. In particular, in the case of character-mode
+ remote login, a delayed ACK can reduce the number of
+ segments sent by the server by a factor of 3 (ACK,
+ window update, and echo character all combined in one
+ segment).
+
+ In addition, on some large multi-user hosts, a delayed
+ ACK can substantially reduce protocol processing
+ overhead by reducing the total number of packets to be
+ processed [TCP:5]. However, excessive delays on ACK's
+ can disturb the round-trip timing and packet "clocking"
+ algorithms [TCP:7].
+
+ 4.2.3.3 When to Send a Window Update
+
+ A TCP MUST include a SWS avoidance algorithm in the receiver
+ [TCP:5].
+
+ IMPLEMENTATION:
+ The receiver's SWS avoidance algorithm determines when
+ the right window edge may be advanced; this is
+ customarily known as "updating the window". This
+ algorithm combines with the delayed ACK algorithm (see
+ Section 4.2.3.2) to determine when an ACK segment
+ containing the current window will really be sent to
+ the receiver. We use the notation of RFC-793; see
+ Figures 4 and 5 in that document.
+
+ The solution to receiver SWS is to avoid advancing the
+ right window edge RCV.NXT+RCV.WND in small increments,
+ even if data is received from the network in small
+ segments.
+
+ Suppose the total receive buffer space is RCV.BUFF. At
+ any given moment, RCV.USER octets of this total may be
+ tied up with data that has been received and
+ acknowledged but which the user process has not yet
+ consumed. When the connection is quiescent, RCV.WND =
+ RCV.BUFF and RCV.USER = 0.
+
+ Keeping the right window edge fixed as data arrives and
+ is acknowledged requires that the receiver offer less
+ than its full buffer space, i.e., the receiver must
+ specify a RCV.WND that keeps RCV.NXT+RCV.WND constant
+ as RCV.NXT increases. Thus, the total buffer space
+ RCV.BUFF is generally divided into three parts:
+
+
+
+Internet Engineering Task Force [Page 97]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+
+ |<------- RCV.BUFF ---------------->|
+ 1 2 3
+ ----|---------|------------------|------|----
+ RCV.NXT ^
+ (Fixed)
+
+ 1 - RCV.USER = data received but not yet consumed;
+ 2 - RCV.WND = space advertised to sender;
+ 3 - Reduction = space available but not yet
+ advertised.
+
+
+ The suggested SWS avoidance algorithm for the receiver
+ is to keep RCV.NXT+RCV.WND fixed until the reduction
+ satisfies:
+
+ RCV.BUFF - RCV.USER - RCV.WND >=
+
+ min( Fr * RCV.BUFF, Eff.snd.MSS )
+
+ where Fr is a fraction whose recommended value is 1/2,
+ and Eff.snd.MSS is the effective send MSS for the
+ connection (see Section 4.2.2.6). When the inequality
+ is satisfied, RCV.WND is set to RCV.BUFF-RCV.USER.
+
+ Note that the general effect of this algorithm is to
+ advance RCV.WND in increments of Eff.snd.MSS (for
+ realistic receive buffers: Eff.snd.MSS < RCV.BUFF/2).
+ Note also that the receiver must use its own
+ Eff.snd.MSS, assuming it is the same as the sender's.
+
+ 4.2.3.4 When to Send Data
+
+ A TCP MUST include a SWS avoidance algorithm in the sender.
+
+ A TCP SHOULD implement the Nagle Algorithm [TCP:9] to
+ coalesce short segments. However, there MUST be a way for
+ an application to disable the Nagle algorithm on an
+ individual connection. In all cases, sending data is also
+ subject to the limitation imposed by the Slow Start
+ algorithm (Section 4.2.2.15).
+
+ DISCUSSION:
+ The Nagle algorithm is generally as follows:
+
+ If there is unacknowledged data (i.e., SND.NXT >
+ SND.UNA), then the sending TCP buffers all user
+
+
+
+Internet Engineering Task Force [Page 98]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ data (regardless of the PSH bit), until the
+ outstanding data has been acknowledged or until
+ the TCP can send a full-sized segment (Eff.snd.MSS
+ bytes; see Section 4.2.2.6).
+
+ Some applications (e.g., real-time display window
+ updates) require that the Nagle algorithm be turned
+ off, so small data segments can be streamed out at the
+ maximum rate.
+
+ IMPLEMENTATION:
+ The sender's SWS avoidance algorithm is more difficult
+ than the receivers's, because the sender does not know
+ (directly) the receiver's total buffer space RCV.BUFF.
+ An approach which has been found to work well is for
+ the sender to calculate Max(SND.WND), the maximum send
+ window it has seen so far on the connection, and to use
+ this value as an estimate of RCV.BUFF. Unfortunately,
+ this can only be an estimate; the receiver may at any
+ time reduce the size of RCV.BUFF. To avoid a resulting
+ deadlock, it is necessary to have a timeout to force
+ transmission of data, overriding the SWS avoidance
+ algorithm. In practice, this timeout should seldom
+ occur.
+
+ The "useable window" [TCP:5] is:
+
+ U = SND.UNA + SND.WND - SND.NXT
+
+ i.e., the offered window less the amount of data sent
+ but not acknowledged. If D is the amount of data
+ queued in the sending TCP but not yet sent, then the
+ following set of rules is recommended.
+
+ Send data:
+
+ (1) if a maximum-sized segment can be sent, i.e, if:
+
+ min(D,U) >= Eff.snd.MSS;
+
+
+ (2) or if the data is pushed and all queued data can
+ be sent now, i.e., if:
+
+ [SND.NXT = SND.UNA and] PUSHED and D <= U
+
+ (the bracketed condition is imposed by the Nagle
+ algorithm);
+
+
+
+Internet Engineering Task Force [Page 99]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ (3) or if at least a fraction Fs of the maximum window
+ can be sent, i.e., if:
+
+ [SND.NXT = SND.UNA and]
+
+ min(D.U) >= Fs * Max(SND.WND);
+
+
+ (4) or if data is PUSHed and the override timeout
+ occurs.
+
+ Here Fs is a fraction whose recommended value is 1/2.
+ The override timeout should be in the range 0.1 - 1.0
+ seconds. It may be convenient to combine this timer
+ with the timer used to probe zero windows (Section
+ 4.2.2.17).
+
+ Finally, note that the SWS avoidance algorithm just
+ specified is to be used instead of the sender-side
+ algorithm contained in [TCP:5].
+
+ 4.2.3.5 TCP Connection Failures
+
+ Excessive retransmission of the same segment by TCP
+ indicates some failure of the remote host or the Internet
+ path. This failure may be of short or long duration. The
+ following procedure MUST be used to handle excessive
+ retransmissions of data segments [IP:11]:
+
+ (a) There are two thresholds R1 and R2 measuring the amount
+ of retransmission that has occurred for the same
+ segment. R1 and R2 might be measured in time units or
+ as a count of retransmissions.
+
+ (b) When the number of transmissions of the same segment
+ reaches or exceeds threshold R1, pass negative advice
+ (see Section 3.3.1.4) to the IP layer, to trigger
+ dead-gateway diagnosis.
+
+ (c) When the number of transmissions of the same segment
+ reaches a threshold R2 greater than R1, close the
+ connection.
+
+ (d) An application MUST be able to set the value for R2 for
+ a particular connection. For example, an interactive
+ application might set R2 to "infinity," giving the user
+ control over when to disconnect.
+
+
+
+
+Internet Engineering Task Force [Page 100]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ (d) TCP SHOULD inform the application of the delivery
+ problem (unless such information has been disabled by
+ the application; see Section 4.2.4.1), when R1 is
+ reached and before R2. This will allow a remote login
+ (User Telnet) application program to inform the user,
+ for example.
+
+ The value of R1 SHOULD correspond to at least 3
+ retransmissions, at the current RTO. The value of R2 SHOULD
+ correspond to at least 100 seconds.
+
+ An attempt to open a TCP connection could fail with
+ excessive retransmissions of the SYN segment or by receipt
+ of a RST segment or an ICMP Port Unreachable. SYN
+ retransmissions MUST be handled in the general way just
+ described for data retransmissions, including notification
+ of the application layer.
+
+ However, the values of R1 and R2 may be different for SYN
+ and data segments. In particular, R2 for a SYN segment MUST
+ be set large enough to provide retransmission of the segment
+ for at least 3 minutes. The application can close the
+ connection (i.e., give up on the open attempt) sooner, of
+ course.
+
+ DISCUSSION:
+ Some Internet paths have significant setup times, and
+ the number of such paths is likely to increase in the
+ future.
+
+ 4.2.3.6 TCP Keep-Alives
+
+ Implementors MAY include "keep-alives" in their TCP
+ implementations, although this practice is not universally
+ accepted. If keep-alives are included, the application MUST
+ be able to turn them on or off for each TCP connection, and
+ they MUST default to off.
+
+ Keep-alive packets MUST only be sent when no data or
+ acknowledgement packets have been received for the
+ connection within an interval. This interval MUST be
+ configurable and MUST default to no less than two hours.
+
+ It is extremely important to remember that ACK segments that
+ contain no data are not reliably transmitted by TCP.
+ Consequently, if a keep-alive mechanism is implemented it
+ MUST NOT interpret failure to respond to any specific probe
+ as a dead connection.
+
+
+
+Internet Engineering Task Force [Page 101]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ An implementation SHOULD send a keep-alive segment with no
+ data; however, it MAY be configurable to send a keep-alive
+ segment containing one garbage octet, for compatibility with
+ erroneous TCP implementations.
+
+ DISCUSSION:
+ A "keep-alive" mechanism periodically probes the other
+ end of a connection when the connection is otherwise
+ idle, even when there is no data to be sent. The TCP
+ specification does not include a keep-alive mechanism
+ because it could: (1) cause perfectly good connections
+ to break during transient Internet failures; (2)
+ consume unnecessary bandwidth ("if no one is using the
+ connection, who cares if it is still good?"); and (3)
+ cost money for an Internet path that charges for
+ packets.
+
+ Some TCP implementations, however, have included a
+ keep-alive mechanism. To confirm that an idle
+ connection is still active, these implementations send
+ a probe segment designed to elicit a response from the
+ peer TCP. Such a segment generally contains SEG.SEQ =
+ SND.NXT-1 and may or may not contain one garbage octet
+ of data. Note that on a quiet connection SND.NXT =
+ RCV.NXT, so that this SEG.SEQ will be outside the
+ window. Therefore, the probe causes the receiver to
+ return an acknowledgment segment, confirming that the
+ connection is still live. If the peer has dropped the
+ connection due to a network partition or a crash, it
+ will respond with a RST instead of an acknowledgment
+ segment.
+
+ Unfortunately, some misbehaved TCP implementations fail
+ to respond to a segment with SEG.SEQ = SND.NXT-1 unless
+ the segment contains data. Alternatively, an
+ implementation could determine whether a peer responded
+ correctly to keep-alive packets with no garbage data
+ octet.
+
+ A TCP keep-alive mechanism should only be invoked in
+ server applications that might otherwise hang
+ indefinitely and consume resources unnecessarily if a
+ client crashes or aborts a connection during a network
+ failure.
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 102]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ 4.2.3.7 TCP Multihoming
+
+ If an application on a multihomed host does not specify the
+ local IP address when actively opening a TCP connection,
+ then the TCP MUST ask the IP layer to select a local IP
+ address before sending the (first) SYN. See the function
+ GET_SRCADDR() in Section 3.4.
+
+ At all other times, a previous segment has either been sent
+ or received on this connection, and TCP MUST use the same
+ local address is used that was used in those previous
+ segments.
+
+ 4.2.3.8 IP Options
+
+ When received options are passed up to TCP from the IP
+ layer, TCP MUST ignore options that it does not understand.
+
+ A TCP MAY support the Time Stamp and Record Route options.
+
+ An application MUST be able to specify a source route when
+ it actively opens a TCP connection, and this MUST take
+ precedence over a source route received in a datagram.
+
+ When a TCP connection is OPENed passively and a packet
+ arrives with a completed IP Source Route option (containing
+ a return route), TCP MUST save the return route and use it
+ for all segments sent on this connection. If a different
+ source route arrives in a later segment, the later
+ definition SHOULD override the earlier one.
+
+ 4.2.3.9 ICMP Messages
+
+ TCP MUST act on an ICMP error message passed up from the IP
+ layer, directing it to the connection that created the
+ error. The necessary demultiplexing information can be
+ found in the IP header contained within the ICMP message.
+
+ o Source Quench
+
+ TCP MUST react to a Source Quench by slowing
+ transmission on the connection. The RECOMMENDED
+ procedure is for a Source Quench to trigger a "slow
+ start," as if a retransmission timeout had occurred.
+
+ o Destination Unreachable -- codes 0, 1, 5
+
+ Since these Unreachable messages indicate soft error
+
+
+
+Internet Engineering Task Force [Page 103]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ conditions, TCP MUST NOT abort the connection, and it
+ SHOULD make the information available to the
+ application.
+
+ DISCUSSION:
+ TCP could report the soft error condition directly
+ to the application layer with an upcall to the
+ ERROR_REPORT routine, or it could merely note the
+ message and report it to the application only when
+ and if the TCP connection times out.
+
+ o Destination Unreachable -- codes 2-4
+
+ These are hard error conditions, so TCP SHOULD abort
+ the connection.
+
+ o Time Exceeded -- codes 0, 1
+
+ This should be handled the same way as Destination
+ Unreachable codes 0, 1, 5 (see above).
+
+ o Parameter Problem
+
+ This should be handled the same way as Destination
+ Unreachable codes 0, 1, 5 (see above).
+
+
+ 4.2.3.10 Remote Address Validation
+
+ A TCP implementation MUST reject as an error a local OPEN
+ call for an invalid remote IP address (e.g., a broadcast or
+ multicast address).
+
+ An incoming SYN with an invalid source address must be
+ ignored either by TCP or by the IP layer (see Section
+ 3.2.1.3).
+
+ A TCP implementation MUST silently discard an incoming SYN
+ segment that is addressed to a broadcast or multicast
+ address.
+
+ 4.2.3.11 TCP Traffic Patterns
+
+ IMPLEMENTATION:
+ The TCP protocol specification [TCP:1] gives the
+ implementor much freedom in designing the algorithms
+ that control the message flow over the connection --
+ packetizing, managing the window, sending
+
+
+
+Internet Engineering Task Force [Page 104]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ acknowledgments, etc. These design decisions are
+ difficult because a TCP must adapt to a wide range of
+ traffic patterns. Experience has shown that a TCP
+ implementor needs to verify the design on two extreme
+ traffic patterns:
+
+ o Single-character Segments
+
+ Even if the sender is using the Nagle Algorithm,
+ when a TCP connection carries remote login traffic
+ across a low-delay LAN the receiver will generally
+ get a stream of single-character segments. If
+ remote terminal echo mode is in effect, the
+ receiver's system will generally echo each
+ character as it is received.
+
+ o Bulk Transfer
+
+ When TCP is used for bulk transfer, the data
+ stream should be made up (almost) entirely of
+ segments of the size of the effective MSS.
+ Although TCP uses a sequence number space with
+ byte (octet) granularity, in bulk-transfer mode
+ its operation should be as if TCP used a sequence
+ space that counted only segments.
+
+ Experience has furthermore shown that a single TCP can
+ effectively and efficiently handle these two extremes.
+
+ The most important tool for verifying a new TCP
+ implementation is a packet trace program. There is a
+ large volume of experience showing the importance of
+ tracing a variety of traffic patterns with other TCP
+ implementations and studying the results carefully.
+
+
+ 4.2.3.12 Efficiency
+
+ IMPLEMENTATION:
+ Extensive experience has led to the following
+ suggestions for efficient implementation of TCP:
+
+ (a) Don't Copy Data
+
+ In bulk data transfer, the primary CPU-intensive
+ tasks are copying data from one place to another
+ and checksumming the data. It is vital to
+ minimize the number of copies of TCP data. Since
+
+
+
+Internet Engineering Task Force [Page 105]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ the ultimate speed limitation may be fetching data
+ across the memory bus, it may be useful to combine
+ the copy with checksumming, doing both with a
+ single memory fetch.
+
+ (b) Hand-Craft the Checksum Routine
+
+ A good TCP checksumming routine is typically two
+ to five times faster than a simple and direct
+ implementation of the definition. Great care and
+ clever coding are often required and advisable to
+ make the checksumming code "blazing fast". See
+ [TCP:10].
+
+ (c) Code for the Common Case
+
+ TCP protocol processing can be complicated, but
+ for most segments there are only a few simple
+ decisions to be made. Per-segment processing will
+ be greatly speeded up by coding the main line to
+ minimize the number of decisions in the most
+ common case.
+
+
+ 4.2.4 TCP/APPLICATION LAYER INTERFACE
+
+ 4.2.4.1 Asynchronous Reports
+
+ There MUST be a mechanism for reporting soft TCP error
+ conditions to the application. Generically, we assume this
+ takes the form of an application-supplied ERROR_REPORT
+ routine that may be upcalled [INTRO:7] asynchronously from
+ the transport layer:
+
+ ERROR_REPORT(local connection name, reason, subreason)
+
+ The precise encoding of the reason and subreason parameters
+ is not specified here. However, the conditions that are
+ reported asynchronously to the application MUST include:
+
+ * ICMP error message arrived (see 4.2.3.9)
+
+ * Excessive retransmissions (see 4.2.3.5)
+
+ * Urgent pointer advance (see 4.2.2.4).
+
+ However, an application program that does not want to
+ receive such ERROR_REPORT calls SHOULD be able to
+
+
+
+Internet Engineering Task Force [Page 106]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ effectively disable these calls.
+
+ DISCUSSION:
+ These error reports generally reflect soft errors that
+ can be ignored without harm by many applications. It
+ has been suggested that these error report calls should
+ default to "disabled," but this is not required.
+
+ 4.2.4.2 Type-of-Service
+
+ The application layer MUST be able to specify the Type-of-
+ Service (TOS) for segments that are sent on a connection.
+ It not required, but the application SHOULD be able to
+ change the TOS during the connection lifetime. TCP SHOULD
+ pass the current TOS value without change to the IP layer,
+ when it sends segments on the connection.
+
+ The TOS will be specified independently in each direction on
+ the connection, so that the receiver application will
+ specify the TOS used for ACK segments.
+
+ TCP MAY pass the most recently received TOS up to the
+ application.
+
+ DISCUSSION
+ Some applications (e.g., SMTP) change the nature of
+ their communication during the lifetime of a
+ connection, and therefore would like to change the TOS
+ specification.
+
+ Note also that the OPEN call specified in RFC-793
+ includes a parameter ("options") in which the caller
+ can specify IP options such as source route, record
+ route, or timestamp.
+
+ 4.2.4.3 Flush Call
+
+ Some TCP implementations have included a FLUSH call, which
+ will empty the TCP send queue of any data for which the user
+ has issued SEND calls but which is still to the right of the
+ current send window. That is, it flushes as much queued
+ send data as possible without losing sequence number
+ synchronization. This is useful for implementing the "abort
+ output" function of Telnet.
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 107]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ 4.2.4.4 Multihoming
+
+ The user interface outlined in sections 2.7 and 3.8 of RFC-
+ 793 needs to be extended for multihoming. The OPEN call
+ MUST have an optional parameter:
+
+ OPEN( ... [local IP address,] ... )
+
+ to allow the specification of the local IP address.
+
+ DISCUSSION:
+ Some TCP-based applications need to specify the local
+ IP address to be used to open a particular connection;
+ FTP is an example.
+
+ IMPLEMENTATION:
+ A passive OPEN call with a specified "local IP address"
+ parameter will await an incoming connection request to
+ that address. If the parameter is unspecified, a
+ passive OPEN will await an incoming connection request
+ to any local IP address, and then bind the local IP
+ address of the connection to the particular address
+ that is used.
+
+ For an active OPEN call, a specified "local IP address"
+ parameter will be used for opening the connection. If
+ the parameter is unspecified, the networking software
+ will choose an appropriate local IP address (see
+ Section 3.3.4.2) for the connection
+
+ 4.2.5 TCP REQUIREMENT SUMMARY
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION | | | |T|T|e
+-------------------------------------------------|--------|-|-|-|-|-|--
+ | | | | | | |
+Push flag | | | | | | |
+ Aggregate or queue un-pushed data |4.2.2.2 | | |x| | |
+ Sender collapse successive PSH flags |4.2.2.2 | |x| | | |
+ SEND call can specify PUSH |4.2.2.2 | | |x| | |
+
+
+
+Internet Engineering Task Force [Page 108]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ If cannot: sender buffer indefinitely |4.2.2.2 | | | | |x|
+ If cannot: PSH last segment |4.2.2.2 |x| | | | |
+ Notify receiving ALP of PSH |4.2.2.2 | | |x| | |1
+ Send max size segment when possible |4.2.2.2 | |x| | | |
+ | | | | | | |
+Window | | | | | | |
+ Treat as unsigned number |4.2.2.3 |x| | | | |
+ Handle as 32-bit number |4.2.2.3 | |x| | | |
+ Shrink window from right |4.2.2.16| | | |x| |
+ Robust against shrinking window |4.2.2.16|x| | | | |
+ Receiver's window closed indefinitely |4.2.2.17| | |x| | |
+ Sender probe zero window |4.2.2.17|x| | | | |
+ First probe after RTO |4.2.2.17| |x| | | |
+ Exponential backoff |4.2.2.17| |x| | | |
+ Allow window stay zero indefinitely |4.2.2.17|x| | | | |
+ Sender timeout OK conn with zero wind |4.2.2.17| | | | |x|
+ | | | | | | |
+Urgent Data | | | | | | |
+ Pointer points to last octet |4.2.2.4 |x| | | | |
+ Arbitrary length urgent data sequence |4.2.2.4 |x| | | | |
+ Inform ALP asynchronously of urgent data |4.2.2.4 |x| | | | |1
+ ALP can learn if/how much urgent data Q'd |4.2.2.4 |x| | | | |1
+ | | | | | | |
+TCP Options | | | | | | |
+ Receive TCP option in any segment |4.2.2.5 |x| | | | |
+ Ignore unsupported options |4.2.2.5 |x| | | | |
+ Cope with illegal option length |4.2.2.5 |x| | | | |
+ Implement sending & receiving MSS option |4.2.2.6 |x| | | | |
+ Send MSS option unless 536 |4.2.2.6 | |x| | | |
+ Send MSS option always |4.2.2.6 | | |x| | |
+ Send-MSS default is 536 |4.2.2.6 |x| | | | |
+ Calculate effective send seg size |4.2.2.6 |x| | | | |
+ | | | | | | |
+TCP Checksums | | | | | | |
+ Sender compute checksum |4.2.2.7 |x| | | | |
+ Receiver check checksum |4.2.2.7 |x| | | | |
+ | | | | | | |
+Use clock-driven ISN selection |4.2.2.9 |x| | | | |
+ | | | | | | |
+Opening Connections | | | | | | |
+ Support simultaneous open attempts |4.2.2.10|x| | | | |
+ SYN-RCVD remembers last state |4.2.2.11|x| | | | |
+ Passive Open call interfere with others |4.2.2.18| | | | |x|
+ Function: simultan. LISTENs for same port |4.2.2.18|x| | | | |
+ Ask IP for src address for SYN if necc. |4.2.3.7 |x| | | | |
+ Otherwise, use local addr of conn. |4.2.3.7 |x| | | | |
+ OPEN to broadcast/multicast IP Address |4.2.3.14| | | | |x|
+ Silently discard seg to bcast/mcast addr |4.2.3.14|x| | | | |
+
+
+
+Internet Engineering Task Force [Page 109]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ | | | | | | |
+Closing Connections | | | | | | |
+ RST can contain data |4.2.2.12| |x| | | |
+ Inform application of aborted conn |4.2.2.13|x| | | | |
+ Half-duplex close connections |4.2.2.13| | |x| | |
+ Send RST to indicate data lost |4.2.2.13| |x| | | |
+ In TIME-WAIT state for 2xMSL seconds |4.2.2.13|x| | | | |
+ Accept SYN from TIME-WAIT state |4.2.2.13| | |x| | |
+ | | | | | | |
+Retransmissions | | | | | | |
+ Jacobson Slow Start algorithm |4.2.2.15|x| | | | |
+ Jacobson Congestion-Avoidance algorithm |4.2.2.15|x| | | | |
+ Retransmit with same IP ident |4.2.2.15| | |x| | |
+ Karn's algorithm |4.2.3.1 |x| | | | |
+ Jacobson's RTO estimation alg. |4.2.3.1 |x| | | | |
+ Exponential backoff |4.2.3.1 |x| | | | |
+ SYN RTO calc same as data |4.2.3.1 | |x| | | |
+ Recommended initial values and bounds |4.2.3.1 | |x| | | |
+ | | | | | | |
+Generating ACK's: | | | | | | |
+ Queue out-of-order segments |4.2.2.20| |x| | | |
+ Process all Q'd before send ACK |4.2.2.20|x| | | | |
+ Send ACK for out-of-order segment |4.2.2.21| | |x| | |
+ Delayed ACK's |4.2.3.2 | |x| | | |
+ Delay < 0.5 seconds |4.2.3.2 |x| | | | |
+ Every 2nd full-sized segment ACK'd |4.2.3.2 |x| | | | |
+ Receiver SWS-Avoidance Algorithm |4.2.3.3 |x| | | | |
+ | | | | | | |
+Sending data | | | | | | |
+ Configurable TTL |4.2.2.19|x| | | | |
+ Sender SWS-Avoidance Algorithm |4.2.3.4 |x| | | | |
+ Nagle algorithm |4.2.3.4 | |x| | | |
+ Application can disable Nagle algorithm |4.2.3.4 |x| | | | |
+ | | | | | | |
+Connection Failures: | | | | | | |
+ Negative advice to IP on R1 retxs |4.2.3.5 |x| | | | |
+ Close connection on R2 retxs |4.2.3.5 |x| | | | |
+ ALP can set R2 |4.2.3.5 |x| | | | |1
+ Inform ALP of R1<=retxs<R2 |4.2.3.5 | |x| | | |1
+ Recommended values for R1, R2 |4.2.3.5 | |x| | | |
+ Same mechanism for SYNs |4.2.3.5 |x| | | | |
+ R2 at least 3 minutes for SYN |4.2.3.5 |x| | | | |
+ | | | | | | |
+Send Keep-alive Packets: |4.2.3.6 | | |x| | |
+ - Application can request |4.2.3.6 |x| | | | |
+ - Default is "off" |4.2.3.6 |x| | | | |
+ - Only send if idle for interval |4.2.3.6 |x| | | | |
+ - Interval configurable |4.2.3.6 |x| | | | |
+
+
+
+Internet Engineering Task Force [Page 110]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ - Default at least 2 hrs. |4.2.3.6 |x| | | | |
+ - Tolerant of lost ACK's |4.2.3.6 |x| | | | |
+ | | | | | | |
+IP Options | | | | | | |
+ Ignore options TCP doesn't understand |4.2.3.8 |x| | | | |
+ Time Stamp support |4.2.3.8 | | |x| | |
+ Record Route support |4.2.3.8 | | |x| | |
+ Source Route: | | | | | | |
+ ALP can specify |4.2.3.8 |x| | | | |1
+ Overrides src rt in datagram |4.2.3.8 |x| | | | |
+ Build return route from src rt |4.2.3.8 |x| | | | |
+ Later src route overrides |4.2.3.8 | |x| | | |
+ | | | | | | |
+Receiving ICMP Messages from IP |4.2.3.9 |x| | | | |
+ Dest. Unreach (0,1,5) => inform ALP |4.2.3.9 | |x| | | |
+ Dest. Unreach (0,1,5) => abort conn |4.2.3.9 | | | | |x|
+ Dest. Unreach (2-4) => abort conn |4.2.3.9 | |x| | | |
+ Source Quench => slow start |4.2.3.9 | |x| | | |
+ Time Exceeded => tell ALP, don't abort |4.2.3.9 | |x| | | |
+ Param Problem => tell ALP, don't abort |4.2.3.9 | |x| | | |
+ | | | | | | |
+Address Validation | | | | | | |
+ Reject OPEN call to invalid IP address |4.2.3.10|x| | | | |
+ Reject SYN from invalid IP address |4.2.3.10|x| | | | |
+ Silently discard SYN to bcast/mcast addr |4.2.3.10|x| | | | |
+ | | | | | | |
+TCP/ALP Interface Services | | | | | | |
+ Error Report mechanism |4.2.4.1 |x| | | | |
+ ALP can disable Error Report Routine |4.2.4.1 | |x| | | |
+ ALP can specify TOS for sending |4.2.4.2 |x| | | | |
+ Passed unchanged to IP |4.2.4.2 | |x| | | |
+ ALP can change TOS during connection |4.2.4.2 | |x| | | |
+ Pass received TOS up to ALP |4.2.4.2 | | |x| | |
+ FLUSH call |4.2.4.3 | | |x| | |
+ Optional local IP addr parm. in OPEN |4.2.4.4 |x| | | | |
+-------------------------------------------------|--------|-|-|-|-|-|--
+-------------------------------------------------|--------|-|-|-|-|-|--
+
+FOOTNOTES:
+
+(1) "ALP" means Application-Layer program.
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 111]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+5. REFERENCES
+
+INTRODUCTORY REFERENCES
+
+
+[INTRO:1] "Requirements for Internet Hosts -- Application and Support,"
+ IETF Host Requirements Working Group, R. Braden, Ed., RFC-1123,
+ October 1989.
+
+[INTRO:2] "Requirements for Internet Gateways," R. Braden and J.
+ Postel, RFC-1009, June 1987.
+
+[INTRO:3] "DDN Protocol Handbook," NIC-50004, NIC-50005, NIC-50006,
+ (three volumes), SRI International, December 1985.
+
+[INTRO:4] "Official Internet Protocols," J. Reynolds and J. Postel,
+ RFC-1011, May 1987.
+
+ This document is republished periodically with new RFC numbers; the
+ latest version must be used.
+
+[INTRO:5] "Protocol Document Order Information," O. Jacobsen and J.
+ Postel, RFC-980, March 1986.
+
+[INTRO:6] "Assigned Numbers," J. Reynolds and J. Postel, RFC-1010, May
+ 1987.
+
+ This document is republished periodically with new RFC numbers; the
+ latest version must be used.
+
+[INTRO:7] "Modularity and Efficiency in Protocol Implementations," D.
+ Clark, RFC-817, July 1982.
+
+[INTRO:8] "The Structuring of Systems Using Upcalls," D. Clark, 10th ACM
+ SOSP, Orcas Island, Washington, December 1985.
+
+
+Secondary References:
+
+
+[INTRO:9] "A Protocol for Packet Network Intercommunication," V. Cerf
+ and R. Kahn, IEEE Transactions on Communication, May 1974.
+
+[INTRO:10] "The ARPA Internet Protocol," J. Postel, C. Sunshine, and D.
+ Cohen, Computer Networks, Vol. 5, No. 4, July 1981.
+
+[INTRO:11] "The DARPA Internet Protocol Suite," B. Leiner, J. Postel,
+ R. Cole and D. Mills, Proceedings INFOCOM 85, IEEE, Washington DC,
+
+
+
+Internet Engineering Task Force [Page 112]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ March 1985. Also in: IEEE Communications Magazine, March 1985.
+ Also available as ISI-RS-85-153.
+
+[INTRO:12] "Final Text of DIS8473, Protocol for Providing the
+ Connectionless Mode Network Service," ANSI, published as RFC-994,
+ March 1986.
+
+[INTRO:13] "End System to Intermediate System Routing Exchange
+ Protocol," ANSI X3S3.3, published as RFC-995, April 1986.
+
+
+LINK LAYER REFERENCES
+
+
+[LINK:1] "Trailer Encapsulations," S. Leffler and M. Karels, RFC-893,
+ April 1984.
+
+[LINK:2] "An Ethernet Address Resolution Protocol," D. Plummer, RFC-826,
+ November 1982.
+
+[LINK:3] "A Standard for the Transmission of IP Datagrams over Ethernet
+ Networks," C. Hornig, RFC-894, April 1984.
+
+[LINK:4] "A Standard for the Transmission of IP Datagrams over IEEE 802
+ "Networks," J. Postel and J. Reynolds, RFC-1042, February 1988.
+
+ This RFC contains a great deal of information of importance to
+ Internet implementers planning to use IEEE 802 networks.
+
+
+IP LAYER REFERENCES
+
+
+[IP:1] "Internet Protocol (IP)," J. Postel, RFC-791, September 1981.
+
+[IP:2] "Internet Control Message Protocol (ICMP)," J. Postel, RFC-792,
+ September 1981.
+
+[IP:3] "Internet Standard Subnetting Procedure," J. Mogul and J. Postel,
+ RFC-950, August 1985.
+
+[IP:4] "Host Extensions for IP Multicasting," S. Deering, RFC-1112,
+ August 1989.
+
+[IP:5] "Military Standard Internet Protocol," MIL-STD-1777, Department
+ of Defense, August 1983.
+
+ This specification, as amended by RFC-963, is intended to describe
+
+
+
+Internet Engineering Task Force [Page 113]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+ the Internet Protocol but has some serious omissions (e.g., the
+ mandatory subnet extension [IP:3] and the optional multicasting
+ extension [IP:4]). It is also out of date. If there is a
+ conflict, RFC-791, RFC-792, and RFC-950 must be taken as
+ authoritative, while the present document is authoritative over
+ all.
+
+[IP:6] "Some Problems with the Specification of the Military Standard
+ Internet Protocol," D. Sidhu, RFC-963, November 1985.
+
+[IP:7] "The TCP Maximum Segment Size and Related Topics," J. Postel,
+ RFC-879, November 1983.
+
+ Discusses and clarifies the relationship between the TCP Maximum
+ Segment Size option and the IP datagram size.
+
+[IP:8] "Internet Protocol Security Options," B. Schofield, RFC-1108,
+ October 1989.
+
+[IP:9] "Fragmentation Considered Harmful," C. Kent and J. Mogul, ACM
+ SIGCOMM-87, August 1987. Published as ACM Comp Comm Review, Vol.
+ 17, no. 5.
+
+ This useful paper discusses the problems created by Internet
+ fragmentation and presents alternative solutions.
+
+[IP:10] "IP Datagram Reassembly Algorithms," D. Clark, RFC-815, July
+ 1982.
+
+ This and the following paper should be read by every implementor.
+
+[IP:11] "Fault Isolation and Recovery," D. Clark, RFC-816, July 1982.
+
+SECONDARY IP REFERENCES:
+
+
+[IP:12] "Broadcasting Internet Datagrams in the Presence of Subnets," J.
+ Mogul, RFC-922, October 1984.
+
+[IP:13] "Name, Addresses, Ports, and Routes," D. Clark, RFC-814, July
+ 1982.
+
+[IP:14] "Something a Host Could Do with Source Quench: The Source Quench
+ Introduced Delay (SQUID)," W. Prue and J. Postel, RFC-1016, July
+ 1987.
+
+ This RFC first described directed broadcast addresses. However,
+ the bulk of the RFC is concerned with gateways, not hosts.
+
+
+
+Internet Engineering Task Force [Page 114]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+UDP REFERENCES:
+
+
+[UDP:1] "User Datagram Protocol," J. Postel, RFC-768, August 1980.
+
+
+TCP REFERENCES:
+
+
+[TCP:1] "Transmission Control Protocol," J. Postel, RFC-793, September
+ 1981.
+
+
+[TCP:2] "Transmission Control Protocol," MIL-STD-1778, US Department of
+ Defense, August 1984.
+
+ This specification as amended by RFC-964 is intended to describe
+ the same protocol as RFC-793 [TCP:1]. If there is a conflict,
+ RFC-793 takes precedence, and the present document is authoritative
+ over both.
+
+
+[TCP:3] "Some Problems with the Specification of the Military Standard
+ Transmission Control Protocol," D. Sidhu and T. Blumer, RFC-964,
+ November 1985.
+
+
+[TCP:4] "The TCP Maximum Segment Size and Related Topics," J. Postel,
+ RFC-879, November 1983.
+
+
+[TCP:5] "Window and Acknowledgment Strategy in TCP," D. Clark, RFC-813,
+ July 1982.
+
+
+[TCP:6] "Round Trip Time Estimation," P. Karn & C. Partridge, ACM
+ SIGCOMM-87, August 1987.
+
+
+[TCP:7] "Congestion Avoidance and Control," V. Jacobson, ACM SIGCOMM-88,
+ August 1988.
+
+
+SECONDARY TCP REFERENCES:
+
+
+[TCP:8] "Modularity and Efficiency in Protocol Implementation," D.
+ Clark, RFC-817, July 1982.
+
+
+
+Internet Engineering Task Force [Page 115]
+
+
+
+
+RFC1122 TRANSPORT LAYER -- TCP October 1989
+
+
+[TCP:9] "Congestion Control in IP/TCP," J. Nagle, RFC-896, January 1984.
+
+
+[TCP:10] "Computing the Internet Checksum," R. Braden, D. Borman, and C.
+ Partridge, RFC-1071, September 1988.
+
+
+[TCP:11] "TCP Extensions for Long-Delay Paths," V. Jacobson & R. Braden,
+ RFC-1072, October 1988.
+
+
+Security Considerations
+
+ There are many security issues in the communication layers of host
+ software, but a full discussion is beyond the scope of this RFC.
+
+ The Internet architecture generally provides little protection
+ against spoofing of IP source addresses, so any security mechanism
+ that is based upon verifying the IP source address of a datagram
+ should be treated with suspicion. However, in restricted
+ environments some source-address checking may be possible. For
+ example, there might be a secure LAN whose gateway to the rest of the
+ Internet discarded any incoming datagram with a source address that
+ spoofed the LAN address. In this case, a host on the LAN could use
+ the source address to test for local vs. remote source. This problem
+ is complicated by source routing, and some have suggested that
+ source-routed datagram forwarding by hosts (see Section 3.3.5) should
+ be outlawed for security reasons.
+
+ Security-related issues are mentioned in sections concerning the IP
+ Security option (Section 3.2.1.8), the ICMP Parameter Problem message
+ (Section 3.2.2.5), IP options in UDP datagrams (Section 4.1.3.2), and
+ reserved TCP ports (Section 4.2.2.1).
+
+Author's Address
+
+ Robert Braden
+ USC/Information Sciences Institute
+ 4676 Admiralty Way
+ Marina del Rey, CA 90292-6695
+
+ Phone: (213) 822 1511
+
+ EMail: Braden@ISI.EDU
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 116]
+
diff --git a/doc/rfc/rfc1123.txt b/doc/rfc/rfc1123.txt
new file mode 100644
index 0000000..51cdf83
--- /dev/null
+++ b/doc/rfc/rfc1123.txt
@@ -0,0 +1,5782 @@
+
+
+
+
+
+
+Network Working Group Internet Engineering Task Force
+Request for Comments: 1123 R. Braden, Editor
+ October 1989
+
+
+ Requirements for Internet Hosts -- Application and Support
+
+Status of This Memo
+
+ This RFC is an official specification for the Internet community. It
+ incorporates by reference, amends, corrects, and supplements the
+ primary protocol standards documents relating to hosts. Distribution
+ of this document is unlimited.
+
+Summary
+
+ This RFC is one of a pair that defines and discusses the requirements
+ for Internet host software. This RFC covers the application and
+ support protocols; its companion RFC-1122 covers the communication
+ protocol layers: link layer, IP layer, and transport layer.
+
+
+
+ Table of Contents
+
+
+
+
+ 1. INTRODUCTION ............................................... 5
+ 1.1 The Internet Architecture .............................. 6
+ 1.2 General Considerations ................................. 6
+ 1.2.1 Continuing Internet Evolution ..................... 6
+ 1.2.2 Robustness Principle .............................. 7
+ 1.2.3 Error Logging ..................................... 8
+ 1.2.4 Configuration ..................................... 8
+ 1.3 Reading this Document .................................. 10
+ 1.3.1 Organization ...................................... 10
+ 1.3.2 Requirements ...................................... 10
+ 1.3.3 Terminology ....................................... 11
+ 1.4 Acknowledgments ........................................ 12
+
+ 2. GENERAL ISSUES ............................................. 13
+ 2.1 Host Names and Numbers ................................. 13
+ 2.2 Using Domain Name Service .............................. 13
+ 2.3 Applications on Multihomed hosts ....................... 14
+ 2.4 Type-of-Service ........................................ 14
+ 2.5 GENERAL APPLICATION REQUIREMENTS SUMMARY ............... 15
+
+
+
+
+Internet Engineering Task Force [Page 1]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+ 3. REMOTE LOGIN -- TELNET PROTOCOL ............................ 16
+ 3.1 INTRODUCTION ........................................... 16
+ 3.2 PROTOCOL WALK-THROUGH .................................. 16
+ 3.2.1 Option Negotiation ................................ 16
+ 3.2.2 Telnet Go-Ahead Function .......................... 16
+ 3.2.3 Control Functions ................................. 17
+ 3.2.4 Telnet "Synch" Signal ............................. 18
+ 3.2.5 NVT Printer and Keyboard .......................... 19
+ 3.2.6 Telnet Command Structure .......................... 20
+ 3.2.7 Telnet Binary Option .............................. 20
+ 3.2.8 Telnet Terminal-Type Option ....................... 20
+ 3.3 SPECIFIC ISSUES ........................................ 21
+ 3.3.1 Telnet End-of-Line Convention ..................... 21
+ 3.3.2 Data Entry Terminals .............................. 23
+ 3.3.3 Option Requirements ............................... 24
+ 3.3.4 Option Initiation ................................. 24
+ 3.3.5 Telnet Linemode Option ............................ 25
+ 3.4 TELNET/USER INTERFACE .................................. 25
+ 3.4.1 Character Set Transparency ........................ 25
+ 3.4.2 Telnet Commands ................................... 26
+ 3.4.3 TCP Connection Errors ............................. 26
+ 3.4.4 Non-Default Telnet Contact Port ................... 26
+ 3.4.5 Flushing Output ................................... 26
+ 3.5. TELNET REQUIREMENTS SUMMARY ........................... 27
+
+ 4. FILE TRANSFER .............................................. 29
+ 4.1 FILE TRANSFER PROTOCOL -- FTP .......................... 29
+ 4.1.1 INTRODUCTION ...................................... 29
+ 4.1.2. PROTOCOL WALK-THROUGH ............................ 29
+ 4.1.2.1 LOCAL Type ................................... 29
+ 4.1.2.2 Telnet Format Control ........................ 30
+ 4.1.2.3 Page Structure ............................... 30
+ 4.1.2.4 Data Structure Transformations ............... 30
+ 4.1.2.5 Data Connection Management ................... 31
+ 4.1.2.6 PASV Command ................................. 31
+ 4.1.2.7 LIST and NLST Commands ....................... 31
+ 4.1.2.8 SITE Command ................................. 32
+ 4.1.2.9 STOU Command ................................. 32
+ 4.1.2.10 Telnet End-of-line Code ..................... 32
+ 4.1.2.11 FTP Replies ................................. 33
+ 4.1.2.12 Connections ................................. 34
+ 4.1.2.13 Minimum Implementation; RFC-959 Section ..... 34
+ 4.1.3 SPECIFIC ISSUES ................................... 35
+ 4.1.3.1 Non-standard Command Verbs ................... 35
+ 4.1.3.2 Idle Timeout ................................. 36
+ 4.1.3.3 Concurrency of Data and Control .............. 36
+ 4.1.3.4 FTP Restart Mechanism ........................ 36
+ 4.1.4 FTP/USER INTERFACE ................................ 39
+
+
+
+Internet Engineering Task Force [Page 2]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+ 4.1.4.1 Pathname Specification ....................... 39
+ 4.1.4.2 "QUOTE" Command .............................. 40
+ 4.1.4.3 Displaying Replies to User ................... 40
+ 4.1.4.4 Maintaining Synchronization .................. 40
+ 4.1.5 FTP REQUIREMENTS SUMMARY ......................... 41
+ 4.2 TRIVIAL FILE TRANSFER PROTOCOL -- TFTP ................. 44
+ 4.2.1 INTRODUCTION ...................................... 44
+ 4.2.2 PROTOCOL WALK-THROUGH ............................. 44
+ 4.2.2.1 Transfer Modes ............................... 44
+ 4.2.2.2 UDP Header ................................... 44
+ 4.2.3 SPECIFIC ISSUES ................................... 44
+ 4.2.3.1 Sorcerer's Apprentice Syndrome ............... 44
+ 4.2.3.2 Timeout Algorithms ........................... 46
+ 4.2.3.3 Extensions ................................... 46
+ 4.2.3.4 Access Control ............................... 46
+ 4.2.3.5 Broadcast Request ............................ 46
+ 4.2.4 TFTP REQUIREMENTS SUMMARY ......................... 47
+
+ 5. ELECTRONIC MAIL -- SMTP and RFC-822 ........................ 48
+ 5.1 INTRODUCTION ........................................... 48
+ 5.2 PROTOCOL WALK-THROUGH .................................. 48
+ 5.2.1 The SMTP Model .................................... 48
+ 5.2.2 Canonicalization .................................. 49
+ 5.2.3 VRFY and EXPN Commands ............................ 50
+ 5.2.4 SEND, SOML, and SAML Commands ..................... 50
+ 5.2.5 HELO Command ...................................... 50
+ 5.2.6 Mail Relay ........................................ 51
+ 5.2.7 RCPT Command ...................................... 52
+ 5.2.8 DATA Command ...................................... 53
+ 5.2.9 Command Syntax .................................... 54
+ 5.2.10 SMTP Replies ..................................... 54
+ 5.2.11 Transparency ..................................... 55
+ 5.2.12 WKS Use in MX Processing ......................... 55
+ 5.2.13 RFC-822 Message Specification .................... 55
+ 5.2.14 RFC-822 Date and Time Specification .............. 55
+ 5.2.15 RFC-822 Syntax Change ............................ 56
+ 5.2.16 RFC-822 Local-part .............................. 56
+ 5.2.17 Domain Literals .................................. 57
+ 5.2.18 Common Address Formatting Errors ................. 58
+ 5.2.19 Explicit Source Routes ........................... 58
+ 5.3 SPECIFIC ISSUES ........................................ 59
+ 5.3.1 SMTP Queueing Strategies .......................... 59
+ 5.3.1.1 Sending Strategy .............................. 59
+ 5.3.1.2 Receiving strategy ........................... 61
+ 5.3.2 Timeouts in SMTP .................................. 61
+ 5.3.3 Reliable Mail Receipt ............................. 63
+ 5.3.4 Reliable Mail Transmission ........................ 63
+ 5.3.5 Domain Name Support ............................... 65
+
+
+
+Internet Engineering Task Force [Page 3]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+ 5.3.6 Mailing Lists and Aliases ......................... 65
+ 5.3.7 Mail Gatewaying ................................... 66
+ 5.3.8 Maximum Message Size .............................. 68
+ 5.4 SMTP REQUIREMENTS SUMMARY .............................. 69
+
+ 6. SUPPORT SERVICES ............................................ 72
+ 6.1 DOMAIN NAME TRANSLATION ................................. 72
+ 6.1.1 INTRODUCTION ....................................... 72
+ 6.1.2 PROTOCOL WALK-THROUGH ............................. 72
+ 6.1.2.1 Resource Records with Zero TTL ............... 73
+ 6.1.2.2 QCLASS Values ................................ 73
+ 6.1.2.3 Unused Fields ................................ 73
+ 6.1.2.4 Compression .................................. 73
+ 6.1.2.5 Misusing Configuration Info .................. 73
+ 6.1.3 SPECIFIC ISSUES ................................... 74
+ 6.1.3.1 Resolver Implementation ...................... 74
+ 6.1.3.2 Transport Protocols .......................... 75
+ 6.1.3.3 Efficient Resource Usage ..................... 77
+ 6.1.3.4 Multihomed Hosts ............................. 78
+ 6.1.3.5 Extensibility ................................ 79
+ 6.1.3.6 Status of RR Types ........................... 79
+ 6.1.3.7 Robustness ................................... 80
+ 6.1.3.8 Local Host Table ............................. 80
+ 6.1.4 DNS USER INTERFACE ................................ 81
+ 6.1.4.1 DNS Administration ........................... 81
+ 6.1.4.2 DNS User Interface ........................... 81
+ 6.1.4.3 Interface Abbreviation Facilities ............. 82
+ 6.1.5 DOMAIN NAME SYSTEM REQUIREMENTS SUMMARY ........... 84
+ 6.2 HOST INITIALIZATION .................................... 87
+ 6.2.1 INTRODUCTION ...................................... 87
+ 6.2.2 REQUIREMENTS ...................................... 87
+ 6.2.2.1 Dynamic Configuration ........................ 87
+ 6.2.2.2 Loading Phase ................................ 89
+ 6.3 REMOTE MANAGEMENT ...................................... 90
+ 6.3.1 INTRODUCTION ...................................... 90
+ 6.3.2 PROTOCOL WALK-THROUGH ............................. 90
+ 6.3.3 MANAGEMENT REQUIREMENTS SUMMARY ................... 92
+
+ 7. REFERENCES ................................................. 93
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 4]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+1. INTRODUCTION
+
+ This document is one of a pair that defines and discusses the
+ requirements for host system implementations of the Internet protocol
+ suite. This RFC covers the applications layer and support protocols.
+ Its companion RFC, "Requirements for Internet Hosts -- Communications
+ Layers" [INTRO:1] covers the lower layer protocols: transport layer,
+ IP layer, and link layer.
+
+ These documents are intended to provide guidance for vendors,
+ implementors, and users of Internet communication software. They
+ represent the consensus of a large body of technical experience and
+ wisdom, contributed by members of the Internet research and vendor
+ communities.
+
+ This RFC enumerates standard protocols that a host connected to the
+ Internet must use, and it incorporates by reference the RFCs and
+ other documents describing the current specifications for these
+ protocols. It corrects errors in the referenced documents and adds
+ additional discussion and guidance for an implementor.
+
+ For each protocol, this document also contains an explicit set of
+ requirements, recommendations, and options. The reader must
+ understand that the list of requirements in this document is
+ incomplete by itself; the complete set of requirements for an
+ Internet host is primarily defined in the standard protocol
+ specification documents, with the corrections, amendments, and
+ supplements contained in this RFC.
+
+ A good-faith implementation of the protocols that was produced after
+ careful reading of the RFC's and with some interaction with the
+ Internet technical community, and that followed good communications
+ software engineering practices, should differ from the requirements
+ of this document in only minor ways. Thus, in many cases, the
+ "requirements" in this RFC are already stated or implied in the
+ standard protocol documents, so that their inclusion here is, in a
+ sense, redundant. However, they were included because some past
+ implementation has made the wrong choice, causing problems of
+ interoperability, performance, and/or robustness.
+
+ This document includes discussion and explanation of many of the
+ requirements and recommendations. A simple list of requirements
+ would be dangerous, because:
+
+ o Some required features are more important than others, and some
+ features are optional.
+
+ o There may be valid reasons why particular vendor products that
+
+
+
+Internet Engineering Task Force [Page 5]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+ are designed for restricted contexts might choose to use
+ different specifications.
+
+ However, the specifications of this document must be followed to meet
+ the general goal of arbitrary host interoperation across the
+ diversity and complexity of the Internet system. Although most
+ current implementations fail to meet these requirements in various
+ ways, some minor and some major, this specification is the ideal
+ towards which we need to move.
+
+ These requirements are based on the current level of Internet
+ architecture. This document will be updated as required to provide
+ additional clarifications or to include additional information in
+ those areas in which specifications are still evolving.
+
+ This introductory section begins with general advice to host software
+ vendors, and then gives some guidance on reading the rest of the
+ document. Section 2 contains general requirements that may be
+ applicable to all application and support protocols. Sections 3, 4,
+ and 5 contain the requirements on protocols for the three major
+ applications: Telnet, file transfer, and electronic mail,
+ respectively. Section 6 covers the support applications: the domain
+ name system, system initialization, and management. Finally, all
+ references will be found in Section 7.
+
+ 1.1 The Internet Architecture
+
+ For a brief introduction to the Internet architecture from a host
+ viewpoint, see Section 1.1 of [INTRO:1]. That section also
+ contains recommended references for general background on the
+ Internet architecture.
+
+ 1.2 General Considerations
+
+ There are two important lessons that vendors of Internet host
+ software have learned and which a new vendor should consider
+ seriously.
+
+ 1.2.1 Continuing Internet Evolution
+
+ The enormous growth of the Internet has revealed problems of
+ management and scaling in a large datagram-based packet
+ communication system. These problems are being addressed, and
+ as a result there will be continuing evolution of the
+ specifications described in this document. These changes will
+ be carefully planned and controlled, since there is extensive
+ participation in this planning by the vendors and by the
+ organizations responsible for operations of the networks.
+
+
+
+Internet Engineering Task Force [Page 6]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+ Development, evolution, and revision are characteristic of
+ computer network protocols today, and this situation will
+ persist for some years. A vendor who develops computer
+ communication software for the Internet protocol suite (or any
+ other protocol suite!) and then fails to maintain and update
+ that software for changing specifications is going to leave a
+ trail of unhappy customers. The Internet is a large
+ communication network, and the users are in constant contact
+ through it. Experience has shown that knowledge of
+ deficiencies in vendor software propagates quickly through the
+ Internet technical community.
+
+ 1.2.2 Robustness Principle
+
+ At every layer of the protocols, there is a general rule whose
+ application can lead to enormous benefits in robustness and
+ interoperability:
+
+ "Be liberal in what you accept, and
+ conservative in what you send"
+
+ Software should be written to deal with every conceivable
+ error, no matter how unlikely; sooner or later a packet will
+ come in with that particular combination of errors and
+ attributes, and unless the software is prepared, chaos can
+ ensue. In general, it is best to assume that the network is
+ filled with malevolent entities that will send in packets
+ designed to have the worst possible effect. This assumption
+ will lead to suitable protective design, although the most
+ serious problems in the Internet have been caused by
+ unenvisaged mechanisms triggered by low-probability events;
+ mere human malice would never have taken so devious a course!
+
+ Adaptability to change must be designed into all levels of
+ Internet host software. As a simple example, consider a
+ protocol specification that contains an enumeration of values
+ for a particular header field -- e.g., a type field, a port
+ number, or an error code; this enumeration must be assumed to
+ be incomplete. Thus, if a protocol specification defines four
+ possible error codes, the software must not break when a fifth
+ code shows up. An undefined code might be logged (see below),
+ but it must not cause a failure.
+
+ The second part of the principle is almost as important:
+ software on other hosts may contain deficiencies that make it
+ unwise to exploit legal but obscure protocol features. It is
+ unwise to stray far from the obvious and simple, lest untoward
+ effects result elsewhere. A corollary of this is "watch out
+
+
+
+Internet Engineering Task Force [Page 7]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+ for misbehaving hosts"; host software should be prepared, not
+ just to survive other misbehaving hosts, but also to cooperate
+ to limit the amount of disruption such hosts can cause to the
+ shared communication facility.
+
+ 1.2.3 Error Logging
+
+ The Internet includes a great variety of host and gateway
+ systems, each implementing many protocols and protocol layers,
+ and some of these contain bugs and mis-features in their
+ Internet protocol software. As a result of complexity,
+ diversity, and distribution of function, the diagnosis of user
+ problems is often very difficult.
+
+ Problem diagnosis will be aided if host implementations include
+ a carefully designed facility for logging erroneous or
+ "strange" protocol events. It is important to include as much
+ diagnostic information as possible when an error is logged. In
+ particular, it is often useful to record the header(s) of a
+ packet that caused an error. However, care must be taken to
+ ensure that error logging does not consume prohibitive amounts
+ of resources or otherwise interfere with the operation of the
+ host.
+
+ There is a tendency for abnormal but harmless protocol events
+ to overflow error logging files; this can be avoided by using a
+ "circular" log, or by enabling logging only while diagnosing a
+ known failure. It may be useful to filter and count duplicate
+ successive messages. One strategy that seems to work well is:
+ (1) always count abnormalities and make such counts accessible
+ through the management protocol (see Section 6.3); and (2)
+ allow the logging of a great variety of events to be
+ selectively enabled. For example, it might useful to be able
+ to "log everything" or to "log everything for host X".
+
+ Note that different managements may have differing policies
+ about the amount of error logging that they want normally
+ enabled in a host. Some will say, "if it doesn't hurt me, I
+ don't want to know about it", while others will want to take a
+ more watchful and aggressive attitude about detecting and
+ removing protocol abnormalities.
+
+ 1.2.4 Configuration
+
+ It would be ideal if a host implementation of the Internet
+ protocol suite could be entirely self-configuring. This would
+ allow the whole suite to be implemented in ROM or cast into
+ silicon, it would simplify diskless workstations, and it would
+
+
+
+Internet Engineering Task Force [Page 8]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+ be an immense boon to harried LAN administrators as well as
+ system vendors. We have not reached this ideal; in fact, we
+ are not even close.
+
+ At many points in this document, you will find a requirement
+ that a parameter be a configurable option. There are several
+ different reasons behind such requirements. In a few cases,
+ there is current uncertainty or disagreement about the best
+ value, and it may be necessary to update the recommended value
+ in the future. In other cases, the value really depends on
+ external factors -- e.g., the size of the host and the
+ distribution of its communication load, or the speeds and
+ topology of nearby networks -- and self-tuning algorithms are
+ unavailable and may be insufficient. In some cases,
+ configurability is needed because of administrative
+ requirements.
+
+ Finally, some configuration options are required to communicate
+ with obsolete or incorrect implementations of the protocols,
+ distributed without sources, that unfortunately persist in many
+ parts of the Internet. To make correct systems coexist with
+ these faulty systems, administrators often have to "mis-
+ configure" the correct systems. This problem will correct
+ itself gradually as the faulty systems are retired, but it
+ cannot be ignored by vendors.
+
+ When we say that a parameter must be configurable, we do not
+ intend to require that its value be explicitly read from a
+ configuration file at every boot time. We recommend that
+ implementors set up a default for each parameter, so a
+ configuration file is only necessary to override those defaults
+ that are inappropriate in a particular installation. Thus, the
+ configurability requirement is an assurance that it will be
+ POSSIBLE to override the default when necessary, even in a
+ binary-only or ROM-based product.
+
+ This document requires a particular value for such defaults in
+ some cases. The choice of default is a sensitive issue when
+ the configuration item controls the accommodation to existing
+ faulty systems. If the Internet is to converge successfully to
+ complete interoperability, the default values built into
+ implementations must implement the official protocol, not
+ "mis-configurations" to accommodate faulty implementations.
+ Although marketing considerations have led some vendors to
+ choose mis-configuration defaults, we urge vendors to choose
+ defaults that will conform to the standard.
+
+ Finally, we note that a vendor needs to provide adequate
+
+
+
+Internet Engineering Task Force [Page 9]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+ documentation on all configuration parameters, their limits and
+ effects.
+
+
+ 1.3 Reading this Document
+
+ 1.3.1 Organization
+
+ In general, each major section is organized into the following
+ subsections:
+
+ (1) Introduction
+
+ (2) Protocol Walk-Through -- considers the protocol
+ specification documents section-by-section, correcting
+ errors, stating requirements that may be ambiguous or
+ ill-defined, and providing further clarification or
+ explanation.
+
+ (3) Specific Issues -- discusses protocol design and
+ implementation issues that were not included in the walk-
+ through.
+
+ (4) Interfaces -- discusses the service interface to the next
+ higher layer.
+
+ (5) Summary -- contains a summary of the requirements of the
+ section.
+
+ Under many of the individual topics in this document, there is
+ parenthetical material labeled "DISCUSSION" or
+ "IMPLEMENTATION". This material is intended to give
+ clarification and explanation of the preceding requirements
+ text. It also includes some suggestions on possible future
+ directions or developments. The implementation material
+ contains suggested approaches that an implementor may want to
+ consider.
+
+ The summary sections are intended to be guides and indexes to
+ the text, but are necessarily cryptic and incomplete. The
+ summaries should never be used or referenced separately from
+ the complete RFC.
+
+ 1.3.2 Requirements
+
+ In this document, the words that are used to define the
+ significance of each particular requirement are capitalized.
+ These words are:
+
+
+
+Internet Engineering Task Force [Page 10]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+ * "MUST"
+
+ This word or the adjective "REQUIRED" means that the item
+ is an absolute requirement of the specification.
+
+ * "SHOULD"
+
+ This word or the adjective "RECOMMENDED" means that there
+ may exist valid reasons in particular circumstances to
+ ignore this item, but the full implications should be
+ understood and the case carefully weighed before choosing
+ a different course.
+
+ * "MAY"
+
+ This word or the adjective "OPTIONAL" means that this item
+ is truly optional. One vendor may choose to include the
+ item because a particular marketplace requires it or
+ because it enhances the product, for example; another
+ vendor may omit the same item.
+
+
+ An implementation is not compliant if it fails to satisfy one
+ or more of the MUST requirements for the protocols it
+ implements. An implementation that satisfies all the MUST and
+ all the SHOULD requirements for its protocols is said to be
+ "unconditionally compliant"; one that satisfies all the MUST
+ requirements but not all the SHOULD requirements for its
+ protocols is said to be "conditionally compliant".
+
+ 1.3.3 Terminology
+
+ This document uses the following technical terms:
+
+ Segment
+ A segment is the unit of end-to-end transmission in the
+ TCP protocol. A segment consists of a TCP header followed
+ by application data. A segment is transmitted by
+ encapsulation in an IP datagram.
+
+ Message
+ This term is used by some application layer protocols
+ (particularly SMTP) for an application data unit.
+
+ Datagram
+ A [UDP] datagram is the unit of end-to-end transmission in
+ the UDP protocol.
+
+
+
+
+Internet Engineering Task Force [Page 11]
+
+
+
+
+RFC1123 INTRODUCTION October 1989
+
+
+ Multihomed
+ A host is said to be multihomed if it has multiple IP
+ addresses to connected networks.
+
+
+
+ 1.4 Acknowledgments
+
+ This document incorporates contributions and comments from a large
+ group of Internet protocol experts, including representatives of
+ university and research labs, vendors, and government agencies.
+ It was assembled primarily by the Host Requirements Working Group
+ of the Internet Engineering Task Force (IETF).
+
+ The Editor would especially like to acknowledge the tireless
+ dedication of the following people, who attended many long
+ meetings and generated 3 million bytes of electronic mail over the
+ past 18 months in pursuit of this document: Philip Almquist, Dave
+ Borman (Cray Research), Noel Chiappa, Dave Crocker (DEC), Steve
+ Deering (Stanford), Mike Karels (Berkeley), Phil Karn (Bellcore),
+ John Lekashman (NASA), Charles Lynn (BBN), Keith McCloghrie (TWG),
+ Paul Mockapetris (ISI), Thomas Narten (Purdue), Craig Partridge
+ (BBN), Drew Perkins (CMU), and James Van Bokkelen (FTP Software).
+
+ In addition, the following people made major contributions to the
+ effort: Bill Barns (Mitre), Steve Bellovin (AT&T), Mike Brescia
+ (BBN), Ed Cain (DCA), Annette DeSchon (ISI), Martin Gross (DCA),
+ Phill Gross (NRI), Charles Hedrick (Rutgers), Van Jacobson (LBL),
+ John Klensin (MIT), Mark Lottor (SRI), Milo Medin (NASA), Bill
+ Melohn (Sun Microsystems), Greg Minshall (Kinetics), Jeff Mogul
+ (DEC), John Mullen (CMC), Jon Postel (ISI), John Romkey (Epilogue
+ Technology), and Mike StJohns (DCA). The following also made
+ significant contributions to particular areas: Eric Allman
+ (Berkeley), Rob Austein (MIT), Art Berggreen (ACC), Keith Bostic
+ (Berkeley), Vint Cerf (NRI), Wayne Hathaway (NASA), Matt Korn
+ (IBM), Erik Naggum (Naggum Software, Norway), Robert Ullmann
+ (Prime Computer), David Waitzman (BBN), Frank Wancho (USA), Arun
+ Welch (Ohio State), Bill Westfield (Cisco), and Rayan Zachariassen
+ (Toronto).
+
+ We are grateful to all, including any contributors who may have
+ been inadvertently omitted from this list.
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 12]
+
+
+
+
+RFC1123 APPLICATIONS LAYER -- GENERAL October 1989
+
+
+2. GENERAL ISSUES
+
+ This section contains general requirements that may be applicable to
+ all application-layer protocols.
+
+ 2.1 Host Names and Numbers
+
+ The syntax of a legal Internet host name was specified in RFC-952
+ [DNS:4]. One aspect of host name syntax is hereby changed: the
+ restriction on the first character is relaxed to allow either a
+ letter or a digit. Host software MUST support this more liberal
+ syntax.
+
+ Host software MUST handle host names of up to 63 characters and
+ SHOULD handle host names of up to 255 characters.
+
+ Whenever a user inputs the identity of an Internet host, it SHOULD
+ be possible to enter either (1) a host domain name or (2) an IP
+ address in dotted-decimal ("#.#.#.#") form. The host SHOULD check
+ the string syntactically for a dotted-decimal number before
+ looking it up in the Domain Name System.
+
+ DISCUSSION:
+ This last requirement is not intended to specify the complete
+ syntactic form for entering a dotted-decimal host number;
+ that is considered to be a user-interface issue. For
+ example, a dotted-decimal number must be enclosed within
+ "[ ]" brackets for SMTP mail (see Section 5.2.17). This
+ notation could be made universal within a host system,
+ simplifying the syntactic checking for a dotted-decimal
+ number.
+
+ If a dotted-decimal number can be entered without such
+ identifying delimiters, then a full syntactic check must be
+ made, because a segment of a host domain name is now allowed
+ to begin with a digit and could legally be entirely numeric
+ (see Section 6.1.2.4). However, a valid host name can never
+ have the dotted-decimal form #.#.#.#, since at least the
+ highest-level component label will be alphabetic.
+
+ 2.2 Using Domain Name Service
+
+ Host domain names MUST be translated to IP addresses as described
+ in Section 6.1.
+
+ Applications using domain name services MUST be able to cope with
+ soft error conditions. Applications MUST wait a reasonable
+ interval between successive retries due to a soft error, and MUST
+
+
+
+Internet Engineering Task Force [Page 13]
+
+
+
+
+RFC1123 APPLICATIONS LAYER -- GENERAL October 1989
+
+
+ allow for the possibility that network problems may deny service
+ for hours or even days.
+
+ An application SHOULD NOT rely on the ability to locate a WKS
+ record containing an accurate listing of all services at a
+ particular host address, since the WKS RR type is not often used
+ by Internet sites. To confirm that a service is present, simply
+ attempt to use it.
+
+ 2.3 Applications on Multihomed hosts
+
+ When the remote host is multihomed, the name-to-address
+ translation will return a list of alternative IP addresses. As
+ specified in Section 6.1.3.4, this list should be in order of
+ decreasing preference. Application protocol implementations
+ SHOULD be prepared to try multiple addresses from the list until
+ success is obtained. More specific requirements for SMTP are
+ given in Section 5.3.4.
+
+ When the local host is multihomed, a UDP-based request/response
+ application SHOULD send the response with an IP source address
+ that is the same as the specific destination address of the UDP
+ request datagram. The "specific destination address" is defined
+ in the "IP Addressing" section of the companion RFC [INTRO:1].
+
+ Similarly, a server application that opens multiple TCP
+ connections to the same client SHOULD use the same local IP
+ address for all.
+
+ 2.4 Type-of-Service
+
+ Applications MUST select appropriate TOS values when they invoke
+ transport layer services, and these values MUST be configurable.
+ Note that a TOS value contains 5 bits, of which only the most-
+ significant 3 bits are currently defined; the other two bits MUST
+ be zero.
+
+ DISCUSSION:
+ As gateway algorithms are developed to implement Type-of-
+ Service, the recommended values for various application
+ protocols may change. In addition, it is likely that
+ particular combinations of users and Internet paths will want
+ non-standard TOS values. For these reasons, the TOS values
+ must be configurable.
+
+ See the latest version of the "Assigned Numbers" RFC
+ [INTRO:5] for the recommended TOS values for the major
+ application protocols.
+
+
+
+Internet Engineering Task Force [Page 14]
+
+
+
+
+RFC1123 APPLICATIONS LAYER -- GENERAL October 1989
+
+
+ 2.5 GENERAL APPLICATION REQUIREMENTS SUMMARY
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION | | | |T|T|e
+-----------------------------------------------|----------|-|-|-|-|-|--
+ | | | | | | |
+User interfaces: | | | | | | |
+ Allow host name to begin with digit |2.1 |x| | | | |
+ Host names of up to 635 characters |2.1 |x| | | | |
+ Host names of up to 255 characters |2.1 | |x| | | |
+ Support dotted-decimal host numbers |2.1 | |x| | | |
+ Check syntactically for dotted-dec first |2.1 | |x| | | |
+ | | | | | | |
+Map domain names per Section 6.1 |2.2 |x| | | | |
+Cope with soft DNS errors |2.2 |x| | | | |
+ Reasonable interval between retries |2.2 |x| | | | |
+ Allow for long outages |2.2 |x| | | | |
+Expect WKS records to be available |2.2 | | | |x| |
+ | | | | | | |
+Try multiple addr's for remote multihomed host |2.3 | |x| | | |
+UDP reply src addr is specific dest of request |2.3 | |x| | | |
+Use same IP addr for related TCP connections |2.3 | |x| | | |
+Specify appropriate TOS values |2.4 |x| | | | |
+ TOS values configurable |2.4 |x| | | | |
+ Unused TOS bits zero |2.4 |x| | | | |
+ | | | | | | |
+ | | | | | | |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 15]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+3. REMOTE LOGIN -- TELNET PROTOCOL
+
+ 3.1 INTRODUCTION
+
+ Telnet is the standard Internet application protocol for remote
+ login. It provides the encoding rules to link a user's
+ keyboard/display on a client ("user") system with a command
+ interpreter on a remote server system. A subset of the Telnet
+ protocol is also incorporated within other application protocols,
+ e.g., FTP and SMTP.
+
+ Telnet uses a single TCP connection, and its normal data stream
+ ("Network Virtual Terminal" or "NVT" mode) is 7-bit ASCII with
+ escape sequences to embed control functions. Telnet also allows
+ the negotiation of many optional modes and functions.
+
+ The primary Telnet specification is to be found in RFC-854
+ [TELNET:1], while the options are defined in many other RFCs; see
+ Section 7 for references.
+
+ 3.2 PROTOCOL WALK-THROUGH
+
+ 3.2.1 Option Negotiation: RFC-854, pp. 2-3
+
+ Every Telnet implementation MUST include option negotiation and
+ subnegotiation machinery [TELNET:2].
+
+ A host MUST carefully follow the rules of RFC-854 to avoid
+ option-negotiation loops. A host MUST refuse (i.e, reply
+ WONT/DONT to a DO/WILL) an unsupported option. Option
+ negotiation SHOULD continue to function (even if all requests
+ are refused) throughout the lifetime of a Telnet connection.
+
+ If all option negotiations fail, a Telnet implementation MUST
+ default to, and support, an NVT.
+
+ DISCUSSION:
+ Even though more sophisticated "terminals" and supporting
+ option negotiations are becoming the norm, all
+ implementations must be prepared to support an NVT for any
+ user-server communication.
+
+ 3.2.2 Telnet Go-Ahead Function: RFC-854, p. 5, and RFC-858
+
+ On a host that never sends the Telnet command Go Ahead (GA),
+ the Telnet Server MUST attempt to negotiate the Suppress Go
+ Ahead option (i.e., send "WILL Suppress Go Ahead"). A User or
+ Server Telnet MUST always accept negotiation of the Suppress Go
+
+
+
+Internet Engineering Task Force [Page 16]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ Ahead option.
+
+ When it is driving a full-duplex terminal for which GA has no
+ meaning, a User Telnet implementation MAY ignore GA commands.
+
+ DISCUSSION:
+ Half-duplex ("locked-keyboard") line-at-a-time terminals
+ for which the Go-Ahead mechanism was designed have largely
+ disappeared from the scene. It turned out to be difficult
+ to implement sending the Go-Ahead signal in many operating
+ systems, even some systems that support native half-duplex
+ terminals. The difficulty is typically that the Telnet
+ server code does not have access to information about
+ whether the user process is blocked awaiting input from
+ the Telnet connection, i.e., it cannot reliably determine
+ when to send a GA command. Therefore, most Telnet Server
+ hosts do not send GA commands.
+
+ The effect of the rules in this section is to allow either
+ end of a Telnet connection to veto the use of GA commands.
+
+ There is a class of half-duplex terminals that is still
+ commercially important: "data entry terminals," which
+ interact in a full-screen manner. However, supporting
+ data entry terminals using the Telnet protocol does not
+ require the Go Ahead signal; see Section 3.3.2.
+
+ 3.2.3 Control Functions: RFC-854, pp. 7-8
+
+ The list of Telnet commands has been extended to include EOR
+ (End-of-Record), with code 239 [TELNET:9].
+
+ Both User and Server Telnets MAY support the control functions
+ EOR, EC, EL, and Break, and MUST support AO, AYT, DM, IP, NOP,
+ SB, and SE.
+
+ A host MUST be able to receive and ignore any Telnet control
+ functions that it does not support.
+
+ DISCUSSION:
+ Note that a Server Telnet is required to support the
+ Telnet IP (Interrupt Process) function, even if the server
+ host has an equivalent in-stream function (e.g., Control-C
+ in many systems). The Telnet IP function may be stronger
+ than an in-stream interrupt command, because of the out-
+ of-band effect of TCP urgent data.
+
+ The EOR control function may be used to delimit the
+
+
+
+Internet Engineering Task Force [Page 17]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ stream. An important application is data entry terminal
+ support (see Section 3.3.2). There was concern that since
+ EOR had not been defined in RFC-854, a host that was not
+ prepared to correctly ignore unknown Telnet commands might
+ crash if it received an EOR. To protect such hosts, the
+ End-of-Record option [TELNET:9] was introduced; however, a
+ properly implemented Telnet program will not require this
+ protection.
+
+ 3.2.4 Telnet "Synch" Signal: RFC-854, pp. 8-10
+
+ When it receives "urgent" TCP data, a User or Server Telnet
+ MUST discard all data except Telnet commands until the DM (and
+ end of urgent) is reached.
+
+ When it sends Telnet IP (Interrupt Process), a User Telnet
+ SHOULD follow it by the Telnet "Synch" sequence, i.e., send as
+ TCP urgent data the sequence "IAC IP IAC DM". The TCP urgent
+ pointer points to the DM octet.
+
+ When it receives a Telnet IP command, a Server Telnet MAY send
+ a Telnet "Synch" sequence back to the user, to flush the output
+ stream. The choice ought to be consistent with the way the
+ server operating system behaves when a local user interrupts a
+ process.
+
+ When it receives a Telnet AO command, a Server Telnet MUST send
+ a Telnet "Synch" sequence back to the user, to flush the output
+ stream.
+
+ A User Telnet SHOULD have the capability of flushing output
+ when it sends a Telnet IP; see also Section 3.4.5.
+
+ DISCUSSION:
+ There are three possible ways for a User Telnet to flush
+ the stream of server output data:
+
+ (1) Send AO after IP.
+
+ This will cause the server host to send a "flush-
+ buffered-output" signal to its operating system.
+ However, the AO may not take effect locally, i.e.,
+ stop terminal output at the User Telnet end, until
+ the Server Telnet has received and processed the AO
+ and has sent back a "Synch".
+
+ (2) Send DO TIMING-MARK [TELNET:7] after IP, and discard
+ all output locally until a WILL/WONT TIMING-MARK is
+
+
+
+Internet Engineering Task Force [Page 18]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ received from the Server Telnet.
+
+ Since the DO TIMING-MARK will be processed after the
+ IP at the server, the reply to it should be in the
+ right place in the output data stream. However, the
+ TIMING-MARK will not send a "flush buffered output"
+ signal to the server operating system. Whether or
+ not this is needed is dependent upon the server
+ system.
+
+ (3) Do both.
+
+ The best method is not entirely clear, since it must
+ accommodate a number of existing server hosts that do not
+ follow the Telnet standards in various ways. The safest
+ approach is probably to provide a user-controllable option
+ to select (1), (2), or (3).
+
+ 3.2.5 NVT Printer and Keyboard: RFC-854, p. 11
+
+ In NVT mode, a Telnet SHOULD NOT send characters with the
+ high-order bit 1, and MUST NOT send it as a parity bit.
+ Implementations that pass the high-order bit to applications
+ SHOULD negotiate binary mode (see Section 3.2.6).
+
+
+ DISCUSSION:
+ Implementors should be aware that a strict reading of
+ RFC-854 allows a client or server expecting NVT ASCII to
+ ignore characters with the high-order bit set. In
+ general, binary mode is expected to be used for
+ transmission of an extended (beyond 7-bit) character set
+ with Telnet.
+
+ However, there exist applications that really need an 8-
+ bit NVT mode, which is currently not defined, and these
+ existing applications do set the high-order bit during
+ part or all of the life of a Telnet connection. Note that
+ binary mode is not the same as 8-bit NVT mode, since
+ binary mode turns off end-of-line processing. For this
+ reason, the requirements on the high-order bit are stated
+ as SHOULD, not MUST.
+
+ RFC-854 defines a minimal set of properties of a "network
+ virtual terminal" or NVT; this is not meant to preclude
+ additional features in a real terminal. A Telnet
+ connection is fully transparent to all 7-bit ASCII
+ characters, including arbitrary ASCII control characters.
+
+
+
+Internet Engineering Task Force [Page 19]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ For example, a terminal might support full-screen commands
+ coded as ASCII escape sequences; a Telnet implementation
+ would pass these sequences as uninterpreted data. Thus,
+ an NVT should not be conceived as a terminal type of a
+ highly-restricted device.
+
+ 3.2.6 Telnet Command Structure: RFC-854, p. 13
+
+ Since options may appear at any point in the data stream, a
+ Telnet escape character (known as IAC, with the value 255) to
+ be sent as data MUST be doubled.
+
+ 3.2.7 Telnet Binary Option: RFC-856
+
+ When the Binary option has been successfully negotiated,
+ arbitrary 8-bit characters are allowed. However, the data
+ stream MUST still be scanned for IAC characters, any embedded
+ Telnet commands MUST be obeyed, and data bytes equal to IAC
+ MUST be doubled. Other character processing (e.g., replacing
+ CR by CR NUL or by CR LF) MUST NOT be done. In particular,
+ there is no end-of-line convention (see Section 3.3.1) in
+ binary mode.
+
+ DISCUSSION:
+ The Binary option is normally negotiated in both
+ directions, to change the Telnet connection from NVT mode
+ to "binary mode".
+
+ The sequence IAC EOR can be used to delimit blocks of data
+ within a binary-mode Telnet stream.
+
+ 3.2.8 Telnet Terminal-Type Option: RFC-1091
+
+ The Terminal-Type option MUST use the terminal type names
+ officially defined in the Assigned Numbers RFC [INTRO:5], when
+ they are available for the particular terminal. However, the
+ receiver of a Terminal-Type option MUST accept any name.
+
+ DISCUSSION:
+ RFC-1091 [TELNET:10] updates an earlier version of the
+ Terminal-Type option defined in RFC-930. The earlier
+ version allowed a server host capable of supporting
+ multiple terminal types to learn the type of a particular
+ client's terminal, assuming that each physical terminal
+ had an intrinsic type. However, today a "terminal" is
+ often really a terminal emulator program running in a PC,
+ perhaps capable of emulating a range of terminal types.
+ Therefore, RFC-1091 extends the specification to allow a
+
+
+
+Internet Engineering Task Force [Page 20]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ more general terminal-type negotiation between User and
+ Server Telnets.
+
+ 3.3 SPECIFIC ISSUES
+
+ 3.3.1 Telnet End-of-Line Convention
+
+ The Telnet protocol defines the sequence CR LF to mean "end-
+ of-line". For terminal input, this corresponds to a command-
+ completion or "end-of-line" key being pressed on a user
+ terminal; on an ASCII terminal, this is the CR key, but it may
+ also be labelled "Return" or "Enter".
+
+ When a Server Telnet receives the Telnet end-of-line sequence
+ CR LF as input from a remote terminal, the effect MUST be the
+ same as if the user had pressed the "end-of-line" key on a
+ local terminal. On server hosts that use ASCII, in particular,
+ receipt of the Telnet sequence CR LF must cause the same effect
+ as a local user pressing the CR key on a local terminal. Thus,
+ CR LF and CR NUL MUST have the same effect on an ASCII server
+ host when received as input over a Telnet connection.
+
+ A User Telnet MUST be able to send any of the forms: CR LF, CR
+ NUL, and LF. A User Telnet on an ASCII host SHOULD have a
+ user-controllable mode to send either CR LF or CR NUL when the
+ user presses the "end-of-line" key, and CR LF SHOULD be the
+ default.
+
+ The Telnet end-of-line sequence CR LF MUST be used to send
+ Telnet data that is not terminal-to-computer (e.g., for Server
+ Telnet sending output, or the Telnet protocol incorporated
+ another application protocol).
+
+ DISCUSSION:
+ To allow interoperability between arbitrary Telnet clients
+ and servers, the Telnet protocol defined a standard
+ representation for a line terminator. Since the ASCII
+ character set includes no explicit end-of-line character,
+ systems have chosen various representations, e.g., CR, LF,
+ and the sequence CR LF. The Telnet protocol chose the CR
+ LF sequence as the standard for network transmission.
+
+ Unfortunately, the Telnet protocol specification in RFC-
+ 854 [TELNET:1] has turned out to be somewhat ambiguous on
+ what character(s) should be sent from client to server for
+ the "end-of-line" key. The result has been a massive and
+ continuing interoperability headache, made worse by
+ various faulty implementations of both User and Server
+
+
+
+Internet Engineering Task Force [Page 21]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ Telnets.
+
+ Although the Telnet protocol is based on a perfectly
+ symmetric model, in a remote login session the role of the
+ user at a terminal differs from the role of the server
+ host. For example, RFC-854 defines the meaning of CR, LF,
+ and CR LF as output from the server, but does not specify
+ what the User Telnet should send when the user presses the
+ "end-of-line" key on the terminal; this turns out to be
+ the point at issue.
+
+ When a user presses the "end-of-line" key, some User
+ Telnet implementations send CR LF, while others send CR
+ NUL (based on a different interpretation of the same
+ sentence in RFC-854). These will be equivalent for a
+ correctly-implemented ASCII server host, as discussed
+ above. For other servers, a mode in the User Telnet is
+ needed.
+
+ The existence of User Telnets that send only CR NUL when
+ CR is pressed creates a dilemma for non-ASCII hosts: they
+ can either treat CR NUL as equivalent to CR LF in input,
+ thus precluding the possibility of entering a "bare" CR,
+ or else lose complete interworking.
+
+ Suppose a user on host A uses Telnet to log into a server
+ host B, and then execute B's User Telnet program to log
+ into server host C. It is desirable for the Server/User
+ Telnet combination on B to be as transparent as possible,
+ i.e., to appear as if A were connected directly to C. In
+ particular, correct implementation will make B transparent
+ to Telnet end-of-line sequences, except that CR LF may be
+ translated to CR NUL or vice versa.
+
+ IMPLEMENTATION:
+ To understand Telnet end-of-line issues, one must have at
+ least a general model of the relationship of Telnet to the
+ local operating system. The Server Telnet process is
+ typically coupled into the terminal driver software of the
+ operating system as a pseudo-terminal. A Telnet end-of-
+ line sequence received by the Server Telnet must have the
+ same effect as pressing the end-of-line key on a real
+ locally-connected terminal.
+
+ Operating systems that support interactive character-at-
+ a-time applications (e.g., editors) typically have two
+ internal modes for their terminal I/O: a formatted mode,
+ in which local conventions for end-of-line and other
+
+
+
+Internet Engineering Task Force [Page 22]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ formatting rules have been applied to the data stream, and
+ a "raw" mode, in which the application has direct access
+ to every character as it was entered. A Server Telnet
+ must be implemented in such a way that these modes have
+ the same effect for remote as for local terminals. For
+ example, suppose a CR LF or CR NUL is received by the
+ Server Telnet on an ASCII host. In raw mode, a CR
+ character is passed to the application; in formatted mode,
+ the local system's end-of-line convention is used.
+
+ 3.3.2 Data Entry Terminals
+
+ DISCUSSION:
+ In addition to the line-oriented and character-oriented
+ ASCII terminals for which Telnet was designed, there are
+ several families of video display terminals that are
+ sometimes known as "data entry terminals" or DETs. The
+ IBM 3270 family is a well-known example.
+
+ Two Internet protocols have been designed to support
+ generic DETs: SUPDUP [TELNET:16, TELNET:17], and the DET
+ option [TELNET:18, TELNET:19]. The DET option drives a
+ data entry terminal over a Telnet connection using (sub-)
+ negotiation. SUPDUP is a completely separate terminal
+ protocol, which can be entered from Telnet by negotiation.
+ Although both SUPDUP and the DET option have been used
+ successfully in particular environments, neither has
+ gained general acceptance or wide implementation.
+
+ A different approach to DET interaction has been developed
+ for supporting the IBM 3270 family through Telnet,
+ although the same approach would be applicable to any DET.
+ The idea is to enter a "native DET" mode, in which the
+ native DET input/output stream is sent as binary data.
+ The Telnet EOR command is used to delimit logical records
+ (e.g., "screens") within this binary stream.
+
+ IMPLEMENTATION:
+ The rules for entering and leaving native DET mode are as
+ follows:
+
+ o The Server uses the Terminal-Type option [TELNET:10]
+ to learn that the client is a DET.
+
+ o It is conventional, but not required, that both ends
+ negotiate the EOR option [TELNET:9].
+
+ o Both ends negotiate the Binary option [TELNET:3] to
+
+
+
+Internet Engineering Task Force [Page 23]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ enter native DET mode.
+
+ o When either end negotiates out of binary mode, the
+ other end does too, and the mode then reverts to
+ normal NVT.
+
+
+ 3.3.3 Option Requirements
+
+ Every Telnet implementation MUST support the Binary option
+ [TELNET:3] and the Suppress Go Ahead option [TELNET:5], and
+ SHOULD support the Echo [TELNET:4], Status [TELNET:6], End-of-
+ Record [TELNET:9], and Extended Options List [TELNET:8]
+ options.
+
+ A User or Server Telnet SHOULD support the Window Size Option
+ [TELNET:12] if the local operating system provides the
+ corresponding capability.
+
+ DISCUSSION:
+ Note that the End-of-Record option only signifies that a
+ Telnet can receive a Telnet EOR without crashing;
+ therefore, every Telnet ought to be willing to accept
+ negotiation of the End-of-Record option. See also the
+ discussion in Section 3.2.3.
+
+ 3.3.4 Option Initiation
+
+ When the Telnet protocol is used in a client/server situation,
+ the server SHOULD initiate negotiation of the terminal
+ interaction mode it expects.
+
+ DISCUSSION:
+ The Telnet protocol was defined to be perfectly
+ symmetrical, but its application is generally asymmetric.
+ Remote login has been known to fail because NEITHER side
+ initiated negotiation of the required non-default terminal
+ modes. It is generally the server that determines the
+ preferred mode, so the server needs to initiate the
+ negotiation; since the negotiation is symmetric, the user
+ can also initiate it.
+
+ A client (User Telnet) SHOULD provide a means for users to
+ enable and disable the initiation of option negotiation.
+
+ DISCUSSION:
+ A user sometimes needs to connect to an application
+ service (e.g., FTP or SMTP) that uses Telnet for its
+
+
+
+Internet Engineering Task Force [Page 24]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ control stream but does not support Telnet options. User
+ Telnet may be used for this purpose if initiation of
+ option negotiation is disabled.
+
+ 3.3.5 Telnet Linemode Option
+
+ DISCUSSION:
+ An important new Telnet option, LINEMODE [TELNET:12], has
+ been proposed. The LINEMODE option provides a standard
+ way for a User Telnet and a Server Telnet to agree that
+ the client rather than the server will perform terminal
+ character processing. When the client has prepared a
+ complete line of text, it will send it to the server in
+ (usually) one TCP packet. This option will greatly
+ decrease the packet cost of Telnet sessions and will also
+ give much better user response over congested or long-
+ delay networks.
+
+ The LINEMODE option allows dynamic switching between local
+ and remote character processing. For example, the Telnet
+ connection will automatically negotiate into single-
+ character mode while a full screen editor is running, and
+ then return to linemode when the editor is finished.
+
+ We expect that when this RFC is released, hosts should
+ implement the client side of this option, and may
+ implement the server side of this option. To properly
+ implement the server side, the server needs to be able to
+ tell the local system not to do any input character
+ processing, but to remember its current terminal state and
+ notify the Server Telnet process whenever the state
+ changes. This will allow password echoing and full screen
+ editors to be handled properly, for example.
+
+ 3.4 TELNET/USER INTERFACE
+
+ 3.4.1 Character Set Transparency
+
+ User Telnet implementations SHOULD be able to send or receive
+ any 7-bit ASCII character. Where possible, any special
+ character interpretations by the user host's operating system
+ SHOULD be bypassed so that these characters can conveniently be
+ sent and received on the connection.
+
+ Some character value MUST be reserved as "escape to command
+ mode"; conventionally, doubling this character allows it to be
+ entered as data. The specific character used SHOULD be user
+ selectable.
+
+
+
+Internet Engineering Task Force [Page 25]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ On binary-mode connections, a User Telnet program MAY provide
+ an escape mechanism for entering arbitrary 8-bit values, if the
+ host operating system doesn't allow them to be entered directly
+ from the keyboard.
+
+ IMPLEMENTATION:
+ The transparency issues are less pressing on servers, but
+ implementors should take care in dealing with issues like:
+ masking off parity bits (sent by an older, non-conforming
+ client) before they reach programs that expect only NVT
+ ASCII, and properly handling programs that request 8-bit
+ data streams.
+
+ 3.4.2 Telnet Commands
+
+ A User Telnet program MUST provide a user the capability of
+ entering any of the Telnet control functions IP, AO, or AYT,
+ and SHOULD provide the capability of entering EC, EL, and
+ Break.
+
+ 3.4.3 TCP Connection Errors
+
+ A User Telnet program SHOULD report to the user any TCP errors
+ that are reported by the transport layer (see "TCP/Application
+ Layer Interface" section in [INTRO:1]).
+
+ 3.4.4 Non-Default Telnet Contact Port
+
+ A User Telnet program SHOULD allow the user to optionally
+ specify a non-standard contact port number at the Server Telnet
+ host.
+
+ 3.4.5 Flushing Output
+
+ A User Telnet program SHOULD provide the user the ability to
+ specify whether or not output should be flushed when an IP is
+ sent; see Section 3.2.4.
+
+ For any output flushing scheme that causes the User Telnet to
+ flush output locally until a Telnet signal is received from the
+ Server, there SHOULD be a way for the user to manually restore
+ normal output, in case the Server fails to send the expected
+ signal.
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 26]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ 3.5. TELNET REQUIREMENTS SUMMARY
+
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION | | | |T|T|e
+-------------------------------------------------|--------|-|-|-|-|-|--
+ | | | | | | |
+Option Negotiation |3.2.1 |x| | | | |
+ Avoid negotiation loops |3.2.1 |x| | | | |
+ Refuse unsupported options |3.2.1 |x| | | | |
+ Negotiation OK anytime on connection |3.2.1 | |x| | | |
+ Default to NVT |3.2.1 |x| | | | |
+ Send official name in Term-Type option |3.2.8 |x| | | | |
+ Accept any name in Term-Type option |3.2.8 |x| | | | |
+ Implement Binary, Suppress-GA options |3.3.3 |x| | | | |
+ Echo, Status, EOL, Ext-Opt-List options |3.3.3 | |x| | | |
+ Implement Window-Size option if appropriate |3.3.3 | |x| | | |
+ Server initiate mode negotiations |3.3.4 | |x| | | |
+ User can enable/disable init negotiations |3.3.4 | |x| | | |
+ | | | | | | |
+Go-Aheads | | | | | | |
+ Non-GA server negotiate SUPPRESS-GA option |3.2.2 |x| | | | |
+ User or Server accept SUPPRESS-GA option |3.2.2 |x| | | | |
+ User Telnet ignore GA's |3.2.2 | | |x| | |
+ | | | | | | |
+Control Functions | | | | | | |
+ Support SE NOP DM IP AO AYT SB |3.2.3 |x| | | | |
+ Support EOR EC EL Break |3.2.3 | | |x| | |
+ Ignore unsupported control functions |3.2.3 |x| | | | |
+ User, Server discard urgent data up to DM |3.2.4 |x| | | | |
+ User Telnet send "Synch" after IP, AO, AYT |3.2.4 | |x| | | |
+ Server Telnet reply Synch to IP |3.2.4 | | |x| | |
+ Server Telnet reply Synch to AO |3.2.4 |x| | | | |
+ User Telnet can flush output when send IP |3.2.4 | |x| | | |
+ | | | | | | |
+Encoding | | | | | | |
+ Send high-order bit in NVT mode |3.2.5 | | | |x| |
+ Send high-order bit as parity bit |3.2.5 | | | | |x|
+ Negot. BINARY if pass high-ord. bit to applic |3.2.5 | |x| | | |
+ Always double IAC data byte |3.2.6 |x| | | | |
+
+
+
+Internet Engineering Task Force [Page 27]
+
+
+
+
+RFC1123 REMOTE LOGIN -- TELNET October 1989
+
+
+ Double IAC data byte in binary mode |3.2.7 |x| | | | |
+ Obey Telnet cmds in binary mode |3.2.7 |x| | | | |
+ End-of-line, CR NUL in binary mode |3.2.7 | | | | |x|
+ | | | | | | |
+End-of-Line | | | | | | |
+ EOL at Server same as local end-of-line |3.3.1 |x| | | | |
+ ASCII Server accept CR LF or CR NUL for EOL |3.3.1 |x| | | | |
+ User Telnet able to send CR LF, CR NUL, or LF |3.3.1 |x| | | | |
+ ASCII user able to select CR LF/CR NUL |3.3.1 | |x| | | |
+ User Telnet default mode is CR LF |3.3.1 | |x| | | |
+ Non-interactive uses CR LF for EOL |3.3.1 |x| | | | |
+ | | | | | | |
+User Telnet interface | | | | | | |
+ Input & output all 7-bit characters |3.4.1 | |x| | | |
+ Bypass local op sys interpretation |3.4.1 | |x| | | |
+ Escape character |3.4.1 |x| | | | |
+ User-settable escape character |3.4.1 | |x| | | |
+ Escape to enter 8-bit values |3.4.1 | | |x| | |
+ Can input IP, AO, AYT |3.4.2 |x| | | | |
+ Can input EC, EL, Break |3.4.2 | |x| | | |
+ Report TCP connection errors to user |3.4.3 | |x| | | |
+ Optional non-default contact port |3.4.4 | |x| | | |
+ Can spec: output flushed when IP sent |3.4.5 | |x| | | |
+ Can manually restore output mode |3.4.5 | |x| | | |
+ | | | | | | |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 28]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+4. FILE TRANSFER
+
+ 4.1 FILE TRANSFER PROTOCOL -- FTP
+
+ 4.1.1 INTRODUCTION
+
+ The File Transfer Protocol FTP is the primary Internet standard
+ for file transfer. The current specification is contained in
+ RFC-959 [FTP:1].
+
+ FTP uses separate simultaneous TCP connections for control and
+ for data transfer. The FTP protocol includes many features,
+ some of which are not commonly implemented. However, for every
+ feature in FTP, there exists at least one implementation. The
+ minimum implementation defined in RFC-959 was too small, so a
+ somewhat larger minimum implementation is defined here.
+
+ Internet users have been unnecessarily burdened for years by
+ deficient FTP implementations. Protocol implementors have
+ suffered from the erroneous opinion that implementing FTP ought
+ to be a small and trivial task. This is wrong, because FTP has
+ a user interface, because it has to deal (correctly) with the
+ whole variety of communication and operating system errors that
+ may occur, and because it has to handle the great diversity of
+ real file systems in the world.
+
+ 4.1.2. PROTOCOL WALK-THROUGH
+
+ 4.1.2.1 LOCAL Type: RFC-959 Section 3.1.1.4
+
+ An FTP program MUST support TYPE I ("IMAGE" or binary type)
+ as well as TYPE L 8 ("LOCAL" type with logical byte size 8).
+ A machine whose memory is organized into m-bit words, where
+ m is not a multiple of 8, MAY also support TYPE L m.
+
+ DISCUSSION:
+ The command "TYPE L 8" is often required to transfer
+ binary data between a machine whose memory is organized
+ into (e.g.) 36-bit words and a machine with an 8-bit
+ byte organization. For an 8-bit byte machine, TYPE L 8
+ is equivalent to IMAGE.
+
+ "TYPE L m" is sometimes specified to the FTP programs
+ on two m-bit word machines to ensure the correct
+ transfer of a native-mode binary file from one machine
+ to the other. However, this command should have the
+ same effect on these machines as "TYPE I".
+
+
+
+
+Internet Engineering Task Force [Page 29]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ 4.1.2.2 Telnet Format Control: RFC-959 Section 3.1.1.5.2
+
+ A host that makes no distinction between TYPE N and TYPE T
+ SHOULD implement TYPE T to be identical to TYPE N.
+
+ DISCUSSION:
+ This provision should ease interoperation with hosts
+ that do make this distinction.
+
+ Many hosts represent text files internally as strings
+ of ASCII characters, using the embedded ASCII format
+ effector characters (LF, BS, FF, ...) to control the
+ format when a file is printed. For such hosts, there
+ is no distinction between "print" files and other
+ files. However, systems that use record structured
+ files typically need a special format for printable
+ files (e.g., ASA carriage control). For the latter
+ hosts, FTP allows a choice of TYPE N or TYPE T.
+
+ 4.1.2.3 Page Structure: RFC-959 Section 3.1.2.3 and Appendix I
+
+ Implementation of page structure is NOT RECOMMENDED in
+ general. However, if a host system does need to implement
+ FTP for "random access" or "holey" files, it MUST use the
+ defined page structure format rather than define a new
+ private FTP format.
+
+ 4.1.2.4 Data Structure Transformations: RFC-959 Section 3.1.2
+
+ An FTP transformation between record-structure and file-
+ structure SHOULD be invertible, to the extent possible while
+ making the result useful on the target host.
+
+ DISCUSSION:
+ RFC-959 required strict invertibility between record-
+ structure and file-structure, but in practice,
+ efficiency and convenience often preclude it.
+ Therefore, the requirement is being relaxed. There are
+ two different objectives for transferring a file:
+ processing it on the target host, or just storage. For
+ storage, strict invertibility is important. For
+ processing, the file created on the target host needs
+ to be in the format expected by application programs on
+ that host.
+
+ As an example of the conflict, imagine a record-
+ oriented operating system that requires some data files
+ to have exactly 80 bytes in each record. While STORing
+
+
+
+Internet Engineering Task Force [Page 30]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ a file on such a host, an FTP Server must be able to
+ pad each line or record to 80 bytes; a later retrieval
+ of such a file cannot be strictly invertible.
+
+ 4.1.2.5 Data Connection Management: RFC-959 Section 3.3
+
+ A User-FTP that uses STREAM mode SHOULD send a PORT command
+ to assign a non-default data port before each transfer
+ command is issued.
+
+ DISCUSSION:
+ This is required because of the long delay after a TCP
+ connection is closed until its socket pair can be
+ reused, to allow multiple transfers during a single FTP
+ session. Sending a port command can avoided if a
+ transfer mode other than stream is used, by leaving the
+ data transfer connection open between transfers.
+
+ 4.1.2.6 PASV Command: RFC-959 Section 4.1.2
+
+ A server-FTP MUST implement the PASV command.
+
+ If multiple third-party transfers are to be executed during
+ the same session, a new PASV command MUST be issued before
+ each transfer command, to obtain a unique port pair.
+
+ IMPLEMENTATION:
+ The format of the 227 reply to a PASV command is not
+ well standardized. In particular, an FTP client cannot
+ assume that the parentheses shown on page 40 of RFC-959
+ will be present (and in fact, Figure 3 on page 43 omits
+ them). Therefore, a User-FTP program that interprets
+ the PASV reply must scan the reply for the first digit
+ of the host and port numbers.
+
+ Note that the host number h1,h2,h3,h4 is the IP address
+ of the server host that is sending the reply, and that
+ p1,p2 is a non-default data transfer port that PASV has
+ assigned.
+
+ 4.1.2.7 LIST and NLST Commands: RFC-959 Section 4.1.3
+
+ The data returned by an NLST command MUST contain only a
+ simple list of legal pathnames, such that the server can use
+ them directly as the arguments of subsequent data transfer
+ commands for the individual files.
+
+ The data returned by a LIST or NLST command SHOULD use an
+
+
+
+Internet Engineering Task Force [Page 31]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ implied TYPE AN, unless the current type is EBCDIC, in which
+ case an implied TYPE EN SHOULD be used.
+
+ DISCUSSION:
+ Many FTP clients support macro-commands that will get
+ or put files matching a wildcard specification, using
+ NLST to obtain a list of pathnames. The expansion of
+ "multiple-put" is local to the client, but "multiple-
+ get" requires cooperation by the server.
+
+ The implied type for LIST and NLST is designed to
+ provide compatibility with existing User-FTPs, and in
+ particular with multiple-get commands.
+
+ 4.1.2.8 SITE Command: RFC-959 Section 4.1.3
+
+ A Server-FTP SHOULD use the SITE command for non-standard
+ features, rather than invent new private commands or
+ unstandardized extensions to existing commands.
+
+ 4.1.2.9 STOU Command: RFC-959 Section 4.1.3
+
+ The STOU command stores into a uniquely named file. When it
+ receives an STOU command, a Server-FTP MUST return the
+ actual file name in the "125 Transfer Starting" or the "150
+ Opening Data Connection" message that precedes the transfer
+ (the 250 reply code mentioned in RFC-959 is incorrect). The
+ exact format of these messages is hereby defined to be as
+ follows:
+
+ 125 FILE: pppp
+ 150 FILE: pppp
+
+ where pppp represents the unique pathname of the file that
+ will be written.
+
+ 4.1.2.10 Telnet End-of-line Code: RFC-959, Page 34
+
+ Implementors MUST NOT assume any correspondence between READ
+ boundaries on the control connection and the Telnet EOL
+ sequences (CR LF).
+
+ DISCUSSION:
+ Thus, a server-FTP (or User-FTP) must continue reading
+ characters from the control connection until a complete
+ Telnet EOL sequence is encountered, before processing
+ the command (or response, respectively). Conversely, a
+ single READ from the control connection may include
+
+
+
+Internet Engineering Task Force [Page 32]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ more than one FTP command.
+
+ 4.1.2.11 FTP Replies: RFC-959 Section 4.2, Page 35
+
+ A Server-FTP MUST send only correctly formatted replies on
+ the control connection. Note that RFC-959 (unlike earlier
+ versions of the FTP spec) contains no provision for a
+ "spontaneous" reply message.
+
+ A Server-FTP SHOULD use the reply codes defined in RFC-959
+ whenever they apply. However, a server-FTP MAY use a
+ different reply code when needed, as long as the general
+ rules of Section 4.2 are followed. When the implementor has
+ a choice between a 4xx and 5xx reply code, a Server-FTP
+ SHOULD send a 4xx (temporary failure) code when there is any
+ reasonable possibility that a failed FTP will succeed a few
+ hours later.
+
+ A User-FTP SHOULD generally use only the highest-order digit
+ of a 3-digit reply code for making a procedural decision, to
+ prevent difficulties when a Server-FTP uses non-standard
+ reply codes.
+
+ A User-FTP MUST be able to handle multi-line replies. If
+ the implementation imposes a limit on the number of lines
+ and if this limit is exceeded, the User-FTP MUST recover,
+ e.g., by ignoring the excess lines until the end of the
+ multi-line reply is reached.
+
+ A User-FTP SHOULD NOT interpret a 421 reply code ("Service
+ not available, closing control connection") specially, but
+ SHOULD detect closing of the control connection by the
+ server.
+
+ DISCUSSION:
+ Server implementations that fail to strictly follow the
+ reply rules often cause FTP user programs to hang.
+ Note that RFC-959 resolved ambiguities in the reply
+ rules found in earlier FTP specifications and must be
+ followed.
+
+ It is important to choose FTP reply codes that properly
+ distinguish between temporary and permanent failures,
+ to allow the successful use of file transfer client
+ daemons. These programs depend on the reply codes to
+ decide whether or not to retry a failed transfer; using
+ a permanent failure code (5xx) for a temporary error
+ will cause these programs to give up unnecessarily.
+
+
+
+Internet Engineering Task Force [Page 33]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ When the meaning of a reply matches exactly the text
+ shown in RFC-959, uniformity will be enhanced by using
+ the RFC-959 text verbatim. However, a Server-FTP
+ implementor is encouraged to choose reply text that
+ conveys specific system-dependent information, when
+ appropriate.
+
+ 4.1.2.12 Connections: RFC-959 Section 5.2
+
+ The words "and the port used" in the second paragraph of
+ this section of RFC-959 are erroneous (historical), and they
+ should be ignored.
+
+ On a multihomed server host, the default data transfer port
+ (L-1) MUST be associated with the same local IP address as
+ the corresponding control connection to port L.
+
+ A user-FTP MUST NOT send any Telnet controls other than
+ SYNCH and IP on an FTP control connection. In particular, it
+ MUST NOT attempt to negotiate Telnet options on the control
+ connection. However, a server-FTP MUST be capable of
+ accepting and refusing Telnet negotiations (i.e., sending
+ DONT/WONT).
+
+ DISCUSSION:
+ Although the RFC says: "Server- and User- processes
+ should follow the conventions for the Telnet
+ protocol...[on the control connection]", it is not the
+ intent that Telnet option negotiation is to be
+ employed.
+
+ 4.1.2.13 Minimum Implementation; RFC-959 Section 5.1
+
+ The following commands and options MUST be supported by
+ every server-FTP and user-FTP, except in cases where the
+ underlying file system or operating system does not allow or
+ support a particular command.
+
+ Type: ASCII Non-print, IMAGE, LOCAL 8
+ Mode: Stream
+ Structure: File, Record*
+ Commands:
+ USER, PASS, ACCT,
+ PORT, PASV,
+ TYPE, MODE, STRU,
+ RETR, STOR, APPE,
+ RNFR, RNTO, DELE,
+ CWD, CDUP, RMD, MKD, PWD,
+
+
+
+Internet Engineering Task Force [Page 34]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ LIST, NLST,
+ SYST, STAT,
+ HELP, NOOP, QUIT.
+
+ *Record structure is REQUIRED only for hosts whose file
+ systems support record structure.
+
+ DISCUSSION:
+ Vendors are encouraged to implement a larger subset of
+ the protocol. For example, there are important
+ robustness features in the protocol (e.g., Restart,
+ ABOR, block mode) that would be an aid to some Internet
+ users but are not widely implemented.
+
+ A host that does not have record structures in its file
+ system may still accept files with STRU R, recording
+ the byte stream literally.
+
+ 4.1.3 SPECIFIC ISSUES
+
+ 4.1.3.1 Non-standard Command Verbs
+
+ FTP allows "experimental" commands, whose names begin with
+ "X". If these commands are subsequently adopted as
+ standards, there may still be existing implementations using
+ the "X" form. At present, this is true for the directory
+ commands:
+
+ RFC-959 "Experimental"
+
+ MKD XMKD
+ RMD XRMD
+ PWD XPWD
+ CDUP XCUP
+ CWD XCWD
+
+ All FTP implementations SHOULD recognize both forms of these
+ commands, by simply equating them with extra entries in the
+ command lookup table.
+
+ IMPLEMENTATION:
+ A User-FTP can access a server that supports only the
+ "X" forms by implementing a mode switch, or
+ automatically using the following procedure: if the
+ RFC-959 form of one of the above commands is rejected
+ with a 500 or 502 response code, then try the
+ experimental form; any other response would be passed
+ to the user.
+
+
+
+Internet Engineering Task Force [Page 35]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ 4.1.3.2 Idle Timeout
+
+ A Server-FTP process SHOULD have an idle timeout, which will
+ terminate the process and close the control connection if
+ the server is inactive (i.e., no command or data transfer in
+ progress) for a long period of time. The idle timeout time
+ SHOULD be configurable, and the default should be at least 5
+ minutes.
+
+ A client FTP process ("User-PI" in RFC-959) will need
+ timeouts on responses only if it is invoked from a program.
+
+ DISCUSSION:
+ Without a timeout, a Server-FTP process may be left
+ pending indefinitely if the corresponding client
+ crashes without closing the control connection.
+
+ 4.1.3.3 Concurrency of Data and Control
+
+ DISCUSSION:
+ The intent of the designers of FTP was that a user
+ should be able to send a STAT command at any time while
+ data transfer was in progress and that the server-FTP
+ would reply immediately with status -- e.g., the number
+ of bytes transferred so far. Similarly, an ABOR
+ command should be possible at any time during a data
+ transfer.
+
+ Unfortunately, some small-machine operating systems
+ make such concurrent programming difficult, and some
+ other implementers seek minimal solutions, so some FTP
+ implementations do not allow concurrent use of the data
+ and control connections. Even such a minimal server
+ must be prepared to accept and defer a STAT or ABOR
+ command that arrives during data transfer.
+
+ 4.1.3.4 FTP Restart Mechanism
+
+ The description of the 110 reply on pp. 40-41 of RFC-959 is
+ incorrect; the correct description is as follows. A restart
+ reply message, sent over the control connection from the
+ receiving FTP to the User-FTP, has the format:
+
+ 110 MARK ssss = rrrr
+
+ Here:
+
+ * ssss is a text string that appeared in a Restart Marker
+
+
+
+Internet Engineering Task Force [Page 36]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ in the data stream and encodes a position in the
+ sender's file system;
+
+ * rrrr encodes the corresponding position in the
+ receiver's file system.
+
+ The encoding, which is specific to a particular file system
+ and network implementation, is always generated and
+ interpreted by the same system, either sender or receiver.
+
+ When an FTP that implements restart receives a Restart
+ Marker in the data stream, it SHOULD force the data to that
+ point to be written to stable storage before encoding the
+ corresponding position rrrr. An FTP sending Restart Markers
+ MUST NOT assume that 110 replies will be returned
+ synchronously with the data, i.e., it must not await a 110
+ reply before sending more data.
+
+ Two new reply codes are hereby defined for errors
+ encountered in restarting a transfer:
+
+ 554 Requested action not taken: invalid REST parameter.
+
+ A 554 reply may result from a FTP service command that
+ follows a REST command. The reply indicates that the
+ existing file at the Server-FTP cannot be repositioned
+ as specified in the REST.
+
+ 555 Requested action not taken: type or stru mismatch.
+
+ A 555 reply may result from an APPE command or from any
+ FTP service command following a REST command. The
+ reply indicates that there is some mismatch between the
+ current transfer parameters (type and stru) and the
+ attributes of the existing file.
+
+ DISCUSSION:
+ Note that the FTP Restart mechanism requires that Block
+ or Compressed mode be used for data transfer, to allow
+ the Restart Markers to be included within the data
+ stream. The frequency of Restart Markers can be low.
+
+ Restart Markers mark a place in the data stream, but
+ the receiver may be performing some transformation on
+ the data as it is stored into stable storage. In
+ general, the receiver's encoding must include any state
+ information necessary to restart this transformation at
+ any point of the FTP data stream. For example, in TYPE
+
+
+
+Internet Engineering Task Force [Page 37]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ A transfers, some receiver hosts transform CR LF
+ sequences into a single LF character on disk. If a
+ Restart Marker happens to fall between CR and LF, the
+ receiver must encode in rrrr that the transfer must be
+ restarted in a "CR has been seen and discarded" state.
+
+ Note that the Restart Marker is required to be encoded
+ as a string of printable ASCII characters, regardless
+ of the type of the data.
+
+ RFC-959 says that restart information is to be returned
+ "to the user". This should not be taken literally. In
+ general, the User-FTP should save the restart
+ information (ssss,rrrr) in stable storage, e.g., append
+ it to a restart control file. An empty restart control
+ file should be created when the transfer first starts
+ and deleted automatically when the transfer completes
+ successfully. It is suggested that this file have a
+ name derived in an easily-identifiable manner from the
+ name of the file being transferred and the remote host
+ name; this is analogous to the means used by many text
+ editors for naming "backup" files.
+
+ There are three cases for FTP restart.
+
+ (1) User-to-Server Transfer
+
+ The User-FTP puts Restart Markers <ssss> at
+ convenient places in the data stream. When the
+ Server-FTP receives a Marker, it writes all prior
+ data to disk, encodes its file system position and
+ transformation state as rrrr, and returns a "110
+ MARK ssss = rrrr" reply over the control
+ connection. The User-FTP appends the pair
+ (ssss,rrrr) to its restart control file.
+
+ To restart the transfer, the User-FTP fetches the
+ last (ssss,rrrr) pair from the restart control
+ file, repositions its local file system and
+ transformation state using ssss, and sends the
+ command "REST rrrr" to the Server-FTP.
+
+ (2) Server-to-User Transfer
+
+ The Server-FTP puts Restart Markers <ssss> at
+ convenient places in the data stream. When the
+ User-FTP receives a Marker, it writes all prior
+ data to disk, encodes its file system position and
+
+
+
+Internet Engineering Task Force [Page 38]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ transformation state as rrrr, and appends the pair
+ (rrrr,ssss) to its restart control file.
+
+ To restart the transfer, the User-FTP fetches the
+ last (rrrr,ssss) pair from the restart control
+ file, repositions its local file system and
+ transformation state using rrrr, and sends the
+ command "REST ssss" to the Server-FTP.
+
+ (3) Server-to-Server ("Third-Party") Transfer
+
+ The sending Server-FTP puts Restart Markers <ssss>
+ at convenient places in the data stream. When it
+ receives a Marker, the receiving Server-FTP writes
+ all prior data to disk, encodes its file system
+ position and transformation state as rrrr, and
+ sends a "110 MARK ssss = rrrr" reply over the
+ control connection to the User. The User-FTP
+ appends the pair (ssss,rrrr) to its restart
+ control file.
+
+ To restart the transfer, the User-FTP fetches the
+ last (ssss,rrrr) pair from the restart control
+ file, sends "REST ssss" to the sending Server-FTP,
+ and sends "REST rrrr" to the receiving Server-FTP.
+
+
+ 4.1.4 FTP/USER INTERFACE
+
+ This section discusses the user interface for a User-FTP
+ program.
+
+ 4.1.4.1 Pathname Specification
+
+ Since FTP is intended for use in a heterogeneous
+ environment, User-FTP implementations MUST support remote
+ pathnames as arbitrary character strings, so that their form
+ and content are not limited by the conventions of the local
+ operating system.
+
+ DISCUSSION:
+ In particular, remote pathnames can be of arbitrary
+ length, and all the printing ASCII characters as well
+ as space (0x20) must be allowed. RFC-959 allows a
+ pathname to contain any 7-bit ASCII character except CR
+ or LF.
+
+
+
+
+
+Internet Engineering Task Force [Page 39]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ 4.1.4.2 "QUOTE" Command
+
+ A User-FTP program MUST implement a "QUOTE" command that
+ will pass an arbitrary character string to the server and
+ display all resulting response messages to the user.
+
+ To make the "QUOTE" command useful, a User-FTP SHOULD send
+ transfer control commands to the server as the user enters
+ them, rather than saving all the commands and sending them
+ to the server only when a data transfer is started.
+
+ DISCUSSION:
+ The "QUOTE" command is essential to allow the user to
+ access servers that require system-specific commands
+ (e.g., SITE or ALLO), or to invoke new or optional
+ features that are not implemented by the User-FTP. For
+ example, "QUOTE" may be used to specify "TYPE A T" to
+ send a print file to hosts that require the
+ distinction, even if the User-FTP does not recognize
+ that TYPE.
+
+ 4.1.4.3 Displaying Replies to User
+
+ A User-FTP SHOULD display to the user the full text of all
+ error reply messages it receives. It SHOULD have a
+ "verbose" mode in which all commands it sends and the full
+ text and reply codes it receives are displayed, for
+ diagnosis of problems.
+
+ 4.1.4.4 Maintaining Synchronization
+
+ The state machine in a User-FTP SHOULD be forgiving of
+ missing and unexpected reply messages, in order to maintain
+ command synchronization with the server.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 40]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ 4.1.5 FTP REQUIREMENTS SUMMARY
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION | | | |T|T|e
+-------------------------------------------|---------------|-|-|-|-|-|--
+Implement TYPE T if same as TYPE N |4.1.2.2 | |x| | | |
+File/Record transform invertible if poss. |4.1.2.4 | |x| | | |
+User-FTP send PORT cmd for stream mode |4.1.2.5 | |x| | | |
+Server-FTP implement PASV |4.1.2.6 |x| | | | |
+ PASV is per-transfer |4.1.2.6 |x| | | | |
+NLST reply usable in RETR cmds |4.1.2.7 |x| | | | |
+Implied type for LIST and NLST |4.1.2.7 | |x| | | |
+SITE cmd for non-standard features |4.1.2.8 | |x| | | |
+STOU cmd return pathname as specified |4.1.2.9 |x| | | | |
+Use TCP READ boundaries on control conn. |4.1.2.10 | | | | |x|
+ | | | | | | |
+Server-FTP send only correct reply format |4.1.2.11 |x| | | | |
+Server-FTP use defined reply code if poss. |4.1.2.11 | |x| | | |
+ New reply code following Section 4.2 |4.1.2.11 | | |x| | |
+User-FTP use only high digit of reply |4.1.2.11 | |x| | | |
+User-FTP handle multi-line reply lines |4.1.2.11 |x| | | | |
+User-FTP handle 421 reply specially |4.1.2.11 | | | |x| |
+ | | | | | | |
+Default data port same IP addr as ctl conn |4.1.2.12 |x| | | | |
+User-FTP send Telnet cmds exc. SYNCH, IP |4.1.2.12 | | | | |x|
+User-FTP negotiate Telnet options |4.1.2.12 | | | | |x|
+Server-FTP handle Telnet options |4.1.2.12 |x| | | | |
+Handle "Experimental" directory cmds |4.1.3.1 | |x| | | |
+Idle timeout in server-FTP |4.1.3.2 | |x| | | |
+ Configurable idle timeout |4.1.3.2 | |x| | | |
+Receiver checkpoint data at Restart Marker |4.1.3.4 | |x| | | |
+Sender assume 110 replies are synchronous |4.1.3.4 | | | | |x|
+ | | | | | | |
+Support TYPE: | | | | | | |
+ ASCII - Non-Print (AN) |4.1.2.13 |x| | | | |
+ ASCII - Telnet (AT) -- if same as AN |4.1.2.2 | |x| | | |
+ ASCII - Carriage Control (AC) |959 3.1.1.5.2 | | |x| | |
+ EBCDIC - (any form) |959 3.1.1.2 | | |x| | |
+ IMAGE |4.1.2.1 |x| | | | |
+ LOCAL 8 |4.1.2.1 |x| | | | |
+
+
+
+Internet Engineering Task Force [Page 41]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+ LOCAL m |4.1.2.1 | | |x| | |2
+ | | | | | | |
+Support MODE: | | | | | | |
+ Stream |4.1.2.13 |x| | | | |
+ Block |959 3.4.2 | | |x| | |
+ | | | | | | |
+Support STRUCTURE: | | | | | | |
+ File |4.1.2.13 |x| | | | |
+ Record |4.1.2.13 |x| | | | |3
+ Page |4.1.2.3 | | | |x| |
+ | | | | | | |
+Support commands: | | | | | | |
+ USER |4.1.2.13 |x| | | | |
+ PASS |4.1.2.13 |x| | | | |
+ ACCT |4.1.2.13 |x| | | | |
+ CWD |4.1.2.13 |x| | | | |
+ CDUP |4.1.2.13 |x| | | | |
+ SMNT |959 5.3.1 | | |x| | |
+ REIN |959 5.3.1 | | |x| | |
+ QUIT |4.1.2.13 |x| | | | |
+ | | | | | | |
+ PORT |4.1.2.13 |x| | | | |
+ PASV |4.1.2.6 |x| | | | |
+ TYPE |4.1.2.13 |x| | | | |1
+ STRU |4.1.2.13 |x| | | | |1
+ MODE |4.1.2.13 |x| | | | |1
+ | | | | | | |
+ RETR |4.1.2.13 |x| | | | |
+ STOR |4.1.2.13 |x| | | | |
+ STOU |959 5.3.1 | | |x| | |
+ APPE |4.1.2.13 |x| | | | |
+ ALLO |959 5.3.1 | | |x| | |
+ REST |959 5.3.1 | | |x| | |
+ RNFR |4.1.2.13 |x| | | | |
+ RNTO |4.1.2.13 |x| | | | |
+ ABOR |959 5.3.1 | | |x| | |
+ DELE |4.1.2.13 |x| | | | |
+ RMD |4.1.2.13 |x| | | | |
+ MKD |4.1.2.13 |x| | | | |
+ PWD |4.1.2.13 |x| | | | |
+ LIST |4.1.2.13 |x| | | | |
+ NLST |4.1.2.13 |x| | | | |
+ SITE |4.1.2.8 | | |x| | |
+ STAT |4.1.2.13 |x| | | | |
+ SYST |4.1.2.13 |x| | | | |
+ HELP |4.1.2.13 |x| | | | |
+ NOOP |4.1.2.13 |x| | | | |
+ | | | | | | |
+
+
+
+Internet Engineering Task Force [Page 42]
+
+
+
+
+RFC1123 FILE TRANSFER -- FTP October 1989
+
+
+User Interface: | | | | | | |
+ Arbitrary pathnames |4.1.4.1 |x| | | | |
+ Implement "QUOTE" command |4.1.4.2 |x| | | | |
+ Transfer control commands immediately |4.1.4.2 | |x| | | |
+ Display error messages to user |4.1.4.3 | |x| | | |
+ Verbose mode |4.1.4.3 | |x| | | |
+ Maintain synchronization with server |4.1.4.4 | |x| | | |
+
+Footnotes:
+
+(1) For the values shown earlier.
+
+(2) Here m is number of bits in a memory word.
+
+(3) Required for host with record-structured file system, optional
+ otherwise.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 43]
+
+
+
+
+RFC1123 FILE TRANSFER -- TFTP October 1989
+
+
+ 4.2 TRIVIAL FILE TRANSFER PROTOCOL -- TFTP
+
+ 4.2.1 INTRODUCTION
+
+ The Trivial File Transfer Protocol TFTP is defined in RFC-783
+ [TFTP:1].
+
+ TFTP provides its own reliable delivery with UDP as its
+ transport protocol, using a simple stop-and-wait acknowledgment
+ system. Since TFTP has an effective window of only one 512
+ octet segment, it can provide good performance only over paths
+ that have a small delay*bandwidth product. The TFTP file
+ interface is very simple, providing no access control or
+ security.
+
+ TFTP's most important application is bootstrapping a host over
+ a local network, since it is simple and small enough to be
+ easily implemented in EPROM [BOOT:1, BOOT:2]. Vendors are
+ urged to support TFTP for booting.
+
+ 4.2.2 PROTOCOL WALK-THROUGH
+
+ The TFTP specification [TFTP:1] is written in an open style,
+ and does not fully specify many parts of the protocol.
+
+ 4.2.2.1 Transfer Modes: RFC-783, Page 3
+
+ The transfer mode "mail" SHOULD NOT be supported.
+
+ 4.2.2.2 UDP Header: RFC-783, Page 17
+
+ The Length field of a UDP header is incorrectly defined; it
+ includes the UDP header length (8).
+
+ 4.2.3 SPECIFIC ISSUES
+
+ 4.2.3.1 Sorcerer's Apprentice Syndrome
+
+ There is a serious bug, known as the "Sorcerer's Apprentice
+ Syndrome," in the protocol specification. While it does not
+ cause incorrect operation of the transfer (the file will
+ always be transferred correctly if the transfer completes),
+ this bug may cause excessive retransmission, which may cause
+ the transfer to time out.
+
+ Implementations MUST contain the fix for this problem: the
+ sender (i.e., the side originating the DATA packets) must
+ never resend the current DATA packet on receipt of a
+
+
+
+Internet Engineering Task Force [Page 44]
+
+
+
+
+RFC1123 FILE TRANSFER -- TFTP October 1989
+
+
+ duplicate ACK.
+
+ DISCUSSION:
+ The bug is caused by the protocol rule that either
+ side, on receiving an old duplicate datagram, may
+ resend the current datagram. If a packet is delayed in
+ the network but later successfully delivered after
+ either side has timed out and retransmitted a packet, a
+ duplicate copy of the response may be generated. If
+ the other side responds to this duplicate with a
+ duplicate of its own, then every datagram will be sent
+ in duplicate for the remainder of the transfer (unless
+ a datagram is lost, breaking the repetition). Worse
+ yet, since the delay is often caused by congestion,
+ this duplicate transmission will usually causes more
+ congestion, leading to more delayed packets, etc.
+
+ The following example may help to clarify this problem.
+
+ TFTP A TFTP B
+
+ (1) Receive ACK X-1
+ Send DATA X
+ (2) Receive DATA X
+ Send ACK X
+ (ACK X is delayed in network,
+ and A times out):
+ (3) Retransmit DATA X
+
+ (4) Receive DATA X again
+ Send ACK X again
+ (5) Receive (delayed) ACK X
+ Send DATA X+1
+ (6) Receive DATA X+1
+ Send ACK X+1
+ (7) Receive ACK X again
+ Send DATA X+1 again
+ (8) Receive DATA X+1 again
+ Send ACK X+1 again
+ (9) Receive ACK X+1
+ Send DATA X+2
+ (10) Receive DATA X+2
+ Send ACK X+3
+ (11) Receive ACK X+1 again
+ Send DATA X+2 again
+ (12) Receive DATA X+2 again
+ Send ACK X+3 again
+
+
+
+
+Internet Engineering Task Force [Page 45]
+
+
+
+
+RFC1123 FILE TRANSFER -- TFTP October 1989
+
+
+ Notice that once the delayed ACK arrives, the protocol
+ settles down to duplicate all further packets
+ (sequences 5-8 and 9-12). The problem is caused not by
+ either side timing out, but by both sides
+ retransmitting the current packet when they receive a
+ duplicate.
+
+ The fix is to break the retransmission loop, as
+ indicated above. This is analogous to the behavior of
+ TCP. It is then possible to remove the retransmission
+ timer on the receiver, since the resent ACK will never
+ cause any action; this is a useful simplification where
+ TFTP is used in a bootstrap program. It is OK to allow
+ the timer to remain, and it may be helpful if the
+ retransmitted ACK replaces one that was genuinely lost
+ in the network. The sender still requires a retransmit
+ timer, of course.
+
+ 4.2.3.2 Timeout Algorithms
+
+ A TFTP implementation MUST use an adaptive timeout.
+
+ IMPLEMENTATION:
+ TCP retransmission algorithms provide a useful base to
+ work from. At least an exponential backoff of
+ retransmission timeout is necessary.
+
+ 4.2.3.3 Extensions
+
+ A variety of non-standard extensions have been made to TFTP,
+ including additional transfer modes and a secure operation
+ mode (with passwords). None of these have been
+ standardized.
+
+ 4.2.3.4 Access Control
+
+ A server TFTP implementation SHOULD include some
+ configurable access control over what pathnames are allowed
+ in TFTP operations.
+
+ 4.2.3.5 Broadcast Request
+
+ A TFTP request directed to a broadcast address SHOULD be
+ silently ignored.
+
+ DISCUSSION:
+ Due to the weak access control capability of TFTP,
+ directed broadcasts of TFTP requests to random networks
+
+
+
+Internet Engineering Task Force [Page 46]
+
+
+
+
+RFC1123 FILE TRANSFER -- TFTP October 1989
+
+
+ could create a significant security hole.
+
+ 4.2.4 TFTP REQUIREMENTS SUMMARY
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION | | | |T|T|e
+-------------------------------------------------|--------|-|-|-|-|-|--
+Fix Sorcerer's Apprentice Syndrome |4.2.3.1 |x| | | | |
+Transfer modes: | | | | | | |
+ netascii |RFC-783 |x| | | | |
+ octet |RFC-783 |x| | | | |
+ mail |4.2.2.1 | | | |x| |
+ extensions |4.2.3.3 | | |x| | |
+Use adaptive timeout |4.2.3.2 |x| | | | |
+Configurable access control |4.2.3.4 | |x| | | |
+Silently ignore broadcast request |4.2.3.5 | |x| | | |
+-------------------------------------------------|--------|-|-|-|-|-|--
+-------------------------------------------------|--------|-|-|-|-|-|--
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 47]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+5. ELECTRONIC MAIL -- SMTP and RFC-822
+
+ 5.1 INTRODUCTION
+
+ In the TCP/IP protocol suite, electronic mail in a format
+ specified in RFC-822 [SMTP:2] is transmitted using the Simple Mail
+ Transfer Protocol (SMTP) defined in RFC-821 [SMTP:1].
+
+ While SMTP has remained unchanged over the years, the Internet
+ community has made several changes in the way SMTP is used. In
+ particular, the conversion to the Domain Name System (DNS) has
+ caused changes in address formats and in mail routing. In this
+ section, we assume familiarity with the concepts and terminology
+ of the DNS, whose requirements are given in Section 6.1.
+
+ RFC-822 specifies the Internet standard format for electronic mail
+ messages. RFC-822 supercedes an older standard, RFC-733, that may
+ still be in use in a few places, although it is obsolete. The two
+ formats are sometimes referred to simply by number ("822" and
+ "733").
+
+ RFC-822 is used in some non-Internet mail environments with
+ different mail transfer protocols than SMTP, and SMTP has also
+ been adapted for use in some non-Internet environments. Note that
+ this document presents the rules for the use of SMTP and RFC-822
+ for the Internet environment only; other mail environments that
+ use these protocols may be expected to have their own rules.
+
+ 5.2 PROTOCOL WALK-THROUGH
+
+ This section covers both RFC-821 and RFC-822.
+
+ The SMTP specification in RFC-821 is clear and contains numerous
+ examples, so implementors should not find it difficult to
+ understand. This section simply updates or annotates portions of
+ RFC-821 to conform with current usage.
+
+ RFC-822 is a long and dense document, defining a rich syntax.
+ Unfortunately, incomplete or defective implementations of RFC-822
+ are common. In fact, nearly all of the many formats of RFC-822
+ are actually used, so an implementation generally needs to
+ recognize and correctly interpret all of the RFC-822 syntax.
+
+ 5.2.1 The SMTP Model: RFC-821 Section 2
+
+ DISCUSSION:
+ Mail is sent by a series of request/response transactions
+ between a client, the "sender-SMTP," and a server, the
+
+
+
+Internet Engineering Task Force [Page 48]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ "receiver-SMTP". These transactions pass (1) the message
+ proper, which is composed of header and body, and (2) SMTP
+ source and destination addresses, referred to as the
+ "envelope".
+
+ The SMTP programs are analogous to Message Transfer Agents
+ (MTAs) of X.400. There will be another level of protocol
+ software, closer to the end user, that is responsible for
+ composing and analyzing RFC-822 message headers; this
+ component is known as the "User Agent" in X.400, and we
+ use that term in this document. There is a clear logical
+ distinction between the User Agent and the SMTP
+ implementation, since they operate on different levels of
+ protocol. Note, however, that this distinction is may not
+ be exactly reflected the structure of typical
+ implementations of Internet mail. Often there is a
+ program known as the "mailer" that implements SMTP and
+ also some of the User Agent functions; the rest of the
+ User Agent functions are included in a user interface used
+ for entering and reading mail.
+
+ The SMTP envelope is constructed at the originating site,
+ typically by the User Agent when the message is first
+ queued for the Sender-SMTP program. The envelope
+ addresses may be derived from information in the message
+ header, supplied by the user interface (e.g., to implement
+ a bcc: request), or derived from local configuration
+ information (e.g., expansion of a mailing list). The SMTP
+ envelope cannot in general be re-derived from the header
+ at a later stage in message delivery, so the envelope is
+ transmitted separately from the message itself using the
+ MAIL and RCPT commands of SMTP.
+
+ The text of RFC-821 suggests that mail is to be delivered
+ to an individual user at a host. With the advent of the
+ domain system and of mail routing using mail-exchange (MX)
+ resource records, implementors should now think of
+ delivering mail to a user at a domain, which may or may
+ not be a particular host. This DOES NOT change the fact
+ that SMTP is a host-to-host mail exchange protocol.
+
+ 5.2.2 Canonicalization: RFC-821 Section 3.1
+
+ The domain names that a Sender-SMTP sends in MAIL and RCPT
+ commands MUST have been "canonicalized," i.e., they must be
+ fully-qualified principal names or domain literals, not
+ nicknames or domain abbreviations. A canonicalized name either
+ identifies a host directly or is an MX name; it cannot be a
+
+
+
+Internet Engineering Task Force [Page 49]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ CNAME.
+
+ 5.2.3 VRFY and EXPN Commands: RFC-821 Section 3.3
+
+ A receiver-SMTP MUST implement VRFY and SHOULD implement EXPN
+ (this requirement overrides RFC-821). However, there MAY be
+ configuration information to disable VRFY and EXPN in a
+ particular installation; this might even allow EXPN to be
+ disabled for selected lists.
+
+ A new reply code is defined for the VRFY command:
+
+ 252 Cannot VRFY user (e.g., info is not local), but will
+ take message for this user and attempt delivery.
+
+ DISCUSSION:
+ SMTP users and administrators make regular use of these
+ commands for diagnosing mail delivery problems. With the
+ increasing use of multi-level mailing list expansion
+ (sometimes more than two levels), EXPN has been
+ increasingly important for diagnosing inadvertent mail
+ loops. On the other hand, some feel that EXPN represents
+ a significant privacy, and perhaps even a security,
+ exposure.
+
+ 5.2.4 SEND, SOML, and SAML Commands: RFC-821 Section 3.4
+
+ An SMTP MAY implement the commands to send a message to a
+ user's terminal: SEND, SOML, and SAML.
+
+ DISCUSSION:
+ It has been suggested that the use of mail relaying
+ through an MX record is inconsistent with the intent of
+ SEND to deliver a message immediately and directly to a
+ user's terminal. However, an SMTP receiver that is unable
+ to write directly to the user terminal can return a "251
+ User Not Local" reply to the RCPT following a SEND, to
+ inform the originator of possibly deferred delivery.
+
+ 5.2.5 HELO Command: RFC-821 Section 3.5
+
+ The sender-SMTP MUST ensure that the <domain> parameter in a
+ HELO command is a valid principal host domain name for the
+ client host. As a result, the receiver-SMTP will not have to
+ perform MX resolution on this name in order to validate the
+ HELO parameter.
+
+ The HELO receiver MAY verify that the HELO parameter really
+
+
+
+Internet Engineering Task Force [Page 50]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ corresponds to the IP address of the sender. However, the
+ receiver MUST NOT refuse to accept a message, even if the
+ sender's HELO command fails verification.
+
+ DISCUSSION:
+ Verifying the HELO parameter requires a domain name lookup
+ and may therefore take considerable time. An alternative
+ tool for tracking bogus mail sources is suggested below
+ (see "DATA Command").
+
+ Note also that the HELO argument is still required to have
+ valid <domain> syntax, since it will appear in a Received:
+ line; otherwise, a 501 error is to be sent.
+
+ IMPLEMENTATION:
+ When HELO parameter validation fails, a suggested
+ procedure is to insert a note about the unknown
+ authenticity of the sender into the message header (e.g.,
+ in the "Received:" line).
+
+ 5.2.6 Mail Relay: RFC-821 Section 3.6
+
+ We distinguish three types of mail (store-and-) forwarding:
+
+ (1) A simple forwarder or "mail exchanger" forwards a message
+ using private knowledge about the recipient; see section
+ 3.2 of RFC-821.
+
+ (2) An SMTP mail "relay" forwards a message within an SMTP
+ mail environment as the result of an explicit source route
+ (as defined in section 3.6 of RFC-821). The SMTP relay
+ function uses the "@...:" form of source route from RFC-
+ 822 (see Section 5.2.19 below).
+
+ (3) A mail "gateway" passes a message between different
+ environments. The rules for mail gateways are discussed
+ below in Section 5.3.7.
+
+ An Internet host that is forwarding a message but is not a
+ gateway to a different mail environment (i.e., it falls under
+ (1) or (2)) SHOULD NOT alter any existing header fields,
+ although the host will add an appropriate Received: line as
+ required in Section 5.2.8.
+
+ A Sender-SMTP SHOULD NOT send a RCPT TO: command containing an
+ explicit source route using the "@...:" address form. Thus,
+ the relay function defined in section 3.6 of RFC-821 should
+ not be used.
+
+
+
+Internet Engineering Task Force [Page 51]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ DISCUSSION:
+ The intent is to discourage all source routing and to
+ abolish explicit source routing for mail delivery within
+ the Internet environment. Source-routing is unnecessary;
+ the simple target address "user@domain" should always
+ suffice. This is the result of an explicit architectural
+ decision to use universal naming rather than source
+ routing for mail. Thus, SMTP provides end-to-end
+ connectivity, and the DNS provides globally-unique,
+ location-independent names. MX records handle the major
+ case where source routing might otherwise be needed.
+
+ A receiver-SMTP MUST accept the explicit source route syntax in
+ the envelope, but it MAY implement the relay function as
+ defined in section 3.6 of RFC-821. If it does not implement
+ the relay function, it SHOULD attempt to deliver the message
+ directly to the host to the right of the right-most "@" sign.
+
+ DISCUSSION:
+ For example, suppose a host that does not implement the
+ relay function receives a message with the SMTP command:
+ "RCPT TO:<@ALPHA,@BETA:joe@GAMMA>", where ALPHA, BETA, and
+ GAMMA represent domain names. Rather than immediately
+ refusing the message with a 550 error reply as suggested
+ on page 20 of RFC-821, the host should try to forward the
+ message to GAMMA directly, using: "RCPT TO:<joe@GAMMA>".
+ Since this host does not support relaying, it is not
+ required to update the reverse path.
+
+ Some have suggested that source routing may be needed
+ occasionally for manually routing mail around failures;
+ however, the reality and importance of this need is
+ controversial. The use of explicit SMTP mail relaying for
+ this purpose is discouraged, and in fact it may not be
+ successful, as many host systems do not support it. Some
+ have used the "%-hack" (see Section 5.2.16) for this
+ purpose.
+
+ 5.2.7 RCPT Command: RFC-821 Section 4.1.1
+
+ A host that supports a receiver-SMTP MUST support the reserved
+ mailbox "Postmaster".
+
+ The receiver-SMTP MAY verify RCPT parameters as they arrive;
+ however, RCPT responses MUST NOT be delayed beyond a reasonable
+ time (see Section 5.3.2).
+
+ Therefore, a "250 OK" response to a RCPT does not necessarily
+
+
+
+Internet Engineering Task Force [Page 52]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ imply that the delivery address(es) are valid. Errors found
+ after message acceptance will be reported by mailing a
+ notification message to an appropriate address (see Section
+ 5.3.3).
+
+ DISCUSSION:
+ The set of conditions under which a RCPT parameter can be
+ validated immediately is an engineering design choice.
+ Reporting destination mailbox errors to the Sender-SMTP
+ before mail is transferred is generally desirable to save
+ time and network bandwidth, but this advantage is lost if
+ RCPT verification is lengthy.
+
+ For example, the receiver can verify immediately any
+ simple local reference, such as a single locally-
+ registered mailbox. On the other hand, the "reasonable
+ time" limitation generally implies deferring verification
+ of a mailing list until after the message has been
+ transferred and accepted, since verifying a large mailing
+ list can take a very long time. An implementation might
+ or might not choose to defer validation of addresses that
+ are non-local and therefore require a DNS lookup. If a
+ DNS lookup is performed but a soft domain system error
+ (e.g., timeout) occurs, validity must be assumed.
+
+ 5.2.8 DATA Command: RFC-821 Section 4.1.1
+
+ Every receiver-SMTP (not just one that "accepts a message for
+ relaying or for final delivery" [SMTP:1]) MUST insert a
+ "Received:" line at the beginning of a message. In this line,
+ called a "time stamp line" in RFC-821:
+
+ * The FROM field SHOULD contain both (1) the name of the
+ source host as presented in the HELO command and (2) a
+ domain literal containing the IP address of the source,
+ determined from the TCP connection.
+
+ * The ID field MAY contain an "@" as suggested in RFC-822,
+ but this is not required.
+
+ * The FOR field MAY contain a list of <path> entries when
+ multiple RCPT commands have been given.
+
+
+ An Internet mail program MUST NOT change a Received: line that
+ was previously added to the message header.
+
+
+
+
+
+Internet Engineering Task Force [Page 53]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ DISCUSSION:
+ Including both the source host and the IP source address
+ in the Received: line may provide enough information for
+ tracking illicit mail sources and eliminate a need to
+ explicitly verify the HELO parameter.
+
+ Received: lines are primarily intended for humans tracing
+ mail routes, primarily of diagnosis of faults. See also
+ the discussion under 5.3.7.
+
+ When the receiver-SMTP makes "final delivery" of a message,
+ then it MUST pass the MAIL FROM: address from the SMTP envelope
+ with the message, for use if an error notification message must
+ be sent later (see Section 5.3.3). There is an analogous
+ requirement when gatewaying from the Internet into a different
+ mail environment; see Section 5.3.7.
+
+ DISCUSSION:
+ Note that the final reply to the DATA command depends only
+ upon the successful transfer and storage of the message.
+ Any problem with the destination address(es) must either
+ (1) have been reported in an SMTP error reply to the RCPT
+ command(s), or (2) be reported in a later error message
+ mailed to the originator.
+
+ IMPLEMENTATION:
+ The MAIL FROM: information may be passed as a parameter or
+ in a Return-Path: line inserted at the beginning of the
+ message.
+
+ 5.2.9 Command Syntax: RFC-821 Section 4.1.2
+
+ The syntax shown in RFC-821 for the MAIL FROM: command omits
+ the case of an empty path: "MAIL FROM: <>" (see RFC-821 Page
+ 15). An empty reverse path MUST be supported.
+
+ 5.2.10 SMTP Replies: RFC-821 Section 4.2
+
+ A receiver-SMTP SHOULD send only the reply codes listed in
+ section 4.2.2 of RFC-821 or in this document. A receiver-SMTP
+ SHOULD use the text shown in examples in RFC-821 whenever
+ appropriate.
+
+ A sender-SMTP MUST determine its actions only by the reply
+ code, not by the text (except for 251 and 551 replies); any
+ text, including no text at all, must be acceptable. The space
+ (blank) following the reply code is considered part of the
+ text. Whenever possible, a sender-SMTP SHOULD test only the
+
+
+
+Internet Engineering Task Force [Page 54]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ first digit of the reply code, as specified in Appendix E of
+ RFC-821.
+
+ DISCUSSION:
+ Interoperability problems have arisen with SMTP systems
+ using reply codes that are not listed explicitly in RFC-
+ 821 Section 4.3 but are legal according to the theory of
+ reply codes explained in Appendix E.
+
+ 5.2.11 Transparency: RFC-821 Section 4.5.2
+
+ Implementors MUST be sure that their mail systems always add
+ and delete periods to ensure message transparency.
+
+ 5.2.12 WKS Use in MX Processing: RFC-974, p. 5
+
+ RFC-974 [SMTP:3] recommended that the domain system be queried
+ for WKS ("Well-Known Service") records, to verify that each
+ proposed mail target does support SMTP. Later experience has
+ shown that WKS is not widely supported, so the WKS step in MX
+ processing SHOULD NOT be used.
+
+ The following are notes on RFC-822, organized by section of that
+ document.
+
+ 5.2.13 RFC-822 Message Specification: RFC-822 Section 4
+
+ The syntax shown for the Return-path line omits the possibility
+ of a null return path, which is used to prevent looping of
+ error notifications (see Section 5.3.3). The complete syntax
+ is:
+
+ return = "Return-path" ":" route-addr
+ / "Return-path" ":" "<" ">"
+
+ The set of optional header fields is hereby expanded to include
+ the Content-Type field defined in RFC-1049 [SMTP:7]. This
+ field "allows mail reading systems to automatically identify
+ the type of a structured message body and to process it for
+ display accordingly". [SMTP:7] A User Agent MAY support this
+ field.
+
+ 5.2.14 RFC-822 Date and Time Specification: RFC-822 Section 5
+
+ The syntax for the date is hereby changed to:
+
+ date = 1*2DIGIT month 2*4DIGIT
+
+
+
+
+Internet Engineering Task Force [Page 55]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ All mail software SHOULD use 4-digit years in dates, to ease
+ the transition to the next century.
+
+ There is a strong trend towards the use of numeric timezone
+ indicators, and implementations SHOULD use numeric timezones
+ instead of timezone names. However, all implementations MUST
+ accept either notation. If timezone names are used, they MUST
+ be exactly as defined in RFC-822.
+
+ The military time zones are specified incorrectly in RFC-822:
+ they count the wrong way from UT (the signs are reversed). As
+ a result, military time zones in RFC-822 headers carry no
+ information.
+
+ Finally, note that there is a typo in the definition of "zone"
+ in the syntax summary of appendix D; the correct definition
+ occurs in Section 3 of RFC-822.
+
+ 5.2.15 RFC-822 Syntax Change: RFC-822 Section 6.1
+
+ The syntactic definition of "mailbox" in RFC-822 is hereby
+ changed to:
+
+ mailbox = addr-spec ; simple address
+ / [phrase] route-addr ; name & addr-spec
+
+ That is, the phrase preceding a route address is now OPTIONAL.
+ This change makes the following header field legal, for
+ example:
+
+ From: <craig@nnsc.nsf.net>
+
+ 5.2.16 RFC-822 Local-part: RFC-822 Section 6.2
+
+ The basic mailbox address specification has the form: "local-
+ part@domain". Here "local-part", sometimes called the "left-
+ hand side" of the address, is domain-dependent.
+
+ A host that is forwarding the message but is not the
+ destination host implied by the right-hand side "domain" MUST
+ NOT interpret or modify the "local-part" of the address.
+
+ When mail is to be gatewayed from the Internet mail environment
+ into a foreign mail environment (see Section 5.3.7), routing
+ information for that foreign environment MAY be embedded within
+ the "local-part" of the address. The gateway will then
+ interpret this local part appropriately for the foreign mail
+ environment.
+
+
+
+Internet Engineering Task Force [Page 56]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ DISCUSSION:
+ Although source routes are discouraged within the Internet
+ (see Section 5.2.6), there are non-Internet mail
+ environments whose delivery mechanisms do depend upon
+ source routes. Source routes for extra-Internet
+ environments can generally be buried in the "local-part"
+ of the address (see Section 5.2.16) while mail traverses
+ the Internet. When the mail reaches the appropriate
+ Internet mail gateway, the gateway will interpret the
+ local-part and build the necessary address or route for
+ the target mail environment.
+
+ For example, an Internet host might send mail to:
+ "a!b!c!user@gateway-domain". The complex local part
+ "a!b!c!user" would be uninterpreted within the Internet
+ domain, but could be parsed and understood by the
+ specified mail gateway.
+
+ An embedded source route is sometimes encoded in the
+ "local-part" using "%" as a right-binding routing
+ operator. For example, in:
+
+ user%domain%relay3%relay2@relay1
+
+ the "%" convention implies that the mail is to be routed
+ from "relay1" through "relay2", "relay3", and finally to
+ "user" at "domain". This is commonly known as the "%-
+ hack". It is suggested that "%" have lower precedence
+ than any other routing operator (e.g., "!") hidden in the
+ local-part; for example, "a!b%c" would be interpreted as
+ "(a!b)%c".
+
+ Only the target host (in this case, "relay1") is permitted
+ to analyze the local-part "user%domain%relay3%relay2".
+
+ 5.2.17 Domain Literals: RFC-822 Section 6.2.3
+
+ A mailer MUST be able to accept and parse an Internet domain
+ literal whose content ("dtext"; see RFC-822) is a dotted-
+ decimal host address. This satisfies the requirement of
+ Section 2.1 for the case of mail.
+
+ An SMTP MUST accept and recognize a domain literal for any of
+ its own IP addresses.
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 57]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ 5.2.18 Common Address Formatting Errors: RFC-822 Section 6.1
+
+ Errors in formatting or parsing 822 addresses are unfortunately
+ common. This section mentions only the most common errors. A
+ User Agent MUST accept all valid RFC-822 address formats, and
+ MUST NOT generate illegal address syntax.
+
+ o A common error is to leave out the semicolon after a group
+ identifier.
+
+ o Some systems fail to fully-qualify domain names in
+ messages they generate. The right-hand side of an "@"
+ sign in a header address field MUST be a fully-qualified
+ domain name.
+
+ For example, some systems fail to fully-qualify the From:
+ address; this prevents a "reply" command in the user
+ interface from automatically constructing a return
+ address.
+
+ DISCUSSION:
+ Although RFC-822 allows the local use of abbreviated
+ domain names within a domain, the application of
+ RFC-822 in Internet mail does not allow this. The
+ intent is that an Internet host must not send an SMTP
+ message header containing an abbreviated domain name
+ in an address field. This allows the address fields
+ of the header to be passed without alteration across
+ the Internet, as required in Section 5.2.6.
+
+ o Some systems mis-parse multiple-hop explicit source routes
+ such as:
+
+ @relay1,@relay2,@relay3:user@domain.
+
+
+ o Some systems over-qualify domain names by adding a
+ trailing dot to some or all domain names in addresses or
+ message-ids. This violates RFC-822 syntax.
+
+
+ 5.2.19 Explicit Source Routes: RFC-822 Section 6.2.7
+
+ Internet host software SHOULD NOT create an RFC-822 header
+ containing an address with an explicit source route, but MUST
+ accept such headers for compatibility with earlier systems.
+
+ DISCUSSION:
+
+
+
+Internet Engineering Task Force [Page 58]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ In an understatement, RFC-822 says "The use of explicit
+ source routing is discouraged". Many hosts implemented
+ RFC-822 source routes incorrectly, so the syntax cannot be
+ used unambiguously in practice. Many users feel the
+ syntax is ugly. Explicit source routes are not needed in
+ the mail envelope for delivery; see Section 5.2.6. For
+ all these reasons, explicit source routes using the RFC-
+ 822 notations are not to be used in Internet mail headers.
+
+ As stated in Section 5.2.16, it is necessary to allow an
+ explicit source route to be buried in the local-part of an
+ address, e.g., using the "%-hack", in order to allow mail
+ to be gatewayed into another environment in which explicit
+ source routing is necessary. The vigilant will observe
+ that there is no way for a User Agent to detect and
+ prevent the use of such implicit source routing when the
+ destination is within the Internet. We can only
+ discourage source routing of any kind within the Internet,
+ as unnecessary and undesirable.
+
+ 5.3 SPECIFIC ISSUES
+
+ 5.3.1 SMTP Queueing Strategies
+
+ The common structure of a host SMTP implementation includes
+ user mailboxes, one or more areas for queueing messages in
+ transit, and one or more daemon processes for sending and
+ receiving mail. The exact structure will vary depending on the
+ needs of the users on the host and the number and size of
+ mailing lists supported by the host. We describe several
+ optimizations that have proved helpful, particularly for
+ mailers supporting high traffic levels.
+
+ Any queueing strategy MUST include:
+
+ o Timeouts on all activities. See Section 5.3.2.
+
+ o Never sending error messages in response to error
+ messages.
+
+
+ 5.3.1.1 Sending Strategy
+
+ The general model of a sender-SMTP is one or more processes
+ that periodically attempt to transmit outgoing mail. In a
+ typical system, the program that composes a message has some
+ method for requesting immediate attention for a new piece of
+ outgoing mail, while mail that cannot be transmitted
+
+
+
+Internet Engineering Task Force [Page 59]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ immediately MUST be queued and periodically retried by the
+ sender. A mail queue entry will include not only the
+ message itself but also the envelope information.
+
+ The sender MUST delay retrying a particular destination
+ after one attempt has failed. In general, the retry
+ interval SHOULD be at least 30 minutes; however, more
+ sophisticated and variable strategies will be beneficial
+ when the sender-SMTP can determine the reason for non-
+ delivery.
+
+ Retries continue until the message is transmitted or the
+ sender gives up; the give-up time generally needs to be at
+ least 4-5 days. The parameters to the retry algorithm MUST
+ be configurable.
+
+ A sender SHOULD keep a list of hosts it cannot reach and
+ corresponding timeouts, rather than just retrying queued
+ mail items.
+
+ DISCUSSION:
+ Experience suggests that failures are typically
+ transient (the target system has crashed), favoring a
+ policy of two connection attempts in the first hour the
+ message is in the queue, and then backing off to once
+ every two or three hours.
+
+ The sender-SMTP can shorten the queueing delay by
+ cooperation with the receiver-SMTP. In particular, if
+ mail is received from a particular address, it is good
+ evidence that any mail queued for that host can now be
+ sent.
+
+ The strategy may be further modified as a result of
+ multiple addresses per host (see Section 5.3.4), to
+ optimize delivery time vs. resource usage.
+
+ A sender-SMTP may have a large queue of messages for
+ each unavailable destination host, and if it retried
+ all these messages in every retry cycle, there would be
+ excessive Internet overhead and the daemon would be
+ blocked for a long period. Note that an SMTP can
+ generally determine that a delivery attempt has failed
+ only after a timeout of a minute or more; a one minute
+ timeout per connection will result in a very large
+ delay if it is repeated for dozens or even hundreds of
+ queued messages.
+
+
+
+
+Internet Engineering Task Force [Page 60]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ When the same message is to be delivered to several users on
+ the same host, only one copy of the message SHOULD be
+ transmitted. That is, the sender-SMTP should use the
+ command sequence: RCPT, RCPT,... RCPT, DATA instead of the
+ sequence: RCPT, DATA, RCPT, DATA,... RCPT, DATA.
+ Implementation of this efficiency feature is strongly urged.
+
+ Similarly, the sender-SMTP MAY support multiple concurrent
+ outgoing mail transactions to achieve timely delivery.
+ However, some limit SHOULD be imposed to protect the host
+ from devoting all its resources to mail.
+
+ The use of the different addresses of a multihomed host is
+ discussed below.
+
+ 5.3.1.2 Receiving strategy
+
+ The receiver-SMTP SHOULD attempt to keep a pending listen on
+ the SMTP port at all times. This will require the support
+ of multiple incoming TCP connections for SMTP. Some limit
+ MAY be imposed.
+
+ IMPLEMENTATION:
+ When the receiver-SMTP receives mail from a particular
+ host address, it could notify the sender-SMTP to retry
+ any mail pending for that host address.
+
+ 5.3.2 Timeouts in SMTP
+
+ There are two approaches to timeouts in the sender-SMTP: (a)
+ limit the time for each SMTP command separately, or (b) limit
+ the time for the entire SMTP dialogue for a single mail
+ message. A sender-SMTP SHOULD use option (a), per-command
+ timeouts. Timeouts SHOULD be easily reconfigurable, preferably
+ without recompiling the SMTP code.
+
+ DISCUSSION:
+ Timeouts are an essential feature of an SMTP
+ implementation. If the timeouts are too long (or worse,
+ there are no timeouts), Internet communication failures or
+ software bugs in receiver-SMTP programs can tie up SMTP
+ processes indefinitely. If the timeouts are too short,
+ resources will be wasted with attempts that time out part
+ way through message delivery.
+
+ If option (b) is used, the timeout has to be very large,
+ e.g., an hour, to allow time to expand very large mailing
+ lists. The timeout may also need to increase linearly
+
+
+
+Internet Engineering Task Force [Page 61]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ with the size of the message, to account for the time to
+ transmit a very large message. A large fixed timeout
+ leads to two problems: a failure can still tie up the
+ sender for a very long time, and very large messages may
+ still spuriously time out (which is a wasteful failure!).
+
+ Using the recommended option (a), a timer is set for each
+ SMTP command and for each buffer of the data transfer.
+ The latter means that the overall timeout is inherently
+ proportional to the size of the message.
+
+ Based on extensive experience with busy mail-relay hosts, the
+ minimum per-command timeout values SHOULD be as follows:
+
+ o Initial 220 Message: 5 minutes
+
+ A Sender-SMTP process needs to distinguish between a
+ failed TCP connection and a delay in receiving the initial
+ 220 greeting message. Many receiver-SMTPs will accept a
+ TCP connection but delay delivery of the 220 message until
+ their system load will permit more mail to be processed.
+
+ o MAIL Command: 5 minutes
+
+
+ o RCPT Command: 5 minutes
+
+ A longer timeout would be required if processing of
+ mailing lists and aliases were not deferred until after
+ the message was accepted.
+
+ o DATA Initiation: 2 minutes
+
+ This is while awaiting the "354 Start Input" reply to a
+ DATA command.
+
+ o Data Block: 3 minutes
+
+ This is while awaiting the completion of each TCP SEND
+ call transmitting a chunk of data.
+
+ o DATA Termination: 10 minutes.
+
+ This is while awaiting the "250 OK" reply. When the
+ receiver gets the final period terminating the message
+ data, it typically performs processing to deliver the
+ message to a user mailbox. A spurious timeout at this
+ point would be very wasteful, since the message has been
+
+
+
+Internet Engineering Task Force [Page 62]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ successfully sent.
+
+ A receiver-SMTP SHOULD have a timeout of at least 5 minutes
+ while it is awaiting the next command from the sender.
+
+ 5.3.3 Reliable Mail Receipt
+
+ When the receiver-SMTP accepts a piece of mail (by sending a
+ "250 OK" message in response to DATA), it is accepting
+ responsibility for delivering or relaying the message. It must
+ take this responsibility seriously, i.e., it MUST NOT lose the
+ message for frivolous reasons, e.g., because the host later
+ crashes or because of a predictable resource shortage.
+
+ If there is a delivery failure after acceptance of a message,
+ the receiver-SMTP MUST formulate and mail a notification
+ message. This notification MUST be sent using a null ("<>")
+ reverse path in the envelope; see Section 3.6 of RFC-821. The
+ recipient of this notification SHOULD be the address from the
+ envelope return path (or the Return-Path: line). However, if
+ this address is null ("<>"), the receiver-SMTP MUST NOT send a
+ notification. If the address is an explicit source route, it
+ SHOULD be stripped down to its final hop.
+
+ DISCUSSION:
+ For example, suppose that an error notification must be
+ sent for a message that arrived with:
+ "MAIL FROM:<@a,@b:user@d>". The notification message
+ should be sent to: "RCPT TO:<user@d>".
+
+ Some delivery failures after the message is accepted by
+ SMTP will be unavoidable. For example, it may be
+ impossible for the receiver-SMTP to validate all the
+ delivery addresses in RCPT command(s) due to a "soft"
+ domain system error or because the target is a mailing
+ list (see earlier discussion of RCPT).
+
+ To avoid receiving duplicate messages as the result of
+ timeouts, a receiver-SMTP MUST seek to minimize the time
+ required to respond to the final "." that ends a message
+ transfer. See RFC-1047 [SMTP:4] for a discussion of this
+ problem.
+
+ 5.3.4 Reliable Mail Transmission
+
+ To transmit a message, a sender-SMTP determines the IP address
+ of the target host from the destination address in the
+ envelope. Specifically, it maps the string to the right of the
+
+
+
+Internet Engineering Task Force [Page 63]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ "@" sign into an IP address. This mapping or the transfer
+ itself may fail with a soft error, in which case the sender-
+ SMTP will requeue the outgoing mail for a later retry, as
+ required in Section 5.3.1.1.
+
+ When it succeeds, the mapping can result in a list of
+ alternative delivery addresses rather than a single address,
+ because of (a) multiple MX records, (b) multihoming, or both.
+ To provide reliable mail transmission, the sender-SMTP MUST be
+ able to try (and retry) each of the addresses in this list in
+ order, until a delivery attempt succeeds. However, there MAY
+ also be a configurable limit on the number of alternate
+ addresses that can be tried. In any case, a host SHOULD try at
+ least two addresses.
+
+ The following information is to be used to rank the host
+ addresses:
+
+ (1) Multiple MX Records -- these contain a preference
+ indication that should be used in sorting. If there are
+ multiple destinations with the same preference and there
+ is no clear reason to favor one (e.g., by address
+ preference), then the sender-SMTP SHOULD pick one at
+ random to spread the load across multiple mail exchanges
+ for a specific organization; note that this is a
+ refinement of the procedure in [DNS:3].
+
+ (2) Multihomed host -- The destination host (perhaps taken
+ from the preferred MX record) may be multihomed, in which
+ case the domain name resolver will return a list of
+ alternative IP addresses. It is the responsibility of the
+ domain name resolver interface (see Section 6.1.3.4 below)
+ to have ordered this list by decreasing preference, and
+ SMTP MUST try them in the order presented.
+
+ DISCUSSION:
+ Although the capability to try multiple alternative
+ addresses is required, there may be circumstances where
+ specific installations want to limit or disable the use of
+ alternative addresses. The question of whether a sender
+ should attempt retries using the different addresses of a
+ multihomed host has been controversial. The main argument
+ for using the multiple addresses is that it maximizes the
+ probability of timely delivery, and indeed sometimes the
+ probability of any delivery; the counter argument is that
+ it may result in unnecessary resource use.
+
+ Note that resource use is also strongly determined by the
+
+
+
+Internet Engineering Task Force [Page 64]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ sending strategy discussed in Section 5.3.1.
+
+ 5.3.5 Domain Name Support
+
+ SMTP implementations MUST use the mechanism defined in Section
+ 6.1 for mapping between domain names and IP addresses. This
+ means that every Internet SMTP MUST include support for the
+ Internet DNS.
+
+ In particular, a sender-SMTP MUST support the MX record scheme
+ [SMTP:3]. See also Section 7.4 of [DNS:2] for information on
+ domain name support for SMTP.
+
+ 5.3.6 Mailing Lists and Aliases
+
+ An SMTP-capable host SHOULD support both the alias and the list
+ form of address expansion for multiple delivery. When a
+ message is delivered or forwarded to each address of an
+ expanded list form, the return address in the envelope
+ ("MAIL FROM:") MUST be changed to be the address of a person
+ who administers the list, but the message header MUST be left
+ unchanged; in particular, the "From" field of the message is
+ unaffected.
+
+ DISCUSSION:
+ An important mail facility is a mechanism for multi-
+ destination delivery of a single message, by transforming
+ or "expanding" a pseudo-mailbox address into a list of
+ destination mailbox addresses. When a message is sent to
+ such a pseudo-mailbox (sometimes called an "exploder"),
+ copies are forwarded or redistributed to each mailbox in
+ the expanded list. We classify such a pseudo-mailbox as
+ an "alias" or a "list", depending upon the expansion
+ rules:
+
+ (a) Alias
+
+ To expand an alias, the recipient mailer simply
+ replaces the pseudo-mailbox address in the envelope
+ with each of the expanded addresses in turn; the rest
+ of the envelope and the message body are left
+ unchanged. The message is then delivered or
+ forwarded to each expanded address.
+
+ (b) List
+
+ A mailing list may be said to operate by
+ "redistribution" rather than by "forwarding". To
+
+
+
+Internet Engineering Task Force [Page 65]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ expand a list, the recipient mailer replaces the
+ pseudo-mailbox address in the envelope with each of
+ the expanded addresses in turn. The return address in
+ the envelope is changed so that all error messages
+ generated by the final deliveries will be returned to
+ a list administrator, not to the message originator,
+ who generally has no control over the contents of the
+ list and will typically find error messages annoying.
+
+
+ 5.3.7 Mail Gatewaying
+
+ Gatewaying mail between different mail environments, i.e.,
+ different mail formats and protocols, is complex and does not
+ easily yield to standardization. See for example [SMTP:5a],
+ [SMTP:5b]. However, some general requirements may be given for
+ a gateway between the Internet and another mail environment.
+
+ (A) Header fields MAY be rewritten when necessary as messages
+ are gatewayed across mail environment boundaries.
+
+ DISCUSSION:
+ This may involve interpreting the local-part of the
+ destination address, as suggested in Section 5.2.16.
+
+ The other mail systems gatewayed to the Internet
+ generally use a subset of RFC-822 headers, but some
+ of them do not have an equivalent to the SMTP
+ envelope. Therefore, when a message leaves the
+ Internet environment, it may be necessary to fold the
+ SMTP envelope information into the message header. A
+ possible solution would be to create new header
+ fields to carry the envelope information (e.g., "X-
+ SMTP-MAIL:" and "X-SMTP-RCPT:"); however, this would
+ require changes in mail programs in the foreign
+ environment.
+
+ (B) When forwarding a message into or out of the Internet
+ environment, a gateway MUST prepend a Received: line, but
+ it MUST NOT alter in any way a Received: line that is
+ already in the header.
+
+ DISCUSSION:
+ This requirement is a subset of the general
+ "Received:" line requirement of Section 5.2.8; it is
+ restated here for emphasis.
+
+ Received: fields of messages originating from other
+
+
+
+Internet Engineering Task Force [Page 66]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ environments may not conform exactly to RFC822.
+ However, the most important use of Received: lines is
+ for debugging mail faults, and this debugging can be
+ severely hampered by well-meaning gateways that try
+ to "fix" a Received: line.
+
+ The gateway is strongly encouraged to indicate the
+ environment and protocol in the "via" clauses of
+ Received field(s) that it supplies.
+
+ (C) From the Internet side, the gateway SHOULD accept all
+ valid address formats in SMTP commands and in RFC-822
+ headers, and all valid RFC-822 messages. Although a
+ gateway must accept an RFC-822 explicit source route
+ ("@...:" format) in either the RFC-822 header or in the
+ envelope, it MAY or may not act on the source route; see
+ Sections 5.2.6 and 5.2.19.
+
+ DISCUSSION:
+ It is often tempting to restrict the range of
+ addresses accepted at the mail gateway to simplify
+ the translation into addresses for the remote
+ environment. This practice is based on the
+ assumption that mail users have control over the
+ addresses their mailers send to the mail gateway. In
+ practice, however, users have little control over the
+ addresses that are finally sent; their mailers are
+ free to change addresses into any legal RFC-822
+ format.
+
+ (D) The gateway MUST ensure that all header fields of a
+ message that it forwards into the Internet meet the
+ requirements for Internet mail. In particular, all
+ addresses in "From:", "To:", "Cc:", etc., fields must be
+ transformed (if necessary) to satisfy RFC-822 syntax, and
+ they must be effective and useful for sending replies.
+
+
+ (E) The translation algorithm used to convert mail from the
+ Internet protocols to another environment's protocol
+ SHOULD try to ensure that error messages from the foreign
+ mail environment are delivered to the return path from the
+ SMTP envelope, not to the sender listed in the "From:"
+ field of the RFC-822 message.
+
+ DISCUSSION:
+ Internet mail lists usually place the address of the
+ mail list maintainer in the envelope but leave the
+
+
+
+Internet Engineering Task Force [Page 67]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ original message header intact (with the "From:"
+ field containing the original sender). This yields
+ the behavior the average recipient expects: a reply
+ to the header gets sent to the original sender, not
+ to a mail list maintainer; however, errors get sent
+ to the maintainer (who can fix the problem) and not
+ the sender (who probably cannot).
+
+ (F) Similarly, when forwarding a message from another
+ environment into the Internet, the gateway SHOULD set the
+ envelope return path in accordance with an error message
+ return address, if any, supplied by the foreign
+ environment.
+
+
+ 5.3.8 Maximum Message Size
+
+ Mailer software MUST be able to send and receive messages of at
+ least 64K bytes in length (including header), and a much larger
+ maximum size is highly desirable.
+
+ DISCUSSION:
+ Although SMTP does not define the maximum size of a
+ message, many systems impose implementation limits.
+
+ The current de facto minimum limit in the Internet is 64K
+ bytes. However, electronic mail is used for a variety of
+ purposes that create much larger messages. For example,
+ mail is often used instead of FTP for transmitting ASCII
+ files, and in particular to transmit entire documents. As
+ a result, messages can be 1 megabyte or even larger. We
+ note that the present document together with its lower-
+ layer companion contains 0.5 megabytes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 68]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ 5.4 SMTP REQUIREMENTS SUMMARY
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION | | | |T|T|e
+-----------------------------------------------|----------|-|-|-|-|-|--
+ | | | | | | |
+RECEIVER-SMTP: | | | | | | |
+ Implement VRFY |5.2.3 |x| | | | |
+ Implement EXPN |5.2.3 | |x| | | |
+ EXPN, VRFY configurable |5.2.3 | | |x| | |
+ Implement SEND, SOML, SAML |5.2.4 | | |x| | |
+ Verify HELO parameter |5.2.5 | | |x| | |
+ Refuse message with bad HELO |5.2.5 | | | | |x|
+ Accept explicit src-route syntax in env. |5.2.6 |x| | | | |
+ Support "postmaster" |5.2.7 |x| | | | |
+ Process RCPT when received (except lists) |5.2.7 | | |x| | |
+ Long delay of RCPT responses |5.2.7 | | | | |x|
+ | | | | | | |
+ Add Received: line |5.2.8 |x| | | | |
+ Received: line include domain literal |5.2.8 | |x| | | |
+ Change previous Received: line |5.2.8 | | | | |x|
+ Pass Return-Path info (final deliv/gwy) |5.2.8 |x| | | | |
+ Support empty reverse path |5.2.9 |x| | | | |
+ Send only official reply codes |5.2.10 | |x| | | |
+ Send text from RFC-821 when appropriate |5.2.10 | |x| | | |
+ Delete "." for transparency |5.2.11 |x| | | | |
+ Accept and recognize self domain literal(s) |5.2.17 |x| | | | |
+ | | | | | | |
+ Error message about error message |5.3.1 | | | | |x|
+ Keep pending listen on SMTP port |5.3.1.2 | |x| | | |
+ Provide limit on recv concurrency |5.3.1.2 | | |x| | |
+ Wait at least 5 mins for next sender cmd |5.3.2 | |x| | | |
+ Avoidable delivery failure after "250 OK" |5.3.3 | | | | |x|
+ Send error notification msg after accept |5.3.3 |x| | | | |
+ Send using null return path |5.3.3 |x| | | | |
+ Send to envelope return path |5.3.3 | |x| | | |
+ Send to null address |5.3.3 | | | | |x|
+ Strip off explicit src route |5.3.3 | |x| | | |
+ Minimize acceptance delay (RFC-1047) |5.3.3 |x| | | | |
+-----------------------------------------------|----------|-|-|-|-|-|--
+
+
+
+Internet Engineering Task Force [Page 69]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ | | | | | | |
+SENDER-SMTP: | | | | | | |
+ Canonicalized domain names in MAIL, RCPT |5.2.2 |x| | | | |
+ Implement SEND, SOML, SAML |5.2.4 | | |x| | |
+ Send valid principal host name in HELO |5.2.5 |x| | | | |
+ Send explicit source route in RCPT TO: |5.2.6 | | | |x| |
+ Use only reply code to determine action |5.2.10 |x| | | | |
+ Use only high digit of reply code when poss. |5.2.10 | |x| | | |
+ Add "." for transparency |5.2.11 |x| | | | |
+ | | | | | | |
+ Retry messages after soft failure |5.3.1.1 |x| | | | |
+ Delay before retry |5.3.1.1 |x| | | | |
+ Configurable retry parameters |5.3.1.1 |x| | | | |
+ Retry once per each queued dest host |5.3.1.1 | |x| | | |
+ Multiple RCPT's for same DATA |5.3.1.1 | |x| | | |
+ Support multiple concurrent transactions |5.3.1.1 | | |x| | |
+ Provide limit on concurrency |5.3.1.1 | |x| | | |
+ | | | | | | |
+ Timeouts on all activities |5.3.1 |x| | | | |
+ Per-command timeouts |5.3.2 | |x| | | |
+ Timeouts easily reconfigurable |5.3.2 | |x| | | |
+ Recommended times |5.3.2 | |x| | | |
+ Try alternate addr's in order |5.3.4 |x| | | | |
+ Configurable limit on alternate tries |5.3.4 | | |x| | |
+ Try at least two alternates |5.3.4 | |x| | | |
+ Load-split across equal MX alternates |5.3.4 | |x| | | |
+ Use the Domain Name System |5.3.5 |x| | | | |
+ Support MX records |5.3.5 |x| | | | |
+ Use WKS records in MX processing |5.2.12 | | | |x| |
+-----------------------------------------------|----------|-|-|-|-|-|--
+ | | | | | | |
+MAIL FORWARDING: | | | | | | |
+ Alter existing header field(s) |5.2.6 | | | |x| |
+ Implement relay function: 821/section 3.6 |5.2.6 | | |x| | |
+ If not, deliver to RHS domain |5.2.6 | |x| | | |
+ Interpret 'local-part' of addr |5.2.16 | | | | |x|
+ | | | | | | |
+MAILING LISTS AND ALIASES | | | | | | |
+ Support both |5.3.6 | |x| | | |
+ Report mail list error to local admin. |5.3.6 |x| | | | |
+ | | | | | | |
+MAIL GATEWAYS: | | | | | | |
+ Embed foreign mail route in local-part |5.2.16 | | |x| | |
+ Rewrite header fields when necessary |5.3.7 | | |x| | |
+ Prepend Received: line |5.3.7 |x| | | | |
+ Change existing Received: line |5.3.7 | | | | |x|
+ Accept full RFC-822 on Internet side |5.3.7 | |x| | | |
+ Act on RFC-822 explicit source route |5.3.7 | | |x| | |
+
+
+
+Internet Engineering Task Force [Page 70]
+
+
+
+
+RFC1123 MAIL -- SMTP & RFC-822 October 1989
+
+
+ Send only valid RFC-822 on Internet side |5.3.7 |x| | | | |
+ Deliver error msgs to envelope addr |5.3.7 | |x| | | |
+ Set env return path from err return addr |5.3.7 | |x| | | |
+ | | | | | | |
+USER AGENT -- RFC-822 | | | | | | |
+ Allow user to enter <route> address |5.2.6 | | | |x| |
+ Support RFC-1049 Content Type field |5.2.13 | | |x| | |
+ Use 4-digit years |5.2.14 | |x| | | |
+ Generate numeric timezones |5.2.14 | |x| | | |
+ Accept all timezones |5.2.14 |x| | | | |
+ Use non-num timezones from RFC-822 |5.2.14 |x| | | | |
+ Omit phrase before route-addr |5.2.15 | | |x| | |
+ Accept and parse dot.dec. domain literals |5.2.17 |x| | | | |
+ Accept all RFC-822 address formats |5.2.18 |x| | | | |
+ Generate invalid RFC-822 address format |5.2.18 | | | | |x|
+ Fully-qualified domain names in header |5.2.18 |x| | | | |
+ Create explicit src route in header |5.2.19 | | | |x| |
+ Accept explicit src route in header |5.2.19 |x| | | | |
+ | | | | | | |
+Send/recv at least 64KB messages |5.3.8 |x| | | | |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 71]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+6. SUPPORT SERVICES
+
+ 6.1 DOMAIN NAME TRANSLATION
+
+ 6.1.1 INTRODUCTION
+
+ Every host MUST implement a resolver for the Domain Name System
+ (DNS), and it MUST implement a mechanism using this DNS
+ resolver to convert host names to IP addresses and vice-versa
+ [DNS:1, DNS:2].
+
+ In addition to the DNS, a host MAY also implement a host name
+ translation mechanism that searches a local Internet host
+ table. See Section 6.1.3.8 for more information on this
+ option.
+
+ DISCUSSION:
+ Internet host name translation was originally performed by
+ searching local copies of a table of all hosts. This
+ table became too large to update and distribute in a
+ timely manner and too large to fit into many hosts, so the
+ DNS was invented.
+
+ The DNS creates a distributed database used primarily for
+ the translation between host names and host addresses.
+ Implementation of DNS software is required. The DNS
+ consists of two logically distinct parts: name servers and
+ resolvers (although implementations often combine these
+ two logical parts in the interest of efficiency) [DNS:2].
+
+ Domain name servers store authoritative data about certain
+ sections of the database and answer queries about the
+ data. Domain resolvers query domain name servers for data
+ on behalf of user processes. Every host therefore needs a
+ DNS resolver; some host machines will also need to run
+ domain name servers. Since no name server has complete
+ information, in general it is necessary to obtain
+ information from more than one name server to resolve a
+ query.
+
+ 6.1.2 PROTOCOL WALK-THROUGH
+
+ An implementor must study references [DNS:1] and [DNS:2]
+ carefully. They provide a thorough description of the theory,
+ protocol, and implementation of the domain name system, and
+ reflect several years of experience.
+
+
+
+
+
+Internet Engineering Task Force [Page 72]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ 6.1.2.1 Resource Records with Zero TTL: RFC-1035 Section 3.2.1
+
+ All DNS name servers and resolvers MUST properly handle RRs
+ with a zero TTL: return the RR to the client but do not
+ cache it.
+
+ DISCUSSION:
+ Zero TTL values are interpreted to mean that the RR can
+ only be used for the transaction in progress, and
+ should not be cached; they are useful for extremely
+ volatile data.
+
+ 6.1.2.2 QCLASS Values: RFC-1035 Section 3.2.5
+
+ A query with "QCLASS=*" SHOULD NOT be used unless the
+ requestor is seeking data from more than one class. In
+ particular, if the requestor is only interested in Internet
+ data types, QCLASS=IN MUST be used.
+
+ 6.1.2.3 Unused Fields: RFC-1035 Section 4.1.1
+
+ Unused fields in a query or response message MUST be zero.
+
+ 6.1.2.4 Compression: RFC-1035 Section 4.1.4
+
+ Name servers MUST use compression in responses.
+
+ DISCUSSION:
+ Compression is essential to avoid overflowing UDP
+ datagrams; see Section 6.1.3.2.
+
+ 6.1.2.5 Misusing Configuration Info: RFC-1035 Section 6.1.2
+
+ Recursive name servers and full-service resolvers generally
+ have some configuration information containing hints about
+ the location of root or local name servers. An
+ implementation MUST NOT include any of these hints in a
+ response.
+
+ DISCUSSION:
+ Many implementors have found it convenient to store
+ these hints as if they were cached data, but some
+ neglected to ensure that this "cached data" was not
+ included in responses. This has caused serious
+ problems in the Internet when the hints were obsolete
+ or incorrect.
+
+
+
+
+
+Internet Engineering Task Force [Page 73]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ 6.1.3 SPECIFIC ISSUES
+
+ 6.1.3.1 Resolver Implementation
+
+ A name resolver SHOULD be able to multiplex concurrent
+ requests if the host supports concurrent processes.
+
+ In implementing a DNS resolver, one of two different models
+ MAY optionally be chosen: a full-service resolver, or a stub
+ resolver.
+
+
+ (A) Full-Service Resolver
+
+ A full-service resolver is a complete implementation of
+ the resolver service, and is capable of dealing with
+ communication failures, failure of individual name
+ servers, location of the proper name server for a given
+ name, etc. It must satisfy the following requirements:
+
+ o The resolver MUST implement a local caching
+ function to avoid repeated remote access for
+ identical requests, and MUST time out information
+ in the cache.
+
+ o The resolver SHOULD be configurable with start-up
+ information pointing to multiple root name servers
+ and multiple name servers for the local domain.
+ This insures that the resolver will be able to
+ access the whole name space in normal cases, and
+ will be able to access local domain information
+ should the local network become disconnected from
+ the rest of the Internet.
+
+
+ (B) Stub Resolver
+
+ A "stub resolver" relies on the services of a recursive
+ name server on the connected network or a "nearby"
+ network. This scheme allows the host to pass on the
+ burden of the resolver function to a name server on
+ another host. This model is often essential for less
+ capable hosts, such as PCs, and is also recommended
+ when the host is one of several workstations on a local
+ network, because it allows all of the workstations to
+ share the cache of the recursive name server and hence
+ reduce the number of domain requests exported by the
+ local network.
+
+
+
+Internet Engineering Task Force [Page 74]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ At a minimum, the stub resolver MUST be capable of
+ directing its requests to redundant recursive name
+ servers. Note that recursive name servers are allowed
+ to restrict the sources of requests that they will
+ honor, so the host administrator must verify that the
+ service will be provided. Stub resolvers MAY implement
+ caching if they choose, but if so, MUST timeout cached
+ information.
+
+
+ 6.1.3.2 Transport Protocols
+
+ DNS resolvers and recursive servers MUST support UDP, and
+ SHOULD support TCP, for sending (non-zone-transfer) queries.
+ Specifically, a DNS resolver or server that is sending a
+ non-zone-transfer query MUST send a UDP query first. If the
+ Answer section of the response is truncated and if the
+ requester supports TCP, it SHOULD try the query again using
+ TCP.
+
+ DNS servers MUST be able to service UDP queries and SHOULD
+ be able to service TCP queries. A name server MAY limit the
+ resources it devotes to TCP queries, but it SHOULD NOT
+ refuse to service a TCP query just because it would have
+ succeeded with UDP.
+
+ Truncated responses MUST NOT be saved (cached) and later
+ used in such a way that the fact that they are truncated is
+ lost.
+
+ DISCUSSION:
+ UDP is preferred over TCP for queries because UDP
+ queries have much lower overhead, both in packet count
+ and in connection state. The use of UDP is essential
+ for heavily-loaded servers, especially the root
+ servers. UDP also offers additional robustness, since
+ a resolver can attempt several UDP queries to different
+ servers for the cost of a single TCP query.
+
+ It is possible for a DNS response to be truncated,
+ although this is a very rare occurrence in the present
+ Internet DNS. Practically speaking, truncation cannot
+ be predicted, since it is data-dependent. The
+ dependencies include the number of RRs in the answer,
+ the size of each RR, and the savings in space realized
+ by the name compression algorithm. As a rule of thumb,
+ truncation in NS and MX lists should not occur for
+ answers containing 15 or fewer RRs.
+
+
+
+Internet Engineering Task Force [Page 75]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ Whether it is possible to use a truncated answer
+ depends on the application. A mailer must not use a
+ truncated MX response, since this could lead to mail
+ loops.
+
+ Responsible practices can make UDP suffice in the vast
+ majority of cases. Name servers must use compression
+ in responses. Resolvers must differentiate truncation
+ of the Additional section of a response (which only
+ loses extra information) from truncation of the Answer
+ section (which for MX records renders the response
+ unusable by mailers). Database administrators should
+ list only a reasonable number of primary names in lists
+ of name servers, MX alternatives, etc.
+
+ However, it is also clear that some new DNS record
+ types defined in the future will contain information
+ exceeding the 512 byte limit that applies to UDP, and
+ hence will require TCP. Thus, resolvers and name
+ servers should implement TCP services as a backup to
+ UDP today, with the knowledge that they will require
+ the TCP service in the future.
+
+ By private agreement, name servers and resolvers MAY arrange
+ to use TCP for all traffic between themselves. TCP MUST be
+ used for zone transfers.
+
+ A DNS server MUST have sufficient internal concurrency that
+ it can continue to process UDP queries while awaiting a
+ response or performing a zone transfer on an open TCP
+ connection [DNS:2].
+
+ A server MAY support a UDP query that is delivered using an
+ IP broadcast or multicast address. However, the Recursion
+ Desired bit MUST NOT be set in a query that is multicast,
+ and MUST be ignored by name servers receiving queries via a
+ broadcast or multicast address. A host that sends broadcast
+ or multicast DNS queries SHOULD send them only as occasional
+ probes, caching the IP address(es) it obtains from the
+ response(s) so it can normally send unicast queries.
+
+ DISCUSSION:
+ Broadcast or (especially) IP multicast can provide a
+ way to locate nearby name servers without knowing their
+ IP addresses in advance. However, general broadcasting
+ of recursive queries can result in excessive and
+ unnecessary load on both network and servers.
+
+
+
+
+Internet Engineering Task Force [Page 76]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ 6.1.3.3 Efficient Resource Usage
+
+ The following requirements on servers and resolvers are very
+ important to the health of the Internet as a whole,
+ particularly when DNS services are invoked repeatedly by
+ higher level automatic servers, such as mailers.
+
+ (1) The resolver MUST implement retransmission controls to
+ insure that it does not waste communication bandwidth,
+ and MUST impose finite bounds on the resources consumed
+ to respond to a single request. See [DNS:2] pages 43-
+ 44 for specific recommendations.
+
+ (2) After a query has been retransmitted several times
+ without a response, an implementation MUST give up and
+ return a soft error to the application.
+
+ (3) All DNS name servers and resolvers SHOULD cache
+ temporary failures, with a timeout period of the order
+ of minutes.
+
+ DISCUSSION:
+ This will prevent applications that immediately
+ retry soft failures (in violation of Section 2.2
+ of this document) from generating excessive DNS
+ traffic.
+
+ (4) All DNS name servers and resolvers SHOULD cache
+ negative responses that indicate the specified name, or
+ data of the specified type, does not exist, as
+ described in [DNS:2].
+
+ (5) When a DNS server or resolver retries a UDP query, the
+ retry interval SHOULD be constrained by an exponential
+ backoff algorithm, and SHOULD also have upper and lower
+ bounds.
+
+ IMPLEMENTATION:
+ A measured RTT and variance (if available) should
+ be used to calculate an initial retransmission
+ interval. If this information is not available, a
+ default of no less than 5 seconds should be used.
+ Implementations may limit the retransmission
+ interval, but this limit must exceed twice the
+ Internet maximum segment lifetime plus service
+ delay at the name server.
+
+ (6) When a resolver or server receives a Source Quench for
+
+
+
+Internet Engineering Task Force [Page 77]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ a query it has issued, it SHOULD take steps to reduce
+ the rate of querying that server in the near future. A
+ server MAY ignore a Source Quench that it receives as
+ the result of sending a response datagram.
+
+ IMPLEMENTATION:
+ One recommended action to reduce the rate is to
+ send the next query attempt to an alternate
+ server, if there is one available. Another is to
+ backoff the retry interval for the same server.
+
+
+ 6.1.3.4 Multihomed Hosts
+
+ When the host name-to-address function encounters a host
+ with multiple addresses, it SHOULD rank or sort the
+ addresses using knowledge of the immediately connected
+ network number(s) and any other applicable performance or
+ history information.
+
+ DISCUSSION:
+ The different addresses of a multihomed host generally
+ imply different Internet paths, and some paths may be
+ preferable to others in performance, reliability, or
+ administrative restrictions. There is no general way
+ for the domain system to determine the best path. A
+ recommended approach is to base this decision on local
+ configuration information set by the system
+ administrator.
+
+ IMPLEMENTATION:
+ The following scheme has been used successfully:
+
+ (a) Incorporate into the host configuration data a
+ Network-Preference List, that is simply a list of
+ networks in preferred order. This list may be
+ empty if there is no preference.
+
+ (b) When a host name is mapped into a list of IP
+ addresses, these addresses should be sorted by
+ network number, into the same order as the
+ corresponding networks in the Network-Preference
+ List. IP addresses whose networks do not appear
+ in the Network-Preference List should be placed at
+ the end of the list.
+
+
+
+
+
+
+Internet Engineering Task Force [Page 78]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ 6.1.3.5 Extensibility
+
+ DNS software MUST support all well-known, class-independent
+ formats [DNS:2], and SHOULD be written to minimize the
+ trauma associated with the introduction of new well-known
+ types and local experimentation with non-standard types.
+
+ DISCUSSION:
+ The data types and classes used by the DNS are
+ extensible, and thus new types will be added and old
+ types deleted or redefined. Introduction of new data
+ types ought to be dependent only upon the rules for
+ compression of domain names inside DNS messages, and
+ the translation between printable (i.e., master file)
+ and internal formats for Resource Records (RRs).
+
+ Compression relies on knowledge of the format of data
+ inside a particular RR. Hence compression must only be
+ used for the contents of well-known, class-independent
+ RRs, and must never be used for class-specific RRs or
+ RR types that are not well-known. The owner name of an
+ RR is always eligible for compression.
+
+ A name server may acquire, via zone transfer, RRs that
+ the server doesn't know how to convert to printable
+ format. A resolver can receive similar information as
+ the result of queries. For proper operation, this data
+ must be preserved, and hence the implication is that
+ DNS software cannot use textual formats for internal
+ storage.
+
+ The DNS defines domain name syntax very generally -- a
+ string of labels each containing up to 63 8-bit octets,
+ separated by dots, and with a maximum total of 255
+ octets. Particular applications of the DNS are
+ permitted to further constrain the syntax of the domain
+ names they use, although the DNS deployment has led to
+ some applications allowing more general names. In
+ particular, Section 2.1 of this document liberalizes
+ slightly the syntax of a legal Internet host name that
+ was defined in RFC-952 [DNS:4].
+
+ 6.1.3.6 Status of RR Types
+
+ Name servers MUST be able to load all RR types except MD and
+ MF from configuration files. The MD and MF types are
+ obsolete and MUST NOT be implemented; in particular, name
+ servers MUST NOT load these types from configuration files.
+
+
+
+Internet Engineering Task Force [Page 79]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ DISCUSSION:
+ The RR types MB, MG, MR, NULL, MINFO and RP are
+ considered experimental, and applications that use the
+ DNS cannot expect these RR types to be supported by
+ most domains. Furthermore these types are subject to
+ redefinition.
+
+ The TXT and WKS RR types have not been widely used by
+ Internet sites; as a result, an application cannot rely
+ on the the existence of a TXT or WKS RR in most
+ domains.
+
+ 6.1.3.7 Robustness
+
+ DNS software may need to operate in environments where the
+ root servers or other servers are unavailable due to network
+ connectivity or other problems. In this situation, DNS name
+ servers and resolvers MUST continue to provide service for
+ the reachable part of the name space, while giving temporary
+ failures for the rest.
+
+ DISCUSSION:
+ Although the DNS is meant to be used primarily in the
+ connected Internet, it should be possible to use the
+ system in networks which are unconnected to the
+ Internet. Hence implementations must not depend on
+ access to root servers before providing service for
+ local names.
+
+ 6.1.3.8 Local Host Table
+
+ DISCUSSION:
+ A host may use a local host table as a backup or
+ supplement to the DNS. This raises the question of
+ which takes precedence, the DNS or the host table; the
+ most flexible approach would make this a configuration
+ option.
+
+ Typically, the contents of such a supplementary host
+ table will be determined locally by the site. However,
+ a publically-available table of Internet hosts is
+ maintained by the DDN Network Information Center (DDN
+ NIC), with a format documented in [DNS:4]. This table
+ can be retrieved from the DDN NIC using a protocol
+ described in [DNS:5]. It must be noted that this table
+ contains only a small fraction of all Internet hosts.
+ Hosts using this protocol to retrieve the DDN NIC host
+ table should use the VERSION command to check if the
+
+
+
+Internet Engineering Task Force [Page 80]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ table has changed before requesting the entire table
+ with the ALL command. The VERSION identifier should be
+ treated as an arbitrary string and tested only for
+ equality; no numerical sequence may be assumed.
+
+ The DDN NIC host table includes administrative
+ information that is not needed for host operation and
+ is therefore not currently included in the DNS
+ database; examples include network and gateway entries.
+ However, much of this additional information will be
+ added to the DNS in the future. Conversely, the DNS
+ provides essential services (in particular, MX records)
+ that are not available from the DDN NIC host table.
+
+ 6.1.4 DNS USER INTERFACE
+
+ 6.1.4.1 DNS Administration
+
+ This document is concerned with design and implementation
+ issues in host software, not with administrative or
+ operational issues. However, administrative issues are of
+ particular importance in the DNS, since errors in particular
+ segments of this large distributed database can cause poor
+ or erroneous performance for many sites. These issues are
+ discussed in [DNS:6] and [DNS:7].
+
+ 6.1.4.2 DNS User Interface
+
+ Hosts MUST provide an interface to the DNS for all
+ application programs running on the host. This interface
+ will typically direct requests to a system process to
+ perform the resolver function [DNS:1, 6.1:2].
+
+ At a minimum, the basic interface MUST support a request for
+ all information of a specific type and class associated with
+ a specific name, and it MUST return either all of the
+ requested information, a hard error code, or a soft error
+ indication. When there is no error, the basic interface
+ returns the complete response information without
+ modification, deletion, or ordering, so that the basic
+ interface will not need to be changed to accommodate new
+ data types.
+
+ DISCUSSION:
+ The soft error indication is an essential part of the
+ interface, since it may not always be possible to
+ access particular information from the DNS; see Section
+ 6.1.3.3.
+
+
+
+Internet Engineering Task Force [Page 81]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ A host MAY provide other DNS interfaces tailored to
+ particular functions, transforming the raw domain data into
+ formats more suited to these functions. In particular, a
+ host MUST provide a DNS interface to facilitate translation
+ between host addresses and host names.
+
+ 6.1.4.3 Interface Abbreviation Facilities
+
+ User interfaces MAY provide a method for users to enter
+ abbreviations for commonly-used names. Although the
+ definition of such methods is outside of the scope of the
+ DNS specification, certain rules are necessary to insure
+ that these methods allow access to the entire DNS name space
+ and to prevent excessive use of Internet resources.
+
+ If an abbreviation method is provided, then:
+
+ (a) There MUST be some convention for denoting that a name
+ is already complete, so that the abbreviation method(s)
+ are suppressed. A trailing dot is the usual method.
+
+ (b) Abbreviation expansion MUST be done exactly once, and
+ MUST be done in the context in which the name was
+ entered.
+
+
+ DISCUSSION:
+ For example, if an abbreviation is used in a mail
+ program for a destination, the abbreviation should be
+ expanded into a full domain name and stored in the
+ queued message with an indication that it is already
+ complete. Otherwise, the abbreviation might be
+ expanded with a mail system search list, not the
+ user's, or a name could grow due to repeated
+ canonicalizations attempts interacting with wildcards.
+
+ The two most common abbreviation methods are:
+
+ (1) Interface-level aliases
+
+ Interface-level aliases are conceptually implemented as
+ a list of alias/domain name pairs. The list can be
+ per-user or per-host, and separate lists can be
+ associated with different functions, e.g. one list for
+ host name-to-address translation, and a different list
+ for mail domains. When the user enters a name, the
+ interface attempts to match the name to the alias
+ component of a list entry, and if a matching entry can
+
+
+
+Internet Engineering Task Force [Page 82]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ be found, the name is replaced by the domain name found
+ in the pair.
+
+ Note that interface-level aliases and CNAMEs are
+ completely separate mechanisms; interface-level aliases
+ are a local matter while CNAMEs are an Internet-wide
+ aliasing mechanism which is a required part of any DNS
+ implementation.
+
+ (2) Search Lists
+
+ A search list is conceptually implemented as an ordered
+ list of domain names. When the user enters a name, the
+ domain names in the search list are used as suffixes to
+ the user-supplied name, one by one, until a domain name
+ with the desired associated data is found, or the
+ search list is exhausted. Search lists often contain
+ the name of the local host's parent domain or other
+ ancestor domains. Search lists are often per-user or
+ per-process.
+
+ It SHOULD be possible for an administrator to disable a
+ DNS search-list facility. Administrative denial may be
+ warranted in some cases, to prevent abuse of the DNS.
+
+ There is danger that a search-list mechanism will
+ generate excessive queries to the root servers while
+ testing whether user input is a complete domain name,
+ lacking a final period to mark it as complete. A
+ search-list mechanism MUST have one of, and SHOULD have
+ both of, the following two provisions to prevent this:
+
+ (a) The local resolver/name server can implement
+ caching of negative responses (see Section
+ 6.1.3.3).
+
+ (b) The search list expander can require two or more
+ interior dots in a generated domain name before it
+ tries using the name in a query to non-local
+ domain servers, such as the root.
+
+ DISCUSSION:
+ The intent of this requirement is to avoid
+ excessive delay for the user as the search list is
+ tested, and more importantly to prevent excessive
+ traffic to the root and other high-level servers.
+ For example, if the user supplied a name "X" and
+ the search list contained the root as a component,
+
+
+
+Internet Engineering Task Force [Page 83]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ a query would have to consult a root server before
+ the next search list alternative could be tried.
+ The resulting load seen by the root servers and
+ gateways near the root would be multiplied by the
+ number of hosts in the Internet.
+
+ The negative caching alternative limits the effect
+ to the first time a name is used. The interior
+ dot rule is simpler to implement but can prevent
+ easy use of some top-level names.
+
+
+ 6.1.5 DOMAIN NAME SYSTEM REQUIREMENTS SUMMARY
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION | | | |T|T|e
+-----------------------------------------------|-----------|-|-|-|-|-|--
+GENERAL ISSUES | | | | | | |
+ | | | | | | |
+Implement DNS name-to-address conversion |6.1.1 |x| | | | |
+Implement DNS address-to-name conversion |6.1.1 |x| | | | |
+Support conversions using host table |6.1.1 | | |x| | |
+Properly handle RR with zero TTL |6.1.2.1 |x| | | | |
+Use QCLASS=* unnecessarily |6.1.2.2 | |x| | | |
+ Use QCLASS=IN for Internet class |6.1.2.2 |x| | | | |
+Unused fields zero |6.1.2.3 |x| | | | |
+Use compression in responses |6.1.2.4 |x| | | | |
+ | | | | | | |
+Include config info in responses |6.1.2.5 | | | | |x|
+Support all well-known, class-indep. types |6.1.3.5 |x| | | | |
+Easily expand type list |6.1.3.5 | |x| | | |
+Load all RR types (except MD and MF) |6.1.3.6 |x| | | | |
+Load MD or MF type |6.1.3.6 | | | | |x|
+Operate when root servers, etc. unavailable |6.1.3.7 |x| | | | |
+-----------------------------------------------|-----------|-|-|-|-|-|--
+RESOLVER ISSUES: | | | | | | |
+ | | | | | | |
+Resolver support multiple concurrent requests |6.1.3.1 | |x| | | |
+Full-service resolver: |6.1.3.1 | | |x| | |
+ Local caching |6.1.3.1 |x| | | | |
+
+
+
+Internet Engineering Task Force [Page 84]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ Information in local cache times out |6.1.3.1 |x| | | | |
+ Configurable with starting info |6.1.3.1 | |x| | | |
+Stub resolver: |6.1.3.1 | | |x| | |
+ Use redundant recursive name servers |6.1.3.1 |x| | | | |
+ Local caching |6.1.3.1 | | |x| | |
+ Information in local cache times out |6.1.3.1 |x| | | | |
+Support for remote multi-homed hosts: | | | | | | |
+ Sort multiple addresses by preference list |6.1.3.4 | |x| | | |
+ | | | | | | |
+-----------------------------------------------|-----------|-|-|-|-|-|--
+TRANSPORT PROTOCOLS: | | | | | | |
+ | | | | | | |
+Support UDP queries |6.1.3.2 |x| | | | |
+Support TCP queries |6.1.3.2 | |x| | | |
+ Send query using UDP first |6.1.3.2 |x| | | | |1
+ Try TCP if UDP answers are truncated |6.1.3.2 | |x| | | |
+Name server limit TCP query resources |6.1.3.2 | | |x| | |
+ Punish unnecessary TCP query |6.1.3.2 | | | |x| |
+Use truncated data as if it were not |6.1.3.2 | | | | |x|
+Private agreement to use only TCP |6.1.3.2 | | |x| | |
+Use TCP for zone transfers |6.1.3.2 |x| | | | |
+TCP usage not block UDP queries |6.1.3.2 |x| | | | |
+Support broadcast or multicast queries |6.1.3.2 | | |x| | |
+ RD bit set in query |6.1.3.2 | | | | |x|
+ RD bit ignored by server is b'cast/m'cast |6.1.3.2 |x| | | | |
+ Send only as occasional probe for addr's |6.1.3.2 | |x| | | |
+-----------------------------------------------|-----------|-|-|-|-|-|--
+RESOURCE USAGE: | | | | | | |
+ | | | | | | |
+Transmission controls, per [DNS:2] |6.1.3.3 |x| | | | |
+ Finite bounds per request |6.1.3.3 |x| | | | |
+Failure after retries => soft error |6.1.3.3 |x| | | | |
+Cache temporary failures |6.1.3.3 | |x| | | |
+Cache negative responses |6.1.3.3 | |x| | | |
+Retries use exponential backoff |6.1.3.3 | |x| | | |
+ Upper, lower bounds |6.1.3.3 | |x| | | |
+Client handle Source Quench |6.1.3.3 | |x| | | |
+Server ignore Source Quench |6.1.3.3 | | |x| | |
+-----------------------------------------------|-----------|-|-|-|-|-|--
+USER INTERFACE: | | | | | | |
+ | | | | | | |
+All programs have access to DNS interface |6.1.4.2 |x| | | | |
+Able to request all info for given name |6.1.4.2 |x| | | | |
+Returns complete info or error |6.1.4.2 |x| | | | |
+Special interfaces |6.1.4.2 | | |x| | |
+ Name<->Address translation |6.1.4.2 |x| | | | |
+ | | | | | | |
+Abbreviation Facilities: |6.1.4.3 | | |x| | |
+
+
+
+Internet Engineering Task Force [Page 85]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- DOMAINS October 1989
+
+
+ Convention for complete names |6.1.4.3 |x| | | | |
+ Conversion exactly once |6.1.4.3 |x| | | | |
+ Conversion in proper context |6.1.4.3 |x| | | | |
+ Search list: |6.1.4.3 | | |x| | |
+ Administrator can disable |6.1.4.3 | |x| | | |
+ Prevention of excessive root queries |6.1.4.3 |x| | | | |
+ Both methods |6.1.4.3 | |x| | | |
+-----------------------------------------------|-----------|-|-|-|-|-|--
+-----------------------------------------------|-----------|-|-|-|-|-|--
+
+1. Unless there is private agreement between particular resolver and
+ particular server.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 86]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- INITIALIZATION October 1989
+
+
+ 6.2 HOST INITIALIZATION
+
+ 6.2.1 INTRODUCTION
+
+ This section discusses the initialization of host software
+ across a connected network, or more generally across an
+ Internet path. This is necessary for a diskless host, and may
+ optionally be used for a host with disk drives. For a diskless
+ host, the initialization process is called "network booting"
+ and is controlled by a bootstrap program located in a boot ROM.
+
+ To initialize a diskless host across the network, there are two
+ distinct phases:
+
+ (1) Configure the IP layer.
+
+ Diskless machines often have no permanent storage in which
+ to store network configuration information, so that
+ sufficient configuration information must be obtained
+ dynamically to support the loading phase that follows.
+ This information must include at least the IP addresses of
+ the host and of the boot server. To support booting
+ across a gateway, the address mask and a list of default
+ gateways are also required.
+
+ (2) Load the host system code.
+
+ During the loading phase, an appropriate file transfer
+ protocol is used to copy the system code across the
+ network from the boot server.
+
+ A host with a disk may perform the first step, dynamic
+ configuration. This is important for microcomputers, whose
+ floppy disks allow network configuration information to be
+ mistakenly duplicated on more than one host. Also,
+ installation of new hosts is much simpler if they automatically
+ obtain their configuration information from a central server,
+ saving administrator time and decreasing the probability of
+ mistakes.
+
+ 6.2.2 REQUIREMENTS
+
+ 6.2.2.1 Dynamic Configuration
+
+ A number of protocol provisions have been made for dynamic
+ configuration.
+
+ o ICMP Information Request/Reply messages
+
+
+
+Internet Engineering Task Force [Page 87]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- INITIALIZATION October 1989
+
+
+ This obsolete message pair was designed to allow a host
+ to find the number of the network it is on.
+ Unfortunately, it was useful only if the host already
+ knew the host number part of its IP address,
+ information that hosts requiring dynamic configuration
+ seldom had.
+
+ o Reverse Address Resolution Protocol (RARP) [BOOT:4]
+
+ RARP is a link-layer protocol for a broadcast medium
+ that allows a host to find its IP address given its
+ link layer address. Unfortunately, RARP does not work
+ across IP gateways and therefore requires a RARP server
+ on every network. In addition, RARP does not provide
+ any other configuration information.
+
+ o ICMP Address Mask Request/Reply messages
+
+ These ICMP messages allow a host to learn the address
+ mask for a particular network interface.
+
+ o BOOTP Protocol [BOOT:2]
+
+ This protocol allows a host to determine the IP
+ addresses of the local host and the boot server, the
+ name of an appropriate boot file, and optionally the
+ address mask and list of default gateways. To locate a
+ BOOTP server, the host broadcasts a BOOTP request using
+ UDP. Ad hoc gateway extensions have been used to
+ transmit the BOOTP broadcast through gateways, and in
+ the future the IP Multicasting facility will provide a
+ standard mechanism for this purpose.
+
+
+ The suggested approach to dynamic configuration is to use
+ the BOOTP protocol with the extensions defined in "BOOTP
+ Vendor Information Extensions" RFC-1084 [BOOT:3]. RFC-1084
+ defines some important general (not vendor-specific)
+ extensions. In particular, these extensions allow the
+ address mask to be supplied in BOOTP; we RECOMMEND that the
+ address mask be supplied in this manner.
+
+ DISCUSSION:
+ Historically, subnetting was defined long after IP, and
+ so a separate mechanism (ICMP Address Mask messages)
+ was designed to supply the address mask to a host.
+ However, the IP address mask and the corresponding IP
+ address conceptually form a pair, and for operational
+
+
+
+Internet Engineering Task Force [Page 88]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- INITIALIZATION October 1989
+
+
+ simplicity they ought to be defined at the same time
+ and by the same mechanism, whether a configuration file
+ or a dynamic mechanism like BOOTP.
+
+ Note that BOOTP is not sufficiently general to specify
+ the configurations of all interfaces of a multihomed
+ host. A multihomed host must either use BOOTP
+ separately for each interface, or configure one
+ interface using BOOTP to perform the loading, and
+ perform the complete initialization from a file later.
+
+ Application layer configuration information is expected
+ to be obtained from files after loading of the system
+ code.
+
+ 6.2.2.2 Loading Phase
+
+ A suggested approach for the loading phase is to use TFTP
+ [BOOT:1] between the IP addresses established by BOOTP.
+
+ TFTP to a broadcast address SHOULD NOT be used, for reasons
+ explained in Section 4.2.3.4.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 89]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- MANAGEMENT October 1989
+
+
+ 6.3 REMOTE MANAGEMENT
+
+ 6.3.1 INTRODUCTION
+
+ The Internet community has recently put considerable effort
+ into the development of network management protocols. The
+ result has been a two-pronged approach [MGT:1, MGT:6]: the
+ Simple Network Management Protocol (SNMP) [MGT:4] and the
+ Common Management Information Protocol over TCP (CMOT) [MGT:5].
+
+ In order to be managed using SNMP or CMOT, a host will need to
+ implement an appropriate management agent. An Internet host
+ SHOULD include an agent for either SNMP or CMOT.
+
+ Both SNMP and CMOT operate on a Management Information Base
+ (MIB) that defines a collection of management values. By
+ reading and setting these values, a remote application may
+ query and change the state of the managed system.
+
+ A standard MIB [MGT:3] has been defined for use by both
+ management protocols, using data types defined by the Structure
+ of Management Information (SMI) defined in [MGT:2]. Additional
+ MIB variables can be introduced under the "enterprises" and
+ "experimental" subtrees of the MIB naming space [MGT:2].
+
+ Every protocol module in the host SHOULD implement the relevant
+ MIB variables. A host SHOULD implement the MIB variables as
+ defined in the most recent standard MIB, and MAY implement
+ other MIB variables when appropriate and useful.
+
+ 6.3.2 PROTOCOL WALK-THROUGH
+
+ The MIB is intended to cover both hosts and gateways, although
+ there may be detailed differences in MIB application to the two
+ cases. This section contains the appropriate interpretation of
+ the MIB for hosts. It is likely that later versions of the MIB
+ will include more entries for host management.
+
+ A managed host must implement the following groups of MIB
+ object definitions: System, Interfaces, Address Translation,
+ IP, ICMP, TCP, and UDP.
+
+ The following specific interpretations apply to hosts:
+
+ o ipInHdrErrors
+
+ Note that the error "time-to-live exceeded" can occur in a
+ host only when it is forwarding a source-routed datagram.
+
+
+
+Internet Engineering Task Force [Page 90]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- MANAGEMENT October 1989
+
+
+ o ipOutNoRoutes
+
+ This object counts datagrams discarded because no route
+ can be found. This may happen in a host if all the
+ default gateways in the host's configuration are down.
+
+ o ipFragOKs, ipFragFails, ipFragCreates
+
+ A host that does not implement intentional fragmentation
+ (see "Fragmentation" section of [INTRO:1]) MUST return the
+ value zero for these three objects.
+
+ o icmpOutRedirects
+
+ For a host, this object MUST always be zero, since hosts
+ do not send Redirects.
+
+ o icmpOutAddrMaskReps
+
+ For a host, this object MUST always be zero, unless the
+ host is an authoritative source of address mask
+ information.
+
+ o ipAddrTable
+
+ For a host, the "IP Address Table" object is effectively a
+ table of logical interfaces.
+
+ o ipRoutingTable
+
+ For a host, the "IP Routing Table" object is effectively a
+ combination of the host's Routing Cache and the static
+ route table described in "Routing Outbound Datagrams"
+ section of [INTRO:1].
+
+ Within each ipRouteEntry, ipRouteMetric1...4 normally will
+ have no meaning for a host and SHOULD always be -1, while
+ ipRouteType will normally have the value "remote".
+
+ If destinations on the connected network do not appear in
+ the Route Cache (see "Routing Outbound Datagrams section
+ of [INTRO:1]), there will be no entries with ipRouteType
+ of "direct".
+
+
+ DISCUSSION:
+ The current MIB does not include Type-of-Service in an
+ ipRouteEntry, but a future revision is expected to make
+
+
+
+Internet Engineering Task Force [Page 91]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- MANAGEMENT October 1989
+
+
+ this addition.
+
+ We also expect the MIB to be expanded to allow the remote
+ management of applications (e.g., the ability to partially
+ reconfigure mail systems). Network service applications
+ such as mail systems should therefore be written with the
+ "hooks" for remote management.
+
+ 6.3.3 MANAGEMENT REQUIREMENTS SUMMARY
+
+ | | | | |S| |
+ | | | | |H| |F
+ | | | | |O|M|o
+ | | |S| |U|U|o
+ | | |H| |L|S|t
+ | |M|O| |D|T|n
+ | |U|U|M| | |o
+ | |S|L|A|N|N|t
+ | |T|D|Y|O|O|t
+FEATURE |SECTION | | | |T|T|e
+-----------------------------------------------|-----------|-|-|-|-|-|--
+Support SNMP or CMOT agent |6.3.1 | |x| | | |
+Implement specified objects in standard MIB |6.3.1 | |x| | | |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 92]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- MANAGEMENT October 1989
+
+
+7. REFERENCES
+
+ This section lists the primary references with which every
+ implementer must be thoroughly familiar. It also lists some
+ secondary references that are suggested additional reading.
+
+ INTRODUCTORY REFERENCES:
+
+
+ [INTRO:1] "Requirements for Internet Hosts -- Communication Layers,"
+ IETF Host Requirements Working Group, R. Braden, Ed., RFC-1122,
+ October 1989.
+
+ [INTRO:2] "DDN Protocol Handbook," NIC-50004, NIC-50005, NIC-50006,
+ (three volumes), SRI International, December 1985.
+
+ [INTRO:3] "Official Internet Protocols," J. Reynolds and J. Postel,
+ RFC-1011, May 1987.
+
+ This document is republished periodically with new RFC numbers;
+ the latest version must be used.
+
+ [INTRO:4] "Protocol Document Order Information," O. Jacobsen and J.
+ Postel, RFC-980, March 1986.
+
+ [INTRO:5] "Assigned Numbers," J. Reynolds and J. Postel, RFC-1010,
+ May 1987.
+
+ This document is republished periodically with new RFC numbers;
+ the latest version must be used.
+
+
+ TELNET REFERENCES:
+
+
+ [TELNET:1] "Telnet Protocol Specification," J. Postel and J.
+ Reynolds, RFC-854, May 1983.
+
+ [TELNET:2] "Telnet Option Specification," J. Postel and J. Reynolds,
+ RFC-855, May 1983.
+
+ [TELNET:3] "Telnet Binary Transmission," J. Postel and J. Reynolds,
+ RFC-856, May 1983.
+
+ [TELNET:4] "Telnet Echo Option," J. Postel and J. Reynolds, RFC-857,
+ May 1983.
+
+ [TELNET:5] "Telnet Suppress Go Ahead Option," J. Postel and J.
+
+
+
+Internet Engineering Task Force [Page 93]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- MANAGEMENT October 1989
+
+
+ Reynolds, RFC-858, May 1983.
+
+ [TELNET:6] "Telnet Status Option," J. Postel and J. Reynolds, RFC-
+ 859, May 1983.
+
+ [TELNET:7] "Telnet Timing Mark Option," J. Postel and J. Reynolds,
+ RFC-860, May 1983.
+
+ [TELNET:8] "Telnet Extended Options List," J. Postel and J.
+ Reynolds, RFC-861, May 1983.
+
+ [TELNET:9] "Telnet End-Of-Record Option," J. Postel, RFC-855,
+ December 1983.
+
+ [TELNET:10] "Telnet Terminal-Type Option," J. VanBokkelen, RFC-1091,
+ February 1989.
+
+ This document supercedes RFC-930.
+
+ [TELNET:11] "Telnet Window Size Option," D. Waitzman, RFC-1073,
+ October 1988.
+
+ [TELNET:12] "Telnet Linemode Option," D. Borman, RFC-1116, August
+ 1989.
+
+ [TELNET:13] "Telnet Terminal Speed Option," C. Hedrick, RFC-1079,
+ December 1988.
+
+ [TELNET:14] "Telnet Remote Flow Control Option," C. Hedrick, RFC-
+ 1080, November 1988.
+
+
+ SECONDARY TELNET REFERENCES:
+
+
+ [TELNET:15] "Telnet Protocol," MIL-STD-1782, U.S. Department of
+ Defense, May 1984.
+
+ This document is intended to describe the same protocol as RFC-
+ 854. In case of conflict, RFC-854 takes precedence, and the
+ present document takes precedence over both.
+
+ [TELNET:16] "SUPDUP Protocol," M. Crispin, RFC-734, October 1977.
+
+ [TELNET:17] "Telnet SUPDUP Option," M. Crispin, RFC-736, October
+ 1977.
+
+ [TELNET:18] "Data Entry Terminal Option," J. Day, RFC-732, June 1977.
+
+
+
+Internet Engineering Task Force [Page 94]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- MANAGEMENT October 1989
+
+
+ [TELNET:19] "TELNET Data Entry Terminal option -- DODIIS
+ Implementation," A. Yasuda and T. Thompson, RFC-1043, February
+ 1988.
+
+
+ FTP REFERENCES:
+
+
+ [FTP:1] "File Transfer Protocol," J. Postel and J. Reynolds, RFC-
+ 959, October 1985.
+
+ [FTP:2] "Document File Format Standards," J. Postel, RFC-678,
+ December 1974.
+
+ [FTP:3] "File Transfer Protocol," MIL-STD-1780, U.S. Department of
+ Defense, May 1984.
+
+ This document is based on an earlier version of the FTP
+ specification (RFC-765) and is obsolete.
+
+
+ TFTP REFERENCES:
+
+
+ [TFTP:1] "The TFTP Protocol Revision 2," K. Sollins, RFC-783, June
+ 1981.
+
+
+ MAIL REFERENCES:
+
+
+ [SMTP:1] "Simple Mail Transfer Protocol," J. Postel, RFC-821, August
+ 1982.
+
+ [SMTP:2] "Standard For The Format of ARPA Internet Text Messages,"
+ D. Crocker, RFC-822, August 1982.
+
+ This document obsoleted an earlier specification, RFC-733.
+
+ [SMTP:3] "Mail Routing and the Domain System," C. Partridge, RFC-
+ 974, January 1986.
+
+ This RFC describes the use of MX records, a mandatory extension
+ to the mail delivery process.
+
+ [SMTP:4] "Duplicate Messages and SMTP," C. Partridge, RFC-1047,
+ February 1988.
+
+
+
+
+Internet Engineering Task Force [Page 95]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- MANAGEMENT October 1989
+
+
+ [SMTP:5a] "Mapping between X.400 and RFC 822," S. Kille, RFC-987,
+ June 1986.
+
+ [SMTP:5b] "Addendum to RFC-987," S. Kille, RFC-???, September 1987.
+
+ The two preceding RFC's define a proposed standard for
+ gatewaying mail between the Internet and the X.400 environments.
+
+ [SMTP:6] "Simple Mail Transfer Protocol," MIL-STD-1781, U.S.
+ Department of Defense, May 1984.
+
+ This specification is intended to describe the same protocol as
+ does RFC-821. However, MIL-STD-1781 is incomplete; in
+ particular, it does not include MX records [SMTP:3].
+
+ [SMTP:7] "A Content-Type Field for Internet Messages," M. Sirbu,
+ RFC-1049, March 1988.
+
+
+ DOMAIN NAME SYSTEM REFERENCES:
+
+
+ [DNS:1] "Domain Names - Concepts and Facilities," P. Mockapetris,
+ RFC-1034, November 1987.
+
+ This document and the following one obsolete RFC-882, RFC-883,
+ and RFC-973.
+
+ [DNS:2] "Domain Names - Implementation and Specification," RFC-1035,
+ P. Mockapetris, November 1987.
+
+
+ [DNS:3] "Mail Routing and the Domain System," C. Partridge, RFC-974,
+ January 1986.
+
+
+ [DNS:4] "DoD Internet Host Table Specification," K. Harrenstein,
+ RFC-952, M. Stahl, E. Feinler, October 1985.
+
+ SECONDARY DNS REFERENCES:
+
+
+ [DNS:5] "Hostname Server," K. Harrenstein, M. Stahl, E. Feinler,
+ RFC-953, October 1985.
+
+ [DNS:6] "Domain Administrators Guide," M. Stahl, RFC-1032, November
+ 1987.
+
+
+
+
+Internet Engineering Task Force [Page 96]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- MANAGEMENT October 1989
+
+
+ [DNS:7] "Domain Administrators Operations Guide," M. Lottor, RFC-
+ 1033, November 1987.
+
+ [DNS:8] "The Domain Name System Handbook," Vol. 4 of Internet
+ Protocol Handbook, NIC 50007, SRI Network Information Center,
+ August 1989.
+
+
+ SYSTEM INITIALIZATION REFERENCES:
+
+
+ [BOOT:1] "Bootstrap Loading Using TFTP," R. Finlayson, RFC-906, June
+ 1984.
+
+ [BOOT:2] "Bootstrap Protocol (BOOTP)," W. Croft and J. Gilmore, RFC-
+ 951, September 1985.
+
+ [BOOT:3] "BOOTP Vendor Information Extensions," J. Reynolds, RFC-
+ 1084, December 1988.
+
+ Note: this RFC revised and obsoleted RFC-1048.
+
+ [BOOT:4] "A Reverse Address Resolution Protocol," R. Finlayson, T.
+ Mann, J. Mogul, and M. Theimer, RFC-903, June 1984.
+
+
+ MANAGEMENT REFERENCES:
+
+
+ [MGT:1] "IAB Recommendations for the Development of Internet Network
+ Management Standards," V. Cerf, RFC-1052, April 1988.
+
+ [MGT:2] "Structure and Identification of Management Information for
+ TCP/IP-based internets," M. Rose and K. McCloghrie, RFC-1065,
+ August 1988.
+
+ [MGT:3] "Management Information Base for Network Management of
+ TCP/IP-based internets," M. Rose and K. McCloghrie, RFC-1066,
+ August 1988.
+
+ [MGT:4] "A Simple Network Management Protocol," J. Case, M. Fedor,
+ M. Schoffstall, and C. Davin, RFC-1098, April 1989.
+
+ [MGT:5] "The Common Management Information Services and Protocol
+ over TCP/IP," U. Warrier and L. Besaw, RFC-1095, April 1989.
+
+ [MGT:6] "Report of the Second Ad Hoc Network Management Review
+ Group," V. Cerf, RFC-1109, August 1989.
+
+
+
+Internet Engineering Task Force [Page 97]
+
+
+
+
+RFC1123 SUPPORT SERVICES -- MANAGEMENT October 1989
+
+
+Security Considerations
+
+ There are many security issues in the application and support
+ programs of host software, but a full discussion is beyond the scope
+ of this RFC. Security-related issues are mentioned in sections
+ concerning TFTP (Sections 4.2.1, 4.2.3.4, 4.2.3.5), the SMTP VRFY and
+ EXPN commands (Section 5.2.3), the SMTP HELO command (5.2.5), and the
+ SMTP DATA command (Section 5.2.8).
+
+Author's Address
+
+ Robert Braden
+ USC/Information Sciences Institute
+ 4676 Admiralty Way
+ Marina del Rey, CA 90292-6695
+
+ Phone: (213) 822 1511
+
+ EMail: Braden@ISI.EDU
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Internet Engineering Task Force [Page 98]
+
diff --git a/doc/rfc/rfc1183.txt b/doc/rfc/rfc1183.txt
new file mode 100644
index 0000000..6f08044
--- /dev/null
+++ b/doc/rfc/rfc1183.txt
@@ -0,0 +1,619 @@
+
+
+
+
+
+
+Network Working Group C. Everhart
+Request for Comments: 1183 Transarc
+Updates: RFCs 1034, 1035 L. Mamakos
+ University of Maryland
+ R. Ullmann
+ Prime Computer
+ P. Mockapetris, Editor
+ ISI
+ October 1990
+
+
+ New DNS RR Definitions
+
+Status of this Memo
+
+ This memo defines five new DNS types for experimental purposes. This
+ RFC describes an Experimental Protocol for the Internet community,
+ and requests discussion and suggestions for improvements.
+ Distribution of this memo is unlimited.
+
+Table of Contents
+
+ Introduction.................................................... 1
+ 1. AFS Data Base location....................................... 2
+ 2. Responsible Person........................................... 3
+ 2.1. Identification of the guilty party......................... 3
+ 2.2. The Responsible Person RR.................................. 4
+ 3. X.25 and ISDN addresses, Route Binding....................... 6
+ 3.1. The X25 RR................................................. 6
+ 3.2. The ISDN RR................................................ 7
+ 3.3. The Route Through RR....................................... 8
+ REFERENCES and BIBLIOGRAPHY..................................... 9
+ Security Considerations......................................... 10
+ Authors' Addresses.............................................. 11
+
+Introduction
+
+ This RFC defines the format of new Resource Records (RRs) for the
+ Domain Name System (DNS), and reserves corresponding DNS type
+ mnemonics and numerical codes. The definitions are in three
+ independent sections: (1) location of AFS database servers, (2)
+ location of responsible persons, and (3) representation of X.25 and
+ ISDN addresses and route binding. All are experimental.
+
+ This RFC assumes that the reader is familiar with the DNS [3,4]. The
+ data shown is for pedagogical use and does not necessarily reflect
+ the real Internet.
+
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 1]
+
+RFC 1183 New DNS RR Definitions October 1990
+
+
+1. AFS Data Base location
+
+ This section defines an extension of the DNS to locate servers both
+ for AFS (AFS is a registered trademark of Transarc Corporation) and
+ for the Open Software Foundation's (OSF) Distributed Computing
+ Environment (DCE) authenticated naming system using HP/Apollo's NCA,
+ both to be components of the OSF DCE. The discussion assumes that
+ the reader is familiar with AFS [5] and NCA [6].
+
+ The AFS (originally the Andrew File System) system uses the DNS to
+ map from a domain name to the name of an AFS cell database server.
+ The DCE Naming service uses the DNS for a similar function: mapping
+ from the domain name of a cell to authenticated name servers for that
+ cell. The method uses a new RR type with mnemonic AFSDB and type
+ code of 18 (decimal).
+
+ AFSDB has the following format:
+
+ <owner> <ttl> <class> AFSDB <subtype> <hostname>
+
+ Both RDATA fields are required in all AFSDB RRs. The <subtype> field
+ is a 16 bit integer. The <hostname> field is a domain name of a host
+ that has a server for the cell named by the owner name of the RR.
+
+ The format of the AFSDB RR is class insensitive. AFSDB records cause
+ type A additional section processing for <hostname>. This, in fact,
+ is the rationale for using a new type code, rather than trying to
+ build the same functionality with TXT RRs.
+
+ Note that the format of AFSDB in a master file is identical to MX.
+ For purposes of the DNS itself, the subtype is merely an integer.
+ The present subtype semantics are discussed below, but changes are
+ possible and will be announced in subsequent RFCs.
+
+ In the case of subtype 1, the host has an AFS version 3.0 Volume
+ Location Server for the named AFS cell. In the case of subtype 2,
+ the host has an authenticated name server holding the cell-root
+ directory node for the named DCE/NCA cell.
+
+ The use of subtypes is motivated by two considerations. First, the
+ space of DNS RR types is limited. Second, the services provided are
+ sufficiently distinct that it would continue to be confusing for a
+ client to attempt to connect to a cell's servers using the protocol
+ for one service, if the cell offered only the other service.
+
+ As an example of the use of this RR, suppose that the Toaster
+ Corporation has deployed AFS 3.0 but not (yet) the OSF's DCE. Their
+ cell, named toaster.com, has three "AFS 3.0 cell database server"
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 2]
+
+RFC 1183 New DNS RR Definitions October 1990
+
+
+ machines: bigbird.toaster.com, ernie.toaster.com, and
+ henson.toaster.com. These three machines would be listed in three
+ AFSDB RRs. These might appear in a master file as:
+
+ toaster.com. AFSDB 1 bigbird.toaster.com.
+ toaster.com. AFSDB 1 ernie.toaster.com.
+ toaster.com. AFSDB 1 henson.toaster.com.
+
+ As another example use of this RR, suppose that Femto College (domain
+ name femto.edu) has deployed DCE, and that their DCE cell root
+ directory is served by processes running on green.femto.edu and
+ turquoise.femto.edu. Furthermore, their DCE file servers also run
+ AFS 3.0-compatible volume location servers, on the hosts
+ turquoise.femto.edu and orange.femto.edu. These machines would be
+ listed in four AFSDB RRs, which might appear in a master file as:
+
+ femto.edu. AFSDB 2 green.femto.edu.
+ femto.edu. AFSDB 2 turquoise.femto.edu.
+ femto.edu. AFSDB 1 turquoise.femto.edu.
+ femto.edu. AFSDB 1 orange.femto.edu.
+
+2. Responsible Person
+
+ The purpose of this section is to provide a standard method for
+ associating responsible person identification to any name in the DNS.
+
+ The domain name system functions as a distributed database which
+ contains many different form of information. For a particular name
+ or host, you can discover it's Internet address, mail forwarding
+ information, hardware type and operating system among others.
+
+ A key aspect of the DNS is that the tree-structured namespace can be
+ divided into pieces, called zones, for purposes of distributing
+ control and responsibility. The responsible person for zone database
+ purposes is named in the SOA RR for that zone. This section
+ describes an extension which allows different responsible persons to
+ be specified for different names in a zone.
+
+2.1. Identification of the guilty party
+
+ Often it is desirable to be able to identify the responsible entity
+ for a particular host. When that host is down or malfunctioning, it
+ is difficult to contact those parties which might resolve or repair
+ the host. Mail sent to POSTMASTER may not reach the person in a
+ timely fashion. If the host is one of a multitude of workstations,
+ there may be no responsible person which can be contacted on that
+ host.
+
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 3]
+
+RFC 1183 New DNS RR Definitions October 1990
+
+
+ The POSTMASTER mailbox on that host continues to be a good contact
+ point for mail problems, and the zone contact in the SOA record for
+ database problem, but the RP record allows us to associate a mailbox
+ to entities that don't receive mail or are not directly connected
+ (namespace-wise) to the problem (e.g., GATEWAY.ISI.EDU might want to
+ point at HOTLINE@BBN.COM, and GATEWAY doesn't get mail, nor does the
+ ISI zone administrator have a clue about fixing gateways).
+
+2.2. The Responsible Person RR
+
+ The method uses a new RR type with mnemonic RP and type code of 17
+ (decimal).
+
+ RP has the following format:
+
+ <owner> <ttl> <class> RP <mbox-dname> <txt-dname>
+
+ Both RDATA fields are required in all RP RRs.
+
+ The first field, <mbox-dname>, is a domain name that specifies the
+ mailbox for the responsible person. Its format in master files uses
+ the DNS convention for mailbox encoding, identical to that used for
+ the RNAME mailbox field in the SOA RR. The root domain name (just
+ ".") may be specified for <mbox-dname> to indicate that no mailbox is
+ available.
+
+ The second field, <txt-dname>, is a domain name for which TXT RR's
+ exist. A subsequent query can be performed to retrieve the
+ associated TXT resource records at <txt-dname>. This provides a
+ level of indirection so that the entity can be referred to from
+ multiple places in the DNS. The root domain name (just ".") may be
+ specified for <txt-dname> to indicate that the TXT_DNAME is absent,
+ and no associated TXT RR exists.
+
+ The format of the RP RR is class insensitive. RP records cause no
+ additional section processing. (TXT additional section processing
+ for <txt-dname> is allowed as an option, but only if it is disabled
+ for the root, i.e., ".").
+
+ The Responsible Person RR can be associated with any node in the
+ Domain Name System hierarchy, not just at the leaves of the tree.
+
+ The TXT RR associated with the TXT_DNAME contain free format text
+ suitable for humans. Refer to [4] for more details on the TXT RR.
+
+ Multiple RP records at a single name may be present in the database.
+ They should have identical TTLs.
+
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 4]
+
+RFC 1183 New DNS RR Definitions October 1990
+
+
+ EXAMPLES
+
+ Some examples of how the RP record might be used.
+
+ sayshell.umd.edu. A 128.8.1.14
+ MX 10 sayshell.umd.edu.
+ HINFO NeXT UNIX
+ WKS 128.8.1.14 tcp ftp telnet smtp
+ RP louie.trantor.umd.edu. LAM1.people.umd.edu.
+
+ LAM1.people.umd.edu. TXT (
+ "Louis A. Mamakos, (301) 454-2946, don't call me at home!" )
+
+ In this example, the responsible person's mailbox for the host
+ SAYSHELL.UMD.EDU is louie@trantor.umd.edu. The TXT RR at
+ LAM1.people.umd.edu provides additional information and advice.
+
+ TERP.UMD.EDU. A 128.8.10.90
+ MX 10 128.8.10.90
+ HINFO MICROVAX-II UNIX
+ WKS 128.8.10.90 udp domain
+ WKS 128.8.10.90 tcp ftp telnet smtp domain
+ RP louie.trantor.umd.edu. LAM1.people.umd.edu.
+ RP root.terp.umd.edu. ops.CS.UMD.EDU.
+
+ TRANTOR.UMD.EDU. A 128.8.10.14
+ MX 10 trantor.umd.edu.
+ HINFO MICROVAX-II UNIX
+ WKS 128.8.10.14 udp domain
+ WKS 128.8.10.14 tcp ftp telnet smtp domain
+ RP louie.trantor.umd.edu. LAM1.people.umd.edu.
+ RP petry.netwolf.umd.edu. petry.people.UMD.EDU.
+ RP root.trantor.umd.edu. ops.CS.UMD.EDU.
+ RP gregh.sunset.umd.edu. .
+
+ LAM1.people.umd.edu. TXT "Louis A. Mamakos (301) 454-2946"
+ petry.people.umd.edu. TXT "Michael G. Petry (301) 454-2946"
+ ops.CS.UMD.EDU. TXT "CS Operations Staff (301) 454-2943"
+
+ This set of resource records has two hosts, TRANTOR.UMD.EDU and
+ TERP.UMD.EDU, as well as a number of TXT RRs. Note that TERP.UMD.EDU
+ and TRANTOR.UMD.EDU both reference the same pair of TXT resource
+ records, although the mail box names (root.terp.umd.edu and
+ root.trantor.umd.edu) differ.
+
+ Here, we obviously care much more if the machine flakes out, as we've
+ specified four persons which might want to be notified of problems or
+ other events involving TRANTOR.UMD.EDU. In this example, the last RP
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 5]
+
+RFC 1183 New DNS RR Definitions October 1990
+
+
+ RR for TRANTOR.UMD.EDU specifies a mailbox (gregh.sunset.umd.edu),
+ but no associated TXT RR.
+
+3. X.25 and ISDN addresses, Route Binding
+
+ This section describes an experimental representation of X.25 and
+ ISDN addresses in the DNS, as well as a route binding method,
+ analogous to the MX for mail routing, for very large scale networks.
+
+ There are several possible uses, all experimental at this time.
+ First, the RRs provide simple documentation of the correct addresses
+ to use in static configurations of IP/X.25 [11] and SMTP/X.25 [12].
+
+ The RRs could also be used automatically by an internet network-layer
+ router, typically IP. The procedure would be to map IP address to
+ domain name, then name to canonical name if needed, then following RT
+ records, and finally attempting an IP/X.25 call to the address found.
+ Alternately, configured domain names could be resolved to identify IP
+ to X.25/ISDN bindings for a static but periodically refreshed routing
+ table.
+
+ This provides a function similar to ARP for wide area non-broadcast
+ networks that will scale well to a network with hundreds of millions
+ of hosts.
+
+ Also, a standard address binding reference will facilitate other
+ experiments in the use of X.25 and ISDN, especially in serious
+ inter-operability testing. The majority of work in such a test is
+ establishing the n-squared entries in static tables.
+
+ Finally, the RRs are intended for use in a proposal [13] by one of
+ the authors for a possible next-generation internet.
+
+3.1. The X25 RR
+
+ The X25 RR is defined with mnemonic X25 and type code 19 (decimal).
+
+ X25 has the following format:
+
+ <owner> <ttl> <class> X25 <PSDN-address>
+
+ <PSDN-address> is required in all X25 RRs.
+
+ <PSDN-address> identifies the PSDN (Public Switched Data Network)
+ address in the X.121 [10] numbering plan associated with <owner>.
+ Its format in master files is a <character-string> syntactically
+ identical to that used in TXT and HINFO.
+
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 6]
+
+RFC 1183 New DNS RR Definitions October 1990
+
+
+ The format of X25 is class insensitive. X25 RRs cause no additional
+ section processing.
+
+ The <PSDN-address> is a string of decimal digits, beginning with the
+ 4 digit DNIC (Data Network Identification Code), as specified in
+ X.121. National prefixes (such as a 0) MUST NOT be used.
+
+ For example:
+
+ Relay.Prime.COM. X25 311061700956
+
+3.2. The ISDN RR
+
+ The ISDN RR is defined with mnemonic ISDN and type code 20 (decimal).
+
+ An ISDN (Integrated Service Digital Network) number is simply a
+ telephone number. The intent of the members of the CCITT is to
+ upgrade all telephone and data network service to a common service.
+
+ The numbering plan (E.163/E.164) is the same as the familiar
+ international plan for POTS (an un-official acronym, meaning Plain
+ Old Telephone Service). In E.166, CCITT says "An E.163/E.164
+ telephony subscriber may become an ISDN subscriber without a number
+ change."
+
+ ISDN has the following format:
+
+ <owner> <ttl> <class> ISDN <ISDN-address> <sa>
+
+ The <ISDN-address> field is required; <sa> is optional.
+
+ <ISDN-address> identifies the ISDN number of <owner> and DDI (Direct
+ Dial In) if any, as defined by E.164 [8] and E.163 [7], the ISDN and
+ PSTN (Public Switched Telephone Network) numbering plan. E.163
+ defines the country codes, and E.164 the form of the addresses. Its
+ format in master files is a <character-string> syntactically
+ identical to that used in TXT and HINFO.
+
+ <sa> specifies the subaddress (SA). The format of <sa> in master
+ files is a <character-string> syntactically identical to that used in
+ TXT and HINFO.
+
+ The format of ISDN is class insensitive. ISDN RRs cause no
+ additional section processing.
+
+ The <ISDN-address> is a string of characters, normally decimal
+ digits, beginning with the E.163 country code and ending with the DDI
+ if any. Note that ISDN, in Q.931, permits any IA5 character in the
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 7]
+
+RFC 1183 New DNS RR Definitions October 1990
+
+
+ general case.
+
+ The <sa> is a string of hexadecimal digits. For digits 0-9, the
+ concrete encoding in the Q.931 call setup information element is
+ identical to BCD.
+
+ For example:
+
+ Relay.Prime.COM. IN ISDN 150862028003217
+ sh.Prime.COM. IN ISDN 150862028003217 004
+
+ (Note: "1" is the country code for the North American Integrated
+ Numbering Area, i.e., the system of "area codes" familiar to people
+ in those countries.)
+
+ The RR data is the ASCII representation of the digits. It is encoded
+ as one or two <character-string>s, i.e., count followed by
+ characters.
+
+ CCITT recommendation E.166 [9] defines prefix escape codes for the
+ representation of ISDN (E.163/E.164) addresses in X.121, and PSDN
+ (X.121) addresses in E.164. It specifies that the exact codes are a
+ "national matter", i.e., different on different networks. A host
+ connected to the ISDN may be able to use both the X25 and ISDN
+ addresses, with the local prefix added.
+
+3.3. The Route Through RR
+
+ The Route Through RR is defined with mnemonic RT and type code 21
+ (decimal).
+
+ The RT resource record provides a route-through binding for hosts
+ that do not have their own direct wide area network addresses. It is
+ used in much the same way as the MX RR.
+
+ RT has the following format:
+
+ <owner> <ttl> <class> RT <preference> <intermediate-host>
+
+ Both RDATA fields are required in all RT RRs.
+
+ The first field, <preference>, is a 16 bit integer, representing the
+ preference of the route. Smaller numbers indicate more preferred
+ routes.
+
+ <intermediate-host> is the domain name of a host which will serve as
+ an intermediate in reaching the host specified by <owner>. The DNS
+ RRs associated with <intermediate-host> are expected to include at
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 8]
+
+RFC 1183 New DNS RR Definitions October 1990
+
+
+ least one A, X25, or ISDN record.
+
+ The format of the RT RR is class insensitive. RT records cause type
+ X25, ISDN, and A additional section processing for <intermediate-
+ host>.
+
+ For example,
+
+ sh.prime.com. IN RT 2 Relay.Prime.COM.
+ IN RT 10 NET.Prime.COM.
+ *.prime.com. IN RT 90 Relay.Prime.COM.
+
+ When a host is looking up DNS records to attempt to route a datagram,
+ it first looks for RT records for the destination host, which point
+ to hosts with address records (A, X25, ISDN) compatible with the wide
+ area networks available to the host. If it is itself in the set of
+ RT records, it discards any RTs with preferences higher or equal to
+ its own. If there are no (remaining) RTs, it can then use address
+ records of the destination itself.
+
+ Wild-card RTs are used exactly as are wild-card MXs. RT's do not
+ "chain"; that is, it is not valid to use the RT RRs found for a host
+ referred to by an RT.
+
+ The concrete encoding is identical to the MX RR.
+
+REFERENCES and BIBLIOGRAPHY
+
+ [1] Stahl, M., "Domain Administrators Guide", RFC 1032, Network
+ Information Center, SRI International, November 1987.
+
+ [2] Lottor, M., "Domain Administrators Operations Guide", RFC 1033,
+ Network Information Center, SRI International, November, 1987.
+
+ [3] Mockapetris, P., "Domain Names - Concepts and Facilities", RFC
+ 1034, USC/Information Sciences Institute, November 1987.
+
+ [4] Mockapetris, P., "Domain Names - Implementation and
+ Specification", RFC 1035, USC/Information Sciences Institute,
+ November 1987.
+
+ [5] Spector A., and M. Kazar, "Uniting File Systems", UNIX Review,
+ 7(3), pp. 61-69, March 1989.
+
+ [6] Zahn, et al., "Network Computing Architecture", Prentice-Hall,
+ 1989.
+
+ [7] International Telegraph and Telephone Consultative Committee,
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 9]
+
+RFC 1183 New DNS RR Definitions October 1990
+
+
+ "Numbering Plan for the International Telephone Service", CCITT
+ Recommendations E.163., IXth Plenary Assembly, Melbourne, 1988,
+ Fascicle II.2 ("Blue Book").
+
+ [8] International Telegraph and Telephone Consultative Committee,
+ "Numbering Plan for the ISDN Era", CCITT Recommendations E.164.,
+ IXth Plenary Assembly, Melbourne, 1988, Fascicle II.2 ("Blue
+ Book").
+
+ [9] International Telegraph and Telephone Consultative Committee.
+ "Numbering Plan Interworking in the ISDN Era", CCITT
+ Recommendations E.166., IXth Plenary Assembly, Melbourne, 1988,
+ Fascicle II.2 ("Blue Book").
+
+ [10] International Telegraph and Telephone Consultative Committee,
+ "International Numbering Plan for the Public Data Networks",
+ CCITT Recommendations X.121., IXth Plenary Assembly, Melbourne,
+ 1988, Fascicle VIII.3 ("Blue Book"); provisional, Geneva, 1978;
+ amended, Geneva, 1980, Malaga-Torremolinos, 1984 and Melborne,
+ 1988.
+
+ [11] Korb, J., "Standard for the Transmission of IP datagrams Over
+ Public Data Networks", RFC 877, Purdue University, September
+ 1983.
+
+ [12] Ullmann, R., "SMTP on X.25", RFC 1090, Prime Computer, February
+ 1989.
+
+ [13] Ullmann, R., "TP/IX: The Next Internet", Prime Computer
+ (unpublished), July 1990.
+
+ [14] Mockapetris, P., "DNS Encoding of Network Names and Other Types",
+ RFC 1101, USC/Information Sciences Institute, April 1989.
+
+Security Considerations
+
+ Security issues are not addressed in this memo.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 10]
+
+RFC 1183 New DNS RR Definitions October 1990
+
+
+Authors' Addresses
+
+ Craig F. Everhart
+ Transarc Corporation
+ The Gulf Tower
+ 707 Grant Street
+ Pittsburgh, PA 15219
+
+ Phone: +1 412 338 4467
+
+ EMail: Craig_Everhart@transarc.com
+
+
+ Louis A. Mamakos
+ Network Infrastructure Group
+ Computer Science Center
+ University of Maryland
+ College Park, MD 20742-2411
+
+ Phone: +1-301-405-7836
+
+ Email: louie@Sayshell.UMD.EDU
+
+
+ Robert Ullmann 10-30
+ Prime Computer, Inc.
+ 500 Old Connecticut Path
+ Framingham, MA 01701
+
+ Phone: +1 508 620 2800 ext 1736
+
+ Email: Ariel@Relay.Prime.COM
+
+
+ Paul Mockapetris
+ USC Information Sciences Institute
+ 4676 Admiralty Way
+ Marina del Rey, CA 90292
+
+ Phone: 213-822-1511
+
+ EMail: pvm@isi.edu
+
+
+
+
+
+
+
+
+
+Everhart, Mamakos, Ullmann & Mockapetris [Page 11]
+ \ No newline at end of file
diff --git a/doc/rfc/rfc1348.txt b/doc/rfc/rfc1348.txt
new file mode 100644
index 0000000..d9e5dea
--- /dev/null
+++ b/doc/rfc/rfc1348.txt
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+Network Working Group B. Manning
+Request for Comments: 1348 Rice University
+Updates: RFCs 1034, 1035 July 1992
+
+
+ DNS NSAP RRs
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. Discussion and suggestions for improvement are requested.
+ Please refer to the current edition of the "IAB Official Protocol
+ Standards" for the standardization state and status of this protocol.
+ Distribution of this memo is unlimited.
+
+Table of Contents
+
+ Introduction ..................................................... 1
+ Background ....................................................... 1
+ NSAP RR .......................................................... 2
+ NSAP-PTR RR ...................................................... 2
+ REFERENCES and BIBLIOGRAPHY ...................................... 3
+ Security Considerations .......................................... 4
+ Author's Address ................................................. 4
+
+Introduction
+
+ This RFC defines the format of two new Resource Records (RRs) for the
+ Domain Name System (DNS), and reserves corresponding DNS type
+ mnemonic and numerical codes. This format may be used with the any
+ proposal that has variable length addresses, but is targeted for CLNP
+ use.
+
+ This memo assumes that the reader is familiar with the DNS [3,4].
+
+Background
+
+ This section describes an experimental representation of NSAP
+ addresses in the DNS. There are several reasons to take this approch.
+ First, it provides simple documentation of the correct addresses to
+ use in static configurations of CLNP compliant hosts and routers.
+
+ NSAP support requires that a new DNS resource record entry type
+ ("NSAP") be defined, to store longer Internet (i.e., NSAP) addresses.
+ This resource record allows mapping from DNS names to NSAP addresses,
+ and will contain entries for systems which are able to run Internet
+ applications, over TCP or UDP, over CLNP.
+
+
+
+
+Manning [Page 1]
+
+RFC 1348 DNS NSAP RRs July 1992
+
+
+ The backward translation (from NSAP address to DNS name) is
+ facilitated by definition of an associated resource record. This
+ resource record is known as "NSAP-PTR", and is used in a manner
+ analogous to the existing "in-addr.arpa".
+
+ These RRs are intended for use in a proposal [6] by one of the
+ members of the NOOP WG to address the next-generation internet.
+
+The NSAP RR
+
+ The NSAP RR is defined with mnemonic NSAP and type code 22 (decimal).
+
+ An NSAP (Network Service Access Protocol) number is a unique string
+ to OSI transport service.
+
+ The numbering plan follows RFC 1237 and associated OSI definitions
+ for NSAP format.
+
+ NSAP has the following format:
+
+ <owner> <ttl> <class> NSAP <length> <NSAP-address>
+
+ All fields are required.
+
+ <length> identifies the number of octets in the <NSAP-address> as
+ defined by the various national and international authorities.
+
+ <NSAP-address> enumerates the actual octet values assigned by the
+ assigning authority. Its format in master files is a <character-
+ string> syntactically identical to that used in TXT and HINFO.
+
+ The format of NSAP is class insensitive. NSAP RR causes no
+ additional section processing.
+
+ For example:
+
+foo.bar.com. IN NSAP 21 47000580ffff000000321099991111222233334444
+host.school.de IN NSAP 17 39276f3100111100002222333344449876
+
+ The RR data is the ASCII representation of the digits. It is encoded
+ as two <character-strings>, i.e., count followed by characters.
+
+The NSAP-PTR RR
+
+ The NSAP-PTR RR is defined with mnemonic NSAP-PTR and a type code 23
+ (decimal).
+
+ Its function is analogous to the PTR record used for IP addresses
+
+
+
+Manning [Page 2]
+
+RFC 1348 DNS NSAP RRs July 1992
+
+
+ [4,7].
+
+ NSAP-PTR has the following format:
+
+ <NSAP-suffix> <ttl> <class> NSAP-PTR <owner>
+
+ All fields are required.
+
+ <NSAP-suffix> enumerates the actual octet values assigned by the
+ assigning authority for the LOCAL network. Its format in master
+ files is a <character-string> syntactically identical to that used in
+ TXT and HINFO.
+
+ The format of NSAP-PTR is class insensitive. NSAP-PTR RR causes no
+ additional section processing.
+
+ For example:
+
+ In net ff08000574.nsap-in-addr.arpa:
+
+ 444433332222111199990123000000ff NSAP-PTR foo.bar.com.
+
+ Or in net 11110031f67293.nsap-in-addr.arpa:
+
+ 67894444333322220000 NSAP-PTR host.school.de.
+
+ The RR data is the ASCII representation of the digits. It is encoded
+ as a <character-string>.
+
+REFERENCES and BIBLIOGRAPHY
+
+ [1] Stahl, M., "Domain Administrators Guide", RFC 1032, Network
+ Information Center, SRI International, November 1987.
+
+ [2] Lottor, M., "Domain Administrators Operations Guide", RFC 1033,
+ Network Information Center, SRI International, November, 1987.
+
+ [3] Mockapetris, P., "Domain Names - Concepts and Facilities", RFC
+ 1034, USC/Information Sciences Institute, November 1987.
+
+ [4] Mockapetris, P., "Domain Names - Implementation and
+ Specification", RFC 1035, USC/Information Sciences Institute,
+ November 1987.
+
+ [5] Colella, R., Gardner, E., and R. Callon, "Guidelines for OSI
+ NSAP Allocation in the Internet", RFC 1237, NIST, Mitre, DEC,
+ July 1991.
+
+
+
+
+Manning [Page 3]
+
+RFC 1348 DNS NSAP RRs July 1992
+
+
+ [6] Callon, R., "TCP and UDP with Bigger Addresses (TUBA),
+ A Simple Proposal for Internet Addressing and Routing",
+ Digital Equipment Corporation, RFC 1347, June 1992.
+
+ [7] Mockapetris, P., "DNS Encoding of Network Names and Other Types",
+ RFC 1101, USC/Information Sciences Institute, April 1989.
+
+ [8] ISO/IEC. Information Processing Systems -- Data Communications
+ -- Network Service Definition Addendum 2: Network Layer Address-
+ ing. International Standard 8348/Addendum 2, ISO/IEC JTC 1,
+ Switzerland, 1988.
+
+ [9] Bryant, P., "NSAPs", PB660, IPTAG/92/23, SCIENCE AND ENGINEERING
+ RESEARCH COUNCIL, RUTHERFORD APPLETON LABORATORY May 1992.
+
+Security Considerations
+
+ Security issues are not addressed in this memo.
+
+Author's Address
+
+ Bill Manning
+ Rice University - ONCS
+ PO Box 1892
+ 6100 South Main
+ Houston, Texas 77251-1892
+
+ Phone: +1.713.285.5415
+ EMail: bmanning@rice.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Manning [Page 4]
+ \ No newline at end of file
diff --git a/doc/rfc/rfc1535.txt b/doc/rfc/rfc1535.txt
new file mode 100644
index 0000000..03bddee
--- /dev/null
+++ b/doc/rfc/rfc1535.txt
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+Network Working Group E. Gavron
+Request for Comments: 1535 ACES Research Inc.
+Category: Informational October 1993
+
+
+ A Security Problem and Proposed Correction
+ With Widely Deployed DNS Software
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard. Distribution of this memo is
+ unlimited.
+
+Abstract
+
+ This document discusses a flaw in some of the currently distributed
+ name resolver clients. The flaw exposes a security weakness related
+ to the search heuristic invoked by these same resolvers when users
+ provide a partial domain name, and which is easy to exploit (although
+ not by the masses). This document points out the flaw, a case in
+ point, and a solution.
+
+Background
+
+ Current Domain Name Server clients are designed to ease the burden of
+ remembering IP dotted quad addresses. As such they translate human-
+ readable names into addresses and other resource records. Part of
+ the translation process includes understanding and dealing with
+ hostnames that are not fully qualified domain names (FQDNs).
+
+ An absolute "rooted" FQDN is of the format {name}{.} A non "rooted"
+ domain name is of the format {name}
+
+ A domain name may have many parts and typically these include the
+ host, domain, and type. Example: foobar.company.com or
+ fooschool.university.edu.
+
+Flaw
+
+ The problem with most widely distributed resolvers based on the BSD
+ BIND resolver is that they attempt to resolve a partial name by
+ processing a search list of partial domains to be added to portions
+ of the specified host name until a DNS record is found. This
+ "feature" is disabled by default in the official BIND 4.9.2 release.
+
+ Example: A TELNET attempt by User@Machine.Tech.ACES.COM
+ to UnivHost.University.EDU
+
+
+
+Gavron [Page 1]
+
+RFC 1535 DNS Software Enhancements October 1993
+
+
+ The resolver client will realize that since "UnivHost.University.EDU"
+ does not end with a ".", it is not an absolute "rooted" FQDN. It
+ will then try the following combinations until a resource record is
+ found:
+
+ UnivHost.University.EDU.Tech.ACES.COM.
+ UnivHost.University.EDU.ACES.COM.
+ UnivHost.University.EDU.COM.
+ UnivHost.University.EDU.
+
+Security Issue
+
+ After registering the EDU.COM domain, it was discovered that an
+ unliberal application of one wildcard CNAME record would cause *all*
+ connects from any .COM site to any .EDU site to terminate at one
+ target machine in the private edu.com sub-domain.
+
+ Further, discussion reveals that specific hostnames registered in
+ this private subdomain, or any similarly named subdomain may be used
+ to spoof a host.
+
+ Example: harvard.edu.com. CNAME targethost
+
+ Thus all connects to Harvard.edu from all .com sites would end up at
+ targthost, a machine which could provide a Harvard.edu login banner.
+
+ This is clearly unacceptable. Further, it could only be made worse
+ with domains like COM.EDU, MIL.GOV, GOV.COM, etc.
+
+Public vs. Local Name Space Administration
+
+ The specification of the Domain Name System and the software that
+ implements it provides an undifferentiated hierarchy which permits
+ delegation of administration for subordinate portions of the name
+ space. Actual administration of the name space is divided between
+ "public" and "local" portions. Public administration pertains to all
+ top-level domains, such as .COM and .EDU. For some domains, it also
+ pertains to some number of sub-domain levels. The multi-level nature
+ of the public administration is most evident for top-level domains
+ for countries. For example in the Fully Qualified Domain Name,
+ dbc.mtview.ca.us., the portion "mtview.ca.us" represents three levels
+ of public administration. Only the left-most portion is subject to
+ local administration.
+
+
+
+
+
+
+
+
+Gavron [Page 2]
+
+RFC 1535 DNS Software Enhancements October 1993
+
+
+ The danger of the heuristic search common in current practise is that
+ it it is possible to "intercept" the search by matching against an
+ unintended value while walking up the search list. While this is
+ potentially dangerous at any level, it is entirely unacceptable when
+ the error impacts users outside of a local administration.
+
+ When attempting to resolve a partial domain name, DNS resolvers use
+ the Domain Name of the searching host for deriving the search list.
+ Existing DNS resolvers do not distinguish the portion of that name
+ which is in the locally administered scope from the part that is
+ publically administered.
+
+Solution(s)
+
+ At a minimum, DNS resolvers must honor the BOUNDARY between local and
+ public administration, by limiting any search lists to locally-
+ administered portions of the Domain Name space. This requires a
+ parameter which shows the scope of the name space controlled by the
+ local administrator.
+
+ This would permit progressive searches from the most qualified to
+ less qualified up through the locally controlled domain, but not
+ beyond.
+
+ For example, if the local user were trying to reach:
+
+ User@chief.admin.DESERTU.EDU from
+ starburst,astro.DESERTU.EDU,
+
+ it is reasonable to permit the user to enter just chief.admin, and
+ for the search to cover:
+
+ chief.admin.astro.DESERTU.EDU
+ chief.admin.DESERTU.EDU
+
+ but not
+
+ chief.admin.EDU
+
+ In this case, the value of "search" should be set to "DESERTU.EDU"
+ because that's the scope of the name space controlled by the local
+ DNS administrator.
+
+ This is more than a mere optimization hack. The local administrator
+ has control over the assignment of names within the locally
+ administered domain, so the administrator can make sure that
+ abbreviations result in the right thing. Outside of the local
+ control, users are necessarily at risk.
+
+
+
+Gavron [Page 3]
+
+RFC 1535 DNS Software Enhancements October 1993
+
+
+ A more stringent mechanism is implemented in BIND 4.9.2, to respond
+ to this problem:
+
+ The DNS Name resolver clients narrows its IMPLICIT search list IF ANY
+ to only try the first and the last of the examples shown.
+
+ Any additional search alternatives must be configured into the
+ resolver EXPLICITLY.
+
+ DNS Name resolver software SHOULD NOT use implicit search lists in
+ attempts to resolve partial names into absolute FQDNs other than the
+ hosts's immediate parent domain.
+
+ Resolvers which continue to use implicit search lists MUST limit
+ their scope to locally administered sub-domains.
+
+ DNS Name resolver software SHOULD NOT come pre-configured with
+ explicit search lists that perpetuate this problem.
+
+ Further, in any event where a "." exists in a specified name it
+ should be assumed to be a fully qualified domain name (FQDN) and
+ SHOULD be tried as a rooted name first.
+
+ Example: Given user@a.b.c.d connecting to e.f.g.h only two tries
+ should be attempted as a result of using an implicit
+ search list:
+
+ e.f.g.h. and e.f.g.h.b.c.d.
+
+ Given user@a.b.c.d. connecting to host those same two
+ tries would appear as:
+
+ x.b.c.d. and x.
+
+ Some organizations make regular use of multi-part, partially
+ qualified Domain Names. For example, host foo.loc1.org.city.state.us
+ might be used to making references to bar.loc2, or mumble.loc3, all
+ of which refer to whatever.locN.org.city.state.us
+
+ The stringent implicit search rules for BIND 4.9.2 will now cause
+ these searches to fail. To return the ability for them to succeed,
+ configuration of the client resolvers must be changed to include an
+ explicit search rule for org.city.state.us. That is, it must contain
+ an explicit rule for any -- and each -- portion of the locally-
+ administered sub-domain that it wishes to have as part of the search
+ list.
+
+
+
+
+
+Gavron [Page 4]
+
+RFC 1535 DNS Software Enhancements October 1993
+
+
+References
+
+ [1] Mockapetris, P., "Domain Names Concepts and Facilities", STD 13,
+ RFC 1034, USC/Information Sciences Institute, November 1987.
+
+ [2] Mockapetris, P., "Domain Names Implementation and Specification",
+ STD 13, RFC 1035, USC/Information Sciences Institute, November
+ 1987.
+
+ [3] Partridge, C., "Mail Routing and the Domain System", STD 14, RFC
+ 974, CSNET CIC BBN, January 1986.
+
+ [4] Kumar, A., Postel, J., Neuman, C., Danzig, P., and S. Miller,
+ "Common DNS Implementation Errors and Suggested Fixes", RFC 1536,
+ USC/Information Sciences Institute, USC, October 1993.
+
+ [5] Beertema, P., "Common DNS Data File Configuration Errors", RFC
+ 1537, CWI, October 1993.
+
+Security Considerations
+
+ This memo indicates vulnerabilities with all too-forgiving DNS
+ clients. It points out a correction that would eliminate the future
+ potential of the problem.
+
+Author's Address
+
+ Ehud Gavron
+ ACES Research Inc.
+ PO Box 14546
+ Tucson, AZ 85711
+
+ Phone: (602) 743-9841
+ EMail: gavron@aces.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gavron [Page 5]
+
diff --git a/doc/rfc/rfc1536.txt b/doc/rfc/rfc1536.txt
new file mode 100644
index 0000000..5ff2b25
--- /dev/null
+++ b/doc/rfc/rfc1536.txt
@@ -0,0 +1,675 @@
+
+
+
+
+
+
+Network Working Group A. Kumar
+Request for Comments: 1536 J. Postel
+Category: Informational C. Neuman
+ ISI
+ P. Danzig
+ S. Miller
+ USC
+ October 1993
+
+
+ Common DNS Implementation Errors and Suggested Fixes
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard. Distribution of this memo is
+ unlimited.
+
+Abstract
+
+ This memo describes common errors seen in DNS implementations and
+ suggests some fixes. Where applicable, violations of recommendations
+ from STD 13, RFC 1034 and STD 13, RFC 1035 are mentioned. The memo
+ also describes, where relevant, the algorithms followed in BIND
+ (versions 4.8.3 and 4.9 which the authors referred to) to serve as an
+ example.
+
+Introduction
+
+ The last few years have seen, virtually, an explosion of DNS traffic
+ on the NSFnet backbone. Various DNS implementations and various
+ versions of these implementations interact with each other, producing
+ huge amounts of unnecessary traffic. Attempts are being made by
+ researchers all over the internet, to document the nature of these
+ interactions, the symptomatic traffic patterns and to devise remedies
+ for the sick pieces of software.
+
+ This draft is an attempt to document fixes for known DNS problems so
+ people know what problems to watch out for and how to repair broken
+ software.
+
+1. Fast Retransmissions
+
+ DNS implements the classic request-response scheme of client-server
+ interaction. UDP is, therefore, the chosen protocol for communication
+ though TCP is used for zone transfers. The onus of requerying in case
+ no response is seen in a "reasonable" period of time, lies with the
+ client. Although RFC 1034 and 1035 do not recommend any
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 1]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+ retransmission policy, RFC 1035 does recommend that the resolvers
+ should cycle through a list of servers. Both name servers and stub
+ resolvers should, therefore, implement some kind of a retransmission
+ policy based on round trip time estimates of the name servers. The
+ client should back-off exponentially, probably to a maximum timeout
+ value.
+
+ However, clients might not implement either of the two. They might
+ not wait a sufficient amount of time before retransmitting or they
+ might not back-off their inter-query times sufficiently.
+
+ Thus, what the server would see will be a series of queries from the
+ same querying entity, spaced very close together. Of course, a
+ correctly implemented server discards all duplicate queries but the
+ queries contribute to wide-area traffic, nevertheless.
+
+ We classify a retransmission of a query as a pure Fast retry timeout
+ problem when a series of query packets meet the following conditions.
+
+ a. Query packets are seen within a time less than a "reasonable
+ waiting period" of each other.
+
+ b. No response to the original query was seen i.e., we see two or
+ more queries, back to back.
+
+ c. The query packets share the same query identifier.
+
+ d. The server eventually responds to the query.
+
+A GOOD IMPLEMENTATION:
+
+ BIND (we looked at versions 4.8.3 and 4.9) implements a good
+ retransmission algorithm which solves or limits all of these
+ problems. The Berkeley stub-resolver queries servers at an interval
+ that starts at the greater of 4 seconds and 5 seconds divided by the
+ number of servers the resolver queries. The resolver cycles through
+ servers and at the end of a cycle, backs off the time out
+ exponentially.
+
+ The Berkeley full-service resolver (built in with the program
+ "named") starts with a time-out equal to the greater of 4 seconds and
+ two times the round-trip time estimate of the server. The time-out
+ is backed off with each cycle, exponentially, to a ceiling value of
+ 45 seconds.
+
+
+
+
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 2]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+FIXES:
+
+ a. Estimate round-trip times or set a reasonably high initial
+ time-out.
+
+ b. Back-off timeout periods exponentially.
+
+ c. Yet another fundamental though difficult fix is to send the
+ client an acknowledgement of a query, with a round-trip time
+ estimate.
+
+ Since UDP is used, no response is expected by the client until the
+ query is complete. Thus, it is less likely to have information about
+ previous packets on which to estimate its back-off time. Unless, you
+ maintain state across queries, so subsequent queries to the same
+ server use information from previous queries. Unfortunately, such
+ estimates are likely to be inaccurate for chained requests since the
+ variance is likely to be high.
+
+ The fix chosen in the ARDP library used by Prospero is that the
+ server will send an initial acknowledgement to the client in those
+ cases where the server expects the query to take a long time (as
+ might be the case for chained queries). This initial acknowledgement
+ can include an expected time to wait before retrying.
+
+ This fix is more difficult since it requires that the client software
+ also be trained to expect the acknowledgement packet. This, in an
+ internet of millions of hosts is at best a hard problem.
+
+2. Recursion Bugs
+
+ When a server receives a client request, it first looks up its zone
+ data and the cache to check if the query can be answered. If the
+ answer is unavailable in either place, the server seeks names of
+ servers that are more likely to have the information, in its cache or
+ zone data. It then does one of two things. If the client desires the
+ server to recurse and the server architecture allows recursion, the
+ server chains this request to these known servers closest to the
+ queried name. If the client doesn't seek recursion or if the server
+ cannot handle recursion, it returns the list of name servers to the
+ client assuming the client knows what to do with these records.
+
+ The client queries this new list of name servers to get either the
+ answer, or names of another set of name servers to query. This
+ process repeats until the client is satisfied. Servers might also go
+ through this chaining process if the server returns a CNAME record
+ for the queried name. Some servers reprocess this name to try and get
+ the desired record type.
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 3]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+ However, in certain cases, this chain of events may not be good. For
+ example, a broken or malicious name server might list itself as one
+ of the name servers to query again. The unsuspecting client resends
+ the same query to the same server.
+
+ In another situation, more difficult to detect, a set of servers
+ might form a loop wherein A refers to B and B refers to A. This loop
+ might involve more than two servers.
+
+ Yet another error is where the client does not know how to process
+ the list of name servers returned, and requeries the same server
+ since that is one (of the few) servers it knows.
+
+ We, therefore, classify recursion bugs into three distinct
+ categories:
+
+ a. Ignored referral: Client did not know how to handle NS records
+ in the AUTHORITY section.
+
+ b. Too many referrals: Client called on a server too many times,
+ beyond a "reasonable" number, with same query. This is
+ different from a Fast retransmission problem and a Server
+ Failure detection problem in that a response is seen for every
+ query. Also, the identifiers are always different. It implies
+ client is in a loop and should have detected that and broken
+ it. (RFC 1035 mentions that client should not recurse beyond
+ a certain depth.)
+
+ c. Malicious Server: a server refers to itself in the authority
+ section. If a server does not have an answer now, it is very
+ unlikely it will be any better the next time you query it,
+ specially when it claims to be authoritative over a domain.
+
+ RFC 1034 warns against such situations, on page 35.
+
+ "Bound the amount of work (packets sent, parallel processes
+ started) so that a request can't get into an infinite loop or
+ start off a chain reaction of requests or queries with other
+ implementations EVEN IF SOMEONE HAS INCORRECTLY CONFIGURED
+ SOME DATA."
+
+A GOOD IMPLEMENTATION:
+
+ BIND fixes at least one of these problems. It places an upper limit
+ on the number of recursive queries it will make, to answer a
+ question. It chases a maximum of 20 referral links and 8 canonical
+ name translations.
+
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 4]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+FIXES:
+
+ a. Set an upper limit on the number of referral links and CNAME
+ links you are willing to chase.
+
+ Note that this is not guaranteed to break only recursion loops.
+ It could, in a rare case, prune off a very long search path,
+ prematurely. We know, however, with high probability, that if
+ the number of links cross a certain metric (two times the depth
+ of the DNS tree), it is a recursion problem.
+
+ b. Watch out for self-referring servers. Avoid them whenever
+ possible.
+
+ c. Make sure you never pass off an authority NS record with your
+ own name on it!
+
+ d. Fix clients to accept iterative answers from servers not built
+ to provide recursion. Such clients should either be happy with
+ the non-authoritative answer or be willing to chase the
+ referral links themselves.
+
+3. Zero Answer Bugs:
+
+ Name servers sometimes return an authoritative NOERROR with no
+ ANSWER, AUTHORITY or ADDITIONAL records. This happens when the
+ queried name is valid but it does not have a record of the desired
+ type. Of course, the server has authority over the domain.
+
+ However, once again, some implementations of resolvers do not
+ interpret this kind of a response reasonably. They always expect an
+ answer record when they see an authoritative NOERROR. These entities
+ continue to resend their queries, possibly endlessly.
+
+A GOOD IMPLEMENTATION
+
+ BIND resolver code does not query a server more than 3 times. If it
+ is unable to get an answer from 4 servers, querying them three times
+ each, it returns error.
+
+ Of course, it treats a zero-answer response the way it should be
+ treated; with respect!
+
+FIXES:
+
+ a. Set an upper limit on the number of retransmissions for a given
+ query, at the very least.
+
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 5]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+ b. Fix resolvers to interpret such a response as an authoritative
+ statement of non-existence of the record type for the given
+ name.
+
+4. Inability to detect server failure:
+
+ Servers in the internet are not very reliable (they go down every
+ once in a while) and resolvers are expected to adapt to the changed
+ scenario by not querying the server for a while. Thus, when a server
+ does not respond to a query, resolvers should try another server.
+ Also, non-stub resolvers should update their round trip time estimate
+ for the server to a large value so that server is not tried again
+ before other, faster servers.
+
+ Stub resolvers, however, cycle through a fixed set of servers and if,
+ unfortunately, a server is down while others do not respond for other
+ reasons (high load, recursive resolution of query is taking more time
+ than the resolver's time-out, ....), the resolver queries the dead
+ server again! In fact, some resolvers might not set an upper limit on
+ the number of query retransmissions they will send and continue to
+ query dead servers indefinitely.
+
+ Name servers running system or chained queries might also suffer from
+ the same problem. They store names of servers they should query for a
+ given domain. They cycle through these names and in case none of them
+ answers, hit each one more than one. It is, once again, important
+ that there be an upper limit on the number of retransmissions, to
+ prevent network overload.
+
+ This behavior is clearly in violation of the dictum in RFC 1035 (page
+ 46)
+
+ "If a resolver gets a server error or other bizarre response
+ from a name server, it should remove it from SLIST, and may
+ wish to schedule an immediate transmission to the next
+ candidate server address."
+
+ Removal from SLIST implies that the server is not queried again for
+ some time.
+
+ Correctly implemented full-service resolvers should, as pointed out
+ before, update round trip time values for servers that do not respond
+ and query them only after other, good servers. Full-service resolvers
+ might, however, not follow any of these common sense directives. They
+ query dead servers, and they query them endlessly.
+
+
+
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 6]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+A GOOD IMPLEMENTATION:
+
+ BIND places an upper limit on the number of times it queries a
+ server. Both the stub-resolver and the full-service resolver code do
+ this. Also, since the full-service resolver estimates round-trip
+ times and sorts name server addresses by these estimates, it does not
+ query a dead server again, until and unless all the other servers in
+ the list are dead too! Further, BIND implements exponential back-off
+ too.
+
+FIXES:
+
+ a. Set an upper limit on number of retransmissions.
+
+ b. Measure round-trip time from servers (some estimate is better
+ than none). Treat no response as a "very large" round-trip
+ time.
+
+ c. Maintain a weighted rtt estimate and decay the "large" value
+ slowly, with time, so that the server is eventually tested
+ again, but not after an indefinitely long period.
+
+ d. Follow an exponential back-off scheme so that even if you do
+ not restrict the number of queries, you do not overload the
+ net excessively.
+
+5. Cache Leaks:
+
+ Every resource record returned by a server is cached for TTL seconds,
+ where the TTL value is returned with the RR. Full-service (or stub)
+ resolvers cache the RR and answer any queries based on this cached
+ information, in the future, until the TTL expires. After that, one
+ more query to the wide-area network gets the RR in cache again.
+
+ Full-service resolvers might not implement this caching mechanism
+ well. They might impose a limit on the cache size or might not
+ interpret the TTL value correctly. In either case, queries repeated
+ within a TTL period of a RR constitute a cache leak.
+
+A GOOD/BAD IMPLEMENTATION:
+
+ BIND has no restriction on the cache size and the size is governed by
+ the limits on the virtual address space of the machine it is running
+ on. BIND caches RRs for the duration of the TTL returned with each
+ record.
+
+ It does, however, not follow the RFCs with respect to interpretation
+ of a 0 TTL value. If a record has a TTL value of 0 seconds, BIND uses
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 7]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+ the minimum TTL value, for that zone, from the SOA record and caches
+ it for that duration. This, though it saves some traffic on the
+ wide-area network, is not correct behavior.
+
+FIXES:
+
+ a. Look over your caching mechanism to ensure TTLs are interpreted
+ correctly.
+
+ b. Do not restrict cache sizes (come on, memory is cheap!).
+ Expired entries are reclaimed periodically, anyway. Of course,
+ the cache size is bound to have some physical limit. But, when
+ possible, this limit should be large (run your name server on
+ a machine with a large amount of physical memory).
+
+ c. Possibly, a mechanism is needed to flush the cache, when it is
+ known or even suspected that the information has changed.
+
+6. Name Error Bugs:
+
+ This bug is very similar to the Zero Answer bug. A server returns an
+ authoritative NXDOMAIN when the queried name is known to be bad, by
+ the server authoritative for the domain, in the absence of negative
+ caching. This authoritative NXDOMAIN response is usually accompanied
+ by the SOA record for the domain, in the authority section.
+
+ Resolvers should recognize that the name they queried for was a bad
+ name and should stop querying further.
+
+ Some resolvers might, however, not interpret this correctly and
+ continue to query servers, expecting an answer record.
+
+ Some applications, in fact, prompt NXDOMAIN answers! When given a
+ perfectly good name to resolve, they append the local domain to it
+ e.g., an application in the domain "foo.bar.com", when trying to
+ resolve the name "usc.edu" first tries "usc.edu.foo.bar.com", then
+ "usc.edu.bar.com" and finally the good name "usc.edu". This causes at
+ least two queries that return NXDOMAIN, for every good query. The
+ problem is aggravated since the negative answers from the previous
+ queries are not cached. When the same name is sought again, the
+ process repeats.
+
+ Some DNS resolver implementations suffer from this problem, too. They
+ append successive sub-parts of the local domain using an implicit
+ searchlist mechanism, when certain conditions are satisfied and try
+ the original name, only when this first set of iterations fails. This
+ behavior recently caused pandemonium in the Internet when the domain
+ "edu.com" was registered and a wildcard "CNAME" record placed at the
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 8]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+ top level. All machines from "com" domains trying to connect to hosts
+ in the "edu" domain ended up with connections to the local machine in
+ the "edu.com" domain!
+
+GOOD/BAD IMPLEMENTATIONS:
+
+ Some local versions of BIND already implement negative caching. They
+ typically cache negative answers with a very small TTL, sufficient to
+ answer a burst of queries spaced close together, as is typically
+ seen.
+
+ The next official public release of BIND (4.9.2) will have negative
+ caching as an ifdef'd feature.
+
+ The BIND resolver appends local domain to the given name, when one of
+ two conditions is met:
+
+ i. The name has no periods and the flag RES_DEFNAME is set.
+ ii. There is no trailing period and the flag RES_DNSRCH is set.
+
+ The flags RES_DEFNAME and RES_DNSRCH are default resolver options, in
+ BIND, but can be changed at compile time.
+
+ Only if the name, so generated, returns an NXDOMAIN is the original
+ name tried as a Fully Qualified Domain Name. And only if it contains
+ at least one period.
+
+FIXES:
+
+ a. Fix the resolver code.
+
+ b. Negative Caching. Negative caching servers will restrict the
+ traffic seen on the wide-area network, even if not curb it
+ altogether.
+
+ c. Applications and resolvers should not append the local domain to
+ names they seek to resolve, as far as possible. Names
+ interspersed with periods should be treated as Fully Qualified
+ Domain Names.
+
+ In other words, Use searchlists only when explicitly specified.
+ No implicit searchlists should be used. A name that contains
+ any dots should first be tried as a FQDN and if that fails, with
+ the local domain name (or searchlist if specified) appended. A
+ name containing no dots can be appended with the searchlist right
+ away, but once again, no implicit searchlists should be used.
+
+
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 9]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+ Associated with the name error bug is another problem where a server
+ might return an authoritative NXDOMAIN, although the name is valid. A
+ secondary server, on start-up, reads the zone information from the
+ primary, through a zone transfer. While it is in the process of
+ loading the zones, it does not have information about them, although
+ it is authoritative for them. Thus, any query for a name in that
+ domain is answered with an NXDOMAIN response code. This problem might
+ not be disastrous were it not for negative caching servers that cache
+ this answer and so propagate incorrect information over the internet.
+
+BAD IMPLEMENTATION:
+
+ BIND apparently suffers from this problem.
+
+ Also, a new name added to the primary database will take a while to
+ propagate to the secondaries. Until that time, they will return
+ NXDOMAIN answers for a good name. Negative caching servers store this
+ answer, too and aggravate this problem further. This is probably a
+ more general DNS problem but is apparently more harmful in this
+ situation.
+
+FIX:
+
+ a. Servers should start answering only after loading all the zone
+ data. A failed server is better than a server handing out
+ incorrect information.
+
+ b. Negative cache records for a very small time, sufficient only
+ to ward off a burst of requests for the same bad name. This
+ could be related to the round-trip time of the server from
+ which the negative answer was received. Alternatively, a
+ statistical measure of the amount of time for which queries
+ for such names are received could be used. Minimum TTL value
+ from the SOA record is not advisable since they tend to be
+ pretty large.
+
+ c. A "PUSH" (or, at least, a "NOTIFY") mechanism should be allowed
+ and implemented, to allow the primary server to inform
+ secondaries that the database has been modified since it last
+ transferred zone data. To alleviate the problem of "too many
+ zone transfers" that this might cause, Incremental Zone
+ Transfers should also be part of DNS. Also, the primary should
+ not NOTIFY/PUSH with every update but bunch a good number
+ together.
+
+
+
+
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 10]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+7. Format Errors:
+
+ Some resolvers issue query packets that do not necessarily conform to
+ standards as laid out in the relevant RFCs. This unnecessarily
+ increases net traffic and wastes server time.
+
+FIXES:
+
+ a. Fix resolvers.
+
+ b. Each resolver verify format of packets before sending them out,
+ using a mechanism outside of the resolver. This is, obviously,
+ needed only if step 1 cannot be followed.
+
+References
+
+ [1] Mockapetris, P., "Domain Names Concepts and Facilities", STD 13,
+ RFC 1034, USC/Information Sciences Institute, November 1987.
+
+ [2] Mockapetris, P., "Domain Names Implementation and Specification",
+ STD 13, RFC 1035, USC/Information Sciences Institute, November
+ 1987.
+
+ [3] Partridge, C., "Mail Routing and the Domain System", STD 14, RFC
+ 974, CSNET CIC BBN, January 1986.
+
+ [4] Gavron, E., "A Security Problem and Proposed Correction With
+ Widely Deployed DNS Software", RFC 1535, ACES Research Inc.,
+ October 1993.
+
+ [5] Beertema, P., "Common DNS Data File Configuration Errors", RFC
+ 1537, CWI, October 1993.
+
+Security Considerations
+
+ Security issues are not discussed in this memo.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 11]
+
+RFC 1536 Common DNS Implementation Errors October 1993
+
+
+Authors' Addresses
+
+ Anant Kumar
+ USC Information Sciences Institute
+ 4676 Admiralty Way
+ Marina Del Rey CA 90292-6695
+
+ Phone:(310) 822-1511
+ FAX: (310) 823-6741
+ EMail: anant@isi.edu
+
+
+ Jon Postel
+ USC Information Sciences Institute
+ 4676 Admiralty Way
+ Marina Del Rey CA 90292-6695
+
+ Phone:(310) 822-1511
+ FAX: (310) 823-6714
+ EMail: postel@isi.edu
+
+
+ Cliff Neuman
+ USC Information Sciences Institute
+ 4676 Admiralty Way
+ Marina Del Rey CA 90292-6695
+
+ Phone:(310) 822-1511
+ FAX: (310) 823-6714
+ EMail: bcn@isi.edu
+
+
+ Peter Danzig
+ Computer Science Department
+ University of Southern California
+ University Park
+
+ EMail: danzig@caldera.usc.edu
+
+
+ Steve Miller
+ Computer Science Department
+ University of Southern California
+ University Park
+ Los Angeles CA 90089
+
+ EMail: smiller@caldera.usc.edu
+
+
+
+
+Kumar, Postel, Neuman, Danzig & Miller [Page 12]
+
diff --git a/doc/rfc/rfc1537.txt b/doc/rfc/rfc1537.txt
new file mode 100644
index 0000000..81b9768
--- /dev/null
+++ b/doc/rfc/rfc1537.txt
@@ -0,0 +1,507 @@
+
+
+
+
+
+
+Network Working Group P. Beertema
+Request for Comments: 1537 CWI
+Category: Informational October 1993
+
+
+ Common DNS Data File Configuration Errors
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard. Distribution of this memo is
+ unlimited.
+
+Abstract
+
+ This memo describes errors often found in DNS data files. It points
+ out common mistakes system administrators tend to make and why they
+ often go unnoticed for long periods of time.
+
+Introduction
+
+ Due to the lack of extensive documentation and automated tools, DNS
+ zone files have mostly been configured by system administrators, by
+ hand. Some of the rules for writing the data files are rather subtle
+ and a few common mistakes are seen in domains worldwide.
+
+ This document is an attempt to list "surprises" that administrators
+ might find hidden in their zone files. It describes the symptoms of
+ the malady and prescribes medicine to cure that. It also gives some
+ general recommendations and advice on specific nameserver and zone
+ file issues and on the (proper) use of the Domain Name System.
+
+1. SOA records
+
+ A problem I've found in quite some nameservers is that the various
+ timers have been set (far) too low. Especially for top level domain
+ nameservers this causes unnecessary traffic over international and
+ intercontinental links.
+
+ Unfortunately the examples given in the BIND manual, in RFC's and in
+ some expert documents give those very short timer values, and that's
+ most likely what people have modeled their SOA records after.
+
+ First of all a short explanation of the timers used in the SOA
+ record:
+
+
+
+
+
+
+Beertema [Page 1]
+
+RFC 1537 Common DNS Data File Configuration Errors October 1993
+
+
+ - Refresh: The SOA record of the primary server is checked
+ every "refresh" time by the secondary servers;
+ if it has changed, a zone transfer is done.
+
+ - Retry: If a secondary server cannot reach the primary
+ server, it tries it again every "retry" time.
+
+ - Expire: If for "expire" time the primary server cannot
+ be reached, all information about the zone is
+ invalidated on the secondary servers (i.e., they
+ are no longer authoritative for that zone).
+
+ - Minimum TTL: The default TTL value for all records in the
+ zone file; a different TTL value may be given
+ explicitly in a record when necessary.
+ (This timer is named "Minimum", and that's
+ what it's function should be according to
+ STD 13, RFC 1035, but most (all?)
+ implementations take it as the default value
+ exported with records without an explicit TTL
+ value).
+
+ For top level domain servers I would recommend the following values:
+
+ 86400 ; Refresh 24 hours
+ 7200 ; Retry 2 hours
+ 2592000 ; Expire 30 days
+ 345600 ; Minimum TTL 4 days
+
+ For other servers I would suggest:
+
+ 28800 ; Refresh 8 hours
+ 7200 ; Retry 2 hours
+ 604800 ; Expire 7 days
+ 86400 ; Minimum TTL 1 day
+
+ but here the frequency of changes, the required speed of propagation,
+ the reachability of the primary server etc. play a role in optimizing
+ the timer values.
+
+2. Glue records
+
+ Quite often, people put unnecessary glue (A) records in their zone
+ files. Even worse is that I've even seen *wrong* glue records for an
+ external host in a primary zone file! Glue records need only be in a
+ zone file if the server host is within the zone and there is no A
+ record for that host elsewhere in the zone file.
+
+
+
+
+Beertema [Page 2]
+
+RFC 1537 Common DNS Data File Configuration Errors October 1993
+
+
+ Old BIND versions ("native" 4.8.3 and older versions) showed the
+ problem that wrong glue records could enter secondary servers in a
+ zone transfer.
+
+3. "Secondary server surprise"
+
+ I've seen it happen on various occasions that hosts got bombarded by
+ nameserver requests without knowing why. On investigation it turned
+ out then that such a host was supposed to (i.e., the information was
+ in the root servers) run secondary for some domain (or reverse (in-
+ addr.arpa)) domain, without that host's nameserver manager having
+ been asked or even been told so!
+
+ Newer BIND versions (4.9 and later) solved this problem. At the same
+ time though the fix has the disadvantage that it's far less easy to
+ spot this problem.
+
+ Practice has shown that most domain registrars accept registrations
+ of nameservers without checking if primary (!) and secondary servers
+ have been set up, informed, or even asked. It should also be noted
+ that a combination of long-lasting unreachability of primary
+ nameservers, (therefore) expiration of zone information, plus static
+ IP routing, can lead to massive network traffic that can fill up
+ lines completely.
+
+4. "MX records surprise"
+
+ In a sense similar to point 3. Sometimes nameserver managers enter MX
+ records in their zone files that point to external hosts, without
+ first asking or even informing the systems managers of those external
+ hosts. This has to be fought out between the nameserver manager and
+ the systems managers involved. Only as a last resort, if really
+ nothing helps to get the offending records removed, can the systems
+ manager turn to the naming authority of the domain above the
+ offending domain to get the problem sorted out.
+
+5. "Name extension surprise"
+
+ Sometimes one encounters weird names, which appear to be an external
+ name extended with a local domain. This is caused by forgetting to
+ terminate a name with a dot: names in zone files that don't end with
+ a dot are always expanded with the name of the current zone (the
+ domain that the zone file stands for or the last $ORIGIN).
+
+ Example: zone file for foo.xx:
+
+ pqr MX 100 relay.yy.
+ xyz MX 100 relay.yy (no trailing dot!)
+
+
+
+Beertema [Page 3]
+
+RFC 1537 Common DNS Data File Configuration Errors October 1993
+
+
+ When fully written out this stands for:
+
+ pqr.foo.xx. MX 100 relay.yy.
+ xyz.foo.xx. MX 100 relay.yy.foo.xx. (name extension!)
+
+6. Missing secondary servers
+
+ It is required that there be a least 2 nameservers for a domain. For
+ obvious reasons the nameservers for top level domains need to be very
+ well reachable from all over the Internet. This implies that there
+ must be more than just 2 of them; besides, most of the (secondary)
+ servers should be placed at "strategic" locations, e.g., close to a
+ point where international and/or intercontinental lines come
+ together. To keep things manageable, there shouldn't be too many
+ servers for a domain either.
+
+ Important aspects in selecting the location of primary and secondary
+ servers are reliability (network, host) and expedient contacts: in
+ case of problems, changes/fixes must be carried out quickly. It
+ should be considered logical that primary servers for European top
+ level domains should run on a host in Europe, preferably (if
+ possible) in the country itself. For each top level domain there
+ should be 2 secondary servers in Europe and 2 in the USA, but there
+ may of course be more on either side. An excessive number of
+ nameservers is not a good idea though; a recommended maximum is 7
+ nameservers. In Europe, EUnet has offered to run secondary server
+ for each European top level domain.
+
+7. Wildcard MX records
+
+ Wildcard MX records should be avoided where possible. They often
+ cause confusion and errors: especially beginning nameserver managers
+ tend to overlook the fact that a host/domain listed with ANY type of
+ record in a zone file is NOT covered by an overall wildcard MX record
+ in that zone; this goes not only for simple domain/host names, but
+ also for names that cover one or more domains. Take the following
+ example in zone foo.bar:
+
+ * MX 100 mailhost
+ pqr MX 100 mailhost
+ abc.def MX 100 mailhost
+
+ This makes pqr.foo.bar, def.foo.bar and abd.def.foo.bar valid
+ domains, but the wildcard MX record covers NONE of them, nor anything
+ below them. To cover everything by MX records, the required entries
+ are:
+
+
+
+
+
+Beertema [Page 4]
+
+RFC 1537 Common DNS Data File Configuration Errors October 1993
+
+
+ * MX 100 mailhost
+ pqr MX 100 mailhost
+ *.pqr MX 100 mailhost
+ abc.def MX 100 mailhost
+ *.def MX 100 mailhost
+ *.abc.def MX 100 mailhost
+
+ An overall wildcard MX record is almost never useful.
+
+ In particular the zone file of a top level domain should NEVER
+ contain only an overall wildcard MX record (*.XX). The effect of such
+ a wildcard MX record can be that mail is unnecessarily sent across
+ possibly expensive links, only to fail at the destination or gateway
+ that the record points to. Top level domain zone files should
+ explicitly list at least all the officially registered primary
+ subdomains.
+
+ Whereas overall wildcard MX records should be avoided, wildcard MX
+ records are acceptable as an explicit part of subdomain entries,
+ provided they are allowed under a given subdomain (to be determined
+ by the naming authority for that domain).
+
+ Example:
+
+ foo.xx. MX 100 gateway.xx.
+ MX 200 fallback.yy.
+ *.foo.xx. MX 100 gateway.xx.
+ MX 200 fallback.yy.
+8. Hostnames
+
+ People appear to sometimes look only at STD 11, RFC 822 to determine
+ whether a particular hostname is correct or not. Hostnames should
+ strictly conform to the syntax given in STD 13, RFC 1034 (page 11),
+ with *addresses* in addition conforming to RFC 822. As an example
+ take "c&w.blues" which is perfectly legal according to RFC 822, but
+ which can have quite surprising effects on particular systems, e.g.,
+ "telnet c&w.blues" on a Unix system.
+
+9. HINFO records
+
+ There appears to be a common misunderstanding that one of the data
+ fields (usually the second field) in HINFO records is optional. A
+ recent scan of all reachable nameservers in only one country revealed
+ some 300 incomplete HINFO records. Specifying two data fields in a
+ HINFO record is mandatory (RFC 1033), but note that this does *not*
+ mean that HINFO records themselves are mandatory.
+
+
+
+
+
+Beertema [Page 5]
+
+RFC 1537 Common DNS Data File Configuration Errors October 1993
+
+
+10. Safety measures and specialties
+
+ Nameservers and resolvers aren't flawless. Bogus queries should be
+ kept from being forwarded to the root servers, since they'll only
+ lead to unnecessary intercontinental traffic. Known bogus queries
+ that can easily be dealt with locally are queries for 0 and broadcast
+ addresses. To catch such queries, every nameserver should run
+ primary for the 0.in-addr.arpa and 255.in-addr.arpa zones; the zone
+ files need only contain a SOA and an NS record.
+
+ Also each nameserver should run primary for 0.0.127.in-addr.arpa;
+ that zone file should contain a SOA and NS record and an entry:
+
+ 1 PTR localhost.
+
+ There has been extensive discussion about whether or not to append
+ the local domain to it. The conclusion was that "localhost." would be
+ the best solution; reasons given were:
+
+ - "localhost" itself is used and expected to work on some systems.
+
+ - translating 127.0.0.1 into "localhost.my_domain" can cause some
+ software to connect to itself using the loopback interface when
+ it didn't want to.
+
+ Note that all domains that contain hosts should have a "localhost" A
+ record in them.
+
+ People maintaining zone files with the Serial number given in dotted
+ decimal notation (e.g., when SCCS is used to maintain the files)
+ should beware of a bug in all BIND versions: if the serial number is
+ in Release.Version (dotted decimal) notation, then it is virtually
+ impossible to change to a higher release: because of the wrong way
+ that notation is turned into an integer, it results in a serial
+ number that is LOWER than that of the former release.
+
+ For this reason and because the Serial is an (unsigned) integer
+ according to STD 13, RFC 1035, it is recommended not to use the
+ dotted decimal notation. A recommended notation is to use the date
+ (yyyymmdd), if necessary with an extra digit (yyyymmddn) if there is
+ or can be more than one change per day in a zone file.
+
+ Very old versions of DNS resolver code have a bug that causes queries
+ for A records with domain names like "192.16.184.3" to go out. This
+ happens when users type in IP addresses and the resolver code does
+ not catch this case before sending out a DNS query. This problem has
+ been fixed in all resolver implementations known to us but if it
+ still pops up it is very serious because all those queries will go to
+
+
+
+Beertema [Page 6]
+
+RFC 1537 Common DNS Data File Configuration Errors October 1993
+
+
+ the root servers looking for top level domains like "3" etc. It is
+ strongly recommended to install the latest (publicly) available BIND
+ version plus all available patches to get rid of these and other
+ problems.
+
+ Running secondary nameserver off another secondary nameserver is
+ possible, but not recommended unless really necessary: there are
+ known cases where it has led to problems like bogus TTL values. This
+ can be caused by older or flawed implementations, but secondary
+ nameservers in principle should always transfer their zones from the
+ official primary nameserver.
+
+11. Some general points
+
+ The Domain Name System and nameserver are purely technical tools, not
+ meant in any way to exert control or impose politics. The function of
+ a naming authority is that of a clearing house. Anyone registering a
+ subdomain under a particular (top level) domain becomes naming
+ authority and therewith the sole responsible for that subdomain.
+ Requests to enter MX or NS records concerning such a subdomain
+ therefore always MUST be honored by the registrar of the next higher
+ domain.
+
+ Examples of practices that are not allowed are:
+
+ - imposing specific mail routing (MX records) when registering
+ a subdomain.
+
+ - making registration of a subdomain dependent on to the use of
+ certain networks or services.
+
+ - using TXT records as a means of (free) commercial advertising.
+
+ In the latter case a network service provider could decide to cut off
+ a particular site until the offending TXT records have been removed
+ from the site's zone file.
+
+ Of course there are obvious cases where a naming authority can refuse
+ to register a particular subdomain and can require a proposed name to
+ be changed in order to get it registered (think of DEC trying to
+ register a domain IBM.XX).
+
+ There are also cases were one has to probe the authority of the
+ person: sending in the application - not every systems manager should
+ be able to register a domain name for a whole university. The naming
+ authority can impose certain extra rules as long as they don't
+ violate or conflict with the rights and interest of the registrars of
+ subdomains; a top level domain registrar may e.g., require that there
+
+
+
+Beertema [Page 7]
+
+RFC 1537 Common DNS Data File Configuration Errors October 1993
+
+
+ be primary subdomain "ac" and "co" only and that subdomains be
+ registered under those primary subdomains.
+
+ The naming authority can also interfere in exceptional cases like the
+ one mentioned in point 4, e.g., by temporarily removing a domain's
+ entry from the nameserver zone files; this of course should be done
+ only with extreme care and only as a last resort.
+
+ When adding NS records for subdomains, top level domain nameserver
+ managers should realize that the people setting up the nameserver for
+ a subdomain often are rather inexperienced and can make mistakes that
+ can easily lead to the subdomain becoming completely unreachable or
+ that can cause unnecessary DNS traffic (see point 1). It is therefore
+ highly recommended that, prior to entering such an NS record, the
+ (top level) nameserver manager does a couple of sanity checks on the
+ new nameserver (SOA record and timers OK?, MX records present where
+ needed? No obvious errors made? Listed secondary servers
+ operational?). Things that cannot be caught though by such checks
+ are:
+
+ - resolvers set up to use external hosts as nameservers
+
+ - nameservers set up to use external hosts as forwarders
+ without permission from those hosts.
+
+ Care should also be taken when registering 2-letter subdomains.
+ Although this is allowed, an implication is that abbreviated
+ addressing (see STD 11, RFC 822, paragraph 6.2.2) is not possible in
+ and under that subdomain. When requested to register such a domain,
+ one should always notify the people of this consequence. As an
+ example take the name "cs", which is commonly used for Computer
+ Science departments: it is also the name of the top level domain for
+ Czecho-Slovakia, so within the domain cs.foo.bar the user@host.cs is
+ ambiguous in that in can denote both a user on the host
+ host.cs.foo.bar and a user on the host "host" in Czecho-Slovakia.
+ (This example does not take into account the recent political changes
+ in the mentioned country).
+
+References
+
+ [1] Mockapetris, P., "Domain Names Concepts and Facilities", STD 13,
+ RFC 1034, USC/Information Sciences Institute, November 1987.
+
+ [2] Mockapetris, P., "Domain Names Implementation and Specification",
+ STD 13, RFC 1035, USC/Information Sciences Institute, November
+ 1987.
+
+
+
+
+
+Beertema [Page 8]
+
+RFC 1537 Common DNS Data File Configuration Errors October 1993
+
+
+ [3] Partridge, C., "Mail Routing and the Domain System", STD 14, RFC
+ 974, CSNET CIC BBN, January 1986.
+
+ [4] Gavron, E., "A Security Problem and Proposed Correction With
+ Widely Deployed DNS Software", RFC 1535, ACES Research Inc.,
+ October 1993.
+
+ [5] Kumar, A., Postel, J., Neuman, C., Danzig, P., and S. Miller,
+ "Common DNS Implementation Errors and Suggested Fixes", RFC 1536,
+ USC/Information Sciences Institute, USC, October 1993.
+
+Security Considerations
+
+ Security issues are not discussed in this memo.
+
+Author's Address
+
+ Piet Beertema
+ CWI
+ Kruislaan 413
+ NL-1098 SJ Amsterdam
+ The Netherlands
+
+ Phone: +31 20 592 4112
+ FAX: +31 20 592 4199
+ EMail: Piet.Beertema@cwi.nl
+
+
+Editor's Address
+
+ Anant Kumar
+ USC Information Sciences Institute
+ 4676 Admiralty Way
+ Marina Del Rey CA 90292-6695
+
+ Phone:(310) 822-1511
+ FAX: (310) 823-6741
+ EMail: anant@isi.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+Beertema [Page 9]
+ \ No newline at end of file
diff --git a/doc/rfc/rfc1591.txt b/doc/rfc/rfc1591.txt
new file mode 100644
index 0000000..89e0a25
--- /dev/null
+++ b/doc/rfc/rfc1591.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group J. Postel
+Request for Comments: 1591 ISI
+Category: Informational March 1994
+
+
+ Domain Name System Structure and Delegation
+
+
+Status of this Memo
+
+ This memo provides information for the Internet community. This memo
+ does not specify an Internet standard of any kind. Distribution of
+ this memo is unlimited.
+
+1. Introduction
+
+ This memo provides some information on the structure of the names in
+ the Domain Name System (DNS), specifically the top-level domain
+ names; and on the administration of domains. The Internet Assigned
+ Numbers Authority (IANA) is the overall authority for the IP
+ Addresses, the Domain Names, and many other parameters, used in the
+ Internet. The day-to-day responsibility for the assignment of IP
+ Addresses, Autonomous System Numbers, and most top and second level
+ Domain Names are handled by the Internet Registry (IR) and regional
+ registries.
+
+2. The Top Level Structure of the Domain Names
+
+ In the Domain Name System (DNS) naming of computers there is a
+ hierarchy of names. The root of system is unnamed. There are a set
+ of what are called "top-level domain names" (TLDs). These are the
+ generic TLDs (EDU, COM, NET, ORG, GOV, MIL, and INT), and the two
+ letter country codes from ISO-3166. It is extremely unlikely that
+ any other TLDs will be created.
+
+ Under each TLD may be created a hierarchy of names. Generally, under
+ the generic TLDs the structure is very flat. That is, many
+ organizations are registered directly under the TLD, and any further
+ structure is up to the individual organizations.
+
+ In the country TLDs, there is a wide variation in the structure, in
+ some countries the structure is very flat, in others there is
+ substantial structural organization. In some country domains the
+ second levels are generic categories (such as, AC, CO, GO, and RE),
+ in others they are based on political geography, and in still others,
+ organization names are listed directly under the country code. The
+ organization for the US country domain is described in RFC 1480 [1].
+
+
+
+
+Postel [Page 1]
+
+RFC 1591 Domain Name System Structure and Delegation March 1994
+
+
+ Each of the generic TLDs was created for a general category of
+ organizations. The country code domains (for example, FR, NL, KR,
+ US) are each organized by an administrator for that country. These
+ administrators may further delegate the management of portions of the
+ naming tree. These administrators are performing a public service on
+ behalf of the Internet community. Descriptions of the generic
+ domains and the US country domain follow.
+
+ Of these generic domains, five are international in nature, and two
+ are restricted to use by entities in the United States.
+
+ World Wide Generic Domains:
+
+ COM - This domain is intended for commercial entities, that is
+ companies. This domain has grown very large and there is
+ concern about the administrative load and system performance if
+ the current growth pattern is continued. Consideration is
+ being taken to subdivide the COM domain and only allow future
+ commercial registrations in the subdomains.
+
+ EDU - This domain was originally intended for all educational
+ institutions. Many Universities, colleges, schools,
+ educational service organizations, and educational consortia
+ have registered here. More recently a decision has been taken
+ to limit further registrations to 4 year colleges and
+ universities. Schools and 2-year colleges will be registered
+ in the country domains (see US Domain, especially K12 and CC,
+ below).
+
+ NET - This domain is intended to hold only the computers of network
+ providers, that is the NIC and NOC computers, the
+ administrative computers, and the network node computers. The
+ customers of the network provider would have domain names of
+ their own (not in the NET TLD).
+
+ ORG - This domain is intended as the miscellaneous TLD for
+ organizations that didn't fit anywhere else. Some non-
+ government organizations may fit here.
+
+ INT - This domain is for organizations established by international
+ treaties, or international databases.
+
+ United States Only Generic Domains:
+
+ GOV - This domain was originally intended for any kind of government
+ office or agency. More recently a decision was taken to
+ register only agencies of the US Federal government in this
+ domain. State and local agencies are registered in the country
+
+
+
+Postel [Page 2]
+
+RFC 1591 Domain Name System Structure and Delegation March 1994
+
+
+ domains (see US Domain, below).
+
+ MIL - This domain is used by the US military.
+
+ Example country code Domain:
+
+ US - As an example of a country domain, the US domain provides for
+ the registration of all kinds of entities in the United States
+ on the basis of political geography, that is, a hierarchy of
+ <entity-name>.<locality>.<state-code>.US. For example,
+ "IBM.Armonk.NY.US". In addition, branches of the US domain are
+ provided within each state for schools (K12), community colleges
+ (CC), technical schools (TEC), state government agencies
+ (STATE), councils of governments (COG),libraries (LIB), museums
+ (MUS), and several other generic types of entities (see RFC 1480
+ for details [1]).
+
+ To find a contact for a TLD use the "whois" program to access the
+ database on the host rs.internic.net. Append "-dom" to the name of
+ TLD you are interested in. For example:
+
+ whois -h rs.internic.net us-dom
+ or
+ whois -h rs.internic.net edu-dom
+
+3. The Administration of Delegated Domains
+
+ The Internet Assigned Numbers Authority (IANA) is responsible for the
+ overall coordination and management of the Domain Name System (DNS),
+ and especially the delegation of portions of the name space called
+ top-level domains. Most of these top-level domains are two-letter
+ country codes taken from the ISO standard 3166.
+
+ A central Internet Registry (IR) has been selected and designated to
+ handled the bulk of the day-to-day administration of the Domain Name
+ System. Applications for new top-level domains (for example, country
+ code domains) are handled by the IR with consultation with the IANA.
+ The central IR is INTERNIC.NET. Second level domains in COM, EDU,
+ ORG, NET, and GOV are registered by the Internet Registry at the
+ InterNIC. The second level domains in the MIL are registered by the
+ DDN registry at NIC.DDN.MIL. Second level names in INT are
+ registered by the PVM at ISI.EDU.
+
+ While all requests for new top-level domains must be sent to the
+ Internic (at hostmaster@internic.net), the regional registries are
+ often enlisted to assist in the administration of the DNS, especially
+ in solving problems with a country administration. Currently, the
+ RIPE NCC is the regional registry for Europe and the APNIC is the
+
+
+
+Postel [Page 3]
+
+RFC 1591 Domain Name System Structure and Delegation March 1994
+
+
+ regional registry for the Asia-Pacific region, while the INTERNIC
+ administers the North America region, and all the as yet undelegated
+ regions.
+
+ The contact mailboxes for these regional registries are:
+
+ INTERNIC hostmaster@internic.net
+ APNIC hostmaster@apnic.net
+ RIPE NCC ncc@ripe.net
+
+ The policy concerns involved when a new top-level domain is
+ established are described in the following. Also mentioned are
+ concerns raised when it is necessary to change the delegation of an
+ established domain from one party to another.
+
+ A new top-level domain is usually created and its management
+ delegated to a "designated manager" all at once.
+
+ Most of these same concerns are relevant when a sub-domain is
+ delegated and in general the principles described here apply
+ recursively to all delegations of the Internet DNS name space.
+
+ The major concern in selecting a designated manager for a domain is
+ that it be able to carry out the necessary responsibilities, and have
+ the ability to do a equitable, just, honest, and competent job.
+
+ 1) The key requirement is that for each domain there be a designated
+ manager for supervising that domain's name space. In the case of
+ top-level domains that are country codes this means that there is
+ a manager that supervises the domain names and operates the domain
+ name system in that country.
+
+ The manager must, of course, be on the Internet. There must be
+ Internet Protocol (IP) connectivity to the nameservers and email
+ connectivity to the management and staff of the manager.
+
+ There must be an administrative contact and a technical contact
+ for each domain. For top-level domains that are country codes at
+ least the administrative contact must reside in the country
+ involved.
+
+ 2) These designated authorities are trustees for the delegated
+ domain, and have a duty to serve the community.
+
+ The designated manager is the trustee of the top-level domain for
+ both the nation, in the case of a country code, and the global
+ Internet community.
+
+
+
+
+Postel [Page 4]
+
+RFC 1591 Domain Name System Structure and Delegation March 1994
+
+
+ Concerns about "rights" and "ownership" of domains are
+ inappropriate. It is appropriate to be concerned about
+ "responsibilities" and "service" to the community.
+
+ 3) The designated manager must be equitable to all groups in the
+ domain that request domain names.
+
+ This means that the same rules are applied to all requests, all
+ requests must be processed in a non-discriminatory fashion, and
+ academic and commercial (and other) users are treated on an equal
+ basis. No bias shall be shown regarding requests that may come
+ from customers of some other business related to the manager --
+ e.g., no preferential service for customers of a particular data
+ network provider. There can be no requirement that a particular
+ mail system (or other application), protocol, or product be used.
+
+ There are no requirements on subdomains of top-level domains
+ beyond the requirements on higher-level domains themselves. That
+ is, the requirements in this memo are applied recursively. In
+ particular, all subdomains shall be allowed to operate their own
+ domain name servers, providing in them whatever information the
+ subdomain manager sees fit (as long as it is true and correct).
+
+ 4) Significantly interested parties in the domain should agree that
+ the designated manager is the appropriate party.
+
+ The IANA tries to have any contending parties reach agreement
+ among themselves, and generally takes no action to change things
+ unless all the contending parties agree; only in cases where the
+ designated manager has substantially mis-behaved would the IANA
+ step in.
+
+ However, it is also appropriate for interested parties to have
+ some voice in selecting the designated manager.
+
+ There are two cases where the IANA and the central IR may
+ establish a new top-level domain and delegate only a portion of
+ it: (1) there are contending parties that cannot agree, or (2) the
+ applying party may not be able to represent or serve the whole
+ country. The later case sometimes arises when a party outside a
+ country is trying to be helpful in getting networking started in a
+ country -- this is sometimes called a "proxy" DNS service.
+
+ The Internet DNS Names Review Board (IDNB), a committee
+ established by the IANA, will act as a review panel for cases in
+ which the parties can not reach agreement among themselves. The
+ IDNB's decisions will be binding.
+
+
+
+
+Postel [Page 5]
+
+RFC 1591 Domain Name System Structure and Delegation March 1994
+
+
+ 5) The designated manager must do a satisfactory job of operating the
+ DNS service for the domain.
+
+ That is, the actual management of the assigning of domain names,
+ delegating subdomains and operating nameservers must be done with
+ technical competence. This includes keeping the central IR (in
+ the case of top-level domains) or other higher-level domain
+ manager advised of the status of the domain, responding to
+ requests in a timely manner, and operating the database with
+ accuracy, robustness, and resilience.
+
+ There must be a primary and a secondary nameserver that have IP
+ connectivity to the Internet and can be easily checked for
+ operational status and database accuracy by the IR and the IANA.
+
+ In cases when there are persistent problems with the proper
+ operation of a domain, the delegation may be revoked, and possibly
+ delegated to another designated manager.
+
+ 6) For any transfer of the designated manager trusteeship from one
+ organization to another, the higher-level domain manager (the IANA
+ in the case of top-level domains) must receive communications from
+ both the old organization and the new organization that assure the
+ IANA that the transfer in mutually agreed, and that the new
+ organization understands its responsibilities.
+
+ It is also very helpful for the IANA to receive communications
+ from other parties that may be concerned or affected by the
+ transfer.
+
+4. Rights to Names
+
+ 1) Names and Trademarks
+
+ In case of a dispute between domain name registrants as to the
+ rights to a particular name, the registration authority shall have
+ no role or responsibility other than to provide the contact
+ information to both parties.
+
+ The registration of a domain name does not have any Trademark
+ status. It is up to the requestor to be sure he is not violating
+ anyone else's Trademark.
+
+ 2) Country Codes
+
+ The IANA is not in the business of deciding what is and what is
+ not a country.
+
+
+
+
+Postel [Page 6]
+
+RFC 1591 Domain Name System Structure and Delegation March 1994
+
+
+ The selection of the ISO 3166 list as a basis for country code
+ top-level domain names was made with the knowledge that ISO has a
+ procedure for determining which entities should be and should not
+ be on that list.
+
+5. Security Considerations
+
+ Security issues are not discussed in this memo.
+
+6. Acknowledgements
+
+ Many people have made comments on draft version of these descriptions
+ and procedures. Steve Goldstein and John Klensin have been
+ particularly helpful.
+
+7. Author's Address
+
+ Jon Postel
+ USC/Information Sciences Institute
+ 4676 Admiralty Way
+ Marina del Rey, CA 90292
+
+ Phone: 310-822-1511
+ Fax: 310-823-6714
+ EMail: Postel@ISI.EDU
+
+7. References
+
+ [1] Cooper, A., and J. Postel, "The US Domain", RFC 1480,
+ USC/Information Sciences Institute, June 1993.
+
+ [2] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC 1340,
+ USC/Information Sciences Institute, July 1992.
+
+ [3] Mockapetris, P., "Domain Names - Concepts and Facilities", STD
+ 13, RFC 1034, USC/Information Sciences Institute, November 1987.
+
+ [4] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, USC/Information Sciences
+ Institute, November 1987.
+
+ [6] Partridge, C., "Mail Routing and the Domain System", STD 14, RFC
+ 974, CSNET CIC BBN, January 1986.
+
+ [7] Braden, R., Editor, "Requirements for Internet Hosts --
+ Application and Support", STD 3, RFC 1123, Internet Engineering
+ Task Force, October 1989.
+
+
+
+
+Postel [Page 7]
+
diff --git a/doc/rfc/rfc1611.txt b/doc/rfc/rfc1611.txt
new file mode 100644
index 0000000..ed5b93a
--- /dev/null
+++ b/doc/rfc/rfc1611.txt
@@ -0,0 +1,1683 @@
+
+
+
+
+
+
+Network Working Group R. Austein
+Request for Comments: 1611 Epilogue Technology Corporation
+Category: Standards Track J. Saperia
+ Digital Equipment Corporation
+ May 1994
+
+ DNS Server MIB Extensions
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Table of Contents
+
+ 1. Introduction .............................................. 1
+ 2. The SNMPv2 Network Management Framework ................... 2
+ 2.1 Object Definitions ....................................... 2
+ 3. Overview .................................................. 2
+ 3.1 Resolvers ................................................ 3
+ 3.2 Name Servers ............................................. 3
+ 3.3 Selected Objects ......................................... 4
+ 3.4 Textual Conventions ...................................... 4
+ 4. Definitions ............................................... 5
+ 5. Acknowledgements .......................................... 28
+ 6. References ................................................ 28
+ 7. Security Considerations ................................... 29
+ 8. Authors' Addresses ........................................ 30
+
+1. Introduction
+
+ This memo defines a portion of the Management Information Base (MIB)
+ for use with network management protocols in the Internet community.
+ In particular, it describes a set of extensions which instrument DNS
+ name server functions. This memo was produced by the DNS working
+ group.
+
+ With the adoption of the Internet-standard Network Management
+ Framework [4,5,6,7], and with a large number of vendor
+ implementations of these standards in commercially available
+ products, it became possible to provide a higher level of effective
+ network management in TCP/IP-based internets than was previously
+ available. With the growth in the use of these standards, it has
+ become possible to consider the management of other elements of the
+ infrastructure beyond the basic TCP/IP protocols. A key element of
+
+
+
+Austein & Saperia [Page 1]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ the TCP/IP infrastructure is the DNS.
+
+ Up to this point there has been no mechanism to integrate the
+ management of the DNS with SNMP-based managers. This memo provides
+ the mechanisms by which IP-based management stations can effectively
+ manage DNS name server software in an integrated fashion.
+
+ We have defined DNS MIB objects to be used in conjunction with the
+ Internet MIB to allow access to and control of DNS name server
+ software via SNMP by the Internet community.
+
+2. The SNMPv2 Network Management Framework
+
+ The SNMPv2 Network Management Framework consists of four major
+ components. They are:
+
+ o RFC 1442 which defines the SMI, the mechanisms used for
+ describing and naming objects for the purpose of management.
+
+ o STD 17, RFC 1213 defines MIB-II, the core set of managed objects
+ for the Internet suite of protocols.
+
+ o RFC 1445 which defines the administrative and other architectural
+ aspects of the framework.
+
+ o RFC 1448 which defines the protocol used for network access to
+ managed objects.
+
+ The Framework permits new objects to be defined for the purpose of
+ experimentation and evaluation.
+
+2.1. Object Definitions
+
+ Managed objects are accessed via a virtual information store, termed
+ the Management Information Base or MIB. Objects in the MIB are
+ defined using the subset of Abstract Syntax Notation One (ASN.1)
+ defined in the SMI. In particular, each object object type is named
+ by an OBJECT IDENTIFIER, an administratively assigned name. The
+ object type together with an object instance serves to uniquely
+ identify a specific instantiation of the object. For human
+ convenience, we often use a textual string, termed the descriptor, to
+ refer to the object type.
+
+3. Overview
+
+ In theory, the DNS world is pretty simple. There are two kinds of
+ entities: resolvers and name servers. Resolvers ask questions. Name
+ servers answer them. The real world, however, is not so simple.
+
+
+
+Austein & Saperia [Page 2]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ Implementors have made widely differing choices about how to divide
+ DNS functions between resolvers and servers. They have also
+ constructed various sorts of exotic hybrids. The most difficult task
+ in defining this MIB was to accommodate this wide range of entities
+ without having to come up with a separate MIB for each.
+
+ We divided up the various DNS functions into two, non-overlapping
+ classes, called "resolver functions" and "name server functions." A
+ DNS entity that performs what we define as resolver functions
+ contains a resolver, and therefore must implement the MIB groups
+ required of all resolvers which are defined in a separate MIB Module.
+ A DNS entity which implements name server functions is considered to
+ be a name server, and must implement the MIB groups required for name
+ servers in this module. If the same piece of software performs both
+ resolver and server functions, we imagine that it contains both a
+ resolver and a server and would thus implement both the DNS Server
+ and DNS Resolver MIBs.
+
+3.1. Resolvers
+
+ In our model, a resolver is a program (or piece thereof) which
+ obtains resource records from servers. Normally it does so at the
+ behest of an application, but may also do so as part of its own
+ operation. A resolver sends DNS protocol queries and receives DNS
+ protocol replies. A resolver neither receives queries nor sends
+ replies. A full service resolver is one that knows how to resolve
+ queries: it obtains the needed resource records by contacting a
+ server authoritative for the records desired. A stub resolver does
+ not know how to resolve queries: it sends all queries to a local name
+ server, setting the "recursion desired" flag to indicate that it
+ hopes that the name server will be willing to resolve the query. A
+ resolver may (optionally) have a cache for remembering previously
+ acquired resource records. It may also have a negative cache for
+ remembering names or data that have been determined not to exist.
+
+3.2. Name Servers
+
+ A name server is a program (or piece thereof) that provides resource
+ records to resolvers. All references in this document to "a name
+ server" imply "the name server's role"; in some cases the name
+ server's role and the resolver's role might be combined into a single
+ program. A name server receives DNS protocol queries and sends DNS
+ protocol replies. A name server neither sends queries nor receives
+ replies. As a consequence, name servers do not have caches.
+ Normally, a name server would expect to receive only those queries to
+ which it could respond with authoritative information. However, if a
+ name server receives a query that it cannot respond to with purely
+ authoritative information, it may choose to try to obtain the
+
+
+
+Austein & Saperia [Page 3]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ necessary additional information from a resolver which may or may not
+ be a separate process.
+
+3.3. Selected Objects
+
+ Many of the objects included in this memo have been created from
+ information contained in the DNS specifications [1,2], as amended and
+ clarified by subsequent host requirements documents [3]. Other
+ objects have been created based on experience with existing DNS
+ management tools, expected operational needs, the statistics
+ generated by existing DNS implementations, and the configuration
+ files used by existing DNS implementations. These objects have been
+ ordered into groups as follows:
+
+ o Server Configuration Group
+
+ o Server Counter Group
+
+ o Server Optional Counter Group
+
+ o Server Zone Group
+
+ This information has been converted into a standard form using the
+ SNMPv2 SMI defined in [9]. For the most part, the descriptions are
+ influenced by the DNS related RFCs noted above. For example, the
+ descriptions for counters used for the various types of queries of
+ DNS records are influenced by the definitions used for the various
+ record types found in [2].
+
+3.4. Textual Conventions
+
+ Several conceptual data types have been introduced as a textual
+ conventions in this DNS MIB document. These additions will
+ facilitate the common understanding of information used by the DNS.
+ No changes to the SMI or the SNMP are necessary to support these
+ conventions.
+
+ Readers familiar with MIBs designed to manage entities in the lower
+ layers of the Internet protocol suite may be surprised at the number
+ of non-enumerated integers used in this MIB to represent values such
+ as DNS RR class and type numbers. The reason for this choice is
+ simple: the DNS itself is designed as an extensible protocol,
+ allowing new classes and types of resource records to be added to the
+ protocol without recoding the core DNS software. Using non-
+ enumerated integers to represent these data types in this MIB allows
+ the MIB to accommodate these changes as well.
+
+
+
+
+
+Austein & Saperia [Page 4]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+4. Definitions
+
+ DNS-SERVER-MIB DEFINITIONS ::= BEGIN
+
+ IMPORTS
+ mib-2
+ FROM RFC-1213
+ MODULE-IDENTITY, OBJECT-TYPE, OBJECT-IDENTITY,
+ IpAddress, Counter32, Gauge32
+ FROM SNMPv2-SMI
+ TEXTUAL-CONVENTION, RowStatus, DisplayString, TruthValue
+ FROM SNMPv2-TC
+ MODULE-COMPLIANCE, OBJECT-GROUP
+ FROM SNMPv2-CONF;
+
+ dns OBJECT-IDENTITY
+ STATUS current
+ DESCRIPTION
+ "The OID assigned to DNS MIB work by the IANA."
+ ::= { mib-2 32 }
+
+ dnsServMIB MODULE-IDENTITY
+ LAST-UPDATED "9401282251Z"
+ ORGANIZATION "IETF DNS Working Group"
+ CONTACT-INFO
+ " Rob Austein
+ Postal: Epilogue Technology Corporation
+ 268 Main Street, Suite 283
+ North Reading, MA 10864
+ US
+ Tel: +1 617 245 0804
+ Fax: +1 617 245 8122
+ E-Mail: sra@epilogue.com
+
+ Jon Saperia
+ Postal: Digital Equipment Corporation
+ 110 Spit Brook Road
+ ZKO1-3/H18
+ Nashua, NH 03062-2698
+ US
+ Tel: +1 603 881 0480
+ Fax: +1 603 881 0120
+ Email: saperia@zko.dec.com"
+ DESCRIPTION
+ "The MIB module for entities implementing the server side
+ of the Domain Name System (DNS) protocol."
+ ::= { dns 1 }
+
+
+
+
+Austein & Saperia [Page 5]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ dnsServMIBObjects OBJECT IDENTIFIER ::= { dnsServMIB 1 }
+
+ -- (Old-style) groups in the DNS server MIB.
+
+ dnsServConfig OBJECT IDENTIFIER ::= { dnsServMIBObjects 1 }
+ dnsServCounter OBJECT IDENTIFIER ::= { dnsServMIBObjects 2 }
+ dnsServOptCounter OBJECT IDENTIFIER ::= { dnsServMIBObjects 3 }
+ dnsServZone OBJECT IDENTIFIER ::= { dnsServMIBObjects 4 }
+
+
+ -- Textual conventions
+
+ DnsName ::= TEXTUAL-CONVENTION
+ -- A DISPLAY-HINT would be nice, but difficult to express.
+ STATUS current
+ DESCRIPTION
+ "A DNS name is a sequence of labels. When DNS names are
+ displayed, the boundaries between labels are typically
+ indicated by dots (e.g. `Acme' and `COM' are labels in
+ the name `Acme.COM'). In the DNS protocol, however, no
+ such separators are needed because each label is encoded
+ as a length octet followed by the indicated number of
+ octets of label. For example, `Acme.COM' is encoded as
+ the octet sequence { 4, 'A', 'c', 'm', 'e', 3, 'C', 'O',
+ 'M', 0 } (the final 0 is the length of the name of the
+ root domain, which appears implicitly at the end of any
+ DNS name). This MIB uses the same encoding as the DNS
+ protocol.
+
+ A DnsName must always be a fully qualified name. It is
+ an error to encode a relative domain name as a DnsName
+ without first making it a fully qualified name."
+ REFERENCE
+ "RFC-1034 section 3.1."
+ SYNTAX OCTET STRING (SIZE (0..255))
+
+ DnsNameAsIndex ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "This textual convention is like a DnsName, but is used
+ as an index componant in tables. Alphabetic characters
+ in names of this type are restricted to uppercase: the
+ characters 'a' through 'z' are mapped to the characters
+ 'A' through 'Z'. This restriction is intended to make
+ the lexical ordering imposed by SNMP useful when applied
+ to DNS names.
+
+ Note that it is theoretically possible for a valid DNS
+
+
+
+Austein & Saperia [Page 6]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ name to exceed the allowed length of an SNMP object
+ identifer, and thus be impossible to represent in tables
+ in this MIB that are indexed by DNS name. Sampling of
+ DNS names in current use on the Internet suggests that
+ this limit does not pose a serious problem in practice."
+ REFERENCE
+ "RFC-1034 section 3.1, RFC-1448 section 4.1."
+ SYNTAX DnsName
+
+ DnsClass ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "2d"
+ STATUS current
+ DESCRIPTION
+ "This data type is used to represent the class values
+ which appear in Resource Records in the DNS. A 16-bit
+ unsigned integer is used to allow room for new classes
+ of records to be defined. Existing standard classes are
+ listed in the DNS specifications."
+ REFERENCE
+ "RFC-1035 section 3.2.4."
+ SYNTAX INTEGER (0..65535)
+
+ DnsType ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "2d"
+ STATUS current
+ DESCRIPTION
+ "This data type is used to represent the type values
+ which appear in Resource Records in the DNS. A 16-bit
+ unsigned integer is used to allow room for new record
+ types to be defined. Existing standard types are listed
+ in the DNS specifications."
+ REFERENCE
+ "RFC-1035 section 3.2.2."
+ SYNTAX INTEGER (0..65535)
+
+ DnsQClass ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "2d"
+ STATUS current
+ DESCRIPTION
+ "This data type is used to represent the QClass values
+ which appear in Resource Records in the DNS. A 16-bit
+ unsigned integer is used to allow room for new QClass
+ records to be defined. Existing standard QClasses are
+ listed in the DNS specification."
+ REFERENCE
+ "RFC-1035 section 3.2.5."
+ SYNTAX INTEGER (0..65535)
+
+
+
+
+Austein & Saperia [Page 7]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ DnsQType ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "2d"
+ STATUS current
+ DESCRIPTION
+ "This data type is used to represent the QType values
+ which appear in Resource Records in the DNS. A 16-bit
+ unsigned integer is used to allow room for new QType
+ records to be defined. Existing standard QTypes are
+ listed in the DNS specification."
+ REFERENCE
+ "RFC-1035 section 3.2.3."
+ SYNTAX INTEGER (0..65535)
+
+ DnsTime ::= TEXTUAL-CONVENTION
+ DISPLAY-HINT "4d"
+ STATUS current
+ DESCRIPTION
+ "DnsTime values are 32-bit unsigned integers which
+ measure time in seconds."
+ REFERENCE
+ "RFC-1035."
+ SYNTAX Gauge32
+
+
+ DnsOpCode ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "This textual convention is used to represent the DNS
+ OPCODE values used in the header section of DNS
+ messages. Existing standard OPCODE values are listed in
+ the DNS specifications."
+ REFERENCE
+ "RFC-1035 section 4.1.1."
+ SYNTAX INTEGER (0..15)
+
+ DnsRespCode ::= TEXTUAL-CONVENTION
+ STATUS current
+ DESCRIPTION
+ "This data type is used to represent the DNS RCODE value
+ in DNS response messages. Existing standard RCODE
+ values are listed in the DNS specifications."
+ REFERENCE
+ "RFC-1035 section 4.1.1."
+ SYNTAX INTEGER (0..15)
+
+
+
+
+
+
+
+Austein & Saperia [Page 8]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ -- Server Configuration Group
+
+ dnsServConfigImplementIdent OBJECT-TYPE
+ SYNTAX DisplayString
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The implementation identification string for the DNS
+ server software in use on the system, for example;
+ `FNS-2.1'"
+ ::= { dnsServConfig 1 }
+
+ dnsServConfigRecurs OBJECT-TYPE
+ SYNTAX INTEGER { available(1),
+ restricted(2),
+ unavailable(3) }
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "This represents the recursion services offered by this
+ name server. The values that can be read or written
+ are:
+
+ available(1) - performs recursion on requests from
+ clients.
+
+ restricted(2) - recursion is performed on requests only
+ from certain clients, for example; clients on an access
+ control list.
+
+ unavailable(3) - recursion is not available."
+ ::= { dnsServConfig 2 }
+
+ dnsServConfigUpTime OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "If the server has a persistent state (e.g., a process),
+ this value will be the time elapsed since it started.
+ For software without persistant state, this value will
+ be zero."
+ ::= { dnsServConfig 3 }
+
+ dnsServConfigResetTime OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-only
+ STATUS current
+
+
+
+Austein & Saperia [Page 9]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ DESCRIPTION
+ "If the server has a persistent state (e.g., a process)
+ and supports a `reset' operation (e.g., can be told to
+ re-read configuration files), this value will be the
+ time elapsed since the last time the name server was
+ `reset.' For software that does not have persistence or
+ does not support a `reset' operation, this value will be
+ zero."
+ ::= { dnsServConfig 4 }
+
+ dnsServConfigReset OBJECT-TYPE
+ SYNTAX INTEGER { other(1),
+ reset(2),
+ initializing(3),
+ running(4) }
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Status/action object to reinitialize any persistant name
+ server state. When set to reset(2), any persistant
+ name server state (such as a process) is reinitialized as
+ if the name server had just been started. This value
+ will never be returned by a read operation. When read,
+ one of the following values will be returned:
+ other(1) - server in some unknown state;
+ initializing(3) - server (re)initializing;
+ running(4) - server currently running."
+ ::= { dnsServConfig 5 }
+
+
+ -- Server Counter Group
+
+ dnsServCounterAuthAns OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries which were authoritatively answered."
+ ::= { dnsServCounter 2 }
+
+ dnsServCounterAuthNoNames OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries for which `authoritative no such name'
+ responses were made."
+ ::= { dnsServCounter 3 }
+
+
+
+Austein & Saperia [Page 10]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ dnsServCounterAuthNoDataResps OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries for which `authoritative no such data'
+ (empty answer) responses were made."
+ ::= { dnsServCounter 4 }
+
+ dnsServCounterNonAuthDatas OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries which were non-authoritatively
+ answered (cached data)."
+ ::= { dnsServCounter 5 }
+
+ dnsServCounterNonAuthNoDatas OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries which were non-authoritatively
+ answered with no data (empty answer)."
+ ::= { dnsServCounter 6 }
+
+ dnsServCounterReferrals OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests that were referred to other servers."
+ ::= { dnsServCounter 7 }
+
+ dnsServCounterErrors OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests the server has processed that were
+ answered with errors (RCODE values other than 0 and 3)."
+ REFERENCE
+ "RFC-1035 section 4.1.1."
+ ::= { dnsServCounter 8 }
+
+ dnsServCounterRelNames OBJECT-TYPE
+ SYNTAX Counter32
+
+
+
+Austein & Saperia [Page 11]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests received by the server for names that
+ are only 1 label long (text form - no internal dots)."
+ ::= { dnsServCounter 9 }
+
+ dnsServCounterReqRefusals OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of DNS requests refused by the server."
+ ::= { dnsServCounter 10 }
+
+ dnsServCounterReqUnparses OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests received which were unparseable."
+ ::= { dnsServCounter 11 }
+
+ dnsServCounterOtherErrors OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests which were aborted for other (local)
+ server errors."
+ ::= { dnsServCounter 12 }
+
+ -- DNS Server Counter Table
+
+ dnsServCounterTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DnsServCounterEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Counter information broken down by DNS class and type."
+ ::= { dnsServCounter 13 }
+
+ dnsServCounterEntry OBJECT-TYPE
+ SYNTAX DnsServCounterEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "This table contains count information for each DNS class
+
+
+
+Austein & Saperia [Page 12]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ and type value known to the server. The index allows
+ management software to to create indices to the table to
+ get the specific information desired, e.g., number of
+ queries over UDP for records with type value `A' which
+ came to this server. In order to prevent an
+ uncontrolled expansion of rows in the table; if
+ dnsServCounterRequests is 0 and dnsServCounterResponses
+ is 0, then the row does not exist and `no such' is
+ returned when the agent is queried for such instances."
+ INDEX { dnsServCounterOpCode,
+ dnsServCounterQClass,
+ dnsServCounterQType,
+ dnsServCounterTransport }
+ ::= { dnsServCounterTable 1 }
+
+ DnsServCounterEntry ::=
+ SEQUENCE {
+ dnsServCounterOpCode
+ DnsOpCode,
+ dnsServCounterQClass
+ DnsClass,
+ dnsServCounterQType
+ DnsType,
+ dnsServCounterTransport
+ INTEGER,
+ dnsServCounterRequests
+ Counter32,
+ dnsServCounterResponses
+ Counter32
+ }
+
+ dnsServCounterOpCode OBJECT-TYPE
+ SYNTAX DnsOpCode
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The DNS OPCODE being counted in this row of the table."
+ ::= { dnsServCounterEntry 1 }
+
+ dnsServCounterQClass OBJECT-TYPE
+ SYNTAX DnsClass
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The class of record being counted in this row of the
+ table."
+ ::= { dnsServCounterEntry 2 }
+
+
+
+
+Austein & Saperia [Page 13]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ dnsServCounterQType OBJECT-TYPE
+ SYNTAX DnsType
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The type of record which is being counted in this row in
+ the table."
+ ::= { dnsServCounterEntry 3 }
+
+ dnsServCounterTransport OBJECT-TYPE
+ SYNTAX INTEGER { udp(1), tcp(2), other(3) }
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A value of udp(1) indicates that the queries reported on
+ this row were sent using UDP.
+
+ A value of tcp(2) indicates that the queries reported on
+ this row were sent using TCP.
+
+ A value of other(3) indicates that the queries reported
+ on this row were sent using a transport that was neither
+ TCP nor UDP."
+ ::= { dnsServCounterEntry 4 }
+
+ dnsServCounterRequests OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests (queries) that have been recorded in
+ this row of the table."
+ ::= { dnsServCounterEntry 5 }
+
+ dnsServCounterResponses OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of responses made by the server since
+ initialization for the kind of query identified on this
+ row of the table."
+ ::= { dnsServCounterEntry 6 }
+
+
+
+
+
+
+
+
+Austein & Saperia [Page 14]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ -- Server Optional Counter Group
+
+ -- The Server Optional Counter Group is intended for those systems
+ -- which make distinctions between the different sources of the DNS
+ -- queries as defined below.
+ --
+ -- Objects in this group are implemented on servers which distinguish
+ -- between queries which originate from the same host as the server,
+ -- queries from one of an arbitrary group of hosts that are on an
+ -- access list defined by the server, and queries from hosts that do
+ -- not fit either of these descriptions.
+ --
+ -- The objects found in the Server Counter group are totals. Thus if
+ -- one wanted to identify, for example, the number of queries from
+ -- `remote' hosts which have been given authoritative answers, one
+ -- would subtract the current values of ServOptCounterFriendsAuthAns
+ -- and ServOptCounterSelfAuthAns from servCounterAuthAns.
+ --
+ -- The purpose of these distinctions is to allow for implementations
+ -- to group queries and responses on this basis. One way in which
+ -- servers may make these distinctions is by looking at the source IP
+ -- address of the DNS query. If the source of the query is `your
+ -- own' then the query should be counted as `yourself' (local host).
+ -- If the source of the query matches an `access list,' the query
+ -- came from a friend. What constitutes an `access list' is
+ -- implementation dependent and could be as simple as a rule that all
+ -- hosts on the same IP network as the DNS server are classed
+ -- `friends.'
+ --
+ -- In order to avoid double counting, the following rules apply:
+ --
+ -- 1. No host is in more than one of the three groups defined above.
+ --
+ -- 2. All queries from the local host are always counted in the
+ -- `yourself' group regardless of what the access list, if any,
+ -- says.
+ --
+ -- 3. The access list should not define `your friends' in such a way
+ -- that it includes all hosts. That is, not everybody is your
+ -- `friend.'
+
+ dnsServOptCounterSelfAuthAns OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests the server has processed which
+ originated from a resolver on the same host for which
+
+
+
+Austein & Saperia [Page 15]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ there has been an authoritative answer."
+ ::= { dnsServOptCounter 1 }
+
+ dnsServOptCounterSelfAuthNoNames OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests the server has processed which
+ originated from a resolver on the same host for which
+ there has been an authoritative no such name answer
+ given."
+ ::= { dnsServOptCounter 2 }
+
+ dnsServOptCounterSelfAuthNoDataResps OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests the server has processed which
+ originated from a resolver on the same host for which
+ there has been an authoritative no such data answer
+ (empty answer) made."
+ ::= { dnsServOptCounter 3 }
+
+ dnsServOptCounterSelfNonAuthDatas OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests the server has processed which
+ originated from a resolver on the same host for which a
+ non-authoritative answer (cached data) was made."
+ ::= { dnsServOptCounter 4 }
+
+ dnsServOptCounterSelfNonAuthNoDatas OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests the server has processed which
+ originated from a resolver on the same host for which a
+ `non-authoritative, no such data' response was made
+ (empty answer)."
+ ::= { dnsServOptCounter 5 }
+
+ dnsServOptCounterSelfReferrals OBJECT-TYPE
+ SYNTAX Counter32
+
+
+
+Austein & Saperia [Page 16]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries the server has processed which
+ originated from a resolver on the same host and were
+ referred to other servers."
+ ::= { dnsServOptCounter 6 }
+
+ dnsServOptCounterSelfErrors OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests the server has processed which
+ originated from a resolver on the same host which have
+ been answered with errors (RCODEs other than 0 and 3)."
+ REFERENCE
+ "RFC-1035 section 4.1.1."
+ ::= { dnsServOptCounter 7 }
+
+ dnsServOptCounterSelfRelNames OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests received for names that are only 1
+ label long (text form - no internal dots) the server has
+ processed which originated from a resolver on the same
+ host."
+ ::= { dnsServOptCounter 8 }
+
+ dnsServOptCounterSelfReqRefusals OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of DNS requests refused by the server which
+ originated from a resolver on the same host."
+ ::= { dnsServOptCounter 9 }
+
+ dnsServOptCounterSelfReqUnparses OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests received which were unparseable and
+ which originated from a resolver on the same host."
+ ::= { dnsServOptCounter 10 }
+
+
+
+Austein & Saperia [Page 17]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ dnsServOptCounterSelfOtherErrors OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests which were aborted for other (local)
+ server errors and which originated on the same host."
+ ::= { dnsServOptCounter 11 }
+
+ dnsServOptCounterFriendsAuthAns OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries originating from friends which were
+ authoritatively answered. The definition of friends is
+ a locally defined matter."
+ ::= { dnsServOptCounter 12 }
+
+ dnsServOptCounterFriendsAuthNoNames OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries originating from friends, for which
+ authoritative `no such name' responses were made. The
+ definition of friends is a locally defined matter."
+ ::= { dnsServOptCounter 13 }
+
+ dnsServOptCounterFriendsAuthNoDataResps OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries originating from friends for which
+ authoritative no such data (empty answer) responses were
+ made. The definition of friends is a locally defined
+ matter."
+ ::= { dnsServOptCounter 14 }
+
+ dnsServOptCounterFriendsNonAuthDatas OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries originating from friends which were
+ non-authoritatively answered (cached data). The
+ definition of friends is a locally defined matter."
+
+
+
+Austein & Saperia [Page 18]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ ::= { dnsServOptCounter 15 }
+
+ dnsServOptCounterFriendsNonAuthNoDatas OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries originating from friends which were
+ non-authoritatively answered with no such data (empty
+ answer)."
+ ::= { dnsServOptCounter 16 }
+
+ dnsServOptCounterFriendsReferrals OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests which originated from friends that
+ were referred to other servers. The definition of
+ friends is a locally defined matter."
+ ::= { dnsServOptCounter 17 }
+
+ dnsServOptCounterFriendsErrors OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests the server has processed which
+ originated from friends and were answered with errors
+ (RCODE values other than 0 and 3). The definition of
+ friends is a locally defined matter."
+ REFERENCE
+ "RFC-1035 section 4.1.1."
+ ::= { dnsServOptCounter 18 }
+
+ dnsServOptCounterFriendsRelNames OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests received for names from friends that
+ are only 1 label long (text form - no internal dots) the
+ server has processed."
+ ::= { dnsServOptCounter 19 }
+
+ dnsServOptCounterFriendsReqRefusals OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+
+
+
+Austein & Saperia [Page 19]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ STATUS current
+ DESCRIPTION
+ "Number of DNS requests refused by the server which were
+ received from `friends'."
+ ::= { dnsServOptCounter 20 }
+
+ dnsServOptCounterFriendsReqUnparses OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests received which were unparseable and
+ which originated from `friends'."
+ ::= { dnsServOptCounter 21 }
+
+ dnsServOptCounterFriendsOtherErrors OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests which were aborted for other (local)
+ server errors and which originated from `friends'."
+ ::= { dnsServOptCounter 22 }
+
+
+ -- Server Zone Group
+
+ -- DNS Management Zone Configuration Table
+
+ -- This table contains zone configuration information.
+
+ dnsServZoneTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DnsServZoneEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Table of zones for which this name server provides
+ information. Each of the zones may be loaded from stable
+ storage via an implementation-specific mechanism or may
+ be obtained from another name server via a zone transfer.
+
+ If name server doesn't load any zones, this table is
+ empty."
+ ::= { dnsServZone 1 }
+
+ dnsServZoneEntry OBJECT-TYPE
+ SYNTAX DnsServZoneEntry
+ MAX-ACCESS not-accessible
+
+
+
+Austein & Saperia [Page 20]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ STATUS current
+ DESCRIPTION
+ "An entry in the name server zone table. New rows may be
+ added either via SNMP or by the name server itself."
+ INDEX { dnsServZoneName,
+ dnsServZoneClass }
+ ::= { dnsServZoneTable 1 }
+
+ DnsServZoneEntry ::=
+ SEQUENCE {
+ dnsServZoneName
+ DnsNameAsIndex,
+ dnsServZoneClass
+ DnsClass,
+ dnsServZoneLastReloadSuccess
+ DnsTime,
+ dnsServZoneLastReloadAttempt
+ DnsTime,
+ dnsServZoneLastSourceAttempt
+ IpAddress,
+ dnsServZoneStatus
+ RowStatus,
+ dnsServZoneSerial
+ Counter32,
+ dnsServZoneCurrent
+ TruthValue,
+ dnsServZoneLastSourceSuccess
+ IpAddress
+ }
+
+ dnsServZoneName OBJECT-TYPE
+ SYNTAX DnsNameAsIndex
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "DNS name of the zone described by this row of the table.
+ This is the owner name of the SOA RR that defines the
+ top of the zone. This is name is in uppercase:
+ characters 'a' through 'z' are mapped to 'A' through 'Z'
+ in order to make the lexical ordering useful."
+ ::= { dnsServZoneEntry 1 }
+
+ dnsServZoneClass OBJECT-TYPE
+ SYNTAX DnsClass
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "DNS class of the RRs in this zone."
+
+
+
+Austein & Saperia [Page 21]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ ::= { dnsServZoneEntry 2 }
+
+ dnsServZoneLastReloadSuccess OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Elapsed time in seconds since last successful reload of
+ this zone."
+ ::= { dnsServZoneEntry 3 }
+
+ dnsServZoneLastReloadAttempt OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Elapsed time in seconds since last attempted reload of
+ this zone."
+ ::= { dnsServZoneEntry 4 }
+
+ dnsServZoneLastSourceAttempt OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "IP address of host from which most recent zone transfer
+ of this zone was attempted. This value should match the
+ value of dnsServZoneSourceSuccess if the attempt was
+ succcessful. If zone transfer has not been attempted
+ within the memory of this name server, this value should
+ be 0.0.0.0."
+ ::= { dnsServZoneEntry 5 }
+
+ dnsServZoneStatus OBJECT-TYPE
+ SYNTAX RowStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The status of the information represented in this row of
+ the table."
+ ::= { dnsServZoneEntry 6 }
+
+ dnsServZoneSerial OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Zone serial number (from the SOA RR) of the zone
+
+
+
+Austein & Saperia [Page 22]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ represented by this row of the table. If the zone has
+ not been successfully loaded within the memory of this
+ name server, the value of this variable is zero."
+ ::= { dnsServZoneEntry 7 }
+
+ dnsServZoneCurrent OBJECT-TYPE
+ SYNTAX TruthValue
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Whether the server's copy of the zone represented by
+ this row of the table is currently valid. If the zone
+ has never been successfully loaded or has expired since
+ it was last succesfully loaded, this variable will have
+ the value false(2), otherwise this variable will have
+ the value true(1)."
+ ::= { dnsServZoneEntry 8 }
+
+ dnsServZoneLastSourceSuccess OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "IP address of host which was the source of the most
+ recent successful zone transfer for this zone. If
+ unknown (e.g., zone has never been successfully
+ transfered) or irrelevant (e.g., zone was loaded from
+ stable storage), this value should be 0.0.0.0."
+ ::= { dnsServZoneEntry 9 }
+
+ -- DNS Zone Source Table
+
+ dnsServZoneSrcTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DnsServZoneSrcEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "This table is a list of IP addresses from which the
+ server will attempt to load zone information using DNS
+ zone transfer operations. A reload may occur due to SNMP
+ operations that create a row in dnsServZoneTable or a
+ SET to object dnsServZoneReload. This table is only
+ used when the zone is loaded via zone transfer."
+ ::= { dnsServZone 2 }
+
+ dnsServZoneSrcEntry OBJECT-TYPE
+ SYNTAX DnsServZoneSrcEntry
+ MAX-ACCESS not-accessible
+
+
+
+Austein & Saperia [Page 23]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ STATUS current
+ DESCRIPTION
+ "An entry in the name server zone source table."
+ INDEX { dnsServZoneSrcName,
+ dnsServZoneSrcClass,
+ dnsServZoneSrcAddr }
+ ::= { dnsServZoneSrcTable 1 }
+
+ DnsServZoneSrcEntry ::=
+ SEQUENCE {
+ dnsServZoneSrcName
+ DnsNameAsIndex,
+ dnsServZoneSrcClass
+ DnsClass,
+ dnsServZoneSrcAddr
+ IpAddress,
+ dnsServZoneSrcStatus
+ RowStatus
+ }
+
+ dnsServZoneSrcName OBJECT-TYPE
+ SYNTAX DnsNameAsIndex
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "DNS name of the zone to which this entry applies."
+ ::= { dnsServZoneSrcEntry 1 }
+
+ dnsServZoneSrcClass OBJECT-TYPE
+ SYNTAX DnsClass
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "DNS class of zone to which this entry applies."
+ ::= { dnsServZoneSrcEntry 2 }
+
+ dnsServZoneSrcAddr OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "IP address of name server host from which this zone
+ might be obtainable."
+ ::= { dnsServZoneSrcEntry 3 }
+
+ dnsServZoneSrcStatus OBJECT-TYPE
+ SYNTAX RowStatus
+ MAX-ACCESS read-create
+
+
+
+Austein & Saperia [Page 24]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ STATUS current
+ DESCRIPTION
+ "The status of the information represented in this row of
+ the table."
+ ::= { dnsServZoneSrcEntry 4 }
+
+
+ -- SNMPv2 groups.
+
+ dnsServMIBGroups OBJECT IDENTIFIER ::= { dnsServMIB 2 }
+
+ dnsServConfigGroup OBJECT-GROUP
+ OBJECTS { dnsServConfigImplementIdent,
+ dnsServConfigRecurs,
+ dnsServConfigUpTime,
+ dnsServConfigResetTime,
+ dnsServConfigReset }
+ STATUS current
+ DESCRIPTION
+ "A collection of objects providing basic configuration
+ control of a DNS name server."
+ ::= { dnsServMIBGroups 1 }
+
+ dnsServCounterGroup OBJECT-GROUP
+ OBJECTS { dnsServCounterAuthAns,
+ dnsServCounterAuthNoNames,
+ dnsServCounterAuthNoDataResps,
+ dnsServCounterNonAuthDatas,
+ dnsServCounterNonAuthNoDatas,
+ dnsServCounterReferrals,
+ dnsServCounterErrors,
+ dnsServCounterRelNames,
+ dnsServCounterReqRefusals,
+ dnsServCounterReqUnparses,
+ dnsServCounterOtherErrors,
+ dnsServCounterOpCode,
+ dnsServCounterQClass,
+ dnsServCounterQType,
+ dnsServCounterTransport,
+ dnsServCounterRequests,
+ dnsServCounterResponses }
+ STATUS current
+ DESCRIPTION
+ "A collection of objects providing basic instrumentation
+ of a DNS name server."
+ ::= { dnsServMIBGroups 2 }
+
+
+
+
+
+Austein & Saperia [Page 25]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ dnsServOptCounterGroup OBJECT-GROUP
+ OBJECTS { dnsServOptCounterSelfAuthAns,
+ dnsServOptCounterSelfAuthNoNames,
+ dnsServOptCounterSelfAuthNoDataResps,
+ dnsServOptCounterSelfNonAuthDatas,
+ dnsServOptCounterSelfNonAuthNoDatas,
+ dnsServOptCounterSelfReferrals,
+ dnsServOptCounterSelfErrors,
+ dnsServOptCounterSelfRelNames,
+ dnsServOptCounterSelfReqRefusals,
+ dnsServOptCounterSelfReqUnparses,
+ dnsServOptCounterSelfOtherErrors,
+ dnsServOptCounterFriendsAuthAns,
+ dnsServOptCounterFriendsAuthNoNames,
+ dnsServOptCounterFriendsAuthNoDataResps,
+ dnsServOptCounterFriendsNonAuthDatas,
+ dnsServOptCounterFriendsNonAuthNoDatas,
+ dnsServOptCounterFriendsReferrals,
+ dnsServOptCounterFriendsErrors,
+ dnsServOptCounterFriendsRelNames,
+ dnsServOptCounterFriendsReqRefusals,
+ dnsServOptCounterFriendsReqUnparses,
+ dnsServOptCounterFriendsOtherErrors }
+ STATUS current
+ DESCRIPTION
+ "A collection of objects providing extended
+ instrumentation of a DNS name server."
+ ::= { dnsServMIBGroups 3 }
+
+ dnsServZoneGroup OBJECT-GROUP
+ OBJECTS { dnsServZoneName,
+ dnsServZoneClass,
+ dnsServZoneLastReloadSuccess,
+ dnsServZoneLastReloadAttempt,
+ dnsServZoneLastSourceAttempt,
+ dnsServZoneLastSourceSuccess,
+ dnsServZoneStatus,
+ dnsServZoneSerial,
+ dnsServZoneCurrent,
+ dnsServZoneSrcName,
+ dnsServZoneSrcClass,
+ dnsServZoneSrcAddr,
+ dnsServZoneSrcStatus }
+ STATUS current
+ DESCRIPTION
+ "A collection of objects providing configuration control
+ of a DNS name server which loads authoritative zones."
+ ::= { dnsServMIBGroups 4 }
+
+
+
+Austein & Saperia [Page 26]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ -- Compliances.
+
+ dnsServMIBCompliances OBJECT IDENTIFIER ::= { dnsServMIB 3 }
+
+ dnsServMIBCompliance MODULE-COMPLIANCE
+ STATUS current
+ DESCRIPTION
+ "The compliance statement for agents implementing the DNS
+ name server MIB extensions."
+ MODULE -- This MIB module
+ MANDATORY-GROUPS { dnsServConfigGroup, dnsServCounterGroup }
+ GROUP dnsServOptCounterGroup
+ DESCRIPTION
+ "The server optional counter group is unconditionally
+ optional."
+ GROUP dnsServZoneGroup
+ DESCRIPTION
+ "The server zone group is mandatory for any name server
+ that acts as an authoritative server for any DNS zone."
+ OBJECT dnsServConfigRecurs
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+ OBJECT dnsServConfigReset
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+ ::= { dnsServMIBCompliances 1 }
+
+ END
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein & Saperia [Page 27]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+5. Acknowledgements
+
+ This document is the result of work undertaken the by DNS working
+ group. The authors would particularly like to thank the following
+ people for their contributions to this document: Philip Almquist,
+ Frank Kastenholz (FTP Software), Joe Peck (DEC), Dave Perkins
+ (SynOptics), Win Treese (DEC), and Mimi Zohar (IBM).
+
+6. References
+
+ [1] Mockapetris, P., "Domain Names -- Concepts and Facilities", STD
+ 13, RFC 1034, USC/Information Sciences Institute, November 1987.
+
+ [2] Mockapetris, P., "Domain Names -- Implementation and
+ Specification", STD 13, RFC 1035, USC/Information Sciences
+ Institute, November 1987.
+
+ [3] Braden, R., Editor, "Requirements for Internet Hosts --
+ Application and Support, STD 3, RFC 1123, USC/Information
+ Sciences Institute, October 1989.
+
+ [4] Rose, M., and K. McCloghrie, "Structure and Identification of
+ Management Information for TCP/IP-based internets", STD 16, RFC
+ 1155, Performance Systems International, Hughes LAN Systems, May
+ 1990.
+
+ [5] McCloghrie, K., and M. Rose, "Management Information Base for
+ Network Management of TCP/IP-based internets", RFC 1156, Hughes
+ LAN Systems, Performance Systems International, May 1990.
+
+ [6] Case, J., Fedor, M., Schoffstall, M., and J. Davin, "Simple
+ Network Management Protocol", STD 15, RFC 1157, SNMP Research,
+ Performance Systems International, Performance Systems
+ International, MIT Laboratory for Computer Science, May 1990.
+
+ [7] Rose, M., and K. McCloghrie, Editors, "Concise MIB Definitions",
+ STD 16, RFC 1212, Performance Systems International, Hughes LAN
+ Systems, March 1991.
+
+ [8] McCloghrie, K., and M. Rose, Editors, "Management Information
+ Base for Network Management of TCP/IP-based internets: MIB-II",
+ STD 17, RFC 1213, Hughes LAN Systems, Performance Systems
+ International, March 1991.
+
+ [9] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Structure
+ of Management Information for version 2 of the Simple Network
+ Management Protocol (SNMPv2)", RFC 1442, SNMP Research, Inc.,
+ Hughes LAN Systems, Dover Beach Consulting, Inc., Carnegie Mellon
+
+
+
+Austein & Saperia [Page 28]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+ University, April 1993.
+
+ [10] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Textual
+ Conventions for version 2 of the the Simple Network Management
+ Protocol (SNMPv2)", RFC 1443, SNMP Research, Inc., Hughes LAN
+ Systems, Dover Beach Consulting, Inc., Carnegie Mellon
+ University, April 1993.
+
+ [11] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser,
+ "Conformance Statements for version 2 of the the Simple Network
+ Management Protocol (SNMPv2)", RFC 1444, SNMP Research, Inc.,
+ Hughes LAN Systems, Dover Beach Consulting, Inc., Carnegie Mellon
+ University, April 1993.
+
+ [12] Galvin, J., and K. McCloghrie, "Administrative Model for version
+ 2 of the Simple Network Management Protocol (SNMPv2)", RFC 1445,
+ Trusted Information Systems, Hughes LAN Systems, April 1993.
+
+ [13] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Protocol
+ Operations for version 2 of the Simple Network Management
+ Protocol (SNMPv2)", RFC 1448, SNMP Research, Inc., Hughes LAN
+ Systems, Dover Beach Consulting, Inc., Carnegie Mellon
+ University, April 1993.
+
+ [14] "Information processing systems - Open Systems Interconnection -
+ Specification of Abstract Syntax Notation One (ASN.1)",
+ International Organization for Standardization, International
+ Standard 8824, December 1987.
+
+7. Security Considerations
+
+ Security issues are not discussed in this memo.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein & Saperia [Page 29]
+
+RFC 1611 DNS Server MIB Extensions May 1994
+
+
+8. Authors' Addresses
+
+ Rob Austein
+ Epilogue Technology Corporation
+ 268 Main Street, Suite 283
+ North Reading, MA 01864
+ USA
+
+ Phone: +1-617-245-0804
+ Fax: +1-617-245-8122
+ EMail: sra@epilogue.com
+
+
+ Jon Saperia
+ Digital Equipment Corporation
+ 110 Spit Brook Road
+ ZKO1-3/H18
+ Nashua, NH 03062-2698
+ USA
+
+ Phone: +1-603-881-0480
+ Fax: +1-603-881-0120
+ EMail: saperia@zko.dec.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein & Saperia [Page 30]
+
diff --git a/doc/rfc/rfc1612.txt b/doc/rfc/rfc1612.txt
new file mode 100644
index 0000000..4ef23b0
--- /dev/null
+++ b/doc/rfc/rfc1612.txt
@@ -0,0 +1,1795 @@
+
+
+
+
+
+
+Network Working Group R. Austein
+Request for Comments: 1612 Epilogue Technology Corporation
+Category: Standards Track J. Saperia
+ Digital Equipment Corporation
+ May 1994
+
+
+ DNS Resolver MIB Extensions
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Table of Contents
+
+ 1. Introduction .............................................. 1
+ 2. The SNMPv2 Network Management Framework ................... 2
+ 2.1 Object Definitions ....................................... 2
+ 3. Overview .................................................. 2
+ 3.1 Resolvers ................................................ 3
+ 3.2 Name Servers ............................................. 3
+ 3.3 Selected Objects ......................................... 4
+ 3.4 Textual Conventions ...................................... 4
+ 4. Definitions ............................................... 5
+ 5. Acknowledgements .......................................... 30
+ 6. References ................................................ 30
+ 7. Security Considerations ................................... 32
+ 8. Authors' Addresses ........................................ 32
+
+1. Introduction
+
+ This memo defines a portion of the Management Information Base (MIB)
+ for use with network management protocols in the Internet community.
+ In particular, it describes a set of extensions which instrument DNS
+ resolver functions. This memo was produced by the DNS working group.
+
+ With the adoption of the Internet-standard Network Management
+ Framework [4,5,6,7], and with a large number of vendor
+ implementations of these standards in commercially available
+ products, it became possible to provide a higher level of effective
+ network management in TCP/IP-based internets than was previously
+ available. With the growth in the use of these standards, it has
+ become possible to consider the management of other elements of the
+ infrastructure beyond the basic TCP/IP protocols. A key element of
+
+
+
+Austein & Saperia [Page 1]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ the TCP/IP infrastructure is the DNS.
+
+ Up to this point there has been no mechanism to integrate the
+ management of the DNS with SNMP-based managers. This memo provides
+ the mechanisms by which IP-based management stations can effectively
+ manage DNS resolver software in an integrated fashion.
+
+ We have defined DNS MIB objects to be used in conjunction with the
+ Internet MIB to allow access to and control of DNS resolver software
+ via SNMP by the Internet community.
+
+2. The SNMPv2 Network Management Framework
+
+ The SNMPv2 Network Management Framework consists of four major
+ components. They are:
+
+ o RFC 1442 which defines the SMI, the mechanisms used for
+ describing and naming objects for the purpose of management.
+
+ o STD 17, RFC 1213 defines MIB-II, the core set of managed
+ objects for the Internet suite of protocols.
+
+ o RFC 1445 which defines the administrative and other
+ architectural aspects of the framework.
+
+ o RFC 1448 which defines the protocol used for network access to
+ managed objects.
+
+ The Framework permits new objects to be defined for the purpose of
+ experimentation and evaluation.
+
+2.1. Object Definitions
+
+ Managed objects are accessed via a virtual information store, termed
+ the Management Information Base or MIB. Objects in the MIB are
+ defined using the subset of Abstract Syntax Notation One (ASN.1)
+ defined in the SMI. In particular, each object object type is named
+ by an OBJECT IDENTIFIER, an administratively assigned name. The
+ object type together with an object instance serves to uniquely
+ identify a specific instantiation of the object. For human
+ convenience, we often use a textual string, termed the descriptor, to
+ refer to the object type.
+
+3. Overview
+
+ In theory, the DNS world is pretty simple. There are two kinds of
+ entities: resolvers and name servers. Resolvers ask questions. Name
+ servers answer them. The real world, however, is not so simple.
+
+
+
+Austein & Saperia [Page 2]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ Implementors have made widely differing choices about how to divide
+ DNS functions between resolvers and servers. They have also
+ constructed various sorts of exotic hybrids. The most difficult task
+ in defining this MIB was to accommodate this wide range of entities
+ without having to come up with a separate MIB for each.
+
+ We divided up the various DNS functions into two, non-overlapping
+ classes, called "resolver functions" and "name server functions." A
+ DNS entity that performs what we define as resolver functions
+ contains a resolver, and therefore must implement the MIB groups
+ required of all resolvers which are defined in this module. Some
+ resolvers also implement "optional" functions such as a cache, in
+ which case they must also implement the cache group contained in this
+ MIB. A DNS entity which implements name server functions is
+ considered to be a name server, and must implement the MIB groups
+ required for name servers which are defined in a separate module. If
+ the same piece of software performs both resolver and server
+ functions, we imagine that it contains both a resolver and a server
+ and would thus implement both the DNS Server and DNS Resolver MIBs.
+
+3.1. Resolvers
+
+ In our model, a resolver is a program (or piece thereof) which
+ obtains resource records from servers. Normally it does so at the
+ behest of an application, but may also do so as part of its own
+ operation. A resolver sends DNS protocol queries and receives DNS
+ protocol replies. A resolver neither receives queries nor sends
+ replies. A full service resolver is one that knows how to resolve
+ queries: it obtains the needed resource records by contacting a
+ server authoritative for the records desired. A stub resolver does
+ not know how to resolve queries: it sends all queries to a local name
+ server, setting the "recursion desired" flag to indicate that it
+ hopes that the name server will be willing to resolve the query. A
+ resolver may (optionally) have a cache for remembering previously
+ acquired resource records. It may also have a negative cache for
+ remembering names or data that have been determined not to exist.
+
+3.2. Name Servers
+
+ A name server is a program (or piece thereof) that provides resource
+ records to resolvers. All references in this document to "a name
+ server" imply "the name server's role"; in some cases the name
+ server's role and the resolver's role might be combined into a single
+ program. A name server receives DNS protocol queries and sends DNS
+ protocol replies. A name server neither sends queries nor receives
+ replies. As a consequence, name servers do not have caches.
+ Normally, a name server would expect to receive only those queries to
+ which it could respond with authoritative information. However, if a
+
+
+
+Austein & Saperia [Page 3]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ name server receives a query that it cannot respond to with purely
+ authoritative information, it may choose to try to obtain the
+ necessary additional information from a resolver which may or may not
+ be a separate process.
+
+3.3. Selected Objects
+
+ Many of the objects included in this memo have been created from
+ information contained in the DNS specifications [1,2], as amended and
+ clarified by subsequent host requirements documents [3]. Other
+ objects have been created based on experience with existing DNS
+ management tools, expected operational needs, the statistics
+ generated by existing DNS implementations, and the configuration
+ files used by existing DNS implementations. These objects have been
+ ordered into groups as follows:
+
+ o Resolver Configuration Group
+
+ o Resolver Counter Group
+
+ o Resolver Lame Delegation Group
+
+ o Resolver Cache Group
+
+ o Resolver Negative Cache Group
+
+ o Resolver Optional Counter Group
+
+ This information has been converted into a standard form using the
+ SNMPv2 SMI defined in [9]. For the most part, the descriptions are
+ influenced by the DNS related RFCs noted above. For example, the
+ descriptions for counters used for the various types of queries of
+ DNS records are influenced by the definitions used for the various
+ record types found in [2].
+
+3.4. Textual Conventions
+
+ Several conceptual data types have been introduced as a textual
+ conventions in the DNS Server MIB document and have been imported
+ into this MIB module. These additions will facilitate the common
+ understanding of information used by the DNS. No changes to the SMI
+ or the SNMP are necessary to support these conventions.
+
+ Readers familiar with MIBs designed to manage entities in the lower
+ layers of the Internet protocol suite may be surprised at the number
+ of non-enumerated integers used in this MIB to represent values such
+ as DNS RR class and type numbers. The reason for this choice is
+ simple: the DNS itself is designed as an extensible protocol,
+
+
+
+Austein & Saperia [Page 4]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ allowing new classes and types of resource records to be added to the
+ protocol without recoding the core DNS software. Using non-
+ enumerated integers to represent these data types in this MIB allows
+ the MIB to accommodate these changes as well.
+
+4. Definitions
+
+ DNS-RESOLVER-MIB DEFINITIONS ::= BEGIN
+
+ IMPORTS
+ MODULE-IDENTITY, OBJECT-TYPE, IpAddress, Counter32, Integer32
+ FROM SNMPv2-SMI
+ TEXTUAL-CONVENTION, RowStatus, DisplayString
+ FROM SNMPv2-TC
+ MODULE-COMPLIANCE, OBJECT-GROUP
+ FROM SNMPv2-CONF
+ dns, DnsName, DnsNameAsIndex, DnsClass, DnsType, DnsQClass,
+ DnsQType, DnsTime, DnsOpCode, DnsRespCode
+ FROM DNS-SERVER-MIB;
+
+ -- DNS Resolver MIB
+
+ dnsResMIB MODULE-IDENTITY
+ LAST-UPDATED "9401282250Z"
+ ORGANIZATION "IETF DNS Working Group"
+ CONTACT-INFO
+ " Rob Austein
+ Postal: Epilogue Technology Corporation
+ 268 Main Street, Suite 283
+ North Reading, MA 10864
+ US
+ Tel: +1 617 245 0804
+ Fax: +1 617 245 8122
+ E-Mail: sra@epilogue.com
+
+ Jon Saperia
+ Postal: Digital Equipment Corporation
+ 110 Spit Brook Road
+ ZKO1-3/H18
+ Nashua, NH 03062-2698
+ US
+ Tel: +1 603 881 0480
+ Fax: +1 603 881 0120
+ E-mail: saperia@zko.dec.com"
+ DESCRIPTION
+ "The MIB module for entities implementing the client
+ (resolver) side of the Domain Name System (DNS)
+ protocol."
+
+
+
+Austein & Saperia [Page 5]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ ::= { dns 2 }
+
+ dnsResMIBObjects OBJECT IDENTIFIER ::= { dnsResMIB 1 }
+
+ -- (Old-style) groups in the DNS resolver MIB.
+
+ dnsResConfig OBJECT IDENTIFIER ::= { dnsResMIBObjects 1 }
+ dnsResCounter OBJECT IDENTIFIER ::= { dnsResMIBObjects 2 }
+ dnsResLameDelegation OBJECT IDENTIFIER ::= { dnsResMIBObjects 3 }
+ dnsResCache OBJECT IDENTIFIER ::= { dnsResMIBObjects 4 }
+ dnsResNCache OBJECT IDENTIFIER ::= { dnsResMIBObjects 5 }
+ dnsResOptCounter OBJECT IDENTIFIER ::= { dnsResMIBObjects 6 }
+
+
+ -- Resolver Configuration Group
+
+ dnsResConfigImplementIdent OBJECT-TYPE
+ SYNTAX DisplayString
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The implementation identification string for the
+ resolver software in use on the system, for example;
+ `RES-2.1'"
+ ::= { dnsResConfig 1 }
+
+ dnsResConfigService OBJECT-TYPE
+ SYNTAX INTEGER { recursiveOnly(1),
+ iterativeOnly(2),
+ recursiveAndIterative(3) }
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Kind of DNS resolution service provided:
+
+ recursiveOnly(1) indicates a stub resolver.
+
+ iterativeOnly(2) indicates a normal full service
+ resolver.
+
+ recursiveAndIterative(3) indicates a full-service
+ resolver which performs a mix of recursive and iterative
+ queries."
+ ::= { dnsResConfig 2 }
+
+ dnsResConfigMaxCnames OBJECT-TYPE
+ SYNTAX INTEGER (0..2147483647)
+ MAX-ACCESS read-write
+
+
+
+Austein & Saperia [Page 6]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ STATUS current
+ DESCRIPTION
+ "Limit on how many CNAMEs the resolver should allow
+ before deciding that there's a CNAME loop. Zero means
+ that resolver has no explicit CNAME limit."
+ REFERENCE
+ "RFC-1035 section 7.1."
+ ::= { dnsResConfig 3 }
+
+ -- DNS Resolver Safety Belt Table
+
+ dnsResConfigSbeltTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DnsResConfigSbeltEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Table of safety belt information used by the resolver
+ when it hasn't got any better idea of where to send a
+ query, such as when the resolver is booting or is a stub
+ resolver."
+ ::= { dnsResConfig 4 }
+
+ dnsResConfigSbeltEntry OBJECT-TYPE
+ SYNTAX DnsResConfigSbeltEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "An entry in the resolver's Sbelt table.
+ Rows may be created or deleted at any time by the DNS
+ resolver and by SNMP SET requests. Whether the values
+ changed via SNMP are saved in stable storage across
+ `reset' operations is implementation-specific."
+ INDEX { dnsResConfigSbeltAddr,
+ dnsResConfigSbeltSubTree,
+ dnsResConfigSbeltClass }
+ ::= { dnsResConfigSbeltTable 1 }
+
+ DnsResConfigSbeltEntry ::=
+ SEQUENCE {
+ dnsResConfigSbeltAddr
+ IpAddress,
+ dnsResConfigSbeltName
+ DnsName,
+ dnsResConfigSbeltRecursion
+ INTEGER,
+ dnsResConfigSbeltPref
+ INTEGER,
+ dnsResConfigSbeltSubTree
+
+
+
+Austein & Saperia [Page 7]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ DnsNameAsIndex,
+ dnsResConfigSbeltClass
+ DnsClass,
+ dnsResConfigSbeltStatus
+ RowStatus
+ }
+
+ dnsResConfigSbeltAddr OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The IP address of the Sbelt name server identified by
+ this row of the table."
+ ::= { dnsResConfigSbeltEntry 1 }
+
+ dnsResConfigSbeltName OBJECT-TYPE
+ SYNTAX DnsName
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "The DNS name of a Sbelt nameserver identified by this
+ row of the table. A zero-length string indicates that
+ the name is not known by the resolver."
+ ::= { dnsResConfigSbeltEntry 2 }
+
+ dnsResConfigSbeltRecursion OBJECT-TYPE
+ SYNTAX INTEGER { iterative(1),
+ recursive(2),
+ recursiveAndIterative(3) }
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "Kind of queries resolver will be sending to the name
+ server identified in this row of the table:
+
+ iterative(1) indicates that resolver will be directing
+ iterative queries to this name server (RD bit turned
+ off).
+
+ recursive(2) indicates that resolver will be directing
+ recursive queries to this name server (RD bit turned
+ on).
+
+ recursiveAndIterative(3) indicates that the resolver
+ will be directing both recursive and iterative queries
+ to the server identified in this row of the table."
+ ::= { dnsResConfigSbeltEntry 3 }
+
+
+
+Austein & Saperia [Page 8]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ dnsResConfigSbeltPref OBJECT-TYPE
+ SYNTAX INTEGER (0..2147483647)
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "This value identifies the preference for the name server
+ identified in this row of the table. The lower the
+ value, the more desirable the resolver considers this
+ server."
+ ::= { dnsResConfigSbeltEntry 4 }
+
+ dnsResConfigSbeltSubTree OBJECT-TYPE
+ SYNTAX DnsNameAsIndex
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Queries sent to the name server identified by this row
+ of the table are limited to those for names in the name
+ subtree identified by this variable. If no such
+ limitation applies, the value of this variable is the
+ name of the root domain (a DNS name consisting of a
+ single zero octet)."
+ ::= { dnsResConfigSbeltEntry 5 }
+
+ dnsResConfigSbeltClass OBJECT-TYPE
+ SYNTAX DnsClass
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The class of DNS queries that will be sent to the server
+ identified by this row of the table."
+ ::= { dnsResConfigSbeltEntry 6 }
+
+ dnsResConfigSbeltStatus OBJECT-TYPE
+ SYNTAX RowStatus
+ MAX-ACCESS read-create
+ STATUS current
+ DESCRIPTION
+ "Row status column for this row of the Sbelt table."
+ ::= { dnsResConfigSbeltEntry 7 }
+
+ dnsResConfigUpTime OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "If the resolver has a persistent state (e.g., a
+ process), this value will be the time elapsed since it
+
+
+
+Austein & Saperia [Page 9]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ started. For software without persistant state, this
+ value will be 0."
+ ::= { dnsResConfig 5 }
+
+ dnsResConfigResetTime OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "If the resolver has a persistent state (e.g., a process)
+ and supports a `reset' operation (e.g., can be told to
+ re-read configuration files), this value will be the
+ time elapsed since the last time the resolver was
+ `reset.' For software that does not have persistence or
+ does not support a `reset' operation, this value will be
+ zero."
+ ::= { dnsResConfig 6 }
+
+ dnsResConfigReset OBJECT-TYPE
+ SYNTAX INTEGER { other(1),
+ reset(2),
+ initializing(3),
+ running(4) }
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Status/action object to reinitialize any persistant
+ resolver state. When set to reset(2), any persistant
+ resolver state (such as a process) is reinitialized as if
+ the resolver had just been started. This value will
+ never be returned by a read operation. When read, one of
+ the following values will be returned:
+ other(1) - resolver in some unknown state;
+ initializing(3) - resolver (re)initializing;
+ running(4) - resolver currently running."
+ ::= { dnsResConfig 7 }
+
+
+ -- Resolver Counters Group
+
+ -- Resolver Counter Table
+
+ dnsResCounterByOpcodeTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DnsResCounterByOpcodeEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Table of the current count of resolver queries and
+
+
+
+Austein & Saperia [Page 10]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ answers."
+ ::= { dnsResCounter 3 }
+
+ dnsResCounterByOpcodeEntry OBJECT-TYPE
+ SYNTAX DnsResCounterByOpcodeEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Entry in the resolver counter table. Entries are
+ indexed by DNS OpCode."
+ INDEX { dnsResCounterByOpcodeCode }
+ ::= { dnsResCounterByOpcodeTable 1 }
+
+ DnsResCounterByOpcodeEntry ::=
+ SEQUENCE {
+ dnsResCounterByOpcodeCode
+ DnsOpCode,
+ dnsResCounterByOpcodeQueries
+ Counter32,
+ dnsResCounterByOpcodeResponses
+ Counter32
+ }
+
+ dnsResCounterByOpcodeCode OBJECT-TYPE
+ SYNTAX DnsOpCode
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The index to this table. The OpCodes that have already
+ been defined are found in RFC-1035."
+ REFERENCE
+ "RFC-1035 section 4.1.1."
+ ::= { dnsResCounterByOpcodeEntry 1 }
+
+ dnsResCounterByOpcodeQueries OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Total number of queries that have sent out by the
+ resolver since initialization for the OpCode which is
+ the index to this row of the table."
+ ::= { dnsResCounterByOpcodeEntry 2 }
+
+ dnsResCounterByOpcodeResponses OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+
+
+
+Austein & Saperia [Page 11]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ DESCRIPTION
+ "Total number of responses that have been received by the
+ resolver since initialization for the OpCode which is
+ the index to this row of the table."
+ ::= { dnsResCounterByOpcodeEntry 3 }
+
+ -- Resolver Response Code Counter Table
+
+ dnsResCounterByRcodeTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DnsResCounterByRcodeEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Table of the current count of responses to resolver
+ queries."
+ ::= { dnsResCounter 4 }
+
+ dnsResCounterByRcodeEntry OBJECT-TYPE
+ SYNTAX DnsResCounterByRcodeEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Entry in the resolver response table. Entries are
+ indexed by DNS response code."
+ INDEX { dnsResCounterByRcodeCode }
+ ::= { dnsResCounterByRcodeTable 1 }
+
+ DnsResCounterByRcodeEntry ::=
+ SEQUENCE {
+ dnsResCounterByRcodeCode
+ DnsRespCode,
+ dnsResCounterByRcodeResponses
+ Counter32
+ }
+
+ dnsResCounterByRcodeCode OBJECT-TYPE
+ SYNTAX DnsRespCode
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "The index to this table. The Response Codes that have
+ already been defined are found in RFC-1035."
+ REFERENCE
+ "RFC-1035 section 4.1.1."
+ ::= { dnsResCounterByRcodeEntry 1 }
+
+
+
+
+
+
+Austein & Saperia [Page 12]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ dnsResCounterByRcodeResponses OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of responses the resolver has received for the
+ response code value which identifies this row of the
+ table."
+ ::= { dnsResCounterByRcodeEntry 2 }
+
+ -- Additional DNS Resolver Counter Objects
+
+ dnsResCounterNonAuthDataResps OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests made by the resolver for which a
+ non-authoritative answer (cached data) was received."
+ ::= { dnsResCounter 5 }
+
+ dnsResCounterNonAuthNoDataResps OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests made by the resolver for which a
+ non-authoritative answer - no such data response (empty
+ answer) was received."
+ ::= { dnsResCounter 6 }
+
+ dnsResCounterMartians OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of responses received which were received from
+ servers that the resolver does not think it asked."
+ ::= { dnsResCounter 7 }
+
+ dnsResCounterRecdResponses OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of responses received to all queries."
+ ::= { dnsResCounter 8 }
+
+
+
+
+Austein & Saperia [Page 13]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ dnsResCounterUnparseResps OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of responses received which were unparseable."
+ ::= { dnsResCounter 9 }
+
+ dnsResCounterFallbacks OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of times the resolver had to fall back to its
+ seat belt information."
+ ::= { dnsResCounter 10 }
+
+
+ -- Lame Delegation Group
+
+ dnsResLameDelegationOverflows OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of times the resolver attempted to add an entry
+ to the Lame Delegation table but was unable to for some
+ reason such as space constraints."
+ ::= { dnsResLameDelegation 1 }
+
+ -- Lame Delegation Table
+
+ dnsResLameDelegationTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DnsResLameDelegationEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Table of name servers returning lame delegations.
+
+ A lame delegation has occured when a parent zone
+ delegates authority for a child zone to a server that
+ appears not to think that it is authoritative for the
+ child zone in question."
+ ::= { dnsResLameDelegation 2 }
+
+ dnsResLameDelegationEntry OBJECT-TYPE
+ SYNTAX DnsResLameDelegationEntry
+ MAX-ACCESS not-accessible
+
+
+
+Austein & Saperia [Page 14]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ STATUS current
+ DESCRIPTION
+ "Entry in lame delegation table. Only the resolver may
+ create rows in this table. SNMP SET requests may be used
+ to delete rows."
+ INDEX { dnsResLameDelegationSource,
+ dnsResLameDelegationName,
+ dnsResLameDelegationClass }
+ ::= { dnsResLameDelegationTable 1 }
+
+ DnsResLameDelegationEntry ::=
+ SEQUENCE {
+ dnsResLameDelegationSource
+ IpAddress,
+ dnsResLameDelegationName
+ DnsNameAsIndex,
+ dnsResLameDelegationClass
+ DnsClass,
+ dnsResLameDelegationCounts
+ Counter32,
+ dnsResLameDelegationStatus
+ RowStatus
+ }
+
+ dnsResLameDelegationSource OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Source of lame delegation."
+ ::= { dnsResLameDelegationEntry 1 }
+
+ dnsResLameDelegationName OBJECT-TYPE
+ SYNTAX DnsNameAsIndex
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "DNS name for which lame delegation was received."
+ ::= { dnsResLameDelegationEntry 2 }
+
+ dnsResLameDelegationClass OBJECT-TYPE
+ SYNTAX DnsClass
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "DNS class of received lame delegation."
+ ::= { dnsResLameDelegationEntry 3 }
+
+
+
+
+Austein & Saperia [Page 15]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ dnsResLameDelegationCounts OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "How many times this lame delegation has been received."
+ ::= { dnsResLameDelegationEntry 4 }
+
+ dnsResLameDelegationStatus OBJECT-TYPE
+ SYNTAX RowStatus
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Status column for the lame delegation table. Since only
+ the agent (DNS resolver) creates rows in this table, the
+ only values that a manager may write to this variable
+ are active(1) and destroy(6)."
+ ::= { dnsResLameDelegationEntry 5 }
+
+
+ -- Resolver Cache Group
+
+ dnsResCacheStatus OBJECT-TYPE
+ SYNTAX INTEGER { enabled(1), disabled(2), clear(3) }
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Status/action for the resolver's cache.
+
+ enabled(1) means that the use of the cache is allowed.
+ Query operations can return this state.
+
+ disabled(2) means that the cache is not being used.
+ Query operations can return this state.
+
+ Setting this variable to clear(3) deletes the entire
+ contents of the resolver's cache, but does not otherwise
+ change the resolver's state. The status will retain its
+ previous value from before the clear operation (i.e.,
+ enabled(1) or disabled(2)). The value of clear(3) can
+ NOT be returned by a query operation."
+ ::= { dnsResCache 1 }
+
+ dnsResCacheMaxTTL OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+
+
+
+Austein & Saperia [Page 16]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ "Maximum Time-To-Live for RRs in this cache. If the
+ resolver does not implement a TTL ceiling, the value of
+ this field should be zero."
+ ::= { dnsResCache 2 }
+
+ dnsResCacheGoodCaches OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of RRs the resolver has cached successfully."
+ ::= { dnsResCache 3 }
+
+ dnsResCacheBadCaches OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of RRs the resolver has refused to cache because
+ they appear to be dangerous or irrelevant. E.g., RRs
+ with suspiciously high TTLs, unsolicited root
+ information, or that just don't appear to be relevant to
+ the question the resolver asked."
+ ::= { dnsResCache 4 }
+
+ -- Resolver Cache Table
+
+ dnsResCacheRRTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DnsResCacheRREntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "This table contains information about all the resource
+ records currently in the resolver's cache."
+ ::= { dnsResCache 5 }
+
+ dnsResCacheRREntry OBJECT-TYPE
+ SYNTAX DnsResCacheRREntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "An entry in the resolvers's cache. Rows may be created
+ only by the resolver. SNMP SET requests may be used to
+ delete rows."
+ INDEX { dnsResCacheRRName,
+ dnsResCacheRRClass,
+ dnsResCacheRRType,
+ dnsResCacheRRIndex }
+
+
+
+Austein & Saperia [Page 17]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ ::= { dnsResCacheRRTable 1 }
+
+ DnsResCacheRREntry ::=
+ SEQUENCE {
+ dnsResCacheRRName
+ DnsNameAsIndex,
+ dnsResCacheRRClass
+ DnsClass,
+ dnsResCacheRRType
+ DnsType,
+ dnsResCacheRRTTL
+ DnsTime,
+ dnsResCacheRRElapsedTTL
+ DnsTime,
+ dnsResCacheRRSource
+ IpAddress,
+ dnsResCacheRRData
+ OCTET STRING,
+ dnsResCacheRRStatus
+ RowStatus,
+ dnsResCacheRRIndex
+ Integer32,
+ dnsResCacheRRPrettyName
+ DnsName
+ }
+
+ dnsResCacheRRName OBJECT-TYPE
+ SYNTAX DnsNameAsIndex
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "Owner name of the Resource Record in the cache which is
+ identified in this row of the table. As described in
+ RFC-1034, the owner of the record is the domain name
+ were the RR is found."
+ REFERENCE
+ "RFC-1034 section 3.6."
+ ::= { dnsResCacheRREntry 1 }
+
+ dnsResCacheRRClass OBJECT-TYPE
+ SYNTAX DnsClass
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "DNS class of the Resource Record in the cache which is
+ identified in this row of the table."
+ ::= { dnsResCacheRREntry 2 }
+
+
+
+
+Austein & Saperia [Page 18]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ dnsResCacheRRType OBJECT-TYPE
+ SYNTAX DnsType
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "DNS type of the Resource Record in the cache which is
+ identified in this row of the table."
+ ::= { dnsResCacheRREntry 3 }
+
+ dnsResCacheRRTTL OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Time-To-Live of RR in DNS cache. This is the initial
+ TTL value which was received with the RR when it was
+ originally received."
+ ::= { dnsResCacheRREntry 4 }
+
+ dnsResCacheRRElapsedTTL OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Elapsed seconds since RR was received."
+ ::= { dnsResCacheRREntry 5 }
+
+ dnsResCacheRRSource OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Host from which RR was received, 0.0.0.0 if unknown."
+ ::= { dnsResCacheRREntry 6 }
+
+ dnsResCacheRRData OBJECT-TYPE
+ SYNTAX OCTET STRING
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "RDATA portion of a cached RR. The value is in the
+ format defined for the particular DNS class and type of
+ the resource record."
+ REFERENCE
+ "RFC-1035 section 3.2.1."
+ ::= { dnsResCacheRREntry 7 }
+
+
+
+
+
+Austein & Saperia [Page 19]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ dnsResCacheRRStatus OBJECT-TYPE
+ SYNTAX RowStatus
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Status column for the resolver cache table. Since only
+ the agent (DNS resolver) creates rows in this table, the
+ only values that a manager may write to this variable
+ are active(1) and destroy(6)."
+ ::= { dnsResCacheRREntry 8 }
+
+ dnsResCacheRRIndex OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "A value which makes entries in the table unique when the
+ other index values (dnsResCacheRRName,
+ dnsResCacheRRClass, and dnsResCacheRRType) do not
+ provide a unique index."
+ ::= { dnsResCacheRREntry 9 }
+
+ dnsResCacheRRPrettyName OBJECT-TYPE
+ SYNTAX DnsName
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Name of the RR at this row in the table. This is
+ identical to the dnsResCacheRRName variable, except that
+ character case is preserved in this variable, per DNS
+ conventions."
+ REFERENCE
+ "RFC-1035 section 2.3.3."
+ ::= { dnsResCacheRREntry 10 }
+
+ -- Resolver Negative Cache Group
+
+ dnsResNCacheStatus OBJECT-TYPE
+ SYNTAX INTEGER { enabled(1), disabled(2), clear(3) }
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Status/action for the resolver's negative response
+ cache.
+
+ enabled(1) means that the use of the negative response
+ cache is allowed. Query operations can return this
+ state.
+
+
+
+Austein & Saperia [Page 20]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ disabled(2) means that the negative response cache is
+ not being used. Query operations can return this state.
+
+ Setting this variable to clear(3) deletes the entire
+ contents of the resolver's negative response cache. The
+ status will retain its previous value from before the
+ clear operation (i.e., enabled(1) or disabled(2)). The
+ value of clear(3) can NOT be returned by a query
+ operation."
+ ::= { dnsResNCache 1 }
+
+ dnsResNCacheMaxTTL OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Maximum Time-To-Live for cached authoritative errors.
+ If the resolver does not implement a TTL ceiling, the
+ value of this field should be zero."
+ ::= { dnsResNCache 2 }
+
+ dnsResNCacheGoodNCaches OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of authoritative errors the resolver has cached
+ successfully."
+ ::= { dnsResNCache 3 }
+
+ dnsResNCacheBadNCaches OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of authoritative errors the resolver would have
+ liked to cache but was unable to because the appropriate
+ SOA RR was not supplied or looked suspicious."
+ REFERENCE
+ "RFC-1034 section 4.3.4."
+ ::= { dnsResNCache 4 }
+
+ -- Resolver Negative Cache Table
+
+ dnsResNCacheErrTable OBJECT-TYPE
+ SYNTAX SEQUENCE OF DnsResNCacheErrEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+
+
+
+Austein & Saperia [Page 21]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ DESCRIPTION
+ "The resolver's negative response cache. This table
+ contains information about authoritative errors that
+ have been cached by the resolver."
+ ::= { dnsResNCache 5 }
+
+ dnsResNCacheErrEntry OBJECT-TYPE
+ SYNTAX DnsResNCacheErrEntry
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "An entry in the resolver's negative response cache
+ table. Only the resolver can create rows. SNMP SET
+ requests may be used to delete rows."
+ INDEX { dnsResNCacheErrQName,
+ dnsResNCacheErrQClass,
+ dnsResNCacheErrQType,
+ dnsResNCacheErrIndex }
+ ::= { dnsResNCacheErrTable 1 }
+
+ DnsResNCacheErrEntry ::=
+ SEQUENCE {
+ dnsResNCacheErrQName
+ DnsNameAsIndex,
+ dnsResNCacheErrQClass
+ DnsQClass,
+ dnsResNCacheErrQType
+ DnsQType,
+ dnsResNCacheErrTTL
+ DnsTime,
+ dnsResNCacheErrElapsedTTL
+ DnsTime,
+ dnsResNCacheErrSource
+ IpAddress,
+ dnsResNCacheErrCode
+ INTEGER,
+ dnsResNCacheErrStatus
+ RowStatus,
+ dnsResNCacheErrIndex
+ Integer32,
+ dnsResNCacheErrPrettyName
+ DnsName
+ }
+
+ dnsResNCacheErrQName OBJECT-TYPE
+ SYNTAX DnsNameAsIndex
+ MAX-ACCESS not-accessible
+ STATUS current
+
+
+
+Austein & Saperia [Page 22]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ DESCRIPTION
+ "QNAME associated with a cached authoritative error."
+ REFERENCE
+ "RFC-1034 section 3.7.1."
+ ::= { dnsResNCacheErrEntry 1 }
+
+ dnsResNCacheErrQClass OBJECT-TYPE
+ SYNTAX DnsQClass
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "DNS QCLASS associated with a cached authoritative
+ error."
+ ::= { dnsResNCacheErrEntry 2 }
+
+ dnsResNCacheErrQType OBJECT-TYPE
+ SYNTAX DnsQType
+ MAX-ACCESS not-accessible
+ STATUS current
+ DESCRIPTION
+ "DNS QTYPE associated with a cached authoritative error."
+ ::= { dnsResNCacheErrEntry 3 }
+
+ dnsResNCacheErrTTL OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Time-To-Live of a cached authoritative error at the time
+ of the error, it should not be decremented by the number
+ of seconds since it was received. This should be the
+ TTL as copied from the MINIMUM field of the SOA that
+ accompanied the authoritative error, or a smaller value
+ if the resolver implements a ceiling on negative
+ response cache TTLs."
+ REFERENCE
+ "RFC-1034 section 4.3.4."
+ ::= { dnsResNCacheErrEntry 4 }
+
+ dnsResNCacheErrElapsedTTL OBJECT-TYPE
+ SYNTAX DnsTime
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Elapsed seconds since authoritative error was received."
+ ::= { dnsResNCacheErrEntry 5 }
+
+
+
+
+
+Austein & Saperia [Page 23]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ dnsResNCacheErrSource OBJECT-TYPE
+ SYNTAX IpAddress
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Host which sent the authoritative error, 0.0.0.0 if
+ unknown."
+ ::= { dnsResNCacheErrEntry 6 }
+
+ dnsResNCacheErrCode OBJECT-TYPE
+ SYNTAX INTEGER { nonexistantName(1), noData(2), other(3) }
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "The authoritative error that has been cached:
+
+ nonexistantName(1) indicates an authoritative name error
+ (RCODE = 3).
+
+ noData(2) indicates an authoritative response with no
+ error (RCODE = 0) and no relevant data.
+
+ other(3) indicates some other cached authoritative
+ error. At present, no such errors are known to exist."
+ ::= { dnsResNCacheErrEntry 7 }
+
+ dnsResNCacheErrStatus OBJECT-TYPE
+ SYNTAX RowStatus
+ MAX-ACCESS read-write
+ STATUS current
+ DESCRIPTION
+ "Status column for the resolver negative response cache
+ table. Since only the agent (DNS resolver) creates rows
+ in this table, the only values that a manager may write
+ to this variable are active(1) and destroy(6)."
+ ::= { dnsResNCacheErrEntry 8 }
+
+ dnsResNCacheErrIndex OBJECT-TYPE
+ SYNTAX Integer32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "A value which makes entries in the table unique when the
+ other index values (dnsResNCacheErrQName,
+ dnsResNCacheErrQClass, and dnsResNCacheErrQType) do not
+ provide a unique index."
+ ::= { dnsResNCacheErrEntry 9 }
+
+
+
+
+Austein & Saperia [Page 24]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ dnsResNCacheErrPrettyName OBJECT-TYPE
+ SYNTAX DnsName
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "QNAME associated with this row in the table. This is
+ identical to the dnsResNCacheErrQName variable, except
+ that character case is preserved in this variable, per
+ DNS conventions."
+ REFERENCE
+ "RFC-1035 section 2.3.3."
+ ::= { dnsResNCacheErrEntry 10 }
+
+
+ -- Resolver Optional Counters Group
+
+ dnsResOptCounterReferals OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of responses which were received from servers
+ redirecting query to another server."
+ ::= { dnsResOptCounter 1 }
+
+ dnsResOptCounterRetrans OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number requests retransmitted for all reasons."
+ ::= { dnsResOptCounter 2 }
+
+ dnsResOptCounterNoResponses OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries that were retransmitted because of no
+ response."
+ ::= { dnsResOptCounter 3 }
+
+ dnsResOptCounterRootRetrans OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of queries that were retransmitted that were to
+
+
+
+Austein & Saperia [Page 25]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ root servers."
+ ::= { dnsResOptCounter 4 }
+
+ dnsResOptCounterInternals OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests internally generated by the
+ resolver."
+ ::= { dnsResOptCounter 5 }
+
+ dnsResOptCounterInternalTimeOuts OBJECT-TYPE
+ SYNTAX Counter32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of requests internally generated which timed
+ out."
+ ::= { dnsResOptCounter 6 }
+
+
+ -- SNMPv2 groups.
+
+ dnsResMIBGroups OBJECT IDENTIFIER ::= { dnsResMIB 2 }
+
+ dnsResConfigGroup OBJECT-GROUP
+ OBJECTS { dnsResConfigImplementIdent,
+ dnsResConfigService,
+ dnsResConfigMaxCnames,
+ dnsResConfigSbeltAddr,
+ dnsResConfigSbeltName,
+ dnsResConfigSbeltRecursion,
+ dnsResConfigSbeltPref,
+ dnsResConfigSbeltSubTree,
+ dnsResConfigSbeltClass,
+ dnsResConfigSbeltStatus,
+ dnsResConfigUpTime,
+ dnsResConfigResetTime }
+ STATUS current
+ DESCRIPTION
+ "A collection of objects providing basic configuration
+ information for a DNS resolver implementation."
+ ::= { dnsResMIBGroups 1 }
+
+ dnsResCounterGroup OBJECT-GROUP
+ OBJECTS { dnsResCounterByOpcodeCode,
+ dnsResCounterByOpcodeQueries,
+
+
+
+Austein & Saperia [Page 26]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ dnsResCounterByOpcodeResponses,
+ dnsResCounterByRcodeCode,
+ dnsResCounterByRcodeResponses,
+ dnsResCounterNonAuthDataResps,
+ dnsResCounterNonAuthNoDataResps,
+ dnsResCounterMartians,
+ dnsResCounterRecdResponses,
+ dnsResCounterUnparseResps,
+ dnsResCounterFallbacks }
+ STATUS current
+ DESCRIPTION
+ "A collection of objects providing basic instrumentation
+ of a DNS resolver implementation."
+ ::= { dnsResMIBGroups 2 }
+
+ dnsResLameDelegationGroup OBJECT-GROUP
+ OBJECTS { dnsResLameDelegationOverflows,
+ dnsResLameDelegationSource,
+ dnsResLameDelegationName,
+ dnsResLameDelegationClass,
+ dnsResLameDelegationCounts,
+ dnsResLameDelegationStatus }
+ STATUS current
+ DESCRIPTION
+ "A collection of objects providing instrumentation of
+ `lame delegation' failures."
+ ::= { dnsResMIBGroups 3 }
+
+
+ dnsResCacheGroup OBJECT-GROUP
+ OBJECTS { dnsResCacheStatus,
+ dnsResCacheMaxTTL,
+ dnsResCacheGoodCaches,
+ dnsResCacheBadCaches,
+ dnsResCacheRRName,
+ dnsResCacheRRClass,
+ dnsResCacheRRType,
+ dnsResCacheRRTTL,
+ dnsResCacheRRElapsedTTL,
+ dnsResCacheRRSource,
+ dnsResCacheRRData,
+ dnsResCacheRRStatus,
+ dnsResCacheRRIndex,
+ dnsResCacheRRPrettyName }
+ STATUS current
+ DESCRIPTION
+ "A collection of objects providing access to and control
+ of a DNS resolver's cache."
+
+
+
+Austein & Saperia [Page 27]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ ::= { dnsResMIBGroups 4 }
+
+ dnsResNCacheGroup OBJECT-GROUP
+ OBJECTS { dnsResNCacheStatus,
+ dnsResNCacheMaxTTL,
+ dnsResNCacheGoodNCaches,
+ dnsResNCacheBadNCaches,
+ dnsResNCacheErrQName,
+ dnsResNCacheErrQClass,
+ dnsResNCacheErrQType,
+ dnsResNCacheErrTTL,
+ dnsResNCacheErrElapsedTTL,
+ dnsResNCacheErrSource,
+ dnsResNCacheErrCode,
+ dnsResNCacheErrStatus,
+ dnsResNCacheErrIndex,
+ dnsResNCacheErrPrettyName }
+ STATUS current
+ DESCRIPTION
+ "A collection of objects providing access to and control
+ of a DNS resolver's negative response cache."
+ ::= { dnsResMIBGroups 5 }
+
+ dnsResOptCounterGroup OBJECT-GROUP
+ OBJECTS { dnsResOptCounterReferals,
+ dnsResOptCounterRetrans,
+ dnsResOptCounterNoResponses,
+ dnsResOptCounterRootRetrans,
+ dnsResOptCounterInternals,
+ dnsResOptCounterInternalTimeOuts }
+ STATUS current
+ DESCRIPTION
+ "A collection of objects providing further
+ instrumentation applicable to many but not all DNS
+ resolvers."
+ ::= { dnsResMIBGroups 6 }
+
+
+ -- Compliances.
+
+ dnsResMIBCompliances OBJECT IDENTIFIER ::= { dnsResMIB 3 }
+
+ dnsResMIBCompliance MODULE-COMPLIANCE
+ STATUS current
+ DESCRIPTION
+ "The compliance statement for agents implementing the DNS
+ resolver MIB extensions."
+ MODULE -- This MIB module
+
+
+
+Austein & Saperia [Page 28]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ MANDATORY-GROUPS { dnsResConfigGroup, dnsResCounterGroup }
+ GROUP dnsResCacheGroup
+ DESCRIPTION
+ "The resolver cache group is mandatory for resolvers that
+ implement a cache."
+ GROUP dnsResNCacheGroup
+ DESCRIPTION
+ "The resolver negative cache group is mandatory for
+ resolvers that implement a negative response cache."
+ GROUP dnsResLameDelegationGroup
+ DESCRIPTION
+ "The lame delegation group is unconditionally optional."
+ GROUP dnsResOptCounterGroup
+ DESCRIPTION
+ "The optional counters group is unconditionally
+ optional."
+ OBJECT dnsResConfigMaxCnames
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+ OBJECT dnsResConfigSbeltName
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+ OBJECT dnsResConfigSbeltRecursion
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+ OBJECT dnsResConfigSbeltPref
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+ OBJECT dnsResConfigReset
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+ OBJECT dnsResCacheStatus
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+ OBJECT dnsResCacheMaxTTL
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+ OBJECT dnsResNCacheStatus
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+
+
+
+Austein & Saperia [Page 29]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ OBJECT dnsResNCacheMaxTTL
+ MIN-ACCESS read-only
+ DESCRIPTION
+ "This object need not be writable."
+ ::= { dnsResMIBCompliances 1 }
+
+ END
+
+5. Acknowledgements
+
+ This document is the result of work undertaken the by DNS working
+ group. The authors would particularly like to thank the following
+ people for their contributions to this document: Philip Almquist,
+ Frank Kastenholz (FTP Software), Joe Peck (DEC), Dave Perkins
+ (SynOptics), Win Treese (DEC), and Mimi Zohar (IBM).
+
+6. References
+
+ [1] Mockapetris, P., "Domain Names -- Concepts and Facilities", STD
+ 13, RFC 1034, USC/Information Sciences Institute, November 1987.
+
+ [2] Mockapetris, P., "Domain Names -- Implementation and
+ Specification", STD 13, RFC 1035, USC/Information Sciences
+ Institute, November 1987.
+
+ [3] Braden, R., Editor, "Requirements for Internet Hosts --
+ Application and Support, STD 3, RFC 1123, USC/Information
+ Sciences Institute, October 1989.
+
+ [4] Rose, M., and K. McCloghrie, "Structure and Identification of
+ Management Information for TCP/IP-based internets", STD 16, RFC
+ 1155, Performance Systems International, Hughes LAN Systems, May
+ 1990.
+
+ [5] McCloghrie, K., and M. Rose, "Management Information Base for
+ Network Management of TCP/IP-based internets", RFC 1156, Hughes
+ LAN Systems, Performance Systems International, May 1990.
+
+ [6] Case, J., Fedor, M., Schoffstall, M., and J. Davin, "Simple
+ Network Management Protocol", STD 15, RFC 1157, SNMP Research,
+ Performance Systems International, Performance Systems
+ International, MIT Laboratory for Computer Science, May 1990.
+
+ [7] Rose, M., and K. McCloghrie, Editors, "Concise MIB Definitions",
+ STD 16, RFC 1212, Performance Systems International, Hughes LAN
+ Systems, March 1991.
+
+
+
+
+
+Austein & Saperia [Page 30]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+ [8] McCloghrie, K., and M. Rose, "Management Information Base for
+ Network Management of TCP/IP-based internets: MIB-II", STD 17,
+ RFC 1213, Hughes LAN Systems, Performance Systems International,
+ March 1991.
+
+ [9] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Structure
+ of Management Information for version 2 of the Simple Network
+ Management Protocol (SNMPv2)", RFC 1442, SNMP Research, Inc.,
+ Hughes LAN Systems, Dover Beach Consulting, Inc., Carnegie Mellon
+ University, April 1993.
+
+ [10] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Textual
+ Conventions for version 2 of the the Simple Network Management
+ Protocol (SNMPv2)", RFC 1443, SNMP Research, Inc., Hughes LAN
+ Systems, Dover Beach Consulting, Inc., Carnegie Mellon
+ University, April 1993.
+
+ [11] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser,
+ "Conformance Statements for version 2 of the the Simple Network
+ Management Protocol (SNMPv2)", RFC 1444, SNMP Research, Inc.,
+ Hughes LAN Systems, Dover Beach Consulting, Inc., Carnegie Mellon
+ University, April 1993.
+
+ [12] Galvin, J., and K. McCloghrie, "Administrative Model for version
+ 2 of the Simple Network Management Protocol (SNMPv2)", RFC 1445,
+ Trusted Information Systems, Hughes LAN Systems, April 1993.
+
+ [13] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Protocol
+ Operations for version 2 of the Simple Network Management
+ Protocol (SNMPv2)", RFC 1448, SNMP Research, Inc., Hughes LAN
+ Systems, Dover Beach Consulting, Inc., Carnegie Mellon
+ University, April 1993.
+
+ [14] "Information processing systems - Open Systems Interconnection -
+ Specification of Abstract Syntax Notation One (ASN.1)",
+ International Organization for Standardization, International
+ Standard 8824, December 1987.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein & Saperia [Page 31]
+
+RFC 1612 DNS Resolver MIB May 1994
+
+
+7. Security Considerations
+
+ Security issues are not discussed in this memo.
+
+8. Authors' Addresses
+
+ Rob Austein
+ Epilogue Technology Corporation
+ 268 Main Street, Suite 283
+ North Reading, MA 01864
+ USA
+
+ Phone: +1-617-245-0804
+ Fax: +1-617-245-8122
+ EMail: sra@epilogue.com
+
+
+ Jon Saperia
+ Digital Equipment Corporation
+ 110 Spit Brook Road
+ ZKO1-3/H18
+ Nashua, NH 03062-2698
+ USA
+
+ Phone: +1-603-881-0480
+ Fax: +1-603-881-0120
+ EMail: saperia@zko.dec.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein & Saperia [Page 32]
+
diff --git a/doc/rfc/rfc1706.txt b/doc/rfc/rfc1706.txt
new file mode 100644
index 0000000..5b5d821
--- /dev/null
+++ b/doc/rfc/rfc1706.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group B. Manning
+Request for Comments: 1706 ISI
+Obsoletes: 1637, 1348 R. Colella
+Category: Informational NIST
+ October 1994
+
+
+ DNS NSAP Resource Records
+
+
+Status of this Memo
+
+ This memo provides information for the Internet community. This memo
+ does not specify an Internet standard of any kind. Distribution of
+ this memo is unlimited.
+
+Abstract
+
+ OSI lower layer protocols, comprising the connectionless network
+ protocol (CLNP) and supporting routing protocols, are deployed in
+ some parts of the global Internet. Maintenance and debugging of CLNP
+ connectivity is greatly aided by support in the Domain Name System
+ (DNS) for mapping between names and NSAP addresses.
+
+ This document defines the format of one new Resource Record (RR) for
+ the DNS for domain name-to-NSAP mapping. The RR may be used with any
+ NSAP address format.
+
+ NSAP-to-name translation is accomplished through use of the PTR RR
+ (see STD 13, RFC 1035 for a description of the PTR RR). This paper
+ describes how PTR RRs are used to support this translation.
+
+ This document obsoletes RFC 1348 and RFC 1637.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Manning & Colella [Page 1]
+
+RFC 1706 DNS NSAP RRs October 1994
+
+
+1. Introduction
+
+ OSI lower layer protocols, comprising the connectionless network
+ protocol (CLNP) [5] and supporting routing protocols, are deployed in
+ some parts of the global Internet. Maintenance and debugging of CLNP
+ connectivity is greatly aided by support in the Domain Name System
+ (DNS) [7] [8] for mapping between names and NSAP (network service
+ access point) addresses [6] [Note: NSAP and NSAP address are used
+ interchangeably throughout this memo].
+
+ This document defines the format of one new Resource Record (RR) for
+ the DNS for domain name-to-NSAP mapping. The RR may be used with any
+ NSAP address format.
+
+ NSAP-to-name translation is accomplished through use of the PTR RR
+ (see RFC 1035 for a description of the PTR RR). This paper describes
+ how PTR RRs are used to support this translation.
+
+ This memo assumes that the reader is familiar with the DNS. Some
+ familiarity with NSAPs is useful; see [1] or Annex A of [6] for
+ additional information.
+
+2. Background
+
+ The reason for defining DNS mappings for NSAPs is to support the
+ existing CLNP deployment in the Internet. Debugging with CLNP ping
+ and traceroute has become more difficult with only numeric NSAPs as
+ the scale of deployment has increased. Current debugging is supported
+ by maintaining and exchanging a configuration file with name/NSAP
+ mappings similar in function to hosts.txt. This suffers from the lack
+ of a central coordinator for this file and also from the perspective
+ of scaling. The former describes the most serious short-term
+ problem. Scaling of a hosts.txt-like solution has well-known long-
+ term scaling difficiencies.
+
+3. Scope
+
+ The methods defined in this paper are applicable to all NSAP formats.
+
+ As a point of reference, there is a distinction between registration
+ and publication of addresses. For IP addresses, the IANA is the root
+ registration authority and the DNS a publication method. For NSAPs,
+ Annex A of the network service definition, ISO8348 [6], describes the
+ root registration authority and this memo defines how the DNS is used
+ as a publication method.
+
+
+
+
+
+
+Manning & Colella [Page 2]
+
+RFC 1706 DNS NSAP RRs October 1994
+
+
+4. Structure of NSAPs
+
+ NSAPs are hierarchically structured to allow distributed
+ administration and efficient routing. Distributed administration
+ permits subdelegated addressing authorities to, as allowed by the
+ delegator, further structure the portion of the NSAP space under
+ their delegated control. Accomodating this distributed authority
+ requires that there be little or no a priori knowledge of the
+ structure of NSAPs built into DNS resolvers and servers.
+
+ For the purposes of this memo, NSAPs can be thought of as a tree of
+ identifiers. The root of the tree is ISO8348 [6], and has as its
+ immediately registered subordinates the one-octet Authority and
+ Format Identifiers (AFIs) defined there. The size of subsequently-
+ defined fields depends on which branch of the tree is taken. The
+ depth of the tree varies according to the authority responsible for
+ defining subsequent fields.
+
+ An example is the authority under which U.S. GOSIP defines NSAPs [2].
+ Under the AFI of 47, NIST (National Institute of Standards and
+ Technology) obtained a value of 0005 (the AFI of 47 defines the next
+ field as being two octets consisting of four BCD digits from the
+ International Code Designator space [3]). NIST defined the subsequent
+ fields in [2], as shown in Figure 1. The field immediately following
+ 0005 is a format identifier for the rest of the U.S. GOSIP NSAP
+ structure, with a hex value of 80. Following this is the three-octet
+ field, values for which are allocated to network operators; the
+ registration authority for this field is delegated to GSA (General
+ Services Administration).
+
+ The last octet of the NSAP is the NSelector (NSel). In practice, the
+ NSAP minus the NSel identifies the CLNP protocol machine on a given
+ system, and the NSel identifies the CLNP user. Since there can be
+ more than one CLNP user (meaning multiple NSel values for a given
+ "base" NSAP), the representation of the NSAP should be CLNP-user
+ independent. To achieve this, an NSel value of zero shall be used
+ with all NSAP values stored in the DNS. An NSAP with NSel=0
+ identifies the network layer itself. It is left to the application
+ retrieving the NSAP to determine the appropriate value to use in that
+ instance of communication.
+
+ When CLNP is used to support TCP and UDP services, the NSel value
+ used is the appropriate IP PROTO value as registered with the IANA.
+ For "standard" OSI, the selection of NSel values is left as a matter
+ of local administration. Administrators of systems that support the
+ OSI transport protocol [4] in addition to TCP/UDP must select NSels
+ for use by OSI Transport that do not conflict with the IP PROTO
+ values.
+
+
+
+Manning & Colella [Page 3]
+
+RFC 1706 DNS NSAP RRs October 1994
+
+
+ |--------------|
+ | <-- IDP --> |
+ |--------------|-------------------------------------|
+ | AFI | IDI | <-- DSP --> |
+ |-----|--------|-------------------------------------|
+ | 47 | 0005 | DFI | AA |Rsvd | RD |Area | ID |Sel |
+ |-----|--------|-----|----|-----|----|-----|----|----|
+ octets | 1 | 2 | 1 | 3 | 2 | 2 | 2 | 6 | 1 |
+ |-----|--------|-----|----|-----|----|-----|----|----|
+
+ IDP Initial Domain Part
+ AFI Authority and Format Identifier
+ IDI Initial Domain Identifier
+ DSP Domain Specific Part
+ DFI DSP Format Identifier
+ AA Administrative Authority
+ Rsvd Reserved
+ RD Routing Domain Identifier
+ Area Area Identifier
+ ID System Identifier
+ SEL NSAP Selector
+
+ Figure 1: GOSIP Version 2 NSAP structure.
+
+
+ In the NSAP RRs in Master Files and in the printed text in this memo,
+ NSAPs are often represented as a string of "."-separated hex values.
+ The values correspond to convenient divisions of the NSAP to make it
+ more readable. For example, the "."-separated fields might correspond
+ to the NSAP fields as defined by the appropriate authority (RARE,
+ U.S. GOSIP, ANSI, etc.). The use of this notation is strictly for
+ readability. The "."s do not appear in DNS packets and DNS servers
+ can ignore them when reading Master Files. For example, a printable
+ representation of the first four fields of a U.S. GOSIP NSAP might
+ look like
+
+ 47.0005.80.005a00
+
+ and a full U.S. GOSIP NSAP might appear as
+
+ 47.0005.80.005a00.0000.1000.0020.00800a123456.00.
+
+ Other NSAP formats have different lengths and different
+ administratively defined field widths to accomodate different
+ requirements. For more information on NSAP formats in use see RFC
+ 1629 [1].
+
+
+
+
+
+Manning & Colella [Page 4]
+
+RFC 1706 DNS NSAP RRs October 1994
+
+
+5. The NSAP RR
+
+ The NSAP RR is defined with mnemonic "NSAP" and TYPE code 22
+ (decimal) and is used to map from domain names to NSAPs. Name-to-NSAP
+ mapping in the DNS using the NSAP RR operates analogously to IP
+ address lookup. A query is generated by the resolver requesting an
+ NSAP RR for a provided domain name.
+
+ NSAP RRs conform to the top level RR format and semantics as defined
+ in Section 3.2.1 of RFC 1035.
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / /
+ / NAME /
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TYPE = NSAP |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | CLASS = IN |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TTL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RDLENGTH |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / RDATA /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ where:
+
+ * NAME: an owner name, i.e., the name of the node to which this
+ resource record pertains.
+
+ * TYPE: two octets containing the NSAP RR TYPE code of 22 (decimal).
+
+ * CLASS: two octets containing the RR IN CLASS code of 1.
+
+ * TTL: a 32 bit signed integer that specifies the time interval in
+ seconds that the resource record may be cached before the source
+ of the information should again be consulted. Zero values are
+ interpreted to mean that the RR can only be used for the
+ transaction in progress, and should not be cached. For example,
+ SOA records are always distributed with a zero TTL to prohibit
+ caching. Zero values can also be used for extremely volatile data.
+
+
+
+Manning & Colella [Page 5]
+
+RFC 1706 DNS NSAP RRs October 1994
+
+
+ * RDLENGTH: an unsigned 16 bit integer that specifies the length in
+ octets of the RDATA field.
+
+ * RDATA: a variable length string of octets containing the NSAP.
+ The value is the binary encoding of the NSAP as it would appear in
+ the CLNP source or destination address field. A typical example of
+ such an NSAP (in hex) is shown below. For this NSAP, RDLENGTH is
+ 20 (decimal); "."s have been omitted to emphasize that they don't
+ appear in the DNS packets.
+
+ 39840f80005a0000000001e13708002010726e00
+
+ NSAP RRs cause no additional section processing.
+
+6. NSAP-to-name Mapping Using the PTR RR
+
+ The PTR RR is defined in RFC 1035. This RR is typically used under
+ the "IN-ADDR.ARPA" domain to map from IPv4 addresses to domain names.
+
+ Similarly, the PTR RR is used to map from NSAPs to domain names under
+ the "NSAP.INT" domain. A domain name is generated from the NSAP
+ according to the rules described below. A query is sent by the
+ resolver requesting a PTR RR for the provided domain name.
+
+ A domain name is generated from an NSAP by reversing the hex nibbles
+ of the NSAP, treating each nibble as a separate subdomain, and
+ appending the top-level subdomain name "NSAP.INT" to it. For example,
+ the domain name used in the reverse lookup for the NSAP
+
+ 47.0005.80.005a00.0000.0001.e133.ffffff000162.00
+
+ would appear as
+
+ 0.0.2.6.1.0.0.0.f.f.f.f.f.f.3.3.1.e.1.0.0.0.0.0.0.0.0.0.a.5.0.0. \
+ 0.8.5.0.0.0.7.4.NSAP.INT.
+
+ [Implementation note: For sanity's sake user interfaces should be
+ designed to allow users to enter NSAPs using their natural order,
+ i.e., as they are typically written on paper. Also, arbitrary "."s
+ should be allowed (and ignored) on input.]
+
+7. Master File Format
+
+ The format of NSAP RRs (and NSAP-related PTR RRs) in Master Files
+ conforms to Section 5, "Master Files," of RFC 1035. Below are
+ examples of the use of these RRs in Master Files to support name-to-
+ NSAP and NSAP-to-name mapping.
+
+
+
+
+Manning & Colella [Page 6]
+
+RFC 1706 DNS NSAP RRs October 1994
+
+
+ The NSAP RR introduces a new hex string format for the RDATA field.
+ The format is "0x" (i.e., a zero followed by an 'x' character)
+ followed by a variable length string of hex characters (0 to 9, a to
+ f). The hex string is case-insensitive. "."s (i.e., periods) may be
+ inserted in the hex string anywhere after the "0x" for readability.
+ The "."s have no significance other than for readability and are not
+ propagated in the protocol (e.g., queries or zone transfers).
+
+
+ ;;;;;;
+ ;;;;;; Master File for domain nsap.nist.gov.
+ ;;;;;;
+
+
+ @ IN SOA emu.ncsl.nist.gov. root.emu.ncsl.nist.gov. (
+ 1994041800 ; Serial - date
+ 1800 ; Refresh - 30 minutes
+ 300 ; Retry - 5 minutes
+ 604800 ; Expire - 7 days
+ 3600 ) ; Minimum - 1 hour
+ IN NS emu.ncsl.nist.gov.
+ IN NS tuba.nsap.lanl.gov.
+ ;
+ ;
+ $ORIGIN nsap.nist.gov.
+ ;
+ ; hosts
+ ;
+ bsdi1 IN NSAP 0x47.0005.80.005a00.0000.0001.e133.ffffff000161.00
+ IN A 129.6.224.161
+ IN HINFO PC_486 BSDi1.1
+ ;
+ bsdi2 IN NSAP 0x47.0005.80.005a00.0000.0001.e133.ffffff000162.00
+ IN A 129.6.224.162
+ IN HINFO PC_486 BSDi1.1
+ ;
+ cursive IN NSAP 0x47.0005.80.005a00.0000.0001.e133.ffffff000171.00
+ IN A 129.6.224.171
+ IN HINFO PC_386 DOS_5.0/NCSA_Telnet(TUBA)
+ ;
+ infidel IN NSAP 0x47.0005.80.005a00.0000.0001.e133.ffffff000164.00
+ IN A 129.6.55.164
+ IN HINFO PC/486 BSDi1.0(TUBA)
+ ;
+ ; routers
+ ;
+ cisco1 IN NSAP 0x47.0005.80.005a00.0000.0001.e133.aaaaaa000151.00
+ IN A 129.6.224.151
+
+
+
+Manning & Colella [Page 7]
+
+RFC 1706 DNS NSAP RRs October 1994
+
+
+ IN A 129.6.225.151
+ IN A 129.6.229.151
+ ;
+ 3com1 IN NSAP 0x47.0005.80.005a00.0000.0001.e133.aaaaaa000111.00
+ IN A 129.6.224.111
+ IN A 129.6.225.111
+ IN A 129.6.228.111
+
+
+
+
+ ;;;;;;
+ ;;;;;; Master File for reverse mapping of NSAPs under the
+ ;;;;;; NSAP prefix:
+ ;;;;;;
+ ;;;;;; 47.0005.80.005a00.0000.0001.e133
+ ;;;;;;
+
+
+ @ IN SOA emu.ncsl.nist.gov. root.emu.ncsl.nist.gov. (
+ 1994041800 ; Serial - date
+ 1800 ; Refresh - 30 minutes
+ 300 ; Retry - 5 minutes
+ 604800 ; Expire - 7 days
+ 3600 ) ; Minimum - 1 hour
+ IN NS emu.ncsl.nist.gov.
+ IN NS tuba.nsap.lanl.gov.
+ ;
+ ;
+ $ORIGIN 3.3.1.e.1.0.0.0.0.0.0.0.0.0.a.5.0.0.0.8.5.0.0.0.7.4.NSAP.INT.
+ ;
+ 0.0.1.6.1.0.0.0.f.f.f.f.f.f IN PTR bsdi1.nsap.nist.gov.
+ ;
+ 0.0.2.6.1.0.0.0.f.f.f.f.f.f IN PTR bsdi2.nsap.nist.gov.
+ ;
+ 0.0.1.7.1.0.0.0.f.f.f.f.f.f IN PTR cursive.nsap.nist.gov.
+ ;
+ 0.0.4.6.1.0.0.0.f.f.f.f.f.f IN PTR infidel.nsap.nist.gov.
+ ;
+ 0.0.1.5.1.0.0.0.a.a.a.a.a.a IN PTR cisco1.nsap.nist.gov.
+ ;
+ 0.0.1.1.1.0.0.0.a.a.a.a.a.a IN PTR 3com1.nsap.nist.gov.
+
+8. Security Considerations
+
+ Security issues are not discussed in this memo.
+
+
+
+
+
+Manning & Colella [Page 8]
+
+RFC 1706 DNS NSAP RRs October 1994
+
+
+9. Authors' Addresses
+
+ Bill Manning
+ USC/Information Sciences Institute
+ 4676 Admiralty Way
+ Marina del Rey, CA. 90292
+ USA
+
+ Phone: +1.310.822.1511
+ EMail: bmanning@isi.edu
+
+
+ Richard Colella
+ National Institute of Standards and Technology
+ Technology/B217
+ Gaithersburg, MD 20899
+ USA
+
+ Phone: +1 301-975-3627
+ Fax: +1 301 590-0932
+ EMail: colella@nist.gov
+
+10. References
+
+ [1] Colella, R., Gardner, E., Callon, R., and Y. Rekhter, "Guidelines
+ for OSI NSAP Allocation inh the Internet", RFC 1629, NIST,
+ Wellfleet, Mitre, T.J. Watson Research Center, IBM Corp., May
+ 1994.
+
+ [2] GOSIP Advanced Requirements Group. Government Open Systems
+ Interconnection Profile (GOSIP) Version 2. Federal Information
+ Processing Standard 146-1, U.S. Department of Commerce, National
+ Institute of Standards and Technology, Gaithersburg, MD, April
+ 1991.
+
+ [3] ISO/IEC. Data interchange - structures for the identification of
+ organization. International Standard 6523, ISO/IEC JTC 1,
+ Switzerland, 1984.
+
+ [4] ISO/IEC. Connection oriented transport protocol specification.
+ International Standard 8073, ISO/IEC JTC 1, Switzerland, 1986.
+
+ [5] ISO/IEC. Protocol for Providing the Connectionless-mode Network
+ Service. International Standard 8473, ISO/IEC JTC 1,
+ Switzerland, 1986.
+
+
+
+
+
+
+Manning & Colella [Page 9]
+
+RFC 1706 DNS NSAP RRs October 1994
+
+
+ [6] ISO/IEC. Information Processing Systems -- Data Communications --
+ Network Service Definition. International Standard 8348, ISO/IEC
+ JTC 1, Switzerland, 1993.
+
+ [7] Mockapetris, P., "Domain Names -- Concepts and Facilities", STD
+ 13, RFC 1034, USC/Information Sciences Institute, November 1987.
+
+ [8] Mockapetris, P., "Domain Names -- Implementation and
+ Specification", STD 13, RFC 1035, USC/Information Sciences
+ Institute, November 1987.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Manning & Colella [Page 10]
+
diff --git a/doc/rfc/rfc1712.txt b/doc/rfc/rfc1712.txt
new file mode 100644
index 0000000..40d8857
--- /dev/null
+++ b/doc/rfc/rfc1712.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group C. Farrell
+Request for Comments: 1712 M. Schulze
+Category: Experimental S. Pleitner
+ D. Baldoni
+ Curtin University of Technology
+ November 1994
+
+
+ DNS Encoding of Geographical Location
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. This memo does not specify an Internet standard of any
+ kind. Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Abstract
+
+ This document defines the format of a new Resource Record (RR) for
+ the Domain Naming System (DNS), and reserves a corresponding DNS type
+ mnemonic and numerical code. This definition deals with associating
+ geographical host location mappings to host names within a domain.
+ The data shown in this document is fictitious and does not
+ necessarily reflect the real Internet.
+
+1. Introduction
+
+ It has been a long standing problem to relate IP numbers to
+ geographical locations. The availability of Geographical location
+ information has immediate applications in network management. Such
+ information can be used to supplement the data already provided by
+ utilities such as whois [Har85], traceroute [VJ89], and nslookup
+ [UCB89]. The usefulness and functionality of these already widely
+ used tools would be greatly enhanced by the provision of reliable
+ geographical location information.
+
+ The ideal way to manage and maintain a database of information, such
+ as geographical location of internet hosts, is to delegate
+ responsibility to local domain administrators. A large distributed
+ database could be implemented with a simple mechanism for updating
+ the local information. A query mechanism also has to be available
+ for checking local entries, as well as inquiring about data from
+ non-local domains.
+
+
+
+
+
+
+
+Farrell, Schulze, Pleitner & Baldoni [Page 1]
+
+RFC 1712 DNS Encoding of Geographical Location November 1994
+
+
+2. Background
+
+ The Internet continues to grow at an ever increasing rate with IP
+ numbers allocated on a first-come-first-serve basis. Deciding when
+ and how to setup a database of geographical information about
+ internet hosts presented a number of options. The uumap project
+ [UU85] was the first serious attempt to collect geographical location
+ data from sites and store it centrally. This project met with
+ limited success because of the difficulty in maintaining and updating
+ a large central database. Another problem was the lack of tools for
+ the checking the data supplied, this problem resulted in some
+ erroneous data entering the database.
+
+2.1 SNMP:
+
+ Using an SNMP get request on the sysLocation MIB (Management
+ Information Base) variable was also an option, however this would
+ require the host to be running an appropriate agent with public read
+ access. It was also felt that MIB data should reflect local
+ management data (e.g., "this" host is on level 5 room 74) rather than
+ a hosts geographical position. This view is supported in the
+ examples given in literature in this area [ROSE91].
+
+2.2 X500:
+
+ The X.500 Directory service [X.500.88] defined as part of the ISO
+ standards also appears as a potential provider of geographical
+ location data. However due to the limited implementations of this
+ service it was decided to defer this until this service gains wider
+ use and acceptance within the Internet community.
+
+2.3 BIND:
+
+ The DNS [Mock87a][Mock87b] represents an existing system ideally
+ suited to the provision of host specific information. The DNS is a
+ widely used and well-understood mechanism for providing a distributed
+ database of such information and its extensible nature allows it to
+ be used to disseminate virtually any information. The most commonly
+ used DNS implementation is the Berkeley Internet Name Domain server
+ BIND [UCB89]. The information we wished to make available needed to
+ be updated locally but available globally; a perfect match with the
+ services provided by the DNS. Current DNS servers provide a variety
+ of useful information about hosts in their domain but lack the
+ ability to report a host's geographical location.
+
+
+
+
+
+
+
+Farrell, Schulze, Pleitner & Baldoni [Page 2]
+
+RFC 1712 DNS Encoding of Geographical Location November 1994
+
+
+3. RDATA Format
+
+ MSB LSB
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / LONGITUDE /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / LATITUDE /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / ALTITUDE /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ where:
+
+ LONGITUDE The real number describing the longitude encoded as a
+ printable string. The precision is limited by 256 charcters
+ within the range -90..90 degrees. Positive numbers
+ indicate locations north of the equator.
+
+ LATITUDE The real number describing the latitude encoded as a
+ printable string. The precision is limited by 256 charcters
+ within the range -180..180 degrees. Positive numbers
+ indicate locations east of the prime meridian.
+
+ ALTITUDE The real number describing the altitude (in meters) from
+ mean sea-level encoded as a printable string. The precision
+ is limited by 256 charcters. Positive numbers indicate
+ locations above mean sea-level.
+
+ Latitude/Longitude/Altitude values are encoded as strings as to avoid
+ the precision limitations imposed by encoding as unsigned integers.
+ Although this might not be considered optimal, it allows for a very
+ high degree of precision with an acceptable average encoded record
+ length.
+
+4. The GPOS RR
+
+ The geographical location is defined with the mnemonic GPOS and type
+ code 27.
+
+ GPOS has the following format:
+ <owner> <ttl> <class> GPOS <longitude> <latitude> <altitude>
+
+ A floating point format was chosen to specify geographical locations
+ for reasons of simplicity. This also guarantees a concise
+ unambiguous description of a location by enforcing three compulsory
+ numerical values to be specified.
+
+
+
+
+
+Farrell, Schulze, Pleitner & Baldoni [Page 3]
+
+RFC 1712 DNS Encoding of Geographical Location November 1994
+
+
+ The owner, ttl, and class fields are optional and default to the last
+ defined value if omitted. The longitude is a floating point number
+ ranging from -90 to 90 with positive values indicating locations
+ north of the equator. For example Perth, Western Australia is
+ located at 32^ 7` 19" south of the equator which would be specified
+ as -32.68820. The latitude is a number ranging from -180.0 to 180.0.
+ For example Perth, Western Australia is located at 116^ 2' 25" east
+ of the prime meridian which would be specified as 116.86520. Curtin
+ University, Perth is also 10 meters above sea-level.
+
+ The valid GPOS record for a host at Curtin University in Perth
+ Western Australia would therefore be:
+
+ GPOS -32.6882 116.8652 10.0
+
+ There is no limit imposed on the number of decimal places, although
+ the length of the encoded string is limited to 256 characters for
+ each field. It is also suggested that administrators limit their
+ entries to the minimum number of necessary characters in each field.
+
+5. Master File Format
+
+ Each host requires its own GPOS field in the corresponding DNS RR to
+ explicitly specify its geographical location and altitude. If the
+ GPOS field is omitted, a DNS enquiry will return no position
+ information for that host.
+
+ Consider the following example:
+
+; Authoritative data for cs.curtin.edu.au.
+;
+@ IN SOA marsh.cs.curtin.edu.au. postmaster.cs.curtin.edu.au.
+ (
+ 94070503 ; Serial (yymmddnn)
+ 10800 ; Refresh (3 hours)
+ 3600 ; Retry (1 hour)
+ 3600000 ; Expire (1000 hours)
+ 86400 ; Minimum (24 hours)
+ )
+
+ IN NS marsh.cs.curtin.edu.au.
+
+marsh IN A 134.7.1.1
+ IN MX 0 marsh
+ IN HINFO SGI-Indigo IRIX-4.0.5F
+ IN GPOS -32.6882 116.8652 10.0
+ftp IN CNAME marsh
+
+
+
+
+Farrell, Schulze, Pleitner & Baldoni [Page 4]
+
+RFC 1712 DNS Encoding of Geographical Location November 1994
+
+
+lillee IN A 134.7.1.2
+ IN MX 0 marsh
+ IN HINFO SGI-Indigo IRIX-4.0.5F
+ IN GPOS -32.6882 116.8652 10.0
+
+hinault IN A 134.7.1.23
+ IN MX 0 marsh
+ IN HINFO SUN-IPC SunOS-4.1.3
+ IN GPOS -22.6882 116.8652 250.0
+
+merckx IN A 134.7.1.24
+ IN MX 0 marsh
+ IN HINFO SUN-IPC SunOS-4.1.1
+
+ambrose IN A 134.7.1.99
+ IN MX 0 marsh
+ IN HINFO SGI-CHALLENGE_L IRIX-5.2
+ IN GPOS -32.6882 116.8652 10.0
+
+ The hosts marsh, lillee, and ambrose are all at the same geographical
+ location, Perth Western Australia (-32.68820 116.86520). The host
+ hinault is at a different geographical location, 10 degrees north of
+ Perth in the mountains (-22.6882 116.8652 250.0). For security
+ reasons we do not wish to give the location of the host merckx.
+
+ Although the GPOS clause is not a standard entry within BIND
+ configuration files, most vendor implementations seem to ignore
+ whatever is not understood upon startup of the DNS. Usually this
+ will result in a number of warnings appearing in system log files,
+ but in no way alters naming information or impedes the DNS from
+ performing its normal duties.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Farrell, Schulze, Pleitner & Baldoni [Page 5]
+
+RFC 1712 DNS Encoding of Geographical Location November 1994
+
+
+7. References
+
+ [ROSE91] Rose M., "The Simple Book: An Introduction to
+ Management of TCP/IP-based Internets", Prentice-Hall,
+ Englewood Cliffs, New Jersey, 1991.
+
+ [X.500.88] CCITT: The Directory - Overview of Concepts, Models
+ and Services", Recommendations X.500 - X.521.
+
+ [Har82] Harrenstein K, Stahl M., and E. Feinler,
+ "NICNAME/WHOIS" RFC 812, SRI NIC, March 1982.
+
+ [Mock87a] Mockapetris P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, USC/Information
+ Sciences Institute, November 1987.
+
+ [Mock87b] Mockapetris P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, USC/Information
+ Sciences Institute, November 1987.
+
+ [FRB93] Ford P., Rekhter Y., and H-W. Braun, "Improving the
+ Routing and Addressing of IP", IEEE Network
+ Vol.7, No. 3, pp. 11-15, May 1993.
+
+ [VJ89] Jacobsen V., "The Traceroute(8) Manual Page",
+ Lawrence Berkeley Laboratory, Berkeley,
+ CA, February 1989.
+
+ [UCB89] University of California, "BIND: Berkeley Internet
+ Name Domain Server", 1989.
+ [UU85] UUCP Mapping Project, Software available via
+ anonymous FTP from ftp.uu.net., 1985.
+
+8. Security Considerations
+
+ Once information has been entered into the DNS, it is considered
+ public.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Farrell, Schulze, Pleitner & Baldoni [Page 6]
+
+RFC 1712 DNS Encoding of Geographical Location November 1994
+
+
+9. Authors' Addresses
+
+ Craig Farrell
+ Department of Computer Science
+ Curtin University of technology
+ GPO Box U1987 Perth,
+ Western Australia
+
+ EMail: craig@cs.curtin.edu.au
+
+
+ Mike Schulze
+ Department of Computer Science
+ Curtin University of technology
+ GPO Box U1987 Perth,
+ Western Australia
+
+ EMail: mike@cs.curtin.edu.au
+
+
+ Scott Pleitner
+ Department of Computer Science
+ Curtin University of technology
+ GPO Box U1987 Perth,
+ Western Australia
+
+ EMail: pleitner@cs.curtin.edu.au
+
+
+ Daniel Baldoni
+ Department of Computer Science
+ Curtin University of technology
+ GPO Box U1987 Perth,
+ Western Australia
+
+ EMail: flint@cs.curtin.edu.au
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Farrell, Schulze, Pleitner & Baldoni [Page 7]
+
diff --git a/doc/rfc/rfc1750.txt b/doc/rfc/rfc1750.txt
new file mode 100644
index 0000000..56d478c
--- /dev/null
+++ b/doc/rfc/rfc1750.txt
@@ -0,0 +1,1683 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake, 3rd
+Request for Comments: 1750 DEC
+Category: Informational S. Crocker
+ Cybercash
+ J. Schiller
+ MIT
+ December 1994
+
+
+ Randomness Recommendations for Security
+
+Status of this Memo
+
+ This memo provides information for the Internet community. This memo
+ does not specify an Internet standard of any kind. Distribution of
+ this memo is unlimited.
+
+Abstract
+
+ Security systems today are built on increasingly strong cryptographic
+ algorithms that foil pattern analysis attempts. However, the security
+ of these systems is dependent on generating secret quantities for
+ passwords, cryptographic keys, and similar quantities. The use of
+ pseudo-random processes to generate secret quantities can result in
+ pseudo-security. The sophisticated attacker of these security
+ systems may find it easier to reproduce the environment that produced
+ the secret quantities, searching the resulting small set of
+ possibilities, than to locate the quantities in the whole of the
+ number space.
+
+ Choosing random quantities to foil a resourceful and motivated
+ adversary is surprisingly difficult. This paper points out many
+ pitfalls in using traditional pseudo-random number generation
+ techniques for choosing such quantities. It recommends the use of
+ truly random hardware techniques and shows that the existing hardware
+ on many systems can be used for this purpose. It provides
+ suggestions to ameliorate the problem when a hardware solution is not
+ available. And it gives examples of how large such quantities need
+ to be for some particular applications.
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 1]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+Acknowledgements
+
+ Comments on this document that have been incorporated were received
+ from (in alphabetic order) the following:
+
+ David M. Balenson (TIS)
+ Don Coppersmith (IBM)
+ Don T. Davis (consultant)
+ Carl Ellison (Stratus)
+ Marc Horowitz (MIT)
+ Christian Huitema (INRIA)
+ Charlie Kaufman (IRIS)
+ Steve Kent (BBN)
+ Hal Murray (DEC)
+ Neil Haller (Bellcore)
+ Richard Pitkin (DEC)
+ Tim Redmond (TIS)
+ Doug Tygar (CMU)
+
+Table of Contents
+
+ 1. Introduction........................................... 3
+ 2. Requirements........................................... 4
+ 3. Traditional Pseudo-Random Sequences.................... 5
+ 4. Unpredictability....................................... 7
+ 4.1 Problems with Clocks and Serial Numbers............... 7
+ 4.2 Timing and Content of External Events................ 8
+ 4.3 The Fallacy of Complex Manipulation.................. 8
+ 4.4 The Fallacy of Selection from a Large Database....... 9
+ 5. Hardware for Randomness............................... 10
+ 5.1 Volume Required...................................... 10
+ 5.2 Sensitivity to Skew.................................. 10
+ 5.2.1 Using Stream Parity to De-Skew..................... 11
+ 5.2.2 Using Transition Mappings to De-Skew............... 12
+ 5.2.3 Using FFT to De-Skew............................... 13
+ 5.2.4 Using Compression to De-Skew....................... 13
+ 5.3 Existing Hardware Can Be Used For Randomness......... 14
+ 5.3.1 Using Existing Sound/Video Input................... 14
+ 5.3.2 Using Existing Disk Drives......................... 14
+ 6. Recommended Non-Hardware Strategy..................... 14
+ 6.1 Mixing Functions..................................... 15
+ 6.1.1 A Trivial Mixing Function.......................... 15
+ 6.1.2 Stronger Mixing Functions.......................... 16
+ 6.1.3 Diff-Hellman as a Mixing Function.................. 17
+ 6.1.4 Using a Mixing Function to Stretch Random Bits..... 17
+ 6.1.5 Other Factors in Choosing a Mixing Function........ 18
+ 6.2 Non-Hardware Sources of Randomness................... 19
+ 6.3 Cryptographically Strong Sequences................... 19
+
+
+
+Eastlake, Crocker & Schiller [Page 2]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ 6.3.1 Traditional Strong Sequences....................... 20
+ 6.3.2 The Blum Blum Shub Sequence Generator.............. 21
+ 7. Key Generation Standards.............................. 22
+ 7.1 US DoD Recommendations for Password Generation....... 23
+ 7.2 X9.17 Key Generation................................. 23
+ 8. Examples of Randomness Required....................... 24
+ 8.1 Password Generation................................. 24
+ 8.2 A Very High Security Cryptographic Key............... 25
+ 8.2.1 Effort per Key Trial............................... 25
+ 8.2.2 Meet in the Middle Attacks......................... 26
+ 8.2.3 Other Considerations............................... 26
+ 9. Conclusion............................................ 27
+ 10. Security Considerations.............................. 27
+ References............................................... 28
+ Authors' Addresses....................................... 30
+
+1. Introduction
+
+ Software cryptography is coming into wider use. Systems like
+ Kerberos, PEM, PGP, etc. are maturing and becoming a part of the
+ network landscape [PEM]. These systems provide substantial
+ protection against snooping and spoofing. However, there is a
+ potential flaw. At the heart of all cryptographic systems is the
+ generation of secret, unguessable (i.e., random) numbers.
+
+ For the present, the lack of generally available facilities for
+ generating such unpredictable numbers is an open wound in the design
+ of cryptographic software. For the software developer who wants to
+ build a key or password generation procedure that runs on a wide
+ range of hardware, the only safe strategy so far has been to force
+ the local installation to supply a suitable routine to generate
+ random numbers. To say the least, this is an awkward, error-prone
+ and unpalatable solution.
+
+ It is important to keep in mind that the requirement is for data that
+ an adversary has a very low probability of guessing or determining.
+ This will fail if pseudo-random data is used which only meets
+ traditional statistical tests for randomness or which is based on
+ limited range sources, such as clocks. Frequently such random
+ quantities are determinable by an adversary searching through an
+ embarrassingly small space of possibilities.
+
+ This informational document suggests techniques for producing random
+ quantities that will be resistant to such attack. It recommends that
+ future systems include hardware random number generation or provide
+ access to existing hardware that can be used for this purpose. It
+ suggests methods for use if such hardware is not available. And it
+ gives some estimates of the number of random bits required for sample
+
+
+
+Eastlake, Crocker & Schiller [Page 3]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ applications.
+
+2. Requirements
+
+ Probably the most commonly encountered randomness requirement today
+ is the user password. This is usually a simple character string.
+ Obviously, if a password can be guessed, it does not provide
+ security. (For re-usable passwords, it is desirable that users be
+ able to remember the password. This may make it advisable to use
+ pronounceable character strings or phrases composed on ordinary
+ words. But this only affects the format of the password information,
+ not the requirement that the password be very hard to guess.)
+
+ Many other requirements come from the cryptographic arena.
+ Cryptographic techniques can be used to provide a variety of services
+ including confidentiality and authentication. Such services are
+ based on quantities, traditionally called "keys", that are unknown to
+ and unguessable by an adversary.
+
+ In some cases, such as the use of symmetric encryption with the one
+ time pads [CRYPTO*] or the US Data Encryption Standard [DES], the
+ parties who wish to communicate confidentially and/or with
+ authentication must all know the same secret key. In other cases,
+ using what are called asymmetric or "public key" cryptographic
+ techniques, keys come in pairs. One key of the pair is private and
+ must be kept secret by one party, the other is public and can be
+ published to the world. It is computationally infeasible to
+ determine the private key from the public key [ASYMMETRIC, CRYPTO*].
+
+ The frequency and volume of the requirement for random quantities
+ differs greatly for different cryptographic systems. Using pure RSA
+ [CRYPTO*], random quantities are required when the key pair is
+ generated, but thereafter any number of messages can be signed
+ without any further need for randomness. The public key Digital
+ Signature Algorithm that has been proposed by the US National
+ Institute of Standards and Technology (NIST) requires good random
+ numbers for each signature. And encrypting with a one time pad, in
+ principle the strongest possible encryption technique, requires a
+ volume of randomness equal to all the messages to be processed.
+
+ In most of these cases, an adversary can try to determine the
+ "secret" key by trial and error. (This is possible as long as the
+ key is enough smaller than the message that the correct key can be
+ uniquely identified.) The probability of an adversary succeeding at
+ this must be made acceptably low, depending on the particular
+ application. The size of the space the adversary must search is
+ related to the amount of key "information" present in the information
+ theoretic sense [SHANNON]. This depends on the number of different
+
+
+
+Eastlake, Crocker & Schiller [Page 4]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ secret values possible and the probability of each value as follows:
+
+ -----
+ \
+ Bits-of-info = \ - p * log ( p )
+ / i 2 i
+ /
+ -----
+
+ where i varies from 1 to the number of possible secret values and p
+ sub i is the probability of the value numbered i. (Since p sub i is
+ less than one, the log will be negative so each term in the sum will
+ be non-negative.)
+
+ If there are 2^n different values of equal probability, then n bits
+ of information are present and an adversary would, on the average,
+ have to try half of the values, or 2^(n-1) , before guessing the
+ secret quantity. If the probability of different values is unequal,
+ then there is less information present and fewer guesses will, on
+ average, be required by an adversary. In particular, any values that
+ the adversary can know are impossible, or are of low probability, can
+ be initially ignored by an adversary, who will search through the
+ more probable values first.
+
+ For example, consider a cryptographic system that uses 56 bit keys.
+ If these 56 bit keys are derived by using a fixed pseudo-random
+ number generator that is seeded with an 8 bit seed, then an adversary
+ needs to search through only 256 keys (by running the pseudo-random
+ number generator with every possible seed), not the 2^56 keys that
+ may at first appear to be the case. Only 8 bits of "information" are
+ in these 56 bit keys.
+
+3. Traditional Pseudo-Random Sequences
+
+ Most traditional sources of random numbers use deterministic sources
+ of "pseudo-random" numbers. These typically start with a "seed"
+ quantity and use numeric or logical operations to produce a sequence
+ of values.
+
+ [KNUTH] has a classic exposition on pseudo-random numbers.
+ Applications he mentions are simulation of natural phenomena,
+ sampling, numerical analysis, testing computer programs, decision
+ making, and games. None of these have the same characteristics as
+ the sort of security uses we are talking about. Only in the last two
+ could there be an adversary trying to find the random quantity.
+ However, in these cases, the adversary normally has only a single
+ chance to use a guessed value. In guessing passwords or attempting
+ to break an encryption scheme, the adversary normally has many,
+
+
+
+Eastlake, Crocker & Schiller [Page 5]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ perhaps unlimited, chances at guessing the correct value and should
+ be assumed to be aided by a computer.
+
+ For testing the "randomness" of numbers, Knuth suggests a variety of
+ measures including statistical and spectral. These tests check
+ things like autocorrelation between different parts of a "random"
+ sequence or distribution of its values. They could be met by a
+ constant stored random sequence, such as the "random" sequence
+ printed in the CRC Standard Mathematical Tables [CRC].
+
+ A typical pseudo-random number generation technique, known as a
+ linear congruence pseudo-random number generator, is modular
+ arithmetic where the N+1th value is calculated from the Nth value by
+
+ V = ( V * a + b )(Mod c)
+ N+1 N
+
+ The above technique has a strong relationship to linear shift
+ register pseudo-random number generators, which are well understood
+ cryptographically [SHIFT*]. In such generators bits are introduced
+ at one end of a shift register as the Exclusive Or (binary sum
+ without carry) of bits from selected fixed taps into the register.
+
+ For example:
+
+ +----+ +----+ +----+ +----+
+ | B | <-- | B | <-- | B | <-- . . . . . . <-- | B | <-+
+ | 0 | | 1 | | 2 | | n | |
+ +----+ +----+ +----+ +----+ |
+ | | | |
+ | | V +-----+
+ | V +----------------> | |
+ V +-----------------------------> | XOR |
+ +---------------------------------------------------> | |
+ +-----+
+
+
+ V = ( ( V * 2 ) + B .xor. B ... )(Mod 2^n)
+ N+1 N 0 2
+
+ The goodness of traditional pseudo-random number generator algorithms
+ is measured by statistical tests on such sequences. Carefully chosen
+ values of the initial V and a, b, and c or the placement of shift
+ register tap in the above simple processes can produce excellent
+ statistics.
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 6]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ These sequences may be adequate in simulations (Monte Carlo
+ experiments) as long as the sequence is orthogonal to the structure
+ of the space being explored. Even there, subtle patterns may cause
+ problems. However, such sequences are clearly bad for use in
+ security applications. They are fully predictable if the initial
+ state is known. Depending on the form of the pseudo-random number
+ generator, the sequence may be determinable from observation of a
+ short portion of the sequence [CRYPTO*, STERN]. For example, with
+ the generators above, one can determine V(n+1) given knowledge of
+ V(n). In fact, it has been shown that with these techniques, even if
+ only one bit of the pseudo-random values is released, the seed can be
+ determined from short sequences.
+
+ Not only have linear congruent generators been broken, but techniques
+ are now known for breaking all polynomial congruent generators
+ [KRAWCZYK].
+
+4. Unpredictability
+
+ Randomness in the traditional sense described in section 3 is NOT the
+ same as the unpredictability required for security use.
+
+ For example, use of a widely available constant sequence, such as
+ that from the CRC tables, is very weak against an adversary. Once
+ they learn of or guess it, they can easily break all security, future
+ and past, based on the sequence [CRC]. Yet the statistical
+ properties of these tables are good.
+
+ The following sections describe the limitations of some randomness
+ generation techniques and sources.
+
+4.1 Problems with Clocks and Serial Numbers
+
+ Computer clocks, or similar operating system or hardware values,
+ provide significantly fewer real bits of unpredictability than might
+ appear from their specifications.
+
+ Tests have been done on clocks on numerous systems and it was found
+ that their behavior can vary widely and in unexpected ways. One
+ version of an operating system running on one set of hardware may
+ actually provide, say, microsecond resolution in a clock while a
+ different configuration of the "same" system may always provide the
+ same lower bits and only count in the upper bits at much lower
+ resolution. This means that successive reads on the clock may
+ produce identical values even if enough time has passed that the
+ value "should" change based on the nominal clock resolution. There
+ are also cases where frequently reading a clock can produce
+ artificial sequential values because of extra code that checks for
+
+
+
+Eastlake, Crocker & Schiller [Page 7]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ the clock being unchanged between two reads and increases it by one!
+ Designing portable application code to generate unpredictable numbers
+ based on such system clocks is particularly challenging because the
+ system designer does not always know the properties of the system
+ clocks that the code will execute on.
+
+ Use of a hardware serial number such as an Ethernet address may also
+ provide fewer bits of uniqueness than one would guess. Such
+ quantities are usually heavily structured and subfields may have only
+ a limited range of possible values or values easily guessable based
+ on approximate date of manufacture or other data. For example, it is
+ likely that most of the Ethernet cards installed on Digital Equipment
+ Corporation (DEC) hardware within DEC were manufactured by DEC
+ itself, which significantly limits the range of built in addresses.
+
+ Problems such as those described above related to clocks and serial
+ numbers make code to produce unpredictable quantities difficult if
+ the code is to be ported across a variety of computer platforms and
+ systems.
+
+4.2 Timing and Content of External Events
+
+ It is possible to measure the timing and content of mouse movement,
+ key strokes, and similar user events. This is a reasonable source of
+ unguessable data with some qualifications. On some machines, inputs
+ such as key strokes are buffered. Even though the user's inter-
+ keystroke timing may have sufficient variation and unpredictability,
+ there might not be an easy way to access that variation. Another
+ problem is that no standard method exists to sample timing details.
+ This makes it hard to build standard software intended for
+ distribution to a large range of machines based on this technique.
+
+ The amount of mouse movement or the keys actually hit are usually
+ easier to access than timings but may yield less unpredictability as
+ the user may provide highly repetitive input.
+
+ Other external events, such as network packet arrival times, can also
+ be used with care. In particular, the possibility of manipulation of
+ such times by an adversary must be considered.
+
+4.3 The Fallacy of Complex Manipulation
+
+ One strategy which may give a misleading appearance of
+ unpredictability is to take a very complex algorithm (or an excellent
+ traditional pseudo-random number generator with good statistical
+ properties) and calculate a cryptographic key by starting with the
+ current value of a computer system clock as the seed. An adversary
+ who knew roughly when the generator was started would have a
+
+
+
+Eastlake, Crocker & Schiller [Page 8]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ relatively small number of seed values to test as they would know
+ likely values of the system clock. Large numbers of pseudo-random
+ bits could be generated but the search space an adversary would need
+ to check could be quite small.
+
+ Thus very strong and/or complex manipulation of data will not help if
+ the adversary can learn what the manipulation is and there is not
+ enough unpredictability in the starting seed value. Even if they can
+ not learn what the manipulation is, they may be able to use the
+ limited number of results stemming from a limited number of seed
+ values to defeat security.
+
+ Another serious strategy error is to assume that a very complex
+ pseudo-random number generation algorithm will produce strong random
+ numbers when there has been no theory behind or analysis of the
+ algorithm. There is a excellent example of this fallacy right near
+ the beginning of chapter 3 in [KNUTH] where the author describes a
+ complex algorithm. It was intended that the machine language program
+ corresponding to the algorithm would be so complicated that a person
+ trying to read the code without comments wouldn't know what the
+ program was doing. Unfortunately, actual use of this algorithm
+ showed that it almost immediately converged to a single repeated
+ value in one case and a small cycle of values in another case.
+
+ Not only does complex manipulation not help you if you have a limited
+ range of seeds but blindly chosen complex manipulation can destroy
+ the randomness in a good seed!
+
+4.4 The Fallacy of Selection from a Large Database
+
+ Another strategy that can give a misleading appearance of
+ unpredictability is selection of a quantity randomly from a database
+ and assume that its strength is related to the total number of bits
+ in the database. For example, typical USENET servers as of this date
+ process over 35 megabytes of information per day. Assume a random
+ quantity was selected by fetching 32 bytes of data from a random
+ starting point in this data. This does not yield 32*8 = 256 bits
+ worth of unguessability. Even after allowing that much of the data
+ is human language and probably has more like 2 or 3 bits of
+ information per byte, it doesn't yield 32*2.5 = 80 bits of
+ unguessability. For an adversary with access to the same 35
+ megabytes the unguessability rests only on the starting point of the
+ selection. That is, at best, about 25 bits of unguessability in this
+ case.
+
+ The same argument applies to selecting sequences from the data on a
+ CD ROM or Audio CD recording or any other large public database. If
+ the adversary has access to the same database, this "selection from a
+
+
+
+Eastlake, Crocker & Schiller [Page 9]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ large volume of data" step buys very little. However, if a selection
+ can be made from data to which the adversary has no access, such as
+ system buffers on an active multi-user system, it may be of some
+ help.
+
+5. Hardware for Randomness
+
+ Is there any hope for strong portable randomness in the future?
+ There might be. All that's needed is a physical source of
+ unpredictable numbers.
+
+ A thermal noise or radioactive decay source and a fast, free-running
+ oscillator would do the trick directly [GIFFORD]. This is a trivial
+ amount of hardware, and could easily be included as a standard part
+ of a computer system's architecture. Furthermore, any system with a
+ spinning disk or the like has an adequate source of randomness
+ [DAVIS]. All that's needed is the common perception among computer
+ vendors that this small additional hardware and the software to
+ access it is necessary and useful.
+
+5.1 Volume Required
+
+ How much unpredictability is needed? Is it possible to quantify the
+ requirement in, say, number of random bits per second?
+
+ The answer is not very much is needed. For DES, the key is 56 bits
+ and, as we show in an example in Section 8, even the highest security
+ system is unlikely to require a keying material of over 200 bits. If
+ a series of keys are needed, it can be generated from a strong random
+ seed using a cryptographically strong sequence as explained in
+ Section 6.3. A few hundred random bits generated once a day would be
+ enough using such techniques. Even if the random bits are generated
+ as slowly as one per second and it is not possible to overlap the
+ generation process, it should be tolerable in high security
+ applications to wait 200 seconds occasionally.
+
+ These numbers are trivial to achieve. It could be done by a person
+ repeatedly tossing a coin. Almost any hardware process is likely to
+ be much faster.
+
+5.2 Sensitivity to Skew
+
+ Is there any specific requirement on the shape of the distribution of
+ the random numbers? The good news is the distribution need not be
+ uniform. All that is needed is a conservative estimate of how non-
+ uniform it is to bound performance. Two simple techniques to de-skew
+ the bit stream are given below and stronger techniques are mentioned
+ in Section 6.1.2 below.
+
+
+
+Eastlake, Crocker & Schiller [Page 10]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+5.2.1 Using Stream Parity to De-Skew
+
+ Consider taking a sufficiently long string of bits and map the string
+ to "zero" or "one". The mapping will not yield a perfectly uniform
+ distribution, but it can be as close as desired. One mapping that
+ serves the purpose is to take the parity of the string. This has the
+ advantages that it is robust across all degrees of skew up to the
+ estimated maximum skew and is absolutely trivial to implement in
+ hardware.
+
+ The following analysis gives the number of bits that must be sampled:
+
+ Suppose the ratio of ones to zeros is 0.5 + e : 0.5 - e, where e is
+ between 0 and 0.5 and is a measure of the "eccentricity" of the
+ distribution. Consider the distribution of the parity function of N
+ bit samples. The probabilities that the parity will be one or zero
+ will be the sum of the odd or even terms in the binomial expansion of
+ (p + q)^N, where p = 0.5 + e, the probability of a one, and q = 0.5 -
+ e, the probability of a zero.
+
+ These sums can be computed easily as
+
+ N N
+ 1/2 * ( ( p + q ) + ( p - q ) )
+ and
+ N N
+ 1/2 * ( ( p + q ) - ( p - q ) ).
+
+ (Which one corresponds to the probability the parity will be 1
+ depends on whether N is odd or even.)
+
+ Since p + q = 1 and p - q = 2e, these expressions reduce to
+
+ N
+ 1/2 * [1 + (2e) ]
+ and
+ N
+ 1/2 * [1 - (2e) ].
+
+ Neither of these will ever be exactly 0.5 unless e is zero, but we
+ can bring them arbitrarily close to 0.5. If we want the
+ probabilities to be within some delta d of 0.5, i.e. then
+
+ N
+ ( 0.5 + ( 0.5 * (2e) ) ) < 0.5 + d.
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 11]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ Solving for N yields N > log(2d)/log(2e). (Note that 2e is less than
+ 1, so its log is negative. Division by a negative number reverses
+ the sense of an inequality.)
+
+ The following table gives the length of the string which must be
+ sampled for various degrees of skew in order to come within 0.001 of
+ a 50/50 distribution.
+
+ +---------+--------+-------+
+ | Prob(1) | e | N |
+ +---------+--------+-------+
+ | 0.5 | 0.00 | 1 |
+ | 0.6 | 0.10 | 4 |
+ | 0.7 | 0.20 | 7 |
+ | 0.8 | 0.30 | 13 |
+ | 0.9 | 0.40 | 28 |
+ | 0.95 | 0.45 | 59 |
+ | 0.99 | 0.49 | 308 |
+ +---------+--------+-------+
+
+ The last entry shows that even if the distribution is skewed 99% in
+ favor of ones, the parity of a string of 308 samples will be within
+ 0.001 of a 50/50 distribution.
+
+5.2.2 Using Transition Mappings to De-Skew
+
+ Another technique, originally due to von Neumann [VON NEUMANN], is to
+ examine a bit stream as a sequence of non-overlapping pairs. You
+ could then discard any 00 or 11 pairs found, interpret 01 as a 0 and
+ 10 as a 1. Assume the probability of a 1 is 0.5+e and the
+ probability of a 0 is 0.5-e where e is the eccentricity of the source
+ and described in the previous section. Then the probability of each
+ pair is as follows:
+
+ +------+-----------------------------------------+
+ | pair | probability |
+ +------+-----------------------------------------+
+ | 00 | (0.5 - e)^2 = 0.25 - e + e^2 |
+ | 01 | (0.5 - e)*(0.5 + e) = 0.25 - e^2 |
+ | 10 | (0.5 + e)*(0.5 - e) = 0.25 - e^2 |
+ | 11 | (0.5 + e)^2 = 0.25 + e + e^2 |
+ +------+-----------------------------------------+
+
+ This technique will completely eliminate any bias but at the expense
+ of taking an indeterminate number of input bits for any particular
+ desired number of output bits. The probability of any particular
+ pair being discarded is 0.5 + 2e^2 so the expected number of input
+ bits to produce X output bits is X/(0.25 - e^2).
+
+
+
+Eastlake, Crocker & Schiller [Page 12]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ This technique assumes that the bits are from a stream where each bit
+ has the same probability of being a 0 or 1 as any other bit in the
+ stream and that bits are not correlated, i.e., that the bits are
+ identical independent distributions. If alternate bits were from two
+ correlated sources, for example, the above analysis breaks down.
+
+ The above technique also provides another illustration of how a
+ simple statistical analysis can mislead if one is not always on the
+ lookout for patterns that could be exploited by an adversary. If the
+ algorithm were mis-read slightly so that overlapping successive bits
+ pairs were used instead of non-overlapping pairs, the statistical
+ analysis given is the same; however, instead of provided an unbiased
+ uncorrelated series of random 1's and 0's, it instead produces a
+ totally predictable sequence of exactly alternating 1's and 0's.
+
+5.2.3 Using FFT to De-Skew
+
+ When real world data consists of strongly biased or correlated bits,
+ it may still contain useful amounts of randomness. This randomness
+ can be extracted through use of the discrete Fourier transform or its
+ optimized variant, the FFT.
+
+ Using the Fourier transform of the data, strong correlations can be
+ discarded. If adequate data is processed and remaining correlations
+ decay, spectral lines approaching statistical independence and
+ normally distributed randomness can be produced [BRILLINGER].
+
+5.2.4 Using Compression to De-Skew
+
+ Reversible compression techniques also provide a crude method of de-
+ skewing a skewed bit stream. This follows directly from the
+ definition of reversible compression and the formula in Section 2
+ above for the amount of information in a sequence. Since the
+ compression is reversible, the same amount of information must be
+ present in the shorter output than was present in the longer input.
+ By the Shannon information equation, this is only possible if, on
+ average, the probabilities of the different shorter sequences are
+ more uniformly distributed than were the probabilities of the longer
+ sequences. Thus the shorter sequences are de-skewed relative to the
+ input.
+
+ However, many compression techniques add a somewhat predicatable
+ preface to their output stream and may insert such a sequence again
+ periodically in their output or otherwise introduce subtle patterns
+ of their own. They should be considered only a rough technique
+ compared with those described above or in Section 6.1.2. At a
+ minimum, the beginning of the compressed sequence should be skipped
+ and only later bits used for applications requiring random bits.
+
+
+
+Eastlake, Crocker & Schiller [Page 13]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+5.3 Existing Hardware Can Be Used For Randomness
+
+ As described below, many computers come with hardware that can, with
+ care, be used to generate truly random quantities.
+
+5.3.1 Using Existing Sound/Video Input
+
+ Increasingly computers are being built with inputs that digitize some
+ real world analog source, such as sound from a microphone or video
+ input from a camera. Under appropriate circumstances, such input can
+ provide reasonably high quality random bits. The "input" from a
+ sound digitizer with no source plugged in or a camera with the lens
+ cap on, if the system has enough gain to detect anything, is
+ essentially thermal noise.
+
+ For example, on a SPARCstation, one can read from the /dev/audio
+ device with nothing plugged into the microphone jack. Such data is
+ essentially random noise although it should not be trusted without
+ some checking in case of hardware failure. It will, in any case,
+ need to be de-skewed as described elsewhere.
+
+ Combining this with compression to de-skew one can, in UNIXese,
+ generate a huge amount of medium quality random data by doing
+
+ cat /dev/audio | compress - >random-bits-file
+
+5.3.2 Using Existing Disk Drives
+
+ Disk drives have small random fluctuations in their rotational speed
+ due to chaotic air turbulence [DAVIS]. By adding low level disk seek
+ time instrumentation to a system, a series of measurements can be
+ obtained that include this randomness. Such data is usually highly
+ correlated so that significant processing is needed, including FFT
+ (see section 5.2.3). Nevertheless experimentation has shown that,
+ with such processing, disk drives easily produce 100 bits a minute or
+ more of excellent random data.
+
+ Partly offsetting this need for processing is the fact that disk
+ drive failure will normally be rapidly noticed. Thus, problems with
+ this method of random number generation due to hardware failure are
+ very unlikely.
+
+6. Recommended Non-Hardware Strategy
+
+ What is the best overall strategy for meeting the requirement for
+ unguessable random numbers in the absence of a reliable hardware
+ source? It is to obtain random input from a large number of
+ uncorrelated sources and to mix them with a strong mixing function.
+
+
+
+Eastlake, Crocker & Schiller [Page 14]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ Such a function will preserve the randomness present in any of the
+ sources even if other quantities being combined are fixed or easily
+ guessable. This may be advisable even with a good hardware source as
+ hardware can also fail, though this should be weighed against any
+ increase in the chance of overall failure due to added software
+ complexity.
+
+6.1 Mixing Functions
+
+ A strong mixing function is one which combines two or more inputs and
+ produces an output where each output bit is a different complex non-
+ linear function of all the input bits. On average, changing any
+ input bit will change about half the output bits. But because the
+ relationship is complex and non-linear, no particular output bit is
+ guaranteed to change when any particular input bit is changed.
+
+ Consider the problem of converting a stream of bits that is skewed
+ towards 0 or 1 to a shorter stream which is more random, as discussed
+ in Section 5.2 above. This is simply another case where a strong
+ mixing function is desired, mixing the input bits to produce a
+ smaller number of output bits. The technique given in Section 5.2.1
+ of using the parity of a number of bits is simply the result of
+ successively Exclusive Or'ing them which is examined as a trivial
+ mixing function immediately below. Use of stronger mixing functions
+ to extract more of the randomness in a stream of skewed bits is
+ examined in Section 6.1.2.
+
+6.1.1 A Trivial Mixing Function
+
+ A trivial example for single bit inputs is the Exclusive Or function,
+ which is equivalent to addition without carry, as show in the table
+ below. This is a degenerate case in which the one output bit always
+ changes for a change in either input bit. But, despite its
+ simplicity, it will still provide a useful illustration.
+
+ +-----------+-----------+----------+
+ | input 1 | input 2 | output |
+ +-----------+-----------+----------+
+ | 0 | 0 | 0 |
+ | 0 | 1 | 1 |
+ | 1 | 0 | 1 |
+ | 1 | 1 | 0 |
+ +-----------+-----------+----------+
+
+ If inputs 1 and 2 are uncorrelated and combined in this fashion then
+ the output will be an even better (less skewed) random bit than the
+ inputs. If we assume an "eccentricity" e as defined in Section 5.2
+ above, then the output eccentricity relates to the input eccentricity
+
+
+
+Eastlake, Crocker & Schiller [Page 15]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ as follows:
+
+ e = 2 * e * e
+ output input 1 input 2
+
+ Since e is never greater than 1/2, the eccentricity is always
+ improved except in the case where at least one input is a totally
+ skewed constant. This is illustrated in the following table where
+ the top and left side values are the two input eccentricities and the
+ entries are the output eccentricity:
+
+ +--------+--------+--------+--------+--------+--------+--------+
+ | e | 0.00 | 0.10 | 0.20 | 0.30 | 0.40 | 0.50 |
+ +--------+--------+--------+--------+--------+--------+--------+
+ | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
+ | 0.10 | 0.00 | 0.02 | 0.04 | 0.06 | 0.08 | 0.10 |
+ | 0.20 | 0.00 | 0.04 | 0.08 | 0.12 | 0.16 | 0.20 |
+ | 0.30 | 0.00 | 0.06 | 0.12 | 0.18 | 0.24 | 0.30 |
+ | 0.40 | 0.00 | 0.08 | 0.16 | 0.24 | 0.32 | 0.40 |
+ | 0.50 | 0.00 | 0.10 | 0.20 | 0.30 | 0.40 | 0.50 |
+ +--------+--------+--------+--------+--------+--------+--------+
+
+ However, keep in mind that the above calculations assume that the
+ inputs are not correlated. If the inputs were, say, the parity of
+ the number of minutes from midnight on two clocks accurate to a few
+ seconds, then each might appear random if sampled at random intervals
+ much longer than a minute. Yet if they were both sampled and
+ combined with xor, the result would be zero most of the time.
+
+6.1.2 Stronger Mixing Functions
+
+ The US Government Data Encryption Standard [DES] is an example of a
+ strong mixing function for multiple bit quantities. It takes up to
+ 120 bits of input (64 bits of "data" and 56 bits of "key") and
+ produces 64 bits of output each of which is dependent on a complex
+ non-linear function of all input bits. Other strong encryption
+ functions with this characteristic can also be used by considering
+ them to mix all of their key and data input bits.
+
+ Another good family of mixing functions are the "message digest" or
+ hashing functions such as The US Government Secure Hash Standard
+ [SHS] and the MD2, MD4, MD5 [MD2, MD4, MD5] series. These functions
+ all take an arbitrary amount of input and produce an output mixing
+ all the input bits. The MD* series produce 128 bits of output and SHS
+ produces 160 bits.
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 16]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ Although the message digest functions are designed for variable
+ amounts of input, DES and other encryption functions can also be used
+ to combine any number of inputs. If 64 bits of output is adequate,
+ the inputs can be packed into a 64 bit data quantity and successive
+ 56 bit keys, padding with zeros if needed, which are then used to
+ successively encrypt using DES in Electronic Codebook Mode [DES
+ MODES]. If more than 64 bits of output are needed, use more complex
+ mixing. For example, if inputs are packed into three quantities, A,
+ B, and C, use DES to encrypt A with B as a key and then with C as a
+ key to produce the 1st part of the output, then encrypt B with C and
+ then A for more output and, if necessary, encrypt C with A and then B
+ for yet more output. Still more output can be produced by reversing
+ the order of the keys given above to stretch things. The same can be
+ done with the hash functions by hashing various subsets of the input
+ data to produce multiple outputs. But keep in mind that it is
+ impossible to get more bits of "randomness" out than are put in.
+
+ An example of using a strong mixing function would be to reconsider
+ the case of a string of 308 bits each of which is biased 99% towards
+ zero. The parity technique given in Section 5.2.1 above reduced this
+ to one bit with only a 1/1000 deviance from being equally likely a
+ zero or one. But, applying the equation for information given in
+ Section 2, this 308 bit sequence has 5 bits of information in it.
+ Thus hashing it with SHS or MD5 and taking the bottom 5 bits of the
+ result would yield 5 unbiased random bits as opposed to the single
+ bit given by calculating the parity of the string.
+
+6.1.3 Diffie-Hellman as a Mixing Function
+
+ Diffie-Hellman exponential key exchange is a technique that yields a
+ shared secret between two parties that can be made computationally
+ infeasible for a third party to determine even if they can observe
+ all the messages between the two communicating parties. This shared
+ secret is a mixture of initial quantities generated by each of them
+ [D-H]. If these initial quantities are random, then the shared
+ secret contains the combined randomness of them both, assuming they
+ are uncorrelated.
+
+6.1.4 Using a Mixing Function to Stretch Random Bits
+
+ While it is not necessary for a mixing function to produce the same
+ or fewer bits than its inputs, mixing bits cannot "stretch" the
+ amount of random unpredictability present in the inputs. Thus four
+ inputs of 32 bits each where there is 12 bits worth of
+ unpredicatability (such as 4,096 equally probable values) in each
+ input cannot produce more than 48 bits worth of unpredictable output.
+ The output can be expanded to hundreds or thousands of bits by, for
+ example, mixing with successive integers, but the clever adversary's
+
+
+
+Eastlake, Crocker & Schiller [Page 17]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ search space is still 2^48 possibilities. Furthermore, mixing to
+ fewer bits than are input will tend to strengthen the randomness of
+ the output the way using Exclusive Or to produce one bit from two did
+ above.
+
+ The last table in Section 6.1.1 shows that mixing a random bit with a
+ constant bit with Exclusive Or will produce a random bit. While this
+ is true, it does not provide a way to "stretch" one random bit into
+ more than one. If, for example, a random bit is mixed with a 0 and
+ then with a 1, this produces a two bit sequence but it will always be
+ either 01 or 10. Since there are only two possible values, there is
+ still only the one bit of original randomness.
+
+6.1.5 Other Factors in Choosing a Mixing Function
+
+ For local use, DES has the advantages that it has been widely tested
+ for flaws, is widely documented, and is widely implemented with
+ hardware and software implementations available all over the world
+ including source code available by anonymous FTP. The SHS and MD*
+ family are younger algorithms which have been less tested but there
+ is no particular reason to believe they are flawed. Both MD5 and SHS
+ were derived from the earlier MD4 algorithm. They all have source
+ code available by anonymous FTP [SHS, MD2, MD4, MD5].
+
+ DES and SHS have been vouched for the the US National Security Agency
+ (NSA) on the basis of criteria that primarily remain secret. While
+ this is the cause of much speculation and doubt, investigation of DES
+ over the years has indicated that NSA involvement in modifications to
+ its design, which originated with IBM, was primarily to strengthen
+ it. No concealed or special weakness has been found in DES. It is
+ almost certain that the NSA modification to MD4 to produce the SHS
+ similarly strengthened the algorithm, possibly against threats not
+ yet known in the public cryptographic community.
+
+ DES, SHS, MD4, and MD5 are royalty free for all purposes. MD2 has
+ been freely licensed only for non-profit use in connection with
+ Privacy Enhanced Mail [PEM]. Between the MD* algorithms, some people
+ believe that, as with "Goldilocks and the Three Bears", MD2 is strong
+ but too slow, MD4 is fast but too weak, and MD5 is just right.
+
+ Another advantage of the MD* or similar hashing algorithms over
+ encryption algorithms is that they are not subject to the same
+ regulations imposed by the US Government prohibiting the unlicensed
+ export or import of encryption/decryption software and hardware. The
+ same should be true of DES rigged to produce an irreversible hash
+ code but most DES packages are oriented to reversible encryption.
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 18]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+6.2 Non-Hardware Sources of Randomness
+
+ The best source of input for mixing would be a hardware randomness
+ such as disk drive timing affected by air turbulence, audio input
+ with thermal noise, or radioactive decay. However, if that is not
+ available there are other possibilities. These include system
+ clocks, system or input/output buffers, user/system/hardware/network
+ serial numbers and/or addresses and timing, and user input.
+ Unfortunately, any of these sources can produce limited or
+ predicatable values under some circumstances.
+
+ Some of the sources listed above would be quite strong on multi-user
+ systems where, in essence, each user of the system is a source of
+ randomness. However, on a small single user system, such as a
+ typical IBM PC or Apple Macintosh, it might be possible for an
+ adversary to assemble a similar configuration. This could give the
+ adversary inputs to the mixing process that were sufficiently
+ correlated to those used originally as to make exhaustive search
+ practical.
+
+ The use of multiple random inputs with a strong mixing function is
+ recommended and can overcome weakness in any particular input. For
+ example, the timing and content of requested "random" user keystrokes
+ can yield hundreds of random bits but conservative assumptions need
+ to be made. For example, assuming a few bits of randomness if the
+ inter-keystroke interval is unique in the sequence up to that point
+ and a similar assumption if the key hit is unique but assuming that
+ no bits of randomness are present in the initial key value or if the
+ timing or key value duplicate previous values. The results of mixing
+ these timings and characters typed could be further combined with
+ clock values and other inputs.
+
+ This strategy may make practical portable code to produce good random
+ numbers for security even if some of the inputs are very weak on some
+ of the target systems. However, it may still fail against a high
+ grade attack on small single user systems, especially if the
+ adversary has ever been able to observe the generation process in the
+ past. A hardware based random source is still preferable.
+
+6.3 Cryptographically Strong Sequences
+
+ In cases where a series of random quantities must be generated, an
+ adversary may learn some values in the sequence. In general, they
+ should not be able to predict other values from the ones that they
+ know.
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 19]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ The correct technique is to start with a strong random seed, take
+ cryptographically strong steps from that seed [CRYPTO2, CRYPTO3], and
+ do not reveal the complete state of the generator in the sequence
+ elements. If each value in the sequence can be calculated in a fixed
+ way from the previous value, then when any value is compromised, all
+ future values can be determined. This would be the case, for
+ example, if each value were a constant function of the previously
+ used values, even if the function were a very strong, non-invertible
+ message digest function.
+
+ It should be noted that if your technique for generating a sequence
+ of key values is fast enough, it can trivially be used as the basis
+ for a confidentiality system. If two parties use the same sequence
+ generating technique and start with the same seed material, they will
+ generate identical sequences. These could, for example, be xor'ed at
+ one end with data being send, encrypting it, and xor'ed with this
+ data as received, decrypting it due to the reversible properties of
+ the xor operation.
+
+6.3.1 Traditional Strong Sequences
+
+ A traditional way to achieve a strong sequence has been to have the
+ values be produced by hashing the quantities produced by
+ concatenating the seed with successive integers or the like and then
+ mask the values obtained so as to limit the amount of generator state
+ available to the adversary.
+
+ It may also be possible to use an "encryption" algorithm with a
+ random key and seed value to encrypt and feedback some or all of the
+ output encrypted value into the value to be encrypted for the next
+ iteration. Appropriate feedback techniques will usually be
+ recommended with the encryption algorithm. An example is shown below
+ where shifting and masking are used to combine the cypher output
+ feedback. This type of feedback is recommended by the US Government
+ in connection with DES [DES MODES].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 20]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ +---------------+
+ | V |
+ | | n |
+ +--+------------+
+ | | +---------+
+ | +---------> | | +-----+
+ +--+ | Encrypt | <--- | Key |
+ | +-------- | | +-----+
+ | | +---------+
+ V V
+ +------------+--+
+ | V | |
+ | n+1 |
+ +---------------+
+
+ Note that if a shift of one is used, this is the same as the shift
+ register technique described in Section 3 above but with the all
+ important difference that the feedback is determined by a complex
+ non-linear function of all bits rather than a simple linear or
+ polynomial combination of output from a few bit position taps.
+
+ It has been shown by Donald W. Davies that this sort of shifted
+ partial output feedback significantly weakens an algorithm compared
+ will feeding all of the output bits back as input. In particular,
+ for DES, repeated encrypting a full 64 bit quantity will give an
+ expected repeat in about 2^63 iterations. Feeding back anything less
+ than 64 (and more than 0) bits will give an expected repeat in
+ between 2**31 and 2**32 iterations!
+
+ To predict values of a sequence from others when the sequence was
+ generated by these techniques is equivalent to breaking the
+ cryptosystem or inverting the "non-invertible" hashing involved with
+ only partial information available. The less information revealed
+ each iteration, the harder it will be for an adversary to predict the
+ sequence. Thus it is best to use only one bit from each value. It
+ has been shown that in some cases this makes it impossible to break a
+ system even when the cryptographic system is invertible and can be
+ broken if all of each generated value was revealed.
+
+6.3.2 The Blum Blum Shub Sequence Generator
+
+ Currently the generator which has the strongest public proof of
+ strength is called the Blum Blum Shub generator after its inventors
+ [BBS]. It is also very simple and is based on quadratic residues.
+ It's only disadvantage is that is is computationally intensive
+ compared with the traditional techniques give in 6.3.1 above. This
+ is not a serious draw back if it is used for moderately infrequent
+ purposes, such as generating session keys.
+
+
+
+Eastlake, Crocker & Schiller [Page 21]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ Simply choose two large prime numbers, say p and q, which both have
+ the property that you get a remainder of 3 if you divide them by 4.
+ Let n = p * q. Then you choose a random number x relatively prime to
+ n. The initial seed for the generator and the method for calculating
+ subsequent values are then
+
+ 2
+ s = ( x )(Mod n)
+ 0
+
+ 2
+ s = ( s )(Mod n)
+ i+1 i
+
+ You must be careful to use only a few bits from the bottom of each s.
+ It is always safe to use only the lowest order bit. If you use no
+ more than the
+
+ log ( log ( s ) )
+ 2 2 i
+
+ low order bits, then predicting any additional bits from a sequence
+ generated in this manner is provable as hard as factoring n. As long
+ as the initial x is secret, you can even make n public if you want.
+
+ An intersting characteristic of this generator is that you can
+ directly calculate any of the s values. In particular
+
+ i
+ ( ( 2 )(Mod (( p - 1 ) * ( q - 1 )) ) )
+ s = ( s )(Mod n)
+ i 0
+
+ This means that in applications where many keys are generated in this
+ fashion, it is not necessary to save them all. Each key can be
+ effectively indexed and recovered from that small index and the
+ initial s and n.
+
+7. Key Generation Standards
+
+ Several public standards are now in place for the generation of keys.
+ Two of these are described below. Both use DES but any equally
+ strong or stronger mixing function could be substituted.
+
+
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 22]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+7.1 US DoD Recommendations for Password Generation
+
+ The United States Department of Defense has specific recommendations
+ for password generation [DoD]. They suggest using the US Data
+ Encryption Standard [DES] in Output Feedback Mode [DES MODES] as
+ follows:
+
+ use an initialization vector determined from
+ the system clock,
+ system ID,
+ user ID, and
+ date and time;
+ use a key determined from
+ system interrupt registers,
+ system status registers, and
+ system counters; and,
+ as plain text, use an external randomly generated 64 bit
+ quantity such as 8 characters typed in by a system
+ administrator.
+
+ The password can then be calculated from the 64 bit "cipher text"
+ generated in 64-bit Output Feedback Mode. As many bits as are needed
+ can be taken from these 64 bits and expanded into a pronounceable
+ word, phrase, or other format if a human being needs to remember the
+ password.
+
+7.2 X9.17 Key Generation
+
+ The American National Standards Institute has specified a method for
+ generating a sequence of keys as follows:
+
+ s is the initial 64 bit seed
+ 0
+
+ g is the sequence of generated 64 bit key quantities
+ n
+
+ k is a random key reserved for generating this key sequence
+
+ t is the time at which a key is generated to as fine a resolution
+ as is available (up to 64 bits).
+
+ DES ( K, Q ) is the DES encryption of quantity Q with key K
+
+
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 23]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ g = DES ( k, DES ( k, t ) .xor. s )
+ n n
+
+ s = DES ( k, DES ( k, t ) .xor. g )
+ n+1 n
+
+ If g sub n is to be used as a DES key, then every eighth bit should
+ be adjusted for parity for that use but the entire 64 bit unmodified
+ g should be used in calculating the next s.
+
+8. Examples of Randomness Required
+
+ Below are two examples showing rough calculations of needed
+ randomness for security. The first is for moderate security
+ passwords while the second assumes a need for a very high security
+ cryptographic key.
+
+8.1 Password Generation
+
+ Assume that user passwords change once a year and it is desired that
+ the probability that an adversary could guess the password for a
+ particular account be less than one in a thousand. Further assume
+ that sending a password to the system is the only way to try a
+ password. Then the crucial question is how often an adversary can
+ try possibilities. Assume that delays have been introduced into a
+ system so that, at most, an adversary can make one password try every
+ six seconds. That's 600 per hour or about 15,000 per day or about
+ 5,000,000 tries in a year. Assuming any sort of monitoring, it is
+ unlikely someone could actually try continuously for a year. In
+ fact, even if log files are only checked monthly, 500,000 tries is
+ more plausible before the attack is noticed and steps taken to change
+ passwords and make it harder to try more passwords.
+
+ To have a one in a thousand chance of guessing the password in
+ 500,000 tries implies a universe of at least 500,000,000 passwords or
+ about 2^29. Thus 29 bits of randomness are needed. This can probably
+ be achieved using the US DoD recommended inputs for password
+ generation as it has 8 inputs which probably average over 5 bits of
+ randomness each (see section 7.1). Using a list of 1000 words, the
+ password could be expressed as a three word phrase (1,000,000,000
+ possibilities) or, using case insensitive letters and digits, six
+ would suffice ((26+10)^6 = 2,176,782,336 possibilities).
+
+ For a higher security password, the number of bits required goes up.
+ To decrease the probability by 1,000 requires increasing the universe
+ of passwords by the same factor which adds about 10 bits. Thus to
+ have only a one in a million chance of a password being guessed under
+ the above scenario would require 39 bits of randomness and a password
+
+
+
+Eastlake, Crocker & Schiller [Page 24]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ that was a four word phrase from a 1000 word list or eight
+ letters/digits. To go to a one in 10^9 chance, 49 bits of randomness
+ are needed implying a five word phrase or ten letter/digit password.
+
+ In a real system, of course, there are also other factors. For
+ example, the larger and harder to remember passwords are, the more
+ likely users are to write them down resulting in an additional risk
+ of compromise.
+
+8.2 A Very High Security Cryptographic Key
+
+ Assume that a very high security key is needed for symmetric
+ encryption / decryption between two parties. Assume an adversary can
+ observe communications and knows the algorithm being used. Within
+ the field of random possibilities, the adversary can try key values
+ in hopes of finding the one in use. Assume further that brute force
+ trial of keys is the best the adversary can do.
+
+8.2.1 Effort per Key Trial
+
+ How much effort will it take to try each key? For very high security
+ applications it is best to assume a low value of effort. Even if it
+ would clearly take tens of thousands of computer cycles or more to
+ try a single key, there may be some pattern that enables huge blocks
+ of key values to be tested with much less effort per key. Thus it is
+ probably best to assume no more than a couple hundred cycles per key.
+ (There is no clear lower bound on this as computers operate in
+ parallel on a number of bits and a poor encryption algorithm could
+ allow many keys or even groups of keys to be tested in parallel.
+ However, we need to assume some value and can hope that a reasonably
+ strong algorithm has been chosen for our hypothetical high security
+ task.)
+
+ If the adversary can command a highly parallel processor or a large
+ network of work stations, 2*10^10 cycles per second is probably a
+ minimum assumption for availability today. Looking forward just a
+ couple years, there should be at least an order of magnitude
+ improvement. Thus assuming 10^9 keys could be checked per second or
+ 3.6*10^11 per hour or 6*10^13 per week or 2.4*10^14 per month is
+ reasonable. This implies a need for a minimum of 51 bits of
+ randomness in keys to be sure they cannot be found in a month. Even
+ then it is possible that, a few years from now, a highly determined
+ and resourceful adversary could break the key in 2 weeks (on average
+ they need try only half the keys).
+
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 25]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+8.2.2 Meet in the Middle Attacks
+
+ If chosen or known plain text and the resulting encrypted text are
+ available, a "meet in the middle" attack is possible if the structure
+ of the encryption algorithm allows it. (In a known plain text
+ attack, the adversary knows all or part of the messages being
+ encrypted, possibly some standard header or trailer fields. In a
+ chosen plain text attack, the adversary can force some chosen plain
+ text to be encrypted, possibly by "leaking" an exciting text that
+ would then be sent by the adversary over an encrypted channel.)
+
+ An oversimplified explanation of the meet in the middle attack is as
+ follows: the adversary can half-encrypt the known or chosen plain
+ text with all possible first half-keys, sort the output, then half-
+ decrypt the encoded text with all the second half-keys. If a match
+ is found, the full key can be assembled from the halves and used to
+ decrypt other parts of the message or other messages. At its best,
+ this type of attack can halve the exponent of the work required by
+ the adversary while adding a large but roughly constant factor of
+ effort. To be assured of safety against this, a doubling of the
+ amount of randomness in the key to a minimum of 102 bits is required.
+
+ The meet in the middle attack assumes that the cryptographic
+ algorithm can be decomposed in this way but we can not rule that out
+ without a deep knowledge of the algorithm. Even if a basic algorithm
+ is not subject to a meet in the middle attack, an attempt to produce
+ a stronger algorithm by applying the basic algorithm twice (or two
+ different algorithms sequentially) with different keys may gain less
+ added security than would be expected. Such a composite algorithm
+ would be subject to a meet in the middle attack.
+
+ Enormous resources may be required to mount a meet in the middle
+ attack but they are probably within the range of the national
+ security services of a major nation. Essentially all nations spy on
+ other nations government traffic and several nations are believed to
+ spy on commercial traffic for economic advantage.
+
+8.2.3 Other Considerations
+
+ Since we have not even considered the possibilities of special
+ purpose code breaking hardware or just how much of a safety margin we
+ want beyond our assumptions above, probably a good minimum for a very
+ high security cryptographic key is 128 bits of randomness which
+ implies a minimum key length of 128 bits. If the two parties agree
+ on a key by Diffie-Hellman exchange [D-H], then in principle only
+ half of this randomness would have to be supplied by each party.
+ However, there is probably some correlation between their random
+ inputs so it is probably best to assume that each party needs to
+
+
+
+Eastlake, Crocker & Schiller [Page 26]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ provide at least 96 bits worth of randomness for very high security
+ if Diffie-Hellman is used.
+
+ This amount of randomness is beyond the limit of that in the inputs
+ recommended by the US DoD for password generation and could require
+ user typing timing, hardware random number generation, or other
+ sources.
+
+ It should be noted that key length calculations such at those above
+ are controversial and depend on various assumptions about the
+ cryptographic algorithms in use. In some cases, a professional with
+ a deep knowledge of code breaking techniques and of the strength of
+ the algorithm in use could be satisfied with less than half of the
+ key size derived above.
+
+9. Conclusion
+
+ Generation of unguessable "random" secret quantities for security use
+ is an essential but difficult task.
+
+ We have shown that hardware techniques to produce such randomness
+ would be relatively simple. In particular, the volume and quality
+ would not need to be high and existing computer hardware, such as
+ disk drives, can be used. Computational techniques are available to
+ process low quality random quantities from multiple sources or a
+ larger quantity of such low quality input from one source and produce
+ a smaller quantity of higher quality, less predictable key material.
+ In the absence of hardware sources of randomness, a variety of user
+ and software sources can frequently be used instead with care;
+ however, most modern systems already have hardware, such as disk
+ drives or audio input, that could be used to produce high quality
+ randomness.
+
+ Once a sufficient quantity of high quality seed key material (a few
+ hundred bits) is available, strong computational techniques are
+ available to produce cryptographically strong sequences of
+ unpredicatable quantities from this seed material.
+
+10. Security Considerations
+
+ The entirety of this document concerns techniques and recommendations
+ for generating unguessable "random" quantities for use as passwords,
+ cryptographic keys, and similar security uses.
+
+
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 27]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+References
+
+ [ASYMMETRIC] - Secure Communications and Asymmetric Cryptosystems,
+ edited by Gustavus J. Simmons, AAAS Selected Symposium 69, Westview
+ Press, Inc.
+
+ [BBS] - A Simple Unpredictable Pseudo-Random Number Generator, SIAM
+ Journal on Computing, v. 15, n. 2, 1986, L. Blum, M. Blum, & M. Shub.
+
+ [BRILLINGER] - Time Series: Data Analysis and Theory, Holden-Day,
+ 1981, David Brillinger.
+
+ [CRC] - C.R.C. Standard Mathematical Tables, Chemical Rubber
+ Publishing Company.
+
+ [CRYPTO1] - Cryptography: A Primer, A Wiley-Interscience Publication,
+ John Wiley & Sons, 1981, Alan G. Konheim.
+
+ [CRYPTO2] - Cryptography: A New Dimension in Computer Data Security,
+ A Wiley-Interscience Publication, John Wiley & Sons, 1982, Carl H.
+ Meyer & Stephen M. Matyas.
+
+ [CRYPTO3] - Applied Cryptography: Protocols, Algorithms, and Source
+ Code in C, John Wiley & Sons, 1994, Bruce Schneier.
+
+ [DAVIS] - Cryptographic Randomness from Air Turbulence in Disk
+ Drives, Advances in Cryptology - Crypto '94, Springer-Verlag Lecture
+ Notes in Computer Science #839, 1984, Don Davis, Ross Ihaka, and
+ Philip Fenstermacher.
+
+ [DES] - Data Encryption Standard, United States of America,
+ Department of Commerce, National Institute of Standards and
+ Technology, Federal Information Processing Standard (FIPS) 46-1.
+ - Data Encryption Algorithm, American National Standards Institute,
+ ANSI X3.92-1981.
+ (See also FIPS 112, Password Usage, which includes FORTRAN code for
+ performing DES.)
+
+ [DES MODES] - DES Modes of Operation, United States of America,
+ Department of Commerce, National Institute of Standards and
+ Technology, Federal Information Processing Standard (FIPS) 81.
+ - Data Encryption Algorithm - Modes of Operation, American National
+ Standards Institute, ANSI X3.106-1983.
+
+ [D-H] - New Directions in Cryptography, IEEE Transactions on
+ Information Technology, November, 1976, Whitfield Diffie and Martin
+ E. Hellman.
+
+
+
+
+Eastlake, Crocker & Schiller [Page 28]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ [DoD] - Password Management Guideline, United States of America,
+ Department of Defense, Computer Security Center, CSC-STD-002-85.
+ (See also FIPS 112, Password Usage, which incorporates CSC-STD-002-85
+ as one of its appendices.)
+
+ [GIFFORD] - Natural Random Number, MIT/LCS/TM-371, September 1988,
+ David K. Gifford
+
+ [KNUTH] - The Art of Computer Programming, Volume 2: Seminumerical
+ Algorithms, Chapter 3: Random Numbers. Addison Wesley Publishing
+ Company, Second Edition 1982, Donald E. Knuth.
+
+ [KRAWCZYK] - How to Predict Congruential Generators, Journal of
+ Algorithms, V. 13, N. 4, December 1992, H. Krawczyk
+
+ [MD2] - The MD2 Message-Digest Algorithm, RFC1319, April 1992, B.
+ Kaliski
+ [MD4] - The MD4 Message-Digest Algorithm, RFC1320, April 1992, R.
+ Rivest
+ [MD5] - The MD5 Message-Digest Algorithm, RFC1321, April 1992, R.
+ Rivest
+
+ [PEM] - RFCs 1421 through 1424:
+ - RFC 1424, Privacy Enhancement for Internet Electronic Mail: Part
+ IV: Key Certification and Related Services, 02/10/1993, B. Kaliski
+ - RFC 1423, Privacy Enhancement for Internet Electronic Mail: Part
+ III: Algorithms, Modes, and Identifiers, 02/10/1993, D. Balenson
+ - RFC 1422, Privacy Enhancement for Internet Electronic Mail: Part
+ II: Certificate-Based Key Management, 02/10/1993, S. Kent
+ - RFC 1421, Privacy Enhancement for Internet Electronic Mail: Part I:
+ Message Encryption and Authentication Procedures, 02/10/1993, J. Linn
+
+ [SHANNON] - The Mathematical Theory of Communication, University of
+ Illinois Press, 1963, Claude E. Shannon. (originally from: Bell
+ System Technical Journal, July and October 1948)
+
+ [SHIFT1] - Shift Register Sequences, Aegean Park Press, Revised
+ Edition 1982, Solomon W. Golomb.
+
+ [SHIFT2] - Cryptanalysis of Shift-Register Generated Stream Cypher
+ Systems, Aegean Park Press, 1984, Wayne G. Barker.
+
+ [SHS] - Secure Hash Standard, United States of American, National
+ Institute of Science and Technology, Federal Information Processing
+ Standard (FIPS) 180, April 1993.
+
+ [STERN] - Secret Linear Congruential Generators are not
+ Cryptograhically Secure, Proceedings of IEEE STOC, 1987, J. Stern.
+
+
+
+Eastlake, Crocker & Schiller [Page 29]
+
+RFC 1750 Randomness Recommendations for Security December 1994
+
+
+ [VON NEUMANN] - Various techniques used in connection with random
+ digits, von Neumann's Collected Works, Vol. 5, Pergamon Press, 1963,
+ J. von Neumann.
+
+Authors' Addresses
+
+ Donald E. Eastlake 3rd
+ Digital Equipment Corporation
+ 550 King Street, LKG2-1/BB3
+ Littleton, MA 01460
+
+ Phone: +1 508 486 6577(w) +1 508 287 4877(h)
+ EMail: dee@lkg.dec.com
+
+
+ Stephen D. Crocker
+ CyberCash Inc.
+ 2086 Hunters Crest Way
+ Vienna, VA 22181
+
+ Phone: +1 703-620-1222(w) +1 703-391-2651 (fax)
+ EMail: crocker@cybercash.com
+
+
+ Jeffrey I. Schiller
+ Massachusetts Institute of Technology
+ 77 Massachusetts Avenue
+ Cambridge, MA 02139
+
+ Phone: +1 617 253 0161(w)
+ EMail: jis@mit.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake, Crocker & Schiller [Page 30]
+
diff --git a/doc/rfc/rfc1876.txt b/doc/rfc/rfc1876.txt
new file mode 100644
index 0000000..a289cff
--- /dev/null
+++ b/doc/rfc/rfc1876.txt
@@ -0,0 +1,1011 @@
+
+
+
+
+
+
+Network Working Group C. Davis
+Request for Comments: 1876 Kapor Enterprises
+Updates: 1034, 1035 P. Vixie
+Category: Experimental Vixie Enterprises
+ T. Goodwin
+ FORE Systems
+ I. Dickinson
+ University of Warwick
+ January 1996
+
+
+ A Means for Expressing Location Information in the Domain Name System
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. This memo does not specify an Internet standard of any
+ kind. Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+1. Abstract
+
+ This memo defines a new DNS RR type for experimental purposes. This
+ RFC describes a mechanism to allow the DNS to carry location
+ information about hosts, networks, and subnets. Such information for
+ a small subset of hosts is currently contained in the flat-file UUCP
+ maps. However, just as the DNS replaced the use of HOSTS.TXT to
+ carry host and network address information, it is possible to replace
+ the UUCP maps as carriers of location information.
+
+ This RFC defines the format of a new Resource Record (RR) for the
+ Domain Name System (DNS), and reserves a corresponding DNS type
+ mnemonic (LOC) and numerical code (29).
+
+ This RFC assumes that the reader is familiar with the DNS [RFC 1034,
+ RFC 1035]. The data shown in our examples is for pedagogical use and
+ does not necessarily reflect the real Internet.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Davis, et al Experimental [Page 1]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+2. RDATA Format
+
+ MSB LSB
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 0| VERSION | SIZE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 2| HORIZ PRE | VERT PRE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 4| LATITUDE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 6| LATITUDE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 8| LONGITUDE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 10| LONGITUDE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 12| ALTITUDE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 14| ALTITUDE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ (octet)
+
+where:
+
+VERSION Version number of the representation. This must be zero.
+ Implementations are required to check this field and make
+ no assumptions about the format of unrecognized versions.
+
+SIZE The diameter of a sphere enclosing the described entity, in
+ centimeters, expressed as a pair of four-bit unsigned
+ integers, each ranging from zero to nine, with the most
+ significant four bits representing the base and the second
+ number representing the power of ten by which to multiply
+ the base. This allows sizes from 0e0 (<1cm) to 9e9
+ (90,000km) to be expressed. This representation was chosen
+ such that the hexadecimal representation can be read by
+ eye; 0x15 = 1e5. Four-bit values greater than 9 are
+ undefined, as are values with a base of zero and a non-zero
+ exponent.
+
+ Since 20000000m (represented by the value 0x29) is greater
+ than the equatorial diameter of the WGS 84 ellipsoid
+ (12756274m), it is therefore suitable for use as a
+ "worldwide" size.
+
+HORIZ PRE The horizontal precision of the data, in centimeters,
+ expressed using the same representation as SIZE. This is
+ the diameter of the horizontal "circle of error", rather
+
+
+
+Davis, et al Experimental [Page 2]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ than a "plus or minus" value. (This was chosen to match
+ the interpretation of SIZE; to get a "plus or minus" value,
+ divide by 2.)
+
+VERT PRE The vertical precision of the data, in centimeters,
+ expressed using the sane representation as for SIZE. This
+ is the total potential vertical error, rather than a "plus
+ or minus" value. (This was chosen to match the
+ interpretation of SIZE; to get a "plus or minus" value,
+ divide by 2.) Note that if altitude above or below sea
+ level is used as an approximation for altitude relative to
+ the [WGS 84] ellipsoid, the precision value should be
+ adjusted.
+
+LATITUDE The latitude of the center of the sphere described by the
+ SIZE field, expressed as a 32-bit integer, most significant
+ octet first (network standard byte order), in thousandths
+ of a second of arc. 2^31 represents the equator; numbers
+ above that are north latitude.
+
+LONGITUDE The longitude of the center of the sphere described by the
+ SIZE field, expressed as a 32-bit integer, most significant
+ octet first (network standard byte order), in thousandths
+ of a second of arc, rounded away from the prime meridian.
+ 2^31 represents the prime meridian; numbers above that are
+ east longitude.
+
+ALTITUDE The altitude of the center of the sphere described by the
+ SIZE field, expressed as a 32-bit integer, most significant
+ octet first (network standard byte order), in centimeters,
+ from a base of 100,000m below the [WGS 84] reference
+ spheroid used by GPS (semimajor axis a=6378137.0,
+ reciprocal flattening rf=298.257223563). Altitude above
+ (or below) sea level may be used as an approximation of
+ altitude relative to the the [WGS 84] spheroid, though due
+ to the Earth's surface not being a perfect spheroid, there
+ will be differences. (For example, the geoid (which sea
+ level approximates) for the continental US ranges from 10
+ meters to 50 meters below the [WGS 84] spheroid.
+ Adjustments to ALTITUDE and/or VERT PRE will be necessary
+ in most cases. The Defense Mapping Agency publishes geoid
+ height values relative to the [WGS 84] ellipsoid.
+
+
+
+
+
+
+
+
+
+Davis, et al Experimental [Page 3]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+3. Master File Format
+
+ The LOC record is expressed in a master file in the following format:
+
+ <owner> <TTL> <class> LOC ( d1 [m1 [s1]] {"N"|"S"} d2 [m2 [s2]]
+ {"E"|"W"} alt["m"] [siz["m"] [hp["m"]
+ [vp["m"]]]] )
+
+ (The parentheses are used for multi-line data as specified in [RFC
+ 1035] section 5.1.)
+
+ where:
+
+ d1: [0 .. 90] (degrees latitude)
+ d2: [0 .. 180] (degrees longitude)
+ m1, m2: [0 .. 59] (minutes latitude/longitude)
+ s1, s2: [0 .. 59.999] (seconds latitude/longitude)
+ alt: [-100000.00 .. 42849672.95] BY .01 (altitude in meters)
+ siz, hp, vp: [0 .. 90000000.00] (size/precision in meters)
+
+ If omitted, minutes and seconds default to zero, size defaults to 1m,
+ horizontal precision defaults to 10000m, and vertical precision
+ defaults to 10m. These defaults are chosen to represent typical
+ ZIP/postal code area sizes, since it is often easy to find
+ approximate geographical location by ZIP/postal code.
+
+4. Example Data
+
+;;;
+;;; note that these data would not all appear in one zone file
+;;;
+
+;; network LOC RR derived from ZIP data. note use of precision defaults
+cambridge-net.kei.com. LOC 42 21 54 N 71 06 18 W -24m 30m
+
+;; higher-precision host LOC RR. note use of vertical precision default
+loiosh.kei.com. LOC 42 21 43.952 N 71 5 6.344 W
+ -24m 1m 200m
+
+pipex.net. LOC 52 14 05 N 00 08 50 E 10m
+
+curtin.edu.au. LOC 32 7 19 S 116 2 25 E 10m
+
+rwy04L.logan-airport.boston. LOC 42 21 28.764 N 71 00 51.617 W
+ -44m 2000m
+
+
+
+
+
+
+Davis, et al Experimental [Page 4]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+5. Application use of the LOC RR
+
+5.1 Suggested Uses
+
+ Some uses for the LOC RR have already been suggested, including the
+ USENET backbone flow maps, a "visual traceroute" application showing
+ the geographical path of an IP packet, and network management
+ applications that could use LOC RRs to generate a map of hosts and
+ routers being managed.
+
+5.2 Search Algorithms
+
+ This section specifies how to use the DNS to translate domain names
+ and/or IP addresses into location information.
+
+ If an application wishes to have a "fallback" behavior, displaying a
+ less precise or larger area when a host does not have an associated
+ LOC RR, it MAY support use of the algorithm in section 5.2.3, as
+ noted in sections 5.2.1 and 5.2.2. If fallback is desired, this
+ behaviour is the RECOMMENDED default, but in some cases it may need
+ to be modified based on the specific requirements of the application
+ involved.
+
+ This search algorithm is designed to allow network administrators to
+ specify the location of a network or subnet without requiring LOC RR
+ data for each individual host. For example, a computer lab with 24
+ workstations, all of which are on the same subnet and in basically
+ the same location, would only need a LOC RR for the subnet.
+ (However, if the file server's location has been more precisely
+ measured, a separate LOC RR for it can be placed in the DNS.)
+
+5.2.1 Searching by Name
+
+ If the application is beginning with a name, rather than an IP
+ address (as the USENET backbone flow maps do), it MUST check for a
+ LOC RR associated with that name. (CNAME records should be followed
+ as for any other RR type.)
+
+ If there is no LOC RR for that name, all A records (if any)
+ associated with the name MAY be checked for network (or subnet) LOC
+ RRs using the "Searching by Network or Subnet" algorithm (5.2.3). If
+ multiple A records exist and have associated network or subnet LOC
+ RRs, the application may choose to use any, some, or all of the LOC
+ RRs found, possibly in combination. It is suggested that multi-homed
+ hosts have LOC RRs for their name in the DNS to avoid any ambiguity
+ in these cases.
+
+
+
+
+
+Davis, et al Experimental [Page 5]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ Note that domain names that do not have associated A records must
+ have a LOC RR associated with their name in order for location
+ information to be accessible.
+
+5.2.2 Searching by Address
+
+ If the application is beginning with an IP address (as a "visual
+ traceroute" application might be) it MUST first map the address to a
+ name using the IN-ADDR.ARPA namespace (see [RFC 1034], section
+ 5.2.1), then check for a LOC RR associated with that name.
+
+ If there is no LOC RR for the name, the address MAY be checked for
+ network (or subnet) LOC RRs using the "Searching by Network or
+ Subnet" algorithm (5.2.3).
+
+5.2.3 Searching by Network or Subnet
+
+ Even if a host's name does not have any associated LOC RRs, the
+ network(s) or subnet(s) it is on may. If the application wishes to
+ search for such less specific data, the following algorithm SHOULD be
+ followed to find a network or subnet LOC RR associated with the IP
+ address. This algorithm is adapted slightly from that specified in
+ [RFC 1101], sections 4.3 and 4.4.
+
+ Since subnet LOC RRs are (if present) more specific than network LOC
+ RRs, it is best to use them if available. In order to do so, we
+ build a stack of network and subnet names found while performing the
+ [RFC 1101] search, then work our way down the stack until a LOC RR is
+ found.
+
+ 1. create a host-zero address using the network portion of the IP
+ address (one, two, or three bytes for class A, B, or C networks,
+ respectively). For example, for the host 128.9.2.17, on the class
+ B network 128.9, this would result in the address "128.9.0.0".
+
+ 2. Reverse the octets, suffix IN-ADDR.ARPA, and query for PTR and A
+ records. Retrieve:
+
+ 0.0.9.128.IN-ADDR.ARPA. PTR isi-net.isi.edu.
+ A 255.255.255.0
+
+ Push the name "isi-net.isi.edu" onto the stack of names to be
+ searched for LOC RRs later.
+
+
+
+
+
+
+
+
+Davis, et al Experimental [Page 6]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ 3. Since an A RR was found, repeat using mask from RR
+ (255.255.255.0), constructing a query for 0.2.9.128.IN-ADDR.ARPA.
+ Retrieve:
+
+ 0.2.9.128.IN-ADDR.ARPA. PTR div2-subnet.isi.edu.
+ A 255.255.255.240
+
+ Push the name "div2-subnet.isi.edu" onto the stack of names to be
+ searched for LOC RRs later.
+
+ 4. Since another A RR was found, repeat using mask 255.255.255.240
+ (x'FFFFFFF0'), constructing a query for 16.2.9.128.IN-ADDR.ARPA.
+ Retrieve:
+
+ 16.2.9.128.IN-ADDR.ARPA. PTR inc-subsubnet.isi.edu.
+
+ Push the name "inc-subsubnet.isi.edu" onto the stack of names to
+ be searched for LOC RRs later.
+
+ 5. Since no A RR is present at 16.2.9.128.IN-ADDR.ARPA., there are no
+ more subnet levels to search. We now pop the top name from the
+ stack and check for an associated LOC RR. Repeat until a LOC RR
+ is found.
+
+ In this case, assume that inc-subsubnet.isi.edu does not have an
+ associated LOC RR, but that div2-subnet.isi.edu does. We will
+ then use div2-subnet.isi.edu's LOC RR as an approximation of this
+ host's location. (Note that even if isi-net.isi.edu has a LOC RR,
+ it will not be used if a subnet also has a LOC RR.)
+
+5.3 Applicability to non-IN Classes and non-IP Addresses
+
+ The LOC record is defined for all RR classes, and may be used with
+ non-IN classes such as HS and CH. The semantics of such use are not
+ defined by this memo.
+
+ The search algorithm in section 5.2.3 may be adapted to other
+ addressing schemes by extending [RFC 1101]'s encoding of network
+ names to cover those schemes. Such extensions are not defined by
+ this memo.
+
+
+
+
+
+
+
+
+
+
+
+Davis, et al Experimental [Page 7]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+6. References
+
+ [RFC 1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, USC/Information Sciences Institute,
+ November 1987.
+
+ [RFC 1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, USC/Information Sciences
+ Institute, November 1987.
+
+ [RFC 1101] Mockapetris, P., "DNS Encoding of Network Names and Other
+ Types", RFC 1101, USC/Information Sciences Institute,
+ April 1989.
+
+ [WGS 84] United States Department of Defense; DoD WGS-1984 - Its
+ Definition and Relationships with Local Geodetic Systems;
+ Washington, D.C.; 1985; Report AD-A188 815 DMA; 6127; 7-R-
+ 138-R; CV, KV;
+
+7. Security Considerations
+
+ High-precision LOC RR information could be used to plan a penetration
+ of physical security, leading to potential denial-of-machine attacks.
+ To avoid any appearance of suggesting this method to potential
+ attackers, we declined the opportunity to name this RR "ICBM".
+
+8. Authors' Addresses
+
+ The authors as a group can be reached as <loc@pipex.net>.
+
+ Christopher Davis
+ Kapor Enterprises, Inc.
+ 238 Main Street, Suite 400
+ Cambridge, MA 02142
+
+ Phone: +1 617 576 4532
+ EMail: ckd@kei.com
+
+
+ Paul Vixie
+ Vixie Enterprises
+ Star Route Box 159A
+ Woodside, CA 94062
+
+ Phone: +1 415 747 0204
+ EMail: paul@vix.com
+
+
+
+
+
+Davis, et al Experimental [Page 8]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ Tim Goodwin
+ Public IP Exchange Ltd (PIPEX)
+ 216 The Science Park
+ Cambridge CB4 4WA
+ UK
+
+ Phone: +44 1223 250250
+ EMail: tim@pipex.net
+
+
+ Ian Dickinson
+ FORE Systems
+ 2475 The Crescent
+ Solihull Parkway
+ Birmingham Business Park
+ B37 7YE
+ UK
+
+ Phone: +44 121 717 4444
+ EMail: idickins@fore.co.uk
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Davis, et al Experimental [Page 9]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+Appendix A: Sample Conversion Routines
+
+/*
+ * routines to convert between on-the-wire RR format and zone file
+ * format. Does not contain conversion to/from decimal degrees;
+ * divide or multiply by 60*60*1000 for that.
+ */
+
+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+ 1000000,10000000,100000000,1000000000};
+
+/* takes an XeY precision/size value, returns a string representation.*/
+static const char *
+precsize_ntoa(prec)
+ u_int8_t prec;
+{
+ static char retbuf[sizeof("90000000.00")];
+ unsigned long val;
+ int mantissa, exponent;
+
+ mantissa = (int)((prec >> 4) & 0x0f) % 10;
+ exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+ val = mantissa * poweroften[exponent];
+
+ (void) sprintf(retbuf,"%d.%.2d", val/100, val%100);
+ return (retbuf);
+}
+
+/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/
+static u_int8_t
+precsize_aton(strptr)
+ char **strptr;
+{
+ unsigned int mval = 0, cmval = 0;
+ u_int8_t retval = 0;
+ register char *cp;
+ register int exponent;
+ register int mantissa;
+
+ cp = *strptr;
+
+ while (isdigit(*cp))
+ mval = mval * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* centimeters */
+ cp++;
+ if (isdigit(*cp)) {
+
+
+
+Davis, et al Experimental [Page 10]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ cmval = (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ cmval += (*cp++ - '0');
+ }
+ }
+ }
+ cmval = (mval * 100) + cmval;
+
+ for (exponent = 0; exponent < 9; exponent++)
+ if (cmval < poweroften[exponent+1])
+ break;
+
+ mantissa = cmval / poweroften[exponent];
+ if (mantissa > 9)
+ mantissa = 9;
+
+ retval = (mantissa << 4) | exponent;
+
+ *strptr = cp;
+
+ return (retval);
+}
+
+/* converts ascii lat/lon to unsigned encoded 32-bit number.
+ * moves pointer. */
+static u_int32_t
+latlon2ul(latlonstrptr,which)
+ char **latlonstrptr;
+ int *which;
+{
+ register char *cp;
+ u_int32_t retval;
+ int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+ cp = *latlonstrptr;
+
+ while (isdigit(*cp))
+ deg = deg * 10 + (*cp++ - '0');
+
+ while (isspace(*cp))
+ cp++;
+
+ if (!(isdigit(*cp)))
+ goto fndhemi;
+
+ while (isdigit(*cp))
+ min = min * 10 + (*cp++ - '0');
+
+
+
+
+Davis, et al Experimental [Page 11]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ while (isspace(*cp))
+ cp++;
+
+ if (!(isdigit(*cp)))
+ goto fndhemi;
+
+ while (isdigit(*cp))
+ secs = secs * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal seconds */
+ cp++;
+ if (isdigit(*cp)) {
+ secsfrac = (*cp++ - '0') * 100;
+ if (isdigit(*cp)) {
+ secsfrac += (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ secsfrac += (*cp++ - '0');
+ }
+ }
+ }
+ }
+
+ while (!isspace(*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace(*cp))
+ cp++;
+
+ fndhemi:
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'E': case 'e':
+ retval = ((unsigned)1<<31)
+ + (((((deg * 60) + min) * 60) + secs) * 1000)
+ + secsfrac;
+ break;
+ case 'S': case 's':
+ case 'W': case 'w':
+ retval = ((unsigned)1<<31)
+ - (((((deg * 60) + min) * 60) + secs) * 1000)
+ - secsfrac;
+ break;
+ default:
+ retval = 0; /* invalid value -- indicates error */
+ break;
+ }
+
+ switch (*cp) {
+
+
+
+Davis, et al Experimental [Page 12]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ case 'N': case 'n':
+ case 'S': case 's':
+ *which = 1; /* latitude */
+ break;
+ case 'E': case 'e':
+ case 'W': case 'w':
+ *which = 2; /* longitude */
+ break;
+ default:
+ *which = 0; /* error */
+ break;
+ }
+
+ cp++; /* skip the hemisphere */
+
+ while (!isspace(*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace(*cp)) /* move to next field */
+ cp++;
+
+ *latlonstrptr = cp;
+
+ return (retval);
+}
+
+/* converts a zone file representation in a string to an RDATA
+ * on-the-wire representation. */
+u_int32_t
+loc_aton(ascii, binary)
+ const char *ascii;
+ u_char *binary;
+{
+ const char *cp, *maxcp;
+ u_char *bcp;
+
+ u_int32_t latit = 0, longit = 0, alt = 0;
+ u_int32_t lltemp1 = 0, lltemp2 = 0;
+ int altmeters = 0, altfrac = 0, altsign = 1;
+ u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
+ u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
+ u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
+ int which1 = 0, which2 = 0;
+
+ cp = ascii;
+ maxcp = cp + strlen(ascii);
+
+ lltemp1 = latlon2ul(&cp, &which1);
+
+
+
+Davis, et al Experimental [Page 13]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ lltemp2 = latlon2ul(&cp, &which2);
+
+ switch (which1 + which2) {
+ case 3: /* 1 + 2, the only valid combination */
+ if ((which1 == 1) && (which2 == 2)) { /* normal case */
+ latit = lltemp1;
+ longit = lltemp2;
+ } else if ((which1 == 2) && (which2 == 1)) {/*reversed*/
+ longit = lltemp1;
+ latit = lltemp2;
+ } else { /* some kind of brokenness */
+ return 0;
+ }
+ break;
+ default: /* we didn't get one of each */
+ return 0;
+ }
+
+ /* altitude */
+ if (*cp == '-') {
+ altsign = -1;
+ cp++;
+ }
+
+ if (*cp == '+')
+ cp++;
+
+ while (isdigit(*cp))
+ altmeters = altmeters * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal meters */
+ cp++;
+ if (isdigit(*cp)) {
+ altfrac = (*cp++ - '0') * 10;
+ if (isdigit(*cp)) {
+ altfrac += (*cp++ - '0');
+ }
+ }
+ }
+
+ alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+ while (!isspace(*cp) && (cp < maxcp))
+ /* if trailing garbage or m */
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+
+
+Davis, et al Experimental [Page 14]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ siz = precsize_aton(&cp);
+
+ while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ hp = precsize_aton(&cp);
+
+ while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/
+ cp++;
+
+ while (isspace(*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ vp = precsize_aton(&cp);
+
+ defaults:
+
+ bcp = binary;
+ *bcp++ = (u_int8_t) 0; /* version byte */
+ *bcp++ = siz;
+ *bcp++ = hp;
+ *bcp++ = vp;
+ PUTLONG(latit,bcp);
+ PUTLONG(longit,bcp);
+ PUTLONG(alt,bcp);
+
+ return (16); /* size of RR in octets */
+}
+
+/* takes an on-the-wire LOC RR and prints it in zone file
+ * (human readable) format. */
+char *
+loc_ntoa(binary,ascii)
+ const u_char *binary;
+ char *ascii;
+{
+
+
+
+Davis, et al Experimental [Page 15]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ static char tmpbuf[255*3];
+
+ register char *cp;
+ register const u_char *rcp;
+
+ int latdeg, latmin, latsec, latsecfrac;
+ int longdeg, longmin, longsec, longsecfrac;
+ char northsouth, eastwest;
+ int altmeters, altfrac, altsign;
+
+ const int referencealt = 100000 * 100;
+
+ int32_t latval, longval, altval;
+ u_int32_t templ;
+ u_int8_t sizeval, hpval, vpval, versionval;
+
+ char *sizestr, *hpstr, *vpstr;
+
+ rcp = binary;
+ if (ascii)
+ cp = ascii;
+ else {
+ cp = tmpbuf;
+ }
+
+ versionval = *rcp++;
+
+ if (versionval) {
+ sprintf(cp,"; error: unknown LOC RR version");
+ return (cp);
+ }
+
+ sizeval = *rcp++;
+
+ hpval = *rcp++;
+ vpval = *rcp++;
+
+ GETLONG(templ,rcp);
+ latval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ,rcp);
+ longval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ,rcp);
+ if (templ < referencealt) { /* below WGS 84 spheroid */
+ altval = referencealt - templ;
+ altsign = -1;
+ } else {
+
+
+
+Davis, et al Experimental [Page 16]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ altval = templ - referencealt;
+ altsign = 1;
+ }
+
+ if (latval < 0) {
+ northsouth = 'S';
+ latval = -latval;
+ }
+ else
+ northsouth = 'N';
+
+ latsecfrac = latval % 1000;
+ latval = latval / 1000;
+ latsec = latval % 60;
+ latval = latval / 60;
+ latmin = latval % 60;
+ latval = latval / 60;
+ latdeg = latval;
+
+ if (longval < 0) {
+ eastwest = 'W';
+ longval = -longval;
+ }
+ else
+ eastwest = 'E';
+
+ longsecfrac = longval % 1000;
+ longval = longval / 1000;
+ longsec = longval % 60;
+ longval = longval / 60;
+ longmin = longval % 60;
+ longval = longval / 60;
+ longdeg = longval;
+
+ altfrac = altval % 100;
+ altmeters = (altval / 100) * altsign;
+
+ sizestr = savestr(precsize_ntoa(sizeval));
+ hpstr = savestr(precsize_ntoa(hpval));
+ vpstr = savestr(precsize_ntoa(vpval));
+
+ sprintf(cp,
+ "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm
+ %sm %sm %sm",
+ latdeg, latmin, latsec, latsecfrac, northsouth,
+ longdeg, longmin, longsec, longsecfrac, eastwest,
+ altmeters, altfrac, sizestr, hpstr, vpstr);
+
+
+
+
+Davis, et al Experimental [Page 17]
+
+RFC 1876 Location Information in the DNS January 1996
+
+
+ free(sizestr);
+ free(hpstr);
+ free(vpstr);
+
+ return (cp);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Davis, et al Experimental [Page 18]
+
diff --git a/doc/rfc/rfc1886.txt b/doc/rfc/rfc1886.txt
new file mode 100644
index 0000000..9874fdd
--- /dev/null
+++ b/doc/rfc/rfc1886.txt
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+Network Working Group S. Thomson
+Request for Comments: 1886 Bellcore
+Category: Standards Track C. Huitema
+ INRIA
+ December 1995
+
+
+ DNS Extensions to support IP version 6
+
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+
+Abstract
+
+ This document defines the changes that need to be made to the Domain
+ Name System to support hosts running IP version 6 (IPv6). The
+ changes include a new resource record type to store an IPv6 address,
+ a new domain to support lookups based on an IPv6 address, and updated
+ definitions of existing query types that return Internet addresses as
+ part of additional section processing. The extensions are designed
+ to be compatible with existing applications and, in particular, DNS
+ implementations themselves.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Thompson & Huitema Standards Track [Page 1]
+
+RFC 1886 IPv6 DNS Extensions December 1995
+
+
+1. INTRODUCTION
+
+ Current support for the storage of Internet addresses in the Domain
+ Name System (DNS)[1,2] cannot easily be extended to support IPv6
+ addresses[3] since applications assume that address queries return
+ 32-bit IPv4 addresses only.
+
+ To support the storage of IPv6 addresses we define the following
+ extensions:
+
+ o A new resource record type is defined to map a domain name to an
+ IPv6 address.
+
+ o A new domain is defined to support lookups based on address.
+
+ o Existing queries that perform additional section processing to
+ locate IPv4 addresses are redefined to perform additional
+ section processing on both IPv4 and IPv6 addresses.
+
+ The changes are designed to be compatible with existing software. The
+ existing support for IPv4 addresses is retained. Transition issues
+ related to the co-existence of both IPv4 and IPv6 addresses in DNS
+ are discussed in [4].
+
+
+2. NEW RESOURCE RECORD DEFINITION AND DOMAIN
+
+ A new record type is defined to store a host's IPv6 address. A host
+ that has more than one IPv6 address must have more than one such
+ record.
+
+
+2.1 AAAA record type
+
+ The AAAA resource record type is a new record specific to the
+ Internet class that stores a single IPv6 address.
+
+ The value of the type is 28 (decimal).
+
+
+2.2 AAAA data format
+
+ A 128 bit IPv6 address is encoded in the data portion of an AAAA
+ resource record in network byte order (high-order byte first).
+
+
+
+
+Thompson & Huitema Standards Track [Page 2]
+
+RFC 1886 IPv6 DNS Extensions December 1995
+
+
+2.3 AAAA query
+
+ An AAAA query for a specified domain name in the Internet class
+ returns all associated AAAA resource records in the answer section of
+ a response.
+
+ A type AAAA query does not perform additional section processing.
+
+
+2.4 Textual format of AAAA records
+
+ The textual representation of the data portion of the AAAA resource
+ record used in a master database file is the textual representation
+ of a IPv6 address as defined in [3].
+
+
+2.5 IP6.INT Domain
+
+ A special domain is defined to look up a record given an address. The
+ intent of this domain is to provide a way of mapping an IPv6 address
+ to a host name, although it may be used for other purposes as well.
+ The domain is rooted at IP6.INT.
+
+ An IPv6 address is represented as a name in the IP6.INT domain by a
+ sequence of nibbles separated by dots with the suffix ".IP6.INT". The
+ sequence of nibbles is encoded in reverse order, i.e. the low-order
+ nibble is encoded first, followed by the next low-order nibble and so
+ on. Each nibble is represented by a hexadecimal digit. For example,
+ the inverse lookup domain name corresponding to the address
+
+ 4321:0:1:2:3:4:567:89ab
+
+ would be
+
+b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.INT.
+
+
+
+3. MODIFICATIONS TO EXISTING QUERY TYPES
+
+ All existing query types that perform type A additional section
+ processing, i.e. name server (NS), mail exchange (MX) and mailbox
+ (MB) query types, must be redefined to perform both type A and type
+ AAAA additional section processing. These new definitions mean that a
+ name server must add any relevant IPv4 addresses and any relevant
+
+
+
+Thompson & Huitema Standards Track [Page 3]
+
+RFC 1886 IPv6 DNS Extensions December 1995
+
+
+ IPv6 addresses available locally to the additional section of a
+ response when processing any one of the above queries.
+
+
+4. SECURITY CONSIDERATIONS
+
+ Security issues are not discussed in this memo.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Thompson & Huitema Standards Track [Page 4]
+
+RFC 1886 IPv6 DNS Extensions December 1995
+
+
+5. REFERENCES
+
+
+ [1] Mockapetris, P., "Domain Names - Concepts and Facilities", STD
+ 13, RFC 1034, USC/Information Sciences Institute, November 1987.
+
+ [2] Mockapetris, P., "Domain Names - Implementation and Specifica-
+ tion", STD 13, RFC 1035, USC/Information Sciences Institute,
+ November 1987.
+
+ [3] Hinden, R., and S. Deering, Editors, "IP Version 6 Addressing
+ Architecture", RFC 1884, Ipsilon Networks, Xerox PARC, December
+ 1995.
+
+
+ [4] Gilligan, R., and E. Nordmark, "Transition Mechanisms for IPv6
+ Hosts and Routers", Work in Progress.
+
+
+Authors' Addresses
+
+ Susan Thomson
+ Bellcore
+ MRE 2P343
+ 445 South Street
+ Morristown, NJ 07960
+ U.S.A.
+
+ Phone: +1 201-829-4514
+ EMail: set@thumper.bellcore.com
+
+
+ Christian Huitema
+ INRIA, Sophia-Antipolis
+ 2004 Route des Lucioles
+ BP 109
+ F-06561 Valbonne Cedex
+ France
+
+ Phone: +33 93 65 77 15
+ EMail: Christian.Huitema@MIRSA.INRIA.FR
+
+
+
+
+
+
+
+Thompson & Huitema Standards Track [Page 5]
+
diff --git a/doc/rfc/rfc1982.txt b/doc/rfc/rfc1982.txt
new file mode 100644
index 0000000..5a34bc4
--- /dev/null
+++ b/doc/rfc/rfc1982.txt
@@ -0,0 +1,394 @@
+
+
+
+
+
+
+Network Working Group R. Elz
+Request for Comments: 1982 University of Melbourne
+Updates: 1034, 1035 R. Bush
+Category: Standards Track RGnet, Inc.
+ August 1996
+
+
+ Serial Number Arithmetic
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Abstract
+
+ This memo defines serial number arithmetic, as used in the Domain
+ Name System. The DNS has long relied upon serial number arithmetic,
+ a concept which has never really been defined, certainly not in an
+ IETF document, though which has been widely understood. This memo
+ supplies the missing definition. It is intended to update RFC1034
+ and RFC1035.
+
+1. Introduction
+
+ The serial number field of the SOA resource record is defined in
+ RFC1035 as
+
+ SERIAL The unsigned 32 bit version number of the original copy of
+ the zone. Zone transfers preserve this value. This value
+ wraps and should be compared using sequence space
+ arithmetic.
+
+ RFC1034 uses the same terminology when defining secondary server zone
+ consistency procedures.
+
+ Unfortunately the term "sequence space arithmetic" is not defined in
+ either RFC1034 or RFC1035, nor do any of their references provide
+ further information.
+
+ This phrase seems to have been intending to specify arithmetic as
+ used in TCP sequence numbers [RFC793], and defined in [IEN-74].
+
+ Unfortunately, the arithmetic defined in [IEN-74] is not adequate for
+ the purposes of the DNS, as no general comparison operator is
+
+
+
+Elz & Bush Standards Track [Page 1]
+
+RFC 1982 Serial Number Arithmetic August 1996
+
+
+ defined.
+
+ To avoid further problems with this simple field, this document
+ defines the field and the operations available upon it. This
+ definition is intended merely to clarify the intent of RFC1034 and
+ RFC1035, and is believed to generally agree with current
+ implementations. However, older, superseded, implementations are
+ known to have treated the serial number as a simple unsigned integer,
+ with no attempt to implement any kind of "sequence space arithmetic",
+ however that may have been interpreted, and further, ignoring the
+ requirement that the value wraps. Nothing can be done with these
+ implementations, beyond extermination.
+
+2. Serial Number Arithmetic
+
+ Serial numbers are formed from non-negative integers from a finite
+ subset of the range of all integer values. The lowest integer in
+ every subset used for this purpose is zero, the maximum is always one
+ less than a power of two.
+
+ When considered as serial numbers however no value has any particular
+ significance, there is no minimum or maximum serial number, every
+ value has a successor and predecessor.
+
+ To define a serial number to be used in this way, the size of the
+ serial number space must be given. This value, called "SERIAL_BITS",
+ gives the power of two which results in one larger than the largest
+ integer corresponding to a serial number value. This also specifies
+ the number of bits required to hold every possible value of a serial
+ number of the defined type. The operations permitted upon serial
+ numbers are defined in the following section.
+
+3. Operations upon the serial number
+
+ Only two operations are defined upon serial numbers, addition of a
+ positive integer of limited range, and comparison with another serial
+ number.
+
+3.1. Addition
+
+ Serial numbers may be incremented by the addition of a positive
+ integer n, where n is taken from the range of integers
+ [0 .. (2^(SERIAL_BITS - 1) - 1)]. For a sequence number s, the
+ result of such an addition, s', is defined as
+
+ s' = (s + n) modulo (2 ^ SERIAL_BITS)
+
+
+
+
+
+Elz & Bush Standards Track [Page 2]
+
+RFC 1982 Serial Number Arithmetic August 1996
+
+
+ where the addition and modulus operations here act upon values that
+ are non-negative values of unbounded size in the usual ways of
+ integer arithmetic.
+
+ Addition of a value outside the range
+ [0 .. (2^(SERIAL_BITS - 1) - 1)] is undefined.
+
+3.2. Comparison
+
+ Any two serial numbers, s1 and s2, may be compared. The definition
+ of the result of this comparison is as follows.
+
+ For the purposes of this definition, consider two integers, i1 and
+ i2, from the unbounded set of non-negative integers, such that i1 and
+ s1 have the same numeric value, as do i2 and s2. Arithmetic and
+ comparisons applied to i1 and i2 use ordinary unbounded integer
+ arithmetic.
+
+ Then, s1 is said to be equal to s2 if and only if i1 is equal to i2,
+ in all other cases, s1 is not equal to s2.
+
+ s1 is said to be less than s2 if, and only if, s1 is not equal to s2,
+ and
+
+ (i1 < i2 and i2 - i1 < 2^(SERIAL_BITS - 1)) or
+ (i1 > i2 and i1 - i2 > 2^(SERIAL_BITS - 1))
+
+ s1 is said to be greater than s2 if, and only if, s1 is not equal to
+ s2, and
+
+ (i1 < i2 and i2 - i1 > 2^(SERIAL_BITS - 1)) or
+ (i1 > i2 and i1 - i2 < 2^(SERIAL_BITS - 1))
+
+ Note that there are some pairs of values s1 and s2 for which s1 is
+ not equal to s2, but for which s1 is neither greater than, nor less
+ than, s2. An attempt to use these ordering operators on such pairs
+ of values produces an undefined result.
+
+ The reason for this is that those pairs of values are such that any
+ simple definition that were to define s1 to be less than s2 where
+ (s1, s2) is such a pair, would also usually cause s2 to be less than
+ s1, when the pair is (s2, s1). This would mean that the particular
+ order selected for a test could cause the result to differ, leading
+ to unpredictable implementations.
+
+ While it would be possible to define the test in such a way that the
+ inequality would not have this surprising property, while being
+ defined for all pairs of values, such a definition would be
+
+
+
+Elz & Bush Standards Track [Page 3]
+
+RFC 1982 Serial Number Arithmetic August 1996
+
+
+ unnecessarily burdensome to implement, and difficult to understand,
+ and would still allow cases where
+
+ s1 < s2 and (s1 + 1) > (s2 + 1)
+
+ which is just as non-intuitive.
+
+ Thus the problem case is left undefined, implementations are free to
+ return either result, or to flag an error, and users must take care
+ not to depend on any particular outcome. Usually this will mean
+ avoiding allowing those particular pairs of numbers to co-exist.
+
+ The relationships greater than or equal to, and less than or equal
+ to, follow in the natural way from the above definitions.
+
+4. Corollaries
+
+ These definitions give rise to some results of note.
+
+4.1. Corollary 1
+
+ For any sequence number s and any integer n such that addition of n
+ to s is well defined, (s + n) >= s. Further (s + n) == s only when
+ n == 0, in all other defined cases, (s + n) > s.
+
+4.2. Corollary 2
+
+ If s' is the result of adding the non-zero integer n to the sequence
+ number s, and m is another integer from the range defined as able to
+ be added to a sequence number, and s" is the result of adding m to
+ s', then it is undefined whether s" is greater than, or less than s,
+ though it is known that s" is not equal to s.
+
+4.3. Corollary 3
+
+ If s" from the previous corollary is further incremented, then there
+ is no longer any known relationship between the result and s.
+
+4.4. Corollary 4
+
+ If in corollary 2 the value (n + m) is such that addition of the sum
+ to sequence number s would produce a defined result, then corollary 1
+ applies, and s" is known to be greater than s.
+
+
+
+
+
+
+
+
+Elz & Bush Standards Track [Page 4]
+
+RFC 1982 Serial Number Arithmetic August 1996
+
+
+5. Examples
+
+5.1. A trivial example
+
+ The simplest meaningful serial number space has SERIAL_BITS == 2. In
+ this space, the integers that make up the serial number space are 0,
+ 1, 2, and 3. That is, 3 == 2^SERIAL_BITS - 1.
+
+ In this space, the largest integer that it is meaningful to add to a
+ sequence number is 2^(SERIAL_BITS - 1) - 1, or 1.
+
+ Then, as defined 0+1 == 1, 1+1 == 2, 2+1 == 3, and 3+1 == 0.
+ Further, 1 > 0, 2 > 1, 3 > 2, and 0 > 3. It is undefined whether
+ 2 > 0 or 0 > 2, and whether 1 > 3 or 3 > 1.
+
+5.2. A slightly larger example
+
+ Consider the case where SERIAL_BITS == 8. In this space the integers
+ that make up the serial number space are 0, 1, 2, ... 254, 255.
+ 255 == 2^SERIAL_BITS - 1.
+
+ In this space, the largest integer that it is meaningful to add to a
+ sequence number is 2^(SERIAL_BITS - 1) - 1, or 127.
+
+ Addition is as expected in this space, for example: 255+1 == 0,
+ 100+100 == 200, and 200+100 == 44.
+
+ Comparison is more interesting, 1 > 0, 44 > 0, 100 > 0, 100 > 44,
+ 200 > 100, 255 > 200, 0 > 255, 100 > 255, 0 > 200, and 44 > 200.
+
+ Note that 100+100 > 100, but that (100+100)+100 < 100. Incrementing
+ a serial number can cause it to become "smaller". Of course,
+ incrementing by a smaller number will allow many more increments to
+ be made before this occurs. However this is always something to be
+ aware of, it can cause surprising errors, or be useful as it is the
+ only defined way to actually cause a serial number to decrease.
+
+ The pairs of values 0 and 128, 1 and 129, 2 and 130, etc, to 127 and
+ 255 are not equal, but in each pair, neither number is defined as
+ being greater than, or less than, the other.
+
+ It could be defined (arbitrarily) that 128 > 0, 129 > 1,
+ 130 > 2, ..., 255 > 127, by changing the comparison operator
+ definitions, as mentioned above. However note that that would cause
+ 255 > 127, while (255 + 1) < (127 + 1), as 0 < 128. Such a
+ definition, apart from being arbitrary, would also be more costly to
+ implement.
+
+
+
+
+Elz & Bush Standards Track [Page 5]
+
+RFC 1982 Serial Number Arithmetic August 1996
+
+
+6. Citation
+
+ As this defined arithmetic may be useful for purposes other than for
+ the DNS serial number, it may be referenced as Serial Number
+ Arithmetic from RFC1982. Any such reference shall be taken as
+ implying that the rules of sections 2 to 5 of this document apply to
+ the stated values.
+
+7. The DNS SOA serial number
+
+ The serial number in the DNS SOA Resource Record is a Serial Number
+ as defined above, with SERIAL_BITS being 32. That is, the serial
+ number is a non negative integer with values taken from the range
+ [0 .. 4294967295]. That is, a 32 bit unsigned integer.
+
+ The maximum defined increment is 2147483647 (2^31 - 1).
+
+ Care should be taken that the serial number not be incremented, in
+ one or more steps, by more than this maximum within the period given
+ by the value of SOA.expire. Doing so may leave some secondary
+ servers with out of date copies of the zone, but with a serial number
+ "greater" than that of the primary server. Of course, special
+ circumstances may require this rule be set aside, for example, when
+ the serial number needs to be set lower for some reason. If this
+ must be done, then take special care to verify that ALL servers have
+ correctly succeeded in following the primary server's serial number
+ changes, at each step.
+
+ Note that each, and every, increment to the serial number must be
+ treated as the start of a new sequence of increments for this
+ purpose, as well as being the continuation of all previous sequences
+ started within the period specified by SOA.expire.
+
+ Caution should also be exercised before causing the serial number to
+ be set to the value zero. While this value is not in any way special
+ in serial number arithmetic, or to the DNS SOA serial number, many
+ DNS implementations have incorrectly treated zero as a special case,
+ with special properties, and unusual behaviour may be expected if
+ zero is used as a DNS SOA serial number.
+
+
+
+
+
+
+
+
+
+
+
+
+Elz & Bush Standards Track [Page 6]
+
+RFC 1982 Serial Number Arithmetic August 1996
+
+
+8. Document Updates
+
+ RFC1034 and RFC1035 are to be treated as if the references to
+ "sequence space arithmetic" therein are replaced by references to
+ serial number arithmetic, as defined in this document.
+
+9. Security Considerations
+
+ This document does not consider security.
+
+ It is not believed that anything in this document adds to any
+ security issues that may exist with the DNS, nor does it do anything
+ to lessen them.
+
+References
+
+ [RFC1034] Domain Names - Concepts and Facilities,
+ P. Mockapetris, STD 13, ISI, November 1987.
+
+ [RFC1035] Domain Names - Implementation and Specification
+ P. Mockapetris, STD 13, ISI, November 1987
+
+ [RFC793] Transmission Control protocol
+ Information Sciences Institute, STD 7, USC, September 1981
+
+ [IEN-74] Sequence Number Arithmetic
+ William W. Plummer, BB&N Inc, September 1978
+
+Acknowledgements
+
+ Thanks to Rob Austein for suggesting clarification of the undefined
+ comparison operators, and to Michael Patton for attempting to locate
+ another reference for this procedure. Thanks also to members of the
+ IETF DNSIND working group of 1995-6, in particular, Paul Mockapetris.
+
+Authors' Addresses
+
+ Robert Elz Randy Bush
+ Computer Science RGnet, Inc.
+ University of Melbourne 10361 NE Sasquatch Lane
+ Parkville, Vic, 3052 Bainbridge Island, Washington, 98110
+ Australia. United States.
+
+ EMail: kre@munnari.OZ.AU EMail: randy@psg.com
+
+
+
+
+
+
+
+Elz & Bush Standards Track [Page 7]
diff --git a/doc/rfc/rfc1995.txt b/doc/rfc/rfc1995.txt
new file mode 100644
index 0000000..b50bdc6
--- /dev/null
+++ b/doc/rfc/rfc1995.txt
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+Network Working Group M. Ohta
+Request for Comments: 1995 Tokyo Institute of Technology
+Updates: 1035 August 1996
+Category: Standards Track
+
+
+ Incremental Zone Transfer in DNS
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Abstract
+
+ This document proposes extensions to the DNS protocols to provide an
+ incremental zone transfer (IXFR) mechanism.
+
+1. Introduction
+
+ For rapid propagation of changes to a DNS database [STD13], it is
+ necessary to reduce latency by actively notifying servers of the
+ change. This is accomplished by the NOTIFY extension of the DNS
+ [NOTIFY].
+
+ The current full zone transfer mechanism (AXFR) is not an efficient
+ means to propagate changes to a small part of a zone, as it transfers
+ the entire zone file.
+
+ Incremental transfer (IXFR) as proposed is a more efficient
+ mechanism, as it transfers only the changed portion(s) of a zone.
+
+ In this document, a secondary name server which requests IXFR is
+ called an IXFR client and a primary or secondary name server which
+ responds to the request is called an IXFR server.
+
+2. Brief Description of the Protocol
+
+ If an IXFR client, which likely has an older version of a zone,
+ thinks it needs new information about the zone (typically through SOA
+ refresh timeout or the NOTIFY mechanism), it sends an IXFR message
+ containing the SOA serial number of its, presumably outdated, copy of
+ the zone.
+
+
+
+
+
+Ohta Standards Track [Page 1]
+
+RFC 1995 Incremental Zone Transfer in DNS August 1996
+
+
+ An IXFR server should keep record of the newest version of the zone
+ and the differences between that copy and several older versions.
+ When an IXFR request with an older version number is received, the
+ IXFR server needs to send only the differences required to make that
+ version current. Alternatively, the server may choose to transfer
+ the entire zone just as in a normal full zone transfer.
+
+ When a zone has been updated, it should be saved in stable storage
+ before the new version is used to respond to IXFR (or AXFR) queries.
+ Otherwise, if the server crashes, data which is no longer available
+ may have been distributed to secondary servers, which can cause
+ persistent database inconsistencies.
+
+ If an IXFR query with the same or newer version number than that of
+ the server is received, it is replied to with a single SOA record of
+ the server's current version, just as in AXFR.
+
+ Transport of a query may be by either UDP or TCP. If an IXFR query
+ is via UDP, the IXFR server may attempt to reply using UDP if the
+ entire response can be contained in a single DNS packet. If the UDP
+ reply does not fit, the query is responded to with a single SOA
+ record of the server's current version to inform the client that a
+ TCP query should be initiated.
+
+ Thus, a client should first make an IXFR query using UDP. If the
+ query type is not recognized by the server, an AXFR (preceded by a
+ UDP SOA query) should be tried, ensuring backward compatibility. If
+ the query response is a single packet with the entire new zone, or if
+ the server does not have a newer version than the client, everything
+ is done. Otherwise, a TCP IXFR query should be tried.
+
+ To ensure integrity, servers should use UDP checksums for all UDP
+ responses. A cautious client which receives a UDP packet with a
+ checksum value of zero should ignore the result and try a TCP IXFR
+ instead.
+
+ The query type value of IXFR assigned by IANA is 251.
+
+3. Query Format
+
+ The IXFR query packet format is the same as that of a normal DNS
+ query, but with the query type being IXFR and the authority section
+ containing the SOA record of client's version of the zone.
+
+
+
+
+
+
+
+
+Ohta Standards Track [Page 2]
+
+RFC 1995 Incremental Zone Transfer in DNS August 1996
+
+
+4. Response Format
+
+ If incremental zone transfer is not available, the entire zone is
+ returned. The first and the last RR of the response is the SOA
+ record of the zone. I.e. the behavior is the same as an AXFR
+ response except the query type is IXFR.
+
+ If incremental zone transfer is available, one or more difference
+ sequences is returned. The list of difference sequences is preceded
+ and followed by a copy of the server's current version of the SOA.
+
+ Each difference sequence represents one update to the zone (one SOA
+ serial change) consisting of deleted RRs and added RRs. The first RR
+ of the deleted RRs is the older SOA RR and the first RR of the added
+ RRs is the newer SOA RR.
+
+ Modification of an RR is performed first by removing the original RR
+ and then adding the modified one.
+
+ The sequences of differential information are ordered oldest first
+ newest last. Thus, the differential sequences are the history of
+ changes made since the version known by the IXFR client up to the
+ server's current version.
+
+ RRs in the incremental transfer messages may be partial. That is, if
+ a single RR of multiple RRs of the same RR type changes, only the
+ changed RR is transferred.
+
+ An IXFR client, should only replace an older version with a newer
+ version after all the differences have been successfully processed.
+
+ An incremental response is different from that of a non-incremental
+ response in that it begins with two SOA RRs, the server's current SOA
+ followed by the SOA of the client's version which is about to be
+ replaced.
+
+ 5. Purging Strategy
+
+ An IXFR server can not be required to hold all previous versions
+ forever and may delete them anytime. In general, there is a trade-off
+ between the size of storage space and the possibility of using IXFR.
+
+ Information about older versions should be purged if the total length
+ of an IXFR response would be longer than that of an AXFR response.
+ Given that the purpose of IXFR is to reduce AXFR overhead, this
+ strategy is quite reasonable. The strategy assures that the amount
+ of storage required is at most twice that of the current zone
+ information.
+
+
+
+Ohta Standards Track [Page 3]
+
+RFC 1995 Incremental Zone Transfer in DNS August 1996
+
+
+ Information older than the SOA expire period may also be purged.
+
+6. Optional Condensation of Multiple Versions
+
+ An IXFR server may optionally condense multiple difference sequences
+ into a single difference sequence, thus, dropping information on
+ intermediate versions.
+
+ This may be beneficial if a lot of versions, not all of which are
+ useful, are generated. For example, if multiple ftp servers share a
+ single DNS name and the IP address associated with the name is
+ changed once a minute to balance load between the ftp servers, it is
+ not so important to keep track of all the history of changes.
+
+ But, this feature may not be so useful if an IXFR client has access
+ to two IXFR servers: A and B, with inconsistent condensation results.
+ The current version of the IXFR client, received from server A, may
+ be unknown to server B. In such a case, server B can not provide
+ incremental data from the unknown version and a full zone transfer is
+ necessary.
+
+ Condensation is completely optional. Clients can't detect from the
+ response whether the server has condensed the reply or not.
+
+ For interoperability, IXFR servers, including those without the
+ condensation feature, should not flag an error even if it receives a
+ client's IXFR request with a unknown version number and should,
+ instead, attempt to perform a full zone transfer.
+
+7. Example
+
+ Given the following three generations of data with the current serial
+ number of 3,
+
+ JAIN.AD.JP. IN SOA NS.JAIN.AD.JP. mohta.jain.ad.jp. (
+ 1 600 600 3600000 604800)
+ IN NS NS.JAIN.AD.JP.
+ NS.JAIN.AD.JP. IN A 133.69.136.1
+ NEZU.JAIN.AD.JP. IN A 133.69.136.5
+
+ NEZU.JAIN.AD.JP. is removed and JAIN-BB.JAIN.AD.JP. is added.
+
+ jain.ad.jp. IN SOA ns.jain.ad.jp. mohta.jain.ad.jp. (
+ 2 600 600 3600000 604800)
+ IN NS NS.JAIN.AD.JP.
+ NS.JAIN.AD.JP. IN A 133.69.136.1
+ JAIN-BB.JAIN.AD.JP. IN A 133.69.136.4
+ IN A 192.41.197.2
+
+
+
+Ohta Standards Track [Page 4]
+
+RFC 1995 Incremental Zone Transfer in DNS August 1996
+
+
+ One of the IP addresses of JAIN-BB.JAIN.AD.JP. is changed.
+
+ JAIN.AD.JP. IN SOA ns.jain.ad.jp. mohta.jain.ad.jp. (
+ 3 600 600 3600000 604800)
+ IN NS NS.JAIN.AD.JP.
+ NS.JAIN.AD.JP. IN A 133.69.136.1
+ JAIN-BB.JAIN.AD.JP. IN A 133.69.136.3
+ IN A 192.41.197.2
+
+ The following IXFR query
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY |
+ +---------------------------------------------------+
+ Question | QNAME=JAIN.AD.JP., QCLASS=IN, QTYPE=IXFR |
+ +---------------------------------------------------+
+ Answer | <empty> |
+ +---------------------------------------------------+
+ Authority | JAIN.AD.JP. IN SOA serial=1 |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+ could be replied to with the following full zone transfer message:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE |
+ +---------------------------------------------------+
+ Question | QNAME=JAIN.AD.JP., QCLASS=IN, QTYPE=IXFR |
+ +---------------------------------------------------+
+ Answer | JAIN.AD.JP. IN SOA serial=3 |
+ | JAIN.AD.JP. IN NS NS.JAIN.AD.JP. |
+ | NS.JAIN.AD.JP. IN A 133.69.136.1 |
+ | JAIN-BB.JAIN.AD.JP. IN A 133.69.136.3 |
+ | JAIN-BB.JAIN.AD.JP. IN A 192.41.197.2 |
+ | JAIN.AD.JP. IN SOA serial=3 |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+
+
+
+
+
+
+
+
+
+Ohta Standards Track [Page 5]
+
+RFC 1995 Incremental Zone Transfer in DNS August 1996
+
+
+ or with the following incremental message:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE |
+ +---------------------------------------------------+
+ Question | QNAME=JAIN.AD.JP., QCLASS=IN, QTYPE=IXFR |
+ +---------------------------------------------------+
+ Answer | JAIN.AD.JP. IN SOA serial=3 |
+ | JAIN.AD.JP. IN SOA serial=1 |
+ | NEZU.JAIN.AD.JP. IN A 133.69.136.5 |
+ | JAIN.AD.JP. IN SOA serial=2 |
+ | JAIN-BB.JAIN.AD.JP. IN A 133.69.136.4 |
+ | JAIN-BB.JAIN.AD.JP. IN A 192.41.197.2 |
+ | JAIN.AD.JP. IN SOA serial=2 |
+ | JAIN-BB.JAIN.AD.JP. IN A 133.69.136.4 |
+ | JAIN.AD.JP. IN SOA serial=3 |
+ | JAIN-BB.JAIN.AD.JP. IN A 133.69.136.3 |
+ | JAIN.AD.JP. IN SOA serial=3 |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+ or with the following condensed incremental message:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE |
+ +---------------------------------------------------+
+ Question | QNAME=JAIN.AD.JP., QCLASS=IN, QTYPE=IXFR |
+ +---------------------------------------------------+
+ Answer | JAIN.AD.JP. IN SOA serial=3 |
+ | JAIN.AD.JP. IN SOA serial=1 |
+ | NEZU.JAIN.AD.JP. IN A 133.69.136.5 |
+ | JAIN.AD.JP. IN SOA serial=3 |
+ | JAIN-BB.JAIN.AD.JP. IN A 133.69.136.3 |
+ | JAIN-BB.JAIN.AD.JP. IN A 192.41.197.2 |
+ | JAIN.AD.JP. IN SOA serial=3 |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+
+
+
+
+
+
+
+Ohta Standards Track [Page 6]
+
+RFC 1995 Incremental Zone Transfer in DNS August 1996
+
+
+ or, if UDP packet overflow occurs, with the following message:
+
+ +---------------------------------------------------+
+ Header | OPCODE=SQUERY, RESPONSE |
+ +---------------------------------------------------+
+ Question | QNAME=JAIN.AD.JP., QCLASS=IN, QTYPE=IXFR |
+ +---------------------------------------------------+
+ Answer | JAIN.AD.JP. IN SOA serial=3 |
+ +---------------------------------------------------+
+ Authority | <empty> |
+ +---------------------------------------------------+
+ Additional | <empty> |
+ +---------------------------------------------------+
+
+8. Acknowledgements
+
+ The original idea of IXFR was conceived by Anant Kumar, Steve Hotz
+ and Jon Postel.
+
+ For the refinement of the protocol and documentation, many people
+ have contributed including, but not limited to, Anant Kumar, Robert
+ Austein, Paul Vixie, Randy Bush, Mark Andrews, Robert Elz and the
+ members of the IETF DNSIND working group.
+
+9. References
+
+ [NOTIFY] Vixie, P., "DNS NOTIFY: A Mechanism for Prompt
+ Notification of Zone Changes", RFC 1996, August 1996.
+
+ [STD13] Mockapetris, P., "Domain Name System", STD 13, RFC 1034 and
+ RFC 1035), November 1987.
+
+10. Security Considerations
+
+ Though DNS is related to several security problems, no attempt is
+ made to fix them in this document.
+
+ This document is believed to introduce no additional security
+ problems to the current DNS protocol.
+
+
+
+
+
+
+
+
+
+
+
+
+Ohta Standards Track [Page 7]
+
+RFC 1995 Incremental Zone Transfer in DNS August 1996
+
+
+11. Author's Address
+
+ Masataka Ohta
+ Computer Center
+ Tokyo Institute of Technology
+ 2-12-1, O-okayama, Meguro-ku, Tokyo 152, JAPAN
+
+ Phone: +81-3-5734-3299
+ Fax: +81-3-5734-3415
+ EMail: mohta@necom830.hpcl.titech.ac.jp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ohta Standards Track [Page 8]
+
diff --git a/doc/rfc/rfc1996.txt b/doc/rfc/rfc1996.txt
new file mode 100644
index 0000000..b08f200
--- /dev/null
+++ b/doc/rfc/rfc1996.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group P. Vixie
+Request for Comments: 1996 ISC
+Updates: 1035 August 1996
+Category: Standards Track
+
+
+ A Mechanism for Prompt Notification of Zone Changes (DNS NOTIFY)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Abstract
+
+ This memo describes the NOTIFY opcode for DNS, by which a master
+ server advises a set of slave servers that the master's data has been
+ changed and that a query should be initiated to discover the new
+ data.
+
+1. Rationale and Scope
+
+ 1.1. Slow propagation of new and changed data in a DNS zone can be
+ due to a zone's relatively long refresh times. Longer refresh times
+ are beneficial in that they reduce load on the master servers, but
+ that benefit comes at the cost of long intervals of incoherence among
+ authority servers whenever the zone is updated.
+
+ 1.2. The DNS NOTIFY transaction allows master servers to inform slave
+ servers when the zone has changed -- an interrupt as opposed to poll
+ model -- which it is hoped will reduce propagation delay while not
+ unduly increasing the masters' load. This specification only allows
+ slaves to be notified of SOA RR changes, but the architechture of
+ NOTIFY is intended to be extensible to other RR types.
+
+ 1.3. This document intentionally gives more definition to the roles
+ of "Master," "Slave" and "Stealth" servers, their enumeration in NS
+ RRs, and the SOA MNAME field. In that sense, this document can be
+ considered an addendum to [RFC1035].
+
+
+
+
+
+
+
+
+
+Vixie Standards Track [Page 1]
+
+RFC 1996 DNS NOTIFY August 1996
+
+
+2. Definitions and Invariants
+
+ 2.1. The following definitions are used in this document:
+
+ Slave an authoritative server which uses zone transfer to
+ retrieve the zone. All slave servers are named in
+ the NS RRs for the zone.
+
+ Master any authoritative server configured to be the source
+ of zone transfer for one or more slave servers.
+
+ Primary Master master server at the root of the zone transfer
+ dependency graph. The primary master is named in the
+ zone's SOA MNAME field and optionally by an NS RR.
+ There is by definition only one primary master server
+ per zone.
+
+ Stealth like a slave server except not listed in an NS RR for
+ the zone. A stealth server, unless explicitly
+ configured to do otherwise, will set the AA bit in
+ responses and be capable of acting as a master. A
+ stealth server will only be known by other servers if
+ they are given static configuration data indicating
+ its existence.
+
+ Notify Set set of servers to be notified of changes to some
+ zone. Default is all servers named in the NS RRset,
+ except for any server also named in the SOA MNAME.
+ Some implementations will permit the name server
+ administrator to override this set or add elements to
+ it (such as, for example, stealth servers).
+
+ 2.2. The zone's servers must be organized into a dependency graph
+ such that there is a primary master, and all other servers must use
+ AXFR or IXFR either from the primary master or from some slave which
+ is also a master. No loops are permitted in the AXFR dependency
+ graph.
+
+3. NOTIFY Message
+
+ 3.1. When a master has updated one or more RRs in which slave servers
+ may be interested, the master may send the changed RR's name, class,
+ type, and optionally, new RDATA(s), to each known slave server using
+ a best efforts protocol based on the NOTIFY opcode.
+
+ 3.2. NOTIFY uses the DNS Message Format, although it uses only a
+ subset of the available fields. Fields not otherwise described
+ herein are to be filled with binary zero (0), and implementations
+
+
+
+Vixie Standards Track [Page 2]
+
+RFC 1996 DNS NOTIFY August 1996
+
+
+ must ignore all messages for which this is not the case.
+
+ 3.3. NOTIFY is similar to QUERY in that it has a request message with
+ the header QR flag "clear" and a response message with QR "set". The
+ response message contains no useful information, but its reception by
+ the master is an indication that the slave has received the NOTIFY
+ and that the master can remove the slave from any retry queue for
+ this NOTIFY event.
+
+ 3.4. The transport protocol used for a NOTIFY transaction will be UDP
+ unless the master has reason to believe that TCP is necessary; for
+ example, if a firewall has been installed between master and slave,
+ and only TCP has been allowed; or, if the changed RR is too large to
+ fit in a UDP/DNS datagram.
+
+ 3.5. If TCP is used, both master and slave must continue to offer
+ name service during the transaction, even when the TCP transaction is
+ not making progress. The NOTIFY request is sent once, and a
+ "timeout" is said to have occurred if no NOTIFY response is received
+ within a reasonable interval.
+
+ 3.6. If UDP is used, a master periodically sends a NOTIFY request to
+ a slave until either too many copies have been sent (a "timeout"), an
+ ICMP message indicating that the port is unreachable, or until a
+ NOTIFY response is received from the slave with a matching query ID,
+ QNAME, IP source address, and UDP source port number.
+
+ Note:
+ The interval between transmissions, and the total number of
+ retransmissions, should be operational parameters specifiable by
+ the name server administrator, perhaps on a per-zone basis.
+ Reasonable defaults are a 60 second interval (or timeout if
+ using TCP), and a maximum of 5 retransmissions (for UDP). It is
+ considered reasonable to use additive or exponential backoff for
+ the retry interval.
+
+ 3.7. A NOTIFY request has QDCOUNT>0, ANCOUNT>=0, AUCOUNT>=0,
+ ADCOUNT>=0. If ANCOUNT>0, then the answer section represents an
+ unsecure hint at the new RRset for this <QNAME,QCLASS,QTYPE>. A
+ slave receiving such a hint is free to treat equivilence of this
+ answer section with its local data as a "no further work needs to be
+ done" indication. If ANCOUNT=0, or ANCOUNT>0 and the answer section
+ differs from the slave's local data, then the slave should query its
+ known masters to retrieve the new data.
+
+ 3.8. In no case shall the answer section of a NOTIFY request be used
+ to update a slave's local data, or to indicate that a zone transfer
+ needs to be undertaken, or to change the slave's zone refresh timers.
+
+
+
+Vixie Standards Track [Page 3]
+
+RFC 1996 DNS NOTIFY August 1996
+
+
+ Only a "data present; data same" condition can lead a slave to act
+ differently if ANCOUNT>0 than it would if ANCOUNT=0.
+
+ 3.9. This version of the NOTIFY specification makes no use of the
+ authority or additional data sections, and so conforming
+ implementations should set AUCOUNT=0 and ADCOUNT=0 when transmitting
+ requests. Since a future revision of this specification may define a
+ backwards compatible use for either or both of these sections,
+ current implementations must ignore these sections, but not the
+ entire message, if AUCOUNT>0 and/or ADCOUNT>0.
+
+ 3.10. If a slave receives a NOTIFY request from a host that is not a
+ known master for the zone containing the QNAME, it should ignore the
+ request and produce an error message in its operations log.
+
+ Note:
+ This implies that slaves of a multihomed master must either know
+ their master by the "closest" of the master's interface
+ addresses, or must know all of the master's interface addresses.
+ Otherwise, a valid NOTIFY request might come from an address
+ that is not on the slave's state list of masters for the zone,
+ which would be an error.
+
+ 3.11. The only defined NOTIFY event at this time is that the SOA RR
+ has changed. Upon completion of a NOTIFY transaction for QTYPE=SOA,
+ the slave should behave as though the zone given in the QNAME had
+ reached its REFRESH interval (see [RFC1035]), i.e., it should query
+ its masters for the SOA of the zone given in the NOTIFY QNAME, and
+ check the answer to see if the SOA SERIAL has been incremented since
+ the last time the zone was fetched. If so, a zone transfer (either
+ AXFR or IXFR) should be initiated.
+
+ Note:
+ Because a deep server dependency graph may have multiple paths
+ from the primary master to any given slave, it is possible that
+ a slave will receive a NOTIFY from one of its known masters even
+ though the rest of its known masters have not yet updated their
+ copies of the zone. Therefore, when issuing a QUERY for the
+ zone's SOA, the query should be directed at the known master who
+ was the source of the NOTIFY event, and not at any of the other
+ known masters. This represents a departure from [RFC1035],
+ which specifies that upon expiry of the SOA REFRESH interval,
+ all known masters should be queried in turn.
+
+ 3.12. If a NOTIFY request is received by a slave who does not
+ implement the NOTIFY opcode, it will respond with a NOTIMP
+ (unimplemented feature error) message. A master server who receives
+ such a NOTIMP should consider the NOTIFY transaction complete for
+
+
+
+Vixie Standards Track [Page 4]
+
+RFC 1996 DNS NOTIFY August 1996
+
+
+ that slave.
+
+4. Details and Examples
+
+ 4.1. Retaining query state information across host reboots is
+ optional, but it is reasonable to simply execute an SOA NOTIFY
+ transaction on each authority zone when a server first starts.
+
+ 4.2. Each slave is likely to receive several copies of the same
+ NOTIFY request: One from the primary master, and one from each other
+ slave as that slave transfers the new zone and notifies its potential
+ peers. The NOTIFY protocol supports this multiplicity by requiring
+ that NOTIFY be sent by a slave/master only AFTER it has updated the
+ SOA RR or has determined that no update is necessary, which in
+ practice means after a successful zone transfer. Thus, barring
+ delivery reordering, the last NOTIFY any slave receives will be the
+ one indicating the latest change. Since a slave always requests SOAs
+ and AXFR/IXFRs only from its known masters, it will have an
+ opportunity to retry its QUERY for the SOA after each of its masters
+ have completed each zone update.
+
+ 4.3. If a master server seeks to avoid causing a large number of
+ simultaneous outbound zone transfers, it may delay for an arbitrary
+ length of time before sending a NOTIFY message to any given slave.
+ It is expected that the time will be chosen at random, so that each
+ slave will begin its transfer at a unique time. The delay shall not
+ in any case be longer than the SOA REFRESH time.
+
+ Note:
+ This delay should be a parameter that each primary master name
+ server can specify, perhaps on a per-zone basis. Random delays
+ of between 30 and 60 seconds would seem adequate if the servers
+ share a LAN and the zones are of moderate size.
+
+ 4.4. A slave which receives a valid NOTIFY should defer action on any
+ subsequent NOTIFY with the same <QNAME,QCLASS,QTYPE> until it has
+ completed the transaction begun by the first NOTIFY. This duplicate
+ rejection is necessary to avoid having multiple notifications lead to
+ pummeling the master server.
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie Standards Track [Page 5]
+
+RFC 1996 DNS NOTIFY August 1996
+
+
+ 4.5 Zone has Updated on Primary Master
+
+ Primary master sends a NOTIFY request to all servers named in Notify
+ Set. The NOTIFY request has the following characteristics:
+
+ query ID: (new)
+ op: NOTIFY (4)
+ resp: NOERROR
+ flags: AA
+ qcount: 1
+ qname: (zone name)
+ qclass: (zone class)
+ qtype: T_SOA
+
+ 4.6 Zone has Updated on a Slave that is also a Master
+
+ As above in 4.5, except that this server's Notify Set may be
+ different from the Primary Master's due to optional static
+ specification of local stealth servers.
+
+ 4.7 Slave Receives a NOTIFY Request from a Master
+
+ When a slave server receives a NOTIFY request from one of its locally
+ designated masters for the zone enclosing the given QNAME, with
+ QTYPE=SOA and QR=0, it should enter the state it would if the zone's
+ refresh timer had expired. It will also send a NOTIFY response back
+ to the NOTIFY request's source, with the following characteristics:
+
+ query ID: (same)
+ op: NOTIFY (4)
+ resp: NOERROR
+ flags: QR AA
+ qcount: 1
+ qname: (zone name)
+ qclass: (zone class)
+ qtype: T_SOA
+
+ This is intended to be identical to the NOTIFY request, except that
+ the QR bit is also set. The query ID of the response must be the
+ same as was received in the request.
+
+ 4.8 Master Receives a NOTIFY Response from Slave
+
+ When a master server receives a NOTIFY response, it deletes this
+ query from the retry queue, thus completing the "notification
+ process" of "this" RRset change to "that" server.
+
+
+
+
+
+Vixie Standards Track [Page 6]
+
+RFC 1996 DNS NOTIFY August 1996
+
+
+5. Security Considerations
+
+ We believe that the NOTIFY operation's only security considerations
+ are:
+
+ 1. That a NOTIFY request with a forged IP/UDP source address can
+ cause a slave to send spurious SOA queries to its masters,
+ leading to a benign denial of service attack if the forged
+ requests are sent very often.
+
+ 2. That TCP spoofing could be used against a slave server given
+ NOTIFY as a means of synchronizing an SOA query and UDP/DNS
+ spoofing as a means of forcing a zone transfer.
+
+6. References
+
+ [RFC1035]
+ Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [IXFR]
+ Ohta, M., "Incremental Zone Transfer", RFC 1995, August 1996.
+
+7. Author's Address
+
+ Paul Vixie
+ Internet Software Consortium
+ Star Route Box 159A
+ Woodside, CA 94062
+
+ Phone: +1 415 747 0204
+ EMail: paul@vix.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie Standards Track [Page 7]
+
diff --git a/doc/rfc/rfc2052.txt b/doc/rfc/rfc2052.txt
new file mode 100644
index 0000000..46ba362
--- /dev/null
+++ b/doc/rfc/rfc2052.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group A. Gulbrandsen
+Request for Comments: 2052 Troll Technologies
+Updates: 1035, 1183 P. Vixie
+Category: Experimental Vixie Enterprises
+ October 1996
+
+
+ A DNS RR for specifying the location of services (DNS SRV)
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. This memo does not specify an Internet standard of any
+ kind. Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Abstract
+
+ This document describes a DNS RR which specifies the location of the
+ server(s) for a specific protocol and domain (like a more general
+ form of MX).
+
+Overview and rationale
+
+ Currently, one must either know the exact address of a server to
+ contact it, or broadcast a question. This has led to, for example,
+ ftp.whatever.com aliases, the SMTP-specific MX RR, and using MAC-
+ level broadcasts to locate servers.
+
+ The SRV RR allows administrators to use several servers for a single
+ domain, to move services from host to host with little fuss, and to
+ designate some hosts as primary servers for a service and others as
+ backups.
+
+ Clients ask for a specific service/protocol for a specific domain
+ (the word domain is used here in the strict RFC 1034 sense), and get
+ back the names of any available servers.
+
+Introductory example
+
+ When a SRV-cognizant web-browser wants to retrieve
+
+ http://www.asdf.com/
+
+ it does a lookup of
+
+ http.tcp.www.asdf.com
+
+
+
+
+Gulbrandsen & Vixie Experimental [Page 1]
+
+RFC 2052 DNS SRV RR October 1996
+
+
+ and retrieves the document from one of the servers in the reply. The
+ example zone file near the end of the memo contains answering RRs for
+ this query.
+
+The format of the SRV RR
+
+ Here is the format of the SRV RR, whose DNS type code is 33:
+
+ Service.Proto.Name TTL Class SRV Priority Weight Port Target
+
+ (There is an example near the end of this document.)
+
+ Service
+ The symbolic name of the desired service, as defined in Assigned
+ Numbers or locally.
+
+ Some widely used services, notably POP, don't have a single
+ universal name. If Assigned Numbers names the service
+ indicated, that name is the only name which is legal for SRV
+ lookups. Only locally defined services may be named locally.
+ The Service is case insensitive.
+
+ Proto
+ TCP and UDP are at present the most useful values
+ for this field, though any name defined by Assigned Numbers or
+ locally may be used (as for Service). The Proto is case
+ insensitive.
+
+ Name
+ The domain this RR refers to. The SRV RR is unique in that the
+ name one searches for is not this name; the example near the end
+ shows this clearly.
+
+ TTL
+ Standard DNS meaning.
+
+ Class
+ Standard DNS meaning.
+
+ Priority
+ As for MX, the priority of this target host. A client MUST
+ attempt to contact the target host with the lowest-numbered
+ priority it can reach; target hosts with the same priority
+ SHOULD be tried in pseudorandom order. The range is 0-65535.
+
+
+
+
+
+
+
+Gulbrandsen & Vixie Experimental [Page 2]
+
+RFC 2052 DNS SRV RR October 1996
+
+
+ Weight
+ Load balancing mechanism. When selecting a target host among
+ the those that have the same priority, the chance of trying this
+ one first SHOULD be proportional to its weight. The range of
+ this number is 1-65535. Domain administrators are urged to use
+ Weight 0 when there isn't any load balancing to do, to make the
+ RR easier to read for humans (less noisy).
+
+ Port
+ The port on this target host of this service. The range is
+ 0-65535. This is often as specified in Assigned Numbers but
+ need not be.
+
+ Target
+ As for MX, the domain name of the target host. There MUST be
+ one or more A records for this name. Implementors are urged, but
+ not required, to return the A record(s) in the Additional Data
+ section. Name compression is to be used for this field.
+
+ A Target of "." means that the service is decidedly not
+ available at this domain.
+
+Domain administrator advice
+
+ Asking everyone to update their telnet (for example) clients when the
+ first internet site adds a SRV RR for Telnet/TCP is futile (even if
+ desirable). Therefore SRV will have to coexist with A record lookups
+ for a long time, and DNS administrators should try to provide A
+ records to support old clients:
+
+ - Where the services for a single domain are spread over several
+ hosts, it seems advisable to have a list of A RRs at the same
+ DNS node as the SRV RR, listing reasonable (if perhaps
+ suboptimal) fallback hosts for Telnet, NNTP and other protocols
+ likely to be used with this name. Note that some programs only
+ try the first address they get back from e.g. gethostbyname(),
+ and we don't know how widespread this behaviour is.
+
+ - Where one service is provided by several hosts, one can either
+ provide A records for all the hosts (in which case the round-
+ robin mechanism, where available, will share the load equally)
+ or just for one (presumably the fastest).
+
+ - If a host is intended to provide a service only when the main
+ server(s) is/are down, it probably shouldn't be listed in A
+ records.
+
+
+
+
+
+Gulbrandsen & Vixie Experimental [Page 3]
+
+RFC 2052 DNS SRV RR October 1996
+
+
+ - Hosts that are referenced by backup A records must use the port
+ number specified in Assigned Numbers for the service.
+
+ Currently there's a practical limit of 512 bytes for DNS replies.
+ Until all resolvers can handle larger responses, domain
+ administrators are strongly advised to keep their SRV replies below
+ 512 bytes.
+
+ All round numbers, wrote Dr. Johnson, are false, and these numbers
+ are very round: A reply packet has a 30-byte overhead plus the name
+ of the service ("telnet.tcp.asdf.com" for instance); each SRV RR adds
+ 20 bytes plus the name of the target host; each NS RR in the NS
+ section is 15 bytes plus the name of the name server host; and
+ finally each A RR in the additional data section is 20 bytes or so,
+ and there are A's for each SRV and NS RR mentioned in the answer.
+ This size estimate is extremely crude, but shouldn't underestimate
+ the actual answer size by much. If an answer may be close to the
+ limit, using e.g. "dig" to look at the actual answer is a good idea.
+
+The "Weight" field
+
+ Weight, the load balancing field, is not quite satisfactory, but the
+ actual load on typical servers changes much too quickly to be kept
+ around in DNS caches. It seems to the authors that offering
+ administrators a way to say "this machine is three times as fast as
+ that one" is the best that can practically be done.
+
+ The only way the authors can see of getting a "better" load figure is
+ asking a separate server when the client selects a server and
+ contacts it. For short-lived services like SMTP an extra step in the
+ connection establishment seems too expensive, and for long-lived
+ services like telnet, the load figure may well be thrown off a minute
+ after the connection is established when someone else starts or
+ finishes a heavy job.
+
+The Port number
+
+ Currently, the translation from service name to port number happens
+ at the client, often using a file such as /etc/services.
+
+ Moving this information to the DNS makes it less necessary to update
+ these files on every single computer of the net every time a new
+ service is added, and makes it possible to move standard services out
+ of the "root-only" port range on unix
+
+
+
+
+
+
+
+Gulbrandsen & Vixie Experimental [Page 4]
+
+RFC 2052 DNS SRV RR October 1996
+
+
+Usage rules
+
+ A SRV-cognizant client SHOULD use this procedure to locate a list of
+ servers and connect to the preferred one:
+
+ Do a lookup for QNAME=service.protocol.target, QCLASS=IN,
+ QTYPE=SRV.
+
+ If the reply is NOERROR, ANCOUNT>0 and there is at least one SRV
+ RR which specifies the requested Service and Protocol in the
+ reply:
+
+ If there is precisely one SRV RR, and its Target is "."
+ (the root domain), abort.
+
+ Else, for all such RR's, build a list of (Priority, Weight,
+ Target) tuples
+
+ Sort the list by priority (lowest number first)
+
+ Create a new empty list
+
+ For each distinct priority level
+ While there are still elements left at this priority
+ level
+ Select an element randomly, with probability
+ Weight, and move it to the tail of the new list
+
+ For each element in the new list
+
+ query the DNS for A RR's for the Target or use any
+ RR's found in the Additional Data secion of the
+ earlier SRV query.
+
+ for each A RR found, try to connect to the (protocol,
+ address, service).
+
+ else if the service desired is SMTP
+
+ skip to RFC 974 (MX).
+
+ else
+
+ Do a lookup for QNAME=target, QCLASS=IN, QTYPE=A
+
+ for each A RR found, try to connect to the (protocol,
+ address, service)
+
+
+
+
+Gulbrandsen & Vixie Experimental [Page 5]
+
+RFC 2052 DNS SRV RR October 1996
+
+
+ Notes:
+
+ - Port numbers SHOULD NOT be used in place of the symbolic service
+ or protocol names (for the same reason why variant names cannot
+ be allowed: Applications would have to do two or more lookups).
+
+ - If a truncated response comes back from an SRV query, and the
+ Additional Data section has at least one complete RR in it, the
+ answer MUST be considered complete and the client resolver
+ SHOULD NOT retry the query using TCP, but use normal UDP queries
+ for A RR's missing from the Additional Data section.
+
+ - A client MAY use means other than Weight to choose among target
+ hosts with equal Priority.
+
+ - A client MUST parse all of the RR's in the reply.
+
+ - If the Additional Data section doesn't contain A RR's for all
+ the SRV RR's and the client may want to connect to the target
+ host(s) involved, the client MUST look up the A RR(s). (This
+ happens quite often when the A RR has shorter TTL than the SRV
+ or NS RR's.)
+
+ - A future standard could specify that a SRV RR whose Protocol was
+ TCP and whose Service was SMTP would override RFC 974's rules
+ with regard to the use of an MX RR. This would allow firewalled
+ organizations with several SMTP relays to control the load
+ distribution using the Weight field.
+
+ - Future protocols could be designed to use SRV RR lookups as the
+ means by which clients locate their servers.
+
+Fictional example
+
+ This is (part of) the zone file for asdf.com, a still-unused domain:
+
+ $ORIGIN asdf.com.
+ @ SOA server.asdf.com. root.asdf.com. (
+ 1995032001 3600 3600 604800 86400 )
+ NS server.asdf.com.
+ NS ns1.ip-provider.net.
+ NS ns2.ip-provider.net.
+ ftp.tcp SRV 0 0 21 server.asdf.com.
+ finger.tcp SRV 0 0 79 server.asdf.com.
+ ; telnet - use old-slow-box or new-fast-box if either is
+ ; available, make three quarters of the logins go to
+ ; new-fast-box.
+ telnet.tcp SRV 0 1 23 old-slow-box.asdf.com.
+
+
+
+Gulbrandsen & Vixie Experimental [Page 6]
+
+RFC 2052 DNS SRV RR October 1996
+
+
+ SRV 0 3 23 new-fast-box.asdf.com.
+ ; if neither old-slow-box or new-fast-box is up, switch to
+ ; using the sysdmin's box and the server
+ SRV 1 0 23 sysadmins-box.asdf.com.
+ SRV 1 0 23 server.asdf.com.
+ ; HTTP - server is the main server, new-fast-box is the backup
+ ; (On new-fast-box, the HTTP daemon runs on port 8000)
+ http.tcp SRV 0 0 80 server.asdf.com.
+ SRV 10 0 8000 new-fast-box.asdf.com.
+ ; since we want to support both http://asdf.com/ and
+ ; http://www.asdf.com/ we need the next two RRs as well
+ http.tcp.www SRV 0 0 80 server.asdf.com.
+ SRV 10 0 8000 new-fast-box.asdf.com.
+ ; SMTP - mail goes to the server, and to the IP provider if
+ ; the net is down
+ smtp.tcp SRV 0 0 25 server.asdf.com.
+ SRV 1 0 25 mailhost.ip-provider.net.
+ @ MX 0 server.asdf.com.
+ MX 1 mailhost.ip-provider.net.
+ ; NNTP - use the IP providers's NNTP server
+ nntp.tcp SRV 0 0 119 nntphost.ip-provider.net.
+ ; IDB is an locally defined protocol
+ idb.tcp SRV 0 0 2025 new-fast-box.asdf.com.
+ ; addresses
+ server A 172.30.79.10
+ old-slow-box A 172.30.79.11
+ sysadmins-box A 172.30.79.12
+ new-fast-box A 172.30.79.13
+ ; backup A records - new-fast-box and old-slow-box are
+ ; included, naturally, and server is too, but might go
+ ; if the load got too bad
+ @ A 172.30.79.10
+ A 172.30.79.11
+ A 172.30.79.13
+ ; backup A RR for www.asdf.com
+ www A 172.30.79.10
+ ; NO other services are supported
+ *.tcp SRV 0 0 0 .
+ *.udp SRV 0 0 0 .
+
+ In this example, a telnet connection to "asdf.com." needs an SRV
+ lookup of "telnet.tcp.asdf.com." and possibly A lookups of "new-
+ fast-box.asdf.com." and/or the other hosts named. The size of the
+ SRV reply is approximately 365 bytes:
+
+ 30 bytes general overhead
+ 20 bytes for the query string, "telnet.tcp.asdf.com."
+ 130 bytes for 4 SRV RR's, 20 bytes each plus the lengths of "new-
+
+
+
+Gulbrandsen & Vixie Experimental [Page 7]
+
+RFC 2052 DNS SRV RR October 1996
+
+
+ fast-box", "old-slow-box", "server" and "sysadmins-box" -
+ "asdf.com" in the query section is quoted here and doesn't
+ need to be counted again.
+ 75 bytes for 3 NS RRs, 15 bytes each plus the lengths of
+ "server", "ns1.ip-provider.net." and "ns2" - again, "ip-
+ provider.net." is quoted and only needs to be counted once.
+ 120 bytes for the 6 A RR's mentioned by the SRV and NS RR's.
+
+Refererences
+
+ RFC 1918: Rekhter, Y., Moskowitz, R., Karrenberg, D., de Groot, G.,
+ and E. Lear, "Address Allocation for Private Internets",
+ RFC 1918, February 1996.
+
+ RFC 1916 Berkowitz, H., Ferguson, P, Leland, W. and P. Nesser,
+ "Enterprise Renumbering: Experience and Information
+ Solicitation", RFC 1916, February 1996.
+
+ RFC 1912 Barr, D., "Common DNS Operational and Configuration
+ Errors", RFC 1912, February 1996.
+
+ RFC 1900: Carpenter, B., and Y. Rekhter, "Renumbering Needs Work",
+ RFC 1900, February 1996.
+
+ RFC 1920: Postel, J., "INTERNET OFFICIAL PROTOCOL STANDARDS",
+ STD 1, RFC 1920, March 1996.
+
+ RFC 1814: Gerich, E., "Unique Addresses are Good", RFC 1814, June
+ 1995.
+
+ RFC 1794: Brisco, T., "DNS Support for Load Balancing", April 1995.
+
+ RFC 1713: Romao, A., "Tools for DNS debugging", November 1994.
+
+ RFC 1712: Farrell, C., Schulze, M., Pleitner, S., and D. Baldoni,
+ "DNS Encoding of Geographical Location", RFC 1712, November
+ 1994.
+
+ RFC 1706: Manning, B. and R. Colella, "DNS NSAP Resource Records",
+ RFC 1706, October 1994.
+
+ RFC 1700: Reynolds, J., and J. Postel, "ASSIGNED NUMBERS",
+ STD 2, RFC 1700, October 1994.
+
+ RFC 1183: Ullmann, R., Mockapetris, P., Mamakos, L., and
+ C. Everhart, "New DNS RR Definitions", RFC 1183, November
+ 1990.
+
+
+
+
+Gulbrandsen & Vixie Experimental [Page 8]
+
+RFC 2052 DNS SRV RR October 1996
+
+
+ RFC 1101: Mockapetris, P., "DNS encoding of network names and other
+ types", RFC 1101, April 1989.
+
+ RFC 1035: Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ RFC 1034: Mockapetris, P., "Domain names - concepts and
+ facilities", STD 13, RFC 1034, November 1987.
+
+ RFC 1033: Lottor, M., "Domain administrators operations guide",
+ RFC 1033, November 1987.
+
+ RFC 1032: Stahl, M., "Domain administrators guide", RFC 1032,
+ November 1987.
+
+ RFC 974: Partridge, C., "Mail routing and the domain system",
+ STD 14, RFC 974, January 1986.
+
+Security Considerations
+
+ The authors believes this RR to not cause any new security problems.
+ Some problems become more visible, though.
+
+ - The ability to specify ports on a fine-grained basis obviously
+ changes how a router can filter packets. It becomes impossible
+ to block internal clients from accessing specific external
+ services, slightly harder to block internal users from running
+ unautorised services, and more important for the router
+ operations and DNS operations personnel to cooperate.
+
+ - There is no way a site can keep its hosts from being referenced
+ as servers (as, indeed, some sites become unwilling secondary
+ MXes today). This could lead to denial of service.
+
+ - With SRV, DNS spoofers can supply false port numbers, as well as
+ host names and addresses. The authors do not see any practical
+ effect of this.
+
+ We assume that as the DNS-security people invent new features, DNS
+ servers will return the relevant RRs in the Additional Data section
+ when answering an SRV query.
+
+
+
+
+
+
+
+
+
+
+Gulbrandsen & Vixie Experimental [Page 9]
+
+RFC 2052 DNS SRV RR October 1996
+
+
+Authors' Addresses
+
+ Arnt Gulbrandsen
+ Troll Tech
+ Postboks 6133 Etterstad
+ N-0602 Oslo
+ Norway
+
+ Phone: +47 22646966
+ EMail: agulbra@troll.no
+
+
+ Paul Vixie
+ Vixie Enterprises
+ Star Route 159A
+ Woodside, CA 94062
+
+ Phone: (415) 747-0204
+ EMail: paul@vix.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gulbrandsen & Vixie Experimental [Page 10]
+
diff --git a/doc/rfc/rfc2104.txt b/doc/rfc/rfc2104.txt
new file mode 100644
index 0000000..a205103
--- /dev/null
+++ b/doc/rfc/rfc2104.txt
@@ -0,0 +1,620 @@
+
+
+
+
+
+
+Network Working Group H. Krawczyk
+Request for Comments: 2104 IBM
+Category: Informational M. Bellare
+ UCSD
+ R. Canetti
+ IBM
+ February 1997
+
+
+ HMAC: Keyed-Hashing for Message Authentication
+
+Status of This Memo
+
+ This memo provides information for the Internet community. This memo
+ does not specify an Internet standard of any kind. Distribution of
+ this memo is unlimited.
+
+Abstract
+
+ This document describes HMAC, a mechanism for message authentication
+ using cryptographic hash functions. HMAC can be used with any
+ iterative cryptographic hash function, e.g., MD5, SHA-1, in
+ combination with a secret shared key. The cryptographic strength of
+ HMAC depends on the properties of the underlying hash function.
+
+1. Introduction
+
+ Providing a way to check the integrity of information transmitted
+ over or stored in an unreliable medium is a prime necessity in the
+ world of open computing and communications. Mechanisms that provide
+ such integrity check based on a secret key are usually called
+ "message authentication codes" (MAC). Typically, message
+ authentication codes are used between two parties that share a secret
+ key in order to validate information transmitted between these
+ parties. In this document we present such a MAC mechanism based on
+ cryptographic hash functions. This mechanism, called HMAC, is based
+ on work by the authors [BCK1] where the construction is presented and
+ cryptographically analyzed. We refer to that work for the details on
+ the rationale and security analysis of HMAC, and its comparison to
+ other keyed-hash methods.
+
+
+
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 1]
+
+RFC 2104 HMAC February 1997
+
+
+ HMAC can be used in combination with any iterated cryptographic hash
+ function. MD5 and SHA-1 are examples of such hash functions. HMAC
+ also uses a secret key for calculation and verification of the
+ message authentication values. The main goals behind this
+ construction are
+
+ * To use, without modifications, available hash functions.
+ In particular, hash functions that perform well in software,
+ and for which code is freely and widely available.
+
+ * To preserve the original performance of the hash function without
+ incurring a significant degradation.
+
+ * To use and handle keys in a simple way.
+
+ * To have a well understood cryptographic analysis of the strength of
+ the authentication mechanism based on reasonable assumptions on the
+ underlying hash function.
+
+ * To allow for easy replaceability of the underlying hash function in
+ case that faster or more secure hash functions are found or
+ required.
+
+ This document specifies HMAC using a generic cryptographic hash
+ function (denoted by H). Specific instantiations of HMAC need to
+ define a particular hash function. Current candidates for such hash
+ functions include SHA-1 [SHA], MD5 [MD5], RIPEMD-128/160 [RIPEMD].
+ These different realizations of HMAC will be denoted by HMAC-SHA1,
+ HMAC-MD5, HMAC-RIPEMD, etc.
+
+ Note: To the date of writing of this document MD5 and SHA-1 are the
+ most widely used cryptographic hash functions. MD5 has been recently
+ shown to be vulnerable to collision search attacks [Dobb]. This
+ attack and other currently known weaknesses of MD5 do not compromise
+ the use of MD5 within HMAC as specified in this document (see
+ [Dobb]); however, SHA-1 appears to be a cryptographically stronger
+ function. To this date, MD5 can be considered for use in HMAC for
+ applications where the superior performance of MD5 is critical. In
+ any case, implementers and users need to be aware of possible
+ cryptanalytic developments regarding any of these cryptographic hash
+ functions, and the eventual need to replace the underlying hash
+ function. (See section 6 for more information on the security of
+ HMAC.)
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 2]
+
+RFC 2104 HMAC February 1997
+
+
+2. Definition of HMAC
+
+ The definition of HMAC requires a cryptographic hash function, which
+ we denote by H, and a secret key K. We assume H to be a cryptographic
+ hash function where data is hashed by iterating a basic compression
+ function on blocks of data. We denote by B the byte-length of such
+ blocks (B=64 for all the above mentioned examples of hash functions),
+ and by L the byte-length of hash outputs (L=16 for MD5, L=20 for
+ SHA-1). The authentication key K can be of any length up to B, the
+ block length of the hash function. Applications that use keys longer
+ than B bytes will first hash the key using H and then use the
+ resultant L byte string as the actual key to HMAC. In any case the
+ minimal recommended length for K is L bytes (as the hash output
+ length). See section 3 for more information on keys.
+
+ We define two fixed and different strings ipad and opad as follows
+ (the 'i' and 'o' are mnemonics for inner and outer):
+
+ ipad = the byte 0x36 repeated B times
+ opad = the byte 0x5C repeated B times.
+
+ To compute HMAC over the data `text' we perform
+
+ H(K XOR opad, H(K XOR ipad, text))
+
+ Namely,
+
+ (1) append zeros to the end of K to create a B byte string
+ (e.g., if K is of length 20 bytes and B=64, then K will be
+ appended with 44 zero bytes 0x00)
+ (2) XOR (bitwise exclusive-OR) the B byte string computed in step
+ (1) with ipad
+ (3) append the stream of data 'text' to the B byte string resulting
+ from step (2)
+ (4) apply H to the stream generated in step (3)
+ (5) XOR (bitwise exclusive-OR) the B byte string computed in
+ step (1) with opad
+ (6) append the H result from step (4) to the B byte string
+ resulting from step (5)
+ (7) apply H to the stream generated in step (6) and output
+ the result
+
+ For illustration purposes, sample code based on MD5 is provided as an
+ appendix.
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 3]
+
+RFC 2104 HMAC February 1997
+
+
+3. Keys
+
+ The key for HMAC can be of any length (keys longer than B bytes are
+ first hashed using H). However, less than L bytes is strongly
+ discouraged as it would decrease the security strength of the
+ function. Keys longer than L bytes are acceptable but the extra
+ length would not significantly increase the function strength. (A
+ longer key may be advisable if the randomness of the key is
+ considered weak.)
+
+ Keys need to be chosen at random (or using a cryptographically strong
+ pseudo-random generator seeded with a random seed), and periodically
+ refreshed. (Current attacks do not indicate a specific recommended
+ frequency for key changes as these attacks are practically
+ infeasible. However, periodic key refreshment is a fundamental
+ security practice that helps against potential weaknesses of the
+ function and keys, and limits the damage of an exposed key.)
+
+4. Implementation Note
+
+ HMAC is defined in such a way that the underlying hash function H can
+ be used with no modification to its code. In particular, it uses the
+ function H with the pre-defined initial value IV (a fixed value
+ specified by each iterative hash function to initialize its
+ compression function). However, if desired, a performance
+ improvement can be achieved at the cost of (possibly) modifying the
+ code of H to support variable IVs.
+
+ The idea is that the intermediate results of the compression function
+ on the B-byte blocks (K XOR ipad) and (K XOR opad) can be precomputed
+ only once at the time of generation of the key K, or before its first
+ use. These intermediate results are stored and then used to
+ initialize the IV of H each time that a message needs to be
+ authenticated. This method saves, for each authenticated message,
+ the application of the compression function of H on two B-byte blocks
+ (i.e., on (K XOR ipad) and (K XOR opad)). Such a savings may be
+ significant when authenticating short streams of data. We stress
+ that the stored intermediate values need to be treated and protected
+ the same as secret keys.
+
+ Choosing to implement HMAC in the above way is a decision of the
+ local implementation and has no effect on inter-operability.
+
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 4]
+
+RFC 2104 HMAC February 1997
+
+
+5. Truncated output
+
+ A well-known practice with message authentication codes is to
+ truncate the output of the MAC and output only part of the bits
+ (e.g., [MM, ANSI]). Preneel and van Oorschot [PV] show some
+ analytical advantages of truncating the output of hash-based MAC
+ functions. The results in this area are not absolute as for the
+ overall security advantages of truncation. It has advantages (less
+ information on the hash result available to an attacker) and
+ disadvantages (less bits to predict for the attacker). Applications
+ of HMAC can choose to truncate the output of HMAC by outputting the t
+ leftmost bits of the HMAC computation for some parameter t (namely,
+ the computation is carried in the normal way as defined in section 2
+ above but the end result is truncated to t bits). We recommend that
+ the output length t be not less than half the length of the hash
+ output (to match the birthday attack bound) and not less than 80 bits
+ (a suitable lower bound on the number of bits that need to be
+ predicted by an attacker). We propose denoting a realization of HMAC
+ that uses a hash function H with t bits of output as HMAC-H-t. For
+ example, HMAC-SHA1-80 denotes HMAC computed using the SHA-1 function
+ and with the output truncated to 80 bits. (If the parameter t is not
+ specified, e.g. HMAC-MD5, then it is assumed that all the bits of the
+ hash are output.)
+
+6. Security
+
+ The security of the message authentication mechanism presented here
+ depends on cryptographic properties of the hash function H: the
+ resistance to collision finding (limited to the case where the
+ initial value is secret and random, and where the output of the
+ function is not explicitly available to the attacker), and the
+ message authentication property of the compression function of H when
+ applied to single blocks (in HMAC these blocks are partially unknown
+ to an attacker as they contain the result of the inner H computation
+ and, in particular, cannot be fully chosen by the attacker).
+
+ These properties, and actually stronger ones, are commonly assumed
+ for hash functions of the kind used with HMAC. In particular, a hash
+ function for which the above properties do not hold would become
+ unsuitable for most (probably, all) cryptographic applications,
+ including alternative message authentication schemes based on such
+ functions. (For a complete analysis and rationale of the HMAC
+ function the reader is referred to [BCK1].)
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 5]
+
+RFC 2104 HMAC February 1997
+
+
+ Given the limited confidence gained so far as for the cryptographic
+ strength of candidate hash functions, it is important to observe the
+ following two properties of the HMAC construction and its secure use
+ for message authentication:
+
+ 1. The construction is independent of the details of the particular
+ hash function H in use and then the latter can be replaced by any
+ other secure (iterative) cryptographic hash function.
+
+ 2. Message authentication, as opposed to encryption, has a
+ "transient" effect. A published breaking of a message authentication
+ scheme would lead to the replacement of that scheme, but would have
+ no adversarial effect on information authenticated in the past. This
+ is in sharp contrast with encryption, where information encrypted
+ today may suffer from exposure in the future if, and when, the
+ encryption algorithm is broken.
+
+ The strongest attack known against HMAC is based on the frequency of
+ collisions for the hash function H ("birthday attack") [PV,BCK2], and
+ is totally impractical for minimally reasonable hash functions.
+
+ As an example, if we consider a hash function like MD5 where the
+ output length equals L=16 bytes (128 bits) the attacker needs to
+ acquire the correct message authentication tags computed (with the
+ _same_ secret key K!) on about 2**64 known plaintexts. This would
+ require the processing of at least 2**64 blocks under H, an
+ impossible task in any realistic scenario (for a block length of 64
+ bytes this would take 250,000 years in a continuous 1Gbps link, and
+ without changing the secret key K during all this time). This attack
+ could become realistic only if serious flaws in the collision
+ behavior of the function H are discovered (e.g. collisions found
+ after 2**30 messages). Such a discovery would determine the immediate
+ replacement of the function H (the effects of such failure would be
+ far more severe for the traditional uses of H in the context of
+ digital signatures, public key certificates, etc.).
+
+ Note: this attack needs to be strongly contrasted with regular
+ collision attacks on cryptographic hash functions where no secret key
+ is involved and where 2**64 off-line parallelizable (!) operations
+ suffice to find collisions. The latter attack is approaching
+ feasibility [VW] while the birthday attack on HMAC is totally
+ impractical. (In the above examples, if one uses a hash function
+ with, say, 160 bit of output then 2**64 should be replaced by 2**80.)
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 6]
+
+RFC 2104 HMAC February 1997
+
+
+ A correct implementation of the above construction, the choice of
+ random (or cryptographically pseudorandom) keys, a secure key
+ exchange mechanism, frequent key refreshments, and good secrecy
+ protection of keys are all essential ingredients for the security of
+ the integrity verification mechanism provided by HMAC.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 7]
+
+RFC 2104 HMAC February 1997
+
+
+Appendix -- Sample Code
+
+ For the sake of illustration we provide the following sample code for
+ the implementation of HMAC-MD5 as well as some corresponding test
+ vectors (the code is based on MD5 code as described in [MD5]).
+
+/*
+** Function: hmac_md5
+*/
+
+void
+hmac_md5(text, text_len, key, key_len, digest)
+unsigned char* text; /* pointer to data stream */
+int text_len; /* length of data stream */
+unsigned char* key; /* pointer to authentication key */
+int key_len; /* length of authentication key */
+caddr_t digest; /* caller digest to be filled in */
+
+{
+ MD5_CTX context;
+ unsigned char k_ipad[65]; /* inner padding -
+ * key XORd with ipad
+ */
+ unsigned char k_opad[65]; /* outer padding -
+ * key XORd with opad
+ */
+ unsigned char tk[16];
+ int i;
+ /* if key is longer than 64 bytes reset it to key=MD5(key) */
+ if (key_len > 64) {
+
+ MD5_CTX tctx;
+
+ MD5Init(&tctx);
+ MD5Update(&tctx, key, key_len);
+ MD5Final(tk, &tctx);
+
+ key = tk;
+ key_len = 16;
+ }
+
+ /*
+ * the HMAC_MD5 transform looks like:
+ *
+ * MD5(K XOR opad, MD5(K XOR ipad, text))
+ *
+ * where K is an n byte key
+ * ipad is the byte 0x36 repeated 64 times
+
+
+
+Krawczyk, et. al. Informational [Page 8]
+
+RFC 2104 HMAC February 1997
+
+
+ * opad is the byte 0x5c repeated 64 times
+ * and text is the data being protected
+ */
+
+ /* start out by storing key in pads */
+ bzero( k_ipad, sizeof k_ipad);
+ bzero( k_opad, sizeof k_opad);
+ bcopy( key, k_ipad, key_len);
+ bcopy( key, k_opad, key_len);
+
+ /* XOR key with ipad and opad values */
+ for (i=0; i<64; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+ /*
+ * perform inner MD5
+ */
+ MD5Init(&context); /* init context for 1st
+ * pass */
+ MD5Update(&context, k_ipad, 64) /* start with inner pad */
+ MD5Update(&context, text, text_len); /* then text of datagram */
+ MD5Final(digest, &context); /* finish up 1st pass */
+ /*
+ * perform outer MD5
+ */
+ MD5Init(&context); /* init context for 2nd
+ * pass */
+ MD5Update(&context, k_opad, 64); /* start with outer pad */
+ MD5Update(&context, digest, 16); /* then results of 1st
+ * hash */
+ MD5Final(digest, &context); /* finish up 2nd pass */
+}
+
+Test Vectors (Trailing '\0' of a character string not included in test):
+
+ key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+ key_len = 16 bytes
+ data = "Hi There"
+ data_len = 8 bytes
+ digest = 0x9294727a3638bb1c13f48ef8158bfc9d
+
+ key = "Jefe"
+ data = "what do ya want for nothing?"
+ data_len = 28 bytes
+ digest = 0x750c783e6ab0b503eaa86e310a5db738
+
+ key = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+
+
+Krawczyk, et. al. Informational [Page 9]
+
+RFC 2104 HMAC February 1997
+
+
+ key_len 16 bytes
+ data = 0xDDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD...
+ ..DDDDDDDDDDDDDDDDDDDD
+ data_len = 50 bytes
+ digest = 0x56be34521d144c88dbb8c733f0e8b3f6
+
+Acknowledgments
+
+ Pau-Chen Cheng, Jeff Kraemer, and Michael Oehler, have provided
+ useful comments on early drafts, and ran the first interoperability
+ tests of this specification. Jeff and Pau-Chen kindly provided the
+ sample code and test vectors that appear in the appendix. Burt
+ Kaliski, Bart Preneel, Matt Robshaw, Adi Shamir, and Paul van
+ Oorschot have provided useful comments and suggestions during the
+ investigation of the HMAC construction.
+
+References
+
+ [ANSI] ANSI X9.9, "American National Standard for Financial
+ Institution Message Authentication (Wholesale)," American
+ Bankers Association, 1981. Revised 1986.
+
+ [Atk] Atkinson, R., "IP Authentication Header", RFC 1826, August
+ 1995.
+
+ [BCK1] M. Bellare, R. Canetti, and H. Krawczyk,
+ "Keyed Hash Functions and Message Authentication",
+ Proceedings of Crypto'96, LNCS 1109, pp. 1-15.
+ (http://www.research.ibm.com/security/keyed-md5.html)
+
+ [BCK2] M. Bellare, R. Canetti, and H. Krawczyk,
+ "Pseudorandom Functions Revisited: The Cascade Construction",
+ Proceedings of FOCS'96.
+
+ [Dobb] H. Dobbertin, "The Status of MD5 After a Recent Attack",
+ RSA Labs' CryptoBytes, Vol. 2 No. 2, Summer 1996.
+ http://www.rsa.com/rsalabs/pubs/cryptobytes.html
+
+ [PV] B. Preneel and P. van Oorschot, "Building fast MACs from hash
+ functions", Advances in Cryptology -- CRYPTO'95 Proceedings,
+ Lecture Notes in Computer Science, Springer-Verlag Vol.963,
+ 1995, pp. 1-14.
+
+ [MD5] Rivest, R., "The MD5 Message-Digest Algorithm",
+ RFC 1321, April 1992.
+
+
+
+Krawczyk, et. al. Informational [Page 10]
+
+RFC 2104 HMAC February 1997
+
+
+ [MM] Meyer, S. and Matyas, S.M., Cryptography, New York Wiley,
+ 1982.
+
+ [RIPEMD] H. Dobbertin, A. Bosselaers, and B. Preneel, "RIPEMD-160: A
+ strengthened version of RIPEMD", Fast Software Encryption,
+ LNCS Vol 1039, pp. 71-82.
+ ftp://ftp.esat.kuleuven.ac.be/pub/COSIC/bosselae/ripemd/.
+
+ [SHA] NIST, FIPS PUB 180-1: Secure Hash Standard, April 1995.
+
+ [Tsu] G. Tsudik, "Message authentication with one-way hash
+ functions", In Proceedings of Infocom'92, May 1992.
+ (Also in "Access Control and Policy Enforcement in
+ Internetworks", Ph.D. Dissertation, Computer Science
+ Department, University of Southern California, April 1991.)
+
+ [VW] P. van Oorschot and M. Wiener, "Parallel Collision
+ Search with Applications to Hash Functions and Discrete
+ Logarithms", Proceedings of the 2nd ACM Conf. Computer and
+ Communications Security, Fairfax, VA, November 1994.
+
+Authors' Addresses
+
+ Hugo Krawczyk
+ IBM T.J. Watson Research Center
+ P.O.Box 704
+ Yorktown Heights, NY 10598
+
+ EMail: hugo@watson.ibm.com
+
+ Mihir Bellare
+ Dept of Computer Science and Engineering
+ Mail Code 0114
+ University of California at San Diego
+ 9500 Gilman Drive
+ La Jolla, CA 92093
+
+ EMail: mihir@cs.ucsd.edu
+
+ Ran Canetti
+ IBM T.J. Watson Research Center
+ P.O.Box 704
+ Yorktown Heights, NY 10598
+
+ EMail: canetti@watson.ibm.com
+
+
+
+
+
+
+Krawczyk, et. al. Informational [Page 11]
+
+
diff --git a/doc/rfc/rfc2119.txt b/doc/rfc/rfc2119.txt
new file mode 100644
index 0000000..e31fae4
--- /dev/null
+++ b/doc/rfc/rfc2119.txt
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+Network Working Group S. Bradner
+Request for Comments: 2119 Harvard University
+BCP: 14 March 1997
+Category: Best Current Practice
+
+
+ Key words for use in RFCs to Indicate Requirement Levels
+
+Status of this Memo
+
+ This document specifies an Internet Best Current Practices for the
+ Internet Community, and requests discussion and suggestions for
+ improvements. Distribution of this memo is unlimited.
+
+Abstract
+
+ In many standards track documents several words are used to signify
+ the requirements in the specification. These words are often
+ capitalized. This document defines these words as they should be
+ interpreted in IETF documents. Authors who follow these guidelines
+ should incorporate this phrase near the beginning of their document:
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
+ NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and
+ "OPTIONAL" in this document are to be interpreted as described in
+ RFC 2119.
+
+ Note that the force of these words is modified by the requirement
+ level of the document in which they are used.
+
+1. MUST This word, or the terms "REQUIRED" or "SHALL", mean that the
+ definition is an absolute requirement of the specification.
+
+2. MUST NOT This phrase, or the phrase "SHALL NOT", mean that the
+ definition is an absolute prohibition of the specification.
+
+3. SHOULD This word, or the adjective "RECOMMENDED", mean that there
+ may exist valid reasons in particular circumstances to ignore a
+ particular item, but the full implications must be understood and
+ carefully weighed before choosing a different course.
+
+4. SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean that
+ there may exist valid reasons in particular circumstances when the
+ particular behavior is acceptable or even useful, but the full
+ implications should be understood and the case carefully weighed
+ before implementing any behavior described with this label.
+
+
+
+
+
+Bradner Best Current Practice [Page 1]
+
+RFC 2119 RFC Key Words March 1997
+
+
+5. MAY This word, or the adjective "OPTIONAL", mean that an item is
+ truly optional. One vendor may choose to include the item because a
+ particular marketplace requires it or because the vendor feels that
+ it enhances the product while another vendor may omit the same item.
+ An implementation which does not include a particular option MUST be
+ prepared to interoperate with another implementation which does
+ include the option, though perhaps with reduced functionality. In the
+ same vein an implementation which does include a particular option
+ MUST be prepared to interoperate with another implementation which
+ does not include the option (except, of course, for the feature the
+ option provides.)
+
+6. Guidance in the use of these Imperatives
+
+ Imperatives of the type defined in this memo must be used with care
+ and sparingly. In particular, they MUST only be used where it is
+ actually required for interoperation or to limit behavior which has
+ potential for causing harm (e.g., limiting retransmisssions) For
+ example, they must not be used to try to impose a particular method
+ on implementors where the method is not required for
+ interoperability.
+
+7. Security Considerations
+
+ These terms are frequently used to specify behavior with security
+ implications. The effects on security of not implementing a MUST or
+ SHOULD, or doing something the specification says MUST NOT or SHOULD
+ NOT be done may be very subtle. Document authors should take the time
+ to elaborate the security implications of not following
+ recommendations or requirements as most implementors will not have
+ had the benefit of the experience and discussion that produced the
+ specification.
+
+8. Acknowledgments
+
+ The definitions of these terms are an amalgam of definitions taken
+ from a number of RFCs. In addition, suggestions have been
+ incorporated from a number of people including Robert Ullmann, Thomas
+ Narten, Neal McBurnett, and Robert Elz.
+
+
+
+
+
+
+
+
+
+
+
+
+Bradner Best Current Practice [Page 2]
+
+RFC 2119 RFC Key Words March 1997
+
+
+9. Author's Address
+
+ Scott Bradner
+ Harvard University
+ 1350 Mass. Ave.
+ Cambridge, MA 02138
+
+ phone - +1 617 495 3864
+
+ email - sob@harvard.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bradner Best Current Practice [Page 3]
+
diff --git a/doc/rfc/rfc2133.txt b/doc/rfc/rfc2133.txt
new file mode 100644
index 0000000..ea66cf0
--- /dev/null
+++ b/doc/rfc/rfc2133.txt
@@ -0,0 +1,1795 @@
+
+
+
+
+
+
+Network Working Group R. Gilligan
+Request for Comments: 2133 Freegate
+Category: Informational S. Thomson
+ Bellcore
+ J. Bound
+ Digital
+ W. Stevens
+ Consultant
+ April 1997
+
+ Basic Socket Interface Extensions for IPv6
+
+Status of this Memo
+
+ This memo provides information for the Internet community. This memo
+ does not specify an Internet standard of any kind. Distribution of
+ this memo is unlimited.
+
+Abstract
+
+ The de facto standard application program interface (API) for TCP/IP
+ applications is the "sockets" interface. Although this API was
+ developed for Unix in the early 1980s it has also been implemented on
+ a wide variety of non-Unix systems. TCP/IP applications written
+ using the sockets API have in the past enjoyed a high degree of
+ portability and we would like the same portability with IPv6
+ applications. But changes are required to the sockets API to support
+ IPv6 and this memo describes these changes. These include a new
+ socket address structure to carry IPv6 addresses, new address
+ conversion functions, and some new socket options. These extensions
+ are designed to provide access to the basic IPv6 features required by
+ TCP and UDP applications, including multicasting, while introducing a
+ minimum of change into the system and providing complete
+ compatibility for existing IPv4 applications. Additional extensions
+ for advanced IPv6 features (raw sockets and access to the IPv6
+ extension headers) are defined in another document [5].
+
+Table of Contents
+
+ 1. Introduction ................................................ 2
+ 2. Design Considerations ....................................... 3
+ 2.1. What Needs to be Changed .................................. 3
+ 2.2. Data Types ................................................ 5
+ 2.3. Headers ................................................... 5
+ 2.4. Structures ................................................ 5
+ 3. Socket Interface ............................................ 5
+ 3.1. IPv6 Address Family and Protocol Family ................... 5
+ 3.2. IPv6 Address Structure .................................... 6
+
+
+
+Gilligan, et. al. Informational [Page 1]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ 3.3. Socket Address Structure for 4.3BSD-Based Systems ......... 6
+ 3.4. Socket Address Structure for 4.4BSD-Based Systems ......... 7
+ 3.5. The Socket Functions ...................................... 8
+ 3.6. Compatibility with IPv4 Applications ...................... 9
+ 3.7. Compatibility with IPv4 Nodes ............................. 9
+ 3.8. IPv6 Wildcard Address ..................................... 10
+ 3.9. IPv6 Loopback Address ..................................... 11
+ 4. Interface Identification .................................... 12
+ 4.1. Name-to-Index ............................................. 13
+ 4.2. Index-to-Name ............................................. 13
+ 4.3. Return All Interface Names and Indexes .................... 14
+ 4.4. Free Memory ............................................... 14
+ 5. Socket Options .............................................. 14
+ 5.1. Changing Socket Type ...................................... 15
+ 5.2. Unicast Hop Limit ......................................... 16
+ 5.3. Sending and Receiving Multicast Packets ................... 17
+ 6. Library Functions ........................................... 19
+ 6.1. Hostname-to-Address Translation ........................... 19
+ 6.2. Address To Hostname Translation ........................... 22
+ 6.3. Protocol-Independent Hostname and Service Name Translation 22
+ 6.4. Socket Address Structure to Hostname and Service Name ..... 25
+ 6.5. Address Conversion Functions .............................. 27
+ 6.6. Address Testing Macros .................................... 28
+ 7. Summary of New Definitions .................................. 29
+ 8. Security Considerations ..................................... 31
+ 9. Acknowledgments ............................................. 31
+ 10. References ................................................. 31
+ 11. Authors' Addresses ......................................... 32
+
+1. Introduction
+
+ While IPv4 addresses are 32 bits long, IPv6 interfaces are identified
+ by 128-bit addresses. The socket interface make the size of an IP
+ address quite visible to an application; virtually all TCP/IP
+ applications for BSD-based systems have knowledge of the size of an
+ IP address. Those parts of the API that expose the addresses must be
+ changed to accommodate the larger IPv6 address size. IPv6 also
+ introduces new features (e.g., flow label and priority), some of
+ which must be made visible to applications via the API. This memo
+ defines a set of extensions to the socket interface to support the
+ larger address size and new features of IPv6.
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 2]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+2. Design Considerations
+
+ There are a number of important considerations in designing changes
+ to this well-worn API:
+
+ - The API changes should provide both source and binary
+ compatibility for programs written to the original API. That is,
+ existing program binaries should continue to operate when run on
+ a system supporting the new API. In addition, existing
+ applications that are re-compiled and run on a system supporting
+ the new API should continue to operate. Simply put, the API
+ changes for IPv6 should not break existing programs.
+
+ - The changes to the API should be as small as possible in order to
+ simplify the task of converting existing IPv4 applications to
+ IPv6.
+
+ - Where possible, applications should be able to use this API to
+ interoperate with both IPv6 and IPv4 hosts. Applications should
+ not need to know which type of host they are communicating with.
+
+ - IPv6 addresses carried in data structures should be 64-bit
+ aligned. This is necessary in order to obtain optimum
+ performance on 64-bit machine architectures.
+
+ Because of the importance of providing IPv4 compatibility in the API,
+ these extensions are explicitly designed to operate on machines that
+ provide complete support for both IPv4 and IPv6. A subset of this
+ API could probably be designed for operation on systems that support
+ only IPv6. However, this is not addressed in this memo.
+
+2.1. What Needs to be Changed
+
+ The socket interface API consists of a few distinct components:
+
+ - Core socket functions.
+
+ - Address data structures.
+
+ - Name-to-address translation functions.
+
+ - Address conversion functions.
+
+ The core socket functions -- those functions that deal with such
+ things as setting up and tearing down TCP connections, and sending
+ and receiving UDP packets -- were designed to be transport
+ independent. Where protocol addresses are passed as function
+ arguments, they are carried via opaque pointers. A protocol-specific
+
+
+
+Gilligan, et. al. Informational [Page 3]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ address data structure is defined for each protocol that the socket
+ functions support. Applications must cast pointers to these
+ protocol-specific address structures into pointers to the generic
+ "sockaddr" address structure when using the socket functions. These
+ functions need not change for IPv6, but a new IPv6-specific address
+ data structure is needed.
+
+ The "sockaddr_in" structure is the protocol-specific data structure
+ for IPv4. This data structure actually includes 8-octets of unused
+ space, and it is tempting to try to use this space to adapt the
+ sockaddr_in structure to IPv6. Unfortunately, the sockaddr_in
+ structure is not large enough to hold the 16-octet IPv6 address as
+ well as the other information (address family and port number) that
+ is needed. So a new address data structure must be defined for IPv6.
+
+ The name-to-address translation functions in the socket interface are
+ gethostbyname() and gethostbyaddr(). These must be modified to
+ support IPv6 and the semantics defined must provide 100% backward
+ compatibility for all existing IPv4 applications, along with IPv6
+ support for new applications. Additionally, the POSIX 1003.g work in
+ progress [4] specifies a new hostname-to-address translation function
+ which is protocol independent. This function can also be used with
+ IPv6.
+
+ The address conversion functions -- inet_ntoa() and inet_addr() --
+ convert IPv4 addresses between binary and printable form. These
+ functions are quite specific to 32-bit IPv4 addresses. We have
+ designed two analogous functions that convert both IPv4 and IPv6
+ addresses, and carry an address type parameter so that they can be
+ extended to other protocol families as well.
+
+ Finally, a few miscellaneous features are needed to support IPv6.
+ New interfaces are needed to support the IPv6 flow label, priority,
+ and hop limit header fields. New socket options are needed to
+ control the sending and receiving of IPv6 multicast packets.
+
+ The socket interface will be enhanced in the future to provide access
+ to other IPv6 features. These extensions are described in [5].
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 4]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+2.2. Data Types
+
+ The data types of the structure elements given in this memo are
+ intended to be examples, not absolute requirements. Whenever
+ possible, POSIX 1003.1g data types are used: u_intN_t means an
+ unsigned integer of exactly N bits (e.g., u_int16_t) and u_intNm_t
+ means an unsigned integer of at least N bits (e.g., u_int32m_t). We
+ also assume the argument data types from 1003.1g when possible (e.g.,
+ the final argument to setsockopt() is a size_t value). Whenever
+ buffer sizes are specified, the POSIX 1003.1 size_t data type is used
+ (e.g., the two length arguments to getnameinfo()).
+
+2.3. Headers
+
+ When function prototypes and structures are shown we show the headers
+ that must be #included to cause that item to be defined.
+
+2.4. Structures
+
+ When structures are described the members shown are the ones that
+ must appear in an implementation. Additional, nonstandard members
+ may also be defined by an implementation.
+
+ The ordering shown for the members of a structure is the recommended
+ ordering, given alignment considerations of multibyte members, but an
+ implementation may order the members differently.
+
+3. Socket Interface
+
+ This section specifies the socket interface changes for IPv6.
+
+3.1. IPv6 Address Family and Protocol Family
+
+ A new address family name, AF_INET6, is defined in <sys/socket.h>.
+ The AF_INET6 definition distinguishes between the original
+ sockaddr_in address data structure, and the new sockaddr_in6 data
+ structure.
+
+ A new protocol family name, PF_INET6, is defined in <sys/socket.h>.
+ Like most of the other protocol family names, this will usually be
+ defined to have the same value as the corresponding address family
+ name:
+
+ #define PF_INET6 AF_INET6
+
+ The PF_INET6 is used in the first argument to the socket() function
+ to indicate that an IPv6 socket is being created.
+
+
+
+
+Gilligan, et. al. Informational [Page 5]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+3.2. IPv6 Address Structure
+
+ A new data structure to hold a single IPv6 address is defined as
+ follows:
+
+ #include <netinet/in.h>
+
+ struct in6_addr {
+ u_int8_t s6_addr[16]; /* IPv6 address */
+ }
+
+ This data structure contains an array of sixteen 8-bit elements,
+ which make up one 128-bit IPv6 address. The IPv6 address is stored
+ in network byte order.
+
+3.3. Socket Address Structure for 4.3BSD-Based Systems
+
+ In the socket interface, a different protocol-specific data structure
+ is defined to carry the addresses for each protocol suite. Each
+ protocol-specific data structure is designed so it can be cast into a
+ protocol-independent data structure -- the "sockaddr" structure.
+ Each has a "family" field that overlays the "sa_family" of the
+ sockaddr data structure. This field identifies the type of the data
+ structure.
+
+ The sockaddr_in structure is the protocol-specific address data
+ structure for IPv4. It is used to pass addresses between
+ applications and the system in the socket functions. The following
+ structure is defined to carry IPv6 addresses:
+
+ #include <netinet/in.h>
+
+ struct sockaddr_in6 {
+ u_int16m_t sin6_family; /* AF_INET6 */
+ u_int16m_t sin6_port; /* transport layer port # */
+ u_int32m_t sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ };
+
+ This structure is designed to be compatible with the sockaddr data
+ structure used in the 4.3BSD release.
+
+ The sin6_family field identifies this as a sockaddr_in6 structure.
+ This field overlays the sa_family field when the buffer is cast to a
+ sockaddr data structure. The value of this field must be AF_INET6.
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 6]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ The sin6_port field contains the 16-bit UDP or TCP port number. This
+ field is used in the same way as the sin_port field of the
+ sockaddr_in structure. The port number is stored in network byte
+ order.
+
+ The sin6_flowinfo field is a 32-bit field that contains two pieces of
+ information: the 24-bit IPv6 flow label and the 4-bit priority field.
+ The contents and interpretation of this member is unspecified at this
+ time.
+
+ The sin6_addr field is a single in6_addr structure (defined in the
+ previous section). This field holds one 128-bit IPv6 address. The
+ address is stored in network byte order.
+
+ The ordering of elements in this structure is specifically designed
+ so that the sin6_addr field will be aligned on a 64-bit boundary.
+ This is done for optimum performance on 64-bit architectures.
+
+ Notice that the sockaddr_in6 structure will normally be larger than
+ the generic sockaddr structure. On many existing implementations the
+ sizeof(struct sockaddr_in) equals sizeof(struct sockaddr), with both
+ being 16 bytes. Any existing code that makes this assumption needs
+ to be examined carefully when converting to IPv6.
+
+3.4. Socket Address Structure for 4.4BSD-Based Systems
+
+ The 4.4BSD release includes a small, but incompatible change to the
+ socket interface. The "sa_family" field of the sockaddr data
+ structure was changed from a 16-bit value to an 8-bit value, and the
+ space saved used to hold a length field, named "sa_len". The
+ sockaddr_in6 data structure given in the previous section cannot be
+ correctly cast into the newer sockaddr data structure. For this
+ reason, the following alternative IPv6 address data structure is
+ provided to be used on systems based on 4.4BSD:
+
+ #include <netinet/in.h>
+
+ #define SIN6_LEN
+
+ struct sockaddr_in6 {
+ u_char sin6_len; /* length of this struct */
+ u_char sin6_family; /* AF_INET6 */
+ u_int16m_t sin6_port; /* transport layer port # */
+ u_int32m_t sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ };
+
+
+
+
+
+Gilligan, et. al. Informational [Page 7]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ The only differences between this data structure and the 4.3BSD
+ variant are the inclusion of the length field, and the change of the
+ family field to a 8-bit data type. The definitions of all the other
+ fields are identical to the structure defined in the previous
+ section.
+
+ Systems that provide this version of the sockaddr_in6 data structure
+ must also declare SIN6_LEN as a result of including the
+ <netinet/in.h> header. This macro allows applications to determine
+ whether they are being built on a system that supports the 4.3BSD or
+ 4.4BSD variants of the data structure.
+
+3.5. The Socket Functions
+
+ Applications call the socket() function to create a socket descriptor
+ that represents a communication endpoint. The arguments to the
+ socket() function tell the system which protocol to use, and what
+ format address structure will be used in subsequent functions. For
+ example, to create an IPv4/TCP socket, applications make the call:
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+
+ To create an IPv4/UDP socket, applications make the call:
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+
+ Applications may create IPv6/TCP and IPv6/UDP sockets by simply using
+ the constant PF_INET6 instead of PF_INET in the first argument. For
+ example, to create an IPv6/TCP socket, applications make the call:
+
+ s = socket(PF_INET6, SOCK_STREAM, 0);
+
+ To create an IPv6/UDP socket, applications make the call:
+
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+
+ Once the application has created a PF_INET6 socket, it must use the
+ sockaddr_in6 address structure when passing addresses in to the
+ system. The functions that the application uses to pass addresses
+ into the system are:
+
+ bind()
+ connect()
+ sendmsg()
+ sendto()
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 8]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ The system will use the sockaddr_in6 address structure to return
+ addresses to applications that are using PF_INET6 sockets. The
+ functions that return an address from the system to an application
+ are:
+
+ accept()
+ recvfrom()
+ recvmsg()
+ getpeername()
+ getsockname()
+
+ No changes to the syntax of the socket functions are needed to
+ support IPv6, since all of the "address carrying" functions use an
+ opaque address pointer, and carry an address length as a function
+ argument.
+
+3.6. Compatibility with IPv4 Applications
+
+ In order to support the large base of applications using the original
+ API, system implementations must provide complete source and binary
+ compatibility with the original API. This means that systems must
+ continue to support PF_INET sockets and the sockaddr_in address
+ structure. Applications must be able to create IPv4/TCP and IPv4/UDP
+ sockets using the PF_INET constant in the socket() function, as
+ described in the previous section. Applications should be able to
+ hold a combination of IPv4/TCP, IPv4/UDP, IPv6/TCP and IPv6/UDP
+ sockets simultaneously within the same process.
+
+ Applications using the original API should continue to operate as
+ they did on systems supporting only IPv4. That is, they should
+ continue to interoperate with IPv4 nodes.
+
+3.7. Compatibility with IPv4 Nodes
+
+ The API also provides a different type of compatibility: the ability
+ for IPv6 applications to interoperate with IPv4 applications. This
+ feature uses the IPv4-mapped IPv6 address format defined in the IPv6
+ addressing architecture specification [2]. This address format
+ allows the IPv4 address of an IPv4 node to be represented as an IPv6
+ address. The IPv4 address is encoded into the low-order 32 bits of
+ the IPv6 address, and the high-order 96 bits hold the fixed prefix
+ 0:0:0:0:0:FFFF. IPv4-mapped addresses are written as follows:
+
+ ::FFFF:<IPv4-address>
+
+ These addresses are often generated automatically by the
+ gethostbyname() function when the specified host has only IPv4
+ addresses (as described in Section 6.1).
+
+
+
+Gilligan, et. al. Informational [Page 9]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ Applications may use PF_INET6 sockets to open TCP connections to IPv4
+ nodes, or send UDP packets to IPv4 nodes, by simply encoding the
+ destination's IPv4 address as an IPv4-mapped IPv6 address, and
+ passing that address, within a sockaddr_in6 structure, in the
+ connect() or sendto() call. When applications use PF_INET6 sockets
+ to accept TCP connections from IPv4 nodes, or receive UDP packets
+ from IPv4 nodes, the system returns the peer's address to the
+ application in the accept(), recvfrom(), or getpeername() call using
+ a sockaddr_in6 structure encoded this way.
+
+ Few applications will likely need to know which type of node they are
+ interoperating with. However, for those applications that do need to
+ know, the IN6_IS_ADDR_V4MAPPED() macro, defined in Section 6.6, is
+ provided.
+
+3.8. IPv6 Wildcard Address
+
+ While the bind() function allows applications to select the source IP
+ address of UDP packets and TCP connections, applications often want
+ the system to select the source address for them. With IPv4, one
+ specifies the address as the symbolic constant INADDR_ANY (called the
+ "wildcard" address) in the bind() call, or simply omits the bind()
+ entirely.
+
+ Since the IPv6 address type is a structure (struct in6_addr), a
+ symbolic constant can be used to initialize an IPv6 address variable,
+ but cannot be used in an assignment. Therefore systems provide the
+ IPv6 wildcard address in two forms.
+
+ The first version is a global variable named "in6addr_any" that is an
+ in6_addr structure. The extern declaration for this variable is
+ defined in <netinet/in.h>:
+
+ extern const struct in6_addr in6addr_any;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 10]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ Applications use in6addr_any similarly to the way they use INADDR_ANY
+ in IPv4. For example, to bind a socket to port number 23, but let
+ the system select the source address, an application could use the
+ following code:
+
+ struct sockaddr_in6 sin6;
+ . . .
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_flowinfo = 0;
+ sin6.sin6_port = htons(23);
+ sin6.sin6_addr = in6addr_any; /* structure assignment */
+ . . .
+ if (bind(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1)
+ . . .
+
+ The other version is a symbolic constant named IN6ADDR_ANY_INIT and
+ is defined in <netinet/in.h>. This constant can be used to
+ initialize an in6_addr structure:
+
+ struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
+
+ Note that this constant can be used ONLY at declaration time. It can
+ not be used to assign a previously declared in6_addr structure. For
+ example, the following code will not work:
+
+ /* This is the WRONG way to assign an unspecified address */
+ struct sockaddr_in6 sin6;
+ . . .
+ sin6.sin6_addr = IN6ADDR_ANY_INIT; /* will NOT compile */
+
+ Be aware that the IPv4 INADDR_xxx constants are all defined in host
+ byte order but the IPv6 IN6ADDR_xxx constants and the IPv6
+ in6addr_xxx externals are defined in network byte order.
+
+3.9. IPv6 Loopback Address
+
+ Applications may need to send UDP packets to, or originate TCP
+ connections to, services residing on the local node. In IPv4, they
+ can do this by using the constant IPv4 address INADDR_LOOPBACK in
+ their connect(), sendto(), or sendmsg() call.
+
+ IPv6 also provides a loopback address to contact local TCP and UDP
+ services. Like the unspecified address, the IPv6 loopback address is
+ provided in two forms -- a global variable and a symbolic constant.
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 11]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ The global variable is an in6_addr structure named
+ "in6addr_loopback." The extern declaration for this variable is
+ defined in <netinet/in.h>:
+
+ extern const struct in6_addr in6addr_loopback;
+
+ Applications use in6addr_loopback as they would use INADDR_LOOPBACK
+ in IPv4 applications (but beware of the byte ordering difference
+ mentioned at the end of the previous section). For example, to open
+ a TCP connection to the local telnet server, an application could use
+ the following code:
+
+ struct sockaddr_in6 sin6;
+ . . .
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_flowinfo = 0;
+ sin6.sin6_port = htons(23);
+ sin6.sin6_addr = in6addr_loopback; /* structure assignment */
+ . . .
+ if (connect(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1)
+ . . .
+
+ The symbolic constant is named IN6ADDR_LOOPBACK_INIT and is defined
+ in <netinet/in.h>. It can be used at declaration time ONLY; for
+ example:
+
+ struct in6_addr loopbackaddr = IN6ADDR_LOOPBACK_INIT;
+
+ Like IN6ADDR_ANY_INIT, this constant cannot be used in an assignment
+ to a previously declared IPv6 address variable.
+
+4. Interface Identification
+
+ This API uses an interface index (a small positive integer) to
+ identify the local interface on which a multicast group is joined
+ (Section 5.3). Additionally, the advanced API [5] uses these same
+ interface indexes to identify the interface on which a datagram is
+ received, or to specify the interface on which a datagram is to be
+ sent.
+
+ Interfaces are normally known by names such as "le0", "sl1", "ppp2",
+ and the like. On Berkeley-derived implementations, when an interface
+ is made known to the system, the kernel assigns a unique positive
+ integer value (called the interface index) to that interface. These
+ are small positive integers that start at 1. (Note that 0 is never
+ used for an interface index.) There may be gaps so that there is no
+ current interface for a particular positive interface index.
+
+
+
+
+Gilligan, et. al. Informational [Page 12]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ This API defines two functions that map between an interface name and
+ index, a third function that returns all the interface names and
+ indexes, and a fourth function to return the dynamic memory allocated
+ by the previous function. How these functions are implemented is
+ left up to the implementation. 4.4BSD implementations can implement
+ these functions using the existing sysctl() function with the
+ NET_RT_LIST command. Other implementations may wish to use ioctl()
+ for this purpose.
+
+4.1. Name-to-Index
+
+ The first function maps an interface name into its corresponding
+ index.
+
+ #include <net/if.h>
+
+ unsigned int if_nametoindex(const char *ifname);
+
+ If the specified interface does not exist, the return value is 0.
+
+4.2. Index-to-Name
+
+ The second function maps an interface index into its corresponding
+ name.
+
+ #include <net/if.h>
+
+ char *if_indextoname(unsigned int ifindex, char *ifname);
+
+ The ifname argument must point to a buffer of at least IFNAMSIZ bytes
+ into which the interface name corresponding to the specified index is
+ returned. (IFNAMSIZ is also defined in <net/if.h> and its value
+ includes a terminating null byte at the end of the interface name.)
+ This pointer is also the return value of the function. If there is
+ no interface corresponding to the specified index, NULL is returned.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 13]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+4.3. Return All Interface Names and Indexes
+
+ The final function returns an array of if_nameindex structures, one
+ structure per interface.
+
+ #include <net/if.h>
+
+ struct if_nameindex {
+ unsigned int if_index; /* 1, 2, ... */
+ char *if_name; /* null terminated name: "le0", ... */
+ };
+
+ struct if_nameindex *if_nameindex(void);
+
+ The end of the array of structures is indicated by a structure with
+ an if_index of 0 and an if_name of NULL. The function returns a NULL
+ pointer upon an error.
+
+ The memory used for this array of structures along with the interface
+ names pointed to by the if_name members is obtained dynamically.
+ This memory is freed by the next function.
+
+4.4. Free Memory
+
+ The following function frees the dynamic memory that was allocated by
+ if_nameindex().
+
+ #include <net/if.h>
+
+ void if_freenameindex(struct if_nameindex *ptr);
+
+ The argument to this function must be a pointer that was returned by
+ if_nameindex().
+
+5. Socket Options
+
+ A number of new socket options are defined for IPv6. All of these
+ new options are at the IPPROTO_IPV6 level. That is, the "level"
+ parameter in the getsockopt() and setsockopt() calls is IPPROTO_IPV6
+ when using these options. The constant name prefix IPV6_ is used in
+ all of the new socket options. This serves to clearly identify these
+ options as applying to IPv6.
+
+ The declaration for IPPROTO_IPV6, the new IPv6 socket options, and
+ related constants defined in this section are obtained by including
+ the header <netinet/in.h>.
+
+
+
+
+
+Gilligan, et. al. Informational [Page 14]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+5.1. Changing Socket Type
+
+ Unix allows open sockets to be passed between processes via the
+ exec() call and other means. It is a relatively common application
+ practice to pass open sockets across exec() calls. Thus it is
+ possible for an application using the original API to pass an open
+ PF_INET socket to an application that is expecting to receive a
+ PF_INET6 socket. Similarly, it is possible for an application using
+ the extended API to pass an open PF_INET6 socket to an application
+ using the original API, which would be equipped only to deal with
+ PF_INET sockets. Either of these cases could cause problems, because
+ the application that is passed the open socket might not know how to
+ decode the address structures returned in subsequent socket
+ functions.
+
+ To remedy this problem, a new setsockopt() option is defined that
+ allows an application to "convert" a PF_INET6 socket into a PF_INET
+ socket and vice versa.
+
+ An IPv6 application that is passed an open socket from an unknown
+ process may use the IPV6_ADDRFORM setsockopt() option to "convert"
+ the socket to PF_INET6. Once that has been done, the system will
+ return sockaddr_in6 address structures in subsequent socket
+ functions.
+
+ An IPv6 application that is about to pass an open PF_INET6 socket to
+ a program that is not be IPv6 capable can "downgrade" the socket to
+ PF_INET before calling exec(). After that, the system will return
+ sockaddr_in address structures to the application that was exec()'ed.
+ Be aware that you cannot downgrade an IPv6 socket to an IPv4 socket
+ unless all nonwildcard addresses already associated with the IPv6
+ socket are IPv4-mapped IPv6 addresses.
+
+ The IPV6_ADDRFORM option is valid at both the IPPROTO_IP and
+ IPPROTO_IPV6 levels. The only valid option values are PF_INET6 and
+ PF_INET. For example, to convert a PF_INET6 socket to PF_INET, a
+ program would call:
+
+ int addrform = PF_INET;
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_ADDRFORM,
+ (char *) &addrform, sizeof(addrform)) == -1)
+ perror("setsockopt IPV6_ADDRFORM");
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 15]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ An application may use IPV6_ADDRFORM with getsockopt() to learn
+ whether an open socket is a PF_INET of PF_INET6 socket. For example:
+
+ int addrform;
+ size_t len = sizeof(addrform);
+
+ if (getsockopt(s, IPPROTO_IPV6, IPV6_ADDRFORM,
+ (char *) &addrform, &len) == -1)
+ perror("getsockopt IPV6_ADDRFORM");
+ else if (addrform == PF_INET)
+ printf("This is an IPv4 socket.\n");
+ else if (addrform == PF_INET6)
+ printf("This is an IPv6 socket.\n");
+ else
+ printf("This system is broken.\n");
+
+5.2. Unicast Hop Limit
+
+ A new setsockopt() option controls the hop limit used in outgoing
+ unicast IPv6 packets. The name of this option is IPV6_UNICAST_HOPS,
+ and it is used at the IPPROTO_IPV6 layer. The following example
+ illustrates how it is used:
+
+ int hoplimit = 10;
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+ (char *) &hoplimit, sizeof(hoplimit)) == -1)
+ perror("setsockopt IPV6_UNICAST_HOPS");
+
+ When the IPV6_UNICAST_HOPS option is set with setsockopt(), the
+ option value given is used as the hop limit for all subsequent
+ unicast packets sent via that socket. If the option is not set, the
+ system selects a default value. The integer hop limit value (called
+ x) is interpreted as follows:
+
+ x < -1: return an error of EINVAL
+ x == -1: use kernel default
+ 0 <= x <= 255: use x
+ x >= 256: return an error of EINVAL
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 16]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ The IPV6_UNICAST_HOPS option may be used with getsockopt() to
+ determine the hop limit value that the system will use for subsequent
+ unicast packets sent via that socket. For example:
+
+ int hoplimit;
+ size_t len = sizeof(hoplimit);
+
+ if (getsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+ (char *) &hoplimit, &len) == -1)
+ perror("getsockopt IPV6_UNICAST_HOPS");
+ else
+ printf("Using %d for hop limit.\n", hoplimit);
+
+5.3. Sending and Receiving Multicast Packets
+
+ IPv6 applications may send UDP multicast packets by simply specifying
+ an IPv6 multicast address in the address argument of the sendto()
+ function.
+
+ Three socket options at the IPPROTO_IPV6 layer control some of the
+ parameters for sending multicast packets. Setting these options is
+ not required: applications may send multicast packets without using
+ these options. The setsockopt() options for controlling the sending
+ of multicast packets are summarized below:
+
+ IPV6_MULTICAST_IF
+
+ Set the interface to use for outgoing multicast packets. The
+ argument is the index of the interface to use.
+
+ Argument type: unsigned int
+
+ IPV6_MULTICAST_HOPS
+
+ Set the hop limit to use for outgoing multicast packets.
+ (Note a separate option - IPV6_UNICAST_HOPS - is provided to
+ set the hop limit to use for outgoing unicast packets.) The
+ interpretation of the argument is the same as for the
+ IPV6_UNICAST_HOPS option:
+
+ x < -1: return an error of EINVAL
+ x == -1: use kernel default
+ 0 <= x <= 255: use x
+ x >= 256: return an error of EINVAL
+
+ Argument type: int
+
+
+
+
+
+Gilligan, et. al. Informational [Page 17]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ IPV6_MULTICAST_LOOP
+
+ Controls whether outgoing multicast packets sent should be
+ delivered back to the local application. A toggle. If the
+ option is set to 1, multicast packets are looped back. If it
+ is set to 0, they are not.
+
+ Argument type: unsigned int
+
+ The reception of multicast packets is controlled by the two
+ setsockopt() options summarized below:
+
+ IPV6_ADD_MEMBERSHIP
+
+ Join a multicast group on a specified local interface. If
+ the interface index is specified as 0, the kernel chooses the
+ local interface. For example, some kernels look up the
+ multicast group in the normal IPv6 routing table and using
+ the resulting interface.
+
+ Argument type: struct ipv6_mreq
+
+ IPV6_DROP_MEMBERSHIP
+
+ Leave a multicast group on a specified interface.
+
+ Argument type: struct ipv6_mreq
+
+ The argument type of both of these options is the ipv6_mreq
+ structure, defined as:
+
+ #include <netinet/in.h>
+
+ struct ipv6_mreq {
+ struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast addr */
+ unsigned int ipv6mr_interface; /* interface index */
+ };
+
+ Note that to receive multicast datagrams a process must join the
+ multicast group and bind the UDP port to which datagrams will be
+ sent. Some processes also bind the multicast group address to the
+ socket, in addition to the port, to prevent other datagrams destined
+ to that same port from being delivered to the socket.
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 18]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+6. Library Functions
+
+ New library functions are needed to perform a variety of operations
+ with IPv6 addresses. Functions are needed to lookup IPv6 addresses
+ in the Domain Name System (DNS). Both forward lookup (hostname-to-
+ address translation) and reverse lookup (address-to-hostname
+ translation) need to be supported. Functions are also needed to
+ convert IPv6 addresses between their binary and textual form.
+
+6.1. Hostname-to-Address Translation
+
+ The commonly used function gethostbyname() remains unchanged as does
+ the hostent structure to which it returns a pointer. Existing
+ applications that call this function continue to receive only IPv4
+ addresses that are the result of a query in the DNS for A records.
+ (We assume the DNS is being used; some environments may be using a
+ hosts file or some other name resolution system, either of which may
+ impede renumbering. We also assume that the RES_USE_INET6 resolver
+ option is not set, which we describe in more detail shortly.)
+
+ Two new changes are made to support IPv6 addresses. First, the
+ following function is new:
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+ struct hostent *gethostbyname2(const char *name, int af);
+
+ The af argument specifies the address family. The default operation
+ of this function is simple:
+
+ - If the af argument is AF_INET, then a query is made for A
+ records. If successful, IPv4 addresses are returned and the
+ h_length member of the hostent structure will be 4, else the
+ function returns a NULL pointer.
+
+ - If the af argument is AF_INET6, then a query is made for AAAA
+ records. If successful, IPv6 addresses are returned and the
+ h_length member of the hostent structure will be 16, else the
+ function returns a NULL pointer.
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 19]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ The second change, that provides additional functionality, is a new
+ resolver option RES_USE_INET6, which is defined as a result of
+ including the <resolv.h> header. (This option is provided starting
+ with the BIND 4.9.4 release.) There are three ways to set this
+ option.
+
+ - The first way is
+
+ res_init();
+ _res.options |= RES_USE_INET6;
+
+ and then call either gethostbyname() or gethostbyname2(). This
+ option then affects only the process that is calling the
+ resolver.
+
+ - The second way to set this option is to set the environment
+ variable RES_OPTIONS, as in RES_OPTIONS=inet6. (This example is
+ for the Bourne and Korn shells.) This method affects any
+ processes that see this environment variable.
+
+ - The third way is to set this option in the resolver configuration
+ file (normally /etc/resolv.conf) and the option then affects all
+ applications on the host. This final method should not be done
+ until all applications on the host are capable of dealing with
+ IPv6 addresses.
+
+ There is no priority among these three methods. When the
+ RES_USE_INET6 option is set, two changes occur:
+
+ - gethostbyname(host) first calls gethostbyname2(host, AF_INET6)
+ looking for AAAA records, and if this fails it then calls
+ gethostbyname2(host, AF_INET) looking for A records.
+
+ - gethostbyname2(host, AF_INET) always returns IPv4-mapped IPv6
+ addresses with the h_length member of the hostent structure set
+ to 16.
+
+ An application must not enable the RES_USE_INET6 option until it is
+ prepared to deal with 16-byte addresses in the returned hostent
+ structure.
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 20]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ The following table summarizes the operation of the existing
+ gethostbyname() function, the new function gethostbyname2(), along
+ with the new resolver option RES_USE_INET6.
+
++------------------+---------------------------------------------------+
+| | RES_USE_INET6 option |
+| +-------------------------+-------------------------+
+| | off | on |
++------------------+-------------------------+-------------------------+
+| |Search for A records. |Search for AAAA records. |
+| gethostbyname | If found, return IPv4 | If found, return IPv6 |
+| (host) | addresses (h_length=4). | addresses (h_length=16).|
+| | Else error. | Else search for A |
+| | | records. If found, |
+| |Provides backward | return IPv4-mapped IPv6 |
+| | compatibility with all | addresses (h_length=16).|
+| | existing IPv4 appls. | Else error. |
++------------------+-------------------------+-------------------------+
+| |Search for A records. |Search for A records. |
+| gethostbyname2 | If found, return IPv4 | If found, return |
+| (host, AF_INET) | addresses (h_length=4). | IPv4-mapped IPv6 |
+| | Else error. | addresses (h_length=16).|
+| | | Else error. |
++------------------+-------------------------+-------------------------+
+| |Search for AAAA records. |Search for AAAA records. |
+| gethostbyname2 | If found, return IPv6 | If found, return IPv6 |
+| (host, AF_INET6) | addresses (h_length=16).| addresses (h_length=16).|
+| | Else error. | Else error. |
++------------------+-------------------------+-------------------------+
+
+ It is expected that when a typical naive application that calls
+ gethostbyname() today is modified to use IPv6, it simply changes the
+ program to use IPv6 sockets and then enables the RES_USE_INET6
+ resolver option before calling gethostbyname(). This application
+ will then work with either IPv4 or IPv6 peers.
+
+ Note that gethostbyname() and gethostbyname2() are not thread-safe,
+ since both return a pointer to a static hostent structure. But
+ several vendors have defined a thread-safe gethostbyname_r() function
+ that requires four additional arguments. We expect these vendors to
+ also define a gethostbyname2_r() function.
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 21]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+6.2. Address To Hostname Translation
+
+ The existing gethostbyaddr() function already requires an address
+ family argument and can therefore work with IPv6 addresses:
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+ struct hostent *gethostbyaddr(const char *src, int len, int af);
+
+ One possible source of confusion is the handling of IPv4-mapped IPv6
+ addresses and IPv4-compatible IPv6 addresses. This is addressed in
+ [6] and involves the following logic:
+
+ 1. If af is AF_INET6, and if len equals 16, and if the IPv6 address
+ is an IPv4-mapped IPv6 address or an IPv4-compatible IPv6
+ address, then skip over the first 12 bytes of the IPv6 address,
+ set af to AF_INET, and set len to 4.
+
+ 2. If af is AF_INET, then query for a PTR record in the in-
+ addr.arpa domain.
+
+ 3. If af is AF_INET6, then query for a PTR record in the ip6.int
+ domain.
+
+ 4. If the function is returning success, and if af equals AF_INET,
+ and if the RES_USE_INET6 option was set, then the single address
+ that is returned in the hostent structure (a copy of the first
+ argument to the function) is returned as an IPv4-mapped IPv6
+ address and the h_length member is set to 16.
+
+ All four steps listed are performed, in order. The same caveats
+ regarding a thread-safe version of gethostbyname() that were made at
+ the end of the previous section apply here as well.
+
+6.3. Protocol-Independent Hostname and Service Name Translation
+
+ Hostname-to-address translation is done in a protocol-independent
+ fashion using the getaddrinfo() function that is taken from the
+ Institute of Electrical and Electronic Engineers (IEEE) POSIX 1003.1g
+ (Protocol Independent Interfaces) work in progress specification [4].
+
+ The official specification for this function will be the final POSIX
+ standard. We are providing this independent description of the
+ function because POSIX standards are not freely available (as are
+ IETF documents). Should there be any discrepancies between this
+ description and the POSIX description, the POSIX description takes
+ precedence.
+
+
+
+Gilligan, et. al. Informational [Page 22]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+ int getaddrinfo(const char *hostname, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res);
+
+ The addrinfo structure is defined as:
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+ 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 */
+ };
+
+ The return value from the function is 0 upon success or a nonzero
+ error code. The following names are the nonzero error codes from
+ getaddrinfo(), and are defined in <netdb.h>:
+
+ EAI_ADDRFAMILY address family for hostname not supported
+ EAI_AGAIN temporary failure in name resolution
+ EAI_BADFLAGS invalid value for ai_flags
+ EAI_FAIL non-recoverable failure in name resolution
+ EAI_FAMILY ai_family not supported
+ EAI_MEMORY memory allocation failure
+ EAI_NODATA no address associated with hostname
+ EAI_NONAME hostname nor servname provided, or not known
+ EAI_SERVICE servname not supported for ai_socktype
+ EAI_SOCKTYPE ai_socktype not supported
+ EAI_SYSTEM system error returned in errno
+
+ The hostname and servname arguments are pointers to null-terminated
+ strings or NULL. One or both of these two arguments must be a non-
+ NULL pointer. In the normal client scenario, both the hostname and
+ servname are specified. In the normal server scenario, only the
+ servname is specified. A non-NULL hostname string can be either a
+ host name or a numeric host address string (i.e., a dotted-decimal
+ IPv4 address or an IPv6 hex address). A non-NULL servname string can
+ be either a service name or a decimal port number.
+
+
+
+
+Gilligan, et. al. Informational [Page 23]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ The caller can optionally pass an addrinfo structure, pointed to by
+ the third argument, to provide hints concerning the type of socket
+ that the caller supports. In this hints structure all members other
+ than ai_flags, ai_family, ai_socktype, and ai_protocol must be zero
+ or a NULL pointer. A value of PF_UNSPEC for ai_family means the
+ caller will accept any protocol family. A value of 0 for ai_socktype
+ means the caller will accept any socket type. A value of 0 for
+ ai_protocol means the caller will accept any protocol. For example,
+ if the caller handles only TCP and not UDP, then the ai_socktype
+ member of the hints structure should be set to SOCK_STREAM when
+ getaddrinfo() is called. If the caller handles only IPv4 and not
+ IPv6, then the ai_family member of the hints structure should be set
+ to PF_INET when getaddrinfo() is called. If the third argument to
+ getaddrinfo() is a NULL pointer, this is the same as if the caller
+ had filled in an addrinfo structure initialized to zero with
+ ai_family set to PF_UNSPEC.
+
+ Upon successful return a pointer to a linked list of one or more
+ addrinfo structures is returned through the final argument. The
+ caller can process each addrinfo structure in this list by following
+ the ai_next pointer, until a NULL pointer is encountered. In each
+ returned addrinfo structure the three members ai_family, ai_socktype,
+ and ai_protocol are the corresponding arguments for a call to the
+ socket() function. In each addrinfo structure the ai_addr member
+ points to a filled-in socket address structure whose length is
+ specified by the ai_addrlen member.
+
+ If the AI_PASSIVE bit is set in the ai_flags member of the hints
+ structure, then the caller plans to use the returned socket address
+ structure in a call to bind(). 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.
+
+ If the AI_PASSIVE bit is not set in the ai_flags member of the hints
+ structure, then the returned socket address structure will be ready
+ for a call to connect() (for a connection-oriented protocol) or
+ either connect(), sendto(), or sendmsg() (for a connectionless
+ protocol). 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 the loopback address.
+
+ If the AI_CANONNAME bit is set in the ai_flags member of the hints
+ structure, then upon successful return the ai_canonname member of the
+ first addrinfo structure in the linked list will point to a null-
+ terminated string containing the canonical name of the specified
+ hostname.
+
+
+
+
+Gilligan, et. al. Informational [Page 24]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ 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 addrinfo
+ structures. To return this information to the system the function
+ freeaddrinfo() is called:
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+ void freeaddrinfo(struct addrinfo *ai);
+
+ The addrinfo structure pointed to by the ai argument is freed, along
+ with any dynamic storage pointed to by the structure. This operation
+ is repeated until a NULL ai_next pointer is encountered.
+
+ To aid applications in printing error messages based on the EAI_xxx
+ codes returned by getaddrinfo(), the following function is defined.
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+ char *gai_strerror(int ecode);
+
+ The argument is one of the EAI_xxx values defined earlier and the
+ eturn value points to a string describing the error. If the argument
+ is not one of the EAI_xxx values, the function still returns a
+ pointer to a string whose contents indicate an unknown error.
+
+6.4. Socket Address Structure to Hostname and Service Name
+
+ The POSIX 1003.1g specification includes no function to perform the
+ reverse conversion from getaddrinfo(): to look up a hostname and
+ service name, given the binary address and port. Therefore, we
+ define the following function:
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+ int getnameinfo(const struct sockaddr *sa, size_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen,
+ int flags);
+
+ This function looks up an IP address and port number provided by the
+ caller in the DNS and system-specific database, and returns text
+ strings for both in buffers provided by the caller. The function
+ indicates successful completion by a zero return value; a non-zero
+ return value indicates failure.
+
+
+
+Gilligan, et. al. Informational [Page 25]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ The first argument, sa, points to either a sockaddr_in structure (for
+ IPv4) or a sockaddr_in6 structure (for IPv6) that holds the IP
+ address and port number. The salen argument gives the length of the
+ sockaddr_in or sockaddr_in6 structure.
+
+ The function returns the hostname associated with the IP address in
+ the buffer pointed to by the host argument. The caller provides the
+ size of this buffer via the hostlen argument. The service name
+ associated with the port number is returned in the buffer pointed to
+ by serv, and the servlen argument gives the length of this buffer.
+ The caller specifies not to return either string by providing a zero
+ value for the hostlen or servlen arguments. Otherwise, the caller
+ must provide buffers large enough to hold the hostname and the
+ service name, including the terminating null characters.
+
+ Unfortunately most systems do not provide constants that specify the
+ maximum size of either a fully-qualified domain name or a service
+ name. Therefore to aid the application in allocating buffers for
+ these two returned strings the following constants are defined in
+ <netdb.h>:
+
+ #define NI_MAXHOST 1025
+ #define NI_MAXSERV 32
+
+ The first value is actually defined as the constant MAXDNAME in
+ recent versions of BIND's <arpa/nameser.h> header (older versions of
+ BIND define this constant to be 256) and the second is a guess based
+ on the services listed in the current Assigned Numbers RFC.
+
+ The final argument is a flag that changes the default actions of this
+ function. By default the fully-qualified domain name (FQDN) for the
+ host is looked up in the DNS and returned. If the flag bit NI_NOFQDN
+ is set, only the hostname portion of the FQDN is returned for local
+ hosts.
+
+ If the flag bit NI_NUMERICHOST is set, or if the host's name cannot
+ be located in the DNS, the numeric form of the host's address is
+ returned instead of its name (e.g., by calling inet_ntop() instead of
+ gethostbyaddr()). If the flag bit NI_NAMEREQD is set, an error is
+ returned if the host's name cannot be located in the DNS.
+
+ If the flag bit NI_NUMERICSERV is set, the numeric form of the
+ service address is returned (e.g., its port number) instead of its
+ name. The two NI_NUMERICxxx flags are required to support the "-n"
+ flag that many commands provide.
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 26]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ A fifth flag bit, NI_DGRAM, specifies that the service 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.
+
+ These NI_xxx flags are defined in <netdb.h> along with the AI_xxx
+ flags already defined for getaddrinfo().
+
+6.5. Address Conversion Functions
+
+ The two functions inet_addr() and inet_ntoa() convert an IPv4 address
+ between binary and text form. IPv6 applications need similar
+ functions. The following two functions convert both IPv6 and IPv4
+ addresses:
+
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+
+ int inet_pton(int af, const char *src, void *dst);
+
+ const char *inet_ntop(int af, const void *src,
+ char *dst, size_t size);
+
+ The inet_pton() function converts an address in its standard text
+ presentation form into its numeric binary form. The af argument
+ specifies the family of the address. Currently the AF_INET and
+ AF_INET6 address families are supported. The src argument points to
+ the string being passed in. The dst argument points to a buffer into
+ which the function stores the numeric address. The address is
+ returned in network byte order. Inet_pton() returns 1 if the
+ conversion succeeds, 0 if the input is not a valid IPv4 dotted-
+ decimal string or a valid IPv6 address string, or -1 with errno set
+ to EAFNOSUPPORT if the af argument is unknown. The calling
+ application must ensure that the buffer referred to by dst is large
+ enough to hold the numeric address (e.g., 4 bytes for AF_INET or 16
+ bytes for AF_INET6).
+
+ If the af argument is AF_INET, the function accepts a string in the
+ standard IPv4 dotted-decimal form:
+
+ ddd.ddd.ddd.ddd
+
+ where ddd is a one to three digit decimal number between 0 and 255.
+ Note that many implementations of the existing inet_addr() and
+ inet_aton() functions accept nonstandard input: octal numbers,
+ hexadecimal numbers, and fewer than four numbers. inet_pton() does
+ not accept these formats.
+
+
+
+Gilligan, et. al. Informational [Page 27]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ If the af argument is AF_INET6, then the function accepts a string in
+ one of the standard IPv6 text forms defined in Section 2.2 of the
+ addressing architecture specification [2].
+
+ The inet_ntop() function converts a numeric address into a text
+ string suitable for presentation. The af argument specifies the
+ family of the address. This can be AF_INET or AF_INET6. The src
+ argument points to a buffer holding an IPv4 address if the af
+ argument is AF_INET, or an IPv6 address if the af argument is
+ AF_INET6. The dst argument points to a buffer where the function
+ will store the resulting text string. The size argument specifies
+ the size of this buffer. The application must specify a non-NULL dst
+ argument. For IPv6 addresses, the buffer must be at least 46-octets.
+ For IPv4 addresses, the buffer must be at least 16-octets. In order
+ to allow applications to easily declare buffers of the proper size to
+ store IPv4 and IPv6 addresses in string form, the following two
+ constants are defined in <netinet/in.h>:
+
+ #define INET_ADDRSTRLEN 16
+ #define INET6_ADDRSTRLEN 46
+
+ The inet_ntop() function returns a pointer to the buffer containing
+ the text string if the conversion succeeds, and NULL otherwise. Upon
+ failure, errno is set to EAFNOSUPPORT if the af argument is invalid
+ or ENOSPC if the size of the result buffer is inadequate.
+
+6.6. Address Testing Macros
+
+ The following macros can be used to test for special IPv6 addresses.
+
+ #include <netinet/in.h>
+
+ int IN6_IS_ADDR_UNSPECIFIED (const struct in6_addr *);
+ int IN6_IS_ADDR_LOOPBACK (const struct in6_addr *);
+ int IN6_IS_ADDR_MULTICAST (const struct in6_addr *);
+ int IN6_IS_ADDR_LINKLOCAL (const struct in6_addr *);
+ int IN6_IS_ADDR_SITELOCAL (const struct in6_addr *);
+ int IN6_IS_ADDR_V4MAPPED (const struct in6_addr *);
+ int IN6_IS_ADDR_V4COMPAT (const struct in6_addr *);
+
+ int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
+ int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
+ int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
+ int IN6_IS_ADDR_MC_ORGLOCAL (const struct in6_addr *);
+ int IN6_IS_ADDR_MC_GLOBAL (const struct in6_addr *);
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 28]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ The first seven macros return true if the address is of the specified
+ type, or false otherwise. The last five test the scope of a
+ multicast address and return true if the address is a multicast
+ address of the specified scope or false if the address is either not
+ a multicast address or not of the specified scope.
+
+7. Summary of New Definitions
+
+ The following list summarizes the constants, structure, and extern
+ definitions discussed in this memo, sorted by header.
+
+ <net/if.h> IFNAMSIZ
+ <net/if.h> struct if_nameindex{};
+
+ <netdb.h> AI_CANONNAME
+ <netdb.h> AI_PASSIVE
+ <netdb.h> EAI_ADDRFAMILY
+ <netdb.h> EAI_AGAIN
+ <netdb.h> EAI_BADFLAGS
+ <netdb.h> EAI_FAIL
+ <netdb.h> EAI_FAMILY
+ <netdb.h> EAI_MEMORY
+ <netdb.h> EAI_NODATA
+ <netdb.h> EAI_NONAME
+ <netdb.h> EAI_SERVICE
+ <netdb.h> EAI_SOCKTYPE
+ <netdb.h> EAI_SYSTEM
+ <netdb.h> NI_DGRAM
+ <netdb.h> NI_MAXHOST
+ <netdb.h> NI_MAXSERV
+ <netdb.h> NI_NAMEREQD
+ <netdb.h> NI_NOFQDN
+ <netdb.h> NI_NUMERICHOST
+ <netdb.h> NI_NUMERICSERV
+ <netdb.h> struct addrinfo{};
+
+ <netinet/in.h> IN6ADDR_ANY_INIT
+ <netinet/in.h> IN6ADDR_LOOPBACK_INIT
+ <netinet/in.h> INET6_ADDRSTRLEN
+ <netinet/in.h> INET_ADDRSTRLEN
+ <netinet/in.h> IPPROTO_IPV6
+ <netinet/in.h> IPV6_ADDRFORM
+ <netinet/in.h> IPV6_ADD_MEMBERSHIP
+ <netinet/in.h> IPV6_DROP_MEMBERSHIP
+ <netinet/in.h> IPV6_MULTICAST_HOPS
+ <netinet/in.h> IPV6_MULTICAST_IF
+ <netinet/in.h> IPV6_MULTICAST_LOOP
+ <netinet/in.h> IPV6_UNICAST_HOPS
+
+
+
+Gilligan, et. al. Informational [Page 29]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ <netinet/in.h> SIN6_LEN
+ <netinet/in.h> extern const struct in6_addr in6addr_any;
+ <netinet/in.h> extern const struct in6_addr in6addr_loopback;
+ <netinet/in.h> struct in6_addr{};
+ <netinet/in.h> struct ipv6_mreq{};
+ <netinet/in.h> struct sockaddr_in6{};
+
+ <resolv.h> RES_USE_INET6
+
+ <sys/socket.h> AF_INET6
+ <sys/socket.h> PF_INET6
+
+
+ The following list summarizes the function and macro prototypes
+ discussed in this memo, sorted by header.
+
+<arpa/inet.h> int inet_pton(int, const char *, void *);
+<arpa/inet.h> const char *inet_ntop(int, const void *,
+ char *, size_t);
+
+<net/if.h> char *if_indextoname(unsigned int, char *);
+<net/if.h> unsigned int if_nametoindex(const char *);
+<net/if.h> void if_freenameindex(struct if_nameindex *);
+<net/if.h> struct if_nameindex *if_nameindex(void);
+
+<netdb.h> int getaddrinfo(const char *, const char *,
+ const struct addrinfo *,
+ struct addrinfo **);
+<netdb.h> int getnameinfo(const struct sockaddr *, size_t,
+ char *, size_t, char *, size_t, int);
+<netdb.h> void freeaddrinfo(struct addrinfo *);
+<netdb.h> char *gai_strerror(int);
+<netdb.h> struct hostent *gethostbyname(const char *);
+<netdb.h> struct hostent *gethostbyaddr(const char *, int, int);
+<netdb.h> struct hostent *gethostbyname2(const char *, int);
+
+<netinet/in.h> int IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_LOOPBACK(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_GLOBAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_ORGLOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MULTICAST(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_SITELOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_UNSPECIFIED(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_V4COMPAT(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_V4MAPPED(const struct in6_addr *);
+
+
+
+Gilligan, et. al. Informational [Page 30]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+8. Security Considerations
+
+ IPv6 provides a number of new security mechanisms, many of which need
+ to be accessible to applications. A companion memo detailing the
+ extensions to the socket interfaces to support IPv6 security is being
+ written [3].
+
+9. Acknowledgments
+
+ Thanks to the many people who made suggestions and provided feedback
+ to to the numerous revisions of this document, including: Werner
+ Almesberger, Ran Atkinson, Fred Baker, Dave Borman, Andrew Cherenson,
+ Alex Conta, Alan Cox, Steve Deering, Richard Draves, Francis Dupont,
+ Robert Elz, Marc Hasson, Tim Hartrick, Tom Herbert, Bob Hinden, Wan-
+ Yen Hsu, Christian Huitema, Koji Imada, Markus Jork, Ron Lee, Alan
+ Lloyd, Charles Lynn, Jack McCann, Dan McDonald, Dave Mitton, Thomas
+ Narten, Erik Nordmark, Josh Osborne, Craig Partridge, Jean-Luc
+ Richier, Erik Scoredos, Keith Sklower, Matt Thomas, Harvey Thompson,
+ Dean D. Throop, Karen Tracey, Glenn Trewitt, Paul Vixie, David
+ Waitzman, Carl Williams, and Kazuhiko Yamamoto,
+
+ The getaddrinfo() and getnameinfo() functions are taken from an
+ earlier Work in Progress by Keith Sklower. As noted in that
+ document, William Durst, Steven Wise, Michael Karels, and Eric Allman
+ provided many useful discussions on the subject of protocol-
+ independent name-to-address translation, and reviewed early versions
+ of Keith Sklower's original proposal. Eric Allman implemented the
+ first prototype of getaddrinfo(). The observation that specifying
+ the pair of name and service would suffice for connecting to a
+ service independent of protocol details was made by Marshall Rose in
+ a proposal to X/Open for a "Uniform Network Interface".
+
+ Craig Metz made many contributions to this document. Ramesh Govindan
+ made a number of contributions and co-authored an earlier version of
+ this memo.
+
+10. References
+
+ [1] Deering, S., and R. Hinden, "Internet Protocol, Version 6 (IPv6)
+ Specification", RFC 1883, December 1995.
+
+ [2] Hinden, R., and S. Deering, "IP Version 6 Addressing Architecture",
+ RFC 1884, December 1995.
+
+ [3] McDonald, D., "A Simple IP Security API Extension to BSD Sockets",
+ Work in Progress.
+
+
+
+
+
+Gilligan, et. al. Informational [Page 31]
+
+RFC 2133 IPv6 Socket Interface Extensions April 1997
+
+
+ [4] IEEE, "Protocol Independent Interfaces", IEEE Std 1003.1g, DRAFT
+ 6.3, November 1995.
+
+ [5] Stevens, W., and M. Thomas, "Advanced Sockets API for IPv6",
+ Work in Progress.
+
+ [6] Vixie, P., "Reverse Name Lookups of Encapsulated IPv4 Addresses in
+ IPv6", Work in Progress.
+
+11. Authors' Addresses
+
+ Robert E. Gilligan
+ Freegate Corporation
+ 710 Lakeway Dr. STE 230
+ Sunnyvale, CA 94086
+
+ Phone: +1 408 524 4804
+ EMail: gilligan@freegate.net
+
+
+ Susan Thomson
+ Bell Communications Research
+ MRE 2P-343, 445 South Street
+ Morristown, NJ 07960
+
+ Phone: +1 201 829 4514
+ EMail: set@thumper.bellcore.com
+
+
+ Jim Bound
+ Digital Equipment Corporation
+ 110 Spitbrook Road ZK3-3/U14
+ Nashua, NH 03062-2698
+
+ Phone: +1 603 881 0400
+ Email: bound@zk3.dec.com
+
+
+ W. Richard Stevens
+ 1202 E. Paseo del Zorro
+ Tucson, AZ 85718-2826
+
+ Phone: +1 520 297 9416
+ EMail: rstevens@kohala.com
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 32]
+
diff --git a/doc/rfc/rfc2136.txt b/doc/rfc/rfc2136.txt
new file mode 100644
index 0000000..4d62702
--- /dev/null
+++ b/doc/rfc/rfc2136.txt
@@ -0,0 +1,1460 @@
+
+
+
+
+
+
+Network Working Group P. Vixie, Editor
+Request for Comments: 2136 ISC
+Updates: 1035 S. Thomson
+Category: Standards Track Bellcore
+ Y. Rekhter
+ Cisco
+ J. Bound
+ DEC
+ April 1997
+
+ Dynamic Updates in the Domain Name System (DNS UPDATE)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Abstract
+
+ The Domain Name System was originally designed to support queries of
+ a statically configured database. While the data was expected to
+ change, the frequency of those changes was expected to be fairly low,
+ and all updates were made as external edits to a zone's Master File.
+
+ Using this specification of the UPDATE opcode, it is possible to add
+ or delete RRs or RRsets from a specified zone. Prerequisites are
+ specified separately from update operations, and can specify a
+ dependency upon either the previous existence or nonexistence of an
+ RRset, or the existence of a single RR.
+
+ UPDATE is atomic, i.e., all prerequisites must be satisfied or else
+ no update operations will take place. There are no data dependent
+ error conditions defined after the prerequisites have been met.
+
+1 - Definitions
+
+ This document intentionally gives more definition to the roles of
+ "Master," "Slave," and "Primary Master" servers, and their
+ enumeration in NS RRs, and the SOA MNAME field. In that sense, the
+ following server type definitions can be considered an addendum to
+ [RFC1035], and are intended to be consistent with [RFC1996]:
+
+ Slave an authoritative server that uses AXFR or IXFR to
+ retrieve the zone and is named in the zone's NS
+ RRset.
+
+
+
+Vixie, et. al. Standards Track [Page 1]
+
+RFC 2136 DNS Update April 1997
+
+
+ Master an authoritative server configured to be the
+ source of AXFR or IXFR data for one or more slave
+ servers.
+
+ Primary Master master server at the root of the AXFR/IXFR
+ dependency graph. The primary master is named in
+ the zone's SOA MNAME field and optionally by an NS
+ RR. There is by definition only one primary master
+ server per zone.
+
+ A domain name identifies a node within the domain name space tree
+ structure. Each node has a set (possibly empty) of Resource Records
+ (RRs). All RRs having the same NAME, CLASS and TYPE are called a
+ Resource Record Set (RRset).
+
+ The pseudocode used in this document is for example purposes only.
+ If it is found to disagree with the text, the text shall be
+ considered authoritative. If the text is found to be ambiguous, the
+ pseudocode can be used to help resolve the ambiguity.
+
+ 1.1 - Comparison Rules
+
+ 1.1.1. Two RRs are considered equal if their NAME, CLASS, TYPE,
+ RDLENGTH and RDATA fields are equal. Note that the time-to-live
+ (TTL) field is explicitly excluded from the comparison.
+
+ 1.1.2. The rules for comparison of character strings in names are
+ specified in [RFC1035 2.3.3].
+
+ 1.1.3. Wildcarding is disabled. That is, a wildcard ("*") in an
+ update only matches a wildcard ("*") in the zone, and vice versa.
+
+ 1.1.4. Aliasing is disabled: A CNAME in the zone matches a CNAME in
+ the update, and will not otherwise be followed. All UPDATE
+ operations are done on the basis of canonical names.
+
+ 1.1.5. The following RR types cannot be appended to an RRset. If the
+ following comparison rules are met, then an attempt to add the new RR
+ will result in the replacement of the previous RR:
+
+ SOA compare only NAME, CLASS and TYPE -- it is not possible to
+ have more than one SOA per zone, even if any of the data
+ fields differ.
+
+ WKS compare only NAME, CLASS, TYPE, ADDRESS, and PROTOCOL
+ -- only one WKS RR is possible for this tuple, even if the
+ services masks differ.
+
+
+
+
+Vixie, et. al. Standards Track [Page 2]
+
+RFC 2136 DNS Update April 1997
+
+
+ CNAME compare only NAME, CLASS, and TYPE -- it is not possible
+ to have more than one CNAME RR, even if their data fields
+ differ.
+
+ 1.2 - Glue RRs
+
+ For the purpose of determining whether a domain name used in the
+ UPDATE protocol is contained within a specified zone, a domain name
+ is "in" a zone if it is owned by that zone's domain name. See
+ section 7.18 for details.
+
+ 1.3 - New Assigned Numbers
+
+ CLASS = NONE (254)
+ RCODE = YXDOMAIN (6)
+ RCODE = YXRRSET (7)
+ RCODE = NXRRSET (8)
+ RCODE = NOTAUTH (9)
+ RCODE = NOTZONE (10)
+ Opcode = UPDATE (5)
+
+2 - Update Message Format
+
+ The DNS Message Format is defined by [RFC1035 4.1]. Some extensions
+ are necessary (for example, more error codes are possible under
+ UPDATE than under QUERY) and some fields must be overloaded (see
+ description of CLASS fields below).
+
+ The overall format of an UPDATE message is, following [ibid]:
+
+ +---------------------+
+ | Header |
+ +---------------------+
+ | Zone | specifies the zone to be updated
+ +---------------------+
+ | Prerequisite | RRs or RRsets which must (not) preexist
+ +---------------------+
+ | Update | RRs or RRsets to be added or deleted
+ +---------------------+
+ | Additional Data | additional data
+ +---------------------+
+
+
+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 3]
+
+RFC 2136 DNS Update April 1997
+
+
+ The Header Section specifies that this message is an UPDATE, and
+ describes the size of the other sections. The Zone Section names the
+ zone that is to be updated by this message. The Prerequisite Section
+ specifies the starting invariants (in terms of zone content) required
+ for this update. The Update Section contains the edits to be made,
+ and the Additional Data Section contains data which may be necessary
+ to complete, but is not part of, this update.
+
+ 2.1 - Transport Issues
+
+ An update transaction may be carried in a UDP datagram, if the
+ request fits, or in a TCP connection (at the discretion of the
+ requestor). When TCP is used, the message is in the format described
+ in [RFC1035 4.2.2].
+
+ 2.2 - Message Header
+
+ The header of the DNS Message Format is defined by [RFC 1035 4.1].
+ Not all opcodes define the same set of flag bits, though as a
+ practical matter most of the bits defined for QUERY (in [ibid]) are
+ identically defined by the other opcodes. UPDATE uses only one flag
+ bit (QR).
+
+ The DNS Message Format specifies record counts for its four sections
+ (Question, Answer, Authority, and Additional). UPDATE uses the same
+ fields, and the same section formats, but the naming and use of these
+ sections differs as shown in the following modified header, after
+ [RFC1035 4.1.1]:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ID |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ |QR| Opcode | Z | RCODE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ZOCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PRCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | UPCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ADCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 4]
+
+RFC 2136 DNS Update April 1997
+
+
+ These fields are used as follows:
+
+ ID A 16-bit identifier assigned by the entity that generates any
+ kind of request. This identifier is copied in the
+ corresponding reply and can be used by the requestor to match
+ replies to outstanding requests, or by the server to detect
+ duplicated requests from some requestor.
+
+ QR A one bit field that specifies whether this message is a
+ request (0), or a response (1).
+
+ Opcode A four bit field that specifies the kind of request in this
+ message. This value is set by the originator of a request
+ and copied into the response. The Opcode value that
+ identifies an UPDATE message is five (5).
+
+ Z Reserved for future use. Should be zero (0) in all requests
+ and responses. A non-zero Z field should be ignored by
+ implementations of this specification.
+
+ RCODE Response code - this four bit field is undefined in requests
+ and set in responses. The values and meanings of this field
+ within responses are as follows:
+
+ Mneumonic Value Description
+ ------------------------------------------------------------
+ NOERROR 0 No error condition.
+ FORMERR 1 The name server was unable to interpret
+ the request due to a format error.
+ SERVFAIL 2 The name server encountered an internal
+ failure while processing this request,
+ for example an operating system error
+ or a forwarding timeout.
+ NXDOMAIN 3 Some name that ought to exist,
+ does not exist.
+ NOTIMP 4 The name server does not support
+ the specified Opcode.
+ REFUSED 5 The name server refuses to perform the
+ specified operation for policy or
+ security reasons.
+ YXDOMAIN 6 Some name that ought not to exist,
+ does exist.
+ YXRRSET 7 Some RRset that ought not to exist,
+ does exist.
+ NXRRSET 8 Some RRset that ought to exist,
+ does not exist.
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 5]
+
+RFC 2136 DNS Update April 1997
+
+
+ NOTAUTH 9 The server is not authoritative for
+ the zone named in the Zone Section.
+ NOTZONE 10 A name used in the Prerequisite or
+ Update Section is not within the
+ zone denoted by the Zone Section.
+
+ ZOCOUNT The number of RRs in the Zone Section.
+
+ PRCOUNT The number of RRs in the Prerequisite Section.
+
+ UPCOUNT The number of RRs in the Update Section.
+
+ ADCOUNT The number of RRs in the Additional Data Section.
+
+ 2.3 - Zone Section
+
+ The Zone Section has the same format as that specified in [RFC1035
+ 4.1.2], with the fields redefined as follows:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / ZNAME /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ZTYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ZCLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ UPDATE uses this section to denote the zone of the records being
+ updated. All records to be updated must be in the same zone, and
+ therefore the Zone Section is allowed to contain exactly one record.
+ The ZNAME is the zone name, the ZTYPE must be SOA, and the ZCLASS is
+ the zone's class.
+
+ 2.4 - Prerequisite Section
+
+ This section contains a set of RRset prerequisites which must be
+ satisfied at the time the UPDATE packet is received by the primary
+ master server. The format of this section is as specified by
+ [RFC1035 4.1.3]. There are five possible sets of semantics that can
+ be expressed here, summarized as follows and then explained below.
+
+ (1) RRset exists (value independent). At least one RR with a
+ specified NAME and TYPE (in the zone and class specified by
+ the Zone Section) must exist.
+
+
+
+Vixie, et. al. Standards Track [Page 6]
+
+RFC 2136 DNS Update April 1997
+
+
+ (2) RRset exists (value dependent). A set of RRs with a
+ specified NAME and TYPE exists and has the same members
+ with the same RDATAs as the RRset specified here in this
+ Section.
+
+ (3) RRset does not exist. No RRs with a specified NAME and TYPE
+ (in the zone and class denoted by the Zone Section) can exist.
+
+ (4) Name is in use. At least one RR with a specified NAME (in
+ the zone and class specified by the Zone Section) must exist.
+ Note that this prerequisite is NOT satisfied by empty
+ nonterminals.
+
+ (5) Name is not in use. No RR of any type is owned by a
+ specified NAME. Note that this prerequisite IS satisfied by
+ empty nonterminals.
+
+ The syntax of these is as follows:
+
+ 2.4.1 - RRset Exists (Value Independent)
+
+ At least one RR with a specified NAME and TYPE (in the zone and class
+ specified in the Zone Section) must exist.
+
+ For this prerequisite, a requestor adds to the section a single RR
+ whose NAME and TYPE are equal to that of the zone RRset whose
+ existence is required. RDLENGTH is zero and RDATA is therefore
+ empty. CLASS must be specified as ANY to differentiate this
+ condition from that of an actual RR whose RDLENGTH is naturally zero
+ (0) (e.g., NULL). TTL is specified as zero (0).
+
+ 2.4.2 - RRset Exists (Value Dependent)
+
+ A set of RRs with a specified NAME and TYPE exists and has the same
+ members with the same RDATAs as the RRset specified here in this
+ section. While RRset ordering is undefined and therefore not
+ significant to this comparison, the sets be identical in their
+ extent.
+
+ For this prerequisite, a requestor adds to the section an entire
+ RRset whose preexistence is required. NAME and TYPE are that of the
+ RRset being denoted. CLASS is that of the zone. TTL must be
+ specified as zero (0) and is ignored when comparing RRsets for
+ identity.
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 7]
+
+RFC 2136 DNS Update April 1997
+
+
+ 2.4.3 - RRset Does Not Exist
+
+ No RRs with a specified NAME and TYPE (in the zone and class denoted
+ by the Zone Section) can exist.
+
+ For this prerequisite, a requestor adds to the section a single RR
+ whose NAME and TYPE are equal to that of the RRset whose nonexistence
+ is required. The RDLENGTH of this record is zero (0), and RDATA
+ field is therefore empty. CLASS must be specified as NONE in order
+ to distinguish this condition from a valid RR whose RDLENGTH is
+ naturally zero (0) (for example, the NULL RR). TTL must be specified
+ as zero (0).
+
+ 2.4.4 - Name Is In Use
+
+ Name is in use. At least one RR with a specified NAME (in the zone
+ and class specified by the Zone Section) must exist. Note that this
+ prerequisite is NOT satisfied by empty nonterminals.
+
+ For this prerequisite, a requestor adds to the section a single RR
+ whose NAME is equal to that of the name whose ownership of an RR is
+ required. RDLENGTH is zero and RDATA is therefore empty. CLASS must
+ be specified as ANY to differentiate this condition from that of an
+ actual RR whose RDLENGTH is naturally zero (0) (e.g., NULL). TYPE
+ must be specified as ANY to differentiate this case from that of an
+ RRset existence test. TTL is specified as zero (0).
+
+ 2.4.5 - Name Is Not In Use
+
+ Name is not in use. No RR of any type is owned by a specified NAME.
+ Note that this prerequisite IS satisfied by empty nonterminals.
+
+ For this prerequisite, a requestor adds to the section a single RR
+ whose NAME is equal to that of the name whose nonownership of any RRs
+ is required. RDLENGTH is zero and RDATA is therefore empty. CLASS
+ must be specified as NONE. TYPE must be specified as ANY. TTL must
+ be specified as zero (0).
+
+ 2.5 - Update Section
+
+ This section contains RRs to be added to or deleted from the zone.
+ The format of this section is as specified by [RFC1035 4.1.3]. There
+ are four possible sets of semantics, summarized below and with
+ details to follow.
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 8]
+
+RFC 2136 DNS Update April 1997
+
+
+ (1) Add RRs to an RRset.
+ (2) Delete an RRset.
+ (3) Delete all RRsets from a name.
+ (4) Delete an RR from an RRset.
+
+ The syntax of these is as follows:
+
+ 2.5.1 - Add To An RRset
+
+ RRs are added to the Update Section whose NAME, TYPE, TTL, RDLENGTH
+ and RDATA are those being added, and CLASS is the same as the zone
+ class. Any duplicate RRs will be silently ignored by the primary
+ master.
+
+ 2.5.2 - Delete An RRset
+
+ One RR is added to the Update Section whose NAME and TYPE are those
+ of the RRset to be deleted. TTL must be specified as zero (0) and is
+ otherwise not used by the primary master. CLASS must be specified as
+ ANY. RDLENGTH must be zero (0) and RDATA must therefore be empty.
+ If no such RRset exists, then this Update RR will be silently ignored
+ by the primary master.
+
+ 2.5.3 - Delete All RRsets From A Name
+
+ One RR is added to the Update Section whose NAME is that of the name
+ to be cleansed of RRsets. TYPE must be specified as ANY. TTL must
+ be specified as zero (0) and is otherwise not used by the primary
+ master. CLASS must be specified as ANY. RDLENGTH must be zero (0)
+ and RDATA must therefore be empty. If no such RRsets exist, then
+ this Update RR will be silently ignored by the primary master.
+
+ 2.5.4 - Delete An RR From An RRset
+
+ RRs to be deleted are added to the Update Section. The NAME, TYPE,
+ RDLENGTH and RDATA must match the RR being deleted. TTL must be
+ specified as zero (0) and will otherwise be ignored by the primary
+ master. CLASS must be specified as NONE to distinguish this from an
+ RR addition. If no such RRs exist, then this Update RR will be
+ silently ignored by the primary master.
+
+
+
+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 9]
+
+RFC 2136 DNS Update April 1997
+
+
+ 2.6 - Additional Data Section
+
+ This section contains RRs which are related to the update itself, or
+ to new RRs being added by the update. For example, out of zone glue
+ (A RRs referred to by new NS RRs) should be presented here. The
+ server can use or ignore out of zone glue, at the discretion of the
+ server implementor. The format of this section is as specified by
+ [RFC1035 4.1.3].
+
+3 - Server Behavior
+
+ A server, upon receiving an UPDATE request, will signal NOTIMP to the
+ requestor if the UPDATE opcode is not recognized or if it is
+ recognized but has not been implemented. Otherwise, processing
+ continues as follows.
+
+ 3.1 - Process Zone Section
+
+ 3.1.1. The Zone Section is checked to see that there is exactly one
+ RR therein and that the RR's ZTYPE is SOA, else signal FORMERR to the
+ requestor. Next, the ZNAME and ZCLASS are checked to see if the zone
+ so named is one of this server's authority zones, else signal NOTAUTH
+ to the requestor. If the server is a zone slave, the request will be
+ forwarded toward the primary master.
+
+ 3.1.2 - Pseudocode For Zone Section Processing
+
+ if (zcount != 1 || ztype != SOA)
+ return (FORMERR)
+ if (zone_type(zname, zclass) == SLAVE)
+ return forward()
+ if (zone_type(zname, zclass) == MASTER)
+ return update()
+ return (NOTAUTH)
+
+ Sections 3.2 through 3.8 describe the primary master's behaviour,
+ whereas Section 6 describes a forwarder's behaviour.
+
+ 3.2 - Process Prerequisite Section
+
+ Next, the Prerequisite Section is checked to see that all
+ prerequisites are satisfied by the current state of the zone. Using
+ the definitions expressed in Section 1.2, if any RR's NAME is not
+ within the zone specified in the Zone Section, signal NOTZONE to the
+ requestor.
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 10]
+
+RFC 2136 DNS Update April 1997
+
+
+ 3.2.1. For RRs in this section whose CLASS is ANY, test to see that
+ TTL and RDLENGTH are both zero (0), else signal FORMERR to the
+ requestor. If TYPE is ANY, test to see that there is at least one RR
+ in the zone whose NAME is the same as that of the Prerequisite RR,
+ else signal NXDOMAIN to the requestor. If TYPE is not ANY, test to
+ see that there is at least one RR in the zone whose NAME and TYPE are
+ the same as that of the Prerequisite RR, else signal NXRRSET to the
+ requestor.
+
+ 3.2.2. For RRs in this section whose CLASS is NONE, test to see that
+ the TTL and RDLENGTH are both zero (0), else signal FORMERR to the
+ requestor. If the TYPE is ANY, test to see that there are no RRs in
+ the zone whose NAME is the same as that of the Prerequisite RR, else
+ signal YXDOMAIN to the requestor. If the TYPE is not ANY, test to
+ see that there are no RRs in the zone whose NAME and TYPE are the
+ same as that of the Prerequisite RR, else signal YXRRSET to the
+ requestor.
+
+ 3.2.3. For RRs in this section whose CLASS is the same as the ZCLASS,
+ test to see that the TTL is zero (0), else signal FORMERR to the
+ requestor. Then, build an RRset for each unique <NAME,TYPE> and
+ compare each resulting RRset for set equality (same members, no more,
+ no less) with RRsets in the zone. If any Prerequisite RRset is not
+ entirely and exactly matched by a zone RRset, signal NXRRSET to the
+ requestor. If any RR in this section has a CLASS other than ZCLASS
+ or NONE or ANY, signal FORMERR to the requestor.
+
+ 3.2.4 - Table Of Metavalues Used In Prerequisite Section
+
+ CLASS TYPE RDATA Meaning
+ ------------------------------------------------------------
+ ANY ANY empty Name is in use
+ ANY rrset empty RRset exists (value independent)
+ NONE ANY empty Name is not in use
+ NONE rrset empty RRset does not exist
+ zone rrset rr RRset exists (value dependent)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 11]
+
+RFC 2136 DNS Update April 1997
+
+
+ 3.2.5 - Pseudocode for Prerequisite Section Processing
+
+ for rr in prerequisites
+ if (rr.ttl != 0)
+ return (FORMERR)
+ if (zone_of(rr.name) != ZNAME)
+ return (NOTZONE);
+ if (rr.class == ANY)
+ if (rr.rdlength != 0)
+ return (FORMERR)
+ if (rr.type == ANY)
+ if (!zone_name<rr.name>)
+ return (NXDOMAIN)
+ else
+ if (!zone_rrset<rr.name, rr.type>)
+ return (NXRRSET)
+ if (rr.class == NONE)
+ if (rr.rdlength != 0)
+ return (FORMERR)
+ if (rr.type == ANY)
+ if (zone_name<rr.name>)
+ return (YXDOMAIN)
+ else
+ if (zone_rrset<rr.name, rr.type>)
+ return (YXRRSET)
+ if (rr.class == zclass)
+ temp<rr.name, rr.type> += rr
+ else
+ return (FORMERR)
+
+ for rrset in temp
+ if (zone_rrset<rrset.name, rrset.type> != rrset)
+ return (NXRRSET)
+
+ 3.3 - Check Requestor's Permissions
+
+ 3.3.1. Next, the requestor's permission to update the RRs named in
+ the Update Section may be tested in an implementation dependent
+ fashion or using mechanisms specified in a subsequent Secure DNS
+ Update protocol. If the requestor does not have permission to
+ perform these updates, the server may write a warning message in its
+ operations log, and may either signal REFUSED to the requestor, or
+ ignore the permission problem and proceed with the update.
+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 12]
+
+RFC 2136 DNS Update April 1997
+
+
+ 3.3.2. While the exact processing is implementation defined, if these
+ verification activities are to be performed, this is the point in the
+ server's processing where such performance should take place, since
+ if a REFUSED condition is encountered after an update has been
+ partially applied, it will be necessary to undo the partial update
+ and restore the zone to its original state before answering the
+ requestor.
+
+ 3.3.3 - Pseudocode for Permission Checking
+
+ if (security policy exists)
+ if (this update is not permitted)
+ if (local option)
+ log a message about permission problem
+ if (local option)
+ return (REFUSED)
+
+ 3.4 - Process Update Section
+
+ Next, the Update Section is processed as follows.
+
+ 3.4.1 - Prescan
+
+ The Update Section is parsed into RRs and each RR's CLASS is checked
+ to see if it is ANY, NONE, or the same as the Zone Class, else signal
+ a FORMERR to the requestor. Using the definitions in Section 1.2,
+ each RR's NAME must be in the zone specified by the Zone Section,
+ else signal NOTZONE to the requestor.
+
+ 3.4.1.2. For RRs whose CLASS is not ANY, check the TYPE and if it is
+ ANY, AXFR, MAILA, MAILB, or any other QUERY metatype, or any
+ unrecognized type, then signal FORMERR to the requestor. For RRs
+ whose CLASS is ANY or NONE, check the TTL to see that it is zero (0),
+ else signal a FORMERR to the requestor. For any RR whose CLASS is
+ ANY, check the RDLENGTH to make sure that it is zero (0) (that is,
+ the RDATA field is empty), and that the TYPE is not AXFR, MAILA,
+ MAILB, or any other QUERY metatype besides ANY, or any unrecognized
+ type, else signal FORMERR to the requestor.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 13]
+
+RFC 2136 DNS Update April 1997
+
+
+ 3.4.1.3 - Pseudocode For Update Section Prescan
+
+ [rr] for rr in updates
+ if (zone_of(rr.name) != ZNAME)
+ return (NOTZONE);
+ if (rr.class == zclass)
+ if (rr.type & ANY|AXFR|MAILA|MAILB)
+ return (FORMERR)
+ elsif (rr.class == ANY)
+ if (rr.ttl != 0 || rr.rdlength != 0
+ || rr.type & AXFR|MAILA|MAILB)
+ return (FORMERR)
+ elsif (rr.class == NONE)
+ if (rr.ttl != 0 || rr.type & ANY|AXFR|MAILA|MAILB)
+ return (FORMERR)
+ else
+ return (FORMERR)
+
+ 3.4.2 - Update
+
+ The Update Section is parsed into RRs and these RRs are processed in
+ order.
+
+ 3.4.2.1. If any system failure (such as an out of memory condition,
+ or a hardware error in persistent storage) occurs during the
+ processing of this section, signal SERVFAIL to the requestor and undo
+ all updates applied to the zone during this transaction.
+
+ 3.4.2.2. Any Update RR whose CLASS is the same as ZCLASS is added to
+ the zone. In case of duplicate RDATAs (which for SOA RRs is always
+ the case, and for WKS RRs is the case if the ADDRESS and PROTOCOL
+ fields both match), the Zone RR is replaced by Update RR. If the
+ TYPE is SOA and there is no Zone SOA RR, or the new SOA.SERIAL is
+ lower (according to [RFC1982]) than or equal to the current Zone SOA
+ RR's SOA.SERIAL, the Update RR is ignored. In the case of a CNAME
+ Update RR and a non-CNAME Zone RRset or vice versa, ignore the CNAME
+ Update RR, otherwise replace the CNAME Zone RR with the CNAME Update
+ RR.
+
+ 3.4.2.3. For any Update RR whose CLASS is ANY and whose TYPE is ANY,
+ all Zone RRs with the same NAME are deleted, unless the NAME is the
+ same as ZNAME in which case only those RRs whose TYPE is other than
+ SOA or NS are deleted. For any Update RR whose CLASS is ANY and
+ whose TYPE is not ANY all Zone RRs with the same NAME and TYPE are
+ deleted, unless the NAME is the same as ZNAME in which case neither
+ SOA or NS RRs will be deleted.
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 14]
+
+RFC 2136 DNS Update April 1997
+
+
+ 3.4.2.4. For any Update RR whose class is NONE, any Zone RR whose
+ NAME, TYPE, RDATA and RDLENGTH are equal to the Update RR is deleted,
+ unless the NAME is the same as ZNAME and either the TYPE is SOA or
+ the TYPE is NS and the matching Zone RR is the only NS remaining in
+ the RRset, in which case this Update RR is ignored.
+
+ 3.4.2.5. Signal NOERROR to the requestor.
+
+ 3.4.2.6 - Table Of Metavalues Used In Update Section
+
+ CLASS TYPE RDATA Meaning
+ ---------------------------------------------------------
+ ANY ANY empty Delete all RRsets from a name
+ ANY rrset empty Delete an RRset
+ NONE rrset rr Delete an RR from an RRset
+ zone rrset rr Add to an RRset
+
+ 3.4.2.7 - Pseudocode For Update Section Processing
+
+ [rr] for rr in updates
+ if (rr.class == zclass)
+ if (rr.type == CNAME)
+ if (zone_rrset<rr.name, ~CNAME>)
+ next [rr]
+ elsif (zone_rrset<rr.name, CNAME>)
+ next [rr]
+ if (rr.type == SOA)
+ if (!zone_rrset<rr.name, SOA> ||
+ zone_rr<rr.name, SOA>.serial > rr.soa.serial)
+ next [rr]
+ for zrr in zone_rrset<rr.name, rr.type>
+ if (rr.type == CNAME || rr.type == SOA ||
+ (rr.type == WKS && rr.proto == zrr.proto &&
+ rr.address == zrr.address) ||
+ rr.rdata == zrr.rdata)
+ zrr = rr
+ next [rr]
+ zone_rrset<rr.name, rr.type> += rr
+ elsif (rr.class == ANY)
+ if (rr.type == ANY)
+ if (rr.name == zname)
+ zone_rrset<rr.name, ~(SOA|NS)> = Nil
+ else
+ zone_rrset<rr.name, *> = Nil
+ elsif (rr.name == zname &&
+ (rr.type == SOA || rr.type == NS))
+ next [rr]
+ else
+
+
+
+Vixie, et. al. Standards Track [Page 15]
+
+RFC 2136 DNS Update April 1997
+
+
+ zone_rrset<rr.name, rr.type> = Nil
+ elsif (rr.class == NONE)
+ if (rr.type == SOA)
+ next [rr]
+ if (rr.type == NS && zone_rrset<rr.name, NS> == rr)
+ next [rr]
+ zone_rr<rr.name, rr.type, rr.data> = Nil
+ return (NOERROR)
+
+ 3.5 - Stability
+
+ When a zone is modified by an UPDATE operation, the server must
+ commit the change to nonvolatile storage before sending a response to
+ the requestor or answering any queries or transfers for the modified
+ zone. It is reasonable for a server to store only the update records
+ as long as a system reboot or power failure will cause these update
+ records to be incorporated into the zone the next time the server is
+ started. It is also reasonable for the server to copy the entire
+ modified zone to nonvolatile storage after each update operation,
+ though this would have suboptimal performance for large zones.
+
+ 3.6 - Zone Identity
+
+ If the zone's SOA SERIAL is changed by an update operation, that
+ change must be in a positive direction (using modulo 2**32 arithmetic
+ as specified by [RFC1982]). Attempts to replace an SOA with one
+ whose SERIAL is less than the current one will be silently ignored by
+ the primary master server.
+
+ If the zone's SOA's SERIAL is not changed as a result of an update
+ operation, then the server shall increment it automatically before
+ the SOA or any changed name or RR or RRset is included in any
+ response or transfer. The primary master server's implementor might
+ choose to autoincrement the SOA SERIAL if any of the following events
+ occurs:
+
+ (1) Each update operation.
+
+ (2) A name, RR or RRset in the zone has changed and has subsequently
+ been visible to a DNS client since the unincremented SOA was
+ visible to a DNS client, and the SOA is about to become visible
+ to a DNS client.
+
+ (3) A configurable period of time has elapsed since the last update
+ operation. This period shall be less than or equal to one third
+ of the zone refresh time, and the default shall be the lesser of
+ that maximum and 300 seconds.
+
+
+
+
+Vixie, et. al. Standards Track [Page 16]
+
+RFC 2136 DNS Update April 1997
+
+
+ (4) A configurable number of updates has been applied since the last
+ SOA change. The default value for this configuration parameter
+ shall be one hundred (100).
+
+ It is imperative that the zone's contents and the SOA's SERIAL be
+ tightly synchronized. If the zone appears to change, the SOA must
+ appear to change as well.
+
+ 3.7 - Atomicity
+
+ During the processing of an UPDATE transaction, the server must
+ ensure atomicity with respect to other (concurrent) UPDATE or QUERY
+ transactions. No two transactions can be processed concurrently if
+ either depends on the final results of the other; in particular, a
+ QUERY should not be able to retrieve RRsets which have been partially
+ modified by a concurrent UPDATE, and an UPDATE should not be able to
+ start from prerequisites that might not still hold at the completion
+ of some other concurrent UPDATE. Finally, if two UPDATE transactions
+ would modify the same names, RRs or RRsets, then such UPDATE
+ transactions must be serialized.
+
+ 3.8 - Response
+
+ At the end of UPDATE processing, a response code will be known. A
+ response message is generated by copying the ID and Opcode fields
+ from the request, and either copying the ZOCOUNT, PRCOUNT, UPCOUNT,
+ and ADCOUNT fields and associated sections, or placing zeros (0) in
+ the these "count" fields and not including any part of the original
+ update. The QR bit is set to one (1), and the response is sent back
+ to the requestor. If the requestor used UDP, then the response will
+ be sent to the requestor's source UDP port. If the requestor used
+ TCP, then the response will be sent back on the requestor's open TCP
+ connection.
+
+4 - Requestor Behaviour
+
+ 4.1. From a requestor's point of view, any authoritative server for
+ the zone can appear to be able to process update requests, even
+ though only the primary master server is actually able to modify the
+ zone's master file. Requestors are expected to know the name of the
+ zone they intend to update and to know or be able to determine the
+ name servers for that zone.
+
+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 17]
+
+RFC 2136 DNS Update April 1997
+
+
+ 4.2. If update ordering is desired, the requestor will need to know
+ the value of the existing SOA RR. Requestors who update the SOA RR
+ must update the SOA SERIAL field in a positive direction (as defined
+ by [RFC1982]) and also preserve the other SOA fields unless the
+ requestor's explicit intent is to change them. The SOA SERIAL field
+ must never be set to zero (0).
+
+ 4.3. If the requestor has reasonable cause to believe that all of a
+ zone's servers will be equally reachable, then it should arrange to
+ try the primary master server (as given by the SOA MNAME field if
+ matched by some NS NSDNAME) first to avoid unnecessary forwarding
+ inside the slave servers. (Note that the primary master will in some
+ cases not be reachable by all requestors, due to firewalls or network
+ partitioning.)
+
+ 4.4. Once the zone's name servers been found and possibly sorted so
+ that the ones more likely to be reachable and/or support the UPDATE
+ opcode are listed first, the requestor composes an UPDATE message of
+ the following form and sends it to the first name server on its list:
+
+ ID: (new)
+ Opcode: UPDATE
+ Zone zcount: 1
+ Zone zname: (zone name)
+ Zone zclass: (zone class)
+ Zone ztype: T_SOA
+ Prerequisite Section: (see previous text)
+ Update Section: (see previous text)
+ Additional Data Section: (empty)
+
+ 4.5. If the requestor receives a response, and the response has an
+ RCODE other than SERVFAIL or NOTIMP, then the requestor returns an
+ appropriate response to its caller.
+
+ 4.6. If a response is received whose RCODE is SERVFAIL or NOTIMP, or
+ if no response is received within an implementation dependent timeout
+ period, or if an ICMP error is received indicating that the server's
+ port is unreachable, then the requestor will delete the unusable
+ server from its internal name server list and try the next one,
+ repeating until the name server list is empty. If the requestor runs
+ out of servers to try, an appropriate error will be returned to the
+ requestor's caller.
+
+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 18]
+
+RFC 2136 DNS Update April 1997
+
+
+5 - Duplicate Detection, Ordering and Mutual Exclusion
+
+ 5.1. For correct operation, mechanisms may be needed to ensure
+ idempotence, order UPDATE requests and provide mutual exclusion. An
+ UPDATE message or response might be delivered zero times, one time,
+ or multiple times. Datagram duplication is of particular interest
+ since it covers the case of the so-called "replay attack" where a
+ correct request is duplicated maliciously by an intruder.
+
+ 5.2. Multiple UPDATE requests or responses in transit might be
+ delivered in any order, due to network topology changes or load
+ balancing, or to multipath forwarding graphs wherein several slave
+ servers all forward to the primary master. In some cases, it might
+ be required that the earlier update not be applied after the later
+ update, where "earlier" and "later" are defined by an external time
+ base visible to some set of requestors, rather than by the order of
+ request receipt at the primary master.
+
+ 5.3. A requestor can ensure transaction idempotence by explicitly
+ deleting some "marker RR" (rather than deleting the RRset of which it
+ is a part) and then adding a new "marker RR" with a different RDATA
+ field. The Prerequisite Section should specify that the original
+ "marker RR" must be present in order for this UPDATE message to be
+ accepted by the server.
+
+ 5.4. If the request is duplicated by a network error, all duplicate
+ requests will fail since only the first will find the original
+ "marker RR" present and having its known previous value. The
+ decisions of whether to use such a "marker RR" and what RR to use are
+ left up to the application programmer, though one obvious choice is
+ the zone's SOA RR as described below.
+
+ 5.5. Requestors can ensure update ordering by externally
+ synchronizing their use of successive values of the "marker RR."
+ Mutual exclusion can be addressed as a degenerate case, in that a
+ single succession of the "marker RR" is all that is needed.
+
+ 5.6. A special case where update ordering and datagram duplication
+ intersect is when an RR validly changes to some new value and then
+ back to its previous value. Without a "marker RR" as described
+ above, this sequence of updates can leave the zone in an undefined
+ state if datagrams are duplicated.
+
+ 5.7. To achieve an atomic multitransaction "read-modify-write" cycle,
+ a requestor could first retrieve the SOA RR, and build an UPDATE
+ message one of whose prerequisites was the old SOA RR. It would then
+ specify updates that would delete this SOA RR and add a new one with
+ an incremented SOA SERIAL, along with whatever actual prerequisites
+
+
+
+Vixie, et. al. Standards Track [Page 19]
+
+RFC 2136 DNS Update April 1997
+
+
+ and updates were the object of the transaction. If the transaction
+ succeeds, the requestor knows that the RRs being changed were not
+ otherwise altered by any other requestor.
+
+6 - Forwarding
+
+ When a zone slave forwards an UPDATE message upward toward the zone's
+ primary master server, it must allocate a new ID and prepare to enter
+ the role of "forwarding server," which is a requestor with respect to
+ the forward server.
+
+ 6.1. The set of forward servers will be same as the set of servers
+ this zone slave would use as the source of AXFR or IXFR data. So,
+ while the original requestor might have used the zone's NS RRset to
+ locate its update server, a forwarder always forwards toward its
+ designated zone master servers.
+
+ 6.2. If the original requestor used TCP, then the TCP connection from
+ the requestor is still open and the forwarder must use TCP to forward
+ the message. If the original requestor used UDP, the forwarder may
+ use either UDP or TCP to forward the message, at the whim of the
+ implementor.
+
+ 6.3. It is reasonable for forward servers to be forwarders
+ themselves, if the AXFR dependency graph being followed is a deep one
+ involving firewalls and multiple connectivity realms. In most cases
+ the AXFR dependency graph will be shallow and the forward server will
+ be the primary master server.
+
+ 6.4. The forwarder will not respond to its requestor until it
+ receives a response from its forward server. UPDATE transactions
+ involving forwarders are therefore time synchronized with respect to
+ the original requestor and the primary master server.
+
+ 6.5. When there are multiple possible sources of AXFR data and
+ therefore multiple possible forward servers, a forwarder will use the
+ same fallback strategy with respect to connectivity or timeout errors
+ that it would use when performing an AXFR. This is implementation
+ dependent.
+
+ 6.6. When a forwarder receives a response from a forward server, it
+ copies this response into a new response message, assigns its
+ requestor's ID to that message, and sends the response back to the
+ requestor.
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 20]
+
+RFC 2136 DNS Update April 1997
+
+
+7 - Design, Implementation, Operation, and Protocol Notes
+
+ Some of the principles which guided the design of this UPDATE
+ specification are as follows. Note that these are not part of the
+ formal specification and any disagreement between this section and
+ any other section of this document should be resolved in favour of
+ the other section.
+
+ 7.1. Using metavalues for CLASS is possible only because all RRs in
+ the packet are assumed to be in the same zone, and CLASS is an
+ attribute of a zone rather than of an RRset. (It is for this reason
+ that the Zone Section is not optional.)
+
+ 7.2. Since there are no data-present or data-absent errors possible
+ from processing the Update Section, any necessary data-present and
+ data- absent dependencies should be specified in the Prerequisite
+ Section.
+
+ 7.3. The Additional Data Section can be used to supply a server with
+ out of zone glue that will be needed in referrals. For example, if
+ adding a new NS RR to HOME.VIX.COM specifying a nameserver called
+ NS.AU.OZ, the A RR for NS.AU.OZ can be included in the Additional
+ Data Section. Servers can use this information or ignore it, at the
+ discretion of the implementor. We discourage caching this
+ information for use in subsequent DNS responses.
+
+ 7.4. The Additional Data Section might be used if some of the RRs
+ later needed for Secure DNS Update are not actually zone updates, but
+ rather ancillary keys or signatures not intended to be stored in the
+ zone (as an update would be), yet necessary for validating the update
+ operation.
+
+ 7.5. It is expected that in the absence of Secure DNS Update, a
+ server will only accept updates if they come from a source address
+ that has been statically configured in the server's description of a
+ primary master zone. DHCP servers would be likely candidates for
+ inclusion in this statically configured list.
+
+ 7.6. It is not possible to create a zone using this protocol, since
+ there is no provision for a slave server to be told who its master
+ servers are. It is expected that this protocol will be extended in
+ the future to cover this case. Therefore, at this time, the addition
+ of SOA RRs is unsupported. For similar reasons, deletion of SOA RRs
+ is also unsupported.
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 21]
+
+RFC 2136 DNS Update April 1997
+
+
+ 7.7. The prerequisite for specifying that a name own at least one RR
+ differs semantically from QUERY, in that QUERY would return
+ <NOERROR,ANCOUNT=0> rather than NXDOMAIN if queried for an RRset at
+ this name, while UPDATE's prerequisite condition [Section 2.4.4]
+ would NOT be satisfied.
+
+ 7.8. It is possible for a UDP response to be lost in transit and for
+ a request to be retried due to a timeout condition. In this case an
+ UPDATE that was successful the first time it was received by the
+ primary master might ultimately appear to have failed when the
+ response to a duplicate request is finally received by the requestor.
+ (This is because the original prerequisites may no longer be
+ satisfied after the update has been applied.) For this reason,
+ requestors who require an accurate response code must use TCP.
+
+ 7.9. Because a requestor who requires an accurate response code will
+ initiate their UPDATE transaction using TCP, a forwarder who receives
+ a request via TCP must forward it using TCP.
+
+ 7.10. Deferral of SOA SERIAL autoincrements is made possible so that
+ serial numbers can be conserved and wraparound at 2**32 can be made
+ an infrequent occurance. Visible (to DNS clients) SOA SERIALs need
+ to differ if the zone differs. Note that the Authority Section SOA
+ in a QUERY response is a form of visibility, for the purposes of this
+ prerequisite.
+
+ 7.11. A zone's SOA SERIAL should never be set to zero (0) due to
+ interoperability problems with some older but widely installed
+ implementations of DNS. When incrementing an SOA SERIAL, if the
+ result of the increment is zero (0) (as will be true when wrapping
+ around 2**32), it is necessary to increment it again or set it to one
+ (1). See [RFC1982] for more detail on this subject.
+
+ 7.12. Due to the TTL minimalization necessary when caching an RRset,
+ it is recommended that all TTLs in an RRset be set to the same value.
+ While the DNS Message Format permits variant TTLs to exist in the
+ same RRset, and this variance can exist inside a zone, such variance
+ will have counterintuitive results and its use is discouraged.
+
+ 7.13. Zone cut management presents some obscure corner cases to the
+ add and delete operations in the Update Section. It is possible to
+ delete an NS RR as long as it is not the last NS RR at the root of a
+ zone. If deleting all RRs from a name, SOA and NS RRs at the root of
+ a zone are unaffected. If deleting RRsets, it is not possible to
+ delete either SOA or NS RRsets at the top of a zone. An attempt to
+ add an SOA will be treated as a replace operation if an SOA already
+ exists, or as a no-op if the SOA would be new.
+
+
+
+
+Vixie, et. al. Standards Track [Page 22]
+
+RFC 2136 DNS Update April 1997
+
+
+ 7.14. No semantic checking is required in the primary master server
+ when adding new RRs. Therefore a requestor can cause CNAME or NS or
+ any other kind of RR to be added even if their target name does not
+ exist or does not have the proper RRsets to make the original RR
+ useful. Primary master servers that DO implement this kind of
+ checking should take great care to avoid out-of-zone dependencies
+ (whose veracity cannot be authoritatively checked) and should
+ implement all such checking during the prescan phase.
+
+ 7.15. Nonterminal or wildcard CNAMEs are not well specified by
+ [RFC1035] and their use will probably lead to unpredictable results.
+ Their use is discouraged.
+
+ 7.16. Empty nonterminals (nodes with children but no RRs of their
+ own) will cause <NOERROR,ANCOUNT=0> responses to be sent in response
+ to a query of any type for that name. There is no provision for
+ empty terminal nodes -- so if all RRs of a terminal node are deleted,
+ the name is no longer in use, and queries of any type for that name
+ will result in an NXDOMAIN response.
+
+ 7.17. In a deep AXFR dependency graph, it has not historically been
+ an error for slaves to depend mutually upon each other. This
+ configuration has been used to enable a zone to flow from the primary
+ master to all slaves even though not all slaves have continuous
+ connectivity to the primary master. UPDATE's use of the AXFR
+ dependency graph for forwarding prohibits this kind of dependency
+ loop, since UPDATE forwarding has no loop detection analagous to the
+ SOA SERIAL pretest used by AXFR.
+
+ 7.18. Previously existing names which are occluded by a new zone cut
+ are still considered part of the parent zone, for the purposes of
+ zone transfers, even though queries for such names will be referred
+ to the new subzone's servers. If a zone cut is removed, all parent
+ zone names that were occluded by it will again become visible to
+ queries. (This is a clarification of [RFC1034].)
+
+ 7.19. If a server is authoritative for both a zone and its child,
+ then queries for names at the zone cut between them will be answered
+ authoritatively using only data from the child zone. (This is a
+ clarification of [RFC1034].)
+
+
+
+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 23]
+
+RFC 2136 DNS Update April 1997
+
+
+ 7.20. Update ordering using the SOA RR is problematic since there is
+ no way to know which of a zone's NS RRs represents the primary
+ master, and the zone slaves can be out of date if their SOA.REFRESH
+ timers have not elapsed since the last time the zone was changed on
+ the primary master. We recommend that a zone needing ordered updates
+ use only servers which implement NOTIFY (see [RFC1996]) and IXFR (see
+ [RFC1995]), and that a client receiving a prerequisite error while
+ attempting an ordered update simply retry after a random delay period
+ to allow the zone to settle.
+
+8 - Security Considerations
+
+ 8.1. In the absence of [RFC2137] or equivilent technology, the
+ protocol described by this document makes it possible for anyone who
+ can reach an authoritative name server to alter the contents of any
+ zones on that server. This is a serious increase in vulnerability
+ from the current technology. Therefore it is very strongly
+ recommended that the protocols described in this document not be used
+ without [RFC2137] or other equivalently strong security measures,
+ e.g. IPsec.
+
+ 8.2. A denial of service attack can be launched by flooding an update
+ forwarder with TCP sessions containing updates that the primary
+ master server will ultimately refuse due to permission problems.
+ This arises due to the requirement that an update forwarder receiving
+ a request via TCP use a synchronous TCP session for its forwarding
+ operation. The connection management mechanisms of [RFC1035 4.2.2]
+ are sufficient to prevent large scale damage from such an attack, but
+ not to prevent some queries from going unanswered during the attack.
+
+Acknowledgements
+
+ We would like to thank the IETF DNSIND working group for their input
+ and assistance, in particular, Rob Austein, Randy Bush, Donald
+ Eastlake, Masataka Ohta, Mark Andrews, and Robert Elz. Special
+ thanks to Bill Simpson, Ken Wallich and Bob Halley for reviewing this
+ document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 24]
+
+RFC 2136 DNS Update April 1997
+
+
+References
+
+ [RFC1035]
+ Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, USC/Information Sciences
+ Institute, November 1987.
+
+ [RFC1982]
+ Elz, R., "Serial Number Arithmetic", RFC 1982, University of
+ Melbourne, August 1996.
+
+ [RFC1995]
+ Ohta, M., "Incremental Zone Transfer", RFC 1995, Tokyo Institute
+ of Technology, August 1996.
+
+ [RFC1996]
+ Vixie, P., "A Mechanism for Prompt Notification of Zone Changes",
+ RFC 1996, Internet Software Consortium, August 1996.
+
+ [RFC2065]
+ Eastlake, D., and C. Kaufman, "Domain Name System Protocol
+ Security Extensions", RFC 2065, January 1997.
+
+ [RFC2137]
+ Eastlake, D., "Secure Domain Name System Dynamic Update", RFC
+ 2137, April 1997.
+
+Authors' Addresses
+
+ Yakov Rekhter
+ Cisco Systems
+ 170 West Tasman Drive
+ San Jose, CA 95134-1706
+
+ Phone: +1 914 528 0090
+ EMail: yakov@cisco.com
+
+
+ Susan Thomson
+ Bellcore
+ 445 South Street
+ Morristown, NJ 07960
+
+ Phone: +1 201 829 4514
+ EMail: set@thumper.bellcore.com
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 25]
+
+RFC 2136 DNS Update April 1997
+
+
+ Jim Bound
+ Digital Equipment Corp.
+ 110 Spitbrook Rd ZK3-3/U14
+ Nashua, NH 03062-2698
+
+ Phone: +1 603 881 0400
+ EMail: bound@zk3.dec.com
+
+
+ Paul Vixie
+ Internet Software Consortium
+ Star Route Box 159A
+ Woodside, CA 94062
+
+ Phone: +1 415 747 0204
+ EMail: paul@vix.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie, et. al. Standards Track [Page 26]
+
+
diff --git a/doc/rfc/rfc2137.txt b/doc/rfc/rfc2137.txt
new file mode 100644
index 0000000..ceb3613
--- /dev/null
+++ b/doc/rfc/rfc2137.txt
@@ -0,0 +1,619 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake 3rd
+Request for Comments: 2137 CyberCash, Inc.
+Updates: 1035 April 1997
+Category: Standards Track
+
+
+ Secure Domain Name System Dynamic Update
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Abstract
+
+ Domain Name System (DNS) protocol extensions have been defined to
+ authenticate the data in DNS and provide key distribution services
+ [RFC2065]. DNS Dynamic Update operations have also been defined
+ [RFC2136], but without a detailed description of security for the
+ update operation. This memo describes how to use DNSSEC digital
+ signatures covering requests and data to secure updates and restrict
+ updates to those authorized to perform them as indicated by the
+ updater's possession of cryptographic keys.
+
+Acknowledgements
+
+ The contributions of the following persons (who are listed in
+ alphabetic order) to this memo are gratefully acknowledged:
+
+ Olafur Gudmundsson (ogud@tis.com>
+ Charlie Kaufman <Charlie_Kaufman@iris.com>
+ Stuart Kwan <skwan@microsoft.com>
+ Edward Lewis <lewis@tis.com>
+
+Table of Contents
+
+ 1. Introduction............................................2
+ 1.1 Overview of DNS Dynamic Update.........................2
+ 1.2 Overview of DNS Security...............................2
+ 2. Two Basic Modes.........................................3
+ 3. Keys....................................................5
+ 3.1 Update Keys............................................6
+ 3.1.1 Update Key Name Scope................................6
+ 3.1.2 Update Key Class Scope...............................6
+ 3.1.3 Update Key Signatory Field...........................6
+
+
+
+Eastlake Standards Track [Page 1]
+
+RFC 2137 SDNSDU April 1997
+
+
+ 3.2 Zone Keys and Update Modes.............................8
+ 3.3 Wildcard Key Punch Through.............................9
+ 4. Update Signatures.......................................9
+ 4.1 Update Request Signatures..............................9
+ 4.2 Update Data Signatures................................10
+ 5. Security Considerations................................10
+ References................................................10
+ Author's Address..........................................11
+
+1. Introduction
+
+ Dynamic update operations have been defined for the Domain Name
+ System (DNS) in RFC 2136, but without a detailed description of
+ security for those updates. Means of securing the DNS and using it
+ for key distribution have been defined in RFC 2065.
+
+ This memo proposes techniques based on the defined DNS security
+ mechanisms to authenticate DNS updates.
+
+ Familiarity with the DNS system [RFC 1034, 1035] is assumed.
+ Familiarity with the DNS security and dynamic update proposals will
+ be helpful.
+
+1.1 Overview of DNS Dynamic Update
+
+ DNS dynamic update defines a new DNS opcode, new DNS request and
+ response structure if that opcode is used, and new error codes. An
+ update can specify complex combinations of deletion and insertion
+ (with or without pre-existence testing) of resource records (RRs)
+ with one or more owner names; however, all testing and changes for
+ any particular DNS update request are restricted to a single zone.
+ Updates occur at the primary server for a zone.
+
+ The primary server for a secure dynamic zone must increment the zone
+ SOA serial number when an update occurs or the next time the SOA is
+ retrieved if one or more updates have occurred since the previous SOA
+ retrieval and the updates themselves did not update the SOA.
+
+1.2 Overview of DNS Security
+
+ DNS security authenticates data in the DNS by also storing digital
+ signatures in the DNS as SIG resource records (RRs). A SIG RR
+ provides a digital signature on the set of all RRs with the same
+ owner name and class as the SIG and whose type is the type covered by
+ the SIG. The SIG RR cryptographically binds the covered RR set to
+ the signer, time signed, signature expiration date, etc. There are
+ one or more keys associated with every secure zone and all data in
+ the secure zone is signed either by a zone key or by a dynamic update
+
+
+
+Eastlake Standards Track [Page 2]
+
+RFC 2137 SDNSDU April 1997
+
+
+ key tracing its authority to a zone key.
+
+ DNS security also defines transaction SIGs and request SIGs.
+ Transaction SIGs appear at the end of a response. Transaction SIGs
+ authenticate the response and bind it to the corresponding request
+ with the key of the host where the responding DNS server is. Request
+ SIGs appear at the end of a request and authenticate the request with
+ the key of the submitting entity.
+
+ Request SIGs are the primary means of authenticating update requests.
+
+ DNS security also permits the storage of public keys in the DNS via
+ KEY RRs. These KEY RRs are also, of course, authenticated by SIG
+ RRs. KEY RRs for zones are stored in their superzone and subzone
+ servers, if any, so that the secure DNS tree of zones can be
+ traversed by a security aware resolver.
+
+2. Two Basic Modes
+
+ A dynamic secure zone is any secure DNS zone containing one or more
+ KEY RRs that can authorize dynamic updates, i.e., entity or user KEY
+ RRs with the signatory field non-zero, and whose zone KEY RR
+ signatory field indicates that updates are implemented. There are two
+ basic modes of dynamic secure zone which relate to the update
+ strategy, mode A and mode B. A summary comparison table is given
+ below and then each mode is described.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 3]
+
+RFC 2137 SDNSDU April 1997
+
+
+ SUMMARY OF DYNAMIC SECURE ZONE MODES
+
+ CRITERIA: | MODE A | MODE B
+ =========================+====================+===================
+ Definition: | Zone Key Off line | Zone Key On line
+ =========================+====================+===================
+ Server Workload | Low | High
+ -------------------------+--------------------+-------------------
+ Static Data Security | Very High | Medium-High
+ -------------------------+--------------------+-------------------
+ Dynamic Data Security | Medium | Medium-High
+ -------------------------+--------------------+-------------------
+ Key Restrictions | Fine grain | Coarse grain
+ -------------------------+--------------------+-------------------
+ Dynamic Data Temporality | Transient | Permanent
+ -------------------------+--------------------+-------------------
+ Dynamic Key Rollover | No | Yes
+ -------------------------+--------------------+-------------------
+
+ For mode A, the zone owner key and static zone master file are always
+ kept off-line for maximum security of the static zone contents.
+
+ As a consequence, any dynamicly added or changed RRs are signed in
+ the secure zone by their authorizing dynamic update key and they are
+ backed up, along with this SIG RR, in a separate online dynamic
+ master file. In this type of zone, server computation is minimized
+ since the server need only check signatures on the update data and
+ request, which have already been signed by the updater, generally a
+ much faster operation than signing data. However, the AXFR SIG and
+ NXT RRs which covers the zone under the zone key will not cover
+ dynamically added data. Thus, for type A dynamic secure zones, zone
+ transfer security is not automatically provided for dynamically added
+ RRs, where they could be omitted, and authentication is not provided
+ for the server denial of the existence of a dynamically added type.
+ Because the dynamicly added RRs retain their update KEY signed SIG,
+ finer grained control of updates can be implemented via bits in the
+ KEY RR signatory field. Because dynamic data is only stored in the
+ online dynamic master file and only authenticated by dynamic keys
+ which expire, updates are transient in nature. Key rollover for an
+ entity that can authorize dynamic updates is more cumbersome since
+ the authority of their key must be traceable to a zone key and so, in
+ general, they must securely communicate a new key to the zone
+ authority for manual transfer to the off line static master file.
+ NOTE: for this mode the zone SOA must be signed by a dynamic update
+ key and that private key must be kept on line so that the SOA can be
+ changed for updates.
+
+
+
+
+
+Eastlake Standards Track [Page 4]
+
+RFC 2137 SDNSDU April 1997
+
+
+ For mode B, the zone owner key and master file are kept on-line at
+ the zone primary server. When authenticated updates succeed, SIGs
+ under the zone key for the resulting data (including the possible NXT
+ type bit map changes) are calculated and these SIG (and possible NXT)
+ changes are entered into the zone and the unified on-line master
+ file. (The zone transfer AXFR SIG may be recalculated for each
+ update or on demand when a zone transfer is requested and it is out
+ of date.)
+
+ As a consequence, this mode requires considerably more computational
+ effort on the part of the server as the public/private keys are
+ generally arranged so that signing (calculating a SIG) is more effort
+ than verifying a signature. The security of static data in the zone
+ is decreased because the ultimate state of the static data being
+ served and the ultimate zone authority private key are all on-line on
+ the net. This means that if the primary server is subverted, false
+ data could be authenticated to secondaries and other
+ servers/resolvers. On the other hand, this mode of operation means
+ that data added dynamically is more secure than in mode A. Dynamic
+ data will be covered by the AXFR SIG and thus always protected during
+ zone transfers and will be included in NXT RRs so that it can be
+ falsely denied by a server only to the same extent that static data
+ can (i.e., if it is within a wild card scope). Because the zone key
+ is used to sign all the zone data, the information as to who
+ originated the current state of dynamic RR sets is lost, making
+ unavailable the effects of some of the update control bits in the KEY
+ RR signatory field. In addition, the incorporation of the updates
+ into the primary master file and their authentication by the zone key
+ makes then permanent in nature. Maintaining the zone key on-line
+ also means that dynamic update keys which are signed by the zone key
+ can be dynamically updated since the zone key is available to
+ dynamically sign new values.
+
+ NOTE: The Mode A / Mode B distinction only effects the validation
+ and performance of update requests. It has no effect on retrievals.
+ One reasonable operational scheme may be to keep a mostly static main
+ zone operating in Mode A and have one or more dynamic subzones
+ operating in Mode B.
+
+3. Keys
+
+ Dynamic update requests depend on update keys as described in section
+ 3.1 below. In addition, the zone secure dynamic update mode and
+ availability of some options is indicated in the zone key. Finally,
+ a special rule is used in searching for KEYs to validate updates as
+ described in section 3.3.
+
+
+
+
+
+Eastlake Standards Track [Page 5]
+
+RFC 2137 SDNSDU April 1997
+
+
+3.1 Update Keys
+
+ All update requests to a secure zone must include signatures by one
+ or more key(s) that together can authorize that update. In order for
+ the Domain Name System (DNS) server receiving the request to confirm
+ this, the key or keys must be available to and authenticated by that
+ server as a specially flagged KEY Resource Record.
+
+ The scope of authority of such keys is indicated by their KEY RR
+ owner name, class, and signatory field flags as described below. In
+ addition, such KEY RRs must be entity or user keys and not have the
+ authentication use prohibited bit on. All parts of the actual update
+ must be within the scope of at least one of the keys used for a
+ request SIG on the update request as described in section 4.
+
+3.1.1 Update Key Name Scope
+
+ The owner name of any update authorizing KEY RR must (1) be the same
+ as the owner name of any RRs being added or deleted or (2) a wildcard
+ name including within its extended scope (see section 3.3) the name
+ of any RRs being added or deleted and those RRs must be in the same
+ zone.
+
+3.1.2 Update Key Class Scope
+
+ The class of any update authorizing KEY RR must be the same as the
+ class of any RR's being added or deleted.
+
+3.1.3 Update Key Signatory Field
+
+ The four bit "signatory field" (see RFC 2065) of any update
+ authorizing KEY RR must be non-zero. The bits have the meanings
+ described below for non-zone keys (see section 3.2 for zone type
+ keys).
+
+ UPDATE KEY RR SIGNATORY FIELD BITS
+
+ 0 1 2 3
+ +-----------+-----------+-----------+-----------+
+ | zone | strong | unique | general |
+ +-----------+-----------+-----------+-----------+
+
+ Bit 0, zone control - If nonzero, this key is authorized to attach,
+ detach, and move zones by creating and deleting NS, glue A, and
+ zone KEY RR(s). If zero, the key can not authorize any update
+ that would effect such RRs. This bit is meaningful for both
+ type A and type B dynamic secure zones.
+
+
+
+
+Eastlake Standards Track [Page 6]
+
+RFC 2137 SDNSDU April 1997
+
+
+ NOTE: do not confuse the "zone" signatory field bit with the
+ "zone" key type bit.
+
+ Bit 1, strong update - If nonzero, this key is authorized to add and
+ delete RRs even if there are other RRs with the same owner name
+ and class that are authenticated by a SIG signed with a
+ different dynamic update KEY. If zero, the key can only
+ authorize updates where any existing RRs of the same owner and
+ class are authenticated by a SIG using the same key. This bit
+ is meaningful only for type A dynamic zones and is ignored in
+ type B dynamic zones.
+
+ Keeping this bit zero on multiple KEY RRs with the same or
+ nested wild card owner names permits multiple entities to exist
+ that can create and delete names but can not effect RRs with
+ different owner names from any they created. In effect, this
+ creates two levels of dynamic update key, strong and weak, where
+ weak keys are limited in interfering with each other but a
+ strong key can interfere with any weak keys or other strong
+ keys.
+
+ Bit 2, unique name update - If nonzero, this key is authorized to add
+ and update RRs for only a single owner name. If there already
+ exist RRs with one or more names signed by this key, they may be
+ updated but no new name created until the number of existing
+ names is reduced to zero. This bit is meaningful only for mode
+ A dynamic zones and is ignored in mode B dynamic zones. This bit
+ is meaningful only if the owner name is a wildcard. (Any
+ dynamic update KEY with a non-wildcard name is, in effect, a
+ unique name update key.)
+
+ This bit can be used to restrict a KEY from flooding a zone with
+ new names. In conjunction with a local administratively imposed
+ limit on the number of dynamic RRs with a particular name, it
+ can completely restrict a KEY from flooding a zone with RRs.
+
+ Bit 3, general update - The general update signatory field bit has no
+ special meaning. If the other three bits are all zero, it must
+ be one so that the field is non-zero to designate that the key
+ is an update key. The meaning of all values of the signatory
+ field with the general bit and one or more other signatory field
+ bits on is reserved.
+
+ All the signatory bit update authorizations described above only
+ apply if the update is within the name and class scope as per
+ sections 3.1.1 and 3.1.2.
+
+
+
+
+
+Eastlake Standards Track [Page 7]
+
+RFC 2137 SDNSDU April 1997
+
+
+3.2 Zone Keys and Update Modes
+
+ Zone type keys are automatically authorized to sign anything in their
+ zone, of course, regardless of the value of their signatory field.
+ For zone keys, the signatory field bits have different means than
+ they they do for update keys, as shown below. The signatory field
+ MUST be zero if dynamic update is not supported for a zone and MUST
+ be non-zero if it is.
+
+ ZONE KEY RR SIGNATORY FIELD BITS
+
+ 0 1 2 3
+ +-----------+-----------+-----------+-----------+
+ | mode | strong | unique | general |
+ +-----------+-----------+-----------+-----------+
+
+ Bit 0, mode - This bit indicates the update mode for this zone. Zero
+ indicates mode A while a one indicates mode B.
+
+ Bit 1, strong update - If nonzero, this indicates that the "strong"
+ key feature described in section 3.1.3 above is implemented and
+ enabled for this secure zone. If zero, the feature is not
+ available. Has no effect if the zone is a mode B secure update
+ zone.
+
+ Bit 2, unique name update - If nonzero, this indicates that the
+ "unique name" feature described in section 3.1.3 above is
+ implemented and enabled for this secure zone. If zero, this
+ feature is not available. Has no effect if the zone is a mode B
+ secure update zone.
+
+ Bit 3, general - This bit has no special meeting. If dynamic update
+ for a zone is supported and the other bits in the zone key
+ signatory field are zero, it must be a one. The meaning of zone
+ keys where the signatory field has the general bit and one or
+ more other bits on is reserved.
+
+ If there are multiple dynamic update KEY RRs for a zone and zone
+ policy is in transition, they might have different non-zero signatory
+ fields. In that case, strong and unique name restrictions must be
+ enforced as long as there is a non-expired zone key being advertised
+ that indicates mode A with the strong or unique name bit on
+ respectively. Mode B updates MUST be supported as long as there is a
+ non-expired zone key that indicates mode B. Mode A updates may be
+ treated as mode B updates at server option if non-expired zone keys
+ indicate that both are supported.
+
+
+
+
+
+Eastlake Standards Track [Page 8]
+
+RFC 2137 SDNSDU April 1997
+
+
+ A server that will be executing update operations on a zone, that is,
+ the primary master server, MUST not advertize a zone key that will
+ attract requests for a mode or features that it can not support.
+
+3.3 Wildcard Key Punch Through
+
+ Just as a zone key is valid throughout the entire zone, update keys
+ with wildcard names are valid throughout their extended scope, within
+ the zone. That is, they remain valid for any name that would match
+ them, even existing specific names within their apparent scope.
+
+ If this were not so, then whenever a name within a wildcard scope was
+ created by dynamic update, it would be necessary to first create a
+ copy of the KEY RR with this name, because otherwise the existence of
+ the more specific name would hide the authorizing KEY RR and would
+ make later updates impossible. An updater could create such a KEY RR
+ but could not zone sign it with their authorizing signer. They would
+ have to sign it with the same key using the wildcard name as signer.
+ Thus in creating, for example, one hundred type A RRs authorized by a
+ *.1.1.1.in-addr.arpa. KEY RR, without key punch through 100 As, 100
+ KEYs, and 200 SIGs would have to be created as opposed to merely 100
+ As and 100 SIGs with key punch through.
+
+4. Update Signatures
+
+ Two kinds of signatures can appear in updates. Request signatures,
+ which are always required, cover the entire request and authenticate
+ the DNS header, including opcode, counts, etc., as well as the data.
+ Data signatures, on the other hand, appear only among the RRs to be
+ added and are only required for mode A operation. These two types of
+ signatures are described further below.
+
+4.1 Update Request Signatures
+
+ An update can effect multiple owner names in a zone. It may be that
+ these different names are covered by different dynamic update keys.
+ For every owner name effected, the updater must know a private key
+ valid for that name (and the zone's class) and must prove this by
+ appending request SIG RRs under each such key.
+
+ As specified in RFC 2065, a request signature is a SIG RR occurring
+ at the end of a request with a type covered field of zero. For an
+ update, request signatures occur in the Additional information
+ section. Each request SIG signs the entire request, including DNS
+ header, but excluding any other request SIG(s) and with the ARCOUNT
+ in the DNS header set to what it wold be without the request SIGs.
+
+
+
+
+
+Eastlake Standards Track [Page 9]
+
+RFC 2137 SDNSDU April 1997
+
+
+4.2 Update Data Signatures
+
+ Mode A dynamic secure zones require that the update requester provide
+ SIG RRs that will authenticate the after update state of all RR sets
+ that are changed by the update and are non-empty after the update.
+ These SIG RRs appear in the request as RRs to be added and the
+ request must delete any previous data SIG RRs that are invalidated by
+ the request.
+
+ In Mode B dynamic secure zones, all zone data is authenticated by
+ zone key SIG RRs. In this case, data signatures need not be included
+ with the update. A resolver can determine which mode an updatable
+ secure zone is using by examining the signatory field bits of the
+ zone KEY RR (see section 3.2).
+
+5. Security Considerations
+
+ Any zone permitting dynamic updates is inherently less secure than a
+ static secure zone maintained off line as recommended in RFC 2065. If
+ nothing else, secure dynamic update requires on line change to and
+ re-signing of the zone SOA resource record (RR) to increase the SOA
+ serial number. This means that compromise of the primary server host
+ could lead to arbitrary serial number changes.
+
+ Isolation of dynamic RRs to separate zones from those holding most
+ static RRs can limit the damage that could occur from breach of a
+ dynamic zone's security.
+
+References
+
+ [RFC2065] Eastlake, D., and C. Kaufman, "Domain Name System Security
+ Extensions", RFC 2065, CyberCash, Iris, January 1997.
+
+ [RFC2136] Vixie, P., Editor, Thomson, T., Rekhter, Y., and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)", RFC 2136,
+ April 1997.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specifications", STD 13, RFC 1035, November 1987.
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 10]
+
+RFC 2137 SDNSDU April 1997
+
+
+Author's Address
+
+ Donald E. Eastlake, 3rd
+ CyberCash, Inc.
+ 318 Acton Street
+ Carlisle, MA 01741 USA
+
+ Phone: +1 508-287-4877
+ +1 508-371-7148 (fax)
+ +1 703-620-4200 (main office, Reston, Virginia, USA)
+ EMail: dee@cybercash.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 11]
+
diff --git a/doc/rfc/rfc2163.txt b/doc/rfc/rfc2163.txt
new file mode 100644
index 0000000..00fcee7
--- /dev/null
+++ b/doc/rfc/rfc2163.txt
@@ -0,0 +1,1459 @@
+
+
+
+
+
+
+Network Working Group C. Allocchio
+Request for Comments: 2163 GARR-Italy
+Obsoletes: 1664 January 1998
+Category: Standards Track
+
+
+ Using the Internet DNS to Distribute
+ MIXER Conformant Global Address Mapping (MCGAM)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+Abstract
+
+ This memo is the complete technical specification to store in the
+ Internet Domain Name System (DNS) the mapping information (MCGAM)
+ needed by MIXER conformant e-mail gateways and other tools to map
+ RFC822 domain names into X.400 O/R names and vice versa. Mapping
+ information can be managed in a distributed rather than a centralised
+ way. Organizations can publish their MIXER mapping or preferred
+ gateway routing information using just local resources (their local
+ DNS server), avoiding the need for a strong coordination with any
+ centralised organization. MIXER conformant gateways and tools located
+ on Internet hosts can retrieve the mapping information querying the
+ DNS instead of having fixed tables which need to be centrally updated
+ and distributed.
+
+ This memo obsoletes RFC1664. It includes the changes introduced by
+ MIXER specification with respect to RFC1327: the new 'gate1' (O/R
+ addresses to domain) table is fully supported. Full backward
+ compatibility with RFC1664 specification is mantained, too.
+
+ RFC1664 was a joint effort of IETF X400 operation working group
+ (x400ops) and TERENA (formely named "RARE") Mail and Messaging
+ working group (WG-MSG). This update was performed by the IETF MIXER
+ working group.
+
+
+
+
+
+
+Allocchio Standards Track [Page 1]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+1. Introduction
+
+ The connectivity between the Internet SMTP mail and other mail
+ services, including the Internet X.400 mail and the commercial X.400
+ service providers, is assured by the Mail eXchanger (MX) record
+ information distributed via the Internet Domain Name System (DNS). A
+ number of documents then specify in details how to convert or encode
+ addresses from/to RFC822 style to the other mail system syntax.
+ However, only conversion methods provide, via some algorithm or a set
+ of mapping rules, a smooth translation, resulting in addresses
+ indistinguishable from the native ones in both RFC822 and foreign
+ world.
+
+ MIXER describes a set of mappings (MIXER Conformant Global Address
+ Mapping - MCGAM) which will enable interworking between systems
+ operating the CCITT X.400 (1984/88/92) Recommendations and systems
+ using using the RFC822 mail protocol, or protocols derived from
+ RFC822. That document addresses conversion of services, addresses,
+ message envelopes, and message bodies between the two mail systems.
+ This document is concerned with one aspect of MIXER: the mechanism
+ for mapping between X.400 O/R addresses and RFC822 domain names. As
+ described in Appendix F of MIXER, implementation of the mappings
+ requires a database which maps between X.400 O/R addresses and domain
+ names; in RFC1327 this database was statically defined.
+
+ The original approach in RFC1327 required many efforts to maintain
+ the correct mapping: all the gateways needed to get coherent tables
+ to apply the same mappings, the conversion tables had to be
+ distributed among all the operational gateways, and also every update
+ needed to be distributed.
+
+ The concept of mapping rules distribution and use has been revised in
+ the new MIXER specification, introducing the concept of MIXER
+ Conformant Global Address Mapping (MCGAM). A MCGAM does not need to
+ be globally installed by any MIXER conformant gateway in the world
+ any more. However MIXER requires now efficient methods to publish its
+ MCGAM.
+
+ Static tables are one of the possible methods to publish MCGAM.
+ However this static mechanism requires quite a long time to be spent
+ modifying and distributing the information, putting heavy constraints
+ on the time schedule of every update. In fact it does not appear
+ efficient compared to the Internet Domain Name Service (DNS). More
+ over it does not look feasible to distribute the database to a large
+ number of other useful applications, like local address converters,
+ e-mail User Agents or any other tool requiring the mapping rules to
+ produce correct results.
+
+
+
+
+Allocchio Standards Track [Page 2]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ Two much more efficient methods are proposed by MIXER for publication
+ of MCGAM: the Internet DNS and X.500. This memo is the complete
+ technical specification for publishing MCGAM via Internet DNS.
+
+ A first proposal to use the Internet DNS to store, retrieve and
+ maintain those mappings was introduced by two of the authors of
+ RFC1664 (B. Cole and R. Hagens) adopting two new DNS resource record
+ (RR) types: TO-X400 and TO-822. This proposal now adopts a more
+ complete strategy, and requires one new RR only. The distribution of
+ MCGAMs via DNS is in fact an important service for the whole Internet
+ community: it completes the information given by MX resource record
+ and it allows to produce clean addresses when messages are exchanged
+ among the Internet RFC822 world and the X.400 one (both Internet and
+ Public X.400 service providers).
+
+ A first experiment in using the DNS without expanding the current set
+ of RR and using available ones was deployed by some of the authors of
+ RFC1664 at the time of its development. The existing PTR resource
+ records were used to store the mapping rules, and a new DNS tree was
+ created under the ".it" top level domain. The result of the
+ experiment was positive, and a few test applications ran under this
+ provisional set up. This test was also very useful in order to define
+ a possible migration strategy during the deployment of the new DNS
+ containing the new RR. The Internet DNS nameservers wishing to
+ provide this mapping information need in fact to be modified to
+ support the new RR type, and in the real Internet, due to the large
+ number of different implementations, this takes some time.
+
+ The basic idea is to adopt a new DNS RR to store the mapping
+ information. The RFC822 to X.400 mapping rules (including the so
+ called 'gate2' rules) will be stored in the ordinary DNS tree, while
+ the definition of a new branch of the name space defined under each
+ national top level domain is envisaged in order to contain the X.400
+ to RFC822 mappings ('table1' and 'gate1'). A "two-way" mapping
+ resolution schema is thus fully implemented.
+
+ The creation of the new domain name space representing the X.400 O/R
+ names structure also provides the chance to use the DNS to distribute
+ dynamically other X.400 related information, thus solving other
+ efficiency problems currently affecting the X.400 MHS service.
+
+ In this paper we will adopt the MCGAM syntax, showing how it can be
+ stored into the Internet DNS.
+
+
+
+
+
+
+
+
+Allocchio Standards Track [Page 3]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+1.1 Definitions syntax
+
+ The definitions in this document is given in BNF-like syntax, using
+ the following conventions:
+
+ | means choice
+ \ is used for continuation of a definition over several lines
+ [] means optional
+ {} means repeated one or more times
+
+ The definitions, however, are detailed only until a certain level,
+ and below it self-explaining character text strings will be used.
+
+2. Motivation
+
+ Implementations of MIXER gateways require that a database store
+ address mapping information for X.400 and RFC822. This information
+ must be made available (published) to all MIXER gateways. In the
+ Internet community, the DNS has proven to be a practical mean for
+ providing a distributed name service. Advantages of using a DNS based
+ system over a table based approach for mapping between O/R addresses
+ and domain names are:
+
+ - It avoids fetching and storing of entire mapping tables by every
+ host that wishes to implement MIXER gateways and/or tools
+
+ - Modifications to the DNS based mapping information can be made
+ available in a more timely manner than with a table driven
+ approach.
+
+ - It allows full authority delegation, in agreement with the
+ Internet regionalization process.
+
+ - Table management is not necessarily required for DNS-based
+ MIXER gateways.
+
+ - One can determine the mappings in use by a remote gateway by
+ querying the DNS (remote debugging).
+
+ Also many other tools, like address converters and User Agents can
+ take advantage of the real-time availability of MIXER tables,
+ allowing a much easier maintenance of the information.
+
+3. The domain space for X.400 O/R name addresses
+
+ Usual domain names (the ones normally used as the global part of an
+ RFC822 e-mail address) and their associated information, i.e., host
+ IP addresses, mail exchanger names, etc., are stored in the DNS as a
+
+
+
+Allocchio Standards Track [Page 4]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ distributed database under a number of top-level domains. Some top-
+ level domains are used for traditional categories or international
+ organisations (EDU, COM, NET, ORG, INT, MIL...). On the other hand
+ any country has its own two letter ISO country code as top-level
+ domain (FR, DE, GB, IT, RU, ...), including "US" for USA. The
+ special top-level/second-level couple IN-ADDR.ARPA is used to store
+ the IP address to domain name relationship. This memo defines in the
+ above structure the appropriate way to locate the X.400 O/R name
+ space, thus enabling to store in DNS the MIXER mappings (MCGAMs).
+
+ The MIXER mapping information is composed by four tables:
+
+ - 'table1' and 'gate1' gives the translation from X.400 to RFC822;
+ - 'table2' and 'gate2' tables map RFC822 into X.400.
+
+ Each mapping table is composed by mapping rules, and a single mapping
+ rule is composed by a keyword (the argument of the mapping function
+ derived from the address to be translated) and a translator (the
+ mapping function parameter):
+
+ keyword#translator#
+
+ the '#' sign is a delimiter enclosing the translator. An example:
+
+ foo.bar.us#PRMD$foo\.bar.ADMD$intx.C$us#
+
+ Local mappings are not intended for use outside their restricted
+ environment, thus they should not be included in DNS. If local
+ mappings are used, they should be stored using static local tables,
+ exactly as local static host tables can be used with DNS.
+
+ The keyword of a 'table2' and 'gate2' table entry is a valid RFC822
+ domain; thus the usual domain name space can be used without problems
+ to store these entries.
+ On the other hand, the keyword of a 'table1' and 'gate1' entry
+ belongs to the X.400 O/R name space. The X.400 O/R name space does
+ not usually fit into the usual domain name space, although there are
+ a number of similarities; a new name structure is thus needed to
+ represent it. This new name structure contains the X.400 mail
+ domains.
+
+ To ensure the correct functioning of the DNS system, the new X.400
+ name structure must be hooked to the existing domain name space in a
+ way which respects the existing name hierarchy.
+
+ A possible solution was to create another special branch, starting
+ from the root of the DNS tree, somehow similar to the in-addr.arpa
+ tree. This idea would have required to establish a central authority
+
+
+
+Allocchio Standards Track [Page 5]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ to coordinate at international level the management of each national
+ X.400 name tree, including the X.400 public service providers. This
+ coordination problem is a heavy burden if approached globally. More
+ over the X.400 name structure is very 'country oriented': thus while
+ it requires a coordination at national level, it does not have
+ concepts like the international root. In fact the X.400 international
+ service is based on a large number of bilateral agreements, and only
+ within some communities an international coordination service exists.
+
+ The X.400 two letter ISO country codes, however, are the same used
+ for the RFC822 country top-level domains and this gives us an
+ appropriate hook to insert the new branches. The proposal is, in
+ fact, to create under each national top level ISO country code a new
+ branch in the name space. This branch represents exactly the X.400
+ O/R name structure as defined in each single country, following the
+ ADMD, PRMD, O, OU hierarchy. A unique reserved label 'X42D' is placed
+ under each country top-level domain, and hence the national X.400
+ name space derives its own structure:
+
+ . (root)
+ |
+ +-----------------+-----------+--------+-----------------+...
+ | | | |
+ edu it us fr
+ | | | |
+ +---+---+... +-----+-----+... +-----+-----+... +--+---+...
+ | | | | | | | | | |
+ ... ... cnr X42D infn va ca X42D X42D inria
+ | | | |
+ +------------+------------+... ... ... +----+-------+...
+ | | | | |
+ ADMD-PtPostel ADMD-garr ADMD-Master400 ADMD-atlas ADMD-red
+ | | | |
+ +----------+----+... ... +-------+------+... ...
+ | | | |
+ PRMD-infn PRMD-STET PRMD-Telecom PRMD-Renault
+ | | | |
+ ... ... ... ...
+
+
+ The creation of the X.400 new name tree at national level solves the
+ problem of the international coordination. Actually the coordination
+ problem is just moved at national level, but it thus becomes easier
+ to solve. The coordination at national level between the X.400
+ communities and the Internet world is already a requirement for the
+ creation of the national static MIXER mapping tables; the use of the
+ Internet DNS gives further motivations for this coordination.
+
+
+
+
+Allocchio Standards Track [Page 6]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ The coordination at national level also fits in the new concept of
+ MCGAM pubblication. The DNS in fact allows a step by step authority
+ distribution, up to a final complete delegation: thus organizations
+ whishing to publish their MCGAM just need to receive delegation also
+ for their branch of the new X.400 name space. A further advantage of
+ the national based solution is to allow each country to set up its
+ own X.400 name structure in DNS and to deploy its own authority
+ delegation according to its local time scale and requirements, with
+ no loss of global service in the mean time. And last, placing the new
+ X.400 name tree and coordination process at national level fits into
+ the Internet regionalization and internationalisation process, as it
+ requires local bodies to take care of local coordination problems.
+
+ The DNS name space thus contains completely the information required
+ by an e-mail gateway or tool to perform the X.400-RFC822 mapping: a
+ simple query to the nearest nameserver provides it. Moreover there is
+ no more any need to store, maintain and distribute manually any
+ mapping table. The new X.400 name space can also contain further
+ information about the X.400 community, as DNS allows for it a
+ complete set of resource records, and thus it allows further
+ developments. This set of RRs in the new X.400 name space must be
+ considered 'reserved' and thus not used until further specifications.
+
+ The construction of the new domain space trees will follow the same
+ procedures used when organising at first the already existing DNS
+ space: at first the information will be stored in a quite centralised
+ way, and distribution of authority will be gradually achieved. A
+ separate document will describe the implementation phase and the
+ methods to assure a smooth introduction of the new service.
+
+4. The new DNS resource record for MIXER mapping rules: PX
+
+ The specification of the Internet DNS (RFC1035) provides a number of
+ specific resource records (RRs) to contain specific pieces of
+ information. In particular they contain the Mail eXchanger (MX) RR
+ and the host Address (A) records which are used by the Internet SMTP
+ mailers. As we will store the RFC822 to X.400 mapping information in
+ the already existing DNS name tree, we need to define a new DNS RR in
+ order to avoid any possible clash or misuse of already existing data
+ structures. The same new RR will also be used to store the mappings
+ from X.400 to RFC822. More over the mapping information, i.e., the
+ MCGAMs, has a specific format and syntax which require an appropriate
+ data structure and processing. A further advantage of defining a new
+ RR is the ability to include flexibility for some eventual future
+ development.
+
+
+
+
+
+
+Allocchio Standards Track [Page 7]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ The definition of the new 'PX' DNS resource record is:
+
+ class: IN (Internet)
+
+ name: PX (pointer to X.400/RFC822 mapping information)
+
+ value: 26
+
+ The PX RDATA format is:
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PREFERENCE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MAP822 /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / MAPX400 /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ where:
+
+ PREFERENCE A 16 bit integer which specifies the preference given to
+ this RR among others at the same owner. Lower values
+ are preferred;
+
+ MAP822 A <domain-name> element containing <rfc822-domain>, the
+ RFC822 part of the MCGAM;
+
+ MAPX400 A <domain-name> element containing the value of
+ <x400-in-domain-syntax> derived from the X.400 part of
+ the MCGAM (see sect. 4.2);
+
+ PX records cause no additional section processing. The PX RR format
+ is the usual one:
+
+ <name> [<class>] [<TTL>] <type> <RDATA>
+
+ When we store in DNS a 'table1' or a 'gate1' entry, then <name> will
+ be an X.400 mail domain name in DNS syntax (see sect. 4.2). When we
+ store a 'table2' or a 'gate2' table entry, <name> will be an RFC822
+ mail domain name, including both fully qualified DNS domains and mail
+ only domains (MX-only domains). All normal DNS conventions, like
+ default values, wildcards, abbreviations and message compression,
+ apply also for all the components of the PX RR. In particular <name>,
+ MAP822 and MAPX400, as <domain-name> elements, must have the final
+ "." (root) when they are fully qualified.
+
+
+
+
+Allocchio Standards Track [Page 8]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+4.1 Additional features of the PX resource record
+
+ The definition of the RDATA for the PX resource record, and the fact
+ that DNS allows a distinction between an exact value and a wildcard
+ match for the <name> parameter, represent an extension of the MIXER
+ specification for mapping rules. In fact, any MCGAM entry is an
+ implicit wildcard entry, i.e., the rule
+
+ net2.it#PRMD$net2.ADMD$p400.C$it#
+
+ covers any RFC822 domain ending with 'net2.it', unless more detailed
+ rules for some subdomain in 'net2.it' are present. Thus there is no
+ possibility to specify explicitly a MCGAM as an exact match only
+ rule. In DNS an entry like
+
+ *.net2.it. IN PX 10 net2.it. PRMD-net2.ADMD-p400.C-it.
+
+ specify the usual wildcard match as for MIXER tables. However an
+ entry like
+
+ ab.net2.it. IN PX 10 ab.net2.it. O-ab.PRMD-net2.ADMDb.C-it.
+
+ is valid only for an exact match of 'ab.net2.it' RFC822 domain.
+
+ Note also that in DNS syntax there is no '#' delimiter around MAP822
+ and MAPX400 fields: the syntax defined in sect. 4.2 in fact does not
+ allow the <blank> (ASCII decimal 32) character within these fields,
+ making unneeded the use of an explicit delimiter as required in the
+ MIXER original syntax.
+
+ Another extension to the MIXER specifications is the PREFERENCE value
+ defined as part of the PX RDATA section. This numeric value has
+ exactly the same meaning than the similar one used for the MX RR. It
+ is thus possible to specify more than one single mapping for a domain
+ (both from RFC822 to X.400 and vice versa), giving as the preference
+ order. In MIXER static tables, however, you cannot specify more than
+ one mapping per each RFC822 domain, and the same restriction apply
+ for any X.400 domain mapping to an RFC822 one.
+
+ More over, in the X.400 recommendations a note suggests than an
+ ADMD=<blank> should be reserved for some special cases. Various
+ national functional profile specifications for an X.400 MHS states
+ that if an X.400 PRMD is reachable via any of its national ADMDs,
+ independently of its actual single or multiple connectivity with
+ them, it should use ADMD=<blank> to advertise this fact. Again, if a
+ PRMD has no connections to any ADMD it should use ADMD=0 to notify
+ its status, etc. However, in most of the current real situations, the
+ ADMD service providers do not accept messages coming from their
+
+
+
+Allocchio Standards Track [Page 9]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ subscribers if they have a blank ADMD, forcing them to have their own
+ ADMD value. In such a situation there are problems in indicating
+ properly the actually working mappings for domains with multiple
+ connectivity. The PX RDATA 'PREFERENCE' extension was introduced to
+ take in consideration these problems.
+
+ However, as these extensions are not available with MIXER static
+ tables, it is strongly discouraged to use them when interworking with
+ any table based gateway or application. The extensions were in fact
+ introduced just to add more flexibility, like the PREFERENCE value,
+ or they were already implicit in the DNS mechanism, like the
+ wildcard specification. They should be used very carefully or just
+ considered 'reserved for future use'. In particular, for current use,
+ the PREFERENCE value in the PX record specification should be fixed
+ to a value of 50, and only wildcard specifications should be used
+ when specifying <name> values.
+
+4.2 The DNS syntax for an X.400 'domain'
+
+ The syntax definition of the MCGAM rules is defined in appendix F of
+ that document. However that syntax is not very human oriented and
+ contains a number of characters which have a special meaning in other
+ fields of the Internet DNS. Thus in order to avoid any possible
+ problem, especially due to some old DNS implementations still being
+ used in the Internet, we define a syntax for the X.400 part of any
+ MCGAM rules (and hence for any X.400 O/R name) which makes it
+ compatible with a <domain-name> element, i.e.,
+
+ <domain-name> ::= <subdomain> | " "
+ <subdomain> ::= <label> | <label> "." <subdomain>
+ <label> ::= <alphanum>|
+ <alphanum> {<alphanumhyphen>} <alphanum>
+ <alphanum> ::= "0".."9" | "A".."Z" | "a".."z"
+ <alphanumhyphen> ::= "0".."9" | "A".."Z" | "a".."z" | "-"
+
+ (see RFC1035, section 2.3.1, page 8). The legal character set for
+ <label> does not correspond to the IA5 Printablestring one used in
+ MIXER to define MCGAM rules. However a very simple "escape mechanism"
+ can be applied in order to bypass the problem. We can in fact simply
+ describe the X.400 part of a MCGAM rule format as:
+
+ <map-rule> ::= <map-elem> | <map-elem> { "." <map-elem> }
+ <map-elem> ::= <attr-label> "$" <attr-value>
+ <attr-label> ::= "C" | "ADMD" | "PRMD" | "O" | "OU"
+ <attr-value> ::= " " | "@" | IA5-Printablestring
+
+
+
+
+
+
+Allocchio Standards Track [Page 10]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ As you can notice <domain-name> and <map-rule> look similar, and also
+ <label> and <map-elem> look the same. If we define the correct method
+ to transform a <map-elem> into a <label> and vice versa the problem
+ to write a MCGAM rule in <domain-name> syntax is solved.
+
+ The RFC822 domain part of any MCGAM rule is of course already in
+ <domain-name> syntax, and thus remains unchanged.
+
+ In particular, in a 'table1' or 'gate1' mapping rule the 'keyword'
+ value must be converted into <x400-in-domain-syntax> (X.400 mail DNS
+ mail domain), while the 'translator' value is already a valid RFC822
+ domain. Vice versa in a 'table2' or 'gate2' mapping rule, the
+ 'translator' must be converted into <x400-in-domain-syntax>, while
+ the 'keyword' is already a valid RFC822 domain.
+
+4.2.1 IA5-Printablestring to <alphanumhyphen> mappings
+
+ The problem of unmatching IA5-Printablestring and <label> character
+ set definition is solved by a simple character mapping rule: whenever
+ an IA5 character does not belong to <alphanumhyphen>, then it is
+ mapped using its 3 digit decimal ASCII code, enclosed in hyphens. A
+ small set of special rules is also defined for the most frequent
+ cases. Moreover some frequent characters combinations used in MIXER
+ rules are also mapped as special cases.
+
+ Let's then define the following simple rules:
+
+ MCGAM rule DNS store translation conditions
+ -----------------------------------------------------------------
+ <attr-label>$@ <attr-label> missing attribute
+ <attr-label>$<blank> <attr-label>"b" blank attribute
+ <attr-label>$xxx <attr-label>-xxx elsewhere
+
+ Non <alphanumhyphen> characters in <attr-value>:
+
+ MCGAM rule DNS store translation conditions
+ -----------------------------------------------------------------
+ - -h- hyphen
+ \. -d- quoted dot
+ <blank> -b- blank
+ <non A/N character> -<3digit-decimal>- elsewhere
+
+ If the DNS store translation of <attr-value> happens to end with an
+ hyphen, then this last hyphen is omitted.
+
+ Let's now have some examples:
+
+
+
+
+
+Allocchio Standards Track [Page 11]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ MCGAM rule DNS store translation conditions
+ -----------------------------------------------------------------
+ PRMD$@ PRMD missing attribute
+ ADMD$<blank> ADMDb blank attribute
+ ADMD$400-net ADMD-400-h-net hyphen mapping
+ PRMD$UK\.BD PRMD-UK-d-BD quoted dot mapping
+ O$ACME Inc\. O-ACME-b-Inc-d blank & final hyphen
+ PRMD$main-400-a PRMD-main-h-400-h-a hyphen mapping
+ O$-123-b O--h-123-h-b hyphen mapping
+ OU$123-x OU-123-h-x hyphen mapping
+ PRMD$Adis+co PRMD-Adis-043-co 3digit mapping
+
+ Thus, an X.400 part from a MCGAM like
+
+ OU$uuu.O$@.PRMD$ppp\.rrr.ADMD$aaa ddd-mmm.C$cc
+
+ translates to
+
+ OU-uuu.O.PRMD-ppp-d-rrr.ADMD-aaa-b-ddd-h-mmm.C-cc
+
+ Another example:
+
+ OU$sales dept\..O$@.PRMD$ACME.ADMD$ .C$GB
+
+ translates to
+
+ OU-sales-b-dept-d.O.PRMD-ACME.ADMDb.C-GB
+
+4.2.2 Flow chart
+
+ In order to achieve the proper DNS store translations of the X.400
+ part of a MCGAM or any other X.400 O/R name, some software tools will
+ be used. It is in fact evident that the above rules for converting
+ mapping table from MIXER to DNS format (and vice versa) are not user
+ friendly enough to think of a human made conversion.
+
+ To help in designing such tools, we describe hereunder a small flow
+ chart. The fundamental rule to be applied during translation is,
+ however, the following:
+
+ "A string must be parsed from left to right, moving appropriately
+ the pointer in order not to consider again the already translated
+ left section of the string in subsequent analysis."
+
+
+
+
+
+
+
+
+Allocchio Standards Track [Page 12]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ Flow chart 1 - Translation from MIXER to DNS format:
+
+ parse single attribute
+ (enclosed in "." separators)
+ |
+ (yes) --- <label>$@ ? --- (no)
+ | |
+ map to <label> (no) <label>$<blank> ? (yes)
+ | | |
+ | map to <label>- map to <label>"b"
+ | | |
+ | map "\." to -d- |
+ | | |
+ | map "-" to -h- |
+ | | |
+ | map non A/N char to -<3digit>- |
+ restart | | |
+ ^ | remove (if any) last "-" |
+ | | | |
+ | \-------> add a "." <--------------/
+ | |
+ \---------- take next attribute (if any)
+
+
+ Flow chart 2 - Translation from DNS to MIXER format:
+
+
+ parse single attribute
+ (enclosed in "." separators)
+ |
+ (yes) ---- <label> ? ---- (no)
+ | |
+ map to <label>$@ (no) <label>"b" ? (yes)
+ | | |
+ | map to <label>$ map to <label>$<blank>
+ | | |
+ | map -d- to "\." |
+ | | |
+ | map -h- to "-" |
+ | | |
+ | map -b- to " " |
+ restart | | |
+ ^ | map -<3digit>- to non A/N char |
+ | | | |
+ | \--------> add a "." <----------/
+ | |
+ \------------- take next attribute (if any)
+
+
+
+
+Allocchio Standards Track [Page 13]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ Note that the above flow charts deal with the translation of the
+ attributes syntax, only.
+
+4.2.3 The Country Code convention in the <name> value.
+
+ The RFC822 domain space and the X.400 O/R address space, as said in
+ section 3, have one specific common feature: the X.400 ISO country
+ codes are the same as the RFC822 ISO top level domains for countries.
+ In the previous sections we have also defined a method to write in
+ <domain-name> syntax any X.400 domain, while in section 3 we
+ described the new name space starting at each country top level
+ domain under the X42D.cc (where 'cc' is then two letter ISO country
+ code).
+
+ The <name> value for a 'table1' or 'gate1' entry in DNS should thus
+ be derived from the X.400 domain value, translated to <domain-name>
+ syntax, adding the 'X42D.cc.' post-fix to it, i.e.,
+
+ ADMD$acme.C$fr
+
+ produces in <domain-name> syntax the key:
+
+ ADMD-acme.C-fr
+
+ which is post-fixed by 'X42D.fr.' resulting in:
+
+ ADMD-acme.C-fr.X42D.fr.
+
+ However, due to the identical encoding for X.400 country codes and
+ RFC822 country top level domains, the string 'C-fr.X42D.fr.' is
+ clearly redundant.
+
+ We thus define the 'Country Code convention' for the <name> key,
+ i.e.,
+
+ "The C-cc section of an X.400 domain in <domain-name> syntax must
+ be omitted when creating a <name> key, as it is identical to the
+ top level country code used to identify the DNS zone where the
+ information is stored".
+
+ Thus we obtain the following <name> key examples:
+
+ X.400 domain DNS <name> key
+ --------------------------------------------------------------------
+ ADMD$acme.C$fr ADMD-acme.X42D.fr.
+ PRMD$ux\.av.ADMD$ .C$gb PRMD-ux-d-av.ADMDb.X42D.gb.
+ PRMD$ppb.ADMD$Dat 400.C$de PRMD-ppb.ADMD-Dat-b-400.X42D.de.
+
+
+
+
+Allocchio Standards Track [Page 14]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+4.3 Creating the appropriate DNS files
+
+ Using MIXER's assumption of an asymmetric mapping between X.400 and
+ RFC822 addresses, two separate relations are required to store the
+ mapping database: MIXER 'table1' and MIXER 'table2'; thus also in DNS
+ we will maintain the two different sections, even if they will both
+ use the PX resource record. More over MIXER also specify two
+ additional tables: MIXER 'gate1' and 'gate2' tables. These additional
+ tables, however, have the same syntax rules than MIXER 'table1' and
+ 'table2' respectively, and thus the same translation procedure as
+ 'table1' and 'table2' will be applied; some details about the MIXER
+ 'gate1' and 'gate2' tables are discussed in section 4.4.
+
+ Let's now check how to create, from an MCGAM entry, the appropriate
+ DNS entry in a DNS data file. We can again define an MCGAM entry as
+ defined in appendix F of that document as:
+
+ <x400-domain>#<rfc822-domain># (case A: 'table1' and 'gate1'
+ entry)
+
+ and
+
+ <rfc822-domain>#<x400-domain># (case B: 'table2' and 'gate2'
+ entry)
+
+ The two cases must be considered separately. Let's consider case A.
+
+ - take <x400-domain> and translate it into <domain-name> syntax,
+ obtaining <x400-in-domain-syntax>;
+ - create the <name> key from <x400-in-domain-syntax> i.e., apply
+ the Country Code convention described in sect. 4.2.3;
+ - construct the DNS PX record as:
+
+ *.<name> IN PX 50 <rfc822-domain> <x400-in-domain-syntax>
+
+ Please note that within PX RDATA the <rfc822-domain> precedes the
+ <x400-in-domain-syntax> also for a 'table1' and 'gate1' entry.
+
+ an example: from the 'table1' rule
+
+ PRMD$ab.ADMD$ac.C$fr#ab.fr#
+
+ we obtain
+
+ *.PRMD-ab.ADMD-ac.X42D.fr. IN PX 50 ab.fr. PRMD-ab.ADMD-ac.C-fr.
+
+ Note that <name>, <rfc822-domain> and <x400-in-domain-syntax> are
+ fully qualified <domain-name> elements, thus ending with a ".".
+
+
+
+Allocchio Standards Track [Page 15]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ Let's now consider case B.
+
+ - take <rfc822-domain> as <name> key;
+ - translate <x400-domain> into <x400-in-domain-syntax>;
+ - construct the DNS PX record as:
+
+ *.<name> IN PX 50 <rfc822-domain> <x400-in-domain-syntax>
+
+ an example: from the 'table2' rule
+
+ ab.fr#PRMD$ab.ADMD$ac.C$fr#
+
+ we obtain
+
+ *.ab.fr. IN PX 50 ab.fr. PRMD-ab.ADMD-ac.C-fr.
+
+ Again note the fully qualified <domain-name> elements.
+
+ A file containing the MIXER mapping rules and MIXER 'gate1' and
+ 'gate2' table written in DNS format will look like the following
+ fictious example:
+
+ !
+ ! MIXER table 1: X.400 --> RFC822
+ !
+ *.ADMD-acme.X42D.it. IN PX 50 it. ADMD-acme.C-it.
+ *.PRMD-accred.ADMD-tx400.X42D.it. IN PX 50 \
+ accred.it. PRMD-accred.ADMD-tx400.C-it.
+ *.O-u-h-newcity.PRMD-x4net.ADMDb.X42D.it. IN PX 50 \
+ cs.ncty.it. O-u-h-newcity.PRMD-x4net.ADMDb.C-it.
+ !
+ ! MIXER table 2: RFC822 --> X.400
+ !
+ *.nrc.it. IN PX 50 nrc.it. PRMD-nrc.ADMD-acme.C-it.
+ *.ninp.it. IN PX 50 ninp.it. O.PRMD-ninp.ADMD-acme.C-it.
+ *.bd.it. IN PX 50 bd.it. PRMD-uk-d-bd.ADMDb.C-it.
+ !
+ ! MIXER Gate 1 Table
+ !
+ *.ADMD-XKW-h-Mail.X42D.it. IN PX 50 \
+ XKW-gateway.it. ADMD-XKW-h-Mail.C-it.G.
+ *.PRMD-Super-b-Inc.ADMDb.X42D.it. IN PX 50 \
+ GlobalGw.it. PRMD-Super-b-Inc.ADMDb.C-it.G.
+ !
+ ! MIXER Gate 2 Table
+ !
+ my.it. IN PX 50 my.it. OU-int-h-gw.O.PRMD-ninp.ADMD-acme.C-it.G.
+ co.it. IN PX 50 co.it. O-mhs-h-relay.PRMD-x4net.ADMDb.C-it.G.
+
+
+
+Allocchio Standards Track [Page 16]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ (here the "\" indicates continuation on the same line, as wrapping is
+ done only due to typographical reasons).
+
+ Note the special suffix ".G." on the right side of the 'gate1' and
+ 'gate2' Tables section whose aim is described in section 4.4. The
+ corresponding MIXER tables are:
+
+ #
+ # MIXER table 1: X.400 --> RFC822
+ #
+ ADMD$acme.C$it#it#
+ PRMD$accred.ADMD$tx400.C$it#accred.it#
+ O$u-newcity.PRMD$x4net.ADMD$ .C$it#cs.ncty.it#
+ #
+ # MIXER table 2: RFC822 --> X.400
+ #
+ nrc.it#PRMD$nrc.ADMD$acme.C$it#
+ ninp.it#O.PRMD$ninp.ADMD$acme.C$it#
+ bd.it#PRMD$uk\.bd.ADMD$ .C$it#
+ #
+ # MIXER Gate 1 Table
+ #
+ ADMD$XKW-Mail.C$it#XKW-gateway.it#
+ PRMD$Super Inc.ADMD$ .C$it#GlobalGw.it#
+ #
+ # MIXER Gate 2 Table
+ #
+ my.it#OU$int-gw.O$@.PRMD$ninp.ADMD$acme.C$it#
+ co.it#O$mhs-relay.PRMD$x4net.ADMD$ .C$t#
+
+4.4 Storing the MIXER 'gate1' and 'gate2' tables
+
+ Section 4.3.4 of MIXER also specify how an address should be
+ converted between RFC822 and X.400 in case a complete mapping is
+ impossible. To allow the use of DDAs for non mappable domains, the
+ MIXER 'gate2' table is thus introduced.
+
+ In a totally similar way, when an X.400 address cannot be completely
+ converted in RFC822, section 4.3.5 of MIXER specifies how to encode
+ (LHS encoding) the address itself, pointing then to the appropriate
+ MIXER conformant gateway, indicated in the MIXER 'gate1' table.
+
+ DNS must store and distribute also these 'gate1' and 'gate2' data.
+
+ One of the major features of the DNS is the ability to distribute the
+ authority: a certain site runs the "primary" nameserver for one
+ determined sub-tree and thus it is also the only place allowed to
+ update information regarding that sub-tree. This fact allows, in our
+
+
+
+Allocchio Standards Track [Page 17]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ case, a further additional feature to the table based approach. In
+ fact we can avoid one possible ambiguity about the use of the 'gate1'
+ and 'gate2' tables (and thus of LHS and DDAs encoding).
+
+ The authority maintaining a DNS entry in the usual RFC822 domain
+ space is the only one allowed to decide if its domain should be
+ mapped using Standard Attributes (SA) syntax or Domain Defined
+ Attributes (DDA) one. If the authority decides that its RFC822 domain
+ should be mapped using SA, then the PX RDATA will be a 'table2'
+ entry, otherwise it will be a 'gate2' table entry. Thus for an RFC822
+ domain we cannot have any more two possible entries, one from 'table2
+ and another one from 'gate2' table, and the action for a gateway
+ results clearly stated.
+
+ Similarly, the authority mantaining a DNS entry in the new X.400 name
+ space is the only one allowed to decide if its X.400 domain should be
+ mapped using SA syntax or Left Hand Side (LHS) encoding. If the
+ authority decides that its X.400 domain should be mapped using SA,
+ then the PX RDATA will be a 'table1' entry, otherwise it will be a
+ 'gate1' table entry. Thus also for an X.400 domain we cannot have any
+ more two possible entries, one from 'table1' and another one from
+ 'gate1' table, and the action for a gateway results clearly stated.
+
+ The MIXER 'gate1' table syntax is actually identical to MIXER
+ 'table1', and 'gate2' table syntax is identical to MIXER 'table2'.
+ Thus the same syntax translation rules from MIXER to DNS format can
+ be applied in both cases. However a gateway or any other application
+ must know if the answer it got from DNS contains some 'table1',
+ 'table2' or some 'gate1', 'gate2' table information. This is easily
+ obtained flagging with an additional ".G." post-fix the PX RDATA
+ value when it contains a 'gate1' or 'gate2' table entry. The example
+ in section 4.3 shows clearly the result. As any X.400 O/R domain must
+ end with a country code ("C-xx" in our DNS syntax) the additional
+ ".G." creates no conflicts or ambiguities at all. This postfix must
+ obviously be removed before using the MIXER 'gate1' or 'gate2' table
+ data.
+
+5. Finding MIXER mapping information from DNS
+
+ The MIXER mapping information is stored in DNS both in the normal
+ RFC822 domain name space, and in the newly defined X.400 name space.
+ The information, stored in PX resource records, does not represent a
+ full RFC822 or X.400 O/R address: it is a template which specifies
+ the fields of the domain that are used by the mapping algorithm.
+
+ When mapping information is stored in the DNS, queries to the DNS are
+ issued whenever an iterative search through the mapping table would
+ be performed (MIXER: section 4.3.4, State I; section 4.3.5, mapping
+
+
+
+Allocchio Standards Track [Page 18]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ B). Due to the DNS search mechanism, DNS by itself returns the
+ longest possible match in the stored mapping rule with a single
+ query, thus no iteration and/or multiple queries are needed. As
+ specified in MIXER, a search of the mapping table will result in
+ either success (mapping found) or failure (query failed, mapping not
+ found).
+
+ When a DNS query is issued, a third possible result is timeout. If
+ the result is timeout, the gateway operation is delayed and then
+ retried at a later time. A result of success or failure is processed
+ according to the algorithms specified in MIXER. If a DNS error code
+ is returned, an error message should be logged and the gateway
+ operation is delayed as for timeout. These pathological situations,
+ however, should be avoided with a careful duplication and chaching
+ mechanism which DNS itself provides.
+
+ Searching the nameserver which can authoritatively solve the query is
+ automatically performed by the DNS distributed name service.
+
+5.1 A DNS query example
+
+ An MIXER mail-gateway located in the Internet, when translating
+ addresses from RFC822 to X.400, can get information about the MCGAM
+ rule asking the DNS. As an example, when translating the address
+ SUN.CCE.NRC.IT, the gateway will just query DNS for the associated PX
+ resource record. The DNS should contain a PX record like this:
+
+ *.cce.nrc.it. IN PX 50 cce.nrc.it. O-cce.PRMD-nrc.ADMD-acme.C-it.
+
+ The first query will return immediately the appropriate mapping rule
+ in DNS store format.
+
+ There is no ".G." at the end of the obtained PX RDATA value, thus
+ applying the syntax translation specified in paragraph 4.2 the MIXER
+ Table 2 mapping rule will be obtained.
+
+ Let's now take another example where a 'gate2' table rule is
+ returned. If we are looking for an RFC822 domain ending with top
+ level domain "MW", and the DNS contains a PX record like this,
+
+ *.mw. IN PX 50 mw. O-cce.PRMD-nrc.ADMD-acme.C-it.G.
+
+ DNS will return 'mw.' and 'O-cce.PRMD-nrc.ADMD-acme.C-it.G.', i.e., a
+ 'gate2' table entry in DNS store format. Dropping the final ".G." and
+ applying the syntax translation specified in paragraph 4.2 the
+ original rule will be available. More over, the ".G." flag also tells
+ the gateway to use DDA encoding for the inquired RFC822 domain.
+
+
+
+
+Allocchio Standards Track [Page 19]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ On the other hand, translating from X.400 to RFC822 the address
+
+ C=de; ADMD=pkz; PRMD=nfc; O=top;
+
+ the mail gateway should convert the syntax according to paragraph
+ 4.2, apply the 'Country code convention' described in 4.2.3 to derive
+ the appropriate DNS translation of the X.400 O/R name and then query
+ DNS for the corresponding PX resource record. The obtained record for
+ which the PX record must be queried is thus:
+
+ O-top.PRMD-nfc.ADMD-pkz.X42D.de.
+
+ The DNS could contain:
+
+ *.ADMD-pkz.X42D.de. IN PX 50 pkz.de. ADMD-pkz.C-de.
+
+ Assuming that there are not more specific records in DNS, the
+ wildcard mechanism will return the MIXER 'table1' rule in encoded
+ format.
+
+ Finally, an example where a 'gate1' rule is involved. If we are
+ looking for an X.400 domain ending with ADMD=PWT400; C=US; , and the
+ DNS contains a PX record like this,
+
+ *.ADMD-PWT400.X42D.us. IN PX 50 intGw.com. ADMD-PWT400.C-us.G.
+
+ DNS will return 'intGw.com.' and 'ADMD-PWT400.C-us.G.', i.e., a
+ 'gate1' table entry in DNS store format. Dropping the final ".G." and
+ applying the syntax translation specified in paragraph 4.2 the
+ original rule will be available. More over, the ".G." flag also tells
+ the gateway to use LHS encoding for the inquired X.400 domain.
+
+6. Administration of mapping information
+
+ The DNS, using the PX RR, is able to distribute the MCGAM rules to
+ all MIXER gateways located on the Internet. However, not all MIXER
+ gateways will be able to use the Internet DNS. It is expected that
+ some gateways in a particular management domain will conform to one
+ of the following models:
+
+ (a) Table-based, (b) DNS-based, (c) X.500-based
+
+ Table-based management domains will continue to publish their MCGAM
+ rules and retrieve the mapping tables via the International Mapping
+ Table coordinator, manually or via some automated procedures. Their
+ MCGAM information can be made available also in DNS by the
+ appropriate DNS authorities, using the same mechanism already in
+ place for MX records: if a branch has not yet in place its own DNS
+
+
+
+Allocchio Standards Track [Page 20]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ server, some higher authority in the DNS tree will provide the
+ service for it. A transition procedure similar to the one used to
+ migrate from the 'hosts.txt' tables to DNS can be applied also to the
+ deployment phase of this specification. An informational document
+ describing the implementation phase and the detailed coordination
+ procedures is expected.
+
+ Another distributed directory service which can distribute the MCGAM
+ information is X.500. Coordination with table-based domains can be
+ obtained in an identical way as for the DNS case.
+
+ Coordination of MCGAM information between DNS and X.500 is more
+ complex, as it requies some kind of uploading information between the
+ two systems. The ideal solution is a dynamic alignment mechanism
+ which transparently makes the DNS mapping information available in
+ X.500 and vice versa. Some work in this specific field is already
+ being done [see Costa] which can result in a global transparent
+ directory service, where the information is stored in DNS or in
+ X.500, but is visible completely by any of the two systems.
+
+ However we must remind that MIXER concept of MCGAM rules publication
+ is different from the old RFC1327 concept of globally distributed,
+ coordinated and unique mapping rules. In fact MIXER does not requires
+ any more for any conformant gateway or tool to know the complete set
+ of MCGAM: it only requires to use some set (eventually empty) of
+ valid MCGAM rules, published either by Tables, DNS or X.500
+ mechanisms or any combination of these methods. More over MIXER
+ specifies that also incomplete sets of MCGAM can be used, and
+ supplementary local unpublished (but valid) MCGAM can also be used.
+ As a consequence, the problem of coordination between the three
+ systems proposed by MIXER for MCGAM publication is non essential, and
+ important only for efficient operational matters. It does not in fact
+ affect the correct behaviour of MIXER conformant gateways and tools.
+
+7. Conclusion
+
+ The introduction of the new PX resource record and the definition of
+ the X.400 O/R name space in the DNS structure provide a good
+ repository for MCGAM information. The mapping information is stored
+ in the DNS tree structure so that it can be easily obtained using the
+ DNS distributed name service. At the same time the definition of the
+ appropriate DNS space for X.400 O/R names provide a repository where
+ to store and distribute some other X.400 MHS information. The use of
+ the DNS has many known advantages in storing, managing and updating
+ the information. A successful number of tests were been performed
+ under the provisional top level domain "X400.IT" when RFC1664 was
+ developed, and their results confirmed the advantages of the method.
+ Operational exeprience for over 2 years with RFC1664 specification
+
+
+
+Allocchio Standards Track [Page 21]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ confirmed the feasibility of the method, and helped identifying some
+ operational procedures to deploy the insertion of MCGAM into DNS.
+
+ Software to query the DNS and then to convert between the textual
+ representation of DNS resource records and the address format defined
+ in MIXER was developed with RFC1664. This software also allows a
+ smooth implementation and deployment period, eventually taking care
+ of the transition phase. This software can be easily used (with
+ little or null modification) also for this updated specification,
+ supporting the new 'gate1' MIXER table. DNS software implementations
+ supporting RFC1664 also supports with no modification this memo new
+ specification.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Allocchio Standards Track [Page 22]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ A further informational document describing operational and
+ implementation of the service is expected.
+
+8. Acknowledgements
+
+ We wish to thanks all those who contributed to the discussion and
+ revision of this document: many of their ideas and suggestions
+ constitute essential parts of this work. In particular thanks to Jon
+ Postel, Paul Mockapetris, Rob Austin and the whole IETF x400ops,
+ TERENA wg-msg and IETF namedroppers groups. A special mention to
+ Christian Huitema for his fundamental contribution to this work.
+
+ This document is a revision of RFC1664, edited by one of its authors
+ on behalf of the IETF MIXER working group. The current editor wishes
+ to thank here also the authors of RFC1664:
+
+ Antonio Blasco Bonito RFC822: bonito@cnuce.cnr.it
+ CNUCE - CNR X.400: C=it;A=garr;P=cnr;
+ Reparto infr. reti O=cnuce;S=bonito;
+ Viale S. Maria 36
+ I 56126 Pisa
+ Italy
+
+
+ Bruce Cole RFC822: bcole@cisco.com
+ Cisco Systems Inc. X.400: C=us;A= ;P=Internet;
+ P.O. Box 3075 DD.rfc-822=bcole(a)cisco.com;
+ 1525 O'Brien Drive
+ Menlo Park, CA 94026
+ U.S.A.
+
+
+ Silvia Giordano RFC822: giordano@cscs.ch
+ Centro Svizzero di X.400: C=ch;A=arcom;P=switch;O=cscs;
+ Calcolo Scientifico S=giordano;
+ Via Cantonale
+ CH 6928 Manno
+ Switzerland
+
+
+ Robert Hagens RFC822: hagens@ans.net
+ Advanced Network and Services X.400: C=us;A= ;P=Internet;
+ 1875 Campus Commons Drive DD.rfc-822=hagens(a)ans.net;
+ Reston, VA 22091
+ U.S.A.
+
+
+
+
+
+
+Allocchio Standards Track [Page 23]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+9. References
+
+ [CCITT] CCITT SG 5/VII, "Recommendation X.400, Message Handling
+ Systems: System Model - Service Elements", October 1988.
+
+ [RFC 1327] Kille, S., "Mapping between X.400(1988)/ISO 10021 and RFC
+ 822", RFC 1327, March 1992.
+
+ [RFC 1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, USC/Information Sciences Institute, November
+ 1987.
+
+ [RFC 1035] Mockapetris, P., "Domain names - Implementation and
+ Specification", STD 13, RFC 1035, USC/Information Sciences
+ Institute, November 1987.
+
+ [RFC 1033] Lottor, M., "Domain Administrators Operation Guide", RFC
+ 1033, SRI International, November 1987.
+
+ [RFC 2156] Kille, S. E., " MIXER (Mime Internet X.400 Enhanced
+ Relay): Mapping between X.400 and RFC 822/MIME", RFC 2156,
+ January 1998.
+
+ [Costa] Costa, A., Macedo, J., and V. Freitas, "Accessing and
+ Managing DNS Information in the X.500 Directory", Proceeding of
+ the 4th Joint European Networking Conference, Trondheim, NO, May
+ 1993.
+
+10. Security Considerations
+
+ This document specifies a means by which DNS "PX" records can direct
+ the translation between X.400 and Internet mail addresses.
+
+ This can indirectly affect the routing of mail across an gateway
+ between X.400 and Internet Mail. A succesful attack on this service
+ could cause incorrect translation of an originator address (thus
+ "forging" the originator address), or incorrect translation of a
+ recipient address (thus directing the mail to an unauthorized
+ recipient, or making it appear to an authorized recipient, that the
+ message was intended for recipients other than those chosen by the
+ originator) or could force the mail path via some particular gateway
+ or message transfer agent where mail security can be affected by
+ compromised software.
+
+
+
+
+
+
+
+
+Allocchio Standards Track [Page 24]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+ There are several means by which an attacker might be able to deliver
+ incorrect PX records to a client. These include: (a) compromise of a
+ DNS server, (b) generating a counterfeit response to a client's DNS
+ query, (c) returning incorrect "additional information" in response
+ to an unrelated query.
+
+ Clients using PX records SHOULD ensure that routing and address
+ translations are based only on authoritative answers. Once DNS
+ Security mechanisms [RFC 2065] become more widely deployed, clients
+ SHOULD employ those mechanisms to verify the authenticity and
+ integrity of PX records.
+
+11. Author's Address
+
+ Claudio Allocchio
+ Sincrotrone Trieste
+ SS 14 Km 163.5 Basovizza
+ I 34012 Trieste
+ Italy
+
+ RFC822: Claudio.Allocchio@elettra.trieste.it
+ X.400: C=it;A=garr;P=Trieste;O=Elettra;
+ S=Allocchio;G=Claudio;
+ Phone: +39 40 3758523
+ Fax: +39 40 3758565
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Allocchio Standards Track [Page 25]
+
+RFC 2163 MIXER MCGAM January 1998
+
+
+12. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Allocchio Standards Track [Page 26]
+
diff --git a/doc/rfc/rfc2168.txt b/doc/rfc/rfc2168.txt
new file mode 100644
index 0000000..3eed1bd
--- /dev/null
+++ b/doc/rfc/rfc2168.txt
@@ -0,0 +1,1123 @@
+
+
+
+
+
+
+Network Working Group R. Daniel
+Request for Comments: 2168 Los Alamos National Laboratory
+Category: Experimental M. Mealling
+ Network Solutions, Inc.
+ June 1997
+
+
+ Resolution of Uniform Resource Identifiers
+ using the Domain Name System
+
+Status of this Memo
+===================
+
+ This memo defines an Experimental Protocol for the Internet
+ community. This memo does not specify an Internet standard of any
+ kind. Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Abstract:
+=========
+
+ Uniform Resource Locators (URLs) are the foundation of the World Wide
+ Web, and are a vital Internet technology. However, they have proven
+ to be brittle in practice. The basic problem is that URLs typically
+ identify a particular path to a file on a particular host. There is
+ no graceful way of changing the path or host once the URL has been
+ assigned. Neither is there a graceful way of replicating the resource
+ located by the URL to achieve better network utilization and/or fault
+ tolerance. Uniform Resource Names (URNs) have been hypothesized as a
+ adjunct to URLs that would overcome such problems. URNs and URLs are
+ both instances of a broader class of identifiers known as Uniform
+ Resource Identifiers (URIs).
+
+ The requirements document for URN resolution systems[15] defines the
+ concept of a "resolver discovery service". This document describes
+ the first, experimental, RDS. It is implemented by a new DNS Resource
+ Record, NAPTR (Naming Authority PoinTeR), that provides rules for
+ mapping parts of URIs to domain names. By changing the mapping
+ rules, we can change the host that is contacted to resolve a URI.
+ This will allow a more graceful handling of URLs over long time
+ periods, and forms the foundation for a new proposal for Uniform
+ Resource Names.
+
+
+
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 1]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ In addition to locating resolvers, the NAPTR provides for other
+ naming systems to be grandfathered into the URN world, provides
+ independence between the name assignment system and the resolution
+ protocol system, and allows multiple services (Name to Location, Name
+ to Description, Name to Resource, ...) to be offered. In conjunction
+ with the SRV RR, the NAPTR record allows those services to be
+ replicated for the purposes of fault tolerance and load balancing.
+
+Introduction:
+=============
+
+ Uniform Resource Locators have been a significant advance in
+ retrieving Internet-accessible resources. However, their brittle
+ nature over time has been recognized for several years. The Uniform
+ Resource Identifier working group proposed the development of Uniform
+ Resource Names to serve as persistent, location-independent
+ identifiers for Internet resources in order to overcome most of the
+ problems with URLs. RFC-1737 [1] sets forth requirements on URNs.
+
+ During the lifetime of the URI-WG, a number of URN proposals were
+ generated. The developers of several of those proposals met in a
+ series of meetings, resulting in a compromise known as the Knoxville
+ framework. The major principle behind the Knoxville framework is
+ that the resolution system must be separate from the way names are
+ assigned. This is in marked contrast to most URLs, which identify the
+ host to contact and the protocol to use. Readers are referred to [2]
+ for background on the Knoxville framework and for additional
+ information on the context and purpose of this proposal.
+
+ Separating the way names are resolved from the way they are
+ constructed provides several benefits. It allows multiple naming
+ approaches and resolution approaches to compete, as it allows
+ different protocols and resolvers to be used. There is just one
+ problem with such a separation - how do we resolve a name when it
+ can't give us directions to its resolver?
+
+ For the short term, DNS is the obvious candidate for the resolution
+ framework, since it is widely deployed and understood. However, it is
+ not appropriate to use DNS to maintain information on a per-resource
+ basis. First of all, DNS was never intended to handle that many
+ records. Second, the limited record size is inappropriate for catalog
+ information. Third, domain names are not appropriate as URNs.
+
+ Therefore our approach is to use DNS to locate "resolvers" that can
+ provide information on individual resources, potentially including
+ the resource itself. To accomplish this, we "rewrite" the URI into a
+ domain name following the rules provided in NAPTR records. Rewrite
+ rules provide considerable power, which is important when trying to
+
+
+
+Daniel & Mealling Experimental [Page 2]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ meet the goals listed above. However, collections of rules can become
+ difficult to understand. To lessen this problem, the NAPTR rules are
+ *always* applied to the original URI, *never* to the output of
+ previous rules.
+
+ Locating a resolver through the rewrite procedure may take multiple
+ steps, but the beginning is always the same. The start of the URI is
+ scanned to extract its colon-delimited prefix. (For URNs, the prefix
+ is always "urn:" and we extract the following colon-delimited
+ namespace identifier [3]). NAPTR resolution begins by taking the
+ extracted string, appending the well-known suffix ".urn.net", and
+ querying the DNS for NAPTR records at that domain name. Based on the
+ results of this query, zero or more additional DNS queries may be
+ needed to locate resolvers for the URI. The details of the
+ conversation between the client and the resolver thus located are
+ outside the bounds of this draft. Three brief examples of this
+ procedure are given in the next section.
+
+ The NAPTR RR provides the level of indirection needed to keep the
+ naming system independent of the resolution system, its protocols,
+ and services. Coupled with the new SRV resource record proposal[4]
+ there is also the potential for replicating the resolver on multiple
+ hosts, overcoming some of the most significant problems of URLs. This
+ is an important and subtle point. Not only do the NAPTR and SRV
+ records allow us to replicate the resource, we can replicate the
+ resolvers that know about the replicated resource. Preventing a
+ single point of failure at the resolver level is a significant
+ benefit. Separating the resolution procedure from the way names are
+ constructed has additional benefits. Different resolution procedures
+ can be used over time, and resolution procedures that are determined
+ to be useful can be extended to deal with additional namespaces.
+
+Caveats
+=======
+
+ The NAPTR proposal is the first resolution procedure to be considered
+ by the URN-WG. There are several concerns about the proposal which
+ have motivated the group to recommend it for publication as an
+ Experimental rather than a standards-track RFC.
+
+ First, URN resolution is new to the IETF and we wish to gain
+ operational experience before recommending any procedure for the
+ standards track. Second, the NAPTR proposal is based on DNS and
+ consequently inherits concerns about security and administration. The
+ recent advancement of the DNSSEC and secure update drafts to Proposed
+ Standard reduce these concerns, but we wish to experiment with those
+ new capabilities in the context of URN administration. A third area
+ of concern is the potential for a noticeable impact on the DNS. We
+
+
+
+Daniel & Mealling Experimental [Page 3]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ believe that the proposal makes appropriate use of caching and
+ additional information, but it is best to go slow where the potential
+ for impact on a core system like the DNS is concerned. Fourth, the
+ rewrite rules in the NAPTR proposal are based on regular expressions.
+ Since regular expressions are difficult for humans to construct
+ correctly, concerns exist about the usability and maintainability of
+ the rules. This is especially true where international character sets
+ are concerned. Finally, the URN-WG is developing a requirements
+ document for URN Resolution Services[15], but that document is not
+ complete. That document needs to precede any resolution service
+ proposals on the standards track.
+
+Terminology
+===========
+
+ "Must" or "Shall" - Software that does not behave in the manner that
+ this document says it must is not conformant to this
+ document.
+ "Should" - Software that does not follow the behavior that this
+ document says it should may still be conformant, but is
+ probably broken in some fundamental way.
+ "May" - Implementations may or may not provide the described
+ behavior, while still remaining conformant to this
+ document.
+
+Brief overview and examples of the NAPTR RR:
+============================================
+
+ A detailed description of the NAPTR RR will be given later, but to
+ give a flavor for the proposal we first give a simple description of
+ the record and three examples of its use.
+
+ The key fields in the NAPTR RR are order, preference, service, flags,
+ regexp, and replacement:
+
+ * The order field specifies the order in which records MUST be
+ processed when multiple NAPTR records are returned in response to a
+ single query. A naming authority may have delegated a portion of
+ its namespace to another agency. Evaluating the NAPTR records in
+ the correct order is necessary for delegation to work properly.
+
+ * The preference field specifies the order in which records SHOULD be
+ processed when multiple NAPTR records have the same value of
+ "order". This field lets a service provider specify the order in
+ which resolvers are contacted, so that more capable machines are
+ contacted in preference to less capable ones.
+
+
+
+
+
+Daniel & Mealling Experimental [Page 4]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ * The service field specifies the resolution protocol and resolution
+ service(s) that will be available if the rewrite specified by the
+ regexp or replacement fields is applied. Resolution protocols are
+ the protocols used to talk with a resolver. They will be specified
+ in other documents, such as [5]. Resolution services are operations
+ such as N2R (URN to Resource), N2L (URN to URL), N2C (URN to URC),
+ etc. These will be discussed in the URN Resolution Services
+ document[6], and their behavior in a particular resolution protocol
+ will be given in the specification for that protocol (see [5] for a
+ concrete example).
+
+ * The flags field contains modifiers that affect what happens in the
+ next DNS lookup, typically for optimizing the process. Flags may
+ also affect the interpretation of the other fields in the record,
+ therefore, clients MUST skip NAPTR records which contain an unknown
+ flag value.
+
+ * The regexp field is one of two fields used for the rewrite rules,
+ and is the core concept of the NAPTR record. The regexp field is a
+ String containing a sed-like substitution expression. (The actual
+ grammar for the substitution expressions is given later in this
+ draft). The substitution expression is applied to the original URN
+ to determine the next domain name to be queried. The regexp field
+ should be used when the domain name to be generated is conditional
+ on information in the URI. If the next domain name is always known,
+ which is anticipated to be a common occurrence, the replacement
+ field should be used instead.
+
+ * The replacement field is the other field that may be used for the
+ rewrite rule. It is an optimization of the rewrite process for the
+ case where the next domain name is fixed instead of being
+ conditional on the content of the URI. The replacement field is a
+ domain name (subject to compression if a DNS sender knows that a
+ given recipient is able to decompress names in this RR type's RDATA
+ field). If the rewrite is more complex than a simple substitution
+ of a domain name, the replacement field should be set to . and the
+ regexp field used.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 5]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ Note that the client applies all the substitutions and performs all
+ lookups, they are not performed in the DNS servers. Note also that it
+ is the belief of the developers of this document that regexps should
+ rarely be used. The replacement field seems adequate for the vast
+ majority of situations. Regexps are only necessary when portions of a
+ namespace are to be delegated to different resolvers. Finally, note
+ that the regexp and replacement fields are, at present, mutually
+ exclusive. However, developers of client software should be aware
+ that a new flag might be defined which requires values in both
+ fields.
+
+Example 1
+---------
+
+ Consider a URN that uses the hypothetical DUNS namespace. DUNS
+ numbers are identifiers for approximately 30 million registered
+ businesses around the world, assigned and maintained by Dunn and
+ Bradstreet. The URN might look like:
+
+ urn:duns:002372413:annual-report-1997
+
+ The first step in the resolution process is to find out about the
+ DUNS namespace. The namespace identifier, "duns", is extracted from
+ the URN, prepended to urn.net, and the NAPTRs for duns.urn.net looked
+ up. It might return records of the form:
+
+duns.urn.net
+;; order pref flags service regexp replacement
+ IN NAPTR 100 10 "s" "dunslink+N2L+N2C" "" dunslink.udp.isi.dandb.com
+ IN NAPTR 100 20 "s" "rcds+N2C" "" rcds.udp.isi.dandb.com
+ IN NAPTR 100 30 "s" "http+N2L+N2C+N2R" "" http.tcp.isi.dandb.com
+
+ The order field contains equal values, indicating that no name
+ delegation order has to be followed. The preference field indicates
+ that the provider would like clients to use the special dunslink
+ protocol, followed by the RCDS protocol, and that HTTP is offered as
+ a last resort. All the records specify the "s" flag, which will be
+ explained momentarily. The service fields say that if we speak
+ dunslink, we will be able to issue either the N2L or N2C requests to
+ obtain a URL or a URC (description) of the resource. The Resource
+ Cataloging and Distribution Service (RCDS)[7] could be used to get a
+ URC for the resource, while HTTP could be used to get a URL, URC, or
+ the resource itself. All the records supply the next domain name to
+ query, none of them need to be rewritten with the aid of regular
+ expressions.
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 6]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ The general case might require multiple NAPTR rewrites to locate a
+ resolver, but eventually we will come to the "terminal NAPTR". Once
+ we have the terminal NAPTR, our next probe into the DNS will be for a
+ SRV or A record instead of another NAPTR. Rather than probing for a
+ non-existent NAPTR record to terminate the loop, the flags field is
+ used to indicate a terminal lookup. If it has a value of "s", the
+ next lookup should be for SRV RRs, "a" denotes that A records should
+ sought. A "p" flag is also provided to indicate that the next action
+ is Protocol-specific, but that looking up another NAPTR will not be
+ part of it.
+
+ Since our example RR specified the "s" flag, it was terminal.
+ Assuming our client does not know the dunslink protocol, our next
+ action is to lookup SRV RRs for rcds.udp.isi.dandb.com, which will
+ tell us hosts that can provide the necessary resolution service. That
+ lookup might return:
+
+ ;; Pref Weight Port Target
+ rcds.udp.isi.dandb.com IN SRV 0 0 1000 defduns.isi.dandb.com
+ IN SRV 0 0 1000 dbmirror.com.au
+ IN SRV 0 0 1000 ukmirror.com.uk
+
+ telling us three hosts that could actually do the resolution, and
+ giving us the port we should use to talk to their RCDS server. (The
+ reader is referred to the SRV proposal [4] for the interpretation of
+ the fields above).
+
+ There is opportunity for significant optimization here. We can return
+ the SRV records as additional information for terminal NAPTRs (and
+ the A records as additional information for those SRVs). While this
+ recursive provision of additional information is not explicitly
+ blessed in the DNS specifications, it is not forbidden, and BIND does
+ take advantage of it [8]. This is a significant optimization. In
+ conjunction with a long TTL for *.urn.net records, the average number
+ of probes to DNS for resolving DUNS URNs would approach one.
+ Therefore, DNS server implementors SHOULD provide additional
+ information with NAPTR responses. The additional information will be
+ either SRV or A records. If SRV records are available, their A
+ records should be provided as recursive additional information.
+
+ Note that the example NAPTR records above are intended to represent
+ the reply the client will see. They are not quite identical to what
+ the domain administrator would put into the zone files. For one
+ thing, the administrator should supply the trailing '.' character on
+ any FQDNs.
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 7]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+Example 2
+---------
+
+ Consider a URN namespace based on MIME Content-Ids. The URN might
+ look like this:
+
+ urn:cid:199606121851.1@mordred.gatech.edu
+
+ (Note that this example is chosen for pedagogical purposes, and does
+ not conform to the recently-approved CID URL scheme.)
+
+ The first step in the resolution process is to find out about the CID
+ namespace. The namespace identifier, cid, is extracted from the URN,
+ prepended to urn.net, and the NAPTR for cid.urn.net looked up. It
+ might return records of the form:
+
+ cid.urn.net
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 10 "" "" "/urn:cid:.+@([^\.]+\.)(.*)$/\2/i" .
+
+ We have only one NAPTR response, so ordering the responses is not a
+ problem. The replacement field is empty, so we check the regexp
+ field and use the pattern provided there. We apply that regexp to the
+ entire URN to see if it matches, which it does. The \2 part of the
+ substitution expression returns the string "gatech.edu". Since the
+ flags field does not contain "s" or "a", the lookup is not terminal
+ and our next probe to DNS is for more NAPTR records:
+ lookup(query=NAPTR, "gatech.edu").
+
+ Note that the rule does not extract the full domain name from the
+ CID, instead it assumes the CID comes from a host and extracts its
+ domain. While all hosts, such as mordred, could have their very own
+ NAPTR, maintaining those records for all the machines at a site as
+ large as Georgia Tech would be an intolerable burden. Wildcards are
+ not appropriate here since they only return results when there is no
+ exactly matching names already in the system.
+
+ The record returned from the query on "gatech.edu" might look like:
+
+gatech.edu IN NAPTR
+;; order pref flags service regexp replacement
+ IN NAPTR 100 50 "s" "z3950+N2L+N2C" "" z3950.tcp.gatech.edu
+ IN NAPTR 100 50 "s" "rcds+N2C" "" rcds.udp.gatech.edu
+ IN NAPTR 100 50 "s" "http+N2L+N2C+N2R" "" http.tcp.gatech.edu
+
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 8]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ Continuing with our example, we note that the values of the order and
+ preference fields are equal in all records, so the client is free to
+ pick any record. The flags field tells us that these are the last
+ NAPTR patterns we should see, and after the rewrite (a simple
+ replacement in this case) we should look up SRV records to get
+ information on the hosts that can provide the necessary service.
+
+ Assuming we prefer the Z39.50 protocol, our lookup might return:
+
+ ;; Pref Weight Port Target
+ z3950.tcp.gatech.edu IN SRV 0 0 1000 z3950.gatech.edu
+ IN SRV 0 0 1000 z3950.cc.gatech.edu
+ IN SRV 0 0 1000 z3950.uga.edu
+
+ telling us three hosts that could actually do the resolution, and
+ giving us the port we should use to talk to their Z39.50 server.
+
+ Recall that the regular expression used \2 to extract a domain name
+ from the CID, and \. for matching the literal '.' characters
+ seperating the domain name components. Since '\' is the escape
+ character, literal occurances of a backslash must be escaped by
+ another backslash. For the case of the cid.urn.net record above, the
+ regular expression entered into the zone file should be
+ "/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i". When the client code actually
+ receives the record, the pattern will have been converted to
+ "/urn:cid:.+@([^.]+\.)(.*)$/\2/i".
+
+Example 3
+---------
+
+ Even if URN systems were in place now, there would still be a
+ tremendous number of URLs. It should be possible to develop a URN
+ resolution system that can also provide location independence for
+ those URLs. This is related to the requirement in [1] to be able to
+ grandfather in names from other naming systems, such as ISO Formal
+ Public Identifiers, Library of Congress Call Numbers, ISBNs, ISSNs,
+ etc.
+
+ The NAPTR RR could also be used for URLs that have already been
+ assigned. Assume we have the URL for a very popular piece of
+ software that the publisher wishes to mirror at multiple sites around
+ the world:
+
+ http://www.foo.com/software/latest-beta.exe
+
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 9]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ We extract the prefix, "http", and lookup NAPTR records for
+ http.urn.net. This might return a record of the form
+
+ http.urn.net IN NAPTR
+ ;; order pref flags service regexp replacement
+ 100 90 "" "" "!http://([^/:]+)!\1!i" .
+
+ This expression returns everything after the first double slash and
+ before the next slash or colon. (We use the '!' character to delimit
+ the parts of the substitution expression. Otherwise we would have to
+ use backslashes to escape the forward slashes, and would have a
+ regexp in the zone file that looked like
+ "/http:\\/\\/([^\\/:]+)/\\1/i".).
+
+ Applying this pattern to the URL extracts "www.foo.com". Looking up
+ NAPTR records for that might return:
+
+ www.foo.com
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 100 "s" "http+L2R" "" http.tcp.foo.com
+ IN NAPTR 100 100 "s" "ftp+L2R" "" ftp.tcp.foo.com
+
+ Looking up SRV records for http.tcp.foo.com would return information
+ on the hosts that foo.com has designated to be its mirror sites. The
+ client can then pick one for the user.
+
+NAPTR RR Format
+===============
+
+ The format of the NAPTR RR is given below. The DNS type code for
+ NAPTR is 35.
+
+ Domain TTL Class Order Preference Flags Service Regexp
+ Replacement
+
+ where:
+
+ Domain
+ The domain name this resource record refers to.
+ TTL
+ Standard DNS Time To Live field
+ Class
+ Standard DNS meaning
+
+
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 10]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ Order
+ A 16-bit integer specifying the order in which the NAPTR
+ records MUST be processed to ensure correct delegation of
+ portions of the namespace over time. Low numbers are processed
+ before high numbers, and once a NAPTR is found that "matches"
+ a URN, the client MUST NOT consider any NAPTRs with a higher
+ value for order.
+
+ Preference
+ A 16-bit integer which specifies the order in which NAPTR
+ records with equal "order" values SHOULD be processed, low
+ numbers being processed before high numbers. This is similar
+ to the preference field in an MX record, and is used so domain
+ administrators can direct clients towards more capable hosts
+ or lighter weight protocols.
+
+ Flags
+ A String giving flags to control aspects of the rewriting and
+ interpretation of the fields in the record. Flags are single
+ characters from the set [A-Z0-9]. The case of the alphabetic
+ characters is not significant.
+
+ At this time only three flags, "S", "A", and "P", are defined.
+ "S" means that the next lookup should be for SRV records
+ instead of NAPTR records. "A" means that the next lookup
+ should be for A records. The "P" flag says that the remainder
+ of the resolution shall be carried out in a Protocol-specific
+ fashion, and we should not do any more DNS queries.
+
+ The remaining alphabetic flags are reserved. The numeric flags
+ may be used for local experimentation. The S, A, and P flags
+ are all mutually exclusive, and resolution libraries MAY
+ signal an error if more than one is given. (Experimental code
+ and code for assisting in the creation of NAPTRs would be more
+ likely to signal such an error than a client such as a
+ browser). We anticipate that multiple flags will be allowed in
+ the future, so implementers MUST NOT assume that the flags
+ field can only contain 0 or 1 characters. Finally, if a client
+ encounters a record with an unknown flag, it MUST ignore it
+ and move to the next record. This test takes precedence even
+ over the "order" field. Since flags can control the
+ interpretation placed on fields, a novel flag might change the
+ interpretation of the regexp and/or replacement fields such
+ that it is impossible to determine if a record matched a URN.
+
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 11]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ Service
+ Specifies the resolution service(s) available down this
+ rewrite path. It may also specify the particular protocol that
+ is used to talk with a resolver. A protocol MUST be specified
+ if the flags field states that the NAPTR is terminal. If a
+ protocol is specified, but the flags field does not state that
+ the NAPTR is terminal, the next lookup MUST be for a NAPTR.
+ The client MAY choose not to perform the next lookup if the
+ protocol is unknown, but that behavior MUST NOT be relied
+ upon.
+
+ The service field may take any of the values below (using the
+ Augmented BNF of RFC 822[9]):
+
+ service_field = [ [protocol] *("+" rs)]
+ protocol = ALPHA *31ALPHANUM
+ rs = ALPHA *31ALPHANUM
+ // The protocol and rs fields are limited to 32
+ // characters and must start with an alphabetic.
+ // The current set of "known" strings are:
+ // protocol = "rcds" / "thttp" / "hdl" / "rwhois" / "z3950"
+ // rs = "N2L" / "N2Ls" / "N2R" / "N2Rs" / "N2C"
+ // / "N2Ns" / "L2R" / "L2Ns" / "L2Ls" / "L2C"
+
+ i.e. an optional protocol specification followed by 0 or more
+ resolution services. Each resolution service is indicated by
+ an initial '+' character.
+
+ Note that the empty string is also a valid service field. This
+ will typically be seen at the top levels of a namespace, when
+ it is impossible to know what services and protocols will be
+ offered by a particular publisher within that name space.
+
+ At this time the known protocols are rcds[7], hdl[10] (binary,
+ UDP-based protocols), thttp[5] (a textual, TCP-based
+ protocol), rwhois[11] (textual, UDP or TCP based), and
+ Z39.50[12] (binary, TCP-based). More will be allowed later.
+ The names of the protocols must be formed from the characters
+ [a-Z0-9]. Case of the characters is not significant.
+
+ The service requests currently allowed will be described in
+ more detail in [6], but in brief they are:
+ N2L - Given a URN, return a URL
+ N2Ls - Given a URN, return a set of URLs
+ N2R - Given a URN, return an instance of the resource.
+ N2Rs - Given a URN, return multiple instances of the
+ resource, typically encoded using
+ multipart/alternative.
+
+
+
+Daniel & Mealling Experimental [Page 12]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ N2C - Given a URN, return a collection of meta-
+ information on the named resource. The format of
+ this response is the subject of another document.
+ N2Ns - Given a URN, return all URNs that are also
+ identifers for the resource.
+ L2R - Given a URL, return the resource.
+ L2Ns - Given a URL, return all the URNs that are
+ identifiers for the resource.
+ L2Ls - Given a URL, return all the URLs for instances of
+ of the same resource.
+ L2C - Given a URL, return a description of the
+ resource.
+
+ The actual format of the service request and response will be
+ determined by the resolution protocol, and is the subject for
+ other documents (e.g. [5]). Protocols need not offer all
+ services. The labels for service requests shall be formed from
+ the set of characters [A-Z0-9]. The case of the alphabetic
+ characters is not significant.
+
+ Regexp
+ A STRING containing a substitution expression that is applied
+ to the original URI in order to construct the next domain name
+ to lookup. The grammar of the substitution expression is given
+ in the next section.
+
+ Replacement
+ The next NAME to query for NAPTR, SRV, or A records depending
+ on the value of the flags field. As mentioned above, this may
+ be compressed.
+
+Substitution Expression Grammar:
+================================
+
+ The content of the regexp field is a substitution expression. True
+ sed(1) substitution expressions are not appropriate for use in this
+ application for a variety of reasons, therefore the contents of the
+ regexp field MUST follow the grammar below:
+
+subst_expr = delim-char ere delim-char repl delim-char *flags
+delim-char = "/" / "!" / ... (Any non-digit or non-flag character other
+ than backslash '\'. All occurances of a delim_char in a
+ subst_expr must be the same character.)
+ere = POSIX Extended Regular Expression (see [13], section
+ 2.8.4)
+repl = dns_str / backref / repl dns_str / repl backref
+dns_str = 1*DNS_CHAR
+backref = "\" 1POS_DIGIT
+
+
+
+Daniel & Mealling Experimental [Page 13]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+flags = "i"
+DNS_CHAR = "-" / "0" / ... / "9" / "a" / ... / "z" / "A" / ... / "Z"
+POS_DIGIT = "1" / "2" / ... / "9" ; 0 is not an allowed backref
+value domain name (see RFC-1123 [14]).
+
+ The result of applying the substitution expression to the original
+ URI MUST result in a string that obeys the syntax for DNS host names
+ [14]. Since it is possible for the regexp field to be improperly
+ specified, such that a non-conforming host name can be constructed,
+ client software SHOULD verify that the result is a legal host name
+ before making queries on it.
+
+ Backref expressions in the repl portion of the substitution
+ expression are replaced by the (possibly empty) string of characters
+ enclosed by '(' and ')' in the ERE portion of the substitution
+ expression. N is a single digit from 1 through 9, inclusive. It
+ specifies the N'th backref expression, the one that begins with the
+ N'th '(' and continues to the matching ')'. For example, the ERE
+ (A(B(C)DE)(F)G)
+ has backref expressions:
+ \1 = ABCDEFG
+ \2 = BCDE
+ \3 = C
+ \4 = F
+ \5..\9 = error - no matching subexpression
+
+ The "i" flag indicates that the ERE matching SHALL be performed in a
+ case-insensitive fashion. Furthermore, any backref replacements MAY
+ be normalized to lower case when the "i" flag is given.
+
+ The first character in the substitution expression shall be used as
+ the character that delimits the components of the substitution
+ expression. There must be exactly three non-escaped occurrences of
+ the delimiter character in a substitution expression. Since escaped
+ occurrences of the delimiter character will be interpreted as
+ occurrences of that character, digits MUST NOT be used as delimiters.
+ Backrefs would be confused with literal digits were this allowed.
+ Similarly, if flags are specified in the substitution expression, the
+ delimiter character must not also be a flag character.
+
+
+
+
+
+
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 14]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+Advice to domain administrators:
+================================
+
+ Beware of regular expressions. Not only are they a pain to get
+ correct on their own, but there is the previously mentioned
+ interaction with DNS. Any backslashes in a regexp must be entered
+ twice in a zone file in order to appear once in a query response.
+ More seriously, the need for double backslashes has probably not been
+ tested by all implementors of DNS servers. We anticipate that urn.net
+ will be the heaviest user of regexps. Only when delegating portions
+ of namespaces should the typical domain administrator need to use
+ regexps.
+
+ On a related note, beware of interactions with the shell when
+ manipulating regexps from the command line. Since '\' is a common
+ escape character in shells, there is a good chance that when you
+ think you are saying "\\" you are actually saying "\". Similar
+ caveats apply to characters such as
+
+ The "a" flag allows the next lookup to be for A records rather than
+ SRV records. Since there is no place for a port specification in the
+ NAPTR record, when the "A" flag is used the specified protocol must
+ be running on its default port.
+
+ The URN Sytnax draft defines a canonical form for each URN, which
+ requires %encoding characters outside a limited repertoire. The
+ regular expressions MUST be written to operate on that canonical
+ form. Since international character sets will end up with extensive
+ use of %encoded characters, regular expressions operating on them
+ will be essentially impossible to read or write by hand.
+
+Usage
+=====
+
+ For the edification of implementers, pseudocode for a client routine
+ using NAPTRs is given below. This code is provided merely as a
+ convience, it does not have any weight as a standard way to process
+ NAPTR records. Also, as is the case with pseudocode, it has never
+ been executed and may contain logical errors. You have been warned.
+
+ //
+ // findResolver(URN)
+ // Given a URN, find a host that can resolve it.
+ //
+ findResolver(string URN) {
+ // prepend prefix to urn.net
+ sprintf(key, "%s.urn.net", extractNS(URN));
+ do {
+
+
+
+Daniel & Mealling Experimental [Page 15]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ rewrite_flag = false;
+ terminal = false;
+ if (key has been seen) {
+ quit with a loop detected error
+ }
+ add key to list of "seens"
+ records = lookup(type=NAPTR, key); // get all NAPTR RRs for 'key'
+
+ discard any records with an unknown value in the "flags" field.
+ sort NAPTR records by "order" field and "preference" field
+ (with "order" being more significant than "preference").
+ n_naptrs = number of NAPTR records in response.
+ curr_order = records[0].order;
+ max_order = records[n_naptrs-1].order;
+
+ // Process current batch of NAPTRs according to "order" field.
+ for (j=0; j < n_naptrs && records[j].order <= max_order; j++) {
+ if (unknown_flag) // skip this record and go to next one
+ continue;
+ newkey = rewrite(URN, naptr[j].replacement, naptr[j].regexp);
+ if (!newkey) // Skip to next record if the rewrite didn't
+ match continue;
+ // We did do a rewrite, shrink max_order to current value
+ // so that delegation works properly
+ max_order = naptr[j].order;
+ // Will we know what to do with the protocol and services
+ // specified in the NAPTR? If not, try next record.
+ if(!isKnownProto(naptr[j].services)) {
+ continue;
+ }
+ if(!isKnownService(naptr[j].services)) {
+ continue;
+ }
+
+ // At this point we have a successful rewrite and we will
+ // know how to speak the protocol and request a known
+ // resolution service. Before we do the next lookup, check
+ // some optimization possibilities.
+
+ if (strcasecmp(flags, "S")
+ || strcasecmp(flags, "P"))
+ || strcasecmp(flags, "A")) {
+ terminal = true;
+ services = naptr[j].services;
+ addnl = any SRV and/or A records returned as additional
+ info for naptr[j].
+ }
+ key = newkey;
+
+
+
+Daniel & Mealling Experimental [Page 16]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ rewriteflag = true;
+ break;
+ }
+ } while (rewriteflag && !terminal);
+
+ // Did we not find our way to a resolver?
+ if (!rewrite_flag) {
+ report an error
+ return NULL;
+ }
+
+
+ // Leave rest to another protocol?
+ if (strcasecmp(flags, "P")) {
+ return key as host to talk to;
+ }
+
+ // If not, keep plugging
+ if (!addnl) { // No SRVs came in as additional info, look them up
+ srvs = lookup(type=SRV, key);
+ }
+
+ sort SRV records by preference, weight, ...
+ foreach (SRV record) { // in order of preference
+ try contacting srv[j].target using the protocol and one of the
+ resolution service requests from the "services" field of the
+ last NAPTR record.
+ if (successful)
+ return (target, protocol, service);
+ // Actually we would probably return a result, but this
+ // code was supposed to just tell us a good host to talk to.
+ }
+ die with an "unable to find a host" error;
+ }
+
+Notes:
+======
+
+ - A client MUST process multiple NAPTR records in the order
+ specified by the "order" field, it MUST NOT simply use the first
+ record that provides a known protocol and service combination.
+
+
+
+
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 17]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ - If a record at a particular order matches the URI, but the
+ client doesn't know the specified protocol and service, the
+ client SHOULD continue to examine records that have the same
+ order. The client MUST NOT consider records with a higher value
+ of order. This is necessary to make delegation of portions of
+ the namespace work. The order field is what lets site
+ administrators say "all requests for URIs matching pattern x go
+ to server 1, all others go to server 2".
+ (A match is defined as:
+ 1) The NAPTR provides a replacement domain name
+ or
+ 2) The regular expression matches the URN
+ )
+
+ - When multiple RRs have the same "order", the client should use
+ the value of the preference field to select the next NAPTR to
+ consider. However, because of preferred protocols or services,
+ estimates of network distance and bandwidth, etc. clients may
+ use different criteria to sort the records.
+ - If the lookup after a rewrite fails, clients are strongly
+ encouraged to report a failure, rather than backing up to pursue
+ other rewrite paths.
+ - When a namespace is to be delegated among a set of resolvers,
+ regexps must be used. Each regexp appears in a separate NAPTR
+ RR. Administrators should do as little delegation as possible,
+ because of limitations on the size of DNS responses.
+ - Note that SRV RRs impose additional requirements on clients.
+
+Acknowledgments:
+=================
+
+ The editors would like to thank Keith Moore for all his consultations
+ during the development of this draft. We would also like to thank
+ Paul Vixie for his assistance in debugging our implementation, and
+ his answers on our questions. Finally, we would like to acknowledge
+ our enormous intellectual debt to the participants in the Knoxville
+ series of meetings, as well as to the participants in the URI and URN
+ working groups.
+
+References:
+===========
+
+ [1] Sollins, Karen and Larry Masinter, "Functional Requirements
+ for Uniform Resource Names", RFC-1737, Dec. 1994.
+
+ [2] The URN Implementors, Uniform Resource Names: A Progress Report,
+ http://www.dlib.org/dlib/february96/02arms.html, D-Lib Magazine,
+ February 1996.
+
+
+
+Daniel & Mealling Experimental [Page 18]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+ [3] Moats, Ryan, "URN Syntax", RFC-2141, May 1997.
+
+ [4] Gulbrandsen, A. and P. Vixie, "A DNS RR for specifying
+ the location of services (DNS SRV)", RFC-2052, October 1996.
+
+ [5] Daniel, Jr., Ron, "A Trivial Convention for using HTTP in URN
+ Resolution", RFC-2169, June 1997.
+
+ [6] URN-WG, "URN Resolution Services", Work in Progress.
+
+ [7] Moore, Keith, Shirley Browne, Jason Cox, and Jonathan Gettler,
+ Resource Cataloging and Distribution System, Technical Report
+ CS-97-346, University of Tennessee, Knoxville, December 1996
+
+ [8] Paul Vixie, personal communication.
+
+ [9] Crocker, Dave H. "Standard for the Format of ARPA Internet Text
+ Messages", RFC-822, August 1982.
+
+ [10] Orth, Charles and Bill Arms; Handle Resolution Protocol
+ Specification, http://www.handle.net/docs/client_spec.html
+
+ [11] Williamson, S., M. Kosters, D. Blacka, J. Singh, K. Zeilstra,
+ "Referral Whois Protocol (RWhois)", RFC-2167, June 1997.
+
+ [12] Information Retrieval (Z39.50): Application Service Definition
+ and Protocol Specification, ANSI/NISO Z39.50-1995, July 1995.
+
+ [13] IEEE Standard for Information Technology - Portable Operating
+ System Interface (POSIX) - Part 2: Shell and Utilities (Vol. 1);
+ IEEE Std 1003.2-1992; The Institute of Electrical and
+ Electronics Engineers; New York; 1993. ISBN:1-55937-255-9
+
+ [14] Braden, R., "Requirements for Internet Hosts - Application and
+ and Support", RFC-1123, Oct. 1989.
+
+ [15] Sollins, Karen, "Requirements and a Framework for URN Resolution
+ Systems", November 1996, Work in Progress.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 19]
+
+RFC 2168 Resolution of URIs Using the DNS June 1997
+
+
+Security Considerations
+=======================
+
+ The use of "urn.net" as the registry for URN namespaces is subject to
+ denial of service attacks, as well as other DNS spoofing attacks. The
+ interactions with DNSSEC are currently being studied. It is expected
+ that NAPTR records will be signed with SIG records once the DNSSEC
+ work is deployed.
+
+ The rewrite rules make identifiers from other namespaces subject to
+ the same attacks as normal domain names. Since they have not been
+ easily resolvable before, this may or may not be considered a
+ problem.
+
+ Regular expressions should be checked for sanity, not blindly passed
+ to something like PERL.
+
+ This document has discussed a way of locating a resolver, but has not
+ discussed any detail of how the communication with the resolver takes
+ place. There are significant security considerations attached to the
+ communication with a resolver. Those considerations are outside the
+ scope of this document, and must be addressed by the specifications
+ for particular resolver communication protocols.
+
+Author Contact Information:
+===========================
+
+ Ron Daniel
+ Los Alamos National Laboratory
+ MS B287
+ Los Alamos, NM, USA, 87545
+ voice: +1 505 665 0597
+ fax: +1 505 665 4939
+ email: rdaniel@lanl.gov
+
+
+ Michael Mealling
+ Network Solutions
+ 505 Huntmar Park Drive
+ Herndon, VA 22070
+ voice: (703) 742-0400
+ fax: (703) 742-9552
+ email: michaelm@internic.net
+ URL: http://www.netsol.com/
+
+
+
+
+
+
+
+Daniel & Mealling Experimental [Page 20]
+
diff --git a/doc/rfc/rfc2181.txt b/doc/rfc/rfc2181.txt
new file mode 100644
index 0000000..7899e1c
--- /dev/null
+++ b/doc/rfc/rfc2181.txt
@@ -0,0 +1,842 @@
+
+
+
+
+
+
+Network Working Group R. Elz
+Request for Comments: 2181 University of Melbourne
+Updates: 1034, 1035, 1123 R. Bush
+Category: Standards Track RGnet, Inc.
+ July 1997
+
+
+ Clarifications to the DNS Specification
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+1. Abstract
+
+ This document considers some areas that have been identified as
+ problems with the specification of the Domain Name System, and
+ proposes remedies for the defects identified. Eight separate issues
+ are considered:
+
+ + IP packet header address usage from multi-homed servers,
+ + TTLs in sets of records with the same name, class, and type,
+ + correct handling of zone cuts,
+ + three minor issues concerning SOA records and their use,
+ + the precise definition of the Time to Live (TTL)
+ + Use of the TC (truncated) header bit
+ + the issue of what is an authoritative, or canonical, name,
+ + and the issue of what makes a valid DNS label.
+
+ The first six of these are areas where the correct behaviour has been
+ somewhat unclear, we seek to rectify that. The other two are already
+ adequately specified, however the specifications seem to be sometimes
+ ignored. We seek to reinforce the existing specifications.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Elz & Bush Standards Track [Page 1]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+
+
+Contents
+
+ 1 Abstract ................................................... 1
+ 2 Introduction ............................................... 2
+ 3 Terminology ................................................ 3
+ 4 Server Reply Source Address Selection ...................... 3
+ 5 Resource Record Sets ....................................... 4
+ 6 Zone Cuts .................................................. 8
+ 7 SOA RRs .................................................... 10
+ 8 Time to Live (TTL) ......................................... 10
+ 9 The TC (truncated) header bit .............................. 11
+ 10 Naming issues .............................................. 11
+ 11 Name syntax ................................................ 13
+ 12 Security Considerations .................................... 14
+ 13 References ................................................. 14
+ 14 Acknowledgements ........................................... 15
+ 15 Authors' Addresses ......................................... 15
+
+
+
+
+2. Introduction
+
+ Several problem areas in the Domain Name System specification
+ [RFC1034, RFC1035] have been noted through the years [RFC1123]. This
+ document addresses several additional problem areas. The issues here
+ are independent. Those issues are the question of which source
+ address a multi-homed DNS server should use when replying to a query,
+ the issue of differing TTLs for DNS records with the same label,
+ class and type, and the issue of canonical names, what they are, how
+ CNAME records relate, what names are legal in what parts of the DNS,
+ and what is the valid syntax of a DNS name.
+
+ Clarifications to the DNS specification to avoid these problems are
+ made in this memo. A minor ambiguity in RFC1034 concerned with SOA
+ records is also corrected, as is one in the definition of the TTL
+ (Time To Live) and some possible confusion in use of the TC bit.
+
+
+
+
+
+
+
+
+
+
+
+
+Elz & Bush Standards Track [Page 2]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+3. Terminology
+
+ This memo does not use the oft used expressions MUST, SHOULD, MAY, or
+ their negative forms. In some sections it may seem that a
+ specification is worded mildly, and hence some may infer that the
+ specification is optional. That is not correct. Anywhere that this
+ memo suggests that some action should be carried out, or must be
+ carried out, or that some behaviour is acceptable, or not, that is to
+ be considered as a fundamental aspect of this specification,
+ regardless of the specific words used. If some behaviour or action
+ is truly optional, that will be clearly specified by the text.
+
+4. Server Reply Source Address Selection
+
+ Most, if not all, DNS clients, expect the address from which a reply
+ is received to be the same address as that to which the query
+ eliciting the reply was sent. This is true for servers acting as
+ clients for the purposes of recursive query resolution, as well as
+ simple resolver clients. The address, along with the identifier (ID)
+ in the reply is used for disambiguating replies, and filtering
+ spurious responses. This may, or may not, have been intended when
+ the DNS was designed, but is now a fact of life.
+
+ Some multi-homed hosts running DNS servers generate a reply using a
+ source address that is not the same as the destination address from
+ the client's request packet. Such replies will be discarded by the
+ client because the source address of the reply does not match that of
+ a host to which the client sent the original request. That is, it
+ appears to be an unsolicited response.
+
+4.1. UDP Source Address Selection
+
+ To avoid these problems, servers when responding to queries using UDP
+ must cause the reply to be sent with the source address field in the
+ IP header set to the address that was in the destination address
+ field of the IP header of the packet containing the query causing the
+ response. If this would cause the response to be sent from an IP
+ address that is not permitted for this purpose, then the response may
+ be sent from any legal IP address allocated to the server. That
+ address should be chosen to maximise the possibility that the client
+ will be able to use it for further queries. Servers configured in
+ such a way that not all their addresses are equally reachable from
+ all potential clients need take particular care when responding to
+ queries sent to anycast, multicast, or similar, addresses.
+
+
+
+
+
+
+
+Elz & Bush Standards Track [Page 3]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+4.2. Port Number Selection
+
+ Replies to all queries must be directed to the port from which they
+ were sent. When queries are received via TCP this is an inherent
+ part of the transport protocol. For queries received by UDP the
+ server must take note of the source port and use that as the
+ destination port in the response. Replies should always be sent from
+ the port to which they were directed. Except in extraordinary
+ circumstances, this will be the well known port assigned for DNS
+ queries [RFC1700].
+
+5. Resource Record Sets
+
+ Each DNS Resource Record (RR) has a label, class, type, and data. It
+ is meaningless for two records to ever have label, class, type and
+ data all equal - servers should suppress such duplicates if
+ encountered. It is however possible for most record types to exist
+ with the same label, class and type, but with different data. Such a
+ group of records is hereby defined to be a Resource Record Set
+ (RRSet).
+
+5.1. Sending RRs from an RRSet
+
+ A query for a specific (or non-specific) label, class, and type, will
+ always return all records in the associated RRSet - whether that be
+ one or more RRs. The response must be marked as "truncated" if the
+ entire RRSet will not fit in the response.
+
+5.2. TTLs of RRs in an RRSet
+
+ Resource Records also have a time to live (TTL). It is possible for
+ the RRs in an RRSet to have different TTLs. No uses for this have
+ been found that cannot be better accomplished in other ways. This
+ can, however, cause partial replies (not marked "truncated") from a
+ caching server, where the TTLs for some but not all the RRs in the
+ RRSet have expired.
+
+ Consequently the use of differing TTLs in an RRSet is hereby
+ deprecated, the TTLs of all RRs in an RRSet must be the same.
+
+ Should a client receive a response containing RRs from an RRSet with
+ differing TTLs, it should treat this as an error. If the RRSet
+ concerned is from a non-authoritative source for this data, the
+ client should simply ignore the RRSet, and if the values were
+ required, seek to acquire them from an authoritative source. Clients
+ that are configured to send all queries to one, or more, particular
+ servers should treat those servers as authoritative for this purpose.
+ Should an authoritative source send such a malformed RRSet, the
+
+
+
+Elz & Bush Standards Track [Page 4]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+ client should treat the RRs for all purposes as if all TTLs in the
+ RRSet had been set to the value of the lowest TTL in the RRSet. In
+ no case may a server send an RRSet with TTLs not all equal.
+
+5.3. DNSSEC Special Cases
+
+ Two of the record types added by DNS Security (DNSSEC) [RFC2065]
+ require special attention when considering the formation of Resource
+ Record Sets. Those are the SIG and NXT records. It should be noted
+ that DNS Security is still very new, and there is, as yet, little
+ experience with it. Readers should be prepared for the information
+ related to DNSSEC contained in this document to become outdated as
+ the DNS Security specification matures.
+
+5.3.1. SIG records and RRSets
+
+ A SIG record provides signature (validation) data for another RRSet
+ in the DNS. Where a zone has been signed, every RRSet in the zone
+ will have had a SIG record associated with it. The data type of the
+ RRSet is included in the data of the SIG RR, to indicate with which
+ particular RRSet this SIG record is associated. Were the rules above
+ applied, whenever a SIG record was included with a response to
+ validate that response, the SIG records for all other RRSets
+ associated with the appropriate node would also need to be included.
+ In some cases, this could be a very large number of records, not
+ helped by their being rather large RRs.
+
+ Thus, it is specifically permitted for the authority section to
+ contain only those SIG RRs with the "type covered" field equal to the
+ type field of an answer being returned. However, where SIG records
+ are being returned in the answer section, in response to a query for
+ SIG records, or a query for all records associated with a name
+ (type=ANY) the entire SIG RRSet must be included, as for any other RR
+ type.
+
+ Servers that receive responses containing SIG records in the
+ authority section, or (probably incorrectly) as additional data, must
+ understand that the entire RRSet has almost certainly not been
+ included. Thus, they must not cache that SIG record in a way that
+ would permit it to be returned should a query for SIG records be
+ received at that server. RFC2065 actually requires that SIG queries
+ be directed only to authoritative servers to avoid the problems that
+ could be caused here, and while servers exist that do not understand
+ the special properties of SIG records, this will remain necessary.
+ However, careful design of SIG record processing in new
+ implementations should permit this restriction to be relaxed in the
+ future, so resolvers do not need to treat SIG record queries
+ specially.
+
+
+
+Elz & Bush Standards Track [Page 5]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+ It has been occasionally stated that a received request for a SIG
+ record should be forwarded to an authoritative server, rather than
+ being answered from data in the cache. This is not necessary - a
+ server that has the knowledge of SIG as a special case for processing
+ this way would be better to correctly cache SIG records, taking into
+ account their characteristics. Then the server can determine when it
+ is safe to reply from the cache, and when the answer is not available
+ and the query must be forwarded.
+
+5.3.2. NXT RRs
+
+ Next Resource Records (NXT) are even more peculiar. There will only
+ ever be one NXT record in a zone for a particular label, so
+ superficially, the RRSet problem is trivial. However, at a zone cut,
+ both the parent zone, and the child zone (superzone and subzone in
+ RFC2065 terminology) will have NXT records for the same name. Those
+ two NXT records do not form an RRSet, even where both zones are
+ housed at the same server. NXT RRSets always contain just a single
+ RR. Where both NXT records are visible, two RRSets exist. However,
+ servers are not required to treat this as a special case when
+ receiving NXT records in a response. They may elect to notice the
+ existence of two different NXT RRSets, and treat that as they would
+ two different RRSets of any other type. That is, cache one, and
+ ignore the other. Security aware servers will need to correctly
+ process the NXT record in the received response though.
+
+5.4. Receiving RRSets
+
+ Servers must never merge RRs from a response with RRs in their cache
+ to form an RRSet. If a response contains data that would form an
+ RRSet with data in a server's cache the server must either ignore the
+ RRs in the response, or discard the entire RRSet currently in the
+ cache, as appropriate. Consequently the issue of TTLs varying
+ between the cache and a response does not cause concern, one will be
+ ignored. That is, one of the data sets is always incorrect if the
+ data from an answer differs from the data in the cache. The
+ challenge for the server is to determine which of the data sets is
+ correct, if one is, and retain that, while ignoring the other. Note
+ that if a server receives an answer containing an RRSet that is
+ identical to that in its cache, with the possible exception of the
+ TTL value, it may, optionally, update the TTL in its cache with the
+ TTL of the received answer. It should do this if the received answer
+ would be considered more authoritative (as discussed in the next
+ section) than the previously cached answer.
+
+
+
+
+
+
+
+Elz & Bush Standards Track [Page 6]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+5.4.1. Ranking data
+
+ When considering whether to accept an RRSet in a reply, or retain an
+ RRSet already in its cache instead, a server should consider the
+ relative likely trustworthiness of the various data. An
+ authoritative answer from a reply should replace cached data that had
+ been obtained from additional information in an earlier reply.
+ However additional information from a reply will be ignored if the
+ cache contains data from an authoritative answer or a zone file.
+
+ The accuracy of data available is assumed from its source.
+ Trustworthiness shall be, in order from most to least:
+
+ + Data from a primary zone file, other than glue data,
+ + Data from a zone transfer, other than glue,
+ + The authoritative data included in the answer section of an
+ authoritative reply.
+ + Data from the authority section of an authoritative answer,
+ + Glue from a primary zone, or glue from a zone transfer,
+ + Data from the answer section of a non-authoritative answer, and
+ non-authoritative data from the answer section of authoritative
+ answers,
+ + Additional information from an authoritative answer,
+ Data from the authority section of a non-authoritative answer,
+ Additional information from non-authoritative answers.
+
+ Note that the answer section of an authoritative answer normally
+ contains only authoritative data. However when the name sought is an
+ alias (see section 10.1.1) only the record describing that alias is
+ necessarily authoritative. Clients should assume that other records
+ may have come from the server's cache. Where authoritative answers
+ are required, the client should query again, using the canonical name
+ associated with the alias.
+
+ Unauthenticated RRs received and cached from the least trustworthy of
+ those groupings, that is data from the additional data section, and
+ data from the authority section of a non-authoritative answer, should
+ not be cached in such a way that they would ever be returned as
+ answers to a received query. They may be returned as additional
+ information where appropriate. Ignoring this would allow the
+ trustworthiness of relatively untrustworthy data to be increased
+ without cause or excuse.
+
+ When DNS security [RFC2065] is in use, and an authenticated reply has
+ been received and verified, the data thus authenticated shall be
+ considered more trustworthy than unauthenticated data of the same
+ type. Note that throughout this document, "authoritative" means a
+ reply with the AA bit set. DNSSEC uses trusted chains of SIG and KEY
+
+
+
+Elz & Bush Standards Track [Page 7]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+ records to determine the authenticity of data, the AA bit is almost
+ irrelevant. However DNSSEC aware servers must still correctly set
+ the AA bit in responses to enable correct operation with servers that
+ are not security aware (almost all currently).
+
+ Note that, glue excluded, it is impossible for data from two
+ correctly configured primary zone files, two correctly configured
+ secondary zones (data from zone transfers) or data from correctly
+ configured primary and secondary zones to ever conflict. Where glue
+ for the same name exists in multiple zones, and differs in value, the
+ nameserver should select data from a primary zone file in preference
+ to secondary, but otherwise may choose any single set of such data.
+ Choosing that which appears to come from a source nearer the
+ authoritative data source may make sense where that can be
+ determined. Choosing primary data over secondary allows the source
+ of incorrect glue data to be discovered more readily, when a problem
+ with such data exists. Where a server can detect from two zone files
+ that one or more are incorrectly configured, so as to create
+ conflicts, it should refuse to load the zones determined to be
+ erroneous, and issue suitable diagnostics.
+
+ "Glue" above includes any record in a zone file that is not properly
+ part of that zone, including nameserver records of delegated sub-
+ zones (NS records), address records that accompany those NS records
+ (A, AAAA, etc), and any other stray data that might appear.
+
+5.5. Sending RRSets (reprise)
+
+ A Resource Record Set should only be included once in any DNS reply.
+ It may occur in any of the Answer, Authority, or Additional
+ Information sections, as required. However it should not be repeated
+ in the same, or any other, section, except where explicitly required
+ by a specification. For example, an AXFR response requires the SOA
+ record (always an RRSet containing a single RR) be both the first and
+ last record of the reply. Where duplicates are required this way,
+ the TTL transmitted in each case must be the same.
+
+6. Zone Cuts
+
+ The DNS tree is divided into "zones", which are collections of
+ domains that are treated as a unit for certain management purposes.
+ Zones are delimited by "zone cuts". Each zone cut separates a
+ "child" zone (below the cut) from a "parent" zone (above the cut).
+ The domain name that appears at the top of a zone (just below the cut
+ that separates the zone from its parent) is called the zone's
+ "origin". The name of the zone is the same as the name of the domain
+ at the zone's origin. Each zone comprises that subset of the DNS
+ tree that is at or below the zone's origin, and that is above the
+
+
+
+Elz & Bush Standards Track [Page 8]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+ cuts that separate the zone from its children (if any). The
+ existence of a zone cut is indicated in the parent zone by the
+ existence of NS records specifying the origin of the child zone. A
+ child zone does not contain any explicit reference to its parent.
+
+6.1. Zone authority
+
+ The authoritative servers for a zone are enumerated in the NS records
+ for the origin of the zone, which, along with a Start of Authority
+ (SOA) record are the mandatory records in every zone. Such a server
+ is authoritative for all resource records in a zone that are not in
+ another zone. The NS records that indicate a zone cut are the
+ property of the child zone created, as are any other records for the
+ origin of that child zone, or any sub-domains of it. A server for a
+ zone should not return authoritative answers for queries related to
+ names in another zone, which includes the NS, and perhaps A, records
+ at a zone cut, unless it also happens to be a server for the other
+ zone.
+
+ Other than the DNSSEC cases mentioned immediately below, servers
+ should ignore data other than NS records, and necessary A records to
+ locate the servers listed in the NS records, that may happen to be
+ configured in a zone at a zone cut.
+
+6.2. DNSSEC issues
+
+ The DNS security mechanisms [RFC2065] complicate this somewhat, as
+ some of the new resource record types added are very unusual when
+ compared with other DNS RRs. In particular the NXT ("next") RR type
+ contains information about which names exist in a zone, and hence
+ which do not, and thus must necessarily relate to the zone in which
+ it exists. The same domain name may have different NXT records in
+ the parent zone and the child zone, and both are valid, and are not
+ an RRSet. See also section 5.3.2.
+
+ Since NXT records are intended to be automatically generated, rather
+ than configured by DNS operators, servers may, but are not required
+ to, retain all differing NXT records they receive regardless of the
+ rules in section 5.4.
+
+ For a secure parent zone to securely indicate that a subzone is
+ insecure, DNSSEC requires that a KEY RR indicating that the subzone
+ is insecure, and the parent zone's authenticating SIG RR(s) be
+ present in the parent zone, as they by definition cannot be in the
+ subzone. Where a subzone is secure, the KEY and SIG records will be
+ present, and authoritative, in that zone, but should also always be
+ present in the parent zone (if secure).
+
+
+
+
+Elz & Bush Standards Track [Page 9]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+ Note that in none of these cases should a server for the parent zone,
+ not also being a server for the subzone, set the AA bit in any
+ response for a label at a zone cut.
+
+7. SOA RRs
+
+ Three minor issues concerning the Start of Zone of Authority (SOA)
+ Resource Record need some clarification.
+
+7.1. Placement of SOA RRs in authoritative answers
+
+ RFC1034, in section 3.7, indicates that the authority section of an
+ authoritative answer may contain the SOA record for the zone from
+ which the answer was obtained. When discussing negative caching,
+ RFC1034 section 4.3.4 refers to this technique but mentions the
+ additional section of the response. The former is correct, as is
+ implied by the example shown in section 6.2.5 of RFC1034. SOA
+ records, if added, are to be placed in the authority section.
+
+7.2. TTLs on SOA RRs
+
+ It may be observed that in section 3.2.1 of RFC1035, which defines
+ the format of a Resource Record, that the definition of the TTL field
+ contains a throw away line which states that the TTL of an SOA record
+ should always be sent as zero to prevent caching. This is mentioned
+ nowhere else, and has not generally been implemented.
+ Implementations should not assume that SOA records will have a TTL of
+ zero, nor are they required to send SOA records with a TTL of zero.
+
+7.3. The SOA.MNAME field
+
+ It is quite clear in the specifications, yet seems to have been
+ widely ignored, that the MNAME field of the SOA record should contain
+ the name of the primary (master) server for the zone identified by
+ the SOA. It should not contain the name of the zone itself. That
+ information would be useless, as to discover it, one needs to start
+ with the domain name of the SOA record - that is the name of the
+ zone.
+
+8. Time to Live (TTL)
+
+ The definition of values appropriate to the TTL field in STD 13 is
+ not as clear as it could be, with respect to how many significant
+ bits exist, and whether the value is signed or unsigned. It is
+ hereby specified that a TTL value is an unsigned number, with a
+ minimum value of 0, and a maximum value of 2147483647. That is, a
+ maximum of 2^31 - 1. When transmitted, this value shall be encoded
+ in the less significant 31 bits of the 32 bit TTL field, with the
+
+
+
+Elz & Bush Standards Track [Page 10]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+ most significant, or sign, bit set to zero.
+
+ Implementations should treat TTL values received with the most
+ significant bit set as if the entire value received was zero.
+
+ Implementations are always free to place an upper bound on any TTL
+ received, and treat any larger values as if they were that upper
+ bound. The TTL specifies a maximum time to live, not a mandatory
+ time to live.
+
+9. The TC (truncated) header bit
+
+ The TC bit should be set in responses only when an RRSet is required
+ as a part of the response, but could not be included in its entirety.
+ The TC bit should not be set merely because some extra information
+ could have been included, but there was insufficient room. This
+ includes the results of additional section processing. In such cases
+ the entire RRSet that will not fit in the response should be omitted,
+ and the reply sent as is, with the TC bit clear. If the recipient of
+ the reply needs the omitted data, it can construct a query for that
+ data and send that separately.
+
+ Where TC is set, the partial RRSet that would not completely fit may
+ be left in the response. When a DNS client receives a reply with TC
+ set, it should ignore that response, and query again, using a
+ mechanism, such as a TCP connection, that will permit larger replies.
+
+10. Naming issues
+
+ It has sometimes been inferred from some sections of the DNS
+ specification [RFC1034, RFC1035] that a host, or perhaps an interface
+ of a host, is permitted exactly one authoritative, or official, name,
+ called the canonical name. There is no such requirement in the DNS.
+
+10.1. CNAME resource records
+
+ The DNS CNAME ("canonical name") record exists to provide the
+ canonical name associated with an alias name. There may be only one
+ such canonical name for any one alias. That name should generally be
+ a name that exists elsewhere in the DNS, though there are some rare
+ applications for aliases with the accompanying canonical name
+ undefined in the DNS. An alias name (label of a CNAME record) may,
+ if DNSSEC is in use, have SIG, NXT, and KEY RRs, but may have no
+ other data. That is, for any label in the DNS (any domain name)
+ exactly one of the following is true:
+
+
+
+
+
+
+Elz & Bush Standards Track [Page 11]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+ + one CNAME record exists, optionally accompanied by SIG, NXT, and
+ KEY RRs,
+ + one or more records exist, none being CNAME records,
+ + the name exists, but has no associated RRs of any type,
+ + the name does not exist at all.
+
+10.1.1. CNAME terminology
+
+ It has been traditional to refer to the label of a CNAME record as "a
+ CNAME". This is unfortunate, as "CNAME" is an abbreviation of
+ "canonical name", and the label of a CNAME record is most certainly
+ not a canonical name. It is, however, an entrenched usage. Care
+ must therefore be taken to be very clear whether the label, or the
+ value (the canonical name) of a CNAME resource record is intended.
+ In this document, the label of a CNAME resource record will always be
+ referred to as an alias.
+
+10.2. PTR records
+
+ Confusion about canonical names has lead to a belief that a PTR
+ record should have exactly one RR in its RRSet. This is incorrect,
+ the relevant section of RFC1034 (section 3.6.2) indicates that the
+ value of a PTR record should be a canonical name. That is, it should
+ not be an alias. There is no implication in that section that only
+ one PTR record is permitted for a name. No such restriction should
+ be inferred.
+
+ Note that while the value of a PTR record must not be an alias, there
+ is no requirement that the process of resolving a PTR record not
+ encounter any aliases. The label that is being looked up for a PTR
+ value might have a CNAME record. That is, it might be an alias. The
+ value of that CNAME RR, if not another alias, which it should not be,
+ will give the location where the PTR record is found. That record
+ gives the result of the PTR type lookup. This final result, the
+ value of the PTR RR, is the label which must not be an alias.
+
+10.3. MX and NS records
+
+ The domain name used as the value of a NS resource record, or part of
+ the value of a MX resource record must not be an alias. Not only is
+ the specification clear on this point, but using an alias in either
+ of these positions neither works as well as might be hoped, nor well
+ fulfills the ambition that may have led to this approach. This
+ domain name must have as its value one or more address records.
+ Currently those will be A records, however in the future other record
+ types giving addressing information may be acceptable. It can also
+ have other RRs, but never a CNAME RR.
+
+
+
+
+Elz & Bush Standards Track [Page 12]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+ Searching for either NS or MX records causes "additional section
+ processing" in which address records associated with the value of the
+ record sought are appended to the answer. This helps avoid needless
+ extra queries that are easily anticipated when the first was made.
+
+ Additional section processing does not include CNAME records, let
+ alone the address records that may be associated with the canonical
+ name derived from the alias. Thus, if an alias is used as the value
+ of an NS or MX record, no address will be returned with the NS or MX
+ value. This can cause extra queries, and extra network burden, on
+ every query. It is trivial for the DNS administrator to avoid this
+ by resolving the alias and placing the canonical name directly in the
+ affected record just once when it is updated or installed. In some
+ particular hard cases the lack of the additional section address
+ records in the results of a NS lookup can cause the request to fail.
+
+11. Name syntax
+
+ Occasionally it is assumed that the Domain Name System serves only
+ the purpose of mapping Internet host names to data, and mapping
+ Internet addresses to host names. This is not correct, the DNS is a
+ general (if somewhat limited) hierarchical database, and can store
+ almost any kind of data, for almost any purpose.
+
+ The DNS itself places only one restriction on the particular labels
+ that can be used to identify resource records. That one restriction
+ relates to the length of the label and the full name. The length of
+ any one label is limited to between 1 and 63 octets. A full domain
+ name is limited to 255 octets (including the separators). The zero
+ length full name is defined as representing the root of the DNS tree,
+ and is typically written and displayed as ".". Those restrictions
+ aside, any binary string whatever can be used as the label of any
+ resource record. Similarly, any binary string can serve as the value
+ of any record that includes a domain name as some or all of its value
+ (SOA, NS, MX, PTR, CNAME, and any others that may be added).
+ Implementations of the DNS protocols must not place any restrictions
+ on the labels that can be used. In particular, DNS servers must not
+ refuse to serve a zone because it contains labels that might not be
+ acceptable to some DNS client programs. A DNS server may be
+ configurable to issue warnings when loading, or even to refuse to
+ load, a primary zone containing labels that might be considered
+ questionable, however this should not happen by default.
+
+ Note however, that the various applications that make use of DNS data
+ can have restrictions imposed on what particular values are
+ acceptable in their environment. For example, that any binary label
+ can have an MX record does not imply that any binary name can be used
+ as the host part of an e-mail address. Clients of the DNS can impose
+
+
+
+Elz & Bush Standards Track [Page 13]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+ whatever restrictions are appropriate to their circumstances on the
+ values they use as keys for DNS lookup requests, and on the values
+ returned by the DNS. If the client has such restrictions, it is
+ solely responsible for validating the data from the DNS to ensure
+ that it conforms before it makes any use of that data.
+
+ See also [RFC1123] section 6.1.3.5.
+
+12. Security Considerations
+
+ This document does not consider security.
+
+ In particular, nothing in section 4 is any way related to, or useful
+ for, any security related purposes.
+
+ Section 5.4.1 is also not related to security. Security of DNS data
+ will be obtained by the Secure DNS [RFC2065], which is mostly
+ orthogonal to this memo.
+
+ It is not believed that anything in this document adds to any
+ security issues that may exist with the DNS, nor does it do anything
+ to that will necessarily lessen them. Correct implementation of the
+ clarifications in this document might play some small part in
+ limiting the spread of non-malicious bad data in the DNS, but only
+ DNSSEC can help with deliberate attempts to subvert DNS data.
+
+13. References
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts - application
+ and support", STD 3, RFC 1123, January 1989.
+
+ [RFC1700] Reynolds, J., Postel, J., "Assigned Numbers",
+ STD 2, RFC 1700, October 1994.
+
+ [RFC2065] Eastlake, D., Kaufman, C., "Domain Name System Security
+ Extensions", RFC 2065, January 1997.
+
+
+
+
+
+
+
+
+
+Elz & Bush Standards Track [Page 14]
+
+RFC 2181 Clarifications to the DNS Specification July 1997
+
+
+14. Acknowledgements
+
+ This memo arose from discussions in the DNSIND working group of the
+ IETF in 1995 and 1996, the members of that working group are largely
+ responsible for the ideas captured herein. Particular thanks to
+ Donald E. Eastlake, 3rd, and Olafur Gudmundsson, for help with the
+ DNSSEC issues in this document, and to John Gilmore for pointing out
+ where the clarifications were not necessarily clarifying. Bob Halley
+ suggested clarifying the placement of SOA records in authoritative
+ answers, and provided the references. Michael Patton, as usual, and
+ Mark Andrews, Alan Barrett and Stan Barber provided much assistance
+ with many details. Josh Littlefield helped make sure that the
+ clarifications didn't cause problems in some irritating corner cases.
+
+15. Authors' Addresses
+
+ Robert Elz
+ Computer Science
+ University of Melbourne
+ Parkville, Victoria, 3052
+ Australia.
+
+ EMail: kre@munnari.OZ.AU
+
+
+ Randy Bush
+ RGnet, Inc.
+ 5147 Crystal Springs Drive NE
+ Bainbridge Island, Washington, 98110
+ United States.
+
+ EMail: randy@psg.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Elz & Bush Standards Track [Page 15]
diff --git a/doc/rfc/rfc2230.txt b/doc/rfc/rfc2230.txt
new file mode 100644
index 0000000..03995fe
--- /dev/null
+++ b/doc/rfc/rfc2230.txt
@@ -0,0 +1,619 @@
+
+
+
+
+
+
+Network Working Group R. Atkinson
+Request for Comments: 2230 NRL
+Category: Informational November 1997
+
+
+ Key Exchange Delegation Record for the DNS
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1997). All Rights Reserved.
+
+ABSTRACT
+
+ This note describes a mechanism whereby authorisation for one node to
+ act as key exchanger for a second node is delegated and made
+ available via the Secure DNS. This mechanism is intended to be used
+ only with the Secure DNS. It can be used with several security
+ services. For example, a system seeking to use IP Security [RFC-
+ 1825, RFC-1826, RFC-1827] to protect IP packets for a given
+ destination can use this mechanism to determine the set of authorised
+ remote key exchanger systems for that destination.
+
+1. INTRODUCTION
+
+
+ The Domain Name System (DNS) is the standard way that Internet nodes
+ locate information about addresses, mail exchangers, and other data
+ relating to remote Internet nodes. [RFC-1035, RFC-1034] More
+ recently, Eastlake and Kaufman have defined standards-track security
+ extensions to the DNS. [RFC-2065] These security extensions can be
+ used to authenticate signed DNS data records and can also be used to
+ store signed public keys in the DNS.
+
+ The KX record is useful in providing an authenticatible method of
+ delegating authorisation for one node to provide key exchange
+ services on behalf of one or more, possibly different, nodes. This
+ note specifies the syntax and semantics of the KX record, which is
+ currently in limited deployment in certain IP-based networks. The
+
+
+
+
+
+
+
+Atkinson Informational [Page 1]
+
+RFC 2230 DNS Key Exchange Delegation Record November 1997
+
+
+ reader is assumed to be familiar with the basics of DNS, including
+ familiarity with [RFC-1035, RFC-1034]. This document is not on the
+ IETF standards-track and does not specify any level of standard.
+ This document merely provides information for the Internet community.
+
+1.1 Identity Terminology
+
+ This document relies upon the concept of "identity domination". This
+ concept might be new to the reader and so is explained in this
+ section. The subject of endpoint naming for security associations
+ has historically been somewhat contentious. This document takes no
+ position on what forms of identity should be used. In a network,
+ there are several forms of identity that are possible.
+
+ For example, IP Security has defined notions of identity that
+ include: IP Address, IP Address Range, Connection ID, Fully-Qualified
+ Domain Name (FQDN), and User with Fully Qualified Domain Name (USER
+ FQDN).
+
+ A USER FQDN identity dominates a FQDN identity. A FQDN identity in
+ turn dominates an IP Address identity. Similarly, a Connection ID
+ dominates an IP Address identity. An IP Address Range dominates each
+ IP Address identity for each IP address within that IP address range.
+ Also, for completeness, an IP Address identity is considered to
+ dominate itself.
+
+2. APPROACH
+
+ This document specifies a new kind of DNS Resource Record (RR), known
+ as the Key Exchanger (KX) record. A Key Exchanger Record has the
+ mnemonic "KX" and the type code of 36. Each KX record is associated
+ with a fully-qualified domain name. The KX record is modeled on the
+ MX record described in [Part86]. Any given domain, subdomain, or host
+ entry in the DNS might have a KX record.
+
+2.1 IPsec Examples
+
+ In these two examples, let S be the originating node and let D be the
+ destination node. S2 is another node on the same subnet as S. D2 is
+ another node on the same subnet as D. R1 and R2 are IPsec-capable
+ routers. The path from S to D goes via first R1 and later R2. The
+ return path from D to S goes via first R2 and later R1.
+
+ IETF-standard IP Security uses unidirectional Security Associations
+ [RFC-1825]. Therefore, a typical IP session will use a pair of
+ related Security Associations, one in each direction. The examples
+ below talk about how to setup an example Security Association, but in
+ practice a pair of matched Security Associations will normally be
+
+
+
+Atkinson Informational [Page 2]
+
+RFC 2230 DNS Key Exchange Delegation Record November 1997
+
+
+ used.
+
+2.1.1 Subnet-to-Subnet Example
+
+ If neither S nor D implements IPsec, security can still be provided
+ between R1 and R2 by building a secure tunnel. This can use either
+ AH or ESP.
+
+ S ---+ +----D
+ | |
+ +- R1 -----[zero or more routers]-------R2-+
+ | |
+ S2---+ +----D2
+
+ Figure 1: Network Diagram for Subnet-to-Subnet Example
+
+ In this example, R1 makes the policy decision to provide the IPsec
+ service for traffic from R1 destined for R2. Once R1 has decided
+ that the packet from S to D should be protected, it performs a secure
+ DNS lookup for the records associated with domain D. If R1 only
+ knows the IP address for D, then a secure reverse DNS lookup will be
+ necessary to determine the domain D, before that forward secure DNS
+ lookup for records associated with domain D. If these DNS records of
+ domain D include a KX record for the IPsec service, then R1 knows
+ which set of nodes are authorised key exchanger nodes for the
+ destination D.
+
+ In this example, let there be at least one KX record for D and let
+ the most preferred KX record for D point at R2. R1 then selects a
+ key exchanger (in this example, R2) for D from the list obtained from
+ the secure DNS. Then R1 initiates a key management session with that
+ key exchanger (in this example, R2) to setup an IPsec Security
+ Association between R1 and D. In this example, R1 knows (either by
+ seeing an outbound packet arriving from S destined to D or via other
+ methods) that S will be sending traffic to D. In this example R1's
+ policy requires that traffic from S to D should be segregated at
+ least on a host-to-host basis, so R1 desires an IPsec Security
+ Association with source identity that dominates S, proxy identity
+ that dominates R1, and destination identity that dominates R2.
+
+ In turn, R2 is able to authenticate the delegation of Key Exchanger
+ authorisation for target S to R1 by making an authenticated forward
+ DNS lookup for KX records associated with S and verifying that at
+ least one such record points to R1. The identity S is typically
+ given to R2 as part of the key management process between R1 and R2.
+
+
+
+
+
+
+Atkinson Informational [Page 3]
+
+RFC 2230 DNS Key Exchange Delegation Record November 1997
+
+
+ If D initially only knows the IP address of S, then it will need to
+ perform a secure reverse DNS lookup to obtain the fully-qualified
+ domain name for S prior to that secure forward DNS lookup.
+
+ If R2 does not receive an authenticated DNS response indicating that
+ R1 is an authorised key exchanger for S, then D will not accept the
+ SA negotiation from R1 on behalf of identity S.
+
+ If the proposed IPsec Security Association is acceptable to both R1
+ and R2, each of which might have separate policies, then they create
+ that IPsec Security Association via Key Management.
+
+ Note that for unicast traffic, Key Management will typically also
+ setup a separate (but related) IPsec Security Association for the
+ return traffic. That return IPsec Security Association will have
+ equivalent identities. In this example, that return IPsec Security
+ Association will have a source identity that dominates D, a proxy
+ identity that dominates R2, and a destination identity that dominates
+ R1.
+
+ Once the IPsec Security Association has been created, then R1 uses it
+ to protect traffic from S destined for D via a secure tunnel that
+ originates at R1 and terminates at R2. For the case of unicast, R2
+ will use the return IPsec Security Association to protect traffic
+ from D destined for S via a secure tunnel that originates at R2 and
+ terminates at R1.
+
+2.1.2 Subnet-to-Host Example
+
+ Consider the case where D and R1 implement IPsec, but S does not
+ implement IPsec, which is an interesting variation on the previous
+ example. This example is shown in Figure 2 below.
+
+ S ---+
+ |
+ +- R1 -----[zero or more routers]-------D
+ |
+ S2---+
+
+ Figure 2: Network Diagram for Subnet-to-Host Example
+
+ In this example, R1 makes the policy decision that IP Security is
+ needed for the packet travelling from S to D. Then, R1 performs the
+ secure DNS lookup for D and determines that D is its own key
+ exchanger, either from the existence of a KX record for D pointing to
+ D or from an authenticated DNS response indicating that no KX record
+ exists for D. If R1 does not initially know the domain name of D,
+ then prior to the above forward secure DNS lookup, R1 performs a
+
+
+
+Atkinson Informational [Page 4]
+
+RFC 2230 DNS Key Exchange Delegation Record November 1997
+
+
+ secure reverse DNS lookup on the IP address of D to determine the
+ fully-qualified domain name for that IP address. R1 then initiates
+ key management with D to create an IPsec Security Association on
+ behalf of S.
+
+ In turn, D can verify that R1 is authorised to create an IPsec
+ Security Association on behalf of S by performing a DNS KX record
+ lookup for target S. R1 usually provides identity S to D via key
+ management. If D only has the IP address of S, then D will need to
+ perform a secure reverse lookup on the IP address of S to determine
+ domain name S prior to the secure forward DNS lookup on S to locate
+ the KX records for S.
+
+ If D does not receive an authenticated DNS response indicating that
+ R1 is an authorised key exchanger for S, then D will not accept the
+ SA negotiation from R1 on behalf of identity S.
+
+ If the IPsec Security Association is successfully established between
+ R1 and D, that IPsec Security Association has a source identity that
+ dominates S's IP address, a proxy identity that dominates R1's IP
+ address, and a destination identity that dominates D's IP address.
+
+ Finally, R1 begins providing the security service for packets from S
+ that transit R1 destined for D. When D receives such packets, D
+ examines the SA information during IPsec input processing and sees
+ that R1's address is listed as valid proxy address for that SA and
+ that S is the source address for that SA. Hence, D knows at input
+ processing time that R1 is authorised to provide security on behalf
+ of S. Therefore packets coming from R1 with valid IP security that
+ claim to be from S are trusted by D to have really come from S.
+
+2.1.3 Host to Subnet Example
+
+ Now consider the above case from D's perspective (i.e. where D is
+ sending IP packets to S). This variant is sometimes known as the
+ Mobile Host or "roadwarrier" case. The same basic concepts apply, but
+ the details are covered here in hope of improved clarity.
+
+ S ---+
+ |
+ +- R1 -----[zero or more routers]-------D
+ |
+ S2---+
+
+ Figure 3: Network Diagram for Host-to-Subnet Example
+
+
+
+
+
+
+Atkinson Informational [Page 5]
+
+RFC 2230 DNS Key Exchange Delegation Record November 1997
+
+
+ In this example, D makes the policy decision that IP Security is
+ needed for the packets from D to S. Then D performs the secure DNS
+ lookup for S and discovers that a KX record for S exists and points
+ at R1. If D only has the IP address of S, then it performs a secure
+ reverse DNS lookup on the IP address of S prior to the forward secure
+ DNS lookup for S.
+
+ D then initiates key management with R1, where R1 is acting on behalf
+ of S, to create an appropriate Security Association. Because D is
+ acting as its own key exchanger, R1 does not need to perform a secure
+ DNS lookup for KX records associated with D.
+
+ D and R1 then create an appropriate IPsec Security Security
+ Association. This IPsec Security Association is setup as a secure
+ tunnel with a source identity that dominates D's IP Address and a
+ destination identity that dominates R1's IP Address. Because D
+ performs IPsec for itself, no proxy identity is needed in this IPsec
+ Security Association. If the proxy identity is non-null in this
+ situation, then the proxy identity must dominate D's IP Address.
+
+ Finally, D sends secured IP packets to R1. R1 receives those
+ packets, provides IPsec input processing (including appropriate
+ inner/outer IP address validation), and forwards valid packets along
+ to S.
+
+2.2 Other Examples
+
+ This mechanism can be extended for use with other services as well.
+ To give some insight into other possible uses, this section discusses
+ use of KX records in environments using a Key Distribution Center
+ (KDC), such as Kerberos [KN93], and a possible use of KX records in
+ conjunction with mobile nodes accessing the network via a dialup
+ service.
+
+2.2.1 KDC Examples
+
+ This example considers the situation of a destination node
+ implementing IPsec that can only obtain its Security Association
+ information from a Key Distribution Center (KDC). Let the KDC
+ implement both the KDC protocol and also a non-KDC key management
+ protocol (e.g. ISAKMP). In such a case, each client node of the KDC
+ might have its own KX record pointing at the KDC so that nodes not
+ implementing the KDC protocol can still create Security Associations
+ with each of the client nodes of the KDC.
+
+ In the event the session initiator were not using the KDC but the
+ session target was an IPsec node that only used the KDC, the
+ initiator would find the KX record for the target pointing at the
+
+
+
+Atkinson Informational [Page 6]
+
+RFC 2230 DNS Key Exchange Delegation Record November 1997
+
+
+ KDC. Then, the external key management exchange (e.g. ISAKMP) would
+ be between the initiator and the KDC. Then the KDC would distribute
+ the IPsec SA to the KDC-only IPsec node using the KDC. The IPsec
+ traffic itself could travel directly between the initiator and the
+ destination node.
+
+ In the event the initiator node could only use the KDC and the target
+ were not using the KDC, the initiator would send its request for a
+ key to the KDC. The KDC would then initiate an external key
+ management exchange (e.g. ISAKMP) with a node that the target's KX
+ record(s) pointed to, on behalf of the initiator node.
+
+ The target node could verify that the KDC were allowed to proxy for
+ the initiator node by looking up the KX records for the initiator
+ node and finding a KX record for the initiator that listed the KDC.
+
+ Then the external key exchange would be performed between the KDC and
+ the target node. Then the KDC would distribute the resulting IPsec
+ Security Association to the initiator. Again, IPsec traffic itself
+ could travel directly between the initiator and the destination.
+
+2.2.2 Dial-Up Host Example
+
+ This example outlines a possible use of KX records with mobile hosts
+ that dial into the network via PPP and are dynamically assigned an IP
+ address and domain-name at dial-in time.
+
+ Consider the situation where each mobile node is dynamically assigned
+ both a domain name and an IP address at the time that node dials into
+ the network. Let the policy require that each mobile node act as its
+ own Key Exchanger. In this case, it is important that dial-in nodes
+ use addresses from one or more well known IP subnets or address pools
+ dedicated to dial-in access. If that is true, then no KX record or
+ other action is needed to ensure that each node will act as its own
+ Key Exchanger because lack of a KX record indicates that the node is
+ its own Key Exchanger.
+
+ Consider the situation where the mobile node's domain name remains
+ constant but its IP address changes. Let the policy require that
+ each mobile node act as its own Key Exchanger. In this case, there
+ might be operational problems when another node attempts to perform a
+ secure reverse DNS lookup on the IP address to determine the
+ corresponding domain name. The authenticated DNS binding (in the
+ form of a PTR record) between the mobile node's currently assigned IP
+ address and its permanent domain name will need to be securely
+ updated each time the node is assigned a new IP address. There are
+ no mechanisms for accomplishing this that are both IETF-standard and
+ widely deployed as of the time this note was written. Use of Dynamic
+
+
+
+Atkinson Informational [Page 7]
+
+RFC 2230 DNS Key Exchange Delegation Record November 1997
+
+
+ DNS Update without authentication is a significant security risk and
+ hence is not recommended for this situation.
+
+3. SYNTAX OF KX RECORD
+
+ A KX record has the DNS TYPE of "KX" and a numeric value of 36. A KX
+ record is a member of the Internet ("IN") CLASS in the DNS. Each KX
+ record is associated with a <domain-name> entry in the DNS. A KX
+ record has the following textual syntax:
+
+ <domain-name> IN KX <preference> <domain-name>
+
+ For this description, let the <domain-name> item to the left of the
+ "KX" string be called <domain-name 1> and the <domain-name> item to
+ the right of the "KX" string be called <domain-name 2>. <preference>
+ is a non-negative integer.
+
+ Internet nodes about to initiate a key exchange with <domain-name 1>
+ should instead contact <domain-name 2> to initiate the key exchange
+ for a security service between the initiator and <domain-name 2>. If
+ more than one KX record exists for <domain-name 1>, then the
+ <preference> field is used to indicate preference among the systems
+ delegated to. Lower values are preferred over higher values. The
+ <domain-name 2> is authorised to provide key exchange services on
+ behalf of <domain-name 1>. The <domain-name 2> MUST have a CNAME
+ record, an A record, or an AAAA record associated with it.
+
+3.1 KX RDATA format
+
+ The KX DNS record has the following RDATA format:
+
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PREFERENCE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / EXCHANGER /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ where:
+
+ PREFERENCE A 16 bit non-negative integer which specifies the
+ preference given to this RR among other KX records
+ at the same owner. Lower values are preferred.
+
+ EXCHANGER A <domain-name> which specifies a host willing to
+ act as a mail exchange for the owner name.
+
+
+
+
+
+Atkinson Informational [Page 8]
+
+RFC 2230 DNS Key Exchange Delegation Record November 1997
+
+
+ KX records MUST cause type A additional section processing for the
+ host specified by EXCHANGER. In the event that the host processing
+ the DNS transaction supports IPv6, KX records MUST also cause type
+ AAAA additional section processing.
+
+ The KX RDATA field MUST NOT be compressed.
+
+4. SECURITY CONSIDERATIONS
+
+ KX records MUST always be signed using the method(s) defined by the
+ DNS Security extensions specified in [RFC-2065]. All unsigned KX
+ records MUST be ignored because of the security vulnerability caused
+ by assuming that unsigned records are valid. All signed KX records
+ whose signatures do not correctly validate MUST be ignored because of
+ the potential security vulnerability in trusting an invalid KX
+ record.
+
+ KX records MUST be ignored by systems not implementing Secure DNS
+ because such systems have no mechanism to authenticate the KX record.
+
+ If a node does not have a permanent DNS entry and some form of
+ Dynamic DNS Update is in use, then those dynamic DNS updates MUST be
+ fully authenticated to prevent an adversary from injecting false DNS
+ records (especially the KX, A, and PTR records) into the Domain Name
+ System. If false records were inserted into the DNS without being
+ signed by the Secure DNS mechanisms, then a denial-of-service attack
+ results. If false records were inserted into the DNS and were
+ (erroneously) signed by the signing authority, then an active attack
+ results.
+
+ Myriad serious security vulnerabilities can arise if the restrictions
+ throuhout this document are not strictly adhered to. Implementers
+ should carefully consider the openly published issues relating to DNS
+ security [Bell95,Vixie95] as they build their implementations.
+ Readers should also consider the security considerations discussed in
+ the DNS Security Extensions document [RFC-2065].
+
+5. REFERENCES
+
+
+ [RFC-1825] Atkinson, R., "IP Authentication Header", RFC 1826,
+ August 1995.
+
+ [RFC-1827] Atkinson, R., "IP Encapsulating Security Payload",
+ RFC 1827, August 1995.
+
+
+
+
+
+
+Atkinson Informational [Page 9]
+
+RFC 2230 DNS Key Exchange Delegation Record November 1997
+
+
+ [Bell95] Bellovin, S., "Using the Domain Name System for System
+ Break-ins", Proceedings of 5th USENIX UNIX Security
+ Symposium, USENIX Association, Berkeley, CA, June 1995.
+ ftp://ftp.research.att.com/dist/smb/dnshack.ps
+
+ [RFC-2065] Eastlake, D., and C. Kaufman, "Domain Name System
+ Security Extensions", RFC 2065, January 1997.
+
+ [RFC-1510] Kohl J., and C. Neuman, "The Kerberos Network
+ Authentication Service", RFC 1510, September 1993.
+
+ [RFC-1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC-1034] Mockapetris, P., "Domain names - concepts and
+ facilities", STD 13, RFC 1034, November 1987.
+
+ [Vixie95] P. Vixie, "DNS and BIND Security Issues", Proceedings of
+ the 5th USENIX UNIX Security Symposium, USENIX
+ Association, Berkeley, CA, June 1995.
+ ftp://ftp.vix.com/pri/vixie/bindsec.psf
+
+ACKNOWLEDGEMENTS
+
+ Development of this DNS record was primarily performed during 1993
+ through 1995. The author's work on this was sponsored jointly by the
+ Computing Systems Technology Office (CSTO) of the Advanced Research
+ Projects Agency (ARPA) and by the Information Security Program Office
+ (PD71E), Space & Naval Warface Systems Command (SPAWAR). In that
+ era, Dave Mihelcic and others provided detailed review and
+ constructive feedback. More recently, Bob Moscowitz and Todd Welch
+ provided detailed review and constructive feedback of a work in
+ progress version of this document.
+
+AUTHOR'S ADDRESS
+
+ Randall Atkinson
+ Code 5544
+ Naval Research Laboratory
+ 4555 Overlook Avenue, SW
+ Washington, DC 20375-5337
+
+ Phone: (DSN) 354-8590
+ EMail: atkinson@itd.nrl.navy.mil
+
+
+
+
+
+
+
+Atkinson Informational [Page 10]
+
+RFC 2230 DNS Key Exchange Delegation Record November 1997
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1997). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implmentation may be prepared, copied, published
+ andand distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Atkinson Informational [Page 11]
+
diff --git a/doc/rfc/rfc2308.txt b/doc/rfc/rfc2308.txt
new file mode 100644
index 0000000..9123a95
--- /dev/null
+++ b/doc/rfc/rfc2308.txt
@@ -0,0 +1,1067 @@
+
+
+
+
+
+
+Network Working Group M. Andrews
+Request for Comments: 2308 CSIRO
+Updates: 1034, 1035 March 1998
+Category: Standards Track
+
+
+ Negative Caching of DNS Queries (DNS NCACHE)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+Abstract
+
+ [RFC1034] provided a description of how to cache negative responses.
+ It however had a fundamental flaw in that it did not allow a name
+ server to hand out those cached responses to other resolvers, thereby
+ greatly reducing the effect of the caching. This document addresses
+ issues raise in the light of experience and replaces [RFC1034 Section
+ 4.3.4].
+
+ Negative caching was an optional part of the DNS specification and
+ deals with the caching of the non-existence of an RRset [RFC2181] or
+ domain name.
+
+ Negative caching is useful as it reduces the response time for
+ negative answers. It also reduces the number of messages that have
+ to be sent between resolvers and name servers hence overall network
+ traffic. A large proportion of DNS traffic on the Internet could be
+ eliminated if all resolvers implemented negative caching. With this
+ in mind negative caching should no longer be seen as an optional part
+ of a DNS resolver.
+
+
+
+
+
+
+
+
+
+
+
+Andrews Standards Track [Page 1]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+1 - Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+ "Negative caching" - the storage of knowledge that something does not
+ exist. We can store the knowledge that a record has a particular
+ value. We can also do the reverse, that is, to store the knowledge
+ that a record does not exist. It is the storage of knowledge that
+ something does not exist, cannot or does not give an answer that we
+ call negative caching.
+
+ "QNAME" - the name in the query section of an answer, or where this
+ resolves to a CNAME, or CNAME chain, the data field of the last
+ CNAME. The last CNAME in this sense is that which contains a value
+ which does not resolve to another CNAME. Implementations should note
+ that including CNAME records in responses in order, so that the first
+ has the label from the query section, and then each in sequence has
+ the label from the data section of the previous (where more than one
+ CNAME is needed) allows the sequence to be processed in one pass, and
+ considerably eases the task of the receiver. Other relevant records
+ (such as SIG RRs [RFC2065]) can be interspersed amongst the CNAMEs.
+
+ "NXDOMAIN" - an alternate expression for the "Name Error" RCODE as
+ described in [RFC1035 Section 4.1.1] and the two terms are used
+ interchangeably in this document.
+
+ "NODATA" - a pseudo RCODE which indicates that the name is valid, for
+ the given class, but are no records of the given type. A NODATA
+ response has to be inferred from the answer.
+
+ "FORWARDER" - a nameserver used to resolve queries instead of
+ directly using the authoritative nameserver chain. The forwarder
+ typically either has better access to the internet, or maintains a
+ bigger cache which may be shared amongst many resolvers. How a
+ server is identified as a FORWARDER, or knows it is a FORWARDER is
+ outside the scope of this document. However if you are being used as
+ a forwarder the query will have the recursion desired flag set.
+
+ An understanding of [RFC1034], [RFC1035] and [RFC2065] is expected
+ when reading this document.
+
+
+
+
+
+
+
+
+
+Andrews Standards Track [Page 2]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+2 - Negative Responses
+
+ The most common negative responses indicate that a particular RRset
+ does not exist in the DNS. The first sections of this document deal
+ with this case. Other negative responses can indicate failures of a
+ nameserver, those are dealt with in section 7 (Other Negative
+ Responses).
+
+ A negative response is indicated by one of the following conditions:
+
+2.1 - Name Error
+
+ Name errors (NXDOMAIN) are indicated by the presence of "Name Error"
+ in the RCODE field. In this case the domain referred to by the QNAME
+ does not exist. Note: the answer section may have SIG and CNAME RRs
+ and the authority section may have SOA, NXT [RFC2065] and SIG RRsets.
+
+ It is possible to distinguish between a referral and a NXDOMAIN
+ response by the presense of NXDOMAIN in the RCODE regardless of the
+ presence of NS or SOA records in the authority section.
+
+ NXDOMAIN responses can be categorised into four types by the contents
+ of the authority section. These are shown below along with a
+ referral for comparison. Fields not mentioned are not important in
+ terms of the examples.
+
+ NXDOMAIN RESPONSE: TYPE 1.
+
+ Header:
+ RDCODE=NXDOMAIN
+ Query:
+ AN.EXAMPLE. A
+ Answer:
+ AN.EXAMPLE. CNAME TRIPPLE.XX.
+ Authority:
+ XX. SOA NS1.XX. HOSTMASTER.NS1.XX. ....
+ XX. NS NS1.XX.
+ XX. NS NS2.XX.
+ Additional:
+ NS1.XX. A 127.0.0.2
+ NS2.XX. A 127.0.0.3
+
+ NXDOMAIN RESPONSE: TYPE 2.
+
+ Header:
+ RDCODE=NXDOMAIN
+ Query:
+ AN.EXAMPLE. A
+
+
+
+Andrews Standards Track [Page 3]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ Answer:
+ AN.EXAMPLE. CNAME TRIPPLE.XX.
+ Authority:
+ XX. SOA NS1.XX. HOSTMASTER.NS1.XX. ....
+ Additional:
+ <empty>
+
+ NXDOMAIN RESPONSE: TYPE 3.
+
+ Header:
+ RDCODE=NXDOMAIN
+ Query:
+ AN.EXAMPLE. A
+ Answer:
+ AN.EXAMPLE. CNAME TRIPPLE.XX.
+ Authority:
+ <empty>
+ Additional:
+ <empty>
+
+ NXDOMAIN RESPONSE: TYPE 4
+
+ Header:
+ RDCODE=NXDOMAIN
+ Query:
+ AN.EXAMPLE. A
+ Answer:
+ AN.EXAMPLE. CNAME TRIPPLE.XX.
+ Authority:
+ XX. NS NS1.XX.
+ XX. NS NS2.XX.
+ Additional:
+ NS1.XX. A 127.0.0.2
+ NS2.XX. A 127.0.0.3
+
+ REFERRAL RESPONSE.
+
+ Header:
+ RDCODE=NOERROR
+ Query:
+ AN.EXAMPLE. A
+ Answer:
+ AN.EXAMPLE. CNAME TRIPPLE.XX.
+ Authority:
+ XX. NS NS1.XX.
+ XX. NS NS2.XX.
+ Additional:
+ NS1.XX. A 127.0.0.2
+
+
+
+Andrews Standards Track [Page 4]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ NS2.XX. A 127.0.0.3
+
+ Note, in the four examples of NXDOMAIN responses, it is known that
+ the name "AN.EXAMPLE." exists, and has as its value a CNAME record.
+ The NXDOMAIN refers to "TRIPPLE.XX", which is then known not to
+ exist. On the other hand, in the referral example, it is shown that
+ "AN.EXAMPLE" exists, and has a CNAME RR as its value, but nothing is
+ known one way or the other about the existence of "TRIPPLE.XX", other
+ than that "NS1.XX" or "NS2.XX" can be consulted as the next step in
+ obtaining information about it.
+
+ Where no CNAME records appear, the NXDOMAIN response refers to the
+ name in the label of the RR in the question section.
+
+2.1.1 Special Handling of Name Error
+
+ This section deals with errors encountered when implementing negative
+ caching of NXDOMAIN responses.
+
+ There are a large number of resolvers currently in existence that
+ fail to correctly detect and process all forms of NXDOMAIN response.
+ Some resolvers treat a TYPE 1 NXDOMAIN response as a referral. To
+ alleviate this problem it is recommended that servers that are
+ authoritative for the NXDOMAIN response only send TYPE 2 NXDOMAIN
+ responses, that is the authority section contains a SOA record and no
+ NS records. If a non- authoritative server sends a type 1 NXDOMAIN
+ response to one of these old resolvers, the result will be an
+ unnecessary query to an authoritative server. This is undesirable,
+ but not fatal except when the server is being used a FORWARDER. If
+ however the resolver is using the server as a FORWARDER to such a
+ resolver it will be necessary to disable the sending of TYPE 1
+ NXDOMAIN response to it, use TYPE 2 NXDOMAIN instead.
+
+ Some resolvers incorrectly continue processing if the authoritative
+ answer flag is not set, looping until the query retry threshold is
+ exceeded and then returning SERVFAIL. This is a problem when your
+ nameserver is listed as a FORWARDER for such resolvers. If the
+ nameserver is used as a FORWARDER by such resolver, the authority
+ flag will have to be forced on for NXDOMAIN responses to these
+ resolvers. In practice this causes no problems even if turned on
+ always, and has been the default behaviour in BIND from 4.9.3
+ onwards.
+
+2.2 - No Data
+
+ NODATA is indicated by an answer with the RCODE set to NOERROR and no
+ relevant answers in the answer section. The authority section will
+ contain an SOA record, or there will be no NS records there.
+
+
+
+Andrews Standards Track [Page 5]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ NODATA responses have to be algorithmically determined from the
+ response's contents as there is no RCODE value to indicate NODATA.
+ In some cases to determine with certainty that NODATA is the correct
+ response it can be necessary to send another query.
+
+ The authority section may contain NXT and SIG RRsets in addition to
+ NS and SOA records. CNAME and SIG records may exist in the answer
+ section.
+
+ It is possible to distinguish between a NODATA and a referral
+ response by the presence of a SOA record in the authority section or
+ the absence of NS records in the authority section.
+
+ NODATA responses can be categorised into three types by the contents
+ of the authority section. These are shown below along with a
+ referral for comparison. Fields not mentioned are not important in
+ terms of the examples.
+
+ NODATA RESPONSE: TYPE 1.
+
+ Header:
+ RDCODE=NOERROR
+ Query:
+ ANOTHER.EXAMPLE. A
+ Answer:
+ <empty>
+ Authority:
+ EXAMPLE. SOA NS1.XX. HOSTMASTER.NS1.XX. ....
+ EXAMPLE. NS NS1.XX.
+ EXAMPLE. NS NS2.XX.
+ Additional:
+ NS1.XX. A 127.0.0.2
+ NS2.XX. A 127.0.0.3
+
+ NO DATA RESPONSE: TYPE 2.
+
+ Header:
+ RDCODE=NOERROR
+ Query:
+ ANOTHER.EXAMPLE. A
+ Answer:
+ <empty>
+ Authority:
+ EXAMPLE. SOA NS1.XX. HOSTMASTER.NS1.XX. ....
+ Additional:
+ <empty>
+
+
+
+
+
+Andrews Standards Track [Page 6]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ NO DATA RESPONSE: TYPE 3.
+
+ Header:
+ RDCODE=NOERROR
+ Query:
+ ANOTHER.EXAMPLE. A
+ Answer:
+ <empty>
+ Authority:
+ <empty>
+ Additional:
+ <empty>
+
+ REFERRAL RESPONSE.
+
+ Header:
+ RDCODE=NOERROR
+ Query:
+ ANOTHER.EXAMPLE. A
+ Answer:
+ <empty>
+ Authority:
+ EXAMPLE. NS NS1.XX.
+ EXAMPLE. NS NS2.XX.
+ Additional:
+ NS1.XX. A 127.0.0.2
+ NS2.XX. A 127.0.0.3
+
+
+ These examples, unlike the NXDOMAIN examples above, have no CNAME
+ records, however they could, in just the same way that the NXDOMAIN
+ examples did, in which case it would be the value of the last CNAME
+ (the QNAME) for which NODATA would be concluded.
+
+2.2.1 - Special Handling of No Data
+
+ There are a large number of resolvers currently in existence that
+ fail to correctly detect and process all forms of NODATA response.
+ Some resolvers treat a TYPE 1 NODATA response as a referral. To
+ alleviate this problem it is recommended that servers that are
+ authoritative for the NODATA response only send TYPE 2 NODATA
+ responses, that is the authority section contains a SOA record and no
+ NS records. Sending a TYPE 1 NODATA response from a non-
+ authoritative server to one of these resolvers will only result in an
+ unnecessary query. If a server is listed as a FORWARDER for another
+ resolver it may also be necessary to disable the sending of TYPE 1
+ NODATA response for non-authoritative NODATA responses.
+
+
+
+
+Andrews Standards Track [Page 7]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ Some name servers fail to set the RCODE to NXDOMAIN in the presence
+ of CNAMEs in the answer section. If a definitive NXDOMAIN / NODATA
+ answer is required in this case the resolver must query again using
+ the QNAME as the query label.
+
+3 - Negative Answers from Authoritative Servers
+
+ Name servers authoritative for a zone MUST include the SOA record of
+ the zone in the authority section of the response when reporting an
+ NXDOMAIN or indicating that no data of the requested type exists.
+ This is required so that the response may be cached. The TTL of this
+ record is set from the minimum of the MINIMUM field of the SOA record
+ and the TTL of the SOA itself, and indicates how long a resolver may
+ cache the negative answer. The TTL SIG record associated with the
+ SOA record should also be trimmed in line with the SOA's TTL.
+
+ If the containing zone is signed [RFC2065] the SOA and appropriate
+ NXT and SIG records MUST be added.
+
+4 - SOA Minimum Field
+
+ The SOA minimum field has been overloaded in the past to have three
+ different meanings, the minimum TTL value of all RRs in a zone, the
+ default TTL of RRs which did not contain a TTL value and the TTL of
+ negative responses.
+
+ Despite being the original defined meaning, the first of these, the
+ minimum TTL value of all RRs in a zone, has never in practice been
+ used and is hereby deprecated.
+
+ The second, the default TTL of RRs which contain no explicit TTL in
+ the master zone file, is relevant only at the primary server. After
+ a zone transfer all RRs have explicit TTLs and it is impossible to
+ determine whether the TTL for a record was explicitly set or derived
+ from the default after a zone transfer. Where a server does not
+ require RRs to include the TTL value explicitly, it should provide a
+ mechanism, not being the value of the MINIMUM field of the SOA
+ record, from which the missing TTL values are obtained. How this is
+ done is implementation dependent.
+
+ The Master File format [RFC 1035 Section 5] is extended to include
+ the following directive:
+
+ $TTL <TTL> [comment]
+
+
+
+
+
+
+
+Andrews Standards Track [Page 8]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ All resource records appearing after the directive, and which do not
+ explicitly include a TTL value, have their TTL set to the TTL given
+ in the $TTL directive. SIG records without a explicit TTL get their
+ TTL from the "original TTL" of the SIG record [RFC 2065 Section 4.5].
+
+ The remaining of the current meanings, of being the TTL to be used
+ for negative responses, is the new defined meaning of the SOA minimum
+ field.
+
+5 - Caching Negative Answers
+
+ Like normal answers negative answers have a time to live (TTL). As
+ there is no record in the answer section to which this TTL can be
+ applied, the TTL must be carried by another method. This is done by
+ including the SOA record from the zone in the authority section of
+ the reply. When the authoritative server creates this record its TTL
+ is taken from the minimum of the SOA.MINIMUM field and SOA's TTL.
+ This TTL decrements in a similar manner to a normal cached answer and
+ upon reaching zero (0) indicates the cached negative answer MUST NOT
+ be used again.
+
+ A negative answer that resulted from a name error (NXDOMAIN) should
+ be cached such that it can be retrieved and returned in response to
+ another query for the same <QNAME, QCLASS> that resulted in the
+ cached negative response.
+
+ A negative answer that resulted from a no data error (NODATA) should
+ be cached such that it can be retrieved and returned in response to
+ another query for the same <QNAME, QTYPE, QCLASS> that resulted in
+ the cached negative response.
+
+ The NXT record, if it exists in the authority section of a negative
+ answer received, MUST be stored such that it can be be located and
+ returned with SOA record in the authority section, as should any SIG
+ records in the authority section. For NXDOMAIN answers there is no
+ "necessary" obvious relationship between the NXT records and the
+ QNAME. The NXT record MUST have the same owner name as the query
+ name for NODATA responses.
+
+ Negative responses without SOA records SHOULD NOT be cached as there
+ is no way to prevent the negative responses looping forever between a
+ pair of servers even with a short TTL.
+
+ Despite the DNS forming a tree of servers, with various mis-
+ configurations it is possible to form a loop in the query graph, e.g.
+ two servers listing each other as forwarders, various lame server
+ configurations. Without a TTL count down a cache negative response
+
+
+
+
+Andrews Standards Track [Page 9]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ when received by the next server would have its TTL reset. This
+ negative indication could then live forever circulating between the
+ servers involved.
+
+ As with caching positive responses it is sensible for a resolver to
+ limit for how long it will cache a negative response as the protocol
+ supports caching for up to 68 years. Such a limit should not be
+ greater than that applied to positive answers and preferably be
+ tunable. Values of one to three hours have been found to work well
+ and would make sensible a default. Values exceeding one day have
+ been found to be problematic.
+
+6 - Negative answers from the cache
+
+ When a server, in answering a query, encounters a cached negative
+ response it MUST add the cached SOA record to the authority section
+ of the response with the TTL decremented by the amount of time it was
+ stored in the cache. This allows the NXDOMAIN / NODATA response to
+ time out correctly.
+
+ If a NXT record was cached along with SOA record it MUST be added to
+ the authority section. If a SIG record was cached along with a NXT
+ record it SHOULD be added to the authority section.
+
+ As with all answers coming from the cache, negative answers SHOULD
+ have an implicit referral built into the answer. This enables the
+ resolver to locate an authoritative source. An implicit referral is
+ characterised by NS records in the authority section referring the
+ resolver towards a authoritative source. NXDOMAIN types 1 and 4
+ responses contain implicit referrals as does NODATA type 1 response.
+
+7 - Other Negative Responses
+
+ Caching of other negative responses is not covered by any existing
+ RFC. There is no way to indicate a desired TTL in these responses.
+ Care needs to be taken to ensure that there are not forwarding loops.
+
+7.1 Server Failure (OPTIONAL)
+
+ Server failures fall into two major classes. The first is where a
+ server can determine that it has been misconfigured for a zone. This
+ may be where it has been listed as a server, but not configured to be
+ a server for the zone, or where it has been configured to be a server
+ for the zone, but cannot obtain the zone data for some reason. This
+ can occur either because the zone file does not exist or contains
+ errors, or because another server from which the zone should have
+ been available either did not respond or was unable or unwilling to
+ supply the zone.
+
+
+
+Andrews Standards Track [Page 10]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ The second class is where the server needs to obtain an answer from
+ elsewhere, but is unable to do so, due to network failures, other
+ servers that don't reply, or return server failure errors, or
+ similar.
+
+ In either case a resolver MAY cache a server failure response. If it
+ does so it MUST NOT cache it for longer than five (5) minutes, and it
+ MUST be cached against the specific query tuple <query name, type,
+ class, server IP address>.
+
+7.2 Dead / Unreachable Server (OPTIONAL)
+
+ Dead / Unreachable servers are servers that fail to respond in any
+ way to a query or where the transport layer has provided an
+ indication that the server does not exist or is unreachable. A
+ server may be deemed to be dead or unreachable if it has not
+ responded to an outstanding query within 120 seconds.
+
+ Examples of transport layer indications are:
+
+ ICMP error messages indicating host, net or port unreachable.
+ TCP resets
+ IP stack error messages providing similar indications to those above.
+
+ A server MAY cache a dead server indication. If it does so it MUST
+ NOT be deemed dead for longer than five (5) minutes. The indication
+ MUST be stored against query tuple <query name, type, class, server
+ IP address> unless there was a transport layer indication that the
+ server does not exist, in which case it applies to all queries to
+ that specific IP address.
+
+8 - Changes from RFC 1034
+
+ Negative caching in resolvers is no-longer optional, if a resolver
+ caches anything it must also cache negative answers.
+
+ Non-authoritative negative answers MAY be cached.
+
+ The SOA record from the authority section MUST be cached. Name error
+ indications must be cached against the tuple <query name, QCLASS>.
+ No data indications must be cached against <query name, QTYPE,
+ QCLASS> tuple.
+
+ A cached SOA record must be added to the response. This was
+ explicitly not allowed because previously the distinction between a
+ normal cached SOA record, and the SOA cached as a result of a
+ negative response was not made, and simply extracting a normal cached
+ SOA and adding that to a cached negative response causes problems.
+
+
+
+Andrews Standards Track [Page 11]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ The $TTL TTL directive was added to the master file format.
+
+9 - History of Negative Caching
+
+ This section presents a potted history of negative caching in the DNS
+ and forms no part of the technical specification of negative caching.
+
+ It is interesting to note that the same concepts were re-invented in
+ both the CHIVES and BIND servers.
+
+ The history of the early CHIVES work (Section 9.1) was supplied by
+ Rob Austein <sra@epilogue.com> and is reproduced here in the form in
+ which he supplied it [MPA].
+
+ Sometime around the spring of 1985, I mentioned to Paul Mockapetris
+ that our experience with his JEEVES DNS resolver had pointed out the
+ need for some kind of negative caching scheme. Paul suggested that
+ we simply cache authoritative errors, using the SOA MINIMUM value for
+ the zone that would have contained the target RRs. I'm pretty sure
+ that this conversation took place before RFC-973 was written, but it
+ was never clear to me whether this idea was something that Paul came
+ up with on the spot in response to my question or something he'd
+ already been planning to put into the document that became RFC-973.
+ In any case, neither of us was entirely sure that the SOA MINIMUM
+ value was really the right metric to use, but it was available and
+ was under the control of the administrator of the target zone, both
+ of which seemed to us at the time to be important feature.
+
+ Late in 1987, I released the initial beta-test version of CHIVES, the
+ DNS resolver I'd written to replace Paul's JEEVES resolver. CHIVES
+ included a search path mechanism that was used pretty heavily at
+ several sites (including my own), so CHIVES also included a negative
+ caching mechanism based on SOA MINIMUM values. The basic strategy
+ was to cache authoritative error codes keyed by the exact query
+ parameters (QNAME, QCLASS, and QTYPE), with a cache TTL equal to the
+ SOA MINIMUM value. CHIVES did not attempt to track down SOA RRs if
+ they weren't supplied in the authoritative response, so it never
+ managed to completely eliminate the gratuitous DNS error message
+ traffic, but it did help considerably. Keep in mind that this was
+ happening at about the same time as the near-collapse of the ARPANET
+ due to congestion caused by exponential growth and the the "old"
+ (pre-VJ) TCP retransmission algorithm, so negative caching resulted
+ in drasticly better DNS response time for our users, mailer daemons,
+ etcetera.
+
+
+
+
+
+
+
+Andrews Standards Track [Page 12]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ As far as I know, CHIVES was the first resolver to implement negative
+ caching. CHIVES was developed during the twilight years of TOPS-20,
+ so it never ran on very many machines, but the few machines that it
+ did run on were the ones that were too critical to shut down quickly
+ no matter how much it cost to keep them running. So what few users
+ we did have tended to drive CHIVES pretty hard. Several interesting
+ bits of DNS technology resulted from that, but the one that's
+ relevant here is the MAXTTL configuration parameter.
+
+ Experience with JEEVES had already shown that RRs often showed up
+ with ridiculously long TTLs (99999999 was particularly popular for
+ many years, due to bugs in the code and documentation of several
+ early versions of BIND), and that robust software that blindly
+ believed such TTLs could create so many strange failures that it was
+ often necessary to reboot the resolver frequently just to clear this
+ garbage out of the cache. So CHIVES had a configuration parameter
+ "MAXTTL", which specified the maximum "reasonable" TTL in a received
+ RR. RRs with TTLs greater than MAXTTL would either have their TTLs
+ reduced to MAXTTL or would be discarded entirely, depending on the
+ setting of another configuration parameter.
+
+ When we started getting field experience with CHIVES's negative
+ caching code, it became clear that the SOA MINIMUM value was often
+ large enough to cause the same kinds of problems for negative caching
+ as the huge TTLs in RRs had for normal caching (again, this was in
+ part due to a bug in several early versions of BIND, where a
+ secondary server would authoritatively deny all knowledge of its
+ zones if it couldn't contact the primaries on reboot). So we started
+ running the negative cache TTLs through the MAXTTL check too, and
+ continued to experiment.
+
+ The configuration that seemed to work best on WSMR-SIMTEL20.ARMY.MIL
+ (last of the major Internet TOPS-20 machines to be shut down, thus
+ the last major user of CHIVES, thus the place where we had the
+ longest experimental baseline) was to set MAXTTL to about three days.
+ Most of the traffic initiated by SIMTEL20 in its last years was
+ mail-related, and the mail queue timeout was set to one week, so this
+ gave a "stuck" message several tries at complete DNS resolution,
+ without bogging down the system with a lot of useless queries. Since
+ (for reasons that now escape me) we only had the single MAXTTL
+ parameter rather than separate ones for positive and negative
+ caching, it's not clear how much effect this setting of MAXTTL had on
+ the negative caching code.
+
+ CHIVES also included a second, somewhat controversial mechanism which
+ took the place of negative caching in some cases. The CHIVES
+ resolver daemon could be configured to load DNS master files, giving
+ it the ability to act as what today would be called a "stealth
+
+
+
+Andrews Standards Track [Page 13]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ secondary". That is, when configured in this way, the resolver had
+ direct access to authoritative information for heavily-used zones.
+ The search path mechanisms in CHIVES reflected this: there were
+ actually two separate search paths, one of which only searched local
+ authoritative zone data, and one which could generate normal
+ iterative queries. This cut down on the need for negative caching in
+ cases where usage was predictably heavy (e.g., the resolver on
+ XX.LCS.MIT.EDU always loaded the zone files for both LCS.MIT.EDU and
+ AI.MIT.EDU and put both of these suffixes into the "local" search
+ path, since between them the hosts in these two zones accounted for
+ the bulk of the DNS traffic). Not all sites running CHIVES chose to
+ use this feature; C.CS.CMU.EDU, for example, chose to use the
+ "remote" search path for everything because there were too many
+ different sub-zones at CMU for zone shadowing to be practical for
+ them, so they relied pretty heavily on negative caching even for
+ local traffic.
+
+ Overall, I still think the basic design we used for negative caching
+ was pretty reasonable: the zone administrator specified how long to
+ cache negative answers, and the resolver configuration chose the
+ actual cache time from the range between zero and the period
+ specified by the zone administrator. There are a lot of details I'd
+ do differently now (like using a new SOA field instead of overloading
+ the MINIMUM field), but after more than a decade, I'd be more worried
+ if we couldn't think of at least a few improvements.
+
+9.2 BIND
+
+ While not the first attempt to get negative caching into BIND, in
+ July 1993, BIND 4.9.2 ALPHA, Anant Kumar of ISI supplied code that
+ implemented, validation and negative caching (NCACHE). This code had
+ a 10 minute TTL for negative caching and only cached the indication
+ that there was a negative response, NXDOMAIN or NOERROR_NODATA. This
+ is the origin of the NODATA pseudo response code mentioned above.
+
+ Mark Andrews of CSIRO added code (RETURNSOA) that stored the SOA
+ record such that it could be retrieved by a similar query. UUnet
+ complained that they were getting old answers after loading a new
+ zone, and the option was turned off, BIND 4.9.3-alpha5, April 1994.
+ In reality this indicated that the named needed to purge the space
+ the zone would occupy. Functionality to do this was added in BIND
+ 4.9.3 BETA11 patch2, December 1994.
+
+ RETURNSOA was re-enabled by default, BIND 4.9.5-T1A, August 1996.
+
+
+
+
+
+
+
+Andrews Standards Track [Page 14]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+10 Example
+
+ The following example is based on a signed zone that is empty apart
+ from the nameservers. We will query for WWW.XX.EXAMPLE showing
+ initial response and again 10 minutes later. Note 1: during the
+ intervening 10 minutes the NS records for XX.EXAMPLE have expired.
+ Note 2: the TTL of the SIG records are not explicitly set in the zone
+ file and are hence the TTL of the RRset they are the signature for.
+
+ Zone File:
+
+ $TTL 86400
+ $ORIGIN XX.EXAMPLE.
+ @ IN SOA NS1.XX.EXAMPLE. HOSTMATER.XX.EXAMPLE. (
+ 1997102000 ; serial
+ 1800 ; refresh (30 mins)
+ 900 ; retry (15 mins)
+ 604800 ; expire (7 days)
+ 1200 ) ; minimum (20 mins)
+ IN SIG SOA ...
+ 1200 IN NXT NS1.XX.EXAMPLE. A NXT SIG SOA NS KEY
+ IN SIG NXT ... XX.EXAMPLE. ...
+ 300 IN NS NS1.XX.EXAMPLE.
+ 300 IN NS NS2.XX.EXAMPLE.
+ IN SIG NS ... XX.EXAMPLE. ...
+ IN KEY 0x4100 1 1 ...
+ IN SIG KEY ... XX.EXAMPLE. ...
+ IN SIG KEY ... EXAMPLE. ...
+ NS1 IN A 10.0.0.1
+ IN SIG A ... XX.EXAMPLE. ...
+ 1200 IN NXT NS2.XX.EXAMPLE. A NXT SIG
+ IN SIG NXT ...
+ NS2 IN A 10.0.0.2
+ IN SIG A ... XX.EXAMPLE. ...
+ 1200 IN NXT XX.EXAMPLE. A NXT SIG
+ IN SIG NXT ... XX.EXAMPLE. ...
+
+ Initial Response:
+
+ Header:
+ RDCODE=NXDOMAIN, AA=1, QR=1, TC=0
+ Query:
+ WWW.XX.EXAMPLE. IN A
+ Answer:
+ <empty>
+ Authority:
+ XX.EXAMPLE. 1200 IN SOA NS1.XX.EXAMPLE. ...
+ XX.EXAMPLE. 1200 IN SIG SOA ... XX.EXAMPLE. ...
+
+
+
+Andrews Standards Track [Page 15]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ NS2.XX.EXAMPLE. 1200 IN NXT XX.EXAMPLE. NXT A NXT SIG
+ NS2.XX.EXAMPLE. 1200 IN SIG NXT ... XX.EXAMPLE. ...
+ XX.EXAMPLE. 86400 IN NS NS1.XX.EXAMPLE.
+ XX.EXAMPLE. 86400 IN NS NS2.XX.EXAMPLE.
+ XX.EXAMPLE. 86400 IN SIG NS ... XX.EXAMPLE. ...
+ Additional
+ XX.EXAMPLE. 86400 IN KEY 0x4100 1 1 ...
+ XX.EXAMPLE. 86400 IN SIG KEY ... EXAMPLE. ...
+ NS1.XX.EXAMPLE. 86400 IN A 10.0.0.1
+ NS1.XX.EXAMPLE. 86400 IN SIG A ... XX.EXAMPLE. ...
+ NS2.XX.EXAMPLE. 86400 IN A 10.0.0.2
+ NS3.XX.EXAMPLE. 86400 IN SIG A ... XX.EXAMPLE. ...
+
+ After 10 Minutes:
+
+ Header:
+ RDCODE=NXDOMAIN, AA=0, QR=1, TC=0
+ Query:
+ WWW.XX.EXAMPLE. IN A
+ Answer:
+ <empty>
+ Authority:
+ XX.EXAMPLE. 600 IN SOA NS1.XX.EXAMPLE. ...
+ XX.EXAMPLE. 600 IN SIG SOA ... XX.EXAMPLE. ...
+ NS2.XX.EXAMPLE. 600 IN NXT XX.EXAMPLE. NXT A NXT SIG
+ NS2.XX.EXAMPLE. 600 IN SIG NXT ... XX.EXAMPLE. ...
+ EXAMPLE. 65799 IN NS NS1.YY.EXAMPLE.
+ EXAMPLE. 65799 IN NS NS2.YY.EXAMPLE.
+ EXAMPLE. 65799 IN SIG NS ... XX.EXAMPLE. ...
+ Additional
+ XX.EXAMPLE. 65800 IN KEY 0x4100 1 1 ...
+ XX.EXAMPLE. 65800 IN SIG KEY ... EXAMPLE. ...
+ NS1.YY.EXAMPLE. 65799 IN A 10.100.0.1
+ NS1.YY.EXAMPLE. 65799 IN SIG A ... EXAMPLE. ...
+ NS2.YY.EXAMPLE. 65799 IN A 10.100.0.2
+ NS3.YY.EXAMPLE. 65799 IN SIG A ... EXAMPLE. ...
+ EXAMPLE. 65799 IN KEY 0x4100 1 1 ...
+ EXAMPLE. 65799 IN SIG KEY ... . ...
+
+
+11 Security Considerations
+
+ It is believed that this document does not introduce any significant
+ additional security threats other that those that already exist when
+ using data from the DNS.
+
+
+
+
+
+
+Andrews Standards Track [Page 16]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+ With negative caching it might be possible to propagate a denial of
+ service attack by spreading a NXDOMAIN message with a very high TTL.
+ Without negative caching that would be much harder. A similar effect
+ could be achieved previously by spreading a bad A record, so that the
+ server could not be reached - which is almost the same. It has the
+ same effect as far as what the end user is able to do, but with a
+ different psychological effect. With the bad A, I feel "damn the
+ network is broken again" and try again tomorrow. With the "NXDOMAIN"
+ I feel "Oh, they've turned off the server and it doesn't exist any
+ more" and probably never bother trying this server again.
+
+ A practical example of this is a SMTP server where this behaviour is
+ encoded. With a NXDOMAIN attack the mail message would bounce
+ immediately, where as with a bad A attack the mail would be queued
+ and could potentially get through after the attack was suspended.
+
+ For such an attack to be successful, the NXDOMAIN indiction must be
+ injected into a parent server (or a busy caching resolver). One way
+ this might be done by the use of a CNAME which results in the parent
+ server querying an attackers server. Resolvers that wish to prevent
+ such attacks can query again the final QNAME ignoring any NS data in
+ the query responses it has received for this query.
+
+ Implementing TTL sanity checking will reduce the effectiveness of
+ such an attack, because a successful attack would require re-
+ injection of the bogus data at more frequent intervals.
+
+ DNS Security [RFC2065] provides a mechanism to verify whether a
+ negative response is valid or not, through the use of NXT and SIG
+ records. This document supports the use of that mechanism by
+ promoting the transmission of the relevant security records even in a
+ non security aware server.
+
+Acknowledgments
+
+ I would like to thank Rob Austein for his history of the CHIVES
+ nameserver. The DNSIND working group, in particular Robert Elz for
+ his valuable technical and editorial contributions to this document.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Andrews Standards Track [Page 17]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+References
+
+ [RFC1034]
+ Mockapetris, P., "DOMAIN NAMES - CONCEPTS AND FACILITIES,"
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035]
+ Mockapetris, P., "DOMAIN NAMES - IMPLEMENTATION AND
+ SPECIFICATION," STD 13, RFC 1035, November 1987.
+
+ [RFC2065]
+ Eastlake, D., and C. Kaufman, "Domain Name System Security
+ Extensions," RFC 2065, January 1997.
+
+ [RFC2119]
+ Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels," BCP 14, RFC 2119, March 1997.
+
+ [RFC2181]
+ Elz, R., and R. Bush, "Clarifications to the DNS
+ Specification," RFC 2181, July 1997.
+
+Author's Address
+
+ Mark Andrews
+ CSIRO - Mathematical and Information Sciences
+ Locked Bag 17
+ North Ryde NSW 2113
+ AUSTRALIA
+
+ Phone: +61 2 9325 3148
+ EMail: Mark.Andrews@cmis.csiro.au
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Andrews Standards Track [Page 18]
+
+RFC 2308 DNS NCACHE March 1998
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Andrews Standards Track [Page 19]
+
diff --git a/doc/rfc/rfc2317.txt b/doc/rfc/rfc2317.txt
new file mode 100644
index 0000000..c17bb41
--- /dev/null
+++ b/doc/rfc/rfc2317.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group H. Eidnes
+Request for Comments: 2317 SINTEF RUNIT
+BCP: 20 G. de Groot
+Category: Best Current Practice Berkeley Software Design, Inc.
+ P. Vixie
+ Internet Software Consortium
+ March 1998
+
+
+ Classless IN-ADDR.ARPA delegation
+
+Status of this Memo
+
+ This document specifies an Internet Best Current Practices for the
+ Internet Community, and requests discussion and suggestions for
+ improvements. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+2. Introduction
+
+ This document describes a way to do IN-ADDR.ARPA delegation on non-
+ octet boundaries for address spaces covering fewer than 256
+ addresses. The proposed method should thus remove one of the
+ objections to subnet on non-octet boundaries but perhaps more
+ significantly, make it possible to assign IP address space in smaller
+ chunks than 24-bit prefixes, without losing the ability to delegate
+ authority for the corresponding IN-ADDR.ARPA mappings. The proposed
+ method is fully compatible with the original DNS lookup mechanisms
+ specified in [1], i.e. there is no need to modify the lookup
+ algorithm used, and there should be no need to modify any software
+ which does DNS lookups.
+
+ The document also discusses some operational considerations to
+ provide some guidance in implementing this method.
+
+3. Motivation
+
+ With the proliferation of classless routing technology, it has become
+ feasible to assign address space on non-octet boundaries. In case of
+ a very small organization with only a few hosts, assigning a full
+ 24-bit prefix (what was traditionally referred to as a "class C
+ network number") often leads to inefficient address space
+ utilization.
+
+
+
+
+
+Eidnes, et. al. Best Current Practice [Page 1]
+
+RFC 2317 Classless IN-ADDR.ARPA delegation March 1998
+
+
+ One of the problems encountered when assigning a longer prefix (less
+ address space) is that it seems impossible for such an organization
+ to maintain its own reverse ("IN-ADDR.ARPA") zone autonomously. By
+ use of the reverse delegation method described below, the most
+ important objection to assignment of longer prefixes to unrelated
+ organizations can be removed.
+
+ Let us assume we have assigned the address spaces to three different
+ parties as follows:
+
+ 192.0.2.0/25 to organization A
+ 192.0.2.128/26 to organization B
+ 192.0.2.192/26 to organization C
+
+ In the classical approach, this would lead to a single zone like
+ this:
+
+ $ORIGIN 2.0.192.in-addr.arpa.
+ ;
+ 1 PTR host1.A.domain.
+ 2 PTR host2.A.domain.
+ 3 PTR host3.A.domain.
+ ;
+ 129 PTR host1.B.domain.
+ 130 PTR host2.B.domain.
+ 131 PTR host3.B.domain.
+ ;
+ 193 PTR host1.C.domain.
+ 194 PTR host2.C.domain.
+ 195 PTR host3.C.domain.
+
+ The administration of this zone is problematic. Authority for this
+ zone can only be delegated once, and this usually translates into
+ "this zone can only be administered by one organization." The other
+ organizations with address space that corresponds to entries in this
+ zone would thus have to depend on another organization for their
+ address to name translation. With the proposed method, this
+ potential problem can be avoided.
+
+4. Classless IN-ADDR.ARPA delegation
+
+ Since a single zone can only be delegated once, we need more points
+ to do delegation on to solve the problem above. These extra points
+ of delegation can be introduced by extending the IN-ADDR.ARPA tree
+ downwards, e.g. by using the first address or the first address and
+ the network mask length (as shown below) in the corresponding address
+
+
+
+
+
+Eidnes, et. al. Best Current Practice [Page 2]
+
+RFC 2317 Classless IN-ADDR.ARPA delegation March 1998
+
+
+ space to form the the first component in the name for the zones. The
+ following four zone files show how the problem in the motivation
+ section could be solved using this method.
+
+ $ORIGIN 2.0.192.in-addr.arpa.
+ @ IN SOA my-ns.my.domain. hostmaster.my.domain. (...)
+ ;...
+ ; <<0-127>> /25
+ 0/25 NS ns.A.domain.
+ 0/25 NS some.other.name.server.
+ ;
+ 1 CNAME 1.0/25.2.0.192.in-addr.arpa.
+ 2 CNAME 2.0/25.2.0.192.in-addr.arpa.
+ 3 CNAME 3.0/25.2.0.192.in-addr.arpa.
+ ;
+ ; <<128-191>> /26
+ 128/26 NS ns.B.domain.
+ 128/26 NS some.other.name.server.too.
+ ;
+ 129 CNAME 129.128/26.2.0.192.in-addr.arpa.
+ 130 CNAME 130.128/26.2.0.192.in-addr.arpa.
+ 131 CNAME 131.128/26.2.0.192.in-addr.arpa.
+ ;
+ ; <<192-255>> /26
+ 192/26 NS ns.C.domain.
+ 192/26 NS some.other.third.name.server.
+ ;
+ 193 CNAME 193.192/26.2.0.192.in-addr.arpa.
+ 194 CNAME 194.192/26.2.0.192.in-addr.arpa.
+ 195 CNAME 195.192/26.2.0.192.in-addr.arpa.
+
+ $ORIGIN 0/25.2.0.192.in-addr.arpa.
+ @ IN SOA ns.A.domain. hostmaster.A.domain. (...)
+ @ NS ns.A.domain.
+ @ NS some.other.name.server.
+ ;
+ 1 PTR host1.A.domain.
+ 2 PTR host2.A.domain.
+ 3 PTR host3.A.domain.
+
+
+
+
+
+
+
+
+
+
+
+
+Eidnes, et. al. Best Current Practice [Page 3]
+
+RFC 2317 Classless IN-ADDR.ARPA delegation March 1998
+
+
+ $ORIGIN 128/26.2.0.192.in-addr.arpa.
+ @ IN SOA ns.B.domain. hostmaster.B.domain. (...)
+ @ NS ns.B.domain.
+ @ NS some.other.name.server.too.
+ ;
+ 129 PTR host1.B.domain.
+ 130 PTR host2.B.domain.
+ 131 PTR host3.B.domain.
+
+
+ $ORIGIN 192/26.2.0.192.in-addr.arpa.
+ @ IN SOA ns.C.domain. hostmaster.C.domain. (...)
+ @ NS ns.C.domain.
+ @ NS some.other.third.name.server.
+ ;
+ 193 PTR host1.C.domain.
+ 194 PTR host2.C.domain.
+ 195 PTR host3.C.domain.
+
+ For each size-256 chunk split up using this method, there is a need
+ to install close to 256 CNAME records in the parent zone. Some
+ people might view this as ugly; we will not argue that particular
+ point. It is however quite easy to automatically generate the CNAME
+ resource records in the parent zone once and for all, if the way the
+ address space is partitioned is known.
+
+ The advantage of this approach over the other proposed approaches for
+ dealing with this problem is that there should be no need to modify
+ any already-deployed software. In particular, the lookup mechanism
+ in the DNS does not have to be modified to accommodate this splitting
+ of the responsibility for the IPv4 address to name translation on
+ "non-dot" boundaries. Furthermore, this technique has been in use
+ for several years in many installations, apparently with no ill
+ effects.
+
+ As usual, a resource record like
+
+ $ORIGIN 2.0.192.in-addr.arpa.
+ 129 CNAME 129.128/26.2.0.192.in-addr.arpa.
+
+ can be convienently abbreviated to
+
+ $ORIGIN 2.0.192.in-addr.arpa.
+ 129 CNAME 129.128/26
+
+
+
+
+
+
+
+Eidnes, et. al. Best Current Practice [Page 4]
+
+RFC 2317 Classless IN-ADDR.ARPA delegation March 1998
+
+
+ Some DNS implementations are not kind to special characters in domain
+ names, e.g. the "/" used in the above examples. As [3] makes clear,
+ these are legal, though some might feel unsightly. Because these are
+ not host names the restriction of [2] does not apply. Modern clients
+ and servers have an option to act in the liberal and correct fashion.
+
+ The examples here use "/" because it was felt to be more visible and
+ pedantic reviewers felt that the 'these are not hostnames' argument
+ needed to be repeated. We advise you not to be so pedantic, and to
+ not precisely copy the above examples, e.g. substitute a more
+ conservative character, such as hyphen, for "/".
+
+5. Operational considerations
+
+ This technique is intended to be used for delegating address spaces
+ covering fewer than 256 addresses. For delegations covering larger
+ blocks of addresses the traditional methods (multiple delegations)
+ can be used instead.
+
+5.1 Recommended secondary name service
+
+ Some older versions of name server software will make no effort to
+ find and return the pointed-to name in CNAME records if the pointed-
+ to name is not already known locally as cached or as authoritative
+ data. This can cause some confusion in resolvers, as only the CNAME
+ record will be returned in the response. To avoid this problem it is
+ recommended that the authoritative name servers for the delegating
+ zone (the zone containing all the CNAME records) all run as slave
+ (secondary) name servers for the "child" zones delegated and pointed
+ into via the CNAME records.
+
+5.2 Alternative naming conventions
+
+ As a result of this method, the location of the zone containing the
+ actual PTR records is no longer predefined. This gives flexibility
+ and some examples will be presented here.
+
+ An alternative to using the first address, or the first address and
+ the network mask length in the corresponding address space, to name
+ the new zones is to use some other (non-numeric) name. Thus it is
+ also possible to point to an entirely different part of the DNS tree
+ (i.e. outside of the IN-ADDR.ARPA tree). It would be necessary to
+ use one of these alternate methods if two organizations somehow
+ shared the same physical subnet (and corresponding IP address space)
+ with no "neat" alignment of the addresses, but still wanted to
+ administrate their own IN-ADDR.ARPA mappings.
+
+
+
+
+
+Eidnes, et. al. Best Current Practice [Page 5]
+
+RFC 2317 Classless IN-ADDR.ARPA delegation March 1998
+
+
+ The following short example shows how you can point out of the IN-
+ ADDR.ARPA tree:
+
+ $ORIGIN 2.0.192.in-addr.arpa.
+ @ IN SOA my-ns.my.domain. hostmaster.my.domain. (...)
+ ; ...
+ 1 CNAME 1.A.domain.
+ 2 CNAME 2.A.domain.
+ ; ...
+ 129 CNAME 129.B.domain.
+ 130 CNAME 130.B.domain.
+ ;
+
+
+ $ORIGIN A.domain.
+ @ IN SOA my-ns.A.domain. hostmaster.A.domain. (...)
+ ; ...
+ ;
+ host1 A 192.0.2.1
+ 1 PTR host1
+ ;
+ host2 A 192.0.2.2
+ 2 PTR host2
+ ;
+
+ etc.
+
+ This way you can actually end up with the name->address and the
+ (pointed-to) address->name mapping data in the same zone file - some
+ may view this as an added bonus as no separate set of secondaries for
+ the reverse zone is required. Do however note that the traversal via
+ the IN-ADDR.ARPA tree will still be done, so the CNAME records
+ inserted there need to point in the right direction for this to work.
+
+ Sketched below is an alternative approach using the same solution:
+
+ $ORIGIN 2.0.192.in-addr.arpa.
+ @ SOA my-ns.my.domain. hostmaster.my.domain. (...)
+ ; ...
+ 1 CNAME 1.2.0.192.in-addr.A.domain.
+ 2 CNAME 2.2.0.192.in-addr.A.domain.
+
+ $ORIGIN A.domain.
+ @ SOA my-ns.A.domain. hostmaster.A.domain. (...)
+ ; ...
+ ;
+ host1 A 192.0.2.1
+ 1.2.0.192.in-addr PTR host1
+
+
+
+Eidnes, et. al. Best Current Practice [Page 6]
+
+RFC 2317 Classless IN-ADDR.ARPA delegation March 1998
+
+
+ host2 A 192.0.2.2
+ 2.2.0.192.in-addr PTR host2
+
+ It is clear that many possibilities exist which can be adapted to the
+ specific requirements of the situation at hand.
+
+5.3 Other operational issues
+
+ Note that one cannot provide CNAME referrals twice for the same
+ address space, i.e. you cannot allocate a /25 prefix to one
+ organisation, and run IN-ADDR.ARPA this way, and then have the
+ organisation subnet the /25 into longer prefixes, and attempt to
+ employ the same technique to give each subnet control of its own
+ number space. This would result in a CNAME record pointing to a CNAME
+ record, which may be less robust overall.
+
+ Unfortunately, some old beta releases of the popular DNS name server
+ implementation BIND 4.9.3 had a bug which caused problems if a CNAME
+ record was encountered when a reverse lookup was made. The beta
+ releases involved have since been obsoleted, and this issue is
+ resolved in the released code. Some software manufacturers have
+ included the defective beta code in their product. In the few cases
+ we know of, patches from the manufacturers are available or planned
+ to replace the obsolete beta code involved.
+
+6. Security Considerations
+
+ With this scheme, the "leaf sites" will need to rely on one more site
+ running their DNS name service correctly than they would be if they
+ had a /24 allocation of their own, and this may add an extra
+ component which will need to work for reliable name resolution.
+
+ Other than that, the authors are not aware of any additional security
+ issues introduced by this mechanism.
+
+7. Conclusion
+
+ The suggested scheme gives more flexibility in delegating authority
+ in the IN-ADDR.ARPA domain, thus making it possible to assign address
+ space more efficiently without losing the ability to delegate the DNS
+ authority over the corresponding address to name mappings.
+
+8. Acknowledgments
+
+ Glen A. Herrmannsfeldt described this trick on comp.protocols.tcp-
+ ip.domains some time ago. Alan Barrett and Sam Wilson provided
+ valuable comments on the newsgroup.
+
+
+
+
+Eidnes, et. al. Best Current Practice [Page 7]
+
+RFC 2317 Classless IN-ADDR.ARPA delegation March 1998
+
+
+ We would like to thank Rob Austein, Randy Bush, Matt Crawford, Robert
+ Elz, Glen A. Herrmannsfeldt, Daniel Karrenberg, David Kessens, Tony
+ Li, Paul Mockapetris, Eric Wassenaar, Michael Patton, Hans Maurer,
+ and Peter Koch for their review and constructive comments.
+
+9. References
+
+ [1] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [2] Harrenstien, K., Stahl, M., and E. Feinler, "DoD Internet Host
+ Table Specification", RFC 952, October 1985.
+
+ [3] Elz, R., and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eidnes, et. al. Best Current Practice [Page 8]
+
+RFC 2317 Classless IN-ADDR.ARPA delegation March 1998
+
+
+10. Authors' Addresses
+
+ Havard Eidnes
+ SINTEF RUNIT
+ N-7034 Trondheim
+ Norway
+
+ Phone: +47 73 59 44 68
+ Fax: +47 73 59 17 00
+ EMail: Havard.Eidnes@runit.sintef.no
+
+
+ Geert Jan de Groot
+ Berkeley Software Design, Inc. (BSDI)
+ Hendrik Staetslaan 69
+ 5622 HM Eindhoven
+ The Netherlands
+
+ Phone: +31 40 2960509
+ Fax: +31 40 2960309
+ EMail: GeertJan.deGroot@bsdi.com
+
+
+ Paul Vixie
+ Internet Software Consortium
+ Star Route Box 159A
+ Woodside, CA 94062
+ USA
+
+ Phone: +1 415 747 0204
+ EMail: paul@vix.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eidnes, et. al. Best Current Practice [Page 9]
+
+RFC 2317 Classless IN-ADDR.ARPA delegation March 1998
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eidnes, et. al. Best Current Practice [Page 10]
+
diff --git a/doc/rfc/rfc2373.txt b/doc/rfc/rfc2373.txt
new file mode 100644
index 0000000..59fcff8
--- /dev/null
+++ b/doc/rfc/rfc2373.txt
@@ -0,0 +1,1459 @@
+
+
+
+
+
+
+Network Working Group R. Hinden
+Request for Comments: 2373 Nokia
+Obsoletes: 1884 S. Deering
+Category: Standards Track Cisco Systems
+ July 1998
+
+ IP Version 6 Addressing Architecture
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+Abstract
+
+ This specification defines the addressing architecture of the IP
+ Version 6 protocol [IPV6]. The document includes the IPv6 addressing
+ model, text representations of IPv6 addresses, definition of IPv6
+ unicast addresses, anycast addresses, and multicast addresses, and an
+ IPv6 node's required addresses.
+
+Table of Contents
+
+ 1. Introduction.................................................2
+ 2. IPv6 Addressing..............................................2
+ 2.1 Addressing Model.........................................3
+ 2.2 Text Representation of Addresses.........................3
+ 2.3 Text Representation of Address Prefixes..................5
+ 2.4 Address Type Representation..............................6
+ 2.5 Unicast Addresses........................................7
+ 2.5.1 Interface Identifiers................................8
+ 2.5.2 The Unspecified Address..............................9
+ 2.5.3 The Loopback Address.................................9
+ 2.5.4 IPv6 Addresses with Embedded IPv4 Addresses.........10
+ 2.5.5 NSAP Addresses......................................10
+ 2.5.6 IPX Addresses.......................................10
+ 2.5.7 Aggregatable Global Unicast Addresses...............11
+ 2.5.8 Local-use IPv6 Unicast Addresses....................11
+ 2.6 Anycast Addresses.......................................12
+ 2.6.1 Required Anycast Address............................13
+ 2.7 Multicast Addresses.....................................14
+
+
+
+Hinden & Deering Standards Track [Page 1]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ 2.7.1 Pre-Defined Multicast Addresses.....................15
+ 2.7.2 Assignment of New IPv6 Multicast Addresses..........17
+ 2.8 A Node's Required Addresses.............................17
+ 3. Security Considerations.....................................18
+ APPENDIX A: Creating EUI-64 based Interface Identifiers........19
+ APPENDIX B: ABNF Description of Text Representations...........22
+ APPENDIX C: CHANGES FROM RFC-1884..............................23
+ REFERENCES.....................................................24
+ AUTHORS' ADDRESSES.............................................25
+ FULL COPYRIGHT STATEMENT.......................................26
+
+
+1.0 INTRODUCTION
+
+ This specification defines the addressing architecture of the IP
+ Version 6 protocol. It includes a detailed description of the
+ currently defined address formats for IPv6 [IPV6].
+
+ The authors would like to acknowledge the contributions of Paul
+ Francis, Scott Bradner, Jim Bound, Brian Carpenter, Matt Crawford,
+ Deborah Estrin, Roger Fajman, Bob Fink, Peter Ford, Bob Gilligan,
+ Dimitry Haskin, Tom Harsch, Christian Huitema, Tony Li, Greg
+ Minshall, Thomas Narten, Erik Nordmark, Yakov Rekhter, Bill Simpson,
+ and Sue Thomson.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC 2119].
+
+2.0 IPv6 ADDRESSING
+
+ IPv6 addresses are 128-bit identifiers for interfaces and sets of
+ interfaces. There are three types of addresses:
+
+ Unicast: An identifier for a single interface. A packet sent to
+ a unicast address is delivered to the interface
+ identified by that address.
+
+ Anycast: An identifier for a set of interfaces (typically
+ belonging to different nodes). A packet sent to an
+ anycast address is delivered to one of the interfaces
+ identified by that address (the "nearest" one, according
+ to the routing protocols' measure of distance).
+
+ Multicast: An identifier for a set of interfaces (typically
+ belonging to different nodes). A packet sent to a
+ multicast address is delivered to all interfaces
+ identified by that address.
+
+
+
+Hinden & Deering Standards Track [Page 2]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ There are no broadcast addresses in IPv6, their function being
+ superseded by multicast addresses.
+
+ In this document, fields in addresses are given a specific name, for
+ example "subscriber". When this name is used with the term "ID" for
+ identifier after the name (e.g., "subscriber ID"), it refers to the
+ contents of the named field. When it is used with the term "prefix"
+ (e.g. "subscriber prefix") it refers to all of the address up to and
+ including this field.
+
+ In IPv6, all zeros and all ones are legal values for any field,
+ unless specifically excluded. Specifically, prefixes may contain
+ zero-valued fields or end in zeros.
+
+2.1 Addressing Model
+
+ IPv6 addresses of all types are assigned to interfaces, not nodes.
+ An IPv6 unicast address refers to a single interface. Since each
+ interface belongs to a single node, any of that node's interfaces'
+ unicast addresses may be used as an identifier for the node.
+
+ All interfaces are required to have at least one link-local unicast
+ address (see section 2.8 for additional required addresses). A
+ single interface may also be assigned multiple IPv6 addresses of any
+ type (unicast, anycast, and multicast) or scope. Unicast addresses
+ with scope greater than link-scope are not needed for interfaces that
+ are not used as the origin or destination of any IPv6 packets to or
+ from non-neighbors. This is sometimes convenient for point-to-point
+ interfaces. There is one exception to this addressing model:
+
+ An unicast address or a set of unicast addresses may be assigned to
+ multiple physical interfaces if the implementation treats the
+ multiple physical interfaces as one interface when presenting it to
+ the internet layer. This is useful for load-sharing over multiple
+ physical interfaces.
+
+ Currently IPv6 continues the IPv4 model that a subnet prefix is
+ associated with one link. Multiple subnet prefixes may be assigned
+ to the same link.
+
+2.2 Text Representation of Addresses
+
+ There are three conventional forms for representing IPv6 addresses as
+ text strings:
+
+ 1. The preferred form is x:x:x:x:x:x:x:x, where the 'x's are the
+ hexadecimal values of the eight 16-bit pieces of the address.
+ Examples:
+
+
+
+Hinden & Deering Standards Track [Page 3]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
+
+ 1080:0:0:0:8:800:200C:417A
+
+ Note that it is not necessary to write the leading zeros in an
+ individual field, but there must be at least one numeral in every
+ field (except for the case described in 2.).
+
+ 2. Due to some methods of allocating certain styles of IPv6
+ addresses, it will be common for addresses to contain long strings
+ of zero bits. In order to make writing addresses containing zero
+ bits easier a special syntax is available to compress the zeros.
+ The use of "::" indicates multiple groups of 16-bits of zeros.
+ The "::" can only appear once in an address. The "::" can also be
+ used to compress the leading and/or trailing zeros in an address.
+
+ For example the following addresses:
+
+ 1080:0:0:0:8:800:200C:417A a unicast address
+ FF01:0:0:0:0:0:0:101 a multicast address
+ 0:0:0:0:0:0:0:1 the loopback address
+ 0:0:0:0:0:0:0:0 the unspecified addresses
+
+ may be represented as:
+
+ 1080::8:800:200C:417A a unicast address
+ FF01::101 a multicast address
+ ::1 the loopback address
+ :: the unspecified addresses
+
+ 3. An alternative form that is sometimes more convenient when dealing
+ with a mixed environment of IPv4 and IPv6 nodes is
+ x:x:x:x:x:x:d.d.d.d, where the 'x's are the hexadecimal values of
+ the six high-order 16-bit pieces of the address, and the 'd's are
+ the decimal values of the four low-order 8-bit pieces of the
+ address (standard IPv4 representation). Examples:
+
+ 0:0:0:0:0:0:13.1.68.3
+
+ 0:0:0:0:0:FFFF:129.144.52.38
+
+ or in compressed form:
+
+ ::13.1.68.3
+
+ ::FFFF:129.144.52.38
+
+
+
+
+
+Hinden & Deering Standards Track [Page 4]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+2.3 Text Representation of Address Prefixes
+
+ The text representation of IPv6 address prefixes is similar to the
+ way IPv4 addresses prefixes are written in CIDR notation. An IPv6
+ address prefix is represented by the notation:
+
+ ipv6-address/prefix-length
+
+ where
+
+ ipv6-address is an IPv6 address in any of the notations listed
+ in section 2.2.
+
+ prefix-length is a decimal value specifying how many of the
+ leftmost contiguous bits of the address comprise
+ the prefix.
+
+ For example, the following are legal representations of the 60-bit
+ prefix 12AB00000000CD3 (hexadecimal):
+
+ 12AB:0000:0000:CD30:0000:0000:0000:0000/60
+ 12AB::CD30:0:0:0:0/60
+ 12AB:0:0:CD30::/60
+
+ The following are NOT legal representations of the above prefix:
+
+ 12AB:0:0:CD3/60 may drop leading zeros, but not trailing zeros,
+ within any 16-bit chunk of the address
+
+ 12AB::CD30/60 address to left of "/" expands to
+ 12AB:0000:0000:0000:0000:000:0000:CD30
+
+ 12AB::CD3/60 address to left of "/" expands to
+ 12AB:0000:0000:0000:0000:000:0000:0CD3
+
+ When writing both a node address and a prefix of that node address
+ (e.g., the node's subnet prefix), the two can combined as follows:
+
+ the node address 12AB:0:0:CD30:123:4567:89AB:CDEF
+ and its subnet number 12AB:0:0:CD30::/60
+
+ can be abbreviated as 12AB:0:0:CD30:123:4567:89AB:CDEF/60
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 5]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+2.4 Address Type Representation
+
+ The specific type of an IPv6 address is indicated by the leading bits
+ in the address. The variable-length field comprising these leading
+ bits is called the Format Prefix (FP). The initial allocation of
+ these prefixes is as follows:
+
+ Allocation Prefix Fraction of
+ (binary) Address Space
+ ----------------------------------- -------- -------------
+ Reserved 0000 0000 1/256
+ Unassigned 0000 0001 1/256
+
+ Reserved for NSAP Allocation 0000 001 1/128
+ Reserved for IPX Allocation 0000 010 1/128
+
+ Unassigned 0000 011 1/128
+ Unassigned 0000 1 1/32
+ Unassigned 0001 1/16
+
+ Aggregatable Global Unicast Addresses 001 1/8
+ Unassigned 010 1/8
+ Unassigned 011 1/8
+ Unassigned 100 1/8
+ Unassigned 101 1/8
+ Unassigned 110 1/8
+
+ Unassigned 1110 1/16
+ Unassigned 1111 0 1/32
+ Unassigned 1111 10 1/64
+ Unassigned 1111 110 1/128
+ Unassigned 1111 1110 0 1/512
+
+ Link-Local Unicast Addresses 1111 1110 10 1/1024
+ Site-Local Unicast Addresses 1111 1110 11 1/1024
+
+ Multicast Addresses 1111 1111 1/256
+
+ Notes:
+
+ (1) The "unspecified address" (see section 2.5.2), the loopback
+ address (see section 2.5.3), and the IPv6 Addresses with
+ Embedded IPv4 Addresses (see section 2.5.4), are assigned out
+ of the 0000 0000 format prefix space.
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 6]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ (2) The format prefixes 001 through 111, except for Multicast
+ Addresses (1111 1111), are all required to have to have 64-bit
+ interface identifiers in EUI-64 format. See section 2.5.1 for
+ definitions.
+
+ This allocation supports the direct allocation of aggregation
+ addresses, local use addresses, and multicast addresses. Space is
+ reserved for NSAP addresses and IPX addresses. The remainder of the
+ address space is unassigned for future use. This can be used for
+ expansion of existing use (e.g., additional aggregatable addresses,
+ etc.) or new uses (e.g., separate locators and identifiers). Fifteen
+ percent of the address space is initially allocated. The remaining
+ 85% is reserved for future use.
+
+ Unicast addresses are distinguished from multicast addresses by the
+ value of the high-order octet of the addresses: a value of FF
+ (11111111) identifies an address as a multicast address; any other
+ value identifies an address as a unicast address. Anycast addresses
+ are taken from the unicast address space, and are not syntactically
+ distinguishable from unicast addresses.
+
+2.5 Unicast Addresses
+
+ IPv6 unicast addresses are aggregatable with contiguous bit-wise
+ masks similar to IPv4 addresses under Class-less Interdomain Routing
+ [CIDR].
+
+ There are several forms of unicast address assignment in IPv6,
+ including the global aggregatable global unicast address, the NSAP
+ address, the IPX hierarchical address, the site-local address, the
+ link-local address, and the IPv4-capable host address. Additional
+ address types can be defined in the future.
+
+ IPv6 nodes may have considerable or little knowledge of the internal
+ structure of the IPv6 address, depending on the role the node plays
+ (for instance, host versus router). At a minimum, a node may
+ consider that unicast addresses (including its own) have no internal
+ structure:
+
+ | 128 bits |
+ +-----------------------------------------------------------------+
+ | node address |
+ +-----------------------------------------------------------------+
+
+ A slightly sophisticated host (but still rather simple) may
+ additionally be aware of subnet prefix(es) for the link(s) it is
+ attached to, where different addresses may have different values for
+ n:
+
+
+
+Hinden & Deering Standards Track [Page 7]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ | n bits | 128-n bits |
+ +------------------------------------------------+----------------+
+ | subnet prefix | interface ID |
+ +------------------------------------------------+----------------+
+
+ Still more sophisticated hosts may be aware of other hierarchical
+ boundaries in the unicast address. Though a very simple router may
+ have no knowledge of the internal structure of IPv6 unicast
+ addresses, routers will more generally have knowledge of one or more
+ of the hierarchical boundaries for the operation of routing
+ protocols. The known boundaries will differ from router to router,
+ depending on what positions the router holds in the routing
+ hierarchy.
+
+2.5.1 Interface Identifiers
+
+ Interface identifiers in IPv6 unicast addresses are used to identify
+ interfaces on a link. They are required to be unique on that link.
+ They may also be unique over a broader scope. In many cases an
+ interface's identifier will be the same as that interface's link-
+ layer address. The same interface identifier may be used on multiple
+ interfaces on a single node.
+
+ Note that the use of the same interface identifier on multiple
+ interfaces of a single node does not affect the interface
+ identifier's global uniqueness or each IPv6 addresses global
+ uniqueness created using that interface identifier.
+
+ In a number of the format prefixes (see section 2.4) Interface IDs
+ are required to be 64 bits long and to be constructed in IEEE EUI-64
+ format [EUI64]. EUI-64 based Interface identifiers may have global
+ scope when a global token is available (e.g., IEEE 48bit MAC) or may
+ have local scope where a global token is not available (e.g., serial
+ links, tunnel end-points, etc.). It is required that the "u" bit
+ (universal/local bit in IEEE EUI-64 terminology) be inverted when
+ forming the interface identifier from the EUI-64. The "u" bit is set
+ to one (1) to indicate global scope, and it is set to zero (0) to
+ indicate local scope. The first three octets in binary of an EUI-64
+ identifier are as follows:
+
+ 0 0 0 1 1 2
+ |0 7 8 5 6 3|
+ +----+----+----+----+----+----+
+ |cccc|ccug|cccc|cccc|cccc|cccc|
+ +----+----+----+----+----+----+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 8]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ written in Internet standard bit-order , where "u" is the
+ universal/local bit, "g" is the individual/group bit, and "c" are the
+ bits of the company_id. Appendix A: "Creating EUI-64 based Interface
+ Identifiers" provides examples on the creation of different EUI-64
+ based interface identifiers.
+
+ The motivation for inverting the "u" bit when forming the interface
+ identifier is to make it easy for system administrators to hand
+ configure local scope identifiers when hardware tokens are not
+ available. This is expected to be case for serial links, tunnel end-
+ points, etc. The alternative would have been for these to be of the
+ form 0200:0:0:1, 0200:0:0:2, etc., instead of the much simpler ::1,
+ ::2, etc.
+
+ The use of the universal/local bit in the IEEE EUI-64 identifier is
+ to allow development of future technology that can take advantage of
+ interface identifiers with global scope.
+
+ The details of forming interface identifiers are defined in the
+ appropriate "IPv6 over <link>" specification such as "IPv6 over
+ Ethernet" [ETHER], "IPv6 over FDDI" [FDDI], etc.
+
+2.5.2 The Unspecified Address
+
+ The address 0:0:0:0:0:0:0:0 is called the unspecified address. It
+ must never be assigned to any node. It indicates the absence of an
+ address. One example of its use is in the Source Address field of
+ any IPv6 packets sent by an initializing host before it has learned
+ its own address.
+
+ The unspecified address must not be used as the destination address
+ of IPv6 packets or in IPv6 Routing Headers.
+
+2.5.3 The Loopback Address
+
+ The unicast address 0:0:0:0:0:0:0:1 is called the loopback address.
+ It may be used by a node to send an IPv6 packet to itself. It may
+ never be assigned to any physical interface. It may be thought of as
+ being associated with a virtual interface (e.g., the loopback
+ interface).
+
+ The loopback address must not be used as the source address in IPv6
+ packets that are sent outside of a single node. An IPv6 packet with
+ a destination address of loopback must never be sent outside of a
+ single node and must never be forwarded by an IPv6 router.
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 9]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+2.5.4 IPv6 Addresses with Embedded IPv4 Addresses
+
+ The IPv6 transition mechanisms [TRAN] include a technique for hosts
+ and routers to dynamically tunnel IPv6 packets over IPv4 routing
+ infrastructure. IPv6 nodes that utilize this technique are assigned
+ special IPv6 unicast addresses that carry an IPv4 address in the low-
+ order 32-bits. This type of address is termed an "IPv4-compatible
+ IPv6 address" and has the format:
+
+ | 80 bits | 16 | 32 bits |
+ +--------------------------------------+--------------------------+
+ |0000..............................0000|0000| IPv4 address |
+ +--------------------------------------+----+---------------------+
+
+ A second type of IPv6 address which holds an embedded IPv4 address is
+ also defined. This address is used to represent the addresses of
+ IPv4-only nodes (those that *do not* support IPv6) as IPv6 addresses.
+ This type of address is termed an "IPv4-mapped IPv6 address" and has
+ the format:
+
+ | 80 bits | 16 | 32 bits |
+ +--------------------------------------+--------------------------+
+ |0000..............................0000|FFFF| IPv4 address |
+ +--------------------------------------+----+---------------------+
+
+2.5.5 NSAP Addresses
+
+ This mapping of NSAP address into IPv6 addresses is defined in
+ [NSAP]. This document recommends that network implementors who have
+ planned or deployed an OSI NSAP addressing plan, and who wish to
+ deploy or transition to IPv6, should redesign a native IPv6
+ addressing plan to meet their needs. However, it also defines a set
+ of mechanisms for the support of OSI NSAP addressing in an IPv6
+ network. These mechanisms are the ones that must be used if such
+ support is required. This document also defines a mapping of IPv6
+ addresses within the OSI address format, should this be required.
+
+2.5.6 IPX Addresses
+
+ This mapping of IPX address into IPv6 addresses is as follows:
+
+ | 7 | 121 bits |
+ +-------+---------------------------------------------------------+
+ |0000010| to be defined |
+ +-------+---------------------------------------------------------+
+
+ The draft definition, motivation, and usage are under study.
+
+
+
+
+Hinden & Deering Standards Track [Page 10]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+2.5.7 Aggregatable Global Unicast Addresses
+
+ The global aggregatable global unicast address is defined in [AGGR].
+ This address format is designed to support both the current provider
+ based aggregation and a new type of aggregation called exchanges.
+ The combination will allow efficient routing aggregation for both
+ sites which connect directly to providers and who connect to
+ exchanges. Sites will have the choice to connect to either type of
+ aggregation point.
+
+ The IPv6 aggregatable global unicast address format is as follows:
+
+ | 3| 13 | 8 | 24 | 16 | 64 bits |
+ +--+-----+---+--------+--------+--------------------------------+
+ |FP| TLA |RES| NLA | SLA | Interface ID |
+ | | ID | | ID | ID | |
+ +--+-----+---+--------+--------+--------------------------------+
+
+ Where
+
+ 001 Format Prefix (3 bit) for Aggregatable Global
+ Unicast Addresses
+ TLA ID Top-Level Aggregation Identifier
+ RES Reserved for future use
+ NLA ID Next-Level Aggregation Identifier
+ SLA ID Site-Level Aggregation Identifier
+ INTERFACE ID Interface Identifier
+
+ The contents, field sizes, and assignment rules are defined in
+ [AGGR].
+
+2.5.8 Local-Use IPv6 Unicast Addresses
+
+ There are two types of local-use unicast addresses defined. These
+ are Link-Local and Site-Local. The Link-Local is for use on a single
+ link and the Site-Local is for use in a single site. Link-Local
+ addresses have the following format:
+
+ | 10 |
+ | bits | 54 bits | 64 bits |
+ +----------+-------------------------+----------------------------+
+ |1111111010| 0 | interface ID |
+ +----------+-------------------------+----------------------------+
+
+ Link-Local addresses are designed to be used for addressing on a
+ single link for purposes such as auto-address configuration, neighbor
+ discovery, or when no routers are present.
+
+
+
+
+Hinden & Deering Standards Track [Page 11]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ Routers must not forward any packets with link-local source or
+ destination addresses to other links.
+
+ Site-Local addresses have the following format:
+
+ | 10 |
+ | bits | 38 bits | 16 bits | 64 bits |
+ +----------+-------------+-----------+----------------------------+
+ |1111111011| 0 | subnet ID | interface ID |
+ +----------+-------------+-----------+----------------------------+
+
+ Site-Local addresses are designed to be used for addressing inside of
+ a site without the need for a global prefix.
+
+ Routers must not forward any packets with site-local source or
+ destination addresses outside of the site.
+
+2.6 Anycast Addresses
+
+ An IPv6 anycast address is an address that is assigned to more than
+ one interface (typically belonging to different nodes), with the
+ property that a packet sent to an anycast address is routed to the
+ "nearest" interface having that address, according to the routing
+ protocols' measure of distance.
+
+ Anycast addresses are allocated from the unicast address space, using
+ any of the defined unicast address formats. Thus, anycast addresses
+ are syntactically indistinguishable from unicast addresses. When a
+ unicast address is assigned to more than one interface, thus turning
+ it into an anycast address, the nodes to which the address is
+ assigned must be explicitly configured to know that it is an anycast
+ address.
+
+ For any assigned anycast address, there is a longest address prefix P
+ that identifies the topological region in which all interfaces
+ belonging to that anycast address reside. Within the region
+ identified by P, each member of the anycast set must be advertised as
+ a separate entry in the routing system (commonly referred to as a
+ "host route"); outside the region identified by P, the anycast
+ address may be aggregated into the routing advertisement for prefix
+ P.
+
+ Note that in, the worst case, the prefix P of an anycast set may be
+ the null prefix, i.e., the members of the set may have no topological
+ locality. In that case, the anycast address must be advertised as a
+ separate routing entry throughout the entire internet, which presents
+
+
+
+
+
+Hinden & Deering Standards Track [Page 12]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ a severe scaling limit on how many such "global" anycast sets may be
+ supported. Therefore, it is expected that support for global anycast
+ sets may be unavailable or very restricted.
+
+ One expected use of anycast addresses is to identify the set of
+ routers belonging to an organization providing internet service.
+ Such addresses could be used as intermediate addresses in an IPv6
+ Routing header, to cause a packet to be delivered via a particular
+ aggregation or sequence of aggregations. Some other possible uses
+ are to identify the set of routers attached to a particular subnet,
+ or the set of routers providing entry into a particular routing
+ domain.
+
+ There is little experience with widespread, arbitrary use of internet
+ anycast addresses, and some known complications and hazards when
+ using them in their full generality [ANYCST]. Until more experience
+ has been gained and solutions agreed upon for those problems, the
+ following restrictions are imposed on IPv6 anycast addresses:
+
+ o An anycast address must not be used as the source address of an
+ IPv6 packet.
+
+ o An anycast address must not be assigned to an IPv6 host, that
+ is, it may be assigned to an IPv6 router only.
+
+2.6.1 Required Anycast Address
+
+ The Subnet-Router anycast address is predefined. Its format is as
+ follows:
+
+ | n bits | 128-n bits |
+ +------------------------------------------------+----------------+
+ | subnet prefix | 00000000000000 |
+ +------------------------------------------------+----------------+
+
+ The "subnet prefix" in an anycast address is the prefix which
+ identifies a specific link. This anycast address is syntactically
+ the same as a unicast address for an interface on the link with the
+ interface identifier set to zero.
+
+ Packets sent to the Subnet-Router anycast address will be delivered
+ to one router on the subnet. All routers are required to support the
+ Subnet-Router anycast addresses for the subnets which they have
+ interfaces.
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 13]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ The subnet-router anycast address is intended to be used for
+ applications where a node needs to communicate with one of a set of
+ routers on a remote subnet. For example when a mobile host needs to
+ communicate with one of the mobile agents on its "home" subnet.
+
+2.7 Multicast Addresses
+
+ An IPv6 multicast address is an identifier for a group of nodes. A
+ node may belong to any number of multicast groups. Multicast
+ addresses have the following format:
+
+ | 8 | 4 | 4 | 112 bits |
+ +------ -+----+----+---------------------------------------------+
+ |11111111|flgs|scop| group ID |
+ +--------+----+----+---------------------------------------------+
+
+ 11111111 at the start of the address identifies the address as
+ being a multicast address.
+
+ +-+-+-+-+
+ flgs is a set of 4 flags: |0|0|0|T|
+ +-+-+-+-+
+
+ The high-order 3 flags are reserved, and must be initialized to
+ 0.
+
+ T = 0 indicates a permanently-assigned ("well-known") multicast
+ address, assigned by the global internet numbering authority.
+
+ T = 1 indicates a non-permanently-assigned ("transient")
+ multicast address.
+
+ scop is a 4-bit multicast scope value used to limit the scope of
+ the multicast group. The values are:
+
+ 0 reserved
+ 1 node-local scope
+ 2 link-local scope
+ 3 (unassigned)
+ 4 (unassigned)
+ 5 site-local scope
+ 6 (unassigned)
+ 7 (unassigned)
+ 8 organization-local scope
+ 9 (unassigned)
+ A (unassigned)
+ B (unassigned)
+ C (unassigned)
+
+
+
+Hinden & Deering Standards Track [Page 14]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ D (unassigned)
+ E global scope
+ F reserved
+
+ group ID identifies the multicast group, either permanent or
+ transient, within the given scope.
+
+ The "meaning" of a permanently-assigned multicast address is
+ independent of the scope value. For example, if the "NTP servers
+ group" is assigned a permanent multicast address with a group ID of
+ 101 (hex), then:
+
+ FF01:0:0:0:0:0:0:101 means all NTP servers on the same node as the
+ sender.
+
+ FF02:0:0:0:0:0:0:101 means all NTP servers on the same link as the
+ sender.
+
+ FF05:0:0:0:0:0:0:101 means all NTP servers at the same site as the
+ sender.
+
+ FF0E:0:0:0:0:0:0:101 means all NTP servers in the internet.
+
+ Non-permanently-assigned multicast addresses are meaningful only
+ within a given scope. For example, a group identified by the non-
+ permanent, site-local multicast address FF15:0:0:0:0:0:0:101 at one
+ site bears no relationship to a group using the same address at a
+ different site, nor to a non-permanent group using the same group ID
+ with different scope, nor to a permanent group with the same group
+ ID.
+
+ Multicast addresses must not be used as source addresses in IPv6
+ packets or appear in any routing header.
+
+2.7.1 Pre-Defined Multicast Addresses
+
+ The following well-known multicast addresses are pre-defined:
+
+ Reserved Multicast Addresses: FF00:0:0:0:0:0:0:0
+ FF01:0:0:0:0:0:0:0
+ FF02:0:0:0:0:0:0:0
+ FF03:0:0:0:0:0:0:0
+ FF04:0:0:0:0:0:0:0
+ FF05:0:0:0:0:0:0:0
+ FF06:0:0:0:0:0:0:0
+ FF07:0:0:0:0:0:0:0
+ FF08:0:0:0:0:0:0:0
+ FF09:0:0:0:0:0:0:0
+
+
+
+Hinden & Deering Standards Track [Page 15]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ FF0A:0:0:0:0:0:0:0
+ FF0B:0:0:0:0:0:0:0
+ FF0C:0:0:0:0:0:0:0
+ FF0D:0:0:0:0:0:0:0
+ FF0E:0:0:0:0:0:0:0
+ FF0F:0:0:0:0:0:0:0
+
+ The above multicast addresses are reserved and shall never be
+ assigned to any multicast group.
+
+ All Nodes Addresses: FF01:0:0:0:0:0:0:1
+ FF02:0:0:0:0:0:0:1
+
+ The above multicast addresses identify the group of all IPv6 nodes,
+ within scope 1 (node-local) or 2 (link-local).
+
+ All Routers Addresses: FF01:0:0:0:0:0:0:2
+ FF02:0:0:0:0:0:0:2
+ FF05:0:0:0:0:0:0:2
+
+ The above multicast addresses identify the group of all IPv6 routers,
+ within scope 1 (node-local), 2 (link-local), or 5 (site-local).
+
+ Solicited-Node Address: FF02:0:0:0:0:1:FFXX:XXXX
+
+ The above multicast address is computed as a function of a node's
+ unicast and anycast addresses. The solicited-node multicast address
+ is formed by taking the low-order 24 bits of the address (unicast or
+ anycast) and appending those bits to the prefix
+ FF02:0:0:0:0:1:FF00::/104 resulting in a multicast address in the
+ range
+
+ FF02:0:0:0:0:1:FF00:0000
+
+ to
+
+ FF02:0:0:0:0:1:FFFF:FFFF
+
+ For example, the solicited node multicast address corresponding to
+ the IPv6 address 4037::01:800:200E:8C6C is FF02::1:FF0E:8C6C. IPv6
+ addresses that differ only in the high-order bits, e.g. due to
+ multiple high-order prefixes associated with different aggregations,
+ will map to the same solicited-node address thereby reducing the
+ number of multicast addresses a node must join.
+
+ A node is required to compute and join the associated Solicited-Node
+ multicast addresses for every unicast and anycast address it is
+ assigned.
+
+
+
+Hinden & Deering Standards Track [Page 16]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+2.7.2 Assignment of New IPv6 Multicast Addresses
+
+ The current approach [ETHER] to map IPv6 multicast addresses into
+ IEEE 802 MAC addresses takes the low order 32 bits of the IPv6
+ multicast address and uses it to create a MAC address. Note that
+ Token Ring networks are handled differently. This is defined in
+ [TOKEN]. Group ID's less than or equal to 32 bits will generate
+ unique MAC addresses. Due to this new IPv6 multicast addresses
+ should be assigned so that the group identifier is always in the low
+ order 32 bits as shown in the following:
+
+ | 8 | 4 | 4 | 80 bits | 32 bits |
+ +------ -+----+----+---------------------------+-----------------+
+ |11111111|flgs|scop| reserved must be zero | group ID |
+ +--------+----+----+---------------------------+-----------------+
+
+ While this limits the number of permanent IPv6 multicast groups to
+ 2^32 this is unlikely to be a limitation in the future. If it
+ becomes necessary to exceed this limit in the future multicast will
+ still work but the processing will be sightly slower.
+
+ Additional IPv6 multicast addresses are defined and registered by the
+ IANA [MASGN].
+
+2.8 A Node's Required Addresses
+
+ A host is required to recognize the following addresses as
+ identifying itself:
+
+ o Its Link-Local Address for each interface
+ o Assigned Unicast Addresses
+ o Loopback Address
+ o All-Nodes Multicast Addresses
+ o Solicited-Node Multicast Address for each of its assigned
+ unicast and anycast addresses
+ o Multicast Addresses of all other groups to which the host
+ belongs.
+
+ A router is required to recognize all addresses that a host is
+ required to recognize, plus the following addresses as identifying
+ itself:
+
+ o The Subnet-Router anycast addresses for the interfaces it is
+ configured to act as a router on.
+ o All other Anycast addresses with which the router has been
+ configured.
+ o All-Routers Multicast Addresses
+
+
+
+
+Hinden & Deering Standards Track [Page 17]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ o Multicast Addresses of all other groups to which the router
+ belongs.
+
+ The only address prefixes which should be predefined in an
+ implementation are the:
+
+ o Unspecified Address
+ o Loopback Address
+ o Multicast Prefix (FF)
+ o Local-Use Prefixes (Link-Local and Site-Local)
+ o Pre-Defined Multicast Addresses
+ o IPv4-Compatible Prefixes
+
+ Implementations should assume all other addresses are unicast unless
+ specifically configured (e.g., anycast addresses).
+
+3. Security Considerations
+
+ IPv6 addressing documents do not have any direct impact on Internet
+ infrastructure security. Authentication of IPv6 packets is defined
+ in [AUTH].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 18]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+APPENDIX A : Creating EUI-64 based Interface Identifiers
+--------------------------------------------------------
+
+ Depending on the characteristics of a specific link or node there are
+ a number of approaches for creating EUI-64 based interface
+ identifiers. This appendix describes some of these approaches.
+
+Links or Nodes with EUI-64 Identifiers
+
+ The only change needed to transform an EUI-64 identifier to an
+ interface identifier is to invert the "u" (universal/local) bit. For
+ example, a globally unique EUI-64 identifier of the form:
+
+ |0 1|1 3|3 4|4 6|
+ |0 5|6 1|2 7|8 3|
+ +----------------+----------------+----------------+----------------+
+ |cccccc0gcccccccc|ccccccccmmmmmmmm|mmmmmmmmmmmmmmmm|mmmmmmmmmmmmmmmm|
+ +----------------+----------------+----------------+----------------+
+
+ where "c" are the bits of the assigned company_id, "0" is the value
+ of the universal/local bit to indicate global scope, "g" is
+ individual/group bit, and "m" are the bits of the manufacturer-
+ selected extension identifier. The IPv6 interface identifier would
+ be of the form:
+
+ |0 1|1 3|3 4|4 6|
+ |0 5|6 1|2 7|8 3|
+ +----------------+----------------+----------------+----------------+
+ |cccccc1gcccccccc|ccccccccmmmmmmmm|mmmmmmmmmmmmmmmm|mmmmmmmmmmmmmmmm|
+ +----------------+----------------+----------------+----------------+
+
+ The only change is inverting the value of the universal/local bit.
+
+Links or Nodes with IEEE 802 48 bit MAC's
+
+ [EUI64] defines a method to create a EUI-64 identifier from an IEEE
+ 48bit MAC identifier. This is to insert two octets, with hexadecimal
+ values of 0xFF and 0xFE, in the middle of the 48 bit MAC (between the
+ company_id and vendor supplied id). For example the 48 bit MAC with
+ global scope:
+
+ |0 1|1 3|3 4|
+ |0 5|6 1|2 7|
+ +----------------+----------------+----------------+
+ |cccccc0gcccccccc|ccccccccmmmmmmmm|mmmmmmmmmmmmmmmm|
+ +----------------+----------------+----------------+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 19]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ where "c" are the bits of the assigned company_id, "0" is the value
+ of the universal/local bit to indicate global scope, "g" is
+ individual/group bit, and "m" are the bits of the manufacturer-
+ selected extension identifier. The interface identifier would be of
+ the form:
+
+ |0 1|1 3|3 4|4 6|
+ |0 5|6 1|2 7|8 3|
+ +----------------+----------------+----------------+----------------+
+ |cccccc1gcccccccc|cccccccc11111111|11111110mmmmmmmm|mmmmmmmmmmmmmmmm|
+ +----------------+----------------+----------------+----------------+
+
+ When IEEE 802 48bit MAC addresses are available (on an interface or a
+ node), an implementation should use them to create interface
+ identifiers due to their availability and uniqueness properties.
+
+Links with Non-Global Identifiers
+
+ There are a number of types of links that, while multi-access, do not
+ have globally unique link identifiers. Examples include LocalTalk
+ and Arcnet. The method to create an EUI-64 formatted identifier is
+ to take the link identifier (e.g., the LocalTalk 8 bit node
+ identifier) and zero fill it to the left. For example a LocalTalk 8
+ bit node identifier of hexadecimal value 0x4F results in the
+ following interface identifier:
+
+ |0 1|1 3|3 4|4 6|
+ |0 5|6 1|2 7|8 3|
+ +----------------+----------------+----------------+----------------+
+ |0000000000000000|0000000000000000|0000000000000000|0000000001001111|
+ +----------------+----------------+----------------+----------------+
+
+ Note that this results in the universal/local bit set to "0" to
+ indicate local scope.
+
+Links without Identifiers
+
+ There are a number of links that do not have any type of built-in
+ identifier. The most common of these are serial links and configured
+ tunnels. Interface identifiers must be chosen that are unique for
+ the link.
+
+ When no built-in identifier is available on a link the preferred
+ approach is to use a global interface identifier from another
+ interface or one which is assigned to the node itself. To use this
+ approach no other interface connecting the same node to the same link
+ may use the same identifier.
+
+
+
+
+Hinden & Deering Standards Track [Page 20]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+ If there is no global interface identifier available for use on the
+ link the implementation needs to create a local scope interface
+ identifier. The only requirement is that it be unique on the link.
+ There are many possible approaches to select a link-unique interface
+ identifier. They include:
+
+ Manual Configuration
+ Generated Random Number
+ Node Serial Number (or other node-specific token)
+
+ The link-unique interface identifier should be generated in a manner
+ that it does not change after a reboot of a node or if interfaces are
+ added or deleted from the node.
+
+ The selection of the appropriate algorithm is link and implementation
+ dependent. The details on forming interface identifiers are defined
+ in the appropriate "IPv6 over <link>" specification. It is strongly
+ recommended that a collision detection algorithm be implemented as
+ part of any automatic algorithm.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 21]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+APPENDIX B: ABNF Description of Text Representations
+----------------------------------------------------
+
+ This appendix defines the text representation of IPv6 addresses and
+ prefixes in Augmented BNF [ABNF] for reference purposes.
+
+ IPv6address = hexpart [ ":" IPv4address ]
+ IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
+
+ IPv6prefix = hexpart "/" 1*2DIGIT
+
+ hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ]
+ hexseq = hex4 *( ":" hex4)
+ hex4 = 1*4HEXDIG
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 22]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+APPENDIX C: CHANGES FROM RFC-1884
+---------------------------------
+
+ The following changes were made from RFC-1884 "IP Version 6
+ Addressing Architecture":
+
+ - Added an appendix providing a ABNF description of text
+ representations.
+ - Clarification that link unique identifiers not change after
+ reboot or other interface reconfigurations.
+ - Clarification of Address Model based on comments.
+ - Changed aggregation format terminology to be consistent with
+ aggregation draft.
+ - Added text to allow interface identifier to be used on more than
+ one interface on same node.
+ - Added rules for defining new multicast addresses.
+ - Added appendix describing procedures for creating EUI-64 based
+ interface ID's.
+ - Added notation for defining IPv6 prefixes.
+ - Changed solicited node multicast definition to use a longer
+ prefix.
+ - Added site scope all routers multicast address.
+ - Defined Aggregatable Global Unicast Addresses to use "001" Format
+ Prefix.
+ - Changed "010" (Provider-Based Unicast) and "100" (Reserved for
+ Geographic) Format Prefixes to Unassigned.
+ - Added section on Interface ID definition for unicast addresses.
+ Requires use of EUI-64 in range of format prefixes and rules for
+ setting global/local scope bit in EUI-64.
+ - Updated NSAP text to reflect working in RFC1888.
+ - Removed protocol specific IPv6 multicast addresses (e.g., DHCP)
+ and referenced the IANA definitions.
+ - Removed section "Unicast Address Example". Had become OBE.
+ - Added new and updated references.
+ - Minor text clarifications and improvements.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 23]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+REFERENCES
+
+ [ABNF] Crocker, D., and P. Overell, "Augmented BNF for
+ Syntax Specifications: ABNF", RFC 2234, November 1997.
+
+ [AGGR] Hinden, R., O'Dell, M., and S. Deering, "An
+ Aggregatable Global Unicast Address Format", RFC 2374, July
+ 1998.
+
+ [AUTH] Atkinson, R., "IP Authentication Header", RFC 1826, August
+ 1995.
+
+ [ANYCST] Partridge, C., Mendez, T., and W. Milliken, "Host
+ Anycasting Service", RFC 1546, November 1993.
+
+ [CIDR] Fuller, V., Li, T., Yu, J., and K. Varadhan, "Classless
+ Inter-Domain Routing (CIDR): An Address Assignment and
+ Aggregation Strategy", RFC 1519, September 1993.
+
+ [ETHER] Crawford, M., "Transmission of IPv6 Pacekts over Ethernet
+ Networks", Work in Progress.
+
+ [EUI64] IEEE, "Guidelines for 64-bit Global Identifier (EUI-64)
+ Registration Authority",
+ http://standards.ieee.org/db/oui/tutorials/EUI64.html,
+ March 1997.
+
+ [FDDI] Crawford, M., "Transmission of IPv6 Packets over FDDI
+ Networks", Work in Progress.
+
+ [IPV6] Deering, S., and R. Hinden, Editors, "Internet Protocol,
+ Version 6 (IPv6) Specification", RFC 1883, December 1995.
+
+ [MASGN] Hinden, R., and S. Deering, "IPv6 Multicast Address
+ Assignments", RFC 2375, July 1998.
+
+ [NSAP] Bound, J., Carpenter, B., Harrington, D., Houldsworth, J.,
+ and A. Lloyd, "OSI NSAPs and IPv6", RFC 1888, August 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [TOKEN] Thomas, S., "Transmission of IPv6 Packets over Token Ring
+ Networks", Work in Progress.
+
+ [TRAN] Gilligan, R., and E. Nordmark, "Transition Mechanisms for
+ IPv6 Hosts and Routers", RFC 1993, April 1996.
+
+
+
+
+Hinden & Deering Standards Track [Page 24]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+AUTHORS' ADDRESSES
+
+ Robert M. Hinden
+ Nokia
+ 232 Java Drive
+ Sunnyvale, CA 94089
+ USA
+
+ Phone: +1 408 990-2004
+ Fax: +1 408 743-5677
+ EMail: hinden@iprg.nokia.com
+
+
+ Stephen E. Deering
+ Cisco Systems, Inc.
+ 170 West Tasman Drive
+ San Jose, CA 95134-1706
+ USA
+
+ Phone: +1 408 527-8213
+ Fax: +1 408 527-8254
+ EMail: deering@cisco.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 25]
+
+RFC 2373 IPv6 Addressing Architecture July 1998
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 26]
+
diff --git a/doc/rfc/rfc2374.txt b/doc/rfc/rfc2374.txt
new file mode 100644
index 0000000..e3c7f0d
--- /dev/null
+++ b/doc/rfc/rfc2374.txt
@@ -0,0 +1,675 @@
+
+
+
+
+
+
+Network Working Group R. Hinden
+Request for Comments: 2374 Nokia
+Obsoletes: 2073 M. O'Dell
+Category: Standards Track UUNET
+ S. Deering
+ Cisco
+ July 1998
+
+
+ An IPv6 Aggregatable Global Unicast Address Format
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+1.0 Introduction
+
+ This document defines an IPv6 aggregatable global unicast address
+ format for use in the Internet. The address format defined in this
+ document is consistent with the IPv6 Protocol [IPV6] and the "IPv6
+ Addressing Architecture" [ARCH]. It is designed to facilitate
+ scalable Internet routing.
+
+ This documented replaces RFC 2073, "An IPv6 Provider-Based Unicast
+ Address Format". RFC 2073 will become historic. The Aggregatable
+ Global Unicast Address Format is an improvement over RFC 2073 in a
+ number of areas. The major changes include removal of the registry
+ bits because they are not needed for route aggregation, support of
+ EUI-64 based interface identifiers, support of provider and exchange
+ based aggregation, separation of public and site topology, and new
+ aggregation based terminology.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC 2119].
+
+
+
+
+
+
+
+
+Hinden, et. al. Standards Track [Page 1]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+2.0 Overview of the IPv6 Address
+
+ IPv6 addresses are 128-bit identifiers for interfaces and sets of
+ interfaces. There are three types of addresses: Unicast, Anycast,
+ and Multicast. This document defines a specific type of Unicast
+ address.
+
+ In this document, fields in addresses are given specific names, for
+ example "subnet". When this name is used with the term "ID" (for
+ "identifier") after the name (e.g., "subnet ID"), it refers to the
+ contents of the named field. When it is used with the term "prefix"
+ (e.g. "subnet prefix") it refers to all of the addressing bits to
+ the left of and including this field.
+
+ IPv6 unicast addresses are designed assuming that the Internet
+ routing system makes forwarding decisions based on a "longest prefix
+ match" algorithm on arbitrary bit boundaries and does not have any
+ knowledge of the internal structure of IPv6 addresses. The structure
+ in IPv6 addresses is for assignment and allocation. The only
+ exception to this is the distinction made between unicast and
+ multicast addresses.
+
+ The specific type of an IPv6 address is indicated by the leading bits
+ in the address. The variable-length field comprising these leading
+ bits is called the Format Prefix (FP).
+
+ This document defines an address format for the 001 (binary) Format
+ Prefix for Aggregatable Global Unicast addresses. The same address
+ format could be used for other Format Prefixes, as long as these
+ Format Prefixes also identify IPv6 unicast addresses. Only the "001"
+ Format Prefix is defined here.
+
+3.0 IPv6 Aggregatable Global Unicast Address Format
+
+ This document defines an address format for the IPv6 aggregatable
+ global unicast address assignment. The authors believe that this
+ address format will be widely used for IPv6 nodes connected to the
+ Internet. This address format is designed to support both the
+ current provider-based aggregation and a new type of exchange-based
+ aggregation. The combination will allow efficient routing
+ aggregation for sites that connect directly to providers and for
+ sites that connect to exchanges. Sites will have the choice to
+ connect to either type of aggregation entity.
+
+
+
+
+
+
+
+
+Hinden, et. al. Standards Track [Page 2]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+ While this address format is designed to support exchange-based
+ aggregation (in addition to current provider-based aggregation) it is
+ not dependent on exchanges for it's overall route aggregation
+ properties. It will provide efficient route aggregation with only
+ provider-based aggregation.
+
+ Aggregatable addresses are organized into a three level hierarchy:
+
+ - Public Topology
+ - Site Topology
+ - Interface Identifier
+
+ Public topology is the collection of providers and exchanges who
+ provide public Internet transit services. Site topology is local to
+ a specific site or organization which does not provide public transit
+ service to nodes outside of the site. Interface identifiers identify
+ interfaces on links.
+
+ ______________ ______________
+ --+/ \+--------------+/ \+----------
+ ( P1 ) +----+ ( P3 ) +----+
+ +\______________/ | |----+\______________/+--| |--
+ | +--| X1 | +| X2 |
+ | ______________ / | |-+ ______________ / | |--
+ +/ \+ +-+--+ \ / \+ +----+
+ ( P2 ) / \ +( P4 )
+ --+\______________/ / \ \______________/
+ | / \ | |
+ | / | | |
+ | / | | |
+ _|_ _/_ _|_ _|_ _|_
+ / \ / \ / \ / \ / \
+ ( S.A ) ( S.B ) ( P5 ) ( P6 )( S.C )
+ \___/ \___/ \___/ \___/ \___/
+ | / \
+ _|_ _/_ \ ___
+ / \ / \ +-/ \
+ ( S.D ) ( S.E ) ( S.F )
+ \___/ \___/ \___/
+
+ As shown in the figure above, the aggregatable address format is
+ designed to support long-haul providers (shown as P1, P2, P3, and
+ P4), exchanges (shown as X1 and X2), multiple levels of providers
+ (shown at P5 and P6), and subscribers (shown as S.x) Exchanges
+ (unlike current NAPs, FIXes, etc.) will allocate IPv6 addresses.
+ Organizations who connect to these exchanges will also subscribe
+ (directly, indirectly via the exchange, etc.) for long-haul service
+ from one or more long-haul providers. Doing so, they will achieve
+
+
+
+Hinden, et. al. Standards Track [Page 3]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+ addressing independence from long-haul transit providers. They will
+ be able to change long-haul providers without having to renumber
+ their organization. They can also be multihomed via the exchange to
+ more than one long-haul provider without having to have address
+ prefixes from each long-haul provider. Note that the mechanisms used
+ for this type of provider selection and portability are not discussed
+ in the document.
+
+3.1 Aggregatable Global Unicast Address Structure
+
+ The aggregatable global unicast address format is as follows:
+
+ | 3| 13 | 8 | 24 | 16 | 64 bits |
+ +--+-----+---+--------+--------+--------------------------------+
+ |FP| TLA |RES| NLA | SLA | Interface ID |
+ | | ID | | ID | ID | |
+ +--+-----+---+--------+--------+--------------------------------+
+
+ <--Public Topology---> Site
+ <-------->
+ Topology
+ <------Interface Identifier----->
+
+ Where
+
+ FP Format Prefix (001)
+ TLA ID Top-Level Aggregation Identifier
+ RES Reserved for future use
+ NLA ID Next-Level Aggregation Identifier
+ SLA ID Site-Level Aggregation Identifier
+ INTERFACE ID Interface Identifier
+
+ The following sections specify each part of the IPv6 Aggregatable
+ Global Unicast address format.
+
+3.2 Top-Level Aggregation ID
+
+ Top-Level Aggregation Identifiers (TLA ID) are the top level in the
+ routing hierarchy. Default-free routers must have a routing table
+ entry for every active TLA ID and will probably have additional
+ entries providing routing information for the TLA ID in which they
+ are located. They may have additional entries in order to optimize
+ routing for their specific topology, but the routing topology at all
+ levels must be designed to minimize the number of additional entries
+ fed into the default free routing tables.
+
+
+
+
+
+
+Hinden, et. al. Standards Track [Page 4]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+ This addressing format supports 8,192 (2^13) TLA ID's. Additional
+ TLA ID's may be added by either growing the TLA field to the right
+ into the reserved field or by using this format for additional format
+ prefixes.
+
+ The issues relating to TLA ID assignment are beyond the scope of this
+ document. They will be described in a document under preparation.
+
+3.3 Reserved
+
+ The Reserved field is reserved for future use and must be set to
+ zero.
+
+ The Reserved field allows for future growth of the TLA and NLA fields
+ as appropriate. See section 4.0 for a discussion.
+
+3.4 Next-Level Aggregation Identifier
+
+ Next-Level Aggregation Identifier's are used by organizations
+ assigned a TLA ID to create an addressing hierarchy and to identify
+ sites. The organization can assign the top part of the NLA ID in a
+ manner to create an addressing hierarchy appropriate to its network.
+ It can use the remainder of the bits in the field to identify sites
+ it wishes to serve. This is shown as follows:
+
+ | n | 24-n bits | 16 | 64 bits |
+ +-----+--------------------+--------+-----------------+
+ |NLA1 | Site ID | SLA ID | Interface ID |
+ +-----+--------------------+--------+-----------------+
+
+ Each organization assigned a TLA ID receives 24 bits of NLA ID space.
+ This NLA ID space allows each organization to provide service to
+ approximately as many organizations as the current IPv4 Internet can
+ support total networks.
+
+ Organizations assigned TLA ID's may also support NLA ID's in their
+ own Site ID space. This allows the organization assigned a TLA ID to
+ provide service to organizations providing public transit service and
+ to organizations who do not provide public transit service. These
+ organizations receiving an NLA ID may also choose to use their Site
+ ID space to support other NLA ID's. This is shown as follows:
+
+
+
+
+
+
+
+
+
+
+Hinden, et. al. Standards Track [Page 5]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+ | n | 24-n bits | 16 | 64 bits |
+ +-----+--------------------+--------+-----------------+
+ |NLA1 | Site ID | SLA ID | Interface ID |
+ +-----+--------------------+--------+-----------------+
+
+ | m | 24-n-m | 16 | 64 bits |
+ +-----+--------------+--------+-----------------+
+ |NLA2 | Site ID | SLA ID | Interface ID |
+ +-----+--------------+--------+-----------------+
+
+ | o |24-n-m-o| 16 | 64 bits |
+ +-----+--------+--------+-----------------+
+ |NLA3 | Site ID| SLA ID | Interface ID |
+ +-----+--------+--------+-----------------+
+
+ The design of the bit layout of the NLA ID space for a specific TLA
+ ID is left to the organization responsible for that TLA ID. Likewise
+ the design of the bit layout of the next level NLA ID is the
+ responsibility of the previous level NLA ID. It is recommended that
+ organizations assigning NLA address space use "slow start" allocation
+ procedures similar to [RFC2050].
+
+ The design of an NLA ID allocation plan is a tradeoff between routing
+ aggregation efficiency and flexibility. Creating hierarchies allows
+ for greater amount of aggregation and results in smaller routing
+ tables. Flat NLA ID assignment provides for easier allocation and
+ attachment flexibility, but results in larger routing tables.
+
+3.5 Site-Level Aggregation Identifier
+
+ The SLA ID field is used by an individual organization to create its
+ own local addressing hierarchy and to identify subnets. This is
+ analogous to subnets in IPv4 except that each organization has a much
+ greater number of subnets. The 16 bit SLA ID field support 65,535
+ individual subnets.
+
+ Organizations may choose to either route their SLA ID "flat" (e.g.,
+ not create any logical relationship between the SLA identifiers that
+ results in larger routing tables), or to create a two or more level
+ hierarchy (that results in smaller routing tables) in the SLA ID
+ field. The latter is shown as follows:
+
+
+
+
+
+
+
+
+
+
+Hinden, et. al. Standards Track [Page 6]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+ | n | 16-n | 64 bits |
+ +-----+------------+-------------------------------------+
+ |SLA1 | Subnet | Interface ID |
+ +-----+------------+-------------------------------------+
+
+ | m |16-n-m | 64 bits |
+ +----+-------+-------------------------------------+
+ |SLA2|Subnet | Interface ID |
+ +----+-------+-------------------------------------+
+
+ The approach chosen for structuring an SLA ID field is the
+ responsibility of the individual organization.
+
+ The number of subnets supported in this address format should be
+ sufficient for all but the largest of organizations. Organizations
+ which need additional subnets can arrange with the organization they
+ are obtaining Internet service from to obtain additional site
+ identifiers and use this to create additional subnets.
+
+3.6 Interface ID
+
+ Interface identifiers are used to identify interfaces on a link.
+ They are required to be unique on that link. They may also be unique
+ over a broader scope. In many cases an interfaces identifier will be
+ the same or be based on the interface's link-layer address.
+ Interface IDs used in the aggregatable global unicast address format
+ are required to be 64 bits long and to be constructed in IEEE EUI-64
+ format [EUI-64]. These identifiers may have global scope when a
+ global token (e.g., IEEE 48bit MAC) is available or may have local
+ scope where a global token is not available (e.g., serial links,
+ tunnel end-points, etc.). The "u" bit (universal/local bit in IEEE
+ EUI-64 terminology) in the EUI-64 identifier must be set correctly,
+ as defined in [ARCH], to indicate global or local scope.
+
+ The procedures for creating EUI-64 based Interface Identifiers is
+ defined in [ARCH]. The details on forming interface identifiers is
+ defined in the appropriate "IPv6 over <link>" specification such as
+ "IPv6 over Ethernet" [ETHER], "IPv6 over FDDI" [FDDI], etc.
+
+4.0 Technical Motivation
+
+ The design choices for the size of the fields in the aggregatable
+ address format were based on the need to meet a number of technical
+ requirements. These are described in the following paragraphs.
+
+ The size of the Top-Level Aggregation Identifier is 13 bits. This
+ allows for 8,192 TLA ID's. This size was chosen to insure that the
+ default-free routing table in top level routers in the Internet is
+
+
+
+Hinden, et. al. Standards Track [Page 7]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+ kept within the limits, with a reasonable margin, of the current
+ routing technology. The margin is important because default-free
+ routers will also carry a significant number of longer (i.e., more-
+ specific) prefixes for optimizing paths internal to a TLA and between
+ TLAs.
+
+ The important issue is not only the size of the default-free routing
+ table, but the complexity of the topology that determines the number
+ of copies of the default-free routes that a router must examine while
+ computing a forwarding table. Current practice with IPv4 it is
+ common to see a prefix announced fifteen times via different paths.
+
+ The complexity of Internet topology is very likely to increase in the
+ future. It is important that IPv6 default-free routing support
+ additional complexity as well as a considerably larger internet.
+
+ It should be noted for comparison that at the time of this writing
+ (spring, 1998) the IPv4 default-free routing table contains
+ approximately 50,000 prefixes. While this shows that it is possible
+ to support more routes than 8,192 it is matter of debate if the
+ number of prefixes supported today in IPv4 is already too high for
+ current routing technology. There are serious issues of route
+ stability as well as cases of providers not supporting all top level
+ prefixes. The technical requirement was to pick a TLA ID size that
+ was below, with a reasonable margin, what was being done with IPv4.
+
+ The choice of 13 bits for the TLA field was an engineering
+ compromise. Fewer bits would have been too small by not supporting
+ enough top level organizations. More bits would have exceeded what
+ can be reasonably accommodated, with a reasonable margin, with
+ current routing technology in order to deal with the issues described
+ in the previous paragraphs.
+
+ If in the future, routing technology improves to support a larger
+ number of top level routes in the default-free routing tables there
+ are two choices on how to increase the number TLA identifiers. The
+ first is to expand the TLA ID field into the reserved field. This
+ would increase the number of TLA ID's to approximately 2 million.
+ The second approach is to allocate another format prefix (FP) for use
+ with this address format. Either or a combination of these
+ approaches allows the number of TLA ID's to increase significantly.
+
+ The size of the Reserved field is 8 bits. This size was chosen to
+ allow significant growth of either the TLA ID and/or the NLA ID
+ fields.
+
+ The size of the Next-Level Aggregation Identifier field is 24 bits.
+
+
+
+
+Hinden, et. al. Standards Track [Page 8]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+ This allows for approximately sixteen million NLA ID's if used in a
+ flat manner. Used hierarchically it allows for a complexity roughly
+ equivalent to the IPv4 address space (assuming an average network
+ size of 254 interfaces). If in the future additional room for
+ complexity is needed in the NLA ID, this may be accommodated by
+ extending the NLA ID into the Reserved field.
+
+ The size of the Site-Level Aggregation Identifier field is 16 bits.
+ This supports 65,535 individual subnets per site. The design goal
+ for the size of this field was to be sufficient for all but the
+ largest of organizations. Organizations which need additional
+ subnets can arrange with the organization they are obtaining Internet
+ service from to obtain additional site identifiers and use this to
+ create additional subnets.
+
+ The Site-Level Aggregation Identifier field was given a fixed size in
+ order to force the length of all prefixes identifying a particular
+ site to be the same length (i.e., 48 bits). This facilitates
+ movement of sites in the topology (e.g., changing service providers
+ and multi-homing to multiple service providers).
+
+ The Interface ID Interface Identifier field is 64 bits. This size
+ was chosen to meet the requirement specified in [ARCH] to support
+ EUI-64 based Interface Identifiers.
+
+5.0 Acknowledgments
+
+ The authors would like to express our thanks to Thomas Narten, Bob
+ Fink, Matt Crawford, Allison Mankin, Jim Bound, Christian Huitema,
+ Scott Bradner, Brian Carpenter, John Stewart, and Daniel Karrenberg
+ for their review and constructive comments.
+
+6.0 References
+
+ [ALLOC] IAB and IESG, "IPv6 Address Allocation Management",
+ RFC 1881, December 1995.
+
+ [ARCH] Hinden, R., "IP Version 6 Addressing Architecture",
+ RFC 2373, July 1998.
+
+ [AUTH] Atkinson, R., "IP Authentication Header", RFC 1826, August
+ 1995.
+
+ [AUTO] Thompson, S., and T. Narten., "IPv6 Stateless Address
+ Autoconfiguration", RFC 1971, August 1996.
+
+ [ETHER] Crawford, M., "Transmission of IPv6 Packets over Ethernet
+ Networks", Work in Progress.
+
+
+
+Hinden, et. al. Standards Track [Page 9]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+ [EUI64] IEEE, "Guidelines for 64-bit Global Identifier (EUI-64)
+ Registration Authority",
+ http://standards.ieee.org/db/oui/tutorials/EUI64.html,
+ March 1997.
+
+ [FDDI] Crawford, M., "Transmission of IPv6 Packets over FDDI
+ Networks", Work in Progress.
+
+ [IPV6] Deering, S., and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 1883, December 1995.
+
+ [RFC2050] Hubbard, K., Kosters, M., Conrad, D., Karrenberg, D.,
+ and J. Postel, "Internet Registry IP Allocation
+ Guidelines", BCP 12, RFC 1466, November 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+7.0 Security Considerations
+
+ IPv6 addressing documents do not have any direct impact on Internet
+ infrastructure security. Authentication of IPv6 packets is defined
+ in [AUTH].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden, et. al. Standards Track [Page 10]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+8.0 Authors' Addresses
+
+ Robert M. Hinden
+ Nokia
+ 232 Java Drive
+ Sunnyvale, CA 94089
+ USA
+
+ Phone: 1 408 990-2004
+ EMail: hinden@iprg.nokia.com
+
+
+ Mike O'Dell
+ UUNET Technologies, Inc.
+ 3060 Williams Drive
+ Fairfax, VA 22030
+ USA
+
+ Phone: 1 703 206-5890
+ EMail: mo@uunet.uu.net
+
+
+ Stephen E. Deering
+ Cisco Systems, Inc.
+ 170 West Tasman Drive
+ San Jose, CA 95134-1706
+ USA
+
+ Phone: 1 408 527-8213
+ EMail: deering@cisco.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden, et. al. Standards Track [Page 11]
+
+RFC 2374 IPv6 Global Unicast Address Format July 1998
+
+
+9.0 Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden, et. al. Standards Track [Page 12]
+
diff --git a/doc/rfc/rfc2375.txt b/doc/rfc/rfc2375.txt
new file mode 100644
index 0000000..a1fe8b9
--- /dev/null
+++ b/doc/rfc/rfc2375.txt
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+Network Working Group R. Hinden
+Request for Comments: 2375 Ipsilon Networks
+Category: Informational S. Deering
+ Cisco
+ July 1998
+
+
+ IPv6 Multicast Address Assignments
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+1.0 Introduction
+
+ This document defines the initial assignment of IPv6 multicast
+ addresses. It is based on the "IP Version 6 Addressing Architecture"
+ [ADDARCH] and current IPv4 multicast address assignment found in
+ <ftp://venera.isi.edu/in-notes/iana/assignments/multicast-addresses>.
+ It adapts the IPv4 assignments that are relevant to IPv6 assignments.
+ IPv4 assignments that were not relevant were not converted into IPv6
+ assignments. Comments are solicited on this conversion.
+
+ All other IPv6 multicast addresses are reserved.
+
+ Sections 2 and 3 specify reserved and preassigned IPv6 multicast
+ addresses.
+
+ [ADDRARCH] defines rules for assigning new IPv6 multicast addresses.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC 2119].
+
+2. Fixed Scope Multicast Addresses
+
+ These permanently assigned multicast addresses are valid over a
+ specified scope value.
+
+
+
+
+
+
+
+Hinden & Deering Informational [Page 1]
+
+RFC 2375 IPv6 Multicast Address Assignments July 1998
+
+
+2.1 Node-Local Scope
+
+ FF01:0:0:0:0:0:0:1 All Nodes Address [ADDARCH]
+ FF01:0:0:0:0:0:0:2 All Routers Address [ADDARCH]
+
+2.2 Link-Local Scope
+
+ FF02:0:0:0:0:0:0:1 All Nodes Address [ADDARCH]
+ FF02:0:0:0:0:0:0:2 All Routers Address [ADDARCH]
+ FF02:0:0:0:0:0:0:3 Unassigned [JBP]
+ FF02:0:0:0:0:0:0:4 DVMRP Routers [RFC1075,JBP]
+ FF02:0:0:0:0:0:0:5 OSPFIGP [RFC2328,Moy]
+ FF02:0:0:0:0:0:0:6 OSPFIGP Designated Routers [RFC2328,Moy]
+ FF02:0:0:0:0:0:0:7 ST Routers [RFC1190,KS14]
+ FF02:0:0:0:0:0:0:8 ST Hosts [RFC1190,KS14]
+ FF02:0:0:0:0:0:0:9 RIP Routers [RFC2080]
+ FF02:0:0:0:0:0:0:A EIGRP Routers [Farinacci]
+ FF02:0:0:0:0:0:0:B Mobile-Agents [Bill Simpson]
+
+ FF02:0:0:0:0:0:0:D All PIM Routers [Farinacci]
+ FF02:0:0:0:0:0:0:E RSVP-ENCAPSULATION [Braden]
+
+ FF02:0:0:0:0:0:1:1 Link Name [Harrington]
+ FF02:0:0:0:0:0:1:2 All-dhcp-agents [Bound,Perkins]
+
+ FF02:0:0:0:0:1:FFXX:XXXX Solicited-Node Address [ADDARCH]
+
+2.3 Site-Local Scope
+
+ FF05:0:0:0:0:0:0:2 All Routers Address [ADDARCH]
+
+ FF05:0:0:0:0:0:1:3 All-dhcp-servers [Bound,Perkins]
+ FF05:0:0:0:0:0:1:4 All-dhcp-relays [Bound,Perkins]
+ FF05:0:0:0:0:0:1:1000 Service Location [RFC2165]
+ -FF05:0:0:0:0:0:1:13FF
+
+3.0 All Scope Multicast Addresses
+
+ These permanently assigned multicast addresses are valid over all
+ scope ranges. This is shown by an "X" in the scope field of the
+ address that means any legal scope value.
+
+ Note that, as defined in [ADDARCH], IPv6 multicast addresses which
+ are only different in scope represent different groups. Nodes must
+ join each group individually.
+
+ The IPv6 multicast addresses with variable scope are as follows:
+
+
+
+
+Hinden & Deering Informational [Page 2]
+
+RFC 2375 IPv6 Multicast Address Assignments July 1998
+
+
+ FF0X:0:0:0:0:0:0:0 Reserved Multicast Address [ADDARCH]
+
+ FF0X:0:0:0:0:0:0:100 VMTP Managers Group [RFC1045,DRC3]
+ FF0X:0:0:0:0:0:0:101 Network Time Protocol (NTP) [RFC1119,DLM1]
+ FF0X:0:0:0:0:0:0:102 SGI-Dogfight [AXC]
+ FF0X:0:0:0:0:0:0:103 Rwhod [SXD]
+ FF0X:0:0:0:0:0:0:104 VNP [DRC3]
+ FF0X:0:0:0:0:0:0:105 Artificial Horizons - Aviator [BXF]
+ FF0X:0:0:0:0:0:0:106 NSS - Name Service Server [BXS2]
+ FF0X:0:0:0:0:0:0:107 AUDIONEWS - Audio News Multicast [MXF2]
+ FF0X:0:0:0:0:0:0:108 SUN NIS+ Information Service [CXM3]
+ FF0X:0:0:0:0:0:0:109 MTP Multicast Transport Protocol [SXA]
+ FF0X:0:0:0:0:0:0:10A IETF-1-LOW-AUDIO [SC3]
+ FF0X:0:0:0:0:0:0:10B IETF-1-AUDIO [SC3]
+ FF0X:0:0:0:0:0:0:10C IETF-1-VIDEO [SC3]
+ FF0X:0:0:0:0:0:0:10D IETF-2-LOW-AUDIO [SC3]
+ FF0X:0:0:0:0:0:0:10E IETF-2-AUDIO [SC3]
+ FF0X:0:0:0:0:0:0:10F IETF-2-VIDEO [SC3]
+
+ FF0X:0:0:0:0:0:0:110 MUSIC-SERVICE [Guido van Rossum]
+ FF0X:0:0:0:0:0:0:111 SEANET-TELEMETRY [Andrew Maffei]
+ FF0X:0:0:0:0:0:0:112 SEANET-IMAGE [Andrew Maffei]
+ FF0X:0:0:0:0:0:0:113 MLOADD [Braden]
+ FF0X:0:0:0:0:0:0:114 any private experiment [JBP]
+ FF0X:0:0:0:0:0:0:115 DVMRP on MOSPF [Moy]
+ FF0X:0:0:0:0:0:0:116 SVRLOC [Veizades]
+ FF0X:0:0:0:0:0:0:117 XINGTV <hgxing@aol.com>
+ FF0X:0:0:0:0:0:0:118 microsoft-ds <arnoldm@microsoft.com>
+ FF0X:0:0:0:0:0:0:119 nbc-pro <bloomer@birch.crd.ge.com>
+ FF0X:0:0:0:0:0:0:11A nbc-pfn <bloomer@birch.crd.ge.com>
+ FF0X:0:0:0:0:0:0:11B lmsc-calren-1 [Uang]
+ FF0X:0:0:0:0:0:0:11C lmsc-calren-2 [Uang]
+ FF0X:0:0:0:0:0:0:11D lmsc-calren-3 [Uang]
+ FF0X:0:0:0:0:0:0:11E lmsc-calren-4 [Uang]
+ FF0X:0:0:0:0:0:0:11F ampr-info [Janssen]
+
+ FF0X:0:0:0:0:0:0:120 mtrace [Casner]
+ FF0X:0:0:0:0:0:0:121 RSVP-encap-1 [Braden]
+ FF0X:0:0:0:0:0:0:122 RSVP-encap-2 [Braden]
+ FF0X:0:0:0:0:0:0:123 SVRLOC-DA [Veizades]
+ FF0X:0:0:0:0:0:0:124 rln-server [Kean]
+ FF0X:0:0:0:0:0:0:125 proshare-mc [Lewis]
+ FF0X:0:0:0:0:0:0:126 dantz [Yackle]
+ FF0X:0:0:0:0:0:0:127 cisco-rp-announce [Farinacci]
+ FF0X:0:0:0:0:0:0:128 cisco-rp-discovery [Farinacci]
+ FF0X:0:0:0:0:0:0:129 gatekeeper [Toga]
+ FF0X:0:0:0:0:0:0:12A iberiagames [Marocho]
+
+
+
+
+Hinden & Deering Informational [Page 3]
+
+RFC 2375 IPv6 Multicast Address Assignments July 1998
+
+
+ FF0X:0:0:0:0:0:0:201 "rwho" Group (BSD) (unofficial) [JBP]
+ FF0X:0:0:0:0:0:0:202 SUN RPC PMAPPROC_CALLIT [BXE1]
+
+ FF0X:0:0:0:0:0:2:0000
+ -FF0X:0:0:0:0:0:2:7FFD Multimedia Conference Calls [SC3]
+ FF0X:0:0:0:0:0:2:7FFE SAPv1 Announcements [SC3]
+ FF0X:0:0:0:0:0:2:7FFF SAPv0 Announcements (deprecated) [SC3]
+ FF0X:0:0:0:0:0:2:8000
+ -FF0X:0:0:0:0:0:2:FFFF SAP Dynamic Assignments [SC3]
+
+5.0 References
+
+ [ADDARCH] Hinden, R., and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 2373, July 1998.
+
+ [AUTORFC] Thompson, S., and T. Narten, "IPv6 Stateless Address
+ Autoconfiguration", RFC 1971, August 1996.
+
+ [ETHER] Crawford, M., "Transmission of IPv6 Packets over Ethernet
+ Networks", Work in Progress.
+
+ [RFC1045] Cheriton, D., "VMTP: Versatile Message Transaction Protocol
+ Specification", RFC 1045, February 1988.
+
+ [RFC1075] Waitzman, D., Partridge, C., and S. Deering, "Distance
+ Vector Multicast Routing Protocol", RFC 1075, November
+ 1988.
+
+ [RFC1112] Deering, S., "Host Extensions for IP Multicasting", STD 5,
+ RFC 1112, Stanford University, August 1989.
+
+ [RFC1119] Mills, D., "Network Time Protocol (Version 1),
+ Specification and Implementation", STD 12, RFC 1119, July
+ 1988.
+
+ [RFC1190] Topolcic, C., Editor, "Experimental Internet Stream
+ Protocol, Version 2 (ST-II)", RFC 1190, October 1990.
+
+ [RFC2080] Malkin, G., and R. Minnear, "RIPng for IPv6", RFC 2080,
+ January 1997.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2165] Veizades, J., Guttman, E., Perkins, C., and S. Kaplan
+ "Service Location Protocol", RFC 2165 June 1997.
+
+ [RFC2328] Moy, J., "OSPF Version 2", STD 54, RFC 2328, April 1998.
+
+
+
+Hinden & Deering Informational [Page 4]
+
+RFC 2375 IPv6 Multicast Address Assignments July 1998
+
+
+6. People
+
+ <arnoldm@microsoft.com>
+
+ [AXC] Andrew Cherenson <arc@SGI.COM>
+
+ [Braden] Bob Braden, <braden@isi.edu>, April 1996.
+
+ [Bob Brenner]
+
+ [Bressler] David J. Bressler, <bressler@tss.com>, April 1996.
+
+ <bloomer@birch.crd.ge.com>
+
+ [Bound] Jim Bound <bound@zk3.dec.com>
+
+ [BXE1] Brendan Eic <brendan@illyria.wpd.sgi.com>
+
+ [BXF] Bruce Factor <ahi!bigapple!bruce@uunet.UU.NET>
+
+ [BXS2] Bill Schilit <schilit@parc.xerox.com>
+
+ [Casner] Steve Casner, <casner@isi.edu>, January 1995.
+
+ [CXM3] Chuck McManis <cmcmanis@sun.com>
+
+ [Tim Clark]
+
+ [DLM1] David Mills <Mills@HUEY.UDEL.EDU>
+
+ [DRC3] Dave Cheriton <cheriton@PESCADERO.STANFORD.EDU>
+
+ [DXS3] Daniel Steinber <Daniel.Steinberg@Eng.Sun.COM>
+
+ [Farinacci] Dino Farinacci, <dino@cisco.com>
+
+ [GSM11] Gary S. Malkin <GMALKIN@XYLOGICS.COM>
+
+ [Harrington] Dan Harrington, <dan@lucent.com>, July 1996.
+
+ <hgxing@aol.com>
+
+ [IANA] IANA <iana@iana.org>
+
+ [Janssen] Rob Janssen, <rob@pe1chl.ampr.org>, January 1995.
+
+ [JBP] Jon Postel <postel@isi.edu>
+
+
+
+
+Hinden & Deering Informational [Page 5]
+
+RFC 2375 IPv6 Multicast Address Assignments July 1998
+
+
+ [JXM1] Jim Miner <miner@star.com>
+
+ [Kean] Brian Kean, <bkean@dca.com>, August 1995.
+
+ [KS14] <mystery contact>
+
+ [Lee] Choon Lee, <cwl@nsd.3com.com>, April 1996.
+
+ [Lewis] Mark Lewis, <Mark_Lewis@ccm.jf.intel.com>, October 1995.
+
+ [Malamud] Carl Malamud, <carl@radio.com>, January 1996.
+
+ [Andrew Maffei]
+
+ [Marohco] Jose Luis Marocho, <73374.313@compuserve.com>, July 1996.
+
+ [Moy] John Moy <jmoy@casc.com>
+
+ [MXF2] Martin Forssen <maf@dtek.chalmers.se>
+
+ [Perkins] Charlie Perkins, <cperkins@corp.sun.com>
+
+ [Guido van Rossum]
+
+ [SC3] Steve Casner <casner@isi.edu>
+
+ [Simpson] Bill Simpson <bill.simpson@um.cc.umich.edu> November 1994.
+
+ [Joel Snyder]
+
+ [SXA] Susie Armstrong <Armstrong.wbst128@XEROX.COM>
+
+ [SXD] Steve Deering <deering@PARC.XEROX.COM>
+
+ [tynan] Dermot Tynan, <dtynan@claddagh.ie>, August 1995.
+
+ [Toga] Jim Toga, <jtoga@ibeam.jf.intel.com>, May 1996.
+
+ [Uang] Yea Uang <uang@force.decnet.lockheed.com> November 1994.
+
+ [Veizades] John Veizades, <veizades@tgv.com>, May 1995.
+
+ [Yackle] Dotty Yackle, <ditty_yackle@dantz.com>, February 1996.
+
+
+
+
+
+
+
+
+Hinden & Deering Informational [Page 6]
+
+RFC 2375 IPv6 Multicast Address Assignments July 1998
+
+
+7.0 Security Considerations
+
+ This document defines the initial assignment of IPv6 multicast
+ addresses. As such it does not directly impact the security of the
+ Internet infrastructure or its applications.
+
+8.0 Authors' Addresses
+
+ Robert M. Hinden
+ Ipsilon Networks, Inc.
+ 232 Java Drive
+ Sunnyvale, CA 94089
+ USA
+
+ Phone: +1 415 990 2004
+ EMail: hinden@ipsilon.com
+
+
+ Stephen E. Deering
+ Cisco Systems, Inc.
+ 170 West Tasman Drive
+ San Jose, CA 95134-1706
+ USA
+
+ Phone: +1 408 527-8213
+ EMail: deering@cisco.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Informational [Page 7]
+
+RFC 2375 IPv6 Multicast Address Assignments July 1998
+
+
+9.0 Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Informational [Page 8]
+
diff --git a/doc/rfc/rfc2418.txt b/doc/rfc/rfc2418.txt
new file mode 100644
index 0000000..9bdb2c5
--- /dev/null
+++ b/doc/rfc/rfc2418.txt
@@ -0,0 +1,1459 @@
+
+
+
+
+
+
+Network Working Group S. Bradner
+Request for Comments: 2418 Editor
+Obsoletes: 1603 Harvard University
+BCP: 25 September 1998
+Category: Best Current Practice
+
+
+ IETF Working Group
+ Guidelines and Procedures
+
+Status of this Memo
+
+ This document specifies an Internet Best Current Practices for the
+ Internet Community, and requests discussion and suggestions for
+ improvements. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+Abstract
+
+ The Internet Engineering Task Force (IETF) has responsibility for
+ developing and reviewing specifications intended as Internet
+ Standards. IETF activities are organized into working groups (WGs).
+ This document describes the guidelines and procedures for formation
+ and operation of IETF working groups. It also describes the formal
+ relationship between IETF participants WG and the Internet
+ Engineering Steering Group (IESG) and the basic duties of IETF
+ participants, including WG Chairs, WG participants, and IETF Area
+ Directors.
+
+Table of Contents
+
+ Abstract ......................................................... 1
+ 1. Introduction .................................................. 2
+ 1.1. IETF approach to standardization .......................... 4
+ 1.2. Roles within a Working Group .............................. 4
+ 2. Working group formation ....................................... 4
+ 2.1. Criteria for formation .................................... 4
+ 2.2. Charter ................................................... 6
+ 2.3. Charter review & approval ................................. 8
+ 2.4. Birds of a feather (BOF) .................................. 9
+ 3. Working Group Operation ....................................... 10
+ 3.1. Session planning .......................................... 11
+ 3.2. Session venue ............................................. 11
+ 3.3. Session management ........................................ 13
+ 3.4. Contention and appeals .................................... 15
+
+
+
+Bradner Best Current Practice [Page 1]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ 4. Working Group Termination ..................................... 15
+ 5. Rechartering a Working Group .................................. 15
+ 6. Staff Roles ................................................... 16
+ 6.1. WG Chair .................................................. 16
+ 6.2. WG Secretary .............................................. 18
+ 6.3. Document Editor ........................................... 18
+ 6.4. WG Facilitator ............................................ 18
+ 6.5. Design teams .............................................. 19
+ 6.6. Working Group Consultant .................................. 19
+ 6.7. Area Director ............................................. 19
+ 7. Working Group Documents ....................................... 19
+ 7.1. Session documents ......................................... 19
+ 7.2. Internet-Drafts (I-D) ..................................... 19
+ 7.3. Request For Comments (RFC) ................................ 20
+ 7.4. Working Group Last-Call ................................... 20
+ 7.5. Submission of documents ................................... 21
+ 8. Review of documents ........................................... 21
+ 9. Security Considerations ....................................... 22
+ 10. Acknowledgments .............................................. 23
+ 11. References ................................................... 23
+ 12. Editor's Address ............................................. 23
+ Appendix: Sample Working Group Charter .......................... 24
+ Full Copyright Statement ......................................... 26
+
+1. Introduction
+
+ The Internet, a loosely-organized international collaboration of
+ autonomous, interconnected networks, supports host-to-host
+ communication through voluntary adherence to open protocols and
+ procedures defined by Internet Standards. There are also many
+ isolated interconnected networks, which are not connected to the
+ global Internet but use the Internet Standards. Internet Standards
+ are developed in the Internet Engineering Task Force (IETF). This
+ document defines guidelines and procedures for IETF working groups.
+ The Internet Standards Process of the IETF is defined in [1]. The
+ organizations involved in the IETF Standards Process are described in
+ [2] as are the roles of specific individuals.
+
+ The IETF is a large, open community of network designers, operators,
+ vendors, users, and researchers concerned with the Internet and the
+ technology used on it. The primary activities of the IETF are
+ performed by committees known as working groups. There are currently
+ more than 100 working groups. (See the IETF web page for an up-to-
+ date list of IETF Working Groups - http://www.ietf.org.) Working
+ groups tend to have a narrow focus and a lifetime bounded by the
+ completion of a specific set of tasks, although there are exceptions.
+
+
+
+
+
+Bradner Best Current Practice [Page 2]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ For management purposes, the IETF working groups are collected
+ together into areas, with each area having a separate focus. For
+ example, the security area deals with the development of security-
+ related technology. Each IETF area is managed by one or two Area
+ Directors (ADs). There are currently 8 areas in the IETF but the
+ number changes from time to time. (See the IETF web page for a list
+ of the current areas, the Area Directors for each area, and a list of
+ which working groups are assigned to each area.)
+
+ In many areas, the Area Directors have formed an advisory group or
+ directorate. These comprise experienced members of the IETF and the
+ technical community represented by the area. The specific name and
+ the details of the role for each group differ from area to area, but
+ the primary intent is that these groups assist the Area Director(s),
+ e.g., with the review of specifications produced in the area.
+
+ The IETF area directors are selected by a nominating committee, which
+ also selects an overall chair for the IETF. The nominations process
+ is described in [3].
+
+ The area directors sitting as a body, along with the IETF Chair,
+ comprise the Internet Engineering Steering Group (IESG). The IETF
+ Executive Director is an ex-officio participant of the IESG, as are
+ the IAB Chair and a designated Internet Architecture Board (IAB)
+ liaison. The IESG approves IETF Standards and approves the
+ publication of other IETF documents. (See [1].)
+
+ A small IETF Secretariat provides staff and administrative support
+ for the operation of the IETF.
+
+ There is no formal membership in the IETF. Participation is open to
+ all. This participation may be by on-line contribution, attendance
+ at face-to-face sessions, or both. Anyone from the Internet
+ community who has the time and interest is urged to participate in
+ IETF meetings and any of its on-line working group discussions.
+ Participation is by individual technical contributors, rather than by
+ formal representatives of organizations.
+
+ This document defines procedures and guidelines for the formation and
+ operation of working groups in the IETF. It defines the relations of
+ working groups to other bodies within the IETF. The duties of working
+ group Chairs and Area Directors with respect to the operation of the
+ working group are also defined. When used in this document the key
+ words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
+ "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" are to be
+ interpreted as described in RFC 2119 [6]. RFC 2119 defines the use
+ of these key words to help make the intent of standards track
+ documents as clear as possible. The same key words are used in this
+
+
+
+Bradner Best Current Practice [Page 3]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ document to help smooth WG operation and reduce the chance for
+ confusion about the processes.
+
+1.1. IETF approach to standardization
+
+ Familiarity with The Internet Standards Process [1] is essential for
+ a complete understanding of the philosophy, procedures and guidelines
+ described in this document.
+
+1.2. Roles within a Working Group
+
+ The document, "Organizations Involved in the IETF Standards Process"
+ [2] describes the roles of a number of individuals within a working
+ group, including the working group chair and the document editor.
+ These descriptions are expanded later in this document.
+
+2. Working group formation
+
+ IETF working groups (WGs) are the primary mechanism for development
+ of IETF specifications and guidelines, many of which are intended to
+ be standards or recommendations. A working group may be established
+ at the initiative of an Area Director or it may be initiated by an
+ individual or group of individuals. Anyone interested in creating an
+ IETF working group MUST obtain the advice and consent of the IETF
+ Area Director(s) in whose area the working group would fall and MUST
+ proceed through the formal steps detailed in this section.
+
+ Working groups are typically created to address a specific problem or
+ to produce one or more specific deliverables (a guideline, standards
+ specification, etc.). Working groups are generally expected to be
+ short-lived in nature. Upon completion of its goals and achievement
+ of its objectives, the working group is terminated. A working group
+ may also be terminated for other reasons (see section 4).
+ Alternatively, with the concurrence of the IESG, Area Director, the
+ WG Chair, and the WG participants, the objectives or assignment of
+ the working group may be extended by modifying the working group's
+ charter through a rechartering process (see section 5).
+
+2.1. Criteria for formation
+
+ When determining whether it is appropriate to create a working group,
+ the Area Director(s) and the IESG will consider several issues:
+
+ - Are the issues that the working group plans to address clear and
+ relevant to the Internet community?
+
+ - Are the goals specific and reasonably achievable, and achievable
+ within a reasonable time frame?
+
+
+
+Bradner Best Current Practice [Page 4]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ - What are the risks and urgency of the work, to determine the level
+ of effort required?
+
+ - Do the working group's activities overlap with those of another
+ working group? If so, it may still be appropriate to create the
+ working group, but this question must be considered carefully by
+ the Area Directors as subdividing efforts often dilutes the
+ available technical expertise.
+
+ - Is there sufficient interest within the IETF in the working
+ group's topic with enough people willing to expend the effort to
+ produce the desired result (e.g., a protocol specification)?
+ Working groups require considerable effort, including management
+ of the working group process, editing of working group documents,
+ and contributing to the document text. IETF experience suggests
+ that these roles typically cannot all be handled by one person; a
+ minimum of four or five active participants in the management
+ positions are typically required in addition to a minimum of one
+ or two dozen people that will attend the working group meetings
+ and contribute on the mailing list. NOTE: The interest must be
+ broad enough that a working group would not be seen as merely the
+ activity of a single vendor.
+
+ - Is there enough expertise within the IETF in the working group's
+ topic, and are those people interested in contributing in the
+ working group?
+
+ - Does a base of interested consumers (end-users) appear to exist
+ for the planned work? Consumer interest can be measured by
+ participation of end-users within the IETF process, as well as by
+ less direct means.
+
+ - Does the IETF have a reasonable role to play in the determination
+ of the technology? There are many Internet-related technologies
+ that may be interesting to IETF members but in some cases the IETF
+ may not be in a position to effect the course of the technology in
+ the "real world". This can happen, for example, if the technology
+ is being developed by another standards body or an industry
+ consortium.
+
+ - Are all known intellectual property rights relevant to the
+ proposed working group's efforts issues understood?
+
+ - Is the proposed work plan an open IETF effort or is it an attempt
+ to "bless" non-IETF technology where the effect of input from IETF
+ participants may be limited?
+
+
+
+
+
+Bradner Best Current Practice [Page 5]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ - Is there a good understanding of any existing work that is
+ relevant to the topics that the proposed working group is to
+ pursue? This includes work within the IETF and elsewhere.
+
+ - Do the working group's goals overlap with known work in another
+ standards body, and if so is adequate liaison in place?
+
+ Considering the above criteria, the Area Director(s), using his or
+ her best judgement, will decide whether to pursue the formation of
+ the group through the chartering process.
+
+2.2. Charter
+
+ The formation of a working group requires a charter which is
+ primarily negotiated between a prospective working group Chair and
+ the relevant Area Director(s), although final approval is made by the
+ IESG with advice from the Internet Architecture Board (IAB). A
+ charter is a contract between a working group and the IETF to perform
+ a set of tasks. A charter:
+
+ 1. Lists relevant administrative information for the working group;
+ 2. Specifies the direction or objectives of the working group and
+ describes the approach that will be taken to achieve the goals;
+ and
+ 3. Enumerates a set of milestones together with time frames for their
+ completion.
+
+ When the prospective Chair(s), the Area Director and the IETF
+ Secretariat are satisfied with the charter form and content, it
+ becomes the basis for forming a working group. Note that an Area
+ Director MAY require holding an exploratory Birds of a Feather (BOF)
+ meeting, as described below, to gage the level of support for a
+ working group before submitting the charter to the IESG and IAB for
+ approval.
+
+ Charters may be renegotiated periodically to reflect the current
+ status, organization or goals of the working group (see section 5).
+ Hence, a charter is a contract between the IETF and the working group
+ which is committing to meet explicit milestones and delivering
+ specific "products".
+
+ Specifically, each charter consists of the following sections:
+
+ Working group name
+ A working group name should be reasonably descriptive or
+ identifiable. Additionally, the group shall define an acronym
+ (maximum 8 printable ASCII characters) to reference the group in
+ the IETF directories, mailing lists, and general documents.
+
+
+
+Bradner Best Current Practice [Page 6]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ Chair(s)
+ The working group may have one or more Chairs to perform the
+ administrative functions of the group. The email address(es) of
+ the Chair(s) shall be included. Generally, a working group is
+ limited to two chairs.
+
+ Area and Area Director(s)
+ The name of the IETF area with which the working group is
+ affiliated and the name and electronic mail address of the
+ associated Area Director(s).
+
+ Responsible Area Director
+ The Area Director who acts as the primary IESG contact for the
+ working group.
+
+ Mailing list
+ An IETF working group MUST have a general Internet mailing list.
+ Most of the work of an IETF working group will be conducted on the
+ mailing list. The working group charter MUST include:
+
+ 1. The address to which a participant sends a subscription request
+ and the procedures to follow when subscribing,
+
+ 2. The address to which a participant sends submissions and
+ special procedures, if any, and
+
+ 3. The location of the mailing list archive. A message archive
+ MUST be maintained in a public place which can be accessed via
+ FTP or via the web.
+
+ As a service to the community, the IETF Secretariat operates a
+ mailing list archive for working group mailing lists. In order
+ to take advantage of this service, working group mailing lists
+ MUST include the address "wg_acronym-archive@lists.ietf.org"
+ (where "wg_acronym" is the working group acronym) in the
+ mailing list in order that a copy of all mailing list messages
+ be recorded in the Secretariat's archive. Those archives are
+ located at ftp://ftp.ietf.org/ietf-mail-archive. For
+ robustness, WGs SHOULD maintain an additional archive separate
+ from that maintained by the Secretariat.
+
+ Description of working group
+ The focus and intent of the group shall be set forth briefly. By
+ reading this section alone, an individual should be able to decide
+ whether this group is relevant to their own work. The first
+ paragraph must give a brief summary of the problem area, basis,
+ goal(s) and approach(es) planned for the working group. This
+ paragraph can be used as an overview of the working group's
+
+
+
+Bradner Best Current Practice [Page 7]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ effort.
+
+ To facilitate evaluation of the intended work and to provide on-
+ going guidance to the working group, the charter must describe the
+ problem being solved and should discuss objectives and expected
+ impact with respect to:
+
+ - Architecture
+ - Operations
+ - Security
+ - Network management
+ - Scaling
+ - Transition (where applicable)
+
+ Goals and milestones
+ The working group charter MUST establish a timetable for specific
+ work items. While this may be renegotiated over time, the list of
+ milestones and dates facilitates the Area Director's tracking of
+ working group progress and status, and it is indispensable to
+ potential participants identifying the critical moments for input.
+ Milestones shall consist of deliverables that can be qualified as
+ showing specific achievement; e.g., "Internet-Draft finished" is
+ fine, but "discuss via email" is not. It is helpful to specify
+ milestones for every 3-6 months, so that progress can be gauged
+ easily. This milestone list is expected to be updated
+ periodically (see section 5).
+
+ An example of a WG charter is included as Appendix A.
+
+2.3. Charter review & approval
+
+ Proposed working groups often comprise technically competent
+ participants who are not familiar with the history of Internet
+ architecture or IETF processes. This can, unfortunately, lead to
+ good working group consensus about a bad design. To facilitate
+ working group efforts, an Area Director may assign a Consultant from
+ among the ranks of senior IETF participants. (Consultants are
+ described in section 6.) At the discretion of the Area Director,
+ approval of a new WG may be withheld in the absence of sufficient
+ consultant resources.
+
+ Once the Area Director (and the Area Directorate, as the Area
+ Director deems appropriate) has approved the working group charter,
+ the charter is submitted for review by the IAB and approval by the
+ IESG. After a review period of at least a week the proposed charter
+ is posted to the IETF-announce mailing list as a public notice that
+ the formation of the working group is being considered. At the same
+ time the proposed charter is also posted to the "new-work" mailing
+
+
+
+Bradner Best Current Practice [Page 8]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ list. This mailing list has been created to let qualified
+ representatives from other standards organizations know about pending
+ IETF working groups. After another review period lasting at least a
+ week the IESG MAY approve the charter as-is, it MAY request that
+ changes be made in the charter, or MAY decline to approve chartering
+ of the working group
+
+ If the IESG approves the formation of the working group it remands
+ the approved charter to the IETF Secretariat who records and enters
+ the information into the IETF tracking database. The working group
+ is announced to the IETF-announce a by the IETF Secretariat.
+
+2.4. Birds of a Feather (BOF)
+
+ Often it is not clear whether an issue merits the formation of a
+ working group. To facilitate exploration of the issues the IETF
+ offers the possibility of a Birds of a Feather (BOF) session, as well
+ as the early formation of an email list for preliminary discussion.
+ In addition, a BOF may serve as a forum for a single presentation or
+ discussion, without any intent to form a working group.
+
+ A BOF is a session at an IETF meeting which permits "market research"
+ and technical "brainstorming". Any individual may request permission
+ to hold a BOF on a subject. The request MUST be filed with a relevant
+ Area Director who must approve a BOF before it can be scheduled. The
+ person who requests the BOF may be asked to serve as Chair of the
+ BOF.
+
+ The Chair of the BOF is also responsible for providing a report on
+ the outcome of the BOF. If the Area Director approves, the BOF is
+ then scheduled by submitting a request to agenda@ietf.org with copies
+ to the Area Director(s). A BOF description and agenda are required
+ before a BOF can be scheduled.
+
+ Available time for BOFs is limited, and BOFs are held at the
+ discretion of the ADs for an area. The AD(s) may require additional
+ assurances before authorizing a BOF. For example,
+
+ - The Area Director MAY require the establishment of an open email
+ list prior to authorizing a BOF. This permits initial exchanges
+ and sharing of framework, vocabulary and approaches, in order to
+ make the time spent in the BOF more productive.
+
+ - The Area Director MAY require that a BOF be held, prior to
+ establishing a working group (see section 2.2).
+
+ - The Area Director MAY require that there be a draft of the WG
+ charter prior to holding a BOF.
+
+
+
+Bradner Best Current Practice [Page 9]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ - The Area Director MAY require that a BOF not be held until an
+ Internet-Draft describing the proposed technology has been
+ published so it can be used as a basis for discussion in the BOF.
+
+ In general, a BOF on a particular topic is held only once (ONE slot
+ at one IETF Plenary meeting). Under unusual circumstances Area
+ Directors may, at their discretion, allow a BOF to meet for a second
+ time. BOFs are not permitted to meet three times. Note that all
+ other things being equal, WGs will be given priority for meeting
+ space over BOFs. Also, occasionally BOFs may be held for other
+ purposes than to discuss formation of a working group.
+
+ Usually the outcome of a BOF will be one of the following:
+
+ - There was enough interest and focus in the subject to warrant the
+ formation of a WG;
+
+ - While there was a reasonable level of interest expressed in the
+ BOF some other criteria for working group formation was not met
+ (see section 2.1).
+
+ - The discussion came to a fruitful conclusion, with results to be
+ written down and published, however there is no need to establish
+ a WG; or
+
+ - There was not enough interest in the subject to warrant the
+ formation of a WG.
+
+3. Working Group Operation
+
+ The IETF has basic requirements for open and fair participation and
+ for thorough consideration of technical alternatives. Within those
+ constraints, working groups are autonomous and each determines most
+ of the details of its own operation with respect to session
+ participation, reaching closure, etc. The core rule for operation is
+ that acceptance or agreement is achieved via working group "rough
+ consensus". WG participants should specifically note the
+ requirements for disclosure of conflicts of interest in [2].
+
+ A number of procedural questions and issues will arise over time, and
+ it is the function of the Working Group Chair(s) to manage the group
+ process, keeping in mind that the overall purpose of the group is to
+ make progress towards reaching rough consensus in realizing the
+ working group's goals and objectives.
+
+ There are few hard and fast rules on organizing or conducting working
+ group activities, but a set of guidelines and practices has evolved
+ over time that have proven successful. These are listed here, with
+
+
+
+Bradner Best Current Practice [Page 10]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ actual choices typically determined by the working group participants
+ and the Chair(s).
+
+3.1. Session planning
+
+ For coordinated, structured WG interactions, the Chair(s) MUST
+ publish a draft agenda well in advance of the actual session. The
+ agenda should contain at least:
+
+ - The items for discussion;
+ - The estimated time necessary per item; and
+ - A clear indication of what documents the participants will need to
+ read before the session in order to be well prepared.
+
+ Publication of the working group agenda shall include sending a copy
+ of the agenda to the working group mailing list and to
+ agenda@ietf.org.
+
+ All working group actions shall be taken in a public forum, and wide
+ participation is encouraged. A working group will conduct much of its
+ business via electronic mail distribution lists but may meet
+ periodically to discuss and review task status and progress, to
+ resolve specific issues and to direct future activities. IETF
+ Plenary meetings are the primary venue for these face-to-face working
+ group sessions, and it is common (though not required) that active
+ "interim" face-to-face meetings, telephone conferences, or video
+ conferences may also be held. Interim meetings are subject to the
+ same rules for advance notification, reporting, open participation,
+ and process, which apply to other working group meetings.
+
+ All working group sessions (including those held outside of the IETF
+ meetings) shall be reported by making minutes available. These
+ minutes should include the agenda for the session, an account of the
+ discussion including any decisions made, and a list of attendees. The
+ Working Group Chair is responsible for insuring that session minutes
+ are written and distributed, though the actual task may be performed
+ by someone designated by the Working Group Chair. The minutes shall
+ be submitted in printable ASCII text for publication in the IETF
+ Proceedings, and for posting in the IETF Directories and are to be
+ sent to: minutes@ietf.org
+
+3.2. Session venue
+
+ Each working group will determine the balance of email and face-to-
+ face sessions that is appropriate for achieving its milestones.
+ Electronic mail permits the widest participation; face-to-face
+ meetings often permit better focus and therefore can be more
+ efficient for reaching a consensus among a core of the working group
+
+
+
+Bradner Best Current Practice [Page 11]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ participants. In determining the balance, the WG must ensure that
+ its process does not serve to exclude contribution by email-only
+ participants. Decisions reached during a face-to-face meeting about
+ topics or issues which have not been discussed on the mailing list,
+ or are significantly different from previously arrived mailing list
+ consensus MUST be reviewed on the mailing list.
+
+ IETF Meetings
+ If a WG needs a session at an IETF meeting, the Chair must apply for
+ time-slots as soon as the first announcement of that IETF meeting is
+ made by the IETF Secretariat to the WG-chairs list. Session time is
+ a scarce resource at IETF meetings, so placing requests early will
+ facilitate schedule coordination for WGs requiring the same set of
+ experts.
+
+ The application for a WG session at an IETF meeting MUST be made to
+ the IETF Secretariat at the address agenda@ietf.org. Some Area
+ Directors may want to coordinate WG sessions in their area and
+ request that time slots be coordinated through them. If this is the
+ case it will be noted in the IETF meeting announcement. A WG
+ scheduling request MUST contain:
+
+ - The working group name and full title;
+ - The amount of time requested;
+ - The rough outline of the WG agenda that is expected to be covered;
+ - The estimated number of people that will attend the WG session;
+ - Related WGs that should not be scheduled for the same time slot(s);
+ and
+ - Optionally a request can be added for the WG session to be
+ transmitted over the Internet in audio and video.
+
+ NOTE: While open discussion and contribution is essential to working
+ group success, the Chair is responsible for ensuring forward
+ progress. When acceptable to the WG, the Chair may call for
+ restricted participation (but not restricted attendance!) at IETF
+ working group sessions for the purpose of achieving progress. The
+ Working Group Chair then has the authority to refuse to grant the
+ floor to any individual who is unprepared or otherwise covering
+ inappropriate material, or who, in the opinion of the Chair is
+ disrupting the WG process. The Chair should consult with the Area
+ Director(s) if the individual persists in disruptive behavior.
+
+ On-line
+ It can be quite useful to conduct email exchanges in the same manner
+ as a face-to-face session, with published schedule and agenda, as
+ well as on-going summarization and consensus polling.
+
+
+
+
+
+Bradner Best Current Practice [Page 12]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ Many working group participants hold that mailing list discussion is
+ the best place to consider and resolve issues and make decisions. The
+ choice of operational style is made by the working group itself. It
+ is important to note, however, that Internet email discussion is
+ possible for a much wider base of interested persons than is
+ attendance at IETF meetings, due to the time and expense required to
+ attend.
+
+ As with face-to-face sessions occasionally one or more individuals
+ may engage in behavior on a mailing list which disrupts the WG's
+ progress. In these cases the Chair should attempt to discourage the
+ behavior by communication directly with the offending individual
+ rather than on the open mailing list. If the behavior persists then
+ the Chair must involve the Area Director in the issue. As a last
+ resort and after explicit warnings, the Area Director, with the
+ approval of the IESG, may request that the mailing list maintainer
+ block the ability of the offending individual to post to the mailing
+ list. (If the mailing list software permits this type of operation.)
+ Even if this is done, the individual must not be prevented from
+ receiving messages posted to the list. Other methods of mailing list
+ control may be considered but must be approved by the AD(s) and the
+ IESG.
+
+3.3. Session management
+
+ Working groups make decisions through a "rough consensus" process.
+ IETF consensus does not require that all participants agree although
+ this is, of course, preferred. In general, the dominant view of the
+ working group shall prevail. (However, it must be noted that
+ "dominance" is not to be determined on the basis of volume or
+ persistence, but rather a more general sense of agreement.) Consensus
+ can be determined by a show of hands, humming, or any other means on
+ which the WG agrees (by rough consensus, of course). Note that 51%
+ of the working group does not qualify as "rough consensus" and 99% is
+ better than rough. It is up to the Chair to determine if rough
+ consensus has been reached.
+
+ It can be particularly challenging to gauge the level of consensus on
+ a mailing list. There are two different cases where a working group
+ may be trying to understand the level of consensus via a mailing list
+ discussion. But in both cases the volume of messages on a topic is
+ not, by itself, a good indicator of consensus since one or two
+ individuals may be generating much of the traffic.
+
+ In the case where a consensus which has been reached during a face-
+ to-face meeting is being verified on a mailing list the people who
+ were in the meeting and expressed agreement must be taken into
+ account. If there were 100 people in a meeting and only a few people
+
+
+
+Bradner Best Current Practice [Page 13]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ on the mailing list disagree with the consensus of the meeting then
+ the consensus should be seen as being verified. Note that enough
+ time should be given to the verification process for the mailing list
+ readers to understand and consider any objections that may be raised
+ on the list. The normal two week last-call period should be
+ sufficient for this.
+
+ The other case is where the discussion has been held entirely over
+ the mailing list. The determination of the level of consensus may be
+ harder to do in this case since most people subscribed to mailing
+ lists do not actively participate in discussions on the list. It is
+ left to the discretion of the working group chair how to evaluate the
+ level of consensus. The most common method used is for the working
+ group chair to state what he or she believes to be the consensus view
+ and. at the same time, requests comments from the list about the
+ stated conclusion.
+
+ The challenge to managing working group sessions is to balance the
+ need for open and fair consideration of the issues against the need
+ to make forward progress. The working group, as a whole, has the
+ final responsibility for striking this balance. The Chair has the
+ responsibility for overseeing the process but may delegate direct
+ process management to a formally-designated Facilitator.
+
+ It is occasionally appropriate to revisit a topic, to re-evaluate
+ alternatives or to improve the group's understanding of a relevant
+ decision. However, unnecessary repeated discussions on issues can be
+ avoided if the Chair makes sure that the main arguments in the
+ discussion (and the outcome) are summarized and archived after a
+ discussion has come to conclusion. It is also good practice to note
+ important decisions/consensus reached by email in the minutes of the
+ next 'live' session, and to summarize briefly the decision-making
+ history in the final documents the WG produces.
+
+ To facilitate making forward progress, a Working Group Chair may wish
+ to decide to reject or defer the input from a member, based upon the
+ following criteria:
+
+ Old
+ The input pertains to a topic that already has been resolved and is
+ redundant with information previously available;
+
+ Minor
+ The input is new and pertains to a topic that has already been
+ resolved, but it is felt to be of minor import to the existing
+ decision;
+
+
+
+
+
+Bradner Best Current Practice [Page 14]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ Timing
+ The input pertains to a topic that the working group has not yet
+ opened for discussion; or
+
+ Scope
+ The input is outside of the scope of the working group charter.
+
+3.4. Contention and appeals
+
+ Disputes are possible at various stages during the IETF process. As
+ much as possible the process is designed so that compromises can be
+ made, and genuine consensus achieved; however, there are times when
+ even the most reasonable and knowledgeable people are unable to
+ agree. To achieve the goals of openness and fairness, such conflicts
+ must be resolved by a process of open review and discussion.
+
+ Formal procedures for requesting a review of WG, Chair, Area Director
+ or IESG actions and conducting appeals are documented in The Internet
+ Standards Process [1].
+
+4. Working Group Termination
+
+ Working groups are typically chartered to accomplish a specific task
+ or tasks. After the tasks are complete, the group will be disbanded.
+ However, if a WG produces a Proposed or Draft Standard, the WG will
+ frequently become dormant rather than disband (i.e., the WG will no
+ longer conduct formal activities, but the mailing list will remain
+ available to review the work as it moves to Draft Standard and
+ Standard status.)
+
+ If, at some point, it becomes evident that a working group is unable
+ to complete the work outlined in the charter, or if the assumptions
+ which that work was based have been modified in discussion or by
+ experience, the Area Director, in consultation with the working group
+ can either:
+
+ 1. Recharter to refocus its tasks,
+ 2. Choose new Chair(s), or
+ 3. Disband.
+
+ If the working group disagrees with the Area Director's choice, it
+ may appeal to the IESG (see section 3.4).
+
+5. Rechartering a Working Group
+
+ Updated milestones are renegotiated with the Area Director and the
+ IESG, as needed, and then are submitted to the IESG Secretariat:
+ iesg-secretary@ietf.org.
+
+
+
+Bradner Best Current Practice [Page 15]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ Rechartering (other than revising milestones) a working group follows
+ the same procedures that the initial chartering does (see section 2).
+ The revised charter must be submitted to the IESG and IAB for
+ approval. As with the initial chartering, the IESG may approve new
+ charter as-is, it may request that changes be made in the new charter
+ (including having the Working Group continue to use the old charter),
+ or it may decline to approve the rechartered working group. In the
+ latter case, the working group is disbanded.
+
+6. Staff Roles
+
+ Working groups require considerable care and feeding. In addition to
+ general participation, successful working groups benefit from the
+ efforts of participants filling specific functional roles. The Area
+ Director must agree to the specific people performing the WG Chair,
+ and Working Group Consultant roles, and they serve at the discretion
+ of the Area Director.
+
+6.1. WG Chair
+
+ The Working Group Chair is concerned with making forward progress
+ through a fair and open process, and has wide discretion in the
+ conduct of WG business. The Chair must ensure that a number of tasks
+ are performed, either directly or by others assigned to the tasks.
+
+ The Chair has the responsibility and the authority to make decisions,
+ on behalf of the working group, regarding all matters of working
+ group process and staffing, in conformance with the rules of the
+ IETF. The AD has the authority and the responsibility to assist in
+ making those decisions at the request of the Chair or when
+ circumstances warrant such an intervention.
+
+ The Chair's responsibility encompasses at least the following:
+
+ Ensure WG process and content management
+
+ The Chair has ultimate responsibility for ensuring that a working
+ group achieves forward progress and meets its milestones. The
+ Chair is also responsible to ensure that the working group
+ operates in an open and fair manner. For some working groups,
+ this can be accomplished by having the Chair perform all
+ management-related activities. In other working groups --
+ particularly those with large or divisive participation -- it is
+ helpful to allocate process and/or secretarial functions to other
+ participants. Process management pertains strictly to the style
+ of working group interaction and not to its content. It ensures
+ fairness and detects redundancy. The secretarial function
+ encompasses document editing. It is quite common for a working
+
+
+
+Bradner Best Current Practice [Page 16]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ group to assign the task of specification Editor to one or two
+ participants. Sometimes, they also are part of the design team,
+ described below.
+
+ Moderate the WG email list
+
+ The Chair should attempt to ensure that the discussions on this
+ list are relevant and that they converge to consensus agreements.
+ The Chair should make sure that discussions on the list are
+ summarized and that the outcome is well documented (to avoid
+ repetition). The Chair also may choose to schedule organized on-
+ line "sessions" with agenda and deliverables. These can be
+ structured as true meetings, conducted over the course of several
+ days (to allow participation across the Internet).
+
+ Organize, prepare and chair face-to-face and on-line formal
+ sessions.
+
+ Plan WG Sessions
+
+ The Chair must plan and announce all WG sessions well in advance
+ (see section 3.1).
+
+ Communicate results of sessions
+
+ The Chair and/or Secretary must ensure that minutes of a session
+ are taken and that an attendance list is circulated (see section
+ 3.1).
+
+ Immediately after a session, the WG Chair MUST provide the Area
+ Director with a very short report (approximately one paragraph,
+ via email) on the session.
+
+ Distribute the workload
+
+ Of course, each WG will have participants who may not be able (or
+ want) to do any work at all. Most of the time the bulk of the work
+ is done by a few dedicated participants. It is the task of the
+ Chair to motivate enough experts to allow for a fair distribution
+ of the workload.
+
+ Document development
+
+ Working groups produce documents and documents need authors. The
+ Chair must make sure that authors of WG documents incorporate
+ changes as agreed to by the WG (see section 6.3).
+
+
+
+
+
+Bradner Best Current Practice [Page 17]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ Document publication
+
+ The Chair and/or Document Editor will work with the RFC Editor to
+ ensure document conformance with RFC publication requirements [5]
+ and to coordinate any editorial changes suggested by the RFC
+ Editor. A particular concern is that all participants are working
+ from the same version of a document at the same time.
+
+ Document implementations
+
+ Under the procedures described in [1], the Chair is responsible
+ for documenting the specific implementations which qualify the
+ specification for Draft or Internet Standard status along with
+ documentation about testing of the interoperation of these
+ implementations.
+
+6.2. WG Secretary
+
+ Taking minutes and editing working group documents often is performed
+ by a specifically-designated participant or set of participants. In
+ this role, the Secretary's job is to record WG decisions, rather than
+ to perform basic specification.
+
+6.3. Document Editor
+
+ Most IETF working groups focus their efforts on a document, or set of
+ documents, that capture the results of the group's work. A working
+ group generally designates a person or persons to serve as the Editor
+ for a particular document. The Document Editor is responsible for
+ ensuring that the contents of the document accurately reflect the
+ decisions that have been made by the working group.
+
+ As a general practice, the Working Group Chair and Document Editor
+ positions are filled by different individuals to help ensure that the
+ resulting documents accurately reflect the consensus of the working
+ group and that all processes are followed.
+
+6.4. WG Facilitator
+
+ When meetings tend to become distracted or divisive, it often is
+ helpful to assign the task of "process management" to one
+ participant. Their job is to oversee the nature, rather than the
+ content, of participant interactions. That is, they attend to the
+ style of the discussion and to the schedule of the agenda, rather
+ than making direct technical contributions themselves.
+
+
+
+
+
+
+Bradner Best Current Practice [Page 18]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+6.5. Design teams
+
+ It is often useful, and perhaps inevitable, for a sub-group of a
+ working group to develop a proposal to solve a particular problem.
+ Such a sub-group is called a design team. In order for a design team
+ to remain small and agile, it is acceptable to have closed membership
+ and private meetings. Design teams may range from an informal chat
+ between people in a hallway to a formal set of expert volunteers that
+ the WG chair or AD appoints to attack a controversial problem. The
+ output of a design team is always subject to approval, rejection or
+ modification by the WG as a whole.
+
+6.6. Working Group Consultant
+
+ At the discretion of the Area Director, a Consultant may be assigned
+ to a working group. Consultants have specific technical background
+ appropriate to the WG and experience in Internet architecture and
+ IETF process.
+
+6.7. Area Director
+
+ Area Directors are responsible for ensuring that working groups in
+ their area produce coherent, coordinated, architecturally consistent
+ and timely output as a contribution to the overall results of the
+ IETF.
+
+7. Working Group Documents
+
+7.1. Session documents
+
+ All relevant documents to be discussed at a session should be
+ published and available as Internet-Drafts at least two weeks before
+ a session starts. Any document which does not meet this publication
+ deadline can only be discussed in a working group session with the
+ specific approval of the working group chair(s). Since it is
+ important that working group members have adequate time to review all
+ documents, granting such an exception should only be done under
+ unusual conditions. The final session agenda should be posted to the
+ working group mailing list at least two weeks before the session and
+ sent at that time to agenda@ietf.org for publication on the IETF web
+ site.
+
+7.2. Internet-Drafts (I-D)
+
+ The Internet-Drafts directory is provided to working groups as a
+ resource for posting and disseminating in-process copies of working
+ group documents. This repository is replicated at various locations
+ around the Internet. It is encouraged that draft documents be posted
+
+
+
+Bradner Best Current Practice [Page 19]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ as soon as they become reasonably stable.
+
+ It is stressed here that Internet-Drafts are working documents and
+ have no official standards status whatsoever. They may, eventually,
+ turn into a standards-track document or they may sink from sight.
+ Internet-Drafts are submitted to: internet-drafts@ietf.org
+
+ The format of an Internet-Draft must be the same as for an RFC [2].
+ Further, an I-D must contain:
+
+ - Beginning, standard, boilerplate text which is provided by the
+ Secretariat on their web site and in the ftp directory;
+ - The I-D filename; and
+ - The expiration date for the I-D.
+
+ Complete specification of requirements for an Internet-Draft are
+ found in the file "1id-guidelines.txt" in the Internet-Drafts
+ directory at an Internet Repository site. The organization of the
+ Internet-Drafts directory is found in the file "1id-organization" in
+ the Internet-Drafts directory at an Internet Repository site. This
+ file also contains the rules for naming Internet-Drafts. (See [1]
+ for more information about Internet-Drafts.)
+
+7.3. Request For Comments (RFC)
+
+ The work of an IETF working group often results in publication of one
+ or more documents, as part of the Request For Comments (RFCs) [1]
+ series. This series is the archival publication record for the
+ Internet community. A document can be written by an individual in a
+ working group, by a group as a whole with a designated Editor, or by
+ others not involved with the IETF.
+
+ NOTE: The RFC series is a publication mechanism only and publication
+ does not determine the IETF status of a document. Status is
+ determined through separate, explicit status labels assigned by the
+ IESG on behalf of the IETF. In other words, the reader is reminded
+ that all Internet Standards are published as RFCs, but NOT all RFCs
+ specify standards [4].
+
+7.4. Working Group Last-Call
+
+ When a WG decides that a document is ready for publication it may be
+ submitted to the IESG for consideration. In most cases the
+ determination that a WG feels that a document is ready for
+ publication is done by the WG Chair issuing a working group Last-
+ Call. The decision to issue a working group Last-Call is at the
+ discretion of the WG Chair working with the Area Director. A working
+ group Last-Call serves the same purpose within a working group that
+
+
+
+Bradner Best Current Practice [Page 20]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ an IESG Last-Call does in the broader IETF community (see [1]).
+
+7.5. Submission of documents
+
+ Once that a WG has determined at least rough consensus exists within
+ the WG for the advancement of a document the following must be done:
+
+ - The version of the relevant document exactly as agreed to by the WG
+ MUST be in the Internet-Drafts directory.
+
+ - The relevant document MUST be formatted according to section 7.3.
+
+ - The WG Chair MUST send email to the relevant Area Director. A copy
+ of the request MUST be also sent to the IESG Secretariat. The mail
+ MUST contain the reference to the document's ID filename, and the
+ action requested. The copy of the message to the IESG Secretariat
+ is to ensure that the request gets recorded by the Secretariat so
+ that they can monitor the progress of the document through the
+ process.
+
+ Unless returned by the IESG to the WG for further development,
+ progressing of the document is then the responsibility of the IESG.
+ After IESG approval, responsibility for final disposition is the
+ joint responsibility of the RFC Editor, the WG Chair and the Document
+ Editor.
+
+8. Review of documents
+
+ The IESG reviews all documents submitted for publication as RFCs.
+ Usually minimal IESG review is necessary in the case of a submission
+ from a WG intended as an Informational or Experimental RFC. More
+ extensive review is undertaken in the case of standards-track
+ documents.
+
+ Prior to the IESG beginning their deliberations on standards-track
+ documents, IETF Secretariat will issue a "Last-Call" to the IETF
+ mailing list (see [1]). This Last Call will announce the intention of
+ the IESG to consider the document, and it will solicit final comments
+ from the IETF within a period of two weeks. It is important to note
+ that a Last-Call is intended as a brief, final check with the
+ Internet community, to make sure that no important concerns have been
+ missed or misunderstood. The Last-Call should not serve as a more
+ general, in-depth review.
+
+ The IESG review takes into account responses to the Last-Call and
+ will lead to one of these possible conclusions:
+
+
+
+
+
+Bradner Best Current Practice [Page 21]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ 1. The document is accepted as is for the status requested.
+ This fact will be announced by the IETF Secretariat to the IETF
+ mailing list and to the RFC Editor.
+
+ 2. The document is accepted as-is but not for the status requested.
+ This fact will be announced by the IETF Secretariat to the IETF
+ mailing list and to the RFC Editor (see [1] for more details).
+
+ 3. Changes regarding content are suggested to the author(s)/WG.
+ Suggestions from the IESG must be clear and direct, so as to
+ facilitate working group and author correction of the
+ specification. If the author(s)/WG can explain to the
+ satisfaction of the IESG why the changes are not necessary, the
+ document will be accepted for publication as under point 1, above.
+ If the changes are made the revised document may be resubmitted
+ for IESG review.
+
+ 4. Changes are suggested by the IESG and a change in status is
+ recommended.
+ The process described above for 3 and 2 are followed in that
+ order.
+
+ 5. The document is rejected.
+ Any document rejection will be accompanied by specific and
+ thorough arguments from the IESG. Although the IETF and working
+ group process is structured such that this alternative is not
+ likely to arise for documents coming from a working group, the
+ IESG has the right and responsibility to reject documents that the
+ IESG feels are fatally flawed in some way.
+
+ If any individual or group of individuals feels that the review
+ treatment has been unfair, there is the opportunity to make a
+ procedural complaint. The mechanism for this type of complaints is
+ described in [1].
+
+9. Security Considerations
+
+ Documents describing IETF processes, such as this one, do not have an
+ impact on the security of the network infrastructure or of Internet
+ applications.
+
+ It should be noted that all IETF working groups are required to
+ examine and understand the security implications of any technology
+ they develop. This analysis must be included in any resulting RFCs
+ in a Security Considerations section. Note that merely noting a
+ significant security hole is no longer sufficient. IETF developed
+ technologies should not add insecurity to the environment in which
+ they are run.
+
+
+
+Bradner Best Current Practice [Page 22]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+10. Acknowledgments
+
+ This revision of this document relies heavily on the previous version
+ (RFC 1603) which was edited by Erik Huizer and Dave Crocker. It has
+ been reviewed by the Poisson Working Group.
+
+11. References
+
+ [1] Bradner, S., Editor, "The Internet Standards Process -- Revision
+ 3", BCP 9, RFC 2026, October 1996.
+
+ [2] Hovey, R., and S. Bradner, "The Organizations involved in the
+ IETF Standards Process", BCP 11, RFC 2028, October 1996.
+
+ [3] Gavin, J., "IAB and IESG Selection, Confirmation, and Recall
+ Process: Operation of the Nominating and Recall Committees", BCP
+ 10, RFC 2282, February 1998.
+
+ [4] Huitema, C., J. Postel, S. Crocker, "Not all RFCs are Standards",
+ RFC 1796, April 1995.
+
+ [5] Postel, J., and J. Reynolds, "Instructions to RFC Authors", RFC
+ 2223, October 1997.
+
+ [6] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Level", BCP 14, RFC 2119, March 1997.
+
+
+12. Editor's Address
+
+ Scott Bradner
+ Harvard University
+ 1350 Mass Ave.
+ Cambridge MA
+ 02138
+ USA
+
+ Phone +1 617 495 3864
+ EMail: sob@harvard.edu
+
+
+
+
+
+
+
+
+
+
+
+
+Bradner Best Current Practice [Page 23]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ Appendix: Sample Working Group Charter
+
+ Working Group Name:
+ IP Telephony (iptel)
+
+ IETF Area:
+ Transport Area
+
+ Chair(s):
+ Jonathan Rosenberg <jdrosen@bell-labs.com>
+
+ Transport Area Director(s):
+ Scott Bradner <sob@harvard.edu>
+ Allyn Romanow <allyn@mci.net>
+
+ Responsible Area Director:
+ Allyn Romanow <allyn@mci.net>
+
+ Mailing Lists:
+ General Discussion:iptel@lists.research.bell-labs.com
+ To Subscribe: iptel-request@lists.research.bell-labs.com
+ Archive: http://www.bell-labs.com/mailing-lists/siptel
+
+ Description of Working Group:
+
+ Before Internet telephony can become a widely deployed service, a
+ number of protocols must be deployed. These include signaling and
+ capabilities exchange, but also include a number of "peripheral"
+ protocols for providing related services.
+
+ The primary purpose of this working group is to develop two such
+ supportive protocols and a frameword document. They are:
+
+ 1. Call Processing Syntax. When a call is setup between two
+ endpoints, the signaling will generally pass through several servers
+ (such as an H.323 gatekeeper) which are responsible for forwarding,
+ redirecting, or proxying the signaling messages. For example, a user
+ may make a call to j.doe@bigcompany.com. The signaling message to
+ initiate the call will arrive at some server at bigcompany. This
+ server can inform the caller that the callee is busy, forward the
+ call initiation request to another server closer to the user, or drop
+ the call completely (among other possibilities). It is very desirable
+ to allow the callee to provide input to this process, guiding the
+ server in its decision on how to act. This can enable a wide variety
+ of advanced personal mobility and call agent services.
+
+
+
+
+
+
+Bradner Best Current Practice [Page 24]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+ Such preferences can be expressed in a call processing syntax, which
+ can be authored by the user (or generated automatically by some
+ tool), and then uploaded to the server. The group will develop this
+ syntax, and specify means of securely transporting and extending it.
+ The result will be a single standards track RFC.
+
+ 2. In addition, the group will write a service model document, which
+ describes the services that are enabled by the call processing
+ syntax, and discusses how the syntax can be used. This document will
+ result in a single RFC.
+
+ 3. Gateway Attribute Distribution Protocol. When making a call
+ between an IP host and a PSTN user, a telephony gateway must be used.
+ The selection of such gateways can be based on many criteria,
+ including client expressed preferences, service provider preferences,
+ and availability of gateways, in addition to destination telephone
+ number. Since gateways outside of the hosts' administrative domain
+ might be used, a protocol is required to allow gateways in remote
+ domains to distribute their attributes (such as PSTN connectivity,
+ supported codecs, etc.) to entities in other domains which must make
+ a selection of a gateway. The protocol must allow for scalable,
+ bandwidth efficient, and very secure transmission of these
+ attributes. The group will investigate and design a protocol for this
+ purpose, generate an Internet Draft, and advance it to RFC as
+ appropriate.
+
+ Goals and Milestones:
+
+ May 98 Issue first Internet-Draft on service framework
+ Jul 98 Submit framework ID to IESG for publication as an RFC.
+ Aug 98 Issue first Internet-Draft on Call Processing Syntax
+ Oct 98 Submit Call processing syntax to IESG for consideration
+ as a Proposed Standard.
+ Dec 98 Achieve consensus on basics of gateway attribute
+ distribution protocol
+ Jan 99 Submit Gateway Attribute Distribution protocol to IESG
+ for consideration as a RFC (info, exp, stds track TB
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bradner Best Current Practice [Page 25]
+
+RFC 2418 Working Group Guidelines September 1998
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bradner Best Current Practice [Page 26]
+
diff --git a/doc/rfc/rfc2535.txt b/doc/rfc/rfc2535.txt
new file mode 100644
index 0000000..fe0b3d0
--- /dev/null
+++ b/doc/rfc/rfc2535.txt
@@ -0,0 +1,2635 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake
+Request for Comments: 2535 IBM
+Obsoletes: 2065 March 1999
+Updates: 2181, 1035, 1034
+Category: Standards Track
+
+ Domain Name System Security Extensions
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ Extensions to the Domain Name System (DNS) are described that provide
+ data integrity and authentication to security aware resolvers and
+ applications through the use of cryptographic digital signatures.
+ These digital signatures are included in secured zones as resource
+ records. Security can also be provided through non-security aware
+ DNS servers in some cases.
+
+ The extensions provide for the storage of authenticated public keys
+ in the DNS. This storage of keys can support general public key
+ distribution services as well as DNS security. The stored keys
+ enable security aware resolvers to learn the authenticating key of
+ zones in addition to those for which they are initially configured.
+ Keys associated with DNS names can be retrieved to support other
+ protocols. Provision is made for a variety of key types and
+ algorithms.
+
+ In addition, the security extensions provide for the optional
+ authentication of DNS protocol transactions and requests.
+
+ This document incorporates feedback on RFC 2065 from early
+ implementers and potential users.
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 1]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+Acknowledgments
+
+ The significant contributions and suggestions of the following
+ persons (in alphabetic order) to DNS security are gratefully
+ acknowledged:
+
+ James M. Galvin
+ John Gilmore
+ Olafur Gudmundsson
+ Charlie Kaufman
+ Edward Lewis
+ Thomas Narten
+ Radia J. Perlman
+ Jeffrey I. Schiller
+ Steven (Xunhua) Wang
+ Brian Wellington
+
+Table of Contents
+
+ Abstract...................................................1
+ Acknowledgments............................................2
+ 1. Overview of Contents....................................4
+ 2. Overview of the DNS Extensions..........................5
+ 2.1 Services Not Provided..................................5
+ 2.2 Key Distribution.......................................5
+ 2.3 Data Origin Authentication and Integrity...............6
+ 2.3.1 The SIG Resource Record..............................7
+ 2.3.2 Authenticating Name and Type Non-existence...........7
+ 2.3.3 Special Considerations With Time-to-Live.............7
+ 2.3.4 Special Considerations at Delegation Points..........8
+ 2.3.5 Special Considerations with CNAME....................8
+ 2.3.6 Signers Other Than The Zone..........................9
+ 2.4 DNS Transaction and Request Authentication.............9
+ 3. The KEY Resource Record................................10
+ 3.1 KEY RDATA format......................................10
+ 3.1.1 Object Types, DNS Names, and Keys...................11
+ 3.1.2 The KEY RR Flag Field...............................11
+ 3.1.3 The Protocol Octet..................................13
+ 3.2 The KEY Algorithm Number Specification................14
+ 3.3 Interaction of Flags, Algorithm, and Protocol Bytes...15
+ 3.4 Determination of Zone Secure/Unsecured Status.........15
+ 3.5 KEY RRs in the Construction of Responses..............17
+ 4. The SIG Resource Record................................17
+ 4.1 SIG RDATA Format......................................17
+ 4.1.1 Type Covered Field..................................18
+ 4.1.2 Algorithm Number Field..............................18
+ 4.1.3 Labels Field........................................18
+ 4.1.4 Original TTL Field..................................19
+
+
+
+Eastlake Standards Track [Page 2]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ 4.1.5 Signature Expiration and Inception Fields...........19
+ 4.1.6 Key Tag Field.......................................20
+ 4.1.7 Signer's Name Field.................................20
+ 4.1.8 Signature Field.....................................20
+ 4.1.8.1 Calculating Transaction and Request SIGs..........21
+ 4.2 SIG RRs in the Construction of Responses..............21
+ 4.3 Processing Responses and SIG RRs......................22
+ 4.4 Signature Lifetime, Expiration, TTLs, and Validity....23
+ 5. Non-existent Names and Types...........................24
+ 5.1 The NXT Resource Record...............................24
+ 5.2 NXT RDATA Format......................................25
+ 5.3 Additional Complexity Due to Wildcards................26
+ 5.4 Example...............................................26
+ 5.5 Special Considerations at Delegation Points...........27
+ 5.6 Zone Transfers........................................27
+ 5.6.1 Full Zone Transfers.................................28
+ 5.6.2 Incremental Zone Transfers..........................28
+ 6. How to Resolve Securely and the AD and CD Bits.........29
+ 6.1 The AD and CD Header Bits.............................29
+ 6.2 Staticly Configured Keys..............................31
+ 6.3 Chaining Through The DNS..............................31
+ 6.3.1 Chaining Through KEYs...............................31
+ 6.3.2 Conflicting Data....................................33
+ 6.4 Secure Time...........................................33
+ 7. ASCII Representation of Security RRs...................34
+ 7.1 Presentation of KEY RRs...............................34
+ 7.2 Presentation of SIG RRs...............................35
+ 7.3 Presentation of NXT RRs...............................36
+ 8. Canonical Form and Order of Resource Records...........36
+ 8.1 Canonical RR Form.....................................36
+ 8.2 Canonical DNS Name Order..............................37
+ 8.3 Canonical RR Ordering Within An RRset.................37
+ 8.4 Canonical Ordering of RR Types........................37
+ 9. Conformance............................................37
+ 9.1 Server Conformance....................................37
+ 9.2 Resolver Conformance..................................38
+ 10. Security Considerations...............................38
+ 11. IANA Considerations...................................39
+ References................................................39
+ Author's Address..........................................41
+ Appendix A: Base 64 Encoding..............................42
+ Appendix B: Changes from RFC 2065.........................44
+ Appendix C: Key Tag Calculation...........................46
+ Full Copyright Statement..................................47
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 3]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+1. Overview of Contents
+
+ This document standardizes extensions of the Domain Name System (DNS)
+ protocol to support DNS security and public key distribution. It
+ assumes that the reader is familiar with the Domain Name System,
+ particularly as described in RFCs 1033, 1034, 1035 and later RFCs. An
+ earlier version of these extensions appears in RFC 2065. This
+ replacement for that RFC incorporates early implementation experience
+ and requests from potential users.
+
+ Section 2 provides an overview of the extensions and the key
+ distribution, data origin authentication, and transaction and request
+ security they provide.
+
+ Section 3 discusses the KEY resource record, its structure, and use
+ in DNS responses. These resource records represent the public keys
+ of entities named in the DNS and are used for key distribution.
+
+ Section 4 discusses the SIG digital signature resource record, its
+ structure, and use in DNS responses. These resource records are used
+ to authenticate other resource records in the DNS and optionally to
+ authenticate DNS transactions and requests.
+
+ Section 5 discusses the NXT resource record (RR) and its use in DNS
+ responses including full and incremental zone transfers. The NXT RR
+ permits authenticated denial of the existence of a name or of an RR
+ type for an existing name.
+
+ Section 6 discusses how a resolver can be configured with a starting
+ key or keys and proceed to securely resolve DNS requests.
+ Interactions between resolvers and servers are discussed for various
+ combinations of security aware and security non-aware. Two
+ additional DNS header bits are defined for signaling between
+ resolvers and servers.
+
+ Section 7 describes the ASCII representation of the security resource
+ records for use in master files and elsewhere.
+
+ Section 8 defines the canonical form and order of RRs for DNS
+ security purposes.
+
+ Section 9 defines levels of conformance for resolvers and servers.
+
+ Section 10 provides a few paragraphs on overall security
+ considerations.
+
+ Section 11 specified IANA considerations for allocation of additional
+ values of paramters defined in this document.
+
+
+
+Eastlake Standards Track [Page 4]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ Appendix A gives details of base 64 encoding which is used in the
+ file representation of some RRs defined in this document.
+
+ Appendix B summarizes changes between this memo and RFC 2065.
+
+ Appendix C specified how to calculate the simple checksum used as a
+ key tag in most SIG RRs.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+2. Overview of the DNS Extensions
+
+ The Domain Name System (DNS) protocol security extensions provide
+ three distinct services: key distribution as described in Section 2.2
+ below, data origin authentication as described in Section 2.3 below,
+ and transaction and request authentication, described in Section 2.4
+ below.
+
+ Special considerations related to "time to live", CNAMEs, and
+ delegation points are also discussed in Section 2.3.
+
+2.1 Services Not Provided
+
+ It is part of the design philosophy of the DNS that the data in it is
+ public and that the DNS gives the same answers to all inquirers.
+ Following this philosophy, no attempt has been made to include any
+ sort of access control lists or other means to differentiate
+ inquirers.
+
+ No effort has been made to provide for any confidentiality for
+ queries or responses. (This service may be available via IPSEC [RFC
+ 2401], TLS, or other security protocols.)
+
+ Protection is not provided against denial of service.
+
+2.2 Key Distribution
+
+ A resource record format is defined to associate keys with DNS names.
+ This permits the DNS to be used as a public key distribution
+ mechanism in support of DNS security itself and other protocols.
+
+ The syntax of a KEY resource record (RR) is described in Section 3.
+ It includes an algorithm identifier, the actual public key
+ parameter(s), and a variety of flags including those indicating the
+ type of entity the key is associated with and/or asserting that there
+ is no key associated with that entity.
+
+
+
+Eastlake Standards Track [Page 5]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ Under conditions described in Section 3.5, security aware DNS servers
+ will automatically attempt to return KEY resources as additional
+ information, along with those resource records actually requested, to
+ minimize the number of queries needed.
+
+2.3 Data Origin Authentication and Integrity
+
+ Authentication is provided by associating with resource record sets
+ (RRsets [RFC 2181]) in the DNS cryptographically generated digital
+ signatures. Commonly, there will be a single private key that
+ authenticates an entire zone but there might be multiple keys for
+ different algorithms, signers, etc. If a security aware resolver
+ reliably learns a public key of the zone, it can authenticate, for
+ signed data read from that zone, that it is properly authorized. The
+ most secure implementation is for the zone private key(s) to be kept
+ off-line and used to re-sign all of the records in the zone
+ periodically. However, there are cases, for example dynamic update
+ [RFCs 2136, 2137], where DNS private keys need to be on-line [RFC
+ 2541].
+
+ The data origin authentication key(s) are associated with the zone
+ and not with the servers that store copies of the data. That means
+ compromise of a secondary server or, if the key(s) are kept off line,
+ even the primary server for a zone, will not necessarily affect the
+ degree of assurance that a resolver has that it can determine whether
+ data is genuine.
+
+ A resolver could learn a public key of a zone either by reading it
+ from the DNS or by having it staticly configured. To reliably learn
+ a public key by reading it from the DNS, the key itself must be
+ signed with a key the resolver trusts. The resolver must be
+ configured with at least a public key which authenticates one zone as
+ a starting point. From there, it can securely read public keys of
+ other zones, if the intervening zones in the DNS tree are secure and
+ their signed keys accessible.
+
+ Adding data origin authentication and integrity requires no change to
+ the "on-the-wire" DNS protocol beyond the addition of the signature
+ resource type and the key resource type needed for key distribution.
+ (Data non-existence authentication also requires the NXT RR as
+ described in 2.3.2.) This service can be supported by existing
+ resolver and caching server implementations so long as they can
+ support the additional resource types (see Section 9). The one
+ exception is that CNAME referrals in a secure zone can not be
+ authenticated if they are from non-security aware servers (see
+ Section 2.3.5).
+
+
+
+
+
+Eastlake Standards Track [Page 6]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ If signatures are separately retrieved and verified when retrieving
+ the information they authenticate, there will be more trips to the
+ server and performance will suffer. Security aware servers mitigate
+ that degradation by attempting to send the signature(s) needed (see
+ Section 4.2).
+
+2.3.1 The SIG Resource Record
+
+ The syntax of a SIG resource record (signature) is described in
+ Section 4. It cryptographicly binds the RRset being signed to the
+ signer and a validity interval.
+
+ Every name in a secured zone will have associated with it at least
+ one SIG resource record for each resource type under that name except
+ for glue address RRs and delegation point NS RRs. A security aware
+ server will attempt to return, with RRs retrieved, the corresponding
+ SIGs. If a server is not security aware, the resolver must retrieve
+ all the SIG records for a name and select the one or ones that sign
+ the resource record set(s) that resolver is interested in.
+
+2.3.2 Authenticating Name and Type Non-existence
+
+ The above security mechanism only provides a way to sign existing
+ RRsets in a zone. "Data origin" authentication is not obviously
+ provided for the non-existence of a domain name in a zone or the
+ non-existence of a type for an existing name. This gap is filled by
+ the NXT RR which authenticatably asserts a range of non-existent
+ names in a zone and the non-existence of types for the existing name
+ just before that range.
+
+ Section 5 below covers the NXT RR.
+
+2.3.3 Special Considerations With Time-to-Live
+
+ A digital signature will fail to verify if any change has occurred to
+ the data between the time it was originally signed and the time the
+ signature is verified. This conflicts with our desire to have the
+ time-to-live (TTL) field of resource records tick down while they are
+ cached.
+
+ This could be avoided by leaving the time-to-live out of the digital
+ signature, but that would allow unscrupulous servers to set
+ arbitrarily long TTL values undetected. Instead, we include the
+ "original" TTL in the signature and communicate that data along with
+ the current TTL. Unscrupulous servers under this scheme can
+ manipulate the TTL but a security aware resolver will bound the TTL
+ value it uses at the original signed value. Separately, signatures
+ include a signature inception time and a signature expiration time. A
+
+
+
+Eastlake Standards Track [Page 7]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ resolver that knows the absolute time can determine securely whether
+ a signature is in effect. It is not possible to rely solely on the
+ signature expiration as a substitute for the TTL, however, since the
+ TTL is primarily a database consistency mechanism and non-security
+ aware servers that depend on TTL must still be supported.
+
+2.3.4 Special Considerations at Delegation Points
+
+ DNS security would like to view each zone as a unit of data
+ completely under the control of the zone owner with each entry
+ (RRset) signed by a special private key held by the zone manager.
+ But the DNS protocol views the leaf nodes in a zone, which are also
+ the apex nodes of a subzone (i.e., delegation points), as "really"
+ belonging to the subzone. These nodes occur in two master files and
+ might have RRs signed by both the upper and lower zone's keys. A
+ retrieval could get a mixture of these RRs and SIGs, especially since
+ one server could be serving both the zone above and below a
+ delegation point. [RFC 2181]
+
+ There MUST be a zone KEY RR, signed by its superzone, for every
+ subzone if the superzone is secure. This will normally appear in the
+ subzone and may also be included in the superzone. But, in the case
+ of an unsecured subzone which can not or will not be modified to add
+ any security RRs, a KEY declaring the subzone to be unsecured MUST
+ appear with the superzone signature in the superzone, if the
+ superzone is secure. For all but one other RR type the data from the
+ subzone is more authoritative so only the subzone KEY RR should be
+ signed in the superzone if it appears there. The NS and any glue
+ address RRs SHOULD only be signed in the subzone. The SOA and any
+ other RRs that have the zone name as owner should appear only in the
+ subzone and thus are signed only there. The NXT RR type is the
+ exceptional case that will always appear differently and
+ authoritatively in both the superzone and subzone, if both are
+ secure, as described in Section 5.
+
+2.3.5 Special Considerations with CNAME
+
+ There is a problem when security related RRs with the same owner name
+ as a CNAME RR are retrieved from a non-security-aware server. In
+ particular, an initial retrieval for the CNAME or any other type may
+ not retrieve any associated SIG, KEY, or NXT RR. For retrieved types
+ other than CNAME, it will retrieve that type at the target name of
+ the CNAME (or chain of CNAMEs) and will also return the CNAME. In
+ particular, a specific retrieval for type SIG will not get the SIG,
+ if any, at the original CNAME domain name but rather a SIG at the
+ target name.
+
+
+
+
+
+Eastlake Standards Track [Page 8]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ Security aware servers must be used to securely CNAME in DNS.
+ Security aware servers MUST (1) allow KEY, SIG, and NXT RRs along
+ with CNAME RRs, (2) suppress CNAME processing on retrieval of these
+ types as well as on retrieval of the type CNAME, and (3)
+ automatically return SIG RRs authenticating the CNAME or CNAMEs
+ encountered in resolving a query. This is a change from the previous
+ DNS standard [RFCs 1034/1035] which prohibited any other RR type at a
+ node where a CNAME RR was present.
+
+2.3.6 Signers Other Than The Zone
+
+ There are cases where the signer in a SIG resource record is other
+ than one of the private key(s) used to authenticate a zone.
+
+ One is for support of dynamic update [RFC 2136] (or future requests
+ which require secure authentication) where an entity is permitted to
+ authenticate/update its records [RFC 2137] and the zone is operating
+ in a mode where the zone key is not on line. The public key of the
+ entity must be present in the DNS and be signed by a zone level key
+ but the other RR(s) may be signed with the entity's key.
+
+ A second case is support of transaction and request authentication as
+ described in Section 2.4.
+
+ In additions, signatures can be included on resource records within
+ the DNS for use by applications other than DNS. DNS related
+ signatures authenticate that data originated with the authority of a
+ zone owner or that a request or transaction originated with the
+ relevant entity. Other signatures can provide other types of
+ assurances.
+
+2.4 DNS Transaction and Request Authentication
+
+ The data origin authentication service described above protects
+ retrieved resource records and the non-existence of resource records
+ but provides no protection for DNS requests or for message headers.
+
+ If header bits are falsely set by a bad server, there is little that
+ can be done. However, it is possible to add transaction
+ authentication. Such authentication means that a resolver can be
+ sure it is at least getting messages from the server it thinks it
+ queried and that the response is from the query it sent (i.e., that
+ these messages have not been diddled in transit). This is
+ accomplished by optionally adding a special SIG resource record at
+ the end of the reply which digitally signs the concatenation of the
+ server's response and the resolver's query.
+
+
+
+
+
+Eastlake Standards Track [Page 9]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ Requests can also be authenticated by including a special SIG RR at
+ the end of the request. Authenticating requests serves no function
+ in older DNS servers and requests with a non-empty additional
+ information section produce error returns or may even be ignored by
+ many of them. However, this syntax for signing requests is defined as
+ a way of authenticating secure dynamic update requests [RFC 2137] or
+ future requests requiring authentication.
+
+ The private keys used in transaction security belong to the entity
+ composing the reply, not to the zone involved. Request
+ authentication may also involve the private key of the host or other
+ entity composing the request or other private keys depending on the
+ request authority it is sought to establish. The corresponding public
+ key(s) are normally stored in and retrieved from the DNS for
+ verification.
+
+ Because requests and replies are highly variable, message
+ authentication SIGs can not be pre-calculated. Thus it will be
+ necessary to keep the private key on-line, for example in software or
+ in a directly connected piece of hardware.
+
+3. The KEY Resource Record
+
+ The KEY resource record (RR) is used to store a public key that is
+ associated with a Domain Name System (DNS) name. This can be the
+ public key of a zone, a user, or a host or other end entity. Security
+ aware DNS implementations MUST be designed to handle at least two
+ simultaneously valid keys of the same type associated with the same
+ name.
+
+ The type number for the KEY RR is 25.
+
+ A KEY RR is, like any other RR, authenticated by a SIG RR. KEY RRs
+ must be signed by a zone level key.
+
+3.1 KEY RDATA format
+
+ The RDATA for a KEY RR consists of flags, a protocol octet, the
+ algorithm number octet, and the public key itself. The format is as
+ follows:
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 10]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | flags | protocol | algorithm |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | /
+ / public key /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+
+ The KEY RR is not intended for storage of certificates and a separate
+ certificate RR has been developed for that purpose, defined in [RFC
+ 2538].
+
+ The meaning of the KEY RR owner name, flags, and protocol octet are
+ described in Sections 3.1.1 through 3.1.5 below. The flags and
+ algorithm must be examined before any data following the algorithm
+ octet as they control the existence and format of any following data.
+ The algorithm and public key fields are described in Section 3.2.
+ The format of the public key is algorithm dependent.
+
+ KEY RRs do not specify their validity period but their authenticating
+ SIG RR(s) do as described in Section 4 below.
+
+3.1.1 Object Types, DNS Names, and Keys
+
+ The public key in a KEY RR is for the object named in the owner name.
+
+ A DNS name may refer to three different categories of things. For
+ example, foo.host.example could be (1) a zone, (2) a host or other
+ end entity , or (3) the mapping into a DNS name of the user or
+ account foo@host.example. Thus, there are flag bits, as described
+ below, in the KEY RR to indicate with which of these roles the owner
+ name and public key are associated. Note that an appropriate zone
+ KEY RR MUST occur at the apex node of a secure zone and zone KEY RRs
+ occur only at delegation points.
+
+3.1.2 The KEY RR Flag Field
+
+ In the "flags" field:
+
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ | A/C | Z | XT| Z | Z | NAMTYP| Z | Z | Z | Z | SIG |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+
+ Bit 0 and 1 are the key "type" bits whose values have the following
+ meanings:
+
+
+
+Eastlake Standards Track [Page 11]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ 10: Use of the key is prohibited for authentication.
+ 01: Use of the key is prohibited for confidentiality.
+ 00: Use of the key for authentication and/or confidentiality
+ is permitted. Note that DNS security makes use of keys
+ for authentication only. Confidentiality use flagging is
+ provided for use of keys in other protocols.
+ Implementations not intended to support key distribution
+ for confidentiality MAY require that the confidentiality
+ use prohibited bit be on for keys they serve.
+ 11: If both bits are one, the "no key" value, there is no key
+ information and the RR stops after the algorithm octet.
+ By the use of this "no key" value, a signed KEY RR can
+ authenticatably assert that, for example, a zone is not
+ secured. See section 3.4 below.
+
+ Bits 2 is reserved and must be zero.
+
+ Bits 3 is reserved as a flag extension bit. If it is a one, a second
+ 16 bit flag field is added after the algorithm octet and
+ before the key data. This bit MUST NOT be set unless one or
+ more such additional bits have been defined and are non-zero.
+
+ Bits 4-5 are reserved and must be zero.
+
+ Bits 6 and 7 form a field that encodes the name type. Field values
+ have the following meanings:
+
+ 00: indicates that this is a key associated with a "user" or
+ "account" at an end entity, usually a host. The coding
+ of the owner name is that used for the responsible
+ individual mailbox in the SOA and RP RRs: The owner name
+ is the user name as the name of a node under the entity
+ name. For example, "j_random_user" on
+ host.subdomain.example could have a public key associated
+ through a KEY RR with name
+ j_random_user.host.subdomain.example. It could be used
+ in a security protocol where authentication of a user was
+ desired. This key might be useful in IP or other
+ security for a user level service such a telnet, ftp,
+ rlogin, etc.
+ 01: indicates that this is a zone key for the zone whose name
+ is the KEY RR owner name. This is the public key used
+ for the primary DNS security feature of data origin
+ authentication. Zone KEY RRs occur only at delegation
+ points.
+ 10: indicates that this is a key associated with the non-zone
+ "entity" whose name is the RR owner name. This will
+ commonly be a host but could, in some parts of the DNS
+
+
+
+Eastlake Standards Track [Page 12]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ tree, be some other type of entity such as a telephone
+ number [RFC 1530] or numeric IP address. This is the
+ public key used in connection with DNS request and
+ transaction authentication services. It could also be
+ used in an IP-security protocol where authentication at
+ the host, rather than user, level was desired, such as
+ routing, NTP, etc.
+ 11: reserved.
+
+ Bits 8-11 are reserved and must be zero.
+
+ Bits 12-15 are the "signatory" field. If non-zero, they indicate
+ that the key can validly sign things as specified in DNS
+ dynamic update [RFC 2137]. Note that zone keys (see bits
+ 6 and 7 above) always have authority to sign any RRs in
+ the zone regardless of the value of the signatory field.
+
+3.1.3 The Protocol Octet
+
+ It is anticipated that keys stored in DNS will be used in conjunction
+ with a variety of Internet protocols. It is intended that the
+ protocol octet and possibly some of the currently unused (must be
+ zero) bits in the KEY RR flags as specified in the future will be
+ used to indicate a key's validity for different protocols.
+
+ The following values of the Protocol Octet are reserved as indicated:
+
+ VALUE Protocol
+
+ 0 -reserved
+ 1 TLS
+ 2 email
+ 3 dnssec
+ 4 IPSEC
+ 5-254 - available for assignment by IANA
+ 255 All
+
+ In more detail:
+ 1 is reserved for use in connection with TLS.
+ 2 is reserved for use in connection with email.
+ 3 is used for DNS security. The protocol field SHOULD be set to
+ this value for zone keys and other keys used in DNS security.
+ Implementations that can determine that a key is a DNS
+ security key by the fact that flags label it a zone key or the
+ signatory flag field is non-zero are NOT REQUIRED to check the
+ protocol field.
+ 4 is reserved to refer to the Oakley/IPSEC [RFC 2401] protocol
+ and indicates that this key is valid for use in conjunction
+
+
+
+Eastlake Standards Track [Page 13]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ with that security standard. This key could be used in
+ connection with secured communication on behalf of an end
+ entity or user whose name is the owner name of the KEY RR if
+ the entity or user flag bits are set. The presence of a KEY
+ resource with this protocol value is an assertion that the
+ host speaks Oakley/IPSEC.
+ 255 indicates that the key can be used in connection with any
+ protocol for which KEY RR protocol octet values have been
+ defined. The use of this value is discouraged and the use of
+ different keys for different protocols is encouraged.
+
+3.2 The KEY Algorithm Number Specification
+
+ This octet is the key algorithm parallel to the same field for the
+ SIG resource as described in Section 4.1. The following values are
+ assigned:
+
+ VALUE Algorithm
+
+ 0 - reserved, see Section 11
+ 1 RSA/MD5 [RFC 2537] - recommended
+ 2 Diffie-Hellman [RFC 2539] - optional, key only
+ 3 DSA [RFC 2536] - MANDATORY
+ 4 reserved for elliptic curve crypto
+ 5-251 - available, see Section 11
+ 252 reserved for indirect keys
+ 253 private - domain name (see below)
+ 254 private - OID (see below)
+ 255 - reserved, see Section 11
+
+ Algorithm specific formats and procedures are given in separate
+ documents. The mandatory to implement for interoperability algorithm
+ is number 3, DSA. It is recommended that the RSA/MD5 algorithm,
+ number 1, also be implemented. Algorithm 2 is used to indicate
+ Diffie-Hellman keys and algorithm 4 is reserved for elliptic curve.
+
+ Algorithm number 252 indicates an indirect key format where the
+ actual key material is elsewhere. This format is to be defined in a
+ separate document.
+
+ Algorithm numbers 253 and 254 are reserved for private use and will
+ never be assigned a specific algorithm. For number 253, the public
+ key area and the signature begin with a wire encoded domain name.
+ Only local domain name compression is permitted. The domain name
+ indicates the private algorithm to use and the remainder of the
+ public key area is whatever is required by that algorithm. For
+ number 254, the public key area for the KEY RR and the signature
+ begin with an unsigned length byte followed by a BER encoded Object
+
+
+
+Eastlake Standards Track [Page 14]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ Identifier (ISO OID) of that length. The OID indicates the private
+ algorithm in use and the remainder of the area is whatever is
+ required by that algorithm. Entities should only use domain names
+ and OIDs they control to designate their private algorithms.
+
+ Values 0 and 255 are reserved but the value 0 is used in the
+ algorithm field when that field is not used. An example is in a KEY
+ RR with the top two flag bits on, the "no-key" value, where no key is
+ present.
+
+3.3 Interaction of Flags, Algorithm, and Protocol Bytes
+
+ Various combinations of the no-key type flags, algorithm byte,
+ protocol byte, and any future assigned protocol indicating flags are
+ possible. The meaning of these combinations is indicated below:
+
+ NK = no key type (flags bits 0 and 1 on)
+ AL = algorithm byte
+ PR = protocols indicated by protocol byte or future assigned flags
+
+ x represents any valid non-zero value(s).
+
+ AL PR NK Meaning
+ 0 0 0 Illegal, claims key but has bad algorithm field.
+ 0 0 1 Specifies total lack of security for owner zone.
+ 0 x 0 Illegal, claims key but has bad algorithm field.
+ 0 x 1 Specified protocols unsecured, others may be secure.
+ x 0 0 Gives key but no protocols to use it.
+ x 0 1 Denies key for specific algorithm.
+ x x 0 Specifies key for protocols.
+ x x 1 Algorithm not understood for protocol.
+
+3.4 Determination of Zone Secure/Unsecured Status
+
+ A zone KEY RR with the "no-key" type field value (both key type flag
+ bits 0 and 1 on) indicates that the zone named is unsecured while a
+ zone KEY RR with a key present indicates that the zone named is
+ secure. The secured versus unsecured status of a zone may vary with
+ different cryptographic algorithms. Even for the same algorithm,
+ conflicting zone KEY RRs may be present.
+
+ Zone KEY RRs, like all RRs, are only trusted if they are
+ authenticated by a SIG RR whose signer field is a signer for which
+ the resolver has a public key they trust and where resolver policy
+ permits that signer to sign for the KEY owner name. Untrusted zone
+ KEY RRs MUST be ignored in determining the security status of the
+ zone. However, there can be multiple sets of trusted zone KEY RRs
+ for a zone with different algorithms, signers, etc.
+
+
+
+Eastlake Standards Track [Page 15]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ For any particular algorithm, zones can be (1) secure, indicating
+ that any retrieved RR must be authenticated by a SIG RR or it will be
+ discarded as bogus, (2) unsecured, indicating that SIG RRs are not
+ expected or required for RRs retrieved from the zone, or (3)
+ experimentally secure, which indicates that SIG RRs might or might
+ not be present but must be checked if found. The status of a zone is
+ determined as follows:
+
+ 1. If, for a zone and algorithm, every trusted zone KEY RR for the
+ zone says there is no key for that zone, it is unsecured for that
+ algorithm.
+
+ 2. If, there is at least one trusted no-key zone KEY RR and one
+ trusted key specifying zone KEY RR, then that zone is only
+ experimentally secure for the algorithm. Both authenticated and
+ non-authenticated RRs for it should be accepted by the resolver.
+
+ 3. If every trusted zone KEY RR that the zone and algorithm has is
+ key specifying, then it is secure for that algorithm and only
+ authenticated RRs from it will be accepted.
+
+ Examples:
+
+ (1) A resolver initially trusts only signatures by the superzone of
+ zone Z within the DNS hierarchy. Thus it will look only at the KEY
+ RRs that are signed by the superzone. If it finds only no-key KEY
+ RRs, it will assume the zone is not secure. If it finds only key
+ specifying KEY RRs, it will assume the zone is secure and reject any
+ unsigned responses. If it finds both, it will assume the zone is
+ experimentally secure
+
+ (2) A resolver trusts the superzone of zone Z (to which it got
+ securely from its local zone) and a third party, cert-auth.example.
+ When considering data from zone Z, it may be signed by the superzone
+ of Z, by cert-auth.example, by both, or by neither. The following
+ table indicates whether zone Z will be considered secure,
+ experimentally secure, or unsecured, depending on the signed zone KEY
+ RRs for Z;
+
+ c e r t - a u t h . e x a m p l e
+
+ KEY RRs| None | NoKeys | Mixed | Keys |
+ S --+-----------+-----------+----------+----------+
+ u None | illegal | unsecured | experim. | secure |
+ p --+-----------+-----------+----------+----------+
+ e NoKeys | unsecured | unsecured | experim. | secure |
+ r --+-----------+-----------+----------+----------+
+ Z Mixed | experim. | experim. | experim. | secure |
+
+
+
+Eastlake Standards Track [Page 16]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ o --+-----------+-----------+----------+----------+
+ n Keys | secure | secure | secure | secure |
+ e +-----------+-----------+----------+----------+
+
+3.5 KEY RRs in the Construction of Responses
+
+ An explicit request for KEY RRs does not cause any special additional
+ information processing except, of course, for the corresponding SIG
+ RR from a security aware server (see Section 4.2).
+
+ Security aware DNS servers include KEY RRs as additional information
+ in responses, where a KEY is available, in the following cases:
+
+ (1) On the retrieval of SOA or NS RRs, the KEY RRset with the same
+ name (perhaps just a zone key) SHOULD be included as additional
+ information if space is available. If not all additional information
+ will fit, type A and AAAA glue RRs have higher priority than KEY
+ RR(s).
+
+ (2) On retrieval of type A or AAAA RRs, the KEY RRset with the same
+ name (usually just a host RR and NOT the zone key (which usually
+ would have a different name)) SHOULD be included if space is
+ available. On inclusion of A or AAAA RRs as additional information,
+ the KEY RRset with the same name should also be included but with
+ lower priority than the A or AAAA RRs.
+
+4. The SIG Resource Record
+
+ The SIG or "signature" resource record (RR) is the fundamental way
+ that data is authenticated in the secure Domain Name System (DNS). As
+ such it is the heart of the security provided.
+
+ The SIG RR unforgably authenticates an RRset [RFC 2181] of a
+ particular type, class, and name and binds it to a time interval and
+ the signer's domain name. This is done using cryptographic
+ techniques and the signer's private key. The signer is frequently
+ the owner of the zone from which the RR originated.
+
+ The type number for the SIG RR type is 24.
+
+4.1 SIG RDATA Format
+
+ The RDATA portion of a SIG RR is as shown below. The integrity of
+ the RDATA information is protected by the signature field.
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 17]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | type covered | algorithm | labels |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | original TTL |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | signature expiration |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | signature inception |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | key tag | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ signer's name +
+ | /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-/
+ / /
+ / signature /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+4.1.1 Type Covered Field
+
+ The "type covered" is the type of the other RRs covered by this SIG.
+
+4.1.2 Algorithm Number Field
+
+ This octet is as described in section 3.2.
+
+4.1.3 Labels Field
+
+ The "labels" octet is an unsigned count of how many labels there are
+ in the original SIG RR owner name not counting the null label for
+ root and not counting any initial "*" for a wildcard. If a secured
+ retrieval is the result of wild card substitution, it is necessary
+ for the resolver to use the original form of the name in verifying
+ the digital signature. This field makes it easy to determine the
+ original form.
+
+ If, on retrieval, the RR appears to have a longer name than indicated
+ by "labels", the resolver can tell it is the result of wildcard
+ substitution. If the RR owner name appears to be shorter than the
+ labels count, the SIG RR must be considered corrupt and ignored. The
+ maximum number of labels allowed in the current DNS is 127 but the
+ entire octet is reserved and would be required should DNS names ever
+ be expanded to 255 labels. The following table gives some examples.
+ The value of "labels" is at the top, the retrieved owner name on the
+ left, and the table entry is the name to use in signature
+ verification except that "bad" means the RR is corrupt.
+
+
+
+Eastlake Standards Track [Page 18]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ labels= | 0 | 1 | 2 | 3 | 4 |
+ --------+-----+------+--------+----------+----------+
+ .| . | bad | bad | bad | bad |
+ d.| *. | d. | bad | bad | bad |
+ c.d.| *. | *.d. | c.d. | bad | bad |
+ b.c.d.| *. | *.d. | *.c.d. | b.c.d. | bad |
+ a.b.c.d.| *. | *.d. | *.c.d. | *.b.c.d. | a.b.c.d. |
+
+4.1.4 Original TTL Field
+
+ The "original TTL" field is included in the RDATA portion to avoid
+ (1) authentication problems that caching servers would otherwise
+ cause by decrementing the real TTL field and (2) security problems
+ that unscrupulous servers could otherwise cause by manipulating the
+ real TTL field. This original TTL is protected by the signature
+ while the current TTL field is not.
+
+ NOTE: The "original TTL" must be restored into the covered RRs when
+ the signature is verified (see Section 8). This generaly implies
+ that all RRs for a particular type, name, and class, that is, all the
+ RRs in any particular RRset, must have the same TTL to start with.
+
+4.1.5 Signature Expiration and Inception Fields
+
+ The SIG is valid from the "signature inception" time until the
+ "signature expiration" time. Both are unsigned numbers of seconds
+ since the start of 1 January 1970, GMT, ignoring leap seconds. (See
+ also Section 4.4.) Ring arithmetic is used as for DNS SOA serial
+ numbers [RFC 1982] which means that these times can never be more
+ than about 68 years in the past or the future. This means that these
+ times are ambiguous modulo ~136.09 years. However there is no
+ security flaw because keys are required to be changed to new random
+ keys by [RFC 2541] at least every five years. This means that the
+ probability that the same key is in use N*136.09 years later should
+ be the same as the probability that a random guess will work.
+
+ A SIG RR may have an expiration time numerically less than the
+ inception time if the expiration time is near the 32 bit wrap around
+ point and/or the signature is long lived.
+
+ (To prevent misordering of network requests to update a zone
+ dynamically, monotonically increasing "signature inception" times may
+ be necessary.)
+
+ A secure zone must be considered changed for SOA serial number
+ purposes not only when its data is updated but also when new SIG RRs
+ are inserted (ie, the zone or any part of it is re-signed).
+
+
+
+
+Eastlake Standards Track [Page 19]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+4.1.6 Key Tag Field
+
+ The "key Tag" is a two octet quantity that is used to efficiently
+ select between multiple keys which may be applicable and thus check
+ that a public key about to be used for the computationally expensive
+ effort to check the signature is possibly valid. For algorithm 1
+ (MD5/RSA) as defined in [RFC 2537], it is the next to the bottom two
+ octets of the public key modulus needed to decode the signature
+ field. That is to say, the most significant 16 of the least
+ significant 24 bits of the modulus in network (big endian) order. For
+ all other algorithms, including private algorithms, it is calculated
+ as a simple checksum of the KEY RR as described in Appendix C.
+
+4.1.7 Signer's Name Field
+
+ The "signer's name" field is the domain name of the signer generating
+ the SIG RR. This is the owner name of the public KEY RR that can be
+ used to verify the signature. It is frequently the zone which
+ contained the RRset being authenticated. Which signers should be
+ authorized to sign what is a significant resolver policy question as
+ discussed in Section 6. The signer's name may be compressed with
+ standard DNS name compression when being transmitted over the
+ network.
+
+4.1.8 Signature Field
+
+ The actual signature portion of the SIG RR binds the other RDATA
+ fields to the RRset of the "type covered" RRs with that owner name
+ and class. This covered RRset is thereby authenticated. To
+ accomplish this, a data sequence is constructed as follows:
+
+ data = RDATA | RR(s)...
+
+ where "|" is concatenation,
+
+ RDATA is the wire format of all the RDATA fields in the SIG RR itself
+ (including the canonical form of the signer's name) before but not
+ including the signature, and
+
+ RR(s) is the RRset of the RR(s) of the type covered with the same
+ owner name and class as the SIG RR in canonical form and order as
+ defined in Section 8.
+
+ How this data sequence is processed into the signature is algorithm
+ dependent. These algorithm dependent formats and procedures are
+ described in separate documents (Section 3.2).
+
+
+
+
+
+Eastlake Standards Track [Page 20]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ SIGs SHOULD NOT be included in a zone for any "meta-type" such as
+ ANY, AXFR, etc. (but see section 5.6.2 with regard to IXFR).
+
+4.1.8.1 Calculating Transaction and Request SIGs
+
+ A response message from a security aware server may optionally
+ contain a special SIG at the end of the additional information
+ section to authenticate the transaction.
+
+ This SIG has a "type covered" field of zero, which is not a valid RR
+ type. It is calculated by using a "data" (see Section 4.1.8) of the
+ entire preceding DNS reply message, including DNS header but not the
+ IP header and before the reply RR counts have been adjusted for the
+ inclusion of any transaction SIG, concatenated with the entire DNS
+ query message that produced this response, including the query's DNS
+ header and any request SIGs but not its IP header. That is
+
+ data = full response (less transaction SIG) | full query
+
+ Verification of the transaction SIG (which is signed by the server
+ host key, not the zone key) by the requesting resolver shows that the
+ query and response were not tampered with in transit, that the
+ response corresponds to the intended query, and that the response
+ comes from the queried server.
+
+ A DNS request may be optionally signed by including one or more SIGs
+ at the end of the query. Such SIGs are identified by having a "type
+ covered" field of zero. They sign the preceding DNS request message
+ including DNS header but not including the IP header or any request
+ SIGs at the end and before the request RR counts have been adjusted
+ for the inclusions of any request SIG(s).
+
+ WARNING: Request SIGs are unnecessary for any currently defined
+ request other than update [RFC 2136, 2137] and will cause some old
+ DNS servers to give an error return or ignore a query. However, such
+ SIGs may in the future be needed for other requests.
+
+ Except where needed to authenticate an update or similar privileged
+ request, servers are not required to check request SIGs.
+
+4.2 SIG RRs in the Construction of Responses
+
+ Security aware DNS servers SHOULD, for every authenticated RRset the
+ query will return, attempt to send the available SIG RRs which
+ authenticate the requested RRset. The following rules apply to the
+ inclusion of SIG RRs in responses:
+
+
+
+
+
+Eastlake Standards Track [Page 21]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ 1. when an RRset is placed in a response, its SIG RR has a higher
+ priority for inclusion than additional RRs that may need to be
+ included. If space does not permit its inclusion, the response
+ MUST be considered truncated except as provided in 2 below.
+
+ 2. When a SIG RR is present in the zone for an additional
+ information section RR, the response MUST NOT be considered
+ truncated merely because space does not permit the inclusion of
+ the SIG RR with the additional information.
+
+ 3. SIGs to authenticate glue records and NS RRs for subzones at a
+ delegation point are unnecessary and MUST NOT be sent.
+
+ 4. If a SIG covers any RR that would be in the answer section of
+ the response, its automatic inclusion MUST be in the answer
+ section. If it covers an RR that would appear in the authority
+ section, its automatic inclusion MUST be in the authority
+ section. If it covers an RR that would appear in the additional
+ information section it MUST appear in the additional information
+ section. This is a change in the existing standard [RFCs 1034,
+ 1035] which contemplates only NS and SOA RRs in the authority
+ section.
+
+ 5. Optionally, DNS transactions may be authenticated by a SIG RR at
+ the end of the response in the additional information section
+ (Section 4.1.8.1). Such SIG RRs are signed by the DNS server
+ originating the response. Although the signer field MUST be a
+ name of the originating server host, the owner name, class, TTL,
+ and original TTL, are meaningless. The class and TTL fields
+ SHOULD be zero. To conserve space, the owner name SHOULD be
+ root (a single zero octet). If transaction authentication is
+ desired, that SIG RR must be considered the highest priority for
+ inclusion.
+
+4.3 Processing Responses and SIG RRs
+
+ The following rules apply to the processing of SIG RRs included in a
+ response:
+
+ 1. A security aware resolver that receives a response from a
+ security aware server via a secure communication with the AD bit
+ (see Section 6.1) set, MAY choose to accept the RRs as received
+ without verifying the zone SIG RRs.
+
+ 2. In other cases, a security aware resolver SHOULD verify the SIG
+ RRs for the RRs of interest. This may involve initiating
+ additional queries for SIG or KEY RRs, especially in the case of
+
+
+
+
+Eastlake Standards Track [Page 22]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ getting a response from a server that does not implement
+ security. (As explained in 2.3.5 above, it will not be possible
+ to secure CNAMEs being served up by non-secure resolvers.)
+
+ NOTE: Implementers might expect the above SHOULD to be a MUST.
+ However, local policy or the calling application may not require
+ the security services.
+
+ 3. If SIG RRs are received in response to a user query explicitly
+ specifying the SIG type, no special processing is required.
+
+ If the message does not pass integrity checks or the SIG does not
+ check against the signed RRs, the SIG RR is invalid and should be
+ ignored. If all of the SIG RR(s) purporting to authenticate an RRset
+ are invalid, then the RRset is not authenticated.
+
+ If the SIG RR is the last RR in a response in the additional
+ information section and has a type covered of zero, it is a
+ transaction signature of the response and the query that produced the
+ response. It MAY be optionally checked and the message rejected if
+ the checks fail. But even if the checks succeed, such a transaction
+ authentication SIG does NOT directly authenticate any RRs in the
+ message. Only a proper SIG RR signed by the zone or a key tracing
+ its authority to the zone or to static resolver configuration can
+ directly authenticate RRs, depending on resolver policy (see Section
+ 6). If a resolver does not implement transaction and/or request
+ SIGs, it MUST ignore them without error.
+
+ If all checks indicate that the SIG RR is valid then RRs verified by
+ it should be considered authenticated.
+
+4.4 Signature Lifetime, Expiration, TTLs, and Validity
+
+ Security aware servers MUST NOT consider SIG RRs to authenticate
+ anything before their signature inception or after its expiration
+ time (see also Section 6). Security aware servers MUST NOT consider
+ any RR to be authenticated after all its signatures have expired.
+ When a secure server caches authenticated data, if the TTL would
+ expire at a time further in the future than the authentication
+ expiration time, the server SHOULD trim the TTL in the cache entry
+ not to extent beyond the authentication expiration time. Within
+ these constraints, servers should continue to follow DNS TTL aging.
+ Thus authoritative servers should continue to follow the zone refresh
+ and expire parameters and a non-authoritative server should count
+ down the TTL and discard RRs when the TTL is zero (even for a SIG
+ that has not yet reached its authentication expiration time). In
+ addition, when RRs are transmitted in a query response, the TTL
+
+
+
+
+Eastlake Standards Track [Page 23]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ should be trimmed so that current time plus the TTL does not extend
+ beyond the authentication expiration time. Thus, in general, the TTL
+ on a transmitted RR would be
+
+ min(authExpTim,max(zoneMinTTL,min(originalTTL,currentTTL)))
+
+ When signatures are generated, signature expiration times should be
+ set far enough in the future that it is quite certain that new
+ signatures can be generated before the old ones expire. However,
+ setting expiration too far into the future could mean a long time to
+ flush any bad data or signatures that may have been generated.
+
+ It is recommended that signature lifetime be a small multiple of the
+ TTL (ie, 4 to 16 times the TTL) but not less than a reasonable
+ maximum re-signing interval and not less than the zone expiry time.
+
+5. Non-existent Names and Types
+
+ The SIG RR mechanism described in Section 4 above provides strong
+ authentication of RRs that exist in a zone. But it is not clear
+ above how to verifiably deny the existence of a name in a zone or a
+ type for an existent name.
+
+ The nonexistence of a name in a zone is indicated by the NXT ("next")
+ RR for a name interval containing the nonexistent name. An NXT RR or
+ RRs and its or their SIG(s) are returned in the authority section,
+ along with the error, if the server is security aware. The same is
+ true for a non-existent type under an existing name except that there
+ is no error indication other than an empty answer section
+ accompanying the NXT(s). This is a change in the existing standard
+ [RFCs 1034/1035] which contemplates only NS and SOA RRs in the
+ authority section. NXT RRs will also be returned if an explicit query
+ is made for the NXT type.
+
+ The existence of a complete set of NXT records in a zone means that
+ any query for any name and any type to a security aware server
+ serving the zone will result in an reply containing at least one
+ signed RR unless it is a query for delegation point NS or glue A or
+ AAAA RRs.
+
+5.1 The NXT Resource Record
+
+ The NXT resource record is used to securely indicate that RRs with an
+ owner name in a certain name interval do not exist in a zone and to
+ indicate what RR types are present for an existing name.
+
+
+
+
+
+
+Eastlake Standards Track [Page 24]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ The owner name of the NXT RR is an existing name in the zone. It's
+ RDATA is a "next" name and a type bit map. Thus the NXT RRs in a zone
+ create a chain of all of the literal owner names in that zone,
+ including unexpanded wildcards but omitting the owner name of glue
+ address records unless they would otherwise be included. This implies
+ a canonical ordering of all domain names in a zone as described in
+ Section 8. The presence of the NXT RR means that no name between its
+ owner name and the name in its RDATA area exists and that no other
+ types exist under its owner name.
+
+ There is a potential problem with the last NXT in a zone as it wants
+ to have an owner name which is the last existing name in canonical
+ order, which is easy, but it is not obvious what name to put in its
+ RDATA to indicate the entire remainder of the name space. This is
+ handled by treating the name space as circular and putting the zone
+ name in the RDATA of the last NXT in a zone.
+
+ The NXT RRs for a zone SHOULD be automatically calculated and added
+ to the zone when SIGs are added. The NXT RR's TTL SHOULD NOT exceed
+ the zone minimum TTL.
+
+ The type number for the NXT RR is 30.
+
+ NXT RRs are only signed by zone level keys.
+
+5.2 NXT RDATA Format
+
+ The RDATA for an NXT RR consists simply of a domain name followed by
+ a bit map, as shown below.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | next domain name /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | type bit map /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The NXT RR type bit map format currently defined is one bit per RR
+ type present for the owner name. A one bit indicates that at least
+ one RR of that type is present for the owner name. A zero indicates
+ that no such RR is present. All bits not specified because they are
+ beyond the end of the bit map are assumed to be zero. Note that bit
+ 30, for NXT, will always be on so the minimum bit map length is
+ actually four octets. Trailing zero octets are prohibited in this
+ format. The first bit represents RR type zero (an illegal type which
+ can not be present) and so will be zero in this format. This format
+ is not used if there exists an RR with a type number greater than
+
+
+
+Eastlake Standards Track [Page 25]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ 127. If the zero bit of the type bit map is a one, it indicates that
+ a different format is being used which will always be the case if a
+ type number greater than 127 is present.
+
+ The domain name may be compressed with standard DNS name compression
+ when being transmitted over the network. The size of the bit map can
+ be inferred from the RDLENGTH and the length of the next domain name.
+
+5.3 Additional Complexity Due to Wildcards
+
+ Proving that a non-existent name response is correct or that a
+ wildcard expansion response is correct makes things a little more
+ complex.
+
+ In particular, when a non-existent name response is returned, an NXT
+ must be returned showing that the exact name queried did not exist
+ and, in general, one or more additional NXT's need to be returned to
+ also prove that there wasn't a wildcard whose expansion should have
+ been returned. (There is no need to return multiple copies of the
+ same NXT.) These NXTs, if any, are returned in the authority section
+ of the response.
+
+ Furthermore, if a wildcard expansion is returned in a response, in
+ general one or more NXTs needs to also be returned in the authority
+ section to prove that no more specific name (including possibly more
+ specific wildcards in the zone) existed on which the response should
+ have been based.
+
+5.4 Example
+
+ Assume zone foo.nil has entries for
+
+ big.foo.nil,
+ medium.foo.nil.
+ small.foo.nil.
+ tiny.foo.nil.
+
+ Then a query to a security aware server for huge.foo.nil would
+ produce an error reply with an RCODE of NXDOMAIN and the authority
+ section data including something like the following:
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 26]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ foo.nil. NXT big.foo.nil NS KEY SOA NXT ;prove no *.foo.nil
+ foo.nil. SIG NXT 1 2 ( ;type-cov=NXT, alg=1, labels=2
+ 19970102030405 ;signature expiration
+ 19961211100908 ;signature inception
+ 2143 ;key identifier
+ foo.nil. ;signer
+ AIYADP8d3zYNyQwW2EM4wXVFdslEJcUx/fxkfBeH1El4ixPFhpfHFElxbvKoWmvjDTCm
+ fiYy2X+8XpFjwICHc398kzWsTMKlxovpz2FnCTM= ;signature (640 bits)
+ )
+ big.foo.nil. NXT medium.foo.nil. A MX SIG NXT ;prove no huge.foo.nil
+ big.foo.nil. SIG NXT 1 3 ( ;type-cov=NXT, alg=1, labels=3
+ 19970102030405 ;signature expiration
+ 19961211100908 ;signature inception
+ 2143 ;key identifier
+ foo.nil. ;signer
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgiWCn/GxHhai6VAuHAoNUz4YoU
+ 1tVfSCSqQYn6//11U6Nld80jEeC8aTrO+KKmCaY= ;signature (640 bits)
+ )
+ Note that this response implies that big.foo.nil is an existing name
+ in the zone and thus has other RR types associated with it than NXT.
+ However, only the NXT (and its SIG) RR appear in the response to this
+ query for huge.foo.nil, which is a non-existent name.
+
+5.5 Special Considerations at Delegation Points
+
+ A name (other than root) which is the head of a zone also appears as
+ the leaf in a superzone. If both are secure, there will always be
+ two different NXT RRs with the same name. They can be easily
+ distinguished by their signers, the next domain name fields, the
+ presence of the SOA type bit, etc. Security aware servers should
+ return the correct NXT automatically when required to authenticate
+ the non-existence of a name and both NXTs, if available, on explicit
+ query for type NXT.
+
+ Non-security aware servers will never automatically return an NXT and
+ some old implementations may only return the NXT from the subzone on
+ explicit queries.
+
+5.6 Zone Transfers
+
+ The subsections below describe how full and incremental zone
+ transfers are secured.
+
+ SIG RRs secure all authoritative RRs transferred for both full and
+ incremental [RFC 1995] zone transfers. NXT RRs are an essential
+ element in secure zone transfers and assure that every authoritative
+ name and type will be present; however, if there are multiple SIGs
+ with the same name and type covered, a subset of the SIGs could be
+
+
+
+Eastlake Standards Track [Page 27]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ sent as long as at least one is present and, in the case of unsigned
+ delegation point NS or glue A or AAAA RRs a subset of these RRs or
+ simply a modified set could be sent as long as at least one of each
+ type is included.
+
+ When an incremental or full zone transfer request is received with
+ the same or newer version number than that of the server's copy of
+ the zone, it is replied to with just the SOA RR of the server's
+ current version and the SIG RRset verifying that SOA RR.
+
+ The complete NXT chains specified in this document enable a resolver
+ to obtain, by successive queries chaining through NXTs, all of the
+ names in a zone even if zone transfers are prohibited. Different
+ format NXTs may be specified in the future to avoid this.
+
+5.6.1 Full Zone Transfers
+
+ To provide server authentication that a complete transfer has
+ occurred, transaction authentication SHOULD be used on full zone
+ transfers. This provides strong server based protection for the
+ entire zone in transit.
+
+5.6.2 Incremental Zone Transfers
+
+ Individual RRs in an incremental (IXFR) transfer [RFC 1995] can be
+ verified in the same way as for a full zone transfer and the
+ integrity of the NXT name chain and correctness of the NXT type bits
+ for the zone after the incremental RR deletes and adds can check each
+ disjoint area of the zone updated. But the completeness of an
+ incremental transfer can not be confirmed because usually neither the
+ deleted RR section nor the added RR section has a compete zone NXT
+ chain. As a result, a server which securely supports IXFR must
+ handle IXFR SIG RRs for each incremental transfer set that it
+ maintains.
+
+ The IXFR SIG is calculated over the incremental zone update
+ collection of RRs in the order in which it is transmitted: old SOA,
+ then deleted RRs, then new SOA and added RRs. Within each section,
+ RRs must be ordered as specified in Section 8. If condensation of
+ adjacent incremental update sets is done by the zone owner, the
+ original IXFR SIG for each set included in the condensation must be
+ discarded and a new on IXFR SIG calculated to cover the resulting
+ condensed set.
+
+ The IXFR SIG really belongs to the zone as a whole, not to the zone
+ name. Although it SHOULD be correct for the zone name, the labels
+ field of an IXFR SIG is otherwise meaningless. The IXFR SIG is only
+ sent as part of an incremental zone transfer. After validation of
+
+
+
+Eastlake Standards Track [Page 28]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ the IXFR SIG, the transferred RRs MAY be considered valid without
+ verification of the internal SIGs if such trust in the server
+ conforms to local policy.
+
+6. How to Resolve Securely and the AD and CD Bits
+
+ Retrieving or resolving secure data from the Domain Name System (DNS)
+ involves starting with one or more trusted public keys that have been
+ staticly configured at the resolver. With starting trusted keys, a
+ resolver willing to perform cryptography can progress securely
+ through the secure DNS structure to the zone of interest as described
+ in Section 6.3. Such trusted public keys would normally be configured
+ in a manner similar to that described in Section 6.2. However, as a
+ practical matter, a security aware resolver would still gain some
+ confidence in the results it returns even if it was not configured
+ with any keys but trusted what it got from a local well known server
+ as if it were staticly configured.
+
+ Data stored at a security aware server needs to be internally
+ categorized as Authenticated, Pending, or Insecure. There is also a
+ fourth transient state of Bad which indicates that all SIG checks
+ have explicitly failed on the data. Such Bad data is not retained at
+ a security aware server. Authenticated means that the data has a
+ valid SIG under a KEY traceable via a chain of zero or more SIG and
+ KEY RRs allowed by the resolvers policies to a KEY staticly
+ configured at the resolver. Pending data has no authenticated SIGs
+ and at least one additional SIG the resolver is still trying to
+ authenticate. Insecure data is data which it is known can never be
+ either Authenticated or found Bad in the zone where it was found
+ because it is in or has been reached via a unsecured zone or because
+ it is unsigned glue address or delegation point NS data. Behavior in
+ terms of control of and flagging based on such data labels is
+ described in Section 6.1.
+
+ The proper validation of signatures requires a reasonably secure
+ shared opinion of the absolute time between resolvers and servers as
+ described in Section 6.4.
+
+6.1 The AD and CD Header Bits
+
+ Two previously unused bits are allocated out of the DNS
+ query/response format header. The AD (authentic data) bit indicates
+ in a response that all the data included in the answer and authority
+ portion of the response has been authenticated by the server
+ according to the policies of that server. The CD (checking disabled)
+ bit indicates in a query that Pending (non-authenticated) data is
+ acceptable to the resolver sending the query.
+
+
+
+
+Eastlake Standards Track [Page 29]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ These bits are allocated from the previously must-be-zero Z field as
+ follows:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ID |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QDCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ANCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | NSCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ARCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ These bits are zero in old servers and resolvers. Thus the responses
+ of old servers are not flagged as authenticated to security aware
+ resolvers and queries from non-security aware resolvers do not assert
+ the checking disabled bit and thus will be answered by security aware
+ servers only with Authenticated or Insecure data. Security aware
+ resolvers MUST NOT trust the AD bit unless they trust the server they
+ are talking to and either have a secure path to it or use DNS
+ transaction security.
+
+ Any security aware resolver willing to do cryptography SHOULD assert
+ the CD bit on all queries to permit it to impose its own policies and
+ to reduce DNS latency time by allowing security aware servers to
+ answer with Pending data.
+
+ Security aware servers MUST NOT return Bad data. For non-security
+ aware resolvers or security aware resolvers requesting service by
+ having the CD bit clear, security aware servers MUST return only
+ Authenticated or Insecure data in the answer and authority sections
+ with the AD bit set in the response. Security aware servers SHOULD
+ return Pending data, with the AD bit clear in the response, to
+ security aware resolvers requesting this service by asserting the CD
+ bit in their request. The AD bit MUST NOT be set on a response
+ unless all of the RRs in the answer and authority sections of the
+ response are either Authenticated or Insecure. The AD bit does not
+ cover the additional information section.
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 30]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+6.2 Staticly Configured Keys
+
+ The public key to authenticate a zone SHOULD be defined in local
+ configuration files before that zone is loaded at the primary server
+ so the zone can be authenticated.
+
+ While it might seem logical for everyone to start with a public key
+ associated with the root zone and staticly configure this in every
+ resolver, this has problems. The logistics of updating every DNS
+ resolver in the world should this key ever change would be severe.
+ Furthermore, many organizations will explicitly wish their "interior"
+ DNS implementations to completely trust only their own DNS servers.
+ Interior resolvers of such organizations can then go through the
+ organization's zone servers to access data outside the organization's
+ domain and need not be configured with keys above the organization's
+ DNS apex.
+
+ Host resolvers that are not part of a larger organization may be
+ configured with a key for the domain of their local ISP whose
+ recursive secure DNS caching server they use.
+
+6.3 Chaining Through The DNS
+
+ Starting with one or more trusted keys for any zone, it should be
+ possible to retrieve signed keys for that zone's subzones which have
+ a key. A secure sub-zone is indicated by a KEY RR with non-null key
+ information appearing with the NS RRs in the sub-zone and which may
+ also be present in the parent. These make it possible to descend
+ within the tree of zones.
+
+6.3.1 Chaining Through KEYs
+
+ In general, some RRset that you wish to validate in the secure DNS
+ will be signed by one or more SIG RRs. Each of these SIG RRs has a
+ signer under whose name is stored the public KEY to use in
+ authenticating the SIG. Each of those KEYs will, generally, also be
+ signed with a SIG. And those SIGs will have signer names also
+ referring to KEYs. And so on. As a result, authentication leads to
+ chains of alternating SIG and KEY RRs with the first SIG signing the
+ original data whose authenticity is to be shown and the final KEY
+ being some trusted key staticly configured at the resolver performing
+ the authentication.
+
+ In testing such a chain, the validity periods of the SIGs encountered
+ must be intersected to determine the validity period of the
+ authentication of the data, a purely algorithmic process. In
+ addition, the validation of each SIG over the data with reference to
+ a KEY must meet the objective cryptographic test implied by the
+
+
+
+Eastlake Standards Track [Page 31]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ cryptographic algorithm used (although even here the resolver may
+ have policies as to trusted algorithms and key lengths). Finally,
+ the judgement that a SIG with a particular signer name can
+ authenticate data (possibly a KEY RRset) with a particular owner
+ name, is primarily a policy question. Ultimately, this is a policy
+ local to the resolver and any clients that depend on that resolver's
+ decisions. It is, however, recommended, that the policy below be
+ adopted:
+
+ Let A < B mean that A is a shorter domain name than B formed by
+ dropping one or more whole labels from the left end of B, i.e.,
+ A is a direct or indirect superdomain of B. Let A = B mean that
+ A and B are the same domain name (i.e., are identical after
+ letter case canonicalization). Let A > B mean that A is a
+ longer domain name than B formed by adding one or more whole
+ labels on the left end of B, i.e., A is a direct or indirect
+ subdomain of B
+
+ Let Static be the owner names of the set of staticly configured
+ trusted keys at a resolver.
+
+ Then Signer is a valid signer name for a SIG authenticating an
+ RRset (possibly a KEY RRset) with owner name Owner at the
+ resolver if any of the following three rules apply:
+
+ (1) Owner > or = Signer (except that if Signer is root, Owner
+ must be root or a top level domain name). That is, Owner is the
+ same as or a subdomain of Signer.
+
+ (2) ( Owner < Signer ) and ( Signer > or = some Static ). That
+ is, Owner is a superdomain of Signer and Signer is staticly
+ configured or a subdomain of a staticly configured key.
+
+ (3) Signer = some Static. That is, the signer is exactly some
+ staticly configured key.
+
+ Rule 1 is the rule for descending the DNS tree and includes a special
+ prohibition on the root zone key due to the restriction that the root
+ zone be only one label deep. This is the most fundamental rule.
+
+ Rule 2 is the rule for ascending the DNS tree from one or more
+ staticly configured keys. Rule 2 has no effect if only root zone
+ keys are staticly configured.
+
+ Rule 3 is a rule permitting direct cross certification. Rule 3 has
+ no effect if only root zone keys are staticly configured.
+
+
+
+
+
+Eastlake Standards Track [Page 32]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ Great care should be taken that the consequences have been fully
+ considered before making any local policy adjustments to these rules
+ (other than dispensing with rules 2 and 3 if only root zone keys are
+ staticly configured).
+
+6.3.2 Conflicting Data
+
+ It is possible that there will be multiple SIG-KEY chains that appear
+ to authenticate conflicting RRset answers to the same query. A
+ resolver should choose only the most reliable answer to return and
+ discard other data. This choice of most reliable is a matter of
+ local policy which could take into account differing trust in
+ algorithms, key sizes, staticly configured keys, zones traversed,
+ etc. The technique given below is recommended for taking into
+ account SIG-KEY chain length.
+
+ A resolver should keep track of the number of successive secure zones
+ traversed from a staticly configured key starting point to any secure
+ zone it can reach. In general, the lower such a distance number is,
+ the greater the confidence in the data. Staticly configured data
+ should be given a distance number of zero. If a query encounters
+ different Authenticated data for the same query with different
+ distance values, that with a larger value should be ignored unless
+ some other local policy covers the case.
+
+ A security conscious resolver should completely refuse to step from a
+ secure zone into a unsecured zone unless the unsecured zone is
+ certified to be non-secure by the presence of an authenticated KEY RR
+ for the unsecured zone with the no-key type value. Otherwise the
+ resolver is getting bogus or spoofed data.
+
+ If legitimate unsecured zones are encountered in traversing the DNS
+ tree, then no zone can be trusted as secure that can be reached only
+ via information from such non-secure zones. Since the unsecured zone
+ data could have been spoofed, the "secure" zone reached via it could
+ be counterfeit. The "distance" to data in such zones or zones
+ reached via such zones could be set to 256 or more as this exceeds
+ the largest possible distance through secure zones in the DNS.
+
+6.4 Secure Time
+
+ Coordinated interpretation of the time fields in SIG RRs requires
+ that reasonably consistent time be available to the hosts
+ implementing the DNS security extensions.
+
+ A variety of time synchronization protocols exist including the
+ Network Time Protocol (NTP [RFC 1305, 2030]). If such protocols are
+ used, they MUST be used securely so that time can not be spoofed.
+
+
+
+Eastlake Standards Track [Page 33]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ Otherwise, for example, a host could get its clock turned back and
+ might then believe old SIG RRs, and the data they authenticate, which
+ were valid but are no longer.
+
+7. ASCII Representation of Security RRs
+
+ This section discusses the format for master file and other ASCII
+ presentation of the three DNS security resource records.
+
+ The algorithm field in KEY and SIG RRs can be represented as either
+ an unsigned integer or symbolicly. The following initial symbols are
+ defined as indicated:
+
+ Value Symbol
+
+ 001 RSAMD5
+ 002 DH
+ 003 DSA
+ 004 ECC
+ 252 INDIRECT
+ 253 PRIVATEDNS
+ 254 PRIVATEOID
+
+7.1 Presentation of KEY RRs
+
+ KEY RRs may appear as single logical lines in a zone data master file
+ [RFC 1033].
+
+ The flag field is represented as an unsigned integer or a sequence of
+ mnemonics as follows separated by instances of the verticle bar ("|")
+ character:
+
+ BIT Mnemonic Explanation
+ 0-1 key type
+ NOCONF =1 confidentiality use prohibited
+ NOAUTH =2 authentication use prohibited
+ NOKEY =3 no key present
+ 2 FLAG2 - reserved
+ 3 EXTEND flags extension
+ 4 FLAG4 - reserved
+ 5 FLAG5 - reserved
+ 6-7 name type
+ USER =0 (default, may be omitted)
+ ZONE =1
+ HOST =2 (host or other end entity)
+ NTYP3 - reserved
+ 8 FLAG8 - reserved
+ 9 FLAG9 - reserved
+
+
+
+Eastlake Standards Track [Page 34]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ 10 FLAG10 - reserved
+ 11 FLAG11 - reserved
+ 12-15 signatory field, values 0 to 15
+ can be represented by SIG0, SIG1, ... SIG15
+
+ No flag mnemonic need be present if the bit or field it represents is
+ zero.
+
+ The protocol octet can be represented as either an unsigned integer
+ or symbolicly. The following initial symbols are defined:
+
+ 000 NONE
+ 001 TLS
+ 002 EMAIL
+ 003 DNSSEC
+ 004 IPSEC
+ 255 ALL
+
+ Note that if the type flags field has the NOKEY value, nothing
+ appears after the algorithm octet.
+
+ The remaining public key portion is represented in base 64 (see
+ Appendix A) and may be divided up into any number of white space
+ separated substrings, down to single base 64 digits, which are
+ concatenated to obtain the full signature. These substrings can span
+ lines using the standard parenthesis.
+
+ Note that the public key may have internal sub-fields but these do
+ not appear in the master file representation. For example, with
+ algorithm 1 there is a public exponent size, then a public exponent,
+ and then a modulus. With algorithm 254, there will be an OID size,
+ an OID, and algorithm dependent information. But in both cases only a
+ single logical base 64 string will appear in the master file.
+
+7.2 Presentation of SIG RRs
+
+ A data SIG RR may be represented as a single logical line in a zone
+ data file [RFC 1033] but there are some special considerations as
+ described below. (It does not make sense to include a transaction or
+ request authenticating SIG RR in a file as they are a transient
+ authentication that covers data including an ephemeral transaction
+ number and so must be calculated in real time.)
+
+ There is no particular problem with the signer, covered type, and
+ times. The time fields appears in the form YYYYMMDDHHMMSS where YYYY
+ is the year, the first MM is the month number (01-12), DD is the day
+ of the month (01-31), HH is the hour in 24 hours notation (00-23),
+ the second MM is the minute (00-59), and SS is the second (00-59).
+
+
+
+Eastlake Standards Track [Page 35]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ The original TTL field appears as an unsigned integer.
+
+ If the original TTL, which applies to the type signed, is the same as
+ the TTL of the SIG RR itself, it may be omitted. The date field
+ which follows it is larger than the maximum possible TTL so there is
+ no ambiguity.
+
+ The "labels" field appears as an unsigned integer.
+
+ The key tag appears as an unsigned number.
+
+ However, the signature itself can be very long. It is the last data
+ field and is represented in base 64 (see Appendix A) and may be
+ divided up into any number of white space separated substrings, down
+ to single base 64 digits, which are concatenated to obtain the full
+ signature. These substrings can be split between lines using the
+ standard parenthesis.
+
+7.3 Presentation of NXT RRs
+
+ NXT RRs do not appear in original unsigned zone master files since
+ they should be derived from the zone as it is being signed. If a
+ signed file with NXTs added is printed or NXTs are printed by
+ debugging code, they appear as the next domain name followed by the
+ RR type present bits as an unsigned interger or sequence of RR
+ mnemonics.
+
+8. Canonical Form and Order of Resource Records
+
+ This section specifies, for purposes of domain name system (DNS)
+ security, the canonical form of resource records (RRs), their name
+ order, and their overall order. A canonical name order is necessary
+ to construct the NXT name chain. A canonical form and ordering
+ within an RRset is necessary in consistently constructing and
+ verifying SIG RRs. A canonical ordering of types within a name is
+ required in connection with incremental transfer (Section 5.6.2).
+
+8.1 Canonical RR Form
+
+ For purposes of DNS security, the canonical form for an RR is the
+ wire format of the RR with domain names (1) fully expanded (no name
+ compression via pointers), (2) all domain name letters set to lower
+ case, (3) owner name wild cards in master file form (no substitution
+ made for *), and (4) the original TTL substituted for the current
+ TTL.
+
+
+
+
+
+
+Eastlake Standards Track [Page 36]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+8.2 Canonical DNS Name Order
+
+ For purposes of DNS security, the canonical ordering of owner names
+ is to sort individual labels as unsigned left justified octet strings
+ where the absence of a octet sorts before a zero value octet and
+ upper case letters are treated as lower case letters. Names in a
+ zone are sorted by sorting on the highest level label and then,
+ within those names with the same highest level label by the next
+ lower label, etc. down to leaf node labels. Within a zone, the zone
+ name itself always exists and all other names are the zone name with
+ some prefix of lower level labels. Thus the zone name itself always
+ sorts first.
+
+ Example:
+ foo.example
+ a.foo.example
+ yljkjljk.a.foo.example
+ Z.a.foo.example
+ zABC.a.FOO.EXAMPLE
+ z.foo.example
+ *.z.foo.example
+ \200.z.foo.example
+
+8.3 Canonical RR Ordering Within An RRset
+
+ Within any particular owner name and type, RRs are sorted by RDATA as
+ a left justified unsigned octet sequence where the absence of an
+ octet sorts before the zero octet.
+
+8.4 Canonical Ordering of RR Types
+
+ When RRs of the same name but different types must be ordered, they
+ are ordered by type, considering the type to be an unsigned integer,
+ except that SIG RRs are placed immediately after the type they cover.
+ Thus, for example, an A record would be put before an MX record
+ because A is type 1 and MX is type 15 but if both were signed, the
+ order would be A < SIG(A) < MX < SIG(MX).
+
+9. Conformance
+
+ Levels of server and resolver conformance are defined below.
+
+9.1 Server Conformance
+
+ Two levels of server conformance for DNS security are defined as
+ follows:
+
+
+
+
+
+Eastlake Standards Track [Page 37]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ BASIC: Basic server compliance is the ability to store and retrieve
+ (including zone transfer) SIG, KEY, and NXT RRs. Any secondary or
+ caching server for a secure zone MUST have at least basic compliance
+ and even then some things, such as secure CNAMEs, will not work
+ without full compliance.
+
+ FULL: Full server compliance adds the following to basic compliance:
+ (1) ability to read SIG, KEY, and NXT RRs in zone files and (2)
+ ability, given a zone file and private key, to add appropriate SIG
+ and NXT RRs, possibly via a separate application, (3) proper
+ automatic inclusion of SIG, KEY, and NXT RRs in responses, (4)
+ suppression of CNAME following on retrieval of the security type RRs,
+ (5) recognize the CD query header bit and set the AD query header
+ bit, as appropriate, and (6) proper handling of the two NXT RRs at
+ delegation points. Primary servers for secure zones MUST be fully
+ compliant and for complete secure operation, all secondary, caching,
+ and other servers handling the zone SHOULD be fully compliant as
+ well.
+
+9.2 Resolver Conformance
+
+ Two levels of resolver compliance (including the resolver portion of
+ a server) are defined for DNS Security:
+
+ BASIC: A basic compliance resolver can handle SIG, KEY, and NXT RRs
+ when they are explicitly requested.
+
+ FULL: A fully compliant resolver (1) understands KEY, SIG, and NXT
+ RRs including verification of SIGs at least for the mandatory
+ algorithm, (2) maintains appropriate information in its local caches
+ and database to indicate which RRs have been authenticated and to
+ what extent they have been authenticated, (3) performs additional
+ queries as necessary to attempt to obtain KEY, SIG, or NXT RRs when
+ needed, (4) normally sets the CD query header bit on its queries.
+
+10. Security Considerations
+
+ This document specifies extensions to the Domain Name System (DNS)
+ protocol to provide data integrity and data origin authentication,
+ public key distribution, and optional transaction and request
+ security.
+
+ It should be noted that, at most, these extensions guarantee the
+ validity of resource records, including KEY resource records,
+ retrieved from the DNS. They do not magically solve other security
+ problems. For example, using secure DNS you can have high confidence
+ in the IP address you retrieve for a host name; however, this does
+ not stop someone for substituting an unauthorized host at that
+
+
+
+Eastlake Standards Track [Page 38]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ address or capturing packets sent to that address and falsely
+ responding with packets apparently from that address. Any reasonably
+ complete security system will require the protection of many
+ additional facets of the Internet beyond DNS.
+
+ The implementation of NXT RRs as described herein enables a resolver
+ to determine all the names in a zone even if zone transfers are
+ prohibited (section 5.6). This is an active area of work and may
+ change.
+
+ A number of precautions in DNS implementation have evolved over the
+ years to harden the insecure DNS against spoofing. These precautions
+ should not be abandoned but should be considered to provide
+ additional protection in case of key compromise in secure DNS.
+
+11. IANA Considerations
+
+ KEY RR flag bits 2 and 8-11 and all flag extension field bits can be
+ assigned by IETF consensus as defined in RFC 2434. The remaining
+ values of the NAMTYP flag field and flag bits 4 and 5 (which could
+ conceivably become an extension of the NAMTYP field) can only be
+ assigned by an IETF Standards Action [RFC 2434].
+
+ Algorithm numbers 5 through 251 are available for assignment should
+ sufficient reason arise. However, the designation of a new algorithm
+ could have a major impact on interoperability and requires an IETF
+ Standards Action [RFC 2434]. The existence of the private algorithm
+ types 253 and 254 should satify most needs for private or proprietary
+ algorithms.
+
+ Additional values of the Protocol Octet (5-254) can be assigned by
+ IETF Consensus [RFC 2434].
+
+ The meaning of the first bit of the NXT RR "type bit map" being a one
+ can only be assigned by a standards action.
+
+References
+
+ [RFC 1033] Lottor, M., "Domain Administrators Operations Guide", RFC
+ 1033, November 1987.
+
+ [RFC 1034] Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC 1035] Mockapetris, P., "Domain Names - Implementation and
+ Specifications", STD 13, RFC 1035, November 1987.
+
+
+
+
+
+Eastlake Standards Track [Page 39]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ [RFC 1305] Mills, D., "Network Time Protocol (v3)", RFC 1305, March
+ 1992.
+
+ [RFC 1530] Malamud, C. and M. Rose, "Principles of Operation for the
+ TPC.INT Subdomain: General Principles and Policy", RFC
+ 1530, October 1993.
+
+ [RFC 2401] Kent, S. and R. Atkinson, "Security Architecture for the
+ Internet Protocol", RFC 2401, November 1998.
+
+ [RFC 1982] Elz, R. and R. Bush, "Serial Number Arithmetic", RFC
+ 1982, September 1996.
+
+ [RFC 1995] Ohta, M., "Incremental Zone Transfer in DNS", RFC 1995,
+ August 1996.
+
+ [RFC 2030] Mills, D., "Simple Network Time Protocol (SNTP) Version 4
+ for IPv4, IPv6 and OSI", RFC 2030, October 1996.
+
+ [RFC 2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+ [RFC 2065] Eastlake, D. and C. Kaufman, "Domain Name System Security
+ Extensions", RFC 2065, January 1997.
+
+ [RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC 2136] Vixie, P., Thomson, S., Rekhter, Y. and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)",
+ RFC 2136, April 1997.
+
+ [RFC 2137] Eastlake, D., "Secure Domain Name System Dynamic Update",
+ RFC 2137, April 1997.
+
+ [RFC 2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC 2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+ [RFC 2537] Eastlake, D., "RSA/MD5 KEYs and SIGs in the Domain Name
+ System (DNS)", RFC 2537, March 1999.
+
+ [RFC 2539] Eastlake, D., "Storage of Diffie-Hellman Keys in the
+ Domain Name System (DNS)", RFC 2539, March 1999.
+
+
+
+Eastlake Standards Track [Page 40]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ [RFC 2536] Eastlake, D., "DSA KEYs and SIGs in the Domain Name
+ System (DNS)", RFC 2536, March 1999.
+
+ [RFC 2538] Eastlake, D. and O. Gudmundsson, "Storing Certificates in
+ the Domain Name System", RFC 2538, March 1999.
+
+ [RFC 2541] Eastlake, D., "DNS Operational Security Considerations",
+ RFC 2541, March 1999.
+
+ [RSA FAQ] - RSADSI Frequently Asked Questions periodic posting.
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ IBM
+ 65 Shindegan Hill Road
+ RR #1
+ Carmel, NY 10512
+
+ Phone: +1-914-784-7913 (w)
+ +1-914-276-2668 (h)
+ Fax: +1-914-784-3833 (w-fax)
+ EMail: dee3@us.ibm.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 41]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+Appendix A: Base 64 Encoding
+
+ The following encoding technique is taken from [RFC 2045] by N.
+ Borenstein and N. Freed. It is reproduced here in an edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base 64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base 64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character. Since all base
+ 64 input is an integral number of octets, only the following cases
+
+
+
+Eastlake Standards Track [Page 42]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ can arise: (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded output will be
+ an integral multiple of 4 characters with no "=" padding, (2) the
+ final quantum of encoding input is exactly 8 bits; here, the final
+ unit of encoded output will be two characters followed by two "="
+ padding characters, or (3) the final quantum of encoding input is
+ exactly 16 bits; here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 43]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+Appendix B: Changes from RFC 2065
+
+ This section summarizes the most important changes that have been
+ made since RFC 2065.
+
+ 1. Most of Section 7 of [RFC 2065] called "Operational
+ Considerations", has been removed and may be made into a separate
+ document [RFC 2541].
+
+ 2. The KEY RR has been changed by (2a) eliminating the "experimental"
+ flag as unnecessary, (2b) reserving a flag bit for flags
+ expansion, (2c) more compactly encoding a number of bit fields in
+ such a way as to leave unchanged bits actually used by the limited
+ code currently deployed, (2d) eliminating the IPSEC and email flag
+ bits which are replaced by values of the protocol field and adding
+ a protocol field value for DNS security itself, (2e) adding
+ material to indicate that zone KEY RRs occur only at delegation
+ points, and (2f) removing the description of the RSA/MD5 algorithm
+ to a separate document [RFC 2537]. Section 3.4 describing the
+ meaning of various combinations of "no-key" and key present KEY
+ RRs has been added and the secure / unsecure status of a zone has
+ been clarified as being per algorithm.
+
+ 3. The SIG RR has been changed by (3a) renaming the "time signed"
+ field to be the "signature inception" field, (3b) clarifying that
+ signature expiration and inception use serial number ring
+ arithmetic, (3c) changing the definition of the key footprint/tag
+ for algorithms other than 1 and adding Appendix C to specify its
+ calculation. In addition, the SIG covering type AXFR has been
+ eliminated while one covering IXFR [RFC 1995] has been added (see
+ section 5.6).
+
+ 4. Algorithm 3, the DSA algorithm, is now designated as the mandatory
+ to implement algorithm. Algorithm 1, the RSA/MD5 algorithm, is
+ now a recommended option. Algorithm 2 and 4 are designated as the
+ Diffie-Hellman key and elliptic cryptography algorithms
+ respectively, all to be defined in separate documents. Algorithm
+ code point 252 is designated to indicate "indirect" keys, to be
+ defined in a separate document, where the actual key is elsewhere.
+ Both the KEY and SIG RR definitions have been simplified by
+ eliminating the "null" algorithm 253 as defined in [RFC 2065].
+ That algorithm had been included because at the time it was
+ thought it might be useful in DNS dynamic update [RFC 2136]. It
+ was in fact not so used and it is dropped to simplify DNS
+ security. Howver, that algorithm number has been re-used to
+ indicate private algorithms where a domain name specifies the
+ algorithm.
+
+
+
+
+Eastlake Standards Track [Page 44]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+ 5. The NXT RR has been changed so that (5a) the NXT RRs in a zone
+ cover all names, including wildcards as literal names without
+ expansion, except for glue address records whose names would not
+ otherwise appear, (5b) all NXT bit map areas whose first octet has
+ bit zero set have been reserved for future definition, (5c) the
+ number of and circumstances under which an NXT must be returned in
+ connection with wildcard names has been extended, and (5d) in
+ connection with the bit map, references to the WKS RR have been
+ removed and verticle bars ("|") have been added between the RR
+ type mnemonics in the ASCII representation.
+
+ 6. Information on the canonical form and ordering of RRs has been
+ moved into a separate Section 8.
+
+ 7. A subsection covering incremental and full zone transfer has been
+ added in Section 5.
+
+ 8. Concerning DNS chaining: Further specification and policy
+ recommendations on secure resolution have been added, primarily in
+ Section 6.3.1. It is now clearly stated that authenticated data
+ has a validity period of the intersection of the validity periods
+ of the SIG RRs in its authentication chain. The requirement to
+ staticly configure a superzone's key signed by a zone in all of
+ the zone's authoritative servers has been removed. The
+ recommendation to continue DNS security checks in a secure island
+ of DNS data that is separated from other parts of the DNS tree by
+ insecure zones and does not contain a zone for which a key has
+ been staticly configured was dropped.
+
+ 9. It was clarified that the presence of the AD bit in a response
+ does not apply to the additional information section or to glue
+ address or delegation point NS RRs. The AD bit only indicates
+ that the answer and authority sections of the response are
+ authoritative.
+
+ 10. It is now required that KEY RRs and NXT RRs be signed only with
+ zone-level keys.
+
+ 11. Add IANA Considerations section and references to RFC 2434.
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 45]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+Appendix C: Key Tag Calculation
+
+ The key tag field in the SIG RR is just a means of more efficiently
+ selecting the correct KEY RR to use when there is more than one KEY
+ RR candidate available, for example, in verifying a signature. It is
+ possible for more than one candidate key to have the same tag, in
+ which case each must be tried until one works or all fail. The
+ following reference implementation of how to calculate the Key Tag,
+ for all algorithms other than algorithm 1, is in ANSI C. It is coded
+ for clarity, not efficiency. (See section 4.1.6 for how to determine
+ the Key Tag of an algorithm 1 key.)
+
+ /* assumes int is at least 16 bits
+ first byte of the key tag is the most significant byte of return
+ value
+ second byte of the key tag is the least significant byte of
+ return value
+ */
+
+ int keytag (
+
+ unsigned char key[], /* the RDATA part of the KEY RR */
+ unsigned int keysize, /* the RDLENGTH */
+ )
+ {
+ long int ac; /* assumed to be 32 bits or larger */
+
+ for ( ac = 0, i = 0; i < keysize; ++i )
+ ac += (i&1) ? key[i] : key[i]<<8;
+ ac += (ac>>16) & 0xFFFF;
+ return ac & 0xFFFF;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 46]
+
+RFC 2535 DNS Security Extensions March 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 47]
+
diff --git a/doc/rfc/rfc2536.txt b/doc/rfc/rfc2536.txt
new file mode 100644
index 0000000..88be242
--- /dev/null
+++ b/doc/rfc/rfc2536.txt
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+Network Working Group D. EastLake
+Request for Comments: 2536 IBM
+Category: Standards Track March 1999
+
+
+ DSA KEYs and SIGs in the Domain Name System (DNS)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ A standard method for storing US Government Digital Signature
+ Algorithm keys and signatures in the Domain Name System is described
+ which utilizes DNS KEY and SIG resource records.
+
+Table of Contents
+
+ Abstract...................................................1
+ 1. Introduction............................................1
+ 2. DSA KEY Resource Records................................2
+ 3. DSA SIG Resource Records................................3
+ 4. Performance Considerations..............................3
+ 5. Security Considerations.................................4
+ 6. IANA Considerations.....................................4
+ References.................................................5
+ Author's Address...........................................5
+ Full Copyright Statement...................................6
+
+1. Introduction
+
+ The Domain Name System (DNS) is the global hierarchical replicated
+ distributed database system for Internet addressing, mail proxy, and
+ other information. The DNS has been extended to include digital
+ signatures and cryptographic keys as described in [RFC 2535]. Thus
+ the DNS can now be secured and can be used for secure key
+ distribution.
+
+
+
+
+
+Eastlake Standards Track [Page 1]
+
+RFC 2536 DSA in the DNS March 1999
+
+
+ This document describes how to store US Government Digital Signature
+ Algorithm (DSA) keys and signatures in the DNS. Familiarity with the
+ US Digital Signature Algorithm is assumed [Schneier]. Implementation
+ of DSA is mandatory for DNS security.
+
+2. DSA KEY Resource Records
+
+ DSA public keys are stored in the DNS as KEY RRs using algorithm
+ number 3 [RFC 2535]. The structure of the algorithm specific portion
+ of the RDATA part of this RR is as shown below. These fields, from Q
+ through Y are the "public key" part of the DSA KEY RR.
+
+ The period of key validity is not in the KEY RR but is indicated by
+ the SIG RR(s) which signs and authenticates the KEY RR(s) at that
+ domain name.
+
+ Field Size
+ ----- ----
+ T 1 octet
+ Q 20 octets
+ P 64 + T*8 octets
+ G 64 + T*8 octets
+ Y 64 + T*8 octets
+
+ As described in [FIPS 186] and [Schneier]: T is a key size parameter
+ chosen such that 0 <= T <= 8. (The meaning for algorithm 3 if the T
+ octet is greater than 8 is reserved and the remainder of the RDATA
+ portion may have a different format in that case.) Q is a prime
+ number selected at key generation time such that 2**159 < Q < 2**160
+ so Q is always 20 octets long and, as with all other fields, is
+ stored in "big-endian" network order. P, G, and Y are calculated as
+ directed by the FIPS 186 key generation algorithm [Schneier]. P is
+ in the range 2**(511+64T) < P < 2**(512+64T) and so is 64 + 8*T
+ octets long. G and Y are quantities modulus P and so can be up to
+ the same length as P and are allocated fixed size fields with the
+ same number of octets as P.
+
+ During the key generation process, a random number X must be
+ generated such that 1 <= X <= Q-1. X is the private key and is used
+ in the final step of public key generation where Y is computed as
+
+ Y = G**X mod P
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 2]
+
+RFC 2536 DSA in the DNS March 1999
+
+
+3. DSA SIG Resource Records
+
+ The signature portion of the SIG RR RDATA area, when using the US
+ Digital Signature Algorithm, is shown below with fields in the order
+ they occur. See [RFC 2535] for fields in the SIG RR RDATA which
+ precede the signature itself.
+
+ Field Size
+ ----- ----
+ T 1 octet
+ R 20 octets
+ S 20 octets
+
+ The data signed is determined as specified in [RFC 2535]. Then the
+ following steps are taken, as specified in [FIPS 186], where Q, P, G,
+ and Y are as specified in the public key [Schneier]:
+
+ hash = SHA-1 ( data )
+
+ Generate a random K such that 0 < K < Q.
+
+ R = ( G**K mod P ) mod Q
+
+ S = ( K**(-1) * (hash + X*R) ) mod Q
+
+ Since Q is 160 bits long, R and S can not be larger than 20 octets,
+ which is the space allocated.
+
+ T is copied from the public key. It is not logically necessary in
+ the SIG but is present so that values of T > 8 can more conveniently
+ be used as an escape for extended versions of DSA or other algorithms
+ as later specified.
+
+4. Performance Considerations
+
+ General signature generation speeds are roughly the same for RSA [RFC
+ 2537] and DSA. With sufficient pre-computation, signature generation
+ with DSA is faster than RSA. Key generation is also faster for DSA.
+ However, signature verification is an order of magnitude slower than
+ RSA when the RSA public exponent is chosen to be small as is
+ recommended for KEY RRs used in domain name system (DNS) data
+ authentication.
+
+ Current DNS implementations are optimized for small transfers,
+ typically less than 512 bytes including overhead. While larger
+ transfers will perform correctly and work is underway to make larger
+ transfers more efficient, it is still advisable at this time to make
+ reasonable efforts to minimize the size of KEY RR sets stored within
+
+
+
+Eastlake Standards Track [Page 3]
+
+RFC 2536 DSA in the DNS March 1999
+
+
+ the DNS consistent with adequate security. Keep in mind that in a
+ secure zone, at least one authenticating SIG RR will also be
+ returned.
+
+5. Security Considerations
+
+ Many of the general security consideration in [RFC 2535] apply. Keys
+ retrieved from the DNS should not be trusted unless (1) they have
+ been securely obtained from a secure resolver or independently
+ verified by the user and (2) this secure resolver and secure
+ obtainment or independent verification conform to security policies
+ acceptable to the user. As with all cryptographic algorithms,
+ evaluating the necessary strength of the key is essential and
+ dependent on local policy.
+
+ The key size limitation of a maximum of 1024 bits ( T = 8 ) in the
+ current DSA standard may limit the security of DSA. For particularly
+ critical applications, implementors are encouraged to consider the
+ range of available algorithms and key sizes.
+
+ DSA assumes the ability to frequently generate high quality random
+ numbers. See [RFC 1750] for guidance. DSA is designed so that if
+ manipulated rather than random numbers are used, very high bandwidth
+ covert channels are possible. See [Schneier] and more recent
+ research. The leakage of an entire DSA private key in only two DSA
+ signatures has been demonstrated. DSA provides security only if
+ trusted implementations, including trusted random number generation,
+ are used.
+
+6. IANA Considerations
+
+ Allocation of meaning to values of the T parameter that are not
+ defined herein requires an IETF standards actions. It is intended
+ that values unallocated herein be used to cover future extensions of
+ the DSS standard.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 4]
+
+RFC 2536 DSA in the DNS March 1999
+
+
+References
+
+ [FIPS 186] U.S. Federal Information Processing Standard: Digital
+ Signature Standard.
+
+ [RFC 1034] Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC 1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC 1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness
+ Recommendations for Security", RFC 1750, December 1994.
+
+ [RFC 2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC 2537] Eastlake, D., "RSA/MD5 KEYs and SIGs in the Domain Name
+ System (DNS)", RFC 2537, March 1999.
+
+ [Schneier] Schneier, B., "Applied Cryptography Second Edition:
+ protocols, algorithms, and source code in C", 1996.
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ IBM
+ 65 Shindegan Hill Road, RR #1
+ Carmel, NY 10512
+
+ Phone: +1-914-276-2668(h)
+ +1-914-784-7913(w)
+ Fax: +1-914-784-3833(w)
+ EMail: dee3@us.ibm.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 5]
+
+RFC 2536 DSA in the DNS March 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 6]
+
diff --git a/doc/rfc/rfc2537.txt b/doc/rfc/rfc2537.txt
new file mode 100644
index 0000000..cb75cf5
--- /dev/null
+++ b/doc/rfc/rfc2537.txt
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake
+Request for Comments: 2537 IBM
+Category: Standards Track March 1999
+
+
+ RSA/MD5 KEYs and SIGs in the Domain Name System (DNS)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ A standard method for storing RSA keys and and RSA/MD5 based
+ signatures in the Domain Name System is described which utilizes DNS
+ KEY and SIG resource records.
+
+Table of Contents
+
+ Abstract...................................................1
+ 1. Introduction............................................1
+ 2. RSA Public KEY Resource Records.........................2
+ 3. RSA/MD5 SIG Resource Records............................2
+ 4. Performance Considerations..............................3
+ 5. Security Considerations.................................4
+ References.................................................4
+ Author's Address...........................................5
+ Full Copyright Statement...................................6
+
+1. Introduction
+
+ The Domain Name System (DNS) is the global hierarchical replicated
+ distributed database system for Internet addressing, mail proxy, and
+ other information. The DNS has been extended to include digital
+ signatures and cryptographic keys as described in [RFC 2535]. Thus
+ the DNS can now be secured and used for secure key distribution.
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 1]
+
+RFC 2537 RSA/MD5 KEYs and SIGs in the DNS March 1999
+
+
+ This document describes how to store RSA keys and and RSA/MD5 based
+ signatures in the DNS. Familiarity with the RSA algorithm is assumed
+ [Schneier]. Implementation of the RSA algorithm in DNS is
+ recommended.
+
+ The key words "MUST", "REQUIRED", "SHOULD", "RECOMMENDED", and "MAY"
+ in this document are to be interpreted as described in RFC 2119.
+
+2. RSA Public KEY Resource Records
+
+ RSA public keys are stored in the DNS as KEY RRs using algorithm
+ number 1 [RFC 2535]. The structure of the algorithm specific portion
+ of the RDATA part of such RRs is as shown below.
+
+ Field Size
+ ----- ----
+ exponent length 1 or 3 octets (see text)
+ exponent as specified by length field
+ modulus remaining space
+
+ For interoperability, the exponent and modulus are each currently
+ limited to 4096 bits in length. The public key exponent is a
+ variable length unsigned integer. Its length in octets is
+ represented as one octet if it is in the range of 1 to 255 and by a
+ zero octet followed by a two octet unsigned length if it is longer
+ than 255 bytes. The public key modulus field is a multiprecision
+ unsigned integer. The length of the modulus can be determined from
+ the RDLENGTH and the preceding RDATA fields including the exponent.
+ Leading zero octets are prohibited in the exponent and modulus.
+
+3. RSA/MD5 SIG Resource Records
+
+ The signature portion of the SIG RR RDATA area, when using the
+ RSA/MD5 algorithm, is calculated as shown below. The data signed is
+ determined as specified in [RFC 2535]. See [RFC 2535] for fields in
+ the SIG RR RDATA which precede the signature itself.
+
+
+ hash = MD5 ( data )
+
+ signature = ( 00 | 01 | FF* | 00 | prefix | hash ) ** e (mod n)
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 2]
+
+RFC 2537 RSA/MD5 KEYs and SIGs in the DNS March 1999
+
+
+ where MD5 is the message digest algorithm documented in [RFC 1321],
+ "|" is concatenation, "e" is the private key exponent of the signer,
+ and "n" is the modulus of the signer's public key. 01, FF, and 00
+ are fixed octets of the corresponding hexadecimal value. "prefix" is
+ the ASN.1 BER MD5 algorithm designator prefix specified in [RFC
+ 2437], that is,
+
+ hex 3020300c06082a864886f70d020505000410 [NETSEC].
+
+ This prefix is included to make it easier to use RSAREF (or similar
+ packages such as EuroRef). The FF octet MUST be repeated the maximum
+ number of times such that the value of the quantity being
+ exponentiated is the same length in octets as the value of n.
+
+ (The above specifications are identical to the corresponding part of
+ Public Key Cryptographic Standard #1 [RFC 2437].)
+
+ The size of n, including most and least significant bits (which will
+ be 1) MUST be not less than 512 bits and not more than 4096 bits. n
+ and e SHOULD be chosen such that the public exponent is small.
+
+ Leading zero bytes are permitted in the RSA/MD5 algorithm signature.
+
+ A public exponent of 3 minimizes the effort needed to verify a
+ signature. Use of 3 as the public exponent is weak for
+ confidentiality uses since, if the same data can be collected
+ encrypted under three different keys with an exponent of 3 then,
+ using the Chinese Remainder Theorem [NETSEC], the original plain text
+ can be easily recovered. This weakness is not significant for DNS
+ security because we seek only authentication, not confidentiality.
+
+4. Performance Considerations
+
+ General signature generation speeds are roughly the same for RSA and
+ DSA [RFC 2536]. With sufficient pre-computation, signature
+ generation with DSA is faster than RSA. Key generation is also
+ faster for DSA. However, signature verification is an order of
+ magnitude slower with DSA when the RSA public exponent is chosen to
+ be small as is recommended for KEY RRs used in domain name system
+ (DNS) data authentication.
+
+ Current DNS implementations are optimized for small transfers,
+ typically less than 512 bytes including overhead. While larger
+ transfers will perform correctly and work is underway to make larger
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 3]
+
+RFC 2537 RSA/MD5 KEYs and SIGs in the DNS March 1999
+
+
+ transfers more efficient, it is still advisable at this time to make
+ reasonable efforts to minimize the size of KEY RR sets stored within
+ the DNS consistent with adequate security. Keep in mind that in a
+ secure zone, at least one authenticating SIG RR will also be
+ returned.
+
+5. Security Considerations
+
+ Many of the general security consideration in [RFC 2535] apply. Keys
+ retrieved from the DNS should not be trusted unless (1) they have
+ been securely obtained from a secure resolver or independently
+ verified by the user and (2) this secure resolver and secure
+ obtainment or independent verification conform to security policies
+ acceptable to the user. As with all cryptographic algorithms,
+ evaluating the necessary strength of the key is essential and
+ dependent on local policy.
+
+ For interoperability, the RSA key size is limited to 4096 bits. For
+ particularly critical applications, implementors are encouraged to
+ consider the range of available algorithms and key sizes.
+
+References
+
+ [NETSEC] Kaufman, C., Perlman, R. and M. Speciner, "Network
+ Security: PRIVATE Communications in a PUBLIC World",
+ Series in Computer Networking and Distributed
+ Communications, 1995.
+
+ [RFC 2437] Kaliski, B. and J. Staddon, "PKCS #1: RSA Cryptography
+ Specifications Version 2.0", RFC 2437, October 1998.
+
+ [RFC 1034] Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC 1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC 1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321
+ April 1992.
+
+ [RFC 2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC 2536] EastLake, D., "DSA KEYs and SIGs in the Domain Name
+ System (DNS)", RFC 2536, March 1999.
+
+
+
+
+
+
+Eastlake Standards Track [Page 4]
+
+RFC 2537 RSA/MD5 KEYs and SIGs in the DNS March 1999
+
+
+ [Schneier] Bruce Schneier, "Applied Cryptography Second Edition:
+ protocols, algorithms, and source code in C", 1996, John
+ Wiley and Sons, ISBN 0-471-11709-9.
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ IBM
+ 65 Shindegan Hill Road, RR #1
+ Carmel, NY 10512
+
+ Phone: +1-914-276-2668(h)
+ +1-914-784-7913(w)
+ Fax: +1-914-784-3833(w)
+ EMail: dee3@us.ibm.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 5]
+
+RFC 2537 RSA/MD5 KEYs and SIGs in the DNS March 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 6]
+
diff --git a/doc/rfc/rfc2538.txt b/doc/rfc/rfc2538.txt
new file mode 100644
index 0000000..c53e3ef
--- /dev/null
+++ b/doc/rfc/rfc2538.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake
+Request for Comments: 2538 IBM
+Category: Standards Track O. Gudmundsson
+ TIS Labs
+ March 1999
+
+
+ Storing Certificates in the Domain Name System (DNS)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ Cryptographic public key are frequently published and their
+ authenticity demonstrated by certificates. A CERT resource record
+ (RR) is defined so that such certificates and related certificate
+ revocation lists can be stored in the Domain Name System (DNS).
+
+Table of Contents
+
+ Abstract...................................................1
+ 1. Introduction............................................2
+ 2. The CERT Resource Record................................2
+ 2.1 Certificate Type Values................................3
+ 2.2 Text Representation of CERT RRs........................4
+ 2.3 X.509 OIDs.............................................4
+ 3. Appropriate Owner Names for CERT RRs....................5
+ 3.1 X.509 CERT RR Names....................................5
+ 3.2 PGP CERT RR Names......................................6
+ 4. Performance Considerations..............................6
+ 5. IANA Considerations.....................................7
+ 6. Security Considerations.................................7
+ References.................................................8
+ Authors' Addresses.........................................9
+ Full Copyright Notice.....................................10
+
+
+
+
+
+
+Eastlake & Gudmundsson Standards Track [Page 1]
+
+RFC 2538 Storing Certificates in the DNS March 1999
+
+
+1. Introduction
+
+ Public keys are frequently published in the form of a certificate and
+ their authenticity is commonly demonstrated by certificates and
+ related certificate revocation lists (CRLs). A certificate is a
+ binding, through a cryptographic digital signature, of a public key,
+ a validity interval and/or conditions, and identity, authorization,
+ or other information. A certificate revocation list is a list of
+ certificates that are revoked, and incidental information, all signed
+ by the signer (issuer) of the revoked certificates. Examples are
+ X.509 certificates/CRLs in the X.500 directory system or PGP
+ certificates/revocations used by PGP software.
+
+ Section 2 below specifies a CERT resource record (RR) for the storage
+ of certificates in the Domain Name System.
+
+ Section 3 discusses appropriate owner names for CERT RRs.
+
+ Sections 4, 5, and 6 below cover performance, IANA, and security
+ considerations, respectively.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+2. The CERT Resource Record
+
+ The CERT resource record (RR) has the structure given below. Its RR
+ type code is 37.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | type | key tag |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | algorithm | /
+ +---------------+ certificate or CRL /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+
+ The type field is the certificate type as define in section 2.1
+ below.
+
+ The algorithm field has the same meaning as the algorithm field in
+ KEY and SIG RRs [RFC 2535] except that a zero algorithm field
+ indicates the algorithm is unknown to a secure DNS, which may simply
+ be the result of the algorithm not having been standardized for
+ secure DNS.
+
+
+
+Eastlake & Gudmundsson Standards Track [Page 2]
+
+RFC 2538 Storing Certificates in the DNS March 1999
+
+
+ The key tag field is the 16 bit value computed for the key embedded
+ in the certificate as specified in the DNSSEC Standard [RFC 2535].
+ This field is used as an efficiency measure to pick which CERT RRs
+ may be applicable to a particular key. The key tag can be calculated
+ for the key in question and then only CERT RRs with the same key tag
+ need be examined. However, the key must always be transformed to the
+ format it would have as the public key portion of a KEY RR before the
+ key tag is computed. This is only possible if the key is applicable
+ to an algorithm (and limits such as key size limits) defined for DNS
+ security. If it is not, the algorithm field MUST BE zero and the tag
+ field is meaningless and SHOULD BE zero.
+
+2.1 Certificate Type Values
+
+ The following values are defined or reserved:
+
+ Value Mnemonic Certificate Type
+ ----- -------- ----------- ----
+ 0 reserved
+ 1 PKIX X.509 as per PKIX
+ 2 SPKI SPKI cert
+ 3 PGP PGP cert
+ 4-252 available for IANA assignment
+ 253 URI URI private
+ 254 OID OID private
+ 255-65534 available for IANA assignment
+ 65535 reserved
+
+ The PKIX type is reserved to indicate an X.509 certificate conforming
+ to the profile being defined by the IETF PKIX working group. The
+ certificate section will start with a one byte unsigned OID length
+ and then an X.500 OID indicating the nature of the remainder of the
+ certificate section (see 2.3 below). (NOTE: X.509 certificates do
+ not include their X.500 directory type designating OID as a prefix.)
+
+ The SPKI type is reserved to indicate a certificate formated as to be
+ specified by the IETF SPKI working group.
+
+ The PGP type indicates a Pretty Good Privacy certificate as described
+ in RFC 2440 and its extensions and successors.
+
+ The URI private type indicates a certificate format defined by an
+ absolute URI. The certificate portion of the CERT RR MUST begin with
+ a null terminated URI [RFC 2396] and the data after the null is the
+ private format certificate itself. The URI SHOULD be such that a
+ retrieval from it will lead to documentation on the format of the
+ certificate. Recognition of private certificate types need not be
+ based on URI equality but can use various forms of pattern matching
+
+
+
+Eastlake & Gudmundsson Standards Track [Page 3]
+
+RFC 2538 Storing Certificates in the DNS March 1999
+
+
+ so that, for example, subtype or version information can also be
+ encoded into the URI.
+
+ The OID private type indicates a private format certificate specified
+ by a an ISO OID prefix. The certificate section will start with a
+ one byte unsigned OID length and then a BER encoded OID indicating
+ the nature of the remainder of the certificate section. This can be
+ an X.509 certificate format or some other format. X.509 certificates
+ that conform to the IETF PKIX profile SHOULD be indicated by the PKIX
+ type, not the OID private type. Recognition of private certificate
+ types need not be based on OID equality but can use various forms of
+ pattern matching such as OID prefix.
+
+2.2 Text Representation of CERT RRs
+
+ The RDATA portion of a CERT RR has the type field as an unsigned
+ integer or as a mnemonic symbol as listed in section 2.1 above.
+
+ The key tag field is represented as an unsigned integer.
+
+ The algorithm field is represented as an unsigned integer or a
+ mnemonic symbol as listed in [RFC 2535].
+
+ The certificate / CRL portion is represented in base 64 and may be
+ divided up into any number of white space separated substrings, down
+ to single base 64 digits, which are concatenated to obtain the full
+ signature. These substrings can span lines using the standard
+ parenthesis.
+
+ Note that the certificate / CRL portion may have internal sub-fields
+ but these do not appear in the master file representation. For
+ example, with type 254, there will be an OID size, an OID, and then
+ the certificate / CRL proper. But only a single logical base 64
+ string will appear in the text representation.
+
+2.3 X.509 OIDs
+
+ OIDs have been defined in connection with the X.500 directory for
+ user certificates, certification authority certificates, revocations
+ of certification authority, and revocations of user certificates.
+ The following table lists the OIDs, their BER encoding, and their
+ length prefixed hex format for use in CERT RRs:
+
+
+
+
+
+
+
+
+
+Eastlake & Gudmundsson Standards Track [Page 4]
+
+RFC 2538 Storing Certificates in the DNS March 1999
+
+
+ id-at-userCertificate
+ = { joint-iso-ccitt(2) ds(5) at(4) 36 }
+ == 0x 03 55 04 24
+ id-at-cACertificate
+ = { joint-iso-ccitt(2) ds(5) at(4) 37 }
+ == 0x 03 55 04 25
+ id-at-authorityRevocationList
+ = { joint-iso-ccitt(2) ds(5) at(4) 38 }
+ == 0x 03 55 04 26
+ id-at-certificateRevocationList
+ = { joint-iso-ccitt(2) ds(5) at(4) 39 }
+ == 0x 03 55 04 27
+
+3. Appropriate Owner Names for CERT RRs
+
+ It is recommended that certificate CERT RRs be stored under a domain
+ name related to their subject, i.e., the name of the entity intended
+ to control the private key corresponding to the public key being
+ certified. It is recommended that certificate revocation list CERT
+ RRs be stored under a domain name related to their issuer.
+
+ Following some of the guidelines below may result in the use in DNS
+ names of characters that require DNS quoting which is to use a
+ backslash followed by the octal representation of the ASCII code for
+ the character such as \000 for NULL.
+
+3.1 X.509 CERT RR Names
+
+ Some X.509 versions permit multiple names to be associated with
+ subjects and issuers under "Subject Alternate Name" and "Issuer
+ Alternate Name". For example, x.509v3 has such Alternate Names with
+ an ASN.1 specification as follows:
+
+ GeneralName ::= CHOICE {
+ otherName [0] INSTANCE OF OTHER-NAME,
+ rfc822Name [1] IA5String,
+ dNSName [2] IA5String,
+ x400Address [3] EXPLICIT OR-ADDRESS.&Type,
+ directoryName [4] EXPLICIT Name,
+ ediPartyName [5] EDIPartyName,
+ uniformResourceIdentifier [6] IA5String,
+ iPAddress [7] OCTET STRING,
+ registeredID [8] OBJECT IDENTIFIER
+ }
+
+ The recommended locations of CERT storage are as follows, in priority
+ order:
+
+
+
+
+Eastlake & Gudmundsson Standards Track [Page 5]
+
+RFC 2538 Storing Certificates in the DNS March 1999
+
+
+ (1) If a domain name is included in the identification in the
+ certificate or CRL, that should be used.
+ (2) If a domain name is not included but an IP address is included,
+ then the translation of that IP address into the appropriate
+ inverse domain name should be used.
+ (3) If neither of the above it used but a URI containing a domain
+ name is present, that domain name should be used.
+ (4) If none of the above is included but a character string name is
+ included, then it should be treated as described for PGP names in
+ 3.2 below.
+ (5) If none of the above apply, then the distinguished name (DN)
+ should be mapped into a domain name as specified in RFC 2247.
+
+ Example 1: Assume that an X.509v3 certificate is issued to /CN=John
+ Doe/DC=Doe/DC=com/DC=xy/O=Doe Inc/C=XY/ with Subject Alternative
+ names of (a) string "John (the Man) Doe", (b) domain name john-
+ doe.com, and (c) uri <https://www.secure.john-doe.com:8080/>. Then
+ the storage locations recommended, in priority order, would be
+ (1) john-doe.com,
+ (2) www.secure.john-doe.com, and
+ (3) Doe.com.xy.
+
+ Example 2: Assume that an X.509v3 certificate is issued to /CN=James
+ Hacker/L=Basingstoke/O=Widget Inc/C=GB/ with Subject Alternate names
+ of (a) domain name widget.foo.example, (b) IPv4 address
+ 10.251.13.201, and (c) string "James Hacker
+ <hacker@mail.widget.foo.example>". Then the storage locations
+ recommended, in priority order, would be
+ (1) widget.foo.example,
+ (2) 201.13.251.10.in-addr.arpa, and
+ (3) hacker.mail.widget.foo.example.
+
+3.2 PGP CERT RR Names
+
+ PGP signed keys (certificates) use a general character string User ID
+ [RFC 2440]. However, it is recommended by PGP that such names include
+ the RFC 822 email address of the party, as in "Leslie Example
+ <Leslie@host.example>". If such a format is used, the CERT should be
+ under the standard translation of the email address into a domain
+ name, which would be leslie.host.example in this case. If no RFC 822
+ name can be extracted from the string name no specific domain name is
+ recommended.
+
+4. Performance Considerations
+
+ Current Domain Name System (DNS) implementations are optimized for
+ small transfers, typically not more than 512 bytes including
+ overhead. While larger transfers will perform correctly and work is
+
+
+
+Eastlake & Gudmundsson Standards Track [Page 6]
+
+RFC 2538 Storing Certificates in the DNS March 1999
+
+
+ underway to make larger transfers more efficient, it is still
+ advisable at this time to make every reasonable effort to minimize
+ the size of certificates stored within the DNS. Steps that can be
+ taken may include using the fewest possible optional or extensions
+ fields and using short field values for variable length fields that
+ must be included.
+
+5. IANA Considerations
+
+ Certificate types 0x0000 through 0x00FF and 0xFF00 through 0xFFFF can
+ only be assigned by an IETF standards action [RFC 2434] (and this
+ document assigns 0x0001 through 0x0003 and 0x00FD and 0x00FE).
+ Certificate types 0x0100 through 0xFEFF are assigned through IETF
+ Consensus [RFC 2434] based on RFC documentation of the certificate
+ type. The availability of private types under 0x00FD and 0x00FE
+ should satisfy most requirements for proprietary or private types.
+
+6. Security Considerations
+
+ By definition, certificates contain their own authenticating
+ signature. Thus it is reasonable to store certificates in non-secure
+ DNS zones or to retrieve certificates from DNS with DNS security
+ checking not implemented or deferred for efficiency. The results MAY
+ be trusted if the certificate chain is verified back to a known
+ trusted key and this conforms with the user's security policy.
+
+ Alternatively, if certificates are retrieved from a secure DNS zone
+ with DNS security checking enabled and are verified by DNS security,
+ the key within the retrieved certificate MAY be trusted without
+ verifying the certificate chain if this conforms with the user's
+ security policy.
+
+ CERT RRs are not used in connection with securing the DNS security
+ additions so there are no security considerations related to CERT RRs
+ and securing the DNS itself.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake & Gudmundsson Standards Track [Page 7]
+
+RFC 2538 Storing Certificates in the DNS March 1999
+
+
+References
+
+ RFC 1034 Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ RFC 1035 Mockapetris, P., "Domain Names - Implementation and
+ Specifications", STD 13, RFC 1035, November 1987.
+
+ RFC 2119 Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ RFC 2247 Kille, S., Wahl, M., Grimstad, A., Huber, R. and S.
+ Sataluri, "Using Domains in LDAP/X.500 Distinguished
+ Names", RFC 2247, January 1998.
+
+ RFC 2396 Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396,
+ August 1998.
+
+ RFC 2440 Callas, J., Donnerhacke, L., Finney, H. and R. Thayer,
+ "OpenPGP Message Format", RFC 2240, November 1998.
+
+ RFC 2434 Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+ RFC 2535 Eastlake, D., "Domain Name System (DNS) Security
+ Extensions", RFC 2535, March 1999.
+
+ RFC 2459 Housley, R., Ford, W., Polk, W. and D. Solo, "Internet
+ X.509 Public Key Infrastructure Certificate and CRL
+ Profile", RFC 2459, January 1999.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake & Gudmundsson Standards Track [Page 8]
+
+RFC 2538 Storing Certificates in the DNS March 1999
+
+
+Authors' Addresses
+
+ Donald E. Eastlake 3rd
+ IBM
+ 65 Shindegan Hill Road
+ RR#1
+ Carmel, NY 10512 USA
+
+ Phone: +1-914-784-7913 (w)
+ +1-914-276-2668 (h)
+ Fax: +1-914-784-3833 (w-fax)
+ EMail: dee3@us.ibm.com
+
+
+ Olafur Gudmundsson
+ TIS Labs at Network Associates
+ 3060 Washington Rd, Route 97
+ Glenwood MD 21738
+
+ Phone: +1 443-259-2389
+ EMail: ogud@tislabs.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake & Gudmundsson Standards Track [Page 9]
+
+RFC 2538 Storing Certificates in the DNS March 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake & Gudmundsson Standards Track [Page 10]
+
diff --git a/doc/rfc/rfc2539.txt b/doc/rfc/rfc2539.txt
new file mode 100644
index 0000000..cf32523
--- /dev/null
+++ b/doc/rfc/rfc2539.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake
+Request for Comments: 2539 IBM
+Category: Standards Track March 1999
+
+
+ Storage of Diffie-Hellman Keys in the Domain Name System (DNS)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ A standard method for storing Diffie-Hellman keys in the Domain Name
+ System is described which utilizes DNS KEY resource records.
+
+Acknowledgements
+
+ Part of the format for Diffie-Hellman keys and the description
+ thereof was taken from a work in progress by:
+
+ Ashar Aziz <ashar.aziz@eng.sun.com>
+ Tom Markson <markson@incog.com>
+ Hemma Prafullchandra <hemma@eng.sun.com>
+
+ In addition, the following person provided useful comments that have
+ been incorporated:
+
+ Ran Atkinson <rja@inet.org>
+ Thomas Narten <narten@raleigh.ibm.com>
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 1]
+
+RFC 2539 Diffie-Hellman Keys in the DNS March 1999
+
+
+Table of Contents
+
+ Abstract...................................................1
+ Acknowledgements...........................................1
+ 1. Introduction............................................2
+ 1.1 About This Document....................................2
+ 1.2 About Diffie-Hellman...................................2
+ 2. Diffie-Hellman KEY Resource Records.....................3
+ 3. Performance Considerations..............................4
+ 4. IANA Considerations.....................................4
+ 5. Security Considerations.................................4
+ References.................................................5
+ Author's Address...........................................5
+ Appendix A: Well known prime/generator pairs...............6
+ A.1. Well-Known Group 1: A 768 bit prime..................6
+ A.2. Well-Known Group 2: A 1024 bit prime.................6
+ Full Copyright Notice......................................7
+
+1. Introduction
+
+ The Domain Name System (DNS) is the current global hierarchical
+ replicated distributed database system for Internet addressing, mail
+ proxy, and similar information. The DNS has been extended to include
+ digital signatures and cryptographic keys as described in [RFC 2535].
+ Thus the DNS can now be used for secure key distribution.
+
+1.1 About This Document
+
+ This document describes how to store Diffie-Hellman keys in the DNS.
+ Familiarity with the Diffie-Hellman key exchange algorithm is assumed
+ [Schneier].
+
+1.2 About Diffie-Hellman
+
+ Diffie-Hellman requires two parties to interact to derive keying
+ information which can then be used for authentication. Since DNS SIG
+ RRs are primarily used as stored authenticators of zone information
+ for many different resolvers, no Diffie-Hellman algorithm SIG RR is
+ defined. For example, assume that two parties have local secrets "i"
+ and "j". Assume they each respectively calculate X and Y as follows:
+
+ X = g**i ( mod p ) Y = g**j ( mod p )
+
+ They exchange these quantities and then each calculates a Z as
+ follows:
+
+ Zi = Y**i ( mod p ) Zj = X**j ( mod p )
+
+
+
+
+Eastlake Standards Track [Page 2]
+
+RFC 2539 Diffie-Hellman Keys in the DNS March 1999
+
+
+ shared secret between the two parties that an adversary who does not
+ know i or j will not be able to learn from the exchanged messages
+ (unless the adversary can derive i or j by performing a discrete
+ logarithm mod p which is hard for strong p and g).
+
+ The private key for each party is their secret i (or j). The public
+ key is the pair p and g, which must be the same for the parties, and
+ their individual X (or Y).
+
+2. Diffie-Hellman KEY Resource Records
+
+ Diffie-Hellman keys are stored in the DNS as KEY RRs using algorithm
+ number 2. The structure of the RDATA portion of this RR is as shown
+ below. The first 4 octets, including the flags, protocol, and
+ algorithm fields are common to all KEY RRs as described in [RFC
+ 2535]. The remainder, from prime length through public value is the
+ "public key" part of the KEY RR. The period of key validity is not in
+ the KEY RR but is indicated by the SIG RR(s) which signs and
+ authenticates the KEY RR(s) at that domain name.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | KEY flags | protocol | algorithm=2 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | prime length (or flag) | prime (p) (or special) /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / prime (p) (variable length) | generator length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | generator (g) (variable length) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | public value length | public value (variable length)/
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / public value (g^i mod p) (variable length) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Prime length is length of the Diffie-Hellman prime (p) in bytes if it
+ is 16 or greater. Prime contains the binary representation of the
+ Diffie-Hellman prime with most significant byte first (i.e., in
+ network order). If "prime length" field is 1 or 2, then the "prime"
+ field is actually an unsigned index into a table of 65,536
+ prime/generator pairs and the generator length SHOULD be zero. See
+ Appedix A for defined table entries and Section 4 for information on
+ allocating additional table entries. The meaning of a zero or 3
+ through 15 value for "prime length" is reserved.
+
+
+
+
+
+
+Eastlake Standards Track [Page 3]
+
+RFC 2539 Diffie-Hellman Keys in the DNS March 1999
+
+
+ Generator length is the length of the generator (g) in bytes.
+ Generator is the binary representation of generator with most
+ significant byte first. PublicValueLen is the Length of the Public
+ Value (g**i (mod p)) in bytes. PublicValue is the binary
+ representation of the DH public value with most significant byte
+ first.
+
+ The corresponding algorithm=2 SIG resource record is not used so no
+ format for it is defined.
+
+3. Performance Considerations
+
+ Current DNS implementations are optimized for small transfers,
+ typically less than 512 bytes including overhead. While larger
+ transfers will perform correctly and work is underway to make larger
+ transfers more efficient, it is still advisable to make reasonable
+ efforts to minimize the size of KEY RR sets stored within the DNS
+ consistent with adequate security. Keep in mind that in a secure
+ zone, an authenticating SIG RR will also be returned.
+
+4. IANA Considerations
+
+ Assignment of meaning to Prime Lengths of 0 and 3 through 15 requires
+ an IETF consensus.
+
+ Well known prime/generator pairs number 0x0000 through 0x07FF can
+ only be assigned by an IETF standards action and this Proposed
+ Standard assigns 0x0001 through 0x0002. Pairs number 0s0800 through
+ 0xBFFF can be assigned based on RFC documentation. Pairs number
+ 0xC000 through 0xFFFF are available for private use and are not
+ centrally coordinated. Use of such private pairs outside of a closed
+ environment may result in conflicts.
+
+5. Security Considerations
+
+ Many of the general security consideration in [RFC 2535] apply. Keys
+ retrieved from the DNS should not be trusted unless (1) they have
+ been securely obtained from a secure resolver or independently
+ verified by the user and (2) this secure resolver and secure
+ obtainment or independent verification conform to security policies
+ acceptable to the user. As with all cryptographic algorithms,
+ evaluating the necessary strength of the key is important and
+ dependent on local policy.
+
+ In addition, the usual Diffie-Hellman key strength considerations
+ apply. (p-1)/2 should also be prime, g should be primitive mod p, p
+ should be "large", etc. [Schneier]
+
+
+
+
+Eastlake Standards Track [Page 4]
+
+RFC 2539 Diffie-Hellman Keys in the DNS March 1999
+
+
+References
+
+ [RFC 1034] Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC 1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC 2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [Schneier] Bruce Schneier, "Applied Cryptography: Protocols,
+ Algorithms, and Source Code in C", 1996, John Wiley and
+ Sons
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ IBM
+ 65 Shindegan Hill Road, RR #1
+ Carmel, NY 10512
+
+ Phone: +1-914-276-2668(h)
+ +1-914-784-7913(w)
+ Fax: +1-914-784-3833(w)
+ EMail: dee3@us.ibm.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 5]
+
+RFC 2539 Diffie-Hellman Keys in the DNS March 1999
+
+
+Appendix A: Well known prime/generator pairs
+
+ These numbers are copied from the IPSEC effort where the derivation
+ of these values is more fully explained and additional information is
+ available. Richard Schroeppel performed all the mathematical and
+ computational work for this appendix.
+
+A.1. Well-Known Group 1: A 768 bit prime
+
+ The prime is 2^768 - 2^704 - 1 + 2^64 * { [2^638 pi] + 149686 }. Its
+ decimal value is
+ 155251809230070893513091813125848175563133404943451431320235
+ 119490296623994910210725866945387659164244291000768028886422
+ 915080371891804634263272761303128298374438082089019628850917
+ 0691316593175367469551763119843371637221007210577919
+
+ Prime modulus: Length (32 bit words): 24, Data (hex):
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+ 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+ EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+ E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF
+
+ Generator: Length (32 bit words): 1, Data (hex): 2
+
+A.2. Well-Known Group 2: A 1024 bit prime
+
+ The prime is 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
+ Its decimal value is
+ 179769313486231590770839156793787453197860296048756011706444
+ 423684197180216158519368947833795864925541502180565485980503
+ 646440548199239100050792877003355816639229553136239076508735
+ 759914822574862575007425302077447712589550957937778424442426
+ 617334727629299387668709205606050270810842907692932019128194
+ 467627007
+
+ Prime modulus: Length (32 bit words): 32, Data (hex):
+ FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+ 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+ EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+ E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
+ EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381
+ FFFFFFFF FFFFFFFF
+
+ Generator: Length (32 bit words): 1, Data (hex): 2
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 6]
+
+RFC 2539 Diffie-Hellman Keys in the DNS March 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 7]
+
diff --git a/doc/rfc/rfc2540.txt b/doc/rfc/rfc2540.txt
new file mode 100644
index 0000000..6314806
--- /dev/null
+++ b/doc/rfc/rfc2540.txt
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake
+Request for Comments: 2540 IBM
+Category: Experimental March 1999
+
+
+ Detached Domain Name System (DNS) Information
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. It does not specify an Internet standard of any kind.
+ Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ A standard format is defined for representing detached DNS
+ information. This is anticipated to be of use for storing
+ information retrieved from the Domain Name System (DNS), including
+ security information, in archival contexts or contexts not connected
+ to the Internet.
+
+Table of Contents
+
+ Abstract...................................................1
+ 1. Introduction............................................1
+ 2. General Format..........................................2
+ 2.1 Binary Format..........................................3
+ 2.2. Text Format...........................................4
+ 3. Usage Example...........................................4
+ 4. IANA Considerations.....................................4
+ 5. Security Considerations.................................4
+ References.................................................5
+ Author's Address...........................................5
+ Full Copyright Statement...................................6
+
+1. Introduction
+
+ The Domain Name System (DNS) is a replicated hierarchical distributed
+ database system [RFC 1034, 1035] that can provide highly available
+ service. It provides the operational basis for Internet host name to
+ address translation, automatic SMTP mail routing, and other basic
+ Internet functions. The DNS has been extended as described in [RFC
+ 2535] to permit the general storage of public cryptographic keys in
+
+
+
+Eastlake Experimental [Page 1]
+
+RFC 2540 Detached DNS Information March 1999
+
+
+ the DNS and to enable the authentication of information retrieved
+ from the DNS though digital signatures.
+
+ The DNS was not originally designed for storage of information
+ outside of the active zones and authoritative master files that are
+ part of the connected DNS. However there may be cases where this is
+ useful, particularly in connection with archived security
+ information.
+
+2. General Format
+
+ The formats used for detached Domain Name System (DNS) information
+ are similar to those used for connected DNS information. The primary
+ difference is that elements of the connected DNS system (unless they
+ are an authoritative server for the zone containing the information)
+ are required to count down the Time To Live (TTL) associated with
+ each DNS Resource Record (RR) and discard them (possibly fetching a
+ fresh copy) when the TTL reaches zero. In contrast to this, detached
+ information may be stored in a off-line file, where it can not be
+ updated, and perhaps used to authenticate historic data or it might
+ be received via non-DNS protocols long after it was retrieved from
+ the DNS. Therefore, it is not practical to count down detached DNS
+ information TTL and it may be necessary to keep the data beyond the
+ point where the TTL (which is defined as an unsigned field) would
+ underflow. To preserve information as to the freshness of this
+ detached data, it is accompanied by its retrieval time.
+
+ Whatever retrieves the information from the DNS must associate this
+ retrieval time with it. The retrieval time remains fixed thereafter.
+ When the current time minus the retrieval time exceeds the TTL for
+ any particular detached RR, it is no longer a valid copy within the
+ normal connected DNS scheme. This may make it invalid in context for
+ some detached purposes as well. If the RR is a SIG (signature) RR it
+ also has an expiration time. Regardless of the TTL, it and any RRs
+ it signs can not be considered authenticated after the signature
+ expiration time.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Experimental [Page 2]
+
+RFC 2540 Detached DNS Information March 1999
+
+
+2.1 Binary Format
+
+ The standard binary format for detached DNS information is as
+ follows:
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | first retrieval time |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | RR count | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Resource Records (RRs) |
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+ | next retrieval time |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | RR count | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Resource Records (RRs) |
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / ... /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | hex 20 |
+ +-+-+-+-+-+-+-+-+
+
+ Retrieval time - the time that the immediately following information
+ was obtained from the connected DNS system. It is an unsigned
+ number of seconds since the start of 1 January 1970, GMT,
+ ignoring leap seconds, in network (big-endian) order. Note that
+ this time can not be before the initial proposal of this
+ standard. Therefore, the initial byte of an actual retrieval
+ time, considered as a 32 bit unsigned quantity, would always be
+ larger than 20 hex. The end of detached DNS information is
+ indicated by a "retrieval time" field initial byte equal to 0x20.
+ Use of a "retrieval time" field with a leading unsigned byte of
+ zero indicates a 64 bit (actually 8 leading zero bits plus a 56
+ bit quantity). This 64 bit format will be required when
+ retrieval time is larger than 0xFFFFFFFF, which is some time in
+ the year 2106. The meaning of retrieval times with an initial
+ byte between 0x01 and 0x1F is reserved (see section 5).
+ Retrieval times will not generally be 32 bit aligned with respect
+ to each other due to the variable length nature of RRs.
+
+ RR count - an unsigned integer number (with bytes in network order)
+ of following resource records retrieved at the preceding
+ retrieval time.
+
+
+
+
+
+Eastlake Experimental [Page 3]
+
+RFC 2540 Detached DNS Information March 1999
+
+
+ Resource Records - the actual data which is in the same format as if
+ it were being transmitted in a DNS response. In particular, name
+ compression via pointers is permitted with the origin at the
+ beginning of the particular detached information data section,
+ just after the RR count.
+
+2.2. Text Format
+
+ The standard text format for detached DNS information is as
+ prescribed for zone master files [RFC 1035] except that the $INCLUDE
+ control entry is prohibited and the new $DATE entry is required
+ (unless the information set is empty). $DATE is followed by the date
+ and time that the following information was obtained from the DNS
+ system as described for retrieval time in section 2.1 above. It is
+ in the text format YYYYMMDDHHMMSS where YYYY is the year (which may
+ be more than four digits to cover years after 9999), the first MM is
+ the month number (01-12), DD is the day of the month (01-31), HH is
+ the hour in 24 hours notation (00-23), the second MM is the minute
+ (00-59), and SS is the second (00-59). Thus a $DATE must appear
+ before the first RR and at every change in retrieval time through the
+ detached information.
+
+3. Usage Example
+
+ A document might be authenticated by a key retrieved from the DNS in
+ a KEY resource record (RR). To later prove the authenticity of this
+ document, it would be desirable to preserve the KEY RR for that
+ public key, the SIG RR signing that KEY RR, the KEY RR for the key
+ used to authenticate that SIG, and so on through SIG and KEY RRs
+ until a well known trusted key is reached, perhaps the key for the
+ DNS root or some third party authentication service. (In some cases
+ these KEY RRs will actually be sets of KEY RRs with the same owner
+ and class because SIGs actually sign such record sets.)
+
+ This information could be preserved as a set of detached DNS
+ information blocks.
+
+4. IANA Considerations
+
+ Allocation of meanings to retrieval time fields with a initial byte
+ of between 0x01 and 0x1F requires an IETF consensus.
+
+5. Security Considerations
+
+ The entirety of this document concerns a means to represent detached
+ DNS information. Such detached resource records may be security
+ relevant and/or secured information as described in [RFC 2535]. The
+ detached format provides no overall security for sets of detached
+
+
+
+Eastlake Experimental [Page 4]
+
+RFC 2540 Detached DNS Information March 1999
+
+
+ information or for the association between retrieval time and
+ information. This can be provided by wrapping the detached
+ information format with some other form of signature. However, if
+ the detached information is accompanied by SIG RRs, its validity
+ period is indicated in those SIG RRs so the retrieval time might be
+ of secondary importance.
+
+References
+
+ [RFC 1034] Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC 1035] Mockapetris, P., " Domain Names - Implementation and
+ Specifications", STD 13, RFC 1035, November 1987.
+
+ [RFC 2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ IBM
+ 65 Shindegan Hill Road, RR #1
+ Carmel, NY 10512
+
+ Phone: +1-914-276-2668(h)
+ +1-914-784-7913(w)
+ Fax: +1-914-784-3833(w)
+ EMail: dee3@us.ibm.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Experimental [Page 5]
+
+RFC 2540 Detached DNS Information March 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Experimental [Page 6]
+
diff --git a/doc/rfc/rfc2541.txt b/doc/rfc/rfc2541.txt
new file mode 100644
index 0000000..a62ed2b
--- /dev/null
+++ b/doc/rfc/rfc2541.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake
+Request for Comments: 2541 IBM
+Category: Informational March 1999
+
+
+ DNS Security Operational Considerations
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ Secure DNS is based on cryptographic techniques. A necessary part of
+ the strength of these techniques is careful attention to the
+ operational aspects of key and signature generation, lifetime, size,
+ and storage. In addition, special attention must be paid to the
+ security of the high level zones, particularly the root zone. This
+ document discusses these operational aspects for keys and signatures
+ used in connection with the KEY and SIG DNS resource records.
+
+Acknowledgments
+
+ The contributions and suggestions of the following persons (in
+ alphabetic order) are gratefully acknowledged:
+
+ John Gilmore
+ Olafur Gudmundsson
+ Charlie Kaufman
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Informational [Page 1]
+
+RFC 2541 DNS Security Operational Considerations March 1999
+
+
+Table of Contents
+
+ Abstract...................................................1
+ Acknowledgments............................................1
+ 1. Introduction............................................2
+ 2. Public/Private Key Generation...........................2
+ 3. Public/Private Key Lifetimes............................2
+ 4. Public/Private Key Size Considerations..................3
+ 4.1 RSA Key Sizes..........................................3
+ 4.2 DSS Key Sizes..........................................4
+ 5. Private Key Storage.....................................4
+ 6. High Level Zones, The Root Zone, and The Meta-Root Key..5
+ 7. Security Considerations.................................5
+ References.................................................6
+ Author's Address...........................................6
+ Full Copyright Statement...................................7
+
+1. Introduction
+
+ This document describes operational considerations for the
+ generation, lifetime, size, and storage of DNS cryptographic keys and
+ signatures for use in the KEY and SIG resource records [RFC 2535].
+ Particular attention is paid to high level zones and the root zone.
+
+2. Public/Private Key Generation
+
+ Careful generation of all keys is a sometimes overlooked but
+ absolutely essential element in any cryptographically secure system.
+ The strongest algorithms used with the longest keys are still of no
+ use if an adversary can guess enough to lower the size of the likely
+ key space so that it can be exhaustively searched. Technical
+ suggestions for the generation of random keys will be found in [RFC
+ 1750].
+
+ Long term keys are particularly sensitive as they will represent a
+ more valuable target and be subject to attack for a longer time than
+ short period keys. It is strongly recommended that long term key
+ generation occur off-line in a manner isolated from the network via
+ an air gap or, at a minimum, high level secure hardware.
+
+3. Public/Private Key Lifetimes
+
+ No key should be used forever. The longer a key is in use, the
+ greater the probability that it will have been compromised through
+ carelessness, accident, espionage, or cryptanalysis. Furthermore, if
+
+
+
+
+
+
+Eastlake Informational [Page 2]
+
+RFC 2541 DNS Security Operational Considerations March 1999
+
+
+ key rollover is a rare event, there is an increased risk that, when
+ the time does come to change the key, no one at the site will
+ remember how to do it or operational problems will have developed in
+ the key rollover procedures.
+
+ While public key lifetime is a matter of local policy, these
+ considerations imply that, unless there are extraordinary
+ circumstances, no long term key should have a lifetime significantly
+ over four years. In fact, a reasonable guideline for long term keys
+ that are kept off-line and carefully guarded is a 13 month lifetime
+ with the intent that they be replaced every year. A reasonable
+ maximum lifetime for keys that are used for transaction security or
+ the like and are kept on line is 36 days with the intent that they be
+ replaced monthly or more often. In many cases, a key lifetime of
+ somewhat over a day may be reasonable.
+
+ On the other hand, public keys with too short a lifetime can lead to
+ excessive resource consumption in re-signing data and retrieving
+ fresh information because cached information becomes stale. In the
+ Internet environment, almost all public keys should have lifetimes no
+ shorter than three minutes, which is a reasonable estimate of maximum
+ packet delay even in unusual circumstances.
+
+4. Public/Private Key Size Considerations
+
+ There are a number of factors that effect public key size choice for
+ use in the DNS security extension. Unfortunately, these factors
+ usually do not all point in the same direction. Choice of zone key
+ size should generally be made by the zone administrator depending on
+ their local conditions.
+
+ For most schemes, larger keys are more secure but slower. In
+ addition, larger keys increase the size of the KEY and SIG RRs. This
+ increases the chance of DNS UDP packet overflow and the possible
+ necessity for using higher overhead TCP in responses.
+
+4.1 RSA Key Sizes
+
+ Given a small public exponent, verification (the most common
+ operation) for the MD5/RSA algorithm will vary roughly with the
+ square of the modulus length, signing will vary with the cube of the
+ modulus length, and key generation (the least common operation) will
+ vary with the fourth power of the modulus length. The current best
+ algorithms for factoring a modulus and breaking RSA security vary
+ roughly with the 1.6 power of the modulus itself. Thus going from a
+ 640 bit modulus to a 1280 bit modulus only increases the verification
+ time by a factor of 4 but may increase the work factor of breaking
+ the key by over 2^900.
+
+
+
+Eastlake Informational [Page 3]
+
+RFC 2541 DNS Security Operational Considerations March 1999
+
+
+ The recommended minimum RSA algorithm modulus size is 704 bits which
+ is believed by the author to be secure at this time. But high level
+ zones in the DNS tree may wish to set a higher minimum, perhaps 1000
+ bits, for security reasons. (Since the United States National
+ Security Agency generally permits export of encryption systems using
+ an RSA modulus of up to 512 bits, use of that small a modulus, i.e.
+ n, must be considered weak.)
+
+ For an RSA key used only to secure data and not to secure other keys,
+ 704 bits should be adequate at this time.
+
+4.2 DSS Key Sizes
+
+ DSS keys are probably roughly as strong as an RSA key of the same
+ length but DSS signatures are significantly smaller.
+
+5. Private Key Storage
+
+ It is recommended that, where possible, zone private keys and the
+ zone file master copy be kept and used in off-line, non-network
+ connected, physically secure machines only. Periodically an
+ application can be run to add authentication to a zone by adding SIG
+ and NXT RRs and adding no-key type KEY RRs for subzones/algorithms
+ where a real KEY RR for the subzone with that algorithm is not
+ provided. Then the augmented file can be transferred, perhaps by
+ sneaker-net, to the networked zone primary server machine.
+
+ The idea is to have a one way information flow to the network to
+ avoid the possibility of tampering from the network. Keeping the
+ zone master file on-line on the network and simply cycling it through
+ an off-line signer does not do this. The on-line version could still
+ be tampered with if the host it resides on is compromised. For
+ maximum security, the master copy of the zone file should be off net
+ and should not be updated based on an unsecured network mediated
+ communication.
+
+ This is not possible if the zone is to be dynamically updated
+ securely [RFC 2137]. At least a private key capable of updating the
+ SOA and NXT chain must be on line in that case.
+
+ Secure resolvers must be configured with some trusted on-line public
+ key information (or a secure path to such a resolver) or they will be
+ unable to authenticate. Although on line, this public key
+ information must be protected or it could be altered so that spoofed
+ DNS data would appear authentic.
+
+
+
+
+
+
+Eastlake Informational [Page 4]
+
+RFC 2541 DNS Security Operational Considerations March 1999
+
+
+ Non-zone private keys, such as host or user keys, generally have to
+ be kept on line to be used for real-time purposes such as DNS
+ transaction security.
+
+6. High Level Zones, The Root Zone, and The Meta-Root Key
+
+ Higher level zones are generally more sensitive than lower level
+ zones. Anyone controlling or breaking the security of a zone thereby
+ obtains authority over all of its subdomains (except in the case of
+ resolvers that have locally configured the public key of a
+ subdomain). Therefore, extra care should be taken with high level
+ zones and strong keys used.
+
+ The root zone is the most critical of all zones. Someone controlling
+ or compromising the security of the root zone would control the
+ entire DNS name space of all resolvers using that root zone (except
+ in the case of resolvers that have locally configured the public key
+ of a subdomain). Therefore, the utmost care must be taken in the
+ securing of the root zone. The strongest and most carefully handled
+ keys should be used. The root zone private key should always be kept
+ off line.
+
+ Many resolvers will start at a root server for their access to and
+ authentication of DNS data. Securely updating an enormous population
+ of resolvers around the world will be extremely difficult. Yet the
+ guidelines in section 3 above would imply that the root zone private
+ key be changed annually or more often and if it were staticly
+ configured at all these resolvers, it would have to be updated when
+ changed.
+
+ To permit relatively frequent change to the root zone key yet
+ minimize exposure of the ultimate key of the DNS tree, there will be
+ a "meta-root" key used very rarely and then only to sign a sequence
+ of regular root key RRsets with overlapping time validity periods
+ that are to be rolled out. The root zone contains the meta-root and
+ current regular root KEY RR(s) signed by SIG RRs under both the
+ meta-root and other root private key(s) themselves.
+
+ The utmost security in the storage and use of the meta-root key is
+ essential. The exact techniques are precautions to be used are
+ beyond the scope of this document. Because of its special position,
+ it may be best to continue with the same meta-root key for an
+ extended period of time such as ten to fifteen years.
+
+7. Security Considerations
+
+ The entirety of this document is concerned with operational
+ considerations of public/private key pair DNS Security.
+
+
+
+Eastlake Informational [Page 5]
+
+RFC 2541 DNS Security Operational Considerations March 1999
+
+
+References
+
+ [RFC 1034] Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC 1035] Mockapetris, P., "Domain Names - Implementation and
+ Specifications", STD 13, RFC 1035, November 1987.
+
+ [RFC 1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness
+ Requirements for Security", RFC 1750, December 1994.
+
+ [RFC 2065] Eastlake, D. and C. Kaufman, "Domain Name System
+ Security Extensions", RFC 2065, January 1997.
+
+ [RFC 2137] Eastlake, D., "Secure Domain Name System Dynamic
+ Update", RFC 2137, April 1997.
+
+ [RFC 2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RSA FAQ] RSADSI Frequently Asked Questions periodic posting.
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ IBM
+ 65 Shindegan Hill Road, RR #1
+ Carmel, NY 10512
+
+ Phone: +1-914-276-2668(h)
+ +1-914-784-7913(w)
+ Fax: +1-914-784-3833(w)
+ EMail: dee3@us.ibm.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Informational [Page 6]
+
+RFC 2541 DNS Security Operational Considerations March 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Informational [Page 7]
+
diff --git a/doc/rfc/rfc2553.txt b/doc/rfc/rfc2553.txt
new file mode 100644
index 0000000..6989bf3
--- /dev/null
+++ b/doc/rfc/rfc2553.txt
@@ -0,0 +1,2299 @@
+
+
+
+
+
+
+Network Working Group R. Gilligan
+Request for Comments: 2553 FreeGate
+Obsoletes: 2133 S. Thomson
+Category: Informational Bellcore
+ J. Bound
+ Compaq
+ W. Stevens
+ Consultant
+ March 1999
+
+
+ Basic Socket Interface Extensions for IPv6
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ The de facto standard application program interface (API) for TCP/IP
+ applications is the "sockets" interface. Although this API was
+ developed for Unix in the early 1980s it has also been implemented on
+ a wide variety of non-Unix systems. TCP/IP applications written
+ using the sockets API have in the past enjoyed a high degree of
+ portability and we would like the same portability with IPv6
+ applications. But changes are required to the sockets API to support
+ IPv6 and this memo describes these changes. These include a new
+ socket address structure to carry IPv6 addresses, new address
+ conversion functions, and some new socket options. These extensions
+ are designed to provide access to the basic IPv6 features required by
+ TCP and UDP applications, including multicasting, while introducing a
+ minimum of change into the system and providing complete
+ compatibility for existing IPv4 applications. Additional extensions
+ for advanced IPv6 features (raw sockets and access to the IPv6
+ extension headers) are defined in another document [4].
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 1]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+Table of Contents
+
+ 1. Introduction.................................................3
+ 2. Design Considerations........................................3
+ 2.1 What Needs to be Changed....................................4
+ 2.2 Data Types..................................................5
+ 2.3 Headers.....................................................5
+ 2.4 Structures..................................................5
+ 3. Socket Interface.............................................6
+ 3.1 IPv6 Address Family and Protocol Family.....................6
+ 3.2 IPv6 Address Structure......................................6
+ 3.3 Socket Address Structure for 4.3BSD-Based Systems...........7
+ 3.4 Socket Address Structure for 4.4BSD-Based Systems...........8
+ 3.5 The Socket Functions........................................9
+ 3.6 Compatibility with IPv4 Applications.......................10
+ 3.7 Compatibility with IPv4 Nodes..............................10
+ 3.8 IPv6 Wildcard Address......................................11
+ 3.9 IPv6 Loopback Address......................................12
+ 3.10 Portability Additions.....................................13
+ 4. Interface Identification....................................16
+ 4.1 Name-to-Index..............................................16
+ 4.2 Index-to-Name..............................................17
+ 4.3 Return All Interface Names and Indexes.....................17
+ 4.4 Free Memory................................................18
+ 5. Socket Options..............................................18
+ 5.1 Unicast Hop Limit..........................................18
+ 5.2 Sending and Receiving Multicast Packets....................19
+ 6. Library Functions...........................................21
+ 6.1 Nodename-to-Address Translation............................21
+ 6.2 Address-To-Nodename Translation............................24
+ 6.3 Freeing memory for getipnodebyname and getipnodebyaddr.....26
+ 6.4 Protocol-Independent Nodename and Service Name Translation.26
+ 6.5 Socket Address Structure to Nodename and Service Name......29
+ 6.6 Address Conversion Functions...............................31
+ 6.7 Address Testing Macros.....................................32
+ 7. Summary of New Definitions..................................33
+ 8. Security Considerations.....................................35
+ 9. Year 2000 Considerations....................................35
+ Changes From RFC 2133..........................................35
+ Acknowledgments................................................38
+ References.....................................................39
+ Authors' Addresses.............................................40
+ Full Copyright Statement.......................................41
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 2]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+1. Introduction
+
+ While IPv4 addresses are 32 bits long, IPv6 interfaces are identified
+ by 128-bit addresses. The socket interface makes the size of an IP
+ address quite visible to an application; virtually all TCP/IP
+ applications for BSD-based systems have knowledge of the size of an
+ IP address. Those parts of the API that expose the addresses must be
+ changed to accommodate the larger IPv6 address size. IPv6 also
+ introduces new features (e.g., traffic class and flowlabel), some of
+ which must be made visible to applications via the API. This memo
+ defines a set of extensions to the socket interface to support the
+ larger address size and new features of IPv6.
+
+2. Design Considerations
+
+ There are a number of important considerations in designing changes
+ to this well-worn API:
+
+ - The API changes should provide both source and binary
+ compatibility for programs written to the original API. That
+ is, existing program binaries should continue to operate when
+ run on a system supporting the new API. In addition, existing
+ applications that are re-compiled and run on a system supporting
+ the new API should continue to operate. Simply put, the API
+ changes for IPv6 should not break existing programs. An
+ additonal mechanism for implementations to verify this is to
+ verify the new symbols are protected by Feature Test Macros as
+ described in IEEE Std 1003.1. (Such Feature Test Macros are not
+ defined by this RFC.)
+
+ - The changes to the API should be as small as possible in order
+ to simplify the task of converting existing IPv4 applications to
+ IPv6.
+
+ - Where possible, applications should be able to use this API to
+ interoperate with both IPv6 and IPv4 hosts. Applications should
+ not need to know which type of host they are communicating with.
+
+ - IPv6 addresses carried in data structures should be 64-bit
+ aligned. This is necessary in order to obtain optimum
+ performance on 64-bit machine architectures.
+
+ Because of the importance of providing IPv4 compatibility in the API,
+ these extensions are explicitly designed to operate on machines that
+ provide complete support for both IPv4 and IPv6. A subset of this
+ API could probably be designed for operation on systems that support
+ only IPv6. However, this is not addressed in this memo.
+
+
+
+
+Gilligan, et. al. Informational [Page 3]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+2.1 What Needs to be Changed
+
+ The socket interface API consists of a few distinct components:
+
+ - Core socket functions.
+
+ - Address data structures.
+
+ - Name-to-address translation functions.
+
+ - Address conversion functions.
+
+ The core socket functions -- those functions that deal with such
+ things as setting up and tearing down TCP connections, and sending
+ and receiving UDP packets -- were designed to be transport
+ independent. Where protocol addresses are passed as function
+ arguments, they are carried via opaque pointers. A protocol-specific
+ address data structure is defined for each protocol that the socket
+ functions support. Applications must cast pointers to these
+ protocol-specific address structures into pointers to the generic
+ "sockaddr" address structure when using the socket functions. These
+ functions need not change for IPv6, but a new IPv6-specific address
+ data structure is needed.
+
+ The "sockaddr_in" structure is the protocol-specific data structure
+ for IPv4. This data structure actually includes 8-octets of unused
+ space, and it is tempting to try to use this space to adapt the
+ sockaddr_in structure to IPv6. Unfortunately, the sockaddr_in
+ structure is not large enough to hold the 16-octet IPv6 address as
+ well as the other information (address family and port number) that
+ is needed. So a new address data structure must be defined for IPv6.
+
+ IPv6 addresses are scoped [2] so they could be link-local, site,
+ organization, global, or other scopes at this time undefined. To
+ support applications that want to be able to identify a set of
+ interfaces for a specific scope, the IPv6 sockaddr_in structure must
+ support a field that can be used by an implementation to identify a
+ set of interfaces identifying the scope for an IPv6 address.
+
+ The name-to-address translation functions in the socket interface are
+ gethostbyname() and gethostbyaddr(). These are left as is and new
+ functions are defined to support IPv4 and IPv6. Additionally, the
+ POSIX 1003.g draft [3] specifies a new nodename-to-address
+ translation function which is protocol independent. This function
+ can also be used with IPv4 and IPv6.
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 4]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ The address conversion functions -- inet_ntoa() and inet_addr() --
+ convert IPv4 addresses between binary and printable form. These
+ functions are quite specific to 32-bit IPv4 addresses. We have
+ designed two analogous functions that convert both IPv4 and IPv6
+ addresses, and carry an address type parameter so that they can be
+ extended to other protocol families as well.
+
+ Finally, a few miscellaneous features are needed to support IPv6.
+ New interfaces are needed to support the IPv6 traffic class, flow
+ label, and hop limit header fields. New socket options are needed to
+ control the sending and receiving of IPv6 multicast packets.
+
+ The socket interface will be enhanced in the future to provide access
+ to other IPv6 features. These extensions are described in [4].
+
+2.2 Data Types
+
+ The data types of the structure elements given in this memo are
+ intended to be examples, not absolute requirements. Whenever
+ possible, data types from Draft 6.6 (March 1997) of POSIX 1003.1g are
+ used: uintN_t means an unsigned integer of exactly N bits (e.g.,
+ uint16_t). We also assume the argument data types from 1003.1g when
+ possible (e.g., the final argument to setsockopt() is a size_t
+ value). Whenever buffer sizes are specified, the POSIX 1003.1 size_t
+ data type is used (e.g., the two length arguments to getnameinfo()).
+
+2.3 Headers
+
+ When function prototypes and structures are shown we show the headers
+ that must be #included to cause that item to be defined.
+
+2.4 Structures
+
+ When structures are described the members shown are the ones that
+ must appear in an implementation. Additional, nonstandard members
+ may also be defined by an implementation. As an additional
+ precaution nonstandard members could be verified by Feature Test
+ Macros as described in IEEE Std 1003.1. (Such Feature Test Macros
+ are not defined by this RFC.)
+
+ The ordering shown for the members of a structure is the recommended
+ ordering, given alignment considerations of multibyte members, but an
+ implementation may order the members differently.
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 5]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+3. Socket Interface
+
+ This section specifies the socket interface changes for IPv6.
+
+3.1 IPv6 Address Family and Protocol Family
+
+ A new address family name, AF_INET6, is defined in <sys/socket.h>.
+ The AF_INET6 definition distinguishes between the original
+ sockaddr_in address data structure, and the new sockaddr_in6 data
+ structure.
+
+ A new protocol family name, PF_INET6, is defined in <sys/socket.h>.
+ Like most of the other protocol family names, this will usually be
+ defined to have the same value as the corresponding address family
+ name:
+
+ #define PF_INET6 AF_INET6
+
+ The PF_INET6 is used in the first argument to the socket() function
+ to indicate that an IPv6 socket is being created.
+
+3.2 IPv6 Address Structure
+
+ A new in6_addr structure holds a single IPv6 address and is defined
+ as a result of including <netinet/in.h>:
+
+ struct in6_addr {
+ uint8_t s6_addr[16]; /* IPv6 address */
+ };
+
+ This data structure contains an array of sixteen 8-bit elements,
+ which make up one 128-bit IPv6 address. The IPv6 address is stored
+ in network byte order.
+
+ The structure in6_addr above is usually implemented with an embedded
+ union with extra fields that force the desired alignment level in a
+ manner similar to BSD implementations of "struct in_addr". Those
+ additional implementation details are omitted here for simplicity.
+
+ An example is as follows:
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 6]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ struct in6_addr {
+ union {
+ uint8_t _S6_u8[16];
+ uint32_t _S6_u32[4];
+ uint64_t _S6_u64[2];
+ } _S6_un;
+ };
+ #define s6_addr _S6_un._S6_u8
+
+3.3 Socket Address Structure for 4.3BSD-Based Systems
+
+ In the socket interface, a different protocol-specific data structure
+ is defined to carry the addresses for each protocol suite. Each
+ protocol- specific data structure is designed so it can be cast into a
+ protocol- independent data structure -- the "sockaddr" structure.
+ Each has a "family" field that overlays the "sa_family" of the
+ sockaddr data structure. This field identifies the type of the data
+ structure.
+
+ The sockaddr_in structure is the protocol-specific address data
+ structure for IPv4. It is used to pass addresses between applications
+ and the system in the socket functions. The following sockaddr_in6
+ structure holds IPv6 addresses and is defined as a result of including
+ the <netinet/in.h> header:
+
+struct sockaddr_in6 {
+ sa_family_t sin6_family; /* AF_INET6 */
+ in_port_t sin6_port; /* transport layer port # */
+ uint32_t sin6_flowinfo; /* IPv6 traffic class & flow info */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ uint32_t sin6_scope_id; /* set of interfaces for a scope */
+};
+
+ This structure is designed to be compatible with the sockaddr data
+ structure used in the 4.3BSD release.
+
+ The sin6_family field identifies this as a sockaddr_in6 structure.
+ This field overlays the sa_family field when the buffer is cast to a
+ sockaddr data structure. The value of this field must be AF_INET6.
+
+ The sin6_port field contains the 16-bit UDP or TCP port number. This
+ field is used in the same way as the sin_port field of the
+ sockaddr_in structure. The port number is stored in network byte
+ order.
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 7]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ The sin6_flowinfo field is a 32-bit field that contains two pieces of
+ information: the traffic class and the flow label. The contents and
+ interpretation of this member is specified in [1]. The sin6_flowinfo
+ field SHOULD be set to zero by an implementation prior to using the
+ sockaddr_in6 structure by an application on receive operations.
+
+ The sin6_addr field is a single in6_addr structure (defined in the
+ previous section). This field holds one 128-bit IPv6 address. The
+ address is stored in network byte order.
+
+ The ordering of elements in this structure is specifically designed
+ so that when sin6_addr field is aligned on a 64-bit boundary, the
+ start of the structure will also be aligned on a 64-bit boundary.
+ This is done for optimum performance on 64-bit architectures.
+
+ The sin6_scope_id field is a 32-bit integer that identifies a set of
+ interfaces as appropriate for the scope of the address carried in the
+ sin6_addr field. For a link scope sin6_addr sin6_scope_id would be
+ an interface index. For a site scope sin6_addr, sin6_scope_id would
+ be a site identifier. The mapping of sin6_scope_id to an interface
+ or set of interfaces is left to implementation and future
+ specifications on the subject of site identifiers.
+
+ Notice that the sockaddr_in6 structure will normally be larger than
+ the generic sockaddr structure. On many existing implementations the
+ sizeof(struct sockaddr_in) equals sizeof(struct sockaddr), with both
+ being 16 bytes. Any existing code that makes this assumption needs
+ to be examined carefully when converting to IPv6.
+
+3.4 Socket Address Structure for 4.4BSD-Based Systems
+
+ The 4.4BSD release includes a small, but incompatible change to the
+ socket interface. The "sa_family" field of the sockaddr data
+ structure was changed from a 16-bit value to an 8-bit value, and the
+ space saved used to hold a length field, named "sa_len". The
+ sockaddr_in6 data structure given in the previous section cannot be
+ correctly cast into the newer sockaddr data structure. For this
+ reason, the following alternative IPv6 address data structure is
+ provided to be used on systems based on 4.4BSD. It is defined as a
+ result of including the <netinet/in.h> header.
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 8]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+struct sockaddr_in6 {
+ uint8_t sin6_len; /* length of this struct */
+ sa_family_t sin6_family; /* AF_INET6 */
+ in_port_t sin6_port; /* transport layer port # */
+ uint32_t sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ uint32_t sin6_scope_id; /* set of interfaces for a scope */
+};
+
+ The only differences between this data structure and the 4.3BSD
+ variant are the inclusion of the length field, and the change of the
+ family field to a 8-bit data type. The definitions of all the other
+ fields are identical to the structure defined in the previous
+ section.
+
+ Systems that provide this version of the sockaddr_in6 data structure
+ must also declare SIN6_LEN as a result of including the
+ <netinet/in.h> header. This macro allows applications to determine
+ whether they are being built on a system that supports the 4.3BSD or
+ 4.4BSD variants of the data structure.
+
+3.5 The Socket Functions
+
+ Applications call the socket() function to create a socket descriptor
+ that represents a communication endpoint. The arguments to the
+ socket() function tell the system which protocol to use, and what
+ format address structure will be used in subsequent functions. For
+ example, to create an IPv4/TCP socket, applications make the call:
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+
+ To create an IPv4/UDP socket, applications make the call:
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+
+ Applications may create IPv6/TCP and IPv6/UDP sockets by simply using
+ the constant PF_INET6 instead of PF_INET in the first argument. For
+ example, to create an IPv6/TCP socket, applications make the call:
+
+ s = socket(PF_INET6, SOCK_STREAM, 0);
+
+ To create an IPv6/UDP socket, applications make the call:
+
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 9]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ Once the application has created a PF_INET6 socket, it must use the
+ sockaddr_in6 address structure when passing addresses in to the
+ system. The functions that the application uses to pass addresses
+ into the system are:
+
+ bind()
+ connect()
+ sendmsg()
+ sendto()
+
+ The system will use the sockaddr_in6 address structure to return
+ addresses to applications that are using PF_INET6 sockets. The
+ functions that return an address from the system to an application
+ are:
+
+ accept()
+ recvfrom()
+ recvmsg()
+ getpeername()
+ getsockname()
+
+ No changes to the syntax of the socket functions are needed to
+ support IPv6, since all of the "address carrying" functions use an
+ opaque address pointer, and carry an address length as a function
+ argument.
+
+3.6 Compatibility with IPv4 Applications
+
+ In order to support the large base of applications using the original
+ API, system implementations must provide complete source and binary
+ compatibility with the original API. This means that systems must
+ continue to support PF_INET sockets and the sockaddr_in address
+ structure. Applications must be able to create IPv4/TCP and IPv4/UDP
+ sockets using the PF_INET constant in the socket() function, as
+ described in the previous section. Applications should be able to
+ hold a combination of IPv4/TCP, IPv4/UDP, IPv6/TCP and IPv6/UDP
+ sockets simultaneously within the same process.
+
+ Applications using the original API should continue to operate as
+ they did on systems supporting only IPv4. That is, they should
+ continue to interoperate with IPv4 nodes.
+
+3.7 Compatibility with IPv4 Nodes
+
+ The API also provides a different type of compatibility: the ability
+ for IPv6 applications to interoperate with IPv4 applications. This
+ feature uses the IPv4-mapped IPv6 address format defined in the IPv6
+ addressing architecture specification [2]. This address format
+
+
+
+Gilligan, et. al. Informational [Page 10]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ allows the IPv4 address of an IPv4 node to be represented as an IPv6
+ address. The IPv4 address is encoded into the low-order 32 bits of
+ the IPv6 address, and the high-order 96 bits hold the fixed prefix
+ 0:0:0:0:0:FFFF. IPv4- mapped addresses are written as follows:
+
+ ::FFFF:<IPv4-address>
+
+ These addresses can be generated automatically by the
+ getipnodebyname() function when the specified host has only IPv4
+ addresses (as described in Section 6.1).
+
+ Applications may use PF_INET6 sockets to open TCP connections to IPv4
+ nodes, or send UDP packets to IPv4 nodes, by simply encoding the
+ destination's IPv4 address as an IPv4-mapped IPv6 address, and
+ passing that address, within a sockaddr_in6 structure, in the
+ connect() or sendto() call. When applications use PF_INET6 sockets
+ to accept TCP connections from IPv4 nodes, or receive UDP packets
+ from IPv4 nodes, the system returns the peer's address to the
+ application in the accept(), recvfrom(), or getpeername() call using
+ a sockaddr_in6 structure encoded this way.
+
+ Few applications will likely need to know which type of node they are
+ interoperating with. However, for those applications that do need to
+ know, the IN6_IS_ADDR_V4MAPPED() macro, defined in Section 6.7, is
+ provided.
+
+3.8 IPv6 Wildcard Address
+
+ While the bind() function allows applications to select the source IP
+ address of UDP packets and TCP connections, applications often want
+ the system to select the source address for them. With IPv4, one
+ specifies the address as the symbolic constant INADDR_ANY (called the
+ "wildcard" address) in the bind() call, or simply omits the bind()
+ entirely.
+
+ Since the IPv6 address type is a structure (struct in6_addr), a
+ symbolic constant can be used to initialize an IPv6 address variable,
+ but cannot be used in an assignment. Therefore systems provide the
+ IPv6 wildcard address in two forms.
+
+ The first version is a global variable named "in6addr_any" that is an
+ in6_addr structure. The extern declaration for this variable is
+ defined in <netinet/in.h>:
+
+ extern const struct in6_addr in6addr_any;
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 11]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ Applications use in6addr_any similarly to the way they use INADDR_ANY
+ in IPv4. For example, to bind a socket to port number 23, but let
+ the system select the source address, an application could use the
+ following code:
+
+ struct sockaddr_in6 sin6;
+ . . .
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_flowinfo = 0;
+ sin6.sin6_port = htons(23);
+ sin6.sin6_addr = in6addr_any; /* structure assignment */
+ . . .
+ if (bind(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1)
+ . . .
+
+ The other version is a symbolic constant named IN6ADDR_ANY_INIT and
+ is defined in <netinet/in.h>. This constant can be used to
+ initialize an in6_addr structure:
+
+ struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
+
+ Note that this constant can be used ONLY at declaration time. It can
+ not be used to assign a previously declared in6_addr structure. For
+ example, the following code will not work:
+
+ /* This is the WRONG way to assign an unspecified address */
+ struct sockaddr_in6 sin6;
+ . . .
+ sin6.sin6_addr = IN6ADDR_ANY_INIT; /* will NOT compile */
+
+ Be aware that the IPv4 INADDR_xxx constants are all defined in host
+ byte order but the IPv6 IN6ADDR_xxx constants and the IPv6
+ in6addr_xxx externals are defined in network byte order.
+
+3.9 IPv6 Loopback Address
+
+ Applications may need to send UDP packets to, or originate TCP
+ connections to, services residing on the local node. In IPv4, they
+ can do this by using the constant IPv4 address INADDR_LOOPBACK in
+ their connect(), sendto(), or sendmsg() call.
+
+ IPv6 also provides a loopback address to contact local TCP and UDP
+ services. Like the unspecified address, the IPv6 loopback address is
+ provided in two forms -- a global variable and a symbolic constant.
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 12]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ The global variable is an in6_addr structure named
+ "in6addr_loopback." The extern declaration for this variable is
+ defined in <netinet/in.h>:
+
+ extern const struct in6_addr in6addr_loopback;
+
+ Applications use in6addr_loopback as they would use INADDR_LOOPBACK
+ in IPv4 applications (but beware of the byte ordering difference
+ mentioned at the end of the previous section). For example, to open
+ a TCP connection to the local telnet server, an application could use
+ the following code:
+
+ struct sockaddr_in6 sin6;
+ . . .
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_flowinfo = 0;
+ sin6.sin6_port = htons(23);
+ sin6.sin6_addr = in6addr_loopback; /* structure assignment */
+ . . .
+ if (connect(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1)
+ . . .
+
+ The symbolic constant is named IN6ADDR_LOOPBACK_INIT and is defined
+ in <netinet/in.h>. It can be used at declaration time ONLY; for
+ example:
+
+ struct in6_addr loopbackaddr = IN6ADDR_LOOPBACK_INIT;
+
+ Like IN6ADDR_ANY_INIT, this constant cannot be used in an assignment
+ to a previously declared IPv6 address variable.
+
+3.10 Portability Additions
+
+ One simple addition to the sockets API that can help application
+ writers is the "struct sockaddr_storage". This data structure can
+ simplify writing code portable across multiple address families and
+ platforms. This data structure is designed with the following goals.
+
+ - It has a large enough implementation specific maximum size to
+ store the desired set of protocol specific socket address data
+ structures. Specifically, it is at least large enough to
+ accommodate sockaddr_in and sockaddr_in6 and possibly other
+ protocol specific socket addresses too.
+ - It is aligned at an appropriate boundary so protocol specific
+ socket address data structure pointers can be cast to it and
+ access their fields without alignment problems. (e.g. pointers
+ to sockaddr_in6 and/or sockaddr_in can be cast to it and access
+ fields without alignment problems).
+
+
+
+Gilligan, et. al. Informational [Page 13]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ - It has the initial field(s) isomorphic to the fields of the
+ "struct sockaddr" data structure on that implementation which
+ can be used as a discriminants for deriving the protocol in use.
+ These initial field(s) would on most implementations either be a
+ single field of type "sa_family_t" (isomorphic to sa_family
+ field, 16 bits) or two fields of type uint8_t and sa_family_t
+ respectively, (isomorphic to sa_len and sa_family_t, 8 bits
+ each).
+
+ An example implementation design of such a data structure would be as
+ follows.
+
+/*
+ * Desired design of maximum size and alignment
+ */
+#define _SS_MAXSIZE 128 /* Implementation specific max size */
+#define _SS_ALIGNSIZE (sizeof (int64_t))
+ /* Implementation specific desired alignment */
+/*
+ * Definitions used for sockaddr_storage structure paddings design.
+ */
+#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (sa_family_t))
+#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t)+
+ _SS_PAD1SIZE + _SS_ALIGNSIZE))
+struct sockaddr_storage {
+ sa_family_t __ss_family; /* address family */
+ /* Following fields are implementation specific */
+ char __ss_pad1[_SS_PAD1SIZE];
+ /* 6 byte pad, this is to make implementation
+ /* specific pad up to alignment field that */
+ /* follows explicit in the data structure */
+ int64_t __ss_align; /* field to force desired structure */
+ /* storage alignment */
+ char __ss_pad2[_SS_PAD2SIZE];
+ /* 112 byte pad to achieve desired size, */
+ /* _SS_MAXSIZE value minus size of ss_family */
+ /* __ss_pad1, __ss_align fields is 112 */
+};
+
+ On implementations where sockaddr data structure includes a "sa_len",
+ field this data structure would look like this:
+
+/*
+ * Definitions used for sockaddr_storage structure paddings design.
+ */
+#define _SS_PAD1SIZE (_SS_ALIGNSIZE -
+ (sizeof (uint8_t) + sizeof (sa_family_t))
+#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t)+
+
+
+
+Gilligan, et. al. Informational [Page 14]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ _SS_PAD1SIZE + _SS_ALIGNSIZE))
+struct sockaddr_storage {
+ uint8_t __ss_len; /* address length */
+ sa_family_t __ss_family; /* address family */
+ /* Following fields are implementation specific */
+ char __ss_pad1[_SS_PAD1SIZE];
+ /* 6 byte pad, this is to make implementation
+ /* specific pad up to alignment field that */
+ /* follows explicit in the data structure */
+ int64_t __ss_align; /* field to force desired structure */
+ /* storage alignment */
+ char __ss_pad2[_SS_PAD2SIZE];
+ /* 112 byte pad to achieve desired size, */
+ /* _SS_MAXSIZE value minus size of ss_len, */
+ /* __ss_family, __ss_pad1, __ss_align fields is 112 */
+};
+
+ The above example implementation illustrates a data structure which
+ will align on a 64 bit boundary. An implementation specific field
+ "__ss_align" along "__ss_pad1" is used to force a 64-bit alignment
+ which covers proper alignment good enough for needs of sockaddr_in6
+ (IPv6), sockaddr_in (IPv4) address data structures. The size of
+ padding fields __ss_pad1 depends on the chosen alignment boundary.
+ The size of padding field __ss_pad2 depends on the value of overall
+ size chosen for the total size of the structure. This size and
+ alignment are represented in the above example by implementation
+ specific (not required) constants _SS_MAXSIZE (chosen value 128) and
+ _SS_ALIGNMENT (with chosen value 8). Constants _SS_PAD1SIZE (derived
+ value 6) and _SS_PAD2SIZE (derived value 112) are also for
+ illustration and not required. The implementation specific
+ definitions and structure field names above start with an underscore
+ to denote implementation private namespace. Portable code is not
+ expected to access or reference those fields or constants.
+
+ The sockaddr_storage structure solves the problem of declaring
+ storage for automatic variables which is large enough and aligned
+ enough for storing socket address data structure of any family. For
+ example, code with a file descriptor and without the context of the
+ address family can pass a pointer to a variable of this type where a
+ pointer to a socket address structure is expected in calls such as
+ getpeername() and determine the address family by accessing the
+ received content after the call.
+
+ The sockaddr_storage structure may also be useful and applied to
+ certain other interfaces where a generic socket address large enough
+ and aligned for use with multiple address families may be needed. A
+ discussion of those interfaces is outside the scope of this document.
+
+
+
+
+Gilligan, et. al. Informational [Page 15]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ Also, much existing code assumes that any socket address structure
+ can fit in a generic sockaddr structure. While this has been true
+ for IPv4 socket address structures, it has always been false for Unix
+ domain socket address structures (but in practice this has not been a
+ problem) and it is also false for IPv6 socket address structures
+ (which can be a problem).
+
+ So now an application can do the following:
+
+ struct sockaddr_storage __ss;
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *) &__ss;
+
+4. Interface Identification
+
+ This API uses an interface index (a small positive integer) to
+ identify the local interface on which a multicast group is joined
+ (Section 5.3). Additionally, the advanced API [4] uses these same
+ interface indexes to identify the interface on which a datagram is
+ received, or to specify the interface on which a datagram is to be
+ sent.
+
+ Interfaces are normally known by names such as "le0", "sl1", "ppp2",
+ and the like. On Berkeley-derived implementations, when an interface
+ is made known to the system, the kernel assigns a unique positive
+ integer value (called the interface index) to that interface. These
+ are small positive integers that start at 1. (Note that 0 is never
+ used for an interface index.) There may be gaps so that there is no
+ current interface for a particular positive interface index.
+
+ This API defines two functions that map between an interface name and
+ index, a third function that returns all the interface names and
+ indexes, and a fourth function to return the dynamic memory allocated
+ by the previous function. How these functions are implemented is
+ left up to the implementation. 4.4BSD implementations can implement
+ these functions using the existing sysctl() function with the
+ NET_RT_IFLIST command. Other implementations may wish to use ioctl()
+ for this purpose.
+
+4.1 Name-to-Index
+
+ The first function maps an interface name into its corresponding
+ index.
+
+ #include <net/if.h>
+
+ unsigned int if_nametoindex(const char *ifname);
+
+
+
+
+Gilligan, et. al. Informational [Page 16]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ If the specified interface name does not exist, the return value is
+ 0, and errno is set to ENXIO. If there was a system error (such as
+ running out of memory), the return value is 0 and errno is set to the
+ proper value (e.g., ENOMEM).
+
+4.2 Index-to-Name
+
+ The second function maps an interface index into its corresponding
+ name.
+
+ #include <net/if.h>
+
+ char *if_indextoname(unsigned int ifindex, char *ifname);
+
+ The ifname argument must point to a buffer of at least IF_NAMESIZE
+ bytes into which the interface name corresponding to the specified
+ index is returned. (IF_NAMESIZE is also defined in <net/if.h> and
+ its value includes a terminating null byte at the end of the
+ interface name.) This pointer is also the return value of the
+ function. If there is no interface corresponding to the specified
+ index, NULL is returned, and errno is set to ENXIO, if there was a
+ system error (such as running out of memory), if_indextoname returns
+ NULL and errno would be set to the proper value (e.g., ENOMEM).
+
+4.3 Return All Interface Names and Indexes
+
+ The if_nameindex structure holds the information about a single
+ interface and is defined as a result of including the <net/if.h>
+ header.
+
+ struct if_nameindex {
+ unsigned int if_index; /* 1, 2, ... */
+ char *if_name; /* null terminated name: "le0", ... */
+ };
+
+ The final function returns an array of if_nameindex structures, one
+ structure per interface.
+
+ struct if_nameindex *if_nameindex(void);
+
+ The end of the array of structures is indicated by a structure with
+ an if_index of 0 and an if_name of NULL. The function returns a NULL
+ pointer upon an error, and would set errno to the appropriate value.
+
+ The memory used for this array of structures along with the interface
+ names pointed to by the if_name members is obtained dynamically.
+ This memory is freed by the next function.
+
+
+
+
+Gilligan, et. al. Informational [Page 17]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+4.4 Free Memory
+
+ The following function frees the dynamic memory that was allocated by
+ if_nameindex().
+
+ #include <net/if.h>
+
+ void if_freenameindex(struct if_nameindex *ptr);
+
+ The argument to this function must be a pointer that was returned by
+ if_nameindex().
+
+ Currently net/if.h doesn't have prototype definitions for functions
+ and it is recommended that these definitions be defined in net/if.h
+ as well and the struct if_nameindex{}.
+
+5. Socket Options
+
+ A number of new socket options are defined for IPv6. All of these
+ new options are at the IPPROTO_IPV6 level. That is, the "level"
+ parameter in the getsockopt() and setsockopt() calls is IPPROTO_IPV6
+ when using these options. The constant name prefix IPV6_ is used in
+ all of the new socket options. This serves to clearly identify these
+ options as applying to IPv6.
+
+ The declaration for IPPROTO_IPV6, the new IPv6 socket options, and
+ related constants defined in this section are obtained by including
+ the header <netinet/in.h>.
+
+5.1 Unicast Hop Limit
+
+ A new setsockopt() option controls the hop limit used in outgoing
+ unicast IPv6 packets. The name of this option is IPV6_UNICAST_HOPS,
+ and it is used at the IPPROTO_IPV6 layer. The following example
+ illustrates how it is used:
+
+ int hoplimit = 10;
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+ (char *) &hoplimit, sizeof(hoplimit)) == -1)
+ perror("setsockopt IPV6_UNICAST_HOPS");
+
+ When the IPV6_UNICAST_HOPS option is set with setsockopt(), the
+ option value given is used as the hop limit for all subsequent
+ unicast packets sent via that socket. If the option is not set, the
+ system selects a default value. The integer hop limit value (called
+ x) is interpreted as follows:
+
+
+
+
+Gilligan, et. al. Informational [Page 18]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ x < -1: return an error of EINVAL
+ x == -1: use kernel default
+ 0 <= x <= 255: use x
+ x >= 256: return an error of EINVAL
+
+ The IPV6_UNICAST_HOPS option may be used with getsockopt() to
+ determine the hop limit value that the system will use for subsequent
+ unicast packets sent via that socket. For example:
+
+ int hoplimit;
+ size_t len = sizeof(hoplimit);
+
+ if (getsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+ (char *) &hoplimit, &len) == -1)
+ perror("getsockopt IPV6_UNICAST_HOPS");
+ else
+ printf("Using %d for hop limit.\n", hoplimit);
+
+5.2 Sending and Receiving Multicast Packets
+
+ IPv6 applications may send UDP multicast packets by simply specifying
+ an IPv6 multicast address in the address argument of the sendto()
+ function.
+
+ Three socket options at the IPPROTO_IPV6 layer control some of the
+ parameters for sending multicast packets. Setting these options is
+ not required: applications may send multicast packets without using
+ these options. The setsockopt() options for controlling the sending
+ of multicast packets are summarized below. These three options can
+ also be used with getsockopt().
+
+ IPV6_MULTICAST_IF
+
+ Set the interface to use for outgoing multicast packets. The
+ argument is the index of the interface to use.
+
+ Argument type: unsigned int
+
+ IPV6_MULTICAST_HOPS
+
+ Set the hop limit to use for outgoing multicast packets. (Note
+ a separate option - IPV6_UNICAST_HOPS - is provided to set the
+ hop limit to use for outgoing unicast packets.)
+
+ The interpretation of the argument is the same as for the
+ IPV6_UNICAST_HOPS option:
+
+
+
+
+
+Gilligan, et. al. Informational [Page 19]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ x < -1: return an error of EINVAL
+ x == -1: use kernel default
+ 0 <= x <= 255: use x
+ x >= 256: return an error of EINVAL
+
+ If IPV6_MULTICAST_HOPS is not set, the default is 1
+ (same as IPv4 today)
+
+ Argument type: int
+
+ IPV6_MULTICAST_LOOP
+
+ If a multicast datagram is sent to a group to which the sending
+ host itself belongs (on the outgoing interface), a copy of the
+ datagram is looped back by the IP layer for local delivery if
+ this option is set to 1. If this option is set to 0 a copy
+ is not looped back. Other option values return an error of
+ EINVAL.
+
+ If IPV6_MULTICAST_LOOP is not set, the default is 1 (loopback;
+ same as IPv4 today).
+
+ Argument type: unsigned int
+
+ The reception of multicast packets is controlled by the two
+ setsockopt() options summarized below. An error of EOPNOTSUPP is
+ returned if these two options are used with getsockopt().
+
+ IPV6_JOIN_GROUP
+
+ Join a multicast group on a specified local interface. If the
+ interface index is specified as 0, the kernel chooses the local
+ interface. For example, some kernels look up the multicast
+ group in the normal IPv6 routing table and using the resulting
+ interface.
+
+ Argument type: struct ipv6_mreq
+
+ IPV6_LEAVE_GROUP
+
+ Leave a multicast group on a specified interface.
+
+ Argument type: struct ipv6_mreq
+
+ The argument type of both of these options is the ipv6_mreq structure,
+ defined as a result of including the <netinet/in.h> header;
+
+
+
+
+
+Gilligan, et. al. Informational [Page 20]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ struct ipv6_mreq {
+ struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast addr */
+ unsigned int ipv6mr_interface; /* interface index */
+ };
+
+ Note that to receive multicast datagrams a process must join the
+ multicast group and bind the UDP port to which datagrams will be
+ sent. Some processes also bind the multicast group address to the
+ socket, in addition to the port, to prevent other datagrams destined
+ to that same port from being delivered to the socket.
+
+6. Library Functions
+
+ New library functions are needed to perform a variety of operations
+ with IPv6 addresses. Functions are needed to lookup IPv6 addresses
+ in the Domain Name System (DNS). Both forward lookup (nodename-to-
+ address translation) and reverse lookup (address-to-nodename
+ translation) need to be supported. Functions are also needed to
+ convert IPv6 addresses between their binary and textual form.
+
+ We note that the two existing functions, gethostbyname() and
+ gethostbyaddr(), are left as-is. New functions are defined to handle
+ both IPv4 and IPv6 addresses.
+
+6.1 Nodename-to-Address Translation
+
+ The commonly used function gethostbyname() is inadequate for many
+ applications, first because it provides no way for the caller to
+ specify anything about the types of addresses desired (IPv4 only,
+ IPv6 only, IPv4-mapped IPv6 are OK, etc.), and second because many
+ implementations of this function are not thread safe. RFC 2133
+ defined a function named gethostbyname2() but this function was also
+ inadequate, first because its use required setting a global option
+ (RES_USE_INET6) when IPv6 addresses were required, and second because
+ a flag argument is needed to provide the caller with additional
+ control over the types of addresses required.
+
+ The following function is new and must be thread safe:
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+ struct hostent *getipnodebyname(const char *name, int af, int flags
+ int *error_num);
+
+ The name argument can be either a node name or a numeric address
+ string (i.e., a dotted-decimal IPv4 address or an IPv6 hex address).
+ The af argument specifies the address family, either AF_INET or
+
+
+
+Gilligan, et. al. Informational [Page 21]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ AF_INET6. The error_num value is returned to the caller, via a
+ pointer, with the appropriate error code in error_num, to support
+ thread safe error code returns. error_num will be set to one of the
+ following values:
+
+ HOST_NOT_FOUND
+
+ No such host is known.
+
+ NO_ADDRESS
+
+ The server recognised the request and the name but no address is
+ available. Another type of request to the name server for the
+ domain might return an answer.
+
+ NO_RECOVERY
+
+ An unexpected server failure occurred which cannot be recovered.
+
+ TRY_AGAIN
+
+ A temporary and possibly transient error occurred, such as a
+ failure of a server to respond.
+
+ The flags argument specifies the types of addresses that are searched
+ for, and the types of addresses that are returned. We note that a
+ special flags value of AI_DEFAULT (defined below) should handle most
+ applications.
+
+ That is, porting simple applications to use IPv6 replaces the call
+
+ hptr = gethostbyname(name);
+
+ with
+
+ hptr = getipnodebyname(name, AF_INET6, AI_DEFAULT, &error_num);
+
+ and changes any subsequent error diagnosis code to use error_num
+ instead of externally declared variables, such as h_errno.
+
+ Applications desiring finer control over the types of addresses
+ searched for and returned, can specify other combinations of the
+ flags argument.
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 22]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ A flags of 0 implies a strict interpretation of the af argument:
+
+ - If flags is 0 and af is AF_INET, then the caller wants only
+ IPv4 addresses. A query is made for A records. If successful,
+ the IPv4 addresses are returned and the h_length member of the
+ hostent structure will be 4, else the function returns a NULL
+ pointer.
+
+ - If flags is 0 and if af is AF_INET6, then the caller wants only
+ IPv6 addresses. A query is made for AAAA records. If
+ successful, the IPv6 addresses are returned and the h_length
+ member of the hostent structure will be 16, else the function
+ returns a NULL pointer.
+
+ Other constants can be logically-ORed into the flags argument, to
+ modify the behavior of the function.
+
+ - If the AI_V4MAPPED flag is specified along with an af of
+ AF_INET6, then the caller will accept IPv4-mapped IPv6
+ addresses. That is, if no AAAA records are found then a query
+ is made for A records and any found are returned as IPv4-mapped
+ IPv6 addresses (h_length will be 16). The AI_V4MAPPED flag is
+ ignored unless af equals AF_INET6.
+
+ - The AI_ALL flag is used in conjunction with the AI_V4MAPPED
+ flag, and is only used with the IPv6 address family. When AI_ALL
+ is logically or'd with AI_V4MAPPED flag then the caller wants
+ all addresses: IPv6 and IPv4-mapped IPv6. A query is first made
+ for AAAA records and if successful, the IPv6 addresses are
+ returned. Another query is then made for A records and any found
+ are returned as IPv4-mapped IPv6 addresses. h_length will be 16.
+ Only if both queries fail does the function return a NULL pointer.
+ This flag is ignored unless af equals AF_INET6.
+
+ - The AI_ADDRCONFIG flag specifies that a query for AAAA records
+ should occur only if the node has at least one IPv6 source
+ address configured and a query for A records should occur only
+ if the node has at least one IPv4 source address configured.
+
+ For example, if the node has no IPv6 source addresses
+ configured, and af equals AF_INET6, and the node name being
+ looked up has both AAAA and A records, then:
+
+ (a) if only AI_ADDRCONFIG is specified, the function
+ returns a NULL pointer;
+ (b) if AI_ADDRCONFIG | AI_V4MAPPED is specified, the A
+ records are returned as IPv4-mapped IPv6 addresses;
+
+
+
+
+Gilligan, et. al. Informational [Page 23]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ The special flags value of AI_DEFAULT is defined as
+
+ #define AI_DEFAULT (AI_V4MAPPED | AI_ADDRCONFIG)
+
+ We noted that the getipnodebyname() function must allow the name
+ argument to be either a node name or a literal address string (i.e.,
+ a dotted-decimal IPv4 address or an IPv6 hex address). This saves
+ applications from having to call inet_pton() to handle literal
+ address strings.
+
+ There are four scenarios based on the type of literal address string
+ and the value of the af argument.
+
+ The two simple cases are:
+
+ When name is a dotted-decimal IPv4 address and af equals AF_INET, or
+ when name is an IPv6 hex address and af equals AF_INET6. The members
+ of the returned hostent structure are: h_name points to a copy of the
+ name argument, h_aliases is a NULL pointer, h_addrtype is a copy of
+ the af argument, h_length is either 4 (for AF_INET) or 16 (for
+ AF_INET6), h_addr_list[0] is a pointer to the 4-byte or 16-byte
+ binary address, and h_addr_list[1] is a NULL pointer.
+
+ When name is a dotted-decimal IPv4 address and af equals AF_INET6,
+ and flags equals AI_V4MAPPED, an IPv4-mapped IPv6 address is
+ returned: h_name points to an IPv6 hex address containing the IPv4-
+ mapped IPv6 address, h_aliases is a NULL pointer, h_addrtype is
+ AF_INET6, h_length is 16, h_addr_list[0] is a pointer to the 16-byte
+ binary address, and h_addr_list[1] is a NULL pointer. If AI_V4MAPPED
+ is set (with or without AI_ALL) return IPv4-mapped otherwise return
+ NULL.
+
+ It is an error when name is an IPv6 hex address and af equals
+ AF_INET. The function's return value is a NULL pointer and error_num
+ equals HOST_NOT_FOUND.
+
+6.2 Address-To-Nodename Translation
+
+ The following function has the same arguments as the existing
+ gethostbyaddr() function, but adds an error number.
+
+ #include <sys/socket.h> #include <netdb.h>
+
+ struct hostent *getipnodebyaddr(const void *src, size_t len,
+ int af, int *error_num);
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 24]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ As with getipnodebyname(), getipnodebyaddr() must be thread safe.
+ The error_num value is returned to the caller with the appropriate
+ error code, to support thread safe error code returns. The following
+ error conditions may be returned for error_num:
+
+ HOST_NOT_FOUND
+
+ No such host is known.
+
+ NO_ADDRESS
+
+ The server recognized the request and the name but no address
+ is available. Another type of request to the name server for
+ the domain might return an answer.
+
+ NO_RECOVERY
+
+ An unexpected server failure occurred which cannot be
+ recovered.
+
+ TRY_AGAIN
+
+ A temporary and possibly transient error occurred, such as a
+ failure of a server to respond.
+
+ One possible source of confusion is the handling of IPv4-mapped IPv6
+ addresses and IPv4-compatible IPv6 addresses, but the following logic
+ should apply.
+
+ 1. If af is AF_INET6, and if len equals 16, and if the IPv6
+ address is an IPv4-mapped IPv6 address or an IPv4-compatible
+ IPv6 address, then skip over the first 12 bytes of the IPv6
+ address, set af to AF_INET, and set len to 4.
+
+ 2. If af is AF_INET, lookup the name for the given IPv4 address
+ (e.g., query for a PTR record in the in-addr.arpa domain).
+
+ 3. If af is AF_INET6, lookup the name for the given IPv6 address
+ (e.g., query for a PTR record in the ip6.int domain).
+
+ 4. If the function is returning success, then the single address
+ that is returned in the hostent structure is a copy of the
+ first argument to the function with the same address family
+ that was passed as an argument to this function.
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 25]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ All four steps listed are performed, in order. Also note that the
+ IPv6 hex addresses "::" and "::1" MUST NOT be treated as IPv4-
+ compatible addresses, and if the address is "::", HOST_NOT_FOUND MUST
+ be returned and a query of the address not performed.
+
+ Also for the macro in section 6.7 IN6_IS_ADDR_V4COMPAT MUST return
+ false for "::" and "::1".
+
+6.3 Freeing memory for getipnodebyname and getipnodebyaddr
+
+ The hostent structure does not change from its existing definition.
+ This structure, and the information pointed to by this structure, are
+ dynamically allocated by getipnodebyname and getipnodebyaddr. The
+ following function frees this memory:
+
+ #include <netdb.h>
+
+ void freehostent(struct hostent *ptr);
+
+6.4 Protocol-Independent Nodename and Service Name Translation
+
+ Nodename-to-address translation is done in a protocol-independent
+ fashion using the getaddrinfo() function that is taken from the
+ Institute of Electrical and Electronic Engineers (IEEE) POSIX 1003.1g
+ (Protocol Independent Interfaces) draft specification [3].
+
+ The official specification for this function will be the final POSIX
+ standard, with the following additional requirements:
+
+ - getaddrinfo() (along with the getnameinfo() function described
+ in the next section) must be thread safe.
+
+ - The AI_NUMERICHOST is new with this document.
+
+ - All fields in socket address structures returned by
+ getaddrinfo() that are not filled in through an explicit
+ argument (e.g., sin6_flowinfo and sin_zero) must be set to 0.
+ (This makes it easier to compare socket address structures.)
+
+ - getaddrinfo() must fill in the length field of a socket address
+ structure (e.g., sin6_len) on systems that support this field.
+
+ We are providing this independent description of the function because
+ POSIX standards are not freely available (as are IETF documents).
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+
+
+
+Gilligan, et. al. Informational [Page 26]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ int getaddrinfo(const char *nodename, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res);
+
+ The addrinfo structure is defined as a result of including the
+ <netdb.h> header.
+
+ struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
+ 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 nodename */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+ };
+
+ The return value from the function is 0 upon success or a nonzero
+ error code. The following names are the nonzero error codes from
+ getaddrinfo(), and are defined in <netdb.h>:
+
+ EAI_ADDRFAMILY address family for nodename not supported
+ EAI_AGAIN temporary failure in name resolution
+ EAI_BADFLAGS invalid value for ai_flags
+ EAI_FAIL non-recoverable failure in name resolution
+ EAI_FAMILY ai_family not supported
+ EAI_MEMORY memory allocation failure
+ EAI_NODATA no address associated with nodename
+ EAI_NONAME nodename nor servname provided, or not known
+ EAI_SERVICE servname not supported for ai_socktype
+ EAI_SOCKTYPE ai_socktype not supported
+ EAI_SYSTEM system error returned in errno
+
+ The nodename and servname arguments are pointers to null-terminated
+ strings or NULL. One or both of these two arguments must be a non-
+ NULL pointer. In the normal client scenario, both the nodename and
+ servname are specified. In the normal server scenario, only the
+ servname is specified. A non-NULL nodename string can be either a
+ node name or a numeric host address string (i.e., a dotted-decimal
+ IPv4 address or an IPv6 hex address). A non-NULL servname string can
+ be either a service name or a decimal port number.
+
+ The caller can optionally pass an addrinfo structure, pointed to by
+ the third argument, to provide hints concerning the type of socket
+ that the caller supports. In this hints structure all members other
+ than ai_flags, ai_family, ai_socktype, and ai_protocol must be zero
+ or a NULL pointer. A value of PF_UNSPEC for ai_family means the
+
+
+
+Gilligan, et. al. Informational [Page 27]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ caller will accept any protocol family. A value of 0 for ai_socktype
+ means the caller will accept any socket type. A value of 0 for
+ ai_protocol means the caller will accept any protocol. For example,
+ if the caller handles only TCP and not UDP, then the ai_socktype
+ member of the hints structure should be set to SOCK_STREAM when
+ getaddrinfo() is called. If the caller handles only IPv4 and not
+ IPv6, then the ai_family member of the hints structure should be set
+ to PF_INET when getaddrinfo() is called. If the third argument to
+ getaddrinfo() is a NULL pointer, this is the same as if the caller
+ had filled in an addrinfo structure initialized to zero with
+ ai_family set to PF_UNSPEC.
+
+ Upon successful return a pointer to a linked list of one or more
+ addrinfo structures is returned through the final argument. The
+ caller can process each addrinfo structure in this list by following
+ the ai_next pointer, until a NULL pointer is encountered. In each
+ returned addrinfo structure the three members ai_family, ai_socktype,
+ and ai_protocol are the corresponding arguments for a call to the
+ socket() function. In each addrinfo structure the ai_addr member
+ points to a filled-in socket address structure whose length is
+ specified by the ai_addrlen member.
+
+ If the AI_PASSIVE bit is set in the ai_flags member of the hints
+ structure, then the caller plans to use the returned socket address
+ structure in a call to bind(). In this case, if the nodename
+ 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.
+
+ If the AI_PASSIVE bit is not set in the ai_flags member of the hints
+ structure, then the returned socket address structure will be ready
+ for a call to connect() (for a connection-oriented protocol) or
+ either connect(), sendto(), or sendmsg() (for a connectionless
+ protocol). In this case, if the nodename argument is a NULL pointer,
+ then the IP address portion of the socket address structure will be
+ set to the loopback address.
+
+ If the AI_CANONNAME bit is set in the ai_flags member of the hints
+ structure, then upon successful return the ai_canonname member of the
+ first addrinfo structure in the linked list will point to a null-
+ terminated string containing the canonical name of the specified
+ nodename.
+
+ If the AI_NUMERICHOST bit is set in the ai_flags member of the hints
+ structure, then a non-NULL nodename string must be a numeric host
+ address string. Otherwise an error of EAI_NONAME is returned. This
+ flag prevents any type of name resolution service (e.g., the DNS)
+ from being called.
+
+
+
+Gilligan, et. al. Informational [Page 28]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ All of the information returned by getaddrinfo() is dynamically
+ allocated: the addrinfo structures, and the socket address structures
+ and canonical node name strings pointed to by the addrinfo
+ structures. To return this information to the system the function
+ freeaddrinfo() is called:
+
+ #include <sys/socket.h> #include <netdb.h>
+
+ void freeaddrinfo(struct addrinfo *ai);
+
+ The addrinfo structure pointed to by the ai argument is freed, along
+ with any dynamic storage pointed to by the structure. This operation
+ is repeated until a NULL ai_next pointer is encountered.
+
+ To aid applications in printing error messages based on the EAI_xxx
+ codes returned by getaddrinfo(), the following function is defined.
+
+ #include <sys/socket.h> #include <netdb.h>
+
+ char *gai_strerror(int ecode);
+
+ The argument is one of the EAI_xxx values defined earlier and the
+ return value points to a string describing the error. If the
+ argument is not one of the EAI_xxx values, the function still returns
+ a pointer to a string whose contents indicate an unknown error.
+
+6.5 Socket Address Structure to Nodename and Service Name
+
+ The POSIX 1003.1g specification includes no function to perform the
+ reverse conversion from getaddrinfo(): to look up a nodename and
+ service name, given the binary address and port. Therefore, we
+ define the following function:
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+ int getnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen,
+ char *serv, size_t servlen,
+ int flags);
+
+ This function looks up an IP address and port number provided by the
+ caller in the DNS and system-specific database, and returns text
+ strings for both in buffers provided by the caller. The function
+ indicates successful completion by a zero return value; a non-zero
+ return value indicates failure.
+
+
+
+
+
+Gilligan, et. al. Informational [Page 29]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ The first argument, sa, points to either a sockaddr_in structure (for
+ IPv4) or a sockaddr_in6 structure (for IPv6) that holds the IP
+ address and port number. The salen argument gives the length of the
+ sockaddr_in or sockaddr_in6 structure.
+
+ The function returns the nodename associated with the IP address in
+ the buffer pointed to by the host argument. The caller provides the
+ size of this buffer via the hostlen argument. The service name
+ associated with the port number is returned in the buffer pointed to
+ by serv, and the servlen argument gives the length of this buffer.
+ The caller specifies not to return either string by providing a zero
+ value for the hostlen or servlen arguments. Otherwise, the caller
+ must provide buffers large enough to hold the nodename and the
+ service name, including the terminating null characters.
+
+ Unfortunately most systems do not provide constants that specify the
+ maximum size of either a fully-qualified domain name or a service
+ name. Therefore to aid the application in allocating buffers for
+ these two returned strings the following constants are defined in
+ <netdb.h>:
+
+ #define NI_MAXHOST 1025
+ #define NI_MAXSERV 32
+
+ The first value is actually defined as the constant MAXDNAME in recent
+ versions of BIND's <arpa/nameser.h> header (older versions of BIND
+ define this constant to be 256) and the second is a guess based on the
+ services listed in the current Assigned Numbers RFC.
+
+ The final argument is a flag that changes the default actions of this
+ function. By default the fully-qualified domain name (FQDN) for the
+ host is looked up in the DNS and returned. If the flag bit NI_NOFQDN
+ is set, only the nodename portion of the FQDN is returned for local
+ hosts.
+
+ If the flag bit NI_NUMERICHOST is set, or if the host's name cannot be
+ located in the DNS, the numeric form of the host's address is returned
+ instead of its name (e.g., by calling inet_ntop() instead of
+ getipnodebyaddr()). If the flag bit NI_NAMEREQD is set, an error is
+ returned if the host's name cannot be located in the DNS.
+
+ If the flag bit NI_NUMERICSERV is set, the numeric form of the service
+ address is returned (e.g., its port number) instead of its name. The
+ two NI_NUMERICxxx flags are required to support the "-n" flag that
+ many commands provide.
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 30]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ A fifth flag bit, NI_DGRAM, specifies that the service 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 (e.g. 512-514) that have different services for UDP
+ and TCP.
+
+ These NI_xxx flags are defined in <netdb.h> along with the AI_xxx
+ flags already defined for getaddrinfo().
+
+6.6 Address Conversion Functions
+
+ The two functions inet_addr() and inet_ntoa() convert an IPv4 address
+ between binary and text form. IPv6 applications need similar
+ functions. The following two functions convert both IPv6 and IPv4
+ addresses:
+
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+
+ int inet_pton(int af, const char *src, void *dst);
+
+ const char *inet_ntop(int af, const void *src,
+ char *dst, size_t size);
+
+ The inet_pton() function converts an address in its standard text
+ presentation form into its numeric binary form. The af argument
+ specifies the family of the address. Currently the AF_INET and
+ AF_INET6 address families are supported. The src argument points to
+ the string being passed in. The dst argument points to a buffer into
+ which the function stores the numeric address. The address is
+ returned in network byte order. Inet_pton() returns 1 if the
+ conversion succeeds, 0 if the input is not a valid IPv4 dotted-
+ decimal string or a valid IPv6 address string, or -1 with errno set
+ to EAFNOSUPPORT if the af argument is unknown. The calling
+ application must ensure that the buffer referred to by dst is large
+ enough to hold the numeric address (e.g., 4 bytes for AF_INET or 16
+ bytes for AF_INET6).
+
+ If the af argument is AF_INET, the function accepts a string in the
+ standard IPv4 dotted-decimal form:
+
+ ddd.ddd.ddd.ddd
+
+ where ddd is a one to three digit decimal number between 0 and 255.
+ Note that many implementations of the existing inet_addr() and
+ inet_aton() functions accept nonstandard input: octal numbers,
+ hexadecimal numbers, and fewer than four numbers. inet_pton() does
+ not accept these formats.
+
+
+
+Gilligan, et. al. Informational [Page 31]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ If the af argument is AF_INET6, then the function accepts a string in
+ one of the standard IPv6 text forms defined in Section 2.2 of the
+ addressing architecture specification [2].
+
+ The inet_ntop() function converts a numeric address into a text
+ string suitable for presentation. The af argument specifies the
+ family of the address. This can be AF_INET or AF_INET6. The src
+ argument points to a buffer holding an IPv4 address if the af
+ argument is AF_INET, or an IPv6 address if the af argument is
+ AF_INET6, the address must be in network byte order. The dst
+ argument points to a buffer where the function will store the
+ resulting text string. The size argument specifies the size of this
+ buffer. The application must specify a non-NULL dst argument. For
+ IPv6 addresses, the buffer must be at least 46-octets. For IPv4
+ addresses, the buffer must be at least 16-octets. In order to allow
+ applications to easily declare buffers of the proper size to store
+ IPv4 and IPv6 addresses in string form, the following two constants
+ are defined in <netinet/in.h>:
+
+ #define INET_ADDRSTRLEN 16
+ #define INET6_ADDRSTRLEN 46
+
+ The inet_ntop() function returns a pointer to the buffer containing
+ the text string if the conversion succeeds, and NULL otherwise. Upon
+ failure, errno is set to EAFNOSUPPORT if the af argument is invalid or
+ ENOSPC if the size of the result buffer is inadequate.
+
+6.7 Address Testing Macros
+
+ The following macros can be used to test for special IPv6 addresses.
+
+ #include <netinet/in.h>
+
+ int IN6_IS_ADDR_UNSPECIFIED (const struct in6_addr *);
+ int IN6_IS_ADDR_LOOPBACK (const struct in6_addr *);
+ int IN6_IS_ADDR_MULTICAST (const struct in6_addr *);
+ int IN6_IS_ADDR_LINKLOCAL (const struct in6_addr *);
+ int IN6_IS_ADDR_SITELOCAL (const struct in6_addr *);
+ int IN6_IS_ADDR_V4MAPPED (const struct in6_addr *);
+ int IN6_IS_ADDR_V4COMPAT (const struct in6_addr *);
+
+ int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
+ int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
+ int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
+ int IN6_IS_ADDR_MC_ORGLOCAL (const struct in6_addr *);
+ int IN6_IS_ADDR_MC_GLOBAL (const struct in6_addr *);
+
+
+
+
+
+Gilligan, et. al. Informational [Page 32]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ The first seven macros return true if the address is of the specified
+ type, or false otherwise. The last five test the scope of a
+ multicast address and return true if the address is a multicast
+ address of the specified scope or false if the address is either not
+ a multicast address or not of the specified scope. Note that
+ IN6_IS_ADDR_LINKLOCAL and IN6_IS_ADDR_SITELOCAL return true only for
+ the two local-use IPv6 unicast addresses. These two macros do not
+ return true for IPv6 multicast addresses of either link-local scope
+ or site-local scope.
+
+7. Summary of New Definitions
+
+ The following list summarizes the constants, structure, and extern
+ definitions discussed in this memo, sorted by header.
+
+ <net/if.h> IF_NAMESIZE
+ <net/if.h> struct if_nameindex{};
+
+ <netdb.h> AI_ADDRCONFIG
+ <netdb.h> AI_DEFAULT
+ <netdb.h> AI_ALL
+ <netdb.h> AI_CANONNAME
+ <netdb.h> AI_NUMERICHOST
+ <netdb.h> AI_PASSIVE
+ <netdb.h> AI_V4MAPPED
+ <netdb.h> EAI_ADDRFAMILY
+ <netdb.h> EAI_AGAIN
+ <netdb.h> EAI_BADFLAGS
+ <netdb.h> EAI_FAIL
+ <netdb.h> EAI_FAMILY
+ <netdb.h> EAI_MEMORY
+ <netdb.h> EAI_NODATA
+ <netdb.h> EAI_NONAME
+ <netdb.h> EAI_SERVICE
+ <netdb.h> EAI_SOCKTYPE
+ <netdb.h> EAI_SYSTEM
+ <netdb.h> NI_DGRAM
+ <netdb.h> NI_MAXHOST
+ <netdb.h> NI_MAXSERV
+ <netdb.h> NI_NAMEREQD
+ <netdb.h> NI_NOFQDN
+ <netdb.h> NI_NUMERICHOST
+ <netdb.h> NI_NUMERICSERV
+ <netdb.h> struct addrinfo{};
+
+ <netinet/in.h> IN6ADDR_ANY_INIT
+ <netinet/in.h> IN6ADDR_LOOPBACK_INIT
+ <netinet/in.h> INET6_ADDRSTRLEN
+
+
+
+Gilligan, et. al. Informational [Page 33]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ <netinet/in.h> INET_ADDRSTRLEN
+ <netinet/in.h> IPPROTO_IPV6
+ <netinet/in.h> IPV6_JOIN_GROUP
+ <netinet/in.h> IPV6_LEAVE_GROUP
+ <netinet/in.h> IPV6_MULTICAST_HOPS
+ <netinet/in.h> IPV6_MULTICAST_IF
+ <netinet/in.h> IPV6_MULTICAST_LOOP
+ <netinet/in.h> IPV6_UNICAST_HOPS
+ <netinet/in.h> SIN6_LEN
+ <netinet/in.h> extern const struct in6_addr in6addr_any;
+ <netinet/in.h> extern const struct in6_addr in6addr_loopback;
+ <netinet/in.h> struct in6_addr{};
+ <netinet/in.h> struct ipv6_mreq{};
+ <netinet/in.h> struct sockaddr_in6{};
+
+ <sys/socket.h> AF_INET6
+ <sys/socket.h> PF_INET6
+ <sys/socket.h> struct sockaddr_storage;
+
+ The following list summarizes the function and macro prototypes
+ discussed in this memo, sorted by header.
+
+<arpa/inet.h> int inet_pton(int, const char *, void *);
+<arpa/inet.h> const char *inet_ntop(int, const void *,
+ char *, size_t);
+
+<net/if.h> char *if_indextoname(unsigned int, char *);
+<net/if.h> unsigned int if_nametoindex(const char *);
+<net/if.h> void if_freenameindex(struct if_nameindex *);
+<net/if.h> struct if_nameindex *if_nameindex(void);
+
+<netdb.h> int getaddrinfo(const char *, const char *,
+ const struct addrinfo *,
+ struct addrinfo **);
+<netdb.h> int getnameinfo(const struct sockaddr *, socklen_t,
+ char *, size_t, char *, size_t, int);
+<netdb.h> void freeaddrinfo(struct addrinfo *);
+<netdb.h> char *gai_strerror(int);
+<netdb.h> struct hostent *getipnodebyname(const char *, int, int,
+ int *);
+<netdb.h> struct hostent *getipnodebyaddr(const void *, size_t,
+ int, int *);
+<netdb.h> void freehostent(struct hostent *);
+
+<netinet/in.h> int IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_LOOPBACK(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_GLOBAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
+
+
+
+Gilligan, et. al. Informational [Page 34]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+<netinet/in.h> int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_ORGLOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MULTICAST(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_SITELOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_UNSPECIFIED(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_V4COMPAT(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_V4MAPPED(const struct in6_addr *);
+
+8. Security Considerations
+
+ IPv6 provides a number of new security mechanisms, many of which need
+ to be accessible to applications. Companion memos detailing the
+ extensions to the socket interfaces to support IPv6 security are
+ being written.
+
+9. Year 2000 Considerations
+
+ There are no issues for this memo concerning the Year 2000 issue
+ regarding the use of dates.
+
+Changes From RFC 2133
+
+ Changes made in the March 1998 Edition (-01 draft):
+
+ Changed all "hostname" to "nodename" for consistency with other
+ IPv6 documents.
+
+ Section 3.3: changed comment for sin6_flowinfo to be "traffic
+ class & flow info" and updated corresponding text description to
+ current definition of these two fields.
+
+ Section 3.10 ("Portability Additions") is new.
+
+ Section 6: a new paragraph was added reiterating that the existing
+ gethostbyname() and gethostbyaddr() are not changed.
+
+ Section 6.1: change gethostbyname3() to getnodebyname(). Add
+ AI_DEFAULT to handle majority of applications. Renamed
+ AI_V6ADDRCONFIG to AI_ADDRCONFIG and define it for A records and
+ IPv4 addresses too. Defined exactly what getnodebyname() must
+ return if the name argument is a numeric address string.
+
+ Section 6.2: change gethostbyaddr() to getnodebyaddr(). Reword
+ items 2 and 3 in the description of how to handle IPv4-mapped and
+ IPv4- compatible addresses to "lookup a name" for a given address,
+ instead of specifying what type of DNS query to issue.
+
+
+
+
+Gilligan, et. al. Informational [Page 35]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ Section 6.3: added two more requirements to getaddrinfo().
+
+ Section 7: added the following constants to the list for
+ <netdb.h>: AI_ADDRCONFIG, AI_ALL, and AI_V4MAPPED. Add union
+ sockaddr_union and SA_LEN to the lists for <sys/socket.h>.
+
+ Updated references.
+
+ Changes made in the November 1997 Edition (-00 draft):
+
+ The data types have been changed to conform with Draft 6.6 of the
+ Posix 1003.1g standard.
+
+ Section 3.2: data type of s6_addr changed to "uint8_t".
+
+ Section 3.3: data type of sin6_family changed to "sa_family_t".
+ data type of sin6_port changed to "in_port_t", data type of
+ sin6_flowinfo changed to "uint32_t".
+
+ Section 3.4: same as Section 3.3, plus data type of sin6_len
+ changed to "uint8_t".
+
+ Section 6.2: first argument of gethostbyaddr() changed from "const
+ char *" to "const void *" and second argument changed from "int"
+ to "size_t".
+
+ Section 6.4: second argument of getnameinfo() changed from
+ "size_t" to "socklen_t".
+
+ The wording was changed when new structures were defined, to be
+ more explicit as to which header must be included to define the
+ structure:
+
+ Section 3.2 (in6_addr{}), Section 3.3 (sockaddr_in6{}), Section
+ 3.4 (sockaddr_in6{}), Section 4.3 (if_nameindex{}), Section 5.3
+ (ipv6_mreq{}), and Section 6.3 (addrinfo{}).
+
+ Section 4: NET_RT_LIST changed to NET_RT_IFLIST.
+
+ Section 5.1: The IPV6_ADDRFORM socket option was removed.
+
+ Section 5.3: Added a note that an option value other than 0 or 1
+ for IPV6_MULTICAST_LOOP returns an error. Added a note that
+ IPV6_MULTICAST_IF, IPV6_MULTICAST_HOPS, and IPV6_MULTICAST_LOOP
+ can also be used with getsockopt(), but IPV6_ADD_MEMBERSHIP and
+ IPV6_DROP_MEMBERSHIP cannot be used with getsockopt().
+
+
+
+
+
+Gilligan, et. al. Informational [Page 36]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ Section 6.1: Removed the description of gethostbyname2() and its
+ associated RES_USE_INET6 option, replacing it with
+ gethostbyname3().
+
+ Section 6.2: Added requirement that gethostbyaddr() be thread
+ safe. Reworded step 4 to avoid using the RES_USE_INET6 option.
+
+ Section 6.3: Added the requirement that getaddrinfo() and
+ getnameinfo() be thread safe. Added the AI_NUMERICHOST flag.
+
+ Section 6.6: Added clarification about IN6_IS_ADDR_LINKLOCAL and
+ IN6_IS_ADDR_SITELOCAL macros.
+
+ Changes made to the draft -01 specification Sept 98
+
+ Changed priority to traffic class in the spec.
+
+ Added the need for scope identification in section 2.1.
+
+ Added sin6_scope_id to struct sockaddr_in6 in sections 3.3 and
+ 3.4.
+
+ Changed 3.10 to use generic storage structure to support holding
+ IPv6 addresses and removed the SA_LEN macro.
+
+ Distinguished between invalid input parameters and system failures
+ for Interface Identification in Section 4.1 and 4.2.
+
+ Added defaults for multicast operations in section 5.2 and changed
+ the names from ADD to JOIN and DROP to LEAVE to be consistent with
+ IPv6 multicast terminology.
+
+ Changed getnodebyname to getipnodebyname, getnodebyaddr to
+ getipnodebyaddr, and added MT safe error code to function
+ parameters in section 6.
+
+ Moved freehostent to its own sub-section after getipnodebyaddr now
+ 6.3 (so this bumps all remaining sections in section 6.
+
+ Clarified the use of AI_ALL and AI_V4MAPPED that these are
+ dependent on the AF parameter and must be used as a conjunction in
+ section 6.1.
+
+ Removed the restriction that literal addresses cannot be used with
+ a flags argument in section 6.1.
+
+ Added Year 2000 Section to the draft
+
+
+
+
+Gilligan, et. al. Informational [Page 37]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ Deleted Reference to the following because the attached is deleted
+ from the ID directory and has expired. But the logic from the
+ aforementioned draft still applies, so that was kept in Section
+ 6.2 bullets after 3rd paragraph.
+
+ [7] P. Vixie, "Reverse Name Lookups of Encapsulated IPv4
+ Addresses in IPv6", Internet-Draft, <draft-vixie-ipng-
+ ipv4ptr-00.txt>, May 1996.
+
+ Deleted the following reference as it is no longer referenced.
+ And the draft has expired.
+
+ [3] D. McDonald, "A Simple IP Security API Extension to BSD
+ Sockets", Internet-Draft, <draft-mcdonald-simple-ipsec-api-
+ 01.txt>, March 1997.
+
+ Deleted the following reference as it is no longer referenced.
+
+ [4] C. Metz, "Network Security API for Sockets",
+ Internet-Draft, <draft-metz-net-security-api-01.txt>, January
+ 1998.
+
+ Update current references to current status.
+
+ Added alignment notes for in6_addr and sin6_addr.
+
+ Clarified further that AI_V4MAPPED must be used with a dotted IPv4
+ literal address for getipnodebyname(), when address family is
+ AF_INET6.
+
+ Added text to clarify "::" and "::1" when used by
+ getipnodebyaddr().
+
+Acknowledgments
+
+ Thanks to the many people who made suggestions and provided feedback
+ to this document, including: Werner Almesberger, Ran Atkinson, Fred
+ Baker, Dave Borman, Andrew Cherenson, Alex Conta, Alan Cox, Steve
+ Deering, Richard Draves, Francis Dupont, Robert Elz, Marc Hasson, Tom
+ Herbert, Bob Hinden, Wan-Yen Hsu, Christian Huitema, Koji Imada,
+ Markus Jork, Ron Lee, Alan Lloyd, Charles Lynn, Dan McDonald, Dave
+ Mitton, Thomas Narten, Josh Osborne, Craig Partridge, Jean-Luc
+ Richier, Erik Scoredos, Keith Sklower, Matt Thomas, Harvey Thompson,
+ Dean D. Throop, Karen Tracey, Glenn Trewitt, Paul Vixie, David
+ Waitzman, Carl Williams, and Kazu Yamamoto,
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 38]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+ The getaddrinfo() and getnameinfo() functions are taken from an
+ earlier Internet Draft by Keith Sklower. As noted in that draft,
+ William Durst, Steven Wise, Michael Karels, and Eric Allman provided
+ many useful discussions on the subject of protocol-independent name-
+ to-address translation, and reviewed early versions of Keith
+ Sklower's original proposal. Eric Allman implemented the first
+ prototype of getaddrinfo(). The observation that specifying the pair
+ of name and service would suffice for connecting to a service
+ independent of protocol details was made by Marshall Rose in a
+ proposal to X/Open for a "Uniform Network Interface".
+
+ Craig Metz, Jack McCann, Erik Nordmark, Tim Hartrick, and Mukesh
+ Kacker made many contributions to this document. Ramesh Govindan
+ made a number of contributions and co-authored an earlier version of
+ this memo.
+
+References
+
+ [1] Deering, S. and R. Hinden, "Internet Protocol, Version 6 (IPv6)
+ Specification", RFC 2460, December 1998.
+
+ [2] Hinden, R. and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 2373, July 1998.
+
+ [3] IEEE, "Protocol Independent Interfaces", IEEE Std 1003.1g, DRAFT
+ 6.6, March 1997.
+
+ [4] Stevens, W. and M. Thomas, "Advanced Sockets API for IPv6", RFC
+ 2292, February 1998.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 39]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+Authors' Addresses
+
+ Robert E. Gilligan
+ FreeGate Corporation
+ 1208 E. Arques Ave.
+ Sunnyvale, CA 94086
+
+ Phone: +1 408 617 1004
+ EMail: gilligan@freegate.com
+
+
+ Susan Thomson
+ Bell Communications Research
+ MRE 2P-343, 445 South Street
+ Morristown, NJ 07960
+
+ Phone: +1 201 829 4514
+ EMail: set@thumper.bellcore.com
+
+
+ Jim Bound
+ Compaq Computer Corporation
+ 110 Spitbrook Road ZK3-3/U14
+ Nashua, NH 03062-2698
+
+ Phone: +1 603 884 0400
+ EMail: bound@zk3.dec.com
+
+
+ W. Richard Stevens
+ 1202 E. Paseo del Zorro
+ Tucson, AZ 85718-2826
+
+ Phone: +1 520 297 9416
+ EMail: rstevens@kohala.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 40]
+
+RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et. al. Informational [Page 41]
+
diff --git a/doc/rfc/rfc2671.txt b/doc/rfc/rfc2671.txt
new file mode 100644
index 0000000..ec05f80
--- /dev/null
+++ b/doc/rfc/rfc2671.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group P. Vixie
+Request for Comments: 2671 ISC
+Category: Standards Track August 1999
+
+
+ Extension Mechanisms for DNS (EDNS0)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+Abstract
+
+ The Domain Name System's wire protocol includes a number of fixed
+ fields whose range has been or soon will be exhausted and does not
+ allow clients to advertise their capabilities to servers. This
+ document describes backward compatible mechanisms for allowing the
+ protocol to grow.
+
+1 - Rationale and Scope
+
+1.1. DNS (see [RFC1035]) specifies a Message Format and within such
+ messages there are standard formats for encoding options, errors,
+ and name compression. The maximum allowable size of a DNS Message
+ is fixed. Many of DNS's protocol limits are too small for uses
+ which are or which are desired to become common. There is no way
+ for implementations to advertise their capabilities.
+
+1.2. Existing clients will not know how to interpret the protocol
+ extensions detailed here. In practice, these clients will be
+ upgraded when they have need of a new feature, and only new
+ features will make use of the extensions. We must however take
+ account of client behaviour in the face of extra fields, and design
+ a fallback scheme for interoperability with these clients.
+
+
+
+
+
+
+
+
+
+Vixie Standards Track [Page 1]
+
+RFC 2671 Extension Mechanisms for DNS (EDNS0) August 1999
+
+
+2 - Affected Protocol Elements
+
+2.1. The DNS Message Header's (see [RFC1035 4.1.1]) second full 16-bit
+ word is divided into a 4-bit OPCODE, a 4-bit RCODE, and a number of
+ 1-bit flags. The original reserved Z bits have been allocated to
+ various purposes, and most of the RCODE values are now in use.
+ More flags and more possible RCODEs are needed.
+
+2.2. The first two bits of a wire format domain label are used to denote
+ the type of the label. [RFC1035 4.1.4] allocates two of the four
+ possible types and reserves the other two. Proposals for use of
+ the remaining types far outnumber those available. More label
+ types are needed.
+
+2.3. DNS Messages are limited to 512 octets in size when sent over UDP.
+ While the minimum maximum reassembly buffer size still allows a
+ limit of 512 octets of UDP payload, most of the hosts now connected
+ to the Internet are able to reassemble larger datagrams. Some
+ mechanism must be created to allow requestors to advertise larger
+ buffer sizes to responders.
+
+3 - Extended Label Types
+
+3.1. The "0 1" label type will now indicate an extended label type,
+ whose value is encoded in the lower six bits of the first octet of
+ a label. All subsequently developed label types should be encoded
+ using an extended label type.
+
+3.2. The "1 1 1 1 1 1" extended label type will be reserved for future
+ expansion of the extended label type code space.
+
+4 - OPT pseudo-RR
+
+4.1. One OPT pseudo-RR can be added to the additional data section of
+ either a request or a response. An OPT is called a pseudo-RR
+ because it pertains to a particular transport level message and not
+ to any actual DNS data. OPT RRs shall never be cached, forwarded,
+ or stored in or loaded from master files. The quantity of OPT
+ pseudo-RRs per message shall be either zero or one, but not
+ greater.
+
+4.2. An OPT RR has a fixed part and a variable set of options expressed
+ as {attribute, value} pairs. The fixed part holds some DNS meta
+ data and also a small collection of new protocol elements which we
+ expect to be so popular that it would be a waste of wire space to
+ encode them as {attribute, value} pairs.
+
+
+
+
+
+Vixie Standards Track [Page 2]
+
+RFC 2671 Extension Mechanisms for DNS (EDNS0) August 1999
+
+
+4.3. The fixed part of an OPT RR is structured as follows:
+
+ Field Name Field Type Description
+ ------------------------------------------------------
+ NAME domain name empty (root domain)
+ TYPE u_int16_t OPT
+ CLASS u_int16_t sender's UDP payload size
+ TTL u_int32_t extended RCODE and flags
+ RDLEN u_int16_t describes RDATA
+ RDATA octet stream {attribute,value} pairs
+
+4.4. The variable part of an OPT RR is encoded in its RDATA and is
+ structured as zero or more of the following:
+
+ +0 (MSB) +1 (LSB)
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 0: | OPTION-CODE |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 2: | OPTION-LENGTH |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 4: | |
+ / OPTION-DATA /
+ / /
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+
+ OPTION-CODE (Assigned by IANA.)
+
+ OPTION-LENGTH Size (in octets) of OPTION-DATA.
+
+ OPTION-DATA Varies per OPTION-CODE.
+
+4.5. The sender's UDP payload size (which OPT stores in the RR CLASS
+ field) is the number of octets of the largest UDP payload that can
+ be reassembled and delivered in the sender's network stack. Note
+ that path MTU, with or without fragmentation, may be smaller than
+ this.
+
+4.5.1. Note that a 512-octet UDP payload requires a 576-octet IP
+ reassembly buffer. Choosing 1280 on an Ethernet connected
+ requestor would be reasonable. The consequence of choosing too
+ large a value may be an ICMP message from an intermediate
+ gateway, or even a silent drop of the response message.
+
+4.5.2. Both requestors and responders are advised to take account of the
+ path's discovered MTU (if already known) when considering message
+ sizes.
+
+
+
+
+
+Vixie Standards Track [Page 3]
+
+RFC 2671 Extension Mechanisms for DNS (EDNS0) August 1999
+
+
+4.5.3. The requestor's maximum payload size can change over time, and
+ should therefore not be cached for use beyond the transaction in
+ which it is advertised.
+
+4.5.4. The responder's maximum payload size can change over time, but
+ can be reasonably expected to remain constant between two
+ sequential transactions; for example, a meaningless QUERY to
+ discover a responder's maximum UDP payload size, followed
+ immediately by an UPDATE which takes advantage of this size.
+ (This is considered preferrable to the outright use of TCP for
+ oversized requests, if there is any reason to suspect that the
+ responder implements EDNS, and if a request will not fit in the
+ default 512 payload size limit.)
+
+4.5.5. Due to transaction overhead, it is unwise to advertise an
+ architectural limit as a maximum UDP payload size. Just because
+ your stack can reassemble 64KB datagrams, don't assume that you
+ want to spend more than about 4KB of state memory per ongoing
+ transaction.
+
+4.6. The extended RCODE and flags (which OPT stores in the RR TTL field)
+ are structured as follows:
+
+ +0 (MSB) +1 (LSB)
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 0: | EXTENDED-RCODE | VERSION |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ 2: | Z |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+
+ EXTENDED-RCODE Forms upper 8 bits of extended 12-bit RCODE. Note
+ that EXTENDED-RCODE value "0" indicates that an
+ unextended RCODE is in use (values "0" through "15").
+
+ VERSION Indicates the implementation level of whoever sets
+ it. Full conformance with this specification is
+ indicated by version "0." Requestors are encouraged
+ to set this to the lowest implemented level capable
+ of expressing a transaction, to minimize the
+ responder and network load of discovering the
+ greatest common implementation level between
+ requestor and responder. A requestor's version
+ numbering strategy should ideally be a run time
+ configuration option.
+
+ If a responder does not implement the VERSION level
+ of the request, then it answers with RCODE=BADVERS.
+ All responses will be limited in format to the
+
+
+
+Vixie Standards Track [Page 4]
+
+RFC 2671 Extension Mechanisms for DNS (EDNS0) August 1999
+
+
+ VERSION level of the request, but the VERSION of each
+ response will be the highest implementation level of
+ the responder. In this way a requestor will learn
+ the implementation level of a responder as a side
+ effect of every response, including error responses,
+ including RCODE=BADVERS.
+
+ Z Set to zero by senders and ignored by receivers,
+ unless modified in a subsequent specification.
+
+5 - Transport Considerations
+
+5.1. The presence of an OPT pseudo-RR in a request should be taken as an
+ indication that the requestor fully implements the given version of
+ EDNS, and can correctly understand any response that conforms to
+ that feature's specification.
+
+5.2. Lack of use of these features in a request must be taken as an
+ indication that the requestor does not implement any part of this
+ specification and that the responder may make no use of any
+ protocol extension described here in its response.
+
+5.3. Responders who do not understand these protocol extensions are
+ expected to send a response with RCODE NOTIMPL, FORMERR, or
+ SERVFAIL. Therefore use of extensions should be "probed" such that
+ a responder who isn't known to support them be allowed a retry with
+ no extensions if it responds with such an RCODE. If a responder's
+ capability level is cached by a requestor, a new probe should be
+ sent periodically to test for changes to responder capability.
+
+6 - Security Considerations
+
+ Requestor-side specification of the maximum buffer size may open a
+ new DNS denial of service attack if responders can be made to send
+ messages which are too large for intermediate gateways to forward,
+ thus leading to potential ICMP storms between gateways and
+ responders.
+
+7 - IANA Considerations
+
+ The IANA has assigned RR type code 41 for OPT.
+
+ It is the recommendation of this document and its working group
+ that IANA create a registry for EDNS Extended Label Types, for EDNS
+ Option Codes, and for EDNS Version Numbers.
+
+ This document assigns label type 0b01xxxxxx as "EDNS Extended Label
+ Type." We request that IANA record this assignment.
+
+
+
+Vixie Standards Track [Page 5]
+
+RFC 2671 Extension Mechanisms for DNS (EDNS0) August 1999
+
+
+ This document assigns extended label type 0bxx111111 as "Reserved
+ for future extended label types." We request that IANA record this
+ assignment.
+
+ This document assigns option code 65535 to "Reserved for future
+ expansion."
+
+ This document expands the RCODE space from 4 bits to 12 bits. This
+ will allow IANA to assign more than the 16 distinct RCODE values
+ allowed in [RFC1035].
+
+ This document assigns EDNS Extended RCODE "16" to "BADVERS".
+
+ IESG approval should be required to create new entries in the EDNS
+ Extended Label Type or EDNS Version Number registries, while any
+ published RFC (including Informational, Experimental, or BCP)
+ should be grounds for allocation of an EDNS Option Code.
+
+8 - Acknowledgements
+
+ Paul Mockapetris, Mark Andrews, Robert Elz, Don Lewis, Bob Halley,
+ Donald Eastlake, Rob Austein, Matt Crawford, Randy Bush, and Thomas
+ Narten were each instrumental in creating and refining this
+ specification.
+
+9 - References
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+10 - Author's Address
+
+ Paul Vixie
+ Internet Software Consortium
+ 950 Charter Street
+ Redwood City, CA 94063
+
+ Phone: +1 650 779 7001
+ EMail: vixie@isc.org
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie Standards Track [Page 6]
+
+RFC 2671 Extension Mechanisms for DNS (EDNS0) August 1999
+
+
+11 - Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie Standards Track [Page 7]
+
diff --git a/doc/rfc/rfc2672.txt b/doc/rfc/rfc2672.txt
new file mode 100644
index 0000000..1103016
--- /dev/null
+++ b/doc/rfc/rfc2672.txt
@@ -0,0 +1,507 @@
+
+
+
+
+
+
+Network Working Group M. Crawford
+Request for Comments: 2672 Fermilab
+Category: Standards Track August 1999
+
+
+ Non-Terminal DNS Name Redirection
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+1. Introduction
+
+ This document defines a new DNS Resource Record called "DNAME", which
+ provides the capability to map an entire subtree of the DNS name
+ space to another domain. It differs from the CNAME record which maps
+ a single node of the name space.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [KWORD].
+
+2. Motivation
+
+ This Resource Record and its processing rules were conceived as a
+ solution to the problem of maintaining address-to-name mappings in a
+ context of network renumbering. Without the DNAME mechanism, an
+ authoritative DNS server for the address-to-name mappings of some
+ network must be reconfigured when that network is renumbered. With
+ DNAME, the zone can be constructed so that it needs no modification
+ when renumbered. DNAME can also be useful in other situations, such
+ as when an organizational unit is renamed.
+
+3. The DNAME Resource Record
+
+ The DNAME RR has mnemonic DNAME and type code 39 (decimal).
+
+
+
+
+
+
+
+Crawford Standards Track [Page 1]
+
+RFC 2672 Non-Terminal DNS Name Redirection August 1999
+
+
+ DNAME has the following format:
+
+ <owner> <ttl> <class> DNAME <target>
+
+ The format is not class-sensitive. All fields are required. The
+ RDATA field <target> is a <domain-name> [DNSIS].
+
+ The DNAME RR causes type NS additional section processing.
+
+ The effect of the DNAME record is the substitution of the record's
+ <target> for its <owner> as a suffix of a domain name. A "no-
+ descendants" limitation governs the use of DNAMEs in a zone file:
+
+ If a DNAME RR is present at a node N, there may be other data at N
+ (except a CNAME or another DNAME), but there MUST be no data at
+ any descendant of N. This restriction applies only to records of
+ the same class as the DNAME record.
+
+ This rule assures predictable results when a DNAME record is cached
+ by a server which is not authoritative for the record's zone. It
+ MUST be enforced when authoritative zone data is loaded. Together
+ with the rules for DNS zone authority [DNSCLR] it implies that DNAME
+ and NS records can only coexist at the top of a zone which has only
+ one node.
+
+ The compression scheme of [DNSIS] MUST NOT be applied to the RDATA
+ portion of a DNAME record unless the sending server has some way of
+ knowing that the receiver understands the DNAME record format.
+ Signalling such understanding is expected to be the subject of future
+ DNS Extensions.
+
+ Naming loops can be created with DNAME records or a combination of
+ DNAME and CNAME records, just as they can with CNAME records alone.
+ Resolvers, including resolvers embedded in DNS servers, MUST limit
+ the resources they devote to any query. Implementors should note,
+ however, that fairly lengthy chains of DNAME records may be valid.
+
+4. Query Processing
+
+ To exploit the DNAME mechanism the name resolution algorithms [DNSCF]
+ must be modified slightly for both servers and resolvers.
+
+ Both modified algorithms incorporate the operation of making a
+ substitution on a name (either QNAME or SNAME) under control of a
+ DNAME record. This operation will be referred to as "the DNAME
+ substitution".
+
+
+
+
+
+Crawford Standards Track [Page 2]
+
+RFC 2672 Non-Terminal DNS Name Redirection August 1999
+
+
+4.1. Processing by Servers
+
+ For a server performing non-recursive service steps 3.c and 4 of
+ section 4.3.2 [DNSCF] are changed to check for a DNAME record before
+ checking for a wildcard ("*") label, and to return certain DNAME
+ records from zone data and the cache.
+
+ DNS clients sending Extended DNS [EDNS0] queries with Version 0 or
+ non-extended queries are presumed not to understand the semantics of
+ the DNAME record, so a server which implements this specification,
+ when answering a non-extended query, SHOULD synthesize a CNAME record
+ for each DNAME record encountered during query processing to help the
+ client reach the correct DNS data. The behavior of clients and
+ servers under Extended DNS versions greater than 0 will be specified
+ when those versions are defined.
+
+ The synthesized CNAME RR, if provided, MUST have
+
+ The same CLASS as the QCLASS of the query,
+
+ TTL equal to zero,
+
+ An <owner> equal to the QNAME in effect at the moment the DNAME RR
+ was encountered, and
+
+ An RDATA field containing the new QNAME formed by the action of
+ the DNAME substitution.
+
+ If the server has the appropriate key on-line [DNSSEC, SECDYN], it
+ MAY generate and return a SIG RR for the synthesized CNAME RR.
+
+ The revised server algorithm is:
+
+ 1. Set or clear the value of recursion available in the response
+ depending on whether the name server is willing to provide
+ recursive service. If recursive service is available and
+ requested via the RD bit in the query, go to step 5, otherwise
+ step 2.
+
+ 2. Search the available zones for the zone which is the nearest
+ ancestor to QNAME. If such a zone is found, go to step 3,
+ otherwise step 4.
+
+ 3. Start matching down, label by label, in the zone. The matching
+ process can terminate several ways:
+
+
+
+
+
+
+Crawford Standards Track [Page 3]
+
+RFC 2672 Non-Terminal DNS Name Redirection August 1999
+
+
+ a. If the whole of QNAME is matched, we have found the node.
+
+ If the data at the node is a CNAME, and QTYPE doesn't match
+ CNAME, copy the CNAME RR into the answer section of the
+ response, change QNAME to the canonical name in the CNAME RR,
+ and go back to step 1.
+
+ Otherwise, copy all RRs which match QTYPE into the answer
+ section and go to step 6.
+
+ b. If a match would take us out of the authoritative data, we have
+ a referral. This happens when we encounter a node with NS RRs
+ marking cuts along the bottom of a zone.
+
+ Copy the NS RRs for the subzone into the authority section of
+ the reply. Put whatever addresses are available into the
+ additional section, using glue RRs if the addresses are not
+ available from authoritative data or the cache. Go to step 4.
+
+ c. If at some label, a match is impossible (i.e., the
+ corresponding label does not exist), look to see whether the
+ last label matched has a DNAME record.
+
+ If a DNAME record exists at that point, copy that record into
+ the answer section. If substitution of its <target> for its
+ <owner> in QNAME would overflow the legal size for a <domain-
+ name>, set RCODE to YXDOMAIN [DNSUPD] and exit; otherwise
+ perform the substitution and continue. If the query was not
+ extended [EDNS0] with a Version indicating understanding of the
+ DNAME record, the server SHOULD synthesize a CNAME record as
+ described above and include it in the answer section. Go back
+ to step 1.
+
+ If there was no DNAME record, look to see if the "*" label
+ exists.
+
+ If the "*" label does not exist, check whether the name we are
+ looking for is the original QNAME in the query or a name we
+ have followed due to a CNAME. If the name is original, set an
+ authoritative name error in the response and exit. Otherwise
+ just exit.
+
+ If the "*" label does exist, match RRs at that node against
+ QTYPE. If any match, copy them into the answer section, but
+ set the owner of the RR to be QNAME, and not the node with the
+ "*" label. Go to step 6.
+
+
+
+
+
+Crawford Standards Track [Page 4]
+
+RFC 2672 Non-Terminal DNS Name Redirection August 1999
+
+
+ 4. Start matching down in the cache. If QNAME is found in the cache,
+ copy all RRs attached to it that match QTYPE into the answer
+ section. If QNAME is not found in the cache but a DNAME record is
+ present at an ancestor of QNAME, copy that DNAME record into the
+ answer section. If there was no delegation from authoritative
+ data, look for the best one from the cache, and put it in the
+ authority section. Go to step 6.
+
+ 5. Use the local resolver or a copy of its algorithm (see resolver
+ section of this memo) to answer the query. Store the results,
+ including any intermediate CNAMEs and DNAMEs, in the answer
+ section of the response.
+
+ 6. Using local data only, attempt to add other RRs which may be
+ useful to the additional section of the query. Exit.
+
+ Note that there will be at most one ancestor with a DNAME as
+ described in step 4 unless some zone's data is in violation of the
+ no-descendants limitation in section 3. An implementation might take
+ advantage of this limitation by stopping the search of step 3c or
+ step 4 when a DNAME record is encountered.
+
+4.2. Processing by Resolvers
+
+ A resolver or a server providing recursive service must be modified
+ to treat a DNAME as somewhat analogous to a CNAME. The resolver
+ algorithm of [DNSCF] section 5.3.3 is modified to renumber step 4.d
+ as 4.e and insert a new 4.d. The complete algorithm becomes:
+
+ 1. See if the answer is in local information, and if so return it to
+ the client.
+
+ 2. Find the best servers to ask.
+
+ 3. Send them queries until one returns a response.
+
+ 4. Analyze the response, either:
+
+ a. if the response answers the question or contains a name error,
+ cache the data as well as returning it back to the client.
+
+ b. if the response contains a better delegation to other servers,
+ cache the delegation information, and go to step 2.
+
+ c. if the response shows a CNAME and that is not the answer
+ itself, cache the CNAME, change the SNAME to the canonical name
+ in the CNAME RR and go to step 1.
+
+
+
+
+Crawford Standards Track [Page 5]
+
+RFC 2672 Non-Terminal DNS Name Redirection August 1999
+
+
+ d. if the response shows a DNAME and that is not the answer
+ itself, cache the DNAME. If substitution of the DNAME's
+ <target> for its <owner> in the SNAME would overflow the legal
+ size for a <domain-name>, return an implementation-dependent
+ error to the application; otherwise perform the substitution
+ and go to step 1.
+
+ e. if the response shows a server failure or other bizarre
+ contents, delete the server from the SLIST and go back to step
+ 3.
+
+ A resolver or recursive server which understands DNAME records but
+ sends non-extended queries MUST augment step 4.c by deleting from the
+ reply any CNAME records which have an <owner> which is a subdomain of
+ the <owner> of any DNAME record in the response.
+
+5. Examples of Use
+
+5.1. Organizational Renaming
+
+ If an organization with domain name FROBOZZ.EXAMPLE became part of an
+ organization with domain name ACME.EXAMPLE, it might ease transition
+ by placing information such as this in its old zone.
+
+ frobozz.example. DNAME frobozz-division.acme.example.
+ MX 10 mailhub.acme.example.
+
+ The response to an extended recursive query for www.frobozz.example
+ would contain, in the answer section, the DNAME record shown above
+ and the relevant RRs for www.frobozz-division.acme.example.
+
+5.2. Classless Delegation of Shorter Prefixes
+
+ The classless scheme for in-addr.arpa delegation [INADDR] can be
+ extended to prefixes shorter than 24 bits by use of the DNAME record.
+ For example, the prefix 192.0.8.0/22 can be delegated by the
+ following records.
+
+ $ORIGIN 0.192.in-addr.arpa.
+ 8/22 NS ns.slash-22-holder.example.
+ 8 DNAME 8.8/22
+ 9 DNAME 9.8/22
+ 10 DNAME 10.8/22
+ 11 DNAME 11.8/22
+
+
+
+
+
+
+
+Crawford Standards Track [Page 6]
+
+RFC 2672 Non-Terminal DNS Name Redirection August 1999
+
+
+ A typical entry in the resulting reverse zone for some host with
+ address 192.0.9.33 might be
+
+ $ORIGIN 8/22.0.192.in-addr.arpa.
+ 33.9 PTR somehost.slash-22-holder.example.
+
+ The same advisory remarks concerning the choice of the "/" character
+ apply here as in [INADDR].
+
+5.3. Network Renumbering Support
+
+ If IPv4 network renumbering were common, maintenance of address space
+ delegation could be simplified by using DNAME records instead of NS
+ records to delegate.
+
+ $ORIGIN new-style.in-addr.arpa.
+ 189.190 DNAME in-addr.example.net.
+
+ $ORIGIN in-addr.example.net.
+ 188 DNAME in-addr.customer.example.
+
+ $ORIGIN in-addr.customer.example.
+ 1 PTR www.customer.example.
+ 2 PTR mailhub.customer.example.
+ ; etc ...
+
+ This would allow the address space 190.189.0.0/16 assigned to the ISP
+ "example.net" to be changed without the necessity of altering the
+ zone files describing the use of that space by the ISP and its
+ customers.
+
+ Renumbering IPv4 networks is currently so arduous a task that
+ updating the DNS is only a small part of the labor, so this scheme
+ may have a low value. But it is hoped that in IPv6 the renumbering
+ task will be quite different and the DNAME mechanism may play a
+ useful part.
+
+6. IANA Considerations
+
+ This document defines a new DNS Resource Record type with the
+ mnemonic DNAME and type code 39 (decimal). The naming/numbering
+ space is defined in [DNSIS]. This name and number have already been
+ registered with the IANA.
+
+
+
+
+
+
+
+
+Crawford Standards Track [Page 7]
+
+RFC 2672 Non-Terminal DNS Name Redirection August 1999
+
+
+7. Security Considerations
+
+ The DNAME record is similar to the CNAME record with regard to the
+ consequences of insertion of a spoofed record into a DNS server or
+ resolver, differing in that the DNAME's effect covers a whole subtree
+ of the name space. The facilities of [DNSSEC] are available to
+ authenticate this record type.
+
+8. References
+
+ [DNSCF] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [DNSCLR] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [DNSIS] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [DNSSEC] Eastlake, 3rd, D. and C. Kaufman, "Domain Name System
+ Security Extensions", RFC 2065, January 1997.
+
+ [DNSUPD] Vixie, P., Ed., Thomson, S., Rekhter, Y. and J. Bound,
+ "Dynamic Updates in the Domain Name System", RFC 2136, April
+ 1997.
+
+ [EDNS0] Vixie, P., "Extensions mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [INADDR] Eidnes, H., de Groot, G. and P. Vixie, "Classless IN-
+ ADDR.ARPA delegation", RFC 2317, March 1998.
+
+ [KWORD] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels," BCP 14, RFC 2119, March 1997.
+
+ [SECDYN] D. Eastlake, 3rd, "Secure Domain Name System Dynamic
+ Update", RFC 2137, April 1997.
+
+9. Author's Address
+
+ Matt Crawford
+ Fermilab MS 368
+ PO Box 500
+ Batavia, IL 60510
+ USA
+
+ Phone: +1 630 840-3461
+ EMail: crawdad@fnal.gov
+
+
+
+Crawford Standards Track [Page 8]
+
+RFC 2672 Non-Terminal DNS Name Redirection August 1999
+
+
+10. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Crawford Standards Track [Page 9]
+
diff --git a/doc/rfc/rfc2673.txt b/doc/rfc/rfc2673.txt
new file mode 100644
index 0000000..19d272e
--- /dev/null
+++ b/doc/rfc/rfc2673.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group M. Crawford
+Request for Comments: 2673 Fermilab
+Category: Standards Track August 1999
+
+
+ Binary Labels in the Domain Name System
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+1. Introduction and Terminology
+
+ This document defines a "Bit-String Label" which may appear within
+ domain names. This new label type compactly represents a sequence of
+ "One-Bit Labels" and enables resource records to be stored at any
+ bit-boundary in a binary-named section of the domain name tree.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [KWORD].
+
+2. Motivation
+
+ Binary labels are intended to efficiently solve the problem of
+ storing data and delegating authority on arbitrary boundaries when
+ the structure of underlying name space is most naturally represented
+ in binary.
+
+3. Label Format
+
+ Up to 256 One-Bit Labels can be grouped into a single Bit-String
+ Label. Within a Bit-String Label the most significant or "highest
+ level" bit appears first. This is unlike the ordering of DNS labels
+ themselves, which has the least significant or "lowest level" label
+ first. Nonetheless, this ordering seems to be the most natural and
+ efficient for representing binary labels.
+
+
+
+
+
+
+Crawford Standards Track [Page 1]
+
+RFC 2673 Binary Labels in the Domain Name System August 1999
+
+
+ Among consecutive Bit-String Labels, the bits in the first-appearing
+ label are less significant or "at a lower level" than the bits in
+ subsequent Bit-String Labels, just as ASCII labels are ordered.
+
+3.1. Encoding
+
+ 0 1 2
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 . . .
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-//+-+-+-+-+-+-+
+ |0 1| ELT | Count | Label ... |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+//-+-+-+-+-+-+-+
+
+ (Each tic mark represents one bit.)
+
+
+ ELT 000001 binary, the six-bit extended label type [EDNS0]
+ assigned to the Bit-String Label.
+
+ Count The number of significant bits in the Label field. A Count
+ value of zero indicates that 256 bits are significant.
+ (Thus the null label representing the DNS root cannot be
+ represented as a Bit String Label.)
+
+ Label The bit string representing a sequence of One-Bit Labels,
+ with the most significant bit first. That is, the One-Bit
+ Label in position 17 in the diagram above represents a
+ subdomain of the domain represented by the One-Bit Label in
+ position 16, and so on.
+
+ The Label field is padded on the right with zero to seven
+ pad bits to make the entire field occupy an integral number
+ of octets. These pad bits MUST be zero on transmission and
+ ignored on reception.
+
+ A sequence of bits may be split into two or more Bit-String Labels,
+ but the division points have no significance and need not be
+ preserved. An excessively clever server implementation might split
+ Bit-String Labels so as to maximize the effectiveness of message
+ compression [DNSIS]. A simpler server might divide Bit-String Labels
+ at zone boundaries, if any zone boundaries happen to fall between
+ One-Bit Labels.
+
+3.2. Textual Representation
+
+ A Bit-String Label is represented in text -- in a zone file, for
+ example -- as a <bit-spec> surrounded by the delimiters "\[" and "]".
+ The <bit-spec> is either a dotted quad or a base indicator and a
+ sequence of digits appropriate to that base, optionally followed by a
+
+
+
+Crawford Standards Track [Page 2]
+
+RFC 2673 Binary Labels in the Domain Name System August 1999
+
+
+ slash and a length. The base indicators are "b", "o" and "x",
+ denoting base 2, 8 and 16 respectively. The length counts the
+ significant bits and MUST be between 1 and 32, inclusive, after a
+ dotted quad, or between 1 and 256, inclusive, after one of the other
+ forms. If the length is omitted, the implicit length is 32 for a
+ dotted quad or 1, 3 or 4 times the number of binary, octal or
+ hexadecimal digits supplied, respectively, for the other forms.
+
+ In augmented Backus-Naur form [ABNF],
+
+ bit-string-label = "\[" bit-spec "]"
+
+ bit-spec = bit-data [ "/" length ]
+ / dotted-quad [ "/" slength ]
+
+ bit-data = "x" 1*64HEXDIG
+ / "o" 1*86OCTDIG
+ / "b" 1*256BIT
+
+ dotted-quad = decbyte "." decbyte "." decbyte "." decbyte
+
+ decbyte = 1*3DIGIT
+
+ length = NZDIGIT *2DIGIT
+
+ slength = NZDIGIT [ DIGIT ]
+
+ OCTDIG = %x30-37
+
+ NZDIGIT = %x31-39
+
+ If a <length> is present, the number of digits in the <bit-data> MUST
+ be just sufficient to contain the number of bits specified by the
+ <length>. If there are insignificant bits in a final hexadecimal or
+ octal digit, they MUST be zero. A <dotted-quad> always has all four
+ parts even if the associated <slength> is less than 24, but, like the
+ other forms, insignificant bits MUST be zero.
+
+ Each number represented by a <decbyte> must be between 0 and 255,
+ inclusive.
+
+ The number represented by <length> must be between 1 and 256
+ inclusive.
+
+ The number represented by <slength> must be between 1 and 32
+ inclusive.
+
+
+
+
+
+Crawford Standards Track [Page 3]
+
+RFC 2673 Binary Labels in the Domain Name System August 1999
+
+
+ When the textual form of a Bit-String Label is generated by machine,
+ the length SHOULD be explicit, not implicit.
+
+3.2.1. Examples
+
+ The following four textual forms represent the same Bit-String Label.
+
+ \[b11010000011101]
+ \[o64072/14]
+ \[xd074/14]
+ \[208.116.0.0/14]
+
+ The following represents two consecutive Bit-String Labels which
+ denote the same relative point in the DNS tree as any of the above
+ single Bit-String Labels.
+
+ \[b11101].\[o640]
+
+3.3. Canonical Representation and Sort Order
+
+ Both the wire form and the text form of binary labels have a degree
+ of flexibility in their grouping into multiple consecutive Bit-String
+ Labels. For generating and checking DNS signature records [DNSSEC]
+ binary labels must be in a predictable form. This canonical form is
+ defined as the form which has the fewest possible Bit-String Labels
+ and in which all except possibly the first (least significant) label
+ in any sequence of consecutive Bit-String Labels is of maximum
+ length.
+
+ For example, the canonical form of any sequence of up to 256 One-Bit
+ Labels has a single Bit-String Label, and the canonical form of a
+ sequence of 513 to 768 One-Bit Labels has three Bit-String Labels of
+ which the second and third contain 256 label bits.
+
+ The canonical sort order of domain names [DNSSEC] is extended to
+ encompass binary labels as follows. Sorting is still label-by-label,
+ from most to least significant, where a label may now be a One-Bit
+ Label or a standard (code 00) label. Any One-Bit Label sorts before
+ any standard label, and a 0 bit sorts before a 1 bit. The absence of
+ a label sorts before any label, as specified in [DNSSEC].
+
+
+
+
+
+
+
+
+
+
+
+Crawford Standards Track [Page 4]
+
+RFC 2673 Binary Labels in the Domain Name System August 1999
+
+
+ For example, the following domain names are correctly sorted.
+
+ foo.example
+ \[b1].foo.example
+ \[b100].foo.example
+ \[b101].foo.example
+ bravo.\[b10].foo.example
+ alpha.foo.example
+
+4. Processing Rules
+
+ A One-Bit Label never matches any other kind of label. In
+ particular, the DNS labels represented by the single ASCII characters
+ "0" and "1" do not match One-Bit Labels represented by the bit values
+ 0 and 1.
+
+5. Discussion
+
+ A Count of zero in the wire-form represents a 256-bit sequence, not
+ to optimize that particular case, but to make it completely
+ impossible to have a zero-bit label.
+
+6. IANA Considerations
+
+ This document defines one Extended Label Type, termed the Bit-String
+ Label, and requests registration of the code point 000001 binary in
+ the space defined by [EDNS0].
+
+7. Security Considerations
+
+ All security considerations which apply to traditional ASCII DNS
+ labels apply equally to binary labels. he canonicalization and
+ sorting rules of section 3.3 allow these to be addressed by DNS
+ Security [DNSSEC].
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Crawford Standards Track [Page 5]
+
+RFC 2673 Binary Labels in the Domain Name System August 1999
+
+
+8. References
+
+ [ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 2234, November 1997.
+
+ [DNSIS] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [DNSSEC] Eastlake, D., 3rd, C. Kaufman, "Domain Name System Security
+ Extensions", RFC 2065, January 1997
+
+ [EDNS0] Vixie, P., "Extension mechanisms for DNS (EDNS0)", RFC 2671,
+ August 1999.
+
+ [KWORD] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels," BCP 14, RFC 2119, March 1997.
+
+9. Author's Address
+
+ Matt Crawford
+ Fermilab MS 368
+ PO Box 500
+ Batavia, IL 60510
+ USA
+
+ Phone: +1 630 840-3461
+ EMail: crawdad@fnal.gov
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Crawford Standards Track [Page 6]
+
+RFC 2673 Binary Labels in the Domain Name System August 1999
+
+
+10. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1999). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Crawford Standards Track [Page 7]
+
diff --git a/doc/rfc/rfc2782.txt b/doc/rfc/rfc2782.txt
new file mode 100644
index 0000000..1827f10
--- /dev/null
+++ b/doc/rfc/rfc2782.txt
@@ -0,0 +1,675 @@
+
+
+
+
+
+
+Network Working Group A. Gulbrandsen
+Request for Comments: 2782 Troll Technologies
+Obsoletes: 2052 P. Vixie
+Category: Standards Track Internet Software Consortium
+ L. Esibov
+ Microsoft Corp.
+ February 2000
+
+
+ A DNS RR for specifying the location of services (DNS SRV)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ This document describes a DNS RR which specifies the location of the
+ server(s) for a specific protocol and domain.
+
+Overview and rationale
+
+ Currently, one must either know the exact address of a server to
+ contact it, or broadcast a question.
+
+ The SRV RR allows administrators to use several servers for a single
+ domain, to move services from host to host with little fuss, and to
+ designate some hosts as primary servers for a service and others as
+ backups.
+
+ Clients ask for a specific service/protocol for a specific domain
+ (the word domain is used here in the strict RFC 1034 sense), and get
+ back the names of any available servers.
+
+ Note that where this document refers to "address records", it means A
+ RR's, AAAA RR's, or their most modern equivalent.
+
+
+
+
+
+
+
+Gulbrandsen, et al. Standards Track [Page 1]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+Definitions
+
+ The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT" and "MAY"
+ used in this document are to be interpreted as specified in [BCP 14].
+ Other terms used in this document are defined in the DNS
+ specification, RFC 1034.
+
+Applicability Statement
+
+ In general, it is expected that SRV records will be used by clients
+ for applications where the relevant protocol specification indicates
+ that clients should use the SRV record. Such specification MUST
+ define the symbolic name to be used in the Service field of the SRV
+ record as described below. It also MUST include security
+ considerations. Service SRV records SHOULD NOT be used in the absence
+ of such specification.
+
+Introductory example
+
+ If a SRV-cognizant LDAP client wants to discover a LDAP server that
+ supports TCP protocol and provides LDAP service for the domain
+ example.com., it does a lookup of
+
+ _ldap._tcp.example.com
+
+ as described in [ARM]. The example zone file near the end of this
+ memo contains answering RRs for an SRV query.
+
+ Note: LDAP is chosen as an example for illustrative purposes only,
+ and the LDAP examples used in this document should not be considered
+ a definitive statement on the recommended way for LDAP to use SRV
+ records. As described in the earlier applicability section, consult
+ the appropriate LDAP documents for the recommended procedures.
+
+The format of the SRV RR
+
+ Here is the format of the SRV RR, whose DNS type code is 33:
+
+ _Service._Proto.Name TTL Class SRV Priority Weight Port Target
+
+ (There is an example near the end of this document.)
+
+ Service
+ The symbolic name of the desired service, as defined in Assigned
+ Numbers [STD 2] or locally. An underscore (_) is prepended to
+ the service identifier to avoid collisions with DNS labels that
+ occur in nature.
+
+
+
+
+Gulbrandsen, et al. Standards Track [Page 2]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+ Some widely used services, notably POP, don't have a single
+ universal name. If Assigned Numbers names the service
+ indicated, that name is the only name which is legal for SRV
+ lookups. The Service is case insensitive.
+
+ Proto
+ The symbolic name of the desired protocol, with an underscore
+ (_) prepended to prevent collisions with DNS labels that occur
+ in nature. _TCP and _UDP are at present the most useful values
+ for this field, though any name defined by Assigned Numbers or
+ locally may be used (as for Service). The Proto is case
+ insensitive.
+
+ Name
+ The domain this RR refers to. The SRV RR is unique in that the
+ name one searches for is not this name; the example near the end
+ shows this clearly.
+
+ TTL
+ Standard DNS meaning [RFC 1035].
+
+ Class
+ Standard DNS meaning [RFC 1035]. SRV records occur in the IN
+ Class.
+
+ Priority
+ The priority of this target host. A client MUST attempt to
+ contact the target host with the lowest-numbered priority it can
+ reach; target hosts with the same priority SHOULD be tried in an
+ order defined by the weight field. The range is 0-65535. This
+ is a 16 bit unsigned integer in network byte order.
+
+ Weight
+ A server selection mechanism. The weight field specifies a
+ relative weight for entries with the same priority. Larger
+ weights SHOULD be given a proportionately higher probability of
+ being selected. The range of this number is 0-65535. This is a
+ 16 bit unsigned integer in network byte order. Domain
+ administrators SHOULD use Weight 0 when there isn't any server
+ selection to do, to make the RR easier to read for humans (less
+ noisy). In the presence of records containing weights greater
+ than 0, records with weight 0 should have a very small chance of
+ being selected.
+
+ In the absence of a protocol whose specification calls for the
+ use of other weighting information, a client arranges the SRV
+ RRs of the same Priority in the order in which target hosts,
+
+
+
+
+Gulbrandsen, et al. Standards Track [Page 3]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+ specified by the SRV RRs, will be contacted. The following
+ algorithm SHOULD be used to order the SRV RRs of the same
+ priority:
+
+ To select a target to be contacted next, arrange all SRV RRs
+ (that have not been ordered yet) in any order, except that all
+ those with weight 0 are placed at the beginning of the list.
+
+ Compute the sum of the weights of those RRs, and with each RR
+ associate the running sum in the selected order. Then choose a
+ uniform random number between 0 and the sum computed
+ (inclusive), and select the RR whose running sum value is the
+ first in the selected order which is greater than or equal to
+ the random number selected. The target host specified in the
+ selected SRV RR is the next one to be contacted by the client.
+ Remove this SRV RR from the set of the unordered SRV RRs and
+ apply the described algorithm to the unordered SRV RRs to select
+ the next target host. Continue the ordering process until there
+ are no unordered SRV RRs. This process is repeated for each
+ Priority.
+
+ Port
+ The port on this target host of this service. The range is 0-
+ 65535. This is a 16 bit unsigned integer in network byte order.
+ This is often as specified in Assigned Numbers but need not be.
+
+ Target
+ The domain name of the target host. There MUST be one or more
+ address records for this name, the name MUST NOT be an alias (in
+ the sense of RFC 1034 or RFC 2181). Implementors are urged, but
+ not required, to return the address record(s) in the Additional
+ Data section. Unless and until permitted by future standards
+ action, name compression is not to be used for this field.
+
+ A Target of "." means that the service is decidedly not
+ available at this domain.
+
+Domain administrator advice
+
+ Expecting everyone to update their client applications when the first
+ server publishes a SRV RR is futile (even if desirable). Therefore
+ SRV would have to coexist with address record lookups for existing
+ protocols, and DNS administrators should try to provide address
+ records to support old clients:
+
+ - Where the services for a single domain are spread over several
+ hosts, it seems advisable to have a list of address records at
+ the same DNS node as the SRV RR, listing reasonable (if perhaps
+
+
+
+Gulbrandsen, et al. Standards Track [Page 4]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+ suboptimal) fallback hosts for Telnet, NNTP and other protocols
+ likely to be used with this name. Note that some programs only
+ try the first address they get back from e.g. gethostbyname(),
+ and we don't know how widespread this behavior is.
+
+ - Where one service is provided by several hosts, one can either
+ provide address records for all the hosts (in which case the
+ round-robin mechanism, where available, will share the load
+ equally) or just for one (presumably the fastest).
+
+ - If a host is intended to provide a service only when the main
+ server(s) is/are down, it probably shouldn't be listed in
+ address records.
+
+ - Hosts that are referenced by backup address records must use the
+ port number specified in Assigned Numbers for the service.
+
+ - Designers of future protocols for which "secondary servers" is
+ not useful (or meaningful) may choose to not use SRV's support
+ for secondary servers. Clients for such protocols may use or
+ ignore SRV RRs with Priority higher than the RR with the lowest
+ Priority for a domain.
+
+ Currently there's a practical limit of 512 bytes for DNS replies.
+ Until all resolvers can handle larger responses, domain
+ administrators are strongly advised to keep their SRV replies below
+ 512 bytes.
+
+ All round numbers, wrote Dr. Johnson, are false, and these numbers
+ are very round: A reply packet has a 30-byte overhead plus the name
+ of the service ("_ldap._tcp.example.com" for instance); each SRV RR
+ adds 20 bytes plus the name of the target host; each NS RR in the NS
+ section is 15 bytes plus the name of the name server host; and
+ finally each A RR in the additional data section is 20 bytes or so,
+ and there are A's for each SRV and NS RR mentioned in the answer.
+ This size estimate is extremely crude, but shouldn't underestimate
+ the actual answer size by much. If an answer may be close to the
+ limit, using a DNS query tool (e.g. "dig") to look at the actual
+ answer is a good idea.
+
+The "Weight" field
+
+ Weight, the server selection field, is not quite satisfactory, but
+ the actual load on typical servers changes much too quickly to be
+ kept around in DNS caches. It seems to the authors that offering
+ administrators a way to say "this machine is three times as fast as
+ that one" is the best that can practically be done.
+
+
+
+
+Gulbrandsen, et al. Standards Track [Page 5]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+ The only way the authors can see of getting a "better" load figure is
+ asking a separate server when the client selects a server and
+ contacts it. For short-lived services an extra step in the
+ connection establishment seems too expensive, and for long-lived
+ services, the load figure may well be thrown off a minute after the
+ connection is established when someone else starts or finishes a
+ heavy job.
+
+ Note: There are currently various experiments at providing relative
+ network proximity estimation, available bandwidth estimation, and
+ similar services. Use of the SRV record with such facilities, and in
+ particular the interpretation of the Weight field when these
+ facilities are used, is for further study. Weight is only intended
+ for static, not dynamic, server selection. Using SRV weight for
+ dynamic server selection would require assigning unreasonably short
+ TTLs to the SRV RRs, which would limit the usefulness of the DNS
+ caching mechanism, thus increasing overall network load and
+ decreasing overall reliability. Server selection via SRV is only
+ intended to express static information such as "this server has a
+ faster CPU than that one" or "this server has a much better network
+ connection than that one".
+
+The Port number
+
+ Currently, the translation from service name to port number happens
+ at the client, often using a file such as /etc/services.
+
+ Moving this information to the DNS makes it less necessary to update
+ these files on every single computer of the net every time a new
+ service is added, and makes it possible to move standard services out
+ of the "root-only" port range on unix.
+
+Usage rules
+
+ A SRV-cognizant client SHOULD use this procedure to locate a list of
+ servers and connect to the preferred one:
+
+ Do a lookup for QNAME=_service._protocol.target, QCLASS=IN,
+ QTYPE=SRV.
+
+ If the reply is NOERROR, ANCOUNT>0 and there is at least one
+ SRV RR which specifies the requested Service and Protocol in
+ the reply:
+
+ If there is precisely one SRV RR, and its Target is "."
+ (the root domain), abort.
+
+
+
+
+
+Gulbrandsen, et al. Standards Track [Page 6]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+ Else, for all such RR's, build a list of (Priority, Weight,
+ Target) tuples
+
+ Sort the list by priority (lowest number first)
+
+ Create a new empty list
+
+ For each distinct priority level
+ While there are still elements left at this priority
+ level
+
+ Select an element as specified above, in the
+ description of Weight in "The format of the SRV
+ RR" Section, and move it to the tail of the new
+ list
+
+ For each element in the new list
+
+ query the DNS for address records for the Target or
+ use any such records found in the Additional Data
+ section of the earlier SRV response.
+
+ for each address record found, try to connect to the
+ (protocol, address, service).
+
+ else
+
+ Do a lookup for QNAME=target, QCLASS=IN, QTYPE=A
+
+ for each address record found, try to connect to the
+ (protocol, address, service)
+
+Notes:
+
+ - Port numbers SHOULD NOT be used in place of the symbolic service
+ or protocol names (for the same reason why variant names cannot
+ be allowed: Applications would have to do two or more lookups).
+
+ - If a truncated response comes back from an SRV query, the rules
+ described in [RFC 2181] shall apply.
+
+ - A client MUST parse all of the RR's in the reply.
+
+ - If the Additional Data section doesn't contain address records
+ for all the SRV RR's and the client may want to connect to the
+ target host(s) involved, the client MUST look up the address
+ record(s). (This happens quite often when the address record
+ has shorter TTL than the SRV or NS RR's.)
+
+
+
+Gulbrandsen, et al. Standards Track [Page 7]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+ - Future protocols could be designed to use SRV RR lookups as the
+ means by which clients locate their servers.
+
+Fictional example
+
+ This example uses fictional service "foobar" as an aid in
+ understanding SRV records. If ever service "foobar" is implemented,
+ it is not intended that it will necessarily use SRV records. This is
+ (part of) the zone file for example.com, a still-unused domain:
+
+ $ORIGIN example.com.
+ @ SOA server.example.com. root.example.com. (
+ 1995032001 3600 3600 604800 86400 )
+ NS server.example.com.
+ NS ns1.ip-provider.net.
+ NS ns2.ip-provider.net.
+ ; foobar - use old-slow-box or new-fast-box if either is
+ ; available, make three quarters of the logins go to
+ ; new-fast-box.
+ _foobar._tcp SRV 0 1 9 old-slow-box.example.com.
+ SRV 0 3 9 new-fast-box.example.com.
+ ; if neither old-slow-box or new-fast-box is up, switch to
+ ; using the sysdmin's box and the server
+ SRV 1 0 9 sysadmins-box.example.com.
+ SRV 1 0 9 server.example.com.
+ server A 172.30.79.10
+ old-slow-box A 172.30.79.11
+ sysadmins-box A 172.30.79.12
+ new-fast-box A 172.30.79.13
+ ; NO other services are supported
+ *._tcp SRV 0 0 0 .
+ *._udp SRV 0 0 0 .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gulbrandsen, et al. Standards Track [Page 8]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+ In this example, a client of the "foobar" service in the
+ "example.com." domain needs an SRV lookup of
+ "_foobar._tcp.example.com." and possibly A lookups of "new-fast-
+ box.example.com." and/or the other hosts named. The size of the SRV
+ reply is approximately 365 bytes:
+
+ 30 bytes general overhead
+ 20 bytes for the query string, "_foobar._tcp.example.com."
+ 130 bytes for 4 SRV RR's, 20 bytes each plus the lengths of "new-
+ fast-box", "old-slow-box", "server" and "sysadmins-box" -
+ "example.com" in the query section is quoted here and doesn't
+ need to be counted again.
+ 75 bytes for 3 NS RRs, 15 bytes each plus the lengths of "server",
+ "ns1.ip-provider.net." and "ns2" - again, "ip-provider.net." is
+ quoted and only needs to be counted once.
+ 120 bytes for the 6 address records (assuming IPv4 only) mentioned
+ by the SRV and NS RR's.
+
+IANA Considerations
+
+ The IANA has assigned RR type value 33 to the SRV RR. No other IANA
+ services are required by this document.
+
+Changes from RFC 2052
+
+ This document obsoletes RFC 2052. The major change from that
+ previous, experimental, version of this specification is that now the
+ protocol and service labels are prepended with an underscore, to
+ lower the probability of an accidental clash with a similar name used
+ for unrelated purposes. Aside from that, changes are only intended
+ to increase the clarity and completeness of the document. This
+ document especially clarifies the use of the Weight field of the SRV
+ records.
+
+Security Considerations
+
+ The authors believe this RR to not cause any new security problems.
+ Some problems become more visible, though.
+
+ - The ability to specify ports on a fine-grained basis obviously
+ changes how a router can filter packets. It becomes impossible
+ to block internal clients from accessing specific external
+ services, slightly harder to block internal users from running
+ unauthorized services, and more important for the router
+ operations and DNS operations personnel to cooperate.
+
+ - There is no way a site can keep its hosts from being referenced
+ as servers. This could lead to denial of service.
+
+
+
+Gulbrandsen, et al. Standards Track [Page 9]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+ - With SRV, DNS spoofers can supply false port numbers, as well as
+ host names and addresses. Because this vulnerability exists
+ already, with names and addresses, this is not a new
+ vulnerability, merely a slightly extended one, with little
+ practical effect.
+
+References
+
+ STD 2: Reynolds, J., and J. Postel, "Assigned Numbers", STD 2, RFC
+ 1700, October 1994.
+
+ RFC 1034: Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ RFC 1035: Mockapetris, P., "Domain names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ RFC 974: Partridge, C., "Mail routing and the domain system", STD
+ 14, RFC 974, January 1986.
+
+ BCP 14: Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ RFC 2181: Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ RFC 2219: Hamilton, M. and R. Wright, "Use of DNS Aliases for Network
+ Services", BCP 17, RFC 2219, October 1997.
+
+ BCP 14: Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ ARM: Armijo, M., Esibov, L. and P. Leach, "Discovering LDAP
+ Services with DNS", Work in Progress.
+
+ KDC-DNS: Hornstein, K. and J. Altman, "Distributing Kerberos KDC and
+ Realm Information with DNS", Work in Progress.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gulbrandsen, et al. Standards Track [Page 10]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+Acknowledgements
+
+ The algorithm used to select from the weighted SRV RRs of equal
+ priority is adapted from one supplied by Dan Bernstein.
+
+Authors' Addresses
+
+ Arnt Gulbrandsen
+ Troll Tech
+ Waldemar Thranes gate 98B
+ N-0175 Oslo, Norway
+
+ Fax: +47 22806380
+ Phone: +47 22806390
+ EMail: arnt@troll.no
+
+
+ Paul Vixie
+ Internet Software Consortium
+ 950 Charter Street
+ Redwood City, CA 94063
+
+ Phone: +1 650 779 7001
+
+
+ Levon Esibov
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+
+ EMail: levone@microsoft.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gulbrandsen, et al. Standards Track [Page 11]
+
+RFC 2782 DNS SRV RR February 2000
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gulbrandsen, et al. Standards Track [Page 12]
+
diff --git a/doc/rfc/rfc2825.txt b/doc/rfc/rfc2825.txt
new file mode 100644
index 0000000..fd8ef7c
--- /dev/null
+++ b/doc/rfc/rfc2825.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group Internet Architecture Board (IAB)
+Request for Comments: 2825 L. Daigle, Editor
+Category: Informational May 2000
+
+
+ A Tangled Web: Issues of I18N, Domain Names, and the
+ Other Internet protocols
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ The goals of the work to "internationalize" Internet protocols
+ include providing all users of the Internet with the capability of
+ using their own language and its standard character set to express
+ themselves, write names, and to navigate the network. This impacts
+ the domain names visible in e-mail addresses and so many of today's
+ URLs used to locate information on the World Wide Web, etc. However,
+ domain names are used by Internet protocols that are used across
+ national boundaries. These services must interoperate worldwide, or
+ we risk isolating components of the network from each other along
+ locale boundaries. This type of isolation could impede not only
+ communications among people, but opportunities of the areas involved
+ to participate effectively in e-commerce, distance learning, and
+ other activities at an international scale, thereby retarding
+ economic development.
+
+ There are several proposals for internationalizing domain names,
+ however it it is still to be determined whether any of them will
+ ensure this interoperability and global reach while addressing
+ visible-name representation. Some of them obviously do not. This
+ document does not attempt to review any specific proposals, as that
+ is the work of the Internationalized Domain Name (IDN) Working Group
+ of the IETF, which is tasked with evaluating them in consideration of
+ the continued global network interoperation that is the deserved
+ expectation of all Internet users.
+
+
+
+
+
+
+
+IAB Informational [Page 1]
+
+RFC 2825 Issues: I18N, Domain Names, and Internet Protocols May 2000
+
+
+ This document is a statement by the Internet Architecture Board. It
+ is not a protocol specification, but an attempt to clarify the range
+ of architectural issues that the internationalization of domain names
+ faces.
+
+1. A Definition of Success
+
+ The Internationalized Domain Names (IDN) Working Group is one
+ component of the IETF's continuing comprehensive effort to
+ internationalize language representation facilities in the protocols
+ that support the global functioning of the Internet.
+
+ In keeping with the principles of rough consensus, running code,
+ architectural integrity, and in the interest of ensuring the global
+ stability of the Internet, the IAB emphasizes that all solutions
+ proposed to the (IDN) Working Group will have to be evaluated not
+ only on their individual technical features, but also in terms of
+ impact on existing standards and operations of the Internet and the
+ total effect for end-users: solutions must not cause users to become
+ more isolated from their global neighbors even if they appear to
+ solve a local problem. In some cases, existing protocols have
+ limitations on allowable characters, and in other cases
+ implementations of protocols used in the core of the Internet (beyond
+ individual organizations) have in practice not implemented all the
+ requisite options of the standards.
+
+2. Technical Challenges within the Domain Name System (DNS)
+
+ In many technical respects, the IDN work is not different from any
+ other effort to enable multiple character set representations in
+ textual elements that were traditionally restricted to English
+ language characters.
+
+ One aspect of the challenge is to decide how to represent the names
+ users want in the DNS in a way that is clear, technically feasible,
+ and ensures that a name always means the same thing. Several
+ proposals have been suggested to address these issues.
+
+ These issues are being outlined in more detail in the IDN WG's
+ evolving draft requirements document; further discussion is deferred
+ to the WG and its documents.
+
+3. Integrating with Current Realities
+
+ Nevertheless, issues faced by the IDN working group are complex and
+ intricately intertwined with other operational components of the
+ Internet. A key challenge in evaluating any proposed solution is the
+ analysis of the impact on existing critical operational standards
+
+
+
+IAB Informational [Page 2]
+
+RFC 2825 Issues: I18N, Domain Names, and Internet Protocols May 2000
+
+
+ which use fully-qualified domain names [RFC1034], or simply host
+ names [RFC1123]. Standards-changes can be effected, but the best
+ path forward is one that takes into account current realities and
+ (re)deployment latencies. In the Internet's global context, it is not
+ enough to update a few isolated systems, or even most of the systems
+ in a country or region. Deployment must be nearly universal in order
+ to avoid the creation of "islands" of interoperation that provide
+ users with less access to and connection from the rest of the world.
+
+ These are not esoteric or ephemeral concerns. Some specific issues
+ have already been identified as part of the IDN WG's efforts. These
+ include (but are not limited to) the following examples.
+
+3.1 Domain Names and E-mail
+
+ As indicated in the IDN WG's draft requirements document, the issue
+ goes beyond standardization of DNS usage. Electronic mail has long
+ been one of the most-used and most important applications of the
+ Internet. Internet e-mail is also used as the bridge that permits
+ the users of a variety of local and proprietary mail systems to
+ communicate. The standard protocols that define its use (e.g., SMTP
+ [RFC821, RFC822] and MIME [RFC2045]) do not permit the full range of
+ characters allowed in the DNS specification. Certain characters are
+ not allowed in e-mail address domain portions of these
+ specifications. Some mailers, built to adhere to these
+ specifications, are known to fail when on mail having non-ASCII
+ domain names in its address -- by discarding, misrouting or damaging
+ the mail. Thus, it's not possible to simply switch to
+ internationalized domain names and expect global e-mail to continue
+ to work until most of the servers in the world are upgraded.
+
+3.2 Domain Names and Routing
+
+ At a lower level, the Routing Policy Specification Language (RPLS)
+ [RFC2622] makes use of "named objects" -- and inherits object naming
+ restrictions from older standards ([RFC822] for the same e-mail
+ address restrictions, [RFC1034] for hostnames). This means that
+ until routing registries and their protocols are updated, it is not
+ possible to enter or retrieve network descriptions utilizing
+ internationalized domain names.
+
+3.3 Domain Names and Network Management
+
+ Also, the Simple Network Management Protocol (SNMP) uses the textual
+ representation defined in [RFC2579]. While that specification does
+ allow for UTF-8-based domain names, an informal survey of deployed
+ implementations of software libraries being used to build SNMP-
+ compliant software uncovered the fact that few (if any) implement it.
+
+
+
+IAB Informational [Page 3]
+
+RFC 2825 Issues: I18N, Domain Names, and Internet Protocols May 2000
+
+
+ This may cause inability to enter or display correct data in network
+ management tools, if such names are internationalized domain names.
+
+3.4 Domain Names and Security
+
+ Critical components of Internet public key technologies (PKIX,
+ [RFC2459], IKE [RFC2409]) rely heavily on identification of servers
+ (hostnames, or fully qualified domain names) and users (e-mail
+ addresses). Failure to respect the character restrictions in these
+ protocols will impact security tools built to use them -- Transport
+ Layer Security protocol (TLS, [RFC2246]), and IPsec [RFC2401] to name
+ two.
+
+ Failure may not be obvious. For example, in TLS, it is common usage
+ for a server to display a certificate containing a domain name
+ purporting to be the domain name of the server, which the client can
+ then match with the server name he thought he used to reach the
+ service.
+
+ Unless comparison of domain names is properly defined, the client may
+ either fail to match the domain name of a legitimate server, or match
+ incorrectly the domain name of a server performing a man-in-the-
+ middle attack. Either failure could enable attacks on systems that
+ are now impossible or at least far more difficult.
+
+4. Conclusion
+
+ It is therefore clear that, although there are many possible ways to
+ assign internationalized names that are compatible with today's DNS
+ (or a version that is easily-deployable in the near future), not all
+ of them are compatible with the full range of necessary networking
+ tools. When designing a solution for internationalization of domain
+ names, the effects on the current Internet must be carefully
+ evaluated. Some types of solutions proposed would, if put into effect
+ immediately, cause Internet communications to fail in ways that would
+ be hard to detect by and pose problems for those who deploy the new
+ services, but also for those who do not; this would have the effect
+ of cutting those who deploy them off from effective use of the
+ Internet.
+
+ The IDN WG has been identified as the appropriate forum for
+ identifying and discussing solutions for such potential
+ interoperability issues.
+
+ Experience with deployment of other protocols has indicated that it
+ will take years before a new protocol or enhancement is used all over
+ the Internet. So far, the IDN WG has benefited from proposed
+ solutions from all quarters, including organizations hoping to
+
+
+
+IAB Informational [Page 4]
+
+RFC 2825 Issues: I18N, Domain Names, and Internet Protocols May 2000
+
+
+ provide services that address visible-name representation and
+ registration -- continuing this process with the aim of getting a
+ single, scalable and deployable solution to this problem is the only
+ way to ensure the continued global interoperation that is the
+ deserved expectation of all Internet users.
+
+5. Security Considerations
+
+ In general, assignment and use of names does not raise any special
+ security problems. However, as noted above, some existing security
+ mechanisms are reliant on the current specification of domain names
+ and may not be expected to work, as is, with Internationalized domain
+ names. Additionally, deployment of non-standard systems (e.g., in
+ response to current pressures to address national or regional
+ characterset representation) might result in name strings that are
+ not globally unique, thereby opening up the possibility of "spoofing"
+ hosts from one domain in another, as described in [RFC2826].
+
+6. Acknowledgements
+
+ This document is the outcome of the joint effort of the members of
+ the IAB. Additionally, valuable remarks were provided by Randy Bush,
+ Patrik Faltstrom, Ted Hardie, Paul Hoffman, and Mark Kosters.
+
+7. References
+
+ [RFC821] Postel, J., "Simple Mail Transfer Protocol", STD 10, RFC
+ 821, August 1982.
+
+ [RFC822] Crocker, D., "Standard for the Format of ARPA Internet Text
+ Messages", STD 11, RFC 822, August 1982.
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts -- Application
+ and Support", STD 3, RFC 1123, November 1989.
+
+ [RFC2401] Kent, S. and R. Atkinson, "Security Architecture for the
+ Internet Protocol", RFC 2401, November 1998.
+
+ [RFC2409] Harkins, D and D. Carrel, "The Internet Key Exchange
+ (IKE)", RFC 2409, November 1998.
+
+ [RFC2045] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message
+ Bodies", RFC 2045, November 1996.
+
+
+
+
+IAB Informational [Page 5]
+
+RFC 2825 Issues: I18N, Domain Names, and Internet Protocols May 2000
+
+
+ [RFC2246] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0",
+ RFC 2246, January 1999.
+
+ [RFC2459] Housley, R., Ford, W., Polk, W. and D. Solo, "Internet
+ X.509 Public Key Infrastructure Certificate and CRL
+ Profile", RFC 2459, January 1999.
+
+ [RFC2579] McCloghrie, K., Perkins, D., Schoenwaelder, J., Case, J.
+ and M. Rose, "Textual Conventions for SMIv2", RFC 2579,
+ April 1999.
+
+ [RFC2622] Alaettinoglu, C., Villamizar, C., Gerich, E., Kessens, D.,
+ Meyer, D., Bates, T., Karrenberg, D. and M. Terpstra,
+ "Routing Policy Specification Language (RPSL)", RFC 2622,
+ June 1999.
+
+ [RFC2826] IAB, "IAB Technical Comment on the Unique DNS Root", RFC
+ 2826, May 2000.
+
+8. Author's Address
+
+ Internet Architecture Board
+
+ EMail: iab@iab.org
+
+
+ Membership at time this document was completed:
+
+ Harald Alvestrand
+ Ran Atkinson
+ Rob Austein
+ Brian Carpenter
+ Steve Bellovin
+ Jon Crowcroft
+ Leslie Daigle
+ Steve Deering
+ Tony Hain
+ Geoff Huston
+ John Klensin
+ Henning Schulzrinne
+
+
+
+
+
+
+
+
+
+
+
+IAB Informational [Page 6]
+
+RFC 2825 Issues: I18N, Domain Names, and Internet Protocols May 2000
+
+
+9. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+IAB Informational [Page 7]
+
diff --git a/doc/rfc/rfc2826.txt b/doc/rfc/rfc2826.txt
new file mode 100644
index 0000000..b4d8869
--- /dev/null
+++ b/doc/rfc/rfc2826.txt
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+Network Working Group Internet Architecture Board
+Request for Comments: 2826 May 2000
+Category: Informational
+
+
+ IAB Technical Comment on the Unique DNS Root
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Summary
+
+ To remain a global network, the Internet requires the existence of a
+ globally unique public name space. The DNS name space is a
+ hierarchical name space derived from a single, globally unique root.
+ This is a technical constraint inherent in the design of the DNS.
+ Therefore it is not technically feasible for there to be more than
+ one root in the public DNS. That one root must be supported by a set
+ of coordinated root servers administered by a unique naming
+ authority.
+
+ Put simply, deploying multiple public DNS roots would raise a very
+ strong possibility that users of different ISPs who click on the same
+ link on a web page could end up at different destinations, against
+ the will of the web page designers.
+
+ This does not preclude private networks from operating their own
+ private name spaces, but if they wish to make use of names uniquely
+ defined for the global Internet, they have to fetch that information
+ from the global DNS naming hierarchy, and in particular from the
+ coordinated root servers of the global DNS naming hierarchy.
+
+1. Detailed Explanation
+
+ There are several distinct reasons why the DNS requires a single root
+ in order to operate properly.
+
+1.1. Maintenance of a Common Symbol Set
+
+ Effective communications between two parties requires two essential
+ preconditions:
+
+
+
+IAB Informational [Page 1]
+
+RFC 2826 IAB Technical Comment on the Unique DNS Root May 2000
+
+
+ - The existence of a common symbol set, and
+
+ - The existence of a common semantic interpretation of these
+ symbols.
+
+ Failure to meet the first condition implies a failure to communicate
+ at all, while failure to meet the second implies that the meaning of
+ the communication is lost.
+
+ In the case of a public communications system this condition of a
+ common symbol set with a common semantic interpretation must be
+ further strengthened to that of a unique symbol set with a unique
+ semantic interpretation. This condition of uniqueness allows any
+ party to initiate a communication that can be received and understood
+ by any other party. Such a condition rules out the ability to define
+ a symbol within some bounded context. In such a case, once the
+ communication moves out of the context of interpretation in which it
+ was defined, the meaning of the symbol becomes lost.
+
+ Within public digital communications networks such as the Internet
+ this requirement for a uniquely defined symbol set with a uniquely
+ defined meaning exists at many levels, commencing with the binary
+ encoding scheme, extending to packet headers and payload formats and
+ the protocol that an application uses to interact. In each case a
+ variation of the symbol set or a difference of interpretation of the
+ symbols being used within the interaction causes a protocol failure,
+ and the communication fails. The property of uniqueness allows a
+ symbol to be used unambiguously in any context, allowing the symbol
+ to be passed on, referred to, and reused, while still preserving the
+ meaning of the original use.
+
+ The DNS fulfills an essential role within the Internet protocol
+ environment, allowing network locations to be referred to using a
+ label other than a protocol address. As with any other such symbol
+ set, DNS names are designed to be globally unique, that is, for any
+ one DNS name at any one time there must be a single set of DNS
+ records uniquely describing protocol addresses, network resources and
+ services associated with that DNS name. All of the applications
+ deployed on the Internet which use the DNS assume this, and Internet
+ users expect such behavior from DNS names. Names are then constant
+ symbols, whose interpretation does not specifically require knowledge
+ of the context of any individual party. A DNS name can be passed
+ from one party to another without altering the semantic intent of the
+ name.
+
+ Since the DNS is hierarchically structured into domains, the
+ uniqueness requirement for DNS names in their entirety implies that
+ each of the names (sub-domains) defined within a domain has a unique
+
+
+
+IAB Informational [Page 2]
+
+RFC 2826 IAB Technical Comment on the Unique DNS Root May 2000
+
+
+ meaning (i.e., set of DNS records) within that domain. This is as
+ true for the root domain as for any other DNS domain. The
+ requirement for uniqueness within a domain further implies that there
+ be some mechanism to prevent name conflicts within a domain. In DNS
+ this is accomplished by assigning a single owner or maintainer to
+ every domain, including the root domain, who is responsible for
+ ensuring that each sub-domain of that domain has the proper records
+ associated with it. This is a technical requirement, not a policy
+ choice.
+
+1.2. Coordination of Updates
+
+ Both the design and implementations of the DNS protocol are heavily
+ based on the assumption that there is a single owner or maintainer
+ for every domain, and that any set of resources records associated
+ with a domain is modified in a single-copy serializable fashion.
+ That is, even assuming that a single domain could somehow be "shared"
+ by uncooperating parties, there is no means within the DNS protocol
+ by which a user or client could discover, and choose between,
+ conflicting definitions of a DNS name made by different parties. The
+ client will simply return the first set of resource records that it
+ finds that matches the requested domain, and assume that these are
+ valid. This protocol is embedded in the operating software of
+ hundreds of millions of computer systems, and is not easily updated
+ to support a shared domain scenario.
+
+ Moreover, even supposing that some other means of resolving
+ conflicting definitions could be provided in the future, it would
+ have to be based on objective rules established in advance. For
+ example, zone A.B could declare that naming authority Y had been
+ delegated all subdomains of A.B with an odd number of characters, and
+ that naming authority Z had been delegated authority to define
+ subdomains of A.B with an even number of characters. Thus, a single
+ set of rules would have to be agreed to prevent Y and Z from making
+ conflicting assignments, and with this train of actions a single
+ unique space has been created in any case. Even this would not allow
+ multiple non-cooperating authorities to assign arbitrary sub-domains
+ within a single domain.
+
+ It seems that a degree of cooperation and agreed technical rules are
+ required in order to guarantee the uniqueness of names. In the DNS,
+ these rules are established independently for each part of the naming
+ hierarchy, and the root domain is no exception. Thus, there must be
+ a generally agreed single set of rules for the root.
+
+
+
+
+
+
+
+IAB Informational [Page 3]
+
+RFC 2826 IAB Technical Comment on the Unique DNS Root May 2000
+
+
+1.3. Difficulty of Relocating the Root Zone
+
+ There is one specific technical respect in which the root zone
+ differs from all other DNS zones: the addresses of the name servers
+ for the root zone come primarily from out-of-band information. This
+ out-of-band information is often poorly maintained and, unlike all
+ other data in the DNS, the out-of-band information has no automatic
+ timeout mechanism. It is not uncommon for this information to be
+ years out of date at many sites.
+
+ Like any other zone, the root zone contains a set of "name server"
+ resource records listing its servers, but a resolver with no valid
+ addresses for the current set of root servers will never be able to
+ obtain these records. More insidiously, a resolver that has a mixed
+ set of partially valid and partially stale out-of-band configuration
+ information will not be able to tell which are the "real" root
+ servers if it gets back conflicting answers; thus, it is very
+ difficult to revoke the status of a malicious root server, or even to
+ route around a buggy root server.
+
+ In effect, every full-service resolver in the world "delegates" the
+ root of the public tree to the public root server(s) of its choice.
+
+ As a direct consequence, any change to the list of IP addresses that
+ specify the public root zone is significantly more difficult than
+ changing any other aspect of the DNS delegation chain. Thus,
+ stability of the system calls for extremely conservative and cautious
+ management of the public root zone: the frequency of updates to the
+ root zone must be kept low, and the servers for the root zone must be
+ closely coordinated.
+
+ These problems can be ameliorated to some extent by the DNS Security
+ Extensions [DNSSEC], but a similar out-of-band configuration problem
+ exists for the cryptographic signature key to the root zone, so the
+ root zone still requires tight coupling and coordinated management
+ even in the presence of DNSSEC.
+
+2. Conclusion
+
+ The DNS type of unique naming and name-mapping system may not be
+ ideal for a number of purposes for which it was never designed, such
+ a locating information when the user doesn't precisely know the
+ correct names. As the Internet continues to expand, we would expect
+ directory systems to evolve which can assist the user in dealing with
+ vague or ambiguous references. To preserve the many important
+ features of the DNS and its multiple record types -- including the
+ Internet's equivalent of telephone number portability -- we would
+ expect the result of directory lookups and identification of the
+
+
+
+IAB Informational [Page 4]
+
+RFC 2826 IAB Technical Comment on the Unique DNS Root May 2000
+
+
+ correct names for a particular purpose to be unique DNS names that
+ are then resolved normally, rather than having directory systems
+ "replace" the DNS.
+
+ There is no getting away from the unique root of the public DNS.
+
+3. Security Considerations
+
+ This memo does not introduce any new security issues, but it does
+ attempt to identify some of the problems inherent in a family of
+ recurring technically naive proposals.
+
+4. IANA Considerations
+
+ This memo is not intended to create any new issues for IANA.
+
+5. References
+
+ [DNS-CONCEPTS] Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [DNS-IMPLEMENTATION] Mockapetris, P., "Domain Names - Implementation
+ and Specification", STD 13, RFC 1035, November
+ 1987.
+
+ [DNSSEC] Eastlake, D., "Domain Name System Security
+ Extensions", RFC 2535, March 1999.
+
+6. Author's Address
+
+ Internet Architecture Board
+
+ EMail: iab@iab.org
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+IAB Informational [Page 5]
+
+RFC 2826 IAB Technical Comment on the Unique DNS Root May 2000
+
+
+7. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+IAB Informational [Page 6]
+
diff --git a/doc/rfc/rfc2845.txt b/doc/rfc/rfc2845.txt
new file mode 100644
index 0000000..aa9f385
--- /dev/null
+++ b/doc/rfc/rfc2845.txt
@@ -0,0 +1,843 @@
+
+
+
+
+
+
+Network Working Group P. Vixie
+Request for Comments: 2845 ISC
+Category: Standards Track O. Gudmundsson
+Updates: 1035 NAI Labs
+ D. Eastlake 3rd
+ Motorola
+ B. Wellington
+ Nominum
+ May 2000
+
+
+ Secret Key Transaction Authentication for DNS (TSIG)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ This protocol allows for transaction level authentication using
+ shared secrets and one way hashing. It can be used to authenticate
+ dynamic updates as coming from an approved client, or to authenticate
+ responses as coming from an approved recursive name server.
+
+ No provision has been made here for distributing the shared secrets;
+ it is expected that a network administrator will statically configure
+ name servers and clients using some out of band mechanism such as
+ sneaker-net until a secure automated mechanism for key distribution
+ is available.
+
+1 - Introduction
+
+ 1.1. The Domain Name System (DNS) [RFC1034, RFC1035] is a replicated
+ hierarchical distributed database system that provides information
+ fundamental to Internet operations, such as name <=> address
+ translation and mail handling information. DNS has recently been
+ extended [RFC2535] to provide for data origin authentication, and
+ public key distribution, all based on public key cryptography and
+ public key based digital signatures. To be practical, this form of
+
+
+
+
+Vixie, et al. Standards Track [Page 1]
+
+RFC 2845 DNS TSIG May 2000
+
+
+ security generally requires extensive local caching of keys and
+ tracing of authentication through multiple keys and signatures to a
+ pre-trusted locally configured key.
+
+ 1.2. One difficulty with the [RFC2535] scheme is that common DNS
+ implementations include simple "stub" resolvers which do not have
+ caches. Such resolvers typically rely on a caching DNS server on
+ another host. It is impractical for these stub resolvers to perform
+ general [RFC2535] authentication and they would naturally depend on
+ their caching DNS server to perform such services for them. To do so
+ securely requires secure communication of queries and responses.
+ [RFC2535] provides public key transaction signatures to support this,
+ but such signatures are very expensive computationally to generate.
+ In general, these require the same complex public key logic that is
+ impractical for stubs. This document specifies use of a message
+ authentication code (MAC), specifically HMAC-MD5 (a keyed hash
+ function), to provide an efficient means of point-to-point
+ authentication and integrity checking for transactions.
+
+ 1.3. A second area where use of straight [RFC2535] public key based
+ mechanisms may be impractical is authenticating dynamic update
+ [RFC2136] requests. [RFC2535] provides for request signatures but
+ with [RFC2535] they, like transaction signatures, require
+ computationally expensive public key cryptography and complex
+ authentication logic. Secure Domain Name System Dynamic Update
+ ([RFC2137]) describes how different keys are used in dynamically
+ updated zones. This document's secret key based MACs can be used to
+ authenticate DNS update requests as well as transaction responses,
+ providing a lightweight alternative to the protocol described by
+ [RFC2137].
+
+ 1.4. A further use of this mechanism is to protect zone transfers.
+ In this case the data covered would be the whole zone transfer
+ including any glue records sent. The protocol described by [RFC2535]
+ does not protect glue records and unsigned records unless SIG(0)
+ (transaction signature) is used.
+
+ 1.5. The authentication mechanism proposed in this document uses
+ shared secret keys to establish a trust relationship between two
+ entities. Such keys must be protected in a fashion similar to
+ private keys, lest a third party masquerade as one of the intended
+ parties (forge MACs). There is an urgent need to provide simple and
+ efficient authentication between clients and local servers and this
+ proposal addresses that need. This proposal is unsuitable for
+ general server to server authentication for servers which speak with
+ many other servers, since key management would become unwieldy with
+
+
+
+
+
+Vixie, et al. Standards Track [Page 2]
+
+RFC 2845 DNS TSIG May 2000
+
+
+ the number of shared keys going up quadratically. But it is suitable
+ for many resolvers on hosts that only talk to a few recursive
+ servers.
+
+ 1.6. A server acting as an indirect caching resolver -- a "forwarder"
+ in common usage -- might use transaction-based authentication when
+ communicating with its small number of preconfigured "upstream"
+ servers. Other uses of DNS secret key authentication and possible
+ systems for automatic secret key distribution may be proposed in
+ separate future documents.
+
+ 1.7. New Assigned Numbers
+
+ RRTYPE = TSIG (250)
+ ERROR = 0..15 (a DNS RCODE)
+ ERROR = 16 (BADSIG)
+ ERROR = 17 (BADKEY)
+ ERROR = 18 (BADTIME)
+
+ 1.8. The key words "MUST", "REQUIRED", "SHOULD", "RECOMMENDED", and
+ "MAY" in this document are to be interpreted as described in [RFC
+ 2119].
+
+2 - TSIG RR Format
+
+ 2.1 TSIG RR Type
+
+ To provide secret key authentication, we use a new RR type whose
+ mnemonic is TSIG and whose type code is 250. TSIG is a meta-RR and
+ MUST not be cached. TSIG RRs are used for authentication between DNS
+ entities that have established a shared secret key. TSIG RRs are
+ dynamically computed to cover a particular DNS transaction and are
+ not DNS RRs in the usual sense.
+
+ 2.2 TSIG Calculation
+
+ As the TSIG RRs are related to one DNS request/response, there is no
+ value in storing or retransmitting them, thus the TSIG RR is
+ discarded once it has been used to authenticate a DNS message. The
+ only message digest algorithm specified in this document is "HMAC-
+ MD5" (see [RFC1321], [RFC2104]). The "HMAC-MD5" algorithm is
+ mandatory to implement for interoperability. Other algorithms can be
+ specified at a later date. Names and definitions of new algorithms
+ MUST be registered with IANA. All multi-octet integers in the TSIG
+ record are sent in network byte order (see [RFC1035 2.3.2]).
+
+
+
+
+
+
+Vixie, et al. Standards Track [Page 3]
+
+RFC 2845 DNS TSIG May 2000
+
+
+ 2.3. Record Format
+
+ NAME The name of the key used in domain name syntax. The name
+ should reflect the names of the hosts and uniquely identify
+ the key among a set of keys these two hosts may share at any
+ given time. If hosts A.site.example and B.example.net share a
+ key, possibilities for the key name include
+ <id>.A.site.example, <id>.B.example.net, and
+ <id>.A.site.example.B.example.net. It should be possible for
+ more than one key to be in simultaneous use among a set of
+ interacting hosts. The name only needs to be meaningful to
+ the communicating hosts but a meaningful mnemonic name as
+ above is strongly recommended.
+
+ The name may be used as a local index to the key involved and
+ it is recommended that it be globally unique. Where a key is
+ just shared between two hosts, its name actually only need
+ only be meaningful to them but it is recommended that the key
+ name be mnemonic and incorporate the resolver and server host
+ names in that order.
+
+ TYPE TSIG (250: Transaction SIGnature)
+
+ CLASS ANY
+
+ TTL 0
+
+ RdLen (variable)
+
+ RDATA
+
+ Field Name Data Type Notes
+ --------------------------------------------------------------
+ Algorithm Name domain-name Name of the algorithm
+ in domain name syntax.
+ Time Signed u_int48_t seconds since 1-Jan-70 UTC.
+ Fudge u_int16_t seconds of error permitted
+ in Time Signed.
+ MAC Size u_int16_t number of octets in MAC.
+ MAC octet stream defined by Algorithm Name.
+ Original ID u_int16_t original message ID
+ Error u_int16_t expanded RCODE covering
+ TSIG processing.
+ Other Len u_int16_t length, in octets, of
+ Other Data.
+ Other Data octet stream empty unless Error == BADTIME
+
+
+
+
+
+Vixie, et al. Standards Track [Page 4]
+
+RFC 2845 DNS TSIG May 2000
+
+
+ 2.4. Example
+
+ NAME HOST.EXAMPLE.
+
+ TYPE TSIG
+
+ CLASS ANY
+
+ TTL 0
+
+ RdLen as appropriate
+
+ RDATA
+
+ Field Name Contents
+ -------------------------------------
+ Algorithm Name SAMPLE-ALG.EXAMPLE.
+ Time Signed 853804800
+ Fudge 300
+ MAC Size as appropriate
+ MAC as appropriate
+ Original ID as appropriate
+ Error 0 (NOERROR)
+ Other Len 0
+ Other Data empty
+
+3 - Protocol Operation
+
+ 3.1. Effects of adding TSIG to outgoing message
+
+ Once the outgoing message has been constructed, the keyed message
+ digest operation can be performed. The resulting message digest will
+ then be stored in a TSIG which is appended to the additional data
+ section (the ARCOUNT is incremented to reflect this). If the TSIG
+ record cannot be added without causing the message to be truncated,
+ the server MUST alter the response so that a TSIG can be included.
+ This response consists of only the question and a TSIG record, and
+ has the TC bit set and RCODE 0 (NOERROR). The client SHOULD at this
+ point retry the request using TCP (per [RFC1035 4.2.2]).
+
+ 3.2. TSIG processing on incoming messages
+
+ If an incoming message contains a TSIG record, it MUST be the last
+ record in the additional section. Multiple TSIG records are not
+ allowed. If a TSIG record is present in any other position, the
+ packet is dropped and a response with RCODE 1 (FORMERR) MUST be
+ returned. Upon receipt of a message with a correctly placed TSIG RR,
+ the TSIG RR is copied to a safe location, removed from the DNS
+
+
+
+Vixie, et al. Standards Track [Page 5]
+
+RFC 2845 DNS TSIG May 2000
+
+
+ Message, and decremented out of the DNS message header's ARCOUNT. At
+ this point the keyed message digest operation is performed. If the
+ algorithm name or key name is unknown to the recipient, or if the
+ message digests do not match, the whole DNS message MUST be
+ discarded. If the message is a query, a response with RCODE 9
+ (NOTAUTH) MUST be sent back to the originator with TSIG ERROR 17
+ (BADKEY) or TSIG ERROR 16 (BADSIG). If no key is available to sign
+ this message it MUST be sent unsigned (MAC size == 0 and empty MAC).
+ A message to the system operations log SHOULD be generated, to warn
+ the operations staff of a possible security incident in progress.
+ Care should be taken to ensure that logging of this type of event
+ does not open the system to a denial of service attack.
+
+ 3.3. Time values used in TSIG calculations
+
+ The data digested includes the two timer values in the TSIG header in
+ order to defend against replay attacks. If this were not done, an
+ attacker could replay old messages but update the "Time Signed" and
+ "Fudge" fields to make the message look new. This data is named
+ "TSIG Timers", and for the purpose of digest calculation they are
+ invoked in their "on the wire" format, in the following order: first
+ Time Signed, then Fudge. For example:
+
+Field Name Value Wire Format Meaning
+----------------------------------------------------------------------
+Time Signed 853804800 00 00 32 e4 07 00 Tue Jan 21 00:00:00 1997
+Fudge 300 01 2C 5 minutes
+
+ 3.4. TSIG Variables and Coverage
+
+ When generating or verifying the contents of a TSIG record, the
+ following data are digested, in network byte order or wire format, as
+ appropriate:
+
+ 3.4.1. DNS Message
+
+ A whole and complete DNS message in wire format, before the TSIG RR
+ has been added to the additional data section and before the DNS
+ Message Header's ARCOUNT field has been incremented to contain the
+ TSIG RR. If the message ID differs from the original message ID, the
+ original message ID is substituted for the message ID. This could
+ happen when forwarding a dynamic update request, for example.
+
+
+
+
+
+
+
+
+
+Vixie, et al. Standards Track [Page 6]
+
+RFC 2845 DNS TSIG May 2000
+
+
+ 3.4.2. TSIG Variables
+
+Source Field Name Notes
+-----------------------------------------------------------------------
+TSIG RR NAME Key name, in canonical wire format
+TSIG RR CLASS (Always ANY in the current specification)
+TSIG RR TTL (Always 0 in the current specification)
+TSIG RDATA Algorithm Name in canonical wire format
+TSIG RDATA Time Signed in network byte order
+TSIG RDATA Fudge in network byte order
+TSIG RDATA Error in network byte order
+TSIG RDATA Other Len in network byte order
+TSIG RDATA Other Data exactly as transmitted
+
+ The RR RDLEN and RDATA MAC Length are not included in the hash since
+ they are not guaranteed to be knowable before the MAC is generated.
+
+ The Original ID field is not included in this section, as it has
+ already been substituted for the message ID in the DNS header and
+ hashed.
+
+ For each label type, there must be a defined "Canonical wire format"
+ that specifies how to express a label in an unambiguous way. For
+ label type 00, this is defined in [RFC2535], for label type 01, this
+ is defined in [RFC2673]. The use of label types other than 00 and 01
+ is not defined for this specification.
+
+ 3.4.3. Request MAC
+
+ When generating the MAC to be included in a response, the request MAC
+ must be included in the digest. The request's MAC is digested in
+ wire format, including the following fields:
+
+ Field Type Description
+ ---------------------------------------------------
+ MAC Length u_int16_t in network byte order
+ MAC Data octet stream exactly as transmitted
+
+ 3.5. Padding
+
+ Digested components are fed into the hashing function as a continuous
+ octet stream with no interfield padding.
+
+
+
+
+
+
+
+
+
+Vixie, et al. Standards Track [Page 7]
+
+RFC 2845 DNS TSIG May 2000
+
+
+4 - Protocol Details
+
+ 4.1. TSIG generation on requests
+
+ Client performs the message digest operation and appends a TSIG
+ record to the additional data section and transmits the request to
+ the server. The client MUST store the message digest from the
+ request while awaiting an answer. The digest components for a
+ request are:
+
+ DNS Message (request)
+ TSIG Variables (request)
+
+ Note that some older name servers will not accept requests with a
+ nonempty additional data section. Clients SHOULD only attempt signed
+ transactions with servers who are known to support TSIG and share
+ some secret key with the client -- so, this is not a problem in
+ practice.
+
+ 4.2. TSIG on Answers
+
+ When a server has generated a response to a signed request, it signs
+ the response using the same algorithm and key. The server MUST not
+ generate a signed response to an unsigned request. The digest
+ components are:
+
+ Request MAC
+ DNS Message (response)
+ TSIG Variables (response)
+
+ 4.3. TSIG on TSIG Error returns
+
+ When a server detects an error relating to the key or MAC, the server
+ SHOULD send back an unsigned error message (MAC size == 0 and empty
+ MAC). If an error is detected relating to the TSIG validity period,
+ the server SHOULD send back a signed error message. The digest
+ components are:
+
+ Request MAC (if the request MAC validated)
+ DNS Message (response)
+ TSIG Variables (response)
+
+ The reason that the request is not included in this digest in some
+ cases is to make it possible for the client to verify the error. If
+ the error is not a TSIG error the response MUST be generated as
+ specified in [4.2].
+
+
+
+
+
+Vixie, et al. Standards Track [Page 8]
+
+RFC 2845 DNS TSIG May 2000
+
+
+ 4.4. TSIG on TCP connection
+
+ A DNS TCP session can include multiple DNS envelopes. This is, for
+ example, commonly used by zone transfer. Using TSIG on such a
+ connection can protect the connection from hijacking and provide data
+ integrity. The TSIG MUST be included on the first and last DNS
+ envelopes. It can be optionally placed on any intermediary
+ envelopes. It is expensive to include it on every envelopes, but it
+ MUST be placed on at least every 100'th envelope. The first envelope
+ is processed as a standard answer, and subsequent messages have the
+ following digest components:
+
+ Prior Digest (running)
+ DNS Messages (any unsigned messages since the last TSIG)
+ TSIG Timers (current message)
+
+ This allows the client to rapidly detect when the session has been
+ altered; at which point it can close the connection and retry. If a
+ client TSIG verification fails, the client MUST close the connection.
+ If the client does not receive TSIG records frequently enough (as
+ specified above) it SHOULD assume the connection has been hijacked
+ and it SHOULD close the connection. The client SHOULD treat this the
+ same way as they would any other interrupted transfer (although the
+ exact behavior is not specified).
+
+ 4.5. Server TSIG checks
+
+ Upon receipt of a message, server will check if there is a TSIG RR.
+ If one exists, the server is REQUIRED to return a TSIG RR in the
+ response. The server MUST perform the following checks in the
+ following order, check KEY, check TIME values, check MAC.
+
+ 4.5.1. KEY check and error handling
+
+ If a non-forwarding server does not recognize the key used by the
+ client, the server MUST generate an error response with RCODE 9
+ (NOTAUTH) and TSIG ERROR 17 (BADKEY). This response MUST be unsigned
+ as specified in [4.3]. The server SHOULD log the error.
+
+ 4.5.2. TIME check and error handling
+
+ If the server time is outside the time interval specified by the
+ request (which is: Time Signed, plus/minus Fudge), the server MUST
+ generate an error response with RCODE 9 (NOTAUTH) and TSIG ERROR 18
+ (BADTIME). The server SHOULD also cache the most recent time signed
+ value in a message generated by a key, and SHOULD return BADTIME if a
+ message received later has an earlier time signed value. A response
+ indicating a BADTIME error MUST be signed by the same key as the
+
+
+
+Vixie, et al. Standards Track [Page 9]
+
+RFC 2845 DNS TSIG May 2000
+
+
+ request. It MUST include the client's current time in the time
+ signed field, the server's current time (a u_int48_t) in the other
+ data field, and 6 in the other data length field. This is done so
+ that the client can verify a message with a BADTIME error without the
+ verification failing due to another BADTIME error. The data signed
+ is specified in [4.3]. The server SHOULD log the error.
+
+ 4.5.3. MAC check and error handling
+
+ If a TSIG fails to verify, the server MUST generate an error response
+ as specified in [4.3] with RCODE 9 (NOTAUTH) and TSIG ERROR 16
+ (BADSIG). This response MUST be unsigned as specified in [4.3]. The
+ server SHOULD log the error.
+
+ 4.6. Client processing of answer
+
+ When a client receives a response from a server and expects to see a
+ TSIG, it first checks if the TSIG RR is present in the response.
+ Otherwise, the response is treated as having a format error and
+ discarded. The client then extracts the TSIG, adjusts the ARCOUNT,
+ and calculates the keyed digest in the same way as the server. If
+ the TSIG does not validate, that response MUST be discarded, unless
+ the RCODE is 9 (NOTAUTH), in which case the client SHOULD attempt to
+ verify the response as if it were a TSIG Error response, as specified
+ in [4.3]. A message containing an unsigned TSIG record or a TSIG
+ record which fails verification SHOULD not be considered an
+ acceptable response; the client SHOULD log an error and continue to
+ wait for a signed response until the request times out.
+
+ 4.6.1. Key error handling
+
+ If an RCODE on a response is 9 (NOTAUTH), and the response TSIG
+ validates, and the TSIG key is different from the key used on the
+ request, then this is a KEY error. The client MAY retry the request
+ using the key specified by the server. This should never occur, as a
+ server MUST NOT sign a response with a different key than signed the
+ request.
+
+ 4.6.2. Time error handling
+
+ If the response RCODE is 9 (NOTAUTH) and the TSIG ERROR is 18
+ (BADTIME), or the current time does not fall in the range specified
+ in the TSIG record, then this is a TIME error. This is an indication
+ that the client and server clocks are not synchronized. In this case
+ the client SHOULD log the event. DNS resolvers MUST NOT adjust any
+ clocks in the client based on BADTIME errors, but the server's time
+ in the other data field SHOULD be logged.
+
+
+
+
+Vixie, et al. Standards Track [Page 10]
+
+RFC 2845 DNS TSIG May 2000
+
+
+ 4.6.3. MAC error handling
+
+ If the response RCODE is 9 (NOTAUTH) and TSIG ERROR is 16 (BADSIG),
+ this is a MAC error, and client MAY retry the request with a new
+ request ID but it would be better to try a different shared key if
+ one is available. Client SHOULD keep track of how many MAC errors
+ are associated with each key. Clients SHOULD log this event.
+
+ 4.7. Special considerations for forwarding servers
+
+ A server acting as a forwarding server of a DNS message SHOULD check
+ for the existence of a TSIG record. If the name on the TSIG is not
+ of a secret that the server shares with the originator the server
+ MUST forward the message unchanged including the TSIG. If the name
+ of the TSIG is of a key this server shares with the originator, it
+ MUST process the TSIG. If the TSIG passes all checks, the forwarding
+ server MUST, if possible, include a TSIG of his own, to the
+ destination or the next forwarder. If no transaction security is
+ available to the destination and the response has the AD flag (see
+ [RFC2535]), the forwarder MUST unset the AD flag before adding the
+ TSIG to the answer.
+
+5 - Shared Secrets
+
+ 5.1. Secret keys are very sensitive information and all available
+ steps should be taken to protect them on every host on which they are
+ stored. Generally such hosts need to be physically protected. If
+ they are multi-user machines, great care should be taken that
+ unprivileged users have no access to keying material. Resolvers
+ often run unprivileged, which means all users of a host would be able
+ to see whatever configuration data is used by the resolver.
+
+ 5.2. A name server usually runs privileged, which means its
+ configuration data need not be visible to all users of the host. For
+ this reason, a host that implements transaction-based authentication
+ should probably be configured with a "stub resolver" and a local
+ caching and forwarding name server. This presents a special problem
+ for [RFC2136] which otherwise depends on clients to communicate only
+ with a zone's authoritative name servers.
+
+ 5.3. Use of strong random shared secrets is essential to the security
+ of TSIG. See [RFC1750] for a discussion of this issue. The secret
+ should be at least as long as the keyed message digest, i.e. 16 bytes
+ for HMAC-MD5 or 20 bytes for HMAC-SHA1.
+
+
+
+
+
+
+
+Vixie, et al. Standards Track [Page 11]
+
+RFC 2845 DNS TSIG May 2000
+
+
+6 - Security Considerations
+
+ 6.1. The approach specified here is computationally much less
+ expensive than the signatures specified in [RFC2535]. As long as the
+ shared secret key is not compromised, strong authentication is
+ provided for the last hop from a local name server to the user
+ resolver.
+
+ 6.2. Secret keys should be changed periodically. If the client host
+ has been compromised, the server should suspend the use of all
+ secrets known to that client. If possible, secrets should be stored
+ in encrypted form. Secrets should never be transmitted in the clear
+ over any network. This document does not address the issue on how to
+ distribute secrets. Secrets should never be shared by more than two
+ entities.
+
+ 6.3. This mechanism does not authenticate source data, only its
+ transmission between two parties who share some secret. The original
+ source data can come from a compromised zone master or can be
+ corrupted during transit from an authentic zone master to some
+ "caching forwarder." However, if the server is faithfully performing
+ the full [RFC2535] security checks, then only security checked data
+ will be available to the client.
+
+ 6.4. A fudge value that is too large may leave the server open to
+ replay attacks. A fudge value that is too small may cause failures
+ if machines are not time synchronized or there are unexpected network
+ delays. The recommended value in most situation is 300 seconds.
+
+7 - IANA Considerations
+
+ IANA is expected to create and maintain a registry of algorithm names
+ to be used as "Algorithm Names" as defined in Section 2.3. The
+ initial value should be "HMAC-MD5.SIG-ALG.REG.INT". Algorithm names
+ are text strings encoded using the syntax of a domain name. There is
+ no structure required other than names for different algorithms must
+ be unique when compared as DNS names, i.e., comparison is case
+ insensitive. Note that the initial value mentioned above is not a
+ domain name, and therefore need not be a registered name within the
+ DNS. New algorithms are assigned using the IETF Consensus policy
+ defined in RFC 2434. The algorithm name HMAC-MD5.SIG-ALG.REG.INT
+ looks like a FQDN for historical reasons; future algorithm names are
+ expected to be simple (i.e., single-component) names.
+
+
+
+
+
+
+
+
+Vixie, et al. Standards Track [Page 12]
+
+RFC 2845 DNS TSIG May 2000
+
+
+ IANA is expected to create and maintain a registry of "TSIG Error
+ values" to be used for "Error" values as defined in section 2.3.
+ Initial values should be those defined in section 1.7. New TSIG
+ error codes for the TSIG error field are assigned using the IETF
+ Consensus policy defined in RFC 2434.
+
+8 - References
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1034, November 1987.
+
+ [RFC1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321,
+ April 1992.
+
+ [RFC1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness
+ Recommendations for Security", RFC 1750, December 1995.
+
+ [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC-MD5:
+ Keyed-MD5 for Message Authentication", RFC 2104, February
+ 1997.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2136] Vixie, P., Thomson, S., Rekhter, Y. and J. Bound "Dynamic
+ Updates in the Domain Name System", RFC 2136, April 1997.
+
+ [RFC2137] Eastlake 3rd, D., "Secure Domain Name System Dynamic
+ Update", RFC 2137, April 1997.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC2673] Crawford, M., "Binary Labels in the Domain Name System",
+ RFC 2673, August 1999.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie, et al. Standards Track [Page 13]
+
+RFC 2845 DNS TSIG May 2000
+
+
+9 - Authors' Addresses
+
+ Paul Vixie
+ Internet Software Consortium
+ 950 Charter Street
+ Redwood City, CA 94063
+
+ Phone: +1 650 779 7001
+ EMail: vixie@isc.org
+
+
+ Olafur Gudmundsson
+ NAI Labs
+ 3060 Washington Road, Route 97
+ Glenwood, MD 21738
+
+ Phone: +1 443 259 2389
+ EMail: ogud@tislabs.com
+
+
+ Donald E. Eastlake 3rd
+ Motorola
+ 140 Forest Avenue
+ Hudson, MA 01749 USA
+
+ Phone: +1 508 261 5434
+ EMail: dee3@torque.pothole.com
+
+
+ Brian Wellington
+ Nominum, Inc.
+ 950 Charter Street
+ Redwood City, CA 94063
+
+ Phone: +1 650 779 6022
+ EMail: Brian.Wellington@nominum.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie, et al. Standards Track [Page 14]
+
+RFC 2845 DNS TSIG May 2000
+
+
+10 Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Vixie, et al. Standards Track [Page 15]
+
diff --git a/doc/rfc/rfc2874.txt b/doc/rfc/rfc2874.txt
new file mode 100644
index 0000000..915c104
--- /dev/null
+++ b/doc/rfc/rfc2874.txt
@@ -0,0 +1,1123 @@
+
+
+
+
+
+
+Network Working Group M. Crawford
+Request for Comments: 2874 Fermilab
+Category: Standards Track C. Huitema
+ Microsoft Corporation
+ July 2000
+
+
+ DNS Extensions to Support IPv6 Address Aggregation and Renumbering
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ This document defines changes to the Domain Name System to support
+ renumberable and aggregatable IPv6 addressing. The changes include a
+ new resource record type to store an IPv6 address in a manner which
+ expedites network renumbering and updated definitions of existing
+ query types that return Internet addresses as part of additional
+ section processing.
+
+ For lookups keyed on IPv6 addresses (often called reverse lookups),
+ this document defines a new zone structure which allows a zone to be
+ used without modification for parallel copies of an address space (as
+ for a multihomed provider or site) and across network renumbering
+ events.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Crawford, et al. Standards Track [Page 1]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+Table of Contents
+
+ 1. Introduction ............................................... 2
+ 2. Overview ................................................... 3
+ 2.1. Name-to-Address Lookup ............................... 4
+ 2.2. Underlying Mechanisms for Reverse Lookups ............ 4
+ 2.2.1. Delegation on Arbitrary Boundaries ............. 4
+ 2.2.2. Reusable Zones ................................. 5
+ 3. Specifications ............................................. 5
+ 3.1. The A6 Record Type ................................... 5
+ 3.1.1. Format ......................................... 6
+ 3.1.2. Processing ..................................... 6
+ 3.1.3. Textual Representation ......................... 7
+ 3.1.4. Name Resolution Procedure ...................... 7
+ 3.2. Zone Structure for Reverse Lookups ................... 7
+ 4. Modifications to Existing Query Types ...................... 8
+ 5. Usage Illustrations ........................................ 8
+ 5.1. A6 Record Chains ..................................... 9
+ 5.1.1. Authoritative Data ............................. 9
+ 5.1.2. Glue ........................................... 10
+ 5.1.3. Variations ..................................... 12
+ 5.2. Reverse Mapping Zones ................................ 13
+ 5.2.1. The TLA level .................................. 13
+ 5.2.2. The ISP level .................................. 13
+ 5.2.3. The Site Level ................................. 13
+ 5.3. Lookups .............................................. 14
+ 5.4. Operational Note ..................................... 15
+ 6. Transition from RFC 1886 and Deployment Notes .............. 15
+ 6.1. Transition from AAAA and Coexistence with A Records .. 16
+ 6.2. Transition from Nibble Labels to Binary Labels ....... 17
+ 7. Security Considerations .................................... 17
+ 8. IANA Considerations ........................................ 17
+ 9. Acknowledgments ............................................ 18
+ 10. References ................................................ 18
+ 11. Authors' Addresses ........................................ 19
+ 12. Full Copyright Statement .................................. 20
+
+1. Introduction
+
+ Maintenance of address information in the DNS is one of several
+ obstacles which have prevented site and provider renumbering from
+ being feasible in IP version 4. Arguments about the importance of
+ network renumbering for the preservation of a stable routing system
+ and for other purposes may be read in [RENUM1, RENUM2, RENUM3]. To
+ support the storage of IPv6 addresses without impeding renumbering we
+ define the following extensions.
+
+
+
+
+
+Crawford, et al. Standards Track [Page 2]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+ o A new resource record type, "A6", is defined to map a domain name
+ to an IPv6 address, with a provision for indirection for leading
+ "prefix" bits.
+
+ o Existing queries that perform additional section processing to
+ locate IPv4 addresses are redefined to do that processing for both
+ IPv4 and IPv6 addresses.
+
+ o A new domain, IP6.ARPA, is defined to support lookups based on
+ IPv6 address.
+
+ o A new prefix-delegation method is defined, relying on new DNS
+ features [BITLBL, DNAME].
+
+ The changes are designed to be compatible with existing application
+ programming interfaces. The existing support for IPv4 addresses is
+ retained. Transition issues related to the coexistence of both IPv4
+ and IPv6 addresses in DNS are discussed in [TRANS].
+
+ This memo proposes a replacement for the specification in RFC 1886
+ [AAAA] and a departure from current implementation practices. The
+ changes are designed to facilitate network renumbering and
+ multihoming. Domains employing the A6 record for IPv6 addresses can
+ insert automatically-generated AAAA records in zone files to ease
+ transition. It is expected that after a reasonable period, RFC 1886
+ will become Historic.
+
+ The next three major sections of this document are an overview of the
+ facilities defined or employed by this specification, the
+ specification itself, and examples of use.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [KWORD]. The key word
+ "SUGGESTED" signifies a strength between MAY and SHOULD: it is
+ believed that compliance with the suggestion has tangible benefits in
+ most instances.
+
+2. Overview
+
+ This section provides an overview of the DNS facilities for storage
+ of IPv6 addresses and for lookups based on IPv6 address, including
+ those defined here and elsewhere.
+
+
+
+
+
+
+
+
+Crawford, et al. Standards Track [Page 3]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+2.1. Name-to-Address Lookup
+
+ IPv6 addresses are stored in one or more A6 resource records. A
+ single A6 record may include a complete IPv6 address, or a contiguous
+ portion of an address and information leading to one or more
+ prefixes. Prefix information comprises a prefix length and a DNS
+ name which is in turn the owner of one or more A6 records defining
+ the prefix or prefixes which are needed to form one or more complete
+ IPv6 addresses. When the prefix length is zero, no DNS name is
+ present and all the leading bits of the address are significant.
+ There may be multiple levels of indirection and the existence of
+ multiple A6 records at any level multiplies the number of IPv6
+ addresses which are formed.
+
+ An application looking up an IPv6 address will generally cause the
+ DNS resolver to access several A6 records, and multiple IPv6
+ addresses may be returned even if the queried name was the owner of
+ only one A6 record. The authenticity of the returned address(es)
+ cannot be directly verified by DNS Security [DNSSEC]. The A6 records
+ which contributed to the address(es) may of course be verified if
+ signed.
+
+ Implementers are reminded of the necessity to limit the amount of
+ work a resolver will perform in response to a client request. This
+ principle MUST be extended to also limit the generation of DNS
+ requests in response to one name-to-address (or address-to-name)
+ lookup request.
+
+2.2. Underlying Mechanisms for Reverse Lookups
+
+ This section describes the new DNS features which this document
+ exploits. This section is an overview, not a specification of those
+ features. The reader is directed to the referenced documents for
+ more details on each.
+
+2.2.1. Delegation on Arbitrary Boundaries
+
+ This new scheme for reverse lookups relies on a new type of DNS label
+ called the "bit-string label" [BITLBL]. This label compactly
+ represents an arbitrary string of bits which is treated as a
+ hierarchical sequence of one-bit domain labels. Resource records can
+ thereby be stored at arbitrary bit-boundaries.
+
+ Examples in section 5 will employ the following textual
+ representation for bit-string labels, which is a subset of the syntax
+ defined in [BITLBL]. A base indicator "x" for hexadecimal and a
+ sequence of hexadecimal digits is enclosed between "\[" and "]". The
+ bits denoted by the digits represent a sequence of one-bit domain
+
+
+
+Crawford, et al. Standards Track [Page 4]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+ labels ordered from most to least significant. (This is the opposite
+ of the order they would appear if listed one bit at a time, but it
+ appears to be a convenient notation.) The digit string may be
+ followed by a slash ("/") and a decimal count. If omitted, the
+ implicit count is equal to four times the number of hexadecimal
+ digits.
+
+ Consecutive bit-string labels are equivalent (up to the limit imposed
+ by the size of the bit count field) to a single bit-string label
+ containing all the bits of the consecutive labels in the proper
+ order. As an example, either of the following domain names could be
+ used in a QCLASS=IN, QTYPE=PTR query to find the name of the node
+ with IPv6 address 3ffe:7c0:40:9:a00:20ff:fe81:2b32.
+
+ \[x3FFE07C0004000090A0020FFFE812B32/128].IP6.ARPA.
+
+ \[x0A0020FFFE812B32/64].\[x0009/16].\[x3FFE07C00040/48].IP6.ARPA.
+
+2.2.2. Reusable Zones
+
+ DNS address space delegation is implemented not by zone cuts and NS
+ records, but by a new analogue to the CNAME record, called the DNAME
+ resource record [DNAME]. The DNAME record provides alternate naming
+ to an entire subtree of the domain name space, rather than to a
+ single node. It causes some suffix of a queried name to be
+ substituted with a name from the DNAME record's RDATA.
+
+ For example, a resolver or server providing recursion, while looking
+ up a QNAME a.b.c.d.e.f may encounter a DNAME record
+
+ d.e.f. DNAME w.xy.
+
+ which will cause it to look for a.b.c.w.xy.
+
+3. Specifications
+
+3.1. The A6 Record Type
+
+ The A6 record type is specific to the IN (Internet) class and has
+ type number 38 (decimal).
+
+
+
+
+
+
+
+
+
+
+
+Crawford, et al. Standards Track [Page 5]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+3.1.1. Format
+
+ The RDATA portion of the A6 record contains two or three fields.
+
+ +-----------+------------------+-------------------+
+ |Prefix len.| Address suffix | Prefix name |
+ | (1 octet) | (0..16 octets) | (0..255 octets) |
+ +-----------+------------------+-------------------+
+
+ o A prefix length, encoded as an eight-bit unsigned integer with
+ value between 0 and 128 inclusive.
+
+ o An IPv6 address suffix, encoded in network order (high-order octet
+ first). There MUST be exactly enough octets in this field to
+ contain a number of bits equal to 128 minus prefix length, with 0
+ to 7 leading pad bits to make this field an integral number of
+ octets. Pad bits, if present, MUST be set to zero when loading a
+ zone file and ignored (other than for SIG [DNSSEC] verification)
+ on reception.
+
+ o The name of the prefix, encoded as a domain name. By the rules of
+ [DNSIS], this name MUST NOT be compressed.
+
+ The domain name component SHALL NOT be present if the prefix length
+ is zero. The address suffix component SHALL NOT be present if the
+ prefix length is 128.
+
+ It is SUGGESTED that an A6 record intended for use as a prefix for
+ other A6 records have all the insignificant trailing bits in its
+ address suffix field set to zero.
+
+3.1.2. Processing
+
+ A query with QTYPE=A6 causes type A6 and type NS additional section
+ processing for the prefix names, if any, in the RDATA field of the A6
+ records in the answer section. This processing SHOULD be recursively
+ applied to the prefix names of A6 records included as additional
+ data. When space in the reply packet is a limit, inclusion of
+ additional A6 records takes priority over NS records.
+
+ It is an error for an A6 record with prefix length L1 > 0 to refer to
+ a domain name which owns an A6 record with a prefix length L2 > L1.
+ If such a situation is encountered by a resolver, the A6 record with
+ the offending (larger) prefix length MUST be ignored. Robustness
+ precludes signaling an error if addresses can still be formed from
+ valid A6 records, but it is SUGGESTED that zone maintainers from time
+ to time check all the A6 records their zones reference.
+
+
+
+
+Crawford, et al. Standards Track [Page 6]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+3.1.3. Textual Representation
+
+ The textual representation of the RDATA portion of the A6 resource
+ record in a zone file comprises two or three fields separated by
+ whitespace.
+
+ o A prefix length, represented as a decimal number between 0 and 128
+ inclusive,
+
+ o the textual representation of an IPv6 address as defined in
+ [AARCH] (although some leading and/or trailing bits may not be
+ significant),
+
+ o a domain name, if the prefix length is not zero.
+
+ The domain name MUST be absent if the prefix length is zero. The
+ IPv6 address MAY be be absent if the prefix length is 128. A number
+ of leading address bits equal to the prefix length SHOULD be zero,
+ either implicitly (through the :: notation) or explicitly, as
+ specified in section 3.1.1.
+
+3.1.4. Name Resolution Procedure
+
+ To obtain the IPv6 address or addresses which belong to a given name,
+ a DNS client MUST obtain one or more complete chains of A6 records,
+ each chain beginning with a record owned by the given name and
+ including a record owned by the prefix name in that record, and so on
+ recursively, ending with an A6 record with a prefix length of zero.
+ One IPv6 address is formed from one such chain by taking the value of
+ each bit position from the earliest A6 record in the chain which
+ validly covers that position, as indicated by the prefix length. The
+ set of all IPv6 addresses for the given name comprises the addresses
+ formed from all complete chains of A6 records beginning at that name,
+ discarding records which have invalid prefix lengths as defined in
+ section 3.1.2.
+
+ If some A6 queries fail and others succeed, a client might obtain a
+ non-empty but incomplete set of IPv6 addresses for a host. In many
+ situations this may be acceptable. The completeness of a set of A6
+ records may always be determined by inspection.
+
+3.2. Zone Structure for Reverse Lookups
+
+ Very little of the new scheme's data actually appears under IP6.ARPA;
+ only the first level of delegation needs to be under that domain.
+ More levels of delegation could be placed under IP6.ARPA if some
+ top-level delegations were done via NS records instead of DNAME
+ records, but this would incur some cost in renumbering ease at the
+
+
+
+Crawford, et al. Standards Track [Page 7]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+ level of TLAs [AGGR]. Therefore, it is declared here that all
+ address space delegations SHOULD be done by the DNAME mechanism
+ rather than NS.
+
+ In addition, since uniformity in deployment will simplify maintenance
+ of address delegations, it is SUGGESTED that address and prefix
+ information be stored immediately below a DNS label "IP6". Stated
+ another way, conformance with this suggestion would mean that "IP6"
+ is the first label in the RDATA field of DNAME records which support
+ IPv6 reverse lookups.
+
+ When any "reserved" or "must be zero" bits are adjacent to a
+ delegation boundary, the higher-level entity MUST retain those bits
+ in its own control and delegate only the bits over which the lower-
+ level entity has authority.
+
+ To find the name of a node given its IPv6 address, a DNS client MUST
+ perform a query with QCLASS=IN, QTYPE=PTR on the name formed from the
+ 128 bit address as one or more bit-string labels [BITLBL], followed
+ by the two standard labels "IP6.ARPA". If recursive service was not
+ obtained from a server and the desired PTR record was not returned,
+ the resolver MUST handle returned DNAME records as specified in
+ [DNAME], and NS records as specified in [DNSCF], and iterate.
+
+4. Modifications to Existing Query Types
+
+ All existing query types that perform type A additional section
+ processing, i.e. the name server (NS), mail exchange (MX), and
+ mailbox (MB) query types, and the experimental AFS data base (AFSDB)
+ and route through (RT) types, must be redefined to perform type A, A6
+ and AAAA additional section processing, with type A having the
+ highest priority for inclusion and type AAAA the lowest. This
+ redefinition means that a name server may add any relevant IPv4 and
+ IPv6 address information available locally to the additional section
+ of a response when processing any one of the above queries. The
+ recursive inclusion of A6 records referenced by A6 records already
+ included in the additional section is OPTIONAL.
+
+5. Usage Illustrations
+
+ This section provides examples of use of the mechanisms defined in
+ the previous section. All addresses and domains mentioned here are
+ intended to be fictitious and for illustrative purposes only.
+ Example delegations will be on 4-bit boundaries solely for
+ readability; this specification is indifferent to bit alignment.
+
+ Use of the IPv6 aggregatable address format [AGGR] is assumed in the
+ examples.
+
+
+
+Crawford, et al. Standards Track [Page 8]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+5.1. A6 Record Chains
+
+ Let's take the example of a site X that is multi-homed to two
+ "intermediate" providers A and B. The provider A is itself multi-
+ homed to two "transit" providers, C and D. The provider B gets its
+ transit service from a single provider, E. For simplicity suppose
+ that C, D and E all belong to the same top-level aggregate (TLA) with
+ identifier (including format prefix) '2345', and the TLA authority at
+ ALPHA-TLA.ORG assigns to C, D and E respectively the next level
+ aggregate (NLA) prefixes 2345:00C0::/28, 2345:00D0::/28 and
+ 2345:000E::/32.
+
+ C assigns the NLA prefix 2345:00C1:CA00::/40 to A, D assigns the
+ prefix 2345:00D2:DA00::/40 to A and E assigns 2345:000E:EB00::/40 to
+ B.
+
+ A assigns to X the subscriber identification '11' and B assigns the
+ subscriber identification '22'. As a result, the site X inherits
+ three address prefixes:
+
+ o 2345:00C1:CA11::/48 from A, for routes through C.
+ o 2345:00D2:DA11::/48 from A, for routes through D.
+ o 2345:000E:EB22::/48 from B, for routes through E.
+
+ Let us suppose that N is a node in the site X, that it is assigned to
+ subnet number 1 in this site, and that it uses the interface
+ identifier '1234:5678:9ABC:DEF0'. In our configuration, this node
+ will have three addresses:
+
+ o 2345:00C1:CA11:0001:1234:5678:9ABC:DEF0
+ o 2345:00D2:DA11:0001:1234:5678:9ABC:DEF0
+ o 2345:000E:EB22:0001:1234:5678:9ABC:DEF0
+
+5.1.1. Authoritative Data
+
+ We will assume that the site X is represented in the DNS by the
+ domain name X.EXAMPLE, while A, B, C, D and E are represented by
+ A.NET, B.NET, C.NET, D.NET and E.NET. In each of these domains, we
+ assume a subdomain "IP6" that will hold the corresponding prefixes.
+ The node N is identified by the domain name N.X.EXAMPLE. The
+ following records would then appear in X's DNS.
+
+ $ORIGIN X.EXAMPLE.
+ N A6 64 ::1234:5678:9ABC:DEF0 SUBNET-1.IP6
+ SUBNET-1.IP6 A6 48 0:0:0:1:: IP6
+ IP6 A6 48 0::0 SUBSCRIBER-X.IP6.A.NET.
+ IP6 A6 48 0::0 SUBSCRIBER-X.IP6.B.NET.
+
+
+
+
+Crawford, et al. Standards Track [Page 9]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+ And elsewhere there would appear
+
+ SUBSCRIBER-X.IP6.A.NET. A6 40 0:0:0011:: A.NET.IP6.C.NET.
+ SUBSCRIBER-X.IP6.A.NET. A6 40 0:0:0011:: A.NET.IP6.D.NET.
+
+ SUBSCRIBER-X.IP6.B.NET. A6 40 0:0:0022:: B-NET.IP6.E.NET.
+
+ A.NET.IP6.C.NET. A6 28 0:0001:CA00:: C.NET.ALPHA-TLA.ORG.
+
+ A.NET.IP6.D.NET. A6 28 0:0002:DA00:: D.NET.ALPHA-TLA.ORG.
+
+ B-NET.IP6.E.NET. A6 32 0:0:EB00:: E.NET.ALPHA-TLA.ORG.
+
+ C.NET.ALPHA-TLA.ORG. A6 0 2345:00C0::
+ D.NET.ALPHA-TLA.ORG. A6 0 2345:00D0::
+ E.NET.ALPHA-TLA.ORG. A6 0 2345:000E::
+
+5.1.2. Glue
+
+ When, as is common, some or all DNS servers for X.EXAMPLE are within
+ the X.EXAMPLE zone itself, the top-level zone EXAMPLE must carry
+ enough "glue" information to enable DNS clients to reach those
+ nameservers. This is true in IPv6 just as in IPv4. However, the A6
+ record affords the DNS administrator some choices. The glue could be
+ any of
+
+ o a minimal set of A6 records duplicated from the X.EXAMPLE zone,
+
+ o a (possibly smaller) set of records which collapse the structure
+ of that minimal set,
+
+ o or a set of A6 records with prefix length zero, giving the entire
+ global addresses of the servers.
+
+ The trade-off is ease of maintenance against robustness. The best
+ and worst of both may be had together by implementing either the
+ first or second option together with the third. To illustrate the
+ glue options, suppose that X.EXAMPLE is served by two nameservers
+ NS1.X.EXAMPLE and NS2.X.EXAMPLE, having interface identifiers
+ ::1:11:111:1111 and ::2:22:222:2222 on subnets 1 and 2 respectively.
+ Then the top-level zone EXAMPLE would include one (or more) of the
+ following sets of A6 records as glue.
+
+
+
+
+
+
+
+
+
+Crawford, et al. Standards Track [Page 10]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+ $ORIGIN EXAMPLE. ; first option
+ X NS NS1.X
+ NS NS2.X
+ NS1.X A6 64 ::1:11:111:1111 SUBNET-1.IP6.X
+ NS2.X A6 64 ::2:22:222:2222 SUBNET-2.IP6.X
+ SUBNET-1.IP6.X A6 48 0:0:0:1:: IP6.X
+ SUBNET-2.IP6.X A6 48 0:0:0:2:: IP6.X
+ IP6.X A6 48 0::0 SUBSCRIBER-X.IP6.A.NET.
+ IP6.X A6 48 0::0 SUBSCRIBER-X.IP6.B.NET.
+
+
+ $ORIGIN EXAMPLE. ; second option
+ X NS NS1.X
+ NS NS2.X
+ NS1.X A6 48 ::1:1:11:111:1111 SUBSCRIBER-X.IP6.A.NET.
+ A6 48 ::1:1:11:111:1111 SUBSCRIBER-X.IP6.B.NET.
+ NS2.X A6 48 ::2:2:22:222:2222 SUBSCRIBER-X.IP6.A.NET.
+ A6 48 ::2:2:22:222:2222 SUBSCRIBER-X.IP6.B.NET.
+
+
+ $ORIGIN EXAMPLE. ; third option
+ X NS NS1.X
+ NS NS2.X
+ NS1.X A6 0 2345:00C1:CA11:1:1:11:111:1111
+ A6 0 2345:00D2:DA11:1:1:11:111:1111
+ A6 0 2345:000E:EB22:1:1:11:111:1111
+ NS2.X A6 0 2345:00C1:CA11:2:2:22:222:2222
+ A6 0 2345:00D2:DA11:2:2:22:222:2222
+ A6 0 2345:000E:EB22:2:2:22:222:2222
+
+ The first and second glue options are robust against renumbering of
+ X.EXAMPLE's prefixes by providers A.NET and B.NET, but will fail if
+ those providers' own DNS is unreachable. The glue records of the
+ third option are robust against DNS failures elsewhere than the zones
+ EXAMPLE and X.EXAMPLE themselves, but must be updated when X's
+ address space is renumbered.
+
+ If the EXAMPLE zone includes redundant glue, for instance the union
+ of the A6 records of the first and third options, then under normal
+ circumstances duplicate IPv6 addresses will be derived by DNS
+ clients. But if provider DNS fails, addresses will still be obtained
+ from the zero-prefix-length records, while if the EXAMPLE zone lags
+ behind a renumbering of X.EXAMPLE, half of the addresses obtained by
+ DNS clients will still be up-to-date.
+
+ The zero-prefix-length glue records can of course be automatically
+ generated and/or checked in practice.
+
+
+
+
+Crawford, et al. Standards Track [Page 11]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+5.1.3. Variations
+
+ Several more-or-less arbitrary assumptions are reflected in the above
+ structure. All of the following choices could have been made
+ differently, according to someone's notion of convenience or an
+ agreement between two parties.
+
+ First, that site X has chosen to put subnet information in a
+ separate A6 record rather than incorporate it into each node's A6
+ records.
+
+ Second, that site X is referred to as "SUBSCRIBER-X" by both of
+ its providers A and B.
+
+ Third, that site X chose to indirect its provider information
+ through A6 records at IP6.X.EXAMPLE containing no significant
+ bits. An alternative would have been to replicate each subnet
+ record for each provider.
+
+ Fourth, B and E used a slightly different prefix naming convention
+ between themselves than did A, C and D. Each hierarchical pair of
+ network entities must arrange this naming between themselves.
+
+ Fifth, that the upward prefix referral chain topped out at ALPHA-
+ TLA.ORG. There could have been another level which assigned the
+ TLA values and holds A6 records containing those bits.
+
+ Finally, the above structure reflects an assumption that address
+ fields assigned by a given entity are recorded only in A6 records
+ held by that entity. Those bits could be entered into A6 records in
+ the lower-level entity's zone instead, thus:
+
+ IP6.X.EXAMPLE. A6 40 0:0:11:: IP6.A.NET.
+ IP6.X.EXAMPLE. A6 40 0:0:22:: IP6.B.NET.
+
+ IP6.A.NET. A6 28 0:1:CA00:: IP6.C.NET.
+ and so on.
+
+ Or the higher-level entities could hold both sorts of A6 records
+ (with different DNS owner names) and allow the lower-level entities
+ to choose either mode of A6 chaining. But the general principle of
+ avoiding data duplication suggests that the proper place to store
+ assigned values is with the entity that assigned them.
+
+ It is possible, but not necessarily recommended, for a zone
+ maintainer to forego the renumbering support afforded by the chaining
+ of A6 records and to record entire IPv6 addresses within one zone
+ file.
+
+
+
+Crawford, et al. Standards Track [Page 12]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+5.2. Reverse Mapping Zones
+
+ Supposing that address space assignments in the TLAs with Format
+ Prefix (001) binary and IDs 0345, 0678 and 09AB were maintained in
+ zones called ALPHA-TLA.ORG, BRAVO-TLA.ORG and CHARLIE-TLA.XY, then
+ the IP6.ARPA zone would include
+
+ $ORIGIN IP6.ARPA.
+ \[x234500/24] DNAME IP6.ALPHA-TLA.ORG.
+ \[x267800/24] DNAME IP6.BRAVO-TLA.ORG.
+ \[x29AB00/24] DNAME IP6.CHARLIE-TLA.XY.
+
+ Eight trailing zero bits have been included in each TLA ID to reflect
+ the eight reserved bits in the current aggregatable global unicast
+ addresses format [AGGR].
+
+5.2.1. The TLA level
+
+ ALPHA-TLA's assignments to network providers C, D and E are reflected
+ in the reverse data as follows.
+
+ \[xC/4].IP6.ALPHA-TLA.ORG. DNAME IP6.C.NET.
+ \[xD/4].IP6.ALPHA-TLA.ORG. DNAME IP6.D.NET.
+ \[x0E/8].IP6.ALPHA-TLA.ORG. DNAME IP6.E.NET.
+
+5.2.2. The ISP level
+
+ The providers A through E carry the following delegation information
+ in their zone files.
+
+ \[x1CA/12].IP6.C.NET. DNAME IP6.A.NET.
+ \[x2DA/12].IP6.D.NET. DNAME IP6.A.NET.
+ \[xEB/8].IP6.E.NET. DNAME IP6.B.NET.
+ \[x11/8].IP6.A.NET. DNAME IP6.X.EXAMPLE.
+ \[x22/8].IP6.B.NET. DNAME IP6.X.EXAMPLE.
+
+ Note that some domain names appear in the RDATA of more than one
+ DNAME record. In those cases, one zone is being used to map multiple
+ prefixes.
+
+5.2.3. The Site Level
+
+ Consider the customer X.EXAMPLE using IP6.X.EXAMPLE for address-to-
+ name translations. This domain is now referenced by two different
+ DNAME records held by two different providers.
+
+
+
+
+
+
+Crawford, et al. Standards Track [Page 13]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+ $ORIGIN IP6.X.EXAMPLE.
+ \[x0001/16] DNAME SUBNET-1
+ \[x123456789ABCDEF0].SUBNET-1 PTR N.X.EXAMPLE.
+ and so on.
+
+ SUBNET-1 need not have been named in a DNAME record; the subnet bits
+ could have been joined with the interface identifier. But if subnets
+ are treated alike in both the A6 records and in the reverse zone, it
+ will always be possible to keep the forward and reverse definition
+ data for each prefix in one zone.
+
+5.3. Lookups
+
+ A DNS resolver looking for a hostname for the address
+ 2345:00C1:CA11:0001:1234:5678:9ABC:DEF0 would acquire certain of the
+ DNAME records shown above and would form new queries. Assuming that
+ it began the process knowing servers for IP6.ARPA, but that no server
+ it consulted provided recursion and none had other useful additional
+ information cached, the sequence of queried names and responses would
+ be (all with QCLASS=IN, QTYPE=PTR):
+
+ To a server for IP6.ARPA:
+ QNAME=\[x234500C1CA110001123456789ABCDEF0/128].IP6.ARPA.
+
+ Answer:
+ \[x234500/24].IP6.ARPA. DNAME IP6.ALPHA-TLA.ORG.
+
+ To a server for IP6.ALPHA-TLA.ORG:
+ QNAME=\[xC1CA110001123456789ABCDEF0/104].IP6.ALPHA-TLA.ORG.
+
+ Answer:
+ \[xC/4].IP6.ALPHA-TLA.ORG. DNAME IP6.C.NET.
+
+ To a server for IP6.C.NET.:
+ QNAME=\[x1CA110001123456789ABCDEF0/100].IP6.C.NET.
+
+ Answer:
+ \[x1CA/12].IP6.C.NET. DNAME IP6.A.NET.
+
+ To a server for IP6.A.NET.:
+ QNAME=\[x110001123456789ABCDEF0/88].IP6.A.NET.
+
+ Answer:
+ \[x11/8].IP6.A.NET. DNAME IP6.X.EXAMPLE.
+
+ To a server for IP6.X.EXAMPLE.:
+ QNAME=\[x0001123456789ABCDEF0/80].IP6.X.EXAMPLE.
+
+
+
+
+Crawford, et al. Standards Track [Page 14]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+ Answer:
+ \[x0001/16].IP6.X.EXAMPLE. DNAME SUBNET-1.IP6.X.EXAMPLE.
+ \[x123456789ABCDEF0/64].SUBNET-1.X.EXAMPLE. PTR N.X.EXAMPLE.
+
+ All the DNAME (and NS) records acquired along the way can be cached
+ to expedite resolution of addresses topologically near to this
+ address. And if another global address of N.X.EXAMPLE were resolved
+ within the TTL of the final PTR record, that record would not have to
+ be fetched again.
+
+5.4. Operational Note
+
+ In the illustrations in section 5.1, hierarchically adjacent
+ entities, such as a network provider and a customer, must agree on a
+ DNS name which will own the definition of the delegated prefix(es).
+ One simple convention would be to use a bit-string label representing
+ exactly the bits which are assigned to the lower-level entity by the
+ higher. For example, "SUBSCRIBER-X" could be replaced by "\[x11/8]".
+ This would place the A6 record(s) defining the delegated prefix at
+ exactly the same point in the DNS tree as the DNAME record associated
+ with that delegation. The cost of this simplification is that the
+ lower-level zone must update its upward-pointing A6 records when it
+ is renumbered. This cost may be found quite acceptable in practice.
+
+6. Transition from RFC 1886 and Deployment Notes
+
+ When prefixes have been "delegated upward" with A6 records, the
+ number of DNS resource records required to establish a single IPv6
+ address increases by some non-trivial factor. Those records will
+ typically, but not necessarily, come from different DNS zones (which
+ can independently suffer failures for all the usual reasons). When
+ obtaining multiple IPv6 addresses together, this increase in RR count
+ will be proportionally less -- and the total size of a DNS reply
+ might even decrease -- if the addresses are topologically clustered.
+ But the records could still easily exceed the space available in a
+ UDP response which returns a large RRset [DNSCLAR] to an MX, NS, or
+ SRV query, for example. The possibilities for overall degradation of
+ performance and reliability of DNS lookups are numerous, and increase
+ with the number of prefix delegations involved, especially when those
+ delegations point to records in other zones.
+
+ DNS Security [DNSSEC] addresses the trustworthiness of cached data,
+ which is a problem intrinsic to DNS, but the cost of applying this to
+ an IPv6 address is multiplied by a factor which may be greater than
+ the number of prefix delegations involved if different signature
+ chains must be verified for different A6 records. If a trusted
+ centralized caching server (as in [TSIG], for example) is used, this
+ cost might be amortized to acceptable levels. One new phenomenon is
+
+
+
+Crawford, et al. Standards Track [Page 15]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+ the possibility that IPv6 addresses may be formed from a A6 records
+ from a combination of secure and unsecured zones.
+
+ Until more deployment experience is gained with the A6 record, it is
+ recommended that prefix delegations be limited to one or two levels.
+ A reasonable phasing-in mechanism would be to start with no prefix
+ delegations (all A6 records having prefix length 0) and then to move
+ to the use of a single level of delegation within a single zone. (If
+ the TTL of the "prefix" A6 records is kept to an appropriate duration
+ the capability for rapid renumbering is not lost.) More aggressively
+ flexible delegation could be introduced for a subset of hosts for
+ experimentation.
+
+6.1. Transition from AAAA and Coexistence with A Records
+
+ Administrators of zones which contain A6 records can easily
+ accommodate deployed resolvers which understand AAAA records but not
+ A6 records. Such administrators can do automatic generation of AAAA
+ records for all of a zone's names which own A6 records by a process
+ which mimics the resolution of a hostname to an IPv6 address (see
+ section 3.1.4). Attention must be paid to the TTL assigned to a
+ generated AAAA record, which MUST be no more than the minimum of the
+ TTLs of the A6 records that were used to form the IPv6 address in
+ that record. For full robustness, those A6 records which were in
+ different zones should be monitored for changes (in TTL or RDATA)
+ even when there are no changes to zone for which AAAA records are
+ being generated. If the zone is secure [DNSSEC], the generated AAAA
+ records MUST be signed along with the rest of the zone data.
+
+ A zone-specific heuristic MAY be used to avoid generation of AAAA
+ records for A6 records which record prefixes, although such
+ superfluous records would be relatively few in number and harmless.
+ Examples of such heuristics include omitting A6 records with a prefix
+ length less than the largest value found in the zone file, or records
+ with an address suffix field with a certain number of trailing zero
+ bits.
+
+ On the client side, when looking up and IPv6 address, the order of A6
+ and AAAA queries MAY be configurable to be one of: A6, then AAAA;
+ AAAA, then A6; A6 only; or both in parallel. The default order (or
+ only order, if not configurable) MUST be to try A6 first, then AAAA.
+ If and when the AAAA becomes deprecated a new document will change
+ the default.
+
+ The guidelines and options for precedence between IPv4 and IPv6
+ addresses are specified in [TRANS]. All mentions of AAAA records in
+ that document are henceforth to be interpreted as meaning A6 and/or
+ AAAA records in the order specified in the previous paragraph.
+
+
+
+Crawford, et al. Standards Track [Page 16]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+6.2. Transition from Nibble Labels to Binary Labels
+
+ Implementations conforming to RFC 1886 [AAAA] perform reverse lookups
+ as follows:
+
+ An IPv6 address is represented as a name in the IP6.INT domain by
+ a sequence of nibbles separated by dots with the suffix
+ ".IP6.INT". The sequence of nibbles is encoded in reverse order,
+ i.e. the low-order nibble is encoded first, followed by the next
+ low-order nibble and so on. Each nibble is represented by a
+ hexadecimal digit. For example, a name for the address
+ 2345:00C1:CA11:0001:1234:5678:9ABC:DEF0 of the example in section
+ 5.3 would be sought at the DNS name "0.f.e.d.c.b.a.9.-
+ 8.7.6.5.4.3.2.1.1.0.0.0.1.1.a.c.1.c.0.0.5.4.3.2.ip6.int."
+
+ Implementations conforming to this specification will perform a
+ lookup of a binary label in IP6.ARPA as specified in Section 3.2. It
+ is RECOMMENDED that for a transition period implementations first
+ lookup the binary label in IP6.ARPA and if this fails try to lookup
+ the 'nibble' label in IP6.INT.
+
+7. Security Considerations
+
+ The signing authority [DNSSEC] for the A6 records which determine an
+ IPv6 address is distributed among several entities, reflecting the
+ delegation path of the address space which that address occupies.
+ DNS Security is fully applicable to bit-string labels and DNAME
+ records. And just as in IPv4, verification of name-to-address
+ mappings is logically independent of verification of address-to-name
+ mappings.
+
+ With or without DNSSEC, the incomplete but non-empty address set
+ scenario of section 3.1.4 could be caused by selective interference
+ with DNS lookups. If in some situation this would be more harmful
+ than complete DNS failure, it might be mitigated on the client side
+ by refusing to act on an incomplete set, or on the server side by
+ listing all addresses in A6 records with prefix length 0.
+
+8. IANA Considerations
+
+ The A6 resource record has been assigned a Type value of 38.
+
+
+
+
+
+
+
+
+
+
+Crawford, et al. Standards Track [Page 17]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+9. Acknowledgments
+
+ The authors would like to thank the following persons for valuable
+ discussions and reviews: Mark Andrews, Rob Austein, Jim Bound, Randy
+ Bush, Brian Carpenter, David Conrad, Steve Deering, Francis Dupont,
+ Robert Elz, Bob Fink, Olafur Gudmundsson, Bob Halley, Bob Hinden,
+ Edward Lewis, Bill Manning, Keith Moore, Thomas Narten, Erik
+ Nordmark, Mike O'Dell, Michael Patton and Ken Powell.
+
+10. References
+
+ [AAAA] Thomson, S. and C. Huitema, "DNS Extensions to support IP
+ version 6, RFC 1886, December 1995.
+
+ [AARCH] Hinden, R. and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 2373, July 1998.
+
+ [AGGR] Hinden, R., O'Dell, M. and S. Deering, "An IPv6
+ Aggregatable Global Unicast Address Format", RFC 2374, July
+ 1998.
+
+ [BITLBL] Crawford, M., "Binary Labels in the Domain Name System",
+ RFC 2673, August 1999.
+
+ [DNAME] Crawford, M., "Non-Terminal DNS Name Redirection", RFC
+ 2672, August 1999.
+
+ [DNSCLAR] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [DNSIS] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [DNSSEC] Eastlake, D. 3rd and C. Kaufman, "Domain Name System
+ Security Extensions", RFC 2535, March 1999.
+
+ [KWORD] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RENUM1] Carpenter, B. and Y. Rekhter, "Renumbering Needs Work", RFC
+ 1900, February 1996.
+
+ [RENUM2] Ferguson, P. and H. Berkowitz, "Network Renumbering
+ Overview: Why would I want it and what is it anyway?", RFC
+ 2071, January 1997.
+
+ [RENUM3] Carpenter, B., Crowcroft, J. and Y. Rekhter, "IPv4 Address
+ Behaviour Today", RFC 2101, February 1997.
+
+
+
+Crawford, et al. Standards Track [Page 18]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+ [TRANS] Gilligan, R. and E. Nordmark, "Transition Mechanisms for
+ IPv6 Hosts and Routers", RFC 1933, April 1996.
+
+ [TSIG] Vixie, P., Gudmundsson, O., Eastlake, D. 3rd and B.
+ Wellington, "Secret Key Transaction Authentication for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+11. Authors' Addresses
+
+ Matt Crawford
+ Fermilab
+ MS 368
+ PO Box 500
+ Batavia, IL 60510
+ USA
+
+ Phone: +1 630 840-3461
+ EMail: crawdad@fnal.gov
+
+
+ Christian Huitema
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052-6399
+
+ EMail: huitema@microsoft.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Crawford, et al. Standards Track [Page 19]
+
+RFC 2874 IPv6 DNS July 2000
+
+
+12. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Crawford, et al. Standards Track [Page 20]
+
diff --git a/doc/rfc/rfc2915.txt b/doc/rfc/rfc2915.txt
new file mode 100644
index 0000000..2022ba1
--- /dev/null
+++ b/doc/rfc/rfc2915.txt
@@ -0,0 +1,1011 @@
+
+
+
+
+
+
+Network Working Group M. Mealling
+Request for Comments: 2915 Network Solutions, Inc.
+Updates: 2168 R. Daniel
+Category: Standards Track DATAFUSION, Inc.
+ September 2000
+
+
+ The Naming Authority Pointer (NAPTR) DNS Resource Record
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ This document describes a Domain Name System (DNS) resource record
+ which specifies a regular expression based rewrite rule that, when
+ applied to an existing string, will produce a new domain label or
+ Uniform Resource Identifier (URI). Depending on the value of the
+ flags field of the resource record, the resulting domain label or URI
+ may be used in subsequent queries for the Naming Authority Pointer
+ (NAPTR) resource records (to delegate the name lookup) or as the
+ output of the entire process for which this system is used (a
+ resolution server for URI resolution, a service URI for ENUM style
+ e.164 number to URI mapping, etc).
+
+ This allows the DNS to be used to lookup services for a wide variety
+ of resource names (including URIs) which are not in domain name
+ syntax. Reasons for doing this range from URN Resource Discovery
+ Systems to moving out-of-date services to new domains.
+
+ This document updates the portions of RFC 2168 specifically dealing
+ with the definition of the NAPTR records and how other, non-URI
+ specific applications, might use NAPTR.
+
+
+
+
+
+
+
+
+
+Mealling & Daniel Standards Track [Page 1]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 2. NAPTR RR Format . . . . . . . . . . . . . . . . . . . . . . 3
+ 3. Substitution Expression Grammar . . . . . . . . . . . . . . 7
+ 4. The Basic NAPTR Algorithm . . . . . . . . . . . . . . . . . 8
+ 5. Concerning How NAPTR Uses SRV Records . . . . . . . . . . . 9
+ 6. Application Specifications . . . . . . . . . . . . . . . . . 10
+ 7. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 7.1 Example 1 . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 7.2 Example 2 . . . . . . . . . . . . . . . . . . . . . . . . . 12
+ 7.3 Example 3 . . . . . . . . . . . . . . . . . . . . . . . . . 13
+ 8. DNS Packet Format . . . . . . . . . . . . . . . . . . . . . 13
+ 9. Master File Format . . . . . . . . . . . . . . . . . . . . . 14
+ 10. Advice for DNS Administrators . . . . . . . . . . . . . . . 14
+ 11. Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
+ 12. IANA Considerations . . . . . . . . . . . . . . . . . . . . 15
+ 13. Security Considerations . . . . . . . . . . . . . . . . . . 15
+ 14. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . 16
+ References . . . . . . . . . . . . . . . . . . . . . . . . . 16
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . 17
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . 18
+
+1. Introduction
+
+ This RR was originally produced by the URN Working Group [3] as a way
+ to encode rule-sets in DNS so that the delegated sections of a URI
+ could be decomposed in such a way that they could be changed and re-
+ delegated over time. The result was a Resource Record that included
+ a regular expression that would be used by a client program to
+ rewrite a string into a domain name. Regular expressions were chosen
+ for their compactness to expressivity ratio allowing for a great deal
+ of information to be encoded in a rather small DNS packet.
+
+ The function of rewriting a string according to the rules in a record
+ has usefulness in several different applications. This document
+ defines the basic assumptions to which all of those applications must
+ adhere to. It does not define the reasons the rewrite is used, what
+ the expected outcomes are, or what they are used for. Those are
+ specified by applications that define how they use the NAPTR record
+ and algorithms within their contexts.
+
+ Flags and other fields are also specified in the RR to control the
+ rewrite procedure in various ways or to provide information on how to
+ communicate with the host at the domain name that was the result of
+ the rewrite.
+
+
+
+
+
+Mealling & Daniel Standards Track [Page 2]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ The final result is a RR that has several fields that interact in a
+ non-trivial but implementable way. This document specifies those
+ fields and their values.
+
+ This document does not define applications that utilizes this rewrite
+ functionality. Instead it specifies just the mechanics of how it is
+ done. Why its done, what the rules concerning the inputs, and the
+ types of rules used are reserved for other documents that fully
+ specify a particular application. This separation is due to several
+ different applications all wanting to take advantage of the rewrite
+ rule lookup process. Each one has vastly different reasons for why
+ and how it uses the service, thus requiring that the definition of
+ the service be generic.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
+ NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL"
+ in this document are to be interpreted as described in RFC 2119.
+
+ All references to Uniform Resource Identifiers in this document
+ adhere to the 'absoluteURI' production of the "Collected ABNF"
+ found in RFC 2396 [9]. Specifically, the semantics of URI
+ References do not apply since the concept of a Base makes no sense
+ here.
+
+2. NAPTR RR Format
+
+ The format of the NAPTR RR is given below. The DNS type code [1] for
+ NAPTR is 35.
+
+ Domain TTL Class Type Order Preference Flags Service Regexp
+ Replacement
+
+ Domain
+ The domain name to which this resource record refers. This is the
+ 'key' for this entry in the rule database. This value will either
+ be the first well known key (<something>.uri.arpa for example) or
+ a new key that is the output of a replacement or regexp rewrite.
+ Beyond this, it has the standard DNS requirements [1].
+
+ TTL
+ Standard DNS meaning [1].
+
+ Class
+ Standard DNS meaning [1].
+
+ Type
+ The Type Code [1] for NAPTR is 35.
+
+
+
+
+Mealling & Daniel Standards Track [Page 3]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ Order
+ A 16-bit unsigned integer specifying the order in which the NAPTR
+ records MUST be processed to ensure the correct ordering of
+ rules. Low numbers are processed before high numbers, and once a
+ NAPTR is found whose rule "matches" the target, the client MUST
+ NOT consider any NAPTRs with a higher value for order (except as
+ noted below for the Flags field).
+
+ Preference
+ A 16-bit unsigned integer that specifies the order in which NAPTR
+ records with equal "order" values SHOULD be processed, low
+ numbers being processed before high numbers. This is similar to
+ the preference field in an MX record, and is used so domain
+ administrators can direct clients towards more capable hosts or
+ lighter weight protocols. A client MAY look at records with
+ higher preference values if it has a good reason to do so such as
+ not understanding the preferred protocol or service.
+
+ The important difference between Order and Preference is that
+ once a match is found the client MUST NOT consider records with a
+ different Order but they MAY process records with the same Order
+ but different Preferences. I.e., Preference is used to give weight
+ to rules that are considered the same from an authority
+ standpoint but not from a simple load balancing standpoint.
+
+ Flags
+ A <character-string> containing flags to control aspects of the
+ rewriting and interpretation of the fields in the record. Flags
+ are single characters from the set [A-Z0-9]. The case of the
+ alphabetic characters is not significant.
+
+ At this time only four flags, "S", "A", "U", and "P", are
+ defined. The "S", "A" and "U" flags denote a terminal lookup.
+ This means that this NAPTR record is the last one and that the
+ flag determines what the next stage should be. The "S" flag
+ means that the next lookup should be for SRV records [4]. See
+ Section 5 for additional information on how NAPTR uses the SRV
+ record type. "A" means that the next lookup should be for either
+ an A, AAAA, or A6 record. The "U" flag means that the next step
+ is not a DNS lookup but that the output of the Regexp field is an
+ URI that adheres to the 'absoluteURI' production found in the
+ ABNF of RFC 2396 [9]. Since there may be applications that use
+ NAPTR to also lookup aspects of URIs, implementors should be
+ aware that this may cause loop conditions and should act
+ accordingly.
+
+
+
+
+
+
+Mealling & Daniel Standards Track [Page 4]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ The "P" flag says that the remainder of the application side
+ algorithm shall be carried out in a Protocol-specific fashion.
+ The new set of rules is identified by the Protocol specified in
+ the Services field. The record that contains the 'P' flag is the
+ last record that is interpreted by the rules specified in this
+ document. The new rules are dependent on the application for
+ which they are being used and the protocol specified. For
+ example, if the application is a URI RDS and the protocol is WIRE
+ then the new set of rules are governed by the algorithms
+ surrounding the WIRE HTTP specification and not this document.
+
+ The remaining alphabetic flags are reserved for future versions
+ of the NAPTR specification. The numeric flags may be used for
+ local experimentation. The S, A, U and P flags are all mutually
+ exclusive, and resolution libraries MAY signal an error if more
+ than one is given. (Experimental code and code for assisting in
+ the creation of NAPTRs would be more likely to signal such an
+ error than a client such as a browser). It is anticipated that
+ multiple flags will be allowed in the future, so implementers
+ MUST NOT assume that the flags field can only contain 0 or 1
+ characters. Finally, if a client encounters a record with an
+ unknown flag, it MUST ignore it and move to the next record. This
+ test takes precedence even over the "order" field. Since flags
+ can control the interpretation placed on fields, a novel flag
+ might change the interpretation of the regexp and/or replacement
+ fields such that it is impossible to determine if a record
+ matched a given target.
+
+ The "S", "A", and "U" flags are called 'terminal' flags since
+ they halt the looping rewrite algorithm. If those flags are not
+ present, clients may assume that another NAPTR RR exists at the
+ domain name produced by the current rewrite rule. Since the "P"
+ flag specifies a new algorithm, it may or may not be 'terminal'.
+ Thus, the client cannot assume that another NAPTR exists since
+ this case is determined elsewhere.
+
+ DNS servers MAY interpret these flags and values and use that
+ information to include appropriate SRV and A,AAAA, or A6 records
+ in the additional information portion of the DNS packet. Clients
+ are encouraged to check for additional information but are not
+ required to do so.
+
+ Service
+ Specifies the service(s) available down this rewrite path. It may
+ also specify the particular protocol that is used to talk with a
+ service. A protocol MUST be specified if the flags field states
+ that the NAPTR is terminal. If a protocol is specified, but the
+ flags field does not state that the NAPTR is terminal, the next
+
+
+
+Mealling & Daniel Standards Track [Page 5]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ lookup MUST be for a NAPTR. The client MAY choose not to perform
+ the next lookup if the protocol is unknown, but that behavior
+ MUST NOT be relied upon.
+
+ The service field may take any of the values below (using the
+ Augmented BNF of RFC 2234 [5]):
+
+ service_field = [ [protocol] *("+" rs)]
+ protocol = ALPHA *31ALPHANUM
+ rs = ALPHA *31ALPHANUM
+ ; The protocol and rs fields are limited to 32
+ ; characters and must start with an alphabetic.
+
+ For example, an optional protocol specification followed by 0 or
+ more resolution services. Each resolution service is indicated by
+ an initial '+' character.
+
+ Note that the empty string is also a valid service field. This
+ will typically be seen at the beginning of a series of rules,
+ when it is impossible to know what services and protocols will be
+ offered by a particular service.
+
+ The actual format of the service request and response will be
+ determined by the resolution protocol, and is the subject for
+ other documents. Protocols need not offer all services. The
+ labels for service requests shall be formed from the set of
+ characters [A-Z0-9]. The case of the alphabetic characters is
+ not significant.
+
+ The list of "valid" protocols for any given NAPTR record is any
+ protocol that implements some or all of the services defined for
+ a NAPTR application. Currently, THTTP [6] is the only protocol
+ that is known to make that claim at the time of publication. Any
+ other protocol that is to be used must have documentation
+ specifying:
+
+ * how it implements the services of the application
+
+ * how it is to appear in the NAPTR record (i.e., the string id
+ of the protocol)
+
+ The list of valid Resolution Services is defined by the documents
+ that specify individual NAPTR based applications.
+
+ It is worth noting that the interpretation of this field is
+ subject to being changed by new flags, and that the current
+ specification is oriented towards telling clients how to talk
+ with a URN resolver.
+
+
+
+Mealling & Daniel Standards Track [Page 6]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ Regexp
+ A STRING containing a substitution expression that is applied to
+ the original string held by the client in order to construct the
+ next domain name to lookup. The grammar of the substitution
+ expression is given in the next section.
+
+ The regular expressions MUST NOT be used in a cumulative fashion,
+ that is, they should only be applied to the original string held
+ by the client, never to the domain name produced by a previous
+ NAPTR rewrite. The latter is tempting in some applications but
+ experience has shown such use to be extremely fault sensitive,
+ very error prone, and extremely difficult to debug.
+
+ Replacement
+ The next NAME to query for NAPTR, SRV, or address records
+ depending on the value of the flags field. This MUST be a fully
+ qualified domain-name. Unless and until permitted by future
+ standards action, name compression is not to be used for this
+ field.
+
+3. Substitution Expression Grammar
+
+ The content of the regexp field is a substitution expression. True
+ sed(1) and Perl style substitution expressions are not appropriate
+ for use in this application for a variety of reasons stemming from
+ internationalization requirements and backref limitations, therefore
+ the contents of the regexp field MUST follow the grammar below:
+
+subst_expr = delim-char ere delim-char repl delim-char *flags
+delim-char = "/" / "!" / ... <Any non-digit or non-flag character
+ other than backslash '\'. All occurances of a delim_char
+ in a subst_expr must be the same character.>
+ere = POSIX Extended Regular Expression
+repl = 1 * ( OCTET / backref )
+backref = "\" 1POS_DIGIT
+flags = "i"
+POS_DIGIT = %x31-39 ; 0 is not an allowed backref
+
+ The definition of a POSIX Extended Regular Expression can be found in
+ [8], section 2.8.4.
+
+ The result of applying the substitution expression to the original
+ URI MUST result in either a string that obeys the syntax for DNS
+ domain-names [1] or a URI [9] if the Flags field contains a 'u'.
+ Since it is possible for the regexp field to be improperly specified,
+ such that a non-conforming domain-name can be constructed, client
+ software SHOULD verify that the result is a legal DNS domain-name
+ before making queries on it.
+
+
+
+Mealling & Daniel Standards Track [Page 7]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ Backref expressions in the repl portion of the substitution
+ expression are replaced by the (possibly empty) string of characters
+ enclosed by '(' and ')' in the ERE portion of the substitution
+ expression. N is a single digit from 1 through 9, inclusive. It
+ specifies the N'th backref expression, the one that begins with the
+ N'th '(' and continues to the matching ')'. For example, the ERE
+
+ (A(B(C)DE)(F)G)
+
+ has backref expressions:
+
+ \1 = ABCDEFG
+ \2 = BCDE
+ \3 = C
+ \4 = F
+ \5..\9 = error - no matching subexpression
+
+ The "i" flag indicates that the ERE matching SHALL be performed in a
+ case-insensitive fashion. Furthermore, any backref replacements MAY
+ be normalized to lower case when the "i" flag is given.
+
+ The first character in the substitution expression shall be used as
+ the character that delimits the components of the substitution
+ expression. There must be exactly three non-escaped occurrences of
+ the delimiter character in a substitution expression. Since escaped
+ occurrences of the delimiter character will be interpreted as
+ occurrences of that character, digits MUST NOT be used as delimiters.
+ Backrefs would be confused with literal digits were this allowed.
+ Similarly, if flags are specified in the substitution expression, the
+ delimiter character must not also be a flag character.
+
+4. The Basic NAPTR Algorithm
+
+ The behavior and meaning of the flags and services assume an
+ algorithm where the output of one rewrite is a new key that points to
+ another rule. This looping algorithm allows NAPTR records to
+ incrementally specify a complete rule. These incremental rules can
+ be delegated which allows other entities to specify rules so that one
+ entity does not need to understand _all_ rules.
+
+ The algorithm starts with a string and some known key (domain).
+ NAPTR records for this key are retrieved, those with unknown Flags or
+ inappropriate Services are discarded and the remaining records are
+ sorted by their Order field. Within each value of Order, the records
+ are further sorted by the Preferences field.
+
+ The records are examined in sorted order until a matching record is
+ found. A record is considered a match iff:
+
+
+
+Mealling & Daniel Standards Track [Page 8]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ o it has a Replacement field value instead of a Regexp field value.
+
+ o or the Regexp field matches the string held by the client.
+
+ The first match MUST be the match that is used. Once a match is
+ found, the Services field is examined for whether or not this rule
+ advances toward the desired result. If so, the rule is applied to
+ the target string. If not, the process halts. The domain that
+ results from the regular expression is then used as the domain of the
+ next loop through the NAPTR algorithm. Note that the same target
+ string is used throughout the algorithm.
+
+ This looping is extremely important since it is the method by which
+ complex rules are broken down into manageable delegated chunks. The
+ flags fields simply determine at which point the looping should stop
+ (or other specialized behavior).
+
+ Since flags are valid at any level of the algorithm, the degenerative
+ case is to never loop but to look up the NAPTR and then stop. In
+ many specialized cases this is all that is needed. Implementors
+ should be aware that the degenerative case should not become the
+ common case.
+
+5. Concerning How NAPTR Uses SRV Records
+
+ When the SRV record type was originally specified it assumed that the
+ client did not know the specific domain-name before hand. The client
+ would construct a domain-name more in the form of a question than the
+ usual case of knowing ahead of time that the domain-name should
+ exist. I.e., if the client wants to know if there is a TCP based
+ HTTP server running at a particular domain, the client would
+ construct the domain-name _http._tcp.somedomain.com and ask the DNS
+ if that records exists. The underscores are used to avoid collisions
+ with potentially 'real' domain-names.
+
+ In the case of NAPTR, the actual domain-name is specified by the
+ various fields in the NAPTR record. In this case the client isn't
+ asking a question but is instead attempting to get at information
+ that it has been told exists in an SRV record at that particular
+ domain-name. While this usage of SRV is slightly different than the
+ SRV authors originally intended it does not break any of the
+ assumptions concerning what SRV contains. Also, since the NAPTR
+ explicitly spells out the domain-name for which an SRV exists, that
+ domain-name MUST be used in SRV queries with NO transformations. Any
+ given NAPTR record may result in a domain-name to be used for SRV
+ queries that may or may not contain the SRV standardized underscore
+
+
+
+
+
+Mealling & Daniel Standards Track [Page 9]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ characters. NAPTR applications that make use of SRV MUST NOT attempt
+ to understand these domains or use them according to how the SRV
+ specification structures its query domains.
+
+6. Application Specifications
+
+ It should be noted that the NAPTR algorithm is the basic assumption
+ about how NAPTR works. The reasons for the rewrite and the expected
+ output and its use are specified by documents that define what
+ applications the NAPTR record and algorithm are used for. Any
+ document that defines such an application must define the following:
+
+ o The first known domain-name or how to build it
+
+ o The valid Services and Protocols
+
+ o What the expected use is for the output of the last rewrite
+
+ o The validity and/or behavior of any 'P' flag protocols.
+
+ o The general semantics surrounding why and how NAPTR and its
+ algorithm are being used.
+
+7. Examples
+
+ NOTE: These are examples only. They are taken from ongoing work and
+ may not represent the end result of that work. They are here for
+ pedagogical reasons only.
+
+7.1 Example 1
+
+ NAPTR was originally specified for use with the a Uniform Resource
+ Name Resolver Discovery System. This example details how a
+ particular URN would use the NAPTR record to find a resolver service.
+
+ Consider a URN namespace based on MIME Content-Ids. The URN might
+ look like this:
+
+ urn:cid:39CB83F7.A8450130@fake.gatech.edu
+
+ (Note that this example is chosen for pedagogical purposes, and does
+ not conform to the CID URL scheme.)
+
+ The first step in the resolution process is to find out about the CID
+ namespace. The namespace identifier [3], 'cid', is extracted from
+ the URN, prepended to urn.arpa. 'cid.urn.arpa' then becomes the first
+ 'known' key in the NAPTR algorithm. The NAPTR records for
+ cid.urn.arpa looked up and return a single record:
+
+
+
+Mealling & Daniel Standards Track [Page 10]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ cid.urn.arpa.
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 10 "" "" "/urn:cid:.+@([^\.]+\.)(.*)$/\2/i" .
+
+ There is only one NAPTR response, so ordering the responses is not a
+ problem. The replacement field is empty, so the pattern provided in
+ the regexp field is used. We apply that regexp to the entire URN to
+ see if it matches, which it does. The \2 part of the substitution
+ expression returns the string "gatech.edu". Since the flags field
+ does not contain "s" or "a", the lookup is not terminal and our next
+ probe to DNS is for more NAPTR records where the new domain is '
+ gatech.edu' and the string is the same string as before.
+
+ Note that the rule does not extract the full domain name from the
+ CID, instead it assumes the CID comes from a host and extracts its
+ domain. While all hosts, such as mordred, could have their very own
+ NAPTR, maintaining those records for all the machines at a site as
+ large as Georgia Tech would be an intolerable burden. Wildcards are
+ not appropriate here since they only return results when there is no
+ exactly matching names already in the system.
+
+ The record returned from the query on "gatech.edu" might look like:
+
+;; order pref flags service regexp replacement
+ IN NAPTR 100 50 "s" "z3950+I2L+I2C" "" _z3950._tcp.gatech.edu.
+ IN NAPTR 100 50 "s" "rcds+I2C" "" _rcds._udp.gatech.edu.
+ IN NAPTR 100 50 "s" "http+I2L+I2C+I2R" "" _http._tcp.gatech.edu.
+
+ Continuing with the example, note that the values of the order and
+ preference fields are equal in all records, so the client is free to
+ pick any record. The flags field tells us that these are the last
+ NAPTR patterns we should see, and after the rewrite (a simple
+ replacement in this case) we should look up SRV records to get
+ information on the hosts that can provide the necessary service.
+
+ Assuming we prefer the Z39.50 protocol, our lookup might return:
+
+ ;; Pref Weight Port Target
+ _z3950._tcp.gatech.edu. IN SRV 0 0 1000 z3950.gatech.edu.
+ IN SRV 0 0 1000 z3950.cc.gatech.edu.
+ IN SRV 0 0 1000 z3950.uga.edu.
+
+ telling us three hosts that could actually do the resolution, and
+ giving us the port we should use to talk to their Z39.50 server.
+
+ Recall that the regular expression used \2 to extract a domain name
+ from the CID, and \. for matching the literal '.' characters
+ separating the domain name components. Since '\' is the escape
+
+
+
+Mealling & Daniel Standards Track [Page 11]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ character, literal occurances of a backslash must be escaped by
+ another backslash. For the case of the cid.urn.arpa record above,
+ the regular expression entered into the master file should be
+ "/urn:cid:.+@([^\\.]+\\.)(.*)$/\\2/i". When the client code actually
+ receives the record, the pattern will have been converted to
+ "/urn:cid:.+@([^\.]+\.)(.*)$/\2/i".
+
+7.2 Example 2
+
+ Even if URN systems were in place now, there would still be a
+ tremendous number of URLs. It should be possible to develop a URN
+ resolution system that can also provide location independence for
+ those URLs. This is related to the requirement that URNs be able to
+ grandfather in names from other naming systems, such as ISO Formal
+ Public Identifiers, Library of Congress Call Numbers, ISBNs, ISSNs,
+ etc.
+
+ The NAPTR RR could also be used for URLs that have already been
+ assigned. Assume we have the URL for a very popular piece of
+ software that the publisher wishes to mirror at multiple sites around
+ the world:
+
+ Using the rules specified for this application we extract the prefix,
+ "http", and lookup NAPTR records for http.uri.arpa. This might
+ return a record of the form
+
+ http.uri.arpa. IN NAPTR
+ ;; order pref flags service regexp replacement
+ 100 90 "" "" "!http://([^/:]+)!\1!i" .
+
+ This expression returns everything after the first double slash and
+ before the next slash or colon. (We use the '!' character to delimit
+ the parts of the substitution expression. Otherwise we would have to
+ use backslashes to escape the forward slashes and would have a regexp
+ in the zone file that looked like "/http:\\/\\/([^\\/:]+)/\\1/i".).
+
+ Applying this pattern to the URL extracts "www.foo.com". Looking up
+ NAPTR records for that might return:
+
+ www.foo.com.
+ ;; order pref flags service regexp replacement
+ IN NAPTR 100 100 "s" "http+I2R" "" _http._tcp.foo.com.
+ IN NAPTR 100 100 "s" "ftp+I2R" "" _ftp._tcp.foo.com.
+
+ Looking up SRV records for http.tcp.foo.com would return information
+ on the hosts that foo.com has designated to be its mirror sites. The
+ client can then pick one for the user.
+
+
+
+
+Mealling & Daniel Standards Track [Page 12]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+7.3 Example 3
+
+ A non-URI example is the ENUM application which uses a NAPTR record
+ to map an e.164 telephone number to a URI. In order to convert the
+ phone number to a domain name for the first iteration all characters
+ other than digits are removed from the the telephone number, the
+ entire number is inverted, periods are put between each digit and the
+ string ".e164.arpa" is put on the left-hand side. For example, the
+ E.164 phone number "+1-770-555-1212" converted to a domain-name it
+ would be "2.1.2.1.5.5.5.0.7.7.1.e164.arpa."
+
+ For this example telephone number we might get back the following
+ NAPTR records:
+
+$ORIGIN 2.1.2.1.5.5.5.0.7.7.1.e164.arpa.
+ IN NAPTR 100 10 "u" "sip+E2U" "!^.*$!sip:information@tele2.se!" .
+ IN NAPTR 102 10 "u" "mailto+E2U" "!^.*$!mailto:information@tele2.se!" .
+
+ This application uses the same 'u' flag as the URI Resolution
+ application. This flag states that the Rule is terminal and that the
+ output is a URI which contains the information needed to contact that
+ telephone service. ENUM also uses the same format for its Service
+ field except that it defines the 'E2U' service instead of the 'I2*'
+ services that URI resolution uses. The example above states that the
+ available protocols used to access that telephone's service are
+ either the Session Initiation Protocol or SMTP mail.
+
+8. DNS Packet Format
+
+ The packet format for the NAPTR record is:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ORDER |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | PREFERENCE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / FLAGS /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / SERVICES /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / REGEXP /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ / REPLACEMENT /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+
+
+
+Mealling & Daniel Standards Track [Page 13]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ where:
+
+ FLAGS A <character-string> which contains various flags.
+
+ SERVICES A <character-string> which contains protocol and service
+ identifiers.
+
+ REGEXP A <character-string> which contains a regular expression.
+
+ REPLACEMENT A <domain-name> which specifies the new value in the
+ case where the regular expression is a simple replacement
+ operation.
+
+ <character-string> and <domain-name> as used here are defined in
+ RFC1035 [1].
+
+9. Master File Format
+
+ The master file format follows the standard rules in RFC-1035 [1].
+ Order and preference, being 16-bit unsigned integers, shall be an
+ integer between 0 and 65535. The Flags and Services and Regexp
+ fields are all quoted <character-string>s. Since the Regexp field
+ can contain numerous backslashes and thus should be treated with
+ care. See Section 10 for how to correctly enter and escape the
+ regular expression.
+
+10. Advice for DNS Administrators
+
+ Beware of regular expressions. Not only are they difficult to get
+ correct on their own, but there is the previously mentioned
+ interaction with DNS. Any backslashes in a regexp must be entered
+ twice in a zone file in order to appear once in a query response.
+ More seriously, the need for double backslashes has probably not been
+ tested by all implementors of DNS servers.
+
+ The "a" flag allows the next lookup to be for address records (A,
+ AAAA, A6) rather than SRV records. Since there is no place for a
+ port specification in the NAPTR record, when the "A" flag is used the
+ specified protocol must be running on its default port.
+
+ The URN Syntax draft defines a canonical form for each URN, which
+ requires %encoding characters outside a limited repertoire. The
+ regular expressions MUST be written to operate on that canonical
+ form. Since international character sets will end up with extensive
+ use of %encoded characters, regular expressions operating on them
+ will be essentially impossible to read or write by hand.
+
+
+
+
+
+Mealling & Daniel Standards Track [Page 14]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+11. Notes
+
+ o A client MUST process multiple NAPTR records in the order
+ specified by the "order" field, it MUST NOT simply use the first
+ record that provides a known protocol and service combination.
+
+ o When multiple RRs have the same "order" and all other criteria
+ being equal, the client should use the value of the preference
+ field to select the next NAPTR to consider. However, because it
+ will often be the case where preferred protocols or services
+ exist, clients may use this additional criteria to sort
+ the records.
+
+ o If the lookup after a rewrite fails, clients are strongly
+ encouraged to report a failure, rather than backing up to pursue
+ other rewrite paths.
+
+ o Note that SRV RRs impose additional requirements on clients.
+
+12. IANA Considerations
+
+ The only registration function that impacts the IANA is for the
+ values that are standardized for the Services and Flags fields. To
+ extend the valid values of the Flags field beyond what is specified
+ in this document requires a published specification that is approved
+ by the IESG.
+
+ The values for the Services field will be determined by the
+ application that makes use of the NAPTR record. Those values must be
+ specified in a published specification and approved by the IESG.
+
+13. Security Considerations
+
+ The interactions with DNSSEC are currently being studied. It is
+ expected that NAPTR records will be signed with SIG records once the
+ DNSSEC work is deployed.
+
+ The rewrite rules make identifiers from other namespaces subject to
+ the same attacks as normal domain names. Since they have not been
+ easily resolvable before, this may or may not be considered a
+ problem.
+
+ Regular expressions should be checked for sanity, not blindly passed
+ to something like PERL.
+
+ This document has discussed a way of locating a service, but has not
+ discussed any detail of how the communication with that service takes
+ place. There are significant security considerations attached to the
+
+
+
+Mealling & Daniel Standards Track [Page 15]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+ communication with a service. Those considerations are outside the
+ scope of this document, and must be addressed by the specifications
+ for particular communication protocols.
+
+14. Acknowledgments
+
+ The editors would like to thank Keith Moore for all his consultations
+ during the development of this memo. We would also like to thank
+ Paul Vixie for his assistance in debugging our implementation, and
+ his answers on our questions. Finally, we would like to acknowledge
+ our enormous intellectual debt to the participants in the Knoxville
+ series of meetings, as well as to the participants in the URI and URN
+ working groups.
+
+References
+
+ [1] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [2] Mockapetris, P., "Domain names - concepts and facilities", STD
+ 13, RFC 1034, November 1987.
+
+ [3] Moats, R., "URN Syntax", RFC 2141, May 1997.
+
+ [4] Gulbrandsen, A., Vixie, P. and L. Esibov, "A DNS RR for
+ specifying the location of services (DNS SRV)", RFC 2782,
+ February 2000.
+
+ [5] Crocker, D., "Augmented BNF for Syntax Specifications: ABNF",
+ RFC 2234, November 1997.
+
+ [6] Daniel, R., "A Trivial Convention for using HTTP in URN
+ Resolution", RFC 2169, June 1997.
+
+ [7] Daniel, R. and M. Mealling, "Resolution of Uniform Resource
+ Identifiers using the Domain Name System", RFC 2168, June 1997.
+
+ [8] IEEE, "IEEE Standard for Information Technology - Portable
+ Operating System Interface (POSIX) - Part 2: Shell and Utilities
+ (Vol. 1)", IEEE Std 1003.2-1992, January 1993.
+
+ [9] Berners-Lee, T., Fielding, R.T. and L. Masinter, "Uniform
+ Resource Identifiers (URI): Generic Syntax", RFC 2396, August
+ 1998.
+
+
+
+
+
+
+
+Mealling & Daniel Standards Track [Page 16]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+Authors' Addresses
+
+ Michael Mealling
+ Network Solutions, Inc.
+ 505 Huntmar Park Drive
+ Herndon, VA 22070
+ US
+
+ Phone: +1 770 921 2251
+ EMail: michaelm@netsol.com
+ URI: http://www.netsol.com
+
+
+ Ron Daniel
+ DATAFUSION, Inc.
+ 139 Townsend Street, Ste. 100
+ San Francisco, CA 94107
+ US
+
+ Phone: +1 415 222 0100
+ EMail: rdaniel@datafusion.net
+ URI: http://www.datafusion.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mealling & Daniel Standards Track [Page 17]
+
+RFC 2915 NAPTR DNS RR September 2000
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Mealling & Daniel Standards Track [Page 18]
+
diff --git a/doc/rfc/rfc2929.txt b/doc/rfc/rfc2929.txt
new file mode 100644
index 0000000..f055968
--- /dev/null
+++ b/doc/rfc/rfc2929.txt
@@ -0,0 +1,675 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake, 3rd
+Request for Comments: 2929 Motorola
+BCP: 42 E. Brunner-Williams
+Category: Best Current Practice Engage
+ B. Manning
+ ISI
+ September 2000
+
+ Domain Name System (DNS) IANA Considerations
+
+Status of this Memo
+
+ This document specifies an Internet Best Current Practices for the
+ Internet Community, and requests discussion and suggestions for
+ improvements. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ Internet Assigned Number Authority (IANA) parameter assignment
+ considerations are given for the allocation of Domain Name System
+ (DNS) classes, Resource Record (RR) types, operation codes, error
+ codes, etc.
+
+Table of Contents
+
+ 1. Introduction................................................. 2
+ 2. DNS Query/Response Headers................................... 2
+ 2.1 One Spare Bit?.............................................. 3
+ 2.2 Opcode Assignment........................................... 3
+ 2.3 RCODE Assignment............................................ 4
+ 3. DNS Resource Records......................................... 5
+ 3.1 RR TYPE IANA Considerations................................. 6
+ 3.1.1 Special Note on the OPT RR................................ 7
+ 3.2 RR CLASS IANA Considerations................................ 7
+ 3.3 RR NAME Considerations...................................... 8
+ 4. Security Considerations...................................... 9
+ References...................................................... 9
+ Authors' Addresses.............................................. 11
+ Full Copyright Statement........................................ 12
+
+
+
+
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 1]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+1. Introduction
+
+ The Domain Name System (DNS) provides replicated distributed secure
+ hierarchical databases which hierarchically store "resource records"
+ (RRs) under domain names.
+
+ This data is structured into CLASSes and zones which can be
+ independently maintained. See [RFC 1034, 1035, 2136, 2181, 2535]
+ familiarity with which is assumed.
+
+ This document covers, either directly or by reference, general IANA
+ parameter assignment considerations applying across DNS query and
+ response headers and all RRs. There may be additional IANA
+ considerations that apply to only a particular RR type or
+ query/response opcode. See the specific RFC defining that RR type or
+ query/response opcode for such considerations if they have been
+ defined.
+
+ IANA currently maintains a web page of DNS parameters. See
+ <http://www.iana.org/numbers.htm>.
+
+ "IETF Standards Action", "IETF Consensus", "Specification Required",
+ and "Private Use" are as defined in [RFC 2434].
+
+2. DNS Query/Response Headers
+
+ The header for DNS queries and responses contains field/bits in the
+ following diagram taken from [RFC 2136, 2535]:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ID |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ |QR| Opcode |AA|TC|RD|RA| Z|AD|CD| RCODE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | QDCOUNT/ZOCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ANCOUNT/PRCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | NSCOUNT/UPCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | ARCOUNT |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ The ID field identifies the query and is echoed in the response so
+ they can be matched.
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 2]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+ The QR bit indicates whether the header is for a query or a response.
+
+ The AA, TC, RD, RA, AD, and CD bits are each theoretically meaningful
+ only in queries or only in responses, depending on the bit. However,
+ many DNS implementations copy the query header as the initial value
+ of the response header without clearing bits. Thus any attempt to
+ use a "query" bit with a different meaning in a response or to define
+ a query meaning for a "response" bit is dangerous given existing
+ implementation. Such meanings may only be assigned by an IETF
+ Standards Action.
+
+ The unsigned fields query count (QDCOUNT), answer count (ANCOUNT),
+ authority count (NSCOUNT), and additional information count (ARCOUNT)
+ express the number of records in each section for all opcodes except
+ Update. These fields have the same structure and data type for
+ Update but are instead the counts for the zone (ZOCOUNT),
+ prerequisite (PRCOUNT), update (UPCOUNT), and additional information
+ (ARCOUNT) sections.
+
+2.1 One Spare Bit?
+
+ There have been ancient DNS implementations for which the Z bit being
+ on in a query meant that only a response from the primary server for
+ a zone is acceptable. It is believed that current DNS
+ implementations ignore this bit.
+
+ Assigning a meaning to the Z bit requires an IETF Standards Action.
+
+2.2 Opcode Assignment
+
+ New OpCode assignments require an IETF Standards Action.
+
+ Currently DNS OpCodes are assigned as follows:
+
+ OpCode Name Reference
+
+ 0 Query [RFC 1035]
+ 1 IQuery (Inverse Query) [RFC 1035]
+ 2 Status [RFC 1035]
+ 3 available for assignment
+ 4 Notify [RFC 1996]
+ 5 Update [RFC 2136]
+ 6-15 available for assignment
+
+
+
+
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 3]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+2.3 RCODE Assignment
+
+ It would appear from the DNS header above that only four bits of
+ RCODE, or response/error code are available. However, RCODEs can
+ appear not only at the top level of a DNS response but also inside
+ OPT RRs [RFC 2671], TSIG RRs [RFC 2845], and TKEY RRs [RFC 2930].
+ The OPT RR provides an eight bit extension resulting in a 12 bit
+ RCODE field and the TSIG and TKEY RRs have a 16 bit RCODE field.
+
+ Error codes appearing in the DNS header and in these three RR types
+ all refer to the same error code space with the single exception of
+ error code 16 which has a different meaning in the OPT RR from its
+ meaning in other contexts. See table below.
+
+ RCODE Name Description Reference
+ Decimal
+ Hexadecimal
+ 0 NoError No Error [RFC 1035]
+ 1 FormErr Format Error [RFC 1035]
+ 2 ServFail Server Failure [RFC 1035]
+ 3 NXDomain Non-Existent Domain [RFC 1035]
+ 4 NotImp Not Implemented [RFC 1035]
+ 5 Refused Query Refused [RFC 1035]
+ 6 YXDomain Name Exists when it should not [RFC 2136]
+ 7 YXRRSet RR Set Exists when it should not [RFC 2136]
+ 8 NXRRSet RR Set that should exist does not [RFC 2136]
+ 9 NotAuth Server Not Authoritative for zone [RFC 2136]
+ 10 NotZone Name not contained in zone [RFC 2136]
+ 11-15 available for assignment
+ 16 BADVERS Bad OPT Version [RFC 2671]
+ 16 BADSIG TSIG Signature Failure [RFC 2845]
+ 17 BADKEY Key not recognized [RFC 2845]
+ 18 BADTIME Signature out of time window [RFC 2845]
+ 19 BADMODE Bad TKEY Mode [RFC 2930]
+ 20 BADNAME Duplicate key name [RFC 2930]
+ 21 BADALG Algorithm not supported [RFC 2930]
+ 22-3840 available for assignment
+ 0x0016-0x0F00
+ 3841-4095 Private Use
+ 0x0F01-0x0FFF
+ 4096-65535 available for assignment
+ 0x1000-0xFFFF
+
+ Since it is important that RCODEs be understood for interoperability,
+ assignment of new RCODE listed above as "available for assignment"
+ requires an IETF Consensus.
+
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 4]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+3. DNS Resource Records
+
+ All RRs have the same top level format shown in the figure below
+ taken from [RFC 1035]:
+
+ 1 1 1 1 1 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | |
+ / /
+ / NAME /
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TYPE |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | CLASS |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | TTL |
+ | |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ | RDLENGTH |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+ / RDATA /
+ / /
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ NAME is an owner name, i.e., the name of the node to which this
+ resource record pertains. NAMEs are specific to a CLASS as described
+ in section 3.2. NAMEs consist of an ordered sequence of one or more
+ labels each of which has a label type [RFC 1035, 2671].
+
+ TYPE is a two octet unsigned integer containing one of the RR TYPE
+ codes. See section 3.1.
+
+ CLASS is a two octet unsigned integer containing one of the RR CLASS
+ codes. See section 3.2.
+
+ TTL is a four octet (32 bit) bit unsigned integer that specifies the
+ number of seconds that the resource record may be cached before the
+ source of the information should again be consulted. Zero is
+ interpreted to mean that the RR can only be used for the transaction
+ in progress.
+
+ RDLENGTH is an unsigned 16 bit integer that specifies the length in
+ octets of the RDATA field.
+
+
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 5]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+ RDATA is a variable length string of octets that constitutes the
+ resource. The format of this information varies according to the
+ TYPE and in some cases the CLASS of the resource record.
+
+3.1 RR TYPE IANA Considerations
+
+ There are three subcategories of RR TYPE numbers: data TYPEs, QTYPEs,
+ and MetaTYPEs.
+
+ Data TYPEs are the primary means of storing data. QTYPES can only be
+ used in queries. Meta-TYPEs designate transient data associated with
+ an particular DNS message and in some cases can also be used in
+ queries. Thus far, data TYPEs have been assigned from 1 upwards plus
+ the block from 100 through 103 while Q and Meta Types have been
+ assigned from 255 downwards (except for the OPT Meta-RR which is
+ assigned TYPE 41). There have been DNS implementations which made
+ caching decisions based on the top bit of the bottom byte of the RR
+ TYPE.
+
+ There are currently three Meta-TYPEs assigned: OPT [RFC 2671], TSIG
+ [RFC 2845], and TKEY [RFC 2930].
+
+ There are currently five QTYPEs assigned: * (all), MAILA, MAILB,
+ AXFR, and IXFR.
+
+ Considerations for the allocation of new RR TYPEs are as follows:
+
+ Decimal
+ Hexadecimal
+
+ 0
+ 0x0000 - TYPE zero is used as a special indicator for the SIG RR [RFC
+ 2535] and in other circumstances and must never be allocated
+ for ordinary use.
+
+ 1 - 127
+ 0x0001 - 0x007F - remaining TYPEs in this range are assigned for data
+ TYPEs by IETF Consensus.
+
+ 128 - 255
+ 0x0080 - 0x00FF - remaining TYPEs in this rage are assigned for Q and
+ Meta TYPEs by IETF Consensus.
+
+ 256 - 32767
+ 0x0100 - 0x7FFF - assigned for data, Q, or Meta TYPE use by IETF
+ Consensus.
+
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 6]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+ 32768 - 65279
+ 0x8000 - 0xFEFF - Specification Required as defined in [RFC 2434].
+
+ 65280 - 65535
+ 0xFF00 - 0xFFFF - Private Use.
+
+3.1.1 Special Note on the OPT RR
+
+ The OPT (OPTion) RR, number 41, is specified in [RFC 2671]. Its
+ primary purpose is to extend the effective field size of various DNS
+ fields including RCODE, label type, flag bits, and RDATA size. In
+ particular, for resolvers and servers that recognize it, it extends
+ the RCODE field from 4 to 12 bits.
+
+3.2 RR CLASS IANA Considerations
+
+ DNS CLASSes have been little used but constitute another dimension of
+ the DNS distributed database. In particular, there is no necessary
+ relationship between the name space or root servers for one CLASS and
+ those for another CLASS. The same name can have completely different
+ meanings in different CLASSes although the label types are the same
+ and the null label is usable only as root in every CLASS. However,
+ as global networking and DNS have evolved, the IN, or Internet, CLASS
+ has dominated DNS use.
+
+ There are two subcategories of DNS CLASSes: normal data containing
+ classes and QCLASSes that are only meaningful in queries or updates.
+
+ The current CLASS assignments and considerations for future
+ assignments are as follows:
+
+ Decimal
+ Hexadecimal
+
+ 0
+ 0x0000 - assignment requires an IETF Standards Action.
+
+ 1
+ 0x0001 - Internet (IN).
+
+ 2
+ 0x0002 - available for assignment by IETF Consensus as a data CLASS.
+
+ 3
+ 0x0003 - Chaos (CH) [Moon 1981].
+
+ 4
+ 0x0004 - Hesiod (HS) [Dyer 1987].
+
+
+
+Eastlake, et al. Best Current Practice [Page 7]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+ 5 - 127
+ 0x0005 - 0x007F - available for assignment by IETF Consensus as data
+ CLASSes only.
+
+ 128 - 253
+ 0x0080 - 0x00FD - available for assignment by IETF Consensus as
+ QCLASSes only.
+
+ 254
+ 0x00FE - QCLASS None [RFC 2136].
+
+ 255
+ 0x00FF - QCLASS Any [RFC 1035].
+
+ 256 - 32767
+ 0x0100 - 0x7FFF - assigned by IETF Consensus.
+
+ 32768 - 65280
+ 0x8000 - 0xFEFF - assigned based on Specification Required as defined
+ in [RFC 2434].
+
+ 65280 - 65534
+ 0xFF00 - 0xFFFE - Private Use.
+
+ 65535
+ 0xFFFF - can only be assigned by an IETF Standards Action.
+
+3.3 RR NAME Considerations
+
+ DNS NAMEs are sequences of labels [RFC 1035]. The last label in each
+ NAME is "ROOT" which is the zero length label. By definition, the
+ null or ROOT label can not be used for any other NAME purpose.
+
+ At the present time, there are two categories of label types, data
+ labels and compression labels. Compression labels are pointers to
+ data labels elsewhere within an RR or DNS message and are intended to
+ shorten the wire encoding of NAMEs. The two existing data label
+ types are sometimes referred to as Text and Binary. Text labels can,
+ in fact, include any octet value including zero octets but most
+ current uses involve only [US-ASCII]. For retrieval, Text labels are
+ defined to treat ASCII upper and lower case letter codes as matching.
+ Binary labels are bit sequences [RFC 2673].
+
+ IANA considerations for label types are given in [RFC 2671].
+
+
+
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 8]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+ NAMEs are local to a CLASS. The Hesiod [Dyer 1987] and Chaos [Moon
+ 1981] CLASSes are essentially for local use. The IN or Internet
+ CLASS is thus the only DNS CLASS in global use on the Internet at
+ this time.
+
+ A somewhat dated description of name allocation in the IN Class is
+ given in [RFC 1591]. Some information on reserved top level domain
+ names is in Best Current Practice 32 [RFC 2606].
+
+4. Security Considerations
+
+ This document addresses IANA considerations in the allocation of
+ general DNS parameters, not security. See [RFC 2535] for secure DNS
+ considerations.
+
+References
+
+ [Dyer 1987] Dyer, S., and F. Hsu, "Hesiod", Project Athena Technical
+ Plan - Name Service, April 1987,
+
+ [Moon 1981] D. Moon, "Chaosnet", A.I. Memo 628, Massachusetts
+ Institute of Technology Artificial Intelligence
+ Laboratory, June 1981.
+
+ [RFC 1034] Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC 1035] Mockapetris, P., "Domain Names - Implementation and
+ Specifications", STD 13, RFC 1035, November 1987.
+
+ [RFC 1591] Postel, J., "Domain Name System Structure and
+ Delegation", RFC 1591, March 1994.
+
+ [RFC 1996] Vixie, P., "A Mechanism for Prompt Notification of Zone
+ Changes (DNS NOTIFY)", RFC 1996, August 1996.
+
+ [RFC 2136] Vixie, P., Thomson, S., Rekhter, Y. and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)",
+ RFC 2136, April 1997.
+
+ [RFC 2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC 2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 9]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+ [RFC 2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC 2606] Eastlake, D. and A. Panitz, "Reserved Top Level DNS
+ Names", RFC 2606, June 1999.
+
+ [RFC 2671] Vixie, P., "Extension mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [RFC 2672] Crawford, M., "Non-Terminal DNS Name Redirection", RFC
+ 2672, August 1999.
+
+ [RFC 2673] Crawford, M., "Binary Labels in the Domain Name System",
+ RFC 2673, August 1999.
+
+ [RFC 2845] Vixie, P., Gudmundsson, O., Eastlake, D. and B.
+ Wellington, "Secret Key Transaction Authentication for
+ DNS (TSIG)", RFC 2845, May 2000.
+
+ [RFC 2930] Eastlake, D., "Secret Key Establishment for DNS (TKEY
+ RR)", RFC 2930, September 2000.
+
+ [US-ASCII] ANSI, "USA Standard Code for Information Interchange",
+ X3.4, American National Standards Institute: New York,
+ 1968.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 10]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+Authors' Addresses
+
+ Donald E. Eastlake 3rd
+ Motorola
+ 140 Forest Avenue
+ Hudson, MA 01749 USA
+
+ Phone: +1-978-562-2827 (h)
+ +1-508-261-5434 (w)
+ Fax: +1-508-261-4447 (w)
+ EMail: Donald.Eastlake@motorola.com
+
+
+ Eric Brunner-Williams
+ Engage
+ 100 Brickstone Square, 2nd Floor
+ Andover, MA 01810
+
+ Phone: +1-207-797-0525 (h)
+ +1-978-684-7796 (w)
+ Fax: +1-978-684-3118
+ EMail: brunner@engage.com
+
+
+ Bill Manning
+ USC/ISI
+ 4676 Admiralty Way, #1001
+ Marina del Rey, CA 90292 USA
+
+ Phone: +1-310-822-1511
+ EMail: bmanning@isi.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 11]
+
+RFC 2929 DNS IANA Considerations September 2000
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake, et al. Best Current Practice [Page 12]
+
diff --git a/doc/rfc/rfc2930.txt b/doc/rfc/rfc2930.txt
new file mode 100644
index 0000000..f99573d
--- /dev/null
+++ b/doc/rfc/rfc2930.txt
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake, 3rd
+Request for Comments: 2930 Motorola
+Category: Standards Track September 2000
+
+
+ Secret Key Establishment for DNS (TKEY RR)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ [RFC 2845] provides a means of authenticating Domain Name System
+ (DNS) queries and responses using shared secret keys via the
+ Transaction Signature (TSIG) resource record (RR). However, it
+ provides no mechanism for setting up such keys other than manual
+ exchange. This document describes a Transaction Key (TKEY) RR that
+ can be used in a number of different modes to establish shared secret
+ keys between a DNS resolver and server.
+
+Acknowledgments
+
+ The comments and ideas of the following persons (listed in alphabetic
+ order) have been incorporated herein and are gratefully acknowledged:
+
+ Olafur Gudmundsson (TIS)
+
+ Stuart Kwan (Microsoft)
+
+ Ed Lewis (TIS)
+
+ Erik Nordmark (SUN)
+
+ Brian Wellington (Nominum)
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 1]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+Table of Contents
+
+ 1. Introduction............................................... 2
+ 1.1 Overview of Contents...................................... 3
+ 2. The TKEY Resource Record................................... 4
+ 2.1 The Name Field............................................ 4
+ 2.2 The TTL Field............................................. 5
+ 2.3 The Algorithm Field....................................... 5
+ 2.4 The Inception and Expiration Fields....................... 5
+ 2.5 The Mode Field............................................ 5
+ 2.6 The Error Field........................................... 6
+ 2.7 The Key Size and Data Fields.............................. 6
+ 2.8 The Other Size and Data Fields............................ 6
+ 3. General TKEY Considerations................................ 7
+ 4. Exchange via Resolver Query................................ 8
+ 4.1 Query for Diffie-Hellman Exchanged Keying................. 8
+ 4.2 Query for TKEY Deletion................................... 9
+ 4.3 Query for GSS-API Establishment........................... 10
+ 4.4 Query for Server Assigned Keying.......................... 10
+ 4.5 Query for Resolver Assigned Keying........................ 11
+ 5. Spontaneous Server Inclusion............................... 12
+ 5.1 Spontaneous Server Key Deletion........................... 12
+ 6. Methods of Encryption...................................... 12
+ 7. IANA Considerations........................................ 13
+ 8. Security Considerations.................................... 13
+ References.................................................... 14
+ Author's Address.............................................. 15
+ Full Copyright Statement...................................... 16
+
+1. Introduction
+
+ The Domain Name System (DNS) is a hierarchical, distributed, highly
+ available database used for bi-directional mapping between domain
+ names and addresses, for email routing, and for other information
+ [RFC 1034, 1035]. It has been extended to provide for public key
+ security and dynamic update [RFC 2535, RFC 2136]. Familiarity with
+ these RFCs is assumed.
+
+ [RFC 2845] provides a means of efficiently authenticating DNS
+ messages using shared secret keys via the TSIG resource record (RR)
+ but provides no mechanism for setting up such keys other than manual
+ exchange. This document specifies a TKEY RR that can be used in a
+ number of different modes to establish and delete such shared secret
+ keys between a DNS resolver and server.
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 2]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+ Note that TKEY established keying material and TSIGs that use it are
+ associated with DNS servers or resolvers. They are not associated
+ with zones. They may be used to authenticate queries and responses
+ but they do not provide zone based DNS data origin or denial
+ authentication [RFC 2535].
+
+ Certain modes of TKEY perform encryption which may affect their
+ export or import status for some countries. The affected modes
+ specified in this document are the server assigned mode and the
+ resolver assigned mode.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC 2119].
+
+ In all cases herein, the term "resolver" includes that part of a
+ server which may make full and incremental [RFC 1995] zone transfer
+ queries, forwards recursive queries, etc.
+
+1.1 Overview of Contents
+
+ Section 2 below specifies the TKEY RR and provides a description of
+ and considerations for its constituent fields.
+
+ Section 3 describes general principles of operations with TKEY.
+
+ Section 4 discusses key agreement and deletion via DNS requests with
+ the Query opcode for RR type TKEY. This method is applicable to all
+ currently defined TKEY modes, although in some cases it is not what
+ would intuitively be called a "query".
+
+ Section 5 discusses spontaneous inclusion of TKEY RRs in responses by
+ servers which is currently used only for key deletion.
+
+ Section 6 describes encryption methods for transmitting secret key
+ information. In this document these are used only for the server
+ assigned mode and the resolver assigned mode.
+
+ Section 7 covers IANA considerations in assignment of TKEY modes.
+
+ Finally, Section 8 provides the required security considerations
+ section.
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 3]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+2. The TKEY Resource Record
+
+ The TKEY resource record (RR) has the structure given below. Its RR
+ type code is 249.
+
+ Field Type Comment
+ ----- ---- -------
+
+ NAME domain see description below
+ TTYPE u_int16_t TKEY = 249
+ CLASS u_int16_t ignored, SHOULD be 255 (ANY)
+ TTL u_int32_t ignored, SHOULD be zero
+ RDLEN u_int16_t size of RDATA
+ RDATA:
+ Algorithm: domain
+ Inception: u_int32_t
+ Expiration: u_int32_t
+ Mode: u_int16_t
+ Error: u_int16_t
+ Key Size: u_int16_t
+ Key Data: octet-stream
+ Other Size: u_int16_t
+ Other Data: octet-stream undefined by this specification
+
+2.1 The Name Field
+
+ The Name field relates to naming keys. Its meaning differs somewhat
+ with mode and context as explained in subsequent sections.
+
+ At any DNS server or resolver only one octet string of keying
+ material may be in place for any particular key name. An attempt to
+ establish another set of keying material at a server for an existing
+ name returns a BADNAME error.
+
+ For a TKEY with a non-root name appearing in a query, the TKEY RR
+ name SHOULD be a domain locally unique at the resolver, less than 128
+ octets long in wire encoding, and meaningful to the resolver to
+ assist in distinguishing keys and/or key agreement sessions. For
+ TKEY(s) appearing in a response to a query, the TKEY RR name SHOULD
+ be a globally unique server assigned domain.
+
+ A reasonable key naming strategy is as follows:
+
+ If the key is generated as the result of a query with root as its
+ owner name, then the server SHOULD create a globally unique domain
+ name, to be the key name, by suffixing a pseudo-random [RFC 1750]
+ label with a domain name of the server. For example
+ 89n3mDgX072pp.server1.example.com. If generation of a new
+
+
+
+Eastlake Standards Track [Page 4]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+ pseudo-random name in each case is an excessive computation load
+ or entropy drain, a serial number prefix can be added to a fixed
+ pseudo-random name generated an DNS server start time, such as
+ 1001.89n3mDgX072pp.server1.example.com.
+
+ If the key is generated as the result of a query with a non-root
+ name, say 789.resolver.example.net, then use the concatenation of
+ that with a name of the server. For example
+ 789.resolver.example.net.server1.example.com.
+
+2.2 The TTL Field
+
+ The TTL field is meaningless in TKEY RRs. It SHOULD always be zero to
+ be sure that older DNS implementations do not cache TKEY RRs.
+
+2.3 The Algorithm Field
+
+ The algorithm name is in the form of a domain name with the same
+ meaning as in [RFC 2845]. The algorithm determines how the secret
+ keying material agreed to using the TKEY RR is actually used to
+ derive the algorithm specific key.
+
+2.4 The Inception and Expiration Fields
+
+ The inception time and expiration times are in number of seconds
+ since the beginning of 1 January 1970 GMT ignoring leap seconds
+ treated as modulo 2**32 using ring arithmetic [RFC 1982]. In messages
+ between a DNS resolver and a DNS server where these fields are
+ meaningful, they are either the requested validity interval for the
+ keying material asked for or specify the validity interval of keying
+ material provided.
+
+ To avoid different interpretations of the inception and expiration
+ times in TKEY RRs, resolvers and servers exchanging them must have
+ the same idea of what time it is. One way of doing this is with the
+ NTP protocol [RFC 2030] but that or any other time synchronization
+ used for this purpose MUST be done securely.
+
+2.5 The Mode Field
+
+ The mode field specifies the general scheme for key agreement or the
+ purpose of the TKEY DNS message. Servers and resolvers supporting
+ this specification MUST implement the Diffie-Hellman key agreement
+ mode and the key deletion mode for queries. All other modes are
+ OPTIONAL. A server supporting TKEY that receives a TKEY request with
+ a mode it does not support returns the BADMODE error. The following
+ values of the Mode octet are defined, available, or reserved:
+
+
+
+
+Eastlake Standards Track [Page 5]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+ Value Description
+ ----- -----------
+ 0 - reserved, see section 7
+ 1 server assignment
+ 2 Diffie-Hellman exchange
+ 3 GSS-API negotiation
+ 4 resolver assignment
+ 5 key deletion
+ 6-65534 - available, see section 7
+ 65535 - reserved, see section 7
+
+2.6 The Error Field
+
+ The error code field is an extended RCODE. The following values are
+ defined:
+
+ Value Description
+ ----- -----------
+ 0 - no error
+ 1-15 a non-extended RCODE
+ 16 BADSIG (TSIG)
+ 17 BADKEY (TSIG)
+ 18 BADTIME (TSIG)
+ 19 BADMODE
+ 20 BADNAME
+ 21 BADALG
+
+ When the TKEY Error Field is non-zero in a response to a TKEY query,
+ the DNS header RCODE field indicates no error. However, it is
+ possible if a TKEY is spontaneously included in a response the TKEY
+ RR and DNS header error field could have unrelated non-zero error
+ codes.
+
+2.7 The Key Size and Data Fields
+
+ The key data size field is an unsigned 16 bit integer in network
+ order which specifies the size of the key exchange data field in
+ octets. The meaning of this data depends on the mode.
+
+2.8 The Other Size and Data Fields
+
+ The Other Size and Other Data fields are not used in this
+ specification but may be used in future extensions. The RDLEN field
+ MUST equal the length of the RDATA section through the end of Other
+ Data or the RR is to be considered malformed and rejected.
+
+
+
+
+
+
+Eastlake Standards Track [Page 6]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+3. General TKEY Considerations
+
+ TKEY is a meta-RR that is not stored or cached in the DNS and does
+ not appear in zone files. It supports a variety of modes for the
+ establishment and deletion of shared secret keys information between
+ DNS resolvers and servers. The establishment of such a shared key
+ requires that state be maintained at both ends and the allocation of
+ the resources to maintain such state may require mutual agreement. In
+ the absence of willingness to provide such state, servers MUST return
+ errors such as NOTIMP or REFUSED for an attempt to use TKEY and
+ resolvers are free to ignore any TKEY RRs they receive.
+
+ The shared secret keying material developed by using TKEY is a plain
+ octet sequence. The means by which this shared secret keying
+ material, exchanged via TKEY, is actually used in any particular TSIG
+ algorithm is algorithm dependent and is defined in connection with
+ that algorithm. For example, see [RFC 2104] for how TKEY agreed
+ shared secret keying material is used in the HMAC-MD5 algorithm or
+ other HMAC algorithms.
+
+ There MUST NOT be more than one TKEY RR in a DNS query or response.
+
+ Except for GSS-API mode, TKEY responses MUST always have DNS
+ transaction authentication to protect the integrity of any keying
+ data, error codes, etc. This authentication MUST use a previously
+ established secret (TSIG) or public (SIG(0) [RFC 2931]) key and MUST
+ NOT use any key that the response to be verified is itself providing.
+
+ TKEY queries MUST be authenticated for all modes except GSS-API and,
+ under some circumstances, server assignment mode. In particular, if
+ the query for a server assigned key is for a key to assert some
+ privilege, such as update authority, then the query must be
+ authenticated to avoid spoofing. However, if the key is just to be
+ used for transaction security, then spoofing will lead at worst to
+ denial of service. Query authentication SHOULD use an established
+ secret (TSIG) key authenticator if available. Otherwise, it must use
+ a public (SIG(0)) key signature. It MUST NOT use any key that the
+ query is itself providing.
+
+ In the absence of required TKEY authentication, a NOTAUTH error MUST
+ be returned.
+
+ To avoid replay attacks, it is necessary that a TKEY response or
+ query not be valid if replayed on the order of 2**32 second (about
+ 136 years), or a multiple thereof, later. To accomplish this, the
+ keying material used in any TSIG or SIG(0) RR that authenticates a
+ TKEY message MUST NOT have a lifetime of more then 2**31 - 1 seconds
+
+
+
+
+Eastlake Standards Track [Page 7]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+ (about 68 years). Thus, on attempted replay, the authenticating TSIG
+ or SIG(0) RR will not be verifiable due to key expiration and the
+ replay will fail.
+
+4. Exchange via Resolver Query
+
+ One method for a resolver and a server to agree about shared secret
+ keying material for use in TSIG is through DNS requests from the
+ resolver which are syntactically DNS queries for type TKEY. Such
+ queries MUST be accompanied by a TKEY RR in the additional
+ information section to indicate the mode in use and accompanied by
+ other information where required.
+
+ Type TKEY queries SHOULD NOT be flagged as recursive and servers MAY
+ ignore the recursive header bit in TKEY queries they receive.
+
+4.1 Query for Diffie-Hellman Exchanged Keying
+
+ Diffie-Hellman (DH) key exchange is a means whereby two parties can
+ derive some shared secret information without requiring any secrecy
+ of the messages they exchange [Schneier]. Provisions have been made
+ for the storage of DH public keys in the DNS [RFC 2539].
+
+ A resolver sends a query for type TKEY accompanied by a TKEY RR in
+ the additional information section specifying the Diffie-Hellman mode
+ and accompanied by a KEY RR also in the additional information
+ section specifying a resolver Diffie-Hellman key. The TKEY RR
+ algorithm field is set to the authentication algorithm the resolver
+ plans to use. The "key data" provided in the TKEY is used as a random
+ [RFC 1750] nonce to avoid always deriving the same keying material
+ for the same pair of DH KEYs.
+
+ The server response contains a TKEY in its answer section with the
+ Diffie-Hellman mode. The "key data" provided in this TKEY is used as
+ an additional nonce to avoid always deriving the same keying material
+ for the same pair of DH KEYs. If the TKEY error field is non-zero,
+ the query failed for the reason given. FORMERR is given if the query
+ included no DH KEY and BADKEY is given if the query included an
+ incompatible DH KEY.
+
+ If the TKEY error field is zero, the resolver supplied Diffie-Hellman
+ KEY RR SHOULD be echoed in the additional information section and a
+ server Diffie-Hellman KEY RR will also be present in the answer
+ section of the response. Both parties can then calculate the same
+ shared secret quantity from the pair of Diffie-Hellman (DH) keys used
+ [Schneier] (provided these DH keys use the same generator and
+ modulus) and the data in the TKEY RRs. The TKEY RR data is mixed
+ with the DH result as follows:
+
+
+
+Eastlake Standards Track [Page 8]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+ keying material =
+ XOR ( DH value, MD5 ( query data | DH value ) |
+ MD5 ( server data | DH value ) )
+
+ Where XOR is an exclusive-OR operation and "|" is byte-stream
+ concatenation. The shorter of the two operands to XOR is byte-wise
+ left justified and padded with zero-valued bytes to match the length
+ of the other operand. "DH value" is the Diffie-Hellman value derived
+ from the KEY RRs. Query data and server data are the values sent in
+ the TKEY RR data fields. These "query data" and "server data" nonces
+ are suffixed by the DH value, digested by MD5, the results
+ concatenated, and then XORed with the DH value.
+
+ The inception and expiry times in the query TKEY RR are those
+ requested for the keying material. The inception and expiry times in
+ the response TKEY RR are the maximum period the server will consider
+ the keying material valid. Servers may pre-expire keys so this is
+ not a guarantee.
+
+4.2 Query for TKEY Deletion
+
+ Keys established via TKEY can be treated as soft state. Since DNS
+ transactions are originated by the resolver, the resolver can simply
+ toss keys, although it may have to go through another key exchange if
+ it later needs one. Similarly, the server can discard keys although
+ that will result in an error on receiving a query with a TSIG using
+ the discarded key.
+
+ To avoid attempted reliance in requests on keys no longer in effect,
+ servers MUST implement key deletion whereby the server "discards" a
+ key on receipt from a resolver of an authenticated delete request for
+ a TKEY RR with the key's name. If the server has no record of a key
+ with that name, it returns BADNAME.
+
+ Key deletion TKEY queries MUST be authenticated. This authentication
+ MAY be a TSIG RR using the key to be deleted.
+
+ For querier assigned and Diffie-Hellman keys, the server MUST truly
+ "discard" all active state associated with the key. For server
+ assigned keys, the server MAY simply mark the key as no longer
+ retained by the client and may re-send it in response to a future
+ query for server assigned keying material.
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 9]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+4.3 Query for GSS-API Establishment
+
+ This mode is described in a separate document under preparation which
+ should be seen for the full description. Basically the resolver and
+ server can exchange queries and responses for type TKEY with a TKEY
+ RR specifying the GSS-API mode in the additional information section
+ and a GSS-API token in the key data portion of the TKEY RR.
+
+ Any issues of possible encryption of parts the GSS-API token data
+ being transmitted are handled by the GSS-API level. In addition, the
+ GSS-API level provides its own authentication so that this mode of
+ TKEY query and response MAY be, but do not need to be, authenticated
+ with TSIG RR or SIG(0) RR [RFC 2931].
+
+ The inception and expiry times in a GSS-API mode TKEY RR are ignored.
+
+4.4 Query for Server Assigned Keying
+
+ Optionally, the server can assign keying for the resolver. It is
+ sent to the resolver encrypted under a resolver public key. See
+ section 6 for description of encryption methods.
+
+ A resolver sends a query for type TKEY accompanied by a TKEY RR
+ specifying the "server assignment" mode and a resolver KEY RR to be
+ used in encrypting the response, both in the additional information
+ section. The TKEY algorithm field is set to the authentication
+ algorithm the resolver plans to use. It is RECOMMENDED that any "key
+ data" provided in the query TKEY RR by the resolver be strongly mixed
+ by the server with server generated randomness [RFC 1750] to derive
+ the keying material to be used. The KEY RR that appears in the query
+ need not be accompanied by a SIG(KEY) RR. If the query is
+ authenticated by the resolver with a TSIG RR [RFC 2845] or SIG(0) RR
+ and that authentication is verified, then any SIG(KEY) provided in
+ the query SHOULD be ignored. The KEY RR in such a query SHOULD have
+ a name that corresponds to the resolver but it is only essential that
+ it be a public key for which the resolver has the corresponding
+ private key so it can decrypt the response data.
+
+ The server response contains a TKEY RR in its answer section with the
+ server assigned mode and echoes the KEY RR provided in the query in
+ its additional information section.
+
+ If the response TKEY error field is zero, the key data portion of the
+ response TKEY RR will be the server assigned keying data encrypted
+ under the public key in the resolver provided KEY RR. In this case,
+ the owner name of the answer TKEY RR will be the server assigned name
+ of the key.
+
+
+
+
+Eastlake Standards Track [Page 10]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+ If the error field of the response TKEY is non-zero, the query failed
+ for the reason given. FORMERR is given if the query specified no
+ encryption key.
+
+ The inception and expiry times in the query TKEY RR are those
+ requested for the keying material. The inception and expiry times in
+ the response TKEY are the maximum period the server will consider the
+ keying material valid. Servers may pre-expire keys so this is not a
+ guarantee.
+
+ The resolver KEY RR MUST be authenticated, through the authentication
+ of this query with a TSIG or SIG(0) or the signing of the resolver
+ KEY with a SIG(KEY). Otherwise, an attacker can forge a resolver KEY
+ for which they know the private key, and thereby the attacker could
+ obtain a valid shared secret key from the server.
+
+4.5 Query for Resolver Assigned Keying
+
+ Optionally, a server can accept resolver assigned keys. The keying
+ material MUST be encrypted under a server key for protection in
+ transmission as described in Section 6.
+
+ The resolver sends a TKEY query with a TKEY RR that specifies the
+ encrypted keying material and a KEY RR specifying the server public
+ key used to encrypt the data, both in the additional information
+ section. The name of the key and the keying data are completely
+ controlled by the sending resolver so a globally unique key name
+ SHOULD be used. The KEY RR used MUST be one for which the server has
+ the corresponding private key, or it will not be able to decrypt the
+ keying material and will return a FORMERR. It is also important that
+ no untrusted party (preferably no other party than the server) has
+ the private key corresponding to the KEY RR because, if they do, they
+ can capture the messages to the server, learn the shared secret, and
+ spoof valid TSIGs.
+
+ The query TKEY RR inception and expiry give the time period the
+ querier intends to consider the keying material valid. The server
+ can return a lesser time interval to advise that it will not maintain
+ state for that long and can pre-expire keys in any case.
+
+ This mode of query MUST be authenticated with a TSIG or SIG(0).
+ Otherwise, an attacker can forge a resolver assigned TKEY query, and
+ thereby the attacker could specify a shared secret key that would be
+ accepted, used, and honored by the server.
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 11]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+5. Spontaneous Server Inclusion
+
+ A DNS server may include a TKEY RR spontaneously as additional
+ information in responses. This SHOULD only be done if the server
+ knows the querier understands TKEY and has this option implemented.
+ This technique can be used to delete a key and may be specified for
+ modes defined in the future. A disadvantage of this technique is
+ that there is no way for the server to get any error or success
+ indication back and, in the case of UDP, no way to even know if the
+ DNS response reached the resolver.
+
+5.1 Spontaneous Server Key Deletion
+
+ A server can optionally tell a client that it has deleted a secret
+ key by spontaneously including a TKEY RR in the additional
+ information section of a response with the key's name and specifying
+ the key deletion mode. Such a response SHOULD be authenticated. If
+ authenticated, it "deletes" the key with the given name. The
+ inception and expiry times of the delete TKEY RR are ignored. Failure
+ by a client to receive or properly process such additional
+ information in a response would mean that the client might use a key
+ that the server had discarded and would then get an error indication.
+
+ For server assigned and Diffie-Hellman keys, the client MUST
+ "discard" active state associated with the key. For querier assigned
+ keys, the querier MAY simply mark the key as no longer retained by
+ the server and may re-send it in a future query specifying querier
+ assigned keying material.
+
+6. Methods of Encryption
+
+ For the server assigned and resolver assigned key agreement modes,
+ the keying material is sent within the key data field of a TKEY RR
+ encrypted under the public key in an accompanying KEY RR [RFC 2535].
+ This KEY RR MUST be for a public key algorithm where the public and
+ private keys can be used for encryption and the corresponding
+ decryption which recovers the originally encrypted data. The KEY RR
+ SHOULD correspond to a name for the decrypting resolver/server such
+ that the decrypting process has access to the corresponding private
+ key to decrypt the data. The secret keying material being sent will
+ generally be fairly short, usually less than 256 bits, because that
+ is adequate for very strong protection with modern keyed hash or
+ symmetric algorithms.
+
+ If the KEY RR specifies the RSA algorithm, then the keying material
+ is encrypted as per the description of RSAES-PKCS1-v1_5 encryption in
+ PKCS#1 [RFC 2437]. (Note, the secret keying material being sent is
+ directly RSA encrypted in PKCS#1 format. It is not "enveloped" under
+
+
+
+Eastlake Standards Track [Page 12]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+ some other symmetric algorithm.) In the unlikely event that the
+ keying material will not fit within one RSA modulus of the chosen
+ public key, additional RSA encryption blocks are included. The
+ length of each block is clear from the public RSA key specified and
+ the RSAES-PKCS1-v1_5 padding makes it clear what part of the
+ encrypted data is actually keying material and what part is
+ formatting or the required at least eight bytes of random [RFC 1750]
+ padding.
+
+7. IANA Considerations
+
+ This section is to be interpreted as provided in [RFC 2434].
+
+ Mode field values 0x0000 and 0xFFFF are reserved.
+
+ Mode field values 0x0001 through 0x00FF, and 0XFF00 through 0XFFFE
+ can only be assigned by an IETF Standards Action.
+
+ Mode field values 0x0100 through 0x0FFF and 0xF0000 through 0xFEFF
+ are allocated by IESG approval or IETF consensus.
+
+ Mode field values 0x1000 through 0xEFFF are allocated based on
+ Specification Required as defined in [RFC 2434].
+
+ Mode values should not be changed when the status of their use
+ changes. For example, a mode value assigned based just on providing
+ a specification should not be changed later just because that use's
+ status is changed to standards track.
+
+ The following assignments are documented herein:
+
+ RR Type 249 for TKEY.
+
+ TKEY Modes 1 through 5 as listed in section 2.5.
+
+ Extended RCODE Error values of 19, 20, and 21 as listed in section
+ 2.6.
+
+8. Security Considerations
+
+ The entirety of this specification is concerned with the secure
+ establishment of a shared secret between DNS clients and servers in
+ support of TSIG [RFC 2845].
+
+ Protection against denial of service via the use of TKEY is not
+ provided.
+
+
+
+
+
+Eastlake Standards Track [Page 13]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+References
+
+ [Schneier] Bruce Schneier, "Applied Cryptography: Protocols,
+ Algorithms, and Source Code in C", 1996, John Wiley and
+ Sons
+
+ [RFC 1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC 1035] Mockapetris, P., "Domain Names - Implementation and
+ Specifications", STD 13, RFC 1035, November 1987.
+
+ [RFC 1750] Eastlake, D., Crocker, S. and J. Schiller, "Randomness
+ Recommendations for Security", RFC 1750, December 1994.
+
+ [RFC 1982] Elz, R. and R. Bush, "Serial Number Arithmetic", RFC 1982,
+ September 1996.
+
+ [RFC 1995] Ohta, M., "Incremental Zone Transfer in DNS", RFC 1995,
+ August 1996.
+
+ [RFC 2030] Mills, D., "Simple Network Time Protocol (SNTP) Version 4
+ for IPv4, IPv6 and OSI", RFC 2030, October 1996.
+
+ [RFC 2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC: Keyed-
+ Hashing for Message Authentication", RFC 2104, February
+ 1997.
+
+ [RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC 2136] Vixie, P., Thomson, S., Rekhter, Y. and J. Bound, "Dynamic
+ Updates in the Domain Name System (DNS UPDATE)", RFC 2136,
+ April 1997.
+
+ [RFC 2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+ [RFC 2437] Kaliski, B. and J. Staddon, "PKCS #1: RSA Cryptography
+ Specifications Version 2.0", RFC 2437, October 1998.
+
+ [RFC 2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC 2539] Eastlake, D., "Storage of Diffie-Hellman Keys in the
+ Domain Name System (DNS)", RFC 2539, March 1999.
+
+
+
+
+Eastlake Standards Track [Page 14]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+ [RFC 2845] Vixie, P., Gudmundsson, O., Eastlake, D. and B.
+ Wellington, "Secret Key Transaction Authentication for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+ [RFC 2931] Eastlake, D., "DNS Request and Transaction Signatures
+ (SIG(0)s )", RFC 2931, September 2000.
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ Motorola
+ 140 Forest Avenue
+ Hudson, MA 01749 USA
+
+ Phone: +1 978-562-2827 (h)
+ +1 508-261-5434 (w)
+ Fax: +1 508-261-4447 (w)
+ EMail: Donald.Eastlake@motorola.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 15]
+
+RFC 2930 The DNS TKEY RR September 2000
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 16]
+
diff --git a/doc/rfc/rfc2931.txt b/doc/rfc/rfc2931.txt
new file mode 100644
index 0000000..84cc97e
--- /dev/null
+++ b/doc/rfc/rfc2931.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake 3rd
+Request for Comments: 2931 Motorola
+Updates: 2535 September 2000
+Category: Standards Track
+
+
+ DNS Request and Transaction Signatures ( SIG(0)s )
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ Extensions to the Domain Name System (DNS) are described in [RFC
+ 2535] that can provide data origin and transaction integrity and
+ authentication to security aware resolvers and applications through
+ the use of cryptographic digital signatures.
+
+ Implementation experience has indicated the need for minor but non-
+ interoperable changes in Request and Transaction signature resource
+ records ( SIG(0)s ). These changes are documented herein.
+
+Acknowledgments
+
+ The contributions and suggestions of the following persons (in
+ alphabetic order) to this memo are gratefully acknowledged:
+
+ Olafur Gudmundsson
+
+ Ed Lewis
+
+ Erik Nordmark
+
+ Brian Wellington
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 1]
+
+RFC 2931 DNS SIG(0) September 2000
+
+
+Table of Contents
+
+ 1. Introduction................................................. 2
+ 2. SIG(0) Design Rationale...................................... 3
+ 2.1 Transaction Authentication.................................. 3
+ 2.2 Request Authentication...................................... 3
+ 2.3 Keying...................................................... 3
+ 2.4 Differences Between TSIG and SIG(0)......................... 4
+ 3. The SIG(0) Resource Record................................... 4
+ 3.1 Calculating Request and Transaction SIGs.................... 5
+ 3.2 Processing Responses and SIG(0) RRs......................... 6
+ 3.3 SIG(0) Lifetime and Expiration.............................. 7
+ 4. Security Considerations...................................... 7
+ 5. IANA Considerations.......................................... 7
+ References...................................................... 7
+ Author's Address................................................ 8
+ Appendix: SIG(0) Changes from RFC 2535.......................... 9
+ Full Copyright Statement........................................ 10
+
+1. Introduction
+
+ This document makes minor but non-interoperable changes to part of
+ [RFC 2535], familiarity with which is assumed, and includes
+ additional explanatory text. These changes concern SIG Resource
+ Records (RRs) that are used to digitally sign DNS requests and
+ transactions / responses. Such a resource record, because it has a
+ type covered field of zero, is frequently called a SIG(0). The
+ changes are based on implementation and attempted implementation
+ experience with TSIG [RFC 2845] and the [RFC 2535] specification for
+ SIG(0).
+
+ Sections of [RFC 2535] updated are all of 4.1.8.1 and parts of 4.2
+ and 4.3. No changes are made herein related to the KEY or NXT RRs or
+ to the processing involved with data origin and denial authentication
+ for DNS data.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC 2119].
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 2]
+
+RFC 2931 DNS SIG(0) September 2000
+
+
+2. SIG(0) Design Rationale
+
+ SIG(0) provides protection for DNS transactions and requests that is
+ not provided by the regular SIG, KEY, and NXT RRs specified in [RFC
+ 2535]. The authenticated data origin services of secure DNS either
+ provide protected data resource records (RRs) or authenticatably deny
+ their nonexistence. These services provide no protection for glue
+ records, DNS requests, no protection for message headers on requests
+ or responses, and no protection of the overall integrity of a
+ response.
+
+2.1 Transaction Authentication
+
+ Transaction authentication means that a requester can be sure it is
+ at least getting the messages from the server it queried and that the
+ received messages are in response to the query it sent. This is
+ accomplished by optionally adding either a TSIG RR [RFC 2845] or, as
+ described herein, a SIG(0) resource record at the end of the response
+ which digitally signs the concatenation of the server's response and
+ the corresponding resolver query.
+
+2.2 Request Authentication
+
+ Requests can also be authenticated by including a TSIG or, as
+ described herein, a special SIG(0) RR at the end of the request.
+ Authenticating requests serves no function in DNS servers that
+ predate the specification of dynamic update. Requests with a non-
+ empty additional information section produce error returns or may
+ even be ignored by a few such older DNS servers. However, this syntax
+ for signing requests is defined for authenticating dynamic update
+ requests [RFC 2136], TKEY requests [RFC 2930], or future requests
+ requiring authentication.
+
+2.3 Keying
+
+ The private keys used in transaction security belong to the host
+ composing the DNS response message, not to the zone involved.
+ Request authentication may also involve the private key of the host
+ or other entity composing the request or of a zone to be affected by
+ the request or other private keys depending on the request authority
+ it is sought to establish. The corresponding public key(s) are
+ normally stored in and retrieved from the DNS for verification as KEY
+ RRs with a protocol byte of 3 (DNSSEC) or 255 (ANY).
+
+ Because requests and replies are highly variable, message
+ authentication SIGs can not be pre-calculated. Thus it will be
+ necessary to keep the private key on-line, for example in software or
+ in a directly connected piece of hardware.
+
+
+
+Eastlake Standards Track [Page 3]
+
+RFC 2931 DNS SIG(0) September 2000
+
+
+2.4 Differences Between TSIG and SIG(0)
+
+ There are significant differences between TSIG and SIG(0).
+
+ Because TSIG involves secret keys installed at both the requester and
+ server the presence of such a key implies that the other party
+ understands TSIG and very likely has the same key installed.
+ Furthermore, TSIG uses keyed hash authentication codes which are
+ relatively inexpensive to compute. Thus it is common to authenticate
+ requests with TSIG and responses are authenticated with TSIG if the
+ corresponding request is authenticated.
+
+ SIG(0) on the other hand, uses public key authentication, where the
+ public keys are stored in DNS as KEY RRs and a private key is stored
+ at the signer. Existence of such a KEY RR does not necessarily imply
+ implementation of SIG(0). In addition, SIG(0) involves relatively
+ expensive public key cryptographic operations that should be
+ minimized and the verification of a SIG(0) involves obtaining and
+ verifying the corresponding KEY which can be an expensive and lengthy
+ operation. Indeed, a policy of using SIG(0) on all requests and
+ verifying it before responding would, for some configurations, lead
+ to a deadly embrace with the attempt to obtain and verify the KEY
+ needed to authenticate the request SIG(0) resulting in additional
+ requests accompanied by a SIG(0) leading to further requests
+ accompanied by a SIG(0), etc. Furthermore, omitting SIG(0)s when not
+ required on requests halves the number of public key operations
+ required by the transaction.
+
+ For these reasons, SIG(0)s SHOULD only be used on requests when
+ necessary to authenticate that the requester has some required
+ privilege or identity. SIG(0)s on replies are defined in such a way
+ as to not require a SIG(0) on the corresponding request and still
+ provide transaction protection. For other replies, whether they are
+ authenticated by the server or required to be authenticated by the
+ requester SHOULD be a local configuration option.
+
+3. The SIG(0) Resource Record
+
+ The structure of and type number of SIG resource records (RRs) is
+ given in [RFC 2535] Section 4.1. However all of Section 4.1.8.1 and
+ the parts of Sections 4.2 and 4.3 related to SIG(0) should be
+ considered replaced by the material below. Any conflict between [RFC
+ 2535] and this document concerning SIG(0) RRs should be resolved in
+ favor of this document.
+
+ For all transaction SIG(0)s, the signer field MUST be a name of the
+ originating host and there MUST be a KEY RR at that name with the
+ public key corresponding to the private key used to calculate the
+
+
+
+Eastlake Standards Track [Page 4]
+
+RFC 2931 DNS SIG(0) September 2000
+
+
+ signature. (The host domain name used may be the inverse IP address
+ mapping name for an IP address of the host if the relevant KEY is
+ stored there.)
+
+ For all SIG(0) RRs, the owner name, class, TTL, and original TTL, are
+ meaningless. The TTL fields SHOULD be zero and the CLASS field
+ SHOULD be ANY. To conserve space, the owner name SHOULD be root (a
+ single zero octet). When SIG(0) authentication on a response is
+ desired, that SIG RR MUST be considered the highest priority of any
+ additional information for inclusion in the response. If the SIG(0)
+ RR cannot be added without causing the message to be truncated, the
+ server MUST alter the response so that a SIG(0) can be included.
+ This response consists of only the question and a SIG(0) record, and
+ has the TC bit set and RCODE 0 (NOERROR). The client should at this
+ point retry the request using TCP.
+
+3.1 Calculating Request and Transaction SIGs
+
+ A DNS request may be optionally signed by including one SIG(0)s at
+ the end of the query additional information section. Such a SIG is
+ identified by having a "type covered" field of zero. It signs the
+ preceding DNS request message including DNS header but not including
+ the UDP/IP header and before the request RR counts have been adjusted
+ for the inclusions of the request SIG(0).
+
+ It is calculated by using a "data" (see [RFC 2535], Section 4.1.8) of
+ (1) the SIG's RDATA section entirely omitting (not just zeroing) the
+ signature subfield itself, (2) the DNS query messages, including DNS
+ header, but not the UDP/IP header and before the reply RR counts have
+ been adjusted for the inclusion of the SIG(0). That is
+
+ data = RDATA | request - SIG(0)
+
+ where "|" is concatenation and RDATA is the RDATA of the SIG(0) being
+ calculated less the signature itself.
+
+ Similarly, a SIG(0) can be used to secure a response and the request
+ that produced it. Such transaction signatures are calculated by
+ using a "data" of (1) the SIG's RDATA section omitting the signature
+ itself, (2) the entire DNS query message that produced this response,
+ including the query's DNS header but not its UDP/IP header, and (3)
+ the entire DNS response message, including DNS header but not the
+ UDP/IP header and before the response RR counts have been adjusted
+ for the inclusion of the SIG(0).
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 5]
+
+RFC 2931 DNS SIG(0) September 2000
+
+
+ That is
+
+ data = RDATA | full query | response - SIG(0)
+
+ where "|" is concatenation and RDATA is the RDATA of the SIG(0) being
+ calculated less the signature itself.
+
+ Verification of a response SIG(0) (which is signed by the server host
+ key, not the zone key) by the requesting resolver shows that the
+ query and response were not tampered with in transit, that the
+ response corresponds to the intended query, and that the response
+ comes from the queried server.
+
+ In the case of a DNS message via TCP, a SIG(0) on the first data
+ packet is calculated with "data" as above and for each subsequent
+ packet, it is calculated as follows:
+
+ data = RDATA | DNS payload - SIG(0) | previous packet
+
+ where "|" is concatenations, RDATA is as above, and previous packet
+ is the previous DNS payload including DNS header and the SIG(0) but
+ not the TCP/IP header. Support of SIG(0) for TCP is OPTIONAL. As an
+ alternative, TSIG may be used after, if necessary, setting up a key
+ with TKEY [RFC 2930].
+
+ Except where needed to authenticate an update, TKEY, or similar
+ privileged request, servers are not required to check a request
+ SIG(0).
+
+ Note: requests and responses can either have a single TSIG or one
+ SIG(0) but not both a TSIG and a SIG(0).
+
+3.2 Processing Responses and SIG(0) RRs
+
+ If a SIG RR is at the end of the additional information section of a
+ response and has a type covered of zero, it is a transaction
+ signature covering the response and the query that produced the
+ response. For TKEY responses, it MUST be checked and the message
+ rejected if the checks fail unless otherwise specified for the TKEY
+ mode in use. For all other responses, it MAY be checked and the
+ message rejected if the checks fail.
+
+ If a response's SIG(0) check succeed, such a transaction
+ authentication SIG does NOT directly authenticate the validity any
+ data-RRs in the message. However, it authenticates that they were
+ sent by the queried server and have not been diddled. (Only a proper
+ SIG(0) RR signed by the zone or a key tracing its authority to the
+ zone or to static resolver configuration can directly authenticate
+
+
+
+Eastlake Standards Track [Page 6]
+
+RFC 2931 DNS SIG(0) September 2000
+
+
+ data-RRs, depending on resolver policy.) If a resolver or server does
+ not implement transaction and/or request SIGs, it MUST ignore them
+ without error where they are optional and treat them as failing where
+ they are required.
+
+3.3 SIG(0) Lifetime and Expiration
+
+ The inception and expiration times in SIG(0)s are for the purpose of
+ resisting replay attacks. They should be set to form a time bracket
+ such that messages outside that bracket can be ignored. In IP
+ networks, this time bracket should not normally extend further than 5
+ minutes into the past and 5 minutes into the future.
+
+4. Security Considerations
+
+ No additional considerations beyond those in [RFC 2535].
+
+ The inclusion of the SIG(0) inception and expiration time under the
+ signature improves resistance to replay attacks.
+
+5. IANA Considerations
+
+ No new parameters are created or parameter values assigned by this
+ document.
+
+References
+
+ [RFC 1982] Elz, R. and R. Bush, "Serial Number Arithmetic", RFC 1982,
+ September 1996.
+
+ [RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC 2136] Vixie, P., Thomson, S., Rekhter, Y. and J. Bound, "Dynamic
+ Updates in the Domain Name System (DNS UPDATE)", RFC 2136,
+ April 1997.
+
+ [RFC 2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC 2845] Vixie, P., Gudmundsson, O., Eastlake, D. and B.
+ Wellington, "Secret Key Transaction Signatures for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+ [RFC 2930] Eastlake, D., "Secret Key Establishment for DNS (RR)", RFC
+ 2930, September 2000.
+
+
+
+
+
+Eastlake Standards Track [Page 7]
+
+RFC 2931 DNS SIG(0) September 2000
+
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ Motorola
+ 140 Forest Avenue
+ Hudson, MA 01749 USA
+
+ Phone: +1-978-562-2827(h)
+ +1-508-261-5434(w)
+ Fax: +1 978-567-7941(h)
+ +1-508-261-4447(w)
+ EMail: Donald.Eastlake@motorola.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 8]
+
+RFC 2931 DNS SIG(0) September 2000
+
+
+Appendix: SIG(0) Changes from RFC 2535
+
+ Add explanatory text concerning the differences between TSIG and
+ SIG(0).
+
+ Change the data over which SIG(0) is calculated to include the SIG(0)
+ RDATA other than the signature itself so as to secure the signature
+ inception and expiration times and resist replay attacks. Specify
+ SIG(0) for TCP.
+
+ Add discussion of appropriate inception and expiration times for
+ SIG(0).
+
+ Add wording to indicate that either a TSIG or one or more SIG(0)s may
+ be present but not both.
+
+ Reword some areas for clarity.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 9]
+
+RFC 2931 DNS SIG(0) September 2000
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake Standards Track [Page 10]
+
diff --git a/doc/rfc/rfc3007.txt b/doc/rfc/rfc3007.txt
new file mode 100644
index 0000000..1697475
--- /dev/null
+++ b/doc/rfc/rfc3007.txt
@@ -0,0 +1,507 @@
+
+
+
+
+
+
+Network Working Group B. Wellington
+Request for Comments: 3007 Nominum
+Updates: 2535, 2136 November 2000
+Obsoletes: 2137
+Category: Standards Track
+
+
+ Secure Domain Name System (DNS) Dynamic Update
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ This document proposes a method for performing secure Domain Name
+ System (DNS) dynamic updates. The method described here is intended
+ to be flexible and useful while requiring as few changes to the
+ protocol as possible. The authentication of the dynamic update
+ message is separate from later DNSSEC validation of the data. Secure
+ communication based on authenticated requests and transactions is
+ used to provide authorization.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [RFC2119].
+
+1 - Introduction
+
+ This document defines a means to secure dynamic updates of the Domain
+ Name System (DNS), allowing only authorized sources to make changes
+ to a zone's contents. The existing unsecured dynamic update
+ operations form the basis for this work.
+
+ Familiarity with the DNS system [RFC1034, RFC1035] and dynamic update
+ [RFC2136] is helpful and is assumed by this document. In addition,
+ knowledge of DNS security extensions [RFC2535], SIG(0) transaction
+ security [RFC2535, RFC2931], and TSIG transaction security [RFC2845]
+ is recommended.
+
+
+
+
+Wellington Standards Track [Page 1]
+
+RFC 3007 Secure Dynamic Update November 2000
+
+
+ This document updates portions of RFC 2535, in particular section
+ 3.1.2, and RFC 2136. This document obsoletes RFC 2137, an alternate
+ proposal for secure dynamic update, due to implementation experience.
+
+1.1 - Overview of DNS Dynamic Update
+
+ DNS dynamic update defines a new DNS opcode and a new interpretation
+ of the DNS message if that opcode is used. An update can specify
+ insertions or deletions of data, along with prerequisites necessary
+ for the updates to occur. All tests and changes for a DNS update
+ request are restricted to a single zone, and are performed at the
+ primary server for the zone. The primary server for a dynamic zone
+ must increment the zone SOA serial number when an update occurs or
+ before the next retrieval of the SOA.
+
+1.2 - Overview of DNS Transaction Security
+
+ Exchanges of DNS messages which include TSIG [RFC2845] or SIG(0)
+ [RFC2535, RFC2931] records allow two DNS entities to authenticate DNS
+ requests and responses sent between them. A TSIG MAC (message
+ authentication code) is derived from a shared secret, and a SIG(0) is
+ generated from a private key whose public counterpart is stored in
+ DNS. In both cases, a record containing the message signature/MAC is
+ included as the final resource record in a DNS message. Keyed
+ hashes, used in TSIG, are inexpensive to calculate and verify.
+ Public key encryption, as used in SIG(0), is more scalable as the
+ public keys are stored in DNS.
+
+1.3 - Comparison of data authentication and message authentication
+
+ Message based authentication, using TSIG or SIG(0), provides
+ protection for the entire message with a single signing and single
+ verification which, in the case of TSIG, is a relatively inexpensive
+ MAC creation and check. For update requests, this signature can
+ establish, based on policy or key negotiation, the authority to make
+ the request.
+
+ DNSSEC SIG records can be used to protect the integrity of individual
+ RRs or RRsets in a DNS message with the authority of the zone owner.
+ However, this cannot sufficiently protect the dynamic update request.
+
+ Using SIG records to secure RRsets in an update request is
+ incompatible with the design of update, as described below, and would
+ in any case require multiple expensive public key signatures and
+ verifications.
+
+
+
+
+
+
+Wellington Standards Track [Page 2]
+
+RFC 3007 Secure Dynamic Update November 2000
+
+
+ SIG records do not cover the message header, which includes record
+ counts. Therefore, it is possible to maliciously insert or remove
+ RRsets in an update request without causing a verification failure.
+
+ If SIG records were used to protect the prerequisite section, it
+ would be impossible to determine whether the SIGs themselves were a
+ prerequisite or simply used for validation.
+
+ In the update section of an update request, signing requests to add
+ an RRset is straightforward, and this signature could be permanently
+ used to protect the data, as specified in [RFC2535]. However, if an
+ RRset is deleted, there is no data for a SIG to cover.
+
+1.4 - Data and message signatures
+
+ As specified in [RFC3008], the DNSSEC validation process performed by
+ a resolver MUST NOT process any non-zone keys unless local policy
+ dictates otherwise. When performing secure dynamic update, all zone
+ data modified in a signed zone MUST be signed by a relevant zone key.
+ This completely disassociates authentication of an update request
+ from authentication of the data itself.
+
+ The primary usefulness of host and user keys, with respect to DNSSEC,
+ is to authenticate messages, including dynamic updates. Thus, host
+ and user keys MAY be used to generate SIG(0) records to authenticate
+ updates and MAY be used in the TKEY [RFC2930] process to generate
+ TSIG shared secrets. In both cases, no SIG records generated by
+ non-zone keys will be used in a DNSSEC validation process unless
+ local policy dictates.
+
+ Authentication of data, once it is present in DNS, only involves
+ DNSSEC zone keys and signatures generated by them.
+
+1.5 - Signatory strength
+
+ [RFC2535, section 3.1.2] defines the signatory field of a key as the
+ final 4 bits of the flags field, but does not define its value. This
+ proposal leaves this field undefined. Updating [RFC2535], this field
+ SHOULD be set to 0 in KEY records, and MUST be ignored.
+
+2 - Authentication
+
+ TSIG or SIG(0) records MUST be included in all secure dynamic update
+ messages. This allows the server to verifiably determine the
+ originator of a message. If the message contains authentication in
+ the form of a SIG(0), the identity of the sender (that is, the
+ principal) is the owner of the KEY RR that generated the SIG(0). If
+ the message contains a TSIG generated by a statically configured
+
+
+
+Wellington Standards Track [Page 3]
+
+RFC 3007 Secure Dynamic Update November 2000
+
+
+ shared secret, the principal is the same as or derived from the
+ shared secret name. If the message contains a TSIG generated by a
+ dynamically configured shared secret, the principal is the same as
+ the one that authenticated the TKEY process; if the TKEY process was
+ unauthenticated, no information is known about the principal, and the
+ associated TSIG shared secret MUST NOT be used for secure dynamic
+ update.
+
+ SIG(0) signatures SHOULD NOT be generated by zone keys, since
+ transactions are initiated by a host or user, not a zone.
+
+ DNSSEC SIG records (other than SIG(0)) MAY be included in an update
+ message, but MUST NOT be used to authenticate the update request.
+
+ If an update fails because it is signed with an unauthorized key, the
+ server MUST indicate failure by returning a message with RCODE
+ REFUSED. Other TSIG, SIG(0), or dynamic update errors are returned
+ as specified in the appropriate protocol description.
+
+3 - Policy
+
+ All policy is configured by the zone administrator and enforced by
+ the zone's primary name server. Policy dictates the authorized
+ actions that an authenticated principal can take. Policy checks are
+ based on the principal and the desired action, where the principal is
+ derived from the message signing key and applied to dynamic update
+ messages signed with that key.
+
+ The server's policy defines criteria which determine if the key used
+ to sign the update is permitted to perform the requested updates. By
+ default, a principal MUST NOT be permitted to make any changes to
+ zone data; any permissions MUST be enabled though configuration.
+
+ The policy is fully implemented in the primary zone server's
+ configuration for several reasons. This removes limitations imposed
+ by encoding policy into a fixed number of bits (such as the KEY RR's
+ signatory field). Policy is only relevant in the server applying it,
+ so there is no reason to expose it. Finally, a change in policy or a
+ new type of policy should not affect the DNS protocol or data format,
+ and should not cause interoperability failures.
+
+3.1 - Standard policies
+
+ Implementations SHOULD allow access control policies to use the
+ principal as an authorization token, and MAY also allow policies to
+ grant permission to a signed message regardless of principal.
+
+
+
+
+
+Wellington Standards Track [Page 4]
+
+RFC 3007 Secure Dynamic Update November 2000
+
+
+ A common practice would be to restrict the permissions of a principal
+ by domain name. That is, a principal could be permitted to add,
+ delete, or modify entries corresponding to one or more domain names.
+ Implementations SHOULD allow per-name access control, and SHOULD
+ provide a concise representation of the principal's own name, its
+ subdomains, and all names in the zone.
+
+ Additionally, a server SHOULD allow restricting updates by RR type,
+ so that a principal could add, delete, or modify specific record
+ types at certain names. Implementations SHOULD allow per-type access
+ control, and SHOULD provide concise representations of all types and
+ all "user" types, where a user type is defined as one that does not
+ affect the operation of DNS itself.
+
+3.1.1 - User types
+
+ User types include all data types except SOA, NS, SIG, and NXT. SOA
+ and NS records SHOULD NOT be modified by normal users, since these
+ types create or modify delegation points. The addition of SIG
+ records can lead to attacks resulting in additional workload for
+ resolvers, and the deletion of SIG records could lead to extra work
+ for the server if the zone SIG was deleted. Note that these records
+ are not forbidden, but not recommended for normal users.
+
+ NXT records MUST NOT be created, modified, or deleted by dynamic
+ update, as their update may cause instability in the protocol. This
+ is an update to RFC 2136.
+
+ Issues concerning updates of KEY records are discussed in the
+ Security Considerations section.
+
+3.2 - Additional policies
+
+ Users are free to implement any policies. Policies may be as
+ specific or general as desired, and as complex as desired. They may
+ depend on the principal or any other characteristics of the signed
+ message.
+
+4 - Interaction with DNSSEC
+
+ Although this protocol does not change the way updates to secure
+ zones are processed, there are a number of issues that should be
+ clarified.
+
+
+
+
+
+
+
+
+Wellington Standards Track [Page 5]
+
+RFC 3007 Secure Dynamic Update November 2000
+
+
+4.1 - Adding SIGs
+
+ An authorized update request MAY include SIG records with each RRset.
+ Since SIG records (except SIG(0) records) MUST NOT be used for
+ authentication of the update message, they are not required.
+
+ If a principal is authorized to update SIG records and there are SIG
+ records in the update, the SIG records are added without
+ verification. The server MAY examine SIG records and drop SIGs with
+ a temporal validity period in the past.
+
+4.2 - Deleting SIGs
+
+ If a principal is authorized to update SIG records and the update
+ specifies the deletion of SIG records, the server MAY choose to
+ override the authority and refuse the update. For example, the
+ server may allow all SIG records not generated by a zone key to be
+ deleted.
+
+4.3 - Non-explicit updates to SIGs
+
+ If the updated zone is secured, the RRset affected by an update
+ operation MUST, at the completion of the update, be signed in
+ accordance with the zone's signing policy. This will usually require
+ one or more SIG records to be generated by one or more zone keys
+ whose private components MUST be online [RFC3008].
+
+ When the contents of an RRset are updated, the server MAY delete all
+ associated SIG records, since they will no longer be valid.
+
+4.4 - Effects on the zone
+
+ If any changes are made, the server MUST, if necessary, generate a
+ new SOA record and new NXT records, and sign these with the
+ appropriate zone keys. Changes to NXT records by secure dynamic
+ update are explicitly forbidden. SOA updates are allowed, since the
+ maintenance of SOA parameters is outside of the scope of the DNS
+ protocol.
+
+5 - Security Considerations
+
+ This document requires that a zone key and possibly other
+ cryptographic secret material be held in an on-line, network-
+ connected host, most likely a name server. This material is at the
+ mercy of host security to remain a secret. Exposing this secret puts
+ DNS data at risk of masquerade attacks. The data at risk is that in
+ both zones served by the machine and delegated from this machine.
+
+
+
+
+Wellington Standards Track [Page 6]
+
+RFC 3007 Secure Dynamic Update November 2000
+
+
+ Allowing updates of KEY records may lead to undesirable results,
+ since a principal may be allowed to insert a public key without
+ holding the private key, and possibly masquerade as the key owner.
+
+6 - Acknowledgements
+
+ The author would like to thank the following people for review and
+ informative comments (in alphabetical order):
+
+ Harald Alvestrand
+ Donald Eastlake
+ Olafur Gudmundsson
+ Andreas Gustafsson
+ Bob Halley
+ Stuart Kwan
+ Ed Lewis
+
+7 - References
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2136] Vixie (Ed.), P., Thomson, S., Rekhter, Y. and J. Bound,
+ "Dynamic Updates in the Domain Name System", RFC 2136,
+ April 1997.
+
+ [RFC2137] Eastlake, D., "Secure Domain Name System Dynamic Update",
+ RFC 2137, April 1997.
+
+ [RFC2535] Eastlake, G., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC2845] Vixie, P., Gudmundsson, O., Eastlake, D. and B.
+ Wellington, "Secret Key Transaction Signatures for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+ [RFC2930] Eastlake, D., "Secret Key Establishment for DNS (TKEY
+ RR)", RFC 2930, September 2000.
+
+ [RFC2931] Eastlake, D., "DNS Request and Transaction Signatures
+ (SIG(0)s)", RFC 2931, September 2000.
+
+ [RFC3008] Wellington, B., "Domain Name System Security (DNSSEC)
+ Signing Authority", RFC 3008, November 2000.
+
+
+
+
+Wellington Standards Track [Page 7]
+
+RFC 3007 Secure Dynamic Update November 2000
+
+
+8 - Author's Address
+
+ Brian Wellington
+ Nominum, Inc.
+ 950 Charter Street
+ Redwood City, CA 94063
+
+ Phone: +1 650 381 6022
+ EMail: Brian.Wellington@nominum.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wellington Standards Track [Page 8]
+
+RFC 3007 Secure Dynamic Update November 2000
+
+
+9. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wellington Standards Track [Page 9]
+
diff --git a/doc/rfc/rfc3008.txt b/doc/rfc/rfc3008.txt
new file mode 100644
index 0000000..08a4a8f
--- /dev/null
+++ b/doc/rfc/rfc3008.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group B. Wellington
+Request for Comments: 3008 Nominum
+Updates: 2535 November 2000
+Category: Standards Track
+
+
+ Domain Name System Security (DNSSEC) Signing Authority
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+Abstract
+
+ This document proposes a revised model of Domain Name System Security
+ (DNSSEC) Signing Authority. The revised model is designed to clarify
+ earlier documents and add additional restrictions to simplify the
+ secure resolution process. Specifically, this affects the
+ authorization of keys to sign sets of records.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [RFC2119].
+
+1 - Introduction
+
+ This document defines additional restrictions on DNSSEC signatures
+ (SIG) records relating to their authority to sign associated data.
+ The intent is to establish a standard policy followed by a secure
+ resolver; this policy can be augmented by local rules. This builds
+ upon [RFC2535], updating section 2.3.6 of that document.
+
+ The most significant change is that in a secure zone, zone data is
+ required to be signed by the zone key.
+
+ Familiarity with the DNS system [RFC1034, RFC1035] and the DNS
+ security extensions [RFC2535] is assumed.
+
+
+
+
+
+
+Wellington Standards Track [Page 1]
+
+RFC 3008 DNSSEC Signing Authority November 2000
+
+
+2 - The SIG Record
+
+ A SIG record is normally associated with an RRset, and "covers" (that
+ is, demonstrates the authenticity and integrity of) the RRset. This
+ is referred to as a "data SIG". Note that there can be multiple SIG
+ records covering an RRset, and the same validation process should be
+ repeated for each of them. Some data SIGs are considered "material",
+ that is, relevant to a DNSSEC capable resolver, and some are
+ "immaterial" or "extra-DNSSEC", as they are not relevant to DNSSEC
+ validation. Immaterial SIGs may have application defined roles. SIG
+ records may exist which are not bound to any RRset; these are also
+ considered immaterial. The validation process determines which SIGs
+ are material; once a SIG is shown to be immaterial, no other
+ validation is necessary.
+
+ SIGs may also be used for transaction security. In this case, a SIG
+ record with a type covered field of 0 is attached to a message, and
+ is used to protect message integrity. This is referred to as a
+ SIG(0) [RFC2535, RFC2931].
+
+ The following sections define requirements for all of the fields of a
+ SIG record. These requirements MUST be met in order for a DNSSEC
+ capable resolver to process this signature. If any of these
+ requirements are not met, the SIG cannot be further processed.
+ Additionally, once a KEY has been identified as having generated this
+ SIG, there are requirements that it MUST meet.
+
+2.1 - Type Covered
+
+ For a data SIG, the type covered MUST be the same as the type of data
+ in the associated RRset. For a SIG(0), the type covered MUST be 0.
+
+2.2 - Algorithm Number
+
+ The algorithm specified in a SIG MUST be recognized by the client,
+ and it MUST be an algorithm that has a defined SIG rdata format.
+
+2.3 - Labels
+
+ The labels count MUST be less than or equal to the number of labels
+ in the SIG owner name, as specified in [RFC2535, section 4.1.3].
+
+2.4 - Original TTL
+
+ The original TTL MUST be greater than or equal to the TTL of the SIG
+ record itself, since the TTL cannot be increased by intermediate
+ servers. This field can be ignored for SIG(0) records.
+
+
+
+
+Wellington Standards Track [Page 2]
+
+RFC 3008 DNSSEC Signing Authority November 2000
+
+
+2.5 - Signature Expiration and Inception
+
+ The current time at the time of validation MUST lie within the
+ validity period bounded by the inception and expiration times.
+
+2.6 - Key Tag
+
+ There are no restrictions on the Key Tag field, although it is
+ possible that future algorithms will impose constraints.
+
+2.7 - Signer's Name
+
+ The signer's name field of a data SIG MUST contain the name of the
+ zone to which the data and signature belong. The combination of
+ signer's name, key tag, and algorithm MUST identify a zone key if the
+ SIG is to be considered material. The only exception that the
+ signer's name field in a SIG KEY at a zone apex SHOULD contain the
+ parent zone's name, unless the KEY set is self-signed. This document
+ defines a standard policy for DNSSEC validation; local policy may
+ override the standard policy.
+
+ There are no restrictions on the signer field of a SIG(0) record.
+ The combination of signer's name, key tag, and algorithm MUST
+ identify a key if this SIG(0) is to be processed.
+
+2.8 - Signature
+
+ There are no restrictions on the signature field. The signature will
+ be verified at some point, but does not need to be examined prior to
+ verification unless a future algorithm imposes constraints.
+
+3 - The Signing KEY Record
+
+ Once a signature has been examined and its fields validated (but
+ before the signature has been verified), the resolver attempts to
+ locate a KEY that matches the signer name, key tag, and algorithm
+ fields in the SIG. If one is not found, the SIG cannot be verified
+ and is considered immaterial. If KEYs are found, several fields of
+ the KEY record MUST have specific values if the SIG is to be
+ considered material and authorized. If there are multiple KEYs, the
+ following checks are performed on all of them, as there is no way to
+ determine which one generated the signature until the verification is
+ performed.
+
+
+
+
+
+
+
+
+Wellington Standards Track [Page 3]
+
+RFC 3008 DNSSEC Signing Authority November 2000
+
+
+3.1 - Type Flags
+
+ The signing KEY record MUST have a flags value of 00 or 01
+ (authentication allowed, confidentiality optional) [RFC2535, 3.1.2].
+ A DNSSEC resolver MUST only trust signatures generated by keys that
+ are permitted to authenticate data.
+
+3.2 - Name Flags
+
+ The interpretation of this field is considerably different for data
+ SIGs and SIG(0) records.
+
+3.2.1 - Data SIG
+
+ If the SIG record covers an RRset, the name type of the associated
+ KEY MUST be 01 (zone) [RFC2535, 3.1.2]. This updates RFC 2535,
+ section 2.3.6. The DNSSEC validation process performed by a resolver
+ MUST ignore all keys that are not zone keys unless local policy
+ dictates otherwise.
+
+ The primary reason that RFC 2535 allows host and user keys to
+ generate material DNSSEC signatures is to allow dynamic update
+ without online zone keys; that is, avoid storing private keys in an
+ online server. The desire to avoid online signing keys cannot be
+ achieved, though, because they are necessary to sign NXT and SOA sets
+ [RFC3007]. These online zone keys can sign any incoming data.
+ Removing the goal of having no online keys removes the reason to
+ allow host and user keys to generate material signatures.
+
+ Limiting material signatures to zone keys simplifies the validation
+ process. The length of the verification chain is bounded by the
+ name's label depth. The authority of a key is clearly defined; a
+ resolver does not need to make a potentially complicated decision to
+ determine whether a key has the proper authority to sign data.
+
+ Finally, there is no additional flexibility granted by allowing
+ host/user key generated material signatures. As long as users and
+ hosts have the ability to authenticate update requests to the primary
+ zone server, signatures by zone keys are sufficient to protect the
+ integrity of the data to the world at large.
+
+3.2.2 - SIG(0)
+
+ If the SIG record is a SIG(0) protecting a message, the name type of
+ the associated KEY SHOULD be 00 (user) or 10 (host/entity).
+ Transactions are initiated by a host or user, not a zone, so zone
+ keys SHOULD not generate SIG(0) records.
+
+
+
+
+Wellington Standards Track [Page 4]
+
+RFC 3008 DNSSEC Signing Authority November 2000
+
+
+ A client is either explicitly executed by a user or on behalf of a
+ host, therefore the name type of a SIG(0) generated by a client
+ SHOULD be either user or host. A nameserver is associated with a
+ host, and its use of SIG(0) is not associated with a particular zone,
+ so the name type of a SIG(0) generated by a nameserver SHOULD be
+ host.
+
+3.3 - Signatory Flags
+
+ This document does not assign any values to the signatory field, nor
+ require any values to be present.
+
+3.4 - Protocol
+
+ The signing KEY record MUST have a protocol value of 3 (DNSSEC) or
+ 255 (ALL). If a key is not specified for use with DNSSEC, a DNSSEC
+ resolver MUST NOT trust any signature that it generates.
+
+3.5 - Algorithm Number
+
+ The algorithm field MUST be identical to that of the generated SIG
+ record, and MUST meet all requirements for an algorithm value in a
+ SIG record.
+
+4 - Security Considerations
+
+ This document defines a standard baseline for a DNSSEC capable
+ resolver. This is necessary for a thorough security analysis of
+ DNSSEC, if one is to be done.
+
+ Specifically, this document places additional restrictions on SIG
+ records that a resolver must validate before the signature can be
+ considered worthy of DNSSEC trust. This simplifies the protocol,
+ making it more robust and able to withstand scrutiny by the security
+ community.
+
+5 - Acknowledgements
+
+ The author would like to thank the following people for review and
+ informative comments (in alphabetical order):
+
+ Olafur Gudmundsson
+ Ed Lewis
+
+
+
+
+
+
+
+
+Wellington Standards Track [Page 5]
+
+RFC 3008 DNSSEC Signing Authority November 2000
+
+
+6 - References
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2136] Vixie (Ed.), P., Thomson, S., Rekhter, Y. and J. Bound,
+ "Dynamic Updates in the Domain Name System", RFC 2136,
+ April 1997.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC2931] Eastlake, D., "DNS Request and Transaction Signatures
+ (SIG(0)s )", RFC 2931, September 2000.
+
+ [RFC3007] Wellington, B., "Simple Secure Domain Name System
+ (DNS) Dynamic Update", RFC 3007, November 2000.
+
+7 - Author's Address
+
+ Brian Wellington
+ Nominum, Inc.
+ 950 Charter Street
+ Redwood City, CA 94063
+
+ Phone: +1 650 381 6022
+ EMail: Brian.Wellington@nominum.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wellington Standards Track [Page 6]
+
+RFC 3008 DNSSEC Signing Authority November 2000
+
+
+8 Full Copyright Statement
+
+ Copyright (C) The Internet Society (2000). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wellington Standards Track [Page 7]
+
diff --git a/doc/rfc/rfc3071.txt b/doc/rfc/rfc3071.txt
new file mode 100644
index 0000000..2c4d52f
--- /dev/null
+++ b/doc/rfc/rfc3071.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group J. Klensin
+Request for Comments: 3071 February 2001
+Category: Informational
+
+
+ Reflections on the DNS, RFC 1591, and Categories of Domains
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ RFC 1591, "Domain Name System Structure and Delegation", laid out the
+ basic administrative design and principles for the allocation and
+ administration of domains, from the top level down. It was written
+ before the introduction of the world wide web (WWW) and rapid growth
+ of the Internet put significant market, social, and political
+ pressure on domain name allocations. In recent years, 1591 has been
+ cited by all sides in various debates, and attempts have been made by
+ various bodies to update it or adjust its provisions, sometimes under
+ pressures that have arguably produced policies that are less well
+ thought out than the original. Some of those efforts have begun from
+ misconceptions about the provisions of 1591 or the motivation for
+ those provisions. The current directions of the Internet Corporation
+ for Assigned Names and Numbers (ICANN) and other groups who now
+ determine the Domain Name System (DNS) policy directions appear to be
+ drifting away from the policies and philosophy of 1591. This
+ document is being published primarily for historical context and
+ comparative purposes, essentially to document some thoughts about how
+ 1591 might have been interpreted and adjusted by the Internet
+ Assigned Numbers Authority (IANA) and ICANN to better reflect today's
+ world while retaining characteristics and policies that have proven
+ to be effective in supporting Internet growth and stability. An
+ earlier variation of this memo was submitted to ICANN as a comment on
+ its evolving Top-level Domain (TLD) policies.
+
+
+
+
+
+
+
+
+
+Klensin Informational [Page 1]
+
+RFC 3071 Reflections on the DNS and RFC 1591 February 2001
+
+
+1. Introduction
+
+ RFC 1591 [1] has been heavily discussed and referenced in the last
+ year or two, especially in discussions within ICANN and its
+ predecessors about the creation, delegation, and management of top-
+ level domains. In particular, the ICANN Domain Name Supporting
+ Organization (DNSO), and especially its ccTLD constituency, have been
+ the home of many discussions in which 1591 and interpretations of it
+ have been cited in support of a variety of sometimes-contradictory
+ positions. During that period, other discussions have gone on to try
+ to reconstruct the thinking that went into RFC 1591. Those in turn
+ have led me and others to muse on how that original thinking might
+ relate to some of the issues being raised. 1591 is, I believe, one
+ of Jon Postel's masterpieces, drawing together very different
+ philosophies (e.g., his traditional view that people are basically
+ reasonable and will do the right thing if told what it is with some
+ stronger mechanisms when that model is not successful) into a single
+ whole.
+
+ RFC 1591 was written in the context of the assumption that what it
+ described as generic TLDs would be bound to policies and categories
+ of registration (see the "This domain is intended..." text in
+ section 2) while ccTLDs were expected to be used primarily to support
+ users and uses within and for a country and its residents. The
+ notion that different domains would be run in different ways --albeit
+ within the broad contexts of "public service on behalf of the
+ Internet community" and "trustee... for the global Internet
+ community"-- was considered a design feature and a safeguard against
+ a variety of potential abuses. Obviously the world has changed in
+ many ways in the seven or eight years since 1591 was written. In
+ particular, the Internet has become more heavily used and, because
+ the design of the world wide web has put domain names in front of
+ users, top-level domain names and registrations in them have been
+ heavily in demand: not only has the number of hosts increased
+ dramatically during that time, but the ratio between registered
+ domain names and physical hosts has increased very significantly.
+
+ The issues 1591 attempted to address when it was written and those we
+ face today have not changed significantly in principle. But one
+ alternative to present trends would be to take a step back to refine
+ it into a model that can function effectively today. Therefore, it
+ may be useful to try to reconstruct 1591's principles and think about
+ their applicability today as a model that could continue to be
+ applied: not because it is historically significant, but because many
+ of its elements have proven to work reasonably well, even in
+ difficult situations. In particular, for many domains (some in
+ 1591's "generic" list and others in its "country code" category) the
+ notion of "public service" --expected then to imply being carried out
+
+
+
+Klensin Informational [Page 2]
+
+RFC 3071 Reflections on the DNS and RFC 1591 February 2001
+
+
+ at no or minimal cost to the users, not merely on a non-profit
+ basis-- has yielded to profitability calculations. And, in most of
+ the rest, considerations of at least calculating and recovering costs
+ have crept in. While many of us feel some nostalgia for the old
+ system, it is clear that its days are waning if not gone: perhaps the
+ public service notions as understood when 1591 was written just don't
+ scale to rapid internet growth and very large numbers of
+ yregistrations.
+
+ In particular, some ccTLDs have advertised for registrations outside
+ the designated countries (or other entities), while others have made
+ clear decisions to allow registrations by non-nationals. These
+ decisions and others have produced protests from many sides,
+ suggesting, in turn, that a recategorization is in order. For
+ example, we have heard concerns by governments and managers of
+ traditional, "public service", in-country, ccTLDs about excessive
+ ICANN interference and fears of being forced to conform to
+ internationally-set policies for dispute resolution when their
+ domestic ones are considered more appropriate. We have also heard
+ concerns from registrars and operators of externally-marketed ccTLDs
+ about unreasonable government interference and from gTLD registrars
+ and registries about unreasonable competition from aggressively
+ marketed ccTLDs. The appropriate distinction is no longer between
+ what RFC 1591 described as "generic" TLDs (but which were really
+ intended to be "purpose-specific", a term I will use again below) and
+ ccTLDs but among:
+
+ (i) true "generic" TLDs, in which any registration is acceptable
+ and, ordinarily, registrations from all sources are actively
+ promoted. This list currently includes (the formerly purpose-
+ specific) COM, NET, and ORG, and some ccTLDs. There have been
+ proposals from time to time for additional TLDs of this variety in
+ which, as with COM (and, more recently, NET and ORG) anyone
+ (generally subject only to name conflicts and national law) could
+ register who could pay the fees.
+
+ (ii) purpose-specific TLDs, in which registration is accepted only
+ from organizations or individuals meeting particular
+ qualifications, but where those qualifications are not tied to
+ national boundaries. This list currently includes INT, EDU, the
+ infrastructure domain ARPA, and, arguably, the specialized US
+ Government TLDs MIL and GOV. There have been proposals from time
+ to time for other international TLDs of this variety, e.g., for
+ medical entities such as physicians and hospitals and for museums.
+ ICANN has recently approved several TLDs of this type and
+ describes them as "sponsored" TLDs.
+
+
+
+
+
+Klensin Informational [Page 3]
+
+RFC 3071 Reflections on the DNS and RFC 1591 February 2001
+
+
+ (iii) Country domains, operated according to the original
+ underlying assumptions of 1591, i.e., registrants are largely
+ expected to be people or other entities within the country. While
+ external registrations might be accepted by some of these, the
+ country does not aggressively advertise for such registrations,
+ nor does anyone expect to derive significant fee revenue from
+ them. All current domains in this category are ccTLDs, but not
+ all ccTLDs are in this category.
+
+ These categories are clearly orthogonal to the association between
+ the use of the IS 3166-1 registered code list [2] and two-letter
+ "country" domain names. If that relationship is to be maintained
+ (and I believe it is desirable), the only inherent requirement is
+ that no two-letter TLDs be created except from that list (in order to
+ avoid future conflicts). ICANN should control the allocation and
+ delegation of TLDs using these, and other, criteria, but only
+ registered 3166-1 two letter codes should be used as two-letter TLDs.
+
+2. Implications of the Categories
+
+ If we had adopted this type of three-way categorization and could
+ make it work, I believe it would have presented several opportunities
+ for ICANN and the community more generally to reduce controversies
+ and move forward. Of course, there will be cases where the
+ categorization of a particular domain and its operating style will
+ not be completely clear-cut (see section 3, below). But having ICANN
+ work out procedures for dealing with those (probably few) situations
+ appears preferable to strategies that would tend to propel ICANN into
+ areas that are beyond its competence or that might require
+ significant expansion of its mandate.
+
+ First, the internally-operated ccTLDs (category iii above) should not
+ be required to have much interaction with ICANN or vice versa. Once
+ a domain of this sort is established and delegated, and assuming that
+ the "admin contact in the country" rule is strictly observed, the
+ domain should be able to function effectively without ICANN
+ intervention or oversight. In particular, while a country might
+ choose to adopt the general ICANN policies about dispute resolution
+ or name management, issues that arise in these areas might equally
+ well be dealt with exclusively under applicable national laws. If a
+ domain chooses to use ICANN services that cost resources to provide,
+ it should contribute to ICANN's support, but, if it does not, ICANN
+ should not presume to charge it for other than a reasonable fraction
+ of the costs to ICANN of operating the root, root servers, and any
+ directory systems that are generally agreed upon to be necessary and
+ in which the domain participates.
+
+
+
+
+
+Klensin Informational [Page 4]
+
+RFC 3071 Reflections on the DNS and RFC 1591 February 2001
+
+
+ By contrast, ccTLDs operated as generic domains ought to be treated
+ as generic domains. ICANN dispute resolution and name management
+ policies and any special rules developed to protect the Internet
+ public in multiple registrar or registry situations should reasonably
+ apply.
+
+3. Telling TLD types apart
+
+ If appropriate policies are adopted, ccTLDs operated as generic
+ domains (category (i) above) and those operated as country domains
+ (category (iii) above) ought to be able to be self-identified. There
+ are several criteria that could be applied to make this
+ determination. For example, either a domain is aggressively seeking
+ outside registrations or it is not and either the vast majority of
+ registrants in a domain are in-country or they are not. One could
+ also think of this as the issue of having some tangible level of
+ presence in the jurisdiction - e.g., is the administrative contact
+ subject, in practical terms, to the in-country laws, or are the
+ registration rules such that it is reasonably likely that a court in
+ the jurisdiction of the country associated with the domain can
+ exercise jurisdiction and enforce a judgment against the registrant.
+
+ One (fairly non-intrusive) rule ICANN might well impose on all top-
+ level domains is that they identify and publish the policies they
+ intend to use. E.g., registrants in a domain that will use the laws
+ of one particular country to resolve disputes should have a
+ reasonable opportunity to understand those policies prior to
+ registration and to make other arrangements (e.g., to register
+ elsewhere) if that mechanism for dispute resolution is not
+ acceptable. Giving IANA (as the root registrar) incorrect
+ information about the purpose and use of a domain should be subject
+ to challenge, and should be grounds for reviewing the appropriateness
+ of the domain delegation, just as not acting consistently and
+ equitably provides such grounds under the original provisions of RFC
+ 1591.
+
+ In order to ensure the availability of accurate and up-to-date
+ registration information the criteria must be consistent, and
+ consistent with more traditional gTLDs, for all nominally country
+ code domains operating as generic TLDs.
+
+4. The role of ICANN in country domains
+
+ ICANN (and IANA) should, as described above, have as little
+ involvement as possible in the direction of true country [code]
+ domains (i.e., category (iii)). There is no particular reason why
+
+
+
+
+
+Klensin Informational [Page 5]
+
+RFC 3071 Reflections on the DNS and RFC 1591 February 2001
+
+
+ these domains should be subject to ICANN regulation beyond the basic
+ principles of 1591 and associated arrangements needed to ensure
+ Internet interoperability and stability.
+
+ ICANN's avoiding such involvement strengthens it: the desirability of
+ avoiding collisions with national sovereignty, determinations about
+ government legitimacy, and the authority of someone purportedly
+ writing on behalf of a government, is as important today as it was
+ when 1591 was written. The alternatives take us quickly from
+ "administration" into "internet governance" or, in the case of
+ determining which claimant is the legitimate government of a country,
+ "international relations", and the reasons for not moving in that
+ particular direction are legion.
+
+5. The role of governments
+
+ The history of IANA strategy in handling ccTLDs included three major
+ "things to avoid" considerations:
+
+ * Never get involved in determining which entities were countries
+ and which ones were not.
+
+ * Never get involved in determining who was, or was not, the
+ legitimate government of a country. And, more generally, avoid
+ deciding what entity --government, religion, commercial,
+ academic, etc.-- has what legitimacy or rights.
+
+ * If possible, never become involved in in-country disputes.
+ Instead, very strongly encourage internal parties to work
+ problems out among themselves. At most, adopt a role as
+ mediator and educator, rather than judge, unless abuses are very
+ clear and clearly will not be settled by any internal mechanism.
+
+ All three considerations were obviously intended to avoid IANA's
+ being dragged into a political morass in which it had (and, I
+ suggest, has) no competence to resolve the issues and could only get
+ bogged down. The first consideration was the most visible (and the
+ easiest) and was implemented by strict and careful adherence (see
+ below) to the ISO 3166 registered Country Code list. If an entity
+ had a code, it was eligible to be registered with a TLD (although
+ IANA was free to apply additional criteria-most of them stated in
+ 1591). If it did not, there were no exceptions: the applicant's only
+ recourse was a discussion with the 3166 Registration Authority (now
+ Maintenance Agency, often known just as "3166/MA") or the UN
+ Statistical Office (now Statistics Bureau), not with IANA.
+
+
+
+
+
+
+Klensin Informational [Page 6]
+
+RFC 3071 Reflections on the DNS and RFC 1591 February 2001
+
+
+ There are actually five ccTLD exceptions to the strict rules. One,
+ "UK", is historical: it predates the adoption of ISO 3166 for this
+ purpose. The others --Ascension Island, Guernsey, Isle of Man, and
+ Jersey --are arguably, at least in retrospect, just mistakes.
+ Regardless of the historical reasons (about which there has been much
+ speculation), it is almost certainly the case that the right way to
+ handle mistakes of this sort is to acknowledge them and move on,
+ rather than trying to use them as precedents to justify more
+ mistakes.
+
+ This, obviously, is also the argument against use of the "reserved"
+ list (technically internal to the 3166 maintenance activity, and not
+ part of the Standard): since IANA (or ICANN) can ask that a name be
+ placed on that list, there is no rule of an absolute determination by
+ an external organization. Purported countries can come to ICANN,
+ insist on having delegations made and persuade ICANN to ask that the
+ names be reserved. Then, since the reserved name would exist, they
+ could insist that the domain be delegated. Worse, someone could use
+ another organization to request reservation of the name by 3166/MA;
+ once it was reserved, ICANN might be hard-pressed not to do the
+ delegation. Of course, ICANN could (and probably would be forced to)
+ adopt additional criteria other than appearance on the "reserved
+ list" in order to delegate such domains. But those criteria would
+ almost certainly be nearly equivalent to determining which applicants
+ were legitimate and stable enough to be considered a country, the
+ exact decision process that 1591 strove to avoid.
+
+ The other two considerations were more subtle and not always
+ successful: from time to time, both before and after the formal
+ policy shifted toward "governments could have their way", IANA
+ received letters from people purporting to be competent government
+ authorities asking for changes. Some of them turned out later to not
+ have that authority or appropriate qualifications. The assumption of
+ 1591 itself was that, if the "administrative contact in country" rule
+ was strictly observed, as was the rule that delegation changes
+ requested by the administrative contact would be honored, then, if a
+ government _really_ wanted to assert itself, it could pressure the
+ administrative contact into requesting the changes it wanted, using
+ whatever would pass for due process in that country. And the ability
+ to apply that process and pressure would effectively determine who
+ was the government and who wasn't, and would do so far more
+ effectively than any IANA evaluation of, e.g., whether the letterhead
+ on a request looked authentic (and far more safely for ICANN than
+ asking the opinion of any particular other government or selection of
+ governments).
+
+
+
+
+
+
+Klensin Informational [Page 7]
+
+RFC 3071 Reflections on the DNS and RFC 1591 February 2001
+
+
+ Specific language in 1591 permitted IANA to adopt a "work it out
+ yourselves; if we have to decide, we will strive for a solution that
+ is not satisfactory to any party" stance. That approach was used
+ successfully, along with large doses of education, on many occasions
+ over the years, to avoid IANA's having to assume the role of judge
+ between conflicting parties.
+
+ Similar principles could be applied to the boundary between country-
+ code-based generic TLDs and country domains. Different countries,
+ under different circumstances, might prefer to operate the ccTLD
+ either as a national service or as a profit center where the
+ "customers" were largely external. Whatever decisions were made
+ historically, general Internet stability argues that changes should
+ not be made lightly. At the same time, if a government wishes to
+ make a change, the best mechanism for doing so is not to involve
+ ICANN in a potential determination of legitimacy (or even to have
+ ICANN's Government Advisory Committee (GAC) try to formally make that
+ decision for individual countries) but for the relevant government to
+ use its own procedures to persuade the administrative contact to
+ request the change and for IANA to promptly and efficiently carry out
+ requests made by administrative contacts.
+
+6. Implications for the current ICANN DNSO structure.
+
+ The arguments by some of the ccTLD administrators that they are
+ different from the rest of the ICANN and DNSO structures are (in this
+ model) correct: they are different. The ccTLDs that are operating as
+ generic TLDs should be separated from the ccTLD constituency and
+ joined to the gTLD constituency. The country ccTLDs should be
+ separated from ICANN's immediate Supporting Organization structure,
+ and operate in a parallel and advisory capacity to ICANN, similar to
+ the arrangements used with the GAC. The DNSO and country TLDs should
+ not be required to interact with each other except on a mutually
+ voluntary basis and, if ICANN needs interaction or advice from some
+ of all of those TLDs, it would be more appropriate to get it in the
+ form of an advisory body like the GAC rather than as DNSO
+ constituency.
+
+7. References
+
+ [1] Postel, J., "Domain Name System Structure and Delegation", RFC
+ 1591, March 1994.
+
+ [2] ISO 3166. ISO 3166-1. Codes for the representation of names of
+ countries and their subdivisions - Part 1: Country codes (1997).
+
+
+
+
+
+
+Klensin Informational [Page 8]
+
+RFC 3071 Reflections on the DNS and RFC 1591 February 2001
+
+
+8. Acknowledgements and disclaimer
+
+ These reflections have been prepared in my individual capacity and do
+ not necessarily reflect the views of my past or present employers.
+ Several people, including Randy Bush, Theresa Swinehart, Zita Wenzel,
+ Geoff Huston, Havard Eidnes, and several anonymous reviewers, made
+ suggestions or offered editorial comments about earlier versions of
+ this document. Cord Wischhoefer, of the ISO 3166/MA, was also kind
+ enough to look at the draft and supplied some useful details. Those
+ comments contributed significantly to whatever clarity the document
+ has, but the author bears responsibility for the selection of
+ comments which were ultimately incorporated and the way in which the
+ conclusions were presented.
+
+9. Security Considerations
+
+ This memo addresses the context for a set of administrative decisions
+ and procedures, and does not raise or address security issues.
+
+10. Author's Address
+
+ John C. Klensin
+ 1770 Massachusetts Ave, Suite 322
+ Cambridge, MA 02140, USA
+
+ EMail: klensin@jck.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Klensin Informational [Page 9]
+
+RFC 3071 Reflections on the DNS and RFC 1591 February 2001
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society 2001. All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others provided that the above copyright notice and this paragraph
+ are included on all such copies. However, this document itself may
+ not be modified in any way, such as by removing the copyright notice
+ or references to the Internet Society or other Internet
+ organizations, except as required to translate it into languages
+ other than English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Klensin Informational [Page 10]
+
diff --git a/doc/rfc/rfc3090.txt b/doc/rfc/rfc3090.txt
new file mode 100644
index 0000000..08008f7
--- /dev/null
+++ b/doc/rfc/rfc3090.txt
@@ -0,0 +1,619 @@
+
+
+
+
+
+
+Network Working Group E. Lewis
+Request for Comments: 3090 NAI Labs
+Category: Standards Track March 2001
+
+
+ DNS Security Extension Clarification on Zone Status
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ The definition of a secured zone is presented, clarifying and
+ updating sections of RFC 2535. RFC 2535 defines a zone to be secured
+ based on a per algorithm basis, e.g., a zone can be secured with RSA
+ keys, and not secured with DSA keys. This document changes this to
+ define a zone to be secured or not secured regardless of the key
+ algorithm used (or not used). To further simplify the determination
+ of a zone's status, "experimentally secure" status is deprecated.
+
+1 Introduction
+
+ Whether a DNS zone is "secured" or not is a question asked in at
+ least four contexts. A zone administrator asks the question when
+ configuring a zone to use DNSSEC. A dynamic update server asks the
+ question when an update request arrives, which may require DNSSEC
+ processing. A delegating zone asks the question of a child zone when
+ the parent enters data indicating the status the child. A resolver
+ asks the question upon receipt of data belonging to the zone.
+
+1.1 When a Zone's Status is Important
+
+ A zone administrator needs to be able to determine what steps are
+ needed to make the zone as secure as it can be. Realizing that due
+ to the distributed nature of DNS and its administration, any single
+ zone is at the mercy of other zones when it comes to the appearance
+ of security. This document will define what makes a zone qualify as
+ secure.
+
+
+
+
+Lewis Standards Track [Page 1]
+
+RFC 3090 DNS Security Extension on Zone Status March 2001
+
+
+ A name server performing dynamic updates needs to know whether a zone
+ being updated is to have signatures added to the updated data, NXT
+ records applied, and other required processing. In this case, it is
+ conceivable that the name server is configured with the knowledge,
+ but being able to determine the status of a zone by examining the
+ data is a desirable alternative to configuration parameters.
+
+ A delegating zone is required to indicate whether a child zone is
+ secured. The reason for this requirement lies in the way in which a
+ resolver makes its own determination about a zone (next paragraph).
+ To shorten a long story, a parent needs to know whether a child
+ should be considered secured. This is a two part question. Under
+ what circumstances does a parent consider a child zone to be secure,
+ and how does a parent know if the child conforms?
+
+ A resolver needs to know if a zone is secured when the resolver is
+ processing data from the zone. Ultimately, a resolver needs to know
+ whether or not to expect a usable signature covering the data. How
+ this determination is done is out of the scope of this document,
+ except that, in some cases, the resolver will need to contact the
+ parent of the zone to see if the parent states that the child is
+ secured.
+
+1.2 Islands of Security
+
+ The goal of DNSSEC is to have each zone secured, from the root zone
+ and the top-level domains down the hierarchy to the leaf zones.
+ Transitioning from an unsecured DNS, as we have now, to a fully
+ secured - or "as much as will be secured" - tree will take some time.
+ During this time, DNSSEC will be applied in various locations in the
+ tree, not necessarily "top down."
+
+ For example, at a particular instant, the root zone and the "test."
+ TLD might be secured, but region1.test. might not be. (For
+ reference, let's assume that region2.test. is secured.) However,
+ subarea1.region1.test. may have gone through the process of becoming
+ secured, along with its delegations. The dilemma here is that
+ subarea1 cannot get its zone keys properly signed as its parent zone,
+ region1, is not secured.
+
+ The colloquial phrase describing the collection of contiguous secured
+ zones at or below subarea1.region1.test. is an "island of security."
+ The only way in which a DNSSEC resolver will come to trust any data
+ from this island is if the resolver is pre-configured with the zone
+ key(s) for subarea1.region1.test., i.e., the root of the island of
+ security. Other resolvers (not so configured) will recognize this
+ island as unsecured.
+
+
+
+
+Lewis Standards Track [Page 2]
+
+RFC 3090 DNS Security Extension on Zone Status March 2001
+
+
+ An island of security begins with one zone whose public key is pre-
+ configured in resolvers. Within this island are subzones which are
+ also secured. The "bottom" of the island is defined by delegations
+ to unsecured zones. One island may also be on top of another -
+ meaning that there is at least one unsecured zone between the bottom
+ of the upper island and the root of the lower secured island.
+
+ Although both subarea1.region1.test. and region2.test. have both been
+ properly brought to a secured state by the administering staff, only
+ the latter of the two is actually "globally" secured - in the sense
+ that all DNSSEC resolvers can and will verify its data. The former,
+ subarea1, will be seen as secured by a subset of those resolvers,
+ just those appropriately configured. This document refers to such
+ zones as being "locally" secured.
+
+ In RFC 2535, there is a provision for "certification authorities,"
+ entities that will sign public keys for zones such as subarea1.
+ There is another document, [RFC3008], that restricts this activity.
+ Regardless of the other document, resolvers would still need proper
+ configuration to be able to use the certification authority to verify
+ the data for the subarea1 island.
+
+1.2.1 Determining the closest security root
+
+ Given a domain, in order to determine whether it is secure or not,
+ the first step is to determine the closest security root. The
+ closest security root is the top of an island of security whose name
+ has the most matching (in order from the root) right-most labels to
+ the given domain.
+
+ For example, given a name "sub.domain.testing.signed.exp.test.", and
+ given the secure roots "exp.test.", "testing.signed.exp.test." and
+ "not-the-same.xy.", the middle one is the closest. The first secure
+ root shares 2 labels, the middle 4, and the last 0.
+
+ The reason why the closest is desired is to eliminate false senses of
+ insecurity because of a NULL key. Continuing with the example, the
+ reason both "testing..." and "exp.test." are listed as secure root is
+ presumably because "signed.exp.test." is unsecured (has a NULL key).
+ If we started to descend from "exp.test." to our given domain
+ (sub...), we would encounter a NULL key and conclude that sub... was
+ unsigned. However, if we descend from "testing..." and find keys
+ "domain...." then we can conclude that "sub..." is secured.
+
+ Note that this example assumes one-label deep zones, and assumes that
+ we do not configure overlapping islands of security. To be clear,
+ the definition given should exclude "short.xy.test." from being a
+ closest security root for "short.xy." even though 2 labels match.
+
+
+
+Lewis Standards Track [Page 3]
+
+RFC 3090 DNS Security Extension on Zone Status March 2001
+
+
+ Overlapping islands of security introduce no conceptually interesting
+ ideas and do not impact the protocol in anyway. However, protocol
+ implementers are advised to make sure their code is not thrown for a
+ loop by overlaps. Overlaps are sure to be configuration problems as
+ islands of security grow to encompass larger regions of the name
+ space.
+
+1.3 Parent Statement of Child Security
+
+ In 1.1 of this document, there is the comment "the parent states that
+ the child is secured." This has caused quite a bit of confusion.
+
+ The need to have the parent "state" the status of a child is derived
+ from the following observation. If you are looking to see if an
+ answer is secured, that it comes from an "island of security" and is
+ properly signed, you must begin at the (appropriate) root of the
+ island of security.
+
+ To find the answer you are inspecting, you may have to descend
+ through zones within the island of security. Beginning with the
+ trusted root of the island, you descend into the next zone down. As
+ you trust the upper zone, you need to get data from it about the next
+ zone down, otherwise there is a vulnerable point in which a zone can
+ be hijacked. When or if you reach a point of traversing from a
+ secured zone to an unsecured zone, you have left the island of
+ security and should conclude that the answer is unsecured.
+
+ However, in RFC 2535, section 2.3.4, these words seem to conflict
+ with the need to have the parent "state" something about a child:
+
+ There MUST be a zone KEY RR, signed by its superzone, for every
+ subzone if the superzone is secure. This will normally appear in
+ the subzone and may also be included in the superzone. But, in
+ the case of an unsecured subzone which can not or will not be
+ modified to add any security RRs, a KEY declaring the subzone to
+ be unsecured MUST appear with the superzone signature in the
+ superzone, if the superzone is secure.
+
+ The confusion here is that in RFC 2535, a secured parent states that
+ a child is secured by SAYING NOTHING ("may also be" as opposed to
+ "MUST also be"). This is counter intuitive, the fact that an absence
+ of data means something is "secured." This notion, while acceptable
+ in a theoretic setting has met with some discomfort in an operation
+ setting. However, the use of "silence" to state something does
+ indeed work in this case, so there hasn't been sufficient need
+ demonstrated to change the definition.
+
+
+
+
+
+Lewis Standards Track [Page 4]
+
+RFC 3090 DNS Security Extension on Zone Status March 2001
+
+
+1.4 Impact on RFC 2535
+
+ This document updates sections of RFC 2535. The definition of a
+ secured zone is an update to section 3.4 of the RFC. Section 3.4 is
+ updated to eliminate the definition of experimental keys and
+ illustrate a way to still achieve the functionality they were
+ designed to provide. Section 3.1.3 is updated by the specifying the
+ value of the protocol octet in a zone key.
+
+1.5 "MUST" and other key words
+
+ The key words "MUST", "REQUIRED", "SHOULD", "RECOMMENDED", and "MAY"
+ in this document are to be interpreted as described in [RFC 2119].
+ Currently, only "MUST" is used in this document.
+
+2 Status of a Zone
+
+ In this section, rules governing a zone's DNSSEC status are
+ presented. There are three levels of security defined: global,
+ local, and unsecured. A zone is globally secure when it complies
+ with the strictest set of DNSSEC processing rules. A zone is locally
+ secured when it is configured in such a way that only resolvers that
+ are appropriately configured see the zone as secured. All other
+ zones are unsecured.
+
+ Note: there currently is no document completely defining DNSSEC
+ verification rules. For the purposes of this document, the strictest
+ rules are assumed to state that the verification chain of zone keys
+ parallels the delegation tree up to the root zone. (See 2.b below.)
+ This is not intended to disallow alternate verification paths, just
+ to establish a baseline definition.
+
+ To avoid repetition in the rules below, the following terms are
+ defined.
+
+ 2.a Zone signing KEY RR - A KEY RR whose flag field has the value 01
+ for name type (indicating a zone key) and either value 00 or value 01
+ for key type (indicating a key permitted to authenticate data). (See
+ RFC 2535, section 3.1.2). The KEY RR also has a protocol octet value
+ of DNSSEC (3) or ALL (255).
+
+ The definition updates RFC 2535's definition of a zone key. The
+ requirement that the protocol field be either DNSSEC or ALL is a new
+ requirement (a change to section 3.1.3.)
+
+ 2.b On-tree Validation - The authorization model in which only the
+ parent zone is recognized to supply a DNSSEC-meaningful signature
+ that is used by a resolver to build a chain of trust from the child's
+
+
+
+Lewis Standards Track [Page 5]
+
+RFC 3090 DNS Security Extension on Zone Status March 2001
+
+
+ keys to a recognized root of security. The term "on-tree" refers to
+ following the DNS domain hierarchy (upwards) to reach a trusted key,
+ presumably the root key if no other key is available. The term
+ "validation" refers to the digital signature by the parent to prove
+ the integrity, authentication and authorization of the child's key to
+ sign the child's zone data.
+
+ 2.c Off-tree Validation - Any authorization model that permits domain
+ names other than the parent's to provide a signature over a child's
+ zone keys that will enable a resolver to trust the keys.
+
+2.1 Globally Secured
+
+ A globally secured zone, in a nutshell, is a zone that uses only
+ mandatory to implement algorithms (RFC 2535, section 3.2) and relies
+ on a key certification chain that parallels the delegation tree (on-
+ tree validation). Globally secured zones are defined by the
+ following rules.
+
+ 2.1.a. The zone's apex MUST have a KEY RR set. There MUST be at
+ least one zone signing KEY RR (2.a) of a mandatory to implement
+ algorithm in the set.
+
+ 2.1.b. The zone's apex KEY RR set MUST be signed by a private key
+ belonging to the parent zone. The private key's public companion
+ MUST be a zone signing KEY RR (2.a) of a mandatory to implement
+ algorithm and owned by the parent's apex.
+
+ If a zone cannot get a conforming signature from the parent zone, the
+ child zone cannot be considered globally secured. The only exception
+ to this is the root zone, for which there is no parent zone.
+
+ 2.1.c. NXT records MUST be deployed throughout the zone. (Clarifies
+ RFC 2535, section 2.3.2.) Note: there is some operational discomfort
+ with the current NXT record. This requirement is open to
+ modification when two things happen. First, an alternate mechanism
+ to the NXT is defined and second, a means by which a zone can
+ indicate that it is using an alternate method.
+
+ 2.1.d. Each RR set that qualifies for zone membership MUST be signed
+ by a key that is in the apex's KEY RR set and is a zone signing KEY
+ RR (2.a) of a mandatory to implement algorithm. (Updates 2535,
+ section 2.3.1.)
+
+ Mentioned earlier, the root zone is a special case. The root zone
+ will be considered to be globally secured provided that if conforms
+ to the rules for locally secured, with the exception that rule 2.1.a.
+ be also met (mandatory to implement requirement).
+
+
+
+Lewis Standards Track [Page 6]
+
+RFC 3090 DNS Security Extension on Zone Status March 2001
+
+
+2.2 Locally Secured
+
+ The term "locally" stems from the likely hood that the only resolvers
+ to be configured for a particular zone will be resolvers "local" to
+ an organization.
+
+ A locally secured zone is a zone that complies with rules like those
+ for a globally secured zone with the following exceptions. The
+ signing keys may be of an algorithm that is not mandatory to
+ implement and/or the verification of the zone keys in use may rely on
+ a verification chain that is not parallel to the delegation tree
+ (off-tree validation).
+
+ 2.2.a. The zone's apex MUST have a KEY RR set. There MUST be at
+ least one zone signing KEY RR (2.a) in the set.
+
+ 2.2.b. The zone's apex KEY RR set MUST be signed by a private key and
+ one of the following two subclauses MUST hold true.
+
+ 2.2.b.1 The private key's public companion MUST be pre-configured in
+ all the resolvers of interest.
+
+ 2.2.b.2 The private key's public companion MUST be a zone signing KEY
+ RR (2.a) authorized to provide validation of the zone's apex KEY RR
+ set, as recognized by resolvers of interest.
+
+ The previous sentence is trying to convey the notion of using a
+ trusted third party to provide validation of keys. If the domain
+ name owning the validating key is not the parent zone, the domain
+ name must represent someone the resolver trusts to provide
+ validation.
+
+ 2.2.c. NXT records MUST be deployed throughout the zone. Note: see
+ the discussion following 2.1.c.
+
+ 2.2.d. Each RR set that qualifies for zone membership MUST be signed
+ by a key that is in the apex's KEY RR set and is a zone signing KEY
+ RR (2.a). (Updates 2535, section 2.3.1.)
+
+2.3 Unsecured
+
+ All other zones qualify as unsecured. This includes zones that are
+ designed to be experimentally secure, as defined in a later section
+ on that topic.
+
+
+
+
+
+
+
+Lewis Standards Track [Page 7]
+
+RFC 3090 DNS Security Extension on Zone Status March 2001
+
+
+2.4 Wrap up
+
+ The designation of globally secured, locally secured, and unsecured
+ are merely labels to apply to zones, based on their contents.
+ Resolvers, when determining whether a signature is expected or not,
+ will only see a zone as secured or unsecured.
+
+ Resolvers that follow the most restrictive DNSSEC verification rules
+ will only see globally secured zones as secured, and all others as
+ unsecured, including zones which are locally secured. Resolvers that
+ are not as restrictive, such as those that implement algorithms in
+ addition to the mandatory to implement algorithms, will see some
+ locally secured zones as secured.
+
+ The intent of the labels "global" and "local" is to identify the
+ specific attributes of a zone. The words are chosen to assist in the
+ writing of a document recommending the actions a zone administrator
+ take in making use of the DNS security extensions. The words are
+ explicitly not intended to convey a state of compliance with DNS
+ security standards.
+
+3 Experimental Status
+
+ The purpose of an experimentally secured zone is to facilitate the
+ migration from an unsecured zone to a secured zone. This distinction
+ is dropped.
+
+ The objective of facilitating the migration can be achieved without a
+ special designation of an experimentally secure status.
+ Experimentally secured is a special case of locally secured. A zone
+ administrator can achieve this by publishing a zone with signatures
+ and configuring a set of test resolvers with the corresponding public
+ keys. Even if the public key is published in a KEY RR, as long as
+ there is no parent signature, the resolvers will need some pre-
+ configuration to know to process the signatures. This allows a zone
+ to be secured with in the sphere of the experiment, yet still be
+ registered as unsecured in the general Internet.
+
+4 IANA Considerations
+
+ This document does not request any action from an assigned number
+ authority nor recommends any actions.
+
+
+
+
+
+
+
+
+
+Lewis Standards Track [Page 8]
+
+RFC 3090 DNS Security Extension on Zone Status March 2001
+
+
+5 Security Considerations
+
+ Without a means to enforce compliance with specified protocols or
+ recommended actions, declaring a DNS zone to be "completely" secured
+ is impossible. Even if, assuming an omnipotent view of DNS, one can
+ declare a zone to be properly configured for security, and all of the
+ zones up to the root too, a misbehaving resolver could be duped into
+ believing bad data. If a zone and resolver comply, a non-compliant
+ or subverted parent could interrupt operations. The best that can be
+ hoped for is that all parties are prepared to be judged secure and
+ that security incidents can be traced to the cause in short order.
+
+6 Acknowledgements
+
+ The need to refine the definition of a secured zone has become
+ apparent through the efforts of the participants at two DNSSEC
+ workshops, sponsored by the NIC-SE (.se registrar), CAIRN (a DARPA-
+ funded research network), and other workshops. Further discussions
+ leading to the document include Olafur Gudmundsson, Russ Mundy,
+ Robert Watson, and Brian Wellington. Roy Arends, Ted Lindgreen and
+ others have contributed significant input via the namedroppers
+ mailing list.
+
+7 References
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2136] Vixie, P., (Ed.), Thomson, S., Rekhter, Y. and J. Bound,
+ "Dynamic Updates in the Domain Name System", RFC 2136,
+ April 1997.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [RFC3007] Wellington, B., "Simple Secure Domain Name System (DNS)
+ Dynamic Update", RFC 3007, November 2000.
+
+ [RFC3008] Wellington, B., "Domain Name System Security (DNSSEC)
+ Signing Authority", RFC 3008, November 2000.
+
+
+
+
+
+Lewis Standards Track [Page 9]
+
+RFC 3090 DNS Security Extension on Zone Status March 2001
+
+
+10 Author's Address
+
+ Edward Lewis
+ NAI Labs
+ 3060 Washington Road Glenwood
+ MD 21738
+
+ Phone: +1 443 259 2352
+ EMail: lewis@tislabs.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lewis Standards Track [Page 10]
+
+RFC 3090 DNS Security Extension on Zone Status March 2001
+
+
+11 Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lewis Standards Track [Page 11]
+
diff --git a/doc/rfc/rfc3110.txt b/doc/rfc/rfc3110.txt
new file mode 100644
index 0000000..7646948
--- /dev/null
+++ b/doc/rfc/rfc3110.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake 3rd
+Request for Comments: 3110 Motorola
+Obsoletes: 2537 May 2001
+Category: Standards Track
+
+
+ RSA/SHA-1 SIGs and RSA KEYs in the Domain Name System (DNS)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ This document describes how to produce RSA/SHA1 SIG resource records
+ (RRs) in Section 3 and, so as to completely replace RFC 2537,
+ describes how to produce RSA KEY RRs in Section 2.
+
+ Since the adoption of a Proposed Standard for RSA signatures in the
+ DNS (Domain Name Space), advances in hashing have been made. A new
+ DNS signature algorithm is defined to make these advances available
+ in SIG RRs. The use of the previously specified weaker mechanism is
+ deprecated. The algorithm number of the RSA KEY RR is changed to
+ correspond to this new SIG algorithm. No other changes are made to
+ DNS security.
+
+Acknowledgements
+
+ Material and comments from the following have been incorporated and
+ are gratefully acknowledged:
+
+ Olafur Gudmundsson
+
+ The IESG
+
+ Charlie Kaufman
+
+ Steve Wang
+
+
+
+
+
+D. Eastlake 3rd Standards Track [Page 1]
+
+RFC 3110 RSA SIGs and KEYs in the DNS May 2001
+
+
+Table of Contents
+
+ 1. Introduction................................................... 2
+ 2. RSA Public KEY Resource Records................................ 3
+ 3. RSA/SHA1 SIG Resource Records.................................. 3
+ 4. Performance Considerations..................................... 4
+ 5. IANA Considerations............................................ 5
+ 6. Security Considerations........................................ 5
+ References........................................................ 5
+ Author's Address.................................................. 6
+ Full Copyright Statement.......................................... 7
+
+1. Introduction
+
+ The Domain Name System (DNS) is the global hierarchical replicated
+ distributed database system for Internet addressing, mail proxy, and
+ other information [RFC1034, 1035, etc.]. The DNS has been extended
+ to include digital signatures and cryptographic keys as described in
+ [RFC2535]. Thus the DNS can now be secured and used for secure key
+ distribution.
+
+ Familiarity with the RSA and SHA-1 algorithms is assumed [Schneier,
+ FIP180] in this document.
+
+ RFC 2537 described how to store RSA keys and RSA/MD5 based signatures
+ in the DNS. However, since the adoption of RFC 2537, continued
+ cryptographic research has revealed hints of weakness in the MD5
+ [RFC1321] algorithm used in RFC 2537. The SHA1 Secure Hash Algorithm
+ [FIP180], which produces a larger hash, has been developed. By now
+ there has been sufficient experience with SHA1 that it is generally
+ acknowledged to be stronger than MD5. While this stronger hash is
+ probably not needed today in most secure DNS zones, critical zones
+ such a root, most top level domains, and some second and third level
+ domains, are sufficiently valuable targets that it would be negligent
+ not to provide what are generally agreed to be stronger mechanisms.
+ Furthermore, future advances in cryptanalysis and/or computer speeds
+ may require a stronger hash everywhere. In addition, the additional
+ computation required by SHA1 above that required by MD5 is
+ insignificant compared with the computational effort required by the
+ RSA modular exponentiation.
+
+ This document describes how to produce RSA/SHA1 SIG RRs in Section 3
+ and, so as to completely replace RFC 2537, describes how to produce
+ RSA KEY RRs in Section 2.
+
+ Implementation of the RSA algorithm in DNS with SHA1 is MANDATORY for
+ DNSSEC. The generation of RSA/MD5 SIG RRs as described in RFC 2537
+ is NOT RECOMMENDED.
+
+
+
+D. Eastlake 3rd Standards Track [Page 2]
+
+RFC 3110 RSA SIGs and KEYs in the DNS May 2001
+
+
+ The key words "MUST", "REQUIRED", "SHOULD", "RECOMMENDED", "NOT
+ RECOMMENDED", and "MAY" in this document are to be interpreted as
+ described in RFC 2119.
+
+2. RSA Public KEY Resource Records
+
+ RSA public keys are stored in the DNS as KEY RRs using algorithm
+ number 5 [RFC2535]. The structure of the algorithm specific portion
+ of the RDATA part of such RRs is as shown below.
+
+ Field Size
+ ----- ----
+ exponent length 1 or 3 octets (see text)
+ exponent as specified by length field
+ modulus remaining space
+
+ For interoperability, the exponent and modulus are each limited to
+ 4096 bits in length. The public key exponent is a variable length
+ unsigned integer. Its length in octets is represented as one octet
+ if it is in the range of 1 to 255 and by a zero octet followed by a
+ two octet unsigned length if it is longer than 255 bytes. The public
+ key modulus field is a multiprecision unsigned integer. The length
+ of the modulus can be determined from the RDLENGTH and the preceding
+ RDATA fields including the exponent. Leading zero octets are
+ prohibited in the exponent and modulus.
+
+ Note: KEY RRs for use with RSA/SHA1 DNS signatures MUST use this
+ algorithm number (rather than the algorithm number specified in the
+ obsoleted RFC 2537).
+
+ Note: This changes the algorithm number for RSA KEY RRs to be the
+ same as the new algorithm number for RSA/SHA1 SIGs.
+
+3. RSA/SHA1 SIG Resource Records
+
+ RSA/SHA1 signatures are stored in the DNS using SIG resource records
+ (RRs) with algorithm number 5.
+
+ The signature portion of the SIG RR RDATA area, when using the
+ RSA/SHA1 algorithm, is calculated as shown below. The data signed is
+ determined as specified in RFC 2535. See RFC 2535 for fields in the
+ SIG RR RDATA which precede the signature itself.
+
+ hash = SHA1 ( data )
+
+ signature = ( 01 | FF* | 00 | prefix | hash ) ** e (mod n)
+
+
+
+
+
+D. Eastlake 3rd Standards Track [Page 3]
+
+RFC 3110 RSA SIGs and KEYs in the DNS May 2001
+
+
+ where SHA1 is the message digest algorithm documented in [FIP180],
+ "|" is concatenation, "e" is the private key exponent of the signer,
+ and "n" is the modulus of the signer's public key. 01, FF, and 00
+ are fixed octets of the corresponding hexadecimal value. "prefix" is
+ the ASN.1 BER SHA1 algorithm designator prefix required in PKCS1
+ [RFC2437], that is,
+
+ hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14
+
+ This prefix is included to make it easier to use standard
+ cryptographic libraries. The FF octet MUST be repeated the maximum
+ number of times such that the value of the quantity being
+ exponentiated is one octet shorter than the value of n.
+
+ (The above specifications are identical to the corresponding parts of
+ Public Key Cryptographic Standard #1 [RFC2437].)
+
+ The size of "n", including most and least significant bits (which
+ will be 1) MUST be not less than 512 bits and not more than 4096
+ bits. "n" and "e" SHOULD be chosen such that the public exponent is
+ small. These are protocol limits. For a discussion of key size see
+ RFC 2541.
+
+ Leading zero bytes are permitted in the RSA/SHA1 algorithm signature.
+
+4. Performance Considerations
+
+ General signature generation speeds are roughly the same for RSA and
+ DSA [RFC2536]. With sufficient pre-computation, signature generation
+ with DSA is faster than RSA. Key generation is also faster for DSA.
+ However, signature verification is an order of magnitude slower with
+ DSA when the RSA public exponent is chosen to be small as is
+ recommended for KEY RRs used in domain name system (DNS) data
+ authentication.
+
+ A public exponent of 3 minimizes the effort needed to verify a
+ signature. Use of 3 as the public exponent is weak for
+ confidentiality uses since, if the same data can be collected
+ encrypted under three different keys with an exponent of 3 then,
+ using the Chinese Remainder Theorem [NETSEC], the original plain text
+ can be easily recovered. If a key is known to be used only for
+ authentication, as is the case with DNSSEC, then an exponent of 3 is
+ acceptable. However other applications in the future may wish to
+ leverage DNS distributed keys for applications that do require
+ confidentiality. For keys which might have such other uses, a more
+ conservative choice would be 65537 (F4, the fourth fermat number).
+
+
+
+
+
+D. Eastlake 3rd Standards Track [Page 4]
+
+RFC 3110 RSA SIGs and KEYs in the DNS May 2001
+
+
+ Current DNS implementations are optimized for small transfers,
+ typically less than 512 bytes including DNS overhead. Larger
+ transfers will perform correctly and extensions have been
+ standardized [RFC2671] to make larger transfers more efficient, it is
+ still advisable at this time to make reasonable efforts to minimize
+ the size of KEY RR sets stored within the DNS consistent with
+ adequate security. Keep in mind that in a secure zone, at least one
+ authenticating SIG RR will also be returned.
+
+5. IANA Considerations
+
+ The DNSSEC algorithm number 5 is allocated for RSA/SHA1 SIG RRs and
+ RSA KEY RRs.
+
+6. Security Considerations
+
+ Many of the general security considerations in RFC 2535 apply. Keys
+ retrieved from the DNS should not be trusted unless (1) they have
+ been securely obtained from a secure resolver or independently
+ verified by the user and (2) this secure resolver and secure
+ obtainment or independent verification conform to security policies
+ acceptable to the user. As with all cryptographic algorithms,
+ evaluating the necessary strength of the key is essential and
+ dependent on local policy. For particularly critical applications,
+ implementers are encouraged to consider the range of available
+ algorithms and key sizes. See also RFC 2541, "DNS Security
+ Operational Considerations".
+
+References
+
+ [FIP180] U.S. Department of Commerce, "Secure Hash Standard", FIPS
+ PUB 180-1, 17 Apr 1995.
+
+ [NETSEC] Network Security: PRIVATE Communications in a PUBLIC
+ World, Charlie Kaufman, Radia Perlman, & Mike Speciner,
+ Prentice Hall Series in Computer Networking and
+ Distributed Communications, 1995.
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321,
+ April 1992.
+
+
+
+
+
+D. Eastlake 3rd Standards Track [Page 5]
+
+RFC 3110 RSA SIGs and KEYs in the DNS May 2001
+
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2437] Kaliski, B. and J. Staddon, "PKCS #1: RSA Cryptography
+ Specifications Version 2.0", RFC 2437, October 1998.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC2536] Eastlake, D., "DSA KEYs and SIGs in the Domain Name System
+ (DNS)", RFC 2536, March 1999.
+
+ [RFC2537] Eastlake, D., "RSA/MD5 KEYs and SIGs in the Domain Name
+ System (DNS)", RFC 2537, March 1999.
+
+ [RFC2541] Eastlake, D., "DNS Security Operational Considerations",
+ RFC 2541, March 1999.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [Schneier] Bruce Schneier, "Applied Cryptography Second Edition:
+ protocols, algorithms, and source code in C", 1996, John
+ Wiley and Sons, ISBN 0-471-11709-9.
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ Motorola
+ 155 Beaver Street
+ Milford, MA 01757 USA
+
+ Phone: +1-508-261-5434 (w)
+ +1-508-634-2066 (h)
+ Fax +1-508-261-4777 (w)
+ EMail: Donald.Eastlake@motorola.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd Standards Track [Page 6]
+
+RFC 3110 RSA SIGs and KEYs in the DNS May 2001
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+D. Eastlake 3rd Standards Track [Page 7]
+
diff --git a/doc/rfc/rfc3123.txt b/doc/rfc/rfc3123.txt
new file mode 100644
index 0000000..3b2fe00
--- /dev/null
+++ b/doc/rfc/rfc3123.txt
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+Network Working Group P. Koch
+Request for Comments: 3123 Universitaet Bielefeld
+Category: Experimental June 2001
+
+
+ A DNS RR Type for Lists of Address Prefixes (APL RR)
+
+Status of this Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. It does not specify an Internet standard of any kind.
+ Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ The Domain Name System (DNS) is primarily used to translate domain
+ names into IPv4 addresses using A RRs (Resource Records). Several
+ approaches exist to describe networks or address ranges. This
+ document specifies a new DNS RR type "APL" for address prefix lists.
+
+1. Conventions used in this document
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+ Domain names herein are for explanatory purposes only and should not
+ be expected to lead to useful information in real life [RFC2606].
+
+2. Background
+
+ The Domain Name System [RFC1034], [RFC1035] provides a mechanism to
+ associate addresses and other Internet infrastructure elements with
+ hierarchically built domain names. Various types of resource records
+ have been defined, especially those for IPv4 and IPv6 [RFC2874]
+ addresses. In [RFC1101] a method is described to publish information
+ about the address space allocated to an organisation. In older BIND
+ versions, a weak form of controlling access to zone data was
+ implemented using TXT RRs describing address ranges.
+
+ This document specifies a new RR type for address prefix lists.
+
+
+
+
+
+Koch Experimental [Page 1]
+
+RFC 3123 DNS APL RR June 2001
+
+
+3. APL RR Type
+
+ An APL record has the DNS type of "APL" and a numeric value of 42
+ [IANA]. The APL RR is defined in the IN class only. APL RRs cause
+ no additional section processing.
+
+4. APL RDATA format
+
+ The RDATA section consists of zero or more items (<apitem>) of the
+ form
+
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ | ADDRESSFAMILY |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ | PREFIX | N | AFDLENGTH |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ / AFDPART /
+ | |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+
+ ADDRESSFAMILY 16 bit unsigned value as assigned by IANA
+ (see IANA Considerations)
+ PREFIX 8 bit unsigned binary coded prefix length.
+ Upper and lower bounds and interpretation of
+ this value are address family specific.
+ N negation flag, indicates the presence of the
+ "!" character in the textual format. It has
+ the value "1" if the "!" was given, "0" else.
+ AFDLENGTH length in octets of the following address
+ family dependent part (7 bit unsigned).
+ AFDPART address family dependent part. See below.
+
+ This document defines the AFDPARTs for address families 1 (IPv4) and
+ 2 (IPv6). Future revisions may deal with additional address
+ families.
+
+4.1. AFDPART for IPv4
+
+ The encoding of an IPv4 address (address family 1) follows the
+ encoding specified for the A RR by [RFC1035], section 3.4.1.
+
+ PREFIX specifies the number of bits of the IPv4 address starting at
+ the most significant bit. Legal values range from 0 to 32.
+
+ Trailing zero octets do not bear any information (e.g., there is no
+ semantic difference between 10.0.0.0/16 and 10/16) in an address
+ prefix, so the shortest possible AFDLENGTH can be used to encode it.
+ However, for DNSSEC [RFC2535] a single wire encoding must be used by
+
+
+
+Koch Experimental [Page 2]
+
+RFC 3123 DNS APL RR June 2001
+
+
+ all. Therefore the sender MUST NOT include trailing zero octets in
+ the AFDPART regardless of the value of PREFIX. This includes cases
+ in which AFDLENGTH times 8 results in a value less than PREFIX. The
+ AFDPART is padded with zero bits to match a full octet boundary.
+
+ An IPv4 AFDPART has a variable length of 0 to 4 octets.
+
+4.2. AFDPART for IPv6
+
+ The 128 bit IPv6 address (address family 2) is encoded in network
+ byte order (high-order byte first).
+
+ PREFIX specifies the number of bits of the IPv6 address starting at
+ the most significant bit. Legal values range from 0 to 128.
+
+ With the same reasoning as in 4.1 above, the sender MUST NOT include
+ trailing zero octets in the AFDPART regardless of the value of
+ PREFIX. This includes cases in which AFDLENGTH times 8 results in a
+ value less than PREFIX. The AFDPART is padded with zero bits to
+ match a full octet boundary.
+
+ An IPv6 AFDPART has a variable length of 0 to 16 octets.
+
+5. Zone File Syntax
+
+ The textual representation of an APL RR in a DNS zone file is as
+ follows:
+
+ <owner> IN <TTL> APL {[!]afi:address/prefix}*
+
+ The data consists of zero or more strings of the address family
+ indicator <afi>, immediately followed by a colon ":", an address,
+ immediately followed by the "/" character, immediately followed by a
+ decimal numeric value for the prefix length. Any such string may be
+ preceded by a "!" character. The strings are separated by
+ whitespace. The <afi> is the decimal numeric value of that
+ particular address family.
+
+5.1. Textual Representation of IPv4 Addresses
+
+ An IPv4 address in the <address> part of an <apitem> is in dotted
+ quad notation, just as in an A RR. The <prefix> has values from the
+ interval 0..32 (decimal).
+
+
+
+
+
+
+
+
+Koch Experimental [Page 3]
+
+RFC 3123 DNS APL RR June 2001
+
+
+5.2. Textual Representation of IPv6 Addresses
+
+ The representation of an IPv6 address in the <address> part of an
+ <apitem> follows [RFC2373], section 2.2. Legal values for <prefix>
+ are from the interval 0..128 (decimal).
+
+6. APL RR usage
+
+ An APL RR with empty RDATA is valid and implements an empty list.
+ Multiple occurrences of the same <apitem> in a single APL RR are
+ allowed and MUST NOT be merged by a DNS server or resolver.
+ <apitems> MUST be kept in order and MUST NOT be rearranged or
+ aggregated.
+
+ A single APL RR may contain <apitems> belonging to different address
+ families. The maximum number of <apitems> is upper bounded by the
+ available RDATA space.
+
+ RRSets consisting of more than one APL RR are legal but the
+ interpretation is left to the particular application.
+
+7. Applicability Statement
+
+ The APL RR defines a framework without specifying any particular
+ meaning for the list of prefixes. It is expected that APL RRs will
+ be used in different application scenarios which have to be
+ documented separately. Those scenarios may be distinguished by
+ characteristic prefixes placed in front of the DNS owner name.
+
+ An APL application specification MUST include information on
+
+ o the characteristic prefix, if any
+
+ o how to interpret APL RRSets consisting of more than one RR
+
+ o how to interpret an empty APL RR
+
+ o which address families are expected to appear in the APL RRs for
+ that application
+
+ o how to deal with APL RR list elements which belong to other
+ address families, including those not yet defined
+
+ o the exact semantics of list elements negated by the "!" character
+
+
+
+
+
+
+
+Koch Experimental [Page 4]
+
+RFC 3123 DNS APL RR June 2001
+
+
+ Possible applications include the publication of address ranges
+ similar to [RFC1101], description of zones built following [RFC2317]
+ and in-band access control to limit general access or zone transfer
+ (AXFR) availability for zone data held in DNS servers.
+
+ The specification of particular application scenarios is out of the
+ scope of this document.
+
+8. Examples
+
+ The following examples only illustrate some of the possible usages
+ outlined in the previous section. None of those applications are
+ hereby specified nor is it implied that any particular APL RR based
+ application does exist now or will exist in the future.
+
+ ; RFC 1101-like announcement of address ranges for foo.example
+ foo.example. IN APL 1:192.168.32.0/21 !1:192.168.38.0/28
+
+ ; CIDR blocks covered by classless delegation
+ 42.168.192.IN-ADDR.ARPA. IN APL ( 1:192.168.42.0/26 1:192.168.42.64/26
+ 1:192.168.42.128/25 )
+
+ ; Zone transfer restriction
+ _axfr.sbo.example. IN APL 1:127.0.0.1/32 1:172.16.64.0/22
+
+ ; List of address ranges for multicast
+ multicast.example. IN APL 1:224.0.0.0/4 2:FF00:0:0:0:0:0:0:0/8
+
+ Note that since trailing zeroes are ignored in the first APL RR the
+ AFDLENGTH of both <apitems> is three.
+
+9. Security Considerations
+
+ Any information obtained from the DNS should be regarded as unsafe
+ unless techniques specified in [RFC2535] or [RFC2845] were used. The
+ definition of a new RR type does not introduce security problems into
+ the DNS, but usage of information made available by APL RRs may
+ compromise security. This includes disclosure of network topology
+ information and in particular the use of APL RRs to construct access
+ control lists.
+
+
+
+
+
+
+
+
+
+
+
+Koch Experimental [Page 5]
+
+RFC 3123 DNS APL RR June 2001
+
+
+10. IANA Considerations
+
+ This section is to be interpreted as following [RFC2434].
+
+ This document does not define any new namespaces. It uses the 16 bit
+ identifiers for address families maintained by IANA in
+ http://www.iana.org/numbers.html.
+
+ The IANA assigned numeric RR type value 42 for APL [IANA].
+
+11. Acknowledgements
+
+ The author would like to thank Mark Andrews, Olafur Gudmundsson, Ed
+ Lewis, Thomas Narten, Erik Nordmark, and Paul Vixie for their review
+ and constructive comments.
+
+12. References
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC1101] Mockapetris, P., "DNS Encoding of Network Names and Other
+ Types", RFC 1101, April 1989.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC2317] Eidnes, H., de Groot, G. and P. Vixie, "Classless IN-
+ ADDR.ARPA delegation", BCP 20, RFC 2317, March 1998.
+
+ [RFC2373] Hinden, R. and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 2373, July 1998.
+
+ [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for Writing an
+ IANA Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [RFC2606] Eastlake, D. and A. Panitz, "Reserved Top Level DNS Names",
+ BCP 32, RFC 2606, June 1999.
+
+
+
+Koch Experimental [Page 6]
+
+RFC 3123 DNS APL RR June 2001
+
+
+ [RFC2845] Vixie, P., Gudmundsson, O., Eastlake, D. and B. Wellington,
+ "Secret Key Transaction Authentication for DNS (TSIG)", RFC
+ 2845, May 2000.
+
+ [RFC2874] Crawford, M. and C. Huitema, "DNS Extensions to Support
+ IPv6 Address Aggregation and Renumbering", RFC 2874, July
+ 2000.
+
+ [IANA] http://www.iana.org/assignments/dns-parameters
+
+13. Author's Address
+
+ Peter Koch
+ Universitaet Bielefeld
+ Technische Fakultaet
+ D-33594 Bielefeld
+ Germany
+
+ Phone: +49 521 106 2902
+ EMail: pk@TechFak.Uni-Bielefeld.DE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Koch Experimental [Page 7]
+
+RFC 3123 DNS APL RR June 2001
+
+
+14. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Koch Experimental [Page 8]
+
diff --git a/doc/rfc/rfc3152.txt b/doc/rfc/rfc3152.txt
new file mode 100644
index 0000000..b226ce6
--- /dev/null
+++ b/doc/rfc/rfc3152.txt
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+Network Working Group R. Bush
+Request for Comments: 3152 RGnet
+BCP: 49 August 2001
+Updates: 2874, 2772, 2766, 2553, 1886
+Category: Best Current Practice
+
+
+ Delegation of IP6.ARPA
+
+Status of this Memo
+
+ This document specifies an Internet Best Current Practices for the
+ Internet Community, and requests discussion and suggestions for
+ improvements. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ This document discusses the need for delegation of the IP6.ARPA DNS
+ zone, and specifies a plan for the technical operation thereof.
+
+1. Why IP6.ARPA?
+
+ In the IPv6 address space, there is a need for 'reverse mapping' of
+ addresses to DNS names analogous to that provided by the IN-ADDR.ARPA
+ zone for IPv4.
+
+ The IAB recommended that the ARPA top level domain (the name is now
+ considered an acronym for "Address and Routing Parameters Area") be
+ used for technical infrastructure sub-domains when possible. It is
+ already in use for IPv4 reverse mapping and has been established as
+ the location for E.164 numbering on the Internet [RFC2916 RFC3026].
+
+ IETF consensus was reached that the IP6.ARPA domain be used for
+ address to DNS name mapping for the IPv6 address space [RFC2874].
+
+2. Obsoleted Usage
+
+ This document deprecates references to IP6.INT in [RFC1886] section
+ 2.5, [RFC2553] section 6.2.3, [RFC2766] section 4.1, [RFC2772]
+ section 7.1.c, and [RFC2874] section 2.5.
+
+ In this context, 'deprecate' means that the old usage is not
+ appropriate for new implementations, and IP6.INT will likely be
+ phased out in an orderly fashion.
+
+
+
+Bush Best Current Practice [Page 1]
+
+RFC 3152 Delegation of IP6.ARPA August 2001
+
+
+3. IANA Considerations
+
+ This memo requests that the IANA delegate the IP6.ARPA domain
+ following instructions to be provided by the IAB. Names within this
+ zone are to be further delegated to the regional IP registries in
+ accordance with the delegation of IPv6 address space to those
+ registries. The names allocated should be hierarchic in accordance
+ with the address space assignment.
+
+4. Security Considerations
+
+ While DNS spoofing of address to name mapping has been exploited in
+ IPv4, delegation of the IP6.ARPA zone creates no new threats to the
+ security of the internet.
+
+5. References
+
+ [RFC1886] Thomson, S. and C. Huitema, "DNS Extensions to support IP
+ version 6", RFC 1886, December 1995.
+
+ [RFC2553] Gilligan, R., Thomson, S., Bound, J. and W. Stevens,
+ "Basic Socket Interface Extensions for IPv6", RFC 2553,
+ March 1999.
+
+ [RFC2766] Tsirtsis, G. and P. Srisuresh, "Network Address
+ Translation - Protocol Translation (NAT-PT)", RFC 2766,
+ February 2000.
+
+ [RFC2772] Rockell, R. and R. Fink, "6Bone Backbone Routing
+ Guidelines", RFC 2772, February 2000.
+
+ [RFC2874] Crawford, M. and C. Huitema, "DNS Extensions to Support
+ IPv6 Address Aggregation and Renumbering", RFC 2874, July
+ 2001.
+
+ [RFC2916] Faltstrom, P., "E.164 number and DNS", RFC 2916,
+ September 2000.
+
+ [RFC3026] Blane, R., "Liaison to IETF/ISOC on ENUM", RFC 3026,
+ January 2001.
+
+
+
+
+
+
+
+
+
+
+
+Bush Best Current Practice [Page 2]
+
+RFC 3152 Delegation of IP6.ARPA August 2001
+
+
+6. Author's Address
+
+ Randy Bush
+ 5147 Crystal Springs
+ Bainbridge Island, WA US-98110
+
+ Phone: +1 206 780 0431
+ EMail: randy@psg.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bush Best Current Practice [Page 3]
+
+RFC 3152 Delegation of IP6.ARPA August 2001
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bush Best Current Practice [Page 4]
+
diff --git a/doc/rfc/rfc3197.txt b/doc/rfc/rfc3197.txt
new file mode 100644
index 0000000..94cefa4
--- /dev/null
+++ b/doc/rfc/rfc3197.txt
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+Network Working Group R. Austein
+Request for Comments: 3197 InterNetShare
+Category: Informational November 2001
+
+
+ Applicability Statement for DNS MIB Extensions
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ This document explains why, after more than six years as proposed
+ standards, the DNS Server and Resolver MIB extensions were never
+ deployed, and recommends retiring these MIB extensions by moving them
+ to Historical status.
+
+1. History
+
+ The road to the DNS MIB extensions was paved with good intentions.
+
+ In retrospect, it's obvious that the working group never had much
+ agreement on what belonged in the MIB extensions, just that we should
+ have some. This happened during the height of the craze for MIB
+ extensions in virtually every protocol that the IETF was working on
+ at the time, so the question of why we were doing this in the first
+ place never got a lot of scrutiny. Very late in the development
+ cycle we discovered that much of the support for writing the MIB
+ extensions in the first place had come from people who wanted to use
+ SNMP SET operations to update DNS zones on the fly. Examination of
+ the security model involved, however, led us to conclude that this
+ was not a good way to do dynamic update and that a separate DNS
+ Dynamic Update protocol would be necessary.
+
+ The MIB extensions started out being fairly specific to one
+ particular DNS implementation (BIND-4.8.3); as work progressed, the
+ BIND-specific portions were rewritten to be as implementation-neutral
+ as we knew how to make them, but somehow every revision of the MIB
+ extensions managed to create new counters that just happened to
+ closely match statistics kept by some version of BIND. As a result,
+ the MIB extensions ended up being much too big, which raised a number
+
+
+
+Austein Informational [Page 1]
+
+RFC 3197 Applicability Statement - DNS MIB Extensions November 2001
+
+
+ of concerns with the network management directorate, but the WG
+ resisted every attempt to remove any of these variables. In the end,
+ large portions of the MIB extensions were moved into optional groups
+ in an attempt to get the required subset down to a manageable size.
+
+ The DNS Server and Resolver MIB extensions were one of the first
+ attempts to write MIB extensions for a protocol usually considered to
+ be at the application layer. Fairly early on it became clear that,
+ while it was certainly possible to write MIB extensions for DNS, the
+ SMI was not really designed with this sort of thing in mind. A case
+ in point was the attempt to provide direct indexing into the caches
+ in the resolver MIB extensions: while arguably the only sane way to
+ do this for a large cache, this required much more complex indexing
+ clauses than is usual, and ended up running into known length limits
+ for object identifiers in some SNMP implementations.
+
+ Furthermore, the lack of either real proxy MIB support in SNMP
+ managers or a standard subagent protocol meant that there was no
+ reasonable way to implement the MIB extensions in the dominant
+ implementation (BIND). When the AgentX subagent protocol was
+ developed a few years later, we initially hoped that this would
+ finally clear the way for an implementation of the DNS MIB
+ extensions, but by the time AgentX was a viable protocol it had
+ become clear that nobody really wanted to implement these MIB
+ extensions.
+
+ Finally, the MIB extensions took much too long to produce. In
+ retrospect, this should have been a clear warning sign, particularly
+ when the WG had clearly become so tired of the project that the
+ authors found it impossible to elicit any comments whatsoever on the
+ documents.
+
+2. Lessons
+
+ Observations based on the preceding list of mistakes, for the benefit
+ of anyone else who ever attempts to write DNS MIB extensions again:
+
+ - Define a clear set of goals before writing any MIB extensions.
+ Know who the constituency is and make sure that what you write
+ solves their problem.
+
+ - Keep the MIB extensions short, and don't add variables just
+ because somebody in the WG thinks they'd be a cool thing to
+ measure.
+
+ - If some portion of the task seems to be very hard to do within the
+ SMI, that's a strong hint that SNMP is not the right tool for
+ whatever it is that you're trying to do.
+
+
+
+Austein Informational [Page 2]
+
+RFC 3197 Applicability Statement - DNS MIB Extensions November 2001
+
+
+ - If the entire project is taking too long, perhaps that's a hint
+ too.
+
+3. Recommendation
+
+ In view of the community's apparent total lack of interest in
+ deploying these MIB extensions, we recommend that RFCs 1611 and 1612
+ be reclassified as Historical documents.
+
+4. Security Considerations
+
+ Re-classifying an existing MIB document from Proposed Standard to
+ Historic should not have any negative impact on security for the
+ Internet.
+
+5. IANA Considerations
+
+ Getting rid of the DNS MIB extensions should not impose any new work
+ on IANA.
+
+6. Acknowledgments
+
+ The author would like to thank all the people who were involved in
+ this project over the years for their optimism and patience,
+ misguided though it may have been.
+
+7. References
+
+ [DNS-SERVER-MIB] Austein, R. and J. Saperia, "DNS Server MIB
+ Extensions", RFC 1611, May 1994.
+
+ [DNS-RESOLVER-MIB] Austein, R. and J. Saperia, "DNS Resolver MIB
+ Extensions", RFC 1612, May 1994.
+
+ [DNS-DYNAMIC-UPDATE] Vixie, P., Thomson, S., Rekhter, Y. and J.
+ Bound, "Dynamic Updates in the Domain Name
+ System (DNS UPDATE)", RFC 2136, April 1997.
+
+ [AGENTX] Daniele, M., Wijnen, B., Ellison, M., and D.
+ Francisco, "Agent Extensibility (AgentX)
+ Protocol Version 1", RFC 2741, January 2000.
+
+
+
+
+
+
+
+
+
+
+Austein Informational [Page 3]
+
+RFC 3197 Applicability Statement - DNS MIB Extensions November 2001
+
+
+8. Author's Address
+
+ Rob Austein
+ InterNetShare, Incorporated
+ 325M Sharon Park Drive, Suite 308
+ Menlo Park, CA 94025
+ USA
+
+ EMail: sra@hactrn.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Informational [Page 4]
+
+RFC 3197 Applicability Statement - DNS MIB Extensions November 2001
+
+
+9. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Informational [Page 5]
+
diff --git a/doc/rfc/rfc3225.txt b/doc/rfc/rfc3225.txt
new file mode 100644
index 0000000..13e6768
--- /dev/null
+++ b/doc/rfc/rfc3225.txt
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+Network Working Group D. Conrad
+Request for Comments: 3225 Nominum, Inc.
+Category: Standards Track December 2001
+
+
+ Indicating Resolver Support of DNSSEC
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ In order to deploy DNSSEC (Domain Name System Security Extensions)
+ operationally, DNSSEC aware servers should only perform automatic
+ inclusion of DNSSEC RRs when there is an explicit indication that the
+ resolver can understand those RRs. This document proposes the use of
+ a bit in the EDNS0 header to provide that explicit indication and
+ describes the necessary protocol changes to implement that
+ notification.
+
+1. Introduction
+
+ DNSSEC [RFC2535] has been specified to provide data integrity and
+ authentication to security aware resolvers and applications through
+ the use of cryptographic digital signatures. However, as DNSSEC is
+ deployed, non-DNSSEC-aware clients will likely query DNSSEC-aware
+ servers. In such situations, the DNSSEC-aware server (responding to
+ a request for data in a signed zone) will respond with SIG, KEY,
+ and/or NXT records. For reasons described in the subsequent section,
+ such responses can have significant negative operational impacts for
+ the DNS infrastructure.
+
+ This document discusses a method to avoid these negative impacts,
+ namely DNSSEC-aware servers should only respond with SIG, KEY, and/or
+ NXT RRs when there is an explicit indication from the resolver that
+ it can understand those RRs.
+
+ For the purposes of this document, "DNSSEC security RRs" are
+ considered RRs of type SIG, KEY, or NXT.
+
+
+
+Conrad Standards Track [Page 1]
+
+RFC 3225 Indicating Resolver Support of DNSSEC December 2001
+
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+2. Rationale
+
+ Initially, as DNSSEC is deployed, the vast majority of queries will
+ be from resolvers that are not DNSSEC aware and thus do not
+ understand or support the DNSSEC security RRs. When a query from
+ such a resolver is received for a DNSSEC signed zone, the DNSSEC
+ specification indicates the nameserver must respond with the
+ appropriate DNSSEC security RRs. As DNS UDP datagrams are limited to
+ 512 bytes [RFC1035], responses including DNSSEC security RRs have a
+ high probability of resulting in a truncated response being returned
+ and the resolver retrying the query using TCP.
+
+ TCP DNS queries result in significant overhead due to connection
+ setup and teardown. Operationally, the impact of these TCP queries
+ will likely be quite detrimental in terms of increased network
+ traffic (typically five packets for a single query/response instead
+ of two), increased latency resulting from the additional round trip
+ times, increased incidences of queries failing due to timeouts, and
+ significantly increased load on nameservers.
+
+ In addition, in preliminary and experimental deployment of DNSSEC,
+ there have been reports of non-DNSSEC aware resolvers being unable to
+ handle responses which contain DNSSEC security RRs, resulting in the
+ resolver failing (in the worst case) or entire responses being
+ ignored (in the better case).
+
+ Given these operational implications, explicitly notifying the
+ nameserver that the client is prepared to receive (if not understand)
+ DNSSEC security RRs would be prudent.
+
+ Client-side support of DNSSEC is assumed to be binary -- either the
+ client is willing to receive all DNSSEC security RRs or it is not
+ willing to accept any. As such, a single bit is sufficient to
+ indicate client-side DNSSEC support. As effective use of DNSSEC
+ implies the need of EDNS0 [RFC2671], bits in the "classic" (non-EDNS
+ enhanced DNS header) are scarce, and there may be situations in which
+ non-compliant caching or forwarding servers inappropriately copy data
+ from classic headers as queries are passed on to authoritative
+ servers, the use of a bit from the EDNS0 header is proposed.
+
+ An alternative approach would be to use the existence of an EDNS0
+ header as an implicit indication of client-side support of DNSSEC.
+ This approach was not chosen as there may be applications in which
+ EDNS0 is supported but in which the use of DNSSEC is inappropriate.
+
+
+
+Conrad Standards Track [Page 2]
+
+RFC 3225 Indicating Resolver Support of DNSSEC December 2001
+
+
+3. Protocol Changes
+
+ The mechanism chosen for the explicit notification of the ability of
+ the client to accept (if not understand) DNSSEC security RRs is using
+ the most significant bit of the Z field on the EDNS0 OPT header in
+ the query. This bit is referred to as the "DNSSEC OK" (DO) bit. In
+ the context of the EDNS0 OPT meta-RR, the DO bit is the first bit of
+ the third and fourth bytes of the "extended RCODE and flags" portion
+ of the EDNS0 OPT meta-RR, structured as follows:
+
+ +0 (MSB) +1 (LSB)
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 0: | EXTENDED-RCODE | VERSION |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 2: |DO| Z |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+ Setting the DO bit to one in a query indicates to the server that the
+ resolver is able to accept DNSSEC security RRs. The DO bit cleared
+ (set to zero) indicates the resolver is unprepared to handle DNSSEC
+ security RRs and those RRs MUST NOT be returned in the response
+ (unless DNSSEC security RRs are explicitly queried for). The DO bit
+ of the query MUST be copied in the response.
+
+ More explicitly, DNSSEC-aware nameservers MUST NOT insert SIG, KEY,
+ or NXT RRs to authenticate a response as specified in [RFC2535]
+ unless the DO bit was set on the request. Security records that
+ match an explicit SIG, KEY, NXT, or ANY query, or are part of the
+ zone data for an AXFR or IXFR query, are included whether or not the
+ DO bit was set.
+
+ A recursive DNSSEC-aware server MUST set the DO bit on recursive
+ requests, regardless of the status of the DO bit on the initiating
+ resolver request. If the initiating resolver request does not have
+ the DO bit set, the recursive DNSSEC-aware server MUST remove DNSSEC
+ security RRs before returning the data to the client, however cached
+ data MUST NOT be modified.
+
+ In the event a server returns a NOTIMP, FORMERR or SERVFAIL response
+ to a query that has the DO bit set, the resolver SHOULD NOT expect
+ DNSSEC security RRs and SHOULD retry the query without EDNS0 in
+ accordance with section 5.3 of [RFC2671].
+
+
+
+
+
+
+
+
+
+Conrad Standards Track [Page 3]
+
+RFC 3225 Indicating Resolver Support of DNSSEC December 2001
+
+
+Security Considerations
+
+ The absence of DNSSEC data in response to a query with the DO bit set
+ MUST NOT be taken to mean no security information is available for
+ that zone as the response may be forged or a non-forged response of
+ an altered (DO bit cleared) query.
+
+IANA Considerations
+
+ EDNS0 [RFC2671] defines 16 bits as extended flags in the OPT record,
+ these bits are encoded into the TTL field of the OPT record (RFC2671
+ section 4.6).
+
+ This document reserves one of these bits as the OK bit. It is
+ requested that the left most bit be allocated. Thus the USE of the
+ OPT record TTL field would look like
+
+ +0 (MSB) +1 (LSB)
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 0: | EXTENDED-RCODE | VERSION |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ 2: |DO| Z |
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
+Acknowledgements
+
+ This document is based on a rough draft by Bob Halley with input from
+ Olafur Gudmundsson, Andreas Gustafsson, Brian Wellington, Randy Bush,
+ Rob Austein, Steve Bellovin, and Erik Nordmark.
+
+References
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specifications", STD 13, RFC 1035, November 1987.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+
+
+
+
+Conrad Standards Track [Page 4]
+
+RFC 3225 Indicating Resolver Support of DNSSEC December 2001
+
+
+Author's Address
+
+ David Conrad
+ Nominum Inc.
+ 950 Charter Street
+ Redwood City, CA 94063
+ USA
+
+ Phone: +1 650 381 6003
+ EMail: david.conrad@nominum.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Conrad Standards Track [Page 5]
+
+RFC 3225 Indicating Resolver Support of DNSSEC December 2001
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Conrad Standards Track [Page 6]
+
diff --git a/doc/rfc/rfc3226.txt b/doc/rfc/rfc3226.txt
new file mode 100644
index 0000000..dac0e11
--- /dev/null
+++ b/doc/rfc/rfc3226.txt
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+Network Working Group O. Gudmundsson
+Request for Comments: 3226 December 2001
+Updates: 2874, 2535
+Category: Standards Track
+
+
+ DNSSEC and IPv6 A6 aware server/resolver message size requirements
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+Abstract
+
+ This document mandates support for EDNS0 (Extension Mechanisms for
+ DNS) in DNS entities claiming to support either DNS Security
+ Extensions or A6 records. This requirement is necessary because
+ these new features increase the size of DNS messages. If EDNS0 is
+ not supported fall back to TCP will happen, having a detrimental
+ impact on query latency and DNS server load. This document updates
+ RFC 2535 and RFC 2874, by adding new requirements.
+
+1. Introduction
+
+ Familiarity with the DNS [RFC1034, RFC1035], DNS Security Extensions
+ [RFC2535], EDNS0 [RFC2671] and A6 [RFC2874] is helpful.
+
+ STD 13, RFC 1035 Section 2.3.4 requires that DNS messages over UDP
+ have a data payload of 512 octets or less. Most DNS software today
+ will not accept larger UDP datagrams. Any answer that requires more
+ than 512 octets, results in a partial and sometimes useless reply
+ with the Truncation Bit set; in most cases the requester will then
+ retry using TCP. Furthermore, server delivery of truncated responses
+ varies widely and resolver handling of these responses also varies,
+ leading to additional inefficiencies in handling truncation.
+
+ Compared to UDP, TCP is an expensive protocol to use for a simple
+ transaction like DNS: a TCP connection requires 5 packets for setup
+ and tear down, excluding data packets, thus requiring at least 3
+ round trips on top of the one for the original UDP query. The DNS
+
+
+
+Gudmundsson Standards Track [Page 1]
+
+RFC 3226 DNSSEC and IPv6 A6 requirements December 2001
+
+
+ server also needs to keep a state of the connection during this
+ transaction. Many DNS servers answer thousands of queries per
+ second, requiring them to use TCP will cause significant overhead and
+ delays.
+
+1.1. Requirements
+
+ The key words "MUST", "REQUIRED", "SHOULD", "RECOMMENDED", and "MAY"
+ in this document are to be interpreted as described in RFC 2119.
+
+2. Motivating factors
+
+2.1. DNSSEC motivations
+
+ DNSSEC [RFC2535] secures DNS by adding a Public Key signature on each
+ RR set. These signatures range in size from about 80 octets to 800
+ octets, most are going to be in the range of 80 to 200 octets. The
+ addition of signatures on each or most RR sets in an answer
+ significantly increases the size of DNS answers from secure zones.
+
+ For performance reasons and to reduce load on DNS servers, it is
+ important that security aware servers and resolvers get all the data
+ in Answer and Authority section in one query without truncation.
+ Sending Additional Data in the same query is helpful when the server
+ is authoritative for the data, and this reduces round trips.
+
+ DNSSEC OK[OK] specifies how a client can, using EDNS0, indicate that
+ it is interested in receiving DNSSEC records. The OK bit does not
+ eliminate the need for large answers for DNSSEC capable clients.
+
+2.1.1. Message authentication or TSIG motivation
+
+ TSIG [RFC2845] allows for the light weight authentication of DNS
+ messages, but increases the size of the messages by at least 70
+ octets. DNSSEC specifies for computationally expensive message
+ authentication SIG(0) using a standard public key signature. As only
+ one TSIG or SIG(0) can be attached to each DNS answer the size
+ increase of message authentication is not significant, but may still
+ lead to a truncation.
+
+2.2. IPv6 Motivations
+
+ IPv6 addresses [RFC2874] are 128 bits and can be represented in the
+ DNS by multiple A6 records, each consisting of a domain name and a
+ bit field. The domain name refers to an address prefix that may
+ require additional A6 RRs to be included in the answer. Answers
+ where the queried name has multiple A6 addresses may overflow a 512-
+ octet UDP packet size.
+
+
+
+Gudmundsson Standards Track [Page 2]
+
+RFC 3226 DNSSEC and IPv6 A6 requirements December 2001
+
+
+2.3. Root server and TLD server motivations
+
+ The current number of root servers is limited to 13 as that is the
+ maximum number of name servers and their address records that fit in
+ one 512-octet answer for a SOA record. If root servers start
+ advertising A6 or KEY records then the answer for the root NS records
+ will not fit in a single 512-octet DNS message, resulting in a large
+ number of TCP query connections to the root servers. Even if all
+ client resolver query their local name server for information, there
+ are millions of these servers. Each name server must periodically
+ update its information about the high level servers.
+
+ For redundancy, latency and load balancing reasons, large numbers of
+ DNS servers are required for some zones. Since the root zone is used
+ by the entire net, it is important to have as many servers as
+ possible. Large TLDs (and many high-visibility SLDs) often have
+ enough servers that either A6 or KEY records would cause the NS
+ response to overflow the 512 byte limit. Note that these zones with
+ large numbers of servers are often exactly those zones that are
+ critical to network operation and that already sustain fairly high
+ loads.
+
+2.4. UDP vs TCP for DNS messages
+
+ Given all these factors, it is essential that any implementation that
+ supports DNSSEC and or A6 be able to use larger DNS messages than 512
+ octets.
+
+ The original 512 restriction was put in place to reduce the
+ probability of fragmentation of DNS responses. A fragmented UDP
+ message that suffers a loss of one of the fragments renders the
+ answer useless and the query must be retried. A TCP connection
+ requires a larger number of round trips for establishment, data
+ transfer and tear down, but only the lost data segments are
+ retransmitted.
+
+ In the early days a number of IP implementations did not handle
+ fragmentation well, but all modern operating systems have overcome
+ that issue thus sending fragmented messages is fine from that
+ standpoint. The open issue is the effect of losses on fragmented
+ messages. If connection has high loss ratio only TCP will allow
+ reliable transfer of DNS data, most links have low loss ratios thus
+ sending fragmented UDP packet in one round trip is better than
+ establishing a TCP connection to transfer a few thousand octets.
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 3]
+
+RFC 3226 DNSSEC and IPv6 A6 requirements December 2001
+
+
+2.5. EDNS0 and large UDP messages
+
+ EDNS0 [RFC2671] allows clients to declare the maximum size of UDP
+ message they are willing to handle. Thus, if the expected answer is
+ between 512 octets and the maximum size that the client can accept,
+ the additional overhead of a TCP connection can be avoided.
+
+3. Protocol changes:
+
+ This document updates RFC 2535 and RFC 2874, by adding new
+ requirements.
+
+ All RFC 2535 compliant servers and resolvers MUST support EDNS0 and
+ advertise message size of at least 1220 octets, but SHOULD advertise
+ message size of 4000. This value might be too low to get full
+ answers for high level servers and successor of this document may
+ require a larger value.
+
+ All RFC 2874 compliant servers and resolver MUST support EDNS0 and
+ advertise message size of at least 1024 octets, but SHOULD advertise
+ message size of 2048. The IPv6 datagrams should be 1024 octets,
+ unless the MTU of the path is known. (Note that this is smaller than
+ the minimum IPv6 MTU to allow for some extension headers and/or
+ encapsulation without exceeding the minimum MTU.)
+
+ All RFC 2535 and RFC 2874 compliant entities MUST be able to handle
+ fragmented IPv4 and IPv6 UDP packets.
+
+ All hosts supporting both RFC 2535 and RFC 2874 MUST use the larger
+ required value in EDNS0 advertisements.
+
+4. Acknowledgments
+
+ Harald Alvestrand, Rob Austein, Randy Bush, David Conrad, Andreas
+ Gustafsson, Jun-ichiro itojun Hagino, Bob Halley, Edward Lewis
+ Michael Patton and Kazu Yamamoto were instrumental in motivating and
+ shaping this document.
+
+5. Security Considerations:
+
+ There are no additional security considerations other than those in
+ RFC 2671.
+
+6. IANA Considerations:
+
+ None
+
+
+
+
+
+Gudmundsson Standards Track [Page 4]
+
+RFC 3226 DNSSEC and IPv6 A6 requirements December 2001
+
+
+7. References
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2535] Eastlake, D. "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [RFC2845] Vixie, P., Gudmundsson, O., Eastlake, D. and B.
+ Wellington, "Secret Key Transaction Authentication for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+ [RFC2874] Crawford, M. and C. Huitema, "DNS Extensions to Support
+ IPv6 Address Aggregation and Renumbering", RFC 2874, July
+ 2000.
+
+ [RFC3225] Conrad, D., "Indicating Resolver Support of DNSSEC", RFC
+ 3225, December 2001.
+
+8. Author Address
+
+ Olafur Gudmundsson
+ 3826 Legation Street, NW
+ Washington, DC 20015
+ USA
+
+ EMail: ogud@ogud.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 5]
+
+RFC 3226 DNSSEC and IPv6 A6 requirements December 2001
+
+
+9. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2001). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 6]
+
diff --git a/doc/rfc/rfc3258.txt b/doc/rfc/rfc3258.txt
new file mode 100644
index 0000000..dcd4b34
--- /dev/null
+++ b/doc/rfc/rfc3258.txt
@@ -0,0 +1,619 @@
+
+
+
+
+
+
+Network Working Group T. Hardie
+Request for Comments: 3258 Nominum, Inc.
+Category: Informational April 2002
+
+
+ Distributing Authoritative Name Servers via Shared Unicast Addresses
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This memo describes a set of practices intended to enable an
+ authoritative name server operator to provide access to a single
+ named server in multiple locations. The primary motivation for the
+ development and deployment of these practices is to increase the
+ distribution of Domain Name System (DNS) servers to previously
+ under-served areas of the network topology and to reduce the latency
+ for DNS query responses in those areas.
+
+1. Introduction
+
+ This memo describes a set of practices intended to enable an
+ authoritative name server operator to provide access to a single
+ named server in multiple locations. The primary motivation for the
+ development and deployment of these practices is to increase the
+ distribution of DNS servers to previously under-served areas of the
+ network topology and to reduce the latency for DNS query responses in
+ those areas. This document presumes a one-to-one mapping between
+ named authoritative servers and administrative entities (operators).
+ This document contains no guidelines or recommendations for caching
+ name servers. The shared unicast system described here is specific
+ to IPv4; applicability to IPv6 is an area for further study. It
+ should also be noted that the system described here is related to
+ that described in [ANYCAST], but it does not require dedicated
+ address space, routing changes, or the other elements of a full
+ anycast infrastructure which that document describes.
+
+
+
+
+
+
+
+Hardie Informational [Page 1]
+
+RFC 3258 Distributing Authoritative Name Servers April 2002
+
+
+2. Architecture
+
+2.1 Server Requirements
+
+ Operators of authoritative name servers may wish to refer to
+ [SECONDARY] and [ROOT] for general guidance on appropriate practice
+ for authoritative name servers. In addition to proper configuration
+ as a standard authoritative name server, each of the hosts
+ participating in a shared-unicast system should be configured with
+ two network interfaces. These interfaces may be either two physical
+ interfaces or one physical interface mapped to two logical
+ interfaces. One of the network interfaces should use the IPv4 shared
+ unicast address associated with the authoritative name server. The
+ other interface, referred to as the administrative interface below,
+ should use a distinct IPv4 address specific to that host. The host
+ should respond to DNS queries only on the shared-unicast interface.
+ In order to provide the most consistent set of responses from the
+ mesh of anycast hosts, it is good practice to limit responses on that
+ interface to zones for which the host is authoritative.
+
+2.2 Zone file delivery
+
+ In order to minimize the risk of man-in-the-middle attacks, zone
+ files should be delivered to the administrative interface of the
+ servers participating in the mesh. Secure file transfer methods and
+ strong authentication should be used for all transfers. If the hosts
+ in the mesh make their zones available for zone transfer, the
+ administrative interfaces should be used for those transfers as well,
+ in order to avoid the problems with potential routing changes for TCP
+ traffic noted in section 2.5 below.
+
+2.3 Synchronization
+
+ Authoritative name servers may be loosely or tightly synchronized,
+ depending on the practices set by the operating organization. As
+ noted below in section 4.1.2, lack of synchronization among servers
+ using the same shared unicast address could create problems for some
+ users of this service. In order to minimize that risk, switch-overs
+ from one data set to another data set should be coordinated as much
+ as possible. The use of synchronized clocks on the participating
+ hosts and set times for switch-overs provides a basic level of
+ coordination. A more complete coordination process would involve:
+
+ a) receipt of zones at a distribution host
+ b) confirmation of the integrity of zones received
+ c) distribution of the zones to all of the servers in the mesh
+ d) confirmation of the integrity of the zones at each server
+
+
+
+
+Hardie Informational [Page 2]
+
+RFC 3258 Distributing Authoritative Name Servers April 2002
+
+
+ e) coordination of the switchover times for the servers in the
+ mesh
+ f) institution of a failure process to ensure that servers that
+ did not receive correct data or could not switchover to the new
+ data ceased to respond to incoming queries until the problem
+ could be resolved.
+
+ Depending on the size of the mesh, the distribution host may also be
+ a participant; for authoritative servers, it may also be the host on
+ which zones are generated.
+
+ This document presumes that the usual DNS failover methods are the
+ only ones used to ensure reachability of the data for clients. It
+ does not advise that the routes be withdrawn in the case of failure;
+ it advises instead that the DNS process shutdown so that servers on
+ other addresses are queried. This recommendation reflects a choice
+ between performance and operational complexity. While it would be
+ possible to have some process withdraw the route for a specific
+ server instance when it is not available, there is considerable
+ operational complexity involved in ensuring that this occurs
+ reliably. Given the existing DNS failover methods, the marginal
+ improvement in performance will not be sufficient to justify the
+ additional complexity for most uses.
+
+2.4 Server Placement
+
+ Though the geographic diversity of server placement helps reduce the
+ effects of service disruptions due to local problems, it is diversity
+ of placement in the network topology which is the driving force
+ behind these distribution practices. Server placement should
+ emphasize that diversity. Ideally, servers should be placed
+ topologically near the points at which the operator exchanges routes
+ and traffic with other networks.
+
+2.5 Routing
+
+ The organization administering the mesh of servers sharing a unicast
+ address must have an autonomous system number and speak BGP to its
+ peers. To those peers, the organization announces a route to the
+ network containing the shared-unicast address of the name server.
+ The organization's border routers must then deliver the traffic
+ destined for the name server to the nearest instantiation. Routing
+ to the administrative interfaces for the servers can use the normal
+ routing methods for the administering organization.
+
+ One potential problem with using shared unicast addresses is that
+ routers forwarding traffic to them may have more than one available
+ route, and those routes may, in fact, reach different instances of
+
+
+
+Hardie Informational [Page 3]
+
+RFC 3258 Distributing Authoritative Name Servers April 2002
+
+
+ the shared unicast address. Applications like the DNS, whose
+ communication typically consists of independent request-response
+ messages each fitting in a single UDP packet present no problem.
+ Other applications, in which multiple packets must reach the same
+ endpoint (e.g., TCP) may fail or present unworkable performance
+ characteristics in some circumstances. Split-destination failures
+ may occur when a router does per-packet (or round-robin) load
+ sharing, a topology change occurs that changes the relative metrics
+ of two paths to the same anycast destination, etc.
+
+ Four things mitigate the severity of this problem. The first is that
+ UDP is a fairly high proportion of the query traffic to name servers.
+ The second is that the aim of this proposal is to diversify
+ topological placement; for most users, this means that the
+ coordination of placement will ensure that new instances of a name
+ server will be at a significantly different cost metric from existing
+ instances. Some set of users may end up in the middle, but that
+ should be relatively rare. The third is that per packet load sharing
+ is only one of the possible load sharing mechanisms, and other
+ mechanisms are increasing in popularity.
+
+ Lastly, in the case where the traffic is TCP, per packet load sharing
+ is used, and equal cost routes to different instances of a name
+ server are available, any DNS implementation which measures the
+ performance of servers to select a preferred server will quickly
+ prefer a server for which this problem does not occur. For the DNS
+ failover mechanisms to reliably avoid this problem, however, those
+ using shared unicast distribution mechanisms must take care that all
+ of the servers for a specific zone are not participants in the same
+ shared-unicast mesh. To guard even against the case where multiple
+ meshes have a set of users affected by per packet load sharing along
+ equal cost routes, organizations implementing these practices should
+ always provide at least one authoritative server which is not a
+ participant in any shared unicast mesh. Those deploying shared-
+ unicast meshes should note that any specific host may become
+ unreachable to a client should a server fail, a path fail, or the
+ route to that host be withdrawn. These error conditions are,
+ however, not specific to shared-unicast distributions, but would
+ occur for standard unicast hosts.
+
+ Since ICMP response packets might go to a different member of the
+ mesh than that sending a packet, packets sent with a shared unicast
+ source address should also avoid using path MTU discovery.
+
+ Appendix A. contains an ASCII diagram of an example of a simple
+ implementation of this system. In it, the odd numbered routers
+ deliver traffic to the shared-unicast interface network and filter
+ traffic from the administrative network; the even numbered routers
+
+
+
+Hardie Informational [Page 4]
+
+RFC 3258 Distributing Authoritative Name Servers April 2002
+
+
+ deliver traffic to the administrative network and filter traffic from
+ the shared-unicast network. These are depicted as separate routers
+ for the ease this gives in explanation, but they could easily be
+ separate interfaces on the same router. Similarly, a local NTP
+ source is depicted for synchronization, but the level of
+ synchronization needed would not require that source to be either
+ local or a stratum one NTP server.
+
+3. Administration
+
+3.1 Points of Contact
+
+ A single point of contact for reporting problems is crucial to the
+ correct administration of this system. If an external user of the
+ system needs to report a problem related to the service, there must
+ be no ambiguity about whom to contact. If internal monitoring does
+ not indicate a problem, the contact may, of course, need to work with
+ the external user to identify which server generated the error.
+
+4. Security Considerations
+
+ As a core piece of Internet infrastructure, authoritative name
+ servers are common targets of attack. The practices outlined here
+ increase the risk of certain kinds of attacks and reduce the risk of
+ others.
+
+4.1 Increased Risks
+
+4.1.1 Increase in physical servers
+
+ The architecture outlined in this document increases the number of
+ physical servers, which could increase the possibility that a server
+ mis-configuration will occur which allows for a security breach. In
+ general, the entity administering a mesh should ensure that patches
+ and security mechanisms applied to a single member of the mesh are
+ appropriate for and applied to all of the members of a mesh.
+ "Genetic diversity" (code from different code bases) can be a useful
+ security measure in avoiding attacks based on vulnerabilities in a
+ specific code base; in order to ensure consistency of responses from
+ a single named server, however, that diversity should be applied to
+ different shared-unicast meshes or between a mesh and a related
+ unicast authoritative server.
+
+4.1.2 Data synchronization problems
+
+ The level of systemic synchronization described above should be
+ augmented by synchronization of the data present at each of the
+ servers. While the DNS itself is a loosely coupled system, debugging
+
+
+
+Hardie Informational [Page 5]
+
+RFC 3258 Distributing Authoritative Name Servers April 2002
+
+
+ problems with data in specific zones would be far more difficult if
+ two different servers sharing a single unicast address might return
+ different responses to the same query. For example, if the data
+ associated with www.example.com has changed and the administrators of
+ the domain are testing for the changes at the example.com
+ authoritative name servers, they should not need to check each
+ instance of a named authoritative server. The use of NTP to provide
+ a synchronized time for switch-over eliminates some aspects of this
+ problem, but mechanisms to handle failure during the switchover are
+ required. In particular, a server which cannot make the switchover
+ must not roll-back to a previous version; it must cease to respond to
+ queries so that other servers are queried.
+
+4.1.3 Distribution risks
+
+ If the mechanism used to distribute zone files among the servers is
+ not well secured, a man-in-the-middle attack could result in the
+ injection of false information. Digital signatures will alleviate
+ this risk, but encrypted transport and tight access lists are a
+ necessary adjunct to them. Since zone files will be distributed to
+ the administrative interfaces of meshed servers, the access control
+ list for distribution of the zone files should include the
+ administrative interface of the server or servers, rather than their
+ shared unicast addresses.
+
+4.2 Decreased Risks
+
+ The increase in number of physical servers reduces the likelihood
+ that a denial-of-service attack will take out a significant portion
+ of the DNS infrastructure. The increase in servers also reduces the
+ effect of machine crashes, fiber cuts, and localized disasters by
+ reducing the number of users dependent on a specific machine.
+
+5. Acknowledgments
+
+ Masataka Ohta, Bill Manning, Randy Bush, Chris Yarnell, Ray Plzak,
+ Mark Andrews, Robert Elz, Geoff Huston, Bill Norton, Akira Kato,
+ Suzanne Woolf, Bernard Aboba, Casey Ajalat, and Gunnar Lindberg all
+ provided input and commentary on this work. The editor wishes to
+ remember in particular the contribution of the late Scott Tucker,
+ whose extensive systems experience and plain common sense both
+ contributed greatly to the editor's own deployment experience and are
+ missed by all who knew him.
+
+
+
+
+
+
+
+
+Hardie Informational [Page 6]
+
+RFC 3258 Distributing Authoritative Name Servers April 2002
+
+
+6. References
+
+ [SECONDARY] Elz, R., Bush, R., Bradner, S. and M. Patton, "Selection
+ and Operation of Secondary DNS Servers", BCP 16, RFC
+ 2182, July 1997.
+
+ [ROOT] Bush, R., Karrenberg, D., Kosters, M. and R. Plzak, "Root
+ Name Server Operational Requirements", BCP 40, RFC 2870,
+ June 2000.
+
+ [ANYCAST] Patridge, C., Mendez, T. and W. Milliken, "Host
+ Anycasting Service", RFC 1546, November 1993.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hardie Informational [Page 7]
+
+RFC 3258 Distributing Authoritative Name Servers April 2002
+
+
+Appendix A.
+
+ __________________
+Peer 1-| |
+Peer 2-| |
+Peer 3-| Switch |
+Transit| | _________ _________
+etc | |--|Router1|---|----|----------|Router2|---WAN-|
+ | | --------- | | --------- |
+ | | | | |
+ | | | | |
+ ------------------ [NTP] [DNS] |
+ |
+ |
+ |
+ |
+ __________________ |
+Peer 1-| | |
+Peer 2-| | |
+Peer 3-| Switch | |
+Transit| | _________ _________ |
+etc | |--|Router3|---|----|----------|Router4|---WAN-|
+ | | --------- | | --------- |
+ | | | | |
+ | | | | |
+ ------------------ [NTP] [DNS] |
+ |
+ |
+ |
+ |
+ __________________ |
+Peer 1-| | |
+Peer 2-| | |
+Peer 3-| Switch | |
+Transit| | _________ _________ |
+etc | |--|Router5|---|----|----------|Router6|---WAN-|
+ | | --------- | | --------- |
+ | | | | |
+ | | | | |
+ ------------------ [NTP] [DNS] |
+ |
+ |
+ |
+
+
+
+
+
+
+
+
+Hardie Informational [Page 8]
+
+RFC 3258 Distributing Authoritative Name Servers April 2002
+
+
+ |
+ __________________ |
+Peer 1-| | |
+Peer 2-| | |
+Peer 3-| Switch | |
+Transit| | _________ _________ |
+etc | |--|Router7|---|----|----------|Router8|---WAN-|
+ | | --------- | | ---------
+ | | | |
+ | | | |
+ ------------------ [NTP] [DNS]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hardie Informational [Page 9]
+
+RFC 3258 Distributing Authoritative Name Servers April 2002
+
+
+7. Editor's Address
+
+ Ted Hardie
+ Nominum, Inc.
+ 2385 Bay Road.
+ Redwood City, CA 94063
+
+ Phone: 1.650.381.6226
+ EMail: Ted.Hardie@nominum.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hardie Informational [Page 10]
+
+RFC 3258 Distributing Authoritative Name Servers April 2002
+
+
+8. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hardie Informational [Page 11]
+
diff --git a/doc/rfc/rfc3363.txt b/doc/rfc/rfc3363.txt
new file mode 100644
index 0000000..9d7a39c
--- /dev/null
+++ b/doc/rfc/rfc3363.txt
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+Network Working Group R. Bush
+Request for Comments: 3363 A. Durand
+Updates: 2673, 2874 B. Fink
+Category: Informational O. Gudmundsson
+ T. Hain
+ Editors
+ August 2002
+
+
+ Representing Internet Protocol version 6 (IPv6)
+ Addresses in the Domain Name System (DNS)
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document clarifies and updates the standards status of RFCs that
+ define direct and reverse map of IPv6 addresses in DNS. This
+ document moves the A6 and Bit label specifications to experimental
+ status.
+
+1. Introduction
+
+ The IETF had begun the process of standardizing two different address
+ formats for IPv6 addresses AAAA [RFC1886] and A6 [RFC2874] and both
+ are at proposed standard. This had led to confusion and conflicts on
+ which one to deploy. It is important for deployment that any
+ confusion in this area be cleared up, as there is a feeling in the
+ community that having more than one choice will lead to delays in the
+ deployment of IPv6. The goal of this document is to clarify the
+ situation.
+
+ This document also discusses issues relating to the usage of Binary
+ Labels [RFC 2673] to support the reverse mapping of IPv6 addresses.
+
+ This document is based on extensive technical discussion on various
+ relevant working groups mailing lists and a joint DNSEXT and NGTRANS
+ meeting at the 51st IETF in August 2001. This document attempts to
+ capture the sense of the discussions and reflect them in this
+ document to represent the consensus of the community.
+
+
+
+Bush, et. al. Informational [Page 1]
+
+RFC 3363 Representation of IPv6 Addresses in DNS August 2002
+
+
+ The main arguments and the issues are covered in a separate document
+ [RFC3364] that reflects the current understanding of the issues.
+ This document summarizes the outcome of these discussions.
+
+ The issue of the root of reverse IPv6 address map is outside the
+ scope of this document and is covered in a different document
+ [RFC3152].
+
+1.1 Standards Action Taken
+
+ This document changes the status of RFCs 2673 and 2874 from Proposed
+ Standard to Experimental.
+
+2. IPv6 Addresses: AAAA RR vs A6 RR
+
+ Working group consensus as perceived by the chairs of the DNSEXT and
+ NGTRANS working groups is that:
+
+ a) AAAA records are preferable at the moment for production
+ deployment of IPv6, and
+
+ b) that A6 records have interesting properties that need to be better
+ understood before deployment.
+
+ c) It is not known if the benefits of A6 outweigh the costs and
+ risks.
+
+2.1 Rationale
+
+ There are several potential issues with A6 RRs that stem directly
+ from the feature that makes them different from AAAA RRs: the ability
+ to build up addresses via chaining.
+
+ Resolving a chain of A6 RRs involves resolving a series of what are
+ nearly-independent queries. Each of these sub-queries takes some
+ non-zero amount of time, unless the answer happens to be in the
+ resolver's local cache already. Other things being equal, we expect
+ that the time it takes to resolve an N-link chain of A6 RRs will be
+ roughly proportional to N. What data we have suggests that users are
+ already impatient with the length of time it takes to resolve A RRs
+ in the IPv4 Internet, which suggests that users are not likely to be
+ patient with significantly longer delays in the IPv6 Internet, but
+ terminating queries prematurely is both a waste of resources and
+ another source of user frustration. Thus, we are forced to conclude
+ that indiscriminate use of long A6 chains is likely to lead to
+ increased user frustration.
+
+
+
+
+
+Bush, et. al. Informational [Page 2]
+
+RFC 3363 Representation of IPv6 Addresses in DNS August 2002
+
+
+ The probability of failure during the process of resolving an N-link
+ A6 chain also appears to be roughly proportional to N, since each of
+ the queries involved in resolving an A6 chain has roughly the same
+ probability of failure as a single AAAA query.
+
+ Last, several of the most interesting potential applications for A6
+ RRs involve situations where the prefix name field in the A6 RR
+ points to a target that is not only outside the DNS zone containing
+ the A6 RR, but is administered by a different organization entirely.
+ While pointers out of zone are not a problem per se, experience both
+ with glue RRs and with PTR RRs in the IN-ADDR.ARPA tree suggests that
+ pointers to other organizations are often not maintained properly,
+ perhaps because they're less susceptible to automation than pointers
+ within a single organization would be.
+
+2.2 Recommended Standard Action
+
+ Based on the perceived consensus, this document recommends that RFC
+ 1886 stay on standards track and be advanced, while moving RFC 2874
+ to Experimental status.
+
+3. Bitlabels in the Reverse DNS Tree
+
+ RFC 2673 defines a new DNS label type. This was the first new type
+ defined since RFC 1035 [RFC1035]. Since the development of 2673 it
+ has been learned that deployment of a new type is difficult since DNS
+ servers that do not support bitlabels reject queries containing bit
+ labels as being malformed. The community has also indicated that
+ this new label type is not needed for mapping reverse addresses.
+
+3.1 Rationale
+
+ The hexadecimal text representation of IPv6 addresses appears to be
+ capable of expressing all of the delegation schemes that we expect to
+ be used in the DNS reverse tree.
+
+3.2 Recommended Standard Action
+
+ RFC 2673 standard status is to be changed from Proposed to
+ Experimental. Future standardization of these documents is to be
+ done by the DNSEXT working group or its successor.
+
+
+
+
+
+
+
+
+
+
+Bush, et. al. Informational [Page 3]
+
+RFC 3363 Representation of IPv6 Addresses in DNS August 2002
+
+
+4. DNAME in IPv6 Reverse Tree
+
+ The issues for DNAME in the reverse mapping tree appears to be
+ closely tied to the need to use fragmented A6 in the main tree: if
+ one is necessary, so is the other, and if one isn't necessary, the
+ other isn't either. Therefore, in moving RFC 2874 to experimental,
+ the intent of this document is that use of DNAME RRs in the reverse
+ tree be deprecated.
+
+5. Acknowledgments
+
+ This document is based on input from many members of the various IETF
+ working groups involved in this issues. Special thanks go to the
+ people that prepared reading material for the joint DNSEXT and
+ NGTRANS working group meeting at the 51st IETF in London, Rob
+ Austein, Dan Bernstein, Matt Crawford, Jun-ichiro itojun Hagino,
+ Christian Huitema. Number of other people have made number of
+ comments on mailing lists about this issue including Andrew W.
+ Barclay, Robert Elz, Johan Ihren, Edward Lewis, Bill Manning, Pekka
+ Savola, Paul Vixie.
+
+6. Security Considerations
+
+ As this document specifies a course of action, there are no direct
+ security considerations. There is an indirect security impact of the
+ choice, in that the relationship between A6 and DNSSEC is not well
+ understood throughout the community, while the choice of AAAA does
+ leads to a model for use of DNSSEC in IPv6 networks which parallels
+ current IPv4 practice.
+
+7. IANA Considerations
+
+ None.
+
+Normative References
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC1886] Thompson, S. and C. Huitema, "DNS Extensions to support IP
+ version 6", RFC 1886, December 1995.
+
+ [RFC2673] Crawford, M., "Binary Labels in the Domain Name System",
+ RFC 2673, August 1999.
+
+ [RFC2874] Crawford, M. and C. Huitema, "DNS Extensions to Support
+ IPv6 Address Aggregation and Renumbering", RFC 2874, July
+ 2000.
+
+
+
+Bush, et. al. Informational [Page 4]
+
+RFC 3363 Representation of IPv6 Addresses in DNS August 2002
+
+
+ [RFC3152] Bush, R., "Delegation of IP6.ARPA", BCP 49, RFC 3152
+ August 2001.
+
+Informative References
+
+ [RFC3364] Austein, R., "Tradeoffs in Domain Name System (DNS)
+ Support for Internet Protocol version 6 (IPv6)", RFC 3364,
+ August 2002.
+
+Editors' Addresses
+
+ Randy Bush
+ EMail: randy@psg.com
+
+
+ Alain Durand
+ EMail: alain.durand@sun.com
+
+
+ Bob Fink
+ EMail: fink@es.net
+
+
+ Olafur Gudmundsson
+ EMail: ogud@ogud.com
+
+
+ Tony Hain
+ EMail: hain@tndh.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bush, et. al. Informational [Page 5]
+
+RFC 3363 Representation of IPv6 Addresses in DNS August 2002
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Bush, et. al. Informational [Page 6]
+
diff --git a/doc/rfc/rfc3364.txt b/doc/rfc/rfc3364.txt
new file mode 100644
index 0000000..189c0d2
--- /dev/null
+++ b/doc/rfc/rfc3364.txt
@@ -0,0 +1,619 @@
+
+
+
+
+
+
+Network Working Group R. Austein
+Request for Comments: 3364 Bourgeois Dilettant
+Updates: 2673, 2874 August 2002
+Category: Informational
+
+
+ Tradeoffs in Domain Name System (DNS) Support
+ for Internet Protocol version 6 (IPv6)
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ The IETF has two different proposals on the table for how to do DNS
+ support for IPv6, and has thus far failed to reach a clear consensus
+ on which approach is better. This note attempts to examine the pros
+ and cons of each approach, in the hope of clarifying the debate so
+ that we can reach closure and move on.
+
+Introduction
+
+ RFC 1886 [RFC1886] specified straightforward mechanisms to support
+ IPv6 addresses in the DNS. These mechanisms closely resemble the
+ mechanisms used to support IPv4, with a minor improvement to the
+ reverse mapping mechanism based on experience with CIDR. RFC 1886 is
+ currently listed as a Proposed Standard.
+
+ RFC 2874 [RFC2874] specified enhanced mechanisms to support IPv6
+ addresses in the DNS. These mechanisms provide new features that
+ make it possible for an IPv6 address stored in the DNS to be broken
+ up into multiple DNS resource records in ways that can reflect the
+ network topology underlying the address, thus making it possible for
+ the data stored in the DNS to reflect certain kinds of network
+ topology changes or routing architectures that are either impossible
+ or more difficult to represent without these mechanisms. RFC 2874 is
+ also currently listed as a Proposed Standard.
+
+
+
+
+
+
+
+Austein Informational [Page 1]
+
+RFC 3364 Tradeoffs in DNS Support for IPv6 August 2002
+
+
+ Both of these Proposed Standards were the output of the IPNG Working
+ Group. Both have been implemented, although implementation of
+ [RFC1886] is more widespread, both because it was specified earlier
+ and because it's simpler to implement.
+
+ There's little question that the mechanisms proposed in [RFC2874] are
+ more general than the mechanisms proposed in [RFC1886], and that
+ these enhanced mechanisms might be valuable if IPv6's evolution goes
+ in certain directions. The questions are whether we really need the
+ more general mechanism, what new usage problems might come along with
+ the enhanced mechanisms, and what effect all this will have on IPv6
+ deployment.
+
+ The one thing on which there does seem to be widespread agreement is
+ that we should make up our minds about all this Real Soon Now.
+
+Main Advantages of Going with A6
+
+ While the A6 RR proposed in [RFC2874] is very general and provides a
+ superset of the functionality provided by the AAAA RR in [RFC1886],
+ many of the features of A6 can also be implemented with AAAA RRs via
+ preprocessing during zone file generation.
+
+ There is one specific area where A6 RRs provide something that cannot
+ be provided using AAAA RRs: A6 RRs can represent addresses in which a
+ prefix portion of the address can change without any action (or
+ perhaps even knowledge) by the parties controlling the DNS zone
+ containing the terminal portion (least significant bits) of the
+ address. This includes both so-called "rapid renumbering" scenarios
+ (where an entire network's prefix may change very quickly) and
+ routing architectures such as the former "GSE" proposal [GSE] (where
+ the "routing goop" portion of an address may be subject to change
+ without warning). A6 RRs do not completely remove the need to update
+ leaf zones during all renumbering events (for example, changing ISPs
+ would usually require a change to the upward delegation pointer), but
+ careful use of A6 RRs could keep the number of RRs that need to
+ change during such an event to a minimum.
+
+ Note that constructing AAAA RRs via preprocessing during zone file
+ generation requires exactly the sort of information that A6 RRs store
+ in the DNS. This begs the question of where the hypothetical
+ preprocessor obtains that information if it's not getting it from the
+ DNS.
+
+ Note also that the A6 RR, when restricted to its zero-length-prefix
+ form ("A6 0"), is semantically equivalent to an AAAA RR (with one
+ "wasted" octet in the wire representation), so anything that can be
+ done with an AAAA RR can also be done with an A6 RR.
+
+
+
+Austein Informational [Page 2]
+
+RFC 3364 Tradeoffs in DNS Support for IPv6 August 2002
+
+
+Main Advantages of Going with AAAA
+
+ The AAAA RR proposed in [RFC1886], while providing only a subset of
+ the functionality provided by the A6 RR proposed in [RFC2874], has
+ two main points to recommend it:
+
+ - AAAA RRs are essentially identical (other than their length) to
+ IPv4's A RRs, so we have more than 15 years of experience to help
+ us predict the usage patterns, failure scenarios and so forth
+ associated with AAAA RRs.
+
+ - The AAAA RR is "optimized for read", in the sense that, by storing
+ a complete address rather than making the resolver fetch the
+ address in pieces, it minimizes the effort involved in fetching
+ addresses from the DNS (at the expense of increasing the effort
+ involved in injecting new data into the DNS).
+
+Less Compelling Arguments in Favor of A6
+
+ Since the A6 RR allows a zone administrator to write zone files whose
+ description of addresses maps to the underlying network topology, A6
+ RRs can be construed as a "better" way of representing addresses than
+ AAAA. This may well be a useful capability, but in and of itself
+ it's more of an argument for better tools for zone administrators to
+ use when constructing zone files than a justification for changing
+ the resolution protocol used on the wire.
+
+Less Compelling Arguments in Favor of AAAA
+
+ Some of the pressure to go with AAAA instead of A6 appears to be
+ based on the wider deployment of AAAA. Since it is possible to
+ construct transition tools (see discussion of AAAA synthesis, later
+ in this note), this does not appear to be a compelling argument if A6
+ provides features that we really need.
+
+ Another argument in favor of AAAA RRs over A6 RRs appears to be that
+ the A6 RR's advanced capabilities increase the number of ways in
+ which a zone administrator could build a non-working configuration.
+ While operational issues are certainly important, this is more of
+ argument that we need better tools for zone administrators than it is
+ a justification for turning away from A6 if A6 provides features that
+ we really need.
+
+
+
+
+
+
+
+
+
+Austein Informational [Page 3]
+
+RFC 3364 Tradeoffs in DNS Support for IPv6 August 2002
+
+
+Potential Problems with A6
+
+ The enhanced capabilities of the A6 RR, while interesting, are not in
+ themselves justification for choosing A6 if we don't really need
+ those capabilities. The A6 RR is "optimized for write", in the sense
+ that, by making it possible to store fragmented IPv6 addresses in the
+ DNS, it makes it possible to reduce the effort that it takes to
+ inject new data into the DNS (at the expense of increasing the effort
+ involved in fetching data from the DNS). This may be justified if we
+ expect the effort involved in maintaining AAAA-style DNS entries to
+ be prohibitive, but in general, we expect the DNS data to be read
+ more frequently than it is written, so we need to evaluate this
+ particular tradeoff very carefully.
+
+ There are also several potential issues with A6 RRs that stem
+ directly from the feature that makes them different from AAAA RRs:
+ the ability to build up address via chaining.
+
+ Resolving a chain of A6 RRs involves resolving a series of what are
+ almost independent queries, but not quite. Each of these sub-queries
+ takes some non-zero amount of time, unless the answer happens to be
+ in the resolver's local cache already. Assuming that resolving an
+ AAAA RR takes time T as a baseline, we can guess that, on the
+ average, it will take something approaching time N*T to resolve an
+ N-link chain of A6 RRs, although we would expect to see a fairly good
+ caching factor for the A6 fragments representing the more significant
+ bits of an address. This leaves us with two choices, neither of
+ which is very good: we can decrease the amount of time that the
+ resolver is willing to wait for each fragment, or we can increase the
+ amount of time that a resolver is willing to wait before returning
+ failure to a client. What little data we have on this subject
+ suggests that users are already impatient with the length of time it
+ takes to resolve A RRs in the IPv4 Internet, which suggests that they
+ are not likely to be patient with significantly longer delays in the
+ IPv6 Internet. At the same time, terminating queries prematurely is
+ both a waste of resources and another source of user frustration.
+ Thus, we are forced to conclude that indiscriminate use of long A6
+ chains is likely to lead to problems.
+
+ To make matters worse, the places where A6 RRs are likely to be most
+ critical for rapid renumbering or GSE-like routing are situations
+ where the prefix name field in the A6 RR points to a target that is
+ not only outside the DNS zone containing the A6 RR, but is
+ administered by a different organization (for example, in the case of
+ an end user's site, the prefix name will most likely point to a name
+ belonging to an ISP that provides connectivity for the site). While
+ pointers out of zone are not a problem per se, pointers to other
+ organizations are somewhat more difficult to maintain and less
+
+
+
+Austein Informational [Page 4]
+
+RFC 3364 Tradeoffs in DNS Support for IPv6 August 2002
+
+
+ susceptible to automation than pointers within a single organization
+ would be. Experience both with glue RRs and with PTR RRs in the IN-
+ ADDR.ARPA tree suggests that many zone administrators do not really
+ understand how to set up and maintain these pointers properly, and we
+ have no particular reason to believe that these zone administrators
+ will do a better job with A6 chains than they do today. To be fair,
+ however, the alternative case of building AAAA RRs via preprocessing
+ before loading zones has many of the same problems; at best, one can
+ claim that using AAAA RRs for this purpose would allow DNS clients to
+ get the wrong answer somewhat more efficiently than with A6 RRs.
+
+ Finally, assuming near total ignorance of how likely a query is to
+ fail, the probability of failure with an N-link A6 chain would appear
+ to be roughly proportional to N, since each of the queries involved
+ in resolving an A6 chain would have the same probability of failure
+ as a single AAAA query. Note again that this comment applies to
+ failures in the the process of resolving a query, not to the data
+ obtained via that process. Arguably, in an ideal world, A6 RRs would
+ increase the probability of the answer a client (finally) gets being
+ right, assuming that nothing goes wrong in the query process, but we
+ have no real idea how to quantify that assumption at this point even
+ to the hand-wavey extent used elsewhere in this note.
+
+ One potential problem that has been raised in the past regarding A6
+ RRs turns out not to be a serious issue. The A6 design includes the
+ possibility of there being more than one A6 RR matching the prefix
+ name portion of a leaf A6 RR. That is, an A6 chain may not be a
+ simple linked list, it may in fact be a tree, where each branch
+ represents a possible prefix. Some critics of A6 have been concerned
+ that this will lead to a wild expansion of queries, but this turns
+ out not to be a problem if a resolver simply follows the "bounded
+ work per query" rule described in RFC 1034 (page 35). That rule
+ applies to all work resulting from attempts to process a query,
+ regardless of whether it's a simple query, a CNAME chain, an A6 tree,
+ or an infinite loop. The client may not get back a useful answer in
+ cases where the zone has been configured badly, but a proper
+ implementation should not produce a query explosion as a result of
+ processing even the most perverse A6 tree, chain, or loop.
+
+Interactions with DNSSEC
+
+ One of the areas where AAAA and A6 RRs differ is in the precise
+ details of how they interact with DNSSEC. The following comments
+ apply only to non-zero-prefix A6 RRs (A6 0 RRs, once again, are
+ semantically equivalent to AAAA RRs).
+
+
+
+
+
+
+Austein Informational [Page 5]
+
+RFC 3364 Tradeoffs in DNS Support for IPv6 August 2002
+
+
+ Other things being equal, the time it takes to re-sign all of the
+ addresses in a zone after a renumbering event is longer with AAAA RRs
+ than with A6 RRs (because each address record has to be re-signed
+ rather than just signing a common prefix A6 RR and a few A6 0 RRs
+ associated with the zone's name servers). Note, however, that in
+ general this does not present a serious scaling problem, because the
+ re-signing is performed in the leaf zones.
+
+ Other things being equal, there's more work involved in verifying the
+ signatures received back for A6 RRs, because each address fragment
+ has a separate associated signature. Similarly, a DNS message
+ containing a set of A6 address fragments and their associated
+ signatures will be larger than the equivalent packet with a single
+ AAAA (or A6 0) and a single associated signature.
+
+ Since AAAA RRs cannot really represent rapid renumbering or GSE-style
+ routing scenarios very well, it should not be surprising that DNSSEC
+ signatures of AAAA RRs are also somewhat problematic. In cases where
+ the AAAA RRs would have to be changing very quickly to keep up with
+ prefix changes, the time required to re-sign the AAAA RRs may be
+ prohibitive.
+
+ Empirical testing by Bill Sommerfeld [Sommerfeld] suggests that
+ 333MHz Celeron laptop with 128KB L2 cache and 64MB RAM running the
+ BIND-9 dnssec-signzone program under NetBSD can generate roughly 40
+ 1024-bit RSA signatures per second. Extrapolating from this,
+ assuming one A RR, one AAAA RR, and one NXT RR per host, this
+ suggests that it would take this laptop a few hours to sign a zone
+ listing 10**5 hosts, or about a day to sign a zone listing 10**6
+ hosts using AAAA RRs.
+
+ This suggests that the additional effort of re-signing a large zone
+ full of AAAA RRs during a re-numbering event, while noticeable, is
+ only likely to be prohibitive in the rapid renumbering case where
+ AAAA RRs don't work well anyway.
+
+Interactions with Dynamic Update
+
+ DNS dynamic update appears to work equally well for AAAA or A6 RRs,
+ with one minor exception: with A6 RRs, the dynamic update client
+ needs to know the prefix length and prefix name. At present, no
+ mechanism exists to inform a dynamic update client of these values,
+ but presumably such a mechanism could be provided via an extension to
+ DHCP, or some other equivalent could be devised.
+
+
+
+
+
+
+
+Austein Informational [Page 6]
+
+RFC 3364 Tradeoffs in DNS Support for IPv6 August 2002
+
+
+Transition from AAAA to A6 Via AAAA Synthesis
+
+ While AAAA is at present more widely deployed than A6, it is possible
+ to transition from AAAA-aware DNS software to A6-aware DNS software.
+ A rough plan for this was presented at IETF-50 in Minneapolis and has
+ been discussed on the ipng mailing list. So if the IETF concludes
+ that A6's enhanced capabilities are necessary, it should be possible
+ to transition from AAAA to A6.
+
+ The details of this transition have been left to a separate document,
+ but the general idea is that the resolver that is performing
+ iterative resolution on behalf of a DNS client program could
+ synthesize AAAA RRs representing the result of performing the
+ equivalent A6 queries. Note that in this case it is not possible to
+ generate an equivalent DNSSEC signature for the AAAA RR, so clients
+ that care about performing DNSSEC validation for themselves would
+ have to issue A6 queries directly rather than relying on AAAA
+ synthesis.
+
+Bitlabels
+
+ While the differences between AAAA and A6 RRs have generated most of
+ the discussion to date, there are also two proposed mechanisms for
+ building the reverse mapping tree (the IPv6 equivalent of IPv4's IN-
+ ADDR.ARPA tree).
+
+ [RFC1886] proposes a mechanism very similar to the IN-ADDR.ARPA
+ mechanism used for IPv4 addresses: the RR name is the hexadecimal
+ representation of the IPv6 address, reversed and concatenated with a
+ well-known suffix, broken up with a dot between each hexadecimal
+ digit. The resulting DNS names are somewhat tedious for humans to
+ type, but are very easy for programs to generate. Making each
+ hexadecimal digit a separate label means that delegation on arbitrary
+ bit boundaries will result in a maximum of 16 NS RRsets per label
+ level; again, the mechanism is somewhat tedious for humans, but is
+ very easy to program. As with IPv4's IN-ADDR.ARPA tree, the one
+ place where this scheme is weak is in handling delegations in the
+ least significant label; however, since there appears to be no real
+ need to delegate the least significant four bits of an IPv6 address,
+ this does not appear to be a serious restriction.
+
+ [RFC2874] proposed a radically different way of naming entries in the
+ reverse mapping tree: rather than using textual representations of
+ addresses, it proposes to use a new kind of DNS label (a "bit label")
+ to represent binary addresses directly in the DNS. This has the
+ advantage of being significantly more compact than the textual
+ representation, and arguably might have been a better solution for
+ DNS to use for this purpose if it had been designed into the protocol
+
+
+
+Austein Informational [Page 7]
+
+RFC 3364 Tradeoffs in DNS Support for IPv6 August 2002
+
+
+ from the outset. Unfortunately, experience to date suggests that
+ deploying a new DNS label type is very hard: all of the DNS name
+ servers that are authoritative for any portion of the name in
+ question must be upgraded before the new label type can be used, as
+ must any resolvers involved in the resolution process. Any name
+ server that has not been upgraded to understand the new label type
+ will reject the query as being malformed.
+
+ Since the main benefit of the bit label approach appears to be an
+ ability that we don't really need (delegation in the least
+ significant four bits of an IPv6 address), and since the upgrade
+ problem is likely to render bit labels unusable until a significant
+ portion of the DNS code base has been upgraded, it is difficult to
+ escape the conclusion that the textual solution is good enough.
+
+DNAME RRs
+
+ [RFC2874] also proposes using DNAME RRs as a way of providing the
+ equivalent of A6's fragmented addresses in the reverse mapping tree.
+ That is, by using DNAME RRs, one can write zone files for the reverse
+ mapping tree that have the same ability to cope with rapid
+ renumbering or GSE-style routing that the A6 RR offers in the main
+ portion of the DNS tree. Consequently, the need to use DNAME in the
+ reverse mapping tree appears to be closely tied to the need to use
+ fragmented A6 in the main tree: if one is necessary, so is the other,
+ and if one isn't necessary, the other isn't either.
+
+ Other uses have also been proposed for the DNAME RR, but since they
+ are outside the scope of the IPv6 address discussion, they will not
+ be addressed here.
+
+Recommendation
+
+ Distilling the above feature comparisons down to their key elements,
+ the important questions appear to be:
+
+ (a) Is IPv6 going to do rapid renumbering or GSE-like routing?
+
+ (b) Is the reverse mapping tree for IPv6 going to require delegation
+ in the least significant four bits of the address?
+
+ Question (a) appears to be the key to the debate. This is really a
+ decision for the IPv6 community to make, not the DNS community.
+
+ Question (b) is also for the IPv6 community to make, but it seems
+ fairly obvious that the answer is "no".
+
+
+
+
+
+Austein Informational [Page 8]
+
+RFC 3364 Tradeoffs in DNS Support for IPv6 August 2002
+
+
+ Recommendations based on these questions:
+
+ (1) If the IPv6 working groups seriously intend to specify and deploy
+ rapid renumbering or GSE-like routing, we should transition to
+ using the A6 RR in the main tree and to using DNAME RRs as
+ necessary in the reverse tree.
+
+ (2) Otherwise, we should keep the simpler AAAA solution in the main
+ tree and should not use DNAME RRs in the reverse tree.
+
+ (3) In either case, the reverse tree should use the textual
+ representation described in [RFC1886] rather than the bit label
+ representation described in [RFC2874].
+
+ (4) If we do go to using A6 RRs in the main tree and to using DNAME
+ RRs in the reverse tree, we should write applicability statements
+ and implementation guidelines designed to discourage excessively
+ complex uses of these features; in general, any network that can
+ be described adequately using A6 0 RRs and without using DNAME
+ RRs should be described that way, and the enhanced features
+ should be used only when absolutely necessary, at least until we
+ have much more experience with them and have a better
+ understanding of their failure modes.
+
+Security Considerations
+
+ This note compares two mechanisms with similar security
+ characteristics, but there are a few security implications to the
+ choice between these two mechanisms:
+
+ (1) The two mechanisms have similar but not identical interactions
+ with DNSSEC. Please see the section entitled "Interactions with
+ DNSSEC" (above) for a discussion of these issues.
+
+ (2) To the extent that operational complexity is the enemy of
+ security, the tradeoffs in operational complexity discussed
+ throughout this note have an impact on security.
+
+ (3) To the extent that protocol complexity is the enemy of security,
+ the additional protocol complexity of [RFC2874] as compared to
+ [RFC1886] has some impact on security.
+
+IANA Considerations
+
+ None, since all of these RR types have already been allocated.
+
+
+
+
+
+
+Austein Informational [Page 9]
+
+RFC 3364 Tradeoffs in DNS Support for IPv6 August 2002
+
+
+Acknowledgments
+
+ This note is based on a number of discussions both public and private
+ over a period of (at least) eight years, but particular thanks go to
+ Alain Durand, Bill Sommerfeld, Christian Huitema, Jun-ichiro itojun
+ Hagino, Mark Andrews, Matt Crawford, Olafur Gudmundsson, Randy Bush,
+ and Sue Thomson, none of whom are responsible for what the author did
+ with their ideas.
+
+References
+
+ [RFC1886] Thomson, S. and C. Huitema, "DNS Extensions to support
+ IP version 6", RFC 1886, December 1995.
+
+ [RFC2874] Crawford, M. and C. Huitema, "DNS Extensions to Support
+ IPv6 Address Aggregation and Renumbering", RFC 2874,
+ July 2000.
+
+ [Sommerfeld] Private message to the author from Bill Sommerfeld dated
+ 21 March 2001, summarizing the result of experiments he
+ performed on a copy of the MIT.EDU zone.
+
+ [GSE] "GSE" was an evolution of the so-called "8+8" proposal
+ discussed by the IPng working group in 1996 and 1997.
+ The GSE proposal itself was written up as an Internet-
+ Draft, which has long since expired. Readers interested
+ in the details and history of GSE should review the IPng
+ working group's mailing list archives and minutes from
+ that period.
+
+Author's Address
+
+ Rob Austein
+
+ EMail: sra@hactrn.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Informational [Page 10]
+
+RFC 3364 Tradeoffs in DNS Support for IPv6 August 2002
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Austein Informational [Page 11]
+
diff --git a/doc/rfc/rfc3425.txt b/doc/rfc/rfc3425.txt
new file mode 100644
index 0000000..707cafd
--- /dev/null
+++ b/doc/rfc/rfc3425.txt
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+Network Working Group D. Lawrence
+Request for Comments: 3425 Nominum
+Updates: 1035 November 2002
+Category: Standards Track
+
+
+ Obsoleting IQUERY
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ The IQUERY method of performing inverse DNS lookups, specified in RFC
+ 1035, has not been generally implemented and has usually been
+ operationally disabled where it has been implemented. Both reflect a
+ general view in the community that the concept was unwise and that
+ the widely-used alternate approach of using pointer (PTR) queries and
+ reverse-mapping records is preferable. Consequently, this document
+ deprecates the IQUERY operation, declaring it entirely obsolete.
+ This document updates RFC 1035.
+
+1 - Introduction
+
+ As specified in RFC 1035 (section 6.4), the IQUERY operation for DNS
+ queries is used to look up the name(s) which are associated with the
+ given value. The value being sought is provided in the query's
+ answer section and the response fills in the question section with
+ one or more 3-tuples of type, name and class.
+
+ As noted in [RFC1035], section 6.4.3, inverse query processing can
+ put quite an arduous burden on a server. A server would need to
+ perform either an exhaustive search of its database or maintain a
+ separate database that is keyed by the values of the primary
+ database. Both of these approaches could strain system resource use,
+ particularly for servers that are authoritative for millions of
+ names.
+
+
+
+
+
+Lawrence Standards Track [Page 1]
+
+RFC 3425 Obsoleting IQUERY November 2002
+
+
+ Response packets from these megaservers could be exceptionally large,
+ and easily run into megabyte sizes. For example, using IQUERY to
+ find every domain that is delegated to one of the nameservers of a
+ large ISP could return tens of thousands of 3-tuples in the question
+ section. This could easily be used to launch denial of service
+ attacks.
+
+ Operators of servers that do support IQUERY in some form (such as
+ very old BIND 4 servers) generally opt to disable it. This is
+ largely due to bugs in insufficiently-exercised code, or concerns
+ about exposure of large blocks of names in their zones by probes such
+ as inverse MX queries.
+
+ IQUERY is also somewhat inherently crippled by being unable to tell a
+ requester where it needs to go to get the information that was
+ requested. The answer is very specific to the single server that was
+ queried. This is sometimes a handy diagnostic tool, but apparently
+ not enough so that server operators like to enable it, or request
+ implementation where it is lacking.
+
+ No known clients use IQUERY to provide any meaningful service. The
+ only common reverse mapping support on the Internet, mapping address
+ records to names, is provided through the use of pointer (PTR)
+ records in the in-addr.arpa tree and has served the community well
+ for many years.
+
+ Based on all of these factors, this document recommends that the
+ IQUERY operation for DNS servers be officially obsoleted.
+
+2 - Requirements
+
+ The key word "SHOULD" in this document is to be interpreted as
+ described in BCP 14, RFC 2119, namely that there may exist valid
+ reasons to ignore a particular item, but the full implications must
+ be understood and carefully weighed before choosing a different
+ course.
+
+3 - Effect on RFC 1035
+
+ The effect of this document is to change the definition of opcode 1
+ from that originally defined in section 4.1.1 of RFC 1035, and to
+ entirely supersede section 6.4 (including subsections) of RFC 1035.
+
+ The definition of opcode 1 is hereby changed to:
+
+ "1 an inverse query (IQUERY) (obsolete)"
+
+
+
+
+
+Lawrence Standards Track [Page 2]
+
+RFC 3425 Obsoleting IQUERY November 2002
+
+
+ The text in section 6.4 of RFC 1035 is now considered obsolete. The
+ following is an applicability statement regarding the IQUERY opcode:
+
+ Inverse queries using the IQUERY opcode were originally described as
+ the ability to look up the names that are associated with a
+ particular Resource Record (RR). Their implementation was optional
+ and never achieved widespread use. Therefore IQUERY is now obsolete,
+ and name servers SHOULD return a "Not Implemented" error when an
+ IQUERY request is received.
+
+4 - Security Considerations
+
+ Since this document obsoletes an operation that was once available,
+ it is conceivable that someone was using it as the basis of a
+ security policy. However, since the most logical course for such a
+ policy to take in the face of a lack of positive response from a
+ server is to deny authentication/authorization, it is highly unlikely
+ that removing support for IQUERY will open any new security holes.
+
+ Note that if IQUERY is not obsoleted, securing the responses with DNS
+ Security (DNSSEC) is extremely difficult without out-on-the-fly
+ digital signing.
+
+5 - IANA Considerations
+
+ The IQUERY opcode of 1 should be permanently retired, not to be
+ assigned to any future opcode.
+
+6 - Acknowledgments
+
+ Olafur Gudmundsson instigated this action. Matt Crawford, John
+ Klensin, Erik Nordmark and Keith Moore contributed some improved
+ wording in how to handle obsoleting functionality described by an
+ Internet Standard.
+
+7 - References
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2026] Bradner, S., "The Internet Standards Process -- Revision
+ 3", BCP 9, RFC 2026, October 1996.
+
+ [RFC2119] Bradner, S., "Key Words for Use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+
+
+
+Lawrence Standards Track [Page 3]
+
+RFC 3425 Obsoleting IQUERY November 2002
+
+
+8 - Author's Address
+
+ David C Lawrence
+ Nominum, Inc.
+ 2385 Bay Rd
+ Redwood City CA 94063
+ USA
+
+ Phone: +1.650.779.6042
+ EMail: tale@nominum.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lawrence Standards Track [Page 4]
+
+RFC 3425 Obsoleting IQUERY November 2002
+
+
+9 - Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Lawrence Standards Track [Page 5]
+
diff --git a/doc/rfc/rfc3445.txt b/doc/rfc/rfc3445.txt
new file mode 100644
index 0000000..67f9b2d
--- /dev/null
+++ b/doc/rfc/rfc3445.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group D. Massey
+Request for Comments: 3445 USC/ISI
+Updates: 2535 S. Rose
+Category: Standards Track NIST
+ December 2002
+
+
+ Limiting the Scope of the KEY Resource Record (RR)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+Abstract
+
+ This document limits the Domain Name System (DNS) KEY Resource Record
+ (RR) to only keys used by the Domain Name System Security Extensions
+ (DNSSEC). The original KEY RR used sub-typing to store both DNSSEC
+ keys and arbitrary application keys. Storing both DNSSEC and
+ application keys with the same record type is a mistake. This
+ document removes application keys from the KEY record by redefining
+ the Protocol Octet field in the KEY RR Data. As a result of removing
+ application keys, all but one of the flags in the KEY record become
+ unnecessary and are redefined. Three existing application key sub-
+ types are changed to reserved, but the format of the KEY record is
+ not changed. This document updates RFC 2535.
+
+1. Introduction
+
+ This document limits the scope of the KEY Resource Record (RR). The
+ KEY RR was defined in [3] and used resource record sub-typing to hold
+ arbitrary public keys such as Email, IPSEC, DNSSEC, and TLS keys.
+ This document eliminates the existing Email, IPSEC, and TLS sub-types
+ and prohibits the introduction of new sub-types. DNSSEC will be the
+ only allowable sub-type for the KEY RR (hence sub-typing is
+ essentially eliminated) and all but one of the KEY RR flags are also
+ eliminated.
+
+
+
+
+
+
+Massey & Rose Standards Track [Page 1]
+
+RFC 3445 Limiting the KEY Resource Record (RR) December 2002
+
+
+ Section 2 presents the motivation for restricting the KEY record and
+ Section 3 defines the revised KEY RR. Sections 4 and 5 summarize the
+ changes from RFC 2535 and discuss backwards compatibility. It is
+ important to note that this document restricts the use of the KEY RR
+ and simplifies the flags, but does not change the definition or use
+ of DNSSEC keys.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [1].
+
+2. Motivation for Restricting the KEY RR
+
+ The KEY RR RDATA [3] consists of Flags, a Protocol Octet, an
+ Algorithm type, and a Public Key. The Protocol Octet identifies the
+ KEY RR sub-type. DNSSEC public keys are stored in the KEY RR using a
+ Protocol Octet value of 3. Email, IPSEC, and TLS keys were also
+ stored in the KEY RR and used Protocol Octet values of 1,2, and 4
+ (respectively). Protocol Octet values 5-254 were available for
+ assignment by IANA and values were requested (but not assigned) for
+ applications such as SSH.
+
+ Any use of sub-typing has inherent limitations. A resolver can not
+ specify the desired sub-type in a DNS query and most DNS operations
+ apply only to resource records sets. For example, a resolver can not
+ directly request the DNSSEC subtype KEY RRs. Instead, the resolver
+ has to request all KEY RRs associated with a DNS name and then search
+ the set for the desired DNSSEC sub-type. DNSSEC signatures also
+ apply to the set of all KEY RRs associated with the DNS name,
+ regardless of sub-type.
+
+ In the case of the KEY RR, the inherent sub-type limitations are
+ exacerbated since the sub-type is used to distinguish between DNSSEC
+ keys and application keys. DNSSEC keys and application keys differ
+ in virtually every respect and Section 2.1 discusses these
+ differences in more detail. Combining these very different types of
+ keys into a single sub-typed resource record adds unnecessary
+ complexity and increases the potential for implementation and
+ deployment errors. Limited experimental deployment has shown that
+ application keys stored in KEY RRs are problematic.
+
+ This document addresses these issues by removing all application keys
+ from the KEY RR. Note that the scope of this document is strictly
+ limited to the KEY RR and this document does not endorse or restrict
+ the storage of application keys in other, yet undefined, resource
+ records.
+
+
+
+
+
+Massey & Rose Standards Track [Page 2]
+
+RFC 3445 Limiting the KEY Resource Record (RR) December 2002
+
+
+2.1 Differences Between DNSSEC and Application Keys
+
+ DNSSEC keys are an essential part of the DNSSEC protocol and are used
+ by both name servers and resolvers in order to perform DNS tasks. A
+ DNS zone key, used to sign and authenticate RR sets, is the most
+ common example of a DNSSEC key. SIG(0) [4] and TKEY [3] also use
+ DNSSEC keys.
+
+ Application keys such as Email keys, IPSEC keys, and TLS keys are
+ simply another type of data. These keys have no special meaning to a
+ name server or resolver.
+
+ The following table summarizes some of the differences between DNSSEC
+ keys and application keys:
+
+ 1. They serve different purposes.
+
+ 2. They are managed by different administrators.
+
+ 3. They are authenticated according to different rules.
+
+ 4. Nameservers use different rules when including them in
+ responses.
+
+ 5. Resolvers process them in different ways.
+
+ 6. Faults/key compromises have different consequences.
+
+ 1. The purpose of a DNSSEC key is to sign resource records
+ associated with a DNS zone (or generate DNS transaction signatures in
+ the case of SIG(0)/TKEY). But the purpose of an application key is
+ specific to the application. Application keys, such as PGP/email,
+ IPSEC, TLS, and SSH keys, are not a mandatory part of any zone and
+ the purpose and proper use of application keys is outside the scope
+ of DNS.
+
+ 2. DNSSEC keys are managed by DNS administrators, but application
+ keys are managed by application administrators. The DNS zone
+ administrator determines the key lifetime, handles any suspected key
+ compromises, and manages any DNSSEC key changes. Likewise, the
+ application administrator is responsible for the same functions for
+ the application keys related to the application. For example, a user
+ typically manages her own PGP key and a server manages its own TLS
+ key. Application key management tasks are outside the scope of DNS
+ administration.
+
+
+
+
+
+
+Massey & Rose Standards Track [Page 3]
+
+RFC 3445 Limiting the KEY Resource Record (RR) December 2002
+
+
+ 3. DNSSEC zone keys are used to authenticate application keys, but
+ by definition, application keys are not allowed to authenticate DNS
+ zone keys. A DNS zone key is either configured as a trusted key or
+ authenticated by constructing a chain of trust in the DNS hierarchy.
+ To participate in the chain of trust, a DNS zone needs to exchange
+ zone key information with its parent zone [3]. Application keys are
+ not configured as trusted keys in the DNS and are never part of any
+ DNS chain of trust. Application key data is not needed by the parent
+ and does not need to be exchanged with the parent zone for secure DNS
+ resolution to work. A resolver considers an application key RRset as
+ authenticated DNS information if it has a valid signature from the
+ local DNS zone keys, but applications could impose additional
+ security requirements before the application key is accepted as
+ authentic for use with the application.
+
+ 4. It may be useful for nameservers to include DNS zone keys in the
+ additional section of a response, but application keys are typically
+ not useful unless they have been specifically requested. For
+ example, it could be useful to include the example.com zone key along
+ with a response that contains the www.example.com A record and SIG
+ record. A secure resolver will need the example.com zone key in
+ order to check the SIG and authenticate the www.example.com A record.
+ It is typically not useful to include the IPSEC, email, and TLS keys
+ along with the A record. Note that by placing application keys in
+ the KEY record, a resolver would need the IPSEC, email, TLS, and
+ other key associated with example.com if the resolver intends to
+ authenticate the example.com zone key (since signatures only apply to
+ the entire KEY RR set). Depending on the number of protocols
+ involved, the KEY RR set could grow unwieldy for resolvers, and DNS
+ administrators to manage.
+
+ 5. DNS zone keys require special handling by resolvers, but
+ application keys are treated the same as any other type of DNS data.
+ The DNSSEC keys are of no value to end applications, unless the
+ applications plan to do their own DNS authentication. By definition,
+ secure resolvers are not allowed to use application keys as part of
+ the authentication process. Application keys have no unique meaning
+ to resolvers and are only useful to the application requesting the
+ key. Note that if sub-types are used to identify the application
+ key, then either the interface to the resolver needs to specify the
+ sub-type or the application needs to be able to accept all KEY RRs
+ and pick out the desired sub-type.
+
+ 6. A fault or compromise of a DNS zone key can lead to invalid or
+ forged DNS data, but a fault or compromise of an application key
+ should have no impact on other DNS data. Incorrectly adding or
+ changing a DNS zone key can invalidate all of the DNS data in the
+ zone and in all of its subzones. By using a compromised key, an
+
+
+
+Massey & Rose Standards Track [Page 4]
+
+RFC 3445 Limiting the KEY Resource Record (RR) December 2002
+
+
+ attacker can forge data from the effected zone and for any of its
+ sub-zones. A fault or compromise of an application key has
+ implications for that application, but it should not have an impact
+ on the DNS. Note that application key faults and key compromises can
+ have an impact on the entire DNS if the application key and DNS zone
+ keys are both stored in the KEY RR.
+
+ In summary, DNSSEC keys and application keys differ in most every
+ respect. DNSSEC keys are an essential part of the DNS infrastructure
+ and require special handling by DNS administrators and DNS resolvers.
+ Application keys are simply another type of data and have no special
+ meaning to DNS administrators or resolvers. These two different
+ types of data do not belong in the same resource record.
+
+3. Definition of the KEY RR
+
+ The KEY RR uses type 25 and is used as resource record for storing
+ DNSSEC keys. The RDATA for a KEY RR consists of flags, a protocol
+ octet, the algorithm number octet, and the public key itself. The
+ format is as follows:
+
+ ---------------------------------------------------------------------
+
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | flags | protocol | algorithm |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | /
+ / public key /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ KEY RR Format
+
+ ---------------------------------------------------------------------
+
+ In the flags field, all bits except bit 7 are reserved and MUST be
+ zero. If Bit 7 (Zone bit) is set to 1, then the KEY is a DNS Zone
+ key. If Bit 7 is set to 0, the KEY is not a zone key. SIG(0)/TKEY
+ are examples of DNSSEC keys that are not zone keys.
+
+ The protocol field MUST be set to 3.
+
+ The algorithm and public key fields are not changed.
+
+
+
+
+
+Massey & Rose Standards Track [Page 5]
+
+RFC 3445 Limiting the KEY Resource Record (RR) December 2002
+
+
+4. Changes from RFC 2535 KEY RR
+
+ The KEY RDATA format is not changed.
+
+ All flags except for the zone key flag are eliminated:
+
+ The A/C bits (bits 0 and 1) are eliminated. They MUST be set to 0
+ and MUST be ignored by the receiver.
+
+ The extended flags bit (bit 3) is eliminated. It MUST be set to 0
+ and MUST be ignored by the receiver.
+
+ The host/user bit (bit 6) is eliminated. It MUST be set to 0 and
+ MUST be ignored by the receiver.
+
+ The zone bit (bit 7) remains unchanged.
+
+ The signatory field (bits 12-15) are eliminated by [5]. They MUST
+ be set to 0 and MUST be ignored by the receiver.
+
+ Bits 2,4,5,8,9,10,11 remain unchanged. They are reserved, MUST be
+ set to zero and MUST be ignored by the receiver.
+
+ Assignment of any future KEY RR Flag values requires a standards
+ action.
+
+ All Protocol Octet values except DNSSEC (3) are eliminated:
+
+ Value 1 (Email) is renamed to RESERVED.
+
+ Value 2 (IPSEC) is renamed to RESERVED.
+
+ Value 3 (DNSSEC) is unchanged.
+
+ Value 4 (TLS) is renamed to RESERVED.
+
+ Value 5-254 remains unchanged (reserved).
+
+ Value 255 (ANY) is renamed to RESERVED.
+
+ The authoritative data for a zone MUST NOT include any KEY records
+ with a protocol octet other than 3. The registry maintained by IANA
+ for protocol values is closed for new assignments.
+
+ Name servers and resolvers SHOULD accept KEY RR sets that contain KEY
+ RRs with a value other than 3. If out of date DNS zones contain
+ deprecated KEY RRs with a protocol octet value other than 3, then
+ simply dropping the deprecated KEY RRs from the KEY RR set would
+
+
+
+Massey & Rose Standards Track [Page 6]
+
+RFC 3445 Limiting the KEY Resource Record (RR) December 2002
+
+
+ invalidate any associated SIG record(s) and could create caching
+ consistency problems. Note that KEY RRs with a protocol octet value
+ other than 3 MUST NOT be used to authenticate DNS data.
+
+ The algorithm and public key fields are not changed.
+
+5. Backward Compatibility
+
+ DNSSEC zone KEY RRs are not changed and remain backwards compatible.
+ A properly formatted RFC 2535 zone KEY would have all flag bits,
+ other than the Zone Bit (Bit 7), set to 0 and would have the Protocol
+ Octet set to 3. This remains true under the restricted KEY.
+
+ DNSSEC non-zone KEY RRs (SIG(0)/TKEY keys) are backwards compatible,
+ but the distinction between host and user keys (flag bit 6) is lost.
+
+ No backwards compatibility is provided for application keys. Any
+ Email, IPSEC, or TLS keys are now deprecated. Storing application
+ keys in the KEY RR created problems such as keys at the apex and
+ large RR sets and some change in the definition and/or usage of the
+ KEY RR would have been required even if the approach described here
+ were not adopted.
+
+ Overall, existing nameservers and resolvers will continue to
+ correctly process KEY RRs with a sub-type of DNSSEC keys.
+
+6. Storing Application Keys in the DNS
+
+ The scope of this document is strictly limited to the KEY record.
+ This document prohibits storing application keys in the KEY record,
+ but it does not endorse or restrict the storing application keys in
+ other record types. Other documents can describe how DNS handles
+ application keys.
+
+7. IANA Considerations
+
+ RFC 2535 created an IANA registry for DNS KEY RR Protocol Octet
+ values. Values 1, 2, 3, 4, and 255 were assigned by RFC 2535 and
+ values 5-254 were made available for assignment by IANA. This
+ document makes two sets of changes to this registry.
+
+ First, this document re-assigns DNS KEY RR Protocol Octet values 1,
+ 2, 4, and 255 to "reserved". DNS Key RR Protocol Octet Value 3
+ remains unchanged as "DNSSEC".
+
+
+
+
+
+
+
+Massey & Rose Standards Track [Page 7]
+
+RFC 3445 Limiting the KEY Resource Record (RR) December 2002
+
+
+ Second, new values are no longer available for assignment by IANA and
+ this document closes the IANA registry for DNS KEY RR Protocol Octet
+ Values. Assignment of any future KEY RR Protocol Octet values
+ requires a standards action.
+
+8. Security Considerations
+
+ This document eliminates potential security problems that could arise
+ due to the coupling of DNS zone keys and application keys. Prior to
+ the change described in this document, a correctly authenticated KEY
+ set could include both application keys and DNSSEC keys. This
+ document restricts the KEY RR to DNS security usage only. This is an
+ attempt to simplify the security model and make it less user-error
+ prone. If one of the application keys is compromised, it could be
+ used as a false zone key to create false DNS signatures (SIG
+ records). Resolvers that do not carefully check the KEY sub-type
+ could believe these false signatures and incorrectly authenticate DNS
+ data. With this change, application keys cannot appear in an
+ authenticated KEY set and this vulnerability is eliminated.
+
+ The format and correct usage of DNSSEC keys is not changed by this
+ document and no new security considerations are introduced.
+
+9. Normative References
+
+ [1] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [2] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [3] Eastlake, D., "Secret Key Establishment for DNS (TKEY RR)", RFC
+ 2930, September 2000.
+
+ [4] Eastlake, D., "DNS Request and Transaction Signatures
+ (SIG(0)s)", RFC 2931, September 2000.
+
+ [5] Wellington, B., "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+
+
+
+
+
+
+
+
+
+
+
+Massey & Rose Standards Track [Page 8]
+
+RFC 3445 Limiting the KEY Resource Record (RR) December 2002
+
+
+10. Authors' Addresses
+
+ Dan Massey
+ USC Information Sciences Institute
+ 3811 N. Fairfax Drive
+ Arlington, VA 22203
+ USA
+
+ EMail: masseyd@isi.edu
+
+
+ Scott Rose
+ National Institute for Standards and Technology
+ 100 Bureau Drive
+ Gaithersburg, MD 20899-3460
+ USA
+
+ EMail: scott.rose@nist.gov
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Massey & Rose Standards Track [Page 9]
+
+RFC 3445 Limiting the KEY Resource Record (RR) December 2002
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2002). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Massey & Rose Standards Track [Page 10]
+
diff --git a/doc/rfc/rfc3467.txt b/doc/rfc/rfc3467.txt
new file mode 100644
index 0000000..37ac7ec
--- /dev/null
+++ b/doc/rfc/rfc3467.txt
@@ -0,0 +1,1739 @@
+
+
+
+
+
+
+Network Working Group J. Klensin
+Request for Comments: 3467 February 2003
+Category: Informational
+
+
+ Role of the Domain Name System (DNS)
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ This document reviews the original function and purpose of the domain
+ name system (DNS). It contrasts that history with some of the
+ purposes for which the DNS has recently been applied and some of the
+ newer demands being placed upon it or suggested for it. A framework
+ for an alternative to placing these additional stresses on the DNS is
+ then outlined. This document and that framework are not a proposed
+ solution, only a strong suggestion that the time has come to begin
+ thinking more broadly about the problems we are encountering and
+ possible approaches to solving them.
+
+Table of Contents
+
+ 1. Introduction and History ..................................... 2
+ 1.1 Context for DNS Development ............................... 3
+ 1.2 Review of the DNS and Its Role as Designed ................ 4
+ 1.3 The Web and User-visible Domain Names ..................... 6
+ 1.4 Internet Applications Protocols and Their Evolution ....... 7
+ 2. Signs of DNS Overloading ..................................... 8
+ 3. Searching, Directories, and the DNS .......................... 12
+ 3.1 Overview ................................................. 12
+ 3.2 Some Details and Comments ................................. 14
+ 4. Internationalization ......................................... 15
+ 4.1 ASCII Isn't Just Because of English ....................... 16
+ 4.2 The "ASCII Encoding" Approaches ........................... 17
+ 4.3 "Stringprep" and Its Complexities ......................... 17
+ 4.4 The Unicode Stability Problem ............................. 19
+ 4.5 Audiences, End Users, and the User Interface Problem ...... 20
+ 4.6 Business Cards and Other Natural Uses of Natural Languages. 22
+ 4.7 ASCII Encodings and the Roman Keyboard Assumption ......... 22
+
+
+
+Klensin Informational [Page 1]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ 4.8 Intra-DNS Approaches for "Multilingual Names" ............. 23
+ 5. Search-based Systems: The Key Controversies .................. 23
+ 6. Security Considerations ...................................... 24
+ 7. References ................................................... 25
+ 7.1 Normative References ...................................... 25
+ 7.2 Explanatory and Informative References .................... 25
+ 8. Acknowledgements ............................................. 30
+ 9. Author's Address ............................................. 30
+ 10. Full Copyright Statement ..................................... 31
+
+1. Introduction and History
+
+ The DNS was designed as a replacement for the older "host table"
+ system. Both were intended to provide names for network resources at
+ a more abstract level than network (IP) addresses (see, e.g.,
+ [RFC625], [RFC811], [RFC819], [RFC830], [RFC882]). In recent years,
+ the DNS has become a database of convenience for the Internet, with
+ many proposals to add new features. Only some of these proposals
+ have been successful. Often the main (or only) motivation for using
+ the DNS is because it exists and is widely deployed, not because its
+ existing structure, facilities, and content are appropriate for the
+ particular application of data involved. This document reviews the
+ history of the DNS, including examination of some of those newer
+ applications. It then argues that the overloading process is often
+ inappropriate. Instead, it suggests that the DNS should be
+ supplemented by systems better matched to the intended applications
+ and outlines a framework and rationale for one such system.
+
+ Several of the comments that follow are somewhat revisionist. Good
+ design and engineering often requires a level of intuition by the
+ designers about things that will be necessary in the future; the
+ reasons for some of these design decisions are not made explicit at
+ the time because no one is able to articulate them. The discussion
+ below reconstructs some of the decisions about the Internet's primary
+ namespace (the "Class=IN" DNS) in the light of subsequent development
+ and experience. In addition, the historical reasons for particular
+ decisions about the Internet were often severely underdocumented
+ contemporaneously and, not surprisingly, different participants have
+ different recollections about what happened and what was considered
+ important. Consequently, the quasi-historical story below is just
+ one story. There may be (indeed, almost certainly are) other stories
+ about how the DNS evolved to its present state, but those variants do
+ not invalidate the inferences and conclusions.
+
+ This document presumes a general understanding of the terminology of
+ RFC 1034 [RFC1034] or of any good DNS tutorial (see, e.g., [Albitz]).
+
+
+
+
+
+Klensin Informational [Page 2]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+1.1 Context for DNS Development
+
+ During the entire post-startup-period life of the ARPANET and nearly
+ the first decade or so of operation of the Internet, the list of host
+ names and their mapping to and from addresses was maintained in a
+ frequently-updated "host table" [RFC625], [RFC811], [RFC952]. The
+ names themselves were restricted to a subset of ASCII [ASCII] chosen
+ to avoid ambiguities in printed form, to permit interoperation with
+ systems using other character codings (notably EBCDIC), and to avoid
+ the "national use" code positions of ISO 646 [IS646]. These
+ restrictions later became collectively known as the "LDH" rules for
+ "letter-digit-hyphen", the permitted characters. The table was just
+ a list with a common format that was eventually agreed upon; sites
+ were expected to frequently obtain copies of, and install, new
+ versions. The host tables themselves were introduced to:
+
+ o Eliminate the requirement for people to remember host numbers
+ (addresses). Despite apparent experience to the contrary in the
+ conventional telephone system, numeric numbering systems,
+ including the numeric host number strategy, did not (and do not)
+ work well for more than a (large) handful of hosts.
+
+ o Provide stability when addresses changed. Since addresses -- to
+ some degree in the ARPANET and more importantly in the
+ contemporary Internet -- are a function of network topology and
+ routing, they often had to be changed when connectivity or
+ topology changed. The names could be kept stable even as
+ addresses changed.
+
+ o Provide the capability to have multiple addresses associated with
+ a given host to reflect different types of connectivity and
+ topology. Use of names, rather than explicit addresses, avoided
+ the requirement that would otherwise exist for users and other
+ hosts to track these multiple host numbers and addresses and the
+ topological considerations for selecting one over others.
+
+ After several years of using the host table approach, the community
+ concluded that model did not scale adequately and that it would not
+ adequately support new service variations. A number of discussions
+ and meetings were held which drew several ideas and incomplete
+ proposals together. The DNS was the result of that effort. It
+ continued to evolve during the design and initial implementation
+ period, with a number of documents recording the changes (see
+ [RFC819], [RFC830], and [RFC1034]).
+
+
+
+
+
+
+
+Klensin Informational [Page 3]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ The goals for the DNS included:
+
+ o Preservation of the capabilities of the host table arrangements
+ (especially unique, unambiguous, host names),
+
+ o Provision for addition of additional services (e.g., the special
+ record types for electronic mail routing which quickly followed
+ introduction of the DNS), and
+
+ o Creation of a robust, hierarchical, distributed, name lookup
+ system to accomplish the other goals.
+
+ The DNS design also permitted distribution of name administration,
+ rather than requiring that each host be entered into a single,
+ central, table by a central administration.
+
+1.2 Review of the DNS and Its Role as Designed
+
+ The DNS was designed to identify network resources. Although there
+ was speculation about including, e.g., personal names and email
+ addresses, it was not designed primarily to identify people, brands,
+ etc. At the same time, the system was designed with the flexibility
+ to accommodate new data types and structures, both through the
+ addition of new record types to the initial "INternet" class, and,
+ potentially, through the introduction of new classes. Since the
+ appropriate identifiers and content of those future extensions could
+ not be anticipated, the design provided that these fields could
+ contain any (binary) information, not just the restricted text forms
+ of the host table.
+
+ However, the DNS, as it is actually used, is intimately tied to the
+ applications and application protocols that utilize it, often at a
+ fairly low level.
+
+ In particular, despite the ability of the protocols and data
+ structures themselves to accommodate any binary representation, DNS
+ names as used were historically not even unrestricted ASCII, but a
+ very restricted subset of it, a subset that derives from the original
+ host table naming rules. Selection of that subset was driven in part
+ by human factors considerations, including a desire to eliminate
+ possible ambiguities in an international context. Hence character
+ codes that had international variations in interpretation were
+ excluded, the underscore character and case distinctions were
+ eliminated as being confusing (in the underscore's case, with the
+ hyphen character) when written or read by people, and so on. These
+ considerations appear to be very similar to those that resulted in
+ similarly restricted character sets being used as protocol elements
+ in many ITU and ISO protocols (cf. [X29]).
+
+
+
+Klensin Informational [Page 4]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ Another assumption was that there would be a high ratio of physical
+ hosts to second level domains and, more generally, that the system
+ would be deeply hierarchical, with most systems (and names) at the
+ third level or below and a very large percentage of the total names
+ representing physical hosts. There are domains that follow this
+ model: many university and corporate domains use fairly deep
+ hierarchies, as do a few country-oriented top level domains
+ ("ccTLDs"). Historically, the "US." domain has been an excellent
+ example of the deeply hierarchical approach. However, by 1998,
+ comparison of several efforts to survey the DNS showed a count of SOA
+ records that approached (and may have passed) the number of distinct
+ hosts. Looked at differently, we appear to be moving toward a
+ situation in which the number of delegated domains on the Internet is
+ approaching or exceeding the number of hosts, or at least the number
+ of hosts able to provide services to others on the network. This
+ presumably results from synonyms or aliases that map a great many
+ names onto a smaller number of hosts. While experience up to this
+ time has shown that the DNS is robust enough -- given contemporary
+ machines as servers and current bandwidth norms -- to be able to
+ continue to operate reasonably well when those historical assumptions
+ are not met (e.g., with a flat, structure under ".COM" containing
+ well over ten million delegated subdomains [COMSIZE]), it is still
+ useful to remember that the system could have been designed to work
+ optimally with a flat structure (and very large zones) rather than a
+ deeply hierarchical one, and was not.
+
+ Similarly, despite some early speculation about entering people's
+ names and email addresses into the DNS directly (e.g., see
+ [RFC1034]), electronic mail addresses in the Internet have preserved
+ the original, pre-DNS, "user (or mailbox) at location" conceptual
+ format rather than a flatter or strictly dot-separated one.
+ Location, in that instance, is a reference to a host. The sole
+ exception, at least in the "IN" class, has been one field of the SOA
+ record.
+
+ Both the DNS architecture itself and the two-level (host name and
+ mailbox name) provisions for email and similar functions (e.g., see
+ the finger protocol [FINGER]), also anticipated a relatively high
+ ratio of users to actual hosts. Despite the observation in RFC 1034
+ that the DNS was expected to grow to be proportional to the number of
+ users (section 2.3), it has never been clear that the DNS was
+ seriously designed for, or could, scale to the order of magnitude of
+ number of users (or, more recently, products or document objects),
+ rather than that of physical hosts.
+
+ Just as was the case for the host table before it, the DNS provided
+ critical uniqueness for names, and universal accessibility to them,
+ as part of overall "single internet" and "end to end" models (cf.
+
+
+
+Klensin Informational [Page 5]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ [RFC2826]). However, there are many signs that, as new uses evolved
+ and original assumptions were abused (if not violated outright), the
+ system was being stretched to, or beyond, its practical limits.
+
+ The original design effort that led to the DNS included examination
+ of the directory technologies available at the time. The design
+ group concluded that the DNS design, with its simplifying assumptions
+ and restricted capabilities, would be feasible to deploy and make
+ adequately robust, which the more comprehensive directory approaches
+ were not. At the same time, some of the participants feared that the
+ limitations might cause future problems; this document essentially
+ takes the position that they were probably correct. On the other
+ hand, directory technology and implementations have evolved
+ significantly in the ensuing years: it may be time to revisit the
+ assumptions, either in the context of the two- (or more) level
+ mechanism contemplated by the rest of this document or, even more
+ radically, as a path toward a DNS replacement.
+
+1.3 The Web and User-visible Domain Names
+
+ From the standpoint of the integrity of the domain name system -- and
+ scaling of the Internet, including optimal accessibility to content
+ -- the web design decision to use "A record" domain names directly in
+ URLs, rather than some system of indirection, has proven to be a
+ serious mistake in several respects. Convenience of typing, and the
+ desire to make domain names out of easily-remembered product names,
+ has led to a flattening of the DNS, with many people now perceiving
+ that second-level names under COM (or in some countries, second- or
+ third-level names under the relevant ccTLD) are all that is
+ meaningful. This perception has been reinforced by some domain name
+ registrars [REGISTRAR] who have been anxious to "sell" additional
+ names. And, of course, the perception that one needed a second-level
+ (or even top-level) domain per product, rather than having names
+ associated with a (usually organizational) collection of network
+ resources, has led to a rapid acceleration in the number of names
+ being registered. That acceleration has, in turn, clearly benefited
+ registrars charging on a per-name basis, "cybersquatters", and others
+ in the business of "selling" names, but it has not obviously
+ benefited the Internet as a whole.
+
+ This emphasis on second-level domain names has also created a problem
+ for the trademark community. Since the Internet is international,
+ and names are being populated in a flat and unqualified space,
+ similarly-named entities are in conflict even if there would
+ ordinarily be no chance of confusing them in the marketplace. The
+ problem appears to be unsolvable except by a choice between draconian
+ measures. These might include significant changes to the legislation
+ and conventions that govern disputes over "names" and "marks". Or
+
+
+
+Klensin Informational [Page 6]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ they might result in a situation in which the "rights" to a name are
+ typically not settled using the subtle and traditional product (or
+ industry) type and geopolitical scope rules of the trademark system.
+ Instead they have depended largely on political or economic power,
+ e.g., the organization with the greatest resources to invest in
+ defending (or attacking) names will ultimately win out. The latter
+ raises not only important issues of equity, but also the risk of
+ backlash as the numerous small players are forced to relinquish names
+ they find attractive and to adopt less-desirable naming conventions.
+
+ Independent of these sociopolitical problems, content distribution
+ issues have made it clear that it should be possible for an
+ organization to have copies of data it wishes to make available
+ distributed around the network, with a user who asks for the
+ information by name getting the topologically-closest copy. This is
+ not possible with simple, as-designed, use of the DNS: DNS names
+ identify target resources or, in the case of email "MX" records, a
+ preferentially-ordered list of resources "closest" to a target (not
+ to the source/user). Several technologies (and, in some cases,
+ corresponding business models) have arisen to work around these
+ problems, including intercepting and altering DNS requests so as to
+ point to other locations.
+
+ Additional implications are still being discovered and evaluated.
+
+ Approaches that involve interception of DNS queries and rewriting of
+ DNS names (or otherwise altering the resolution process based on the
+ topological location of the user) seem, however, to risk disrupting
+ end-to-end applications in the general case and raise many of the
+ issues discussed by the IAB in [IAB-OPES]. These problems occur even
+ if the rewriting machinery is accompanied by additional workarounds
+ for particular applications. For example, security associations and
+ applications that need to identify "the same host" often run into
+ problems if DNS names or other references are changed in the network
+ without participation of the applications that are trying to invoke
+ the associated services.
+
+1.4 Internet Applications Protocols and Their Evolution
+
+ At the applications level, few of the protocols in active,
+ widespread, use on the Internet reflect either contemporary knowledge
+ in computer science or human factors or experience accumulated
+ through deployment and use. Instead, protocols tend to be deployed
+ at a just-past-prototype level, typically including the types of
+ expedient compromises typical with prototypes. If they prove useful,
+ the nature of the network permits very rapid dissemination (i.e.,
+ they fill a vacuum, even if a vacuum that no one previously knew
+ existed). But, once the vacuum is filled, the installed base
+
+
+
+Klensin Informational [Page 7]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ provides its own inertia: unless the design is so seriously faulty as
+ to prevent effective use (or there is a widely-perceived sense of
+ impending disaster unless the protocol is replaced), future
+ developments must maintain backward compatibility and workarounds for
+ problematic characteristics rather than benefiting from redesign in
+ the light of experience. Applications that are "almost good enough"
+ prevent development and deployment of high-quality replacements.
+
+ The DNS is both an illustration of, and an exception to, parts of
+ this pessimistic interpretation. It was a second-generation
+ development, with the host table system being seen as at the end of
+ its useful life. There was a serious attempt made to reflect the
+ computing state of the art at the time. However, deployment was much
+ slower than expected (and very painful for many sites) and some fixed
+ (although relaxed several times) deadlines from a central network
+ administration were necessary for deployment to occur at all.
+ Replacing it now, in order to add functionality, while it continues
+ to perform its core functions at least reasonably well, would
+ presumably be extremely difficult.
+
+ There are many, perhaps obvious, examples of this. Despite many
+ known deficiencies and weaknesses of definition, the "finger" and
+ "whois" [WHOIS] protocols have not been replaced (despite many
+ efforts to update or replace the latter [WHOIS-UPDATE]). The Telnet
+ protocol and its many options drove out the SUPDUP [RFC734] one,
+ which was arguably much better designed for a diverse collection of
+ network hosts. A number of efforts to replace the email or file
+ transfer protocols with models which their advocates considered much
+ better have failed. And, more recently and below the applications
+ level, there is some reason to believe that this resistance to change
+ has been one of the factors impeding IPv6 deployment.
+
+2. Signs of DNS Overloading
+
+ Parts of the historical discussion above identify areas in which the
+ DNS has become overloaded (semantically if not in the mechanical
+ ability to resolve names). Despite this overloading, it appears that
+ DNS performance and reliability are still within an acceptable range:
+ there is little evidence of serious performance degradation. Recent
+ proposals and mechanisms to better respond to overloading and scaling
+ issues have all focused on patching or working around limitations
+ that develop when the DNS is utilized for out-of-design functions,
+ rather than on dramatic rethinking of either DNS design or those
+ uses. The number of these issues that have arisen at much the same
+ time may argue for just that type of rethinking, and not just for
+ adding complexity and attempting to incrementally alter the design
+ (see, for example, the discussion of simplicity in section 2 of
+ [RFC3439]).
+
+
+
+Klensin Informational [Page 8]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ For example:
+
+ o While technical approaches such as larger and higher-powered
+ servers and more bandwidth, and legal/political mechanisms such as
+ dispute resolution policies, have arguably kept the problems from
+ becoming critical, the DNS has not proven adequately responsive to
+ business and individual needs to describe or identify things (such
+ as product names and names of individuals) other than strict
+ network resources.
+
+ o While stacks have been modified to better handle multiple
+ addresses on a physical interface and some protocols have been
+ extended to include DNS names for determining context, the DNS
+ does not deal especially well with many names associated with a
+ given host (e.g., web hosting facilities with multiple domains on
+ a server).
+
+ o Efforts to add names deriving from languages or character sets
+ based on other than simple ASCII and English-like names (see
+ below), or even to utilize complex company or product names
+ without the use of hierarchy, have created apparent requirements
+ for names (labels) that are over 63 octets long. This requirement
+ will undoubtedly increase over time; while there are workarounds
+ to accommodate longer names, they impose their own restrictions
+ and cause their own problems.
+
+ o Increasing commercialization of the Internet, and visibility of
+ domain names that are assumed to match names of companies or
+ products, has turned the DNS and DNS names into a trademark
+ battleground. The traditional trademark system in (at least) most
+ countries makes careful distinctions about fields of
+ applicability. When the space is flattened, without
+ differentiation by either geography or industry sector, not only
+ are there likely conflicts between "Joe's Pizza" (of Boston) and
+ "Joe's Pizza" (of San Francisco) but between both and "Joe's Auto
+ Repair" (of Los Angeles). All three would like to control
+ "Joes.com" (and would prefer, if it were permitted by DNS naming
+ rules, to also spell it as "Joe's.com" and have both resolve the
+ same way) and may claim trademark rights to do so, even though
+ conflict or confusion would not occur with traditional trademark
+ principles.
+
+ o Many organizations wish to have different web sites under the same
+ URL and domain name. Sometimes this is to create local variations
+ -- the Widget Company might want to present different material to
+ a UK user relative to a US one -- and sometimes it is to provide
+ higher performance by supplying information from the server
+ topologically closest to the user. If the name resolution
+
+
+
+Klensin Informational [Page 9]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ mechanism is expected to provide this functionality, there are
+ three possible models (which might be combined):
+
+ - supply information about multiple sites (or locations or
+ references). Those sites would, in turn, provide information
+ associated with the name and sufficient site-specific
+ attributes to permit the application to make a sensible choice
+ of destination, or
+
+ - accept client-site attributes and utilize them in the search
+ process, or
+
+ - return different answers based on the location or identity of
+ the requestor.
+
+ While there are some tricks that can provide partial simulations of
+ these types of function, DNS responses cannot be reliably conditioned
+ in this way.
+
+ These, and similar, issues of performance or content choices can, of
+ course, be thought of as not involving the DNS at all. For example,
+ the commonly-cited alternate approach of coupling these issues to
+ HTTP content negotiation (cf. [RFC2295]), requires that an HTTP
+ connection first be opened to some "common" or "primary" host so that
+ preferences can be negotiated and then the client redirected or sent
+ alternate data. At least from the standpoint of improving
+ performance by accessing a "closer" location, both initially and
+ thereafter, this approach sacrifices the desired result before the
+ client initiates any action. It could even be argued that some of
+ the characteristics of common content negotiation approaches are
+ workarounds for the non-optimal use of the DNS in web URLs.
+
+ o Many existing and proposed systems for "finding things on the
+ Internet" require a true search capability in which near matches
+ can be reported to the user (or to some user agent with an
+ appropriate rule-set) and to which queries may be ambiguous or
+ fuzzy. The DNS, by contrast, can accommodate only one set of
+ (quite rigid) matching rules. Proposals to permit different rules
+ in different localities (e.g., matching rules that are TLD- or
+ zone-specific) help to identify the problem. But they cannot be
+ applied directly to the DNS without either abandoning the desired
+ level of flexibility or isolating different parts of the Internet
+ from each other (or both). Fuzzy or ambiguous searches are
+ desirable for resolution of names that might have spelling
+ variations and for names that can be resolved into different sets
+ of glyphs depending on context. Especially when
+ internationalization is considered, variant name problems go
+ beyond simple differences in representation of a character or
+
+
+
+Klensin Informational [Page 10]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ ordering of a string. Instead, avoiding user astonishment and
+ confusion requires consideration of relationships such as
+ languages that can be written with different alphabets, Kanji-
+ Hiragana relationships, Simplified and Traditional Chinese, etc.
+ See [Seng] for a discussion and suggestions for addressing a
+ subset of these issues in the context of characters based on
+ Chinese ones. But that document essentially illustrates the
+ difficulty of providing the type of flexible matching that would
+ be anticipated by users; instead, it tries to protect against the
+ worst types of confusion (and opportunities for fraud).
+
+ o The historical DNS, and applications that make assumptions about
+ how it works, impose significant risk (or forces technical kludges
+ and consequent odd restrictions), when one considers adding
+ mechanisms for use with various multi-character-set and
+ multilingual "internationalization" systems. See the IAB's
+ discussion of some of these issues [RFC2825] for more information.
+
+ o In order to provide proper functionality to the Internet, the DNS
+ must have a single unique root (the IAB provides more discussion
+ of this issue [RFC2826]). There are many desires for local
+ treatment of names or character sets that cannot be accommodated
+ without either multiple roots (e.g., a separate root for
+ multilingual names, proposed at various times by MINC [MINC] and
+ others), or mechanisms that would have similar effects in terms of
+ Internet fragmentation and isolation.
+
+ o For some purposes, it is desirable to be able to search not only
+ an index entry (labels or fully-qualified names in the DNS case),
+ but their values or targets (DNS data). One might, for example,
+ want to locate all of the host (and virtual host) names which
+ cause mail to be directed to a given server via MX records. The
+ DNS does not support this capability (see the discussion in
+ [IQUERY]) and it can be simulated only by extracting all of the
+ relevant records (perhaps by zone transfer if the source permits
+ doing so, but that permission is becoming less frequently
+ available) and then searching a file built from those records.
+
+ o Finally, as additional types of personal or identifying
+ information are added to the DNS, issues arise with protection of
+ that information. There are increasing calls to make different
+ information available based on the credentials and authorization
+ of the source of the inquiry. As with information keyed to site
+ locations or proximity (as discussed above), the DNS protocols
+ make providing these differentiated services quite difficult if
+ not impossible.
+
+
+
+
+
+Klensin Informational [Page 11]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ In each of these cases, it is, or might be, possible to devise ways
+ to trick the DNS system into supporting mechanisms that were not
+ designed into it. Several ingenious solutions have been proposed in
+ many of these areas already, and some have been deployed into the
+ marketplace with some success. But the price of each of these
+ changes is added complexity and, with it, added risk of unexpected
+ and destabilizing problems.
+
+ Several of the above problems are addressed well by a good directory
+ system (supported by the LDAP protocol or some protocol more
+ precisely suited to these specific applications) or searching
+ environment (such as common web search engines) although not by the
+ DNS. Given the difficulty of deploying new applications discussed
+ above, an important question is whether the tricks and kludges are
+ bad enough, or will become bad enough as usage grows, that new
+ solutions are needed and can be deployed.
+
+3. Searching, Directories, and the DNS
+
+3.1 Overview
+
+ The constraints of the DNS and the discussion above suggest the
+ introduction of an intermediate protocol mechanism, referred to below
+ as a "search layer" or "searchable system". The terms "directory"
+ and "directory system" are used interchangeably with "searchable
+ system" in this document, although the latter is far more precise.
+ Search layer proposals would use a two (or more) stage lookup, not
+ unlike several of the proposals for internationalized names in the
+ DNS (see section 4), but all operations but the final one would
+ involve searching other systems, rather than looking up identifiers
+ in the DNS itself. As explained below, this would permit relaxation
+ of several constraints, leading to a more capable and comprehensive
+ overall system.
+
+ Ultimately, many of the issues with domain names arise as the result
+ of efforts to use the DNS as a directory. While, at the time this
+ document was written, sufficient pressure or demand had not occurred
+ to justify a change, it was already quite clear that, as a directory
+ system, the DNS is a good deal less than ideal. This document
+ suggests that there actually is a requirement for a directory system,
+ and that the right solution to a searchable system requirement is a
+ searchable system, not a series of DNS patches, kludges, or
+ workarounds.
+
+
+
+
+
+
+
+
+Klensin Informational [Page 12]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ The following points illustrate particular aspects of this
+ conclusion.
+
+ o A directory system would not require imposition of particular
+ length limits on names.
+
+ o A directory system could permit explicit association of
+ attributes, e.g., language and country, with a name, without
+ having to utilize trick encodings to incorporate that information
+ in DNS labels (or creating artificial hierarchy for doing so).
+
+ o There is considerable experience (albeit not much of it very
+ successful) in doing fuzzy and "sonex" (similar-sounding) matching
+ in directory systems. Moreover, it is plausible to think about
+ different matching rules for different areas and sets of names so
+ that these can be adapted to local cultural requirements.
+ Specifically, it might be possible to have a single form of a name
+ in a directory, but to have great flexibility about what queries
+ matched that name (and even have different variations in different
+ areas). Of course, the more flexibility that a system provides,
+ the greater the possibility of real or imagined trademark
+ conflicts. But the opportunity would exist to design a directory
+ structure that dealt with those issues in an intelligent way,
+ while DNS constraints almost certainly make a general and
+ equitable DNS-only solution impossible.
+
+ o If a directory system is used to translate to DNS names, and then
+ DNS names are looked up in the normal fashion, it may be possible
+ to relax several of the constraints that have been traditional
+ (and perhaps necessary) with the DNS. For example, reverse-
+ mapping of addresses to directory names may not be a requirement
+ even if mapping of addresses to DNS names continues to be, since
+ the DNS name(s) would (continue to) uniquely identify the host.
+
+ o Solutions to multilingual transcription problems that are common
+ in "normal life" (e.g., two-sided business cards to be sure that
+ recipients trying to contact a person can access romanized
+ spellings and numbers if the original language is not
+ comprehensible to them) can be easily handled in a directory
+ system by inserting both sets of entries.
+
+ o A directory system could be designed that would return, not a
+ single name, but a set of names paired with network-locational
+ information or other context-establishing attributes. This type
+ of information might be of considerable use in resolving the
+ "nearest (or best) server for a particular named resource"
+
+
+
+
+
+Klensin Informational [Page 13]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ problems that are a significant concern for organizations hosting
+ web and other sites that are accessed from a wide range of
+ locations and subnets.
+
+ o Names bound to countries and languages might help to manage
+ trademark realities, while, as discussed in section 1.3 above, use
+ of the DNS in trademark-significant contexts tends to require
+ worldwide "flattening" of the trademark system.
+
+ Many of these issues are a consequence of another property of the
+ DNS: names must be unique across the Internet. The need to have a
+ system of unique identifiers is fairly obvious (see [RFC2826]).
+ However, if that requirement were to be eliminated in a search or
+ directory system that was visible to users instead of the DNS, many
+ difficult problems -- of both an engineering and a policy nature --
+ would be likely to vanish.
+
+3.2 Some Details and Comments
+
+ Almost any internationalization proposal for names that are in, or
+ map into, the DNS will require changing DNS resolver API calls
+ ("gethostbyname" or equivalent), or adding some pre-resolution
+ preparation mechanism, in almost all Internet applications -- whether
+ to cause the API to take a different character set (no matter how it
+ is then mapped into the bits used in the DNS or another system), to
+ accept or return more arguments with qualifying or identifying
+ information, or otherwise. Once applications must be opened to make
+ such changes, it is a relatively small matter to switch from calling
+ into the DNS to calling a directory service and then the DNS (in many
+ situations, both actions could be accomplished in a single API call).
+
+ A directory approach can be consistent both with "flat" models and
+ multi-attribute ones. The DNS requires strict hierarchies, limiting
+ its ability to differentiate among names by their properties. By
+ contrast, modern directories can utilize independently-searched
+ attributes and other structured schema to provide flexibilities not
+ present in a strictly hierarchical system.
+
+ There is a strong historical argument for a single directory
+ structure (implying a need for mechanisms for registration,
+ delegation, etc.). But a single structure is not a strict
+ requirement, especially if in-depth case analysis and design work
+ leads to the conclusion that reverse-mapping to directory names is
+ not a requirement (see section 5). If a single structure is not
+ needed, then, unlike the DNS, there would be no requirement for a
+ global organization to authorize or delegate operation of portions of
+ the structure.
+
+
+
+
+Klensin Informational [Page 14]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ The "no single structure" concept could be taken further by moving
+ away from simple "names" in favor of, e.g., multiattribute,
+ multihierarchical, faceted systems in which most of the facets use
+ restricted vocabularies. (These terms are fairly standard in the
+ information retrieval and classification system literature, see,
+ e.g., [IS5127].) Such systems could be designed to avoid the need
+ for procedures to ensure uniqueness across, or even within, providers
+ and databases of the faceted entities for which the search is to be
+ performed. (See [DNS-Search] for further discussion.)
+
+ While the discussion above includes very general comments about
+ attributes, it appears that only a very small number of attributes
+ would be needed. The list would almost certainly include country and
+ language for internationalization purposes. It might require
+ "charset" if we cannot agree on a character set and encoding,
+ although there are strong arguments for simply using ISO 10646 (also
+ known as Unicode or "UCS" (for Universal Character Set) [UNICODE],
+ [IS10646] coding in interchange. Trademark issues might motivate
+ "commercial" and "non-commercial" (or other) attributes if they would
+ be helpful in bypassing trademark problems. And applications to
+ resource location, such as those contemplated for Uniform Resource
+ Identifiers (URIs) [RFC2396, RFC3305] or the Service Location
+ Protocol [RFC2608], might argue for a few other attributes (as
+ outlined above).
+
+4. Internationalization
+
+ Much of the thinking underlying this document was driven by
+ considerations of internationalizing the DNS or, more specifically,
+ providing access to the functions of the DNS from languages and
+ naming systems that cannot be accurately expressed in the traditional
+ DNS subset of ASCII. Much of the relevant work was done in the
+ IETF's "Internationalized Domain Names" Working Group (IDN-WG),
+ although this document also draws on extensive parallel discussions
+ in other forums. This section contains an evaluation of what was
+ learned as an "internationalized DNS" or "multilingual DNS" was
+ explored and suggests future steps based on that evaluation.
+
+ When the IDN-WG was initiated, it was obvious to several of the
+ participants that its first important task was an undocumented one:
+ to increase the understanding of the complexities of the problem
+ sufficiently that naive solutions could be rejected and people could
+ go to work on the harder problems. The IDN-WG clearly accomplished
+ that task. The beliefs that the problems were simple, and in the
+ corresponding simplistic approaches and their promises of quick and
+ painless deployment, effectively disappeared as the WG's efforts
+ matured.
+
+
+
+
+Klensin Informational [Page 15]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ Some of the lessons learned from increased understanding and the
+ dissipation of naive beliefs should be taken as cautions by the wider
+ community: the problems are not simple. Specifically, extracting
+ small elements for solution rather than looking at whole systems, may
+ result in obscuring the problems but not solving any problem that is
+ worth the trouble.
+
+4.1 ASCII Isn't Just Because of English
+
+ The hostname rules chosen in the mid-70s weren't just "ASCII because
+ English uses ASCII", although that was a starting point. We have
+ discovered that almost every other script (and even ASCII if we
+ permit the rest of the characters specified in the ISO 646
+ International Reference Version) is more complex than hostname-
+ restricted-ASCII (the "LDH" form, see section 1.1). And ASCII isn't
+ sufficient to completely represent English -- there are several words
+ in the language that are correctly spelled only with characters or
+ diacritical marks that do not appear in ASCII. With a broader
+ selection of scripts, in some examples, case mapping works from one
+ case to the other but is not reversible. In others, there are
+ conventions about alternate ways to represent characters (in the
+ language, not [only] in character coding) that work most of the time,
+ but not always. And there are issues in coding, with Unicode/10646
+ providing different ways to represent the same character
+ ("character", rather than "glyph", is used deliberately here). And,
+ in still others, there are questions as to whether two glyphs
+ "match", which may be a distance-function question, not one with a
+ binary answer. The IETF approach to these problems is to require
+ pre-matching canonicalization (see the "stringprep" discussion
+ below).
+
+ The IETF has resisted the temptations to either try to specify an
+ entirely new coded character set, or to pick and choose Unicode/10646
+ characters on a per-character basis rather than by using well-defined
+ blocks. While it may appear that a character set designed to meet
+ Internet-specific needs would be very attractive, the IETF has never
+ had the expertise, resources, and representation from critically-
+ important communities to actually take on that job. Perhaps more
+ important, a new effort might have chosen to make some of the many
+ complex tradeoffs differently than the Unicode committee did,
+ producing a code with somewhat different characteristics. But there
+ is no evidence that doing so would produce a code with fewer problems
+ and side-effects. It is much more likely that making tradeoffs
+ differently would simply result in a different set of problems, which
+ would be equally or more difficult.
+
+
+
+
+
+
+Klensin Informational [Page 16]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+4.2 The "ASCII Encoding" Approaches
+
+ While the DNS can handle arbitrary binary strings without known
+ internal problems (see [RFC2181]), some restrictions are imposed by
+ the requirement that text be interpreted in a case-independent way
+ ([RFC1034], [RFC1035]). More important, most internet applications
+ assume the hostname-restricted "LDH" syntax that is specified in the
+ host table RFCs and as "prudent" in RFC 1035. If those assumptions
+ are not met, many conforming implementations of those applications
+ may exhibit behavior that would surprise implementors and users. To
+ avoid these potential problems, IETF internationalization work has
+ focused on "ASCII-Compatible Encodings" (ACE). These encodings
+ preserve the LDH conventions in the DNS itself. Implementations of
+ applications that have not been upgraded utilize the encoded forms,
+ while newer ones can be written to recognize the special codings and
+ map them into non-ASCII characters. These approaches are, however,
+ not problem-free even if human interface issues are ignored. Among
+ other issues, they rely on what is ultimately a heuristic to
+ determine whether a DNS label is to be considered as an
+ internationalized name (i.e., encoded Unicode) or interpreted as an
+ actual LDH name in its own right. And, while all determinations of
+ whether a particular query matches a stored object are traditionally
+ made by DNS servers, the ACE systems, when combined with the
+ complexities of international scripts and names, require that much of
+ the matching work be separated into a separate, client-side,
+ canonicalization or "preparation" process before the DNS matching
+ mechanisms are invoked [STRINGPREP].
+
+4.3 "Stringprep" and Its Complexities
+
+ As outlined above, the model for avoiding problems associated with
+ putting non-ASCII names in the DNS and elsewhere evolved into the
+ principle that strings are to be placed into the DNS only after being
+ passed through a string preparation function that eliminates or
+ rejects spurious character codes, maps some characters onto others,
+ performs some sequence canonicalization, and generally creates forms
+ that can be accurately compared. The impact of this process on
+ hostname-restricted ASCII (i.e., "LDH") strings is trivial and
+ essentially adds only overhead. For other scripts, the impact is, of
+ necessity, quite significant.
+
+ Although the general notion underlying stringprep is simple, the many
+ details are quite subtle and the associated tradeoffs are complex. A
+ design team worked on it for months, with considerable effort placed
+ into clarifying and fine-tuning the protocol and tables. Despite
+ general agreement that the IETF would avoid getting into the business
+ of defining character sets, character codings, and the associated
+ conventions, the group several times considered and rejected special
+
+
+
+Klensin Informational [Page 17]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ treatment of code positions to more nearly match the distinctions
+ made by Unicode with user perceptions about similarities and
+ differences between characters. But there were intense temptations
+ (and pressures) to incorporate language-specific or country-specific
+ rules. Those temptations, even when resisted, were indicative of
+ parts of the ongoing controversy or of the basic unsuitability of the
+ DNS for fully internationalized names that are visible,
+ comprehensible, and predictable for end users.
+
+ There have also been controversies about how far one should go in
+ these processes of preparation and transformation and, ultimately,
+ about the validity of various analogies. For example, each of the
+ following operations has been claimed to be similar to case-mapping
+ in ASCII:
+
+ o stripping of vowels in Arabic or Hebrew
+
+ o matching of "look-alike" characters such as upper-case Alpha in
+ Greek and upper-case A in Roman-based alphabets
+
+ o matching of Traditional and Simplified Chinese characters that
+ represent the same words,
+
+ o matching of Serbo-Croatian words whether written in Roman-derived
+ or Cyrillic characters
+
+ A decision to support any of these operations would have implications
+ for other scripts or languages and would increase the overall
+ complexity of the process. For example, unless language-specific
+ information is somehow available, performing matching between
+ Traditional and Simplified Chinese has impacts on Japanese and Korean
+ uses of the same "traditional" characters (e.g., it would not be
+ appropriate to map Kanji into Simplified Chinese).
+
+ Even were the IDN-WG's other work to have been abandoned completely
+ or if it were to fail in the marketplace, the stringprep and nameprep
+ work will continue to be extremely useful, both in identifying issues
+ and problem code points and in providing a reasonable set of basic
+ rules. Where problems remain, they are arguably not with nameprep,
+ but with the DNS-imposed requirement that its results, as with all
+ other parts of the matching and comparison process, yield a binary
+ "match or no match" answer, rather than, e.g., a value on a
+ similarity scale that can be evaluated by the user or by user-driven
+ heuristic functions.
+
+
+
+
+
+
+
+Klensin Informational [Page 18]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+4.4 The Unicode Stability Problem
+
+ ISO 10646 basically defines only code points, and not rules for using
+ or comparing the characters. This is part of a long-standing
+ tradition with the work of what is now ISO/IEC JTC1/SC2: they have
+ performed code point assignments and have typically treated the ways
+ in which characters are used as beyond their scope. Consequently,
+ they have not dealt effectively with the broader range of
+ internationalization issues. By contrast, the Unicode Technical
+ Committee (UTC) has defined, in annexes and technical reports (see,
+ e.g., [UTR15]), some additional rules for canonicalization and
+ comparison. Many of those rules and conventions have been factored
+ into the "stringprep" and "nameprep" work, but it is not
+ straightforward to make or define them in a fashion that is
+ sufficiently precise and permanent to be relied on by the DNS.
+
+ Perhaps more important, the discussions leading to nameprep also
+ identified several areas in which the UTC definitions are inadequate,
+ at least without additional information, to make matching precise and
+ unambiguous. In some of these cases, the Unicode Standard permits
+ several alternate approaches, none of which are an exact and obvious
+ match to DNS needs. That has left these sensitive choices up to
+ IETF, which lacks sufficient in-depth expertise, much less any
+ mechanism for deciding to optimize one language at the expense of
+ another.
+
+ For example, it is tempting to define some rules on the basis of
+ membership in particular scripts, or for punctuation characters, but
+ there is no precise definition of what characters belong to which
+ script or which ones are, or are not, punctuation. The existence of
+ these areas of vagueness raises two issues: whether trying to do
+ precise matching at the character set level is actually possible
+ (addressed below) and whether driving toward more precision could
+ create issues that cause instability in the implementation and
+ resolution models for the DNS.
+
+ The Unicode definition also evolves. Version 3.2 appeared shortly
+ after work on this document was initiated. It added some characters
+ and functionality and included a few minor incompatible code point
+ changes. IETF has secured an agreement about constraints on future
+ changes, but it remains to be seen how that agreement will work out
+ in practice. The prognosis actually appears poor at this stage,
+ since UTC chose to ballot a recent possible change which should have
+ been prohibited by the agreement (the outcome of the ballot is not
+ relevant, only that the ballot was issued rather than having the
+ result be a foregone conclusion). However, some members of the
+ community consider some of the changes between Unicode 3.0 and 3.1
+ and between 3.1 and 3.2, as well as this recent ballot, to be
+
+
+
+Klensin Informational [Page 19]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ evidence of instability and that these instabilities are better
+ handled in a system that can be more flexible about handling of
+ characters, scripts, and ancillary information than the DNS.
+
+ In addition, because the systems implications of internationalization
+ are considered out of scope in SC2, ISO/IEC JTC1 has assigned some of
+ those issues to its SC22/WG20 (the Internationalization working group
+ within the subcommittee that deals with programming languages,
+ systems, and environments). WG20 has historically dealt with
+ internationalization issues thoughtfully and in depth, but its status
+ has several times been in doubt in recent years. However, assignment
+ of these matters to WG20 increases the risk of eventual ISO
+ internationalization standards that specify different behavior than
+ the UTC specifications.
+
+4.5 Audiences, End Users, and the User Interface Problem
+
+ Part of what has "caused" the DNS internationalization problem, as
+ well as the DNS trademark problem and several others, is that we have
+ stopped thinking about "identifiers for objects" -- which normal
+ people are not expected to see -- and started thinking about "names"
+ -- strings that are expected not only to be readable, but to have
+ linguistically-sensible and culturally-dependent meaning to non-
+ specialist users.
+
+ Within the IETF, the IDN-WG, and sometimes other groups, avoided
+ addressing the implications of that transition by taking "outside our
+ scope -- someone else's problem" approaches or by suggesting that
+ people will just become accustomed to whatever conventions are
+ adopted. The realities of user and vendor behavior suggest that
+ these approaches will not serve the Internet community well in the
+ long term:
+
+ o If we want to make it a problem in a different part of the user
+ interface structure, we need to figure out where it goes in order
+ to have proof of concept of our solution. Unlike vendors whose
+ sole [business] model is the selling or registering of names, the
+ IETF must produce solutions that actually work, in the
+ applications context as seen by the end user.
+
+ o The principle that "they will get used to our conventions and
+ adapt" is fine if we are writing rules for programming languages
+ or an API. But the conventions under discussion are not part of a
+ semi-mathematical system, they are deeply ingrained in culture.
+ No matter how often an English-speaking American is told that the
+ Internet requires that the correct spelling of "colour" be used,
+ he or she isn't going to be convinced. Getting a French-speaker in
+ Lyon to use exactly the same lexical conventions as a French-
+
+
+
+Klensin Informational [Page 20]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ speaker in Quebec in order to accommodate the decisions of the
+ IETF or of a registrar or registry is just not likely. "Montreal"
+ is either a misspelling or an anglicization of a similar word with
+ an acute accent mark over the "e" (i.e., using the Unicode
+ character U+00E9 or one of its equivalents). But global agreement
+ on a rule that will determine whether the two forms should match
+ -- and that won't astonish end users and speakers of one language
+ or the other -- is as unlikely as agreement on whether
+ "misspelling" or "anglicization" is the greater travesty.
+
+ More generally, it is not clear that the outcome of any conceivable
+ nameprep-like process is going to be good enough for practical,
+ user-level, use. In the use of human languages by humans, there are
+ many cases in which things that do not match are nonetheless
+ interpreted as matching. The Norwegian/Danish character that appears
+ in U+00F8 (visually, a lower case 'o' overstruck with a forward
+ slash) and the "o-umlaut" German character that appears in U+00F6
+ (visually, a lower case 'o' with diaeresis (or umlaut)) are clearly
+ different and no matching program should yield an "equal" comparison.
+ But they are more similar to each other than either of them is to,
+ e.g., "e". Humans are able to mentally make the correction in
+ context, and do so easily, and they can be surprised if computers
+ cannot do so. Worse, there is a Swedish character whose appearance
+ is identical to the German o-umlaut, and which shares code point
+ U+00F6, but that, if the languages are known and the sounds of the
+ letters or meanings of words including the character are considered,
+ actually should match the Norwegian/Danish use of U+00F8.
+
+ This text uses examples in Roman scripts because it is being written
+ in English and those examples are relatively easy to render. But one
+ of the important lessons of the discussions about domain name
+ internationalization in recent years is that problems similar to
+ those described above exist in almost every language and script.
+ Each one has its idiosyncrasies, and each set of idiosyncracies is
+ tied to common usage and cultural issues that are very familiar in
+ the relevant group, and often deeply held as cultural values. As
+ long as a schoolchild in the US can get a bad grade on a spelling
+ test for using a perfectly valid British spelling, or one in France
+ or Germany can get a poor grade for leaving off a diacritical mark,
+ there are issues with the relevant language. Similarly, if children
+ in Egypt or Israel are taught that it is acceptable to write a word
+ with or without vowels or stress marks, but that, if those marks are
+ included, they must be the correct ones, or a user in Korea is
+ potentially offended or astonished by out-of-order sequences of Jamo,
+ systems based on character-at-a-time processing and simplistic
+ matching, with no contextual information, are not going to satisfy
+ user needs.
+
+
+
+
+Klensin Informational [Page 21]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ Users are demanding solutions that deal with language and culture.
+ Systems of identifier symbol-strings that serve specialists or
+ computers are, at best, a solution to a rather different (and, at the
+ time this document was written, somewhat ill-defined), problem. The
+ recent efforts have made it ever more clear that, if we ignore the
+ distinction between the user requirements and narrowly-defined
+ identifiers, we are solving an insufficient problem. And,
+ conversely, the approaches that have been proposed to approximate
+ solutions to the user requirement may be far more complex than simple
+ identifiers require.
+
+4.6 Business Cards and Other Natural Uses of Natural Languages
+
+ Over the last few centuries, local conventions have been established
+ in various parts of the world for dealing with multilingual
+ situations. It may be helpful to examine some of these. For
+ example, if one visits a country where the language is different from
+ ones own, business cards are often printed on two sides, one side in
+ each language. The conventions are not completely consistent and the
+ technique assumes that recipients will be tolerant. Translations of
+ names or places are attempted in some situations and transliterations
+ in others. Since it is widely understood that exact translations or
+ transliterations are often not possible, people typically smile at
+ errors, appreciate the effort, and move on.
+
+ The DNS situation differs from these practices in at least two ways.
+ Since a global solution is required, the business card would need a
+ number of sides approximating the number of languages in the world,
+ which is probably impossible without violating laws of physics. More
+ important, the opportunities for tolerance don't exist: the DNS
+ requires a exact match or the lookup fails.
+
+4.7 ASCII Encodings and the Roman Keyboard Assumption
+
+ Part of the argument for ACE-based solutions is that they provide an
+ escape for multilingual environments when applications have not been
+ upgraded. When an older application encounters an ACE-based name,
+ the assumption is that the (admittedly ugly) ASCII-coded string will
+ be displayed and can be typed in. This argument is reasonable from
+ the standpoint of mixtures of Roman-based alphabets, but may not be
+ relevant if user-level systems and devices are involved that do not
+ support the entry of Roman-based characters or which cannot
+ conveniently render such characters. Such systems are few in the
+ world today, but the number can reasonably be expected to rise as the
+ Internet is increasingly used by populations whose primary concern is
+ with local issues, local information, and local languages. It is,
+
+
+
+
+
+Klensin Informational [Page 22]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ for example, fairly easy to imagine populations who use Arabic or
+ Thai scripts and who do not have routine access to scripts or input
+ devices based on Roman-derived alphabets.
+
+4.8 Intra-DNS Approaches for "Multilingual Names"
+
+ It appears, from the cases above and others, that none of the intra-
+ DNS-based solutions for "multilingual names" are workable. They rest
+ on too many assumptions that do not appear to be feasible -- that
+ people will adapt deeply-entrenched language habits to conventions
+ laid down to make the lives of computers easy; that we can make
+ "freeze it now, no need for changes in these areas" decisions about
+ Unicode and nameprep; that ACE will smooth over applications
+ problems, even in environments without the ability to key or render
+ Roman-based glyphs (or where user experience is such that such glyphs
+ cannot easily be distinguished from each other); that the Unicode
+ Consortium will never decide to repair an error in a way that creates
+ a risk of DNS incompatibility; that we can either deploy EDNS
+ [RFC2671] or that long names are not really important; that Japanese
+ and Chinese computer users (and others) will either give up their
+ local or IS 2022-based character coding solutions (for which addition
+ of a large fraction of a million new code points to Unicode is almost
+ certainly a necessary, but probably not sufficient, condition) or
+ build leakproof and completely accurate boundary conversion
+ mechanisms; that out of band or contextual information will always be
+ sufficient for the "map glyph onto script" problem; and so on. In
+ each case, it is likely that about 80% or 90% of cases will work
+ satisfactorily, but it is unlikely that such partial solutions will
+ be good enough. For example, suppose someone can spell her name 90%
+ correctly, or a company name is matched correctly 80% of the time but
+ the other 20% of attempts identify a competitor: are either likely to
+ be considered adequate?
+
+5. Search-based Systems: The Key Controversies
+
+ For many years, a common response to requirements to locate people or
+ resources on the Internet has been to invoke the term "directory".
+ While an in-depth analysis of the reasons would require a separate
+ document, the history of failure of these invocations has given
+ "directory" efforts a bad reputation. The effort proposed here is
+ different from those predecessors for several reasons, perhaps the
+ most important of which is that it focuses on a fairly-well-
+ understood set of problems and needs, rather than on finding uses for
+ a particular technology.
+
+ As suggested in some of the text above, it is an open question as to
+ whether the needs of the community would be best served by a single
+ (even if functionally, and perhaps administratively, distributed)
+
+
+
+Klensin Informational [Page 23]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ directory with universal applicability, a single directory that
+ supports locally-tailored search (and, most important, matching)
+ functions, or multiple, locally-determined, directories. Each has
+ its attractions. Any but the first would essentially prevent
+ reverse-mapping (determination of the user-visible name of the host
+ or resource from target information such as an address or DNS name).
+ But reverse mapping has become less useful over the years --at least
+ to users -- as more and more names have been associated with many
+ host addresses and as CIDR [CIDR] has proven problematic for mapping
+ smaller address blocks to meaningful names.
+
+ Locally-tailored searches and mappings would permit national
+ variations on interpretation of which strings matched which other
+ ones, an arrangement that is especially important when different
+ localities apply different rules to, e.g., matching of characters
+ with and without diacriticals. But, of course, this implies that a
+ URL may evaluate properly or not depending on either settings on a
+ client machine or the network connectivity of the user. That is not,
+ in general, a desirable situation, since it implies that users could
+ not, in the general case, share URLs (or other host references) and
+ that a particular user might not be able to carry references from one
+ host or location to another.
+
+ And, of course, completely separate directories would permit
+ translation and transliteration functions to be embedded in the
+ directory, giving much of the Internet a different appearance
+ depending on which directory was chosen. The attractions of this are
+ obvious, but, unless things were very carefully designed to preserve
+ uniqueness and precise identities at the right points (which may or
+ may not be possible), such a system would have many of the
+ difficulties associated with multiple DNS roots.
+
+ Finally, a system of separate directories and databases, if coupled
+ with removal of the DNS-imposed requirement for unique names, would
+ largely eliminate the need for a single worldwide authority to manage
+ the top of the naming hierarchy.
+
+6. Security Considerations
+
+ The set of proposals implied by this document suggests an interesting
+ set of security issues (i.e., nothing important is ever easy). A
+ directory system used for locating network resources would presumably
+ need to be as carefully protected against unauthorized changes as the
+ DNS itself. There also might be new opportunities for problems in an
+ arrangement involving two or more (sub)layers, especially if such a
+ system were designed without central authority or uniqueness of
+ names. It is uncertain how much greater those risks would be as
+ compared to a DNS lookup sequence that involved looking up one name,
+
+
+
+Klensin Informational [Page 24]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ getting back information, and then doing additional lookups
+ potentially in different subtrees. That multistage lookup will often
+ be the case with, e.g., NAPTR records [RFC 2915] unless additional
+ restrictions are imposed. But additional steps, systems, and
+ databases almost certainly involve some additional risks of
+ compromise.
+
+7. References
+
+7.1 Normative References
+
+ None
+
+7.2 Explanatory and Informative References
+
+ [Albitz] Any of the editions of Albitz, P. and C. Liu, DNS and
+ BIND, O'Reilly and Associates, 1992, 1997, 1998, 2001.
+
+ [ASCII] American National Standards Institute (formerly United
+ States of America Standards Institute), X3.4, 1968,
+ "USA Code for Information Interchange". ANSI X3.4-1968
+ has been replaced by newer versions with slight
+ modifications, but the 1968 version remains definitive
+ for the Internet. Some time after ASCII was first
+ formulated as a standard, ISO adopted international
+ standard 646, which uses ASCII as a base. IS 646
+ actually contained two code tables: an "International
+ Reference Version" (often referenced as ISO 646-IRV)
+ which was essentially identical to the ASCII of the
+ time, and a "Basic Version" (ISO 646-BV), which
+ designates a number of character positions for
+ national use.
+
+ [CIDR] Fuller, V., Li, T., Yu, J. and K. Varadhan, "Classless
+ Inter-Domain Routing (CIDR): an Address Assignment and
+ Aggregation Strategy", RFC 1519, September 1993.
+
+ Eidnes, H., de Groot, G. and P. Vixie, "Classless IN-
+ ADDR.ARPA delegation", RFC 2317, March 1998.
+
+ [COM-SIZE] Size information supplied by Verisign Global Registry
+ Services (the zone administrator, or "registry
+ operator", for COM, see [REGISTRAR], below) to ICANN,
+ third quarter 2002.
+
+ [DNS-Search] Klensin, J., "A Search-based access model for the
+ DNS", Work in Progress.
+
+
+
+
+Klensin Informational [Page 25]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ [FINGER] Zimmerman, D., "The Finger User Information Protocol",
+ RFC 1288, December 1991.
+
+ Harrenstien, K., "NAME/FINGER Protocol", RFC 742,
+ December 1977.
+
+ [IAB-OPES] Floyd, S. and L. Daigle, "IAB Architectural and Policy
+ Considerations for Open Pluggable Edge Services", RFC
+ 3238, January 2002.
+
+ [IQUERY] Lawrence, D., "Obsoleting IQUERY", RFC 3425, November
+ 2002.
+
+ [IS646] ISO/IEC 646:1991 Information technology -- ISO 7-bit
+ coded character set for information interchange
+
+ [IS10646] ISO/IEC 10646-1:2000 Information technology --
+ Universal Multiple-Octet Coded Character Set (UCS) --
+ Part 1: Architecture and Basic Multilingual Plane and
+ ISO/IEC 10646-2:2001 Information technology --
+ Universal Multiple-Octet Coded Character Set (UCS) --
+ Part 2: Supplementary Planes
+
+ [MINC] The Multilingual Internet Names Consortium,
+ http://www.minc.org/ has been an early advocate for
+ the importance of expansion of DNS names to
+ accommodate non-ASCII characters. Some of their
+ specific proposals, while helping people to understand
+ the problems better, were not compatible with the
+ design of the DNS.
+
+ [NAPTR] Mealling, M. and R. Daniel, "The Naming Authority
+ Pointer (NAPTR) DNS Resource Record", RFC 2915,
+ September 2000.
+
+ Mealling, M., "Dynamic Delegation Discovery System
+ (DDDS) Part One: The Comprehensive DDDS", RFC 3401,
+ October 2002.
+
+ Mealling, M., "Dynamic Delegation Discovery System
+ (DDDS) Part Two: The Algorithm", RFC 3402, October
+ 2002.
+
+ Mealling, M., "Dynamic Delegation Discovery System
+ (DDDS) Part Three: The Domain Name System (DNS)
+ Database", RFC 3403, October 2002.
+
+
+
+
+
+Klensin Informational [Page 26]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ [REGISTRAR] In an early stage of the process that created the
+ Internet Corporation for Assigned Names and Numbers
+ (ICANN), a "Green Paper" was released by the US
+ Government. That paper introduced new terminology
+ and some concepts not needed by traditional DNS
+ operations. The term "registry" was applied to the
+ actual operator and database holder of a domain
+ (typically at the top level, since the Green Paper was
+ little concerned with anything else), while
+ organizations that marketed names and made them
+ available to "registrants" were known as "registrars".
+ In the classic DNS model, the function of "zone
+ administrator" encompassed both registry and registrar
+ roles, although that model did not anticipate a
+ commercial market in names.
+
+ [RFC625] Kudlick, M. and E. Feinler, "On-line hostnames
+ service", RFC 625, March 1974.
+
+ [RFC734] Crispin, M., "SUPDUP Protocol", RFC 734, October 1977.
+
+ [RFC811] Harrenstien, K., White, V. and E. Feinler, "Hostnames
+ Server", RFC 811, March 1982.
+
+ [RFC819] Su, Z. and J. Postel, "Domain naming convention for
+ Internet user applications", RFC 819, August 1982.
+
+ [RFC830] Su, Z., "Distributed system for Internet name
+ service", RFC 830, October 1982.
+
+ [RFC882] Mockapetris, P., "Domain names: Concepts and
+ facilities", RFC 882, November 1983.
+
+ [RFC883] Mockapetris, P., "Domain names: Implementation
+ specification", RFC 883, November 1983.
+
+ [RFC952] Harrenstien, K, Stahl, M. and E. Feinler, "DoD
+ Internet host table specification", RFC 952, October
+ 1985.
+
+ [RFC953] Harrenstien, K., Stahl, M. and E. Feinler, "HOSTNAME
+ SERVER", RFC 953, October 1985.
+
+ [RFC1034] Mockapetris, P., "Domain names, Concepts and
+ facilities", STD 13, RFC 1034, November 1987.
+
+
+
+
+
+
+Klensin Informational [Page 27]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC1591] Postel, J., "Domain Name System Structure and
+ Delegation", RFC 1591, March 1994.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC2295] Holtman, K. and A. Mutz, "Transparent Content
+ Negotiation in HTTP", RFC 2295, March 1998
+
+ [RFC2396] Berners-Lee, T., Fielding, R. and L. Masinter,
+ "Uniform Resource Identifiers (URI): Generic Syntax",
+ RFC 2396, August 1998.
+
+ [RFC2608] Guttman, E., Perkins, C., Veizades, J. and M. Day,
+ "Service Location Protocol, Version 2", RFC 2608, June
+ 1999.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [RFC2825] IAB, Daigle, L., Ed., "A Tangled Web: Issues of I18N,
+ Domain Names, and the Other Internet protocols", RFC
+ 2825, May 2000.
+
+ [RFC2826] IAB, "IAB Technical Comment on the Unique DNS Root",
+ RFC 2826, May 2000.
+
+ [RFC2972] Popp, N., Mealling, M., Masinter, L. and K. Sollins,
+ "Context and Goals for Common Name Resolution", RFC
+ 2972, October 2000.
+
+ [RFC3305] Mealling, M. and R. Denenberg, Eds., "Report from the
+ Joint W3C/IETF URI Planning Interest Group: Uniform
+ Resource Identifiers (URIs), URLs, and Uniform
+ Resource Names (URNs): Clarifications and
+ Recommendations", RFC 3305, August 2002.
+
+ [RFC3439] Bush, R. and D. Meyer, "Some Internet Architectural
+ Guidelines and Philosophy", RFC 3439, December 2002.
+
+ [Seng] Seng, J., et al., Eds., "Internationalized Domain
+ Names: Registration and Administration Guideline for
+ Chinese, Japanese, and Korean", Work in Progress.
+
+
+
+
+
+Klensin Informational [Page 28]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ [STRINGPREP] Hoffman, P. and M. Blanchet, "Preparation of
+ Internationalized Strings (stringprep)", RFC 3454,
+ December 2002.
+
+ The particular profile used for placing
+ internationalized strings in the DNS is called
+ "nameprep", described in Hoffman, P. and M. Blanchet,
+ "Nameprep: A Stringprep Profile for Internationalized
+ Domain Names", Work in Progress.
+
+ [TELNET] Postel, J. and J. Reynolds, "Telnet Protocol
+ Specification", STD 8, RFC 854, May 1983.
+
+ Postel, J. and J. Reynolds, "Telnet Option
+ Specifications", STD 8, RFC 855, May 1983.
+
+ [UNICODE] The Unicode Consortium, The Unicode Standard, Version
+ 3.0, Addison-Wesley: Reading, MA, 2000. Update to
+ version 3.1, 2001. Update to version 3.2, 2002.
+
+ [UTR15] Davis, M. and M. Duerst, "Unicode Standard Annex #15:
+ Unicode Normalization Forms", Unicode Consortium,
+ March 2002. An integral part of The Unicode Standard,
+ Version 3.1.1. Available at
+ (http://www.unicode.org/reports/tr15/tr15-21.html).
+
+ [WHOIS] Harrenstien, K, Stahl, M. and E. Feinler,
+ "NICNAME/WHOIS", RFC 954, October 1985.
+
+ [WHOIS-UPDATE] Gargano, J. and K. Weiss, "Whois and Network
+ Information Lookup Service, Whois++", RFC 1834, August
+ 1995.
+
+ Weider, C., Fullton, J. and S. Spero, "Architecture of
+ the Whois++ Index Service", RFC 1913, February 1996.
+
+ Williamson, S., Kosters, M., Blacka, D., Singh, J. and
+ K. Zeilstra, "Referral Whois (RWhois) Protocol V1.5",
+ RFC 2167, June 1997;
+
+ Daigle, L. and P. Faltstrom, "The
+ application/whoispp-query Content-Type", RFC 2957,
+ October 2000.
+
+ Daigle, L. and P. Falstrom, "The application/whoispp-
+ response Content-type", RFC 2958, October 2000.
+
+
+
+
+
+Klensin Informational [Page 29]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+ [X29] International Telecommuncations Union, "Recommendation
+ X.29: Procedures for the exchange of control
+ information and user data between a Packet
+ Assembly/Disassembly (PAD) facility and a packet mode
+ DTE or another PAD", December 1997.
+
+8. Acknowledgements
+
+ Many people have contributed to versions of this document or the
+ thinking that went into it. The author would particularly like to
+ thank Harald Alvestrand, Rob Austein, Bob Braden, Vinton Cerf, Matt
+ Crawford, Leslie Daigle, Patrik Faltstrom, Eric A. Hall, Ted Hardie,
+ Paul Hoffman, Erik Nordmark, and Zita Wenzel for making specific
+ suggestions and/or challenging the assumptions and presentation of
+ earlier versions and suggesting ways to improve them.
+
+9. Author's Address
+
+ John C. Klensin
+ 1770 Massachusetts Ave, #322
+ Cambridge, MA 02140
+
+ EMail: klensin+srch@jck.com
+
+ A mailing list has been initiated for discussion of the topics
+ discussed in this document, and closely-related issues, at
+ ietf-irnss@lists.elistx.com. See http://lists.elistx.com/archives/
+ for subscription and archival information.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Klensin Informational [Page 30]
+
+RFC 3467 Role of the Domain Name System (DNS) February 2003
+
+
+10. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Klensin Informational [Page 31]
+
diff --git a/doc/rfc/rfc3490.txt b/doc/rfc/rfc3490.txt
new file mode 100644
index 0000000..d2e0b3b
--- /dev/null
+++ b/doc/rfc/rfc3490.txt
@@ -0,0 +1,1235 @@
+
+
+
+
+
+
+Network Working Group P. Faltstrom
+Request for Comments: 3490 Cisco
+Category: Standards Track P. Hoffman
+ IMC & VPNC
+ A. Costello
+ UC Berkeley
+ March 2003
+
+
+ Internationalizing Domain Names in Applications (IDNA)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ Until now, there has been no standard method for domain names to use
+ characters outside the ASCII repertoire. This document defines
+ internationalized domain names (IDNs) and a mechanism called
+ Internationalizing Domain Names in Applications (IDNA) for handling
+ them in a standard fashion. IDNs use characters drawn from a large
+ repertoire (Unicode), but IDNA allows the non-ASCII characters to be
+ represented using only the ASCII characters already allowed in so-
+ called host names today. This backward-compatible representation is
+ required in existing protocols like DNS, so that IDNs can be
+ introduced with no changes to the existing infrastructure. IDNA is
+ only meant for processing domain names, not free text.
+
+Table of Contents
+
+ 1. Introduction.................................................. 2
+ 1.1 Problem Statement......................................... 3
+ 1.2 Limitations of IDNA....................................... 3
+ 1.3 Brief overview for application developers................. 4
+ 2. Terminology................................................... 5
+ 3. Requirements and applicability................................ 7
+ 3.1 Requirements.............................................. 7
+ 3.2 Applicability............................................. 8
+ 3.2.1. DNS resource records................................ 8
+
+
+
+Faltstrom, et al. Standards Track [Page 1]
+
+RFC 3490 IDNA March 2003
+
+
+ 3.2.2. Non-domain-name data types stored in domain names... 9
+ 4. Conversion operations......................................... 9
+ 4.1 ToASCII................................................... 10
+ 4.2 ToUnicode................................................. 11
+ 5. ACE prefix.................................................... 12
+ 6. Implications for typical applications using DNS............... 13
+ 6.1 Entry and display in applications......................... 14
+ 6.2 Applications and resolver libraries....................... 15
+ 6.3 DNS servers............................................... 15
+ 6.4 Avoiding exposing users to the raw ACE encoding........... 16
+ 6.5 DNSSEC authentication of IDN domain names................ 16
+ 7. Name server considerations.................................... 17
+ 8. Root server considerations.................................... 17
+ 9. References.................................................... 18
+ 9.1 Normative References...................................... 18
+ 9.2 Informative References.................................... 18
+ 10. Security Considerations...................................... 19
+ 11. IANA Considerations.......................................... 20
+ 12. Authors' Addresses........................................... 21
+ 13. Full Copyright Statement..................................... 22
+
+1. Introduction
+
+ IDNA works by allowing applications to use certain ASCII name labels
+ (beginning with a special prefix) to represent non-ASCII name labels.
+ Lower-layer protocols need not be aware of this; therefore IDNA does
+ not depend on changes to any infrastructure. In particular, IDNA
+ does not depend on any changes to DNS servers, resolvers, or protocol
+ elements, because the ASCII name service provided by the existing DNS
+ is entirely sufficient for IDNA.
+
+ This document does not require any applications to conform to IDNA,
+ but applications can elect to use IDNA in order to support IDN while
+ maintaining interoperability with existing infrastructure. If an
+ application wants to use non-ASCII characters in domain names, IDNA
+ is the only currently-defined option. Adding IDNA support to an
+ existing application entails changes to the application only, and
+ leaves room for flexibility in the user interface.
+
+ A great deal of the discussion of IDN solutions has focused on
+ transition issues and how IDN will work in a world where not all of
+ the components have been updated. Proposals that were not chosen by
+ the IDN Working Group would depend on user applications, resolvers,
+ and DNS servers being updated in order for a user to use an
+ internationalized domain name. Rather than rely on widespread
+ updating of all components, IDNA depends on updates to user
+ applications only; no changes are needed to the DNS protocol or any
+ DNS servers or the resolvers on user's computers.
+
+
+
+Faltstrom, et al. Standards Track [Page 2]
+
+RFC 3490 IDNA March 2003
+
+
+1.1 Problem Statement
+
+ The IDNA specification solves the problem of extending the repertoire
+ of characters that can be used in domain names to include the Unicode
+ repertoire (with some restrictions).
+
+ IDNA does not extend the service offered by DNS to the applications.
+ Instead, the applications (and, by implication, the users) continue
+ to see an exact-match lookup service. Either there is a single
+ exactly-matching name or there is no match. This model has served
+ the existing applications well, but it requires, with or without
+ internationalized domain names, that users know the exact spelling of
+ the domain names that the users type into applications such as web
+ browsers and mail user agents. The introduction of the larger
+ repertoire of characters potentially makes the set of misspellings
+ larger, especially given that in some cases the same appearance, for
+ example on a business card, might visually match several Unicode code
+ points or several sequences of code points.
+
+ IDNA allows the graceful introduction of IDNs not only by avoiding
+ upgrades to existing infrastructure (such as DNS servers and mail
+ transport agents), but also by allowing some rudimentary use of IDNs
+ in applications by using the ASCII representation of the non-ASCII
+ name labels. While such names are very user-unfriendly to read and
+ type, and hence are not suitable for user input, they allow (for
+ instance) replying to email and clicking on URLs even though the
+ domain name displayed is incomprehensible to the user. In order to
+ allow user-friendly input and output of the IDNs, the applications
+ need to be modified to conform to this specification.
+
+ IDNA uses the Unicode character repertoire, which avoids the
+ significant delays that would be inherent in waiting for a different
+ and specific character set be defined for IDN purposes by some other
+ standards developing organization.
+
+1.2 Limitations of IDNA
+
+ The IDNA protocol does not solve all linguistic issues with users
+ inputting names in different scripts. Many important language-based
+ and script-based mappings are not covered in IDNA and need to be
+ handled outside the protocol. For example, names that are entered in
+ a mix of traditional and simplified Chinese characters will not be
+ mapped to a single canonical name. Another example is Scandinavian
+ names that are entered with U+00F6 (LATIN SMALL LETTER O WITH
+ DIAERESIS) will not be mapped to U+00F8 (LATIN SMALL LETTER O WITH
+ STROKE).
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 3]
+
+RFC 3490 IDNA March 2003
+
+
+ An example of an important issue that is not considered in detail in
+ IDNA is how to provide a high probability that a user who is entering
+ a domain name based on visual information (such as from a business
+ card or billboard) or aural information (such as from a telephone or
+ radio) would correctly enter the IDN. Similar issues exist for ASCII
+ domain names, for example the possible visual confusion between the
+ letter 'O' and the digit zero, but the introduction of the larger
+ repertoire of characters creates more opportunities of similar
+ looking and similar sounding names. Note that this is a complex
+ issue relating to languages, input methods on computers, and so on.
+ Furthermore, the kind of matching and searching necessary for a high
+ probability of success would not fit the role of the DNS and its
+ exact matching function.
+
+1.3 Brief overview for application developers
+
+ Applications can use IDNA to support internationalized domain names
+ anywhere that ASCII domain names are already supported, including DNS
+ master files and resolver interfaces. (Applications can also define
+ protocols and interfaces that support IDNs directly using non-ASCII
+ representations. IDNA does not prescribe any particular
+ representation for new protocols, but it still defines which names
+ are valid and how they are compared.)
+
+ The IDNA protocol is contained completely within applications. It is
+ not a client-server or peer-to-peer protocol: everything is done
+ inside the application itself. When used with a DNS resolver
+ library, IDNA is inserted as a "shim" between the application and the
+ resolver library. When used for writing names into a DNS zone, IDNA
+ is used just before the name is committed to the zone.
+
+ There are two operations described in section 4 of this document:
+
+ - The ToASCII operation is used before sending an IDN to something
+ that expects ASCII names (such as a resolver) or writing an IDN
+ into a place that expects ASCII names (such as a DNS master file).
+
+ - The ToUnicode operation is used when displaying names to users,
+ for example names obtained from a DNS zone.
+
+ It is important to note that the ToASCII operation can fail. If it
+ fails when processing a domain name, that domain name cannot be used
+ as an internationalized domain name and the application has to have
+ some method of dealing with this failure.
+
+ IDNA requires that implementations process input strings with
+ Nameprep [NAMEPREP], which is a profile of Stringprep [STRINGPREP],
+ and then with Punycode [PUNYCODE]. Implementations of IDNA MUST
+
+
+
+Faltstrom, et al. Standards Track [Page 4]
+
+RFC 3490 IDNA March 2003
+
+
+ fully implement Nameprep and Punycode; neither Nameprep nor Punycode
+ are optional.
+
+2. Terminology
+
+ The key words "MUST", "SHALL", "REQUIRED", "SHOULD", "RECOMMENDED",
+ and "MAY" in this document are to be interpreted as described in BCP
+ 14, RFC 2119 [RFC2119].
+
+ A code point is an integer value associated with a character in a
+ coded character set.
+
+ Unicode [UNICODE] is a coded character set containing tens of
+ thousands of characters. A single Unicode code point is denoted by
+ "U+" followed by four to six hexadecimal digits, while a range of
+ Unicode code points is denoted by two hexadecimal numbers separated
+ by "..", with no prefixes.
+
+ ASCII means US-ASCII [USASCII], a coded character set containing 128
+ characters associated with code points in the range 0..7F. Unicode
+ is an extension of ASCII: it includes all the ASCII characters and
+ associates them with the same code points.
+
+ The term "LDH code points" is defined in this document to mean the
+ code points associated with ASCII letters, digits, and the hyphen-
+ minus; that is, U+002D, 30..39, 41..5A, and 61..7A. "LDH" is an
+ abbreviation for "letters, digits, hyphen".
+
+ [STD13] talks about "domain names" and "host names", but many people
+ use the terms interchangeably. Further, because [STD13] was not
+ terribly clear, many people who are sure they know the exact
+ definitions of each of these terms disagree on the definitions. In
+ this document the term "domain name" is used in general. This
+ document explicitly cites [STD3] whenever referring to the host name
+ syntax restrictions defined therein.
+
+ A label is an individual part of a domain name. Labels are usually
+ shown separated by dots; for example, the domain name
+ "www.example.com" is composed of three labels: "www", "example", and
+ "com". (The zero-length root label described in [STD13], which can
+ be explicit as in "www.example.com." or implicit as in
+ "www.example.com", is not considered a label in this specification.)
+ IDNA extends the set of usable characters in labels that are text.
+ For the rest of this document, the term "label" is shorthand for
+ "text label", and "every label" means "every text label".
+
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 5]
+
+RFC 3490 IDNA March 2003
+
+
+ An "internationalized label" is a label to which the ToASCII
+ operation (see section 4) can be applied without failing (with the
+ UseSTD3ASCIIRules flag unset). This implies that every ASCII label
+ that satisfies the [STD13] length restriction is an internationalized
+ label. Therefore the term "internationalized label" is a
+ generalization, embracing both old ASCII labels and new non-ASCII
+ labels. Although most Unicode characters can appear in
+ internationalized labels, ToASCII will fail for some input strings,
+ and such strings are not valid internationalized labels.
+
+ An "internationalized domain name" (IDN) is a domain name in which
+ every label is an internationalized label. This implies that every
+ ASCII domain name is an IDN (which implies that it is possible for a
+ name to be an IDN without it containing any non-ASCII characters).
+ This document does not attempt to define an "internationalized host
+ name". Just as has been the case with ASCII names, some DNS zone
+ administrators may impose restrictions, beyond those imposed by DNS
+ or IDNA, on the characters or strings that may be registered as
+ labels in their zones. Such restrictions have no impact on the
+ syntax or semantics of DNS protocol messages; a query for a name that
+ matches no records will yield the same response regardless of the
+ reason why it is not in the zone. Clients issuing queries or
+ interpreting responses cannot be assumed to have any knowledge of
+ zone-specific restrictions or conventions.
+
+ In IDNA, equivalence of labels is defined in terms of the ToASCII
+ operation, which constructs an ASCII form for a given label, whether
+ or not the label was already an ASCII label. Labels are defined to
+ be equivalent if and only if their ASCII forms produced by ToASCII
+ match using a case-insensitive ASCII comparison. ASCII labels
+ already have a notion of equivalence: upper case and lower case are
+ considered equivalent. The IDNA notion of equivalence is an
+ extension of that older notion. Equivalent labels in IDNA are
+ treated as alternate forms of the same label, just as "foo" and "Foo"
+ are treated as alternate forms of the same label.
+
+ To allow internationalized labels to be handled by existing
+ applications, IDNA uses an "ACE label" (ACE stands for ASCII
+ Compatible Encoding). An ACE label is an internationalized label
+ that can be rendered in ASCII and is equivalent to an
+ internationalized label that cannot be rendered in ASCII. Given any
+ internationalized label that cannot be rendered in ASCII, the ToASCII
+ operation will convert it to an equivalent ACE label (whereas an
+ ASCII label will be left unaltered by ToASCII). ACE labels are
+ unsuitable for display to users. The ToUnicode operation will
+ convert any label to an equivalent non-ACE label. In fact, an ACE
+ label is formally defined to be any label that the ToUnicode
+ operation would alter (whereas non-ACE labels are left unaltered by
+
+
+
+Faltstrom, et al. Standards Track [Page 6]
+
+RFC 3490 IDNA March 2003
+
+
+ ToUnicode). Every ACE label begins with the ACE prefix specified in
+ section 5. The ToASCII and ToUnicode operations are specified in
+ section 4.
+
+ The "ACE prefix" is defined in this document to be a string of ASCII
+ characters that appears at the beginning of every ACE label. It is
+ specified in section 5.
+
+ A "domain name slot" is defined in this document to be a protocol
+ element or a function argument or a return value (and so on)
+ explicitly designated for carrying a domain name. Examples of domain
+ name slots include: the QNAME field of a DNS query; the name argument
+ of the gethostbyname() library function; the part of an email address
+ following the at-sign (@) in the From: field of an email message
+ header; and the host portion of the URI in the src attribute of an
+ HTML <IMG> tag. General text that just happens to contain a domain
+ name is not a domain name slot; for example, a domain name appearing
+ in the plain text body of an email message is not occupying a domain
+ name slot.
+
+ An "IDN-aware domain name slot" is defined in this document to be a
+ domain name slot explicitly designated for carrying an
+ internationalized domain name as defined in this document. The
+ designation may be static (for example, in the specification of the
+ protocol or interface) or dynamic (for example, as a result of
+ negotiation in an interactive session).
+
+ An "IDN-unaware domain name slot" is defined in this document to be
+ any domain name slot that is not an IDN-aware domain name slot.
+ Obviously, this includes any domain name slot whose specification
+ predates IDNA.
+
+3. Requirements and applicability
+
+3.1 Requirements
+
+ IDNA conformance means adherence to the following four requirements:
+
+ 1) Whenever dots are used as label separators, the following
+ characters MUST be recognized as dots: U+002E (full stop), U+3002
+ (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61
+ (halfwidth ideographic full stop).
+
+ 2) Whenever a domain name is put into an IDN-unaware domain name slot
+ (see section 2), it MUST contain only ASCII characters. Given an
+ internationalized domain name (IDN), an equivalent domain name
+ satisfying this requirement can be obtained by applying the
+
+
+
+
+Faltstrom, et al. Standards Track [Page 7]
+
+RFC 3490 IDNA March 2003
+
+
+ ToASCII operation (see section 4) to each label and, if dots are
+ used as label separators, changing all the label separators to
+ U+002E.
+
+ 3) ACE labels obtained from domain name slots SHOULD be hidden from
+ users when it is known that the environment can handle the non-ACE
+ form, except when the ACE form is explicitly requested. When it
+ is not known whether or not the environment can handle the non-ACE
+ form, the application MAY use the non-ACE form (which might fail,
+ such as by not being displayed properly), or it MAY use the ACE
+ form (which will look unintelligle to the user). Given an
+ internationalized domain name, an equivalent domain name
+ containing no ACE labels can be obtained by applying the ToUnicode
+ operation (see section 4) to each label. When requirements 2 and
+ 3 both apply, requirement 2 takes precedence.
+
+ 4) Whenever two labels are compared, they MUST be considered to match
+ if and only if they are equivalent, that is, their ASCII forms
+ (obtained by applying ToASCII) match using a case-insensitive
+ ASCII comparison. Whenever two names are compared, they MUST be
+ considered to match if and only if their corresponding labels
+ match, regardless of whether the names use the same forms of label
+ separators.
+
+3.2 Applicability
+
+ IDNA is applicable to all domain names in all domain name slots
+ except where it is explicitly excluded.
+
+ This implies that IDNA is applicable to many protocols that predate
+ IDNA. Note that IDNs occupying domain name slots in those protocols
+ MUST be in ASCII form (see section 3.1, requirement 2).
+
+3.2.1. DNS resource records
+
+ IDNA does not apply to domain names in the NAME and RDATA fields of
+ DNS resource records whose CLASS is not IN. This exclusion applies
+ to every non-IN class, present and future, except where future
+ standards override this exclusion by explicitly inviting the use of
+ IDNA.
+
+ There are currently no other exclusions on the applicability of IDNA
+ to DNS resource records; it depends entirely on the CLASS, and not on
+ the TYPE. This will remain true, even as new types are defined,
+ unless there is a compelling reason for a new type to complicate
+ matters by imposing type-specific rules.
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 8]
+
+RFC 3490 IDNA March 2003
+
+
+3.2.2. Non-domain-name data types stored in domain names
+
+ Although IDNA enables the representation of non-ASCII characters in
+ domain names, that does not imply that IDNA enables the
+ representation of non-ASCII characters in other data types that are
+ stored in domain names. For example, an email address local part is
+ sometimes stored in a domain label (hostmaster@example.com would be
+ represented as hostmaster.example.com in the RDATA field of an SOA
+ record). IDNA does not update the existing email standards, which
+ allow only ASCII characters in local parts. Therefore, unless the
+ email standards are revised to invite the use of IDNA for local
+ parts, a domain label that holds the local part of an email address
+ SHOULD NOT begin with the ACE prefix, and even if it does, it is to
+ be interpreted literally as a local part that happens to begin with
+ the ACE prefix.
+
+4. Conversion operations
+
+ An application converts a domain name put into an IDN-unaware slot or
+ displayed to a user. This section specifies the steps to perform in
+ the conversion, and the ToASCII and ToUnicode operations.
+
+ The input to ToASCII or ToUnicode is a single label that is a
+ sequence of Unicode code points (remember that all ASCII code points
+ are also Unicode code points). If a domain name is represented using
+ a character set other than Unicode or US-ASCII, it will first need to
+ be transcoded to Unicode.
+
+ Starting from a whole domain name, the steps that an application
+ takes to do the conversions are:
+
+ 1) Decide whether the domain name is a "stored string" or a "query
+ string" as described in [STRINGPREP]. If this conversion follows
+ the "queries" rule from [STRINGPREP], set the flag called
+ "AllowUnassigned".
+
+ 2) Split the domain name into individual labels as described in
+ section 3.1. The labels do not include the separator.
+
+ 3) For each label, decide whether or not to enforce the restrictions
+ on ASCII characters in host names [STD3]. (Applications already
+ faced this choice before the introduction of IDNA, and can
+ continue to make the decision the same way they always have; IDNA
+ makes no new recommendations regarding this choice.) If the
+ restrictions are to be enforced, set the flag called
+ "UseSTD3ASCIIRules" for that label.
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 9]
+
+RFC 3490 IDNA March 2003
+
+
+ 4) Process each label with either the ToASCII or the ToUnicode
+ operation as appropriate. Typically, you use the ToASCII
+ operation if you are about to put the name into an IDN-unaware
+ slot, and you use the ToUnicode operation if you are displaying
+ the name to a user; section 3.1 gives greater detail on the
+ applicable requirements.
+
+ 5) If ToASCII was applied in step 4 and dots are used as label
+ separators, change all the label separators to U+002E (full stop).
+
+ The following two subsections define the ToASCII and ToUnicode
+ operations that are used in step 4.
+
+ This description of the protocol uses specific procedure names, names
+ of flags, and so on, in order to facilitate the specification of the
+ protocol. These names, as well as the actual steps of the
+ procedures, are not required of an implementation. In fact, any
+ implementation which has the same external behavior as specified in
+ this document conforms to this specification.
+
+4.1 ToASCII
+
+ The ToASCII operation takes a sequence of Unicode code points that
+ make up one label and transforms it into a sequence of code points in
+ the ASCII range (0..7F). If ToASCII succeeds, the original sequence
+ and the resulting sequence are equivalent labels.
+
+ It is important to note that the ToASCII operation can fail. ToASCII
+ fails if any step of it fails. If any step of the ToASCII operation
+ fails on any label in a domain name, that domain name MUST NOT be
+ used as an internationalized domain name. The method for dealing
+ with this failure is application-specific.
+
+ The inputs to ToASCII are a sequence of code points, the
+ AllowUnassigned flag, and the UseSTD3ASCIIRules flag. The output of
+ ToASCII is either a sequence of ASCII code points or a failure
+ condition.
+
+ ToASCII never alters a sequence of code points that are all in the
+ ASCII range to begin with (although it could fail). Applying the
+ ToASCII operation multiple times has exactly the same effect as
+ applying it just once.
+
+ ToASCII consists of the following steps:
+
+ 1. If the sequence contains any code points outside the ASCII range
+ (0..7F) then proceed to step 2, otherwise skip to step 3.
+
+
+
+
+Faltstrom, et al. Standards Track [Page 10]
+
+RFC 3490 IDNA March 2003
+
+
+ 2. Perform the steps specified in [NAMEPREP] and fail if there is an
+ error. The AllowUnassigned flag is used in [NAMEPREP].
+
+ 3. If the UseSTD3ASCIIRules flag is set, then perform these checks:
+
+ (a) Verify the absence of non-LDH ASCII code points; that is, the
+ absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F.
+
+ (b) Verify the absence of leading and trailing hyphen-minus; that
+ is, the absence of U+002D at the beginning and end of the
+ sequence.
+
+ 4. If the sequence contains any code points outside the ASCII range
+ (0..7F) then proceed to step 5, otherwise skip to step 8.
+
+ 5. Verify that the sequence does NOT begin with the ACE prefix.
+
+ 6. Encode the sequence using the encoding algorithm in [PUNYCODE] and
+ fail if there is an error.
+
+ 7. Prepend the ACE prefix.
+
+ 8. Verify that the number of code points is in the range 1 to 63
+ inclusive.
+
+4.2 ToUnicode
+
+ The ToUnicode operation takes a sequence of Unicode code points that
+ make up one label and returns a sequence of Unicode code points. If
+ the input sequence is a label in ACE form, then the result is an
+ equivalent internationalized label that is not in ACE form, otherwise
+ the original sequence is returned unaltered.
+
+ ToUnicode never fails. If any step fails, then the original input
+ sequence is returned immediately in that step.
+
+ The ToUnicode output never contains more code points than its input.
+ Note that the number of octets needed to represent a sequence of code
+ points depends on the particular character encoding used.
+
+ The inputs to ToUnicode are a sequence of code points, the
+ AllowUnassigned flag, and the UseSTD3ASCIIRules flag. The output of
+ ToUnicode is always a sequence of Unicode code points.
+
+ 1. If all code points in the sequence are in the ASCII range (0..7F)
+ then skip to step 3.
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 11]
+
+RFC 3490 IDNA March 2003
+
+
+ 2. Perform the steps specified in [NAMEPREP] and fail if there is an
+ error. (If step 3 of ToASCII is also performed here, it will not
+ affect the overall behavior of ToUnicode, but it is not
+ necessary.) The AllowUnassigned flag is used in [NAMEPREP].
+
+ 3. Verify that the sequence begins with the ACE prefix, and save a
+ copy of the sequence.
+
+ 4. Remove the ACE prefix.
+
+ 5. Decode the sequence using the decoding algorithm in [PUNYCODE] and
+ fail if there is an error. Save a copy of the result of this
+ step.
+
+ 6. Apply ToASCII.
+
+ 7. Verify that the result of step 6 matches the saved copy from step
+ 3, using a case-insensitive ASCII comparison.
+
+ 8. Return the saved copy from step 5.
+
+5. ACE prefix
+
+ The ACE prefix, used in the conversion operations (section 4), is two
+ alphanumeric ASCII characters followed by two hyphen-minuses. It
+ cannot be any of the prefixes already used in earlier documents,
+ which includes the following: "bl--", "bq--", "dq--", "lq--", "mq--",
+ "ra--", "wq--" and "zq--". The ToASCII and ToUnicode operations MUST
+ recognize the ACE prefix in a case-insensitive manner.
+
+ The ACE prefix for IDNA is "xn--" or any capitalization thereof.
+
+ This means that an ACE label might be "xn--de-jg4avhby1noc0d", where
+ "de-jg4avhby1noc0d" is the part of the ACE label that is generated by
+ the encoding steps in [PUNYCODE].
+
+ While all ACE labels begin with the ACE prefix, not all labels
+ beginning with the ACE prefix are necessarily ACE labels. Non-ACE
+ labels that begin with the ACE prefix will confuse users and SHOULD
+ NOT be allowed in DNS zones.
+
+
+
+
+
+
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 12]
+
+RFC 3490 IDNA March 2003
+
+
+6. Implications for typical applications using DNS
+
+ In IDNA, applications perform the processing needed to input
+ internationalized domain names from users, display internationalized
+ domain names to users, and process the inputs and outputs from DNS
+ and other protocols that carry domain names.
+
+ The components and interfaces between them can be represented
+ pictorially as:
+
+ +------+
+ | User |
+ +------+
+ ^
+ | Input and display: local interface methods
+ | (pen, keyboard, glowing phosphorus, ...)
+ +-------------------|-------------------------------+
+ | v |
+ | +-----------------------------+ |
+ | | Application | |
+ | | (ToASCII and ToUnicode | |
+ | | operations may be | |
+ | | called here) | |
+ | +-----------------------------+ |
+ | ^ ^ | End system
+ | | | |
+ | Call to resolver: | | Application-specific |
+ | ACE | | protocol: |
+ | v | ACE unless the |
+ | +----------+ | protocol is updated |
+ | | Resolver | | to handle other |
+ | +----------+ | encodings |
+ | ^ | |
+ +-----------------|----------|----------------------+
+ DNS protocol: | |
+ ACE | |
+ v v
+ +-------------+ +---------------------+
+ | DNS servers | | Application servers |
+ +-------------+ +---------------------+
+
+ The box labeled "Application" is where the application splits a
+ domain name into labels, sets the appropriate flags, and performs the
+ ToASCII and ToUnicode operations. This is described in section 4.
+
+
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 13]
+
+RFC 3490 IDNA March 2003
+
+
+6.1 Entry and display in applications
+
+ Applications can accept domain names using any character set or sets
+ desired by the application developer, and can display domain names in
+ any charset. That is, the IDNA protocol does not affect the
+ interface between users and applications.
+
+ An IDNA-aware application can accept and display internationalized
+ domain names in two formats: the internationalized character set(s)
+ supported by the application, and as an ACE label. ACE labels that
+ are displayed or input MUST always include the ACE prefix.
+ Applications MAY allow input and display of ACE labels, but are not
+ encouraged to do so except as an interface for special purposes,
+ possibly for debugging, or to cope with display limitations as
+ described in section 6.4.. ACE encoding is opaque and ugly, and
+ should thus only be exposed to users who absolutely need it. Because
+ name labels encoded as ACE name labels can be rendered either as the
+ encoded ASCII characters or the proper decoded characters, the
+ application MAY have an option for the user to select the preferred
+ method of display; if it does, rendering the ACE SHOULD NOT be the
+ default.
+
+ Domain names are often stored and transported in many places. For
+ example, they are part of documents such as mail messages and web
+ pages. They are transported in many parts of many protocols, such as
+ both the control commands and the RFC 2822 body parts of SMTP, and
+ the headers and the body content in HTTP. It is important to
+ remember that domain names appear both in domain name slots and in
+ the content that is passed over protocols.
+
+ In protocols and document formats that define how to handle
+ specification or negotiation of charsets, labels can be encoded in
+ any charset allowed by the protocol or document format. If a
+ protocol or document format only allows one charset, the labels MUST
+ be given in that charset.
+
+ In any place where a protocol or document format allows transmission
+ of the characters in internationalized labels, internationalized
+ labels SHOULD be transmitted using whatever character encoding and
+ escape mechanism that the protocol or document format uses at that
+ place.
+
+ All protocols that use domain name slots already have the capacity
+ for handling domain names in the ASCII charset. Thus, ACE labels
+ (internationalized labels that have been processed with the ToASCII
+ operation) can inherently be handled by those protocols.
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 14]
+
+RFC 3490 IDNA March 2003
+
+
+6.2 Applications and resolver libraries
+
+ Applications normally use functions in the operating system when they
+ resolve DNS queries. Those functions in the operating system are
+ often called "the resolver library", and the applications communicate
+ with the resolver libraries through a programming interface (API).
+
+ Because these resolver libraries today expect only domain names in
+ ASCII, applications MUST prepare labels that are passed to the
+ resolver library using the ToASCII operation. Labels received from
+ the resolver library contain only ASCII characters; internationalized
+ labels that cannot be represented directly in ASCII use the ACE form.
+ ACE labels always include the ACE prefix.
+
+ An operating system might have a set of libraries for performing the
+ ToASCII operation. The input to such a library might be in one or
+ more charsets that are used in applications (UTF-8 and UTF-16 are
+ likely candidates for almost any operating system, and script-
+ specific charsets are likely for localized operating systems).
+
+ IDNA-aware applications MUST be able to work with both non-
+ internationalized labels (those that conform to [STD13] and [STD3])
+ and internationalized labels.
+
+ It is expected that new versions of the resolver libraries in the
+ future will be able to accept domain names in other charsets than
+ ASCII, and application developers might one day pass not only domain
+ names in Unicode, but also in local script to a new API for the
+ resolver libraries in the operating system. Thus the ToASCII and
+ ToUnicode operations might be performed inside these new versions of
+ the resolver libraries.
+
+ Domain names passed to resolvers or put into the question section of
+ DNS requests follow the rules for "queries" from [STRINGPREP].
+
+6.3 DNS servers
+
+ Domain names stored in zones follow the rules for "stored strings"
+ from [STRINGPREP].
+
+ For internationalized labels that cannot be represented directly in
+ ASCII, DNS servers MUST use the ACE form produced by the ToASCII
+ operation. All IDNs served by DNS servers MUST contain only ASCII
+ characters.
+
+ If a signaling system which makes negotiation possible between old
+ and new DNS clients and servers is standardized in the future, the
+ encoding of the query in the DNS protocol itself can be changed from
+
+
+
+Faltstrom, et al. Standards Track [Page 15]
+
+RFC 3490 IDNA March 2003
+
+
+ ACE to something else, such as UTF-8. The question whether or not
+ this should be used is, however, a separate problem and is not
+ discussed in this memo.
+
+6.4 Avoiding exposing users to the raw ACE encoding
+
+ Any application that might show the user a domain name obtained from
+ a domain name slot, such as from gethostbyaddr or part of a mail
+ header, will need to be updated if it is to prevent users from seeing
+ the ACE.
+
+ If an application decodes an ACE name using ToUnicode but cannot show
+ all of the characters in the decoded name, such as if the name
+ contains characters that the output system cannot display, the
+ application SHOULD show the name in ACE format (which always includes
+ the ACE prefix) instead of displaying the name with the replacement
+ character (U+FFFD). This is to make it easier for the user to
+ transfer the name correctly to other programs. Programs that by
+ default show the ACE form when they cannot show all the characters in
+ a name label SHOULD also have a mechanism to show the name that is
+ produced by the ToUnicode operation with as many characters as
+ possible and replacement characters in the positions where characters
+ cannot be displayed.
+
+ The ToUnicode operation does not alter labels that are not valid ACE
+ labels, even if they begin with the ACE prefix. After ToUnicode has
+ been applied, if a label still begins with the ACE prefix, then it is
+ not a valid ACE label, and is not equivalent to any of the
+ intermediate Unicode strings constructed by ToUnicode.
+
+6.5 DNSSEC authentication of IDN domain names
+
+ DNS Security [RFC2535] is a method for supplying cryptographic
+ verification information along with DNS messages. Public Key
+ Cryptography is used in conjunction with digital signatures to
+ provide a means for a requester of domain information to authenticate
+ the source of the data. This ensures that it can be traced back to a
+ trusted source, either directly, or via a chain of trust linking the
+ source of the information to the top of the DNS hierarchy.
+
+ IDNA specifies that all internationalized domain names served by DNS
+ servers that cannot be represented directly in ASCII must use the ACE
+ form produced by the ToASCII operation. This operation must be
+ performed prior to a zone being signed by the private key for that
+ zone. Because of this ordering, it is important to recognize that
+ DNSSEC authenticates the ASCII domain name, not the Unicode form or
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 16]
+
+RFC 3490 IDNA March 2003
+
+
+ the mapping between the Unicode form and the ASCII form. In the
+ presence of DNSSEC, this is the name that MUST be signed in the zone
+ and MUST be validated against.
+
+ One consequence of this for sites deploying IDNA in the presence of
+ DNSSEC is that any special purpose proxies or forwarders used to
+ transform user input into IDNs must be earlier in the resolution flow
+ than DNSSEC authenticating nameservers for DNSSEC to work.
+
+7. Name server considerations
+
+ Existing DNS servers do not know the IDNA rules for handling non-
+ ASCII forms of IDNs, and therefore need to be shielded from them.
+ All existing channels through which names can enter a DNS server
+ database (for example, master files [STD13] and DNS update messages
+ [RFC2136]) are IDN-unaware because they predate IDNA, and therefore
+ requirement 2 of section 3.1 of this document provides the needed
+ shielding, by ensuring that internationalized domain names entering
+ DNS server databases through such channels have already been
+ converted to their equivalent ASCII forms.
+
+ It is imperative that there be only one ASCII encoding for a
+ particular domain name. Because of the design of the ToASCII and
+ ToUnicode operations, there are no ACE labels that decode to ASCII
+ labels, and therefore name servers cannot contain multiple ASCII
+ encodings of the same domain name.
+
+ [RFC2181] explicitly allows domain labels to contain octets beyond
+ the ASCII range (0..7F), and this document does not change that.
+ Note, however, that there is no defined interpretation of octets
+ 80..FF as characters. If labels containing these octets are returned
+ to applications, unpredictable behavior could result. The ASCII form
+ defined by ToASCII is the only standard representation for
+ internationalized labels in the current DNS protocol.
+
+8. Root server considerations
+
+ IDNs are likely to be somewhat longer than current domain names, so
+ the bandwidth needed by the root servers is likely to go up by a
+ small amount. Also, queries and responses for IDNs will probably be
+ somewhat longer than typical queries today, so more queries and
+ responses may be forced to go to TCP instead of UDP.
+
+
+
+
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 17]
+
+RFC 3490 IDNA March 2003
+
+
+9. References
+
+9.1 Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [STRINGPREP] Hoffman, P. and M. Blanchet, "Preparation of
+ Internationalized Strings ("stringprep")", RFC 3454,
+ December 2002.
+
+ [NAMEPREP] Hoffman, P. and M. Blanchet, "Nameprep: A Stringprep
+ Profile for Internationalized Domain Names (IDN)", RFC
+ 3491, March 2003.
+
+ [PUNYCODE] Costello, A., "Punycode: A Bootstring encoding of
+ Unicode for use with Internationalized Domain Names in
+ Applications (IDNA)", RFC 3492, March 2003.
+
+ [STD3] Braden, R., "Requirements for Internet Hosts --
+ Communication Layers", STD 3, RFC 1122, and
+ "Requirements for Internet Hosts -- Application and
+ Support", STD 3, RFC 1123, October 1989.
+
+ [STD13] Mockapetris, P., "Domain names - concepts and
+ facilities", STD 13, RFC 1034 and "Domain names -
+ implementation and specification", STD 13, RFC 1035,
+ November 1987.
+
+9.2 Informative References
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [UAX9] Unicode Standard Annex #9, The Bidirectional Algorithm,
+ <http://www.unicode.org/unicode/reports/tr9/>.
+
+ [UNICODE] The Unicode Consortium. The Unicode Standard, Version
+ 3.2.0 is defined by The Unicode Standard, Version 3.0
+ (Reading, MA, Addison-Wesley, 2000. ISBN 0-201-61633-5),
+ as amended by the Unicode Standard Annex #27: Unicode
+ 3.1 (http://www.unicode.org/reports/tr27/) and by the
+ Unicode Standard Annex #28: Unicode 3.2
+ (http://www.unicode.org/reports/tr28/).
+
+
+
+
+Faltstrom, et al. Standards Track [Page 18]
+
+RFC 3490 IDNA March 2003
+
+
+ [USASCII] Cerf, V., "ASCII format for Network Interchange", RFC
+ 20, October 1969.
+
+10. Security Considerations
+
+ Security on the Internet partly relies on the DNS. Thus, any change
+ to the characteristics of the DNS can change the security of much of
+ the Internet.
+
+ This memo describes an algorithm which encodes characters that are
+ not valid according to STD3 and STD13 into octet values that are
+ valid. No security issues such as string length increases or new
+ allowed values are introduced by the encoding process or the use of
+ these encoded values, apart from those introduced by the ACE encoding
+ itself.
+
+ Domain names are used by users to identify and connect to Internet
+ servers. The security of the Internet is compromised if a user
+ entering a single internationalized name is connected to different
+ servers based on different interpretations of the internationalized
+ domain name.
+
+ When systems use local character sets other than ASCII and Unicode,
+ this specification leaves the the problem of transcoding between the
+ local character set and Unicode up to the application. If different
+ applications (or different versions of one application) implement
+ different transcoding rules, they could interpret the same name
+ differently and contact different servers. This problem is not
+ solved by security protocols like TLS that do not take local
+ character sets into account.
+
+ Because this document normatively refers to [NAMEPREP], [PUNYCODE],
+ and [STRINGPREP], it includes the security considerations from those
+ documents as well.
+
+ If or when this specification is updated to use a more recent Unicode
+ normalization table, the new normalization table will need to be
+ compared with the old to spot backwards incompatible changes. If
+ there are such changes, they will need to be handled somehow, or
+ there will be security as well as operational implications. Methods
+ to handle the conflicts could include keeping the old normalization,
+ or taking care of the conflicting characters by operational means, or
+ some other method.
+
+ Implementations MUST NOT use more recent normalization tables than
+ the one referenced from this document, even though more recent tables
+ may be provided by operating systems. If an application is unsure of
+ which version of the normalization tables are in the operating
+
+
+
+Faltstrom, et al. Standards Track [Page 19]
+
+RFC 3490 IDNA March 2003
+
+
+ system, the application needs to include the normalization tables
+ itself. Using normalization tables other than the one referenced
+ from this specification could have security and operational
+ implications.
+
+ To help prevent confusion between characters that are visually
+ similar, it is suggested that implementations provide visual
+ indications where a domain name contains multiple scripts. Such
+ mechanisms can also be used to show when a name contains a mixture of
+ simplified and traditional Chinese characters, or to distinguish zero
+ and one from O and l. DNS zone adminstrators may impose restrictions
+ (subject to the limitations in section 2) that try to minimize
+ homographs.
+
+ Domain names (or portions of them) are sometimes compared against a
+ set of privileged or anti-privileged domains. In such situations it
+ is especially important that the comparisons be done properly, as
+ specified in section 3.1 requirement 4. For labels already in ASCII
+ form, the proper comparison reduces to the same case-insensitive
+ ASCII comparison that has always been used for ASCII labels.
+
+ The introduction of IDNA means that any existing labels that start
+ with the ACE prefix and would be altered by ToUnicode will
+ automatically be ACE labels, and will be considered equivalent to
+ non-ASCII labels, whether or not that was the intent of the zone
+ adminstrator or registrant.
+
+11. IANA Considerations
+
+ IANA has assigned the ACE prefix in consultation with the IESG.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 20]
+
+RFC 3490 IDNA March 2003
+
+
+12. Authors' Addresses
+
+ Patrik Faltstrom
+ Cisco Systems
+ Arstaangsvagen 31 J
+ S-117 43 Stockholm Sweden
+
+ EMail: paf@cisco.com
+
+
+ Paul Hoffman
+ Internet Mail Consortium and VPN Consortium
+ 127 Segre Place
+ Santa Cruz, CA 95060 USA
+
+ EMail: phoffman@imc.org
+
+
+ Adam M. Costello
+ University of California, Berkeley
+
+ URL: http://www.nicemice.net/amc/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 21]
+
+RFC 3490 IDNA March 2003
+
+
+13. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Faltstrom, et al. Standards Track [Page 22]
+
diff --git a/doc/rfc/rfc3491.txt b/doc/rfc/rfc3491.txt
new file mode 100644
index 0000000..dbc86c7
--- /dev/null
+++ b/doc/rfc/rfc3491.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group P. Hoffman
+Request for Comments: 3491 IMC & VPNC
+Category: Standards Track M. Blanchet
+ Viagenie
+ March 2003
+
+
+ Nameprep: A Stringprep Profile for
+ Internationalized Domain Names (IDN)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ This document describes how to prepare internationalized domain name
+ (IDN) labels in order to increase the likelihood that name input and
+ name comparison work in ways that make sense for typical users
+ throughout the world. This profile of the stringprep protocol is
+ used as part of a suite of on-the-wire protocols for
+ internationalizing the Domain Name System (DNS).
+
+1. Introduction
+
+ This document specifies processing rules that will allow users to
+ enter internationalized domain names (IDNs) into applications and
+ have the highest chance of getting the content of the strings
+ correct. It is a profile of stringprep [STRINGPREP]. These
+ processing rules are only intended for internationalized domain
+ names, not for arbitrary text.
+
+ This profile defines the following, as required by [STRINGPREP].
+
+ - The intended applicability of the profile: internationalized
+ domain names processed by IDNA.
+
+ - The character repertoire that is the input and output to
+ stringprep: Unicode 3.2, specified in section 2.
+
+
+
+
+Hoffman & Blanchet Standards Track [Page 1]
+
+RFC 3491 IDN Nameprep March 2003
+
+
+ - The mappings used: specified in section 3.
+
+ - The Unicode normalization used: specified in section 4.
+
+ - The characters that are prohibited as output: specified in section
+ 5.
+
+ - Bidirectional character handling: specified in section 6.
+
+1.1 Interaction of protocol parts
+
+ Nameprep is used by the IDNA [IDNA] protocol for preparing domain
+ names; it is not designed for any other purpose. It is explicitly
+ not designed for processing arbitrary free text and SHOULD NOT be
+ used for that purpose. Nameprep is a profile of Stringprep
+ [STRINGPREP]. Implementations of Nameprep MUST fully implement
+ Stringprep.
+
+ Nameprep is used to process domain name labels, not domain names.
+ IDNA calls nameprep for each label in a domain name, not for the
+ whole domain name.
+
+1.2 Terminology
+
+ The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY"
+ in this document are to be interpreted as described in BCP 14, RFC
+ 2119 [RFC2119].
+
+2. Character Repertoire
+
+ This profile uses Unicode 3.2, as defined in [STRINGPREP] Appendix A.
+
+3. Mapping
+
+ This profile specifies mapping using the following tables from
+ [STRINGPREP]:
+
+ Table B.1
+ Table B.2
+
+4. Normalization
+
+ This profile specifies using Unicode normalization form KC, as
+ described in [STRINGPREP].
+
+
+
+
+
+
+
+Hoffman & Blanchet Standards Track [Page 2]
+
+RFC 3491 IDN Nameprep March 2003
+
+
+5. Prohibited Output
+
+ This profile specifies prohibiting using the following tables from
+ [STRINGPREP]:
+
+ Table C.1.2
+ Table C.2.2
+ Table C.3
+ Table C.4
+ Table C.5
+ Table C.6
+ Table C.7
+ Table C.8
+ Table C.9
+
+ IMPORTANT NOTE: This profile MUST be used with the IDNA protocol.
+ The IDNA protocol has additional prohibitions that are checked
+ outside of this profile.
+
+6. Bidirectional characters
+
+ This profile specifies checking bidirectional strings as described in
+ [STRINGPREP] section 6.
+
+7. Unassigned Code Points in Internationalized Domain Names
+
+ If the processing in [IDNA] specifies that a list of unassigned code
+ points be used, the system uses table A.1 from [STRINGPREP] as its
+ list of unassigned code points.
+
+8. References
+
+8.1 Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [STRINGPREP] Hoffman, P. and M. Blanchet, "Preparation of
+ Internationalized Strings ("stringprep")", RFC 3454,
+ December 2002.
+
+ [IDNA] Faltstrom, P., Hoffman, P. and A. Costello,
+ "Internationalizing Domain Names in Applications
+ (IDNA)", RFC 3490, March 2003.
+
+
+
+
+
+
+
+Hoffman & Blanchet Standards Track [Page 3]
+
+RFC 3491 IDN Nameprep March 2003
+
+
+8.2 Informative references
+
+ [STD13] Mockapetris, P., "Domain names - concepts and
+ facilities", STD 13, RFC 1034, and "Domain names -
+ implementation and specification", STD 13, RFC 1035,
+ November 1987.
+
+9. Security Considerations
+
+ The Unicode and ISO/IEC 10646 repertoires have many characters that
+ look similar. In many cases, users of security protocols might do
+ visual matching, such as when comparing the names of trusted third
+ parties. Because it is impossible to map similar-looking characters
+ without a great deal of context such as knowing the fonts used,
+ stringprep does nothing to map similar-looking characters together
+ nor to prohibit some characters because they look like others.
+
+ Security on the Internet partly relies on the DNS. Thus, any change
+ to the characteristics of the DNS can change the security of much of
+ the Internet.
+
+ Domain names are used by users to connect to Internet servers. The
+ security of the Internet would be compromised if a user entering a
+ single internationalized name could be connected to different servers
+ based on different interpretations of the internationalized domain
+ name.
+
+ Current applications might assume that the characters allowed in
+ domain names will always be the same as they are in [STD13]. This
+ document vastly increases the number of characters available in
+ domain names. Every program that uses "special" characters in
+ conjunction with domain names may be vulnerable to attack based on
+ the new characters allowed by this specification.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hoffman & Blanchet Standards Track [Page 4]
+
+RFC 3491 IDN Nameprep March 2003
+
+
+10. IANA Considerations
+
+ This is a profile of stringprep. It has been registered by the IANA
+ in the stringprep profile registry
+ (www.iana.org/assignments/stringprep-profiles).
+
+ Name of this profile:
+ Nameprep
+
+ RFC in which the profile is defined:
+ This document.
+
+ Indicator whether or not this is the newest version of the
+ profile:
+ This is the first version of Nameprep.
+
+11. Acknowledgements
+
+ Many people from the IETF IDN Working Group and the Unicode Technical
+ Committee contributed ideas that went into this document.
+
+ The IDN Nameprep design team made many useful changes to the
+ document. That team and its advisors include:
+
+ Asmus Freytag
+ Cathy Wissink
+ Francois Yergeau
+ James Seng
+ Marc Blanchet
+ Mark Davis
+ Martin Duerst
+ Patrik Faltstrom
+ Paul Hoffman
+
+ Additional significant improvements were proposed by:
+
+ Jonathan Rosenne
+ Kent Karlsson
+ Scott Hollenbeck
+ Dave Crocker
+ Erik Nordmark
+ Matitiahu Allouche
+
+
+
+
+
+
+
+
+
+Hoffman & Blanchet Standards Track [Page 5]
+
+RFC 3491 IDN Nameprep March 2003
+
+
+12. Authors' Addresses
+
+ Paul Hoffman
+ Internet Mail Consortium and VPN Consortium
+ 127 Segre Place
+ Santa Cruz, CA 95060 USA
+
+ EMail: paul.hoffman@imc.org and paul.hoffman@vpnc.org
+
+
+ Marc Blanchet
+ Viagenie inc.
+ 2875 boul. Laurier, bur. 300
+ Ste-Foy, Quebec, Canada, G1V 2M2
+
+ EMail: Marc.Blanchet@viagenie.qc.ca
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hoffman & Blanchet Standards Track [Page 6]
+
+RFC 3491 IDN Nameprep March 2003
+
+
+13. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hoffman & Blanchet Standards Track [Page 7]
+
diff --git a/doc/rfc/rfc3492.txt b/doc/rfc/rfc3492.txt
new file mode 100644
index 0000000..e72ad81
--- /dev/null
+++ b/doc/rfc/rfc3492.txt
@@ -0,0 +1,1963 @@
+
+
+
+
+
+
+Network Working Group A. Costello
+Request for Comments: 3492 Univ. of California, Berkeley
+Category: Standards Track March 2003
+
+
+ Punycode: A Bootstring encoding of Unicode
+ for Internationalized Domain Names in Applications (IDNA)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ Punycode is a simple and efficient transfer encoding syntax designed
+ for use with Internationalized Domain Names in Applications (IDNA).
+ It uniquely and reversibly transforms a Unicode string into an ASCII
+ string. ASCII characters in the Unicode string are represented
+ literally, and non-ASCII characters are represented by ASCII
+ characters that are allowed in host name labels (letters, digits, and
+ hyphens). This document defines a general algorithm called
+ Bootstring that allows a string of basic code points to uniquely
+ represent any string of code points drawn from a larger set.
+ Punycode is an instance of Bootstring that uses particular parameter
+ values specified by this document, appropriate for IDNA.
+
+Table of Contents
+
+ 1. Introduction...............................................2
+ 1.1 Features..............................................2
+ 1.2 Interaction of protocol parts.........................3
+ 2. Terminology................................................3
+ 3. Bootstring description.....................................4
+ 3.1 Basic code point segregation..........................4
+ 3.2 Insertion unsort coding...............................4
+ 3.3 Generalized variable-length integers..................5
+ 3.4 Bias adaptation.......................................7
+ 4. Bootstring parameters......................................8
+ 5. Parameter values for Punycode..............................8
+ 6. Bootstring algorithms......................................9
+
+
+
+Costello Standards Track [Page 1]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ 6.1 Bias adaptation function.............................10
+ 6.2 Decoding procedure...................................11
+ 6.3 Encoding procedure...................................12
+ 6.4 Overflow handling....................................13
+ 7. Punycode examples.........................................14
+ 7.1 Sample strings.......................................14
+ 7.2 Decoding traces......................................17
+ 7.3 Encoding traces......................................19
+ 8. Security Considerations...................................20
+ 9. References................................................21
+ 9.1 Normative References.................................21
+ 9.2 Informative References...............................21
+ A. Mixed-case annotation.....................................22
+ B. Disclaimer and license....................................22
+ C. Punycode sample implementation............................23
+ Author's Address.............................................34
+ Full Copyright Statement.....................................35
+
+1. Introduction
+
+ [IDNA] describes an architecture for supporting internationalized
+ domain names. Labels containing non-ASCII characters can be
+ represented by ACE labels, which begin with a special ACE prefix and
+ contain only ASCII characters. The remainder of the label after the
+ prefix is a Punycode encoding of a Unicode string satisfying certain
+ constraints. For the details of the prefix and constraints, see
+ [IDNA] and [NAMEPREP].
+
+ Punycode is an instance of a more general algorithm called
+ Bootstring, which allows strings composed from a small set of "basic"
+ code points to uniquely represent any string of code points drawn
+ from a larger set. Punycode is Bootstring with particular parameter
+ values appropriate for IDNA.
+
+1.1 Features
+
+ Bootstring has been designed to have the following features:
+
+ * Completeness: Every extended string (sequence of arbitrary code
+ points) can be represented by a basic string (sequence of basic
+ code points). Restrictions on what strings are allowed, and on
+ length, can be imposed by higher layers.
+
+ * Uniqueness: There is at most one basic string that represents a
+ given extended string.
+
+ * Reversibility: Any extended string mapped to a basic string can
+ be recovered from that basic string.
+
+
+
+Costello Standards Track [Page 2]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ * Efficient encoding: The ratio of basic string length to extended
+ string length is small. This is important in the context of
+ domain names because RFC 1034 [RFC1034] restricts the length of a
+ domain label to 63 characters.
+
+ * Simplicity: The encoding and decoding algorithms are reasonably
+ simple to implement. The goals of efficiency and simplicity are
+ at odds; Bootstring aims at a good balance between them.
+
+ * Readability: Basic code points appearing in the extended string
+ are represented as themselves in the basic string (although the
+ main purpose is to improve efficiency, not readability).
+
+ Punycode can also support an additional feature that is not used by
+ the ToASCII and ToUnicode operations of [IDNA]. When extended
+ strings are case-folded prior to encoding, the basic string can use
+ mixed case to tell how to convert the folded string into a mixed-case
+ string. See appendix A "Mixed-case annotation".
+
+1.2 Interaction of protocol parts
+
+ Punycode is used by the IDNA protocol [IDNA] for converting domain
+ labels into ASCII; it is not designed for any other purpose. It is
+ explicitly not designed for processing arbitrary free text.
+
+2. Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119
+ [RFC2119].
+
+ A code point is an integral value associated with a character in a
+ coded character set.
+
+ As in the Unicode Standard [UNICODE], Unicode code points are denoted
+ by "U+" followed by four to six hexadecimal digits, while a range of
+ code points is denoted by two hexadecimal numbers separated by "..",
+ with no prefixes.
+
+ The operators div and mod perform integer division; (x div y) is the
+ quotient of x divided by y, discarding the remainder, and (x mod y)
+ is the remainder, so (x div y) * y + (x mod y) == x. Bootstring uses
+ these operators only with nonnegative operands, so the quotient and
+ remainder are always nonnegative.
+
+ The break statement jumps out of the innermost loop (as in C).
+
+
+
+
+Costello Standards Track [Page 3]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ An overflow is an attempt to compute a value that exceeds the maximum
+ value of an integer variable.
+
+3. Bootstring description
+
+ Bootstring represents an arbitrary sequence of code points (the
+ "extended string") as a sequence of basic code points (the "basic
+ string"). This section describes the representation. Section 6
+ "Bootstring algorithms" presents the algorithms as pseudocode.
+ Sections 7.1 "Decoding traces" and 7.2 "Encoding traces" trace the
+ algorithms for sample inputs.
+
+ The following sections describe the four techniques used in
+ Bootstring. "Basic code point segregation" is a very simple and
+ efficient encoding for basic code points occurring in the extended
+ string: they are simply copied all at once. "Insertion unsort
+ coding" encodes the non-basic code points as deltas, and processes
+ the code points in numerical order rather than in order of
+ appearance, which typically results in smaller deltas. The deltas
+ are represented as "generalized variable-length integers", which use
+ basic code points to represent nonnegative integers. The parameters
+ of this integer representation are dynamically adjusted using "bias
+ adaptation", to improve efficiency when consecutive deltas have
+ similar magnitudes.
+
+3.1 Basic code point segregation
+
+ All basic code points appearing in the extended string are
+ represented literally at the beginning of the basic string, in their
+ original order, followed by a delimiter if (and only if) the number
+ of basic code points is nonzero. The delimiter is a particular basic
+ code point, which never appears in the remainder of the basic string.
+ The decoder can therefore find the end of the literal portion (if
+ there is one) by scanning for the last delimiter.
+
+3.2 Insertion unsort coding
+
+ The remainder of the basic string (after the last delimiter if there
+ is one) represents a sequence of nonnegative integral deltas as
+ generalized variable-length integers, described in section 3.3. The
+ meaning of the deltas is best understood in terms of the decoder.
+
+ The decoder builds the extended string incrementally. Initially, the
+ extended string is a copy of the literal portion of the basic string
+ (excluding the last delimiter). The decoder inserts non-basic code
+ points, one for each delta, into the extended string, ultimately
+ arriving at the final decoded string.
+
+
+
+
+Costello Standards Track [Page 4]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ At the heart of this process is a state machine with two state
+ variables: an index i and a counter n. The index i refers to a
+ position in the extended string; it ranges from 0 (the first
+ position) to the current length of the extended string (which refers
+ to a potential position beyond the current end). If the current
+ state is <n,i>, the next state is <n,i+1> if i is less than the
+ length of the extended string, or <n+1,0> if i equals the length of
+ the extended string. In other words, each state change causes i to
+ increment, wrapping around to zero if necessary, and n counts the
+ number of wrap-arounds.
+
+ Notice that the state always advances monotonically (there is no way
+ for the decoder to return to an earlier state). At each state, an
+ insertion is either performed or not performed. At most one
+ insertion is performed in a given state. An insertion inserts the
+ value of n at position i in the extended string. The deltas are a
+ run-length encoding of this sequence of events: they are the lengths
+ of the runs of non-insertion states preceeding the insertion states.
+ Hence, for each delta, the decoder performs delta state changes, then
+ an insertion, and then one more state change. (An implementation
+ need not perform each state change individually, but can instead use
+ division and remainder calculations to compute the next insertion
+ state directly.) It is an error if the inserted code point is a
+ basic code point (because basic code points were supposed to be
+ segregated as described in section 3.1).
+
+ The encoder's main task is to derive the sequence of deltas that will
+ cause the decoder to construct the desired string. It can do this by
+ repeatedly scanning the extended string for the next code point that
+ the decoder would need to insert, and counting the number of state
+ changes the decoder would need to perform, mindful of the fact that
+ the decoder's extended string will include only those code points
+ that have already been inserted. Section 6.3 "Encoding procedure"
+ gives a precise algorithm.
+
+3.3 Generalized variable-length integers
+
+ In a conventional integer representation the base is the number of
+ distinct symbols for digits, whose values are 0 through base-1. Let
+ digit_0 denote the least significant digit, digit_1 the next least
+ significant, and so on. The value represented is the sum over j of
+ digit_j * w(j), where w(j) = base^j is the weight (scale factor) for
+ position j. For example, in the base 8 integer 437, the digits are
+ 7, 3, and 4, and the weights are 1, 8, and 64, so the value is 7 +
+ 3*8 + 4*64 = 287. This representation has two disadvantages: First,
+ there are multiple encodings of each value (because there can be
+ extra zeros in the most significant positions), which is inconvenient
+
+
+
+
+Costello Standards Track [Page 5]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ when unique encodings are needed. Second, the integer is not self-
+ delimiting, so if multiple integers are concatenated the boundaries
+ between them are lost.
+
+ The generalized variable-length representation solves these two
+ problems. The digit values are still 0 through base-1, but now the
+ integer is self-delimiting by means of thresholds t(j), each of which
+ is in the range 0 through base-1. Exactly one digit, the most
+ significant, satisfies digit_j < t(j). Therefore, if several
+ integers are concatenated, it is easy to separate them, starting with
+ the first if they are little-endian (least significant digit first),
+ or starting with the last if they are big-endian (most significant
+ digit first). As before, the value is the sum over j of digit_j *
+ w(j), but the weights are different:
+
+ w(0) = 1
+ w(j) = w(j-1) * (base - t(j-1)) for j > 0
+
+ For example, consider the little-endian sequence of base 8 digits
+ 734251... Suppose the thresholds are 2, 3, 5, 5, 5, 5... This
+ implies that the weights are 1, 1*(8-2) = 6, 6*(8-3) = 30, 30*(8-5) =
+ 90, 90*(8-5) = 270, and so on. 7 is not less than 2, and 3 is not
+ less than 3, but 4 is less than 5, so 4 is the last digit. The value
+ of 734 is 7*1 + 3*6 + 4*30 = 145. The next integer is 251, with
+ value 2*1 + 5*6 + 1*30 = 62. Decoding this representation is very
+ similar to decoding a conventional integer: Start with a current
+ value of N = 0 and a weight w = 1. Fetch the next digit d and
+ increase N by d * w. If d is less than the current threshold (t)
+ then stop, otherwise increase w by a factor of (base - t), update t
+ for the next position, and repeat.
+
+ Encoding this representation is similar to encoding a conventional
+ integer: If N < t then output one digit for N and stop, otherwise
+ output the digit for t + ((N - t) mod (base - t)), then replace N
+ with (N - t) div (base - t), update t for the next position, and
+ repeat.
+
+ For any particular set of values of t(j), there is exactly one
+ generalized variable-length representation of each nonnegative
+ integral value.
+
+ Bootstring uses little-endian ordering so that the deltas can be
+ separated starting with the first. The t(j) values are defined in
+ terms of the constants base, tmin, and tmax, and a state variable
+ called bias:
+
+ t(j) = base * (j + 1) - bias,
+ clamped to the range tmin through tmax
+
+
+
+Costello Standards Track [Page 6]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ The clamping means that if the formula yields a value less than tmin
+ or greater than tmax, then t(j) = tmin or tmax, respectively. (In
+ the pseudocode in section 6 "Bootstring algorithms", the expression
+ base * (j + 1) is denoted by k for performance reasons.) These t(j)
+ values cause the representation to favor integers within a particular
+ range determined by the bias.
+
+3.4 Bias adaptation
+
+ After each delta is encoded or decoded, bias is set for the next
+ delta as follows:
+
+ 1. Delta is scaled in order to avoid overflow in the next step:
+
+ let delta = delta div 2
+
+ But when this is the very first delta, the divisor is not 2, but
+ instead a constant called damp. This compensates for the fact
+ that the second delta is usually much smaller than the first.
+
+ 2. Delta is increased to compensate for the fact that the next delta
+ will be inserting into a longer string:
+
+ let delta = delta + (delta div numpoints)
+
+ numpoints is the total number of code points encoded/decoded so
+ far (including the one corresponding to this delta itself, and
+ including the basic code points).
+
+ 3. Delta is repeatedly divided until it falls within a threshold, to
+ predict the minimum number of digits needed to represent the next
+ delta:
+
+ while delta > ((base - tmin) * tmax) div 2
+ do let delta = delta div (base - tmin)
+
+ 4. The bias is set:
+
+ let bias =
+ (base * the number of divisions performed in step 3) +
+ (((base - tmin + 1) * delta) div (delta + skew))
+
+ The motivation for this procedure is that the current delta
+ provides a hint about the likely size of the next delta, and so
+ t(j) is set to tmax for the more significant digits starting with
+ the one expected to be last, tmin for the less significant digits
+ up through the one expected to be third-last, and somewhere
+ between tmin and tmax for the digit expected to be second-last
+
+
+
+Costello Standards Track [Page 7]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ (balancing the hope of the expected-last digit being unnecessary
+ against the danger of it being insufficient).
+
+4. Bootstring parameters
+
+ Given a set of basic code points, one needs to be designated as the
+ delimiter. The base cannot be greater than the number of
+ distinguishable basic code points remaining. The digit-values in the
+ range 0 through base-1 need to be associated with distinct non-
+ delimiter basic code points. In some cases multiple code points need
+ to have the same digit-value; for example, uppercase and lowercase
+ versions of the same letter need to be equivalent if basic strings
+ are case-insensitive.
+
+ The initial value of n cannot be greater than the minimum non-basic
+ code point that could appear in extended strings.
+
+ The remaining five parameters (tmin, tmax, skew, damp, and the
+ initial value of bias) need to satisfy the following constraints:
+
+ 0 <= tmin <= tmax <= base-1
+ skew >= 1
+ damp >= 2
+ initial_bias mod base <= base - tmin
+
+ Provided the constraints are satisfied, these five parameters affect
+ efficiency but not correctness. They are best chosen empirically.
+
+ If support for mixed-case annotation is desired (see appendix A),
+ make sure that the code points corresponding to 0 through tmax-1 all
+ have both uppercase and lowercase forms.
+
+5. Parameter values for Punycode
+
+ Punycode uses the following Bootstring parameter values:
+
+ base = 36
+ tmin = 1
+ tmax = 26
+ skew = 38
+ damp = 700
+ initial_bias = 72
+ initial_n = 128 = 0x80
+
+ Although the only restriction Punycode imposes on the input integers
+ is that they be nonnegative, these parameters are especially designed
+ to work well with Unicode [UNICODE] code points, which are integers
+ in the range 0..10FFFF (but not D800..DFFF, which are reserved for
+
+
+
+Costello Standards Track [Page 8]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ use by the UTF-16 encoding of Unicode). The basic code points are
+ the ASCII [ASCII] code points (0..7F), of which U+002D (-) is the
+ delimiter, and some of the others have digit-values as follows:
+
+ code points digit-values
+ ------------ ----------------------
+ 41..5A (A-Z) = 0 to 25, respectively
+ 61..7A (a-z) = 0 to 25, respectively
+ 30..39 (0-9) = 26 to 35, respectively
+
+ Using hyphen-minus as the delimiter implies that the encoded string
+ can end with a hyphen-minus only if the Unicode string consists
+ entirely of basic code points, but IDNA forbids such strings from
+ being encoded. The encoded string can begin with a hyphen-minus, but
+ IDNA prepends a prefix. Therefore IDNA using Punycode conforms to
+ the RFC 952 rule that host name labels neither begin nor end with a
+ hyphen-minus [RFC952].
+
+ A decoder MUST recognize the letters in both uppercase and lowercase
+ forms (including mixtures of both forms). An encoder SHOULD output
+ only uppercase forms or only lowercase forms, unless it uses mixed-
+ case annotation (see appendix A).
+
+ Presumably most users will not manually write or type encoded strings
+ (as opposed to cutting and pasting them), but those who do will need
+ to be alert to the potential visual ambiguity between the following
+ sets of characters:
+
+ G 6
+ I l 1
+ O 0
+ S 5
+ U V
+ Z 2
+
+ Such ambiguities are usually resolved by context, but in a Punycode
+ encoded string there is no context apparent to humans.
+
+6. Bootstring algorithms
+
+ Some parts of the pseudocode can be omitted if the parameters satisfy
+ certain conditions (for which Punycode qualifies). These parts are
+ enclosed in {braces}, and notes immediately following the pseudocode
+ explain the conditions under which they can be omitted.
+
+
+
+
+
+
+
+Costello Standards Track [Page 9]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ Formally, code points are integers, and hence the pseudocode assumes
+ that arithmetic operations can be performed directly on code points.
+ In some programming languages, explicit conversion between code
+ points and integers might be necessary.
+
+6.1 Bias adaptation function
+
+ function adapt(delta,numpoints,firsttime):
+ if firsttime then let delta = delta div damp
+ else let delta = delta div 2
+ let delta = delta + (delta div numpoints)
+ let k = 0
+ while delta > ((base - tmin) * tmax) div 2 do begin
+ let delta = delta div (base - tmin)
+ let k = k + base
+ end
+ return k + (((base - tmin + 1) * delta) div (delta + skew))
+
+ It does not matter whether the modifications to delta and k inside
+ adapt() affect variables of the same name inside the
+ encoding/decoding procedures, because after calling adapt() the
+ caller does not read those variables before overwriting them.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Costello Standards Track [Page 10]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+6.2 Decoding procedure
+
+ let n = initial_n
+ let i = 0
+ let bias = initial_bias
+ let output = an empty string indexed from 0
+ consume all code points before the last delimiter (if there is one)
+ and copy them to output, fail on any non-basic code point
+ if more than zero code points were consumed then consume one more
+ (which will be the last delimiter)
+ while the input is not exhausted do begin
+ let oldi = i
+ let w = 1
+ for k = base to infinity in steps of base do begin
+ consume a code point, or fail if there was none to consume
+ let digit = the code point's digit-value, fail if it has none
+ let i = i + digit * w, fail on overflow
+ let t = tmin if k <= bias {+ tmin}, or
+ tmax if k >= bias + tmax, or k - bias otherwise
+ if digit < t then break
+ let w = w * (base - t), fail on overflow
+ end
+ let bias = adapt(i - oldi, length(output) + 1, test oldi is 0?)
+ let n = n + i div (length(output) + 1), fail on overflow
+ let i = i mod (length(output) + 1)
+ {if n is a basic code point then fail}
+ insert n into output at position i
+ increment i
+ end
+
+ The full statement enclosed in braces (checking whether n is a basic
+ code point) can be omitted if initial_n exceeds all basic code points
+ (which is true for Punycode), because n is never less than initial_n.
+
+ In the assignment of t, where t is clamped to the range tmin through
+ tmax, "+ tmin" can always be omitted. This makes the clamping
+ calculation incorrect when bias < k < bias + tmin, but that cannot
+ happen because of the way bias is computed and because of the
+ constraints on the parameters.
+
+ Because the decoder state can only advance monotonically, and there
+ is only one representation of any delta, there is therefore only one
+ encoded string that can represent a given sequence of integers. The
+ only error conditions are invalid code points, unexpected end-of-
+ input, overflow, and basic code points encoded using deltas instead
+ of appearing literally. If the decoder fails on these errors as
+ shown above, then it cannot produce the same output for two distinct
+ inputs. Without this property it would have been necessary to re-
+
+
+
+Costello Standards Track [Page 11]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ encode the output and verify that it matches the input in order to
+ guarantee the uniqueness of the encoding.
+
+6.3 Encoding procedure
+
+ let n = initial_n
+ let delta = 0
+ let bias = initial_bias
+ let h = b = the number of basic code points in the input
+ copy them to the output in order, followed by a delimiter if b > 0
+ {if the input contains a non-basic code point < n then fail}
+ while h < length(input) do begin
+ let m = the minimum {non-basic} code point >= n in the input
+ let delta = delta + (m - n) * (h + 1), fail on overflow
+ let n = m
+ for each code point c in the input (in order) do begin
+ if c < n {or c is basic} then increment delta, fail on overflow
+ if c == n then begin
+ let q = delta
+ for k = base to infinity in steps of base do begin
+ let t = tmin if k <= bias {+ tmin}, or
+ tmax if k >= bias + tmax, or k - bias otherwise
+ if q < t then break
+ output the code point for digit t + ((q - t) mod (base - t))
+ let q = (q - t) div (base - t)
+ end
+ output the code point for digit q
+ let bias = adapt(delta, h + 1, test h equals b?)
+ let delta = 0
+ increment h
+ end
+ end
+ increment delta and n
+ end
+
+ The full statement enclosed in braces (checking whether the input
+ contains a non-basic code point less than n) can be omitted if all
+ code points less than initial_n are basic code points (which is true
+ for Punycode if code points are unsigned).
+
+ The brace-enclosed conditions "non-basic" and "or c is basic" can be
+ omitted if initial_n exceeds all basic code points (which is true for
+ Punycode), because the code point being tested is never less than
+ initial_n.
+
+ In the assignment of t, where t is clamped to the range tmin through
+ tmax, "+ tmin" can always be omitted. This makes the clamping
+ calculation incorrect when bias < k < bias + tmin, but that cannot
+
+
+
+Costello Standards Track [Page 12]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ happen because of the way bias is computed and because of the
+ constraints on the parameters.
+
+ The checks for overflow are necessary to avoid producing invalid
+ output when the input contains very large values or is very long.
+
+ The increment of delta at the bottom of the outer loop cannot
+ overflow because delta < length(input) before the increment, and
+ length(input) is already assumed to be representable. The increment
+ of n could overflow, but only if h == length(input), in which case
+ the procedure is finished anyway.
+
+6.4 Overflow handling
+
+ For IDNA, 26-bit unsigned integers are sufficient to handle all valid
+ IDNA labels without overflow, because any string that needed a 27-bit
+ delta would have to exceed either the code point limit (0..10FFFF) or
+ the label length limit (63 characters). However, overflow handling
+ is necessary because the inputs are not necessarily valid IDNA
+ labels.
+
+ If the programming language does not provide overflow detection, the
+ following technique can be used. Suppose A, B, and C are
+ representable nonnegative integers and C is nonzero. Then A + B
+ overflows if and only if B > maxint - A, and A + (B * C) overflows if
+ and only if B > (maxint - A) div C, where maxint is the greatest
+ integer for which maxint + 1 cannot be represented. Refer to
+ appendix C "Punycode sample implementation" for demonstrations of
+ this technique in the C language.
+
+ The decoding and encoding algorithms shown in sections 6.2 and 6.3
+ handle overflow by detecting it whenever it happens. Another
+ approach is to enforce limits on the inputs that prevent overflow
+ from happening. For example, if the encoder were to verify that no
+ input code points exceed M and that the input length does not exceed
+ L, then no delta could ever exceed (M - initial_n) * (L + 1), and
+ hence no overflow could occur if integer variables were capable of
+ representing values that large. This prevention approach would
+ impose more restrictions on the input than the detection approach
+ does, but might be considered simpler in some programming languages.
+
+ In theory, the decoder could use an analogous approach, limiting the
+ number of digits in a variable-length integer (that is, limiting the
+ number of iterations in the innermost loop). However, the number of
+ digits that suffice to represent a given delta can sometimes
+ represent much larger deltas (because of the adaptation), and hence
+ this approach would probably need integers wider than 32 bits.
+
+
+
+
+Costello Standards Track [Page 13]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ Yet another approach for the decoder is to allow overflow to occur,
+ but to check the final output string by re-encoding it and comparing
+ to the decoder input. If and only if they do not match (using a
+ case-insensitive ASCII comparison) overflow has occurred. This
+ delayed-detection approach would not impose any more restrictions on
+ the input than the immediate-detection approach does, and might be
+ considered simpler in some programming languages.
+
+ In fact, if the decoder is used only inside the IDNA ToUnicode
+ operation [IDNA], then it need not check for overflow at all, because
+ ToUnicode performs a higher level re-encoding and comparison, and a
+ mismatch has the same consequence as if the Punycode decoder had
+ failed.
+
+7. Punycode examples
+
+7.1 Sample strings
+
+ In the Punycode encodings below, the ACE prefix is not shown.
+ Backslashes show where line breaks have been inserted in strings too
+ long for one line.
+
+ The first several examples are all translations of the sentence "Why
+ can't they just speak in <language>?" (courtesy of Michael Kaplan's
+ "provincial" page [PROVINCIAL]). Word breaks and punctuation have
+ been removed, as is often done in domain names.
+
+ (A) Arabic (Egyptian):
+ u+0644 u+064A u+0647 u+0645 u+0627 u+0628 u+062A u+0643 u+0644
+ u+0645 u+0648 u+0634 u+0639 u+0631 u+0628 u+064A u+061F
+ Punycode: egbpdaj6bu4bxfgehfvwxn
+
+ (B) Chinese (simplified):
+ u+4ED6 u+4EEC u+4E3A u+4EC0 u+4E48 u+4E0D u+8BF4 u+4E2D u+6587
+ Punycode: ihqwcrb4cv8a8dqg056pqjye
+
+ (C) Chinese (traditional):
+ u+4ED6 u+5011 u+7232 u+4EC0 u+9EBD u+4E0D u+8AAA u+4E2D u+6587
+ Punycode: ihqwctvzc91f659drss3x8bo0yb
+
+ (D) Czech: Pro<ccaron>prost<ecaron>nemluv<iacute><ccaron>esky
+ U+0050 u+0072 u+006F u+010D u+0070 u+0072 u+006F u+0073 u+0074
+ u+011B u+006E u+0065 u+006D u+006C u+0075 u+0076 u+00ED u+010D
+ u+0065 u+0073 u+006B u+0079
+ Punycode: Proprostnemluvesky-uyb24dma41a
+
+
+
+
+
+
+Costello Standards Track [Page 14]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ (E) Hebrew:
+ u+05DC u+05DE u+05D4 u+05D4 u+05DD u+05E4 u+05E9 u+05D5 u+05D8
+ u+05DC u+05D0 u+05DE u+05D3 u+05D1 u+05E8 u+05D9 u+05DD u+05E2
+ u+05D1 u+05E8 u+05D9 u+05EA
+ Punycode: 4dbcagdahymbxekheh6e0a7fei0b
+
+ (F) Hindi (Devanagari):
+ u+092F u+0939 u+0932 u+094B u+0917 u+0939 u+093F u+0928 u+094D
+ u+0926 u+0940 u+0915 u+094D u+092F u+094B u+0902 u+0928 u+0939
+ u+0940 u+0902 u+092C u+094B u+0932 u+0938 u+0915 u+0924 u+0947
+ u+0939 u+0948 u+0902
+ Punycode: i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd
+
+ (G) Japanese (kanji and hiragana):
+ u+306A u+305C u+307F u+3093 u+306A u+65E5 u+672C u+8A9E u+3092
+ u+8A71 u+3057 u+3066 u+304F u+308C u+306A u+3044 u+306E u+304B
+ Punycode: n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa
+
+ (H) Korean (Hangul syllables):
+ u+C138 u+ACC4 u+C758 u+BAA8 u+B4E0 u+C0AC u+B78C u+B4E4 u+C774
+ u+D55C u+AD6D u+C5B4 u+B97C u+C774 u+D574 u+D55C u+B2E4 u+BA74
+ u+C5BC u+B9C8 u+B098 u+C88B u+C744 u+AE4C
+ Punycode: 989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5j\
+ psd879ccm6fea98c
+
+ (I) Russian (Cyrillic):
+ U+043F u+043E u+0447 u+0435 u+043C u+0443 u+0436 u+0435 u+043E
+ u+043D u+0438 u+043D u+0435 u+0433 u+043E u+0432 u+043E u+0440
+ u+044F u+0442 u+043F u+043E u+0440 u+0443 u+0441 u+0441 u+043A
+ u+0438
+ Punycode: b1abfaaepdrnnbgefbaDotcwatmq2g4l
+
+ (J) Spanish: Porqu<eacute>nopuedensimplementehablarenEspa<ntilde>ol
+ U+0050 u+006F u+0072 u+0071 u+0075 u+00E9 u+006E u+006F u+0070
+ u+0075 u+0065 u+0064 u+0065 u+006E u+0073 u+0069 u+006D u+0070
+ u+006C u+0065 u+006D u+0065 u+006E u+0074 u+0065 u+0068 u+0061
+ u+0062 u+006C u+0061 u+0072 u+0065 u+006E U+0045 u+0073 u+0070
+ u+0061 u+00F1 u+006F u+006C
+ Punycode: PorqunopuedensimplementehablarenEspaol-fmd56a
+
+ (K) Vietnamese:
+ T<adotbelow>isaoh<odotbelow>kh<ocirc>ngth<ecirchookabove>ch\
+ <ihookabove>n<oacute>iti<ecircacute>ngVi<ecircdotbelow>t
+ U+0054 u+1EA1 u+0069 u+0073 u+0061 u+006F u+0068 u+1ECD u+006B
+ u+0068 u+00F4 u+006E u+0067 u+0074 u+0068 u+1EC3 u+0063 u+0068
+ u+1EC9 u+006E u+00F3 u+0069 u+0074 u+0069 u+1EBF u+006E u+0067
+ U+0056 u+0069 u+1EC7 u+0074
+ Punycode: TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g
+
+
+
+Costello Standards Track [Page 15]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ The next several examples are all names of Japanese music artists,
+ song titles, and TV programs, just because the author happens to have
+ them handy (but Japanese is useful for providing examples of single-
+ row text, two-row text, ideographic text, and various mixtures
+ thereof).
+
+ (L) 3<nen>B<gumi><kinpachi><sensei>
+ u+0033 u+5E74 U+0042 u+7D44 u+91D1 u+516B u+5148 u+751F
+ Punycode: 3B-ww4c5e180e575a65lsy2b
+
+ (M) <amuro><namie>-with-SUPER-MONKEYS
+ u+5B89 u+5BA4 u+5948 u+7F8E u+6075 u+002D u+0077 u+0069 u+0074
+ u+0068 u+002D U+0053 U+0055 U+0050 U+0045 U+0052 u+002D U+004D
+ U+004F U+004E U+004B U+0045 U+0059 U+0053
+ Punycode: -with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n
+
+ (N) Hello-Another-Way-<sorezore><no><basho>
+ U+0048 u+0065 u+006C u+006C u+006F u+002D U+0041 u+006E u+006F
+ u+0074 u+0068 u+0065 u+0072 u+002D U+0057 u+0061 u+0079 u+002D
+ u+305D u+308C u+305E u+308C u+306E u+5834 u+6240
+ Punycode: Hello-Another-Way--fc4qua05auwb3674vfr0b
+
+ (O) <hitotsu><yane><no><shita>2
+ u+3072 u+3068 u+3064 u+5C4B u+6839 u+306E u+4E0B u+0032
+ Punycode: 2-u9tlzr9756bt3uc0v
+
+ (P) Maji<de>Koi<suru>5<byou><mae>
+ U+004D u+0061 u+006A u+0069 u+3067 U+004B u+006F u+0069 u+3059
+ u+308B u+0035 u+79D2 u+524D
+ Punycode: MajiKoi5-783gue6qz075azm5e
+
+ (Q) <pafii>de<runba>
+ u+30D1 u+30D5 u+30A3 u+30FC u+0064 u+0065 u+30EB u+30F3 u+30D0
+ Punycode: de-jg4avhby1noc0d
+
+ (R) <sono><supiido><de>
+ u+305D u+306E u+30B9 u+30D4 u+30FC u+30C9 u+3067
+ Punycode: d9juau41awczczp
+
+ The last example is an ASCII string that breaks the existing rules
+ for host name labels. (It is not a realistic example for IDNA,
+ because IDNA never encodes pure ASCII labels.)
+
+ (S) -> $1.00 <-
+ u+002D u+003E u+0020 u+0024 u+0031 u+002E u+0030 u+0030 u+0020
+ u+003C u+002D
+ Punycode: -> $1.00 <--
+
+
+
+
+Costello Standards Track [Page 16]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+7.2 Decoding traces
+
+ In the following traces, the evolving state of the decoder is shown
+ as a sequence of hexadecimal values, representing the code points in
+ the extended string. An asterisk appears just after the most
+ recently inserted code point, indicating both n (the value preceeding
+ the asterisk) and i (the position of the value just after the
+ asterisk). Other numerical values are decimal.
+
+ Decoding trace of example B from section 7.1:
+
+ n is 128, i is 0, bias is 72
+ input is "ihqwcrb4cv8a8dqg056pqjye"
+ there is no delimiter, so extended string starts empty
+ delta "ihq" decodes to 19853
+ bias becomes 21
+ 4E0D *
+ delta "wc" decodes to 64
+ bias becomes 20
+ 4E0D 4E2D *
+ delta "rb" decodes to 37
+ bias becomes 13
+ 4E3A * 4E0D 4E2D
+ delta "4c" decodes to 56
+ bias becomes 17
+ 4E3A 4E48 * 4E0D 4E2D
+ delta "v8a" decodes to 599
+ bias becomes 32
+ 4E3A 4EC0 * 4E48 4E0D 4E2D
+ delta "8d" decodes to 130
+ bias becomes 23
+ 4ED6 * 4E3A 4EC0 4E48 4E0D 4E2D
+ delta "qg" decodes to 154
+ bias becomes 25
+ 4ED6 4EEC * 4E3A 4EC0 4E48 4E0D 4E2D
+ delta "056p" decodes to 46301
+ bias becomes 84
+ 4ED6 4EEC 4E3A 4EC0 4E48 4E0D 4E2D 6587 *
+ delta "qjye" decodes to 88531
+ bias becomes 90
+ 4ED6 4EEC 4E3A 4EC0 4E48 4E0D 8BF4 * 4E2D 6587
+
+
+
+
+
+
+
+
+
+
+Costello Standards Track [Page 17]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ Decoding trace of example L from section 7.1:
+
+ n is 128, i is 0, bias is 72
+ input is "3B-ww4c5e180e575a65lsy2b"
+ literal portion is "3B-", so extended string starts as:
+ 0033 0042
+ delta "ww4c" decodes to 62042
+ bias becomes 27
+ 0033 0042 5148 *
+ delta "5e" decodes to 139
+ bias becomes 24
+ 0033 0042 516B * 5148
+ delta "180e" decodes to 16683
+ bias becomes 67
+ 0033 5E74 * 0042 516B 5148
+ delta "575a" decodes to 34821
+ bias becomes 82
+ 0033 5E74 0042 516B 5148 751F *
+ delta "65l" decodes to 14592
+ bias becomes 67
+ 0033 5E74 0042 7D44 * 516B 5148 751F
+ delta "sy2b" decodes to 42088
+ bias becomes 84
+ 0033 5E74 0042 7D44 91D1 * 516B 5148 751F
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Costello Standards Track [Page 18]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+7.3 Encoding traces
+
+ In the following traces, code point values are hexadecimal, while
+ other numerical values are decimal.
+
+ Encoding trace of example B from section 7.1:
+
+ bias is 72
+ input is:
+ 4ED6 4EEC 4E3A 4EC0 4E48 4E0D 8BF4 4E2D 6587
+ there are no basic code points, so no literal portion
+ next code point to insert is 4E0D
+ needed delta is 19853, encodes as "ihq"
+ bias becomes 21
+ next code point to insert is 4E2D
+ needed delta is 64, encodes as "wc"
+ bias becomes 20
+ next code point to insert is 4E3A
+ needed delta is 37, encodes as "rb"
+ bias becomes 13
+ next code point to insert is 4E48
+ needed delta is 56, encodes as "4c"
+ bias becomes 17
+ next code point to insert is 4EC0
+ needed delta is 599, encodes as "v8a"
+ bias becomes 32
+ next code point to insert is 4ED6
+ needed delta is 130, encodes as "8d"
+ bias becomes 23
+ next code point to insert is 4EEC
+ needed delta is 154, encodes as "qg"
+ bias becomes 25
+ next code point to insert is 6587
+ needed delta is 46301, encodes as "056p"
+ bias becomes 84
+ next code point to insert is 8BF4
+ needed delta is 88531, encodes as "qjye"
+ bias becomes 90
+ output is "ihqwcrb4cv8a8dqg056pqjye"
+
+
+
+
+
+
+
+
+
+
+
+
+Costello Standards Track [Page 19]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ Encoding trace of example L from section 7.1:
+
+ bias is 72
+ input is:
+ 0033 5E74 0042 7D44 91D1 516B 5148 751F
+ basic code points (0033, 0042) are copied to literal portion: "3B-"
+ next code point to insert is 5148
+ needed delta is 62042, encodes as "ww4c"
+ bias becomes 27
+ next code point to insert is 516B
+ needed delta is 139, encodes as "5e"
+ bias becomes 24
+ next code point to insert is 5E74
+ needed delta is 16683, encodes as "180e"
+ bias becomes 67
+ next code point to insert is 751F
+ needed delta is 34821, encodes as "575a"
+ bias becomes 82
+ next code point to insert is 7D44
+ needed delta is 14592, encodes as "65l"
+ bias becomes 67
+ next code point to insert is 91D1
+ needed delta is 42088, encodes as "sy2b"
+ bias becomes 84
+ output is "3B-ww4c5e180e575a65lsy2b"
+
+8. Security Considerations
+
+ Users expect each domain name in DNS to be controlled by a single
+ authority. If a Unicode string intended for use as a domain label
+ could map to multiple ACE labels, then an internationalized domain
+ name could map to multiple ASCII domain names, each controlled by a
+ different authority, some of which could be spoofs that hijack
+ service requests intended for another. Therefore Punycode is
+ designed so that each Unicode string has a unique encoding.
+
+ However, there can still be multiple Unicode representations of the
+ "same" text, for various definitions of "same". This problem is
+ addressed to some extent by the Unicode standard under the topic of
+ canonicalization, and this work is leveraged for domain names by
+ Nameprep [NAMEPREP].
+
+
+
+
+
+
+
+
+
+
+Costello Standards Track [Page 20]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+9. References
+
+9.1 Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+9.2 Informative References
+
+ [RFC952] Harrenstien, K., Stahl, M. and E. Feinler, "DOD Internet
+ Host Table Specification", RFC 952, October 1985.
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [IDNA] Faltstrom, P., Hoffman, P. and A. Costello,
+ "Internationalizing Domain Names in Applications
+ (IDNA)", RFC 3490, March 2003.
+
+ [NAMEPREP] Hoffman, P. and M. Blanchet, "Nameprep: A Stringprep
+ Profile for Internationalized Domain Names (IDN)", RFC
+ 3491, March 2003.
+
+ [ASCII] Cerf, V., "ASCII format for Network Interchange", RFC
+ 20, October 1969.
+
+ [PROVINCIAL] Kaplan, M., "The 'anyone can be provincial!' page",
+ http://www.trigeminal.com/samples/provincial.html.
+
+ [UNICODE] The Unicode Consortium, "The Unicode Standard",
+ http://www.unicode.org/unicode/standard/standard.html.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Costello Standards Track [Page 21]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+A. Mixed-case annotation
+
+ In order to use Punycode to represent case-insensitive strings,
+ higher layers need to case-fold the strings prior to Punycode
+ encoding. The encoded string can use mixed case as an annotation
+ telling how to convert the folded string into a mixed-case string for
+ display purposes. Note, however, that mixed-case annotation is not
+ used by the ToASCII and ToUnicode operations specified in [IDNA], and
+ therefore implementors of IDNA can disregard this appendix.
+
+ Basic code points can use mixed case directly, because the decoder
+ copies them verbatim, leaving lowercase code points lowercase, and
+ leaving uppercase code points uppercase. Each non-basic code point
+ is represented by a delta, which is represented by a sequence of
+ basic code points, the last of which provides the annotation. If it
+ is uppercase, it is a suggestion to map the non-basic code point to
+ uppercase (if possible); if it is lowercase, it is a suggestion to
+ map the non-basic code point to lowercase (if possible).
+
+ These annotations do not alter the code points returned by decoders;
+ the annotations are returned separately, for the caller to use or
+ ignore. Encoders can accept annotations in addition to code points,
+ but the annotations do not alter the output, except to influence the
+ uppercase/lowercase form of ASCII letters.
+
+ Punycode encoders and decoders need not support these annotations,
+ and higher layers need not use them.
+
+B. Disclaimer and license
+
+ Regarding this entire document or any portion of it (including the
+ pseudocode and C code), the author makes no guarantees and is not
+ responsible for any damage resulting from its use. The author grants
+ irrevocable permission to anyone to use, modify, and distribute it in
+ any way that does not diminish the rights of anyone else to use,
+ modify, and distribute it, provided that redistributed derivative
+ works do not contain misleading author or version information.
+ Derivative works need not be licensed under similar terms.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Costello Standards Track [Page 22]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+C. Punycode sample implementation
+
+/*
+punycode.c from RFC 3492
+http://www.nicemice.net/idn/
+Adam M. Costello
+http://www.nicemice.net/amc/
+
+This is ANSI C code (C89) implementing Punycode (RFC 3492).
+
+*/
+
+
+/************************************************************/
+/* Public interface (would normally go in its own .h file): */
+
+#include <limits.h>
+
+enum punycode_status {
+ punycode_success,
+ punycode_bad_input, /* Input is invalid. */
+ punycode_big_output, /* Output would exceed the space provided. */
+ punycode_overflow /* Input needs wider integers to process. */
+};
+
+#if UINT_MAX >= (1 << 26) - 1
+typedef unsigned int punycode_uint;
+#else
+typedef unsigned long punycode_uint;
+#endif
+
+enum punycode_status punycode_encode(
+ punycode_uint input_length,
+ const punycode_uint input[],
+ const unsigned char case_flags[],
+ punycode_uint *output_length,
+ char output[] );
+
+ /* punycode_encode() converts Unicode to Punycode. The input */
+ /* is represented as an array of Unicode code points (not code */
+ /* units; surrogate pairs are not allowed), and the output */
+ /* will be represented as an array of ASCII code points. The */
+ /* output string is *not* null-terminated; it will contain */
+ /* zeros if and only if the input contains zeros. (Of course */
+ /* the caller can leave room for a terminator and add one if */
+ /* needed.) The input_length is the number of code points in */
+ /* the input. The output_length is an in/out argument: the */
+ /* caller passes in the maximum number of code points that it */
+
+
+
+Costello Standards Track [Page 23]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ /* can receive, and on successful return it will contain the */
+ /* number of code points actually output. The case_flags array */
+ /* holds input_length boolean values, where nonzero suggests that */
+ /* the corresponding Unicode character be forced to uppercase */
+ /* after being decoded (if possible), and zero suggests that */
+ /* it be forced to lowercase (if possible). ASCII code points */
+ /* are encoded literally, except that ASCII letters are forced */
+ /* to uppercase or lowercase according to the corresponding */
+ /* uppercase flags. If case_flags is a null pointer then ASCII */
+ /* letters are left as they are, and other code points are */
+ /* treated as if their uppercase flags were zero. The return */
+ /* value can be any of the punycode_status values defined above */
+ /* except punycode_bad_input; if not punycode_success, then */
+ /* output_size and output might contain garbage. */
+
+enum punycode_status punycode_decode(
+ punycode_uint input_length,
+ const char input[],
+ punycode_uint *output_length,
+ punycode_uint output[],
+ unsigned char case_flags[] );
+
+ /* punycode_decode() converts Punycode to Unicode. The input is */
+ /* represented as an array of ASCII code points, and the output */
+ /* will be represented as an array of Unicode code points. The */
+ /* input_length is the number of code points in the input. The */
+ /* output_length is an in/out argument: the caller passes in */
+ /* the maximum number of code points that it can receive, and */
+ /* on successful return it will contain the actual number of */
+ /* code points output. The case_flags array needs room for at */
+ /* least output_length values, or it can be a null pointer if the */
+ /* case information is not needed. A nonzero flag suggests that */
+ /* the corresponding Unicode character be forced to uppercase */
+ /* by the caller (if possible), while zero suggests that it be */
+ /* forced to lowercase (if possible). ASCII code points are */
+ /* output already in the proper case, but their flags will be set */
+ /* appropriately so that applying the flags would be harmless. */
+ /* The return value can be any of the punycode_status values */
+ /* defined above; if not punycode_success, then output_length, */
+ /* output, and case_flags might contain garbage. On success, the */
+ /* decoder will never need to write an output_length greater than */
+ /* input_length, because of how the encoding is defined. */
+
+/**********************************************************/
+/* Implementation (would normally go in its own .c file): */
+
+#include <string.h>
+
+
+
+
+Costello Standards Track [Page 24]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+/*** Bootstring parameters for Punycode ***/
+
+enum { base = 36, tmin = 1, tmax = 26, skew = 38, damp = 700,
+ initial_bias = 72, initial_n = 0x80, delimiter = 0x2D };
+
+/* basic(cp) tests whether cp is a basic code point: */
+#define basic(cp) ((punycode_uint)(cp) < 0x80)
+
+/* delim(cp) tests whether cp is a delimiter: */
+#define delim(cp) ((cp) == delimiter)
+
+/* decode_digit(cp) returns the numeric value of a basic code */
+/* point (for use in representing integers) in the range 0 to */
+/* base-1, or base if cp is does not represent a value. */
+
+static punycode_uint decode_digit(punycode_uint cp)
+{
+ return cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 :
+ cp - 97 < 26 ? cp - 97 : base;
+}
+
+/* encode_digit(d,flag) returns the basic code point whose value */
+/* (when used for representing integers) is d, which needs to be in */
+/* the range 0 to base-1. The lowercase form is used unless flag is */
+/* nonzero, in which case the uppercase form is used. The behavior */
+/* is undefined if flag is nonzero and digit d has no uppercase form. */
+
+static char encode_digit(punycode_uint d, int flag)
+{
+ return d + 22 + 75 * (d < 26) - ((flag != 0) << 5);
+ /* 0..25 map to ASCII a..z or A..Z */
+ /* 26..35 map to ASCII 0..9 */
+}
+
+/* flagged(bcp) tests whether a basic code point is flagged */
+/* (uppercase). The behavior is undefined if bcp is not a */
+/* basic code point. */
+
+#define flagged(bcp) ((punycode_uint)(bcp) - 65 < 26)
+
+/* encode_basic(bcp,flag) forces a basic code point to lowercase */
+/* if flag is zero, uppercase if flag is nonzero, and returns */
+/* the resulting code point. The code point is unchanged if it */
+/* is caseless. The behavior is undefined if bcp is not a basic */
+/* code point. */
+
+static char encode_basic(punycode_uint bcp, int flag)
+{
+
+
+
+Costello Standards Track [Page 25]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ bcp -= (bcp - 97 < 26) << 5;
+ return bcp + ((!flag && (bcp - 65 < 26)) << 5);
+}
+
+/*** Platform-specific constants ***/
+
+/* maxint is the maximum value of a punycode_uint variable: */
+static const punycode_uint maxint = -1;
+/* Because maxint is unsigned, -1 becomes the maximum value. */
+
+/*** Bias adaptation function ***/
+
+static punycode_uint adapt(
+ punycode_uint delta, punycode_uint numpoints, int firsttime )
+{
+ punycode_uint k;
+
+ delta = firsttime ? delta / damp : delta >> 1;
+ /* delta >> 1 is a faster way of doing delta / 2 */
+ delta += delta / numpoints;
+
+ for (k = 0; delta > ((base - tmin) * tmax) / 2; k += base) {
+ delta /= base - tmin;
+ }
+
+ return k + (base - tmin + 1) * delta / (delta + skew);
+}
+
+/*** Main encode function ***/
+
+enum punycode_status punycode_encode(
+ punycode_uint input_length,
+ const punycode_uint input[],
+ const unsigned char case_flags[],
+ punycode_uint *output_length,
+ char output[] )
+{
+ punycode_uint n, delta, h, b, out, max_out, bias, j, m, q, k, t;
+
+ /* Initialize the state: */
+
+ n = initial_n;
+ delta = out = 0;
+ max_out = *output_length;
+ bias = initial_bias;
+
+ /* Handle the basic code points: */
+
+
+
+
+Costello Standards Track [Page 26]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ for (j = 0; j < input_length; ++j) {
+ if (basic(input[j])) {
+ if (max_out - out < 2) return punycode_big_output;
+ output[out++] =
+ case_flags ? encode_basic(input[j], case_flags[j]) : input[j];
+ }
+ /* else if (input[j] < n) return punycode_bad_input; */
+ /* (not needed for Punycode with unsigned code points) */
+ }
+
+ h = b = out;
+
+ /* h is the number of code points that have been handled, b is the */
+ /* number of basic code points, and out is the number of characters */
+ /* that have been output. */
+
+ if (b > 0) output[out++] = delimiter;
+
+ /* Main encoding loop: */
+
+ while (h < input_length) {
+ /* All non-basic code points < n have been */
+ /* handled already. Find the next larger one: */
+
+ for (m = maxint, j = 0; j < input_length; ++j) {
+ /* if (basic(input[j])) continue; */
+ /* (not needed for Punycode) */
+ if (input[j] >= n && input[j] < m) m = input[j];
+ }
+
+ /* Increase delta enough to advance the decoder's */
+ /* <n,i> state to <m,0>, but guard against overflow: */
+
+ if (m - n > (maxint - delta) / (h + 1)) return punycode_overflow;
+ delta += (m - n) * (h + 1);
+ n = m;
+
+ for (j = 0; j < input_length; ++j) {
+ /* Punycode does not need to check whether input[j] is basic: */
+ if (input[j] < n /* || basic(input[j]) */ ) {
+ if (++delta == 0) return punycode_overflow;
+ }
+
+ if (input[j] == n) {
+ /* Represent delta as a generalized variable-length integer: */
+
+ for (q = delta, k = base; ; k += base) {
+ if (out >= max_out) return punycode_big_output;
+
+
+
+Costello Standards Track [Page 27]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ t = k <= bias /* + tmin */ ? tmin : /* +tmin not needed */
+ k >= bias + tmax ? tmax : k - bias;
+ if (q < t) break;
+ output[out++] = encode_digit(t + (q - t) % (base - t), 0);
+ q = (q - t) / (base - t);
+ }
+
+ output[out++] = encode_digit(q, case_flags && case_flags[j]);
+ bias = adapt(delta, h + 1, h == b);
+ delta = 0;
+ ++h;
+ }
+ }
+
+ ++delta, ++n;
+ }
+
+ *output_length = out;
+ return punycode_success;
+}
+
+/*** Main decode function ***/
+
+enum punycode_status punycode_decode(
+ punycode_uint input_length,
+ const char input[],
+ punycode_uint *output_length,
+ punycode_uint output[],
+ unsigned char case_flags[] )
+{
+ punycode_uint n, out, i, max_out, bias,
+ b, j, in, oldi, w, k, digit, t;
+
+ /* Initialize the state: */
+
+ n = initial_n;
+ out = i = 0;
+ max_out = *output_length;
+ bias = initial_bias;
+
+ /* Handle the basic code points: Let b be the number of input code */
+ /* points before the last delimiter, or 0 if there is none, then */
+ /* copy the first b code points to the output. */
+
+ for (b = j = 0; j < input_length; ++j) if (delim(input[j])) b = j;
+ if (b > max_out) return punycode_big_output;
+
+ for (j = 0; j < b; ++j) {
+
+
+
+Costello Standards Track [Page 28]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ if (case_flags) case_flags[out] = flagged(input[j]);
+ if (!basic(input[j])) return punycode_bad_input;
+ output[out++] = input[j];
+ }
+
+ /* Main decoding loop: Start just after the last delimiter if any */
+ /* basic code points were copied; start at the beginning otherwise. */
+
+ for (in = b > 0 ? b + 1 : 0; in < input_length; ++out) {
+
+ /* in is the index of the next character to be consumed, and */
+ /* out is the number of code points in the output array. */
+
+ /* Decode a generalized variable-length integer into delta, */
+ /* which gets added to i. The overflow checking is easier */
+ /* if we increase i as we go, then subtract off its starting */
+ /* value at the end to obtain delta. */
+
+ for (oldi = i, w = 1, k = base; ; k += base) {
+ if (in >= input_length) return punycode_bad_input;
+ digit = decode_digit(input[in++]);
+ if (digit >= base) return punycode_bad_input;
+ if (digit > (maxint - i) / w) return punycode_overflow;
+ i += digit * w;
+ t = k <= bias /* + tmin */ ? tmin : /* +tmin not needed */
+ k >= bias + tmax ? tmax : k - bias;
+ if (digit < t) break;
+ if (w > maxint / (base - t)) return punycode_overflow;
+ w *= (base - t);
+ }
+
+ bias = adapt(i - oldi, out + 1, oldi == 0);
+
+ /* i was supposed to wrap around from out+1 to 0, */
+ /* incrementing n each time, so we'll fix that now: */
+
+ if (i / (out + 1) > maxint - n) return punycode_overflow;
+ n += i / (out + 1);
+ i %= (out + 1);
+
+ /* Insert n at position i of the output: */
+
+ /* not needed for Punycode: */
+ /* if (decode_digit(n) <= base) return punycode_invalid_input; */
+ if (out >= max_out) return punycode_big_output;
+
+ if (case_flags) {
+ memmove(case_flags + i + 1, case_flags + i, out - i);
+
+
+
+Costello Standards Track [Page 29]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ /* Case of last character determines uppercase flag: */
+ case_flags[i] = flagged(input[in - 1]);
+ }
+
+ memmove(output + i + 1, output + i, (out - i) * sizeof *output);
+ output[i++] = n;
+ }
+
+ *output_length = out;
+ return punycode_success;
+}
+
+/******************************************************************/
+/* Wrapper for testing (would normally go in a separate .c file): */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* For testing, we'll just set some compile-time limits rather than */
+/* use malloc(), and set a compile-time option rather than using a */
+/* command-line option. */
+
+enum {
+ unicode_max_length = 256,
+ ace_max_length = 256
+};
+
+static void usage(char **argv)
+{
+ fprintf(stderr,
+ "\n"
+ "%s -e reads code points and writes a Punycode string.\n"
+ "%s -d reads a Punycode string and writes code points.\n"
+ "\n"
+ "Input and output are plain text in the native character set.\n"
+ "Code points are in the form u+hex separated by whitespace.\n"
+ "Although the specification allows Punycode strings to contain\n"
+ "any characters from the ASCII repertoire, this test code\n"
+ "supports only the printable characters, and needs the Punycode\n"
+ "string to be followed by a newline.\n"
+ "The case of the u in u+hex is the force-to-uppercase flag.\n"
+ , argv[0], argv[0]);
+ exit(EXIT_FAILURE);
+}
+
+static void fail(const char *msg)
+
+
+
+Costello Standards Track [Page 30]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+{
+ fputs(msg,stderr);
+ exit(EXIT_FAILURE);
+}
+
+static const char too_big[] =
+ "input or output is too large, recompile with larger limits\n";
+static const char invalid_input[] = "invalid input\n";
+static const char overflow[] = "arithmetic overflow\n";
+static const char io_error[] = "I/O error\n";
+
+/* The following string is used to convert printable */
+/* characters between ASCII and the native charset: */
+
+static const char print_ascii[] =
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
+ " !\"#$%&'()*+,-./"
+ "0123456789:;<=>?"
+ "@ABCDEFGHIJKLMNO"
+ "PQRSTUVWXYZ[\\]^_"
+ "`abcdefghijklmno"
+ "pqrstuvwxyz{|}~\n";
+
+int main(int argc, char **argv)
+{
+ enum punycode_status status;
+ int r;
+ unsigned int input_length, output_length, j;
+ unsigned char case_flags[unicode_max_length];
+
+ if (argc != 2) usage(argv);
+ if (argv[1][0] != '-') usage(argv);
+ if (argv[1][2] != 0) usage(argv);
+
+ if (argv[1][1] == 'e') {
+ punycode_uint input[unicode_max_length];
+ unsigned long codept;
+ char output[ace_max_length+1], uplus[3];
+ int c;
+
+ /* Read the input code points: */
+
+ input_length = 0;
+
+ for (;;) {
+ r = scanf("%2s%lx", uplus, &codept);
+ if (ferror(stdin)) fail(io_error);
+
+
+
+Costello Standards Track [Page 31]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ if (r == EOF || r == 0) break;
+
+ if (r != 2 || uplus[1] != '+' || codept > (punycode_uint)-1) {
+ fail(invalid_input);
+ }
+
+ if (input_length == unicode_max_length) fail(too_big);
+
+ if (uplus[0] == 'u') case_flags[input_length] = 0;
+ else if (uplus[0] == 'U') case_flags[input_length] = 1;
+ else fail(invalid_input);
+
+ input[input_length++] = codept;
+ }
+
+ /* Encode: */
+
+ output_length = ace_max_length;
+ status = punycode_encode(input_length, input, case_flags,
+ &output_length, output);
+ if (status == punycode_bad_input) fail(invalid_input);
+ if (status == punycode_big_output) fail(too_big);
+ if (status == punycode_overflow) fail(overflow);
+ assert(status == punycode_success);
+
+ /* Convert to native charset and output: */
+
+ for (j = 0; j < output_length; ++j) {
+ c = output[j];
+ assert(c >= 0 && c <= 127);
+ if (print_ascii[c] == 0) fail(invalid_input);
+ output[j] = print_ascii[c];
+ }
+
+ output[j] = 0;
+ r = puts(output);
+ if (r == EOF) fail(io_error);
+ return EXIT_SUCCESS;
+ }
+
+ if (argv[1][1] == 'd') {
+ char input[ace_max_length+2], *p, *pp;
+ punycode_uint output[unicode_max_length];
+
+ /* Read the Punycode input string and convert to ASCII: */
+
+ fgets(input, ace_max_length+2, stdin);
+ if (ferror(stdin)) fail(io_error);
+
+
+
+Costello Standards Track [Page 32]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+ if (feof(stdin)) fail(invalid_input);
+ input_length = strlen(input) - 1;
+ if (input[input_length] != '\n') fail(too_big);
+ input[input_length] = 0;
+
+ for (p = input; *p != 0; ++p) {
+ pp = strchr(print_ascii, *p);
+ if (pp == 0) fail(invalid_input);
+ *p = pp - print_ascii;
+ }
+
+ /* Decode: */
+
+ output_length = unicode_max_length;
+ status = punycode_decode(input_length, input, &output_length,
+ output, case_flags);
+ if (status == punycode_bad_input) fail(invalid_input);
+ if (status == punycode_big_output) fail(too_big);
+ if (status == punycode_overflow) fail(overflow);
+ assert(status == punycode_success);
+
+ /* Output the result: */
+
+ for (j = 0; j < output_length; ++j) {
+ r = printf("%s+%04lX\n",
+ case_flags[j] ? "U" : "u",
+ (unsigned long) output[j] );
+ if (r < 0) fail(io_error);
+ }
+
+ return EXIT_SUCCESS;
+ }
+
+ usage(argv);
+ return EXIT_SUCCESS; /* not reached, but quiets compiler warning */
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Costello Standards Track [Page 33]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+Author's Address
+
+ Adam M. Costello
+ University of California, Berkeley
+ http://www.nicemice.net/amc/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Costello Standards Track [Page 34]
+
+RFC 3492 IDNA Punycode March 2003
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Costello Standards Track [Page 35]
+
diff --git a/doc/rfc/rfc3493.txt b/doc/rfc/rfc3493.txt
new file mode 100644
index 0000000..5fea6c1
--- /dev/null
+++ b/doc/rfc/rfc3493.txt
@@ -0,0 +1,2187 @@
+
+
+
+
+
+
+Network Working Group R. Gilligan
+Request for Comments: 3493 Intransa, Inc.
+Obsoletes: 2553 S. Thomson
+Category: Informational Cisco
+ J. Bound
+ J. McCann
+ Hewlett-Packard
+ W. Stevens
+ February 2003
+
+
+ Basic Socket Interface Extensions for IPv6
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ The de facto standard Application Program Interface (API) for TCP/IP
+ applications is the "sockets" interface. Although this API was
+ developed for Unix in the early 1980s it has also been implemented on
+ a wide variety of non-Unix systems. TCP/IP applications written
+ using the sockets API have in the past enjoyed a high degree of
+ portability and we would like the same portability with IPv6
+ applications. But changes are required to the sockets API to support
+ IPv6 and this memo describes these changes. These include a new
+ socket address structure to carry IPv6 addresses, new address
+ conversion functions, and some new socket options. These extensions
+ are designed to provide access to the basic IPv6 features required by
+ TCP and UDP applications, including multicasting, while introducing a
+ minimum of change into the system and providing complete
+ compatibility for existing IPv4 applications. Additional extensions
+ for advanced IPv6 features (raw sockets and access to the IPv6
+ extension headers) are defined in another document.
+
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 1]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+Table of Contents
+
+ 1. Introduction................................................3
+ 2. Design Considerations.......................................4
+ 2.1 What Needs to be Changed...............................4
+ 2.2 Data Types.............................................6
+ 2.3 Headers................................................6
+ 2.4 Structures.............................................6
+ 3. Socket Interface............................................6
+ 3.1 IPv6 Address Family and Protocol Family................6
+ 3.2 IPv6 Address Structure.................................7
+ 3.3 Socket Address Structure for 4.3BSD-Based Systems......7
+ 3.4 Socket Address Structure for 4.4BSD-Based Systems......9
+ 3.5 The Socket Functions...................................9
+ 3.6 Compatibility with IPv4 Applications..................10
+ 3.7 Compatibility with IPv4 Nodes.........................11
+ 3.8 IPv6 Wildcard Address.................................11
+ 3.9 IPv6 Loopback Address.................................13
+ 3.10 Portability Additions.................................14
+ 4. Interface Identification...................................16
+ 4.1 Name-to-Index.........................................17
+ 4.2 Index-to-Name.........................................17
+ 4.3 Return All Interface Names and Indexes................18
+ 4.4 Free Memory...........................................18
+ 5. Socket Options.............................................18
+ 5.1 Unicast Hop Limit.....................................19
+ 5.2 Sending and Receiving Multicast Packets...............19
+ 5.3 IPV6_V6ONLY option for AF_INET6 Sockets...............22
+ 6. Library Functions..........................................22
+ 6.1 Protocol-Independent Nodename and
+ Service Name Translation..............................23
+ 6.2 Socket Address Structure to Node Name
+ and Service Name......................................28
+ 6.3 Address Conversion Functions..........................31
+ 6.4 Address Testing Macros................................33
+ 7. Summary of New Definitions.................................33
+ 8. Security Considerations....................................35
+ 9. Changes from RFC 2553......................................35
+ 10. Acknowledgments............................................36
+ 11. References.................................................37
+ 12. Authors' Addresses.........................................38
+ 13. Full Copyright Statement...................................39
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 2]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+1. Introduction
+
+ While IPv4 addresses are 32 bits long, IPv6 addresses are 128 bits
+ long. The socket interface makes the size of an IP address quite
+ visible to an application; virtually all TCP/IP applications for
+ BSD-based systems have knowledge of the size of an IP address. Those
+ parts of the API that expose the addresses must be changed to
+ accommodate the larger IPv6 address size. IPv6 also introduces new
+ features, some of which must be made visible to applications via the
+ API. This memo defines a set of extensions to the socket interface
+ to support the larger address size and new features of IPv6. It
+ defines "basic" extensions that are of use to a broad range of
+ applications. A companion document, the "advanced" API [4], covers
+ extensions that are of use to more specialized applications, examples
+ of which include routing daemons, and the "ping" and "traceroute"
+ utilities.
+
+ The development of this API was started in 1994 in the IETF IPng
+ working group. The API has evolved over the years, published first
+ in RFC 2133, then again in RFC 2553, and reaching its final form in
+ this document.
+
+ As the API matured and stabilized, it was incorporated into the Open
+ Group's Networking Services (XNS) specification, issue 5.2, which was
+ subsequently incorporated into a joint Open Group/IEEE/ISO standard
+ [3].
+
+ Effort has been made to ensure that this document and [3] contain the
+ same information with regard to the API definitions. However, the
+ reader should note that this document is for informational purposes
+ only, and that the official standard specification of the sockets API
+ is [3].
+
+ It is expected that any future standardization work on this API would
+ be done by the Open Group Base Working Group [6].
+
+ It should also be noted that this document describes only those
+ portions of the API needed for IPv4 and IPv6 communications. Other
+ potential uses of the API, for example the use of getaddrinfo() and
+ getnameinfo() with the AF_UNIX address family, are beyond the scope
+ of this document.
+
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 3]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+2. Design Considerations
+
+ There are a number of important considerations in designing changes
+ to this well-worn API:
+
+ - The API changes should provide both source and binary
+ compatibility for programs written to the original API. That is,
+ existing program binaries should continue to operate when run on a
+ system supporting the new API. In addition, existing applications
+ that are re-compiled and run on a system supporting the new API
+ should continue to operate. Simply put, the API changes for IPv6
+ should not break existing programs. An additional mechanism for
+ implementations to verify this is to verify the new symbols are
+ protected by Feature Test Macros as described in [3]. (Such
+ Feature Test Macros are not defined by this RFC.)
+
+ - The changes to the API should be as small as possible in order to
+ simplify the task of converting existing IPv4 applications to
+ IPv6.
+
+ - Where possible, applications should be able to use this API to
+ interoperate with both IPv6 and IPv4 hosts. Applications should
+ not need to know which type of host they are communicating with.
+
+ - IPv6 addresses carried in data structures should be 64-bit
+ aligned. This is necessary in order to obtain optimum performance
+ on 64-bit machine architectures.
+
+ Because of the importance of providing IPv4 compatibility in the API,
+ these extensions are explicitly designed to operate on machines that
+ provide complete support for both IPv4 and IPv6. A subset of this
+ API could probably be designed for operation on systems that support
+ only IPv6. However, this is not addressed in this memo.
+
+2.1 What Needs to be Changed
+
+ The socket interface API consists of a few distinct components:
+
+ - Core socket functions.
+
+ - Address data structures.
+
+ - Name-to-address translation functions.
+
+ - Address conversion functions.
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 4]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ The core socket functions -- those functions that deal with such
+ things as setting up and tearing down TCP connections, and sending
+ and receiving UDP packets -- were designed to be transport
+ independent. Where protocol addresses are passed as function
+ arguments, they are carried via opaque pointers. A protocol-specific
+ address data structure is defined for each protocol that the socket
+ functions support. Applications must cast pointers to these
+ protocol-specific address structures into pointers to the generic
+ "sockaddr" address structure when using the socket functions. These
+ functions need not change for IPv6, but a new IPv6-specific address
+ data structure is needed.
+
+ The "sockaddr_in" structure is the protocol-specific data structure
+ for IPv4. This data structure actually includes 8-octets of unused
+ space, and it is tempting to try to use this space to adapt the
+ sockaddr_in structure to IPv6. Unfortunately, the sockaddr_in
+ structure is not large enough to hold the 16-octet IPv6 address as
+ well as the other information (address family and port number) that
+ is needed. So a new address data structure must be defined for IPv6.
+
+ IPv6 addresses are scoped [2] so they could be link-local, site,
+ organization, global, or other scopes at this time undefined. To
+ support applications that want to be able to identify a set of
+ interfaces for a specific scope, the IPv6 sockaddr_in structure must
+ support a field that can be used by an implementation to identify a
+ set of interfaces identifying the scope for an IPv6 address.
+
+ The IPv4 name-to-address translation functions in the socket
+ interface are gethostbyname() and gethostbyaddr(). These are left as
+ is, and new functions are defined which support both IPv4 and IPv6.
+
+ The IPv4 address conversion functions -- inet_ntoa() and inet_addr()
+ -- convert IPv4 addresses between binary and printable form. These
+ functions are quite specific to 32-bit IPv4 addresses. We have
+ designed two analogous functions that convert both IPv4 and IPv6
+ addresses, and carry an address type parameter so that they can be
+ extended to other protocol families as well.
+
+ Finally, a few miscellaneous features are needed to support IPv6. A
+ new interface is needed to support the IPv6 hop limit header field.
+ New socket options are needed to control the sending and receiving of
+ IPv6 multicast packets.
+
+ The socket interface will be enhanced in the future to provide access
+ to other IPv6 features. Some of these extensions are described in
+ [4].
+
+
+
+
+
+Gilligan, et al. Informational [Page 5]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+2.2 Data Types
+
+ The data types of the structure elements given in this memo are
+ intended to track the relevant standards. uintN_t means an unsigned
+ integer of exactly N bits (e.g., uint16_t). The sa_family_t and
+ in_port_t types are defined in [3].
+
+2.3 Headers
+
+ When function prototypes and structures are shown we show the headers
+ that must be #included to cause that item to be defined.
+
+2.4 Structures
+
+ When structures are described the members shown are the ones that
+ must appear in an implementation. Additional, nonstandard members
+ may also be defined by an implementation. As an additional
+ precaution nonstandard members could be verified by Feature Test
+ Macros as described in [3]. (Such Feature Test Macros are not
+ defined by this RFC.)
+
+ The ordering shown for the members of a structure is the recommended
+ ordering, given alignment considerations of multibyte members, but an
+ implementation may order the members differently.
+
+3. Socket Interface
+
+ This section specifies the socket interface changes for IPv6.
+
+3.1 IPv6 Address Family and Protocol Family
+
+ A new address family name, AF_INET6, is defined in <sys/socket.h>.
+ The AF_INET6 definition distinguishes between the original
+ sockaddr_in address data structure, and the new sockaddr_in6 data
+ structure.
+
+ A new protocol family name, PF_INET6, is defined in <sys/socket.h>.
+ Like most of the other protocol family names, this will usually be
+ defined to have the same value as the corresponding address family
+ name:
+
+ #define PF_INET6 AF_INET6
+
+ The AF_INET6 is used in the first argument to the socket() function
+ to indicate that an IPv6 socket is being created.
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 6]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+3.2 IPv6 Address Structure
+
+ A new in6_addr structure holds a single IPv6 address and is defined
+ as a result of including <netinet/in.h>:
+
+ struct in6_addr {
+ uint8_t s6_addr[16]; /* IPv6 address */
+ };
+
+ This data structure contains an array of sixteen 8-bit elements,
+ which make up one 128-bit IPv6 address. The IPv6 address is stored
+ in network byte order.
+
+ The structure in6_addr above is usually implemented with an embedded
+ union with extra fields that force the desired alignment level in a
+ manner similar to BSD implementations of "struct in_addr". Those
+ additional implementation details are omitted here for simplicity.
+
+ An example is as follows:
+
+ struct in6_addr {
+ union {
+ uint8_t _S6_u8[16];
+ uint32_t _S6_u32[4];
+ uint64_t _S6_u64[2];
+ } _S6_un;
+ };
+ #define s6_addr _S6_un._S6_u8
+
+3.3 Socket Address Structure for 4.3BSD-Based Systems
+
+ In the socket interface, a different protocol-specific data structure
+ is defined to carry the addresses for each protocol suite. Each
+ protocol-specific data structure is designed so it can be cast into a
+ protocol-independent data structure -- the "sockaddr" structure.
+ Each has a "family" field that overlays the "sa_family" of the
+ sockaddr data structure. This field identifies the type of the data
+ structure.
+
+ The sockaddr_in structure is the protocol-specific address data
+ structure for IPv4. It is used to pass addresses between
+ applications and the system in the socket functions. The following
+ sockaddr_in6 structure holds IPv6 addresses and is defined as a
+ result of including the <netinet/in.h> header:
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 7]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+struct sockaddr_in6 {
+ sa_family_t sin6_family; /* AF_INET6 */
+ in_port_t sin6_port; /* transport layer port # */
+ uint32_t sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ uint32_t sin6_scope_id; /* set of interfaces for a scope */
+};
+
+ This structure is designed to be compatible with the sockaddr data
+ structure used in the 4.3BSD release.
+
+ The sin6_family field identifies this as a sockaddr_in6 structure.
+ This field overlays the sa_family field when the buffer is cast to a
+ sockaddr data structure. The value of this field must be AF_INET6.
+
+ The sin6_port field contains the 16-bit UDP or TCP port number. This
+ field is used in the same way as the sin_port field of the
+ sockaddr_in structure. The port number is stored in network byte
+ order.
+
+ The sin6_flowinfo field is a 32-bit field intended to contain flow-
+ related information. The exact way this field is mapped to or from a
+ packet is not currently specified. Until such time as its use is
+ specified, applications should set this field to zero when
+ constructing a sockaddr_in6, and ignore this field in a sockaddr_in6
+ structure constructed by the system.
+
+ The sin6_addr field is a single in6_addr structure (defined in the
+ previous section). This field holds one 128-bit IPv6 address. The
+ address is stored in network byte order.
+
+ The ordering of elements in this structure is specifically designed
+ so that when sin6_addr field is aligned on a 64-bit boundary, the
+ start of the structure will also be aligned on a 64-bit boundary.
+ This is done for optimum performance on 64-bit architectures.
+
+ The sin6_scope_id field is a 32-bit integer that identifies a set of
+ interfaces as appropriate for the scope [2] of the address carried in
+ the sin6_addr field. The mapping of sin6_scope_id to an interface or
+ set of interfaces is left to implementation and future specifications
+ on the subject of scoped addresses.
+
+ Notice that the sockaddr_in6 structure will normally be larger than
+ the generic sockaddr structure. On many existing implementations the
+ sizeof(struct sockaddr_in) equals sizeof(struct sockaddr), with both
+ being 16 bytes. Any existing code that makes this assumption needs
+ to be examined carefully when converting to IPv6.
+
+
+
+
+Gilligan, et al. Informational [Page 8]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+3.4 Socket Address Structure for 4.4BSD-Based Systems
+
+ The 4.4BSD release includes a small, but incompatible change to the
+ socket interface. The "sa_family" field of the sockaddr data
+ structure was changed from a 16-bit value to an 8-bit value, and the
+ space saved used to hold a length field, named "sa_len". The
+ sockaddr_in6 data structure given in the previous section cannot be
+ correctly cast into the newer sockaddr data structure. For this
+ reason, the following alternative IPv6 address data structure is
+ provided to be used on systems based on 4.4BSD. It is defined as a
+ result of including the <netinet/in.h> header.
+
+struct sockaddr_in6 {
+ uint8_t sin6_len; /* length of this struct */
+ sa_family_t sin6_family; /* AF_INET6 */
+ in_port_t sin6_port; /* transport layer port # */
+ uint32_t sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ uint32_t sin6_scope_id; /* set of interfaces for a scope */
+};
+
+ The only differences between this data structure and the 4.3BSD
+ variant are the inclusion of the length field, and the change of the
+ family field to a 8-bit data type. The definitions of all the other
+ fields are identical to the structure defined in the previous
+ section.
+
+ Systems that provide this version of the sockaddr_in6 data structure
+ must also declare SIN6_LEN as a result of including the
+ <netinet/in.h> header. This macro allows applications to determine
+ whether they are being built on a system that supports the 4.3BSD or
+ 4.4BSD variants of the data structure.
+
+3.5 The Socket Functions
+
+ Applications call the socket() function to create a socket descriptor
+ that represents a communication endpoint. The arguments to the
+ socket() function tell the system which protocol to use, and what
+ format address structure will be used in subsequent functions. For
+ example, to create an IPv4/TCP socket, applications make the call:
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+
+ To create an IPv4/UDP socket, applications make the call:
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+
+
+
+
+
+Gilligan, et al. Informational [Page 9]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ Applications may create IPv6/TCP and IPv6/UDP sockets (which may also
+ handle IPv4 communication as described in section 3.7) by simply
+ using the constant AF_INET6 instead of AF_INET in the first argument.
+ For example, to create an IPv6/TCP socket, applications make the
+ call:
+
+ s = socket(AF_INET6, SOCK_STREAM, 0);
+
+ To create an IPv6/UDP socket, applications make the call:
+
+ s = socket(AF_INET6, SOCK_DGRAM, 0);
+
+ Once the application has created a AF_INET6 socket, it must use the
+ sockaddr_in6 address structure when passing addresses in to the
+ system. The functions that the application uses to pass addresses
+ into the system are:
+
+ bind()
+ connect()
+ sendmsg()
+ sendto()
+
+ The system will use the sockaddr_in6 address structure to return
+ addresses to applications that are using AF_INET6 sockets. The
+ functions that return an address from the system to an application
+ are:
+
+ accept()
+ recvfrom()
+ recvmsg()
+ getpeername()
+ getsockname()
+
+ No changes to the syntax of the socket functions are needed to
+ support IPv6, since all of the "address carrying" functions use an
+ opaque address pointer, and carry an address length as a function
+ argument.
+
+3.6 Compatibility with IPv4 Applications
+
+ In order to support the large base of applications using the original
+ API, system implementations must provide complete source and binary
+ compatibility with the original API. This means that systems must
+ continue to support AF_INET sockets and the sockaddr_in address
+ structure. Applications must be able to create IPv4/TCP and IPv4/UDP
+ sockets using the AF_INET constant in the socket() function, as
+
+
+
+
+
+Gilligan, et al. Informational [Page 10]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ described in the previous section. Applications should be able to
+ hold a combination of IPv4/TCP, IPv4/UDP, IPv6/TCP and IPv6/UDP
+ sockets simultaneously within the same process.
+
+ Applications using the original API should continue to operate as
+ they did on systems supporting only IPv4. That is, they should
+ continue to interoperate with IPv4 nodes.
+
+3.7 Compatibility with IPv4 Nodes
+
+ The API also provides a different type of compatibility: the ability
+ for IPv6 applications to interoperate with IPv4 applications. This
+ feature uses the IPv4-mapped IPv6 address format defined in the IPv6
+ addressing architecture specification [2]. This address format
+ allows the IPv4 address of an IPv4 node to be represented as an IPv6
+ address. The IPv4 address is encoded into the low-order 32 bits of
+ the IPv6 address, and the high-order 96 bits hold the fixed prefix
+ 0:0:0:0:0:FFFF. IPv4-mapped addresses are written as follows:
+
+ ::FFFF:<IPv4-address>
+
+ These addresses can be generated automatically by the getaddrinfo()
+ function, as described in Section 6.1.
+
+ Applications may use AF_INET6 sockets to open TCP connections to IPv4
+ nodes, or send UDP packets to IPv4 nodes, by simply encoding the
+ destination's IPv4 address as an IPv4-mapped IPv6 address, and
+ passing that address, within a sockaddr_in6 structure, in the
+ connect() or sendto() call. When applications use AF_INET6 sockets
+ to accept TCP connections from IPv4 nodes, or receive UDP packets
+ from IPv4 nodes, the system returns the peer's address to the
+ application in the accept(), recvfrom(), or getpeername() call using
+ a sockaddr_in6 structure encoded this way.
+
+ Few applications will likely need to know which type of node they are
+ interoperating with. However, for those applications that do need to
+ know, the IN6_IS_ADDR_V4MAPPED() macro, defined in Section 6.4, is
+ provided.
+
+3.8 IPv6 Wildcard Address
+
+ While the bind() function allows applications to select the source IP
+ address of UDP packets and TCP connections, applications often want
+ the system to select the source address for them. With IPv4, one
+ specifies the address as the symbolic constant INADDR_ANY (called the
+ "wildcard" address) in the bind() call, or simply omits the bind()
+ entirely.
+
+
+
+
+Gilligan, et al. Informational [Page 11]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ Since the IPv6 address type is a structure (struct in6_addr), a
+ symbolic constant can be used to initialize an IPv6 address variable,
+ but cannot be used in an assignment. Therefore systems provide the
+ IPv6 wildcard address in two forms.
+
+ The first version is a global variable named "in6addr_any" that is an
+ in6_addr structure. The extern declaration for this variable is
+ defined in <netinet/in.h>:
+
+ extern const struct in6_addr in6addr_any;
+
+ Applications use in6addr_any similarly to the way they use INADDR_ANY
+ in IPv4. For example, to bind a socket to port number 23, but let
+ the system select the source address, an application could use the
+ following code:
+
+ struct sockaddr_in6 sin6;
+ . . .
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_flowinfo = 0;
+ sin6.sin6_port = htons(23);
+ sin6.sin6_addr = in6addr_any; /* structure assignment */
+ . . .
+ if (bind(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1)
+ . . .
+
+ The other version is a symbolic constant named IN6ADDR_ANY_INIT and
+ is defined in <netinet/in.h>. This constant can be used to
+ initialize an in6_addr structure:
+
+ struct in6_addr anyaddr = IN6ADDR_ANY_INIT;
+
+ Note that this constant can be used ONLY at declaration time. It can
+ not be used to assign a previously declared in6_addr structure. For
+ example, the following code will not work:
+
+ /* This is the WRONG way to assign an unspecified address */
+ struct sockaddr_in6 sin6;
+ . . .
+ sin6.sin6_addr = IN6ADDR_ANY_INIT; /* will NOT compile */
+
+ Be aware that the IPv4 INADDR_xxx constants are all defined in host
+ byte order but the IPv6 IN6ADDR_xxx constants and the IPv6
+ in6addr_xxx externals are defined in network byte order.
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 12]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+3.9 IPv6 Loopback Address
+
+ Applications may need to send UDP packets to, or originate TCP
+ connections to, services residing on the local node. In IPv4, they
+ can do this by using the constant IPv4 address INADDR_LOOPBACK in
+ their connect(), sendto(), or sendmsg() call.
+
+ IPv6 also provides a loopback address to contact local TCP and UDP
+ services. Like the unspecified address, the IPv6 loopback address is
+ provided in two forms -- a global variable and a symbolic constant.
+
+ The global variable is an in6_addr structure named
+ "in6addr_loopback." The extern declaration for this variable is
+ defined in <netinet/in.h>:
+
+ extern const struct in6_addr in6addr_loopback;
+
+ Applications use in6addr_loopback as they would use INADDR_LOOPBACK
+ in IPv4 applications (but beware of the byte ordering difference
+ mentioned at the end of the previous section). For example, to open
+ a TCP connection to the local telnet server, an application could use
+ the following code:
+
+ struct sockaddr_in6 sin6;
+ . . .
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_flowinfo = 0;
+ sin6.sin6_port = htons(23);
+ sin6.sin6_addr = in6addr_loopback; /* structure assignment */
+ . . .
+ if (connect(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1)
+ . . .
+
+ The symbolic constant is named IN6ADDR_LOOPBACK_INIT and is defined
+ in <netinet/in.h>. It can be used at declaration time ONLY; for
+ example:
+
+ struct in6_addr loopbackaddr = IN6ADDR_LOOPBACK_INIT;
+
+ Like IN6ADDR_ANY_INIT, this constant cannot be used in an assignment
+ to a previously declared IPv6 address variable.
+
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 13]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+3.10 Portability Additions
+
+ One simple addition to the sockets API that can help application
+ writers is the "struct sockaddr_storage". This data structure can
+ simplify writing code that is portable across multiple address
+ families and platforms. This data structure is designed with the
+ following goals.
+
+ - Large enough to accommodate all supported protocol-specific address
+ structures.
+
+ - Aligned at an appropriate boundary so that pointers to it can be
+ cast as pointers to protocol specific address structures and used
+ to access the fields of those structures without alignment
+ problems.
+
+ The sockaddr_storage structure contains field ss_family which is of
+ type sa_family_t. When a sockaddr_storage structure is cast to a
+ sockaddr structure, the ss_family field of the sockaddr_storage
+ structure maps onto the sa_family field of the sockaddr structure.
+ When a sockaddr_storage structure is cast as a protocol specific
+ address structure, the ss_family field maps onto a field of that
+ structure that is of type sa_family_t and that identifies the
+ protocol's address family.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 14]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ An example implementation design of such a data structure would be as
+ follows.
+
+/*
+ * Desired design of maximum size and alignment
+ */
+#define _SS_MAXSIZE 128 /* Implementation specific max size */
+#define _SS_ALIGNSIZE (sizeof (int64_t))
+ /* Implementation specific desired alignment */
+/*
+ * Definitions used for sockaddr_storage structure paddings design.
+ */
+#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (sa_family_t))
+#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t) +
+ _SS_PAD1SIZE + _SS_ALIGNSIZE))
+struct sockaddr_storage {
+ sa_family_t ss_family; /* address family */
+ /* Following fields are implementation specific */
+ char __ss_pad1[_SS_PAD1SIZE];
+ /* 6 byte pad, this is to make implementation
+ /* specific pad up to alignment field that */
+ /* follows explicit in the data structure */
+ int64_t __ss_align; /* field to force desired structure */
+ /* storage alignment */
+ char __ss_pad2[_SS_PAD2SIZE];
+ /* 112 byte pad to achieve desired size, */
+ /* _SS_MAXSIZE value minus size of ss_family */
+ /* __ss_pad1, __ss_align fields is 112 */
+};
+
+ The above example implementation illustrates a data structure which
+ will align on a 64-bit boundary. An implementation-specific field
+ "__ss_align" along with "__ss_pad1" is used to force a 64-bit
+ alignment which covers proper alignment good enough for the needs of
+ sockaddr_in6 (IPv6), sockaddr_in (IPv4) address data structures. The
+ size of padding field __ss_pad1 depends on the chosen alignment
+ boundary. The size of padding field __ss_pad2 depends on the value
+ of overall size chosen for the total size of the structure. This
+ size and alignment are represented in the above example by
+ implementation specific (not required) constants _SS_MAXSIZE (chosen
+ value 128) and _SS_ALIGNSIZE (with chosen value 8). Constants
+ _SS_PAD1SIZE (derived value 6) and _SS_PAD2SIZE (derived value 112)
+ are also for illustration and not required. The derived values
+ assume sa_family_t is 2 bytes. The implementation specific
+ definitions and structure field names above start with an underscore
+ to denote implementation private namespace. Portable code is not
+ expected to access or reference those fields or constants.
+
+
+
+
+Gilligan, et al. Informational [Page 15]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ On implementations where the sockaddr data structure includes a
+ "sa_len" field this data structure would look like this:
+
+/*
+ * Definitions used for sockaddr_storage structure paddings design.
+ */
+#define _SS_PAD1SIZE (_SS_ALIGNSIZE -
+ (sizeof (uint8_t) + sizeof (sa_family_t))
+#define _SS_PAD2SIZE (_SS_MAXSIZE -
+ (sizeof (uint8_t) + sizeof (sa_family_t) +
+ _SS_PAD1SIZE + _SS_ALIGNSIZE))
+struct sockaddr_storage {
+ uint8_t ss_len; /* address length */
+ sa_family_t ss_family; /* address family */
+ /* Following fields are implementation specific */
+ char __ss_pad1[_SS_PAD1SIZE];
+ /* 6 byte pad, this is to make implementation
+ /* specific pad up to alignment field that */
+ /* follows explicit in the data structure */
+ int64_t __ss_align; /* field to force desired structure */
+ /* storage alignment */
+ char __ss_pad2[_SS_PAD2SIZE];
+ /* 112 byte pad to achieve desired size, */
+ /* _SS_MAXSIZE value minus size of ss_len, */
+ /* __ss_family, __ss_pad1, __ss_align fields is 112 */
+};
+
+4. Interface Identification
+
+ This API uses an interface index (a small positive integer) to
+ identify the local interface on which a multicast group is joined
+ (Section 5.2). Additionally, the advanced API [4] uses these same
+ interface indexes to identify the interface on which a datagram is
+ received, or to specify the interface on which a datagram is to be
+ sent.
+
+ Interfaces are normally known by names such as "le0", "sl1", "ppp2",
+ and the like. On Berkeley-derived implementations, when an interface
+ is made known to the system, the kernel assigns a unique positive
+ integer value (called the interface index) to that interface. These
+ are small positive integers that start at 1. (Note that 0 is never
+ used for an interface index.) There may be gaps so that there is no
+ current interface for a particular positive interface index.
+
+ This API defines two functions that map between an interface name and
+ index, a third function that returns all the interface names and
+ indexes, and a fourth function to return the dynamic memory allocated
+ by the previous function. How these functions are implemented is
+
+
+
+Gilligan, et al. Informational [Page 16]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ left up to the implementation. 4.4BSD implementations can implement
+ these functions using the existing sysctl() function with the
+ NET_RT_IFLIST command. Other implementations may wish to use ioctl()
+ for this purpose.
+
+4.1 Name-to-Index
+
+ The first function maps an interface name into its corresponding
+ index.
+
+ #include <net/if.h>
+
+ unsigned int if_nametoindex(const char *ifname);
+
+ If ifname is the name of an interface, the if_nametoindex() function
+ shall return the interface index corresponding to name ifname;
+ otherwise, it shall return zero. No errors are defined.
+
+4.2 Index-to-Name
+
+ The second function maps an interface index into its corresponding
+ name.
+
+ #include <net/if.h>
+
+ char *if_indextoname(unsigned int ifindex, char *ifname);
+
+ When this function is called, the ifname argument shall point to a
+ buffer of at least IF_NAMESIZE bytes. The function shall place in
+ this buffer the name of the interface with index ifindex.
+ (IF_NAMESIZE is also defined in <net/if.h> and its value includes a
+ terminating null byte at the end of the interface name.) If ifindex
+ is an interface index, then the function shall return the value
+ supplied in ifname, which points to a buffer now containing the
+ interface name. Otherwise, the function shall return a NULL pointer
+ and set errno to indicate the error. If there is no interface
+ corresponding to the specified index, errno is set to ENXIO. If
+ there was a system error (such as running out of memory), errno would
+ be set to the proper value (e.g., ENOMEM).
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 17]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+4.3 Return All Interface Names and Indexes
+
+ The if_nameindex structure holds the information about a single
+ interface and is defined as a result of including the <net/if.h>
+ header.
+
+ struct if_nameindex {
+ unsigned int if_index; /* 1, 2, ... */
+ char *if_name; /* null terminated name: "le0", ... */
+ };
+
+ The final function returns an array of if_nameindex structures, one
+ structure per interface.
+
+ #include <net/if.h>
+
+ struct if_nameindex *if_nameindex(void);
+
+ The end of the array of structures is indicated by a structure with
+ an if_index of 0 and an if_name of NULL. The function returns a NULL
+ pointer upon an error, and would set errno to the appropriate value.
+
+ The memory used for this array of structures along with the interface
+ names pointed to by the if_name members is obtained dynamically.
+ This memory is freed by the next function.
+
+4.4 Free Memory
+
+ The following function frees the dynamic memory that was allocated by
+ if_nameindex().
+
+ #include <net/if.h>
+
+ void if_freenameindex(struct if_nameindex *ptr);
+
+ The ptr argument shall be a pointer that was returned by
+ if_nameindex(). After if_freenameindex() has been called, the
+ application shall not use the array of which ptr is the address.
+
+5. Socket Options
+
+ A number of new socket options are defined for IPv6. All of these
+ new options are at the IPPROTO_IPV6 level. That is, the "level"
+ parameter in the getsockopt() and setsockopt() calls is IPPROTO_IPV6
+ when using these options. The constant name prefix IPV6_ is used in
+ all of the new socket options. This serves to clearly identify these
+ options as applying to IPv6.
+
+
+
+
+Gilligan, et al. Informational [Page 18]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ The declaration for IPPROTO_IPV6, the new IPv6 socket options, and
+ related constants defined in this section are obtained by including
+ the header <netinet/in.h>.
+
+5.1 Unicast Hop Limit
+
+ A new setsockopt() option controls the hop limit used in outgoing
+ unicast IPv6 packets. The name of this option is IPV6_UNICAST_HOPS,
+ and it is used at the IPPROTO_IPV6 layer. The following example
+ illustrates how it is used:
+
+ int hoplimit = 10;
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+ (char *) &hoplimit, sizeof(hoplimit)) == -1)
+ perror("setsockopt IPV6_UNICAST_HOPS");
+
+ When the IPV6_UNICAST_HOPS option is set with setsockopt(), the
+ option value given is used as the hop limit for all subsequent
+ unicast packets sent via that socket. If the option is not set, the
+ system selects a default value. The integer hop limit value (called
+ x) is interpreted as follows:
+
+ x < -1: return an error of EINVAL
+ x == -1: use kernel default
+ 0 <= x <= 255: use x
+ x >= 256: return an error of EINVAL
+
+ The IPV6_UNICAST_HOPS option may be used with getsockopt() to
+ determine the hop limit value that the system will use for subsequent
+ unicast packets sent via that socket. For example:
+
+ int hoplimit;
+ socklen_t len = sizeof(hoplimit);
+
+ if (getsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+ (char *) &hoplimit, &len) == -1)
+ perror("getsockopt IPV6_UNICAST_HOPS");
+ else
+ printf("Using %d for hop limit.\n", hoplimit);
+
+5.2 Sending and Receiving Multicast Packets
+
+ IPv6 applications may send multicast packets by simply specifying an
+ IPv6 multicast address as the destination address, for example in the
+ destination address argument of the sendto() function.
+
+
+
+
+
+Gilligan, et al. Informational [Page 19]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ Three socket options at the IPPROTO_IPV6 layer control some of the
+ parameters for sending multicast packets. Setting these options is
+ not required: applications may send multicast packets without using
+ these options. The setsockopt() options for controlling the sending
+ of multicast packets are summarized below. These three options can
+ also be used with getsockopt().
+
+ IPV6_MULTICAST_IF
+
+ Set the interface to use for outgoing multicast packets. The
+ argument is the index of the interface to use. If the
+ interface index is specified as zero, the system selects the
+ interface (for example, by looking up the address in a routing
+ table and using the resulting interface).
+
+ Argument type: unsigned int
+
+ IPV6_MULTICAST_HOPS
+
+ Set the hop limit to use for outgoing multicast packets. (Note
+ a separate option - IPV6_UNICAST_HOPS - is provided to set the
+ hop limit to use for outgoing unicast packets.)
+
+ The interpretation of the argument is the same as for the
+ IPV6_UNICAST_HOPS option:
+
+ x < -1: return an error of EINVAL
+ x == -1: use kernel default
+ 0 <= x <= 255: use x
+ x >= 256: return an error of EINVAL
+
+ If IPV6_MULTICAST_HOPS is not set, the default is 1
+ (same as IPv4 today)
+
+ Argument type: int
+
+ IPV6_MULTICAST_LOOP
+
+ If a multicast datagram is sent to a group to which the sending
+ host itself belongs (on the outgoing interface), a copy of the
+ datagram is looped back by the IP layer for local delivery if
+ this option is set to 1. If this option is set to 0 a copy is
+ not looped back. Other option values return an error of
+ EINVAL.
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 20]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ If IPV6_MULTICAST_LOOP is not set, the default is 1 (loopback;
+ same as IPv4 today).
+
+ Argument type: unsigned int
+
+ The reception of multicast packets is controlled by the two
+ setsockopt() options summarized below. An error of EOPNOTSUPP is
+ returned if these two options are used with getsockopt().
+
+ IPV6_JOIN_GROUP
+
+ Join a multicast group on a specified local interface.
+ If the interface index is specified as 0,
+ the kernel chooses the local interface.
+ For example, some kernels look up the multicast group
+ in the normal IPv6 routing table and use the resulting
+ interface.
+
+ Argument type: struct ipv6_mreq
+
+ IPV6_LEAVE_GROUP
+
+ Leave a multicast group on a specified interface.
+ If the interface index is specified as 0, the system
+ may choose a multicast group membership to drop by
+ matching the multicast address only.
+
+ Argument type: struct ipv6_mreq
+
+ The argument type of both of these options is the ipv6_mreq
+ structure, defined as a result of including the <netinet/in.h>
+ header;
+
+ struct ipv6_mreq {
+ struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast addr */
+ unsigned int ipv6mr_interface; /* interface index */
+ };
+
+ Note that to receive multicast datagrams a process must join the
+ multicast group to which datagrams will be sent. UDP applications
+ must also bind the UDP port to which datagrams will be sent. Some
+ processes also bind the multicast group address to the socket, in
+ addition to the port, to prevent other datagrams destined to that
+ same port from being delivered to the socket.
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 21]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+5.3 IPV6_V6ONLY option for AF_INET6 Sockets
+
+ This socket option restricts AF_INET6 sockets to IPv6 communications
+ only. As stated in section <3.7 Compatibility with IPv4 Nodes>,
+ AF_INET6 sockets may be used for both IPv4 and IPv6 communications.
+ Some applications may want to restrict their use of an AF_INET6
+ socket to IPv6 communications only. For these applications the
+ IPV6_V6ONLY socket option is defined. When this option is turned on,
+ the socket can be used to send and receive IPv6 packets only. This
+ is an IPPROTO_IPV6 level option. This option takes an int value.
+ This is a boolean option. By default this option is turned off.
+
+ Here is an example of setting this option:
+
+ int on = 1;
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&on, sizeof(on)) == -1)
+ perror("setsockopt IPV6_V6ONLY");
+ else
+ printf("IPV6_V6ONLY set\n");
+
+ Note - This option has no effect on the use of IPv4 Mapped addresses
+ which enter a node as a valid IPv6 addresses for IPv6 communications
+ as defined by Stateless IP/ICMP Translation Algorithm (SIIT) [5].
+
+ An example use of this option is to allow two versions of the same
+ server process to run on the same port, one providing service over
+ IPv6, the other providing the same service over IPv4.
+
+6. Library Functions
+
+ New library functions are needed to perform a variety of operations
+ with IPv6 addresses. Functions are needed to lookup IPv6 addresses
+ in the Domain Name System (DNS). Both forward lookup (nodename-to-
+ address translation) and reverse lookup (address-to-nodename
+ translation) need to be supported. Functions are also needed to
+ convert IPv6 addresses between their binary and textual form.
+
+ We note that the two existing functions, gethostbyname() and
+ gethostbyaddr(), are left as-is. New functions are defined to handle
+ both IPv4 and IPv6 addresses.
+
+ The commonly used function gethostbyname() is inadequate for many
+ applications, first because it provides no way for the caller to
+ specify anything about the types of addresses desired (IPv4 only,
+ IPv6 only, IPv4-mapped IPv6 are OK, etc.), and second because many
+ implementations of this function are not thread safe. RFC 2133
+
+
+
+Gilligan, et al. Informational [Page 22]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ defined a function named gethostbyname2() but this function was also
+ inadequate, first because its use required setting a global option
+ (RES_USE_INET6) when IPv6 addresses were required, and second because
+ a flag argument is needed to provide the caller with additional
+ control over the types of addresses required. The gethostbyname2()
+ function was deprecated in RFC 2553 and is no longer part of the
+ basic API.
+
+6.1 Protocol-Independent Nodename and Service Name Translation
+
+ Nodename-to-address translation is done in a protocol-independent
+ fashion using the getaddrinfo() function.
+
+#include <sys/socket.h>
+#include <netdb.h>
+
+
+int getaddrinfo(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res);
+
+void freeaddrinfo(struct addrinfo *ai);
+
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME,
+ AI_NUMERICHOST, .. */
+ int ai_family; /* AF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ socklen_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for nodename */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+};
+
+ The getaddrinfo() function translates the name of a service location
+ (for example, a host name) and/or a service name and returns a set of
+ socket addresses and associated information to be used in creating a
+ socket with which to address the specified service.
+
+ The nodename and servname arguments are either null pointers or
+ pointers to null-terminated strings. One or both of these two
+ arguments must be a non-null pointer.
+
+ The format of a valid name depends on the address family or families.
+ If a specific family is not given and the name could be interpreted
+ as valid within multiple supported families, the implementation will
+ attempt to resolve the name in all supported families and, in absence
+ of errors, one or more results shall be returned.
+
+
+
+Gilligan, et al. Informational [Page 23]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ If the nodename argument is not null, it can be a descriptive name or
+ can be an address string. If the specified address family is
+ AF_INET, AF_INET6, or AF_UNSPEC, valid descriptive names include host
+ names. If the specified address family is AF_INET or AF_UNSPEC,
+ address strings using Internet standard dot notation as specified in
+ inet_addr() are valid. If the specified address family is AF_INET6
+ or AF_UNSPEC, standard IPv6 text forms described in inet_pton() are
+ valid.
+
+ If nodename is not null, the requested service location is named by
+ nodename; otherwise, the requested service location is local to the
+ caller.
+
+ If servname is null, the call shall return network-level addresses
+ for the specified nodename. If servname is not null, it is a null-
+ terminated character string identifying the requested service. This
+ can be either a descriptive name or a numeric representation suitable
+ for use with the address family or families. If the specified
+ address family is AF_INET, AF_INET6 or AF_UNSPEC, the service can be
+ specified as a string specifying a decimal port number.
+
+ If the argument hints is not null, it refers to a structure
+ containing input values that may direct the operation by providing
+ options and by limiting the returned information to a specific socket
+ type, address family and/or protocol. In this hints structure every
+ member other than ai_flags, ai_family, ai_socktype and ai_protocol
+ shall be set to zero or a null pointer. A value of AF_UNSPEC for
+ ai_family means that the caller shall accept any address family. A
+ value of zero for ai_socktype means that the caller shall accept any
+ socket type. A value of zero for ai_protocol means that the caller
+ shall accept any protocol. If hints is a null pointer, the behavior
+ shall be as if it referred to a structure containing the value zero
+ for the ai_flags, ai_socktype and ai_protocol fields, and AF_UNSPEC
+ for the ai_family field.
+
+ Note:
+
+ 1. If the caller handles only TCP and not UDP, for example, then the
+ ai_protocol member of the hints structure should be set to
+ IPPROTO_TCP when getaddrinfo() is called.
+
+ 2. If the caller handles only IPv4 and not IPv6, then the ai_family
+ member of the hints structure should be set to AF_INET when
+ getaddrinfo() is called.
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 24]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ The ai_flags field to which hints parameter points shall be set to
+ zero or be the bitwise-inclusive OR of one or more of the values
+ AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_NUMERICSERV,
+ AI_V4MAPPED, AI_ALL, and AI_ADDRCONFIG.
+
+ If the AI_PASSIVE flag is specified, the returned address information
+ shall be suitable for use in binding a socket for accepting incoming
+ connections for the specified service (i.e., a call to bind()). In
+ this case, if the nodename argument is null, then the IP address
+ portion of the socket address structure shall be set to INADDR_ANY
+ for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6 address. If the
+ AI_PASSIVE flag is not specified, the returned address information
+ shall be suitable for a call to connect() (for a connection-mode
+ protocol) or for a call to connect(), sendto() or sendmsg() (for a
+ connectionless protocol). In this case, if the nodename argument is
+ null, then the IP address portion of the socket address structure
+ shall be set to the loopback address. This flag is ignored if the
+ nodename argument is not null.
+
+ If the AI_CANONNAME flag is specified and the nodename argument is
+ not null, the function shall attempt to determine the canonical name
+ corresponding to nodename (for example, if nodename is an alias or
+ shorthand notation for a complete name).
+
+ If the AI_NUMERICHOST flag is specified, then a non-null nodename
+ string supplied shall be a numeric host address string. Otherwise,
+ an [EAI_NONAME] error is returned. This flag shall prevent any type
+ of name resolution service (for example, the DNS) from being invoked.
+
+ If the AI_NUMERICSERV flag is specified, then a non-null servname
+ string supplied shall be a numeric port string. Otherwise, an
+ [EAI_NONAME] error shall be returned. This flag shall prevent any
+ type of name resolution service (for example, NIS+) from being
+ invoked.
+
+ If the AI_V4MAPPED flag is specified along with an ai_family of
+ AF_INET6, then getaddrinfo() shall return IPv4-mapped IPv6 addresses
+ on finding no matching IPv6 addresses (ai_addrlen shall be 16).
+
+ For example, when using the DNS, if no AAAA records are found then
+ a query is made for A records and any found are returned as IPv4-
+ mapped IPv6 addresses.
+
+ The AI_V4MAPPED flag shall be ignored unless ai_family equals
+ AF_INET6.
+
+ If the AI_ALL flag is used with the AI_V4MAPPED flag, then
+ getaddrinfo() shall return all matching IPv6 and IPv4 addresses.
+
+
+
+Gilligan, et al. Informational [Page 25]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ For example, when using the DNS, queries are made for both AAAA
+ records and A records, and getaddrinfo() returns the combined
+ results of both queries. Any IPv4 addresses found are returned as
+ IPv4-mapped IPv6 addresses.
+
+ The AI_ALL flag without the AI_V4MAPPED flag is ignored.
+
+ Note:
+
+ When ai_family is not specified (AF_UNSPEC), AI_V4MAPPED and
+ AI_ALL flags will only be used if AF_INET6 is supported.
+
+ If the AI_ADDRCONFIG flag is specified, IPv4 addresses shall be
+ returned only if an IPv4 address is configured on the local system,
+ and IPv6 addresses shall be returned only if an IPv6 address is
+ configured on the local system. The loopback address is not
+ considered for this case as valid as a configured address.
+
+ For example, when using the DNS, a query for AAAA records should
+ occur only if the node has at least one IPv6 address configured
+ (other than IPv6 loopback) and a query for A records should occur
+ only if the node has at least one IPv4 address configured (other
+ than the IPv4 loopback).
+
+ The ai_socktype field to which argument hints points specifies the
+ socket type for the service, as defined for socket(). If a specific
+ socket type is not given (for example, a value of zero) and the
+ service name could be interpreted as valid with multiple supported
+ socket types, the implementation shall attempt to resolve the service
+ name for all supported socket types and, in the absence of errors,
+ all possible results shall be returned. A non-zero socket type value
+ shall limit the returned information to values with the specified
+ socket type.
+
+ If the ai_family field to which hints points has the value AF_UNSPEC,
+ addresses shall be returned for use with any address family that can
+ be used with the specified nodename and/or servname. Otherwise,
+ addresses shall be returned for use only with the specified address
+ family. If ai_family is not AF_UNSPEC and ai_protocol is not zero,
+ then addresses are returned for use only with the specified address
+ family and protocol; the value of ai_protocol shall be interpreted as
+ in a call to the socket() function with the corresponding values of
+ ai_family and ai_protocol.
+
+ The freeaddrinfo() function frees one or more addrinfo structures
+ returned by getaddrinfo(), along with any additional storage
+ associated with those structures (for example, storage pointed to by
+ the ai_canonname and ai_addr fields; an application must not
+
+
+
+Gilligan, et al. Informational [Page 26]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ reference this storage after the associated addrinfo structure has
+ been freed). If the ai_next field of the structure is not null, the
+ entire list of structures is freed. The freeaddrinfo() function must
+ support the freeing of arbitrary sublists of an addrinfo list
+ originally returned by getaddrinfo().
+
+ Functions getaddrinfo() and freeaddrinfo() must be thread-safe.
+
+ A zero return value for getaddrinfo() indicates successful
+ completion; a non-zero return value indicates failure. The possible
+ values for the failures are listed below under Error Return Values.
+
+ Upon successful return of getaddrinfo(), the location to which res
+ points shall refer to a linked list of addrinfo structures, each of
+ which shall specify a socket address and information for use in
+ creating a socket with which to use that socket address. The list
+ shall include at least one addrinfo structure. The ai_next field of
+ each structure contains a pointer to the next structure on the list,
+ or a null pointer if it is the last structure on the list. Each
+ structure on the list shall include values for use with a call to the
+ socket() function, and a socket address for use with the connect()
+ function or, if the AI_PASSIVE flag was specified, for use with the
+ bind() function. The fields ai_family, ai_socktype, and ai_protocol
+ shall be usable as the arguments to the socket() function to create a
+ socket suitable for use with the returned address. The fields
+ ai_addr and ai_addrlen are usable as the arguments to the connect()
+ or bind() functions with such a socket, according to the AI_PASSIVE
+ flag.
+
+ If nodename is not null, and if requested by the AI_CANONNAME flag,
+ the ai_canonname field of the first returned addrinfo structure shall
+ point to a null-terminated string containing the canonical name
+ corresponding to the input nodename; if the canonical name is not
+ available, then ai_canonname shall refer to the nodename argument or
+ a string with the same contents. The contents of the ai_flags field
+ of the returned structures are undefined.
+
+ All fields in socket address structures returned by getaddrinfo()
+ that are not filled in through an explicit argument (for example,
+ sin6_flowinfo) shall be set to zero.
+
+ Note: This makes it easier to compare socket address structures.
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 27]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ Error Return Values:
+
+ The getaddrinfo() function shall fail and return the corresponding
+ value if:
+
+ [EAI_AGAIN] The name could not be resolved at this time. Future
+ attempts may succeed.
+
+ [EAI_BADFLAGS] The flags parameter had an invalid value.
+
+ [EAI_FAIL] A non-recoverable error occurred when attempting to
+ resolve the name.
+
+ [EAI_FAMILY] The address family was not recognized.
+
+ [EAI_MEMORY] There was a memory allocation failure when trying to
+ allocate storage for the return value.
+
+ [EAI_NONAME] The name does not resolve for the supplied
+ parameters. Neither nodename nor servname were
+ supplied. At least one of these must be supplied.
+
+ [EAI_SERVICE] The service passed was not recognized for the
+ specified socket type.
+
+ [EAI_SOCKTYPE] The intended socket type was not recognized.
+
+ [EAI_SYSTEM] A system error occurred; the error code can be found
+ in errno.
+
+ The gai_strerror() function provides a descriptive text string
+ corresponding to an EAI_xxx error value.
+
+ #include <netdb.h>
+
+ const char *gai_strerror(int ecode);
+
+ The argument is one of the EAI_xxx values defined for the
+ getaddrinfo() and getnameinfo() functions. The return value points
+ to a string describing the error. If the argument is not one of the
+ EAI_xxx values, the function still returns a pointer to a string
+ whose contents indicate an unknown error.
+
+6.2 Socket Address Structure to Node Name and Service Name
+
+ The getnameinfo() function is used to translate the contents of a
+ socket address structure to a node name and/or service name.
+
+
+
+
+Gilligan, et al. Informational [Page 28]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ #include <sys/socket.h>
+ #include <netdb.h>
+
+ int getnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *node, socklen_t nodelen,
+ char *service, socklen_t servicelen,
+ int flags);
+
+ The getnameinfo() function shall translate a socket address to a node
+ name and service location, all of which are defined as in
+ getaddrinfo().
+
+ The sa argument points to a socket address structure to be
+ translated.
+
+ The salen argument holds the size of the socket address structure
+ pointed to by sa.
+
+ If the socket address structure contains an IPv4-mapped IPv6 address
+ or an IPv4-compatible IPv6 address, the implementation shall extract
+ the embedded IPv4 address and lookup the node name for that IPv4
+ address.
+
+ Note: The IPv6 unspecified address ("::") and the IPv6 loopback
+ address ("::1") are not IPv4-compatible addresses. If the address
+ is the IPv6 unspecified address ("::"), a lookup is not performed,
+ and the [EAI_NONAME] error is returned.
+
+ If the node argument is non-NULL and the nodelen argument is nonzero,
+ then the node argument points to a buffer able to contain up to
+ nodelen characters that receives the node name as a null-terminated
+ string. If the node argument is NULL or the nodelen argument is
+ zero, the node name shall not be returned. If the node's name cannot
+ be located, the numeric form of the node's address is returned
+ instead of its name.
+
+ If the service argument is non-NULL and the servicelen argument is
+ non-zero, then the service argument points to a buffer able to
+ contain up to servicelen bytes that receives the service name as a
+ null-terminated string. If the service argument is NULL or the
+ servicelen argument is zero, the service name shall not be returned.
+ If the service's name cannot be located, the numeric form of the
+ service address (for example, its port number) shall be returned
+ instead of its name.
+
+ The arguments node and service cannot both be NULL.
+
+
+
+
+
+Gilligan, et al. Informational [Page 29]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ The flags argument is a flag that changes the default actions of the
+ function. By default the fully-qualified domain name (FQDN) for the
+ host shall be returned, but:
+
+ - If the flag bit NI_NOFQDN is set, only the node name portion of
+ the FQDN shall be returned for local hosts.
+
+ - If the flag bit NI_NUMERICHOST is set, the numeric form of the
+ host's address shall be returned instead of its name, under all
+ circumstances.
+
+ - If the flag bit NI_NAMEREQD is set, an error shall be returned if
+ the host's name cannot be located.
+
+ - If the flag bit NI_NUMERICSERV is set, the numeric form of the
+ service address shall be returned (for example, its port number)
+ instead of its name, under all circumstances.
+
+ - If the flag bit NI_DGRAM is set, this indicates that the service
+ is a datagram service (SOCK_DGRAM). The default behavior shall
+ assume that the service is a stream service (SOCK_STREAM).
+
+ Note:
+
+ 1. The NI_NUMERICxxx flags are required to support the "-n" flags
+ that many commands provide.
+
+ 2. The NI_DGRAM flag is required for the few AF_INET and AF_INET6
+ port numbers (for example, [512,514]) that represent different
+ services for UDP and TCP.
+
+ The getnameinfo() function shall be thread safe.
+
+ A zero return value for getnameinfo() indicates successful
+ completion; a non-zero return value indicates failure.
+
+ Upon successful completion, getnameinfo() shall return the node and
+ service names, if requested, in the buffers provided. The returned
+ names are always null-terminated strings.
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 30]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ Error Return Values:
+
+ The getnameinfo() function shall fail and return the corresponding
+ value if:
+
+ [EAI_AGAIN] The name could not be resolved at this time.
+ Future attempts may succeed.
+
+ [EAI_BADFLAGS] The flags had an invalid value.
+
+ [EAI_FAIL] A non-recoverable error occurred.
+
+ [EAI_FAMILY] The address family was not recognized or the address
+ length was invalid for the specified family.
+
+ [EAI_MEMORY] There was a memory allocation failure.
+
+ [EAI_NONAME] The name does not resolve for the supplied parameters.
+ NI_NAMEREQD is set and the host's name cannot be
+ located, or both nodename and servname were null.
+
+ [EAI_OVERFLOW] An argument buffer overflowed.
+
+ [EAI_SYSTEM] A system error occurred. The error code can be found
+ in errno.
+
+6.3 Address Conversion Functions
+
+ The two IPv4 functions inet_addr() and inet_ntoa() convert an IPv4
+ address between binary and text form. IPv6 applications need similar
+ functions. The following two functions convert both IPv6 and IPv4
+ addresses:
+
+ #include <arpa/inet.h>
+
+ int inet_pton(int af, const char *src, void *dst);
+
+ const char *inet_ntop(int af, const void *src,
+ char *dst, socklen_t size);
+
+ The inet_pton() function shall convert an address in its standard
+ text presentation form into its numeric binary form. The af argument
+ shall specify the family of the address. The AF_INET and AF_INET6
+ address families shall be supported. The src argument points to the
+ string being passed in. The dst argument points to a buffer into
+ which the function stores the numeric address; this shall be large
+ enough to hold the numeric address (32 bits for AF_INET, 128 bits for
+ AF_INET6). The inet_pton() function shall return 1 if the conversion
+
+
+
+Gilligan, et al. Informational [Page 31]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ succeeds, with the address pointed to by dst in network byte order.
+ It shall return 0 if the input is not a valid IPv4 dotted-decimal
+ string or a valid IPv6 address string, or -1 with errno set to
+ EAFNOSUPPORT if the af argument is unknown.
+
+ If the af argument of inet_pton() is AF_INET, the src string shall be
+ in the standard IPv4 dotted-decimal form:
+
+ ddd.ddd.ddd.ddd
+
+ where "ddd" is a one to three digit decimal number between 0 and 255.
+ The inet_pton() function does not accept other formats (such as the
+ octal numbers, hexadecimal numbers, and fewer than four numbers that
+ inet_addr() accepts).
+
+ If the af argument of inet_pton() is AF_INET6, the src string shall
+ be in one of the standard IPv6 text forms defined in Section 2.2 of
+ the addressing architecture specification [2].
+
+ The inet_ntop() function shall convert a numeric address into a text
+ string suitable for presentation. The af argument shall specify the
+ family of the address. This can be AF_INET or AF_INET6. The src
+ argument points to a buffer holding an IPv4 address if the af
+ argument is AF_INET, or an IPv6 address if the af argument is
+ AF_INET6; the address must be in network byte order. The dst
+ argument points to a buffer where the function stores the resulting
+ text string; it shall not be NULL. The size argument specifies the
+ size of this buffer, which shall be large enough to hold the text
+ string (INET_ADDRSTRLEN characters for IPv4, INET6_ADDRSTRLEN
+ characters for IPv6).
+
+ In order to allow applications to easily declare buffers of the
+ proper size to store IPv4 and IPv6 addresses in string form, the
+ following two constants are defined in <netinet/in.h>:
+
+ #define INET_ADDRSTRLEN 16
+ #define INET6_ADDRSTRLEN 46
+
+ The inet_ntop() function shall return a pointer to the buffer
+ containing the text string if the conversion succeeds, and NULL
+ otherwise. Upon failure, errno is set to EAFNOSUPPORT if the af
+ argument is invalid or ENOSPC if the size of the result buffer is
+ inadequate.
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 32]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+6.4 Address Testing Macros
+
+ The following macros can be used to test for special IPv6 addresses.
+
+ #include <netinet/in.h>
+
+ int IN6_IS_ADDR_UNSPECIFIED (const struct in6_addr *);
+ int IN6_IS_ADDR_LOOPBACK (const struct in6_addr *);
+ int IN6_IS_ADDR_MULTICAST (const struct in6_addr *);
+ int IN6_IS_ADDR_LINKLOCAL (const struct in6_addr *);
+ int IN6_IS_ADDR_SITELOCAL (const struct in6_addr *);
+ int IN6_IS_ADDR_V4MAPPED (const struct in6_addr *);
+ int IN6_IS_ADDR_V4COMPAT (const struct in6_addr *);
+
+ int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
+ int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
+ int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
+ int IN6_IS_ADDR_MC_ORGLOCAL (const struct in6_addr *);
+ int IN6_IS_ADDR_MC_GLOBAL (const struct in6_addr *);
+
+ The first seven macros return true if the address is of the specified
+ type, or false otherwise. The last five test the scope of a
+ multicast address and return true if the address is a multicast
+ address of the specified scope or false if the address is either not
+ a multicast address or not of the specified scope.
+
+ Note that IN6_IS_ADDR_LINKLOCAL and IN6_IS_ADDR_SITELOCAL return true
+ only for the two types of local-use IPv6 unicast addresses (Link-
+ Local and Site-Local) defined in [2], and that by this definition,
+ the IN6_IS_ADDR_LINKLOCAL macro returns false for the IPv6 loopback
+ address (::1). These two macros do not return true for IPv6
+ multicast addresses of either link-local scope or site-local scope.
+
+7. Summary of New Definitions
+
+ The following list summarizes the constants, structure, and extern
+ definitions discussed in this memo, sorted by header.
+
+<net/if.h> IF_NAMESIZE
+<net/if.h> struct if_nameindex{};
+
+<netdb.h> AI_ADDRCONFIG
+<netdb.h> AI_ALL
+<netdb.h> AI_CANONNAME
+<netdb.h> AI_NUMERICHOST
+<netdb.h> AI_NUMERICSERV
+<netdb.h> AI_PASSIVE
+<netdb.h> AI_V4MAPPED
+
+
+
+Gilligan, et al. Informational [Page 33]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+<netdb.h> EAI_AGAIN
+<netdb.h> EAI_BADFLAGS
+<netdb.h> EAI_FAIL
+<netdb.h> EAI_FAMILY
+<netdb.h> EAI_MEMORY
+<netdb.h> EAI_NONAME
+<netdb.h> EAI_OVERFLOW
+<netdb.h> EAI_SERVICE
+<netdb.h> EAI_SOCKTYPE
+<netdb.h> EAI_SYSTEM
+<netdb.h> NI_DGRAM
+<netdb.h> NI_NAMEREQD
+<netdb.h> NI_NOFQDN
+<netdb.h> NI_NUMERICHOST
+<netdb.h> NI_NUMERICSERV
+<netdb.h> struct addrinfo{};
+
+<netinet/in.h> IN6ADDR_ANY_INIT
+<netinet/in.h> IN6ADDR_LOOPBACK_INIT
+<netinet/in.h> INET6_ADDRSTRLEN
+<netinet/in.h> INET_ADDRSTRLEN
+<netinet/in.h> IPPROTO_IPV6
+<netinet/in.h> IPV6_JOIN_GROUP
+<netinet/in.h> IPV6_LEAVE_GROUP
+<netinet/in.h> IPV6_MULTICAST_HOPS
+<netinet/in.h> IPV6_MULTICAST_IF
+<netinet/in.h> IPV6_MULTICAST_LOOP
+<netinet/in.h> IPV6_UNICAST_HOPS
+<netinet/in.h> IPV6_V6ONLY
+<netinet/in.h> SIN6_LEN
+<netinet/in.h> extern const struct in6_addr in6addr_any;
+<netinet/in.h> extern const struct in6_addr in6addr_loopback;
+<netinet/in.h> struct in6_addr{};
+<netinet/in.h> struct ipv6_mreq{};
+<netinet/in.h> struct sockaddr_in6{};
+
+<sys/socket.h> AF_INET6
+<sys/socket.h> PF_INET6
+<sys/socket.h> struct sockaddr_storage;
+
+ The following list summarizes the function and macro prototypes
+ discussed in this memo, sorted by header.
+
+<arpa/inet.h> int inet_pton(int, const char *, void *);
+<arpa/inet.h> const char *inet_ntop(int, const void *,
+ char *, socklen_t);
+
+
+
+
+
+Gilligan, et al. Informational [Page 34]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+<net/if.h> char *if_indextoname(unsigned int, char *);
+<net/if.h> unsigned int if_nametoindex(const char *);
+<net/if.h> void if_freenameindex(struct if_nameindex *);
+<net/if.h> struct if_nameindex *if_nameindex(void);
+
+<netdb.h> int getaddrinfo(const char *, const char *,
+ const struct addrinfo *,
+ struct addrinfo **);
+<netdb.h> int getnameinfo(const struct sockaddr *, socklen_t,
+ char *, socklen_t, char *, socklen_t, int);
+<netdb.h> void freeaddrinfo(struct addrinfo *);
+<netdb.h> const char *gai_strerror(int);
+
+<netinet/in.h> int IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_LOOPBACK(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_GLOBAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_ORGLOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_MULTICAST(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_SITELOCAL(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_UNSPECIFIED(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_V4COMPAT(const struct in6_addr *);
+<netinet/in.h> int IN6_IS_ADDR_V4MAPPED(const struct in6_addr *);
+
+8. Security Considerations
+
+ IPv6 provides a number of new security mechanisms, many of which need
+ to be accessible to applications. Companion memos detailing the
+ extensions to the socket interfaces to support IPv6 security are
+ being written.
+
+9. Changes from RFC 2553
+
+ 1. Add brief description of the history of this API and its relation
+ to the Open Group/IEEE/ISO standards.
+
+ 2. Alignments with [3].
+
+ 3. Removed all references to getipnodebyname() and getipnodebyaddr(),
+ which are deprecated in favor of getaddrinfo() and getnameinfo().
+
+ 4. Added IPV6_V6ONLY IP level socket option to permit nodes to not
+ process IPv4 packets as IPv4 Mapped addresses in implementations.
+
+ 5. Added SIIT to references and added new contributors.
+
+
+
+
+Gilligan, et al. Informational [Page 35]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+ 6. In previous versions of this specification, the sin6_flowinfo
+ field was associated with the IPv6 traffic class and flow label,
+ but its usage was not completely specified. The complete
+ definition of the sin6_flowinfo field, including its association
+ with the traffic class or flow label, is now deferred to a future
+ specification.
+
+10. Acknowledgments
+
+ This specification's evolution and completeness were significantly
+ influenced by the efforts of Richard Stevens, who has passed on.
+ Richard's wisdom and talent made the specification what it is today.
+ The co-authors will long think of Richard with great respect.
+
+ Thanks to the many people who made suggestions and provided feedback
+ to this document, including:
+
+ Werner Almesberger, Ran Atkinson, Fred Baker, Dave Borman, Andrew
+ Cherenson, Alex Conta, Alan Cox, Steve Deering, Richard Draves,
+ Francis Dupont, Robert Elz, Brian Haberman, Jun-ichiro itojun Hagino,
+ Marc Hasson, Tom Herbert, Bob Hinden, Wan-Yen Hsu, Christian Huitema,
+ Koji Imada, Markus Jork, Ron Lee, Alan Lloyd, Charles Lynn, Dan
+ McDonald, Dave Mitton, Finnbarr Murphy, Thomas Narten, Josh Osborne,
+ Craig Partridge, Jean-Luc Richier, Bill Sommerfield, Erik Scoredos,
+ Keith Sklower, JINMEI Tatuya, Dave Thaler, Matt Thomas, Harvey
+ Thompson, Dean D. Throop, Karen Tracey, Glenn Trewitt, Paul Vixie,
+ David Waitzman, Carl Williams, Kazu Yamamoto, Vlad Yasevich, Stig
+ Venaas, and Brian Zill.
+
+ The getaddrinfo() and getnameinfo() functions are taken from an
+ earlier document by Keith Sklower. As noted in that document,
+ William Durst, Steven Wise, Michael Karels, and Eric Allman provided
+ many useful discussions on the subject of protocol-independent name-
+ to-address translation, and reviewed early versions of Keith
+ Sklower's original proposal. Eric Allman implemented the first
+ prototype of getaddrinfo(). The observation that specifying the pair
+ of name and service would suffice for connecting to a service
+ independent of protocol details was made by Marshall Rose in a
+ proposal to X/Open for a "Uniform Network Interface".
+
+ Craig Metz, Jack McCann, Erik Nordmark, Tim Hartrick, and Mukesh
+ Kacker made many contributions to this document. Ramesh Govindan
+ made a number of contributions and co-authored an earlier version of
+ this memo.
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 36]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+11. References
+
+ [1] Deering, S. and R. Hinden, "Internet Protocol, Version 6 (IPv6)
+ Specification", RFC 2460, December 1998.
+
+ [2] Hinden, R. and S. Deering, "IP Version 6 Addressing
+ Architecture", RFC 2373, July 1998.
+
+ [3] IEEE Std. 1003.1-2001 Standard for Information Technology --
+ Portable Operating System Interface (POSIX). Open Group
+ Technical Standard: Base Specifications, Issue 6, December 2001.
+ ISO/IEC 9945:2002. http://www.opengroup.org/austin
+
+ [4] Stevens, W. and M. Thomas, "Advanced Sockets API for IPv6", RFC
+ 2292, February 1998.
+
+ [5] Nordmark, E., "Stateless IP/ICMP Translation Algorithm (SIIT)",
+ RFC 2765, February 2000.
+
+ [6] The Open Group Base Working Group
+ http://www.opengroup.org/platform/base.html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 37]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+12. Authors' Addresses
+
+ Bob Gilligan
+ Intransa, Inc.
+ 2870 Zanker Rd.
+ San Jose, CA 95134
+
+ Phone: 408-678-8647
+ EMail: gilligan@intransa.com
+
+
+ Susan Thomson
+ Cisco Systems
+ 499 Thornall Street, 8th floor
+ Edison, NJ 08837
+
+ Phone: 732-635-3086
+ EMail: sethomso@cisco.com
+
+
+ Jim Bound
+ Hewlett-Packard Company
+ 110 Spitbrook Road ZKO3-3/W20
+ Nashua, NH 03062
+
+ Phone: 603-884-0062
+ EMail: Jim.Bound@hp.com
+
+
+ Jack McCann
+ Hewlett-Packard Company
+ 110 Spitbrook Road ZKO3-3/W20
+ Nashua, NH 03062
+
+ Phone: 603-884-2608
+ EMail: Jack.McCann@hp.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 38]
+
+RFC 3493 Basic Socket Interface Extensions for IPv6 February 2003
+
+
+13. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gilligan, et al. Informational [Page 39]
+
diff --git a/doc/rfc/rfc3513.txt b/doc/rfc/rfc3513.txt
new file mode 100644
index 0000000..49c0fa4
--- /dev/null
+++ b/doc/rfc/rfc3513.txt
@@ -0,0 +1,1459 @@
+
+
+
+
+
+
+Network Working Group R. Hinden
+Request for Comments: 3513 Nokia
+Obsoletes: 2373 S. Deering
+Category: Standards Track Cisco Systems
+ April 2003
+
+
+ Internet Protocol Version 6 (IPv6) Addressing Architecture
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ This specification defines the addressing architecture of the IP
+ Version 6 (IPv6) protocol. The document includes the IPv6 addressing
+ model, text representations of IPv6 addresses, definition of IPv6
+ unicast addresses, anycast addresses, and multicast addresses, and an
+ IPv6 node's required addresses.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 1]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+Table of Contents
+
+ 1. Introduction.................................................3
+ 2. IPv6 Addressing..............................................3
+ 2.1 Addressing Model.........................................4
+ 2.2 Text Representation of Addresses.........................4
+ 2.3 Text Representation of Address Prefixes..................5
+ 2.4 Address Type Identification..............................6
+ 2.5 Unicast Addresses........................................7
+ 2.5.1 Interface Identifiers..............................8
+ 2.5.2 The Unspecified Address............................9
+ 2.5.3 The Loopback Address...............................9
+ 2.5.4 Global Unicast Addresses..........................10
+ 2.5.5 IPv6 Addresses with Embedded IPv4 Addresses.......10
+ 2.5.6 Local-use IPv6 Unicast Addresses..................11
+ 2.6 Anycast Addresses.......................................12
+ 2.6.1 Required Anycast Address..........................13
+ 2.7 Multicast Addresses.....................................13
+ 2.7.1 Pre-Defined Multicast Addresses...................15
+ 2.8 A Node's Required Addresses.............................17
+ 3. Security Considerations.....................................17
+ 4. IANA Considerations.........................................18
+ 5. References..................................................19
+ 5.1 Normative References....................................19
+ 5.2 Informative References..................................19
+ APPENDIX A: Creating Modified EUI-64 format Interface IDs......21
+ APPENDIX B: Changes from RFC-2373..............................24
+ Authors' Addresses.............................................25
+ Full Copyright Statement.......................................26
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 2]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+1. Introduction
+
+ This specification defines the addressing architecture of the IP
+ Version 6 (IPv6) protocol. It includes the basic formats for the
+ various types of IPv6 addresses (unicast, anycast, and multicast).
+
+ The authors would like to acknowledge the contributions of Paul
+ Francis, Scott Bradner, Jim Bound, Brian Carpenter, Matt Crawford,
+ Deborah Estrin, Roger Fajman, Bob Fink, Peter Ford, Bob Gilligan,
+ Dimitry Haskin, Tom Harsch, Christian Huitema, Tony Li, Greg
+ Minshall, Thomas Narten, Erik Nordmark, Yakov Rekhter, Bill Simpson,
+ Sue Thomson, Markku Savela, and Larry Masinter.
+
+2. IPv6 Addressing
+
+ IPv6 addresses are 128-bit identifiers for interfaces and sets of
+ interfaces (where "interface" is as defined in section 2 of [IPV6]).
+ There are three types of addresses:
+
+ Unicast: An identifier for a single interface. A packet sent to a
+ unicast address is delivered to the interface identified
+ by that address.
+
+ Anycast: An identifier for a set of interfaces (typically belonging
+ to different nodes). A packet sent to an anycast address
+ is delivered to one of the interfaces identified by that
+ address (the "nearest" one, according to the routing
+ protocols' measure of distance).
+
+ Multicast: An identifier for a set of interfaces (typically belonging
+ to different nodes). A packet sent to a multicast address
+ is delivered to all interfaces identified by that address.
+
+ There are no broadcast addresses in IPv6, their function being
+ superseded by multicast addresses.
+
+ In this document, fields in addresses are given a specific name, for
+ example "subnet". When this name is used with the term "ID" for
+ identifier after the name (e.g., "subnet ID"), it refers to the
+ contents of the named field. When it is used with the term "prefix"
+ (e.g., "subnet prefix") it refers to all of the address from the left
+ up to and including this field.
+
+ In IPv6, all zeros and all ones are legal values for any field,
+ unless specifically excluded. Specifically, prefixes may contain, or
+ end with, zero-valued fields.
+
+
+
+
+
+Hinden & Deering Standards Track [Page 3]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+2.1 Addressing Model
+
+ IPv6 addresses of all types are assigned to interfaces, not nodes.
+ An IPv6 unicast address refers to a single interface. Since each
+ interface belongs to a single node, any of that node's interfaces'
+ unicast addresses may be used as an identifier for the node.
+
+ All interfaces are required to have at least one link-local unicast
+ address (see section 2.8 for additional required addresses). A
+ single interface may also have multiple IPv6 addresses of any type
+ (unicast, anycast, and multicast) or scope. Unicast addresses with
+ scope greater than link-scope are not needed for interfaces that are
+ not used as the origin or destination of any IPv6 packets to or from
+ non-neighbors. This is sometimes convenient for point-to-point
+ interfaces. There is one exception to this addressing model:
+
+ A unicast address or a set of unicast addresses may be assigned to
+ multiple physical interfaces if the implementation treats the
+ multiple physical interfaces as one interface when presenting it
+ to the internet layer. This is useful for load-sharing over
+ multiple physical interfaces.
+
+ Currently IPv6 continues the IPv4 model that a subnet prefix is
+ associated with one link. Multiple subnet prefixes may be assigned
+ to the same link.
+
+2.2 Text Representation of Addresses
+
+ There are three conventional forms for representing IPv6 addresses as
+ text strings:
+
+ 1. The preferred form is x:x:x:x:x:x:x:x, where the 'x's are the
+ hexadecimal values of the eight 16-bit pieces of the address.
+
+ Examples:
+
+ FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
+
+ 1080:0:0:0:8:800:200C:417A
+
+ Note that it is not necessary to write the leading zeros in an
+ individual field, but there must be at least one numeral in every
+ field (except for the case described in 2.).
+
+ 2. Due to some methods of allocating certain styles of IPv6
+ addresses, it will be common for addresses to contain long strings
+ of zero bits. In order to make writing addresses containing zero
+ bits easier a special syntax is available to compress the zeros.
+
+
+
+Hinden & Deering Standards Track [Page 4]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ The use of "::" indicates one or more groups of 16 bits of zeros.
+ The "::" can only appear once in an address. The "::" can also be
+ used to compress leading or trailing zeros in an address.
+
+ For example, the following addresses:
+
+ 1080:0:0:0:8:800:200C:417A a unicast address
+ FF01:0:0:0:0:0:0:101 a multicast address
+ 0:0:0:0:0:0:0:1 the loopback address
+ 0:0:0:0:0:0:0:0 the unspecified addresses
+
+ may be represented as:
+
+ 1080::8:800:200C:417A a unicast address
+ FF01::101 a multicast address
+ ::1 the loopback address
+ :: the unspecified addresses
+
+ 3. An alternative form that is sometimes more convenient when dealing
+ with a mixed environment of IPv4 and IPv6 nodes is
+ x:x:x:x:x:x:d.d.d.d, where the 'x's are the hexadecimal values of
+ the six high-order 16-bit pieces of the address, and the 'd's are
+ the decimal values of the four low-order 8-bit pieces of the
+ address (standard IPv4 representation). Examples:
+
+ 0:0:0:0:0:0:13.1.68.3
+
+ 0:0:0:0:0:FFFF:129.144.52.38
+
+ or in compressed form:
+
+ ::13.1.68.3
+
+ ::FFFF:129.144.52.38
+
+2.3 Text Representation of Address Prefixes
+
+ The text representation of IPv6 address prefixes is similar to the
+ way IPv4 addresses prefixes are written in CIDR notation [CIDR]. An
+ IPv6 address prefix is represented by the notation:
+
+ ipv6-address/prefix-length
+
+ where
+
+ ipv6-address is an IPv6 address in any of the notations listed
+ in section 2.2.
+
+
+
+
+Hinden & Deering Standards Track [Page 5]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ prefix-length is a decimal value specifying how many of the
+ leftmost contiguous bits of the address comprise
+ the prefix.
+
+ For example, the following are legal representations of the 60-bit
+ prefix 12AB00000000CD3 (hexadecimal):
+
+ 12AB:0000:0000:CD30:0000:0000:0000:0000/60
+ 12AB::CD30:0:0:0:0/60
+ 12AB:0:0:CD30::/60
+
+ The following are NOT legal representations of the above prefix:
+
+ 12AB:0:0:CD3/60 may drop leading zeros, but not trailing zeros,
+ within any 16-bit chunk of the address
+
+ 12AB::CD30/60 address to left of "/" expands to
+ 12AB:0000:0000:0000:0000:000:0000:CD30
+
+ 12AB::CD3/60 address to left of "/" expands to
+ 12AB:0000:0000:0000:0000:000:0000:0CD3
+
+ When writing both a node address and a prefix of that node address
+ (e.g., the node's subnet prefix), the two can combined as follows:
+
+ the node address 12AB:0:0:CD30:123:4567:89AB:CDEF
+ and its subnet number 12AB:0:0:CD30::/60
+
+ can be abbreviated as 12AB:0:0:CD30:123:4567:89AB:CDEF/60
+
+2.4 Address Type Identification
+
+ The type of an IPv6 address is identified by the high-order bits of
+ the address, as follows:
+
+ Address type Binary prefix IPv6 notation Section
+ ------------ ------------- ------------- -------
+ Unspecified 00...0 (128 bits) ::/128 2.5.2
+ Loopback 00...1 (128 bits) ::1/128 2.5.3
+ Multicast 11111111 FF00::/8 2.7
+ Link-local unicast 1111111010 FE80::/10 2.5.6
+ Site-local unicast 1111111011 FEC0::/10 2.5.6
+ Global unicast (everything else)
+
+ Anycast addresses are taken from the unicast address spaces (of any
+ scope) and are not syntactically distinguishable from unicast
+ addresses.
+
+
+
+
+Hinden & Deering Standards Track [Page 6]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ The general format of global unicast addresses is described in
+ section 2.5.4. Some special-purpose subtypes of global unicast
+ addresses which contain embedded IPv4 addresses (for the purposes of
+ IPv4-IPv6 interoperation) are described in section 2.5.5.
+
+ Future specifications may redefine one or more sub-ranges of the
+ global unicast space for other purposes, but unless and until that
+ happens, implementations must treat all addresses that do not start
+ with any of the above-listed prefixes as global unicast addresses.
+
+2.5 Unicast Addresses
+
+ IPv6 unicast addresses are aggregable with prefixes of arbitrary
+ bit-length similar to IPv4 addresses under Classless Interdomain
+ Routing.
+
+ There are several types of unicast addresses in IPv6, in particular
+ global unicast, site-local unicast, and link-local unicast. There
+ are also some special-purpose subtypes of global unicast, such as
+ IPv6 addresses with embedded IPv4 addresses or encoded NSAP
+ addresses. Additional address types or subtypes can be defined in
+ the future.
+
+ IPv6 nodes may have considerable or little knowledge of the internal
+ structure of the IPv6 address, depending on the role the node plays
+ (for instance, host versus router). At a minimum, a node may
+ consider that unicast addresses (including its own) have no internal
+ structure:
+
+ | 128 bits |
+ +-----------------------------------------------------------------+
+ | node address |
+ +-----------------------------------------------------------------+
+
+ A slightly sophisticated host (but still rather simple) may
+ additionally be aware of subnet prefix(es) for the link(s) it is
+ attached to, where different addresses may have different values for
+ n:
+
+ | n bits | 128-n bits |
+ +------------------------------------------------+----------------+
+ | subnet prefix | interface ID |
+ +------------------------------------------------+----------------+
+
+ Though a very simple router may have no knowledge of the internal
+ structure of IPv6 unicast addresses, routers will more generally have
+ knowledge of one or more of the hierarchical boundaries for the
+ operation of routing protocols. The known boundaries will differ
+
+
+
+Hinden & Deering Standards Track [Page 7]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ from router to router, depending on what positions the router holds
+ in the routing hierarchy.
+
+2.5.1 Interface Identifiers
+
+ Interface identifiers in IPv6 unicast addresses are used to identify
+ interfaces on a link. They are required to be unique within a subnet
+ prefix. It is recommended that the same interface identifier not be
+ assigned to different nodes on a link. They may also be unique over
+ a broader scope. In some cases an interface's identifier will be
+ derived directly from that interface's link-layer address. The same
+ interface identifier may be used on multiple interfaces on a single
+ node, as long as they are attached to different subnets.
+
+ Note that the uniqueness of interface identifiers is independent of
+ the uniqueness of IPv6 addresses. For example, a global unicast
+ address may be created with a non-global scope interface identifier
+ and a site-local address may be created with a global scope interface
+ identifier.
+
+ For all unicast addresses, except those that start with binary value
+ 000, Interface IDs are required to be 64 bits long and to be
+ constructed in Modified EUI-64 format.
+
+ Modified EUI-64 format based Interface identifiers may have global
+ scope when derived from a global token (e.g., IEEE 802 48-bit MAC or
+ IEEE EUI-64 identifiers [EUI64]) or may have local scope where a
+ global token is not available (e.g., serial links, tunnel end-points,
+ etc.) or where global tokens are undesirable (e.g., temporary tokens
+ for privacy [PRIV]).
+
+ Modified EUI-64 format interface identifiers are formed by inverting
+ the "u" bit (universal/local bit in IEEE EUI-64 terminology) when
+ forming the interface identifier from IEEE EUI-64 identifiers. In
+ the resulting Modified EUI-64 format the "u" bit is set to one (1) to
+ indicate global scope, and it is set to zero (0) to indicate local
+ scope. The first three octets in binary of an IEEE EUI-64 identifier
+ are as follows:
+
+ 0 0 0 1 1 2
+ |0 7 8 5 6 3|
+ +----+----+----+----+----+----+
+ |cccc|ccug|cccc|cccc|cccc|cccc|
+ +----+----+----+----+----+----+
+
+ written in Internet standard bit-order , where "u" is the
+ universal/local bit, "g" is the individual/group bit, and "c" are the
+ bits of the company_id. Appendix A: "Creating Modified EUI-64 format
+
+
+
+Hinden & Deering Standards Track [Page 8]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ Interface Identifiers" provides examples on the creation of Modified
+ EUI-64 format based interface identifiers.
+
+ The motivation for inverting the "u" bit when forming an interface
+ identifier is to make it easy for system administrators to hand
+ configure non-global identifiers when hardware tokens are not
+ available. This is expected to be case for serial links, tunnel end-
+ points, etc. The alternative would have been for these to be of the
+ form 0200:0:0:1, 0200:0:0:2, etc., instead of the much simpler 1, 2,
+ etc.
+
+ The use of the universal/local bit in the Modified EUI-64 format
+ identifier is to allow development of future technology that can take
+ advantage of interface identifiers with global scope.
+
+ The details of forming interface identifiers are defined in the
+ appropriate "IPv6 over <link>" specification such as "IPv6 over
+ Ethernet" [ETHER], "IPv6 over FDDI" [FDDI], etc.
+
+2.5.2 The Unspecified Address
+
+ The address 0:0:0:0:0:0:0:0 is called the unspecified address. It
+ must never be assigned to any node. It indicates the absence of an
+ address. One example of its use is in the Source Address field of
+ any IPv6 packets sent by an initializing host before it has learned
+ its own address.
+
+ The unspecified address must not be used as the destination address
+ of IPv6 packets or in IPv6 Routing Headers. An IPv6 packet with a
+ source address of unspecified must never be forwarded by an IPv6
+ router.
+
+2.5.3 The Loopback Address
+
+ The unicast address 0:0:0:0:0:0:0:1 is called the loopback address.
+ It may be used by a node to send an IPv6 packet to itself. It may
+ never be assigned to any physical interface. It is treated as
+ having link-local scope, and may be thought of as the link-local
+ unicast address of a virtual interface (typically called "the
+ loopback interface") to an imaginary link that goes nowhere.
+
+ The loopback address must not be used as the source address in IPv6
+ packets that are sent outside of a single node. An IPv6 packet with
+ a destination address of loopback must never be sent outside of a
+ single node and must never be forwarded by an IPv6 router. A packet
+ received on an interface with destination address of loopback must be
+ dropped.
+
+
+
+
+Hinden & Deering Standards Track [Page 9]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+2.5.4 Global Unicast Addresses
+
+ The general format for IPv6 global unicast addresses is as follows:
+
+ | n bits | m bits | 128-n-m bits |
+ +------------------------+-----------+----------------------------+
+ | global routing prefix | subnet ID | interface ID |
+ +------------------------+-----------+----------------------------+
+
+ where the global routing prefix is a (typically hierarchically-
+ structured) value assigned to a site (a cluster of subnets/links),
+ the subnet ID is an identifier of a link within the site, and the
+ interface ID is as defined in section 2.5.1.
+
+ All global unicast addresses other than those that start with binary
+ 000 have a 64-bit interface ID field (i.e., n + m = 64), formatted as
+ described in section 2.5.1. Global unicast addresses that start with
+ binary 000 have no such constraint on the size or structure of the
+ interface ID field.
+
+ Examples of global unicast addresses that start with binary 000 are
+ the IPv6 address with embedded IPv4 addresses described in section
+ 2.5.5 and the IPv6 address containing encoded NSAP addresses
+ specified in [NSAP]. An example of global addresses starting with a
+ binary value other than 000 (and therefore having a 64-bit interface
+ ID field) can be found in [AGGR].
+
+2.5.5 IPv6 Addresses with Embedded IPv4 Addresses
+
+ The IPv6 transition mechanisms [TRAN] include a technique for hosts
+ and routers to dynamically tunnel IPv6 packets over IPv4 routing
+ infrastructure. IPv6 nodes that use this technique are assigned
+ special IPv6 unicast addresses that carry a global IPv4 address in
+ the low-order 32 bits. This type of address is termed an "IPv4-
+ compatible IPv6 address" and has the format:
+
+ | 80 bits | 16 | 32 bits |
+ +--------------------------------------+--------------------------+
+ |0000..............................0000|0000| IPv4 address |
+ +--------------------------------------+----+---------------------+
+
+ Note: The IPv4 address used in the "IPv4-compatible IPv6 address"
+ must be a globally-unique IPv4 unicast address.
+
+ A second type of IPv6 address which holds an embedded IPv4 address is
+ also defined. This address type is used to represent the addresses
+ of IPv4 nodes as IPv6 addresses. This type of address is termed an
+ "IPv4-mapped IPv6 address" and has the format:
+
+
+
+Hinden & Deering Standards Track [Page 10]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ | 80 bits | 16 | 32 bits |
+ +--------------------------------------+--------------------------+
+ |0000..............................0000|FFFF| IPv4 address |
+ +--------------------------------------+----+---------------------+
+
+2.5.6 Local-Use IPv6 Unicast Addresses
+
+ There are two types of local-use unicast addresses defined. These
+ are Link-Local and Site-Local. The Link-Local is for use on a single
+ link and the Site-Local is for use in a single site. Link-Local
+ addresses have the following format:
+
+ | 10 |
+ | bits | 54 bits | 64 bits |
+ +----------+-------------------------+----------------------------+
+ |1111111010| 0 | interface ID |
+ +----------+-------------------------+----------------------------+
+
+ Link-Local addresses are designed to be used for addressing on a
+ single link for purposes such as automatic address configuration,
+ neighbor discovery, or when no routers are present.
+
+ Routers must not forward any packets with link-local source or
+ destination addresses to other links.
+
+ Site-Local addresses have the following format:
+
+ | 10 |
+ | bits | 54 bits | 64 bits |
+ +----------+-------------------------+----------------------------+
+ |1111111011| subnet ID | interface ID |
+ +----------+-------------------------+----------------------------+
+
+ Site-local addresses are designed to be used for addressing inside of
+ a site without the need for a global prefix. Although a subnet ID
+ may be up to 54-bits long, it is expected that globally-connected
+ sites will use the same subnet IDs for site-local and global
+ prefixes.
+
+ Routers must not forward any packets with site-local source or
+ destination addresses outside of the site.
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 11]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+2.6 Anycast Addresses
+
+ An IPv6 anycast address is an address that is assigned to more than
+ one interface (typically belonging to different nodes), with the
+ property that a packet sent to an anycast address is routed to the
+ "nearest" interface having that address, according to the routing
+ protocols' measure of distance.
+
+ Anycast addresses are allocated from the unicast address space, using
+ any of the defined unicast address formats. Thus, anycast addresses
+ are syntactically indistinguishable from unicast addresses. When a
+ unicast address is assigned to more than one interface, thus turning
+ it into an anycast address, the nodes to which the address is
+ assigned must be explicitly configured to know that it is an anycast
+ address.
+
+ For any assigned anycast address, there is a longest prefix P of that
+ address that identifies the topological region in which all
+ interfaces belonging to that anycast address reside. Within the
+ region identified by P, the anycast address must be maintained as a
+ separate entry in the routing system (commonly referred to as a "host
+ route"); outside the region identified by P, the anycast address may
+ be aggregated into the routing entry for prefix P.
+
+ Note that in the worst case, the prefix P of an anycast set may be
+ the null prefix, i.e., the members of the set may have no topological
+ locality. In that case, the anycast address must be maintained as a
+ separate routing entry throughout the entire internet, which presents
+ a severe scaling limit on how many such "global" anycast sets may be
+ supported. Therefore, it is expected that support for global anycast
+ sets may be unavailable or very restricted.
+
+ One expected use of anycast addresses is to identify the set of
+ routers belonging to an organization providing internet service.
+ Such addresses could be used as intermediate addresses in an IPv6
+ Routing header, to cause a packet to be delivered via a particular
+ service provider or sequence of service providers.
+
+ Some other possible uses are to identify the set of routers attached
+ to a particular subnet, or the set of routers providing entry into a
+ particular routing domain.
+
+ There is little experience with widespread, arbitrary use of internet
+ anycast addresses, and some known complications and hazards when
+ using them in their full generality [ANYCST]. Until more experience
+ has been gained and solutions are specified, the following
+ restrictions are imposed on IPv6 anycast addresses:
+
+
+
+
+Hinden & Deering Standards Track [Page 12]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ o An anycast address must not be used as the source address of an
+ IPv6 packet.
+
+ o An anycast address must not be assigned to an IPv6 host, that is,
+ it may be assigned to an IPv6 router only.
+
+2.6.1 Required Anycast Address
+
+ The Subnet-Router anycast address is predefined. Its format is as
+ follows:
+
+ | n bits | 128-n bits |
+ +------------------------------------------------+----------------+
+ | subnet prefix | 00000000000000 |
+ +------------------------------------------------+----------------+
+
+ The "subnet prefix" in an anycast address is the prefix which
+ identifies a specific link. This anycast address is syntactically
+ the same as a unicast address for an interface on the link with the
+ interface identifier set to zero.
+
+ Packets sent to the Subnet-Router anycast address will be delivered
+ to one router on the subnet. All routers are required to support the
+ Subnet-Router anycast addresses for the subnets to which they have
+ interfaces.
+
+ The subnet-router anycast address is intended to be used for
+ applications where a node needs to communicate with any one of the
+ set of routers.
+
+2.7 Multicast Addresses
+
+ An IPv6 multicast address is an identifier for a group of interfaces
+ (typically on different nodes). An interface may belong to any
+ number of multicast groups. Multicast addresses have the following
+ format:
+
+ | 8 | 4 | 4 | 112 bits |
+ +------ -+----+----+---------------------------------------------+
+ |11111111|flgs|scop| group ID |
+ +--------+----+----+---------------------------------------------+
+
+ binary 11111111 at the start of the address identifies the
+ address as being a multicast address.
+
+ +-+-+-+-+
+ flgs is a set of 4 flags: |0|0|0|T|
+ +-+-+-+-+
+
+
+
+Hinden & Deering Standards Track [Page 13]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ The high-order 3 flags are reserved, and must be initialized
+ to 0.
+
+ T = 0 indicates a permanently-assigned ("well-known")
+ multicast address, assigned by the Internet Assigned Number
+ Authority (IANA).
+
+ T = 1 indicates a non-permanently-assigned ("transient")
+ multicast address.
+
+ scop is a 4-bit multicast scope value used to limit the scope
+ of the multicast group. The values are:
+
+ 0 reserved
+ 1 interface-local scope
+ 2 link-local scope
+ 3 reserved
+ 4 admin-local scope
+ 5 site-local scope
+ 6 (unassigned)
+ 7 (unassigned)
+ 8 organization-local scope
+ 9 (unassigned)
+ A (unassigned)
+ B (unassigned)
+ C (unassigned)
+ D (unassigned)
+ E global scope
+ F reserved
+
+ interface-local scope spans only a single interface on a
+ node, and is useful only for loopback transmission of
+ multicast.
+
+ link-local and site-local multicast scopes span the same
+ topological regions as the corresponding unicast scopes.
+
+ admin-local scope is the smallest scope that must be
+ administratively configured, i.e., not automatically derived
+ from physical connectivity or other, non- multicast-related
+ configuration.
+
+ organization-local scope is intended to span multiple sites
+ belonging to a single organization.
+
+ scopes labeled "(unassigned)" are available for
+ administrators to define additional multicast regions.
+
+
+
+
+Hinden & Deering Standards Track [Page 14]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ group ID identifies the multicast group, either permanent or
+ transient, within the given scope.
+
+ The "meaning" of a permanently-assigned multicast address is
+ independent of the scope value. For example, if the "NTP servers
+ group" is assigned a permanent multicast address with a group ID of
+ 101 (hex), then:
+
+ FF01:0:0:0:0:0:0:101 means all NTP servers on the same interface
+ (i.e., the same node) as the sender.
+
+ FF02:0:0:0:0:0:0:101 means all NTP servers on the same link as the
+ sender.
+
+ FF05:0:0:0:0:0:0:101 means all NTP servers in the same site as the
+ sender.
+
+ FF0E:0:0:0:0:0:0:101 means all NTP servers in the internet.
+
+ Non-permanently-assigned multicast addresses are meaningful only
+ within a given scope. For example, a group identified by the non-
+ permanent, site-local multicast address FF15:0:0:0:0:0:0:101 at one
+ site bears no relationship to a group using the same address at a
+ different site, nor to a non-permanent group using the same group ID
+ with different scope, nor to a permanent group with the same group
+ ID.
+
+ Multicast addresses must not be used as source addresses in IPv6
+ packets or appear in any Routing header.
+
+ Routers must not forward any multicast packets beyond of the scope
+ indicated by the scop field in the destination multicast address.
+
+ Nodes must not originate a packet to a multicast address whose scop
+ field contains the reserved value 0; if such a packet is received, it
+ must be silently dropped. Nodes should not originate a packet to a
+ multicast address whose scop field contains the reserved value F; if
+ such a packet is sent or received, it must be treated the same as
+ packets destined to a global (scop E) multicast address.
+
+2.7.1 Pre-Defined Multicast Addresses
+
+ The following well-known multicast addresses are pre-defined. The
+ group ID's defined in this section are defined for explicit scope
+ values.
+
+ Use of these group IDs for any other scope values, with the T flag
+ equal to 0, is not allowed.
+
+
+
+Hinden & Deering Standards Track [Page 15]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ Reserved Multicast Addresses: FF00:0:0:0:0:0:0:0
+ FF01:0:0:0:0:0:0:0
+ FF02:0:0:0:0:0:0:0
+ FF03:0:0:0:0:0:0:0
+ FF04:0:0:0:0:0:0:0
+ FF05:0:0:0:0:0:0:0
+ FF06:0:0:0:0:0:0:0
+ FF07:0:0:0:0:0:0:0
+ FF08:0:0:0:0:0:0:0
+ FF09:0:0:0:0:0:0:0
+ FF0A:0:0:0:0:0:0:0
+ FF0B:0:0:0:0:0:0:0
+ FF0C:0:0:0:0:0:0:0
+ FF0D:0:0:0:0:0:0:0
+ FF0E:0:0:0:0:0:0:0
+ FF0F:0:0:0:0:0:0:0
+
+ The above multicast addresses are reserved and shall never be
+ assigned to any multicast group.
+
+ All Nodes Addresses: FF01:0:0:0:0:0:0:1
+ FF02:0:0:0:0:0:0:1
+
+ The above multicast addresses identify the group of all IPv6 nodes,
+ within scope 1 (interface-local) or 2 (link-local).
+
+ All Routers Addresses: FF01:0:0:0:0:0:0:2
+ FF02:0:0:0:0:0:0:2
+ FF05:0:0:0:0:0:0:2
+
+ The above multicast addresses identify the group of all IPv6 routers,
+ within scope 1 (interface-local), 2 (link-local), or 5 (site-local).
+
+ Solicited-Node Address: FF02:0:0:0:0:1:FFXX:XXXX
+
+ Solicited-node multicast address are computed as a function of a
+ node's unicast and anycast addresses. A solicited-node multicast
+ address is formed by taking the low-order 24 bits of an address
+ (unicast or anycast) and appending those bits to the prefix
+ FF02:0:0:0:0:1:FF00::/104 resulting in a multicast address in the
+ range
+
+ FF02:0:0:0:0:1:FF00:0000
+
+ to
+
+ FF02:0:0:0:0:1:FFFF:FFFF
+
+
+
+
+Hinden & Deering Standards Track [Page 16]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ For example, the solicited node multicast address corresponding to
+ the IPv6 address 4037::01:800:200E:8C6C is FF02::1:FF0E:8C6C. IPv6
+ addresses that differ only in the high-order bits, e.g., due to
+ multiple high-order prefixes associated with different aggregations,
+ will map to the same solicited-node address thereby, reducing the
+ number of multicast addresses a node must join.
+
+ A node is required to compute and join (on the appropriate interface)
+ the associated Solicited-Node multicast addresses for every unicast
+ and anycast address it is assigned.
+
+2.8 A Node's Required Addresses
+
+ A host is required to recognize the following addresses as
+ identifying itself:
+
+ o Its required Link-Local Address for each interface.
+ o Any additional Unicast and Anycast Addresses that have been
+ configured for the node's interfaces (manually or
+ automatically).
+ o The loopback address.
+ o The All-Nodes Multicast Addresses defined in section 2.7.1.
+ o The Solicited-Node Multicast Address for each of its unicast
+ and anycast addresses.
+ o Multicast Addresses of all other groups to which the node
+ belongs.
+
+ A router is required to recognize all addresses that a host is
+ required to recognize, plus the following addresses as identifying
+ itself:
+
+ o The Subnet-Router Anycast Addresses for all interfaces for
+ which it is configured to act as a router.
+ o All other Anycast Addresses with which the router has been
+ configured.
+ o The All-Routers Multicast Addresses defined in section 2.7.1.
+
+3. Security Considerations
+
+ IPv6 addressing documents do not have any direct impact on Internet
+ infrastructure security. Authentication of IPv6 packets is defined
+ in [AUTH].
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 17]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+4. IANA Considerations
+
+ The table and notes at http://www.isi.edu/in-
+ notes/iana/assignments/ipv6-address-space.txt should be replaced with
+ the following:
+
+ INTERNET PROTOCOL VERSION 6 ADDRESS SPACE
+
+ The initial assignment of IPv6 address space is as follows:
+
+ Allocation Prefix Fraction of
+ (binary) Address Space
+ ----------------------------------- -------- -------------
+ Unassigned (see Note 1 below) 0000 0000 1/256
+ Unassigned 0000 0001 1/256
+ Reserved for NSAP Allocation 0000 001 1/128 [RFC1888]
+ Unassigned 0000 01 1/64
+ Unassigned 0000 1 1/32
+ Unassigned 0001 1/16
+ Global Unicast 001 1/8 [RFC2374]
+ Unassigned 010 1/8
+ Unassigned 011 1/8
+ Unassigned 100 1/8
+ Unassigned 101 1/8
+ Unassigned 110 1/8
+ Unassigned 1110 1/16
+ Unassigned 1111 0 1/32
+ Unassigned 1111 10 1/64
+ Unassigned 1111 110 1/128
+ Unassigned 1111 1110 0 1/512
+ Link-Local Unicast Addresses 1111 1110 10 1/1024
+ Site-Local Unicast Addresses 1111 1110 11 1/1024
+ Multicast Addresses 1111 1111 1/256
+
+ Notes:
+
+ 1. The "unspecified address", the "loopback address", and the IPv6
+ Addresses with Embedded IPv4 Addresses are assigned out of the
+ 0000 0000 binary prefix space.
+
+ 2. For now, IANA should limit its allocation of IPv6 unicast address
+ space to the range of addresses that start with binary value 001.
+ The rest of the global unicast address space (approximately 85% of
+ the IPv6 address space) is reserved for future definition and use,
+ and is not to be assigned by IANA at this time.
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 18]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+5. References
+
+5.1 Normative References
+
+ [IPV6] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC2026] Bradner, S., "The Internet Standards Process -- Revision
+ 3", BCP 9 , RFC 2026, October 1996.
+
+5.2 Informative References
+
+ [ANYCST] Partridge, C., Mendez, T. and W. Milliken, "Host Anycasting
+ Service", RFC 1546, November 1993.
+
+ [AUTH] Kent, S. and R. Atkinson, "IP Authentication Header", RFC
+ 2402, November 1998.
+
+ [AGGR] Hinden, R., O'Dell, M. and S. Deering, "An Aggregatable
+ Global Unicast Address Format", RFC 2374, July 1998.
+
+ [CIDR] Fuller, V., Li, T., Yu, J. and K. Varadhan, "Classless
+ Inter-Domain Routing (CIDR): An Address Assignment and
+ Aggregation Strategy", RFC 1519, September 1993.
+
+ [ETHER] Crawford, M., "Transmission of IPv6 Packets over Ethernet
+ Networks", RFC 2464, December 1998.
+
+ [EUI64] IEEE, "Guidelines for 64-bit Global Identifier (EUI-64)
+ Registration Authority",
+ http://standards.ieee.org/regauth/oui/tutorials/EUI64.html,
+ March 1997.
+
+ [FDDI] Crawford, M., "Transmission of IPv6 Packets over FDDI
+ Networks", RFC 2467, December 1998.
+
+ [MASGN] Hinden, R. and S. Deering, "IPv6 Multicast Address
+ Assignments", RFC 2375, July 1998.
+
+ [NSAP] Bound, J., Carpenter, B., Harrington, D., Houldsworth, J.
+ and A. Lloyd, "OSI NSAPs and IPv6", RFC 1888, August 1996.
+
+ [PRIV] Narten, T. and R. Draves, "Privacy Extensions for Stateless
+ Address Autoconfiguration in IPv6", RFC 3041, January 2001.
+
+ [TOKEN] Crawford, M., Narten, T. and S. Thomas, "Transmission of
+ IPv6 Packets over Token Ring Networks", RFC 2470, December
+ 1998.
+
+
+
+Hinden & Deering Standards Track [Page 19]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ [TRAN] Gilligan, R. and E. Nordmark, "Transition Mechanisms for
+ IPv6 Hosts and Routers", RFC 2893, August 2000.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 20]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+APPENDIX A: Creating Modified EUI-64 format Interface Identifiers
+
+ Depending on the characteristics of a specific link or node there are
+ a number of approaches for creating Modified EUI-64 format interface
+ identifiers. This appendix describes some of these approaches.
+
+Links or Nodes with IEEE EUI-64 Identifiers
+
+ The only change needed to transform an IEEE EUI-64 identifier to an
+ interface identifier is to invert the "u" (universal/local) bit. For
+ example, a globally unique IEEE EUI-64 identifier of the form:
+
+ |0 1|1 3|3 4|4 6|
+ |0 5|6 1|2 7|8 3|
+ +----------------+----------------+----------------+----------------+
+ |cccccc0gcccccccc|ccccccccmmmmmmmm|mmmmmmmmmmmmmmmm|mmmmmmmmmmmmmmmm|
+ +----------------+----------------+----------------+----------------+
+
+ where "c" are the bits of the assigned company_id, "0" is the value
+ of the universal/local bit to indicate global scope, "g" is
+ individual/group bit, and "m" are the bits of the manufacturer-
+ selected extension identifier. The IPv6 interface identifier would
+ be of the form:
+
+ |0 1|1 3|3 4|4 6|
+ |0 5|6 1|2 7|8 3|
+ +----------------+----------------+----------------+----------------+
+ |cccccc1gcccccccc|ccccccccmmmmmmmm|mmmmmmmmmmmmmmmm|mmmmmmmmmmmmmmmm|
+ +----------------+----------------+----------------+----------------+
+
+ The only change is inverting the value of the universal/local bit.
+
+Links or Nodes with IEEE 802 48 bit MAC's
+
+ [EUI64] defines a method to create a IEEE EUI-64 identifier from an
+ IEEE 48bit MAC identifier. This is to insert two octets, with
+ hexadecimal values of 0xFF and 0xFE, in the middle of the 48 bit MAC
+ (between the company_id and vendor supplied id). For example, the 48
+ bit IEEE MAC with global scope:
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 21]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ |0 1|1 3|3 4|
+ |0 5|6 1|2 7|
+ +----------------+----------------+----------------+
+ |cccccc0gcccccccc|ccccccccmmmmmmmm|mmmmmmmmmmmmmmmm|
+ +----------------+----------------+----------------+
+
+ where "c" are the bits of the assigned company_id, "0" is the value
+ of the universal/local bit to indicate global scope, "g" is
+ individual/group bit, and "m" are the bits of the manufacturer-
+ selected extension identifier. The interface identifier would be of
+ the form:
+
+ |0 1|1 3|3 4|4 6|
+ |0 5|6 1|2 7|8 3|
+ +----------------+----------------+----------------+----------------+
+ |cccccc1gcccccccc|cccccccc11111111|11111110mmmmmmmm|mmmmmmmmmmmmmmmm|
+ +----------------+----------------+----------------+----------------+
+
+ When IEEE 802 48bit MAC addresses are available (on an interface or a
+ node), an implementation may use them to create interface identifiers
+ due to their availability and uniqueness properties.
+
+Links with Other Kinds of Identifiers
+
+ There are a number of types of links that have link-layer interface
+ identifiers other than IEEE EIU-64 or IEEE 802 48-bit MACs. Examples
+ include LocalTalk and Arcnet. The method to create an Modified EUI-
+ 64 format identifier is to take the link identifier (e.g., the
+ LocalTalk 8 bit node identifier) and zero fill it to the left. For
+ example, a LocalTalk 8 bit node identifier of hexadecimal value 0x4F
+ results in the following interface identifier:
+
+ |0 1|1 3|3 4|4 6|
+ |0 5|6 1|2 7|8 3|
+ +----------------+----------------+----------------+----------------+
+ |0000000000000000|0000000000000000|0000000000000000|0000000001001111|
+ +----------------+----------------+----------------+----------------+
+
+ Note that this results in the universal/local bit set to "0" to
+ indicate local scope.
+
+Links without Identifiers
+
+ There are a number of links that do not have any type of built-in
+ identifier. The most common of these are serial links and configured
+ tunnels. Interface identifiers must be chosen that are unique within
+ a subnet-prefix.
+
+
+
+
+Hinden & Deering Standards Track [Page 22]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ When no built-in identifier is available on a link the preferred
+ approach is to use a global interface identifier from another
+ interface or one which is assigned to the node itself. When using
+ this approach no other interface connecting the same node to the same
+ subnet-prefix may use the same identifier.
+
+ If there is no global interface identifier available for use on the
+ link the implementation needs to create a local-scope interface
+ identifier. The only requirement is that it be unique within a
+ subnet prefix. There are many possible approaches to select a
+ subnet-prefix-unique interface identifier. These include:
+
+ Manual Configuration
+ Node Serial Number
+ Other node-specific token
+
+ The subnet-prefix-unique interface identifier should be generated in
+ a manner that it does not change after a reboot of a node or if
+ interfaces are added or deleted from the node.
+
+ The selection of the appropriate algorithm is link and implementation
+ dependent. The details on forming interface identifiers are defined
+ in the appropriate "IPv6 over <link>" specification. It is strongly
+ recommended that a collision detection algorithm be implemented as
+ part of any automatic algorithm.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 23]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+APPENDIX B: Changes from RFC-2373
+
+ The following changes were made from RFC-2373 "IP Version 6
+ Addressing Architecture":
+
+ - Clarified text in section 2.2 to allow "::" to represent one or
+ more groups of 16 bits of zeros.
+ - Changed uniqueness requirement of Interface Identifiers from
+ unique on a link to unique within a subnet prefix. Also added a
+ recommendation that the same interface identifier not be assigned
+ to different machines on a link.
+ - Change site-local format to make the subnet ID field 54-bit long
+ and remove the 38-bit zero's field.
+ - Added description of multicast scop values and rules to handle the
+ reserved scop value 0.
+ - Revised sections 2.4 and 2.5.6 to simplify and clarify how
+ different address types are identified. This was done to insure
+ that implementations do not build in any knowledge about global
+ unicast format prefixes. Changes include:
+ o Removed Format Prefix (FP) terminology
+ o Revised list of address types to only include exceptions to
+ global unicast and a singe entry that identifies everything
+ else as Global Unicast.
+ o Removed list of defined prefix exceptions from section 2.5.6
+ as it is now the main part of section 2.4.
+ - Clarified text relating to EUI-64 identifiers to distinguish
+ between IPv6's "Modified EUI-64 format" identifiers and IEEE EUI-
+ 64 identifiers.
+ - Combined the sections on the Global Unicast Addresses and NSAP
+ Addresses into a single section on Global Unicast Addresses,
+ generalized the Global Unicast format, and cited [AGGR] and [NSAP]
+ as examples.
+ - Reordered sections 2.5.4 and 2.5.5.
+ - Removed section 2.7.2 Assignment of New IPv6 Multicast Addresses
+ because this is being redefined elsewhere.
+ - Added an IANA considerations section that updates the IANA IPv6
+ address allocations and documents the NSAP and AGGR allocations.
+ - Added clarification that the "IPv4-compatible IPv6 address" must
+ use global IPv4 unicast addresses.
+ - Divided references in to normative and non-normative sections.
+ - Added reference to [PRIV] in section 2.5.1
+ - Added clarification that routers must not forward multicast
+ packets outside of the scope indicated in the multicast address.
+ - Added clarification that routers must not forward packets with
+ source address of the unspecified address.
+ - Added clarification that routers must drop packets received on an
+ interface with destination address of loopback.
+ - Clarified the definition of IPv4-mapped addresses.
+
+
+
+Hinden & Deering Standards Track [Page 24]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+ - Removed the ABNF Description of Text Representations Appendix.
+ - Removed the address block reserved for IPX addresses.
+ - Multicast scope changes:
+ o Changed name of scope value 1 from "node-local" to
+ "interface-local"
+ o Defined scope value 4 as "admin-local"
+ - Corrected reference to RFC1933 and updated references.
+ - Many small changes to clarify and make the text more consistent.
+
+Authors' Addresses
+
+ Robert M. Hinden
+ Nokia
+ 313 Fairchild Drive
+ Mountain View, CA 94043
+ USA
+
+ Phone: +1 650 625-2004
+ EMail: hinden@iprg.nokia.com
+
+
+ Stephen E. Deering
+ Cisco Systems, Inc.
+ 170 West Tasman Drive
+ San Jose, CA 95134-1706
+ USA
+
+ Phone: +1 408 527-8213
+ EMail: deering@cisco.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 25]
+
+RFC 3513 IPv6 Addressing Architecture April 2003
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Deering Standards Track [Page 26]
+
diff --git a/doc/rfc/rfc3596.txt b/doc/rfc/rfc3596.txt
new file mode 100644
index 0000000..f65690c
--- /dev/null
+++ b/doc/rfc/rfc3596.txt
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+Network Working Group S. Thomson
+Request for Comments: 3596 Cisco
+Obsoletes: 3152, 1886 C. Huitema
+Category: Standards Track Microsoft
+ V. Ksinant
+ 6WIND
+ M. Souissi
+ AFNIC
+ October 2003
+
+
+ DNS Extensions to Support IP Version 6
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ This document defines the changes that need to be made to the Domain
+ Name System (DNS) to support hosts running IP version 6 (IPv6). The
+ changes include a resource record type to store an IPv6 address, a
+ domain to support lookups based on an IPv6 address, and updated
+ definitions of existing query types that return Internet addresses as
+ part of additional section processing. The extensions are designed
+ to be compatible with existing applications and, in particular, DNS
+ implementations themselves.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 2. New resource record definition and domain. . . . . . . . . . . 2
+ 2.1. AAAA record type . . . . . . . . . . . . . . . . . . . . 3
+ 2.2. AAAA data format . . . . . . . . . . . . . . . . . . . . 3
+ 2.3. AAAA query . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2.4. Textual format of AAAA records . . . . . . . . . . . . . 3
+ 2.5. IP6.ARPA domain. . . . . . . . . . . . . . . . . . . . . 3
+ 3. Modifications to existing query types. . . . . . . . . . . . . 4
+ 4. Security Considerations. . . . . . . . . . . . . . . . . . . . 4
+ 5. IANA Considerations. . . . . . . . . . . . . . . . . . . . . . 4
+
+
+
+Thomson, et al. Standards Track [Page 1]
+
+RFC 3596 DNS Extensions to Support IPv6 October 2003
+
+
+ 6. Intellectual Property Statement. . . . . . . . . . . . . . . . 4
+ Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . . . . 5
+ Appendix A: Changes from RFC 1886. . . . . . . . . . . . . . . . . 6
+ Normative References . . . . . . . . . . . . . . . . . . . . . . . 6
+ Informative References . . . . . . . . . . . . . . . . . . . . . . 6
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 7
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 8
+
+1. Introduction
+
+ Current support for the storage of Internet addresses in the Domain
+ Name System (DNS) [1,2] cannot easily be extended to support IPv6
+ addresses [3] since applications assume that address queries return
+ 32-bit IPv4 addresses only.
+
+ To support the storage of IPv6 addresses in the DNS, this document
+ defines the following extensions:
+
+ o A resource record type is defined to map a domain name to an
+ IPv6 address.
+
+ o A domain is defined to support lookups based on address.
+
+ o Existing queries that perform additional section processing to
+ locate IPv4 addresses are redefined to perform additional
+ section processing on both IPv4 and IPv6 addresses.
+
+ The changes are designed to be compatible with existing software.
+ The existing support for IPv4 addresses is retained. Transition
+ issues related to the co-existence of both IPv4 and IPv6 addresses in
+ the DNS are discussed in [4].
+
+ The IP protocol version used for querying resource records is
+ independent of the protocol version of the resource records; e.g.,
+ IPv4 transport can be used to query IPv6 records and vice versa.
+
+ This document combines RFC 1886 [5] and changes to RFC 1886 made by
+ RFC 3152 [6], obsoleting both. Changes mainly consist in replacing
+ the IP6.INT domain by IP6.ARPA as defined in RFC 3152.
+
+2. New resource record definition and domain
+
+ A record type is defined to store a host's IPv6 address. A host that
+ has more than one IPv6 address must have more than one such record.
+
+
+
+
+
+
+
+Thomson, et al. Standards Track [Page 2]
+
+RFC 3596 DNS Extensions to Support IPv6 October 2003
+
+
+2.1 AAAA record type
+
+ The AAAA resource record type is a record specific to the Internet
+ class that stores a single IPv6 address.
+
+ The IANA assigned value of the type is 28 (decimal).
+
+2.2 AAAA data format
+
+ A 128 bit IPv6 address is encoded in the data portion of an AAAA
+ resource record in network byte order (high-order byte first).
+
+2.3 AAAA query
+
+ An AAAA query for a specified domain name in the Internet class
+ returns all associated AAAA resource records in the answer section of
+ a response.
+
+ A type AAAA query does not trigger additional section processing.
+
+2.4 Textual format of AAAA records
+
+ The textual representation of the data portion of the AAAA resource
+ record used in a master database file is the textual representation
+ of an IPv6 address as defined in [3].
+
+2.5 IP6.ARPA Domain
+
+ A special domain is defined to look up a record given an IPv6
+ address. The intent of this domain is to provide a way of mapping an
+ IPv6 address to a host name, although it may be used for other
+ purposes as well. The domain is rooted at IP6.ARPA.
+
+ An IPv6 address is represented as a name in the IP6.ARPA domain by a
+ sequence of nibbles separated by dots with the suffix ".IP6.ARPA".
+ The sequence of nibbles is encoded in reverse order, i.e., the
+ low-order nibble is encoded first, followed by the next low-order
+ nibble and so on. Each nibble is represented by a hexadecimal digit.
+ For example, the reverse lookup domain name corresponding to the
+ address
+
+ 4321:0:1:2:3:4:567:89ab
+
+ would be
+
+ b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.
+ ARPA.
+
+
+
+
+Thomson, et al. Standards Track [Page 3]
+
+RFC 3596 DNS Extensions to Support IPv6 October 2003
+
+
+3. Modifications to existing query types
+
+ All existing query types that perform type A additional section
+ processing, i.e., name server (NS), location of services (SRV) and
+ mail exchange (MX) query types, must be redefined to perform both
+ type A and type AAAA additional section processing. These
+ definitions mean that a name server must add any relevant IPv4
+ addresses and any relevant IPv6 addresses available locally to the
+ additional section of a response when processing any one of the above
+ queries.
+
+4. Security Considerations
+
+ Any information obtained from the DNS must be regarded as unsafe
+ unless techniques specified in [7] or [8] are used. The definitions
+ of the AAAA record type and of the IP6.ARPA domain do not change the
+ model for use of these techniques.
+
+ So, this specification is not believed to cause any new security
+ problems, nor to solve any existing ones.
+
+5. IANA Considerations
+
+ There are no IANA assignments to be performed.
+
+6. Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+
+
+
+
+Thomson, et al. Standards Track [Page 4]
+
+RFC 3596 DNS Extensions to Support IPv6 October 2003
+
+
+Acknowledgments
+
+ Vladimir Ksinant and Mohsen Souissi would like to thank Sebastien
+ Barbin (IRISA), Luc Beloeil (France Telecom R&D), Jean-Mickael Guerin
+ (6WIND), Vincent Levigneron (AFNIC), Alain Ritoux (6WIND), Frederic
+ Roudaut (IRISA) and G6 group for their help during the RFC 1886
+ Interop tests sessions.
+
+ Many thanks to Alain Durand and Olafur Gudmundsson for their support.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Thomson, et al. Standards Track [Page 5]
+
+RFC 3596 DNS Extensions to Support IPv6 October 2003
+
+
+Appendix A: Changes from RFC 1886
+
+ The following changes were made from RFC 1886 "DNS Extensions to
+ support IP version 6":
+
+ - Replaced the "IP6.INT" domain by "IP6.ARPA".
+ - Mentioned SRV query types in section 3 "MODIFICATIONS TO
+ EXISTING QUERY TYPES"
+ - Added security considerations.
+ - Updated references :
+ * From RFC 1884 to RFC 3513 (IP Version 6 Addressing
+ Architecture).
+ * From "work in progress" to RFC 2893 (Transition Mechanisms for
+ IPv6 Hosts and Routers).
+ * Added reference to RFC 1886, RFC 3152, RFC 2535 and RFC 2845.
+ - Updated document abstract
+ - Added table of contents
+ - Added full copyright statement
+ - Added IANA considerations section
+ - Added Intellectual Property Statement
+
+Normative References
+
+ [1] Mockapetris, P., "Domain Names - Concepts and Facilities", STD
+ 13, RFC 1034, November 1987.
+
+ [2] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [3] Hinden, R. and S. Deering, "Internet Protocol Version 6 (IPv6)
+ Addressing Architecture", RFC 3513, April 2003.
+
+Informative References
+
+ [4] Gilligan, R. and E. Nordmark, "Transition Mechanisms for IPv6
+ Hosts and Routers", RFC 2893, August 2000.
+
+ [5] Thomson, S. and C. Huitema, "DNS Extensions to support IP
+ version 6", RFC 1886, December 1995.
+
+ [6] Bush, R., "Delegation of IP6.ARPA", BCP 49, RFC 3152, August
+ 2001.
+
+ [7] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999
+
+
+
+
+
+
+Thomson, et al. Standards Track [Page 6]
+
+RFC 3596 DNS Extensions to Support IPv6 October 2003
+
+
+ [8] Vixie, P., Gudmundsson, O., Eastlake, D. and B. Wellington,
+ "Secret Key Transaction Authentication for DNS (TSIG)", RFC
+ 2845, May 2000.
+
+Authors' Addresses
+
+ Susan Thomson
+ Cisco Systems
+ 499 Thornall Street, 8th floor
+ Edison, NJ 08837
+
+ Phone: +1 732-635-3086
+ EMail: sethomso@cisco.com
+
+
+ Christian Huitema
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052-6399
+
+ EMail: huitema@microsoft.com
+
+
+ Vladimir Ksinant
+ 6WIND S.A.
+ Immeuble Central Gare - Bat.C
+ 1, place Charles de Gaulle
+ 78180, Montigny-Le-Bretonneux - France
+
+ Phone: +33 1 39 30 92 36
+ EMail: vladimir.ksinant@6wind.com
+
+
+ Mohsen Souissi
+ AFNIC
+ Immeuble International
+ 2, rue Stephenson,
+ 78181, Saint-Quentin en Yvelines Cedex - France
+
+ Phone: +33 1 39 30 83 40
+ EMail: Mohsen.Souissi@nic.fr
+
+
+
+
+
+
+
+
+
+
+Thomson, et al. Standards Track [Page 7]
+
+RFC 3596 DNS Extensions to Support IPv6 October 2003
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Thomson, et al. Standards Track [Page 8]
+
diff --git a/doc/rfc/rfc3597.txt b/doc/rfc/rfc3597.txt
new file mode 100644
index 0000000..19e9a55
--- /dev/null
+++ b/doc/rfc/rfc3597.txt
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+Network Working Group A. Gustafsson
+Request for Comments: 3597 Nominum Inc.
+Category: Standards Track September 2003
+
+
+ Handling of Unknown DNS Resource Record (RR) Types
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ Extending the Domain Name System (DNS) with new Resource Record (RR)
+ types currently requires changes to name server software. This
+ document specifies the changes necessary to allow future DNS
+ implementations to handle new RR types transparently.
+
+1. Introduction
+
+ The DNS is designed to be extensible to support new services through
+ the introduction of new resource record (RR) types. In practice,
+ deploying a new RR type currently requires changes to the name server
+ software not only at the authoritative DNS server that is providing
+ the new information and the client making use of it, but also at all
+ slave servers for the zone containing it, and in some cases also at
+ caching name servers and forwarders used by the client.
+
+ Because the deployment of new server software is slow and expensive,
+ the potential of the DNS in supporting new services has never been
+ fully realized. This memo proposes changes to name servers and to
+ procedures for defining new RR types aimed at simplifying the future
+ deployment of new RR types.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC 2119].
+
+
+
+
+
+
+Gustafsson Standards Track [Page 1]
+
+RFC 3597 Handling of Unknown DNS RR Types September 2003
+
+
+2. Definition
+
+ An "RR of unknown type" is an RR whose RDATA format is not known to
+ the DNS implementation at hand, and whose type is not an assigned
+ QTYPE or Meta-TYPE as specified in [RFC 2929] (section 3.1) nor
+ within the range reserved in that section for assignment only to
+ QTYPEs and Meta-TYPEs. Such an RR cannot be converted to a type-
+ specific text format, compressed, or otherwise handled in a type-
+ specific way.
+
+ In the case of a type whose RDATA format is class specific, an RR is
+ considered to be of unknown type when the RDATA format for that
+ combination of type and class is not known.
+
+3. Transparency
+
+ To enable new RR types to be deployed without server changes, name
+ servers and resolvers MUST handle RRs of unknown type transparently.
+ That is, they must treat the RDATA section of such RRs as
+ unstructured binary data, storing and transmitting it without change
+ [RFC1123].
+
+ To ensure the correct operation of equality comparison (section 6)
+ and of the DNSSEC canonical form (section 7) when an RR type is known
+ to some but not all of the servers involved, servers MUST also
+ exactly preserve the RDATA of RRs of known type, except for changes
+ due to compression or decompression where allowed by section 4 of
+ this memo. In particular, the character case of domain names that
+ are not subject to compression MUST be preserved.
+
+4. Domain Name Compression
+
+ RRs containing compression pointers in the RDATA part cannot be
+ treated transparently, as the compression pointers are only
+ meaningful within the context of a DNS message. Transparently
+ copying the RDATA into a new DNS message would cause the compression
+ pointers to point at the corresponding location in the new message,
+ which now contains unrelated data. This would cause the compressed
+ name to be corrupted.
+
+ To avoid such corruption, servers MUST NOT compress domain names
+ embedded in the RDATA of types that are class-specific or not well-
+ known. This requirement was stated in [RFC1123] without defining the
+ term "well-known"; it is hereby specified that only the RR types
+ defined in [RFC1035] are to be considered "well-known".
+
+
+
+
+
+
+Gustafsson Standards Track [Page 2]
+
+RFC 3597 Handling of Unknown DNS RR Types September 2003
+
+
+ The specifications of a few existing RR types have explicitly allowed
+ compression contrary to this specification: [RFC2163] specified that
+ compression applies to the PX RR, and [RFC2535] allowed compression
+ in SIG RRs and NXT RRs records. Since this specification disallows
+ compression in these cases, it is an update to [RFC2163] (section 4)
+ and [RFC2535] (sections 4.1.7 and 5.2).
+
+ Receiving servers MUST decompress domain names in RRs of well-known
+ type, and SHOULD also decompress RRs of type RP, AFSDB, RT, SIG, PX,
+ NXT, NAPTR, and SRV (although the current specification of the SRV RR
+ in [RFC2782] prohibits compression, [RFC2052] mandated it, and some
+ servers following that earlier specification are still in use).
+
+ Future specifications for new RR types that contain domain names
+ within their RDATA MUST NOT allow the use of name compression for
+ those names, and SHOULD explicitly state that the embedded domain
+ names MUST NOT be compressed.
+
+ As noted in [RFC1123], the owner name of an RR is always eligible for
+ compression.
+
+5. Text Representation
+
+ In the "type" field of a master file line, an unknown RR type is
+ represented by the word "TYPE" immediately followed by the decimal RR
+ type number, with no intervening whitespace. In the "class" field,
+ an unknown class is similarly represented as the word "CLASS"
+ immediately followed by the decimal class number.
+
+ This convention allows types and classes to be distinguished from
+ each other and from TTL values, allowing the "[<TTL>] [<class>]
+ <type> <RDATA>" and "[<class>] [<TTL>] <type> <RDATA>" forms of
+ [RFC1035] to both be unambiguously parsed.
+
+ The RDATA section of an RR of unknown type is represented as a
+ sequence of white space separated words as follows:
+
+ The special token \# (a backslash immediately followed by a hash
+ sign), which identifies the RDATA as having the generic encoding
+ defined herein rather than a traditional type-specific encoding.
+
+ An unsigned decimal integer specifying the RDATA length in octets.
+
+ Zero or more words of hexadecimal data encoding the actual RDATA
+ field, each containing an even number of hexadecimal digits.
+
+ If the RDATA is of zero length, the text representation contains only
+ the \# token and the single zero representing the length.
+
+
+
+Gustafsson Standards Track [Page 3]
+
+RFC 3597 Handling of Unknown DNS RR Types September 2003
+
+
+ An implementation MAY also choose to represent some RRs of known type
+ using the above generic representations for the type, class and/or
+ RDATA, which carries the benefit of making the resulting master file
+ portable to servers where these types are unknown. Using the generic
+ representation for the RDATA of an RR of known type can also be
+ useful in the case of an RR type where the text format varies
+ depending on a version, protocol, or similar field (or several)
+ embedded in the RDATA when such a field has a value for which no text
+ format is known, e.g., a LOC RR [RFC1876] with a VERSION other than
+ 0.
+
+ Even though an RR of known type represented in the \# format is
+ effectively treated as an unknown type for the purpose of parsing the
+ RDATA text representation, all further processing by the server MUST
+ treat it as a known type and take into account any applicable type-
+ specific rules regarding compression, canonicalization, etc.
+
+ The following are examples of RRs represented in this manner,
+ illustrating various combinations of generic and type-specific
+ encodings for the different fields of the master file format:
+
+ a.example. CLASS32 TYPE731 \# 6 abcd (
+ ef 01 23 45 )
+ b.example. HS TYPE62347 \# 0
+ e.example. IN A \# 4 0A000001
+ e.example. CLASS1 TYPE1 10.0.0.2
+
+6. Equality Comparison
+
+ Certain DNS protocols, notably Dynamic Update [RFC2136], require RRs
+ to be compared for equality. Two RRs of the same unknown type are
+ considered equal when their RDATA is bitwise equal. To ensure that
+ the outcome of the comparison is identical whether the RR is known to
+ the server or not, specifications for new RR types MUST NOT specify
+ type-specific comparison rules.
+
+ This implies that embedded domain names, being included in the
+ overall bitwise comparison, are compared in a case-sensitive manner.
+
+ As a result, when a new RR type contains one or more embedded domain
+ names, it is possible to have multiple RRs owned by the same name
+ that differ only in the character case of the embedded domain
+ name(s). This is similar to the existing possibility of multiple TXT
+ records differing only in character case, and not expected to cause
+ any problems in practice.
+
+
+
+
+
+
+Gustafsson Standards Track [Page 4]
+
+RFC 3597 Handling of Unknown DNS RR Types September 2003
+
+
+7. DNSSEC Canonical Form and Ordering
+
+ DNSSEC defines a canonical form and ordering for RRs [RFC2535]
+ (section 8.1). In that canonical form, domain names embedded in the
+ RDATA are converted to lower case.
+
+ The downcasing is necessary to ensure the correctness of DNSSEC
+ signatures when case distinctions in domain names are lost due to
+ compression, but since it requires knowledge of the presence and
+ position of embedded domain names, it cannot be applied to unknown
+ types.
+
+ To ensure continued consistency of the canonical form of RR types
+ where compression is allowed, and for continued interoperability with
+ existing implementations that already implement the [RFC2535]
+ canonical form and apply it to their known RR types, the canonical
+ form remains unchanged for all RR types whose whose initial
+ publication as an RFC was prior to the initial publication of this
+ specification as an RFC (RFC 3597).
+
+ As a courtesy to implementors, it is hereby noted that the complete
+ set of such previously published RR types that contain embedded
+ domain names, and whose DNSSEC canonical form therefore involves
+ downcasing according to the DNS rules for character comparisons,
+ consists of the RR types NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+ HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, SRV,
+ DNAME, and A6.
+
+ This document specifies that for all other RR types (whether treated
+ as unknown types or treated as known types according to an RR type
+ definition RFC more recent than RFC 3597), the canonical form is such
+ that no downcasing of embedded domain names takes place, and
+ otherwise identical to the canonical form specified in [RFC2535]
+ section 8.1.
+
+ Note that the owner name is always set to lower case according to the
+ DNS rules for character comparisons, regardless of the RR type.
+
+ The DNSSEC canonical RR ordering is as specified in [RFC2535] section
+ 8.3, where the octet sequence is the canonical form as revised by
+ this specification.
+
+8. Additional Section Processing
+
+ Unknown RR types cause no additional section processing. Future RR
+ type specifications MAY specify type-specific additional section
+ processing rules, but any such processing MUST be optional as it can
+ only be performed by servers for which the RR type in case is known.
+
+
+
+Gustafsson Standards Track [Page 5]
+
+RFC 3597 Handling of Unknown DNS RR Types September 2003
+
+
+9. IANA Considerations
+
+ This document does not require any IANA actions.
+
+10. Security Considerations
+
+ This specification is not believed to cause any new security
+ problems, nor to solve any existing ones.
+
+11. Normative References
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and
+ Facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specifications", STD 13, RFC 1035, November 1987.
+
+ [RFC1123] Braden, R., Ed., "Requirements for Internet Hosts --
+ Application and Support", STD 3, RFC 1123, October 1989.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC2163] Allocchio, C., "Using the Internet DNS to Distribute
+ MIXER Conformant Global Address Mapping (MCGAM)", RFC
+ 2163, January 1998.
+
+ [RFC2929] Eastlake, D., Brunner-Williams, E. and B. Manning,
+ "Domain Name System (DNS) IANA Considerations", BCP 42,
+ RFC 2929, September 2000.
+
+12. Informative References
+
+ [RFC1876] Davis, C., Vixie, P., Goodwin, T. and I. Dickinson, "A
+ Means for Expressing Location Information in the Domain
+ Name System", RFC 1876, January 1996.
+
+ [RFC2052] Gulbrandsen, A. and P. Vixie, "A DNS RR for specifying
+ the location of services (DNS SRV)", RFC 2052, October
+ 1996.
+
+ [RFC2136] Vixie, P., Ed., Thomson, S., Rekhter, Y. and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)",
+ RFC 2136, April 1997.
+
+
+
+
+Gustafsson Standards Track [Page 6]
+
+RFC 3597 Handling of Unknown DNS RR Types September 2003
+
+
+ [RFC2782] Gulbrandsen, A., Vixie, P. and L. Esibov, "A DNS RR for
+ specifying the location of services (DNS SRV)", RFC 2782,
+ February 2000.
+
+13. Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+14. Author's Address
+
+ Andreas Gustafsson
+ Nominum, Inc.
+ 2385 Bay Rd
+ Redwood City, CA 94063
+ USA
+
+ Phone: +1 650 381 6004
+ EMail: gson@nominum.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gustafsson Standards Track [Page 7]
+
+RFC 3597 Handling of Unknown DNS RR Types September 2003
+
+
+15. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gustafsson Standards Track [Page 8]
+
diff --git a/doc/rfc/rfc3645.txt b/doc/rfc/rfc3645.txt
new file mode 100644
index 0000000..6126678
--- /dev/null
+++ b/doc/rfc/rfc3645.txt
@@ -0,0 +1,1459 @@
+
+
+
+
+
+
+Network Working Group S. Kwan
+Request for Comments: 3645 P. Garg
+Updates: 2845 J. Gilroy
+Category: Standards Track L. Esibov
+ J. Westhead
+ Microsoft Corp.
+ R. Hall
+ Lucent Technologies
+ October 2003
+
+
+ Generic Security Service Algorithm for
+ Secret Key Transaction Authentication for DNS (GSS-TSIG)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ The Secret Key Transaction Authentication for DNS (TSIG) protocol
+ provides transaction level authentication for DNS. TSIG is
+ extensible through the definition of new algorithms. This document
+ specifies an algorithm based on the Generic Security Service
+ Application Program Interface (GSS-API) (RFC2743). This document
+ updates RFC 2845.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 1]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 2. Algorithm Overview . . . . . . . . . . . . . . . . . . . . . . 3
+ 2.1. GSS Details. . . . . . . . . . . . . . . . . . . . . . . 4
+ 2.2. Modifications to the TSIG protocol (RFC 2845). . . . . . 4
+ 3. Client Protocol Details. . . . . . . . . . . . . . . . . . . . 5
+ 3.1. Negotiating Context. . . . . . . . . . . . . . . . . . . 5
+ 3.1.1. Call GSS_Init_sec_context. . . . . . . . . . . . . 6
+ 3.1.2. Send TKEY Query to Server. . . . . . . . . . . . . 8
+ 3.1.3. Receive TKEY Query-Response from Server. . . . . . 8
+ 3.2. Context Established. . . . . . . . . . . . . . . . . . . 11
+ 3.2.1. Terminating a Context. . . . . . . . . . . . . . . 11
+ 4. Server Protocol Details. . . . . . . . . . . . . . . . . . . . 12
+ 4.1. Negotiating Context. . . . . . . . . . . . . . . . . . . 12
+ 4.1.1. Receive TKEY Query from Client . . . . . . . . . . 12
+ 4.1.2. Call GSS_Accept_sec_context. . . . . . . . . . . . 12
+ 4.1.3. Send TKEY Query-Response to Client . . . . . . . . 13
+ 4.2. Context Established. . . . . . . . . . . . . . . . . . . 15
+ 4.2.1. Terminating a Context. . . . . . . . . . . . . . . 15
+ 5. Sending and Verifying Signed Messages. . . . . . . . . . . . . 15
+ 5.1. Sending a Signed Message - Call GSS_GetMIC . . . . . . . 15
+ 5.2. Verifying a Signed Message - Call GSS_VerifyMIC. . . . . 16
+ 6. Example usage of GSS-TSIG algorithm. . . . . . . . . . . . . . 18
+ 7. Security Considerations. . . . . . . . . . . . . . . . . . . . 22
+ 8. IANA Considerations. . . . . . . . . . . . . . . . . . . . . . 22
+ 9. Conformance. . . . . . . . . . . . . . . . . . . . . . . . . . 22
+ 10. Intellectual Property Statement. . . . . . . . . . . . . . . . 23
+ 11. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 23
+ 12. References . . . . . . . . . . . . . . . . . . . . . . . . . . 24
+ 12.1. Normative References. . . . . . . . . . . . . . . . . . 24
+ 12.2. Informative References. . . . . . . . . . . . . . . . . 24
+ 13. Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 25
+ 14. Full Copyright Statement . . . . . . . . . . . . . . . . . . . 26
+
+1. Introduction
+
+ The Secret Key Transaction Authentication for DNS (TSIG) [RFC2845]
+ protocol was developed to provide a lightweight authentication and
+ integrity of messages between two DNS entities, such as client and
+ server or server and server. TSIG can be used to protect dynamic
+ update messages, authenticate regular message or to off-load
+ complicated DNSSEC [RFC2535] processing from a client to a server and
+ still allow the client to be assured of the integrity of the answers.
+
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 2]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ The TSIG protocol [RFC2845] is extensible through the definition of
+ new algorithms. This document specifies an algorithm based on the
+ Generic Security Service Application Program Interface (GSS-API)
+ [RFC2743]. GSS-API is a framework that provides an abstraction of
+ security to the application protocol developer. The security
+ services offered can include authentication, integrity, and
+ confidentiality.
+
+ The GSS-API framework has several benefits:
+
+ * Mechanism and protocol independence. The underlying mechanisms
+ that realize the security services can be negotiated on the fly
+ and varied over time. For example, a client and server MAY use
+ Kerberos [RFC1964] for one transaction, whereas that same server
+ MAY use SPKM [RFC2025] with a different client.
+
+ * The protocol developer is removed from the responsibility of
+ creating and managing a security infrastructure. For example, the
+ developer does not need to create new key distribution or key
+ management systems. Instead the developer relies on the security
+ service mechanism to manage this on its behalf.
+
+ The scope of this document is limited to the description of an
+ authentication mechanism only. It does not discuss and/or propose an
+ authorization mechanism. Readers that are unfamiliar with GSS-API
+ concepts are encouraged to read the characteristics and concepts
+ section of [RFC2743] before examining this protocol in detail. It is
+ also assumed that the reader is familiar with [RFC2845], [RFC2930],
+ [RFC1034] and [RFC1035].
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT",
+ "RECOMMENDED", and "MAY" in this document are to be interpreted as
+ described in BCP 14, RFC 2119 [RFC2119].
+
+2. Algorithm Overview
+
+ In GSS, client and server interact to create a "security context".
+ The security context can be used to create and verify transaction
+ signatures on messages between the two parties. A unique security
+ context is required for each unique connection between client and
+ server.
+
+ Creating a security context involves a negotiation between client and
+ server. Once a context has been established, it has a finite
+ lifetime for which it can be used to secure messages. Thus there are
+ three states of a context associated with a connection:
+
+
+
+
+
+Kwan, et al. Standards Track [Page 3]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ +----------+
+ | |
+ V |
+ +---------------+ |
+ | Uninitialized | |
+ | | |
+ +---------------+ |
+ | |
+ V |
+ +---------------+ |
+ | Negotiating | |
+ | Context | |
+ +---------------+ |
+ | |
+ V |
+ +---------------+ |
+ | Context | |
+ | Established | |
+ +---------------+ |
+ | |
+ +----------+
+
+ Every connection begins in the uninitialized state.
+
+2.1. GSS Details
+
+ Client and server MUST be locally authenticated and have acquired
+ default credentials before using this protocol as specified in
+ Section 1.1.1 "Credentials" in RFC 2743 [RFC2743].
+
+ The GSS-TSIG algorithm consists of two stages:
+
+ I. Establish security context. The Client and Server use the
+ GSS_Init_sec_context and GSS_Accept_sec_context APIs to generate
+ the tokens that they pass to each other using [RFC2930] as a
+ transport mechanism.
+
+ II. Once the security context is established it is used to generate
+ and verify signatures using GSS_GetMIC and GSS_VerifyMIC APIs.
+ These signatures are exchanged by the Client and Server as a part
+ of the TSIG records exchanged in DNS messages sent between the
+ Client and Server, as described in [RFC2845].
+
+2.2. Modifications to the TSIG protocol (RFC 2845)
+
+ Modification to RFC 2845 allows use of TSIG through signing server's
+ response in an explicitly specified place in multi message exchange
+ between two DNS entities even if client's request wasn't signed.
+
+
+
+Kwan, et al. Standards Track [Page 4]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ Specifically, Section 4.2 of RFC 2845 MUST be modified as follows:
+
+ Replace:
+ "The server MUST not generate a signed response to an unsigned
+ request."
+
+ With:
+ "The server MUST not generate a signed response to an unsigned
+ request, except in case of response to client's unsigned TKEY
+ query if secret key is established on server side after server
+ processed client's query. Signing responses to unsigned TKEY
+ queries MUST be explicitly specified in the description of an
+ individual secret key establishment algorithm."
+
+3. Client Protocol Details
+
+ A unique context is required for each server to which the client
+ sends secure messages. A context is identified by a context handle.
+ A client maintains a mapping of servers to handles:
+
+ (target_name, key_name, context_handle)
+
+ The value key_name also identifies a context handle. The key_name is
+ the owner name of the TKEY and TSIG records sent between a client and
+ a server to indicate to each other which context MUST be used to
+ process the current request.
+
+ DNS client and server MAY use various underlying security mechanisms
+ to establish security context as described in sections 3 and 4. At
+ the same time, in order to guarantee interoperability between DNS
+ clients and servers that support GSS-TSIG it is REQUIRED that
+ security mechanism used by client enables use of Kerberos v5 (see
+ Section 9 for more information).
+
+3.1. Negotiating Context
+
+ In GSS, establishing a security context involves the passing of
+ opaque tokens between the client and the server. The client
+ generates the initial token and sends it to the server. The server
+ processes the token and if necessary, returns a subsequent token to
+ the client. The client processes this token, and so on, until the
+ negotiation is complete. The number of times the client and server
+ exchange tokens depends on the underlying security mechanism. A
+ completed negotiation results in a context handle.
+
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 5]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ The TKEY resource record [RFC2930] is used as the vehicle to transfer
+ tokens between client and server. The TKEY record is a general
+ mechanism for establishing secret keys for use with TSIG. For more
+ information, see [RFC2930].
+
+3.1.1. Call GSS_Init_sec_context
+
+ To obtain the first token to be sent to a server, a client MUST call
+ GSS_Init_sec_context API.
+
+ The following input parameters MUST be used. The outcome of the call
+ is indicated with the output values below. Consult Sections 2.2.1,
+ "GSS_Init_sec_context call", of [RFC2743] for syntax definitions.
+
+ INPUTS
+ CREDENTIAL HANDLE claimant_cred_handle = NULL (NULL specifies "use
+ default"). Client MAY instead specify some other valid
+ handle to its credentials.
+ CONTEXT HANDLE input_context_handle = 0
+ INTERNAL NAME targ_name = "DNS@<target_server_name>"
+ OBJECT IDENTIFIER mech_type = Underlying security
+ mechanism chosen by implementers. To guarantee
+ interoperability of the implementations of the GSS-TSIG
+ mechanism client MUST specify a valid underlying security
+ mechanism that enables use of Kerberos v5 (see Section 9 for
+ more information).
+ OCTET STRING input_token = NULL
+ BOOLEAN replay_det_req_flag = TRUE
+ BOOLEAN mutual_req_flag = TRUE
+ BOOLEAN deleg_req_flag = TRUE
+ BOOLEAN sequence_req_flag = TRUE
+ BOOLEAN anon_req_flag = FALSE
+ BOOLEAN integ_req_flag = TRUE
+ INTEGER lifetime_req = 0 (0 requests a default
+ value). Client MAY instead specify another upper bound for the
+ lifetime of the context to be established in seconds.
+ OCTET STRING chan_bindings = Any valid channel bindings
+ as specified in Section 1.1.6 "Channel Bindings" in [RFC2743]
+
+ OUTPUTS
+ INTEGER major_status
+ CONTEXT HANDLE output_context_handle
+ OCTET STRING output_token
+ BOOLEAN replay_det_state
+ BOOLEAN mutual_state
+ INTEGER minor_status
+ OBJECT IDENTIFIER mech_type
+ BOOLEAN deleg_state
+
+
+
+Kwan, et al. Standards Track [Page 6]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ BOOLEAN sequence_state
+ BOOLEAN anon_state
+ BOOLEAN trans_state
+ BOOLEAN prot_ready_state
+ BOOLEAN conf_avail
+ BOOLEAN integ_avail
+ INTEGER lifetime_rec
+
+ If returned major_status is set to one of the following errors:
+
+ GSS_S_DEFECTIVE_TOKEN
+ GSS_S_DEFECTIVE_CREDENTIAL
+ GSS_S_BAD_SIG (GSS_S_BAD_MIC)
+ GSS_S_NO_CRED
+ GSS_S_CREDENTIALS_EXPIRED
+ GSS_S_BAD_BINDINGS
+ GSS_S_OLD_TOKEN
+ GSS_S_DUPLICATE_TOKEN
+ GSS_S_NO_CONTEXT
+ GSS_S_BAD_NAMETYPE
+ GSS_S_BAD_NAME
+ GSS_S_BAD_MECH
+ GSS_S_FAILURE
+
+ then the client MUST abandon the algorithm and MUST NOT use the GSS-
+ TSIG algorithm to establish this security context. This document
+ does not prescribe which other mechanism could be used to establish a
+ security context. Next time when this client needs to establish
+ security context, the client MAY use GSS-TSIG algorithm.
+
+ Success values of major_status are GSS_S_CONTINUE_NEEDED and
+ GSS_S_COMPLETE. The exact success code is important during later
+ processing.
+
+ The values of replay_det_state and mutual_state indicate if the
+ security package provides replay detection and mutual authentication,
+ respectively. If returned major_status is GSS_S_COMPLETE AND one or
+ both of these values are FALSE, the client MUST abandon this
+ algorithm.
+
+ Client's behavior MAY depend on other OUTPUT parameters according to
+ the policy local to the client.
+
+ The handle output_context_handle is unique to this negotiation and is
+ stored in the client's mapping table as the context_handle that maps
+ to target_name.
+
+
+
+
+
+Kwan, et al. Standards Track [Page 7]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+3.1.2. Send TKEY Query to Server
+
+ An opaque output_token returned by GSS_Init_sec_context is
+ transmitted to the server in a query request with QTYPE=TKEY. The
+ token itself will be placed in a Key Data field of the RDATA field in
+ the TKEY resource record in the additional records section of the
+ query. The owner name of the TKEY resource record set queried for
+ and the owner name of the supplied TKEY resource record in the
+ additional records section MUST be the same. This name uniquely
+ identifies the security context to both the client and server, and
+ thus the client SHOULD use a value which is globally unique as
+ described in [RFC2930]. To achieve global uniqueness, the name MAY
+ contain a UUID/GUID [ISO11578].
+
+ TKEY Record
+ NAME = client-generated globally unique domain name string
+ (as described in [RFC2930])
+ RDATA
+ Algorithm Name = gss-tsig
+ Mode = 3 (GSS-API negotiation - per [RFC2930])
+ Key Size = size of output_token in octets
+ Key Data = output_token
+
+ The remaining fields in the TKEY RDATA, i.e., Inception, Expiration,
+ Error, Other Size and Data Fields, MUST be set according to
+ [RFC2930].
+
+ The query is transmitted to the server.
+
+ Note: if the original client call to GSS_Init_sec_context returned
+ any major_status other than GSS_S_CONTINUE_NEEDED or GSS_S_COMPLETE,
+ then the client MUST NOT send TKEY query. Client's behavior in this
+ case is described above in Section 3.1.1.
+
+3.1.3. Receive TKEY Query-Response from Server
+
+ Upon the reception of the TKEY query the DNS server MUST respond
+ according to the description in Section 4. This section specifies
+ the behavior of the client after it receives the matching response to
+ its query.
+
+ The next processing step depends on the value of major_status from
+ the most recent call that client performed to GSS_Init_sec_context:
+ either GSS_S_COMPLETE or GSS_S_CONTINUE.
+
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 8]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+3.1.3.1. Value of major_status == GSS_S_COMPLETE
+
+ If the last call to GSS_Init_sec_context yielded a major_status value
+ of GSS_S_COMPLETE and a non-NULL output_token was sent to the server,
+ then the client side component of the negotiation is complete and the
+ client is awaiting confirmation from the server.
+
+ Confirmation is in the form of a query response with RCODE=NOERROR
+ and with the last client supplied TKEY record in the answer section
+ of the query. The response MUST be signed with a TSIG record. Note
+ that the server is allowed to sign a response to unsigned client's
+ query due to modification to the RFC 2845 specified in Section 2.2
+ above. The signature in the TSIG record MUST be verified using the
+ procedure detailed in section 5, Sending and Verifying Signed
+ Messages. If the response is not signed, OR if the response is
+ signed but the signature is invalid, then an attacker has tampered
+ with the message in transit or has attempted to send the client a
+ false response. In this case, the client MAY continue waiting for a
+ response to its last TKEY query until the time period since the
+ client sent last TKEY query expires. Such a time period is specified
+ by the policy local to the client. This is a new option that allows
+ the DNS client to accept multiple answers for one query ID and select
+ one (not necessarily the first one) based on some criteria.
+
+ If the signature is verified, the context state is advanced to
+ Context Established. Proceed to section 3.2 for usage of the
+ security context.
+
+3.1.3.2. Value of major_status == GSS_S_CONTINUE_NEEDED
+
+ If the last call to GSS_Init_sec_context yielded a major_status value
+ of GSS_S_CONTINUE_NEEDED, then the negotiation is not yet complete.
+ The server will return to the client a query response with a TKEY
+ record in the Answer section. If the DNS message error is not
+ NO_ERROR or error field in the TKEY record is not 0 (i.e., no error),
+ then the client MUST abandon this negotiation sequence. The client
+ MUST delete an active context by calling GSS_Delete_sec_context
+ providing the associated context_handle. The client MAY repeat the
+ negotiation sequence starting with the uninitialized state as
+ described in section 3.1. To prevent infinite looping the number of
+ attempts to establish a security context MUST be limited to ten or
+ less.
+
+ If the DNS message error is NO_ERROR and the error field in the TKEY
+ record is 0 (i.e., no error), then the client MUST pass a token
+ specified in the Key Data field in the TKEY resource record to
+
+
+
+
+
+Kwan, et al. Standards Track [Page 9]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ GSS_Init_sec_context using the same parameters values as in previous
+ call except values for CONTEXT HANDLE input_context_handle and OCTET
+ STRING input_token as described below:
+
+ INPUTS
+ CONTEXT HANDLE input_context_handle = context_handle (this is the
+ context_handle corresponding to the key_name which is the
+ owner name of the TKEY record in the answer section in the
+ TKEY query response)
+
+ OCTET STRING input_token = token from Key field of
+ TKEY record
+
+ Depending on the following OUTPUT values of GSS_Init_sec_context
+
+ INTEGER major_status
+ OCTET STRING output_token
+
+ the client MUST take one of the following actions:
+
+ If OUTPUT major_status is set to one of the following values:
+
+ GSS_S_DEFECTIVE_TOKEN
+ GSS_S_DEFECTIVE_CREDENTIAL
+ GSS_S_BAD_SIG (GSS_S_BAD_MIC)
+ GSS_S_NO_CRED
+ GSS_S_CREDENTIALS_EXPIRED
+ GSS_S_BAD_BINDINGS
+ GSS_S_OLD_TOKEN
+ GSS_S_DUPLICATE_TOKEN
+ GSS_S_NO_CONTEXT
+ GSS_S_BAD_NAMETYPE
+ GSS_S_BAD_NAME
+ GSS_S_BAD_MECH
+ GSS_S_FAILURE
+
+ the client MUST abandon this negotiation sequence. This means that
+ the client MUST delete an active context by calling
+ GSS_Delete_sec_context providing the associated context_handle. The
+ client MAY repeat the negotiation sequence starting with the
+ uninitialized state as described in section 3.1. To prevent infinite
+ looping the number of attempts to establish a security context MUST
+ be limited to ten or less.
+
+ If OUTPUT major_status is GSS_S_CONTINUE_NEEDED OR GSS_S_COMPLETE
+ then client MUST act as described below.
+
+
+
+
+
+Kwan, et al. Standards Track [Page 10]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ If the response from the server was signed, and the OUTPUT
+ major_status is GSS_S_COMPLETE,then the signature in the TSIG record
+ MUST be verified using the procedure detailed in section 5, Sending
+ and Verifying Signed Messages. If the signature is invalid, then the
+ client MUST abandon this negotiation sequence. This means that the
+ client MUST delete an active context by calling
+ GSS_Delete_sec_context providing the associated context_handle. The
+ client MAY repeat the negotiation sequence starting with the
+ uninitialized state as described in section 3.1. To prevent infinite
+ looping the number of attempts to establish a security context MUST
+ be limited to ten or less.
+
+ If major_status is GSS_S_CONTINUE_NEEDED the negotiation is not yet
+ finished. The token output_token MUST be passed to the server in a
+ TKEY record by repeating the negotiation sequence beginning with
+ section 3.1.2. The client MUST place a limit on the number of
+ continuations in a context negotiation to prevent endless looping.
+ Such limit SHOULD NOT exceed value of 10.
+
+ If major_status is GSS_S_COMPLETE and output_token is non-NULL, the
+ client-side component of the negotiation is complete but the token
+ output_token MUST be passed to the server by repeating the
+ negotiation sequence beginning with section 3.1.2.
+
+ If major_status is GSS_S_COMPLETE and output_token is NULL, context
+ negotiation is complete. The context state is advanced to Context
+ Established. Proceed to section 3.2 for usage of the security
+ context.
+
+3.2. Context Established
+
+ When context negotiation is complete, the handle context_handle MUST
+ be used for the generation and verification of transaction
+ signatures.
+
+ The procedures for sending and receiving signed messages are
+ described in section 5, Sending and Verifying Signed Messages.
+
+3.2.1. Terminating a Context
+
+ When the client is not intended to continue using the established
+ security context, the client SHOULD delete an active context by
+ calling GSS_Delete_sec_context providing the associated
+ context_handle, AND client SHOULD delete the established context on
+ the DNS server by using TKEY RR with the Mode field set to 5, i.e.,
+ "key deletion" [RFC2930].
+
+
+
+
+
+Kwan, et al. Standards Track [Page 11]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+4. Server Protocol Details
+
+ As on the client-side, the result of a successful context negotiation
+ is a context handle used in future generation and verification of the
+ transaction signatures.
+
+ A server MAY be managing several contexts with several clients.
+ Clients identify their contexts by providing a key name in their
+ request. The server maintains a mapping of key names to handles:
+
+ (key_name, context_handle)
+
+4.1. Negotiating Context
+
+ A server MUST recognize TKEY queries as security context negotiation
+ messages.
+
+4.1.1. Receive TKEY Query from Client
+
+ Upon receiving a query with QTYPE = TKEY, the server MUST examine
+ whether the Mode and Algorithm Name fields of the TKEY record in the
+ additional records section of the message contain values of 3 and
+ gss-tsig, respectively. If they do, then the (key_name,
+ context_handle) mapping table is searched for the key_name matching
+ the owner name of the TKEY record in the additional records section
+ of the query. If the name is found in the table and the security
+ context for this name is established and not expired, then the server
+ MUST respond to the query with BADNAME error in the TKEY error field.
+ If the name is found in the table and the security context is not
+ established, the corresponding context_handle is used in subsequent
+ GSS operations. If the name is found but the security context is
+ expired, then the server deletes this security context, as described
+ in Section 4.2.1, and interprets this query as a start of new
+ security context negotiation and performs operations described in
+ Section 4.1.2 and 4.1.3. If the name is not found, then the server
+ interprets this query as a start of new security context negotiation
+ and performs operations described in Section 4.1.2 and 4.1.3.
+
+4.1.2. Call GSS_Accept_sec_context
+
+ The server performs its side of a context negotiation by calling
+ GSS_Accept_sec_context. The following input parameters MUST be used.
+ The outcome of the call is indicated with the output values below.
+ Consult Sections 2.2.2 "GSS_Accept_sec_context call" of the RFC 2743
+ [RFC2743] for syntax definitions.
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 12]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ INPUTS
+ CONTEXT HANDLE input_context_handle = 0 if new negotiation,
+ context_handle matching
+ key_name if ongoing negotiation
+ OCTET STRING input_token = token specified in the Key
+ field from TKEY RR (from Additional records Section of
+ the client's query)
+
+ CREDENTIAL HANDLE acceptor_cred_handle = NULL (NULL specifies "use
+ default"). Server MAY instead specify some other valid
+ handle to its credentials.
+ OCTET STRING chan_bindings = Any valid channel bindings
+ as specified in Section 1.1.6 "Channel Bindings" in [RFC2743]
+
+ OUTPUTS
+ INTEGER major_status
+ CONTEXT_HANDLE output_context_handle
+ OCTET STRING output_token
+ INTEGER minor_status
+ INTERNAL NAME src_name
+ OBJECT IDENTIFIER mech_type
+ BOOLEAN deleg_state
+ BOOLEAN mutual_state
+ BOOLEAN replay_det_state
+ BOOLEAN sequence_state
+ BOOLEAN anon_state
+ BOOLEAN trans_state
+ BOOLEAN prot_ready_state
+ BOOLEAN conf_avail
+ BOOLEAN integ_avail
+ INTEGER lifetime_rec
+ CONTEXT_HANDLE delegated_cred_handle
+
+ If this is the first call to GSS_Accept_sec_context in a new
+ negotiation, then output_context_handle is stored in the server's
+ key-mapping table as the context_handle that maps to the name of the
+ TKEY record.
+
+4.1.3. Send TKEY Query-Response to Client
+
+ The server MUST respond to the client with a TKEY query response with
+ RCODE = NOERROR, that contains a TKEY record in the answer section.
+
+ If OUTPUT major_status is one of the following errors the error field
+ in the TKEY record set to BADKEY.
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 13]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ GSS_S_DEFECTIVE_TOKEN
+ GSS_S_DEFECTIVE_CREDENTIAL
+ GSS_S_BAD_SIG (GSS_S_BAD_MIC)
+ GSS_S_DUPLICATE_TOKEN
+ GSS_S_OLD_TOKEN
+ GSS_S_NO_CRED
+ GSS_S_CREDENTIALS_EXPIRED
+ GSS_S_BAD_BINDINGS
+ GSS_S_NO_CONTEXT
+ GSS_S_BAD_MECH
+ GSS_S_FAILURE
+
+ If OUTPUT major_status is set to GSS_S_COMPLETE or
+ GSS_S_CONTINUE_NEEDED then server MUST act as described below.
+
+ If major_status is GSS_S_COMPLETE the server component of the
+ negotiation is finished. If output_token is non-NULL, then it MUST
+ be returned to the client in a Key Data field of the RDATA in TKEY.
+ The error field in the TKEY record is set to NOERROR. The message
+ MUST be signed with a TSIG record as described in section 5, Sending
+ and Verifying Signed Messages. Note that server is allowed to sign a
+ response to unsigned client's query due to modification to the RFC
+ 2845 specified in Section 2.2 above. The context state is advanced
+ to Context Established. Section 4.2 discusses the usage of the
+ security context.
+
+ If major_status is GSS_S_COMPLETE and output_token is NULL, then the
+ TKEY record received from the client MUST be returned in the Answer
+ section of the response. The message MUST be signed with a TSIG
+ record as described in section 5, Sending and Verifying Signed
+ Messages. Note that server is allowed to sign a response to unsigned
+ client's query due to modification to the RFC 2845 specified in
+ section 2.2 above. The context state is advanced to Context
+ Established. Section 4.2 discusses the usage of the security
+ context.
+
+ If major_status is GSS_S_CONTINUE_NEEDED, the server component of the
+ negotiation is not yet finished. The server responds to the TKEY
+ query with a standard query response, placing in the answer section a
+ TKEY record containing output_token in the Key Data RDATA field. The
+ error field in the TKEY record is set to NOERROR. The server MUST
+ limit the number of times that a given context is allowed to repeat,
+ to prevent endless looping. Such limit SHOULD NOT exceed value of
+ 10.
+
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 14]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ In all cases, except if major_status is GSS_S_COMPLETE and
+ output_token is NULL, other TKEY record fields MUST contain the
+ following values:
+
+ NAME = key_name
+ RDATA
+ Algorithm Name = gss-tsig
+ Mode = 3 (GSS-API negotiation - per [RFC2930])
+ Key Size = size of output_token in octets
+
+ The remaining fields in the TKEY RDATA, i.e., Inception, Expiration,
+ Error, Other Size and Data Fields, MUST be set according to
+ [RFC2930].
+
+4.2. Context Established
+
+ When context negotiation is complete, the handle context_handle is
+ used for the generation and verification of transaction signatures.
+ The handle is valid for a finite amount of time determined by the
+ underlying security mechanism. A server MAY unilaterally terminate a
+ context at any time (see section 4.2.1).
+
+ Server SHOULD limit the amount of memory used to cache established
+ contexts.
+
+ The procedures for sending and receiving signed messages are given in
+ section 5, Sending and Verifying Signed Messages.
+
+4.2.1. Terminating a Context
+
+ A server can terminate any established context at any time. The
+ server MAY hint to the client that the context is being deleted by
+ including a TKEY RR in a response with the Mode field set to 5, i.e.,
+ "key deletion" [RFC2930]. An active context is deleted by calling
+ GSS_Delete_sec_context providing the associated context_handle.
+
+5. Sending and Verifying Signed Messages
+
+5.1. Sending a Signed Message - Call GSS_GetMIC
+
+ The procedure for sending a signature-protected message is specified
+ in [RFC2845]. The data to be passed to the signature routine
+ includes the whole DNS message with specific TSIG variables appended.
+ For the exact format, see [RFC2845]. For this protocol, use the
+ following TSIG variable values:
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 15]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ TSIG Record
+ NAME = key_name that identifies this context
+ RDATA
+ Algorithm Name = gss-tsig
+
+ Assign the remaining fields in the TSIG RDATA appropriate values as
+ described in [RFC2845].
+
+ The signature is generated by calling GSS_GetMIC. The following
+ input parameters MUST be used. The outcome of the call is indicated
+ with the output values specified below. Consult Sections 2.3.1
+ "GSS_GetMIC call" of the RFC 2743[RFC2743] for syntax definitions.
+
+ INPUTS
+ CONTEXT HANDLE context_handle = context_handle for key_name
+ OCTET STRING message = outgoing message plus TSIG
+ variables (per [RFC2845])
+ INTEGER qop_req = 0 (0 requests a default
+ value). Caller MAY instead specify other valid value (for
+ details see Section 1.2.4 in [RFC2743])
+
+ OUTPUTS
+ INTEGER major_status
+ INTEGER minor_status
+ OCTET STRING per_msg_token
+
+ If major_status is GSS_S_COMPLETE, then signature generation
+ succeeded. The signature in per_msg_token is inserted into the
+ Signature field of the TSIG RR and the message is transmitted.
+
+ If major_status is GSS_S_CONTEXT_EXPIRED, GSS_S_CREDENTIALS_EXPIRED
+ or GSS_S_FAILURE the caller MUST delete the security context, return
+ to the uninitialized state and SHOULD negotiate a new security
+ context, as described above in Section 3.1
+
+ If major_status is GSS_S_NO_CONTEXT, the caller MUST remove the entry
+ for key_name from the (target_ name, key_name, context_handle)
+ mapping table, return to the uninitialized state and SHOULD negotiate
+ a new security context, as described above in Section 3.1
+
+ If major_status is GSS_S_BAD_QOP, the caller SHOULD repeat the
+ GSS_GetMIC call with allowed QOP value. The number of such
+ repetitions MUST be limited to prevent infinite loops.
+
+5.2. Verifying a Signed Message - Call GSS_VerifyMIC
+
+ The procedure for verifying a signature-protected message is
+ specified in [RFC2845].
+
+
+
+Kwan, et al. Standards Track [Page 16]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ The NAME of the TSIG record determines which context_handle maps to
+ the context that MUST be used to verify the signature. If the NAME
+ does not map to an established context, the server MUST send a
+ standard TSIG error response to the client indicating BADKEY in the
+ TSIG error field (as described in [RFC2845]).
+
+ For the GSS algorithm, a signature is verified by using
+ GSS_VerifyMIC:
+
+ INPUTS
+ CONTEXT HANDLE context_handle = context_handle for key_name
+ OCTET STRING message = incoming message plus TSIG
+ variables (per [RFC2845])
+ OCTET STRING per_msg_token = Signature field from TSIG RR
+
+ OUTPUTS
+ INTEGER major_status
+ INTEGER minor_status
+ INTEGER qop_state
+
+ If major_status is GSS_S_COMPLETE, the signature is authentic and the
+ message was delivered intact. Per [RFC2845], the timer values of the
+ TSIG record MUST also be valid before considering the message to be
+ authentic. The caller MUST not act on the request or response in the
+ message until these checks are verified.
+
+ When a server is processing a client request, the server MUST send a
+ standard TSIG error response to the client indicating BADKEY in the
+ TSIG error field as described in [RFC2845], if major_status is set to
+ one of the following values
+
+ GSS_S_DEFECTIVE_TOKEN
+ GSS_S_BAD_SIG (GSS_S_BAD_MIC)
+ GSS_S_DUPLICATE_TOKEN
+ GSS_S_OLD_TOKEN
+ GSS_S_UNSEQ_TOKEN
+ GSS_S_GAP_TOKEN
+ GSS_S_CONTEXT_EXPIRED
+ GSS_S_NO_CONTEXT
+ GSS_S_FAILURE
+
+ If the timer values of the TSIG record are invalid, the message MUST
+ NOT be considered authentic. If this error checking fails when a
+ server is processing a client request, the appropriate error response
+ MUST be sent to the client according to [RFC2845].
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 17]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+6. Example usage of GSS-TSIG algorithm
+
+ This Section describes an example where a Client, client.example.com,
+ and a Server, server.example.com, establish a security context
+ according to the algorithm described above.
+
+ I. Client initializes security context negotiation
+
+ To establish a security context with a server, server.example.com, the
+ Client calls GSS_Init_sec_context with the following parameters.
+ (Note that some INPUT and OUTPUT parameters not critical for this
+ algorithm are not described in this example.)
+
+ CONTEXT HANDLE input_context_handle = 0
+ INTERNAL NAME targ_name = "DNS@server.example.com"
+ OCTET STRING input_token = NULL
+ BOOLEAN replay_det_req_flag = TRUE
+ BOOLEAN mutual_req_flag = TRUE
+
+ The OUTPUTS parameters returned by GSS_Init_sec_context include
+ INTEGER major_status = GSS_S_CONTINUE_NEEDED
+ CONTEXT HANDLE output_context_handle context_handle
+ OCTET STRING output_token output_token
+ BOOLEAN replay_det_state = TRUE
+ BOOLEAN mutual_state = TRUE
+
+ Client verifies that replay_det_state and mutual_state values are
+ TRUE. Since the major_status is GSS_S_CONTINUE_NEEDED, which is a
+ success OUTPUT major_status value, client stores context_handle that
+ maps to "DNS@server.example.com" and proceeds to the next step.
+
+ II. Client sends a query with QTYPE = TKEY to server
+
+ Client sends a query with QTYPE = TKEY for a client-generated globally
+ unique domain name string, 789.client.example.com.server.example.com.
+ Query contains a TKEY record in its Additional records section with
+ the following fields. (Note that some fields not specific to this
+ algorithm are not specified.)
+
+ NAME = 789.client.example.com.server.example.com.
+ RDATA
+ Algorithm Name = gss-tsig
+ Mode = 3 (GSS-API negotiation - per [RFC2930])
+ Key Size = size of output_token in octets
+ Key Data = output_token
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 18]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ After the key_name 789.client.example.com.server.example.com.
+ is generated it is stored in the client's (target_name, key_name,
+ context_handle) mapping table.
+
+ III. Server receives a query with QTYPE = TKEY
+
+ When server receives a query with QTYPE = TKEY, the server verifies
+ that Mode and Algorithm fields in the TKEY record in the Additional
+ records section of the query are set to 3 and "gss-tsig" respectively.
+ It finds that the key_name 789.client.example.com.server.example.com.
+ is not listed in its (key_name, context_handle) mapping table.
+
+ IV. Server calls GSS_Accept_sec_context
+
+ To continue security context negotiation server calls
+ GSS_Accept_sec_context with the following parameters. (Note that
+ some INPUT and OUTPUT parameters not critical for this algorithm
+ are not described in this example.)
+
+ INPUTS
+ CONTEXT HANDLE input_context_handle = 0
+ OCTET STRING input_token = token specified in the Key
+ field from TKEY RR (from Additional
+ records section of the client's query)
+
+ The OUTPUTS parameters returned by GSS_Accept_sec_context include
+ INTEGER major_status = GSS_S_CONTINUE_NEEDED
+ CONTEXT_HANDLE output_context_handle context_handle
+ OCTET STRING output_token output_token
+
+ Server stores the mapping of the
+ 789.client.example.com.server.example.com. to OUTPUT context_handle
+ in its (key_name, context_handle) mapping table.
+
+ V. Server responds to the TKEY query
+
+ Since the major_status = GSS_S_CONTINUE_NEEDED in the last server's
+ call to GSS_Accept_sec_context, the server responds to the TKEY query
+ placing in the answer section a TKEY record containing output_token in
+ the Key Data RDATA field. The error field in the TKEY record is set
+ to 0. The RCODE in the query response is set to NOERROR.
+
+ VI. Client processes token returned by server
+
+ When the client receives the TKEY query response from the server, the
+ client calls GSS_Init_sec_context with the following parameters.
+ (Note that some INPUT and OUTPUT parameters not critical for this
+ algorithm are not described in this example.)
+
+
+
+Kwan, et al. Standards Track [Page 19]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ CONTEXT HANDLE input_context_handle = the context_handle stored
+ in the client's mapping table entry (DNS@server.example.com.,
+ 789.client.example.com.server.example.com., context_handle)
+ INTERNAL NAME targ_name = "DNS@server.example.com"
+ OCTET STRING input_token = token from Key field of TKEY
+ record from the Answer section of the server's response
+ BOOLEAN replay_det_req_flag = TRUE
+ BOOLEAN mutual_req_flag = TRUE
+
+ The OUTPUTS parameters returned by GSS_Init_sec_context include
+ INTEGER major_status = GSS_S_COMPLETE
+ CONTEXT HANDLE output_context_handle = context_handle
+ OCTET STRING output_token = output_token
+ BOOLEAN replay_det_state = TRUE
+ BOOLEAN mutual_state = TRUE
+
+ Since the major_status is set to GSS_S_COMPLETE the client side
+ security context is established, but since the output_token is not
+ NULL client MUST send a TKEY query to the server as described below.
+
+ VII. Client sends a query with QTYPE = TKEY to server
+
+ Client sends to the server a TKEY query for the
+ 789.client.example.com.server.example.com. name. Query contains a
+ TKEY record in its Additional records section with the following
+ fields. (Note that some INPUT and OUTPUT parameters not critical to
+ this algorithm are not described in this example.)
+
+ NAME = 789.client.example.com.server.example.com.
+ RDATA
+ Algorithm Name = gss-tsig
+ Mode = 3 (GSS-API negotiation - per [RFC2930])
+ Key Size = size of output_token in octets
+ Key Data = output_token
+
+ VIII. Server receives a TKEY query
+
+ When the server receives a TKEY query, the server verifies that Mode
+ and Algorithm fields in the TKEY record in the Additional records
+ section of the query are set to 3 and gss-tsig, respectively. It
+ finds that the key_name 789.client.example.com.server.example.com. is
+ listed in its (key_name, context_handle) mapping table.
+
+
+
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 20]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ IX. Server calls GSS_Accept_sec_context
+
+ To continue security context negotiation server calls
+ GSS_Accept_sec_context with the following parameters (Note that some
+ INPUT and OUTPUT parameters not critical for this algorithm are not
+ described in this example)
+
+ INPUTS
+ CONTEXT HANDLE input_context_handle = context_handle from the
+ (789.client.example.com.server.example.com., context_handle)
+ entry in the server's mapping table
+ OCTET STRING input_token = token specified in the Key
+ field of TKEY RR (from Additional records Section of
+ the client's query)
+
+ The OUTPUTS parameters returned by GSS_Accept_sec_context include
+ INTEGER major_status = GSS_S_COMPLETE
+ CONTEXT_HANDLE output_context_handle = context_handle
+ OCTET STRING output_token = NULL
+
+ Since major_status = GSS_S_COMPLETE, the security context on the
+ server side is established, but the server still needs to respond to
+ the client's TKEY query, as described below. The security context
+ state is advanced to Context Established.
+
+ X. Server responds to the TKEY query
+
+ Since the major_status = GSS_S_COMPLETE in the last server's call to
+ GSS_Accept_sec_context and the output_token is NULL, the server
+ responds to the TKEY query placing in the answer section a TKEY record
+ that was sent by the client in the Additional records section of the
+ client's latest TKEY query. In addition, this server places a
+ TSIG record in additional records section of its response. Server
+ calls GSS_GetMIC to generate a signature to include it in the TSIG
+ record. The server specifies the following GSS_GetMIC INPUT
+ parameters:
+
+ CONTEXT HANDLE context_handle = context_handle from the
+ (789.client.example.com.server.example.com., context_handle)
+ entry in the server's mapping table
+ OCTET STRING message = outgoing message plus TSIG
+ variables (as described in [RFC2845])
+
+ The OUTPUTS parameters returned by GSS_GetMIC include
+ INTEGER major_status = GSS_S_COMPLETE
+ OCTET STRING per_msg_token
+
+ Signature field in the TSIG record is set to per_msg_token.
+
+
+
+Kwan, et al. Standards Track [Page 21]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ XI. Client processes token returned by server
+
+ Client receives the TKEY query response from the server. Since the
+ major_status was GSS_S_COMPLETE in the last client's call to
+ GSS_Init_sec_context, the client verifies that the server's response
+ is signed. To validate the signature, the client calls
+ GSS_VerifyMIC with the following parameters:
+
+ INPUTS
+ CONTEXT HANDLE context_handle = context_handle for
+ 789.client.example.com.server.example.com. key_name
+ OCTET STRING message = incoming message plus TSIG
+ variables (as described in [RFC2845])
+ OCTET STRING per_msg_token = Signature field from TSIG RR
+ included in the server's query response
+
+ Since the OUTPUTS parameter major_status = GSS_S_COMPLETE, the
+ signature is validated, security negotiation is complete and the
+ security context state is advanced to Context Established. These
+ client and server will use the established security context to sign
+ and validate the signatures when they exchange packets with each
+ other until the context expires.
+
+7. Security Considerations
+
+ This document describes a protocol for DNS security using GSS-API.
+ The security provided by this protocol is only as effective as the
+ security provided by the underlying GSS mechanisms.
+
+ All the security considerations from RFC 2845, RFC 2930 and RFC 2743
+ apply to the protocol described in this document.
+
+8. IANA Considerations
+
+ The IANA has reserved the TSIG Algorithm name gss-tsig for the use in
+ the Algorithm fields of TKEY and TSIG resource records. This
+ Algorithm name refers to the algorithm described in this document.
+ The requirement to have this name registered with IANA is specified
+ in RFC 2845.
+
+9. Conformance
+
+ The GSS API using SPNEGO [RFC2478] provides maximum flexibility to
+ choose the underlying security mechanisms that enables security
+ context negotiation. GSS API using SPNEGO [RFC2478] enables client
+ and server to negotiate and choose such underlying security
+ mechanisms on the fly. To support such flexibility, DNS clients and
+ servers SHOULD specify SPNEGO mech_type in their GSS API calls. At
+
+
+
+Kwan, et al. Standards Track [Page 22]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+ the same time, in order to guarantee interoperability between DNS
+ clients and servers that support GSS-TSIG it is required that
+
+ - DNS servers specify SPNEGO mech_type
+ - GSS APIs called by DNS client support Kerberos v5
+ - GSS APIs called by DNS server support SPNEGO [RFC2478] and
+ Kerberos v5.
+
+ In addition to these, GSS APIs used by DNS client and server MAY also
+ support other underlying security mechanisms.
+
+10. Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+11. Acknowledgements
+
+ The authors of this document would like to thank the following people
+ for their contribution to this specification: Chuck Chan, Mike
+ Swift, Ram Viswanathan, Olafur Gudmundsson, Donald E. Eastlake, 3rd
+ and Erik Nordmark.
+
+
+
+
+
+
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 23]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+12. References
+
+12.1. Normative References
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2478] Baize, E. and D. Pinkas, "The Simple and Protected GSS-API
+ Negotiation Mechanism", RFC 2478, December 1998.
+
+ [RFC2743] Linn, J., "Generic Security Service Application Program
+ Interface, Version 2 , Update 1", RFC 2743, January 2000.
+
+ [RFC2845] Vixie, P., Gudmundsson, O., Eastlake 3rd, D. and B.
+ Wellington, "Secret Key Transaction Authentication for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+ [RFC2930] Eastlake 3rd, D., "Secret Key Establishment for DNS (TKEY
+ RR)", RFC 2930, September 2000.
+
+12.2. Informative References
+
+
+ [ISO11578] "Information technology", "Open Systems Interconnection",
+ "Remote Procedure Call", ISO/IEC 11578:1996,
+ http://www.iso.ch/cate/d2229.html.
+
+ [RFC1034] Mockapetris, P., "Domain Names - Concepts and Facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1034, November 1987.
+
+ [RFC1964] Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC
+ 1964, June 1996.
+
+ [RFC2025] Adams, C., "The Simple Public-Key GSS-API Mechanism
+ (SPKM)", RFC 2025, October 1996.
+
+ [RFC2137] Eastlake 3rd, D., "Secure Domain Name System Dynamic
+ Update", RFC 2137, April 1997.
+
+ [RFC2535] Eastlake 3rd, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 24]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+13. Authors' Addresses
+
+ Stuart Kwan
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+ USA
+ EMail: skwan@microsoft.com
+
+ Praerit Garg
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+ USA
+ EMail: praeritg@microsoft.com
+
+ James Gilroy
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+ USA
+ EMail: jamesg@microsoft.com
+
+ Levon Esibov
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+ USA
+ EMail: levone@microsoft.com
+
+ Randy Hall
+ Lucent Technologies
+ 400 Lapp Road
+ Malvern PA 19355
+ USA
+ EMail: randyhall@lucent.com
+
+ Jeff Westhead
+ Microsoft Corporation
+ One Microsoft Way
+ Redmond, WA 98052
+ USA
+ EMail: jwesth@microsoft.com
+
+
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 25]
+
+RFC 3645 GSS-TSIG October 2003
+
+
+14. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kwan, et al. Standards Track [Page 26]
+
diff --git a/doc/rfc/rfc3655.txt b/doc/rfc/rfc3655.txt
new file mode 100644
index 0000000..13e586b
--- /dev/null
+++ b/doc/rfc/rfc3655.txt
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+Network Working Group B. Wellington
+Request for Comments: 3655 O. Gudmundsson
+Updates: 2535 November 2003
+Category: Standards Track
+
+
+ Redefinition of DNS Authenticated Data (AD) bit
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ This document alters the specification defined in RFC 2535. Based on
+ implementation experience, the Authenticated Data (AD) bit in the DNS
+ header is not useful. This document redefines the AD bit such that
+ it is only set if all answers or records proving that no answers
+ exist in the response has been cryptographically verified or
+ otherwise meets the server's local security policy.
+
+1. Introduction
+
+ Familiarity with the DNS system [RFC1035] and DNS security extensions
+ [RFC2535] is helpful but not necessary.
+
+ As specified in RFC 2535 (section 6.1), the AD (Authenticated Data)
+ bit indicates in a response that all data included in the answer and
+ authority sections of the response have been authenticated by the
+ server according to the policies of that server. This is not
+ especially useful in practice, since a conformant server SHOULD never
+ reply with data that failed its security policy.
+
+ This document redefines the AD bit such that it is only set if all
+ data in the response has been cryptographically verified or otherwise
+ meets the server's local security policy. Thus, neither a response
+ containing properly delegated insecure data, nor a server configured
+ without DNSSEC keys, will have the AD set. As before, data that
+ failed to verify will not be returned. An application running on a
+ host that has a trust relationship with the server performing the
+
+
+
+Wellington & Gudmundsson Standards Track [Page 1]
+
+RFC 3655 Redefinition of DNS AD bit November 2003
+
+
+ recursive query can now use the value of the AD bit to determine
+ whether the data is secure.
+
+1.1. Motivation
+
+ A full DNSSEC capable resolver called directly from an application
+ can return to the application the security status of the RRsets in
+ the answer. However, most applications use a limited stub resolver
+ that relies on an external recursive name server which incorporates a
+ full resolver. The recursive nameserver can use the AD bit in a
+ response to indicate the security status of the data in the answer,
+ and the local resolver can pass this information to the application.
+ The application in this context can be either a human using a DNS
+ tool or a software application.
+
+ The AD bit SHOULD be used by the local resolver if and only if it has
+ been explicitly configured to trust the remote resolver. The AD bit
+ SHOULD be ignored when the recursive name server is not trusted.
+
+ An alternate solution would be to embed a full DNSSEC resolver into
+ every application, but this has several disadvantages.
+
+ - DNSSEC validation is both CPU and network intensive, and caching
+ SHOULD be used whenever possible.
+
+ - DNSSEC requires non-trivial configuration - the root key must be
+ configured, as well as keys for any "islands of security" that
+ will exist until DNSSEC is fully deployed. The number of
+ configuration points should be minimized.
+
+1.2. Requirements
+
+ The key words "MAY", "MAY NOT" "MUST", "MUST NOT", "SHOULD", "SHOULD
+ NOT", "RECOMMENDED", in this document are to be interpreted as
+ described in BCP 14, RFC 2119 [RFC2119].
+
+1.3. Updated documents and sections
+
+ The definition of the AD bit in RFC 2535, Section 6.1, is changed.
+
+2. Setting of AD bit
+
+ The presence of the CD (Checking Disabled) bit in a query does not
+ affect the setting of the AD bit in the response. If the CD bit is
+ set, the server will not perform checking, but SHOULD still set the
+ AD bit if the data has already been cryptographically verified or
+
+
+
+
+
+Wellington & Gudmundsson Standards Track [Page 2]
+
+RFC 3655 Redefinition of DNS AD bit November 2003
+
+
+ complies with local policy. The AD bit MUST only be set if DNSSEC
+ records have been requested via the DO bit [RFC3225] and relevant SIG
+ records are returned.
+
+2.1. Setting of AD bit by recursive servers
+
+ Section 6.1 of RFC 2535 says:
+
+ "The AD bit MUST NOT be set on a response unless all of the RRs in
+ the answer and authority sections of the response are either
+ Authenticated or Insecure."
+
+ The replacement text reads:
+
+ "The AD bit MUST NOT be set on a response unless all of the RRsets in
+ the answer and authority sections of the response are Authenticated."
+
+ "The AD bit SHOULD be set if and only if all RRs in the answer
+ section and any relevant negative response RRs in the authority
+ section are Authenticated."
+
+ A recursive DNS server following this modified specification will
+ only set the AD bit when it has cryptographically verified the data
+ in the answer.
+
+2.2. Setting of AD bit by authoritative servers
+
+ A primary server for a secure zone MAY have the policy of treating
+ authoritative secure zones as Authenticated. Secondary servers MAY
+ have the same policy, but SHOULD NOT consider zone data Authenticated
+ unless the zone was transferred securely and/or the data was
+ verified. An authoritative server MUST only set the AD bit for
+ authoritative answers from a secure zone if it has been explicitly
+ configured to do so. The default for this behavior SHOULD be off.
+
+ Note that having the AD bit clear on an authoritative answer is
+ normal and expected behavior.
+
+2.2.1. Justification for setting AD bit w/o verifying data
+
+ The setting of the AD bit by authoritative servers affects only the
+ small set of resolvers that are configured to directly query and
+ trust authoritative servers. This only affects servers that function
+ as both recursive and authoritative. Iterative resolvers SHOULD
+ ignore the AD bit.
+
+ The cost of verifying all signatures on load by an authoritative
+ server can be high and increases the delay before it can begin
+
+
+
+Wellington & Gudmundsson Standards Track [Page 3]
+
+RFC 3655 Redefinition of DNS AD bit November 2003
+
+
+ answering queries. Verifying signatures at query time is also
+ expensive and could lead to resolvers timing out on many queries
+ after the server reloads zones.
+
+ Organizations requiring that all DNS responses contain
+ cryptographically verified data will need to separate the
+ authoritative name server and signature verification functions, since
+ name servers are not required to validate signatures of data for
+ which they are authoritative.
+
+3. Interpretation of the AD bit
+
+ A response containing data marked Insecure in the answer or authority
+ section MUST never have the AD bit set. In this case, the resolver
+ SHOULD treat the data as Insecure whether or not SIG records are
+ present.
+
+ A resolver MUST NOT blindly trust the AD bit unless it communicates
+ with a recursive nameserver over a secure transport mechanism or
+ using a message authentication such as TSIG [RFC2845] or SIG(0)
+ [RFC2931] and is explicitly configured to trust this recursive name
+ server.
+
+4. Applicability statement
+
+ The AD bit is intended to allow the transmission of the indication
+ that a resolver has verified the DNSSEC signatures accompanying the
+ records in the Answer and Authority section. The AD bit MUST only be
+ trusted when the end consumer of the DNS data has confidence that the
+ intermediary resolver setting the AD bit is trustworthy. This can
+ only be accomplished via an out of band mechanism such as:
+
+ - Fiat: An organization that can dictate whether it is OK to trust
+ certain DNS servers.
+
+ - Personal: Because of a personal relationship or the reputation of
+ a recursive nameserver operator, a DNS consumer can decide to
+ trust that recursive nameserver.
+
+ - Knowledge: If a recursive nameserver operator posts the configured
+ policy of a recursive nameserver, a consumer can decide that
+ recursive nameserver is trustworthy.
+
+ In the absence of one or more of these factors AD bit from a
+ recursive name server SHOULD NOT be trusted. For example, home users
+ frequently depend on their ISP to provide recursive DNS service; it
+
+
+
+
+
+Wellington & Gudmundsson Standards Track [Page 4]
+
+RFC 3655 Redefinition of DNS AD bit November 2003
+
+
+ is not advisable to trust these recursive nameservers. A
+ roaming/traveling host SHOULD not use recursive DNS servers offered
+ by DHCP when looking up information where security status matters.
+
+ In the latter two cases, the end consumer must also completely trust
+ the path to the trusted recursive name servers, or a secure transport
+ must be employed to protect the traffic.
+
+ When faced with a situation where there are no satisfactory recursive
+ nameservers available, running one locally is RECOMMENDED. This has
+ the advantage that it can be trusted, and the AD bit can still be
+ used to allow applications to use stub resolvers.
+
+5. Security Considerations
+
+ This document redefines a bit in the DNS header. If a resolver
+ trusts the value of the AD bit, it must be sure that the responder is
+ using the updated definition, which is any DNS server/resolver
+ supporting the DO bit [RFC3225].
+
+ Authoritative servers can be explicitly configured to set the AD bit
+ on answers without doing cryptographic checks. This behavior MUST be
+ off by default. The only affected resolvers are those that directly
+ query and trust the authoritative server, and this functionality
+ SHOULD only be used on servers that act both as authoritative and
+ recursive name servers.
+
+ Resolvers (full or stub) that blindly trust the AD bit without
+ knowing the security policy of the server generating the answer can
+ not be considered security aware.
+
+ A resolver MUST NOT blindly trust the AD bit unless it communicates
+ such as IPsec, or using message authentication such as TSIG [RFC2845]
+ or SIG(0) [RFC2931]. In addition, the resolver must have been
+ explicitly configured to trust this recursive name server.
+
+6. IANA Considerations
+
+ None.
+
+7. Internationalization Considerations
+
+ None. This document does not change any textual data in any
+ protocol.
+
+
+
+
+
+
+
+Wellington & Gudmundsson Standards Track [Page 5]
+
+RFC 3655 Redefinition of DNS AD bit November 2003
+
+
+8. Intellectual Property Rights Notice
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+9. Acknowledgments
+
+ The following people have provided input on this document: Robert
+ Elz, Andreas Gustafsson, Bob Halley, Steven Jacob, Erik Nordmark,
+ Edward Lewis, Jakob Schlyter, Roy Arends, Ted Lindgreen.
+
+10. Normative References
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [RFC2845] Vixie, P., Gudmundsson, O., Eastlake 3rd, D. and B.
+ Wellington, "Secret Key Transaction Authentication for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+ [RFC2931] Eastlake, D., "DNS Request and Transaction Signatures
+ (SIG(0))", RFC 2931, September 2000.
+
+ [RFC3225] Conrad, D., "Indicating Resolver Support of DNSSEC", RFC
+ 3225, December 2001.
+
+
+
+Wellington & Gudmundsson Standards Track [Page 6]
+
+RFC 3655 Redefinition of DNS AD bit November 2003
+
+
+11. Authors' Addresses
+
+ Brian Wellington
+ Nominum Inc.
+ 2385 Bay Road
+ Redwood City, CA, 94063
+ USA
+
+ EMail: Brian.Wellington@nominum.com
+
+
+ Olafur Gudmundsson
+ 3821 Village Park Drive
+ Chevy Chase, MD, 20815
+ USA
+
+ EMail: ogud@ogud.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wellington & Gudmundsson Standards Track [Page 7]
+
+RFC 3655 Redefinition of DNS AD bit November 2003
+
+
+12. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wellington & Gudmundsson Standards Track [Page 8]
+
diff --git a/doc/rfc/rfc3658.txt b/doc/rfc/rfc3658.txt
new file mode 100644
index 0000000..88cfb5a
--- /dev/null
+++ b/doc/rfc/rfc3658.txt
@@ -0,0 +1,1067 @@
+
+
+
+
+
+
+Network Working Group O. Gudmundsson
+Request for Comments: 3658 December 2003
+Updates: 3090, 3008, 2535, 1035
+Category: Standards Track
+
+
+ Delegation Signer (DS) Resource Record (RR)
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+Abstract
+
+ The delegation signer (DS) resource record (RR) is inserted at a zone
+ cut (i.e., a delegation point) to indicate that the delegated zone is
+ digitally signed and that the delegated zone recognizes the indicated
+ key as a valid zone key for the delegated zone. The DS RR is a
+ modification to the DNS Security Extensions definition, motivated by
+ operational considerations. The intent is to use this resource
+ record as an explicit statement about the delegation, rather than
+ relying on inference.
+
+ This document defines the DS RR, gives examples of how it is used and
+ describes the implications on resolvers. This change is not
+ backwards compatible with RFC 2535. This document updates RFC 1035,
+ RFC 2535, RFC 3008 and RFC 3090.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 1]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+Table of Contents
+
+ 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.2. Reserved Words. . . . . . . . . . . . . . . . . . . . . 4
+ 2. Specification of the Delegation key Signer. . . . . . . . . . 4
+ 2.1. Delegation Signer Record Model. . . . . . . . . . . . . 4
+ 2.2. Protocol Change . . . . . . . . . . . . . . . . . . . . 5
+ 2.2.1. RFC 2535 2.3.4 and 3.4: Special Considerations
+ at Delegation Points . . . . . . . . . . . . . 6
+ 2.2.1.1. Special processing for DS queries. . . 6
+ 2.2.1.2. Special processing when child and an
+ ancestor share nameserver. . . . . . . 7
+ 2.2.1.3. Modification on use of KEY RR in the
+ construction of Responses. . . . . . . 8
+ 2.2.2. Signer's Name (replaces RFC3008 section 2.7). . 9
+ 2.2.3. Changes to RFC 3090 . . . . . . . . . . . . . . 9
+ 2.2.3.1. RFC 3090: Updates to section 1:
+ Introduction . . . . . . . . . . . . . 9
+ 2.2.3.2. RFC 3090 section 2.1: Globally
+ Secured. . . . . . . . . . . . . . . . 10
+ 2.2.3.3. RFC 3090 section 3: Experimental
+ Status . . . . . . . . . . . . . . . . 10
+ 2.2.4. NULL KEY elimination. . . . . . . . . . . . . . 10
+ 2.3. Comments on Protocol Changes. . . . . . . . . . . . . . 10
+ 2.4. Wire Format of the DS record. . . . . . . . . . . . . . 11
+ 2.4.1. Justifications for Fields . . . . . . . . . . . 12
+ 2.5. Presentation Format of the DS Record. . . . . . . . . . 12
+ 2.6. Transition Issues for Installed Base. . . . . . . . . . 12
+ 2.6.1. Backwards compatibility with RFC 2535 and
+ RFC 1035. . . . . . . . . . . . . . . . . . . . 12
+ 2.7. KEY and corresponding DS record example . . . . . . . . 13
+ 3. Resolver. . . . . . . . . . . . . . . . . . . . . . . . . . . 14
+ 3.1. DS Example" . . . . . . . . . . . . . . . . . . . . . . 14
+ 3.2. Resolver Cost Estimates for DS Records" . . . . . . . . 15
+ 4. Security Considerations . . . . . . . . . . . . . . . . . . . 15
+ 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 16
+ 6. Intellectual Property Statement . . . . . . . . . . . . . . . 16
+ 7. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 17
+ 8. References. . . . . . . . . . . . . . . . . . . . . . . . . . 17
+ 8.1. Normative References. . . . . . . . . . . . . . . . . . 17
+ 8.2. Informational References. . . . . . . . . . . . . . . . 17
+ 9. Author's Address. . . . . . . . . . . . . . . . . . . . . . . 18
+ 10. Full Copyright Statement. . . . . . . . . . . . . . . . . . . 19
+
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 2]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+1. Introduction
+
+ Familiarity with the DNS system [RFC1035], DNS security extensions
+ [RFC2535], and DNSSEC terminology [RFC3090] is important.
+
+ Experience shows that when the same data can reside in two
+ administratively different DNS zones, the data frequently gets out of
+ sync. The presence of an NS RRset in a zone anywhere other than at
+ the apex indicates a zone cut or delegation. The RDATA of the NS
+ RRset specifies the authoritative nameservers for the delegated or
+ "child" zone. Based on actual measurements, 10-30% of all
+ delegations on the Internet have differing NS RRsets at parent and
+ child. There are a number of reasons for this, including a lack of
+ communication between parent and child and bogus name servers being
+ listed to meet registry requirements.
+
+ DNSSEC [RFC2535, RFC3008, RFC3090] specifies that a child zone needs
+ to have its KEY RRset signed by its parent to create a verifiable
+ chain of KEYs. There has been some debate on where the signed KEY
+ RRset should reside, whether at the child [RFC2535] or at the parent.
+ If the KEY RRset resides at the child, maintaining the signed KEY
+ RRset in the child requires frequent two-way communication between
+ the two parties. First, the child transmits the KEY RRset to the
+ parent and then the parent sends the signature(s) to the child.
+ Storing the KEY RRset at the parent was thought to simplify the
+ communication.
+
+ DNSSEC [RFC2535] requires that the parent store a NULL KEY record for
+ an unsecure child zone to indicate that the child is unsecure. A
+ NULL KEY record is a waste: an entire signed RRset is used to
+ communicate effectively one bit of information - that the child is
+ unsecure. Chasing down NULL KEY RRsets complicates the resolution
+ process in many cases, because nameservers for both parent and child
+ need to be queried for the KEY RRset if the child nameserver does not
+ return it. Storing the KEY RRset only in the parent zone simplifies
+ this and would allow the elimination of the NULL KEY RRsets entirely.
+ For large delegation zones, the cost of NULL keys is a significant
+ barrier to deployment.
+
+ Prior to the restrictions imposed by RFC 3445 [RFC3445], another
+ implication of the DNSSEC key model is that the KEY record could be
+ used to store public keys for other protocols in addition to DNSSEC
+ keys. There are a number of potential problems with this, including:
+
+ 1. The KEY RRset can become quite large if many applications and
+ protocols store their keys at the zone apex. Possible protocols
+ are IPSEC, HTTP, SMTP, SSH and others that use public key
+ cryptography.
+
+
+
+Gudmundsson Standards Track [Page 3]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+ 2. The KEY RRset may require frequent updates.
+
+ 3. The probability of compromised or lost keys, which trigger
+ emergency key roll-over procedures, increases.
+
+ 4. The parent may refuse to sign KEY RRsets with non-DNSSEC zone
+ keys.
+
+ 5. The parent may not meet the child's expectations of turnaround
+ time for resigning the KEY RRset.
+
+ Given these reasons, SIG@parent isn't any better than SIG/KEY@Child.
+
+1.2. Reserved Words
+
+ The key words "MAY", "MAY NOT", "MUST", "MUST NOT", "REQUIRED",
+ "RECOMMENDED", "SHOULD", and "SHOULD NOT" in this document are to be
+ interpreted as described in BCP 14, RFC 2119 [RFC2119].
+
+2. Specification of the Delegation key Signer
+
+ This section defines the Delegation Signer (DS) RR type (type code
+ 43) and the changes to DNS to accommodate it.
+
+2.1. Delegation Signer Record Model
+
+ This document presents a replacement for the DNSSEC KEY record chain
+ of trust [RFC2535] that uses a new RR that resides only at the
+ parent. This record identifies the key(s) that the child uses to
+ self-sign its own KEY RRset.
+
+ Even though DS identifies two roles for KEYs, Key Signing Key (KSK)
+ and Zone Signing Key (ZSK), there is no requirement that zone uses
+ two different keys for these roles. It is expected that many small
+ zones will only use one key, while larger zones will be more likely
+ to use multiple keys.
+
+ The chain of trust is now established by verifying the parent KEY
+ RRset, the DS RRset from the parent and the KEY RRset at the child.
+ This is cryptographically equivalent to using just KEY records.
+
+ Communication between the parent and child is greatly reduced, since
+ the child only needs to notify the parent about changes in keys that
+ sign its apex KEY RRset. The parent is ignorant of all other keys in
+ the child's apex KEY RRset. Furthermore, the child maintains full
+ control over the apex KEY RRset and its content. The child can
+ maintain any policies regarding its KEY usage for DNSSEC with minimal
+ impact on the parent. Thus, if the child wants to have frequent key
+
+
+
+Gudmundsson Standards Track [Page 4]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+ roll-over for its DNS zone keys, the parent does not need to be aware
+ of it. The child can use one key to sign only its apex KEY RRset and
+ a different key to sign the other RRsets in the zone.
+
+ This model fits well with a slow roll out of DNSSEC and the islands
+ of security model. In this model, someone who trusts "good.example."
+ can preconfigure a key from "good.example." as a trusted key, and
+ from then on trusts any data signed by that key or that has a chain
+ of trust to that key. If "example." starts advertising DS records,
+ "good.example." does not have to change operations by suspending
+ self-signing. DS records can be used in configuration files to
+ identify trusted keys instead of KEY records. Another significant
+ advantage is that the amount of information stored in large
+ delegation zones is reduced: rather than the NULL KEY record at every
+ unsecure delegation demanded by RFC 2535, only secure delegations
+ require additional information in the form of a signed DS RRset.
+
+ The main disadvantage of this approach is that verifying a zone's KEY
+ RRset requires two signature verification operations instead of the
+ one in RFC 2535 chain of trust. There is no impact on the number of
+ signatures verified for other types of RRsets.
+
+2.2. Protocol Change
+
+ All DNS servers and resolvers that support DS MUST support the OK bit
+ [RFC3225] and a larger message size [RFC3226]. In order for a
+ delegation to be considered secure the delegation MUST contain a DS
+ RRset. If a query contains the OK bit, a nameserver returning a
+ referral for the delegation MUST include the following RRsets in the
+ authority section in this order:
+
+ If DS RRset is present:
+ parent's copy of child's NS RRset
+ DS and SIG(DS)
+
+ If no DS RRset is present:
+ parent's copy of child's NS RRset
+ parent's zone NXT and SIG(NXT)
+
+ This increases the size of referral messages, possibly causing some
+ or all glue to be omitted. If the DS or NXT RRsets with signatures
+ do not fit in the DNS message, the TC bit MUST be set. Additional
+ section processing is not changed.
+
+ A DS RRset accompanying a NS RRset indicates that the child zone is
+ secure. If a NS RRset exists without a DS RRset, the child zone is
+ unsecure (from the parents point of view). DS RRsets MUST NOT appear
+ at non-delegation points or at a zone's apex.
+
+
+
+Gudmundsson Standards Track [Page 5]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+ Section 2.2.1 defines special considerations related to authoritative
+ nameservers responding to DS queries and replaces RFC 2535 sections
+ 2.3.4 and 3.4. Section 2.2.2 replaces RFC 3008 section 2.7, and
+ section 2.2.3 updates RFC 3090.
+
+2.2.1. RFC 2535 2.3.4 and 3.4: Special Considerations at Delegation
+ Points
+
+ DNS security views each zone as a unit of data completely under the
+ control of the zone owner with each entry (RRset) signed by a special
+ private key held by the zone manager. But the DNS protocol views the
+ leaf nodes in a zone that are also the apex nodes of a child zone
+ (i.e., delegation points) as "really" belonging to the child zone.
+ The corresponding domain names appear in two master files and might
+ have RRsets signed by both the parent and child zones' keys. A
+ retrieval could get a mixture of these RRsets and SIGs, especially
+ since one nameserver could be serving both the zone above and below a
+ delegation point [RFC2181].
+
+ Each DS RRset stored in the parent zone MUST be signed by at least
+ one of the parent zone's private keys. The parent zone MUST NOT
+ contain a KEY RRset at any delegation point. Delegations in the
+ parent MAY contain only the following RR types: NS, DS, NXT and SIG.
+ The NS RRset MUST NOT be signed. The NXT RRset is the exceptional
+ case: it will always appear differently and authoritatively in both
+ the parent and child zones, if both are secure.
+
+ A secure zone MUST contain a self-signed KEY RRset at its apex. Upon
+ verifying the DS RRset from the parent, a resolver MAY trust any KEY
+ identified in the DS RRset as a valid signer of the child's apex KEY
+ RRset. Resolvers configured to trust one of the keys signing the KEY
+ RRset MAY now treat any data signed by the zone keys in the KEY RRset
+ as secure. In all other cases, resolvers MUST consider the zone
+ unsecure.
+
+ An authoritative nameserver queried for type DS MUST return the DS
+ RRset in the answer section.
+
+2.2.1.1. Special processing for DS queries
+
+ When a nameserver is authoritative for the parent zone at a
+ delegation point and receives a query for the DS record at that name,
+ it MUST answer based on data in the parent zone, return DS or
+ negative answer. This is true whether or not it is also
+ authoritative for the child zone.
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 6]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+ When the nameserver is authoritative for the child zone at a
+ delegation point but not the parent zone, there is no natural
+ response, since the child zone is not authoritative for the DS record
+ at the zone's apex. As these queries are only expected to originate
+ from recursive nameservers which are not DS-aware, the authoritative
+ nameserver MUST answer with:
+
+ RCODE: NOERROR
+ AA bit: set
+ Answer Section: Empty
+ Authority Section: SOA [+ SIG(SOA) + NXT + SIG(NXT)]
+
+ That is, it answers as if it is authoritative and the DS record does
+ not exist. DS-aware recursive nameservers will query the parent zone
+ at delegation points, so will not be affected by this.
+
+ A nameserver authoritative for only the child zone, that is also a
+ caching server MAY (if the RD bit is set in the query) perform
+ recursion to find the DS record at the delegation point, or MAY
+ return the DS record from its cache. In this case, the AA bit MUST
+ NOT be set in the response.
+
+2.2.1.2. Special processing when child and an ancestor share
+ nameserver
+
+ Special rules are needed to permit DS RR aware nameservers to
+ gracefully interact with older caches which otherwise might falsely
+ label a nameserver as lame because of the placement of the DS RR set.
+
+ Such a situation might arise when a nameserver is authoritative for
+ both a zone and it's grandparent, but not the parent. This sounds
+ like an obscure example, but it is very real. The root zone is
+ currently served on 13 machines, and "root-servers.net." is served on
+ 4 of the 13, but "net." is severed on different nameservers.
+
+ When a nameserver receives a query for (<QNAME>, DS, <QCLASS>), the
+ response MUST be determined from reading these rules in order:
+
+ 1) If the nameserver is authoritative for the zone that holds the DS
+ RR set (i.e., the zone that delegates <QNAME>, a.k.a. the "parent"
+ zone), the response contains the DS RR set as an authoritative
+ answer.
+
+ 2) If the nameserver is offering recursive service and the RD bit is
+ set in the query, the nameserver performs the query itself
+ (according to the rules for resolvers described below) and returns
+ its findings.
+
+
+
+
+Gudmundsson Standards Track [Page 7]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+ 3) If the nameserver is authoritative for the zone that holds the
+ <QNAME>'s SOA RR set, the response is an authoritative negative
+ answer as described in 2.2.1.1.
+
+ 4) If the nameserver is authoritative for a zone or zones above the
+ QNAME, a referral to the most enclosing (deepest match) zone's
+ servers is made.
+
+ 5) If the nameserver is not authoritative for any part of the QNAME,
+ a response indicating a lame nameserver for QNAME is given.
+
+ Using these rules will require some special processing on the part of
+ a DS RR aware resolver. To illustrate this, an example is used.
+
+ Assuming a nameserver is authoritative for roots.example.net. and for
+ the root zone but not the intervening two zones (or the intervening
+ two label deep zone). Assume that QNAME=roots.example.net.,
+ QTYPE=DS, and QCLASS=IN.
+
+ The resolver will issue this request (assuming no cached data)
+ expecting a referral to a nameserver for .net. Instead, rule number
+ 3 above applies and a negative answer is returned by the nameserver.
+ The reaction by the resolver is not to accept this answer as final,
+ as it can determine from the SOA RR in the negative answer the
+ context within which the nameserver has answered.
+
+ A solution would be to instruct the resolver to hunt for the
+ authoritative zone of the data in a brute force manner.
+
+ This can be accomplished by taking the owner name of the returned SOA
+ RR and striping off enough left-hand labels until a successful NS
+ response is obtained. A successful response here means that the
+ answer has NS records in it. (Entertaining the possibility that a
+ cut point can be two labels down in a zone.)
+
+ Returning to the example, the response will include a negative answer
+ with either the SOA RR for "roots.example.net." or "example.net."
+ depending on whether roots.example.net is a delegated domain. In
+ either case, removing the left most label of the SOA owner name will
+ lead to the location of the desired data.
+
+2.2.1.3. Modification on use of KEY RR in the construction of Responses
+
+ This section updates RFC 2535 section 3.5 by replacing it with the
+ following:
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 8]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+ A query for KEY RR MUST NOT trigger any additional section
+ processing. Security aware resolvers will include corresponding SIG
+ records in the answer section.
+
+ KEY records SHOULD NOT be added to the additional records section in
+ response to any query.
+
+ RFC 2535 specified that KEY records be added to the additional
+ section when SOA or NS records were included in an answer. This was
+ done to reduce round trips (in the case of SOA) and to force out NULL
+ KEYs (in the NS case). As this document obsoletes NULL keys, there
+ is no need for the inclusion of KEYs with NSs. Furthermore, as SOAs
+ are included in the authority section of negative answers, including
+ the KEYs each time will cause redundant transfers of KEYs.
+
+ RFC 2535 section 3.5 also included a rule for adding the KEY RRset to
+ the response for a query for A and AAAA types. As Restrict KEY
+ [RFC3445] eliminated use of KEY RR by all applications, this rule is
+ no longer needed.
+
+2.2.2. Signer's Name (replaces RFC 3008 section 2.7)
+
+ The signer's name field of a SIG RR MUST contain the name of the zone
+ to which the data and signature belong. The combination of signer's
+ name, key tag, and algorithm MUST identify a zone key if the SIG is
+ to be considered material. This document defines a standard policy
+ for DNSSEC validation; local policy MAY override the standard policy.
+
+ There are no restrictions on the signer field of a SIG(0) record. The
+ combination of signer's name, key tag, and algorithm MUST identify a
+ key if this SIG(0) is to be processed.
+
+2.2.3. Changes to RFC 3090
+
+ A number of sections in RFC 3090 need to be updated to reflect the DS
+ record.
+
+2.2.3.1. RFC 3090: Updates to section 1: Introduction
+
+ Most of the text is still relevant but the words "NULL key" are to be
+ replaced with "missing DS RRset". In section 1.3, the last three
+ paragraphs discuss the confusion in sections of RFC 2535 that are
+ replaced in section 2.2.1 above. Therefore, these paragraphs are now
+ obsolete.
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 9]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+2.2.3.2. RFC 3090 section 2.1: Globally Secured
+
+ Rule 2.1.b is replaced by the following rule:
+
+ 2.1.b. The KEY RRset at a zone's apex MUST be self-signed by a
+ private key whose public counterpart MUST appear in a zone signing
+ KEY RR (2.a) owned by the zone's apex and specifying a mandatory-to-
+ implement algorithm. This KEY RR MUST be identified by a DS RR in a
+ signed DS RRset in the parent zone.
+
+ If a zone cannot get its parent to advertise a DS record for it, the
+ child zone cannot be considered globally secured. The only exception
+ to this is the root zone, for which there is no parent zone.
+
+2.2.3.3. RFC 3090 section 3: Experimental Status.
+
+ The only difference between experimental status and globally secured
+ is the missing DS RRset in the parent zone. All locally secured
+ zones are experimental.
+
+2.2.4. NULL KEY elimination
+
+ RFC 3445 section 3 eliminates the top two bits in the flags field of
+ KEY RR. These two bits were used to indicate NULL KEY or NO KEY. RFC
+ 3090 defines that zone as either secure or not and these rules
+ eliminate the need to put NULL keys in the zone apex to indicate that
+ the zone is not secured for a algorithm. Along with this document,
+ these other two eliminate all uses for the NULL KEY. This document
+ obsoletes NULL KEY.
+
+2.3. Comments on Protocol Changes
+
+ Over the years, there have been various discussions surrounding the
+ DNS delegation model, declaring it to be broken because there is no
+ good way to assert if a delegation exists. In the RFC 2535 version
+ of DNSSEC, the presence of the NS bit in the NXT bit map proves there
+ is a delegation at this name. Something more explicit is required
+ and the DS record addresses this need for secure delegations.
+
+ The DS record is a major change to DNS: it is the first resource
+ record that can appear only on the upper side of a delegation.
+ Adding it will cause interoperability problems and requires a flag
+ day for DNSSEC. Many old nameservers and resolvers MUST be upgraded
+ to take advantage of DS. Some old nameservers will be able to be
+ authoritative for zones with DS records but will not add the NXT or
+ DS records to the authority section. The same is true for caching
+ nameservers; in fact, some might even refuse to pass on the DS or NXT
+ records.
+
+
+
+Gudmundsson Standards Track [Page 10]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+2.4. Wire Format of the DS record
+
+ The DS (type=43) record contains these fields: key tag, algorithm,
+ digest type, and the digest of a public key KEY record that is
+ allowed and/or used to sign the child's apex KEY RRset. Other keys
+ MAY sign the child's apex KEY RRset.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | key tag | algorithm | Digest type |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | digest (length depends on type) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | (SHA-1 digest is 20 bytes) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The key tag is calculated as specified in RFC 2535. Algorithm MUST
+ be allowed to sign DNS data. The digest type is an identifier for
+ the digest algorithm used. The digest is calculated over the
+ canonical name of the delegated domain name followed by the whole
+ RDATA of the KEY record (all four fields).
+
+ digest = hash( canonical FQDN on KEY RR | KEY_RR_rdata)
+
+ KEY_RR_rdata = Flags | Protocol | Algorithm | Public Key
+
+ Digest type value 0 is reserved, value 1 is SHA-1, and reserving
+ other types requires IETF standards action. For interoperability
+ reasons, keeping number of digest algorithms low is strongly
+ RECOMMENDED. The only reason to reserve additional digest types is
+ to increase security.
+
+ DS records MUST point to zone KEY records that are allowed to
+ authenticate DNS data. The indicated KEY records protocol field MUST
+ be set to 3; flag field bit 7 MUST be set to 1. The value of other
+ flag bits is not significant for the purposes of this document.
+
+ The size of the DS RDATA for type 1 (SHA-1) is 24 bytes, regardless
+ of key size. New digest types probably will have larger digests.
+
+
+
+
+
+Gudmundsson Standards Track [Page 11]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+2.4.1. Justifications for Fields
+
+ The algorithm and key tag fields are present to allow resolvers to
+ quickly identify the candidate KEY records to examine. SHA-1 is a
+ strong cryptographic checksum: it is computationally infeasible for
+ an attacker to generate a KEY record that has the same SHA-1 digest.
+ Combining the name of the key and the key rdata as input to the
+ digest provides stronger assurance of the binding. Having the key
+ tag in the DS record adds greater assurance than the SHA-1 digest
+ alone, as there are now two different mapping functions.
+
+ This format allows concise representation of the keys that the child
+ will use, thus keeping down the size of the answer for the
+ delegation, reducing the probability of DNS message overflow. The
+ SHA-1 hash is strong enough to uniquely identify the key and is
+ similar to the PGP key footprint. The digest type field is present
+ for possible future expansion.
+
+ The DS record is well suited to listing trusted keys for islands of
+ security in configuration files.
+
+2.5. Presentation Format of the DS Record
+
+ The presentation format of the DS record consists of three numbers
+ (key tag, algorithm, and digest type) followed by the digest itself
+ presented in hex:
+
+ example. DS 12345 3 1 123456789abcdef67890123456789abcdef67890
+
+2.6. Transition Issues for Installed Base
+
+ No backwards compatibility with RFC 2535 is provided.
+
+ RFC 2535-compliant resolvers will assume that all DS-secured
+ delegations are locally secure. This is bad, but the DNSEXT Working
+ Group has determined that rather than dealing with both RFC 2535-
+ secured zones and DS-secured zones, a rapid adoption of DS is
+ preferable. Thus, the only option for early adopters is to upgrade
+ to DS as soon as possible.
+
+2.6.1. Backwards compatibility with RFC 2535 and RFC 1035
+
+ This section documents how a resolver determines the type of
+ delegation.
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 12]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+ RFC 1035 delegation (in parent) has:
+
+ RFC 1035 NS
+
+ RFC 2535 adds the following two cases:
+
+ Secure RFC 2535: NS + NXT + SIG(NXT)
+ NXT bit map contains: NS SIG NXT
+ Unsecure RFC 2535: NS + KEY + SIG(KEY) + NXT + SIG(NXT)
+ NXT bit map contains: NS SIG KEY NXT
+ KEY must be a NULL key.
+
+ DNSSEC with DS has the following two states:
+
+ Secure DS: NS + DS + SIG(DS)
+ NXT bit map contains: NS SIG NXT DS
+ Unsecure DS: NS + NXT + SIG(NXT)
+ NXT bit map contains: NS SIG NXT
+
+ It is difficult for a resolver to determine if a delegation is secure
+ RFC 2535 or unsecure DS. This could be overcome by adding a flag to
+ the NXT bit map, but only upgraded resolvers would understand this
+ flag, anyway. Having both parent and child signatures for a KEY
+ RRset might allow old resolvers to accept a zone as secure, but the
+ cost of doing this for a long time is much higher than just
+ prohibiting RFC 2535-style signatures at child zone apexes and
+ forcing rapid deployment of DS-enabled nameservers and resolvers.
+
+ RFC 2535 and DS can, in theory, be deployed in parallel, but this
+ would require resolvers to deal with RFC 2535 configurations forever.
+ This document obsoletes the NULL KEY in parent zones, which is a
+ difficult enough change that to cause a flag day.
+
+2.7. KEY and corresponding DS record example
+
+ This is an example of a KEY record and the corresponding DS record.
+
+ dskey.example. KEY 256 3 1 (
+ AQPwHb4UL1U9RHaU8qP+Ts5bVOU1s7fYbj2b3CCbzNdj
+ 4+/ECd18yKiyUQqKqQFWW5T3iVc8SJOKnueJHt/Jb/wt
+ ) ; key id = 28668
+ DS 28668 1 1 49FD46E6C4B45C55D4AC69CBD3CD34AC1AFE51DE
+
+
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 13]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+3. Resolver
+
+3.1. DS Example
+
+ To create a chain of trust, a resolver goes from trusted KEY to DS to
+ KEY.
+
+ Assume the key for domain "example." is trusted. Zone "example."
+ contains at least the following records:
+ example. SOA <soa stuff>
+ example. NS ns.example.
+ example. KEY <stuff>
+ example. NXT secure.example. NS SOA KEY SIG NXT
+ example. SIG(SOA)
+ example. SIG(NS)
+ example. SIG(NXT)
+ example. SIG(KEY)
+ secure.example. NS ns1.secure.example.
+ secure.example. DS tag=12345 alg=3 digest_type=1 <foofoo>
+ secure.example. NXT unsecure.example. NS SIG NXT DS
+ secure.example. SIG(NXT)
+ secure.example. SIG(DS)
+ unsecure.example NS ns1.unsecure.example.
+ unsecure.example. NXT example. NS SIG NXT
+ unsecure.example. SIG(NXT)
+
+ In zone "secure.example." following records exist:
+ secure.example. SOA <soa stuff>
+ secure.example. NS ns1.secure.example.
+ secure.example. KEY <tag=12345 alg=3>
+ secure.example. KEY <tag=54321 alg=5>
+ secure.example. NXT <nxt stuff>
+ secure.example. SIG(KEY) <key-tag=12345 alg=3>
+ secure.example. SIG(SOA) <key-tag=54321 alg=5>
+ secure.example. SIG(NS) <key-tag=54321 alg=5>
+ secure.example. SIG(NXT) <key-tag=54321 alg=5>
+
+ In this example, the private key for "example." signs the DS record
+ for "secure.example.", making that a secure delegation. The DS
+ record states which key is expected to sign the KEY RRset at
+ "secure.example.". Here "secure.example." signs its KEY RRset with
+ the KEY identified in the DS RRset, thus the KEY RRset is validated
+ and trusted.
+
+ This example has only one DS record for the child, but parents MUST
+ allow multiple DS records to facilitate key roll-over and multiple
+ KEY algorithms.
+
+
+
+
+Gudmundsson Standards Track [Page 14]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+ The resolver determines the security status of "unsecure.example." by
+ examining the parent zone's NXT record for this name. The absence of
+ the DS bit indicates an unsecure delegation. Note the NXT record
+ SHOULD only be examined after verifying the corresponding signature.
+
+3.2. Resolver Cost Estimates for DS Records
+
+ From a RFC 2535 recursive resolver point of view, for each delegation
+ followed to chase down an answer, one KEY RRset has to be verified.
+ Additional RRsets might also need to be verified based on local
+ policy (e.g., the contents of the NS RRset). Once the resolver gets
+ to the appropriate delegation, validating the answer might require
+ verifying one or more signatures. A simple A record lookup requires
+ at least N delegations to be verified and one RRset. For a DS-
+ enabled recursive resolver, the cost is 2N+1. For an MX record,
+ where the target of the MX record is in the same zone as the MX
+ record, the costs are N+2 and 2N+2, for RFC 2535 and DS,
+ respectively. In the case of a negative answer, the same ratios hold
+ true.
+
+ The recursive resolver has to do an extra query to get the DS record,
+ which will increase the overall cost of resolving this question, but
+ it will never be worse than chasing down NULL KEY records from the
+ parent in RFC 2535 DNSSEC.
+
+ DS adds processing overhead on resolvers and increases the size of
+ delegation answers, but much less than storing signatures in the
+ parent zone.
+
+4. Security Considerations
+
+ This document proposes a change to the validation chain of KEY
+ records in DNSSEC. The change is not believed to reduce security in
+ the overall system. In RFC 2535 DNSSEC, the child zone has to
+ communicate keys to its parent and prudent parents will require some
+ authentication with that transaction. The modified protocol will
+ require the same authentication, but allows the child to exert more
+ local control over its own KEY RRset.
+
+ There is a remote possibility that an attacker could generate a valid
+ KEY that matches all the DS fields, of a specific DS set, and thus
+ forge data from the child. This possibility is considered
+ impractical, as on average more than
+
+ 2 ^ (160 - <Number of keys in DS set>)
+
+ keys would have to be generated before a match would be found.
+
+
+
+
+Gudmundsson Standards Track [Page 15]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+ An attacker that wants to match any DS record will have to generate
+ on average at least 2^80 keys.
+
+ The DS record represents a change to the DNSSEC protocol and there is
+ an installed base of implementations, as well as textbooks on how to
+ set up secure delegations. Implementations that do not understand
+ the DS record will not be able to follow the KEY to DS to KEY chain
+ and will consider all zones secured that way as unsecure.
+
+5. IANA Considerations
+
+ IANA has allocated an RR type code for DS from the standard RR type
+ space (type 43).
+
+ IANA has established a new registry for the DS RR type for digest
+ algorithms. Defined types are:
+
+ 0 is Reserved,
+ 1 is SHA-1.
+
+ Adding new reservations requires IETF standards action.
+
+6. Intellectual Property Statement
+
+ The IETF takes no position regarding the validity or scope of any
+ intellectual property or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; neither does it represent that it
+ has made any effort to identify any such rights. Information on the
+ IETF's procedures with respect to rights in standards-track and
+ standards-related documentation can be found in BCP-11. Copies of
+ claims of rights made available for publication and any assurances of
+ licenses to be made available, or the result of an attempt made to
+ obtain a general license or permission for the use of such
+ proprietary rights by implementors or users of this specification can
+ be obtained from the IETF Secretariat.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights which may cover technology that may be required to practice
+ this standard. Please address the information to the IETF Executive
+ Director.
+
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 16]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+7. Acknowledgments
+
+ Over the last few years a number of people have contributed ideas
+ that are captured in this document. The core idea of using one key
+ to sign only the KEY RRset comes from discussions with Bill Manning
+ and Perry Metzger on how to put in a single root key in all
+ resolvers. Alexis Yushin, Brian Wellington, Sam Weiler, Paul Vixie,
+ Jakob Schlyter, Scott Rose, Edward Lewis, Lars-Johan Liman, Matt
+ Larson, Mark Kosters, Dan Massey, Olaf Kolman, Phillip Hallam-Baker,
+ Miek Gieben, Havard Eidnes, Donald Eastlake 3rd., Randy Bush, David
+ Blacka, Steve Bellovin, Rob Austein, Derek Atkins, Roy Arends, Mark
+ Andrews, Harald Alvestrand, and others have provided useful comments.
+
+8. References
+
+8.1. Normative References
+
+ [RFC1035] Mockapetris, P., "Domain Names - Implementation and
+ Specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2535] Eastlake, D., "Domain Name System Security Extensions",
+ RFC 2535, March 1999.
+
+ [RFC3008] Wellington, B., "Domain Name System Security (DNSSEC)
+ Signing Authority", RFC 3008, November 2000.
+
+ [RFC3090] Lewis, E., "DNS Security Extension Clarification on Zone
+ Status", RFC 3090, March 2001.
+
+ [RFC3225] Conrad, D., "Indicating Resolver Support of DNSSEC", RFC
+ 3225, December 2001.
+
+ [RFC3445] Massey, D. and S. Rose, "Limiting the scope of the KEY
+ Resource Record (RR)", RFC 3445, December 2002.
+
+8.2. Informational References
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC3226] Gudmundsson, O., "DNSSEC and IPv6 A6 aware server/resolver
+ message size requirements", RFC 3226, December 2001.
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 17]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+9. Author's Address
+
+ Olafur Gudmundsson
+ 3821 Village Park Drive
+ Chevy Chase, MD, 20815
+
+ EMail: ds-rfc@ogud.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 18]
+
+RFC 3658 Delegation Signer (DS) Resource Record (RR) December 2003
+
+
+10. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assignees.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Gudmundsson Standards Track [Page 19]
+
diff --git a/doc/rfc/rfc3757.txt b/doc/rfc/rfc3757.txt
new file mode 100644
index 0000000..31890a4
--- /dev/null
+++ b/doc/rfc/rfc3757.txt
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+Network Working Group O. Kolkman
+Request for Comments: 3757 RIPE NCC
+Updates: 3755, 2535 J. Schlyter
+Category: Standards Track NIC-SE
+ E. Lewis
+ ARIN
+ April 2004
+
+
+ Domain Name System KEY (DNSKEY) Resource Record (RR)
+ Secure Entry Point (SEP) Flag
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2004). All Rights Reserved.
+
+Abstract
+
+ With the Delegation Signer (DS) resource record (RR), the concept of
+ a public key acting as a secure entry point (SEP) has been
+ introduced. During exchanges of public keys with the parent there is
+ a need to differentiate SEP keys from other public keys in the Domain
+ Name System KEY (DNSKEY) resource record set. A flag bit in the
+ DNSKEY RR is defined to indicate that DNSKEY is to be used as a SEP.
+ The flag bit is intended to assist in operational procedures to
+ correctly generate DS resource records, or to indicate what DNSKEYs
+ are intended for static configuration. The flag bit is not to be
+ used in the DNS verification protocol. This document updates RFC
+ 2535 and RFC 3755.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kolkman, et al. Standard Track [Page 1]
+
+RFC 3757 DNSKEY RR SEP Flag April 2004
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 2. The Secure Entry Point (SEP) Flag. . . . . . . . . . . . . . . 4
+ 3. DNSSEC Protocol Changes. . . . . . . . . . . . . . . . . . . . 4
+ 4. Operational Guidelines . . . . . . . . . . . . . . . . . . . . 4
+ 5. Security Considerations. . . . . . . . . . . . . . . . . . . . 5
+ 6. IANA Considerations. . . . . . . . . . . . . . . . . . . . . . 6
+ 7. Internationalization Considerations. . . . . . . . . . . . . . 6
+ 8. Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . . 6
+ 9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 9.1. Normative References . . . . . . . . . . . . . . . . . . 6
+ 9.2. Informative References . . . . . . . . . . . . . . . . . 6
+ 10. Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . 7
+ 11. Full Copyright Statement . . . . . . . . . . . . . . . . . . . 8
+
+1. Introduction
+
+ "All keys are equal but some keys are more equal than others" [6].
+
+ With the definition of the Delegation Signer Resource Record (DS RR)
+ [5], it has become important to differentiate between the keys in the
+ DNSKEY RR set that are (to be) pointed to by parental DS RRs and the
+ other keys in the DNSKEY RR set. We refer to these public keys as
+ Secure Entry Point (SEP) keys. A SEP key either used to generate a
+ DS RR or is distributed to resolvers that use the key as the root of
+ a trusted subtree [3].
+
+ In early deployment tests, the use of two (kinds of) key pairs for
+ each zone has been prevalent. For one kind of key pair the private
+ key is used to sign just the zone's DNSKEY resource record (RR) set.
+ Its public key is intended to be referenced by a DS RR at the parent
+ or configured statically in a resolver. The private key of the other
+ kind of key pair is used to sign the rest of the zone's data sets.
+ The former key pair is called a key-signing key (KSK) and the latter
+ is called a zone-signing key (ZSK). In practice there have been
+ usually one of each kind of key pair, but there will be multiples of
+ each at times.
+
+ It should be noted that division of keys pairs into KSK's and ZSK's
+ is not mandatory in any definition of DNSSEC, not even with the
+ introduction of the DS RR. But, in testing, this distinction has
+ been helpful when designing key roll over (key super-cession)
+ schemes. Given that the distinction has proven helpful, the labels
+ KSK and ZSK have begun to stick.
+
+
+
+
+
+
+Kolkman, et al. Standard Track [Page 2]
+
+RFC 3757 DNSKEY RR SEP Flag April 2004
+
+
+ There is a need to differentiate the public keys for the key pairs
+ that are used for key signing from keys that are not used key signing
+ (KSKs vs ZSKs). This need is driven by knowing which DNSKEYs are to
+ be sent for generating DS RRs, which DNSKEYs are to be distributed to
+ resolvers, and which keys are fed to the signer application at the
+ appropriate time.
+
+ In other words, the SEP bit provides an in-band method to communicate
+ a DNSKEY RR's intended use to third parties. As an example we
+ present 3 use cases in which the bit is useful:
+
+ The parent is a registry, the parent and the child use secured DNS
+ queries and responses, with a preexisting trust-relation, or plain
+ DNS over a secured channel to exchange the child's DNSKEY RR sets.
+ Since a DNSKEY RR set will contain a complete DNSKEY RRset the SEP
+ bit can be used to isolate the DNSKEYs for which a DS RR needs to
+ be created.
+
+ An administrator has configured a DNSKEY as root for a trusted
+ subtree into security aware resolver. Using a special purpose
+ tool that queries for the KEY RRs from that domain's apex, the
+ administrator will be able to notice the roll over of the trusted
+ anchor by a change of the subset of KEY RRs with the DS flag set.
+
+ A signer might use the SEP bit on the public key to determine
+ which private key to use to exclusively sign the DNSKEY RRset and
+ which private key to use to sign the other RRsets in the zone.
+
+ As demonstrated in the above examples it is important to be able to
+ differentiate the SEP keys from the other keys in a DNSKEY RR set in
+ the flow between signer and (parental) key-collector and in the flow
+ between the signer and the resolver configuration. The SEP flag is
+ to be of no interest to the flow between the verifier and the
+ authoritative data store.
+
+ The reason for the term "SEP" is a result of the observation that the
+ distinction between KSK and ZSK key pairs is made by the signer, a
+ key pair could be used as both a KSK and a ZSK at the same time. To
+ be clear, the term SEP was coined to lessen the confusion caused by
+ the overlap. (Once this label was applied, it had the side effect of
+ removing the temptation to have both a KSK flag bit and a ZSK flag
+ bit.)
+
+ The key words "MAY","MAY NOT", "MUST", "MUST NOT", "REQUIRED",
+ "RECOMMENDED", "SHOULD", and "SHOULD NOT" in this document are to be
+ interpreted as described in BCP 14, RFC 2119 [1].
+
+
+
+
+
+Kolkman, et al. Standard Track [Page 3]
+
+RFC 3757 DNSKEY RR SEP Flag April 2004
+
+
+2. The Secure Entry Point (SEP) Flag
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | flags |S| protocol | algorithm |
+ | |E| | |
+ | |P| | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | /
+ / public key /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ DNSKEY RR Format
+ This document assigns the 15th bit in the flags field as the secure
+ entry point (SEP) bit. If the bit is set to 1 the key is intended to
+ be used as secure entry point key. One SHOULD NOT assign special
+ meaning to the key if the bit is set to 0. Operators can recognize
+ the secure entry point key by the even or odd-ness of the decimal
+ representation of the flag field.
+
+3. DNSSEC Protocol Changes
+
+ The bit MUST NOT be used during the resolving and verification
+ process. The SEP flag is only used to provide a hint about the
+ different administrative properties of the key and therefore the use
+ of the SEP flag does not change the DNS resolution protocol or the
+ resolution process.
+
+4. Operational Guidelines
+
+ The SEP bit is set by the key-pair-generator and MAY be used by the
+ zone signer to decide whether the public part of the key pair is to
+ be prepared for input to a DS RR generation function. The SEP bit is
+ recommended to be set (to 1) whenever the public key of the key pair
+ will be distributed to the parent zone to build the authentication
+ chain or if the public key is to be distributed for static
+ configuration in verifiers.
+
+ When a key pair is created, the operator needs to indicate whether
+ the SEP bit is to be set in the DNSKEY RR. As the SEP bit is within
+ the data that is used to compute the 'key tag field' in the SIG RR,
+ changing the SEP bit will change the identity of the key within DNS.
+ In other words, once a key is used to generate signatures, the
+ setting of the SEP bit is to remain constant. If not, a verifier
+ will not be able to find the relevant KEY RR.
+
+
+
+
+Kolkman, et al. Standard Track [Page 4]
+
+RFC 3757 DNSKEY RR SEP Flag April 2004
+
+
+ When signing a zone, it is intended that the key(s) with the SEP bit
+ set (if such keys exist) are used to sign the KEY RR set of the zone.
+ The same key can be used to sign the rest of the zone data too. It
+ is conceivable that not all keys with a SEP bit set will sign the
+ DNSKEY RR set, such keys might be pending retirement or not yet in
+ use.
+
+ When verifying a RR set, the SEP bit is not intended to play a role.
+ How the key is used by the verifier is not intended to be a
+ consideration at key creation time.
+
+ Although the SEP flag provides a hint on which public key is to be
+ used as trusted root, administrators can choose to ignore the fact
+ that a DNSKEY has its SEP bit set or not when configuring a trusted
+ root for their resolvers.
+
+ Using the SEP flag a key roll over can be automated. The parent can
+ use an existing trust relation to verify DNSKEY RR sets in which a
+ new DNSKEY RR with the SEP flag appears.
+
+5. Security Considerations
+
+ As stated in Section 3 the flag is not to be used in the resolution
+ protocol or to determine the security status of a key. The flag is
+ to be used for administrative purposes only.
+
+ No trust in a key should be inferred from this flag - trust MUST be
+ inferred from an existing chain of trust or an out-of-band exchange.
+
+ Since this flag might be used for automating public key exchanges, we
+ think the following consideration is in place.
+
+ Automated mechanisms for roll over of the DS RR might be vulnerable
+ to a class of replay attacks. This might happen after a public key
+ exchange where a DNSKEY RR set, containing two DNSKEY RRs with the
+ SEP flag set, is sent to the parent. The parent verifies the DNSKEY
+ RR set with the existing trust relation and creates the new DS RR
+ from the DNSKEY RR that the current DS RR is not pointing to. This
+ key exchange might be replayed. Parents are encouraged to implement
+ a replay defense. A simple defense can be based on a registry of
+ keys that have been used to generate DS RRs during the most recent
+ roll over. These same considerations apply to entities that
+ configure keys in resolvers.
+
+
+
+
+
+
+
+
+Kolkman, et al. Standard Track [Page 5]
+
+RFC 3757 DNSKEY RR SEP Flag April 2004
+
+
+6. IANA Considerations
+
+ IANA has assigned the 15th bit in the DNSKEY Flags Registry (see
+ Section 4.3 of [4]) as the Secure Entry Point (SEP) bit.
+
+7. Internationalization Considerations
+
+ Although SEP is a popular acronym in many different languages, there
+ are no internationalization considerations.
+
+8. Acknowledgments
+
+ The ideas documented in this document are inspired by communications
+ we had with numerous people and ideas published by other folk. Among
+ others Mark Andrews, Rob Austein, Miek Gieben, Olafur Gudmundsson,
+ Daniel Karrenberg, Dan Massey, Scott Rose, Marcos Sanz and Sam Weiler
+ have contributed ideas and provided feedback.
+
+ This document saw the light during a workshop on DNSSEC operations
+ hosted by USC/ISI in August 2002.
+
+9. References
+
+9.1. Normative References
+
+ [1] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [2] Eastlake, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [3] Lewis, E., "DNS Security Extension Clarification on Zone
+ Status", RFC 3090, March 2001.
+
+ [4] Weiler, S., "Legacy Resolver Compatibility for Delegation Signer
+ (DS)", RFC 3755, April 2004.
+
+9.2. Informative References
+
+ [5] Gudmundsson, O., "Delegation Signer (DS) Resource Record (RR)",
+ RFC 3658, December 2003.
+
+ [6] Orwell, G. and R. Steadman (illustrator), "Animal Farm; a Fairy
+ Story", ISBN 0151002177 (50th anniversary edition), April 1996.
+
+
+
+
+
+
+
+Kolkman, et al. Standard Track [Page 6]
+
+RFC 3757 DNSKEY RR SEP Flag April 2004
+
+
+10. Authors' Addresses
+
+ Olaf M. Kolkman
+ RIPE NCC
+ Singel 256
+ Amsterdam 1016 AB
+ NL
+
+ Phone: +31 20 535 4444
+ EMail: olaf@ripe.net
+ URI: http://www.ripe.net/
+
+
+ Jakob Schlyter
+ NIC-SE
+ Box 5774
+ SE-114 87 Stockholm
+ Sweden
+
+ EMail: jakob@nic.se
+ URI: http://www.nic.se/
+
+
+ Edward P. Lewis
+ ARIN
+ 3635 Concorde Parkway Suite 200
+ Chantilly, VA 20151
+ US
+
+ Phone: +1 703 227 9854
+ EMail: edlewis@arin.net
+ URI: http://www.arin.net/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kolkman, et al. Standard Track [Page 7]
+
+RFC 3757 DNSKEY RR SEP Flag April 2004
+
+
+11. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2004). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78 and
+ except as set forth therein, the authors retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE
+ REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE
+ INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed
+ to pertain to the implementation or use of the technology
+ described in this document or the extent to which any license
+ under such rights might or might not be available; nor does it
+ represent that it has made any independent effort to identify any
+ such rights. Information on the procedures with respect to
+ rights in RFC documents can be found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use
+ of such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository
+ at http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention
+ any copyrights, patents or patent applications, or other
+ proprietary rights that may cover technology that may be required
+ to implement this standard. Please address the information to the
+ IETF at ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+Kolkman, et al. Standard Track [Page 8]
+
diff --git a/doc/rfc/rfc3833.txt b/doc/rfc/rfc3833.txt
new file mode 100644
index 0000000..8ce4d34
--- /dev/null
+++ b/doc/rfc/rfc3833.txt
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+Network Working Group D. Atkins
+Request for Comments: 3833 IHTFP Consulting
+Category: Informational R. Austein
+ ISC
+ August 2004
+
+
+ Threat Analysis of the Domain Name System (DNS)
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2004).
+
+Abstract
+
+ Although the DNS Security Extensions (DNSSEC) have been under
+ development for most of the last decade, the IETF has never written
+ down the specific set of threats against which DNSSEC is designed to
+ protect. Among other drawbacks, this cart-before-the-horse situation
+ has made it difficult to determine whether DNSSEC meets its design
+ goals, since its design goals are not well specified. This note
+ attempts to document some of the known threats to the DNS, and, in
+ doing so, attempts to measure to what extent (if any) DNSSEC is a
+ useful tool in defending against these threats.
+
+1. Introduction
+
+ The earliest organized work on DNSSEC within the IETF was an open
+ design team meeting organized by members of the DNS working group in
+ November 1993 at the 28th IETF meeting in Houston. The broad
+ outlines of DNSSEC as we know it today are already clear in Jim
+ Galvin's summary of the results of that meeting [Galvin93]:
+
+ - While some participants in the meeting were interested in
+ protecting against disclosure of DNS data to unauthorized parties,
+ the design team made an explicit decision that "DNS data is
+ `public'", and ruled all threats of data disclosure explicitly out
+ of scope for DNSSEC.
+
+ - While some participants in the meeting were interested in
+ authentication of DNS clients and servers as a basis for access
+ control, this work was also ruled out of scope for DNSSEC per se.
+
+
+
+Atkins & Austein Informational [Page 1]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ - Backwards compatibility and co-existence with "insecure DNS" was
+ listed as an explicit requirement.
+
+ - The resulting list of desired security services was
+ 1) data integrity, and
+ 2) data origin authentication.
+
+ - The design team noted that a digital signature mechanism would
+ support the desired services.
+
+ While a number of detail decisions were yet to be made (and in some
+ cases remade after implementation experience) over the subsequent
+ decade, the basic model and design goals have remained fixed.
+
+ Nowhere, however, does any of the DNSSEC work attempt to specify in
+ any detail the sorts of attacks against which DNSSEC is intended to
+ protect, or the reasons behind the list of desired security services
+ that came out of the Houston meeting. For that, we have to go back
+ to a paper originally written by Steve Bellovin in 1990 but not
+ published until 1995, for reasons that Bellovin explained in the
+ paper's epilogue [Bellovin95].
+
+ While it may seem a bit strange to publish the threat analysis a
+ decade after starting work on the protocol designed to defend against
+ it, that is, nevertheless, what this note attempts to do. Better
+ late than never.
+
+ This note assumes that the reader is familiar with both the DNS and
+ with DNSSEC, and does not attempt to provide a tutorial on either.
+ The DNS documents most relevant to the subject of this note are:
+ [RFC1034], [RFC1035], section 6.1 of [RFC1123], [RFC2181], [RFC2308],
+ [RFC2671], [RFC2845], [RFC2930], [RFC3007], and [RFC2535].
+
+ For purposes of discussion, this note uses the term "DNSSEC" to refer
+ to the core hierarchical public key and signature mechanism specified
+ in the DNSSEC documents, and refers to TKEY and TSIG as separate
+ mechanisms, even though channel security mechanisms such as TKEY and
+ TSIG are also part of the larger problem of "securing DNS" and thus
+ are often considered part of the overall set of "DNS security
+ extensions". This is an arbitrary distinction that in part reflects
+ the way in which the protocol has evolved (introduction of a
+ putatively simpler channel security model for certain operations such
+ as zone transfers and dynamic update requests), and perhaps should be
+ changed in a future revision of this note.
+
+
+
+
+
+
+
+Atkins & Austein Informational [Page 2]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+2. Known Threats
+
+ There are several distinct classes of threats to the DNS, most of
+ which are DNS-related instances of more general problems, but a few
+ of which are specific to peculiarities of the DNS protocol.
+
+2.1. Packet Interception
+
+ Some of the simplest threats against DNS are various forms of packet
+ interception: monkey-in-the-middle attacks, eavesdropping on requests
+ combined with spoofed responses that beat the real response back to
+ the resolver, and so forth. In any of these scenarios, the attacker
+ can simply tell either party (usually the resolver) whatever it wants
+ that party to believe. While packet interception attacks are far
+ from unique to DNS, DNS's usual behavior of sending an entire query
+ or response in a single unsigned, unencrypted UDP packet makes these
+ attacks particularly easy for any bad guy with the ability to
+ intercept packets on a shared or transit network.
+
+ To further complicate things, the DNS query the attacker intercepts
+ may just be a means to an end for the attacker: the attacker might
+ even choose to return the correct result in the answer section of a
+ reply message while using other parts of the message to set the stage
+ for something more complicated, for example, a name chaining attack
+ (see section 2.3).
+
+ While it certainly would be possible to sign DNS messages using a
+ channel security mechanism such as TSIG or IPsec, or even to encrypt
+ them using IPsec, this would not be a very good solution for
+ interception attacks. First, this approach would impose a fairly
+ high processing cost per DNS message, as well as a very high cost
+ associated with establishing and maintaining bilateral trust
+ relationships between all the parties that might be involved in
+ resolving any particular query. For heavily used name servers (such
+ as the servers for the root zone), this cost would almost certainly
+ be prohibitively high. Even more important, however, is that the
+ underlying trust model in such a design would be wrong, since at best
+ it would only provide a hop-by-hop integrity check on DNS messages
+ and would not provide any sort of end-to-end integrity check between
+ the producer of DNS data (the zone administrator) and the consumer of
+ DNS data (the application that triggered the query).
+
+ By contrast, DNSSEC (when used properly) does provide an end-to-end
+ data integrity check, and is thus a much better solution for this
+ class of problems during basic DNS lookup operations.
+
+
+
+
+
+
+Atkins & Austein Informational [Page 3]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ TSIG does have its place in corners of the DNS protocol where there's
+ a specific trust relationship between a particular client and a
+ particular server, such as zone transfer, dynamic update, or a
+ resolver (stub or otherwise) that is not going to check all the
+ DNSSEC signatures itself.
+
+ Note that DNSSEC does not provide any protection against modification
+ of the DNS message header, so any properly paranoid resolver must:
+
+ - Perform all of the DNSSEC signature checking on its own,
+
+ - Use TSIG (or some equivalent mechanism) to ensure the integrity of
+ its communication with whatever name servers it chooses to trust,
+ or
+
+ - Resign itself to the possibility of being attacked via packet
+ interception (and via other techniques discussed below).
+
+2.2. ID Guessing and Query Prediction
+
+ Since DNS is for the most part used over UDP/IP, it is relatively
+ easy for an attacker to generate packets which will match the
+ transport protocol parameters. The ID field in the DNS header is
+ only a 16-bit field and the server UDP port associated with DNS is a
+ well-known value, so there are only 2**32 possible combinations of ID
+ and client UDP port for a given client and server. This is not a
+ particularly large range, and is not sufficient to protect against a
+ brute force search; furthermore, in practice both the client UDP port
+ and the ID can often be predicted from previous traffic, and it is
+ not uncommon for the client port to be a known fixed value as well
+ (due to firewalls or other restrictions), thus frequently reducing
+ the search space to a range smaller than 2**16.
+
+ By itself, ID guessing is not enough to allow an attacker to inject
+ bogus data, but combined with knowledge (or guesses) about QNAMEs and
+ QTYPEs for which a resolver might be querying, this leaves the
+ resolver only weakly defended against injection of bogus responses.
+
+ Since this attack relies on predicting a resolver's behavior, it's
+ most likely to be successful when the victim is in a known state,
+ whether because the victim rebooted recently, or because the victim's
+ behavior has been influenced by some other action by the attacker, or
+ because the victim is responding (in a predictable way) to some third
+ party action known to the attacker.
+
+
+
+
+
+
+
+Atkins & Austein Informational [Page 4]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ This attack is both more and less difficult for the attacker than the
+ simple interception attack described above: more difficult, because
+ the attack only works when the attacker guesses correctly; less
+ difficult, because the attacker doesn't need to be on a transit or
+ shared network.
+
+ In most other respects, this attack is similar to a packet
+ interception attack. A resolver that checks DNSSEC signatures will
+ be able to detect the forged response; resolvers that do not perform
+ DNSSEC signature checking themselves should use TSIG or some
+ equivalent mechanism to ensure the integrity of their communication
+ with a recursive name server that does perform DNSSEC signature
+ checking.
+
+2.3. Name Chaining
+
+ Perhaps the most interesting class of DNS-specific threats are the
+ name chaining attacks. These are a subset of a larger class of
+ name-based attacks, sometimes called "cache poisoning" attacks. Most
+ name-based attacks can be partially mitigated by the long-standing
+ defense of checking RRs in response messages for relevance to the
+ original query, but such defenses do not catch name chaining attacks.
+ There are several variations on the basic attack, but what they all
+ have in common is that they all involve DNS RRs whose RDATA portion
+ (right hand side) includes a DNS name (or, in a few cases, something
+ that is not a DNS name but which directly maps to a DNS name). Any
+ such RR is, at least in principle, a hook that lets an attacker feed
+ bad data into a victim's cache, thus potentially subverting
+ subsequent decisions based on DNS names.
+
+ The worst examples in this class of RRs are CNAME, NS, and DNAME RRs
+ because they can redirect a victim's query to a location of the
+ attacker's choosing. RRs like MX and SRV are somewhat less
+ dangerous, but in principle they can also be used to trigger further
+ lookups at a location of the attacker's choosing. Address RR types
+ such as A or AAAA don't have DNS names in their RDATA, but since the
+ IN-ADDR.ARPA and IP6.ARPA trees are indexed using a DNS encoding of
+ IPv4 and IPv6 addresses, these record types can also be used in a
+ name chaining attack.
+
+ The general form of a name chaining attack is something like this:
+
+ - Victim issues a query, perhaps at the instigation of the attacker
+ or some third party; in some cases the query itself may be
+ unrelated to the name under attack (that is, the attacker is just
+ using this query as a means to inject false information about some
+ other name).
+
+
+
+
+Atkins & Austein Informational [Page 5]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ - Attacker injects response, whether via packet interception, query
+ guessing, or by being a legitimate name server that's involved at
+ some point in the process of answering the query that the victim
+ issued.
+
+ - Attacker's response includes one or more RRs with DNS names in
+ their RDATA; depending on which particular form this attack takes,
+ the object may be to inject false data associated with those names
+ into the victim's cache via the Additional section of this
+ response, or may be to redirect the next stage of the query to a
+ server of the attacker's choosing (in order to inject more complex
+ lies into the victim's cache than will fit easily into a single
+ response, or in order to place the lies in the Authority or Answer
+ section of a response where they will have a better chance of
+ sneaking past a resolver's defenses).
+
+ Any attacker who can insert resource records into a victim's cache
+ can almost certainly do some kind of damage, so there are cache
+ poisoning attacks which are not name chaining attacks in the sense
+ discussed here. However, in the case of name chaining attacks, the
+ cause and effect relationship between the initial attack and the
+ eventual result may be significantly more complex than in the other
+ forms of cache poisoning, so name chaining attacks merit special
+ attention.
+
+ The common thread in all of the name chaining attacks is that
+ response messages allow the attacker to introduce arbitrary DNS names
+ of the attacker's choosing and provide further information that the
+ attacker claims is associated with those names; unless the victim has
+ better knowledge of the data associated with those names, the victim
+ is going to have a hard time defending against this class of attacks.
+
+ This class of attack is particularly insidious given that it's quite
+ easy for an attacker to provoke a victim into querying for a
+ particular name of the attacker's choosing, for example, by embedding
+ a link to a 1x1-pixel "web bug" graphic in a piece of Text/HTML mail
+ to the victim. If the victim's mail reading program attempts to
+ follow such a link, the result will be a DNS query for a name chosen
+ by the attacker.
+
+ DNSSEC should provide a good defense against most (all?) variations
+ on this class of attack. By checking signatures, a resolver can
+ determine whether the data associated with a name really was inserted
+ by the delegated authority for that portion of the DNS name space.
+ More precisely, a resolver can determine whether the entity that
+ injected the data had access to an allegedly secret key whose
+
+
+
+
+
+Atkins & Austein Informational [Page 6]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ corresponding public key appears at an expected location in the DNS
+ name space with an expected chain of parental signatures that start
+ with a public key of which the resolver has prior knowledge.
+
+ DNSSEC signatures do not cover glue records, so there's still a
+ possibility of a name chaining attack involving glue, but with DNSSEC
+ it is possible to detect the attack by temporarily accepting the glue
+ in order to fetch the signed authoritative version of the same data,
+ then checking the signatures on the authoritative version.
+
+2.4. Betrayal By Trusted Server
+
+ Another variation on the packet interception attack is the trusted
+ server that turns out not to be so trustworthy, whether by accident
+ or by intent. Many client machines are only configured with stub
+ resolvers, and use trusted servers to perform all of their DNS
+ queries on their behalf. In many cases the trusted server is
+ furnished by the user's ISP and advertised to the client via DHCP or
+ PPP options. Besides accidental betrayal of this trust relationship
+ (via server bugs, successful server break-ins, etc), the server
+ itself may be configured to give back answers that are not what the
+ user would expect, whether in an honest attempt to help the user or
+ to promote some other goal such as furthering a business partnership
+ between the ISP and some third party.
+
+ This problem is particularly acute for frequent travelers who carry
+ their own equipment and expect it to work in much the same way
+ wherever they go. Such travelers need trustworthy DNS service
+ without regard to who operates the network into which their equipment
+ is currently plugged or what brand of middle boxes the local
+ infrastructure might use.
+
+ While the obvious solution to this problem would be for the client to
+ choose a more trustworthy server, in practice this may not be an
+ option for the client. In many network environments a client machine
+ has only a limited set of recursive name servers from which to
+ choose, and none of them may be particularly trustworthy. In extreme
+ cases, port filtering or other forms of packet interception may
+ prevent the client host from being able to run an iterative resolver
+ even if the owner of the client machine is willing and able to do so.
+ Thus, while the initial source of this problem is not a DNS protocol
+ attack per se, this sort of betrayal is a threat to DNS clients, and
+ simply switching to a different recursive name server is not an
+ adequate defense.
+
+ Viewed strictly from the DNS protocol standpoint, the only difference
+ between this sort of betrayal and a packet interception attack is
+ that in this case the client has voluntarily sent its request to the
+
+
+
+Atkins & Austein Informational [Page 7]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ attacker. The defense against this is the same as with a packet
+ interception attack: the resolver must either check DNSSEC signatures
+ itself or use TSIG (or equivalent) to authenticate the server that it
+ has chosen to trust. Note that use of TSIG does not by itself
+ guarantee that a name server is at all trustworthy: all TSIG can do
+ is help a resolver protect its communication with a name server that
+ it has already decided to trust for other reasons. Protecting a
+ resolver's communication with a server that's giving out bogus
+ answers is not particularly useful.
+
+ Also note that if the stub resolver does not trust the name server
+ that is doing work on its behalf and wants to check the DNSSEC
+ signatures itself, the resolver really does need to have independent
+ knowledge of the DNSSEC public key(s) it needs in order to perform
+ the check. Usually the public key for the root zone is enough, but
+ in some cases knowledge of additional keys may also be appropriate.
+
+ It is difficult to escape the conclusion that a properly paranoid
+ resolver must always perform its own signature checking, and that
+ this rule even applies to stub resolvers.
+
+2.5. Denial of Service
+
+ As with any network service (or, indeed, almost any service of any
+ kind in any domain of discourse), DNS is vulnerable to denial of
+ service attacks. DNSSEC does not help this, and may in fact make the
+ problem worse for resolvers that check signatures, since checking
+ signatures both increases the processing cost per DNS message and in
+ some cases can also increase the number of messages needed to answer
+ a query. TSIG (and similar mechanisms) have equivalent problems.
+
+ DNS servers are also at risk of being used as denial of service
+ amplifiers, since DNS response packets tend to be significantly
+ longer than DNS query packets. Unsurprisingly, DNSSEC doesn't help
+ here either.
+
+2.6. Authenticated Denial of Domain Names
+
+ Much discussion has taken place over the question of authenticated
+ denial of domain names. The particular question is whether there is
+ a requirement for authenticating the non-existence of a name. The
+ issue is whether the resolver should be able to detect when an
+ attacker removes RRs from a response.
+
+ General paranoia aside, the existence of RR types whose absence
+ causes an action other than immediate failure (such as missing MX and
+ SRV RRs, which fail over to A RRs) constitutes a real threat.
+ Arguably, in some cases, even the absence of an RR might be
+
+
+
+Atkins & Austein Informational [Page 8]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ considered a problem. The question remains: how serious is this
+ threat? Clearly the threat does exist; general paranoia says that
+ some day it'll be on the front page of some major newspaper, even if
+ we cannot conceive of a plausible scenario involving this attack
+ today. This implies that some mitigation of this risk is required.
+
+ Note that it's necessary to prove the non-existence of applicable
+ wildcard RRs as part of the authenticated denial mechanism, and that,
+ in a zone that is more than one label deep, such a proof may require
+ proving the non-existence of multiple discrete sets of wildcard RRs.
+
+ DNSSEC does include mechanisms which make it possible to determine
+ which authoritative names exist in a zone, and which authoritative
+ resource record types exist at those names. The DNSSEC protections
+ do not cover non-authoritative data such as glue records.
+
+2.7. Wildcards
+
+ Much discussion has taken place over whether and how to provide data
+ integrity and data origin authentication for "wildcard" DNS names.
+ Conceptually, RRs with wildcard names are patterns for synthesizing
+ RRs on the fly according to the matching rules described in section
+ 4.3.2 of RFC 1034. While the rules that control the behavior of
+ wildcard names have a few quirks that can make them a trap for the
+ unwary zone administrator, it's clear that a number of sites make
+ heavy use of wildcard RRs, particularly wildcard MX RRs.
+
+ In order to provide the desired services for wildcard RRs, we need to
+ do two things:
+
+ - We need a way to attest to the existence of the wildcard RR itself
+ (that is, we need to show that the synthesis rule exists), and
+
+ - We need a way to attest to the non-existence of any RRs which, if
+ they existed, would make the wildcard RR irrelevant according to
+ the synthesis rules that govern the way in which wildcard RRs are
+ used (that is, we need to show that the synthesis rule is
+ applicable).
+
+ Note that this makes the wildcard mechanisms dependent upon the
+ authenticated denial mechanism described in the previous section.
+
+ DNSSEC includes mechanisms along the lines described above, which
+ make it possible for a resolver to verify that a name server applied
+ the wildcard expansion rules correctly when generating an answer.
+
+
+
+
+
+
+Atkins & Austein Informational [Page 9]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+3. Weaknesses of DNSSEC
+
+ DNSSEC has some problems of its own:
+
+ - DNSSEC is complex to implement and includes some nasty edge cases
+ at the zone cuts that require very careful coding. Testbed
+ experience to date suggests that trivial zone configuration errors
+ or expired keys can cause serious problems for a DNSSEC-aware
+ resolver, and that the current protocol's error reporting
+ capabilities may leave something to be desired.
+
+ - DNSSEC significantly increases the size of DNS response packets;
+ among other issues, this makes DNSSEC-aware DNS servers even more
+ effective as denial of service amplifiers.
+
+ - DNSSEC answer validation increases the resolver's work load, since
+ a DNSSEC-aware resolver will need to perform signature validation
+ and in some cases will also need to issue further queries. This
+ increased workload will also increase the time it takes to get an
+ answer back to the original DNS client, which is likely to trigger
+ both timeouts and re-queries in some cases. Arguably, many current
+ DNS clients are already too impatient even before taking the
+ further delays that DNSSEC will impose into account, but that topic
+ is beyond the scope of this note.
+
+ - Like DNS itself, DNSSEC's trust model is almost totally
+ hierarchical. While DNSSEC does allow resolvers to have special
+ additional knowledge of public keys beyond those for the root, in
+ the general case the root key is the one that matters. Thus any
+ compromise in any of the zones between the root and a particular
+ target name can damage DNSSEC's ability to protect the integrity of
+ data owned by that target name. This is not a change, since
+ insecure DNS has the same model.
+
+ - Key rollover at the root is really hard. Work to date has not even
+ come close to adequately specifying how the root key rolls over, or
+ even how it's configured in the first place.
+
+ - DNSSEC creates a requirement of loose time synchronization between
+ the validating resolver and the entity creating the DNSSEC
+ signatures. Prior to DNSSEC, all time-related actions in DNS could
+ be performed by a machine that only knew about "elapsed" or
+ "relative" time. Because the validity period of a DNSSEC signature
+ is based on "absolute" time, a validating resolver must have the
+ same concept of absolute time as the zone signer in order to
+ determine whether the signature is within its validity period or
+ has expired. An attacker that can change a resolver's opinion of
+ the current absolute time can fool the resolver using expired
+
+
+
+Atkins & Austein Informational [Page 10]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ signatures. An attacker that can change the zone signer's opinion
+ of the current absolute time can fool the zone signer into
+ generating signatures whose validity period does not match what the
+ signer intended.
+
+ - The possible existence of wildcard RRs in a zone complicates the
+ authenticated denial mechanism considerably. For most of the
+ decade that DNSSEC has been under development these issues were
+ poorly understood. At various times there have been questions as
+ to whether the authenticated denial mechanism is completely
+ airtight and whether it would be worthwhile to optimize the
+ authenticated denial mechanism for the common case in which
+ wildcards are not present in a zone. However, the main problem is
+ just the inherent complexity of the wildcard mechanism itself.
+ This complexity probably makes the code for generating and checking
+ authenticated denial attestations somewhat fragile, but since the
+ alternative of giving up wildcards entirely is not practical due to
+ widespread use, we are going to have to live with wildcards. The
+ question just becomes one of whether or not the proposed
+ optimizations would make DNSSEC's mechanisms more or less fragile.
+
+ - Even with DNSSEC, the class of attacks discussed in section 2.4 is
+ not easy to defeat. In order for DNSSEC to be effective in this
+ case, it must be possible to configure the resolver to expect
+ certain categories of DNS records to be signed. This may require
+ manual configuration of the resolver, especially during the initial
+ DNSSEC rollout period when the resolver cannot reasonably expect
+ the root and TLD zones to be signed.
+
+4. Topics for Future Work
+
+ This section lists a few subjects not covered above which probably
+ need additional study, additional mechanisms, or both.
+
+4.1. Interactions With Other Protocols
+
+ The above discussion has concentrated exclusively on attacks within
+ the boundaries of the DNS protocol itself, since those are (some of)
+ the problems against which DNSSEC was intended to protect. There
+ are, however, other potential problems at the boundaries where DNS
+ interacts with other protocols.
+
+4.2. Securing DNS Dynamic Update
+
+ DNS dynamic update opens a number of potential problems when combined
+ with DNSSEC. Dynamic update of a non-secure zone can use TSIG to
+ authenticate the updating client to the server. While TSIG does not
+ scale very well (it requires manual configuration of shared keys
+
+
+
+Atkins & Austein Informational [Page 11]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ between the DNS name server and each TSIG client), it works well in a
+ limited or closed environment such as a DHCP server updating a local
+ DNS name server.
+
+ Major issues arise when trying to use dynamic update on a secure
+ zone. TSIG can similarly be used in a limited fashion to
+ authenticate the client to the server, but TSIG only protects DNS
+ transactions, not the actual data, and the TSIG is not inserted into
+ the DNS zone, so resolvers cannot use the TSIG as a way of verifying
+ the changes to the zone. This means that either:
+
+ a) The updating client must have access to a zone-signing key in
+ order to sign the update before sending it to the server, or
+
+ b) The DNS name server must have access to an online zone-signing key
+ in order to sign the update.
+
+ In either case, a zone-signing key must be available to create signed
+ RRsets to place in the updated zone. The fact that this key must be
+ online (or at least available) is a potential security risk.
+
+ Dynamic update also requires an update to the SERIAL field of the
+ zone's SOA RR. In theory, this could also be handled via either of
+ the above options, but in practice (a) would almost certainly be
+ extremely fragile, so (b) is the only workable mechanism.
+
+ There are other threats in terms of describing the policy of who can
+ make what changes to which RRsets in the zone. The current access
+ control scheme in Secure Dynamic Update is fairly limited. There is
+ no way to give fine-grained access to updating DNS zone information
+ to multiple entities, each of whom may require different kinds of
+ access. For example, Alice may need to be able to add new nodes to
+ the zone or change existing nodes, but not remove them; Bob may need
+ to be able to remove zones but not add them; Carol may need to be
+ able to add, remove, or modify nodes, but only A records.
+
+ Scaling properties of the key management problem here are a
+ particular concern that needs more study.
+
+4.3. Securing DNS Zone Replication
+
+ As discussed in previous sections, DNSSEC per se attempts to provide
+ data integrity and data origin authentication services on top of the
+ normal DNS query protocol. Using the terminology discussed in
+ [RFC3552], DNSSEC provides "object security" for the normal DNS query
+ protocol. For purposes of replicating entire DNS zones, however,
+ DNSSEC does not provide object security, because zones include
+ unsigned NS RRs and glue at delegation points. Use of TSIG to
+
+
+
+Atkins & Austein Informational [Page 12]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ protect zone transfer (AXFR or IXFR) operations provides "channel
+ security", but still does not provide object security for complete
+ zones. The trust relationships involved in zone transfer are still
+ very much a hop-by-hop matter of name server operators trusting other
+ name server operators rather than an end-to-end matter of name server
+ operators trusting zone administrators.
+
+ Zone object security was not an explicit design goal of DNSSEC, so
+ failure to provide this service should not be a surprise.
+ Nevertheless, there are some zone replication scenarios for which
+ this would be a very useful additional service, so this seems like a
+ useful area for future work. In theory it should not be difficult to
+ add zone object security as a backwards compatible enhancement to the
+ existing DNSSEC model, but the DNSEXT WG has not yet discussed either
+ the desirability of or the requirements for such an enhancement.
+
+5. Conclusion
+
+ Based on the above analysis, the DNSSEC extensions do appear to solve
+ a set of problems that do need to be solved, and are worth deploying.
+
+Security Considerations
+
+ This entire document is about security considerations of the DNS.
+ The authors believe that deploying DNSSEC will help to address some,
+ but not all, of the known threats to the DNS.
+
+Acknowledgments
+
+ This note is based both on previous published works by others and on
+ a number of discussions both public and private over a period of many
+ years, but particular thanks go to
+
+ Jaap Akkerhuis,
+ Steve Bellovin,
+ Dan Bernstein,
+ Randy Bush,
+ Steve Crocker,
+ Olafur Gudmundsson,
+ Russ Housley,
+ Rip Loomis,
+ Allison Mankin,
+ Paul Mockapetris,
+ Thomas Narten
+ Mans Nilsson,
+ Pekka Savola,
+ Paul Vixie,
+ Xunhua Wang,
+
+
+
+Atkins & Austein Informational [Page 13]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+ and any other members of the DNS, DNSSEC, DNSIND, and DNSEXT working
+ groups whose names and contributions the authors have forgotten, none
+ of whom are responsible for what the authors did with their ideas.
+
+ As with any work of this nature, the authors of this note acknowledge
+ that we are standing on the toes of those who have gone before us.
+ Readers interested in this subject may also wish to read
+ [Bellovin95], [Schuba93], and [Vixie95].
+
+Normative References
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and
+ facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts -
+ Application and Support", STD 3, RFC 1123, October 1989.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC2308] Andrews, M., "Negative Caching of DNS Queries (DNS
+ NCACHE)", RFC 2308, March 1998.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [RFC2845] Vixie, P., Gudmundsson, O., Eastlake 3rd, D., and B.
+ Wellington, "Secret Key Transaction Authentication for
+ DNS (TSIG)", RFC 2845, May 2000.
+
+ [RFC2930] Eastlake 3rd, D., "Secret Key Establishment for DNS
+ (TKEY RR)", RFC 2930, September 2000.
+
+ [RFC3007] Wellington, B., "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+ [RFC2535] Eastlake 3rd, D., "Domain Name System Security
+ Extensions", RFC 2535, March 1999.
+
+
+
+
+
+
+
+
+
+
+Atkins & Austein Informational [Page 14]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+Informative References
+
+ [RFC3552] Rescorla, E. and B. Korver, "Guidelines for Writing RFC
+ Text on Security Considerations", BCP 72, RFC 3552, July
+ 2003.
+
+ [Bellovin95] Bellovin, S., "Using the Domain Name System for System
+ Break-Ins", Proceedings of the Fifth Usenix Unix
+ Security Symposium, June 1995.
+
+ [Galvin93] Design team meeting summary message posted to dns-
+ security@tis.com mailing list by Jim Galvin on 19
+ November 1993.
+
+ [Schuba93] Schuba, C., "Addressing Weaknesses in the Domain Name
+ System Protocol", Master's thesis, Purdue University
+ Department of Computer Sciences, August 1993.
+
+ [Vixie95] Vixie, P, "DNS and BIND Security Issues", Proceedings of
+ the Fifth Usenix Unix Security Symposium, June 1995.
+
+Authors' Addresses
+
+ Derek Atkins
+ IHTFP Consulting, Inc.
+ 6 Farragut Ave
+ Somerville, MA 02144
+ USA
+
+ EMail: derek@ihtfp.com
+
+
+ Rob Austein
+ Internet Systems Consortium
+ 950 Charter Street
+ Redwood City, CA 94063
+ USA
+
+ EMail: sra@isc.org
+
+
+
+
+
+
+
+
+
+
+
+
+Atkins & Austein Informational [Page 15]
+
+RFC 3833 DNS Threat Analysis August 2004
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2004). This document is subject
+ to the rights, licenses and restrictions contained in BCP 78, and
+ except as set forth therein, the authors retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+
+
+Atkins & Austein Informational [Page 16]
+
diff --git a/doc/rfc/rfc3845.txt b/doc/rfc/rfc3845.txt
new file mode 100644
index 0000000..9887a20
--- /dev/null
+++ b/doc/rfc/rfc3845.txt
@@ -0,0 +1,395 @@
+
+
+
+
+
+
+Network Working Group J. Schlyter, Ed.
+Request for Comments: 3845 August 2004
+Updates: 3755, 2535
+Category: Standards Track
+
+
+ DNS Security (DNSSEC) NextSECure (NSEC) RDATA Format
+
+Status of this Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2004).
+
+Abstract
+
+ This document redefines the wire format of the "Type Bit Map" field
+ in the DNS NextSECure (NSEC) resource record RDATA format to cover
+ the full resource record (RR) type space.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 2. The NSEC Resource Record . . . . . . . . . . . . . . . . . . . 2
+ 2.1. NSEC RDATA Wire Format . . . . . . . . . . . . . . . . . 3
+ 2.1.1. The Next Domain Name Field . . . . . . . . . . . 3
+ 2.1.2. The List of Type Bit Map(s) Field . . . . . . . 3
+ 2.1.3. Inclusion of Wildcard Names in NSEC RDATA . . . 4
+ 2.2. The NSEC RR Presentation Format . . . . . . . . . . . . 4
+ 2.3. NSEC RR Example . . . . . . . . . . . . . . . . . . . . 5
+ 3. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 5
+ 4. Security Considerations . . . . . . . . . . . . . . . . . . . 5
+ 5. References . . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 5.1. Normative References . . . . . . . . . . . . . . . . . . 6
+ 5.2. Informative References . . . . . . . . . . . . . . . . . 6
+ 6. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 6
+ 7. Author's Address . . . . . . . . . . . . . . . . . . . . . . . 6
+ 8. Full Copyright Statement . . . . . . . . . . . . . . . . . . . 7
+
+
+
+
+
+
+
+Schlyter, Ed. Standards Track [Page 1]
+
+RFC 3845 DNSSEC NSEC RDATA Format August 2004
+
+
+1. Introduction
+
+ The DNS [6][7] NSEC [5] Resource Record (RR) is used for
+ authenticated proof of the non-existence of DNS owner names and
+ types. The NSEC RR is based on the NXT RR as described in RFC 2535
+ [2], and is similar except for the name and typecode. The RDATA
+ format for the NXT RR has the limitation in that the RDATA could only
+ carry information about the existence of the first 127 types. RFC
+ 2535 did reserve a bit to specify an extension mechanism, but the
+ mechanism was never actually defined.
+
+ In order to avoid needing to develop an extension mechanism into a
+ deployed base of DNSSEC aware servers and resolvers once the first
+ 127 type codes are allocated, this document redefines the wire format
+ of the "Type Bit Map" field in the NSEC RDATA to cover the full RR
+ type space.
+
+ This document introduces a new format for the type bit map. The
+ properties of the type bit map format are that it can cover the full
+ possible range of typecodes, that it is relatively economical in the
+ amount of space it uses for the common case of a few types with an
+ owner name, that it can represent owner names with all possible types
+ present in packets of approximately 8.5 kilobytes, and that the
+ representation is simple to implement. Efficient searching of the
+ type bitmap for the presence of certain types is not a requirement.
+
+ For convenience and completeness, this document presents the syntax
+ and semantics for the NSEC RR based on the specification in RFC 2535
+ [2] and as updated by RFC 3755 [5], thereby not introducing changes
+ except for the syntax of the type bit map.
+
+ This document updates RFC 2535 [2] and RFC 3755 [5].
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in BCP 14, RFC 2119 [1].
+
+2. The NSEC Resource Record
+
+ The NSEC resource record lists two separate things: the owner name of
+ the next RRset in the canonical ordering of the zone, and the set of
+ RR types present at the NSEC RR's owner name. The complete set of
+ NSEC RRs in a zone indicate which RRsets exist in a zone, and form a
+ chain of owner names in the zone. This information is used to
+ provide authenticated denial of existence for DNS data, as described
+ in RFC 2535 [2].
+
+ The type value for the NSEC RR is 47.
+
+
+
+Schlyter, Ed. Standards Track [Page 2]
+
+RFC 3845 DNSSEC NSEC RDATA Format August 2004
+
+
+ The NSEC RR RDATA format is class independent and defined for all
+ classes.
+
+ The NSEC RR SHOULD have the same TTL value as the SOA minimum TTL
+ field. This is in the spirit of negative caching [8].
+
+2.1. NSEC RDATA Wire Format
+
+ The RDATA of the NSEC RR is as shown below:
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / Next Domain Name /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / List of Type Bit Map(s) /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+2.1.1. The Next Domain Name Field
+
+ The Next Domain Name field contains the owner name of the next RR in
+ the canonical ordering of the zone. The value of the Next Domain
+ Name field in the last NSEC record in the zone is the name of the
+ zone apex (the owner name of the zone's SOA RR).
+
+ A sender MUST NOT use DNS name compression on the Next Domain Name
+ field when transmitting an NSEC RR.
+
+ Owner names of RRsets that are not authoritative for the given zone
+ (such as glue records) MUST NOT be listed in the Next Domain Name
+ unless at least one authoritative RRset exists at the same owner
+ name.
+
+2.1.2. The List of Type Bit Map(s) Field
+
+ The RR type space is split into 256 window blocks, each representing
+ the low-order 8 bits of the 16-bit RR type space. Each block that
+ has at least one active RR type is encoded using a single octet
+ window number (from 0 to 255), a single octet bitmap length (from 1
+ to 32) indicating the number of octets used for the window block's
+ bitmap, and up to 32 octets (256 bits) of bitmap.
+
+ Window blocks are present in the NSEC RR RDATA in increasing
+ numerical order.
+
+ "|" denotes concatenation
+
+ Type Bit Map(s) Field = ( Window Block # | Bitmap Length | Bitmap ) +
+
+
+
+Schlyter, Ed. Standards Track [Page 3]
+
+RFC 3845 DNSSEC NSEC RDATA Format August 2004
+
+
+ Each bitmap encodes the low-order 8 bits of RR types within the
+ window block, in network bit order. The first bit is bit 0. For
+ window block 0, bit 1 corresponds to RR type 1 (A), bit 2 corresponds
+ to RR type 2 (NS), and so forth. For window block 1, bit 1
+ corresponds to RR type 257, and bit 2 to RR type 258. If a bit is
+ set to 1, it indicates that an RRset of that type is present for the
+ NSEC RR's owner name. If a bit is set to 0, it indicates that no
+ RRset of that type is present for the NSEC RR's owner name.
+
+ Since bit 0 in window block 0 refers to the non-existing RR type 0,
+ it MUST be set to 0. After verification, the validator MUST ignore
+ the value of bit 0 in window block 0.
+
+ Bits representing Meta-TYPEs or QTYPEs, as specified in RFC 2929 [3]
+ (section 3.1), or within the range reserved for assignment only to
+ QTYPEs and Meta-TYPEs MUST be set to 0, since they do not appear in
+ zone data. If encountered, they must be ignored upon reading.
+
+ Blocks with no types present MUST NOT be included. Trailing zero
+ octets in the bitmap MUST be omitted. The length of each block's
+ bitmap is determined by the type code with the largest numerical
+ value within that block, among the set of RR types present at the
+ NSEC RR's owner name. Trailing zero octets not specified MUST be
+ interpreted as zero octets.
+
+2.1.3. Inclusion of Wildcard Names in NSEC RDATA
+
+ If a wildcard owner name appears in a zone, the wildcard label ("*")
+ is treated as a literal symbol and is treated the same as any other
+ owner name for purposes of generating NSEC RRs. Wildcard owner names
+ appear in the Next Domain Name field without any wildcard expansion.
+ RFC 2535 [2] describes the impact of wildcards on authenticated
+ denial of existence.
+
+2.2. The NSEC RR Presentation Format
+
+ The presentation format of the RDATA portion is as follows:
+
+ The Next Domain Name field is represented as a domain name.
+
+ The List of Type Bit Map(s) Field is represented as a sequence of RR
+ type mnemonics. When the mnemonic is not known, the TYPE
+ representation as described in RFC 3597 [4] (section 5) MUST be used.
+
+
+
+
+
+
+
+
+Schlyter, Ed. Standards Track [Page 4]
+
+RFC 3845 DNSSEC NSEC RDATA Format August 2004
+
+
+2.3. NSEC RR Example
+
+ The following NSEC RR identifies the RRsets associated with
+ alfa.example.com. and the next authoritative name after
+ alfa.example.com.
+
+ alfa.example.com. 86400 IN NSEC host.example.com. A MX RRSIG NSEC
+ TYPE1234
+
+ The first four text fields specify the name, TTL, Class, and RR type
+ (NSEC). The entry host.example.com. is the next authoritative name
+ after alfa.example.com. in canonical order. The A, MX, RRSIG, NSEC,
+ and TYPE1234 mnemonics indicate there are A, MX, RRSIG, NSEC, and
+ TYPE1234 RRsets associated with the name alfa.example.com.
+
+ The RDATA section of the NSEC RR above would be encoded as:
+
+ 0x04 'h' 'o' 's' 't'
+ 0x07 'e' 'x' 'a' 'm' 'p' 'l' 'e'
+ 0x03 'c' 'o' 'm' 0x00
+ 0x00 0x06 0x40 0x01 0x00 0x00 0x00 0x03
+ 0x04 0x1b 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x20
+
+ Assuming that the resolver can authenticate this NSEC record, it
+ could be used to prove that beta.example.com does not exist, or could
+ be used to prove that there is no AAAA record associated with
+ alfa.example.com. Authenticated denial of existence is discussed in
+ RFC 2535 [2].
+
+3. IANA Considerations
+
+ This document introduces no new IANA considerations, because all of
+ the protocol parameters used in this document have already been
+ assigned by RFC 3755 [5].
+
+4. Security Considerations
+
+ The update of the RDATA format and encoding does not affect the
+ security of the use of NSEC RRs.
+
+
+
+
+
+
+
+
+
+Schlyter, Ed. Standards Track [Page 5]
+
+RFC 3845 DNSSEC NSEC RDATA Format August 2004
+
+
+5. References
+
+5.1. Normative References
+
+ [1] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [2] Eastlake 3rd, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [3] Eastlake 3rd, D., Brunner-Williams, E., and B. Manning, "Domain
+ Name System (DNS) IANA Considerations", BCP 42, RFC 2929,
+ September 2000.
+
+ [4] Gustafsson, A., "Handling of Unknown DNS Resource Record (RR)
+ Types", RFC 3597, September 2003.
+
+ [5] Weiler, S., "Legacy Resolver Compatibility for Delegation Signer
+ (DS)", RFC 3755, May 2004.
+
+5.2. Informative References
+
+ [6] Mockapetris, P., "Domain names - concepts and facilities", STD
+ 13, RFC 1034, November 1987.
+
+ [7] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [8] Andrews, M., "Negative Caching of DNS Queries (DNS NCACHE)", RFC
+ 2308, March 1998.
+
+6. Acknowledgements
+
+ The encoding described in this document was initially proposed by
+ Mark Andrews. Other encodings where proposed by David Blacka and
+ Michael Graff.
+
+7. Author's Address
+
+ Jakob Schlyter (editor)
+ NIC-SE
+ Box 5774
+ Stockholm SE-114 87
+ Sweden
+
+ EMail: jakob@nic.se
+ URI: http://www.nic.se/
+
+
+
+
+Schlyter, Ed. Standards Track [Page 6]
+
+RFC 3845 DNSSEC NSEC RDATA Format August 2004
+
+
+8. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2004).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/S HE
+ REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE
+ INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the IETF's procedures with respect to rights in IETF Documents can
+ be found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Schlyter, Ed. Standards Track [Page 7]
+
diff --git a/doc/rfc/rfc3901.txt b/doc/rfc/rfc3901.txt
new file mode 100644
index 0000000..43b7356
--- /dev/null
+++ b/doc/rfc/rfc3901.txt
@@ -0,0 +1,283 @@
+
+
+
+
+
+
+Network Working Group A. Durand
+Request for Comments: 3901 SUN Microsystems, Inc.
+BCP: 91 J. Ihren
+Category: Best Current Practice Autonomica
+ September 2004
+
+
+ DNS IPv6 Transport Operational Guidelines
+
+Status of this Memo
+
+ This document specifies an Internet Best Current Practices for the
+ Internet Community, and requests discussion and suggestions for
+ improvements. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2004).
+
+Abstract
+
+ This memo provides guidelines and Best Current Practice for operating
+ DNS in a world where queries and responses are carried in a mixed
+ environment of IPv4 and IPv6 networks.
+
+1. Introduction to the Problem of Name Space Fragmentation:
+ following the referral chain
+
+ A resolver that tries to look up a name starts out at the root, and
+ follows referrals until it is referred to a name server that is
+ authoritative for the name. If somewhere down the chain of referrals
+ it is referred to a name server that is only accessible over a
+ transport which the resolver cannot use, the resolver is unable to
+ finish the task.
+
+ When the Internet moves from IPv4 to a mixture of IPv4 and IPv6 it is
+ only a matter of time until this starts to happen. The complete DNS
+ hierarchy then starts to fragment into a graph where authoritative
+ name servers for certain nodes are only accessible over a certain
+ transport. The concern is that a resolver using only a particular
+ version of IP and querying information about another node using the
+ same version of IP can not do it because somewhere in the chain of
+ servers accessed during the resolution process, one or more of them
+ will only be accessible with the other version of IP.
+
+ With all DNS data only available over IPv4 transport everything is
+ simple. IPv4 resolvers can use the intended mechanism of following
+ referrals from the root and down while IPv6 resolvers have to work
+
+
+
+Durand & Ihren Best Current Practice [Page 1]
+
+RFC 3901 DNS IPv6 Transport Guidelines September 2004
+
+
+ through a "translator", i.e., they have to use a recursive name
+ server on a so-called "dual stack" host as a "forwarder" since they
+ cannot access the DNS data directly.
+
+ With all DNS data only available over IPv6 transport everything would
+ be equally simple, with the exception of IPv4 recursive name servers
+ having to switch to a forwarding configuration.
+
+ However, the second situation will not arise in the foreseeable
+ future. Instead, the transition will be from IPv4 only to a mixture
+ of IPv4 and IPv6, with three categories of DNS data depending on
+ whether the information is available only over IPv4 transport, only
+ over IPv6 or both.
+
+ Having DNS data available on both transports is the best situation.
+ The major question is how to ensure that it becomes the norm as
+ quickly as possible. However, while it is obvious that some DNS data
+ will only be available over v4 transport for a long time it is also
+ obvious that it is important to avoid fragmenting the name space
+ available to IPv4 only hosts. For example, during transition it is
+ not acceptable to break the name space that we presently have
+ available for IPv4-only hosts.
+
+2. Terminology
+
+ The phrase "IPv4 name server" indicates a name server available over
+ IPv4 transport. It does not imply anything about what DNS [1,2] data
+ is served. Likewise, "IPv6 [4,5,6] name server" indicates a name
+ server available over IPv6 transport. The phrase "dual-stack name
+ server" indicates a name server that is actually configured to run
+ both protocols, IPv4 and IPv6, and not merely a server running on a
+ system capable of running both but actually configured to run only
+ one.
+
+3. Policy Based Avoidance of Name Space Fragmentation
+
+ Today there are only a few DNS "zones" on the public Internet that
+ are available over IPv6 transport, and most of them can be regarded
+ as "experimental". However, as soon as the root and top level
+ domains are available over IPv6 transport, it is reasonable to expect
+ that it will become more common to have zones served by IPv6 servers.
+
+ Having those zones served only by IPv6-only name server would not be
+ a good development, since this will fragment the previously
+ unfragmented IPv4 name space and there are strong reasons to find a
+ mechanism to avoid it.
+
+
+
+
+
+Durand & Ihren Best Current Practice [Page 2]
+
+RFC 3901 DNS IPv6 Transport Guidelines September 2004
+
+
+ The recommended approach to maintain name space continuity is to use
+ administrative policies, as described in the next section.
+
+4. DNS IPv6 Transport recommended Guidelines
+
+ In order to preserve name space continuity, the following
+ administrative policies are recommended:
+
+ - every recursive name server SHOULD be either IPv4-only or dual
+ stack,
+
+ This rules out IPv6-only recursive servers. However, one might
+ design configurations where a chain of IPv6-only name server
+ forward queries to a set of dual stack recursive name server
+ actually performing those recursive queries.
+
+ - every DNS zone SHOULD be served by at least one IPv4-reachable
+ authoritative name server.
+
+ This rules out DNS zones served only by IPv6-only authoritative
+ name servers.
+
+ Note: zone validation processes SHOULD ensure that there is at least
+ one IPv4 address record available for the name servers of any child
+ delegations within the zone.
+
+5. Security Considerations
+
+ The guidelines described in this memo introduce no new security
+ considerations into the DNS protocol or associated operational
+ scenarios.
+
+6. Acknowledgment
+
+ This document is the result of many conversations that happened in
+ the DNS community at IETF and elsewhere since 2001. During that
+ period of time, a number of Internet drafts have been published to
+ clarify various aspects of the issues at stake. This document
+ focuses on the conclusion of those discussions.
+
+ The authors would like to acknowledge the role of Pekka Savola in his
+ thorough review of the document.
+
+
+
+
+
+
+
+
+
+Durand & Ihren Best Current Practice [Page 3]
+
+RFC 3901 DNS IPv6 Transport Guidelines September 2004
+
+
+7. Normative References
+
+ [1] Mockapetris, P., "Domain names - concepts and facilities", STD
+ 13, RFC 1034, November 1987.
+
+ [2] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [3] Bradner, S., "The Internet Standards Process -- Revision 3", BCP
+ 9, RFC 2026, October 1996.
+
+ [4] Deering, S. and R. Hinden, "Internet Protocol, Version 6 (IPv6)
+ Specification", RFC 2460, December 1998.
+
+ [5] Hinden, R. and S. Deering, "Internet Protocol Version 6 (IPv6)
+ Addressing Architecture", RFC 3513, April 2003.
+
+ [6] Thomson, S., Huitema, C., Ksinant, V., and M. Souissi, "DNS
+ Extensions to Support IP Version 6", RFC 3596, October 2003.
+
+8. Authors' Addresses
+
+ Alain Durand
+ SUN Microsystems, Inc
+ 17 Network circle UMPK17-202
+ Menlo Park, CA, 94025
+ USA
+
+ EMail: Alain.Durand@sun.com
+
+
+ Johan Ihren
+ Autonomica
+ Bellmansgatan 30
+ SE-118 47 Stockholm
+ Sweden
+
+ EMail: johani@autonomica.se
+
+
+
+
+
+
+
+
+
+
+
+
+
+Durand & Ihren Best Current Practice [Page 4]
+
+RFC 3901 DNS IPv6 Transport Guidelines September 2004
+
+
+9. Full Copyright Statement
+
+ Copyright (C) The Internet Society (2004).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/S HE
+ REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE
+ INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the IETF's procedures with respect to rights in IETF Documents can
+ be found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Durand & Ihren Best Current Practice [Page 5]
+
diff --git a/doc/rfc/rfc4025.txt b/doc/rfc/rfc4025.txt
new file mode 100644
index 0000000..92e7f40
--- /dev/null
+++ b/doc/rfc/rfc4025.txt
@@ -0,0 +1,675 @@
+
+
+
+
+
+
+Network Working Group M. Richardson
+Request for Comments: 4025 SSW
+Category: Standards Track February 2005
+
+
+ A Method for Storing IPsec Keying Material in DNS
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document describes a new resource record for the Domain Name
+ System (DNS). This record may be used to store public keys for use
+ in IP security (IPsec) systems. The record also includes provisions
+ for indicating what system should be contacted when an IPsec tunnel
+ is established with the entity in question.
+
+ This record replaces the functionality of the sub-type #4 of the KEY
+ Resource Record, which has been obsoleted by RFC 3445.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 1.1. Overview . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 1.2. Use of DNS Address-to-Name Maps (IN-ADDR.ARPA and
+ IP6.ARPA) . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.3. Usage Criteria . . . . . . . . . . . . . . . . . . . . . 3
+ 2. Storage Formats . . . . . . . . . . . . . . . . . . . . . . . 3
+ 2.1. IPSECKEY RDATA Format . . . . . . . . . . . . . . . . . 3
+ 2.2. RDATA Format - Precedence . . . . . . . . . . . . . . . 4
+ 2.3. RDATA Format - Gateway Type . . . . . . . . . . . . . . 4
+ 2.4. RDATA Format - Algorithm Type . . . . . . . . . . . . . 4
+ 2.5. RDATA Format - Gateway . . . . . . . . . . . . . . . . . 5
+ 2.6. RDATA Format - Public Keys . . . . . . . . . . . . . . . 5
+ 3. Presentation Formats . . . . . . . . . . . . . . . . . . . . . 6
+ 3.1. Representation of IPSECKEY RRs . . . . . . . . . . . . . 6
+ 3.2. Examples . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 4. Security Considerations . . . . . . . . . . . . . . . . . . . 7
+
+
+
+Richardson Standards Track [Page 1]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+ 4.1. Active Attacks Against Unsecured IPSECKEY Resource
+ Records . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 4.1.1. Active Attacks Against IPSECKEY Keying
+ Materials. . . . . . . . . . . . . . . . . . . . 8
+ 4.1.2. Active Attacks Against IPSECKEY Gateway
+ Material. . . . . . . . . . . . . . . . . . . . 8
+ 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 9
+ 6. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 10
+ 7. References . . . . . . . . . . . . . . . . . . . . . . . . . . 10
+ 7.1. Normative References . . . . . . . . . . . . . . . . . . 10
+ 7.2. Informative References . . . . . . . . . . . . . . . . . 10
+ Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 12
+
+1. Introduction
+
+ Suppose a host wishes (or is required by policy) to establish an
+ IPsec tunnel with some remote entity on the network prior to allowing
+ normal communication to take place. In many cases, this end system
+ will be able to determine the DNS name for the remote entity (either
+ by having the DNS name given explicitly, by performing a DNS PTR
+ query for a particular IP address, or through some other means, e.g.,
+ by extracting the DNS portion of a "user@FQDN" name for a remote
+ entity). In these cases, the host will need to obtain a public key
+ to authenticate the remote entity, and may also need some guidance
+ about whether it should contact the entity directly or use another
+ node as a gateway to the target entity. The IPSECKEY RR provides a
+ mechanism for storing such information.
+
+ The type number for the IPSECKEY RR is 45.
+
+ This record replaces the functionality of the sub-type #4 of the KEY
+ Resource Record, which has been obsoleted by RFC 3445 [11].
+
+1.1. Overview
+
+ The IPSECKEY resource record (RR) is used to publish a public key
+ that is to be associated with a Domain Name System (DNS) [1] name for
+ use with the IPsec protocol suite. This can be the public key of a
+ host, network, or application (in the case of per-port keying).
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [3].
+
+
+
+
+
+
+
+Richardson Standards Track [Page 2]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+1.2. Use of DNS Address-to-Name Maps (IN-ADDR.ARPA and IP6.ARPA)
+
+ Often a security gateway will only have access to the IP address of
+ the node with which communication is desired and will not know any
+ other name for the target node. Because of this, frequently the best
+ way of looking up IPSECKEY RRs will be by using the IP address as an
+ index into one of the reverse mapping trees (IN-ADDR.ARPA for IPv4 or
+ IP6.ARPA for IPv6).
+
+ The lookup is done in the fashion usual for PTR records. The IP
+ address' octets (IPv4) or nibbles (IPv6) are reversed and looked up
+ with the appropriate suffix. Any CNAMEs or DNAMEs found MUST be
+ followed.
+
+ Note: even when the IPsec function is contained in the end-host,
+ often only the application will know the forward name used. Although
+ the case where the application knows the forward name is common, the
+ user could easily have typed in a literal IP address. This storage
+ mechanism does not preclude using the forward name when it is
+ available but does not require it.
+
+1.3. Usage Criteria
+
+ An IPSECKEY resource record SHOULD be used in combination with DNSSEC
+ [8] unless some other means of authenticating the IPSECKEY resource
+ record is available.
+
+ It is expected that there will often be multiple IPSECKEY resource
+ records at the same name. This will be due to the presence of
+ multiple gateways and a need to roll over keys.
+
+ This resource record is class independent.
+
+2. Storage Formats
+
+2.1. IPSECKEY RDATA Format
+
+ The RDATA for an IPSECKEY RR consists of a precedence value, a
+ gateway type, a public key, algorithm type, and an optional gateway
+ address.
+
+
+
+
+
+
+
+
+
+
+
+Richardson Standards Track [Page 3]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | precedence | gateway type | algorithm | gateway |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------+ +
+ ~ gateway ~
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | /
+ / public key /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+
+2.2. RDATA Format - Precedence
+
+ This is an 8-bit precedence for this record. It is interpreted in
+ the same way as the PREFERENCE field described in section 3.3.9 of
+ RFC 1035 [2].
+
+ Gateways listed in IPSECKEY records with lower precedence are to be
+ attempted first. Where there is a tie in precedence, the order
+ should be non-deterministic.
+
+2.3. RDATA Format - Gateway Type
+
+ The gateway type field indicates the format of the information that
+ is stored in the gateway field.
+
+ The following values are defined:
+ 0 No gateway is present.
+ 1 A 4-byte IPv4 address is present.
+ 2 A 16-byte IPv6 address is present.
+ 3 A wire-encoded domain name is present. The wire-encoded format is
+ self-describing, so the length is implicit. The domain name MUST
+ NOT be compressed. (See Section 3.3 of RFC 1035 [2].)
+
+2.4. RDATA Format - Algorithm Type
+
+ The algorithm type field identifies the public key's cryptographic
+ algorithm and determines the format of the public key field.
+
+ A value of 0 indicates that no key is present.
+
+ The following values are defined:
+ 1 A DSA key is present, in the format defined in RFC 2536 [9].
+ 2 A RSA key is present, in the format defined in RFC 3110 [10].
+
+
+
+
+
+
+Richardson Standards Track [Page 4]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+2.5. RDATA Format - Gateway
+
+ The gateway field indicates a gateway to which an IPsec tunnel may be
+ created in order to reach the entity named by this resource record.
+
+ There are three formats:
+
+ A 32-bit IPv4 address is present in the gateway field. The data
+ portion is an IPv4 address as described in section 3.4.1 of RFC 1035
+ [2]. This is a 32-bit number in network byte order.
+
+ A 128-bit IPv6 address is present in the gateway field. The data
+ portion is an IPv6 address as described in section 2.2 of RFC 3596
+ [12]. This is a 128-bit number in network byte order.
+
+ The gateway field is a normal wire-encoded domain name, as described
+ in section 3.3 of RFC 1035 [2]. Compression MUST NOT be used.
+
+2.6. RDATA Format - Public Keys
+
+ Both the public key types defined in this document (RSA and DSA)
+ inherit their public key formats from the corresponding KEY RR
+ formats. Specifically, the public key field contains the
+ algorithm-specific portion of the KEY RR RDATA, which is all the KEY
+ RR DATA after the first four octets. This is the same portion of the
+ KEY RR that must be specified by documents that define a DNSSEC
+ algorithm. Those documents also specify a message digest to be used
+ for generation of SIG RRs; that specification is not relevant for
+ IPSECKEY RRs.
+
+ Future algorithms, if they are to be used by both DNSSEC (in the KEY
+ RR) and IPSECKEY, are likely to use the same public key encodings in
+ both records. Unless otherwise specified, the IPSECKEY public key
+ field will contain the algorithm-specific portion of the KEY RR RDATA
+ for the corresponding algorithm. The algorithm must still be
+ designated for use by IPSECKEY, and an IPSECKEY algorithm type number
+ (which might be different from the DNSSEC algorithm number) must be
+ assigned to it.
+
+ The DSA key format is defined in RFC 2536 [9]
+
+ The RSA key format is defined in RFC 3110 [10], with the following
+ changes:
+
+ The earlier definition of RSA/MD5 in RFC 2065 [4] limited the
+ exponent and modulus to 2552 bits in length. RFC 3110 extended that
+ limit to 4096 bits for RSA/SHA1 keys. The IPSECKEY RR imposes no
+ length limit on RSA public keys, other than the 65535 octet limit
+
+
+
+Richardson Standards Track [Page 5]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+ imposed by the two-octet length encoding. This length extension is
+ applicable only to IPSECKEY; it is not applicable to KEY RRs.
+
+3. Presentation Formats
+
+3.1. Representation of IPSECKEY RRs
+
+ IPSECKEY RRs may appear in a zone data master file. The precedence,
+ gateway type, algorithm, and gateway fields are REQUIRED. The base64
+ encoded public key block is OPTIONAL; if it is not present, the
+ public key field of the resource record MUST be construed to be zero
+ octets in length.
+
+ The algorithm field is an unsigned integer. No mnemonics are
+ defined.
+
+ If no gateway is to be indicated, then the gateway type field MUST be
+ zero, and the gateway field MUST be "."
+
+ The Public Key field is represented as a Base64 encoding of the
+ Public Key. Whitespace is allowed within the Base64 text. For a
+ definition of Base64 encoding, see RFC 3548 [6], Section 5.2.
+
+ The general presentation for the record is as follows:
+
+ IN IPSECKEY ( precedence gateway-type algorithm
+ gateway base64-encoded-public-key )
+
+3.2. Examples
+
+ An example of a node, 192.0.2.38, that will accept IPsec tunnels on
+ its own behalf.
+
+ 38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 1 2
+ 192.0.2.38
+ AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )
+
+ An example of a node, 192.0.2.38, that has published its key only.
+
+ 38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 0 2
+ .
+ AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )
+
+
+
+
+
+
+
+
+
+Richardson Standards Track [Page 6]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+ An example of a node, 192.0.2.38, that has delegated authority to the
+ node 192.0.2.3.
+
+ 38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 1 2
+ 192.0.2.3
+ AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )
+
+ An example of a node, 192.0.1.38 that has delegated authority to the
+ node with the identity "mygateway.example.com".
+
+ 38.1.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 3 2
+ mygateway.example.com.
+ AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )
+
+ An example of a node, 2001:0DB8:0200:1:210:f3ff:fe03:4d0, that has
+ delegated authority to the node 2001:0DB8:c000:0200:2::1
+
+ $ORIGIN 1.0.0.0.0.0.2.8.B.D.0.1.0.0.2.ip6.arpa.
+ 0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0 7200 IN IPSECKEY ( 10 2 2
+ 2001:0DB8:0:8002::2000:1
+ AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )
+
+4. Security Considerations
+
+ This entire memo pertains to the provision of public keying material
+ for use by key management protocols such as ISAKMP/IKE (RFC 2407)
+ [7].
+
+ The IPSECKEY resource record contains information that SHOULD be
+ communicated to the end client in an integral fashion; i.e., free
+ from modification. The form of this channel is up to the consumer of
+ the data; there must be a trust relationship between the end consumer
+ of this resource record and the server. This relationship may be
+ end-to-end DNSSEC validation, a TSIG or SIG(0) channel to another
+ secure source, a secure local channel on the host, or some
+ combination of the above.
+
+ The keying material provided by the IPSECKEY resource record is not
+ sensitive to passive attacks. The keying material may be freely
+ disclosed to any party without any impact on the security properties
+ of the resulting IPsec session. IPsec and IKE provide defense
+ against both active and passive attacks.
+
+ Any derivative specification that makes use of this resource record
+ MUST carefully document its trust model and why the trust model of
+ DNSSEC is appropriate, if that is the secure channel used.
+
+
+
+
+
+Richardson Standards Track [Page 7]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+ An active attack on the DNS that caused the wrong IP address to be
+ retrieved (via forged address), and therefore the wrong QNAME to be
+ queried, would also result in a man-in-the-middle attack. This
+ situation is independent of whether the IPSECKEY RR is used.
+
+4.1. Active Attacks Against Unsecured IPSECKEY Resource Records
+
+ This section deals with active attacks against the DNS. These
+ attacks require that DNS requests and responses be intercepted and
+ changed. DNSSEC is designed to defend against attacks of this kind.
+ This section deals with the situation in which DNSSEC is not
+ available. This is not the recommended deployment scenario.
+
+4.1.1. Active Attacks Against IPSECKEY Keying Materials
+
+ The first kind of active attack is when the attacker replaces the
+ keying material with either a key under its control or with garbage.
+
+ The gateway field is either untouched or is null. The IKE
+ negotiation will therefore occur with the original end-system. For
+ this attack to succeed, the attacker must perform a man-in-the-middle
+ attack on the IKE negotiation. This attack requires that the
+ attacker be able to intercept and modify packets on the forwarding
+ path for the IKE and data packets.
+
+ If the attacker is not able to perform this man-in-the-middle attack
+ on the IKE negotiation, then a denial of service will result, as the
+ IKE negotiation will fail.
+
+ If the attacker is not only able to mount active attacks against DNS
+ but also in a position to perform a man-in-the-middle attack on IKE
+ and IPsec negotiations, then the attacker will be able to compromise
+ the resulting IPsec channel. Note that an attacker must be able to
+ perform active DNS attacks on both sides of the IKE negotiation for
+ this to succeed.
+
+4.1.2. Active Attacks Against IPSECKEY Gateway Material
+
+ The second kind of active attack is one in which the attacker
+ replaces the gateway address to point to a node under the attacker's
+ control. The attacker then either replaces the public key or removes
+ it. If the public key were removed, then the attacker could provide
+ an accurate public key of its own in a second record.
+
+ This second form creates a simple man-in-the-middle attacks since the
+ attacker can then create a second tunnel to the real destination.
+ Note that, as before, this requires that the attacker also mount an
+ active attack against the responder.
+
+
+
+Richardson Standards Track [Page 8]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+ Note that the man-in-the-middle cannot just forward cleartext packets
+ to the original destination. While the destination may be willing to
+ speak in the clear, replying to the original sender, the sender will
+ already have created a policy expecting ciphertext. Thus, the
+ attacker will need to intercept traffic in both directions. In some
+ cases, the attacker may be able to accomplish the full intercept by
+ use of Network Address/Port Translation (NAT/NAPT) technology.
+
+ This attack is easier than the first one because the attacker does
+ NOT need to be on the end-to-end forwarding path. The attacker need
+ only be able to modify DNS replies. This can be done by packet
+ modification, by various kinds of race attacks, or through methods
+ that pollute DNS caches.
+
+ If the end-to-end integrity of the IPSECKEY RR is suspect, the end
+ client MUST restrict its use of the IPSECKEY RR to cases where the RR
+ owner name matches the content of the gateway field. As the RR owner
+ name is assumed when the gateway field is null, a null gateway field
+ is considered a match.
+
+ Thus, any records obtained under unverified conditions (e.g., no
+ DNSSEC or trusted path to source) that have a non-null gateway field
+ MUST be ignored.
+
+ This restriction eliminates attacks against the gateway field, which
+ are considered much easier, as the attack does not need to be on the
+ forwarding path.
+
+ In the case of an IPSECKEY RR with a value of three in its gateway
+ type field, the gateway field contains a domain name. The subsequent
+ query required to translate that name into an IP address or IPSECKEY
+ RR will also be subject to man-in-the-middle attacks. If the
+ end-to-end integrity of this second query is suspect, then the
+ provisions above also apply. The IPSECKEY RR MUST be ignored
+ whenever the resulting gateway does not match the QNAME of the
+ original IPSECKEY RR query.
+
+5. IANA Considerations
+
+ This document updates the IANA Registry for DNS Resource Record Types
+ by assigning type 45 to the IPSECKEY record.
+
+ This document creates two new IANA registries, both specific to the
+ IPSECKEY Resource Record:
+
+ This document creates an IANA registry for the algorithm type field.
+
+
+
+
+
+Richardson Standards Track [Page 9]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+ Values 0, 1, and 2 are defined in Section 2.4. Algorithm numbers 3
+ through 255 can be assigned by IETF Consensus (see RFC 2434 [5]).
+
+ This document creates an IANA registry for the gateway type field.
+
+ Values 0, 1, 2, and 3 are defined in Section 2.3. Gateway type
+ numbers 4 through 255 can be assigned by Standards Action (see RFC
+ 2434 [5]).
+
+6. Acknowledgements
+
+ My thanks to Paul Hoffman, Sam Weiler, Jean-Jacques Puig, Rob
+ Austein, and Olafur Gudmundsson, who reviewed this document
+ carefully. Additional thanks to Olafur Gurmundsson for a reference
+ implementation.
+
+7. References
+
+7.1. Normative References
+
+ [1] Mockapetris, P., "Domain names - concepts and facilities", STD
+ 13, RFC 1034, November 1987.
+
+ [2] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [3] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [4] Eastlake 3rd, D. and C. Kaufman, "Domain Name System Security
+ Extensions", RFC 2065, January 1997.
+
+ [5] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA
+ Considerations Section in RFCs", BCP 26, RFC 2434, October 1998.
+
+ [6] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings",
+ RFC 3548, July 2003.
+
+7.2. Informative References
+
+ [7] Piper, D., "The Internet IP Security Domain of Interpretation
+ for ISAKMP", RFC 2407, November 1998.
+
+ [8] Eastlake 3rd, D., "Domain Name System Security Extensions", RFC
+ 2535, March 1999.
+
+ [9] Eastlake 3rd, D., "DSA KEYs and SIGs in the Domain Name System
+ (DNS)", RFC 2536, March 1999.
+
+
+
+Richardson Standards Track [Page 10]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+ [10] Eastlake 3rd, D., "RSA/SHA-1 SIGs and RSA KEYs in the Domain
+ Name System (DNS)", RFC 3110, May 2001.
+
+ [11] Massey, D. and S. Rose, "Limiting the Scope of the KEY Resource
+ Record (RR)", RFC 3445, December 2002.
+
+ [12] Thomson, S., Huitema, C., Ksinant, V., and M. Souissi, "DNS
+ Extensions to Support IP Version 6", RFC 3596, October 2003.
+
+Author's Address
+
+ Michael C. Richardson
+ Sandelman Software Works
+ 470 Dawson Avenue
+ Ottawa, ON K1Z 5V7
+ CA
+
+ EMail: mcr@sandelman.ottawa.on.ca
+ URI: http://www.sandelman.ottawa.on.ca/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Richardson Standards Track [Page 11]
+
+RFC 4025 Storing IPsec Keying Material in DNS February 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the IETF's procedures with respect to rights in IETF Documents can
+ be found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Richardson Standards Track [Page 12]
+
diff --git a/doc/rfc/rfc4033.txt b/doc/rfc/rfc4033.txt
new file mode 100644
index 0000000..7f0a464
--- /dev/null
+++ b/doc/rfc/rfc4033.txt
@@ -0,0 +1,1179 @@
+
+
+
+
+
+
+Network Working Group R. Arends
+Request for Comments: 4033 Telematica Instituut
+Obsoletes: 2535, 3008, 3090, 3445, 3655, 3658, R. Austein
+ 3755, 3757, 3845 ISC
+Updates: 1034, 1035, 2136, 2181, 2308, 3225, M. Larson
+ 3007, 3597, 3226 VeriSign
+Category: Standards Track D. Massey
+ Colorado State University
+ S. Rose
+ NIST
+ March 2005
+
+
+ DNS Security Introduction and Requirements
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ The Domain Name System Security Extensions (DNSSEC) add data origin
+ authentication and data integrity to the Domain Name System. This
+ document introduces these extensions and describes their capabilities
+ and limitations. This document also discusses the services that the
+ DNS security extensions do and do not provide. Last, this document
+ describes the interrelationships between the documents that
+ collectively describe DNSSEC.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 1]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 2. Definitions of Important DNSSEC Terms . . . . . . . . . . . 3
+ 3. Services Provided by DNS Security . . . . . . . . . . . . . 7
+ 3.1. Data Origin Authentication and Data Integrity . . . . 7
+ 3.2. Authenticating Name and Type Non-Existence . . . . . . 9
+ 4. Services Not Provided by DNS Security . . . . . . . . . . . 9
+ 5. Scope of the DNSSEC Document Set and Last Hop Issues . . . . 9
+ 6. Resolver Considerations . . . . . . . . . . . . . . . . . . 10
+ 7. Stub Resolver Considerations . . . . . . . . . . . . . . . . 11
+ 8. Zone Considerations . . . . . . . . . . . . . . . . . . . . 12
+ 8.1. TTL Values vs. RRSIG Validity Period . . . . . . . . . 13
+ 8.2. New Temporal Dependency Issues for Zones . . . . . . . 13
+ 9. Name Server Considerations . . . . . . . . . . . . . . . . . 13
+ 10. DNS Security Document Family . . . . . . . . . . . . . . . . 14
+ 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . 15
+ 12. Security Considerations . . . . . . . . . . . . . . . . . . 15
+ 13. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 17
+ 14. References . . . . . . . . . . . . . . . . . . . . . . . . . 17
+ 14.1. Normative References . . . . . . . . . . . . . . . . . 17
+ 14.2. Informative References . . . . . . . . . . . . . . . . 18
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 20
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . 21
+
+1. Introduction
+
+ This document introduces the Domain Name System Security Extensions
+ (DNSSEC). This document and its two companion documents ([RFC4034]
+ and [RFC4035]) update, clarify, and refine the security extensions
+ defined in [RFC2535] and its predecessors. These security extensions
+ consist of a set of new resource record types and modifications to
+ the existing DNS protocol ([RFC1035]). The new records and protocol
+ modifications are not fully described in this document, but are
+ described in a family of documents outlined in Section 10. Sections
+ 3 and 4 describe the capabilities and limitations of the security
+ extensions in greater detail. Section 5 discusses the scope of the
+ document set. Sections 6, 7, 8, and 9 discuss the effect that these
+ security extensions will have on resolvers, stub resolvers, zones,
+ and name servers.
+
+ This document and its two companions obsolete [RFC2535], [RFC3008],
+ [RFC3090], [RFC3445], [RFC3655], [RFC3658], [RFC3755], [RFC3757], and
+ [RFC3845]. This document set also updates but does not obsolete
+ [RFC1034], [RFC1035], [RFC2136], [RFC2181], [RFC2308], [RFC3225],
+ [RFC3007], [RFC3597], and the portions of [RFC3226] that deal with
+ DNSSEC.
+
+
+
+
+Arends, et al. Standards Track [Page 2]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ The DNS security extensions provide origin authentication and
+ integrity protection for DNS data, as well as a means of public key
+ distribution. These extensions do not provide confidentiality.
+
+2. Definitions of Important DNSSEC Terms
+
+ This section defines a number of terms used in this document set.
+ Because this is intended to be useful as a reference while reading
+ the rest of the document set, first-time readers may wish to skim
+ this section quickly, read the rest of this document, and then come
+ back to this section.
+
+ Authentication Chain: An alternating sequence of DNS public key
+ (DNSKEY) RRsets and Delegation Signer (DS) RRsets forms a chain of
+ signed data, with each link in the chain vouching for the next. A
+ DNSKEY RR is used to verify the signature covering a DS RR and
+ allows the DS RR to be authenticated. The DS RR contains a hash
+ of another DNSKEY RR and this new DNSKEY RR is authenticated by
+ matching the hash in the DS RR. This new DNSKEY RR in turn
+ authenticates another DNSKEY RRset and, in turn, some DNSKEY RR in
+ this set may be used to authenticate another DS RR, and so forth
+ until the chain finally ends with a DNSKEY RR whose corresponding
+ private key signs the desired DNS data. For example, the root
+ DNSKEY RRset can be used to authenticate the DS RRset for
+ "example." The "example." DS RRset contains a hash that matches
+ some "example." DNSKEY, and this DNSKEY's corresponding private
+ key signs the "example." DNSKEY RRset. Private key counterparts
+ of the "example." DNSKEY RRset sign data records such as
+ "www.example." and DS RRs for delegations such as
+ "subzone.example."
+
+ Authentication Key: A public key that a security-aware resolver has
+ verified and can therefore use to authenticate data. A
+ security-aware resolver can obtain authentication keys in three
+ ways. First, the resolver is generally configured to know about
+ at least one public key; this configured data is usually either
+ the public key itself or a hash of the public key as found in the
+ DS RR (see "trust anchor"). Second, the resolver may use an
+ authenticated public key to verify a DS RR and the DNSKEY RR to
+ which the DS RR refers. Third, the resolver may be able to
+ determine that a new public key has been signed by the private key
+ corresponding to another public key that the resolver has
+ verified. Note that the resolver must always be guided by local
+ policy when deciding whether to authenticate a new public key,
+ even if the local policy is simply to authenticate any new public
+ key for which the resolver is able verify the signature.
+
+
+
+
+
+Arends, et al. Standards Track [Page 3]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ Authoritative RRset: Within the context of a particular zone, an
+ RRset is "authoritative" if and only if the owner name of the
+ RRset lies within the subset of the name space that is at or below
+ the zone apex and at or above the cuts that separate the zone from
+ its children, if any. All RRsets at the zone apex are
+ authoritative, except for certain RRsets at this domain name that,
+ if present, belong to this zone's parent. These RRset could
+ include a DS RRset, the NSEC RRset referencing this DS RRset (the
+ "parental NSEC"), and RRSIG RRs associated with these RRsets, all
+ of which are authoritative in the parent zone. Similarly, if this
+ zone contains any delegation points, only the parental NSEC RRset,
+ DS RRsets, and any RRSIG RRs associated with these RRsets are
+ authoritative for this zone.
+
+ Delegation Point: Term used to describe the name at the parental side
+ of a zone cut. That is, the delegation point for "foo.example"
+ would be the foo.example node in the "example" zone (as opposed to
+ the zone apex of the "foo.example" zone). See also zone apex.
+
+ Island of Security: Term used to describe a signed, delegated zone
+ that does not have an authentication chain from its delegating
+ parent. That is, there is no DS RR containing a hash of a DNSKEY
+ RR for the island in its delegating parent zone (see [RFC4034]).
+ An island of security is served by security-aware name servers and
+ may provide authentication chains to any delegated child zones.
+ Responses from an island of security or its descendents can only
+ be authenticated if its authentication keys can be authenticated
+ by some trusted means out of band from the DNS protocol.
+
+ Key Signing Key (KSK): An authentication key that corresponds to a
+ private key used to sign one or more other authentication keys for
+ a given zone. Typically, the private key corresponding to a key
+ signing key will sign a zone signing key, which in turn has a
+ corresponding private key that will sign other zone data. Local
+ policy may require that the zone signing key be changed
+ frequently, while the key signing key may have a longer validity
+ period in order to provide a more stable secure entry point into
+ the zone. Designating an authentication key as a key signing key
+ is purely an operational issue: DNSSEC validation does not
+ distinguish between key signing keys and other DNSSEC
+ authentication keys, and it is possible to use a single key as
+ both a key signing key and a zone signing key. Key signing keys
+ are discussed in more detail in [RFC3757]. Also see zone signing
+ key.
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 4]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ Non-Validating Security-Aware Stub Resolver: A security-aware stub
+ resolver that trusts one or more security-aware recursive name
+ servers to perform most of the tasks discussed in this document
+ set on its behalf. In particular, a non-validating security-aware
+ stub resolver is an entity that sends DNS queries, receives DNS
+ responses, and is capable of establishing an appropriately secured
+ channel to a security-aware recursive name server that will
+ provide these services on behalf of the security-aware stub
+ resolver. See also security-aware stub resolver, validating
+ security-aware stub resolver.
+
+ Non-Validating Stub Resolver: A less tedious term for a
+ non-validating security-aware stub resolver.
+
+ Security-Aware Name Server: An entity acting in the role of a name
+ server (defined in section 2.4 of [RFC1034]) that understands the
+ DNS security extensions defined in this document set. In
+ particular, a security-aware name server is an entity that
+ receives DNS queries, sends DNS responses, supports the EDNS0
+ ([RFC2671]) message size extension and the DO bit ([RFC3225]), and
+ supports the RR types and message header bits defined in this
+ document set.
+
+ Security-Aware Recursive Name Server: An entity that acts in both the
+ security-aware name server and security-aware resolver roles. A
+ more cumbersome but equivalent phrase would be "a security-aware
+ name server that offers recursive service".
+
+ Security-Aware Resolver: An entity acting in the role of a resolver
+ (defined in section 2.4 of [RFC1034]) that understands the DNS
+ security extensions defined in this document set. In particular,
+ a security-aware resolver is an entity that sends DNS queries,
+ receives DNS responses, supports the EDNS0 ([RFC2671]) message
+ size extension and the DO bit ([RFC3225]), and is capable of using
+ the RR types and message header bits defined in this document set
+ to provide DNSSEC services.
+
+ Security-Aware Stub Resolver: An entity acting in the role of a stub
+ resolver (defined in section 5.3.1 of [RFC1034]) that has enough
+ of an understanding the DNS security extensions defined in this
+ document set to provide additional services not available from a
+ security-oblivious stub resolver. Security-aware stub resolvers
+ may be either "validating" or "non-validating", depending on
+ whether the stub resolver attempts to verify DNSSEC signatures on
+ its own or trusts a friendly security-aware name server to do so.
+ See also validating stub resolver, non-validating stub resolver.
+
+
+
+
+
+Arends, et al. Standards Track [Page 5]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ Security-Oblivious <anything>: An <anything> that is not
+ "security-aware".
+
+ Signed Zone: A zone whose RRsets are signed and that contains
+ properly constructed DNSKEY, Resource Record Signature (RRSIG),
+ Next Secure (NSEC), and (optionally) DS records.
+
+ Trust Anchor: A configured DNSKEY RR or DS RR hash of a DNSKEY RR. A
+ validating security-aware resolver uses this public key or hash as
+ a starting point for building the authentication chain to a signed
+ DNS response. In general, a validating resolver will have to
+ obtain the initial values of its trust anchors via some secure or
+ trusted means outside the DNS protocol. Presence of a trust
+ anchor also implies that the resolver should expect the zone to
+ which the trust anchor points to be signed.
+
+ Unsigned Zone: A zone that is not signed.
+
+ Validating Security-Aware Stub Resolver: A security-aware resolver
+ that sends queries in recursive mode but that performs signature
+ validation on its own rather than just blindly trusting an
+ upstream security-aware recursive name server. See also
+ security-aware stub resolver, non-validating security-aware stub
+ resolver.
+
+ Validating Stub Resolver: A less tedious term for a validating
+ security-aware stub resolver.
+
+ Zone Apex: Term used to describe the name at the child's side of a
+ zone cut. See also delegation point.
+
+ Zone Signing Key (ZSK): An authentication key that corresponds to a
+ private key used to sign a zone. Typically, a zone signing key
+ will be part of the same DNSKEY RRset as the key signing key whose
+ corresponding private key signs this DNSKEY RRset, but the zone
+ signing key is used for a slightly different purpose and may
+ differ from the key signing key in other ways, such as validity
+ lifetime. Designating an authentication key as a zone signing key
+ is purely an operational issue; DNSSEC validation does not
+ distinguish between zone signing keys and other DNSSEC
+ authentication keys, and it is possible to use a single key as
+ both a key signing key and a zone signing key. See also key
+ signing key.
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 6]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+3. Services Provided by DNS Security
+
+ The Domain Name System (DNS) security extensions provide origin
+ authentication and integrity assurance services for DNS data,
+ including mechanisms for authenticated denial of existence of DNS
+ data. These mechanisms are described below.
+
+ These mechanisms require changes to the DNS protocol. DNSSEC adds
+ four new resource record types: Resource Record Signature (RRSIG),
+ DNS Public Key (DNSKEY), Delegation Signer (DS), and Next Secure
+ (NSEC). It also adds two new message header bits: Checking Disabled
+ (CD) and Authenticated Data (AD). In order to support the larger DNS
+ message sizes that result from adding the DNSSEC RRs, DNSSEC also
+ requires EDNS0 support ([RFC2671]). Finally, DNSSEC requires support
+ for the DNSSEC OK (DO) EDNS header bit ([RFC3225]) so that a
+ security-aware resolver can indicate in its queries that it wishes to
+ receive DNSSEC RRs in response messages.
+
+ These services protect against most of the threats to the Domain Name
+ System described in [RFC3833]. Please see Section 12 for a
+ discussion of the limitations of these extensions.
+
+3.1. Data Origin Authentication and Data Integrity
+
+ DNSSEC provides authentication by associating cryptographically
+ generated digital signatures with DNS RRsets. These digital
+ signatures are stored in a new resource record, the RRSIG record.
+ Typically, there will be a single private key that signs a zone's
+ data, but multiple keys are possible. For example, there may be keys
+ for each of several different digital signature algorithms. If a
+ security-aware resolver reliably learns a zone's public key, it can
+ authenticate that zone's signed data. An important DNSSEC concept is
+ that the key that signs a zone's data is associated with the zone
+ itself and not with the zone's authoritative name servers. (Public
+ keys for DNS transaction authentication mechanisms may also appear in
+ zones, as described in [RFC2931], but DNSSEC itself is concerned with
+ object security of DNS data, not channel security of DNS
+ transactions. The keys associated with transaction security may be
+ stored in different RR types. See [RFC3755] for details.)
+
+ A security-aware resolver can learn a zone's public key either by
+ having a trust anchor configured into the resolver or by normal DNS
+ resolution. To allow the latter, public keys are stored in a new
+ type of resource record, the DNSKEY RR. Note that the private keys
+ used to sign zone data must be kept secure and should be stored
+ offline when practical. To discover a public key reliably via DNS
+ resolution, the target key itself has to be signed by either a
+ configured authentication key or another key that has been
+
+
+
+Arends, et al. Standards Track [Page 7]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ authenticated previously. Security-aware resolvers authenticate zone
+ information by forming an authentication chain from a newly learned
+ public key back to a previously known authentication public key,
+ which in turn either has been configured into the resolver or must
+ have been learned and verified previously. Therefore, the resolver
+ must be configured with at least one trust anchor.
+
+ If the configured trust anchor is a zone signing key, then it will
+ authenticate the associated zone; if the configured key is a key
+ signing key, it will authenticate a zone signing key. If the
+ configured trust anchor is the hash of a key rather than the key
+ itself, the resolver may have to obtain the key via a DNS query. To
+ help security-aware resolvers establish this authentication chain,
+ security-aware name servers attempt to send the signature(s) needed
+ to authenticate a zone's public key(s) in the DNS reply message along
+ with the public key itself, provided that there is space available in
+ the message.
+
+ The Delegation Signer (DS) RR type simplifies some of the
+ administrative tasks involved in signing delegations across
+ organizational boundaries. The DS RRset resides at a delegation
+ point in a parent zone and indicates the public key(s) corresponding
+ to the private key(s) used to self-sign the DNSKEY RRset at the
+ delegated child zone's apex. The administrator of the child zone, in
+ turn, uses the private key(s) corresponding to one or more of the
+ public keys in this DNSKEY RRset to sign the child zone's data. The
+ typical authentication chain is therefore
+ DNSKEY->[DS->DNSKEY]*->RRset, where "*" denotes zero or more
+ DS->DNSKEY subchains. DNSSEC permits more complex authentication
+ chains, such as additional layers of DNSKEY RRs signing other DNSKEY
+ RRs within a zone.
+
+ A security-aware resolver normally constructs this authentication
+ chain from the root of the DNS hierarchy down to the leaf zones based
+ on configured knowledge of the public key for the root. Local
+ policy, however, may also allow a security-aware resolver to use one
+ or more configured public keys (or hashes of public keys) other than
+ the root public key, may not provide configured knowledge of the root
+ public key, or may prevent the resolver from using particular public
+ keys for arbitrary reasons, even if those public keys are properly
+ signed with verifiable signatures. DNSSEC provides mechanisms by
+ which a security-aware resolver can determine whether an RRset's
+ signature is "valid" within the meaning of DNSSEC. In the final
+ analysis, however, authenticating both DNS keys and data is a matter
+ of local policy, which may extend or even override the protocol
+ extensions defined in this document set. See Section 5 for further
+ discussion.
+
+
+
+
+Arends, et al. Standards Track [Page 8]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+3.2. Authenticating Name and Type Non-Existence
+
+ The security mechanism described in Section 3.1 only provides a way
+ to sign existing RRsets in a zone. The problem of providing negative
+ responses with the same level of authentication and integrity
+ requires the use of another new resource record type, the NSEC
+ record. The NSEC record allows a security-aware resolver to
+ authenticate a negative reply for either name or type non-existence
+ with the same mechanisms used to authenticate other DNS replies. Use
+ of NSEC records requires a canonical representation and ordering for
+ domain names in zones. Chains of NSEC records explicitly describe
+ the gaps, or "empty space", between domain names in a zone and list
+ the types of RRsets present at existing names. Each NSEC record is
+ signed and authenticated using the mechanisms described in Section
+ 3.1.
+
+4. Services Not Provided by DNS Security
+
+ DNS was originally designed with the assumptions that the DNS will
+ return the same answer to any given query regardless of who may have
+ issued the query, and that all data in the DNS is thus visible.
+ Accordingly, DNSSEC is not designed to provide confidentiality,
+ access control lists, or other means of differentiating between
+ inquirers.
+
+ DNSSEC provides no protection against denial of service attacks.
+ Security-aware resolvers and security-aware name servers are
+ vulnerable to an additional class of denial of service attacks based
+ on cryptographic operations. Please see Section 12 for details.
+
+ The DNS security extensions provide data and origin authentication
+ for DNS data. The mechanisms outlined above are not designed to
+ protect operations such as zone transfers and dynamic update
+ ([RFC2136], [RFC3007]). Message authentication schemes described in
+ [RFC2845] and [RFC2931] address security operations that pertain to
+ these transactions.
+
+5. Scope of the DNSSEC Document Set and Last Hop Issues
+
+ The specification in this document set defines the behavior for zone
+ signers and security-aware name servers and resolvers in such a way
+ that the validating entities can unambiguously determine the state of
+ the data.
+
+ A validating resolver can determine the following 4 states:
+
+ Secure: The validating resolver has a trust anchor, has a chain of
+ trust, and is able to verify all the signatures in the response.
+
+
+
+Arends, et al. Standards Track [Page 9]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ Insecure: The validating resolver has a trust anchor, a chain of
+ trust, and, at some delegation point, signed proof of the
+ non-existence of a DS record. This indicates that subsequent
+ branches in the tree are provably insecure. A validating resolver
+ may have a local policy to mark parts of the domain space as
+ insecure.
+
+ Bogus: The validating resolver has a trust anchor and a secure
+ delegation indicating that subsidiary data is signed, but the
+ response fails to validate for some reason: missing signatures,
+ expired signatures, signatures with unsupported algorithms, data
+ missing that the relevant NSEC RR says should be present, and so
+ forth.
+
+ Indeterminate: There is no trust anchor that would indicate that a
+ specific portion of the tree is secure. This is the default
+ operation mode.
+
+ This specification only defines how security-aware name servers can
+ signal non-validating stub resolvers that data was found to be bogus
+ (using RCODE=2, "Server Failure"; see [RFC4035]).
+
+ There is a mechanism for security-aware name servers to signal
+ security-aware stub resolvers that data was found to be secure (using
+ the AD bit; see [RFC4035]).
+
+ This specification does not define a format for communicating why
+ responses were found to be bogus or marked as insecure. The current
+ signaling mechanism does not distinguish between indeterminate and
+ insecure states.
+
+ A method for signaling advanced error codes and policy between a
+ security-aware stub resolver and security-aware recursive nameservers
+ is a topic for future work, as is the interface between a security-
+ aware resolver and the applications that use it. Note, however, that
+ the lack of the specification of such communication does not prohibit
+ deployment of signed zones or the deployment of security aware
+ recursive name servers that prohibit propagation of bogus data to the
+ applications.
+
+6. Resolver Considerations
+
+ A security-aware resolver has to be able to perform cryptographic
+ functions necessary to verify digital signatures using at least the
+ mandatory-to-implement algorithm(s). Security-aware resolvers must
+ also be capable of forming an authentication chain from a newly
+ learned zone back to an authentication key, as described above. This
+ process might require additional queries to intermediate DNS zones to
+
+
+
+Arends, et al. Standards Track [Page 10]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ obtain necessary DNSKEY, DS, and RRSIG records. A security-aware
+ resolver should be configured with at least one trust anchor as the
+ starting point from which it will attempt to establish authentication
+ chains.
+
+ If a security-aware resolver is separated from the relevant
+ authoritative name servers by a recursive name server or by any sort
+ of intermediary device that acts as a proxy for DNS, and if the
+ recursive name server or intermediary device is not security-aware,
+ the security-aware resolver may not be capable of operating in a
+ secure mode. For example, if a security-aware resolver's packets are
+ routed through a network address translation (NAT) device that
+ includes a DNS proxy that is not security-aware, the security-aware
+ resolver may find it difficult or impossible to obtain or validate
+ signed DNS data. The security-aware resolver may have a particularly
+ difficult time obtaining DS RRs in such a case, as DS RRs do not
+ follow the usual DNS rules for ownership of RRs at zone cuts. Note
+ that this problem is not specific to NATs: any security-oblivious DNS
+ software of any kind between the security-aware resolver and the
+ authoritative name servers will interfere with DNSSEC.
+
+ If a security-aware resolver must rely on an unsigned zone or a name
+ server that is not security aware, the resolver may not be able to
+ validate DNS responses and will need a local policy on whether to
+ accept unverified responses.
+
+ A security-aware resolver should take a signature's validation period
+ into consideration when determining the TTL of data in its cache, to
+ avoid caching signed data beyond the validity period of the
+ signature. However, it should also allow for the possibility that
+ the security-aware resolver's own clock is wrong. Thus, a
+ security-aware resolver that is part of a security-aware recursive
+ name server will have to pay careful attention to the DNSSEC
+ "checking disabled" (CD) bit ([RFC4034]). This is in order to avoid
+ blocking valid signatures from getting through to other
+ security-aware resolvers that are clients of this recursive name
+ server. See [RFC4035] for how a secure recursive server handles
+ queries with the CD bit set.
+
+7. Stub Resolver Considerations
+
+ Although not strictly required to do so by the protocol, most DNS
+ queries originate from stub resolvers. Stub resolvers, by
+ definition, are minimal DNS resolvers that use recursive query mode
+ to offload most of the work of DNS resolution to a recursive name
+ server. Given the widespread use of stub resolvers, the DNSSEC
+
+
+
+
+
+Arends, et al. Standards Track [Page 11]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ architecture has to take stub resolvers into account, but the
+ security features needed in a stub resolver differ in some respects
+ from those needed in a security-aware iterative resolver.
+
+ Even a security-oblivious stub resolver may benefit from DNSSEC if
+ the recursive name servers it uses are security-aware, but for the
+ stub resolver to place any real reliance on DNSSEC services, the stub
+ resolver must trust both the recursive name servers in question and
+ the communication channels between itself and those name servers.
+ The first of these issues is a local policy issue: in essence, a
+ security-oblivious stub resolver has no choice but to place itself at
+ the mercy of the recursive name servers that it uses, as it does not
+ perform DNSSEC validity checks on its own. The second issue requires
+ some kind of channel security mechanism; proper use of DNS
+ transaction authentication mechanisms such as SIG(0) ([RFC2931]) or
+ TSIG ([RFC2845]) would suffice, as would appropriate use of IPsec.
+ Particular implementations may have other choices available, such as
+ operating system specific interprocess communication mechanisms.
+ Confidentiality is not needed for this channel, but data integrity
+ and message authentication are.
+
+ A security-aware stub resolver that does trust both its recursive
+ name servers and its communication channel to them may choose to
+ examine the setting of the Authenticated Data (AD) bit in the message
+ header of the response messages it receives. The stub resolver can
+ use this flag bit as a hint to find out whether the recursive name
+ server was able to validate signatures for all of the data in the
+ Answer and Authority sections of the response.
+
+ There is one more step that a security-aware stub resolver can take
+ if, for whatever reason, it is not able to establish a useful trust
+ relationship with the recursive name servers that it uses: it can
+ perform its own signature validation by setting the Checking Disabled
+ (CD) bit in its query messages. A validating stub resolver is thus
+ able to treat the DNSSEC signatures as trust relationships between
+ the zone administrators and the stub resolver itself.
+
+8. Zone Considerations
+
+ There are several differences between signed and unsigned zones. A
+ signed zone will contain additional security-related records (RRSIG,
+ DNSKEY, DS, and NSEC records). RRSIG and NSEC records may be
+ generated by a signing process prior to serving the zone. The RRSIG
+ records that accompany zone data have defined inception and
+ expiration times that establish a validity period for the signatures
+ and the zone data the signatures cover.
+
+
+
+
+
+Arends, et al. Standards Track [Page 12]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+8.1. TTL Values vs. RRSIG Validity Period
+
+ It is important to note the distinction between a RRset's TTL value
+ and the signature validity period specified by the RRSIG RR covering
+ that RRset. DNSSEC does not change the definition or function of the
+ TTL value, which is intended to maintain database coherency in
+ caches. A caching resolver purges RRsets from its cache no later
+ than the end of the time period specified by the TTL fields of those
+ RRsets, regardless of whether the resolver is security-aware.
+
+ The inception and expiration fields in the RRSIG RR ([RFC4034]), on
+ the other hand, specify the time period during which the signature
+ can be used to validate the covered RRset. The signatures associated
+ with signed zone data are only valid for the time period specified by
+ these fields in the RRSIG RRs in question. TTL values cannot extend
+ the validity period of signed RRsets in a resolver's cache, but the
+ resolver may use the time remaining before expiration of the
+ signature validity period of a signed RRset as an upper bound for the
+ TTL of the signed RRset and its associated RRSIG RR in the resolver's
+ cache.
+
+8.2. New Temporal Dependency Issues for Zones
+
+ Information in a signed zone has a temporal dependency that did not
+ exist in the original DNS protocol. A signed zone requires regular
+ maintenance to ensure that each RRset in the zone has a current valid
+ RRSIG RR. The signature validity period of an RRSIG RR is an
+ interval during which the signature for one particular signed RRset
+ can be considered valid, and the signatures of different RRsets in a
+ zone may expire at different times. Re-signing one or more RRsets in
+ a zone will change one or more RRSIG RRs, which will in turn require
+ incrementing the zone's SOA serial number to indicate that a zone
+ change has occurred and re-signing the SOA RRset itself. Thus,
+ re-signing any RRset in a zone may also trigger DNS NOTIFY messages
+ and zone transfer operations.
+
+9. Name Server Considerations
+
+ A security-aware name server should include the appropriate DNSSEC
+ records (RRSIG, DNSKEY, DS, and NSEC) in all responses to queries
+ from resolvers that have signaled their willingness to receive such
+ records via use of the DO bit in the EDNS header, subject to message
+ size limitations. Because inclusion of these DNSSEC RRs could easily
+ cause UDP message truncation and fallback to TCP, a security-aware
+ name server must also support the EDNS "sender's UDP payload"
+ mechanism.
+
+
+
+
+
+Arends, et al. Standards Track [Page 13]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ If possible, the private half of each DNSSEC key pair should be kept
+ offline, but this will not be possible for a zone for which DNS
+ dynamic update has been enabled. In the dynamic update case, the
+ primary master server for the zone will have to re-sign the zone when
+ it is updated, so the private key corresponding to the zone signing
+ key will have to be kept online. This is an example of a situation
+ in which the ability to separate the zone's DNSKEY RRset into zone
+ signing key(s) and key signing key(s) may be useful, as the key
+ signing key(s) in such a case can still be kept offline and may have
+ a longer useful lifetime than the zone signing key(s).
+
+ By itself, DNSSEC is not enough to protect the integrity of an entire
+ zone during zone transfer operations, as even a signed zone contains
+ some unsigned, nonauthoritative data if the zone has any children.
+ Therefore, zone maintenance operations will require some additional
+ mechanisms (most likely some form of channel security, such as TSIG,
+ SIG(0), or IPsec).
+
+10. DNS Security Document Family
+
+ The DNSSEC document set can be partitioned into several main groups,
+ under the larger umbrella of the DNS base protocol documents.
+
+ The "DNSSEC protocol document set" refers to the three documents that
+ form the core of the DNS security extensions:
+
+ 1. DNS Security Introduction and Requirements (this document)
+
+ 2. Resource Records for DNS Security Extensions [RFC4034]
+
+ 3. Protocol Modifications for the DNS Security Extensions [RFC4035]
+
+ Additionally, any document that would add to or change the core DNS
+ Security extensions would fall into this category. This includes any
+ future work on the communication between security-aware stub
+ resolvers and upstream security-aware recursive name servers.
+
+ The "Digital Signature Algorithm Specification" document set refers
+ to the group of documents that describe how specific digital
+ signature algorithms should be implemented to fit the DNSSEC resource
+ record format. Each document in this set deals with a specific
+ digital signature algorithm. Please see the appendix on "DNSSEC
+ Algorithm and Digest Types" in [RFC4034] for a list of the algorithms
+ that were defined when this core specification was written.
+
+ The "Transaction Authentication Protocol" document set refers to the
+ group of documents that deal with DNS message authentication,
+ including secret key establishment and verification. Although not
+
+
+
+Arends, et al. Standards Track [Page 14]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ strictly part of the DNSSEC specification as defined in this set of
+ documents, this group is noted because of its relationship to DNSSEC.
+
+ The final document set, "New Security Uses", refers to documents that
+ seek to use proposed DNS Security extensions for other security
+ related purposes. DNSSEC does not provide any direct security for
+ these new uses but may be used to support them. Documents that fall
+ in this category include those describing the use of DNS in the
+ storage and distribution of certificates ([RFC2538]).
+
+11. IANA Considerations
+
+ This overview document introduces no new IANA considerations. Please
+ see [RFC4034] for a complete review of the IANA considerations
+ introduced by DNSSEC.
+
+12. Security Considerations
+
+ This document introduces DNS security extensions and describes the
+ document set that contains the new security records and DNS protocol
+ modifications. The extensions provide data origin authentication and
+ data integrity using digital signatures over resource record sets.
+ This section discusses the limitations of these extensions.
+
+ In order for a security-aware resolver to validate a DNS response,
+ all zones along the path from the trusted starting point to the zone
+ containing the response zones must be signed, and all name servers
+ and resolvers involved in the resolution process must be
+ security-aware, as defined in this document set. A security-aware
+ resolver cannot verify responses originating from an unsigned zone,
+ from a zone not served by a security-aware name server, or for any
+ DNS data that the resolver is only able to obtain through a recursive
+ name server that is not security-aware. If there is a break in the
+ authentication chain such that a security-aware resolver cannot
+ obtain and validate the authentication keys it needs, then the
+ security-aware resolver cannot validate the affected DNS data.
+
+ This document briefly discusses other methods of adding security to a
+ DNS query, such as using a channel secured by IPsec or using a DNS
+ transaction authentication mechanism such as TSIG ([RFC2845]) or
+ SIG(0) ([RFC2931]), but transaction security is not part of DNSSEC
+ per se.
+
+ A non-validating security-aware stub resolver, by definition, does
+ not perform DNSSEC signature validation on its own and thus is
+ vulnerable both to attacks on (and by) the security-aware recursive
+ name servers that perform these checks on its behalf and to attacks
+ on its communication with those security-aware recursive name
+
+
+
+Arends, et al. Standards Track [Page 15]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ servers. Non-validating security-aware stub resolvers should use
+ some form of channel security to defend against the latter threat.
+ The only known defense against the former threat would be for the
+ security-aware stub resolver to perform its own signature validation,
+ at which point, again by definition, it would no longer be a
+ non-validating security-aware stub resolver.
+
+ DNSSEC does not protect against denial of service attacks. DNSSEC
+ makes DNS vulnerable to a new class of denial of service attacks
+ based on cryptographic operations against security-aware resolvers
+ and security-aware name servers, as an attacker can attempt to use
+ DNSSEC mechanisms to consume a victim's resources. This class of
+ attacks takes at least two forms. An attacker may be able to consume
+ resources in a security-aware resolver's signature validation code by
+ tampering with RRSIG RRs in response messages or by constructing
+ needlessly complex signature chains. An attacker may also be able to
+ consume resources in a security-aware name server that supports DNS
+ dynamic update, by sending a stream of update messages that force the
+ security-aware name server to re-sign some RRsets in the zone more
+ frequently than would otherwise be necessary.
+
+ Due to a deliberate design choice, DNSSEC does not provide
+ confidentiality.
+
+ DNSSEC introduces the ability for a hostile party to enumerate all
+ the names in a zone by following the NSEC chain. NSEC RRs assert
+ which names do not exist in a zone by linking from existing name to
+ existing name along a canonical ordering of all the names within a
+ zone. Thus, an attacker can query these NSEC RRs in sequence to
+ obtain all the names in a zone. Although this is not an attack on
+ the DNS itself, it could allow an attacker to map network hosts or
+ other resources by enumerating the contents of a zone.
+
+ DNSSEC introduces significant additional complexity to the DNS and
+ thus introduces many new opportunities for implementation bugs and
+ misconfigured zones. In particular, enabling DNSSEC signature
+ validation in a resolver may cause entire legitimate zones to become
+ effectively unreachable due to DNSSEC configuration errors or bugs.
+
+ DNSSEC does not protect against tampering with unsigned zone data.
+ Non-authoritative data at zone cuts (glue and NS RRs in the parent
+ zone) are not signed. This does not pose a problem when validating
+ the authentication chain, but it does mean that the non-authoritative
+ data itself is vulnerable to tampering during zone transfer
+ operations. Thus, while DNSSEC can provide data origin
+ authentication and data integrity for RRsets, it cannot do so for
+ zones, and other mechanisms (such as TSIG, SIG(0), or IPsec) must be
+ used to protect zone transfer operations.
+
+
+
+Arends, et al. Standards Track [Page 16]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ Please see [RFC4034] and [RFC4035] for additional security
+ considerations.
+
+13. Acknowledgements
+
+ This document was created from the input and ideas of the members of
+ the DNS Extensions Working Group. Although explicitly listing
+ everyone who has contributed during the decade in which DNSSEC has
+ been under development would be impossible, the editors would
+ particularly like to thank the following people for their
+ contributions to and comments on this document set: Jaap Akkerhuis,
+ Mark Andrews, Derek Atkins, Roy Badami, Alan Barrett, Dan Bernstein,
+ David Blacka, Len Budney, Randy Bush, Francis Dupont, Donald
+ Eastlake, Robert Elz, Miek Gieben, Michael Graff, Olafur Gudmundsson,
+ Gilles Guette, Andreas Gustafsson, Jun-ichiro Itojun Hagino, Phillip
+ Hallam-Baker, Bob Halley, Ted Hardie, Walter Howard, Greg Hudson,
+ Christian Huitema, Johan Ihren, Stephen Jacob, Jelte Jansen, Simon
+ Josefsson, Andris Kalnozols, Peter Koch, Olaf Kolkman, Mark Kosters,
+ Suresh Krishnaswamy, Ben Laurie, David Lawrence, Ted Lemon, Ed Lewis,
+ Ted Lindgreen, Josh Littlefield, Rip Loomis, Bill Manning, Russ
+ Mundy, Thomas Narten, Mans Nilsson, Masataka Ohta, Mike Patton, Rob
+ Payne, Jim Reid, Michael Richardson, Erik Rozendaal, Marcos Sanz,
+ Pekka Savola, Jakob Schlyter, Mike StJohns, Paul Vixie, Sam Weiler,
+ Brian Wellington, and Suzanne Woolf.
+
+ No doubt the above list is incomplete. We apologize to anyone we
+ left out.
+
+14. References
+
+14.1. Normative References
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2535] Eastlake 3rd, D., "Domain Name System Security
+ Extensions", RFC 2535, March 1999.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [RFC3225] Conrad, D., "Indicating Resolver Support of DNSSEC", RFC
+ 3225, December 2001.
+
+
+
+
+
+Arends, et al. Standards Track [Page 17]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ [RFC3226] Gudmundsson, O., "DNSSEC and IPv6 A6 aware server/resolver
+ message size requirements", RFC 3226, December 2001.
+
+ [RFC3445] Massey, D. and S. Rose, "Limiting the Scope of the KEY
+ Resource Record (RR)", RFC 3445, December 2002.
+
+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for DNS Security Extensions", RFC
+ 4034, March 2005.
+
+ [RFC4035] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security
+ Extensions", RFC 4035, March 2005.
+
+14.2. Informative References
+
+ [RFC2136] Vixie, P., Thomson, S., Rekhter, Y., and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS UPDATE)",
+ RFC 2136, April 1997.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC2308] Andrews, M., "Negative Caching of DNS Queries (DNS
+ NCACHE)", RFC 2308, March 1998.
+
+ [RFC2538] Eastlake 3rd, D. and O. Gudmundsson, "Storing Certificates
+ in the Domain Name System (DNS)", RFC 2538, March 1999.
+
+ [RFC2845] Vixie, P., Gudmundsson, O., Eastlake 3rd, D., and B.
+ Wellington, "Secret Key Transaction Authentication for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+ [RFC2931] Eastlake 3rd, D., "DNS Request and Transaction Signatures
+ ( SIG(0)s )", RFC 2931, September 2000.
+
+ [RFC3007] Wellington, B., "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+ [RFC3008] Wellington, B., "Domain Name System Security (DNSSEC)
+ Signing Authority", RFC 3008, November 2000.
+
+ [RFC3090] Lewis, E., "DNS Security Extension Clarification on Zone
+ Status", RFC 3090, March 2001.
+
+ [RFC3597] Gustafsson, A., "Handling of Unknown DNS Resource Record
+ (RR) Types", RFC 3597, September 2003.
+
+
+
+
+Arends, et al. Standards Track [Page 18]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+ [RFC3655] Wellington, B. and O. Gudmundsson, "Redefinition of DNS
+ Authenticated Data (AD) bit", RFC 3655, November 2003.
+
+ [RFC3658] Gudmundsson, O., "Delegation Signer (DS) Resource Record
+ (RR)", RFC 3658, December 2003.
+
+ [RFC3755] Weiler, S., "Legacy Resolver Compatibility for Delegation
+ Signer (DS)", RFC 3755, May 2004.
+
+ [RFC3757] Kolkman, O., Schlyter, J., and E. Lewis, "Domain Name
+ System KEY (DNSKEY) Resource Record (RR) Secure Entry
+ Point (SEP) Flag", RFC 3757, April 2004.
+
+ [RFC3833] Atkins, D. and R. Austein, "Threat Analysis of the Domain
+ Name System (DNS)", RFC 3833, August 2004.
+
+ [RFC3845] Schlyter, J., "DNS Security (DNSSEC) NextSECure (NSEC)
+ RDATA Format", RFC 3845, August 2004.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 19]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+Authors' Addresses
+
+ Roy Arends
+ Telematica Instituut
+ Brouwerijstraat 1
+ 7523 XC Enschede
+ NL
+
+ EMail: roy.arends@telin.nl
+
+
+ Rob Austein
+ Internet Systems Consortium
+ 950 Charter Street
+ Redwood City, CA 94063
+ USA
+
+ EMail: sra@isc.org
+
+
+ Matt Larson
+ VeriSign, Inc.
+ 21345 Ridgetop Circle
+ Dulles, VA 20166-6503
+ USA
+
+ EMail: mlarson@verisign.com
+
+
+ Dan Massey
+ Colorado State University
+ Department of Computer Science
+ Fort Collins, CO 80523-1873
+
+ EMail: massey@cs.colostate.edu
+
+
+ Scott Rose
+ National Institute for Standards and Technology
+ 100 Bureau Drive
+ Gaithersburg, MD 20899-8920
+ USA
+
+ EMail: scott.rose@nist.gov
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 20]
+
+RFC 4033 DNS Security Introduction and Requirements March 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 21]
+
diff --git a/doc/rfc/rfc4034.txt b/doc/rfc/rfc4034.txt
new file mode 100644
index 0000000..6a12c6b
--- /dev/null
+++ b/doc/rfc/rfc4034.txt
@@ -0,0 +1,1627 @@
+
+
+
+
+
+
+Network Working Group R. Arends
+Request for Comments: 4034 Telematica Instituut
+Obsoletes: 2535, 3008, 3090, 3445, 3655, 3658, R. Austein
+ 3755, 3757, 3845 ISC
+Updates: 1034, 1035, 2136, 2181, 2308, 3225, M. Larson
+ 3007, 3597, 3226 VeriSign
+Category: Standards Track D. Massey
+ Colorado State University
+ S. Rose
+ NIST
+ March 2005
+
+
+ Resource Records for the DNS Security Extensions
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document is part of a family of documents that describe the DNS
+ Security Extensions (DNSSEC). The DNS Security Extensions are a
+ collection of resource records and protocol modifications that
+ provide source authentication for the DNS. This document defines the
+ public key (DNSKEY), delegation signer (DS), resource record digital
+ signature (RRSIG), and authenticated denial of existence (NSEC)
+ resource records. The purpose and format of each resource record is
+ described in detail, and an example of each resource record is given.
+
+ This document obsoletes RFC 2535 and incorporates changes from all
+ updates to RFC 2535.
+
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 1]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1. Background and Related Documents . . . . . . . . . . . 3
+ 1.2. Reserved Words . . . . . . . . . . . . . . . . . . . . 3
+ 2. The DNSKEY Resource Record . . . . . . . . . . . . . . . . . 4
+ 2.1. DNSKEY RDATA Wire Format . . . . . . . . . . . . . . . 4
+ 2.1.1. The Flags Field. . . . . . . . . . . . . . . . 4
+ 2.1.2. The Protocol Field . . . . . . . . . . . . . . 5
+ 2.1.3. The Algorithm Field. . . . . . . . . . . . . . 5
+ 2.1.4. The Public Key Field . . . . . . . . . . . . . 5
+ 2.1.5. Notes on DNSKEY RDATA Design . . . . . . . . . 5
+ 2.2. The DNSKEY RR Presentation Format. . . . . . . . . . . 5
+ 2.3. DNSKEY RR Example . . . . . . . . . . . . . . . . . . 6
+ 3. The RRSIG Resource Record . . . . . . . . . . . . . . . . . 6
+ 3.1. RRSIG RDATA Wire Format. . . . . . . . . . . . . . . . 7
+ 3.1.1. The Type Covered Field . . . . . . . . . . . . 7
+ 3.1.2. The Algorithm Number Field . . . . . . . . . . 8
+ 3.1.3. The Labels Field . . . . . . . . . . . . . . . 8
+ 3.1.4. Original TTL Field . . . . . . . . . . . . . . 8
+ 3.1.5. Signature Expiration and Inception Fields. . . 9
+ 3.1.6. The Key Tag Field. . . . . . . . . . . . . . . 9
+ 3.1.7. The Signer's Name Field. . . . . . . . . . . . 9
+ 3.1.8. The Signature Field. . . . . . . . . . . . . . 9
+ 3.2. The RRSIG RR Presentation Format . . . . . . . . . . . 10
+ 3.3. RRSIG RR Example . . . . . . . . . . . . . . . . . . . 11
+ 4. The NSEC Resource Record . . . . . . . . . . . . . . . . . . 12
+ 4.1. NSEC RDATA Wire Format . . . . . . . . . . . . . . . . 13
+ 4.1.1. The Next Domain Name Field . . . . . . . . . . 13
+ 4.1.2. The Type Bit Maps Field. . . . . . . . . . . . 13
+ 4.1.3. Inclusion of Wildcard Names in NSEC RDATA. . . 14
+ 4.2. The NSEC RR Presentation Format. . . . . . . . . . . . 14
+ 4.3. NSEC RR Example. . . . . . . . . . . . . . . . . . . . 15
+ 5. The DS Resource Record . . . . . . . . . . . . . . . . . . . 15
+ 5.1. DS RDATA Wire Format . . . . . . . . . . . . . . . . . 16
+ 5.1.1. The Key Tag Field. . . . . . . . . . . . . . . 16
+ 5.1.2. The Algorithm Field. . . . . . . . . . . . . . 16
+ 5.1.3. The Digest Type Field. . . . . . . . . . . . . 17
+ 5.1.4. The Digest Field . . . . . . . . . . . . . . . 17
+ 5.2. Processing of DS RRs When Validating Responses . . . . 17
+ 5.3. The DS RR Presentation Format. . . . . . . . . . . . . 17
+ 5.4. DS RR Example. . . . . . . . . . . . . . . . . . . . . 18
+ 6. Canonical Form and Order of Resource Records . . . . . . . . 18
+ 6.1. Canonical DNS Name Order . . . . . . . . . . . . . . . 18
+ 6.2. Canonical RR Form. . . . . . . . . . . . . . . . . . . 19
+ 6.3. Canonical RR Ordering within an RRset. . . . . . . . . 20
+ 7. IANA Considerations. . . . . . . . . . . . . . . . . . . . . 20
+ 8. Security Considerations. . . . . . . . . . . . . . . . . . . 21
+
+
+
+Arends, et al. Standards Track [Page 2]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ 9. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 22
+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 22
+ 10.1. Normative References . . . . . . . . . . . . . . . . . 22
+ 10.2. Informative References . . . . . . . . . . . . . . . . 23
+ A. DNSSEC Algorithm and Digest Types. . . . . . . . . . . . . . 24
+ A.1. DNSSEC Algorithm Types . . . . . . . . . . . . . . . . 24
+ A.1.1. Private Algorithm Types. . . . . . . . . . . . 25
+ A.2. DNSSEC Digest Types. . . . . . . . . . . . . . . . . . 25
+ B. Key Tag Calculation. . . . . . . . . . . . . . . . . . . . . 25
+ B.1. Key Tag for Algorithm 1 (RSA/MD5). . . . . . . . . . . 27
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 28
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . 29
+
+1. Introduction
+
+ The DNS Security Extensions (DNSSEC) introduce four new DNS resource
+ record types: DNS Public Key (DNSKEY), Resource Record Signature
+ (RRSIG), Next Secure (NSEC), and Delegation Signer (DS). This
+ document defines the purpose of each resource record (RR), the RR's
+ RDATA format, and its presentation format (ASCII representation).
+
+1.1. Background and Related Documents
+
+ This document is part of a family of documents defining DNSSEC, which
+ should be read together as a set.
+
+ [RFC4033] contains an introduction to DNSSEC and definition of common
+ terms; the reader is assumed to be familiar with this document.
+ [RFC4033] also contains a list of other documents updated by and
+ obsoleted by this document set.
+
+ [RFC4035] defines the DNSSEC protocol operations.
+
+ The reader is also assumed to be familiar with the basic DNS concepts
+ described in [RFC1034], [RFC1035], and the subsequent documents that
+ update them, particularly [RFC2181] and [RFC2308].
+
+ This document defines the DNSSEC resource records. All numeric DNS
+ type codes given in this document are decimal integers.
+
+1.2. Reserved Words
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 3]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+2. The DNSKEY Resource Record
+
+ DNSSEC uses public key cryptography to sign and authenticate DNS
+ resource record sets (RRsets). The public keys are stored in DNSKEY
+ resource records and are used in the DNSSEC authentication process
+ described in [RFC4035]: A zone signs its authoritative RRsets by
+ using a private key and stores the corresponding public key in a
+ DNSKEY RR. A resolver can then use the public key to validate
+ signatures covering the RRsets in the zone, and thus to authenticate
+ them.
+
+ The DNSKEY RR is not intended as a record for storing arbitrary
+ public keys and MUST NOT be used to store certificates or public keys
+ that do not directly relate to the DNS infrastructure.
+
+ The Type value for the DNSKEY RR type is 48.
+
+ The DNSKEY RR is class independent.
+
+ The DNSKEY RR has no special TTL requirements.
+
+2.1. DNSKEY RDATA Wire Format
+
+ The RDATA for a DNSKEY RR consists of a 2 octet Flags Field, a 1
+ octet Protocol Field, a 1 octet Algorithm Field, and the Public Key
+ Field.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Flags | Protocol | Algorithm |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / /
+ / Public Key /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+2.1.1. The Flags Field
+
+ Bit 7 of the Flags field is the Zone Key flag. If bit 7 has value 1,
+ then the DNSKEY record holds a DNS zone key, and the DNSKEY RR's
+ owner name MUST be the name of a zone. If bit 7 has value 0, then
+ the DNSKEY record holds some other type of DNS public key and MUST
+ NOT be used to verify RRSIGs that cover RRsets.
+
+ Bit 15 of the Flags field is the Secure Entry Point flag, described
+ in [RFC3757]. If bit 15 has value 1, then the DNSKEY record holds a
+ key intended for use as a secure entry point. This flag is only
+
+
+
+Arends, et al. Standards Track [Page 4]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ intended to be a hint to zone signing or debugging software as to the
+ intended use of this DNSKEY record; validators MUST NOT alter their
+ behavior during the signature validation process in any way based on
+ the setting of this bit. This also means that a DNSKEY RR with the
+ SEP bit set would also need the Zone Key flag set in order to be able
+ to generate signatures legally. A DNSKEY RR with the SEP set and the
+ Zone Key flag not set MUST NOT be used to verify RRSIGs that cover
+ RRsets.
+
+ Bits 0-6 and 8-14 are reserved: these bits MUST have value 0 upon
+ creation of the DNSKEY RR and MUST be ignored upon receipt.
+
+2.1.2. The Protocol Field
+
+ The Protocol Field MUST have value 3, and the DNSKEY RR MUST be
+ treated as invalid during signature verification if it is found to be
+ some value other than 3.
+
+2.1.3. The Algorithm Field
+
+ The Algorithm field identifies the public key's cryptographic
+ algorithm and determines the format of the Public Key field. A list
+ of DNSSEC algorithm types can be found in Appendix A.1
+
+2.1.4. The Public Key Field
+
+ The Public Key Field holds the public key material. The format
+ depends on the algorithm of the key being stored and is described in
+ separate documents.
+
+2.1.5. Notes on DNSKEY RDATA Design
+
+ Although the Protocol Field always has value 3, it is retained for
+ backward compatibility with early versions of the KEY record.
+
+2.2. The DNSKEY RR Presentation Format
+
+ The presentation format of the RDATA portion is as follows:
+
+ The Flag field MUST be represented as an unsigned decimal integer.
+ Given the currently defined flags, the possible values are: 0, 256,
+ and 257.
+
+ The Protocol Field MUST be represented as an unsigned decimal integer
+ with a value of 3.
+
+ The Algorithm field MUST be represented either as an unsigned decimal
+ integer or as an algorithm mnemonic as specified in Appendix A.1.
+
+
+
+Arends, et al. Standards Track [Page 5]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ The Public Key field MUST be represented as a Base64 encoding of the
+ Public Key. Whitespace is allowed within the Base64 text. For a
+ definition of Base64 encoding, see [RFC3548].
+
+2.3. DNSKEY RR Example
+
+ The following DNSKEY RR stores a DNS zone key for example.com.
+
+ example.com. 86400 IN DNSKEY 256 3 5 ( AQPSKmynfzW4kyBv015MUG2DeIQ3
+ Cbl+BBZH4b/0PY1kxkmvHjcZc8no
+ kfzj31GajIQKY+5CptLr3buXA10h
+ WqTkF7H6RfoRqXQeogmMHfpftf6z
+ Mv1LyBUgia7za6ZEzOJBOztyvhjL
+ 742iU/TpPSEDhm2SNKLijfUppn1U
+ aNvv4w== )
+
+ The first four text fields specify the owner name, TTL, Class, and RR
+ type (DNSKEY). Value 256 indicates that the Zone Key bit (bit 7) in
+ the Flags field has value 1. Value 3 is the fixed Protocol value.
+ Value 5 indicates the public key algorithm. Appendix A.1 identifies
+ algorithm type 5 as RSA/SHA1 and indicates that the format of the
+ RSA/SHA1 public key field is defined in [RFC3110]. The remaining
+ text is a Base64 encoding of the public key.
+
+3. The RRSIG Resource Record
+
+ DNSSEC uses public key cryptography to sign and authenticate DNS
+ resource record sets (RRsets). Digital signatures are stored in
+ RRSIG resource records and are used in the DNSSEC authentication
+ process described in [RFC4035]. A validator can use these RRSIG RRs
+ to authenticate RRsets from the zone. The RRSIG RR MUST only be used
+ to carry verification material (digital signatures) used to secure
+ DNS operations.
+
+ An RRSIG record contains the signature for an RRset with a particular
+ name, class, and type. The RRSIG RR specifies a validity interval
+ for the signature and uses the Algorithm, the Signer's Name, and the
+ Key Tag to identify the DNSKEY RR containing the public key that a
+ validator can use to verify the signature.
+
+ Because every authoritative RRset in a zone must be protected by a
+ digital signature, RRSIG RRs must be present for names containing a
+ CNAME RR. This is a change to the traditional DNS specification
+ [RFC1034], which stated that if a CNAME is present for a name, it is
+ the only type allowed at that name. A RRSIG and NSEC (see Section 4)
+ MUST exist for the same name as a CNAME resource record in a signed
+ zone.
+
+
+
+
+Arends, et al. Standards Track [Page 6]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ The Type value for the RRSIG RR type is 46.
+
+ The RRSIG RR is class independent.
+
+ An RRSIG RR MUST have the same class as the RRset it covers.
+
+ The TTL value of an RRSIG RR MUST match the TTL value of the RRset it
+ covers. This is an exception to the [RFC2181] rules for TTL values
+ of individual RRs within a RRset: individual RRSIG RRs with the same
+ owner name will have different TTL values if the RRsets they cover
+ have different TTL values.
+
+3.1. RRSIG RDATA Wire Format
+
+ The RDATA for an RRSIG RR consists of a 2 octet Type Covered field, a
+ 1 octet Algorithm field, a 1 octet Labels field, a 4 octet Original
+ TTL field, a 4 octet Signature Expiration field, a 4 octet Signature
+ Inception field, a 2 octet Key tag, the Signer's Name field, and the
+ Signature field.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type Covered | Algorithm | Labels |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Original TTL |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Signature Expiration |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Signature Inception |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Key Tag | /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Signer's Name /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / /
+ / Signature /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+3.1.1. The Type Covered Field
+
+ The Type Covered field identifies the type of the RRset that is
+ covered by this RRSIG record.
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 7]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+3.1.2. The Algorithm Number Field
+
+ The Algorithm Number field identifies the cryptographic algorithm
+ used to create the signature. A list of DNSSEC algorithm types can
+ be found in Appendix A.1
+
+3.1.3. The Labels Field
+
+ The Labels field specifies the number of labels in the original RRSIG
+ RR owner name. The significance of this field is that a validator
+ uses it to determine whether the answer was synthesized from a
+ wildcard. If so, it can be used to determine what owner name was
+ used in generating the signature.
+
+ To validate a signature, the validator needs the original owner name
+ that was used to create the signature. If the original owner name
+ contains a wildcard label ("*"), the owner name may have been
+ expanded by the server during the response process, in which case the
+ validator will have to reconstruct the original owner name in order
+ to validate the signature. [RFC4035] describes how to use the Labels
+ field to reconstruct the original owner name.
+
+ The value of the Labels field MUST NOT count either the null (root)
+ label that terminates the owner name or the wildcard label (if
+ present). The value of the Labels field MUST be less than or equal
+ to the number of labels in the RRSIG owner name. For example,
+ "www.example.com." has a Labels field value of 3, and
+ "*.example.com." has a Labels field value of 2. Root (".") has a
+ Labels field value of 0.
+
+ Although the wildcard label is not included in the count stored in
+ the Labels field of the RRSIG RR, the wildcard label is part of the
+ RRset's owner name when the signature is generated or verified.
+
+3.1.4. Original TTL Field
+
+ The Original TTL field specifies the TTL of the covered RRset as it
+ appears in the authoritative zone.
+
+ The Original TTL field is necessary because a caching resolver
+ decrements the TTL value of a cached RRset. In order to validate a
+ signature, a validator requires the original TTL. [RFC4035]
+ describes how to use the Original TTL field value to reconstruct the
+ original TTL.
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 8]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+3.1.5. Signature Expiration and Inception Fields
+
+ The Signature Expiration and Inception fields specify a validity
+ period for the signature. The RRSIG record MUST NOT be used for
+ authentication prior to the inception date and MUST NOT be used for
+ authentication after the expiration date.
+
+ The Signature Expiration and Inception field values specify a date
+ and time in the form of a 32-bit unsigned number of seconds elapsed
+ since 1 January 1970 00:00:00 UTC, ignoring leap seconds, in network
+ byte order. The longest interval that can be expressed by this
+ format without wrapping is approximately 136 years. An RRSIG RR can
+ have an Expiration field value that is numerically smaller than the
+ Inception field value if the expiration field value is near the
+ 32-bit wrap-around point or if the signature is long lived. Because
+ of this, all comparisons involving these fields MUST use "Serial
+ number arithmetic", as defined in [RFC1982]. As a direct
+ consequence, the values contained in these fields cannot refer to
+ dates more than 68 years in either the past or the future.
+
+3.1.6. The Key Tag Field
+
+ The Key Tag field contains the key tag value of the DNSKEY RR that
+ validates this signature, in network byte order. Appendix B explains
+ how to calculate Key Tag values.
+
+3.1.7. The Signer's Name Field
+
+ The Signer's Name field value identifies the owner name of the DNSKEY
+ RR that a validator is supposed to use to validate this signature.
+ The Signer's Name field MUST contain the name of the zone of the
+ covered RRset. A sender MUST NOT use DNS name compression on the
+ Signer's Name field when transmitting a RRSIG RR.
+
+3.1.8. The Signature Field
+
+ The Signature field contains the cryptographic signature that covers
+ the RRSIG RDATA (excluding the Signature field) and the RRset
+ specified by the RRSIG owner name, RRSIG class, and RRSIG Type
+ Covered field. The format of this field depends on the algorithm in
+ use, and these formats are described in separate companion documents.
+
+3.1.8.1. Signature Calculation
+
+ A signature covers the RRSIG RDATA (excluding the Signature Field)
+ and covers the data RRset specified by the RRSIG owner name, RRSIG
+ class, and RRSIG Type Covered fields. The RRset is in canonical form
+ (see Section 6), and the set RR(1),...RR(n) is signed as follows:
+
+
+
+Arends, et al. Standards Track [Page 9]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ signature = sign(RRSIG_RDATA | RR(1) | RR(2)... ) where
+
+ "|" denotes concatenation;
+
+ RRSIG_RDATA is the wire format of the RRSIG RDATA fields
+ with the Signer's Name field in canonical form and
+ the Signature field excluded;
+
+ RR(i) = owner | type | class | TTL | RDATA length | RDATA
+
+ "owner" is the fully qualified owner name of the RRset in
+ canonical form (for RRs with wildcard owner names, the
+ wildcard label is included in the owner name);
+
+ Each RR MUST have the same owner name as the RRSIG RR;
+
+ Each RR MUST have the same class as the RRSIG RR;
+
+ Each RR in the RRset MUST have the RR type listed in the
+ RRSIG RR's Type Covered field;
+
+ Each RR in the RRset MUST have the TTL listed in the
+ RRSIG Original TTL Field;
+
+ Any DNS names in the RDATA field of each RR MUST be in
+ canonical form; and
+
+ The RRset MUST be sorted in canonical order.
+
+ See Sections 6.2 and 6.3 for details on canonical form and ordering
+ of RRsets.
+
+3.2. The RRSIG RR Presentation Format
+
+ The presentation format of the RDATA portion is as follows:
+
+ The Type Covered field is represented as an RR type mnemonic. When
+ the mnemonic is not known, the TYPE representation as described in
+ [RFC3597], Section 5, MUST be used.
+
+ The Algorithm field value MUST be represented either as an unsigned
+ decimal integer or as an algorithm mnemonic, as specified in Appendix
+ A.1.
+
+ The Labels field value MUST be represented as an unsigned decimal
+ integer.
+
+
+
+
+
+Arends, et al. Standards Track [Page 10]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ The Original TTL field value MUST be represented as an unsigned
+ decimal integer.
+
+ The Signature Expiration Time and Inception Time field values MUST be
+ represented either as an unsigned decimal integer indicating seconds
+ since 1 January 1970 00:00:00 UTC, or in the form YYYYMMDDHHmmSS in
+ UTC, where:
+
+ YYYY is the year (0001-9999, but see Section 3.1.5);
+ MM is the month number (01-12);
+ DD is the day of the month (01-31);
+ HH is the hour, in 24 hour notation (00-23);
+ mm is the minute (00-59); and
+ SS is the second (00-59).
+
+ Note that it is always possible to distinguish between these two
+ formats because the YYYYMMDDHHmmSS format will always be exactly 14
+ digits, while the decimal representation of a 32-bit unsigned integer
+ can never be longer than 10 digits.
+
+ The Key Tag field MUST be represented as an unsigned decimal integer.
+
+ The Signer's Name field value MUST be represented as a domain name.
+
+ The Signature field is represented as a Base64 encoding of the
+ signature. Whitespace is allowed within the Base64 text. See
+ Section 2.2.
+
+3.3. RRSIG RR Example
+
+ The following RRSIG RR stores the signature for the A RRset of
+ host.example.com:
+
+ host.example.com. 86400 IN RRSIG A 5 3 86400 20030322173103 (
+ 20030220173103 2642 example.com.
+ oJB1W6WNGv+ldvQ3WDG0MQkg5IEhjRip8WTr
+ PYGv07h108dUKGMeDPKijVCHX3DDKdfb+v6o
+ B9wfuh3DTJXUAfI/M0zmO/zz8bW0Rznl8O3t
+ GNazPwQKkRN20XPXV6nwwfoXmJQbsLNrLfkG
+ J5D6fwFm8nN+6pBzeDQfsS3Ap3o= )
+
+ The first four fields specify the owner name, TTL, Class, and RR type
+ (RRSIG). The "A" represents the Type Covered field. The value 5
+ identifies the algorithm used (RSA/SHA1) to create the signature.
+ The value 3 is the number of Labels in the original owner name. The
+ value 86400 in the RRSIG RDATA is the Original TTL for the covered A
+ RRset. 20030322173103 and 20030220173103 are the expiration and
+
+
+
+
+Arends, et al. Standards Track [Page 11]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ inception dates, respectively. 2642 is the Key Tag, and example.com.
+ is the Signer's Name. The remaining text is a Base64 encoding of the
+ signature.
+
+ Note that combination of RRSIG RR owner name, class, and Type Covered
+ indicates that this RRSIG covers the "host.example.com" A RRset. The
+ Label value of 3 indicates that no wildcard expansion was used. The
+ Algorithm, Signer's Name, and Key Tag indicate that this signature
+ can be authenticated using an example.com zone DNSKEY RR whose
+ algorithm is 5 and whose key tag is 2642.
+
+4. The NSEC Resource Record
+
+ The NSEC resource record lists two separate things: the next owner
+ name (in the canonical ordering of the zone) that contains
+ authoritative data or a delegation point NS RRset, and the set of RR
+ types present at the NSEC RR's owner name [RFC3845]. The complete
+ set of NSEC RRs in a zone indicates which authoritative RRsets exist
+ in a zone and also form a chain of authoritative owner names in the
+ zone. This information is used to provide authenticated denial of
+ existence for DNS data, as described in [RFC4035].
+
+ Because every authoritative name in a zone must be part of the NSEC
+ chain, NSEC RRs must be present for names containing a CNAME RR.
+ This is a change to the traditional DNS specification [RFC1034],
+ which stated that if a CNAME is present for a name, it is the only
+ type allowed at that name. An RRSIG (see Section 3) and NSEC MUST
+ exist for the same name as does a CNAME resource record in a signed
+ zone.
+
+ See [RFC4035] for discussion of how a zone signer determines
+ precisely which NSEC RRs it has to include in a zone.
+
+ The type value for the NSEC RR is 47.
+
+ The NSEC RR is class independent.
+
+ The NSEC RR SHOULD have the same TTL value as the SOA minimum TTL
+ field. This is in the spirit of negative caching ([RFC2308]).
+
+
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 12]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+4.1. NSEC RDATA Wire Format
+
+ The RDATA of the NSEC RR is as shown below:
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / Next Domain Name /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / Type Bit Maps /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+4.1.1. The Next Domain Name Field
+
+ The Next Domain field contains the next owner name (in the canonical
+ ordering of the zone) that has authoritative data or contains a
+ delegation point NS RRset; see Section 6.1 for an explanation of
+ canonical ordering. The value of the Next Domain Name field in the
+ last NSEC record in the zone is the name of the zone apex (the owner
+ name of the zone's SOA RR). This indicates that the owner name of
+ the NSEC RR is the last name in the canonical ordering of the zone.
+
+ A sender MUST NOT use DNS name compression on the Next Domain Name
+ field when transmitting an NSEC RR.
+
+ Owner names of RRsets for which the given zone is not authoritative
+ (such as glue records) MUST NOT be listed in the Next Domain Name
+ unless at least one authoritative RRset exists at the same owner
+ name.
+
+4.1.2. The Type Bit Maps Field
+
+ The Type Bit Maps field identifies the RRset types that exist at the
+ NSEC RR's owner name.
+
+ The RR type space is split into 256 window blocks, each representing
+ the low-order 8 bits of the 16-bit RR type space. Each block that
+ has at least one active RR type is encoded using a single octet
+ window number (from 0 to 255), a single octet bitmap length (from 1
+ to 32) indicating the number of octets used for the window block's
+ bitmap, and up to 32 octets (256 bits) of bitmap.
+
+ Blocks are present in the NSEC RR RDATA in increasing numerical
+ order.
+
+ Type Bit Maps Field = ( Window Block # | Bitmap Length | Bitmap )+
+
+ where "|" denotes concatenation.
+
+
+
+Arends, et al. Standards Track [Page 13]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ Each bitmap encodes the low-order 8 bits of RR types within the
+ window block, in network bit order. The first bit is bit 0. For
+ window block 0, bit 1 corresponds to RR type 1 (A), bit 2 corresponds
+ to RR type 2 (NS), and so forth. For window block 1, bit 1
+ corresponds to RR type 257, and bit 2 to RR type 258. If a bit is
+ set, it indicates that an RRset of that type is present for the NSEC
+ RR's owner name. If a bit is clear, it indicates that no RRset of
+ that type is present for the NSEC RR's owner name.
+
+ Bits representing pseudo-types MUST be clear, as they do not appear
+ in zone data. If encountered, they MUST be ignored upon being read.
+
+ Blocks with no types present MUST NOT be included. Trailing zero
+ octets in the bitmap MUST be omitted. The length of each block's
+ bitmap is determined by the type code with the largest numerical
+ value, within that block, among the set of RR types present at the
+ NSEC RR's owner name. Trailing zero octets not specified MUST be
+ interpreted as zero octets.
+
+ The bitmap for the NSEC RR at a delegation point requires special
+ attention. Bits corresponding to the delegation NS RRset and the RR
+ types for which the parent zone has authoritative data MUST be set;
+ bits corresponding to any non-NS RRset for which the parent is not
+ authoritative MUST be clear.
+
+ A zone MUST NOT include an NSEC RR for any domain name that only
+ holds glue records.
+
+4.1.3. Inclusion of Wildcard Names in NSEC RDATA
+
+ If a wildcard owner name appears in a zone, the wildcard label ("*")
+ is treated as a literal symbol and is treated the same as any other
+ owner name for the purposes of generating NSEC RRs. Wildcard owner
+ names appear in the Next Domain Name field without any wildcard
+ expansion. [RFC4035] describes the impact of wildcards on
+ authenticated denial of existence.
+
+4.2. The NSEC RR Presentation Format
+
+ The presentation format of the RDATA portion is as follows:
+
+ The Next Domain Name field is represented as a domain name.
+
+ The Type Bit Maps field is represented as a sequence of RR type
+ mnemonics. When the mnemonic is not known, the TYPE representation
+ described in [RFC3597], Section 5, MUST be used.
+
+
+
+
+
+Arends, et al. Standards Track [Page 14]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+4.3. NSEC RR Example
+
+ The following NSEC RR identifies the RRsets associated with
+ alfa.example.com. and identifies the next authoritative name after
+ alfa.example.com.
+
+ alfa.example.com. 86400 IN NSEC host.example.com. (
+ A MX RRSIG NSEC TYPE1234 )
+
+ The first four text fields specify the name, TTL, Class, and RR type
+ (NSEC). The entry host.example.com. is the next authoritative name
+ after alfa.example.com. in canonical order. The A, MX, RRSIG, NSEC,
+ and TYPE1234 mnemonics indicate that there are A, MX, RRSIG, NSEC,
+ and TYPE1234 RRsets associated with the name alfa.example.com.
+
+ The RDATA section of the NSEC RR above would be encoded as:
+
+ 0x04 'h' 'o' 's' 't'
+ 0x07 'e' 'x' 'a' 'm' 'p' 'l' 'e'
+ 0x03 'c' 'o' 'm' 0x00
+ 0x00 0x06 0x40 0x01 0x00 0x00 0x00 0x03
+ 0x04 0x1b 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x20
+
+ Assuming that the validator can authenticate this NSEC record, it
+ could be used to prove that beta.example.com does not exist, or to
+ prove that there is no AAAA record associated with alfa.example.com.
+ Authenticated denial of existence is discussed in [RFC4035].
+
+5. The DS Resource Record
+
+ The DS Resource Record refers to a DNSKEY RR and is used in the DNS
+ DNSKEY authentication process. A DS RR refers to a DNSKEY RR by
+ storing the key tag, algorithm number, and a digest of the DNSKEY RR.
+ Note that while the digest should be sufficient to identify the
+ public key, storing the key tag and key algorithm helps make the
+ identification process more efficient. By authenticating the DS
+ record, a resolver can authenticate the DNSKEY RR to which the DS
+ record points. The key authentication process is described in
+ [RFC4035].
+
+ The DS RR and its corresponding DNSKEY RR have the same owner name,
+ but they are stored in different locations. The DS RR appears only
+ on the upper (parental) side of a delegation, and is authoritative
+ data in the parent zone. For example, the DS RR for "example.com" is
+ stored in the "com" zone (the parent zone) rather than in the
+
+
+
+Arends, et al. Standards Track [Page 15]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ "example.com" zone (the child zone). The corresponding DNSKEY RR is
+ stored in the "example.com" zone (the child zone). This simplifies
+ DNS zone management and zone signing but introduces special response
+ processing requirements for the DS RR; these are described in
+ [RFC4035].
+
+ The type number for the DS record is 43.
+
+ The DS resource record is class independent.
+
+ The DS RR has no special TTL requirements.
+
+5.1. DS RDATA Wire Format
+
+ The RDATA for a DS RR consists of a 2 octet Key Tag field, a 1 octet
+ Algorithm field, a 1 octet Digest Type field, and a Digest field.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Key Tag | Algorithm | Digest Type |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / /
+ / Digest /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+5.1.1. The Key Tag Field
+
+ The Key Tag field lists the key tag of the DNSKEY RR referred to by
+ the DS record, in network byte order.
+
+ The Key Tag used by the DS RR is identical to the Key Tag used by
+ RRSIG RRs. Appendix B describes how to compute a Key Tag.
+
+5.1.2. The Algorithm Field
+
+ The Algorithm field lists the algorithm number of the DNSKEY RR
+ referred to by the DS record.
+
+ The algorithm number used by the DS RR is identical to the algorithm
+ number used by RRSIG and DNSKEY RRs. Appendix A.1 lists the
+ algorithm number types.
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 16]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+5.1.3. The Digest Type Field
+
+ The DS RR refers to a DNSKEY RR by including a digest of that DNSKEY
+ RR. The Digest Type field identifies the algorithm used to construct
+ the digest. Appendix A.2 lists the possible digest algorithm types.
+
+5.1.4. The Digest Field
+
+ The DS record refers to a DNSKEY RR by including a digest of that
+ DNSKEY RR.
+
+ The digest is calculated by concatenating the canonical form of the
+ fully qualified owner name of the DNSKEY RR with the DNSKEY RDATA,
+ and then applying the digest algorithm.
+
+ digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA);
+
+ "|" denotes concatenation
+
+ DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key.
+
+ The size of the digest may vary depending on the digest algorithm and
+ DNSKEY RR size. As of the time of this writing, the only defined
+ digest algorithm is SHA-1, which produces a 20 octet digest.
+
+5.2. Processing of DS RRs When Validating Responses
+
+ The DS RR links the authentication chain across zone boundaries, so
+ the DS RR requires extra care in processing. The DNSKEY RR referred
+ to in the DS RR MUST be a DNSSEC zone key. The DNSKEY RR Flags MUST
+ have Flags bit 7 set. If the DNSKEY flags do not indicate a DNSSEC
+ zone key, the DS RR (and the DNSKEY RR it references) MUST NOT be
+ used in the validation process.
+
+5.3. The DS RR Presentation Format
+
+ The presentation format of the RDATA portion is as follows:
+
+ The Key Tag field MUST be represented as an unsigned decimal integer.
+
+ The Algorithm field MUST be represented either as an unsigned decimal
+ integer or as an algorithm mnemonic specified in Appendix A.1.
+
+ The Digest Type field MUST be represented as an unsigned decimal
+ integer.
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 17]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ The Digest MUST be represented as a sequence of case-insensitive
+ hexadecimal digits. Whitespace is allowed within the hexadecimal
+ text.
+
+5.4. DS RR Example
+
+ The following example shows a DNSKEY RR and its corresponding DS RR.
+
+ dskey.example.com. 86400 IN DNSKEY 256 3 5 ( AQOeiiR0GOMYkDshWoSKz9Xz
+ fwJr1AYtsmx3TGkJaNXVbfi/
+ 2pHm822aJ5iI9BMzNXxeYCmZ
+ DRD99WYwYqUSdjMmmAphXdvx
+ egXd/M5+X7OrzKBaMbCVdFLU
+ Uh6DhweJBjEVv5f2wwjM9Xzc
+ nOf+EPbtG9DMBmADjFDc2w/r
+ ljwvFw==
+ ) ; key id = 60485
+
+ dskey.example.com. 86400 IN DS 60485 5 1 ( 2BB183AF5F22588179A53B0A
+ 98631FAD1A292118 )
+
+ The first four text fields specify the name, TTL, Class, and RR type
+ (DS). Value 60485 is the key tag for the corresponding
+ "dskey.example.com." DNSKEY RR, and value 5 denotes the algorithm
+ used by this "dskey.example.com." DNSKEY RR. The value 1 is the
+ algorithm used to construct the digest, and the rest of the RDATA
+ text is the digest in hexadecimal.
+
+6. Canonical Form and Order of Resource Records
+
+ This section defines a canonical form for resource records, a
+ canonical ordering of DNS names, and a canonical ordering of resource
+ records within an RRset. A canonical name order is required to
+ construct the NSEC name chain. A canonical RR form and ordering
+ within an RRset are required in order to construct and verify RRSIG
+ RRs.
+
+6.1. Canonical DNS Name Order
+
+ For the purposes of DNS security, owner names are ordered by treating
+ individual labels as unsigned left-justified octet strings. The
+ absence of a octet sorts before a zero value octet, and uppercase
+ US-ASCII letters are treated as if they were lowercase US-ASCII
+ letters.
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 18]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ To compute the canonical ordering of a set of DNS names, start by
+ sorting the names according to their most significant (rightmost)
+ labels. For names in which the most significant label is identical,
+ continue sorting according to their next most significant label, and
+ so forth.
+
+ For example, the following names are sorted in canonical DNS name
+ order. The most significant label is "example". At this level,
+ "example" sorts first, followed by names ending in "a.example", then
+ by names ending "z.example". The names within each level are sorted
+ in the same way.
+
+ example
+ a.example
+ yljkjljk.a.example
+ Z.a.example
+ zABC.a.EXAMPLE
+ z.example
+ \001.z.example
+ *.z.example
+ \200.z.example
+
+6.2. Canonical RR Form
+
+ For the purposes of DNS security, the canonical form of an RR is the
+ wire format of the RR where:
+
+ 1. every domain name in the RR is fully expanded (no DNS name
+ compression) and fully qualified;
+
+ 2. all uppercase US-ASCII letters in the owner name of the RR are
+ replaced by the corresponding lowercase US-ASCII letters;
+
+ 3. if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
+ HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
+ SRV, DNAME, A6, RRSIG, or NSEC, all uppercase US-ASCII letters in
+ the DNS names contained within the RDATA are replaced by the
+ corresponding lowercase US-ASCII letters;
+
+ 4. if the owner name of the RR is a wildcard name, the owner name is
+ in its original unexpanded form, including the "*" label (no
+ wildcard substitution); and
+
+ 5. the RR's TTL is set to its original value as it appears in the
+ originating authoritative zone or the Original TTL field of the
+ covering RRSIG RR.
+
+
+
+
+
+Arends, et al. Standards Track [Page 19]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+6.3. Canonical RR Ordering within an RRset
+
+ For the purposes of DNS security, RRs with the same owner name,
+ class, and type are sorted by treating the RDATA portion of the
+ canonical form of each RR as a left-justified unsigned octet sequence
+ in which the absence of an octet sorts before a zero octet.
+
+ [RFC2181] specifies that an RRset is not allowed to contain duplicate
+ records (multiple RRs with the same owner name, class, type, and
+ RDATA). Therefore, if an implementation detects duplicate RRs when
+ putting the RRset in canonical form, it MUST treat this as a protocol
+ error. If the implementation chooses to handle this protocol error
+ in the spirit of the robustness principle (being liberal in what it
+ accepts), it MUST remove all but one of the duplicate RR(s) for the
+ purposes of calculating the canonical form of the RRset.
+
+7. IANA Considerations
+
+ This document introduces no new IANA considerations, as all of the
+ protocol parameters used in this document have already been assigned
+ by previous specifications. However, since the evolution of DNSSEC
+ has been long and somewhat convoluted, this section attempts to
+ describe the current state of the IANA registries and other protocol
+ parameters that are (or once were) related to DNSSEC.
+
+ Please refer to [RFC4035] for additional IANA considerations.
+
+ DNS Resource Record Types: [RFC2535] assigned types 24, 25, and 30 to
+ the SIG, KEY, and NXT RRs, respectively. [RFC3658] assigned DNS
+ Resource Record Type 43 to DS. [RFC3755] assigned types 46, 47,
+ and 48 to the RRSIG, NSEC, and DNSKEY RRs, respectively.
+ [RFC3755] also marked type 30 (NXT) as Obsolete and restricted use
+ of types 24 (SIG) and 25 (KEY) to the "SIG(0)" transaction
+ security protocol described in [RFC2931] and to the transaction
+ KEY Resource Record described in [RFC2930].
+
+ DNS Security Algorithm Numbers: [RFC2535] created an IANA registry
+ for DNSSEC Resource Record Algorithm field numbers and assigned
+ values 1-4 and 252-255. [RFC3110] assigned value 5. [RFC3755]
+ altered this registry to include flags for each entry regarding
+ its use with the DNS security extensions. Each algorithm entry
+ could refer to an algorithm that can be used for zone signing,
+ transaction security (see [RFC2931]), or both. Values 6-251 are
+ available for assignment by IETF standards action ([RFC3755]).
+ See Appendix A for a full listing of the DNS Security Algorithm
+ Numbers entries at the time of this writing and their status for
+ use in DNSSEC.
+
+
+
+
+Arends, et al. Standards Track [Page 20]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ [RFC3658] created an IANA registry for DNSSEC DS Digest Types and
+ assigned value 0 to reserved and value 1 to SHA-1.
+
+ KEY Protocol Values: [RFC2535] created an IANA Registry for KEY
+ Protocol Values, but [RFC3445] reassigned all values other than 3
+ to reserved and closed this IANA registry. The registry remains
+ closed, and all KEY and DNSKEY records are required to have a
+ Protocol Octet value of 3.
+
+ Flag bits in the KEY and DNSKEY RRs: [RFC3755] created an IANA
+ registry for the DNSSEC KEY and DNSKEY RR flag bits. Initially,
+ this registry only contains assignments for bit 7 (the ZONE bit)
+ and bit 15 (the Secure Entry Point flag (SEP) bit; see [RFC3757]).
+ As stated in [RFC3755], bits 0-6 and 8-14 are available for
+ assignment by IETF Standards Action.
+
+8. Security Considerations
+
+ This document describes the format of four DNS resource records used
+ by the DNS security extensions and presents an algorithm for
+ calculating a key tag for a public key. Other than the items
+ described below, the resource records themselves introduce no
+ security considerations. Please see [RFC4033] and [RFC4035] for
+ additional security considerations related to the use of these
+ records.
+
+ The DS record points to a DNSKEY RR by using a cryptographic digest,
+ the key algorithm type, and a key tag. The DS record is intended to
+ identify an existing DNSKEY RR, but it is theoretically possible for
+ an attacker to generate a DNSKEY that matches all the DS fields. The
+ probability of constructing a matching DNSKEY depends on the type of
+ digest algorithm in use. The only currently defined digest algorithm
+ is SHA-1, and the working group believes that constructing a public
+ key that would match the algorithm, key tag, and SHA-1 digest given
+ in a DS record would be a sufficiently difficult problem that such an
+ attack is not a serious threat at this time.
+
+ The key tag is used to help select DNSKEY resource records
+ efficiently, but it does not uniquely identify a single DNSKEY
+ resource record. It is possible for two distinct DNSKEY RRs to have
+ the same owner name, the same algorithm type, and the same key tag.
+ An implementation that uses only the key tag to select a DNSKEY RR
+ might select the wrong public key in some circumstances. Please see
+ Appendix B for further details.
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 21]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ The table of algorithms in Appendix A and the key tag calculation
+ algorithms in Appendix B include the RSA/MD5 algorithm for
+ completeness, but the RSA/MD5 algorithm is NOT RECOMMENDED, as
+ explained in [RFC3110].
+
+9. Acknowledgements
+
+ This document was created from the input and ideas of the members of
+ the DNS Extensions Working Group and working group mailing list. The
+ editors would like to express their thanks for the comments and
+ suggestions received during the revision of these security extension
+ specifications. Although explicitly listing everyone who has
+ contributed during the decade in which DNSSEC has been under
+ development would be impossible, [RFC4033] includes a list of some of
+ the participants who were kind enough to comment on these documents.
+
+10. References
+
+10.1. Normative References
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC1982] Elz, R. and R. Bush, "Serial Number Arithmetic", RFC 1982,
+ August 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC2308] Andrews, M., "Negative Caching of DNS Queries (DNS
+ NCACHE)", RFC 2308, March 1998.
+
+ [RFC2536] Eastlake 3rd, D., "DSA KEYs and SIGs in the Domain Name
+ System (DNS)", RFC 2536, March 1999.
+
+ [RFC2931] Eastlake 3rd, D., "DNS Request and Transaction Signatures
+ ( SIG(0)s )", RFC 2931, September 2000.
+
+ [RFC3110] Eastlake 3rd, D., "RSA/SHA-1 SIGs and RSA KEYs in the
+ Domain Name System (DNS)", RFC 3110, May 2001.
+
+
+
+
+
+Arends, et al. Standards Track [Page 22]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ [RFC3445] Massey, D. and S. Rose, "Limiting the Scope of the KEY
+ Resource Record (RR)", RFC 3445, December 2002.
+
+ [RFC3548] Josefsson, S., "The Base16, Base32, and Base64 Data
+ Encodings", RFC 3548, July 2003.
+
+ [RFC3597] Gustafsson, A., "Handling of Unknown DNS Resource Record
+ (RR) Types", RFC 3597, September 2003.
+
+ [RFC3658] Gudmundsson, O., "Delegation Signer (DS) Resource Record
+ (RR)", RFC 3658, December 2003.
+
+ [RFC3755] Weiler, S., "Legacy Resolver Compatibility for Delegation
+ Signer (DS)", RFC 3755, May 2004.
+
+ [RFC3757] Kolkman, O., Schlyter, J., and E. Lewis, "Domain Name
+ System KEY (DNSKEY) Resource Record (RR) Secure Entry
+ Point (SEP) Flag", RFC 3757, April 2004.
+
+ [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements", RFC
+ 4033, March 2005.
+
+ [RFC4035] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Protocol Modifications for the DNS Security
+ Extensions", RFC 4035, March 2005.
+
+10.2. Informative References
+
+ [RFC2535] Eastlake 3rd, D., "Domain Name System Security
+ Extensions", RFC 2535, March 1999.
+
+ [RFC2537] Eastlake 3rd, D., "RSA/MD5 KEYs and SIGs in the Domain
+ Name System (DNS)", RFC 2537, March 1999.
+
+ [RFC2539] Eastlake 3rd, D., "Storage of Diffie-Hellman Keys in the
+ Domain Name System (DNS)", RFC 2539, March 1999.
+
+ [RFC2930] Eastlake 3rd, D., "Secret Key Establishment for DNS (TKEY
+ RR)", RFC 2930, September 2000.
+
+ [RFC3845] Schlyter, J., "DNS Security (DNSSEC) NextSECure (NSEC)
+ RDATA Format", RFC 3845, August 2004.
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 23]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+Appendix A. DNSSEC Algorithm and Digest Types
+
+ The DNS security extensions are designed to be independent of the
+ underlying cryptographic algorithms. The DNSKEY, RRSIG, and DS
+ resource records all use a DNSSEC Algorithm Number to identify the
+ cryptographic algorithm in use by the resource record. The DS
+ resource record also specifies a Digest Algorithm Number to identify
+ the digest algorithm used to construct the DS record. The currently
+ defined Algorithm and Digest Types are listed below. Additional
+ Algorithm or Digest Types could be added as advances in cryptography
+ warrant them.
+
+ A DNSSEC aware resolver or name server MUST implement all MANDATORY
+ algorithms.
+
+A.1. DNSSEC Algorithm Types
+
+ The DNSKEY, RRSIG, and DS RRs use an 8-bit number to identify the
+ security algorithm being used. These values are stored in the
+ "Algorithm number" field in the resource record RDATA.
+
+ Some algorithms are usable only for zone signing (DNSSEC), some only
+ for transaction security mechanisms (SIG(0) and TSIG), and some for
+ both. Those usable for zone signing may appear in DNSKEY, RRSIG, and
+ DS RRs. Those usable for transaction security would be present in
+ SIG(0) and KEY RRs, as described in [RFC2931].
+
+ Zone
+ Value Algorithm [Mnemonic] Signing References Status
+ ----- -------------------- --------- ---------- ---------
+ 0 reserved
+ 1 RSA/MD5 [RSAMD5] n [RFC2537] NOT RECOMMENDED
+ 2 Diffie-Hellman [DH] n [RFC2539] -
+ 3 DSA/SHA-1 [DSA] y [RFC2536] OPTIONAL
+ 4 Elliptic Curve [ECC] TBA -
+ 5 RSA/SHA-1 [RSASHA1] y [RFC3110] MANDATORY
+ 252 Indirect [INDIRECT] n -
+ 253 Private [PRIVATEDNS] y see below OPTIONAL
+ 254 Private [PRIVATEOID] y see below OPTIONAL
+ 255 reserved
+
+ 6 - 251 Available for assignment by IETF Standards Action.
+
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 24]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+A.1.1. Private Algorithm Types
+
+ Algorithm number 253 is reserved for private use and will never be
+ assigned to a specific algorithm. The public key area in the DNSKEY
+ RR and the signature area in the RRSIG RR begin with a wire encoded
+ domain name, which MUST NOT be compressed. The domain name indicates
+ the private algorithm to use, and the remainder of the public key
+ area is determined by that algorithm. Entities should only use
+ domain names they control to designate their private algorithms.
+
+ Algorithm number 254 is reserved for private use and will never be
+ assigned to a specific algorithm. The public key area in the DNSKEY
+ RR and the signature area in the RRSIG RR begin with an unsigned
+ length byte followed by a BER encoded Object Identifier (ISO OID) of
+ that length. The OID indicates the private algorithm in use, and the
+ remainder of the area is whatever is required by that algorithm.
+ Entities should only use OIDs they control to designate their private
+ algorithms.
+
+A.2. DNSSEC Digest Types
+
+ A "Digest Type" field in the DS resource record types identifies the
+ cryptographic digest algorithm used by the resource record. The
+ following table lists the currently defined digest algorithm types.
+
+ VALUE Algorithm STATUS
+ 0 Reserved -
+ 1 SHA-1 MANDATORY
+ 2-255 Unassigned -
+
+Appendix B. Key Tag Calculation
+
+ The Key Tag field in the RRSIG and DS resource record types provides
+ a mechanism for selecting a public key efficiently. In most cases, a
+ combination of owner name, algorithm, and key tag can efficiently
+ identify a DNSKEY record. Both the RRSIG and DS resource records
+ have corresponding DNSKEY records. The Key Tag field in the RRSIG
+ and DS records can be used to help select the corresponding DNSKEY RR
+ efficiently when more than one candidate DNSKEY RR is available.
+
+ However, it is essential to note that the key tag is not a unique
+ identifier. It is theoretically possible for two distinct DNSKEY RRs
+ to have the same owner name, the same algorithm, and the same key
+ tag. The key tag is used to limit the possible candidate keys, but
+ it does not uniquely identify a DNSKEY record. Implementations MUST
+ NOT assume that the key tag uniquely identifies a DNSKEY RR.
+
+
+
+
+
+Arends, et al. Standards Track [Page 25]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+ The key tag is the same for all DNSKEY algorithm types except
+ algorithm 1 (please see Appendix B.1 for the definition of the key
+ tag for algorithm 1). The key tag algorithm is the sum of the wire
+ format of the DNSKEY RDATA broken into 2 octet groups. First, the
+ RDATA (in wire format) is treated as a series of 2 octet groups.
+ These groups are then added together, ignoring any carry bits.
+
+ A reference implementation of the key tag algorithm is as an ANSI C
+ function is given below, with the RDATA portion of the DNSKEY RR is
+ used as input. It is not necessary to use the following reference
+ code verbatim, but the numerical value of the Key Tag MUST be
+ identical to what the reference implementation would generate for the
+ same input.
+
+ Please note that the algorithm for calculating the Key Tag is almost
+ but not completely identical to the familiar ones-complement checksum
+ used in many other Internet protocols. Key Tags MUST be calculated
+ using the algorithm described here rather than the ones complement
+ checksum.
+
+ The following ANSI C reference implementation calculates the value of
+ a Key Tag. This reference implementation applies to all algorithm
+ types except algorithm 1 (see Appendix B.1). The input is the wire
+ format of the RDATA portion of the DNSKEY RR. The code is written
+ for clarity, not efficiency.
+
+ /*
+ * Assumes that int is at least 16 bits.
+ * First octet of the key tag is the most significant 8 bits of the
+ * return value;
+ * Second octet of the key tag is the least significant 8 bits of the
+ * return value.
+ */
+
+ unsigned int
+ keytag (
+ unsigned char key[], /* the RDATA part of the DNSKEY RR */
+ unsigned int keysize /* the RDLENGTH */
+ )
+ {
+ unsigned long ac; /* assumed to be 32 bits or larger */
+ int i; /* loop index */
+
+ for ( ac = 0, i = 0; i < keysize; ++i )
+ ac += (i & 1) ? key[i] : key[i] << 8;
+ ac += (ac >> 16) & 0xFFFF;
+ return ac & 0xFFFF;
+ }
+
+
+
+Arends, et al. Standards Track [Page 26]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+B.1. Key Tag for Algorithm 1 (RSA/MD5)
+
+ The key tag for algorithm 1 (RSA/MD5) is defined differently from the
+ key tag for all other algorithms, for historical reasons. For a
+ DNSKEY RR with algorithm 1, the key tag is defined to be the most
+ significant 16 bits of the least significant 24 bits in the public
+ key modulus (in other words, the 4th to last and 3rd to last octets
+ of the public key modulus).
+
+ Please note that Algorithm 1 is NOT RECOMMENDED.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 27]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+Authors' Addresses
+
+ Roy Arends
+ Telematica Instituut
+ Brouwerijstraat 1
+ 7523 XC Enschede
+ NL
+
+ EMail: roy.arends@telin.nl
+
+
+ Rob Austein
+ Internet Systems Consortium
+ 950 Charter Street
+ Redwood City, CA 94063
+ USA
+
+ EMail: sra@isc.org
+
+
+ Matt Larson
+ VeriSign, Inc.
+ 21345 Ridgetop Circle
+ Dulles, VA 20166-6503
+ USA
+
+ EMail: mlarson@verisign.com
+
+
+ Dan Massey
+ Colorado State University
+ Department of Computer Science
+ Fort Collins, CO 80523-1873
+
+ EMail: massey@cs.colostate.edu
+
+
+ Scott Rose
+ National Institute for Standards and Technology
+ 100 Bureau Drive
+ Gaithersburg, MD 20899-8920
+ USA
+
+ EMail: scott.rose@nist.gov
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 28]
+
+RFC 4034 DNSSEC Resource Records March 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 29]
+
diff --git a/doc/rfc/rfc4035.txt b/doc/rfc/rfc4035.txt
new file mode 100644
index 0000000..b701cd2
--- /dev/null
+++ b/doc/rfc/rfc4035.txt
@@ -0,0 +1,2971 @@
+
+
+
+
+
+
+Network Working Group R. Arends
+Request for Comments: 4035 Telematica Instituut
+Obsoletes: 2535, 3008, 3090, 3445, 3655, 3658, R. Austein
+ 3755, 3757, 3845 ISC
+Updates: 1034, 1035, 2136, 2181, 2308, 3225, M. Larson
+ 3007, 3597, 3226 VeriSign
+Category: Standards Track D. Massey
+ Colorado State University
+ S. Rose
+ NIST
+ March 2005
+
+
+ Protocol Modifications for the DNS Security Extensions
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document is part of a family of documents that describe the DNS
+ Security Extensions (DNSSEC). The DNS Security Extensions are a
+ collection of new resource records and protocol modifications that
+ add data origin authentication and data integrity to the DNS. This
+ document describes the DNSSEC protocol modifications. This document
+ defines the concept of a signed zone, along with the requirements for
+ serving and resolving by using DNSSEC. These techniques allow a
+ security-aware resolver to authenticate both DNS resource records and
+ authoritative DNS error indications.
+
+ This document obsoletes RFC 2535 and incorporates changes from all
+ updates to RFC 2535.
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 1]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
+ 1.1. Background and Related Documents . . . . . . . . . . . . 4
+ 1.2. Reserved Words . . . . . . . . . . . . . . . . . . . . . 4
+ 2. Zone Signing . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 2.1. Including DNSKEY RRs in a Zone . . . . . . . . . . . . . 5
+ 2.2. Including RRSIG RRs in a Zone . . . . . . . . . . . . . 5
+ 2.3. Including NSEC RRs in a Zone . . . . . . . . . . . . . . 6
+ 2.4. Including DS RRs in a Zone . . . . . . . . . . . . . . . 7
+ 2.5. Changes to the CNAME Resource Record. . . . . . . . . . 7
+ 2.6. DNSSEC RR Types Appearing at Zone Cuts. . . . . . . . . 8
+ 2.7. Example of a Secure Zone . . . . . . . . . . . . . . . . 8
+ 3. Serving . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 3.1. Authoritative Name Servers . . . . . . . . . . . . . . . 9
+ 3.1.1. Including RRSIG RRs in a Response . . . . . . . 10
+ 3.1.2. Including DNSKEY RRs in a Response . . . . . . . 11
+ 3.1.3. Including NSEC RRs in a Response . . . . . . . . 11
+ 3.1.4. Including DS RRs in a Response . . . . . . . . . 14
+ 3.1.5. Responding to Queries for Type AXFR or IXFR . . 15
+ 3.1.6. The AD and CD Bits in an Authoritative Response. 16
+ 3.2. Recursive Name Servers . . . . . . . . . . . . . . . . . 17
+ 3.2.1. The DO Bit . . . . . . . . . . . . . . . . . . . 17
+ 3.2.2. The CD Bit . . . . . . . . . . . . . . . . . . . 17
+ 3.2.3. The AD Bit . . . . . . . . . . . . . . . . . . . 18
+ 3.3. Example DNSSEC Responses . . . . . . . . . . . . . . . . 19
+ 4. Resolving . . . . . . . . . . . . . . . . . . . . . . . . . . 19
+ 4.1. EDNS Support . . . . . . . . . . . . . . . . . . . . . . 19
+ 4.2. Signature Verification Support . . . . . . . . . . . . . 19
+ 4.3. Determining Security Status of Data . . . . . . . . . . 20
+ 4.4. Configured Trust Anchors . . . . . . . . . . . . . . . . 21
+ 4.5. Response Caching . . . . . . . . . . . . . . . . . . . . 21
+ 4.6. Handling of the CD and AD Bits . . . . . . . . . . . . . 22
+ 4.7. Caching BAD Data . . . . . . . . . . . . . . . . . . . . 22
+ 4.8. Synthesized CNAMEs . . . . . . . . . . . . . . . . . . . 23
+ 4.9. Stub Resolvers . . . . . . . . . . . . . . . . . . . . . 23
+ 4.9.1. Handling of the DO Bit . . . . . . . . . . . . . 24
+ 4.9.2. Handling of the CD Bit . . . . . . . . . . . . . 24
+ 4.9.3. Handling of the AD Bit . . . . . . . . . . . . . 24
+ 5. Authenticating DNS Responses . . . . . . . . . . . . . . . . . 25
+ 5.1. Special Considerations for Islands of Security . . . . . 26
+ 5.2. Authenticating Referrals . . . . . . . . . . . . . . . . 26
+ 5.3. Authenticating an RRset with an RRSIG RR . . . . . . . . 28
+ 5.3.1. Checking the RRSIG RR Validity . . . . . . . . . 28
+ 5.3.2. Reconstructing the Signed Data . . . . . . . . . 29
+ 5.3.3. Checking the Signature . . . . . . . . . . . . . 31
+ 5.3.4. Authenticating a Wildcard Expanded RRset
+ Positive Response. . . . . . . . . . . . . . . . 32
+
+
+
+Arends, et al. Standards Track [Page 2]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ 5.4. Authenticated Denial of Existence . . . . . . . . . . . 32
+ 5.5. Resolver Behavior When Signatures Do Not Validate . . . 33
+ 5.6. Authentication Example . . . . . . . . . . . . . . . . . 33
+ 6. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 33
+ 7. Security Considerations . . . . . . . . . . . . . . . . . . . 33
+ 8. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 34
+ 9. References . . . . . . . . . . . . . . . . . . . . . . . . . . 34
+ 9.1. Normative References . . . . . . . . . . . . . . . . . . 34
+ 9.2. Informative References . . . . . . . . . . . . . . . . . 35
+ A. Signed Zone Example . . . . . . . . . . . . . . . . . . . . . 36
+ B. Example Responses . . . . . . . . . . . . . . . . . . . . . . 41
+ B.1. Answer . . . . . . . . . . . . . . . . . . . . . . . . . 41
+ B.2. Name Error . . . . . . . . . . . . . . . . . . . . . . . 43
+ B.3. No Data Error . . . . . . . . . . . . . . . . . . . . . 44
+ B.4. Referral to Signed Zone . . . . . . . . . . . . . . . . 44
+ B.5. Referral to Unsigned Zone . . . . . . . . . . . . . . . 45
+ B.6. Wildcard Expansion . . . . . . . . . . . . . . . . . . . 46
+ B.7. Wildcard No Data Error . . . . . . . . . . . . . . . . . 47
+ B.8. DS Child Zone No Data Error . . . . . . . . . . . . . . 48
+ C. Authentication Examples . . . . . . . . . . . . . . . . . . . 49
+ C.1. Authenticating an Answer . . . . . . . . . . . . . . . . 49
+ C.1.1. Authenticating the Example DNSKEY RR . . . . . . 49
+ C.2. Name Error . . . . . . . . . . . . . . . . . . . . . . . 50
+ C.3. No Data Error . . . . . . . . . . . . . . . . . . . . . 50
+ C.4. Referral to Signed Zone . . . . . . . . . . . . . . . . 50
+ C.5. Referral to Unsigned Zone . . . . . . . . . . . . . . . 51
+ C.6. Wildcard Expansion . . . . . . . . . . . . . . . . . . . 51
+ C.7. Wildcard No Data Error . . . . . . . . . . . . . . . . . 51
+ C.8. DS Child Zone No Data Error . . . . . . . . . . . . . . 51
+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 52
+ Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 53
+
+1. Introduction
+
+ The DNS Security Extensions (DNSSEC) are a collection of new resource
+ records and protocol modifications that add data origin
+ authentication and data integrity to the DNS. This document defines
+ the DNSSEC protocol modifications. Section 2 of this document
+ defines the concept of a signed zone and lists the requirements for
+ zone signing. Section 3 describes the modifications to authoritative
+ name server behavior necessary for handling signed zones. Section 4
+ describes the behavior of entities that include security-aware
+ resolver functions. Finally, Section 5 defines how to use DNSSEC RRs
+ to authenticate a response.
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 3]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+1.1. Background and Related Documents
+
+ This document is part of a family of documents defining DNSSEC that
+ should be read together as a set.
+
+ [RFC4033] contains an introduction to DNSSEC and definitions of
+ common terms; the reader is assumed to be familiar with this
+ document. [RFC4033] also contains a list of other documents updated
+ by and obsoleted by this document set.
+
+ [RFC4034] defines the DNSSEC resource records.
+
+ The reader is also assumed to be familiar with the basic DNS concepts
+ described in [RFC1034], [RFC1035], and the subsequent documents that
+ update them; particularly, [RFC2181] and [RFC2308].
+
+ This document defines the DNSSEC protocol operations.
+
+1.2. Reserved Words
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+2. Zone Signing
+
+ DNSSEC introduces the concept of signed zones. A signed zone
+ includes DNS Public Key (DNSKEY), Resource Record Signature (RRSIG),
+ Next Secure (NSEC), and (optionally) Delegation Signer (DS) records
+ according to the rules specified in Sections 2.1, 2.2, 2.3, and 2.4,
+ respectively. A zone that does not include these records according
+ to the rules in this section is an unsigned zone.
+
+ DNSSEC requires a change to the definition of the CNAME resource
+ record ([RFC1035]). Section 2.5 changes the CNAME RR to allow RRSIG
+ and NSEC RRs to appear at the same owner name as does a CNAME RR.
+
+ DNSSEC specifies the placement of two new RR types, NSEC and DS,
+ which can be placed at the parental side of a zone cut (that is, at a
+ delegation point). This is an exception to the general prohibition
+ against putting data in the parent zone at a zone cut. Section 2.6
+ describes this change.
+
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 4]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+2.1. Including DNSKEY RRs in a Zone
+
+ To sign a zone, the zone's administrator generates one or more
+ public/private key pairs and uses the private key(s) to sign
+ authoritative RRsets in the zone. For each private key used to
+ create RRSIG RRs in a zone, the zone SHOULD include a zone DNSKEY RR
+ containing the corresponding public key. A zone key DNSKEY RR MUST
+ have the Zone Key bit of the flags RDATA field set (see Section 2.1.1
+ of [RFC4034]). Public keys associated with other DNS operations MAY
+ be stored in DNSKEY RRs that are not marked as zone keys but MUST NOT
+ be used to verify RRSIGs.
+
+ If the zone administrator intends a signed zone to be usable other
+ than as an island of security, the zone apex MUST contain at least
+ one DNSKEY RR to act as a secure entry point into the zone. This
+ secure entry point could then be used as the target of a secure
+ delegation via a corresponding DS RR in the parent zone (see
+ [RFC4034]).
+
+2.2. Including RRSIG RRs in a Zone
+
+ For each authoritative RRset in a signed zone, there MUST be at least
+ one RRSIG record that meets the following requirements:
+
+ o The RRSIG owner name is equal to the RRset owner name.
+
+ o The RRSIG class is equal to the RRset class.
+
+ o The RRSIG Type Covered field is equal to the RRset type.
+
+ o The RRSIG Original TTL field is equal to the TTL of the RRset.
+
+ o The RRSIG RR's TTL is equal to the TTL of the RRset.
+
+ o The RRSIG Labels field is equal to the number of labels in the
+ RRset owner name, not counting the null root label and not
+ counting the leftmost label if it is a wildcard.
+
+ o The RRSIG Signer's Name field is equal to the name of the zone
+ containing the RRset.
+
+ o The RRSIG Algorithm, Signer's Name, and Key Tag fields identify a
+ zone key DNSKEY record at the zone apex.
+
+ The process for constructing the RRSIG RR for a given RRset is
+ described in [RFC4034]. An RRset MAY have multiple RRSIG RRs
+ associated with it. Note that as RRSIG RRs are closely tied to the
+ RRsets whose signatures they contain, RRSIG RRs, unlike all other DNS
+
+
+
+Arends, et al. Standards Track [Page 5]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ RR types, do not form RRsets. In particular, the TTL values among
+ RRSIG RRs with a common owner name do not follow the RRset rules
+ described in [RFC2181].
+
+ An RRSIG RR itself MUST NOT be signed, as signing an RRSIG RR would
+ add no value and would create an infinite loop in the signing
+ process.
+
+ The NS RRset that appears at the zone apex name MUST be signed, but
+ the NS RRsets that appear at delegation points (that is, the NS
+ RRsets in the parent zone that delegate the name to the child zone's
+ name servers) MUST NOT be signed. Glue address RRsets associated
+ with delegations MUST NOT be signed.
+
+ There MUST be an RRSIG for each RRset using at least one DNSKEY of
+ each algorithm in the zone apex DNSKEY RRset. The apex DNSKEY RRset
+ itself MUST be signed by each algorithm appearing in the DS RRset
+ located at the delegating parent (if any).
+
+2.3. Including NSEC RRs in a Zone
+
+ Each owner name in the zone that has authoritative data or a
+ delegation point NS RRset MUST have an NSEC resource record. The
+ format of NSEC RRs and the process for constructing the NSEC RR for a
+ given name is described in [RFC4034].
+
+ The TTL value for any NSEC RR SHOULD be the same as the minimum TTL
+ value field in the zone SOA RR.
+
+ An NSEC record (and its associated RRSIG RRset) MUST NOT be the only
+ RRset at any particular owner name. That is, the signing process
+ MUST NOT create NSEC or RRSIG RRs for owner name nodes that were not
+ the owner name of any RRset before the zone was signed. The main
+ reasons for this are a desire for namespace consistency between
+ signed and unsigned versions of the same zone and a desire to reduce
+ the risk of response inconsistency in security oblivious recursive
+ name servers.
+
+ The type bitmap of every NSEC resource record in a signed zone MUST
+ indicate the presence of both the NSEC record itself and its
+ corresponding RRSIG record.
+
+ The difference between the set of owner names that require RRSIG
+ records and the set of owner names that require NSEC records is
+ subtle and worth highlighting. RRSIG records are present at the
+ owner names of all authoritative RRsets. NSEC records are present at
+ the owner names of all names for which the signed zone is
+ authoritative and also at the owner names of delegations from the
+
+
+
+Arends, et al. Standards Track [Page 6]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ signed zone to its children. Neither NSEC nor RRSIG records are
+ present (in the parent zone) at the owner names of glue address
+ RRsets. Note, however, that this distinction is for the most part
+ visible only during the zone signing process, as NSEC RRsets are
+ authoritative data and are therefore signed. Thus, any owner name
+ that has an NSEC RRset will have RRSIG RRs as well in the signed
+ zone.
+
+ The bitmap for the NSEC RR at a delegation point requires special
+ attention. Bits corresponding to the delegation NS RRset and any
+ RRsets for which the parent zone has authoritative data MUST be set;
+ bits corresponding to any non-NS RRset for which the parent is not
+ authoritative MUST be clear.
+
+2.4. Including DS RRs in a Zone
+
+ The DS resource record establishes authentication chains between DNS
+ zones. A DS RRset SHOULD be present at a delegation point when the
+ child zone is signed. The DS RRset MAY contain multiple records,
+ each referencing a public key in the child zone used to verify the
+ RRSIGs in that zone. All DS RRsets in a zone MUST be signed, and DS
+ RRsets MUST NOT appear at a zone's apex.
+
+ A DS RR SHOULD point to a DNSKEY RR that is present in the child's
+ apex DNSKEY RRset, and the child's apex DNSKEY RRset SHOULD be signed
+ by the corresponding private key. DS RRs that fail to meet these
+ conditions are not useful for validation, but because the DS RR and
+ its corresponding DNSKEY RR are in different zones, and because the
+ DNS is only loosely consistent, temporary mismatches can occur.
+
+ The TTL of a DS RRset SHOULD match the TTL of the delegating NS RRset
+ (that is, the NS RRset from the same zone containing the DS RRset).
+
+ Construction of a DS RR requires knowledge of the corresponding
+ DNSKEY RR in the child zone, which implies communication between the
+ child and parent zones. This communication is an operational matter
+ not covered by this document.
+
+2.5. Changes to the CNAME Resource Record
+
+ If a CNAME RRset is present at a name in a signed zone, appropriate
+ RRSIG and NSEC RRsets are REQUIRED at that name. A KEY RRset at that
+ name for secure dynamic update purposes is also allowed ([RFC3007]).
+ Other types MUST NOT be present at that name.
+
+ This is a modification to the original CNAME definition given in
+ [RFC1034]. The original definition of the CNAME RR did not allow any
+ other types to coexist with a CNAME record, but a signed zone
+
+
+
+Arends, et al. Standards Track [Page 7]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ requires NSEC and RRSIG RRs for every authoritative name. To resolve
+ this conflict, this specification modifies the definition of the
+ CNAME resource record to allow it to coexist with NSEC and RRSIG RRs.
+
+2.6. DNSSEC RR Types Appearing at Zone Cuts
+
+ DNSSEC introduced two new RR types that are unusual in that they can
+ appear at the parental side of a zone cut. At the parental side of a
+ zone cut (that is, at a delegation point), NSEC RRs are REQUIRED at
+ the owner name. A DS RR could also be present if the zone being
+ delegated is signed and seeks to have a chain of authentication to
+ the parent zone. This is an exception to the original DNS
+ specification ([RFC1034]), which states that only NS RRsets could
+ appear at the parental side of a zone cut.
+
+ This specification updates the original DNS specification to allow
+ NSEC and DS RR types at the parent side of a zone cut. These RRsets
+ are authoritative for the parent when they appear at the parent side
+ of a zone cut.
+
+2.7. Example of a Secure Zone
+
+ Appendix A shows a complete example of a small signed zone.
+
+3. Serving
+
+ This section describes the behavior of entities that include
+ security-aware name server functions. In many cases such functions
+ will be part of a security-aware recursive name server, but a
+ security-aware authoritative name server has some of the same
+ requirements. Functions specific to security-aware recursive name
+ servers are described in Section 3.2; functions specific to
+ authoritative servers are described in Section 3.1.
+
+ In the following discussion, the terms "SNAME", "SCLASS", and "STYPE"
+ are as used in [RFC1034].
+
+ A security-aware name server MUST support the EDNS0 ([RFC2671])
+ message size extension, MUST support a message size of at least 1220
+ octets, and SHOULD support a message size of 4000 octets. As IPv6
+ packets can only be fragmented by the source host, a security aware
+ name server SHOULD take steps to ensure that UDP datagrams it
+ transmits over IPv6 are fragmented, if necessary, at the minimum IPv6
+ MTU, unless the path MTU is known. Please see [RFC1122], [RFC2460],
+ and [RFC3226] for further discussion of packet size and fragmentation
+ issues.
+
+
+
+
+
+Arends, et al. Standards Track [Page 8]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ A security-aware name server that receives a DNS query that does not
+ include the EDNS OPT pseudo-RR or that has the DO bit clear MUST
+ treat the RRSIG, DNSKEY, and NSEC RRs as it would any other RRset and
+ MUST NOT perform any of the additional processing described below.
+ Because the DS RR type has the peculiar property of only existing in
+ the parent zone at delegation points, DS RRs always require some
+ special processing, as described in Section 3.1.4.1.
+
+ Security aware name servers that receive explicit queries for
+ security RR types that match the content of more than one zone that
+ it serves (for example, NSEC and RRSIG RRs above and below a
+ delegation point where the server is authoritative for both zones)
+ should behave self-consistently. As long as the response is always
+ consistent for each query to the name server, the name server MAY
+ return one of the following:
+
+ o The above-delegation RRsets.
+ o The below-delegation RRsets.
+ o Both above and below-delegation RRsets.
+ o Empty answer section (no records).
+ o Some other response.
+ o An error.
+
+ DNSSEC allocates two new bits in the DNS message header: the CD
+ (Checking Disabled) bit and the AD (Authentic Data) bit. The CD bit
+ is controlled by resolvers; a security-aware name server MUST copy
+ the CD bit from a query into the corresponding response. The AD bit
+ is controlled by name servers; a security-aware name server MUST
+ ignore the setting of the AD bit in queries. See Sections 3.1.6,
+ 3.2.2, 3.2.3, 4, and 4.9 for details on the behavior of these bits.
+
+ A security aware name server that synthesizes CNAME RRs from DNAME
+ RRs as described in [RFC2672] SHOULD NOT generate signatures for the
+ synthesized CNAME RRs.
+
+3.1. Authoritative Name Servers
+
+ Upon receiving a relevant query that has the EDNS ([RFC2671]) OPT
+ pseudo-RR DO bit ([RFC3225]) set, a security-aware authoritative name
+ server for a signed zone MUST include additional RRSIG, NSEC, and DS
+ RRs, according to the following rules:
+
+ o RRSIG RRs that can be used to authenticate a response MUST be
+ included in the response according to the rules in Section 3.1.1.
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 9]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ o NSEC RRs that can be used to provide authenticated denial of
+ existence MUST be included in the response automatically according
+ to the rules in Section 3.1.3.
+
+ o Either a DS RRset or an NSEC RR proving that no DS RRs exist MUST
+ be included in referrals automatically according to the rules in
+ Section 3.1.4.
+
+ These rules only apply to responses where the semantics convey
+ information about the presence or absence of resource records. That
+ is, these rules are not intended to rule out responses such as RCODE
+ 4 ("Not Implemented") or RCODE 5 ("Refused").
+
+ DNSSEC does not change the DNS zone transfer protocol. Section 3.1.5
+ discusses zone transfer requirements.
+
+3.1.1. Including RRSIG RRs in a Response
+
+ When responding to a query that has the DO bit set, a security-aware
+ authoritative name server SHOULD attempt to send RRSIG RRs that a
+ security-aware resolver can use to authenticate the RRsets in the
+ response. A name server SHOULD make every attempt to keep the RRset
+ and its associated RRSIG(s) together in a response. Inclusion of
+ RRSIG RRs in a response is subject to the following rules:
+
+ o When placing a signed RRset in the Answer section, the name server
+ MUST also place its RRSIG RRs in the Answer section. The RRSIG
+ RRs have a higher priority for inclusion than any other RRsets
+ that may have to be included. If space does not permit inclusion
+ of these RRSIG RRs, the name server MUST set the TC bit.
+
+ o When placing a signed RRset in the Authority section, the name
+ server MUST also place its RRSIG RRs in the Authority section.
+ The RRSIG RRs have a higher priority for inclusion than any other
+ RRsets that may have to be included. If space does not permit
+ inclusion of these RRSIG RRs, the name server MUST set the TC bit.
+
+ o When placing a signed RRset in the Additional section, the name
+ server MUST also place its RRSIG RRs in the Additional section.
+ If space does not permit inclusion of both the RRset and its
+ associated RRSIG RRs, the name server MAY retain the RRset while
+ dropping the RRSIG RRs. If this happens, the name server MUST NOT
+ set the TC bit solely because these RRSIG RRs didn't fit.
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 10]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+3.1.2. Including DNSKEY RRs in a Response
+
+ When responding to a query that has the DO bit set and that requests
+ the SOA or NS RRs at the apex of a signed zone, a security-aware
+ authoritative name server for that zone MAY return the zone apex
+ DNSKEY RRset in the Additional section. In this situation, the
+ DNSKEY RRset and associated RRSIG RRs have lower priority than does
+ any other information that would be placed in the additional section.
+ The name server SHOULD NOT include the DNSKEY RRset unless there is
+ enough space in the response message for both the DNSKEY RRset and
+ its associated RRSIG RR(s). If there is not enough space to include
+ these DNSKEY and RRSIG RRs, the name server MUST omit them and MUST
+ NOT set the TC bit solely because these RRs didn't fit (see Section
+ 3.1.1).
+
+3.1.3. Including NSEC RRs in a Response
+
+ When responding to a query that has the DO bit set, a security-aware
+ authoritative name server for a signed zone MUST include NSEC RRs in
+ each of the following cases:
+
+ No Data: The zone contains RRsets that exactly match <SNAME, SCLASS>
+ but does not contain any RRsets that exactly match <SNAME, SCLASS,
+ STYPE>.
+
+ Name Error: The zone does not contain any RRsets that match <SNAME,
+ SCLASS> either exactly or via wildcard name expansion.
+
+ Wildcard Answer: The zone does not contain any RRsets that exactly
+ match <SNAME, SCLASS> but does contain an RRset that matches
+ <SNAME, SCLASS, STYPE> via wildcard name expansion.
+
+ Wildcard No Data: The zone does not contain any RRsets that exactly
+ match <SNAME, SCLASS> and does contain one or more RRsets that
+ match <SNAME, SCLASS> via wildcard name expansion, but does not
+ contain any RRsets that match <SNAME, SCLASS, STYPE> via wildcard
+ name expansion.
+
+ In each of these cases, the name server includes NSEC RRs in the
+ response to prove that an exact match for <SNAME, SCLASS, STYPE> was
+ not present in the zone and that the response that the name server is
+ returning is correct given the data in the zone.
+
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 11]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+3.1.3.1. Including NSEC RRs: No Data Response
+
+ If the zone contains RRsets matching <SNAME, SCLASS> but contains no
+ RRset matching <SNAME, SCLASS, STYPE>, then the name server MUST
+ include the NSEC RR for <SNAME, SCLASS> along with its associated
+ RRSIG RR(s) in the Authority section of the response (see Section
+ 3.1.1). If space does not permit inclusion of the NSEC RR or its
+ associated RRSIG RR(s), the name server MUST set the TC bit (see
+ Section 3.1.1).
+
+ Since the search name exists, wildcard name expansion does not apply
+ to this query, and a single signed NSEC RR suffices to prove that the
+ requested RR type does not exist.
+
+3.1.3.2. Including NSEC RRs: Name Error Response
+
+ If the zone does not contain any RRsets matching <SNAME, SCLASS>
+ either exactly or via wildcard name expansion, then the name server
+ MUST include the following NSEC RRs in the Authority section, along
+ with their associated RRSIG RRs:
+
+ o An NSEC RR proving that there is no exact match for <SNAME,
+ SCLASS>.
+
+ o An NSEC RR proving that the zone contains no RRsets that would
+ match <SNAME, SCLASS> via wildcard name expansion.
+
+ In some cases, a single NSEC RR may prove both of these points. If
+ it does, the name server SHOULD only include the NSEC RR and its
+ RRSIG RR(s) once in the Authority section.
+
+ If space does not permit inclusion of these NSEC and RRSIG RRs, the
+ name server MUST set the TC bit (see Section 3.1.1).
+
+ The owner names of these NSEC and RRSIG RRs are not subject to
+ wildcard name expansion when these RRs are included in the Authority
+ section of the response.
+
+ Note that this form of response includes cases in which SNAME
+ corresponds to an empty non-terminal name within the zone (a name
+ that is not the owner name for any RRset but that is the parent name
+ of one or more RRsets).
+
+3.1.3.3. Including NSEC RRs: Wildcard Answer Response
+
+ If the zone does not contain any RRsets that exactly match <SNAME,
+ SCLASS> but does contain an RRset that matches <SNAME, SCLASS, STYPE>
+ via wildcard name expansion, the name server MUST include the
+
+
+
+Arends, et al. Standards Track [Page 12]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ wildcard-expanded answer and the corresponding wildcard-expanded
+ RRSIG RRs in the Answer section and MUST include in the Authority
+ section an NSEC RR and associated RRSIG RR(s) proving that the zone
+ does not contain a closer match for <SNAME, SCLASS>. If space does
+ not permit inclusion of the answer, NSEC and RRSIG RRs, the name
+ server MUST set the TC bit (see Section 3.1.1).
+
+3.1.3.4. Including NSEC RRs: Wildcard No Data Response
+
+ This case is a combination of the previous cases. The zone does not
+ contain an exact match for <SNAME, SCLASS>, and although the zone
+ does contain RRsets that match <SNAME, SCLASS> via wildcard
+ expansion, none of those RRsets matches STYPE. The name server MUST
+ include the following NSEC RRs in the Authority section, along with
+ their associated RRSIG RRs:
+
+ o An NSEC RR proving that there are no RRsets matching STYPE at the
+ wildcard owner name that matched <SNAME, SCLASS> via wildcard
+ expansion.
+
+ o An NSEC RR proving that there are no RRsets in the zone that would
+ have been a closer match for <SNAME, SCLASS>.
+
+ In some cases, a single NSEC RR may prove both of these points. If
+ it does, the name server SHOULD only include the NSEC RR and its
+ RRSIG RR(s) once in the Authority section.
+
+ The owner names of these NSEC and RRSIG RRs are not subject to
+ wildcard name expansion when these RRs are included in the Authority
+ section of the response.
+
+ If space does not permit inclusion of these NSEC and RRSIG RRs, the
+ name server MUST set the TC bit (see Section 3.1.1).
+
+3.1.3.5. Finding the Right NSEC RRs
+
+ As explained above, there are several situations in which a
+ security-aware authoritative name server has to locate an NSEC RR
+ that proves that no RRsets matching a particular SNAME exist.
+ Locating such an NSEC RR within an authoritative zone is relatively
+ simple, at least in concept. The following discussion assumes that
+ the name server is authoritative for the zone that would have held
+ the non-existent RRsets matching SNAME. The algorithm below is
+ written for clarity, not for efficiency.
+
+ To find the NSEC that proves that no RRsets matching name N exist in
+ the zone Z that would have held them, construct a sequence, S,
+ consisting of the owner names of every RRset in Z, sorted into
+
+
+
+Arends, et al. Standards Track [Page 13]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ canonical order ([RFC4034]), with no duplicate names. Find the name
+ M that would have immediately preceded N in S if any RRsets with
+ owner name N had existed. M is the owner name of the NSEC RR that
+ proves that no RRsets exist with owner name N.
+
+ The algorithm for finding the NSEC RR that proves that a given name
+ is not covered by any applicable wildcard is similar but requires an
+ extra step. More precisely, the algorithm for finding the NSEC
+ proving that no RRsets exist with the applicable wildcard name is
+ precisely the same as the algorithm for finding the NSEC RR that
+ proves that RRsets with any other owner name do not exist. The part
+ that's missing is a method of determining the name of the non-
+ existent applicable wildcard. In practice, this is easy, because the
+ authoritative name server has already checked for the presence of
+ precisely this wildcard name as part of step (1)(c) of the normal
+ lookup algorithm described in Section 4.3.2 of [RFC1034].
+
+3.1.4. Including DS RRs in a Response
+
+ When responding to a query that has the DO bit set, a security-aware
+ authoritative name server returning a referral includes DNSSEC data
+ along with the NS RRset.
+
+ If a DS RRset is present at the delegation point, the name server
+ MUST return both the DS RRset and its associated RRSIG RR(s) in the
+ Authority section along with the NS RRset.
+
+ If no DS RRset is present at the delegation point, the name server
+ MUST return both the NSEC RR that proves that the DS RRset is not
+ present and the NSEC RR's associated RRSIG RR(s) along with the NS
+ RRset. The name server MUST place the NS RRset before the NSEC RRset
+ and its associated RRSIG RR(s).
+
+ Including these DS, NSEC, and RRSIG RRs increases the size of
+ referral messages and may cause some or all glue RRs to be omitted.
+ If space does not permit inclusion of the DS or NSEC RRset and
+ associated RRSIG RRs, the name server MUST set the TC bit (see
+ Section 3.1.1).
+
+3.1.4.1. Responding to Queries for DS RRs
+
+ The DS resource record type is unusual in that it appears only on the
+ parent zone's side of a zone cut. For example, the DS RRset for the
+ delegation of "foo.example" is stored in the "example" zone rather
+ than in the "foo.example" zone. This requires special processing
+ rules for both name servers and resolvers, as the name server for the
+ child zone is authoritative for the name at the zone cut by the
+ normal DNS rules but the child zone does not contain the DS RRset.
+
+
+
+Arends, et al. Standards Track [Page 14]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ A security-aware resolver sends queries to the parent zone when
+ looking for a needed DS RR at a delegation point (see Section 4.2).
+ However, special rules are necessary to avoid confusing
+ security-oblivious resolvers which might become involved in
+ processing such a query (for example, in a network configuration that
+ forces a security-aware resolver to channel its queries through a
+ security-oblivious recursive name server). The rest of this section
+ describes how a security-aware name server processes DS queries in
+ order to avoid this problem.
+
+ The need for special processing by a security-aware name server only
+ arises when all the following conditions are met:
+
+ o The name server has received a query for the DS RRset at a zone
+ cut.
+
+ o The name server is authoritative for the child zone.
+
+ o The name server is not authoritative for the parent zone.
+
+ o The name server does not offer recursion.
+
+ In all other cases, the name server either has some way of obtaining
+ the DS RRset or could not have been expected to have the DS RRset
+ even by the pre-DNSSEC processing rules, so the name server can
+ return either the DS RRset or an error response according to the
+ normal processing rules.
+
+ If all the above conditions are met, however, the name server is
+ authoritative for SNAME but cannot supply the requested RRset. In
+ this case, the name server MUST return an authoritative "no data"
+ response showing that the DS RRset does not exist in the child zone's
+ apex. See Appendix B.8 for an example of such a response.
+
+3.1.5. Responding to Queries for Type AXFR or IXFR
+
+ DNSSEC does not change the DNS zone transfer process. A signed zone
+ will contain RRSIG, DNSKEY, NSEC, and DS resource records, but these
+ records have no special meaning with respect to a zone transfer
+ operation.
+
+ An authoritative name server is not required to verify that a zone is
+ properly signed before sending or accepting a zone transfer.
+ However, an authoritative name server MAY choose to reject the entire
+ zone transfer if the zone fails to meet any of the signing
+ requirements described in Section 2. The primary objective of a zone
+ transfer is to ensure that all authoritative name servers have
+ identical copies of the zone. An authoritative name server that
+
+
+
+Arends, et al. Standards Track [Page 15]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ chooses to perform its own zone validation MUST NOT selectively
+ reject some RRs and accept others.
+
+ DS RRsets appear only on the parental side of a zone cut and are
+ authoritative data in the parent zone. As with any other
+ authoritative RRset, the DS RRset MUST be included in zone transfers
+ of the zone in which the RRset is authoritative data. In the case of
+ the DS RRset, this is the parent zone.
+
+ NSEC RRs appear in both the parent and child zones at a zone cut and
+ are authoritative data in both the parent and child zones. The
+ parental and child NSEC RRs at a zone cut are never identical to each
+ other, as the NSEC RR in the child zone's apex will always indicate
+ the presence of the child zone's SOA RR whereas the parental NSEC RR
+ at the zone cut will never indicate the presence of an SOA RR. As
+ with any other authoritative RRs, NSEC RRs MUST be included in zone
+ transfers of the zone in which they are authoritative data. The
+ parental NSEC RR at a zone cut MUST be included in zone transfers of
+ the parent zone, and the NSEC at the zone apex of the child zone MUST
+ be included in zone transfers of the child zone.
+
+ RRSIG RRs appear in both the parent and child zones at a zone cut and
+ are authoritative in whichever zone contains the authoritative RRset
+ for which the RRSIG RR provides the signature. That is, the RRSIG RR
+ for a DS RRset or a parental NSEC RR at a zone cut will be
+ authoritative in the parent zone, and the RRSIG for any RRset in the
+ child zone's apex will be authoritative in the child zone. Parental
+ and child RRSIG RRs at a zone cut will never be identical to each
+ other, as the Signer's Name field of an RRSIG RR in the child zone's
+ apex will indicate a DNSKEY RR in the child zone's apex whereas the
+ same field of a parental RRSIG RR at the zone cut will indicate a
+ DNSKEY RR in the parent zone's apex. As with any other authoritative
+ RRs, RRSIG RRs MUST be included in zone transfers of the zone in
+ which they are authoritative data.
+
+3.1.6. The AD and CD Bits in an Authoritative Response
+
+ The CD and AD bits are designed for use in communication between
+ security-aware resolvers and security-aware recursive name servers.
+ These bits are for the most part not relevant to query processing by
+ security-aware authoritative name servers.
+
+ A security-aware name server does not perform signature validation
+ for authoritative data during query processing, even when the CD bit
+ is clear. A security-aware name server SHOULD clear the CD bit when
+ composing an authoritative response.
+
+
+
+
+
+Arends, et al. Standards Track [Page 16]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ A security-aware name server MUST NOT set the AD bit in a response
+ unless the name server considers all RRsets in the Answer and
+ Authority sections of the response to be authentic. A security-aware
+ name server's local policy MAY consider data from an authoritative
+ zone to be authentic without further validation. However, the name
+ server MUST NOT do so unless the name server obtained the
+ authoritative zone via secure means (such as a secure zone transfer
+ mechanism) and MUST NOT do so unless this behavior has been
+ configured explicitly.
+
+ A security-aware name server that supports recursion MUST follow the
+ rules for the CD and AD bits given in Section 3.2 when generating a
+ response that involves data obtained via recursion.
+
+3.2. Recursive Name Servers
+
+ As explained in [RFC4033], a security-aware recursive name server is
+ an entity that acts in both the security-aware name server and
+ security-aware resolver roles. This section uses the terms "name
+ server side" and "resolver side" to refer to the code within a
+ security-aware recursive name server that implements the
+ security-aware name server role and the code that implements the
+ security-aware resolver role, respectively.
+
+ The resolver side follows the usual rules for caching and negative
+ caching that would apply to any security-aware resolver.
+
+3.2.1. The DO Bit
+
+ The resolver side of a security-aware recursive name server MUST set
+ the DO bit when sending requests, regardless of the state of the DO
+ bit in the initiating request received by the name server side. If
+ the DO bit in an initiating query is not set, the name server side
+ MUST strip any authenticating DNSSEC RRs from the response but MUST
+ NOT strip any DNSSEC RR types that the initiating query explicitly
+ requested.
+
+3.2.2. The CD Bit
+
+ The CD bit exists in order to allow a security-aware resolver to
+ disable signature validation in a security-aware name server's
+ processing of a particular query.
+
+ The name server side MUST copy the setting of the CD bit from a query
+ to the corresponding response.
+
+ The name server side of a security-aware recursive name server MUST
+ pass the state of the CD bit to the resolver side along with the rest
+
+
+
+Arends, et al. Standards Track [Page 17]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ of an initiating query, so that the resolver side will know whether
+ it is required to verify the response data it returns to the name
+ server side. If the CD bit is set, it indicates that the originating
+ resolver is willing to perform whatever authentication its local
+ policy requires. Thus, the resolver side of the recursive name
+ server need not perform authentication on the RRsets in the response.
+ When the CD bit is set, the recursive name server SHOULD, if
+ possible, return the requested data to the originating resolver, even
+ if the recursive name server's local authentication policy would
+ reject the records in question. That is, by setting the CD bit, the
+ originating resolver has indicated that it takes responsibility for
+ performing its own authentication, and the recursive name server
+ should not interfere.
+
+ If the resolver side implements a BAD cache (see Section 4.7) and the
+ name server side receives a query that matches an entry in the
+ resolver side's BAD cache, the name server side's response depends on
+ the state of the CD bit in the original query. If the CD bit is set,
+ the name server side SHOULD return the data from the BAD cache; if
+ the CD bit is not set, the name server side MUST return RCODE 2
+ (server failure).
+
+ The intent of the above rule is to provide the raw data to clients
+ that are capable of performing their own signature verification
+ checks while protecting clients that depend on the resolver side of a
+ security-aware recursive name server to perform such checks. Several
+ of the possible reasons why signature validation might fail involve
+ conditions that may not apply equally to the recursive name server
+ and the client that invoked it. For example, the recursive name
+ server's clock may be set incorrectly, or the client may have
+ knowledge of a relevant island of security that the recursive name
+ server does not share. In such cases, "protecting" a client that is
+ capable of performing its own signature validation from ever seeing
+ the "bad" data does not help the client.
+
+3.2.3. The AD Bit
+
+ The name server side of a security-aware recursive name server MUST
+ NOT set the AD bit in a response unless the name server considers all
+ RRsets in the Answer and Authority sections of the response to be
+ authentic. The name server side SHOULD set the AD bit if and only if
+ the resolver side considers all RRsets in the Answer section and any
+ relevant negative response RRs in the Authority section to be
+ authentic. The resolver side MUST follow the procedure described in
+ Section 5 to determine whether the RRs in question are authentic.
+ However, for backward compatibility, a recursive name server MAY set
+ the AD bit when a response includes unsigned CNAME RRs if those CNAME
+
+
+
+
+Arends, et al. Standards Track [Page 18]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ RRs demonstrably could have been synthesized from an authentic DNAME
+ RR that is also included in the response according to the synthesis
+ rules described in [RFC2672].
+
+3.3. Example DNSSEC Responses
+
+ See Appendix B for example response packets.
+
+4. Resolving
+
+ This section describes the behavior of entities that include
+ security-aware resolver functions. In many cases such functions will
+ be part of a security-aware recursive name server, but a stand-alone
+ security-aware resolver has many of the same requirements. Functions
+ specific to security-aware recursive name servers are described in
+ Section 3.2.
+
+4.1. EDNS Support
+
+ A security-aware resolver MUST include an EDNS ([RFC2671]) OPT
+ pseudo-RR with the DO ([RFC3225]) bit set when sending queries.
+
+ A security-aware resolver MUST support a message size of at least
+ 1220 octets, SHOULD support a message size of 4000 octets, and MUST
+ use the "sender's UDP payload size" field in the EDNS OPT pseudo-RR
+ to advertise the message size that it is willing to accept. A
+ security-aware resolver's IP layer MUST handle fragmented UDP packets
+ correctly regardless of whether any such fragmented packets were
+ received via IPv4 or IPv6. Please see [RFC1122], [RFC2460], and
+ [RFC3226] for discussion of these requirements.
+
+4.2. Signature Verification Support
+
+ A security-aware resolver MUST support the signature verification
+ mechanisms described in Section 5 and SHOULD apply them to every
+ received response, except when:
+
+ o the security-aware resolver is part of a security-aware recursive
+ name server, and the response is the result of recursion on behalf
+ of a query received with the CD bit set;
+
+ o the response is the result of a query generated directly via some
+ form of application interface that instructed the security-aware
+ resolver not to perform validation for this query; or
+
+ o validation for this query has been disabled by local policy.
+
+
+
+
+
+Arends, et al. Standards Track [Page 19]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ A security-aware resolver's support for signature verification MUST
+ include support for verification of wildcard owner names.
+
+ Security-aware resolvers MAY query for missing security RRs in an
+ attempt to perform validation; implementations that choose to do so
+ must be aware that the answers received may not be sufficient to
+ validate the original response. For example, a zone update may have
+ changed (or deleted) the desired information between the original and
+ follow-up queries.
+
+ When attempting to retrieve missing NSEC RRs that reside on the
+ parental side at a zone cut, a security-aware iterative-mode resolver
+ MUST query the name servers for the parent zone, not the child zone.
+
+ When attempting to retrieve a missing DS, a security-aware
+ iterative-mode resolver MUST query the name servers for the parent
+ zone, not the child zone. As explained in Section 3.1.4.1,
+ security-aware name servers need to apply special processing rules to
+ handle the DS RR, and in some situations the resolver may also need
+ to apply special rules to locate the name servers for the parent zone
+ if the resolver does not already have the parent's NS RRset. To
+ locate the parent NS RRset, the resolver can start with the
+ delegation name, strip off the leftmost label, and query for an NS
+ RRset by that name. If no NS RRset is present at that name, the
+ resolver then strips off the leftmost remaining label and retries the
+ query for that name, repeating this process of walking up the tree
+ until it either finds the NS RRset or runs out of labels.
+
+4.3. Determining Security Status of Data
+
+ A security-aware resolver MUST be able to determine whether it should
+ expect a particular RRset to be signed. More precisely, a
+ security-aware resolver must be able to distinguish between four
+ cases:
+
+ Secure: An RRset for which the resolver is able to build a chain of
+ signed DNSKEY and DS RRs from a trusted security anchor to the
+ RRset. In this case, the RRset should be signed and is subject to
+ signature validation, as described above.
+
+ Insecure: An RRset for which the resolver knows that it has no chain
+ of signed DNSKEY and DS RRs from any trusted starting point to the
+ RRset. This can occur when the target RRset lies in an unsigned
+ zone or in a descendent of an unsigned zone. In this case, the
+ RRset may or may not be signed, but the resolver will not be able
+ to verify the signature.
+
+
+
+
+
+Arends, et al. Standards Track [Page 20]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ Bogus: An RRset for which the resolver believes that it ought to be
+ able to establish a chain of trust but for which it is unable to
+ do so, either due to signatures that for some reason fail to
+ validate or due to missing data that the relevant DNSSEC RRs
+ indicate should be present. This case may indicate an attack but
+ may also indicate a configuration error or some form of data
+ corruption.
+
+ Indeterminate: An RRset for which the resolver is not able to
+ determine whether the RRset should be signed, as the resolver is
+ not able to obtain the necessary DNSSEC RRs. This can occur when
+ the security-aware resolver is not able to contact security-aware
+ name servers for the relevant zones.
+
+4.4. Configured Trust Anchors
+
+ A security-aware resolver MUST be capable of being configured with at
+ least one trusted public key or DS RR and SHOULD be capable of being
+ configured with multiple trusted public keys or DS RRs. Since a
+ security-aware resolver will not be able to validate signatures
+ without such a configured trust anchor, the resolver SHOULD have some
+ reasonably robust mechanism for obtaining such keys when it boots;
+ examples of such a mechanism would be some form of non-volatile
+ storage (such as a disk drive) or some form of trusted local network
+ configuration mechanism.
+
+ Note that trust anchors also cover key material that is updated in a
+ secure manner. This secure manner could be through physical media, a
+ key exchange protocol, or some other out-of-band means.
+
+4.5. Response Caching
+
+ A security-aware resolver SHOULD cache each response as a single
+ atomic entry containing the entire answer, including the named RRset
+ and any associated DNSSEC RRs. The resolver SHOULD discard the
+ entire atomic entry when any of the RRs contained in it expire. In
+ most cases the appropriate cache index for the atomic entry will be
+ the triple <QNAME, QTYPE, QCLASS>, but in cases such as the response
+ form described in Section 3.1.3.2 the appropriate cache index will be
+ the double <QNAME,QCLASS>.
+
+ The reason for these recommendations is that, between the initial
+ query and the expiration of the data from the cache, the
+ authoritative data might have been changed (for example, via dynamic
+ update).
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 21]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ There are two situations for which this is relevant:
+
+ 1. By using the RRSIG record, it is possible to deduce that an
+ answer was synthesized from a wildcard. A security-aware
+ recursive name server could store this wildcard data and use it
+ to generate positive responses to queries other than the name for
+ which the original answer was first received.
+
+ 2. NSEC RRs received to prove the non-existence of a name could be
+ reused by a security-aware resolver to prove the non-existence of
+ any name in the name range it spans.
+
+ In theory, a resolver could use wildcards or NSEC RRs to generate
+ positive and negative responses (respectively) until the TTL or
+ signatures on the records in question expire. However, it seems
+ prudent for resolvers to avoid blocking new authoritative data or
+ synthesizing new data on their own. Resolvers that follow this
+ recommendation will have a more consistent view of the namespace.
+
+4.6. Handling of the CD and AD Bits
+
+ A security-aware resolver MAY set a query's CD bit in order to
+ indicate that the resolver takes responsibility for performing
+ whatever authentication its local policy requires on the RRsets in
+ the response. See Section 3.2 for the effect this bit has on the
+ behavior of security-aware recursive name servers.
+
+ A security-aware resolver MUST clear the AD bit when composing query
+ messages to protect against buggy name servers that blindly copy
+ header bits that they do not understand from the query message to the
+ response message.
+
+ A resolver MUST disregard the meaning of the CD and AD bits in a
+ response unless the response was obtained by using a secure channel
+ or the resolver was specifically configured to regard the message
+ header bits without using a secure channel.
+
+4.7. Caching BAD Data
+
+ While many validation errors will be transient, some are likely to be
+ more persistent, such as those caused by administrative error
+ (failure to re-sign a zone, clock skew, and so forth). Since
+ requerying will not help in these cases, validating resolvers might
+ generate a significant amount of unnecessary DNS traffic as a result
+ of repeated queries for RRsets with persistent validation failures.
+
+ To prevent such unnecessary DNS traffic, security-aware resolvers MAY
+ cache data with invalid signatures, with some restrictions.
+
+
+
+Arends, et al. Standards Track [Page 22]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ Conceptually, caching such data is similar to negative caching
+ ([RFC2308]), except that instead of caching a valid negative
+ response, the resolver is caching the fact that a particular answer
+ failed to validate. This document refers to a cache of data with
+ invalid signatures as a "BAD cache".
+
+ Resolvers that implement a BAD cache MUST take steps to prevent the
+ cache from being useful as a denial-of-service attack amplifier,
+ particularly the following:
+
+ o Since RRsets that fail to validate do not have trustworthy TTLs,
+ the implementation MUST assign a TTL. This TTL SHOULD be small,
+ in order to mitigate the effect of caching the results of an
+ attack.
+
+ o In order to prevent caching of a transient validation failure
+ (which might be the result of an attack), resolvers SHOULD track
+ queries that result in validation failures and SHOULD only answer
+ from the BAD cache after the number of times that responses to
+ queries for that particular <QNAME, QTYPE, QCLASS> have failed to
+ validate exceeds a threshold value.
+
+ Resolvers MUST NOT return RRsets from the BAD cache unless the
+ resolver is not required to validate the signatures of the RRsets in
+ question under the rules given in Section 4.2 of this document. See
+ Section 3.2.2 for discussion of how the responses returned by a
+ security-aware recursive name server interact with a BAD cache.
+
+4.8. Synthesized CNAMEs
+
+ A validating security-aware resolver MUST treat the signature of a
+ valid signed DNAME RR as also covering unsigned CNAME RRs that could
+ have been synthesized from the DNAME RR, as described in [RFC2672],
+ at least to the extent of not rejecting a response message solely
+ because it contains such CNAME RRs. The resolver MAY retain such
+ CNAME RRs in its cache or in the answers it hands back, but is not
+ required to do so.
+
+4.9. Stub Resolvers
+
+ A security-aware stub resolver MUST support the DNSSEC RR types, at
+ least to the extent of not mishandling responses just because they
+ contain DNSSEC RRs.
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 23]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+4.9.1. Handling of the DO Bit
+
+ A non-validating security-aware stub resolver MAY include the DNSSEC
+ RRs returned by a security-aware recursive name server as part of the
+ data that the stub resolver hands back to the application that
+ invoked it, but is not required to do so. A non-validating stub
+ resolver that seeks to do this will need to set the DO bit in order
+ to receive DNSSEC RRs from the recursive name server.
+
+ A validating security-aware stub resolver MUST set the DO bit,
+ because otherwise it will not receive the DNSSEC RRs it needs to
+ perform signature validation.
+
+4.9.2. Handling of the CD Bit
+
+ A non-validating security-aware stub resolver SHOULD NOT set the CD
+ bit when sending queries unless it is requested by the application
+ layer, as by definition, a non-validating stub resolver depends on
+ the security-aware recursive name server to perform validation on its
+ behalf.
+
+ A validating security-aware stub resolver SHOULD set the CD bit,
+ because otherwise the security-aware recursive name server will
+ answer the query using the name server's local policy, which may
+ prevent the stub resolver from receiving data that would be
+ acceptable to the stub resolver's local policy.
+
+4.9.3. Handling of the AD Bit
+
+ A non-validating security-aware stub resolver MAY chose to examine
+ the setting of the AD bit in response messages that it receives in
+ order to determine whether the security-aware recursive name server
+ that sent the response claims to have cryptographically verified the
+ data in the Answer and Authority sections of the response message.
+ Note, however, that the responses received by a security-aware stub
+ resolver are heavily dependent on the local policy of the
+ security-aware recursive name server. Therefore, there may be little
+ practical value in checking the status of the AD bit, except perhaps
+ as a debugging aid. In any case, a security-aware stub resolver MUST
+ NOT place any reliance on signature validation allegedly performed on
+ its behalf, except when the security-aware stub resolver obtained the
+ data in question from a trusted security-aware recursive name server
+ via a secure channel.
+
+ A validating security-aware stub resolver SHOULD NOT examine the
+ setting of the AD bit in response messages, as, by definition, the
+ stub resolver performs its own signature validation regardless of the
+ setting of the AD bit.
+
+
+
+Arends, et al. Standards Track [Page 24]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+5. Authenticating DNS Responses
+
+ To use DNSSEC RRs for authentication, a security-aware resolver
+ requires configured knowledge of at least one authenticated DNSKEY or
+ DS RR. The process for obtaining and authenticating this initial
+ trust anchor is achieved via some external mechanism. For example, a
+ resolver could use some off-line authenticated exchange to obtain a
+ zone's DNSKEY RR or to obtain a DS RR that identifies and
+ authenticates a zone's DNSKEY RR. The remainder of this section
+ assumes that the resolver has somehow obtained an initial set of
+ trust anchors.
+
+ An initial DNSKEY RR can be used to authenticate a zone's apex DNSKEY
+ RRset. To authenticate an apex DNSKEY RRset by using an initial key,
+ the resolver MUST:
+
+ 1. verify that the initial DNSKEY RR appears in the apex DNSKEY
+ RRset, and that the DNSKEY RR has the Zone Key Flag (DNSKEY RDATA
+ bit 7) set; and
+
+ 2. verify that there is some RRSIG RR that covers the apex DNSKEY
+ RRset, and that the combination of the RRSIG RR and the initial
+ DNSKEY RR authenticates the DNSKEY RRset. The process for using
+ an RRSIG RR to authenticate an RRset is described in Section 5.3.
+
+ Once the resolver has authenticated the apex DNSKEY RRset by using an
+ initial DNSKEY RR, delegations from that zone can be authenticated by
+ using DS RRs. This allows a resolver to start from an initial key
+ and use DS RRsets to proceed recursively down the DNS tree, obtaining
+ other apex DNSKEY RRsets. If the resolver were configured with a
+ root DNSKEY RR, and if every delegation had a DS RR associated with
+ it, then the resolver could obtain and validate any apex DNSKEY
+ RRset. The process of using DS RRs to authenticate referrals is
+ described in Section 5.2.
+
+ Section 5.3 shows how the resolver can use DNSKEY RRs in the apex
+ DNSKEY RRset and RRSIG RRs from the zone to authenticate any other
+ RRsets in the zone once the resolver has authenticated a zone's apex
+ DNSKEY RRset. Section 5.4 shows how the resolver can use
+ authenticated NSEC RRsets from the zone to prove that an RRset is not
+ present in the zone.
+
+ When a resolver indicates support for DNSSEC (by setting the DO bit),
+ a security-aware name server should attempt to provide the necessary
+ DNSKEY, RRSIG, NSEC, and DS RRsets in a response (see Section 3).
+ However, a security-aware resolver may still receive a response that
+ lacks the appropriate DNSSEC RRs, whether due to configuration issues
+ such as an upstream security-oblivious recursive name server that
+
+
+
+Arends, et al. Standards Track [Page 25]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ accidentally interferes with DNSSEC RRs or due to a deliberate attack
+ in which an adversary forges a response, strips DNSSEC RRs from a
+ response, or modifies a query so that DNSSEC RRs appear not to be
+ requested. The absence of DNSSEC data in a response MUST NOT by
+ itself be taken as an indication that no authentication information
+ exists.
+
+ A resolver SHOULD expect authentication information from signed
+ zones. A resolver SHOULD believe that a zone is signed if the
+ resolver has been configured with public key information for the
+ zone, or if the zone's parent is signed and the delegation from the
+ parent contains a DS RRset.
+
+5.1. Special Considerations for Islands of Security
+
+ Islands of security (see [RFC4033]) are signed zones for which it is
+ not possible to construct an authentication chain to the zone from
+ its parent. Validating signatures within an island of security
+ requires that the validator have some other means of obtaining an
+ initial authenticated zone key for the island. If a validator cannot
+ obtain such a key, it SHOULD switch to operating as if the zones in
+ the island of security are unsigned.
+
+ All the normal processes for validating responses apply to islands of
+ security. The only difference between normal validation and
+ validation within an island of security is in how the validator
+ obtains a trust anchor for the authentication chain.
+
+5.2. Authenticating Referrals
+
+ Once the apex DNSKEY RRset for a signed parent zone has been
+ authenticated, DS RRsets can be used to authenticate the delegation
+ to a signed child zone. A DS RR identifies a DNSKEY RR in the child
+ zone's apex DNSKEY RRset and contains a cryptographic digest of the
+ child zone's DNSKEY RR. Use of a strong cryptographic digest
+ algorithm ensures that it is computationally infeasible for an
+ adversary to generate a DNSKEY RR that matches the digest. Thus,
+ authenticating the digest allows a resolver to authenticate the
+ matching DNSKEY RR. The resolver can then use this child DNSKEY RR
+ to authenticate the entire child apex DNSKEY RRset.
+
+ Given a DS RR for a delegation, the child zone's apex DNSKEY RRset
+ can be authenticated if all of the following hold:
+
+ o The DS RR has been authenticated using some DNSKEY RR in the
+ parent's apex DNSKEY RRset (see Section 5.3).
+
+
+
+
+
+Arends, et al. Standards Track [Page 26]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ o The Algorithm and Key Tag in the DS RR match the Algorithm field
+ and the key tag of a DNSKEY RR in the child zone's apex DNSKEY
+ RRset, and, when the DNSKEY RR's owner name and RDATA are hashed
+ using the digest algorithm specified in the DS RR's Digest Type
+ field, the resulting digest value matches the Digest field of the
+ DS RR.
+
+ o The matching DNSKEY RR in the child zone has the Zone Flag bit
+ set, the corresponding private key has signed the child zone's
+ apex DNSKEY RRset, and the resulting RRSIG RR authenticates the
+ child zone's apex DNSKEY RRset.
+
+ If the referral from the parent zone did not contain a DS RRset, the
+ response should have included a signed NSEC RRset proving that no DS
+ RRset exists for the delegated name (see Section 3.1.4). A
+ security-aware resolver MUST query the name servers for the parent
+ zone for the DS RRset if the referral includes neither a DS RRset nor
+ a NSEC RRset proving that the DS RRset does not exist (see Section
+ 4).
+
+ If the validator authenticates an NSEC RRset that proves that no DS
+ RRset is present for this zone, then there is no authentication path
+ leading from the parent to the child. If the resolver has an initial
+ DNSKEY or DS RR that belongs to the child zone or to any delegation
+ below the child zone, this initial DNSKEY or DS RR MAY be used to
+ re-establish an authentication path. If no such initial DNSKEY or DS
+ RR exists, the validator cannot authenticate RRsets in or below the
+ child zone.
+
+ If the validator does not support any of the algorithms listed in an
+ authenticated DS RRset, then the resolver has no supported
+ authentication path leading from the parent to the child. The
+ resolver should treat this case as it would the case of an
+ authenticated NSEC RRset proving that no DS RRset exists, as
+ described above.
+
+ Note that, for a signed delegation, there are two NSEC RRs associated
+ with the delegated name. One NSEC RR resides in the parent zone and
+ can be used to prove whether a DS RRset exists for the delegated
+ name. The second NSEC RR resides in the child zone and identifies
+ which RRsets are present at the apex of the child zone. The parent
+ NSEC RR and child NSEC RR can always be distinguished because the SOA
+ bit will be set in the child NSEC RR and clear in the parent NSEC RR.
+ A security-aware resolver MUST use the parent NSEC RR when attempting
+ to prove that a DS RRset does not exist.
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 27]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ If the resolver does not support any of the algorithms listed in an
+ authenticated DS RRset, then the resolver will not be able to verify
+ the authentication path to the child zone. In this case, the
+ resolver SHOULD treat the child zone as if it were unsigned.
+
+5.3. Authenticating an RRset with an RRSIG RR
+
+ A validator can use an RRSIG RR and its corresponding DNSKEY RR to
+ attempt to authenticate RRsets. The validator first checks the RRSIG
+ RR to verify that it covers the RRset, has a valid time interval, and
+ identifies a valid DNSKEY RR. The validator then constructs the
+ canonical form of the signed data by appending the RRSIG RDATA
+ (excluding the Signature Field) with the canonical form of the
+ covered RRset. Finally, the validator uses the public key and
+ signature to authenticate the signed data. Sections 5.3.1, 5.3.2,
+ and 5.3.3 describe each step in detail.
+
+5.3.1. Checking the RRSIG RR Validity
+
+ A security-aware resolver can use an RRSIG RR to authenticate an
+ RRset if all of the following conditions hold:
+
+ o The RRSIG RR and the RRset MUST have the same owner name and the
+ same class.
+
+ o The RRSIG RR's Signer's Name field MUST be the name of the zone
+ that contains the RRset.
+
+ o The RRSIG RR's Type Covered field MUST equal the RRset's type.
+
+ o The number of labels in the RRset owner name MUST be greater than
+ or equal to the value in the RRSIG RR's Labels field.
+
+ o The validator's notion of the current time MUST be less than or
+ equal to the time listed in the RRSIG RR's Expiration field.
+
+ o The validator's notion of the current time MUST be greater than or
+ equal to the time listed in the RRSIG RR's Inception field.
+
+ o The RRSIG RR's Signer's Name, Algorithm, and Key Tag fields MUST
+ match the owner name, algorithm, and key tag for some DNSKEY RR in
+ the zone's apex DNSKEY RRset.
+
+ o The matching DNSKEY RR MUST be present in the zone's apex DNSKEY
+ RRset, and MUST have the Zone Flag bit (DNSKEY RDATA Flag bit 7)
+ set.
+
+
+
+
+
+Arends, et al. Standards Track [Page 28]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ It is possible for more than one DNSKEY RR to match the conditions
+ above. In this case, the validator cannot predetermine which DNSKEY
+ RR to use to authenticate the signature, and it MUST try each
+ matching DNSKEY RR until either the signature is validated or the
+ validator has run out of matching public keys to try.
+
+ Note that this authentication process is only meaningful if the
+ validator authenticates the DNSKEY RR before using it to validate
+ signatures. The matching DNSKEY RR is considered to be authentic if:
+
+ o the apex DNSKEY RRset containing the DNSKEY RR is considered
+ authentic; or
+
+ o the RRset covered by the RRSIG RR is the apex DNSKEY RRset itself,
+ and the DNSKEY RR either matches an authenticated DS RR from the
+ parent zone or matches a trust anchor.
+
+5.3.2. Reconstructing the Signed Data
+
+ Once the RRSIG RR has met the validity requirements described in
+ Section 5.3.1, the validator has to reconstruct the original signed
+ data. The original signed data includes RRSIG RDATA (excluding the
+ Signature field) and the canonical form of the RRset. Aside from
+ being ordered, the canonical form of the RRset might also differ from
+ the received RRset due to DNS name compression, decremented TTLs, or
+ wildcard expansion. The validator should use the following to
+ reconstruct the original signed data:
+
+ signed_data = RRSIG_RDATA | RR(1) | RR(2)... where
+
+ "|" denotes concatenation
+
+ RRSIG_RDATA is the wire format of the RRSIG RDATA fields
+ with the Signature field excluded and the Signer's Name
+ in canonical form.
+
+ RR(i) = name | type | class | OrigTTL | RDATA length | RDATA
+
+ name is calculated according to the function below
+
+ class is the RRset's class
+
+ type is the RRset type and all RRs in the class
+
+ OrigTTL is the value from the RRSIG Original TTL field
+
+ All names in the RDATA field are in canonical form
+
+
+
+
+Arends, et al. Standards Track [Page 29]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ The set of all RR(i) is sorted into canonical order.
+
+ To calculate the name:
+ let rrsig_labels = the value of the RRSIG Labels field
+
+ let fqdn = RRset's fully qualified domain name in
+ canonical form
+
+ let fqdn_labels = Label count of the fqdn above.
+
+ if rrsig_labels = fqdn_labels,
+ name = fqdn
+
+ if rrsig_labels < fqdn_labels,
+ name = "*." | the rightmost rrsig_label labels of the
+ fqdn
+
+ if rrsig_labels > fqdn_labels
+ the RRSIG RR did not pass the necessary validation
+ checks and MUST NOT be used to authenticate this
+ RRset.
+
+ The canonical forms for names and RRsets are defined in [RFC4034].
+
+ NSEC RRsets at a delegation boundary require special processing.
+ There are two distinct NSEC RRsets associated with a signed delegated
+ name. One NSEC RRset resides in the parent zone, and specifies which
+ RRsets are present at the parent zone. The second NSEC RRset resides
+ at the child zone and identifies which RRsets are present at the apex
+ in the child zone. The parent NSEC RRset and child NSEC RRset can
+ always be distinguished as only a child NSEC RR will indicate that an
+ SOA RRset exists at the name. When reconstructing the original NSEC
+ RRset for the delegation from the parent zone, the NSEC RRs MUST NOT
+ be combined with NSEC RRs from the child zone. When reconstructing
+ the original NSEC RRset for the apex of the child zone, the NSEC RRs
+ MUST NOT be combined with NSEC RRs from the parent zone.
+
+ Note that each of the two NSEC RRsets at a delegation point has a
+ corresponding RRSIG RR with an owner name matching the delegated
+ name, and each of these RRSIG RRs is authoritative data associated
+ with the same zone that contains the corresponding NSEC RRset. If
+ necessary, a resolver can tell these RRSIG RRs apart by checking the
+ Signer's Name field.
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 30]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+5.3.3. Checking the Signature
+
+ Once the resolver has validated the RRSIG RR as described in Section
+ 5.3.1 and reconstructed the original signed data as described in
+ Section 5.3.2, the validator can attempt to use the cryptographic
+ signature to authenticate the signed data, and thus (finally!)
+ authenticate the RRset.
+
+ The Algorithm field in the RRSIG RR identifies the cryptographic
+ algorithm used to generate the signature. The signature itself is
+ contained in the Signature field of the RRSIG RDATA, and the public
+ key used to verify the signature is contained in the Public Key field
+ of the matching DNSKEY RR(s) (found in Section 5.3.1). [RFC4034]
+ provides a list of algorithm types and provides pointers to the
+ documents that define each algorithm's use.
+
+ Note that it is possible for more than one DNSKEY RR to match the
+ conditions in Section 5.3.1. In this case, the validator can only
+ determine which DNSKEY RR is correct by trying each matching public
+ key until the validator either succeeds in validating the signature
+ or runs out of keys to try.
+
+ If the Labels field of the RRSIG RR is not equal to the number of
+ labels in the RRset's fully qualified owner name, then the RRset is
+ either invalid or the result of wildcard expansion. The resolver
+ MUST verify that wildcard expansion was applied properly before
+ considering the RRset to be authentic. Section 5.3.4 describes how
+ to determine whether a wildcard was applied properly.
+
+ If other RRSIG RRs also cover this RRset, the local resolver security
+ policy determines whether the resolver also has to test these RRSIG
+ RRs and how to resolve conflicts if these RRSIG RRs lead to differing
+ results.
+
+ If the resolver accepts the RRset as authentic, the validator MUST
+ set the TTL of the RRSIG RR and each RR in the authenticated RRset to
+ a value no greater than the minimum of:
+
+ o the RRset's TTL as received in the response;
+
+ o the RRSIG RR's TTL as received in the response;
+
+ o the value in the RRSIG RR's Original TTL field; and
+
+ o the difference of the RRSIG RR's Signature Expiration time and the
+ current time.
+
+
+
+
+
+Arends, et al. Standards Track [Page 31]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+5.3.4. Authenticating a Wildcard Expanded RRset Positive Response
+
+ If the number of labels in an RRset's owner name is greater than the
+ Labels field of the covering RRSIG RR, then the RRset and its
+ covering RRSIG RR were created as a result of wildcard expansion.
+ Once the validator has verified the signature, as described in
+ Section 5.3, it must take additional steps to verify the non-
+ existence of an exact match or closer wildcard match for the query.
+ Section 5.4 discusses these steps.
+
+ Note that the response received by the resolver should include all
+ NSEC RRs needed to authenticate the response (see Section 3.1.3).
+
+5.4. Authenticated Denial of Existence
+
+ A resolver can use authenticated NSEC RRs to prove that an RRset is
+ not present in a signed zone. Security-aware name servers should
+ automatically include any necessary NSEC RRs for signed zones in
+ their responses to security-aware resolvers.
+
+ Denial of existence is determined by the following rules:
+
+ o If the requested RR name matches the owner name of an
+ authenticated NSEC RR, then the NSEC RR's type bit map field lists
+ all RR types present at that owner name, and a resolver can prove
+ that the requested RR type does not exist by checking for the RR
+ type in the bit map. If the number of labels in an authenticated
+ NSEC RR's owner name equals the Labels field of the covering RRSIG
+ RR, then the existence of the NSEC RR proves that wildcard
+ expansion could not have been used to match the request.
+
+ o If the requested RR name would appear after an authenticated NSEC
+ RR's owner name and before the name listed in that NSEC RR's Next
+ Domain Name field according to the canonical DNS name order
+ defined in [RFC4034], then no RRsets with the requested name exist
+ in the zone. However, it is possible that a wildcard could be
+ used to match the requested RR owner name and type, so proving
+ that the requested RRset does not exist also requires proving that
+ no possible wildcard RRset exists that could have been used to
+ generate a positive response.
+
+ In addition, security-aware resolvers MUST authenticate the NSEC
+ RRsets that comprise the non-existence proof as described in Section
+ 5.3.
+
+ To prove the non-existence of an RRset, the resolver must be able to
+ verify both that the queried RRset does not exist and that no
+ relevant wildcard RRset exists. Proving this may require more than
+
+
+
+Arends, et al. Standards Track [Page 32]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ one NSEC RRset from the zone. If the complete set of necessary NSEC
+ RRsets is not present in a response (perhaps due to message
+ truncation), then a security-aware resolver MUST resend the query in
+ order to attempt to obtain the full collection of NSEC RRs necessary
+ to verify the non-existence of the requested RRset. As with all DNS
+ operations, however, the resolver MUST bound the work it puts into
+ answering any particular query.
+
+ Since a validated NSEC RR proves the existence of both itself and its
+ corresponding RRSIG RR, a validator MUST ignore the settings of the
+ NSEC and RRSIG bits in an NSEC RR.
+
+5.5. Resolver Behavior When Signatures Do Not Validate
+
+ If for whatever reason none of the RRSIGs can be validated, the
+ response SHOULD be considered BAD. If the validation was being done
+ to service a recursive query, the name server MUST return RCODE 2 to
+ the originating client. However, it MUST return the full response if
+ and only if the original query had the CD bit set. Also see Section
+ 4.7 on caching responses that do not validate.
+
+5.6. Authentication Example
+
+ Appendix C shows an example of the authentication process.
+
+6. IANA Considerations
+
+ [RFC4034] contains a review of the IANA considerations introduced by
+ DNSSEC. The following are additional IANA considerations discussed
+ in this document:
+
+ [RFC2535] reserved the CD and AD bits in the message header. The
+ meaning of the AD bit was redefined in [RFC3655], and the meaning of
+ both the CD and AD bit are restated in this document. No new bits in
+ the DNS message header are defined in this document.
+
+ [RFC2671] introduced EDNS, and [RFC3225] reserved the DNSSEC OK bit
+ and defined its use. The use is restated but not altered in this
+ document.
+
+7. Security Considerations
+
+ This document describes how the DNS security extensions use public
+ key cryptography to sign and authenticate DNS resource record sets.
+ Please see [RFC4033] for terminology and general security
+ considerations related to DNSSEC; see [RFC4034] for considerations
+ specific to the DNSSEC resource record types.
+
+
+
+
+Arends, et al. Standards Track [Page 33]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ An active attacker who can set the CD bit in a DNS query message or
+ the AD bit in a DNS response message can use these bits to defeat the
+ protection that DNSSEC attempts to provide to security-oblivious
+ recursive-mode resolvers. For this reason, use of these control bits
+ by a security-aware recursive-mode resolver requires a secure
+ channel. See Sections 3.2.2 and 4.9 for further discussion.
+
+ The protocol described in this document attempts to extend the
+ benefits of DNSSEC to security-oblivious stub resolvers. However, as
+ recovery from validation failures is likely to be specific to
+ particular applications, the facilities that DNSSEC provides for stub
+ resolvers may prove inadequate. Operators of security-aware
+ recursive name servers will have to pay close attention to the
+ behavior of the applications that use their services when choosing a
+ local validation policy; failure to do so could easily result in the
+ recursive name server accidentally denying service to the clients it
+ is intended to support.
+
+8. Acknowledgements
+
+ This document was created from the input and ideas of the members of
+ the DNS Extensions Working Group and working group mailing list. The
+ editors would like to express their thanks for the comments and
+ suggestions received during the revision of these security extension
+ specifications. Although explicitly listing everyone who has
+ contributed during the decade in which DNSSEC has been under
+ development would be impossible, [RFC4033] includes a list of some of
+ the participants who were kind enough to comment on these documents.
+
+9. References
+
+9.1. Normative References
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC1122] Braden, R., "Requirements for Internet Hosts -
+ Communication Layers", STD 3, RFC 1122, October 1989.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+
+
+
+Arends, et al. Standards Track [Page 34]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ [RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [RFC2672] Crawford, M., "Non-Terminal DNS Name Redirection", RFC
+ 2672, August 1999.
+
+ [RFC3225] Conrad, D., "Indicating Resolver Support of DNSSEC", RFC
+ 3225, December 2001.
+
+ [RFC3226] Gudmundsson, O., "DNSSEC and IPv6 A6 aware server/resolver
+ message size requirements", RFC 3226, December 2001.
+
+ [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "DNS Security Introduction and Requirements", RFC
+ 4033, March 2005.
+
+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for DNS Security Extensions", RFC
+ 4034, March 2005.
+
+9.2. Informative References
+
+ [RFC2308] Andrews, M., "Negative Caching of DNS Queries (DNS
+ NCACHE)", RFC 2308, March 1998.
+
+ [RFC2535] Eastlake 3rd, D., "Domain Name System Security
+ Extensions", RFC 2535, March 1999.
+
+ [RFC3007] Wellington, B., "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+ [RFC3655] Wellington, B. and O. Gudmundsson, "Redefinition of DNS
+ Authenticated Data (AD) bit", RFC 3655, November 2003.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 35]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+Appendix A. Signed Zone Example
+
+ The following example shows a (small) complete signed zone.
+
+ example. 3600 IN SOA ns1.example. bugs.x.w.example. (
+ 1081539377
+ 3600
+ 300
+ 3600000
+ 3600
+ )
+ 3600 RRSIG SOA 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ ONx0k36rcjaxYtcNgq6iQnpNV5+drqYAsC9h
+ 7TSJaHCqbhE67Sr6aH2xDUGcqQWu/n0UVzrF
+ vkgO9ebarZ0GWDKcuwlM6eNB5SiX2K74l5LW
+ DA7S/Un/IbtDq4Ay8NMNLQI7Dw7n4p8/rjkB
+ jV7j86HyQgM5e7+miRAz8V01b0I= )
+ 3600 NS ns1.example.
+ 3600 NS ns2.example.
+ 3600 RRSIG NS 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ gl13F00f2U0R+SWiXXLHwsMY+qStYy5k6zfd
+ EuivWc+wd1fmbNCyql0Tk7lHTX6UOxc8AgNf
+ 4ISFve8XqF4q+o9qlnqIzmppU3LiNeKT4FZ8
+ RO5urFOvoMRTbQxW3U0hXWuggE4g3ZpsHv48
+ 0HjMeRaZB/FRPGfJPajngcq6Kwg= )
+ 3600 MX 1 xx.example.
+ 3600 RRSIG MX 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ HyDHYVT5KHSZ7HtO/vypumPmSZQrcOP3tzWB
+ 2qaKkHVPfau/DgLgS/IKENkYOGL95G4N+NzE
+ VyNU8dcTOckT+ChPcGeVjguQ7a3Ao9Z/ZkUO
+ 6gmmUW4b89rz1PUxW4jzUxj66PTwoVtUU/iM
+ W6OISukd1EQt7a0kygkg+PEDxdI= )
+ 3600 NSEC a.example. NS SOA MX RRSIG NSEC DNSKEY
+ 3600 RRSIG NSEC 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ O0k558jHhyrC97ISHnislm4kLMW48C7U7cBm
+ FTfhke5iVqNRVTB1STLMpgpbDIC9hcryoO0V
+ Z9ME5xPzUEhbvGnHd5sfzgFVeGxr5Nyyq4tW
+ SDBgIBiLQUv1ivy29vhXy7WgR62dPrZ0PWvm
+ jfFJ5arXf4nPxp/kEowGgBRzY/U= )
+ 3600 DNSKEY 256 3 5 (
+ AQOy1bZVvpPqhg4j7EJoM9rI3ZmyEx2OzDBV
+ rZy/lvI5CQePxXHZS4i8dANH4DX3tbHol61e
+ k8EFMcsGXxKciJFHyhl94C+NwILQdzsUlSFo
+ vBZsyl/NX6yEbtw/xN9ZNcrbYvgjjZ/UVPZI
+
+
+
+Arends, et al. Standards Track [Page 36]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ ySFNsgEYvh0z2542lzMKR4Dh8uZffQ==
+ )
+ 3600 DNSKEY 257 3 5 (
+ AQOeX7+baTmvpVHb2CcLnL1dMRWbuscRvHXl
+ LnXwDzvqp4tZVKp1sZMepFb8MvxhhW3y/0QZ
+ syCjczGJ1qk8vJe52iOhInKROVLRwxGpMfzP
+ RLMlGybr51bOV/1se0ODacj3DomyB4QB5gKT
+ Yot/K9alk5/j8vfd4jWCWD+E1Sze0Q==
+ )
+ 3600 RRSIG DNSKEY 5 1 3600 20040509183619 (
+ 20040409183619 9465 example.
+ ZxgauAuIj+k1YoVEOSlZfx41fcmKzTFHoweZ
+ xYnz99JVQZJ33wFS0Q0jcP7VXKkaElXk9nYJ
+ XevO/7nAbo88iWsMkSpSR6jWzYYKwfrBI/L9
+ hjYmyVO9m6FjQ7uwM4dCP/bIuV/DKqOAK9NY
+ NC3AHfvCV1Tp4VKDqxqG7R5tTVM= )
+ 3600 RRSIG DNSKEY 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ eGL0s90glUqcOmloo/2y+bSzyEfKVOQViD9Z
+ DNhLz/Yn9CQZlDVRJffACQDAUhXpU/oP34ri
+ bKBpysRXosczFrKqS5Oa0bzMOfXCXup9qHAp
+ eFIku28Vqfr8Nt7cigZLxjK+u0Ws/4lIRjKk
+ 7z5OXogYVaFzHKillDt3HRxHIZM= )
+ a.example. 3600 IN NS ns1.a.example.
+ 3600 IN NS ns2.a.example.
+ 3600 DS 57855 5 1 (
+ B6DCD485719ADCA18E5F3D48A2331627FDD3
+ 636B )
+ 3600 RRSIG DS 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ oXIKit/QtdG64J/CB+Gi8dOvnwRvqrto1AdQ
+ oRkAN15FP3iZ7suB7gvTBmXzCjL7XUgQVcoH
+ kdhyCuzp8W9qJHgRUSwKKkczSyuL64nhgjuD
+ EML8l9wlWVsl7PR2VnZduM9bLyBhaaPmRKX/
+ Fm+v6ccF2EGNLRiY08kdkz+XHHo= )
+ 3600 NSEC ai.example. NS DS RRSIG NSEC
+ 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ cOlYgqJLqlRqmBQ3iap2SyIsK4O5aqpKSoba
+ U9fQ5SMApZmHfq3AgLflkrkXRXvgxTQSKkG2
+ 039/cRUs6Jk/25+fi7Xr5nOVJsb0lq4zsB3I
+ BBdjyGDAHE0F5ROJj87996vJupdm1fbH481g
+ sdkOW6Zyqtz3Zos8N0BBkEx+2G4= )
+ ns1.a.example. 3600 IN A 192.0.2.5
+ ns2.a.example. 3600 IN A 192.0.2.6
+ ai.example. 3600 IN A 192.0.2.9
+ 3600 RRSIG A 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+
+
+
+Arends, et al. Standards Track [Page 37]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ pAOtzLP2MU0tDJUwHOKE5FPIIHmdYsCgTb5B
+ ERGgpnJluA9ixOyf6xxVCgrEJW0WNZSsJicd
+ hBHXfDmAGKUajUUlYSAH8tS4ZnrhyymIvk3u
+ ArDu2wfT130e9UHnumaHHMpUTosKe22PblOy
+ 6zrTpg9FkS0XGVmYRvOTNYx2HvQ= )
+ 3600 HINFO "KLH-10" "ITS"
+ 3600 RRSIG HINFO 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ Iq/RGCbBdKzcYzlGE4ovbr5YcB+ezxbZ9W0l
+ e/7WqyvhOO9J16HxhhL7VY/IKmTUY0GGdcfh
+ ZEOCkf4lEykZF9NPok1/R/fWrtzNp8jobuY7
+ AZEcZadp1WdDF3jc2/ndCa5XZhLKD3JzOsBw
+ FvL8sqlS5QS6FY/ijFEDnI4RkZA= )
+ 3600 AAAA 2001:db8::f00:baa9
+ 3600 RRSIG AAAA 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ nLcpFuXdT35AcE+EoafOUkl69KB+/e56XmFK
+ kewXG2IadYLKAOBIoR5+VoQV3XgTcofTJNsh
+ 1rnF6Eav2zpZB3byI6yo2bwY8MNkr4A7cL9T
+ cMmDwV/hWFKsbGBsj8xSCN/caEL2CWY/5XP2
+ sZM6QjBBLmukH30+w1z3h8PUP2o= )
+ 3600 NSEC b.example. A HINFO AAAA RRSIG NSEC
+ 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ QoshyPevLcJ/xcRpEtMft1uoIrcrieVcc9pG
+ CScIn5Glnib40T6ayVOimXwdSTZ/8ISXGj4p
+ P8Sh0PlA6olZQ84L453/BUqB8BpdOGky4hsN
+ 3AGcLEv1Gr0QMvirQaFcjzOECfnGyBm+wpFL
+ AhS+JOVfDI/79QtyTI0SaDWcg8U= )
+ b.example. 3600 IN NS ns1.b.example.
+ 3600 IN NS ns2.b.example.
+ 3600 NSEC ns1.example. NS RRSIG NSEC
+ 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ GNuxHn844wfmUhPzGWKJCPY5ttEX/RfjDoOx
+ 9ueK1PtYkOWKOOdiJ/PJKCYB3hYX+858dDWS
+ xb2qnV/LSTCNVBnkm6owOpysY97MVj5VQEWs
+ 0lm9tFoqjcptQkmQKYPrwUnCSNwvvclSF1xZ
+ vhRXgWT7OuFXldoCG6TfVFMs9xE= )
+ ns1.b.example. 3600 IN A 192.0.2.7
+ ns2.b.example. 3600 IN A 192.0.2.8
+ ns1.example. 3600 IN A 192.0.2.1
+ 3600 RRSIG A 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ F1C9HVhIcs10cZU09G5yIVfKJy5yRQQ3qVet
+ 5pGhp82pzhAOMZ3K22JnmK4c+IjUeFp/to06
+ im5FVpHtbFisdjyPq84bhTv8vrXt5AB1wNB+
+ +iAqvIfdgW4sFNC6oADb1hK8QNauw9VePJhK
+
+
+
+Arends, et al. Standards Track [Page 38]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ v/iVXSYC0b7mPSU+EOlknFpVECs= )
+ 3600 NSEC ns2.example. A RRSIG NSEC
+ 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ I4hj+Kt6+8rCcHcUdolks2S+Wzri9h3fHas8
+ 1rGN/eILdJHN7JpV6lLGPIh/8fIBkfvdyWnB
+ jjf1q3O7JgYO1UdI7FvBNWqaaEPJK3UkddBq
+ ZIaLi8Qr2XHkjq38BeQsbp8X0+6h4ETWSGT8
+ IZaIGBLryQWGLw6Y6X8dqhlnxJM= )
+ ns2.example. 3600 IN A 192.0.2.2
+ 3600 RRSIG A 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ V7cQRw1TR+knlaL1z/psxlS1PcD37JJDaCMq
+ Qo6/u1qFQu6x+wuDHRH22Ap9ulJPQjFwMKOu
+ yfPGQPC8KzGdE3vt5snFEAoE1Vn3mQqtu7SO
+ 6amIjk13Kj/jyJ4nGmdRIc/3cM3ipXFhNTKq
+ rdhx8SZ0yy4ObIRzIzvBFLiSS8o= )
+ 3600 NSEC *.w.example. A RRSIG NSEC
+ 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ N0QzHvaJf5NRw1rE9uxS1Ltb2LZ73Qb9bKGE
+ VyaISkqzGpP3jYJXZJPVTq4UVEsgT3CgeHvb
+ 3QbeJ5Dfb2V9NGCHj/OvF/LBxFFWwhLwzngH
+ l+bQAgAcMsLu/nL3nDi1y/JSQjAcdZNDl4bw
+ Ymx28EtgIpo9A0qmP08rMBqs1Jw= )
+ *.w.example. 3600 IN MX 1 ai.example.
+ 3600 RRSIG MX 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ OMK8rAZlepfzLWW75Dxd63jy2wswESzxDKG2
+ f9AMN1CytCd10cYISAxfAdvXSZ7xujKAtPbc
+ tvOQ2ofO7AZJ+d01EeeQTVBPq4/6KCWhqe2X
+ TjnkVLNvvhnc0u28aoSsG0+4InvkkOHknKxw
+ 4kX18MMR34i8lC36SR5xBni8vHI= )
+ 3600 NSEC x.w.example. MX RRSIG NSEC
+ 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ r/mZnRC3I/VIcrelgIcteSxDhtsdlTDt8ng9
+ HSBlABOlzLxQtfgTnn8f+aOwJIAFe1Ee5RvU
+ 5cVhQJNP5XpXMJHfyps8tVvfxSAXfahpYqtx
+ 91gsmcV/1V9/bZAG55CefP9cM4Z9Y9NT9XQ8
+ s1InQ2UoIv6tJEaaKkP701j8OLA= )
+ x.w.example. 3600 IN MX 1 xx.example.
+ 3600 RRSIG MX 5 3 3600 20040509183619 (
+ 20040409183619 38519 example.
+ Il2WTZ+Bkv+OytBx4LItNW5mjB4RCwhOO8y1
+ XzPHZmZUTVYL7LaA63f6T9ysVBzJRI3KRjAP
+ H3U1qaYnDoN1DrWqmi9RJe4FoObkbcdm7P3I
+ kx70ePCoFgRz1Yq+bVVXCvGuAU4xALv3W/Y1
+
+
+
+Arends, et al. Standards Track [Page 39]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ jNSlwZ2mSWKHfxFQxPtLj8s32+k= )
+ 3600 NSEC x.y.w.example. MX RRSIG NSEC
+ 3600 RRSIG NSEC 5 3 3600 20040509183619 (
+ 20040409183619 38519 example.
+ aRbpHftxggzgMXdDlym9SsADqMZovZZl2QWK
+ vw8J0tZEUNQByH5Qfnf5N1FqH/pS46UA7A4E
+ mcWBN9PUA1pdPY6RVeaRlZlCr1IkVctvbtaI
+ NJuBba/VHm+pebTbKcAPIvL9tBOoh+to1h6e
+ IjgiM8PXkBQtxPq37wDKALkyn7Q= )
+ x.y.w.example. 3600 IN MX 1 xx.example.
+ 3600 RRSIG MX 5 4 3600 20040509183619 (
+ 20040409183619 38519 example.
+ k2bJHbwP5LH5qN4is39UiPzjAWYmJA38Hhia
+ t7i9t7nbX/e0FPnvDSQXzcK7UL+zrVA+3MDj
+ q1ub4q3SZgcbLMgexxIW3Va//LVrxkP6Xupq
+ GtOB9prkK54QTl/qZTXfMQpW480YOvVknhvb
+ +gLcMZBnHJ326nb/TOOmrqNmQQE= )
+ 3600 NSEC xx.example. MX RRSIG NSEC
+ 3600 RRSIG NSEC 5 4 3600 20040509183619 (
+ 20040409183619 38519 example.
+ OvE6WUzN2ziieJcvKPWbCAyXyP6ef8cr6Csp
+ ArVSTzKSquNwbezZmkU7E34o5lmb6CWSSSpg
+ xw098kNUFnHcQf/LzY2zqRomubrNQhJTiDTX
+ a0ArunJQCzPjOYq5t0SLjm6qp6McJI1AP5Vr
+ QoKqJDCLnoAlcPOPKAm/jJkn3jk= )
+ xx.example. 3600 IN A 192.0.2.10
+ 3600 RRSIG A 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ kBF4YxMGWF0D8r0cztL+2fWWOvN1U/GYSpYP
+ 7SoKoNQ4fZKyk+weWGlKLIUM+uE1zjVTPXoa
+ 0Z6WG0oZp46rkl1EzMcdMgoaeUzzAJ2BMq+Y
+ VdxG9IK1yZkYGY9AgbTOGPoAgbJyO9EPULsx
+ kbIDV6GPPSZVusnZU6OMgdgzHV4= )
+ 3600 HINFO "KLH-10" "TOPS-20"
+ 3600 RRSIG HINFO 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ GY2PLSXmMHkWHfLdggiox8+chWpeMNJLkML0
+ t+U/SXSUsoUdR91KNdNUkTDWamwcF8oFRjhq
+ BcPZ6EqrF+vl5v5oGuvSF7U52epfVTC+wWF8
+ 3yCUeUw8YklhLWlvk8gQ15YKth0ITQy8/wI+
+ RgNvuwbioFSEuv2pNlkq0goYxNY= )
+ 3600 AAAA 2001:db8::f00:baaa
+ 3600 RRSIG AAAA 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ Zzj0yodDxcBLnnOIwDsuKo5WqiaK24DlKg9C
+ aGaxDFiKgKobUj2jilYQHpGFn2poFRetZd4z
+ ulyQkssz2QHrVrPuTMS22knudCiwP4LWpVTr
+ U4zfeA+rDz9stmSBP/4PekH/x2IoAYnwctd/
+
+
+
+Arends, et al. Standards Track [Page 40]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ xS9cL2QgW7FChw16mzlkH6/vsfs= )
+ 3600 NSEC example. A HINFO AAAA RRSIG NSEC
+ 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ ZFWUln6Avc8bmGl5GFjD3BwT530DUZKHNuoY
+ 9A8lgXYyrxu+pqgFiRVbyZRQvVB5pccEOT3k
+ mvHgEa/HzbDB4PIYY79W+VHrgOxzdQGGCZzi
+ asXrpSGOWwSOElghPnMIi8xdF7qtCntr382W
+ GghLahumFIpg4MO3LS/prgzVVWo= )
+
+ The apex DNSKEY set includes two DNSKEY RRs, and the DNSKEY RDATA
+ Flags indicate that each of these DNSKEY RRs is a zone key. One of
+ these DNSKEY RRs also has the SEP flag set and has been used to sign
+ the apex DNSKEY RRset; this is the key that should be hashed to
+ generate a DS record to be inserted into the parent zone. The other
+ DNSKEY is used to sign all the other RRsets in the zone.
+
+ The zone includes a wildcard entry, "*.w.example". Note that the
+ name "*.w.example" is used in constructing NSEC chains, and that the
+ RRSIG covering the "*.w.example" MX RRset has a label count of 2.
+
+ The zone also includes two delegations. The delegation to
+ "b.example" includes an NS RRset, glue address records, and an NSEC
+ RR; note that only the NSEC RRset is signed. The delegation to
+ "a.example" provides a DS RR; note that only the NSEC and DS RRsets
+ are signed.
+
+Appendix B. Example Responses
+
+ The examples in this section show response messages using the signed
+ zone example in Appendix A.
+
+B.1. Answer
+
+ A successful query to an authoritative server.
+
+ ;; Header: QR AA DO RCODE=0
+ ;;
+ ;; Question
+ x.w.example. IN MX
+
+ ;; Answer
+ x.w.example. 3600 IN MX 1 xx.example.
+ x.w.example. 3600 RRSIG MX 5 3 3600 20040509183619 (
+ 20040409183619 38519 example.
+ Il2WTZ+Bkv+OytBx4LItNW5mjB4RCwhOO8y1
+ XzPHZmZUTVYL7LaA63f6T9ysVBzJRI3KRjAP
+ H3U1qaYnDoN1DrWqmi9RJe4FoObkbcdm7P3I
+
+
+
+Arends, et al. Standards Track [Page 41]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ kx70ePCoFgRz1Yq+bVVXCvGuAU4xALv3W/Y1
+ jNSlwZ2mSWKHfxFQxPtLj8s32+k= )
+
+ ;; Authority
+ example. 3600 NS ns1.example.
+ example. 3600 NS ns2.example.
+ example. 3600 RRSIG NS 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ gl13F00f2U0R+SWiXXLHwsMY+qStYy5k6zfd
+ EuivWc+wd1fmbNCyql0Tk7lHTX6UOxc8AgNf
+ 4ISFve8XqF4q+o9qlnqIzmppU3LiNeKT4FZ8
+ RO5urFOvoMRTbQxW3U0hXWuggE4g3ZpsHv48
+ 0HjMeRaZB/FRPGfJPajngcq6Kwg= )
+
+ ;; Additional
+ xx.example. 3600 IN A 192.0.2.10
+ xx.example. 3600 RRSIG A 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ kBF4YxMGWF0D8r0cztL+2fWWOvN1U/GYSpYP
+ 7SoKoNQ4fZKyk+weWGlKLIUM+uE1zjVTPXoa
+ 0Z6WG0oZp46rkl1EzMcdMgoaeUzzAJ2BMq+Y
+ VdxG9IK1yZkYGY9AgbTOGPoAgbJyO9EPULsx
+ kbIDV6GPPSZVusnZU6OMgdgzHV4= )
+ xx.example. 3600 AAAA 2001:db8::f00:baaa
+ xx.example. 3600 RRSIG AAAA 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ Zzj0yodDxcBLnnOIwDsuKo5WqiaK24DlKg9C
+ aGaxDFiKgKobUj2jilYQHpGFn2poFRetZd4z
+ ulyQkssz2QHrVrPuTMS22knudCiwP4LWpVTr
+ U4zfeA+rDz9stmSBP/4PekH/x2IoAYnwctd/
+ xS9cL2QgW7FChw16mzlkH6/vsfs= )
+ ns1.example. 3600 IN A 192.0.2.1
+ ns1.example. 3600 RRSIG A 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ F1C9HVhIcs10cZU09G5yIVfKJy5yRQQ3qVet
+ 5pGhp82pzhAOMZ3K22JnmK4c+IjUeFp/to06
+ im5FVpHtbFisdjyPq84bhTv8vrXt5AB1wNB+
+ +iAqvIfdgW4sFNC6oADb1hK8QNauw9VePJhK
+ v/iVXSYC0b7mPSU+EOlknFpVECs= )
+ ns2.example. 3600 IN A 192.0.2.2
+ ns2.example. 3600 RRSIG A 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ V7cQRw1TR+knlaL1z/psxlS1PcD37JJDaCMq
+ Qo6/u1qFQu6x+wuDHRH22Ap9ulJPQjFwMKOu
+ yfPGQPC8KzGdE3vt5snFEAoE1Vn3mQqtu7SO
+ 6amIjk13Kj/jyJ4nGmdRIc/3cM3ipXFhNTKq
+ rdhx8SZ0yy4ObIRzIzvBFLiSS8o= )
+
+
+
+
+Arends, et al. Standards Track [Page 42]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+B.2. Name Error
+
+ An authoritative name error. The NSEC RRs prove that the name does
+ not exist and that no covering wildcard exists.
+
+ ;; Header: QR AA DO RCODE=3
+ ;;
+ ;; Question
+ ml.example. IN A
+
+ ;; Answer
+ ;; (empty)
+
+ ;; Authority
+ example. 3600 IN SOA ns1.example. bugs.x.w.example. (
+ 1081539377
+ 3600
+ 300
+ 3600000
+ 3600
+ )
+ example. 3600 RRSIG SOA 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ ONx0k36rcjaxYtcNgq6iQnpNV5+drqYAsC9h
+ 7TSJaHCqbhE67Sr6aH2xDUGcqQWu/n0UVzrF
+ vkgO9ebarZ0GWDKcuwlM6eNB5SiX2K74l5LW
+ DA7S/Un/IbtDq4Ay8NMNLQI7Dw7n4p8/rjkB
+ jV7j86HyQgM5e7+miRAz8V01b0I= )
+ b.example. 3600 NSEC ns1.example. NS RRSIG NSEC
+ b.example. 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ GNuxHn844wfmUhPzGWKJCPY5ttEX/RfjDoOx
+ 9ueK1PtYkOWKOOdiJ/PJKCYB3hYX+858dDWS
+ xb2qnV/LSTCNVBnkm6owOpysY97MVj5VQEWs
+ 0lm9tFoqjcptQkmQKYPrwUnCSNwvvclSF1xZ
+ vhRXgWT7OuFXldoCG6TfVFMs9xE= )
+ example. 3600 NSEC a.example. NS SOA MX RRSIG NSEC DNSKEY
+ example. 3600 RRSIG NSEC 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ O0k558jHhyrC97ISHnislm4kLMW48C7U7cBm
+ FTfhke5iVqNRVTB1STLMpgpbDIC9hcryoO0V
+ Z9ME5xPzUEhbvGnHd5sfzgFVeGxr5Nyyq4tW
+ SDBgIBiLQUv1ivy29vhXy7WgR62dPrZ0PWvm
+ jfFJ5arXf4nPxp/kEowGgBRzY/U= )
+
+ ;; Additional
+ ;; (empty)
+
+
+
+
+Arends, et al. Standards Track [Page 43]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+B.3. No Data Error
+
+ A "no data" response. The NSEC RR proves that the name exists and
+ that the requested RR type does not.
+
+ ;; Header: QR AA DO RCODE=0
+ ;;
+ ;; Question
+ ns1.example. IN MX
+
+ ;; Answer
+ ;; (empty)
+
+ ;; Authority
+ example. 3600 IN SOA ns1.example. bugs.x.w.example. (
+ 1081539377
+ 3600
+ 300
+ 3600000
+ 3600
+ )
+ example. 3600 RRSIG SOA 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ ONx0k36rcjaxYtcNgq6iQnpNV5+drqYAsC9h
+ 7TSJaHCqbhE67Sr6aH2xDUGcqQWu/n0UVzrF
+ vkgO9ebarZ0GWDKcuwlM6eNB5SiX2K74l5LW
+ DA7S/Un/IbtDq4Ay8NMNLQI7Dw7n4p8/rjkB
+ jV7j86HyQgM5e7+miRAz8V01b0I= )
+ ns1.example. 3600 NSEC ns2.example. A RRSIG NSEC
+ ns1.example. 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ I4hj+Kt6+8rCcHcUdolks2S+Wzri9h3fHas8
+ 1rGN/eILdJHN7JpV6lLGPIh/8fIBkfvdyWnB
+ jjf1q3O7JgYO1UdI7FvBNWqaaEPJK3UkddBq
+ ZIaLi8Qr2XHkjq38BeQsbp8X0+6h4ETWSGT8
+ IZaIGBLryQWGLw6Y6X8dqhlnxJM= )
+
+ ;; Additional
+ ;; (empty)
+
+B.4. Referral to Signed Zone
+
+ Referral to a signed zone. The DS RR contains the data which the
+ resolver will need to validate the corresponding DNSKEY RR in the
+ child zone's apex.
+
+ ;; Header: QR DO RCODE=0
+ ;;
+
+
+
+Arends, et al. Standards Track [Page 44]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ ;; Question
+ mc.a.example. IN MX
+
+ ;; Answer
+ ;; (empty)
+
+ ;; Authority
+ a.example. 3600 IN NS ns1.a.example.
+ a.example. 3600 IN NS ns2.a.example.
+ a.example. 3600 DS 57855 5 1 (
+ B6DCD485719ADCA18E5F3D48A2331627FDD3
+ 636B )
+ a.example. 3600 RRSIG DS 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ oXIKit/QtdG64J/CB+Gi8dOvnwRvqrto1AdQ
+ oRkAN15FP3iZ7suB7gvTBmXzCjL7XUgQVcoH
+ kdhyCuzp8W9qJHgRUSwKKkczSyuL64nhgjuD
+ EML8l9wlWVsl7PR2VnZduM9bLyBhaaPmRKX/
+ Fm+v6ccF2EGNLRiY08kdkz+XHHo= )
+
+ ;; Additional
+ ns1.a.example. 3600 IN A 192.0.2.5
+ ns2.a.example. 3600 IN A 192.0.2.6
+
+B.5. Referral to Unsigned Zone
+
+ Referral to an unsigned zone. The NSEC RR proves that no DS RR for
+ this delegation exists in the parent zone.
+
+ ;; Header: QR DO RCODE=0
+ ;;
+ ;; Question
+ mc.b.example. IN MX
+
+ ;; Answer
+ ;; (empty)
+
+ ;; Authority
+ b.example. 3600 IN NS ns1.b.example.
+ b.example. 3600 IN NS ns2.b.example.
+ b.example. 3600 NSEC ns1.example. NS RRSIG NSEC
+ b.example. 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ GNuxHn844wfmUhPzGWKJCPY5ttEX/RfjDoOx
+ 9ueK1PtYkOWKOOdiJ/PJKCYB3hYX+858dDWS
+ xb2qnV/LSTCNVBnkm6owOpysY97MVj5VQEWs
+ 0lm9tFoqjcptQkmQKYPrwUnCSNwvvclSF1xZ
+ vhRXgWT7OuFXldoCG6TfVFMs9xE= )
+
+
+
+Arends, et al. Standards Track [Page 45]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ ;; Additional
+ ns1.b.example. 3600 IN A 192.0.2.7
+ ns2.b.example. 3600 IN A 192.0.2.8
+
+B.6. Wildcard Expansion
+
+ A successful query that was answered via wildcard expansion. The
+ label count in the answer's RRSIG RR indicates that a wildcard RRset
+ was expanded to produce this response, and the NSEC RR proves that no
+ closer match exists in the zone.
+
+ ;; Header: QR AA DO RCODE=0
+ ;;
+ ;; Question
+ a.z.w.example. IN MX
+
+ ;; Answer
+ a.z.w.example. 3600 IN MX 1 ai.example.
+ a.z.w.example. 3600 RRSIG MX 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ OMK8rAZlepfzLWW75Dxd63jy2wswESzxDKG2
+ f9AMN1CytCd10cYISAxfAdvXSZ7xujKAtPbc
+ tvOQ2ofO7AZJ+d01EeeQTVBPq4/6KCWhqe2X
+ TjnkVLNvvhnc0u28aoSsG0+4InvkkOHknKxw
+ 4kX18MMR34i8lC36SR5xBni8vHI= )
+
+ ;; Authority
+ example. 3600 NS ns1.example.
+ example. 3600 NS ns2.example.
+ example. 3600 RRSIG NS 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ gl13F00f2U0R+SWiXXLHwsMY+qStYy5k6zfd
+ EuivWc+wd1fmbNCyql0Tk7lHTX6UOxc8AgNf
+ 4ISFve8XqF4q+o9qlnqIzmppU3LiNeKT4FZ8
+ RO5urFOvoMRTbQxW3U0hXWuggE4g3ZpsHv48
+ 0HjMeRaZB/FRPGfJPajngcq6Kwg= )
+ x.y.w.example. 3600 NSEC xx.example. MX RRSIG NSEC
+ x.y.w.example. 3600 RRSIG NSEC 5 4 3600 20040509183619 (
+ 20040409183619 38519 example.
+ OvE6WUzN2ziieJcvKPWbCAyXyP6ef8cr6Csp
+ ArVSTzKSquNwbezZmkU7E34o5lmb6CWSSSpg
+ xw098kNUFnHcQf/LzY2zqRomubrNQhJTiDTX
+ a0ArunJQCzPjOYq5t0SLjm6qp6McJI1AP5Vr
+ QoKqJDCLnoAlcPOPKAm/jJkn3jk= )
+
+ ;; Additional
+ ai.example. 3600 IN A 192.0.2.9
+ ai.example. 3600 RRSIG A 5 2 3600 20040509183619 (
+
+
+
+Arends, et al. Standards Track [Page 46]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ 20040409183619 38519 example.
+ pAOtzLP2MU0tDJUwHOKE5FPIIHmdYsCgTb5B
+ ERGgpnJluA9ixOyf6xxVCgrEJW0WNZSsJicd
+ hBHXfDmAGKUajUUlYSAH8tS4ZnrhyymIvk3u
+ ArDu2wfT130e9UHnumaHHMpUTosKe22PblOy
+ 6zrTpg9FkS0XGVmYRvOTNYx2HvQ= )
+ ai.example. 3600 AAAA 2001:db8::f00:baa9
+ ai.example. 3600 RRSIG AAAA 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ nLcpFuXdT35AcE+EoafOUkl69KB+/e56XmFK
+ kewXG2IadYLKAOBIoR5+VoQV3XgTcofTJNsh
+ 1rnF6Eav2zpZB3byI6yo2bwY8MNkr4A7cL9T
+ cMmDwV/hWFKsbGBsj8xSCN/caEL2CWY/5XP2
+ sZM6QjBBLmukH30+w1z3h8PUP2o= )
+
+B.7. Wildcard No Data Error
+
+ A "no data" response for a name covered by a wildcard. The NSEC RRs
+ prove that the matching wildcard name does not have any RRs of the
+ requested type and that no closer match exists in the zone.
+
+ ;; Header: QR AA DO RCODE=0
+ ;;
+ ;; Question
+ a.z.w.example. IN AAAA
+
+ ;; Answer
+ ;; (empty)
+
+ ;; Authority
+ example. 3600 IN SOA ns1.example. bugs.x.w.example. (
+ 1081539377
+ 3600
+ 300
+ 3600000
+ 3600
+ )
+ example. 3600 RRSIG SOA 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ ONx0k36rcjaxYtcNgq6iQnpNV5+drqYAsC9h
+ 7TSJaHCqbhE67Sr6aH2xDUGcqQWu/n0UVzrF
+ vkgO9ebarZ0GWDKcuwlM6eNB5SiX2K74l5LW
+ DA7S/Un/IbtDq4Ay8NMNLQI7Dw7n4p8/rjkB
+ jV7j86HyQgM5e7+miRAz8V01b0I= )
+ x.y.w.example. 3600 NSEC xx.example. MX RRSIG NSEC
+ x.y.w.example. 3600 RRSIG NSEC 5 4 3600 20040509183619 (
+ 20040409183619 38519 example.
+ OvE6WUzN2ziieJcvKPWbCAyXyP6ef8cr6Csp
+
+
+
+Arends, et al. Standards Track [Page 47]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ ArVSTzKSquNwbezZmkU7E34o5lmb6CWSSSpg
+ xw098kNUFnHcQf/LzY2zqRomubrNQhJTiDTX
+ a0ArunJQCzPjOYq5t0SLjm6qp6McJI1AP5Vr
+ QoKqJDCLnoAlcPOPKAm/jJkn3jk= )
+ *.w.example. 3600 NSEC x.w.example. MX RRSIG NSEC
+ *.w.example. 3600 RRSIG NSEC 5 2 3600 20040509183619 (
+ 20040409183619 38519 example.
+ r/mZnRC3I/VIcrelgIcteSxDhtsdlTDt8ng9
+ HSBlABOlzLxQtfgTnn8f+aOwJIAFe1Ee5RvU
+ 5cVhQJNP5XpXMJHfyps8tVvfxSAXfahpYqtx
+ 91gsmcV/1V9/bZAG55CefP9cM4Z9Y9NT9XQ8
+ s1InQ2UoIv6tJEaaKkP701j8OLA= )
+
+ ;; Additional
+ ;; (empty)
+
+B.8. DS Child Zone No Data Error
+
+ A "no data" response for a QTYPE=DS query that was mistakenly sent to
+ a name server for the child zone.
+
+ ;; Header: QR AA DO RCODE=0
+ ;;
+ ;; Question
+ example. IN DS
+
+ ;; Answer
+ ;; (empty)
+
+ ;; Authority
+ example. 3600 IN SOA ns1.example. bugs.x.w.example. (
+ 1081539377
+ 3600
+ 300
+ 3600000
+ 3600
+ )
+ example. 3600 RRSIG SOA 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ ONx0k36rcjaxYtcNgq6iQnpNV5+drqYAsC9h
+ 7TSJaHCqbhE67Sr6aH2xDUGcqQWu/n0UVzrF
+ vkgO9ebarZ0GWDKcuwlM6eNB5SiX2K74l5LW
+ DA7S/Un/IbtDq4Ay8NMNLQI7Dw7n4p8/rjkB
+ jV7j86HyQgM5e7+miRAz8V01b0I= )
+ example. 3600 NSEC a.example. NS SOA MX RRSIG NSEC DNSKEY
+ example. 3600 RRSIG NSEC 5 1 3600 20040509183619 (
+ 20040409183619 38519 example.
+ O0k558jHhyrC97ISHnislm4kLMW48C7U7cBm
+
+
+
+Arends, et al. Standards Track [Page 48]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ FTfhke5iVqNRVTB1STLMpgpbDIC9hcryoO0V
+ Z9ME5xPzUEhbvGnHd5sfzgFVeGxr5Nyyq4tW
+ SDBgIBiLQUv1ivy29vhXy7WgR62dPrZ0PWvm
+ jfFJ5arXf4nPxp/kEowGgBRzY/U= )
+
+ ;; Additional
+ ;; (empty)
+
+Appendix C. Authentication Examples
+
+ The examples in this section show how the response messages in
+ Appendix B are authenticated.
+
+C.1. Authenticating an Answer
+
+ The query in Appendix B.1 returned an MX RRset for "x.w.example.com".
+ The corresponding RRSIG indicates that the MX RRset was signed by an
+ "example" DNSKEY with algorithm 5 and key tag 38519. The resolver
+ needs the corresponding DNSKEY RR in order to authenticate this
+ answer. The discussion below describes how a resolver might obtain
+ this DNSKEY RR.
+
+ The RRSIG indicates the original TTL of the MX RRset was 3600, and,
+ for the purpose of authentication, the current TTL is replaced by
+ 3600. The RRSIG labels field value of 3 indicates that the answer
+ was not the result of wildcard expansion. The "x.w.example.com" MX
+ RRset is placed in canonical form, and, assuming the current time
+ falls between the signature inception and expiration dates, the
+ signature is authenticated.
+
+C.1.1. Authenticating the Example DNSKEY RR
+
+ This example shows the logical authentication process that starts
+ from the a configured root DNSKEY (or DS RR) and moves down the tree
+ to authenticate the desired "example" DNSKEY RR. Note that the
+ logical order is presented for clarity. An implementation may choose
+ to construct the authentication as referrals are received or to
+ construct the authentication chain only after all RRsets have been
+ obtained, or in any other combination it sees fit. The example here
+ demonstrates only the logical process and does not dictate any
+ implementation rules.
+
+ We assume the resolver starts with a configured DNSKEY RR for the
+ root zone (or a configured DS RR for the root zone). The resolver
+ checks whether this configured DNSKEY RR is present in the root
+ DNSKEY RRset (or whether the DS RR matches some DNSKEY in the root
+ DNSKEY RRset), whether this DNSKEY RR has signed the root DNSKEY
+ RRset, and whether the signature lifetime is valid. If all these
+
+
+
+Arends, et al. Standards Track [Page 49]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ conditions are met, all keys in the DNSKEY RRset are considered
+ authenticated. The resolver then uses one (or more) of the root
+ DNSKEY RRs to authenticate the "example" DS RRset. Note that the
+ resolver may have to query the root zone to obtain the root DNSKEY
+ RRset or "example" DS RRset.
+
+ Once the DS RRset has been authenticated using the root DNSKEY, the
+ resolver checks the "example" DNSKEY RRset for some "example" DNSKEY
+ RR that matches one of the authenticated "example" DS RRs. If such a
+ matching "example" DNSKEY is found, the resolver checks whether this
+ DNSKEY RR has signed the "example" DNSKEY RRset and the signature
+ lifetime is valid. If these conditions are met, all keys in the
+ "example" DNSKEY RRset are considered authenticated.
+
+ Finally, the resolver checks that some DNSKEY RR in the "example"
+ DNSKEY RRset uses algorithm 5 and has a key tag of 38519. This
+ DNSKEY is used to authenticate the RRSIG included in the response.
+ If multiple "example" DNSKEY RRs match this algorithm and key tag,
+ then each DNSKEY RR is tried, and the answer is authenticated if any
+ of the matching DNSKEY RRs validate the signature as described above.
+
+C.2. Name Error
+
+ The query in Appendix B.2 returned NSEC RRs that prove that the
+ requested data does not exist and no wildcard applies. The negative
+ reply is authenticated by verifying both NSEC RRs. The NSEC RRs are
+ authenticated in a manner identical to that of the MX RRset discussed
+ above.
+
+C.3. No Data Error
+
+ The query in Appendix B.3 returned an NSEC RR that proves that the
+ requested name exists, but the requested RR type does not exist. The
+ negative reply is authenticated by verifying the NSEC RR. The NSEC
+ RR is authenticated in a manner identical to that of the MX RRset
+ discussed above.
+
+C.4. Referral to Signed Zone
+
+ The query in Appendix B.4 returned a referral to the signed
+ "a.example." zone. The DS RR is authenticated in a manner identical
+ to that of the MX RRset discussed above. This DS RR is used to
+ authenticate the "a.example" DNSKEY RRset.
+
+ Once the "a.example" DS RRset has been authenticated using the
+ "example" DNSKEY, the resolver checks the "a.example" DNSKEY RRset
+ for some "a.example" DNSKEY RR that matches the DS RR. If such a
+ matching "a.example" DNSKEY is found, the resolver checks whether
+
+
+
+Arends, et al. Standards Track [Page 50]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+ this DNSKEY RR has signed the "a.example" DNSKEY RRset and whether
+ the signature lifetime is valid. If all these conditions are met,
+ all keys in the "a.example" DNSKEY RRset are considered
+ authenticated.
+
+C.5. Referral to Unsigned Zone
+
+ The query in Appendix B.5 returned a referral to an unsigned
+ "b.example." zone. The NSEC proves that no authentication leads from
+ "example" to "b.example", and the NSEC RR is authenticated in a
+ manner identical to that of the MX RRset discussed above.
+
+C.6. Wildcard Expansion
+
+ The query in Appendix B.6 returned an answer that was produced as a
+ result of wildcard expansion. The answer section contains a wildcard
+ RRset expanded as it would be in a traditional DNS response, and the
+ corresponding RRSIG indicates that the expanded wildcard MX RRset was
+ signed by an "example" DNSKEY with algorithm 5 and key tag 38519.
+ The RRSIG indicates that the original TTL of the MX RRset was 3600,
+ and, for the purpose of authentication, the current TTL is replaced
+ by 3600. The RRSIG labels field value of 2 indicates that the answer
+ is the result of wildcard expansion, as the "a.z.w.example" name
+ contains 4 labels. The name "a.z.w.w.example" is replaced by
+ "*.w.example", the MX RRset is placed in canonical form, and,
+ assuming that the current time falls between the signature inception
+ and expiration dates, the signature is authenticated.
+
+ The NSEC proves that no closer match (exact or closer wildcard) could
+ have been used to answer this query, and the NSEC RR must also be
+ authenticated before the answer is considered valid.
+
+C.7. Wildcard No Data Error
+
+ The query in Appendix B.7 returned NSEC RRs that prove that the
+ requested data does not exist and no wildcard applies. The negative
+ reply is authenticated by verifying both NSEC RRs.
+
+C.8. DS Child Zone No Data Error
+
+ The query in Appendix B.8 returned NSEC RRs that shows the requested
+ was answered by a child server ("example" server). The NSEC RR
+ indicates the presence of an SOA RR, showing that the answer is from
+ the child . Queries for the "example" DS RRset should be sent to the
+ parent servers ("root" servers).
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 51]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+Authors' Addresses
+
+ Roy Arends
+ Telematica Instituut
+ Brouwerijstraat 1
+ 7523 XC Enschede
+ NL
+
+ EMail: roy.arends@telin.nl
+
+
+ Rob Austein
+ Internet Systems Consortium
+ 950 Charter Street
+ Redwood City, CA 94063
+ USA
+
+ EMail: sra@isc.org
+
+
+ Matt Larson
+ VeriSign, Inc.
+ 21345 Ridgetop Circle
+ Dulles, VA 20166-6503
+ USA
+
+ EMail: mlarson@verisign.com
+
+
+ Dan Massey
+ Colorado State University
+ Department of Computer Science
+ Fort Collins, CO 80523-1873
+
+ EMail: massey@cs.colostate.edu
+
+
+ Scott Rose
+ National Institute for Standards and Technology
+ 100 Bureau Drive
+ Gaithersburg, MD 20899-8920
+ USA
+
+ EMail: scott.rose@nist.gov
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 52]
+
+RFC 4035 DNSSEC Protocol Modifications March 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Arends, et al. Standards Track [Page 53]
+
diff --git a/doc/rfc/rfc4074.txt b/doc/rfc/rfc4074.txt
new file mode 100644
index 0000000..d9252b3
--- /dev/null
+++ b/doc/rfc/rfc4074.txt
@@ -0,0 +1,339 @@
+
+
+
+
+
+
+Network Working Group Y. Morishita
+Request for Comments: 4074 JPRS
+Category: Informational T. Jinmei
+ Toshiba
+ May 2005
+
+
+ Common Misbehavior Against DNS Queries for IPv6 Addresses
+
+Status of This Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ There is some known misbehavior of DNS authoritative servers when
+ they are queried for AAAA resource records. Such behavior can block
+ IPv4 communication that should actually be available, cause a
+ significant delay in name resolution, or even make a denial of
+ service attack. This memo describes details of known cases and
+ discusses their effects.
+
+1. Introduction
+
+ Many existing DNS clients (resolvers) that support IPv6 first search
+ for AAAA Resource Records (RRs) of a target host name, and then for A
+ RRs of the same name. This fallback mechanism is based on the DNS
+ specifications, which if not obeyed by authoritative servers, can
+ produce unpleasant results. In some cases, for example, a web
+ browser fails to connect to a web server it could otherwise reach.
+ In the following sections, this memo describes some typical cases of
+ such misbehavior and its (bad) effects.
+
+ Note that the misbehavior is not specific to AAAA RRs. In fact, all
+ known examples also apply to the cases of queries for MX, NS, and SOA
+ RRs. The authors believe this can be generalized for all types of
+ queries other than those for A RRs. In this memo, however, we
+ concentrate on the case for AAAA queries, since the problem is
+ particularly severe for resolvers that support IPv6, which thus
+ affects many end users. Resolvers at end users normally send A
+ and/or AAAA queries only, so the problem for the other cases is
+ relatively minor.
+
+
+
+Morishita & Jinmei Informational [Page 1]
+
+RFC 4074 Common Misbehavior Against DNS Queries May 2005
+
+
+2. Network Model
+
+ In this memo, we assume a typical network model of name resolution
+ environment using DNS. It consists of three components: stub
+ resolvers, caching servers, and authoritative servers. A stub
+ resolver issues a recursive query to a caching server, which then
+ handles the entire name resolution procedure recursively. The
+ caching server caches the result of the query and sends the result to
+ the stub resolver. The authoritative servers respond to queries for
+ names for which they have the authority, normally in a non-recursive
+ manner.
+
+3. Expected Behavior
+
+ Suppose that an authoritative server has an A RR but has no AAAA RR
+ for a host name. Then, the server should return a response to a
+ query for an AAAA RR of the name with the response code (RCODE) being
+ 0 (indicating no error) and with an empty answer section (see
+ Sections 4.3.2 and 6.2.4 of [1]). Such a response indicates that
+ there is at least one RR of a different type than AAAA for the
+ queried name, and the stub resolver can then look for A RRs.
+
+ This way, the caching server can cache the fact that the queried name
+ has no AAAA RR (but may have other types of RRs), and thus improve
+ the response time to further queries for an AAAA RR of the name.
+
+4. Problematic Behaviors
+
+ There are some known cases at authoritative servers that do not
+ conform to the expected behavior. This section describes those
+ problematic cases.
+
+4.1. Ignore Queries for AAAA
+
+ Some authoritative servers seem to ignore queries for an AAAA RR,
+ causing a delay at the stub resolver to fall back to a query for an A
+ RR. This behavior may cause a fatal timeout at the resolver or at
+ the application that calls the resolver. Even if the resolver
+ eventually falls back, the result can be an unacceptable delay for
+ the application user, especially with interactive applications like
+ web browsing.
+
+4.2. Return "Name Error"
+
+ This type of server returns a response with RCODE 3 ("Name Error") to
+ a query for an AAAA RR, indicating that it does not have any RRs of
+ any type for the queried name.
+
+
+
+
+Morishita & Jinmei Informational [Page 2]
+
+RFC 4074 Common Misbehavior Against DNS Queries May 2005
+
+
+ With this response, the stub resolver may immediately give up and
+ never fall back. Even if the resolver retries with a query for an A
+ RR, the negative response for the name has been cached in the caching
+ server, and the caching server will simply return the negative
+ response. As a result, the stub resolver considers this to be a
+ fatal error in name resolution.
+
+ Several examples of this behavior are known to the authors. As of
+ this writing, all have been fixed.
+
+4.3. Return Other Erroneous Codes
+
+ Other authoritative servers return a response with erroneous response
+ codes other than RCODE 3 ("Name Error"). One such RCODE is 4 ("Not
+ Implemented"), indicating that the servers do not support the
+ requested type of query.
+
+ These cases are less harmful than the previous one; if the stub
+ resolver falls back to querying for an A RR, the caching server will
+ process the query correctly and return an appropriate response.
+
+ However, these can still cause a serious effect. There was an
+ authoritative server implementation that returned RCODE 2 ("Server
+ failure") to queries for AAAA RRs. One widely deployed mail server
+ implementation with a certain type of resolver library interpreted
+ this result as an indication of retry and did not fall back to
+ queries for A RRs, causing message delivery failure.
+
+ If the caching server receives a response with these response codes,
+ it does not cache the fact that the queried name has no AAAA RR,
+ resulting in redundant queries for AAAA RRs in the future. The
+ behavior will waste network bandwidth and increase the load of the
+ authoritative server.
+
+ Using RCODE 1 ("Format error") would cause a similar effect, though
+ the authors have not seen such implementations yet.
+
+4.4. Return a Broken Response
+
+ Another type of authoritative servers returns broken responses to
+ AAAA queries. Returning a response whose RR type is AAAA with the
+ length of the RDATA being 4 bytes is a known behavior of this
+ category. The 4-byte data looks like the IPv4 address of the queried
+ host name.
+
+
+
+
+
+
+
+Morishita & Jinmei Informational [Page 3]
+
+RFC 4074 Common Misbehavior Against DNS Queries May 2005
+
+
+ That is, the RR in the answer section would be described as follows:
+
+ www.bad.example. 600 IN AAAA 192.0.2.1
+
+ which is, of course, bogus (or at least meaningless).
+
+ A widely deployed caching server implementation transparently returns
+ the broken response (and caches it) to the stub resolver. Another
+ known server implementation parses the response by itself, and sends
+ a separate response with RCODE 2 ("Server failure").
+
+ In either case, the broken response does not affect queries for an A
+ RR of the same name. If the stub resolver falls back to A queries,
+ it will get an appropriate response.
+
+ The latter case, however, causes the same bad effect as that
+ described in the previous section: redundant queries for AAAA RRs.
+
+4.5. Make Lame Delegation
+
+ Some authoritative servers respond to AAAA queries in a way that
+ causes lame delegation. In this case, the parent zone specifies that
+ the authoritative server should have the authority of a zone, but the
+ server should not return an authoritative response for AAAA queries
+ within the zone (i.e., the AA bit in the response is not set). On
+ the other hand, the authoritative server returns an authoritative
+ response for A queries.
+
+ When a caching server asks the server for AAAA RRs in the zone, it
+ recognizes the delegation is lame, and returns a response with RCODE
+ 2 ("Server failure") to the stub resolver.
+
+ Furthermore, some caching servers record the authoritative server as
+ lame for the zone and will not use it for a certain period of time.
+ With this type of caching server, even if the stub resolver falls
+ back to querying for an A RR, the caching server will simply return a
+ response with RCODE 2, since all the servers are known to be "lame."
+
+ There is also an implementation that relaxes the behavior a little
+ bit. It tries to avoid using the lame server, but continues to try
+ it as a last resort. With this type of caching server, the stub
+ resolver will get a correct response if it falls back after Server
+ failure. However, this still causes redundant AAAA queries, as
+ explained in the previous sections.
+
+
+
+
+
+
+
+Morishita & Jinmei Informational [Page 4]
+
+RFC 4074 Common Misbehavior Against DNS Queries May 2005
+
+
+5. Security Considerations
+
+ The CERT/CC pointed out that the response with RCODE 3 ("Name
+ Error"), described in Section 4.2, can be used for a denial of
+ service attack [2]. The same argument applies to the case of "lame
+ delegation", described in Section 4.5, with a certain type of caching
+ server.
+
+6. Acknowledgements
+
+ Erik Nordmark encouraged the authors to publish this document as an
+ RFC. Akira Kato and Paul Vixie reviewed a preliminary version of
+ this document. Pekka Savola carefully reviewed a previous version
+ and provided detailed comments. Bill Fenner, Scott Hollenbeck,
+ Thomas Narten, and Alex Zinin reviewed and helped improve the
+ document at the last stage for publication.
+
+7. Informative References
+
+ [1] Mockapetris, P., "Domain names - concepts and facilities", STD
+ 13, RFC 1034, November 1987.
+
+ [2] The CERT Coordination Center, "Incorrect NXDOMAIN responses from
+ AAAA queries could cause denial-of-service conditions",
+ March 2003, <http://www.kb.cert.org/vuls/id/714121>.
+
+Authors' Addresses
+
+ MORISHITA Orange Yasuhiro
+ Research and Development Department, Japan Registry Services Co.,Ltd.
+ Chiyoda First Bldg. East 13F, 3-8-1 Nishi-Kanda
+ Chiyoda-ku, Tokyo 101-0065
+ Japan
+
+ EMail: yasuhiro@jprs.co.jp
+
+
+ JINMEI Tatuya
+ Corporate Research & Development Center, Toshiba Corporation
+ 1 Komukai Toshiba-cho, Saiwai-ku
+ Kawasaki-shi, Kanagawa 212-8582
+ Japan
+
+ EMail: jinmei@isl.rdc.toshiba.co.jp
+
+
+
+
+
+
+
+Morishita & Jinmei Informational [Page 5]
+
+RFC 4074 Common Misbehavior Against DNS Queries May 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Morishita & Jinmei Informational [Page 6]
+
diff --git a/doc/rfc/rfc4159.txt b/doc/rfc/rfc4159.txt
new file mode 100644
index 0000000..1ab4bd1
--- /dev/null
+++ b/doc/rfc/rfc4159.txt
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+Network Working Group G. Huston
+Request for Comments: 4159 APNIC
+BCP: 109 August 2005
+Category: Best Current Practice
+
+
+ Deprecation of "ip6.int"
+
+Status of This Memo
+
+ This document specifies an Internet Best Current Practices for the
+ Internet Community, and requests discussion and suggestions for
+ improvements. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document advises of the deprecation of the use of "ip6.int" for
+ Standards Conformant IPv6 implementations.
+
+1. IPv6 Standards Action
+
+ In August 2001 the IETF published [RFC3152], which advised that the
+ use of "ip6.int" as the domain for reverse-mapping of IPv6 addresses
+ to DNS names was deprecated. The document noted that the use of
+ "ip6.int" would be phased out in an orderly fashion.
+
+ As of 1 September 2005, the IETF advises the community that the DNS
+ domain "ip6.int" should no longer be used to perform reverse mapping
+ of IPv6 addresses to domain names, and that the domain "ip6.arpa"
+ should be used henceforth, in accordance with the IANA Considerations
+ described in [RFC3596]. The domain "ip6.int" is deprecated, and its
+ use in IPv6 implementations that conform to the IPv6 Internet
+ Standards is discontinued.
+
+ The Regional Internet Registries (RIRs) are advised that maintenance
+ of delegation of entries in "ip6.int" is no longer required as part
+ of infrastructure services in support of Internet Standards
+ Conformant IPv6 implementations as of 1 September 2005. The RIRs are
+ requested to work with their communities to adopt a schedule
+ regarding the cessation of support of registration services for the
+ "ip6.int" domain.
+
+
+
+
+
+
+Huston Best Current Practice [Page 1]
+
+RFC 4159 ip6.int August 2005
+
+
+2. IANA Considerations
+
+ IANA is advised that the "ip6.int" domain for reverse mapping of IPv6
+ addresses to domain names is no longer part of Internet Standards
+ Conformant support of IPv6 as of 1 September 2005.
+
+3. Security Considerations
+
+ While DNS spoofing of address to name mapping has been exploited in
+ IPv4, removal of the "ip6.int" zone from the standard IPv6
+ specification creates no new threats to the security of the internet.
+
+4. Acknowledgements
+
+ The document was prepared with the assistance of Kurt Lindqvist,
+ Thomas Narten, Paul Wilson, David Kessens, Bob Hinden, Brian
+ Haberman, and Bill Manning.
+
+5. Normative References
+
+ [RFC3152] Bush, R., "Delegation of IP6.ARPA", BCP 49, RFC 3152,
+ August 2001.
+
+ [RFC3596] Thomson, S., Huitema, C., Ksinant, V., and M. Souissi, "DNS
+ Extensions to Support IP Version 6", RFC 3596, October
+ 2003.
+
+Author's Address
+
+ Geoff Huston
+ APNIC
+
+ EMail: gih@apnic.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Huston Best Current Practice [Page 2]
+
+RFC 4159 ip6.int August 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Huston Best Current Practice [Page 3]
+
diff --git a/doc/rfc/rfc4193.txt b/doc/rfc/rfc4193.txt
new file mode 100644
index 0000000..17e2c0b
--- /dev/null
+++ b/doc/rfc/rfc4193.txt
@@ -0,0 +1,899 @@
+
+
+
+
+
+
+Network Working Group R. Hinden
+Request for Comments: 4193 Nokia
+Category: Standards Track B. Haberman
+ JHU-APL
+ October 2005
+
+
+ Unique Local IPv6 Unicast Addresses
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2005).
+
+Abstract
+
+ This document defines an IPv6 unicast address format that is globally
+ unique and is intended for local communications, usually inside of a
+ site. These addresses are not expected to be routable on the global
+ Internet.
+
+Table of Contents
+
+ 1. Introduction ....................................................2
+ 2. Acknowledgements ................................................3
+ 3. Local IPv6 Unicast Addresses ....................................3
+ 3.1. Format .....................................................3
+ 3.1.1. Background ..........................................4
+ 3.2. Global ID ..................................................4
+ 3.2.1. Locally Assigned Global IDs .........................5
+ 3.2.2. Sample Code for Pseudo-Random Global ID Algorithm ...5
+ 3.2.3. Analysis of the Uniqueness of Global IDs ............6
+ 3.3. Scope Definition ...........................................6
+ 4. Operational Guidelines ..........................................7
+ 4.1. Routing ....................................................7
+ 4.2. Renumbering and Site Merging ...............................7
+ 4.3. Site Border Router and Firewall Packet Filtering ...........8
+ 4.4. DNS Issues .................................................8
+ 4.5. Application and Higher Level Protocol Issues ...............9
+ 4.6. Use of Local IPv6 Addresses for Local Communication ........9
+ 4.7. Use of Local IPv6 Addresses with VPNs .....................10
+
+
+
+Hinden & Haberman Standards Track [Page 1]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+ 5. Global Routing Considerations ..................................11
+ 5.1. From the Standpoint of the Internet .......................11
+ 5.2. From the Standpoint of a Site .............................11
+ 6. Advantages and Disadvantages ...................................12
+ 6.1. Advantages ................................................12
+ 6.2. Disadvantages .............................................13
+ 7. Security Considerations ........................................13
+ 8. IANA Considerations ............................................13
+ 9. References .....................................................13
+ 9.1. Normative References ......................................13
+ 9.2. Informative References ....................................14
+
+1. Introduction
+
+ This document defines an IPv6 unicast address format that is globally
+ unique and is intended for local communications [IPV6]. These
+ addresses are called Unique Local IPv6 Unicast Addresses and are
+ abbreviated in this document as Local IPv6 addresses. They are not
+ expected to be routable on the global Internet. They are routable
+ inside of a more limited area such as a site. They may also be
+ routed between a limited set of sites.
+
+ Local IPv6 unicast addresses have the following characteristics:
+
+ - Globally unique prefix (with high probability of uniqueness).
+
+ - Well-known prefix to allow for easy filtering at site
+ boundaries.
+
+ - Allow sites to be combined or privately interconnected without
+ creating any address conflicts or requiring renumbering of
+ interfaces that use these prefixes.
+
+ - Internet Service Provider independent and can be used for
+ communications inside of a site without having any permanent or
+ intermittent Internet connectivity.
+
+ - If accidentally leaked outside of a site via routing or DNS,
+ there is no conflict with any other addresses.
+
+ - In practice, applications may treat these addresses like global
+ scoped addresses.
+
+ This document defines the format of Local IPv6 addresses, how to
+ allocate them, and usage considerations including routing, site
+ border routers, DNS, application support, VPN usage, and guidelines
+ for how to use for local communication inside a site.
+
+
+
+
+Hinden & Haberman Standards Track [Page 2]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+2. Acknowledgements
+
+ The underlying idea of creating Local IPv6 addresses described in
+ this document has been proposed a number of times by a variety of
+ people. The authors of this document do not claim exclusive credit.
+ Credit goes to Brian Carpenter, Christian Huitema, Aidan Williams,
+ Andrew White, Charlie Perkins, and many others. The authors would
+ also like to thank Brian Carpenter, Charlie Perkins, Harald
+ Alvestrand, Keith Moore, Margaret Wasserman, Shannon Behrens, Alan
+ Beard, Hans Kruse, Geoff Huston, Pekka Savola, Christian Huitema, Tim
+ Chown, Steve Bellovin, Alex Zinin, Tony Hain, Bill Fenner, Sam
+ Hartman, and Elwyn Davies for their comments and suggestions on this
+ document.
+
+3. Local IPv6 Unicast Addresses
+
+3.1. Format
+
+ The Local IPv6 addresses are created using a pseudo-randomly
+ allocated global ID. They have the following format:
+
+ | 7 bits |1| 40 bits | 16 bits | 64 bits |
+ +--------+-+------------+-----------+----------------------------+
+ | Prefix |L| Global ID | Subnet ID | Interface ID |
+ +--------+-+------------+-----------+----------------------------+
+
+ Where:
+
+ Prefix FC00::/7 prefix to identify Local IPv6 unicast
+ addresses.
+
+ L Set to 1 if the prefix is locally assigned.
+ Set to 0 may be defined in the future. See
+ Section 3.2 for additional information.
+
+ Global ID 40-bit global identifier used to create a
+ globally unique prefix. See Section 3.2 for
+ additional information.
+
+ Subnet ID 16-bit Subnet ID is an identifier of a subnet
+ within the site.
+
+ Interface ID 64-bit Interface ID as defined in [ADDARCH].
+
+
+
+
+Hinden & Haberman Standards Track [Page 3]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+3.1.1. Background
+
+ There were a range of choices available when choosing the size of the
+ prefix and Global ID field length. There is a direct tradeoff
+ between having a Global ID field large enough to support foreseeable
+ future growth and not using too much of the IPv6 address space
+ needlessly. A reasonable way of evaluating a specific field length
+ is to compare it to a projected 2050 world population of 9.3 billion
+ [POPUL] and the number of resulting /48 prefixes per person. A range
+ of prefix choices is shown in the following table:
+
+ Prefix Global ID Number of Prefixes % of IPv6
+ Length /48 Prefixes per Person Address Space
+
+ /11 37 137,438,953,472 15 0.049%
+ /10 38 274,877,906,944 30 0.098%
+ /9 39 549,755,813,888 59 0.195%
+ /8 40 1,099,511,627,776 118 0.391%
+ /7 41 2,199,023,255,552 236 0.781%
+ /6 42 4,398,046,511,104 473 1.563%
+
+ A very high utilization ratio of these allocations can be assumed
+ because the Global ID field does not require internal structure, and
+ there is no reason to be able to aggregate the prefixes.
+
+ The authors believe that a /7 prefix resulting in a 41-bit Global ID
+ space (including the L bit) is a good choice. It provides for a
+ large number of assignments (i.e., 2.2 trillion) and at the same time
+ uses less than .8% of the total IPv6 address space. It is unlikely
+ that this space will be exhausted. If more than this were to be
+ needed, then additional IPv6 address space could be allocated for
+ this purpose.
+
+3.2. Global ID
+
+ The allocation of Global IDs is pseudo-random [RANDOM]. They MUST
+ NOT be assigned sequentially or with well-known numbers. This is to
+ ensure that there is not any relationship between allocations and to
+ help clarify that these prefixes are not intended to be routed
+ globally. Specifically, these prefixes are not designed to
+ aggregate.
+
+ This document defines a specific local method to allocate Global IDs,
+ indicated by setting the L bit to 1. Another method, indicated by
+ clearing the L bit, may be defined later. Apart from the allocation
+ method, all Local IPv6 addresses behave and are treated identically.
+
+
+
+
+
+Hinden & Haberman Standards Track [Page 4]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+ The local assignments are self-generated and do not need any central
+ coordination or assignment, but have an extremely high probability of
+ being unique.
+
+3.2.1. Locally Assigned Global IDs
+
+ Locally assigned Global IDs MUST be generated with a pseudo-random
+ algorithm consistent with [RANDOM]. Section 3.2.2 describes a
+ suggested algorithm. It is important that all sites generating
+ Global IDs use a functionally similar algorithm to ensure there is a
+ high probability of uniqueness.
+
+ The use of a pseudo-random algorithm to generate Global IDs in the
+ locally assigned prefix gives an assurance that any network numbered
+ using such a prefix is highly unlikely to have that address space
+ clash with any other network that has another locally assigned prefix
+ allocated to it. This is a particularly useful property when
+ considering a number of scenarios including networks that merge,
+ overlapping VPN address space, or hosts mobile between such networks.
+
+3.2.2. Sample Code for Pseudo-Random Global ID Algorithm
+
+ The algorithm described below is intended to be used for locally
+ assigned Global IDs. In each case the resulting global ID will be
+ used in the appropriate prefix as defined in Section 3.2.
+
+ 1) Obtain the current time of day in 64-bit NTP format [NTP].
+
+ 2) Obtain an EUI-64 identifier from the system running this
+ algorithm. If an EUI-64 does not exist, one can be created from
+ a 48-bit MAC address as specified in [ADDARCH]. If an EUI-64
+ cannot be obtained or created, a suitably unique identifier,
+ local to the node, should be used (e.g., system serial number).
+
+ 3) Concatenate the time of day with the system-specific identifier
+ in order to create a key.
+
+ 4) Compute an SHA-1 digest on the key as specified in [FIPS, SHA1];
+ the resulting value is 160 bits.
+
+ 5) Use the least significant 40 bits as the Global ID.
+
+ 6) Concatenate FC00::/7, the L bit set to 1, and the 40-bit Global
+ ID to create a Local IPv6 address prefix.
+
+ This algorithm will result in a Global ID that is reasonably unique
+ and can be used to create a locally assigned Local IPv6 address
+ prefix.
+
+
+
+Hinden & Haberman Standards Track [Page 5]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+3.2.3. Analysis of the Uniqueness of Global IDs
+
+ The selection of a pseudo random Global ID is similar to the
+ selection of an SSRC identifier in RTP/RTCP defined in Section 8.1 of
+ [RTP]. This analysis is adapted from that document.
+
+ Since Global IDs are chosen randomly (and independently), it is
+ possible that separate networks have chosen the same Global ID. For
+ any given network, with one or more random Global IDs, that has
+ inter-connections to other such networks, having a total of N such
+ IDs, the probability that two or more of these IDs will collide can
+ be approximated using the formula:
+
+ P = 1 - exp(-N**2 / 2**(L+1))
+
+ where P is the probability of collision, N is the number of
+ interconnected Global IDs, and L is the length of the Global ID.
+
+ The following table shows the probability of a collision for a range
+ of connections using a 40-bit Global ID field.
+
+ Connections Probability of Collision
+
+ 2 1.81*10^-12
+ 10 4.54*10^-11
+ 100 4.54*10^-09
+ 1000 4.54*10^-07
+ 10000 4.54*10^-05
+
+ Based on this analysis, the uniqueness of locally generated Global
+ IDs is adequate for sites planning a small to moderate amount of
+ inter-site communication using locally generated Global IDs.
+
+3.3. Scope Definition
+
+ By default, the scope of these addresses is global. That is, they
+ are not limited by ambiguity like the site-local addresses defined in
+ [ADDARCH]. Rather, these prefixes are globally unique, and as such,
+ their applicability is greater than site-local addresses. Their
+ limitation is in the routability of the prefixes, which is limited to
+ a site and any explicit routing agreements with other sites to
+ propagate them (also see Section 4.1). Also, unlike site-locals, a
+ site may have more than one of these prefixes and use them at the
+ same time.
+
+
+
+
+
+
+
+Hinden & Haberman Standards Track [Page 6]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+4. Operational Guidelines
+
+ The guidelines in this section do not require any change to the
+ normal routing and forwarding functionality in an IPv6 host or
+ router. These are configuration and operational usage guidelines.
+
+4.1. Routing
+
+ Local IPv6 addresses are designed to be routed inside of a site in
+ the same manner as other types of unicast addresses. They can be
+ carried in any IPv6 routing protocol without any change.
+
+ It is expected that they would share the same Subnet IDs with
+ provider-based global unicast addresses, if they were being used
+ concurrently [GLOBAL].
+
+ The default behavior of exterior routing protocol sessions between
+ administrative routing regions must be to ignore receipt of and not
+ advertise prefixes in the FC00::/7 block. A network operator may
+ specifically configure prefixes longer than FC00::/7 for inter-site
+ communication.
+
+ If BGP is being used at the site border with an ISP, the default BGP
+ configuration must filter out any Local IPv6 address prefixes, both
+ incoming and outgoing. It must be set both to keep any Local IPv6
+ address prefixes from being advertised outside of the site as well as
+ to keep these prefixes from being learned from another site. The
+ exception to this is if there are specific /48 or longer routes
+ created for one or more Local IPv6 prefixes.
+
+ For link-state IGPs, it is suggested that a site utilizing IPv6 local
+ address prefixes be contained within one IGP domain or area. By
+ containing an IPv6 local address prefix to a single link-state area
+ or domain, the distribution of prefixes can be controlled.
+
+4.2. Renumbering and Site Merging
+
+ The use of Local IPv6 addresses in a site results in making
+ communication that uses these addresses independent of renumbering a
+ site's provider-based global addresses.
+
+ When merging multiple sites, the addresses created with these
+ prefixes are unlikely to need to be renumbered because all of the
+ addresses have a high probability of being unique. Routes for each
+ specific prefix would have to be configured to allow routing to work
+ correctly between the formerly separate sites.
+
+
+
+
+
+Hinden & Haberman Standards Track [Page 7]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+4.3. Site Border Router and Firewall Packet Filtering
+
+ While no serious harm will be done if packets with these addresses
+ are sent outside of a site via a default route, it is recommended
+ that routers be configured by default to keep any packets with Local
+ IPv6 addresses from leaking outside of the site and to keep any site
+ prefixes from being advertised outside of their site.
+
+ Site border routers and firewalls should be configured to not forward
+ any packets with Local IPv6 source or destination addresses outside
+ of the site, unless they have been explicitly configured with routing
+ information about specific /48 or longer Local IPv6 prefixes. This
+ will ensure that packets with Local IPv6 destination addresses will
+ not be forwarded outside of the site via a default route. The
+ default behavior of these devices should be to install a "reject"
+ route for these prefixes. Site border routers should respond with
+ the appropriate ICMPv6 Destination Unreachable message to inform the
+ source that the packet was not forwarded. [ICMPV6]. This feedback is
+ important to avoid transport protocol timeouts.
+
+ Routers that maintain peering arrangements between Autonomous Systems
+ throughout the Internet should obey the recommendations for site
+ border routers, unless configured otherwise.
+
+4.4. DNS Issues
+
+ At the present time, AAAA and PTR records for locally assigned local
+ IPv6 addresses are not recommended to be installed in the global DNS.
+
+ For background on this recommendation, one of the concerns about
+ adding AAAA and PTR records to the global DNS for locally assigned
+ Local IPv6 addresses stems from the lack of complete assurance that
+ the prefixes are unique. There is a small possibility that the same
+ locally assigned IPv6 Local addresses will be used by two different
+ organizations both claiming to be authoritative with different
+ contents. In this scenario, it is likely there will be a connection
+ attempt to the closest host with the corresponding locally assigned
+ IPv6 Local address. This may result in connection timeouts,
+ connection failures indicated by ICMP Destination Unreachable
+ messages, or successful connections to the wrong host. Due to this
+ concern, adding AAAA records for these addresses to the global DNS is
+ thought to be unwise.
+
+ Reverse (address-to-name) queries for locally assigned IPv6 Local
+ addresses MUST NOT be sent to name servers for the global DNS, due to
+ the load that such queries would create for the authoritative name
+ servers for the ip6.arpa zone. This form of query load is not
+ specific to locally assigned Local IPv6 addresses; any current form
+
+
+
+Hinden & Haberman Standards Track [Page 8]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+ of local addressing creates additional load of this kind, due to
+ reverse queries leaking out of the site. However, since allowing
+ such queries to escape from the site serves no useful purpose, there
+ is no good reason to make the existing load problems worse.
+
+ The recommended way to avoid sending such queries to nameservers for
+ the global DNS is for recursive name server implementations to act as
+ if they were authoritative for an empty d.f.ip6.arpa zone and return
+ RCODE 3 for any such query. Implementations that choose this
+ strategy should allow it to be overridden, but returning an RCODE 3
+ response for such queries should be the default, both because this
+ will reduce the query load problem and also because, if the site
+ administrator has not set up the reverse tree corresponding to the
+ locally assigned IPv6 Local addresses in use, returning RCODE 3 is in
+ fact the correct answer.
+
+4.5. Application and Higher Level Protocol Issues
+
+ Application and other higher level protocols can treat Local IPv6
+ addresses in the same manner as other types of global unicast
+ addresses. No special handling is required. This type of address
+ may not be reachable, but that is no different from other types of
+ IPv6 global unicast address. Applications need to be able to handle
+ multiple addresses that may or may not be reachable at any point in
+ time. In most cases, this complexity should be hidden in APIs.
+
+ From a host's perspective, the difference between Local IPv6 and
+ other types of global unicast addresses shows up as different
+ reachability and could be handled by default in that way. In some
+ cases, it is better for nodes and applications to treat them
+ differently from global unicast addresses. A starting point might be
+ to give them preference over global unicast, but fall back to global
+ unicast if a particular destination is found to be unreachable. Much
+ of this behavior can be controlled by how they are allocated to nodes
+ and put into the DNS. However, it is useful if a host can have both
+ types of addresses and use them appropriately.
+
+ Note that the address selection mechanisms of [ADDSEL], and in
+ particular the policy override mechanism replacing default address
+ selection, are expected to be used on a site where Local IPv6
+ addresses are configured.
+
+4.6. Use of Local IPv6 Addresses for Local Communication
+
+ Local IPv6 addresses, like global scope unicast addresses, are only
+ assigned to nodes if their use has been enabled (via IPv6 address
+ autoconfiguration [ADDAUTO], DHCPv6 [DHCP6], or manually). They are
+
+
+
+
+Hinden & Haberman Standards Track [Page 9]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+ not created automatically in the way that IPv6 link-local addresses
+ are and will not appear or be used unless they are purposely
+ configured.
+
+ In order for hosts to autoconfigure Local IPv6 addresses, routers
+ have to be configured to advertise Local IPv6 /64 prefixes in router
+ advertisements, or a DHCPv6 server must have been configured to
+ assign them. In order for a node to learn the Local IPv6 address of
+ another node, the Local IPv6 address must have been installed in a
+ naming system (e.g., DNS, proprietary naming system, etc.) For these
+ reasons, controlling their usage in a site is straightforward.
+
+ To limit the use of Local IPv6 addresses the following guidelines
+ apply:
+
+ - Nodes that are to only be reachable inside of a site: The local
+ DNS should be configured to only include the Local IPv6
+ addresses of these nodes. Nodes with only Local IPv6 addresses
+ must not be installed in the global DNS.
+
+ - Nodes that are to be limited to only communicate with other
+ nodes in the site: These nodes should be set to only
+ autoconfigure Local IPv6 addresses via [ADDAUTO] or to only
+ receive Local IPv6 addresses via [DHCP6]. Note: For the case
+ where both global and Local IPv6 prefixes are being advertised
+ on a subnet, this will require a switch in the devices to only
+ autoconfigure Local IPv6 addresses.
+
+ - Nodes that are to be reachable from inside of the site and from
+ outside of the site: The DNS should be configured to include
+ the global addresses of these nodes. The local DNS may be
+ configured to also include the Local IPv6 addresses of these
+ nodes.
+
+ - Nodes that can communicate with other nodes inside of the site
+ and outside of the site: These nodes should autoconfigure global
+ addresses via [ADDAUTO] or receive global address via [DHCP6].
+ They may also obtain Local IPv6 addresses via the same
+ mechanisms.
+
+4.7. Use of Local IPv6 Addresses with VPNs
+
+ Local IPv6 addresses can be used for inter-site Virtual Private
+ Networks (VPN) if appropriate routes are set up. Because the
+ addresses are unique, these VPNs will work reliably and without the
+ need for translation. They have the additional property that they
+ will continue to work if the individual sites are renumbered or
+ merged.
+
+
+
+Hinden & Haberman Standards Track [Page 10]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+5. Global Routing Considerations
+
+ Section 4.1 provides operational guidelines that forbid default
+ routing of local addresses between sites. Concerns were raised to
+ the IPv6 working group and to the IETF as a whole that sites may
+ attempt to use local addresses as globally routed provider-
+ independent addresses. This section describes why using local
+ addresses as globally-routed provider-independent addresses is
+ unadvisable.
+
+5.1. From the Standpoint of the Internet
+
+ There is a mismatch between the structure of IPv6 local addresses and
+ the normal IPv6 wide area routing model. The /48 prefix of an IPv6
+ local addresses fits nowhere in the normal hierarchy of IPv6 unicast
+ addresses. Normal IPv6 unicast addresses can be routed
+ hierarchically down to physical subnet (link) level and only have to
+ be flat-routed on the physical subnet. IPv6 local addresses would
+ have to be flat-routed even over the wide area Internet.
+
+ Thus, packets whose destination address is an IPv6 local address
+ could be routed over the wide area only if the corresponding /48
+ prefix were carried by the wide area routing protocol in use, such as
+ BGP. This contravenes the operational assumption that long prefixes
+ will be aggregated into many fewer short prefixes, to limit the table
+ size and convergence time of the routing protocol. If a network uses
+ both normal IPv6 addresses [ADDARCH] and IPv6 local addresses, these
+ types of addresses will certainly not aggregate with each other,
+ since they differ from the most significant bit onwards. Neither
+ will IPv6 local addresses aggregate with each other, due to their
+ random bit patterns. This means that there would be a very
+ significant operational penalty for attempting to use IPv6 local
+ address prefixes generically with currently known wide area routing
+ technology.
+
+5.2. From the Standpoint of a Site
+
+ There are a number of design factors in IPv6 local addresses that
+ reduce the likelihood that IPv6 local addresses will be used as
+ arbitrary global unicast addresses. These include:
+
+ - The default rules to filter packets and routes make it very
+ difficult to use IPv6 local addresses for arbitrary use across
+ the Internet. For a site to use them as general purpose unicast
+ addresses, it would have to make sure that the default rules
+ were not being used by all other sites and intermediate ISPs
+ used for their current and future communication.
+
+
+
+
+Hinden & Haberman Standards Track [Page 11]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+ - They are not mathematically guaranteed to be unique and are not
+ registered in public databases. Collisions, while highly
+ unlikely, are possible and a collision can compromise the
+ integrity of the communications. The lack of public
+ registration creates operational problems.
+
+ - The addresses are allocated randomly. If a site had multiple
+ prefixes that it wanted to be used globally, the cost of
+ advertising them would be very high because they could not be
+ aggregated.
+
+ - They have a long prefix (i.e., /48) so a single local address
+ prefix doesn't provide enough address space to be used
+ exclusively by the largest organizations.
+
+6. Advantages and Disadvantages
+
+6.1. Advantages
+
+ This approach has the following advantages:
+
+ - Provides Local IPv6 prefixes that can be used independently of
+ any provider-based IPv6 unicast address allocations. This is
+ useful for sites not always connected to the Internet or sites
+ that wish to have a distinct prefix that can be used to localize
+ traffic inside of the site.
+
+ - Applications can treat these addresses in an identical manner as
+ any other type of global IPv6 unicast addresses.
+
+ - Sites can be merged without any renumbering of the Local IPv6
+ addresses.
+
+ - Sites can change their provider-based IPv6 unicast address
+ without disrupting any communication that uses Local IPv6
+ addresses.
+
+ - Well-known prefix that allows for easy filtering at site
+ boundary.
+
+ - Can be used for inter-site VPNs.
+
+ - If accidently leaked outside of a site via routing or DNS, there
+ is no conflict with any other addresses.
+
+
+
+
+
+
+
+Hinden & Haberman Standards Track [Page 12]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+6.2. Disadvantages
+
+ This approach has the following disadvantages:
+
+ - Not possible to route Local IPv6 prefixes on the global Internet
+ with current routing technology. Consequentially, it is
+ necessary to have the default behavior of site border routers to
+ filter these addresses.
+
+ - There is a very low probability of non-unique locally assigned
+ Global IDs being generated by the algorithm in Section 3.2.3.
+ This risk can be ignored for all practical purposes, but it
+ leads to a theoretical risk of clashing address prefixes.
+
+7. Security Considerations
+
+ Local IPv6 addresses do not provide any inherent security to the
+ nodes that use them. They may be used with filters at site
+ boundaries to keep Local IPv6 traffic inside of the site, but this is
+ no more or less secure than filtering any other type of global IPv6
+ unicast addresses.
+
+ Local IPv6 addresses do allow for address-based security mechanisms,
+ including IPsec, across end to end VPN connections.
+
+8. IANA Considerations
+
+ The IANA has assigned the FC00::/7 prefix to "Unique Local Unicast".
+
+9. References
+
+9.1. Normative References
+
+ [ADDARCH] Hinden, R. and S. Deering, "Internet Protocol Version 6
+ (IPv6) Addressing Architecture", RFC 3513, April 2003.
+
+ [FIPS] "Federal Information Processing Standards Publication",
+ (FIPS PUB) 180-1, Secure Hash Standard, 17 April 1995.
+
+ [GLOBAL] Hinden, R., Deering, S., and E. Nordmark, "IPv6 Global
+ Unicast Address Format", RFC 3587, August 2003.
+
+ [ICMPV6] Conta, A. and S. Deering, "Internet Control Message
+ Protocol (ICMPv6) for the Internet Protocol Version 6
+ (IPv6) Specification", RFC 2463, December 1998.
+
+
+
+
+
+
+Hinden & Haberman Standards Track [Page 13]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+ [IPV6] Deering, S. and R. Hinden, "Internet Protocol, Version 6
+ (IPv6) Specification", RFC 2460, December 1998.
+
+ [NTP] Mills, D., "Network Time Protocol (Version 3)
+ Specification, Implementation and Analysis", RFC 1305,
+ March 1992.
+
+ [RANDOM] Eastlake, D., 3rd, Schiller, J., and S. Crocker,
+ "Randomness Requirements for Security", BCP 106, RFC 4086,
+ June 2005.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [SHA1] Eastlake 3rd, D. and P. Jones, "US Secure Hash Algorithm 1
+ (SHA1)", RFC 3174, September 2001.
+
+9.2. Informative References
+
+ [ADDAUTO] Thomson, S. and T. Narten, "IPv6 Stateless Address
+ Autoconfiguration", RFC 2462, December 1998.
+
+ [ADDSEL] Draves, R., "Default Address Selection for Internet
+ Protocol version 6 (IPv6)", RFC 3484, February 2003.
+
+ [DHCP6] Droms, R., Bound, J., Volz, B., Lemon, T., Perkins, C., and
+ M. Carney, "Dynamic Host Configuration Protocol for IPv6
+ (DHCPv6)", RFC 3315, July 2003.
+
+ [POPUL] Population Reference Bureau, "World Population Data Sheet
+ of the Population Reference Bureau 2002", August 2002.
+
+ [RTP] Schulzrinne, H., Casner, S., Frederick, R., and V.
+ Jacobson, "RTP: A Transport Protocol for Real-Time
+ Applications", STD 64, RFC 3550, July 2003.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Haberman Standards Track [Page 14]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+Authors' Addresses
+
+ Robert M. Hinden
+ Nokia
+ 313 Fairchild Drive
+ Mountain View, CA 94043
+ USA
+
+ Phone: +1 650 625-2004
+ EMail: bob.hinden@nokia.com
+
+
+ Brian Haberman
+ Johns Hopkins University
+ Applied Physics Lab
+ 11100 Johns Hopkins Road
+ Laurel, MD 20723
+ USA
+
+ Phone: +1 443 778 1319
+ EMail: brian@innovationslab.net
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hinden & Haberman Standards Track [Page 15]
+
+RFC 4193 Unique Local IPv6 Unicast Addresses October 2005
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2005).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at ietf-
+ ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is currently provided by the
+ Internet Society.
+
+
+
+
+
+
+
+Hinden & Haberman Standards Track [Page 16]
+
diff --git a/doc/rfc/rfc4255.txt b/doc/rfc/rfc4255.txt
new file mode 100644
index 0000000..f350b7a
--- /dev/null
+++ b/doc/rfc/rfc4255.txt
@@ -0,0 +1,507 @@
+
+
+
+
+
+
+Network Working Group J. Schlyter
+Request for Comments: 4255 OpenSSH
+Category: Standards Track W. Griffin
+ SPARTA
+ January 2006
+
+
+ Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ This document describes a method of verifying Secure Shell (SSH) host
+ keys using Domain Name System Security (DNSSEC). The document
+ defines a new DNS resource record that contains a standard SSH key
+ fingerprint.
+
+Table of Contents
+
+ 1. Introduction ....................................................2
+ 2. SSH Host Key Verification .......................................2
+ 2.1. Method .....................................................2
+ 2.2. Implementation Notes .......................................2
+ 2.3. Fingerprint Matching .......................................3
+ 2.4. Authentication .............................................3
+ 3. The SSHFP Resource Record .......................................3
+ 3.1. The SSHFP RDATA Format .....................................4
+ 3.1.1. Algorithm Number Specification ......................4
+ 3.1.2. Fingerprint Type Specification ......................4
+ 3.1.3. Fingerprint .........................................5
+ 3.2. Presentation Format of the SSHFP RR ........................5
+ 4. Security Considerations .........................................5
+ 5. IANA Considerations .............................................6
+ 6. Normative References ............................................7
+ 7. Informational References ........................................7
+ 8. Acknowledgements ................................................8
+
+
+
+
+Schlyter & Griffin Standards Track [Page 1]
+
+RFC 4255 DNS and SSH Fingerprints January 2006
+
+
+1. Introduction
+
+ The SSH [6] protocol provides secure remote login and other secure
+ network services over an insecure network. The security of the
+ connection relies on the server authenticating itself to the client
+ as well as the user authenticating itself to the server.
+
+ If a connection is established to a server whose public key is not
+ already known to the client, a fingerprint of the key is presented to
+ the user for verification. If the user decides that the fingerprint
+ is correct and accepts the key, the key is saved locally and used for
+ verification for all following connections. While some security-
+ conscious users verify the fingerprint out-of-band before accepting
+ the key, many users blindly accept the presented key.
+
+ The method described here can provide out-of-band verification by
+ looking up a fingerprint of the server public key in the DNS [1][2]
+ and using DNSSEC [5] to verify the lookup.
+
+ In order to distribute the fingerprint using DNS, this document
+ defines a new DNS resource record, "SSHFP", to carry the fingerprint.
+
+ Basic understanding of the DNS system [1][2] and the DNS security
+ extensions [5] is assumed by this document.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [3].
+
+2. SSH Host Key Verification
+
+2.1. Method
+
+ Upon connection to an SSH server, the SSH client MAY look up the
+ SSHFP resource record(s) for the host it is connecting to. If the
+ algorithm and fingerprint of the key received from the SSH server
+ match the algorithm and fingerprint of one of the SSHFP resource
+ record(s) returned from DNS, the client MAY accept the identity of
+ the server.
+
+2.2. Implementation Notes
+
+ Client implementors SHOULD provide a configurable policy used to
+ select the order of methods used to verify a host key. This document
+ defines one method: Fingerprint storage in DNS. Another method
+ defined in the SSH Architecture [6] uses local files to store keys
+ for comparison. Other methods that could be defined in the future
+ might include storing fingerprints in LDAP or other databases. A
+
+
+
+Schlyter & Griffin Standards Track [Page 2]
+
+RFC 4255 DNS and SSH Fingerprints January 2006
+
+
+ configurable policy will allow administrators to determine which
+ methods they want to use and in what order the methods should be
+ prioritized. This will allow administrators to determine how much
+ trust they want to place in the different methods.
+
+ One specific scenario for having a configurable policy is where
+ clients do not use fully qualified host names to connect to servers.
+ In this scenario, the implementation SHOULD verify the host key
+ against a local database before verifying the key via the fingerprint
+ returned from DNS. This would help prevent an attacker from
+ injecting a DNS search path into the local resolver and forcing the
+ client to connect to a different host.
+
+2.3. Fingerprint Matching
+
+ The public key and the SSHFP resource record are matched together by
+ comparing algorithm number and fingerprint.
+
+ The public key algorithm and the SSHFP algorithm number MUST
+ match.
+
+ A message digest of the public key, using the message digest
+ algorithm specified in the SSHFP fingerprint type, MUST match the
+ SSHFP fingerprint.
+
+2.4. Authentication
+
+ A public key verified using this method MUST NOT be trusted if the
+ SSHFP resource record (RR) used for verification was not
+ authenticated by a trusted SIG RR.
+
+ Clients that do validate the DNSSEC signatures themselves SHOULD use
+ standard DNSSEC validation procedures.
+
+ Clients that do not validate the DNSSEC signatures themselves MUST
+ use a secure transport (e.g., TSIG [9], SIG(0) [10], or IPsec [8])
+ between themselves and the entity performing the signature
+ validation.
+
+3. The SSHFP Resource Record
+
+ The SSHFP resource record (RR) is used to store a fingerprint of an
+ SSH public host key that is associated with a Domain Name System
+ (DNS) name.
+
+ The RR type code for the SSHFP RR is 44.
+
+
+
+
+
+Schlyter & Griffin Standards Track [Page 3]
+
+RFC 4255 DNS and SSH Fingerprints January 2006
+
+
+3.1. The SSHFP RDATA Format
+
+ The RDATA for a SSHFP RR consists of an algorithm number, fingerprint
+ type and the fingerprint of the public host key.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | algorithm | fp type | /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ /
+ / /
+ / fingerprint /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+3.1.1. Algorithm Number Specification
+
+ This algorithm number octet describes the algorithm of the public
+ key. The following values are assigned:
+
+ Value Algorithm name
+ ----- --------------
+ 0 reserved
+ 1 RSA
+ 2 DSS
+
+ Reserving other types requires IETF consensus [4].
+
+3.1.2. Fingerprint Type Specification
+
+ The fingerprint type octet describes the message-digest algorithm
+ used to calculate the fingerprint of the public key. The following
+ values are assigned:
+
+ Value Fingerprint type
+ ----- ----------------
+ 0 reserved
+ 1 SHA-1
+
+ Reserving other types requires IETF consensus [4].
+
+ For interoperability reasons, as few fingerprint types as possible
+ should be reserved. The only reason to reserve additional types is
+ to increase security.
+
+
+
+
+
+
+
+Schlyter & Griffin Standards Track [Page 4]
+
+RFC 4255 DNS and SSH Fingerprints January 2006
+
+
+3.1.3. Fingerprint
+
+ The fingerprint is calculated over the public key blob as described
+ in [7].
+
+ The message-digest algorithm is presumed to produce an opaque octet
+ string output, which is placed as-is in the RDATA fingerprint field.
+
+3.2. Presentation Format of the SSHFP RR
+
+ The RDATA of the presentation format of the SSHFP resource record
+ consists of two numbers (algorithm and fingerprint type) followed by
+ the fingerprint itself, presented in hex, e.g.:
+
+ host.example. SSHFP 2 1 123456789abcdef67890123456789abcdef67890
+
+ The use of mnemonics instead of numbers is not allowed.
+
+4. Security Considerations
+
+ Currently, the amount of trust a user can realistically place in a
+ server key is proportional to the amount of attention paid to
+ verifying that the public key presented actually corresponds to the
+ private key of the server. If a user accepts a key without verifying
+ the fingerprint with something learned through a secured channel, the
+ connection is vulnerable to a man-in-the-middle attack.
+
+ The overall security of using SSHFP for SSH host key verification is
+ dependent on the security policies of the SSH host administrator and
+ DNS zone administrator (in transferring the fingerprint), detailed
+ aspects of how verification is done in the SSH implementation, and in
+ the client's diligence in accessing the DNS in a secure manner.
+
+ One such aspect is in which order fingerprints are looked up (e.g.,
+ first checking local file and then SSHFP). We note that, in addition
+ to protecting the first-time transfer of host keys, SSHFP can
+ optionally be used for stronger host key protection.
+
+ If SSHFP is checked first, new SSH host keys may be distributed by
+ replacing the corresponding SSHFP in DNS.
+
+ If SSH host key verification can be configured to require SSHFP,
+ SSH host key revocation can be implemented by removing the
+ corresponding SSHFP from DNS.
+
+
+
+
+
+
+
+Schlyter & Griffin Standards Track [Page 5]
+
+RFC 4255 DNS and SSH Fingerprints January 2006
+
+
+ As stated in Section 2.2, we recommend that SSH implementors provide
+ a policy mechanism to control the order of methods used for host key
+ verification. One specific scenario for having a configurable policy
+ is where clients use unqualified host names to connect to servers.
+ In this case, we recommend that SSH implementations check the host
+ key against a local database before verifying the key via the
+ fingerprint returned from DNS. This would help prevent an attacker
+ from injecting a DNS search path into the local resolver and forcing
+ the client to connect to a different host.
+
+ A different approach to solve the DNS search path issue would be for
+ clients to use a trusted DNS search path, i.e., one not acquired
+ through DHCP or other autoconfiguration mechanisms. Since there is
+ no way with current DNS lookup APIs to tell whether a search path is
+ from a trusted source, the entire client system would need to be
+ configured with this trusted DNS search path.
+
+ Another dependency is on the implementation of DNSSEC itself. As
+ stated in Section 2.4, we mandate the use of secure methods for
+ lookup and that SSHFP RRs are authenticated by trusted SIG RRs. This
+ is especially important if SSHFP is to be used as a basis for host
+ key rollover and/or revocation, as described above.
+
+ Since DNSSEC only protects the integrity of the host key fingerprint
+ after it is signed by the DNS zone administrator, the fingerprint
+ must be transferred securely from the SSH host administrator to the
+ DNS zone administrator. This could be done manually between the
+ administrators or automatically using secure DNS dynamic update [11]
+ between the SSH server and the nameserver. We note that this is no
+ different from other key enrollment situations, e.g., a client
+ sending a certificate request to a certificate authority for signing.
+
+5. IANA Considerations
+
+ IANA has allocated the RR type code 44 for SSHFP from the standard RR
+ type space.
+
+ IANA has opened a new registry for the SSHFP RR type for public key
+ algorithms. The defined types are:
+
+ 0 is reserved
+ 1 is RSA
+ 2 is DSA
+
+ Adding new reservations requires IETF consensus [4].
+
+
+
+
+
+
+Schlyter & Griffin Standards Track [Page 6]
+
+RFC 4255 DNS and SSH Fingerprints January 2006
+
+
+ IANA has opened a new registry for the SSHFP RR type for fingerprint
+ types. The defined types are:
+
+ 0 is reserved
+ 1 is SHA-1
+
+ Adding new reservations requires IETF consensus [4].
+
+6. Normative References
+
+ [1] Mockapetris, P., "Domain names - concepts and facilities", STD
+ 13, RFC 1034, November 1987.
+
+ [2] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [3] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [4] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA
+ Considerations Section in RFCs", BCP 26, RFC 2434, October
+ 1998.
+
+ [5] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033, March
+ 2005.
+
+ Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+ Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Protocol Modifications for the DNS Security Extensions", RFC
+ 4035, March 2005.
+
+ [6] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH)
+ Protocol Architecture", RFC 4251, January 2006.
+
+ [7] Ylonen, T. and C. Lonvick, Ed., "The Secure Shell (SSH)
+ Transport Layer Protocol", RFC 4253, January 2006.
+
+7. Informational References
+
+ [8] Thayer, R., Doraswamy, N., and R. Glenn, "IP Security Document
+ Roadmap", RFC 2411, November 1998.
+
+
+
+
+
+
+Schlyter & Griffin Standards Track [Page 7]
+
+RFC 4255 DNS and SSH Fingerprints January 2006
+
+
+ [9] Vixie, P., Gudmundsson, O., Eastlake 3rd, D., and B.
+ Wellington, "Secret Key Transaction Authentication for DNS
+ (TSIG)", RFC 2845, May 2000.
+
+ [10] Eastlake 3rd, D., "DNS Request and Transaction Signatures
+ ( SIG(0)s )", RFC 2931, September 2000.
+
+ [11] Wellington, B., "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+8. Acknowledgements
+
+ The authors gratefully acknowledge, in no particular order, the
+ contributions of the following persons:
+
+ Martin Fredriksson
+
+ Olafur Gudmundsson
+
+ Edward Lewis
+
+ Bill Sommerfeld
+
+Authors' Addresses
+
+ Jakob Schlyter
+ OpenSSH
+ 812 23rd Avenue SE
+ Calgary, Alberta T2G 1N8
+ Canada
+
+ EMail: jakob@openssh.com
+ URI: http://www.openssh.com/
+
+
+ Wesley Griffin
+ SPARTA
+ 7075 Samuel Morse Drive
+ Columbia, MD 21046
+ USA
+
+ EMail: wgriffin@sparta.com
+ URI: http://www.sparta.com/
+
+
+
+
+
+
+
+
+Schlyter & Griffin Standards Track [Page 8]
+
+RFC 4255 DNS and SSH Fingerprints January 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Schlyter & Griffin Standards Track [Page 9]
+
diff --git a/doc/rfc/rfc4343.txt b/doc/rfc/rfc4343.txt
new file mode 100644
index 0000000..621420a
--- /dev/null
+++ b/doc/rfc/rfc4343.txt
@@ -0,0 +1,563 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake 3rd
+Request for Comments: 4343 Motorola Laboratories
+Updates: 1034, 1035, 2181 January 2006
+Category: Standards Track
+
+
+ Domain Name System (DNS) Case Insensitivity Clarification
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ Domain Name System (DNS) names are "case insensitive". This document
+ explains exactly what that means and provides a clear specification
+ of the rules. This clarification updates RFCs 1034, 1035, and 2181.
+
+Table of Contents
+
+ 1. Introduction ....................................................2
+ 2. Case Insensitivity of DNS Labels ................................2
+ 2.1. Escaping Unusual DNS Label Octets ..........................2
+ 2.2. Example Labels with Escapes ................................3
+ 3. Name Lookup, Label Types, and CLASS .............................3
+ 3.1. Original DNS Label Types ...................................4
+ 3.2. Extended Label Type Case Insensitivity Considerations ......4
+ 3.3. CLASS Case Insensitivity Considerations ....................4
+ 4. Case on Input and Output ........................................5
+ 4.1. DNS Output Case Preservation ...............................5
+ 4.2. DNS Input Case Preservation ................................5
+ 5. Internationalized Domain Names ..................................6
+ 6. Security Considerations .........................................6
+ 7. Acknowledgements ................................................7
+ Normative References................................................7
+ Informative References..............................................8
+
+
+
+
+
+
+
+Eastlake 3rd Standards Track [Page 1]
+
+RFC 4343 DNS Case Insensitivity Clarification January 2006
+
+
+1. Introduction
+
+ The Domain Name System (DNS) is the global hierarchical replicated
+ distributed database system for Internet addressing, mail proxy, and
+ other information. Each node in the DNS tree has a name consisting
+ of zero or more labels [STD13, RFC1591, RFC2606] that are treated in
+ a case insensitive fashion. This document clarifies the meaning of
+ "case insensitive" for the DNS. This clarification updates RFCs
+ 1034, 1035 [STD13], and [RFC2181].
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+2. Case Insensitivity of DNS Labels
+
+ DNS was specified in the era of [ASCII]. DNS names were expected to
+ look like most host names or Internet email address right halves (the
+ part after the at-sign, "@") or to be numeric, as in the in-addr.arpa
+ part of the DNS name space. For example,
+
+ foo.example.net.
+ aol.com.
+ www.gnu.ai.mit.edu.
+ or 69.2.0.192.in-addr.arpa.
+
+ Case-varied alternatives to the above [RFC3092] would be DNS names
+ like
+
+ Foo.ExamplE.net.
+ AOL.COM.
+ WWW.gnu.AI.mit.EDU.
+ or 69.2.0.192.in-ADDR.ARPA.
+
+ However, the individual octets of which DNS names consist are not
+ limited to valid ASCII character codes. They are 8-bit bytes, and
+ all values are allowed. Many applications, however, interpret them
+ as ASCII characters.
+
+2.1. Escaping Unusual DNS Label Octets
+
+ In Master Files [STD13] and other human-readable and -writable ASCII
+ contexts, an escape is needed for the byte value for period (0x2E,
+ ".") and all octet values outside of the inclusive range from 0x21
+ ("!") to 0x7E ("~"). That is to say, 0x2E and all octet values in
+ the two inclusive ranges from 0x00 to 0x20 and from 0x7F to 0xFF.
+
+
+
+
+
+Eastlake 3rd Standards Track [Page 2]
+
+RFC 4343 DNS Case Insensitivity Clarification January 2006
+
+
+ One typographic convention for octets that do not correspond to an
+ ASCII printing graphic is to use a back-slash followed by the value
+ of the octet as an unsigned integer represented by exactly three
+ decimal digits.
+
+ The same convention can be used for printing ASCII characters so that
+ they will be treated as a normal label character. This includes the
+ back-slash character used in this convention itself, which can be
+ expressed as \092 or \\, and the special label separator period
+ ("."), which can be expressed as and \046 or \. It is advisable to
+ avoid using a backslash to quote an immediately following non-
+ printing ASCII character code to avoid implementation difficulties.
+
+ A back-slash followed by only one or two decimal digits is undefined.
+ A back-slash followed by four decimal digits produces two octets, the
+ first octet having the value of the first three digits considered as
+ a decimal number, and the second octet being the character code for
+ the fourth decimal digit.
+
+2.2. Example Labels with Escapes
+
+ The first example below shows embedded spaces and a period (".")
+ within a label. The second one shows a 5-octet label where the
+ second octet has all bits zero, the third is a backslash, and the
+ fourth octet has all bits one.
+
+ Donald\032E\.\032Eastlake\0323rd.example.
+ and a\000\\\255z.example.
+
+3. Name Lookup, Label Types, and CLASS
+
+ According to the original DNS design decision, comparisons on name
+ lookup for DNS queries should be case insensitive [STD13]. That is
+ to say, a lookup string octet with a value in the inclusive range
+ from 0x41 to 0x5A, the uppercase ASCII letters, MUST match the
+ identical value and also match the corresponding value in the
+ inclusive range from 0x61 to 0x7A, the lowercase ASCII letters. A
+ lookup string octet with a lowercase ASCII letter value MUST
+ similarly match the identical value and also match the corresponding
+ value in the uppercase ASCII letter range.
+
+ (Historical note: The terms "uppercase" and "lowercase" were invented
+ after movable type. The terms originally referred to the two font
+ trays for storing, in partitioned areas, the different physical type
+ elements. Before movable type, the nearest equivalent terms were
+ "majuscule" and "minuscule".)
+
+
+
+
+
+Eastlake 3rd Standards Track [Page 3]
+
+RFC 4343 DNS Case Insensitivity Clarification January 2006
+
+
+ One way to implement this rule would be to subtract 0x20 from all
+ octets in the inclusive range from 0x61 to 0x7A before comparing
+ octets. Such an operation is commonly known as "case folding", but
+ implementation via case folding is not required. Note that the DNS
+ case insensitivity does NOT correspond to the case folding specified
+ in [ISO-8859-1] or [ISO-8859-2]. For example, the octets 0xDD (\221)
+ and 0xFD (\253) do NOT match, although in other contexts, where they
+ are interpreted as the upper- and lower-case version of "Y" with an
+ acute accent, they might.
+
+3.1. Original DNS Label Types
+
+ DNS labels in wire-encoded names have a type associated with them.
+ The original DNS standard [STD13] had only two types: ASCII labels,
+ with a length from zero to 63 octets, and indirect (or compression)
+ labels, which consist of an offset pointer to a name location
+ elsewhere in the wire encoding on a DNS message. (The ASCII label of
+ length zero is reserved for use as the name of the root node of the
+ name tree.) ASCII labels follow the ASCII case conventions described
+ herein and, as stated above, can actually contain arbitrary byte
+ values. Indirect labels are, in effect, replaced by the name to
+ which they point, which is then treated with the case insensitivity
+ rules in this document.
+
+3.2. Extended Label Type Case Insensitivity Considerations
+
+ DNS was extended by [RFC2671] so that additional label type numbers
+ would be available. (The only such type defined so far is the BINARY
+ type [RFC2673], which is now Experimental [RFC3363].)
+
+ The ASCII case insensitivity conventions only apply to ASCII labels;
+ that is to say, label type 0x0, whether appearing directly or invoked
+ by indirect labels.
+
+3.3. CLASS Case Insensitivity Considerations
+
+ As described in [STD13] and [RFC2929], DNS has an additional axis for
+ data location called CLASS. The only CLASS in global use at this
+ time is the "IN" (Internet) CLASS.
+
+ The handling of DNS label case is not CLASS dependent. With the
+ original design of DNS, it was intended that a recursive DNS resolver
+ be able to handle new CLASSes that were unknown at the time of its
+ implementation. This requires uniform handling of label case
+ insensitivity. Should it become desirable, for example, to allocate
+ a CLASS with "case sensitive ASCII labels", it would be necessary to
+ allocate a new label type for these labels.
+
+
+
+
+Eastlake 3rd Standards Track [Page 4]
+
+RFC 4343 DNS Case Insensitivity Clarification January 2006
+
+
+4. Case on Input and Output
+
+ While ASCII label comparisons are case insensitive, [STD13] says case
+ MUST be preserved on output and preserved when convenient on input.
+ However, this means less than it would appear, since the preservation
+ of case on output is NOT required when output is optimized by the use
+ of indirect labels, as explained below.
+
+4.1. DNS Output Case Preservation
+
+ [STD13] views the DNS namespace as a node tree. ASCII output is as
+ if a name were marshaled by taking the label on the node whose name
+ is to be output, converting it to a typographically encoded ASCII
+ string, walking up the tree outputting each label encountered, and
+ preceding all labels but the first with a period ("."). Wire output
+ follows the same sequence, but each label is wire encoded, and no
+ periods are inserted. No "case conversion" or "case folding" is done
+ during such output operations, thus "preserving" case. However, to
+ optimize output, indirect labels may be used to point to names
+ elsewhere in the DNS answer. In determining whether the name to be
+ pointed to (for example, the QNAME) is the "same" as the remainder of
+ the name being optimized, the case insensitive comparison specified
+ above is done. Thus, such optimization may easily destroy the output
+ preservation of case. This type of optimization is commonly called
+ "name compression".
+
+4.2. DNS Input Case Preservation
+
+ Originally, DNS data came from an ASCII Master File as defined in
+ [STD13] or a zone transfer. DNS Dynamic update and incremental zone
+ transfers [RFC1995] have been added as a source of DNS data [RFC2136,
+ RFC3007]. When a node in the DNS name tree is created by any of such
+ inputs, no case conversion is done. Thus, the case of ASCII labels
+ is preserved if they are for nodes being created. However, when a
+ name label is input for a node that already exists in DNS data being
+ held, the situation is more complex. Implementations are free to
+ retain the case first loaded for such a label, to allow new input to
+ override the old case, or even to maintain separate copies preserving
+ the input case.
+
+ For example, if data with owner name "foo.bar.example" [RFC3092] is
+ loaded and then later data with owner name "xyz.BAR.example" is
+ input, the name of the label on the "bar.example" node (i.e., "bar")
+ might or might not be changed to "BAR" in the DNS stored data. Thus,
+ later retrieval of data stored under "xyz.bar.example" in this case
+ can use "xyz.BAR.example" in all returned data, use "xyz.bar.example"
+ in all returned data, or even, when more than one RR is being
+ returned, use a mixture of these two capitalizations. This last case
+
+
+
+Eastlake 3rd Standards Track [Page 5]
+
+RFC 4343 DNS Case Insensitivity Clarification January 2006
+
+
+ is unlikely, as optimization of answer length through indirect labels
+ tends to cause only one copy of the name tail ("bar.example" or
+ "BAR.example") to be used for all returned RRs. Note that none of
+ this has any effect on the number or completeness of the RR set
+ returned, only on the case of the names in the RR set returned.
+
+ The same considerations apply when inputting multiple data records
+ with owner names differing only in case. For example, if an "A"
+ record is the first resource record stored under owner name
+ "xyz.BAR.example" and then a second "A" record is stored under
+ "XYZ.BAR.example", the second MAY be stored with the first (lower
+ case initial label) name, the second MAY override the first so that
+ only an uppercase initial label is retained, or both capitalizations
+ MAY be kept in the DNS stored data. In any case, a retrieval with
+ either capitalization will retrieve all RRs with either
+ capitalization.
+
+ Note that the order of insertion into a server database of the DNS
+ name tree nodes that appear in a Master File is not defined so that
+ the results of inconsistent capitalization in a Master File are
+ unpredictable output capitalization.
+
+5. Internationalized Domain Names
+
+ A scheme has been adopted for "internationalized domain names" and
+ "internationalized labels" as described in [RFC3490, RFC3454,
+ RFC3491, and RFC3492]. It makes most of [UNICODE] available through
+ a separate application level transformation from internationalized
+ domain name to DNS domain name and from DNS domain name to
+ internationalized domain name. Any case insensitivity that
+ internationalized domain names and labels have varies depending on
+ the script and is handled entirely as part of the transformation
+ described in [RFC3454] and [RFC3491], which should be seen for
+ further details. This is not a part of the DNS as standardized in
+ STD 13.
+
+6. Security Considerations
+
+ The equivalence of certain DNS label types with case differences, as
+ clarified in this document, can lead to security problems. For
+ example, a user could be confused by believing that two domain names
+ differing only in case were actually different names.
+
+ Furthermore, a domain name may be used in contexts other than the
+ DNS. It could be used as a case sensitive index into some database
+ or file system. Or it could be interpreted as binary data by some
+ integrity or authentication code system. These problems can usually
+ be handled by using a standardized or "canonical" form of the DNS
+
+
+
+Eastlake 3rd Standards Track [Page 6]
+
+RFC 4343 DNS Case Insensitivity Clarification January 2006
+
+
+ ASCII type labels; that is, always mapping the ASCII letter value
+ octets in ASCII labels to some specific pre-chosen case, either
+ uppercase or lower case. An example of a canonical form for domain
+ names (and also a canonical ordering for them) appears in Section 6
+ of [RFC4034]. See also [RFC3597].
+
+ Finally, a non-DNS name may be stored into DNS with the false
+ expectation that case will always be preserved. For example,
+ although this would be quite rare, on a system with case sensitive
+ email address local parts, an attempt to store two Responsible Person
+ (RP) [RFC1183] records that differed only in case would probably
+ produce unexpected results that might have security implications.
+ That is because the entire email address, including the possibly case
+ sensitive local or left-hand part, is encoded into a DNS name in a
+ readable fashion where the case of some letters might be changed on
+ output as described above.
+
+7. Acknowledgements
+
+ The contributions to this document by Rob Austein, Olafur
+ Gudmundsson, Daniel J. Anderson, Alan Barrett, Marc Blanchet, Dana,
+ Andreas Gustafsson, Andrew Main, Thomas Narten, and Scott Seligman
+ are gratefully acknowledged.
+
+Normative References
+
+ [ASCII] ANSI, "USA Standard Code for Information Interchange",
+ X3.4, American National Standards Institute: New York,
+ 1968.
+
+ [RFC1995] Ohta, M., "Incremental Zone Transfer in DNS", RFC 1995,
+ August 1996.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2136] Vixie, P., Thomson, S., Rekhter, Y., and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS
+ UPDATE)", RFC 2136, April 1997.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC3007] Wellington, B., "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+
+
+
+
+
+Eastlake 3rd Standards Track [Page 7]
+
+RFC 4343 DNS Case Insensitivity Clarification January 2006
+
+
+ [RFC3597] Gustafsson, A., "Handling of Unknown DNS Resource Record
+ (RR) Types", RFC 3597, September 2003.
+
+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D., and S.
+ Rose, "Resource Records for the DNS Security
+ Extensions", RFC 4034, March 2005.
+
+ [STD13] Mockapetris, P., "Domain names - concepts and
+ facilities", STD 13, RFC 1034, November 1987.
+
+ Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+Informative References
+
+ [ISO-8859-1] International Standards Organization, Standard for
+ Character Encodings, Latin-1.
+
+ [ISO-8859-2] International Standards Organization, Standard for
+ Character Encodings, Latin-2.
+
+ [RFC1183] Everhart, C., Mamakos, L., Ullmann, R., and P.
+ Mockapetris, "New DNS RR Definitions", RFC 1183, October
+ 1990.
+
+ [RFC1591] Postel, J., "Domain Name System Structure and
+ Delegation", RFC 1591, March 1994.
+
+ [RFC2606] Eastlake 3rd, D. and A. Panitz, "Reserved Top Level DNS
+ Names", BCP 32, RFC 2606, June 1999.
+
+ [RFC2929] Eastlake 3rd, D., Brunner-Williams, E., and B. Manning,
+ "Domain Name System (DNS) IANA Considerations", BCP 42,
+ RFC 2929, September 2000.
+
+ [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC
+ 2671, August 1999.
+
+ [RFC2673] Crawford, M., "Binary Labels in the Domain Name System",
+ RFC 2673, August 1999.
+
+ [RFC3092] Eastlake 3rd, D., Manros, C., and E. Raymond, "Etymology
+ of "Foo"", RFC 3092, 1 April 2001.
+
+ [RFC3363] Bush, R., Durand, A., Fink, B., Gudmundsson, O., and T.
+ Hain, "Representing Internet Protocol version 6 (IPv6)
+ Addresses in the Domain Name System (DNS)", RFC 3363,
+ August 2002.
+
+
+
+Eastlake 3rd Standards Track [Page 8]
+
+RFC 4343 DNS Case Insensitivity Clarification January 2006
+
+
+ [RFC3454] Hoffman, P. and M. Blanchet, "Preparation of
+ Internationalized Strings ("stringprep")", RFC 3454,
+ December 2002.
+
+ [RFC3490] Faltstrom, P., Hoffman, P., and A. Costello,
+ "Internationalizing Domain Names in Applications
+ (IDNA)", RFC 3490, March 2003.
+
+ [RFC3491] Hoffman, P. and M. Blanchet, "Nameprep: A Stringprep
+ Profile for Internationalized Domain Names (IDN)", RFC
+ 3491, March 2003.
+
+ [RFC3492] Costello, A., "Punycode: A Bootstring encoding of
+ Unicode for Internationalized Domain Names in
+ Applications (IDNA)", RFC 3492, March 2003.
+
+ [UNICODE] The Unicode Consortium, "The Unicode Standard",
+ <http://www.unicode.org/unicode/standard/standard.html>.
+
+Author's Address
+
+ Donald E. Eastlake 3rd
+ Motorola Laboratories
+ 155 Beaver Street
+ Milford, MA 01757 USA
+
+ Phone: +1 508-786-7554 (w)
+ EMail: Donald.Eastlake@motorola.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake 3rd Standards Track [Page 9]
+
+RFC 4343 DNS Case Insensitivity Clarification January 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Eastlake 3rd Standards Track [Page 10]
+
diff --git a/doc/rfc/rfc4367.txt b/doc/rfc/rfc4367.txt
new file mode 100644
index 0000000..f066b64
--- /dev/null
+++ b/doc/rfc/rfc4367.txt
@@ -0,0 +1,955 @@
+
+
+
+
+
+
+Network Working Group J. Rosenberg, Ed.
+Request for Comments: 4367 IAB
+Category: Informational February 2006
+
+
+ What's in a Name: False Assumptions about DNS Names
+
+Status of This Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ The Domain Name System (DNS) provides an essential service on the
+ Internet, mapping structured names to a variety of data, usually IP
+ addresses. These names appear in email addresses, Uniform Resource
+ Identifiers (URIs), and other application-layer identifiers that are
+ often rendered to human users. Because of this, there has been a
+ strong demand to acquire names that have significance to people,
+ through equivalence to registered trademarks, company names, types of
+ services, and so on. There is a danger in this trend; the humans and
+ automata that consume and use such names will associate specific
+ semantics with some names and thereby make assumptions about the
+ services that are, or should be, provided by the hosts associated
+ with the names. Those assumptions can often be false, resulting in a
+ variety of failure conditions. This document discusses this problem
+ in more detail and makes recommendations on how it can be avoided.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Rosenberg Informational [Page 1]
+
+RFC 4367 Name Assumptions February 2006
+
+
+Table of Contents
+
+ 1. Introduction ....................................................2
+ 2. Target Audience .................................................4
+ 3. Modeling Usage of the DNS .......................................4
+ 4. Possible Assumptions ............................................5
+ 4.1. By the User ................................................5
+ 4.2. By the Client ..............................................6
+ 4.3. By the Server ..............................................7
+ 5. Consequences of False Assumptions ...............................8
+ 6. Reasons Why the Assumptions Can Be False ........................9
+ 6.1. Evolution ..................................................9
+ 6.2. Leakage ...................................................10
+ 6.3. Sub-Delegation ............................................10
+ 6.4. Mobility ..................................................12
+ 6.5. Human Error ...............................................12
+ 7. Recommendations ................................................12
+ 8. A Note on RFC 2219 and RFC 2782 ................................13
+ 9. Security Considerations ........................................14
+ 10. Acknowledgements ..............................................14
+ 11. IAB Members ...................................................14
+ 12. Informative References ........................................15
+
+1. Introduction
+
+ The Domain Name System (DNS) [1] provides an essential service on the
+ Internet, mapping structured names to a variety of different types of
+ data. Most often it is used to obtain the IP address of a host
+ associated with that name [2] [1] [3]. However, it can be used to
+ obtain other information, and proposals have been made for nearly
+ everything, including geographic information [4].
+
+ Domain names are most often used in identifiers used by application
+ protocols. The most well known include email addresses and URIs,
+ such as the HTTP URL [5], Real Time Streaming Protocol (RTSP) URL
+ [6], and SIP URI [7]. These identifiers are ubiquitous, appearing on
+ business cards, web pages, street signs, and so on. Because of this,
+ there has been a strong demand to acquire domain names that have
+ significance to people through equivalence to registered trademarks,
+ company names, types of services, and so on. Such identifiers serve
+ many business purposes, including extension of brand, advertising,
+ and so on.
+
+ People often make assumptions about the type of service that is or
+ should be provided by a host associated with that name, based on
+ their expectations and understanding of what the name implies. This,
+ in turn, triggers attempts by organizations to register domain names
+ based on that presumed user expectation. Examples of this are the
+
+
+
+Rosenberg Informational [Page 2]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ various proposals for a Top-Level Domain (TLD) that could be
+ associated with adult content [8], the requests for creation of TLDs
+ associated with mobile devices and services, and even phishing
+ attacks.
+
+ When these assumptions are codified into the behavior of an
+ automaton, such as an application client or server, as a result of
+ implementor choice, management directive, or domain owner policy, the
+ overall system can fail in various ways. This document describes a
+ number of typical ways in which these assumptions can be codified,
+ how they can be wrong, the consequences of those mistakes, and the
+ recommended ways in which they can be avoided.
+
+ Section 4 describes some of the possible assumptions that clients,
+ servers, and people can make about a domain name. In this context,
+ an "assumption" is defined as any behavior that is expected when
+ accessing a service at a domain name, even though the behavior is not
+ explicitly codified in protocol specifications. Frequently, these
+ assumptions involve ignoring parts of a specification based on an
+ assumption that the client or server is deployed in an environment
+ that is more rigid than the specification allows. Section 5
+ overviews some of the consequences of these false assumptions.
+ Generally speaking, these consequences can include a variety of
+ different interoperability failures, user experience failures, and
+ system failures. Section 6 discusses why these assumptions can be
+ false from the very beginning or become false at some point in the
+ future. Most commonly, they become false because the environment
+ changes in unexpected ways over time, and what was a valid assumption
+ before, no longer is. Other times, the assumptions prove wrong
+ because they were based on the belief that a specific community of
+ clients and servers was participating, and an element outside of that
+ community began participating.
+
+ Section 7 then provides some recommendations. These recommendations
+ encapsulate some of the engineering mantras that have been at the
+ root of Internet protocol design for decades. These include:
+
+ Follow the specifications.
+
+ Use the capability negotiation techniques provided in the
+ protocols.
+
+ Be liberal in what you accept, and conservative in what you send.
+ [18]
+
+ Overall, automata should not change their behavior within a protocol
+ based on the domain name, or some component of the domain name, of
+ the host they are communicating with.
+
+
+
+Rosenberg Informational [Page 3]
+
+RFC 4367 Name Assumptions February 2006
+
+
+2. Target Audience
+
+ This document has several audiences. Firstly, it is aimed at
+ implementors who ultimately develop the software that make the false
+ assumptions that are the subject of this document. The
+ recommendations described here are meant to reinforce the engineering
+ guidelines that are often understood by implementors, but frequently
+ forgotten as deadlines near and pressures mount.
+
+ The document is also aimed at technology managers, who often develop
+ the requirements that lead to these false assumptions. For them,
+ this document serves as a vehicle for emphasizing the importance of
+ not taking shortcuts in the scope of applicability of a project.
+
+ Finally, this document is aimed at domain name policy makers and
+ administrators. For them, it points out the perils in establishing
+ domain policies that get codified into the operation of applications
+ running within that domain.
+
+3. Modeling Usage of the DNS
+
+
+ +--------+
+ | |
+ | |
+ | DNS |
+ |Service |
+ | |
+ +--------+
+ ^ |
+ | |
+ | |
+ | |
+ /--\ | |
+ | | | V
+ | | +--------+ +--------+
+ \--/ | | | |
+ | | | | |
+ ---+--- | Client |-------------------->| Server |
+ | | | | |
+ | | | | |
+ /\ +--------+ +--------+
+ / \
+ / \
+
+ User
+ Figure 1
+
+
+
+
+Rosenberg Informational [Page 4]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ Figure 1 shows a simple conceptual model of how the DNS is used by
+ applications. A user of the application obtains an identifier for
+ particular content or service it wishes to obtain. This identifier
+ is often a URL or URI that contains a domain name. The user enters
+ this identifier into its client application (for example, by typing
+ in the URL in a web browser window). The client is the automaton (a
+ software and/or hardware system) that contacts a server for that
+ application in order to provide service to the user. To do that, it
+ contacts a DNS server to resolve the domain name in the identifier to
+ an IP address. It then contacts the server at that IP address. This
+ simple model applies to application protocols such as HTTP [5], SIP
+ [7], RTSP [6], and SMTP [9].
+
+ >From this model, it is clear that three entities in the system can
+ potentially make false assumptions about the service provided by the
+ server. The human user may form expectations relating to the content
+ of the service based on a parsing of the host name from which the
+ content originated. The server might assume that the client
+ connecting to it supports protocols that it does not, can process
+ content that it cannot, or has capabilities that it does not.
+ Similarly, the client might assume that the server supports
+ protocols, content, or capabilities that it does not. Furthermore,
+ applications can potentially contain a multiplicity of humans,
+ clients, and servers, all of which can independently make these false
+ assumptions.
+
+4. Possible Assumptions
+
+ For each of the three elements, there are many types of false
+ assumptions that can be made.
+
+4.1. By the User
+
+ The set of possible assumptions here is nearly boundless. Users
+ might assume that an HTTP URL that looks like a company name maps to
+ a server run by that company. They might assume that an email from a
+ email address in the .gov TLD is actually from a government employee.
+ They might assume that the content obtained from a web server within
+ a TLD labeled as containing adult materials (for example, .sex)
+ actually contains adult content [8]. These assumptions are
+ unavoidable, may all be false, and are not the focus of this
+ document.
+
+
+
+
+
+
+
+
+
+Rosenberg Informational [Page 5]
+
+RFC 4367 Name Assumptions February 2006
+
+
+4.2. By the Client
+
+ Even though the client is an automaton, it can make some of the same
+ assumptions that a human user might make. For example, many clients
+ assume that any host with a hostname that begins with "www" is a web
+ server, even though this assumption may be false.
+
+ In addition, the client concerns itself with the protocols needed to
+ communicate with the server. As a result, it might make assumptions
+ about the operation of the protocols for communicating with the
+ server. These assumptions manifest themselves in an implementation
+ when a standardized protocol negotiation technique defined by the
+ protocol is ignored, and instead, some kind of rule is coded into the
+ software that comes to its own conclusion about what the negotiation
+ would have determined. The result is often a loss of
+ interoperability, degradation in reliability, and worsening of user
+ experience.
+
+ Authentication Algorithm: Though a protocol might support a
+ multiplicity of authentication techniques, a client might assume
+ that a server always supports one that is only optional according
+ to the protocol. For example, a SIP client contacting a SIP
+ server in a domain that is apparently used to identify mobile
+ devices (for example, www.example.cellular) might assume that the
+ server supports the optional Authentication and Key Agreement
+ (AKA) digest technique [10], just because of the domain name that
+ was used to access the server. As another example, a web client
+ might assume that a server with the name https.example.com
+ supports HTTP over Transport Layer Security (TLS) [16].
+
+ Data Formats: Though a protocol might allow a multiplicity of data
+ formats to be sent from the server to the client, the client might
+ assume a specific one, rather than using the content labeling and
+ negotiation capabilities of the underlying protocol. For example,
+ an RTSP client might assume that all audio content delivered to it
+ from media.example.cellular uses a low-bandwidth codec. As
+ another example, a mail client might assume that the contents of
+ messages it retrieves from a mail server at mail.example.cellular
+ are always text, instead of checking the MIME headers [11] in the
+ message in order to determine the actual content type.
+
+ Protocol Extensions: A client may attempt an operation on the server
+ that requires the server to support an optional protocol
+ extension. However, rather than implementing the necessary
+ fallback logic, the client may falsely assume that the extension
+ is supported. As an example, a SIP client that requires reliable
+ provisional responses to its request (RFC 3262 [17]) might assume
+ that this extension is supported on servers in the domain
+
+
+
+Rosenberg Informational [Page 6]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ sip.example.telecom. Furthermore, the client would not implement
+ the fallback behavior defined in RFC 3262, since it would assume
+ that all servers it will communicate with are in this domain and
+ that all therefore support this extension. However, if the
+ assumptions prove wrong, the client is unable to make any phone
+ calls.
+
+ Languages: A client may support facilities for processing text
+ content differently depending on the language of the text. Rather
+ than determining the language from markers in the message from the
+ server, the client might assume a language based on the domain
+ name. This assumption can easily be wrong. For example, a client
+ might assume that any text in a web page retrieved from a server
+ within the .de country code TLD (ccTLD) is in German, and attempt
+ a translation to Finnish. This would fail dramatically if the
+ text was actually in French. Unfortunately, this client behavior
+ is sometimes exhibited because the server has not properly labeled
+ the language of the content in the first place, often because the
+ server assumed such a labeling was not needed. This is an example
+ of how these false assumptions can create vicious cycles.
+
+4.3. By the Server
+
+ The server, like the client, is an automaton. Let us consider one
+ servicing a particular domain -- www.company.cellular, for example.
+ It might assume that all clients connecting to this domain support
+ particular capabilities, rather than using the underlying protocol to
+ make this determination. Some examples include:
+
+ Authentication Algorithm: The server can assume that a client
+ supports a particular, optional, authentication technique, and it
+ therefore does not support the mandatory one.
+
+ Language: The server can serve content in a particular language,
+ based on an assumption that clients accessing the domain speak a
+ particular language, or based on an assumption that clients coming
+ from a particular IP address speak a certain language.
+
+ Data Formats: The server can assume that the client supports a
+ particular set of MIME types and is only capable of sending ones
+ within that set. When it generates content in a protocol
+ response, it ignores any content negotiation headers that were
+ present in the request. For example, a web server might ignore
+ the Accept HTTP header field and send a specific image format.
+
+
+
+
+
+
+
+Rosenberg Informational [Page 7]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ Protocol Extensions: The server might assume that the client supports
+ a particular optional protocol extension, and so it does not
+ support the fallback behavior necessary in the case where the
+ client does not.
+
+ Client Characteristics: The server might assume certain things about
+ the physical characteristics of its clients, such as memory
+ footprint, processing power, screen sizes, screen colors, pointing
+ devices, and so on. Based on these assumptions, it might choose
+ specific behaviors when processing a request. For example, a web
+ server might always assume that clients connect through cell
+ phones, and therefore return content that lacks images and is
+ tuned for such devices.
+
+5. Consequences of False Assumptions
+
+ There are numerous negative outcomes that can arise from the various
+ false assumptions that users, servers, and clients can make. These
+ include:
+
+ Interoperability Failure: In these cases, the client or server
+ assumed some kind of protocol operation, and this assumption was
+ wrong. The result is that the two are unable to communicate, and
+ the user receives some kind of an error. This represents a total
+ interoperability failure, manifesting itself as a lack of service
+ to users of the system. Unfortunately, this kind of failure
+ persists. Repeated attempts over time by the client to access the
+ service will fail. Only a change in the server or client software
+ can fix this problem.
+
+ System Failure: In these cases, the client or server misinterpreted a
+ protocol operation, and this misinterpretation was serious enough
+ to uncover a bug in the implementation. The bug causes a system
+ crash or some kind of outage, either transient or permanent (until
+ user reset). If this failure occurs in a server, not only will
+ the connecting client lose service, but other clients attempting
+ to connect will not get service. As an example, if a web server
+ assumes that content passed to it from a client (created, for
+ example, by a digital camera) is of a particular content type, and
+ it always passes image content to a codec for decompression prior
+ to storage, the codec might crash when it unexpectedly receives an
+ image compressed in a different format. Of course, it might crash
+ even if the Content-Type was correct, but the compressed bitstream
+ was invalid. False assumptions merely introduce additional
+ failure cases.
+
+
+
+
+
+
+Rosenberg Informational [Page 8]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ Poor User Experience: In these cases, the client and server
+ communicate, but the user receives a diminished user experience.
+ For example, if a client on a PC connects to a web site that
+ provides content for mobile devices, the content may be
+ underwhelming when viewed on the PC. Or, a client accessing a
+ streaming media service may receive content of very low bitrate,
+ even though the client supported better codecs. Indeed, if a user
+ wishes to access content from both a cellular device and a PC
+ using a shared address book (that is, an address book shared
+ across multiple devices), the user would need two entries in that
+ address book, and would need to use the right one from the right
+ device. This is a poor user experience.
+
+ Degraded Security: In these cases, a weaker security mechanism is
+ used than the one that ought to have been used. As an example, a
+ server in a domain might assume that it is only contacted by
+ clients with a limited set of authentication algorithms, even
+ though the clients have been recently upgraded to support a
+ stronger set.
+
+6. Reasons Why the Assumptions Can Be False
+
+ Assumptions made by clients and servers about the operation of
+ protocols when contacting a particular domain are brittle, and can be
+ wrong for many reasons. On the server side, many of the assumptions
+ are based on the notion that a domain name will only be given to, or
+ used by, a restricted set of clients. If the holder of the domain
+ name assumes something about those clients, and can assume that only
+ those clients use the domain name, then it can configure or program
+ the server to operate specifically for those clients. Both parts of
+ this assumption can be wrong, as discussed in more detail below.
+
+ On the client side, the notion is similar, being based on the
+ assumption that a server within a particular domain will provide a
+ specific type of service. Sub-delegation and evolution, both
+ discussed below, can make these assumptions wrong.
+
+6.1. Evolution
+
+ The Internet and the devices that access it are constantly evolving,
+ often at a rapid pace. Unfortunately, there is a tendency to build
+ for the here and now, and then worry about the future at a later
+ time. Many of the assumptions above are predicated on
+ characteristics of today's clients and servers. Support for specific
+ protocols, authentication techniques, or content are based on today's
+ standards and today's devices. Even though they may, for the most
+ part, be true, they won't always be. An excellent example is mobile
+ devices. A server servicing a domain accessed by mobile devices
+
+
+
+Rosenberg Informational [Page 9]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ might try to make assumptions about the protocols, protocol
+ extensions, security mechanisms, screen sizes, or processor power of
+ such devices. However, all of these characteristics can and will
+ change over time.
+
+ When they do change, the change is usually evolutionary. The result
+ is that the assumptions remain valid in some cases, but not in
+ others. It is difficult to fix such systems, since it requires the
+ server to detect what type of client is connecting, and what its
+ capabilities are. Unless the system is built and deployed with these
+ capability negotiation techniques built in to begin with, such
+ detection can be extremely difficult. In fact, fixing it will often
+ require the addition of such capability negotiation features that, if
+ they had been in place and used to begin with, would have avoided the
+ problem altogether.
+
+6.2. Leakage
+
+ Servers also make assumptions because of the belief that they will
+ only be accessed by specific clients, and in particular, those that
+ are configured or provisioned to use the domain name. In essence,
+ there is an assumption of community -- that a specific community
+ knows and uses the domain name, while others outside of the community
+ do not.
+
+ The problem is that this notion of community is a false one. The
+ Internet is global. The DNS is global. There is no technical
+ barrier that separates those inside of the community from those
+ outside. The ease with which information propagates across the
+ Internet makes it extremely likely that such domain names will
+ eventually find their way into clients outside of the presumed
+ community. The ubiquitous presence of domain names in various URI
+ formats, coupled with the ease of conveyance of URIs, makes such
+ leakage merely a matter of time. Furthermore, since the DNS is
+ global, and since it can only have one root [12], it becomes possible
+ for clients outside of the community to search and find and use such
+ "special" domain names.
+
+ Indeed, this leakage is a strength of the Internet architecture, not
+ a weakness. It enables global access to services from any client
+ with a connection to the Internet. That, in turn, allows for rapid
+ growth in the number of customers for any particular service.
+
+6.3. Sub-Delegation
+
+ Clients and users make assumptions about domains because of the
+ notion that there is some kind of centralized control that can
+ enforce those assumptions. However, the DNS is not centralized; it
+
+
+
+Rosenberg Informational [Page 10]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ is distributed. If a domain doesn't delegate its sub-domains and has
+ its records within a single zone, it is possible to maintain a
+ centralized policy about operation of its domain. However, once a
+ domain gets sufficiently large that the domain administrators begin
+ to delegate sub-domains to other authorities, it becomes increasingly
+ difficult to maintain any kind of central control on the nature of
+ the service provided in each sub-domain.
+
+ Similarly, the usage of domain names with human semantic connotation
+ tends to lead to a registration of multiple domains in which a
+ particular service is to run. As an example, a service provider with
+ the name "example" might register and set up its services in
+ "example.com", "example.net", and generally example.foo for each foo
+ that is a valid TLD. This, like sub-delegation, results in a growth
+ in the number of domains over which it is difficult to maintain
+ centralized control.
+
+ Not that it is not possible, since there are many examples of
+ successful administration of policies across sub-domains many levels
+ deep. However, it takes an increasing amount of effort to ensure
+ this result, as it requires human intervention and the creation of
+ process and procedure. Automated validation of adherence to policies
+ is very difficult to do, as there is no way to automatically verify
+ many policies that might be put into place.
+
+ A less costly process for providing centralized management of
+ policies is to just hope that any centralized policies are being
+ followed, and then wait for complaints or perform random audits.
+ Those approaches have many problems.
+
+ The invalidation of assumptions due to sub-delegation is discussed in
+ further detail in Section 4.1.3 of [8] and in Section 3.3 of [20].
+
+ As a result of the fragility of policy continuity across sub-
+ delegations, if a client or user assumes some kind of property
+ associated with a TLD (such as ".wifi"), it becomes increasingly more
+ likely with the number of sub-domains that this property will not
+ exist in a server identified by a particular name. For example, in
+ "store.chain.company.provider.wifi", there may be four levels of
+ delegation from ".wifi", making it quite likely that, unless the
+ holder of ".wifi" is working diligently, the properties that the
+ holder of ".wifi" wishes to enforce are not present. These
+ properties may not be present due to human error or due to a willful
+ decision not to adhere to them.
+
+
+
+
+
+
+
+Rosenberg Informational [Page 11]
+
+RFC 4367 Name Assumptions February 2006
+
+
+6.4. Mobility
+
+ One of the primary value propositions of a hostname as an identifier
+ is its persistence. A client can change IP addresses, yet still
+ retain a persistent identifier used by other hosts to reach it.
+ Because their value derives from their persistence, hostnames tend to
+ move with a host not just as it changes IP addresses, but as it
+ changes access network providers and technologies. For this reason,
+ assumptions made about a host based on the presumed access network
+ corresponding to that hostname tend to be wrong over time. As an
+ example, a PC might normally be connected to its broadband provider,
+ and through dynamic DNS have a hostname within the domain of that
+ provider. However, one cannot assume that any host within that
+ network has access over a broadband link; the user could connect
+ their PC over a low-bandwidth wireless access network and still
+ retain its domain name.
+
+6.5. Human Error
+
+ Of course, human error can be the source of errors in any system, and
+ the same is true here. There are many examples relevant to the
+ problem under discussion.
+
+ A client implementation may make the assumption that, just because a
+ DNS SRV record exists for a particular protocol in a particular
+ domain, indicating that the service is available on some port, that
+ the service is, in fact, running there. This assumption could be
+ wrong because the SRV records haven't been updated by the system
+ administrators to reflect the services currently running. As another
+ example, a client might assume that a particular domain policy
+ applies to all sub-domains. However, a system administrator might
+ have omitted to apply the policy to servers running in one of those
+ sub-domains.
+
+7. Recommendations
+
+ Based on these problems, the clear conclusion is that clients,
+ servers, and users should not make assumptions on the nature of the
+ service provided to, or by, a domain. More specifically, however,
+ the following can be said:
+
+ Follow the specifications: When specifications define mandatory
+ baseline procedures and formats, those should be implemented and
+ supported, even if the expectation is that optional procedures
+ will most often be used. For example, if a specification mandates
+ a particular baseline authentication technique, but allows others
+ to be negotiated and used, implementations need to implement the
+ baseline authentication algorithm even if the other ones are used
+
+
+
+Rosenberg Informational [Page 12]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ most of the time. Put more simply, the behavior of the protocol
+ machinery should never change based on the domain name of the
+ host.
+
+ Use capability negotiation: Many protocols are engineered with
+ capability negotiation mechanisms. For example, a content
+ negotiation framework has been defined for protocols using MIME
+ content [13] [14] [15]. SIP allows for clients to negotiate the
+ media types used in the multimedia session, as well as protocol
+ parameters. HTTP allows for clients to negotiate the media types
+ returned in requests for content. When such features are
+ available in a protocol, client and servers should make use of
+ them rather than making assumptions about supported capabilities.
+ A corollary is that protocol designers should include such
+ mechanisms when evolution is expected in the usage of the
+ protocol.
+
+ "Be liberal in what you accept, and conservative in what you send"
+ [18]: This axiom of Internet protocol design is applicable here
+ as well. Implementations should be prepared for the full breadth
+ of what a protocol allows another entity to send, rather than be
+ limiting in what it is willing to receive.
+
+ To summarize -- there is never a need to make assumptions. Rather
+ than doing so, utilize the specifications and the negotiation
+ capabilities they provide, and the overall system will be robust and
+ interoperable.
+
+8. A Note on RFC 2219 and RFC 2782
+
+ Based on the definition of an assumption given here, the behavior
+ hinted at by records in the DNS also represents an assumption. RFC
+ 2219 [19] defines well-known aliases that can be used to construct
+ domain names for reaching various well-known services in a domain.
+ This approach was later followed by the definition of a new resource
+ record, the SRV record [2], which specifies that a particular service
+ is running on a server in a domain. Although both of these
+ mechanisms are useful as a hint that a particular service is running
+ in a domain, both of them represent assumptions that may be false.
+ However, they differ in the set of reasons why those assumptions
+ might be false.
+
+ A client that assumes that "ftp.example.com" is an FTP server may be
+ wrong because the presumed naming convention in RFC 2219 was not
+ known by, or not followed by, the owner of domain.com. With RFC
+ 2782, an SRV record for a particular service would be present only by
+ explicit choice of the domain administrator, and thus a client that
+
+
+
+
+Rosenberg Informational [Page 13]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ assumes that the corresponding host provides this service would be
+ wrong only because of human error in configuration. In this case,
+ the assumption is less likely to be wrong, but it certainly can be.
+
+ The only way to determine with certainty that a service is running on
+ a host is to initiate a connection to the port for that service, and
+ check. Implementations need to be careful not to codify any
+ behaviors that cause failures should the information provided in the
+ record actually be false. This borders on common sense for robust
+ implementations, but it is valuable to raise this point explicitly.
+
+9. Security Considerations
+
+ One of the assumptions that can be made by clients or servers is the
+ availability and usage (or lack thereof) of certain security
+ protocols and algorithms. For example, a client accessing a service
+ in a particular domain might assume a specific authentication
+ algorithm or hash function in the application protocol. It is
+ possible that, over time, weaknesses are found in such a technique,
+ requiring usage of a different mechanism. Similarly, a system might
+ start with an insecure mechanism, and then decide later on to use a
+ secure one. In either case, assumptions made on security properties
+ can result in interoperability failures, or worse yet, providing
+ service in an insecure way, even though the client asked for, and
+ thought it would get, secure service. These kinds of assumptions are
+ fundamentally unsound even if the records themselves are secured with
+ DNSSEC.
+
+10. Acknowledgements
+
+ The IAB would like to thank John Klensin, Keith Moore and Peter Koch
+ for their comments.
+
+11. IAB Members
+
+ Internet Architecture Board members at the time of writing of this
+ document are:
+
+ Bernard Aboba
+
+ Loa Andersson
+
+ Brian Carpenter
+
+ Leslie Daigle
+
+ Patrik Faltstrom
+
+
+
+
+Rosenberg Informational [Page 14]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ Bob Hinden
+
+ Kurtis Lindqvist
+
+ David Meyer
+
+ Pekka Nikander
+
+ Eric Rescorla
+
+ Pete Resnick
+
+ Jonathan Rosenberg
+
+12. Informative References
+
+ [1] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [2] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for
+ specifying the location of services (DNS SRV)", RFC 2782,
+ February 2000.
+
+ [3] Mealling, M., "Dynamic Delegation Discovery System (DDDS) Part
+ Three: The Domain Name System (DNS) Database", RFC 3403,
+ October 2002.
+
+ [4] Davis, C., Vixie, P., Goodwin, T., and I. Dickinson, "A Means
+ for Expressing Location Information in the Domain Name System",
+ RFC 1876, January 1996.
+
+ [5] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L.,
+ Leach, P., and T. Berners-Lee, "Hypertext Transfer Protocol --
+ HTTP/1.1", RFC 2616, June 1999.
+
+ [6] Schulzrinne, H., Rao, A., and R. Lanphier, "Real Time Streaming
+ Protocol (RTSP)", RFC 2326, April 1998.
+
+ [7] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A.,
+ Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP:
+ Session Initiation Protocol", RFC 3261, June 2002.
+
+ [8] Eastlake, D., ".sex Considered Dangerous", RFC 3675,
+ February 2004.
+
+ [9] Klensin, J., "Simple Mail Transfer Protocol", RFC 2821,
+ April 2001.
+
+
+
+
+Rosenberg Informational [Page 15]
+
+RFC 4367 Name Assumptions February 2006
+
+
+ [10] Niemi, A., Arkko, J., and V. Torvinen, "Hypertext Transfer
+ Protocol (HTTP) Digest Authentication Using Authentication and
+ Key Agreement (AKA)", RFC 3310, September 2002.
+
+ [11] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message Bodies",
+ RFC 2045, November 1996.
+
+ [12] Internet Architecture Board, "IAB Technical Comment on the
+ Unique DNS Root", RFC 2826, May 2000.
+
+ [13] Klyne, G., "Indicating Media Features for MIME Content",
+ RFC 2912, September 2000.
+
+ [14] Klyne, G., "A Syntax for Describing Media Feature Sets",
+ RFC 2533, March 1999.
+
+ [15] Klyne, G., "Protocol-independent Content Negotiation
+ Framework", RFC 2703, September 1999.
+
+ [16] Rescorla, E., "HTTP Over TLS", RFC 2818, May 2000.
+
+ [17] Rosenberg, J. and H. Schulzrinne, "Reliability of Provisional
+ Responses in Session Initiation Protocol (SIP)", RFC 3262,
+ June 2002.
+
+ [18] Braden, R., "Requirements for Internet Hosts - Communication
+ Layers", STD 3, RFC 1122, October 1989.
+
+ [19] Hamilton, M. and R. Wright, "Use of DNS Aliases for Network
+ Services", BCP 17, RFC 2219, October 1997.
+
+ [20] Faltstrom, P., "Design Choices When Expanding DNS", Work in
+ Progress, June 2005.
+
+Author's Address
+
+ Jonathan Rosenberg, Editor
+ IAB
+ 600 Lanidex Plaza
+ Parsippany, NJ 07054
+ US
+
+ Phone: +1 973 952-5000
+ EMail: jdrosen@cisco.com
+ URI: http://www.jdrosen.net
+
+
+
+
+
+Rosenberg Informational [Page 16]
+
+RFC 4367 Name Assumptions February 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Rosenberg Informational [Page 17]
+
diff --git a/doc/rfc/rfc4398.txt b/doc/rfc/rfc4398.txt
new file mode 100644
index 0000000..6437436
--- /dev/null
+++ b/doc/rfc/rfc4398.txt
@@ -0,0 +1,955 @@
+
+
+
+
+
+
+Network Working Group S. Josefsson
+Request for Comments: 4398 March 2006
+Obsoletes: 2538
+Category: Standards Track
+
+
+ Storing Certificates in the Domain Name System (DNS)
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ Cryptographic public keys are frequently published, and their
+ authenticity is demonstrated by certificates. A CERT resource record
+ (RR) is defined so that such certificates and related certificate
+ revocation lists can be stored in the Domain Name System (DNS).
+
+ This document obsoletes RFC 2538.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 1]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+Table of Contents
+
+ 1. Introduction ....................................................3
+ 2. The CERT Resource Record ........................................3
+ 2.1. Certificate Type Values ....................................4
+ 2.2. Text Representation of CERT RRs ............................6
+ 2.3. X.509 OIDs .................................................6
+ 3. Appropriate Owner Names for CERT RRs ............................7
+ 3.1. Content-Based X.509 CERT RR Names ..........................8
+ 3.2. Purpose-Based X.509 CERT RR Names ..........................9
+ 3.3. Content-Based OpenPGP CERT RR Names ........................9
+ 3.4. Purpose-Based OpenPGP CERT RR Names .......................10
+ 3.5. Owner Names for IPKIX, ISPKI, IPGP, and IACPKIX ...........10
+ 4. Performance Considerations .....................................11
+ 5. Contributors ...................................................11
+ 6. Acknowledgements ...............................................11
+ 7. Security Considerations ........................................12
+ 8. IANA Considerations ............................................12
+ 9. Changes since RFC 2538 .........................................13
+ 10. References ....................................................14
+ 10.1. Normative References .....................................14
+ 10.2. Informative References ...................................15
+ Appendix A. Copying Conditions ...................................16
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 2]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+1. Introduction
+
+ Public keys are frequently published in the form of a certificate,
+ and their authenticity is commonly demonstrated by certificates and
+ related certificate revocation lists (CRLs). A certificate is a
+ binding, through a cryptographic digital signature, of a public key,
+ a validity interval and/or conditions, and identity, authorization,
+ or other information. A certificate revocation list is a list of
+ certificates that are revoked, and of incidental information, all
+ signed by the signer (issuer) of the revoked certificates. Examples
+ are X.509 certificates/CRLs in the X.500 directory system or OpenPGP
+ certificates/revocations used by OpenPGP software.
+
+ Section 2 specifies a CERT resource record (RR) for the storage of
+ certificates in the Domain Name System [1] [2].
+
+ Section 3 discusses appropriate owner names for CERT RRs.
+
+ Sections 4, 7, and 8 cover performance, security, and IANA
+ considerations, respectively.
+
+ Section 9 explains the changes in this document compared to RFC 2538.
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [3].
+
+2. The CERT Resource Record
+
+ The CERT resource record (RR) has the structure given below. Its RR
+ type code is 37.
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | type | key tag |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | algorithm | /
+ +---------------+ certificate or CRL /
+ / /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+
+ The type field is the certificate type as defined in Section 2.1
+ below.
+
+ The key tag field is the 16-bit value computed for the key embedded
+ in the certificate, using the RRSIG Key Tag algorithm described in
+ Appendix B of [12]. This field is used as an efficiency measure to
+
+
+
+Josefsson Standards Track [Page 3]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+ pick which CERT RRs may be applicable to a particular key. The key
+ tag can be calculated for the key in question, and then only CERT RRs
+ with the same key tag need to be examined. Note that two different
+ keys can have the same key tag. However, the key MUST be transformed
+ to the format it would have as the public key portion of a DNSKEY RR
+ before the key tag is computed. This is only possible if the key is
+ applicable to an algorithm and complies to limits (such as key size)
+ defined for DNS security. If it is not, the algorithm field MUST be
+ zero and the tag field is meaningless and SHOULD be zero.
+
+ The algorithm field has the same meaning as the algorithm field in
+ DNSKEY and RRSIG RRs [12], except that a zero algorithm field
+ indicates that the algorithm is unknown to a secure DNS, which may
+ simply be the result of the algorithm not having been standardized
+ for DNSSEC [11].
+
+2.1. Certificate Type Values
+
+ The following values are defined or reserved:
+
+ Value Mnemonic Certificate Type
+ ----- -------- ----------------
+ 0 Reserved
+ 1 PKIX X.509 as per PKIX
+ 2 SPKI SPKI certificate
+ 3 PGP OpenPGP packet
+ 4 IPKIX The URL of an X.509 data object
+ 5 ISPKI The URL of an SPKI certificate
+ 6 IPGP The fingerprint and URL of an OpenPGP packet
+ 7 ACPKIX Attribute Certificate
+ 8 IACPKIX The URL of an Attribute Certificate
+ 9-252 Available for IANA assignment
+ 253 URI URI private
+ 254 OID OID private
+ 255 Reserved
+ 256-65279 Available for IANA assignment
+ 65280-65534 Experimental
+ 65535 Reserved
+
+ These values represent the initial content of the IANA registry; see
+ Section 8.
+
+ The PKIX type is reserved to indicate an X.509 certificate conforming
+ to the profile defined by the IETF PKIX working group [8]. The
+ certificate section will start with a one-octet unsigned OID length
+ and then an X.500 OID indicating the nature of the remainder of the
+
+
+
+
+
+Josefsson Standards Track [Page 4]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+ certificate section (see Section 2.3, below). (NOTE: X.509
+ certificates do not include their X.500 directory-type-designating
+ OID as a prefix.)
+
+ The SPKI and ISPKI types are reserved to indicate the SPKI
+ certificate format [15], for use when the SPKI documents are moved
+ from experimental status. The format for these two CERT RR types
+ will need to be specified later.
+
+ The PGP type indicates an OpenPGP packet as described in [5] and its
+ extensions and successors. This is used to transfer public key
+ material and revocation signatures. The data is binary and MUST NOT
+ be encoded into an ASCII armor. An implementation SHOULD process
+ transferable public keys as described in Section 10.1 of [5], but it
+ MAY handle additional OpenPGP packets.
+
+ The ACPKIX type indicates an Attribute Certificate format [9].
+
+ The IPKIX and IACPKIX types indicate a URL that will serve the
+ content that would have been in the "certificate, CRL, or URL" field
+ of the corresponding type (PKIX or ACPKIX, respectively).
+
+ The IPGP type contains both an OpenPGP fingerprint for the key in
+ question, as well as a URL. The certificate portion of the IPGP CERT
+ RR is defined as a one-octet fingerprint length, followed by the
+ OpenPGP fingerprint, followed by the URL. The OpenPGP fingerprint is
+ calculated as defined in RFC 2440 [5]. A zero-length fingerprint or
+ a zero-length URL are legal, and indicate URL-only IPGP data or
+ fingerprint-only IPGP data, respectively. A zero-length fingerprint
+ and a zero-length URL are meaningless and invalid.
+
+ The IPKIX, ISPKI, IPGP, and IACPKIX types are known as "indirect".
+ These types MUST be used when the content is too large to fit in the
+ CERT RR and MAY be used at the implementer's discretion. They SHOULD
+ NOT be used where the DNS message is 512 octets or smaller and could
+ thus be expected to fit a UDP packet.
+
+ The URI private type indicates a certificate format defined by an
+ absolute URI. The certificate portion of the CERT RR MUST begin with
+ a null-terminated URI [10], and the data after the null is the
+ private format certificate itself. The URI SHOULD be such that a
+ retrieval from it will lead to documentation on the format of the
+ certificate. Recognition of private certificate types need not be
+ based on URI equality but can use various forms of pattern matching
+ so that, for example, subtype or version information can also be
+ encoded into the URI.
+
+
+
+
+
+Josefsson Standards Track [Page 5]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+ The OID private type indicates a private format certificate specified
+ by an ISO OID prefix. The certificate section will start with a
+ one-octet unsigned OID length and then a BER-encoded OID indicating
+ the nature of the remainder of the certificate section. This can be
+ an X.509 certificate format or some other format. X.509 certificates
+ that conform to the IETF PKIX profile SHOULD be indicated by the PKIX
+ type, not the OID private type. Recognition of private certificate
+ types need not be based on OID equality but can use various forms of
+ pattern matching such as OID prefix.
+
+2.2. Text Representation of CERT RRs
+
+ The RDATA portion of a CERT RR has the type field as an unsigned
+ decimal integer or as a mnemonic symbol as listed in Section 2.1,
+ above.
+
+ The key tag field is represented as an unsigned decimal integer.
+
+ The algorithm field is represented as an unsigned decimal integer or
+ a mnemonic symbol as listed in [12].
+
+ The certificate/CRL portion is represented in base 64 [16] and may be
+ divided into any number of white-space-separated substrings, down to
+ single base-64 digits, which are concatenated to obtain the full
+ signature. These substrings can span lines using the standard
+ parenthesis.
+
+ Note that the certificate/CRL portion may have internal sub-fields,
+ but these do not appear in the master file representation. For
+ example, with type 254, there will be an OID size, an OID, and then
+ the certificate/CRL proper. However, only a single logical base-64
+ string will appear in the text representation.
+
+2.3. X.509 OIDs
+
+ OIDs have been defined in connection with the X.500 directory for
+ user certificates, certification authority certificates, revocations
+ of certification authority, and revocations of user certificates.
+ The following table lists the OIDs, their BER encoding, and their
+ length-prefixed hex format for use in CERT RRs:
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 6]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+ id-at-userCertificate
+ = { joint-iso-ccitt(2) ds(5) at(4) 36 }
+ == 0x 03 55 04 24
+ id-at-cACertificate
+ = { joint-iso-ccitt(2) ds(5) at(4) 37 }
+ == 0x 03 55 04 25
+ id-at-authorityRevocationList
+ = { joint-iso-ccitt(2) ds(5) at(4) 38 }
+ == 0x 03 55 04 26
+ id-at-certificateRevocationList
+ = { joint-iso-ccitt(2) ds(5) at(4) 39 }
+ == 0x 03 55 04 27
+
+3. Appropriate Owner Names for CERT RRs
+
+ It is recommended that certificate CERT RRs be stored under a domain
+ name related to their subject, i.e., the name of the entity intended
+ to control the private key corresponding to the public key being
+ certified. It is recommended that certificate revocation list CERT
+ RRs be stored under a domain name related to their issuer.
+
+ Following some of the guidelines below may result in DNS names with
+ characters that require DNS quoting as per Section 5.1 of RFC 1035
+ [2].
+
+ The choice of name under which CERT RRs are stored is important to
+ clients that perform CERT queries. In some situations, the clients
+ may not know all information about the CERT RR object it wishes to
+ retrieve. For example, a client may not know the subject name of an
+ X.509 certificate, or the email address of the owner of an OpenPGP
+ key. Further, the client might only know the hostname of a service
+ that uses X.509 certificates or the Key ID of an OpenPGP key.
+
+ Therefore, two owner name guidelines are defined: content-based owner
+ names and purpose-based owner names. A content-based owner name is
+ derived from the content of the CERT RR data; for example, the
+ Subject field in an X.509 certificate or the User ID field in OpenPGP
+ keys. A purpose-based owner name is a name that a client retrieving
+ CERT RRs ought to know already; for example, the host name of an
+ X.509 protected service or the Key ID of an OpenPGP key. The
+ content-based and purpose-based owner name may be the same; for
+ example, when a client looks up a key based on the From: address of
+ an incoming email.
+
+ Implementations SHOULD use the purpose-based owner name guidelines
+ described in this document and MAY use CNAME RRs at content-based
+ owner names (or other names), pointing to the purpose-based owner
+ name.
+
+
+
+Josefsson Standards Track [Page 7]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+ Note that this section describes an application-based mapping from
+ the name space used in a certificate to the name space used by DNS.
+ The DNS does not infer any relationship amongst CERT resource records
+ based on similarities or differences of the DNS owner name(s) of CERT
+ resource records. For example, if multiple labels are used when
+ mapping from a CERT identifier to a domain name, then care must be
+ taken in understanding wildcard record synthesis.
+
+3.1. Content-Based X.509 CERT RR Names
+
+ Some X.509 versions, such as the PKIX profile of X.509 [8], permit
+ multiple names to be associated with subjects and issuers under
+ "Subject Alternative Name" and "Issuer Alternative Name". For
+ example, the PKIX profile has such Alternate Names with an ASN.1
+ specification as follows:
+
+ GeneralName ::= CHOICE {
+ otherName [0] OtherName,
+ rfc822Name [1] IA5String,
+ dNSName [2] IA5String,
+ x400Address [3] ORAddress,
+ directoryName [4] Name,
+ ediPartyName [5] EDIPartyName,
+ uniformResourceIdentifier [6] IA5String,
+ iPAddress [7] OCTET STRING,
+ registeredID [8] OBJECT IDENTIFIER }
+
+ The recommended locations of CERT storage are as follows, in priority
+ order:
+
+ 1. If a domain name is included in the identification in the
+ certificate or CRL, that ought to be used.
+ 2. If a domain name is not included but an IP address is included,
+ then the translation of that IP address into the appropriate
+ inverse domain name ought to be used.
+ 3. If neither of the above is used, but a URI containing a domain
+ name is present, that domain name ought to be used.
+ 4. If none of the above is included but a character string name is
+ included, then it ought to be treated as described below for
+ OpenPGP names.
+ 5. If none of the above apply, then the distinguished name (DN)
+ ought to be mapped into a domain name as specified in [4].
+
+ Example 1: An X.509v3 certificate is issued to /CN=John Doe /DC=Doe/
+ DC=com/DC=xy/O=Doe Inc/C=XY/ with Subject Alternative Names of (a)
+ string "John (the Man) Doe", (b) domain name john-doe.com, and (c)
+ URI <https://www.secure.john-doe.com:8080/>. The storage locations
+ recommended, in priority order, would be
+
+
+
+Josefsson Standards Track [Page 8]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+ 1. john-doe.com,
+ 2. www.secure.john-doe.com, and
+ 3. Doe.com.xy.
+
+ Example 2: An X.509v3 certificate is issued to /CN=James Hacker/
+ L=Basingstoke/O=Widget Inc/C=GB/ with Subject Alternate names of (a)
+ domain name widget.foo.example, (b) IPv4 address 10.251.13.201, and
+ (c) string "James Hacker <hacker@mail.widget.foo.example>". The
+ storage locations recommended, in priority order, would be
+
+ 1. widget.foo.example,
+ 2. 201.13.251.10.in-addr.arpa, and
+ 3. hacker.mail.widget.foo.example.
+
+3.2. Purpose-Based X.509 CERT RR Names
+
+ Due to the difficulty for clients that do not already possess a
+ certificate to reconstruct the content-based owner name,
+ purpose-based owner names are recommended in this section.
+ Recommendations for purpose-based owner names vary per scenario. The
+ following table summarizes the purpose-based X.509 CERT RR owner name
+ guidelines for use with S/MIME [17], SSL/TLS [13], and IPsec [14]:
+
+ Scenario Owner name
+ ------------------ ----------------------------------------------
+ S/MIME Certificate Standard translation of an RFC 2822 email
+ address. Example: An S/MIME certificate for
+ "postmaster@example.org" will use a standard
+ hostname translation of the owner name,
+ "postmaster.example.org".
+
+ TLS Certificate Hostname of the TLS server.
+
+ IPsec Certificate Hostname of the IPsec machine and/or, for IPv4
+ or IPv6 addresses, the fully qualified domain
+ name in the appropriate reverse domain.
+
+ An alternate approach for IPsec is to store raw public keys [18].
+
+3.3. Content-Based OpenPGP CERT RR Names
+
+ OpenPGP signed keys (certificates) use a general character string
+ User ID [5]. However, it is recommended by OpenPGP that such names
+ include the RFC 2822 [7] email address of the party, as in "Leslie
+ Example <Leslie@host.example>". If such a format is used, the CERT
+ ought to be under the standard translation of the email address into
+
+
+
+
+
+Josefsson Standards Track [Page 9]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+ a domain name, which would be leslie.host.example in this case. If
+ no RFC 2822 name can be extracted from the string name, no specific
+ domain name is recommended.
+
+ If a user has more than one email address, the CNAME type can be used
+ to reduce the amount of data stored in the DNS. For example:
+
+ $ORIGIN example.org.
+ smith IN CERT PGP 0 0 <OpenPGP binary>
+ john.smith IN CNAME smith
+ js IN CNAME smith
+
+3.4. Purpose-Based OpenPGP CERT RR Names
+
+ Applications that receive an OpenPGP packet containing encrypted or
+ signed data but do not know the email address of the sender will have
+ difficulties constructing the correct owner name and cannot use the
+ content-based owner name guidelines. However, these clients commonly
+ know the key fingerprint or the Key ID. The key ID is found in
+ OpenPGP packets, and the key fingerprint is commonly found in
+ auxiliary data that may be available. In this case, use of an owner
+ name identical to the key fingerprint and the key ID expressed in
+ hexadecimal [16] is recommended. For example:
+
+ $ORIGIN example.org.
+ 0424D4EE81A0E3D119C6F835EDA21E94B565716F IN CERT PGP ...
+ F835EDA21E94B565716F IN CERT PGP ...
+ B565716F IN CERT PGP ...
+
+ If the same key material is stored for several owner names, the use
+ of CNAME may help avoid data duplication. Note that CNAME is not
+ always applicable, because it maps one owner name to the other for
+ all purposes, which may be sub-optimal when two keys with the same
+ Key ID are stored.
+
+3.5. Owner Names for IPKIX, ISPKI, IPGP, and IACPKIX
+
+ These types are stored under the same owner names, both purpose- and
+ content-based, as the PKIX, SPKI, PGP, and ACPKIX types.
+
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 10]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+4. Performance Considerations
+
+ The Domain Name System (DNS) protocol was designed for small
+ transfers, typically below 512 octets. While larger transfers will
+ perform correctly and work is underway to make larger transfers more
+ efficient, it is still advisable at this time that every reasonable
+ effort be made to minimize the size of certificates stored within the
+ DNS. Steps that can be taken may include using the fewest possible
+ optional or extension fields and using short field values for
+ necessary variable-length fields.
+
+ The RDATA field in the DNS protocol may only hold data of size 65535
+ octets (64kb) or less. This means that each CERT RR MUST NOT contain
+ more than 64kb of payload, even if the corresponding certificate or
+ certificate revocation list is larger. This document addresses this
+ by defining "indirect" data types for each normal type.
+
+ Deploying CERT RRs to support digitally signed email changes the
+ access patterns of DNS lookups from per-domain to per-user. If
+ digitally signed email and a key/certificate lookup based on CERT RRs
+ are deployed on a wide scale, this may lead to an increased DNS load,
+ with potential performance and cache effectiveness consequences.
+ Whether or not this load increase will be noticeable is not known.
+
+5. Contributors
+
+ The majority of this document is copied verbatim from RFC 2538, by
+ Donald Eastlake 3rd and Olafur Gudmundsson.
+
+6. Acknowledgements
+
+ Thanks to David Shaw and Michael Graff for their contributions to
+ earlier works that motivated, and served as inspiration for, this
+ document.
+
+ This document was improved by suggestions and comments from Olivier
+ Dubuisson, Scott Hollenbeck, Russ Housley, Peter Koch, Olaf M.
+ Kolkman, Ben Laurie, Edward Lewis, John Loughney, Allison Mankin,
+ Douglas Otis, Marcos Sanz, Pekka Savola, Jason Sloderbeck, Samuel
+ Weiler, and Florian Weimer. No doubt the list is incomplete. We
+ apologize to anyone we left out.
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 11]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+7. Security Considerations
+
+ By definition, certificates contain their own authenticating
+ signatures. Thus, it is reasonable to store certificates in
+ non-secure DNS zones or to retrieve certificates from DNS with DNS
+ security checking not implemented or deferred for efficiency. The
+ results may be trusted if the certificate chain is verified back to a
+ known trusted key and this conforms with the user's security policy.
+
+ Alternatively, if certificates are retrieved from a secure DNS zone
+ with DNS security checking enabled and are verified by DNS security,
+ the key within the retrieved certificate may be trusted without
+ verifying the certificate chain if this conforms with the user's
+ security policy.
+
+ If an organization chooses to issue certificates for its employees,
+ placing CERT RRs in the DNS by owner name, and if DNSSEC (with NSEC)
+ is in use, it is possible for someone to enumerate all employees of
+ the organization. This is usually not considered desirable, for the
+ same reason that enterprise phone listings are not often publicly
+ published and are even marked confidential.
+
+ Using the URI type introduces another level of indirection that may
+ open a new vulnerability. One method of securing that indirection is
+ to include a hash of the certificate in the URI itself.
+
+ If DNSSEC is used, then the non-existence of a CERT RR and,
+ consequently, certificates or revocation lists can be securely
+ asserted. Without DNSSEC, this is not possible.
+
+8. IANA Considerations
+
+ The IANA has created a new registry for CERT RR: certificate types.
+ The initial contents of this registry is:
+
+ Decimal Type Meaning Reference
+ ------- ---- ------- ---------
+ 0 Reserved RFC 4398
+ 1 PKIX X.509 as per PKIX RFC 4398
+ 2 SPKI SPKI certificate RFC 4398
+ 3 PGP OpenPGP packet RFC 4398
+ 4 IPKIX The URL of an X.509 data object RFC 4398
+ 5 ISPKI The URL of an SPKI certificate RFC 4398
+ 6 IPGP The fingerprint and URL RFC 4398
+ of an OpenPGP packet
+ 7 ACPKIX Attribute Certificate RFC 4398
+ 8 IACPKIX The URL of an Attribute RFC 4398
+ Certificate
+
+
+
+Josefsson Standards Track [Page 12]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+ 9-252 Available for IANA assignment
+ by IETF Standards action
+ 253 URI URI private RFC 4398
+ 254 OID OID private RFC 4398
+ 255 Reserved RFC 4398
+ 256-65279 Available for IANA assignment
+ by IETF Consensus
+ 65280-65534 Experimental RFC 4398
+ 65535 Reserved RFC 4398
+
+ Certificate types 0x0000 through 0x00FF and 0xFF00 through 0xFFFF can
+ only be assigned by an IETF standards action [6]. This document
+ assigns 0x0001 through 0x0008 and 0x00FD and 0x00FE. Certificate
+ types 0x0100 through 0xFEFF are assigned through IETF Consensus [6]
+ based on RFC documentation of the certificate type. The availability
+ of private types under 0x00FD and 0x00FE ought to satisfy most
+ requirements for proprietary or private types.
+
+ The CERT RR reuses the DNS Security Algorithm Numbers registry. In
+ particular, the CERT RR requires that algorithm number 0 remain
+ reserved, as described in Section 2. The IANA will reference the
+ CERT RR as a user of this registry and value 0, in particular.
+
+9. Changes since RFC 2538
+
+ 1. Editorial changes to conform with new document requirements,
+ including splitting reference section into two parts and
+ updating the references to point at latest versions, and to add
+ some additional references.
+ 2. Improve terminology. For example replace "PGP" with "OpenPGP",
+ to align with RFC 2440.
+ 3. In Section 2.1, clarify that OpenPGP public key data are binary,
+ not the ASCII armored format, and reference 10.1 in RFC 2440 on
+ how to deal with OpenPGP keys, and acknowledge that
+ implementations may handle additional packet types.
+ 4. Clarify that integers in the representation format are decimal.
+ 5. Replace KEY/SIG with DNSKEY/RRSIG etc, to align with DNSSECbis
+ terminology. Improve reference for Key Tag Algorithm
+ calculations.
+ 6. Add examples that suggest use of CNAME to reduce bandwidth.
+ 7. In Section 3, appended the last paragraphs that discuss
+ "content-based" vs "purpose-based" owner names. Add Section 3.2
+ for purpose-based X.509 CERT owner names, and Section 3.4 for
+ purpose-based OpenPGP CERT owner names.
+ 8. Added size considerations.
+ 9. The SPKI types has been reserved, until RFC 2692/2693 is moved
+ from the experimental status.
+ 10. Added indirect types IPKIX, ISPKI, IPGP, and IACPKIX.
+
+
+
+Josefsson Standards Track [Page 13]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+ 11. An IANA registry of CERT type values was created.
+
+10. References
+
+10.1. Normative References
+
+ [1] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [2] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [3] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [4] Kille, S., Wahl, M., Grimstad, A., Huber, R., and S. Sataluri,
+ "Using Domains in LDAP/X.500 Distinguished Names", RFC 2247,
+ January 1998.
+
+ [5] Callas, J., Donnerhacke, L., Finney, H., and R. Thayer,
+ "OpenPGP Message Format", RFC 2440, November 1998.
+
+ [6] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA
+ Considerations Section in RFCs", BCP 26, RFC 2434,
+ October 1998.
+
+ [7] Resnick, P., "Internet Message Format", RFC 2822, April 2001.
+
+ [8] Housley, R., Polk, W., Ford, W., and D. Solo, "Internet X.509
+ Public Key Infrastructure Certificate and Certificate
+ Revocation List (CRL) Profile", RFC 3280, April 2002.
+
+ [9] Farrell, S. and R. Housley, "An Internet Attribute Certificate
+ Profile for Authorization", RFC 3281, April 2002.
+
+ [10] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
+ Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986,
+ January 2005.
+
+ [11] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033,
+ March 2005.
+
+ [12] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+
+
+
+
+Josefsson Standards Track [Page 14]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+10.2. Informative References
+
+ [13] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0",
+ RFC 2246, January 1999.
+
+ [14] Kent, S. and K. Seo, "Security Architecture for the Internet
+ Protocol", RFC 4301, December 2005.
+
+ [15] Ellison, C., Frantz, B., Lampson, B., Rivest, R., Thomas, B.,
+ and T. Ylonen, "SPKI Certificate Theory", RFC 2693,
+ September 1999.
+
+ [16] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings",
+ RFC 3548, July 2003.
+
+ [17] Ramsdell, B., "Secure/Multipurpose Internet Mail Extensions
+ (S/MIME) Version 3.1 Message Specification", RFC 3851,
+ July 2004.
+
+ [18] Richardson, M., "A Method for Storing IPsec Keying Material in
+ DNS", RFC 4025, March 2005.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 15]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+Appendix A. Copying Conditions
+
+ Regarding the portion of this document that was written by Simon
+ Josefsson ("the author", for the remainder of this section), the
+ author makes no guarantees and is not responsible for any damage
+ resulting from its use. The author grants irrevocable permission to
+ anyone to use, modify, and distribute it in any way that does not
+ diminish the rights of anyone else to use, modify, and distribute it,
+ provided that redistributed derivative works do not contain
+ misleading author or version information. Derivative works need not
+ be licensed under similar terms.
+
+Author's Address
+
+ Simon Josefsson
+
+ EMail: simon@josefsson.org
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 16]
+
+RFC 4398 Storing Certificates in the DNS February 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 17]
+
diff --git a/doc/rfc/rfc4408.txt b/doc/rfc/rfc4408.txt
new file mode 100644
index 0000000..bc1b3f5
--- /dev/null
+++ b/doc/rfc/rfc4408.txt
@@ -0,0 +1,2691 @@
+
+
+
+
+
+
+Network Working Group M. Wong
+Request for Comments: 4408 W. Schlitt
+Category: Experimental April 2006
+
+
+ Sender Policy Framework (SPF) for
+ Authorizing Use of Domains in E-Mail, Version 1
+
+Status of This Memo
+
+ This memo defines an Experimental Protocol for the Internet
+ community. It does not specify an Internet standard of any kind.
+ Discussion and suggestions for improvement are requested.
+ Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+IESG Note
+
+ The following documents (RFC 4405, RFC 4406, RFC 4407, and RFC 4408)
+ are published simultaneously as Experimental RFCs, although there is
+ no general technical consensus and efforts to reconcile the two
+ approaches have failed. As such, these documents have not received
+ full IETF review and are published "AS-IS" to document the different
+ approaches as they were considered in the MARID working group.
+
+ The IESG takes no position about which approach is to be preferred
+ and cautions the reader that there are serious open issues for each
+ approach and concerns about using them in tandem. The IESG believes
+ that documenting the different approaches does less harm than not
+ documenting them.
+
+ Note that the Sender ID experiment may use DNS records that may have
+ been created for the current SPF experiment or earlier versions in
+ this set of experiments. Depending on the content of the record,
+ this may mean that Sender-ID heuristics would be applied incorrectly
+ to a message. Depending on the actions associated by the recipient
+ with those heuristics, the message may not be delivered or may be
+ discarded on receipt.
+
+ Participants relying on Sender ID experiment DNS records are warned
+ that they may lose valid messages in this set of circumstances.
+ aParticipants publishing SPF experiment DNS records should consider
+ the advice given in section 3.4 of RFC 4406 and may wish to publish
+ both v=spf1 and spf2.0 records to avoid the conflict.
+
+
+
+
+Wong & Schlitt Experimental [Page 1]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ Participants in the Sender-ID experiment need to be aware that the
+ way Resent-* header fields are used will result in failure to receive
+ legitimate email when interacting with standards-compliant systems
+ (specifically automatic forwarders which comply with the standards by
+ not adding Resent-* headers, and systems which comply with RFC 822
+ but have not yet implemented RFC 2822 Resent-* semantics). It would
+ be inappropriate to advance Sender-ID on the standards track without
+ resolving this interoperability problem.
+
+ The community is invited to observe the success or failure of the two
+ approaches during the two years following publication, in order that
+ a community consensus can be reached in the future.
+
+Abstract
+
+ E-mail on the Internet can be forged in a number of ways. In
+ particular, existing protocols place no restriction on what a sending
+ host can use as the reverse-path of a message or the domain given on
+ the SMTP HELO/EHLO commands. This document describes version 1 of
+ the Sender Policy Framework (SPF) protocol, whereby a domain may
+ explicitly authorize the hosts that are allowed to use its domain
+ name, and a receiving host may check such authorization.
+
+Table of Contents
+
+ 1. Introduction ....................................................4
+ 1.1. Protocol Status ............................................4
+ 1.2. Terminology ................................................5
+ 2. Operation .......................................................5
+ 2.1. The HELO Identity ..........................................5
+ 2.2. The MAIL FROM Identity .....................................5
+ 2.3. Publishing Authorization ...................................6
+ 2.4. Checking Authorization .....................................6
+ 2.5. Interpreting the Result ....................................7
+ 2.5.1. None ................................................8
+ 2.5.2. Neutral .............................................8
+ 2.5.3. Pass ................................................8
+ 2.5.4. Fail ................................................8
+ 2.5.5. SoftFail ............................................9
+ 2.5.6. TempError ...........................................9
+ 2.5.7. PermError ...........................................9
+ 3. SPF Records .....................................................9
+ 3.1. Publishing ................................................10
+ 3.1.1. DNS Resource Record Types ..........................10
+ 3.1.2. Multiple DNS Records ...............................11
+ 3.1.3. Multiple Strings in a Single DNS record ............11
+ 3.1.4. Record Size ........................................11
+ 3.1.5. Wildcard Records ...................................11
+
+
+
+Wong & Schlitt Experimental [Page 2]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ 4. The check_host() Function ......................................12
+ 4.1. Arguments .................................................12
+ 4.2. Results ...................................................13
+ 4.3. Initial Processing ........................................13
+ 4.4. Record Lookup .............................................13
+ 4.5. Selecting Records .........................................13
+ 4.6. Record Evaluation .........................................14
+ 4.6.1. Term Evaluation ....................................14
+ 4.6.2. Mechanisms .........................................15
+ 4.6.3. Modifiers ..........................................15
+ 4.7. Default Result ............................................16
+ 4.8. Domain Specification ......................................16
+ 5. Mechanism Definitions ..........................................16
+ 5.1. "all" .....................................................17
+ 5.2. "include" .................................................18
+ 5.3. "a" .......................................................19
+ 5.4. "mx" ......................................................20
+ 5.5. "ptr" .....................................................20
+ 5.6. "ip4" and "ip6" ...........................................21
+ 5.7. "exists" ..................................................22
+ 6. Modifier Definitions ...........................................22
+ 6.1. redirect: Redirected Query ................................23
+ 6.2. exp: Explanation ..........................................23
+ 7. The Received-SPF Header Field ..................................25
+ 8. Macros .........................................................27
+ 8.1. Macro Definitions .........................................27
+ 8.2. Expansion Examples ........................................30
+ 9. Implications ...................................................31
+ 9.1. Sending Domains ...........................................31
+ 9.2. Mailing Lists .............................................32
+ 9.3. Forwarding Services and Aliases ...........................32
+ 9.4. Mail Services .............................................34
+ 9.5. MTA Relays ................................................34
+ 10. Security Considerations .......................................35
+ 10.1. Processing Limits ........................................35
+ 10.2. SPF-Authorized E-Mail May Contain Other False
+ Identities ...............................................37
+ 10.3. Spoofed DNS and IP Data ..................................37
+ 10.4. Cross-User Forgery .......................................37
+ 10.5. Untrusted Information Sources ............................38
+ 10.6. Privacy Exposure .........................................38
+ 11. Contributors and Acknowledgements .............................38
+ 12. IANA Considerations ...........................................39
+ 12.1. The SPF DNS Record Type ..................................39
+ 12.2. The Received-SPF Mail Header Field .......................39
+ 13. References ....................................................39
+ 13.1. Normative References .....................................39
+ 13.2. Informative References ...................................40
+
+
+
+Wong & Schlitt Experimental [Page 3]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ Appendix A. Collected ABNF .......................................42
+ Appendix B. Extended Examples ....................................44
+ B.1. Simple Examples ..........................................44
+ B.2. Multiple Domain Example ..................................45
+ B.3. DNSBL Style Example ......................................46
+ B.4. Multiple Requirements Example ............................46
+
+1. Introduction
+
+ The current E-Mail infrastructure has the property that any host
+ injecting mail into the mail system can identify itself as any domain
+ name it wants. Hosts can do this at a variety of levels: in
+ particular, the session, the envelope, and the mail headers.
+ Although this feature is desirable in some circumstances, it is a
+ major obstacle to reducing Unsolicited Bulk E-Mail (UBE, aka spam).
+ Furthermore, many domain name holders are understandably concerned
+ about the ease with which other entities may make use of their domain
+ names, often with malicious intent.
+
+ This document defines a protocol by which domain owners may authorize
+ hosts to use their domain name in the "MAIL FROM" or "HELO" identity.
+ Compliant domain holders publish Sender Policy Framework (SPF)
+ records specifying which hosts are permitted to use their names, and
+ compliant mail receivers use the published SPF records to test the
+ authorization of sending Mail Transfer Agents (MTAs) using a given
+ "HELO" or "MAIL FROM" identity during a mail transaction.
+
+ An additional benefit to mail receivers is that after the use of an
+ identity is verified, local policy decisions about the mail can be
+ made based on the sender's domain, rather than the host's IP address.
+ This is advantageous because reputation of domain names is likely to
+ be more accurate than reputation of host IP addresses. Furthermore,
+ if a claimed identity fails verification, local policy can take
+ stronger action against such E-Mail, such as rejecting it.
+
+1.1. Protocol Status
+
+ SPF has been in development since the summer of 2003 and has seen
+ deployment beyond the developers beginning in December 2003. The
+ design of SPF slowly evolved until the spring of 2004 and has since
+ stabilized. There have been quite a number of forms of SPF, some
+ written up as documents, some submitted as Internet Drafts, and many
+ discussed and debated in development forums.
+
+ The goal of this document is to clearly document the protocol defined
+ by earlier draft specifications of SPF as used in existing
+ implementations. This conception of SPF is sometimes called "SPF
+ Classic". It is understood that particular implementations and
+
+
+
+Wong & Schlitt Experimental [Page 4]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ deployments may differ from, and build upon, this work. It is hoped
+ that we have nonetheless captured the common understanding of SPF
+ version 1.
+
+1.2. Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+ This document is concerned with the portion of a mail message
+ commonly called "envelope sender", "return path", "reverse path",
+ "bounce address", "2821 FROM", or "MAIL FROM". Since these terms are
+ either not well defined or often used casually, this document defines
+ the "MAIL FROM" identity in Section 2.2. Note that other terms that
+ may superficially look like the common terms, such as "reverse-path",
+ are used only with the defined meanings from normative documents.
+
+2. Operation
+
+2.1. The HELO Identity
+
+ The "HELO" identity derives from either the SMTP HELO or EHLO command
+ (see [RFC2821]). These commands supply the SMTP client (sending
+ host) for the SMTP session. Note that requirements for the domain
+ presented in the EHLO or HELO command are not always clear to the
+ sending party, and SPF clients must be prepared for the "HELO"
+ identity to be malformed or an IP address literal. At the time of
+ this writing, many legitimate E-Mails are delivered with invalid HELO
+ domains.
+
+ It is RECOMMENDED that SPF clients not only check the "MAIL FROM"
+ identity, but also separately check the "HELO" identity by applying
+ the check_host() function (Section 4) to the "HELO" identity as the
+ <sender>.
+
+2.2. The MAIL FROM Identity
+
+ The "MAIL FROM" identity derives from the SMTP MAIL command (see
+ [RFC2821]). This command supplies the "reverse-path" for a message,
+ which generally consists of the sender mailbox, and is the mailbox to
+ which notification messages are to be sent if there are problems
+ delivering the message.
+
+ [RFC2821] allows the reverse-path to be null (see Section 4.5.5 in
+ RFC 2821). In this case, there is no explicit sender mailbox, and
+ such a message can be assumed to be a notification message from the
+ mail system itself. When the reverse-path is null, this document
+
+
+
+Wong & Schlitt Experimental [Page 5]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ defines the "MAIL FROM" identity to be the mailbox composed of the
+ localpart "postmaster" and the "HELO" identity (which may or may not
+ have been checked separately before).
+
+ SPF clients MUST check the "MAIL FROM" identity. SPF clients check
+ the "MAIL FROM" identity by applying the check_host() function to the
+ "MAIL FROM" identity as the <sender>.
+
+2.3. Publishing Authorization
+
+ An SPF-compliant domain MUST publish a valid SPF record as described
+ in Section 3. This record authorizes the use of the domain name in
+ the "HELO" and "MAIL FROM" identities by the MTAs it specifies.
+
+ If domain owners choose to publish SPF records, it is RECOMMENDED
+ that they end in "-all", or redirect to other records that do, so
+ that a definitive determination of authorization can be made.
+
+ Domain holders may publish SPF records that explicitly authorize no
+ hosts if mail should never originate using that domain.
+
+ When changing SPF records, care must be taken to ensure that there is
+ a transition period so that the old policy remains valid until all
+ legitimate E-Mail has been checked.
+
+2.4. Checking Authorization
+
+ A mail receiver can perform a set of SPF checks for each mail message
+ it receives. An SPF check tests the authorization of a client host
+ to emit mail with a given identity. Typically, such checks are done
+ by a receiving MTA, but can be performed elsewhere in the mail
+ processing chain so long as the required information is available and
+ reliable. At least the "MAIL FROM" identity MUST be checked, but it
+ is RECOMMENDED that the "HELO" identity also be checked beforehand.
+
+ Without explicit approval of the domain owner, checking other
+ identities against SPF version 1 records is NOT RECOMMENDED because
+ there are cases that are known to give incorrect results. For
+ example, almost all mailing lists rewrite the "MAIL FROM" identity
+ (see Section 9.2), but some do not change any other identities in the
+ message. The scenario described in Section 9.3, sub-section 1.2, is
+ another example. Documents that define other identities should
+ define the method for explicit approval.
+
+ It is possible that mail receivers will use the SPF check as part of
+ a larger set of tests on incoming mail. The results of other tests
+ may influence whether or not a particular SPF check is performed.
+ For example, finding the sending host's IP address on a local white
+
+
+
+Wong & Schlitt Experimental [Page 6]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ list may cause all other tests to be skipped and all mail from that
+ host to be accepted.
+
+ When a mail receiver decides to perform an SPF check, it MUST use a
+ correctly-implemented check_host() function (Section 4) evaluated
+ with the correct parameters. Although the test as a whole is
+ optional, once it has been decided to perform a test it must be
+ performed as specified so that the correct semantics are preserved
+ between publisher and receiver.
+
+ To make the test, the mail receiver MUST evaluate the check_host()
+ function with the arguments set as follows:
+
+ <ip> - the IP address of the SMTP client that is emitting the
+ mail, either IPv4 or IPv6.
+
+ <domain> - the domain portion of the "MAIL FROM" or "HELO" identity.
+
+ <sender> - the "MAIL FROM" or "HELO" identity.
+
+ Note that the <domain> argument may not be a well-formed domain name.
+ For example, if the reverse-path was null, then the EHLO/HELO domain
+ is used, with its associated problems (see Section 2.1). In these
+ cases, check_host() is defined in Section 4.3 to return a "None"
+ result.
+
+ Although invalid, malformed, or non-existent domains cause SPF checks
+ to return "None" because no SPF record can be found, it has long been
+ the policy of many MTAs to reject E-Mail from such domains,
+ especially in the case of invalid "MAIL FROM". In order to prevent
+ the circumvention of SPF records, rejecting E-Mail from invalid
+ domains should be considered.
+
+ Implementations must take care to correctly extract the <domain> from
+ the data given with the SMTP MAIL FROM command as many MTAs will
+ still accept such things as source routes (see [RFC2821], Appendix
+ C), the %-hack (see [RFC1123]), and bang paths (see [RFC1983]).
+ These archaic features have been maliciously used to bypass security
+ systems.
+
+2.5. Interpreting the Result
+
+ This section describes how software that performs the authorization
+ should interpret the results of the check_host() function. The
+ authorization check SHOULD be performed during the processing of the
+ SMTP transaction that sends the mail. This allows errors to be
+ returned directly to the sending MTA by way of SMTP replies.
+
+
+
+
+Wong & Schlitt Experimental [Page 7]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ Performing the authorization after the SMTP transaction has finished
+ may cause problems, such as the following: (1) It may be difficult to
+ accurately extract the required information from potentially
+ deceptive headers; (2) legitimate E-Mail may fail because the
+ sender's policy may have since changed.
+
+ Generating non-delivery notifications to forged identities that have
+ failed the authorization check is generally abusive and against the
+ explicit wishes of the identity owner.
+
+2.5.1. None
+
+ A result of "None" means that no records were published by the domain
+ or that no checkable sender domain could be determined from the given
+ identity. The checking software cannot ascertain whether or not the
+ client host is authorized.
+
+2.5.2. Neutral
+
+ The domain owner has explicitly stated that he cannot or does not
+ want to assert whether or not the IP address is authorized. A
+ "Neutral" result MUST be treated exactly like the "None" result; the
+ distinction exists only for informational purposes. Treating
+ "Neutral" more harshly than "None" would discourage domain owners
+ from testing the use of SPF records (see Section 9.1).
+
+2.5.3. Pass
+
+ A "Pass" result means that the client is authorized to inject mail
+ with the given identity. The domain can now, in the sense of
+ reputation, be considered responsible for sending the message.
+ Further policy checks can now proceed with confidence in the
+ legitimate use of the identity.
+
+2.5.4. Fail
+
+ A "Fail" result is an explicit statement that the client is not
+ authorized to use the domain in the given identity. The checking
+ software can choose to mark the mail based on this or to reject the
+ mail outright.
+
+ If the checking software chooses to reject the mail during the SMTP
+ transaction, then it SHOULD use an SMTP reply code of 550 (see
+ [RFC2821]) and, if supported, the 5.7.1 Delivery Status Notification
+ (DSN) code (see [RFC3464]), in addition to an appropriate reply text.
+ The check_host() function may return either a default explanation
+ string or one from the domain that published the SPF records (see
+ Section 6.2). If the information does not originate with the
+
+
+
+Wong & Schlitt Experimental [Page 8]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ checking software, it should be made clear that the text is provided
+ by the sender's domain. For example:
+
+ 550-5.7.1 SPF MAIL FROM check failed:
+ 550-5.7.1 The domain example.com explains:
+ 550 5.7.1 Please see http://www.example.com/mailpolicy.html
+
+2.5.5. SoftFail
+
+ A "SoftFail" result should be treated as somewhere between a "Fail"
+ and a "Neutral". The domain believes the host is not authorized but
+ is not willing to make that strong of a statement. Receiving
+ software SHOULD NOT reject the message based solely on this result,
+ but MAY subject the message to closer scrutiny than normal.
+
+ The domain owner wants to discourage the use of this host and thus
+ desires limited feedback when a "SoftFail" result occurs. For
+ example, the recipient's Mail User Agent (MUA) could highlight the
+ "SoftFail" status, or the receiving MTA could give the sender a
+ message using a technique called "greylisting" whereby the MTA can
+ issue an SMTP reply code of 451 (4.3.0 DSN code) with a note the
+ first time the message is received, but accept it the second time.
+
+2.5.6. TempError
+
+ A "TempError" result means that the SPF client encountered a
+ transient error while performing the check. Checking software can
+ choose to accept or temporarily reject the message. If the message
+ is rejected during the SMTP transaction for this reason, the software
+ SHOULD use an SMTP reply code of 451 and, if supported, the 4.4.3 DSN
+ code.
+
+2.5.7. PermError
+
+ A "PermError" result means that the domain's published records could
+ not be correctly interpreted. This signals an error condition that
+ requires manual intervention to be resolved, as opposed to the
+ TempError result. Be aware that if the domain owner uses macros
+ (Section 8), it is possible that this result is due to the checked
+ identities having an unexpected format.
+
+3. SPF Records
+
+ An SPF record is a DNS Resource Record (RR) that declares which hosts
+ are, and are not, authorized to use a domain name for the "HELO" and
+ "MAIL FROM" identities. Loosely, the record partitions all hosts
+ into permitted and not-permitted sets (though some hosts might fall
+ into neither category).
+
+
+
+Wong & Schlitt Experimental [Page 9]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ The SPF record is a single string of text. An example record is the
+ following:
+
+ v=spf1 +mx a:colo.example.com/28 -all
+
+ This record has a version of "spf1" and three directives: "+mx",
+ "a:colo.example.com/28" (the + is implied), and "-all".
+
+3.1. Publishing
+
+ Domain owners wishing to be SPF compliant must publish SPF records
+ for the hosts that are used in the "MAIL FROM" and "HELO" identities.
+ The SPF records are placed in the DNS tree at the host name it
+ pertains to, not a subdomain under it, such as is done with SRV
+ records. This is the same whether the TXT or SPF RR type (see
+ Section 3.1.1) is used.
+
+ The example above in Section 3 might be published via these lines in
+ a domain zone file:
+
+ example.com. TXT "v=spf1 +mx a:colo.example.com/28 -all"
+ smtp-out.example.com. TXT "v=spf1 a -all"
+
+ When publishing via TXT records, beware of other TXT records
+ published there for other purposes. They may cause problems with
+ size limits (see Section 3.1.4).
+
+3.1.1. DNS Resource Record Types
+
+ This document defines a new DNS RR of type SPF, code 99. The format
+ of this type is identical to the TXT RR [RFC1035]. For either type,
+ the character content of the record is encoded as [US-ASCII].
+
+ It is recognized that the current practice (using a TXT record) is
+ not optimal, but it is necessary because there are a number of DNS
+ server and resolver implementations in common use that cannot handle
+ the new RR type. The two-record-type scheme provides a forward path
+ to the better solution of using an RR type reserved for this purpose.
+
+ An SPF-compliant domain name SHOULD have SPF records of both RR
+ types. A compliant domain name MUST have a record of at least one
+ type. If a domain has records of both types, they MUST have
+ identical content. For example, instead of publishing just one
+ record as in Section 3.1 above, it is better to publish:
+
+ example.com. IN TXT "v=spf1 +mx a:colo.example.com/28 -all"
+ example.com. IN SPF "v=spf1 +mx a:colo.example.com/28 -all"
+
+
+
+
+Wong & Schlitt Experimental [Page 10]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ Example RRs in this document are shown with the TXT record type;
+ however, they could be published with the SPF type or with both
+ types.
+
+3.1.2. Multiple DNS Records
+
+ A domain name MUST NOT have multiple records that would cause an
+ authorization check to select more than one record. See Section 4.5
+ for the selection rules.
+
+3.1.3. Multiple Strings in a Single DNS record
+
+ As defined in [RFC1035] sections 3.3.14 and 3.3, a single text DNS
+ record (either TXT or SPF RR types) can be composed of more than one
+ string. If a published record contains multiple strings, then the
+ record MUST be treated as if those strings are concatenated together
+ without adding spaces. For example:
+
+ IN TXT "v=spf1 .... first" "second string..."
+
+ MUST be treated as equivalent to
+
+ IN TXT "v=spf1 .... firstsecond string..."
+
+ SPF or TXT records containing multiple strings are useful in
+ constructing records that would exceed the 255-byte maximum length of
+ a string within a single TXT or SPF RR record.
+
+3.1.4. Record Size
+
+ The published SPF record for a given domain name SHOULD remain small
+ enough that the results of a query for it will fit within 512 octets.
+ This will keep even older DNS implementations from falling over to
+ TCP. Since the answer size is dependent on many things outside the
+ scope of this document, it is only possible to give this guideline:
+ If the combined length of the DNS name and the text of all the
+ records of a given type (TXT or SPF) is under 450 characters, then
+ DNS answers should fit in UDP packets. Note that when computing the
+ sizes for queries of the TXT format, one must take into account any
+ other TXT records published at the domain name. Records that are too
+ long to fit in a single UDP packet MAY be silently ignored by SPF
+ clients.
+
+3.1.5. Wildcard Records
+
+ Use of wildcard records for publishing is not recommended. Care must
+ be taken if wildcard records are used. If a domain publishes
+ wildcard MX records, it may want to publish wildcard declarations,
+
+
+
+Wong & Schlitt Experimental [Page 11]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ subject to the same requirements and problems. In particular, the
+ declaration must be repeated for any host that has any RR records at
+ all, and for subdomains thereof. For example, the example given in
+ [RFC1034], Section 4.3.3, could be extended with the following:
+
+ X.COM. MX 10 A.X.COM
+ X.COM. TXT "v=spf1 a:A.X.COM -all"
+
+ *.X.COM. MX 10 A.X.COM
+ *.X.COM. TXT "v=spf1 a:A.X.COM -all"
+
+ A.X.COM. A 1.2.3.4
+ A.X.COM. MX 10 A.X.COM
+ A.X.COM. TXT "v=spf1 a:A.X.COM -all"
+
+ *.A.X.COM. MX 10 A.X.COM
+ *.A.X.COM. TXT "v=spf1 a:A.X.COM -all"
+
+ Notice that SPF records must be repeated twice for every name within
+ the domain: once for the name, and once with a wildcard to cover the
+ tree under the name.
+
+ Use of wildcards is discouraged in general as they cause every name
+ under the domain to exist and queries against arbitrary names will
+ never return RCODE 3 (Name Error).
+
+4. The check_host() Function
+
+ The check_host() function fetches SPF records, parses them, and
+ interprets them to determine whether a particular host is or is not
+ permitted to send mail with a given identity. Mail receivers that
+ perform this check MUST correctly evaluate the check_host() function
+ as described here.
+
+ Implementations MAY use a different algorithm than the canonical
+ algorithm defined here, so long as the results are the same in all
+ cases.
+
+4.1. Arguments
+
+ The check_host() function takes these arguments:
+
+ <ip> - the IP address of the SMTP client that is emitting the
+ mail, either IPv4 or IPv6.
+
+ <domain> - the domain that provides the sought-after authorization
+ information; initially, the domain portion of the "MAIL
+ FROM" or "HELO" identity.
+
+
+
+Wong & Schlitt Experimental [Page 12]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ <sender> - the "MAIL FROM" or "HELO" identity.
+
+ The domain portion of <sender> will usually be the same as the
+ <domain> argument when check_host() is initially evaluated. However,
+ this will generally not be true for recursive evaluations (see
+ Section 5.2 below).
+
+ Actual implementations of the check_host() function may need
+ additional arguments.
+
+4.2. Results
+
+ The function check_host() can return one of several results described
+ in Section 2.5. Based on the result, the action to be taken is
+ determined by the local policies of the receiver.
+
+4.3. Initial Processing
+
+ If the <domain> is malformed (label longer than 63 characters, zero-
+ length label not at the end, etc.) or is not a fully qualified domain
+ name, or if the DNS lookup returns "domain does not exist" (RCODE 3),
+ check_host() immediately returns the result "None".
+
+ If the <sender> has no localpart, substitute the string "postmaster"
+ for the localpart.
+
+4.4. Record Lookup
+
+ In accordance with how the records are published (see Section 3.1
+ above), a DNS query needs to be made for the <domain> name, querying
+ for either RR type TXT, SPF, or both. If both SPF and TXT RRs are
+ looked up, the queries MAY be done in parallel.
+
+ If all DNS lookups that are made return a server failure (RCODE 2),
+ or other error (RCODE other than 0 or 3), or time out, then
+ check_host() exits immediately with the result "TempError".
+
+4.5. Selecting Records
+
+ Records begin with a version section:
+
+ record = version terms *SP
+ version = "v=spf1"
+
+ Starting with the set of records that were returned by the lookup,
+ record selection proceeds in two steps:
+
+
+
+
+
+Wong & Schlitt Experimental [Page 13]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ 1. Records that do not begin with a version section of exactly
+ "v=spf1" are discarded. Note that the version section is
+ terminated either by an SP character or the end of the record. A
+ record with a version section of "v=spf10" does not match and must
+ be discarded.
+
+ 2. If any records of type SPF are in the set, then all records of
+ type TXT are discarded.
+
+ After the above steps, there should be exactly one record remaining
+ and evaluation can proceed. If there are two or more records
+ remaining, then check_host() exits immediately with the result of
+ "PermError".
+
+ If no matching records are returned, an SPF client MUST assume that
+ the domain makes no SPF declarations. SPF processing MUST stop and
+ return "None".
+
+4.6. Record Evaluation
+
+ After one SPF record has been selected, the check_host() function
+ parses and interprets it to find a result for the current test. If
+ there are any syntax errors, check_host() returns immediately with
+ the result "PermError".
+
+ Implementations MAY choose to parse the entire record first and
+ return "PermError" if the record is not syntactically well formed.
+ However, in all cases, any syntax errors anywhere in the record MUST
+ be detected.
+
+4.6.1. Term Evaluation
+
+ There are two types of terms: mechanisms and modifiers. A record
+ contains an ordered list of these as specified in the following
+ Augmented Backus-Naur Form (ABNF).
+
+ terms = *( 1*SP ( directive / modifier ) )
+
+ directive = [ qualifier ] mechanism
+ qualifier = "+" / "-" / "?" / "~"
+ mechanism = ( all / include
+ / A / MX / PTR / IP4 / IP6 / exists )
+ modifier = redirect / explanation / unknown-modifier
+ unknown-modifier = name "=" macro-string
+
+ name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." )
+
+ Most mechanisms allow a ":" or "/" character after the name.
+
+
+
+Wong & Schlitt Experimental [Page 14]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ Modifiers always contain an equals ('=') character immediately after
+ the name, and before any ":" or "/" characters that may be part of
+ the macro-string.
+
+ Terms that do not contain any of "=", ":", or "/" are mechanisms, as
+ defined in Section 5.
+
+ As per the definition of the ABNF notation in [RFC4234], mechanism
+ and modifier names are case-insensitive.
+
+4.6.2. Mechanisms
+
+ Each mechanism is considered in turn from left to right. If there
+ are no more mechanisms, the result is specified in Section 4.7.
+
+ When a mechanism is evaluated, one of three things can happen: it can
+ match, not match, or throw an exception.
+
+ If it matches, processing ends and the qualifier value is returned as
+ the result of that record. If it does not match, processing
+ continues with the next mechanism. If it throws an exception,
+ mechanism processing ends and the exception value is returned.
+
+ The possible qualifiers, and the results they return are as follows:
+
+ "+" Pass
+ "-" Fail
+ "~" SoftFail
+ "?" Neutral
+
+ The qualifier is optional and defaults to "+".
+
+ When a mechanism matches and the qualifier is "-", then a "Fail"
+ result is returned and the explanation string is computed as
+ described in Section 6.2.
+
+ The specific mechanisms are described in Section 5.
+
+4.6.3. Modifiers
+
+ Modifiers are not mechanisms: they do not return match or not-match.
+ Instead they provide additional information. Although modifiers do
+ not directly affect the evaluation of the record, the "redirect"
+ modifier has an effect after all the mechanisms have been evaluated.
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 15]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+4.7. Default Result
+
+ If none of the mechanisms match and there is no "redirect" modifier,
+ then the check_host() returns a result of "Neutral", just as if
+ "?all" were specified as the last directive. If there is a
+ "redirect" modifier, check_host() proceeds as defined in Section 6.1.
+
+ Note that records SHOULD always use either a "redirect" modifier or
+ an "all" mechanism to explicitly terminate processing.
+
+ For example:
+
+ v=spf1 +mx -all
+ or
+ v=spf1 +mx redirect=_spf.example.com
+
+4.8. Domain Specification
+
+ Several of these mechanisms and modifiers have a <domain-spec>
+ section. The <domain-spec> string is macro expanded (see Section 8).
+ The resulting string is the common presentation form of a fully-
+ qualified DNS name: a series of labels separated by periods. This
+ domain is called the <target-name> in the rest of this document.
+
+ Note: The result of the macro expansion is not subject to any further
+ escaping. Hence, this facility cannot produce all characters that
+ are legal in a DNS label (e.g., the control characters). However,
+ this facility is powerful enough to express legal host names and
+ common utility labels (such as "_spf") that are used in DNS.
+
+ For several mechanisms, the <domain-spec> is optional. If it is not
+ provided, the <domain> is used as the <target-name>.
+
+5. Mechanism Definitions
+
+ This section defines two types of mechanisms.
+
+ Basic mechanisms contribute to the language framework. They do not
+ specify a particular type of authorization scheme.
+
+ all
+ include
+
+ Designated sender mechanisms are used to designate a set of <ip>
+ addresses as being permitted or not permitted to use the <domain> for
+ sending mail.
+
+
+
+
+
+Wong & Schlitt Experimental [Page 16]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ a
+ mx
+ ptr
+ ip4
+ ip6
+ exists
+
+ The following conventions apply to all mechanisms that perform a
+ comparison between <ip> and an IP address at any point:
+
+ If no CIDR-length is given in the directive, then <ip> and the IP
+ address are compared for equality. (Here, CIDR is Classless Inter-
+ Domain Routing.)
+
+ If a CIDR-length is specified, then only the specified number of
+ high-order bits of <ip> and the IP address are compared for equality.
+
+ When any mechanism fetches host addresses to compare with <ip>, when
+ <ip> is an IPv4 address, A records are fetched, when <ip> is an IPv6
+ address, AAAA records are fetched. Even if the SMTP connection is
+ via IPv6, an IPv4-mapped IPv6 IP address (see [RFC3513], Section
+ 2.5.5) MUST still be considered an IPv4 address.
+
+ Several mechanisms rely on information fetched from DNS. For these
+ DNS queries, except where noted, if the DNS server returns an error
+ (RCODE other than 0 or 3) or the query times out, the mechanism
+ throws the exception "TempError". If the server returns "domain does
+ not exist" (RCODE 3), then evaluation of the mechanism continues as
+ if the server returned no error (RCODE 0) and zero answer records.
+
+5.1. "all"
+
+ all = "all"
+
+ The "all" mechanism is a test that always matches. It is used as the
+ rightmost mechanism in a record to provide an explicit default.
+
+ For example:
+
+ v=spf1 a mx -all
+
+ Mechanisms after "all" will never be tested. Any "redirect" modifier
+ (Section 6.1) has no effect when there is an "all" mechanism.
+
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 17]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+5.2. "include"
+
+ include = "include" ":" domain-spec
+
+ The "include" mechanism triggers a recursive evaluation of
+ check_host(). The domain-spec is expanded as per Section 8. Then
+ check_host() is evaluated with the resulting string as the <domain>.
+ The <ip> and <sender> arguments remain the same as in the current
+ evaluation of check_host().
+
+ In hindsight, the name "include" was poorly chosen. Only the
+ evaluated result of the referenced SPF record is used, rather than
+ acting as if the referenced SPF record was literally included in the
+ first. For example, evaluating a "-all" directive in the referenced
+ record does not terminate the overall processing and does not
+ necessarily result in an overall "Fail". (Better names for this
+ mechanism would have been "if-pass", "on-pass", etc.)
+
+ The "include" mechanism makes it possible for one domain to designate
+ multiple administratively-independent domains. For example, a vanity
+ domain "example.net" might send mail using the servers of
+ administratively-independent domains example.com and example.org.
+
+ Example.net could say
+
+ IN TXT "v=spf1 include:example.com include:example.org -all"
+
+ This would direct check_host() to, in effect, check the records of
+ example.com and example.org for a "Pass" result. Only if the host
+ were not permitted for either of those domains would the result be
+ "Fail".
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 18]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ Whether this mechanism matches, does not match, or throws an
+ exception depends on the result of the recursive evaluation of
+ check_host():
+
+ +---------------------------------+---------------------------------+
+ | A recursive check_host() result | Causes the "include" mechanism |
+ | of: | to: |
+ +---------------------------------+---------------------------------+
+ | Pass | match |
+ | | |
+ | Fail | not match |
+ | | |
+ | SoftFail | not match |
+ | | |
+ | Neutral | not match |
+ | | |
+ | TempError | throw TempError |
+ | | |
+ | PermError | throw PermError |
+ | | |
+ | None | throw PermError |
+ +---------------------------------+---------------------------------+
+
+ The "include" mechanism is intended for crossing administrative
+ boundaries. Although it is possible to use includes to consolidate
+ multiple domains that share the same set of designated hosts, domains
+ are encouraged to use redirects where possible, and to minimize the
+ number of includes within a single administrative domain. For
+ example, if example.com and example.org were managed by the same
+ entity, and if the permitted set of hosts for both domains was
+ "mx:example.com", it would be possible for example.org to specify
+ "include:example.com", but it would be preferable to specify
+ "redirect=example.com" or even "mx:example.com".
+
+5.3. "a"
+
+ This mechanism matches if <ip> is one of the <target-name>'s IP
+ addresses.
+
+ A = "a" [ ":" domain-spec ] [ dual-cidr-length ]
+
+ An address lookup is done on the <target-name>. The <ip> is compared
+ to the returned address(es). If any address matches, the mechanism
+ matches.
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 19]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+5.4. "mx"
+
+ This mechanism matches if <ip> is one of the MX hosts for a domain
+ name.
+
+ MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ]
+
+ check_host() first performs an MX lookup on the <target-name>. Then
+ it performs an address lookup on each MX name returned. The <ip> is
+ compared to each returned IP address. To prevent Denial of Service
+ (DoS) attacks, more than 10 MX names MUST NOT be looked up during the
+ evaluation of an "mx" mechanism (see Section 10). If any address
+ matches, the mechanism matches.
+
+ Note regarding implicit MXs: If the <target-name> has no MX records,
+ check_host() MUST NOT pretend the target is its single MX, and MUST
+ NOT default to an A lookup on the <target-name> directly. This
+ behavior breaks with the legacy "implicit MX" rule. See [RFC2821],
+ Section 5. If such behavior is desired, the publisher should specify
+ an "a" directive.
+
+5.5. "ptr"
+
+ This mechanism tests whether the DNS reverse-mapping for <ip> exists
+ and correctly points to a domain name within a particular domain.
+
+ PTR = "ptr" [ ":" domain-spec ]
+
+ First, the <ip>'s name is looked up using this procedure: perform a
+ DNS reverse-mapping for <ip>, looking up the corresponding PTR record
+ in "in-addr.arpa." if the address is an IPv4 one and in "ip6.arpa."
+ if it is an IPv6 address. For each record returned, validate the
+ domain name by looking up its IP address. To prevent DoS attacks,
+ more than 10 PTR names MUST NOT be looked up during the evaluation of
+ a "ptr" mechanism (see Section 10). If <ip> is among the returned IP
+ addresses, then that domain name is validated. In pseudocode:
+
+ sending-domain_names := ptr_lookup(sending-host_IP); if more than 10
+ sending-domain_names are found, use at most 10. for each name in
+ (sending-domain_names) {
+ IP_addresses := a_lookup(name);
+ if the sending-domain_IP is one of the IP_addresses {
+ validated-sending-domain_names += name;
+ } }
+
+ Check all validated domain names to see if they end in the
+ <target-name> domain. If any do, this mechanism matches. If no
+ validated domain name can be found, or if none of the validated
+
+
+
+Wong & Schlitt Experimental [Page 20]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ domain names end in the <target-name>, this mechanism fails to match.
+ If a DNS error occurs while doing the PTR RR lookup, then this
+ mechanism fails to match. If a DNS error occurs while doing an A RR
+ lookup, then that domain name is skipped and the search continues.
+
+ Pseudocode:
+
+ for each name in (validated-sending-domain_names) {
+ if name ends in <domain-spec>, return match.
+ if name is <domain-spec>, return match.
+ }
+ return no-match.
+
+ This mechanism matches if the <target-name> is either an ancestor of
+ a validated domain name or if the <target-name> and a validated
+ domain name are the same. For example: "mail.example.com" is within
+ the domain "example.com", but "mail.bad-example.com" is not.
+
+ Note: Use of this mechanism is discouraged because it is slow, it is
+ not as reliable as other mechanisms in cases of DNS errors, and it
+ places a large burden on the arpa name servers. If used, proper PTR
+ records must be in place for the domain's hosts and the "ptr"
+ mechanism should be one of the last mechanisms checked.
+
+5.6. "ip4" and "ip6"
+
+ These mechanisms test whether <ip> is contained within a given IP
+ network.
+
+ IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ]
+ IP6 = "ip6" ":" ip6-network [ ip6-cidr-length ]
+
+ ip4-cidr-length = "/" 1*DIGIT
+ ip6-cidr-length = "/" 1*DIGIT
+ dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]
+
+ ip4-network = qnum "." qnum "." qnum "." qnum
+ qnum = DIGIT ; 0-9
+ / %x31-39 DIGIT ; 10-99
+ / "1" 2DIGIT ; 100-199
+ / "2" %x30-34 DIGIT ; 200-249
+ / "25" %x30-35 ; 250-255
+ ; as per conventional dotted quad notation. e.g., 192.0.2.0
+ ip6-network = <as per [RFC 3513], section 2.2>
+ ; e.g., 2001:DB8::CD30
+
+ The <ip> is compared to the given network. If CIDR-length high-order
+ bits match, the mechanism matches.
+
+
+
+Wong & Schlitt Experimental [Page 21]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ If ip4-cidr-length is omitted, it is taken to be "/32". If
+ ip6-cidr-length is omitted, it is taken to be "/128". It is not
+ permitted to omit parts of the IP address instead of using CIDR
+ notations. That is, use 192.0.2.0/24 instead of 192.0.2.
+
+5.7. "exists"
+
+ This mechanism is used to construct an arbitrary domain name that is
+ used for a DNS A record query. It allows for complicated schemes
+ involving arbitrary parts of the mail envelope to determine what is
+ permitted.
+
+ exists = "exists" ":" domain-spec
+
+ The domain-spec is expanded as per Section 8. The resulting domain
+ name is used for a DNS A RR lookup. If any A record is returned,
+ this mechanism matches. The lookup type is A even when the
+ connection type is IPv6.
+
+ Domains can use this mechanism to specify arbitrarily complex
+ queries. For example, suppose example.com publishes the record:
+
+ v=spf1 exists:%{ir}.%{l1r+-}._spf.%{d} -all
+
+ The <target-name> might expand to
+ "1.2.0.192.someuser._spf.example.com". This makes fine-grained
+ decisions possible at the level of the user and client IP address.
+
+ This mechanism enables queries that mimic the style of tests that
+ existing anti-spam DNS blacklists (DNSBL) use.
+
+6. Modifier Definitions
+
+ Modifiers are name/value pairs that provide additional information.
+ Modifiers always have an "=" separating the name and the value.
+
+ The modifiers defined in this document ("redirect" and "exp") MAY
+ appear anywhere in the record, but SHOULD appear at the end, after
+ all mechanisms. Ordering of these two modifiers does not matter.
+ These two modifiers MUST NOT appear in a record more than once each.
+ If they do, then check_host() exits with a result of "PermError".
+
+ Unrecognized modifiers MUST be ignored no matter where in a record,
+ or how often. This allows implementations of this document to
+ gracefully handle records with modifiers that are defined in other
+ specifications.
+
+
+
+
+
+Wong & Schlitt Experimental [Page 22]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+6.1. redirect: Redirected Query
+
+ If all mechanisms fail to match, and a "redirect" modifier is
+ present, then processing proceeds as follows:
+
+ redirect = "redirect" "=" domain-spec
+
+ The domain-spec portion of the redirect section is expanded as per
+ the macro rules in Section 8. Then check_host() is evaluated with
+ the resulting string as the <domain>. The <ip> and <sender>
+ arguments remain the same as current evaluation of check_host().
+
+ The result of this new evaluation of check_host() is then considered
+ the result of the current evaluation with the exception that if no
+ SPF record is found, or if the target-name is malformed, the result
+ is a "PermError" rather than "None".
+
+ Note that the newly-queried domain may itself specify redirect
+ processing.
+
+ This facility is intended for use by organizations that wish to apply
+ the same record to multiple domains. For example:
+
+ la.example.com. TXT "v=spf1 redirect=_spf.example.com"
+ ny.example.com. TXT "v=spf1 redirect=_spf.example.com"
+ sf.example.com. TXT "v=spf1 redirect=_spf.example.com"
+ _spf.example.com. TXT "v=spf1 mx:example.com -all"
+
+ In this example, mail from any of the three domains is described by
+ the same record. This can be an administrative advantage.
+
+ Note: In general, the domain "A" cannot reliably use a redirect to
+ another domain "B" not under the same administrative control. Since
+ the <sender> stays the same, there is no guarantee that the record at
+ domain "B" will correctly work for mailboxes in domain "A",
+ especially if domain "B" uses mechanisms involving localparts. An
+ "include" directive may be more appropriate.
+
+ For clarity, it is RECOMMENDED that any "redirect" modifier appear as
+ the very last term in a record.
+
+6.2. exp: Explanation
+
+ explanation = "exp" "=" domain-spec
+
+ If check_host() results in a "Fail" due to a mechanism match (such as
+ "-all"), and the "exp" modifier is present, then the explanation
+ string returned is computed as described below. If no "exp" modifier
+
+
+
+Wong & Schlitt Experimental [Page 23]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ is present, then either a default explanation string or an empty
+ explanation string may be returned.
+
+ The <domain-spec> is macro expanded (see Section 8) and becomes the
+ <target-name>. The DNS TXT record for the <target-name> is fetched.
+
+ If <domain-spec> is empty, or there are any DNS processing errors
+ (any RCODE other than 0), or if no records are returned, or if more
+ than one record is returned, or if there are syntax errors in the
+ explanation string, then proceed as if no exp modifier was given.
+
+ The fetched TXT record's strings are concatenated with no spaces, and
+ then treated as an <explain-string>, which is macro-expanded. This
+ final result is the explanation string. Implementations MAY limit
+ the length of the resulting explanation string to allow for other
+ protocol constraints and/or reasonable processing limits. Since the
+ explanation string is intended for an SMTP response and [RFC2821]
+ Section 2.4 says that responses are in [US-ASCII], the explanation
+ string is also limited to US-ASCII.
+
+ Software evaluating check_host() can use this string to communicate
+ information from the publishing domain in the form of a short message
+ or URL. Software SHOULD make it clear that the explanation string
+ comes from a third party. For example, it can prepend the macro
+ string "%{o} explains: " to the explanation, such as shown in Section
+ 2.5.4.
+
+ Suppose example.com has this record:
+
+ v=spf1 mx -all exp=explain._spf.%{d}
+
+ Here are some examples of possible explanation TXT records at
+ explain._spf.example.com:
+
+ "Mail from example.com should only be sent by its own servers."
+ -- a simple, constant message
+
+ "%{i} is not one of %{d}'s designated mail servers."
+ -- a message with a little more information, including the IP
+ address that failed the check
+
+ "See http://%{d}/why.html?s=%{S}&i=%{I}"
+ -- a complicated example that constructs a URL with the
+ arguments to check_host() so that a web page can be
+ generated with detailed, custom instructions
+
+ Note: During recursion into an "include" mechanism, an exp= modifier
+ from the <target-name> MUST NOT be used. In contrast, when executing
+
+
+
+Wong & Schlitt Experimental [Page 24]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ a "redirect" modifier, an exp= modifier from the original domain MUST
+ NOT be used.
+
+7. The Received-SPF Header Field
+
+ It is RECOMMENDED that SMTP receivers record the result of SPF
+ processing in the message header. If an SMTP receiver chooses to do
+ so, it SHOULD use the "Received-SPF" header field defined here for
+ each identity that was checked. This information is intended for the
+ recipient. (Information intended for the sender is described in
+ Section 6.2, Explanation.)
+
+ The Received-SPF header field is a trace field (see [RFC2822] Section
+ 3.6.7) and SHOULD be prepended to the existing header, above the
+ Received: field that is generated by the SMTP receiver. It MUST
+ appear above all other Received-SPF fields in the message. The
+ header field has the following format:
+
+ header-field = "Received-SPF:" [CFWS] result FWS [comment FWS]
+ [ key-value-list ] CRLF
+
+ result = "Pass" / "Fail" / "SoftFail" / "Neutral" /
+ "None" / "TempError" / "PermError"
+
+ key-value-list = key-value-pair *( ";" [CFWS] key-value-pair )
+ [";"]
+
+ key-value-pair = key [CFWS] "=" ( dot-atom / quoted-string )
+
+ key = "client-ip" / "envelope-from" / "helo" /
+ "problem" / "receiver" / "identity" /
+ mechanism / "x-" name / name
+
+ identity = "mailfrom" ; for the "MAIL FROM" identity
+ / "helo" ; for the "HELO" identity
+ / name ; other identities
+
+ dot-atom = <unquoted word as per [RFC2822]>
+ quoted-string = <quoted string as per [RFC2822]>
+ comment = <comment string as per [RFC2822]>
+ CFWS = <comment or folding white space as per [RFC2822]>
+ FWS = <folding white space as per [RFC2822]>
+ CRLF = <standard end-of-line token as per [RFC2822]>
+
+ The header field SHOULD include a "(...)" style <comment> after the
+ result, conveying supporting information for the result, such as
+ <ip>, <sender>, and <domain>.
+
+
+
+
+Wong & Schlitt Experimental [Page 25]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ The following key-value pairs are designed for later machine parsing.
+ SPF clients SHOULD give enough information so that the SPF results
+ can be verified. That is, at least "client-ip", "helo", and, if the
+ "MAIL FROM" identity was checked, "envelope-from".
+
+ client-ip the IP address of the SMTP client
+
+ envelope-from the envelope sender mailbox
+
+ helo the host name given in the HELO or EHLO command
+
+ mechanism the mechanism that matched (if no mechanisms matched,
+ substitute the word "default")
+
+ problem if an error was returned, details about the error
+
+ receiver the host name of the SPF client
+
+ identity the identity that was checked; see the <identity> ABNF
+ rule
+
+ Other keys may be defined by SPF clients. Until a new key name
+ becomes widely accepted, new key names should start with "x-".
+
+ SPF clients MUST make sure that the Received-SPF header field does
+ not contain invalid characters, is not excessively long, and does not
+ contain malicious data that has been provided by the sender.
+
+ Examples of various header styles that could be generated are the
+ following:
+
+ Received-SPF: Pass (mybox.example.org: domain of
+ myname@example.com designates 192.0.2.1 as permitted sender)
+ receiver=mybox.example.org; client-ip=192.0.2.1;
+ envelope-from=<myname@example.com>; helo=foo.example.com;
+
+ Received-SPF: Fail (mybox.example.org: domain of
+ myname@example.com does not designate
+ 192.0.2.1 as permitted sender)
+ identity=mailfrom; client-ip=192.0.2.1;
+ envelope-from=<myname@example.com>;
+
+
+
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 26]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+8. Macros
+
+8.1. Macro Definitions
+
+ Many mechanisms and modifiers perform macro expansion on part of the
+ term.
+
+ domain-spec = macro-string domain-end
+ domain-end = ( "." toplabel [ "." ] ) / macro-expand
+
+ toplabel = ( *alphanum ALPHA *alphanum ) /
+ ( 1*alphanum "-" *( alphanum / "-" ) alphanum )
+ ; LDH rule plus additional TLD restrictions
+ ; (see [RFC3696], Section 2)
+ alphanum = ALPHA / DIGIT
+
+ explain-string = *( macro-string / SP )
+
+ macro-string = *( macro-expand / macro-literal )
+ macro-expand = ( "%{" macro-letter transformers *delimiter "}" )
+ / "%%" / "%_" / "%-"
+ macro-literal = %x21-24 / %x26-7E
+ ; visible characters except "%"
+ macro-letter = "s" / "l" / "o" / "d" / "i" / "p" / "h" /
+ "c" / "r" / "t"
+ transformers = *DIGIT [ "r" ]
+ delimiter = "." / "-" / "+" / "," / "/" / "_" / "="
+
+ A literal "%" is expressed by "%%".
+
+ "%_" expands to a single " " space.
+ "%-" expands to a URL-encoded space, viz., "%20".
+
+ The following macro letters are expanded in term arguments:
+
+ s = <sender>
+ l = local-part of <sender>
+ o = domain of <sender>
+ d = <domain>
+ i = <ip>
+ p = the validated domain name of <ip>
+ v = the string "in-addr" if <ip> is ipv4, or "ip6" if <ip> is ipv6
+ h = HELO/EHLO domain
+
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 27]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ The following macro letters are allowed only in "exp" text:
+
+ c = SMTP client IP (easily readable format)
+ r = domain name of host performing the check
+ t = current timestamp
+
+ A '%' character not followed by a '{', '%', '-', or '_' character is
+ a syntax error. So
+
+ -exists:%(ir).sbl.spamhaus.example.org
+
+ is incorrect and will cause check_host() to return a "PermError".
+ Instead, say
+
+ -exists:%{ir}.sbl.spamhaus.example.org
+
+ Optional transformers are the following:
+
+ *DIGIT = zero or more digits
+ 'r' = reverse value, splitting on dots by default
+
+ If transformers or delimiters are provided, the replacement value for
+ a macro letter is split into parts. After performing any reversal
+ operation and/or removal of left-hand parts, the parts are rejoined
+ using "." and not the original splitting characters.
+
+ By default, strings are split on "." (dots). Note that no special
+ treatment is given to leading, trailing, or consecutive delimiters,
+ and so the list of parts may contain empty strings. Older
+ implementations of SPF prohibit trailing dots in domain names, so
+ trailing dots should not be published by domain owners, although they
+ must be accepted by implementations conforming to this document.
+ Macros may specify delimiter characters that are used instead of ".".
+
+ The 'r' transformer indicates a reversal operation: if the client IP
+ address were 192.0.2.1, the macro %{i} would expand to "192.0.2.1"
+ and the macro %{ir} would expand to "1.2.0.192".
+
+ The DIGIT transformer indicates the number of right-hand parts to
+ use, after optional reversal. If a DIGIT is specified, the value
+ MUST be nonzero. If no DIGITs are specified, or if the value
+ specifies more parts than are available, all the available parts are
+ used. If the DIGIT was 5, and only 3 parts were available, the macro
+ interpreter would pretend the DIGIT was 3. Implementations MUST
+ support at least a value of 128, as that is the maximum number of
+ labels in a domain name.
+
+
+
+
+
+Wong & Schlitt Experimental [Page 28]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ The "s" macro expands to the <sender> argument. It is an E-Mail
+ address with a localpart, an "@" character, and a domain. The "l"
+ macro expands to just the localpart. The "o" macro expands to just
+ the domain part. Note that these values remain the same during
+ recursive and chained evaluations due to "include" and/or "redirect".
+ Note also that if the original <sender> had no localpart, the
+ localpart was set to "postmaster" in initial processing (see Section
+ 4.3).
+
+ For IPv4 addresses, both the "i" and "c" macros expand to the
+ standard dotted-quad format.
+
+ For IPv6 addresses, the "i" macro expands to a dot-format address; it
+ is intended for use in %{ir}. The "c" macro may expand to any of the
+ hexadecimal colon-format addresses specified in [RFC3513], Section
+ 2.2. It is intended for humans to read.
+
+ The "p" macro expands to the validated domain name of <ip>. The
+ procedure for finding the validated domain name is defined in Section
+ 5.5. If the <domain> is present in the list of validated domains, it
+ SHOULD be used. Otherwise, if a subdomain of the <domain> is
+ present, it SHOULD be used. Otherwise, any name from the list may be
+ used. If there are no validated domain names or if a DNS error
+ occurs, the string "unknown" is used.
+
+ The "r" macro expands to the name of the receiving MTA. This SHOULD
+ be a fully qualified domain name, but if one does not exist (as when
+ the checking is done by a MUA) or if policy restrictions dictate
+ otherwise, the word "unknown" SHOULD be substituted. The domain name
+ may be different from the name found in the MX record that the client
+ MTA used to locate the receiving MTA.
+
+ The "t" macro expands to the decimal representation of the
+ approximate number of seconds since the Epoch (Midnight, January 1,
+ 1970, UTC). This is the same value as is returned by the POSIX
+ time() function in most standards-compliant libraries.
+
+ When the result of macro expansion is used in a domain name query, if
+ the expanded domain name exceeds 253 characters (the maximum length
+ of a domain name), the left side is truncated to fit, by removing
+ successive domain labels until the total length does not exceed 253
+ characters.
+
+ Uppercased macros expand exactly as their lowercased equivalents, and
+ are then URL escaped. URL escaping must be performed for characters
+ not in the "uric" set, which is defined in [RFC3986].
+
+
+
+
+
+Wong & Schlitt Experimental [Page 29]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ Note: Care must be taken so that macro expansion for legitimate
+ E-Mail does not exceed the 63-character limit on DNS labels. The
+ localpart of E-Mail addresses, in particular, can have more than 63
+ characters between dots.
+
+ Note: Domains should avoid using the "s", "l", "o", or "h" macros in
+ conjunction with any mechanism directive. Although these macros are
+ powerful and allow per-user records to be published, they severely
+ limit the ability of implementations to cache results of check_host()
+ and they reduce the effectiveness of DNS caches.
+
+ Implementations should be aware that if no directive processed during
+ the evaluation of check_host() contains an "s", "l", "o", or "h"
+ macro, then the results of the evaluation can be cached on the basis
+ of <domain> and <ip> alone for as long as the shortest Time To Live
+ (TTL) of all the DNS records involved.
+
+8.2. Expansion Examples
+
+ The <sender> is strong-bad@email.example.com.
+ The IPv4 SMTP client IP is 192.0.2.3.
+ The IPv6 SMTP client IP is 2001:DB8::CB01.
+ The PTR domain name of the client IP is mx.example.org.
+
+ macro expansion
+ ------- ----------------------------
+ %{s} strong-bad@email.example.com
+ %{o} email.example.com
+ %{d} email.example.com
+ %{d4} email.example.com
+ %{d3} email.example.com
+ %{d2} example.com
+ %{d1} com
+ %{dr} com.example.email
+ %{d2r} example.email
+ %{l} strong-bad
+ %{l-} strong.bad
+ %{lr} strong-bad
+ %{lr-} bad.strong
+ %{l1r-} strong
+
+
+
+
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 30]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ macro-string expansion
+ --------------------------------------------------------------------
+ %{ir}.%{v}._spf.%{d2} 3.2.0.192.in-addr._spf.example.com
+ %{lr-}.lp._spf.%{d2} bad.strong.lp._spf.example.com
+
+ %{lr-}.lp.%{ir}.%{v}._spf.%{d2}
+ bad.strong.lp.3.2.0.192.in-addr._spf.example.com
+
+ %{ir}.%{v}.%{l1r-}.lp._spf.%{d2}
+ 3.2.0.192.in-addr.strong.lp._spf.example.com
+
+ %{d2}.trusted-domains.example.net
+ example.com.trusted-domains.example.net
+
+ IPv6:
+ %{ir}.%{v}._spf.%{d2} 1.0.B.C.0.0.0.0.
+ 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.B.D.0.1.0.0.2.ip6._spf.example.com
+
+9. Implications
+
+ This section outlines the major implications that adoption of this
+ document will have on various entities involved in Internet E-Mail.
+ It is intended to make clear to the reader where this document
+ knowingly affects the operation of such entities. This section is
+ not a "how-to" manual, or a "best practices" document, and it is not
+ a comprehensive list of what such entities should do in light of this
+ document.
+
+ This section is non-normative.
+
+9.1. Sending Domains
+
+ Domains that wish to be compliant with this specification will need
+ to determine the list of hosts that they allow to use their domain
+ name in the "HELO" and "MAIL FROM" identities. It is recognized that
+ forming such a list is not just a simple technical exercise, but
+ involves policy decisions with both technical and administrative
+ considerations.
+
+ It can be helpful to publish records that include a "tracking
+ exists:" mechanism. By looking at the name server logs, a rough list
+ may then be generated. For example:
+
+ v=spf1 exists:_h.%{h}._l.%{l}._o.%{o}._i.%{i}._spf.%{d} ?all
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 31]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+9.2. Mailing Lists
+
+ Mailing lists must be aware of how they re-inject mail that is sent
+ to the list. Mailing lists MUST comply with the requirements in
+ [RFC2821], Section 3.10, and [RFC1123], Section 5.3.6, that say that
+ the reverse-path MUST be changed to be the mailbox of a person or
+ other entity who administers the list. Whereas the reasons for
+ changing the reverse-path are many and long-standing, SPF adds
+ enforcement to this requirement.
+
+ In practice, almost all mailing list software in use already complies
+ with this requirement. Mailing lists that do not comply may or may
+ not encounter problems depending on how access to the list is
+ restricted. Such lists that are entirely internal to a domain (only
+ people in the domain can send to or receive from the list) are not
+ affected.
+
+9.3. Forwarding Services and Aliases
+
+ Forwarding services take mail that is received at a mailbox and
+ direct it to some external mailbox. At the time of this writing, the
+ near-universal practice of such services is to use the original "MAIL
+ FROM" of a message when re-injecting it for delivery to the external
+ mailbox. [RFC1123] and [RFC2821] describe this action as an "alias"
+ rather than a "mail list". This means that the external mailbox's
+ MTA sees all such mail in a connection from a host of the forwarding
+ service, and so the "MAIL FROM" identity will not, in general, pass
+ authorization.
+
+ There are three places that techniques can be used to ameliorate this
+ problem.
+
+ 1. The beginning, when E-Mail is first sent.
+
+ 1. "Neutral" results could be given for IP addresses that may be
+ forwarders, instead of "Fail" results. For example:
+
+ "v=spf1 mx -exists:%{ir}.sbl.spamhaus.example.org ?all"
+
+ This would cause a lookup on an anti-spam DNS blacklist
+ (DNSBL) and cause a result of "Fail" only for E-Mail coming
+ from listed sources. All other E-Mail, including E-Mail sent
+ through forwarders, would receive a "Neutral" result. By
+ checking the DNSBL after the known good sources, problems with
+ incorrect listing on the DNSBL are greatly reduced.
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 32]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ 2. The "MAIL FROM" identity could have additional information in
+ the localpart that cryptographically identifies the mail as
+ coming from an authorized source. In this case, such an SPF
+ record could be used:
+
+ "v=spf1 mx exists:%{l}._spf_verify.%{d} -all"
+
+ Then, a specialized DNS server can be set up to serve the
+ _spf_verify subdomain that validates the localpart. Although
+ this requires an extra DNS lookup, this happens only when the
+ E-Mail would otherwise be rejected as not coming from a known
+ good source.
+
+ Note that due to the 63-character limit for domain labels,
+ this approach only works reliably if the localpart signature
+ scheme is guaranteed either to only produce localparts with a
+ maximum of 63 characters or to gracefully handle truncated
+ localparts.
+
+ 3. Similarly, a specialized DNS server could be set up that will
+ rate-limit the E-Mail coming from unexpected IP addresses.
+
+ "v=spf1 mx exists:%{ir}._spf_rate.%{d} -all"
+
+ 4. SPF allows the creation of per-user policies for special
+ cases. For example, the following SPF record and appropriate
+ wildcard DNS records can be used:
+
+ "v=spf1 mx redirect=%{l1r+}._at_.%{o}._spf.%{d}"
+
+ 2. The middle, when E-Mail is forwarded.
+
+ 1. Forwarding services can solve the problem by rewriting the
+ "MAIL FROM" to be in their own domain. This means that mail
+ bounced from the external mailbox will have to be re-bounced
+ by the forwarding service. Various schemes to do this exist
+ though they vary widely in complexity and resource
+ requirements on the part of the forwarding service.
+
+ 2. Several popular MTAs can be forced from "alias" semantics to
+ "mailing list" semantics by configuring an additional alias
+ with "owner-" prepended to the original alias name (e.g., an
+ alias of "friends: george@example.com, fred@example.org" would
+ need another alias of the form "owner-friends: localowner").
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 33]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ 3. The end, when E-Mail is received.
+
+ 1. If the owner of the external mailbox wishes to trust the
+ forwarding service, he can direct the external mailbox's MTA
+ to skip SPF tests when the client host belongs to the
+ forwarding service.
+
+ 2. Tests against other identities, such as the "HELO" identity,
+ may be used to override a failed test against the "MAIL FROM"
+ identity.
+
+ 3. For larger domains, it may not be possible to have a complete
+ or accurate list of forwarding services used by the owners of
+ the domain's mailboxes. In such cases, whitelists of
+ generally-recognized forwarding services could be employed.
+
+9.4. Mail Services
+
+ Service providers that offer mail services to third-party domains,
+ such as sending of bulk mail, may want to adjust their setup in light
+ of the authorization check described in this document. If the "MAIL
+ FROM" identity used for such E-Mail uses the domain of the service
+ provider, then the provider needs only to ensure that its sending
+ host is authorized by its own SPF record, if any.
+
+ If the "MAIL FROM" identity does not use the mail service provider's
+ domain, then extra care must be taken. The SPF record format has
+ several options for the third-party domain to authorize the service
+ provider's MTAs to send mail on its behalf. For mail service
+ providers, such as ISPs, that have a wide variety of customers using
+ the same MTA, steps should be taken to prevent cross-customer forgery
+ (see Section 10.4).
+
+9.5. MTA Relays
+
+ The authorization check generally precludes the use of arbitrary MTA
+ relays between sender and receiver of an E-Mail message.
+
+ Within an organization, MTA relays can be effectively deployed.
+ However, for purposes of this document, such relays are effectively
+ transparent. The SPF authorization check is a check between border
+ MTAs of different domains.
+
+ For mail senders, this means that published SPF records must
+ authorize any MTAs that actually send across the Internet. Usually,
+ these are just the border MTAs as internal MTAs simply forward mail
+ to these MTAs for delivery.
+
+
+
+
+Wong & Schlitt Experimental [Page 34]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ Mail receivers will generally want to perform the authorization check
+ at the border MTAs, specifically including all secondary MXs. This
+ allows mail that fails to be rejected during the SMTP session rather
+ than bounced. Internal MTAs then do not perform the authorization
+ test. To perform the authorization test other than at the border,
+ the host that first transferred the message to the organization must
+ be determined, which can be difficult to extract from the message
+ header. Testing other than at the border is not recommended.
+
+10. Security Considerations
+
+10.1. Processing Limits
+
+ As with most aspects of E-Mail, there are a number of ways that
+ malicious parties could use the protocol as an avenue for a
+ Denial-of-Service (DoS) attack. The processing limits outlined here
+ are designed to prevent attacks such as the following:
+
+ o A malicious party could create an SPF record with many references
+ to a victim's domain and send many E-Mails to different SPF
+ clients; those SPF clients would then create a DoS attack. In
+ effect, the SPF clients are being used to amplify the attacker's
+ bandwidth by using fewer bytes in the SMTP session than are used
+ by the DNS queries. Using SPF clients also allows the attacker to
+ hide the true source of the attack.
+
+ o Whereas implementations of check_host() are supposed to limit the
+ number of DNS lookups, malicious domains could publish records
+ that exceed these limits in an attempt to waste computation effort
+ at their targets when they send them mail. Malicious domains
+ could also design SPF records that cause particular
+ implementations to use excessive memory or CPU usage, or to
+ trigger bugs.
+
+ o Malicious parties could send a large volume of mail purporting to
+ come from the intended target to a wide variety of legitimate mail
+ hosts. These legitimate machines would then present a DNS load on
+ the target as they fetched the relevant records.
+
+ Of these, the case of a third party referenced in the SPF record is
+ the easiest for a DoS attack to effectively exploit. As a result,
+ limits that may seem reasonable for an individual mail server can
+ still allow an unreasonable amount of bandwidth amplification.
+ Therefore, the processing limits need to be quite low.
+
+ SPF implementations MUST limit the number of mechanisms and modifiers
+ that do DNS lookups to at most 10 per SPF check, including any
+ lookups caused by the use of the "include" mechanism or the
+
+
+
+Wong & Schlitt Experimental [Page 35]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ "redirect" modifier. If this number is exceeded during a check, a
+ PermError MUST be returned. The "include", "a", "mx", "ptr", and
+ "exists" mechanisms as well as the "redirect" modifier do count
+ against this limit. The "all", "ip4", and "ip6" mechanisms do not
+ require DNS lookups and therefore do not count against this limit.
+ The "exp" modifier does not count against this limit because the DNS
+ lookup to fetch the explanation string occurs after the SPF record
+ has been evaluated.
+
+ When evaluating the "mx" and "ptr" mechanisms, or the %{p} macro,
+ there MUST be a limit of no more than 10 MX or PTR RRs looked up and
+ checked.
+
+ SPF implementations SHOULD limit the total amount of data obtained
+ from the DNS queries. For example, when DNS over TCP or EDNS0 are
+ available, there may need to be an explicit limit to how much data
+ will be accepted to prevent excessive bandwidth usage or memory usage
+ and DoS attacks.
+
+ MTAs or other processors MAY also impose a limit on the maximum
+ amount of elapsed time to evaluate check_host(). Such a limit SHOULD
+ allow at least 20 seconds. If such a limit is exceeded, the result
+ of authorization SHOULD be "TempError".
+
+ Domains publishing records SHOULD try to keep the number of "include"
+ mechanisms and chained "redirect" modifiers to a minimum. Domains
+ SHOULD also try to minimize the amount of other DNS information
+ needed to evaluate a record. This can be done by choosing directives
+ that require less DNS information and placing lower-cost mechanisms
+ earlier in the SPF record.
+
+ For example, consider a domain set up as follows:
+
+ example.com. IN MX 10 mx.example.com.
+ mx.example.com. IN A 192.0.2.1
+ a.example.com. IN TXT "v=spf1 mx:example.com -all"
+ b.example.com. IN TXT "v=spf1 a:mx.example.com -all"
+ c.example.com. IN TXT "v=spf1 ip4:192.0.2.1 -all"
+
+ Evaluating check_host() for the domain "a.example.com" requires the
+ MX records for "example.com", and then the A records for the listed
+ hosts. Evaluating for "b.example.com" requires only the A records.
+ Evaluating for "c.example.com" requires none.
+
+ However, there may be administrative considerations: using "a" over
+ "ip4" allows hosts to be renumbered easily. Using "mx" over "a"
+ allows the set of mail hosts to be changed easily.
+
+
+
+
+Wong & Schlitt Experimental [Page 36]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+10.2. SPF-Authorized E-Mail May Contain Other False Identities
+
+ The "MAIL FROM" and "HELO" identity authorizations must not be
+ construed to provide more assurance than they do. It is entirely
+ possible for a malicious sender to inject a message using his own
+ domain in the identities used by SPF, to have that domain's SPF
+ record authorize the sending host, and yet the message can easily
+ list other identities in its header. Unless the user or the MUA
+ takes care to note that the authorized identity does not match the
+ other more commonly-presented identities (such as the From: header
+ field), the user may be lulled into a false sense of security.
+
+10.3. Spoofed DNS and IP Data
+
+ There are two aspects of this protocol that malicious parties could
+ exploit to undermine the validity of the check_host() function:
+
+ o The evaluation of check_host() relies heavily on DNS. A malicious
+ attacker could attack the DNS infrastructure and cause
+ check_host() to see spoofed DNS data, and then return incorrect
+ results. This could include returning "Pass" for an <ip> value
+ where the actual domain's record would evaluate to "Fail". See
+ [RFC3833] for a description of DNS weaknesses.
+
+ o The client IP address, <ip>, is assumed to be correct. A
+ malicious attacker could spoof TCP sequence numbers to make mail
+ appear to come from a permitted host for a domain that the
+ attacker is impersonating.
+
+10.4. Cross-User Forgery
+
+ By definition, SPF policies just map domain names to sets of
+ authorized MTAs, not whole E-Mail addresses to sets of authorized
+ users. Although the "l" macro (Section 8) provides a limited way to
+ define individual sets of authorized MTAs for specific E-Mail
+ addresses, it is generally impossible to verify, through SPF, the use
+ of specific E-Mail addresses by individual users of the same MTA.
+
+ It is up to mail services and their MTAs to directly prevent
+ cross-user forgery: based on SMTP AUTH ([RFC2554]), users should be
+ restricted to using only those E-Mail addresses that are actually
+ under their control (see [RFC4409], Section 6.1). Another means to
+ verify the identity of individual users is message cryptography such
+ as PGP ([RFC2440]) or S/MIME ([RFC3851]).
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 37]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+10.5. Untrusted Information Sources
+
+ SPF uses information supplied by third parties, such as the "HELO"
+ domain name, the "MAIL FROM" address, and SPF records. This
+ information is then passed to the receiver in the Received-SPF: trace
+ fields and possibly returned to the client MTA in the form of an SMTP
+ rejection message. This information must be checked for invalid
+ characters and excessively long lines.
+
+ When the authorization check fails, an explanation string may be
+ included in the reject response. Both the sender and the rejecting
+ receiver need to be aware that the explanation was determined by the
+ publisher of the SPF record checked and, in general, not the
+ receiver. The explanation may contain malicious URLs, or it may be
+ offensive or misleading.
+
+ This is probably less of a concern than it may initially seem since
+ such messages are returned to the sender, and the explanation strings
+ come from the sender policy published by the domain in the identity
+ claimed by that very sender. As long as the DSN is not redirected to
+ someone other than the actual sender, the only people who see
+ malicious explanation strings are people whose messages claim to be
+ from domains that publish such strings in their SPF records. In
+ practice, DSNs can be misdirected, such as when an MTA accepts an
+ E-Mail and then later generates a DSN to a forged address, or when an
+ E-Mail forwarder does not direct the DSN back to the original sender.
+
+10.6. Privacy Exposure
+
+ Checking SPF records causes DNS queries to be sent to the domain
+ owner. These DNS queries, especially if they are caused by the
+ "exists" mechanism, can contain information about who is sending
+ E-Mail and likely to which MTA the E-Mail is being sent. This can
+ introduce some privacy concerns, which may be more or less of an
+ issue depending on local laws and the relationship between the domain
+ owner and the person sending the E-Mail.
+
+11. Contributors and Acknowledgements
+
+ This document is largely based on the work of Meng Weng Wong and Mark
+ Lentczner. Although, as this section acknowledges, many people have
+ contributed to this document, a very large portion of the writing and
+ editing are due to Meng and Mark.
+
+ This design owes a debt of parentage to [RMX] by Hadmut Danisch and
+ to [DMP] by Gordon Fecyk. The idea of using a DNS record to check
+ the legitimacy of an E-Mail address traces its ancestry further back
+ through messages on the namedroppers mailing list by Paul Vixie
+
+
+
+Wong & Schlitt Experimental [Page 38]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ [Vixie] (based on suggestion by Jim Miller) and by David Green
+ [Green].
+
+ Philip Gladstone contributed the concept of macros to the
+ specification, multiplying the expressiveness of the language and
+ making per-user and per-IP lookups possible.
+
+ The authors would also like to thank the literally hundreds of
+ individuals who have participated in the development of this design.
+ They are far too numerous to name, but they include the following:
+
+ The folks on the spf-discuss mailing list.
+ The folks on the SPAM-L mailing list.
+ The folks on the IRTF ASRG mailing list.
+ The folks on the IETF MARID mailing list.
+ The folks on #perl.
+
+12. IANA Considerations
+
+12.1. The SPF DNS Record Type
+
+ The IANA has assigned a new Resource Record Type and Qtype from the
+ DNS Parameters Registry for the SPF RR type with code 99.
+
+12.2. The Received-SPF Mail Header Field
+
+ Per [RFC3864], the "Received-SPF:" header field is added to the IANA
+ Permanent Message Header Field Registry. The following is the
+ registration template:
+
+ Header field name: Received-SPF
+ Applicable protocol: mail ([RFC2822])
+ Status: Experimental
+ Author/Change controller: IETF
+ Specification document(s): RFC 4408
+ Related information:
+ Requesting SPF Council review of any proposed changes and
+ additions to this field are recommended. For information about
+ the SPF Council see http://www.openspf.org/Council
+
+13. References
+
+13.1. Normative References
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+
+
+
+
+Wong & Schlitt Experimental [Page 39]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ [RFC1123] Braden, R., "Requirements for Internet Hosts - Application
+ and Support", STD 3, RFC 1123, October 1989.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2821] Klensin, J., "Simple Mail Transfer Protocol", RFC 2821,
+ April 2001.
+
+ [RFC2822] Resnick, P., "Internet Message Format", RFC 2822, April
+ 2001.
+
+ [RFC3464] Moore, K. and G. Vaudreuil, "An Extensible Message Format
+ for Delivery Status Notifications", RFC 3464, January
+ 2003.
+
+ [RFC3513] Hinden, R. and S. Deering, "Internet Protocol Version 6
+ (IPv6) Addressing Architecture", RFC 3513, April 2003.
+
+ [RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration
+ Procedures for Message Header Fields", BCP 90, RFC 3864,
+ September 2004.
+
+ [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
+ Resource Identifier (URI): Generic Syntax", STD 66, RFC
+ 3986, January 2005.
+
+ [RFC4234] Crocker, D. and P. Overell, "Augmented BNF for Syntax
+ Specifications: ABNF", RFC 4234, October 2005.
+
+ [US-ASCII] American National Standards Institute (formerly United
+ States of America Standards Institute), "USA Code for
+ Information Interchange, X3.4", 1968.
+
+ ANSI X3.4-1968 has been replaced by newer versions with slight
+ modifications, but the 1968 version remains definitive for
+ the Internet.
+
+13.2 Informative References
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [RFC1983] Malkin, G., "Internet Users' Glossary", RFC 1983, August
+ 1996.
+
+ [RFC2440] Callas, J., Donnerhacke, L., Finney, H., and R. Thayer,
+ "OpenPGP Message Format", RFC 2440, November 1998.
+
+
+
+Wong & Schlitt Experimental [Page 40]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ [RFC2554] Myers, J., "SMTP Service Extension for Authentication",
+ RFC 2554, March 1999.
+
+ [RFC3696] Klensin, J., "Application Techniques for Checking and
+ Transformation of Names", RFC 3696, February 2004.
+
+ [RFC3833] Atkins, D. and R. Austein, "Threat Analysis of the Domain
+ Name System (DNS)", RFC 3833, August 2004.
+
+ [RFC3851] Ramsdell, B., "Secure/Multipurpose Internet Mail
+ Extensions (S/MIME) Version 3.1 Message Specification",
+ RFC 3851, July 2004.
+
+ [RFC4409] Gellens, R. and J. Klensin, "Message Submission for Mail",
+ RFC 4409, April 2006.
+
+ [RMX] Danish, H., "The RMX DNS RR Type for light weight sender
+ authentication", Work In Progress
+
+ [DMP] Fecyk, G., "Designated Mailers Protocol", Work In Progress
+
+ [Vixie] Vixie, P., "Repudiating MAIL FROM", 2002.
+
+ [Green] Green, D., "Domain-Authorized SMTP Mail", 2002.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 41]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+Appendix A. Collected ABNF
+
+ This section is normative and any discrepancies with the ABNF
+ fragments in the preceding text are to be resolved in favor of this
+ grammar.
+
+ See [RFC4234] for ABNF notation. Please note that as per this ABNF
+ definition, literal text strings (those in quotes) are case-
+ insensitive. Hence, "mx" matches "mx", "MX", "mX", and "Mx".
+
+ record = version terms *SP
+ version = "v=spf1"
+
+ terms = *( 1*SP ( directive / modifier ) )
+
+ directive = [ qualifier ] mechanism
+ qualifier = "+" / "-" / "?" / "~"
+ mechanism = ( all / include
+ / A / MX / PTR / IP4 / IP6 / exists )
+
+ all = "all"
+ include = "include" ":" domain-spec
+ A = "a" [ ":" domain-spec ] [ dual-cidr-length ]
+ MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ]
+ PTR = "ptr" [ ":" domain-spec ]
+ IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ]
+ IP6 = "ip6" ":" ip6-network [ ip6-cidr-length ]
+ exists = "exists" ":" domain-spec
+
+ modifier = redirect / explanation / unknown-modifier
+ redirect = "redirect" "=" domain-spec
+ explanation = "exp" "=" domain-spec
+ unknown-modifier = name "=" macro-string
+
+ ip4-cidr-length = "/" 1*DIGIT
+ ip6-cidr-length = "/" 1*DIGIT
+ dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]
+
+ ip4-network = qnum "." qnum "." qnum "." qnum
+ qnum = DIGIT ; 0-9
+ / %x31-39 DIGIT ; 10-99
+ / "1" 2DIGIT ; 100-199
+ / "2" %x30-34 DIGIT ; 200-249
+ / "25" %x30-35 ; 250-255
+ ; conventional dotted quad notation. e.g., 192.0.2.0
+ ip6-network = <as per [RFC 3513], section 2.2>
+ ; e.g., 2001:DB8::CD30
+
+
+
+
+Wong & Schlitt Experimental [Page 42]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ domain-spec = macro-string domain-end
+ domain-end = ( "." toplabel [ "." ] ) / macro-expand
+ toplabel = ( *alphanum ALPHA *alphanum ) /
+ ( 1*alphanum "-" *( alphanum / "-" ) alphanum )
+ ; LDH rule plus additional TLD restrictions
+ ; (see [RFC3696], Section 2)
+
+ alphanum = ALPHA / DIGIT
+
+ explain-string = *( macro-string / SP )
+
+ macro-string = *( macro-expand / macro-literal )
+ macro-expand = ( "%{" macro-letter transformers *delimiter "}" )
+ / "%%" / "%_" / "%-"
+ macro-literal = %x21-24 / %x26-7E
+ ; visible characters except "%"
+ macro-letter = "s" / "l" / "o" / "d" / "i" / "p" / "h" /
+ "c" / "r" / "t"
+ transformers = *DIGIT [ "r" ]
+ delimiter = "." / "-" / "+" / "," / "/" / "_" / "="
+
+ name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." )
+
+ header-field = "Received-SPF:" [CFWS] result FWS [comment FWS]
+ [ key-value-list ] CRLF
+
+ result = "Pass" / "Fail" / "SoftFail" / "Neutral" /
+ "None" / "TempError" / "PermError"
+
+ key-value-list = key-value-pair *( ";" [CFWS] key-value-pair )
+ [";"]
+
+ key-value-pair = key [CFWS] "=" ( dot-atom / quoted-string )
+
+ key = "client-ip" / "envelope-from" / "helo" /
+ "problem" / "receiver" / "identity" /
+ mechanism / "x-" name / name
+
+ identity = "mailfrom" ; for the "MAIL FROM" identity
+ / "helo" ; for the "HELO" identity
+ / name ; other identities
+
+ dot-atom = <unquoted word as per [RFC2822]>
+ quoted-string = <quoted string as per [RFC2822]>
+ comment = <comment string as per [RFC2822]>
+ CFWS = <comment or folding white space as per [RFC2822]>
+ FWS = <folding white space as per [RFC2822]>
+ CRLF = <standard end-of-line token as per [RFC2822]>
+
+
+
+Wong & Schlitt Experimental [Page 43]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+Appendix B. Extended Examples
+
+ These examples are based on the following DNS setup:
+
+ ; A domain with two mail servers, two hosts
+ ; and two servers at the domain name
+ $ORIGIN example.com.
+ @ MX 10 mail-a
+ MX 20 mail-b
+ A 192.0.2.10
+ A 192.0.2.11
+ amy A 192.0.2.65
+ bob A 192.0.2.66
+ mail-a A 192.0.2.129
+ mail-b A 192.0.2.130
+ www CNAME example.com.
+
+ ; A related domain
+ $ORIGIN example.org.
+ @ MX 10 mail-c
+ mail-c A 192.0.2.140
+
+ ; The reverse IP for those addresses
+ $ORIGIN 2.0.192.in-addr.arpa.
+ 10 PTR example.com.
+ 11 PTR example.com.
+ 65 PTR amy.example.com.
+ 66 PTR bob.example.com.
+ 129 PTR mail-a.example.com.
+ 130 PTR mail-b.example.com.
+ 140 PTR mail-c.example.org.
+
+ ; A rogue reverse IP domain that claims to be
+ ; something it's not
+ $ORIGIN 0.0.10.in-addr.arpa.
+ 4 PTR bob.example.com.
+
+B.1. Simple Examples
+
+ These examples show various possible published records for
+ example.com and which values if <ip> would cause check_host() to
+ return "Pass". Note that <domain> is "example.com".
+
+ v=spf1 +all
+ -- any <ip> passes
+
+ v=spf1 a -all
+ -- hosts 192.0.2.10 and 192.0.2.11 pass
+
+
+
+Wong & Schlitt Experimental [Page 44]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+ v=spf1 a:example.org -all
+ -- no sending hosts pass since example.org has no A records
+
+ v=spf1 mx -all
+ -- sending hosts 192.0.2.129 and 192.0.2.130 pass
+
+ v=spf1 mx:example.org -all
+ -- sending host 192.0.2.140 passes
+
+ v=spf1 mx mx:example.org -all
+ -- sending hosts 192.0.2.129, 192.0.2.130, and 192.0.2.140 pass
+
+ v=spf1 mx/30 mx:example.org/30 -all
+ -- any sending host in 192.0.2.128/30 or 192.0.2.140/30 passes
+
+ v=spf1 ptr -all
+ -- sending host 192.0.2.65 passes (reverse DNS is valid and is in
+ example.com)
+ -- sending host 192.0.2.140 fails (reverse DNS is valid, but not
+ in example.com)
+ -- sending host 10.0.0.4 fails (reverse IP is not valid)
+
+ v=spf1 ip4:192.0.2.128/28 -all
+ -- sending host 192.0.2.65 fails
+ -- sending host 192.0.2.129 passes
+
+B.2. Multiple Domain Example
+
+ These examples show the effect of related records:
+
+ example.org: "v=spf1 include:example.com include:example.net -all"
+
+ This record would be used if mail from example.org actually came
+ through servers at example.com and example.net. Example.org's
+ designated servers are the union of example.com's and example.net's
+ designated servers.
+
+ la.example.org: "v=spf1 redirect=example.org"
+ ny.example.org: "v=spf1 redirect=example.org"
+ sf.example.org: "v=spf1 redirect=example.org"
+
+ These records allow a set of domains that all use the same mail
+ system to make use of that mail system's record. In this way, only
+ the mail system's record needs to be updated when the mail setup
+ changes. These domains' records never have to change.
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 45]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+B.3. DNSBL Style Example
+
+ Imagine that, in addition to the domain records listed above, there
+ are these:
+
+ $ORIGIN _spf.example.com. mary.mobile-users A
+ 127.0.0.2 fred.mobile-users A 127.0.0.2
+ 15.15.168.192.joel.remote-users A 127.0.0.2
+ 16.15.168.192.joel.remote-users A 127.0.0.2
+
+ The following records describe users at example.com who mail from
+ arbitrary servers, or who mail from personal servers.
+
+ example.com:
+
+ v=spf1 mx
+ include:mobile-users._spf.%{d}
+ include:remote-users._spf.%{d}
+ -all
+
+ mobile-users._spf.example.com:
+
+ v=spf1 exists:%{l1r+}.%{d}
+
+ remote-users._spf.example.com:
+
+ v=spf1 exists:%{ir}.%{l1r+}.%{d}
+
+B.4. Multiple Requirements Example
+
+ Say that your sender policy requires both that the IP address is
+ within a certain range and that the reverse DNS for the IP matches.
+ This can be done several ways, including the following:
+
+ example.com. SPF ( "v=spf1 "
+ "-include:ip4._spf.%{d} "
+ "-include:ptr._spf.%{d} "
+ "+all" )
+ ip4._spf.example.com. SPF "v=spf1 -ip4:192.0.2.0/24 +all"
+ ptr._spf.example.com. SPF "v=spf1 -ptr +all"
+
+ This example shows how the "-include" mechanism can be useful, how an
+ SPF record that ends in "+all" can be very restrictive, and the use
+ of De Morgan's Law.
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 46]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+Authors' Addresses
+
+ Meng Weng Wong
+ Singapore
+
+ EMail: mengwong+spf@pobox.com
+
+
+ Wayne Schlitt
+ 4615 Meredeth #9
+ Lincoln Nebraska, NE 68506
+ United States of America
+
+ EMail: wayne@schlitt.net
+ URI: http://www.schlitt.net/spf/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 47]
+
+RFC 4408 Sender Policy Framework (SPF) April 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Wong & Schlitt Experimental [Page 48]
+
diff --git a/doc/rfc/rfc4431.txt b/doc/rfc/rfc4431.txt
new file mode 100644
index 0000000..8b38872
--- /dev/null
+++ b/doc/rfc/rfc4431.txt
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+Network Working Group M. Andrews
+Request for Comments: 4431 Internet Systems Consortium
+Category: Informational S. Weiler
+ SPARTA, Inc.
+ February 2006
+
+
+ The DNSSEC Lookaside Validation (DLV) DNS Resource Record
+
+Status of This Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ This document defines a new DNS resource record, called the DNSSEC
+ Lookaside Validation (DLV) RR, for publishing DNSSEC trust anchors
+ outside of the DNS delegation chain.
+
+1. Introduction
+
+ DNSSEC [1] [2] [3] authenticates DNS data by building public-key
+ signature chains along the DNS delegation chain from a trust anchor,
+ ideally a trust anchor for the DNS root.
+
+ This document defines a new resource record for publishing such trust
+ anchors outside of the DNS's normal delegation chain. Use of these
+ records by DNSSEC validators is outside the scope of this document,
+ but it is expected that these records will help resolvers validate
+ DNSSEC-signed data from zones whose ancestors either aren't signed or
+ refuse to publish delegation signer (DS) records for their children.
+
+2. DLV Resource Record
+
+ The DLV resource record has exactly the same wire and presentation
+ formats as the DS resource record, defined in RFC 4034, Section 5.
+ It uses the same IANA-assigned values in the algorithm and digest
+ type fields as the DS record. (Those IANA registries are known as
+ the "DNS Security Algorithm Numbers" and "DS RR Type Algorithm
+ Numbers" registries.)
+
+
+
+
+
+Andrews & Weiler Informational [Page 1]
+
+RFC 4431 DLV Resource Record February 2006
+
+
+ The DLV record is a normal DNS record type without any special
+ processing requirements. In particular, the DLV record does not
+ inherit any of the special processing or handling requirements of the
+ DS record type (described in Section 3.1.4.1 of RFC 4035). Unlike
+ the DS record, the DLV record may not appear on the parent's side of
+ a zone cut. A DLV record may, however, appear at the apex of a zone.
+
+3. Security Considerations
+
+ For authoritative servers and resolvers that do not attempt to use
+ DLV RRs as part of DNSSEC validation, there are no particular
+ security concerns -- DLV RRs are just like any other DNS data.
+
+ Software using DLV RRs as part of DNSSEC validation will almost
+ certainly want to impose constraints on their use, but those
+ constraints are best left to be described by the documents that more
+ fully describe the particulars of how the records are used. At a
+ minimum, it would be unwise to use the records without some sort of
+ cryptographic authentication. More likely than not, DNSSEC itself
+ will be used to authenticate the DLV RRs. Depending on how a DLV RR
+ is used, failure to properly authenticate it could lead to
+ significant additional security problems including failure to detect
+ spoofed DNS data.
+
+ RFC 4034, Section 8, describes security considerations specific to
+ the DS RR. Those considerations are equally applicable to DLV RRs.
+ Of particular note, the key tag field is used to help select DNSKEY
+ RRs efficiently, but it does not uniquely identify a single DNSKEY
+ RR. It is possible for two distinct DNSKEY RRs to have the same
+ owner name, the same algorithm type, and the same key tag. An
+ implementation that uses only the key tag to select a DNSKEY RR might
+ select the wrong public key in some circumstances.
+
+ For further discussion of the security implications of DNSSEC, see
+ RFC 4033, RFC 4034, and RFC 4035.
+
+4. IANA Considerations
+
+ IANA has assigned DNS type code 32769 to the DLV resource record from
+ the Specification Required portion of the DNS Resource Record Type
+ registry, as defined in [4].
+
+ The DLV resource record reuses the same algorithm and digest type
+ registries already used for the DS resource record, currently known
+ as the "DNS Security Algorithm Numbers" and "DS RR Type Algorithm
+ Numbers" registries.
+
+
+
+
+
+Andrews & Weiler Informational [Page 2]
+
+RFC 4431 DLV Resource Record February 2006
+
+
+5. Normative References
+
+ [1] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033,
+ March 2005.
+
+ [2] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+ [3] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Protocol Modifications for the DNS Security Extensions",
+ RFC 4035, March 2005.
+
+ [4] Eastlake, D., Brunner-Williams, E., and B. Manning, "Domain Name
+ System (DNS) IANA Considerations", BCP 42, RFC 2929,
+ September 2000.
+
+Authors' Addresses
+
+ Mark Andrews
+ Internet Systems Consortium
+ 950 Charter St.
+ Redwood City, CA 94063
+ US
+
+ EMail: Mark_Andrews@isc.org
+
+
+ Samuel Weiler
+ SPARTA, Inc.
+ 7075 Samuel Morse Drive
+ Columbia, Maryland 21046
+ US
+
+ EMail: weiler@tislabs.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Andrews & Weiler Informational [Page 3]
+
+RFC 4431 DLV Resource Record February 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Andrews & Weiler Informational [Page 4]
+
diff --git a/doc/rfc/rfc4470.txt b/doc/rfc/rfc4470.txt
new file mode 100644
index 0000000..ac12d65
--- /dev/null
+++ b/doc/rfc/rfc4470.txt
@@ -0,0 +1,451 @@
+
+
+
+
+
+
+Network Working Group S. Weiler
+Request for Comments: 4470 SPARTA, Inc.
+Updates: 4035, 4034 J. Ihren
+Category: Standards Track Autonomica AB
+ April 2006
+
+
+ Minimally Covering NSEC Records and DNSSEC On-line Signing
+
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ This document describes how to construct DNSSEC NSEC resource records
+ that cover a smaller range of names than called for by RFC 4034. By
+ generating and signing these records on demand, authoritative name
+ servers can effectively stop the disclosure of zone contents
+ otherwise made possible by walking the chain of NSEC records in a
+ signed zone.
+
+Table of Contents
+
+ 1. Introduction ....................................................1
+ 2. Applicability of This Technique .................................2
+ 3. Minimally Covering NSEC Records .................................2
+ 4. Better Epsilon Functions ........................................4
+ 5. Security Considerations .........................................5
+ 6. Acknowledgements ................................................6
+ 7. Normative References ............................................6
+
+1. Introduction
+
+ With DNSSEC [1], an NSEC record lists the next instantiated name in
+ its zone, proving that no names exist in the "span" between the
+ NSEC's owner name and the name in the "next name" field. In this
+ document, an NSEC record is said to "cover" the names between its
+ owner name and next name.
+
+
+
+Weiler & Ihren Standards Track [Page 1]
+
+RFC 4470 NSEC Epsilon April 2006
+
+
+ Through repeated queries that return NSEC records, it is possible to
+ retrieve all of the names in the zone, a process commonly called
+ "walking" the zone. Some zone owners have policies forbidding zone
+ transfers by arbitrary clients; this side effect of the NSEC
+ architecture subverts those policies.
+
+ This document presents a way to prevent zone walking by constructing
+ NSEC records that cover fewer names. These records can make zone
+ walking take approximately as many queries as simply asking for all
+ possible names in a zone, making zone walking impractical. Some of
+ these records must be created and signed on demand, which requires
+ on-line private keys. Anyone contemplating use of this technique is
+ strongly encouraged to review the discussion of the risks of on-line
+ signing in Section 5.
+
+1.2. Keywords
+
+ The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in RFC 2119 [4].
+
+2. Applicability of This Technique
+
+ The technique presented here may be useful to a zone owner that wants
+ to use DNSSEC, is concerned about exposure of its zone contents via
+ zone walking, and is willing to bear the costs of on-line signing.
+
+ As discussed in Section 5, on-line signing has several security
+ risks, including an increased likelihood of private keys being
+ disclosed and an increased risk of denial of service attack. Anyone
+ contemplating use of this technique is strongly encouraged to review
+ the discussion of the risks of on-line signing in Section 5.
+
+ Furthermore, at the time this document was published, the DNSEXT
+ working group was actively working on a mechanism to prevent zone
+ walking that does not require on-line signing (tentatively called
+ NSEC3). The new mechanism is likely to expose slightly more
+ information about the zone than this technique (e.g., the number of
+ instantiated names), but it may be preferable to this technique.
+
+3. Minimally Covering NSEC Records
+
+ This mechanism involves changes to NSEC records for instantiated
+ names, which can still be generated and signed in advance, as well as
+ the on-demand generation and signing of new NSEC records whenever a
+ name must be proven not to exist.
+
+
+
+
+
+Weiler & Ihren Standards Track [Page 2]
+
+RFC 4470 NSEC Epsilon April 2006
+
+
+ In the "next name" field of instantiated names' NSEC records, rather
+ than list the next instantiated name in the zone, list any name that
+ falls lexically after the NSEC's owner name and before the next
+ instantiated name in the zone, according to the ordering function in
+ RFC 4034 [2] Section 6.1. This relaxes the requirement in Section
+ 4.1.1 of RFC 4034 that the "next name" field contains the next owner
+ name in the zone. This change is expected to be fully compatible
+ with all existing DNSSEC validators. These NSEC records are returned
+ whenever proving something specifically about the owner name (e.g.,
+ that no resource records of a given type appear at that name).
+
+ Whenever an NSEC record is needed to prove the non-existence of a
+ name, a new NSEC record is dynamically produced and signed. The new
+ NSEC record has an owner name lexically before the QNAME but
+ lexically following any existing name and a "next name" lexically
+ following the QNAME but before any existing name.
+
+ The generated NSEC record's type bitmap MUST have the RRSIG and NSEC
+ bits set and SHOULD NOT have any other bits set. This relaxes the
+ requirement in Section 2.3 of RFC4035 that NSEC RRs not appear at
+ names that did not exist before the zone was signed.
+
+ The functions to generate the lexically following and proceeding
+ names need not be perfect or consistent, but the generated NSEC
+ records must not cover any existing names. Furthermore, this
+ technique works best when the generated NSEC records cover as few
+ names as possible. In this document, the functions that generate the
+ nearby names are called "epsilon" functions, a reference to the
+ mathematical convention of using the greek letter epsilon to
+ represent small deviations.
+
+ An NSEC record denying the existence of a wildcard may be generated
+ in the same way. Since the NSEC record covering a non-existent
+ wildcard is likely to be used in response to many queries,
+ authoritative name servers using the techniques described here may
+ want to pregenerate or cache that record and its corresponding RRSIG.
+
+ For example, a query for an A record at the non-instantiated name
+ example.com might produce the following two NSEC records, the first
+ denying the existence of the name example.com and the second denying
+ the existence of a wildcard:
+
+ exampld.com 3600 IN NSEC example-.com ( RRSIG NSEC )
+
+ \).com 3600 IN NSEC +.com ( RRSIG NSEC )
+
+
+
+
+
+
+Weiler & Ihren Standards Track [Page 3]
+
+RFC 4470 NSEC Epsilon April 2006
+
+
+ Before answering a query with these records, an authoritative server
+ must test for the existence of names between these endpoints. If the
+ generated NSEC would cover existing names (e.g., exampldd.com or
+ *bizarre.example.com), a better epsilon function may be used or the
+ covered name closest to the QNAME could be used as the NSEC owner
+ name or next name, as appropriate. If an existing name is used as
+ the NSEC owner name, that name's real NSEC record MUST be returned.
+ Using the same example, assuming an exampldd.com delegation exists,
+ this record might be returned from the parent:
+
+ exampldd.com 3600 IN NSEC example-.com ( NS DS RRSIG NSEC )
+
+ Like every authoritative record in the zone, each generated NSEC
+ record MUST have corresponding RRSIGs generated using each algorithm
+ (but not necessarily each DNSKEY) in the zone's DNSKEY RRset, as
+ described in RFC 4035 [3] Section 2.2. To minimize the number of
+ signatures that must be generated, a zone may wish to limit the
+ number of algorithms in its DNSKEY RRset.
+
+4. Better Epsilon Functions
+
+ Section 6.1 of RFC 4034 defines a strict ordering of DNS names.
+ Working backward from that definition, it should be possible to
+ define epsilon functions that generate the immediately following and
+ preceding names, respectively. This document does not define such
+ functions. Instead, this section presents functions that come
+ reasonably close to the perfect ones. As described above, an
+ authoritative server should still ensure than no generated NSEC
+ covers any existing name.
+
+ To increment a name, add a leading label with a single null (zero-
+ value) octet.
+
+ To decrement a name, decrement the last character of the leftmost
+ label, then fill that label to a length of 63 octets with octets of
+ value 255. To decrement a null (zero-value) octet, remove the octet
+ -- if an empty label is left, remove the label. Defining this
+ function numerically: fill the leftmost label to its maximum length
+ with zeros (numeric, not ASCII zeros) and subtract one.
+
+ In response to a query for the non-existent name foo.example.com,
+ these functions produce NSEC records of the following:
+
+
+
+
+
+
+
+
+
+Weiler & Ihren Standards Track [Page 4]
+
+RFC 4470 NSEC Epsilon April 2006
+
+
+ fon\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255.example.com 3600 IN NSEC \000.foo.example.com ( NSEC RRSIG )
+
+ \)\255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255\255\255\255\255\255\255\255\255\255\255\255\255\255
+ \255\255.example.com 3600 IN NSEC \000.*.example.com ( NSEC RRSIG )
+
+ The first of these NSEC RRs proves that no exact match for
+ foo.example.com exists, and the second proves that there is no
+ wildcard in example.com.
+
+ Both of these functions are imperfect: they do not take into account
+ constraints on number of labels in a name nor total length of a name.
+ As noted in the previous section, though, this technique does not
+ depend on the use of perfect epsilon functions: it is sufficient to
+ test whether any instantiated names fall into the span covered by the
+ generated NSEC and, if so, substitute those instantiated owner names
+ for the NSEC owner name or next name, as appropriate.
+
+5. Security Considerations
+
+ This approach requires on-demand generation of RRSIG records. This
+ creates several new vulnerabilities.
+
+ First, on-demand signing requires that a zone's authoritative servers
+ have access to its private keys. Storing private keys on well-known
+ Internet-accessible servers may make them more vulnerable to
+ unintended disclosure.
+
+ Second, since generation of digital signatures tends to be
+ computationally demanding, the requirement for on-demand signing
+ makes authoritative servers vulnerable to a denial of service attack.
+
+ Last, if the epsilon functions are predictable, on-demand signing may
+ enable a chosen-plaintext attack on a zone's private keys. Zones
+ using this approach should attempt to use cryptographic algorithms
+ that are resistant to chosen-plaintext attacks. It is worth noting
+ that although DNSSEC has a "mandatory to implement" algorithm, that
+ is a requirement on resolvers and validators -- there is no
+ requirement that a zone be signed with any given algorithm.
+
+ The success of using minimally covering NSEC records to prevent zone
+ walking depends greatly on the quality of the epsilon functions
+
+
+
+Weiler & Ihren Standards Track [Page 5]
+
+RFC 4470 NSEC Epsilon April 2006
+
+
+ chosen. An increment function that chooses a name obviously derived
+ from the next instantiated name may be easily reverse engineered,
+ destroying the value of this technique. An increment function that
+ always returns a name close to the next instantiated name is likewise
+ a poor choice. Good choices of epsilon functions are the ones that
+ produce the immediately following and preceding names, respectively,
+ though zone administrators may wish to use less perfect functions
+ that return more human-friendly names than the functions described in
+ Section 4 above.
+
+ Another obvious but misguided concern is the danger from synthesized
+ NSEC records being replayed. It is possible for an attacker to
+ replay an old but still validly signed NSEC record after a new name
+ has been added in the span covered by that NSEC, incorrectly proving
+ that there is no record at that name. This danger exists with DNSSEC
+ as defined in [3]. The techniques described here actually decrease
+ the danger, since the span covered by any NSEC record is smaller than
+ before. Choosing better epsilon functions will further reduce this
+ danger.
+
+6. Acknowledgements
+
+ Many individuals contributed to this design. They include, in
+ addition to the authors of this document, Olaf Kolkman, Ed Lewis,
+ Peter Koch, Matt Larson, David Blacka, Suzanne Woolf, Jaap Akkerhuis,
+ Jakob Schlyter, Bill Manning, and Joao Damas.
+
+ In addition, the editors would like to thank Ed Lewis, Scott Rose,
+ and David Blacka for their careful review of the document.
+
+7. Normative References
+
+ [1] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033, March
+ 2005.
+
+ [2] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+ [3] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Protocol Modifications for the DNS Security Extensions", RFC
+ 4035, March 2005.
+
+ [4] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+
+
+Weiler & Ihren Standards Track [Page 6]
+
+RFC 4470 NSEC Epsilon April 2006
+
+
+Authors' Addresses
+
+ Samuel Weiler
+ SPARTA, Inc.
+ 7075 Samuel Morse Drive
+ Columbia, Maryland 21046
+ US
+
+ EMail: weiler@tislabs.com
+
+
+ Johan Ihren
+ Autonomica AB
+ Bellmansgatan 30
+ Stockholm SE-118 47
+ Sweden
+
+ EMail: johani@autonomica.se
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Weiler & Ihren Standards Track [Page 7]
+
+RFC 4470 NSEC Epsilon April 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Weiler & Ihren Standards Track [Page 8]
+
diff --git a/doc/rfc/rfc4634.txt b/doc/rfc/rfc4634.txt
new file mode 100644
index 0000000..b672df8
--- /dev/null
+++ b/doc/rfc/rfc4634.txt
@@ -0,0 +1,6051 @@
+
+
+
+
+
+
+Network Working Group D. Eastlake 3rd
+Request for Comments: 4634 Motorola Labs
+Updates: 3174 T. Hansen
+Category: Informational AT&T Labs
+ July 2006
+
+
+ US Secure Hash Algorithms (SHA and HMAC-SHA)
+
+Status of This Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ The United States of America has adopted a suite of Secure Hash
+ Algorithms (SHAs), including four beyond SHA-1, as part of a Federal
+ Information Processing Standard (FIPS), specifically SHA-224 (RFC
+ 3874), SHA-256, SHA-384, and SHA-512. The purpose of this document
+ is to make source code performing these hash functions conveniently
+ available to the Internet community. The sample code supports input
+ strings of arbitrary bit length. SHA-1's sample code from RFC 3174
+ has also been updated to handle input strings of arbitrary bit
+ length. Most of the text herein was adapted by the authors from FIPS
+ 180-2.
+
+ Code to perform SHA-based HMACs, with arbitrary bit length text, is
+ also included.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 1]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+Table of Contents
+
+ 1. Overview of Contents ............................................3
+ 1.1. License ....................................................4
+ 2. Notation for Bit Strings and Integers ...........................4
+ 3. Operations on Words .............................................5
+ 4. Message Padding and Parsing .....................................6
+ 4.1. SHA-224 and SHA-256 ........................................7
+ 4.2. SHA-384 and SHA-512 ........................................8
+ 5. Functions and Constants Used ....................................9
+ 5.1. SHA-224 and SHA-256 ........................................9
+ 5.2. SHA-384 and SHA-512 .......................................10
+ 6. Computing the Message Digest ...................................11
+ 6.1. SHA-224 and SHA-256 Initialization ........................11
+ 6.2. SHA-224 and SHA-256 Processing ............................11
+ 6.3. SHA-384 and SHA-512 Initialization ........................13
+ 6.4. SHA-384 and SHA-512 Processing ............................14
+ 7. SHA-Based HMACs ................................................15
+ 8. C Code for SHAs ................................................15
+ 8.1. The .h File ...............................................18
+ 8.2. The SHA Code ..............................................24
+ 8.2.1. sha1.c .............................................24
+ 8.2.2. sha224-256.c .......................................33
+ 8.2.3. sha384-512.c .......................................45
+ 8.2.4. usha.c .............................................67
+ 8.2.5. sha-private.h ......................................72
+ 8.3. The HMAC Code .............................................73
+ 8.4. The Test Driver ...........................................78
+ 9. Security Considerations .......................................106
+ 10. Normative References .........................................106
+ 11. Informative References .......................................106
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 2]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+1. Overview of Contents
+
+ NOTE: Much of the text below is taken from [FIPS180-2] and assertions
+ therein of the security of the algorithms described are made by the
+ US Government, the author of [FIPS180-2], and not by the authors of
+ this document.
+
+ The text below specifies Secure Hash Algorithms, SHA-224 [RFC3874],
+ SHA-256, SHA-384, and SHA-512, for computing a condensed
+ representation of a message or a data file. (SHA-1 is specified in
+ [RFC3174].) When a message of any length < 2^64 bits (for SHA-224
+ and SHA-256) or < 2^128 bits (for SHA-384 and SHA-512) is input to
+ one of these algorithms, the result is an output called a message
+ digest. The message digests range in length from 224 to 512 bits,
+ depending on the algorithm. Secure hash algorithms are typically
+ used with other cryptographic algorithms, such as digital signature
+ algorithms and keyed hash authentication codes, or in the generation
+ of random numbers [RFC4086].
+
+ The four algorithms specified in this document are called secure
+ because it is computationally infeasible to (1) find a message that
+ corresponds to a given message digest, or (2) find two different
+ messages that produce the same message digest. Any change to a
+ message in transit will, with very high probability, result in a
+ different message digest. This will result in a verification failure
+ when the secure hash algorithm is used with a digital signature
+ algorithm or a keyed-hash message authentication algorithm.
+
+ The code provided herein supports input strings of arbitrary bit
+ length. SHA-1's sample code from [RFC3174] has also been updated to
+ handle input strings of arbitrary bit length. See Section 1.1 for
+ license information for this code.
+
+ Section 2 below defines the terminology and functions used as
+ building blocks to form these algorithms. Section 3 describes the
+ fundamental operations on words from which these algorithms are
+ built. Section 4 describes how messages are padded up to an integral
+ multiple of the required block size and then parsed into blocks.
+ Section 5 defines the constants and the composite functions used to
+ specify these algorithms. Section 6 gives the actual specification
+ for the SHA-224, SHA-256, SHA-384, and SHA-512 functions. Section 7
+ provides pointers to the specification of HMAC keyed message
+ authentication codes based on the SHA algorithms. Section 8 gives
+ sample code for the SHA algorithms and Section 9 code for SHA-based
+ HMACs. The SHA-based HMACs will accept arbitrary bit length text.
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 3]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+1.1. License
+
+ Permission is granted for all uses, commercial and non-commercial, of
+ the sample code found in Section 8. Royalty free license to use,
+ copy, modify and distribute the software found in Section 8 is
+ granted, provided that this document is identified in all material
+ mentioning or referencing this software, and provided that
+ redistributed derivative works do not contain misleading author or
+ version information.
+
+ The authors make no representations concerning either the
+ merchantability of this software or the suitability of this software
+ for any particular purpose. It is provided "as is" without express
+ or implied warranty of any kind.
+
+2. Notation for Bit Strings and Integers
+
+ The following terminology related to bit strings and integers will be
+ used:
+
+ a. A hex digit is an element of the set {0, 1, ... , 9, A, ... ,
+ F}. A hex digit is the representation of a 4-bit string.
+ Examples: 7 = 0111, A = 1010.
+
+ b. A word equals a 32-bit or 64-bit string, which may be
+ represented as a sequence of 8 or 16 hex digits, respectively.
+ To convert a word to hex digits, each 4-bit string is converted
+ to its hex equivalent as described in (a) above. Example:
+
+ 1010 0001 0000 0011 1111 1110 0010 0011 = A103FE23.
+
+ Throughout this document, the "big-endian" convention is used
+ when expressing both 32-bit and 64-bit words, so that within
+ each word the most significant bit is shown in the left-most bit
+ position.
+
+ c. An integer may be represented as a word or pair of words.
+
+ An integer between 0 and 2^32 - 1 inclusive may be represented
+ as a 32-bit word. The least significant four bits of the
+ integer are represented by the right-most hex digit of the word
+ representation. Example: the integer 291 = 2^8+2^5+2^1+2^0 =
+ 256+32+2+1 is represented by the hex word 00000123.
+
+ The same holds true for an integer between 0 and 2^64-1
+ inclusive, which may be represented as a 64-bit word.
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 4]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ If Z is an integer, 0 <= z < 2^64, then z = (2^32)x + y where 0
+ <= x < 2^32 and 0 <= y < 2^32. Since x and y can be represented
+ as words X and Y, respectively, z can be represented as the pair
+ of words (X,Y).
+
+ d. block = 512-bit or 1024-bit string. A block (e.g., B) may be
+ represented as a sequence of 32-bit or 64-bit words.
+
+3. Operations on Words
+
+ The following logical operators will be applied to words in all four
+ hash operations specified herein. SHA-224 and SHA-256 operate on
+ 32-bit words, while SHA-384 and SHA-512 operate on 64-bit words.
+
+ In the operations below, x<<n is obtained as follows: discard the
+ left-most n bits of x and then pad the result with n zeroed bits on
+ the right (the result will still be the same number of bits).
+
+ a. Bitwise logical word operations
+
+ X AND Y = bitwise logical "and" of X and Y.
+
+ X OR Y = bitwise logical "inclusive-or" of X and Y.
+
+ X XOR Y = bitwise logical "exclusive-or" of X and Y.
+
+ NOT X = bitwise logical "complement" of X.
+
+ Example:
+ 01101100101110011101001001111011
+ XOR 01100101110000010110100110110111
+ --------------------------------
+ = 00001001011110001011101111001100
+
+ b. The operation X + Y is defined as follows: words X and Y
+ represent w-bit integers x and y, where 0 <= x < 2^w and
+ 0 <= y < 2^w. For positive integers n and m, let
+
+ n mod m
+
+ be the remainder upon dividing n by m. Compute
+
+ z = (x + y) mod 2^w.
+
+ Then 0 <= z < 2^w. Convert z to a word, Z, and define Z = X +
+ Y.
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 5]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ c. The right shift operation SHR^n(x), where x is a w-bit word and
+ n is an integer with 0 <= n < w, is defined by
+
+ SHR^n(x) = x>>n
+
+ d. The rotate right (circular right shift) operation ROTR^n(x),
+ where x is a w-bit word and n is an integer with 0 <= n < w, is
+ defined by
+
+ ROTR^n(x) = (x>>n) OR (x<<(w-n))
+
+ e. The rotate left (circular left shift) operation ROTL^n(x), where
+ x is a w-bit word and n is an integer with 0 <= n < w, is
+ defined by
+
+ ROTL^n(X) = (x<<n) OR (x>>w-n)
+
+ Note the following equivalence relationships, where w is fixed
+ in each relationship:
+
+ ROTL^n(x) = ROTR^(w-x)(x)
+
+ ROTR^n(x) = ROTL^(w-n)(x)
+
+4. Message Padding and Parsing
+
+ The hash functions specified herein are used to compute a message
+ digest for a message or data file that is provided as input. The
+ message or data file should be considered to be a bit string. The
+ length of the message is the number of bits in the message (the empty
+ message has length 0). If the number of bits in a message is a
+ multiple of 8, for compactness we can represent the message in hex.
+ The purpose of message padding is to make the total length of a
+ padded message a multiple of 512 for SHA-224 and SHA-256 or a
+ multiple of 1024 for SHA-384 and SHA-512.
+
+ The following specifies how this padding shall be performed. As a
+ summary, a "1" followed by a number of "0"s followed by a 64-bit or
+ 128-bit integer are appended to the end of the message to produce a
+ padded message of length 512*n or 1024*n. The minimum number of "0"s
+ necessary to meet this criterion is used. The appended integer is
+ the length of the original message. The padded message is then
+ processed by the hash function as n 512-bit or 1024-bit blocks.
+
+
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 6]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+4.1. SHA-224 and SHA-256
+
+ Suppose a message has length L < 2^64. Before it is input to the
+ hash function, the message is padded on the right as follows:
+
+ a. "1" is appended. Example: if the original message is
+ "01010000", this is padded to "010100001".
+
+ b. K "0"s are appended where K is the smallest, non-negative
+ solution to the equation
+
+ L + 1 + K = 448 (mod 512)
+
+ c. Then append the 64-bit block that is L in binary representation.
+ After appending this block, the length of the message will be a
+ multiple of 512 bits.
+
+ Example: Suppose the original message is the bit string
+
+ 01100001 01100010 01100011 01100100 01100101
+
+ After step (a), this gives
+
+ 01100001 01100010 01100011 01100100 01100101 1
+
+ Since L = 40, the number of bits in the above is 41 and K = 407
+ "0"s are appended, making the total now 448. This gives the
+ following in hex:
+
+ 61626364 65800000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000
+
+ The 64-bit representation of L = 40 is hex 00000000 00000028.
+ Hence the final padded message is the following hex:
+
+ 61626364 65800000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000028
+
+
+
+
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 7]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+4.2. SHA-384 and SHA-512
+
+ Suppose a message has length L < 2^128. Before it is input to the
+ hash function, the message is padded on the right as follows:
+
+ a. "1" is appended. Example: if the original message is
+ "01010000", this is padded to "010100001".
+
+ b. K "0"s are appended where K is the smallest, non-negative
+ solution to the equation
+
+ L + 1 + K = 896 (mod 1024)
+
+ c. Then append the 128-bit block that is L in binary
+ representation. After appending this block, the length of the
+ message will be a multiple of 1024 bits.
+
+ Example: Suppose the original message is the bit string
+
+ 01100001 01100010 01100011 01100100 01100101
+
+ After step (a) this gives
+
+ 01100001 01100010 01100011 01100100 01100101 1
+
+ Since L = 40, the number of bits in the above is 41 and K = 855
+ "0"s are appended, making the total now 896. This gives the
+ following in hex:
+
+ 61626364 65800000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+
+ The 128-bit representation of L = 40 is hex 00000000 00000000
+ 00000000 00000028. Hence the final padded message is the
+ following hex:
+
+ 61626364 65800000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 8]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000000
+ 00000000 00000000 00000000 00000028
+
+5. Functions and Constants Used
+
+ The following subsections give the six logical functions and the
+ table of constants used in each of the hash functions.
+
+5.1. SHA-224 and SHA-256
+
+ SHA-224 and SHA-256 use six logical functions, where each function
+ operates on 32-bit words, which are represented as x, y, and z. The
+ result of each function is a new 32-bit word.
+
+ CH( x, y, z) = (x AND y) XOR ( (NOT x) AND z)
+
+ MAJ( x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z)
+
+ BSIG0(x) = ROTR^2(x) XOR ROTR^13(x) XOR ROTR^22(x)
+
+ BSIG1(x) = ROTR^6(x) XOR ROTR^11(x) XOR ROTR^25(x)
+
+ SSIG0(x) = ROTR^7(x) XOR ROTR^18(x) XOR SHR^3(x)
+
+ SSIG1(x) = ROTR^17(x) XOR ROTR^19(x) XOR SHR^10(x)
+
+ SHA-224 and SHA-256 use the same sequence of sixty-four constant
+ 32-bit words, K0, K1, ..., K63. These words represent the first
+ thirty-two bits of the fractional parts of the cube roots of the
+ first sixty-four prime numbers. In hex, these constant words are as
+ follows (from left to right):
+
+ 428a2f98 71374491 b5c0fbcf e9b5dba5
+ 3956c25b 59f111f1 923f82a4 ab1c5ed5
+ d807aa98 12835b01 243185be 550c7dc3
+ 72be5d74 80deb1fe 9bdc06a7 c19bf174
+ e49b69c1 efbe4786 0fc19dc6 240ca1cc
+ 2de92c6f 4a7484aa 5cb0a9dc 76f988da
+ 983e5152 a831c66d b00327c8 bf597fc7
+ c6e00bf3 d5a79147 06ca6351 14292967
+ 27b70a85 2e1b2138 4d2c6dfc 53380d13
+ 650a7354 766a0abb 81c2c92e 92722c85
+ a2bfe8a1 a81a664b c24b8b70 c76c51a3
+ d192e819 d6990624 f40e3585 106aa070
+ 19a4c116 1e376c08 2748774c 34b0bcb5
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 9]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ 391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3
+ 748f82ee 78a5636f 84c87814 8cc70208
+ 90befffa a4506ceb bef9a3f7 c67178f2
+
+5.2. SHA-384 and SHA-512
+
+ SHA-384 and SHA-512 each use six logical functions, where each
+ function operates on 64-bit words, which are represented as x, y, and
+ z. The result of each function is a new 64-bit word.
+
+ CH( x, y, z) = (x AND y) XOR ( (NOT x) AND z)
+
+ MAJ( x, y, z) = (x AND y) XOR (x AND z) XOR (y AND z)
+
+ BSIG0(x) = ROTR^28(x) XOR ROTR^34(x) XOR ROTR^39(x)
+
+ BSIG1(x) = ROTR^14(x) XOR ROTR^18(x) XOR ROTR^41(x)
+
+ SSIG0(x) = ROTR^1(x) XOR ROTR^8(x) XOR SHR^7(x)
+
+ SSIG1(x) = ROTR^19(x) XOR ROTR^61(x) XOR SHR^6(x)
+
+ SHA-384 and SHA-512 use the same sequence of eighty constant 64-bit
+ words, K0, K1, ... K79. These words represent the first sixty-four
+ bits of the fractional parts of the cube roots of the first eighty
+ prime numbers. In hex, these constant words are as follows (from
+ left to right):
+
+ 428a2f98d728ae22 7137449123ef65cd b5c0fbcfec4d3b2f e9b5dba58189dbbc
+ 3956c25bf348b538 59f111f1b605d019 923f82a4af194f9b ab1c5ed5da6d8118
+ d807aa98a3030242 12835b0145706fbe 243185be4ee4b28c 550c7dc3d5ffb4e2
+ 72be5d74f27b896f 80deb1fe3b1696b1 9bdc06a725c71235 c19bf174cf692694
+ e49b69c19ef14ad2 efbe4786384f25e3 0fc19dc68b8cd5b5 240ca1cc77ac9c65
+ 2de92c6f592b0275 4a7484aa6ea6e483 5cb0a9dcbd41fbd4 76f988da831153b5
+ 983e5152ee66dfab a831c66d2db43210 b00327c898fb213f bf597fc7beef0ee4
+ c6e00bf33da88fc2 d5a79147930aa725 06ca6351e003826f 142929670a0e6e70
+ 27b70a8546d22ffc 2e1b21385c26c926 4d2c6dfc5ac42aed 53380d139d95b3df
+ 650a73548baf63de 766a0abb3c77b2a8 81c2c92e47edaee6 92722c851482353b
+ a2bfe8a14cf10364 a81a664bbc423001 c24b8b70d0f89791 c76c51a30654be30
+ d192e819d6ef5218 d69906245565a910 f40e35855771202a 106aa07032bbd1b8
+ 19a4c116b8d2d0c8 1e376c085141ab53 2748774cdf8eeb99 34b0bcb5e19b48a8
+ 391c0cb3c5c95a63 4ed8aa4ae3418acb 5b9cca4f7763e373 682e6ff3d6b2b8a3
+ 748f82ee5defb2fc 78a5636f43172f60 84c87814a1f0ab72 8cc702081a6439ec
+ 90befffa23631e28 a4506cebde82bde9 bef9a3f7b2c67915 c67178f2e372532b
+ ca273eceea26619c d186b8c721c0c207 eada7dd6cde0eb1e f57d4f7fee6ed178
+ 06f067aa72176fba 0a637dc5a2c898a6 113f9804bef90dae 1b710b35131c471b
+ 28db77f523047d84 32caab7b40c72493 3c9ebe0a15c9bebc 431d67c49c100d4c
+ 4cc5d4becb3e42b6 597f299cfc657e2a 5fcb6fab3ad6faec 6c44198c4a475817
+
+
+
+Eastlake 3rd & Hansen Informational [Page 10]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+6. Computing the Message Digest
+
+ The output of each of the secure hash functions, after being applied
+ to a message of N blocks, is the hash quantity H(N). For SHA-224 and
+ SHA-256, H(i) can be considered to be eight 32-bit words, H(i)0,
+ H(i)1, ... H(i)7. For SHA-384 and SHA-512, it can be considered to
+ be eight 64-bit words, H(i)0, H(i)1, ..., H(i)7.
+
+ As described below, the hash words are initialized, modified as each
+ message block is processed, and finally concatenated after processing
+ the last block to yield the output. For SHA-256 and SHA-512, all of
+ the H(N) variables are concatenated while the SHA-224 and SHA-384
+ hashes are produced by omitting some from the final concatenation.
+
+6.1. SHA-224 and SHA-256 Initialization
+
+ For SHA-224, the initial hash value, H(0), consists of the following
+ 32-bit words in hex:
+
+ H(0)0 = c1059ed8
+ H(0)1 = 367cd507
+ H(0)2 = 3070dd17
+ H(0)3 = f70e5939
+ H(0)4 = ffc00b31
+ H(0)5 = 68581511
+ H(0)6 = 64f98fa7
+ H(0)7 = befa4fa4
+
+ For SHA-256, the initial hash value, H(0), consists of the following
+ eight 32-bit words, in hex. These words were obtained by taking the
+ first thirty-two bits of the fractional parts of the square roots of
+ the first eight prime numbers.
+
+ H(0)0 = 6a09e667
+ H(0)1 = bb67ae85
+ H(0)2 = 3c6ef372
+ H(0)3 = a54ff53a
+ H(0)4 = 510e527f
+ H(0)5 = 9b05688c
+ H(0)6 = 1f83d9ab
+ H(0)7 = 5be0cd19
+
+6.2. SHA-224 and SHA-256 Processing
+
+ SHA-224 and SHA-256 perform identical processing on messages blocks
+ and differ only in how H(0) is initialized and how they produce their
+ final output. They may be used to hash a message, M, having a length
+ of L bits, where 0 <= L < 2^64. The algorithm uses (1) a message
+
+
+
+Eastlake 3rd & Hansen Informational [Page 11]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ schedule of sixty-four 32-bit words, (2) eight working variables of
+ 32 bits each, and (3) a hash value of eight 32-bit words.
+
+ The words of the message schedule are labeled W0, W1, ..., W63. The
+ eight working variables are labeled a, b, c, d, e, f, g, and h. The
+ words of the hash value are labeled H(i)0, H(i)1, ..., H(i)7, which
+ will hold the initial hash value, H(0), replaced by each successive
+ intermediate hash value (after each message block is processed),
+ H(i), and ending with the final hash value, H(N), after all N blocks
+ are processed. They also use two temporary words, T1 and T2.
+
+ The input message is padded as described in Section 4.1 above then
+ parsed into 512-bit blocks, which are considered to be composed of 16
+ 32-bit words M(i)0, M(i)1, ..., M(i)15. The following computations
+ are then performed for each of the N message blocks. All addition is
+ performed modulo 2^32.
+
+ For i = 1 to N
+
+ 1. Prepare the message schedule W:
+ For t = 0 to 15
+ Wt = M(i)t
+ For t = 16 to 63
+ Wt = SSIG1(W(t-2)) + W(t-7) + SSIG0(t-15) + W(t-16)
+
+ 2. Initialize the working variables:
+ a = H(i-1)0
+ b = H(i-1)1
+ c = H(i-1)2
+ d = H(i-1)3
+ e = H(i-1)4
+ f = H(i-1)5
+ g = H(i-1)6
+ h = H(i-1)7
+
+ 3. Perform the main hash computation:
+ For t = 0 to 63
+ T1 = h + BSIG1(e) + CH(e,f,g) + Kt + Wt
+ T2 = BSIG0(a) + MAJ(a,b,c)
+ h = g
+ g = f
+ f = e
+ e = d + T1
+ d = c
+ c = b
+ b = a
+ a = T1 + T2
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 12]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ 4. Compute the intermediate hash value H(i):
+ H(i)0 = a + H(i-1)0
+ H(i)1 = b + H(i-1)1
+ H(i)2 = c + H(i-1)2
+ H(i)3 = d + H(i-1)3
+ H(i)4 = e + H(i-1)4
+ H(i)5 = f + H(i-1)5
+ H(i)6 = g + H(i-1)6
+ H(i)7 = h + H(i-1)7
+
+ After the above computations have been sequentially performed for all
+ of the blocks in the message, the final output is calculated. For
+ SHA-256, this is the concatenation of all of H(N)0, H(N)1, through
+ H(N)7. For SHA-224, this is the concatenation of H(N)0, H(N)1,
+ through H(N)6.
+
+6.3. SHA-384 and SHA-512 Initialization
+
+ For SHA-384, the initial hash value, H(0), consists of the following
+ eight 64-bit words, in hex. These words were obtained by taking the
+ first sixty-four bits of the fractional parts of the square roots of
+ the ninth through sixteenth prime numbers.
+
+ H(0)0 = cbbb9d5dc1059ed8
+ H(0)1 = 629a292a367cd507
+ H(0)2 = 9159015a3070dd17
+ H(0)3 = 152fecd8f70e5939
+ H(0)4 = 67332667ffc00b31
+ H(0)5 = 8eb44a8768581511
+ H(0)6 = db0c2e0d64f98fa7
+ H(0)7 = 47b5481dbefa4fa4
+
+ For SHA-512, the initial hash value, H(0), consists of the following
+ eight 64-bit words, in hex. These words were obtained by taking the
+ first sixty-four bits of the fractional parts of the square roots of
+ the first eight prime numbers.
+
+ H(0)0 = 6a09e667f3bcc908
+ H(0)1 = bb67ae8584caa73b
+ H(0)2 = 3c6ef372fe94f82b
+ H(0)3 = a54ff53a5f1d36f1
+ H(0)4 = 510e527fade682d1
+ H(0)5 = 9b05688c2b3e6c1f
+ H(0)6 = 1f83d9abfb41bd6b
+ H(0)7 = 5be0cd19137e2179
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 13]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+6.4. SHA-384 and SHA-512 Processing
+
+ SHA-384 and SHA-512 perform identical processing on message blocks
+ and differ only in how H(0) is initialized and how they produce their
+ final output. They may be used to hash a message, M, having a length
+ of L bits, where 0 <= L < 2^128. The algorithm uses (1) a message
+ schedule of eighty 64-bit words, (2) eight working variables of 64
+ bits each, and (3) a hash value of eight 64-bit words.
+
+ The words of the message schedule are labeled W0, W1, ..., W79. The
+ eight working variables are labeled a, b, c, d, e, f, g, and h. The
+ words of the hash value are labeled H(i)0, H(i)1, ..., H(i)7, which
+ will hold the initial hash value, H(0), replaced by each successive
+ intermediate hash value (after each message block is processed),
+ H(i), and ending with the final hash value, H(N) after all N blocks
+ are processed.
+
+ The input message is padded as described in Section 4.2 above, then
+ parsed into 1024-bit blocks, which are considered to be composed of
+ 16 64-bit words M(i)0, M(i)1, ..., M(i)15. The following
+ computations are then performed for each of the N message blocks.
+ All addition is performed modulo 2^64.
+
+ For i = 1 to N
+
+ 1. Prepare the message schedule W:
+ For t = 0 to 15
+ Wt = M(i)t
+ For t = 16 to 79
+ Wt = SSIG1(W(t-2)) + W(t-7) + SSIG0(t-15) + W(t-16)
+
+ 2. Initialize the working variables:
+ a = H(i-1)0
+ b = H(i-1)1
+ c = H(i-1)2
+ d = H(i-1)3
+ e = H(i-1)4
+ f = H(i-1)5
+ g = H(i-1)6
+ h = H(i-1)7
+
+ 3. Perform the main hash computation:
+ For t = 0 to 79
+ T1 = h + BSIG1(e) + CH(e,f,g) + Kt + Wt
+ T2 = BSIG0(a) + MAJ(a,b,c)
+ h = g
+ g = f
+ f = e
+
+
+
+Eastlake 3rd & Hansen Informational [Page 14]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ e = d + T1
+ d = c
+ c = b
+ b = a
+ a = T1 + T2
+
+ 4. Compute the intermediate hash value H(i):
+ H(i)0 = a + H(i-1)0
+ H(i)1 = b + H(i-1)1
+ H(i)2 = c + H(i-1)2
+ H(i)3 = d + H(i-1)3
+ H(i)4 = e + H(i-1)4
+ H(i)5 = f + H(i-1)5
+ H(i)6 = g + H(i-1)6
+ H(i)7 = h + H(i-1)7
+
+ After the above computations have been sequentially performed for all
+ of the blocks in the message, the final output is calculated. For
+ SHA-512, this is the concatenation of all of H(N)0, H(N)1, through
+ H(N)7. For SHA-384, this is the concatenation of H(N)0, H(N)1,
+ through H(N)5.
+
+7. SHA-Based HMACs
+
+ HMAC is a method for computing a keyed MAC (message authentication
+ code) using a hash function as described in [RFC2104]. It uses a key
+ to mix in with the input text to produce the final hash.
+
+ Sample code is also provided, in Section 8.3 below, to perform HMAC
+ based on any of the SHA algorithms described herein. The sample code
+ found in [RFC2104] was written in terms of a specified text size.
+ Since SHA is defined in terms of an arbitrary number of bits, the
+ sample HMAC code has been written to allow the text input to HMAC to
+ have an arbitrary number of octets and bits. A fixed-length
+ interface is also provided.
+
+8. C Code for SHAs
+
+ Below is a demonstration implementation of these secure hash
+ functions in C. Section 8.1 contains the header file sha.h, which
+ declares all constants, structures, and functions used by the sha and
+ hmac functions. Section 8.2 contains the C code for sha1.c,
+ sha224-256.c, sha384-512.c, and usha.c along with sha-private.h,
+ which provides some declarations common to all the sha functions.
+ Section 8.3 contains the C code for the hmac functions. Section 8.4
+ contains a test driver to exercise the code.
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 15]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ For each of the digest length $$$, there is the following set of
+ constants, a structure, and functions:
+
+ Constants:
+ SHA$$$HashSize number of octets in the hash
+ SHA$$$HashSizeBits number of bits in the hash
+ SHA$$$_Message_Block_Size
+ number of octets used in the intermediate
+ message blocks
+ shaSuccess = 0 constant returned by each function on success
+ shaNull = 1 constant returned by each function when
+ presented with a null pointer parameter
+ shaInputTooLong = 2 constant returned by each function when the
+ input data is too long
+ shaStateError constant returned by each function when
+ SHA$$$Input is called after SHA$$$FinalBits or
+ SHA$$$Result.
+
+ Structure:
+ typedef SHA$$$Context
+ an opaque structure holding the complete state
+ for producing the hash
+
+ Functions:
+ int SHA$$$Reset(SHA$$$Context *);
+ Reset the hash context state
+ int SHA$$$Input(SHA$$$Context *, const uint8_t *octets,
+ unsigned int bytecount);
+ Incorporate bytecount octets into the hash.
+ int SHA$$$FinalBits(SHA$$$Context *, const uint8_t octet,
+ unsigned int bitcount);
+ Incorporate bitcount bits into the hash. The bits are in
+ the upper portion of the octet. SHA$$$Input() cannot be
+ called after this.
+ int SHA$$$Result(SHA$$$Context *,
+ uint8_t Message_Digest[SHA$$$HashSize]);
+ Do the final calculations on the hash and copy the value
+ into Message_Digest.
+
+ In addition, functions with the prefix USHA are provided that take a
+ SHAversion value (SHA$$$) to select the SHA function suite. They add
+ the following constants, structure, and functions:
+
+ Constants:
+ shaBadParam constant returned by USHA functions when
+ presented with a bad SHAversion (SHA$$$)
+ parameter
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 16]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ SHA$$$ SHAversion enumeration values, used by usha
+ and hmac functions to select the SHA function
+ suite
+
+ Structure:
+ typedef USHAContext
+ an opaque structure holding the complete state
+ for producing the hash
+
+ Functions:
+ int USHAReset(USHAContext *, SHAversion whichSha);
+ Reset the hash context state.
+ int USHAInput(USHAContext *,
+ const uint8_t *bytes, unsigned int bytecount);
+ Incorporate bytecount octets into the hash.
+ int USHAFinalBits(USHAContext *,
+ const uint8_t bits, unsigned int bitcount);
+ Incorporate bitcount bits into the hash.
+ int USHAResult(USHAContext *,
+ uint8_t Message_Digest[USHAMaxHashSize]);
+ Do the final calculations on the hash and copy the value
+ into Message_Digest. Octets in Message_Digest beyond
+ USHAHashSize(whichSha) are left untouched.
+ int USHAHashSize(enum SHAversion whichSha);
+ The number of octets in the given hash.
+ int USHAHashSizeBits(enum SHAversion whichSha);
+ The number of bits in the given hash.
+ int USHABlockSize(enum SHAversion whichSha);
+ The internal block size for the given hash.
+
+ The hmac functions follow the same pattern to allow any length of
+ text input to be used.
+
+ Structure:
+ typedef HMACContext an opaque structure holding the complete state
+ for producing the hash
+
+ Functions:
+ int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
+ const unsigned char *key, int key_len);
+ Reset the hash context state.
+ int hmacInput(HMACContext *ctx, const unsigned char *text,
+ int text_len);
+ Incorporate text_len octets into the hash.
+ int hmacFinalBits(HMACContext *ctx, const uint8_t bits,
+ unsigned int bitcount);
+ Incorporate bitcount bits into the hash.
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 17]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ int hmacResult(HMACContext *ctx,
+ uint8_t Message_Digest[USHAMaxHashSize]);
+ Do the final calculations on the hash and copy the value
+ into Message_Digest. Octets in Message_Digest beyond
+ USHAHashSize(whichSha) are left untouched.
+
+ In addition, a combined interface is provided, similar to that shown
+ in RFC 2104, that allows a fixed-length text input to be used.
+
+ int hmac(SHAversion whichSha,
+ const unsigned char *text, int text_len,
+ const unsigned char *key, int key_len,
+ uint8_t Message_Digest[USHAMaxHashSize]);
+ Calculate the given digest for the given text and key, and
+ return the resulting hash. Octets in Message_Digest beyond
+ USHAHashSize(whichSha) are left untouched.
+
+8.1. The .h File
+
+/**************************** sha.h ****************************/
+/******************* See RFC 4634 for details ******************/
+#ifndef _SHA_H_
+#define _SHA_H_
+
+/*
+ * Description:
+ * This file implements the Secure Hash Signature Standard
+ * algorithms as defined in the National Institute of Standards
+ * and Technology Federal Information Processing Standards
+ * Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
+ * published on August 1, 2002, and the FIPS PUB 180-2 Change
+ * Notice published on February 28, 2004.
+ *
+ * A combined document showing all algorithms is available at
+ * http://csrc.nist.gov/publications/fips/
+ * fips180-2/fips180-2withchangenotice.pdf
+ *
+ * The five hashes are defined in these sizes:
+ * SHA-1 20 byte / 160 bit
+ * SHA-224 28 byte / 224 bit
+ * SHA-256 32 byte / 256 bit
+ * SHA-384 48 byte / 384 bit
+ * SHA-512 64 byte / 512 bit
+ */
+
+#include <stdint.h>
+/*
+ * If you do not have the ISO standard stdint.h header file, then you
+
+
+
+Eastlake 3rd & Hansen Informational [Page 18]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * must typedef the following:
+ * name meaning
+ * uint64_t unsigned 64 bit integer
+ * uint32_t unsigned 32 bit integer
+ * uint8_t unsigned 8 bit integer (i.e., unsigned char)
+ * int_least16_t integer of >= 16 bits
+ *
+ */
+
+#ifndef _SHA_enum_
+#define _SHA_enum_
+/*
+ * All SHA functions return one of these values.
+ */
+enum {
+ shaSuccess = 0,
+ shaNull, /* Null pointer parameter */
+ shaInputTooLong, /* input data too long */
+ shaStateError, /* called Input after FinalBits or Result */
+ shaBadParam /* passed a bad parameter */
+};
+#endif /* _SHA_enum_ */
+
+/*
+ * These constants hold size information for each of the SHA
+ * hashing operations
+ */
+enum {
+ SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64,
+ SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128,
+ SHA512_Message_Block_Size = 128,
+ USHA_Max_Message_Block_Size = SHA512_Message_Block_Size,
+
+ SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32,
+ SHA384HashSize = 48, SHA512HashSize = 64,
+ USHAMaxHashSize = SHA512HashSize,
+
+ SHA1HashSizeBits = 160, SHA224HashSizeBits = 224,
+ SHA256HashSizeBits = 256, SHA384HashSizeBits = 384,
+ SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits
+};
+
+/*
+ * These constants are used in the USHA (unified sha) functions.
+ */
+typedef enum SHAversion {
+ SHA1, SHA224, SHA256, SHA384, SHA512
+} SHAversion;
+
+
+
+Eastlake 3rd & Hansen Informational [Page 19]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+/*
+ * This structure will hold context information for the SHA-1
+ * hashing operation.
+ */
+typedef struct SHA1Context {
+ uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
+
+ uint32_t Length_Low; /* Message length in bits */
+ uint32_t Length_High; /* Message length in bits */
+
+ int_least16_t Message_Block_Index; /* Message_Block array index */
+ /* 512-bit message blocks */
+ uint8_t Message_Block[SHA1_Message_Block_Size];
+
+ int Computed; /* Is the digest computed? */
+ int Corrupted; /* Is the digest corrupted? */
+} SHA1Context;
+
+/*
+ * This structure will hold context information for the SHA-256
+ * hashing operation.
+ */
+typedef struct SHA256Context {
+ uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */
+
+ uint32_t Length_Low; /* Message length in bits */
+ uint32_t Length_High; /* Message length in bits */
+
+ int_least16_t Message_Block_Index; /* Message_Block array index */
+ /* 512-bit message blocks */
+ uint8_t Message_Block[SHA256_Message_Block_Size];
+
+ int Computed; /* Is the digest computed? */
+ int Corrupted; /* Is the digest corrupted? */
+} SHA256Context;
+
+/*
+ * This structure will hold context information for the SHA-512
+ * hashing operation.
+ */
+typedef struct SHA512Context {
+#ifdef USE_32BIT_ONLY
+ uint32_t Intermediate_Hash[SHA512HashSize/4]; /* Message Digest */
+ uint32_t Length[4]; /* Message length in bits */
+#else /* !USE_32BIT_ONLY */
+ uint64_t Intermediate_Hash[SHA512HashSize/8]; /* Message Digest */
+ uint64_t Length_Low, Length_High; /* Message length in bits */
+#endif /* USE_32BIT_ONLY */
+
+
+
+Eastlake 3rd & Hansen Informational [Page 20]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ int_least16_t Message_Block_Index; /* Message_Block array index */
+ /* 1024-bit message blocks */
+ uint8_t Message_Block[SHA512_Message_Block_Size];
+
+ int Computed; /* Is the digest computed?*/
+ int Corrupted; /* Is the digest corrupted? */
+} SHA512Context;
+
+/*
+ * This structure will hold context information for the SHA-224
+ * hashing operation. It uses the SHA-256 structure for computation.
+ */
+typedef struct SHA256Context SHA224Context;
+
+/*
+ * This structure will hold context information for the SHA-384
+ * hashing operation. It uses the SHA-512 structure for computation.
+ */
+typedef struct SHA512Context SHA384Context;
+
+/*
+ * This structure holds context information for all SHA
+ * hashing operations.
+ */
+typedef struct USHAContext {
+ int whichSha; /* which SHA is being used */
+ union {
+ SHA1Context sha1Context;
+ SHA224Context sha224Context; SHA256Context sha256Context;
+ SHA384Context sha384Context; SHA512Context sha512Context;
+ } ctx;
+} USHAContext;
+
+/*
+ * This structure will hold context information for the HMAC
+ * keyed hashing operation.
+ */
+typedef struct HMACContext {
+ int whichSha; /* which SHA is being used */
+ int hashSize; /* hash size of SHA being used */
+ int blockSize; /* block size of SHA being used */
+ USHAContext shaContext; /* SHA context */
+ unsigned char k_opad[USHA_Max_Message_Block_Size];
+ /* outer padding - key XORd with opad */
+} HMACContext;
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 21]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+/*
+ * Function Prototypes
+ */
+
+/* SHA-1 */
+extern int SHA1Reset(SHA1Context *);
+extern int SHA1Input(SHA1Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA1FinalBits(SHA1Context *, const uint8_t bits,
+ unsigned int bitcount);
+extern int SHA1Result(SHA1Context *,
+ uint8_t Message_Digest[SHA1HashSize]);
+
+/* SHA-224 */
+extern int SHA224Reset(SHA224Context *);
+extern int SHA224Input(SHA224Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA224FinalBits(SHA224Context *, const uint8_t bits,
+ unsigned int bitcount);
+extern int SHA224Result(SHA224Context *,
+ uint8_t Message_Digest[SHA224HashSize]);
+
+/* SHA-256 */
+extern int SHA256Reset(SHA256Context *);
+extern int SHA256Input(SHA256Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA256FinalBits(SHA256Context *, const uint8_t bits,
+ unsigned int bitcount);
+extern int SHA256Result(SHA256Context *,
+ uint8_t Message_Digest[SHA256HashSize]);
+
+/* SHA-384 */
+extern int SHA384Reset(SHA384Context *);
+extern int SHA384Input(SHA384Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA384FinalBits(SHA384Context *, const uint8_t bits,
+ unsigned int bitcount);
+extern int SHA384Result(SHA384Context *,
+ uint8_t Message_Digest[SHA384HashSize]);
+
+/* SHA-512 */
+extern int SHA512Reset(SHA512Context *);
+extern int SHA512Input(SHA512Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA512FinalBits(SHA512Context *, const uint8_t bits,
+ unsigned int bitcount);
+extern int SHA512Result(SHA512Context *,
+ uint8_t Message_Digest[SHA512HashSize]);
+
+
+
+Eastlake 3rd & Hansen Informational [Page 22]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+/* Unified SHA functions, chosen by whichSha */
+extern int USHAReset(USHAContext *, SHAversion whichSha);
+extern int USHAInput(USHAContext *,
+ const uint8_t *bytes, unsigned int bytecount);
+extern int USHAFinalBits(USHAContext *,
+ const uint8_t bits, unsigned int bitcount);
+extern int USHAResult(USHAContext *,
+ uint8_t Message_Digest[USHAMaxHashSize]);
+extern int USHABlockSize(enum SHAversion whichSha);
+extern int USHAHashSize(enum SHAversion whichSha);
+extern int USHAHashSizeBits(enum SHAversion whichSha);
+
+/*
+ * HMAC Keyed-Hashing for Message Authentication, RFC2104,
+ * for all SHAs.
+ * This interface allows a fixed-length text input to be used.
+ */
+extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */
+ const unsigned char *text, /* pointer to data stream */
+ int text_len, /* length of data stream */
+ const unsigned char *key, /* pointer to authentication key */
+ int key_len, /* length of authentication key */
+ uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */
+
+/*
+ * HMAC Keyed-Hashing for Message Authentication, RFC2104,
+ * for all SHAs.
+ * This interface allows any length of text input to be used.
+ */
+extern int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
+ const unsigned char *key, int key_len);
+extern int hmacInput(HMACContext *ctx, const unsigned char *text,
+ int text_len);
+
+extern int hmacFinalBits(HMACContext *ctx, const uint8_t bits,
+ unsigned int bitcount);
+extern int hmacResult(HMACContext *ctx,
+ uint8_t digest[USHAMaxHashSize]);
+
+#endif /* _SHA_H_ */
+
+
+
+
+
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 23]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+8.2. The SHA Code
+
+ This code is primarily intended as expository and could be optimized
+ further. For example, the assignment rotations through the variables
+ a, b, ..., h could be treated as a cycle and the loop unrolled,
+ rather than doing the explicit copying.
+
+ Note that there are alternative representations of the Ch() and Maj()
+ functions controlled by an ifdef.
+
+8.2.1. sha1.c
+
+/**************************** sha1.c ****************************/
+/******************** See RFC 4634 for details ******************/
+/*
+ * Description:
+ * This file implements the Secure Hash Signature Standard
+ * algorithms as defined in the National Institute of Standards
+ * and Technology Federal Information Processing Standards
+ * Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
+ * published on August 1, 2002, and the FIPS PUB 180-2 Change
+ * Notice published on February 28, 2004.
+ *
+ * A combined document showing all algorithms is available at
+ * http://csrc.nist.gov/publications/fips/
+ * fips180-2/fips180-2withchangenotice.pdf
+ *
+ * The SHA-1 algorithm produces a 160-bit message digest for a
+ * given data stream. It should take about 2**n steps to find a
+ * message with the same digest as a given message and
+ * 2**(n/2) to find any two messages with the same digest,
+ * when n is the digest size in bits. Therefore, this
+ * algorithm can serve as a means of providing a
+ * "fingerprint" for a message.
+ *
+ * Portability Issues:
+ * SHA-1 is defined in terms of 32-bit "words". This code
+ * uses <stdint.h> (included via "sha.h") to define 32 and 8
+ * bit unsigned integer types. If your C compiler does not
+ * support 32 bit unsigned integers, this code is not
+ * appropriate.
+ *
+ * Caveats:
+ * SHA-1 is designed to work with messages less than 2^64 bits
+ * long. This implementation uses SHA1Input() to hash the bits
+ * that are a multiple of the size of an 8-bit character, and then
+ * uses SHA1FinalBits() to hash the final few bits of the input.
+ */
+
+
+
+Eastlake 3rd & Hansen Informational [Page 24]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+#include "sha.h"
+#include "sha-private.h"
+
+/*
+ * Define the SHA1 circular left shift macro
+ */
+#define SHA1_ROTL(bits,word) \
+ (((word) << (bits)) | ((word) >> (32-(bits))))
+
+/*
+ * add "length" to the length
+ */
+static uint32_t addTemp;
+#define SHA1AddLength(context, length) \
+ (addTemp = (context)->Length_Low, \
+ (context)->Corrupted = \
+ (((context)->Length_Low += (length)) < addTemp) && \
+ (++(context)->Length_High == 0) ? 1 : 0)
+
+/* Local Function Prototypes */
+static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte);
+static void SHA1PadMessage(SHA1Context *, uint8_t Pad_Byte);
+static void SHA1ProcessMessageBlock(SHA1Context *);
+
+/*
+ * SHA1Reset
+ *
+ * Description:
+ * This function will initialize the SHA1Context in preparation
+ * for computing a new SHA1 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA1Reset(SHA1Context *context)
+{
+ if (!context)
+ return shaNull;
+
+ context->Length_Low = 0;
+ context->Length_High = 0;
+ context->Message_Block_Index = 0;
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 25]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ /* Initial Hash Values: FIPS-180-2 section 5.3.1 */
+ context->Intermediate_Hash[0] = 0x67452301;
+ context->Intermediate_Hash[1] = 0xEFCDAB89;
+ context->Intermediate_Hash[2] = 0x98BADCFE;
+ context->Intermediate_Hash[3] = 0x10325476;
+ context->Intermediate_Hash[4] = 0xC3D2E1F0;
+
+ context->Computed = 0;
+ context->Corrupted = 0;
+
+ return shaSuccess;
+}
+
+/*
+ * SHA1Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_array: [in]
+ * An array of characters representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA1Input(SHA1Context *context,
+ const uint8_t *message_array, unsigned length)
+{
+ if (!length)
+ return shaSuccess;
+
+ if (!context || !message_array)
+ return shaNull;
+
+ if (context->Computed) {
+ context->Corrupted = shaStateError;
+ return shaStateError;
+ }
+
+ if (context->Corrupted)
+
+
+
+Eastlake 3rd & Hansen Informational [Page 26]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ return context->Corrupted;
+
+ while (length-- && !context->Corrupted) {
+ context->Message_Block[context->Message_Block_Index++] =
+ (*message_array & 0xFF);
+
+ if (!SHA1AddLength(context, 8) &&
+ (context->Message_Block_Index == SHA1_Message_Block_Size))
+ SHA1ProcessMessageBlock(context);
+
+ message_array++;
+ }
+
+ return shaSuccess;
+}
+
+/*
+ * SHA1FinalBits
+ *
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA1FinalBits(SHA1Context *context, const uint8_t message_bits,
+ unsigned int length)
+{
+ uint8_t masks[8] = {
+ /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
+ /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
+ /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
+ /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
+ };
+ uint8_t markbit[8] = {
+ /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
+ /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
+ /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
+
+
+
+Eastlake 3rd & Hansen Informational [Page 27]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
+ };
+
+ if (!length)
+ return shaSuccess;
+
+ if (!context)
+ return shaNull;
+
+ if (context->Computed || (length >= 8) || (length == 0)) {
+ context->Corrupted = shaStateError;
+ return shaStateError;
+ }
+
+ if (context->Corrupted)
+ return context->Corrupted;
+
+ SHA1AddLength(context, length);
+ SHA1Finalize(context,
+ (uint8_t) ((message_bits & masks[length]) | markbit[length]));
+
+ return shaSuccess;
+}
+
+/*
+ * SHA1Result
+ *
+ * Description:
+ * This function will return the 160-bit message digest into the
+ * Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 19th element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA-1 hash.
+ * Message_Digest: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA1Result(SHA1Context *context,
+ uint8_t Message_Digest[SHA1HashSize])
+{
+ int i;
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 28]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ if (!context || !Message_Digest)
+ return shaNull;
+
+ if (context->Corrupted)
+ return context->Corrupted;
+
+ if (!context->Computed)
+ SHA1Finalize(context, 0x80);
+
+ for (i = 0; i < SHA1HashSize; ++i)
+ Message_Digest[i] = (uint8_t) (context->Intermediate_Hash[i>>2]
+ >> 8 * ( 3 - ( i & 0x03 ) ));
+
+ return shaSuccess;
+}
+
+/*
+ * SHA1Finalize
+ *
+ * Description:
+ * This helper function finishes off the digest calculations.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * Pad_Byte: [in]
+ * The last byte to add to the digest before the 0-padding
+ * and length. This will contain the last bits of the message
+ * followed by another single bit. If the message was an
+ * exact multiple of 8-bits long, Pad_Byte will be 0x80.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+static void SHA1Finalize(SHA1Context *context, uint8_t Pad_Byte)
+{
+ int i;
+ SHA1PadMessage(context, Pad_Byte);
+ /* message may be sensitive, clear it out */
+ for (i = 0; i < SHA1_Message_Block_Size; ++i)
+ context->Message_Block[i] = 0;
+ context->Length_Low = 0; /* and clear length */
+ context->Length_High = 0;
+ context->Computed = 1;
+}
+
+/*
+
+
+
+Eastlake 3rd & Hansen Informational [Page 29]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * SHA1PadMessage
+ *
+ * Description:
+ * According to the standard, the message must be padded to an
+ * even 512 bits. The first padding bit must be a '1'. The last
+ * 64 bits represent the length of the original message. All bits
+ * in between should be 0. This helper function will pad the
+ * message according to those rules by filling the Message_Block
+ * array accordingly. When it returns, it can be assumed that the
+ * message digest has been computed.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to pad
+ * Pad_Byte: [in]
+ * The last byte to add to the digest before the 0-padding
+ * and length. This will contain the last bits of the message
+ * followed by another single bit. If the message was an
+ * exact multiple of 8-bits long, Pad_Byte will be 0x80.
+ *
+ * Returns:
+ * Nothing.
+ */
+static void SHA1PadMessage(SHA1Context *context, uint8_t Pad_Byte)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (context->Message_Block_Index >= (SHA1_Message_Block_Size - 8)) {
+ context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+ while (context->Message_Block_Index < SHA1_Message_Block_Size)
+ context->Message_Block[context->Message_Block_Index++] = 0;
+
+ SHA1ProcessMessageBlock(context);
+ } else
+ context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+
+ while (context->Message_Block_Index < (SHA1_Message_Block_Size - 8))
+ context->Message_Block[context->Message_Block_Index++] = 0;
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ context->Message_Block[56] = (uint8_t) (context->Length_High >> 24);
+ context->Message_Block[57] = (uint8_t) (context->Length_High >> 16);
+
+
+
+Eastlake 3rd & Hansen Informational [Page 30]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ context->Message_Block[58] = (uint8_t) (context->Length_High >> 8);
+ context->Message_Block[59] = (uint8_t) (context->Length_High);
+ context->Message_Block[60] = (uint8_t) (context->Length_Low >> 24);
+ context->Message_Block[61] = (uint8_t) (context->Length_Low >> 16);
+ context->Message_Block[62] = (uint8_t) (context->Length_Low >> 8);
+ context->Message_Block[63] = (uint8_t) (context->Length_Low);
+
+ SHA1ProcessMessageBlock(context);
+}
+
+/*
+ * SHA1ProcessMessageBlock
+ *
+ * Description:
+ * This helper function will process the next 512 bits of the
+ * message stored in the Message_Block array.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ * Many of the variable names in this code, especially the
+ * single character names, were used because those were the
+ * names used in the publication.
+ */
+static void SHA1ProcessMessageBlock(SHA1Context *context)
+{
+ /* Constants defined in FIPS-180-2, section 4.2.1 */
+ const uint32_t K[4] = {
+ 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6
+ };
+ int t; /* Loop counter */
+ uint32_t temp; /* Temporary word value */
+ uint32_t W[80]; /* Word sequence */
+ uint32_t A, B, C, D, E; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for (t = 0; t < 16; t++) {
+ W[t] = ((uint32_t)context->Message_Block[t * 4]) << 24;
+ W[t] |= ((uint32_t)context->Message_Block[t * 4 + 1]) << 16;
+ W[t] |= ((uint32_t)context->Message_Block[t * 4 + 2]) << 8;
+ W[t] |= ((uint32_t)context->Message_Block[t * 4 + 3]);
+ }
+
+
+
+Eastlake 3rd & Hansen Informational [Page 31]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ for (t = 16; t < 80; t++)
+ W[t] = SHA1_ROTL(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+
+ A = context->Intermediate_Hash[0];
+ B = context->Intermediate_Hash[1];
+ C = context->Intermediate_Hash[2];
+ D = context->Intermediate_Hash[3];
+ E = context->Intermediate_Hash[4];
+
+ for (t = 0; t < 20; t++) {
+ temp = SHA1_ROTL(5,A) + SHA_Ch(B, C, D) + E + W[t] + K[0];
+ E = D;
+ D = C;
+ C = SHA1_ROTL(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for (t = 20; t < 40; t++) {
+ temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[1];
+ E = D;
+ D = C;
+ C = SHA1_ROTL(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for (t = 40; t < 60; t++) {
+ temp = SHA1_ROTL(5,A) + SHA_Maj(B, C, D) + E + W[t] + K[2];
+ E = D;
+ D = C;
+ C = SHA1_ROTL(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for (t = 60; t < 80; t++) {
+ temp = SHA1_ROTL(5,A) + SHA_Parity(B, C, D) + E + W[t] + K[3];
+ E = D;
+ D = C;
+ C = SHA1_ROTL(30,B);
+ B = A;
+ A = temp;
+ }
+
+ context->Intermediate_Hash[0] += A;
+ context->Intermediate_Hash[1] += B;
+ context->Intermediate_Hash[2] += C;
+
+
+
+Eastlake 3rd & Hansen Informational [Page 32]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ context->Intermediate_Hash[3] += D;
+ context->Intermediate_Hash[4] += E;
+
+ context->Message_Block_Index = 0;
+}
+
+8.2.2. sha224-256.c
+
+/*************************** sha224-256.c ***************************/
+/********************* See RFC 4634 for details *********************/
+/*
+ * Description:
+ * This file implements the Secure Hash Signature Standard
+ * algorithms as defined in the National Institute of Standards
+ * and Technology Federal Information Processing Standards
+ * Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
+ * published on August 1, 2002, and the FIPS PUB 180-2 Change
+ * Notice published on February 28, 2004.
+ *
+ * A combined document showing all algorithms is available at
+ * http://csrc.nist.gov/publications/fips/
+ * fips180-2/fips180-2withchangenotice.pdf
+ *
+ * The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit
+ * message digests for a given data stream. It should take about
+ * 2**n steps to find a message with the same digest as a given
+ * message and 2**(n/2) to find any two messages with the same
+ * digest, when n is the digest size in bits. Therefore, this
+ * algorithm can serve as a means of providing a
+ * "fingerprint" for a message.
+ *
+ * Portability Issues:
+ * SHA-224 and SHA-256 are defined in terms of 32-bit "words".
+ * This code uses <stdint.h> (included via "sha.h") to define 32
+ * and 8 bit unsigned integer types. If your C compiler does not
+ * support 32 bit unsigned integers, this code is not
+ * appropriate.
+ *
+ * Caveats:
+ * SHA-224 and SHA-256 are designed to work with messages less
+ * than 2^64 bits long. This implementation uses SHA224/256Input()
+ * to hash the bits that are a multiple of the size of an 8-bit
+ * character, and then uses SHA224/256FinalBits() to hash the
+ * final few bits of the input.
+ */
+
+#include "sha.h"
+#include "sha-private.h"
+
+
+
+Eastlake 3rd & Hansen Informational [Page 33]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+/* Define the SHA shift, rotate left and rotate right macro */
+#define SHA256_SHR(bits,word) ((word) >> (bits))
+#define SHA256_ROTL(bits,word) \
+ (((word) << (bits)) | ((word) >> (32-(bits))))
+#define SHA256_ROTR(bits,word) \
+ (((word) >> (bits)) | ((word) << (32-(bits))))
+
+/* Define the SHA SIGMA and sigma macros */
+#define SHA256_SIGMA0(word) \
+ (SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word))
+#define SHA256_SIGMA1(word) \
+ (SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word))
+#define SHA256_sigma0(word) \
+ (SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word))
+#define SHA256_sigma1(word) \
+ (SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word))
+
+/*
+ * add "length" to the length
+ */
+static uint32_t addTemp;
+#define SHA224_256AddLength(context, length) \
+ (addTemp = (context)->Length_Low, (context)->Corrupted = \
+ (((context)->Length_Low += (length)) < addTemp) && \
+ (++(context)->Length_High == 0) ? 1 : 0)
+
+/* Local Function Prototypes */
+static void SHA224_256Finalize(SHA256Context *context,
+ uint8_t Pad_Byte);
+static void SHA224_256PadMessage(SHA256Context *context,
+ uint8_t Pad_Byte);
+static void SHA224_256ProcessMessageBlock(SHA256Context *context);
+static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
+static int SHA224_256ResultN(SHA256Context *context,
+ uint8_t Message_Digest[], int HashSize);
+
+/* Initial Hash Values: FIPS-180-2 Change Notice 1 */
+static uint32_t SHA224_H0[SHA256HashSize/4] = {
+ 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
+ 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
+};
+
+/* Initial Hash Values: FIPS-180-2 section 5.3.2 */
+static uint32_t SHA256_H0[SHA256HashSize/4] = {
+ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
+ 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
+};
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 34]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+/*
+ * SHA224Reset
+ *
+ * Description:
+ * This function will initialize the SHA384Context in preparation
+ * for computing a new SHA224 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA224Reset(SHA224Context *context)
+{
+ return SHA224_256Reset(context, SHA224_H0);
+}
+
+/*
+ * SHA224Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_array: [in]
+ * An array of characters representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA224Input(SHA224Context *context, const uint8_t *message_array,
+ unsigned int length)
+{
+ return SHA256Input(context, message_array, length);
+}
+
+/*
+ * SHA224FinalBits
+ *
+
+
+
+Eastlake 3rd & Hansen Informational [Page 35]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA224FinalBits( SHA224Context *context,
+ const uint8_t message_bits, unsigned int length)
+{
+ return SHA256FinalBits(context, message_bits, length);
+}
+
+/*
+ * SHA224Result
+ *
+ * Description:
+ * This function will return the 224-bit message
+ * digest into the Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 28th element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA224Result(SHA224Context *context,
+ uint8_t Message_Digest[SHA224HashSize])
+{
+ return SHA224_256ResultN(context, Message_Digest, SHA224HashSize);
+}
+
+/*
+ * SHA256Reset
+
+
+
+Eastlake 3rd & Hansen Informational [Page 36]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ *
+ * Description:
+ * This function will initialize the SHA256Context in preparation
+ * for computing a new SHA256 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256Reset(SHA256Context *context)
+{
+ return SHA224_256Reset(context, SHA256_H0);
+}
+
+/*
+ * SHA256Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_array: [in]
+ * An array of characters representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256Input(SHA256Context *context, const uint8_t *message_array,
+ unsigned int length)
+{
+ if (!length)
+ return shaSuccess;
+
+ if (!context || !message_array)
+ return shaNull;
+
+ if (context->Computed) {
+ context->Corrupted = shaStateError;
+ return shaStateError;
+
+
+
+Eastlake 3rd & Hansen Informational [Page 37]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ }
+
+ if (context->Corrupted)
+ return context->Corrupted;
+
+ while (length-- && !context->Corrupted) {
+ context->Message_Block[context->Message_Block_Index++] =
+ (*message_array & 0xFF);
+
+ if (!SHA224_256AddLength(context, 8) &&
+ (context->Message_Block_Index == SHA256_Message_Block_Size))
+ SHA224_256ProcessMessageBlock(context);
+
+ message_array++;
+ }
+
+ return shaSuccess;
+
+}
+
+/*
+ * SHA256FinalBits
+ *
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256FinalBits(SHA256Context *context,
+ const uint8_t message_bits, unsigned int length)
+{
+ uint8_t masks[8] = {
+ /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
+ /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
+ /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
+ /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
+ };
+
+
+
+Eastlake 3rd & Hansen Informational [Page 38]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ uint8_t markbit[8] = {
+ /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
+ /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
+ /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
+ /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
+ };
+
+ if (!length)
+ return shaSuccess;
+
+ if (!context)
+ return shaNull;
+
+ if ((context->Computed) || (length >= 8) || (length == 0)) {
+ context->Corrupted = shaStateError;
+ return shaStateError;
+ }
+
+ if (context->Corrupted)
+ return context->Corrupted;
+
+ SHA224_256AddLength(context, length);
+ SHA224_256Finalize(context, (uint8_t)
+ ((message_bits & masks[length]) | markbit[length]));
+
+ return shaSuccess;
+}
+
+/*
+ * SHA256Result
+ *
+ * Description:
+ * This function will return the 256-bit message
+ * digest into the Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 32nd element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256Result(SHA256Context *context, uint8_t Message_Digest[])
+{
+
+
+
+Eastlake 3rd & Hansen Informational [Page 39]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ return SHA224_256ResultN(context, Message_Digest, SHA256HashSize);
+}
+
+/*
+ * SHA224_256Finalize
+ *
+ * Description:
+ * This helper function finishes off the digest calculations.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * Pad_Byte: [in]
+ * The last byte to add to the digest before the 0-padding
+ * and length. This will contain the last bits of the message
+ * followed by another single bit. If the message was an
+ * exact multiple of 8-bits long, Pad_Byte will be 0x80.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+static void SHA224_256Finalize(SHA256Context *context,
+ uint8_t Pad_Byte)
+{
+ int i;
+ SHA224_256PadMessage(context, Pad_Byte);
+ /* message may be sensitive, so clear it out */
+ for (i = 0; i < SHA256_Message_Block_Size; ++i)
+ context->Message_Block[i] = 0;
+ context->Length_Low = 0; /* and clear length */
+ context->Length_High = 0;
+ context->Computed = 1;
+}
+
+/*
+ * SHA224_256PadMessage
+ *
+ * Description:
+ * According to the standard, the message must be padded to an
+ * even 512 bits. The first padding bit must be a '1'. The
+ * last 64 bits represent the length of the original message.
+ * All bits in between should be 0. This helper function will pad
+ * the message according to those rules by filling the
+ * Message_Block array accordingly. When it returns, it can be
+ * assumed that the message digest has been computed.
+ *
+ * Parameters:
+ * context: [in/out]
+
+
+
+Eastlake 3rd & Hansen Informational [Page 40]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * The context to pad
+ * Pad_Byte: [in]
+ * The last byte to add to the digest before the 0-padding
+ * and length. This will contain the last bits of the message
+ * followed by another single bit. If the message was an
+ * exact multiple of 8-bits long, Pad_Byte will be 0x80.
+ *
+ * Returns:
+ * Nothing.
+ */
+static void SHA224_256PadMessage(SHA256Context *context,
+ uint8_t Pad_Byte)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (context->Message_Block_Index >= (SHA256_Message_Block_Size-8)) {
+ context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+ while (context->Message_Block_Index < SHA256_Message_Block_Size)
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ SHA224_256ProcessMessageBlock(context);
+ } else
+ context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+
+ while (context->Message_Block_Index < (SHA256_Message_Block_Size-8))
+ context->Message_Block[context->Message_Block_Index++] = 0;
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
+ context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
+ context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
+ context->Message_Block[59] = (uint8_t)(context->Length_High);
+ context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
+ context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
+ context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
+ context->Message_Block[63] = (uint8_t)(context->Length_Low);
+
+ SHA224_256ProcessMessageBlock(context);
+}
+
+/*
+ * SHA224_256ProcessMessageBlock
+ *
+
+
+
+Eastlake 3rd & Hansen Informational [Page 41]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * Description:
+ * This function will process the next 512 bits of the message
+ * stored in the Message_Block array.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ * Many of the variable names in this code, especially the
+ * single character names, were used because those were the
+ * names used in the publication.
+ */
+static void SHA224_256ProcessMessageBlock(SHA256Context *context)
+{
+ /* Constants defined in FIPS-180-2, section 4.2.2 */
+ static const uint32_t K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
+ 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
+ 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
+ 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
+ 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
+ 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
+ 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
+ 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
+ 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+ int t, t4; /* Loop counter */
+ uint32_t temp1, temp2; /* Temporary word value */
+ uint32_t W[64]; /* Word sequence */
+ uint32_t A, B, C, D, E, F, G, H; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for (t = t4 = 0; t < 16; t++, t4 += 4)
+ W[t] = (((uint32_t)context->Message_Block[t4]) << 24) |
+ (((uint32_t)context->Message_Block[t4 + 1]) << 16) |
+ (((uint32_t)context->Message_Block[t4 + 2]) << 8) |
+ (((uint32_t)context->Message_Block[t4 + 3]));
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 42]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ for (t = 16; t < 64; t++)
+ W[t] = SHA256_sigma1(W[t-2]) + W[t-7] +
+ SHA256_sigma0(W[t-15]) + W[t-16];
+
+ A = context->Intermediate_Hash[0];
+ B = context->Intermediate_Hash[1];
+ C = context->Intermediate_Hash[2];
+ D = context->Intermediate_Hash[3];
+ E = context->Intermediate_Hash[4];
+ F = context->Intermediate_Hash[5];
+ G = context->Intermediate_Hash[6];
+ H = context->Intermediate_Hash[7];
+
+ for (t = 0; t < 64; t++) {
+ temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t];
+ temp2 = SHA256_SIGMA0(A) + SHA_Maj(A,B,C);
+ H = G;
+ G = F;
+ F = E;
+ E = D + temp1;
+ D = C;
+ C = B;
+ B = A;
+ A = temp1 + temp2;
+ }
+
+ context->Intermediate_Hash[0] += A;
+ context->Intermediate_Hash[1] += B;
+ context->Intermediate_Hash[2] += C;
+ context->Intermediate_Hash[3] += D;
+ context->Intermediate_Hash[4] += E;
+ context->Intermediate_Hash[5] += F;
+ context->Intermediate_Hash[6] += G;
+ context->Intermediate_Hash[7] += H;
+
+ context->Message_Block_Index = 0;
+}
+
+/*
+ * SHA224_256Reset
+ *
+ * Description:
+ * This helper function will initialize the SHA256Context in
+ * preparation for computing a new SHA256 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+
+
+
+Eastlake 3rd & Hansen Informational [Page 43]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * H0
+ * The initial hash value to use.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
+{
+ if (!context)
+ return shaNull;
+
+ context->Length_Low = 0;
+ context->Length_High = 0;
+ context->Message_Block_Index = 0;
+
+ context->Intermediate_Hash[0] = H0[0];
+ context->Intermediate_Hash[1] = H0[1];
+ context->Intermediate_Hash[2] = H0[2];
+ context->Intermediate_Hash[3] = H0[3];
+ context->Intermediate_Hash[4] = H0[4];
+ context->Intermediate_Hash[5] = H0[5];
+ context->Intermediate_Hash[6] = H0[6];
+ context->Intermediate_Hash[7] = H0[7];
+
+ context->Computed = 0;
+ context->Corrupted = 0;
+
+ return shaSuccess;
+}
+
+/*
+ * SHA224_256ResultN
+ *
+ * Description:
+ * This helper function will return the 224-bit or 256-bit message
+ * digest into the Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 28th/32nd element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest: [out]
+ * Where the digest is returned.
+ * HashSize: [in]
+ * The size of the hash, either 28 or 32.
+ *
+ * Returns:
+
+
+
+Eastlake 3rd & Hansen Informational [Page 44]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * sha Error Code.
+ */
+static int SHA224_256ResultN(SHA256Context *context,
+ uint8_t Message_Digest[], int HashSize)
+{
+ int i;
+
+ if (!context || !Message_Digest)
+ return shaNull;
+
+ if (context->Corrupted)
+ return context->Corrupted;
+
+ if (!context->Computed)
+ SHA224_256Finalize(context, 0x80);
+
+ for (i = 0; i < HashSize; ++i)
+ Message_Digest[i] = (uint8_t)
+ (context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ));
+
+ return shaSuccess;
+}
+
+8.2.3. sha384-512.c
+
+/*************************** sha384-512.c ***************************/
+/********************* See RFC 4634 for details *********************/
+/*
+ * Description:
+ * This file implements the Secure Hash Signature Standard
+ * algorithms as defined in the National Institute of Standards
+ * and Technology Federal Information Processing Standards
+ * Publication (FIPS PUB) 180-1 published on April 17, 1995, 180-2
+ * published on August 1, 2002, and the FIPS PUB 180-2 Change
+ * Notice published on February 28, 2004.
+ *
+ * A combined document showing all algorithms is available at
+ * http://csrc.nist.gov/publications/fips/
+ * fips180-2/fips180-2withchangenotice.pdf
+ *
+ * The SHA-384 and SHA-512 algorithms produce 384-bit and 512-bit
+ * message digests for a given data stream. It should take about
+ * 2**n steps to find a message with the same digest as a given
+ * message and 2**(n/2) to find any two messages with the same
+ * digest, when n is the digest size in bits. Therefore, this
+ * algorithm can serve as a means of providing a
+ * "fingerprint" for a message.
+ *
+
+
+
+Eastlake 3rd & Hansen Informational [Page 45]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * Portability Issues:
+ * SHA-384 and SHA-512 are defined in terms of 64-bit "words",
+ * but if USE_32BIT_ONLY is #defined, this code is implemented in
+ * terms of 32-bit "words". This code uses <stdint.h> (included
+ * via "sha.h") to define the 64, 32 and 8 bit unsigned integer
+ * types. If your C compiler does not support 64 bit unsigned
+ * integers, and you do not #define USE_32BIT_ONLY, this code is
+ * not appropriate.
+ *
+ * Caveats:
+ * SHA-384 and SHA-512 are designed to work with messages less
+ * than 2^128 bits long. This implementation uses
+ * SHA384/512Input() to hash the bits that are a multiple of the
+ * size of an 8-bit character, and then uses SHA384/256FinalBits()
+ * to hash the final few bits of the input.
+ *
+ */
+
+#include "sha.h"
+#include "sha-private.h"
+
+#ifdef USE_32BIT_ONLY
+/*
+ * Define 64-bit arithmetic in terms of 32-bit arithmetic.
+ * Each 64-bit number is represented in a 2-word array.
+ * All macros are defined such that the result is the last parameter.
+ */
+
+/*
+ * Define shift, rotate left and rotate right functions
+ */
+#define SHA512_SHR(bits, word, ret) ( \
+ /* (((uint64_t)((word))) >> (bits)) */ \
+ (ret)[0] = (((bits) < 32) && ((bits) >= 0)) ? \
+ ((word)[0] >> (bits)) : 0, \
+ (ret)[1] = ((bits) > 32) ? ((word)[0] >> ((bits) - 32)) : \
+ ((bits) == 32) ? (word)[0] : \
+ ((bits) >= 0) ? \
+ (((word)[0] << (32 - (bits))) | \
+ ((word)[1] >> (bits))) : 0 )
+
+#define SHA512_SHL(bits, word, ret) ( \
+ /* (((uint64_t)(word)) << (bits)) */ \
+ (ret)[0] = ((bits) > 32) ? ((word)[1] << ((bits) - 32)) : \
+ ((bits) == 32) ? (word)[1] : \
+ ((bits) >= 0) ? \
+ (((word)[0] << (bits)) | \
+ ((word)[1] >> (32 - (bits)))) : \
+
+
+
+Eastlake 3rd & Hansen Informational [Page 46]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ 0, \
+ (ret)[1] = (((bits) < 32) && ((bits) >= 0)) ? \
+ ((word)[1] << (bits)) : 0 )
+
+/*
+ * Define 64-bit OR
+ */
+#define SHA512_OR(word1, word2, ret) ( \
+ (ret)[0] = (word1)[0] | (word2)[0], \
+ (ret)[1] = (word1)[1] | (word2)[1] )
+
+/*
+ * Define 64-bit XOR
+ */
+#define SHA512_XOR(word1, word2, ret) ( \
+ (ret)[0] = (word1)[0] ^ (word2)[0], \
+ (ret)[1] = (word1)[1] ^ (word2)[1] )
+
+/*
+ * Define 64-bit AND
+ */
+#define SHA512_AND(word1, word2, ret) ( \
+ (ret)[0] = (word1)[0] & (word2)[0], \
+ (ret)[1] = (word1)[1] & (word2)[1] )
+
+/*
+ * Define 64-bit TILDA
+ */
+#define SHA512_TILDA(word, ret) \
+ ( (ret)[0] = ~(word)[0], (ret)[1] = ~(word)[1] )
+
+/*
+ * Define 64-bit ADD
+ */
+#define SHA512_ADD(word1, word2, ret) ( \
+ (ret)[1] = (word1)[1], (ret)[1] += (word2)[1], \
+ (ret)[0] = (word1)[0] + (word2)[0] + ((ret)[1] < (word1)[1]) )
+
+/*
+ * Add the 4word value in word2 to word1.
+ */
+static uint32_t ADDTO4_temp, ADDTO4_temp2;
+#define SHA512_ADDTO4(word1, word2) ( \
+ ADDTO4_temp = (word1)[3], \
+ (word1)[3] += (word2)[3], \
+ ADDTO4_temp2 = (word1)[2], \
+ (word1)[2] += (word2)[2] + ((word1)[3] < ADDTO4_temp), \
+ ADDTO4_temp = (word1)[1], \
+
+
+
+Eastlake 3rd & Hansen Informational [Page 47]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ (word1)[1] += (word2)[1] + ((word1)[2] < ADDTO4_temp2), \
+ (word1)[0] += (word2)[0] + ((word1)[1] < ADDTO4_temp) )
+
+/*
+ * Add the 2word value in word2 to word1.
+ */
+static uint32_t ADDTO2_temp;
+#define SHA512_ADDTO2(word1, word2) ( \
+ ADDTO2_temp = (word1)[1], \
+ (word1)[1] += (word2)[1], \
+ (word1)[0] += (word2)[0] + ((word1)[1] < ADDTO2_temp) )
+
+/*
+ * SHA rotate ((word >> bits) | (word << (64-bits)))
+ */
+static uint32_t ROTR_temp1[2], ROTR_temp2[2];
+#define SHA512_ROTR(bits, word, ret) ( \
+ SHA512_SHR((bits), (word), ROTR_temp1), \
+ SHA512_SHL(64-(bits), (word), ROTR_temp2), \
+ SHA512_OR(ROTR_temp1, ROTR_temp2, (ret)) )
+
+/*
+ * Define the SHA SIGMA and sigma macros
+ * SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word)
+ */
+static uint32_t SIGMA0_temp1[2], SIGMA0_temp2[2],
+ SIGMA0_temp3[2], SIGMA0_temp4[2];
+#define SHA512_SIGMA0(word, ret) ( \
+ SHA512_ROTR(28, (word), SIGMA0_temp1), \
+ SHA512_ROTR(34, (word), SIGMA0_temp2), \
+ SHA512_ROTR(39, (word), SIGMA0_temp3), \
+ SHA512_XOR(SIGMA0_temp2, SIGMA0_temp3, SIGMA0_temp4), \
+ SHA512_XOR(SIGMA0_temp1, SIGMA0_temp4, (ret)) )
+
+/*
+ * SHA512_ROTR(14,word) ^ SHA512_ROTR(18,word) ^ SHA512_ROTR(41,word)
+ */
+static uint32_t SIGMA1_temp1[2], SIGMA1_temp2[2],
+ SIGMA1_temp3[2], SIGMA1_temp4[2];
+#define SHA512_SIGMA1(word, ret) ( \
+ SHA512_ROTR(14, (word), SIGMA1_temp1), \
+ SHA512_ROTR(18, (word), SIGMA1_temp2), \
+ SHA512_ROTR(41, (word), SIGMA1_temp3), \
+ SHA512_XOR(SIGMA1_temp2, SIGMA1_temp3, SIGMA1_temp4), \
+ SHA512_XOR(SIGMA1_temp1, SIGMA1_temp4, (ret)) )
+
+/*
+ * (SHA512_ROTR( 1,word) ^ SHA512_ROTR( 8,word) ^ SHA512_SHR( 7,word))
+
+
+
+Eastlake 3rd & Hansen Informational [Page 48]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ */
+static uint32_t sigma0_temp1[2], sigma0_temp2[2],
+ sigma0_temp3[2], sigma0_temp4[2];
+#define SHA512_sigma0(word, ret) ( \
+ SHA512_ROTR( 1, (word), sigma0_temp1), \
+ SHA512_ROTR( 8, (word), sigma0_temp2), \
+ SHA512_SHR( 7, (word), sigma0_temp3), \
+ SHA512_XOR(sigma0_temp2, sigma0_temp3, sigma0_temp4), \
+ SHA512_XOR(sigma0_temp1, sigma0_temp4, (ret)) )
+
+/*
+ * (SHA512_ROTR(19,word) ^ SHA512_ROTR(61,word) ^ SHA512_SHR( 6,word))
+ */
+static uint32_t sigma1_temp1[2], sigma1_temp2[2],
+ sigma1_temp3[2], sigma1_temp4[2];
+#define SHA512_sigma1(word, ret) ( \
+ SHA512_ROTR(19, (word), sigma1_temp1), \
+ SHA512_ROTR(61, (word), sigma1_temp2), \
+ SHA512_SHR( 6, (word), sigma1_temp3), \
+ SHA512_XOR(sigma1_temp2, sigma1_temp3, sigma1_temp4), \
+ SHA512_XOR(sigma1_temp1, sigma1_temp4, (ret)) )
+
+#undef SHA_Ch
+#undef SHA_Maj
+
+#ifndef USE_MODIFIED_MACROS
+/*
+ * These definitions are the ones used in FIPS-180-2, section 4.1.3
+ * Ch(x,y,z) ((x & y) ^ (~x & z))
+ */
+static uint32_t Ch_temp1[2], Ch_temp2[2], Ch_temp3[2];
+#define SHA_Ch(x, y, z, ret) ( \
+ SHA512_AND(x, y, Ch_temp1), \
+ SHA512_TILDA(x, Ch_temp2), \
+ SHA512_AND(Ch_temp2, z, Ch_temp3), \
+ SHA512_XOR(Ch_temp1, Ch_temp3, (ret)) )
+/*
+ * Maj(x,y,z) (((x)&(y)) ^ ((x)&(z)) ^ ((y)&(z)))
+ */
+static uint32_t Maj_temp1[2], Maj_temp2[2],
+ Maj_temp3[2], Maj_temp4[2];
+#define SHA_Maj(x, y, z, ret) ( \
+ SHA512_AND(x, y, Maj_temp1), \
+ SHA512_AND(x, z, Maj_temp2), \
+ SHA512_AND(y, z, Maj_temp3), \
+ SHA512_XOR(Maj_temp2, Maj_temp3, Maj_temp4), \
+ SHA512_XOR(Maj_temp1, Maj_temp4, (ret)) )
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 49]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+#else /* !USE_32BIT_ONLY */
+/*
+ * These definitions are potentially faster equivalents for the ones
+ * used in FIPS-180-2, section 4.1.3.
+ * ((x & y) ^ (~x & z)) becomes
+ * ((x & (y ^ z)) ^ z)
+ */
+#define SHA_Ch(x, y, z, ret) ( \
+ (ret)[0] = (((x)[0] & ((y)[0] ^ (z)[0])) ^ (z)[0]), \
+ (ret)[1] = (((x)[1] & ((y)[1] ^ (z)[1])) ^ (z)[1]) )
+
+/*
+ * ((x & y) ^ (x & z) ^ (y & z)) becomes
+ * ((x & (y | z)) | (y & z))
+ */
+#define SHA_Maj(x, y, z, ret) ( \
+ ret[0] = (((x)[0] & ((y)[0] | (z)[0])) | ((y)[0] & (z)[0])), \
+ ret[1] = (((x)[1] & ((y)[1] | (z)[1])) | ((y)[1] & (z)[1])) )
+#endif /* USE_MODIFIED_MACROS */
+
+/*
+ * add "length" to the length
+ */
+static uint32_t addTemp[4] = { 0, 0, 0, 0 };
+#define SHA384_512AddLength(context, length) ( \
+ addTemp[3] = (length), SHA512_ADDTO4((context)->Length, addTemp), \
+ (context)->Corrupted = (((context)->Length[3] == 0) && \
+ ((context)->Length[2] == 0) && ((context)->Length[1] == 0) && \
+ ((context)->Length[0] < 8)) ? 1 : 0 )
+
+/* Local Function Prototypes */
+static void SHA384_512Finalize(SHA512Context *context,
+ uint8_t Pad_Byte);
+static void SHA384_512PadMessage(SHA512Context *context,
+ uint8_t Pad_Byte);
+static void SHA384_512ProcessMessageBlock(SHA512Context *context);
+static int SHA384_512Reset(SHA512Context *context, uint32_t H0[]);
+static int SHA384_512ResultN( SHA512Context *context,
+ uint8_t Message_Digest[], int HashSize);
+
+/* Initial Hash Values: FIPS-180-2 sections 5.3.3 and 5.3.4 */
+static uint32_t SHA384_H0[SHA512HashSize/4] = {
+ 0xCBBB9D5D, 0xC1059ED8, 0x629A292A, 0x367CD507, 0x9159015A,
+ 0x3070DD17, 0x152FECD8, 0xF70E5939, 0x67332667, 0xFFC00B31,
+ 0x8EB44A87, 0x68581511, 0xDB0C2E0D, 0x64F98FA7, 0x47B5481D,
+ 0xBEFA4FA4
+};
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 50]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+static uint32_t SHA512_H0[SHA512HashSize/4] = {
+ 0x6A09E667, 0xF3BCC908, 0xBB67AE85, 0x84CAA73B, 0x3C6EF372,
+ 0xFE94F82B, 0xA54FF53A, 0x5F1D36F1, 0x510E527F, 0xADE682D1,
+ 0x9B05688C, 0x2B3E6C1F, 0x1F83D9AB, 0xFB41BD6B, 0x5BE0CD19,
+ 0x137E2179
+};
+
+#else /* !USE_32BIT_ONLY */
+
+/* Define the SHA shift, rotate left and rotate right macro */
+#define SHA512_SHR(bits,word) (((uint64_t)(word)) >> (bits))
+#define SHA512_ROTR(bits,word) ((((uint64_t)(word)) >> (bits)) | \
+ (((uint64_t)(word)) << (64-(bits))))
+
+/* Define the SHA SIGMA and sigma macros */
+#define SHA512_SIGMA0(word) \
+ (SHA512_ROTR(28,word) ^ SHA512_ROTR(34,word) ^ SHA512_ROTR(39,word))
+#define SHA512_SIGMA1(word) \
+ (SHA512_ROTR(14,word) ^ SHA512_ROTR(18,word) ^ SHA512_ROTR(41,word))
+#define SHA512_sigma0(word) \
+ (SHA512_ROTR( 1,word) ^ SHA512_ROTR( 8,word) ^ SHA512_SHR( 7,word))
+#define SHA512_sigma1(word) \
+ (SHA512_ROTR(19,word) ^ SHA512_ROTR(61,word) ^ SHA512_SHR( 6,word))
+
+/*
+ * add "length" to the length
+ */
+static uint64_t addTemp;
+#define SHA384_512AddLength(context, length) \
+ (addTemp = context->Length_Low, context->Corrupted = \
+ ((context->Length_Low += length) < addTemp) && \
+ (++context->Length_High == 0) ? 1 : 0)
+
+/* Local Function Prototypes */
+static void SHA384_512Finalize(SHA512Context *context,
+ uint8_t Pad_Byte);
+static void SHA384_512PadMessage(SHA512Context *context,
+ uint8_t Pad_Byte);
+static void SHA384_512ProcessMessageBlock(SHA512Context *context);
+static int SHA384_512Reset(SHA512Context *context, uint64_t H0[]);
+static int SHA384_512ResultN(SHA512Context *context,
+ uint8_t Message_Digest[], int HashSize);
+
+/* Initial Hash Values: FIPS-180-2 sections 5.3.3 and 5.3.4 */
+static uint64_t SHA384_H0[] = {
+ 0xCBBB9D5DC1059ED8ll, 0x629A292A367CD507ll, 0x9159015A3070DD17ll,
+ 0x152FECD8F70E5939ll, 0x67332667FFC00B31ll, 0x8EB44A8768581511ll,
+ 0xDB0C2E0D64F98FA7ll, 0x47B5481DBEFA4FA4ll
+
+
+
+Eastlake 3rd & Hansen Informational [Page 51]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+};
+static uint64_t SHA512_H0[] = {
+ 0x6A09E667F3BCC908ll, 0xBB67AE8584CAA73Bll, 0x3C6EF372FE94F82Bll,
+ 0xA54FF53A5F1D36F1ll, 0x510E527FADE682D1ll, 0x9B05688C2B3E6C1Fll,
+ 0x1F83D9ABFB41BD6Bll, 0x5BE0CD19137E2179ll
+};
+
+#endif /* USE_32BIT_ONLY */
+
+/*
+ * SHA384Reset
+ *
+ * Description:
+ * This function will initialize the SHA384Context in preparation
+ * for computing a new SHA384 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA384Reset(SHA384Context *context)
+{
+ return SHA384_512Reset(context, SHA384_H0);
+}
+
+/*
+ * SHA384Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_array: [in]
+ * An array of characters representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array
+ *
+ * Returns:
+ * sha Error Code.
+ *
+
+
+
+Eastlake 3rd & Hansen Informational [Page 52]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ */
+int SHA384Input(SHA384Context *context,
+ const uint8_t *message_array, unsigned int length)
+{
+ return SHA512Input(context, message_array, length);
+}
+
+/*
+ * SHA384FinalBits
+ *
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA384FinalBits(SHA384Context *context,
+ const uint8_t message_bits, unsigned int length)
+{
+ return SHA512FinalBits(context, message_bits, length);
+}
+
+/*
+ * SHA384Result
+ *
+ * Description:
+ * This function will return the 384-bit message
+ * digest into the Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 48th element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest: [out]
+ * Where the digest is returned.
+ *
+
+
+
+Eastlake 3rd & Hansen Informational [Page 53]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA384Result(SHA384Context *context,
+ uint8_t Message_Digest[SHA384HashSize])
+{
+ return SHA384_512ResultN(context, Message_Digest, SHA384HashSize);
+}
+
+/*
+ * SHA512Reset
+ *
+ * Description:
+ * This function will initialize the SHA512Context in preparation
+ * for computing a new SHA512 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA512Reset(SHA512Context *context)
+{
+ return SHA384_512Reset(context, SHA512_H0);
+}
+
+/*
+ * SHA512Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_array: [in]
+ * An array of characters representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array
+ *
+ * Returns:
+ * sha Error Code.
+
+
+
+Eastlake 3rd & Hansen Informational [Page 54]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ *
+ */
+int SHA512Input(SHA512Context *context,
+ const uint8_t *message_array,
+ unsigned int length)
+{
+ if (!length)
+ return shaSuccess;
+
+ if (!context || !message_array)
+ return shaNull;
+
+ if (context->Computed) {
+ context->Corrupted = shaStateError;
+ return shaStateError;
+ }
+
+ if (context->Corrupted)
+ return context->Corrupted;
+
+ while (length-- && !context->Corrupted) {
+ context->Message_Block[context->Message_Block_Index++] =
+ (*message_array & 0xFF);
+
+ if (!SHA384_512AddLength(context, 8) &&
+ (context->Message_Block_Index == SHA512_Message_Block_Size))
+ SHA384_512ProcessMessageBlock(context);
+
+ message_array++;
+ }
+
+ return shaSuccess;
+}
+
+/*
+ * SHA512FinalBits
+ *
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+
+
+
+Eastlake 3rd & Hansen Informational [Page 55]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA512FinalBits(SHA512Context *context,
+ const uint8_t message_bits, unsigned int length)
+{
+ uint8_t masks[8] = {
+ /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
+ /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
+ /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
+ /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
+ };
+ uint8_t markbit[8] = {
+ /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
+ /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
+ /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
+ /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
+ };
+
+ if (!length)
+ return shaSuccess;
+
+ if (!context)
+ return shaNull;
+
+ if ((context->Computed) || (length >= 8) || (length == 0)) {
+ context->Corrupted = shaStateError;
+ return shaStateError;
+ }
+
+ if (context->Corrupted)
+ return context->Corrupted;
+
+ SHA384_512AddLength(context, length);
+ SHA384_512Finalize(context, (uint8_t)
+ ((message_bits & masks[length]) | markbit[length]));
+
+ return shaSuccess;
+}
+
+/*
+ * SHA384_512Finalize
+ *
+ * Description:
+ * This helper function finishes off the digest calculations.
+
+
+
+Eastlake 3rd & Hansen Informational [Page 56]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * Pad_Byte: [in]
+ * The last byte to add to the digest before the 0-padding
+ * and length. This will contain the last bits of the message
+ * followed by another single bit. If the message was an
+ * exact multiple of 8-bits long, Pad_Byte will be 0x80.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+static void SHA384_512Finalize(SHA512Context *context,
+ uint8_t Pad_Byte)
+{
+ int_least16_t i;
+ SHA384_512PadMessage(context, Pad_Byte);
+ /* message may be sensitive, clear it out */
+ for (i = 0; i < SHA512_Message_Block_Size; ++i)
+ context->Message_Block[i] = 0;
+#ifdef USE_32BIT_ONLY /* and clear length */
+ context->Length[0] = context->Length[1] = 0;
+ context->Length[2] = context->Length[3] = 0;
+#else /* !USE_32BIT_ONLY */
+ context->Length_Low = 0;
+ context->Length_High = 0;
+#endif /* USE_32BIT_ONLY */
+ context->Computed = 1;
+}
+
+/*
+ * SHA512Result
+ *
+ * Description:
+ * This function will return the 512-bit message
+ * digest into the Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 64th element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+
+
+
+Eastlake 3rd & Hansen Informational [Page 57]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * sha Error Code.
+ *
+ */
+int SHA512Result(SHA512Context *context,
+ uint8_t Message_Digest[SHA512HashSize])
+{
+ return SHA384_512ResultN(context, Message_Digest, SHA512HashSize);
+}
+
+/*
+ * SHA384_512PadMessage
+ *
+ * Description:
+ * According to the standard, the message must be padded to an
+ * even 1024 bits. The first padding bit must be a '1'. The
+ * last 128 bits represent the length of the original message.
+ * All bits in between should be 0. This helper function will
+ * pad the message according to those rules by filling the
+ * Message_Block array accordingly. When it returns, it can be
+ * assumed that the message digest has been computed.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to pad
+ * Pad_Byte: [in]
+ * The last byte to add to the digest before the 0-padding
+ * and length. This will contain the last bits of the message
+ * followed by another single bit. If the message was an
+ * exact multiple of 8-bits long, Pad_Byte will be 0x80.
+ *
+ * Returns:
+ * Nothing.
+ *
+ */
+static void SHA384_512PadMessage(SHA512Context *context,
+ uint8_t Pad_Byte)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (context->Message_Block_Index >= (SHA512_Message_Block_Size-16)) {
+ context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+ while (context->Message_Block_Index < SHA512_Message_Block_Size)
+ context->Message_Block[context->Message_Block_Index++] = 0;
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 58]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ SHA384_512ProcessMessageBlock(context);
+ } else
+ context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+
+ while (context->Message_Block_Index < (SHA512_Message_Block_Size-16))
+ context->Message_Block[context->Message_Block_Index++] = 0;
+
+ /*
+ * Store the message length as the last 16 octets
+ */
+#ifdef USE_32BIT_ONLY
+ context->Message_Block[112] = (uint8_t)(context->Length[0] >> 24);
+ context->Message_Block[113] = (uint8_t)(context->Length[0] >> 16);
+ context->Message_Block[114] = (uint8_t)(context->Length[0] >> 8);
+ context->Message_Block[115] = (uint8_t)(context->Length[0]);
+ context->Message_Block[116] = (uint8_t)(context->Length[1] >> 24);
+ context->Message_Block[117] = (uint8_t)(context->Length[1] >> 16);
+ context->Message_Block[118] = (uint8_t)(context->Length[1] >> 8);
+ context->Message_Block[119] = (uint8_t)(context->Length[1]);
+
+ context->Message_Block[120] = (uint8_t)(context->Length[2] >> 24);
+ context->Message_Block[121] = (uint8_t)(context->Length[2] >> 16);
+ context->Message_Block[122] = (uint8_t)(context->Length[2] >> 8);
+ context->Message_Block[123] = (uint8_t)(context->Length[2]);
+ context->Message_Block[124] = (uint8_t)(context->Length[3] >> 24);
+ context->Message_Block[125] = (uint8_t)(context->Length[3] >> 16);
+ context->Message_Block[126] = (uint8_t)(context->Length[3] >> 8);
+ context->Message_Block[127] = (uint8_t)(context->Length[3]);
+#else /* !USE_32BIT_ONLY */
+ context->Message_Block[112] = (uint8_t)(context->Length_High >> 56);
+ context->Message_Block[113] = (uint8_t)(context->Length_High >> 48);
+ context->Message_Block[114] = (uint8_t)(context->Length_High >> 40);
+ context->Message_Block[115] = (uint8_t)(context->Length_High >> 32);
+ context->Message_Block[116] = (uint8_t)(context->Length_High >> 24);
+ context->Message_Block[117] = (uint8_t)(context->Length_High >> 16);
+ context->Message_Block[118] = (uint8_t)(context->Length_High >> 8);
+ context->Message_Block[119] = (uint8_t)(context->Length_High);
+
+ context->Message_Block[120] = (uint8_t)(context->Length_Low >> 56);
+ context->Message_Block[121] = (uint8_t)(context->Length_Low >> 48);
+ context->Message_Block[122] = (uint8_t)(context->Length_Low >> 40);
+ context->Message_Block[123] = (uint8_t)(context->Length_Low >> 32);
+ context->Message_Block[124] = (uint8_t)(context->Length_Low >> 24);
+ context->Message_Block[125] = (uint8_t)(context->Length_Low >> 16);
+ context->Message_Block[126] = (uint8_t)(context->Length_Low >> 8);
+ context->Message_Block[127] = (uint8_t)(context->Length_Low);
+#endif /* USE_32BIT_ONLY */
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 59]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ SHA384_512ProcessMessageBlock(context);
+}
+
+/*
+ * SHA384_512ProcessMessageBlock
+ *
+ * Description:
+ * This helper function will process the next 1024 bits of the
+ * message stored in the Message_Block array.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ * Many of the variable names in this code, especially the
+ * single character names, were used because those were the
+ * names used in the publication.
+ *
+ *
+ */
+static void SHA384_512ProcessMessageBlock(SHA512Context *context)
+{
+ /* Constants defined in FIPS-180-2, section 4.2.3 */
+#ifdef USE_32BIT_ONLY
+ static const uint32_t K[80*2] = {
+ 0x428A2F98, 0xD728AE22, 0x71374491, 0x23EF65CD, 0xB5C0FBCF,
+ 0xEC4D3B2F, 0xE9B5DBA5, 0x8189DBBC, 0x3956C25B, 0xF348B538,
+ 0x59F111F1, 0xB605D019, 0x923F82A4, 0xAF194F9B, 0xAB1C5ED5,
+ 0xDA6D8118, 0xD807AA98, 0xA3030242, 0x12835B01, 0x45706FBE,
+ 0x243185BE, 0x4EE4B28C, 0x550C7DC3, 0xD5FFB4E2, 0x72BE5D74,
+ 0xF27B896F, 0x80DEB1FE, 0x3B1696B1, 0x9BDC06A7, 0x25C71235,
+ 0xC19BF174, 0xCF692694, 0xE49B69C1, 0x9EF14AD2, 0xEFBE4786,
+ 0x384F25E3, 0x0FC19DC6, 0x8B8CD5B5, 0x240CA1CC, 0x77AC9C65,
+ 0x2DE92C6F, 0x592B0275, 0x4A7484AA, 0x6EA6E483, 0x5CB0A9DC,
+ 0xBD41FBD4, 0x76F988DA, 0x831153B5, 0x983E5152, 0xEE66DFAB,
+ 0xA831C66D, 0x2DB43210, 0xB00327C8, 0x98FB213F, 0xBF597FC7,
+ 0xBEEF0EE4, 0xC6E00BF3, 0x3DA88FC2, 0xD5A79147, 0x930AA725,
+ 0x06CA6351, 0xE003826F, 0x14292967, 0x0A0E6E70, 0x27B70A85,
+ 0x46D22FFC, 0x2E1B2138, 0x5C26C926, 0x4D2C6DFC, 0x5AC42AED,
+ 0x53380D13, 0x9D95B3DF, 0x650A7354, 0x8BAF63DE, 0x766A0ABB,
+ 0x3C77B2A8, 0x81C2C92E, 0x47EDAEE6, 0x92722C85, 0x1482353B,
+ 0xA2BFE8A1, 0x4CF10364, 0xA81A664B, 0xBC423001, 0xC24B8B70,
+ 0xD0F89791, 0xC76C51A3, 0x0654BE30, 0xD192E819, 0xD6EF5218,
+ 0xD6990624, 0x5565A910, 0xF40E3585, 0x5771202A, 0x106AA070,
+
+
+
+Eastlake 3rd & Hansen Informational [Page 60]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ 0x32BBD1B8, 0x19A4C116, 0xB8D2D0C8, 0x1E376C08, 0x5141AB53,
+ 0x2748774C, 0xDF8EEB99, 0x34B0BCB5, 0xE19B48A8, 0x391C0CB3,
+ 0xC5C95A63, 0x4ED8AA4A, 0xE3418ACB, 0x5B9CCA4F, 0x7763E373,
+ 0x682E6FF3, 0xD6B2B8A3, 0x748F82EE, 0x5DEFB2FC, 0x78A5636F,
+ 0x43172F60, 0x84C87814, 0xA1F0AB72, 0x8CC70208, 0x1A6439EC,
+ 0x90BEFFFA, 0x23631E28, 0xA4506CEB, 0xDE82BDE9, 0xBEF9A3F7,
+ 0xB2C67915, 0xC67178F2, 0xE372532B, 0xCA273ECE, 0xEA26619C,
+ 0xD186B8C7, 0x21C0C207, 0xEADA7DD6, 0xCDE0EB1E, 0xF57D4F7F,
+ 0xEE6ED178, 0x06F067AA, 0x72176FBA, 0x0A637DC5, 0xA2C898A6,
+ 0x113F9804, 0xBEF90DAE, 0x1B710B35, 0x131C471B, 0x28DB77F5,
+ 0x23047D84, 0x32CAAB7B, 0x40C72493, 0x3C9EBE0A, 0x15C9BEBC,
+ 0x431D67C4, 0x9C100D4C, 0x4CC5D4BE, 0xCB3E42B6, 0x597F299C,
+ 0xFC657E2A, 0x5FCB6FAB, 0x3AD6FAEC, 0x6C44198C, 0x4A475817
+ };
+ int t, t2, t8; /* Loop counter */
+ uint32_t temp1[2], temp2[2], /* Temporary word values */
+ temp3[2], temp4[2], temp5[2];
+ uint32_t W[2*80]; /* Word sequence */
+ uint32_t A[2], B[2], C[2], D[2], /* Word buffers */
+ E[2], F[2], G[2], H[2];
+
+ /* Initialize the first 16 words in the array W */
+ for (t = t2 = t8 = 0; t < 16; t++, t8 += 8) {
+ W[t2++] = ((((uint32_t)context->Message_Block[t8 ])) << 24) |
+ ((((uint32_t)context->Message_Block[t8 + 1])) << 16) |
+ ((((uint32_t)context->Message_Block[t8 + 2])) << 8) |
+ ((((uint32_t)context->Message_Block[t8 + 3])));
+ W[t2++] = ((((uint32_t)context->Message_Block[t8 + 4])) << 24) |
+ ((((uint32_t)context->Message_Block[t8 + 5])) << 16) |
+ ((((uint32_t)context->Message_Block[t8 + 6])) << 8) |
+ ((((uint32_t)context->Message_Block[t8 + 7])));
+ }
+
+ for (t = 16; t < 80; t++, t2 += 2) {
+ /* W[t] = SHA512_sigma1(W[t-2]) + W[t-7] +
+ SHA512_sigma0(W[t-15]) + W[t-16]; */
+ uint32_t *Wt2 = &W[t2-2*2];
+ uint32_t *Wt7 = &W[t2-7*2];
+ uint32_t *Wt15 = &W[t2-15*2];
+ uint32_t *Wt16 = &W[t2-16*2];
+ SHA512_sigma1(Wt2, temp1);
+ SHA512_ADD(temp1, Wt7, temp2);
+ SHA512_sigma0(Wt15, temp1);
+ SHA512_ADD(temp1, Wt16, temp3);
+ SHA512_ADD(temp2, temp3, &W[t2]);
+ }
+
+ A[0] = context->Intermediate_Hash[0];
+
+
+
+Eastlake 3rd & Hansen Informational [Page 61]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ A[1] = context->Intermediate_Hash[1];
+ B[0] = context->Intermediate_Hash[2];
+ B[1] = context->Intermediate_Hash[3];
+ C[0] = context->Intermediate_Hash[4];
+ C[1] = context->Intermediate_Hash[5];
+ D[0] = context->Intermediate_Hash[6];
+ D[1] = context->Intermediate_Hash[7];
+ E[0] = context->Intermediate_Hash[8];
+ E[1] = context->Intermediate_Hash[9];
+ F[0] = context->Intermediate_Hash[10];
+ F[1] = context->Intermediate_Hash[11];
+ G[0] = context->Intermediate_Hash[12];
+ G[1] = context->Intermediate_Hash[13];
+ H[0] = context->Intermediate_Hash[14];
+ H[1] = context->Intermediate_Hash[15];
+
+ for (t = t2 = 0; t < 80; t++, t2 += 2) {
+ /*
+ * temp1 = H + SHA512_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t];
+ */
+ SHA512_SIGMA1(E,temp1);
+ SHA512_ADD(H, temp1, temp2);
+ SHA_Ch(E,F,G,temp3);
+ SHA512_ADD(temp2, temp3, temp4);
+ SHA512_ADD(&K[t2], &W[t2], temp5);
+ SHA512_ADD(temp4, temp5, temp1);
+ /*
+ * temp2 = SHA512_SIGMA0(A) + SHA_Maj(A,B,C);
+ */
+ SHA512_SIGMA0(A,temp3);
+ SHA_Maj(A,B,C,temp4);
+ SHA512_ADD(temp3, temp4, temp2);
+ H[0] = G[0]; H[1] = G[1];
+ G[0] = F[0]; G[1] = F[1];
+ F[0] = E[0]; F[1] = E[1];
+ SHA512_ADD(D, temp1, E);
+ D[0] = C[0]; D[1] = C[1];
+ C[0] = B[0]; C[1] = B[1];
+ B[0] = A[0]; B[1] = A[1];
+ SHA512_ADD(temp1, temp2, A);
+ }
+
+ SHA512_ADDTO2(&context->Intermediate_Hash[0], A);
+ SHA512_ADDTO2(&context->Intermediate_Hash[2], B);
+ SHA512_ADDTO2(&context->Intermediate_Hash[4], C);
+ SHA512_ADDTO2(&context->Intermediate_Hash[6], D);
+ SHA512_ADDTO2(&context->Intermediate_Hash[8], E);
+ SHA512_ADDTO2(&context->Intermediate_Hash[10], F);
+
+
+
+Eastlake 3rd & Hansen Informational [Page 62]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ SHA512_ADDTO2(&context->Intermediate_Hash[12], G);
+ SHA512_ADDTO2(&context->Intermediate_Hash[14], H);
+
+#else /* !USE_32BIT_ONLY */
+ static const uint64_t K[80] = {
+ 0x428A2F98D728AE22ll, 0x7137449123EF65CDll, 0xB5C0FBCFEC4D3B2Fll,
+ 0xE9B5DBA58189DBBCll, 0x3956C25BF348B538ll, 0x59F111F1B605D019ll,
+ 0x923F82A4AF194F9Bll, 0xAB1C5ED5DA6D8118ll, 0xD807AA98A3030242ll,
+ 0x12835B0145706FBEll, 0x243185BE4EE4B28Cll, 0x550C7DC3D5FFB4E2ll,
+ 0x72BE5D74F27B896Fll, 0x80DEB1FE3B1696B1ll, 0x9BDC06A725C71235ll,
+ 0xC19BF174CF692694ll, 0xE49B69C19EF14AD2ll, 0xEFBE4786384F25E3ll,
+ 0x0FC19DC68B8CD5B5ll, 0x240CA1CC77AC9C65ll, 0x2DE92C6F592B0275ll,
+ 0x4A7484AA6EA6E483ll, 0x5CB0A9DCBD41FBD4ll, 0x76F988DA831153B5ll,
+ 0x983E5152EE66DFABll, 0xA831C66D2DB43210ll, 0xB00327C898FB213Fll,
+ 0xBF597FC7BEEF0EE4ll, 0xC6E00BF33DA88FC2ll, 0xD5A79147930AA725ll,
+ 0x06CA6351E003826Fll, 0x142929670A0E6E70ll, 0x27B70A8546D22FFCll,
+ 0x2E1B21385C26C926ll, 0x4D2C6DFC5AC42AEDll, 0x53380D139D95B3DFll,
+ 0x650A73548BAF63DEll, 0x766A0ABB3C77B2A8ll, 0x81C2C92E47EDAEE6ll,
+ 0x92722C851482353Bll, 0xA2BFE8A14CF10364ll, 0xA81A664BBC423001ll,
+ 0xC24B8B70D0F89791ll, 0xC76C51A30654BE30ll, 0xD192E819D6EF5218ll,
+ 0xD69906245565A910ll, 0xF40E35855771202All, 0x106AA07032BBD1B8ll,
+ 0x19A4C116B8D2D0C8ll, 0x1E376C085141AB53ll, 0x2748774CDF8EEB99ll,
+ 0x34B0BCB5E19B48A8ll, 0x391C0CB3C5C95A63ll, 0x4ED8AA4AE3418ACBll,
+ 0x5B9CCA4F7763E373ll, 0x682E6FF3D6B2B8A3ll, 0x748F82EE5DEFB2FCll,
+ 0x78A5636F43172F60ll, 0x84C87814A1F0AB72ll, 0x8CC702081A6439ECll,
+ 0x90BEFFFA23631E28ll, 0xA4506CEBDE82BDE9ll, 0xBEF9A3F7B2C67915ll,
+ 0xC67178F2E372532Bll, 0xCA273ECEEA26619Cll, 0xD186B8C721C0C207ll,
+ 0xEADA7DD6CDE0EB1Ell, 0xF57D4F7FEE6ED178ll, 0x06F067AA72176FBAll,
+ 0x0A637DC5A2C898A6ll, 0x113F9804BEF90DAEll, 0x1B710B35131C471Bll,
+ 0x28DB77F523047D84ll, 0x32CAAB7B40C72493ll, 0x3C9EBE0A15C9BEBCll,
+ 0x431D67C49C100D4Cll, 0x4CC5D4BECB3E42B6ll, 0x597F299CFC657E2All,
+ 0x5FCB6FAB3AD6FAECll, 0x6C44198C4A475817ll
+ };
+ int t, t8; /* Loop counter */
+ uint64_t temp1, temp2; /* Temporary word value */
+ uint64_t W[80]; /* Word sequence */
+ uint64_t A, B, C, D, E, F, G, H; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for (t = t8 = 0; t < 16; t++, t8 += 8)
+ W[t] = ((uint64_t)(context->Message_Block[t8 ]) << 56) |
+ ((uint64_t)(context->Message_Block[t8 + 1]) << 48) |
+ ((uint64_t)(context->Message_Block[t8 + 2]) << 40) |
+ ((uint64_t)(context->Message_Block[t8 + 3]) << 32) |
+ ((uint64_t)(context->Message_Block[t8 + 4]) << 24) |
+ ((uint64_t)(context->Message_Block[t8 + 5]) << 16) |
+
+
+
+Eastlake 3rd & Hansen Informational [Page 63]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ ((uint64_t)(context->Message_Block[t8 + 6]) << 8) |
+ ((uint64_t)(context->Message_Block[t8 + 7]));
+
+ for (t = 16; t < 80; t++)
+ W[t] = SHA512_sigma1(W[t-2]) + W[t-7] +
+ SHA512_sigma0(W[t-15]) + W[t-16];
+
+ A = context->Intermediate_Hash[0];
+ B = context->Intermediate_Hash[1];
+ C = context->Intermediate_Hash[2];
+ D = context->Intermediate_Hash[3];
+ E = context->Intermediate_Hash[4];
+ F = context->Intermediate_Hash[5];
+ G = context->Intermediate_Hash[6];
+ H = context->Intermediate_Hash[7];
+
+ for (t = 0; t < 80; t++) {
+ temp1 = H + SHA512_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t];
+ temp2 = SHA512_SIGMA0(A) + SHA_Maj(A,B,C);
+ H = G;
+ G = F;
+ F = E;
+ E = D + temp1;
+ D = C;
+ C = B;
+ B = A;
+ A = temp1 + temp2;
+ }
+
+ context->Intermediate_Hash[0] += A;
+ context->Intermediate_Hash[1] += B;
+ context->Intermediate_Hash[2] += C;
+ context->Intermediate_Hash[3] += D;
+ context->Intermediate_Hash[4] += E;
+ context->Intermediate_Hash[5] += F;
+ context->Intermediate_Hash[6] += G;
+ context->Intermediate_Hash[7] += H;
+#endif /* USE_32BIT_ONLY */
+
+ context->Message_Block_Index = 0;
+}
+
+/*
+ * SHA384_512Reset
+ *
+ * Description:
+ * This helper function will initialize the SHA512Context in
+ * preparation for computing a new SHA384 or SHA512 message
+
+
+
+Eastlake 3rd & Hansen Informational [Page 64]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ * H0
+ * The initial hash value to use.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+#ifdef USE_32BIT_ONLY
+static int SHA384_512Reset(SHA512Context *context, uint32_t H0[])
+#else /* !USE_32BIT_ONLY */
+static int SHA384_512Reset(SHA512Context *context, uint64_t H0[])
+#endif /* USE_32BIT_ONLY */
+{
+ int i;
+ if (!context)
+ return shaNull;
+
+ context->Message_Block_Index = 0;
+
+#ifdef USE_32BIT_ONLY
+ context->Length[0] = context->Length[1] = 0;
+ context->Length[2] = context->Length[3] = 0;
+
+ for (i = 0; i < SHA512HashSize/4; i++)
+ context->Intermediate_Hash[i] = H0[i];
+#else /* !USE_32BIT_ONLY */
+ context->Length_High = context->Length_Low = 0;
+
+ for (i = 0; i < SHA512HashSize/8; i++)
+ context->Intermediate_Hash[i] = H0[i];
+#endif /* USE_32BIT_ONLY */
+
+ context->Computed = 0;
+ context->Corrupted = 0;
+
+ return shaSuccess;
+}
+
+/*
+ * SHA384_512ResultN
+ *
+ * Description:
+ * This helper function will return the 384-bit or 512-bit message
+
+
+
+Eastlake 3rd & Hansen Informational [Page 65]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * digest into the Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 48th/64th element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest: [out]
+ * Where the digest is returned.
+ * HashSize: [in]
+ * The size of the hash, either 48 or 64.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+static int SHA384_512ResultN(SHA512Context *context,
+ uint8_t Message_Digest[], int HashSize)
+{
+ int i;
+
+#ifdef USE_32BIT_ONLY
+ int i2;
+#endif /* USE_32BIT_ONLY */
+
+ if (!context || !Message_Digest)
+ return shaNull;
+
+ if (context->Corrupted)
+ return context->Corrupted;
+
+ if (!context->Computed)
+ SHA384_512Finalize(context, 0x80);
+
+#ifdef USE_32BIT_ONLY
+ for (i = i2 = 0; i < HashSize; ) {
+ Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>24);
+ Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>16);
+ Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>8);
+ Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2++]);
+ Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>24);
+ Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>16);
+ Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2]>>8);
+ Message_Digest[i++]=(uint8_t)(context->Intermediate_Hash[i2++]);
+ }
+#else /* !USE_32BIT_ONLY */
+ for (i = 0; i < HashSize; ++i)
+ Message_Digest[i] = (uint8_t)
+
+
+
+Eastlake 3rd & Hansen Informational [Page 66]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ (context->Intermediate_Hash[i>>3] >> 8 * ( 7 - ( i % 8 ) ));
+#endif /* USE_32BIT_ONLY */
+
+ return shaSuccess;
+}
+
+8.2.4. usha.c
+
+/**************************** usha.c ****************************/
+/******************** See RFC 4634 for details ******************/
+/*
+ * Description:
+ * This file implements a unified interface to the SHA algorithms.
+ */
+
+#include "sha.h"
+
+/*
+ * USHAReset
+ *
+ * Description:
+ * This function will initialize the SHA Context in preparation
+ * for computing a new SHA message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ * whichSha: [in]
+ * Selects which SHA reset to call
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int USHAReset(USHAContext *ctx, enum SHAversion whichSha)
+{
+ if (ctx) {
+ ctx->whichSha = whichSha;
+ switch (whichSha) {
+ case SHA1: return SHA1Reset((SHA1Context*)&ctx->ctx);
+ case SHA224: return SHA224Reset((SHA224Context*)&ctx->ctx);
+ case SHA256: return SHA256Reset((SHA256Context*)&ctx->ctx);
+ case SHA384: return SHA384Reset((SHA384Context*)&ctx->ctx);
+ case SHA512: return SHA512Reset((SHA512Context*)&ctx->ctx);
+ default: return shaBadParam;
+ }
+ } else {
+ return shaNull;
+
+
+
+Eastlake 3rd & Hansen Informational [Page 67]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ }
+}
+
+/*
+ * USHAInput
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_array: [in]
+ * An array of characters representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int USHAInput(USHAContext *ctx,
+ const uint8_t *bytes, unsigned int bytecount)
+{
+ if (ctx) {
+ switch (ctx->whichSha) {
+ case SHA1:
+ return SHA1Input((SHA1Context*)&ctx->ctx, bytes, bytecount);
+ case SHA224:
+ return SHA224Input((SHA224Context*)&ctx->ctx, bytes,
+ bytecount);
+ case SHA256:
+ return SHA256Input((SHA256Context*)&ctx->ctx, bytes,
+ bytecount);
+ case SHA384:
+ return SHA384Input((SHA384Context*)&ctx->ctx, bytes,
+ bytecount);
+ case SHA512:
+ return SHA512Input((SHA512Context*)&ctx->ctx, bytes,
+ bytecount);
+ default: return shaBadParam;
+ }
+ } else {
+ return shaNull;
+ }
+}
+
+
+
+Eastlake 3rd & Hansen Informational [Page 68]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+/*
+ * USHAFinalBits
+ *
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int USHAFinalBits(USHAContext *ctx,
+ const uint8_t bits, unsigned int bitcount)
+{
+ if (ctx) {
+ switch (ctx->whichSha) {
+ case SHA1:
+ return SHA1FinalBits((SHA1Context*)&ctx->ctx, bits, bitcount);
+ case SHA224:
+ return SHA224FinalBits((SHA224Context*)&ctx->ctx, bits,
+ bitcount);
+ case SHA256:
+ return SHA256FinalBits((SHA256Context*)&ctx->ctx, bits,
+ bitcount);
+ case SHA384:
+ return SHA384FinalBits((SHA384Context*)&ctx->ctx, bits,
+ bitcount);
+ case SHA512:
+ return SHA512FinalBits((SHA512Context*)&ctx->ctx, bits,
+ bitcount);
+ default: return shaBadParam;
+ }
+ } else {
+ return shaNull;
+ }
+}
+
+/*
+ * USHAResult
+ *
+
+
+
+Eastlake 3rd & Hansen Informational [Page 69]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * Description:
+ * This function will return the 160-bit message digest into the
+ * Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 19th element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA-1 hash.
+ * Message_Digest: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int USHAResult(USHAContext *ctx,
+ uint8_t Message_Digest[USHAMaxHashSize])
+{
+ if (ctx) {
+ switch (ctx->whichSha) {
+ case SHA1:
+ return SHA1Result((SHA1Context*)&ctx->ctx, Message_Digest);
+ case SHA224:
+ return SHA224Result((SHA224Context*)&ctx->ctx, Message_Digest);
+ case SHA256:
+ return SHA256Result((SHA256Context*)&ctx->ctx, Message_Digest);
+ case SHA384:
+ return SHA384Result((SHA384Context*)&ctx->ctx, Message_Digest);
+ case SHA512:
+ return SHA512Result((SHA512Context*)&ctx->ctx, Message_Digest);
+ default: return shaBadParam;
+ }
+ } else {
+ return shaNull;
+ }
+}
+
+/*
+ * USHABlockSize
+ *
+ * Description:
+ * This function will return the blocksize for the given SHA
+ * algorithm.
+ *
+ * Parameters:
+ * whichSha:
+ * which SHA algorithm to query
+
+
+
+Eastlake 3rd & Hansen Informational [Page 70]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ *
+ * Returns:
+ * block size
+ *
+ */
+int USHABlockSize(enum SHAversion whichSha)
+{
+ switch (whichSha) {
+ case SHA1: return SHA1_Message_Block_Size;
+ case SHA224: return SHA224_Message_Block_Size;
+ case SHA256: return SHA256_Message_Block_Size;
+ case SHA384: return SHA384_Message_Block_Size;
+ default:
+ case SHA512: return SHA512_Message_Block_Size;
+ }
+}
+
+/*
+ * USHAHashSize
+ *
+ * Description:
+ * This function will return the hashsize for the given SHA
+ * algorithm.
+ *
+ * Parameters:
+ * whichSha:
+ * which SHA algorithm to query
+ *
+ * Returns:
+ * hash size
+ *
+ */
+int USHAHashSize(enum SHAversion whichSha)
+{
+ switch (whichSha) {
+ case SHA1: return SHA1HashSize;
+ case SHA224: return SHA224HashSize;
+ case SHA256: return SHA256HashSize;
+ case SHA384: return SHA384HashSize;
+ default:
+ case SHA512: return SHA512HashSize;
+ }
+}
+
+/*
+ * USHAHashSizeBits
+ *
+ * Description:
+
+
+
+Eastlake 3rd & Hansen Informational [Page 71]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * This function will return the hashsize for the given SHA
+ * algorithm, expressed in bits.
+ *
+ * Parameters:
+ * whichSha:
+ * which SHA algorithm to query
+ *
+ * Returns:
+ * hash size in bits
+ *
+ */
+int USHAHashSizeBits(enum SHAversion whichSha)
+{
+ switch (whichSha) {
+ case SHA1: return SHA1HashSizeBits;
+ case SHA224: return SHA224HashSizeBits;
+ case SHA256: return SHA256HashSizeBits;
+ case SHA384: return SHA384HashSizeBits;
+ default:
+ case SHA512: return SHA512HashSizeBits;
+ }
+}
+
+8.2.5. sha-private.h
+
+/*************************** sha-private.h ***************************/
+/********************** See RFC 4634 for details *********************/
+#ifndef _SHA_PRIVATE__H
+#define _SHA_PRIVATE__H
+/*
+ * These definitions are defined in FIPS-180-2, section 4.1.
+ * Ch() and Maj() are defined identically in sections 4.1.1,
+ * 4.1.2 and 4.1.3.
+ *
+ * The definitions used in FIPS-180-2 are as follows:
+ */
+
+#ifndef USE_MODIFIED_MACROS
+#define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+#else /* USE_MODIFIED_MACROS */
+/*
+ * The following definitions are equivalent and potentially faster.
+ */
+
+#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
+#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
+
+
+
+Eastlake 3rd & Hansen Informational [Page 72]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+#endif /* USE_MODIFIED_MACROS */
+
+#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
+
+#endif /* _SHA_PRIVATE__H */
+
+8.3 The HMAC Code
+
+/**************************** hmac.c ****************************/
+/******************** See RFC 4634 for details ******************/
+/*
+ * Description:
+ * This file implements the HMAC algorithm (Keyed-Hashing for
+ * Message Authentication, RFC2104), expressed in terms of the
+ * various SHA algorithms.
+ */
+
+#include "sha.h"
+
+/*
+ * hmac
+ *
+ * Description:
+ * This function will compute an HMAC message digest.
+ *
+ * Parameters:
+ * whichSha: [in]
+ * One of SHA1, SHA224, SHA256, SHA384, SHA512
+ * key: [in]
+ * The secret shared key.
+ * key_len: [in]
+ * The length of the secret shared key.
+ * message_array: [in]
+ * An array of characters representing the message.
+ * length: [in]
+ * The length of the message in message_array
+ * digest: [out]
+ * Where the digest is returned.
+ * NOTE: The length of the digest is determined by
+ * the value of whichSha.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int hmac(SHAversion whichSha, const unsigned char *text, int text_len,
+ const unsigned char *key, int key_len,
+ uint8_t digest[USHAMaxHashSize])
+
+
+
+Eastlake 3rd & Hansen Informational [Page 73]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+{
+ HMACContext ctx;
+ return hmacReset(&ctx, whichSha, key, key_len) ||
+ hmacInput(&ctx, text, text_len) ||
+ hmacResult(&ctx, digest);
+}
+
+/*
+ * hmacReset
+ *
+ * Description:
+ * This function will initialize the hmacContext in preparation
+ * for computing a new HMAC message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ * whichSha: [in]
+ * One of SHA1, SHA224, SHA256, SHA384, SHA512
+ * key: [in]
+ * The secret shared key.
+ * key_len: [in]
+ * The length of the secret shared key.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int hmacReset(HMACContext *ctx, enum SHAversion whichSha,
+ const unsigned char *key, int key_len)
+{
+ int i, blocksize, hashsize;
+
+ /* inner padding - key XORd with ipad */
+ unsigned char k_ipad[USHA_Max_Message_Block_Size];
+
+ /* temporary buffer when keylen > blocksize */
+ unsigned char tempkey[USHAMaxHashSize];
+
+ if (!ctx) return shaNull;
+
+ blocksize = ctx->blockSize = USHABlockSize(whichSha);
+ hashsize = ctx->hashSize = USHAHashSize(whichSha);
+
+ ctx->whichSha = whichSha;
+
+ /*
+ * If key is longer than the hash blocksize,
+
+
+
+Eastlake 3rd & Hansen Informational [Page 74]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * reset it to key = HASH(key).
+ */
+ if (key_len > blocksize) {
+ USHAContext tctx;
+ int err = USHAReset(&tctx, whichSha) ||
+ USHAInput(&tctx, key, key_len) ||
+ USHAResult(&tctx, tempkey);
+ if (err != shaSuccess) return err;
+
+ key = tempkey;
+ key_len = hashsize;
+ }
+
+ /*
+ * The HMAC transform looks like:
+ *
+ * SHA(K XOR opad, SHA(K XOR ipad, text))
+ *
+ * where K is an n byte key.
+ * ipad is the byte 0x36 repeated blocksize times
+ * opad is the byte 0x5c repeated blocksize times
+ * and text is the data being protected.
+ */
+
+ /* store key into the pads, XOR'd with ipad and opad values */
+ for (i = 0; i < key_len; i++) {
+ k_ipad[i] = key[i] ^ 0x36;
+ ctx->k_opad[i] = key[i] ^ 0x5c;
+ }
+ /* remaining pad bytes are '\0' XOR'd with ipad and opad values */
+ for ( ; i < blocksize; i++) {
+ k_ipad[i] = 0x36;
+ ctx->k_opad[i] = 0x5c;
+ }
+
+ /* perform inner hash */
+ /* init context for 1st pass */
+ return USHAReset(&ctx->shaContext, whichSha) ||
+ /* and start with inner pad */
+ USHAInput(&ctx->shaContext, k_ipad, blocksize);
+}
+
+/*
+ * hmacInput
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+
+
+
+Eastlake 3rd & Hansen Informational [Page 75]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ *
+ * Parameters:
+ * context: [in/out]
+ * The HMAC context to update
+ * message_array: [in]
+ * An array of characters representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int hmacInput(HMACContext *ctx, const unsigned char *text,
+ int text_len)
+{
+ if (!ctx) return shaNull;
+ /* then text of datagram */
+ return USHAInput(&ctx->shaContext, text, text_len);
+}
+
+/*
+ * HMACFinalBits
+ *
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The HMAC context to update
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int hmacFinalBits(HMACContext *ctx,
+ const uint8_t bits,
+ unsigned int bitcount)
+{
+ if (!ctx) return shaNull;
+ /* then final bits of datagram */
+ return USHAFinalBits(&ctx->shaContext, bits, bitcount);
+
+
+
+Eastlake 3rd & Hansen Informational [Page 76]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+}
+
+/*
+ * HMACResult
+ *
+ * Description:
+ * This function will return the N-byte message digest into the
+ * Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the Nth element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the HMAC hash.
+ * digest: [out]
+ * Where the digest is returned.
+ * NOTE 2: The length of the hash is determined by the value of
+ * whichSha that was passed to hmacReset().
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int hmacResult(HMACContext *ctx, uint8_t *digest)
+{
+ if (!ctx) return shaNull;
+
+ /* finish up 1st pass */
+ /* (Use digest here as a temporary buffer.) */
+ return USHAResult(&ctx->shaContext, digest) ||
+
+ /* perform outer SHA */
+ /* init context for 2nd pass */
+ USHAReset(&ctx->shaContext, ctx->whichSha) ||
+
+ /* start with outer pad */
+ USHAInput(&ctx->shaContext, ctx->k_opad, ctx->blockSize) ||
+
+ /* then results of 1st hash */
+ USHAInput(&ctx->shaContext, digest, ctx->hashSize) ||
+
+ /* finish up 2nd pass */
+ USHAResult(&ctx->shaContext, digest);
+}
+
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 77]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+8.4. The Test Driver
+
+ The following code is a main program test driver to exercise the code
+ in sha1.c, sha224-256.c, and sha384-512.c. The test driver can also
+ be used as a stand-alone program for generating the hashes.
+
+ See also [RFC2202], [RFC4231], and [SHAVS].
+
+/**************************** shatest.c ****************************/
+/********************* See RFC 4634 for details ********************/
+/*
+ * Description:
+ * This file will exercise the SHA code performing
+ * the three tests documented in FIPS PUB 180-2
+ * (http://csrc.nist.gov/publications/fips/
+ * fips180-2/fips180-2withchangenotice.pdf)
+ * one that calls SHAInput with an exact multiple of 512 bits
+ * the seven tests documented for each algorithm in
+ * "The Secure Hash Algorithm Validation System (SHAVS)",
+ * three of which are bit-level tests
+ * (http://csrc.nist.gov/cryptval/shs/SHAVS.pdf)
+ *
+ * This file will exercise the HMAC SHA1 code performing
+ * the seven tests documented in RFCs 2202 and 4231.
+ *
+ * To run the tests and just see PASSED/FAILED, use the -p option.
+ *
+ * Other options exercise:
+ * hashing an arbitrary string
+ * hashing a file's contents
+ * a few error test checks
+ * printing the results in raw format
+ *
+ * Portability Issues:
+ * None.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "sha.h"
+
+static int xgetopt(int argc, char **argv, const char *optstring);
+extern char *xoptarg;
+static int scasecmp(const char *s1, const char *s2);
+
+
+
+Eastlake 3rd & Hansen Informational [Page 78]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+/*
+ * Define patterns for testing
+ */
+#define TEST1 "abc"
+#define TEST2_1 \
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+#define TEST2_2a \
+ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+#define TEST2_2b \
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+#define TEST2_2 TEST2_2a TEST2_2b
+#define TEST3 "a" /* times 1000000 */
+#define TEST4a "01234567012345670123456701234567"
+#define TEST4b "01234567012345670123456701234567"
+ /* an exact multiple of 512 bits */
+#define TEST4 TEST4a TEST4b /* times 10 */
+
+#define TEST7_1 \
+ "\x49\xb2\xae\xc2\x59\x4b\xbe\x3a\x3b\x11\x75\x42\xd9\x4a\xc8"
+#define TEST8_1 \
+ "\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46\xaa\x55\xfe\x75\x71\x46"
+#define TEST9_1 \
+ "\x65\xf9\x32\x99\x5b\xa4\xce\x2c\xb1\xb4\xa2\xe7\x1a\xe7\x02\x20" \
+ "\xaa\xce\xc8\x96\x2d\xd4\x49\x9c\xbd\x7c\x88\x7a\x94\xea\xaa\x10" \
+ "\x1e\xa5\xaa\xbc\x52\x9b\x4e\x7e\x43\x66\x5a\x5a\xf2\xcd\x03\xfe" \
+ "\x67\x8e\xa6\xa5\x00\x5b\xba\x3b\x08\x22\x04\xc2\x8b\x91\x09\xf4" \
+ "\x69\xda\xc9\x2a\xaa\xb3\xaa\x7c\x11\xa1\xb3\x2a"
+#define TEST10_1 \
+ "\xf7\x8f\x92\x14\x1b\xcd\x17\x0a\xe8\x9b\x4f\xba\x15\xa1\xd5\x9f" \
+ "\x3f\xd8\x4d\x22\x3c\x92\x51\xbd\xac\xbb\xae\x61\xd0\x5e\xd1\x15" \
+ "\xa0\x6a\x7c\xe1\x17\xb7\xbe\xea\xd2\x44\x21\xde\xd9\xc3\x25\x92" \
+ "\xbd\x57\xed\xea\xe3\x9c\x39\xfa\x1f\xe8\x94\x6a\x84\xd0\xcf\x1f" \
+ "\x7b\xee\xad\x17\x13\xe2\xe0\x95\x98\x97\x34\x7f\x67\xc8\x0b\x04" \
+ "\x00\xc2\x09\x81\x5d\x6b\x10\xa6\x83\x83\x6f\xd5\x56\x2a\x56\xca" \
+ "\xb1\xa2\x8e\x81\xb6\x57\x66\x54\x63\x1c\xf1\x65\x66\xb8\x6e\x3b" \
+ "\x33\xa1\x08\xb0\x53\x07\xc0\x0a\xff\x14\xa7\x68\xed\x73\x50\x60" \
+ "\x6a\x0f\x85\xe6\xa9\x1d\x39\x6f\x5b\x5c\xbe\x57\x7f\x9b\x38\x80" \
+ "\x7c\x7d\x52\x3d\x6d\x79\x2f\x6e\xbc\x24\xa4\xec\xf2\xb3\xa4\x27" \
+ "\xcd\xbb\xfb"
+#define TEST7_224 \
+ "\xf0\x70\x06\xf2\x5a\x0b\xea\x68\xcd\x76\xa2\x95\x87\xc2\x8d"
+#define TEST8_224 \
+ "\x18\x80\x40\x05\xdd\x4f\xbd\x15\x56\x29\x9d\x6f\x9d\x93\xdf\x62"
+#define TEST9_224 \
+ "\xa2\xbe\x6e\x46\x32\x81\x09\x02\x94\xd9\xce\x94\x82\x65\x69\x42" \
+ "\x3a\x3a\x30\x5e\xd5\xe2\x11\x6c\xd4\xa4\xc9\x87\xfc\x06\x57\x00" \
+ "\x64\x91\xb1\x49\xcc\xd4\xb5\x11\x30\xac\x62\xb1\x9d\xc2\x48\xc7" \
+ "\x44\x54\x3d\x20\xcd\x39\x52\xdc\xed\x1f\x06\xcc\x3b\x18\xb9\x1f" \
+
+
+
+Eastlake 3rd & Hansen Informational [Page 79]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ "\x3f\x55\x63\x3e\xcc\x30\x85\xf4\x90\x70\x60\xd2"
+#define TEST10_224 \
+ "\x55\xb2\x10\x07\x9c\x61\xb5\x3a\xdd\x52\x06\x22\xd1\xac\x97\xd5" \
+ "\xcd\xbe\x8c\xb3\x3a\xa0\xae\x34\x45\x17\xbe\xe4\xd7\xba\x09\xab" \
+ "\xc8\x53\x3c\x52\x50\x88\x7a\x43\xbe\xbb\xac\x90\x6c\x2e\x18\x37" \
+ "\xf2\x6b\x36\xa5\x9a\xe3\xbe\x78\x14\xd5\x06\x89\x6b\x71\x8b\x2a" \
+ "\x38\x3e\xcd\xac\x16\xb9\x61\x25\x55\x3f\x41\x6f\xf3\x2c\x66\x74" \
+ "\xc7\x45\x99\xa9\x00\x53\x86\xd9\xce\x11\x12\x24\x5f\x48\xee\x47" \
+ "\x0d\x39\x6c\x1e\xd6\x3b\x92\x67\x0c\xa5\x6e\xc8\x4d\xee\xa8\x14" \
+ "\xb6\x13\x5e\xca\x54\x39\x2b\xde\xdb\x94\x89\xbc\x9b\x87\x5a\x8b" \
+ "\xaf\x0d\xc1\xae\x78\x57\x36\x91\x4a\xb7\xda\xa2\x64\xbc\x07\x9d" \
+ "\x26\x9f\x2c\x0d\x7e\xdd\xd8\x10\xa4\x26\x14\x5a\x07\x76\xf6\x7c" \
+ "\x87\x82\x73"
+#define TEST7_256 \
+ "\xbe\x27\x46\xc6\xdb\x52\x76\x5f\xdb\x2f\x88\x70\x0f\x9a\x73"
+#define TEST8_256 \
+ "\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3\x88\x7a\xb2\xcd\x68\x46\x52"
+#define TEST9_256 \
+ "\x3e\x74\x03\x71\xc8\x10\xc2\xb9\x9f\xc0\x4e\x80\x49\x07\xef\x7c" \
+ "\xf2\x6b\xe2\x8b\x57\xcb\x58\xa3\xe2\xf3\xc0\x07\x16\x6e\x49\xc1" \
+ "\x2e\x9b\xa3\x4c\x01\x04\x06\x91\x29\xea\x76\x15\x64\x25\x45\x70" \
+ "\x3a\x2b\xd9\x01\xe1\x6e\xb0\xe0\x5d\xeb\xa0\x14\xeb\xff\x64\x06" \
+ "\xa0\x7d\x54\x36\x4e\xff\x74\x2d\xa7\x79\xb0\xb3"
+#define TEST10_256 \
+ "\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1\x2b\x20\x52\x7a\xfe\xf0" \
+ "\x4d\x8a\x05\x69\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76\x00\x00" \
+ "\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08\x3a\xa3\x9d\x81\x0d\xb3\x10\x77" \
+ "\x7d\xab\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32\x5f\x8b\x23\x74" \
+ "\xde\x7a\x4b\x5a\x58\xcb\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" \
+ "\xd6\x94\xfa\x59\x3a\x8b\xeb\x3f\x9d\x65\x92\xec\xed\xaa\x66\xca" \
+ "\x82\xa2\x9d\x0c\x51\xbc\xf9\x33\x62\x30\xe5\xd7\x84\xe4\xc0\xa4" \
+ "\x3f\x8d\x79\xa3\x0a\x16\x5c\xba\xbe\x45\x2b\x77\x4b\x9c\x71\x09" \
+ "\xa9\x7d\x13\x8f\x12\x92\x28\x96\x6f\x6c\x0a\xdc\x10\x6a\xad\x5a" \
+ "\x9f\xdd\x30\x82\x57\x69\xb2\xc6\x71\xaf\x67\x59\xdf\x28\xeb\x39" \
+ "\x3d\x54\xd6"
+#define TEST7_384 \
+ "\x8b\xc5\x00\xc7\x7c\xee\xd9\x87\x9d\xa9\x89\x10\x7c\xe0\xaa"
+#define TEST8_384 \
+ "\xa4\x1c\x49\x77\x79\xc0\x37\x5f\xf1\x0a\x7f\x4e\x08\x59\x17\x39"
+#define TEST9_384 \
+ "\x68\xf5\x01\x79\x2d\xea\x97\x96\x76\x70\x22\xd9\x3d\xa7\x16\x79" \
+ "\x30\x99\x20\xfa\x10\x12\xae\xa3\x57\xb2\xb1\x33\x1d\x40\xa1\xd0" \
+ "\x3c\x41\xc2\x40\xb3\xc9\xa7\x5b\x48\x92\xf4\xc0\x72\x4b\x68\xc8" \
+ "\x75\x32\x1a\xb8\xcf\xe5\x02\x3b\xd3\x75\xbc\x0f\x94\xbd\x89\xfe" \
+ "\x04\xf2\x97\x10\x5d\x7b\x82\xff\xc0\x02\x1a\xeb\x1c\xcb\x67\x4f" \
+ "\x52\x44\xea\x34\x97\xde\x26\xa4\x19\x1c\x5f\x62\xe5\xe9\xa2\xd8" \
+ "\x08\x2f\x05\x51\xf4\xa5\x30\x68\x26\xe9\x1c\xc0\x06\xce\x1b\xf6" \
+ "\x0f\xf7\x19\xd4\x2f\xa5\x21\xc8\x71\xcd\x23\x94\xd9\x6e\xf4\x46" \
+
+
+
+Eastlake 3rd & Hansen Informational [Page 80]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ "\x8f\x21\x96\x6b\x41\xf2\xba\x80\xc2\x6e\x83\xa9"
+#define TEST10_384 \
+ "\x39\x96\x69\xe2\x8f\x6b\x9c\x6d\xbc\xbb\x69\x12\xec\x10\xff\xcf" \
+ "\x74\x79\x03\x49\xb7\xdc\x8f\xbe\x4a\x8e\x7b\x3b\x56\x21\xdb\x0f" \
+ "\x3e\x7d\xc8\x7f\x82\x32\x64\xbb\xe4\x0d\x18\x11\xc9\xea\x20\x61" \
+ "\xe1\xc8\x4a\xd1\x0a\x23\xfa\xc1\x72\x7e\x72\x02\xfc\x3f\x50\x42" \
+ "\xe6\xbf\x58\xcb\xa8\xa2\x74\x6e\x1f\x64\xf9\xb9\xea\x35\x2c\x71" \
+ "\x15\x07\x05\x3c\xf4\xe5\x33\x9d\x52\x86\x5f\x25\xcc\x22\xb5\xe8" \
+ "\x77\x84\xa1\x2f\xc9\x61\xd6\x6c\xb6\xe8\x95\x73\x19\x9a\x2c\xe6" \
+ "\x56\x5c\xbd\xf1\x3d\xca\x40\x38\x32\xcf\xcb\x0e\x8b\x72\x11\xe8" \
+ "\x3a\xf3\x2a\x11\xac\x17\x92\x9f\xf1\xc0\x73\xa5\x1c\xc0\x27\xaa" \
+ "\xed\xef\xf8\x5a\xad\x7c\x2b\x7c\x5a\x80\x3e\x24\x04\xd9\x6d\x2a" \
+ "\x77\x35\x7b\xda\x1a\x6d\xae\xed\x17\x15\x1c\xb9\xbc\x51\x25\xa4" \
+ "\x22\xe9\x41\xde\x0c\xa0\xfc\x50\x11\xc2\x3e\xcf\xfe\xfd\xd0\x96" \
+ "\x76\x71\x1c\xf3\xdb\x0a\x34\x40\x72\x0e\x16\x15\xc1\xf2\x2f\xbc" \
+ "\x3c\x72\x1d\xe5\x21\xe1\xb9\x9b\xa1\xbd\x55\x77\x40\x86\x42\x14" \
+ "\x7e\xd0\x96"
+#define TEST7_512 \
+ "\x08\xec\xb5\x2e\xba\xe1\xf7\x42\x2d\xb6\x2b\xcd\x54\x26\x70"
+#define TEST8_512 \
+ "\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81\x6e\x9d\x98\xbf\xf0\xa0"
+#define TEST9_512 \
+ "\x3a\xdd\xec\x85\x59\x32\x16\xd1\x61\x9a\xa0\x2d\x97\x56\x97\x0b" \
+ "\xfc\x70\xac\xe2\x74\x4f\x7c\x6b\x27\x88\x15\x10\x28\xf7\xb6\xa2" \
+ "\x55\x0f\xd7\x4a\x7e\x6e\x69\xc2\xc9\xb4\x5f\xc4\x54\x96\x6d\xc3" \
+ "\x1d\x2e\x10\xda\x1f\x95\xce\x02\xbe\xb4\xbf\x87\x65\x57\x4c\xbd" \
+ "\x6e\x83\x37\xef\x42\x0a\xdc\x98\xc1\x5c\xb6\xd5\xe4\xa0\x24\x1b" \
+ "\xa0\x04\x6d\x25\x0e\x51\x02\x31\xca\xc2\x04\x6c\x99\x16\x06\xab" \
+ "\x4e\xe4\x14\x5b\xee\x2f\xf4\xbb\x12\x3a\xab\x49\x8d\x9d\x44\x79" \
+ "\x4f\x99\xcc\xad\x89\xa9\xa1\x62\x12\x59\xed\xa7\x0a\x5b\x6d\xd4" \
+ "\xbd\xd8\x77\x78\xc9\x04\x3b\x93\x84\xf5\x49\x06"
+#define TEST10_512 \
+ "\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a\x50\x2d\x65\x82\x4e\x31" \
+ "\xa2\x30\x54\x32\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d\xe1\xde" \
+ "\x69\x74\xbf\x49\x54\x69\xfc\x7f\x33\x8f\x80\x54\xd5\x8c\x26\xc4" \
+ "\x93\x60\xc3\xe8\x7a\xf5\x65\x23\xac\xf6\xd8\x9d\x03\xe5\x6f\xf2" \
+ "\xf8\x68\x00\x2b\xc3\xe4\x31\xed\xc4\x4d\xf2\xf0\x22\x3d\x4b\xb3" \
+ "\xb2\x43\x58\x6e\x1a\x7d\x92\x49\x36\x69\x4f\xcb\xba\xf8\x8d\x95" \
+ "\x19\xe4\xeb\x50\xa6\x44\xf8\xe4\xf9\x5e\xb0\xea\x95\xbc\x44\x65" \
+ "\xc8\x82\x1a\xac\xd2\xfe\x15\xab\x49\x81\x16\x4b\xbb\x6d\xc3\x2f" \
+ "\x96\x90\x87\xa1\x45\xb0\xd9\xcc\x9c\x67\xc2\x2b\x76\x32\x99\x41" \
+ "\x9c\xc4\x12\x8b\xe9\xa0\x77\xb3\xac\xe6\x34\x06\x4e\x6d\x99\x28" \
+ "\x35\x13\xdc\x06\xe7\x51\x5d\x0d\x73\x13\x2e\x9a\x0d\xc6\xd3\xb1" \
+ "\xf8\xb2\x46\xf1\xa9\x8a\x3f\xc7\x29\x41\xb1\xe3\xbb\x20\x98\xe8" \
+ "\xbf\x16\xf2\x68\xd6\x4f\x0b\x0f\x47\x07\xfe\x1e\xa1\xa1\x79\x1b" \
+ "\xa2\xf3\xc0\xc7\x58\xe5\xf5\x51\x86\x3a\x96\xc9\x49\xad\x47\xd7" \
+ "\xfb\x40\xd2"
+#define SHA1_SEED "\xd0\x56\x9c\xb3\x66\x5a\x8a\x43\xeb\x6e\xa2\x3d" \
+
+
+
+Eastlake 3rd & Hansen Informational [Page 81]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ "\x75\xa3\xc4\xd2\x05\x4a\x0d\x7d"
+#define SHA224_SEED "\xd0\x56\x9c\xb3\x66\x5a\x8a\x43\xeb\x6e\xa2" \
+ "\x3d\x75\xa3\xc4\xd2\x05\x4a\x0d\x7d\x66\xa9\xca\x99\xc9\xce\xb0" \
+ "\x27"
+#define SHA256_SEED "\xf4\x1e\xce\x26\x13\xe4\x57\x39\x15\x69\x6b" \
+ "\x5a\xdc\xd5\x1c\xa3\x28\xbe\x3b\xf5\x66\xa9\xca\x99\xc9\xce\xb0" \
+ "\x27\x9c\x1c\xb0\xa7"
+#define SHA384_SEED "\x82\x40\xbc\x51\xe4\xec\x7e\xf7\x6d\x18\xe3" \
+ "\x52\x04\xa1\x9f\x51\xa5\x21\x3a\x73\xa8\x1d\x6f\x94\x46\x80\xd3" \
+ "\x07\x59\x48\xb7\xe4\x63\x80\x4e\xa3\xd2\x6e\x13\xea\x82\x0d\x65" \
+ "\xa4\x84\xbe\x74\x53"
+#define SHA512_SEED "\x47\x3f\xf1\xb9\xb3\xff\xdf\xa1\x26\x69\x9a" \
+ "\xc7\xef\x9e\x8e\x78\x77\x73\x09\x58\x24\xc6\x42\x55\x7c\x13\x99" \
+ "\xd9\x8e\x42\x20\x44\x8d\xc3\x5b\x99\xbf\xdd\x44\x77\x95\x43\x92" \
+ "\x4c\x1c\xe9\x3b\xc5\x94\x15\x38\x89\x5d\xb9\x88\x26\x1b\x00\x77" \
+ "\x4b\x12\x27\x20\x39"
+
+#define TESTCOUNT 10
+#define HASHCOUNT 5
+#define RANDOMCOUNT 4
+#define HMACTESTCOUNT 7
+
+#define PRINTNONE 0
+#define PRINTTEXT 1
+#define PRINTRAW 2
+#define PRINTHEX 3
+#define PRINTBASE64 4
+
+#define PRINTPASSFAIL 1
+#define PRINTFAIL 2
+
+#define length(x) (sizeof(x)-1)
+
+/* Test arrays for hashes. */
+struct hash {
+ const char *name;
+ SHAversion whichSha;
+ int hashsize;
+ struct {
+ const char *testarray;
+ int length;
+ long repeatcount;
+ int extrabits;
+ int numberExtrabits;
+ const char *resultarray;
+ } tests[TESTCOUNT];
+ const char *randomtest;
+ const char *randomresults[RANDOMCOUNT];
+
+
+
+Eastlake 3rd & Hansen Informational [Page 82]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+} hashes[HASHCOUNT] = {
+ { "SHA1", SHA1, SHA1HashSize,
+ {
+ /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
+ "A9993E364706816ABA3E25717850C26C9CD0D89D" },
+ /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0,
+ "84983E441C3BD26EBAAE4AA1F95129E5E54670F1" },
+ /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
+ "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" },
+ /* 4 */ { TEST4, length(TEST4), 10, 0, 0,
+ "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452" },
+ /* 5 */ { "", 0, 0, 0x98, 5,
+ "29826B003B906E660EFF4027CE98AF3531AC75BA" },
+ /* 6 */ { "\x5e", 1, 1, 0, 0,
+ "5E6F80A34A9798CAFC6A5DB96CC57BA4C4DB59C2" },
+ /* 7 */ { TEST7_1, length(TEST7_1), 1, 0x80, 3,
+ "6239781E03729919C01955B3FFA8ACB60B988340" },
+ /* 8 */ { TEST8_1, length(TEST8_1), 1, 0, 0,
+ "82ABFF6605DBE1C17DEF12A394FA22A82B544A35" },
+ /* 9 */ { TEST9_1, length(TEST9_1), 1, 0xE0, 3,
+ "8C5B2A5DDAE5A97FC7F9D85661C672ADBF7933D4" },
+ /* 10 */ { TEST10_1, length(TEST10_1), 1, 0, 0,
+ "CB0082C8F197D260991BA6A460E76E202BAD27B3" }
+ }, SHA1_SEED, { "E216836819477C7F78E0D843FE4FF1B6D6C14CD4",
+ "A2DBC7A5B1C6C0A8BCB7AAA41252A6A7D0690DBC",
+ "DB1F9050BB863DFEF4CE37186044E2EEB17EE013",
+ "127FDEDF43D372A51D5747C48FBFFE38EF6CDF7B"
+ } },
+ { "SHA224", SHA224, SHA224HashSize,
+ {
+ /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
+ "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7" },
+ /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0,
+ "75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B1952522525" },
+ /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
+ "20794655980C91D8BBB4C1EA97618A4BF03F42581948B2EE4EE7AD67" },
+ /* 4 */ { TEST4, length(TEST4), 10, 0, 0,
+ "567F69F168CD7844E65259CE658FE7AADFA25216E68ECA0EB7AB8262" },
+ /* 5 */ { "", 0, 0, 0x68, 5,
+ "E3B048552C3C387BCAB37F6EB06BB79B96A4AEE5FF27F51531A9551C" },
+ /* 6 */ { "\x07", 1, 1, 0, 0,
+ "00ECD5F138422B8AD74C9799FD826C531BAD2FCABC7450BEE2AA8C2A" },
+ /* 7 */ { TEST7_224, length(TEST7_224), 1, 0xA0, 3,
+ "1B01DB6CB4A9E43DED1516BEB3DB0B87B6D1EA43187462C608137150" },
+ /* 8 */ { TEST8_224, length(TEST8_224), 1, 0, 0,
+ "DF90D78AA78821C99B40BA4C966921ACCD8FFB1E98AC388E56191DB1" },
+ /* 9 */ { TEST9_224, length(TEST9_224), 1, 0xE0, 3,
+ "54BEA6EAB8195A2EB0A7906A4B4A876666300EEFBD1F3B8474F9CD57" },
+
+
+
+Eastlake 3rd & Hansen Informational [Page 83]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ /* 10 */ { TEST10_224, length(TEST10_224), 1, 0, 0,
+ "0B31894EC8937AD9B91BDFBCBA294D9ADEFAA18E09305E9F20D5C3A4" }
+ }, SHA224_SEED, { "100966A5B4FDE0B42E2A6C5953D4D7F41BA7CF79FD"
+ "2DF431416734BE", "1DCA396B0C417715DEFAAE9641E10A2E99D55A"
+ "BCB8A00061EB3BE8BD", "1864E627BDB2319973CD5ED7D68DA71D8B"
+ "F0F983D8D9AB32C34ADB34", "A2406481FC1BCAF24DD08E6752E844"
+ "709563FB916227FED598EB621F"
+ } },
+ { "SHA256", SHA256, SHA256HashSize,
+ {
+ /* 1 */ { TEST1, length(TEST1), 1, 0, 0, "BA7816BF8F01CFEA4141"
+ "40DE5DAE2223B00361A396177A9CB410FF61F20015AD" },
+ /* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0, "248D6A61D20638B8"
+ "E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1" },
+ /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, "CDC76E5C9914FB92"
+ "81A1C7E284D73E67F1809A48A497200E046D39CCC7112CD0" },
+ /* 4 */ { TEST4, length(TEST4), 10, 0, 0, "594847328451BDFA"
+ "85056225462CC1D867D877FB388DF0CE35F25AB5562BFBB5" },
+ /* 5 */ { "", 0, 0, 0x68, 5, "D6D3E02A31A84A8CAA9718ED6C2057BE"
+ "09DB45E7823EB5079CE7A573A3760F95" },
+ /* 6 */ { "\x19", 1, 1, 0, 0, "68AA2E2EE5DFF96E3355E6C7EE373E3D"
+ "6A4E17F75F9518D843709C0C9BC3E3D4" },
+ /* 7 */ { TEST7_256, length(TEST7_256), 1, 0x60, 3, "77EC1DC8"
+ "9C821FF2A1279089FA091B35B8CD960BCAF7DE01C6A7680756BEB972" },
+ /* 8 */ { TEST8_256, length(TEST8_256), 1, 0, 0, "175EE69B02BA"
+ "9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8" },
+ /* 9 */ { TEST9_256, length(TEST9_256), 1, 0xA0, 3, "3E9AD646"
+ "8BBBAD2AC3C2CDC292E018BA5FD70B960CF1679777FCE708FDB066E9" },
+ /* 10 */ { TEST10_256, length(TEST10_256), 1, 0, 0, "97DBCA7D"
+ "F46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC" },
+ }, SHA256_SEED, { "83D28614D49C3ADC1D6FC05DB5F48037C056F8D2A4CE44"
+ "EC6457DEA5DD797CD1", "99DBE3127EF2E93DD9322D6A07909EB33B6399"
+ "5E529B3F954B8581621BB74D39", "8D4BE295BB64661CA3C7EFD129A2F7"
+ "25B33072DBDDE32385B9A87B9AF88EA76F", "40AF5D3F9716B040DF9408"
+ "E31536B70FF906EC51B00447CA97D7DD97C12411F4"
+ } },
+ { "SHA384", SHA384, SHA384HashSize,
+ {
+ /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
+ "CB00753F45A35E8BB5A03D699AC65007272C32AB0EDED163"
+ "1A8B605A43FF5BED8086072BA1E7CC2358BAECA134C825A7" },
+ /* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0,
+ "09330C33F71147E83D192FC782CD1B4753111B173B3B05D2"
+ "2FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039" },
+ /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
+ "9D0E1809716474CB086E834E310A4A1CED149E9C00F24852"
+ "7972CEC5704C2A5B07B8B3DC38ECC4EBAE97DDD87F3D8985" },
+ /* 4 */ { TEST4, length(TEST4), 10, 0, 0,
+
+
+
+Eastlake 3rd & Hansen Informational [Page 84]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ "2FC64A4F500DDB6828F6A3430B8DD72A368EB7F3A8322A70"
+ "BC84275B9C0B3AB00D27A5CC3C2D224AA6B61A0D79FB4596" },
+ /* 5 */ { "", 0, 0, 0x10, 5,
+ "8D17BE79E32B6718E07D8A603EB84BA0478F7FCFD1BB9399"
+ "5F7D1149E09143AC1FFCFC56820E469F3878D957A15A3FE4" },
+ /* 6 */ { "\xb9", 1, 1, 0, 0,
+ "BC8089A19007C0B14195F4ECC74094FEC64F01F90929282C"
+ "2FB392881578208AD466828B1C6C283D2722CF0AD1AB6938" },
+ /* 7 */ { TEST7_384, length(TEST7_384), 1, 0xA0, 3,
+ "D8C43B38E12E7C42A7C9B810299FD6A770BEF30920F17532"
+ "A898DE62C7A07E4293449C0B5FA70109F0783211CFC4BCE3" },
+ /* 8 */ { TEST8_384, length(TEST8_384), 1, 0, 0,
+ "C9A68443A005812256B8EC76B00516F0DBB74FAB26D66591"
+ "3F194B6FFB0E91EA9967566B58109CBC675CC208E4C823F7" },
+ /* 9 */ { TEST9_384, length(TEST9_384), 1, 0xE0, 3,
+ "5860E8DE91C21578BB4174D227898A98E0B45C4C760F0095"
+ "49495614DAEDC0775D92D11D9F8CE9B064EEAC8DAFC3A297" },
+ /* 10 */ { TEST10_384, length(TEST10_384), 1, 0, 0,
+ "4F440DB1E6EDD2899FA335F09515AA025EE177A79F4B4AAF"
+ "38E42B5C4DE660F5DE8FB2A5B2FBD2A3CBFFD20CFF1288C0" }
+ }, SHA384_SEED, { "CE44D7D63AE0C91482998CF662A51EC80BF6FC68661A3C"
+ "57F87566112BD635A743EA904DEB7D7A42AC808CABE697F38F", "F9C6D2"
+ "61881FEE41ACD39E67AA8D0BAD507C7363EB67E2B81F45759F9C0FD7B503"
+ "DF1A0B9E80BDE7BC333D75B804197D", "D96512D8C9F4A7A4967A366C01"
+ "C6FD97384225B58343A88264847C18E4EF8AB7AEE4765FFBC3E30BD485D3"
+ "638A01418F", "0CA76BD0813AF1509E170907A96005938BC985628290B2"
+ "5FEF73CF6FAD68DDBA0AC8920C94E0541607B0915A7B4457F7"
+ } },
+ { "SHA512", SHA512, SHA512HashSize,
+ {
+ /* 1 */ { TEST1, length(TEST1), 1, 0, 0,
+ "DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2"
+ "0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD"
+ "454D4423643CE80E2A9AC94FA54CA49F" },
+ /* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0,
+ "8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1"
+ "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A"
+ "C7D329EEB6DD26545E96E55B874BE909" },
+ /* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
+ "E718483D0CE769644E2E42C7BC15B4638E1F98B13B204428"
+ "5632A803AFA973EBDE0FF244877EA60A4CB0432CE577C31B"
+ "EB009C5C2C49AA2E4EADB217AD8CC09B" },
+ /* 4 */ { TEST4, length(TEST4), 10, 0, 0,
+ "89D05BA632C699C31231DED4FFC127D5A894DAD412C0E024"
+ "DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF33C765CB51"
+ "0813A39CD5A84C4ACAA64D3F3FB7BAE9" },
+ /* 5 */ { "", 0, 0, 0xB0, 5,
+ "D4EE29A9E90985446B913CF1D1376C836F4BE2C1CF3CADA0"
+
+
+
+Eastlake 3rd & Hansen Informational [Page 85]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ "720A6BF4857D886A7ECB3C4E4C0FA8C7F95214E41DC1B0D2"
+ "1B22A84CC03BF8CE4845F34DD5BDBAD4" },
+ /* 6 */ { "\xD0", 1, 1, 0, 0,
+ "9992202938E882E73E20F6B69E68A0A7149090423D93C81B"
+ "AB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4A"
+ "D6E74CECE9631BFA8A549B4AB3FBBA15" },
+ /* 7 */ { TEST7_512, length(TEST7_512), 1, 0x80, 3,
+ "ED8DC78E8B01B69750053DBB7A0A9EDA0FB9E9D292B1ED71"
+ "5E80A7FE290A4E16664FD913E85854400C5AF05E6DAD316B"
+ "7359B43E64F8BEC3C1F237119986BBB6" },
+ /* 8 */ { TEST8_512, length(TEST8_512), 1, 0, 0,
+ "CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75ACBD"
+ "D1C153C9828924C3DDEDAAFE669C5FDD0BC66F630F677398"
+ "8213EB1B16F517AD0DE4B2F0C95C90F8" },
+ /* 9 */ { TEST9_512, length(TEST9_512), 1, 0x80, 3,
+ "32BA76FC30EAA0208AEB50FFB5AF1864FDBF17902A4DC0A6"
+ "82C61FCEA6D92B783267B21080301837F59DE79C6B337DB2"
+ "526F8A0A510E5E53CAFED4355FE7C2F1" },
+ /* 10 */ { TEST10_512, length(TEST10_512), 1, 0, 0,
+ "C665BEFB36DA189D78822D10528CBF3B12B3EEF726039909"
+ "C1A16A270D48719377966B957A878E720584779A62825C18"
+ "DA26415E49A7176A894E7510FD1451F5" }
+ }, SHA512_SEED, { "2FBB1E7E00F746BA514FBC8C421F36792EC0E11FF5EFC3"
+ "78E1AB0C079AA5F0F66A1E3EDBAEB4F9984BE14437123038A452004A5576"
+ "8C1FD8EED49E4A21BEDCD0", "25CBE5A4F2C7B1D7EF07011705D50C62C5"
+ "000594243EAFD1241FC9F3D22B58184AE2FEE38E171CF8129E29459C9BC2"
+ "EF461AF5708887315F15419D8D17FE7949", "5B8B1F2687555CE2D7182B"
+ "92E5C3F6C36547DA1C13DBB9EA4F73EA4CBBAF89411527906D35B1B06C1B"
+ "6A8007D05EC66DF0A406066829EAB618BDE3976515AAFC", "46E36B007D"
+ "19876CDB0B29AD074FE3C08CDD174D42169D6ABE5A1414B6E79707DF5877"
+ "6A98091CF431854147BB6D3C66D43BFBC108FD715BDE6AA127C2B0E79F"
+ }
+ }
+};
+
+/* Test arrays for HMAC. */
+struct hmachash {
+ const char *keyarray[5];
+ int keylength[5];
+ const char *dataarray[5];
+ int datalength[5];
+ const char *resultarray[5];
+ int resultlength[5];
+} hmachashes[HMACTESTCOUNT] = {
+ { /* 1 */ {
+ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+ "\x0b\x0b\x0b\x0b\x0b"
+ }, { 20 }, {
+
+
+
+Eastlake 3rd & Hansen Informational [Page 86]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ "\x48\x69\x20\x54\x68\x65\x72\x65" /* "Hi There" */
+ }, { 8 }, {
+ /* HMAC-SHA-1 */
+ "B617318655057264E28BC0B6FB378C8EF146BE00",
+ /* HMAC-SHA-224 */
+ "896FB1128ABBDF196832107CD49DF33F47B4B1169912BA4F53684B22",
+ /* HMAC-SHA-256 */
+ "B0344C61D8DB38535CA8AFCEAF0BF12B881DC200C9833DA726E9376C2E32"
+ "CFF7",
+ /* HMAC-SHA-384 */
+ "AFD03944D84895626B0825F4AB46907F15F9DADBE4101EC682AA034C7CEB"
+ "C59CFAEA9EA9076EDE7F4AF152E8B2FA9CB6",
+ /* HMAC-SHA-512 */
+ "87AA7CDEA5EF619D4FF0B4241A1D6CB02379F4E2CE4EC2787AD0B30545E1"
+ "7CDEDAA833B7D6B8A702038B274EAEA3F4E4BE9D914EEB61F1702E696C20"
+ "3A126854"
+ }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
+ SHA384HashSize, SHA512HashSize }
+ },
+ { /* 2 */ {
+ "\x4a\x65\x66\x65" /* "Jefe" */
+ }, { 4 }, {
+ "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74"
+ "\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f"
+ /* "what do ya want for nothing?" */
+ }, { 28 }, {
+ /* HMAC-SHA-1 */
+ "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79",
+ /* HMAC-SHA-224 */
+ "A30E01098BC6DBBF45690F3A7E9E6D0F8BBEA2A39E6148008FD05E44",
+ /* HMAC-SHA-256 */
+ "5BDCC146BF60754E6A042426089575C75A003F089D2739839DEC58B964EC"
+ "3843",
+ /* HMAC-SHA-384 */
+ "AF45D2E376484031617F78D2B58A6B1B9C7EF464F5A01B47E42EC3736322"
+ "445E8E2240CA5E69E2C78B3239ECFAB21649",
+ /* HMAC-SHA-512 */
+ "164B7A7BFCF819E2E395FBE73B56E0A387BD64222E831FD610270CD7EA25"
+ "05549758BF75C05A994A6D034F65F8F0E6FDCAEAB1A34D4A6B4B636E070A"
+ "38BCE737"
+ }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
+ SHA384HashSize, SHA512HashSize }
+ },
+ { /* 3 */
+ {
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa"
+ }, { 20 }, {
+
+
+
+Eastlake 3rd & Hansen Informational [Page 87]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
+ "\xdd\xdd\xdd\xdd\xdd"
+ }, { 50 }, {
+ /* HMAC-SHA-1 */
+ "125D7342B9AC11CD91A39AF48AA17B4F63F175D3",
+ /* HMAC-SHA-224 */
+ "7FB3CB3588C6C1F6FFA9694D7D6AD2649365B0C1F65D69D1EC8333EA",
+ /* HMAC-SHA-256 */
+ "773EA91E36800E46854DB8EBD09181A72959098B3EF8C122D9635514CED5"
+ "65FE",
+ /* HMAC-SHA-384 */
+ "88062608D3E6AD8A0AA2ACE014C8A86F0AA635D947AC9FEBE83EF4E55966"
+ "144B2A5AB39DC13814B94E3AB6E101A34F27",
+ /* HMAC-SHA-512 */
+ "FA73B0089D56A284EFB0F0756C890BE9B1B5DBDD8EE81A3655F83E33B227"
+ "9D39BF3E848279A722C806B485A47E67C807B946A337BEE8942674278859"
+ "E13292FB"
+ }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
+ SHA384HashSize, SHA512HashSize }
+ },
+ { /* 4 */ {
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19"
+ }, { 25 }, {
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
+ "\xcd\xcd\xcd\xcd\xcd"
+ }, { 50 }, {
+ /* HMAC-SHA-1 */
+ "4C9007F4026250C6BC8414F9BF50C86C2D7235DA",
+ /* HMAC-SHA-224 */
+ "6C11506874013CAC6A2ABC1BB382627CEC6A90D86EFC012DE7AFEC5A",
+ /* HMAC-SHA-256 */
+ "82558A389A443C0EA4CC819899F2083A85F0FAA3E578F8077A2E3FF46729"
+ "665B",
+ /* HMAC-SHA-384 */
+ "3E8A69B7783C25851933AB6290AF6CA77A9981480850009CC5577C6E1F57"
+ "3B4E6801DD23C4A7D679CCF8A386C674CFFB",
+ /* HMAC-SHA-512 */
+ "B0BA465637458C6990E5A8C5F61D4AF7E576D97FF94B872DE76F8050361E"
+ "E3DBA91CA5C11AA25EB4D679275CC5788063A5F19741120C4F2DE2ADEBEB"
+ "10A298DD"
+ }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
+ SHA384HashSize, SHA512HashSize }
+ },
+
+
+
+Eastlake 3rd & Hansen Informational [Page 88]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ { /* 5 */ {
+ "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+ "\x0c\x0c\x0c\x0c\x0c"
+ }, { 20 }, {
+ "Test With Truncation"
+ }, { 20 }, {
+ /* HMAC-SHA-1 */
+ "4C1A03424B55E07FE7F27BE1",
+ /* HMAC-SHA-224 */
+ "0E2AEA68A90C8D37C988BCDB9FCA6FA8",
+ /* HMAC-SHA-256 */
+ "A3B6167473100EE06E0C796C2955552B",
+ /* HMAC-SHA-384 */
+ "3ABF34C3503B2A23A46EFC619BAEF897",
+ /* HMAC-SHA-512 */
+ "415FAD6271580A531D4179BC891D87A6"
+ }, { 12, 16, 16, 16, 16 }
+ },
+ { /* 6 */ {
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ }, { 80, 131 }, {
+ "Test Using Larger Than Block-Size Key - Hash Key First"
+ }, { 54 }, {
+ /* HMAC-SHA-1 */
+ "AA4AE5E15272D00E95705637CE8A3B55ED402112",
+ /* HMAC-SHA-224 */
+ "95E9A0DB962095ADAEBE9B2D6F0DBCE2D499F112F2D2B7273FA6870E",
+ /* HMAC-SHA-256 */
+ "60E431591EE0B67F0D8A26AACBF5B77F8E0BC6213728C5140546040F0EE3"
+ "7F54",
+ /* HMAC-SHA-384 */
+ "4ECE084485813E9088D2C63A041BC5B44F9EF1012A2B588F3CD11F05033A"
+ "C4C60C2EF6AB4030FE8296248DF163F44952",
+ /* HMAC-SHA-512 */
+ "80B24263C7C1A3EBB71493C1DD7BE8B49B46D1F41B4AEEC1121B013783F8"
+ "F3526B56D037E05F2598BD0FD2215D6A1E5295E64F73F63F0AEC8B915A98"
+ "5D786598"
+ }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
+ SHA384HashSize, SHA512HashSize }
+ },
+
+
+
+Eastlake 3rd & Hansen Informational [Page 89]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ { /* 7 */ {
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
+ }, { 80, 131 }, {
+ "Test Using Larger Than Block-Size Key and "
+ "Larger Than One Block-Size Data",
+ "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x20"
+ "\x75\x73\x69\x6e\x67\x20\x61\x20\x6c\x61\x72\x67\x65\x72\x20"
+ "\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73\x69\x7a\x65"
+ "\x20\x6b\x65\x79\x20\x61\x6e\x64\x20\x61\x20\x6c\x61\x72\x67"
+ "\x65\x72\x20\x74\x68\x61\x6e\x20\x62\x6c\x6f\x63\x6b\x2d\x73"
+ "\x69\x7a\x65\x20\x64\x61\x74\x61\x2e\x20\x54\x68\x65\x20\x6b"
+ "\x65\x79\x20\x6e\x65\x65\x64\x73\x20\x74\x6f\x20\x62\x65\x20"
+ "\x68\x61\x73\x68\x65\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x62"
+ "\x65\x69\x6e\x67\x20\x75\x73\x65\x64\x20\x62\x79\x20\x74\x68"
+ "\x65\x20\x48\x4d\x41\x43\x20\x61\x6c\x67\x6f\x72\x69\x74\x68"
+ "\x6d\x2e"
+ /* "This is a test using a larger than block-size key and a "
+ "larger than block-size data. The key needs to be hashed "
+ "before being used by the HMAC algorithm." */
+ }, { 73, 152 }, {
+ /* HMAC-SHA-1 */
+ "E8E99D0F45237D786D6BBAA7965C7808BBFF1A91",
+ /* HMAC-SHA-224 */
+ "3A854166AC5D9F023F54D517D0B39DBD946770DB9C2B95C9F6F565D1",
+ /* HMAC-SHA-256 */
+ "9B09FFA71B942FCB27635FBCD5B0E944BFDC63644F0713938A7F51535C3A"
+ "35E2",
+ /* HMAC-SHA-384 */
+ "6617178E941F020D351E2F254E8FD32C602420FEB0B8FB9ADCCEBB82461E"
+ "99C5A678CC31E799176D3860E6110C46523E",
+ /* HMAC-SHA-512 */
+ "E37B6A775DC87DBAA4DFA9F96E5E3FFDDEBD71F8867289865DF5A32D20CD"
+ "C944B6022CAC3C4982B10D5EEB55C3E4DE15134676FB6DE0446065C97440"
+ "FA8C6A58"
+ }, { SHA1HashSize, SHA224HashSize, SHA256HashSize,
+ SHA384HashSize, SHA512HashSize }
+ }
+};
+
+/*
+
+
+
+Eastlake 3rd & Hansen Informational [Page 90]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * Check the hash value against the expected string, expressed in hex
+ */
+static const char hexdigits[] = "0123456789ABCDEF";
+int checkmatch(const unsigned char *hashvalue,
+ const char *hexstr, int hashsize)
+{
+ int i;
+ for (i = 0; i < hashsize; ++i) {
+ if (*hexstr++ != hexdigits[(hashvalue[i] >> 4) & 0xF])
+ return 0;
+ if (*hexstr++ != hexdigits[hashvalue[i] & 0xF]) return 0;
+ }
+ return 1;
+}
+
+/*
+ * Print the string, converting non-printable characters to "."
+ */
+void printstr(const char *str, int len)
+{
+ for ( ; len-- > 0; str++)
+ putchar(isprint((unsigned char)*str) ? *str : '.');
+}
+
+/*
+ * Print the string, converting non-printable characters to hex "## ".
+ */
+void printxstr(const char *str, int len)
+{
+ for ( ; len-- > 0; str++)
+ printf("%c%c ", hexdigits[(*str >> 4) & 0xF],
+ hexdigits[*str & 0xF]);
+}
+
+/*
+ * Print a usage message.
+ */
+void usage(const char *argv0)
+{
+ fprintf(stderr,
+ "Usage:\n"
+ "Common options: [-h hash] [-w|-x] [-H]\n"
+ "Standard tests:\n"
+ "\t%s [-m] [-l loopcount] [-t test#] [-e]\n"
+ "\t\t[-r randomseed] [-R randomloop-count] "
+ "[-p] [-P|-X]\n"
+ "Hash a string:\n"
+ "\t%s [-S expectedresult] -s hashstr [-k key]\n"
+
+
+
+Eastlake 3rd & Hansen Informational [Page 91]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ "Hash a file:\n"
+ "\t%s [-S expectedresult] -f file [-k key]\n"
+ "Hash a file, ignoring whitespace:\n"
+ "\t%s [-S expectedresult] -F file [-k key]\n"
+ "Additional bits to add in: [-B bitcount -b bits]\n"
+ "-h\thash to test: "
+ "0|SHA1, 1|SHA224, 2|SHA256, 3|SHA384, 4|SHA512\n"
+ "-m\tperform hmac test\n"
+ "-k\tkey for hmac test\n"
+ "-t\ttest case to run, 1-10\n"
+ "-l\thow many times to run the test\n"
+ "-e\ttest error returns\n"
+ "-p\tdo not print results\n"
+ "-P\tdo not print PASSED/FAILED\n"
+ "-X\tprint FAILED, but not PASSED\n"
+ "-r\tseed for random test\n"
+ "-R\thow many times to run random test\n"
+ "-s\tstring to hash\n"
+ "-S\texpected result of hashed string, in hex\n"
+ "-w\toutput hash in raw format\n"
+ "-x\toutput hash in hex format\n"
+ "-B\t# extra bits to add in after string or file input\n"
+ "-b\textra bits to add (high order bits of #, 0# or 0x#)\n"
+ "-H\tinput hashstr or randomseed is in hex\n"
+ , argv0, argv0, argv0, argv0);
+ exit(1);
+}
+
+/*
+ * Print the results and PASS/FAIL.
+ */
+void printResult(uint8_t *Message_Digest, int hashsize,
+ const char *hashname, const char *testtype, const char *testname,
+ const char *resultarray, int printResults, int printPassFail)
+{
+ int i, k;
+ if (printResults == PRINTTEXT) {
+ putchar('\t');
+ for (i = 0; i < hashsize ; ++i) {
+ putchar(hexdigits[(Message_Digest[i] >> 4) & 0xF]);
+ putchar(hexdigits[Message_Digest[i] & 0xF]);
+ putchar(' ');
+ }
+ putchar('\n');
+ } else if (printResults == PRINTRAW) {
+ fwrite(Message_Digest, 1, hashsize, stdout);
+ } else if (printResults == PRINTHEX) {
+ for (i = 0; i < hashsize ; ++i) {
+
+
+
+Eastlake 3rd & Hansen Informational [Page 92]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ putchar(hexdigits[(Message_Digest[i] >> 4) & 0xF]);
+ putchar(hexdigits[Message_Digest[i] & 0xF]);
+ }
+ putchar('\n');
+ }
+
+ if (printResults && resultarray) {
+ printf(" Should match:\n\t");
+ for (i = 0, k = 0; i < hashsize; i++, k += 2) {
+ putchar(resultarray[k]);
+ putchar(resultarray[k+1]);
+ putchar(' ');
+ }
+ putchar('\n');
+ }
+
+ if (printPassFail && resultarray) {
+ int ret = checkmatch(Message_Digest, resultarray, hashsize);
+ if ((printPassFail == PRINTPASSFAIL) || !ret)
+ printf("%s %s %s: %s\n", hashname, testtype, testname,
+ ret ? "PASSED" : "FAILED");
+ }
+}
+
+/*
+ * Exercise a hash series of functions. The input is the testarray,
+ * repeated repeatcount times, followed by the extrabits. If the
+ * result is known, it is in resultarray in uppercase hex.
+ */
+int hash(int testno, int loopno, int hashno,
+ const char *testarray, int length, long repeatcount,
+ int numberExtrabits, int extrabits, const unsigned char *keyarray,
+ int keylen, const char *resultarray, int hashsize, int printResults,
+ int printPassFail)
+{
+ USHAContext sha;
+ HMACContext hmac;
+ int err, i;
+ uint8_t Message_Digest[USHAMaxHashSize];
+ char buf[20];
+
+ if (printResults == PRINTTEXT) {
+ printf("\nTest %d: Iteration %d, Repeat %ld\n\t'", testno+1,
+ loopno, repeatcount);
+ printstr(testarray, length);
+ printf("'\n\t'");
+ printxstr(testarray, length);
+ printf("'\n");
+
+
+
+Eastlake 3rd & Hansen Informational [Page 93]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ printf(" Length=%d bytes (%d bits), ", length, length * 8);
+ printf("ExtraBits %d: %2.2x\n", numberExtrabits, extrabits);
+ }
+
+ memset(&sha, '\343', sizeof(sha)); /* force bad data into struct */
+ memset(&hmac, '\343', sizeof(hmac));
+ err = keyarray ? hmacReset(&hmac, hashes[hashno].whichSha,
+ keyarray, keylen) :
+ USHAReset(&sha, hashes[hashno].whichSha);
+ if (err != shaSuccess) {
+ fprintf(stderr, "hash(): %sReset Error %d.\n",
+ keyarray ? "hmac" : "sha", err);
+ return err;
+ }
+
+ for (i = 0; i < repeatcount; ++i) {
+ err = keyarray ? hmacInput(&hmac, (const uint8_t *) testarray,
+ length) :
+ USHAInput(&sha, (const uint8_t *) testarray,
+ length);
+ if (err != shaSuccess) {
+ fprintf(stderr, "hash(): %sInput Error %d.\n",
+ keyarray ? "hmac" : "sha", err);
+ return err;
+ }
+ }
+
+ if (numberExtrabits > 0) {
+ err = keyarray ? hmacFinalBits(&hmac, (uint8_t) extrabits,
+ numberExtrabits) :
+ USHAFinalBits(&sha, (uint8_t) extrabits,
+ numberExtrabits);
+ if (err != shaSuccess) {
+ fprintf(stderr, "hash(): %sFinalBits Error %d.\n",
+ keyarray ? "hmac" : "sha", err);
+ return err;
+ }
+ }
+
+ err = keyarray ? hmacResult(&hmac, Message_Digest) :
+ USHAResult(&sha, Message_Digest);
+ if (err != shaSuccess) {
+ fprintf(stderr, "hash(): %s Result Error %d, could not "
+ "compute message digest.\n", keyarray ? "hmac" : "sha", err);
+ return err;
+ }
+
+ sprintf(buf, "%d", testno+1);
+
+
+
+Eastlake 3rd & Hansen Informational [Page 94]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ printResult(Message_Digest, hashsize, hashes[hashno].name,
+ keyarray ? "hmac standard test" : "sha standard test", buf,
+ resultarray, printResults, printPassFail);
+
+ return err;
+}
+
+/*
+ * Exercise a hash series of functions. The input is a filename.
+ * If the result is known, it is in resultarray in uppercase hex.
+ */
+int hashfile(int hashno, const char *hashfilename, int bits,
+ int bitcount, int skipSpaces, const unsigned char *keyarray,
+ int keylen, const char *resultarray, int hashsize,
+ int printResults, int printPassFail)
+{
+ USHAContext sha;
+ HMACContext hmac;
+ int err, nread, c;
+ unsigned char buf[4096];
+ uint8_t Message_Digest[USHAMaxHashSize];
+ unsigned char cc;
+ FILE *hashfp = (strcmp(hashfilename, "-") == 0) ? stdin :
+ fopen(hashfilename, "r");
+
+ if (!hashfp) {
+ fprintf(stderr, "cannot open file '%s'\n", hashfilename);
+ return shaStateError;
+ }
+
+ memset(&sha, '\343', sizeof(sha)); /* force bad data into struct */
+ memset(&hmac, '\343', sizeof(hmac));
+ err = keyarray ? hmacReset(&hmac, hashes[hashno].whichSha,
+ keyarray, keylen) :
+ USHAReset(&sha, hashes[hashno].whichSha);
+
+ if (err != shaSuccess) {
+ fprintf(stderr, "hashfile(): %sReset Error %d.\n",
+ keyarray ? "hmac" : "sha", err);
+ return err;
+ }
+
+ if (skipSpaces)
+ while ((c = getc(hashfp)) != EOF) {
+ if (!isspace(c)) {
+ cc = (unsigned char)c;
+ err = keyarray ? hmacInput(&hmac, &cc, 1) :
+ USHAInput(&sha, &cc, 1);
+
+
+
+Eastlake 3rd & Hansen Informational [Page 95]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ if (err != shaSuccess) {
+ fprintf(stderr, "hashfile(): %sInput Error %d.\n",
+ keyarray ? "hmac" : "sha", err);
+ if (hashfp != stdin) fclose(hashfp);
+ return err;
+ }
+ }
+ }
+ else
+ while ((nread = fread(buf, 1, sizeof(buf), hashfp)) > 0) {
+ err = keyarray ? hmacInput(&hmac, buf, nread) :
+ USHAInput(&sha, buf, nread);
+ if (err != shaSuccess) {
+ fprintf(stderr, "hashfile(): %s Error %d.\n",
+ keyarray ? "hmacInput" : "shaInput", err);
+ if (hashfp != stdin) fclose(hashfp);
+ return err;
+ }
+ }
+
+ if (bitcount > 0)
+ err = keyarray ? hmacFinalBits(&hmac, bits, bitcount) :
+ USHAFinalBits(&sha, bits, bitcount);
+ if (err != shaSuccess) {
+ fprintf(stderr, "hashfile(): %s Error %d.\n",
+ keyarray ? "hmacResult" : "shaResult", err);
+ if (hashfp != stdin) fclose(hashfp);
+ return err;
+ }
+
+ err = keyarray ? hmacResult(&hmac, Message_Digest) :
+ USHAResult(&sha, Message_Digest);
+ if (err != shaSuccess) {
+ fprintf(stderr, "hashfile(): %s Error %d.\n",
+ keyarray ? "hmacResult" : "shaResult", err);
+ if (hashfp != stdin) fclose(hashfp);
+ return err;
+ }
+
+ printResult(Message_Digest, hashsize, hashes[hashno].name, "file",
+ hashfilename, resultarray, printResults, printPassFail);
+
+ if (hashfp != stdin) fclose(hashfp);
+ return err;
+}
+
+/*
+ * Exercise a hash series of functions through multiple permutations.
+
+
+
+Eastlake 3rd & Hansen Informational [Page 96]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ * The input is an initial seed. That seed is replicated 3 times.
+ * For 1000 rounds, the previous three results are used as the input.
+ * This result is then checked, and used to seed the next cycle.
+ * If the result is known, it is in resultarrays in uppercase hex.
+ */
+void randomtest(int hashno, const char *seed, int hashsize,
+ const char **resultarrays, int randomcount,
+ int printResults, int printPassFail)
+{
+ int i, j; char buf[20];
+ unsigned char SEED[USHAMaxHashSize], MD[1003][USHAMaxHashSize];
+
+ /* INPUT: Seed - A random seed n bits long */
+ memcpy(SEED, seed, hashsize);
+ if (printResults == PRINTTEXT) {
+ printf("%s random test seed= '", hashes[hashno].name);
+ printxstr(seed, hashsize);
+ printf("'\n");
+ }
+
+ for (j = 0; j < randomcount; j++) {
+ /* MD0 = MD1 = MD2 = Seed; */
+ memcpy(MD[0], SEED, hashsize);
+ memcpy(MD[1], SEED, hashsize);
+ memcpy(MD[2], SEED, hashsize);
+ for (i=3; i<1003; i++) {
+ /* Mi = MDi-3 || MDi-2 || MDi-1; */
+ USHAContext Mi;
+ memset(&Mi, '\343', sizeof(Mi)); /* force bad data into struct */
+ USHAReset(&Mi, hashes[hashno].whichSha);
+ USHAInput(&Mi, MD[i-3], hashsize);
+ USHAInput(&Mi, MD[i-2], hashsize);
+ USHAInput(&Mi, MD[i-1], hashsize);
+ /* MDi = SHA(Mi); */
+ USHAResult(&Mi, MD[i]);
+ }
+
+ /* MDj = Seed = MDi; */
+ memcpy(SEED, MD[i-1], hashsize);
+
+ /* OUTPUT: MDj */
+ sprintf(buf, "%d", j);
+ printResult(SEED, hashsize, hashes[hashno].name, "random test",
+ buf, resultarrays ? resultarrays[j] : 0, printResults,
+ (j < RANDOMCOUNT) ? printPassFail : 0);
+ }
+}
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 97]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+/*
+ * Look up a hash name.
+ */
+int findhash(const char *argv0, const char *opt)
+{
+ int i;
+ const char *names[HASHCOUNT][2] = {
+ { "0", "sha1" }, { "1", "sha224" }, { "2", "sha256" },
+ { "3", "sha384" }, { "4", "sha512" }
+ };
+
+ for (i = 0; i < HASHCOUNT; i++)
+ if ((strcmp(opt, names[i][0]) == 0) ||
+ (scasecmp(opt, names[i][1]) == 0))
+ return i;
+
+ fprintf(stderr, "%s: Unknown hash name: '%s'\n", argv0, opt);
+ usage(argv0);
+ return 0;
+}
+
+/*
+ * Run some tests that should invoke errors.
+ */
+void testErrors(int hashnolow, int hashnohigh, int printResults,
+ int printPassFail)
+{
+ USHAContext usha;
+ uint8_t Message_Digest[USHAMaxHashSize];
+ int hashno, err;
+
+ for (hashno = hashnolow; hashno <= hashnohigh; hashno++) {
+ memset(&usha, '\343', sizeof(usha)); /* force bad data */
+ USHAReset(&usha, hashno);
+ USHAResult(&usha, Message_Digest);
+ err = USHAInput(&usha, (const unsigned char *)"foo", 3);
+ if (printResults == PRINTTEXT)
+ printf ("\nError %d. Should be %d.\n", err, shaStateError);
+ if ((printPassFail == PRINTPASSFAIL) ||
+ ((printPassFail == PRINTFAIL) && (err != shaStateError)))
+ printf("%s se: %s\n", hashes[hashno].name,
+ (err == shaStateError) ? "PASSED" : "FAILED");
+
+ err = USHAFinalBits(&usha, 0x80, 3);
+ if (printResults == PRINTTEXT)
+ printf ("\nError %d. Should be %d.\n", err, shaStateError);
+ if ((printPassFail == PRINTPASSFAIL) ||
+ ((printPassFail == PRINTFAIL) && (err != shaStateError)))
+
+
+
+Eastlake 3rd & Hansen Informational [Page 98]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ printf("%s se: %s\n", hashes[hashno].name,
+ (err == shaStateError) ? "PASSED" : "FAILED");
+
+ err = USHAReset(0, hashes[hashno].whichSha);
+ if (printResults == PRINTTEXT)
+ printf("\nError %d. Should be %d.\n", err, shaNull);
+ if ((printPassFail == PRINTPASSFAIL) ||
+ ((printPassFail == PRINTFAIL) && (err != shaNull)))
+ printf("%s usha null: %s\n", hashes[hashno].name,
+ (err == shaNull) ? "PASSED" : "FAILED");
+
+ switch (hashno) {
+ case SHA1: err = SHA1Reset(0); break;
+ case SHA224: err = SHA224Reset(0); break;
+ case SHA256: err = SHA256Reset(0); break;
+ case SHA384: err = SHA384Reset(0); break;
+ case SHA512: err = SHA512Reset(0); break;
+ }
+ if (printResults == PRINTTEXT)
+ printf("\nError %d. Should be %d.\n", err, shaNull);
+ if ((printPassFail == PRINTPASSFAIL) ||
+ ((printPassFail == PRINTFAIL) && (err != shaNull)))
+ printf("%s sha null: %s\n", hashes[hashno].name,
+ (err == shaNull) ? "PASSED" : "FAILED");
+ }
+}
+
+/* replace a hex string in place with its value */
+int unhexStr(char *hexstr)
+{
+ char *o = hexstr;
+ int len = 0, nibble1 = 0, nibble2 = 0;
+ if (!hexstr) return 0;
+ for ( ; *hexstr; hexstr++) {
+ if (isalpha((int)(unsigned char)(*hexstr))) {
+ nibble1 = tolower(*hexstr) - 'a' + 10;
+ } else if (isdigit((int)(unsigned char)(*hexstr))) {
+ nibble1 = *hexstr - '0';
+ } else {
+ printf("\nError: bad hex character '%c'\n", *hexstr);
+ }
+ if (!*++hexstr) break;
+ if (isalpha((int)(unsigned char)(*hexstr))) {
+ nibble2 = tolower(*hexstr) - 'a' + 10;
+ } else if (isdigit((int)(unsigned char)(*hexstr))) {
+ nibble2 = *hexstr - '0';
+ } else {
+ printf("\nError: bad hex character '%c'\n", *hexstr);
+
+
+
+Eastlake 3rd & Hansen Informational [Page 99]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ }
+ *o++ = (char)((nibble1 << 4) | nibble2);
+ len++;
+ }
+ return len;
+}
+
+int main(int argc, char **argv)
+{
+ int i, err;
+ int loopno, loopnohigh = 1;
+ int hashno, hashnolow = 0, hashnohigh = HASHCOUNT - 1;
+ int testno, testnolow = 0, testnohigh;
+ int ntestnohigh = 0;
+ int printResults = PRINTTEXT;
+ int printPassFail = 1;
+ int checkErrors = 0;
+ char *hashstr = 0;
+ int hashlen = 0;
+ const char *resultstr = 0;
+ char *randomseedstr = 0;
+ int runHmacTests = 0;
+ char *hmacKey = 0;
+ int hmaclen = 0;
+ int randomcount = RANDOMCOUNT;
+ const char *hashfilename = 0;
+ const char *hashFilename = 0;
+ int extrabits = 0, numberExtrabits = 0;
+ int strIsHex = 0;
+
+ while ((i = xgetopt(argc, argv, "b:B:ef:F:h:Hk:l:mpPr:R:s:S:t:wxX"))
+ != -1)
+ switch (i) {
+ case 'b': extrabits = strtol(xoptarg, 0, 0); break;
+ case 'B': numberExtrabits = atoi(xoptarg); break;
+ case 'e': checkErrors = 1; break;
+ case 'f': hashfilename = xoptarg; break;
+ case 'F': hashFilename = xoptarg; break;
+ case 'h': hashnolow = hashnohigh = findhash(argv[0], xoptarg);
+ break;
+ case 'H': strIsHex = 1; break;
+ case 'k': hmacKey = xoptarg; hmaclen = strlen(xoptarg); break;
+ case 'l': loopnohigh = atoi(xoptarg); break;
+ case 'm': runHmacTests = 1; break;
+ case 'P': printPassFail = 0; break;
+ case 'p': printResults = PRINTNONE; break;
+ case 'R': randomcount = atoi(xoptarg); break;
+ case 'r': randomseedstr = xoptarg; break;
+
+
+
+Eastlake 3rd & Hansen Informational [Page 100]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ case 's': hashstr = xoptarg; hashlen = strlen(hashstr); break;
+ case 'S': resultstr = xoptarg; break;
+ case 't': testnolow = ntestnohigh = atoi(xoptarg) - 1; break;
+ case 'w': printResults = PRINTRAW; break;
+ case 'x': printResults = PRINTHEX; break;
+ case 'X': printPassFail = 2; break;
+ default: usage(argv[0]);
+ }
+
+ if (strIsHex) {
+ hashlen = unhexStr(hashstr);
+ unhexStr(randomseedstr);
+ hmaclen = unhexStr(hmacKey);
+ }
+ testnohigh = (ntestnohigh != 0) ? ntestnohigh:
+ runHmacTests ? (HMACTESTCOUNT-1) : (TESTCOUNT-1);
+ if ((testnolow < 0) ||
+ (testnohigh >= (runHmacTests ? HMACTESTCOUNT : TESTCOUNT)) ||
+ (hashnolow < 0) || (hashnohigh >= HASHCOUNT) ||
+ (hashstr && (testnolow == testnohigh)) ||
+ (randomcount < 0) ||
+ (resultstr && (!hashstr && !hashfilename && !hashFilename)) ||
+ ((runHmacTests || hmacKey) && randomseedstr) ||
+ (hashfilename && hashFilename))
+ usage(argv[0]);
+
+ /*
+ * Perform SHA/HMAC tests
+ */
+ for (hashno = hashnolow; hashno <= hashnohigh; ++hashno) {
+ if (printResults == PRINTTEXT)
+ printf("Hash %s\n", hashes[hashno].name);
+ err = shaSuccess;
+
+ for (loopno = 1; (loopno <= loopnohigh) && (err == shaSuccess);
+ ++loopno) {
+ if (hashstr)
+ err = hash(0, loopno, hashno, hashstr, hashlen, 1,
+ numberExtrabits, extrabits, (const unsigned char *)hmacKey,
+ hmaclen, resultstr, hashes[hashno].hashsize, printResults,
+ printPassFail);
+
+ else if (randomseedstr)
+ randomtest(hashno, randomseedstr, hashes[hashno].hashsize, 0,
+ randomcount, printResults, printPassFail);
+
+ else if (hashfilename)
+ err = hashfile(hashno, hashfilename, extrabits,
+
+
+
+Eastlake 3rd & Hansen Informational [Page 101]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ numberExtrabits, 0,
+ (const unsigned char *)hmacKey, hmaclen,
+ resultstr, hashes[hashno].hashsize,
+ printResults, printPassFail);
+
+ else if (hashFilename)
+ err = hashfile(hashno, hashFilename, extrabits,
+ numberExtrabits, 1,
+ (const unsigned char *)hmacKey, hmaclen,
+ resultstr, hashes[hashno].hashsize,
+ printResults, printPassFail);
+
+ else /* standard tests */ {
+ for (testno = testnolow;
+ (testno <= testnohigh) && (err == shaSuccess); ++testno) {
+ if (runHmacTests) {
+ err = hash(testno, loopno, hashno,
+ hmachashes[testno].dataarray[hashno] ?
+ hmachashes[testno].dataarray[hashno] :
+ hmachashes[testno].dataarray[1] ?
+ hmachashes[testno].dataarray[1] :
+ hmachashes[testno].dataarray[0],
+ hmachashes[testno].datalength[hashno] ?
+ hmachashes[testno].datalength[hashno] :
+ hmachashes[testno].datalength[1] ?
+ hmachashes[testno].datalength[1] :
+ hmachashes[testno].datalength[0],
+ 1, 0, 0,
+ (const unsigned char *)(
+ hmachashes[testno].keyarray[hashno] ?
+ hmachashes[testno].keyarray[hashno] :
+ hmachashes[testno].keyarray[1] ?
+ hmachashes[testno].keyarray[1] :
+ hmachashes[testno].keyarray[0]),
+ hmachashes[testno].keylength[hashno] ?
+ hmachashes[testno].keylength[hashno] :
+ hmachashes[testno].keylength[1] ?
+ hmachashes[testno].keylength[1] :
+ hmachashes[testno].keylength[0],
+ hmachashes[testno].resultarray[hashno],
+ hmachashes[testno].resultlength[hashno],
+ printResults, printPassFail);
+ } else {
+ err = hash(testno, loopno, hashno,
+ hashes[hashno].tests[testno].testarray,
+ hashes[hashno].tests[testno].length,
+ hashes[hashno].tests[testno].repeatcount,
+ hashes[hashno].tests[testno].numberExtrabits,
+
+
+
+Eastlake 3rd & Hansen Informational [Page 102]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ hashes[hashno].tests[testno].extrabits, 0, 0,
+ hashes[hashno].tests[testno].resultarray,
+ hashes[hashno].hashsize,
+ printResults, printPassFail);
+ }
+ }
+
+ if (!runHmacTests) {
+ randomtest(hashno, hashes[hashno].randomtest,
+ hashes[hashno].hashsize, hashes[hashno].randomresults,
+ RANDOMCOUNT, printResults, printPassFail);
+ }
+ }
+ }
+ }
+
+ /* Test some error returns */
+ if (checkErrors) {
+ testErrors(hashnolow, hashnohigh, printResults, printPassFail);
+ }
+
+ return 0;
+}
+
+/*
+ * Compare two strings, case independently.
+ * Equivalent to strcasecmp() found on some systems.
+ */
+int scasecmp(const char *s1, const char *s2)
+{
+ for (;;) {
+ char u1 = tolower(*s1++);
+ char u2 = tolower(*s2++);
+ if (u1 != u2)
+ return u1 - u2;
+ if (u1 == '\0')
+ return 0;
+ }
+}
+
+/*
+ * This is a copy of getopt provided for those systems that do not
+ * have it. The name was changed to xgetopt to not conflict on those
+ * systems that do have it. Similarly, optarg, optind and opterr
+ * were renamed to xoptarg, xoptind and xopterr.
+ *
+ * Copyright 1990, 1991, 1992 by the Massachusetts Institute of
+ * Technology and UniSoft Group Limited.
+
+
+
+Eastlake 3rd & Hansen Informational [Page 103]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the names of MIT and UniSoft not
+ * be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission. MIT and
+ * UniSoft make no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * $XConsortium: getopt.c,v 1.2 92/07/01 11:59:04 rws Exp $
+ * NB: Reformatted to match above style.
+ */
+
+char *xoptarg;
+int xoptind = 1;
+int xopterr = 1;
+
+static int xgetopt(int argc, char **argv, const char *optstring)
+{
+ static int avplace;
+ char *ap;
+ char *cp;
+ int c;
+
+ if (xoptind >= argc)
+ return EOF;
+
+ ap = argv[xoptind] + avplace;
+
+ /* At beginning of arg but not an option */
+ if (avplace == 0) {
+ if (ap[0] != '-')
+ return EOF;
+ else if (ap[1] == '-') {
+ /* Special end of options option */
+ xoptind++;
+ return EOF;
+ } else if (ap[1] == '\0')
+ return EOF; /* single '-' is not allowed */
+ }
+
+ /* Get next letter */
+ avplace++;
+ c = *++ap;
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 104]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+ cp = strchr(optstring, c);
+ if (cp == NULL || c == ':') {
+ if (xopterr)
+ fprintf(stderr, "Unrecognised option -- %c\n", c);
+ return '?';
+ }
+
+ if (cp[1] == ':') {
+ /* There should be an option arg */
+ avplace = 0;
+ if (ap[1] == '\0') {
+ /* It is a separate arg */
+ if (++xoptind >= argc) {
+ if (xopterr)
+ fprintf(stderr, "Option requires an argument\n");
+ return '?';
+ }
+ xoptarg = argv[xoptind++];
+ } else {
+ /* is attached to option letter */
+ xoptarg = ap + 1;
+ ++xoptind;
+ }
+ } else {
+ /* If we are out of letters then go to next arg */
+ if (ap[1] == '\0') {
+ ++xoptind;
+ avplace = 0;
+ }
+
+ xoptarg = NULL;
+ }
+ return c;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 105]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+9. Security Considerations
+
+ This document is intended to provides the Internet community
+ convenient access to source code that implements the United States of
+ America Federal Information Processing Standard Secure Hash
+ Algorithms (SHAs) [FIPS180-2] and HMACs based upon these one-way hash
+ functions. See license in Section 1.1. No independent assertion of
+ the security of this hash function by the authors for any particular
+ use is intended.
+
+10. Normative References
+
+ [FIPS180-2] "Secure Hash Standard", United States of America,
+ National Institute of Standards and Technology, Federal
+ Information Processing Standard (FIPS) 180-2,
+ http://csrc.nist.gov/publications/fips/fips180-2/
+ fips180-2withchangenotice.pdf.
+
+ [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
+ Hashing for Message Authentication", RFC 2104, February
+ 1997.
+
+11. Informative References
+
+ [RFC2202] Cheng, P. and R. Glenn, "Test Cases for HMAC-MD5 and
+ HMAC-SHA-1", RFC 2202, September 1997.
+
+ [RFC3174] Eastlake 3rd, D. and P. Jones, "US Secure Hash Algorithm
+ 1 (SHA1)", RFC 3174, September 2001.
+
+ [RFC3874] Housley, R., "A 224-bit One-way Hash Function: SHA-224",
+ RFC 3874, September 2004.
+
+ [RFC4086] Eastlake, D., 3rd, Schiller, J., and S. Crocker,
+ "Randomness Requirements for Security", BCP 106, RFC
+ 4086, June 2005.
+
+ [RFC4231] Nystrom, M., "Identifiers and Test Vectors for HMAC-SHA-
+ 224, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512", RFC
+ 4231, December 2005.
+
+ [SHAVS] "The Secure Hash Algorithm Validation System (SHAVS)",
+ http://csrc.nist.gov/cryptval/shs/SHAVS.pdf.
+
+
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 106]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+Authors' Addresses
+
+ Donald E. Eastlake, 3rd
+ Motorola Laboratories
+ 155 Beaver Street
+ Milford, MA 01757 USA
+
+ Phone: +1-508-786-7554 (w)
+ EMail: donald.eastlake@motorola.com
+
+
+ Tony Hansen
+ AT&T Laboratories
+ 200 Laurel Ave.
+ Middletown, NJ 07748 USA
+
+ Phone: +1-732-420-8934 (w)
+ EMail: tony+shs@maillennium.att.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 107]
+
+RFC 4634 SHAs and HMAC-SHAs July 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Eastlake 3rd & Hansen Informational [Page 108]
+
diff --git a/doc/rfc/rfc4641.txt b/doc/rfc/rfc4641.txt
new file mode 100644
index 0000000..0a013bc
--- /dev/null
+++ b/doc/rfc/rfc4641.txt
@@ -0,0 +1,1963 @@
+
+
+
+
+
+
+Network Working Group O. Kolkman
+Request for Comments: 4641 R. Gieben
+Obsoletes: 2541 NLnet Labs
+Category: Informational September 2006
+
+
+ DNSSEC Operational Practices
+
+Status of This Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ This document describes a set of practices for operating the DNS with
+ security extensions (DNSSEC). The target audience is zone
+ administrators deploying DNSSEC.
+
+ The document discusses operational aspects of using keys and
+ signatures in the DNS. It discusses issues of key generation, key
+ storage, signature generation, key rollover, and related policies.
+
+ This document obsoletes RFC 2541, as it covers more operational
+ ground and gives more up-to-date requirements with respect to key
+ sizes and the new DNSSEC specification.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 1]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+Table of Contents
+
+ 1. Introduction ....................................................3
+ 1.1. The Use of the Term 'key' ..................................4
+ 1.2. Time Definitions ...........................................4
+ 2. Keeping the Chain of Trust Intact ...............................5
+ 3. Keys Generation and Storage .....................................6
+ 3.1. Zone and Key Signing Keys ..................................6
+ 3.1.1. Motivations for the KSK and ZSK Separation ..........6
+ 3.1.2. KSKs for High-Level Zones ...........................7
+ 3.2. Key Generation .............................................8
+ 3.3. Key Effectivity Period .....................................8
+ 3.4. Key Algorithm ..............................................9
+ 3.5. Key Sizes ..................................................9
+ 3.6. Private Key Storage .......................................11
+ 4. Signature Generation, Key Rollover, and Related Policies .......12
+ 4.1. Time in DNSSEC ............................................12
+ 4.1.1. Time Considerations ................................12
+ 4.2. Key Rollovers .............................................14
+ 4.2.1. Zone Signing Key Rollovers .........................14
+ 4.2.1.1. Pre-Publish Key Rollover ..................15
+ 4.2.1.2. Double Signature Zone Signing Key
+ Rollover ..................................17
+ 4.2.1.3. Pros and Cons of the Schemes ..............18
+ 4.2.2. Key Signing Key Rollovers ..........................18
+ 4.2.3. Difference Between ZSK and KSK Rollovers ...........20
+ 4.2.4. Automated Key Rollovers ............................21
+ 4.3. Planning for Emergency Key Rollover .......................21
+ 4.3.1. KSK Compromise .....................................22
+ 4.3.1.1. Keeping the Chain of Trust Intact .........22
+ 4.3.1.2. Breaking the Chain of Trust ...............23
+ 4.3.2. ZSK Compromise .....................................23
+ 4.3.3. Compromises of Keys Anchored in Resolvers ..........24
+ 4.4. Parental Policies .........................................24
+ 4.4.1. Initial Key Exchanges and Parental Policies
+ Considerations .....................................24
+ 4.4.2. Storing Keys or Hashes? ............................25
+ 4.4.3. Security Lameness ..................................25
+ 4.4.4. DS Signature Validity Period .......................26
+ 5. Security Considerations ........................................26
+ 6. Acknowledgments ................................................26
+ 7. References .....................................................27
+ 7.1. Normative References ......................................27
+ 7.2. Informative References ....................................28
+ Appendix A. Terminology ...........................................30
+ Appendix B. Zone Signing Key Rollover How-To ......................31
+ Appendix C. Typographic Conventions ...............................32
+
+
+
+
+Kolkman & Gieben Informational [Page 2]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+1. Introduction
+
+ This document describes how to run a DNS Security (DNSSEC)-enabled
+ environment. It is intended for operators who have knowledge of the
+ DNS (see RFC 1034 [1] and RFC 1035 [2]) and want to deploy DNSSEC.
+ See RFC 4033 [4] for an introduction to DNSSEC, RFC 4034 [5] for the
+ newly introduced Resource Records (RRs), and RFC 4035 [6] for the
+ protocol changes.
+
+ During workshops and early operational deployment tests, operators
+ and system administrators have gained experience about operating the
+ DNS with security extensions (DNSSEC). This document translates
+ these experiences into a set of practices for zone administrators.
+ At the time of writing, there exists very little experience with
+ DNSSEC in production environments; this document should therefore
+ explicitly not be seen as representing 'Best Current Practices'.
+
+ The procedures herein are focused on the maintenance of signed zones
+ (i.e., signing and publishing zones on authoritative servers). It is
+ intended that maintenance of zones such as re-signing or key
+ rollovers be transparent to any verifying clients on the Internet.
+
+ The structure of this document is as follows. In Section 2, we
+ discuss the importance of keeping the "chain of trust" intact.
+ Aspects of key generation and storage of private keys are discussed
+ in Section 3; the focus in this section is mainly on the private part
+ of the key(s). Section 4 describes considerations concerning the
+ public part of the keys. Since these public keys appear in the DNS
+ one has to take into account all kinds of timing issues, which are
+ discussed in Section 4.1. Section 4.2 and Section 4.3 deal with the
+ rollover, or supercession, of keys. Finally, Section 4.4 discusses
+ considerations on how parents deal with their children's public keys
+ in order to maintain chains of trust.
+
+ The typographic conventions used in this document are explained in
+ Appendix C.
+
+ Since this is a document with operational suggestions and there are
+ no protocol specifications, the RFC 2119 [7] language does not apply.
+
+ This document obsoletes RFC 2541 [12] to reflect the evolution of the
+ underlying DNSSEC protocol since then. Changes in the choice of
+ cryptographic algorithms, DNS record types and type names, and the
+ parent-child key and signature exchange demanded a major rewrite and
+ additional information and explanation.
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 3]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+1.1. The Use of the Term 'key'
+
+ It is assumed that the reader is familiar with the concept of
+ asymmetric keys on which DNSSEC is based (public key cryptography
+ [17]). Therefore, this document will use the term 'key' rather
+ loosely. Where it is written that 'a key is used to sign data' it is
+ assumed that the reader understands that it is the private part of
+ the key pair that is used for signing. It is also assumed that the
+ reader understands that the public part of the key pair is published
+ in the DNSKEY Resource Record and that it is the public part that is
+ used in key exchanges.
+
+1.2. Time Definitions
+
+ In this document, we will be using a number of time-related terms.
+ The following definitions apply:
+
+ o "Signature validity period" The period that a signature is valid.
+ It starts at the time specified in the signature inception field
+ of the RRSIG RR and ends at the time specified in the expiration
+ field of the RRSIG RR.
+
+ o "Signature publication period" Time after which a signature (made
+ with a specific key) is replaced with a new signature (made with
+ the same key). This replacement takes place by publishing the
+ relevant RRSIG in the master zone file. After one stops
+ publishing an RRSIG in a zone, it may take a while before the
+ RRSIG has expired from caches and has actually been removed from
+ the DNS.
+
+ o "Key effectivity period" The period during which a key pair is
+ expected to be effective. This period is defined as the time
+ between the first inception time stamp and the last expiration
+ date of any signature made with this key, regardless of any
+ discontinuity in the use of the key. The key effectivity period
+ can span multiple signature validity periods.
+
+ o "Maximum/Minimum Zone Time to Live (TTL)" The maximum or minimum
+ value of the TTLs from the complete set of RRs in a zone. Note
+ that the minimum TTL is not the same as the MINIMUM field in the
+ SOA RR. See [11] for more information.
+
+
+
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 4]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+2. Keeping the Chain of Trust Intact
+
+ Maintaining a valid chain of trust is important because broken chains
+ of trust will result in data being marked as Bogus (as defined in [4]
+ Section 5), which may cause entire (sub)domains to become invisible
+ to verifying clients. The administrators of secured zones have to
+ realize that their zone is, to verifying clients, part of a chain of
+ trust.
+
+ As mentioned in the introduction, the procedures herein are intended
+ to ensure that maintenance of zones, such as re-signing or key
+ rollovers, will be transparent to the verifying clients on the
+ Internet.
+
+ Administrators of secured zones will have to keep in mind that data
+ published on an authoritative primary server will not be immediately
+ seen by verifying clients; it may take some time for the data to be
+ transferred to other secondary authoritative nameservers and clients
+ may be fetching data from caching non-authoritative servers. In this
+ light, note that the time for a zone transfer from master to slave is
+ negligible when using NOTIFY [9] and incremental transfer (IXFR) [8].
+ It increases when full zone transfers (AXFR) are used in combination
+ with NOTIFY. It increases even more if you rely on full zone
+ transfers based on only the SOA timing parameters for refresh.
+
+ For the verifying clients, it is important that data from secured
+ zones can be used to build chains of trust regardless of whether the
+ data came directly from an authoritative server, a caching
+ nameserver, or some middle box. Only by carefully using the
+ available timing parameters can a zone administrator ensure that the
+ data necessary for verification can be obtained.
+
+ The responsibility for maintaining the chain of trust is shared by
+ administrators of secured zones in the chain of trust. This is most
+ obvious in the case of a 'key compromise' when a trade-off between
+ maintaining a valid chain of trust and replacing the compromised keys
+ as soon as possible must be made. Then zone administrators will have
+ to make a trade-off, between keeping the chain of trust intact --
+ thereby allowing for attacks with the compromised key -- or
+ deliberately breaking the chain of trust and making secured
+ subdomains invisible to security-aware resolvers. Also see Section
+ 4.3.
+
+
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 5]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+3. Keys Generation and Storage
+
+ This section describes a number of considerations with respect to the
+ security of keys. It deals with the generation, effectivity period,
+ size, and storage of private keys.
+
+3.1. Zone and Key Signing Keys
+
+ The DNSSEC validation protocol does not distinguish between different
+ types of DNSKEYs. All DNSKEYs can be used during the validation. In
+ practice, operators use Key Signing and Zone Signing Keys and use the
+ so-called Secure Entry Point (SEP) [3] flag to distinguish between
+ them during operations. The dynamics and considerations are
+ discussed below.
+
+ To make zone re-signing and key rollover procedures easier to
+ implement, it is possible to use one or more keys as Key Signing Keys
+ (KSKs). These keys will only sign the apex DNSKEY RRSet in a zone.
+ Other keys can be used to sign all the RRSets in a zone and are
+ referred to as Zone Signing Keys (ZSKs). In this document, we assume
+ that KSKs are the subset of keys that are used for key exchanges with
+ the parent and potentially for configuration as trusted anchors --
+ the SEP keys. In this document, we assume a one-to-one mapping
+ between KSK and SEP keys and we assume the SEP flag to be set on all
+ KSKs.
+
+3.1.1. Motivations for the KSK and ZSK Separation
+
+ Differentiating between the KSK and ZSK functions has several
+ advantages:
+
+ o No parent/child interaction is required when ZSKs are updated.
+
+ o The KSK can be made stronger (i.e., using more bits in the key
+ material). This has little operational impact since it is only
+ used to sign a small fraction of the zone data. Also, the KSK is
+ only used to verify the zone's key set, not for other RRSets in
+ the zone.
+
+ o As the KSK is only used to sign a key set, which is most probably
+ updated less frequently than other data in the zone, it can be
+ stored separately from and in a safer location than the ZSK.
+
+ o A KSK can have a longer key effectivity period.
+
+ For almost any method of key management and zone signing, the KSK is
+ used less frequently than the ZSK. Once a key set is signed with the
+ KSK, all the keys in the key set can be used as ZSKs. If a ZSK is
+
+
+
+Kolkman & Gieben Informational [Page 6]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ compromised, it can be simply dropped from the key set. The new key
+ set is then re-signed with the KSK.
+
+ Given the assumption that for KSKs the SEP flag is set, the KSK can
+ be distinguished from a ZSK by examining the flag field in the DNSKEY
+ RR. If the flag field is an odd number it is a KSK. If it is an
+ even number it is a ZSK.
+
+ The Zone Signing Key can be used to sign all the data in a zone on a
+ regular basis. When a Zone Signing Key is to be rolled, no
+ interaction with the parent is needed. This allows for signature
+ validity periods on the order of days.
+
+ The Key Signing Key is only to be used to sign the DNSKEY RRs in a
+ zone. If a Key Signing Key is to be rolled over, there will be
+ interactions with parties other than the zone administrator. These
+ can include the registry of the parent zone or administrators of
+ verifying resolvers that have the particular key configured as secure
+ entry points. Hence, the key effectivity period of these keys can
+ and should be made much longer. Although, given a long enough key,
+ the key effectivity period can be on the order of years, we suggest
+ planning for a key effectivity on the order of a few months so that a
+ key rollover remains an operational routine.
+
+3.1.2. KSKs for High-Level Zones
+
+ Higher-level zones are generally more sensitive than lower-level
+ zones. Anyone controlling or breaking the security of a zone thereby
+ obtains authority over all of its subdomains (except in the case of
+ resolvers that have locally configured the public key of a subdomain,
+ in which case this, and only this, subdomain wouldn't be affected by
+ the compromise of the parent zone). Therefore, extra care should be
+ taken with high-level zones, and strong keys should be used.
+
+ The root zone is the most critical of all zones. Someone controlling
+ or compromising the security of the root zone would control the
+ entire DNS namespace of all resolvers using that root zone (except in
+ the case of resolvers that have locally configured the public key of
+ a subdomain). Therefore, the utmost care must be taken in the
+ securing of the root zone. The strongest and most carefully handled
+ keys should be used. The root zone private key should always be kept
+ off-line.
+
+ Many resolvers will start at a root server for their access to and
+ authentication of DNS data. Securely updating the trust anchors in
+ an enormous population of resolvers around the world will be
+ extremely difficult.
+
+
+
+
+Kolkman & Gieben Informational [Page 7]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+3.2. Key Generation
+
+ Careful generation of all keys is a sometimes overlooked but
+ absolutely essential element in any cryptographically secure system.
+ The strongest algorithms used with the longest keys are still of no
+ use if an adversary can guess enough to lower the size of the likely
+ key space so that it can be exhaustively searched. Technical
+ suggestions for the generation of random keys will be found in RFC
+ 4086 [14]. One should carefully assess if the random number
+ generator used during key generation adheres to these suggestions.
+
+ Keys with a long effectivity period are particularly sensitive as
+ they will represent a more valuable target and be subject to attack
+ for a longer time than short-period keys. It is strongly recommended
+ that long-term key generation occur off-line in a manner isolated
+ from the network via an air gap or, at a minimum, high-level secure
+ hardware.
+
+3.3. Key Effectivity Period
+
+ For various reasons, keys in DNSSEC need to be changed once in a
+ while. The longer a key is in use, the greater the probability that
+ it will have been compromised through carelessness, accident,
+ espionage, or cryptanalysis. Furthermore, when key rollovers are too
+ rare an event, they will not become part of the operational habit and
+ there is risk that nobody on-site will remember the procedure for
+ rollover when the need is there.
+
+ From a purely operational perspective, a reasonable key effectivity
+ period for Key Signing Keys is 13 months, with the intent to replace
+ them after 12 months. An intended key effectivity period of a month
+ is reasonable for Zone Signing Keys.
+
+ For key sizes that match these effectivity periods, see Section 3.5.
+
+ As argued in Section 3.1.2, securely updating trust anchors will be
+ extremely difficult. On the other hand, the "operational habit"
+ argument does also apply to trust anchor reconfiguration. If a short
+ key effectivity period is used and the trust anchor configuration has
+ to be revisited on a regular basis, the odds that the configuration
+ tends to be forgotten is smaller. The trade-off is against a system
+ that is so dynamic that administrators of the validating clients will
+ not be able to follow the modifications.
+
+ Key effectivity periods can be made very short, as in a few minutes.
+ But when replacing keys one has to take the considerations from
+ Section 4.1 and Section 4.2 into account.
+
+
+
+
+Kolkman & Gieben Informational [Page 8]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+3.4. Key Algorithm
+
+ There are currently three different types of algorithms that can be
+ used in DNSSEC: RSA, DSA, and elliptic curve cryptography. The
+ latter is fairly new and has yet to be standardized for usage in
+ DNSSEC.
+
+ RSA has been developed in an open and transparent manner. As the
+ patent on RSA expired in 2000, its use is now also free.
+
+ DSA has been developed by the National Institute of Standards and
+ Technology (NIST). The creation of signatures takes roughly the same
+ time as with RSA, but is 10 to 40 times as slow for verification
+ [17].
+
+ We suggest the use of RSA/SHA-1 as the preferred algorithm for the
+ key. The current known attacks on RSA can be defeated by making your
+ key longer. As the MD5 hashing algorithm is showing cracks, we
+ recommend the usage of SHA-1.
+
+ At the time of publication, it is known that the SHA-1 hash has
+ cryptanalysis issues. There is work in progress on addressing these
+ issues. We recommend the use of public key algorithms based on
+ hashes stronger than SHA-1 (e.g., SHA-256), as soon as these
+ algorithms are available in protocol specifications (see [19] and
+ [20]) and implementations.
+
+3.5. Key Sizes
+
+ When choosing key sizes, zone administrators will need to take into
+ account how long a key will be used, how much data will be signed
+ during the key publication period (see Section 8.10 of [17]), and,
+ optionally, how large the key size of the parent is. As the chain of
+ trust really is "a chain", there is not much sense in making one of
+ the keys in the chain several times larger then the others. As
+ always, it's the weakest link that defines the strength of the entire
+ chain. Also see Section 3.1.1 for a discussion of how keys serving
+ different roles (ZSK vs. KSK) may need different key sizes.
+
+ Generating a key of the correct size is a difficult problem; RFC 3766
+ [13] tries to deal with that problem. The first part of the
+ selection procedure in Section 1 of the RFC states:
+
+ 1. Determine the attack resistance necessary to satisfy the
+ security requirements of the application. Do this by
+ estimating the minimum number of computer operations that the
+ attacker will be forced to do in order to compromise the
+
+
+
+
+Kolkman & Gieben Informational [Page 9]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ security of the system and then take the logarithm base two of
+ that number. Call that logarithm value "n".
+
+ A 1996 report recommended 90 bits as a good all-around choice
+ for system security. The 90 bit number should be increased by
+ about 2/3 bit/year, or about 96 bits in 2005.
+
+ [13] goes on to explain how this number "n" can be used to calculate
+ the key sizes in public key cryptography. This culminated in the
+ table given below (slightly modified for our purpose):
+
+ +-------------+-----------+--------------+
+ | System | | |
+ | requirement | Symmetric | RSA or DSA |
+ | for attack | key size | modulus size |
+ | resistance | (bits) | (bits) |
+ | (bits) | | |
+ +-------------+-----------+--------------+
+ | 70 | 70 | 947 |
+ | 80 | 80 | 1228 |
+ | 90 | 90 | 1553 |
+ | 100 | 100 | 1926 |
+ | 150 | 150 | 4575 |
+ | 200 | 200 | 8719 |
+ | 250 | 250 | 14596 |
+ +-------------+-----------+--------------+
+
+ The key sizes given are rather large. This is because these keys are
+ resilient against a trillionaire attacker. Assuming this rich
+ attacker will not attack your key and that the key is rolled over
+ once a year, we come to the following recommendations about KSK
+ sizes: 1024 bits for low-value domains, 1300 bits for medium-value
+ domains, and 2048 bits for high-value domains.
+
+ Whether a domain is of low, medium, or high value depends solely on
+ the views of the zone owner. One could, for instance, view leaf
+ nodes in the DNS as of low value, and top-level domains (TLDs) or the
+ root zone of high value. The suggested key sizes should be safe for
+ the next 5 years.
+
+ As ZSKs can be rolled over more easily (and thus more often), the key
+ sizes can be made smaller. But as said in the introduction of this
+ paragraph, making the ZSKs' key sizes too small (in relation to the
+ KSKs' sizes) doesn't make much sense. Try to limit the difference in
+ size to about 100 bits.
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 10]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ Note that nobody can see into the future and that these key sizes are
+ only provided here as a guide. Further information can be found in
+ [16] and Section 7.5 of [17]. It should be noted though that [16] is
+ already considered overly optimistic about what key sizes are
+ considered safe.
+
+ One final note concerning key sizes. Larger keys will increase the
+ sizes of the RRSIG and DNSKEY records and will therefore increase the
+ chance of DNS UDP packet overflow. Also, the time it takes to
+ validate and create RRSIGs increases with larger keys, so don't
+ needlessly double your key sizes.
+
+3.6. Private Key Storage
+
+ It is recommended that, where possible, zone private keys and the
+ zone file master copy that is to be signed be kept and used in off-
+ line, non-network-connected, physically secure machines only.
+ Periodically, an application can be run to add authentication to a
+ zone by adding RRSIG and NSEC RRs. Then the augmented file can be
+ transferred.
+
+ When relying on dynamic update to manage a signed zone [10], be aware
+ that at least one private key of the zone will have to reside on the
+ master server. This key is only as secure as the amount of exposure
+ the server receives to unknown clients and the security of the host.
+ Although not mandatory, one could administer the DNS in the following
+ way. The master that processes the dynamic updates is unavailable
+ from generic hosts on the Internet, it is not listed in the NS RR
+ set, although its name appears in the SOA RRs MNAME field. The
+ nameservers in the NS RRSet are able to receive zone updates through
+ NOTIFY, IXFR, AXFR, or an out-of-band distribution mechanism. This
+ approach is known as the "hidden master" setup.
+
+ The ideal situation is to have a one-way information flow to the
+ network to avoid the possibility of tampering from the network.
+ Keeping the zone master file on-line on the network and simply
+ cycling it through an off-line signer does not do this. The on-line
+ version could still be tampered with if the host it resides on is
+ compromised. For maximum security, the master copy of the zone file
+ should be off-net and should not be updated based on an unsecured
+ network mediated communication.
+
+ In general, keeping a zone file off-line will not be practical and
+ the machines on which zone files are maintained will be connected to
+ a network. Operators are advised to take security measures to shield
+ unauthorized access to the master copy.
+
+
+
+
+
+Kolkman & Gieben Informational [Page 11]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ For dynamically updated secured zones [10], both the master copy and
+ the private key that is used to update signatures on updated RRs will
+ need to be on-line.
+
+4. Signature Generation, Key Rollover, and Related Policies
+
+4.1. Time in DNSSEC
+
+ Without DNSSEC, all times in the DNS are relative. The SOA fields
+ REFRESH, RETRY, and EXPIRATION are timers used to determine the time
+ elapsed after a slave server synchronized with a master server. The
+ Time to Live (TTL) value and the SOA RR minimum TTL parameter [11]
+ are used to determine how long a forwarder should cache data after it
+ has been fetched from an authoritative server. By using a signature
+ validity period, DNSSEC introduces the notion of an absolute time in
+ the DNS. Signatures in DNSSEC have an expiration date after which
+ the signature is marked as invalid and the signed data is to be
+ considered Bogus.
+
+4.1.1. Time Considerations
+
+ Because of the expiration of signatures, one should consider the
+ following:
+
+ o We suggest the Maximum Zone TTL of your zone data to be a fraction
+ of your signature validity period.
+
+ If the TTL would be of similar order as the signature validity
+ period, then all RRSets fetched during the validity period
+ would be cached until the signature expiration time. Section
+ 7.1 of [4] suggests that "the resolver may use the time
+ remaining before expiration of the signature validity period of
+ a signed RRSet as an upper bound for the TTL". As a result,
+ query load on authoritative servers would peak at signature
+ expiration time, as this is also the time at which records
+ simultaneously expire from caches.
+
+ To avoid query load peaks, we suggest the TTL on all the RRs in
+ your zone to be at least a few times smaller than your
+ signature validity period.
+
+ o We suggest the signature publication period to end at least one
+ Maximum Zone TTL duration before the end of the signature validity
+ period.
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 12]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ Re-signing a zone shortly before the end of the signature
+ validity period may cause simultaneous expiration of data from
+ caches. This in turn may lead to peaks in the load on
+ authoritative servers.
+
+ o We suggest the Minimum Zone TTL to be long enough to both fetch
+ and verify all the RRs in the trust chain. In workshop
+ environments, it has been demonstrated [18] that a low TTL (under
+ 5 to 10 minutes) caused disruptions because of the following two
+ problems:
+
+ 1. During validation, some data may expire before the
+ validation is complete. The validator should be able to
+ keep all data until it is completed. This applies to all
+ RRs needed to complete the chain of trust: DSes, DNSKEYs,
+ RRSIGs, and the final answers, i.e., the RRSet that is
+ returned for the initial query.
+
+ 2. Frequent verification causes load on recursive nameservers.
+ Data at delegation points, DSes, DNSKEYs, and RRSIGs
+ benefit from caching. The TTL on those should be
+ relatively long.
+
+ o Slave servers will need to be able to fetch newly signed zones
+ well before the RRSIGs in the zone served by the slave server pass
+ their signature expiration time.
+
+ When a slave server is out of sync with its master and data in
+ a zone is signed by expired signatures, it may be better for
+ the slave server not to give out any answer.
+
+ Normally, a slave server that is not able to contact a master
+ server for an extended period will expire a zone. When that
+ happens, the server will respond differently to queries for
+ that zone. Some servers issue SERVFAIL, whereas others turn
+ off the 'AA' bit in the answers. The time of expiration is set
+ in the SOA record and is relative to the last successful
+ refresh between the master and the slave servers. There exists
+ no coupling between the signature expiration of RRSIGs in the
+ zone and the expire parameter in the SOA.
+
+ If the server serves a DNSSEC zone, then it may well happen
+ that the signatures expire well before the SOA expiration timer
+ counts down to zero. It is not possible to completely prevent
+ this from happening by tweaking the SOA parameters. However,
+ the effects can be minimized where the SOA expiration time is
+ equal to or shorter than the signature validity period. The
+ consequence of an authoritative server not being able to update
+
+
+
+Kolkman & Gieben Informational [Page 13]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ a zone, whilst that zone includes expired signatures, is that
+ non-secure resolvers will continue to be able to resolve data
+ served by the particular slave servers while security-aware
+ resolvers will experience problems because of answers being
+ marked as Bogus.
+
+ We suggest the SOA expiration timer being approximately one
+ third or one fourth of the signature validity period. It will
+ allow problems with transfers from the master server to be
+ noticed before the actual signature times out. We also suggest
+ that operators of nameservers that supply secondary services
+ develop 'watch dogs' to spot upcoming signature expirations in
+ zones they slave, and take appropriate action.
+
+ When determining the value for the expiration parameter one has
+ to take the following into account: What are the chances that
+ all my secondaries expire the zone? How quickly can I reach an
+ administrator of secondary servers to load a valid zone? These
+ questions are not DNSSEC specific but may influence the choice
+ of your signature validity intervals.
+
+4.2. Key Rollovers
+
+ A DNSSEC key cannot be used forever (see Section 3.3). So key
+ rollovers -- or supercessions, as they are sometimes called -- are a
+ fact of life when using DNSSEC. Zone administrators who are in the
+ process of rolling their keys have to take into account that data
+ published in previous versions of their zone still lives in caches.
+ When deploying DNSSEC, this becomes an important consideration;
+ ignoring data that may be in caches may lead to loss of service for
+ clients.
+
+ The most pressing example of this occurs when zone material signed
+ with an old key is being validated by a resolver that does not have
+ the old zone key cached. If the old key is no longer present in the
+ current zone, this validation fails, marking the data "Bogus".
+ Alternatively, an attempt could be made to validate data that is
+ signed with a new key against an old key that lives in a local cache,
+ also resulting in data being marked "Bogus".
+
+4.2.1. Zone Signing Key Rollovers
+
+ For "Zone Signing Key rollovers", there are two ways to make sure
+ that during the rollover data still cached can be verified with the
+ new key sets or newly generated signatures can be verified with the
+ keys still in caches. One schema, described in Section 4.2.1.2, uses
+
+
+
+
+
+Kolkman & Gieben Informational [Page 14]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ double signatures; the other uses key pre-publication (Section
+ 4.2.1.1). The pros, cons, and recommendations are described in
+ Section 4.2.1.3.
+
+4.2.1.1. Pre-Publish Key Rollover
+
+ This section shows how to perform a ZSK rollover without the need to
+ sign all the data in a zone twice -- the "pre-publish key rollover".
+ This method has advantages in the case of a key compromise. If the
+ old key is compromised, the new key has already been distributed in
+ the DNS. The zone administrator is then able to quickly switch to
+ the new key and remove the compromised key from the zone. Another
+ major advantage is that the zone size does not double, as is the case
+ with the double signature ZSK rollover. A small "how-to" for this
+ kind of rollover can be found in Appendix B.
+
+ Pre-publish key rollover involves four stages as follows:
+
+ ----------------------------------------------------------------
+ initial new DNSKEY new RRSIGs DNSKEY removal
+ ----------------------------------------------------------------
+ SOA0 SOA1 SOA2 SOA3
+ RRSIG10(SOA0) RRSIG10(SOA1) RRSIG11(SOA2) RRSIG11(SOA3)
+
+ DNSKEY1 DNSKEY1 DNSKEY1 DNSKEY1
+ DNSKEY10 DNSKEY10 DNSKEY10 DNSKEY11
+ DNSKEY11 DNSKEY11
+ RRSIG1 (DNSKEY) RRSIG1 (DNSKEY) RRSIG1(DNSKEY) RRSIG1 (DNSKEY)
+ RRSIG10(DNSKEY) RRSIG10(DNSKEY) RRSIG11(DNSKEY) RRSIG11(DNSKEY)
+ ----------------------------------------------------------------
+
+ Pre-Publish Key Rollover
+
+ initial: Initial version of the zone: DNSKEY 1 is the Key Signing
+ Key. DNSKEY 10 is used to sign all the data of the zone, the Zone
+ Signing Key.
+
+ new DNSKEY: DNSKEY 11 is introduced into the key set. Note that no
+ signatures are generated with this key yet, but this does not
+ secure against brute force attacks on the public key. The minimum
+ duration of this pre-roll phase is the time it takes for the data
+ to propagate to the authoritative servers plus TTL value of the
+ key set.
+
+ new RRSIGs: At the "new RRSIGs" stage (SOA serial 2), DNSKEY 11 is
+ used to sign the data in the zone exclusively (i.e., all the
+ signatures from DNSKEY 10 are removed from the zone). DNSKEY 10
+ remains published in the key set. This way data that was loaded
+
+
+
+Kolkman & Gieben Informational [Page 15]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ into caches from version 1 of the zone can still be verified with
+ key sets fetched from version 2 of the zone. The minimum time
+ that the key set including DNSKEY 10 is to be published is the
+ time that it takes for zone data from the previous version of the
+ zone to expire from old caches, i.e., the time it takes for this
+ zone to propagate to all authoritative servers plus the Maximum
+ Zone TTL value of any of the data in the previous version of the
+ zone.
+
+ DNSKEY removal: DNSKEY 10 is removed from the zone. The key set, now
+ only containing DNSKEY 1 and DNSKEY 11, is re-signed with the
+ DNSKEY 1.
+
+ The above scheme can be simplified by always publishing the "future"
+ key immediately after the rollover. The scheme would look as follows
+ (we show two rollovers); the future key is introduced in "new DNSKEY"
+ as DNSKEY 12 and again a newer one, numbered 13, in "new DNSKEY
+ (II)":
+
+ ----------------------------------------------------------------
+ initial new RRSIGs new DNSKEY
+ ----------------------------------------------------------------
+ SOA0 SOA1 SOA2
+ RRSIG10(SOA0) RRSIG11(SOA1) RRSIG11(SOA2)
+
+ DNSKEY1 DNSKEY1 DNSKEY1
+ DNSKEY10 DNSKEY10 DNSKEY11
+ DNSKEY11 DNSKEY11 DNSKEY12
+ RRSIG1(DNSKEY) RRSIG1 (DNSKEY) RRSIG1(DNSKEY)
+ RRSIG10(DNSKEY) RRSIG11(DNSKEY) RRSIG11(DNSKEY)
+ ----------------------------------------------------------------
+
+ ----------------------------------------------------------------
+ new RRSIGs (II) new DNSKEY (II)
+ ----------------------------------------------------------------
+ SOA3 SOA4
+ RRSIG12(SOA3) RRSIG12(SOA4)
+
+ DNSKEY1 DNSKEY1
+ DNSKEY11 DNSKEY12
+ DNSKEY12 DNSKEY13
+ RRSIG1(DNSKEY) RRSIG1(DNSKEY)
+ RRSIG12(DNSKEY) RRSIG12(DNSKEY)
+ ----------------------------------------------------------------
+
+ Pre-Publish Key Rollover, Showing Two Rollovers
+
+
+
+
+
+Kolkman & Gieben Informational [Page 16]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ Note that the key introduced in the "new DNSKEY" phase is not used
+ for production yet; the private key can thus be stored in a
+ physically secure manner and does not need to be 'fetched' every time
+ a zone needs to be signed.
+
+4.2.1.2. Double Signature Zone Signing Key Rollover
+
+ This section shows how to perform a ZSK key rollover using the double
+ zone data signature scheme, aptly named "double signature rollover".
+
+ During the "new DNSKEY" stage the new version of the zone file will
+ need to propagate to all authoritative servers and the data that
+ exists in (distant) caches will need to expire, requiring at least
+ the Maximum Zone TTL.
+
+ Double signature ZSK rollover involves three stages as follows:
+
+ ----------------------------------------------------------------
+ initial new DNSKEY DNSKEY removal
+ ----------------------------------------------------------------
+ SOA0 SOA1 SOA2
+ RRSIG10(SOA0) RRSIG10(SOA1) RRSIG11(SOA2)
+ RRSIG11(SOA1)
+
+ DNSKEY1 DNSKEY1 DNSKEY1
+ DNSKEY10 DNSKEY10 DNSKEY11
+ DNSKEY11
+ RRSIG1(DNSKEY) RRSIG1(DNSKEY) RRSIG1(DNSKEY)
+ RRSIG10(DNSKEY) RRSIG10(DNSKEY) RRSIG11(DNSKEY)
+ RRSIG11(DNSKEY)
+ ----------------------------------------------------------------
+
+ Double Signature Zone Signing Key Rollover
+
+ initial: Initial Version of the zone: DNSKEY 1 is the Key Signing
+ Key. DNSKEY 10 is used to sign all the data of the zone, the Zone
+ Signing Key.
+
+ new DNSKEY: At the "New DNSKEY" stage (SOA serial 1) DNSKEY 11 is
+ introduced into the key set and all the data in the zone is signed
+ with DNSKEY 10 and DNSKEY 11. The rollover period will need to
+ continue until all data from version 0 of the zone has expired
+ from remote caches. This will take at least the Maximum Zone TTL
+ of version 0 of the zone.
+
+ DNSKEY removal: DNSKEY 10 is removed from the zone. All the
+ signatures from DNSKEY 10 are removed from the zone. The key set,
+ now only containing DNSKEY 11, is re-signed with DNSKEY 1.
+
+
+
+Kolkman & Gieben Informational [Page 17]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ At every instance, RRSIGs from the previous version of the zone can
+ be verified with the DNSKEY RRSet from the current version and the
+ other way around. The data from the current version can be verified
+ with the data from the previous version of the zone. The duration of
+ the "new DNSKEY" phase and the period between rollovers should be at
+ least the Maximum Zone TTL.
+
+ Making sure that the "new DNSKEY" phase lasts until the signature
+ expiration time of the data in initial version of the zone is
+ recommended. This way all caches are cleared of the old signatures.
+ However, this duration could be considerably longer than the Maximum
+ Zone TTL, making the rollover a lengthy procedure.
+
+ Note that in this example we assumed that the zone was not modified
+ during the rollover. New data can be introduced in the zone as long
+ as it is signed with both keys.
+
+4.2.1.3. Pros and Cons of the Schemes
+
+ Pre-publish key rollover: This rollover does not involve signing the
+ zone data twice. Instead, before the actual rollover, the new key
+ is published in the key set and thus is available for
+ cryptanalysis attacks. A small disadvantage is that this process
+ requires four steps. Also the pre-publish scheme involves more
+ parental work when used for KSK rollovers as explained in Section
+ 4.2.3.
+
+ Double signature ZSK rollover: The drawback of this signing scheme is
+ that during the rollover the number of signatures in your zone
+ doubles; this may be prohibitive if you have very big zones. An
+ advantage is that it only requires three steps.
+
+4.2.2. Key Signing Key Rollovers
+
+ For the rollover of a Key Signing Key, the same considerations as for
+ the rollover of a Zone Signing Key apply. However, we can use a
+ double signature scheme to guarantee that old data (only the apex key
+ set) in caches can be verified with a new key set and vice versa.
+ Since only the key set is signed with a KSK, zone size considerations
+ do not apply.
+
+
+
+
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 18]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ --------------------------------------------------------------------
+ initial new DNSKEY DS change DNSKEY removal
+ --------------------------------------------------------------------
+ Parent:
+ SOA0 --------> SOA1 -------->
+ RRSIGpar(SOA0) --------> RRSIGpar(SOA1) -------->
+ DS1 --------> DS2 -------->
+ RRSIGpar(DS) --------> RRSIGpar(DS) -------->
+
+
+ Child:
+ SOA0 SOA1 --------> SOA2
+ RRSIG10(SOA0) RRSIG10(SOA1) --------> RRSIG10(SOA2)
+ -------->
+ DNSKEY1 DNSKEY1 --------> DNSKEY2
+ DNSKEY2 -------->
+ DNSKEY10 DNSKEY10 --------> DNSKEY10
+ RRSIG1 (DNSKEY) RRSIG1 (DNSKEY) --------> RRSIG2 (DNSKEY)
+ RRSIG2 (DNSKEY) -------->
+ RRSIG10(DNSKEY) RRSIG10(DNSKEY) --------> RRSIG10(DNSKEY)
+ --------------------------------------------------------------------
+
+ Stages of Deployment for a Double Signature Key Signing Key Rollover
+
+ initial: Initial version of the zone. The parental DS points to
+ DNSKEY1. Before the rollover starts, the child will have to
+ verify what the TTL is of the DS RR that points to DNSKEY1 -- it
+ is needed during the rollover and we refer to the value as TTL_DS.
+
+ new DNSKEY: During the "new DNSKEY" phase, the zone administrator
+ generates a second KSK, DNSKEY2. The key is provided to the
+ parent, and the child will have to wait until a new DS RR has been
+ generated that points to DNSKEY2. After that DS RR has been
+ published on all servers authoritative for the parent's zone, the
+ zone administrator has to wait at least TTL_DS to make sure that
+ the old DS RR has expired from caches.
+
+ DS change: The parent replaces DS1 with DS2.
+
+ DNSKEY removal: DNSKEY1 has been removed.
+
+ The scenario above puts the responsibility for maintaining a valid
+ chain of trust with the child. It also is based on the premise that
+ the parent only has one DS RR (per algorithm) per zone. An
+ alternative mechanism has been considered. Using an established
+ trust relation, the interaction can be performed in-band, and the
+ removal of the keys by the child can possibly be signaled by the
+ parent. In this mechanism, there are periods where there are two DS
+
+
+
+Kolkman & Gieben Informational [Page 19]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ RRs at the parent. Since at the moment of writing the protocol for
+ this interaction has not been developed, further discussion is out of
+ scope for this document.
+
+4.2.3. Difference Between ZSK and KSK Rollovers
+
+ Note that KSK rollovers and ZSK rollovers are different in the sense
+ that a KSK rollover requires interaction with the parent (and
+ possibly replacing of trust anchors) and the ensuing delay while
+ waiting for it.
+
+ A zone key rollover can be handled in two different ways: pre-publish
+ (Section 4.2.1.1) and double signature (Section 4.2.1.2).
+
+ As the KSK is used to validate the key set and because the KSK is not
+ changed during a ZSK rollover, a cache is able to validate the new
+ key set of the zone. The pre-publish method would also work for a
+ KSK rollover. The records that are to be pre-published are the
+ parental DS RRs. The pre-publish method has some drawbacks for KSKs.
+ We first describe the rollover scheme and then indicate these
+ drawbacks.
+
+ --------------------------------------------------------------------
+ initial new DS new DNSKEY DS/DNSKEY removal
+ --------------------------------------------------------------------
+ Parent:
+ SOA0 SOA1 --------> SOA2
+ RRSIGpar(SOA0) RRSIGpar(SOA1) --------> RRSIGpar(SOA2)
+ DS1 DS1 --------> DS2
+ DS2 -------->
+ RRSIGpar(DS) RRSIGpar(DS) --------> RRSIGpar(DS)
+
+
+ Child:
+ SOA0 --------> SOA1 SOA1
+ RRSIG10(SOA0) --------> RRSIG10(SOA1) RRSIG10(SOA1)
+ -------->
+ DNSKEY1 --------> DNSKEY2 DNSKEY2
+ -------->
+ DNSKEY10 --------> DNSKEY10 DNSKEY10
+ RRSIG1 (DNSKEY) --------> RRSIG2(DNSKEY) RRSIG2 (DNSKEY)
+ RRSIG10(DNSKEY) --------> RRSIG10(DNSKEY) RRSIG10(DNSKEY)
+ --------------------------------------------------------------------
+
+ Stages of Deployment for a Pre-Publish Key Signing Key Rollover
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 20]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ When the child zone wants to roll, it notifies the parent during the
+ "new DS" phase and submits the new key (or the corresponding DS) to
+ the parent. The parent publishes DS1 and DS2, pointing to DNSKEY1
+ and DNSKEY2, respectively. During the rollover ("new DNSKEY" phase),
+ which can take place as soon as the new DS set propagated through the
+ DNS, the child replaces DNSKEY1 with DNSKEY2. Immediately after that
+ ("DS/DNSKEY removal" phase), it can notify the parent that the old DS
+ record can be deleted.
+
+ The drawbacks of this scheme are that during the "new DS" phase the
+ parent cannot verify the match between the DS2 RR and DNSKEY2 using
+ the DNS -- as DNSKEY2 is not yet published. Besides, we introduce a
+ "security lame" key (see Section 4.4.3). Finally, the child-parent
+ interaction consists of two steps. The "double signature" method
+ only needs one interaction.
+
+4.2.4. Automated Key Rollovers
+
+ As keys must be renewed periodically, there is some motivation to
+ automate the rollover process. Consider the following:
+
+ o ZSK rollovers are easy to automate as only the child zone is
+ involved.
+
+ o A KSK rollover needs interaction between parent and child. Data
+ exchange is needed to provide the new keys to the parent;
+ consequently, this data must be authenticated and integrity must
+ be guaranteed in order to avoid attacks on the rollover.
+
+4.3. Planning for Emergency Key Rollover
+
+ This section deals with preparation for a possible key compromise.
+ Our advice is to have a documented procedure ready for when a key
+ compromise is suspected or confirmed.
+
+ When the private material of one of your keys is compromised it can
+ be used for as long as a valid trust chain exists. A trust chain
+ remains intact for
+
+ o as long as a signature over the compromised key in the trust chain
+ is valid,
+
+ o as long as a parental DS RR (and signature) points to the
+ compromised key,
+
+ o as long as the key is anchored in a resolver and is used as a
+ starting point for validation (this is generally the hardest to
+ update).
+
+
+
+Kolkman & Gieben Informational [Page 21]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ While a trust chain to your compromised key exists, your namespace is
+ vulnerable to abuse by anyone who has obtained illegitimate
+ possession of the key. Zone operators have to make a trade-off if
+ the abuse of the compromised key is worse than having data in caches
+ that cannot be validated. If the zone operator chooses to break the
+ trust chain to the compromised key, data in caches signed with this
+ key cannot be validated. However, if the zone administrator chooses
+ to take the path of a regular rollover, the malicious key holder can
+ spoof data so that it appears to be valid.
+
+4.3.1. KSK Compromise
+
+ A zone containing a DNSKEY RRSet with a compromised KSK is vulnerable
+ as long as the compromised KSK is configured as trust anchor or a
+ parental DS points to it.
+
+ A compromised KSK can be used to sign the key set of an attacker's
+ zone. That zone could be used to poison the DNS.
+
+ Therefore, when the KSK has been compromised, the trust anchor or the
+ parental DS should be replaced as soon as possible. It is local
+ policy whether to break the trust chain during the emergency
+ rollover. The trust chain would be broken when the compromised KSK
+ is removed from the child's zone while the parent still has a DS
+ pointing to the compromised KSK (the assumption is that there is only
+ one DS at the parent. If there are multiple DSes this does not apply
+ -- however the chain of trust of this particular key is broken).
+
+ Note that an attacker's zone still uses the compromised KSK and the
+ presence of a parental DS would cause the data in this zone to appear
+ as valid. Removing the compromised key would cause the attacker's
+ zone to appear as valid and the child's zone as Bogus. Therefore, we
+ advise not to remove the KSK before the parent has a DS to a new KSK
+ in place.
+
+4.3.1.1. Keeping the Chain of Trust Intact
+
+ If we follow this advice, the timing of the replacement of the KSK is
+ somewhat critical. The goal is to remove the compromised KSK as soon
+ as the new DS RR is available at the parent. And also make sure that
+ the signature made with a new KSK over the key set with the
+ compromised KSK in it expires just after the new DS appears at the
+ parent, thus removing the old cruft in one swoop.
+
+ The procedure is as follows:
+
+ 1. Introduce a new KSK into the key set, keep the compromised KSK in
+ the key set.
+
+
+
+Kolkman & Gieben Informational [Page 22]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ 2. Sign the key set, with a short validity period. The validity
+ period should expire shortly after the DS is expected to appear
+ in the parent and the old DSes have expired from caches.
+
+ 3. Upload the DS for this new key to the parent.
+
+ 4. Follow the procedure of the regular KSK rollover: Wait for the DS
+ to appear in the authoritative servers and then wait as long as
+ the TTL of the old DS RRs. If necessary re-sign the DNSKEY RRSet
+ and modify/extend the expiration time.
+
+ 5. Remove the compromised DNSKEY RR from the zone and re-sign the
+ key set using your "normal" validity interval.
+
+ An additional danger of a key compromise is that the compromised key
+ could be used to facilitate a legitimate DNSKEY/DS rollover and/or
+ nameserver changes at the parent. When that happens, the domain may
+ be in dispute. An authenticated out-of-band and secure notify
+ mechanism to contact a parent is needed in this case.
+
+ Note that this is only a problem when the DNSKEY and or DS records
+ are used for authentication at the parent.
+
+4.3.1.2. Breaking the Chain of Trust
+
+ There are two methods to break the chain of trust. The first method
+ causes the child zone to appear 'Bogus' to validating resolvers. The
+ other causes the child zone to appear 'insecure'. These are
+ described below.
+
+ In the method that causes the child zone to appear 'Bogus' to
+ validating resolvers, the child zone replaces the current KSK with a
+ new one and re-signs the key set. Next it sends the DS of the new
+ key to the parent. Only after the parent has placed the new DS in
+ the zone is the child's chain of trust repaired.
+
+ An alternative method of breaking the chain of trust is by removing
+ the DS RRs from the parent zone altogether. As a result, the child
+ zone would become insecure.
+
+4.3.2. ZSK Compromise
+
+ Primarily because there is no parental interaction required when a
+ ZSK is compromised, the situation is less severe than with a KSK
+ compromise. The zone must still be re-signed with a new ZSK as soon
+ as possible. As this is a local operation and requires no
+ communication between the parent and child, this can be achieved
+ fairly quickly. However, one has to take into account that just as
+
+
+
+Kolkman & Gieben Informational [Page 23]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ with a normal rollover the immediate disappearance of the old
+ compromised key may lead to verification problems. Also note that as
+ long as the RRSIG over the compromised ZSK is not expired the zone
+ may be still at risk.
+
+4.3.3. Compromises of Keys Anchored in Resolvers
+
+ A key can also be pre-configured in resolvers. For instance, if
+ DNSSEC is successfully deployed the root key may be pre-configured in
+ most security aware resolvers.
+
+ If trust-anchor keys are compromised, the resolvers using these keys
+ should be notified of this fact. Zone administrators may consider
+ setting up a mailing list to communicate the fact that a SEP key is
+ about to be rolled over. This communication will of course need to
+ be authenticated, e.g., by using digital signatures.
+
+ End-users faced with the task of updating an anchored key should
+ always validate the new key. New keys should be authenticated out-
+ of-band, for example, through the use of an announcement website that
+ is secured using secure sockets (TLS) [21].
+
+4.4. Parental Policies
+
+4.4.1. Initial Key Exchanges and Parental Policies Considerations
+
+ The initial key exchange is always subject to the policies set by the
+ parent. When designing a key exchange policy one should take into
+ account that the authentication and authorization mechanisms used
+ during a key exchange should be as strong as the authentication and
+ authorization mechanisms used for the exchange of delegation
+ information between parent and child. That is, there is no implicit
+ need in DNSSEC to make the authentication process stronger than it
+ was in DNS.
+
+ Using the DNS itself as the source for the actual DNSKEY material,
+ with an out-of-band check on the validity of the DNSKEY, has the
+ benefit that it reduces the chances of user error. A DNSKEY query
+ tool can make use of the SEP bit [3] to select the proper key from a
+ DNSSEC key set, thereby reducing the chance that the wrong DNSKEY is
+ sent. It can validate the self-signature over a key; thereby
+ verifying the ownership of the private key material. Fetching the
+ DNSKEY from the DNS ensures that the chain of trust remains intact
+ once the parent publishes the DS RR indicating the child is secure.
+
+ Note: the out-of-band verification is still needed when the key
+ material is fetched via the DNS. The parent can never be sure
+ whether or not the DNSKEY RRs have been spoofed.
+
+
+
+Kolkman & Gieben Informational [Page 24]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+4.4.2. Storing Keys or Hashes?
+
+ When designing a registry system one should consider which of the
+ DNSKEYs and/or the corresponding DSes to store. Since a child zone
+ might wish to have a DS published using a message digest algorithm
+ not yet understood by the registry, the registry can't count on being
+ able to generate the DS record from a raw DNSKEY. Thus, we recommend
+ that registry systems at least support storing DS records.
+
+ It may also be useful to store DNSKEYs, since having them may help
+ during troubleshooting and, as long as the child's chosen message
+ digest is supported, the overhead of generating DS records from them
+ is minimal. Having an out-of-band mechanism, such as a registry
+ directory (e.g., Whois), to find out which keys are used to generate
+ DS Resource Records for specific owners and/or zones may also help
+ with troubleshooting.
+
+ The storage considerations also relate to the design of the customer
+ interface and the method by which data is transferred between
+ registrant and registry; Will the child zone administrator be able to
+ upload DS RRs with unknown hash algorithms or does the interface only
+ allow DNSKEYs? In the registry-registrar model, one can use the
+ DNSSEC extensions to the Extensible Provisioning Protocol (EPP) [15],
+ which allows transfer of DS RRs and optionally DNSKEY RRs.
+
+4.4.3. Security Lameness
+
+ Security lameness is defined as what happens when a parent has a DS
+ RR pointing to a non-existing DNSKEY RR. When this happens, the
+ child's zone may be marked "Bogus" by verifying DNS clients.
+
+ As part of a comprehensive delegation check, the parent could, at key
+ exchange time, verify that the child's key is actually configured in
+ the DNS. However, if a parent does not understand the hashing
+ algorithm used by child, the parental checks are limited to only
+ comparing the key id.
+
+ Child zones should be very careful in removing DNSKEY material,
+ specifically SEP keys, for which a DS RR exists.
+
+ Once a zone is "security lame", a fix (e.g., removing a DS RR) will
+ take time to propagate through the DNS.
+
+
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 25]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+4.4.4. DS Signature Validity Period
+
+ Since the DS can be replayed as long as it has a valid signature, a
+ short signature validity period over the DS minimizes the time a
+ child is vulnerable in the case of a compromise of the child's
+ KSK(s). A signature validity period that is too short introduces the
+ possibility that a zone is marked "Bogus" in case of a configuration
+ error in the signer. There may not be enough time to fix the
+ problems before signatures expire. Something as mundane as operator
+ unavailability during weekends shows the need for DS signature
+ validity periods longer than 2 days. We recommend an absolute
+ minimum for a DS signature validity period of a few days.
+
+ The maximum signature validity period of the DS record depends on how
+ long child zones are willing to be vulnerable after a key compromise.
+ On the other hand, shortening the DS signature validity interval
+ increases the operational risk for the parent. Therefore, the parent
+ may have policy to use a signature validity interval that is
+ considerably longer than the child would hope for.
+
+ A compromise between the operational constraints of the parent and
+ minimizing damage for the child may result in a DS signature validity
+ period somewhere between a week and months.
+
+ In addition to the signature validity period, which sets a lower
+ bound on the number of times the zone owner will need to sign the
+ zone data and which sets an upper bound to the time a child is
+ vulnerable after key compromise, there is the TTL value on the DS
+ RRs. Shortening the TTL means that the authoritative servers will
+ see more queries. But on the other hand, a short TTL lowers the
+ persistence of DS RRSets in caches thereby increasing the speed with
+ which updated DS RRSets propagate through the DNS.
+
+5. Security Considerations
+
+ DNSSEC adds data integrity to the DNS. This document tries to assess
+ the operational considerations to maintain a stable and secure DNSSEC
+ service. Not taking into account the 'data propagation' properties
+ in the DNS will cause validation failures and may make secured zones
+ unavailable to security-aware resolvers.
+
+6. Acknowledgments
+
+ Most of the ideas in this document were the result of collective
+ efforts during workshops, discussions, and tryouts.
+
+ At the risk of forgetting individuals who were the original
+ contributors of the ideas, we would like to acknowledge people who
+
+
+
+Kolkman & Gieben Informational [Page 26]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ were actively involved in the compilation of this document. In
+ random order: Rip Loomis, Olafur Gudmundsson, Wesley Griffin, Michael
+ Richardson, Scott Rose, Rick van Rein, Tim McGinnis, Gilles Guette
+ Olivier Courtay, Sam Weiler, Jelte Jansen, Niall O'Reilly, Holger
+ Zuleger, Ed Lewis, Hilarie Orman, Marcos Sanz, and Peter Koch.
+
+ Some material in this document has been copied from RFC 2541 [12].
+
+ Mike StJohns designed the key exchange between parent and child
+ mentioned in the last paragraph of Section 4.2.2
+
+ Section 4.2.4 was supplied by G. Guette and O. Courtay.
+
+ Emma Bretherick, Adrian Bedford, and Lindy Foster corrected many of
+ the spelling and style issues.
+
+ Kolkman and Gieben take the blame for introducing all miscakes (sic).
+
+ While working on this document, Kolkman was employed by the RIPE NCC
+ and Gieben was employed by NLnet Labs.
+
+7. References
+
+7.1. Normative References
+
+ [1] Mockapetris, P., "Domain names - concepts and facilities", STD
+ 13, RFC 1034, November 1987.
+
+ [2] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [3] Kolkman, O., Schlyter, J., and E. Lewis, "Domain Name System
+ KEY (DNSKEY) Resource Record (RR) Secure Entry Point (SEP)
+ Flag", RFC 3757, May 2004.
+
+ [4] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033, March
+ 2005.
+
+ [5] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+ [6] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Protocol Modifications for the DNS Security Extensions", RFC
+ 4035, March 2005.
+
+
+
+
+
+Kolkman & Gieben Informational [Page 27]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+7.2. Informative References
+
+ [7] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [8] Ohta, M., "Incremental Zone Transfer in DNS", RFC 1995, August
+ 1996.
+
+ [9] Vixie, P., "A Mechanism for Prompt Notification of Zone Changes
+ (DNS NOTIFY)", RFC 1996, August 1996.
+
+ [10] Wellington, B., "Secure Domain Name System (DNS) Dynamic
+ Update", RFC 3007, November 2000.
+
+ [11] Andrews, M., "Negative Caching of DNS Queries (DNS NCACHE)",
+ RFC 2308, March 1998.
+
+ [12] Eastlake, D., "DNS Security Operational Considerations", RFC
+ 2541, March 1999.
+
+ [13] Orman, H. and P. Hoffman, "Determining Strengths For Public
+ Keys Used For Exchanging Symmetric Keys", BCP 86, RFC 3766,
+ April 2004.
+
+ [14] Eastlake, D., Schiller, J., and S. Crocker, "Randomness
+ Requirements for Security", BCP 106, RFC 4086, June 2005.
+
+ [15] Hollenbeck, S., "Domain Name System (DNS) Security Extensions
+ Mapping for the Extensible Provisioning Protocol (EPP)", RFC
+ 4310, December 2005.
+
+ [16] Lenstra, A. and E. Verheul, "Selecting Cryptographic Key
+ Sizes", The Journal of Cryptology 14 (255-293), 2001.
+
+ [17] Schneier, B., "Applied Cryptography: Protocols, Algorithms, and
+ Source Code in C", ISBN (hardcover) 0-471-12845-7, ISBN
+ (paperback) 0-471-59756-2, Published by John Wiley & Sons Inc.,
+ 1996.
+
+ [18] Rose, S., "NIST DNSSEC workshop notes", June 2001.
+
+ [19] Jansen, J., "Use of RSA/SHA-256 DNSKEY and RRSIG Resource
+ Records in DNSSEC", Work in Progress, January 2006.
+
+ [20] Hardaker, W., "Use of SHA-256 in DNSSEC Delegation Signer (DS)
+ Resource Records (RRs)", RFC 4509, May 2006.
+
+
+
+
+
+Kolkman & Gieben Informational [Page 28]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ [21] Blake-Wilson, S., Nystrom, M., Hopwood, D., Mikkelsen, J., and
+ T. Wright, "Transport Layer Security (TLS) Extensions", RFC
+ 4366, April 2006.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 29]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+Appendix A. Terminology
+
+ In this document, there is some jargon used that is defined in other
+ documents. In most cases, we have not copied the text from the
+ documents defining the terms but have given a more elaborate
+ explanation of the meaning. Note that these explanations should not
+ be seen as authoritative.
+
+ Anchored key: A DNSKEY configured in resolvers around the globe.
+ This key is hard to update, hence the term anchored.
+
+ Bogus: Also see Section 5 of [4]. An RRSet in DNSSEC is marked
+ "Bogus" when a signature of an RRSet does not validate against a
+ DNSKEY.
+
+ Key Signing Key or KSK: A Key Signing Key (KSK) is a key that is used
+ exclusively for signing the apex key set. The fact that a key is
+ a KSK is only relevant to the signing tool.
+
+ Key size: The term 'key size' can be substituted by 'modulus size'
+ throughout the document. It is mathematically more correct to use
+ modulus size, but as this is a document directed at operators we
+ feel more at ease with the term key size.
+
+ Private and public keys: DNSSEC secures the DNS through the use of
+ public key cryptography. Public key cryptography is based on the
+ existence of two (mathematically related) keys, a public key and a
+ private key. The public keys are published in the DNS by use of
+ the DNSKEY Resource Record (DNSKEY RR). Private keys should
+ remain private.
+
+ Key rollover: A key rollover (also called key supercession in some
+ environments) is the act of replacing one key pair with another at
+ the end of a key effectivity period.
+
+ Secure Entry Point (SEP) key: A KSK that has a parental DS record
+ pointing to it or is configured as a trust anchor. Although not
+ required by the protocol, we recommend that the SEP flag [3] is
+ set on these keys.
+
+ Self-signature: This only applies to signatures over DNSKEYs; a
+ signature made with DNSKEY x, over DNSKEY x is called a self-
+ signature. Note: without further information, self-signatures
+ convey no trust. They are useful to check the authenticity of the
+ DNSKEY, i.e., they can be used as a hash.
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 30]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ Singing the zone file: The term used for the event where an
+ administrator joyfully signs its zone file while producing melodic
+ sound patterns.
+
+ Signer: The system that has access to the private key material and
+ signs the Resource Record sets in a zone. A signer may be
+ configured to sign only parts of the zone, e.g., only those RRSets
+ for which existing signatures are about to expire.
+
+ Zone Signing Key (ZSK): A key that is used for signing all data in a
+ zone. The fact that a key is a ZSK is only relevant to the
+ signing tool.
+
+ Zone administrator: The 'role' that is responsible for signing a zone
+ and publishing it on the primary authoritative server.
+
+Appendix B. Zone Signing Key Rollover How-To
+
+ Using the pre-published signature scheme and the most conservative
+ method to assure oneself that data does not live in caches, here
+ follows the "how-to".
+
+ Step 0: The preparation: Create two keys and publish both in your key
+ set. Mark one of the keys "active" and the other "published".
+ Use the "active" key for signing your zone data. Store the
+ private part of the "published" key, preferably off-line. The
+ protocol does not provide for attributes to mark a key as active
+ or published. This is something you have to do on your own,
+ through the use of a notebook or key management tool.
+
+ Step 1: Determine expiration: At the beginning of the rollover make a
+ note of the highest expiration time of signatures in your zone
+ file created with the current key marked as active. Wait until
+ the expiration time marked in Step 1 has passed.
+
+ Step 2: Then start using the key that was marked "published" to sign
+ your data (i.e., mark it "active"). Stop using the key that was
+ marked "active"; mark it "rolled".
+
+ Step 3: It is safe to engage in a new rollover (Step 1) after at
+ least one signature validity period.
+
+
+
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 31]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+Appendix C. Typographic Conventions
+
+ The following typographic conventions are used in this document:
+
+ Key notation: A key is denoted by DNSKEYx, where x is a number or an
+ identifier, x could be thought of as the key id.
+
+ RRSet notations: RRs are only denoted by the type. All other
+ information -- owner, class, rdata, and TTL--is left out. Thus:
+ "example.com 3600 IN A 192.0.2.1" is reduced to "A". RRSets are a
+ list of RRs. A example of this would be "A1, A2", specifying the
+ RRSet containing two "A" records. This could again be abbreviated to
+ just "A".
+
+ Signature notation: Signatures are denoted as RRSIGx(RRSet), which
+ means that RRSet is signed with DNSKEYx.
+
+ Zone representation: Using the above notation we have simplified the
+ representation of a signed zone by leaving out all unnecessary
+ details such as the names and by representing all data by "SOAx"
+
+ SOA representation: SOAs are represented as SOAx, where x is the
+ serial number.
+
+ Using this notation the following signed zone:
+
+ example.net. 86400 IN SOA ns.example.net. bert.example.net. (
+ 2006022100 ; serial
+ 86400 ; refresh ( 24 hours)
+ 7200 ; retry ( 2 hours)
+ 3600000 ; expire (1000 hours)
+ 28800 ) ; minimum ( 8 hours)
+ 86400 RRSIG SOA 5 2 86400 20130522213204 (
+ 20130422213204 14 example.net.
+ cmL62SI6iAX46xGNQAdQ... )
+ 86400 NS a.iana-servers.net.
+ 86400 NS b.iana-servers.net.
+ 86400 RRSIG NS 5 2 86400 20130507213204 (
+ 20130407213204 14 example.net.
+ SO5epiJei19AjXoUpFnQ ... )
+ 86400 DNSKEY 256 3 5 (
+ EtRB9MP5/AvOuVO0I8XDxy0... ) ; id = 14
+ 86400 DNSKEY 257 3 5 (
+ gsPW/Yy19GzYIY+Gnr8HABU... ) ; id = 15
+ 86400 RRSIG DNSKEY 5 2 86400 20130522213204 (
+ 20130422213204 14 example.net.
+ J4zCe8QX4tXVGjV4e1r9... )
+
+
+
+
+Kolkman & Gieben Informational [Page 32]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+ 86400 RRSIG DNSKEY 5 2 86400 20130522213204 (
+ 20130422213204 15 example.net.
+ keVDCOpsSeDReyV6O... )
+ 86400 RRSIG NSEC 5 2 86400 20130507213204 (
+ 20130407213204 14 example.net.
+ obj3HEp1GjnmhRjX... )
+ a.example.net. 86400 IN TXT "A label"
+ 86400 RRSIG TXT 5 3 86400 20130507213204 (
+ 20130407213204 14 example.net.
+ IkDMlRdYLmXH7QJnuF3v... )
+ 86400 NSEC b.example.com. TXT RRSIG NSEC
+ 86400 RRSIG NSEC 5 3 86400 20130507213204 (
+ 20130407213204 14 example.net.
+ bZMjoZ3bHjnEz0nIsPMM... )
+ ...
+
+ is reduced to the following representation:
+
+ SOA2006022100
+ RRSIG14(SOA2006022100)
+ DNSKEY14
+ DNSKEY15
+
+ RRSIG14(KEY)
+ RRSIG15(KEY)
+
+ The rest of the zone data has the same signature as the SOA record,
+ i.e., an RRSIG created with DNSKEY 14.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 33]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+Authors' Addresses
+
+ Olaf M. Kolkman
+ NLnet Labs
+ Kruislaan 419
+ Amsterdam 1098 VA
+ The Netherlands
+
+ EMail: olaf@nlnetlabs.nl
+ URI: http://www.nlnetlabs.nl
+
+
+ R. (Miek) Gieben
+
+ EMail: miek@miek.nl
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 34]
+
+RFC 4641 DNSSEC Operational Practices September 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Kolkman & Gieben Informational [Page 35]
+
diff --git a/doc/rfc/rfc4648.txt b/doc/rfc/rfc4648.txt
new file mode 100644
index 0000000..c7599b4
--- /dev/null
+++ b/doc/rfc/rfc4648.txt
@@ -0,0 +1,1011 @@
+
+
+
+
+
+
+Network Working Group S. Josefsson
+Request for Comments: 4648 SJD
+Obsoletes: 3548 October 2006
+Category: Standards Track
+
+
+ The Base16, Base32, and Base64 Data Encodings
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ This document describes the commonly used base 64, base 32, and base
+ 16 encoding schemes. It also discusses the use of line-feeds in
+ encoded data, use of padding in encoded data, use of non-alphabet
+ characters in encoded data, use of different encoding alphabets, and
+ canonical encodings.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 1]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+Table of Contents
+
+ 1. Introduction ....................................................3
+ 2. Conventions Used in This Document ...............................3
+ 3. Implementation Discrepancies ....................................3
+ 3.1. Line Feeds in Encoded Data .................................3
+ 3.2. Padding of Encoded Data ....................................4
+ 3.3. Interpretation of Non-Alphabet Characters in Encoded Data ..4
+ 3.4. Choosing the Alphabet ......................................4
+ 3.5. Canonical Encoding .........................................5
+ 4. Base 64 Encoding ................................................5
+ 5. Base 64 Encoding with URL and Filename Safe Alphabet ............7
+ 6. Base 32 Encoding ................................................8
+ 7. Base 32 Encoding with Extended Hex Alphabet ....................10
+ 8. Base 16 Encoding ...............................................10
+ 9. Illustrations and Examples .....................................11
+ 10. Test Vectors ..................................................12
+ 11. ISO C99 Implementation of Base64 ..............................14
+ 12. Security Considerations .......................................14
+ 13. Changes Since RFC 3548 ........................................15
+ 14. Acknowledgements ..............................................15
+ 15. Copying Conditions ............................................15
+ 16. References ....................................................16
+ 16.1. Normative References .....................................16
+ 16.2. Informative References ...................................16
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 2]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+1. Introduction
+
+ Base encoding of data is used in many situations to store or transfer
+ data in environments that, perhaps for legacy reasons, are restricted
+ to US-ASCII [1] data. Base encoding can also be used in new
+ applications that do not have legacy restrictions, simply because it
+ makes it possible to manipulate objects with text editors.
+
+ In the past, different applications have had different requirements
+ and thus sometimes implemented base encodings in slightly different
+ ways. Today, protocol specifications sometimes use base encodings in
+ general, and "base64" in particular, without a precise description or
+ reference. Multipurpose Internet Mail Extensions (MIME) [4] is often
+ used as a reference for base64 without considering the consequences
+ for line-wrapping or non-alphabet characters. The purpose of this
+ specification is to establish common alphabet and encoding
+ considerations. This will hopefully reduce ambiguity in other
+ documents, leading to better interoperability.
+
+2. Conventions Used in This Document
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [2].
+
+3. Implementation Discrepancies
+
+ Here we discuss the discrepancies between base encoding
+ implementations in the past and, where appropriate, mandate a
+ specific recommended behavior for the future.
+
+3.1. Line Feeds in Encoded Data
+
+ MIME [4] is often used as a reference for base 64 encoding. However,
+ MIME does not define "base 64" per se, but rather a "base 64 Content-
+ Transfer-Encoding" for use within MIME. As such, MIME enforces a
+ limit on line length of base 64-encoded data to 76 characters. MIME
+ inherits the encoding from Privacy Enhanced Mail (PEM) [3], stating
+ that it is "virtually identical"; however, PEM uses a line length of
+ 64 characters. The MIME and PEM limits are both due to limits within
+ SMTP.
+
+ Implementations MUST NOT add line feeds to base-encoded data unless
+ the specification referring to this document explicitly directs base
+ encoders to add line feeds after a specific number of characters.
+
+
+
+
+
+
+Josefsson Standards Track [Page 3]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+3.2. Padding of Encoded Data
+
+ In some circumstances, the use of padding ("=") in base-encoded data
+ is not required or used. In the general case, when assumptions about
+ the size of transported data cannot be made, padding is required to
+ yield correct decoded data.
+
+ Implementations MUST include appropriate pad characters at the end of
+ encoded data unless the specification referring to this document
+ explicitly states otherwise.
+
+ The base64 and base32 alphabets use padding, as described below in
+ sections 4 and 6, but the base16 alphabet does not need it; see
+ section 8.
+
+3.3. Interpretation of Non-Alphabet Characters in Encoded Data
+
+ Base encodings use a specific, reduced alphabet to encode binary
+ data. Non-alphabet characters could exist within base-encoded data,
+ caused by data corruption or by design. Non-alphabet characters may
+ be exploited as a "covert channel", where non-protocol data can be
+ sent for nefarious purposes. Non-alphabet characters might also be
+ sent in order to exploit implementation errors leading to, e.g.,
+ buffer overflow attacks.
+
+ Implementations MUST reject the encoded data if it contains
+ characters outside the base alphabet when interpreting base-encoded
+ data, unless the specification referring to this document explicitly
+ states otherwise. Such specifications may instead state, as MIME
+ does, that characters outside the base encoding alphabet should
+ simply be ignored when interpreting data ("be liberal in what you
+ accept"). Note that this means that any adjacent carriage return/
+ line feed (CRLF) characters constitute "non-alphabet characters" and
+ are ignored. Furthermore, such specifications MAY ignore the pad
+ character, "=", treating it as non-alphabet data, if it is present
+ before the end of the encoded data. If more than the allowed number
+ of pad characters is found at the end of the string (e.g., a base 64
+ string terminated with "==="), the excess pad characters MAY also be
+ ignored.
+
+3.4. Choosing the Alphabet
+
+ Different applications have different requirements on the characters
+ in the alphabet. Here are a few requirements that determine which
+ alphabet should be used:
+
+
+
+
+
+
+Josefsson Standards Track [Page 4]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+ o Handled by humans. The characters "0" and "O" are easily
+ confused, as are "1", "l", and "I". In the base32 alphabet below,
+ where 0 (zero) and 1 (one) are not present, a decoder may
+ interpret 0 as O, and 1 as I or L depending on case. (However, by
+ default it should not; see previous section.)
+
+ o Encoded into structures that mandate other requirements. For base
+ 16 and base 32, this determines the use of upper- or lowercase
+ alphabets. For base 64, the non-alphanumeric characters (in
+ particular, "/") may be problematic in file names and URLs.
+
+ o Used as identifiers. Certain characters, notably "+" and "/" in
+ the base 64 alphabet, are treated as word-breaks by legacy text
+ search/index tools.
+
+ There is no universally accepted alphabet that fulfills all the
+ requirements. For an example of a highly specialized variant, see
+ IMAP [8]. In this document, we document and name some currently used
+ alphabets.
+
+3.5. Canonical Encoding
+
+ The padding step in base 64 and base 32 encoding can, if improperly
+ implemented, lead to non-significant alterations of the encoded data.
+ For example, if the input is only one octet for a base 64 encoding,
+ then all six bits of the first symbol are used, but only the first
+ two bits of the next symbol are used. These pad bits MUST be set to
+ zero by conforming encoders, which is described in the descriptions
+ on padding below. If this property do not hold, there is no
+ canonical representation of base-encoded data, and multiple base-
+ encoded strings can be decoded to the same binary data. If this
+ property (and others discussed in this document) holds, a canonical
+ encoding is guaranteed.
+
+ In some environments, the alteration is critical and therefore
+ decoders MAY chose to reject an encoding if the pad bits have not
+ been set to zero. The specification referring to this may mandate a
+ specific behaviour.
+
+4. Base 64 Encoding
+
+ The following description of base 64 is derived from [3], [4], [5],
+ and [6]. This encoding may be referred to as "base64".
+
+ The Base 64 encoding is designed to represent arbitrary sequences of
+ octets in a form that allows the use of both upper- and lowercase
+ letters but that need not be human readable.
+
+
+
+
+Josefsson Standards Track [Page 5]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single character in the base 64
+ alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base 64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, bits with value zero are added
+ (on the right) to form an integral number of 6-bit groups. Padding
+ at the end of the data is performed using the '=' character. Since
+ all base 64 input is an integral number of octets, only the following
+ cases can arise:
+
+ (1) The final quantum of encoding input is an integral multiple of 24
+ bits; here, the final unit of encoded output will be an integral
+ multiple of 4 characters with no "=" padding.
+
+
+
+Josefsson Standards Track [Page 6]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+ (2) The final quantum of encoding input is exactly 8 bits; here, the
+ final unit of encoded output will be two characters followed by
+ two "=" padding characters.
+
+ (3) The final quantum of encoding input is exactly 16 bits; here, the
+ final unit of encoded output will be three characters followed by
+ one "=" padding character.
+
+5. Base 64 Encoding with URL and Filename Safe Alphabet
+
+ The Base 64 encoding with an URL and filename safe alphabet has been
+ used in [12].
+
+ An alternative alphabet has been suggested that would use "~" as the
+ 63rd character. Since the "~" character has special meaning in some
+ file system environments, the encoding described in this section is
+ recommended instead. The remaining unreserved URI character is ".",
+ but some file system environments do not permit multiple "." in a
+ filename, thus making the "." character unattractive as well.
+
+ The pad character "=" is typically percent-encoded when used in an
+ URI [9], but if the data length is known implicitly, this can be
+ avoided by skipping the padding; see section 3.2.
+
+ This encoding may be referred to as "base64url". This encoding
+ should not be regarded as the same as the "base64" encoding and
+ should not be referred to as only "base64". Unless clarified
+ otherwise, "base64" refers to the base 64 in the previous section.
+
+ This encoding is technically identical to the previous one, except
+ for the 62:nd and 63:rd alphabet character, as indicated in Table 2.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 7]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+ Table 2: The "URL and Filename safe" Base 64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 - (minus)
+ 12 M 29 d 46 u 63 _
+ 13 N 30 e 47 v (underline)
+ 14 O 31 f 48 w
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y (pad) =
+
+6. Base 32 Encoding
+
+ The following description of base 32 is derived from [11] (with
+ corrections). This encoding may be referred to as "base32".
+
+ The Base 32 encoding is designed to represent arbitrary sequences of
+ octets in a form that needs to be case insensitive but that need not
+ be human readable.
+
+ A 33-character subset of US-ASCII is used, enabling 5 bits to be
+ represented per printable character. (The extra 33rd character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 40-bit groups of input bits as output
+ strings of 8 encoded characters. Proceeding from left to right, a
+ 40-bit input group is formed by concatenating 5 8bit input groups.
+ These 40 bits are then treated as 8 concatenated 5-bit groups, each
+ of which is translated into a single character in the base 32
+ alphabet. When a bit stream is encoded via the base 32 encoding, the
+ bit stream must be presumed to be ordered with the most-significant-
+ bit first. That is, the first bit in the stream will be the high-
+ order bit in the first 8bit byte, the eighth bit will be the low-
+ order bit in the first 8bit byte, and so on.
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 8]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+ Each 5-bit group is used as an index into an array of 32 printable
+ characters. The character referenced by the index is placed in the
+ output string. These characters, identified in Table 3, below, are
+ selected from US-ASCII digits and uppercase letters.
+
+ Table 3: The Base 32 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 9 J 18 S 27 3
+ 1 B 10 K 19 T 28 4
+ 2 C 11 L 20 U 29 5
+ 3 D 12 M 21 V 30 6
+ 4 E 13 N 22 W 31 7
+ 5 F 14 O 23 X
+ 6 G 15 P 24 Y (pad) =
+ 7 H 16 Q 25 Z
+ 8 I 17 R 26 2
+
+ Special processing is performed if fewer than 40 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a body. When fewer than 40 input bits
+ are available in an input group, bits with value zero are added (on
+ the right) to form an integral number of 5-bit groups. Padding at
+ the end of the data is performed using the "=" character. Since all
+ base 32 input is an integral number of octets, only the following
+ cases can arise:
+
+ (1) The final quantum of encoding input is an integral multiple of 40
+ bits; here, the final unit of encoded output will be an integral
+ multiple of 8 characters with no "=" padding.
+
+ (2) The final quantum of encoding input is exactly 8 bits; here, the
+ final unit of encoded output will be two characters followed by
+ six "=" padding characters.
+
+ (3) The final quantum of encoding input is exactly 16 bits; here, the
+ final unit of encoded output will be four characters followed by
+ four "=" padding characters.
+
+ (4) The final quantum of encoding input is exactly 24 bits; here, the
+ final unit of encoded output will be five characters followed by
+ three "=" padding characters.
+
+ (5) The final quantum of encoding input is exactly 32 bits; here, the
+ final unit of encoded output will be seven characters followed by
+ one "=" padding character.
+
+
+
+
+
+Josefsson Standards Track [Page 9]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+7. Base 32 Encoding with Extended Hex Alphabet
+
+ The following description of base 32 is derived from [7]. This
+ encoding may be referred to as "base32hex". This encoding should not
+ be regarded as the same as the "base32" encoding and should not be
+ referred to as only "base32". This encoding is used by, e.g.,
+ NextSECure3 (NSEC3) [10].
+
+ One property with this alphabet, which the base64 and base32
+ alphabets lack, is that encoded data maintains its sort order when
+ the encoded data is compared bit-wise.
+
+ This encoding is identical to the previous one, except for the
+ alphabet. The new alphabet is found in Table 4.
+
+ Table 4: The "Extended Hex" Base 32 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 0 9 9 18 I 27 R
+ 1 1 10 A 19 J 28 S
+ 2 2 11 B 20 K 29 T
+ 3 3 12 C 21 L 30 U
+ 4 4 13 D 22 M 31 V
+ 5 5 14 E 23 N
+ 6 6 15 F 24 O (pad) =
+ 7 7 16 G 25 P
+ 8 8 17 H 26 Q
+
+8. Base 16 Encoding
+
+ The following description is original but analogous to previous
+ descriptions. Essentially, Base 16 encoding is the standard case-
+ insensitive hex encoding and may be referred to as "base16" or "hex".
+
+ A 16-character subset of US-ASCII is used, enabling 4 bits to be
+ represented per printable character.
+
+ The encoding process represents 8-bit groups (octets) of input bits
+ as output strings of 2 encoded characters. Proceeding from left to
+ right, an 8-bit input is taken from the input data. These 8 bits are
+ then treated as 2 concatenated 4-bit groups, each of which is
+ translated into a single character in the base 16 alphabet.
+
+ Each 4-bit group is used as an index into an array of 16 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+
+
+
+
+Josefsson Standards Track [Page 10]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+ Table 5: The Base 16 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 0 4 4 8 8 12 C
+ 1 1 5 5 9 9 13 D
+ 2 2 6 6 10 A 14 E
+ 3 3 7 7 11 B 15 F
+
+ Unlike base 32 and base 64, no special padding is necessary since a
+ full code word is always available.
+
+9. Illustrations and Examples
+
+ To translate between binary and a base encoding, the input is stored
+ in a structure, and the output is extracted. The case for base 64 is
+ displayed in the following figure, borrowed from [5].
+
+ +--first octet--+-second octet--+--third octet--+
+ |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|
+ +-----------+---+-------+-------+---+-----------+
+ |5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|5 4 3 2 1 0|
+ +--1.index--+--2.index--+--3.index--+--4.index--+
+
+ The case for base 32 is shown in the following figure, borrowed from
+ [7]. Each successive character in a base-32 value represents 5
+ successive bits of the underlying octet sequence. Thus, each group
+ of 8 characters represents a sequence of 5 octets (40 bits).
+
+ 1 2 3
+ 01234567 89012345 67890123 45678901 23456789
+ +--------+--------+--------+--------+--------+
+ |< 1 >< 2| >< 3 ><|.4 >< 5.|>< 6 ><.|7 >< 8 >|
+ +--------+--------+--------+--------+--------+
+ <===> 8th character
+ <====> 7th character
+ <===> 6th character
+ <====> 5th character
+ <====> 4th character
+ <===> 3rd character
+ <====> 2nd character
+ <===> 1st character
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 11]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+ The following example of Base64 data is from [5], with corrections.
+
+ Input data: 0x14fb9c03d97e
+ Hex: 1 4 f b 9 c | 0 3 d 9 7 e
+ 8-bit: 00010100 11111011 10011100 | 00000011 11011001 01111110
+ 6-bit: 000101 001111 101110 011100 | 000000 111101 100101 111110
+ Decimal: 5 15 46 28 0 61 37 62
+ Output: F P u c A 9 l +
+
+ Input data: 0x14fb9c03d9
+ Hex: 1 4 f b 9 c | 0 3 d 9
+ 8-bit: 00010100 11111011 10011100 | 00000011 11011001
+ pad with 00
+ 6-bit: 000101 001111 101110 011100 | 000000 111101 100100
+ Decimal: 5 15 46 28 0 61 36
+ pad with =
+ Output: F P u c A 9 k =
+
+ Input data: 0x14fb9c03
+ Hex: 1 4 f b 9 c | 0 3
+ 8-bit: 00010100 11111011 10011100 | 00000011
+ pad with 0000
+ 6-bit: 000101 001111 101110 011100 | 000000 110000
+ Decimal: 5 15 46 28 0 48
+ pad with = =
+ Output: F P u c A w = =
+
+10. Test Vectors
+
+ BASE64("") = ""
+
+ BASE64("f") = "Zg=="
+
+ BASE64("fo") = "Zm8="
+
+ BASE64("foo") = "Zm9v"
+
+ BASE64("foob") = "Zm9vYg=="
+
+ BASE64("fooba") = "Zm9vYmE="
+
+ BASE64("foobar") = "Zm9vYmFy"
+
+ BASE32("") = ""
+
+ BASE32("f") = "MY======"
+
+ BASE32("fo") = "MZXQ===="
+
+
+
+Josefsson Standards Track [Page 12]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+ BASE32("foo") = "MZXW6==="
+
+ BASE32("foob") = "MZXW6YQ="
+
+ BASE32("fooba") = "MZXW6YTB"
+
+ BASE32("foobar") = "MZXW6YTBOI======"
+
+ BASE32-HEX("") = ""
+
+ BASE32-HEX("f") = "CO======"
+
+ BASE32-HEX("fo") = "CPNG===="
+
+ BASE32-HEX("foo") = "CPNMU==="
+
+ BASE32-HEX("foob") = "CPNMUOG="
+
+ BASE32-HEX("fooba") = "CPNMUOJ1"
+
+ BASE32-HEX("foobar") = "CPNMUOJ1E8======"
+
+ BASE16("") = ""
+
+ BASE16("f") = "66"
+
+ BASE16("fo") = "666F"
+
+ BASE16("foo") = "666F6F"
+
+ BASE16("foob") = "666F6F62"
+
+ BASE16("fooba") = "666F6F6261"
+
+ BASE16("foobar") = "666F6F626172"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 13]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+11. ISO C99 Implementation of Base64
+
+ An ISO C99 implementation of Base64 encoding and decoding that is
+ believed to follow all recommendations in this RFC is available from:
+
+ http://josefsson.org/base-encoding/
+
+ This code is not normative.
+
+ The code could not be included in this RFC for procedural reasons
+ (RFC 3978 section 5.4).
+
+12. Security Considerations
+
+ When base encoding and decoding is implemented, care should be taken
+ not to introduce vulnerabilities to buffer overflow attacks, or other
+ attacks on the implementation. A decoder should not break on invalid
+ input including, e.g., embedded NUL characters (ASCII 0).
+
+ If non-alphabet characters are ignored, instead of causing rejection
+ of the entire encoding (as recommended), a covert channel that can be
+ used to "leak" information is made possible. The ignored characters
+ could also be used for other nefarious purposes, such as to avoid a
+ string equality comparison or to trigger implementation bugs. The
+ implications of ignoring non-alphabet characters should be understood
+ in applications that do not follow the recommended practice.
+ Similarly, when the base 16 and base 32 alphabets are handled case
+ insensitively, alteration of case can be used to leak information or
+ make string equality comparisons fail.
+
+ When padding is used, there are some non-significant bits that
+ warrant security concerns, as they may be abused to leak information
+ or used to bypass string equality comparisons or to trigger
+ implementation problems.
+
+ Base encoding visually hides otherwise easily recognized information,
+ such as passwords, but does not provide any computational
+ confidentiality. This has been known to cause security incidents
+ when, e.g., a user reports details of a network protocol exchange
+ (perhaps to illustrate some other problem) and accidentally reveals
+ the password because she is unaware that the base encoding does not
+ protect the password.
+
+ Base encoding adds no entropy to the plaintext, but it does increase
+ the amount of plaintext available and provide a signature for
+ cryptanalysis in the form of a characteristic probability
+ distribution.
+
+
+
+
+Josefsson Standards Track [Page 14]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+13. Changes Since RFC 3548
+
+ Added the "base32 extended hex alphabet", needed to preserve sort
+ order of encoded data.
+
+ Referenced IMAP for the special Base64 encoding used there.
+
+ Fixed the example copied from RFC 2440.
+
+ Added security consideration about providing a signature for
+ cryptoanalysis.
+
+ Added test vectors.
+
+ Fixed typos.
+
+14. Acknowledgements
+
+ Several people offered comments and/or suggestions, including John E.
+ Hadstate, Tony Hansen, Gordon Mohr, John Myers, Chris Newman, and
+ Andrew Sieber. Text used in this document are based on earlier RFCs
+ describing specific uses of various base encodings. The author
+ acknowledges the RSA Laboratories for supporting the work that led to
+ this document.
+
+ This revised version is based in parts on comments and/or suggestions
+ made by Roy Arends, Eric Blake, Brian E Carpenter, Elwyn Davies, Bill
+ Fenner, Sam Hartman, Ted Hardie, Per Hygum, Jelte Jansen, Clement
+ Kent, Tero Kivinen, Paul Kwiatkowski, and Ben Laurie.
+
+15. Copying Conditions
+
+ Copyright (c) 2000-2006 Simon Josefsson
+
+ Regarding the abstract and sections 1, 3, 8, 10, 12, 13, and 14 of
+ this document, that were written by Simon Josefsson ("the author",
+ for the remainder of this section), the author makes no guarantees
+ and is not responsible for any damage resulting from its use. The
+ author grants irrevocable permission to anyone to use, modify, and
+ distribute it in any way that does not diminish the rights of anyone
+ else to use, modify, and distribute it, provided that redistributed
+ derivative works do not contain misleading author or version
+ information and do not falsely purport to be IETF RFC documents.
+ Derivative works need not be licensed under similar terms.
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 15]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+16. References
+
+16.1. Normative References
+
+ [1] Cerf, V., "ASCII format for network interchange", RFC 20,
+ October 1969.
+
+ [2] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+16.2. Informative References
+
+ [3] Linn, J., "Privacy Enhancement for Internet Electronic Mail:
+ Part I: Message Encryption and Authentication Procedures", RFC
+ 1421, February 1993.
+
+ [4] Freed, N. and N. Borenstein, "Multipurpose Internet Mail
+ Extensions (MIME) Part One: Format of Internet Message Bodies",
+ RFC 2045, November 1996.
+
+ [5] Callas, J., Donnerhacke, L., Finney, H., and R. Thayer,
+ "OpenPGP Message Format", RFC 2440, November 1998.
+
+ [6] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "DNS Security Introduction and Requirements", RFC 4033, March
+ 2005.
+
+ [7] Klyne, G. and L. Masinter, "Identifying Composite Media
+ Features", RFC 2938, September 2000.
+
+ [8] Crispin, M., "INTERNET MESSAGE ACCESS PROTOCOL - VERSION
+ 4rev1", RFC 3501, March 2003.
+
+ [9] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
+ Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986,
+ January 2005.
+
+ [10] Laurie, B., Sisson, G., Arends, R., and D. Blacka, "DNSSEC Hash
+ Authenticated Denial of Existence", Work in Progress, June
+ 2006.
+
+ [11] Myers, J., "SASL GSSAPI mechanisms", Work in Progress, May
+ 2000.
+
+ [12] Wilcox-O'Hearn, B., "Post to P2P-hackers mailing list",
+ http://zgp.org/pipermail/p2p-hackers/2001-September/
+ 000315.html, September 2001.
+
+
+
+
+Josefsson Standards Track [Page 16]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+Author's Address
+
+ Simon Josefsson
+ SJD
+ EMail: simon@josefsson.org
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 17]
+
+RFC 4648 Base-N Encodings October 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Josefsson Standards Track [Page 18]
+
diff --git a/doc/rfc/rfc4701.txt b/doc/rfc/rfc4701.txt
new file mode 100644
index 0000000..03e3c54
--- /dev/null
+++ b/doc/rfc/rfc4701.txt
@@ -0,0 +1,675 @@
+
+
+
+
+
+
+Network Working Group M. Stapp
+Request for Comments: 4701 Cisco Systems, Inc.
+Category: Standards Track T. Lemon
+ Nominum, Inc.
+ A. Gustafsson
+ Araneus Information Systems Oy
+ October 2006
+
+
+ A DNS Resource Record (RR) for Encoding
+ Dynamic Host Configuration Protocol (DHCP) Information (DHCID RR)
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (2006).
+
+Abstract
+
+ It is possible for Dynamic Host Configuration Protocol (DHCP) clients
+ to attempt to update the same DNS Fully Qualified Domain Name (FQDN)
+ or to update a DNS FQDN that has been added to the DNS for another
+ purpose as they obtain DHCP leases. Whether the DHCP server or the
+ clients themselves perform the DNS updates, conflicts can arise. To
+ resolve such conflicts, RFC 4703 proposes storing client identifiers
+ in the DNS to unambiguously associate domain names with the DHCP
+ clients to which they refer. This memo defines a distinct Resource
+ Record (RR) type for this purpose for use by DHCP clients and
+ servers: the "DHCID" RR.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stapp, et al. Standards Track [Page 1]
+
+RFC 4701 The DHCID RR October 2006
+
+
+Table of Contents
+
+ 1. Introduction ....................................................3
+ 2. Terminology .....................................................3
+ 3. The DHCID RR ....................................................3
+ 3.1. DHCID RDATA Format .........................................3
+ 3.2. DHCID Presentation Format ..................................4
+ 3.3. The DHCID RR Identifier Type Codes .........................4
+ 3.4. The DHCID RR Digest Type Code ..............................4
+ 3.5. Computation of the RDATA ...................................5
+ 3.5.1. Using the Client's DUID .............................5
+ 3.5.2. Using the Client Identifier Option ..................6
+ 3.5.3. Using the Client's htype and chaddr .................6
+ 3.6. Examples ...................................................6
+ 3.6.1. Example 1 ...........................................6
+ 3.6.2. Example 2 ...........................................7
+ 3.6.3. Example 3 ...........................................7
+ 4. Use of the DHCID RR .............................................8
+ 5. Updater Behavior ................................................8
+ 6. Security Considerations .........................................8
+ 7. IANA Considerations .............................................9
+ 8. Acknowledgements ................................................9
+ 9. References ......................................................9
+ 9.1. Normative References .......................................9
+ 9.2. Informative References ....................................10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stapp, et al. Standards Track [Page 2]
+
+RFC 4701 The DHCID RR October 2006
+
+
+1. Introduction
+
+ A set of procedures to allow DHCP [7] [11] clients and servers to
+ automatically update the DNS ([3], [4]) is proposed in [1].
+
+ Conflicts can arise if multiple DHCP clients wish to use the same DNS
+ name or a DHCP client attempts to use a name added for another
+ purpose. To resolve such conflicts, [1] proposes storing client
+ identifiers in the DNS to unambiguously associate domain names with
+ the DHCP clients using them. In the interest of clarity, it is
+ preferable for this DHCP information to use a distinct RR type. This
+ memo defines a distinct RR for this purpose for use by DHCP clients
+ or servers: the "DHCID" RR.
+
+ In order to obscure potentially sensitive client identifying
+ information, the data stored is the result of a one-way SHA-256 hash
+ computation. The hash includes information from the DHCP client's
+ message as well as the domain name itself, so that the data stored in
+ the DHCID RR will be dependent on both the client identification used
+ in the DHCP protocol interaction and the domain name. This means
+ that the DHCID RDATA will vary if a single client is associated over
+ time with more than one name. This makes it difficult to 'track' a
+ client as it is associated with various domain names.
+
+2. Terminology
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [2].
+
+3. The DHCID RR
+
+ The DHCID RR is defined with mnemonic DHCID and type code 49. The
+ DHCID RR is only defined in the IN class. DHCID RRs cause no
+ additional section processing.
+
+3.1. DHCID RDATA Format
+
+ The RDATA section of a DHCID RR in transmission contains RDLENGTH
+ octets of binary data. The format of this data and its
+ interpretation by DHCP servers and clients are described below.
+
+ DNS software should consider the RDATA section to be opaque. DHCP
+ clients or servers use the DHCID RR to associate a DHCP client's
+ identity with a DNS name, so that multiple DHCP clients and servers
+ may deterministically perform dynamic DNS updates to the same zone.
+ From the updater's perspective, the DHCID resource record RDATA
+ consists of a 2-octet identifier type, in network byte order,
+
+
+
+Stapp, et al. Standards Track [Page 3]
+
+RFC 4701 The DHCID RR October 2006
+
+
+ followed by a 1-octet digest type, followed by one or more octets
+ representing the actual identifier:
+
+ < 2 octets > Identifier type code
+ < 1 octet > Digest type code
+ < n octets > Digest (length depends on digest type)
+
+3.2. DHCID Presentation Format
+
+ In DNS master files, the RDATA is represented as a single block in
+ base-64 encoding identical to that used for representing binary data
+ in [8], Section 3. The data may be divided up into any number of
+ white-space-separated substrings, down to single base-64 digits,
+ which are concatenated to form the complete RDATA. These substrings
+ can span lines using the standard parentheses.
+
+3.3. The DHCID RR Identifier Type Codes
+
+ The DHCID RR Identifier Type Code specifies what data from the DHCP
+ client's request was used as input into the hash function. The
+ identifier type codes are defined in a registry maintained by IANA,
+ as specified in Section 7. The initial list of assigned values for
+ the identifier type code and that type's identifier is:
+
+
+ +------------------+------------------------------------------------+
+ | Identifier Type | Identifier |
+ | Code | |
+ +------------------+------------------------------------------------+
+ | 0x0000 | The 1-octet 'htype' followed by 'hlen' octets |
+ | | of 'chaddr' from a DHCPv4 client's DHCPREQUEST |
+ | | [7]. |
+ | 0x0001 | The data octets (i.e., the Type and |
+ | | Client-Identifier fields) from a DHCPv4 |
+ | | client's Client Identifier option [10]. |
+ | 0x0002 | The client's DUID (i.e., the data octets of a |
+ | | DHCPv6 client's Client Identifier option [11] |
+ | | or the DUID field from a DHCPv4 client's |
+ | | Client Identifier option [6]). |
+ | 0x0003 - 0xfffe | Undefined; available to be assigned by IANA. |
+ | 0xffff | Undefined; RESERVED. |
+ +------------------+------------------------------------------------+
+
+3.4. The DHCID RR Digest Type Code
+
+ The DHCID RR Digest Type Code is an identifier for the digest
+ algorithm used. The digest is calculated over an identifier and the
+ canonical FQDN as described in the next section.
+
+
+
+Stapp, et al. Standards Track [Page 4]
+
+RFC 4701 The DHCID RR October 2006
+
+
+ The digest type codes are defined in a registry maintained by IANA,
+ as specified in Section 7. The initial list of assigned values for
+ the digest type codes is: value 0 is reserved, and value 1 is
+ SHA-256. Reserving other types requires IETF standards action.
+ Defining new values will also require IETF standards action to
+ document how DNS updaters are to deal with multiple digest types.
+
+3.5. Computation of the RDATA
+
+ The DHCID RDATA is formed by concatenating the 2-octet identifier
+ type code with variable-length data.
+
+ The RDATA for all type codes other than 0xffff, which is reserved for
+ future expansion, is formed by concatenating the 2-octet identifier
+ type code, the 1-octet digest type code, and the digest value (32
+ octets for SHA-256).
+
+ < identifier-type > < digest-type > < digest >
+
+ The input to the digest hash function is defined to be:
+
+ digest = SHA-256(< identifier > < FQDN >)
+
+ The FQDN is represented in the buffer in the canonical wire format as
+ described in [9], Section 6.2. The identifier type code and the
+ identifier are related as specified in Section 3.3: the identifier
+ type code describes the source of the identifier.
+
+ A DHCPv4 updater uses the 0x0002 type code if a Client Identifier
+ option is present in the DHCPv4 messages and it is encoded as
+ specified in [6]. Otherwise, the updater uses 0x0001 if a Client
+ Identifier option is present, and 0x0000 if not.
+
+ A DHCPv6 updater always uses the 0x0002 type code.
+
+3.5.1. Using the Client's DUID
+
+ When the updater is using the Client's DUID (either from a DHCPv6
+ Client Identifier option or from a portion of the DHCPv4 Client
+ Identifier option encoded as specified in [6]), the first two octets
+ of the DHCID RR MUST be 0x0002, in network byte order. The third
+ octet is the digest type code (1 for SHA-256). The rest of the DHCID
+ RR MUST contain the results of computing the SHA-256 hash across the
+ octets of the DUID followed by the FQDN.
+
+
+
+
+
+
+
+Stapp, et al. Standards Track [Page 5]
+
+RFC 4701 The DHCID RR October 2006
+
+
+3.5.2. Using the Client Identifier Option
+
+ When the updater is using the DHCPv4 Client Identifier option sent by
+ the client in its DHCPREQUEST message, the first two octets of the
+ DHCID RR MUST be 0x0001, in network byte order. The third octet is
+ the digest type code (1 for SHA-256). The rest of the DHCID RR MUST
+ contain the results of computing the SHA-256 hash across the data
+ octets (i.e., the Type and Client-Identifier fields) of the option,
+ followed by the FQDN.
+
+3.5.3. Using the Client's htype and chaddr
+
+ When the updater is using the client's link-layer address as the
+ identifier, the first two octets of the DHCID RDATA MUST be zero.
+ The third octet is the digest type code (1 for SHA-256). To generate
+ the rest of the resource record, the updater computes a one-way hash
+ using the SHA-256 algorithm across a buffer containing the client's
+ network hardware type, link-layer address, and the FQDN data.
+ Specifically, the first octet of the buffer contains the network
+ hardware type as it appeared in the DHCP 'htype' field of the
+ client's DHCPREQUEST message. All of the significant octets of the
+ 'chaddr' field in the client's DHCPREQUEST message follow, in the
+ same order in which the octets appear in the DHCPREQUEST message.
+ The number of significant octets in the 'chaddr' field is specified
+ in the 'hlen' field of the DHCPREQUEST message. The FQDN data, as
+ specified above, follows.
+
+3.6. Examples
+
+3.6.1. Example 1
+
+ A DHCP server allocates the IPv6 address 2001:DB8::1234:5678 to a
+ client that included the DHCPv6 client-identifier option data 00:01:
+ 00:06:41:2d:f1:66:01:02:03:04:05:06 in its DHCPv6 request. The
+ server updates the name "chi6.example.com" on the client's behalf and
+ uses the DHCP client identifier option data as input in forming a
+ DHCID RR. The DHCID RDATA is formed by setting the two type octets
+ to the value 0x0002, the 1-octet digest type to 1 for SHA-256, and
+ performing a SHA-256 hash computation across a buffer containing the
+ 14 octets from the client-id option and the FQDN (represented as
+ specified in Section 3.5).
+
+ chi6.example.com. AAAA 2001:DB8::1234:5678
+ chi6.example.com. DHCID ( AAIBY2/AuCccgoJbsaxcQc9TUapptP69l
+ OjxfNuVAA2kjEA= )
+
+ If the DHCID RR type is not supported, the RDATA would be encoded
+ [13] as:
+
+
+
+Stapp, et al. Standards Track [Page 6]
+
+RFC 4701 The DHCID RR October 2006
+
+
+ \# 35 ( 000201636fc0b8271c82825bb1ac5c41cf5351aa69b4febd94e8f17cd
+ b95000da48c40 )
+
+3.6.2. Example 2
+
+ A DHCP server allocates the IPv4 address 192.0.2.2 to a client that
+ included the DHCP client-identifier option data 01:07:08:09:0a:0b:0c
+ in its DHCP request. The server updates the name "chi.example.com"
+ on the client's behalf and uses the DHCP client identifier option
+ data as input in forming a DHCID RR. The DHCID RDATA is formed by
+ setting the two type octets to the value 0x0001, the 1-octet digest
+ type to 1 for SHA-256, and performing a SHA-256 hash computation
+ across a buffer containing the seven octets from the client-id option
+ and the FQDN (represented as specified in Section 3.5).
+
+ chi.example.com. A 192.0.2.2
+ chi.example.com. DHCID ( AAEBOSD+XR3Os/0LozeXVqcNc7FwCfQdW
+ L3b/NaiUDlW2No= )
+
+ If the DHCID RR type is not supported, the RDATA would be encoded
+ [13] as:
+
+ \# 35 ( 0001013920fe5d1dceb3fd0ba3379756a70d73b17009f41d58bddbfcd
+ 6a2503956d8da )
+
+3.6.3. Example 3
+
+ A DHCP server allocating the IPv4 address 192.0.2.3 to a client with
+ the Ethernet MAC address 01:02:03:04:05:06 using domain name
+ "client.example.com" uses the client's link-layer address to identify
+ the client. The DHCID RDATA is composed by setting the two type
+ octets to zero, the 1-octet digest type to 1 for SHA-256, and
+ performing an SHA-256 hash computation across a buffer containing the
+ 1-octet 'htype' value for Ethernet, 0x01, followed by the six octets
+ of the Ethernet MAC address, and the domain name (represented as
+ specified in Section 3.5).
+
+ client.example.com. A 192.0.2.3
+ client.example.com. DHCID ( AAABxLmlskllE0MVjd57zHcWmEH3pCQ6V
+ ytcKD//7es/deY= )
+
+ If the DHCID RR type is not supported, the RDATA would be encoded
+ [13] as:
+
+ \# 35 ( 000001c4b9a5b249651343158dde7bcc77169841f7a4243a572b5c283
+ fffedeb3f75e6 )
+
+
+
+
+
+Stapp, et al. Standards Track [Page 7]
+
+RFC 4701 The DHCID RR October 2006
+
+
+4. Use of the DHCID RR
+
+ This RR MUST NOT be used for any purpose other than that detailed in
+ [1]. Although this RR contains data that is opaque to DNS servers,
+ the data must be consistent across all entities that update and
+ interpret this record. Therefore, new data formats may only be
+ defined through actions of the DHC Working Group, as a result of
+ revising [1].
+
+5. Updater Behavior
+
+ The data in the DHCID RR allows updaters to determine whether more
+ than one DHCP client desires to use a particular FQDN. This allows
+ site administrators to establish policy about DNS updates. The DHCID
+ RR does not establish any policy itself.
+
+ Updaters use data from a DHCP client's request and the domain name
+ that the client desires to use to compute a client identity hash, and
+ then compare that hash to the data in any DHCID RRs on the name that
+ they wish to associate with the client's IP address. If an updater
+ discovers DHCID RRs whose RDATA does not match the client identity
+ that they have computed, the updater SHOULD conclude that a different
+ client is currently associated with the name in question. The
+ updater SHOULD then proceed according to the site's administrative
+ policy. That policy might dictate that a different name be selected,
+ or it might permit the updater to continue.
+
+6. Security Considerations
+
+ The DHCID record as such does not introduce any new security problems
+ into the DNS. In order to obscure the client's identity information,
+ a one-way hash is used. Further, in order to make it difficult to
+ 'track' a client by examining the names associated with a particular
+ hash value, the FQDN is included in the hash computation. Thus, the
+ RDATA is dependent on both the DHCP client identification data and on
+ each FQDN associated with the client.
+
+ However, it should be noted that an attacker that has some knowledge,
+ such as of MAC addresses commonly used in DHCP client identification
+ data, may be able to discover the client's DHCP identify by using a
+ brute-force attack. Even without any additional knowledge, the
+ number of unknown bits used in computing the hash is typically only
+ 48 to 80.
+
+ Administrators should be wary of permitting unsecured DNS updates to
+ zones, whether or not they are exposed to the global Internet. Both
+ DHCP clients and servers SHOULD use some form of update
+ authentication (e.g., [12]) when performing DNS updates.
+
+
+
+Stapp, et al. Standards Track [Page 8]
+
+RFC 4701 The DHCID RR October 2006
+
+
+7. IANA Considerations
+
+ IANA has allocated a DNS RR type number for the DHCID record type.
+
+ This specification defines a new number-space for the 2-octet
+ identifier type codes associated with the DHCID RR. IANA has
+ established a registry of the values for this number-space. Three
+ initial values are assigned in Section 3.3, and the value 0xFFFF is
+ reserved for future use. New DHCID RR identifier type codes are
+ assigned through Standards Action, as defined in [5].
+
+ This specification defines a new number-space for the 1-octet digest
+ type codes associated with the DHCID RR. IANA has established a
+ registry of the values for this number-space. Two initial values are
+ assigned in Section 3.4. New DHCID RR digest type codes are assigned
+ through Standards Action, as defined in [5].
+
+8. Acknowledgements
+
+ Many thanks to Harald Alvestrand, Ralph Droms, Olafur Gudmundsson,
+ Sam Hartman, Josh Littlefield, Pekka Savola, and especially Bernie
+ Volz for their review and suggestions.
+
+9. References
+
+9.1. Normative References
+
+ [1] Stapp, M. and B. Volz, "Resolution of Fully Qualified Domain
+ Name (FQDN) Conflicts among Dynamic Host Configuration Protocol
+ (DHCP) Clients", RFC 4703, October 2006.
+
+ [2] Bradner, S., "Key words for use in RFCs to Indicate Requirement
+ Levels", BCP 14, RFC 2119, March 1997.
+
+ [3] Mockapetris, P., "Domain names - concepts and facilities",
+ STD 13, RFC 1034, November 1987.
+
+ [4] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [5] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA
+ Considerations Section in RFCs", BCP 26, RFC 2434, October 1998.
+
+ [6] Lemon, T. and B. Sommerfeld, "Node-specific Client Identifiers
+ for Dynamic Host Configuration Protocol Version Four (DHCPv4)",
+ RFC 4361, February 2006.
+
+
+
+
+
+Stapp, et al. Standards Track [Page 9]
+
+RFC 4701 The DHCID RR October 2006
+
+
+9.2. Informative References
+
+ [7] Droms, R., "Dynamic Host Configuration Protocol", RFC 2131,
+ March 1997.
+
+ [8] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings",
+ RFC 3548, July 2003.
+
+ [9] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose,
+ "Resource Records for the DNS Security Extensions", RFC 4034,
+ March 2005.
+
+ [10] Alexander, S. and R. Droms, "DHCP Options and BOOTP Vendor
+ Extensions", RFC 2132, March 1997.
+
+ [11] Droms, R., Bound, J., Volz, B., Lemon, T., Perkins, C., and M.
+ Carney, "Dynamic Host Configuration Protocol for IPv6
+ (DHCPv6)", RFC 3315, July 2003.
+
+ [12] Vixie, P., Gudmundsson, O., Eastlake, D., and B. Wellington,
+ "Secret Key Transaction Authentication for DNS (TSIG)",
+ RFC 2845, May 2000.
+
+ [13] Gustafsson, A., "Handling of Unknown DNS Resource Record (RR)
+ Types", RFC 3597, September 2003.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stapp, et al. Standards Track [Page 10]
+
+RFC 4701 The DHCID RR October 2006
+
+
+Authors' Addresses
+
+ Mark Stapp
+ Cisco Systems, Inc.
+ 1414 Massachusetts Ave.
+ Boxborough, MA 01719
+ USA
+
+ Phone: 978.936.1535
+ EMail: mjs@cisco.com
+
+
+ Ted Lemon
+ Nominum, Inc.
+ 950 Charter St.
+ Redwood City, CA 94063
+ USA
+
+ EMail: mellon@nominum.com
+
+
+ Andreas Gustafsson
+ Araneus Information Systems Oy
+ Ulappakatu 1
+ 02320 Espoo
+ Finland
+
+ EMail: gson@araneus.fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stapp, et al. Standards Track [Page 11]
+
+RFC 4701 The DHCID RR October 2006
+
+
+Full Copyright Statement
+
+ Copyright (C) The Internet Society (2006).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+ ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+ INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+Acknowledgement
+
+ Funding for the RFC Editor function is provided by the IETF
+ Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Stapp, et al. Standards Track [Page 12]
+
diff --git a/doc/rfc/rfc5155.txt b/doc/rfc/rfc5155.txt
new file mode 100644
index 0000000..d4b7297
--- /dev/null
+++ b/doc/rfc/rfc5155.txt
@@ -0,0 +1,2915 @@
+
+
+
+
+
+
+Network Working Group B. Laurie
+Request for Comments: 5155 G. Sisson
+Category: Standards Track R. Arends
+ Nominet
+ D. Blacka
+ VeriSign, Inc.
+ March 2008
+
+
+ DNS Security (DNSSEC) Hashed Authenticated Denial of Existence
+
+Status of This Memo
+
+ This document specifies an Internet standards track protocol for the
+ Internet community, and requests discussion and suggestions for
+ improvements. Please refer to the current edition of the "Internet
+ Official Protocol Standards" (STD 1) for the standardization state
+ and status of this protocol. Distribution of this memo is unlimited.
+
+Abstract
+
+ The Domain Name System Security (DNSSEC) Extensions introduced the
+ NSEC resource record (RR) for authenticated denial of existence.
+ This document introduces an alternative resource record, NSEC3, which
+ similarly provides authenticated denial of existence. However, it
+ also provides measures against zone enumeration and permits gradual
+ expansion of delegation-centric zones.
+
+Table of Contents
+
+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.1. Rationale . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.2. Requirements . . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.3. Terminology . . . . . . . . . . . . . . . . . . . . . . . 5
+ 2. Backwards Compatibility . . . . . . . . . . . . . . . . . . . 6
+ 3. The NSEC3 Resource Record . . . . . . . . . . . . . . . . . . 7
+ 3.1. RDATA Fields . . . . . . . . . . . . . . . . . . . . . . . 8
+ 3.1.1. Hash Algorithm . . . . . . . . . . . . . . . . . . . . 8
+ 3.1.2. Flags . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 3.1.3. Iterations . . . . . . . . . . . . . . . . . . . . . . 8
+ 3.1.4. Salt Length . . . . . . . . . . . . . . . . . . . . . 8
+ 3.1.5. Salt . . . . . . . . . . . . . . . . . . . . . . . . . 8
+ 3.1.6. Hash Length . . . . . . . . . . . . . . . . . . . . . 9
+ 3.1.7. Next Hashed Owner Name . . . . . . . . . . . . . . . . 9
+ 3.1.8. Type Bit Maps . . . . . . . . . . . . . . . . . . . . 9
+ 3.2. NSEC3 RDATA Wire Format . . . . . . . . . . . . . . . . . 9
+ 3.2.1. Type Bit Maps Encoding . . . . . . . . . . . . . . . . 10
+ 3.3. Presentation Format . . . . . . . . . . . . . . . . . . . 11
+
+
+
+Laurie, et al. Standards Track [Page 1]
+
+RFC 5155 NSEC3 March 2008
+
+
+ 4. The NSEC3PARAM Resource Record . . . . . . . . . . . . . . . . 12
+ 4.1. RDATA Fields . . . . . . . . . . . . . . . . . . . . . . . 12
+ 4.1.1. Hash Algorithm . . . . . . . . . . . . . . . . . . . . 12
+ 4.1.2. Flag Fields . . . . . . . . . . . . . . . . . . . . . 12
+ 4.1.3. Iterations . . . . . . . . . . . . . . . . . . . . . . 13
+ 4.1.4. Salt Length . . . . . . . . . . . . . . . . . . . . . 13
+ 4.1.5. Salt . . . . . . . . . . . . . . . . . . . . . . . . . 13
+ 4.2. NSEC3PARAM RDATA Wire Format . . . . . . . . . . . . . . . 13
+ 4.3. Presentation Format . . . . . . . . . . . . . . . . . . . 14
+ 5. Calculation of the Hash . . . . . . . . . . . . . . . . . . . 14
+ 6. Opt-Out . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
+ 7. Authoritative Server Considerations . . . . . . . . . . . . . 16
+ 7.1. Zone Signing . . . . . . . . . . . . . . . . . . . . . . . 16
+ 7.2. Zone Serving . . . . . . . . . . . . . . . . . . . . . . . 17
+ 7.2.1. Closest Encloser Proof . . . . . . . . . . . . . . . . 18
+ 7.2.2. Name Error Responses . . . . . . . . . . . . . . . . . 19
+ 7.2.3. No Data Responses, QTYPE is not DS . . . . . . . . . . 19
+ 7.2.4. No Data Responses, QTYPE is DS . . . . . . . . . . . . 19
+ 7.2.5. Wildcard No Data Responses . . . . . . . . . . . . . . 19
+ 7.2.6. Wildcard Answer Responses . . . . . . . . . . . . . . 20
+ 7.2.7. Referrals to Unsigned Subzones . . . . . . . . . . . . 20
+ 7.2.8. Responding to Queries for NSEC3 Owner Names . . . . . 20
+ 7.2.9. Server Response to a Run-Time Collision . . . . . . . 21
+ 7.3. Secondary Servers . . . . . . . . . . . . . . . . . . . . 21
+ 7.4. Zones Using Unknown Hash Algorithms . . . . . . . . . . . 21
+ 7.5. Dynamic Update . . . . . . . . . . . . . . . . . . . . . . 21
+ 8. Validator Considerations . . . . . . . . . . . . . . . . . . . 23
+ 8.1. Responses with Unknown Hash Types . . . . . . . . . . . . 23
+ 8.2. Verifying NSEC3 RRs . . . . . . . . . . . . . . . . . . . 23
+ 8.3. Closest Encloser Proof . . . . . . . . . . . . . . . . . . 23
+ 8.4. Validating Name Error Responses . . . . . . . . . . . . . 24
+ 8.5. Validating No Data Responses, QTYPE is not DS . . . . . . 24
+ 8.6. Validating No Data Responses, QTYPE is DS . . . . . . . . 24
+ 8.7. Validating Wildcard No Data Responses . . . . . . . . . . 25
+ 8.8. Validating Wildcard Answer Responses . . . . . . . . . . . 25
+ 8.9. Validating Referrals to Unsigned Subzones . . . . . . . . 25
+ 9. Resolver Considerations . . . . . . . . . . . . . . . . . . . 26
+ 9.1. NSEC3 Resource Record Caching . . . . . . . . . . . . . . 26
+ 9.2. Use of the AD Bit . . . . . . . . . . . . . . . . . . . . 26
+ 10. Special Considerations . . . . . . . . . . . . . . . . . . . . 26
+ 10.1. Domain Name Length Restrictions . . . . . . . . . . . . . 26
+ 10.2. DNAME at the Zone Apex . . . . . . . . . . . . . . . . . . 27
+ 10.3. Iterations . . . . . . . . . . . . . . . . . . . . . . . . 27
+ 10.4. Transitioning a Signed Zone from NSEC to NSEC3 . . . . . . 28
+ 10.5. Transitioning a Signed Zone from NSEC3 to NSEC . . . . . . 28
+ 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 29
+ 12. Security Considerations . . . . . . . . . . . . . . . . . . . 30
+ 12.1. Hashing Considerations . . . . . . . . . . . . . . . . . . 30
+
+
+
+Laurie, et al. Standards Track [Page 2]
+
+RFC 5155 NSEC3 March 2008
+
+
+ 12.1.1. Dictionary Attacks . . . . . . . . . . . . . . . . . . 30
+ 12.1.2. Collisions . . . . . . . . . . . . . . . . . . . . . . 31
+ 12.1.3. Transitioning to a New Hash Algorithm . . . . . . . . 31
+ 12.1.4. Using High Iteration Values . . . . . . . . . . . . . 31
+ 12.2. Opt-Out Considerations . . . . . . . . . . . . . . . . . . 32
+ 12.3. Other Considerations . . . . . . . . . . . . . . . . . . . 33
+ 13. References . . . . . . . . . . . . . . . . . . . . . . . . . . 33
+ 13.1. Normative References . . . . . . . . . . . . . . . . . . . 33
+ 13.2. Informative References . . . . . . . . . . . . . . . . . . 34
+ Appendix A. Example Zone . . . . . . . . . . . . . . . . . . . . 35
+ Appendix B. Example Responses . . . . . . . . . . . . . . . . . . 40
+ B.1. Name Error . . . . . . . . . . . . . . . . . . . . . . . . 40
+ B.2. No Data Error . . . . . . . . . . . . . . . . . . . . . . 42
+ B.2.1. No Data Error, Empty Non-Terminal . . . . . . . . . . 43
+ B.3. Referral to an Opt-Out Unsigned Zone . . . . . . . . . . . 44
+ B.4. Wildcard Expansion . . . . . . . . . . . . . . . . . . . . 45
+ B.5. Wildcard No Data Error . . . . . . . . . . . . . . . . . . 46
+ B.6. DS Child Zone No Data Error . . . . . . . . . . . . . . . 48
+ Appendix C. Special Considerations . . . . . . . . . . . . . . . 48
+ C.1. Salting . . . . . . . . . . . . . . . . . . . . . . . . . 49
+ C.2. Hash Collision . . . . . . . . . . . . . . . . . . . . . . 49
+ C.2.1. Avoiding Hash Collisions During Generation . . . . . . 50
+ C.2.2. Second Preimage Requirement Analysis . . . . . . . . . 50
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 3]
+
+RFC 5155 NSEC3 March 2008
+
+
+1. Introduction
+
+1.1. Rationale
+
+ The DNS Security Extensions included the NSEC RR to provide
+ authenticated denial of existence. Though the NSEC RR meets the
+ requirements for authenticated denial of existence, it introduces a
+ side-effect in that the contents of a zone can be enumerated. This
+ property introduces undesired policy issues.
+
+ The enumeration is enabled by the set of NSEC records that exists
+ inside a signed zone. An NSEC record lists two names that are
+ ordered canonically, in order to show that nothing exists between the
+ two names. The complete set of NSEC records lists all the names in a
+ zone. It is trivial to enumerate the content of a zone by querying
+ for names that do not exist.
+
+ An enumerated zone can be used, for example, as a source of probable
+ e-mail addresses for spam, or as a key for multiple WHOIS queries to
+ reveal registrant data that many registries may have legal
+ obligations to protect. Many registries therefore prohibit the
+ copying of their zone data; however, the use of NSEC RRs renders
+ these policies unenforceable.
+
+ A second problem is that the cost to cryptographically secure
+ delegations to unsigned zones is high, relative to the perceived
+ security benefit, in two cases: large, delegation-centric zones, and
+ zones where insecure delegations will be updated rapidly. In these
+ cases, the costs of maintaining the NSEC RR chain may be extremely
+ high and use of the "Opt-Out" convention may be more appropriate (for
+ these unsecured zones).
+
+ This document presents the NSEC3 Resource Record which can be used as
+ an alternative to NSEC to mitigate these issues.
+
+ Earlier work to address these issues include [DNSEXT-NO], [RFC4956],
+ and [DNSEXT-NSEC2v2].
+
+1.2. Requirements
+
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+ document are to be interpreted as described in [RFC2119].
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 4]
+
+RFC 5155 NSEC3 March 2008
+
+
+1.3. Terminology
+
+ The reader is assumed to be familiar with the basic DNS and DNSSEC
+ concepts described in [RFC1034], [RFC1035], [RFC4033], [RFC4034],
+ [RFC4035], and subsequent RFCs that update them: [RFC2136],
+ [RFC2181], and [RFC2308].
+
+ The following terminology is used throughout this document:
+
+ Zone enumeration: the practice of discovering the full content of a
+ zone via successive queries. Zone enumeration was non-trivial
+ prior to the introduction of DNSSEC.
+
+ Original owner name: the owner name corresponding to a hashed owner
+ name.
+
+ Hashed owner name: the owner name created after applying the hash
+ function to an owner name.
+
+ Hash order: the order in which hashed owner names are arranged
+ according to their numerical value, treating the leftmost (lowest
+ numbered) octet as the most significant octet. Note that this
+ order is the same as the canonical DNS name order specified in
+ [RFC4034], when the hashed owner names are in base32, encoded with
+ an Extended Hex Alphabet [RFC4648].
+
+ Empty non-terminal: a domain name that owns no resource records, but
+ has one or more subdomains that do.
+
+ Delegation: an NS RRSet with a name different from the current zone
+ apex (non-zone-apex), signifying a delegation to a child zone.
+
+ Secure delegation: a name containing a delegation (NS RRSet) and a
+ signed DS RRSet, signifying a delegation to a signed child zone.
+
+ Insecure delegation: a name containing a delegation (NS RRSet), but
+ lacking a DS RRSet, signifying a delegation to an unsigned child
+ zone.
+
+ Opt-Out NSEC3 resource record: an NSEC3 resource record that has the
+ Opt-Out flag set to 1.
+
+ Opt-Out zone: a zone with at least one Opt-Out NSEC3 RR.
+
+ Closest encloser: the longest existing ancestor of a name. See also
+ Section 3.3.1 of [RFC4592].
+
+
+
+
+
+Laurie, et al. Standards Track [Page 5]
+
+RFC 5155 NSEC3 March 2008
+
+
+ Closest provable encloser: the longest ancestor of a name that can
+ be proven to exist. Note that this is only different from the
+ closest encloser in an Opt-Out zone.
+
+ Next closer name: the name one label longer than the closest
+ provable encloser of a name.
+
+ Base32: the "Base 32 Encoding with Extended Hex Alphabet" as
+ specified in [RFC4648]. Note that trailing padding characters
+ ("=") are not used in the NSEC3 specification.
+
+ To cover: An NSEC3 RR is said to "cover" a name if the hash of the
+ name or "next closer" name falls between the owner name and the
+ next hashed owner name of the NSEC3. In other words, if it proves
+ the nonexistence of the name, either directly or by proving the
+ nonexistence of an ancestor of the name.
+
+ To match: An NSEC3 RR is said to "match" a name if the owner name of
+ the NSEC3 RR is the same as the hashed owner name of that name.
+
+2. Backwards Compatibility
+
+ This specification describes a protocol change that is not generally
+ backwards compatible with [RFC4033], [RFC4034], and [RFC4035]. In
+ particular, security-aware resolvers that are unaware of this
+ specification (NSEC3-unaware resolvers) may fail to validate the
+ responses introduced by this document.
+
+ In order to aid deployment, this specification uses a signaling
+ technique to prevent NSEC3-unaware resolvers from attempting to
+ validate responses from NSEC3-signed zones.
+
+ This specification allocates two new DNSKEY algorithm identifiers for
+ this purpose. Algorithm 6, DSA-NSEC3-SHA1 is an alias for algorithm
+ 3, DSA. Algorithm 7, RSASHA1-NSEC3-SHA1 is an alias for algorithm 5,
+ RSASHA1. These are not new algorithms, they are additional
+ identifiers for the existing algorithms.
+
+ Zones signed according to this specification MUST only use these
+ algorithm identifiers for their DNSKEY RRs. Because these new
+ identifiers will be unknown algorithms to existing, NSEC3-unaware
+ resolvers, those resolvers will then treat responses from the NSEC3
+ signed zone as insecure, as detailed in Section 5.2 of [RFC4035].
+
+ These algorithm identifiers are used with the NSEC3 hash algorithm
+ SHA1. Using other NSEC3 hash algorithms requires allocation of a new
+ alias (see Section 12.1.3).
+
+
+
+
+Laurie, et al. Standards Track [Page 6]
+
+RFC 5155 NSEC3 March 2008
+
+
+ Security aware resolvers that are aware of this specification MUST
+ recognize the new algorithm identifiers and treat them as equivalent
+ to the algorithms that they alias.
+
+ A methodology for transitioning from a DNSSEC signed zone to a zone
+ signed using NSEC3 is discussed in Section 10.4.
+
+3. The NSEC3 Resource Record
+
+ The NSEC3 Resource Record (RR) provides authenticated denial of
+ existence for DNS Resource Record Sets.
+
+ The NSEC3 RR lists RR types present at the original owner name of the
+ NSEC3 RR. It includes the next hashed owner name in the hash order
+ of the zone. The complete set of NSEC3 RRs in a zone indicates which
+ RRSets exist for the original owner name of the RR and form a chain
+ of hashed owner names in the zone. This information is used to
+ provide authenticated denial of existence for DNS data. To provide
+ protection against zone enumeration, the owner names used in the
+ NSEC3 RR are cryptographic hashes of the original owner name
+ prepended as a single label to the name of the zone. The NSEC3 RR
+ indicates which hash function is used to construct the hash, which
+ salt is used, and how many iterations of the hash function are
+ performed over the original owner name. The hashing technique is
+ described fully in Section 5.
+
+ Hashed owner names of unsigned delegations may be excluded from the
+ chain. An NSEC3 RR whose span covers the hash of an owner name or
+ "next closer" name of an unsigned delegation is referred to as an
+ Opt-Out NSEC3 RR and is indicated by the presence of a flag.
+
+ The owner name for the NSEC3 RR is the base32 encoding of the hashed
+ owner name prepended as a single label to the name of the zone.
+
+ The type value for the NSEC3 RR is 50.
+
+ The NSEC3 RR RDATA format is class independent and is described
+ below.
+
+ The class MUST be the same as the class of the original owner name.
+
+ The NSEC3 RR SHOULD have the same TTL value as the SOA minimum TTL
+ field. This is in the spirit of negative caching [RFC2308].
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 7]
+
+RFC 5155 NSEC3 March 2008
+
+
+3.1. RDATA Fields
+
+3.1.1. Hash Algorithm
+
+ The Hash Algorithm field identifies the cryptographic hash algorithm
+ used to construct the hash-value.
+
+ The values for this field are defined in the NSEC3 hash algorithm
+ registry defined in Section 11.
+
+3.1.2. Flags
+
+ The Flags field contains 8 one-bit flags that can be used to indicate
+ different processing. All undefined flags must be zero. The only
+ flag defined by this specification is the Opt-Out flag.
+
+3.1.2.1. Opt-Out Flag
+
+ If the Opt-Out flag is set, the NSEC3 record covers zero or more
+ unsigned delegations.
+
+ If the Opt-Out flag is clear, the NSEC3 record covers zero unsigned
+ delegations.
+
+ The Opt-Out Flag indicates whether this NSEC3 RR may cover unsigned
+ delegations. It is the least significant bit in the Flags field.
+ See Section 6 for details about the use of this flag.
+
+3.1.3. Iterations
+
+ The Iterations field defines the number of additional times the hash
+ function has been performed. More iterations result in greater
+ resiliency of the hash value against dictionary attacks, but at a
+ higher computational cost for both the server and resolver. See
+ Section 5 for details of the use of this field, and Section 10.3 for
+ limitations on the value.
+
+3.1.4. Salt Length
+
+ The Salt Length field defines the length of the Salt field in octets,
+ ranging in value from 0 to 255.
+
+3.1.5. Salt
+
+ The Salt field is appended to the original owner name before hashing
+ in order to defend against pre-calculated dictionary attacks. See
+ Section 5 for details on how the salt is used.
+
+
+
+
+Laurie, et al. Standards Track [Page 8]
+
+RFC 5155 NSEC3 March 2008
+
+
+3.1.6. Hash Length
+
+ The Hash Length field defines the length of the Next Hashed Owner
+ Name field, ranging in value from 1 to 255 octets.
+
+3.1.7. Next Hashed Owner Name
+
+ The Next Hashed Owner Name field contains the next hashed owner name
+ in hash order. This value is in binary format. Given the ordered
+ set of all hashed owner names, the Next Hashed Owner Name field
+ contains the hash of an owner name that immediately follows the owner
+ name of the given NSEC3 RR. The value of the Next Hashed Owner Name
+ field in the last NSEC3 RR in the zone is the same as the hashed
+ owner name of the first NSEC3 RR in the zone in hash order. Note
+ that, unlike the owner name of the NSEC3 RR, the value of this field
+ does not contain the appended zone name.
+
+3.1.8. Type Bit Maps
+
+ The Type Bit Maps field identifies the RRSet types that exist at the
+ original owner name of the NSEC3 RR.
+
+3.2. NSEC3 RDATA Wire Format
+
+ The RDATA of the NSEC3 RR is as shown below:
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Hash Alg. | Flags | Iterations |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Salt Length | Salt /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Hash Length | Next Hashed Owner Name /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ / Type Bit Maps /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Hash Algorithm is a single octet.
+
+ Flags field is a single octet, the Opt-Out flag is the least
+ significant bit, as shown below:
+
+ 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+
+ | |O|
+ +-+-+-+-+-+-+-+-+
+
+
+
+
+Laurie, et al. Standards Track [Page 9]
+
+RFC 5155 NSEC3 March 2008
+
+
+ Iterations is represented as a 16-bit unsigned integer, with the most
+ significant bit first.
+
+ Salt Length is represented as an unsigned octet. Salt Length
+ represents the length of the Salt field in octets. If the value is
+ zero, the following Salt field is omitted.
+
+ Salt, if present, is encoded as a sequence of binary octets. The
+ length of this field is determined by the preceding Salt Length
+ field.
+
+ Hash Length is represented as an unsigned octet. Hash Length
+ represents the length of the Next Hashed Owner Name field in octets.
+
+ The next hashed owner name is not base32 encoded, unlike the owner
+ name of the NSEC3 RR. It is the unmodified binary hash value. It
+ does not include the name of the containing zone. The length of this
+ field is determined by the preceding Hash Length field.
+
+3.2.1. Type Bit Maps Encoding
+
+ The encoding of the Type Bit Maps field is the same as that used by
+ the NSEC RR, described in [RFC4034]. It is explained and clarified
+ here for clarity.
+
+ The RR type space is split into 256 window blocks, each representing
+ the low-order 8 bits of the 16-bit RR type space. Each block that
+ has at least one active RR type is encoded using a single octet
+ window number (from 0 to 255), a single octet bitmap length (from 1
+ to 32) indicating the number of octets used for the bitmap of the
+ window block, and up to 32 octets (256 bits) of bitmap.
+
+ Blocks are present in the NSEC3 RR RDATA in increasing numerical
+ order.
+
+ Type Bit Maps Field = ( Window Block # | Bitmap Length | Bitmap )+
+
+ where "|" denotes concatenation.
+
+ Each bitmap encodes the low-order 8 bits of RR types within the
+ window block, in network bit order. The first bit is bit 0. For
+ window block 0, bit 1 corresponds to RR type 1 (A), bit 2 corresponds
+ to RR type 2 (NS), and so forth. For window block 1, bit 1
+ corresponds to RR type 257, bit 2 to RR type 258. If a bit is set to
+ 1, it indicates that an RRSet of that type is present for the
+ original owner name of the NSEC3 RR. If a bit is set to 0, it
+ indicates that no RRSet of that type is present for the original
+ owner name of the NSEC3 RR.
+
+
+
+Laurie, et al. Standards Track [Page 10]
+
+RFC 5155 NSEC3 March 2008
+
+
+ Since bit 0 in window block 0 refers to the non-existing RR type 0,
+ it MUST be set to 0. After verification, the validator MUST ignore
+ the value of bit 0 in window block 0.
+
+ Bits representing Meta-TYPEs or QTYPEs as specified in Section 3.1 of
+ [RFC2929] or within the range reserved for assignment only to QTYPEs
+ and Meta-TYPEs MUST be set to 0, since they do not appear in zone
+ data. If encountered, they must be ignored upon reading.
+
+ Blocks with no types present MUST NOT be included. Trailing zero
+ octets in the bitmap MUST be omitted. The length of the bitmap of
+ each block is determined by the type code with the largest numerical
+ value, within that block, among the set of RR types present at the
+ original owner name of the NSEC3 RR. Trailing octets not specified
+ MUST be interpreted as zero octets.
+
+3.3. Presentation Format
+
+ The presentation format of the RDATA portion is as follows:
+
+ o The Hash Algorithm field is represented as an unsigned decimal
+ integer. The value has a maximum of 255.
+
+ o The Flags field is represented as an unsigned decimal integer.
+ The value has a maximum of 255.
+
+ o The Iterations field is represented as an unsigned decimal
+ integer. The value is between 0 and 65535, inclusive.
+
+ o The Salt Length field is not represented.
+
+ o The Salt field is represented as a sequence of case-insensitive
+ hexadecimal digits. Whitespace is not allowed within the
+ sequence. The Salt field is represented as "-" (without the
+ quotes) when the Salt Length field has a value of 0.
+
+ o The Hash Length field is not represented.
+
+ o The Next Hashed Owner Name field is represented as an unpadded
+ sequence of case-insensitive base32 digits, without whitespace.
+
+ o The Type Bit Maps field is represented as a sequence of RR type
+ mnemonics. When the mnemonic is not known, the TYPE
+ representation as described in Section 5 of [RFC3597] MUST be
+ used.
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 11]
+
+RFC 5155 NSEC3 March 2008
+
+
+4. The NSEC3PARAM Resource Record
+
+ The NSEC3PARAM RR contains the NSEC3 parameters (hash algorithm,
+ flags, iterations, and salt) needed by authoritative servers to
+ calculate hashed owner names. The presence of an NSEC3PARAM RR at a
+ zone apex indicates that the specified parameters may be used by
+ authoritative servers to choose an appropriate set of NSEC3 RRs for
+ negative responses. The NSEC3PARAM RR is not used by validators or
+ resolvers.
+
+ If an NSEC3PARAM RR is present at the apex of a zone with a Flags
+ field value of zero, then there MUST be an NSEC3 RR using the same
+ hash algorithm, iterations, and salt parameters present at every
+ hashed owner name in the zone. That is, the zone MUST contain a
+ complete set of NSEC3 RRs with the same hash algorithm, iterations,
+ and salt parameters.
+
+ The owner name for the NSEC3PARAM RR is the name of the zone apex.
+
+ The type value for the NSEC3PARAM RR is 51.
+
+ The NSEC3PARAM RR RDATA format is class independent and is described
+ below.
+
+ The class MUST be the same as the NSEC3 RRs to which this RR refers.
+
+4.1. RDATA Fields
+
+ The RDATA for this RR mirrors the first four fields in the NSEC3 RR.
+
+4.1.1. Hash Algorithm
+
+ The Hash Algorithm field identifies the cryptographic hash algorithm
+ used to construct the hash-value.
+
+ The acceptable values are the same as the corresponding field in the
+ NSEC3 RR.
+
+4.1.2. Flag Fields
+
+ The Opt-Out flag is not used and is set to zero.
+
+ All other flags are reserved for future use, and must be zero.
+
+ NSEC3PARAM RRs with a Flags field value other than zero MUST be
+ ignored.
+
+
+
+
+
+Laurie, et al. Standards Track [Page 12]
+
+RFC 5155 NSEC3 March 2008
+
+
+4.1.3. Iterations
+
+ The Iterations field defines the number of additional times the hash
+ is performed.
+
+ Its acceptable values are the same as the corresponding field in the
+ NSEC3 RR.
+
+4.1.4. Salt Length
+
+ The Salt Length field defines the length of the salt in octets,
+ ranging in value from 0 to 255.
+
+4.1.5. Salt
+
+ The Salt field is appended to the original owner name before hashing.
+
+4.2. NSEC3PARAM RDATA Wire Format
+
+ The RDATA of the NSEC3PARAM RR is as shown below:
+
+ 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Hash Alg. | Flags | Iterations |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Salt Length | Salt /
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Hash Algorithm is a single octet.
+
+ Flags field is a single octet.
+
+ Iterations is represented as a 16-bit unsigned integer, with the most
+ significant bit first.
+
+ Salt Length is represented as an unsigned octet. Salt Length
+ represents the length of the following Salt field in octets. If the
+ value is zero, the Salt field is omitted.
+
+ Salt, if present, is encoded as a sequence of binary octets. The
+ length of this field is determined by the preceding Salt Length
+ field.
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 13]
+
+RFC 5155 NSEC3 March 2008
+
+
+4.3. Presentation Format
+
+ The presentation format of the RDATA portion is as follows:
+
+ o The Hash Algorithm field is represented as an unsigned decimal
+ integer. The value has a maximum of 255.
+
+ o The Flags field is represented as an unsigned decimal integer.
+ The value has a maximum value of 255.
+
+ o The Iterations field is represented as an unsigned decimal
+ integer. The value is between 0 and 65535, inclusive.
+
+ o The Salt Length field is not represented.
+
+ o The Salt field is represented as a sequence of case-insensitive
+ hexadecimal digits. Whitespace is not allowed within the
+ sequence. This field is represented as "-" (without the quotes)
+ when the Salt Length field is zero.
+
+5. Calculation of the Hash
+
+ The hash calculation uses three of the NSEC3 RDATA fields: Hash
+ Algorithm, Salt, and Iterations.
+
+ Define H(x) to be the hash of x using the Hash Algorithm selected by
+ the NSEC3 RR, k to be the number of Iterations, and || to indicate
+ concatenation. Then define:
+
+ IH(salt, x, 0) = H(x || salt), and
+
+ IH(salt, x, k) = H(IH(salt, x, k-1) || salt), if k > 0
+
+ Then the calculated hash of an owner name is
+
+ IH(salt, owner name, iterations),
+
+ where the owner name is in the canonical form, defined as:
+
+ The wire format of the owner name where:
+
+ 1. The owner name is fully expanded (no DNS name compression) and
+ fully qualified;
+
+ 2. All uppercase US-ASCII letters are replaced by the corresponding
+ lowercase US-ASCII letters;
+
+
+
+
+
+Laurie, et al. Standards Track [Page 14]
+
+RFC 5155 NSEC3 March 2008
+
+
+ 3. If the owner name is a wildcard name, the owner name is in its
+ original unexpanded form, including the "*" label (no wildcard
+ substitution);
+
+ This form is as defined in Section 6.2 of [RFC4034].
+
+ The method to calculate the Hash is based on [RFC2898].
+
+6. Opt-Out
+
+ In this specification, as in [RFC4033], [RFC4034] and [RFC4035], NS
+ RRSets at delegation points are not signed and may be accompanied by
+ a DS RRSet. With the Opt-Out bit clear, the security status of the
+ child zone is determined by the presence or absence of this DS RRSet,
+ cryptographically proven by the signed NSEC3 RR at the hashed owner
+ name of the delegation. Setting the Opt-Out flag modifies this by
+ allowing insecure delegations to exist within the signed zone without
+ a corresponding NSEC3 RR at the hashed owner name of the delegation.
+
+ An Opt-Out NSEC3 RR is said to cover a delegation if the hash of the
+ owner name or "next closer" name of the delegation is between the
+ owner name of the NSEC3 RR and the next hashed owner name.
+
+ An Opt-Out NSEC3 RR does not assert the existence or non-existence of
+ the insecure delegations that it may cover. This allows for the
+ addition or removal of these delegations without recalculating or re-
+ signing RRs in the NSEC3 RR chain. However, Opt-Out NSEC3 RRs do
+ assert the (non)existence of other, authoritative RRSets.
+
+ An Opt-Out NSEC3 RR MAY have the same original owner name as an
+ insecure delegation. In this case, the delegation is proven insecure
+ by the lack of a DS bit in the type map and the signed NSEC3 RR does
+ assert the existence of the delegation.
+
+ Zones using Opt-Out MAY contain a mixture of Opt-Out NSEC3 RRs and
+ non-Opt-Out NSEC3 RRs. If an NSEC3 RR is not Opt-Out, there MUST NOT
+ be any hashed owner names of insecure delegations (nor any other RRs)
+ between it and the name indicated by the next hashed owner name in
+ the NSEC3 RDATA. If it is Opt-Out, it MUST only cover hashed owner
+ names or hashed "next closer" names of insecure delegations.
+
+ The effects of the Opt-Out flag on signing, serving, and validating
+ responses are covered in following sections.
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 15]
+
+RFC 5155 NSEC3 March 2008
+
+
+7. Authoritative Server Considerations
+
+7.1. Zone Signing
+
+ Zones using NSEC3 must satisfy the following properties:
+
+ o Each owner name within the zone that owns authoritative RRSets
+ MUST have a corresponding NSEC3 RR. Owner names that correspond
+ to unsigned delegations MAY have a corresponding NSEC3 RR.
+ However, if there is not a corresponding NSEC3 RR, there MUST be
+ an Opt-Out NSEC3 RR that covers the "next closer" name to the
+ delegation. Other non-authoritative RRs are not represented by
+ NSEC3 RRs.
+
+ o Each empty non-terminal MUST have a corresponding NSEC3 RR, unless
+ the empty non-terminal is only derived from an insecure delegation
+ covered by an Opt-Out NSEC3 RR.
+
+ o The TTL value for any NSEC3 RR SHOULD be the same as the minimum
+ TTL value field in the zone SOA RR.
+
+ o The Type Bit Maps field of every NSEC3 RR in a signed zone MUST
+ indicate the presence of all types present at the original owner
+ name, except for the types solely contributed by an NSEC3 RR
+ itself. Note that this means that the NSEC3 type itself will
+ never be present in the Type Bit Maps.
+
+ The following steps describe a method of proper construction of NSEC3
+ RRs. This is not the only such possible method.
+
+ 1. Select the hash algorithm and the values for salt and iterations.
+
+ 2. For each unique original owner name in the zone add an NSEC3 RR.
+
+ * If Opt-Out is being used, owner names of unsigned delegations
+ MAY be excluded.
+
+ * The owner name of the NSEC3 RR is the hash of the original
+ owner name, prepended as a single label to the zone name.
+
+ * The Next Hashed Owner Name field is left blank for the moment.
+
+ * If Opt-Out is being used, set the Opt-Out bit to one.
+
+ * For collision detection purposes, optionally keep track of the
+ original owner name with the NSEC3 RR.
+
+
+
+
+
+Laurie, et al. Standards Track [Page 16]
+
+RFC 5155 NSEC3 March 2008
+
+
+ * Additionally, for collision detection purposes, optionally
+ create an additional NSEC3 RR corresponding to the original
+ owner name with the asterisk label prepended (i.e., as if a
+ wildcard existed as a child of this owner name) and keep track
+ of this original owner name. Mark this NSEC3 RR as temporary.
+
+ 3. For each RRSet at the original owner name, set the corresponding
+ bit in the Type Bit Maps field.
+
+ 4. If the difference in number of labels between the apex and the
+ original owner name is greater than 1, additional NSEC3 RRs need
+ to be added for every empty non-terminal between the apex and the
+ original owner name. This process may generate NSEC3 RRs with
+ duplicate hashed owner names. Optionally, for collision
+ detection, track the original owner names of these NSEC3 RRs and
+ create temporary NSEC3 RRs for wildcard collisions in a similar
+ fashion to step 1.
+
+ 5. Sort the set of NSEC3 RRs into hash order.
+
+ 6. Combine NSEC3 RRs with identical hashed owner names by replacing
+ them with a single NSEC3 RR with the Type Bit Maps field
+ consisting of the union of the types represented by the set of
+ NSEC3 RRs. If the original owner name was tracked, then
+ collisions may be detected when combining, as all of the matching
+ NSEC3 RRs should have the same original owner name. Discard any
+ possible temporary NSEC3 RRs.
+
+ 7. In each NSEC3 RR, insert the next hashed owner name by using the
+ value of the next NSEC3 RR in hash order. The next hashed owner
+ name of the last NSEC3 RR in the zone contains the value of the
+ hashed owner name of the first NSEC3 RR in the hash order.
+
+ 8. Finally, add an NSEC3PARAM RR with the same Hash Algorithm,
+ Iterations, and Salt fields to the zone apex.
+
+ If a hash collision is detected, then a new salt has to be chosen,
+ and the signing process restarted.
+
+7.2. Zone Serving
+
+ This specification modifies DNSSEC-enabled DNS responses generated by
+ authoritative servers. In particular, it replaces the use of NSEC
+ RRs in such responses with NSEC3 RRs.
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 17]
+
+RFC 5155 NSEC3 March 2008
+
+
+ In the following response cases, the NSEC RRs dictated by DNSSEC
+ [RFC4035] are replaced with NSEC3 RRs that prove the same facts.
+ Responses that would not contain NSEC RRs are unchanged by this
+ specification.
+
+ When returning responses containing multiple NSEC3 RRs, all of the
+ NSEC3 RRs MUST use the same hash algorithm, iteration, and salt
+ values. The Flags field value MUST be either zero or one.
+
+7.2.1. Closest Encloser Proof
+
+ For many NSEC3 responses a proof of the closest encloser is required.
+ This is a proof that some ancestor of the QNAME is the closest
+ encloser of QNAME.
+
+ This proof consists of (up to) two different NSEC3 RRs:
+
+ o An NSEC3 RR that matches the closest (provable) encloser.
+
+ o An NSEC3 RR that covers the "next closer" name to the closest
+ encloser.
+
+ The first NSEC3 RR essentially proposes a possible closest encloser,
+ and proves that the particular encloser does, in fact, exist. The
+ second NSEC3 RR proves that the possible closest encloser is the
+ closest, and proves that the QNAME (and any ancestors between QNAME
+ and the closest encloser) does not exist.
+
+ These NSEC3 RRs are collectively referred to as the "closest encloser
+ proof" in the subsequent descriptions.
+
+ For example, the closest encloser proof for the nonexistent
+ "alpha.beta.gamma.example." owner name might prove that
+ "gamma.example." is the closest encloser. This response would
+ contain the NSEC3 RR that matches "gamma.example.", and would also
+ contain the NSEC3 RR that covers "beta.gamma.example." (which is the
+ "next closer" name).
+
+ It is possible, when using Opt-Out (Section 6), to not be able to
+ prove the actual closest encloser because it is, or is part of an
+ insecure delegation covered by an Opt-Out span. In this case,
+ instead of proving the actual closest encloser, the closest provable
+ encloser is used. That is, the closest enclosing authoritative name
+ is used instead. In this case, the set of NSEC3 RRs used for this
+ proof is referred to as the "closest provable encloser proof".
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 18]
+
+RFC 5155 NSEC3 March 2008
+
+
+7.2.2. Name Error Responses
+
+ To prove the nonexistence of QNAME, a closest encloser proof and an
+ NSEC3 RR covering the (nonexistent) wildcard RR at the closest
+ encloser MUST be included in the response. This collection of (up
+ to) three NSEC3 RRs proves both that QNAME does not exist and that a
+ wildcard that could have matched QNAME also does not exist.
+
+ For example, if "gamma.example." is the closest provable encloser to
+ QNAME, then an NSEC3 RR covering "*.gamma.example." is included in
+ the authority section of the response.
+
+7.2.3. No Data Responses, QTYPE is not DS
+
+ The server MUST include the NSEC3 RR that matches QNAME. This NSEC3
+ RR MUST NOT have the bits corresponding to either the QTYPE or CNAME
+ set in its Type Bit Maps field.
+
+7.2.4. No Data Responses, QTYPE is DS
+
+ If there is an NSEC3 RR that matches QNAME, the server MUST return it
+ in the response. The bits corresponding with DS and CNAME MUST NOT
+ be set in the Type Bit Maps field of this NSEC3 RR.
+
+ If no NSEC3 RR matches QNAME, the server MUST return a closest
+ provable encloser proof for QNAME. The NSEC3 RR that covers the
+ "next closer" name MUST have the Opt-Out bit set (note that this is
+ true by definition -- if the Opt-Out bit is not set, something has
+ gone wrong).
+
+ If a server is authoritative for both sides of a zone cut at QNAME,
+ the server MUST return the proof from the parent side of the zone
+ cut.
+
+7.2.5. Wildcard No Data Responses
+
+ If there is a wildcard match for QNAME, but QTYPE is not present at
+ that name, the response MUST include a closest encloser proof for
+ QNAME and MUST include the NSEC3 RR that matches the wildcard. This
+ combination proves both that QNAME itself does not exist and that a
+ wildcard that matches QNAME does exist. Note that the closest
+ encloser to QNAME MUST be the immediate ancestor of the wildcard RR
+ (if this is not the case, then something has gone wrong).
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 19]
+
+RFC 5155 NSEC3 March 2008
+
+
+7.2.6. Wildcard Answer Responses
+
+ If there is a wildcard match for QNAME and QTYPE, then, in addition
+ to the expanded wildcard RRSet returned in the answer section of the
+ response, proof that the wildcard match was valid must be returned.
+
+ This proof is accomplished by proving that both QNAME does not exist
+ and that the closest encloser of the QNAME and the immediate ancestor
+ of the wildcard are the same (i.e., the correct wildcard matched).
+
+ To this end, the NSEC3 RR that covers the "next closer" name of the
+ immediate ancestor of the wildcard MUST be returned. It is not
+ necessary to return an NSEC3 RR that matches the closest encloser, as
+ the existence of this closest encloser is proven by the presence of
+ the expanded wildcard in the response.
+
+7.2.7. Referrals to Unsigned Subzones
+
+ If there is an NSEC3 RR that matches the delegation name, then that
+ NSEC3 RR MUST be included in the response. The DS bit in the type
+ bit maps of the NSEC3 RR MUST NOT be set.
+
+ If the zone is Opt-Out, then there may not be an NSEC3 RR
+ corresponding to the delegation. In this case, the closest provable
+ encloser proof MUST be included in the response. The included NSEC3
+ RR that covers the "next closer" name for the delegation MUST have
+ the Opt-Out flag set to one. (Note that this will be the case unless
+ something has gone wrong).
+
+7.2.8. Responding to Queries for NSEC3 Owner Names
+
+ The owner names of NSEC3 RRs are not represented in the NSEC3 RR
+ chain like other owner names. As a result, each NSEC3 owner name is
+ covered by another NSEC3 RR, effectively negating the existence of
+ the NSEC3 RR. This is a paradox, since the existence of an NSEC3 RR
+ can be proven by its RRSIG RRSet.
+
+ If the following conditions are all true:
+
+ o the QNAME equals the owner name of an existing NSEC3 RR, and
+
+ o no RR types exist at the QNAME, nor at any descendant of QNAME,
+
+ then the response MUST be constructed as a Name Error response
+ (Section 7.2.2). Or, in other words, the authoritative name server
+ will act as if the owner name of the NSEC3 RR did not exist.
+
+
+
+
+
+Laurie, et al. Standards Track [Page 20]
+
+RFC 5155 NSEC3 March 2008
+
+
+ Note that NSEC3 RRs are returned as a result of an AXFR or IXFR
+ query.
+
+7.2.9. Server Response to a Run-Time Collision
+
+ If the hash of a non-existing QNAME collides with the owner name of
+ an existing NSEC3 RR, then the server will be unable to return a
+ response that proves that QNAME does not exist. In this case, the
+ server MUST return a response with an RCODE of 2 (server failure).
+
+ Note that with the hash algorithm specified in this document, SHA-1,
+ such collisions are highly unlikely.
+
+7.3. Secondary Servers
+
+ Secondary servers (and perhaps other entities) need to reliably
+ determine which NSEC3 parameters (i.e., hash, salt, and iterations)
+ are present at every hashed owner name, in order to be able to choose
+ an appropriate set of NSEC3 RRs for negative responses. This is
+ indicated by an NSEC3PARAM RR present at the zone apex.
+
+ If there are multiple NSEC3PARAM RRs present, there are multiple
+ valid NSEC3 chains present. The server must choose one of them, but
+ may use any criteria to do so.
+
+7.4. Zones Using Unknown Hash Algorithms
+
+ Zones that are signed according to this specification, but are using
+ an unrecognized NSEC3 hash algorithm value, cannot be effectively
+ served. Such zones SHOULD be rejected when loading. Servers SHOULD
+ respond with RCODE=2 (server failure) responses when handling queries
+ that would fall under such zones.
+
+7.5. Dynamic Update
+
+ A zone signed using NSEC3 may accept dynamic updates [RFC2136].
+ However, NSEC3 introduces some special considerations for dynamic
+ updates.
+
+ Adding and removing names in a zone MUST account for the creation or
+ removal of empty non-terminals.
+
+ o When removing a name with a corresponding NSEC3 RR, any NSEC3 RRs
+ corresponding to empty non-terminals created by that name MUST be
+ removed. Note that more than one name may be asserting the
+ existence of a particular empty non-terminal.
+
+
+
+
+
+Laurie, et al. Standards Track [Page 21]
+
+RFC 5155 NSEC3 March 2008
+
+
+ o When adding a name that requires adding an NSEC3 RR, NSEC3 RRs
+ MUST also be added for any empty non-terminals that are created.
+ That is, if there is not an existing NSEC3 RR matching an empty
+ non-terminal, it must be created and added.
+
+ The presence of Opt-Out in a zone means that some additions or
+ delegations of names will not require changes to the NSEC3 RRs in a
+ zone.
+
+ o When removing a delegation RRSet, if that delegation does not have
+ a matching NSEC3 RR, then it was opted out. In this case, nothing
+ further needs to be done.
+
+ o When adding a delegation RRSet, if the "next closer" name of the
+ delegation is covered by an existing Opt-Out NSEC3 RR, then the
+ delegation MAY be added without modifying the NSEC3 RRs in the
+ zone.
+
+ The presence of Opt-Out in a zone means that when adding or removing
+ NSEC3 RRs, the value of the Opt-Out flag that should be set in new or
+ modified NSEC3 RRs is ambiguous. Servers SHOULD follow this set of
+ basic rules to resolve the ambiguity.
+
+ The central concept to these rules is that the state of the Opt-Out
+ flag of the covering NSEC3 RR is preserved.
+
+ o When removing an NSEC3 RR, the value of the Opt-Out flag for the
+ previous NSEC3 RR (the one whose next hashed owner name is
+ modified) should not be changed.
+
+ o When adding an NSEC3 RR, the value of the Opt-Out flag is set to
+ the value of the Opt-Out flag of the NSEC3 RR that previously
+ covered the owner name of the NSEC3 RR. That is, the now previous
+ NSEC3 RR.
+
+ If the zone in question is consistent with its use of the Opt-Out
+ flag (that is, all NSEC3 RRs in the zone have the same value for the
+ flag) then these rules will retain that consistency. If the zone is
+ not consistent in the use of the flag (i.e., a partially Opt-Out
+ zone), then these rules will not retain the same pattern of use of
+ the Opt-Out flag.
+
+ For zones that partially use the Opt-Out flag, if there is a logical
+ pattern for that use, the pattern could be maintained by using a
+ local policy on the server.
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 22]
+
+RFC 5155 NSEC3 March 2008
+
+
+8. Validator Considerations
+
+8.1. Responses with Unknown Hash Types
+
+ A validator MUST ignore NSEC3 RRs with unknown hash types. The
+ practical result of this is that responses containing only such NSEC3
+ RRs will generally be considered bogus.
+
+8.2. Verifying NSEC3 RRs
+
+ A validator MUST ignore NSEC3 RRs with a Flag fields value other than
+ zero or one.
+
+ A validator MAY treat a response as bogus if the response contains
+ NSEC3 RRs that contain different values for hash algorithm,
+ iterations, or salt from each other for that zone.
+
+8.3. Closest Encloser Proof
+
+ In order to verify a closest encloser proof, the validator MUST find
+ the longest name, X, such that
+
+ o X is an ancestor of QNAME that is matched by an NSEC3 RR present
+ in the response. This is a candidate for the closest encloser,
+ and
+
+ o The name one label longer than X (but still an ancestor of -- or
+ equal to -- QNAME) is covered by an NSEC3 RR present in the
+ response.
+
+ One possible algorithm for verifying this proof is as follows:
+
+ 1. Set SNAME=QNAME. Clear the flag.
+
+ 2. Check whether SNAME exists:
+
+ * If there is no NSEC3 RR in the response that matches SNAME
+ (i.e., an NSEC3 RR whose owner name is the same as the hash of
+ SNAME, prepended as a single label to the zone name), clear
+ the flag.
+
+ * If there is an NSEC3 RR in the response that covers SNAME, set
+ the flag.
+
+ * If there is a matching NSEC3 RR in the response and the flag
+ was set, then the proof is complete, and SNAME is the closest
+ encloser.
+
+
+
+
+Laurie, et al. Standards Track [Page 23]
+
+RFC 5155 NSEC3 March 2008
+
+
+ * If there is a matching NSEC3 RR in the response, but the flag
+ is not set, then the response is bogus.
+
+ 3. Truncate SNAME by one label from the left, go to step 2.
+
+ Once the closest encloser has been discovered, the validator MUST
+ check that the NSEC3 RR that has the closest encloser as the original
+ owner name is from the proper zone. The DNAME type bit must not be
+ set and the NS type bit may only be set if the SOA type bit is set.
+ If this is not the case, it would be an indication that an attacker
+ is using them to falsely deny the existence of RRs for which the
+ server is not authoritative.
+
+ In the following descriptions, the phrase "a closest (provable)
+ encloser proof for X" means that the algorithm above (or an
+ equivalent algorithm) proves that X does not exist by proving that an
+ ancestor of X is its closest encloser.
+
+8.4. Validating Name Error Responses
+
+ A validator MUST verify that there is a closest encloser proof for
+ QNAME present in the response and that there is an NSEC3 RR that
+ covers the wildcard at the closest encloser (i.e., the name formed by
+ prepending the asterisk label to the closest encloser).
+
+8.5. Validating No Data Responses, QTYPE is not DS
+
+ The validator MUST verify that an NSEC3 RR that matches QNAME is
+ present and that both the QTYPE and the CNAME type are not set in its
+ Type Bit Maps field.
+
+ Note that this test also covers the case where the NSEC3 RR exists
+ because it corresponds to an empty non-terminal, in which case the
+ NSEC3 RR will have an empty Type Bit Maps field.
+
+8.6. Validating No Data Responses, QTYPE is DS
+
+ If there is an NSEC3 RR that matches QNAME present in the response,
+ then that NSEC3 RR MUST NOT have the bits corresponding to DS and
+ CNAME set in its Type Bit Maps field.
+
+ If there is no such NSEC3 RR, then the validator MUST verify that a
+ closest provable encloser proof for QNAME is present in the response,
+ and that the NSEC3 RR that covers the "next closer" name has the Opt-
+ Out bit set.
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 24]
+
+RFC 5155 NSEC3 March 2008
+
+
+8.7. Validating Wildcard No Data Responses
+
+ The validator MUST verify a closest encloser proof for QNAME and MUST
+ find an NSEC3 RR present in the response that matches the wildcard
+ name generated by prepending the asterisk label to the closest
+ encloser. Furthermore, the bits corresponding to both QTYPE and
+ CNAME MUST NOT be set in the wildcard matching NSEC3 RR.
+
+8.8. Validating Wildcard Answer Responses
+
+ The verified wildcard answer RRSet in the response provides the
+ validator with a (candidate) closest encloser for QNAME. This
+ closest encloser is the immediate ancestor to the generating
+ wildcard.
+
+ Validators MUST verify that there is an NSEC3 RR that covers the
+ "next closer" name to QNAME present in the response. This proves
+ that QNAME itself did not exist and that the correct wildcard was
+ used to generate the response.
+
+8.9. Validating Referrals to Unsigned Subzones
+
+ The delegation name in a referral is the owner name of the NS RRSet
+ present in the authority section of the referral response.
+
+ If there is an NSEC3 RR present in the response that matches the
+ delegation name, then the validator MUST ensure that the NS bit is
+ set and that the DS bit is not set in the Type Bit Maps field of the
+ NSEC3 RR. The validator MUST also ensure that the NSEC3 RR is from
+ the correct (i.e., parent) zone. This is done by ensuring that the
+ SOA bit is not set in the Type Bit Maps field of this NSEC3 RR.
+
+ Note that the presence of an NS bit implies the absence of a DNAME
+ bit, so there is no need to check for the DNAME bit in the Type Bit
+ Maps field of the NSEC3 RR.
+
+ If there is no NSEC3 RR present that matches the delegation name,
+ then the validator MUST verify a closest provable encloser proof for
+ the delegation name. The validator MUST verify that the Opt-Out bit
+ is set in the NSEC3 RR that covers the "next closer" name to the
+ delegation name.
+
+
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 25]
+
+RFC 5155 NSEC3 March 2008
+
+
+9. Resolver Considerations
+
+9.1. NSEC3 Resource Record Caching
+
+ Caching resolvers MUST be able to retrieve the appropriate NSEC3 RRs
+ when returning responses that contain them. In DNSSEC [RFC4035], in
+ many cases it is possible to find the correct NSEC RR to return in a
+ response by name (e.g., when returning a referral, the NSEC RR will
+ always have the same owner name as the delegation). With this
+ specification, that will not be true, nor will a cache be able to
+ calculate the name(s) of the appropriate NSEC3 RR(s).
+ Implementations may need to use new methods for caching and
+ retrieving NSEC3 RRs.
+
+9.2. Use of the AD Bit
+
+ The AD bit, as defined by [RFC4035], MUST NOT be set when returning a
+ response containing a closest (provable) encloser proof in which the
+ NSEC3 RR that covers the "next closer" name has the Opt-Out bit set.
+
+ This rule is based on what this closest encloser proof actually
+ proves: names that would be covered by the Opt-Out NSEC3 RR may or
+ may not exist as insecure delegations. As such, not all the data in
+ responses containing such closest encloser proofs will have been
+ cryptographically verified, so the AD bit cannot be set.
+
+10. Special Considerations
+
+10.1. Domain Name Length Restrictions
+
+ Zones signed using this specification have additional domain name
+ length restrictions imposed upon them. In particular, zones with
+ names that, when converted into hashed owner names exceed the 255
+ octet length limit imposed by [RFC1035], cannot use this
+ specification.
+
+ The actual maximum length of a domain name in a particular zone
+ depends on both the length of the zone name (versus the whole domain
+ name) and the particular hash function used.
+
+ As an example, SHA-1 produces a hash of 160 bits. The base-32
+ encoding of 160 bits results in 32 characters. The 32 characters are
+ prepended to the name of the zone as a single label, which includes a
+ length field of a single octet. The maximum length of the zone name,
+ when using SHA-1, is 222 octets (255 - 33).
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 26]
+
+RFC 5155 NSEC3 March 2008
+
+
+10.2. DNAME at the Zone Apex
+
+ The DNAME specification in Section 3 of [RFC2672] has a 'no-
+ descendants' limitation. If a DNAME RR is present at node N, there
+ MUST be no data at any descendant of N.
+
+ If N is the apex of the zone, there will be NSEC3 and RRSIG types
+ present at descendants of N. This specification updates the DNAME
+ specification to allow NSEC3 and RRSIG types at descendants of the
+ apex regardless of the existence of DNAME at the apex.
+
+10.3. Iterations
+
+ Setting the number of iterations used allows the zone owner to choose
+ the cost of computing a hash, and therefore the cost of generating a
+ dictionary. Note that this is distinct from the effect of salt,
+ which prevents the use of a single precomputed dictionary for all
+ time.
+
+ Obviously the number of iterations also affects the zone owner's cost
+ of signing and serving the zone as well as the validator's cost of
+ verifying responses from the zone. We therefore impose an upper
+ limit on the number of iterations. We base this on the number of
+ iterations that approximates the cost of verifying an RRSet.
+
+ The limits, therefore, are based on the size of the smallest zone
+ signing key, rounded up to the nearest table value (or rounded down
+ if the key is larger than the largest table value).
+
+ A zone owner MUST NOT use a value higher than shown in the table
+ below for iterations for the given key size. A resolver MAY treat a
+ response with a higher value as insecure, after the validator has
+ verified that the signature over the NSEC3 RR is correct.
+
+ +----------+------------+
+ | Key Size | Iterations |
+ +----------+------------+
+ | 1024 | 150 |
+ | 2048 | 500 |
+ | 4096 | 2,500 |
+ +----------+------------+
+
+ This table is based on an approximation of the ratio between the cost
+ of an SHA-1 calculation and the cost of an RSA verification for keys
+ of size 1024 bits (150 to 1), 2048 bits (500 to 1), and 4096 bits
+ (2500 to 1).
+
+
+
+
+
+Laurie, et al. Standards Track [Page 27]
+
+RFC 5155 NSEC3 March 2008
+
+
+ The ratio between SHA-1 calculation and DSA verification is higher
+ (1500 to 1 for keys of size 1024). A higher iteration count degrades
+ performance, while DSA verification is already more expensive than
+ RSA for the same key size. Therefore the values in the table MUST be
+ used independent of the key algorithm.
+
+10.4. Transitioning a Signed Zone from NSEC to NSEC3
+
+ When transitioning an already signed and trusted zone to this
+ specification, care must be taken to prevent client validation
+ failures during the process.
+
+ The basic procedure is as follows:
+
+ 1. Transition all DNSKEYs to DNSKEYs using the algorithm aliases
+ described in Section 2. The actual method for safely and
+ securely changing the DNSKEY RRSet of the zone is outside the
+ scope of this specification. However, the end result MUST be
+ that all DS RRs in the parent use the specified algorithm
+ aliases.
+
+ After this transition is complete, all NSEC3-unaware clients will
+ treat the zone as insecure. At this point, the authoritative
+ server still returns negative and wildcard responses that contain
+ NSEC RRs.
+
+ 2. Add signed NSEC3 RRs to the zone, either incrementally or all at
+ once. If adding incrementally, then the last RRSet added MUST be
+ the NSEC3PARAM RRSet.
+
+ 3. Upon the addition of the NSEC3PARAM RRSet, the server switches to
+ serving negative and wildcard responses with NSEC3 RRs according
+ to this specification.
+
+ 4. Remove the NSEC RRs either incrementally or all at once.
+
+10.5. Transitioning a Signed Zone from NSEC3 to NSEC
+
+ To safely transition back to a DNSSEC [RFC4035] signed zone, simply
+ reverse the procedure above:
+
+ 1. Add NSEC RRs incrementally or all at once.
+
+ 2. Remove the NSEC3PARAM RRSet. This will signal the server to use
+ the NSEC RRs for negative and wildcard responses.
+
+ 3. Remove the NSEC3 RRs either incrementally or all at once.
+
+
+
+
+Laurie, et al. Standards Track [Page 28]
+
+RFC 5155 NSEC3 March 2008
+
+
+ 4. Transition all of the DNSKEYs to DNSSEC algorithm identifiers.
+ After this transition is complete, all NSEC3-unaware clients will
+ treat the zone as secure.
+
+11. IANA Considerations
+
+ Although the NSEC3 and NSEC3PARAM RR formats include a hash algorithm
+ parameter, this document does not define a particular mechanism for
+ safely transitioning from one NSEC3 hash algorithm to another. When
+ specifying a new hash algorithm for use with NSEC3, a transition
+ mechanism MUST also be defined.
+
+ This document updates the IANA registry "DOMAIN NAME SYSTEM
+ PARAMETERS" (http://www.iana.org/assignments/dns-parameters) in sub-
+ registry "TYPES", by defining two new types. Section 3 defines the
+ NSEC3 RR type 50. Section 4 defines the NSEC3PARAM RR type 51.
+
+ This document updates the IANA registry "DNS SECURITY ALGORITHM
+ NUMBERS -- per [RFC4035]"
+ (http://www.iana.org/assignments/dns-sec-alg-numbers). Section 2
+ defines the aliases DSA-NSEC3-SHA1 (6) and RSASHA1-NSEC3-SHA1 (7) for
+ respectively existing registrations DSA and RSASHA1 in combination
+ with NSEC3 hash algorithm SHA1.
+
+ Since these algorithm numbers are aliases for existing DNSKEY
+ algorithm numbers, the flags that exist for the original algorithm
+ are valid for the alias algorithm.
+
+ This document creates a new IANA registry for NSEC3 flags. This
+ registry is named "DNSSEC NSEC3 Flags". The initial contents of this
+ registry are:
+
+ 0 1 2 3 4 5 6 7
+ +---+---+---+---+---+---+---+---+
+ | | | | | | | |Opt|
+ | | | | | | | |Out|
+ +---+---+---+---+---+---+---+---+
+
+ bit 7 is the Opt-Out flag.
+
+ bits 0 - 6 are available for assignment.
+
+ Assignment of additional NSEC3 Flags in this registry requires IETF
+ Standards Action [RFC2434].
+
+ This document creates a new IANA registry for NSEC3PARAM flags. This
+ registry is named "DNSSEC NSEC3PARAM Flags". The initial contents of
+ this registry are:
+
+
+
+Laurie, et al. Standards Track [Page 29]
+
+RFC 5155 NSEC3 March 2008
+
+
+ 0 1 2 3 4 5 6 7
+ +---+---+---+---+---+---+---+---+
+ | | | | | | | | 0 |
+ +---+---+---+---+---+---+---+---+
+
+ bit 7 is reserved and must be 0.
+
+ bits 0 - 6 are available for assignment.
+
+ Assignment of additional NSEC3PARAM Flags in this registry requires
+ IETF Standards Action [RFC2434].
+
+ Finally, this document creates a new IANA registry for NSEC3 hash
+ algorithms. This registry is named "DNSSEC NSEC3 Hash Algorithms".
+ The initial contents of this registry are:
+
+ 0 is Reserved.
+
+ 1 is SHA-1.
+
+ 2-255 Available for assignment.
+
+ Assignment of additional NSEC3 hash algorithms in this registry
+ requires IETF Standards Action [RFC2434].
+
+12. Security Considerations
+
+12.1. Hashing Considerations
+
+12.1.1. Dictionary Attacks
+
+ The NSEC3 RRs are still susceptible to dictionary attacks (i.e., the
+ attacker retrieves all the NSEC3 RRs, then calculates the hashes of
+ all likely domain names, comparing against the hashes found in the
+ NSEC3 RRs, and thus enumerating the zone). These are substantially
+ more expensive than enumerating the original NSEC RRs would have
+ been, and in any case, such an attack could also be used directly
+ against the name server itself by performing queries for all likely
+ names, though this would obviously be more detectable. The expense
+ of this off-line attack can be chosen by setting the number of
+ iterations in the NSEC3 RR.
+
+ Zones are also susceptible to a pre-calculated dictionary attack --
+ that is, a list of hashes for all likely names is computed once, then
+ NSEC3 RR is scanned periodically and compared against the precomputed
+ hashes. This attack is prevented by changing the salt on a regular
+ basis.
+
+
+
+
+Laurie, et al. Standards Track [Page 30]
+
+RFC 5155 NSEC3 March 2008
+
+
+ The salt SHOULD be at least 64 bits long and unpredictable, so that
+ an attacker cannot anticipate the value of the salt and compute the
+ next set of dictionaries before the zone is published.
+
+12.1.2. Collisions
+
+ Hash collisions between QNAME and the owner name of an NSEC3 RR may
+ occur. When they do, it will be impossible to prove the non-
+ existence of the colliding QNAME. However, with SHA-1, this is
+ highly unlikely (on the order of 1 in 2^160). Note that DNSSEC
+ already relies on the presumption that a cryptographic hash function
+ is second pre-image resistant, since these hash functions are used
+ for generating and validating signatures and DS RRs.
+
+12.1.3. Transitioning to a New Hash Algorithm
+
+ Although the NSEC3 and NSEC3PARAM RR formats include a hash algorithm
+ parameter, this document does not define a particular mechanism for
+ safely transitioning from one NSEC3 hash algorithm to another. When
+ specifying a new hash algorithm for use with NSEC3, a transition
+ mechanism MUST also be defined. It is possible that the only
+ practical and palatable transition mechanisms may require an
+ intermediate transition to an insecure state, or to a state that uses
+ NSEC records instead of NSEC3.
+
+12.1.4. Using High Iteration Values
+
+ Since validators should treat responses containing NSEC3 RRs with
+ high iteration values as insecure, presence of just one signed NSEC3
+ RR with a high iteration value in a zone provides attackers with a
+ possible downgrade attack.
+
+ The attack is simply to remove any existing NSEC3 RRs from a
+ response, and replace or add a single (or multiple) NSEC3 RR that
+ uses a high iterations value to the response. Validators will then
+ be forced to treat the response as insecure. This attack would be
+ effective only when all of following conditions are met:
+
+ o There is at least one signed NSEC3 RR that uses a high iterations
+ value present in the zone.
+
+ o The attacker has access to one or more of these NSEC3 RRs. This
+ is trivially true when the NSEC3 RRs with high iteration values
+ are being returned in typical responses, but may also be true if
+ the attacker can access the zone via AXFR or IXFR queries, or any
+ other methodology.
+
+
+
+
+
+Laurie, et al. Standards Track [Page 31]
+
+RFC 5155 NSEC3 March 2008
+
+
+ Using a high number of iterations also introduces an additional
+ denial-of-service opportunity against servers, since servers must
+ calculate several hashes per negative or wildcard response.
+
+12.2. Opt-Out Considerations
+
+ The Opt-Out Flag (O) allows for unsigned names, in the form of
+ delegations to unsigned zones, to exist within an otherwise signed
+ zone. All unsigned names are, by definition, insecure, and their
+ validity or existence cannot be cryptographically proven.
+
+ In general:
+
+ o Resource records with unsigned names (whether existing or not)
+ suffer from the same vulnerabilities as RRs in an unsigned zone.
+ These vulnerabilities are described in more detail in [RFC3833]
+ (note in particular Section 2.3, "Name Chaining" and Section 2.6,
+ "Authenticated Denial of Domain Names").
+
+ o Resource records with signed names have the same security whether
+ or not Opt-Out is used.
+
+ Note that with or without Opt-Out, an insecure delegation may be
+ undetectably altered by an attacker. Because of this, the primary
+ difference in security when using Opt-Out is the loss of the ability
+ to prove the existence or nonexistence of an insecure delegation
+ within the span of an Opt-Out NSEC3 RR.
+
+ In particular, this means that a malicious entity may be able to
+ insert or delete RRs with unsigned names. These RRs are normally NS
+ RRs, but this also includes signed wildcard expansions (while the
+ wildcard RR itself is signed, its expanded name is an unsigned name).
+
+ Note that being able to add a delegation is functionally equivalent
+ to being able to add any RR type: an attacker merely has to forge a
+ delegation to name server under his/her control and place whatever
+ RRs needed at the subzone apex.
+
+ While in particular cases, this issue may not present a significant
+ security problem, in general it should not be lightly dismissed.
+ Therefore, it is strongly RECOMMENDED that Opt-Out be used sparingly.
+ In particular, zone signing tools SHOULD NOT default to using Opt-
+ Out, and MAY choose to not support Opt-Out at all.
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 32]
+
+RFC 5155 NSEC3 March 2008
+
+
+12.3. Other Considerations
+
+ Walking the NSEC3 RRs will reveal the total number of RRs in the zone
+ (plus empty non-terminals), and also what types there are. This
+ could be mitigated by adding dummy entries, but certainly an upper
+ limit can always be found.
+
+13. References
+
+13.1. Normative References
+
+ [RFC1034] Mockapetris, P., "Domain names - concepts and
+ facilities", STD 13, RFC 1034, November 1987.
+
+ [RFC1035] Mockapetris, P., "Domain names - implementation and
+ specification", STD 13, RFC 1035, November 1987.
+
+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
+ Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+ [RFC2136] Vixie, P., Thomson, S., Rekhter, Y., and J. Bound,
+ "Dynamic Updates in the Domain Name System (DNS
+ UPDATE)", RFC 2136, April 1997.
+
+ [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS
+ Specification", RFC 2181, July 1997.
+
+ [RFC2308] Andrews, M., "Negative Caching of DNS Queries (DNS
+ NCACHE)", RFC 2308, March 1998.
+
+ [RFC2434] Narten, T. and H. Alvestrand, "Guidelines for
+ Writing an IANA Considerations Section in RFCs",
+ BCP 26, RFC 2434, October 1998.
+
+ [RFC2929] Eastlake, D., Brunner-Williams, E., and B. Manning,
+ "Domain Name System (DNS) IANA Considerations",
+ BCP 42, RFC 2929, September 2000.
+
+ [RFC3597] Gustafsson, A., "Handling of Unknown DNS Resource
+ Record (RR) Types", RFC 3597, September 2003.
+
+ [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D.,
+ and S. Rose, "DNS Security Introduction and
+ Requirements", RFC 4033, March 2005.
+
+ [RFC4034] Arends, R., Austein, R., Larson, M., Massey, D.,
+ and S. Rose, "Resource Records for the DNS Security
+ Extensions", RFC 4034, March 2005.
+
+
+
+Laurie, et al. Standards Track [Page 33]
+
+RFC 5155 NSEC3 March 2008
+
+
+ [RFC4035] Arends, R., Austein, R., Larson, M., Massey, D.,
+ and S. Rose, "Protocol Modifications for the DNS
+ Security Extensions", RFC 4035, March 2005.
+
+ [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data
+ Encodings", RFC 4648, October 2006.
+
+13.2. Informative References
+
+ [DNSEXT-NO] Josefsson, S., "Authenticating Denial of Existence
+ in DNS with Minimum Disclosure", Work in Progress,
+ July 2000.
+
+ [DNSEXT-NSEC2v2] Laurie, B., "DNSSEC NSEC2 Owner and RDATA Format",
+ Work in Progress, December 2004.
+
+ [RFC2672] Crawford, M., "Non-Terminal DNS Name Redirection",
+ RFC 2672, August 1999.
+
+ [RFC2898] Kaliski, B., "PKCS #5: Password-Based Cryptography
+ Specification Version 2.0", RFC 2898,
+ September 2000.
+
+ [RFC3833] Atkins, D. and R. Austein, "Threat Analysis of the
+ Domain Name System (DNS)", RFC 3833, August 2004.
+
+ [RFC4592] Lewis, E., "The Role of Wildcards in the Domain
+ Name System", RFC 4592, July 2006.
+
+ [RFC4956] Arends, R., Kosters, M., and D. Blacka, "DNS
+ Security (DNSSEC) Opt-In", RFC 4956, July 2007.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 34]
+
+RFC 5155 NSEC3 March 2008
+
+
+Appendix A. Example Zone
+
+ This is a zone showing its NSEC3 RRs. They can also be used as test
+ vectors for the hash algorithm.
+
+ The overall TTL and class are specified in the SOA RR, and are
+ subsequently omitted for clarity.
+
+ The zone is preceded by a list that contains the hashes of the
+ original ownernames.
+
+ ; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+ ; H(a.example) = 35mthgpgcu1qg68fab165klnsnk3dpvl
+ ; H(ai.example) = gjeqe526plbf1g8mklp59enfd789njgi
+ ; H(ns1.example) = 2t7b4g4vsa5smi47k61mv5bv1a22bojr
+ ; H(ns2.example) = q04jkcevqvmu85r014c7dkba38o0ji5r
+ ; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h
+ ; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en
+ ; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995
+ ; H(y.w.example) = ji6neoaepv8b5o6k4ev33abha8ht9fgc
+ ; H(x.y.w.example) = 2vptu5timamqttgl4luu9kg21e0aor3s
+ ; H(xx.example) = t644ebqk9bibcna874givr6joj62mlhv
+ ; H(2t7b4g4vsa5smi47k61mv5bv1a22bojr.example)
+ ; = kohar7mbb8dc2ce8a9qvl8hon4k53uhi
+ example. 3600 IN SOA ns1.example. bugs.x.w.example. 1 3600 300 (
+ 3600000 3600 )
+ RRSIG SOA 7 1 3600 20150420235959 20051021000000 (
+ 40430 example.
+ Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i
+ q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd
+ VI2LmKusbZsT0Q== )
+ NS ns1.example.
+ NS ns2.example.
+ RRSIG NS 7 1 3600 20150420235959 20051021000000 (
+ 40430 example.
+ PVOgtMK1HHeSTau+HwDWC8Ts+6C8qtqd4pQJ
+ qOtdEVgg+MA+ai4fWDEhu3qHJyLcQ9tbD2vv
+ CnMXjtz6SyObxA== )
+ MX 1 xx.example.
+ RRSIG MX 7 1 3600 20150420235959 20051021000000 (
+ 40430 example.
+ GgQ1A9xs47k42VPvpL/a1BWUz/6XsnHkjotw
+ 9So8MQtZtl2wJBsnOQsaoHrRCrRbyriEl/GZ
+ n9Mto/Kx+wBo+w== )
+ DNSKEY 256 3 7 AwEAAaetidLzsKWUt4swWR8yu0wPHPiUi8LU (
+ sAD0QPWU+wzt89epO6tHzkMBVDkC7qphQO2h
+ TY4hHn9npWFRw5BYubE= )
+
+
+
+
+Laurie, et al. Standards Track [Page 35]
+
+RFC 5155 NSEC3 March 2008
+
+
+ DNSKEY 257 3 7 AwEAAcUlFV1vhmqx6NSOUOq2R/dsR7Xm3upJ (
+ j7IommWSpJABVfW8Q0rOvXdM6kzt+TAu92L9
+ AbsUdblMFin8CVF3n4s= )
+ RRSIG DNSKEY 7 1 3600 20150420235959 (
+ 20051021000000 12708 example.
+ AuU4juU9RaxescSmStrQks3Gh9FblGBlVU31
+ uzMZ/U/FpsUb8aC6QZS+sTsJXnLnz7flGOsm
+ MGQZf3bH+QsCtg== )
+ NSEC3PARAM 1 0 12 aabbccdd
+ RRSIG NSEC3PARAM 7 1 3600 20150420235959 (
+ 20051021000000 40430 example.
+ C1Gl8tPZNtnjlrYWDeeUV/sGLCyy/IHie2re
+ rN05XSA3Pq0U3+4VvGWYWdUMfflOdxqnXHwJ
+ TLQsjlkynhG6Cg== )
+ 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (
+ 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS
+ SOA NSEC3PARAM RRSIG )
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL
+ IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762
+ BOCXJZMnpuwhpA== )
+ 2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. A 192.0.2.127
+ RRSIG A 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ h6c++bzhRuWWt2bykN6mjaTNBcXNq5UuL5Ed
+ K+iDP4eY8I0kSiKaCjg3tC1SQkeloMeub2GW
+ k8p6xHMPZumXlw== )
+ NSEC3 1 1 12 aabbccdd (
+ 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG )
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ OmBvJ1Vgg1hCKMXHFiNeIYHK9XVW0iLDLwJN
+ 4TFoNxZuP03gAXEI634YwOc4YBNITrj413iq
+ NI6mRk/r1dOSUw== )
+ 2vptu5timamqttgl4luu9kg21e0aor3s.example. NSEC3 1 1 12 aabbccdd (
+ 35mthgpgcu1qg68fab165klnsnk3dpvl MX RRSIG )
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ KL1V2oFYghNV0Hm7Tf2vpJjM6l+0g1JCcVYG
+ VfI0lKrhPmTsOA96cLEACgo1x8I7kApJX+ob
+ TuktZ+sdsZPY1w== )
+ 35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd (
+ b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 36]
+
+RFC 5155 NSEC3 March 2008
+
+
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ
+ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ
+ XtAIR3chwgW+SA== )
+ a.example. NS ns1.a.example.
+ NS ns2.a.example.
+ DS 58470 5 1 (
+ 3079F1593EBAD6DC121E202A8B766A6A4837206C )
+ RRSIG DS 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ XacFcQVHLVzdoc45EJhN616zQ4mEXtE8FzUh
+ M2KWjfy1VfRKD9r1MeVGwwoukOKgJxBPFsWo
+ o722vZ4UZ2dIdA== )
+ ns1.a.example. A 192.0.2.5
+ ns2.a.example. A 192.0.2.6
+ ai.example. A 192.0.2.9
+ RRSIG A 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ hVe+wKYMlObTRPhX0NL67GxeZfdxqr/QeR6F
+ tfdAj5+FgYxyzPEjIzvKWy00hWIl6wD3Vws+
+ rznEn8sQ64UdqA== )
+ HINFO "KLH-10" "ITS"
+ RRSIG HINFO 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ Yi42uOq43eyO6qXHNvwwfFnIustWgV5urFcx
+ enkLvs6pKRh00VBjODmf3Z4nMO7IOl6nHSQ1
+ v0wLHpEZG7Xj2w== )
+ AAAA 2001:db8:0:0:0:0:f00:baa9
+ RRSIG AAAA 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ LcdxKaCB5bGZwPDg+3JJ4O02zoMBrjxqlf6W
+ uaHQZZfTUpb9Nf2nxFGe2XRPfR5tpJT6GdRG
+ cHueLuXkMjBArQ== )
+ b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd (
+ gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh
+ 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3
+ pOv0TSTyiTxIZg== )
+ c.example. NS ns1.c.example.
+ NS ns2.c.example.
+ ns1.c.example. A 192.0.2.7
+ ns2.c.example. A 192.0.2.8
+ gjeqe526plbf1g8mklp59enfd789njgi.example. NSEC3 1 1 12 aabbccdd (
+ ji6neoaepv8b5o6k4ev33abha8ht9fgc HINFO A AAAA
+ RRSIG )
+
+
+
+Laurie, et al. Standards Track [Page 37]
+
+RFC 5155 NSEC3 March 2008
+
+
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ IVnezTJ9iqblFF97vPSmfXZ5Zozngx3KX3by
+ LTZC4QBH2dFWhf6scrGFZB980AfCxoD9qbbK
+ Dy+rdGIeRSVNyw== )
+ ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. NSEC3 1 1 12 aabbccdd (
+ k8udemvp1j2f7eg6jebps17vp3n8i58h )
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ gPkFp1s2QDQ6wQzcg1uSebZ61W33rUBDcTj7
+ 2F3kQ490fEdp7k1BUIfbcZtPbX3YCpE+sIt0
+ MpzVSKfTwx4uYA== )
+ k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd (
+ kohar7mbb8dc2ce8a9qvl8hon4k53uhi )
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK
+ S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt
+ Otx7w9WfcIg62A== )
+ kohar7mbb8dc2ce8a9qvl8hon4k53uhi.example. NSEC3 1 1 12 aabbccdd (
+ q04jkcevqvmu85r014c7dkba38o0ji5r A RRSIG )
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ VrDXs2uVW21N08SyQIz88zml+y4ZCInTwgDr
+ 6zz43yAg+LFERjOrj3Ojct51ac7Dp4eZbf9F
+ QJazmASFKGxGXg== )
+ ns1.example. A 192.0.2.1
+ RRSIG A 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ bu6kx73n6XEunoVGuRfAgY7EF/AJqHy7hj0j
+ kiqJjB0dOrx3wuz9SaBeGfqWIdn/uta3SavN
+ 4FRvZR9SCFHF5Q== )
+ ns2.example. A 192.0.2.2
+ RRSIG A 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ ktQ3TqE0CfRfki0Rb/Ip5BM0VnxelbuejCC4
+ zpLbFKA/7eD7UNAwxMgxJPtbdST+syjYSJaj
+ 4IHfeX6n8vfoGA== )
+ q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd (
+ r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3
+ ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN
+ NlkxWcLsIlMmUg== )
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 38]
+
+RFC 5155 NSEC3 March 2008
+
+
+ r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd (
+ t644ebqk9bibcna874givr6joj62mlhv MX RRSIG )
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C
+ ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+
+ HF1FWKW7RIJdtQ== )
+ t644ebqk9bibcna874givr6joj62mlhv.example. NSEC3 1 1 12 aabbccdd (
+ 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom HINFO A AAAA
+ RRSIG )
+ RRSIG NSEC3 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ RAjGECB8P7O+F4Pa4Dx3tC0M+Z3KmlLKImca
+ fb9XWwx+NWUNz7NBEDBQHivIyKPVDkChcePI
+ X1xPl1ATNa+8Dw== )
+ *.w.example. MX 1 ai.example.
+ RRSIG MX 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ CikebjQwGQPwijVcxgcZcSJKtfynugtlBiKb
+ 9FcBTrmOoyQ4InoWVudhCWsh/URX3lc4WRUM
+ ivEBP6+4KS3ldA== )
+ x.w.example. MX 1 xx.example.
+ RRSIG MX 7 3 3600 20150420235959 20051021000000 (
+ 40430 example.
+ IrK3tq/tHFIBF0scHiE/1IwMAvckS/55hAVv
+ QyxTFbkAdDloP3NbZzu+yoSsr3b3OX6qbBpY
+ 7WCtwwekLKRAwQ== )
+ x.y.w.example. MX 1 xx.example.
+ RRSIG MX 7 4 3600 20150420235959 20051021000000 (
+ 40430 example.
+ MqSt5HqJIN8+SLlzTOImrh5h9Xa6gDvAW/Gn
+ nbdPc6Z7nXvCpLPJj/5lCwx3VuzVOjkbvXze
+ 8/8Ccl2Zn2hbug== )
+ xx.example. A 192.0.2.10
+ RRSIG A 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ T35hBWEZ017VC5u2c4OriKyVn/pu+fVK4AlX
+ YOxJ6iQylfV2HQIKjv6b7DzINB3aF/wjJqgX
+ pQvhq+Ac6+ZiFg== )
+ HINFO "KLH-10" "TOPS-20"
+ RRSIG HINFO 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ KimG+rDd+7VA1zRsu0ITNAQUTRlpnsmqWrih
+ FRnU+bRa93v2e5oFNFYCs3Rqgv62K93N7AhW
+ 6Jfqj/8NzWjvKg== )
+ AAAA 2001:db8:0:0:0:0:f00:baaa
+
+
+
+
+
+Laurie, et al. Standards Track [Page 39]
+
+RFC 5155 NSEC3 March 2008
+
+
+ RRSIG AAAA 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ IXBcXORITNwd8h3gNwyxtYFvAupS/CYWufVe
+ uBUX0O25ivBCULjZjpDxFSxfohb/KA7YRdxE
+ NzYfMItpILl/Xw== )
+
+Appendix B. Example Responses
+
+ The examples in this section show response messages using the signed
+ zone example in Appendix A.
+
+B.1. Name Error
+
+ An authoritative name error. The NSEC3 RRs prove that the name does
+ not exist and that there is no wildcard RR that should have been
+ expanded.
+
+;; Header: QR AA DO RCODE=3
+;;
+;; Question
+a.c.x.w.example. IN A
+
+;; Answer
+;; (empty)
+
+;; Authority
+
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 (
+ 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 (
+ 40430 example.
+ Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i
+ q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd
+ VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR that covers the "next closer" name (c.x.w.example)
+;; H(c.x.w.example) = 0va5bpr2ou0vk0lbqeeljri88laipsfh
+
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (
+ 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS
+ SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL
+ IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762
+ BOCXJZMnpuwhpA== )
+
+
+
+
+
+Laurie, et al. Standards Track [Page 40]
+
+RFC 5155 NSEC3 March 2008
+
+
+;; NSEC3 RR that matches the closest encloser (x.w.example)
+;; H(x.w.example) = b4um86eghhds6nea196smvmlo4ors995
+
+b4um86eghhds6nea196smvmlo4ors995.example. NSEC3 1 1 12 aabbccdd (
+ gjeqe526plbf1g8mklp59enfd789njgi MX RRSIG )
+b4um86eghhds6nea196smvmlo4ors995.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ ZkPG3M32lmoHM6pa3D6gZFGB/rhL//Bs3Omh
+ 5u4m/CUiwtblEVOaAKKZd7S959OeiX43aLX3
+ pOv0TSTyiTxIZg== )
+
+;; NSEC3 RR that covers wildcard at the closest encloser (*.x.w.example)
+;; H(*.x.w.example) = 92pqneegtaue7pjatc3l3qnk738c6v5m
+
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd (
+ b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ
+ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ
+ XtAIR3chwgW+SA== )
+
+;; Additional
+;; (empty)
+
+ The query returned three NSEC3 RRs that prove that the requested data
+ does not exist and that no wildcard expansion applies. The negative
+ response is authenticated by verifying the NSEC3 RRs. The
+ corresponding RRSIGs indicate that the NSEC3 RRs are signed by an
+ "example" DNSKEY of algorithm 7 and with key tag 40430. The resolver
+ needs the corresponding DNSKEY RR in order to authenticate this
+ answer.
+
+ One of the owner names of the NSEC3 RRs matches the closest encloser.
+ One of the NSEC3 RRs prove that there exists no longer name. One of
+ the NSEC3 RRs prove that there exists no wildcard RRSets that should
+ have been expanded. The closest encloser can be found by applying
+ the algorithm in Section 8.3.
+
+ In the above example, the name 'x.w.example' hashes to
+ 'b4um86eghhds6nea196smvmlo4ors995'. This indicates that this might
+ be the closest encloser. To prove that 'c.x.w.example' and
+ '*.x.w.example' do not exist, these names are hashed to,
+ respectively, '0va5bpr2ou0vk0lbqeeljri88laipsfh' and
+ '92pqneegtaue7pjatc3l3qnk738c6v5m'. The first and last NSEC3 RRs
+ prove that these hashed owner names do not exist.
+
+
+
+
+
+Laurie, et al. Standards Track [Page 41]
+
+RFC 5155 NSEC3 March 2008
+
+
+B.2. No Data Error
+
+ A "no data" response. The NSEC3 RR proves that the name exists and
+ that the requested RR type does not.
+
+;; Header: QR AA DO RCODE=0
+;;
+;; Question
+ns1.example. IN MX
+
+;; Answer
+;; (empty)
+
+;; Authority
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 (
+ 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 (
+ 40430 example.
+ Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i
+ q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd
+ VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR matches the QNAME and shows that the MX type bit is not set.
+
+2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. NSEC3 1 1 12 aabbccdd (
+ 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG )
+2t7b4g4vsa5smi47k61mv5bv1a22bojr.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ OmBvJ1Vgg1hCKMXHFiNeIYHK9XVW0iLDLwJN
+ 4TFoNxZuP03gAXEI634YwOc4YBNITrj413iq
+ NI6mRk/r1dOSUw== )
+;; Additional
+;; (empty)
+
+ The query returned an NSEC3 RR that proves that the requested name
+ exists ("ns1.example." hashes to "2t7b4g4vsa5smi47k61mv5bv1a22bojr"),
+ but the requested RR type does not exist (type MX is absent in the
+ type code list of the NSEC3 RR), and was not a CNAME (type CNAME is
+ also absent in the type code list of the NSEC3 RR).
+
+
+
+
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 42]
+
+RFC 5155 NSEC3 March 2008
+
+
+B.2.1. No Data Error, Empty Non-Terminal
+
+ A "no data" response because of an empty non-terminal. The NSEC3 RR
+ proves that the name exists and that the requested RR type does not.
+
+ ;; Header: QR AA DO RCODE=0
+ ;;
+ ;; Question
+ y.w.example. IN A
+
+ ;; Answer
+ ;; (empty)
+
+ ;; Authority
+ example. SOA ns1.example. bugs.x.w.example. 1 3600 300 (
+ 3600000 3600 )
+ example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 (
+ 40430 example.
+ Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i
+ q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd
+ VI2LmKusbZsT0Q== )
+
+ ;; NSEC3 RR matches the QNAME and shows that the A type bit is not set.
+
+ ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. NSEC3 1 1 12 aabbccdd (
+ k8udemvp1j2f7eg6jebps17vp3n8i58h )
+ ji6neoaepv8b5o6k4ev33abha8ht9fgc.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ gPkFp1s2QDQ6wQzcg1uSebZ61W33rUBDcTj7
+ 2F3kQ490fEdp7k1BUIfbcZtPbX3YCpE+sIt0
+ MpzVSKfTwx4uYA== )
+
+ ;; Additional
+ ;; (empty)
+
+ The query returned an NSEC3 RR that proves that the requested name
+ exists ("y.w.example." hashes to "ji6neoaepv8b5o6k4ev33abha8ht9fgc"),
+ but the requested RR type does not exist (Type A is absent in the
+ Type Bit Maps field of the NSEC3 RR). Note that, unlike an empty
+ non-terminal proof using NSECs, this is identical to a No Data Error.
+ This example is solely mentioned to be complete.
+
+
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 43]
+
+RFC 5155 NSEC3 March 2008
+
+
+B.3. Referral to an Opt-Out Unsigned Zone
+
+ The NSEC3 RRs prove that nothing for this delegation was signed.
+ There is no proof that the unsigned delegation exists.
+
+ ;; Header: QR DO RCODE=0
+ ;;
+ ;; Question
+ mc.c.example. IN MX
+
+ ;; Answer
+ ;; (empty)
+
+ ;; Authority
+ c.example. NS ns1.c.example.
+ NS ns2.c.example.
+
+ ;; NSEC3 RR that covers the "next closer" name (c.example)
+ ;; H(c.example) = 4g6p9u5gvfshp30pqecj98b3maqbn1ck
+
+ 35mthgpgcu1qg68fab165klnsnk3dpvl.example. NSEC3 1 1 12 aabbccdd (
+ b4um86eghhds6nea196smvmlo4ors995 NS DS RRSIG )
+ 35mthgpgcu1qg68fab165klnsnk3dpvl.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ g6jPUUpduAJKRljUsN8gB4UagAX0NxY9shwQ
+ Aynzo8EUWH+z6hEIBlUTPGj15eZll6VhQqgZ
+ XtAIR3chwgW+SA== )
+
+ ;; NSEC3 RR that matches the closest encloser (example)
+ ;; H(example) = 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom
+
+ 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (
+ 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS
+ SOA NSEC3PARAM RRSIG )
+ 0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL
+ IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762
+ BOCXJZMnpuwhpA== )
+
+ ;; Additional
+ ns1.c.example. A 192.0.2.7
+ ns2.c.example. A 192.0.2.8
+
+ The query returned a referral to the unsigned "c.example." zone. The
+ response contains the closest provable encloser of "c.example" to be
+ "example", since the hash of "c.example"
+
+
+
+
+Laurie, et al. Standards Track [Page 44]
+
+RFC 5155 NSEC3 March 2008
+
+
+ ("4g6p9u5gvfshp30pqecj98b3maqbn1ck") is covered by the first NSEC3 RR
+ and its Opt-Out bit is set.
+
+B.4. Wildcard Expansion
+
+ A query that was answered with a response containing a wildcard
+ expansion. The label count in the RRSIG RRSet in the answer section
+ indicates that a wildcard RRSet was expanded to produce this
+ response, and the NSEC3 RR proves that no "next closer" name exists
+ in the zone.
+
+ ;; Header: QR AA DO RCODE=0
+ ;;
+ ;; Question
+ a.z.w.example. IN MX
+
+ ;; Answer
+ a.z.w.example. MX 1 ai.example.
+ a.z.w.example. RRSIG MX 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ CikebjQwGQPwijVcxgcZcSJKtfynugtlBiKb
+ 9FcBTrmOoyQ4InoWVudhCWsh/URX3lc4WRUM
+ ivEBP6+4KS3ldA== )
+
+ ;; Authority
+ example. NS ns1.example.
+ example. NS ns2.example.
+ example. RRSIG NS 7 1 3600 20150420235959 20051021000000 (
+ 40430 example.
+ PVOgtMK1HHeSTau+HwDWC8Ts+6C8qtqd4pQJ
+ qOtdEVgg+MA+ai4fWDEhu3qHJyLcQ9tbD2vv
+ CnMXjtz6SyObxA== )
+
+ ;; NSEC3 RR that covers the "next closer" name (z.w.example)
+ ;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03
+
+ q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd (
+ r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+ q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3
+ ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN
+ NlkxWcLsIlMmUg== )
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 45]
+
+RFC 5155 NSEC3 March 2008
+
+
+ ;; Additional
+ ai.example. A 192.0.2.9
+ ai.example. RRSIG A 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ hVe+wKYMlObTRPhX0NL67GxeZfdxqr/QeR6F
+ tfdAj5+FgYxyzPEjIzvKWy00hWIl6wD3Vws+
+ rznEn8sQ64UdqA== )
+ ai.example. AAAA 2001:db8:0:0:0:0:f00:baa9
+ ai.example. RRSIG AAAA 7 2 3600 20150420235959 20051021000000 (
+ 40430 example.
+ LcdxKaCB5bGZwPDg+3JJ4O02zoMBrjxqlf6W
+ uaHQZZfTUpb9Nf2nxFGe2XRPfR5tpJT6GdRG
+ cHueLuXkMjBArQ== )
+
+ The query returned an answer that was produced as a result of a
+ wildcard expansion. The answer section contains a wildcard RRSet
+ expanded as it would be in a traditional DNS response. The RRSIG
+ Labels field value of 2 indicates that the answer is the result of a
+ wildcard expansion, as the "a.z.w.example" name contains 4 labels.
+ This also shows that "w.example" exists, so there is no need for an
+ NSEC3 RR that matches the closest encloser.
+
+ The NSEC3 RR proves that no closer match could have been used to
+ answer this query.
+
+B.5. Wildcard No Data Error
+
+ A "no data" response for a name covered by a wildcard. The NSEC3 RRs
+ prove that the matching wildcard name does not have any RRs of the
+ requested type and that no closer match exists in the zone.
+
+ ;; Header: QR AA DO RCODE=0
+ ;;
+ ;; Question
+ a.z.w.example. IN AAAA
+
+ ;; Answer
+ ;; (empty)
+
+ ;; Authority
+ example. SOA ns1.example. bugs.x.w.example. 1 3600 300 (
+ 3600000 3600 )
+ example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 (
+ 40430 example.
+ Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i
+ q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd
+ VI2LmKusbZsT0Q== )
+
+
+
+
+Laurie, et al. Standards Track [Page 46]
+
+RFC 5155 NSEC3 March 2008
+
+
+ ;; NSEC3 RR that matches the closest encloser (w.example)
+ ;; H(w.example) = k8udemvp1j2f7eg6jebps17vp3n8i58h
+
+ k8udemvp1j2f7eg6jebps17vp3n8i58h.example. NSEC3 1 1 12 aabbccdd (
+ kohar7mbb8dc2ce8a9qvl8hon4k53uhi )
+ k8udemvp1j2f7eg6jebps17vp3n8i58h.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ FtXGbvF0+wf8iWkyo73enAuVx03klN+pILBK
+ S6qCcftVtfH4yVzsEZquJ27NHR7ruxJWDNMt
+ Otx7w9WfcIg62A== )
+
+ ;; NSEC3 RR that covers the "next closer" name (z.w.example)
+ ;; H(z.w.example) = qlu7gtfaeh0ek0c05ksfhdpbcgglbe03
+
+ q04jkcevqvmu85r014c7dkba38o0ji5r.example. NSEC3 1 1 12 aabbccdd (
+ r53bq7cc2uvmubfu5ocmm6pers9tk9en A RRSIG )
+ q04jkcevqvmu85r014c7dkba38o0ji5r.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ hV5I89b+4FHJDATp09g4bbN0R1F845CaXpL3
+ ZxlMKimoPAyqletMlEWwLfFia7sdpSzn+ZlN
+ NlkxWcLsIlMmUg== )
+
+ ;; NSEC3 RR that matches a wildcard at the closest encloser.
+ ;; H(*.w.example) = r53bq7cc2uvmubfu5ocmm6pers9tk9en
+
+ r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. NSEC3 1 1 12 aabbccdd (
+ t644ebqk9bibcna874givr6joj62mlhv MX RRSIG )
+ r53bq7cc2uvmubfu5ocmm6pers9tk9en.example. RRSIG NSEC3 7 2 3600 (
+ 20150420235959 20051021000000 40430 example.
+ aupviViruXs4bDg9rCbezzBMf9h1ZlDvbW/C
+ ZFKulIGXXLj8B/fsDJarXVDA9bnUoRhEbKp+
+ HF1FWKW7RIJdtQ== )
+
+ ;; Additional
+ ;; (empty)
+
+ The query returned the NSEC3 RRs that prove that the requested data
+ does not exist and no wildcard RR applies.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 47]
+
+RFC 5155 NSEC3 March 2008
+
+
+B.6. DS Child Zone No Data Error
+
+ A "no data" response for a QTYPE=DS query that was mistakenly sent to
+ a name server for the child zone.
+
+;; Header: QR AA DO RCODE=0
+;;
+;; Question
+example. IN DS
+
+;; Answer
+;; (empty)
+
+;; Authority
+example. SOA ns1.example. bugs.x.w.example. 1 3600 300 (
+ 3600000 3600 )
+example. RRSIG SOA 7 1 3600 20150420235959 20051021000000 (
+ 40430 example.
+ Hu25UIyNPmvPIVBrldN+9Mlp9Zql39qaUd8i
+ q4ZLlYWfUUbbAS41pG+68z81q1xhkYAcEyHd
+ VI2LmKusbZsT0Q== )
+
+;; NSEC3 RR matches the QNAME and shows that the DS type bit is not set.
+
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. NSEC3 1 1 12 aabbccdd (
+ 2t7b4g4vsa5smi47k61mv5bv1a22bojr MX DNSKEY NS
+ SOA NSEC3PARAM RRSIG )
+0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example. RRSIG NSEC3 7 2 3600
+ 20150420235959 20051021000000 40430 example.
+ OSgWSm26B+cS+dDL8b5QrWr/dEWhtCsKlwKL
+ IBHYH6blRxK9rC0bMJPwQ4mLIuw85H2EY762
+ BOCXJZMnpuwhpA== )
+
+;; Additional
+;; (empty)
+
+ The query returned an NSEC3 RR showing that the requested was
+ answered by the server authoritative for the zone "example". The
+ NSEC3 RR indicates the presence of an SOA RR, showing that this NSEC3
+ RR is from the apex of the child, not from the zone cut of the
+ parent. Queries for the "example" DS RRSet should be sent to the
+ parent servers (which are in this case the root servers).
+
+Appendix C. Special Considerations
+
+ The following paragraphs clarify specific behavior and explain
+ special considerations for implementations.
+
+
+
+
+Laurie, et al. Standards Track [Page 48]
+
+RFC 5155 NSEC3 March 2008
+
+
+C.1. Salting
+
+ Augmenting original owner names with salt before hashing increases
+ the cost of a dictionary of pre-generated hash-values. For every bit
+ of salt, the cost of a precomputed dictionary doubles (because there
+ must be an entry for each word combined with each possible salt
+ value). The NSEC3 RR can use a maximum of 2040 bits (255 octets) of
+ salt, multiplying the cost by 2^2040. This means that an attacker
+ must, in practice, recompute the dictionary each time the salt is
+ changed.
+
+ Including a salt, regardless of size, does not affect the cost of
+ constructing NSEC3 RRs. It does increase the size of the NSEC3 RR.
+
+ There MUST be at least one complete set of NSEC3 RRs for the zone
+ using the same salt value.
+
+ The salt SHOULD be changed periodically to prevent pre-computation
+ using a single salt. It is RECOMMENDED that the salt be changed for
+ every re-signing.
+
+ Note that this could cause a resolver to see RRs with different salt
+ values for the same zone. This is harmless, since each RR stands
+ alone (that is, it denies the set of owner names whose hashes, using
+ the salt in the NSEC3 RR, fall between the two hashes in the NSEC3
+ RR) -- it is only the server that needs a complete set of NSEC3 RRs
+ with the same salt in order to be able to answer every possible
+ query.
+
+ There is no prohibition with having NSEC3 RRs with different salts
+ within the same zone. However, in order for authoritative servers to
+ be able to consistently find covering NSEC3 RRs, the authoritative
+ server MUST choose a single set of parameters (algorithm, salt, and
+ iterations) to use when selecting NSEC3 RRs.
+
+C.2. Hash Collision
+
+ Hash collisions occur when different messages have the same hash
+ value. The expected number of domain names needed to give a 1 in 2
+ chance of a single collision is about 2^(n/2) for a hash of length n
+ bits (i.e., 2^80 for SHA-1). Though this probability is extremely
+ low, the following paragraphs deal with avoiding collisions and
+ assessing possible damage in the event of an attack using hash
+ collisions.
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 49]
+
+RFC 5155 NSEC3 March 2008
+
+
+C.2.1. Avoiding Hash Collisions During Generation
+
+ During generation of NSEC3 RRs, hash values are supposedly unique.
+ In the (academic) case of a collision occurring, an alternative salt
+ MUST be chosen and all hash values MUST be regenerated.
+
+C.2.2. Second Preimage Requirement Analysis
+
+ A cryptographic hash function has a second-preimage resistance
+ property. The second-preimage resistance property means that it is
+ computationally infeasible to find another message with the same hash
+ value as a given message, i.e., given preimage X, to find a second
+ preimage X' != X such that hash(X) = hash(X'). The work factor for
+ finding a second preimage is of the order of 2^160 for SHA-1. To
+ mount an attack using an existing NSEC3 RR, an adversary needs to
+ find a second preimage.
+
+ Assuming an adversary is capable of mounting such an extreme attack,
+ the actual damage is that a response message can be generated that
+ claims that a certain QNAME (i.e., the second pre-image) does exist,
+ while in reality QNAME does not exist (a false positive), which will
+ either cause a security-aware resolver to re-query for the non-
+ existent name, or to fail the initial query. Note that the adversary
+ can't mount this attack on an existing name, but only on a name that
+ the adversary can't choose and that does not yet exist.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 50]
+
+RFC 5155 NSEC3 March 2008
+
+
+Authors' Addresses
+
+ Ben Laurie
+ Nominet
+ 17 Perryn Road
+ London W3 7LR
+ England
+
+ Phone: +44 20 8735 0686
+ EMail: ben@links.org
+
+
+ Geoffrey Sisson
+ Nominet
+ Minerva House
+ Edmund Halley Road
+ Oxford Science Park
+ Oxford OX4 4DQ
+ UNITED KINGDOM
+
+ Phone: +44 1865 332211
+ EMail: geoff-s@panix.com
+
+
+ Roy Arends
+ Nominet
+ Minerva House
+ Edmund Halley Road
+ Oxford Science Park
+ Oxford OX4 4DQ
+ UNITED KINGDOM
+
+ Phone: +44 1865 332211
+ EMail: roy@nominet.org.uk
+
+
+ David Blacka
+ VeriSign, Inc.
+ 21355 Ridgetop Circle
+ Dulles, VA 20166
+ US
+
+ Phone: +1 703 948 3200
+ EMail: davidb@verisign.com
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 51]
+
+RFC 5155 NSEC3 March 2008
+
+
+Full Copyright Statement
+
+ Copyright (C) The IETF Trust (2008).
+
+ This document is subject to the rights, licenses and restrictions
+ contained in BCP 78, and except as set forth therein, the authors
+ retain all their rights.
+
+ This document and the information contained herein are provided on an
+ "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+ OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
+ THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
+ THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+ WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+ The IETF takes no position regarding the validity or scope of any
+ Intellectual Property Rights or other rights that might be claimed to
+ pertain to the implementation or use of the technology described in
+ this document or the extent to which any license under such rights
+ might or might not be available; nor does it represent that it has
+ made any independent effort to identify any such rights. Information
+ on the procedures with respect to rights in RFC documents can be
+ found in BCP 78 and BCP 79.
+
+ Copies of IPR disclosures made to the IETF Secretariat and any
+ assurances of licenses to be made available, or the result of an
+ attempt made to obtain a general license or permission for the use of
+ such proprietary rights by implementers or users of this
+ specification can be obtained from the IETF on-line IPR repository at
+ http://www.ietf.org/ipr.
+
+ The IETF invites any interested party to bring to its attention any
+ copyrights, patents or patent applications, or other proprietary
+ rights that may cover technology that may be required to implement
+ this standard. Please address the information to the IETF at
+ ietf-ipr@ietf.org.
+
+
+
+
+
+
+
+
+
+
+
+
+Laurie, et al. Standards Track [Page 52]
+
diff --git a/doc/rfc/rfc952.txt b/doc/rfc/rfc952.txt
new file mode 100644
index 0000000..7df339a
--- /dev/null
+++ b/doc/rfc/rfc952.txt
@@ -0,0 +1,340 @@
+Network Working Group K. Harrenstien (SRI)
+Request for Comments: 952 M. Stahl (SRI)
+ E. Feinler (SRI)
+Obsoletes: RFC 810, 608 October 1985
+
+ DOD INTERNET HOST TABLE SPECIFICATION
+
+
+STATUS OF THIS MEMO
+
+ This RFC is the official specification of the format of the Internet
+ Host Table. This edition of the specification includes minor
+ revisions to RFC-810 which brings it up to date. Distribution of this
+ memo is unlimited.
+
+INTRODUCTION
+
+ The DoD Host Table is utilized by the DoD Hostname Server maintained
+ by the DDN Network Information Center (NIC) on behalf of the Defense
+ Communications Agency (DCA) [See RFC-953].
+
+LOCATION OF THE STANDARD DOD ONLINE HOST TABLE
+
+ A machine-translatable ASCII text version of the DoD Host Table is
+ online in the file NETINFO:HOSTS.TXT on the SRI-NIC host. It can be
+ obtained via FTP from your local host by connecting to host
+ SRI-NIC.ARPA (26.0.0.73 or 10.0.0.51), logging in as user =
+ ANONYMOUS, password = GUEST, and retrieving the file
+ "NETINFO:HOSTS.TXT". The same table may also be obtained via the NIC
+ Hostname Server, as described in RFC-953. The latter method is
+ faster and easier, but requires a user program to make the necessary
+ connection to the Name Server.
+
+ASSUMPTIONS
+
+ 1. A "name" (Net, Host, Gateway, or Domain name) is a text string up
+ to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus
+ sign (-), and period (.). Note that periods are only allowed when
+ they serve to delimit components of "domain style names". (See
+ RFC-921, "Domain Name System Implementation Schedule", for
+ background). No blank or space characters are permitted as part of a
+ name. No distinction is made between upper and lower case. The first
+ character must be an alpha character. The last character must not be
+ a minus sign or period. A host which serves as a GATEWAY should have
+ "-GATEWAY" or "-GW" as part of its name. Hosts which do not serve as
+ Internet gateways should not use "-GATEWAY" and "-GW" as part of
+ their names. A host which is a TAC should have "-TAC" as the last
+ part of its host name, if it is a DoD host. Single character names
+ or nicknames are not allowed.
+
+ 2. Internet Addresses are 32-bit addresses [See RFC-796]. In the
+
+
+Harrenstien & Stahl & Feinler [Page 1]
+
+
+
+RFC 952 October 1985
+DOD INTERNET HOST TABLE SPECIFICATION
+
+
+ host table described herein each address is represented by four
+ decimal numbers separated by a period. Each decimal number
+ represents 1 octet.
+
+ 3. If the first bit of the first octet of the address is 0 (zero),
+ then the next 7 bits of the first octet indicate the network number
+ (Class A Address). If the first two bits are 1,0 (one,zero), then
+ the next 14 bits define the net number (Class B Address). If the
+ first 3 bits are 1,1,0 (one,one,zero), then the next 21 bits define
+ the net number (Class C Address) [See RFC-943].
+
+ This is depicted in the following diagram:
+
+ +-+------------+--------------+--------------+--------------+
+ |0| NET <-7-> | LOCAL ADDRESS <-24-> |
+ +-+------------+--------------+--------------+--------------+
+
+ +---+----------+--------------+--------------+--------------+
+ |1 0| NET <-14-> | LOCAL ADDRESS <-16-> |
+ +---+----------+--------------+--------------+--------------+
+
+ +-----+--------+--------------+--------------+--------------+
+ |1 1 0| NET <-21-> | LOCAL ADDRESS|
+ +-----+--------+--------------+--------------+--------------+
+
+ 4. The LOCAL ADDRESS portion of the internet address identifies a
+ host within the network specified by the NET portion of the address.
+
+ 5. The ARPANET and MILNET are both Class A networks. The NET portion
+ is 10 decimal for ARPANET, 26 decimal for MILNET, and the LOCAL
+ ADDRESS maps as follows: the second octet identifies the physical
+ host, the third octet identifies the logical host, and the fourth
+ identifies the Packet Switching Node (PSN), formerly known as an
+ Interface Message Processor (IMP).
+
+ +-+------------+--------------+--------------+--------------+
+ |0| 10 or 26 | HOST | LOGICAL HOST | PSN (IMP) |
+ +-+------------+--------------+--------------+--------------+
+
+ (NOTE: RFC-796 also describes the local address mappings for
+ several other networks.)
+
+ 6. It is the responsibility of the users of this host table to
+ translate it into whatever format is needed for their purposes.
+
+ 7. Names and addresses for DoD hosts and gateways will be negotiated
+ and registered with the DDN PMO, and subsequently with the NIC,
+
+
+Harrenstien & Stahl & Feinler [Page 2]
+
+
+
+RFC 952 October 1985
+DOD INTERNET HOST TABLE SPECIFICATION
+
+
+ before being used and before traffic is passed by a DoD host. Names
+ and addresses for domains and networks are to be registered with the
+ DDN Network Information Center (HOSTMASTER@SRI-NIC.ARPA) or
+ 800-235-3155.
+
+ The NIC will attempt to keep similar information for non-DoD networks
+ and hosts, if this information is provided, and as long as it is
+ needed, i.e., until intercommunicating network name servers are in
+ place.
+
+EXAMPLE OF HOST TABLE FORMAT
+
+ NET : 10.0.0.0 : ARPANET :
+ NET : 128.10.0.0 : PURDUE-CS-NET :
+ GATEWAY : 10.0.0.77, 18.10.0.4 : MIT-GW.ARPA,MIT-GATEWAY : PDP-11 :
+ MOS : IP/GW,EGP :
+ HOST : 26.0.0.73, 10.0.0.51 : SRI-NIC.ARPA,SRI-NIC,NIC : DEC-2060 :
+ TOPS20 :TCP/TELNET,TCP/SMTP,TCP/TIME,TCP/FTP,TCP/ECHO,ICMP :
+ HOST : 10.2.0.11 : SU-TAC.ARPA,SU-TAC : C/30 : TAC : TCP :
+
+SYNTAX AND CONVENTIONS
+
+ ; (semicolon) is used to denote the beginning of a comment.
+ Any text on a given line following a ';' is a
+ comment, and not part of the host table.
+
+ NET keyword introducing a network entry
+
+ GATEWAY keyword introducing a gateway entry
+
+ HOST keyword introducing a host entry
+
+ DOMAIN keyword introducing a domain entry
+
+ :(colon) is used as a field delimiter
+
+ ::(2 colons) indicates a null field
+
+ ,(comma) is used as a data element delimiter
+
+ XXX/YYY indicates protocol information of the type
+ TRANSPORT/SERVICE.
+
+ where TRANSPORT/SERVICE options are specified as
+
+ "FOO/BAR" both transport and service known
+
+
+
+Harrenstien & Stahl & Feinler [Page 3]
+
+
+
+RFC 952 October 1985
+DOD INTERNET HOST TABLE SPECIFICATION
+
+
+ "FOO" transport known; services not known
+
+ "BAR" service is known, transport not known
+
+ NOTE: See "Assigned Numbers" for specific options and acronyms
+ for machine types, operating systems, and protocol/services.
+
+ Each host table entry is an ASCII text string comprised of 6 fields,
+ where
+
+ Field 1 KEYWORD indicating whether this entry pertains to
+ a NET, GATEWAY, HOST, or DOMAIN. NET entries are
+ assigned and cannot have alternate addresses or
+ nicknames. DOMAIN entries do not use fields 4, 5,
+ or 6.
+
+ Field 2 Internet Address of Network, Gateway, or Host
+ followed by alternate addresses. Addresses for a
+ Domain are those where a Domain Name Server exists
+ for that domain.
+
+ Field 3 Official Name of Network, Gateway, Host, or Domain
+ (with optional nicknames, where permitted).
+
+ Field 4 Machine Type
+
+ Field 5 Operating System
+
+ Field 6 Protocol List
+
+ Fields 4, 5 and 6 are optional. For a Domain they are not used.
+
+ Fields 3-6, if included, pertain to the first address in Field 2.
+
+ 'Blanks' (spaces and tabs) are ignored between data elements or
+ fields, but are disallowed within a data element.
+
+ Each entry ends with a colon.
+
+ The entries in the table are grouped by types in the order Domain,
+ Net, Gateway, and Host. Within each type the ordering is
+ unspecified.
+
+ Note that although optional nicknames are allowed for hosts, they are
+ discouraged, except in the case where host names have been changed
+
+
+
+
+Harrenstien & Stahl & Feinler [Page 4]
+
+
+
+RFC 952 October 1985
+DOD INTERNET HOST TABLE SPECIFICATION
+
+
+ and both the new and the old names are maintained for a suitable
+ period of time to effect a smooth transition. Nicknames are not
+ permitted for NET names.
+
+GRAMMATICAL HOST TABLE SPECIFICATION
+
+ A. Parsing grammar
+
+ <entry> ::= <keyword> ":" <addresses> ":" <names> [":" [<cputype>]
+ [":" [<opsys>] [":" [<protocol list>] ]]] ":"
+ <addresses> ::= <address> *["," <address>]
+ <address> ::= <octet> "." <octet> "." <octet> "." <octet>
+ <octet> ::= <0 to 255 decimal>
+ <names> ::= <netname> | <gatename> | <domainname> *[","
+ <nicknames>]
+ | <official hostname> *["," <nicknames>]
+ <netname> ::= <name>
+ <gatename> ::= <hname>
+ <domainname> ::= <hname>
+ <official hostname> ::= <hname>
+ <nickname> ::= <hname>
+ <protocol list> ::= <protocol spec> *["," <protocol spec>]
+ <protocol spec> ::= <transport name> "/" <service name>
+ | <raw protocol name>
+
+ B. Lexical grammar
+
+ <entry-field> ::= <entry-text> [<cr><lf> <blank> <entry-field>]
+ <entry-text> ::= <print-char> *<text>
+ <blank> ::= <space-or-tab> [<blank>]
+ <keyword> ::= NET | GATEWAY | HOST | DOMAIN
+ <hname> ::= <name>*["."<name>]
+ <name> ::= <let>[*[<let-or-digit-or-hyphen>]<let-or-digit>]
+ <cputype> ::= PDP-11/70 | DEC-1080 | C/30 | CDC-6400...etc.
+ <opsys> ::= ITS | MULTICS | TOPS20 | UNIX...etc.
+ <transport name> ::= TCP | NCP | UDP | IP...etc.
+ <service name> ::= TELNET | FTP | SMTP | MTP...etc.
+ <raw protocol name> ::= <name>
+ <comment> ::= ";" <text><cr><lf>
+ <text> ::= *[<print-char> | <blank>]
+ <print-char> ::= <any printing char (not space or tab)>
+
+ Notes:
+
+ 1. Zero or more 'blanks' between separators " , : " are allowed.
+ 'Blanks' are spaces and tabs.
+
+
+
+Harrenstien & Stahl & Feinler [Page 5]
+
+
+
+RFC 952 October 1985
+DOD INTERNET HOST TABLE SPECIFICATION
+
+
+ 2. Continuation lines are lines that begin with at least one
+ blank. They may be used anywhere 'blanks' are legal to split an
+ entry across lines.
+
+BIBLIOGRAPHY
+
+ 1. Feinler, E., Harrenstien, K., Su, Z. and White, V., "Official DoD
+ Internet Host Table Specification", RFC-810, Network Information
+ Center, SRI International, March 1982.
+
+ 2. Harrenstien, K., Stahl, M., and Feinler, E., "Hostname Server",
+ RFC-953, Network Information Center, SRI International, October
+ 1985.
+
+ 3. Kudlick, M. "Host Names Online", RFC-608, Network Information
+ Center, SRI International, January 1973.
+
+ 4. Postel, J., "Internet Protocol", RFC-791, Information Sciences
+ Institute, University of Southern California, Marina del Rey,
+ September 1981.
+
+ 5. Postel, J., "Address Mappings", RFC-796, Information Sciences
+ Institute, University of Southern California, Marina del Rey,
+ September 1981.
+
+ 6. Postel, J., "Domain Name System Implementation Schedule", RFC-921,
+ Information Sciences Institute, University of Southern California,
+ Marina del Rey, October 1984.
+
+ 7. Reynolds, J. and Postel, J., "Assigned Numbers", RFC-943,
+ Information Sciences Institute, University of Southern California,
+ Marina del Rey, April 1985.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Harrenstien & Stahl & Feinler [Page 6]
+
diff --git a/doc/xsl/Makefile.in b/doc/xsl/Makefile.in
new file mode 100644
index 0000000..30c1c61
--- /dev/null
+++ b/doc/xsl/Makefile.in
@@ -0,0 +1,28 @@
+# Copyright (C) 2005, 2007 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 2007/06/19 23:47:13 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+distclean::
+ rm -f isc-docbook-chunk.xsl isc-docbook-html.xsl \
+ isc-docbook-latex.xsl isc-manpage.xsl
diff --git a/doc/xsl/copyright.xsl b/doc/xsl/copyright.xsl
new file mode 100644
index 0000000..691cde2
--- /dev/null
+++ b/doc/xsl/copyright.xsl
@@ -0,0 +1,75 @@
+<!--
+ - Copyright (C) 2005, 2007 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: copyright.xsl,v 1.6 2007/06/19 23:47:13 tbox Exp $ -->
+
+<!-- Generate ISC copyright comments from Docbook copyright metadata. -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:template name="isc.copyright.format">
+ <xsl:param name="text"/>
+ <xsl:value-of select="$isc.copyright.leader"/>
+ <xsl:value-of select="normalize-space(substring-before($text, '&#10;'))"/>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:variable name="rest" select="substring-after($text, '&#10;')"/>
+ <xsl:if test="translate($rest, '&#9;&#32;', '')">
+ <xsl:call-template name="isc.copyright.format">
+ <xsl:with-param name="text" select="$rest"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:variable name="isc.copyright.text">
+ <xsl:text>
+ Permission to use, copy, modify, and distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND 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.
+ </xsl:text>
+ </xsl:variable>
+
+ <xsl:variable name="isc.copyright">
+ <xsl:call-template name="isc.copyright.format">
+ <xsl:with-param name="text">
+ <xsl:for-each select="/refentry/docinfo/copyright | /book/bookinfo/copyright">
+ <xsl:text>Copyright (C) </xsl:text>
+ <xsl:call-template name="copyright.years">
+ <xsl:with-param name="years" select="year"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="holder"/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:for-each>
+ <xsl:value-of select="$isc.copyright.text"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+
+</xsl:stylesheet>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+ -->
diff --git a/doc/xsl/isc-docbook-chunk.xsl.in b/doc/xsl/isc-docbook-chunk.xsl.in
new file mode 100644
index 0000000..a766c05
--- /dev/null
+++ b/doc/xsl/isc-docbook-chunk.xsl.in
@@ -0,0 +1,65 @@
+<!--
+ - Copyright (C) 2005, 2007 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-docbook-chunk.xsl.in,v 1.6 2007/06/19 23:47:13 tbox Exp $ -->
+
+<!-- ISC customizations for Docbook-XSL chunked HTML generator -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <!-- Import the Docbook HTML stuff -->
+ <xsl:import href="@XSLT_DOCBOOK_CHUNK_HTML@"/>
+
+ <!-- Readable HTML output, please -->
+ <xsl:output indent="yes"/>
+ <xsl:param name="chunker.output.indent" select="'yes'"/>
+
+ <!-- Chunk at section level, please -->
+ <xsl:param name="chunk.section.depth" select="0"/>
+
+ <!-- Generate chunk filenames from id attribute values -->
+ <xsl:param name="use.id.as.filename" select="1"/>
+
+ <!-- ANSI C function prototypes, please -->
+ <xsl:param name="funcsynopsis.style">ansi</xsl:param>
+
+ <!-- Use ranges when constructing copyrights -->
+ <xsl:param name="make.year.ranges" select="1"/>
+
+ <!-- Include our copyright generator -->
+ <xsl:include href="copyright.xsl"/>
+
+ <!-- Set comment convention for this output format -->
+ <xsl:param name="isc.copyright.leader"> - </xsl:param>
+
+ <!-- Override Docbook template to insert copyright -->
+ <xsl:template name="user.preroot">
+ <xsl:comment>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:value-of select="$isc.copyright"/>
+ </xsl:comment>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:comment> &#36;Id&#36; </xsl:comment>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+ -->
diff --git a/doc/xsl/isc-docbook-html.xsl.in b/doc/xsl/isc-docbook-html.xsl.in
new file mode 100644
index 0000000..ecc0f67
--- /dev/null
+++ b/doc/xsl/isc-docbook-html.xsl.in
@@ -0,0 +1,58 @@
+<!--
+ - Copyright (C) 2005, 2007 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-docbook-html.xsl.in,v 1.6 2007/06/19 23:47:13 tbox Exp $ -->
+
+<!-- ISC customizations for Docbook-XSL HTML generator -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <!-- Import the Docbook HTML stuff -->
+ <xsl:import href="@XSLT_DOCBOOK_STYLE_HTML@"/>
+
+ <!-- Readable HTML output, please -->
+ <xsl:output indent="yes"/>
+
+ <!-- ANSI C function prototypes, please -->
+ <xsl:param name="funcsynopsis.style">ansi</xsl:param>
+
+ <!-- Use ranges when constructing copyrights -->
+ <xsl:param name="make.year.ranges" select="1"/>
+
+ <!-- Include our copyright generator -->
+ <xsl:include href="copyright.xsl"/>
+
+ <!-- Set comment convention for this output format -->
+ <xsl:param name="isc.copyright.leader"> - </xsl:param>
+
+ <!-- Override Docbook template to insert copyright -->
+ <xsl:template name="user.preroot">
+ <xsl:comment>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:value-of select="$isc.copyright"/>
+ </xsl:comment>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:comment> &#36;Id&#36; </xsl:comment>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+ -->
diff --git a/doc/xsl/isc-docbook-latex-mappings.xml b/doc/xsl/isc-docbook-latex-mappings.xml
new file mode 100644
index 0000000..97c7cef
--- /dev/null
+++ b/doc/xsl/isc-docbook-latex-mappings.xml
@@ -0,0 +1,37 @@
+<!--
+ - Copyright (C) 2005, 2007 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-docbook-latex-mappings.xml,v 1.4 2007/06/19 23:47:13 tbox Exp $ -->
+
+<!--
+ - ISC modifications to db2latex mapping rules.
+ -
+ - We want <refentry/> elements to show up in the table of contents,
+ - so we need to generate \section{}, not \section*{}.
+ -->
+
+<latexbindings>
+ <latexmapping role="begin">
+ <mapping key="refentry" text="">
+ <line>% &#10;</line>
+ <line>% -------------------------------------------------------------&#10;</line>
+ <line>% Refentry &#10;</line>
+ <line>% -------------------------------------------------------------&#10;</line>
+ <line>\section{%title%}&#10;</line>
+ <line>\label{%id%}\hypertarget{%id%}{}%&#10;</line>
+ </mapping>
+ </latexmapping>
+</latexbindings>
diff --git a/doc/xsl/isc-docbook-latex.xsl.in b/doc/xsl/isc-docbook-latex.xsl.in
new file mode 100644
index 0000000..1cfcc99
--- /dev/null
+++ b/doc/xsl/isc-docbook-latex.xsl.in
@@ -0,0 +1,166 @@
+<!--
+ - Copyright (C) 2005, 2007 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-docbook-latex.xsl.in,v 1.6 2007/06/19 23:47:13 tbox Exp $ -->
+
+<!-- ISC customizations for db2latex generator -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <!-- Import the db2latex stuff -->
+ <xsl:import href="@XSLT_DB2LATEX_STYLE@"/>
+
+ <!-- Blank lines between paragraphs, please -->
+ <xsl:param name="latex.use.parskip" select="1"/>
+
+ <!-- Least bad current option for constructing tables -->
+ <xsl:param name="latex.use.ltxtable" select="1"/>
+ <xsl:param name="latex.use.longtable" select="1"/>
+
+ <!-- LaTeX2e documentclass options. -->
+ <xsl:param name="latex.documentclass.common"/>
+ <xsl:param name="latex.documentclass.book">10pt,twoside,openright</xsl:param>
+
+ <!-- This documentation is in English (or maybe Bad English) -->
+ <xsl:param name="latex.babel.language" select="'english'"/>
+ <xsl:param name="l10n.gentext.default.language" select="'en'"/>
+
+ <!-- Where to find "admonition" graphics -->
+ <xsl:param name="admon.graphics.path" select="'@XSLT_DB2LATEX_ADMONITIONS@'"/>
+
+ <!-- ANSI C function prototypes, please -->
+ <xsl:param name="funcsynopsis.style">ansi</xsl:param>
+
+ <!-- Local modifications to db2latex's mapping rules -->
+ <xsl:param name="latex.mapping.xml" select="document('isc-docbook-latex-mappings.xml')"/>
+
+ <!-- Patch around db2latex (0.8pre1) bug -->
+ <xsl:template match="copyright/year">
+ <xsl:apply-templates />
+ <xsl:if test="position() != last()">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Include our copyright generator -->
+ <xsl:include href="copyright.xsl"/>
+
+ <!-- Set comment convention for this output format -->
+ <xsl:param name="isc.copyright.leader">% </xsl:param>
+
+ <!-- Intercept top level to prepend copyright -->
+ <xsl:template match="/">
+ <xsl:value-of select="$isc.copyright"/>
+ <xsl:apply-imports/>
+ </xsl:template>
+
+ <!--
+ - Add support for multiple <para/> elements in a table entry.
+ - db2latex is already typesetting the table entry as a parbox,
+ - so we just have to insert the paragraph breaks.
+ -->
+ <xsl:template match="tbody/row/entry/para[position() != last()]">
+ <xsl:apply-imports/>
+ <xsl:text> \par </xsl:text>
+ </xsl:template>
+
+ <!--
+ - Add support for <optional/> in <programlisting/>.
+ -->
+ <xsl:template match="optional" mode="latex.verbatim">
+ <xsl:text>[</xsl:text>
+ <xsl:apply-templates mode="latex.verbatim"/>
+ <xsl:text>]</xsl:text>
+ </xsl:template>
+
+ <!--
+ - Customize the title page. Are we having fun yet?
+ -
+ - NB: filename of graphic specified without extension.
+ - LaTeX includes file.eps, PDFLaTeX includes file.pdf.
+ -
+ - Spacing and font sizes could probably use some work.
+ -->
+ <xsl:param name="latex.maketitle">
+ <xsl:text>
+ \begin{titlepage}
+ \null\vfil
+ \vskip 60pt
+ \begin{center}%
+ { %\LARGE
+ \Huge
+ \bfseries
+ </xsl:text>
+ <xsl:for-each select="/book/title">
+ <xsl:call-template name="text"/>
+ </xsl:for-each>
+ <xsl:text>
+ \par}%
+ \vskip 3em%
+ { %\large
+ \Large
+ \lineskip .75em%
+ </xsl:text>
+ <xsl:for-each select="/book/bookinfo/releaseinfo[1]">
+ <xsl:call-template name="text"/>
+ </xsl:for-each>
+ <xsl:text>
+ \par}
+ %\vskip 1.5em%
+ \vfil
+ \includegraphics{isc-logo}
+ \end{center}\par
+ \vfil\null
+ \end{titlepage}
+ </xsl:text>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:param>
+
+ <!--
+ - More front matter: copyright notice, CVS revision number, table
+ - of contents.
+ -->
+ <xsl:template match="book/bookinfo">
+ <xsl:apply-imports/>
+ <xsl:text>\begin{center}&#10;</xsl:text>
+ <xsl:value-of select="$isc.copyright.text"/>
+ <xsl:text>\end{center}&#10;</xsl:text>
+ <xsl:for-each select="/book/bookinfo/releaseinfo[position() &gt; 1]">
+ <xsl:text>\begin{center}</xsl:text>
+ <xsl:call-template name="text"/>
+ <xsl:text>\end{center}&#10;</xsl:text>
+ </xsl:for-each>
+ <xsl:text>\tableofcontents&#10;</xsl:text>
+ </xsl:template>
+
+ <!--
+ - Try to avoid some weird looking line breaks.
+ -
+ - This doesn't really work right, so disable for now.
+ -->
+ <xsl:template match="literal" mode="disabled">
+ <xsl:text>\mbox{</xsl:text>
+ <xsl:apply-imports/>
+ <xsl:text>}</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+ -->
diff --git a/doc/xsl/isc-docbook-text.xsl b/doc/xsl/isc-docbook-text.xsl
new file mode 100644
index 0000000..abca9ea
--- /dev/null
+++ b/doc/xsl/isc-docbook-text.xsl
@@ -0,0 +1,50 @@
+<!--
+ - Copyright (C) 2005, 2007 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-docbook-text.xsl,v 1.3 2007/06/19 23:47:13 tbox Exp $ -->
+
+<!-- Tweaks to Docbook-XSL HTML for producing flat ASCII text. -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
+ xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
+
+ <!-- Import our Docbook HTML stuff -->
+ <xsl:import href="isc-docbook-html.xsl"/>
+
+ <!-- Disable tables of contents (for now - tweak as needed) -->
+ <xsl:param name="generate.toc"/>
+
+ <!-- Voodoo to read i18n/l10n overrides directly from this stylesheet -->
+ <xsl:param name="local.l10n.xml" select="document('')"/>
+
+ <!-- Customize Docbook-XSL i18n/l10n mappings. -->
+ <l:i18n>
+ <l:l10n language="en" english-language-name="English">
+
+ <!-- Please use plain old ASCII quotes -->
+ <l:dingbat key="startquote" text='&quot;'/>
+ <l:dingbat key="endquote" text='&quot;'/>
+
+ </l:l10n>
+ </l:i18n>
+
+</xsl:stylesheet>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+ -->
diff --git a/doc/xsl/isc-manpage.xsl.in b/doc/xsl/isc-manpage.xsl.in
new file mode 100644
index 0000000..fe008d3
--- /dev/null
+++ b/doc/xsl/isc-manpage.xsl.in
@@ -0,0 +1,145 @@
+<!--
+ - Copyright (C) 2005, 2007 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-manpage.xsl.in,v 1.9 2007/06/18 23:47:34 tbox Exp $ -->
+
+<!-- ISC customizations for Docbook-XSL manual page generator. -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <!-- Import the Docbook manpages stuff -->
+ <xsl:import href="@XSLT_DOCBOOK_STYLE_MAN@"/>
+
+ <!-- Include our copyright generator -->
+ <xsl:include href="copyright.xsl"/>
+
+ <!-- Set comment string for this output format -->
+ <xsl:param name="isc.copyright.leader">.\" </xsl:param>
+
+ <!-- We're not writing any kind of SGML, thanks -->
+ <xsl:output method="text" encoding="us-ascii"/>
+
+ <!-- ANSI C function prototypes, please -->
+ <xsl:param name="funcsynopsis.style">ansi</xsl:param>
+
+ <!-- Use ranges when constructing copyrights -->
+ <xsl:param name="make.year.ranges" select="1"/>
+
+ <!-- Stuff we want in our nroff preamble. -->
+ <xsl:variable name="isc.nroff.preamble">
+ <xsl:text>.\"&#10;</xsl:text>
+ <xsl:text>.\" &#36;Id&#36;&#10;</xsl:text>
+ <xsl:text>.\"&#10;</xsl:text>
+ <xsl:text>.hy 0&#10;</xsl:text>
+ <xsl:text>.ad l&#10;</xsl:text>
+ </xsl:variable>
+
+ <!--
+ - Override Docbook template to insert our copyright,
+ - disable chunking, and suppress output of .so files.
+ -->
+ <xsl:template name="write.text.chunk">
+ <xsl:param name="content"/>
+ <xsl:if test="substring($content, 1, 4) != '.so ' or
+ substring-after($content, '&#10;') != ''">
+ <xsl:call-template name="isc.no.blanks">
+ <xsl:with-param name="text" select="
+ concat($isc.copyright,
+ $isc.nroff.preamble,
+ $content)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!--
+ - Suppress blank lines in nroff source we output.
+ -->
+ <xsl:template name="isc.no.blanks">
+ <xsl:param name="text"/>
+ <xsl:choose>
+ <xsl:when test="contains($text, '&#10;')">
+ <xsl:call-template name="isc.no.blanks">
+ <xsl:with-param name="text"
+ select="substring-before($text, '&#10;')"/>
+ </xsl:call-template>
+ <xsl:call-template name="isc.no.blanks">
+ <xsl:with-param name="text"
+ select="substring-after($text, '&#10;')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="translate($text, '&#9;&#32;', '')">
+ <xsl:value-of select="$text"/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
+ <!--
+ - Override Docbook template to change formatting.
+ - We just want the element name in boldface, no subsection header.
+ -->
+ <xsl:template match="caution|important|note|tip|warning">
+ <xsl:text>&#10;.RS&#10;.B "</xsl:text>
+ <!-- capitalize word -->
+ <xsl:value-of
+ select="translate (substring (name(.), 1, 1), 'cintw', 'CINTW')" />
+ <xsl:value-of select="substring (name(), 2)" />
+ <xsl:if test="title">
+ <xsl:text>: </xsl:text>
+ <xsl:value-of select="title[1]"/>
+ </xsl:if>
+ <xsl:text>:"&#10;</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>&#10;.RE&#10;</xsl:text>
+ </xsl:template>
+
+ <!--
+ - Override template to change formatting.
+ - We don't want hyphenation or justification.
+ -->
+ <xsl:template match="cmdsynopsis">
+ <xsl:text>.HP </xsl:text>
+ <xsl:value-of select="string-length (normalize-space (command)) + 1"/>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:template>
+
+ <!--
+ - Override template to change formatting.
+ - We don't want hyphenation or justification.
+ -->
+ <xsl:template match="funcsynopsis">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <!--
+ - Override template to change formatting.
+ - Line breaks in funcsynopsisinfo are significant.
+ -->
+ <xsl:template match="funcsynopsisinfo">
+ <xsl:text>&#10;.nf&#10;</xsl:text>
+ <xsl:apply-templates/>
+ <xsl:text>&#10;.fi&#10;</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
+
+<!--
+ - Local variables:
+ - mode: sgml
+ - End:
+ -->
diff --git a/doc/xsl/pre-latex.xsl b/doc/xsl/pre-latex.xsl
new file mode 100644
index 0000000..9473556
--- /dev/null
+++ b/doc/xsl/pre-latex.xsl
@@ -0,0 +1,55 @@
+<!--
+ - Copyright (C) 2005, 2007 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: pre-latex.xsl,v 1.6 2007/06/19 23:47:13 tbox Exp $ -->
+
+<!--
+ - Whack &mdash; into something that won't choke LaTeX.
+ - There's probably a better way to do this, but this will work for now.
+ -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:variable name="mdash" select="'&#8212;'"/>
+
+ <xsl:template name="fix-mdash" match="text()[contains(., '&#8212;')]">
+ <xsl:param name="s" select="."/>
+ <xsl:choose>
+ <xsl:when test="contains($s, $mdash)">
+ <xsl:value-of select="substring-before($s, $mdash)"/>
+ <xsl:text>---</xsl:text>
+ <xsl:call-template name="fix-mdash">
+ <xsl:with-param name="s" select="substring-after($s, $mdash)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$s"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:copy-of select="@*"/>
+ <xsl:apply-templates/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="/">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/docutil/HTML_COPYRIGHT b/docutil/HTML_COPYRIGHT
new file mode 100644
index 0000000..61ae4b3
--- /dev/null
+++ b/docutil/HTML_COPYRIGHT
@@ -0,0 +1,16 @@
+<!--
+ - Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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.
+-->
diff --git a/docutil/MAN_COPYRIGHT b/docutil/MAN_COPYRIGHT
new file mode 100644
index 0000000..fe5f81b
--- /dev/null
+++ b/docutil/MAN_COPYRIGHT
@@ -0,0 +1,16 @@
+.\"
+.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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.
+.\"
diff --git a/docutil/patch-db2latex-duplicate-template-bug b/docutil/patch-db2latex-duplicate-template-bug
new file mode 100644
index 0000000..75100e1
--- /dev/null
+++ b/docutil/patch-db2latex-duplicate-template-bug
@@ -0,0 +1,77 @@
+;; $Id: patch-db2latex-duplicate-template-bug,v 1.2 2007/01/12 22:24:20 sra Exp $
+;;
+;; This is a patch to work around a known bug in db2latex. Apparently
+;; xsltproc's error checking got a lot better since the authors of
+;; db2latex last tested this, so a clear language violation that
+;; xsltproc used to ignore now prevents xsltproc from working with
+;; db2latex.
+;;
+;; On FreeBSD you can simply drop this patch into the directory
+;; /usr/ports/textproc/db2latex/files/ and the ports system should
+;; take it from there. I've sent this patch off to the port
+;; maintainer but have not yet heard anything back.
+;;
+;; I don't really know whther this is the "right" fix, but it seems to
+;; work, and I'm pretty sure that the code this patch deletes does not
+;; work as it stands, so at worst the result after applying this patch
+;; should be no worse than the result without this patch.
+;;
+;; YMMV. If this patch breaks, you get to keep both pieces.
+
+Index: xsl/qandaset.mod.xsl
+--- xsl/qandaset.mod.xsl.~1~ Sun Jan 4 08:22:27 2004
++++ xsl/qandaset.mod.xsl Fri Apr 1 22:30:20 2005
+@@ -363,53 +363,4 @@
+ </doc:template>
+ <xsl:template match="revhistory" mode="qandatoc.mode"/>
+
+-<xsl:template name="question.answer.label">
+- <!-- variable: deflabel -->
+- <xsl:variable name="deflabel">
+- <!-- chck whether someone has a defaultlabel attribute -->
+- <xsl:choose>
+- <xsl:when test="ancestor-or-self::*[@defaultlabel]">
+- <xsl:value-of select="(ancestor-or-self::*[@defaultlabel])[last()]/@defaultlabel"/>
+- </xsl:when>
+- <xsl:otherwise>
+- <xsl:value-of select="latex.qanda.defaultlabel"/>
+- </xsl:otherwise>
+- </xsl:choose>
+- </xsl:variable>
+-
+- <xsl:variable name="label" select="@label"/>
+- <xsl:choose>
+- <xsl:when test="$deflabel = 'qanda'">
+- <xsl:call-template name="gentext">
+- <xsl:with-param name="key">
+- <xsl:choose>
+- <xsl:when test="local-name(.) = 'question'">question</xsl:when>
+- <xsl:when test="local-name(.) = 'answer'">answer</xsl:when>
+- <xsl:when test="local-name(.) = 'qandadiv'">qandadiv</xsl:when>
+- <xsl:otherwise>qandaset</xsl:otherwise>
+- </xsl:choose>
+- </xsl:with-param>
+- </xsl:call-template>
+- </xsl:when>
+- <xsl:when test="$deflabel = 'label'">
+- <xsl:value-of select="$label"/>
+- </xsl:when>
+- <xsl:when test="$deflabel = 'number' and local-name(.) = 'question'">
+- <xsl:apply-templates select="ancestor::qandaset[1]" mode="number"/>
+- <xsl:choose>
+- <xsl:when test="ancestor::qandadiv">
+- <xsl:apply-templates select="ancestor::qandadiv[1]" mode="number"/>
+- <xsl:apply-templates select="ancestor::qandaentry" mode="number"/>
+- </xsl:when>
+- <xsl:otherwise>
+- <xsl:apply-templates select="ancestor::qandaentry" mode="number"/>
+- </xsl:otherwise>
+- </xsl:choose>
+- </xsl:when>
+- <xsl:otherwise>
+- <!-- nothing -->
+- </xsl:otherwise>
+- </xsl:choose>
+-</xsl:template>
+-
+ </xsl:stylesheet>
diff --git a/docutil/patch-db2latex-nested-param-bug b/docutil/patch-db2latex-nested-param-bug
new file mode 100644
index 0000000..d73f19b
--- /dev/null
+++ b/docutil/patch-db2latex-nested-param-bug
@@ -0,0 +1,18 @@
+;; $Id: patch-db2latex-nested-param-bug,v 1.1 2007/02/06 20:58:13 sra Exp $
+;;
+;; Latest version of xsltproc doesn't like <xsl:param><xsl:param/></xsl:param>.
+
+--- xsl/lists.mod.xsl.~1~ Sat Jan 31 06:53:50 2004
++++ xsl/lists.mod.xsl Tue Feb 6 15:41:12 2007
+@@ -269,10 +269,8 @@
+ </doc:notes>
+ </doc:template>
+ <xsl:template match="varlistentry">
+- <xsl:param name="next.is.list">
+ <xsl:param name="object" select="listitem/*[1]"/>
+- <xsl:value-of select="count($object[self::itemizedlist or self::orderedlist or self::variablelist])"/>
+- </xsl:param>
++ <xsl:param name="next.is.list" select="count($object[self::itemizedlist or self::orderedlist or self::variablelist])"/>
+ <xsl:variable name="id">
+ <xsl:call-template name="label.id"/>
+ </xsl:variable>
diff --git a/docutil/patch-db2latex-xsltproc-title-bug b/docutil/patch-db2latex-xsltproc-title-bug
new file mode 100644
index 0000000..88d6c24
--- /dev/null
+++ b/docutil/patch-db2latex-xsltproc-title-bug
@@ -0,0 +1,29 @@
+;; $Id: patch-db2latex-xsltproc-title-bug,v 1.2 2007/01/12 22:24:20 sra Exp $
+;;
+;; This patches around a problem that I don't completely understand,
+;; and which may in fact be an xsltproc bug rather than a db2latex
+;; bug. Symptom is that the generated \title{} contains not only the
+;; book title but also the concatenation of all the chapter titles.
+;; This makes no sense, it doesn't happen with saxon, it doesn't
+;; happen with all versions of xsltproc, and attempts to trace this
+;; with --verbose and <xsl:message/> leave me more wondering whether
+;; it's me or xsltproc that doesn't understand the XSLT pattern
+;; matching rules.
+;;
+;; All that said, the change below prevents the bad behavior and
+;; should be completely harmless, so it will do as a workaround.
+
+Index: xsl/book-article.mod.xsl
+--- xsl/book-article.mod.xsl.~1~ Tue May 3 21:51:18 2005
++++ xsl/book-article.mod.xsl Sat May 7 09:00:26 2005
+@@ -87,8 +87,8 @@
+ <xsl:call-template name="generate.latex.book.preamble"/>
+ <!-- book:2: output title information -->
+ <xsl:text>\title{</xsl:text>
+- <xsl:apply-templates select="title|bookinfo/title"/>
+- <xsl:apply-templates select="subtitle|bookinfo/subtitle"/>
++ <xsl:apply-templates select="/book/title|/book/bookinfo/title"/>
++ <xsl:apply-templates select="/book/subtitle|/book/bookinfo/subtitle"/>
+ <xsl:text>}&#10;</xsl:text>
+ <!-- book:3: output author information -->
+ <xsl:text>\author{</xsl:text>
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..058b26c
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/isc-config.sh.in b/isc-config.sh.in
new file mode 100644
index 0000000..0eafca7
--- /dev/null
+++ b/isc-config.sh.in
@@ -0,0 +1,149 @@
+#!/bin/sh
+#
+# Copyright (C) 2004, 2007 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
+# 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-config.sh.in,v 1.17 2007/06/19 23:46:59 tbox Exp $
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+exec_prefix_set=
+
+usage()
+{
+ cat << EOF
+Usage: isc-config [OPTIONS] [LIBRARIES]
+Options:
+ [--prefix[=DIR]]
+ [--exec-prefix[=DIR]]
+ [--version]
+ [--libs]
+ [--cflags]
+Libraries:
+ isc
+ isccc
+ isccfg
+ dns
+ lwres
+ bind9
+EOF
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1 1>&2
+fi
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case "$1" in
+ --prefix=*)
+ prefix=$optarg
+ if test "x$exec_prefix_set" = x ; then
+ exec_prefix=$prefix
+ fi
+ ;;
+ --prefix)
+ echo_prefix=true
+ ;;
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ ;;
+ --exec-prefix)
+ echo_exec_prefix=true
+ ;;
+ --version)
+ echo @BIND9_VERSION@
+ exit 0
+ ;;
+ --cflags)
+ echo_cflags=true
+ ;;
+ --libs)
+ echo_libs=true;
+ ;;
+ isc)
+ libisc=true;
+ ;;
+ isccc)
+ libisccc=true;
+ libisc=true;
+ ;;
+ isccfg)
+ libisccfg=true;
+ libisc=true;
+ ;;
+ dns)
+ libdns=true;
+ libisc=true;
+ ;;
+ lwres)
+ liblwres=true;
+ ;;
+ bind9)
+ libdns=true;
+ libisc=true;
+ libisccfg=true;
+ libbind9=true;
+ ;;
+ *)
+ usage 1 1>&2
+ esac
+ shift
+done
+
+if test x"$echo_prefix" = x"true" ; then
+ echo $prefix
+fi
+if test x"$echo_exec_prefix" = x"true" ; then
+ echo $exec_prefix
+fi
+if test x"$echo_cflags" = x"true"; then
+ includes="-I${exec_prefix}/include"
+ if test x"$libisc" = x"true"; then
+ includes="$includes @ALWAYS_DEFINES@ @STD_CINCLUDES@ @STD_CDEFINES@ @CCOPT@"
+ fi
+ echo $includes
+fi
+if test x"$echo_libs" = x"true"; then
+ libs=-L${exec_prefix}/lib
+ if test x"$liblwres" = x"true" ; then
+ libs="$libs -llwres"
+ fi
+ if test x"$libbind9" = x"true" ; then
+ libs="$libs -lbind9"
+ fi
+ if test x"$libdns" = x"true" ; then
+ libs="$libs -ldns @DNS_CRYPTO_LIBS@"
+ fi
+ if test x"$libisccfg" = x"true" ; then
+ libs="$libs -lisccfg"
+ fi
+ if test x"$libisccc" = x"true" ; then
+ libs="$libs -lisccc"
+ fi
+ if test x"$libisc" = x"true" ; then
+ libs="$libs -lisc"
+ needothers=true
+ fi
+ if test x"$needothers" = x"true" ; then
+ libs="$libs @CCOPT@ @LIBS@"
+ fi
+ echo $libs
+fi
diff --git a/lib/Makefile.in b/lib/Makefile.in
new file mode 100644
index 0000000..e46aef2
--- /dev/null
+++ b/lib/Makefile.in
@@ -0,0 +1,29 @@
+# Copyright (C) 2004, 2007 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
+# 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.21 2007/06/19 23:47:13 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+# Note: the order of SUBDIRS is important.
+# Attempt to disable parallel processing.
+.NOTPARALLEL:
+.NO_PARALLEL:
+SUBDIRS = isc isccc dns isccfg bind9 lwres tests
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/bind9/Makefile.in b/lib/bind9/Makefile.in
new file mode 100644
index 0000000..7c1e5b0
--- /dev/null
+++ b/lib/bind9/Makefile.in
@@ -0,0 +1,84 @@
+# 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.11 2007/06/19 23:47:16 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@LIBBIND9_API@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I. ${BIND9_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} \
+ ${ISCCFG_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@
+
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+
+LIBS = @LIBS@
+
+SUBDIRS = include
+
+# Alphabetically
+OBJS = check.@O@ getaddresses.@O@ version.@O@
+
+# Alphabetically
+SRCS = check.c getaddresses.c version.c
+
+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
+
+libbind9.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+libbind9.la: ${OBJS} ${ISCCFGDEPLIBS} ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libbind9.la -rpath ${libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${DNSLIBS} ${ISCCFGLIBS} ${ISCLIBS} ${LIBS}
+
+timestamp: libbind9.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libbind9.@A@ ${DESTDIR}${libdir}
+
+clean distclean::
+ rm -f libbind9.@A@ timestamp
diff --git a/lib/bind9/api b/lib/bind9/api
new file mode 100644
index 0000000..2240cdd
--- /dev/null
+++ b/lib/bind9/api
@@ -0,0 +1,3 @@
+LIBINTERFACE = 50
+LIBREVISION = 1
+LIBAGE = 0
diff --git a/lib/bind9/check.c b/lib/bind9/check.c
new file mode 100644
index 0000000..f475691
--- /dev/null
+++ b/lib/bind9/check.c
@@ -0,0 +1,2296 @@
+/*
+ * Copyright (C) 2004-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: check.c,v 1.95 2008/11/19 05:38:49 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/parseint.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/symtab.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/fixedname.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/secalg.h>
+
+#include <isccfg/aclconf.h>
+#include <isccfg/cfg.h>
+
+#include <bind9/check.h>
+
+static void
+freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
+ UNUSED(type);
+ UNUSED(value);
+ isc_mem_free(userarg, key);
+}
+
+static isc_result_t
+check_orderent(const cfg_obj_t *ent, isc_log_t *logctx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ isc_textregion_t r;
+ dns_fixedname_t fixed;
+ const cfg_obj_t *obj;
+ dns_rdataclass_t rdclass;
+ dns_rdatatype_t rdtype;
+ isc_buffer_t b;
+ const char *str;
+
+ dns_fixedname_init(&fixed);
+ obj = cfg_tuple_get(ent, "class");
+ if (cfg_obj_isstring(obj)) {
+
+ DE_CONST(cfg_obj_asstring(obj), r.base);
+ r.length = strlen(r.base);
+ tresult = dns_rdataclass_fromtext(&rdclass, &r);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "rrset-order: invalid class '%s'",
+ r.base);
+ result = ISC_R_FAILURE;
+ }
+ }
+
+ obj = cfg_tuple_get(ent, "type");
+ if (cfg_obj_isstring(obj)) {
+
+ DE_CONST(cfg_obj_asstring(obj), r.base);
+ r.length = strlen(r.base);
+ tresult = dns_rdatatype_fromtext(&rdtype, &r);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "rrset-order: invalid type '%s'",
+ r.base);
+ result = ISC_R_FAILURE;
+ }
+ }
+
+ obj = cfg_tuple_get(ent, "name");
+ if (cfg_obj_isstring(obj)) {
+ 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,
+ "rrset-order: invalid name '%s'", str);
+ result = ISC_R_FAILURE;
+ }
+ }
+
+ obj = cfg_tuple_get(ent, "order");
+ if (!cfg_obj_isstring(obj) ||
+ strcasecmp("order", cfg_obj_asstring(obj)) != 0) {
+ cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
+ "rrset-order: keyword 'order' missing");
+ result = ISC_R_FAILURE;
+ }
+
+ obj = cfg_tuple_get(ent, "ordering");
+ if (!cfg_obj_isstring(obj)) {
+ cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
+ "rrset-order: missing ordering");
+ result = ISC_R_FAILURE;
+ } else if (strcasecmp(cfg_obj_asstring(obj), "fixed") == 0) {
+#if !DNS_RDATASET_FIXED
+ cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
+ "rrset-order: order 'fixed' was disabled at "
+ "compilation time");
+#endif
+ } else if (strcasecmp(cfg_obj_asstring(obj), "random") != 0 &&
+ strcasecmp(cfg_obj_asstring(obj), "cyclic") != 0) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "rrset-order: invalid order '%s'",
+ cfg_obj_asstring(obj));
+ result = ISC_R_FAILURE;
+ }
+ return (result);
+}
+
+static isc_result_t
+check_order(const cfg_obj_t *options, isc_log_t *logctx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ const cfg_listelt_t *element;
+ const cfg_obj_t *obj = NULL;
+
+ if (cfg_map_get(options, "rrset-order", &obj) != ISC_R_SUCCESS)
+ return (result);
+
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ tresult = check_orderent(cfg_listelt_value(element), logctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ return (result);
+}
+
+static isc_result_t
+check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *alternates = NULL;
+ const cfg_obj_t *value;
+ const cfg_obj_t *obj;
+ const char *str;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t buffer;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+
+ (void)cfg_map_get(options, "dual-stack-servers", &alternates);
+
+ if (alternates == NULL)
+ return (ISC_R_SUCCESS);
+
+ obj = cfg_tuple_get(alternates, "port");
+ if (cfg_obj_isuint32(obj)) {
+ isc_uint32_t val = cfg_obj_asuint32(obj);
+ if (val > ISC_UINT16_MAX) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ result = ISC_R_FAILURE;
+ }
+ }
+ obj = cfg_tuple_get(alternates, "addresses");
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ value = cfg_listelt_value(element);
+ if (cfg_obj_issockaddr(value))
+ continue;
+ obj = cfg_tuple_get(value, "name");
+ str = cfg_obj_asstring(obj);
+ isc_buffer_init(&buffer, str, strlen(str));
+ isc_buffer_add(&buffer, strlen(str));
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ tresult = dns_name_fromtext(name, &buffer, dns_rootname,
+ ISC_FALSE, NULL);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "bad name '%s'", str);
+ result = ISC_R_FAILURE;
+ }
+ obj = cfg_tuple_get(value, "port");
+ if (cfg_obj_isuint32(obj)) {
+ isc_uint32_t val = cfg_obj_asuint32(obj);
+ if (val > ISC_UINT16_MAX) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "port '%u' out of range", val);
+ result = ISC_R_FAILURE;
+ }
+ }
+ }
+ return (result);
+}
+
+static isc_result_t
+check_forward(const cfg_obj_t *options, const cfg_obj_t *global,
+ isc_log_t *logctx)
+{
+ const cfg_obj_t *forward = NULL;
+ const cfg_obj_t *forwarders = NULL;
+
+ (void)cfg_map_get(options, "forward", &forward);
+ (void)cfg_map_get(options, "forwarders", &forwarders);
+
+ if (forwarders != NULL && global != NULL) {
+ const char *file = cfg_obj_file(global);
+ unsigned int line = cfg_obj_line(global);
+ cfg_obj_log(forwarders, logctx, ISC_LOG_ERROR,
+ "forwarders declared in root zone and "
+ "in general configuration: %s:%u",
+ file, line);
+ return (ISC_R_FAILURE);
+ }
+ if (forward != NULL && forwarders == NULL) {
+ cfg_obj_log(forward, logctx, ISC_LOG_ERROR,
+ "no matching 'forwarders' statement");
+ return (ISC_R_FAILURE);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ const cfg_listelt_t *element;
+ const char *str;
+ isc_buffer_t b;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ const cfg_obj_t *obj;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ obj = cfg_tuple_get(disabled, "name");
+ 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);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "bad domain name '%s'", str);
+ result = tresult;
+ }
+
+ obj = cfg_tuple_get(disabled, "algorithms");
+
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ isc_textregion_t r;
+ dns_secalg_t alg;
+ isc_result_t tresult;
+
+ DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
+ r.length = strlen(r.base);
+
+ tresult = dns_secalg_fromtext(&alg, &r);
+ if (tresult != ISC_R_SUCCESS) {
+ isc_uint8_t ui;
+ result = isc_parse_uint8(&ui, r.base, 10);
+ }
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(cfg_listelt_value(element), logctx,
+ ISC_LOG_ERROR, "invalid algorithm '%s'",
+ r.base);
+ result = tresult;
+ }
+ }
+ return (result);
+}
+
+static isc_result_t
+nameexist(const cfg_obj_t *obj, const char *name, int value,
+ isc_symtab_t *symtab, const char *fmt, isc_log_t *logctx,
+ isc_mem_t *mctx)
+{
+ char *key;
+ const char *file;
+ unsigned int line;
+ isc_result_t result;
+ isc_symvalue_t symvalue;
+
+ key = isc_mem_strdup(mctx, name);
+ if (key == NULL)
+ return (ISC_R_NOMEMORY);
+ symvalue.as_cpointer = obj;
+ result = isc_symtab_define(symtab, key, value, symvalue,
+ isc_symexists_reject);
+ if (result == ISC_R_EXISTS) {
+ RUNTIME_CHECK(isc_symtab_lookup(symtab, key, value,
+ &symvalue) == ISC_R_SUCCESS);
+ file = cfg_obj_file(symvalue.as_cpointer);
+ line = cfg_obj_line(symvalue.as_cpointer);
+
+ if (file == NULL)
+ file = "<unknown file>";
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR, fmt, key, file, line);
+ isc_mem_free(mctx, key);
+ result = ISC_R_EXISTS;
+ } else if (result != ISC_R_SUCCESS) {
+ isc_mem_free(mctx, key);
+ }
+ return (result);
+}
+
+static isc_result_t
+mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
+ isc_mem_t *mctx)
+{
+ const cfg_obj_t *obj;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ const char *str;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t b;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ obj = cfg_tuple_get(secure, "name");
+ 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);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "bad domain name '%s'", str);
+ } else {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ result = nameexist(secure, namebuf, 1, symtab,
+ "dnssec-must-be-secure '%s': already "
+ "exists previous definition: %s:%u",
+ logctx, mctx);
+ }
+ return (result);
+}
+
+static isc_result_t
+checkacl(const char *aclname, cfg_aclconfctx_t *actx, const cfg_obj_t *zconfig,
+ const cfg_obj_t *voptions, const cfg_obj_t *config,
+ isc_log_t *logctx, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ const cfg_obj_t *aclobj = NULL;
+ const cfg_obj_t *options;
+ dns_acl_t *acl = NULL;
+
+ if (zconfig != NULL) {
+ options = cfg_tuple_get(zconfig, "options");
+ cfg_map_get(options, aclname, &aclobj);
+ }
+ if (voptions != NULL && aclobj == NULL)
+ cfg_map_get(voptions, aclname, &aclobj);
+ if (config != NULL && aclobj == NULL) {
+ options = NULL;
+ cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ cfg_map_get(options, aclname, &aclobj);
+ }
+ if (aclobj == NULL)
+ return (ISC_R_SUCCESS);
+ result = cfg_acl_fromconfig(aclobj, config, logctx,
+ actx, mctx, 0, &acl);
+ if (acl != NULL)
+ dns_acl_detach(&acl);
+ return (result);
+}
+
+static isc_result_t
+check_viewacls(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, tresult;
+ int i = 0;
+
+ static const char *acls[] = { "allow-query", "allow-query-on",
+ "allow-query-cache", "allow-query-cache-on",
+ "blackhole", "match-clients", "match-destinations",
+ "sortlist", NULL };
+
+ while (acls[i] != NULL) {
+ tresult = checkacl(acls[i++], actx, NULL, voptions, config,
+ logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ return (result);
+}
+
+/*
+ * Check allow-recursion and allow-recursion-on acls, and also log a
+ * warning if they're inconsistent with the "recursion" option.
+ */
+static isc_result_t
+check_recursionacls(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;
+ isc_boolean_t recursion;
+ const char *forview = " for view ";
+ int i = 0;
+
+ static const char *acls[] = { "allow-recursion", "allow-recursion-on",
+ NULL };
+
+ if (voptions != NULL)
+ cfg_map_get(voptions, "recursion", &obj);
+ if (obj == NULL && config != NULL) {
+ options = NULL;
+ cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ cfg_map_get(options, "recursion", &obj);
+ }
+ if (obj == NULL)
+ recursion = ISC_TRUE;
+ else
+ recursion = cfg_obj_asboolean(obj);
+
+ if (viewname == NULL) {
+ viewname = "";
+ forview = "";
+ }
+
+ for (i = 0; acls[i] != NULL; i++) {
+ aclobj = options = NULL;
+ acl = NULL;
+
+ if (voptions != NULL)
+ cfg_map_get(voptions, acls[i], &aclobj);
+ if (config != NULL && aclobj == NULL) {
+ options = NULL;
+ cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ cfg_map_get(options, acls[i], &aclobj);
+ }
+ if (aclobj == NULL)
+ continue;
+
+ tresult = cfg_acl_fromconfig(aclobj, config, logctx,
+ actx, mctx, 0, &acl);
+
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+
+ if (acl == NULL)
+ continue;
+
+ if (recursion == ISC_FALSE && !dns_acl_isnone(acl)) {
+ cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING,
+ "both \"recursion no;\" and "
+ "\"%s\" active%s%s",
+ acls[i], forview, viewname);
+ }
+
+ if (acl != NULL)
+ dns_acl_detach(&acl);
+ }
+
+ return (result);
+}
+
+typedef struct {
+ const char *name;
+ unsigned int scale;
+ unsigned int max;
+} intervaltable;
+
+static isc_result_t
+check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ unsigned int i;
+ const cfg_obj_t *obj = NULL;
+ const cfg_obj_t *resignobj = NULL;
+ const cfg_listelt_t *element;
+ isc_symtab_t *symtab = NULL;
+ dns_fixedname_t fixed;
+ const char *str;
+ dns_name_t *name;
+ isc_buffer_t b;
+
+ static intervaltable intervals[] = {
+ { "cleaning-interval", 60, 28 * 24 * 60 }, /* 28 days */
+ { "heartbeat-interval", 60, 28 * 24 * 60 }, /* 28 days */
+ { "interface-interval", 60, 28 * 24 * 60 }, /* 28 days */
+ { "max-transfer-idle-in", 60, 28 * 24 * 60 }, /* 28 days */
+ { "max-transfer-idle-out", 60, 28 * 24 * 60 }, /* 28 days */
+ { "max-transfer-time-in", 60, 28 * 24 * 60 }, /* 28 days */
+ { "max-transfer-time-out", 60, 28 * 24 * 60 }, /* 28 days */
+ { "statistics-interval", 60, 28 * 24 * 60 }, /* 28 days */
+ };
+
+ /*
+ * Check that fields specified in units of time other than seconds
+ * have reasonable values.
+ */
+ for (i = 0; i < sizeof(intervals) / sizeof(intervals[0]); i++) {
+ isc_uint32_t val;
+ obj = NULL;
+ (void)cfg_map_get(options, intervals[i].name, &obj);
+ if (obj == NULL)
+ continue;
+ val = cfg_obj_asuint32(obj);
+ if (val > intervals[i].max) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "%s '%u' is out of range (0..%u)",
+ intervals[i].name, val,
+ intervals[i].max);
+ result = ISC_R_RANGE;
+ } else if (val > (ISC_UINT32_MAX / intervals[i].scale)) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "%s '%d' is out of range",
+ intervals[i].name, val);
+ result = ISC_R_RANGE;
+ }
+ }
+
+ obj = NULL;
+ cfg_map_get(options, "sig-validity-interval", &obj);
+ if (obj != NULL) {
+ isc_uint32_t validity, resign = 0;
+
+ validity = cfg_obj_asuint32(cfg_tuple_get(obj, "validity"));
+ resignobj = cfg_tuple_get(obj, "re-sign");
+ if (!cfg_obj_isvoid(resignobj))
+ resign = cfg_obj_asuint32(resignobj);
+
+ if (validity > 3660 || validity == 0) { /* 10 years */
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "%s '%u' is out of range (1..3660)",
+ "sig-validity-interval", validity);
+ result = ISC_R_RANGE;
+ }
+
+ if (!cfg_obj_isvoid(resignobj)) {
+ if (resign > 3660 || resign == 0) { /* 10 years */
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "%s '%u' is out of range (1..3660)",
+ "sig-validity-interval (re-sign)",
+ validity);
+ result = ISC_R_RANGE;
+ } else if ((validity > 7 && validity < resign) ||
+ (validity <= 7 && validity * 24 < resign)) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "validity interval (%u days) "
+ "less than re-signing interval "
+ "(%u %s)", validity, resign,
+ (validity > 7) ? "days" : "hours");
+ result = ISC_R_RANGE;
+ }
+ }
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(options, "preferred-glue", &obj);
+ if (obj != NULL) {
+ const char *str;
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "a") != 0 &&
+ strcasecmp(str, "aaaa") != 0 &&
+ strcasecmp(str, "none") != 0)
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "preferred-glue unexpected value '%s'",
+ str);
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(options, "root-delegation-only", &obj);
+ if (obj != NULL) {
+ if (!cfg_obj_isvoid(obj)) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *exclude;
+ const char *str;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t b;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ exclude = cfg_listelt_value(element);
+ str = cfg_obj_asstring(exclude);
+ isc_buffer_init(&b, str, strlen(str));
+ isc_buffer_add(&b, strlen(str));
+ tresult = dns_name_fromtext(name, &b,
+ dns_rootname,
+ ISC_FALSE, NULL);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "bad domain name '%s'",
+ str);
+ result = tresult;
+ }
+ }
+ }
+ }
+
+ /*
+ * Set supported DNSSEC algorithms.
+ */
+ obj = NULL;
+ (void)cfg_map_get(options, "disable-algorithms", &obj);
+ if (obj != NULL) {
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ tresult = disabled_algorithms(obj, logctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ }
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+
+ /*
+ * Check the DLV zone name.
+ */
+ obj = NULL;
+ (void)cfg_map_get(options, "dnssec-lookaside", &obj);
+ if (obj != NULL) {
+ tresult = isc_symtab_create(mctx, 100, freekey, mctx,
+ ISC_FALSE, &symtab);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const char *dlv;
+
+ obj = cfg_listelt_value(element);
+
+ dlv = cfg_obj_asstring(cfg_tuple_get(obj, "domain"));
+ 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) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "bad domain name '%s'", dlv);
+ result = tresult;
+ continue;
+ }
+ if (symtab != NULL) {
+ tresult = nameexist(obj, dlv, 1, symtab,
+ "dnssec-lookaside '%s': "
+ "already exists previous "
+ "definition: %s:%u",
+ logctx, mctx);
+ if (tresult != ISC_R_SUCCESS &&
+ result == ISC_R_SUCCESS)
+ result = tresult;
+ }
+ /*
+ * XXXMPA to be removed when multiple lookaside
+ * namespaces are supported.
+ */
+ if (!dns_name_equal(dns_rootname, name)) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "dnssec-lookaside '%s': "
+ "non-root not yet supported", dlv);
+ 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) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "bad domain name '%s'", dlv);
+ if (result == ISC_R_SUCCESS)
+ result = tresult;
+ }
+ }
+ if (symtab != NULL)
+ isc_symtab_destroy(&symtab);
+ }
+
+ /*
+ * Check dnssec-must-be-secure.
+ */
+ obj = NULL;
+ (void)cfg_map_get(options, "dnssec-must-be-secure", &obj);
+ if (obj != NULL) {
+ isc_symtab_t *symtab = NULL;
+ tresult = isc_symtab_create(mctx, 100, freekey, mctx,
+ ISC_FALSE, &symtab);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ tresult = mustbesecure(obj, symtab, logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ if (symtab != NULL)
+ isc_symtab_destroy(&symtab);
+ }
+
+ /*
+ * Check empty zone configuration.
+ */
+ 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;
+ }
+ }
+
+ obj = NULL;
+ (void)cfg_map_get(options, "disable-empty-zone", &obj);
+ for (element = cfg_list_first(obj);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ 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,
+ "disable-empty-zone: invalid name '%s'",
+ str);
+ result = ISC_R_FAILURE;
+ }
+ }
+
+ /*
+ * Check that server-id is not too long.
+ * 1024 bytes should be big enough.
+ */
+ obj = NULL;
+ (void)cfg_map_get(options, "server-id", &obj);
+ if (obj != NULL && cfg_obj_isstring(obj) &&
+ strlen(cfg_obj_asstring(obj)) > 1024U) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "'server-id' too big (>1024 bytes)");
+ result = ISC_R_FAILURE;
+ }
+
+ return (result);
+}
+
+static isc_result_t
+get_masters_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) {
+ isc_result_t result;
+ const cfg_obj_t *masters = NULL;
+ const cfg_listelt_t *elt;
+
+ result = cfg_map_get(cctx, "masters", &masters);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ for (elt = cfg_list_first(masters);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ const cfg_obj_t *list;
+ const char *listname;
+
+ list = cfg_listelt_value(elt);
+ listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
+
+ if (strcasecmp(listname, name) == 0) {
+ *ret = list;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+validate_masters(const cfg_obj_t *obj, const cfg_obj_t *config,
+ isc_uint32_t *countp, isc_log_t *logctx, isc_mem_t *mctx)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ isc_uint32_t count = 0;
+ isc_symtab_t *symtab = NULL;
+ isc_symvalue_t symvalue;
+ const cfg_listelt_t *element;
+ const cfg_listelt_t **stack = NULL;
+ isc_uint32_t stackcount = 0, pushed = 0;
+ const cfg_obj_t *list;
+
+ REQUIRE(countp != NULL);
+ result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab);
+ if (result != ISC_R_SUCCESS) {
+ *countp = count;
+ return (result);
+ }
+
+ newlist:
+ list = cfg_tuple_get(obj, "addresses");
+ element = cfg_list_first(list);
+ resume:
+ for ( ;
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const char *listname;
+ const cfg_obj_t *addr;
+ const cfg_obj_t *key;
+
+ addr = cfg_tuple_get(cfg_listelt_value(element),
+ "masterselement");
+ key = cfg_tuple_get(cfg_listelt_value(element), "key");
+
+ if (cfg_obj_issockaddr(addr)) {
+ count++;
+ continue;
+ }
+ if (!cfg_obj_isvoid(key)) {
+ cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+ "unexpected token '%s'",
+ cfg_obj_asstring(key));
+ if (result == ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ }
+ listname = cfg_obj_asstring(addr);
+ symvalue.as_cpointer = addr;
+ tresult = isc_symtab_define(symtab, listname, 1, symvalue,
+ isc_symexists_reject);
+ if (tresult == ISC_R_EXISTS)
+ continue;
+ tresult = get_masters_def(config, listname, &obj);
+ if (tresult != ISC_R_SUCCESS) {
+ if (result == ISC_R_SUCCESS)
+ result = tresult;
+ cfg_obj_log(addr, logctx, ISC_LOG_ERROR,
+ "unable to find masters list '%s'",
+ listname);
+ continue;
+ }
+ /* Grow stack? */
+ if (stackcount == pushed) {
+ void * new;
+ isc_uint32_t newlen = stackcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(*stack);
+ oldsize = stackcount * sizeof(*stack);
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ if (stackcount != 0) {
+ memcpy(new, stack, oldsize);
+ isc_mem_put(mctx, stack, oldsize);
+ }
+ stack = new;
+ stackcount = newlen;
+ }
+ stack[pushed++] = cfg_list_next(element);
+ goto newlist;
+ }
+ if (pushed != 0) {
+ element = stack[--pushed];
+ goto resume;
+ }
+ cleanup:
+ if (stack != NULL)
+ isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
+ isc_symtab_destroy(&symtab);
+ *countp = count;
+ return (result);
+}
+
+static isc_result_t
+check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ const cfg_listelt_t *element;
+ const cfg_listelt_t *element2;
+ dns_fixedname_t fixed;
+ const char *str;
+ isc_buffer_t b;
+
+ for (element = cfg_list_first(policy);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *stmt = cfg_listelt_value(element);
+ const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
+ const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
+ const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
+ const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
+
+ dns_fixedname_init(&fixed);
+ str = cfg_obj_asstring(identity);
+ 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(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), "wildcard") == 0 &&
+ !dns_name_iswildcard(dns_fixedname_name(&fixed))) {
+ cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
+ "'%s' is not a wildcard", str);
+ result = ISC_R_FAILURE;
+ }
+
+ for (element2 = cfg_list_first(typelist);
+ element2 != NULL;
+ element2 = cfg_list_next(element2))
+ {
+ const cfg_obj_t *typeobj;
+ isc_textregion_t r;
+ dns_rdatatype_t type;
+
+ typeobj = cfg_listelt_value(element2);
+ DE_CONST(cfg_obj_asstring(typeobj), r.base);
+ r.length = strlen(r.base);
+
+ tresult = dns_rdatatype_fromtext(&type, &r);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(typeobj, logctx, ISC_LOG_ERROR,
+ "'%s' is not a valid type", r.base);
+ result = tresult;
+ }
+ }
+ }
+ return (result);
+}
+
+#define MASTERZONE 1
+#define SLAVEZONE 2
+#define STUBZONE 4
+#define HINTZONE 8
+#define FORWARDZONE 16
+#define DELEGATIONZONE 32
+#define CHECKACL 64
+
+typedef struct {
+ const char *name;
+ int allowed;
+} optionstable;
+
+static isc_result_t
+check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
+ const cfg_obj_t *config, isc_symtab_t *symtab,
+ dns_rdataclass_t defclass, cfg_aclconfctx_t *actx,
+ isc_log_t *logctx, isc_mem_t *mctx)
+{
+ const char *zname;
+ const char *typestr;
+ unsigned int ztype;
+ const cfg_obj_t *zoptions;
+ const cfg_obj_t *obj = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ unsigned int i;
+ dns_rdataclass_t zclass;
+ dns_fixedname_t fixedname;
+ isc_buffer_t b;
+ isc_boolean_t root = ISC_FALSE;
+
+ static optionstable options[] = {
+ { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL },
+ { "allow-notify", SLAVEZONE | CHECKACL },
+ { "allow-transfer", MASTERZONE | SLAVEZONE | CHECKACL },
+ { "notify", MASTERZONE | SLAVEZONE },
+ { "also-notify", MASTERZONE | SLAVEZONE },
+ { "dialup", MASTERZONE | SLAVEZONE | STUBZONE },
+ { "delegation-only", HINTZONE | STUBZONE },
+ { "forward", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
+ { "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
+ { "maintain-ixfr-base", MASTERZONE | SLAVEZONE },
+ { "max-ixfr-log-size", MASTERZONE | SLAVEZONE },
+ { "notify-source", MASTERZONE | SLAVEZONE },
+ { "notify-source-v6", MASTERZONE | SLAVEZONE },
+ { "transfer-source", SLAVEZONE | STUBZONE },
+ { "transfer-source-v6", SLAVEZONE | STUBZONE },
+ { "max-transfer-time-in", SLAVEZONE | STUBZONE },
+ { "max-transfer-time-out", MASTERZONE | SLAVEZONE },
+ { "max-transfer-idle-in", SLAVEZONE | STUBZONE },
+ { "max-transfer-idle-out", MASTERZONE | SLAVEZONE },
+ { "max-retry-time", SLAVEZONE | STUBZONE },
+ { "min-retry-time", SLAVEZONE | STUBZONE },
+ { "max-refresh-time", SLAVEZONE | STUBZONE },
+ { "min-refresh-time", SLAVEZONE | STUBZONE },
+ { "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 },
+ { "allow-update", MASTERZONE | CHECKACL },
+ { "allow-update-forwarding", SLAVEZONE | CHECKACL },
+ { "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE },
+ { "journal", MASTERZONE | SLAVEZONE },
+ { "ixfr-base", MASTERZONE | SLAVEZONE },
+ { "ixfr-tmp-file", MASTERZONE | SLAVEZONE },
+ { "masters", SLAVEZONE | STUBZONE },
+ { "pubkey", MASTERZONE | SLAVEZONE | STUBZONE },
+ { "update-policy", MASTERZONE },
+ { "database", MASTERZONE | SLAVEZONE | STUBZONE },
+ { "key-directory", MASTERZONE },
+ { "check-wildcard", MASTERZONE },
+ { "check-mx", MASTERZONE },
+ { "integrity-check", MASTERZONE },
+ { "check-mx-cname", MASTERZONE },
+ { "check-srv-cname", MASTERZONE },
+ { "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE },
+ { "update-check-ksk", MASTERZONE },
+ { "try-tcp-refresh", SLAVEZONE },
+ };
+
+ static optionstable dialups[] = {
+ { "notify", MASTERZONE | SLAVEZONE },
+ { "notify-passive", SLAVEZONE },
+ { "refresh", SLAVEZONE | STUBZONE },
+ { "passive", SLAVEZONE | STUBZONE },
+ };
+
+ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
+
+ zoptions = cfg_tuple_get(zconfig, "options");
+
+ obj = NULL;
+ (void)cfg_map_get(zoptions, "type", &obj);
+ if (obj == NULL) {
+ cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
+ "zone '%s': type not present", zname);
+ return (ISC_R_FAILURE);
+ }
+
+ typestr = cfg_obj_asstring(obj);
+ if (strcasecmp(typestr, "master") == 0)
+ ztype = MASTERZONE;
+ else if (strcasecmp(typestr, "slave") == 0)
+ ztype = SLAVEZONE;
+ else if (strcasecmp(typestr, "stub") == 0)
+ ztype = STUBZONE;
+ else if (strcasecmp(typestr, "forward") == 0)
+ ztype = FORWARDZONE;
+ else if (strcasecmp(typestr, "hint") == 0)
+ ztype = HINTZONE;
+ else if (strcasecmp(typestr, "delegation-only") == 0)
+ ztype = DELEGATIONZONE;
+ else {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "zone '%s': invalid type %s",
+ zname, typestr);
+ return (ISC_R_FAILURE);
+ }
+
+ obj = cfg_tuple_get(zconfig, "class");
+ if (cfg_obj_isstring(obj)) {
+ isc_textregion_t r;
+
+ DE_CONST(cfg_obj_asstring(obj), r.base);
+ r.length = strlen(r.base);
+ result = dns_rdataclass_fromtext(&zclass, &r);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "zone '%s': invalid class %s",
+ zname, 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);
+ return (ISC_R_FAILURE);
+ }
+ }
+
+ /*
+ * Look for an already existing zone.
+ * We need to make this cannonical as isc_symtab_define()
+ * deals with strings.
+ */
+ dns_fixedname_init(&fixedname);
+ isc_buffer_init(&b, zname, strlen(zname));
+ isc_buffer_add(&b, strlen(zname));
+ tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b,
+ dns_rootname, ISC_TRUE, NULL);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
+ "zone '%s': is not a valid name", zname);
+ result = ISC_R_FAILURE;
+ } else {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(dns_fixedname_name(&fixedname),
+ 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))
+ root = ISC_TRUE;
+ }
+
+ /*
+ * Look for inappropriate options for the given zone type.
+ * Check that ACLs expand correctly.
+ */
+ for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) {
+ obj = NULL;
+ if ((options[i].allowed & ztype) == 0 &&
+ cfg_map_get(zoptions, options[i].name, &obj) ==
+ ISC_R_SUCCESS)
+ {
+ if (strcmp(options[i].name, "allow-update") != 0 ||
+ ztype != SLAVEZONE) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "option '%s' is not allowed "
+ "in '%s' zone '%s'",
+ options[i].name, typestr, zname);
+ 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);
+ }
+ obj = NULL;
+ if ((options[i].allowed & ztype) != 0 &&
+ (options[i].allowed & CHECKACL) != 0) {
+
+ tresult = checkacl(options[i].name, actx, zconfig,
+ voptions, config, logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+
+ }
+
+ /*
+ * Slave & stub zones must have a "masters" field.
+ */
+ if (ztype == SLAVEZONE || ztype == STUBZONE) {
+ obj = NULL;
+ if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) {
+ cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
+ "zone '%s': missing 'masters' entry",
+ zname);
+ result = ISC_R_FAILURE;
+ } else {
+ isc_uint32_t count;
+ tresult = validate_masters(obj, config, &count,
+ logctx, mctx);
+ if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
+ result = tresult;
+ if (tresult == ISC_R_SUCCESS && count == 0) {
+ cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
+ "zone '%s': empty 'masters' entry",
+ zname);
+ result = ISC_R_FAILURE;
+ }
+ }
+ }
+
+ /*
+ * Master zones can't have both "allow-update" and "update-policy".
+ */
+ if (ztype == MASTERZONE) {
+ isc_result_t res1, res2;
+ obj = NULL;
+ res1 = cfg_map_get(zoptions, "allow-update", &obj);
+ obj = NULL;
+ res2 = cfg_map_get(zoptions, "update-policy", &obj);
+ if (res1 == ISC_R_SUCCESS && res2 == ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "zone '%s': 'allow-update' is ignored "
+ "when 'update-policy' is present",
+ zname);
+ result = ISC_R_FAILURE;
+ } else if (res2 == ISC_R_SUCCESS &&
+ check_update_policy(obj, logctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ obj = NULL;
+ res1 = cfg_map_get(zoptions, "sig-signing-type", &obj);
+ if (res1 == ISC_R_SUCCESS) {
+ isc_uint32_t type = cfg_obj_asuint32(obj);
+ if (type < 0xff00U || type > 0xffffU)
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "sig-signing-type: %u out of "
+ "range [%u..%u]", type,
+ 0xff00U, 0xffffU);
+ result = ISC_R_FAILURE;
+ }
+ }
+
+ /*
+ * Check the excessively complicated "dialup" option.
+ */
+ if (ztype == MASTERZONE || ztype == SLAVEZONE || ztype == STUBZONE) {
+ const cfg_obj_t *dialup = NULL;
+ (void)cfg_map_get(zoptions, "dialup", &dialup);
+ if (dialup != NULL && cfg_obj_isstring(dialup)) {
+ const char *str = cfg_obj_asstring(dialup);
+ for (i = 0;
+ i < sizeof(dialups) / sizeof(dialups[0]);
+ i++)
+ {
+ if (strcasecmp(dialups[i].name, str) != 0)
+ continue;
+ if ((dialups[i].allowed & ztype) == 0) {
+ cfg_obj_log(obj, logctx,
+ ISC_LOG_ERROR,
+ "dialup type '%s' is not "
+ "allowed in '%s' "
+ "zone '%s'",
+ str, typestr, zname);
+ result = ISC_R_FAILURE;
+ }
+ break;
+ }
+ if (i == sizeof(dialups) / sizeof(dialups[0])) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "invalid dialup type '%s' in zone "
+ "'%s'", str, zname);
+ result = ISC_R_FAILURE;
+ }
+ }
+ }
+
+ /*
+ * Check that forwarding is reasonable.
+ */
+ obj = NULL;
+ if (root) {
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "forwarders", &obj);
+ if (obj == NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ (void)cfg_map_get(options, "forwarders", &obj);
+ }
+ }
+ if (check_forward(zoptions, obj, logctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+
+ /*
+ * Check various options.
+ */
+ tresult = check_options(zoptions, logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+
+ /*
+ * If the zone type is rbt/rbt64 then master/hint zones
+ * require file clauses.
+ */
+ obj = NULL;
+ tresult = cfg_map_get(zoptions, "database", &obj);
+ if (tresult == ISC_R_NOTFOUND ||
+ (tresult == ISC_R_SUCCESS &&
+ (strcmp("rbt", cfg_obj_asstring(obj)) == 0 ||
+ strcmp("rbt64", cfg_obj_asstring(obj)) == 0))) {
+ obj = NULL;
+ tresult = cfg_map_get(zoptions, "file", &obj);
+ if (tresult != ISC_R_SUCCESS &&
+ (ztype == MASTERZONE || ztype == HINTZONE)) {
+ cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
+ "zone '%s': missing 'file' entry",
+ zname);
+ result = tresult;
+ }
+ }
+
+ return (result);
+}
+
+
+typedef struct keyalgorithms {
+ const char *name;
+ isc_uint16_t size;
+} algorithmtable;
+
+isc_result_t
+bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) {
+ const cfg_obj_t *algobj = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
+ const char *algorithm;
+ int i;
+ size_t len = 0;
+ static const algorithmtable algorithms[] = {
+ { "hmac-md5", 128 },
+ { "hmac-md5.sig-alg.reg.int", 0 },
+ { "hmac-md5.sig-alg.reg.int.", 0 },
+ { "hmac-sha1", 160 },
+ { "hmac-sha224", 224 },
+ { "hmac-sha256", 256 },
+ { "hmac-sha384", 384 },
+ { "hmac-sha512", 512 },
+ { NULL, 0 }
+ };
+
+ (void)cfg_map_get(key, "algorithm", &algobj);
+ (void)cfg_map_get(key, "secret", &secretobj);
+ if (secretobj == NULL || algobj == NULL) {
+ cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+ "key '%s' must have both 'secret' and "
+ "'algorithm' defined",
+ keyname);
+ return (ISC_R_FAILURE);
+ }
+
+ algorithm = cfg_obj_asstring(algobj);
+ for (i = 0; algorithms[i].name != NULL; i++) {
+ len = strlen(algorithms[i].name);
+ if (strncasecmp(algorithms[i].name, algorithm, len) == 0 &&
+ (algorithm[len] == '\0' ||
+ (algorithms[i].size != 0 && algorithm[len] == '-')))
+ break;
+ }
+ if (algorithms[i].name == NULL) {
+ cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
+ "unknown algorithm '%s'", algorithm);
+ return (ISC_R_NOTFOUND);
+ }
+ if (algorithm[len] == '-') {
+ isc_uint16_t digestbits;
+ isc_result_t result;
+ result = isc_parse_uint16(&digestbits, algorithm + len + 1, 10);
+ if (result == ISC_R_SUCCESS || result == ISC_R_RANGE) {
+ if (result == ISC_R_RANGE ||
+ digestbits > algorithms[i].size) {
+ cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
+ "key '%s' digest-bits too large "
+ "[%u..%u]", keyname,
+ algorithms[i].size / 2,
+ algorithms[i].size);
+ return (ISC_R_RANGE);
+ }
+ if ((digestbits % 8) != 0) {
+ cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
+ "key '%s' digest-bits not multiple"
+ " of 8", keyname);
+ return (ISC_R_RANGE);
+ }
+ /*
+ * Recommended minima for hmac algorithms.
+ */
+ if ((digestbits < (algorithms[i].size / 2U) ||
+ (digestbits < 80U)))
+ cfg_obj_log(algobj, logctx, ISC_LOG_WARNING,
+ "key '%s' digest-bits too small "
+ "[<%u]", keyname,
+ algorithms[i].size/2);
+ } else {
+ cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
+ "key '%s': unable to parse digest-bits",
+ keyname);
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Check key list for duplicates key names and that the key names
+ * are valid domain names as these keys are used for TSIG.
+ *
+ * Check the key contents for validity.
+ */
+static isc_result_t
+check_keylist(const cfg_obj_t *keys, isc_symtab_t *symtab,
+ isc_mem_t *mctx, isc_log_t *logctx)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ const cfg_listelt_t *element;
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ for (element = cfg_list_first(keys);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ const cfg_obj_t *key = cfg_listelt_value(element);
+ const char *keyid = cfg_obj_asstring(cfg_map_getname(key));
+ isc_symvalue_t symvalue;
+ isc_buffer_t b;
+ char *keyname;
+
+ isc_buffer_init(&b, keyid, strlen(keyid));
+ isc_buffer_add(&b, strlen(keyid));
+ tresult = dns_name_fromtext(name, &b, dns_rootname,
+ ISC_FALSE, NULL);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+ "key '%s': bad key name", keyid);
+ result = tresult;
+ continue;
+ }
+ tresult = bind9_check_key(key, logctx);
+ if (tresult != ISC_R_SUCCESS)
+ return (tresult);
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ keyname = isc_mem_strdup(mctx, namebuf);
+ if (keyname == NULL)
+ return (ISC_R_NOMEMORY);
+ symvalue.as_cpointer = key;
+ tresult = isc_symtab_define(symtab, keyname, 1, symvalue,
+ isc_symexists_reject);
+ if (tresult == ISC_R_EXISTS) {
+ const char *file;
+ unsigned int line;
+
+ RUNTIME_CHECK(isc_symtab_lookup(symtab, keyname,
+ 1, &symvalue) == ISC_R_SUCCESS);
+ file = cfg_obj_file(symvalue.as_cpointer);
+ line = cfg_obj_line(symvalue.as_cpointer);
+
+ if (file == NULL)
+ file = "<unknown file>";
+ cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+ "key '%s': already exists "
+ "previous definition: %s:%u",
+ keyid, file, line);
+ isc_mem_free(mctx, keyname);
+ result = tresult;
+ } else if (tresult != ISC_R_SUCCESS) {
+ isc_mem_free(mctx, keyname);
+ return (tresult);
+ }
+ }
+ return (result);
+}
+
+static struct {
+ const char *v4;
+ const char *v6;
+} sources[] = {
+ { "transfer-source", "transfer-source-v6" },
+ { "notify-source", "notify-source-v6" },
+ { "query-source", "query-source-v6" },
+ { NULL, NULL }
+};
+
+/*
+ * RNDC keys are not normalised unlike TSIG keys.
+ *
+ * "foo." is different to "foo".
+ */
+static isc_boolean_t
+rndckey_exists(const cfg_obj_t *keylist, const char *keyname) {
+ const cfg_listelt_t *element;
+ const cfg_obj_t *obj;
+ const char *str;
+
+ if (keylist == NULL)
+ return (ISC_FALSE);
+
+ for (element = cfg_list_first(keylist);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ obj = cfg_listelt_value(element);
+ str = cfg_obj_asstring(cfg_map_getname(obj));
+ if (!strcasecmp(str, keyname))
+ return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions,
+ isc_symtab_t *symtab, isc_log_t *logctx)
+{
+ dns_fixedname_t fname;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ const cfg_listelt_t *e1, *e2;
+ const cfg_obj_t *v1, *v2, *keys;
+ const cfg_obj_t *servers;
+ isc_netaddr_t n1, n2;
+ unsigned int p1, p2;
+ const cfg_obj_t *obj;
+ char buf[ISC_NETADDR_FORMATSIZE];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ const char *xfr;
+ const char *keyval;
+ isc_buffer_t b;
+ int source;
+ dns_name_t *keyname;
+
+ servers = NULL;
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "server", &servers);
+ if (servers == NULL)
+ (void)cfg_map_get(config, "server", &servers);
+ if (servers == NULL)
+ return (ISC_R_SUCCESS);
+
+ for (e1 = cfg_list_first(servers); e1 != NULL; e1 = cfg_list_next(e1)) {
+ v1 = cfg_listelt_value(e1);
+ cfg_obj_asnetprefix(cfg_map_getname(v1), &n1, &p1);
+ /*
+ * Check that unused bits are zero.
+ */
+ tresult = isc_netaddr_prefixok(&n1, p1);
+ if (tresult != ISC_R_SUCCESS) {
+ INSIST(tresult == ISC_R_FAILURE);
+ isc_netaddr_format(&n1, buf, sizeof(buf));
+ cfg_obj_log(v1, logctx, ISC_LOG_ERROR,
+ "server '%s/%u': invalid prefix "
+ "(extra bits specified)", buf, p1);
+ result = tresult;
+ }
+ source = 0;
+ do {
+ obj = NULL;
+ if (n1.family == AF_INET)
+ xfr = sources[source].v6;
+ else
+ xfr = sources[source].v4;
+ (void)cfg_map_get(v1, xfr, &obj);
+ if (obj != NULL) {
+ isc_netaddr_format(&n1, buf, sizeof(buf));
+ cfg_obj_log(v1, logctx, ISC_LOG_ERROR,
+ "server '%s/%u': %s not legal",
+ buf, p1, xfr);
+ result = ISC_R_FAILURE;
+ }
+ } while (sources[++source].v4 != NULL);
+ e2 = e1;
+ while ((e2 = cfg_list_next(e2)) != NULL) {
+ v2 = cfg_listelt_value(e2);
+ cfg_obj_asnetprefix(cfg_map_getname(v2), &n2, &p2);
+ if (p1 == p2 && isc_netaddr_equal(&n1, &n2)) {
+ const char *file = cfg_obj_file(v1);
+ unsigned int line = cfg_obj_line(v1);
+
+ if (file == NULL)
+ file = "<unknown file>";
+
+ isc_netaddr_format(&n2, buf, sizeof(buf));
+ cfg_obj_log(v2, logctx, ISC_LOG_ERROR,
+ "server '%s/%u': already exists "
+ "previous definition: %s:%u",
+ buf, p2, file, line);
+ result = ISC_R_FAILURE;
+ }
+ }
+ keys = NULL;
+ cfg_map_get(v1, "keys", &keys);
+ if (keys != NULL) {
+ /*
+ * Normalize key name.
+ */
+ keyval = cfg_obj_asstring(keys);
+ dns_fixedname_init(&fname);
+ isc_buffer_init(&b, keyval, strlen(keyval));
+ isc_buffer_add(&b, strlen(keyval));
+ keyname = dns_fixedname_name(&fname);
+ tresult = dns_name_fromtext(keyname, &b, dns_rootname,
+ ISC_FALSE, NULL);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(keys, logctx, ISC_LOG_ERROR,
+ "bad key name '%s'", keyval);
+ result = ISC_R_FAILURE;
+ continue;
+ }
+ dns_name_format(keyname, namebuf, sizeof(namebuf));
+ tresult = isc_symtab_lookup(symtab, namebuf, 1, NULL);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(keys, logctx, ISC_LOG_ERROR,
+ "unknown key '%s'", keyval);
+ result = ISC_R_FAILURE;
+ }
+ }
+ }
+ return (result);
+}
+
+static isc_result_t
+check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
+ const char *viewname, dns_rdataclass_t vclass,
+ isc_log_t *logctx, isc_mem_t *mctx)
+{
+ const cfg_obj_t *zones = NULL;
+ const cfg_obj_t *keys = NULL;
+ const cfg_listelt_t *element;
+ isc_symtab_t *symtab = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult = ISC_R_SUCCESS;
+ cfg_aclconfctx_t actx;
+ const cfg_obj_t *obj;
+ isc_boolean_t enablednssec, enablevalidation;
+
+ /*
+ * Check that all zone statements are syntactically correct and
+ * there are no duplicate zones.
+ */
+ tresult = isc_symtab_create(mctx, 100, freekey, mctx,
+ ISC_FALSE, &symtab);
+ if (tresult != ISC_R_SUCCESS)
+ return (ISC_R_NOMEMORY);
+
+ cfg_aclconfctx_init(&actx);
+
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "zone", &zones);
+ else
+ (void)cfg_map_get(config, "zone", &zones);
+
+ for (element = cfg_list_first(zones);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ isc_result_t tresult;
+ const cfg_obj_t *zone = cfg_listelt_value(element);
+
+ tresult = check_zoneconf(zone, voptions, config, symtab,
+ vclass, &actx, logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ }
+
+ isc_symtab_destroy(&symtab);
+
+ /*
+ * Check that forwarding is reasonable.
+ */
+ if (voptions == NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ if (check_forward(options, NULL,
+ logctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ } else {
+ if (check_forward(voptions, NULL, logctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ }
+
+ /*
+ * Check that dual-stack-servers is reasonable.
+ */
+ if (voptions == NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ } else {
+ if (check_dual_stack(voptions, logctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ }
+
+ /*
+ * Check that rrset-order is reasonable.
+ */
+ if (voptions != NULL) {
+ if (check_order(voptions, logctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ }
+
+ /*
+ * Check that all key statements are syntactically correct and
+ * there are no duplicate keys.
+ */
+ tresult = isc_symtab_create(mctx, 100, freekey, mctx,
+ ISC_FALSE, &symtab);
+ if (tresult != ISC_R_SUCCESS)
+ return (ISC_R_NOMEMORY);
+
+ (void)cfg_map_get(config, "key", &keys);
+ tresult = check_keylist(keys, symtab, mctx, logctx);
+ if (tresult == ISC_R_EXISTS)
+ result = ISC_R_FAILURE;
+ else if (tresult != ISC_R_SUCCESS) {
+ isc_symtab_destroy(&symtab);
+ return (tresult);
+ }
+
+ if (voptions != NULL) {
+ keys = NULL;
+ (void)cfg_map_get(voptions, "key", &keys);
+ tresult = check_keylist(keys, symtab, mctx, logctx);
+ if (tresult == ISC_R_EXISTS)
+ result = ISC_R_FAILURE;
+ else if (tresult != ISC_R_SUCCESS) {
+ isc_symtab_destroy(&symtab);
+ return (tresult);
+ }
+ }
+
+ /*
+ * Global servers can refer to keys in views.
+ */
+ if (check_servers(config, voptions, symtab, logctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+
+ isc_symtab_destroy(&symtab);
+
+ /*
+ * Check that dnssec-enable/dnssec-validation are sensible.
+ */
+ obj = NULL;
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "dnssec-enable", &obj);
+ if (obj == NULL)
+ (void)cfg_map_get(config, "dnssec-enable", &obj);
+ if (obj == NULL)
+ enablednssec = ISC_TRUE;
+ else
+ enablednssec = cfg_obj_asboolean(obj);
+
+ obj = NULL;
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "dnssec-validation", &obj);
+ if (obj == NULL)
+ (void)cfg_map_get(config, "dnssec-validation", &obj);
+ if (obj == NULL)
+ enablevalidation = ISC_FALSE; /* XXXMPA Change for 9.5. */
+ else
+ enablevalidation = cfg_obj_asboolean(obj);
+
+ if (enablevalidation && !enablednssec)
+ cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
+ "'dnssec-validation yes;' and 'dnssec-enable no;'");
+
+ if (voptions != NULL)
+ tresult = check_options(voptions, logctx, mctx);
+ else
+ tresult = check_options(config, logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+
+ tresult = check_viewacls(&actx, voptions, config, logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+
+ tresult = check_recursionacls(&actx, voptions, viewname,
+ config, logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+
+ cfg_aclconfctx_destroy(&actx);
+
+ return (result);
+}
+
+static const char *
+default_channels[] = {
+ "default_syslog",
+ "default_stderr",
+ "default_debug",
+ "null",
+ NULL
+};
+
+static isc_result_t
+bind9_check_logging(const cfg_obj_t *config, isc_log_t *logctx,
+ isc_mem_t *mctx)
+{
+ const cfg_obj_t *categories = NULL;
+ const cfg_obj_t *category;
+ const cfg_obj_t *channels = NULL;
+ const cfg_obj_t *channel;
+ const cfg_listelt_t *element;
+ const cfg_listelt_t *delement;
+ const char *channelname;
+ const char *catname;
+ const cfg_obj_t *fileobj = NULL;
+ const cfg_obj_t *syslogobj = NULL;
+ const cfg_obj_t *nullobj = NULL;
+ const cfg_obj_t *stderrobj = NULL;
+ const cfg_obj_t *logobj = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ isc_symtab_t *symtab = NULL;
+ isc_symvalue_t symvalue;
+ int i;
+
+ (void)cfg_map_get(config, "logging", &logobj);
+ if (logobj == NULL)
+ return (ISC_R_SUCCESS);
+
+ result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ symvalue.as_cpointer = NULL;
+ for (i = 0; default_channels[i] != NULL; i++) {
+ tresult = isc_symtab_define(symtab, default_channels[i], 1,
+ symvalue, isc_symexists_replace);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+
+ cfg_map_get(logobj, "channel", &channels);
+
+ for (element = cfg_list_first(channels);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ channel = cfg_listelt_value(element);
+ channelname = cfg_obj_asstring(cfg_map_getname(channel));
+ fileobj = syslogobj = nullobj = stderrobj = NULL;
+ (void)cfg_map_get(channel, "file", &fileobj);
+ (void)cfg_map_get(channel, "syslog", &syslogobj);
+ (void)cfg_map_get(channel, "null", &nullobj);
+ (void)cfg_map_get(channel, "stderr", &stderrobj);
+ i = 0;
+ if (fileobj != NULL)
+ i++;
+ if (syslogobj != NULL)
+ i++;
+ if (nullobj != NULL)
+ i++;
+ if (stderrobj != NULL)
+ i++;
+ if (i != 1) {
+ cfg_obj_log(channel, logctx, ISC_LOG_ERROR,
+ "channel '%s': exactly one of file, syslog, "
+ "null, and stderr must be present",
+ channelname);
+ result = ISC_R_FAILURE;
+ }
+ tresult = isc_symtab_define(symtab, channelname, 1,
+ symvalue, isc_symexists_replace);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+
+ cfg_map_get(logobj, "category", &categories);
+
+ for (element = cfg_list_first(categories);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ category = cfg_listelt_value(element);
+ catname = cfg_obj_asstring(cfg_tuple_get(category, "name"));
+ if (isc_log_categorybyname(logctx, catname) == NULL) {
+ cfg_obj_log(category, logctx, ISC_LOG_ERROR,
+ "undefined category: '%s'", catname);
+ result = ISC_R_FAILURE;
+ }
+ channels = cfg_tuple_get(category, "destinations");
+ for (delement = cfg_list_first(channels);
+ delement != NULL;
+ delement = cfg_list_next(delement))
+ {
+ channel = cfg_listelt_value(delement);
+ channelname = cfg_obj_asstring(channel);
+ tresult = isc_symtab_lookup(symtab, channelname, 1,
+ &symvalue);
+ if (tresult != ISC_R_SUCCESS) {
+ cfg_obj_log(channel, logctx, ISC_LOG_ERROR,
+ "undefined channel: '%s'",
+ channelname);
+ result = tresult;
+ }
+ }
+ }
+ isc_symtab_destroy(&symtab);
+ return (result);
+}
+
+static isc_result_t
+bind9_check_controlskeys(const cfg_obj_t *control, const cfg_obj_t *keylist,
+ isc_log_t *logctx)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ const cfg_obj_t *control_keylist;
+ const cfg_listelt_t *element;
+ const cfg_obj_t *key;
+ const char *keyval;
+
+ control_keylist = cfg_tuple_get(control, "keys");
+ if (cfg_obj_isvoid(control_keylist))
+ return (ISC_R_SUCCESS);
+
+ for (element = cfg_list_first(control_keylist);
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ key = cfg_listelt_value(element);
+ keyval = cfg_obj_asstring(key);
+
+ if (!rndckey_exists(keylist, keyval)) {
+ cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+ "unknown key '%s'", keyval);
+ result = ISC_R_NOTFOUND;
+ }
+ }
+ return (result);
+}
+
+static isc_result_t
+bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx,
+ isc_mem_t *mctx)
+{
+ isc_result_t result = ISC_R_SUCCESS, tresult;
+ cfg_aclconfctx_t actx;
+ const cfg_listelt_t *element, *element2;
+ const cfg_obj_t *allow;
+ const cfg_obj_t *control;
+ const cfg_obj_t *controls;
+ const cfg_obj_t *controlslist = NULL;
+ const cfg_obj_t *inetcontrols;
+ const cfg_obj_t *unixcontrols;
+ const cfg_obj_t *keylist = NULL;
+ const char *path;
+ isc_uint32_t perm, mask;
+ dns_acl_t *acl = NULL;
+ isc_sockaddr_t addr;
+ int i;
+
+ (void)cfg_map_get(config, "controls", &controlslist);
+ if (controlslist == NULL)
+ return (ISC_R_SUCCESS);
+
+ (void)cfg_map_get(config, "key", &keylist);
+
+ cfg_aclconfctx_init(&actx);
+
+ /*
+ * INET: Check allow clause.
+ * UNIX: Check "perm" for sanity, check path length.
+ */
+ for (element = cfg_list_first(controlslist);
+ element != NULL;
+ element = cfg_list_next(element)) {
+ controls = cfg_listelt_value(element);
+ unixcontrols = NULL;
+ inetcontrols = NULL;
+ (void)cfg_map_get(controls, "unix", &unixcontrols);
+ (void)cfg_map_get(controls, "inet", &inetcontrols);
+ for (element2 = cfg_list_first(inetcontrols);
+ element2 != NULL;
+ element2 = cfg_list_next(element2)) {
+ control = cfg_listelt_value(element2);
+ allow = cfg_tuple_get(control, "allow");
+ tresult = cfg_acl_fromconfig(allow, config, logctx,
+ &actx, mctx, 0, &acl);
+ if (acl != NULL)
+ dns_acl_detach(&acl);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ tresult = bind9_check_controlskeys(control, keylist,
+ logctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ for (element2 = cfg_list_first(unixcontrols);
+ element2 != NULL;
+ element2 = cfg_list_next(element2)) {
+ control = cfg_listelt_value(element2);
+ path = cfg_obj_asstring(cfg_tuple_get(control, "path"));
+ tresult = isc_sockaddr_frompath(&addr, path);
+ if (tresult == ISC_R_NOSPACE) {
+ cfg_obj_log(control, logctx, ISC_LOG_ERROR,
+ "unix control '%s': path too long",
+ path);
+ result = ISC_R_NOSPACE;
+ }
+ perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm"));
+ for (i = 0; i < 3; i++) {
+#ifdef NEED_SECURE_DIRECTORY
+ mask = (0x1 << (i*3)); /* SEARCH */
+#else
+ mask = (0x6 << (i*3)); /* READ + WRITE */
+#endif
+ if ((perm & mask) == mask)
+ break;
+ }
+ if (i == 0) {
+ cfg_obj_log(control, logctx, ISC_LOG_WARNING,
+ "unix control '%s' allows access "
+ "to everyone", path);
+ } else if (i == 3) {
+ cfg_obj_log(control, logctx, ISC_LOG_WARNING,
+ "unix control '%s' allows access "
+ "to nobody", path);
+ }
+ tresult = bind9_check_controlskeys(control, keylist,
+ logctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ }
+ }
+ cfg_aclconfctx_destroy(&actx);
+ return (result);
+}
+
+isc_result_t
+bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
+ isc_mem_t *mctx)
+{
+ const cfg_obj_t *options = NULL;
+ const cfg_obj_t *views = NULL;
+ const cfg_obj_t *acls = NULL;
+ const cfg_obj_t *kals = NULL;
+ const cfg_obj_t *obj;
+ const cfg_listelt_t *velement;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ isc_symtab_t *symtab = NULL;
+
+ static const char *builtin[] = { "localhost", "localnets",
+ "any", "none"};
+
+ (void)cfg_map_get(config, "options", &options);
+
+ if (options != NULL &&
+ check_options(options, logctx, mctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+
+ if (bind9_check_logging(config, logctx, mctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+
+ if (bind9_check_controls(config, logctx, mctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+
+ if (options != NULL &&
+ check_order(options, logctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+
+ (void)cfg_map_get(config, "view", &views);
+
+ if (views != NULL && options != NULL)
+ if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+
+ if (views == NULL) {
+ if (check_viewconf(config, NULL, NULL, dns_rdataclass_in,
+ logctx, mctx) != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ } else {
+ const cfg_obj_t *zones = NULL;
+
+ (void)cfg_map_get(config, "zone", &zones);
+ if (zones != NULL) {
+ cfg_obj_log(zones, logctx, ISC_LOG_ERROR,
+ "when using 'view' statements, "
+ "all zones must be in views");
+ result = ISC_R_FAILURE;
+ }
+ }
+
+ tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_TRUE, &symtab);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ for (velement = cfg_list_first(views);
+ velement != NULL;
+ velement = cfg_list_next(velement))
+ {
+ const cfg_obj_t *view = cfg_listelt_value(velement);
+ const cfg_obj_t *vname = cfg_tuple_get(view, "name");
+ const cfg_obj_t *voptions = cfg_tuple_get(view, "options");
+ const cfg_obj_t *vclassobj = cfg_tuple_get(view, "class");
+ dns_rdataclass_t vclass = dns_rdataclass_in;
+ isc_result_t tresult = ISC_R_SUCCESS;
+ const char *key = cfg_obj_asstring(vname);
+ isc_symvalue_t symvalue;
+
+ if (cfg_obj_isstring(vclassobj)) {
+ isc_textregion_t r;
+
+ DE_CONST(cfg_obj_asstring(vclassobj), r.base);
+ r.length = strlen(r.base);
+ tresult = dns_rdataclass_fromtext(&vclass, &r);
+ if (tresult != ISC_R_SUCCESS)
+ cfg_obj_log(vclassobj, logctx, ISC_LOG_ERROR,
+ "view '%s': invalid class %s",
+ cfg_obj_asstring(vname), r.base);
+ }
+ if (tresult == ISC_R_SUCCESS && symtab != NULL) {
+ symvalue.as_cpointer = view;
+ tresult = isc_symtab_define(symtab, key, vclass,
+ symvalue,
+ isc_symexists_reject);
+ if (tresult == ISC_R_EXISTS) {
+ const char *file;
+ unsigned int line;
+ RUNTIME_CHECK(isc_symtab_lookup(symtab, key,
+ vclass, &symvalue) == ISC_R_SUCCESS);
+ file = cfg_obj_file(symvalue.as_cpointer);
+ line = cfg_obj_line(symvalue.as_cpointer);
+ cfg_obj_log(view, logctx, ISC_LOG_ERROR,
+ "view '%s': already exists "
+ "previous definition: %s:%u",
+ key, file, line);
+ result = tresult;
+ } else if (tresult != ISC_R_SUCCESS) {
+ result = tresult;
+ } else if ((strcasecmp(key, "_bind") == 0 &&
+ vclass == dns_rdataclass_ch) ||
+ (strcasecmp(key, "_default") == 0 &&
+ vclass == dns_rdataclass_in)) {
+ cfg_obj_log(view, logctx, ISC_LOG_ERROR,
+ "attempt to redefine builtin view "
+ "'%s'", key);
+ result = ISC_R_EXISTS;
+ }
+ }
+ if (tresult == ISC_R_SUCCESS)
+ tresult = check_viewconf(config, voptions, key,
+ vclass, logctx, mctx);
+ if (tresult != ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ }
+ if (symtab != NULL)
+ isc_symtab_destroy(&symtab);
+
+ if (views != NULL && options != NULL) {
+ obj = NULL;
+ tresult = cfg_map_get(options, "cache-file", &obj);
+ if (tresult == ISC_R_SUCCESS) {
+ cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+ "'cache-file' cannot be a global "
+ "option if views are present");
+ result = ISC_R_FAILURE;
+ }
+ }
+
+ cfg_map_get(config, "acl", &acls);
+
+ if (acls != NULL) {
+ const cfg_listelt_t *elt;
+ const cfg_listelt_t *elt2;
+ const char *aclname;
+
+ for (elt = cfg_list_first(acls);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ const cfg_obj_t *acl = cfg_listelt_value(elt);
+ unsigned int line = cfg_obj_line(acl);
+ unsigned int i;
+
+ aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
+ for (i = 0;
+ i < sizeof(builtin) / sizeof(builtin[0]);
+ i++)
+ if (strcasecmp(aclname, builtin[i]) == 0) {
+ cfg_obj_log(acl, logctx, ISC_LOG_ERROR,
+ "attempt to redefine "
+ "builtin acl '%s'",
+ aclname);
+ result = ISC_R_FAILURE;
+ break;
+ }
+
+ for (elt2 = cfg_list_next(elt);
+ elt2 != NULL;
+ elt2 = cfg_list_next(elt2)) {
+ const cfg_obj_t *acl2 = cfg_listelt_value(elt2);
+ const char *name;
+ name = cfg_obj_asstring(cfg_tuple_get(acl2,
+ "name"));
+ if (strcasecmp(aclname, name) == 0) {
+ const char *file = cfg_obj_file(acl);
+
+ if (file == NULL)
+ file = "<unknown file>";
+
+ cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
+ "attempt to redefine "
+ "acl '%s' previous "
+ "definition: %s:%u",
+ name, file, line);
+ result = ISC_R_FAILURE;
+ }
+ }
+ }
+ }
+
+ tresult = cfg_map_get(config, "kal", &kals);
+ if (tresult == ISC_R_SUCCESS) {
+ const cfg_listelt_t *elt;
+ const cfg_listelt_t *elt2;
+ const char *aclname;
+
+ for (elt = cfg_list_first(kals);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ const cfg_obj_t *acl = cfg_listelt_value(elt);
+
+ aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
+
+ for (elt2 = cfg_list_next(elt);
+ elt2 != NULL;
+ elt2 = cfg_list_next(elt2)) {
+ const cfg_obj_t *acl2 = cfg_listelt_value(elt2);
+ const char *name;
+ name = cfg_obj_asstring(cfg_tuple_get(acl2,
+ "name"));
+ if (strcasecmp(aclname, name) == 0) {
+ const char *file = cfg_obj_file(acl);
+ unsigned int line = cfg_obj_line(acl);
+
+ if (file == NULL)
+ file = "<unknown file>";
+
+ cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
+ "attempt to redefine "
+ "kal '%s' previous "
+ "definition: %s:%u",
+ name, file, line);
+ result = ISC_R_FAILURE;
+ }
+ }
+ }
+ }
+
+ return (result);
+}
diff --git a/lib/bind9/getaddresses.c b/lib/bind9/getaddresses.c
new file mode 100644
index 0000000..a75e14e
--- /dev/null
+++ b/lib/bind9/getaddresses.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002 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: getaddresses.c,v 1.22 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+#include <string.h>
+
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/netdb.h>
+#include <isc/netscope.h>
+#include <isc/result.h>
+#include <isc/sockaddr.h>
+#include <isc/util.h>
+
+#include <bind9/getaddresses.h>
+
+#ifdef HAVE_ADDRINFO
+#ifdef HAVE_GETADDRINFO
+#ifdef HAVE_GAISTRERROR
+#define USE_GETADDRINFO
+#endif
+#endif
+#endif
+
+#ifndef USE_GETADDRINFO
+#ifndef ISC_PLATFORM_NONSTDHERRNO
+extern int h_errno;
+#endif
+#endif
+
+isc_result_t
+bind9_getaddresses(const char *hostname, in_port_t port,
+ isc_sockaddr_t *addrs, int addrsize, int *addrcount)
+{
+ struct in_addr in4;
+ struct in6_addr in6;
+ isc_boolean_t have_ipv4, have_ipv6;
+ int i;
+
+#ifdef USE_GETADDRINFO
+ struct addrinfo *ai = NULL, *tmpai, hints;
+ int result;
+#else
+ struct hostent *he;
+#endif
+
+ REQUIRE(hostname != NULL);
+ REQUIRE(addrs != NULL);
+ REQUIRE(addrcount != NULL);
+ REQUIRE(addrsize > 0);
+
+ have_ipv4 = ISC_TF((isc_net_probeipv4() == ISC_R_SUCCESS));
+ have_ipv6 = ISC_TF((isc_net_probeipv6() == ISC_R_SUCCESS));
+
+ /*
+ * Try IPv4, then IPv6. In order to handle the extended format
+ * for IPv6 scoped addresses (address%scope_ID), we'll use a local
+ * working buffer of 128 bytes. The length is an ad-hoc value, but
+ * should be enough for this purpose; the buffer can contain a string
+ * of at least 80 bytes for scope_ID in addition to any IPv6 numeric
+ * addresses (up to 46 bytes), the delimiter character and the
+ * terminating NULL character.
+ */
+ if (inet_pton(AF_INET, hostname, &in4) == 1) {
+ if (have_ipv4)
+ isc_sockaddr_fromin(&addrs[0], &in4, port);
+ else
+ isc_sockaddr_v6fromin(&addrs[0], &in4, port);
+ *addrcount = 1;
+ return (ISC_R_SUCCESS);
+ } else if (strlen(hostname) <= 127U) {
+ char tmpbuf[128], *d;
+ isc_uint32_t zone = 0;
+
+ strcpy(tmpbuf, hostname);
+ d = strchr(tmpbuf, '%');
+ if (d != NULL)
+ *d = '\0';
+
+ if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) {
+ isc_netaddr_t na;
+
+ if (!have_ipv6)
+ return (ISC_R_FAMILYNOSUPPORT);
+
+ if (d != NULL) {
+#ifdef ISC_PLATFORM_HAVESCOPEID
+ isc_result_t result;
+
+ result = isc_netscope_pton(AF_INET6, d + 1,
+ &in6, &zone);
+
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#else
+ /*
+ * The extended format is specified while the
+ * system does not provide the ability to use
+ * it. Throw an explicit error instead of
+ * ignoring the specified value.
+ */
+ return (ISC_R_BADADDRESSFORM);
+#endif
+ }
+
+ isc_netaddr_fromin6(&na, &in6);
+ isc_netaddr_setzone(&na, zone);
+ isc_sockaddr_fromnetaddr(&addrs[0],
+ (const isc_netaddr_t *)&na,
+ port);
+
+ *addrcount = 1;
+ return (ISC_R_SUCCESS);
+
+ }
+ }
+#ifdef USE_GETADDRINFO
+ memset(&hints, 0, sizeof(hints));
+ if (!have_ipv6)
+ hints.ai_family = PF_INET;
+ else if (!have_ipv4)
+ hints.ai_family = PF_INET6;
+ else {
+ hints.ai_family = PF_UNSPEC;
+#ifdef AI_ADDRCONFIG
+ hints.ai_flags = AI_ADDRCONFIG;
+#endif
+ }
+ hints.ai_socktype = SOCK_STREAM;
+#ifdef AI_ADDRCONFIG
+ again:
+#endif
+ result = getaddrinfo(hostname, NULL, &hints, &ai);
+ switch (result) {
+ case 0:
+ break;
+ case EAI_NONAME:
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ return (ISC_R_NOTFOUND);
+#ifdef AI_ADDRCONFIG
+ case EAI_BADFLAGS:
+ if ((hints.ai_flags & AI_ADDRCONFIG) != 0) {
+ hints.ai_flags &= ~AI_ADDRCONFIG;
+ goto again;
+ }
+#endif
+ default:
+ return (ISC_R_FAILURE);
+ }
+ for (tmpai = ai, i = 0;
+ tmpai != NULL && i < addrsize;
+ tmpai = tmpai->ai_next)
+ {
+ if (tmpai->ai_family != AF_INET &&
+ tmpai->ai_family != AF_INET6)
+ continue;
+ if (tmpai->ai_family == AF_INET) {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)tmpai->ai_addr;
+ isc_sockaddr_fromin(&addrs[i], &sin->sin_addr, port);
+ } else {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *)tmpai->ai_addr;
+ isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr,
+ port);
+ }
+ i++;
+
+ }
+ freeaddrinfo(ai);
+ *addrcount = i;
+#else
+ he = gethostbyname(hostname);
+ if (he == NULL) {
+ switch (h_errno) {
+ case HOST_NOT_FOUND:
+#ifdef NO_DATA
+ case NO_DATA:
+#endif
+#if defined(NO_ADDRESS) && (!defined(NO_DATA) || (NO_DATA != NO_ADDRESS))
+ case NO_ADDRESS:
+#endif
+ return (ISC_R_NOTFOUND);
+ default:
+ return (ISC_R_FAILURE);
+ }
+ }
+ if (he->h_addrtype != AF_INET && he->h_addrtype != AF_INET6)
+ return (ISC_R_NOTFOUND);
+ for (i = 0; i < addrsize; i++) {
+ if (he->h_addrtype == AF_INET) {
+ struct in_addr *inp;
+ inp = (struct in_addr *)(he->h_addr_list[i]);
+ if (inp == NULL)
+ break;
+ isc_sockaddr_fromin(&addrs[i], inp, port);
+ } else {
+ struct in6_addr *in6p;
+ in6p = (struct in6_addr *)(he->h_addr_list[i]);
+ if (in6p == NULL)
+ break;
+ isc_sockaddr_fromin6(&addrs[i], in6p, port);
+ }
+ }
+ *addrcount = i;
+#endif
+ if (*addrcount == 0)
+ return (ISC_R_NOTFOUND);
+ else
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/bind9/include/Makefile.in b/lib/bind9/include/Makefile.in
new file mode 100644
index 0000000..65eecb0
--- /dev/null
+++ b/lib/bind9/include/Makefile.in
@@ -0,0 +1,25 @@
+# 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.4 2007/06/19 23:47:16 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = bind9
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/bind9/include/bind9/Makefile.in b/lib/bind9/include/bind9/Makefile.in
new file mode 100644
index 0000000..8abfaf6
--- /dev/null
+++ b/lib/bind9/include/bind9/Makefile.in
@@ -0,0 +1,42 @@
+# 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.8 2007/06/19 23:47:16 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @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 = check.h getaddresses.h version.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/bind9
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/bind9 ; \
+ done
diff --git a/lib/bind9/include/bind9/check.h b/lib/bind9/include/bind9/check.h
new file mode 100644
index 0000000..1647568
--- /dev/null
+++ b/lib/bind9/include/bind9/check.h
@@ -0,0 +1,57 @@
+/*
+ * 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: check.h,v 1.9 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef BIND9_CHECK_H
+#define BIND9_CHECK_H 1
+
+/*! \file bind9/check.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <isccfg/cfg.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
+ isc_mem_t *mctx);
+/*%<
+ * Check the syntactic validity of a configuration parse tree generated from
+ * a named.conf file.
+ *
+ * Requires:
+ *\li config is a valid parse tree
+ *
+ *\li logctx is a valid logging context.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_FAILURE
+ */
+
+isc_result_t
+bind9_check_key(const cfg_obj_t *config, isc_log_t *logctx);
+/*%<
+ * Same as bind9_check_namedconf(), but for a single 'key' statement.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* BIND9_CHECK_H */
diff --git a/lib/bind9/include/bind9/getaddresses.h b/lib/bind9/include/bind9/getaddresses.h
new file mode 100644
index 0000000..360e262
--- /dev/null
+++ b/lib/bind9/include/bind9/getaddresses.h
@@ -0,0 +1,61 @@
+/*
+ * 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: getaddresses.h,v 1.9 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef BIND9_GETADDRESSES_H
+#define BIND9_GETADDRESSES_H 1
+
+/*! \file bind9/getaddresses.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <isc/net.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+bind9_getaddresses(const char *hostname, in_port_t port,
+ isc_sockaddr_t *addrs, int addrsize, int *addrcount);
+/*%<
+ * Use the system resolver to get the addresses associated with a hostname.
+ * If successful, the number of addresses found is returned in 'addrcount'.
+ * If a hostname lookup is performed and addresses of an unknown family is
+ * seen, it is ignored. If more than 'addrsize' addresses are seen, the
+ * first 'addrsize' are returned and the remainder silently truncated.
+ *
+ * This routine may block. If called by a program using the isc_app
+ * framework, it should be surounded by isc_app_block()/isc_app_unblock().
+ *
+ * Requires:
+ *\li 'hostname' is not NULL.
+ *\li 'addrs' is not NULL.
+ *\li 'addrsize' > 0
+ *\li 'addrcount' is not NULL.
+ *
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOTFOUND
+ *\li #ISC_R_NOFAMILYSUPPORT - 'hostname' is an IPv6 address, and IPv6 is
+ * not supported.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* BIND9_GETADDRESSES_H */
diff --git a/lib/bind9/include/bind9/version.h b/lib/bind9/include/bind9/version.h
new file mode 100644
index 0000000..5b08b7c
--- /dev/null
+++ b/lib/bind9/include/bind9/version.h
@@ -0,0 +1,28 @@
+/*
+ * 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: version.h,v 1.9 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file bind9/version.h */
+
+#include <isc/platform.h>
+
+LIBBIND9_EXTERNAL_DATA extern const char bind9_version[];
+
+LIBBIND9_EXTERNAL_DATA extern const unsigned int bind9_libinterface;
+LIBBIND9_EXTERNAL_DATA extern const unsigned int bind9_librevision;
+LIBBIND9_EXTERNAL_DATA extern const unsigned int bind9_libage;
diff --git a/lib/bind9/version.c b/lib/bind9/version.c
new file mode 100644
index 0000000..d5934cc
--- /dev/null
+++ b/lib/bind9/version.c
@@ -0,0 +1,28 @@
+/*
+ * 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: version.c,v 1.8 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <bind9/version.h>
+
+const char bind9_version[] = VERSION;
+
+const unsigned int bind9_libinterface = LIBINTERFACE;
+const unsigned int bind9_librevision = LIBREVISION;
+const unsigned int bind9_libage = LIBAGE;
diff --git a/lib/bind9/win32/DLLMain.c b/lib/bind9/win32/DLLMain.c
new file mode 100644
index 0000000..74d6e49
--- /dev/null
+++ b/lib/bind9/win32/DLLMain.c
@@ -0,0 +1,57 @@
+/*
+ * 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: DLLMain.c,v 1.4 2007/06/18 23:47:39 tbox Exp $ */
+
+#include <windows.h>
+#include <signal.h>
+
+/*
+ * Called when we enter the DLL
+ */
+__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason) {
+ /*
+ * The DLL is loading due to process
+ * initialization or a call to LoadLibrary.
+ */
+ case DLL_PROCESS_ATTACH:
+ break;
+
+ /* The attached process creates a new thread. */
+ case DLL_THREAD_ATTACH:
+ break;
+
+ /* The thread of the attached process terminates. */
+ case DLL_THREAD_DETACH:
+ break;
+
+ /*
+ * The DLL is unloading from a process due to
+ * process termination or a call to FreeLibrary.
+ */
+ case DLL_PROCESS_DETACH:
+ break;
+
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
diff --git a/lib/bind9/win32/libbind9.def b/lib/bind9/win32/libbind9.def
new file mode 100644
index 0000000..b9a14ad
--- /dev/null
+++ b/lib/bind9/win32/libbind9.def
@@ -0,0 +1,8 @@
+LIBRARY libbind9
+
+; Exported Functions
+EXPORTS
+bind9_check_namedconf
+bind9_check_key
+bind9_getaddresses
+
diff --git a/lib/bind9/win32/libbind9.dsp b/lib/bind9/win32/libbind9.dsp
new file mode 100644
index 0000000..312a3a8
--- /dev/null
+++ b/lib/bind9/win32/libbind9.dsp
@@ -0,0 +1,133 @@
+# Microsoft Developer Studio Project File - Name="libbind9" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libbind9 - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libbind9.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libbind9.mak" CFG="libbind9 - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libbind9 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libbind9 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libbind9 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "libbind9_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../lib/dns/win32/include" /I "../..../lib/dns/sec/openssl/include" /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /D "NDEBUG" /D "WIN32" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBBIND9_EXPORTS" /YX /FD /c
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../isc/win32/Release/libisc.lib ../../dns/win32/Release/libdns.lib ../../isccfg/win32/Release/libisccfg.lib /nologo /dll /machine:I386 /out:"../../../Build/Release/libbind9.dll"
+
+!ELSEIF "$(CFG)" == "libbind9 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "libbind9_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../../lib/isccfg/include" /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBBIND9_EXPORTS" /FR /YX /FD /GZ /c
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../isc/win32/debug/libisc.lib ../../dns/win32/debug/libdns.lib ../../isccfg/win32/debug/libisccfg.lib /nologo /dll /debug /machine:I386 /out:"../../../Build/Debug/libbind9.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "libbind9 - Win32 Release"
+# Name "libbind9 - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\check.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\DLLMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\getaddresses.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\bind9\check.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\bind9\version.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=.\libbind9.def
+# End Source File
+# End Target
+# End Project
diff --git a/lib/bind9/win32/libbind9.dsw b/lib/bind9/win32/libbind9.dsw
new file mode 100644
index 0000000..0810982
--- /dev/null
+++ b/lib/bind9/win32/libbind9.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libbind9"=.\libbind9.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/bind9/win32/libbind9.mak b/lib/bind9/win32/libbind9.mak
new file mode 100644
index 0000000..1a76230
--- /dev/null
+++ b/lib/bind9/win32/libbind9.mak
@@ -0,0 +1,452 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on libbind9.dsp
+!IF "$(CFG)" == ""
+CFG=libbind9 - Win32 Release
+!MESSAGE No configuration specified. Defaulting to libbind9 - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "libbind9 - Win32 Release" && "$(CFG)" != "libbind9 - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libbind9.mak" CFG="libbind9 - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libbind9 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libbind9 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libbind9 - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "libbind9 - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\libbind9.dll"
+
+!ELSE
+
+ALL : "libisccfg - Win32 Release" "libisc - Win32 Release" "libdns - Win32 Release" "..\..\..\Build\Release\libbind9.dll"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN" "libisccfg - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\check.obj"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\getaddresses.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(OUTDIR)\libbind9.exp"
+ -@erase "$(OUTDIR)\libbind9.lib"
+ -@erase "..\..\..\Build\Release\libbind9.dll"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "../../../lib/dns/win32/include" /I "../..../lib/dns/sec/openssl/include" /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /D "NDEBUG" /D "WIN32" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBBIND9_EXPORTS" /Fp"$(INTDIR)\libbind9.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libbind9.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../isc/win32/Release/libisc.lib ../../dns/win32/Release/libdns.lib ../../isccfg/win32/Release/libisccfg.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libbind9.pdb" /machine:I386 /def:".\libbind9.def" /out:"../../../Build/Release/libbind9.dll" /implib:"$(OUTDIR)\libbind9.lib"
+DEF_FILE= \
+ ".\libbind9.def"
+LINK32_OBJS= \
+ "$(INTDIR)\check.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\getaddresses.obj" \
+ "$(INTDIR)\version.obj" \
+ "..\..\dns\win32\Release\libdns.lib" \
+ "..\..\isc\win32\Release\libisc.lib" \
+ "..\..\isccfg\win32\Release\libisccfg.lib"
+
+"..\..\..\Build\Release\libbind9.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ELSEIF "$(CFG)" == "libbind9 - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\libbind9.dll" "$(OUTDIR)\libbind9.bsc"
+
+!ELSE
+
+ALL : "libisccfg - Win32 Debug" "libisc - Win32 Debug" "libdns - Win32 Debug" "..\..\..\Build\Debug\libbind9.dll" "$(OUTDIR)\libbind9.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 DebugCLEAN" "libisc - Win32 DebugCLEAN" "libisccfg - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\check.obj"
+ -@erase "$(INTDIR)\check.sbr"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\DLLMain.sbr"
+ -@erase "$(INTDIR)\getaddresses.obj"
+ -@erase "$(INTDIR)\getaddresses.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(INTDIR)\version.sbr"
+ -@erase "$(OUTDIR)\libbind9.bsc"
+ -@erase "$(OUTDIR)\libbind9.exp"
+ -@erase "$(OUTDIR)\libbind9.lib"
+ -@erase "$(OUTDIR)\libbind9.pdb"
+ -@erase "..\..\..\Build\Debug\libbind9.dll"
+ -@erase "..\..\..\Build\Debug\libbind9.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../../lib/isccfg/include" /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBBIND9_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libbind9.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libbind9.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\check.sbr" \
+ "$(INTDIR)\DLLMain.sbr" \
+ "$(INTDIR)\getaddresses.sbr" \
+ "$(INTDIR)\version.sbr"
+
+"$(OUTDIR)\libbind9.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../isc/win32/debug/libisc.lib ../../dns/win32/debug/libdns.lib ../../isccfg/win32/debug/libisccfg.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libbind9.pdb" /debug /machine:I386 /def:".\libbind9.def" /out:"../../../Build/Debug/libbind9.dll" /implib:"$(OUTDIR)\libbind9.lib" /pdbtype:sept
+DEF_FILE= \
+ ".\libbind9.def"
+LINK32_OBJS= \
+ "$(INTDIR)\check.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\getaddresses.obj" \
+ "$(INTDIR)\version.obj" \
+ "..\..\dns\win32\Debug\libdns.lib" \
+ "..\..\isc\win32\Debug\libisc.lib" \
+ "..\..\isccfg\win32\Debug\libisccfg.lib"
+
+"..\..\..\Build\Debug\libbind9.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("libbind9.dep")
+!INCLUDE "libbind9.dep"
+!ELSE
+!MESSAGE Warning: cannot find "libbind9.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "libbind9 - Win32 Release" || "$(CFG)" == "libbind9 - Win32 Debug"
+SOURCE=..\check.c
+
+!IF "$(CFG)" == "libbind9 - Win32 Release"
+
+
+"$(INTDIR)\check.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libbind9 - Win32 Debug"
+
+
+"$(INTDIR)\check.obj" "$(INTDIR)\check.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\DLLMain.c
+
+!IF "$(CFG)" == "libbind9 - Win32 Release"
+
+
+"$(INTDIR)\DLLMain.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libbind9 - Win32 Debug"
+
+
+"$(INTDIR)\DLLMain.obj" "$(INTDIR)\DLLMain.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\getaddresses.c
+
+!IF "$(CFG)" == "libbind9 - Win32 Release"
+
+
+"$(INTDIR)\getaddresses.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libbind9 - Win32 Debug"
+
+
+"$(INTDIR)\getaddresses.obj" "$(INTDIR)\getaddresses.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\version.c
+
+!IF "$(CFG)" == "libbind9 - Win32 Release"
+
+
+"$(INTDIR)\version.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libbind9 - Win32 Debug"
+
+
+"$(INTDIR)\version.obj" "$(INTDIR)\version.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+!IF "$(CFG)" == "libbind9 - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\bind9\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\bind9\win32"
+
+!ELSEIF "$(CFG)" == "libbind9 - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\bind9\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\bind9\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "libbind9 - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\bind9\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\bind9\win32"
+
+!ELSEIF "$(CFG)" == "libbind9 - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\bind9\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\bind9\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "libbind9 - Win32 Release"
+
+"libisccfg - Win32 Release" :
+ cd "..\..\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Release"
+ cd "..\..\bind9\win32"
+
+"libisccfg - Win32 ReleaseCLEAN" :
+ cd "..\..\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\bind9\win32"
+
+!ELSEIF "$(CFG)" == "libbind9 - Win32 Debug"
+
+"libisccfg - Win32 Debug" :
+ cd "..\..\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Debug"
+ cd "..\..\bind9\win32"
+
+"libisccfg - Win32 DebugCLEAN" :
+ cd "..\..\isccfg\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisccfg.mak" CFG="libisccfg - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\bind9\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/lib/bind9/win32/version.c b/lib/bind9/win32/version.c
new file mode 100644
index 0000000..30d5911
--- /dev/null
+++ b/lib/bind9/win32/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: version.c,v 1.5 2007/06/19 23:47:16 tbox Exp $ */
+
+#include <versions.h>
+
+#include <bind9/version.h>
+
+LIBBIND9_EXTERNAL_DATA const char bind9_version[] = VERSION;
+
+LIBBIND9_EXTERNAL_DATA const unsigned int bind9_libinterface = LIBINTERFACE;
+LIBBIND9_EXTERNAL_DATA const unsigned int bind9_librevision = LIBREVISION;
+LIBBIND9_EXTERNAL_DATA const unsigned int bind9_libage = LIBAGE;
diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in
new file mode 100644
index 0000000..ef5c12a
--- /dev/null
+++ b/lib/dns/Makefile.in
@@ -0,0 +1,179 @@
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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: Makefile.in,v 1.163 2008/09/24 02:46:22 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+# Attempt to disable parallel processing.
+.NOTPARALLEL:
+.NO_PARALLEL:
+
+@BIND9_VERSION@
+
+@LIBDNS_API@
+
+@BIND9_MAKE_INCLUDES@
+
+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}
+
+CWARNINGS =
+
+ISCLIBS = ../../lib/isc/libisc.@A@
+
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+
+LIBS = @LIBS@
+
+# Alphabetically
+
+DSTOBJS = @DST_EXTRA_OBJS@ \
+ dst_api.@O@ dst_lib.@O@ dst_parse.@O@ dst_result.@O@ \
+ gssapi_link.@O@ gssapictx.@O@ hmac_link.@O@ key.@O@ \
+ openssl_link.@O@ openssldh_link.@O@ openssldsa_link.@O@ \
+ opensslrsa_link.@O@
+
+# Alphabetically
+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@ \
+ master.@O@ masterdump.@O@ message.@O@ \
+ name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ order.@O@ peer.@O@ portlist.@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@ \
+ stats.@O@ tcpmsg.@O@ time.@O@ timer.@O@ tkey.@O@ \
+ tsig.@O@ ttl.@O@ validator.@O@ \
+ version.@O@ view.@O@ xfrin.@O@ zone.@O@ zonekey.@O@ zt.@O@
+
+OBJS= ${DNSOBJS} ${OTHEROBJS} ${DSTOBJS}
+
+# Alphabetically
+DSTSRCS = @DST_EXTRA_SRCS@ \
+ dst_api.c dst_lib.c dst_parse.c \
+ dst_result.c gssapi_link.c gssapictx.c \
+ hmac_link.c key.c \
+ openssl_link.c openssldh_link.c \
+ openssldsa_link.c opensslrsa_link.c
+
+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 \
+ 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 \
+ rdataset.c rdatasetiter.c rdataslab.c request.c \
+ resolver.c result.c rootns.c sdb.c sdlz.c \
+ soa.c ssu.c \
+ stats.c tcpmsg.c time.c timer.c tkey.c \
+ tsig.c ttl.c validator.c \
+ version.c view.c xfrin.c zone.c zonekey.c zt.c ${OTHERSRCS}
+SRCS = ${DSTSRCS} ${DNSSRCS}
+
+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@: 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 ${libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${ISCLIBS} @DNS_CRYPTO_LIBS@ ${LIBS}
+
+timestamp: libdns.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libdns.@A@ ${DESTDIR}${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: gen.c
+ ${BUILD_CC} ${BUILD_CFLAGS} -I${top_srcdir}/lib/isc/include \
+ ${BUILD_CPPFLAGS} ${BUILD_LDFLAGS} -o $@ ${srcdir}/gen.c ${BUILD_LIBS}
+
+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
+
+spnego.@O@: spnego_asn1.c spnego.h
diff --git a/lib/dns/acache.c b/lib/dns/acache.c
new file mode 100644
index 0000000..2ad4981
--- /dev/null
+++ b/lib/dns/acache.c
@@ -0,0 +1,1782 @@
+/*
+ * Copyright (C) 2004-2008 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: acache.c,v 1.22 2008/02/07 23:46:54 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/atomic.h>
+#include <isc/event.h>
+#include <isc/hash.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/random.h>
+#include <isc/refcount.h>
+#include <isc/rwlock.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+
+#include <dns/acache.h>
+#include <dns/db.h>
+#include <dns/events.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+#include <dns/zone.h>
+
+#define ACACHE_MAGIC ISC_MAGIC('A', 'C', 'H', 'E')
+#define DNS_ACACHE_VALID(acache) ISC_MAGIC_VALID(acache, ACACHE_MAGIC)
+
+#define ACACHEENTRY_MAGIC ISC_MAGIC('A', 'C', 'E', 'T')
+#define DNS_ACACHEENTRY_VALID(entry) ISC_MAGIC_VALID(entry, ACACHEENTRY_MAGIC)
+
+#define DBBUCKETS 67
+
+#if 0
+#define ATRACE(m) isc_log_write(dns_lctx, \
+ DNS_LOGCATEGORY_DATABASE, \
+ DNS_LOGMODULE_ACACHE, \
+ ISC_LOG_DEBUG(3), \
+ "acache %p: %s", acache, (m))
+#define AATRACE(a,m) isc_log_write(dns_lctx, \
+ DNS_LOGCATEGORY_DATABASE, \
+ DNS_LOGMODULE_ACACHE, \
+ ISC_LOG_DEBUG(3), \
+ "acache %p: %s", (a), (m))
+#else
+#define ATRACE(m)
+#define AATRACE(a, m)
+#endif
+
+/*
+ * The following variables control incremental cleaning.
+ * MINSIZE is how many bytes is the floor for dns_acache_setcachesize().
+ * CLEANERINCREMENT is how many entries are examined in one pass.
+ * (XXX simply derived from definitions in cache.c There may be better
+ * constants here.)
+ */
+#define DNS_ACACHE_MINSIZE 2097152 /* Bytes. 2097152 = 2 MB */
+#define DNS_ACACHE_CLEANERINCREMENT 1000 /* Number of entries. */
+
+#define DEFAULT_ACACHE_ENTRY_LOCK_COUNT 1009 /*%< Should be prime. */
+
+#if defined(ISC_RWLOCK_USEATOMIC) && defined(ISC_PLATFORM_HAVEATOMICSTORE)
+#define ACACHE_USE_RWLOCK 1
+#endif
+
+#ifdef ACACHE_USE_RWLOCK
+#define ACACHE_INITLOCK(l) isc_rwlock_init((l), 0, 0)
+#define ACACHE_DESTROYLOCK(l) isc_rwlock_destroy(l)
+#define ACACHE_LOCK(l, t) RWLOCK((l), (t))
+#define ACACHE_UNLOCK(l, t) RWUNLOCK((l), (t))
+
+#define acache_storetime(entry, t) \
+ (isc_atomic_store((isc_int32_t *)&(entry)->lastused, (t)))
+#else
+#define ACACHE_INITLOCK(l) isc_mutex_init(l)
+#define ACACHE_DESTROYLOCK(l) DESTROYLOCK(l)
+#define ACACHE_LOCK(l, t) LOCK(l)
+#define ACACHE_UNLOCK(l, t) UNLOCK(l)
+
+#define acache_storetime(entry, t) ((entry)->lastused = (t))
+#endif
+
+/* Locked by acache lock */
+typedef struct dbentry {
+ ISC_LINK(struct dbentry) link;
+
+ dns_db_t *db;
+ ISC_LIST(dns_acacheentry_t) originlist;
+ ISC_LIST(dns_acacheentry_t) referlist;
+} dbentry_t;
+
+typedef ISC_LIST(dbentry_t) dbentrylist_t;
+
+typedef struct acache_cleaner acache_cleaner_t;
+
+typedef enum {
+ cleaner_s_idle, /* Waiting for cleaning-interval to expire. */
+ cleaner_s_busy, /* Currently cleaning. */
+ cleaner_s_done /* Freed enough memory after being overmem. */
+} cleaner_state_t;
+
+/*
+ * Convenience macros for comprehensive assertion checking.
+ */
+#define CLEANER_IDLE(c) ((c)->state == cleaner_s_idle && \
+ (c)->resched_event != NULL)
+#define CLEANER_BUSY(c) ((c)->state == cleaner_s_busy && \
+ (c)->resched_event == NULL)
+
+struct acache_cleaner {
+ isc_mutex_t lock;
+ /*
+ * Locks overmem_event, overmem. (See cache.c)
+ */
+
+ dns_acache_t *acache;
+ unsigned int cleaning_interval; /* The cleaning-interval
+ from named.conf,
+ in seconds. */
+
+ isc_stdtime_t last_cleanup_time; /* The time when the last
+ cleanup task completed */
+
+ isc_timer_t *cleaning_timer;
+ isc_event_t *resched_event; /* Sent by cleaner task to
+ itself to reschedule */
+ isc_event_t *overmem_event;
+
+ dns_acacheentry_t *current_entry; /* The bookmark entry to
+ restart the cleaning.
+ Locked by acache lock. */
+ int increment; /* Number of entries to
+ clean in one increment */
+
+ unsigned long ncleaned; /* Number of entries cleaned
+ up (for logging purposes) */
+ cleaner_state_t state; /* Idle/Busy/Done. */
+ isc_boolean_t overmem; /* The acache is in an overmem
+ state. */
+};
+
+struct dns_acachestats {
+ unsigned int hits;
+ unsigned int queries;
+ unsigned int misses;
+ unsigned int adds;
+ unsigned int deleted;
+ unsigned int cleaned;
+ unsigned int cleaner_runs;
+ unsigned int overmem;
+ unsigned int overmem_nocreates;
+ unsigned int nomem;
+};
+
+/*
+ * The actual acache object.
+ */
+
+struct dns_acache {
+ unsigned int magic;
+
+ isc_mem_t *mctx;
+ isc_refcount_t refs;
+
+#ifdef ACACHE_USE_RWLOCK
+ isc_rwlock_t *entrylocks;
+#else
+ isc_mutex_t *entrylocks;
+#endif
+
+ isc_mutex_t lock;
+
+ int live_cleaners;
+ acache_cleaner_t cleaner;
+ ISC_LIST(dns_acacheentry_t) entries;
+ unsigned int dbentries;
+ dbentrylist_t dbbucket[DBBUCKETS];
+
+ isc_boolean_t shutting_down;
+
+ isc_task_t *task;
+ isc_event_t cevent;
+ isc_boolean_t cevent_sent;
+
+ dns_acachestats_t stats;
+};
+
+struct dns_acacheentry {
+ unsigned int magic;
+
+ unsigned int locknum;
+ isc_refcount_t references;
+
+ dns_acache_t *acache;
+
+ /* Data for Management of cache entries */
+ ISC_LINK(dns_acacheentry_t) link;
+ ISC_LINK(dns_acacheentry_t) olink;
+ ISC_LINK(dns_acacheentry_t) rlink;
+
+ dns_db_t *origdb; /* reference to the DB
+ holding this entry */
+
+ /* Cache data */
+ dns_zone_t *zone; /* zone this entry
+ belongs to */
+ dns_db_t *db; /* DB this entry belongs to */
+ dns_dbversion_t *version; /* the version of the DB */
+ dns_dbnode_t *node; /* node this entry
+ belongs to */
+ dns_name_t *foundname; /* corresponding DNS name
+ and rdataset */
+
+ /* Callback function and its argument */
+ void (*callback)(dns_acacheentry_t *, void **);
+ void *cbarg;
+
+ /* Timestamp of the last time this entry is referred to */
+ isc_stdtime32_t lastused;
+};
+
+/*
+ * Internal functions (and prototypes).
+ */
+static inline isc_boolean_t check_noentry(dns_acache_t *acache);
+static void destroy(dns_acache_t *acache);
+static void shutdown_entries(dns_acache_t *acache);
+static void shutdown_buckets(dns_acache_t *acache);
+static void destroy_entry(dns_acacheentry_t *ent);
+static inline void unlink_dbentries(dns_acache_t *acache,
+ dns_acacheentry_t *ent);
+static inline isc_result_t finddbent(dns_acache_t *acache,
+ dns_db_t *db, dbentry_t **dbentryp);
+static inline void clear_entry(dns_acache_t *acache, dns_acacheentry_t *entry);
+static isc_result_t acache_cleaner_init(dns_acache_t *acache,
+ isc_timermgr_t *timermgr,
+ acache_cleaner_t *cleaner);
+static void acache_cleaning_timer_action(isc_task_t *task, isc_event_t *event);
+static void acache_incremental_cleaning_action(isc_task_t *task,
+ isc_event_t *event);
+static void acache_overmem_cleaning_action(isc_task_t *task,
+ isc_event_t *event);
+static void acache_cleaner_shutdown_action(isc_task_t *task,
+ isc_event_t *event);
+
+/*
+ * acache should be locked. If it is not, the stats can get out of whack,
+ * which is not a big deal for us since this is for debugging / stats
+ */
+static void
+reset_stats(dns_acache_t *acache) {
+ acache->stats.hits = 0;
+ acache->stats.queries = 0;
+ acache->stats.misses = 0;
+ acache->stats.adds = 0;
+ acache->stats.deleted = 0;
+ acache->stats.cleaned = 0;
+ acache->stats.overmem = 0;
+ acache->stats.overmem_nocreates = 0;
+ acache->stats.nomem = 0;
+}
+
+/*
+ * The acache must be locked before calling.
+ */
+static inline isc_boolean_t
+check_noentry(dns_acache_t *acache) {
+ if (ISC_LIST_EMPTY(acache->entries) && acache->dbentries == 0) {
+ return (ISC_TRUE);
+ }
+
+ return (ISC_FALSE);
+}
+
+/*
+ * The acache must be locked before calling.
+ */
+static void
+shutdown_entries(dns_acache_t *acache) {
+ dns_acacheentry_t *entry, *entry_next;
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+ INSIST(acache->shutting_down);
+
+ /*
+ * Release the dependency of all entries, and detach them.
+ */
+ for (entry = ISC_LIST_HEAD(acache->entries);
+ entry != NULL;
+ entry = entry_next) {
+ entry_next = ISC_LIST_NEXT(entry, link);
+
+ ACACHE_LOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+
+ /*
+ * If the cleaner holds this entry, it will be unlinked and
+ * freed in the cleaner later.
+ */
+ if (acache->cleaner.current_entry != entry)
+ ISC_LIST_UNLINK(acache->entries, entry, link);
+ unlink_dbentries(acache, entry);
+ if (entry->callback != NULL) {
+ (entry->callback)(entry, &entry->cbarg);
+ entry->callback = NULL;
+ }
+
+ ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+
+ if (acache->cleaner.current_entry != entry)
+ dns_acache_detachentry(&entry);
+ }
+}
+
+/*
+ * The acache must be locked before calling.
+ */
+static void
+shutdown_buckets(dns_acache_t *acache) {
+ int i;
+ dbentry_t *dbent;
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+ INSIST(acache->shutting_down);
+
+ for (i = 0; i < DBBUCKETS; i++) {
+ while ((dbent = ISC_LIST_HEAD(acache->dbbucket[i])) != NULL) {
+ INSIST(ISC_LIST_EMPTY(dbent->originlist) &&
+ ISC_LIST_EMPTY(dbent->referlist));
+ ISC_LIST_UNLINK(acache->dbbucket[i], dbent, link);
+
+ dns_db_detach(&dbent->db);
+
+ isc_mem_put(acache->mctx, dbent, sizeof(*dbent));
+
+ acache->dbentries--;
+ }
+ }
+
+ INSIST(acache->dbentries == 0);
+}
+
+static void
+shutdown_task(isc_task_t *task, isc_event_t *ev) {
+ dns_acache_t *acache;
+
+ UNUSED(task);
+
+ acache = ev->ev_arg;
+ INSIST(DNS_ACACHE_VALID(acache));
+
+ isc_event_free(&ev);
+
+ LOCK(&acache->lock);
+
+ shutdown_entries(acache);
+ shutdown_buckets(acache);
+
+ UNLOCK(&acache->lock);
+
+ dns_acache_detach(&acache);
+}
+
+/* The acache and the entry must be locked before calling. */
+static inline void
+unlink_dbentries(dns_acache_t *acache, dns_acacheentry_t *ent) {
+ isc_result_t result;
+ dbentry_t *dbent;
+
+ if (ISC_LINK_LINKED(ent, olink)) {
+ INSIST(ent->origdb != NULL);
+ dbent = NULL;
+ result = finddbent(acache, ent->origdb, &dbent);
+ INSIST(result == ISC_R_SUCCESS);
+
+ ISC_LIST_UNLINK(dbent->originlist, ent, olink);
+ }
+ if (ISC_LINK_LINKED(ent, rlink)) {
+ INSIST(ent->db != NULL);
+ dbent = NULL;
+ result = finddbent(acache, ent->db, &dbent);
+ INSIST(result == ISC_R_SUCCESS);
+
+ ISC_LIST_UNLINK(dbent->referlist, ent, rlink);
+ }
+}
+
+/* There must not be a reference to this entry. */
+static void
+destroy_entry(dns_acacheentry_t *entry) {
+ dns_acache_t *acache;
+
+ REQUIRE(DNS_ACACHEENTRY_VALID(entry));
+
+ acache = entry->acache;
+ REQUIRE(DNS_ACACHE_VALID(acache));
+
+ /*
+ * Since there is no reference to this entry, it is safe to call
+ * clear_entry() here.
+ */
+ clear_entry(acache, entry);
+
+ isc_mem_put(acache->mctx, entry, sizeof(*entry));
+
+ dns_acache_detach(&acache);
+}
+
+static void
+destroy(dns_acache_t *acache) {
+ int i;
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+
+ ATRACE("destroy");
+
+ isc_mem_setwater(acache->mctx, NULL, NULL, 0, 0);
+
+ if (acache->cleaner.overmem_event != NULL)
+ isc_event_free(&acache->cleaner.overmem_event);
+
+ if (acache->cleaner.resched_event != NULL)
+ isc_event_free(&acache->cleaner.resched_event);
+
+ if (acache->task != NULL)
+ isc_task_detach(&acache->task);
+
+ for (i = 0; i < DEFAULT_ACACHE_ENTRY_LOCK_COUNT; i++)
+ ACACHE_DESTROYLOCK(&acache->entrylocks[i]);
+ isc_mem_put(acache->mctx, acache->entrylocks,
+ sizeof(*acache->entrylocks) *
+ DEFAULT_ACACHE_ENTRY_LOCK_COUNT);
+
+ DESTROYLOCK(&acache->cleaner.lock);
+
+ DESTROYLOCK(&acache->lock);
+ acache->magic = 0;
+
+ isc_mem_putanddetach(&acache->mctx, acache, sizeof(*acache));
+}
+
+static inline isc_result_t
+finddbent(dns_acache_t *acache, dns_db_t *db, dbentry_t **dbentryp) {
+ int bucket;
+ dbentry_t *dbentry;
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+ REQUIRE(db != NULL);
+ REQUIRE(dbentryp != NULL && *dbentryp == NULL);
+
+ /*
+ * The caller must be holding the acache lock.
+ */
+
+ bucket = isc_hash_calc((const unsigned char *)&db,
+ sizeof(db), ISC_TRUE) % DBBUCKETS;
+
+ for (dbentry = ISC_LIST_HEAD(acache->dbbucket[bucket]);
+ dbentry != NULL;
+ dbentry = ISC_LIST_NEXT(dbentry, link)) {
+ if (dbentry->db == db)
+ break;
+ }
+
+ *dbentryp = dbentry;
+
+ if (dbentry == NULL)
+ return (ISC_R_NOTFOUND);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+clear_entry(dns_acache_t *acache, dns_acacheentry_t *entry) {
+ REQUIRE(DNS_ACACHE_VALID(acache));
+ REQUIRE(DNS_ACACHEENTRY_VALID(entry));
+
+ /*
+ * The caller must be holing the entry lock.
+ */
+
+ if (entry->foundname) {
+ dns_rdataset_t *rdataset, *rdataset_next;
+
+ for (rdataset = ISC_LIST_HEAD(entry->foundname->list);
+ rdataset != NULL;
+ rdataset = rdataset_next) {
+ rdataset_next = ISC_LIST_NEXT(rdataset, link);
+ ISC_LIST_UNLINK(entry->foundname->list,
+ rdataset, link);
+ dns_rdataset_disassociate(rdataset);
+ isc_mem_put(acache->mctx, rdataset, sizeof(*rdataset));
+ }
+ if (dns_name_dynamic(entry->foundname))
+ dns_name_free(entry->foundname, acache->mctx);
+ isc_mem_put(acache->mctx, entry->foundname,
+ sizeof(*entry->foundname));
+ entry->foundname = NULL;
+ }
+
+ if (entry->node != NULL) {
+ INSIST(entry->db != NULL);
+ dns_db_detachnode(entry->db, &entry->node);
+ }
+ if (entry->version != NULL) {
+ INSIST(entry->db != NULL);
+ dns_db_closeversion(entry->db, &entry->version, ISC_FALSE);
+ }
+ if (entry->db != NULL)
+ dns_db_detach(&entry->db);
+ if (entry->zone != NULL)
+ dns_zone_detach(&entry->zone);
+
+ if (entry->origdb != NULL)
+ dns_db_detach(&entry->origdb);
+}
+
+static isc_result_t
+acache_cleaner_init(dns_acache_t *acache, isc_timermgr_t *timermgr,
+ acache_cleaner_t *cleaner)
+{
+ int result;
+
+ ATRACE("acache cleaner init");
+
+ result = isc_mutex_init(&cleaner->lock);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ cleaner->increment = DNS_ACACHE_CLEANERINCREMENT;
+ cleaner->state = cleaner_s_idle;
+ cleaner->acache = acache;
+ cleaner->overmem = ISC_FALSE;
+
+ cleaner->cleaning_timer = NULL;
+ cleaner->resched_event = NULL;
+ cleaner->overmem_event = NULL;
+ cleaner->current_entry = NULL;
+
+ if (timermgr != NULL) {
+ cleaner->acache->live_cleaners++;
+
+ result = isc_task_onshutdown(acache->task,
+ acache_cleaner_shutdown_action,
+ acache);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "acache cleaner: "
+ "isc_task_onshutdown() failed: %s",
+ dns_result_totext(result));
+ goto cleanup;
+ }
+
+ cleaner->cleaning_interval = 0; /* Initially turned off. */
+ isc_stdtime_get(&cleaner->last_cleanup_time);
+ result = isc_timer_create(timermgr, isc_timertype_inactive,
+ NULL, NULL,
+ acache->task,
+ acache_cleaning_timer_action,
+ cleaner, &cleaner->cleaning_timer);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_timer_create() failed: %s",
+ dns_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+ cleaner->resched_event =
+ isc_event_allocate(acache->mctx, cleaner,
+ DNS_EVENT_ACACHECLEAN,
+ acache_incremental_cleaning_action,
+ cleaner, sizeof(isc_event_t));
+ if (cleaner->resched_event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ cleaner->overmem_event =
+ isc_event_allocate(acache->mctx, cleaner,
+ DNS_EVENT_ACACHEOVERMEM,
+ acache_overmem_cleaning_action,
+ cleaner, sizeof(isc_event_t));
+ if (cleaner->overmem_event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (cleaner->overmem_event != NULL)
+ isc_event_free(&cleaner->overmem_event);
+ if (cleaner->resched_event != NULL)
+ isc_event_free(&cleaner->resched_event);
+ if (cleaner->cleaning_timer != NULL)
+ isc_timer_detach(&cleaner->cleaning_timer);
+ cleaner->acache->live_cleaners--;
+ DESTROYLOCK(&cleaner->lock);
+ fail:
+ return (result);
+}
+
+static void
+begin_cleaning(acache_cleaner_t *cleaner) {
+ dns_acacheentry_t *head;
+ dns_acache_t *acache = cleaner->acache;
+
+ /*
+ * This function does not have to lock the cleaner, since critical
+ * parameters (except current_entry, which is locked by acache lock,)
+ * are only used in a single task context.
+ */
+
+ REQUIRE(CLEANER_IDLE(cleaner));
+ INSIST(DNS_ACACHE_VALID(acache));
+ INSIST(cleaner->current_entry == NULL);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_ACACHE, ISC_LOG_DEBUG(1),
+ "begin acache cleaning, mem inuse %lu",
+ (unsigned long)isc_mem_inuse(cleaner->acache->mctx));
+
+ LOCK(&acache->lock);
+
+ head = ISC_LIST_HEAD(acache->entries);
+ if (head != NULL)
+ dns_acache_attachentry(head, &cleaner->current_entry);
+
+ UNLOCK(&acache->lock);
+
+ if (cleaner->current_entry != NULL) {
+ cleaner->ncleaned = 0;
+ cleaner->state = cleaner_s_busy;
+ isc_task_send(acache->task, &cleaner->resched_event);
+ }
+
+ return;
+}
+
+static void
+end_cleaning(acache_cleaner_t *cleaner, isc_event_t *event) {
+ dns_acache_t *acache = cleaner->acache;
+
+ REQUIRE(CLEANER_BUSY(cleaner));
+ REQUIRE(event != NULL);
+ REQUIRE(DNS_ACACHEENTRY_VALID(cleaner->current_entry));
+
+ /* No need to lock the cleaner (see begin_cleaning()). */
+
+ LOCK(&acache->lock);
+
+ /*
+ * Even if the cleaner has the last reference to the entry, which means
+ * the entry has been unused, it may still be linked if unlinking the
+ * entry has been delayed due to the reference.
+ */
+ if (isc_refcount_current(&cleaner->current_entry->references) == 1) {
+ INSIST(cleaner->current_entry->callback == NULL);
+
+ if (ISC_LINK_LINKED(cleaner->current_entry, link)) {
+ ISC_LIST_UNLINK(acache->entries,
+ cleaner->current_entry, link);
+ }
+ }
+ dns_acache_detachentry(&cleaner->current_entry);
+
+ if (cleaner->overmem)
+ acache->stats.overmem++;
+ acache->stats.cleaned += cleaner->ncleaned;
+ acache->stats.cleaner_runs++;
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE,
+ ISC_LOG_NOTICE,
+ "acache %p stats: hits=%d misses=%d queries=%d "
+ "adds=%d deleted=%d "
+ "cleaned=%d cleaner_runs=%d overmem=%d "
+ "overmem_nocreates=%d nomem=%d",
+ acache,
+ acache->stats.hits, acache->stats.misses,
+ acache->stats.queries,
+ acache->stats.adds, acache->stats.deleted,
+ acache->stats.cleaned, acache->stats.cleaner_runs,
+ acache->stats.overmem, acache->stats.overmem_nocreates,
+ acache->stats.nomem);
+ reset_stats(acache);
+
+ isc_stdtime_get(&cleaner->last_cleanup_time);
+
+ UNLOCK(&acache->lock);
+
+ dns_acache_setcleaninginterval(cleaner->acache,
+ cleaner->cleaning_interval);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE,
+ ISC_LOG_DEBUG(1), "end acache cleaning, "
+ "%lu entries cleaned, mem inuse %lu",
+ cleaner->ncleaned,
+ (unsigned long)isc_mem_inuse(cleaner->acache->mctx));
+
+ if (cleaner->overmem) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_ACACHE, ISC_LOG_NOTICE,
+ "acache is still in overmem state "
+ "after cleaning");
+ }
+
+ cleaner->ncleaned = 0;
+ cleaner->state = cleaner_s_idle;
+ cleaner->resched_event = event;
+}
+
+/*
+ * This is run once for every acache-cleaning-interval as defined
+ * in named.conf.
+ */
+static void
+acache_cleaning_timer_action(isc_task_t *task, isc_event_t *event) {
+ acache_cleaner_t *cleaner = event->ev_arg;
+
+ UNUSED(task);
+
+ INSIST(event->ev_type == ISC_TIMEREVENT_TICK);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE,
+ ISC_LOG_DEBUG(1), "acache cleaning timer fired, "
+ "cleaner state = %d", cleaner->state);
+
+ if (cleaner->state == cleaner_s_idle)
+ begin_cleaning(cleaner);
+
+ isc_event_free(&event);
+}
+
+/* The caller must hold entry lock. */
+static inline isc_boolean_t
+entry_stale(acache_cleaner_t *cleaner, dns_acacheentry_t *entry,
+ isc_stdtime32_t now32, unsigned int interval)
+{
+ /*
+ * If the callback has been canceled, we definitely do not need the
+ * entry.
+ */
+ if (entry->callback == NULL)
+ return (ISC_TRUE);
+
+ if (interval > cleaner->cleaning_interval)
+ interval = cleaner->cleaning_interval;
+
+ if (entry->lastused + interval < now32)
+ return (ISC_TRUE);
+
+ /*
+ * If the acache is in the overmem state, probabilistically decide if
+ * the entry should be purged, based on the time passed from its last
+ * use and the cleaning interval.
+ */
+ if (cleaner->overmem) {
+ unsigned int passed =
+ now32 - entry->lastused; /* <= interval */
+ isc_uint32_t val;
+
+ if (passed > interval / 2)
+ return (ISC_TRUE);
+ isc_random_get(&val);
+ if (passed > interval / 4)
+ return (ISC_TF(val % 4 == 0));
+ return (ISC_TF(val % 8 == 0));
+ }
+
+ return (ISC_FALSE);
+}
+
+/*
+ * Do incremental cleaning.
+ */
+static void
+acache_incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
+ acache_cleaner_t *cleaner = event->ev_arg;
+ dns_acache_t *acache = cleaner->acache;
+ dns_acacheentry_t *entry, *next = NULL;
+ int n_entries;
+ isc_stdtime32_t now32, last32;
+ isc_stdtime_t now;
+ unsigned int interval;
+
+ INSIST(DNS_ACACHE_VALID(acache));
+ INSIST(task == acache->task);
+ INSIST(event->ev_type == DNS_EVENT_ACACHECLEAN);
+
+ if (cleaner->state == cleaner_s_done) {
+ cleaner->state = cleaner_s_busy;
+ end_cleaning(cleaner, event);
+ return;
+ }
+
+ INSIST(CLEANER_BUSY(cleaner));
+
+ n_entries = cleaner->increment;
+
+ isc_stdtime_get(&now);
+ isc_stdtime_convert32(now, &now32);
+
+ LOCK(&acache->lock);
+
+ entry = cleaner->current_entry;
+ isc_stdtime_convert32(cleaner->last_cleanup_time, &last32);
+ INSIST(now32 > last32);
+ interval = now32 - last32;
+
+ while (n_entries-- > 0) {
+ isc_boolean_t is_stale = ISC_FALSE;
+
+ INSIST(entry != NULL);
+
+ next = ISC_LIST_NEXT(entry, link);
+
+ ACACHE_LOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+
+ is_stale = entry_stale(cleaner, entry, now32, interval);
+ if (is_stale) {
+ ISC_LIST_UNLINK(acache->entries, entry, link);
+ unlink_dbentries(acache, entry);
+ if (entry->callback != NULL)
+ (entry->callback)(entry, &entry->cbarg);
+ entry->callback = NULL;
+
+ cleaner->ncleaned++;
+ }
+
+ ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+
+ if (is_stale)
+ dns_acache_detachentry(&entry);
+
+ if (next == NULL) {
+ if (cleaner->overmem) {
+ entry = ISC_LIST_HEAD(acache->entries);
+ if (entry != NULL) {
+ /*
+ * If we are still in the overmem
+ * state, keep cleaning.
+ */
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_ACACHE,
+ ISC_LOG_DEBUG(1),
+ "acache cleaner: "
+ "still overmem, "
+ "reset and try again");
+ continue;
+ }
+ }
+
+ UNLOCK(&acache->lock);
+ end_cleaning(cleaner, event);
+ return;
+ }
+
+ entry = next;
+ }
+
+ /*
+ * We have successfully performed a cleaning increment but have
+ * not gone through the entire cache. Remember the entry that will
+ * be the starting point in the next clean-up, and reschedule another
+ * batch. If it fails, just try to continue anyway.
+ */
+ INSIST(next != NULL && next != cleaner->current_entry);
+ dns_acache_detachentry(&cleaner->current_entry);
+ dns_acache_attachentry(next, &cleaner->current_entry);
+
+ UNLOCK(&acache->lock);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE,
+ ISC_LOG_DEBUG(1), "acache cleaner: checked %d entries, "
+ "mem inuse %lu, sleeping", cleaner->increment,
+ (unsigned long)isc_mem_inuse(cleaner->acache->mctx));
+
+ isc_task_send(task, &event);
+ INSIST(CLEANER_BUSY(cleaner));
+
+ return;
+}
+
+/*
+ * This is called when the acache either surpasses its upper limit
+ * or shrinks beyond its lower limit.
+ */
+static void
+acache_overmem_cleaning_action(isc_task_t *task, isc_event_t *event) {
+ acache_cleaner_t *cleaner = event->ev_arg;
+ isc_boolean_t want_cleaning = ISC_FALSE;
+
+ UNUSED(task);
+
+ INSIST(event->ev_type == DNS_EVENT_ACACHEOVERMEM);
+ INSIST(cleaner->overmem_event == NULL);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ACACHE,
+ ISC_LOG_DEBUG(1), "overmem_cleaning_action called, "
+ "overmem = %d, state = %d", cleaner->overmem,
+ cleaner->state);
+
+ LOCK(&cleaner->lock);
+
+ if (cleaner->overmem) {
+ if (cleaner->state == cleaner_s_idle)
+ want_cleaning = ISC_TRUE;
+ } else {
+ if (cleaner->state == cleaner_s_busy)
+ /*
+ * end_cleaning() can't be called here because
+ * then both cleaner->overmem_event and
+ * cleaner->resched_event will point to this
+ * event. Set the state to done, and then
+ * when the acache_incremental_cleaning_action() event
+ * is posted, it will handle the end_cleaning.
+ */
+ cleaner->state = cleaner_s_done;
+ }
+
+ cleaner->overmem_event = event;
+
+ UNLOCK(&cleaner->lock);
+
+ if (want_cleaning)
+ begin_cleaning(cleaner);
+}
+
+static void
+water(void *arg, int mark) {
+ dns_acache_t *acache = arg;
+ isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_ACACHE, ISC_LOG_DEBUG(1),
+ "acache memory reaches %s watermark, mem inuse %lu",
+ overmem ? "high" : "low",
+ (unsigned long)isc_mem_inuse(acache->mctx));
+
+ LOCK(&acache->cleaner.lock);
+
+ if (acache->cleaner.overmem != overmem) {
+ acache->cleaner.overmem = overmem;
+
+ if (acache->cleaner.overmem_event != NULL)
+ isc_task_send(acache->task,
+ &acache->cleaner.overmem_event);
+ isc_mem_waterack(acache->mctx, mark);
+ }
+
+ UNLOCK(&acache->cleaner.lock);
+}
+
+/*
+ * The cleaner task is shutting down; do the necessary cleanup.
+ */
+static void
+acache_cleaner_shutdown_action(isc_task_t *task, isc_event_t *event) {
+ dns_acache_t *acache = event->ev_arg;
+ isc_boolean_t should_free = ISC_FALSE;
+
+ INSIST(task == acache->task);
+ INSIST(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
+ INSIST(DNS_ACACHE_VALID(acache));
+
+ ATRACE("acache cleaner shutdown");
+
+ if (CLEANER_BUSY(&acache->cleaner))
+ end_cleaning(&acache->cleaner, event);
+ else
+ isc_event_free(&event);
+
+ LOCK(&acache->lock);
+
+ acache->live_cleaners--;
+ INSIST(acache->live_cleaners == 0);
+
+ if (isc_refcount_current(&acache->refs) == 0) {
+ INSIST(check_noentry(acache) == ISC_TRUE);
+ should_free = ISC_TRUE;
+ }
+
+ /*
+ * By detaching the timer in the context of its task,
+ * we are guaranteed that there will be no further timer
+ * events.
+ */
+ if (acache->cleaner.cleaning_timer != NULL)
+ isc_timer_detach(&acache->cleaner.cleaning_timer);
+
+ /* Make sure we don't reschedule anymore. */
+ (void)isc_task_purge(task, NULL, DNS_EVENT_ACACHECLEAN, NULL);
+
+ UNLOCK(&acache->lock);
+
+ if (should_free)
+ destroy(acache);
+}
+
+/*
+ * Public functions.
+ */
+
+isc_result_t
+dns_acache_create(dns_acache_t **acachep, isc_mem_t *mctx,
+ isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr)
+{
+ int i;
+ isc_result_t result;
+ dns_acache_t *acache;
+
+ REQUIRE(acachep != NULL && *acachep == NULL);
+ REQUIRE(mctx != NULL);
+ REQUIRE(taskmgr != NULL);
+
+ acache = isc_mem_get(mctx, sizeof(*acache));
+ if (acache == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ATRACE("create");
+
+ result = isc_refcount_init(&acache->refs, 1);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, acache, sizeof(*acache));
+ return (result);
+ }
+
+ result = isc_mutex_init(&acache->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_refcount_decrement(&acache->refs, NULL);
+ isc_refcount_destroy(&acache->refs);
+ isc_mem_put(mctx, acache, sizeof(*acache));
+ return (result);
+ }
+
+ acache->mctx = NULL;
+ isc_mem_attach(mctx, &acache->mctx);
+ ISC_LIST_INIT(acache->entries);
+
+ acache->shutting_down = ISC_FALSE;
+
+ acache->task = NULL;
+ acache->entrylocks = NULL;
+
+ result = isc_task_create(taskmgr, 1, &acache->task);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_task_create() failed(): %s",
+ dns_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+ isc_task_setname(acache->task, "acachetask", acache);
+ ISC_EVENT_INIT(&acache->cevent, sizeof(acache->cevent), 0, NULL,
+ DNS_EVENT_ACACHECONTROL, shutdown_task, NULL,
+ NULL, NULL, NULL);
+ acache->cevent_sent = ISC_FALSE;
+
+ acache->dbentries = 0;
+ for (i = 0; i < DBBUCKETS; i++)
+ ISC_LIST_INIT(acache->dbbucket[i]);
+
+ acache->entrylocks = isc_mem_get(mctx, sizeof(*acache->entrylocks) *
+ DEFAULT_ACACHE_ENTRY_LOCK_COUNT);
+ if (acache->entrylocks == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ for (i = 0; i < DEFAULT_ACACHE_ENTRY_LOCK_COUNT; i++) {
+ result = ACACHE_INITLOCK(&acache->entrylocks[i]);
+ if (result != ISC_R_SUCCESS) {
+ while (i-- > 0)
+ ACACHE_DESTROYLOCK(&acache->entrylocks[i]);
+ isc_mem_put(mctx, acache->entrylocks,
+ sizeof(*acache->entrylocks) *
+ DEFAULT_ACACHE_ENTRY_LOCK_COUNT);
+ acache->entrylocks = NULL;
+ goto cleanup;
+ }
+ }
+
+ acache->live_cleaners = 0;
+ result = acache_cleaner_init(acache, timermgr, &acache->cleaner);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ acache->stats.cleaner_runs = 0;
+ reset_stats(acache);
+
+ acache->magic = ACACHE_MAGIC;
+
+ *acachep = acache;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (acache->task != NULL)
+ isc_task_detach(&acache->task);
+ DESTROYLOCK(&acache->lock);
+ isc_refcount_decrement(&acache->refs, NULL);
+ isc_refcount_destroy(&acache->refs);
+ if (acache->entrylocks != NULL) {
+ for (i = 0; i < DEFAULT_ACACHE_ENTRY_LOCK_COUNT; i++)
+ ACACHE_DESTROYLOCK(&acache->entrylocks[i]);
+ isc_mem_put(mctx, acache->entrylocks,
+ sizeof(*acache->entrylocks) *
+ DEFAULT_ACACHE_ENTRY_LOCK_COUNT);
+ }
+ isc_mem_put(mctx, acache, sizeof(*acache));
+ isc_mem_detach(&mctx);
+
+ return (result);
+}
+
+void
+dns_acache_attach(dns_acache_t *source, dns_acache_t **targetp) {
+ REQUIRE(DNS_ACACHE_VALID(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ AATRACE(source, "attach");
+
+ isc_refcount_increment(&source->refs, NULL);
+
+ *targetp = source;
+}
+
+void
+dns_acache_countquerymiss(dns_acache_t *acache) {
+ acache->stats.misses++; /* XXXSK danger: unlocked! */
+ acache->stats.queries++; /* XXXSK danger: unlocked! */
+}
+
+void
+dns_acache_detach(dns_acache_t **acachep) {
+ dns_acache_t *acache;
+ unsigned int refs;
+ isc_boolean_t should_free = ISC_FALSE;
+
+ REQUIRE(acachep != NULL && DNS_ACACHE_VALID(*acachep));
+ acache = *acachep;
+
+ ATRACE("detach");
+
+ isc_refcount_decrement(&acache->refs, &refs);
+ if (refs == 0) {
+ INSIST(check_noentry(acache) == ISC_TRUE);
+ should_free = ISC_TRUE;
+ }
+
+ *acachep = NULL;
+
+ /*
+ * If we're exiting and the cleaner task exists, let it free the cache.
+ */
+ if (should_free && acache->live_cleaners > 0) {
+ isc_task_shutdown(acache->task);
+ should_free = ISC_FALSE;
+ }
+
+ if (should_free)
+ destroy(acache);
+}
+
+void
+dns_acache_shutdown(dns_acache_t *acache) {
+ REQUIRE(DNS_ACACHE_VALID(acache));
+
+ LOCK(&acache->lock);
+
+ ATRACE("shutdown");
+
+ if (!acache->shutting_down) {
+ isc_event_t *event;
+ dns_acache_t *acache_evarg = NULL;
+
+ INSIST(!acache->cevent_sent);
+
+ acache->shutting_down = ISC_TRUE;
+
+ isc_mem_setwater(acache->mctx, NULL, NULL, 0, 0);
+
+ /*
+ * Self attach the object in order to prevent it from being
+ * destroyed while waiting for the event.
+ */
+ dns_acache_attach(acache, &acache_evarg);
+ event = &acache->cevent;
+ event->ev_arg = acache_evarg;
+ isc_task_send(acache->task, &event);
+ acache->cevent_sent = ISC_TRUE;
+ }
+
+ UNLOCK(&acache->lock);
+}
+
+isc_result_t
+dns_acache_setdb(dns_acache_t *acache, dns_db_t *db) {
+ int bucket;
+ dbentry_t *dbentry;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+ REQUIRE(db != NULL);
+
+ ATRACE("setdb");
+
+ LOCK(&acache->lock);
+
+ dbentry = NULL;
+ result = finddbent(acache, db, &dbentry);
+ if (result == ISC_R_SUCCESS) {
+ result = ISC_R_EXISTS;
+ goto end;
+ }
+ result = ISC_R_SUCCESS;
+
+ dbentry = isc_mem_get(acache->mctx, sizeof(*dbentry));
+ if (dbentry == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto end;
+ }
+
+ ISC_LINK_INIT(dbentry, link);
+ ISC_LIST_INIT(dbentry->originlist);
+ ISC_LIST_INIT(dbentry->referlist);
+
+ dbentry->db = NULL;
+ dns_db_attach(db, &dbentry->db);
+
+ bucket = isc_hash_calc((const unsigned char *)&db,
+ sizeof(db), ISC_TRUE) % DBBUCKETS;
+
+ ISC_LIST_APPEND(acache->dbbucket[bucket], dbentry, link);
+
+ acache->dbentries++;
+
+ end:
+ UNLOCK(&acache->lock);
+
+ return (result);
+}
+
+isc_result_t
+dns_acache_putdb(dns_acache_t *acache, dns_db_t *db) {
+ int bucket;
+ isc_result_t result;
+ dbentry_t *dbentry;
+ dns_acacheentry_t *entry;
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+ REQUIRE(db != NULL);
+
+ ATRACE("putdb");
+
+ LOCK(&acache->lock);
+
+ dbentry = NULL;
+ result = finddbent(acache, db, &dbentry);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * The entry may have not been created due to memory shortage.
+ */
+ UNLOCK(&acache->lock);
+ return (ISC_R_NOTFOUND);
+ }
+
+ /*
+ * Release corresponding cache entries: for each entry, release all
+ * links the entry has, and then callback to the entry holder (if any).
+ * If no other external references exist (this can happen if the
+ * original holder has canceled callback,) destroy it here.
+ */
+ while ((entry = ISC_LIST_HEAD(dbentry->originlist)) != NULL) {
+ ACACHE_LOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+
+ /*
+ * Releasing olink first would avoid finddbent() in
+ * unlink_dbentries().
+ */
+ ISC_LIST_UNLINK(dbentry->originlist, entry, olink);
+ if (acache->cleaner.current_entry != entry)
+ ISC_LIST_UNLINK(acache->entries, entry, link);
+ unlink_dbentries(acache, entry);
+
+ if (entry->callback != NULL)
+ (entry->callback)(entry, &entry->cbarg);
+ entry->callback = NULL;
+
+ ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+
+ if (acache->cleaner.current_entry != entry)
+ dns_acache_detachentry(&entry);
+ }
+ while ((entry = ISC_LIST_HEAD(dbentry->referlist)) != NULL) {
+ ACACHE_LOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+
+ ISC_LIST_UNLINK(dbentry->referlist, entry, rlink);
+ if (acache->cleaner.current_entry != entry)
+ ISC_LIST_UNLINK(acache->entries, entry, link);
+ unlink_dbentries(acache, entry);
+
+ if (entry->callback != NULL)
+ (entry->callback)(entry, &entry->cbarg);
+ entry->callback = NULL;
+
+ ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+
+ if (acache->cleaner.current_entry != entry)
+ dns_acache_detachentry(&entry);
+ }
+
+ INSIST(ISC_LIST_EMPTY(dbentry->originlist) &&
+ ISC_LIST_EMPTY(dbentry->referlist));
+
+ bucket = isc_hash_calc((const unsigned char *)&db,
+ sizeof(db), ISC_TRUE) % DBBUCKETS;
+ ISC_LIST_UNLINK(acache->dbbucket[bucket], dbentry, link);
+ dns_db_detach(&dbentry->db);
+
+ isc_mem_put(acache->mctx, dbentry, sizeof(*dbentry));
+
+ acache->dbentries--;
+
+ acache->stats.deleted++;
+
+ UNLOCK(&acache->lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb,
+ void (*callback)(dns_acacheentry_t *, void **),
+ void *cbarg, dns_acacheentry_t **entryp)
+{
+ dns_acacheentry_t *newentry;
+ isc_result_t result;
+ isc_uint32_t r;
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+ REQUIRE(entryp != NULL && *entryp == NULL);
+ REQUIRE(origdb != NULL);
+
+ /*
+ * Should we exceed our memory limit for some reason (for
+ * example, if the cleaner does not run aggressively enough),
+ * then we will not create additional entries.
+ *
+ * XXXSK: It might be better to lock the acache->cleaner->lock,
+ * but locking may be an expensive bottleneck. If we misread
+ * the value, we will occasionally refuse to create a few
+ * cache entries, or create a few that we should not. I do not
+ * expect this to happen often, and it will not have very bad
+ * effects when it does. So no lock for now.
+ */
+ if (acache->cleaner.overmem) {
+ acache->stats.overmem_nocreates++; /* XXXSK danger: unlocked! */
+ return (ISC_R_NORESOURCES);
+ }
+
+ newentry = isc_mem_get(acache->mctx, sizeof(*newentry));
+ if (newentry == NULL) {
+ acache->stats.nomem++; /* XXXMLG danger: unlocked! */
+ return (ISC_R_NOMEMORY);
+ }
+
+ isc_random_get(&r);
+ newentry->locknum = r % DEFAULT_ACACHE_ENTRY_LOCK_COUNT;
+
+ result = isc_refcount_init(&newentry->references, 1);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(acache->mctx, newentry, sizeof(*newentry));
+ return (result);
+ };
+
+ ISC_LINK_INIT(newentry, link);
+ ISC_LINK_INIT(newentry, olink);
+ ISC_LINK_INIT(newentry, rlink);
+
+ newentry->acache = NULL;
+ dns_acache_attach(acache, &newentry->acache);
+
+ newentry->zone = NULL;
+ newentry->db = NULL;
+ newentry->version = NULL;
+ newentry->node = NULL;
+ newentry->foundname = NULL;
+
+ newentry->callback = callback;
+ newentry->cbarg = cbarg;
+ newentry->origdb = NULL;
+ dns_db_attach(origdb, &newentry->origdb);
+
+ isc_stdtime_get(&newentry->lastused);
+
+ newentry->magic = ACACHEENTRY_MAGIC;
+
+ *entryp = newentry;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_acache_getentry(dns_acacheentry_t *entry, dns_zone_t **zonep,
+ dns_db_t **dbp, dns_dbversion_t **versionp,
+ dns_dbnode_t **nodep, dns_name_t *fname,
+ dns_message_t *msg, isc_stdtime_t now)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rdataset_t *erdataset;
+ isc_stdtime32_t now32;
+ dns_acache_t *acache;
+ int locknum;
+
+ REQUIRE(DNS_ACACHEENTRY_VALID(entry));
+ REQUIRE(zonep == NULL || *zonep == NULL);
+ REQUIRE(dbp != NULL && *dbp == NULL);
+ REQUIRE(versionp != NULL && *versionp == NULL);
+ REQUIRE(nodep != NULL && *nodep == NULL);
+ REQUIRE(fname != NULL);
+ REQUIRE(msg != NULL);
+ acache = entry->acache;
+ REQUIRE(DNS_ACACHE_VALID(acache));
+
+ locknum = entry->locknum;
+ ACACHE_LOCK(&acache->entrylocks[locknum], isc_rwlocktype_read);
+
+ isc_stdtime_convert32(now, &now32);
+ acache_storetime(entry, now32);
+
+ if (entry->zone != NULL && zonep != NULL)
+ dns_zone_attach(entry->zone, zonep);
+
+ if (entry->db == NULL) {
+ *dbp = NULL;
+ *versionp = NULL;
+ } else {
+ dns_db_attach(entry->db, dbp);
+ dns_db_attachversion(entry->db, entry->version, versionp);
+ }
+ if (entry->node == NULL)
+ *nodep = NULL;
+ else {
+ dns_db_attachnode(entry->db, entry->node, nodep);
+
+ INSIST(entry->foundname != NULL);
+ dns_name_copy(entry->foundname, fname, NULL);
+ for (erdataset = ISC_LIST_HEAD(entry->foundname->list);
+ erdataset != NULL;
+ erdataset = ISC_LIST_NEXT(erdataset, link)) {
+ dns_rdataset_t *ardataset;
+
+ ardataset = NULL;
+ result = dns_message_gettemprdataset(msg, &ardataset);
+ if (result != ISC_R_SUCCESS) {
+ ACACHE_UNLOCK(&acache->entrylocks[locknum],
+ isc_rwlocktype_read);
+ goto fail;
+ }
+
+ /*
+ * XXXJT: if we simply clone the rdataset, we'll get
+ * lost wrt cyclic ordering. We'll need an additional
+ * trick to get the latest counter from the original
+ * header.
+ */
+ dns_rdataset_init(ardataset);
+ dns_rdataset_clone(erdataset, ardataset);
+ ISC_LIST_APPEND(fname->list, ardataset, link);
+ }
+ }
+
+ entry->acache->stats.hits++; /* XXXMLG danger: unlocked! */
+ entry->acache->stats.queries++;
+
+ ACACHE_UNLOCK(&acache->entrylocks[locknum], isc_rwlocktype_read);
+
+ return (result);
+
+ fail:
+ while ((erdataset = ISC_LIST_HEAD(fname->list)) != NULL) {
+ ISC_LIST_UNLINK(fname->list, erdataset, link);
+ dns_rdataset_disassociate(erdataset);
+ dns_message_puttemprdataset(msg, &erdataset);
+ }
+ if (*nodep != NULL)
+ dns_db_detachnode(*dbp, nodep);
+ if (*versionp != NULL)
+ dns_db_closeversion(*dbp, versionp, ISC_FALSE);
+ if (*dbp != NULL)
+ dns_db_detach(dbp);
+ if (zonep != NULL && *zonep != NULL)
+ dns_zone_detach(zonep);
+
+ return (result);
+}
+
+isc_result_t
+dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry,
+ dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+ dns_dbnode_t *node, dns_name_t *fname)
+{
+ isc_result_t result;
+ dbentry_t *odbent;
+ dbentry_t *rdbent = NULL;
+ isc_boolean_t close_version = ISC_FALSE;
+ dns_acacheentry_t *dummy_entry = NULL;
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+ REQUIRE(DNS_ACACHEENTRY_VALID(entry));
+
+ LOCK(&acache->lock); /* XXX: need to lock it here for ordering */
+ ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write);
+
+ /* Set zone */
+ if (zone != NULL)
+ dns_zone_attach(zone, &entry->zone);
+ /* Set DB */
+ if (db != NULL)
+ dns_db_attach(db, &entry->db);
+ /*
+ * Set DB version. If the version is not given by the caller,
+ * which is the case for glue or cache DBs, use the current version.
+ */
+ if (version == NULL) {
+ if (db != NULL) {
+ dns_db_currentversion(db, &version);
+ close_version = ISC_TRUE;
+ }
+ }
+ if (version != NULL) {
+ INSIST(db != NULL);
+ dns_db_attachversion(db, version, &entry->version);
+ }
+ if (close_version)
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ /* Set DB node. */
+ if (node != NULL) {
+ INSIST(db != NULL);
+ dns_db_attachnode(db, node, &entry->node);
+ }
+
+ /*
+ * Set list of the corresponding rdatasets, if given.
+ * To minimize the overhead and memory consumption, we'll do this for
+ * positive cache only, in which case the DB node is non NULL.
+ * We do not want to cache incomplete information, so give up the
+ * entire entry when a memory shortage happen during the process.
+ */
+ if (node != NULL) {
+ dns_rdataset_t *ardataset, *crdataset;
+
+ entry->foundname = isc_mem_get(acache->mctx,
+ sizeof(*entry->foundname));
+
+ if (entry->foundname == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto fail;
+ }
+ dns_name_init(entry->foundname, NULL);
+ result = dns_name_dup(fname, acache->mctx,
+ entry->foundname);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ for (ardataset = ISC_LIST_HEAD(fname->list);
+ ardataset != NULL;
+ ardataset = ISC_LIST_NEXT(ardataset, link)) {
+ crdataset = isc_mem_get(acache->mctx,
+ sizeof(*crdataset));
+ if (crdataset == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto fail;
+ }
+
+ dns_rdataset_init(crdataset);
+ dns_rdataset_clone(ardataset, crdataset);
+ ISC_LIST_APPEND(entry->foundname->list, crdataset,
+ link);
+ }
+ }
+
+ odbent = NULL;
+ result = finddbent(acache, entry->origdb, &odbent);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ if (db != NULL) {
+ rdbent = NULL;
+ result = finddbent(acache, db, &rdbent);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ }
+
+ ISC_LIST_APPEND(acache->entries, entry, link);
+ ISC_LIST_APPEND(odbent->originlist, entry, olink);
+ if (rdbent != NULL)
+ ISC_LIST_APPEND(rdbent->referlist, entry, rlink);
+
+ /*
+ * The additional cache needs an implicit reference to entries in its
+ * link.
+ */
+ dns_acache_attachentry(entry, &dummy_entry);
+
+ ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+
+ acache->stats.adds++;
+ UNLOCK(&acache->lock);
+
+ return (ISC_R_SUCCESS);
+
+ fail:
+ clear_entry(acache, entry);
+
+ ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+ UNLOCK(&acache->lock);
+
+ return (result);
+}
+
+void
+dns_acache_cancelentry(dns_acacheentry_t *entry) {
+ dns_acache_t *acache = entry->acache;
+
+ REQUIRE(DNS_ACACHEENTRY_VALID(entry));
+ INSIST(DNS_ACACHE_VALID(acache));
+
+ LOCK(&acache->lock);
+ ACACHE_LOCK(&acache->entrylocks[entry->locknum], isc_rwlocktype_write);
+
+ /*
+ * Release dependencies stored in this entry as much as possible.
+ * The main link cannot be released, since the acache object has
+ * a reference to this entry; the empty entry will be released in
+ * the next cleaning action.
+ */
+ unlink_dbentries(acache, entry);
+ clear_entry(entry->acache, entry);
+
+ entry->callback = NULL;
+ entry->cbarg = NULL;
+
+ ACACHE_UNLOCK(&acache->entrylocks[entry->locknum],
+ isc_rwlocktype_write);
+ UNLOCK(&acache->lock);
+}
+
+void
+dns_acache_attachentry(dns_acacheentry_t *source,
+ dns_acacheentry_t **targetp)
+{
+ REQUIRE(DNS_ACACHEENTRY_VALID(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ isc_refcount_increment(&source->references, NULL);
+
+ *targetp = source;
+}
+
+void
+dns_acache_detachentry(dns_acacheentry_t **entryp) {
+ dns_acacheentry_t *entry;
+ unsigned int refs;
+
+ REQUIRE(entryp != NULL && DNS_ACACHEENTRY_VALID(*entryp));
+ entry = *entryp;
+
+ isc_refcount_decrement(&entry->references, &refs);
+
+ /*
+ * If there are no references to the entry, the entry must have been
+ * unlinked and can be destroyed safely.
+ */
+ if (refs == 0) {
+ INSIST(!ISC_LINK_LINKED(entry, link));
+ (*entryp)->acache->stats.deleted++;
+ destroy_entry(entry);
+ }
+
+ *entryp = NULL;
+}
+
+void
+dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t) {
+ isc_interval_t interval;
+ isc_result_t result;
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+
+ ATRACE("dns_acache_setcleaninginterval");
+
+ LOCK(&acache->lock);
+
+ /*
+ * It may be the case that the acache has already shut down.
+ * If so, it has no timer. (Not sure if this can really happen.)
+ */
+ if (acache->cleaner.cleaning_timer == NULL)
+ goto unlock;
+
+ acache->cleaner.cleaning_interval = t;
+
+ if (t == 0) {
+ result = isc_timer_reset(acache->cleaner.cleaning_timer,
+ isc_timertype_inactive,
+ NULL, NULL, ISC_TRUE);
+ } else {
+ isc_interval_set(&interval, acache->cleaner.cleaning_interval,
+ 0);
+ result = isc_timer_reset(acache->cleaner.cleaning_timer,
+ isc_timertype_ticker,
+ NULL, &interval, ISC_FALSE);
+ }
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_ACACHE, ISC_LOG_WARNING,
+ "could not set acache cleaning interval: %s",
+ isc_result_totext(result));
+ else
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_ACACHE, ISC_LOG_NOTICE,
+ "acache %p cleaning interval set to %d.",
+ acache, t);
+
+ unlock:
+ UNLOCK(&acache->lock);
+}
+
+/*
+ * This function was derived from cache.c:dns_cache_setcachesize(). See the
+ * function for more details about the logic.
+ */
+void
+dns_acache_setcachesize(dns_acache_t *acache, isc_uint32_t size) {
+ isc_uint32_t lowater;
+ isc_uint32_t hiwater;
+
+ REQUIRE(DNS_ACACHE_VALID(acache));
+
+ if (size != 0 && size < DNS_ACACHE_MINSIZE)
+ size = DNS_ACACHE_MINSIZE;
+
+ hiwater = size - (size >> 3);
+ lowater = size - (size >> 2);
+
+ if (size == 0 || hiwater == 0 || lowater == 0)
+ isc_mem_setwater(acache->mctx, water, acache, 0, 0);
+ else
+ isc_mem_setwater(acache->mctx, water, acache,
+ hiwater, lowater);
+}
diff --git a/lib/dns/acl.c b/lib/dns/acl.c
new file mode 100644
index 0000000..ed4aab9
--- /dev/null
+++ b/lib/dns/acl.c
@@ -0,0 +1,623 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: acl.c,v 1.50 2008/09/26 23:47:06 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/iptable.h>
+
+/*
+ * Create a new ACL, including an IP table and an array with room
+ * for 'n' ACL elements. The elements are uninitialized and the
+ * length is 0.
+ */
+isc_result_t
+dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
+ isc_result_t result;
+ dns_acl_t *acl;
+
+ /*
+ * Work around silly limitation of isc_mem_get().
+ */
+ if (n == 0)
+ n = 1;
+
+ acl = isc_mem_get(mctx, sizeof(*acl));
+ if (acl == NULL)
+ return (ISC_R_NOMEMORY);
+ acl->mctx = mctx;
+ acl->name = NULL;
+
+ result = isc_refcount_init(&acl->refcount, 1);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, acl, sizeof(*acl));
+ return (result);
+ }
+
+ result = dns_iptable_create(mctx, &acl->iptable);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, acl, sizeof(*acl));
+ return (result);
+ }
+
+ acl->elements = NULL;
+ acl->alloc = 0;
+ acl->length = 0;
+ acl->has_negatives = ISC_FALSE;
+
+ ISC_LINK_INIT(acl, nextincache);
+ /*
+ * Must set magic early because we use dns_acl_detach() to clean up.
+ */
+ acl->magic = DNS_ACL_MAGIC;
+
+ acl->elements = isc_mem_get(mctx, n * sizeof(dns_aclelement_t));
+ if (acl->elements == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ acl->alloc = n;
+ memset(acl->elements, 0, n * sizeof(dns_aclelement_t));
+ *target = acl;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_acl_detach(&acl);
+ return (result);
+}
+
+/*
+ * Create a new ACL and initialize it with the value "any" or "none",
+ * depending on the value of the "neg" parameter.
+ * "any" is a positive iptable entry with bit length 0.
+ * "none" is the same as "!any".
+ */
+static isc_result_t
+dns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
+ isc_result_t result;
+ dns_acl_t *acl = NULL;
+ result = dns_acl_create(mctx, 0, &acl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_iptable_addprefix(acl->iptable, NULL, 0, ISC_TF(!neg));
+ if (result != ISC_R_SUCCESS) {
+ dns_acl_detach(&acl);
+ return (result);
+ }
+
+ *target = acl;
+ return (result);
+}
+
+/*
+ * Create a new ACL that matches everything.
+ */
+isc_result_t
+dns_acl_any(isc_mem_t *mctx, dns_acl_t **target) {
+ return (dns_acl_anyornone(mctx, ISC_FALSE, target));
+}
+
+/*
+ * Create a new ACL that matches nothing.
+ */
+isc_result_t
+dns_acl_none(isc_mem_t *mctx, dns_acl_t **target) {
+ return (dns_acl_anyornone(mctx, ISC_TRUE, target));
+}
+
+/*
+ * If pos is ISC_TRUE, test whether acl is set to "{ any; }"
+ * If pos is ISC_FALSE, test whether acl is set to "{ none; }"
+ */
+static isc_boolean_t
+dns_acl_isanyornone(dns_acl_t *acl, isc_boolean_t pos)
+{
+ /* Should never happen but let's be safe */
+ if (acl == NULL ||
+ acl->iptable == NULL ||
+ acl->iptable->radix == NULL ||
+ acl->iptable->radix->head == NULL ||
+ acl->iptable->radix->head->prefix == NULL)
+ return (ISC_FALSE);
+
+ if (acl->length != 0 || acl->node_count != 1)
+ return (ISC_FALSE);
+
+ if (acl->iptable->radix->head->prefix->bitlen == 0 &&
+ acl->iptable->radix->head->data[0] != NULL &&
+ acl->iptable->radix->head->data[0] ==
+ acl->iptable->radix->head->data[1] &&
+ *(isc_boolean_t *) (acl->iptable->radix->head->data[0]) == pos)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE); /* All others */
+}
+
+/*
+ * Test whether acl is set to "{ any; }"
+ */
+isc_boolean_t
+dns_acl_isany(dns_acl_t *acl)
+{
+ return (dns_acl_isanyornone(acl, ISC_TRUE));
+}
+
+/*
+ * Test whether acl is set to "{ none; }"
+ */
+isc_boolean_t
+dns_acl_isnone(dns_acl_t *acl)
+{
+ return (dns_acl_isanyornone(acl, ISC_FALSE));
+}
+
+/*
+ * Determine whether a given address or signer matches a given ACL.
+ * For a match with a positive ACL element or iptable radix entry,
+ * return with a positive value in match; for a match with a negated ACL
+ * element or radix entry, return with a negative value in match.
+ */
+isc_result_t
+dns_acl_match(const isc_netaddr_t *reqaddr,
+ const dns_name_t *reqsigner,
+ const dns_acl_t *acl,
+ const dns_aclenv_t *env,
+ int *match,
+ const dns_aclelement_t **matchelt)
+{
+ isc_uint16_t bitlen, family;
+ isc_prefix_t pfx;
+ isc_radix_node_t *node;
+ const isc_netaddr_t *addr;
+ isc_netaddr_t v4addr;
+ isc_result_t result;
+ int match_num = -1;
+ unsigned int i;
+
+ REQUIRE(reqaddr != NULL);
+ REQUIRE(matchelt == NULL || *matchelt == NULL);
+
+ if (env == NULL || env->match_mapped == ISC_FALSE ||
+ reqaddr->family != AF_INET6 ||
+ !IN6_IS_ADDR_V4MAPPED(&reqaddr->type.in6))
+ addr = reqaddr;
+ else {
+ isc_netaddr_fromv4mapped(&v4addr, reqaddr);
+ addr = &v4addr;
+ }
+
+ /* Always match with host addresses. */
+ family = addr->family;
+ bitlen = family == AF_INET6 ? 128 : 32;
+ NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
+
+ /* Assume no match. */
+ *match = 0;
+
+ /* Search radix. */
+ result = isc_radix_search(acl->iptable->radix, &node, &pfx);
+
+ /* Found a match. */
+ if (result == ISC_R_SUCCESS && node != NULL) {
+ match_num = node->node_num[ISC_IS6(family)];
+ if (*(isc_boolean_t *) node->data[ISC_IS6(family)] == ISC_TRUE)
+ *match = match_num;
+ else
+ *match = -match_num;
+ }
+
+ /* Now search non-radix elements for a match with a lower node_num. */
+ for (i = 0; i < acl->length; i++) {
+ dns_aclelement_t *e = &acl->elements[i];
+
+ /* Already found a better match? */
+ if (match_num != -1 && match_num < e->node_num) {
+ isc_refcount_destroy(&pfx.refcount);
+ return (ISC_R_SUCCESS);
+ }
+
+ if (dns_aclelement_match(reqaddr, reqsigner,
+ e, env, matchelt)) {
+ if (match_num == -1 || e->node_num < match_num) {
+ if (e->negative == ISC_TRUE)
+ *match = -e->node_num;
+ else
+ *match = e->node_num;
+ }
+ isc_refcount_destroy(&pfx.refcount);
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ isc_refcount_destroy(&pfx.refcount);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Merge the contents of one ACL into another. Call dns_iptable_merge()
+ * for the IP tables, then concatenate the element arrays.
+ *
+ * If pos is set to false, then the nested ACL is to be negated. This
+ * means reverse the sense of each *positive* element or IP table node,
+ * but leave negatives alone, so as to prevent a double-negative causing
+ * an unexpected postive match in the parent ACL.
+ */
+isc_result_t
+dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
+{
+ isc_result_t result;
+ unsigned int newalloc, nelem, i;
+ int max_node = 0, nodes;
+
+ /* Resize the element array if needed. */
+ if (dest->length + source->length > dest->alloc) {
+ void *newmem;
+
+ newalloc = dest->alloc + source->alloc;
+ if (newalloc < 4)
+ newalloc = 4;
+
+ newmem = isc_mem_get(dest->mctx,
+ newalloc * sizeof(dns_aclelement_t));
+ if (newmem == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /* Copy in the original elements */
+ memcpy(newmem, dest->elements,
+ dest->length * sizeof(dns_aclelement_t));
+
+ /* Release the memory for the old elements array */
+ isc_mem_put(dest->mctx, dest->elements,
+ dest->alloc * sizeof(dns_aclelement_t));
+ dest->elements = newmem;
+ dest->alloc = newalloc;
+ }
+
+ /*
+ * Now copy in the new elements, increasing their node_num
+ * values so as to keep the new ACL consistent. If we're
+ * negating, then negate positive elements, but keep negative
+ * elements the same for security reasons.
+ */
+ nelem = dest->length;
+ dest->length += source->length;
+ for (i = 0; i < source->length; i++) {
+ if (source->elements[i].node_num > max_node)
+ max_node = source->elements[i].node_num;
+
+ /* Copy type. */
+ dest->elements[nelem + i].type = source->elements[i].type;
+
+ /* Adjust node numbering. */
+ dest->elements[nelem + i].node_num =
+ source->elements[i].node_num + dest->node_count;
+
+ /* Duplicate nested acl. */
+ if (source->elements[i].type == dns_aclelementtype_nestedacl &&
+ source->elements[i].nestedacl != NULL)
+ dns_acl_attach(source->elements[i].nestedacl,
+ &dest->elements[nelem + i].nestedacl);
+
+ /* Duplicate key name. */
+ if (source->elements[i].type == dns_aclelementtype_keyname) {
+ dns_name_init(&dest->elements[nelem+i].keyname, NULL);
+ result = dns_name_dup(&source->elements[i].keyname,
+ dest->mctx,
+ &dest->elements[nelem+i].keyname);
+ if (result != ISC_R_SUCCESS)
+ return result;
+ }
+
+ /* reverse sense of positives if this is a negative acl */
+ if (!pos && source->elements[i].negative == ISC_FALSE) {
+ dest->elements[nelem + i].negative = ISC_TRUE;
+ } else {
+ dest->elements[nelem + i].negative =
+ source->elements[i].negative;
+ }
+ }
+
+
+ /*
+ * Merge the iptables. Make sure the destination ACL's
+ * node_count value is set correctly afterward.
+ */
+ nodes = max_node + dest->node_count;
+ result = dns_iptable_merge(dest->iptable, source->iptable, pos);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (nodes > dest->node_count)
+ dest->node_count = nodes;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Like dns_acl_match, but matches against the single ACL element 'e'
+ * rather than a complete ACL, and returns ISC_TRUE iff it matched.
+ *
+ * To determine whether the match was prositive or negative, the
+ * caller should examine e->negative. Since the element 'e' may be
+ * a reference to a named ACL or a nested ACL, a matching element
+ * returned through 'matchelt' is not necessarily 'e' itself.
+ */
+isc_boolean_t
+dns_aclelement_match(const isc_netaddr_t *reqaddr,
+ const dns_name_t *reqsigner,
+ const dns_aclelement_t *e,
+ const dns_aclenv_t *env,
+ const dns_aclelement_t **matchelt)
+{
+ dns_acl_t *inner = NULL;
+ int indirectmatch;
+ isc_result_t result;
+
+ switch (e->type) {
+ case dns_aclelementtype_keyname:
+ if (reqsigner != NULL &&
+ dns_name_equal(reqsigner, &e->keyname)) {
+ if (matchelt != NULL)
+ *matchelt = e;
+ return (ISC_TRUE);
+ } else {
+ return (ISC_FALSE);
+ }
+
+ case dns_aclelementtype_nestedacl:
+ inner = e->nestedacl;
+ break;
+
+ case dns_aclelementtype_localhost:
+ if (env == NULL || env->localhost == NULL)
+ return (ISC_FALSE);
+ inner = env->localhost;
+ break;
+
+ case dns_aclelementtype_localnets:
+ if (env == NULL || env->localnets == NULL)
+ return (ISC_FALSE);
+ inner = env->localnets;
+ break;
+
+ default:
+ /* Should be impossible. */
+ INSIST(0);
+ }
+
+ result = dns_acl_match(reqaddr, reqsigner, inner, env,
+ &indirectmatch, matchelt);
+ INSIST(result == ISC_R_SUCCESS);
+
+ /*
+ * Treat negative matches in indirect ACLs as "no match".
+ * That way, a negated indirect ACL will never become a
+ * surprise positive match through double negation.
+ * XXXDCL this should be documented.
+ */
+
+ if (indirectmatch > 0) {
+ if (matchelt != NULL)
+ *matchelt = e;
+ return (ISC_TRUE);
+ }
+
+ /*
+ * A negative indirect match may have set *matchelt, but we don't
+ * want it set when we return.
+ */
+
+ if (matchelt != NULL)
+ *matchelt = NULL;
+
+ return (ISC_FALSE);
+}
+
+void
+dns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
+ REQUIRE(DNS_ACL_VALID(source));
+ isc_refcount_increment(&source->refcount, NULL);
+ *target = source;
+}
+
+static void
+destroy(dns_acl_t *dacl) {
+ unsigned int i;
+ for (i = 0; i < dacl->length; i++) {
+ dns_aclelement_t *de = &dacl->elements[i];
+ if (de->type == dns_aclelementtype_keyname) {
+ dns_name_free(&de->keyname, dacl->mctx);
+ } else if (de->type == dns_aclelementtype_nestedacl) {
+ dns_acl_detach(&de->nestedacl);
+ }
+ }
+ if (dacl->elements != NULL)
+ isc_mem_put(dacl->mctx, dacl->elements,
+ dacl->alloc * sizeof(dns_aclelement_t));
+ if (dacl->name != NULL)
+ isc_mem_free(dacl->mctx, dacl->name);
+ if (dacl->iptable != NULL)
+ dns_iptable_detach(&dacl->iptable);
+ isc_refcount_destroy(&dacl->refcount);
+ dacl->magic = 0;
+ isc_mem_put(dacl->mctx, dacl, sizeof(*dacl));
+}
+
+void
+dns_acl_detach(dns_acl_t **aclp) {
+ dns_acl_t *acl = *aclp;
+ unsigned int refs;
+ REQUIRE(DNS_ACL_VALID(acl));
+ isc_refcount_decrement(&acl->refcount, &refs);
+ if (refs == 0)
+ destroy(acl);
+ *aclp = NULL;
+}
+
+
+static isc_once_t insecure_prefix_once = ISC_ONCE_INIT;
+static isc_mutex_t insecure_prefix_lock;
+static isc_boolean_t insecure_prefix_found;
+
+static void
+initialize_action(void) {
+ RUNTIME_CHECK(isc_mutex_init(&insecure_prefix_lock) == ISC_R_SUCCESS);
+}
+
+/*
+ * Called via isc_radix_walk() to find IP table nodes that are
+ * insecure.
+ */
+static void
+is_insecure(isc_prefix_t *prefix, void **data) {
+ isc_boolean_t secure;
+ int bitlen, family;
+
+ bitlen = prefix->bitlen;
+ family = prefix->family;
+
+ /* Negated entries are always secure. */
+ secure = * (isc_boolean_t *)data[ISC_IS6(family)];
+ if (!secure) {
+ return;
+ }
+
+ /* If loopback prefix found, return */
+ switch (family) {
+ case AF_INET:
+ if (bitlen == 32 &&
+ htonl(prefix->add.sin.s_addr) == INADDR_LOOPBACK)
+ return;
+ break;
+ case AF_INET6:
+ if (bitlen == 128 && IN6_IS_ADDR_LOOPBACK(&prefix->add.sin6))
+ return;
+ break;
+ default:
+ break;
+ }
+
+ /* Non-negated, non-loopback */
+ insecure_prefix_found = ISC_TRUE; /* LOCKED */
+ return;
+}
+
+/*
+ * Return ISC_TRUE iff the acl 'a' is considered insecure, that is,
+ * if it contains IP addresses other than those of the local host.
+ * This is intended for applications such as printing warning
+ * messages for suspect ACLs; it is not intended for making access
+ * control decisions. We make no guarantee that an ACL for which
+ * this function returns ISC_FALSE is safe.
+ */
+isc_boolean_t
+dns_acl_isinsecure(const dns_acl_t *a) {
+ unsigned int i;
+ isc_boolean_t insecure;
+
+ RUNTIME_CHECK(isc_once_do(&insecure_prefix_once,
+ initialize_action) == ISC_R_SUCCESS);
+
+ /*
+ * Walk radix tree to find out if there are any non-negated,
+ * non-loopback prefixes.
+ */
+ LOCK(&insecure_prefix_lock);
+ insecure_prefix_found = ISC_FALSE;
+ isc_radix_process(a->iptable->radix, is_insecure);
+ insecure = insecure_prefix_found;
+ UNLOCK(&insecure_prefix_lock);
+ if (insecure)
+ return(ISC_TRUE);
+
+ /* Now check non-radix elements */
+ for (i = 0; i < a->length; i++) {
+ dns_aclelement_t *e = &a->elements[i];
+
+ /* A negated match can never be insecure. */
+ if (e->negative)
+ continue;
+
+ switch (e->type) {
+ case dns_aclelementtype_keyname:
+ case dns_aclelementtype_localhost:
+ continue;
+
+ case dns_aclelementtype_nestedacl:
+ if (dns_acl_isinsecure(e->nestedacl))
+ return (ISC_TRUE);
+ continue;
+
+ case dns_aclelementtype_localnets:
+ return (ISC_TRUE);
+
+ default:
+ INSIST(0);
+ return (ISC_TRUE);
+ }
+ }
+
+ /* No insecure elements were found. */
+ return (ISC_FALSE);
+}
+
+/*
+ * Initialize ACL environment, setting up localhost and localnets ACLs
+ */
+isc_result_t
+dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
+ isc_result_t result;
+ env->localhost = NULL;
+ env->localnets = NULL;
+ result = dns_acl_create(mctx, 0, &env->localhost);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_nothing;
+ result = dns_acl_create(mctx, 0, &env->localnets);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_localhost;
+ env->match_mapped = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+
+ cleanup_localhost:
+ dns_acl_detach(&env->localhost);
+ cleanup_nothing:
+ return (result);
+}
+
+void
+dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s) {
+ dns_acl_detach(&t->localhost);
+ dns_acl_attach(s->localhost, &t->localhost);
+ dns_acl_detach(&t->localnets);
+ dns_acl_attach(s->localnets, &t->localnets);
+ t->match_mapped = s->match_mapped;
+}
+
+void
+dns_aclenv_destroy(dns_aclenv_t *env) {
+ dns_acl_detach(&env->localhost);
+ dns_acl_detach(&env->localnets);
+}
diff --git a/lib/dns/adb.c b/lib/dns/adb.c
new file mode 100644
index 0000000..a41515c
--- /dev/null
+++ b/lib/dns/adb.c
@@ -0,0 +1,3621 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: adb.c,v 1.243 2008/10/17 03:23:13 marka Exp $ */
+
+/*! \file
+ *
+ * \note
+ * In finds, if task == NULL, no events will be generated, and no events
+ * have been sent. If task != NULL but taskaction == NULL, an event has been
+ * posted but not yet freed. If neither are NULL, no event was posted.
+ *
+ */
+
+#include <config.h>
+
+#include <limits.h>
+
+#include <isc/mutexblock.h>
+#include <isc/netaddr.h>
+#include <isc/random.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/adb.h>
+#include <dns/db.h>
+#include <dns/events.h>
+#include <dns/log.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/stats.h>
+
+#define DNS_ADB_MAGIC ISC_MAGIC('D', 'a', 'd', 'b')
+#define DNS_ADB_VALID(x) ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)
+#define DNS_ADBNAME_MAGIC ISC_MAGIC('a', 'd', 'b', 'N')
+#define DNS_ADBNAME_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)
+#define DNS_ADBNAMEHOOK_MAGIC ISC_MAGIC('a', 'd', 'N', 'H')
+#define DNS_ADBNAMEHOOK_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)
+#define DNS_ADBLAMEINFO_MAGIC ISC_MAGIC('a', 'd', 'b', 'Z')
+#define DNS_ADBLAMEINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBLAMEINFO_MAGIC)
+#define DNS_ADBENTRY_MAGIC ISC_MAGIC('a', 'd', 'b', 'E')
+#define DNS_ADBENTRY_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)
+#define DNS_ADBFETCH_MAGIC ISC_MAGIC('a', 'd', 'F', '4')
+#define DNS_ADBFETCH_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)
+#define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '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
+ * if the zone has extremely low TTLs.
+ */
+#define ADB_CACHE_MINIMUM 10 /*%< seconds */
+#define ADB_CACHE_MAXIMUM 86400 /*%< seconds (86400 = 24 hours) */
+#define ADB_ENTRY_WINDOW 1800 /*%< seconds */
+
+/*%
+ * The period in seconds after which an ADB name entry is regarded as stale
+ * and forced to be cleaned up.
+ * TODO: This should probably be configurable at run-time.
+ */
+#ifndef ADB_STALE_MARGIN
+#define ADB_STALE_MARGIN 1800
+#endif
+
+#define FREE_ITEMS 64 /*%< free count for memory pools */
+#define FILL_COUNT 16 /*%< fill count for memory pools */
+
+#define DNS_ADB_INVALIDBUCKET (-1) /*%< invalid bucket address */
+
+#define DNS_ADB_MINADBSIZE (1024*1024) /*%< 1 Megabyte */
+
+typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;
+typedef struct dns_adbnamehook dns_adbnamehook_t;
+typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;
+typedef struct dns_adblameinfo dns_adblameinfo_t;
+typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;
+typedef struct dns_adbfetch dns_adbfetch_t;
+typedef struct dns_adbfetch6 dns_adbfetch6_t;
+
+/*% dns adb structure */
+struct dns_adb {
+ unsigned int magic;
+
+ isc_mutex_t lock;
+ isc_mutex_t reflock; /*%< Covers irefcnt, erefcnt */
+ isc_mutex_t overmemlock; /*%< Covers overmem */
+ isc_mem_t *mctx;
+ dns_view_t *view;
+
+ isc_taskmgr_t *taskmgr;
+ isc_task_t *task;
+ isc_boolean_t overmem;
+
+ isc_interval_t tick_interval;
+ int next_cleanbucket;
+
+ unsigned int irefcnt;
+ unsigned int erefcnt;
+
+ isc_mutex_t mplock;
+ isc_mempool_t *nmp; /*%< dns_adbname_t */
+ isc_mempool_t *nhmp; /*%< dns_adbnamehook_t */
+ isc_mempool_t *limp; /*%< dns_adblameinfo_t */
+ isc_mempool_t *emp; /*%< dns_adbentry_t */
+ isc_mempool_t *ahmp; /*%< dns_adbfind_t */
+ isc_mempool_t *aimp; /*%< dns_adbaddrinfo_t */
+ isc_mempool_t *afmp; /*%< dns_adbfetch_t */
+
+ /*!
+ * Bucketized locks and lists for names.
+ *
+ * XXXRTH Have a per-bucket structure that contains all of these?
+ */
+ dns_adbnamelist_t names[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];
+
+ /*!
+ * Bucketized locks for entries.
+ *
+ * XXXRTH Have a per-bucket structure that contains all of these?
+ */
+ dns_adbentrylist_t entries[NBUCKETS];
+ isc_mutex_t entrylocks[NBUCKETS];
+ isc_boolean_t entry_sd[NBUCKETS]; /*%< shutting down */
+ unsigned int entry_refcnt[NBUCKETS];
+
+ isc_event_t cevent;
+ isc_boolean_t cevent_sent;
+ isc_boolean_t shutting_down;
+ isc_eventlist_t whenshutdown;
+};
+
+/*
+ * XXXMLG Document these structures.
+ */
+
+/*% dns_adbname structure */
+struct dns_adbname {
+ unsigned int magic;
+ dns_name_t name;
+ dns_adb_t *adb;
+ unsigned int partial_result;
+ unsigned int flags;
+ int lock_bucket;
+ dns_name_t target;
+ isc_stdtime_t expire_target;
+ isc_stdtime_t expire_v4;
+ isc_stdtime_t expire_v6;
+ unsigned int chains;
+ dns_adbnamehooklist_t v4;
+ dns_adbnamehooklist_t v6;
+ dns_adbfetch_t *fetch_a;
+ dns_adbfetch_t *fetch_aaaa;
+ unsigned int fetch_err;
+ unsigned int fetch6_err;
+ dns_adbfindlist_t finds;
+ /* for LRU-based management */
+ isc_stdtime_t last_used;
+
+ ISC_LINK(dns_adbname_t) plink;
+};
+
+/*% The adbfetch structure */
+struct dns_adbfetch {
+ unsigned int magic;
+ dns_adbnamehook_t *namehook;
+ dns_adbentry_t *entry;
+ dns_fetch_t *fetch;
+ dns_rdataset_t rdataset;
+};
+
+/*%
+ * This is a small widget that dangles off a dns_adbname_t. It contains a
+ * pointer to the address information about this host, and a link to the next
+ * namehook that will contain the next address this host has.
+ */
+struct dns_adbnamehook {
+ unsigned int magic;
+ dns_adbentry_t *entry;
+ ISC_LINK(dns_adbnamehook_t) plink;
+};
+
+/*%
+ * This is a small widget that holds qname-specific information about an
+ * address. Currently limited to lameness, but could just as easily be
+ * extended to other types of information about zones.
+ */
+struct dns_adblameinfo {
+ unsigned int magic;
+
+ dns_name_t qname;
+ dns_rdatatype_t qtype;
+ isc_stdtime_t lame_timer;
+
+ ISC_LINK(dns_adblameinfo_t) plink;
+};
+
+/*%
+ * An address entry. It holds quite a bit of information about addresses,
+ * including edns state (in "flags"), rtt, and of course the address of
+ * the host.
+ */
+struct dns_adbentry {
+ unsigned int magic;
+
+ int lock_bucket;
+ unsigned int refcnt;
+
+ unsigned int flags;
+ unsigned int srtt;
+ isc_sockaddr_t sockaddr;
+
+ isc_stdtime_t expires;
+ /*%<
+ * A nonzero 'expires' field indicates that the entry should
+ * persist until that time. This allows entries found
+ * using dns_adb_findaddrinfo() to persist for a limited time
+ * even though they are not necessarily associated with a
+ * name.
+ */
+
+ ISC_LIST(dns_adblameinfo_t) lameinfo;
+ ISC_LINK(dns_adbentry_t) plink;
+};
+
+/*
+ * Internal functions (and prototypes).
+ */
+static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);
+static inline void free_adbname(dns_adb_t *, dns_adbname_t **);
+static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,
+ dns_adbentry_t *);
+static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);
+static inline dns_adblameinfo_t *new_adblameinfo(dns_adb_t *, dns_name_t *,
+ dns_rdatatype_t);
+static inline void free_adblameinfo(dns_adb_t *, dns_adblameinfo_t **);
+static inline dns_adbentry_t *new_adbentry(dns_adb_t *);
+static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);
+static inline dns_adbfind_t *new_adbfind(dns_adb_t *);
+static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **);
+static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,
+ in_port_t);
+static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);
+static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);
+static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,
+ unsigned int, int *);
+static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,
+ isc_sockaddr_t *, int *);
+static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug, isc_stdtime_t);
+static void print_dns_name(FILE *, dns_name_t *);
+static void print_namehook_list(FILE *, const char *legend,
+ dns_adbnamehooklist_t *list,
+ isc_boolean_t debug,
+ isc_stdtime_t now);
+static void print_find_list(FILE *, dns_adbname_t *);
+static void print_fetch_list(FILE *, dns_adbname_t *);
+static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *);
+static inline void inc_adb_irefcnt(dns_adb_t *);
+static inline void inc_adb_erefcnt(dns_adb_t *);
+static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
+ isc_boolean_t);
+static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
+ isc_boolean_t);
+static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);
+static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *,
+ isc_boolean_t);
+static void clean_target(dns_adb_t *, dns_name_t *);
+static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,
+ unsigned int);
+static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t);
+static void cancel_fetches_at_name(dns_adbname_t *);
+static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,
+ dns_rdatatype_t);
+static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,
+ dns_rdatatype_t);
+static inline void check_exit(dns_adb_t *);
+static void destroy(dns_adb_t *);
+static isc_boolean_t shutdown_names(dns_adb_t *);
+static isc_boolean_t shutdown_entries(dns_adb_t *);
+static inline void link_name(dns_adb_t *, int, dns_adbname_t *);
+static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *);
+static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);
+static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);
+static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t,
+ isc_boolean_t);
+static void water(void *, int);
+static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t);
+
+/*
+ * MUST NOT overlap DNS_ADBFIND_* flags!
+ */
+#define FIND_EVENT_SENT 0x40000000
+#define FIND_EVENT_FREED 0x80000000
+#define FIND_EVENTSENT(h) (((h)->flags & FIND_EVENT_SENT) != 0)
+#define FIND_EVENTFREED(h) (((h)->flags & FIND_EVENT_FREED) != 0)
+
+#define NAME_NEEDS_POKE 0x80000000
+#define NAME_IS_DEAD 0x40000000
+#define NAME_HINT_OK DNS_ADBFIND_HINTOK
+#define NAME_GLUE_OK DNS_ADBFIND_GLUEOK
+#define NAME_STARTATZONE DNS_ADBFIND_STARTATZONE
+#define NAME_DEAD(n) (((n)->flags & NAME_IS_DEAD) != 0)
+#define NAME_NEEDSPOKE(n) (((n)->flags & NAME_NEEDS_POKE) != 0)
+#define NAME_GLUEOK(n) (((n)->flags & NAME_GLUE_OK) != 0)
+#define NAME_HINTOK(n) (((n)->flags & NAME_HINT_OK) != 0)
+
+/*
+ * To the name, address classes are all that really exist. If it has a
+ * V6 address it doesn't care if it came from a AAAA query.
+ */
+#define NAME_HAS_V4(n) (!ISC_LIST_EMPTY((n)->v4))
+#define NAME_HAS_V6(n) (!ISC_LIST_EMPTY((n)->v6))
+#define NAME_HAS_ADDRS(n) (NAME_HAS_V4(n) || NAME_HAS_V6(n))
+
+/*
+ * Fetches are broken out into A and AAAA types. In some cases,
+ * however, it makes more sense to test for a particular class of fetches,
+ * like V4 or V6 above.
+ * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA
+ * are now equal to FETCH_V4 and FETCH_V6, respectively.
+ */
+#define NAME_FETCH_A(n) ((n)->fetch_a != NULL)
+#define NAME_FETCH_AAAA(n) ((n)->fetch_aaaa != NULL)
+#define NAME_FETCH_V4(n) (NAME_FETCH_A(n))
+#define NAME_FETCH_V6(n) (NAME_FETCH_AAAA(n))
+#define NAME_FETCH(n) (NAME_FETCH_V4(n) || NAME_FETCH_V6(n))
+
+/*
+ * Find options and tests to see if there are addresses on the list.
+ */
+#define FIND_WANTEVENT(fn) (((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)
+#define FIND_WANTEMPTYEVENT(fn) (((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)
+#define FIND_AVOIDFETCHES(fn) (((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \
+ != 0)
+#define FIND_STARTATZONE(fn) (((fn)->options & DNS_ADBFIND_STARTATZONE) \
+ != 0)
+#define FIND_HINTOK(fn) (((fn)->options & DNS_ADBFIND_HINTOK) != 0)
+#define FIND_GLUEOK(fn) (((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
+#define FIND_HAS_ADDRS(fn) (!ISC_LIST_EMPTY((fn)->list))
+#define FIND_RETURNLAME(fn) (((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
+
+/*
+ * These are currently used on simple unsigned ints, so they are
+ * not really associated with any particular type.
+ */
+#define WANT_INET(x) (((x) & DNS_ADBFIND_INET) != 0)
+#define WANT_INET6(x) (((x) & DNS_ADBFIND_INET6) != 0)
+
+#define EXPIRE_OK(exp, now) ((exp == INT_MAX) || (exp < now))
+
+/*
+ * Find out if the flags on a name (nf) indicate if it is a hint or
+ * glue, and compare this to the appropriate bits set in o, to see if
+ * this is ok.
+ */
+#define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))
+#define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))
+#define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))
+#define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \
+ ((o) & DNS_ADBFIND_STARTATZONE))
+
+#define ENTER_LEVEL ISC_LOG_DEBUG(50)
+#define EXIT_LEVEL ENTER_LEVEL
+#define CLEAN_LEVEL ISC_LOG_DEBUG(100)
+#define DEF_LEVEL ISC_LOG_DEBUG(5)
+#define NCACHE_LEVEL ISC_LOG_DEBUG(20)
+
+#define NCACHE_RESULT(r) ((r) == DNS_R_NCACHENXDOMAIN || \
+ (r) == DNS_R_NCACHENXRRSET)
+#define AUTH_NX(r) ((r) == DNS_R_NXDOMAIN || \
+ (r) == DNS_R_NXRRSET)
+#define NXDOMAIN_RESULT(r) ((r) == DNS_R_NXDOMAIN || \
+ (r) == DNS_R_NCACHENXDOMAIN)
+#define NXRRSET_RESULT(r) ((r) == DNS_R_NCACHENXRRSET || \
+ (r) == DNS_R_NXRRSET || \
+ (r) == DNS_R_HINTNXRRSET)
+
+/*
+ * Error state rankings.
+ */
+
+#define FIND_ERR_SUCCESS 0 /* highest rank */
+#define FIND_ERR_CANCELED 1
+#define FIND_ERR_FAILURE 2
+#define FIND_ERR_NXDOMAIN 3
+#define FIND_ERR_NXRRSET 4
+#define FIND_ERR_UNEXPECTED 5
+#define FIND_ERR_NOTFOUND 6
+#define FIND_ERR_MAX 7
+
+static const char *errnames[] = {
+ "success",
+ "canceled",
+ "failure",
+ "nxdomain",
+ "nxrrset",
+ "unexpected",
+ "not_found"
+};
+
+#define NEWERR(old, new) (ISC_MIN((old), (new)))
+
+static isc_result_t find_err_map[FIND_ERR_MAX] = {
+ ISC_R_SUCCESS,
+ ISC_R_CANCELED,
+ ISC_R_FAILURE,
+ DNS_R_NXDOMAIN,
+ DNS_R_NXRRSET,
+ ISC_R_UNEXPECTED,
+ ISC_R_NOTFOUND /* not YET found */
+};
+
+static void
+DP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
+
+static void
+DP(int level, const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ isc_log_vwrite(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
+ level, format, args);
+ va_end(args);
+}
+
+/*%
+ * Increment resolver-related statistics counters.
+ */
+static inline void
+inc_stats(dns_adb_t *adb, dns_statscounter_t counter) {
+ if (adb->view->resstats != NULL)
+ dns_generalstats_increment(adb->view->resstats, counter);
+}
+
+static inline dns_ttl_t
+ttlclamp(dns_ttl_t ttl) {
+ if (ttl < ADB_CACHE_MINIMUM)
+ ttl = ADB_CACHE_MINIMUM;
+ if (ttl > ADB_CACHE_MAXIMUM)
+ ttl = ADB_CACHE_MAXIMUM;
+
+ return (ttl);
+}
+
+/*
+ * Requires the adbname bucket be locked and that no entry buckets be locked.
+ *
+ * This code handles A and AAAA rdatasets only.
+ */
+static isc_result_t
+import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
+ isc_stdtime_t now)
+{
+ isc_result_t result;
+ dns_adb_t *adb;
+ dns_adbnamehook_t *nh;
+ dns_adbnamehook_t *anh;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ isc_sockaddr_t sockaddr;
+ dns_adbentry_t *foundentry; /* NO CLEAN UP! */
+ int addr_bucket;
+ isc_boolean_t new_addresses_added;
+ dns_rdatatype_t rdtype;
+ unsigned int findoptions;
+ dns_adbnamehooklist_t *hookhead;
+
+ INSIST(DNS_ADBNAME_VALID(adbname));
+ adb = adbname->adb;
+ INSIST(DNS_ADB_VALID(adb));
+
+ rdtype = rdataset->type;
+ INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));
+ if (rdtype == dns_rdatatype_a)
+ findoptions = DNS_ADBFIND_INET;
+ else
+ findoptions = DNS_ADBFIND_INET6;
+
+ addr_bucket = DNS_ADB_INVALIDBUCKET;
+ new_addresses_added = ISC_FALSE;
+
+ nh = NULL;
+ result = dns_rdataset_first(rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ if (rdtype == dns_rdatatype_a) {
+ INSIST(rdata.length == 4);
+ memcpy(&ina.s_addr, rdata.data, 4);
+ isc_sockaddr_fromin(&sockaddr, &ina, 0);
+ hookhead = &adbname->v4;
+ } else {
+ INSIST(rdata.length == 16);
+ memcpy(in6a.s6_addr, rdata.data, 16);
+ isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
+ hookhead = &adbname->v6;
+ }
+
+ INSIST(nh == NULL);
+ nh = new_adbnamehook(adb, NULL);
+ if (nh == NULL) {
+ adbname->partial_result |= findoptions;
+ result = ISC_R_NOMEMORY;
+ goto fail;
+ }
+
+ foundentry = find_entry_and_lock(adb, &sockaddr, &addr_bucket);
+ if (foundentry == NULL) {
+ dns_adbentry_t *entry;
+
+ entry = new_adbentry(adb);
+ if (entry == NULL) {
+ adbname->partial_result |= findoptions;
+ result = ISC_R_NOMEMORY;
+ goto fail;
+ }
+
+ entry->sockaddr = sockaddr;
+ entry->refcnt = 1;
+
+ nh->entry = entry;
+
+ link_entry(adb, addr_bucket, entry);
+ } else {
+ for (anh = ISC_LIST_HEAD(*hookhead);
+ anh != NULL;
+ anh = ISC_LIST_NEXT(anh, plink))
+ if (anh->entry == foundentry)
+ break;
+ if (anh == NULL) {
+ foundentry->refcnt++;
+ nh->entry = foundentry;
+ } else
+ free_adbnamehook(adb, &nh);
+ }
+
+ new_addresses_added = ISC_TRUE;
+ if (nh != NULL)
+ ISC_LIST_APPEND(*hookhead, nh, plink);
+ nh = NULL;
+ result = dns_rdataset_next(rdataset);
+ }
+
+ fail:
+ if (nh != NULL)
+ free_adbnamehook(adb, &nh);
+
+ if (addr_bucket != DNS_ADB_INVALIDBUCKET)
+ UNLOCK(&adb->entrylocks[addr_bucket]);
+
+ if (rdataset->trust == dns_trust_glue ||
+ rdataset->trust == dns_trust_additional)
+ rdataset->ttl = ADB_CACHE_MINIMUM;
+ else
+ rdataset->ttl = ttlclamp(rdataset->ttl);
+
+ if (rdtype == dns_rdatatype_a) {
+ DP(NCACHE_LEVEL, "expire_v4 set to MIN(%u,%u) import_rdataset",
+ adbname->expire_v4, now + rdataset->ttl);
+ adbname->expire_v4 = ISC_MIN(adbname->expire_v4,
+ now + rdataset->ttl);
+ } else {
+ DP(NCACHE_LEVEL, "expire_v6 set to MIN(%u,%u) import_rdataset",
+ adbname->expire_v6, now + rdataset->ttl);
+ adbname->expire_v6 = ISC_MIN(adbname->expire_v6,
+ now + rdataset->ttl);
+ }
+
+ if (new_addresses_added) {
+ /*
+ * Lie a little here. This is more or less so code that cares
+ * can find out if any new information was added or not.
+ */
+ return (ISC_R_SUCCESS);
+ }
+
+ return (result);
+}
+
+/*
+ * Requires the name's bucket be locked.
+ */
+static isc_boolean_t
+kill_name(dns_adbname_t **n, isc_eventtype_t ev, isc_boolean_t is_purge) {
+ dns_adbname_t *name;
+ isc_boolean_t result = ISC_FALSE;
+ isc_boolean_t result4, result6;
+ dns_adb_t *adb;
+
+ INSIST(n != NULL);
+ name = *n;
+ *n = NULL;
+ INSIST(DNS_ADBNAME_VALID(name));
+ adb = name->adb;
+ INSIST(DNS_ADB_VALID(adb));
+
+ DP(DEF_LEVEL, "killing name %p", name);
+
+ /*
+ * If we're dead already, just check to see if we should go
+ * away now or not.
+ */
+ if (NAME_DEAD(name) && !NAME_FETCH(name)) {
+ result = unlink_name(adb, name);
+ free_adbname(adb, &name);
+ if (result)
+ result = dec_adb_irefcnt(adb);
+ return (result);
+ }
+
+ /*
+ * Clean up the name's various lists. These two are destructive
+ * in that they will always empty the list.
+ */
+ clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK);
+ result4 = clean_namehooks(adb, &name->v4, is_purge);
+ result6 = clean_namehooks(adb, &name->v6, is_purge);
+ clean_target(adb, &name->target);
+ result = ISC_TF(result4 || result6);
+
+ /*
+ * If fetches are running, cancel them. If none are running, we can
+ * just kill the name here.
+ */
+ if (!NAME_FETCH(name)) {
+ INSIST(result == ISC_FALSE);
+ result = unlink_name(adb, name);
+ free_adbname(adb, &name);
+ if (result)
+ result = dec_adb_irefcnt(adb);
+ } else {
+ name->flags |= NAME_IS_DEAD;
+ cancel_fetches_at_name(name);
+ }
+ return (result);
+}
+
+/*
+ * Requires the name's bucket be locked and no entry buckets be locked.
+ */
+static isc_boolean_t
+check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now) {
+ dns_adb_t *adb;
+ isc_boolean_t result4 = ISC_FALSE;
+ isc_boolean_t result6 = ISC_FALSE;
+
+ INSIST(DNS_ADBNAME_VALID(name));
+ adb = name->adb;
+ INSIST(DNS_ADB_VALID(adb));
+
+ /*
+ * Check to see if we need to remove the v4 addresses
+ */
+ if (!NAME_FETCH_V4(name) && EXPIRE_OK(name->expire_v4, now)) {
+ if (NAME_HAS_V4(name)) {
+ DP(DEF_LEVEL, "expiring v4 for name %p", name);
+ result4 = clean_namehooks(adb, &name->v4, ISC_FALSE);
+ name->partial_result &= ~DNS_ADBFIND_INET;
+ }
+ name->expire_v4 = INT_MAX;
+ name->fetch_err = FIND_ERR_UNEXPECTED;
+ }
+
+ /*
+ * Check to see if we need to remove the v6 addresses
+ */
+ if (!NAME_FETCH_V6(name) && EXPIRE_OK(name->expire_v6, now)) {
+ if (NAME_HAS_V6(name)) {
+ DP(DEF_LEVEL, "expiring v6 for name %p", name);
+ result6 = clean_namehooks(adb, &name->v6, ISC_FALSE);
+ name->partial_result &= ~DNS_ADBFIND_INET6;
+ }
+ name->expire_v6 = INT_MAX;
+ name->fetch6_err = FIND_ERR_UNEXPECTED;
+ }
+
+ /*
+ * Check to see if we need to remove the alias target.
+ */
+ if (EXPIRE_OK(name->expire_target, now)) {
+ clean_target(adb, &name->target);
+ name->expire_target = INT_MAX;
+ }
+ return (ISC_TF(result4 || result6));
+}
+
+/*
+ * Requires the name's bucket be locked.
+ */
+static inline void
+link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) {
+ INSIST(name->lock_bucket == DNS_ADB_INVALIDBUCKET);
+
+ ISC_LIST_PREPEND(adb->names[bucket], name, plink);
+ name->lock_bucket = bucket;
+ adb->name_refcnt[bucket]++;
+}
+
+/*
+ * Requires the name's bucket be locked.
+ */
+static inline isc_boolean_t
+unlink_name(dns_adb_t *adb, dns_adbname_t *name) {
+ int bucket;
+ isc_boolean_t result = ISC_FALSE;
+
+ bucket = name->lock_bucket;
+ INSIST(bucket != DNS_ADB_INVALIDBUCKET);
+
+ ISC_LIST_UNLINK(adb->names[bucket], name, plink);
+ name->lock_bucket = DNS_ADB_INVALIDBUCKET;
+ INSIST(adb->name_refcnt[bucket] > 0);
+ adb->name_refcnt[bucket]--;
+ if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0)
+ result = ISC_TRUE;
+ return (result);
+}
+
+/*
+ * Requires the entry's bucket be locked.
+ */
+static inline void
+link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) {
+ ISC_LIST_PREPEND(adb->entries[bucket], entry, plink);
+ entry->lock_bucket = bucket;
+ adb->entry_refcnt[bucket]++;
+}
+
+/*
+ * Requires the entry's bucket be locked.
+ */
+static inline isc_boolean_t
+unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) {
+ int bucket;
+ isc_boolean_t result = ISC_FALSE;
+
+ bucket = entry->lock_bucket;
+ INSIST(bucket != DNS_ADB_INVALIDBUCKET);
+
+ ISC_LIST_UNLINK(adb->entries[bucket], entry, plink);
+ entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
+ INSIST(adb->entry_refcnt[bucket] > 0);
+ adb->entry_refcnt[bucket]--;
+ if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0)
+ result = ISC_TRUE;
+ return (result);
+}
+
+static inline void
+violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) {
+ if (isc_mutex_trylock(want) != ISC_R_SUCCESS) {
+ UNLOCK(have);
+ LOCK(want);
+ LOCK(have);
+ }
+}
+
+/*
+ * The ADB _MUST_ be locked before calling. Also, exit conditions must be
+ * checked after calling this function.
+ */
+static isc_boolean_t
+shutdown_names(dns_adb_t *adb) {
+ int bucket;
+ isc_boolean_t result = ISC_FALSE;
+ dns_adbname_t *name;
+ dns_adbname_t *next_name;
+
+ for (bucket = 0; bucket < NBUCKETS; bucket++) {
+ LOCK(&adb->namelocks[bucket]);
+ adb->name_sd[bucket] = ISC_TRUE;
+
+ name = ISC_LIST_HEAD(adb->names[bucket]);
+ if (name == NULL) {
+ /*
+ * This bucket has no names. We must decrement the
+ * irefcnt ourselves, since it will not be
+ * automatically triggered by a name being unlinked.
+ */
+ INSIST(result == ISC_FALSE);
+ result = dec_adb_irefcnt(adb);
+ } else {
+ /*
+ * Run through the list. For each name, clean up finds
+ * found there, and cancel any fetches running. When
+ * all the fetches are canceled, the name will destroy
+ * itself.
+ */
+ while (name != NULL) {
+ next_name = ISC_LIST_NEXT(name, plink);
+ INSIST(result == ISC_FALSE);
+ result = kill_name(&name,
+ DNS_EVENT_ADBSHUTDOWN,
+ ISC_FALSE);
+ name = next_name;
+ }
+ }
+
+ UNLOCK(&adb->namelocks[bucket]);
+ }
+ return (result);
+}
+
+/*
+ * The ADB _MUST_ be locked before calling. Also, exit conditions must be
+ * checked after calling this function.
+ */
+static isc_boolean_t
+shutdown_entries(dns_adb_t *adb) {
+ int bucket;
+ isc_boolean_t result = ISC_FALSE;
+ dns_adbentry_t *entry;
+ dns_adbentry_t *next_entry;
+
+ for (bucket = 0; bucket < NBUCKETS; bucket++) {
+ LOCK(&adb->entrylocks[bucket]);
+ adb->entry_sd[bucket] = ISC_TRUE;
+
+ entry = ISC_LIST_HEAD(adb->entries[bucket]);
+ if (entry == NULL) {
+ /*
+ * This bucket has no entries. We must decrement the
+ * irefcnt ourselves, since it will not be
+ * automatically triggered by an entry being unlinked.
+ */
+ result = dec_adb_irefcnt(adb);
+ } else {
+ /*
+ * Run through the list. Cleanup any entries not
+ * associated with names, and which are not in use.
+ */
+ while (entry != NULL) {
+ next_entry = ISC_LIST_NEXT(entry, plink);
+ if (entry->refcnt == 0 &&
+ entry->expires != 0) {
+ result = unlink_entry(adb, entry);
+ free_adbentry(adb, &entry);
+ if (result)
+ result = dec_adb_irefcnt(adb);
+ }
+ entry = next_entry;
+ }
+ }
+
+ UNLOCK(&adb->entrylocks[bucket]);
+ }
+ return (result);
+}
+
+/*
+ * Name bucket must be locked
+ */
+static void
+cancel_fetches_at_name(dns_adbname_t *name) {
+ if (NAME_FETCH_A(name))
+ dns_resolver_cancelfetch(name->fetch_a->fetch);
+
+ if (NAME_FETCH_AAAA(name))
+ dns_resolver_cancelfetch(name->fetch_aaaa->fetch);
+}
+
+/*
+ * Assumes the name bucket is locked.
+ */
+static isc_boolean_t
+clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks,
+ isc_boolean_t is_purge)
+{
+ dns_adbentry_t *entry;
+ dns_adbnamehook_t *namehook;
+ int addr_bucket;
+ isc_boolean_t result = ISC_FALSE;
+
+ addr_bucket = DNS_ADB_INVALIDBUCKET;
+ namehook = ISC_LIST_HEAD(*namehooks);
+ while (namehook != NULL) {
+ INSIST(DNS_ADBNAMEHOOK_VALID(namehook));
+
+ /*
+ * Clean up the entry if needed.
+ */
+ entry = namehook->entry;
+ if (entry != NULL) {
+ INSIST(DNS_ADBENTRY_VALID(entry));
+
+ if (addr_bucket != entry->lock_bucket) {
+ if (addr_bucket != DNS_ADB_INVALIDBUCKET)
+ UNLOCK(&adb->entrylocks[addr_bucket]);
+ addr_bucket = entry->lock_bucket;
+ LOCK(&adb->entrylocks[addr_bucket]);
+ }
+
+ /*
+ * If we are in an overmem situation, force expiration
+ * so that # of names and # of entries are well
+ * balanced.
+ */
+ if (is_purge)
+ entry->expires = 0;
+ result = dec_entry_refcnt(adb, entry, ISC_FALSE);
+ }
+
+ /*
+ * Free the namehook
+ */
+ namehook->entry = NULL;
+ ISC_LIST_UNLINK(*namehooks, namehook, plink);
+ free_adbnamehook(adb, &namehook);
+
+ namehook = ISC_LIST_HEAD(*namehooks);
+ }
+
+ if (addr_bucket != DNS_ADB_INVALIDBUCKET)
+ UNLOCK(&adb->entrylocks[addr_bucket]);
+ return (result);
+}
+
+static void
+clean_target(dns_adb_t *adb, dns_name_t *target) {
+ if (dns_name_countlabels(target) > 0) {
+ dns_name_free(target, adb->mctx);
+ dns_name_init(target, NULL);
+ }
+}
+
+static isc_result_t
+set_target(dns_adb_t *adb, dns_name_t *name, dns_name_t *fname,
+ dns_rdataset_t *rdataset, dns_name_t *target)
+{
+ isc_result_t result;
+ dns_namereln_t namereln;
+ unsigned int nlabels;
+ int order;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_fixedname_t fixed1, fixed2;
+ dns_name_t *prefix, *new_target;
+
+ REQUIRE(dns_name_countlabels(target) == 0);
+
+ if (rdataset->type == dns_rdatatype_cname) {
+ dns_rdata_cname_t cname;
+
+ /*
+ * Copy the CNAME's target into the target name.
+ */
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_name_dup(&cname.cname, adb->mctx, target);
+ dns_rdata_freestruct(&cname);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else {
+ dns_rdata_dname_t dname;
+
+ INSIST(rdataset->type == dns_rdatatype_dname);
+ namereln = dns_name_fullcompare(name, fname, &order, &nlabels);
+ INSIST(namereln == dns_namereln_subdomain);
+ /*
+ * Get the target name of the DNAME.
+ */
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &dname, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ /*
+ * Construct the new target name.
+ */
+ dns_fixedname_init(&fixed1);
+ prefix = dns_fixedname_name(&fixed1);
+ dns_fixedname_init(&fixed2);
+ new_target = dns_fixedname_name(&fixed2);
+ dns_name_split(name, nlabels, prefix, NULL);
+ result = dns_name_concatenate(prefix, &dname.dname, new_target,
+ NULL);
+ dns_rdata_freestruct(&dname);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_name_dup(new_target, adb->mctx, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Assumes nothing is locked, since this is called by the client.
+ */
+static void
+event_free(isc_event_t *event) {
+ dns_adbfind_t *find;
+
+ INSIST(event != NULL);
+ find = event->ev_destroy_arg;
+ INSIST(DNS_ADBFIND_VALID(find));
+
+ LOCK(&find->lock);
+ find->flags |= FIND_EVENT_FREED;
+ event->ev_destroy_arg = NULL;
+ UNLOCK(&find->lock);
+}
+
+/*
+ * Assumes the name bucket is locked.
+ */
+static void
+clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype,
+ unsigned int addrs)
+{
+ isc_event_t *ev;
+ isc_task_t *task;
+ dns_adbfind_t *find;
+ dns_adbfind_t *next_find;
+ isc_boolean_t process;
+ unsigned int wanted, notify;
+
+ DP(ENTER_LEVEL,
+ "ENTER clean_finds_at_name, name %p, evtype %08x, addrs %08x",
+ name, evtype, addrs);
+
+ find = ISC_LIST_HEAD(name->finds);
+ while (find != NULL) {
+ LOCK(&find->lock);
+ next_find = ISC_LIST_NEXT(find, plink);
+
+ process = ISC_FALSE;
+ wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
+ notify = wanted & addrs;
+
+ switch (evtype) {
+ case DNS_EVENT_ADBMOREADDRESSES:
+ DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBMOREADDRESSES");
+ if ((notify) != 0) {
+ find->flags &= ~addrs;
+ process = ISC_TRUE;
+ }
+ break;
+ case DNS_EVENT_ADBNOMOREADDRESSES:
+ DP(ISC_LOG_DEBUG(3), "DNS_EVENT_ADBNOMOREADDRESSES");
+ find->flags &= ~addrs;
+ wanted = find->flags & DNS_ADBFIND_ADDRESSMASK;
+ if (wanted == 0)
+ process = ISC_TRUE;
+ break;
+ default:
+ find->flags &= ~addrs;
+ process = ISC_TRUE;
+ }
+
+ if (process) {
+ DP(DEF_LEVEL, "cfan: processing find %p", find);
+ /*
+ * Unlink the find from the name, letting the caller
+ * call dns_adb_destroyfind() on it to clean it up
+ * later.
+ */
+ ISC_LIST_UNLINK(name->finds, find, plink);
+ find->adbname = NULL;
+ find->name_bucket = DNS_ADB_INVALIDBUCKET;
+
+ INSIST(!FIND_EVENTSENT(find));
+
+ ev = &find->event;
+ task = ev->ev_sender;
+ ev->ev_sender = find;
+ find->result_v4 = find_err_map[name->fetch_err];
+ find->result_v6 = find_err_map[name->fetch6_err];
+ ev->ev_type = evtype;
+ ev->ev_destroy = event_free;
+ ev->ev_destroy_arg = find;
+
+ DP(DEF_LEVEL,
+ "sending event %p to task %p for find %p",
+ ev, task, find);
+
+ isc_task_sendanddetach(&task, (isc_event_t **)&ev);
+ } else {
+ DP(DEF_LEVEL, "cfan: skipping find %p", find);
+ }
+
+ UNLOCK(&find->lock);
+ find = next_find;
+ }
+
+ DP(ENTER_LEVEL, "EXIT clean_finds_at_name, name %p", name);
+}
+
+static inline void
+check_exit(dns_adb_t *adb) {
+ isc_event_t *event;
+ /*
+ * The caller must be holding the adb lock.
+ */
+ if (adb->shutting_down) {
+ /*
+ * If there aren't any external references either, we're
+ * done. Send the control event to initiate shutdown.
+ */
+ INSIST(!adb->cevent_sent); /* Sanity check. */
+ event = &adb->cevent;
+ isc_task_send(adb->task, &event);
+ adb->cevent_sent = ISC_TRUE;
+ }
+}
+
+static inline isc_boolean_t
+dec_adb_irefcnt(dns_adb_t *adb) {
+ isc_event_t *event;
+ isc_task_t *etask;
+ isc_boolean_t result = ISC_FALSE;
+
+ LOCK(&adb->reflock);
+
+ INSIST(adb->irefcnt > 0);
+ adb->irefcnt--;
+
+ if (adb->irefcnt == 0) {
+ event = ISC_LIST_HEAD(adb->whenshutdown);
+ while (event != NULL) {
+ ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link);
+ etask = event->ev_sender;
+ event->ev_sender = adb;
+ isc_task_sendanddetach(&etask, &event);
+ event = ISC_LIST_HEAD(adb->whenshutdown);
+ }
+ }
+
+ if (adb->irefcnt == 0 && adb->erefcnt == 0)
+ result = ISC_TRUE;
+ UNLOCK(&adb->reflock);
+ return (result);
+}
+
+static inline void
+inc_adb_irefcnt(dns_adb_t *adb) {
+ LOCK(&adb->reflock);
+ adb->irefcnt++;
+ UNLOCK(&adb->reflock);
+}
+
+static inline void
+inc_adb_erefcnt(dns_adb_t *adb) {
+ LOCK(&adb->reflock);
+ adb->erefcnt++;
+ UNLOCK(&adb->reflock);
+}
+
+static inline void
+inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
+ int bucket;
+
+ bucket = entry->lock_bucket;
+
+ if (lock)
+ LOCK(&adb->entrylocks[bucket]);
+
+ entry->refcnt++;
+
+ if (lock)
+ UNLOCK(&adb->entrylocks[bucket]);
+}
+
+static inline isc_boolean_t
+dec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) {
+ int bucket;
+ isc_boolean_t destroy_entry;
+ isc_boolean_t result = ISC_FALSE;
+
+ bucket = entry->lock_bucket;
+
+ if (lock)
+ LOCK(&adb->entrylocks[bucket]);
+
+ INSIST(entry->refcnt > 0);
+ entry->refcnt--;
+
+ destroy_entry = ISC_FALSE;
+ if (entry->refcnt == 0 &&
+ (adb->entry_sd[bucket] || entry->expires == 0)) {
+ destroy_entry = ISC_TRUE;
+ result = unlink_entry(adb, entry);
+ }
+
+ if (lock)
+ UNLOCK(&adb->entrylocks[bucket]);
+
+ if (!destroy_entry)
+ return (result);
+
+ entry->lock_bucket = DNS_ADB_INVALIDBUCKET;
+
+ free_adbentry(adb, &entry);
+ if (result)
+ result = dec_adb_irefcnt(adb);
+
+ return (result);
+}
+
+static inline dns_adbname_t *
+new_adbname(dns_adb_t *adb, dns_name_t *dnsname) {
+ dns_adbname_t *name;
+
+ name = isc_mempool_get(adb->nmp);
+ if (name == NULL)
+ return (NULL);
+
+ dns_name_init(&name->name, NULL);
+ if (dns_name_dup(dnsname, adb->mctx, &name->name) != ISC_R_SUCCESS) {
+ isc_mempool_put(adb->nmp, name);
+ return (NULL);
+ }
+ dns_name_init(&name->target, NULL);
+ name->magic = DNS_ADBNAME_MAGIC;
+ name->adb = adb;
+ name->partial_result = 0;
+ name->flags = 0;
+ name->expire_v4 = INT_MAX;
+ name->expire_v6 = INT_MAX;
+ name->expire_target = INT_MAX;
+ name->chains = 0;
+ name->lock_bucket = DNS_ADB_INVALIDBUCKET;
+ ISC_LIST_INIT(name->v4);
+ ISC_LIST_INIT(name->v6);
+ name->fetch_a = NULL;
+ name->fetch_aaaa = NULL;
+ name->fetch_err = FIND_ERR_UNEXPECTED;
+ name->fetch6_err = FIND_ERR_UNEXPECTED;
+ ISC_LIST_INIT(name->finds);
+ ISC_LINK_INIT(name, plink);
+
+ return (name);
+}
+
+static inline void
+free_adbname(dns_adb_t *adb, dns_adbname_t **name) {
+ dns_adbname_t *n;
+
+ INSIST(name != NULL && DNS_ADBNAME_VALID(*name));
+ n = *name;
+ *name = NULL;
+
+ INSIST(!NAME_HAS_V4(n));
+ INSIST(!NAME_HAS_V6(n));
+ INSIST(!NAME_FETCH(n));
+ INSIST(ISC_LIST_EMPTY(n->finds));
+ INSIST(!ISC_LINK_LINKED(n, plink));
+ INSIST(n->lock_bucket == DNS_ADB_INVALIDBUCKET);
+ INSIST(n->adb == adb);
+
+ n->magic = 0;
+ dns_name_free(&n->name, adb->mctx);
+
+ isc_mempool_put(adb->nmp, n);
+}
+
+static inline dns_adbnamehook_t *
+new_adbnamehook(dns_adb_t *adb, dns_adbentry_t *entry) {
+ dns_adbnamehook_t *nh;
+
+ nh = isc_mempool_get(adb->nhmp);
+ if (nh == NULL)
+ return (NULL);
+
+ nh->magic = DNS_ADBNAMEHOOK_MAGIC;
+ nh->entry = entry;
+ ISC_LINK_INIT(nh, plink);
+
+ return (nh);
+}
+
+static inline void
+free_adbnamehook(dns_adb_t *adb, dns_adbnamehook_t **namehook) {
+ dns_adbnamehook_t *nh;
+
+ INSIST(namehook != NULL && DNS_ADBNAMEHOOK_VALID(*namehook));
+ nh = *namehook;
+ *namehook = NULL;
+
+ INSIST(nh->entry == NULL);
+ INSIST(!ISC_LINK_LINKED(nh, plink));
+
+ nh->magic = 0;
+ isc_mempool_put(adb->nhmp, nh);
+}
+
+static inline dns_adblameinfo_t *
+new_adblameinfo(dns_adb_t *adb, dns_name_t *qname, dns_rdatatype_t qtype) {
+ dns_adblameinfo_t *li;
+
+ li = isc_mempool_get(adb->limp);
+ if (li == NULL)
+ return (NULL);
+
+ dns_name_init(&li->qname, NULL);
+ if (dns_name_dup(qname, adb->mctx, &li->qname) != ISC_R_SUCCESS) {
+ isc_mempool_put(adb->limp, li);
+ return (NULL);
+ }
+ li->magic = DNS_ADBLAMEINFO_MAGIC;
+ li->lame_timer = 0;
+ li->qtype = qtype;
+ ISC_LINK_INIT(li, plink);
+
+ return (li);
+}
+
+static inline void
+free_adblameinfo(dns_adb_t *adb, dns_adblameinfo_t **lameinfo) {
+ dns_adblameinfo_t *li;
+
+ INSIST(lameinfo != NULL && DNS_ADBLAMEINFO_VALID(*lameinfo));
+ li = *lameinfo;
+ *lameinfo = NULL;
+
+ INSIST(!ISC_LINK_LINKED(li, plink));
+
+ dns_name_free(&li->qname, adb->mctx);
+
+ li->magic = 0;
+
+ isc_mempool_put(adb->limp, li);
+}
+
+static inline dns_adbentry_t *
+new_adbentry(dns_adb_t *adb) {
+ dns_adbentry_t *e;
+ isc_uint32_t r;
+
+ e = isc_mempool_get(adb->emp);
+ if (e == NULL)
+ return (NULL);
+
+ e->magic = DNS_ADBENTRY_MAGIC;
+ e->lock_bucket = DNS_ADB_INVALIDBUCKET;
+ e->refcnt = 0;
+ e->flags = 0;
+ isc_random_get(&r);
+ e->srtt = (r & 0x1f) + 1;
+ e->expires = 0;
+ ISC_LIST_INIT(e->lameinfo);
+ ISC_LINK_INIT(e, plink);
+
+ return (e);
+}
+
+static inline void
+free_adbentry(dns_adb_t *adb, dns_adbentry_t **entry) {
+ dns_adbentry_t *e;
+ dns_adblameinfo_t *li;
+
+ INSIST(entry != NULL && DNS_ADBENTRY_VALID(*entry));
+ e = *entry;
+ *entry = NULL;
+
+ INSIST(e->lock_bucket == DNS_ADB_INVALIDBUCKET);
+ INSIST(e->refcnt == 0);
+ INSIST(!ISC_LINK_LINKED(e, plink));
+
+ e->magic = 0;
+
+ li = ISC_LIST_HEAD(e->lameinfo);
+ while (li != NULL) {
+ ISC_LIST_UNLINK(e->lameinfo, li, plink);
+ free_adblameinfo(adb, &li);
+ li = ISC_LIST_HEAD(e->lameinfo);
+ }
+
+ isc_mempool_put(adb->emp, e);
+}
+
+static inline dns_adbfind_t *
+new_adbfind(dns_adb_t *adb) {
+ dns_adbfind_t *h;
+ isc_result_t result;
+
+ h = isc_mempool_get(adb->ahmp);
+ if (h == NULL)
+ return (NULL);
+
+ /*
+ * Public members.
+ */
+ h->magic = 0;
+ h->adb = adb;
+ h->partial_result = 0;
+ h->options = 0;
+ h->flags = 0;
+ h->result_v4 = ISC_R_UNEXPECTED;
+ h->result_v6 = ISC_R_UNEXPECTED;
+ ISC_LINK_INIT(h, publink);
+ ISC_LINK_INIT(h, plink);
+ ISC_LIST_INIT(h->list);
+ h->adbname = NULL;
+ h->name_bucket = DNS_ADB_INVALIDBUCKET;
+
+ /*
+ * private members
+ */
+ result = isc_mutex_init(&h->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mempool_put(adb->ahmp, h);
+ return (NULL);
+ }
+
+ ISC_EVENT_INIT(&h->event, sizeof(isc_event_t), 0, 0, 0, NULL, NULL,
+ NULL, NULL, h);
+
+ inc_adb_irefcnt(adb);
+ h->magic = DNS_ADBFIND_MAGIC;
+ return (h);
+}
+
+static inline dns_adbfetch_t *
+new_adbfetch(dns_adb_t *adb) {
+ dns_adbfetch_t *f;
+
+ f = isc_mempool_get(adb->afmp);
+ if (f == NULL)
+ return (NULL);
+
+ f->magic = 0;
+ f->namehook = NULL;
+ f->entry = NULL;
+ f->fetch = NULL;
+
+ f->namehook = new_adbnamehook(adb, NULL);
+ if (f->namehook == NULL)
+ goto err;
+
+ f->entry = new_adbentry(adb);
+ if (f->entry == NULL)
+ goto err;
+
+ dns_rdataset_init(&f->rdataset);
+
+ f->magic = DNS_ADBFETCH_MAGIC;
+
+ return (f);
+
+ err:
+ if (f->namehook != NULL)
+ free_adbnamehook(adb, &f->namehook);
+ if (f->entry != NULL)
+ free_adbentry(adb, &f->entry);
+ isc_mempool_put(adb->afmp, f);
+ return (NULL);
+}
+
+static inline void
+free_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) {
+ dns_adbfetch_t *f;
+
+ INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch));
+ f = *fetch;
+ *fetch = NULL;
+
+ f->magic = 0;
+
+ if (f->namehook != NULL)
+ free_adbnamehook(adb, &f->namehook);
+ if (f->entry != NULL)
+ free_adbentry(adb, &f->entry);
+
+ if (dns_rdataset_isassociated(&f->rdataset))
+ dns_rdataset_disassociate(&f->rdataset);
+
+ isc_mempool_put(adb->afmp, f);
+}
+
+static inline isc_boolean_t
+free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) {
+ dns_adbfind_t *find;
+
+ INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp));
+ find = *findp;
+ *findp = NULL;
+
+ INSIST(!FIND_HAS_ADDRS(find));
+ INSIST(!ISC_LINK_LINKED(find, publink));
+ INSIST(!ISC_LINK_LINKED(find, plink));
+ INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET);
+ INSIST(find->adbname == NULL);
+
+ find->magic = 0;
+
+ DESTROYLOCK(&find->lock);
+ isc_mempool_put(adb->ahmp, find);
+ return (dec_adb_irefcnt(adb));
+}
+
+/*
+ * Copy bits from the entry into the newly allocated addrinfo. The entry
+ * must be locked, and the reference count must be bumped up by one
+ * if this function returns a valid pointer.
+ */
+static inline dns_adbaddrinfo_t *
+new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {
+ dns_adbaddrinfo_t *ai;
+
+ ai = isc_mempool_get(adb->aimp);
+ if (ai == NULL)
+ return (NULL);
+
+ ai->magic = DNS_ADBADDRINFO_MAGIC;
+ ai->sockaddr = entry->sockaddr;
+ isc_sockaddr_setport(&ai->sockaddr, port);
+ ai->srtt = entry->srtt;
+ ai->flags = entry->flags;
+ ai->entry = entry;
+ ISC_LINK_INIT(ai, publink);
+
+ return (ai);
+}
+
+static inline void
+free_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {
+ dns_adbaddrinfo_t *ai;
+
+ INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo));
+ ai = *ainfo;
+ *ainfo = NULL;
+
+ INSIST(ai->entry == NULL);
+ INSIST(!ISC_LINK_LINKED(ai, publink));
+
+ ai->magic = 0;
+
+ isc_mempool_put(adb->aimp, ai);
+}
+
+/*
+ * Search for the name. NOTE: The bucket is kept locked on both
+ * success and failure, so it must always be unlocked by the caller!
+ *
+ * On the first call to this function, *bucketp must be set to
+ * DNS_ADB_INVALIDBUCKET.
+ */
+static inline dns_adbname_t *
+find_name_and_lock(dns_adb_t *adb, dns_name_t *name,
+ unsigned int options, int *bucketp)
+{
+ dns_adbname_t *adbname;
+ int bucket;
+
+ bucket = dns_name_fullhash(name, ISC_FALSE) % NBUCKETS;
+
+ if (*bucketp == DNS_ADB_INVALIDBUCKET) {
+ LOCK(&adb->namelocks[bucket]);
+ *bucketp = bucket;
+ } else if (*bucketp != bucket) {
+ UNLOCK(&adb->namelocks[*bucketp]);
+ LOCK(&adb->namelocks[bucket]);
+ *bucketp = bucket;
+ }
+
+ adbname = ISC_LIST_HEAD(adb->names[bucket]);
+ while (adbname != NULL) {
+ if (!NAME_DEAD(adbname)) {
+ if (dns_name_equal(name, &adbname->name)
+ && GLUEHINT_OK(adbname, options)
+ && STARTATZONE_MATCHES(adbname, options))
+ return (adbname);
+ }
+ adbname = ISC_LIST_NEXT(adbname, plink);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Search for the address. NOTE: The bucket is kept locked on both
+ * success and failure, so it must always be unlocked by the caller.
+ *
+ * On the first call to this function, *bucketp must be set to
+ * DNS_ADB_INVALIDBUCKET. This will cause a lock to occur. On
+ * later calls (within the same "lock path") it can be left alone, so
+ * if this function is called multiple times locking is only done if
+ * the bucket changes.
+ */
+static inline dns_adbentry_t *
+find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp) {
+ dns_adbentry_t *entry;
+ int bucket;
+
+ bucket = isc_sockaddr_hash(addr, ISC_TRUE) % NBUCKETS;
+
+ if (*bucketp == DNS_ADB_INVALIDBUCKET) {
+ LOCK(&adb->entrylocks[bucket]);
+ *bucketp = bucket;
+ } else if (*bucketp != bucket) {
+ UNLOCK(&adb->entrylocks[*bucketp]);
+ LOCK(&adb->entrylocks[bucket]);
+ *bucketp = bucket;
+ }
+
+ entry = ISC_LIST_HEAD(adb->entries[bucket]);
+ while (entry != NULL) {
+ if (isc_sockaddr_equal(addr, &entry->sockaddr))
+ return (entry);
+ entry = ISC_LIST_NEXT(entry, plink);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Entry bucket MUST be locked!
+ */
+static isc_boolean_t
+entry_is_lame(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *qname,
+ dns_rdatatype_t qtype, isc_stdtime_t now)
+{
+ dns_adblameinfo_t *li, *next_li;
+ isc_boolean_t is_bad;
+
+ is_bad = ISC_FALSE;
+
+ li = ISC_LIST_HEAD(entry->lameinfo);
+ if (li == NULL)
+ return (ISC_FALSE);
+ while (li != NULL) {
+ next_li = ISC_LIST_NEXT(li, plink);
+
+ /*
+ * Has the entry expired?
+ */
+ if (li->lame_timer < now) {
+ ISC_LIST_UNLINK(entry->lameinfo, li, plink);
+ free_adblameinfo(adb, &li);
+ }
+
+ /*
+ * Order tests from least to most expensive.
+ *
+ * We do not break out of the main loop here as
+ * we use the loop for house keeping.
+ */
+ if (li != NULL && !is_bad && li->qtype == qtype &&
+ dns_name_equal(qname, &li->qname))
+ is_bad = ISC_TRUE;
+
+ li = next_li;
+ }
+
+ return (is_bad);
+}
+
+static void
+copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
+ dns_rdatatype_t qtype, dns_adbname_t *name,
+ isc_stdtime_t now)
+{
+ dns_adbnamehook_t *namehook;
+ dns_adbaddrinfo_t *addrinfo;
+ dns_adbentry_t *entry;
+ int bucket;
+
+ bucket = DNS_ADB_INVALIDBUCKET;
+
+ if (find->options & DNS_ADBFIND_INET) {
+ namehook = ISC_LIST_HEAD(name->v4);
+ while (namehook != NULL) {
+ entry = namehook->entry;
+ bucket = entry->lock_bucket;
+ LOCK(&adb->entrylocks[bucket]);
+
+ if (!FIND_RETURNLAME(find)
+ && entry_is_lame(adb, entry, qname, qtype, now)) {
+ find->options |= DNS_ADBFIND_LAMEPRUNED;
+ goto nextv4;
+ }
+ addrinfo = new_adbaddrinfo(adb, entry, find->port);
+ if (addrinfo == NULL) {
+ find->partial_result |= DNS_ADBFIND_INET;
+ goto out;
+ }
+ /*
+ * Found a valid entry. Add it to the find's list.
+ */
+ inc_entry_refcnt(adb, entry, ISC_FALSE);
+ ISC_LIST_APPEND(find->list, addrinfo, publink);
+ addrinfo = NULL;
+ nextv4:
+ UNLOCK(&adb->entrylocks[bucket]);
+ bucket = DNS_ADB_INVALIDBUCKET;
+ namehook = ISC_LIST_NEXT(namehook, plink);
+ }
+ }
+
+ if (find->options & DNS_ADBFIND_INET6) {
+ namehook = ISC_LIST_HEAD(name->v6);
+ while (namehook != NULL) {
+ entry = namehook->entry;
+ bucket = entry->lock_bucket;
+ LOCK(&adb->entrylocks[bucket]);
+
+ if (!FIND_RETURNLAME(find)
+ && entry_is_lame(adb, entry, qname, qtype, now)) {
+ find->options |= DNS_ADBFIND_LAMEPRUNED;
+ goto nextv6;
+ }
+ addrinfo = new_adbaddrinfo(adb, entry, find->port);
+ if (addrinfo == NULL) {
+ find->partial_result |= DNS_ADBFIND_INET6;
+ goto out;
+ }
+ /*
+ * Found a valid entry. Add it to the find's list.
+ */
+ inc_entry_refcnt(adb, entry, ISC_FALSE);
+ ISC_LIST_APPEND(find->list, addrinfo, publink);
+ addrinfo = NULL;
+ nextv6:
+ UNLOCK(&adb->entrylocks[bucket]);
+ bucket = DNS_ADB_INVALIDBUCKET;
+ namehook = ISC_LIST_NEXT(namehook, plink);
+ }
+ }
+
+ out:
+ if (bucket != DNS_ADB_INVALIDBUCKET)
+ UNLOCK(&adb->entrylocks[bucket]);
+}
+
+static void
+shutdown_task(isc_task_t *task, isc_event_t *ev) {
+ dns_adb_t *adb;
+
+ UNUSED(task);
+
+ adb = ev->ev_arg;
+ INSIST(DNS_ADB_VALID(adb));
+
+ isc_event_free(&ev);
+ /*
+ * Wait for lock around check_exit() call to be released.
+ */
+ LOCK(&adb->lock);
+ UNLOCK(&adb->lock);
+ destroy(adb);
+}
+
+/*
+ * Name bucket must be locked; adb may be locked; no other locks held.
+ */
+static isc_boolean_t
+check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {
+ dns_adbname_t *name;
+ isc_boolean_t result = ISC_FALSE;
+
+ INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep));
+ name = *namep;
+
+ if (NAME_HAS_V4(name) || NAME_HAS_V6(name))
+ return (result);
+ if (NAME_FETCH(name))
+ return (result);
+ if (!EXPIRE_OK(name->expire_v4, now))
+ return (result);
+ if (!EXPIRE_OK(name->expire_v6, now))
+ return (result);
+ if (!EXPIRE_OK(name->expire_target, now))
+ return (result);
+
+ /*
+ * The name is empty. Delete it.
+ */
+ result = kill_name(&name, DNS_EVENT_ADBEXPIRED, ISC_FALSE);
+ *namep = NULL;
+
+ /*
+ * Our caller, or one of its callers, will be calling check_exit() at
+ * some point, so we don't need to do it here.
+ */
+ return (result);
+}
+
+/*%
+ * Examine the tail entry of the LRU list to see if it expires or is stale
+ * (unused for some period); if so, the name entry will be freed. If the ADB
+ * is in the overmem condition, the tail and the next to tail entries
+ * will be unconditionally removed (unless they have an outstanding fetch).
+ * We don't care about a race on 'overmem' at the risk of causing some
+ * collateral damage or a small delay in starting cleanup, so we don't bother
+ * to lock ADB (if it's not locked).
+ *
+ * Name bucket must be locked; adb may be locked; no other locks held.
+ */
+static void
+check_stale_name(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
+ int victims, max_victims;
+ isc_boolean_t result;
+ dns_adbname_t *victim, *next_victim;
+ isc_boolean_t overmem = adb->overmem;
+ int scans = 0;
+
+ INSIST(bucket != DNS_ADB_INVALIDBUCKET);
+
+ max_victims = overmem ? 2 : 1;
+
+ /*
+ * We limit the number of scanned entries to 10 (arbitrary choice)
+ * in order to avoid examining too many entries when there are many
+ * tail entries that have fetches (this should be rare, but could
+ * happen).
+ */
+ victim = ISC_LIST_TAIL(adb->names[bucket]);
+ for (victims = 0;
+ victim != NULL && victims < max_victims && scans < 10;
+ victim = next_victim) {
+ scans++;
+ next_victim = ISC_LIST_PREV(victim, plink);
+
+ /*
+ * If the victim is already dead, it simply waits for some
+ * final events. Ignore it.
+ */
+ if (NAME_DEAD(victim))
+ goto next;
+
+ result = check_expire_name(&victim, now);
+ if (victim == NULL) {
+ victims++;
+ goto next;
+ }
+
+ if (!NAME_FETCH(victim) &&
+ (overmem || victim->last_used + ADB_STALE_MARGIN <= now)) {
+ RUNTIME_CHECK(kill_name(&victim,
+ DNS_EVENT_ADBCANCELED,
+ ISC_TRUE) ==
+ ISC_FALSE);
+ victims++;
+ }
+
+ next:
+ if (!overmem)
+ break;
+ }
+}
+
+/*
+ * Entry bucket must be locked; adb may be locked; no other locks held.
+ */
+static isc_boolean_t
+check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now)
+{
+ dns_adbentry_t *entry;
+ isc_boolean_t result = ISC_FALSE;
+
+ INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));
+ entry = *entryp;
+
+ if (entry->refcnt != 0)
+ return (result);
+
+ if (entry->expires == 0 || entry->expires > now)
+ return (result);
+
+ /*
+ * The entry is not in use. Delete it.
+ */
+ DP(DEF_LEVEL, "killing entry %p", entry);
+ INSIST(ISC_LINK_LINKED(entry, plink));
+ result = unlink_entry(adb, entry);
+ free_adbentry(adb, &entry);
+ if (result)
+ dec_adb_irefcnt(adb);
+ *entryp = NULL;
+ return (result);
+}
+
+/*
+ * ADB must be locked, and no other locks held.
+ */
+static isc_boolean_t
+cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
+ dns_adbname_t *name;
+ dns_adbname_t *next_name;
+ isc_boolean_t result = ISC_FALSE;
+
+ DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket);
+
+ LOCK(&adb->namelocks[bucket]);
+ if (adb->name_sd[bucket]) {
+ UNLOCK(&adb->namelocks[bucket]);
+ return (result);
+ }
+
+ name = ISC_LIST_HEAD(adb->names[bucket]);
+ while (name != NULL) {
+ next_name = ISC_LIST_NEXT(name, plink);
+ INSIST(result == ISC_FALSE);
+ result = check_expire_namehooks(name, now);
+ if (!result)
+ result = check_expire_name(&name, now);
+ name = next_name;
+ }
+ UNLOCK(&adb->namelocks[bucket]);
+ return (result);
+}
+
+/*
+ * ADB must be locked, and no other locks held.
+ */
+static isc_boolean_t
+cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {
+ dns_adbentry_t *entry, *next_entry;
+ isc_boolean_t result = ISC_FALSE;
+
+ DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket);
+
+ LOCK(&adb->entrylocks[bucket]);
+ entry = ISC_LIST_HEAD(adb->entries[bucket]);
+ while (entry != NULL) {
+ next_entry = ISC_LIST_NEXT(entry, plink);
+ INSIST(result == ISC_FALSE);
+ result = check_expire_entry(adb, &entry, now);
+ entry = next_entry;
+ }
+ UNLOCK(&adb->entrylocks[bucket]);
+ return (result);
+}
+
+static void
+destroy(dns_adb_t *adb) {
+ adb->magic = 0;
+
+ isc_task_detach(&adb->task);
+
+ isc_mempool_destroy(&adb->nmp);
+ isc_mempool_destroy(&adb->nhmp);
+ isc_mempool_destroy(&adb->limp);
+ isc_mempool_destroy(&adb->emp);
+ isc_mempool_destroy(&adb->ahmp);
+ isc_mempool_destroy(&adb->aimp);
+ isc_mempool_destroy(&adb->afmp);
+
+ DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);
+ DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS);
+
+ DESTROYLOCK(&adb->reflock);
+ DESTROYLOCK(&adb->lock);
+ DESTROYLOCK(&adb->mplock);
+ DESTROYLOCK(&adb->overmemlock);
+
+ isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
+}
+
+
+/*
+ * Public functions.
+ */
+
+isc_result_t
+dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
+ isc_taskmgr_t *taskmgr, dns_adb_t **newadb)
+{
+ dns_adb_t *adb;
+ isc_result_t result;
+ int i;
+
+ REQUIRE(mem != NULL);
+ REQUIRE(view != NULL);
+ REQUIRE(timermgr != NULL); /* this is actually unused */
+ REQUIRE(taskmgr != NULL);
+ REQUIRE(newadb != NULL && *newadb == NULL);
+
+ UNUSED(timermgr);
+
+ adb = isc_mem_get(mem, sizeof(dns_adb_t));
+ if (adb == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /*
+ * Initialize things here that cannot fail, and especially things
+ * that must be NULL for the error return to work properly.
+ */
+ adb->magic = 0;
+ adb->erefcnt = 1;
+ adb->irefcnt = 0;
+ adb->nmp = NULL;
+ adb->nhmp = NULL;
+ adb->limp = NULL;
+ adb->emp = NULL;
+ adb->ahmp = NULL;
+ adb->aimp = NULL;
+ adb->afmp = NULL;
+ adb->task = NULL;
+ adb->mctx = NULL;
+ adb->view = view;
+ adb->taskmgr = taskmgr;
+ adb->next_cleanbucket = 0;
+ ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,
+ DNS_EVENT_ADBCONTROL, shutdown_task, adb,
+ adb, NULL, NULL);
+ adb->cevent_sent = ISC_FALSE;
+ adb->shutting_down = ISC_FALSE;
+ adb->overmem = ISC_FALSE;
+ ISC_LIST_INIT(adb->whenshutdown);
+
+ isc_mem_attach(mem, &adb->mctx);
+
+ result = isc_mutex_init(&adb->lock);
+ if (result != ISC_R_SUCCESS)
+ goto fail0b;
+
+ result = isc_mutex_init(&adb->mplock);
+ if (result != ISC_R_SUCCESS)
+ goto fail0c;
+
+ result = isc_mutex_init(&adb->reflock);
+ if (result != ISC_R_SUCCESS)
+ goto fail0d;
+
+ result = isc_mutex_init(&adb->overmemlock);
+ if (result != ISC_R_SUCCESS)
+ goto fail0e;
+
+ /*
+ * Initialize the bucket locks for names and elements.
+ * May as well initialize the list heads, too.
+ */
+ result = isc_mutexblock_init(adb->namelocks, NBUCKETS);
+ if (result != ISC_R_SUCCESS)
+ goto fail1;
+ for (i = 0; i < NBUCKETS; i++) {
+ ISC_LIST_INIT(adb->names[i]);
+ adb->name_sd[i] = ISC_FALSE;
+ adb->name_refcnt[i] = 0;
+ adb->irefcnt++;
+ }
+ for (i = 0; i < NBUCKETS; i++) {
+ ISC_LIST_INIT(adb->entries[i]);
+ adb->entry_sd[i] = ISC_FALSE;
+ adb->entry_refcnt[i] = 0;
+ adb->irefcnt++;
+ }
+ result = isc_mutexblock_init(adb->entrylocks, NBUCKETS);
+ if (result != ISC_R_SUCCESS)
+ goto fail2;
+
+ /*
+ * Memory pools
+ */
+#define MPINIT(t, p, n) do { \
+ result = isc_mempool_create(mem, sizeof(t), &(p)); \
+ if (result != ISC_R_SUCCESS) \
+ goto fail3; \
+ isc_mempool_setfreemax((p), FREE_ITEMS); \
+ isc_mempool_setfillcount((p), FILL_COUNT); \
+ isc_mempool_setname((p), n); \
+ isc_mempool_associatelock((p), &adb->mplock); \
+} while (0)
+
+ MPINIT(dns_adbname_t, adb->nmp, "adbname");
+ MPINIT(dns_adbnamehook_t, adb->nhmp, "adbnamehook");
+ MPINIT(dns_adblameinfo_t, adb->limp, "adblameinfo");
+ MPINIT(dns_adbentry_t, adb->emp, "adbentry");
+ MPINIT(dns_adbfind_t, adb->ahmp, "adbfind");
+ MPINIT(dns_adbaddrinfo_t, adb->aimp, "adbaddrinfo");
+ MPINIT(dns_adbfetch_t, adb->afmp, "adbfetch");
+
+#undef MPINIT
+
+ /*
+ * Allocate an internal task.
+ */
+ result = isc_task_create(adb->taskmgr, 0, &adb->task);
+ if (result != ISC_R_SUCCESS)
+ goto fail3;
+ isc_task_setname(adb->task, "ADB", adb);
+
+ /*
+ * Normal return.
+ */
+ adb->magic = DNS_ADB_MAGIC;
+ *newadb = adb;
+ return (ISC_R_SUCCESS);
+
+ fail3:
+ if (adb->task != NULL)
+ isc_task_detach(&adb->task);
+
+ /* clean up entrylocks */
+ DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);
+
+ fail2: /* clean up namelocks */
+ DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS);
+
+ fail1: /* clean up only allocated memory */
+ if (adb->nmp != NULL)
+ isc_mempool_destroy(&adb->nmp);
+ if (adb->nhmp != NULL)
+ isc_mempool_destroy(&adb->nhmp);
+ if (adb->limp != NULL)
+ isc_mempool_destroy(&adb->limp);
+ if (adb->emp != NULL)
+ isc_mempool_destroy(&adb->emp);
+ if (adb->ahmp != NULL)
+ isc_mempool_destroy(&adb->ahmp);
+ if (adb->aimp != NULL)
+ isc_mempool_destroy(&adb->aimp);
+ if (adb->afmp != NULL)
+ isc_mempool_destroy(&adb->afmp);
+
+ DESTROYLOCK(&adb->overmemlock);
+ fail0e:
+ DESTROYLOCK(&adb->reflock);
+ fail0d:
+ DESTROYLOCK(&adb->mplock);
+ fail0c:
+ DESTROYLOCK(&adb->lock);
+ fail0b:
+ isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
+
+ return (result);
+}
+
+void
+dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) {
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(adbx != NULL && *adbx == NULL);
+
+ inc_adb_erefcnt(adb);
+ *adbx = adb;
+}
+
+void
+dns_adb_detach(dns_adb_t **adbx) {
+ dns_adb_t *adb;
+ isc_boolean_t need_exit_check;
+
+ REQUIRE(adbx != NULL && DNS_ADB_VALID(*adbx));
+
+ adb = *adbx;
+ *adbx = NULL;
+
+ INSIST(adb->erefcnt > 0);
+
+ LOCK(&adb->reflock);
+ adb->erefcnt--;
+ need_exit_check = ISC_TF(adb->erefcnt == 0 && adb->irefcnt == 0);
+ UNLOCK(&adb->reflock);
+
+ if (need_exit_check) {
+ LOCK(&adb->lock);
+ INSIST(adb->shutting_down);
+ check_exit(adb);
+ UNLOCK(&adb->lock);
+ }
+}
+
+void
+dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) {
+ isc_task_t *clone;
+ isc_event_t *event;
+ isc_boolean_t zeroirefcnt = ISC_FALSE;
+
+ /*
+ * Send '*eventp' to 'task' when 'adb' has shutdown.
+ */
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(eventp != NULL);
+
+ event = *eventp;
+ *eventp = NULL;
+
+ LOCK(&adb->lock);
+
+ LOCK(&adb->reflock);
+ zeroirefcnt = ISC_TF(adb->irefcnt == 0);
+
+ if (adb->shutting_down && zeroirefcnt &&
+ isc_mempool_getallocated(adb->ahmp) == 0) {
+ /*
+ * We're already shutdown. Send the event.
+ */
+ event->ev_sender = adb;
+ isc_task_send(task, &event);
+ } else {
+ clone = NULL;
+ isc_task_attach(task, &clone);
+ event->ev_sender = clone;
+ ISC_LIST_APPEND(adb->whenshutdown, event, ev_link);
+ }
+
+ UNLOCK(&adb->reflock);
+ UNLOCK(&adb->lock);
+}
+
+void
+dns_adb_shutdown(dns_adb_t *adb) {
+ isc_boolean_t need_check_exit;
+
+ /*
+ * Shutdown 'adb'.
+ */
+
+ LOCK(&adb->lock);
+
+ if (!adb->shutting_down) {
+ adb->shutting_down = ISC_TRUE;
+ isc_mem_setwater(adb->mctx, water, adb, 0, 0);
+ need_check_exit = shutdown_names(adb);
+ if (!need_check_exit)
+ need_check_exit = shutdown_entries(adb);
+ if (need_check_exit)
+ check_exit(adb);
+ }
+
+ UNLOCK(&adb->lock);
+}
+
+isc_result_t
+dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
+ void *arg, dns_name_t *name, dns_name_t *qname,
+ dns_rdatatype_t qtype, unsigned int options,
+ isc_stdtime_t now, dns_name_t *target,
+ in_port_t port, dns_adbfind_t **findp)
+{
+ dns_adbfind_t *find;
+ dns_adbname_t *adbname;
+ int bucket;
+ isc_boolean_t want_event, start_at_zone, alias, have_address;
+ isc_result_t result;
+ unsigned int wanted_addresses;
+ unsigned int wanted_fetches;
+ unsigned int query_pending;
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ if (task != NULL) {
+ REQUIRE(action != NULL);
+ }
+ REQUIRE(name != NULL);
+ REQUIRE(qname != NULL);
+ REQUIRE(findp != NULL && *findp == NULL);
+ REQUIRE(target == NULL || dns_name_hasbuffer(target));
+
+ REQUIRE((options & DNS_ADBFIND_ADDRESSMASK) != 0);
+
+ result = ISC_R_UNEXPECTED;
+ wanted_addresses = (options & DNS_ADBFIND_ADDRESSMASK);
+ wanted_fetches = 0;
+ query_pending = 0;
+ want_event = ISC_FALSE;
+ start_at_zone = ISC_FALSE;
+ alias = ISC_FALSE;
+
+ if (now == 0)
+ isc_stdtime_get(&now);
+
+ /*
+ * XXXMLG Move this comment somewhere else!
+ *
+ * Look up the name in our internal database.
+ *
+ * Possibilities: Note that these are not always exclusive.
+ *
+ * No name found. In this case, allocate a new name header and
+ * an initial namehook or two. If any of these allocations
+ * fail, clean up and return ISC_R_NOMEMORY.
+ *
+ * Name found, valid addresses present. Allocate one addrinfo
+ * structure for each found and append it to the linked list
+ * of addresses for this header.
+ *
+ * Name found, queries pending. In this case, if a task was
+ * passed in, allocate a job id, attach it to the name's job
+ * list and remember to tell the caller that there will be
+ * more info coming later.
+ */
+
+ find = new_adbfind(adb);
+ if (find == NULL)
+ return (ISC_R_NOMEMORY);
+
+ find->port = port;
+
+ /*
+ * Remember what types of addresses we are interested in.
+ */
+ find->options = options;
+ find->flags |= wanted_addresses;
+ if (FIND_WANTEVENT(find)) {
+ REQUIRE(task != NULL);
+ }
+
+ /*
+ * Try to see if we know anything about this name at all.
+ */
+ bucket = DNS_ADB_INVALIDBUCKET;
+ adbname = find_name_and_lock(adb, name, find->options, &bucket);
+ if (adb->name_sd[bucket]) {
+ DP(DEF_LEVEL,
+ "dns_adb_createfind: returning ISC_R_SHUTTINGDOWN");
+ RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
+ result = ISC_R_SHUTTINGDOWN;
+ goto out;
+ }
+
+ /*
+ * Nothing found. Allocate a new adbname structure for this name.
+ */
+ if (adbname == NULL) {
+ /*
+ * See if there is any stale name at the end of list, and purge
+ * it if so.
+ */
+ check_stale_name(adb, bucket, now);
+
+ adbname = new_adbname(adb, name);
+ if (adbname == NULL) {
+ RUNTIME_CHECK(free_adbfind(adb, &find) == ISC_FALSE);
+ result = ISC_R_NOMEMORY;
+ goto out;
+ }
+ link_name(adb, bucket, adbname);
+ if (FIND_HINTOK(find))
+ adbname->flags |= NAME_HINT_OK;
+ if (FIND_GLUEOK(find))
+ adbname->flags |= NAME_GLUE_OK;
+ if (FIND_STARTATZONE(find))
+ adbname->flags |= NAME_STARTATZONE;
+ } else {
+ /* Move this name forward in the LRU list */
+ ISC_LIST_UNLINK(adb->names[bucket], adbname, plink);
+ ISC_LIST_PREPEND(adb->names[bucket], adbname, plink);
+ }
+ adbname->last_used = now;
+
+ /*
+ * Expire old entries, etc.
+ */
+ RUNTIME_CHECK(check_expire_namehooks(adbname, now) == ISC_FALSE);
+
+ /*
+ * Do we know that the name is an alias?
+ */
+ if (!EXPIRE_OK(adbname->expire_target, now)) {
+ /*
+ * Yes, it is.
+ */
+ DP(DEF_LEVEL,
+ "dns_adb_createfind: name %p is an alias (cached)",
+ adbname);
+ alias = ISC_TRUE;
+ goto post_copy;
+ }
+
+ /*
+ * Try to populate the name from the database and/or
+ * start fetches. First try looking for an A record
+ * in the database.
+ */
+ if (!NAME_HAS_V4(adbname) && EXPIRE_OK(adbname->expire_v4, now)
+ && WANT_INET(wanted_addresses)) {
+ result = dbfind_name(adbname, now, dns_rdatatype_a);
+ if (result == ISC_R_SUCCESS) {
+ DP(DEF_LEVEL,
+ "dns_adb_createfind: found A for name %p in db",
+ adbname);
+ goto v6;
+ }
+
+ /*
+ * Did we get a CNAME or DNAME?
+ */
+ if (result == DNS_R_ALIAS) {
+ DP(DEF_LEVEL,
+ "dns_adb_createfind: name %p is an alias",
+ adbname);
+ alias = ISC_TRUE;
+ goto post_copy;
+ }
+
+ /*
+ * If the name doesn't exist at all, don't bother with
+ * v6 queries; they won't work.
+ *
+ * If the name does exist but we didn't get our data, go
+ * ahead and try AAAA.
+ *
+ * If the result is neither of these, try a fetch for A.
+ */
+ if (NXDOMAIN_RESULT(result))
+ goto fetch;
+ else if (NXRRSET_RESULT(result))
+ goto v6;
+
+ if (!NAME_FETCH_V4(adbname))
+ wanted_fetches |= DNS_ADBFIND_INET;
+ }
+
+ v6:
+ if (!NAME_HAS_V6(adbname) && EXPIRE_OK(adbname->expire_v6, now)
+ && WANT_INET6(wanted_addresses)) {
+ result = dbfind_name(adbname, now, dns_rdatatype_aaaa);
+ if (result == ISC_R_SUCCESS) {
+ DP(DEF_LEVEL,
+ "dns_adb_createfind: found AAAA for name %p",
+ adbname);
+ goto fetch;
+ }
+
+ /*
+ * Did we get a CNAME or DNAME?
+ */
+ if (result == DNS_R_ALIAS) {
+ DP(DEF_LEVEL,
+ "dns_adb_createfind: name %p is an alias",
+ adbname);
+ alias = ISC_TRUE;
+ goto post_copy;
+ }
+
+ /*
+ * Listen to negative cache hints, and don't start
+ * another query.
+ */
+ if (NCACHE_RESULT(result) || AUTH_NX(result))
+ goto fetch;
+
+ if (!NAME_FETCH_V6(adbname))
+ wanted_fetches |= DNS_ADBFIND_INET6;
+ }
+
+ fetch:
+ if ((WANT_INET(wanted_addresses) && NAME_HAS_V4(adbname)) ||
+ (WANT_INET6(wanted_addresses) && NAME_HAS_V6(adbname)))
+ have_address = ISC_TRUE;
+ else
+ have_address = ISC_FALSE;
+ if (wanted_fetches != 0 &&
+ ! (FIND_AVOIDFETCHES(find) && have_address)) {
+ /*
+ * We're missing at least one address family. Either the
+ * caller hasn't instructed us to avoid fetches, or we don't
+ * know anything about any of the address families that would
+ * be acceptable so we have to launch fetches.
+ */
+
+ if (FIND_STARTATZONE(find))
+ start_at_zone = ISC_TRUE;
+
+ /*
+ * Start V4.
+ */
+ if (WANT_INET(wanted_fetches) &&
+ fetch_name(adbname, start_at_zone,
+ dns_rdatatype_a) == ISC_R_SUCCESS) {
+ DP(DEF_LEVEL,
+ "dns_adb_createfind: started A fetch for name %p",
+ adbname);
+ }
+
+ /*
+ * Start V6.
+ */
+ if (WANT_INET6(wanted_fetches) &&
+ fetch_name(adbname, start_at_zone,
+ dns_rdatatype_aaaa) == ISC_R_SUCCESS) {
+ DP(DEF_LEVEL,
+ "dns_adb_createfind: "
+ "started AAAA fetch for name %p",
+ adbname);
+ }
+ }
+
+ /*
+ * Run through the name and copy out the bits we are
+ * interested in.
+ */
+ copy_namehook_lists(adb, find, qname, qtype, adbname, now);
+
+ post_copy:
+ if (NAME_FETCH_V4(adbname))
+ query_pending |= DNS_ADBFIND_INET;
+ if (NAME_FETCH_V6(adbname))
+ query_pending |= DNS_ADBFIND_INET6;
+
+ /*
+ * Attach to the name's query list if there are queries
+ * already running, and we have been asked to.
+ */
+ want_event = ISC_TRUE;
+ if (!FIND_WANTEVENT(find))
+ want_event = ISC_FALSE;
+ if (FIND_WANTEMPTYEVENT(find) && FIND_HAS_ADDRS(find))
+ want_event = ISC_FALSE;
+ if ((wanted_addresses & query_pending) == 0)
+ want_event = ISC_FALSE;
+ if (alias)
+ want_event = ISC_FALSE;
+ if (want_event) {
+ find->adbname = adbname;
+ find->name_bucket = bucket;
+ ISC_LIST_APPEND(adbname->finds, find, plink);
+ find->query_pending = (query_pending & wanted_addresses);
+ find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
+ find->flags |= (find->query_pending & DNS_ADBFIND_ADDRESSMASK);
+ DP(DEF_LEVEL, "createfind: attaching find %p to adbname %p",
+ find, adbname);
+ } else {
+ /*
+ * Remove the flag so the caller knows there will never
+ * be an event, and set internal flags to fake that
+ * the event was sent and freed, so dns_adb_destroyfind() will
+ * do the right thing.
+ */
+ find->query_pending = (query_pending & wanted_addresses);
+ find->options &= ~DNS_ADBFIND_WANTEVENT;
+ find->flags |= (FIND_EVENT_SENT | FIND_EVENT_FREED);
+ find->flags &= ~DNS_ADBFIND_ADDRESSMASK;
+ }
+
+ find->partial_result |= (adbname->partial_result & wanted_addresses);
+ if (alias) {
+ if (target != NULL) {
+ result = dns_name_copy(&adbname->target, target, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ }
+ result = DNS_R_ALIAS;
+ } else
+ result = ISC_R_SUCCESS;
+
+ /*
+ * Copy out error flags from the name structure into the find.
+ */
+ find->result_v4 = find_err_map[adbname->fetch_err];
+ find->result_v6 = find_err_map[adbname->fetch6_err];
+
+ out:
+ if (find != NULL) {
+ *findp = find;
+
+ if (want_event) {
+ isc_task_t *taskp;
+
+ INSIST((find->flags & DNS_ADBFIND_ADDRESSMASK) != 0);
+ taskp = NULL;
+ isc_task_attach(task, &taskp);
+ find->event.ev_sender = taskp;
+ find->event.ev_action = action;
+ find->event.ev_arg = arg;
+ }
+ }
+
+ UNLOCK(&adb->namelocks[bucket]);
+
+ return (result);
+}
+
+void
+dns_adb_destroyfind(dns_adbfind_t **findp) {
+ dns_adbfind_t *find;
+ dns_adbentry_t *entry;
+ dns_adbaddrinfo_t *ai;
+ int bucket;
+ dns_adb_t *adb;
+
+ REQUIRE(findp != NULL && DNS_ADBFIND_VALID(*findp));
+ find = *findp;
+ *findp = NULL;
+
+ LOCK(&find->lock);
+
+ DP(DEF_LEVEL, "dns_adb_destroyfind on find %p", find);
+
+ adb = find->adb;
+ REQUIRE(DNS_ADB_VALID(adb));
+
+ REQUIRE(FIND_EVENTFREED(find));
+
+ bucket = find->name_bucket;
+ INSIST(bucket == DNS_ADB_INVALIDBUCKET);
+
+ UNLOCK(&find->lock);
+
+ /*
+ * The find doesn't exist on any list, and nothing is locked.
+ * Return the find to the memory pool, and decrement the adb's
+ * reference count.
+ */
+ ai = ISC_LIST_HEAD(find->list);
+ while (ai != NULL) {
+ ISC_LIST_UNLINK(find->list, ai, publink);
+ entry = ai->entry;
+ ai->entry = NULL;
+ INSIST(DNS_ADBENTRY_VALID(entry));
+ RUNTIME_CHECK(dec_entry_refcnt(adb, entry, ISC_TRUE) ==
+ ISC_FALSE);
+ free_adbaddrinfo(adb, &ai);
+ ai = ISC_LIST_HEAD(find->list);
+ }
+
+ /*
+ * WARNING: The find is freed with the adb locked. This is done
+ * to avoid a race condition where we free the find, some other
+ * thread tests to see if it should be destroyed, detects it should
+ * be, destroys it, and then we try to lock it for our check, but the
+ * lock is destroyed.
+ */
+ LOCK(&adb->lock);
+ if (free_adbfind(adb, &find))
+ check_exit(adb);
+ UNLOCK(&adb->lock);
+}
+
+void
+dns_adb_cancelfind(dns_adbfind_t *find) {
+ isc_event_t *ev;
+ isc_task_t *task;
+ dns_adb_t *adb;
+ int bucket;
+ int unlock_bucket;
+
+ LOCK(&find->lock);
+
+ DP(DEF_LEVEL, "dns_adb_cancelfind on find %p", find);
+
+ adb = find->adb;
+ REQUIRE(DNS_ADB_VALID(adb));
+
+ REQUIRE(!FIND_EVENTFREED(find));
+ REQUIRE(FIND_WANTEVENT(find));
+
+ bucket = find->name_bucket;
+ if (bucket == DNS_ADB_INVALIDBUCKET)
+ goto cleanup;
+
+ /*
+ * We need to get the adbname's lock to unlink the find.
+ */
+ unlock_bucket = bucket;
+ violate_locking_hierarchy(&find->lock, &adb->namelocks[unlock_bucket]);
+ bucket = find->name_bucket;
+ if (bucket != DNS_ADB_INVALIDBUCKET) {
+ ISC_LIST_UNLINK(find->adbname->finds, find, plink);
+ find->adbname = NULL;
+ find->name_bucket = DNS_ADB_INVALIDBUCKET;
+ }
+ UNLOCK(&adb->namelocks[unlock_bucket]);
+ bucket = DNS_ADB_INVALIDBUCKET;
+
+ cleanup:
+
+ if (!FIND_EVENTSENT(find)) {
+ ev = &find->event;
+ task = ev->ev_sender;
+ ev->ev_sender = find;
+ ev->ev_type = DNS_EVENT_ADBCANCELED;
+ ev->ev_destroy = event_free;
+ ev->ev_destroy_arg = find;
+ find->result_v4 = ISC_R_CANCELED;
+ find->result_v6 = ISC_R_CANCELED;
+
+ DP(DEF_LEVEL, "sending event %p to task %p for find %p",
+ ev, task, find);
+
+ isc_task_sendanddetach(&task, (isc_event_t **)&ev);
+ }
+
+ UNLOCK(&find->lock);
+}
+
+void
+dns_adb_dump(dns_adb_t *adb, FILE *f) {
+ int i;
+ isc_stdtime_t now;
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(f != NULL);
+
+ /*
+ * Lock the adb itself, lock all the name buckets, then lock all
+ * the entry buckets. This should put the adb into a state where
+ * nothing can change, so we can iterate through everything and
+ * print at our leisure.
+ */
+
+ LOCK(&adb->lock);
+ isc_stdtime_get(&now);
+
+ for (i = 0; i < NBUCKETS; i++)
+ RUNTIME_CHECK(cleanup_names(adb, i, now) == ISC_FALSE);
+ for (i = 0; i < NBUCKETS; i++)
+ RUNTIME_CHECK(cleanup_entries(adb, i, now) == ISC_FALSE);
+
+ dump_adb(adb, f, ISC_FALSE, now);
+ UNLOCK(&adb->lock);
+}
+
+static void
+dump_ttl(FILE *f, const char *legend, isc_stdtime_t value, isc_stdtime_t now) {
+ if (value == INT_MAX)
+ return;
+ fprintf(f, " [%s TTL %d]", legend, value - now);
+}
+
+static void
+dump_adb(dns_adb_t *adb, FILE *f, isc_boolean_t debug, isc_stdtime_t now) {
+ int i;
+ dns_adbname_t *name;
+ dns_adbentry_t *entry;
+
+ fprintf(f, ";\n; Address database dump\n;\n");
+ if (debug)
+ fprintf(f, "; addr %p, erefcnt %u, irefcnt %u, finds out %u\n",
+ adb, adb->erefcnt, adb->irefcnt,
+ isc_mempool_getallocated(adb->nhmp));
+
+ for (i = 0; i < NBUCKETS; i++)
+ LOCK(&adb->namelocks[i]);
+ for (i = 0; i < NBUCKETS; i++)
+ LOCK(&adb->entrylocks[i]);
+
+ /*
+ * Dump the names
+ */
+ for (i = 0; i < NBUCKETS; i++) {
+ name = ISC_LIST_HEAD(adb->names[i]);
+ if (name == NULL)
+ continue;
+ if (debug)
+ fprintf(f, "; bucket %d\n", i);
+ for (;
+ name != NULL;
+ name = ISC_LIST_NEXT(name, plink))
+ {
+ if (debug)
+ fprintf(f, "; name %p (flags %08x)\n",
+ name, name->flags);
+
+ fprintf(f, "; ");
+ print_dns_name(f, &name->name);
+ if (dns_name_countlabels(&name->target) > 0) {
+ fprintf(f, " alias ");
+ print_dns_name(f, &name->target);
+ }
+
+ dump_ttl(f, "v4", name->expire_v4, now);
+ dump_ttl(f, "v6", name->expire_v6, now);
+ dump_ttl(f, "target", name->expire_target, now);
+
+ fprintf(f, " [v4 %s] [v6 %s]",
+ errnames[name->fetch_err],
+ errnames[name->fetch6_err]);
+
+ fprintf(f, "\n");
+
+ print_namehook_list(f, "v4", &name->v4, debug, now);
+ print_namehook_list(f, "v6", &name->v6, debug, now);
+
+ if (debug)
+ print_fetch_list(f, name);
+ if (debug)
+ print_find_list(f, name);
+
+ }
+ }
+
+ fprintf(f, ";\n; Unassociated entries\n;\n");
+
+ for (i = 0; i < NBUCKETS; i++) {
+ entry = ISC_LIST_HEAD(adb->entries[i]);
+ while (entry != NULL) {
+ if (entry->refcnt == 0)
+ dump_entry(f, entry, debug, now);
+ entry = ISC_LIST_NEXT(entry, plink);
+ }
+ }
+
+ /*
+ * Unlock everything
+ */
+ for (i = 0; i < NBUCKETS; i++)
+ UNLOCK(&adb->entrylocks[i]);
+ for (i = 0; i < NBUCKETS; i++)
+ UNLOCK(&adb->namelocks[i]);
+}
+
+static void
+dump_entry(FILE *f, dns_adbentry_t *entry, isc_boolean_t debug,
+ isc_stdtime_t now)
+{
+ char addrbuf[ISC_NETADDR_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ isc_netaddr_t netaddr;
+ dns_adblameinfo_t *li;
+
+ isc_netaddr_fromsockaddr(&netaddr, &entry->sockaddr);
+ isc_netaddr_format(&netaddr, addrbuf, sizeof(addrbuf));
+
+ if (debug)
+ fprintf(f, ";\t%p: refcnt %u\n", entry, entry->refcnt);
+
+ fprintf(f, ";\t%s [srtt %u] [flags %08x]",
+ addrbuf, entry->srtt, entry->flags);
+ if (entry->expires != 0)
+ fprintf(f, " [ttl %d]", entry->expires - now);
+ fprintf(f, "\n");
+ for (li = ISC_LIST_HEAD(entry->lameinfo);
+ li != NULL;
+ li = ISC_LIST_NEXT(li, plink)) {
+ fprintf(f, ";\t\t");
+ print_dns_name(f, &li->qname);
+ dns_rdatatype_format(li->qtype, typebuf, sizeof(typebuf));
+ fprintf(f, " %s [lame TTL %d]\n", typebuf,
+ li->lame_timer - now);
+ }
+}
+
+void
+dns_adb_dumpfind(dns_adbfind_t *find, FILE *f) {
+ char tmp[512];
+ const char *tmpp;
+ dns_adbaddrinfo_t *ai;
+ isc_sockaddr_t *sa;
+
+ /*
+ * Not used currently, in the API Just In Case we
+ * want to dump out the name and/or entries too.
+ */
+
+ LOCK(&find->lock);
+
+ fprintf(f, ";Find %p\n", find);
+ fprintf(f, ";\tqpending %08x partial %08x options %08x flags %08x\n",
+ find->query_pending, find->partial_result,
+ find->options, find->flags);
+ fprintf(f, ";\tname_bucket %d, name %p, event sender %p\n",
+ find->name_bucket, find->adbname, find->event.ev_sender);
+
+ ai = ISC_LIST_HEAD(find->list);
+ if (ai != NULL)
+ fprintf(f, "\tAddresses:\n");
+ while (ai != NULL) {
+ sa = &ai->sockaddr;
+ switch (sa->type.sa.sa_family) {
+ case AF_INET:
+ tmpp = inet_ntop(AF_INET, &sa->type.sin.sin_addr,
+ tmp, sizeof(tmp));
+ break;
+ case AF_INET6:
+ tmpp = inet_ntop(AF_INET6, &sa->type.sin6.sin6_addr,
+ tmp, sizeof(tmp));
+ break;
+ default:
+ tmpp = "UnkFamily";
+ }
+
+ if (tmpp == NULL)
+ tmpp = "BadAddress";
+
+ fprintf(f, "\t\tentry %p, flags %08x"
+ " srtt %u addr %s\n",
+ ai->entry, ai->flags, ai->srtt, tmpp);
+
+ ai = ISC_LIST_NEXT(ai, publink);
+ }
+
+ UNLOCK(&find->lock);
+}
+
+static void
+print_dns_name(FILE *f, dns_name_t *name) {
+ char buf[DNS_NAME_FORMATSIZE];
+
+ INSIST(f != NULL);
+
+ dns_name_format(name, buf, sizeof(buf));
+ fprintf(f, "%s", buf);
+}
+
+static void
+print_namehook_list(FILE *f, const char *legend, dns_adbnamehooklist_t *list,
+ isc_boolean_t debug, isc_stdtime_t now)
+{
+ dns_adbnamehook_t *nh;
+
+ for (nh = ISC_LIST_HEAD(*list);
+ nh != NULL;
+ nh = ISC_LIST_NEXT(nh, plink))
+ {
+ if (debug)
+ fprintf(f, ";\tHook(%s) %p\n", legend, nh);
+ dump_entry(f, nh->entry, debug, now);
+ }
+}
+
+static inline void
+print_fetch(FILE *f, dns_adbfetch_t *ft, const char *type) {
+ fprintf(f, "\t\tFetch(%s): %p -> { nh %p, entry %p, fetch %p }\n",
+ type, ft, ft->namehook, ft->entry, ft->fetch);
+}
+
+static void
+print_fetch_list(FILE *f, dns_adbname_t *n) {
+ if (NAME_FETCH_A(n))
+ print_fetch(f, n->fetch_a, "A");
+ if (NAME_FETCH_AAAA(n))
+ print_fetch(f, n->fetch_aaaa, "AAAA");
+}
+
+static void
+print_find_list(FILE *f, dns_adbname_t *name) {
+ dns_adbfind_t *find;
+
+ find = ISC_LIST_HEAD(name->finds);
+ while (find != NULL) {
+ dns_adb_dumpfind(find, f);
+ find = ISC_LIST_NEXT(find, plink);
+ }
+}
+
+static isc_result_t
+dbfind_name(dns_adbname_t *adbname, isc_stdtime_t now, dns_rdatatype_t rdtype)
+{
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_adb_t *adb;
+ dns_fixedname_t foundname;
+ dns_name_t *fname;
+
+ INSIST(DNS_ADBNAME_VALID(adbname));
+ adb = adbname->adb;
+ INSIST(DNS_ADB_VALID(adb));
+ INSIST(rdtype == dns_rdatatype_a || rdtype == dns_rdatatype_aaaa);
+
+ dns_fixedname_init(&foundname);
+ fname = dns_fixedname_name(&foundname);
+ dns_rdataset_init(&rdataset);
+
+ if (rdtype == dns_rdatatype_a)
+ adbname->fetch_err = FIND_ERR_UNEXPECTED;
+ 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);
+
+ /* XXXVIX this switch statement is too sparse to gen a jump table. */
+ switch (result) {
+ case DNS_R_GLUE:
+ case DNS_R_HINT:
+ case ISC_R_SUCCESS:
+ /*
+ * Found in the database. Even if we can't copy out
+ * any information, return success, or else a fetch
+ * will be made, which will only make things worse.
+ */
+ if (rdtype == dns_rdatatype_a)
+ adbname->fetch_err = FIND_ERR_SUCCESS;
+ else
+ adbname->fetch6_err = FIND_ERR_SUCCESS;
+ result = import_rdataset(adbname, &rdataset, now);
+ break;
+ case DNS_R_NXDOMAIN:
+ case DNS_R_NXRRSET:
+ /*
+ * We're authoritative and the data doesn't exist.
+ * Make up a negative cache entry so we don't ask again
+ * for a while.
+ *
+ * XXXRTH What time should we use? I'm putting in 30 seconds
+ * for now.
+ */
+ if (rdtype == dns_rdatatype_a) {
+ adbname->expire_v4 = now + 30;
+ DP(NCACHE_LEVEL,
+ "adb name %p: Caching auth negative entry for A",
+ adbname);
+ if (result == DNS_R_NXDOMAIN)
+ adbname->fetch_err = FIND_ERR_NXDOMAIN;
+ else
+ adbname->fetch_err = FIND_ERR_NXRRSET;
+ } else {
+ DP(NCACHE_LEVEL,
+ "adb name %p: Caching auth negative entry for AAAA",
+ adbname);
+ adbname->expire_v6 = now + 30;
+ if (result == DNS_R_NXDOMAIN)
+ adbname->fetch6_err = FIND_ERR_NXDOMAIN;
+ else
+ adbname->fetch6_err = FIND_ERR_NXRRSET;
+ }
+ break;
+ case DNS_R_NCACHENXDOMAIN:
+ case DNS_R_NCACHENXRRSET:
+ /*
+ * We found a negative cache entry. Pull the TTL from it
+ * so we won't ask again for a while.
+ */
+ rdataset.ttl = ttlclamp(rdataset.ttl);
+ if (rdtype == dns_rdatatype_a) {
+ adbname->expire_v4 = rdataset.ttl + now;
+ if (result == DNS_R_NCACHENXDOMAIN)
+ adbname->fetch_err = FIND_ERR_NXDOMAIN;
+ else
+ adbname->fetch_err = FIND_ERR_NXRRSET;
+ DP(NCACHE_LEVEL,
+ "adb name %p: Caching negative entry for A (ttl %u)",
+ adbname, rdataset.ttl);
+ } else {
+ DP(NCACHE_LEVEL,
+ "adb name %p: Caching negative entry for AAAA (ttl %u)",
+ adbname, rdataset.ttl);
+ adbname->expire_v6 = rdataset.ttl + now;
+ if (result == DNS_R_NCACHENXDOMAIN)
+ adbname->fetch6_err = FIND_ERR_NXDOMAIN;
+ else
+ adbname->fetch6_err = FIND_ERR_NXRRSET;
+ }
+ break;
+ case DNS_R_CNAME:
+ case DNS_R_DNAME:
+ /*
+ * Clear the hint and glue flags, so this will match
+ * more often.
+ */
+ adbname->flags &= ~(DNS_ADBFIND_GLUEOK | DNS_ADBFIND_HINTOK);
+
+ rdataset.ttl = ttlclamp(rdataset.ttl);
+ clean_target(adb, &adbname->target);
+ adbname->expire_target = INT_MAX;
+ result = set_target(adb, &adbname->name, fname, &rdataset,
+ &adbname->target);
+ if (result == ISC_R_SUCCESS) {
+ result = DNS_R_ALIAS;
+ DP(NCACHE_LEVEL,
+ "adb name %p: caching alias target",
+ adbname);
+ adbname->expire_target = rdataset.ttl + now;
+ }
+ if (rdtype == dns_rdatatype_a)
+ adbname->fetch_err = FIND_ERR_SUCCESS;
+ else
+ adbname->fetch6_err = FIND_ERR_SUCCESS;
+ break;
+ }
+
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+
+ return (result);
+}
+
+static void
+fetch_callback(isc_task_t *task, isc_event_t *ev) {
+ dns_fetchevent_t *dev;
+ dns_adbname_t *name;
+ dns_adb_t *adb;
+ dns_adbfetch_t *fetch;
+ int bucket;
+ isc_eventtype_t ev_status;
+ isc_stdtime_t now;
+ isc_result_t result;
+ unsigned int address_type;
+ isc_boolean_t want_check_exit = ISC_FALSE;
+
+ UNUSED(task);
+
+ INSIST(ev->ev_type == DNS_EVENT_FETCHDONE);
+ dev = (dns_fetchevent_t *)ev;
+ name = ev->ev_arg;
+ INSIST(DNS_ADBNAME_VALID(name));
+ adb = name->adb;
+ INSIST(DNS_ADB_VALID(adb));
+
+ bucket = name->lock_bucket;
+ LOCK(&adb->namelocks[bucket]);
+
+ INSIST(NAME_FETCH_A(name) || NAME_FETCH_AAAA(name));
+ address_type = 0;
+ if (NAME_FETCH_A(name) && (name->fetch_a->fetch == dev->fetch)) {
+ address_type = DNS_ADBFIND_INET;
+ fetch = name->fetch_a;
+ name->fetch_a = NULL;
+ } else if (NAME_FETCH_AAAA(name)
+ && (name->fetch_aaaa->fetch == dev->fetch)) {
+ address_type = DNS_ADBFIND_INET6;
+ fetch = name->fetch_aaaa;
+ name->fetch_aaaa = NULL;
+ } else
+ fetch = NULL;
+
+ INSIST(address_type != 0 && fetch != NULL);
+
+ dns_resolver_destroyfetch(&fetch->fetch);
+ dev->fetch = NULL;
+
+ ev_status = DNS_EVENT_ADBNOMOREADDRESSES;
+
+ /*
+ * Cleanup things we don't care about.
+ */
+ if (dev->node != NULL)
+ dns_db_detachnode(dev->db, &dev->node);
+ if (dev->db != NULL)
+ dns_db_detach(&dev->db);
+
+ /*
+ * If this name is marked as dead, clean up, throwing away
+ * potentially good data.
+ */
+ if (NAME_DEAD(name)) {
+ free_adbfetch(adb, &fetch);
+ isc_event_free(&ev);
+
+ want_check_exit = kill_name(&name, DNS_EVENT_ADBCANCELED,
+ ISC_FALSE);
+
+ UNLOCK(&adb->namelocks[bucket]);
+
+ if (want_check_exit) {
+ LOCK(&adb->lock);
+ check_exit(adb);
+ UNLOCK(&adb->lock);
+ }
+
+ return;
+ }
+
+ isc_stdtime_get(&now);
+
+ /*
+ * If we got a negative cache response, remember it.
+ */
+ if (NCACHE_RESULT(dev->result)) {
+ dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
+ if (address_type == DNS_ADBFIND_INET) {
+ DP(NCACHE_LEVEL, "adb fetch name %p: "
+ "caching negative entry for A (ttl %u)",
+ name, dev->rdataset->ttl);
+ name->expire_v4 = ISC_MIN(name->expire_v4,
+ dev->rdataset->ttl + now);
+ if (dev->result == DNS_R_NCACHENXDOMAIN)
+ name->fetch_err = FIND_ERR_NXDOMAIN;
+ else
+ name->fetch_err = FIND_ERR_NXRRSET;
+ inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
+ } else {
+ DP(NCACHE_LEVEL, "adb fetch name %p: "
+ "caching negative entry for AAAA (ttl %u)",
+ name, dev->rdataset->ttl);
+ name->expire_v6 = ISC_MIN(name->expire_v6,
+ dev->rdataset->ttl + now);
+ if (dev->result == DNS_R_NCACHENXDOMAIN)
+ name->fetch6_err = FIND_ERR_NXDOMAIN;
+ else
+ name->fetch6_err = FIND_ERR_NXRRSET;
+ inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
+ }
+ goto out;
+ }
+
+ /*
+ * Handle CNAME/DNAME.
+ */
+ if (dev->result == DNS_R_CNAME || dev->result == DNS_R_DNAME) {
+ dev->rdataset->ttl = ttlclamp(dev->rdataset->ttl);
+ clean_target(adb, &name->target);
+ name->expire_target = INT_MAX;
+ result = set_target(adb, &name->name,
+ dns_fixedname_name(&dev->foundname),
+ dev->rdataset,
+ &name->target);
+ if (result == ISC_R_SUCCESS) {
+ DP(NCACHE_LEVEL,
+ "adb fetch name %p: caching alias target",
+ name);
+ name->expire_target = dev->rdataset->ttl + now;
+ }
+ goto check_result;
+ }
+
+ /*
+ * Did we get back junk? If so, and there are no more fetches
+ * sitting out there, tell all the finds about it.
+ */
+ if (dev->result != ISC_R_SUCCESS) {
+ char buf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(&name->name, buf, sizeof(buf));
+ DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s",
+ buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA",
+ dns_result_totext(dev->result));
+ /* XXXMLG Don't pound on bad servers. */
+ if (address_type == DNS_ADBFIND_INET) {
+ name->expire_v4 = ISC_MIN(name->expire_v4, now + 300);
+ name->fetch_err = FIND_ERR_FAILURE;
+ inc_stats(adb, dns_resstatscounter_gluefetchv4fail);
+ } else {
+ name->expire_v6 = ISC_MIN(name->expire_v6, now + 300);
+ name->fetch6_err = FIND_ERR_FAILURE;
+ inc_stats(adb, dns_resstatscounter_gluefetchv6fail);
+ }
+ goto out;
+ }
+
+ /*
+ * We got something potentially useful.
+ */
+ result = import_rdataset(name, &fetch->rdataset, now);
+
+ check_result:
+ if (result == ISC_R_SUCCESS) {
+ ev_status = DNS_EVENT_ADBMOREADDRESSES;
+ if (address_type == DNS_ADBFIND_INET)
+ name->fetch_err = FIND_ERR_SUCCESS;
+ else
+ name->fetch6_err = FIND_ERR_SUCCESS;
+ }
+
+ out:
+ free_adbfetch(adb, &fetch);
+ isc_event_free(&ev);
+
+ clean_finds_at_name(name, ev_status, address_type);
+
+ UNLOCK(&adb->namelocks[bucket]);
+}
+
+static isc_result_t
+fetch_name(dns_adbname_t *adbname,
+ isc_boolean_t start_at_zone,
+ dns_rdatatype_t type)
+{
+ isc_result_t result;
+ dns_adbfetch_t *fetch = NULL;
+ dns_adb_t *adb;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ dns_rdataset_t rdataset;
+ dns_rdataset_t *nameservers;
+ unsigned int options;
+
+ INSIST(DNS_ADBNAME_VALID(adbname));
+ adb = adbname->adb;
+ INSIST(DNS_ADB_VALID(adb));
+
+ INSIST((type == dns_rdatatype_a && !NAME_FETCH_V4(adbname)) ||
+ (type == dns_rdatatype_aaaa && !NAME_FETCH_V6(adbname)));
+
+ adbname->fetch_err = FIND_ERR_NOTFOUND;
+
+ name = NULL;
+ nameservers = NULL;
+ dns_rdataset_init(&rdataset);
+
+ options = DNS_FETCHOPT_NOVALIDATE;
+ if (start_at_zone) {
+ DP(ENTER_LEVEL,
+ "fetch_name: starting at zone for name %p",
+ adbname);
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ result = dns_view_findzonecut2(adb->view, &adbname->name, name,
+ 0, 0, ISC_TRUE, ISC_FALSE,
+ &rdataset, NULL);
+ if (result != ISC_R_SUCCESS && result != DNS_R_HINT)
+ goto cleanup;
+ nameservers = &rdataset;
+ options |= DNS_FETCHOPT_UNSHARED;
+ }
+
+ fetch = new_adbfetch(adb);
+ if (fetch == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
+ type, name, nameservers, NULL,
+ options, adb->task, fetch_callback,
+ adbname, &fetch->rdataset, NULL,
+ &fetch->fetch);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ if (type == dns_rdatatype_a) {
+ adbname->fetch_a = fetch;
+ inc_stats(adb, dns_resstatscounter_gluefetchv4);
+ } else {
+ adbname->fetch_aaaa = fetch;
+ inc_stats(adb, dns_resstatscounter_gluefetchv6);
+ }
+ fetch = NULL; /* Keep us from cleaning this up below. */
+
+ cleanup:
+ if (fetch != NULL)
+ free_adbfetch(adb, &fetch);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+
+ return (result);
+}
+
+/*
+ * XXXMLG Needs to take a find argument and an address info, no zone or adb,
+ * since these can be extracted from the find itself.
+ */
+isc_result_t
+dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname,
+ dns_rdatatype_t qtype, isc_stdtime_t expire_time)
+{
+ dns_adblameinfo_t *li;
+ int bucket;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(DNS_ADBADDRINFO_VALID(addr));
+ REQUIRE(qname != NULL);
+
+ bucket = addr->entry->lock_bucket;
+ LOCK(&adb->entrylocks[bucket]);
+ li = ISC_LIST_HEAD(addr->entry->lameinfo);
+ while (li != NULL &&
+ (li->qtype != qtype || !dns_name_equal(qname, &li->qname)))
+ li = ISC_LIST_NEXT(li, plink);
+ if (li != NULL) {
+ if (expire_time > li->lame_timer)
+ li->lame_timer = expire_time;
+ goto unlock;
+ }
+ li = new_adblameinfo(adb, qname, qtype);
+ if (li == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto unlock;
+ }
+
+ li->lame_timer = expire_time;
+
+ ISC_LIST_PREPEND(addr->entry->lameinfo, li, plink);
+ unlock:
+ UNLOCK(&adb->entrylocks[bucket]);
+
+ return (result);
+}
+
+void
+dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
+ unsigned int rtt, unsigned int factor)
+{
+ int bucket;
+ unsigned int new_srtt;
+ isc_stdtime_t now;
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(DNS_ADBADDRINFO_VALID(addr));
+ REQUIRE(factor <= 10);
+
+ bucket = addr->entry->lock_bucket;
+ LOCK(&adb->entrylocks[bucket]);
+
+ if (factor == DNS_ADB_RTTADJAGE)
+ new_srtt = addr->entry->srtt * 98 / 100;
+ else
+ new_srtt = (addr->entry->srtt / 10 * factor)
+ + (rtt / 10 * (10 - factor));
+
+ addr->entry->srtt = new_srtt;
+ addr->srtt = new_srtt;
+
+ isc_stdtime_get(&now);
+ addr->entry->expires = now + ADB_ENTRY_WINDOW;
+
+ UNLOCK(&adb->entrylocks[bucket]);
+}
+
+void
+dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
+ unsigned int bits, unsigned int mask)
+{
+ int bucket;
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(DNS_ADBADDRINFO_VALID(addr));
+
+ bucket = addr->entry->lock_bucket;
+ LOCK(&adb->entrylocks[bucket]);
+
+ addr->entry->flags = (addr->entry->flags & ~mask) | (bits & mask);
+ /*
+ * Note that we do not update the other bits in addr->flags with
+ * the most recent values from addr->entry->flags.
+ */
+ addr->flags = (addr->flags & ~mask) | (bits & mask);
+
+ UNLOCK(&adb->entrylocks[bucket]);
+}
+
+isc_result_t
+dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
+ dns_adbaddrinfo_t **addrp, isc_stdtime_t now)
+{
+ int bucket;
+ dns_adbentry_t *entry;
+ dns_adbaddrinfo_t *addr;
+ isc_result_t result;
+ in_port_t port;
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(addrp != NULL && *addrp == NULL);
+
+ UNUSED(now);
+
+ result = ISC_R_SUCCESS;
+ bucket = DNS_ADB_INVALIDBUCKET;
+ entry = find_entry_and_lock(adb, sa, &bucket);
+ if (adb->entry_sd[bucket]) {
+ result = ISC_R_SHUTTINGDOWN;
+ goto unlock;
+ }
+ if (entry == NULL) {
+ /*
+ * We don't know anything about this address.
+ */
+ entry = new_adbentry(adb);
+ if (entry == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto unlock;
+ }
+ entry->sockaddr = *sa;
+ link_entry(adb, bucket, entry);
+ DP(ENTER_LEVEL, "findaddrinfo: new entry %p", entry);
+ } else
+ DP(ENTER_LEVEL, "findaddrinfo: found entry %p", entry);
+
+ port = isc_sockaddr_getport(sa);
+ addr = new_adbaddrinfo(adb, entry, port);
+ if (addr == NULL) {
+ result = ISC_R_NOMEMORY;
+ } else {
+ inc_entry_refcnt(adb, entry, ISC_FALSE);
+ *addrp = addr;
+ }
+
+ unlock:
+ UNLOCK(&adb->entrylocks[bucket]);
+
+ return (result);
+}
+
+void
+dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) {
+ dns_adbaddrinfo_t *addr;
+ dns_adbentry_t *entry;
+ int bucket;
+ isc_stdtime_t now;
+ isc_boolean_t want_check_exit = ISC_FALSE;
+
+ REQUIRE(DNS_ADB_VALID(adb));
+ REQUIRE(addrp != NULL);
+ addr = *addrp;
+ REQUIRE(DNS_ADBADDRINFO_VALID(addr));
+ entry = addr->entry;
+ REQUIRE(DNS_ADBENTRY_VALID(entry));
+
+ isc_stdtime_get(&now);
+
+ *addrp = NULL;
+
+ bucket = addr->entry->lock_bucket;
+ LOCK(&adb->entrylocks[bucket]);
+
+ entry->expires = now + ADB_ENTRY_WINDOW;
+
+ want_check_exit = dec_entry_refcnt(adb, entry, ISC_FALSE);
+
+ UNLOCK(&adb->entrylocks[bucket]);
+
+ addr->entry = NULL;
+ free_adbaddrinfo(adb, &addr);
+
+ if (want_check_exit) {
+ LOCK(&adb->lock);
+ check_exit(adb);
+ UNLOCK(&adb->lock);
+ }
+}
+
+void
+dns_adb_flush(dns_adb_t *adb) {
+ unsigned int i;
+
+ INSIST(DNS_ADB_VALID(adb));
+
+ LOCK(&adb->lock);
+
+ /*
+ * Call our cleanup routines.
+ */
+ for (i = 0; i < NBUCKETS; i++)
+ RUNTIME_CHECK(cleanup_names(adb, i, INT_MAX) == ISC_FALSE);
+ for (i = 0; i < NBUCKETS; i++)
+ RUNTIME_CHECK(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE);
+
+#ifdef DUMP_ADB_AFTER_CLEANING
+ dump_adb(adb, stdout, ISC_TRUE, INT_MAX);
+#endif
+
+ UNLOCK(&adb->lock);
+}
+
+void
+dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) {
+ dns_adbname_t *adbname;
+ dns_adbname_t *nextname;
+ int bucket;
+
+ INSIST(DNS_ADB_VALID(adb));
+
+ LOCK(&adb->lock);
+ bucket = dns_name_hash(name, ISC_FALSE) % NBUCKETS;
+ LOCK(&adb->namelocks[bucket]);
+ adbname = ISC_LIST_HEAD(adb->names[bucket]);
+ while (adbname != NULL) {
+ nextname = ISC_LIST_NEXT(adbname, plink);
+ if (!NAME_DEAD(adbname) &&
+ dns_name_equal(name, &adbname->name)) {
+ RUNTIME_CHECK(kill_name(&adbname,
+ DNS_EVENT_ADBCANCELED,
+ ISC_TRUE) ==
+ ISC_FALSE);
+ }
+ adbname = nextname;
+ }
+ UNLOCK(&adb->namelocks[bucket]);
+ UNLOCK(&adb->lock);
+}
+
+static void
+water(void *arg, int mark) {
+ dns_adb_t *adb = arg;
+ isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
+
+ REQUIRE(DNS_ADB_VALID(adb));
+
+ DP(ISC_LOG_DEBUG(1),
+ "adb reached %s water mark", overmem ? "high" : "low");
+
+ /*
+ * We can't use adb->lock as there is potential for water
+ * to be called when adb->lock is held.
+ */
+ LOCK(&adb->overmemlock);
+ if (adb->overmem != overmem) {
+ adb->overmem = overmem;
+ isc_mem_waterack(adb->mctx, mark);
+ }
+ UNLOCK(&adb->overmemlock);
+}
+
+void
+dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size) {
+ isc_uint32_t hiwater;
+ isc_uint32_t lowater;
+
+ INSIST(DNS_ADB_VALID(adb));
+
+ if (size != 0 && size < DNS_ADB_MINADBSIZE)
+ size = DNS_ADB_MINADBSIZE;
+
+ hiwater = size - (size >> 3); /* Approximately 7/8ths. */
+ lowater = size - (size >> 2); /* Approximately 3/4ths. */
+
+ if (size == 0 || hiwater == 0 || lowater == 0)
+ isc_mem_setwater(adb->mctx, water, adb, 0, 0);
+ else
+ isc_mem_setwater(adb->mctx, water, adb, hiwater, lowater);
+}
diff --git a/lib/dns/api b/lib/dns/api
new file mode 100644
index 0000000..2240cdd
--- /dev/null
+++ b/lib/dns/api
@@ -0,0 +1,3 @@
+LIBINTERFACE = 50
+LIBREVISION = 1
+LIBAGE = 0
diff --git a/lib/dns/byaddr.c b/lib/dns/byaddr.c
new file mode 100644
index 0000000..234d6b2
--- /dev/null
+++ b/lib/dns/byaddr.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: byaddr.c,v 1.39 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/db.h>
+#include <dns/events.h>
+#include <dns/lookup.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+/*
+ * 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'
+};
+
+isc_result_t
+dns_byaddr_createptrname(isc_netaddr_t *address, isc_boolean_t nibble,
+ dns_name_t *name)
+{
+ /*
+ * We dropped bitstring labels, so all lookups will use nibbles.
+ */
+ UNUSED(nibble);
+
+ return (dns_byaddr_createptrname2(address,
+ DNS_BYADDROPT_IPV6INT, name));
+}
+
+isc_result_t
+dns_byaddr_createptrname2(isc_netaddr_t *address, unsigned int options,
+ dns_name_t *name)
+{
+ char textname[128];
+ unsigned char *bytes;
+ int i;
+ char *cp;
+ isc_buffer_t buffer;
+ unsigned int len;
+
+ REQUIRE(address != NULL);
+
+ /*
+ * We create the text representation and then convert to a
+ * dns_name_t. This is not maximally efficient, but it keeps all
+ * of the knowledge of wire format in the dns_name_ routines.
+ */
+
+ bytes = (unsigned char *)(&address->type);
+ if (address->family == AF_INET) {
+ (void)snprintf(textname, sizeof(textname),
+ "%u.%u.%u.%u.in-addr.arpa.",
+ (bytes[3] & 0xff),
+ (bytes[2] & 0xff),
+ (bytes[1] & 0xff),
+ (bytes[0] & 0xff));
+ } else if (address->family == AF_INET6) {
+ cp = textname;
+ for (i = 15; i >= 0; i--) {
+ *cp++ = hex_digits[bytes[i] & 0x0f];
+ *cp++ = '.';
+ *cp++ = hex_digits[(bytes[i] >> 4) & 0x0f];
+ *cp++ = '.';
+ }
+ if ((options & DNS_BYADDROPT_IPV6INT) != 0)
+ strcpy(cp, "ip6.int.");
+ else
+ strcpy(cp, "ip6.arpa.");
+ } else
+ return (ISC_R_NOTIMPLEMENTED);
+
+ 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));
+}
+
+static inline isc_result_t
+copy_ptr_targets(dns_byaddr_t *byaddr, dns_rdataset_t *rdataset) {
+ isc_result_t result;
+ dns_name_t *name;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ /*
+ * The caller must be holding the byaddr's lock.
+ */
+
+ result = dns_rdataset_first(rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdata_ptr_t ptr;
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &ptr, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ name = isc_mem_get(byaddr->mctx, sizeof(*name));
+ if (name == NULL) {
+ dns_rdata_freestruct(&ptr);
+ return (ISC_R_NOMEMORY);
+ }
+ dns_name_init(name, NULL);
+ result = dns_name_dup(&ptr.ptr, byaddr->mctx, name);
+ dns_rdata_freestruct(&ptr);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(byaddr->mctx, name, sizeof(*name));
+ return (ISC_R_NOMEMORY);
+ }
+ ISC_LIST_APPEND(byaddr->event->names, name, link);
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(rdataset);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ return (result);
+}
+
+static void
+lookup_done(isc_task_t *task, isc_event_t *event) {
+ dns_byaddr_t *byaddr = event->ev_arg;
+ dns_lookupevent_t *levent;
+ isc_result_t result;
+
+ REQUIRE(event->ev_type == DNS_EVENT_LOOKUPDONE);
+ REQUIRE(VALID_BYADDR(byaddr));
+ REQUIRE(byaddr->task == task);
+
+ UNUSED(task);
+
+ levent = (dns_lookupevent_t *)event;
+
+ if (levent->result == ISC_R_SUCCESS) {
+ result = copy_ptr_targets(byaddr, levent->rdataset);
+ byaddr->event->result = result;
+ } else
+ byaddr->event->result = levent->result;
+ isc_event_free(&event);
+ isc_task_sendanddetach(&byaddr->task, (isc_event_t **)&byaddr->event);
+}
+
+static void
+bevent_destroy(isc_event_t *event) {
+ dns_byaddrevent_t *bevent;
+ dns_name_t *name, *next_name;
+ isc_mem_t *mctx;
+
+ REQUIRE(event->ev_type == DNS_EVENT_BYADDRDONE);
+ mctx = event->ev_destroy_arg;
+ bevent = (dns_byaddrevent_t *)event;
+
+ for (name = ISC_LIST_HEAD(bevent->names);
+ name != NULL;
+ name = next_name) {
+ next_name = ISC_LIST_NEXT(name, link);
+ ISC_LIST_UNLINK(bevent->names, name, link);
+ dns_name_free(name, mctx);
+ isc_mem_put(mctx, name, sizeof(*name));
+ }
+ isc_mem_put(mctx, event, event->ev_size);
+}
+
+isc_result_t
+dns_byaddr_create(isc_mem_t *mctx, isc_netaddr_t *address, dns_view_t *view,
+ unsigned int options, isc_task_t *task,
+ isc_taskaction_t action, void *arg, dns_byaddr_t **byaddrp)
+{
+ isc_result_t result;
+ dns_byaddr_t *byaddr;
+ isc_event_t *ievent;
+
+ byaddr = isc_mem_get(mctx, sizeof(*byaddr));
+ if (byaddr == NULL)
+ return (ISC_R_NOMEMORY);
+ byaddr->mctx = mctx;
+ byaddr->options = options;
+
+ byaddr->event = isc_mem_get(mctx, sizeof(*byaddr->event));
+ if (byaddr->event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_byaddr;
+ }
+ ISC_EVENT_INIT(byaddr->event, sizeof(*byaddr->event), 0, NULL,
+ DNS_EVENT_BYADDRDONE, action, arg, byaddr,
+ bevent_destroy, mctx);
+ byaddr->event->result = ISC_R_FAILURE;
+ ISC_LIST_INIT(byaddr->event->names);
+
+ byaddr->task = NULL;
+ isc_task_attach(task, &byaddr->task);
+
+ result = isc_mutex_init(&byaddr->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_event;
+
+ dns_fixedname_init(&byaddr->name);
+
+ result = dns_byaddr_createptrname2(address, options,
+ dns_fixedname_name(&byaddr->name));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lock;
+
+ byaddr->lookup = NULL;
+ result = dns_lookup_create(mctx, dns_fixedname_name(&byaddr->name),
+ dns_rdatatype_ptr, view, 0, task,
+ lookup_done, byaddr, &byaddr->lookup);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lock;
+
+ byaddr->canceled = ISC_FALSE;
+ byaddr->magic = BYADDR_MAGIC;
+
+ *byaddrp = byaddr;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_lock:
+ DESTROYLOCK(&byaddr->lock);
+
+ cleanup_event:
+ ievent = (isc_event_t *)byaddr->event;
+ isc_event_free(&ievent);
+ byaddr->event = NULL;
+
+ isc_task_detach(&byaddr->task);
+
+ cleanup_byaddr:
+ isc_mem_put(mctx, byaddr, sizeof(*byaddr));
+
+ return (result);
+}
+
+void
+dns_byaddr_cancel(dns_byaddr_t *byaddr) {
+ REQUIRE(VALID_BYADDR(byaddr));
+
+ LOCK(&byaddr->lock);
+
+ if (!byaddr->canceled) {
+ byaddr->canceled = ISC_TRUE;
+ if (byaddr->lookup != NULL)
+ dns_lookup_cancel(byaddr->lookup);
+ }
+
+ UNLOCK(&byaddr->lock);
+}
+
+void
+dns_byaddr_destroy(dns_byaddr_t **byaddrp) {
+ dns_byaddr_t *byaddr;
+
+ REQUIRE(byaddrp != NULL);
+ byaddr = *byaddrp;
+ REQUIRE(VALID_BYADDR(byaddr));
+ REQUIRE(byaddr->event == NULL);
+ REQUIRE(byaddr->task == NULL);
+ dns_lookup_destroy(&byaddr->lookup);
+
+ DESTROYLOCK(&byaddr->lock);
+ byaddr->magic = 0;
+ isc_mem_put(byaddr->mctx, byaddr, sizeof(*byaddr));
+
+ *byaddrp = NULL;
+}
diff --git a/lib/dns/cache.c b/lib/dns/cache.c
new file mode 100644
index 0000000..1b8c388
--- /dev/null
+++ b/lib/dns/cache.c
@@ -0,0 +1,1089 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: cache.c,v 1.80 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/cache.h>
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/events.h>
+#include <dns/lib.h>
+#include <dns/log.h>
+#include <dns/masterdump.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+
+#define CACHE_MAGIC ISC_MAGIC('$', '$', '$', '$')
+#define VALID_CACHE(cache) ISC_MAGIC_VALID(cache, CACHE_MAGIC)
+
+/*!
+ * Control incremental cleaning.
+ * DNS_CACHE_MINSIZE is how many bytes is the floor for dns_cache_setcachesize().
+ * See also DNS_CACHE_CLEANERINCREMENT
+ */
+#define DNS_CACHE_MINSIZE 2097152 /*%< Bytes. 2097152 = 2 MB */
+/*!
+ * Control incremental cleaning.
+ * CLEANERINCREMENT is how many nodes are examined in one pass.
+ * See also DNS_CACHE_MINSIZE
+ */
+#define DNS_CACHE_CLEANERINCREMENT 1000U /*%< Number of nodes. */
+
+/***
+ *** Types
+ ***/
+
+/*
+ * A cache_cleaner_t encapsulsates the state of the periodic
+ * cache cleaning.
+ */
+
+typedef struct cache_cleaner cache_cleaner_t;
+
+typedef enum {
+ cleaner_s_idle, /*%< Waiting for cleaning-interval to expire. */
+ cleaner_s_busy, /*%< Currently cleaning. */
+ cleaner_s_done /*%< Freed enough memory after being overmem. */
+} cleaner_state_t;
+
+/*
+ * Convenience macros for comprehensive assertion checking.
+ */
+#define CLEANER_IDLE(c) ((c)->state == cleaner_s_idle && \
+ (c)->resched_event != NULL)
+#define CLEANER_BUSY(c) ((c)->state == cleaner_s_busy && \
+ (c)->iterator != NULL && \
+ (c)->resched_event == NULL)
+
+/*%
+ * Accesses to a cache cleaner object are synchronized through
+ * task/event serialization, or locked from the cache object.
+ */
+struct cache_cleaner {
+ isc_mutex_t lock;
+ /*%<
+ * Locks overmem_event, overmem. Note: never allocate memory
+ * while holding this lock - that could lead to deadlock since
+ * the lock is take by water() which is called from the memory
+ * allocator.
+ */
+
+ dns_cache_t *cache;
+ isc_task_t *task;
+ unsigned int cleaning_interval; /*% The cleaning-interval from
+ named.conf, in seconds. */
+ isc_timer_t *cleaning_timer;
+ isc_event_t *resched_event; /*% Sent by cleaner task to
+ itself to reschedule */
+ isc_event_t *overmem_event;
+
+ dns_dbiterator_t *iterator;
+ unsigned int increment; /*% Number of names to
+ clean in one increment */
+ cleaner_state_t state; /*% Idle/Busy. */
+ isc_boolean_t overmem; /*% The cache is in an overmem state. */
+ isc_boolean_t replaceiterator;
+};
+
+/*%
+ * The actual cache object.
+ */
+
+struct dns_cache {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mutex_t lock;
+ isc_mutex_t filelock;
+ isc_mem_t *mctx;
+
+ /* Locked by 'lock'. */
+ int references;
+ int live_tasks;
+ dns_rdataclass_t rdclass;
+ dns_db_t *db;
+ cache_cleaner_t cleaner;
+ char *db_type;
+ int db_argc;
+ char **db_argv;
+
+ /* Locked by 'filelock'. */
+ char *filename;
+ /* Access to the on-disk cache file is also locked by 'filelock'. */
+};
+
+/***
+ *** Functions
+ ***/
+
+static isc_result_t
+cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
+ isc_timermgr_t *timermgr, cache_cleaner_t *cleaner);
+
+static void
+cleaning_timer_action(isc_task_t *task, isc_event_t *event);
+
+static void
+incremental_cleaning_action(isc_task_t *task, isc_event_t *event);
+
+static void
+cleaner_shutdown_action(isc_task_t *task, isc_event_t *event);
+
+static void
+overmem_cleaning_action(isc_task_t *task, isc_event_t *event);
+
+static inline isc_result_t
+cache_create_db(dns_cache_t *cache, dns_db_t **db) {
+ return (dns_db_create(cache->mctx, cache->db_type, dns_rootname,
+ dns_dbtype_cache, cache->rdclass,
+ cache->db_argc, cache->db_argv, db));
+}
+
+isc_result_t
+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 result;
+ dns_cache_t *cache;
+ int i;
+
+ REQUIRE(cachep != NULL);
+ REQUIRE(*cachep == NULL);
+ REQUIRE(mctx != NULL);
+
+ cache = isc_mem_get(mctx, sizeof(*cache));
+ if (cache == NULL)
+ return (ISC_R_NOMEMORY);
+
+ cache->mctx = NULL;
+ isc_mem_attach(mctx, &cache->mctx);
+
+ result = isc_mutex_init(&cache->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mem;
+
+ result = isc_mutex_init(&cache->filelock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lock;
+
+ cache->references = 1;
+ cache->live_tasks = 0;
+ cache->rdclass = rdclass;
+
+ cache->db_type = isc_mem_strdup(mctx, db_type);
+ if (cache->db_type == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_filelock;
+ }
+
+ cache->db_argc = db_argc;
+ if (cache->db_argc == 0)
+ cache->db_argv = NULL;
+ else {
+ cache->db_argv = isc_mem_get(mctx,
+ cache->db_argc * sizeof(char *));
+ if (cache->db_argv == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_dbtype;
+ }
+ for (i = 0; i < cache->db_argc; i++)
+ cache->db_argv[i] = NULL;
+ for (i = 0; i < cache->db_argc; i++) {
+ cache->db_argv[i] = isc_mem_strdup(mctx, db_argv[i]);
+ if (cache->db_argv[i] == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_dbargv;
+ }
+ }
+ }
+
+ cache->db = NULL;
+ result = cache_create_db(cache, &cache->db);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_dbargv;
+
+ cache->filename = NULL;
+
+ cache->magic = CACHE_MAGIC;
+
+ /*
+ * RBT-type cache DB has its own mechanism of cache cleaning and doesn't
+ * need the control of the generic cleaner.
+ */
+ if (strcmp(db_type, "rbt") == 0)
+ result = cache_cleaner_init(cache, NULL, NULL, &cache->cleaner);
+ else {
+ result = cache_cleaner_init(cache, taskmgr, timermgr,
+ &cache->cleaner);
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_db;
+
+ *cachep = cache;
+ return (ISC_R_SUCCESS);
+
+ cleanup_db:
+ dns_db_detach(&cache->db);
+ cleanup_dbargv:
+ for (i = 0; i < cache->db_argc; i++)
+ if (cache->db_argv[i] != NULL)
+ isc_mem_free(mctx, cache->db_argv[i]);
+ if (cache->db_argv != NULL)
+ isc_mem_put(mctx, cache->db_argv,
+ cache->db_argc * sizeof(char *));
+ cleanup_dbtype:
+ isc_mem_free(mctx, cache->db_type);
+ cleanup_filelock:
+ DESTROYLOCK(&cache->filelock);
+ cleanup_lock:
+ DESTROYLOCK(&cache->lock);
+ cleanup_mem:
+ isc_mem_put(mctx, cache, sizeof(*cache));
+ isc_mem_detach(&mctx);
+ return (result);
+}
+
+static void
+cache_free(dns_cache_t *cache) {
+ isc_mem_t *mctx;
+ int i;
+
+ REQUIRE(VALID_CACHE(cache));
+ REQUIRE(cache->references == 0);
+
+ isc_mem_setwater(cache->mctx, NULL, NULL, 0, 0);
+
+ if (cache->cleaner.task != NULL)
+ isc_task_detach(&cache->cleaner.task);
+
+ if (cache->cleaner.overmem_event != NULL)
+ isc_event_free(&cache->cleaner.overmem_event);
+
+ if (cache->cleaner.resched_event != NULL)
+ isc_event_free(&cache->cleaner.resched_event);
+
+ if (cache->cleaner.iterator != NULL)
+ dns_dbiterator_destroy(&cache->cleaner.iterator);
+
+ DESTROYLOCK(&cache->cleaner.lock);
+
+ if (cache->filename) {
+ isc_mem_free(cache->mctx, cache->filename);
+ cache->filename = NULL;
+ }
+
+ if (cache->db != NULL)
+ dns_db_detach(&cache->db);
+
+ if (cache->db_argv != NULL) {
+ for (i = 0; i < cache->db_argc; i++)
+ if (cache->db_argv[i] != NULL)
+ isc_mem_free(cache->mctx, cache->db_argv[i]);
+ isc_mem_put(cache->mctx, cache->db_argv,
+ cache->db_argc * sizeof(char *));
+ }
+
+ if (cache->db_type != NULL)
+ isc_mem_free(cache->mctx, cache->db_type);
+
+ DESTROYLOCK(&cache->lock);
+ DESTROYLOCK(&cache->filelock);
+ cache->magic = 0;
+ mctx = cache->mctx;
+ isc_mem_put(cache->mctx, cache, sizeof(*cache));
+ isc_mem_detach(&mctx);
+}
+
+
+void
+dns_cache_attach(dns_cache_t *cache, dns_cache_t **targetp) {
+
+ REQUIRE(VALID_CACHE(cache));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ LOCK(&cache->lock);
+ cache->references++;
+ UNLOCK(&cache->lock);
+
+ *targetp = cache;
+}
+
+void
+dns_cache_detach(dns_cache_t **cachep) {
+ dns_cache_t *cache;
+ isc_boolean_t free_cache = ISC_FALSE;
+
+ REQUIRE(cachep != NULL);
+ cache = *cachep;
+ REQUIRE(VALID_CACHE(cache));
+
+ LOCK(&cache->lock);
+ REQUIRE(cache->references > 0);
+ cache->references--;
+ if (cache->references == 0) {
+ cache->cleaner.overmem = ISC_FALSE;
+ free_cache = ISC_TRUE;
+ }
+
+ *cachep = NULL;
+
+ if (free_cache) {
+ /*
+ * When the cache is shut down, dump it to a file if one is
+ * specified.
+ */
+ isc_result_t result = dns_cache_dump(cache);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
+ "error dumping cache: %s ",
+ isc_result_totext(result));
+
+ /*
+ * If the cleaner task exists, let it free the cache.
+ */
+ if (cache->live_tasks > 0) {
+ isc_task_shutdown(cache->cleaner.task);
+ free_cache = ISC_FALSE;
+ }
+ }
+
+ UNLOCK(&cache->lock);
+
+ if (free_cache)
+ cache_free(cache);
+}
+
+void
+dns_cache_attachdb(dns_cache_t *cache, dns_db_t **dbp) {
+ REQUIRE(VALID_CACHE(cache));
+ REQUIRE(dbp != NULL && *dbp == NULL);
+ REQUIRE(cache->db != NULL);
+
+ LOCK(&cache->lock);
+ dns_db_attach(cache->db, dbp);
+ UNLOCK(&cache->lock);
+
+}
+
+isc_result_t
+dns_cache_setfilename(dns_cache_t *cache, const char *filename) {
+ char *newname;
+
+ REQUIRE(VALID_CACHE(cache));
+ REQUIRE(filename != NULL);
+
+ newname = isc_mem_strdup(cache->mctx, filename);
+ if (newname == NULL)
+ return (ISC_R_NOMEMORY);
+
+ LOCK(&cache->filelock);
+ if (cache->filename)
+ isc_mem_free(cache->mctx, cache->filename);
+ cache->filename = newname;
+ UNLOCK(&cache->filelock);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_cache_load(dns_cache_t *cache) {
+ isc_result_t result;
+
+ REQUIRE(VALID_CACHE(cache));
+
+ if (cache->filename == NULL)
+ return (ISC_R_SUCCESS);
+
+ LOCK(&cache->filelock);
+ result = dns_db_load(cache->db, cache->filename);
+ UNLOCK(&cache->filelock);
+
+ return (result);
+}
+
+isc_result_t
+dns_cache_dump(dns_cache_t *cache) {
+ isc_result_t result;
+
+ REQUIRE(VALID_CACHE(cache));
+
+ if (cache->filename == NULL)
+ return (ISC_R_SUCCESS);
+
+ LOCK(&cache->filelock);
+ result = dns_master_dump(cache->mctx, cache->db, NULL,
+ &dns_master_style_cache, cache->filename);
+ UNLOCK(&cache->filelock);
+
+ return (result);
+}
+
+void
+dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int t) {
+ isc_interval_t interval;
+ isc_result_t result;
+
+ LOCK(&cache->lock);
+
+ /*
+ * It may be the case that the cache has already shut down.
+ * If so, it has no timer.
+ */
+ if (cache->cleaner.cleaning_timer == NULL)
+ goto unlock;
+
+ cache->cleaner.cleaning_interval = t;
+
+ if (t == 0) {
+ result = isc_timer_reset(cache->cleaner.cleaning_timer,
+ isc_timertype_inactive,
+ NULL, NULL, ISC_TRUE);
+ } else {
+ isc_interval_set(&interval, cache->cleaner.cleaning_interval,
+ 0);
+ result = isc_timer_reset(cache->cleaner.cleaning_timer,
+ isc_timertype_ticker,
+ NULL, &interval, ISC_FALSE);
+ }
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
+ "could not set cache cleaning interval: %s",
+ isc_result_totext(result));
+
+ unlock:
+ UNLOCK(&cache->lock);
+}
+
+/*
+ * Initialize the cache cleaner object at *cleaner.
+ * Space for the object must be allocated by the caller.
+ */
+
+static isc_result_t
+cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
+ isc_timermgr_t *timermgr, cache_cleaner_t *cleaner)
+{
+ isc_result_t result;
+
+ result = isc_mutex_init(&cleaner->lock);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ cleaner->increment = DNS_CACHE_CLEANERINCREMENT;
+ cleaner->state = cleaner_s_idle;
+ cleaner->cache = cache;
+ cleaner->iterator = NULL;
+ cleaner->overmem = ISC_FALSE;
+ cleaner->replaceiterator = ISC_FALSE;
+
+ cleaner->task = NULL;
+ cleaner->cleaning_timer = NULL;
+ cleaner->resched_event = NULL;
+ cleaner->overmem_event = NULL;
+
+ result = dns_db_createiterator(cleaner->cache->db, ISC_FALSE,
+ &cleaner->iterator);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ if (taskmgr != NULL && timermgr != NULL) {
+ result = isc_task_create(taskmgr, 1, &cleaner->task);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_task_create() failed: %s",
+ dns_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+ cleaner->cache->live_tasks++;
+ isc_task_setname(cleaner->task, "cachecleaner", cleaner);
+
+ result = isc_task_onshutdown(cleaner->task,
+ cleaner_shutdown_action, cache);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "cache cleaner: "
+ "isc_task_onshutdown() failed: %s",
+ dns_result_totext(result));
+ 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,
+ &cleaner->cleaning_timer);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_timer_create() failed: %s",
+ dns_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+
+ cleaner->resched_event =
+ isc_event_allocate(cache->mctx, cleaner,
+ DNS_EVENT_CACHECLEAN,
+ incremental_cleaning_action,
+ cleaner, sizeof(isc_event_t));
+ if (cleaner->resched_event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ cleaner->overmem_event =
+ isc_event_allocate(cache->mctx, cleaner,
+ DNS_EVENT_CACHEOVERMEM,
+ overmem_cleaning_action,
+ cleaner, sizeof(isc_event_t));
+ if (cleaner->overmem_event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (cleaner->overmem_event != NULL)
+ isc_event_free(&cleaner->overmem_event);
+ if (cleaner->resched_event != NULL)
+ isc_event_free(&cleaner->resched_event);
+ if (cleaner->cleaning_timer != NULL)
+ isc_timer_detach(&cleaner->cleaning_timer);
+ if (cleaner->task != NULL)
+ isc_task_detach(&cleaner->task);
+ if (cleaner->iterator != NULL)
+ dns_dbiterator_destroy(&cleaner->iterator);
+ DESTROYLOCK(&cleaner->lock);
+ fail:
+ return (result);
+}
+
+static void
+begin_cleaning(cache_cleaner_t *cleaner) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(CLEANER_IDLE(cleaner));
+
+ /*
+ * Create an iterator, if it does not already exist, and
+ * position it at the beginning of the cache.
+ */
+ if (cleaner->iterator == NULL)
+ result = dns_db_createiterator(cleaner->cache->db, ISC_FALSE,
+ &cleaner->iterator);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
+ "cache cleaner could not create "
+ "iterator: %s", isc_result_totext(result));
+ else {
+ dns_dbiterator_setcleanmode(cleaner->iterator, ISC_TRUE);
+ result = dns_dbiterator_first(cleaner->iterator);
+ }
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * If the result is ISC_R_NOMORE, the database is empty,
+ * so there is nothing to be cleaned.
+ */
+ if (result != ISC_R_NOMORE && cleaner->iterator != NULL) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "cache cleaner: "
+ "dns_dbiterator_first() failed: %s",
+ dns_result_totext(result));
+ dns_dbiterator_destroy(&cleaner->iterator);
+ } else if (cleaner->iterator != NULL) {
+ result = dns_dbiterator_pause(cleaner->iterator);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
+ } else {
+ /*
+ * Pause the iterator to free its lock.
+ */
+ result = dns_dbiterator_pause(cleaner->iterator);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
+ "begin cache cleaning, mem inuse %lu",
+ (unsigned long)isc_mem_inuse(cleaner->cache->mctx));
+ cleaner->state = cleaner_s_busy;
+ isc_task_send(cleaner->task, &cleaner->resched_event);
+ }
+
+ return;
+}
+
+static void
+end_cleaning(cache_cleaner_t *cleaner, isc_event_t *event) {
+ isc_result_t result;
+
+ REQUIRE(CLEANER_BUSY(cleaner));
+ REQUIRE(event != NULL);
+
+ result = dns_dbiterator_pause(cleaner->iterator);
+ if (result != ISC_R_SUCCESS)
+ dns_dbiterator_destroy(&cleaner->iterator);
+
+ dns_cache_setcleaninginterval(cleaner->cache,
+ cleaner->cleaning_interval);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
+ ISC_LOG_DEBUG(1), "end cache cleaning, mem inuse %lu",
+ (unsigned long)isc_mem_inuse(cleaner->cache->mctx));
+
+ cleaner->state = cleaner_s_idle;
+ cleaner->resched_event = event;
+}
+
+/*
+ * This is run once for every cache-cleaning-interval as defined in named.conf.
+ */
+static void
+cleaning_timer_action(isc_task_t *task, isc_event_t *event) {
+ cache_cleaner_t *cleaner = event->ev_arg;
+
+ UNUSED(task);
+
+ INSIST(task == cleaner->task);
+ INSIST(event->ev_type == ISC_TIMEREVENT_TICK);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
+ ISC_LOG_DEBUG(1), "cache cleaning timer fired, "
+ "cleaner state = %d", cleaner->state);
+
+ if (cleaner->state == cleaner_s_idle)
+ begin_cleaning(cleaner);
+
+ isc_event_free(&event);
+}
+
+/*
+ * This is called when the cache either surpasses its upper limit
+ * or shrinks beyond its lower limit.
+ */
+static void
+overmem_cleaning_action(isc_task_t *task, isc_event_t *event) {
+ cache_cleaner_t *cleaner = event->ev_arg;
+ isc_boolean_t want_cleaning = ISC_FALSE;
+
+ UNUSED(task);
+
+ INSIST(task == cleaner->task);
+ INSIST(event->ev_type == DNS_EVENT_CACHEOVERMEM);
+ INSIST(cleaner->overmem_event == NULL);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
+ ISC_LOG_DEBUG(1), "overmem_cleaning_action called, "
+ "overmem = %d, state = %d", cleaner->overmem,
+ cleaner->state);
+
+ LOCK(&cleaner->lock);
+
+ if (cleaner->overmem) {
+ if (cleaner->state == cleaner_s_idle)
+ want_cleaning = ISC_TRUE;
+ } else {
+ if (cleaner->state == cleaner_s_busy)
+ /*
+ * end_cleaning() can't be called here because
+ * then both cleaner->overmem_event and
+ * cleaner->resched_event will point to this
+ * event. Set the state to done, and then
+ * when the incremental_cleaning_action() event
+ * is posted, it will handle the end_cleaning.
+ */
+ cleaner->state = cleaner_s_done;
+ }
+
+ cleaner->overmem_event = event;
+
+ UNLOCK(&cleaner->lock);
+
+ if (want_cleaning)
+ begin_cleaning(cleaner);
+}
+
+/*
+ * Do incremental cleaning.
+ */
+static void
+incremental_cleaning_action(isc_task_t *task, isc_event_t *event) {
+ cache_cleaner_t *cleaner = event->ev_arg;
+ isc_result_t result;
+ unsigned int n_names;
+ isc_time_t start;
+
+ UNUSED(task);
+
+ INSIST(task == cleaner->task);
+ INSIST(event->ev_type == DNS_EVENT_CACHECLEAN);
+
+ if (cleaner->state == cleaner_s_done) {
+ cleaner->state = cleaner_s_busy;
+ end_cleaning(cleaner, event);
+ LOCK(&cleaner->cache->lock);
+ LOCK(&cleaner->lock);
+ if (cleaner->replaceiterator) {
+ dns_dbiterator_destroy(&cleaner->iterator);
+ (void) dns_db_createiterator(cleaner->cache->db,
+ ISC_FALSE,
+ &cleaner->iterator);
+ cleaner->replaceiterator = ISC_FALSE;
+ }
+ UNLOCK(&cleaner->lock);
+ UNLOCK(&cleaner->cache->lock);
+ return;
+ }
+
+ INSIST(CLEANER_BUSY(cleaner));
+
+ n_names = cleaner->increment;
+
+ REQUIRE(DNS_DBITERATOR_VALID(cleaner->iterator));
+
+ isc_time_now(&start);
+ while (n_names-- > 0) {
+ dns_dbnode_t *node = NULL;
+
+ result = dns_dbiterator_current(cleaner->iterator, &node,
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "cache cleaner: dns_dbiterator_current() "
+ "failed: %s", dns_result_totext(result));
+
+ end_cleaning(cleaner, event);
+ return;
+ }
+
+ /*
+ * The node was not needed, but was required by
+ * dns_dbiterator_current(). Give up its reference.
+ */
+ dns_db_detachnode(cleaner->cache->db, &node);
+
+ /*
+ * Step to the next node.
+ */
+ result = dns_dbiterator_next(cleaner->iterator);
+
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * Either the end was reached (ISC_R_NOMORE) or
+ * some error was signaled. If the cache is still
+ * overmem and no error was encountered,
+ * keep trying to clean it, otherwise stop cleaning.
+ */
+ if (result != ISC_R_NOMORE)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "cache cleaner: "
+ "dns_dbiterator_next() "
+ "failed: %s",
+ dns_result_totext(result));
+ else if (cleaner->overmem) {
+ result = dns_dbiterator_first(cleaner->
+ iterator);
+ if (result == ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE,
+ ISC_LOG_DEBUG(1),
+ "cache cleaner: "
+ "still overmem, "
+ "reset and try again");
+ continue;
+ }
+ }
+
+ end_cleaning(cleaner, event);
+ return;
+ }
+ }
+
+ /*
+ * We have successfully performed a cleaning increment but have
+ * not gone through the entire cache. Free the iterator locks
+ * and reschedule another batch. If it fails, just try to continue
+ * anyway.
+ */
+ result = dns_dbiterator_pause(cleaner->iterator);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
+ ISC_LOG_DEBUG(1), "cache cleaner: checked %u nodes, "
+ "mem inuse %lu, sleeping", cleaner->increment,
+ (unsigned long)isc_mem_inuse(cleaner->cache->mctx));
+
+ isc_task_send(task, &event);
+ INSIST(CLEANER_BUSY(cleaner));
+ return;
+}
+
+/*
+ * Do immediate cleaning.
+ */
+isc_result_t
+dns_cache_clean(dns_cache_t *cache, isc_stdtime_t now) {
+ isc_result_t result;
+ dns_dbiterator_t *iterator = NULL;
+
+ REQUIRE(VALID_CACHE(cache));
+
+ result = dns_db_createiterator(cache->db, 0, &iterator);
+ if (result != ISC_R_SUCCESS)
+ return result;
+
+ result = dns_dbiterator_first(iterator);
+
+ while (result == ISC_R_SUCCESS) {
+ dns_dbnode_t *node = NULL;
+ result = dns_dbiterator_current(iterator, &node,
+ (dns_name_t *)NULL);
+ if (result != ISC_R_SUCCESS)
+ break;
+
+ /*
+ * Check TTLs, mark expired rdatasets stale.
+ */
+ result = dns_db_expirenode(cache->db, node, now);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "cache cleaner: dns_db_expirenode() "
+ "failed: %s",
+ dns_result_totext(result));
+ /*
+ * Continue anyway.
+ */
+ }
+
+ /*
+ * This is where the actual freeing takes place.
+ */
+ dns_db_detachnode(cache->db, &node);
+
+ result = dns_dbiterator_next(iterator);
+ }
+
+ dns_dbiterator_destroy(&iterator);
+
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ return (result);
+}
+
+static void
+water(void *arg, int mark) {
+ dns_cache_t *cache = arg;
+ isc_boolean_t overmem = ISC_TF(mark == ISC_MEM_HIWATER);
+
+ REQUIRE(VALID_CACHE(cache));
+
+ LOCK(&cache->cleaner.lock);
+
+ if (overmem != cache->cleaner.overmem) {
+ dns_db_overmem(cache->db, overmem);
+ cache->cleaner.overmem = overmem;
+ isc_mem_waterack(cache->mctx, mark);
+ }
+
+ if (cache->cleaner.overmem_event != NULL)
+ isc_task_send(cache->cleaner.task,
+ &cache->cleaner.overmem_event);
+
+ UNLOCK(&cache->cleaner.lock);
+}
+
+void
+dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size) {
+ isc_uint32_t lowater;
+ isc_uint32_t hiwater;
+
+ REQUIRE(VALID_CACHE(cache));
+
+ /*
+ * Impose a minumum cache size; pathological things happen if there
+ * is too little room.
+ */
+ if (size != 0 && size < DNS_CACHE_MINSIZE)
+ size = DNS_CACHE_MINSIZE;
+
+ hiwater = size - (size >> 3); /* Approximately 7/8ths. */
+ lowater = size - (size >> 2); /* Approximately 3/4ths. */
+
+ /*
+ * If the cache was overmem and cleaning, but now with the new limits
+ * it is no longer in an overmem condition, then the next
+ * isc_mem_put for cache memory will do the right thing and trigger
+ * water().
+ */
+
+ if (size == 0 || hiwater == 0 || lowater == 0)
+ /*
+ * Disable cache memory limiting.
+ */
+ isc_mem_setwater(cache->mctx, water, cache, 0, 0);
+ else
+ /*
+ * Establish new cache memory limits (either for the first
+ * time, or replacing other limits).
+ */
+ isc_mem_setwater(cache->mctx, water, cache, hiwater, lowater);
+}
+
+/*
+ * The cleaner task is shutting down; do the necessary cleanup.
+ */
+static void
+cleaner_shutdown_action(isc_task_t *task, isc_event_t *event) {
+ dns_cache_t *cache = event->ev_arg;
+ isc_boolean_t should_free = ISC_FALSE;
+
+ UNUSED(task);
+
+ INSIST(task == cache->cleaner.task);
+ INSIST(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
+
+ if (CLEANER_BUSY(&cache->cleaner))
+ end_cleaning(&cache->cleaner, event);
+ else
+ isc_event_free(&event);
+
+ LOCK(&cache->lock);
+
+ cache->live_tasks--;
+ INSIST(cache->live_tasks == 0);
+
+ if (cache->references == 0)
+ should_free = ISC_TRUE;
+
+ /*
+ * By detaching the timer in the context of its task,
+ * we are guaranteed that there will be no further timer
+ * events.
+ */
+ if (cache->cleaner.cleaning_timer != NULL)
+ isc_timer_detach(&cache->cleaner.cleaning_timer);
+
+ /* Make sure we don't reschedule anymore. */
+ (void)isc_task_purge(task, NULL, DNS_EVENT_CACHECLEAN, NULL);
+
+ UNLOCK(&cache->lock);
+
+ if (should_free)
+ cache_free(cache);
+}
+
+isc_result_t
+dns_cache_flush(dns_cache_t *cache) {
+ dns_db_t *db = NULL;
+ isc_result_t result;
+
+ result = cache_create_db(cache, &db);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ LOCK(&cache->lock);
+ LOCK(&cache->cleaner.lock);
+ if (cache->cleaner.state == cleaner_s_idle) {
+ if (cache->cleaner.iterator != NULL)
+ dns_dbiterator_destroy(&cache->cleaner.iterator);
+ (void) dns_db_createiterator(db, ISC_FALSE,
+ &cache->cleaner.iterator);
+ } else {
+ if (cache->cleaner.state == cleaner_s_busy)
+ cache->cleaner.state = cleaner_s_done;
+ cache->cleaner.replaceiterator = ISC_TRUE;
+ }
+ dns_db_detach(&cache->db);
+ cache->db = db;
+ UNLOCK(&cache->cleaner.lock);
+ UNLOCK(&cache->lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_cache_flushname(dns_cache_t *cache, dns_name_t *name) {
+ isc_result_t result;
+ dns_rdatasetiter_t *iter = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_db_t *db = NULL;
+
+ LOCK(&cache->lock);
+ if (cache->db != NULL)
+ dns_db_attach(cache->db, &db);
+ UNLOCK(&cache->lock);
+ if (db == NULL)
+ return (ISC_R_SUCCESS);
+ result = dns_db_findnode(cache->db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ goto cleanup_db;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_db;
+
+ result = dns_db_allrdatasets(cache->db, node, NULL,
+ (isc_stdtime_t)0, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ for (result = dns_rdatasetiter_first(iter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iter))
+ {
+ dns_rdataset_t rdataset;
+ dns_rdataset_init(&rdataset);
+
+ dns_rdatasetiter_current(iter, &rdataset);
+ result = dns_db_deleterdataset(cache->db, node, NULL,
+ rdataset.type, rdataset.covers);
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_SUCCESS && result != DNS_R_UNCHANGED)
+ break;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ dns_rdatasetiter_destroy(&iter);
+
+ cleanup_node:
+ dns_db_detachnode(cache->db, &node);
+
+ cleanup_db:
+ dns_db_detach(&db);
+ return (result);
+}
diff --git a/lib/dns/callbacks.c b/lib/dns/callbacks.c
new file mode 100644
index 0000000..928f37d
--- /dev/null
+++ b/lib/dns/callbacks.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: callbacks.c,v 1.17 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/log.h>
+
+static void
+stdio_error_warn_callback(dns_rdatacallbacks_t *, const char *, ...)
+ ISC_FORMAT_PRINTF(2, 3);
+
+static void
+isclog_error_callback(dns_rdatacallbacks_t *callbacks, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(2, 3);
+
+static void
+isclog_warn_callback(dns_rdatacallbacks_t *callbacks, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(2, 3);
+
+/*
+ * Private
+ */
+
+static void
+stdio_error_warn_callback(dns_rdatacallbacks_t *callbacks,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ UNUSED(callbacks);
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void
+isclog_error_callback(dns_rdatacallbacks_t *callbacks, const char *fmt, ...) {
+ va_list ap;
+
+ UNUSED(callbacks);
+
+ va_start(ap, fmt);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, /* XXX */
+ ISC_LOG_ERROR, fmt, ap);
+ va_end(ap);
+}
+
+static void
+isclog_warn_callback(dns_rdatacallbacks_t *callbacks, const char *fmt, ...) {
+ va_list ap;
+
+ UNUSED(callbacks);
+
+ va_start(ap, fmt);
+
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTER, /* XXX */
+ ISC_LOG_WARNING, fmt, ap);
+ va_end(ap);
+}
+
+static void
+dns_rdatacallbacks_initcommon(dns_rdatacallbacks_t *callbacks) {
+ REQUIRE(callbacks != NULL);
+
+ callbacks->add = NULL;
+ callbacks->add_private = NULL;
+ callbacks->error_private = NULL;
+ callbacks->warn_private = NULL;
+}
+
+/*
+ * Public.
+ */
+
+void
+dns_rdatacallbacks_init(dns_rdatacallbacks_t *callbacks) {
+ dns_rdatacallbacks_initcommon(callbacks);
+ callbacks->error = isclog_error_callback;
+ callbacks->warn = isclog_warn_callback;
+}
+
+void
+dns_rdatacallbacks_init_stdio(dns_rdatacallbacks_t *callbacks) {
+ dns_rdatacallbacks_initcommon(callbacks);
+ callbacks->error = stdio_error_warn_callback;
+ callbacks->warn = stdio_error_warn_callback;
+}
+
diff --git a/lib/dns/compress.c b/lib/dns/compress.c
new file mode 100644
index 0000000..11473ee
--- /dev/null
+++ b/lib/dns/compress.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: compress.c,v 1.59 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#define DNS_NAME_USEINLINE 1
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/compress.h>
+#include <dns/fixedname.h>
+#include <dns/rbt.h>
+#include <dns/result.h>
+
+#define CCTX_MAGIC ISC_MAGIC('C', 'C', 'T', 'X')
+#define VALID_CCTX(x) ISC_MAGIC_VALID(x, CCTX_MAGIC)
+
+#define DCTX_MAGIC ISC_MAGIC('D', 'C', 'T', 'X')
+#define VALID_DCTX(x) ISC_MAGIC_VALID(x, DCTX_MAGIC)
+
+/***
+ *** Compression
+ ***/
+
+isc_result_t
+dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx) {
+ unsigned int i;
+
+ REQUIRE(cctx != NULL);
+ REQUIRE(mctx != NULL); /* See: rdataset.c:towiresorted(). */
+
+ cctx->allowed = 0;
+ cctx->edns = edns;
+ for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++)
+ cctx->table[i] = NULL;
+ cctx->mctx = mctx;
+ cctx->count = 0;
+ cctx->magic = CCTX_MAGIC;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_compress_invalidate(dns_compress_t *cctx) {
+ dns_compressnode_t *node;
+ unsigned int i;
+
+ REQUIRE(VALID_CCTX(cctx));
+
+ cctx->magic = 0;
+ for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) {
+ while (cctx->table[i] != NULL) {
+ node = cctx->table[i];
+ cctx->table[i] = cctx->table[i]->next;
+ if (node->count < DNS_COMPRESS_INITIALNODES)
+ continue;
+ isc_mem_put(cctx->mctx, node, sizeof(*node));
+ }
+ }
+ cctx->allowed = 0;
+ cctx->edns = -1;
+}
+
+void
+dns_compress_setmethods(dns_compress_t *cctx, unsigned int allowed) {
+ REQUIRE(VALID_CCTX(cctx));
+
+ cctx->allowed &= ~DNS_COMPRESS_ALL;
+ cctx->allowed |= (allowed & DNS_COMPRESS_ALL);
+}
+
+unsigned int
+dns_compress_getmethods(dns_compress_t *cctx) {
+ REQUIRE(VALID_CCTX(cctx));
+ return (cctx->allowed & DNS_COMPRESS_ALL);
+}
+
+void
+dns_compress_setsensitive(dns_compress_t *cctx, isc_boolean_t sensitive) {
+ REQUIRE(VALID_CCTX(cctx));
+
+ if (sensitive)
+ cctx->allowed |= DNS_COMPRESS_CASESENSITIVE;
+ else
+ cctx->allowed &= ~DNS_COMPRESS_CASESENSITIVE;
+}
+
+isc_boolean_t
+dns_compress_getsensitive(dns_compress_t *cctx) {
+ REQUIRE(VALID_CCTX(cctx));
+
+ return (ISC_TF((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0));
+}
+
+int
+dns_compress_getedns(dns_compress_t *cctx) {
+ REQUIRE(VALID_CCTX(cctx));
+ return (cctx->edns);
+}
+
+#define NODENAME(node, name) \
+do { \
+ (name)->length = (node)->r.length; \
+ (name)->labels = (node)->labels; \
+ (name)->ndata = (node)->r.base; \
+ (name)->attributes = DNS_NAMEATTR_ABSOLUTE; \
+} while (0)
+
+/*
+ * Find the longest match of name in the table.
+ * If match is found return ISC_TRUE. prefix, suffix and offset are updated.
+ * If no match is found return ISC_FALSE.
+ */
+isc_boolean_t
+dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name,
+ dns_name_t *prefix, isc_uint16_t *offset)
+{
+ dns_name_t tname, nname;
+ dns_compressnode_t *node = NULL;
+ unsigned int labels, hash, n;
+
+ REQUIRE(VALID_CCTX(cctx));
+ REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
+ REQUIRE(offset != NULL);
+
+ if (cctx->count == 0)
+ return (ISC_FALSE);
+
+ labels = dns_name_countlabels(name);
+ INSIST(labels > 0);
+
+ dns_name_init(&tname, NULL);
+ dns_name_init(&nname, NULL);
+
+ for (n = 0; n < labels - 1; n++) {
+ dns_name_getlabelsequence(name, n, labels - n, &tname);
+ hash = dns_name_hash(&tname, ISC_FALSE) %
+ DNS_COMPRESS_TABLESIZE;
+ for (node = cctx->table[hash]; node != NULL; node = node->next)
+ {
+ NODENAME(node, &nname);
+ if ((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0) {
+ if (dns_name_caseequal(&nname, &tname))
+ break;
+ } else {
+ if (dns_name_equal(&nname, &tname))
+ break;
+ }
+ }
+ if (node != NULL)
+ break;
+ }
+
+ /*
+ * If node == NULL, we found no match at all.
+ */
+ if (node == NULL)
+ return (ISC_FALSE);
+
+ if (n == 0)
+ dns_name_reset(prefix);
+ else
+ dns_name_getlabelsequence(name, 0, n, prefix);
+
+ *offset = node->offset;
+ return (ISC_TRUE);
+}
+
+static inline unsigned int
+name_length(const dns_name_t *name) {
+ isc_region_t r;
+ dns_name_toregion(name, &r);
+ return (r.length);
+}
+
+void
+dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
+ const dns_name_t *prefix, isc_uint16_t offset)
+{
+ dns_name_t tname;
+ unsigned int start;
+ unsigned int n;
+ unsigned int count;
+ unsigned int hash;
+ dns_compressnode_t *node;
+ unsigned int length;
+ unsigned int tlength;
+ isc_uint16_t toffset;
+
+ REQUIRE(VALID_CCTX(cctx));
+ REQUIRE(dns_name_isabsolute(name));
+
+ dns_name_init(&tname, NULL);
+
+ n = dns_name_countlabels(name);
+ count = dns_name_countlabels(prefix);
+ if (dns_name_isabsolute(prefix))
+ count--;
+ start = 0;
+ length = name_length(name);
+ while (count > 0) {
+ if (offset >= 0x4000)
+ break;
+ dns_name_getlabelsequence(name, start, n, &tname);
+ hash = dns_name_hash(&tname, ISC_FALSE) %
+ DNS_COMPRESS_TABLESIZE;
+ tlength = name_length(&tname);
+ toffset = (isc_uint16_t)(offset + (length - tlength));
+ /*
+ * Create a new node and add it.
+ */
+ if (cctx->count < DNS_COMPRESS_INITIALNODES)
+ node = &cctx->initialnodes[cctx->count];
+ else {
+ node = isc_mem_get(cctx->mctx,
+ sizeof(dns_compressnode_t));
+ if (node == NULL)
+ return;
+ }
+ node->count = cctx->count++;
+ node->offset = toffset;
+ dns_name_toregion(&tname, &node->r);
+ node->labels = (isc_uint8_t)dns_name_countlabels(&tname);
+ node->next = cctx->table[hash];
+ cctx->table[hash] = node;
+ start++;
+ n--;
+ count--;
+ }
+}
+
+void
+dns_compress_rollback(dns_compress_t *cctx, isc_uint16_t offset) {
+ unsigned int i;
+ dns_compressnode_t *node;
+
+ REQUIRE(VALID_CCTX(cctx));
+
+ for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) {
+ node = cctx->table[i];
+ /*
+ * This relies on nodes with greater offsets being
+ * closer to the beginning of the list, and the
+ * items with the greatest offsets being at the end
+ * of the initialnodes[] array.
+ */
+ while (node != NULL && node->offset >= offset) {
+ cctx->table[i] = node->next;
+ if (node->count >= DNS_COMPRESS_INITIALNODES)
+ isc_mem_put(cctx->mctx, node, sizeof(*node));
+ cctx->count--;
+ node = cctx->table[i];
+ }
+ }
+}
+
+/***
+ *** Decompression
+ ***/
+
+void
+dns_decompress_init(dns_decompress_t *dctx, int edns,
+ dns_decompresstype_t type) {
+
+ REQUIRE(dctx != NULL);
+ REQUIRE(edns >= -1 && edns <= 255);
+
+ dctx->allowed = DNS_COMPRESS_NONE;
+ dctx->edns = edns;
+ dctx->type = type;
+ dctx->magic = DCTX_MAGIC;
+}
+
+void
+dns_decompress_invalidate(dns_decompress_t *dctx) {
+
+ REQUIRE(VALID_DCTX(dctx));
+
+ dctx->magic = 0;
+}
+
+void
+dns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed) {
+
+ REQUIRE(VALID_DCTX(dctx));
+
+ switch (dctx->type) {
+ case DNS_DECOMPRESS_ANY:
+ dctx->allowed = DNS_COMPRESS_ALL;
+ break;
+ case DNS_DECOMPRESS_NONE:
+ dctx->allowed = DNS_COMPRESS_NONE;
+ break;
+ case DNS_DECOMPRESS_STRICT:
+ dctx->allowed = allowed;
+ break;
+ }
+}
+
+unsigned int
+dns_decompress_getmethods(dns_decompress_t *dctx) {
+
+ REQUIRE(VALID_DCTX(dctx));
+
+ return (dctx->allowed);
+}
+
+int
+dns_decompress_edns(dns_decompress_t *dctx) {
+
+ REQUIRE(VALID_DCTX(dctx));
+
+ return (dctx->edns);
+}
+
+dns_decompresstype_t
+dns_decompress_type(dns_decompress_t *dctx) {
+
+ REQUIRE(VALID_DCTX(dctx));
+
+ return (dctx->type);
+}
diff --git a/lib/dns/db.c b/lib/dns/db.c
new file mode 100644
index 0000000..a4c2864
--- /dev/null
+++ b/lib/dns/db.c
@@ -0,0 +1,926 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 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
+ * 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: db.c,v 1.88 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+/***
+ *** Imports
+ ***/
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/rwlock.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/db.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+
+/***
+ *** Private Types
+ ***/
+
+struct dns_dbimplementation {
+ const char * name;
+ dns_dbcreatefunc_t create;
+ isc_mem_t * mctx;
+ void * driverarg;
+ ISC_LINK(dns_dbimplementation_t) link;
+};
+
+/***
+ *** Supported DB Implementations Registry
+ ***/
+
+/*
+ * Built in database implementations are registered here.
+ */
+
+#include "rbtdb.h"
+#include "rbtdb64.h"
+
+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;
+static dns_dbimplementation_t rbt64imp;
+
+static void
+initialize(void) {
+ RUNTIME_CHECK(isc_rwlock_init(&implock, 0, 0) == ISC_R_SUCCESS);
+
+ rbtimp.name = "rbt";
+ rbtimp.create = dns_rbtdb_create;
+ rbtimp.mctx = NULL;
+ rbtimp.driverarg = NULL;
+ ISC_LINK_INIT(&rbtimp, link);
+
+ rbt64imp.name = "rbt64";
+ rbt64imp.create = dns_rbtdb64_create;
+ rbt64imp.mctx = NULL;
+ rbt64imp.driverarg = NULL;
+ ISC_LINK_INIT(&rbt64imp, link);
+
+ ISC_LIST_INIT(implementations);
+ ISC_LIST_APPEND(implementations, &rbtimp, link);
+ ISC_LIST_APPEND(implementations, &rbt64imp, link);
+}
+
+static inline dns_dbimplementation_t *
+impfind(const char *name) {
+ dns_dbimplementation_t *imp;
+
+ for (imp = ISC_LIST_HEAD(implementations);
+ imp != NULL;
+ imp = ISC_LIST_NEXT(imp, link))
+ if (strcasecmp(name, imp->name) == 0)
+ return (imp);
+ return (NULL);
+}
+
+
+/***
+ *** Basic DB Methods
+ ***/
+
+isc_result_t
+dns_db_create(isc_mem_t *mctx, const char *db_type, dns_name_t *origin,
+ dns_dbtype_t type, dns_rdataclass_t rdclass,
+ unsigned int argc, char *argv[], dns_db_t **dbp)
+{
+ dns_dbimplementation_t *impinfo;
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+ /*
+ * Create a new database using implementation 'db_type'.
+ */
+
+ REQUIRE(dbp != NULL && *dbp == NULL);
+ REQUIRE(dns_name_isabsolute(origin));
+
+ RWLOCK(&implock, isc_rwlocktype_read);
+ impinfo = impfind(db_type);
+ if (impinfo != NULL) {
+ isc_result_t result;
+ result = ((impinfo->create)(mctx, origin, type,
+ rdclass, argc, argv,
+ impinfo->driverarg, dbp));
+ RWUNLOCK(&implock, isc_rwlocktype_read);
+ return (result);
+ }
+
+ RWUNLOCK(&implock, isc_rwlocktype_read);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DB, ISC_LOG_ERROR,
+ "unsupported database type '%s'", db_type);
+
+ return (ISC_R_NOTFOUND);
+}
+
+void
+dns_db_attach(dns_db_t *source, dns_db_t **targetp) {
+
+ /*
+ * Attach *targetp to source.
+ */
+
+ REQUIRE(DNS_DB_VALID(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ (source->methods->attach)(source, targetp);
+
+ ENSURE(*targetp == source);
+}
+
+void
+dns_db_detach(dns_db_t **dbp) {
+
+ /*
+ * Detach *dbp from its database.
+ */
+
+ REQUIRE(dbp != NULL);
+ REQUIRE(DNS_DB_VALID(*dbp));
+
+ ((*dbp)->methods->detach)(dbp);
+
+ ENSURE(*dbp == NULL);
+}
+
+isc_result_t
+dns_db_ondestroy(dns_db_t *db, isc_task_t *task, isc_event_t **eventp)
+{
+ REQUIRE(DNS_DB_VALID(db));
+
+ return (isc_ondestroy_register(&db->ondest, task, eventp));
+}
+
+
+isc_boolean_t
+dns_db_iscache(dns_db_t *db) {
+
+ /*
+ * Does 'db' have cache semantics?
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+
+ if ((db->attributes & DNS_DBATTR_CACHE) != 0)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_db_iszone(dns_db_t *db) {
+
+ /*
+ * Does 'db' have zone semantics?
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+
+ if ((db->attributes & (DNS_DBATTR_CACHE|DNS_DBATTR_STUB)) == 0)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_db_isstub(dns_db_t *db) {
+
+ /*
+ * Does 'db' have stub semantics?
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+
+ if ((db->attributes & DNS_DBATTR_STUB) != 0)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_db_isdnssec(dns_db_t *db) {
+
+ /*
+ * Is 'db' secure or partially secure?
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
+
+ if (db->methods->isdnssec != NULL)
+ return ((db->methods->isdnssec)(db));
+ return ((db->methods->issecure)(db));
+}
+
+isc_boolean_t
+dns_db_issecure(dns_db_t *db) {
+
+ /*
+ * Is 'db' secure?
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
+
+ return ((db->methods->issecure)(db));
+}
+
+isc_boolean_t
+dns_db_ispersistent(dns_db_t *db) {
+
+ /*
+ * Is 'db' persistent?
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+
+ return ((db->methods->ispersistent)(db));
+}
+
+dns_name_t *
+dns_db_origin(dns_db_t *db) {
+ /*
+ * The origin of the database.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+
+ return (&db->origin);
+}
+
+dns_rdataclass_t
+dns_db_class(dns_db_t *db) {
+ /*
+ * The class of the database.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+
+ return (db->rdclass);
+}
+
+isc_result_t
+dns_db_beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp,
+ dns_dbload_t **dbloadp) {
+ /*
+ * Begin loading 'db'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(addp != NULL && *addp == NULL);
+ REQUIRE(dbloadp != NULL && *dbloadp == NULL);
+
+ return ((db->methods->beginload)(db, addp, dbloadp));
+}
+
+isc_result_t
+dns_db_endload(dns_db_t *db, dns_dbload_t **dbloadp) {
+ /*
+ * Finish loading 'db'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(dbloadp != NULL && *dbloadp != NULL);
+
+ return ((db->methods->endload)(db, dbloadp));
+}
+
+isc_result_t
+dns_db_load(dns_db_t *db, const char *filename) {
+ return (dns_db_load2(db, filename, dns_masterformat_text));
+}
+
+isc_result_t
+dns_db_load2(dns_db_t *db, const char *filename, dns_masterformat_t format) {
+ isc_result_t result, eresult;
+ dns_rdatacallbacks_t callbacks;
+ unsigned int options = 0;
+
+ /*
+ * Load master file 'filename' into 'db'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+
+ if ((db->attributes & DNS_DBATTR_CACHE) != 0)
+ options |= DNS_MASTER_AGETTL;
+
+ dns_rdatacallbacks_init(&callbacks);
+
+ result = dns_db_beginload(db, &callbacks.add, &callbacks.add_private);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_master_loadfile2(filename, &db->origin, &db->origin,
+ db->rdclass, options,
+ &callbacks, db->mctx, format);
+ eresult = dns_db_endload(db, &callbacks.add_private);
+ /*
+ * We always call dns_db_endload(), but we only want to return its
+ * result if dns_master_loadfile() succeeded. If dns_master_loadfile()
+ * failed, we want to return the result code it gave us.
+ */
+ if (eresult != ISC_R_SUCCESS &&
+ (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
+ result = eresult;
+
+ return (result);
+}
+
+isc_result_t
+dns_db_dump(dns_db_t *db, dns_dbversion_t *version, const char *filename) {
+ return ((db->methods->dump)(db, version, filename,
+ dns_masterformat_text));
+}
+
+isc_result_t
+dns_db_dump2(dns_db_t *db, dns_dbversion_t *version, const char *filename,
+ dns_masterformat_t masterformat) {
+ /*
+ * Dump 'db' into master file 'filename' in the 'masterformat' format.
+ * XXXJT: is it okay to modify the interface to the existing "dump"
+ * method?
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+
+ return ((db->methods->dump)(db, version, filename, masterformat));
+}
+
+/***
+ *** Version Methods
+ ***/
+
+void
+dns_db_currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
+
+ /*
+ * Open the current version for reading.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
+ REQUIRE(versionp != NULL && *versionp == NULL);
+
+ (db->methods->currentversion)(db, versionp);
+}
+
+isc_result_t
+dns_db_newversion(dns_db_t *db, dns_dbversion_t **versionp) {
+
+ /*
+ * Open a new version for reading and writing.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
+ REQUIRE(versionp != NULL && *versionp == NULL);
+
+ return ((db->methods->newversion)(db, versionp));
+}
+
+void
+dns_db_attachversion(dns_db_t *db, dns_dbversion_t *source,
+ dns_dbversion_t **targetp)
+{
+ /*
+ * Attach '*targetp' to 'source'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
+ REQUIRE(source != NULL);
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ (db->methods->attachversion)(db, source, targetp);
+
+ ENSURE(*targetp != NULL);
+}
+
+void
+dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
+ isc_boolean_t commit)
+{
+
+ /*
+ * Close version '*versionp'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
+ REQUIRE(versionp != NULL && *versionp != NULL);
+
+ (db->methods->closeversion)(db, versionp, commit);
+
+ ENSURE(*versionp == NULL);
+}
+
+/***
+ *** Node Methods
+ ***/
+
+isc_result_t
+dns_db_findnode(dns_db_t *db, dns_name_t *name,
+ isc_boolean_t create, dns_dbnode_t **nodep)
+{
+
+ /*
+ * Find the node with name 'name'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(nodep != NULL && *nodep == NULL);
+
+ return ((db->methods->findnode)(db, name, create, nodep));
+}
+
+isc_result_t
+dns_db_findnsec3node(dns_db_t *db, dns_name_t *name,
+ isc_boolean_t create, dns_dbnode_t **nodep)
+{
+
+ /*
+ * Find the node with name 'name'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(nodep != NULL && *nodep == NULL);
+
+ return ((db->methods->findnsec3node)(db, name, create, nodep));
+}
+
+isc_result_t
+dns_db_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)
+{
+
+ /*
+ * Find the best match for 'name' and 'type' in version 'version'
+ * of 'db'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(type != dns_rdatatype_rrsig);
+ REQUIRE(nodep == NULL || (nodep != NULL && *nodep == NULL));
+ REQUIRE(dns_name_hasbuffer(foundname));
+ REQUIRE(rdataset == NULL ||
+ (DNS_RDATASET_VALID(rdataset) &&
+ ! dns_rdataset_isassociated(rdataset)));
+ REQUIRE(sigrdataset == NULL ||
+ (DNS_RDATASET_VALID(sigrdataset) &&
+ ! dns_rdataset_isassociated(sigrdataset)));
+
+ return ((db->methods->find)(db, name, version, type, options, now,
+ nodep, foundname, rdataset, sigrdataset));
+}
+
+isc_result_t
+dns_db_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)
+{
+ /*
+ * Find the deepest known zonecut which encloses 'name' in 'db'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
+ REQUIRE(nodep == NULL || (nodep != NULL && *nodep == NULL));
+ REQUIRE(dns_name_hasbuffer(foundname));
+ REQUIRE(sigrdataset == NULL ||
+ (DNS_RDATASET_VALID(sigrdataset) &&
+ ! dns_rdataset_isassociated(sigrdataset)));
+
+ return ((db->methods->findzonecut)(db, name, options, now, nodep,
+ foundname, rdataset, sigrdataset));
+}
+
+void
+dns_db_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
+
+ /*
+ * Attach *targetp to source.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(source != NULL);
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ (db->methods->attachnode)(db, source, targetp);
+}
+
+void
+dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
+
+ /*
+ * Detach *nodep from its node.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(nodep != NULL && *nodep != NULL);
+
+ (db->methods->detachnode)(db, nodep);
+
+ ENSURE(*nodep == NULL);
+}
+
+void
+dns_db_transfernode(dns_db_t *db, dns_dbnode_t **sourcep,
+ dns_dbnode_t **targetp)
+{
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+ /*
+ * This doesn't check the implementation magic. If we find that
+ * we need such checks in future then this will be done in the
+ * method.
+ */
+ REQUIRE(sourcep != NULL && *sourcep != NULL);
+
+ UNUSED(db);
+
+ if (db->methods->transfernode == NULL) {
+ *targetp = *sourcep;
+ *sourcep = NULL;
+ } else
+ (db->methods->transfernode)(db, sourcep, targetp);
+
+ ENSURE(*sourcep == NULL);
+}
+
+isc_result_t
+dns_db_expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
+
+ /*
+ * Mark as stale all records at 'node' which expire at or before 'now'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
+ REQUIRE(node != NULL);
+
+ return ((db->methods->expirenode)(db, node, now));
+}
+
+void
+dns_db_printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
+ /*
+ * Print a textual representation of the contents of the node to
+ * 'out'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(node != NULL);
+
+ (db->methods->printnode)(db, node, out);
+}
+
+/***
+ *** DB Iterator Creation
+ ***/
+
+isc_result_t
+dns_db_createiterator(dns_db_t *db, unsigned int flags,
+ dns_dbiterator_t **iteratorp)
+{
+ /*
+ * Create an iterator for version 'version' of 'db'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(iteratorp != NULL && *iteratorp == NULL);
+
+ return (db->methods->createiterator(db, flags, iteratorp));
+}
+
+/***
+ *** Rdataset Methods
+ ***/
+
+isc_result_t
+dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ /*
+ * Search for an rdataset of type 'type' at 'node' that are in version
+ * 'version' of 'db'. If found, make 'rdataset' refer to it.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(node != NULL);
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(! dns_rdataset_isassociated(rdataset));
+ REQUIRE(covers == 0 || type == dns_rdatatype_rrsig);
+ REQUIRE(type != dns_rdatatype_any);
+ REQUIRE(sigrdataset == NULL ||
+ (DNS_RDATASET_VALID(sigrdataset) &&
+ ! dns_rdataset_isassociated(sigrdataset)));
+
+ return ((db->methods->findrdataset)(db, node, version, type, covers,
+ now, rdataset, sigrdataset));
+}
+
+isc_result_t
+dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
+{
+ /*
+ * Make '*iteratorp' an rdataset iteratator for all rdatasets at
+ * 'node' in version 'version' of 'db'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(iteratorp != NULL && *iteratorp == NULL);
+
+ return ((db->methods->allrdatasets)(db, node, version, now,
+ iteratorp));
+}
+
+isc_result_t
+dns_db_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)
+{
+ /*
+ * Add 'rdataset' to 'node' in version 'version' of 'db'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(node != NULL);
+ REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL)||
+ ((db->attributes & DNS_DBATTR_CACHE) != 0 &&
+ version == NULL && (options & DNS_DBADD_MERGE) == 0));
+ REQUIRE((options & DNS_DBADD_EXACT) == 0 ||
+ (options & DNS_DBADD_MERGE) != 0);
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(dns_rdataset_isassociated(rdataset));
+ REQUIRE(rdataset->rdclass == db->rdclass);
+ REQUIRE(addedrdataset == NULL ||
+ (DNS_RDATASET_VALID(addedrdataset) &&
+ ! dns_rdataset_isassociated(addedrdataset)));
+
+ return ((db->methods->addrdataset)(db, node, version, now, rdataset,
+ options, addedrdataset));
+}
+
+isc_result_t
+dns_db_subtractrdataset(dns_db_t *db, dns_dbnode_t *node,
+ dns_dbversion_t *version, dns_rdataset_t *rdataset,
+ unsigned int options, dns_rdataset_t *newrdataset)
+{
+ /*
+ * Remove any rdata in 'rdataset' from 'node' in version 'version' of
+ * 'db'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(node != NULL);
+ REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL);
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(dns_rdataset_isassociated(rdataset));
+ REQUIRE(rdataset->rdclass == db->rdclass);
+ REQUIRE(newrdataset == NULL ||
+ (DNS_RDATASET_VALID(newrdataset) &&
+ ! dns_rdataset_isassociated(newrdataset)));
+
+ return ((db->methods->subtractrdataset)(db, node, version, rdataset,
+ options, newrdataset));
+}
+
+isc_result_t
+dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
+ dns_dbversion_t *version, dns_rdatatype_t type,
+ dns_rdatatype_t covers)
+{
+ /*
+ * Make it so that no rdataset of type 'type' exists at 'node' in
+ * version version 'version' of 'db'.
+ */
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(node != NULL);
+ REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL)||
+ ((db->attributes & DNS_DBATTR_CACHE) != 0 && version == NULL));
+
+ return ((db->methods->deleterdataset)(db, node, version,
+ type, covers));
+}
+
+void
+dns_db_overmem(dns_db_t *db, isc_boolean_t overmem) {
+
+ REQUIRE(DNS_DB_VALID(db));
+
+ (db->methods->overmem)(db, overmem);
+}
+
+isc_result_t
+dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, isc_uint32_t *serialp)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t buffer;
+
+ REQUIRE(dns_db_iszone(db) || dns_db_isstub(db));
+
+ result = dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0,
+ (isc_stdtime_t)0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto freenode;
+
+ result = dns_rdataset_first(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto freerdataset;
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdataset_next(&rdataset);
+ INSIST(result == ISC_R_NOMORE);
+
+ INSIST(rdata.length > 20);
+ isc_buffer_init(&buffer, rdata.data, rdata.length);
+ isc_buffer_add(&buffer, rdata.length);
+ isc_buffer_forward(&buffer, rdata.length - 20);
+ *serialp = isc_buffer_getuint32(&buffer);
+
+ result = ISC_R_SUCCESS;
+
+ freerdataset:
+ dns_rdataset_disassociate(&rdataset);
+
+ freenode:
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+unsigned int
+dns_db_nodecount(dns_db_t *db) {
+ REQUIRE(DNS_DB_VALID(db));
+
+ return ((db->methods->nodecount)(db));
+}
+
+void
+dns_db_settask(dns_db_t *db, isc_task_t *task) {
+ REQUIRE(DNS_DB_VALID(db));
+
+ (db->methods->settask)(db, task);
+}
+
+isc_result_t
+dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg,
+ isc_mem_t *mctx, dns_dbimplementation_t **dbimp)
+{
+ dns_dbimplementation_t *imp;
+
+ REQUIRE(name != NULL);
+ REQUIRE(dbimp != NULL && *dbimp == NULL);
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+ RWLOCK(&implock, isc_rwlocktype_write);
+ imp = impfind(name);
+ if (imp != NULL) {
+ RWUNLOCK(&implock, isc_rwlocktype_write);
+ return (ISC_R_EXISTS);
+ }
+
+ imp = isc_mem_get(mctx, sizeof(dns_dbimplementation_t));
+ if (imp == NULL) {
+ RWUNLOCK(&implock, isc_rwlocktype_write);
+ return (ISC_R_NOMEMORY);
+ }
+ imp->name = name;
+ imp->create = create;
+ imp->mctx = NULL;
+ imp->driverarg = driverarg;
+ isc_mem_attach(mctx, &imp->mctx);
+ ISC_LINK_INIT(imp, link);
+ ISC_LIST_APPEND(implementations, imp, link);
+ RWUNLOCK(&implock, isc_rwlocktype_write);
+
+ *dbimp = imp;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_db_unregister(dns_dbimplementation_t **dbimp) {
+ dns_dbimplementation_t *imp;
+ isc_mem_t *mctx;
+
+ REQUIRE(dbimp != NULL && *dbimp != NULL);
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
+
+ imp = *dbimp;
+ RWLOCK(&implock, isc_rwlocktype_write);
+ ISC_LIST_UNLINK(implementations, imp, link);
+ mctx = imp->mctx;
+ isc_mem_put(mctx, imp, sizeof(dns_dbimplementation_t));
+ isc_mem_detach(&mctx);
+ RWUNLOCK(&implock, isc_rwlocktype_write);
+}
+
+isc_result_t
+dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(dns_db_iszone(db) == ISC_TRUE);
+ REQUIRE(nodep != NULL && *nodep == NULL);
+
+ if (db->methods->getoriginnode != NULL)
+ return ((db->methods->getoriginnode)(db, nodep));
+
+ return (ISC_R_NOTFOUND);
+}
+
+dns_stats_t *
+dns_db_getrrsetstats(dns_db_t *db) {
+ REQUIRE(DNS_DB_VALID(db));
+
+ if (db->methods->getrrsetstats != NULL)
+ return ((db->methods->getrrsetstats)(db));
+
+ return (NULL);
+}
+
+isc_result_t
+dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version,
+ dns_hash_t *hash, isc_uint8_t *flags,
+ isc_uint16_t *iterations,
+ unsigned char *salt, size_t *salt_length)
+{
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(dns_db_iszone(db) == ISC_TRUE);
+
+ if (db->methods->getnsec3parameters != NULL)
+ return ((db->methods->getnsec3parameters)(db, version, hash,
+ flags, iterations,
+ salt, salt_length));
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
+ isc_stdtime_t resign)
+{
+ if (db->methods->setsigningtime != NULL)
+ return ((db->methods->setsigningtime)(db, rdataset, resign));
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+isc_result_t
+dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name)
+{
+ if (db->methods->getsigningtime != NULL)
+ return ((db->methods->getsigningtime)(db, rdataset, name));
+ return (ISC_R_NOTFOUND);
+}
+
+void
+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);
+}
diff --git a/lib/dns/dbiterator.c b/lib/dns/dbiterator.c
new file mode 100644
index 0000000..8981e49
--- /dev/null
+++ b/lib/dns/dbiterator.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: dbiterator.c,v 1.18 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+#include <dns/dbiterator.h>
+#include <dns/name.h>
+
+void
+dns_dbiterator_destroy(dns_dbiterator_t **iteratorp) {
+ /*
+ * Destroy '*iteratorp'.
+ */
+
+ REQUIRE(iteratorp != NULL);
+ REQUIRE(DNS_DBITERATOR_VALID(*iteratorp));
+
+ (*iteratorp)->methods->destroy(iteratorp);
+
+ ENSURE(*iteratorp == NULL);
+}
+
+isc_result_t
+dns_dbiterator_first(dns_dbiterator_t *iterator) {
+ /*
+ * Move the node cursor to the first node in the database (if any).
+ */
+
+ REQUIRE(DNS_DBITERATOR_VALID(iterator));
+
+ return (iterator->methods->first(iterator));
+}
+
+isc_result_t
+dns_dbiterator_last(dns_dbiterator_t *iterator) {
+ /*
+ * Move the node cursor to the first node in the database (if any).
+ */
+
+ REQUIRE(DNS_DBITERATOR_VALID(iterator));
+
+ return (iterator->methods->last(iterator));
+}
+
+isc_result_t
+dns_dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
+ /*
+ * Move the node cursor to the node with name 'name'.
+ */
+
+ REQUIRE(DNS_DBITERATOR_VALID(iterator));
+
+ return (iterator->methods->seek(iterator, name));
+}
+
+isc_result_t
+dns_dbiterator_prev(dns_dbiterator_t *iterator) {
+ /*
+ * Move the node cursor to the previous node in the database (if any).
+ */
+
+ REQUIRE(DNS_DBITERATOR_VALID(iterator));
+
+ return (iterator->methods->prev(iterator));
+}
+
+isc_result_t
+dns_dbiterator_next(dns_dbiterator_t *iterator) {
+ /*
+ * Move the node cursor to the next node in the database (if any).
+ */
+
+ REQUIRE(DNS_DBITERATOR_VALID(iterator));
+
+ return (iterator->methods->next(iterator));
+}
+
+isc_result_t
+dns_dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
+ dns_name_t *name)
+{
+ /*
+ * Return the current node.
+ */
+
+ REQUIRE(DNS_DBITERATOR_VALID(iterator));
+ REQUIRE(nodep != NULL && *nodep == NULL);
+ REQUIRE(name == NULL || dns_name_hasbuffer(name));
+
+ return (iterator->methods->current(iterator, nodep, name));
+}
+
+isc_result_t
+dns_dbiterator_pause(dns_dbiterator_t *iterator) {
+ /*
+ * Pause iteration.
+ */
+
+ REQUIRE(DNS_DBITERATOR_VALID(iterator));
+
+ return (iterator->methods->pause(iterator));
+}
+
+isc_result_t
+dns_dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
+
+ /*
+ * Return the origin to which returned node names are relative.
+ */
+
+ REQUIRE(DNS_DBITERATOR_VALID(iterator));
+ REQUIRE(iterator->relative_names);
+ REQUIRE(dns_name_hasbuffer(name));
+
+ return (iterator->methods->origin(iterator, name));
+}
+
+void
+dns_dbiterator_setcleanmode(dns_dbiterator_t *iterator, isc_boolean_t mode) {
+ REQUIRE(DNS_DBITERATOR_VALID(iterator));
+
+ iterator->cleaning = mode;
+}
diff --git a/lib/dns/dbtable.c b/lib/dns/dbtable.c
new file mode 100644
index 0000000..57bbfc1
--- /dev/null
+++ b/lib/dns/dbtable.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: dbtable.c,v 1.33 2007/06/19 23:47:16 tbox Exp $
+ */
+
+/*! \file
+ * \author
+ * Principal Author: DCL
+ */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/rwlock.h>
+#include <isc/util.h>
+
+#include <dns/dbtable.h>
+#include <dns/db.h>
+#include <dns/rbt.h>
+#include <dns/result.h>
+
+struct dns_dbtable {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ dns_rdataclass_t rdclass;
+ isc_mutex_t lock;
+ isc_rwlock_t tree_lock;
+ /* Locked by lock. */
+ unsigned int references;
+ /* Locked by tree_lock. */
+ dns_rbt_t * rbt;
+ dns_db_t * default_db;
+};
+
+#define DBTABLE_MAGIC ISC_MAGIC('D', 'B', '-', '-')
+#define VALID_DBTABLE(dbtable) ISC_MAGIC_VALID(dbtable, DBTABLE_MAGIC)
+
+static void
+dbdetach(void *data, void *arg) {
+ dns_db_t *db = data;
+
+ UNUSED(arg);
+
+ dns_db_detach(&db);
+}
+
+isc_result_t
+dns_dbtable_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
+ dns_dbtable_t **dbtablep)
+{
+ dns_dbtable_t *dbtable;
+ isc_result_t result;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(dbtablep != NULL && *dbtablep == NULL);
+
+ dbtable = (dns_dbtable_t *)isc_mem_get(mctx, sizeof(*dbtable));
+ if (dbtable == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dbtable->rbt = NULL;
+ result = dns_rbt_create(mctx, dbdetach, NULL, &dbtable->rbt);
+ if (result != ISC_R_SUCCESS)
+ goto clean1;
+
+ result = isc_mutex_init(&dbtable->lock);
+ if (result != ISC_R_SUCCESS)
+ goto clean2;
+
+ result = isc_rwlock_init(&dbtable->tree_lock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto clean3;
+
+ dbtable->default_db = NULL;
+ dbtable->mctx = mctx;
+ dbtable->rdclass = rdclass;
+ dbtable->magic = DBTABLE_MAGIC;
+ dbtable->references = 1;
+
+ *dbtablep = dbtable;
+
+ return (ISC_R_SUCCESS);
+
+ clean3:
+ DESTROYLOCK(&dbtable->lock);
+
+ clean2:
+ dns_rbt_destroy(&dbtable->rbt);
+
+ clean1:
+ isc_mem_put(mctx, dbtable, sizeof(*dbtable));
+
+ return (result);
+}
+
+static inline void
+dbtable_free(dns_dbtable_t *dbtable) {
+ /*
+ * Caller must ensure that it is safe to call.
+ */
+
+ RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
+
+ if (dbtable->default_db != NULL)
+ dns_db_detach(&dbtable->default_db);
+
+ dns_rbt_destroy(&dbtable->rbt);
+
+ RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
+
+ isc_rwlock_destroy(&dbtable->tree_lock);
+
+ dbtable->magic = 0;
+
+ isc_mem_put(dbtable->mctx, dbtable, sizeof(*dbtable));
+}
+
+void
+dns_dbtable_attach(dns_dbtable_t *source, dns_dbtable_t **targetp) {
+ REQUIRE(VALID_DBTABLE(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ LOCK(&source->lock);
+
+ INSIST(source->references > 0);
+ source->references++;
+ INSIST(source->references != 0);
+
+ UNLOCK(&source->lock);
+
+ *targetp = source;
+}
+
+void
+dns_dbtable_detach(dns_dbtable_t **dbtablep) {
+ dns_dbtable_t *dbtable;
+ isc_boolean_t free_dbtable = ISC_FALSE;
+
+ REQUIRE(dbtablep != NULL);
+ dbtable = *dbtablep;
+ REQUIRE(VALID_DBTABLE(dbtable));
+
+ LOCK(&dbtable->lock);
+
+ INSIST(dbtable->references > 0);
+ dbtable->references--;
+ if (dbtable->references == 0)
+ free_dbtable = ISC_TRUE;
+
+ UNLOCK(&dbtable->lock);
+
+ if (free_dbtable)
+ dbtable_free(dbtable);
+
+ *dbtablep = NULL;
+}
+
+isc_result_t
+dns_dbtable_add(dns_dbtable_t *dbtable, dns_db_t *db) {
+ isc_result_t result;
+ dns_db_t *clone;
+
+ REQUIRE(VALID_DBTABLE(dbtable));
+ REQUIRE(dns_db_class(db) == dbtable->rdclass);
+
+ clone = NULL;
+ dns_db_attach(db, &clone);
+
+ RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
+ result = dns_rbt_addname(dbtable->rbt, dns_db_origin(clone), clone);
+ RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
+
+ return (result);
+}
+
+void
+dns_dbtable_remove(dns_dbtable_t *dbtable, dns_db_t *db) {
+ dns_db_t *stored_data = NULL;
+ isc_result_t result;
+ dns_name_t *name;
+
+ REQUIRE(VALID_DBTABLE(dbtable));
+
+ name = dns_db_origin(db);
+
+ /*
+ * There is a requirement that the association of name with db
+ * be verified. With the current rbt.c this is expensive to do,
+ * because effectively two find operations are being done, but
+ * deletion is relatively infrequent.
+ * XXXDCL ... this could be cheaper now with dns_rbt_deletenode.
+ */
+
+ RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
+
+ result = dns_rbt_findname(dbtable->rbt, name, 0, NULL,
+ (void **) (void *)&stored_data);
+
+ if (result == ISC_R_SUCCESS) {
+ INSIST(stored_data == db);
+
+ (void)dns_rbt_deletename(dbtable->rbt, name, ISC_FALSE);
+ }
+
+ RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
+}
+
+void
+dns_dbtable_adddefault(dns_dbtable_t *dbtable, dns_db_t *db) {
+ REQUIRE(VALID_DBTABLE(dbtable));
+ REQUIRE(dbtable->default_db == NULL);
+ REQUIRE(dns_name_compare(dns_db_origin(db), dns_rootname) == 0);
+
+ RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
+
+ dbtable->default_db = NULL;
+ dns_db_attach(db, &dbtable->default_db);
+
+ RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
+}
+
+void
+dns_dbtable_getdefault(dns_dbtable_t *dbtable, dns_db_t **dbp) {
+ REQUIRE(VALID_DBTABLE(dbtable));
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ RWLOCK(&dbtable->tree_lock, isc_rwlocktype_read);
+
+ dns_db_attach(dbtable->default_db, dbp);
+
+ RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_read);
+}
+
+void
+dns_dbtable_removedefault(dns_dbtable_t *dbtable) {
+ REQUIRE(VALID_DBTABLE(dbtable));
+
+ RWLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
+
+ dns_db_detach(&dbtable->default_db);
+
+ RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_write);
+}
+
+isc_result_t
+dns_dbtable_find(dns_dbtable_t *dbtable, dns_name_t *name,
+ unsigned int options, dns_db_t **dbp)
+{
+ dns_db_t *stored_data = NULL;
+ isc_result_t result;
+ unsigned int rbtoptions = 0;
+
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ if ((options & DNS_DBTABLEFIND_NOEXACT) != 0)
+ rbtoptions |= DNS_RBTFIND_NOEXACT;
+
+ RWLOCK(&dbtable->tree_lock, isc_rwlocktype_read);
+
+ result = dns_rbt_findname(dbtable->rbt, name, rbtoptions, NULL,
+ (void **) (void *)&stored_data);
+
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+ dns_db_attach(stored_data, dbp);
+ else if (dbtable->default_db != NULL) {
+ dns_db_attach(dbtable->default_db, dbp);
+ result = DNS_R_PARTIALMATCH;
+ } else
+ result = ISC_R_NOTFOUND;
+
+ RWUNLOCK(&dbtable->tree_lock, isc_rwlocktype_read);
+
+ return (result);
+}
diff --git a/lib/dns/diff.c b/lib/dns/diff.c
new file mode 100644
index 0000000..850ca91
--- /dev/null
+++ b/lib/dns/diff.c
@@ -0,0 +1,638 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 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
+ * 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: diff.c,v 1.18 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/diff.h>
+#include <dns/log.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+#define DIFF_COMMON_LOGARGS \
+ dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_DIFF
+
+static dns_rdatatype_t
+rdata_covers(dns_rdata_t *rdata) {
+ return (rdata->type == dns_rdatatype_rrsig ?
+ dns_rdata_covers(rdata) : 0);
+}
+
+isc_result_t
+dns_difftuple_create(isc_mem_t *mctx,
+ dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
+ dns_rdata_t *rdata, dns_difftuple_t **tp)
+{
+ dns_difftuple_t *t;
+ unsigned int size;
+ unsigned char *datap;
+
+ REQUIRE(tp != NULL && *tp == NULL);
+
+ /*
+ * Create a new tuple. The variable-size wire-format name data and
+ * rdata immediately follow the dns_difftuple_t structure
+ * in memory.
+ */
+ size = sizeof(*t) + name->length + rdata->length;
+ t = isc_mem_allocate(mctx, size);
+ if (t == NULL)
+ return (ISC_R_NOMEMORY);
+ t->mctx = mctx;
+ t->op = op;
+
+ datap = (unsigned char *)(t + 1);
+
+ memcpy(datap, name->ndata, name->length);
+ dns_name_init(&t->name, NULL);
+ dns_name_clone(name, &t->name);
+ t->name.ndata = datap;
+ datap += name->length;
+
+ t->ttl = ttl;
+
+ memcpy(datap, rdata->data, rdata->length);
+ dns_rdata_init(&t->rdata);
+ dns_rdata_clone(rdata, &t->rdata);
+ t->rdata.data = datap;
+ datap += rdata->length;
+
+ ISC_LINK_INIT(&t->rdata, link);
+ ISC_LINK_INIT(t, link);
+ t->magic = DNS_DIFFTUPLE_MAGIC;
+
+ INSIST(datap == (unsigned char *)t + size);
+
+ *tp = t;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_difftuple_free(dns_difftuple_t **tp) {
+ dns_difftuple_t *t = *tp;
+ REQUIRE(DNS_DIFFTUPLE_VALID(t));
+ dns_name_invalidate(&t->name);
+ t->magic = 0;
+ isc_mem_free(t->mctx, t);
+ *tp = NULL;
+}
+
+isc_result_t
+dns_difftuple_copy(dns_difftuple_t *orig, dns_difftuple_t **copyp) {
+ return (dns_difftuple_create(orig->mctx, orig->op, &orig->name,
+ orig->ttl, &orig->rdata, copyp));
+}
+
+void
+dns_diff_init(isc_mem_t *mctx, dns_diff_t *diff) {
+ diff->mctx = mctx;
+ diff->resign = 0;
+ ISC_LIST_INIT(diff->tuples);
+ diff->magic = DNS_DIFF_MAGIC;
+}
+
+void
+dns_diff_clear(dns_diff_t *diff) {
+ dns_difftuple_t *t;
+ REQUIRE(DNS_DIFF_VALID(diff));
+ while ((t = ISC_LIST_HEAD(diff->tuples)) != NULL) {
+ ISC_LIST_UNLINK(diff->tuples, t, link);
+ dns_difftuple_free(&t);
+ }
+ ENSURE(ISC_LIST_EMPTY(diff->tuples));
+}
+
+void
+dns_diff_append(dns_diff_t *diff, dns_difftuple_t **tuplep)
+{
+ ISC_LIST_APPEND(diff->tuples, *tuplep, link);
+ *tuplep = NULL;
+}
+
+/* XXX this is O(N) */
+
+void
+dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuplep)
+{
+ dns_difftuple_t *ot, *next_ot;
+
+ REQUIRE(DNS_DIFF_VALID(diff));
+ REQUIRE(DNS_DIFFTUPLE_VALID(*tuplep));
+
+ /*
+ * Look for an existing tuple with the same owner name,
+ * rdata, and TTL. If we are doing an addition and find a
+ * deletion or vice versa, remove both the old and the
+ * new tuple since they cancel each other out (assuming
+ * that we never delete nonexistent data or add existing
+ * data).
+ *
+ * If we find an old update of the same kind as
+ * the one we are doing, there must be a programming
+ * error. We report it but try to continue anyway.
+ */
+ for (ot = ISC_LIST_HEAD(diff->tuples); ot != NULL;
+ ot = next_ot)
+ {
+ next_ot = ISC_LIST_NEXT(ot, link);
+ if (dns_name_equal(&ot->name, &(*tuplep)->name) &&
+ dns_rdata_compare(&ot->rdata, &(*tuplep)->rdata) == 0 &&
+ ot->ttl == (*tuplep)->ttl)
+ {
+ ISC_LIST_UNLINK(diff->tuples, ot, link);
+ if ((*tuplep)->op == ot->op) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "unexpected non-minimal diff");
+ } else {
+ dns_difftuple_free(tuplep);
+ }
+ dns_difftuple_free(&ot);
+ break;
+ }
+ }
+
+ if (*tuplep != NULL) {
+ ISC_LIST_APPEND(diff->tuples, *tuplep, link);
+ *tuplep = NULL;
+ }
+
+ ENSURE(*tuplep == NULL);
+}
+
+static isc_stdtime_t
+setresign(dns_rdataset_t *modified, isc_uint32_t delta) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t sig;
+ isc_stdtime_t when;
+ isc_result_t result;
+
+ result = dns_rdataset_first(modified);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdataset_current(modified, &rdata);
+ (void)dns_rdata_tostruct(&rdata, &sig, NULL);
+ if ((rdata.flags & DNS_RDATA_OFFLINE) != 0)
+ when = 0;
+ else
+ when = sig.timeexpire - delta;
+ dns_rdata_reset(&rdata);
+
+ result = dns_rdataset_next(modified);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(modified, &rdata);
+ (void)dns_rdata_tostruct(&rdata, &sig, NULL);
+ if ((rdata.flags & DNS_RDATA_OFFLINE) != 0) {
+ goto next_rr;
+ }
+ if (when == 0 || sig.timeexpire - delta < when)
+ when = sig.timeexpire - delta;
+ next_rr:
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(modified);
+ }
+ INSIST(result == ISC_R_NOMORE);
+ return (when);
+}
+
+static isc_result_t
+diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver,
+ isc_boolean_t warn)
+{
+ dns_difftuple_t *t;
+ dns_dbnode_t *node = NULL;
+ isc_result_t result;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+
+ REQUIRE(DNS_DIFF_VALID(diff));
+ REQUIRE(DNS_DB_VALID(db));
+
+ t = ISC_LIST_HEAD(diff->tuples);
+ while (t != NULL) {
+ dns_name_t *name;
+
+ INSIST(node == NULL);
+ name = &t->name;
+ /*
+ * Find the node.
+ * We create the node if it does not exist.
+ * This will cause an empty node to be created if the diff
+ * contains a deletion of an RR at a nonexistent name,
+ * but such diffs should never be created in the first
+ * place.
+ */
+
+ while (t != NULL && dns_name_equal(&t->name, name)) {
+ dns_rdatatype_t type, covers;
+ dns_diffop_t op;
+ dns_rdatalist_t rdl;
+ dns_rdataset_t rds;
+ dns_rdataset_t ardataset;
+ dns_rdataset_t *modified = NULL;
+ isc_boolean_t offline;
+
+ op = t->op;
+ type = t->rdata.type;
+ covers = rdata_covers(&t->rdata);
+
+ /*
+ * Collect a contiguous set of updates with
+ * the same operation (add/delete) and RR type
+ * into a single rdatalist so that the
+ * database rrset merging/subtraction code
+ * can work more efficiently than if each
+ * RR were merged into / subtracted from
+ * the database separately.
+ *
+ * This is done by linking rdata structures from the
+ * diff into "rdatalist". This uses the rdata link
+ * field, not the diff link field, so the structure
+ * of the diff itself is not affected.
+ */
+
+ rdl.type = type;
+ rdl.covers = covers;
+ rdl.rdclass = t->rdata.rdclass;
+ rdl.ttl = t->ttl;
+ ISC_LIST_INIT(rdl.rdata);
+ ISC_LINK_INIT(&rdl, link);
+
+ node = NULL;
+ if (type != dns_rdatatype_nsec3 &&
+ covers != dns_rdatatype_nsec3)
+ CHECK(dns_db_findnode(db, name, ISC_TRUE,
+ &node));
+ else
+ CHECK(dns_db_findnsec3node(db, name, ISC_TRUE,
+ &node));
+
+ offline = ISC_FALSE;
+ while (t != NULL &&
+ dns_name_equal(&t->name, name) &&
+ t->op == op &&
+ t->rdata.type == type &&
+ rdata_covers(&t->rdata) == covers)
+ {
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(t->rdata.type, typebuf,
+ sizeof(typebuf));
+ dns_rdataclass_format(t->rdata.rdclass,
+ classbuf,
+ sizeof(classbuf));
+ if (t->ttl != rdl.ttl && warn)
+ isc_log_write(DIFF_COMMON_LOGARGS,
+ ISC_LOG_WARNING,
+ "'%s/%s/%s': TTL differs in "
+ "rdataset, adjusting "
+ "%lu -> %lu",
+ namebuf, typebuf, classbuf,
+ (unsigned long) t->ttl,
+ (unsigned long) rdl.ttl);
+ if (t->rdata.flags & DNS_RDATA_OFFLINE)
+ offline = ISC_TRUE;
+ ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
+ t = ISC_LIST_NEXT(t, link);
+ }
+
+ /*
+ * Convert the rdatalist into a rdataset.
+ */
+ dns_rdataset_init(&rds);
+ CHECK(dns_rdatalist_tordataset(&rdl, &rds));
+ if (rds.type == dns_rdatatype_rrsig)
+ switch (op) {
+ case DNS_DIFFOP_ADDRESIGN:
+ case DNS_DIFFOP_DELRESIGN:
+ modified = &ardataset;
+ dns_rdataset_init(modified);
+ break;
+ default:
+ break;
+ }
+ rds.trust = dns_trust_ultimate;
+
+ /*
+ * Merge the rdataset into the database.
+ */
+ switch (op) {
+ case DNS_DIFFOP_ADD:
+ case DNS_DIFFOP_ADDRESIGN:
+ result = dns_db_addrdataset(db, node, ver,
+ 0, &rds,
+ DNS_DBADD_MERGE|
+ DNS_DBADD_EXACT|
+ DNS_DBADD_EXACTTTL,
+ modified);
+ break;
+ case DNS_DIFFOP_DEL:
+ case DNS_DIFFOP_DELRESIGN:
+ result = dns_db_subtractrdataset(db, node, ver,
+ &rds,
+ DNS_DBSUB_EXACT,
+ modified);
+ break;
+ default:
+ INSIST(0);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ if (modified != NULL) {
+ isc_stdtime_t resign;
+ resign = setresign(modified,
+ diff->resign);
+ dns_db_setsigningtime(db, modified,
+ resign);
+ }
+ } else if (result == DNS_R_UNCHANGED) {
+ /*
+ * This will not happen when executing a
+ * dynamic update, because that code will
+ * generate strictly minimal diffs.
+ * It may happen when receiving an IXFR
+ * from a server that is not as careful.
+ * Issue a warning and continue.
+ */
+ if (warn)
+ isc_log_write(DIFF_COMMON_LOGARGS,
+ ISC_LOG_WARNING,
+ "update with no effect");
+ } else if (result == DNS_R_NXRRSET) {
+ /*
+ * OK.
+ */
+ } else {
+ if (modified != NULL &&
+ dns_rdataset_isassociated(modified))
+ dns_rdataset_disassociate(modified);
+ CHECK(result);
+ }
+ dns_db_detachnode(db, &node);
+ if (modified != NULL &&
+ dns_rdataset_isassociated(modified))
+ dns_rdataset_disassociate(modified);
+ }
+ }
+ return (ISC_R_SUCCESS);
+
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+isc_result_t
+dns_diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver) {
+ return (diff_apply(diff, db, ver, ISC_TRUE));
+}
+
+isc_result_t
+dns_diff_applysilently(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver) {
+ return (diff_apply(diff, db, ver, ISC_FALSE));
+}
+
+/* XXX this duplicates lots of code in diff_apply(). */
+
+isc_result_t
+dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
+ void *add_private)
+{
+ dns_difftuple_t *t;
+ isc_result_t result;
+
+ REQUIRE(DNS_DIFF_VALID(diff));
+
+ t = ISC_LIST_HEAD(diff->tuples);
+ while (t != NULL) {
+ dns_name_t *name;
+
+ name = &t->name;
+ while (t != NULL && dns_name_equal(&t->name, name)) {
+ dns_rdatatype_t type, covers;
+ dns_diffop_t op;
+ dns_rdatalist_t rdl;
+ dns_rdataset_t rds;
+
+ op = t->op;
+ type = t->rdata.type;
+ covers = rdata_covers(&t->rdata);
+
+ rdl.type = type;
+ rdl.covers = covers;
+ rdl.rdclass = t->rdata.rdclass;
+ rdl.ttl = t->ttl;
+ ISC_LIST_INIT(rdl.rdata);
+ ISC_LINK_INIT(&rdl, link);
+
+ while (t != NULL && dns_name_equal(&t->name, name) &&
+ t->op == op && t->rdata.type == type &&
+ rdata_covers(&t->rdata) == covers)
+ {
+ ISC_LIST_APPEND(rdl.rdata, &t->rdata, link);
+ t = ISC_LIST_NEXT(t, link);
+ }
+
+ /*
+ * Convert the rdatalist into a rdataset.
+ */
+ dns_rdataset_init(&rds);
+ CHECK(dns_rdatalist_tordataset(&rdl, &rds));
+ rds.trust = dns_trust_ultimate;
+
+ INSIST(op == DNS_DIFFOP_ADD);
+ result = (*addfunc)(add_private, name, &rds);
+ if (result == DNS_R_UNCHANGED) {
+ isc_log_write(DIFF_COMMON_LOGARGS,
+ ISC_LOG_WARNING,
+ "update with no effect");
+ } else if (result == ISC_R_SUCCESS ||
+ result == DNS_R_NXRRSET) {
+ /*
+ * OK.
+ */
+ } else {
+ CHECK(result);
+ }
+ }
+ }
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+/*
+ * XXX uses qsort(); a merge sort would be more natural for lists,
+ * and perhaps safer wrt thread stack overflow.
+ */
+isc_result_t
+dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare) {
+ unsigned int length = 0;
+ unsigned int i;
+ dns_difftuple_t **v;
+ dns_difftuple_t *p;
+ REQUIRE(DNS_DIFF_VALID(diff));
+
+ for (p = ISC_LIST_HEAD(diff->tuples);
+ p != NULL;
+ p = ISC_LIST_NEXT(p, link))
+ length++;
+ if (length == 0)
+ return (ISC_R_SUCCESS);
+ v = isc_mem_get(diff->mctx, length * sizeof(dns_difftuple_t *));
+ if (v == NULL)
+ return (ISC_R_NOMEMORY);
+ i = 0;
+ for (i = 0; i < length; i++) {
+ p = ISC_LIST_HEAD(diff->tuples);
+ v[i] = p;
+ ISC_LIST_UNLINK(diff->tuples, p, link);
+ }
+ INSIST(ISC_LIST_HEAD(diff->tuples) == NULL);
+ qsort(v, length, sizeof(v[0]), compare);
+ for (i = 0; i < length; i++) {
+ ISC_LIST_APPEND(diff->tuples, v[i], link);
+ }
+ isc_mem_put(diff->mctx, v, length * sizeof(dns_difftuple_t *));
+ return (ISC_R_SUCCESS);
+}
+
+
+/*
+ * Create an rdataset containing the single RR of the given
+ * tuple. The caller must allocate the the rdata, rdataset and
+ * an rdatalist structure for it to refer to.
+ */
+
+static isc_result_t
+diff_tuple_tordataset(dns_difftuple_t *t, dns_rdata_t *rdata,
+ dns_rdatalist_t *rdl, dns_rdataset_t *rds)
+{
+ REQUIRE(DNS_DIFFTUPLE_VALID(t));
+ REQUIRE(rdl != NULL);
+ REQUIRE(rds != NULL);
+
+ rdl->type = t->rdata.type;
+ rdl->rdclass = t->rdata.rdclass;
+ rdl->ttl = t->ttl;
+ ISC_LIST_INIT(rdl->rdata);
+ ISC_LINK_INIT(rdl, link);
+ dns_rdataset_init(rds);
+ ISC_LINK_INIT(rdata, link);
+ dns_rdata_clone(&t->rdata, rdata);
+ ISC_LIST_APPEND(rdl->rdata, rdata, link);
+ return (dns_rdatalist_tordataset(rdl, rds));
+}
+
+isc_result_t
+dns_diff_print(dns_diff_t *diff, FILE *file) {
+ isc_result_t result;
+ dns_difftuple_t *t;
+ char *mem = NULL;
+ unsigned int size = 2048;
+ const char *op = NULL;
+
+ REQUIRE(DNS_DIFF_VALID(diff));
+
+ mem = isc_mem_get(diff->mctx, size);
+ if (mem == NULL)
+ return (ISC_R_NOMEMORY);
+
+ for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
+ t = ISC_LIST_NEXT(t, link))
+ {
+ isc_buffer_t buf;
+ isc_region_t r;
+
+ dns_rdatalist_t rdl;
+ dns_rdataset_t rds;
+ dns_rdata_t rd = DNS_RDATA_INIT;
+
+ result = diff_tuple_tordataset(t, &rd, &rdl, &rds);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "diff_tuple_tordataset failed: %s",
+ dns_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+ again:
+ isc_buffer_init(&buf, mem, size);
+ result = dns_rdataset_totext(&rds, &t->name,
+ ISC_FALSE, ISC_FALSE, &buf);
+
+ if (result == ISC_R_NOSPACE) {
+ isc_mem_put(diff->mctx, mem, size);
+ size += 1024;
+ mem = isc_mem_get(diff->mctx, size);
+ if (mem == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ goto again;
+ }
+
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ /*
+ * Get rid of final newline.
+ */
+ INSIST(buf.used >= 1 &&
+ ((char *) buf.base)[buf.used-1] == '\n');
+ buf.used--;
+
+ isc_buffer_usedregion(&buf, &r);
+ switch (t->op) {
+ case DNS_DIFFOP_EXISTS: op = "exists"; break;
+ case DNS_DIFFOP_ADD: op = "add"; break;
+ case DNS_DIFFOP_DEL: op = "del"; break;
+ case DNS_DIFFOP_ADDRESIGN: op = "add re-sign"; break;
+ case DNS_DIFFOP_DELRESIGN: op = "del re-sign"; break;
+ }
+ if (file != NULL)
+ fprintf(file, "%s %.*s\n", op, (int) r.length,
+ (char *) r.base);
+ else
+ isc_log_write(DIFF_COMMON_LOGARGS, ISC_LOG_DEBUG(7),
+ "%s %.*s", op, (int) r.length,
+ (char *) r.base);
+ }
+ result = ISC_R_SUCCESS;
+ cleanup:
+ if (mem != NULL)
+ isc_mem_put(diff->mctx, mem, size);
+ return (result);
+}
diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c
new file mode 100644
index 0000000..4ab2f3e
--- /dev/null
+++ b/lib/dns/dispatch.c
@@ -0,0 +1,3436 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: dispatch.c,v 1.155 2008/11/12 23:10:57 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/portset.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/portlist.h>
+#include <dns/stats.h>
+#include <dns/tcpmsg.h>
+#include <dns/types.h>
+
+typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
+
+typedef struct dispsocket dispsocket_t;
+typedef ISC_LIST(dispsocket_t) dispsocketlist_t;
+
+typedef struct dispportentry dispportentry_t;
+typedef ISC_LIST(dispportentry_t) dispportlist_t;
+
+/* ARC4 Random generator state */
+typedef struct arc4ctx {
+ isc_uint8_t i;
+ isc_uint8_t j;
+ isc_uint8_t s[256];
+ int count;
+ isc_entropy_t *entropy; /*%< entropy source for ARC4 */
+ isc_mutex_t *lock;
+} arc4ctx_t;
+
+typedef struct dns_qid {
+ unsigned int magic;
+ unsigned int qid_nbuckets; /*%< hash table size */
+ unsigned int qid_increment; /*%< id increment on collision */
+ isc_mutex_t lock;
+ dns_displist_t *qid_table; /*%< the table itself */
+ dispsocketlist_t *sock_table; /*%< socket table */
+} dns_qid_t;
+
+struct dns_dispatchmgr {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t *mctx;
+ dns_acl_t *blackhole;
+ dns_portlist_t *portlist;
+ dns_stats_t *stats;
+ isc_entropy_t *entropy; /*%< entropy source */
+
+ /* Locked by "lock". */
+ isc_mutex_t lock;
+ unsigned int state;
+ ISC_LIST(dns_dispatch_t) list;
+
+ /* Locked by arc4_lock. */
+ isc_mutex_t arc4_lock;
+ arc4ctx_t arc4ctx; /*%< ARC4 context for QID */
+
+ /* locked by buffer lock */
+ dns_qid_t *qid;
+ isc_mutex_t buffer_lock;
+ unsigned int buffers; /*%< allocated buffers */
+ unsigned int buffersize; /*%< size of each buffer */
+ unsigned int maxbuffers; /*%< max buffers */
+
+ /* Locked internally. */
+ isc_mutex_t pool_lock;
+ isc_mempool_t *epool; /*%< memory pool for events */
+ isc_mempool_t *rpool; /*%< memory pool for replies */
+ isc_mempool_t *dpool; /*%< dispatch allocations */
+ isc_mempool_t *bpool; /*%< memory pool for buffers */
+ isc_mempool_t *spool; /*%< memory pool for dispsocs */
+
+ /*%
+ * Locked by qid->lock if qid exists; otherwise, can be used without
+ * being locked.
+ * Memory footprint considerations: this is a simple implementation of
+ * available ports, i.e., an ordered array of the actual port numbers.
+ * This will require about 256KB of memory in the worst case (128KB for
+ * each of IPv4 and IPv6). We could reduce it by representing it as a
+ * more sophisticated way such as a list (or array) of ranges that are
+ * searched to identify a specific port. Our decision here is the saved
+ * memory isn't worth the implementation complexity, considering the
+ * fact that the whole BIND9 process (which is mainly named) already
+ * requires a pretty large memory footprint. We may, however, have to
+ * revisit the decision when we want to use it as a separate module for
+ * an environment where memory requirement is severer.
+ */
+ in_port_t *v4ports; /*%< available ports for IPv4 */
+ unsigned int nv4ports; /*%< # of available ports for IPv4 */
+ in_port_t *v6ports; /*%< available ports for IPv4 */
+ unsigned int nv6ports; /*%< # of available ports for IPv4 */
+};
+
+#define MGR_SHUTTINGDOWN 0x00000001U
+#define MGR_IS_SHUTTINGDOWN(l) (((l)->state & MGR_SHUTTINGDOWN) != 0)
+
+#define IS_PRIVATE(d) (((d)->attributes & DNS_DISPATCHATTR_PRIVATE) != 0)
+
+struct dns_dispentry {
+ unsigned int magic;
+ dns_dispatch_t *disp;
+ dns_messageid_t id;
+ in_port_t port;
+ unsigned int bucket;
+ isc_sockaddr_t host;
+ isc_task_t *task;
+ isc_taskaction_t action;
+ void *arg;
+ isc_boolean_t item_out;
+ dispsocket_t *dispsocket;
+ ISC_LIST(dns_dispatchevent_t) items;
+ ISC_LINK(dns_dispentry_t) link;
+};
+
+/*%
+ * Maximum number of dispatch sockets that can be pooled for reuse. The
+ * appropriate value may vary, but experiments have shown a busy caching server
+ * may need more than 1000 sockets concurrently opened. The maximum allowable
+ * number of dispatch sockets (per manager) will be set to the double of this
+ * value.
+ */
+#ifndef DNS_DISPATCH_POOLSOCKS
+#define DNS_DISPATCH_POOLSOCKS 2048
+#endif
+
+/*%
+ * Quota to control the number of dispatch sockets. If a dispatch has more
+ * than the quota of sockets, new queries will purge oldest ones, so that
+ * a massive number of outstanding queries won't prevent subsequent queries
+ * (especially if the older ones take longer time and result in timeout).
+ */
+#ifndef DNS_DISPATCH_SOCKSQUOTA
+#define DNS_DISPATCH_SOCKSQUOTA 3072
+#endif
+
+struct dispsocket {
+ unsigned int magic;
+ isc_socket_t *socket;
+ dns_dispatch_t *disp;
+ isc_sockaddr_t host;
+ in_port_t localport; /* XXX: should be removed later */
+ dispportentry_t *portentry;
+ dns_dispentry_t *resp;
+ isc_task_t *task;
+ ISC_LINK(dispsocket_t) link;
+ unsigned int bucket;
+ ISC_LINK(dispsocket_t) blink;
+};
+
+/*%
+ * A port table entry. We remember every port we first open in a table with a
+ * reference counter so that we can 'reuse' the same port (with different
+ * destination addresses) using the SO_REUSEADDR socket option.
+ */
+struct dispportentry {
+ in_port_t port;
+ unsigned int refs;
+ ISC_LINK(struct dispportentry) link;
+};
+
+#ifndef DNS_DISPATCH_PORTTABLESIZE
+#define DNS_DISPATCH_PORTTABLESIZE 1024
+#endif
+
+#define INVALID_BUCKET (0xffffdead)
+
+/*%
+ * Number of tasks for each dispatch that use separate sockets for different
+ * transactions. This must be a power of 2 as it will divide 32 bit numbers
+ * to get an uniformly random tasks selection. See get_dispsocket().
+ */
+#define MAX_INTERNAL_TASKS 64
+
+struct dns_dispatch {
+ /* Unlocked. */
+ unsigned int magic; /*%< magic */
+ dns_dispatchmgr_t *mgr; /*%< dispatch manager */
+ int ntasks;
+ /*%
+ * internal task buckets. We use multiple tasks to distribute various
+ * socket events well when using separate dispatch sockets. We use the
+ * 1st task (task[0]) for internal control events.
+ */
+ isc_task_t *task[MAX_INTERNAL_TASKS];
+ isc_socket_t *socket; /*%< isc socket attached to */
+ isc_sockaddr_t local; /*%< local address */
+ in_port_t localport; /*%< local UDP port */
+ unsigned int maxrequests; /*%< max requests */
+ isc_event_t *ctlevent;
+
+ /*% Locked by mgr->lock. */
+ ISC_LINK(dns_dispatch_t) link;
+
+ /* Locked by "lock". */
+ isc_mutex_t lock; /*%< locks all below */
+ isc_sockettype_t socktype;
+ unsigned int attributes;
+ unsigned int refcount; /*%< number of users */
+ dns_dispatchevent_t *failsafe_ev; /*%< failsafe cancel event */
+ unsigned int shutting_down : 1,
+ shutdown_out : 1,
+ connected : 1,
+ tcpmsg_valid : 1,
+ recv_pending : 1; /*%< is a recv() pending? */
+ isc_result_t shutdown_why;
+ ISC_LIST(dispsocket_t) activesockets;
+ ISC_LIST(dispsocket_t) inactivesockets;
+ unsigned int nsockets;
+ unsigned int requests; /*%< how many requests we have */
+ unsigned int tcpbuffers; /*%< allocated buffers */
+ dns_tcpmsg_t tcpmsg; /*%< for tcp streams */
+ dns_qid_t *qid;
+ arc4ctx_t arc4ctx; /*%< for QID/UDP port num */
+ dispportlist_t *port_table; /*%< hold ports 'owned' by us */
+ isc_mempool_t *portpool; /*%< port table entries */
+};
+
+#define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ')
+#define VALID_QID(e) ISC_MAGIC_VALID((e), QID_MAGIC)
+
+#define RESPONSE_MAGIC ISC_MAGIC('D', 'r', 's', 'p')
+#define VALID_RESPONSE(e) ISC_MAGIC_VALID((e), RESPONSE_MAGIC)
+
+#define DISPSOCK_MAGIC ISC_MAGIC('D', 's', 'o', 'c')
+#define VALID_DISPSOCK(e) ISC_MAGIC_VALID((e), DISPSOCK_MAGIC)
+
+#define DISPATCH_MAGIC ISC_MAGIC('D', 'i', 's', 'p')
+#define VALID_DISPATCH(e) ISC_MAGIC_VALID((e), DISPATCH_MAGIC)
+
+#define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r')
+#define VALID_DISPATCHMGR(e) ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)
+
+#define DNS_QID(disp) ((disp)->socktype == isc_sockettype_tcp) ? \
+ (disp)->qid : (disp)->mgr->qid
+#define DISP_ARC4CTX(disp) ((disp)->socktype == isc_sockettype_udp) ? \
+ (&(disp)->arc4ctx) : (&(disp)->mgr->arc4ctx)
+
+/*%
+ * Locking a query port buffer is a bit tricky. We access the buffer without
+ * locking until qid is created. Technically, there is a possibility of race
+ * between the creation of qid and access to the port buffer; in practice,
+ * however, this should be safe because qid isn't created until the first
+ * dispatch is created and there should be no contending situation until then.
+ */
+#define PORTBUFLOCK(mgr) if ((mgr)->qid != NULL) LOCK(&((mgr)->qid->lock))
+#define PORTBUFUNLOCK(mgr) if ((mgr)->qid != NULL) UNLOCK((&(mgr)->qid->lock))
+
+/*
+ * Statics.
+ */
+static dns_dispentry_t *entry_search(dns_qid_t *, isc_sockaddr_t *,
+ dns_messageid_t, in_port_t, unsigned int);
+static isc_boolean_t destroy_disp_ok(dns_dispatch_t *);
+static void destroy_disp(isc_task_t *task, isc_event_t *event);
+static void destroy_dispsocket(dns_dispatch_t *, dispsocket_t **);
+static void deactivate_dispsocket(dns_dispatch_t *, dispsocket_t *);
+static void udp_exrecv(isc_task_t *, isc_event_t *);
+static void udp_shrecv(isc_task_t *, isc_event_t *);
+static void udp_recv(isc_event_t *, dns_dispatch_t *, dispsocket_t *);
+static void tcp_recv(isc_task_t *, isc_event_t *);
+static isc_result_t startrecv(dns_dispatch_t *, dispsocket_t *);
+static isc_uint32_t dns_hash(dns_qid_t *, isc_sockaddr_t *, dns_messageid_t,
+ in_port_t);
+static void free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);
+static void *allocate_udp_buffer(dns_dispatch_t *disp);
+static inline void free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev);
+static inline dns_dispatchevent_t *allocate_event(dns_dispatch_t *disp);
+static void do_cancel(dns_dispatch_t *disp);
+static dns_dispentry_t *linear_first(dns_qid_t *disp);
+static dns_dispentry_t *linear_next(dns_qid_t *disp,
+ dns_dispentry_t *resp);
+static void dispatch_free(dns_dispatch_t **dispp);
+static isc_result_t get_udpsocket(dns_dispatchmgr_t *mgr,
+ dns_dispatch_t *disp,
+ isc_socketmgr_t *sockmgr,
+ isc_sockaddr_t *localaddr,
+ isc_socket_t **sockp);
+static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
+ isc_socketmgr_t *sockmgr,
+ isc_taskmgr_t *taskmgr,
+ isc_sockaddr_t *localaddr,
+ unsigned int maxrequests,
+ unsigned int attributes,
+ dns_dispatch_t **dispp);
+static isc_boolean_t destroy_mgr_ok(dns_dispatchmgr_t *mgr);
+static void destroy_mgr(dns_dispatchmgr_t **mgrp);
+static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
+ unsigned int increment, dns_qid_t **qidp,
+ isc_boolean_t needaddrtable);
+static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
+static isc_result_t open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
+ unsigned int options, isc_socket_t **sockp);
+static isc_boolean_t portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
+ isc_sockaddr_t *sockaddrp);
+
+#define LVL(x) ISC_LOG_DEBUG(x)
+
+static void
+mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+static void
+mgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...) {
+ char msgbuf[2048];
+ va_list ap;
+
+ if (! isc_log_wouldlog(dns_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ va_end(ap);
+
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DISPATCH, DNS_LOGMODULE_DISPATCH,
+ level, "dispatchmgr %p: %s", mgr, msgbuf);
+}
+
+static void
+dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+static void
+dispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...) {
+ char msgbuf[2048];
+ va_list ap;
+
+ if (! isc_log_wouldlog(dns_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ va_end(ap);
+
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DISPATCH, DNS_LOGMODULE_DISPATCH,
+ level, "dispatch %p: %s", disp, msgbuf);
+}
+
+static void
+request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
+ int level, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(4, 5);
+
+static void
+request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
+ int level, const char *fmt, ...)
+{
+ char msgbuf[2048];
+ char peerbuf[256];
+ va_list ap;
+
+ if (! isc_log_wouldlog(dns_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ va_end(ap);
+
+ if (VALID_RESPONSE(resp)) {
+ isc_sockaddr_format(&resp->host, peerbuf, sizeof(peerbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
+ DNS_LOGMODULE_DISPATCH, level,
+ "dispatch %p response %p %s: %s", disp, resp,
+ peerbuf, msgbuf);
+ } else {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,
+ DNS_LOGMODULE_DISPATCH, level,
+ "dispatch %p req/resp %p: %s", disp, resp,
+ msgbuf);
+ }
+}
+
+/*%
+ * ARC4 random number generator derived from OpenBSD.
+ * Only dispatch_arc4random() and dispatch_arc4uniformrandom() are expected
+ * to be called from general dispatch routines; the rest of them are subroutines
+ * for these two.
+ *
+ * The original copyright follows:
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+static void
+dispatch_arc4init(arc4ctx_t *actx, isc_entropy_t *entropy, isc_mutex_t *lock) {
+ int n;
+ for (n = 0; n < 256; n++)
+ actx->s[n] = n;
+ actx->i = 0;
+ actx->j = 0;
+ actx->count = 0;
+ actx->entropy = entropy; /* don't have to attach */
+ actx->lock = lock;
+}
+
+static void
+dispatch_arc4addrandom(arc4ctx_t *actx, unsigned char *dat, int datlen) {
+ int n;
+ isc_uint8_t si;
+
+ actx->i--;
+ for (n = 0; n < 256; n++) {
+ actx->i = (actx->i + 1);
+ si = actx->s[actx->i];
+ actx->j = (actx->j + si + dat[n % datlen]);
+ actx->s[actx->i] = actx->s[actx->j];
+ actx->s[actx->j] = si;
+ }
+ actx->j = actx->i;
+}
+
+static inline isc_uint8_t
+dispatch_arc4get8(arc4ctx_t *actx) {
+ isc_uint8_t si, sj;
+
+ actx->i = (actx->i + 1);
+ si = actx->s[actx->i];
+ actx->j = (actx->j + si);
+ sj = actx->s[actx->j];
+ actx->s[actx->i] = sj;
+ actx->s[actx->j] = si;
+
+ return (actx->s[(si + sj) & 0xff]);
+}
+
+static inline isc_uint16_t
+dispatch_arc4get16(arc4ctx_t *actx) {
+ isc_uint16_t val;
+
+ val = dispatch_arc4get8(actx) << 8;
+ val |= dispatch_arc4get8(actx);
+
+ return (val);
+}
+
+static void
+dispatch_arc4stir(arc4ctx_t *actx) {
+ int i;
+ union {
+ unsigned char rnd[128];
+ isc_uint32_t rnd32[32];
+ } rnd;
+ isc_result_t result;
+
+ if (actx->entropy != NULL) {
+ /*
+ * We accept any quality of random data to avoid blocking.
+ */
+ result = isc_entropy_getdata(actx->entropy, rnd.rnd,
+ sizeof(rnd), NULL, 0);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ } else {
+ for (i = 0; i < 32; i++)
+ isc_random_get(&rnd.rnd32[i]);
+ }
+ dispatch_arc4addrandom(actx, rnd.rnd, sizeof(rnd.rnd));
+
+ /*
+ * Discard early keystream, as per recommendations in:
+ * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
+ */
+ for (i = 0; i < 256; i++)
+ (void)dispatch_arc4get8(actx);
+
+ /*
+ * Derived from OpenBSD's implementation. The rationale is not clear,
+ * but should be conservative enough in safety, and reasonably large
+ * for efficiency.
+ */
+ actx->count = 1600000;
+}
+
+static isc_uint16_t
+dispatch_arc4random(arc4ctx_t *actx) {
+ isc_uint16_t result;
+
+ if (actx->lock != NULL)
+ LOCK(actx->lock);
+
+ actx->count -= sizeof(isc_uint16_t);
+ if (actx->count <= 0)
+ dispatch_arc4stir(actx);
+ result = dispatch_arc4get16(actx);
+
+ if (actx->lock != NULL)
+ UNLOCK(actx->lock);
+
+ return (result);
+}
+
+static isc_uint16_t
+dispatch_arc4uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) {
+ isc_uint16_t min, r;
+
+ if (upper_bound < 2)
+ return (0);
+
+ /*
+ * Ensure the range of random numbers [min, 0xffff] be a multiple of
+ * upper_bound and contain at least a half of the 16 bit range.
+ */
+
+ if (upper_bound > 0x8000)
+ min = 1 + ~upper_bound; /* 0x8000 - upper_bound */
+ else
+ min = (isc_uint16_t)(0x10000 % (isc_uint32_t)upper_bound);
+
+ /*
+ * This could theoretically loop forever but each retry has
+ * p > 0.5 (worst case, usually far better) of selecting a
+ * number inside the range we need, so it should rarely need
+ * to re-roll.
+ */
+ for (;;) {
+ r = dispatch_arc4random(actx);
+ if (r >= min)
+ break;
+ }
+
+ return (r % upper_bound);
+}
+
+/*
+ * Return a hash of the destination and message id.
+ */
+static isc_uint32_t
+dns_hash(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id,
+ in_port_t port)
+{
+ unsigned int ret;
+
+ ret = isc_sockaddr_hash(dest, ISC_TRUE);
+ ret ^= (id << 16) | port;
+ ret %= qid->qid_nbuckets;
+
+ INSIST(ret < qid->qid_nbuckets);
+
+ return (ret);
+}
+
+/*
+ * Find the first entry in 'qid'. Returns NULL if there are no entries.
+ */
+static dns_dispentry_t *
+linear_first(dns_qid_t *qid) {
+ dns_dispentry_t *ret;
+ unsigned int bucket;
+
+ bucket = 0;
+
+ while (bucket < qid->qid_nbuckets) {
+ ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
+ if (ret != NULL)
+ return (ret);
+ bucket++;
+ }
+
+ return (NULL);
+}
+
+/*
+ * Find the next entry after 'resp' in 'qid'. Return NULL if there are
+ * no more entries.
+ */
+static dns_dispentry_t *
+linear_next(dns_qid_t *qid, dns_dispentry_t *resp) {
+ dns_dispentry_t *ret;
+ unsigned int bucket;
+
+ ret = ISC_LIST_NEXT(resp, link);
+ if (ret != NULL)
+ return (ret);
+
+ bucket = resp->bucket;
+ bucket++;
+ while (bucket < qid->qid_nbuckets) {
+ ret = ISC_LIST_HEAD(qid->qid_table[bucket]);
+ if (ret != NULL)
+ return (ret);
+ bucket++;
+ }
+
+ return (NULL);
+}
+
+/*
+ * The dispatch must be locked.
+ */
+static isc_boolean_t
+destroy_disp_ok(dns_dispatch_t *disp)
+{
+ if (disp->refcount != 0)
+ return (ISC_FALSE);
+
+ if (disp->recv_pending != 0)
+ return (ISC_FALSE);
+
+ if (!ISC_LIST_EMPTY(disp->activesockets))
+ return (ISC_FALSE);
+
+ if (disp->shutting_down == 0)
+ return (ISC_FALSE);
+
+ return (ISC_TRUE);
+}
+
+/*
+ * Called when refcount reaches 0 (and safe to destroy).
+ *
+ * The dispatcher must not be locked.
+ * The manager must be locked.
+ */
+static void
+destroy_disp(isc_task_t *task, isc_event_t *event) {
+ dns_dispatch_t *disp;
+ dns_dispatchmgr_t *mgr;
+ isc_boolean_t killmgr;
+ dispsocket_t *dispsocket;
+ int i;
+
+ INSIST(event->ev_type == DNS_EVENT_DISPATCHCONTROL);
+
+ UNUSED(task);
+
+ disp = event->ev_arg;
+ mgr = disp->mgr;
+
+ LOCK(&mgr->lock);
+ ISC_LIST_UNLINK(mgr->list, disp, link);
+
+ dispatch_log(disp, LVL(90),
+ "shutting down; detaching from sock %p, task %p",
+ disp->socket, disp->task[0]); /* XXXX */
+
+ if (disp->socket != NULL)
+ isc_socket_detach(&disp->socket);
+ while ((dispsocket = ISC_LIST_HEAD(disp->inactivesockets)) != NULL) {
+ ISC_LIST_UNLINK(disp->inactivesockets, dispsocket, link);
+ destroy_dispsocket(disp, &dispsocket);
+ }
+ for (i = 0; i < disp->ntasks; i++)
+ isc_task_detach(&disp->task[i]);
+ isc_event_free(&event);
+
+ dispatch_free(&disp);
+
+ killmgr = destroy_mgr_ok(mgr);
+ UNLOCK(&mgr->lock);
+ if (killmgr)
+ destroy_mgr(&mgr);
+}
+
+/*%
+ * Manipulate port table per dispatch: find an entry for a given port number,
+ * create a new entry, and decrement a given entry with possible clean-up.
+ */
+static dispportentry_t *
+port_search(dns_dispatch_t *disp, in_port_t port) {
+ dispportentry_t *portentry;
+
+ REQUIRE(disp->port_table != NULL);
+
+ portentry = ISC_LIST_HEAD(disp->port_table[port %
+ DNS_DISPATCH_PORTTABLESIZE]);
+ while (portentry != NULL) {
+ if (portentry->port == port)
+ return (portentry);
+ portentry = ISC_LIST_NEXT(portentry, link);
+ }
+
+ return (NULL);
+}
+
+static dispportentry_t *
+new_portentry(dns_dispatch_t *disp, in_port_t port) {
+ dispportentry_t *portentry;
+
+ REQUIRE(disp->port_table != NULL);
+
+ portentry = isc_mempool_get(disp->portpool);
+ if (portentry == NULL)
+ return (portentry);
+
+ portentry->port = port;
+ portentry->refs = 0;
+ ISC_LINK_INIT(portentry, link);
+ ISC_LIST_APPEND(disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE],
+ portentry, link);
+
+ return (portentry);
+}
+
+static void
+deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
+ dispportentry_t *portentry = *portentryp;
+
+ REQUIRE(disp->port_table != NULL);
+ REQUIRE(portentry != NULL && portentry->refs > 0);
+
+ portentry->refs--;
+ if (portentry->refs == 0) {
+ ISC_LIST_UNLINK(disp->port_table[portentry->port %
+ DNS_DISPATCH_PORTTABLESIZE],
+ portentry, link);
+ isc_mempool_put(disp->portpool, portentry);
+ }
+
+ *portentryp = NULL;
+}
+
+/*%
+ * Find a dispsocket for socket address 'dest', and port number 'port'.
+ * Return NULL if no such entry exists.
+ */
+static dispsocket_t *
+socket_search(dns_qid_t *qid, isc_sockaddr_t *dest, in_port_t port,
+ unsigned int bucket)
+{
+ dispsocket_t *dispsock;
+
+ REQUIRE(bucket < qid->qid_nbuckets);
+
+ dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]);
+
+ while (dispsock != NULL) {
+ if (isc_sockaddr_equal(dest, &dispsock->host) &&
+ dispsock->portentry->port == port)
+ return (dispsock);
+ dispsock = ISC_LIST_NEXT(dispsock, blink);
+ }
+
+ return (NULL);
+}
+
+/*%
+ * Make a new socket for a single dispatch with a random port number.
+ * The caller must hold the disp->lock and qid->lock.
+ */
+static isc_result_t
+get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
+ isc_socketmgr_t *sockmgr, dns_qid_t *qid,
+ dispsocket_t **dispsockp, in_port_t *portp)
+{
+ int i;
+ isc_uint32_t r;
+ dns_dispatchmgr_t *mgr = disp->mgr;
+ isc_socket_t *sock = NULL;
+ isc_result_t result = ISC_R_FAILURE;
+ in_port_t port;
+ isc_sockaddr_t localaddr;
+ unsigned int bucket = 0;
+ dispsocket_t *dispsock;
+ unsigned int nports;
+ in_port_t *ports;
+ unsigned int bindoptions = 0;
+ dispportentry_t *portentry = NULL;
+
+ if (isc_sockaddr_pf(&disp->local) == AF_INET) {
+ nports = disp->mgr->nv4ports;
+ ports = disp->mgr->v4ports;
+ } else {
+ nports = disp->mgr->nv6ports;
+ ports = disp->mgr->v6ports;
+ }
+ if (nports == 0)
+ return (ISC_R_ADDRNOTAVAIL);
+
+ dispsock = ISC_LIST_HEAD(disp->inactivesockets);
+ if (dispsock != NULL) {
+ ISC_LIST_UNLINK(disp->inactivesockets, dispsock, link);
+ sock = dispsock->socket;
+ dispsock->socket = NULL;
+ } else {
+ dispsock = isc_mempool_get(mgr->spool);
+ if (dispsock == NULL)
+ return (ISC_R_NOMEMORY);
+
+ disp->nsockets++;
+ dispsock->socket = NULL;
+ dispsock->disp = disp;
+ dispsock->resp = NULL;
+ dispsock->portentry = NULL;
+ isc_random_get(&r);
+ dispsock->task = NULL;
+ isc_task_attach(disp->task[r % disp->ntasks], &dispsock->task);
+ ISC_LINK_INIT(dispsock, link);
+ ISC_LINK_INIT(dispsock, blink);
+ dispsock->magic = DISPSOCK_MAGIC;
+ }
+
+ /*
+ * Pick up a random UDP port and open a new socket with it. Avoid
+ * choosing ports that share the same destination because it will be
+ * very likely to fail in bind(2) or connect(2).
+ */
+ localaddr = disp->local;
+ for (i = 0; i < 64; i++) {
+ port = ports[dispatch_arc4uniformrandom(DISP_ARC4CTX(disp),
+ nports)];
+ isc_sockaddr_setport(&localaddr, port);
+
+ bucket = dns_hash(qid, dest, 0, port);
+ if (socket_search(qid, dest, port, bucket) != NULL)
+ continue;
+ portentry = port_search(disp, port);
+ if (portentry != NULL)
+ bindoptions |= ISC_SOCKET_REUSEADDRESS;
+ result = open_socket(sockmgr, &localaddr, bindoptions, &sock);
+ if (result == ISC_R_SUCCESS) {
+ if (portentry == NULL) {
+ portentry = new_portentry(disp, port);
+ if (portentry == NULL) {
+ result = ISC_R_NOMEMORY;
+ break;
+ }
+ }
+ portentry->refs++;
+ break;
+ } else if (result != ISC_R_ADDRINUSE)
+ break;
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ dispsock->socket = sock;
+ dispsock->host = *dest;
+ dispsock->portentry = portentry;
+ dispsock->bucket = bucket;
+ ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink);
+ *dispsockp = dispsock;
+ *portp = port;
+ } else {
+ /*
+ * We could keep it in the inactive list, but since this should
+ * be an exceptional case and might be resource shortage, we'd
+ * rather destroy it.
+ */
+ if (sock != NULL)
+ isc_socket_detach(&sock);
+ destroy_dispsocket(disp, &dispsock);
+ }
+
+ return (result);
+}
+
+/*%
+ * Destroy a dedicated dispatch socket.
+ */
+static void
+destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
+ dispsocket_t *dispsock;
+ dns_qid_t *qid;
+
+ /*
+ * The dispatch must be locked.
+ */
+
+ REQUIRE(dispsockp != NULL && *dispsockp != NULL);
+ dispsock = *dispsockp;
+ REQUIRE(!ISC_LINK_LINKED(dispsock, link));
+
+ disp->nsockets--;
+ dispsock->magic = 0;
+ if (dispsock->portentry != NULL)
+ deref_portentry(disp, &dispsock->portentry);
+ if (dispsock->socket != NULL)
+ isc_socket_detach(&dispsock->socket);
+ if (ISC_LINK_LINKED(dispsock, blink)) {
+ qid = DNS_QID(disp);
+ LOCK(&qid->lock);
+ ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock,
+ blink);
+ UNLOCK(&qid->lock);
+ }
+ if (dispsock->task != NULL)
+ isc_task_detach(&dispsock->task);
+ isc_mempool_put(disp->mgr->spool, dispsock);
+
+ *dispsockp = NULL;
+}
+
+/*%
+ * Deactivate a dedicated dispatch socket. Move it to the inactive list for
+ * future reuse unless the total number of sockets are exceeding the maximum.
+ */
+static void
+deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
+ isc_result_t result;
+ dns_qid_t *qid;
+
+ /*
+ * The dispatch must be locked.
+ */
+ ISC_LIST_UNLINK(disp->activesockets, dispsock, link);
+ if (dispsock->resp != NULL) {
+ INSIST(dispsock->resp->dispsocket == dispsock);
+ dispsock->resp->dispsocket = NULL;
+ }
+
+ INSIST(dispsock->portentry != NULL);
+ deref_portentry(disp, &dispsock->portentry);
+
+ if (disp->nsockets > DNS_DISPATCH_POOLSOCKS)
+ destroy_dispsocket(disp, &dispsock);
+ else {
+ result = isc_socket_close(dispsock->socket);
+
+ qid = DNS_QID(disp);
+ LOCK(&qid->lock);
+ ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock,
+ blink);
+ UNLOCK(&qid->lock);
+
+ if (result == ISC_R_SUCCESS)
+ ISC_LIST_APPEND(disp->inactivesockets, dispsock, link);
+ else {
+ /*
+ * If the underlying system does not allow this
+ * optimization, destroy this temporary structure (and
+ * create a new one for a new transaction).
+ */
+ INSIST(result == ISC_R_NOTIMPLEMENTED);
+ destroy_dispsocket(disp, &dispsock);
+ }
+ }
+}
+
+/*
+ * Find an entry for query ID 'id', socket address 'dest', and port number
+ * 'port'.
+ * Return NULL if no such entry exists.
+ */
+static dns_dispentry_t *
+entry_search(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id,
+ in_port_t port, unsigned int bucket)
+{
+ dns_dispentry_t *res;
+
+ REQUIRE(bucket < qid->qid_nbuckets);
+
+ res = ISC_LIST_HEAD(qid->qid_table[bucket]);
+
+ while (res != NULL) {
+ if (res->id == id && isc_sockaddr_equal(dest, &res->host) &&
+ res->port == port) {
+ return (res);
+ }
+ res = ISC_LIST_NEXT(res, link);
+ }
+
+ return (NULL);
+}
+
+static void
+free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {
+ INSIST(buf != NULL && len != 0);
+
+
+ switch (disp->socktype) {
+ case isc_sockettype_tcp:
+ INSIST(disp->tcpbuffers > 0);
+ disp->tcpbuffers--;
+ isc_mem_put(disp->mgr->mctx, buf, len);
+ break;
+ case isc_sockettype_udp:
+ LOCK(&disp->mgr->buffer_lock);
+ INSIST(disp->mgr->buffers > 0);
+ INSIST(len == disp->mgr->buffersize);
+ disp->mgr->buffers--;
+ isc_mempool_put(disp->mgr->bpool, buf);
+ UNLOCK(&disp->mgr->buffer_lock);
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+}
+
+static void *
+allocate_udp_buffer(dns_dispatch_t *disp) {
+ void *temp;
+
+ LOCK(&disp->mgr->buffer_lock);
+ temp = isc_mempool_get(disp->mgr->bpool);
+
+ if (temp != NULL)
+ disp->mgr->buffers++;
+ UNLOCK(&disp->mgr->buffer_lock);
+
+ return (temp);
+}
+
+static inline void
+free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev) {
+ if (disp->failsafe_ev == ev) {
+ INSIST(disp->shutdown_out == 1);
+ disp->shutdown_out = 0;
+
+ return;
+ }
+
+ isc_mempool_put(disp->mgr->epool, ev);
+}
+
+static inline dns_dispatchevent_t *
+allocate_event(dns_dispatch_t *disp) {
+ dns_dispatchevent_t *ev;
+
+ ev = isc_mempool_get(disp->mgr->epool);
+ if (ev == NULL)
+ return (NULL);
+ ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, 0,
+ NULL, NULL, NULL, NULL, NULL);
+
+ return (ev);
+}
+
+static void
+udp_exrecv(isc_task_t *task, isc_event_t *ev) {
+ dispsocket_t *dispsock = ev->ev_arg;
+
+ UNUSED(task);
+
+ REQUIRE(VALID_DISPSOCK(dispsock));
+ udp_recv(ev, dispsock->disp, dispsock);
+}
+
+static void
+udp_shrecv(isc_task_t *task, isc_event_t *ev) {
+ dns_dispatch_t *disp = ev->ev_arg;
+
+ UNUSED(task);
+
+ REQUIRE(VALID_DISPATCH(disp));
+ udp_recv(ev, disp, NULL);
+}
+
+/*
+ * General flow:
+ *
+ * If I/O result == CANCELED or error, free the buffer.
+ *
+ * If query, free the buffer, restart.
+ *
+ * If response:
+ * Allocate event, fill in details.
+ * If cannot allocate, free buffer, restart.
+ * find target. If not found, free buffer, restart.
+ * if event queue is not empty, queue. else, send.
+ * restart.
+ */
+static void
+udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
+ isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
+ dns_messageid_t id;
+ isc_result_t dres;
+ isc_buffer_t source;
+ unsigned int flags;
+ dns_dispentry_t *resp = NULL;
+ dns_dispatchevent_t *rev;
+ unsigned int bucket;
+ isc_boolean_t killit;
+ isc_boolean_t queue_response;
+ dns_dispatchmgr_t *mgr;
+ dns_qid_t *qid;
+ isc_netaddr_t netaddr;
+ int match;
+ int result;
+ isc_boolean_t qidlocked = ISC_FALSE;
+
+ LOCK(&disp->lock);
+
+ mgr = disp->mgr;
+ qid = mgr->qid;
+
+ dispatch_log(disp, LVL(90),
+ "got packet: requests %d, buffers %d, recvs %d",
+ disp->requests, disp->mgr->buffers, disp->recv_pending);
+
+ if (dispsock == NULL && ev->ev_type == ISC_SOCKEVENT_RECVDONE) {
+ /*
+ * Unless the receive event was imported from a listening
+ * interface, in which case the event type is
+ * DNS_EVENT_IMPORTRECVDONE, receive operation must be pending.
+ */
+ INSIST(disp->recv_pending != 0);
+ disp->recv_pending = 0;
+ }
+
+ if (dispsock != NULL &&
+ (ev->result == ISC_R_CANCELED || dispsock->resp == NULL)) {
+ /*
+ * dispsock->resp can be NULL if this transaction was canceled
+ * just after receiving a response. Since this socket is
+ * exclusively used and there should be at most one receive
+ * event the canceled event should have been no effect. So
+ * we can (and should) deactivate the socket right now.
+ */
+ deactivate_dispsocket(disp, dispsock);
+ dispsock = NULL;
+ }
+
+ if (disp->shutting_down) {
+ /*
+ * This dispatcher is shutting down.
+ */
+ free_buffer(disp, ev->region.base, ev->region.length);
+
+ isc_event_free(&ev_in);
+ ev = NULL;
+
+ killit = destroy_disp_ok(disp);
+ UNLOCK(&disp->lock);
+ if (killit)
+ isc_task_send(disp->task[0], &disp->ctlevent);
+
+ return;
+ }
+
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
+ if (dispsock != NULL) {
+ resp = dispsock->resp;
+ id = resp->id;
+ if (ev->result != ISC_R_SUCCESS) {
+ /*
+ * This is most likely a network error on a
+ * connected socket. It makes no sense to
+ * check the address or parse the packet, but it
+ * will help to return the error to the caller.
+ */
+ goto sendresponse;
+ }
+ } else {
+ free_buffer(disp, ev->region.base, ev->region.length);
+
+ UNLOCK(&disp->lock);
+ isc_event_free(&ev_in);
+ return;
+ }
+ } else if (ev->result != ISC_R_SUCCESS) {
+ free_buffer(disp, ev->region.base, ev->region.length);
+
+ if (ev->result != ISC_R_CANCELED)
+ dispatch_log(disp, ISC_LOG_ERROR,
+ "odd socket result in udp_recv(): %s",
+ isc_result_totext(ev->result));
+
+ UNLOCK(&disp->lock);
+ isc_event_free(&ev_in);
+ return;
+ }
+
+ /*
+ * If this is from a blackholed address, drop it.
+ */
+ isc_netaddr_fromsockaddr(&netaddr, &ev->address);
+ if (disp->mgr->blackhole != NULL &&
+ dns_acl_match(&netaddr, NULL, disp->mgr->blackhole,
+ NULL, &match, NULL) == ISC_R_SUCCESS &&
+ match > 0)
+ {
+ if (isc_log_wouldlog(dns_lctx, LVL(10))) {
+ char netaddrstr[ISC_NETADDR_FORMATSIZE];
+ isc_netaddr_format(&netaddr, netaddrstr,
+ sizeof(netaddrstr));
+ dispatch_log(disp, LVL(10),
+ "blackholed packet from %s",
+ netaddrstr);
+ }
+ free_buffer(disp, ev->region.base, ev->region.length);
+ goto restart;
+ }
+
+ /*
+ * Peek into the buffer to see what we can see.
+ */
+ isc_buffer_init(&source, ev->region.base, ev->region.length);
+ isc_buffer_add(&source, ev->n);
+ dres = dns_message_peekheader(&source, &id, &flags);
+ if (dres != ISC_R_SUCCESS) {
+ free_buffer(disp, ev->region.base, ev->region.length);
+ dispatch_log(disp, LVL(10), "got garbage packet");
+ goto restart;
+ }
+
+ dispatch_log(disp, LVL(92),
+ "got valid DNS message header, /QR %c, id %u",
+ ((flags & DNS_MESSAGEFLAG_QR) ? '1' : '0'), id);
+
+ /*
+ * Look at flags. If query, drop it. If response,
+ * look to see where it goes.
+ */
+ queue_response = ISC_FALSE;
+ if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
+ /* query */
+ free_buffer(disp, ev->region.base, ev->region.length);
+ goto restart;
+ }
+
+ /*
+ * Search for the corresponding response. If we are using an exclusive
+ * socket, we've already identified it and we can skip the search; but
+ * the ID and the address must match the expected ones.
+ */
+ if (resp == NULL) {
+ bucket = dns_hash(qid, &ev->address, id, disp->localport);
+ LOCK(&qid->lock);
+ qidlocked = ISC_TRUE;
+ resp = entry_search(qid, &ev->address, id, disp->localport,
+ bucket);
+ dispatch_log(disp, LVL(90),
+ "search for response in bucket %d: %s",
+ bucket, (resp == NULL ? "not found" : "found"));
+
+ if (resp == NULL) {
+ dns_generalstats_increment(mgr->stats,
+ dns_resstatscounter_mismatch);
+ free_buffer(disp, ev->region.base, ev->region.length);
+ goto unlock;
+ }
+ } else if (resp->id != id || !isc_sockaddr_equal(&ev->address,
+ &resp->host)) {
+ dispatch_log(disp, LVL(90),
+ "response to an exclusive socket doesn't match");
+ dns_generalstats_increment(mgr->stats,
+ dns_resstatscounter_mismatch);
+ free_buffer(disp, ev->region.base, ev->region.length);
+ goto unlock;
+ }
+
+ /*
+ * Now that we have the original dispatch the query was sent
+ * from check that the address and port the response was
+ * sent to make sense.
+ */
+ if (disp != resp->disp) {
+ isc_sockaddr_t a1;
+ isc_sockaddr_t a2;
+
+ /*
+ * Check that the socket types and ports match.
+ */
+ if (disp->socktype != resp->disp->socktype ||
+ isc_sockaddr_getport(&disp->local) !=
+ isc_sockaddr_getport(&resp->disp->local)) {
+ free_buffer(disp, ev->region.base, ev->region.length);
+ goto unlock;
+ }
+
+ /*
+ * If both dispatches are bound to an address then fail as
+ * the addresses can't be equal (enforced by the IP stack).
+ *
+ * Note under Linux a packet can be sent out via IPv4 socket
+ * and the response be received via a IPv6 socket.
+ *
+ * Requests sent out via IPv6 should always come back in
+ * via IPv6.
+ */
+ if (isc_sockaddr_pf(&resp->disp->local) == PF_INET6 &&
+ isc_sockaddr_pf(&disp->local) != PF_INET6) {
+ free_buffer(disp, ev->region.base, ev->region.length);
+ goto unlock;
+ }
+ isc_sockaddr_anyofpf(&a1, isc_sockaddr_pf(&resp->disp->local));
+ isc_sockaddr_anyofpf(&a2, isc_sockaddr_pf(&disp->local));
+ if (!isc_sockaddr_eqaddr(&a1, &resp->disp->local) &&
+ !isc_sockaddr_eqaddr(&a2, &disp->local)) {
+ free_buffer(disp, ev->region.base, ev->region.length);
+ goto unlock;
+ }
+ }
+
+ sendresponse:
+ queue_response = resp->item_out;
+ rev = allocate_event(resp->disp);
+ if (rev == NULL) {
+ free_buffer(disp, ev->region.base, ev->region.length);
+ goto unlock;
+ }
+
+ /*
+ * At this point, rev contains the event we want to fill in, and
+ * resp contains the information on the place to send it to.
+ * Send the event off.
+ */
+ isc_buffer_init(&rev->buffer, ev->region.base, ev->region.length);
+ isc_buffer_add(&rev->buffer, ev->n);
+ rev->result = ev->result;
+ rev->id = id;
+ rev->addr = ev->address;
+ rev->pktinfo = ev->pktinfo;
+ rev->attributes = ev->attributes;
+ if (queue_response) {
+ ISC_LIST_APPEND(resp->items, rev, ev_link);
+ } else {
+ ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL,
+ DNS_EVENT_DISPATCH,
+ resp->action, resp->arg, resp, NULL, NULL);
+ request_log(disp, resp, LVL(90),
+ "[a] Sent event %p buffer %p len %d to task %p",
+ rev, rev->buffer.base, rev->buffer.length,
+ resp->task);
+ resp->item_out = ISC_TRUE;
+ isc_task_send(resp->task, ISC_EVENT_PTR(&rev));
+ }
+ unlock:
+ if (qidlocked)
+ UNLOCK(&qid->lock);
+
+ /*
+ * Restart recv() to get the next packet.
+ */
+ restart:
+ result = startrecv(disp, dispsock);
+ if (result != ISC_R_SUCCESS && dispsock != NULL) {
+ /*
+ * XXX: wired. There seems to be no recovery process other than
+ * deactivate this socket anyway (since we cannot start
+ * receiving, we won't be able to receive a cancel event
+ * from the user).
+ */
+ deactivate_dispsocket(disp, dispsock);
+ }
+ UNLOCK(&disp->lock);
+
+ isc_event_free(&ev_in);
+}
+
+/*
+ * General flow:
+ *
+ * If I/O result == CANCELED, EOF, or error, notify everyone as the
+ * various queues drain.
+ *
+ * If query, restart.
+ *
+ * If response:
+ * Allocate event, fill in details.
+ * If cannot allocate, restart.
+ * find target. If not found, restart.
+ * if event queue is not empty, queue. else, send.
+ * restart.
+ */
+static void
+tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
+ dns_dispatch_t *disp = ev_in->ev_arg;
+ dns_tcpmsg_t *tcpmsg = &disp->tcpmsg;
+ dns_messageid_t id;
+ isc_result_t dres;
+ unsigned int flags;
+ dns_dispentry_t *resp;
+ dns_dispatchevent_t *rev;
+ unsigned int bucket;
+ isc_boolean_t killit;
+ isc_boolean_t queue_response;
+ dns_qid_t *qid;
+ int level;
+ char buf[ISC_SOCKADDR_FORMATSIZE];
+
+ UNUSED(task);
+
+ REQUIRE(VALID_DISPATCH(disp));
+
+ qid = disp->qid;
+
+ dispatch_log(disp, LVL(90),
+ "got TCP packet: requests %d, buffers %d, recvs %d",
+ disp->requests, disp->tcpbuffers, disp->recv_pending);
+
+ LOCK(&disp->lock);
+
+ INSIST(disp->recv_pending != 0);
+ disp->recv_pending = 0;
+
+ if (disp->refcount == 0) {
+ /*
+ * This dispatcher is shutting down. Force cancelation.
+ */
+ tcpmsg->result = ISC_R_CANCELED;
+ }
+
+ if (tcpmsg->result != ISC_R_SUCCESS) {
+ switch (tcpmsg->result) {
+ case ISC_R_CANCELED:
+ break;
+
+ case ISC_R_EOF:
+ dispatch_log(disp, LVL(90), "shutting down on EOF");
+ do_cancel(disp);
+ break;
+
+ case ISC_R_CONNECTIONRESET:
+ level = ISC_LOG_INFO;
+ goto logit;
+
+ default:
+ level = ISC_LOG_ERROR;
+ logit:
+ isc_sockaddr_format(&tcpmsg->address, buf, sizeof(buf));
+ dispatch_log(disp, level, "shutting down due to TCP "
+ "receive error: %s: %s", buf,
+ isc_result_totext(tcpmsg->result));
+ do_cancel(disp);
+ break;
+ }
+
+ /*
+ * The event is statically allocated in the tcpmsg
+ * structure, and destroy_disp() frees the tcpmsg, so we must
+ * free the event *before* calling destroy_disp().
+ */
+ isc_event_free(&ev_in);
+
+ disp->shutting_down = 1;
+ disp->shutdown_why = tcpmsg->result;
+
+ /*
+ * If the recv() was canceled pass the word on.
+ */
+ killit = destroy_disp_ok(disp);
+ UNLOCK(&disp->lock);
+ if (killit)
+ isc_task_send(disp->task[0], &disp->ctlevent);
+ return;
+ }
+
+ dispatch_log(disp, LVL(90), "result %d, length == %d, addr = %p",
+ tcpmsg->result,
+ tcpmsg->buffer.length, tcpmsg->buffer.base);
+
+ /*
+ * Peek into the buffer to see what we can see.
+ */
+ dres = dns_message_peekheader(&tcpmsg->buffer, &id, &flags);
+ if (dres != ISC_R_SUCCESS) {
+ dispatch_log(disp, LVL(10), "got garbage packet");
+ goto restart;
+ }
+
+ dispatch_log(disp, LVL(92),
+ "got valid DNS message header, /QR %c, id %u",
+ ((flags & DNS_MESSAGEFLAG_QR) ? '1' : '0'), id);
+
+ /*
+ * Allocate an event to send to the query or response client, and
+ * allocate a new buffer for our use.
+ */
+
+ /*
+ * Look at flags. If query, drop it. If response,
+ * look to see where it goes.
+ */
+ queue_response = ISC_FALSE;
+ if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
+ /*
+ * Query.
+ */
+ goto restart;
+ }
+
+ /*
+ * Response.
+ */
+ bucket = dns_hash(qid, &tcpmsg->address, id, disp->localport);
+ LOCK(&qid->lock);
+ resp = entry_search(qid, &tcpmsg->address, id, disp->localport, bucket);
+ dispatch_log(disp, LVL(90),
+ "search for response in bucket %d: %s",
+ bucket, (resp == NULL ? "not found" : "found"));
+
+ if (resp == NULL)
+ goto unlock;
+ queue_response = resp->item_out;
+ rev = allocate_event(disp);
+ if (rev == NULL)
+ goto unlock;
+
+ /*
+ * At this point, rev contains the event we want to fill in, and
+ * resp contains the information on the place to send it to.
+ * Send the event off.
+ */
+ dns_tcpmsg_keepbuffer(tcpmsg, &rev->buffer);
+ disp->tcpbuffers++;
+ rev->result = ISC_R_SUCCESS;
+ rev->id = id;
+ rev->addr = tcpmsg->address;
+ if (queue_response) {
+ ISC_LIST_APPEND(resp->items, rev, ev_link);
+ } else {
+ ISC_EVENT_INIT(rev, sizeof(*rev), 0, NULL, DNS_EVENT_DISPATCH,
+ resp->action, resp->arg, resp, NULL, NULL);
+ request_log(disp, resp, LVL(90),
+ "[b] Sent event %p buffer %p len %d to task %p",
+ rev, rev->buffer.base, rev->buffer.length,
+ resp->task);
+ resp->item_out = ISC_TRUE;
+ isc_task_send(resp->task, ISC_EVENT_PTR(&rev));
+ }
+ unlock:
+ UNLOCK(&qid->lock);
+
+ /*
+ * Restart recv() to get the next packet.
+ */
+ restart:
+ (void)startrecv(disp, NULL);
+
+ UNLOCK(&disp->lock);
+
+ isc_event_free(&ev_in);
+}
+
+/*
+ * disp must be locked.
+ */
+static isc_result_t
+startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) {
+ isc_result_t res;
+ isc_region_t region;
+ isc_socket_t *socket;
+
+ if (disp->shutting_down == 1)
+ return (ISC_R_SUCCESS);
+
+ if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
+ return (ISC_R_SUCCESS);
+
+ if (disp->recv_pending != 0 && dispsock == NULL)
+ return (ISC_R_SUCCESS);
+
+ if (disp->mgr->buffers >= disp->mgr->maxbuffers)
+ return (ISC_R_NOMEMORY);
+
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0 &&
+ dispsock == NULL)
+ return (ISC_R_SUCCESS);
+
+ if (dispsock != NULL)
+ socket = dispsock->socket;
+ else
+ socket = disp->socket;
+ INSIST(socket != NULL);
+
+ switch (disp->socktype) {
+ /*
+ * UDP reads are always maximal.
+ */
+ case isc_sockettype_udp:
+ region.length = disp->mgr->buffersize;
+ region.base = allocate_udp_buffer(disp);
+ if (region.base == NULL)
+ return (ISC_R_NOMEMORY);
+ if (dispsock != NULL) {
+ res = isc_socket_recv(socket, &region, 1,
+ dispsock->task, udp_exrecv,
+ dispsock);
+ if (res != ISC_R_SUCCESS) {
+ free_buffer(disp, region.base, region.length);
+ return (res);
+ }
+ } else {
+ res = isc_socket_recv(socket, &region, 1,
+ disp->task[0], udp_shrecv, disp);
+ if (res != ISC_R_SUCCESS) {
+ free_buffer(disp, region.base, region.length);
+ disp->shutdown_why = res;
+ disp->shutting_down = 1;
+ do_cancel(disp);
+ return (ISC_R_SUCCESS); /* recover by cancel */
+ }
+ INSIST(disp->recv_pending == 0);
+ disp->recv_pending = 1;
+ }
+ break;
+
+ case isc_sockettype_tcp:
+ res = dns_tcpmsg_readmessage(&disp->tcpmsg, disp->task[0],
+ tcp_recv, disp);
+ if (res != ISC_R_SUCCESS) {
+ disp->shutdown_why = res;
+ disp->shutting_down = 1;
+ do_cancel(disp);
+ return (ISC_R_SUCCESS); /* recover by cancel */
+ }
+ INSIST(disp->recv_pending == 0);
+ disp->recv_pending = 1;
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Mgr must be locked when calling this function.
+ */
+static isc_boolean_t
+destroy_mgr_ok(dns_dispatchmgr_t *mgr) {
+ mgr_log(mgr, LVL(90),
+ "destroy_mgr_ok: shuttingdown=%d, listnonempty=%d, "
+ "epool=%d, rpool=%d, dpool=%d",
+ MGR_IS_SHUTTINGDOWN(mgr), !ISC_LIST_EMPTY(mgr->list),
+ isc_mempool_getallocated(mgr->epool),
+ isc_mempool_getallocated(mgr->rpool),
+ isc_mempool_getallocated(mgr->dpool));
+ if (!MGR_IS_SHUTTINGDOWN(mgr))
+ return (ISC_FALSE);
+ if (!ISC_LIST_EMPTY(mgr->list))
+ return (ISC_FALSE);
+ if (isc_mempool_getallocated(mgr->epool) != 0)
+ return (ISC_FALSE);
+ if (isc_mempool_getallocated(mgr->rpool) != 0)
+ return (ISC_FALSE);
+ if (isc_mempool_getallocated(mgr->dpool) != 0)
+ return (ISC_FALSE);
+
+ return (ISC_TRUE);
+}
+
+/*
+ * Mgr must be unlocked when calling this function.
+ */
+static void
+destroy_mgr(dns_dispatchmgr_t **mgrp) {
+ isc_mem_t *mctx;
+ dns_dispatchmgr_t *mgr;
+
+ mgr = *mgrp;
+ *mgrp = NULL;
+
+ mctx = mgr->mctx;
+
+ mgr->magic = 0;
+ mgr->mctx = NULL;
+ DESTROYLOCK(&mgr->lock);
+ mgr->state = 0;
+
+ DESTROYLOCK(&mgr->arc4_lock);
+
+ 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);
+
+ DESTROYLOCK(&mgr->pool_lock);
+
+ if (mgr->entropy != NULL)
+ isc_entropy_detach(&mgr->entropy);
+ if (mgr->qid != NULL)
+ qid_destroy(mctx, &mgr->qid);
+
+ DESTROYLOCK(&mgr->buffer_lock);
+
+ if (mgr->blackhole != NULL)
+ dns_acl_detach(&mgr->blackhole);
+
+ if (mgr->stats != NULL)
+ dns_stats_detach(&mgr->stats);
+
+ if (mgr->v4ports != NULL) {
+ isc_mem_put(mctx, mgr->v4ports,
+ mgr->nv4ports * sizeof(in_port_t));
+ }
+ if (mgr->v6ports != NULL) {
+ isc_mem_put(mctx, mgr->v6ports,
+ mgr->nv6ports * sizeof(in_port_t));
+ }
+ isc_mem_put(mctx, mgr, sizeof(dns_dispatchmgr_t));
+ isc_mem_detach(&mctx);
+}
+
+static isc_result_t
+open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
+ unsigned int options, isc_socket_t **sockp)
+{
+ isc_socket_t *sock;
+ isc_result_t result;
+
+ sock = *sockp;
+ if (sock == NULL) {
+ result = isc_socket_create(mgr, isc_sockaddr_pf(local),
+ isc_sockettype_udp, &sock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_socket_setname(sock, "dispatcher", NULL);
+ } else {
+ result = isc_socket_open(sock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+#ifndef ISC_ALLOW_MAPPED
+ isc_socket_ipv6only(sock, ISC_TRUE);
+#endif
+ result = isc_socket_bind(sock, local, options);
+ if (result != ISC_R_SUCCESS) {
+ if (*sockp == NULL)
+ isc_socket_detach(&sock);
+ else
+ isc_socket_close(sock);
+ return (result);
+ }
+
+ *sockp = sock;
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Create a temporary port list to set the initial default set of dispatch
+ * ports: [1024, 65535]. This is almost meaningless as the application will
+ * normally set the ports explicitly, but is provided to fill some minor corner
+ * cases.
+ */
+static isc_result_t
+create_default_portset(isc_mem_t *mctx, isc_portset_t **portsetp) {
+ isc_result_t result;
+
+ result = isc_portset_create(mctx, portsetp);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_portset_addrange(*portsetp, 1024, 65535);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Publics.
+ */
+
+isc_result_t
+dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
+ dns_dispatchmgr_t **mgrp)
+{
+ dns_dispatchmgr_t *mgr;
+ isc_result_t result;
+ isc_portset_t *v4portset = NULL;
+ isc_portset_t *v6portset = NULL;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(mgrp != NULL && *mgrp == NULL);
+
+ mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t));
+ if (mgr == NULL)
+ return (ISC_R_NOMEMORY);
+
+ mgr->mctx = NULL;
+ isc_mem_attach(mctx, &mgr->mctx);
+
+ mgr->blackhole = NULL;
+ mgr->stats = NULL;
+
+ result = isc_mutex_init(&mgr->lock);
+ if (result != ISC_R_SUCCESS)
+ goto deallocate;
+
+ result = isc_mutex_init(&mgr->arc4_lock);
+ if (result != ISC_R_SUCCESS)
+ goto kill_lock;
+
+ result = isc_mutex_init(&mgr->buffer_lock);
+ if (result != ISC_R_SUCCESS)
+ goto kill_arc4_lock;
+
+ result = isc_mutex_init(&mgr->pool_lock);
+ if (result != ISC_R_SUCCESS)
+ goto kill_buffer_lock;
+
+ mgr->epool = NULL;
+ if (isc_mempool_create(mgr->mctx, sizeof(dns_dispatchevent_t),
+ &mgr->epool) != ISC_R_SUCCESS) {
+ result = ISC_R_NOMEMORY;
+ goto kill_pool_lock;
+ }
+
+ mgr->rpool = NULL;
+ if (isc_mempool_create(mgr->mctx, sizeof(dns_dispentry_t),
+ &mgr->rpool) != ISC_R_SUCCESS) {
+ result = ISC_R_NOMEMORY;
+ goto kill_epool;
+ }
+
+ mgr->dpool = NULL;
+ if (isc_mempool_create(mgr->mctx, sizeof(dns_dispatch_t),
+ &mgr->dpool) != ISC_R_SUCCESS) {
+ result = ISC_R_NOMEMORY;
+ goto kill_rpool;
+ }
+
+ isc_mempool_setname(mgr->epool, "dispmgr_epool");
+ isc_mempool_setfreemax(mgr->epool, 1024);
+ isc_mempool_associatelock(mgr->epool, &mgr->pool_lock);
+
+ isc_mempool_setname(mgr->rpool, "dispmgr_rpool");
+ isc_mempool_setfreemax(mgr->rpool, 1024);
+ isc_mempool_associatelock(mgr->rpool, &mgr->pool_lock);
+
+ isc_mempool_setname(mgr->dpool, "dispmgr_dpool");
+ isc_mempool_setfreemax(mgr->dpool, 1024);
+ isc_mempool_associatelock(mgr->dpool, &mgr->pool_lock);
+
+ mgr->buffers = 0;
+ mgr->buffersize = 0;
+ mgr->maxbuffers = 0;
+ mgr->bpool = NULL;
+ mgr->spool = NULL;
+ mgr->entropy = NULL;
+ mgr->qid = NULL;
+ mgr->state = 0;
+ ISC_LIST_INIT(mgr->list);
+ mgr->v4ports = NULL;
+ mgr->v6ports = NULL;
+ mgr->nv4ports = 0;
+ mgr->nv6ports = 0;
+ mgr->magic = DNS_DISPATCHMGR_MAGIC;
+
+ result = create_default_portset(mctx, &v4portset);
+ if (result == ISC_R_SUCCESS) {
+ result = create_default_portset(mctx, &v6portset);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_dispatchmgr_setavailports(mgr,
+ v4portset,
+ v6portset);
+ }
+ }
+ if (v4portset != NULL)
+ isc_portset_destroy(mctx, &v4portset);
+ if (v6portset != NULL)
+ isc_portset_destroy(mctx, &v6portset);
+ if (result != ISC_R_SUCCESS)
+ goto kill_dpool;
+
+ if (entropy != NULL)
+ isc_entropy_attach(entropy, &mgr->entropy);
+
+ dispatch_arc4init(&mgr->arc4ctx, mgr->entropy, &mgr->arc4_lock);
+
+ *mgrp = mgr;
+ return (ISC_R_SUCCESS);
+
+ kill_dpool:
+ isc_mempool_destroy(&mgr->dpool);
+ kill_rpool:
+ isc_mempool_destroy(&mgr->rpool);
+ kill_epool:
+ isc_mempool_destroy(&mgr->epool);
+ kill_pool_lock:
+ DESTROYLOCK(&mgr->pool_lock);
+ kill_buffer_lock:
+ DESTROYLOCK(&mgr->buffer_lock);
+ kill_arc4_lock:
+ DESTROYLOCK(&mgr->arc4_lock);
+ kill_lock:
+ DESTROYLOCK(&mgr->lock);
+ deallocate:
+ isc_mem_put(mctx, mgr, sizeof(dns_dispatchmgr_t));
+ isc_mem_detach(&mctx);
+
+ return (result);
+}
+
+void
+dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole) {
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ if (mgr->blackhole != NULL)
+ dns_acl_detach(&mgr->blackhole);
+ dns_acl_attach(blackhole, &mgr->blackhole);
+}
+
+dns_acl_t *
+dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr) {
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ return (mgr->blackhole);
+}
+
+void
+dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr,
+ dns_portlist_t *portlist)
+{
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ UNUSED(portlist);
+
+ /* This function is deprecated: use dns_dispatchmgr_setavailports(). */
+ return;
+}
+
+dns_portlist_t *
+dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr) {
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ return (NULL); /* this function is deprecated */
+}
+
+isc_result_t
+dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
+ isc_portset_t *v6portset)
+{
+ in_port_t *v4ports, *v6ports, p;
+ unsigned int nv4ports, nv6ports, i4, i6;
+
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+
+ nv4ports = isc_portset_nports(v4portset);
+ nv6ports = isc_portset_nports(v6portset);
+
+ v4ports = NULL;
+ if (nv4ports != 0) {
+ v4ports = isc_mem_get(mgr->mctx, sizeof(in_port_t) * nv4ports);
+ if (v4ports == NULL)
+ return (ISC_R_NOMEMORY);
+ }
+ v6ports = NULL;
+ if (nv6ports != 0) {
+ v6ports = isc_mem_get(mgr->mctx, sizeof(in_port_t) * nv6ports);
+ if (v6ports == NULL) {
+ if (v4ports != NULL) {
+ isc_mem_put(mgr->mctx, v4ports,
+ sizeof(in_port_t) *
+ isc_portset_nports(v4portset));
+ }
+ return (ISC_R_NOMEMORY);
+ }
+ }
+
+ p = 0;
+ i4 = 0;
+ i6 = 0;
+ do {
+ if (isc_portset_isset(v4portset, p)) {
+ INSIST(i4 < nv4ports);
+ v4ports[i4++] = p;
+ }
+ if (isc_portset_isset(v6portset, p)) {
+ INSIST(i6 < nv6ports);
+ v6ports[i6++] = p;
+ }
+ } while (p++ < 65535);
+ INSIST(i4 == nv4ports && i6 == nv6ports);
+
+ PORTBUFLOCK(mgr);
+ if (mgr->v4ports != NULL) {
+ isc_mem_put(mgr->mctx, mgr->v4ports,
+ mgr->nv4ports * sizeof(in_port_t));
+ }
+ mgr->v4ports = v4ports;
+ mgr->nv4ports = nv4ports;
+
+ if (mgr->v6ports != NULL) {
+ isc_mem_put(mgr->mctx, mgr->v6ports,
+ mgr->nv6ports * sizeof(in_port_t));
+ }
+ mgr->v6ports = v6ports;
+ mgr->nv6ports = nv6ports;
+ PORTBUFUNLOCK(mgr);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr,
+ unsigned int buffersize, unsigned int maxbuffers,
+ unsigned int maxrequests, unsigned int buckets,
+ unsigned int increment)
+{
+ isc_result_t result;
+
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ REQUIRE(buffersize >= 512 && buffersize < (64 * 1024));
+ REQUIRE(maxbuffers > 0);
+ REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
+ REQUIRE(increment > buckets);
+
+ /*
+ * Keep some number of items around. This should be a config
+ * option. For now, keep 8, but later keep at least two even
+ * if the caller wants less. This allows us to ensure certain
+ * things, like an event can be "freed" and the next allocation
+ * will always succeed.
+ *
+ * Note that if limits are placed on anything here, we use one
+ * event internally, so the actual limit should be "wanted + 1."
+ *
+ * XXXMLG
+ */
+
+ if (maxbuffers < 8)
+ maxbuffers = 8;
+
+ LOCK(&mgr->buffer_lock);
+
+ /* Create or adjust buffer pool */
+ if (mgr->bpool != NULL) {
+ isc_mempool_setmaxalloc(mgr->bpool, maxbuffers);
+ mgr->maxbuffers = maxbuffers;
+ } else {
+ result = isc_mempool_create(mgr->mctx, buffersize, &mgr->bpool);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK(&mgr->buffer_lock);
+ return (result);
+ }
+ isc_mempool_setname(mgr->bpool, "dispmgr_bpool");
+ isc_mempool_setmaxalloc(mgr->bpool, maxbuffers);
+ isc_mempool_associatelock(mgr->bpool, &mgr->pool_lock);
+ }
+
+ /* Create or adjust socket pool */
+ if (mgr->spool != NULL) {
+ isc_mempool_setmaxalloc(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2);
+ UNLOCK(&mgr->buffer_lock);
+ return (ISC_R_SUCCESS);
+ }
+ result = isc_mempool_create(mgr->mctx, sizeof(dispsocket_t),
+ &mgr->spool);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK(&mgr->buffer_lock);
+ goto cleanup;
+ }
+ isc_mempool_setname(mgr->spool, "dispmgr_spool");
+ isc_mempool_setmaxalloc(mgr->spool, maxrequests);
+ isc_mempool_associatelock(mgr->spool, &mgr->pool_lock);
+
+ result = qid_allocate(mgr, buckets, increment, &mgr->qid, ISC_TRUE);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ mgr->buffersize = buffersize;
+ mgr->maxbuffers = maxbuffers;
+ UNLOCK(&mgr->buffer_lock);
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_mempool_destroy(&mgr->bpool);
+ if (mgr->spool != NULL)
+ isc_mempool_destroy(&mgr->spool);
+ UNLOCK(&mgr->buffer_lock);
+ return (result);
+}
+
+void
+dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
+ dns_dispatchmgr_t *mgr;
+ isc_boolean_t killit;
+
+ REQUIRE(mgrp != NULL);
+ REQUIRE(VALID_DISPATCHMGR(*mgrp));
+
+ mgr = *mgrp;
+ *mgrp = NULL;
+
+ LOCK(&mgr->lock);
+ mgr->state |= MGR_SHUTTINGDOWN;
+
+ killit = destroy_mgr_ok(mgr);
+ UNLOCK(&mgr->lock);
+
+ mgr_log(mgr, LVL(90), "destroy: killit=%d", killit);
+
+ if (killit)
+ destroy_mgr(&mgr);
+}
+
+void
+dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, dns_stats_t *stats) {
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ REQUIRE(ISC_LIST_EMPTY(mgr->list));
+ REQUIRE(mgr->stats == NULL);
+
+ dns_stats_attach(stats, &mgr->stats);
+}
+
+static int
+port_cmp(const void *key, const void *ent) {
+ in_port_t p1 = *(const in_port_t *)key;
+ in_port_t p2 = *(const in_port_t *)ent;
+
+ if (p1 < p2)
+ return (-1);
+ else if (p1 == p2)
+ return (0);
+ else
+ return (1);
+}
+
+static isc_boolean_t
+portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
+ isc_sockaddr_t *sockaddrp)
+{
+ isc_sockaddr_t sockaddr;
+ isc_result_t result;
+ in_port_t *ports, port;
+ unsigned int nports;
+ isc_boolean_t available = ISC_FALSE;
+
+ REQUIRE(sock != NULL || sockaddrp != NULL);
+
+ PORTBUFLOCK(mgr);
+ if (sock != NULL) {
+ sockaddrp = &sockaddr;
+ result = isc_socket_getsockname(sock, sockaddrp);
+ if (result != ISC_R_SUCCESS)
+ goto unlock;
+ }
+
+ if (isc_sockaddr_pf(sockaddrp) == AF_INET) {
+ ports = mgr->v4ports;
+ nports = mgr->nv4ports;
+ } else {
+ ports = mgr->v6ports;
+ nports = mgr->nv6ports;
+ }
+ if (ports == NULL)
+ goto unlock;
+
+ port = isc_sockaddr_getport(sockaddrp);
+ if (bsearch(&port, ports, nports, sizeof(in_port_t), port_cmp) != NULL)
+ available = ISC_TRUE;
+
+unlock:
+ PORTBUFUNLOCK(mgr);
+ return (available);
+}
+
+#define ATTRMATCH(_a1, _a2, _mask) (((_a1) & (_mask)) == ((_a2) & (_mask)))
+
+static isc_boolean_t
+local_addr_match(dns_dispatch_t *disp, isc_sockaddr_t *addr) {
+ isc_sockaddr_t sockaddr;
+ isc_result_t result;
+
+ REQUIRE(disp->socket != NULL);
+
+ if (addr == NULL)
+ return (ISC_TRUE);
+
+ /*
+ * Don't match wildcard ports unless the port is available in the
+ * current configuration.
+ */
+ if (isc_sockaddr_getport(addr) == 0 &&
+ isc_sockaddr_getport(&disp->local) == 0 &&
+ !portavailable(disp->mgr, disp->socket, NULL)) {
+ return (ISC_FALSE);
+ }
+
+ /*
+ * Check if we match the binding <address,port>.
+ * Wildcard ports match/fail here.
+ */
+ if (isc_sockaddr_equal(&disp->local, addr))
+ return (ISC_TRUE);
+ if (isc_sockaddr_getport(addr) == 0)
+ return (ISC_FALSE);
+
+ /*
+ * Check if we match a bound wildcard port <address,port>.
+ */
+ if (!isc_sockaddr_eqaddr(&disp->local, addr))
+ return (ISC_FALSE);
+ result = isc_socket_getsockname(disp->socket, &sockaddr);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+
+ return (isc_sockaddr_equal(&sockaddr, addr));
+}
+
+/*
+ * Requires mgr be locked.
+ *
+ * No dispatcher can be locked by this thread when calling this function.
+ *
+ *
+ * NOTE:
+ * If a matching dispatcher is found, it is locked after this function
+ * returns, and must be unlocked by the caller.
+ */
+static isc_result_t
+dispatch_find(dns_dispatchmgr_t *mgr, isc_sockaddr_t *local,
+ unsigned int attributes, unsigned int mask,
+ dns_dispatch_t **dispp)
+{
+ dns_dispatch_t *disp;
+ isc_result_t result;
+
+ /*
+ * Make certain that we will not match a private or exclusive dispatch.
+ */
+ attributes &= ~(DNS_DISPATCHATTR_PRIVATE|DNS_DISPATCHATTR_EXCLUSIVE);
+ mask |= (DNS_DISPATCHATTR_PRIVATE|DNS_DISPATCHATTR_EXCLUSIVE);
+
+ disp = ISC_LIST_HEAD(mgr->list);
+ while (disp != NULL) {
+ LOCK(&disp->lock);
+ if ((disp->shutting_down == 0)
+ && ATTRMATCH(disp->attributes, attributes, mask)
+ && local_addr_match(disp, local))
+ break;
+ UNLOCK(&disp->lock);
+ disp = ISC_LIST_NEXT(disp, link);
+ }
+
+ if (disp == NULL) {
+ result = ISC_R_NOTFOUND;
+ goto out;
+ }
+
+ *dispp = disp;
+ result = ISC_R_SUCCESS;
+ out:
+
+ return (result);
+}
+
+static isc_result_t
+qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
+ unsigned int increment, dns_qid_t **qidp,
+ isc_boolean_t needsocktable)
+{
+ dns_qid_t *qid;
+ unsigned int i;
+ isc_result_t result;
+
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
+ REQUIRE(increment > buckets);
+ REQUIRE(qidp != NULL && *qidp == NULL);
+
+ qid = isc_mem_get(mgr->mctx, sizeof(*qid));
+ if (qid == NULL)
+ return (ISC_R_NOMEMORY);
+
+ qid->qid_table = isc_mem_get(mgr->mctx,
+ buckets * sizeof(dns_displist_t));
+ if (qid->qid_table == NULL) {
+ isc_mem_put(mgr->mctx, qid, sizeof(*qid));
+ return (ISC_R_NOMEMORY);
+ }
+
+ qid->sock_table = NULL;
+ if (needsocktable) {
+ qid->sock_table = isc_mem_get(mgr->mctx, buckets *
+ sizeof(dispsocketlist_t));
+ if (qid->sock_table == NULL) {
+ isc_mem_put(mgr->mctx, qid, sizeof(*qid));
+ isc_mem_put(mgr->mctx, qid->qid_table,
+ buckets * sizeof(dns_displist_t));
+ return (ISC_R_NOMEMORY);
+ }
+ }
+
+ result = isc_mutex_init(&qid->lock);
+ if (result != ISC_R_SUCCESS) {
+ if (qid->sock_table != NULL) {
+ isc_mem_put(mgr->mctx, qid->sock_table,
+ buckets * sizeof(dispsocketlist_t));
+ }
+ isc_mem_put(mgr->mctx, qid->qid_table,
+ buckets * sizeof(dns_displist_t));
+ isc_mem_put(mgr->mctx, qid, sizeof(*qid));
+ return (result);
+ }
+
+ for (i = 0; i < buckets; i++) {
+ ISC_LIST_INIT(qid->qid_table[i]);
+ if (qid->sock_table != NULL)
+ ISC_LIST_INIT(qid->sock_table[i]);
+ }
+
+ qid->qid_nbuckets = buckets;
+ qid->qid_increment = increment;
+ qid->magic = QID_MAGIC;
+ *qidp = qid;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) {
+ dns_qid_t *qid;
+
+ REQUIRE(qidp != NULL);
+ qid = *qidp;
+
+ REQUIRE(VALID_QID(qid));
+
+ *qidp = NULL;
+ qid->magic = 0;
+ isc_mem_put(mctx, qid->qid_table,
+ qid->qid_nbuckets * sizeof(dns_displist_t));
+ if (qid->sock_table != NULL) {
+ isc_mem_put(mctx, qid->sock_table,
+ qid->qid_nbuckets * sizeof(dispsocketlist_t));
+ }
+ DESTROYLOCK(&qid->lock);
+ isc_mem_put(mctx, qid, sizeof(*qid));
+}
+
+/*
+ * Allocate and set important limits.
+ */
+static isc_result_t
+dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
+ dns_dispatch_t **dispp)
+{
+ dns_dispatch_t *disp;
+ isc_result_t result;
+
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ REQUIRE(dispp != NULL && *dispp == NULL);
+
+ /*
+ * Set up the dispatcher, mostly. Don't bother setting some of
+ * the options that are controlled by tcp vs. udp, etc.
+ */
+
+ disp = isc_mempool_get(mgr->dpool);
+ if (disp == NULL)
+ return (ISC_R_NOMEMORY);
+
+ disp->magic = 0;
+ disp->mgr = mgr;
+ disp->maxrequests = maxrequests;
+ disp->attributes = 0;
+ ISC_LINK_INIT(disp, link);
+ disp->refcount = 1;
+ disp->recv_pending = 0;
+ memset(&disp->local, 0, sizeof(disp->local));
+ disp->localport = 0;
+ disp->shutting_down = 0;
+ disp->shutdown_out = 0;
+ disp->connected = 0;
+ disp->tcpmsg_valid = 0;
+ disp->shutdown_why = ISC_R_UNEXPECTED;
+ disp->requests = 0;
+ disp->tcpbuffers = 0;
+ disp->qid = NULL;
+ ISC_LIST_INIT(disp->activesockets);
+ ISC_LIST_INIT(disp->inactivesockets);
+ disp->nsockets = 0;
+ dispatch_arc4init(&disp->arc4ctx, mgr->entropy, NULL);
+ disp->port_table = NULL;
+ disp->portpool = NULL;
+
+ result = isc_mutex_init(&disp->lock);
+ if (result != ISC_R_SUCCESS)
+ goto deallocate;
+
+ disp->failsafe_ev = allocate_event(disp);
+ if (disp->failsafe_ev == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto kill_lock;
+ }
+
+ disp->magic = DISPATCH_MAGIC;
+
+ *dispp = disp;
+ return (ISC_R_SUCCESS);
+
+ /*
+ * error returns
+ */
+ kill_lock:
+ DESTROYLOCK(&disp->lock);
+ deallocate:
+ isc_mempool_put(mgr->dpool, disp);
+
+ return (result);
+}
+
+
+/*
+ * MUST be unlocked, and not used by anthing.
+ */
+static void
+dispatch_free(dns_dispatch_t **dispp)
+{
+ dns_dispatch_t *disp;
+ dns_dispatchmgr_t *mgr;
+ int i;
+
+ REQUIRE(VALID_DISPATCH(*dispp));
+ disp = *dispp;
+ *dispp = NULL;
+
+ mgr = disp->mgr;
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+
+ if (disp->tcpmsg_valid) {
+ dns_tcpmsg_invalidate(&disp->tcpmsg);
+ disp->tcpmsg_valid = 0;
+ }
+
+ INSIST(disp->tcpbuffers == 0);
+ INSIST(disp->requests == 0);
+ INSIST(disp->recv_pending == 0);
+ INSIST(ISC_LIST_EMPTY(disp->activesockets));
+ INSIST(ISC_LIST_EMPTY(disp->inactivesockets));
+
+ isc_mempool_put(mgr->epool, disp->failsafe_ev);
+ disp->failsafe_ev = NULL;
+
+ if (disp->qid != NULL)
+ qid_destroy(mgr->mctx, &disp->qid);
+
+ if (disp->port_table != NULL) {
+ for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++)
+ INSIST(ISC_LIST_EMPTY(disp->port_table[i]));
+ isc_mem_put(mgr->mctx, disp->port_table,
+ sizeof(disp->port_table[0]) *
+ DNS_DISPATCH_PORTTABLESIZE);
+ }
+
+ if (disp->portpool != NULL)
+ isc_mempool_destroy(&disp->portpool);
+
+ disp->mgr = NULL;
+ DESTROYLOCK(&disp->lock);
+ disp->magic = 0;
+ isc_mempool_put(mgr->dpool, disp);
+}
+
+isc_result_t
+dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
+ isc_taskmgr_t *taskmgr, unsigned int buffersize,
+ unsigned int maxbuffers, unsigned int maxrequests,
+ unsigned int buckets, unsigned int increment,
+ unsigned int attributes, dns_dispatch_t **dispp)
+{
+ isc_result_t result;
+ dns_dispatch_t *disp;
+
+ UNUSED(maxbuffers);
+ UNUSED(buffersize);
+
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ REQUIRE(isc_socket_gettype(sock) == isc_sockettype_tcp);
+ REQUIRE((attributes & DNS_DISPATCHATTR_TCP) != 0);
+ REQUIRE((attributes & DNS_DISPATCHATTR_UDP) == 0);
+
+ attributes |= DNS_DISPATCHATTR_PRIVATE; /* XXXMLG */
+
+ LOCK(&mgr->lock);
+
+ /*
+ * dispatch_allocate() checks mgr for us.
+ * qid_allocate() checks buckets and increment for us.
+ */
+ disp = NULL;
+ result = dispatch_allocate(mgr, maxrequests, &disp);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK(&mgr->lock);
+ return (result);
+ }
+
+ result = qid_allocate(mgr, buckets, increment, &disp->qid, ISC_FALSE);
+ if (result != ISC_R_SUCCESS)
+ goto deallocate_dispatch;
+
+ disp->socktype = isc_sockettype_tcp;
+ disp->socket = NULL;
+ isc_socket_attach(sock, &disp->socket);
+
+ disp->ntasks = 1;
+ disp->task[0] = NULL;
+ result = isc_task_create(taskmgr, 0, &disp->task[0]);
+ if (result != ISC_R_SUCCESS)
+ goto kill_socket;
+
+ disp->ctlevent = isc_event_allocate(mgr->mctx, disp,
+ DNS_EVENT_DISPATCHCONTROL,
+ destroy_disp, disp,
+ sizeof(isc_event_t));
+ if (disp->ctlevent == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto kill_task;
+ }
+
+ isc_task_setname(disp->task[0], "tcpdispatch", disp);
+
+ dns_tcpmsg_init(mgr->mctx, disp->socket, &disp->tcpmsg);
+ disp->tcpmsg_valid = 1;
+
+ disp->attributes = attributes;
+
+ /*
+ * Append it to the dispatcher list.
+ */
+ ISC_LIST_APPEND(mgr->list, disp, link);
+ UNLOCK(&mgr->lock);
+
+ mgr_log(mgr, LVL(90), "created TCP dispatcher %p", disp);
+ dispatch_log(disp, LVL(90), "created task %p", disp->task[0]);
+
+ *dispp = disp;
+
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Error returns.
+ */
+ kill_task:
+ isc_task_detach(&disp->task[0]);
+ kill_socket:
+ isc_socket_detach(&disp->socket);
+ deallocate_dispatch:
+ dispatch_free(&disp);
+
+ UNLOCK(&mgr->lock);
+
+ return (result);
+}
+
+isc_result_t
+dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
+ isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
+ unsigned int buffersize,
+ unsigned int maxbuffers, unsigned int maxrequests,
+ unsigned int buckets, unsigned int increment,
+ unsigned int attributes, unsigned int mask,
+ dns_dispatch_t **dispp)
+{
+ isc_result_t result;
+ dns_dispatch_t *disp = NULL;
+
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+ REQUIRE(sockmgr != NULL);
+ REQUIRE(localaddr != NULL);
+ REQUIRE(taskmgr != NULL);
+ REQUIRE(buffersize >= 512 && buffersize < (64 * 1024));
+ REQUIRE(maxbuffers > 0);
+ REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */
+ REQUIRE(increment > buckets);
+ REQUIRE(dispp != NULL && *dispp == NULL);
+ REQUIRE((attributes & DNS_DISPATCHATTR_TCP) == 0);
+
+ result = dns_dispatchmgr_setudp(mgr, buffersize, maxbuffers,
+ maxrequests, buckets, increment);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ LOCK(&mgr->lock);
+
+ if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
+ REQUIRE(isc_sockaddr_getport(localaddr) == 0);
+ goto createudp;
+ }
+
+ /*
+ * See if we have a dispatcher that matches.
+ */
+ result = dispatch_find(mgr, localaddr, attributes, mask, &disp);
+ if (result == ISC_R_SUCCESS) {
+ disp->refcount++;
+
+ if (disp->maxrequests < maxrequests)
+ disp->maxrequests = maxrequests;
+
+ if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) == 0 &&
+ (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
+ {
+ disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
+ if (disp->recv_pending != 0)
+ isc_socket_cancel(disp->socket, disp->task[0],
+ ISC_SOCKCANCEL_RECV);
+ }
+
+ UNLOCK(&disp->lock);
+ UNLOCK(&mgr->lock);
+
+ *dispp = disp;
+
+ return (ISC_R_SUCCESS);
+ }
+
+ createudp:
+ /*
+ * Nope, create one.
+ */
+ result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr,
+ maxrequests, attributes, &disp);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK(&mgr->lock);
+ return (result);
+ }
+
+ UNLOCK(&mgr->lock);
+ *dispp = disp;
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * mgr should be locked.
+ */
+
+#ifndef DNS_DISPATCH_HELD
+#define DNS_DISPATCH_HELD 20U
+#endif
+
+static isc_result_t
+get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
+ isc_socketmgr_t *sockmgr, isc_sockaddr_t *localaddr,
+ isc_socket_t **sockp)
+{
+ unsigned int i, j;
+ isc_socket_t *held[DNS_DISPATCH_HELD];
+ isc_sockaddr_t localaddr_bound;
+ isc_socket_t *sock = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t anyport;
+
+ INSIST(sockp != NULL && *sockp == NULL);
+
+ localaddr_bound = *localaddr;
+ anyport = ISC_TF(isc_sockaddr_getport(localaddr) == 0);
+
+ if (anyport) {
+ unsigned int nports;
+ in_port_t *ports;
+
+ /*
+ * If no port is specified, we first try to pick up a random
+ * port by ourselves.
+ */
+ if (isc_sockaddr_pf(&disp->local) == AF_INET) {
+ nports = disp->mgr->nv4ports;
+ ports = disp->mgr->v4ports;
+ } else {
+ nports = disp->mgr->nv6ports;
+ ports = disp->mgr->v6ports;
+ }
+ if (nports == 0)
+ return (ISC_R_ADDRNOTAVAIL);
+
+ for (i = 0; i < 1024; i++) {
+ in_port_t prt;
+
+ prt = ports[dispatch_arc4uniformrandom(
+ DISP_ARC4CTX(disp),
+ nports)];
+ isc_sockaddr_setport(&localaddr_bound, prt);
+ result = open_socket(sockmgr, &localaddr_bound,
+ 0, &sock);
+ if (result == ISC_R_SUCCESS ||
+ result != ISC_R_ADDRINUSE) {
+ disp->localport = prt;
+ *sockp = sock;
+ return (result);
+ }
+ }
+
+ /*
+ * If this fails 1024 times, we then ask the kernel for
+ * choosing one.
+ */
+ }
+
+ memset(held, 0, sizeof(held));
+ i = 0;
+
+ for (j = 0; j < 0xffffU; j++) {
+ result = open_socket(sockmgr, localaddr, 0, &sock);
+ if (result != ISC_R_SUCCESS)
+ goto end;
+ else if (!anyport)
+ break;
+ else if (portavailable(mgr, sock, NULL))
+ break;
+ if (held[i] != NULL)
+ isc_socket_detach(&held[i]);
+ held[i++] = sock;
+ sock = NULL;
+ if (i == DNS_DISPATCH_HELD)
+ i = 0;
+ }
+ if (j == 0xffffU) {
+ mgr_log(mgr, ISC_LOG_ERROR,
+ "avoid-v%s-udp-ports: unable to allocate "
+ "an available port",
+ isc_sockaddr_pf(localaddr) == AF_INET ? "4" : "6");
+ result = ISC_R_FAILURE;
+ goto end;
+ }
+ *sockp = sock;
+
+end:
+ for (i = 0; i < DNS_DISPATCH_HELD; i++) {
+ if (held[i] != NULL)
+ isc_socket_detach(&held[i]);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
+ isc_taskmgr_t *taskmgr,
+ isc_sockaddr_t *localaddr,
+ unsigned int maxrequests,
+ unsigned int attributes,
+ dns_dispatch_t **dispp)
+{
+ isc_result_t result;
+ dns_dispatch_t *disp;
+ isc_socket_t *sock = NULL;
+ int i = 0;
+
+ /*
+ * dispatch_allocate() checks mgr for us.
+ */
+ disp = NULL;
+ result = dispatch_allocate(mgr, maxrequests, &disp);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) {
+ result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock);
+ if (result != ISC_R_SUCCESS)
+ goto deallocate_dispatch;
+ } else {
+ isc_sockaddr_t sa_any;
+
+ /*
+ * For dispatches using exclusive sockets with a specific
+ * source address, we only check if the specified address is
+ * available on the system. Query sockets will be created later
+ * on demand.
+ */
+ isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
+ if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
+ result = open_socket(sockmgr, localaddr, 0, &sock);
+ if (sock != NULL)
+ isc_socket_detach(&sock);
+ if (result != ISC_R_SUCCESS)
+ goto deallocate_dispatch;
+ }
+
+ disp->port_table = isc_mem_get(mgr->mctx,
+ sizeof(disp->port_table[0]) *
+ DNS_DISPATCH_PORTTABLESIZE);
+ if (disp->port_table == NULL)
+ goto deallocate_dispatch;
+ for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++)
+ ISC_LIST_INIT(disp->port_table[i]);
+
+ result = isc_mempool_create(mgr->mctx, sizeof(dispportentry_t),
+ &disp->portpool);
+ if (result != ISC_R_SUCCESS)
+ goto deallocate_dispatch;
+ isc_mempool_setname(disp->portpool, "disp_portpool");
+ isc_mempool_setfreemax(disp->portpool, 128);
+ }
+ disp->socktype = isc_sockettype_udp;
+ disp->socket = sock;
+ disp->local = *localaddr;
+
+ if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0)
+ disp->ntasks = MAX_INTERNAL_TASKS;
+ else
+ disp->ntasks = 1;
+ for (i = 0; i < disp->ntasks; i++) {
+ 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]);
+ goto kill_socket;
+ }
+ isc_task_setname(disp->task[i], "udpdispatch", disp);
+ }
+
+ disp->ctlevent = isc_event_allocate(mgr->mctx, disp,
+ DNS_EVENT_DISPATCHCONTROL,
+ destroy_disp, disp,
+ sizeof(isc_event_t));
+ if (disp->ctlevent == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto kill_task;
+ }
+
+ attributes &= ~DNS_DISPATCHATTR_TCP;
+ attributes |= DNS_DISPATCHATTR_UDP;
+ disp->attributes = attributes;
+
+ /*
+ * Append it to the dispatcher list.
+ */
+ ISC_LIST_APPEND(mgr->list, disp, link);
+
+ mgr_log(mgr, LVL(90), "created UDP dispatcher %p", disp);
+ dispatch_log(disp, LVL(90), "created task %p", disp->task[0]); /* XXX */
+ if (disp->socket != NULL)
+ dispatch_log(disp, LVL(90), "created socket %p", disp->socket);
+
+ *dispp = disp;
+ return (result);
+
+ /*
+ * Error returns.
+ */
+ kill_task:
+ for (i = 0; i < disp->ntasks; i++)
+ isc_task_detach(&disp->task[i]);
+ kill_socket:
+ if (disp->socket != NULL)
+ isc_socket_detach(&disp->socket);
+ deallocate_dispatch:
+ dispatch_free(&disp);
+
+ return (result);
+}
+
+void
+dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp) {
+ REQUIRE(VALID_DISPATCH(disp));
+ REQUIRE(dispp != NULL && *dispp == NULL);
+
+ LOCK(&disp->lock);
+ disp->refcount++;
+ UNLOCK(&disp->lock);
+
+ *dispp = disp;
+}
+
+/*
+ * It is important to lock the manager while we are deleting the dispatch,
+ * since dns_dispatch_getudp will call dispatch_find, which returns to
+ * the caller a dispatch but does not attach to it until later. _getudp
+ * locks the manager, however, so locking it here will keep us from attaching
+ * to a dispatcher that is in the process of going away.
+ */
+void
+dns_dispatch_detach(dns_dispatch_t **dispp) {
+ dns_dispatch_t *disp;
+ dispsocket_t *dispsock;
+ isc_boolean_t killit;
+
+ REQUIRE(dispp != NULL && VALID_DISPATCH(*dispp));
+
+ disp = *dispp;
+ *dispp = NULL;
+
+ LOCK(&disp->lock);
+
+ INSIST(disp->refcount > 0);
+ disp->refcount--;
+ killit = ISC_FALSE;
+ if (disp->refcount == 0) {
+ if (disp->recv_pending > 0)
+ isc_socket_cancel(disp->socket, disp->task[0],
+ ISC_SOCKCANCEL_RECV);
+ for (dispsock = ISC_LIST_HEAD(disp->activesockets);
+ dispsock != NULL;
+ dispsock = ISC_LIST_NEXT(dispsock, link)) {
+ isc_socket_cancel(dispsock->socket, dispsock->task,
+ ISC_SOCKCANCEL_RECV);
+ }
+ disp->shutting_down = 1;
+ }
+
+ dispatch_log(disp, LVL(90), "detach: refcount %d", disp->refcount);
+
+ killit = destroy_disp_ok(disp);
+ UNLOCK(&disp->lock);
+ if (killit)
+ isc_task_send(disp->task[0], &disp->ctlevent);
+}
+
+isc_result_t
+dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_messageid_t *idp, dns_dispentry_t **resp,
+ isc_socketmgr_t *sockmgr)
+{
+ dns_dispentry_t *res;
+ unsigned int bucket;
+ in_port_t localport = 0;
+ dns_messageid_t id;
+ int i;
+ isc_boolean_t ok;
+ dns_qid_t *qid;
+ dispsocket_t *dispsocket = NULL;
+ isc_result_t result;
+
+ REQUIRE(VALID_DISPATCH(disp));
+ REQUIRE(task != NULL);
+ REQUIRE(dest != NULL);
+ REQUIRE(resp != NULL && *resp == NULL);
+ REQUIRE(idp != NULL);
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0)
+ REQUIRE(sockmgr != NULL);
+
+ LOCK(&disp->lock);
+
+ if (disp->shutting_down == 1) {
+ UNLOCK(&disp->lock);
+ return (ISC_R_SHUTTINGDOWN);
+ }
+
+ if (disp->requests >= disp->maxrequests) {
+ UNLOCK(&disp->lock);
+ return (ISC_R_QUOTA);
+ }
+
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0 &&
+ disp->nsockets > DNS_DISPATCH_SOCKSQUOTA) {
+ dispsocket_t *oldestsocket;
+ dns_dispentry_t *oldestresp;
+ dns_dispatchevent_t *rev;
+
+ /*
+ * Kill oldest outstanding query if the number of sockets
+ * exceeds the quota to keep the room for new queries.
+ */
+ oldestsocket = ISC_LIST_HEAD(disp->activesockets);
+ oldestresp = oldestsocket->resp;
+ if (oldestresp != NULL && !oldestresp->item_out) {
+ rev = allocate_event(oldestresp->disp);
+ if (rev != NULL) {
+ rev->buffer.base = NULL;
+ rev->result = ISC_R_CANCELED;
+ rev->id = oldestresp->id;
+ ISC_EVENT_INIT(rev, sizeof(*rev), 0,
+ NULL, DNS_EVENT_DISPATCH,
+ oldestresp->action,
+ oldestresp->arg, oldestresp,
+ NULL, NULL);
+ oldestresp->item_out = ISC_TRUE;
+ isc_task_send(oldestresp->task,
+ ISC_EVENT_PTR(&rev));
+ }
+ }
+
+ /*
+ * Move this entry to the tail so that it won't (easily) be
+ * examined before actually being canceled.
+ */
+ ISC_LIST_UNLINK(disp->activesockets, oldestsocket, link);
+ ISC_LIST_APPEND(disp->activesockets, oldestsocket, link);
+ }
+
+ qid = DNS_QID(disp);
+ LOCK(&qid->lock);
+
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
+ /*
+ * Get a separate UDP socket with a random port number.
+ */
+ result = get_dispsocket(disp, dest, sockmgr, qid, &dispsocket,
+ &localport);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK(&qid->lock);
+ UNLOCK(&disp->lock);
+ return (result);
+ }
+ } else {
+ localport = disp->localport;
+ }
+
+ /*
+ * Try somewhat hard to find an unique ID.
+ */
+ id = (dns_messageid_t)dispatch_arc4random(DISP_ARC4CTX(disp));
+ bucket = dns_hash(qid, dest, id, localport);
+ ok = ISC_FALSE;
+ for (i = 0; i < 64; i++) {
+ if (entry_search(qid, dest, id, localport, bucket) == NULL) {
+ ok = ISC_TRUE;
+ break;
+ }
+ id += qid->qid_increment;
+ id &= 0x0000ffff;
+ bucket = dns_hash(qid, dest, id, localport);
+ }
+
+ if (!ok) {
+ UNLOCK(&qid->lock);
+ UNLOCK(&disp->lock);
+ return (ISC_R_NOMORE);
+ }
+
+ res = isc_mempool_get(disp->mgr->rpool);
+ if (res == NULL) {
+ UNLOCK(&qid->lock);
+ UNLOCK(&disp->lock);
+ if (dispsocket != NULL)
+ destroy_dispsocket(disp, &dispsocket);
+ return (ISC_R_NOMEMORY);
+ }
+
+ disp->refcount++;
+ disp->requests++;
+ res->task = NULL;
+ isc_task_attach(task, &res->task);
+ res->disp = disp;
+ res->id = id;
+ res->port = localport;
+ res->bucket = bucket;
+ res->host = *dest;
+ res->action = action;
+ res->arg = arg;
+ res->dispsocket = dispsocket;
+ if (dispsocket != NULL)
+ dispsocket->resp = res;
+ res->item_out = ISC_FALSE;
+ ISC_LIST_INIT(res->items);
+ ISC_LINK_INIT(res, link);
+ res->magic = RESPONSE_MAGIC;
+ ISC_LIST_APPEND(qid->qid_table[bucket], res, link);
+ UNLOCK(&qid->lock);
+
+ request_log(disp, res, LVL(90),
+ "attached to task %p", res->task);
+
+ if (((disp->attributes & DNS_DISPATCHATTR_UDP) != 0) ||
+ ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) != 0)) {
+ result = startrecv(disp, dispsocket);
+ if (result != ISC_R_SUCCESS) {
+ LOCK(&qid->lock);
+ ISC_LIST_UNLINK(qid->qid_table[bucket], res, link);
+ UNLOCK(&qid->lock);
+
+ if (dispsocket != NULL)
+ destroy_dispsocket(disp, &dispsocket);
+
+ disp->refcount--;
+ disp->requests--;
+
+ UNLOCK(&disp->lock);
+ isc_task_detach(&res->task);
+ isc_mempool_put(disp->mgr->rpool, res);
+ return (result);
+ }
+ }
+
+ if (dispsocket != NULL)
+ ISC_LIST_APPEND(disp->activesockets, dispsocket, link);
+
+ UNLOCK(&disp->lock);
+
+ *idp = id;
+ *resp = res;
+
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0)
+ INSIST(res->dispsocket != NULL);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_messageid_t *idp, dns_dispentry_t **resp)
+{
+ REQUIRE(VALID_DISPATCH(disp));
+ REQUIRE((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0);
+
+ return (dns_dispatch_addresponse2(disp, dest, task, action, arg,
+ idp, resp, NULL));
+}
+
+void
+dns_dispatch_starttcp(dns_dispatch_t *disp) {
+
+ REQUIRE(VALID_DISPATCH(disp));
+
+ dispatch_log(disp, LVL(90), "starttcp %p", disp->task[0]);
+
+ LOCK(&disp->lock);
+ disp->attributes |= DNS_DISPATCHATTR_CONNECTED;
+ (void)startrecv(disp, NULL);
+ UNLOCK(&disp->lock);
+}
+
+void
+dns_dispatch_removeresponse(dns_dispentry_t **resp,
+ dns_dispatchevent_t **sockevent)
+{
+ dns_dispatchmgr_t *mgr;
+ dns_dispatch_t *disp;
+ dns_dispentry_t *res;
+ dispsocket_t *dispsock;
+ dns_dispatchevent_t *ev;
+ unsigned int bucket;
+ isc_boolean_t killit;
+ unsigned int n;
+ isc_eventlist_t events;
+ dns_qid_t *qid;
+
+ REQUIRE(resp != NULL);
+ REQUIRE(VALID_RESPONSE(*resp));
+
+ res = *resp;
+ *resp = NULL;
+
+ disp = res->disp;
+ REQUIRE(VALID_DISPATCH(disp));
+ mgr = disp->mgr;
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+
+ qid = DNS_QID(disp);
+
+ if (sockevent != NULL) {
+ REQUIRE(*sockevent != NULL);
+ ev = *sockevent;
+ *sockevent = NULL;
+ } else {
+ ev = NULL;
+ }
+
+ LOCK(&disp->lock);
+
+ INSIST(disp->requests > 0);
+ disp->requests--;
+ INSIST(disp->refcount > 0);
+ disp->refcount--;
+ killit = ISC_FALSE;
+ if (disp->refcount == 0) {
+ if (disp->recv_pending > 0)
+ isc_socket_cancel(disp->socket, disp->task[0],
+ ISC_SOCKCANCEL_RECV);
+ for (dispsock = ISC_LIST_HEAD(disp->activesockets);
+ dispsock != NULL;
+ dispsock = ISC_LIST_NEXT(dispsock, link)) {
+ isc_socket_cancel(dispsock->socket, dispsock->task,
+ ISC_SOCKCANCEL_RECV);
+ }
+ disp->shutting_down = 1;
+ }
+
+ bucket = res->bucket;
+
+ LOCK(&qid->lock);
+ ISC_LIST_UNLINK(qid->qid_table[bucket], res, link);
+ UNLOCK(&qid->lock);
+
+ if (ev == NULL && res->item_out) {
+ /*
+ * We've posted our event, but the caller hasn't gotten it
+ * yet. Take it back.
+ */
+ ISC_LIST_INIT(events);
+ n = isc_task_unsend(res->task, res, DNS_EVENT_DISPATCH,
+ NULL, &events);
+ /*
+ * We had better have gotten it back.
+ */
+ INSIST(n == 1);
+ ev = (dns_dispatchevent_t *)ISC_LIST_HEAD(events);
+ }
+
+ if (ev != NULL) {
+ REQUIRE(res->item_out == ISC_TRUE);
+ res->item_out = ISC_FALSE;
+ if (ev->buffer.base != NULL)
+ free_buffer(disp, ev->buffer.base, ev->buffer.length);
+ free_event(disp, ev);
+ }
+
+ request_log(disp, res, LVL(90), "detaching from task %p", res->task);
+ isc_task_detach(&res->task);
+
+ if (res->dispsocket != NULL) {
+ isc_socket_cancel(res->dispsocket->socket,
+ res->dispsocket->task, ISC_SOCKCANCEL_RECV);
+ res->dispsocket->resp = NULL;
+ }
+
+ /*
+ * Free any buffered requests as well
+ */
+ ev = ISC_LIST_HEAD(res->items);
+ while (ev != NULL) {
+ ISC_LIST_UNLINK(res->items, ev, ev_link);
+ if (ev->buffer.base != NULL)
+ free_buffer(disp, ev->buffer.base, ev->buffer.length);
+ free_event(disp, ev);
+ ev = ISC_LIST_HEAD(res->items);
+ }
+ res->magic = 0;
+ isc_mempool_put(disp->mgr->rpool, res);
+ if (disp->shutting_down == 1)
+ do_cancel(disp);
+ else
+ (void)startrecv(disp, NULL);
+
+ killit = destroy_disp_ok(disp);
+ UNLOCK(&disp->lock);
+ if (killit)
+ isc_task_send(disp->task[0], &disp->ctlevent);
+}
+
+static void
+do_cancel(dns_dispatch_t *disp) {
+ dns_dispatchevent_t *ev;
+ dns_dispentry_t *resp;
+ dns_qid_t *qid;
+
+ if (disp->shutdown_out == 1)
+ return;
+
+ qid = DNS_QID(disp);
+
+ /*
+ * Search for the first response handler without packets outstanding
+ * unless a specific hander is given.
+ */
+ LOCK(&qid->lock);
+ for (resp = linear_first(qid);
+ resp != NULL && resp->item_out;
+ /* Empty. */)
+ resp = linear_next(qid, resp);
+
+ /*
+ * No one to send the cancel event to, so nothing to do.
+ */
+ if (resp == NULL)
+ goto unlock;
+
+ /*
+ * Send the shutdown failsafe event to this resp.
+ */
+ ev = disp->failsafe_ev;
+ ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, DNS_EVENT_DISPATCH,
+ resp->action, resp->arg, resp, NULL, NULL);
+ ev->result = disp->shutdown_why;
+ ev->buffer.base = NULL;
+ ev->buffer.length = 0;
+ disp->shutdown_out = 1;
+ request_log(disp, resp, LVL(10),
+ "cancel: failsafe event %p -> task %p",
+ ev, resp->task);
+ resp->item_out = ISC_TRUE;
+ isc_task_send(resp->task, ISC_EVENT_PTR(&ev));
+ unlock:
+ UNLOCK(&qid->lock);
+}
+
+isc_socket_t *
+dns_dispatch_getsocket(dns_dispatch_t *disp) {
+ REQUIRE(VALID_DISPATCH(disp));
+
+ return (disp->socket);
+}
+
+isc_socket_t *
+dns_dispatch_getentrysocket(dns_dispentry_t *resp) {
+ REQUIRE(VALID_RESPONSE(resp));
+
+ if (resp->dispsocket != NULL)
+ return (resp->dispsocket->socket);
+ else
+ return (NULL);
+}
+
+isc_result_t
+dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp) {
+
+ REQUIRE(VALID_DISPATCH(disp));
+ REQUIRE(addrp != NULL);
+
+ if (disp->socktype == isc_sockettype_udp) {
+ *addrp = disp->local;
+ return (ISC_R_SUCCESS);
+ }
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+void
+dns_dispatch_cancel(dns_dispatch_t *disp) {
+ REQUIRE(VALID_DISPATCH(disp));
+
+ LOCK(&disp->lock);
+
+ if (disp->shutting_down == 1) {
+ UNLOCK(&disp->lock);
+ return;
+ }
+
+ disp->shutdown_why = ISC_R_CANCELED;
+ disp->shutting_down = 1;
+ do_cancel(disp);
+
+ UNLOCK(&disp->lock);
+
+ return;
+}
+
+unsigned int
+dns_dispatch_getattributes(dns_dispatch_t *disp) {
+ REQUIRE(VALID_DISPATCH(disp));
+
+ /*
+ * We don't bother locking disp here; it's the caller's responsibility
+ * to use only non volatile flags.
+ */
+ return (disp->attributes);
+}
+
+void
+dns_dispatch_changeattributes(dns_dispatch_t *disp,
+ unsigned int attributes, unsigned int mask)
+{
+ REQUIRE(VALID_DISPATCH(disp));
+ /* Exclusive attribute can only be set on creation */
+ REQUIRE((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0);
+ /* Also, a dispatch with randomport specified cannot start listening */
+ REQUIRE((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0 ||
+ (attributes & DNS_DISPATCHATTR_NOLISTEN) == 0);
+
+ /* XXXMLG
+ * Should check for valid attributes here!
+ */
+
+ LOCK(&disp->lock);
+
+ if ((mask & DNS_DISPATCHATTR_NOLISTEN) != 0) {
+ if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0 &&
+ (attributes & DNS_DISPATCHATTR_NOLISTEN) == 0) {
+ disp->attributes &= ~DNS_DISPATCHATTR_NOLISTEN;
+ (void)startrecv(disp, NULL);
+ } else if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN)
+ == 0 &&
+ (attributes & DNS_DISPATCHATTR_NOLISTEN) != 0) {
+ disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
+ if (disp->recv_pending != 0)
+ isc_socket_cancel(disp->socket, disp->task[0],
+ ISC_SOCKCANCEL_RECV);
+ }
+ }
+
+ disp->attributes &= ~mask;
+ disp->attributes |= (attributes & mask);
+ UNLOCK(&disp->lock);
+}
+
+void
+dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) {
+ void *buf;
+ isc_socketevent_t *sevent, *newsevent;
+
+ REQUIRE(VALID_DISPATCH(disp));
+ REQUIRE((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0);
+ REQUIRE(event != NULL);
+
+ sevent = (isc_socketevent_t *)event;
+
+ INSIST(sevent->n <= disp->mgr->buffersize);
+ newsevent = (isc_socketevent_t *)
+ isc_event_allocate(disp->mgr->mctx, NULL,
+ DNS_EVENT_IMPORTRECVDONE, udp_shrecv,
+ disp, sizeof(isc_socketevent_t));
+ if (newsevent == NULL)
+ return;
+
+ buf = allocate_udp_buffer(disp);
+ if (buf == NULL) {
+ isc_event_free(ISC_EVENT_PTR(&newsevent));
+ return;
+ }
+ memcpy(buf, sevent->region.base, sevent->n);
+ newsevent->region.base = buf;
+ newsevent->region.length = disp->mgr->buffersize;
+ newsevent->n = sevent->n;
+ newsevent->result = sevent->result;
+ newsevent->address = sevent->address;
+ newsevent->timestamp = sevent->timestamp;
+ newsevent->pktinfo = sevent->pktinfo;
+ newsevent->attributes = sevent->attributes;
+
+ isc_task_send(disp->task[0], ISC_EVENT_PTR(&newsevent));
+}
+
+#if 0
+void
+dns_dispatchmgr_dump(dns_dispatchmgr_t *mgr) {
+ dns_dispatch_t *disp;
+ char foo[1024];
+
+ disp = ISC_LIST_HEAD(mgr->list);
+ while (disp != NULL) {
+ isc_sockaddr_format(&disp->local, foo, sizeof(foo));
+ printf("\tdispatch %p, addr %s\n", disp, foo);
+ disp = ISC_LIST_NEXT(disp, link);
+ }
+}
+#endif
diff --git a/lib/dns/dlz.c b/lib/dns/dlz.c
new file mode 100644
index 0000000..420eba3
--- /dev/null
+++ b/lib/dns/dlz.c
@@ -0,0 +1,510 @@
+/*
+ * Portions Copyright (C) 2005, 2007 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
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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: dlz.c,v 1.5 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+/***
+ *** Imports
+ ***/
+
+#include <config.h>
+
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/dlz.h>
+
+
+#include <isc/buffer.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/rwlock.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/***
+ *** Supported DLZ DB Implementations Registry
+ ***/
+
+static ISC_LIST(dns_dlzimplementation_t) dlz_implementations;
+static isc_rwlock_t dlz_implock;
+static isc_once_t once = ISC_ONCE_INIT;
+
+static void
+dlz_initialize(void) {
+ RUNTIME_CHECK(isc_rwlock_init(&dlz_implock, 0, 0) == ISC_R_SUCCESS);
+ ISC_LIST_INIT(dlz_implementations);
+}
+
+/*%
+ * Searches the dlz_implementations list for a driver matching name.
+ */
+static inline dns_dlzimplementation_t *
+dlz_impfind(const char *name) {
+ dns_dlzimplementation_t *imp;
+
+ for (imp = ISC_LIST_HEAD(dlz_implementations);
+ imp != NULL;
+ imp = ISC_LIST_NEXT(imp, link))
+ if (strcasecmp(name, imp->name) == 0)
+ return (imp);
+ return (NULL);
+}
+
+/***
+ *** Basic DLZ Methods
+ ***/
+
+isc_result_t
+dns_dlzallowzonexfr(dns_view_t *view, dns_name_t *name,
+ isc_sockaddr_t *clientaddr, dns_db_t **dbp)
+{
+ isc_result_t result;
+ dns_dlzallowzonexfr_t allowzonexfr;
+ dns_dlzdb_t *dlzdatabase;
+
+ /*
+ * Performs checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
+ REQUIRE(name != NULL);
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ /* ask driver if the zone is supported */
+ dlzdatabase = view->dlzdatabase;
+ allowzonexfr = dlzdatabase->implementation->methods->allowzonexfr;
+ result = (*allowzonexfr)(dlzdatabase->implementation->driverarg,
+ dlzdatabase->dbdata, dlzdatabase->mctx,
+ view->rdclass, name, clientaddr, dbp);
+
+ if (result == ISC_R_NOTIMPLEMENTED)
+ return (ISC_R_NOTFOUND);
+ return (result);
+}
+
+isc_result_t
+dns_dlzcreate(isc_mem_t *mctx, const char *dlzname, const char *drivername,
+ unsigned int argc, char *argv[], dns_dlzdb_t **dbp)
+{
+ dns_dlzimplementation_t *impinfo;
+ isc_result_t result;
+
+ /*
+ * initialize the dlz_implementations list, this is guaranteed
+ * to only really happen once.
+ */
+ RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
+
+ /*
+ * Performs checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(dbp != NULL && *dbp == NULL);
+ REQUIRE(dlzname != NULL);
+ REQUIRE(drivername != NULL);
+ REQUIRE(mctx != NULL);
+
+ /* write log message */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
+ "Loading '%s' using driver %s", dlzname, drivername);
+
+ /* lock the dlz_implementations list so we can search it. */
+ RWLOCK(&dlz_implock, isc_rwlocktype_read);
+
+ /* search for the driver implementation */
+ impinfo = dlz_impfind(drivername);
+ if (impinfo == NULL) {
+ RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "unsupported DLZ database driver '%s'."
+ " %s not loaded.",
+ drivername, dlzname);
+
+ return (ISC_R_NOTFOUND);
+ }
+
+ /* Allocate memory to hold the DLZ database driver */
+ (*dbp) = isc_mem_get(mctx, sizeof(dns_dlzdb_t));
+ if ((*dbp) == NULL) {
+ RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
+ return (ISC_R_NOMEMORY);
+ }
+
+ /* Make sure memory region is set to all 0's */
+ memset((*dbp), 0, sizeof(dns_dlzdb_t));
+
+ (*dbp)->implementation = impinfo;
+
+ /* Create a new database using implementation 'drivername'. */
+ result = ((impinfo->methods->create)(mctx, dlzname, argc, argv,
+ impinfo->driverarg,
+ &(*dbp)->dbdata));
+
+ /* mark the DLZ driver as valid */
+ if (result == ISC_R_SUCCESS) {
+ RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
+ (*dbp)->magic = DNS_DLZ_MAGIC;
+ isc_mem_attach(mctx, &(*dbp)->mctx);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "DLZ driver loaded successfully.");
+ return (ISC_R_SUCCESS);
+ } else {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "DLZ driver failed to load.");
+ }
+
+ /* impinfo->methods->create failed. */
+ RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
+ isc_mem_put(mctx, (*dbp), sizeof(dns_dlzdb_t));
+ return (result);
+}
+
+void
+dns_dlzdestroy(dns_dlzdb_t **dbp) {
+ isc_mem_t *mctx;
+ dns_dlzdestroy_t destroy;
+
+ /* Write debugging message to log */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Unloading DLZ driver.");
+
+ /*
+ * Perform checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(dbp != NULL && DNS_DLZ_VALID(*dbp));
+
+ /* call the drivers destroy method */
+ if ((*dbp) != NULL) {
+ mctx = (*dbp)->mctx;
+ destroy = (*dbp)->implementation->methods->destroy;
+ (*destroy)((*dbp)->implementation->driverarg,(*dbp)->dbdata);
+ /* return memory */
+ isc_mem_put(mctx, (*dbp), sizeof(dns_dlzdb_t));
+ isc_mem_detach(&mctx);
+ }
+
+ *dbp = NULL;
+}
+
+
+isc_result_t
+dns_dlzfindzone(dns_view_t *view, dns_name_t *name, unsigned int minlabels,
+ dns_db_t **dbp)
+{
+ dns_fixedname_t fname;
+ dns_name_t *zonename;
+ unsigned int namelabels;
+ unsigned int i;
+ isc_result_t result;
+ dns_dlzfindzone_t findzone;
+ dns_dlzdb_t *dlzdatabase;
+
+ /*
+ * Performs checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
+ REQUIRE(name != NULL);
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ /* setup a "fixed" dns name */
+ dns_fixedname_init(&fname);
+ zonename = dns_fixedname_name(&fname);
+
+ /* count the number of labels in the name */
+ namelabels = dns_name_countlabels(name);
+
+ /*
+ * loop through starting with the longest domain name and
+ * trying shorter names portions of the name until we find a
+ * match, have an error, or are below the 'minlabels'
+ * threshold. minlabels is 0, if the standard database didn't
+ * have a zone name match. Otherwise minlables is the number
+ * of labels in that name. We need to beat that for a
+ * "better" match for the DLZ database to be authoritative
+ * instead of the standard database.
+ */
+ for (i = namelabels; i > minlabels && i > 1; i--) {
+ if (i == namelabels) {
+ result = dns_name_copy(name, zonename, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else
+ dns_name_split(name, i, NULL, zonename);
+
+ /* ask SDLZ driver if the zone is supported */
+ dlzdatabase = view->dlzdatabase;
+ findzone = dlzdatabase->implementation->methods->findzone;
+ result = (*findzone)(dlzdatabase->implementation->driverarg,
+ dlzdatabase->dbdata, dlzdatabase->mctx,
+ view->rdclass, zonename, dbp);
+ if (result != ISC_R_NOTFOUND)
+ return (result);
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+/*%
+ * Registers a DLZ driver. This basically just adds the dlz
+ * driver to the list of available drivers in the dlz_implementations list.
+ */
+isc_result_t
+dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
+ void *driverarg, isc_mem_t *mctx,
+ dns_dlzimplementation_t **dlzimp)
+{
+
+ dns_dlzimplementation_t *dlz_imp;
+
+ /* Write debugging message to log */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "Registering DLZ driver '%s'", drivername);
+
+ /*
+ * Performs checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(drivername != NULL);
+ REQUIRE(methods != NULL);
+ REQUIRE(methods->create != NULL);
+ REQUIRE(methods->destroy != NULL);
+ REQUIRE(methods->findzone != NULL);
+ REQUIRE(mctx != NULL);
+ REQUIRE(dlzimp != NULL && *dlzimp == NULL);
+
+ /*
+ * initialize the dlz_implementations list, this is guaranteed
+ * to only really happen once.
+ */
+ RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
+
+ /* lock the dlz_implementations list so we can modify it. */
+ RWLOCK(&dlz_implock, isc_rwlocktype_write);
+
+ /*
+ * check that another already registered driver isn't using
+ * the same name
+ */
+ dlz_imp = dlz_impfind(drivername);
+ if (dlz_imp != NULL) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
+ "DLZ Driver '%s' already registered",
+ drivername);
+ RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
+ return (ISC_R_EXISTS);
+ }
+
+ /*
+ * Allocate memory for a dlz_implementation object. Error if
+ * we cannot.
+ */
+ dlz_imp = isc_mem_get(mctx, sizeof(dns_dlzimplementation_t));
+ if (dlz_imp == NULL) {
+ RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
+ return (ISC_R_NOMEMORY);
+ }
+
+ /* Make sure memory region is set to all 0's */
+ memset(dlz_imp, 0, sizeof(dns_dlzimplementation_t));
+
+ /* Store the data passed into this method */
+ dlz_imp->name = drivername;
+ dlz_imp->methods = methods;
+ dlz_imp->mctx = NULL;
+ dlz_imp->driverarg = driverarg;
+
+ /* attach the new dlz_implementation object to a memory context */
+ isc_mem_attach(mctx, &dlz_imp->mctx);
+
+ /*
+ * prepare the dlz_implementation object to be put in a list,
+ * and append it to the list
+ */
+ ISC_LINK_INIT(dlz_imp, link);
+ ISC_LIST_APPEND(dlz_implementations, dlz_imp, link);
+
+ /* Unlock the dlz_implementations list. */
+ RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
+
+ /* Pass back the dlz_implementation that we created. */
+ *dlzimp = dlz_imp;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Helper function for dns_dlzstrtoargv().
+ * Pardon the gratuitous recursion.
+ */
+static isc_result_t
+dns_dlzstrtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp,
+ char ***argvp, unsigned int n)
+{
+ isc_result_t result;
+
+ restart:
+ /* Discard leading whitespace. */
+ while (*s == ' ' || *s == '\t')
+ s++;
+
+ if (*s == '\0') {
+ /* We have reached the end of the string. */
+ *argcp = n;
+ *argvp = isc_mem_get(mctx, n * sizeof(char *));
+ if (*argvp == NULL)
+ return (ISC_R_NOMEMORY);
+ } else {
+ char *p = s;
+ while (*p != ' ' && *p != '\t' && *p != '\0' && *p != '{') {
+ if (*p == '\n') {
+ *p = ' ';
+ goto restart;
+ }
+ p++;
+ }
+
+ /* do "grouping", items between { and } are one arg */
+ if (*p == '{') {
+ char *t = p;
+ /*
+ * shift all characters to left by 1 to get rid of '{'
+ */
+ while (*t != '\0') {
+ t++;
+ *(t-1) = *t;
+ }
+ while (*p != '\0' && *p != '}') {
+ p++;
+ }
+ /* get rid of '}' character */
+ if (*p == '}') {
+ *p = '\0';
+ p++;
+ }
+ /* normal case, no "grouping" */
+ } else if (*p != '\0')
+ *p++ = '\0';
+
+ result = dns_dlzstrtoargvsub(mctx, p, argcp, argvp, n + 1);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ (*argvp)[n] = s;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Tokenize the string "s" into whitespace-separated words,
+ * return the number of words in '*argcp' and an array
+ * of pointers to the words in '*argvp'. The caller
+ * must free the array using isc_mem_put(). The string
+ * is modified in-place.
+ */
+isc_result_t
+dns_dlzstrtoargv(isc_mem_t *mctx, char *s,
+ unsigned int *argcp, char ***argvp)
+{
+ return(dns_dlzstrtoargvsub(mctx, s, argcp, argvp, 0));
+}
+
+/*%
+ * Unregisters a DLZ driver. This basically just removes the dlz
+ * driver from the list of available drivers in the dlz_implementations list.
+ */
+void
+dns_dlzunregister(dns_dlzimplementation_t **dlzimp) {
+ dns_dlzimplementation_t *dlz_imp;
+ 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 DLZ driver.");
+
+ /*
+ * Performs checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(dlzimp != NULL && *dlzimp != NULL);
+
+ /*
+ * initialize the dlz_implementations list, this is guaranteed
+ * to only really happen once.
+ */
+ RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
+
+ dlz_imp = *dlzimp;
+
+ /* lock the dlz_implementations list so we can modify it. */
+ RWLOCK(&dlz_implock, isc_rwlocktype_write);
+
+ /* remove the dlz_implementation object from the list */
+ ISC_LIST_UNLINK(dlz_implementations, dlz_imp, link);
+ mctx = dlz_imp->mctx;
+
+ /*
+ * 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));
+ isc_mem_detach(&mctx);
+
+ /* Unlock the dlz_implementations list. */
+ RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
+}
diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c
new file mode 100644
index 0000000..f06d715
--- /dev/null
+++ b/lib/dns/dnssec.c
@@ -0,0 +1,892 @@
+/*
+ * Copyright (C) 2004-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
+ * 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.c,v 1.93 2008/11/14 23:47:33 tbox Exp $
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/serial.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dnssec.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/message.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+#include <dns/tsig.h> /* for DNS_TSIG_FUDGE */
+
+#include <dst/result.h>
+
+#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
+
+#define RETERR(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
+
+#define TYPE_SIGN 0
+#define TYPE_VERIFY 1
+
+static isc_result_t
+digest_callback(void *arg, isc_region_t *data);
+
+static int
+rdata_compare_wrapper(const void *rdata1, const void *rdata2);
+
+static isc_result_t
+rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
+ dns_rdata_t **rdata, int *nrdata);
+
+static isc_result_t
+digest_callback(void *arg, isc_region_t *data) {
+ dst_context_t *ctx = arg;
+
+ return (dst_context_adddata(ctx, data));
+}
+
+/*
+ * Make qsort happy.
+ */
+static int
+rdata_compare_wrapper(const void *rdata1, const void *rdata2) {
+ return (dns_rdata_compare((const dns_rdata_t *)rdata1,
+ (const dns_rdata_t *)rdata2));
+}
+
+/*
+ * Sort the rdataset into an array.
+ */
+static isc_result_t
+rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
+ dns_rdata_t **rdata, int *nrdata)
+{
+ isc_result_t ret;
+ int i = 0, n;
+ dns_rdata_t *data;
+
+ n = dns_rdataset_count(set);
+
+ data = isc_mem_get(mctx, n * sizeof(dns_rdata_t));
+ if (data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ret = dns_rdataset_first(set);
+ if (ret != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, data, n * sizeof(dns_rdata_t));
+ return (ret);
+ }
+
+ /*
+ * Put them in the array.
+ */
+ do {
+ dns_rdata_init(&data[i]);
+ dns_rdataset_current(set, &data[i++]);
+ } while (dns_rdataset_next(set) == ISC_R_SUCCESS);
+
+ /*
+ * Sort the array.
+ */
+ qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper);
+ *rdata = data;
+ *nrdata = n;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx,
+ dst_key_t **key)
+{
+ isc_buffer_t b;
+ isc_region_t r;
+
+ INSIST(name != NULL);
+ INSIST(rdata != NULL);
+ INSIST(mctx != NULL);
+ INSIST(key != NULL);
+ INSIST(*key == NULL);
+ REQUIRE(rdata->type == dns_rdatatype_key ||
+ rdata->type == dns_rdatatype_dnskey);
+
+ dns_rdata_toregion(rdata, &r);
+ isc_buffer_init(&b, r.base, r.length);
+ isc_buffer_add(&b, r.length);
+ return (dst_key_fromdns(name, rdata->rdclass, &b, mctx, key));
+}
+
+static isc_result_t
+digest_sig(dst_context_t *ctx, dns_rdata_t *sigrdata, dns_rdata_rrsig_t *sig) {
+ isc_region_t r;
+ isc_result_t ret;
+ dns_fixedname_t fname;
+
+ dns_rdata_toregion(sigrdata, &r);
+ INSIST(r.length >= 19);
+
+ r.length = 18;
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ dns_fixedname_init(&fname);
+ RUNTIME_CHECK(dns_name_downcase(&sig->signer,
+ dns_fixedname_name(&fname), NULL)
+ == ISC_R_SUCCESS);
+ dns_name_toregion(dns_fixedname_name(&fname), &r);
+ return (dst_context_adddata(ctx, &r));
+}
+
+isc_result_t
+dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
+ isc_stdtime_t *inception, isc_stdtime_t *expire,
+ isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata)
+{
+ dns_rdata_rrsig_t sig;
+ dns_rdata_t tmpsigrdata;
+ dns_rdata_t *rdatas;
+ int nrdatas, i;
+ isc_buffer_t sigbuf, envbuf;
+ isc_region_t r;
+ dst_context_t *ctx = NULL;
+ isc_result_t ret;
+ isc_buffer_t *databuf = NULL;
+ char data[256 + 8];
+ isc_uint32_t flags;
+ unsigned int sigsize;
+ dns_fixedname_t fnewname;
+
+ REQUIRE(name != NULL);
+ REQUIRE(dns_name_countlabels(name) <= 255);
+ REQUIRE(set != NULL);
+ REQUIRE(key != NULL);
+ REQUIRE(inception != NULL);
+ REQUIRE(expire != NULL);
+ REQUIRE(mctx != NULL);
+ REQUIRE(sigrdata != NULL);
+
+ if (*inception >= *expire)
+ return (DNS_R_INVALIDTIME);
+
+ /*
+ * Is the key allowed to sign data?
+ */
+ flags = dst_key_flags(key);
+ if (flags & DNS_KEYTYPE_NOAUTH)
+ return (DNS_R_KEYUNAUTHORIZED);
+ if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
+ return (DNS_R_KEYUNAUTHORIZED);
+
+ sig.mctx = mctx;
+ sig.common.rdclass = set->rdclass;
+ sig.common.rdtype = dns_rdatatype_rrsig;
+ ISC_LINK_INIT(&sig.common, link);
+
+ dns_name_init(&sig.signer, NULL);
+ dns_name_clone(dst_key_name(key), &sig.signer);
+
+ sig.covered = set->type;
+ sig.algorithm = dst_key_alg(key);
+ sig.labels = dns_name_countlabels(name) - 1;
+ if (dns_name_iswildcard(name))
+ sig.labels--;
+ sig.originalttl = set->ttl;
+ sig.timesigned = *inception;
+ sig.timeexpire = *expire;
+ sig.keyid = dst_key_id(key);
+ ret = dst_key_sigsize(key, &sigsize);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ sig.siglen = sigsize;
+ /*
+ * The actual contents of sig.signature are not important yet, since
+ * they're not used in digest_sig().
+ */
+ sig.signature = isc_mem_get(mctx, sig.siglen);
+ if (sig.signature == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ret = isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_signature;
+
+ dns_rdata_init(&tmpsigrdata);
+ ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass,
+ sig.common.rdtype, &sig, databuf);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_databuf;
+
+ ret = dst_context_create(key, mctx, &ctx);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_databuf;
+
+ /*
+ * Digest the SIG rdata.
+ */
+ ret = digest_sig(ctx, &tmpsigrdata, &sig);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ dns_fixedname_init(&fnewname);
+ RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
+ NULL) == ISC_R_SUCCESS);
+ dns_name_toregion(dns_fixedname_name(&fnewname), &r);
+
+ /*
+ * Create an envelope for each rdata: <name|type|class|ttl>.
+ */
+ isc_buffer_init(&envbuf, data, sizeof(data));
+ memcpy(data, r.base, r.length);
+ isc_buffer_add(&envbuf, r.length);
+ isc_buffer_putuint16(&envbuf, set->type);
+ isc_buffer_putuint16(&envbuf, set->rdclass);
+ isc_buffer_putuint32(&envbuf, set->ttl);
+
+ ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+ isc_buffer_usedregion(&envbuf, &r);
+
+ for (i = 0; i < nrdatas; i++) {
+ isc_uint16_t len;
+ isc_buffer_t lenbuf;
+ isc_region_t lenr;
+
+ /*
+ * Skip duplicates.
+ */
+ if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0)
+ continue;
+
+ /*
+ * Digest the envelope.
+ */
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_array;
+
+ /*
+ * Digest the length of the rdata.
+ */
+ isc_buffer_init(&lenbuf, &len, sizeof(len));
+ INSIST(rdatas[i].length < 65536);
+ isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length);
+ isc_buffer_usedregion(&lenbuf, &lenr);
+ ret = dst_context_adddata(ctx, &lenr);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_array;
+
+ /*
+ * Digest the rdata.
+ */
+ ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_array;
+ }
+
+ isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
+ ret = dst_context_sign(ctx, &sigbuf);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_array;
+ isc_buffer_usedregion(&sigbuf, &r);
+ if (r.length != sig.siglen) {
+ ret = ISC_R_NOSPACE;
+ goto cleanup_array;
+ }
+ memcpy(sig.signature, r.base, sig.siglen);
+
+ ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass,
+ sig.common.rdtype, &sig, buffer);
+
+cleanup_array:
+ isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
+cleanup_context:
+ dst_context_destroy(&ctx);
+cleanup_databuf:
+ isc_buffer_free(&databuf);
+cleanup_signature:
+ isc_mem_put(mctx, sig.signature, sig.siglen);
+
+ return (ret);
+}
+
+isc_result_t
+dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
+ isc_boolean_t ignoretime, isc_mem_t *mctx,
+ dns_rdata_t *sigrdata, dns_name_t *wild)
+{
+ dns_rdata_rrsig_t sig;
+ dns_fixedname_t fnewname;
+ isc_region_t r;
+ isc_buffer_t envbuf;
+ dns_rdata_t *rdatas;
+ int nrdatas, i;
+ isc_stdtime_t now;
+ isc_result_t ret;
+ unsigned char data[300];
+ dst_context_t *ctx = NULL;
+ int labels = 0;
+ isc_uint32_t flags;
+
+ REQUIRE(name != NULL);
+ REQUIRE(set != NULL);
+ REQUIRE(key != NULL);
+ REQUIRE(mctx != NULL);
+ REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig);
+
+ ret = dns_rdata_tostruct(sigrdata, &sig, NULL);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ if (set->type != sig.covered)
+ return (DNS_R_SIGINVALID);
+
+ if (isc_serial_lt(sig.timeexpire, sig.timesigned))
+ return (DNS_R_SIGINVALID);
+
+ if (!ignoretime) {
+ isc_stdtime_get(&now);
+
+ /*
+ * Is SIG temporally valid?
+ */
+ if (isc_serial_lt((isc_uint32_t)now, sig.timesigned))
+ return (DNS_R_SIGFUTURE);
+ else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now))
+ return (DNS_R_SIGEXPIRED);
+ }
+
+ /*
+ * NS, SOA and DNSSKEY records are signed by their owner.
+ * DS records are signed by the parent.
+ */
+ switch (set->type) {
+ case dns_rdatatype_ns:
+ case dns_rdatatype_soa:
+ case dns_rdatatype_dnskey:
+ if (!dns_name_equal(name, &sig.signer))
+ return (DNS_R_SIGINVALID);
+ break;
+ case dns_rdatatype_ds:
+ if (dns_name_equal(name, &sig.signer))
+ return (DNS_R_SIGINVALID);
+ /* FALLTHROUGH */
+ default:
+ if (!dns_name_issubdomain(name, &sig.signer))
+ return (DNS_R_SIGINVALID);
+ break;
+ }
+
+ /*
+ * Is the key allowed to sign data?
+ */
+ flags = dst_key_flags(key);
+ if (flags & DNS_KEYTYPE_NOAUTH)
+ return (DNS_R_KEYUNAUTHORIZED);
+ if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
+ return (DNS_R_KEYUNAUTHORIZED);
+
+ ret = dst_context_create(key, mctx, &ctx);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_struct;
+
+ /*
+ * Digest the SIG rdata (not including the signature).
+ */
+ ret = digest_sig(ctx, sigrdata, &sig);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ /*
+ * If the name is an expanded wildcard, use the wildcard name.
+ */
+ dns_fixedname_init(&fnewname);
+ labels = dns_name_countlabels(name) - 1;
+ RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
+ NULL) == ISC_R_SUCCESS);
+ if (labels - sig.labels > 0)
+ dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1,
+ NULL, dns_fixedname_name(&fnewname));
+
+ dns_name_toregion(dns_fixedname_name(&fnewname), &r);
+
+ /*
+ * Create an envelope for each rdata: <name|type|class|ttl>.
+ */
+ isc_buffer_init(&envbuf, data, sizeof(data));
+ if (labels - sig.labels > 0) {
+ isc_buffer_putuint8(&envbuf, 1);
+ isc_buffer_putuint8(&envbuf, '*');
+ memcpy(data + 2, r.base, r.length);
+ }
+ else
+ memcpy(data, r.base, r.length);
+ isc_buffer_add(&envbuf, r.length);
+ isc_buffer_putuint16(&envbuf, set->type);
+ isc_buffer_putuint16(&envbuf, set->rdclass);
+ isc_buffer_putuint32(&envbuf, sig.originalttl);
+
+ ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ isc_buffer_usedregion(&envbuf, &r);
+
+ for (i = 0; i < nrdatas; i++) {
+ isc_uint16_t len;
+ isc_buffer_t lenbuf;
+ isc_region_t lenr;
+
+ /*
+ * Skip duplicates.
+ */
+ if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0)
+ continue;
+
+ /*
+ * Digest the envelope.
+ */
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_array;
+
+ /*
+ * Digest the rdata length.
+ */
+ isc_buffer_init(&lenbuf, &len, sizeof(len));
+ INSIST(rdatas[i].length < 65536);
+ isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length);
+ isc_buffer_usedregion(&lenbuf, &lenr);
+
+ /*
+ * Digest the rdata.
+ */
+ ret = dst_context_adddata(ctx, &lenr);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_array;
+ ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_array;
+ }
+
+ r.base = sig.signature;
+ r.length = sig.siglen;
+ ret = dst_context_verify(ctx, &r);
+ if (ret == DST_R_VERIFYFAILURE)
+ ret = DNS_R_SIGINVALID;
+
+cleanup_array:
+ isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
+cleanup_context:
+ dst_context_destroy(&ctx);
+cleanup_struct:
+ dns_rdata_freestruct(&sig);
+
+ if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) {
+ if (wild != NULL)
+ RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname,
+ dns_fixedname_name(&fnewname),
+ wild, NULL) == ISC_R_SUCCESS);
+ ret = DNS_R_FROMWILDCARD;
+ }
+ return (ret);
+}
+
+isc_result_t
+dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
+ isc_boolean_t ignoretime, isc_mem_t *mctx,
+ dns_rdata_t *sigrdata)
+{
+ isc_result_t result;
+
+ result = dns_dnssec_verify2(name, set, key, ignoretime, mctx,
+ sigrdata, NULL);
+ if (result == DNS_R_FROMWILDCARD)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
+#define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \
+ == DNS_KEYOWNER_ZONE)
+
+isc_result_t
+dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
+ dns_dbnode_t *node, dns_name_t *name,
+ const char *directory, isc_mem_t *mctx,
+ unsigned int maxkeys, dst_key_t **keys,
+ unsigned int *nkeys)
+{
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ dst_key_t *pubkey = NULL;
+ unsigned int count = 0;
+
+ REQUIRE(nkeys != NULL);
+ REQUIRE(keys != NULL);
+
+ *nkeys = 0;
+ dns_rdataset_init(&rdataset);
+ RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
+ &rdataset, NULL));
+ RETERR(dns_rdataset_first(&rdataset));
+ while (result == ISC_R_SUCCESS && count < maxkeys) {
+ pubkey = NULL;
+ dns_rdataset_current(&rdataset, &rdata);
+ RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey));
+ if (!is_zone_key(pubkey) ||
+ (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0)
+ goto next;
+ /* Corrupted .key file? */
+ if (!dns_name_equal(name, dst_key_name(pubkey)))
+ goto next;
+ keys[count] = NULL;
+ 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_FILENOTFOUND) {
+ keys[count] = pubkey;
+ pubkey = NULL;
+ count++;
+ goto next;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) {
+ /* We should never get here. */
+ dst_key_free(&keys[count]);
+ goto next;
+ }
+ count++;
+ next:
+ if (pubkey != NULL)
+ dst_key_free(&pubkey);
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ if (count == 0)
+ result = ISC_R_NOTFOUND;
+ else
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (pubkey != NULL)
+ dst_key_free(&pubkey);
+ if (result != ISC_R_SUCCESS)
+ while (count > 0)
+ dst_key_free(&keys[--count]);
+ *nkeys = count;
+ return (result);
+}
+
+isc_result_t
+dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver,
+ dns_dbnode_t *node, dns_name_t *name, isc_mem_t *mctx,
+ unsigned int maxkeys, dst_key_t **keys,
+ unsigned int *nkeys)
+{
+ return (dns_dnssec_findzonekeys2(db, ver, node, name, NULL, mctx,
+ maxkeys, keys, nkeys));
+}
+
+isc_result_t
+dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) {
+ dns_rdata_sig_t sig; /* SIG(0) */
+ unsigned char data[512];
+ unsigned char header[DNS_MESSAGE_HEADERLEN];
+ isc_buffer_t headerbuf, databuf, sigbuf;
+ unsigned int sigsize;
+ isc_buffer_t *dynbuf = NULL;
+ dns_rdata_t *rdata;
+ dns_rdatalist_t *datalist;
+ dns_rdataset_t *dataset;
+ isc_region_t r;
+ isc_stdtime_t now;
+ dst_context_t *ctx = NULL;
+ isc_mem_t *mctx;
+ isc_result_t result;
+ isc_boolean_t signeedsfree = ISC_TRUE;
+
+ REQUIRE(msg != NULL);
+ REQUIRE(key != NULL);
+
+ if (is_response(msg))
+ REQUIRE(msg->query.base != NULL);
+
+ mctx = msg->mctx;
+
+ memset(&sig, 0, sizeof(sig));
+
+ sig.mctx = mctx;
+ sig.common.rdclass = dns_rdataclass_any;
+ sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */
+ ISC_LINK_INIT(&sig.common, link);
+
+ sig.covered = 0;
+ sig.algorithm = dst_key_alg(key);
+ sig.labels = 0; /* the root name */
+ sig.originalttl = 0;
+
+ isc_stdtime_get(&now);
+ sig.timesigned = now - DNS_TSIG_FUDGE;
+ sig.timeexpire = now + DNS_TSIG_FUDGE;
+
+ sig.keyid = dst_key_id(key);
+
+ dns_name_init(&sig.signer, NULL);
+ dns_name_clone(dst_key_name(key), &sig.signer);
+
+ sig.siglen = 0;
+ sig.signature = NULL;
+
+ isc_buffer_init(&databuf, data, sizeof(data));
+
+ RETERR(dst_context_create(key, mctx, &ctx));
+
+ /*
+ * Digest the fields of the SIG - we can cheat and use
+ * dns_rdata_fromstruct. Since siglen is 0, the digested data
+ * is identical to dns format.
+ */
+ RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any,
+ dns_rdatatype_sig /* SIG(0) */,
+ &sig, &databuf));
+ isc_buffer_usedregion(&databuf, &r);
+ RETERR(dst_context_adddata(ctx, &r));
+
+ /*
+ * If this is a response, digest the query.
+ */
+ if (is_response(msg))
+ RETERR(dst_context_adddata(ctx, &msg->query));
+
+ /*
+ * Digest the header.
+ */
+ isc_buffer_init(&headerbuf, header, sizeof(header));
+ dns_message_renderheader(msg, &headerbuf);
+ isc_buffer_usedregion(&headerbuf, &r);
+ RETERR(dst_context_adddata(ctx, &r));
+
+ /*
+ * Digest the remainder of the message.
+ */
+ isc_buffer_usedregion(msg->buffer, &r);
+ isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
+ RETERR(dst_context_adddata(ctx, &r));
+
+ RETERR(dst_key_sigsize(key, &sigsize));
+ sig.siglen = sigsize;
+ sig.signature = (unsigned char *) isc_mem_get(mctx, sig.siglen);
+ if (sig.signature == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+
+ isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
+ RETERR(dst_context_sign(ctx, &sigbuf));
+ dst_context_destroy(&ctx);
+
+ rdata = NULL;
+ RETERR(dns_message_gettemprdata(msg, &rdata));
+ RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024));
+ RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
+ dns_rdatatype_sig /* SIG(0) */,
+ &sig, dynbuf));
+
+ isc_mem_put(mctx, sig.signature, sig.siglen);
+ signeedsfree = ISC_FALSE;
+
+ dns_message_takebuffer(msg, &dynbuf);
+
+ datalist = NULL;
+ RETERR(dns_message_gettemprdatalist(msg, &datalist));
+ datalist->rdclass = dns_rdataclass_any;
+ datalist->type = dns_rdatatype_sig; /* SIG(0) */
+ datalist->covers = 0;
+ datalist->ttl = 0;
+ ISC_LIST_INIT(datalist->rdata);
+ ISC_LIST_APPEND(datalist->rdata, rdata, link);
+ dataset = NULL;
+ RETERR(dns_message_gettemprdataset(msg, &dataset));
+ dns_rdataset_init(dataset);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS);
+ msg->sig0 = dataset;
+
+ return (ISC_R_SUCCESS);
+
+failure:
+ if (dynbuf != NULL)
+ isc_buffer_free(&dynbuf);
+ if (signeedsfree)
+ isc_mem_put(mctx, sig.signature, sig.siglen);
+ if (ctx != NULL)
+ dst_context_destroy(&ctx);
+
+ return (result);
+}
+
+isc_result_t
+dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
+ dst_key_t *key)
+{
+ dns_rdata_sig_t sig; /* SIG(0) */
+ unsigned char header[DNS_MESSAGE_HEADERLEN];
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t r, source_r, sig_r, header_r;
+ isc_stdtime_t now;
+ dst_context_t *ctx = NULL;
+ isc_mem_t *mctx;
+ isc_result_t result;
+ isc_uint16_t addcount;
+ isc_boolean_t signeedsfree = ISC_FALSE;
+
+ REQUIRE(source != NULL);
+ REQUIRE(msg != NULL);
+ REQUIRE(key != NULL);
+
+ mctx = msg->mctx;
+
+ msg->verify_attempted = 1;
+
+ if (is_response(msg)) {
+ if (msg->query.base == NULL)
+ return (DNS_R_UNEXPECTEDTSIG);
+ }
+
+ isc_buffer_usedregion(source, &source_r);
+
+ RETERR(dns_rdataset_first(msg->sig0));
+ dns_rdataset_current(msg->sig0, &rdata);
+
+ RETERR(dns_rdata_tostruct(&rdata, &sig, NULL));
+ signeedsfree = ISC_TRUE;
+
+ if (sig.labels != 0) {
+ result = DNS_R_SIGINVALID;
+ goto failure;
+ }
+
+ if (isc_serial_lt(sig.timeexpire, sig.timesigned)) {
+ result = DNS_R_SIGINVALID;
+ msg->sig0status = dns_tsigerror_badtime;
+ goto failure;
+ }
+
+ isc_stdtime_get(&now);
+ if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) {
+ result = DNS_R_SIGFUTURE;
+ msg->sig0status = dns_tsigerror_badtime;
+ goto failure;
+ }
+ else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) {
+ result = DNS_R_SIGEXPIRED;
+ msg->sig0status = dns_tsigerror_badtime;
+ goto failure;
+ }
+
+ if (!dns_name_equal(dst_key_name(key), &sig.signer)) {
+ result = DNS_R_SIGINVALID;
+ msg->sig0status = dns_tsigerror_badkey;
+ goto failure;
+ }
+
+ RETERR(dst_context_create(key, mctx, &ctx));
+
+ /*
+ * Digest the SIG(0) record, except for the signature.
+ */
+ dns_rdata_toregion(&rdata, &r);
+ r.length -= sig.siglen;
+ RETERR(dst_context_adddata(ctx, &r));
+
+ /*
+ * If this is a response, digest the query.
+ */
+ if (is_response(msg))
+ RETERR(dst_context_adddata(ctx, &msg->query));
+
+ /*
+ * Extract the header.
+ */
+ memcpy(header, source_r.base, DNS_MESSAGE_HEADERLEN);
+
+ /*
+ * Decrement the additional field counter.
+ */
+ memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
+ addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
+ memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
+
+ /*
+ * Digest the modified header.
+ */
+ header_r.base = (unsigned char *) header;
+ header_r.length = DNS_MESSAGE_HEADERLEN;
+ RETERR(dst_context_adddata(ctx, &header_r));
+
+ /*
+ * Digest all non-SIG(0) records.
+ */
+ r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
+ r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
+ RETERR(dst_context_adddata(ctx, &r));
+
+ sig_r.base = sig.signature;
+ sig_r.length = sig.siglen;
+ result = dst_context_verify(ctx, &sig_r);
+ if (result != ISC_R_SUCCESS) {
+ msg->sig0status = dns_tsigerror_badsig;
+ goto failure;
+ }
+
+ msg->verified_sig = 1;
+
+ dst_context_destroy(&ctx);
+ dns_rdata_freestruct(&sig);
+
+ return (ISC_R_SUCCESS);
+
+failure:
+ if (signeedsfree)
+ dns_rdata_freestruct(&sig);
+ if (ctx != NULL)
+ dst_context_destroy(&ctx);
+
+ return (result);
+}
diff --git a/lib/dns/ds.c b/lib/dns/ds.c
new file mode 100644
index 0000000..e994cc5
--- /dev/null
+++ b/lib/dns/ds.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002, 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: ds.c,v 1.11 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/region.h>
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+#include <isc/util.h>
+
+#include <dns/ds.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+
+isc_result_t
+dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
+ unsigned int digest_type, unsigned char *buffer,
+ dns_rdata_t *rdata)
+{
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ unsigned char digest[ISC_SHA256_DIGESTLENGTH];
+ isc_region_t r;
+ isc_buffer_t b;
+ dns_rdata_ds_t ds;
+
+ REQUIRE(key != NULL);
+ REQUIRE(key->type == dns_rdatatype_dnskey);
+
+ if (!dns_ds_digest_supported(digest_type))
+ return (ISC_R_NOTIMPLEMENTED);
+
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ (void)dns_name_downcase(owner, name, NULL);
+
+ memset(buffer, 0, DNS_DS_BUFFERSIZE);
+ isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE);
+
+ if (digest_type == DNS_DSDIGEST_SHA1) {
+ isc_sha1_t sha1;
+ isc_sha1_init(&sha1);
+ dns_name_toregion(name, &r);
+ isc_sha1_update(&sha1, r.base, r.length);
+ dns_rdata_toregion(key, &r);
+ INSIST(r.length >= 4);
+ isc_sha1_update(&sha1, r.base, r.length);
+ isc_sha1_final(&sha1, digest);
+ } else {
+ isc_sha256_t sha256;
+ isc_sha256_init(&sha256);
+ dns_name_toregion(name, &r);
+ isc_sha256_update(&sha256, r.base, r.length);
+ dns_rdata_toregion(key, &r);
+ INSIST(r.length >= 4);
+ isc_sha256_update(&sha256, r.base, r.length);
+ isc_sha256_final(digest, &sha256);
+ }
+
+ ds.mctx = NULL;
+ ds.common.rdclass = key->rdclass;
+ ds.common.rdtype = dns_rdatatype_ds;
+ 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;
+ ds.digest = digest;
+
+ return (dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds,
+ &ds, &b));
+}
+
+isc_boolean_t
+dns_ds_digest_supported(unsigned int digest_type) {
+ return (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
+ digest_type == DNS_DSDIGEST_SHA256));
+}
diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c
new file mode 100644
index 0000000..32f894d
--- /dev/null
+++ b/lib/dns/dst_api.c
@@ -0,0 +1,1310 @@
+/*
+ * Portions Copyright (C) 2004-2008 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
+ * 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 AND NETWORK ASSOCIATES 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.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 AND NETWORK ASSOCIATES 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.
+ */
+
+/*
+ * Principal Author: Brian Wellington
+ * $Id: dst_api.c,v 1.16 2008/11/14 22:53:46 marka Exp $
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/fsaccess.h>
+#include <isc/hmacsha.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/ttl.h>
+#include <dns/types.h>
+
+#include <dst/result.h>
+
+#include "dst_internal.h"
+
+#define DST_AS_STR(t) ((t).value.as_textregion.base)
+
+static dst_func_t *dst_t_func[DST_MAX_ALGS];
+static isc_entropy_t *dst_entropy_pool = NULL;
+static unsigned int dst_entropy_flags = 0;
+static isc_boolean_t dst_initialized = ISC_FALSE;
+
+void gss_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
+
+isc_mem_t *dst__memory_pool = NULL;
+
+/*
+ * Static functions.
+ */
+static dst_key_t * get_key_struct(dns_name_t *name,
+ unsigned int alg,
+ unsigned int flags,
+ unsigned int protocol,
+ unsigned int bits,
+ dns_rdataclass_t rdclass,
+ isc_mem_t *mctx);
+static isc_result_t write_public_key(const dst_key_t *key, int type,
+ const char *directory);
+static isc_result_t buildfilename(dns_name_t *name,
+ dns_keytag_t id,
+ unsigned int alg,
+ unsigned int type,
+ const char *directory,
+ isc_buffer_t *out);
+static isc_result_t computeid(dst_key_t *key);
+static isc_result_t frombuffer(dns_name_t *name,
+ unsigned int alg,
+ unsigned int flags,
+ unsigned int protocol,
+ dns_rdataclass_t rdclass,
+ isc_buffer_t *source,
+ isc_mem_t *mctx,
+ dst_key_t **keyp);
+
+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);
+
+#define RETERR(x) \
+ do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto out; \
+ } while (0)
+
+#define CHECKALG(alg) \
+ do { \
+ isc_result_t _r; \
+ _r = algorithm_status(alg); \
+ if (_r != ISC_R_SUCCESS) \
+ return (_r); \
+ } while (0); \
+
+static void *
+default_memalloc(void *arg, size_t size) {
+ UNUSED(arg);
+ if (size == 0U)
+ size = 1;
+ return (malloc(size));
+}
+
+static void
+default_memfree(void *arg, void *ptr) {
+ UNUSED(arg);
+ free(ptr);
+}
+
+isc_result_t
+dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags) {
+ isc_result_t result;
+
+ REQUIRE(mctx != NULL && ectx != NULL);
+ REQUIRE(dst_initialized == ISC_FALSE);
+
+ dst__memory_pool = NULL;
+
+#ifdef OPENSSL
+ UNUSED(mctx);
+ /*
+ * When using --with-openssl, there seems to be no good way of not
+ * leaking memory due to the openssl error handling mechanism.
+ * Avoid assertions by using a local memory context and not checking
+ * for leaks on exit. Note: as there are leaks we cannot use
+ * ISC_MEMFLAG_INTERNAL as it will free up memory still being used
+ * by libcrypto.
+ */
+ result = isc_mem_createx2(0, 0, default_memalloc, default_memfree,
+ NULL, &dst__memory_pool, 0);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_mem_setname(dst__memory_pool, "dst", NULL);
+ isc_mem_setdestroycheck(dst__memory_pool, ISC_FALSE);
+#else
+ isc_mem_attach(mctx, &dst__memory_pool);
+#endif
+ isc_entropy_attach(ectx, &dst_entropy_pool);
+ dst_entropy_flags = eflags;
+
+ dst_result_register();
+
+ memset(dst_t_func, 0, sizeof(dst_t_func));
+ RETERR(dst__hmacmd5_init(&dst_t_func[DST_ALG_HMACMD5]));
+ RETERR(dst__hmacsha1_init(&dst_t_func[DST_ALG_HMACSHA1]));
+ RETERR(dst__hmacsha224_init(&dst_t_func[DST_ALG_HMACSHA224]));
+ RETERR(dst__hmacsha256_init(&dst_t_func[DST_ALG_HMACSHA256]));
+ 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__opensslrsa_init(&dst_t_func[DST_ALG_RSAMD5]));
+ RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_RSASHA1]));
+ RETERR(dst__opensslrsa_init(&dst_t_func[DST_ALG_NSEC3RSASHA1]));
+#ifdef HAVE_OPENSSL_DSA
+ RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_DSA]));
+ RETERR(dst__openssldsa_init(&dst_t_func[DST_ALG_NSEC3DSA]));
+#endif
+ RETERR(dst__openssldh_init(&dst_t_func[DST_ALG_DH]));
+#endif /* OPENSSL */
+#ifdef GSSAPI
+ RETERR(dst__gssapi_init(&dst_t_func[DST_ALG_GSSAPI]));
+#endif
+ dst_initialized = ISC_TRUE;
+ return (ISC_R_SUCCESS);
+
+ out:
+ dst_lib_destroy();
+ return (result);
+}
+
+void
+dst_lib_destroy(void) {
+ int i;
+ RUNTIME_CHECK(dst_initialized == ISC_TRUE);
+ dst_initialized = ISC_FALSE;
+
+ for (i = 0; i < DST_MAX_ALGS; i++)
+ if (dst_t_func[i] != NULL && dst_t_func[i]->cleanup != NULL)
+ dst_t_func[i]->cleanup();
+#ifdef OPENSSL
+ dst__openssl_destroy();
+#endif
+ if (dst__memory_pool != NULL)
+ isc_mem_detach(&dst__memory_pool);
+ if (dst_entropy_pool != NULL)
+ isc_entropy_detach(&dst_entropy_pool);
+
+}
+
+isc_boolean_t
+dst_algorithm_supported(unsigned int alg) {
+ REQUIRE(dst_initialized == ISC_TRUE);
+
+ if (alg >= DST_MAX_ALGS || dst_t_func[alg] == NULL)
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+}
+
+isc_result_t
+dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) {
+ dst_context_t *dctx;
+ isc_result_t result;
+
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(mctx != NULL);
+ REQUIRE(dctxp != NULL && *dctxp == NULL);
+
+ if (key->func->createctx == NULL)
+ return (DST_R_UNSUPPORTEDALG);
+ if (key->keydata.generic == NULL)
+ return (DST_R_NULLKEY);
+
+ dctx = isc_mem_get(mctx, sizeof(dst_context_t));
+ if (dctx == NULL)
+ return (ISC_R_NOMEMORY);
+ dctx->key = key;
+ dctx->mctx = mctx;
+ result = key->func->createctx(key, dctx);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, dctx, sizeof(dst_context_t));
+ return (result);
+ }
+ dctx->magic = CTX_MAGIC;
+ *dctxp = dctx;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dst_context_destroy(dst_context_t **dctxp) {
+ dst_context_t *dctx;
+
+ REQUIRE(dctxp != NULL && VALID_CTX(*dctxp));
+
+ dctx = *dctxp;
+ INSIST(dctx->key->func->destroyctx != NULL);
+ dctx->key->func->destroyctx(dctx);
+ dctx->magic = 0;
+ isc_mem_put(dctx->mctx, dctx, sizeof(dst_context_t));
+ *dctxp = NULL;
+}
+
+isc_result_t
+dst_context_adddata(dst_context_t *dctx, const isc_region_t *data) {
+ REQUIRE(VALID_CTX(dctx));
+ REQUIRE(data != NULL);
+ INSIST(dctx->key->func->adddata != NULL);
+
+ return (dctx->key->func->adddata(dctx, data));
+}
+
+isc_result_t
+dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ dst_key_t *key;
+
+ REQUIRE(VALID_CTX(dctx));
+ REQUIRE(sig != NULL);
+
+ key = dctx->key;
+ CHECKALG(key->key_alg);
+ if (key->keydata.generic == NULL)
+ return (DST_R_NULLKEY);
+
+ if (key->func->sign == NULL)
+ return (DST_R_NOTPRIVATEKEY);
+ if (key->func->isprivate == NULL ||
+ key->func->isprivate(key) == ISC_FALSE)
+ return (DST_R_NOTPRIVATEKEY);
+
+ return (key->func->sign(dctx, sig));
+}
+
+isc_result_t
+dst_context_verify(dst_context_t *dctx, isc_region_t *sig) {
+ REQUIRE(VALID_CTX(dctx));
+ REQUIRE(sig != NULL);
+
+ CHECKALG(dctx->key->key_alg);
+ if (dctx->key->keydata.generic == NULL)
+ return (DST_R_NULLKEY);
+ if (dctx->key->func->verify == NULL)
+ return (DST_R_NOTPUBLICKEY);
+
+ return (dctx->key->func->verify(dctx, sig));
+}
+
+isc_result_t
+dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
+ isc_buffer_t *secret)
+{
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(VALID_KEY(pub) && VALID_KEY(priv));
+ REQUIRE(secret != NULL);
+
+ CHECKALG(pub->key_alg);
+ CHECKALG(priv->key_alg);
+
+ if (pub->keydata.generic == NULL || priv->keydata.generic == NULL)
+ return (DST_R_NULLKEY);
+
+ if (pub->key_alg != priv->key_alg ||
+ pub->func->computesecret == NULL ||
+ priv->func->computesecret == NULL)
+ return (DST_R_KEYCANNOTCOMPUTESECRET);
+
+ if (dst_key_isprivate(priv) == ISC_FALSE)
+ return (DST_R_NOTPRIVATEKEY);
+
+ return (pub->func->computesecret(pub, priv, secret));
+}
+
+isc_result_t
+dst_key_tofile(const dst_key_t *key, int type, const char *directory) {
+ isc_result_t ret = ISC_R_SUCCESS;
+
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(VALID_KEY(key));
+ REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
+
+ CHECKALG(key->key_alg);
+
+ if (key->func->tofile == NULL)
+ return (DST_R_UNSUPPORTEDALG);
+
+ if (type & DST_TYPE_PUBLIC) {
+ ret = write_public_key(key, type, directory);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ }
+
+ if ((type & DST_TYPE_PRIVATE) &&
+ (key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
+ return (key->func->tofile(key, directory));
+ else
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dst_key_fromfile(dns_name_t *name, dns_keytag_t id,
+ unsigned int alg, int type, const char *directory,
+ isc_mem_t *mctx, dst_key_t **keyp)
+{
+ char filename[ISC_DIR_NAMEMAX];
+ isc_buffer_t b;
+ dst_key_t *key;
+ isc_result_t result;
+
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
+ REQUIRE(mctx != NULL);
+ REQUIRE(keyp != NULL && *keyp == NULL);
+
+ CHECKALG(alg);
+
+ isc_buffer_init(&b, filename, sizeof(filename));
+ result = buildfilename(name, id, alg, type, directory, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ key = NULL;
+ result = dst_key_fromnamedfile(filename, type, mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = computeid(key);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (result);
+ }
+
+ if (!dns_name_equal(name, key->key_name) || id != key->key_id ||
+ alg != key->key_alg) {
+ dst_key_free(&key);
+ return (DST_R_INVALIDPRIVATEKEY);
+ }
+ key->key_id = id;
+
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dst_key_fromnamedfile(const char *filename, 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;
+
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(filename != NULL);
+ REQUIRE((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) != 0);
+ REQUIRE(mctx != NULL);
+ REQUIRE(keyp != NULL && *keyp == NULL);
+
+ newfilenamelen = strlen(filename) + 5;
+ newfilename = isc_mem_get(mctx, newfilenamelen);
+ if (newfilename == NULL)
+ return (ISC_R_NOMEMORY);
+ result = addsuffix(newfilename, newfilenamelen, filename, ".key");
+ INSIST(result == ISC_R_SUCCESS);
+
+ result = dst_key_read_public(newfilename, type, mctx, &pubkey);
+ isc_mem_put(mctx, newfilename, newfilenamelen);
+ newfilename = NULL;
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if ((type & (DST_TYPE_PRIVATE | DST_TYPE_PUBLIC)) == DST_TYPE_PUBLIC ||
+ (pubkey->key_flags & DNS_KEYFLAG_TYPEMASK) == DNS_KEYTYPE_NOKEY) {
+ result = computeid(pubkey);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_free(&pubkey);
+ return (result);
+ }
+
+ *keyp = pubkey;
+ return (ISC_R_SUCCESS);
+ }
+
+ result = algorithm_status(pubkey->key_alg);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_free(&pubkey);
+ return (result);
+ }
+
+ 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)
+ return (ISC_R_NOMEMORY);
+
+ if (key->func->parse == NULL)
+ RETERR(DST_R_UNSUPPORTEDALG);
+
+ newfilenamelen = strlen(filename) + 9;
+ newfilename = isc_mem_get(mctx, newfilenamelen);
+ if (newfilename == NULL)
+ RETERR(ISC_R_NOMEMORY);
+ result = addsuffix(newfilename, newfilenamelen, 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));
+ isc_lex_destroy(&lex);
+
+ RETERR(computeid(key));
+
+ if (id != key->key_id)
+ RETERR(DST_R_INVALIDPRIVATEKEY);
+
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+ out:
+ if (newfilename != NULL)
+ isc_mem_put(mctx, newfilename, newfilenamelen);
+ if (lex != NULL)
+ isc_lex_destroy(&lex);
+ dst_key_free(&key);
+ return (result);
+}
+
+isc_result_t
+dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(target != NULL);
+
+ CHECKALG(key->key_alg);
+
+ if (key->func->todns == NULL)
+ return (DST_R_UNSUPPORTEDALG);
+
+ if (isc_buffer_availablelength(target) < 4)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putuint16(target, (isc_uint16_t)(key->key_flags & 0xffff));
+ isc_buffer_putuint8(target, (isc_uint8_t)key->key_proto);
+ isc_buffer_putuint8(target, (isc_uint8_t)key->key_alg);
+
+ if (key->key_flags & DNS_KEYFLAG_EXTENDED) {
+ if (isc_buffer_availablelength(target) < 2)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putuint16(target,
+ (isc_uint16_t)((key->key_flags >> 16)
+ & 0xffff));
+ }
+
+ if (key->keydata.generic == NULL) /*%< NULL KEY */
+ return (ISC_R_SUCCESS);
+
+ return (key->func->todns(key, target));
+}
+
+isc_result_t
+dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass,
+ isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
+{
+ isc_uint8_t alg, proto;
+ isc_uint32_t flags, extflags;
+ dst_key_t *key = NULL;
+ dns_keytag_t id;
+ isc_region_t r;
+ isc_result_t result;
+
+ REQUIRE(dst_initialized);
+
+ isc_buffer_remainingregion(source, &r);
+
+ if (isc_buffer_remaininglength(source) < 4)
+ return (DST_R_INVALIDPUBLICKEY);
+ flags = isc_buffer_getuint16(source);
+ proto = isc_buffer_getuint8(source);
+ alg = isc_buffer_getuint8(source);
+
+ id = dst_region_computeid(&r, alg);
+
+ if (flags & DNS_KEYFLAG_EXTENDED) {
+ if (isc_buffer_remaininglength(source) < 2)
+ return (DST_R_INVALIDPUBLICKEY);
+ extflags = isc_buffer_getuint16(source);
+ flags |= (extflags << 16);
+ }
+
+ result = frombuffer(name, alg, flags, proto, rdclass, source,
+ mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ key->key_id = id;
+
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dst_key_frombuffer(dns_name_t *name, unsigned int alg,
+ unsigned int flags, unsigned int protocol,
+ dns_rdataclass_t rdclass,
+ isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
+{
+ dst_key_t *key = NULL;
+ isc_result_t result;
+
+ REQUIRE(dst_initialized);
+
+ result = frombuffer(name, alg, flags, protocol, rdclass, source,
+ mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = computeid(key);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (result);
+ }
+
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target) {
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(target != NULL);
+
+ CHECKALG(key->key_alg);
+
+ if (key->func->todns == NULL)
+ return (DST_R_UNSUPPORTEDALG);
+
+ return (key->func->todns(key, target));
+}
+
+isc_result_t
+dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer) {
+ isc_lex_t *lex = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(!dst_key_isprivate(key));
+ REQUIRE(buffer != NULL);
+
+ if (key->func->parse == NULL)
+ RETERR(DST_R_UNSUPPORTEDALG);
+
+ RETERR(isc_lex_create(key->mctx, 1500, &lex));
+ RETERR(isc_lex_openbuffer(lex, buffer));
+ RETERR(key->func->parse(key, lex));
+ out:
+ if (lex != NULL)
+ isc_lex_destroy(&lex);
+ return (result);
+}
+
+gss_ctx_id_t
+dst_key_getgssctx(const dst_key_t *key)
+{
+ REQUIRE(key != NULL);
+
+ return (key->keydata.gssctx);
+}
+
+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 *key;
+
+ REQUIRE(gssctx != NULL);
+ REQUIRE(keyp != NULL && *keyp == NULL);
+
+ key = get_key_struct(name, DST_ALG_GSSAPI, 0, DNS_KEYPROTO_DNSSEC,
+ 0, dns_rdataclass_in, mctx);
+ if (key == NULL)
+ return (ISC_R_NOMEMORY);
+
+ key->keydata.gssctx = gssctx;
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags,
+ unsigned int protocol, dns_rdataclass_t rdclass,
+ const char *engine, const char *label, const char *pin,
+ isc_mem_t *mctx, dst_key_t **keyp)
+{
+ dst_key_t *key;
+ isc_result_t result;
+
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE(mctx != NULL);
+ REQUIRE(keyp != NULL && *keyp == NULL);
+ REQUIRE(label != NULL);
+
+ CHECKALG(alg);
+
+ key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx);
+ if (key == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (key->func->fromlabel == NULL) {
+ dst_key_free(&key);
+ return (DST_R_UNSUPPORTEDALG);
+ }
+
+ result = key->func->fromlabel(key, engine, label, pin);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (result);
+ }
+
+ result = computeid(key);
+ if (result != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (result);
+ }
+
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dst_key_generate(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)
+{
+ dst_key_t *key;
+ isc_result_t ret;
+
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE(mctx != NULL);
+ REQUIRE(keyp != NULL && *keyp == NULL);
+
+ CHECKALG(alg);
+
+ key = get_key_struct(name, alg, flags, protocol, bits, rdclass, mctx);
+ if (key == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (bits == 0) { /*%< NULL KEY */
+ key->key_flags |= DNS_KEYTYPE_NOKEY;
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+ }
+
+ if (key->func->generate == NULL) {
+ dst_key_free(&key);
+ return (DST_R_UNSUPPORTEDALG);
+ }
+
+ ret = key->func->generate(key, param);
+ if (ret != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (ret);
+ }
+
+ ret = computeid(key);
+ if (ret != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (ret);
+ }
+
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+dst_key_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);
+ else
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dst_key_paramcompare(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->func->paramcompare != NULL &&
+ key1->func->paramcompare(key1, key2) == ISC_TRUE)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+void
+dst_key_free(dst_key_t **keyp) {
+ isc_mem_t *mctx;
+ dst_key_t *key;
+
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(keyp != NULL && VALID_KEY(*keyp));
+
+ key = *keyp;
+ mctx = key->mctx;
+
+ if (key->keydata.generic != NULL) {
+ INSIST(key->func->destroy != NULL);
+ key->func->destroy(key);
+ }
+ if (key->engine != NULL)
+ isc_mem_free(mctx, key->engine);
+ if (key->label != NULL)
+ isc_mem_free(mctx, key->label);
+ dns_name_free(key->key_name, mctx);
+ isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
+ memset(key, 0, sizeof(dst_key_t));
+ isc_mem_put(mctx, key, sizeof(dst_key_t));
+ *keyp = NULL;
+}
+
+isc_boolean_t
+dst_key_isprivate(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+ INSIST(key->func->isprivate != NULL);
+ return (key->func->isprivate(key));
+}
+
+isc_result_t
+dst_key_buildfilename(const dst_key_t *key, int type,
+ const char *directory, isc_buffer_t *out) {
+
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(type == DST_TYPE_PRIVATE || type == DST_TYPE_PUBLIC ||
+ type == 0);
+
+ return (buildfilename(key->key_name, key->key_id, key->key_alg,
+ type, directory, out));
+}
+
+isc_result_t
+dst_key_sigsize(const dst_key_t *key, unsigned int *n) {
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(n != NULL);
+
+ /* XXXVIX this switch statement is too sparse to gen a jump table. */
+ switch (key->key_alg) {
+ case DST_ALG_RSAMD5:
+ case DST_ALG_RSASHA1:
+ case DST_ALG_NSEC3RSASHA1:
+ *n = (key->key_size + 7) / 8;
+ break;
+ case DST_ALG_DSA:
+ case DST_ALG_NSEC3DSA:
+ *n = DNS_SIG_DSASIGSIZE;
+ break;
+ case DST_ALG_HMACMD5:
+ *n = 16;
+ break;
+ case DST_ALG_HMACSHA1:
+ *n = ISC_SHA1_DIGESTLENGTH;
+ break;
+ case DST_ALG_HMACSHA224:
+ *n = ISC_SHA224_DIGESTLENGTH;
+ break;
+ case DST_ALG_HMACSHA256:
+ *n = ISC_SHA256_DIGESTLENGTH;
+ break;
+ case DST_ALG_HMACSHA384:
+ *n = ISC_SHA384_DIGESTLENGTH;
+ break;
+ case DST_ALG_HMACSHA512:
+ *n = ISC_SHA512_DIGESTLENGTH;
+ break;
+ case DST_ALG_GSSAPI:
+ *n = 128; /*%< XXX */
+ break;
+ case DST_ALG_DH:
+ default:
+ return (DST_R_UNSUPPORTEDALG);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dst_key_secretsize(const dst_key_t *key, unsigned int *n) {
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(VALID_KEY(key));
+ REQUIRE(n != NULL);
+
+ if (key->key_alg == DST_ALG_DH)
+ *n = (key->key_size + 7) / 8;
+ else
+ return (DST_R_UNSUPPORTEDALG);
+ return (ISC_R_SUCCESS);
+}
+
+/***
+ *** Static methods
+ ***/
+
+/*%
+ * Allocates a key structure and fills in some of the fields.
+ */
+static dst_key_t *
+get_key_struct(dns_name_t *name, unsigned int alg,
+ unsigned int flags, unsigned int protocol,
+ unsigned int bits, dns_rdataclass_t rdclass,
+ isc_mem_t *mctx)
+{
+ dst_key_t *key;
+ isc_result_t result;
+
+ key = (dst_key_t *) isc_mem_get(mctx, sizeof(dst_key_t));
+ if (key == NULL)
+ return (NULL);
+
+ memset(key, 0, sizeof(dst_key_t));
+ key->magic = KEY_MAGIC;
+
+ key->key_name = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (key->key_name == NULL) {
+ isc_mem_put(mctx, key, sizeof(dst_key_t));
+ return (NULL);
+ }
+ dns_name_init(key->key_name, NULL);
+ result = dns_name_dup(name, mctx, key->key_name);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, key->key_name, sizeof(dns_name_t));
+ isc_mem_put(mctx, key, sizeof(dst_key_t));
+ return (NULL);
+ }
+ key->key_alg = alg;
+ key->key_flags = flags;
+ key->key_proto = protocol;
+ key->mctx = mctx;
+ key->keydata.generic = NULL;
+ key->key_size = bits;
+ key->key_class = rdclass;
+ key->func = dst_t_func[alg];
+ return (key);
+}
+
+/*%
+ * Reads a public key from disk
+ */
+isc_result_t
+dst_key_read_public(const char *filename, int type,
+ isc_mem_t *mctx, dst_key_t **keyp)
+{
+ u_char rdatabuf[DST_KEY_MAXSIZE];
+ isc_buffer_t b;
+ dns_fixedname_t name;
+ isc_lex_t *lex = NULL;
+ isc_token_t token;
+ isc_result_t ret;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
+ dns_rdataclass_t rdclass = dns_rdataclass_in;
+ isc_lexspecials_t specials;
+ isc_uint32_t ttl;
+ isc_result_t result;
+ dns_rdatatype_t keytype;
+
+ /*
+ * Open the file and read its formatted contents
+ * File format:
+ * domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> <algorithm> <key>
+ */
+
+ /* 1500 should be large enough for any key */
+ ret = isc_lex_create(mctx, 1500, &lex);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup;
+
+ memset(specials, 0, sizeof(specials));
+ specials['('] = 1;
+ specials[')'] = 1;
+ specials['"'] = 1;
+ isc_lex_setspecials(lex, specials);
+ isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
+
+ ret = isc_lex_openfile(lex, filename);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup;
+
+#define NEXTTOKEN(lex, opt, token) { \
+ ret = isc_lex_gettoken(lex, opt, token); \
+ if (ret != ISC_R_SUCCESS) \
+ goto cleanup; \
+ }
+
+#define BADTOKEN() { \
+ ret = ISC_R_UNEXPECTEDTOKEN; \
+ goto cleanup; \
+ }
+
+ /* Read the domain name */
+ NEXTTOKEN(lex, opt, &token);
+ if (token.type != isc_tokentype_string)
+ BADTOKEN();
+
+ /*
+ * We don't support "@" in .key files.
+ */
+ if (!strcmp(DST_AS_STR(token), "@"))
+ BADTOKEN();
+
+ dns_fixedname_init(&name);
+ 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);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Read the next word: either TTL, class, or 'KEY' */
+ NEXTTOKEN(lex, opt, &token);
+
+ /* If it's a TTL, read the next one */
+ result = dns_ttl_fromtext(&token.value.as_textregion, &ttl);
+ if (result == ISC_R_SUCCESS)
+ NEXTTOKEN(lex, opt, &token);
+
+ if (token.type != isc_tokentype_string)
+ BADTOKEN();
+
+ ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion);
+ if (ret == ISC_R_SUCCESS)
+ NEXTTOKEN(lex, opt, &token);
+
+ if (token.type != isc_tokentype_string)
+ BADTOKEN();
+
+ if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0)
+ keytype = dns_rdatatype_dnskey;
+ else if (strcasecmp(DST_AS_STR(token), "KEY") == 0)
+ keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */
+ else
+ BADTOKEN();
+
+ if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) ||
+ ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey)) {
+ ret = DST_R_BADKEYTYPE;
+ goto cleanup;
+ }
+
+ isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
+ ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL,
+ ISC_FALSE, mctx, &b, NULL);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup;
+
+ ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx,
+ keyp);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup;
+
+ cleanup:
+ if (lex != NULL)
+ isc_lex_destroy(&lex);
+ return (ret);
+}
+
+static isc_boolean_t
+issymmetric(const dst_key_t *key) {
+ REQUIRE(dst_initialized == ISC_TRUE);
+ REQUIRE(VALID_KEY(key));
+
+ /* XXXVIX this switch statement is too sparse to gen a jump table. */
+ switch (key->key_alg) {
+ case DST_ALG_RSAMD5:
+ case DST_ALG_RSASHA1:
+ case DST_ALG_NSEC3RSASHA1:
+ case DST_ALG_DSA:
+ case DST_ALG_NSEC3DSA:
+ case DST_ALG_DH:
+ return (ISC_FALSE);
+ case DST_ALG_HMACMD5:
+ case DST_ALG_GSSAPI:
+ return (ISC_TRUE);
+ default:
+ return (ISC_FALSE);
+ }
+}
+
+/*%
+ * Writes a public key to disk in DNS format.
+ */
+static isc_result_t
+write_public_key(const dst_key_t *key, int type, const char *directory) {
+ FILE *fp;
+ isc_buffer_t keyb, textb, fileb, classb;
+ isc_region_t r;
+ char filename[ISC_DIR_NAMEMAX];
+ unsigned char key_array[DST_KEY_MAXSIZE];
+ char text_array[DST_KEY_MAXTEXTSIZE];
+ char class_array[10];
+ isc_result_t ret;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_fsaccess_t access;
+
+ REQUIRE(VALID_KEY(key));
+
+ isc_buffer_init(&keyb, key_array, sizeof(key_array));
+ isc_buffer_init(&textb, text_array, sizeof(text_array));
+ isc_buffer_init(&classb, class_array, sizeof(class_array));
+
+ ret = dst_key_todns(key, &keyb);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ isc_buffer_usedregion(&keyb, &r);
+ dns_rdata_fromregion(&rdata, key->key_class, dns_rdatatype_dnskey, &r);
+
+ ret = dns_rdata_totext(&rdata, (dns_name_t *) NULL, &textb);
+ if (ret != ISC_R_SUCCESS)
+ return (DST_R_INVALIDPUBLICKEY);
+
+ ret = dns_rdataclass_totext(key->key_class, &classb);
+ if (ret != ISC_R_SUCCESS)
+ return (DST_R_INVALIDPUBLICKEY);
+
+ /*
+ * Make the filename.
+ */
+ isc_buffer_init(&fileb, filename, sizeof(filename));
+ ret = dst_key_buildfilename(key, DST_TYPE_PUBLIC, directory, &fileb);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ /*
+ * Create public key file.
+ */
+ if ((fp = fopen(filename, "w")) == NULL)
+ return (DST_R_WRITEERROR);
+
+ if (issymmetric(key)) {
+ access = 0;
+ isc_fsaccess_add(ISC_FSACCESS_OWNER,
+ ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
+ &access);
+ (void)isc_fsaccess_set(filename, access);
+ }
+
+ ret = dns_name_print(key->key_name, fp);
+ if (ret != ISC_R_SUCCESS) {
+ fclose(fp);
+ return (ret);
+ }
+
+ fprintf(fp, " ");
+
+ isc_buffer_usedregion(&classb, &r);
+ fwrite(r.base, 1, r.length, fp);
+
+ if ((type & DST_TYPE_KEY) != 0)
+ fprintf(fp, " KEY ");
+ else
+ fprintf(fp, " DNSKEY ");
+
+ isc_buffer_usedregion(&textb, &r);
+ fwrite(r.base, 1, r.length, fp);
+
+ fputc('\n', fp);
+ fclose(fp);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+buildfilename(dns_name_t *name, dns_keytag_t id,
+ unsigned int alg, unsigned int type,
+ const char *directory, isc_buffer_t *out)
+{
+ const char *suffix = "";
+ unsigned int len;
+ isc_result_t result;
+
+ REQUIRE(out != NULL);
+ if ((type & DST_TYPE_PRIVATE) != 0)
+ suffix = ".private";
+ else if (type == DST_TYPE_PUBLIC)
+ suffix = ".key";
+ if (directory != NULL) {
+ if (isc_buffer_availablelength(out) < strlen(directory))
+ return (ISC_R_NOSPACE);
+ isc_buffer_putstr(out, directory);
+ if (strlen(directory) > 0U &&
+ directory[strlen(directory) - 1] != '/')
+ isc_buffer_putstr(out, "/");
+ }
+ if (isc_buffer_availablelength(out) < 1)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putstr(out, "K");
+ result = dns_name_tofilenametext(name, ISC_FALSE, out);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ len = 1 + 3 + 1 + 5 + strlen(suffix) + 1;
+ if (isc_buffer_availablelength(out) < len)
+ return (ISC_R_NOSPACE);
+ sprintf((char *) isc_buffer_used(out), "+%03d+%05d%s", alg, id,
+ suffix);
+ isc_buffer_add(out, len);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+computeid(dst_key_t *key) {
+ isc_buffer_t dnsbuf;
+ unsigned char dns_array[DST_KEY_MAXSIZE];
+ isc_region_t r;
+ isc_result_t ret;
+
+ isc_buffer_init(&dnsbuf, dns_array, sizeof(dns_array));
+ ret = dst_key_todns(key, &dnsbuf);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ isc_buffer_usedregion(&dnsbuf, &r);
+ key->key_id = dst_region_computeid(&r, key->key_alg);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+frombuffer(dns_name_t *name, unsigned int alg, unsigned int flags,
+ unsigned int protocol, dns_rdataclass_t rdclass,
+ isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp)
+{
+ dst_key_t *key;
+ isc_result_t ret;
+
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE(source != NULL);
+ REQUIRE(mctx != NULL);
+ REQUIRE(keyp != NULL && *keyp == NULL);
+
+ key = get_key_struct(name, alg, flags, protocol, 0, rdclass, mctx);
+ if (key == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (isc_buffer_remaininglength(source) > 0) {
+ ret = algorithm_status(alg);
+ if (ret != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (ret);
+ }
+ if (key->func->fromdns == NULL) {
+ dst_key_free(&key);
+ return (DST_R_UNSUPPORTEDALG);
+ }
+
+ ret = key->func->fromdns(key, source);
+ if (ret != ISC_R_SUCCESS) {
+ dst_key_free(&key);
+ return (ret);
+ }
+ }
+
+ *keyp = key;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+algorithm_status(unsigned int alg) {
+ REQUIRE(dst_initialized == ISC_TRUE);
+
+ if (dst_algorithm_supported(alg))
+ return (ISC_R_SUCCESS);
+#ifndef OPENSSL
+ if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
+ alg == DST_ALG_DSA || alg == DST_ALG_DH ||
+ alg == DST_ALG_HMACMD5 || alg == DST_ALG_NSEC3DSA ||
+ alg == DST_ALG_NSEC3RSASHA1)
+ 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)
+{
+ int olen = strlen(ofilename);
+ int n;
+
+ if (olen > 1 && ofilename[olen - 1] == '.')
+ olen -= 1;
+ else if (olen > 8 && strcmp(ofilename + olen - 8, ".private") == 0)
+ olen -= 8;
+ else if (olen > 4 && strcmp(ofilename + olen - 4, ".key") == 0)
+ olen -= 4;
+
+ n = snprintf(filename, len, "%.*s%s", olen, ofilename, suffix);
+ if (n < 0)
+ return (ISC_R_NOSPACE);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dst__entropy_getdata(void *buf, unsigned int len, isc_boolean_t pseudo) {
+ unsigned int flags = dst_entropy_flags;
+ if (pseudo)
+ flags &= ~ISC_ENTROPY_GOODONLY;
+ return (isc_entropy_getdata(dst_entropy_pool, buf, len, NULL, flags));
+}
+
+unsigned int
+dst__entropy_status(void) {
+ return (isc_entropy_status(dst_entropy_pool));
+}
diff --git a/lib/dns/dst_internal.h b/lib/dns/dst_internal.h
new file mode 100644
index 0000000..0c1a71c
--- /dev/null
+++ b/lib/dns/dst_internal.h
@@ -0,0 +1,217 @@
+/*
+ * Portions Copyright (C) 2004-2008 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
+ * 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 AND NETWORK ASSOCIATES 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.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 AND NETWORK ASSOCIATES 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: dst_internal.h,v 1.11 2008/04/01 23:47:10 tbox Exp $ */
+
+#ifndef DST_DST_INTERNAL_H
+#define DST_DST_INTERNAL_H 1
+
+#include <isc/lang.h>
+#include <isc/buffer.h>
+#include <isc/int.h>
+#include <isc/magic.h>
+#include <isc/region.h>
+#include <isc/types.h>
+#include <isc/md5.h>
+#include <isc/sha1.h>
+#include <isc/hmacmd5.h>
+#include <isc/hmacsha.h>
+
+#include <dst/dst.h>
+
+#ifdef OPENSSL
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/rsa.h>
+#endif
+
+ISC_LANG_BEGINDECLS
+
+#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)
+
+extern isc_mem_t *dst__memory_pool;
+
+/***
+ *** Types
+ ***/
+
+typedef struct dst_func dst_func_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;
+typedef struct dst_hmacsha384_key dst_hmacsha384_key_t;
+typedef struct dst_hmacsha512_key dst_hmacsha512_key_t;
+
+/*% DST Key Structure */
+struct dst_key {
+ unsigned int magic;
+ dns_name_t * key_name; /*%< name of the key */
+ unsigned int key_size; /*%< size of the key in bits */
+ unsigned int key_proto; /*%< protocols this key is used for */
+ unsigned int key_alg; /*%< algorithm of the key */
+ isc_uint32_t key_flags; /*%< flags of the public key */
+ isc_uint16_t key_id; /*%< identifier of the key */
+ isc_uint16_t key_bits; /*%< hmac digest bits */
+ dns_rdataclass_t key_class; /*%< class of the key record */
+ isc_mem_t *mctx; /*%< memory context */
+ char *engine; /*%< engine name (HSM) */
+ char *label; /*%< engine label (HSM) */
+ union {
+ void *generic;
+ gss_ctx_id_t gssctx;
+#ifdef OPENSSL
+#if USE_EVP_RSA
+ RSA *rsa;
+#endif
+ DSA *dsa;
+ DH *dh;
+ EVP_PKEY *pkey;
+#endif
+ dst_hmacmd5_key_t *hmacmd5;
+ dst_hmacsha1_key_t *hmacsha1;
+ dst_hmacsha224_key_t *hmacsha224;
+ dst_hmacsha256_key_t *hmacsha256;
+ dst_hmacsha384_key_t *hmacsha384;
+ dst_hmacsha512_key_t *hmacsha512;
+
+ } keydata; /*%< pointer to key in crypto pkg fmt */
+ dst_func_t * func; /*%< crypto package specific functions */
+};
+
+struct dst_context {
+ unsigned int magic;
+ dst_key_t *key;
+ isc_mem_t *mctx;
+ union {
+ void *generic;
+ dst_gssapi_signverifyctx_t *gssctx;
+ isc_md5_t *md5ctx;
+ isc_sha1_t *sha1ctx;
+ isc_hmacmd5_t *hmacmd5ctx;
+ isc_hmacsha1_t *hmacsha1ctx;
+ isc_hmacsha224_t *hmacsha224ctx;
+ isc_hmacsha256_t *hmacsha256ctx;
+ isc_hmacsha384_t *hmacsha384ctx;
+ isc_hmacsha512_t *hmacsha512ctx;
+#ifdef OPENSSL
+ EVP_MD_CTX *evp_md_ctx;
+#endif
+ } ctxdata;
+};
+
+struct dst_func {
+ /*
+ * Context functions
+ */
+ isc_result_t (*createctx)(dst_key_t *key, dst_context_t *dctx);
+ void (*destroyctx)(dst_context_t *dctx);
+ isc_result_t (*adddata)(dst_context_t *dctx, const isc_region_t *data);
+
+ /*
+ * Key operations
+ */
+ isc_result_t (*sign)(dst_context_t *dctx, isc_buffer_t *sig);
+ isc_result_t (*verify)(dst_context_t *dctx, const isc_region_t *sig);
+ isc_result_t (*computesecret)(const dst_key_t *pub,
+ const dst_key_t *priv,
+ isc_buffer_t *secret);
+ 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_boolean_t (*isprivate)(const dst_key_t *key);
+ void (*destroy)(dst_key_t *key);
+
+ /* conversion functions */
+ 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);
+
+ /* cleanup */
+ void (*cleanup)(void);
+
+ isc_result_t (*fromlabel)(dst_key_t *key, const char *engine,
+ const char *label, const char *pin);
+};
+
+/*%
+ * Initializers
+ */
+isc_result_t dst__openssl_init(void);
+
+isc_result_t dst__hmacmd5_init(struct dst_func **funcp);
+isc_result_t dst__hmacsha1_init(struct dst_func **funcp);
+isc_result_t dst__hmacsha224_init(struct dst_func **funcp);
+isc_result_t dst__hmacsha256_init(struct dst_func **funcp);
+isc_result_t dst__hmacsha384_init(struct dst_func **funcp);
+isc_result_t dst__hmacsha512_init(struct dst_func **funcp);
+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);
+
+/*%
+ * Destructors
+ */
+void dst__openssl_destroy(void);
+
+/*%
+ * Memory allocators using the DST memory pool.
+ */
+void * dst__mem_alloc(size_t size);
+void dst__mem_free(void *ptr);
+void * dst__mem_realloc(void *ptr, size_t size);
+
+/*%
+ * Entropy retriever using the DST entropy pool.
+ */
+isc_result_t dst__entropy_getdata(void *buf, unsigned int len,
+ isc_boolean_t pseudo);
+
+/*
+ * Entropy status hook.
+ */
+unsigned int dst__entropy_status(void);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DST_DST_INTERNAL_H */
+/*! \file */
diff --git a/lib/dns/dst_lib.c b/lib/dns/dst_lib.c
new file mode 100644
index 0000000..f1021d3
--- /dev/null
+++ b/lib/dns/dst_lib.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+/*
+ * Principal Author: Brian Wellington
+ * $Id: dst_lib.c,v 1.5 2007/06/19 23:47:16 tbox Exp $
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/once.h>
+#include <isc/msgcat.h>
+#include <isc/util.h>
+
+#include <dst/lib.h>
+
+/***
+ *** Globals
+ ***/
+
+LIBDNS_EXTERNAL_DATA isc_msgcat_t * dst_msgcat = NULL;
+
+
+/***
+ *** Private
+ ***/
+
+static isc_once_t msgcat_once = ISC_ONCE_INIT;
+
+
+/***
+ *** Functions
+ ***/
+
+static void
+open_msgcat(void) {
+ isc_msgcat_open("libdst.cat", &dst_msgcat);
+}
+
+void
+dst_lib_initmsgcat(void) {
+
+ /*
+ * Initialize the DST library's message catalog, dst_msgcat, if it
+ * has not already been initialized.
+ */
+
+ RUNTIME_CHECK(isc_once_do(&msgcat_once, open_msgcat) == ISC_R_SUCCESS);
+}
diff --git a/lib/dns/dst_openssl.h b/lib/dns/dst_openssl.h
new file mode 100644
index 0000000..80eef93
--- /dev/null
+++ b/lib/dns/dst_openssl.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: dst_openssl.h,v 1.7 2008/04/01 23:47:10 tbox Exp $ */
+
+#ifndef DST_OPENSSL_H
+#define DST_OPENSSL_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+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);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DST_OPENSSL_H */
+/*! \file */
diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c
new file mode 100644
index 0000000..43ac9f3
--- /dev/null
+++ b/lib/dns/dst_parse.c
@@ -0,0 +1,532 @@
+/*
+ * Portions Copyright (C) 2004-2008 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
+ * 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 AND NETWORK ASSOCIATES 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.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 AND NETWORK ASSOCIATES 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.
+ */
+
+/*%
+ * Principal Author: Brian Wellington
+ * $Id: dst_parse.c,v 1.14 2008/03/31 23:47:11 tbox Exp $
+ */
+
+#include <config.h>
+
+#include <isc/base64.h>
+#include <isc/dir.h>
+#include <isc/fsaccess.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include "dst_internal.h"
+#include "dst_parse.h"
+#include "dst/result.h"
+
+#define DST_AS_STR(t) ((t).value.as_textregion.base)
+
+#define PRIVATE_KEY_STR "Private-key-format:"
+#define ALGORITHM_STR "Algorithm:"
+
+struct parse_map {
+ const int value;
+ const char *tag;
+};
+
+static struct parse_map map[] = {
+ {TAG_RSA_MODULUS, "Modulus:"},
+ {TAG_RSA_PUBLICEXPONENT, "PublicExponent:"},
+ {TAG_RSA_PRIVATEEXPONENT, "PrivateExponent:"},
+ {TAG_RSA_PRIME1, "Prime1:"},
+ {TAG_RSA_PRIME2, "Prime2:"},
+ {TAG_RSA_EXPONENT1, "Exponent1:"},
+ {TAG_RSA_EXPONENT2, "Exponent2:"},
+ {TAG_RSA_COEFFICIENT, "Coefficient:"},
+ {TAG_RSA_ENGINE, "Engine:" },
+ {TAG_RSA_LABEL, "Label:" },
+ {TAG_RSA_PIN, "PIN:" },
+
+ {TAG_DH_PRIME, "Prime(p):"},
+ {TAG_DH_GENERATOR, "Generator(g):"},
+ {TAG_DH_PRIVATE, "Private_value(x):"},
+ {TAG_DH_PUBLIC, "Public_value(y):"},
+
+ {TAG_DSA_PRIME, "Prime(p):"},
+ {TAG_DSA_SUBPRIME, "Subprime(q):"},
+ {TAG_DSA_BASE, "Base(g):"},
+ {TAG_DSA_PRIVATE, "Private_value(x):"},
+ {TAG_DSA_PUBLIC, "Public_value(y):"},
+
+ {TAG_HMACMD5_KEY, "Key:"},
+ {TAG_HMACMD5_BITS, "Bits:"},
+
+ {TAG_HMACSHA1_KEY, "Key:"},
+ {TAG_HMACSHA1_BITS, "Bits:"},
+
+ {TAG_HMACSHA224_KEY, "Key:"},
+ {TAG_HMACSHA224_BITS, "Bits:"},
+
+ {TAG_HMACSHA256_KEY, "Key:"},
+ {TAG_HMACSHA256_BITS, "Bits:"},
+
+ {TAG_HMACSHA384_KEY, "Key:"},
+ {TAG_HMACSHA384_BITS, "Bits:"},
+
+ {TAG_HMACSHA512_KEY, "Key:"},
+ {TAG_HMACSHA512_BITS, "Bits:"},
+
+ {0, NULL}
+};
+
+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)
+ return (map[i].value);
+ }
+}
+
+static const char *
+find_tag(const int value) {
+ int i;
+
+ for (i = 0; ; i++) {
+ if (map[i].tag == NULL)
+ return (NULL);
+ else if (value == map[i].value)
+ return (map[i].tag);
+ }
+}
+
+static int
+check_rsa(const dst_private_t *priv) {
+ int i, j;
+ isc_boolean_t have[RSA_NTAGS];
+ isc_boolean_t ok;
+ unsigned int mask;
+
+ for (i = 0; i < RSA_NTAGS; i++)
+ have[i] = ISC_FALSE;
+ for (j = 0; j < priv->nelements; j++) {
+ for (i = 0; i < RSA_NTAGS; i++)
+ if (priv->elements[j].tag == TAG(DST_ALG_RSAMD5, i))
+ break;
+ if (i == RSA_NTAGS)
+ return (-1);
+ have[i] = ISC_TRUE;
+ }
+
+ mask = ~0;
+ mask <<= sizeof(mask) * 8 - TAG_SHIFT;
+ mask >>= sizeof(mask) * 8 - TAG_SHIFT;
+
+ if (have[TAG_RSA_ENGINE & mask])
+ ok = have[TAG_RSA_MODULUS & mask] &&
+ have[TAG_RSA_PUBLICEXPONENT & mask] &&
+ have[TAG_RSA_LABEL & mask];
+ else
+ ok = have[TAG_RSA_MODULUS & mask] &&
+ have[TAG_RSA_PUBLICEXPONENT & mask] &&
+ have[TAG_RSA_PRIVATEEXPONENT & mask] &&
+ have[TAG_RSA_PRIME1 & mask] &&
+ have[TAG_RSA_PRIME2 & mask] &&
+ have[TAG_RSA_EXPONENT1 & mask] &&
+ have[TAG_RSA_EXPONENT2 & mask] &&
+ have[TAG_RSA_COEFFICIENT & mask];
+ return (ok ? 0 : -1 );
+}
+
+static int
+check_dh(const dst_private_t *priv) {
+ int i, j;
+ if (priv->nelements != DH_NTAGS)
+ return (-1);
+ for (i = 0; i < DH_NTAGS; i++) {
+ for (j = 0; j < priv->nelements; j++)
+ if (priv->elements[j].tag == TAG(DST_ALG_DH, i))
+ break;
+ if (j == priv->nelements)
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+check_dsa(const dst_private_t *priv) {
+ int i, j;
+ if (priv->nelements != DSA_NTAGS)
+ return (-1);
+ for (i = 0; i < DSA_NTAGS; i++) {
+ for (j = 0; j < priv->nelements; j++)
+ if (priv->elements[j].tag == TAG(DST_ALG_DSA, i))
+ break;
+ if (j == priv->nelements)
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+check_hmac_md5(const dst_private_t *priv, isc_boolean_t old) {
+ int i, j;
+
+ if (priv->nelements != HMACMD5_NTAGS) {
+ /*
+ * If this is a good old format and we are accepting
+ * the old format return success.
+ */
+ if (old && priv->nelements == OLD_HMACMD5_NTAGS &&
+ priv->elements[0].tag == TAG_HMACMD5_KEY)
+ return (0);
+ return (-1);
+ }
+ /*
+ * We must be new format at this point.
+ */
+ for (i = 0; i < HMACMD5_NTAGS; i++) {
+ for (j = 0; j < priv->nelements; j++)
+ if (priv->elements[j].tag == TAG(DST_ALG_HMACMD5, i))
+ break;
+ if (j == priv->nelements)
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+check_hmac_sha(const dst_private_t *priv, unsigned int ntags,
+ unsigned int alg)
+{
+ unsigned int i, j;
+ if (priv->nelements != ntags)
+ return (-1);
+ for (i = 0; i < ntags; i++) {
+ for (j = 0; j < priv->nelements; j++)
+ if (priv->elements[j].tag == TAG(alg, i))
+ break;
+ if (j == priv->nelements)
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+check_data(const dst_private_t *priv, const unsigned int alg,
+ isc_boolean_t old)
+{
+ /* XXXVIX this switch statement is too sparse to gen a jump table. */
+ switch (alg) {
+ case DST_ALG_RSAMD5:
+ case DST_ALG_RSASHA1:
+ return (check_rsa(priv));
+ case DST_ALG_DH:
+ return (check_dh(priv));
+ case DST_ALG_DSA:
+ return (check_dsa(priv));
+ case DST_ALG_HMACMD5:
+ return (check_hmac_md5(priv, old));
+ case DST_ALG_HMACSHA1:
+ return (check_hmac_sha(priv, HMACSHA1_NTAGS, alg));
+ case DST_ALG_HMACSHA224:
+ return (check_hmac_sha(priv, HMACSHA224_NTAGS, alg));
+ case DST_ALG_HMACSHA256:
+ return (check_hmac_sha(priv, HMACSHA256_NTAGS, alg));
+ case DST_ALG_HMACSHA384:
+ return (check_hmac_sha(priv, HMACSHA384_NTAGS, alg));
+ case DST_ALG_HMACSHA512:
+ return (check_hmac_sha(priv, HMACSHA512_NTAGS, alg));
+ default:
+ return (DST_R_UNSUPPORTEDALG);
+ }
+}
+
+void
+dst__privstruct_free(dst_private_t *priv, isc_mem_t *mctx) {
+ int i;
+
+ if (priv == NULL)
+ return;
+ for (i = 0; i < priv->nelements; i++) {
+ if (priv->elements[i].data == NULL)
+ continue;
+ memset(priv->elements[i].data, 0, MAXFIELDSIZE);
+ isc_mem_put(mctx, priv->elements[i].data, MAXFIELDSIZE);
+ }
+ priv->nelements = 0;
+}
+
+int
+dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
+ isc_mem_t *mctx, dst_private_t *priv)
+{
+ int n = 0, major, minor;
+ isc_buffer_t b;
+ isc_token_t token;
+ unsigned char *data = NULL;
+ unsigned int opt = ISC_LEXOPT_EOL;
+ isc_result_t ret;
+
+ REQUIRE(priv != NULL);
+
+ priv->nelements = 0;
+ memset(priv->elements, 0, sizeof(priv->elements));
+
+#define NEXTTOKEN(lex, opt, token) \
+ do { \
+ ret = isc_lex_gettoken(lex, opt, token); \
+ if (ret != ISC_R_SUCCESS) \
+ goto fail; \
+ } while (0)
+
+#define READLINE(lex, opt, token) \
+ do { \
+ ret = isc_lex_gettoken(lex, opt, token); \
+ if (ret == ISC_R_EOF) \
+ break; \
+ else if (ret != ISC_R_SUCCESS) \
+ goto fail; \
+ } while ((*token).type != isc_tokentype_eol)
+
+ /*
+ * Read the description line.
+ */
+ NEXTTOKEN(lex, opt, &token);
+ if (token.type != isc_tokentype_string ||
+ strcmp(DST_AS_STR(token), PRIVATE_KEY_STR) != 0)
+ {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+
+ NEXTTOKEN(lex, opt, &token);
+ if (token.type != isc_tokentype_string ||
+ (DST_AS_STR(token))[0] != 'v')
+ {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+ if (sscanf(DST_AS_STR(token), "v%d.%d", &major, &minor) != 2)
+ {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+
+ if (major > MAJOR_VERSION ||
+ (major == MAJOR_VERSION && minor > MINOR_VERSION))
+ {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+
+ READLINE(lex, opt, &token);
+
+ /*
+ * Read the algorithm line.
+ */
+ NEXTTOKEN(lex, opt, &token);
+ if (token.type != isc_tokentype_string ||
+ strcmp(DST_AS_STR(token), ALGORITHM_STR) != 0)
+ {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+
+ NEXTTOKEN(lex, opt | ISC_LEXOPT_NUMBER, &token);
+ if (token.type != isc_tokentype_number ||
+ token.value.as_ulong != (unsigned long) dst_key_alg(key))
+ {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+
+ READLINE(lex, opt, &token);
+
+ /*
+ * Read the key data.
+ */
+ 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)
+ goto done;
+ if (ret != ISC_R_SUCCESS)
+ goto fail;
+ } while (token.type == isc_tokentype_eol);
+
+ if (token.type != isc_tokentype_string) {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+
+ tag = find_value(DST_AS_STR(token), alg);
+ if (tag < 0 || TAG_ALG(tag) != alg) {
+ ret = DST_R_INVALIDPRIVATEKEY;
+ goto fail;
+ }
+ priv->elements[n].tag = tag;
+
+ data = (unsigned char *) isc_mem_get(mctx, MAXFIELDSIZE);
+ if (data == NULL)
+ goto fail;
+
+ isc_buffer_init(&b, data, MAXFIELDSIZE);
+ 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;
+
+ 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);
+
+ return (ret);
+}
+
+int
+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;
+ char filename[ISC_DIR_NAMEMAX];
+ char buffer[MAXFIELDSIZE * 2];
+ isc_buffer_t b;
+ isc_fsaccess_t access;
+
+ REQUIRE(priv != NULL);
+
+ if (check_data(priv, dst_key_alg(key), ISC_FALSE) < 0)
+ return (DST_R_INVALIDPRIVATEKEY);
+
+ isc_buffer_init(&b, filename, sizeof(filename));
+ ret = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &b);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ if ((fp = fopen(filename, "w")) == NULL)
+ return (DST_R_WRITEERROR);
+
+ access = 0;
+ isc_fsaccess_add(ISC_FSACCESS_OWNER,
+ ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
+ &access);
+ (void)isc_fsaccess_set(filename, access);
+
+ /* 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 %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:
+ fprintf(fp, "(RSA)\n");
+ break;
+ case DST_ALG_DH:
+ fprintf(fp, "(DH)\n");
+ break;
+ case DST_ALG_DSA:
+ fprintf(fp, "(DSA)\n");
+ break;
+ case DST_ALG_RSASHA1:
+ fprintf(fp, "(RSASHA1)\n");
+ break;
+ case DST_ALG_HMACMD5:
+ fprintf(fp, "(HMAC_MD5)\n");
+ break;
+ case DST_ALG_HMACSHA1:
+ fprintf(fp, "(HMAC_SHA1)\n");
+ break;
+ case DST_ALG_HMACSHA224:
+ fprintf(fp, "(HMAC_SHA224)\n");
+ break;
+ case DST_ALG_HMACSHA256:
+ fprintf(fp, "(HMAC_SHA256)\n");
+ break;
+ case DST_ALG_HMACSHA384:
+ fprintf(fp, "(HMAC_SHA384)\n");
+ break;
+ case DST_ALG_HMACSHA512:
+ fprintf(fp, "(HMAC_SHA512)\n");
+ break;
+ default:
+ fprintf(fp, "(?)\n");
+ break;
+ }
+
+ 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);
+
+ 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) {
+ fclose(fp);
+ return (DST_R_INVALIDPRIVATEKEY);
+ }
+ isc_buffer_usedregion(&b, &r);
+
+ fprintf(fp, "%s ", s);
+ fwrite(r.base, 1, r.length, fp);
+ fprintf(fp, "\n");
+ }
+
+ fclose(fp);
+ return (ISC_R_SUCCESS);
+}
+
+/*! \file */
diff --git a/lib/dns/dst_parse.h b/lib/dns/dst_parse.h
new file mode 100644
index 0000000..27c7580
--- /dev/null
+++ b/lib/dns/dst_parse.h
@@ -0,0 +1,134 @@
+/*
+ * Portions Copyright (C) 2004-2008 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
+ * 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 AND NETWORK ASSOCIATES 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.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 AND NETWORK ASSOCIATES 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: dst_parse.h,v 1.11 2008/05/15 00:50:26 each Exp $ */
+
+/*! \file */
+#ifndef DST_DST_PARSE_H
+#define DST_DST_PARSE_H 1
+
+#include <isc/lang.h>
+
+#include <dst/dst.h>
+
+#define MAJOR_VERSION 1
+#define MINOR_VERSION 2
+
+#define MAXFIELDSIZE 512
+#define MAXFIELDS 12
+
+#define TAG_SHIFT 4
+#define TAG_ALG(tag) ((unsigned int)(tag) >> TAG_SHIFT)
+#define TAG(alg, off) (((alg) << TAG_SHIFT) + (off))
+
+/* These are used by both RSA-MD5 and RSA-SHA1 */
+#define RSA_NTAGS 11
+#define TAG_RSA_MODULUS ((DST_ALG_RSAMD5 << TAG_SHIFT) + 0)
+#define TAG_RSA_PUBLICEXPONENT ((DST_ALG_RSAMD5 << TAG_SHIFT) + 1)
+#define TAG_RSA_PRIVATEEXPONENT ((DST_ALG_RSAMD5 << TAG_SHIFT) + 2)
+#define TAG_RSA_PRIME1 ((DST_ALG_RSAMD5 << TAG_SHIFT) + 3)
+#define TAG_RSA_PRIME2 ((DST_ALG_RSAMD5 << TAG_SHIFT) + 4)
+#define TAG_RSA_EXPONENT1 ((DST_ALG_RSAMD5 << TAG_SHIFT) + 5)
+#define TAG_RSA_EXPONENT2 ((DST_ALG_RSAMD5 << TAG_SHIFT) + 6)
+#define TAG_RSA_COEFFICIENT ((DST_ALG_RSAMD5 << TAG_SHIFT) + 7)
+#define TAG_RSA_ENGINE ((DST_ALG_RSAMD5 << TAG_SHIFT) + 8)
+#define TAG_RSA_LABEL ((DST_ALG_RSAMD5 << TAG_SHIFT) + 9)
+#define TAG_RSA_PIN ((DST_ALG_RSAMD5 << TAG_SHIFT) + 10)
+
+#define DH_NTAGS 4
+#define TAG_DH_PRIME ((DST_ALG_DH << TAG_SHIFT) + 0)
+#define TAG_DH_GENERATOR ((DST_ALG_DH << TAG_SHIFT) + 1)
+#define TAG_DH_PRIVATE ((DST_ALG_DH << TAG_SHIFT) + 2)
+#define TAG_DH_PUBLIC ((DST_ALG_DH << TAG_SHIFT) + 3)
+
+#define DSA_NTAGS 5
+#define TAG_DSA_PRIME ((DST_ALG_DSA << TAG_SHIFT) + 0)
+#define TAG_DSA_SUBPRIME ((DST_ALG_DSA << TAG_SHIFT) + 1)
+#define TAG_DSA_BASE ((DST_ALG_DSA << TAG_SHIFT) + 2)
+#define TAG_DSA_PRIVATE ((DST_ALG_DSA << TAG_SHIFT) + 3)
+#define TAG_DSA_PUBLIC ((DST_ALG_DSA << TAG_SHIFT) + 4)
+
+#define OLD_HMACMD5_NTAGS 1
+#define HMACMD5_NTAGS 2
+#define TAG_HMACMD5_KEY ((DST_ALG_HMACMD5 << TAG_SHIFT) + 0)
+#define TAG_HMACMD5_BITS ((DST_ALG_HMACMD5 << TAG_SHIFT) + 1)
+
+#define HMACSHA1_NTAGS 2
+#define TAG_HMACSHA1_KEY ((DST_ALG_HMACSHA1 << TAG_SHIFT) + 0)
+#define TAG_HMACSHA1_BITS ((DST_ALG_HMACSHA1 << TAG_SHIFT) + 1)
+
+#define HMACSHA224_NTAGS 2
+#define TAG_HMACSHA224_KEY ((DST_ALG_HMACSHA224 << TAG_SHIFT) + 0)
+#define TAG_HMACSHA224_BITS ((DST_ALG_HMACSHA224 << TAG_SHIFT) + 1)
+
+#define HMACSHA256_NTAGS 2
+#define TAG_HMACSHA256_KEY ((DST_ALG_HMACSHA256 << TAG_SHIFT) + 0)
+#define TAG_HMACSHA256_BITS ((DST_ALG_HMACSHA256 << TAG_SHIFT) + 1)
+
+#define HMACSHA384_NTAGS 2
+#define TAG_HMACSHA384_KEY ((DST_ALG_HMACSHA384 << TAG_SHIFT) + 0)
+#define TAG_HMACSHA384_BITS ((DST_ALG_HMACSHA384 << TAG_SHIFT) + 1)
+
+#define HMACSHA512_NTAGS 2
+#define TAG_HMACSHA512_KEY ((DST_ALG_HMACSHA512 << TAG_SHIFT) + 0)
+#define TAG_HMACSHA512_BITS ((DST_ALG_HMACSHA512 << TAG_SHIFT) + 1)
+
+struct dst_private_element {
+ unsigned short tag;
+ unsigned short length;
+ unsigned char *data;
+};
+
+typedef struct dst_private_element dst_private_element_t;
+
+struct dst_private {
+ unsigned short nelements;
+ dst_private_element_t elements[MAXFIELDS];
+};
+
+typedef struct dst_private dst_private_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+dst__privstruct_free(dst_private_t *priv, isc_mem_t *mctx);
+
+int
+dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
+ isc_mem_t *mctx, dst_private_t *priv);
+
+int
+dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
+ const char *directory);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DST_DST_PARSE_H */
diff --git a/lib/dns/dst_result.c b/lib/dns/dst_result.c
new file mode 100644
index 0000000..429dbb2
--- /dev/null
+++ b/lib/dns/dst_result.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+/*%
+ * Principal Author: Brian Wellington
+ * $Id: dst_result.c,v 1.7 2008/04/01 23:47:10 tbox Exp $
+ */
+
+#include <config.h>
+
+#include <isc/once.h>
+#include <isc/util.h>
+
+#include <dst/result.h>
+#include <dst/lib.h>
+
+static const char *text[DST_R_NRESULTS] = {
+ "algorithm is unsupported", /*%< 0 */
+ "openssl failure", /*%< 1 */
+ "built with no crypto support", /*%< 2 */
+ "illegal operation for a null key", /*%< 3 */
+ "public key is invalid", /*%< 4 */
+ "private key is invalid", /*%< 5 */
+ "UNUSED6", /*%< 6 */
+ "error occurred writing key to disk", /*%< 7 */
+ "invalid algorithm specific parameter", /*%< 8 */
+ "UNUSED9", /*%< 9 */
+ "UNUSED10", /*%< 10 */
+ "sign failure", /*%< 11 */
+ "UNUSED12", /*%< 12 */
+ "UNUSED13", /*%< 13 */
+ "verify failure", /*%< 14 */
+ "not a public key", /*%< 15 */
+ "not a private key", /*%< 16 */
+ "not a key that can compute a secret", /*%< 17 */
+ "failure computing a shared secret", /*%< 18 */
+ "no randomness available", /*%< 19 */
+ "bad key type", /*%< 20 */
+ "no engine" /*%< 21 */
+};
+
+#define DST_RESULT_RESULTSET 2
+
+static isc_once_t once = ISC_ONCE_INIT;
+
+static void
+initialize_action(void) {
+ isc_result_t result;
+
+ result = isc_result_register(ISC_RESULTCLASS_DST, DST_R_NRESULTS,
+ text, dst_msgcat, DST_RESULT_RESULTSET);
+ if (result != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_result_register() failed: %u", result);
+}
+
+static void
+initialize(void) {
+ dst_lib_initmsgcat();
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+}
+
+const char *
+dst_result_totext(isc_result_t result) {
+ initialize();
+
+ return (isc_result_totext(result));
+}
+
+void
+dst_result_register(void) {
+ initialize();
+}
+
+/*! \file */
diff --git a/lib/dns/forward.c b/lib/dns/forward.c
new file mode 100644
index 0000000..39e2ef5
--- /dev/null
+++ b/lib/dns/forward.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: forward.c,v 1.12 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/rwlock.h>
+#include <isc/sockaddr.h>
+#include <isc/util.h>
+
+#include <dns/forward.h>
+#include <dns/rbt.h>
+#include <dns/result.h>
+#include <dns/types.h>
+
+struct dns_fwdtable {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_rwlock_t rwlock;
+ /* Locked by lock. */
+ dns_rbt_t *table;
+};
+
+#define FWDTABLEMAGIC ISC_MAGIC('F', 'w', 'd', 'T')
+#define VALID_FWDTABLE(ft) ISC_MAGIC_VALID(ft, FWDTABLEMAGIC)
+
+static void
+auto_detach(void *, void *);
+
+isc_result_t
+dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep) {
+ dns_fwdtable_t *fwdtable;
+ isc_result_t result;
+
+ REQUIRE(fwdtablep != NULL && *fwdtablep == NULL);
+
+ fwdtable = isc_mem_get(mctx, sizeof(dns_fwdtable_t));
+ if (fwdtable == NULL)
+ return (ISC_R_NOMEMORY);
+
+ fwdtable->table = NULL;
+ result = dns_rbt_create(mctx, auto_detach, fwdtable, &fwdtable->table);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_fwdtable;
+
+ result = isc_rwlock_init(&fwdtable->rwlock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_rbt;
+
+ fwdtable->mctx = NULL;
+ isc_mem_attach(mctx, &fwdtable->mctx);
+ fwdtable->magic = FWDTABLEMAGIC;
+ *fwdtablep = fwdtable;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_rbt:
+ dns_rbt_destroy(&fwdtable->table);
+
+ cleanup_fwdtable:
+ isc_mem_put(mctx, fwdtable, sizeof(dns_fwdtable_t));
+
+ return (result);
+}
+
+isc_result_t
+dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
+ isc_sockaddrlist_t *addrs, dns_fwdpolicy_t fwdpolicy)
+{
+ isc_result_t result;
+ dns_forwarders_t *forwarders;
+ isc_sockaddr_t *sa, *nsa;
+
+ REQUIRE(VALID_FWDTABLE(fwdtable));
+
+ forwarders = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarders_t));
+ if (forwarders == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ISC_LIST_INIT(forwarders->addrs);
+ for (sa = ISC_LIST_HEAD(*addrs);
+ sa != NULL;
+ sa = ISC_LIST_NEXT(sa, link))
+ {
+ nsa = isc_mem_get(fwdtable->mctx, sizeof(isc_sockaddr_t));
+ if (nsa == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ *nsa = *sa;
+ ISC_LINK_INIT(nsa, link);
+ ISC_LIST_APPEND(forwarders->addrs, nsa, link);
+ }
+ forwarders->fwdpolicy = fwdpolicy;
+
+ RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
+ result = dns_rbt_addname(fwdtable->table, name, forwarders);
+ RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write);
+
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ while (!ISC_LIST_EMPTY(forwarders->addrs)) {
+ sa = ISC_LIST_HEAD(forwarders->addrs);
+ ISC_LIST_UNLINK(forwarders->addrs, sa, link);
+ isc_mem_put(fwdtable->mctx, sa, sizeof(isc_sockaddr_t));
+ }
+ isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
+ 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,
+ dns_name_t *foundname, dns_forwarders_t **forwardersp)
+{
+ isc_result_t result;
+
+ REQUIRE(VALID_FWDTABLE(fwdtable));
+
+ RWLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
+
+ result = dns_rbt_findname(fwdtable->table, name, 0, foundname,
+ (void **)forwardersp);
+ if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_SUCCESS;
+
+ RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_read);
+
+ return (result);
+}
+
+void
+dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep) {
+ dns_fwdtable_t *fwdtable;
+ isc_mem_t *mctx;
+
+ REQUIRE(fwdtablep != NULL && VALID_FWDTABLE(*fwdtablep));
+
+ fwdtable = *fwdtablep;
+
+ dns_rbt_destroy(&fwdtable->table);
+ isc_rwlock_destroy(&fwdtable->rwlock);
+ fwdtable->magic = 0;
+ mctx = fwdtable->mctx;
+ isc_mem_put(mctx, fwdtable, sizeof(dns_fwdtable_t));
+ isc_mem_detach(&mctx);
+
+ *fwdtablep = NULL;
+}
+
+/***
+ *** Private
+ ***/
+
+static void
+auto_detach(void *data, void *arg) {
+ dns_forwarders_t *forwarders = data;
+ dns_fwdtable_t *fwdtable = arg;
+ isc_sockaddr_t *sa;
+
+ UNUSED(arg);
+
+ while (!ISC_LIST_EMPTY(forwarders->addrs)) {
+ sa = ISC_LIST_HEAD(forwarders->addrs);
+ ISC_LIST_UNLINK(forwarders->addrs, sa, link);
+ isc_mem_put(fwdtable->mctx, sa, sizeof(isc_sockaddr_t));
+ }
+ isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t));
+}
diff --git a/lib/dns/gen-unix.h b/lib/dns/gen-unix.h
new file mode 100644
index 0000000..3db6206
--- /dev/null
+++ b/lib/dns/gen-unix.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: gen-unix.h,v 1.19 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * This file is responsible for defining two operations that are not
+ * directly portable between Unix-like systems and Windows NT, option
+ * parsing and directory scanning. It is here because it was decided
+ * that the "gen" build utility was not to depend on libisc.a, so
+ * the functions delcared in isc/commandline.h and isc/dir.h could not
+ * be used.
+ *
+ * The commandline stuff is really just a wrapper around getopt().
+ * The dir stuff was shrunk to fit the needs of gen.c.
+ */
+
+#ifndef DNS_GEN_UNIX_H
+#define DNS_GEN_UNIX_H 1
+
+#include <sys/types.h> /* Required on some systems for dirent.h. */
+
+#include <dirent.h>
+#include <unistd.h> /* XXXDCL Required for ?. */
+
+#include <isc/boolean.h>
+#include <isc/lang.h>
+
+#ifdef NEED_OPTARG
+extern char *optarg;
+#endif
+
+#define isc_commandline_parse getopt
+#define isc_commandline_argument optarg
+
+typedef struct {
+ DIR *handle;
+ char *filename;
+} isc_dir_t;
+
+ISC_LANG_BEGINDECLS
+
+static isc_boolean_t
+start_directory(const char *path, isc_dir_t *dir) {
+ dir->handle = opendir(path);
+
+ if (dir->handle != NULL)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+
+}
+
+static isc_boolean_t
+next_file(isc_dir_t *dir) {
+ struct dirent *dirent;
+
+ dir->filename = NULL;
+
+ if (dir->handle != NULL) {
+ dirent = readdir(dir->handle);
+ if (dirent != NULL)
+ dir->filename = dirent->d_name;
+ }
+
+ if (dir->filename != NULL)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+static void
+end_directory(isc_dir_t *dir) {
+ if (dir->handle != NULL)
+ (void)closedir(dir->handle);
+
+ dir->handle = NULL;
+}
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_GEN_UNIX_H */
diff --git a/lib/dns/gen-win32.h b/lib/dns/gen-win32.h
new file mode 100644
index 0000000..4b21a31
--- /dev/null
+++ b/lib/dns/gen-win32.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: gen-win32.h,v 1.23 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file
+ * \author Principal Authors: Computer Systems Research Group at UC Berkeley
+ * \author Principal ISC caretaker: DCL
+ */
+
+/*
+ * \note This file was adapted from the NetBSD project's source tree, RCS ID:
+ * NetBSD: getopt.c,v 1.15 1999/09/20 04:39:37 lukem Exp
+ *
+ * The primary change has been to rename items to the ISC namespace
+ * and format in the ISC coding style.
+ *
+ * This file is responsible for defining two operations that are not
+ * directly portable between Unix-like systems and Windows NT, option
+ * parsing and directory scanning. It is here because it was decided
+ * that the "gen" build utility was not to depend on libisc.a, so
+ * the functions delcared in isc/commandline.h and isc/dir.h could not
+ * be used.
+ *
+ * The commandline stuff is pretty much a straight copy from the initial
+ * isc/commandline.c. The dir stuff was shrunk to fit the needs of gen.c.
+ */
+
+#ifndef DNS_GEN_WIN32_H
+#define DNS_GEN_WIN32_H 1
+
+#include <stdio.h>
+#include <string.h>
+#include <windows.h>
+
+#include <isc/boolean.h>
+#include <isc/lang.h>
+
+int isc_commandline_index = 1; /* Index into parent argv vector. */
+int isc_commandline_option; /* Character checked for validity. */
+
+char *isc_commandline_argument; /* Argument associated with option. */
+char *isc_commandline_progname; /* For printing error messages. */
+
+isc_boolean_t isc_commandline_errprint = ISC_TRUE; /* Print error messages. */
+isc_boolean_t isc_commandline_reset = ISC_TRUE; /* Reset processing. */
+
+#define BADOPT '?'
+#define BADARG ':'
+#define ENDOPT ""
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int
+isc_commandline_parse(int argc, char * const *argv, const char *options) {
+ static char *place = ENDOPT;
+ char *option; /* Index into *options of option. */
+
+ /*
+ * Update scanning pointer, either because a reset was requested or
+ * the previous argv was finished.
+ */
+ if (isc_commandline_reset || *place == '\0') {
+ isc_commandline_reset = ISC_FALSE;
+
+ if (isc_commandline_progname == NULL)
+ isc_commandline_progname = argv[0];
+
+ if (isc_commandline_index >= argc ||
+ *(place = argv[isc_commandline_index]) != '-') {
+ /*
+ * Index out of range or points to non-option.
+ */
+ place = ENDOPT;
+ return (-1);
+ }
+
+ if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+ /*
+ * Found '--' to signal end of options. Advance
+ * index to next argv, the first non-option.
+ */
+ isc_commandline_index++;
+ place = ENDOPT;
+ return (-1);
+ }
+ }
+
+ isc_commandline_option = *place++;
+ option = strchr(options, isc_commandline_option);
+
+ /*
+ * Ensure valid option has been passed as specified by options string.
+ * '-:' is never a valid command line option because it could not
+ * distinguish ':' from the argument specifier in the options string.
+ */
+ if (isc_commandline_option == ':' || option == NULL) {
+ if (*place == '\0')
+ isc_commandline_index++;
+
+ if (isc_commandline_errprint && *options != ':')
+ fprintf(stderr, "%s: illegal option -- %c\n",
+ isc_commandline_progname,
+ isc_commandline_option);
+
+ return (BADOPT);
+ }
+
+ if (*++option != ':') {
+ /*
+ * Option does not take an argument.
+ */
+ isc_commandline_argument = NULL;
+
+ /*
+ * Skip to next argv if at the end of the current argv.
+ */
+ if (*place == '\0')
+ ++isc_commandline_index;
+
+ } else {
+ /*
+ * Option needs an argument.
+ */
+ if (*place != '\0')
+ /*
+ * Option is in this argv, -D1 style.
+ */
+ isc_commandline_argument = place;
+
+ else if (argc > ++isc_commandline_index)
+ /*
+ * Option is next argv, -D 1 style.
+ */
+ isc_commandline_argument = argv[isc_commandline_index];
+
+ else {
+ /*
+ * Argument needed, but no more argv.
+ */
+ place = ENDOPT;
+
+ /*
+ * Silent failure with "missing argument" return
+ * when ':' starts options string, per historical spec.
+ */
+ if (*options == ':')
+ return (BADARG);
+
+ if (isc_commandline_errprint)
+ fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ isc_commandline_progname,
+ isc_commandline_option);
+
+ return (BADOPT);
+ }
+
+ place = ENDOPT;
+
+ /*
+ * Point to argv that follows argument.
+ */
+ isc_commandline_index++;
+ }
+
+ return (isc_commandline_option);
+}
+
+typedef struct {
+ HANDLE handle;
+ WIN32_FIND_DATA find_data;
+ isc_boolean_t first_file;
+ char *filename;
+} isc_dir_t;
+
+isc_boolean_t
+start_directory(const char *path, isc_dir_t *dir) {
+ char pattern[_MAX_PATH], *p;
+
+ /*
+ * Need space for slash-splat and final NUL.
+ */
+ if (strlen(path) + 3 > sizeof(pattern))
+ return (ISC_FALSE);
+
+ strcpy(pattern, path);
+
+ /*
+ * Append slash (if needed) and splat.
+ */
+ p = pattern + strlen(pattern);
+ if (p != pattern && p[-1] != '\\' && p[-1] != ':')
+ *p++ = '\\';
+ *p++ = '*';
+ *p++ = '\0';
+
+ dir->first_file = ISC_TRUE;
+
+ dir->handle = FindFirstFile(pattern, &dir->find_data);
+
+ if (dir->handle == INVALID_HANDLE_VALUE) {
+ dir->filename = NULL;
+ return (ISC_FALSE);
+ } else {
+ dir->filename = dir->find_data.cFileName;
+ return (ISC_TRUE);
+ }
+}
+
+isc_boolean_t
+next_file(isc_dir_t *dir) {
+ if (dir->first_file)
+ dir->first_file = ISC_FALSE;
+
+ else if (dir->handle != INVALID_HANDLE_VALUE) {
+ if (FindNextFile(dir->handle, &dir->find_data) == TRUE)
+ dir->filename = dir->find_data.cFileName;
+ else
+ dir->filename = NULL;
+
+ } else
+ dir->filename = NULL;
+
+ if (dir->filename != NULL)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+void
+end_directory(isc_dir_t *dir) {
+ if (dir->handle != INVALID_HANDLE_VALUE)
+ FindClose(dir->handle);
+}
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_GEN_WIN32_H */
diff --git a/lib/dns/gen.c b/lib/dns/gen.c
new file mode 100644
index 0000000..ede8bc0
--- /dev/null
+++ b/lib/dns/gen.c
@@ -0,0 +1,888 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: gen.c,v 1.83 2008/09/25 04:02:38 tbox Exp $ */
+
+/*! \file */
+
+#ifdef WIN32
+/*
+ * Silence compiler warnings about using strcpy and friends.
+ */
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#ifdef WIN32
+#include "gen-win32.h"
+#else
+#include "gen-unix.h"
+#endif
+
+#define TYPECLASSLEN 21
+
+#define FROMTEXTARGS "rdclass, type, lexer, origin, options, target, callbacks"
+#define FROMTEXTCLASS "rdclass"
+#define FROMTEXTTYPE "type"
+#define FROMTEXTDEF "result = DNS_R_UNKNOWN"
+
+#define TOTEXTARGS "rdata, tctx, target"
+#define TOTEXTCLASS "rdata->rdclass"
+#define TOTEXTTYPE "rdata->type"
+#define TOTEXTDEF "use_default = ISC_TRUE"
+
+#define FROMWIREARGS "rdclass, type, source, dctx, options, target"
+#define FROMWIRECLASS "rdclass"
+#define FROMWIRETYPE "type"
+#define FROMWIREDEF "use_default = ISC_TRUE"
+
+#define TOWIREARGS "rdata, cctx, target"
+#define TOWIRECLASS "rdata->rdclass"
+#define TOWIRETYPE "rdata->type"
+#define TOWIREDEF "use_default = ISC_TRUE"
+
+#define FROMSTRUCTARGS "rdclass, type, source, target"
+#define FROMSTRUCTCLASS "rdclass"
+#define FROMSTRUCTTYPE "type"
+#define FROMSTRUCTDEF "use_default = ISC_TRUE"
+
+#define TOSTRUCTARGS "rdata, target, mctx"
+#define TOSTRUCTCLASS "rdata->rdclass"
+#define TOSTRUCTTYPE "rdata->type"
+#define TOSTRUCTDEF "use_default = ISC_TRUE"
+
+#define FREESTRUCTARGS "source"
+#define FREESTRUCTCLASS "common->rdclass"
+#define FREESTRUCTTYPE "common->rdtype"
+#define FREESTRUCTDEF NULL
+
+#define COMPAREARGS "rdata1, rdata2"
+#define COMPARECLASS "rdata1->rdclass"
+#define COMPARETYPE "rdata1->type"
+#define COMPAREDEF "use_default = ISC_TRUE"
+
+#define ADDITIONALDATAARGS "rdata, add, arg"
+#define ADDITIONALDATACLASS "rdata->rdclass"
+#define ADDITIONALDATATYPE "rdata->type"
+#define ADDITIONALDATADEF "use_default = ISC_TRUE"
+
+#define DIGESTARGS "rdata, digest, arg"
+#define DIGESTCLASS "rdata->rdclass"
+#define DIGESTTYPE "rdata->type"
+#define DIGESTDEF "use_default = ISC_TRUE"
+
+#define CHECKOWNERARGS "name, rdclass, type, wildcard"
+#define CHECKOWNERCLASS "rdclass"
+#define CHECKOWNERTYPE "type"
+#define CHECKOWNERDEF "result = ISC_TRUE"
+
+#define CHECKNAMESARGS "rdata, owner, bad"
+#define CHECKNAMESCLASS "rdata->rdclass"
+#define CHECKNAMESTYPE "rdata->type"
+#define CHECKNAMESDEF "result = ISC_TRUE"
+
+const char copyright[] =
+"/*\n"
+" * Copyright (C) 2004%s Internet Systems Consortium, Inc. (\"ISC\")\n"
+" * Copyright (C) 1998-2003 Internet Software Consortium.\n"
+" *\n"
+" * Permission to use, copy, modify, and distribute this software for any\n"
+" * purpose with or without fee is hereby granted, provided that the above\n"
+" * copyright notice and this permission notice appear in all copies.\n"
+" *\n"
+" * THE SOFTWARE IS PROVIDED \"AS IS\" AND ISC DISCLAIMS ALL WARRANTIES WITH\n"
+" * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\n"
+" * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,\n"
+" * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\n"
+" * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE\n"
+" * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n"
+" * PERFORMANCE OF THIS SOFTWARE.\n"
+" */\n"
+"\n"
+"/***************\n"
+" ***************\n"
+" *************** THIS FILE IS AUTOMATICALLY GENERATED BY gen.c.\n"
+" *************** DO NOT EDIT!\n"
+" ***************\n"
+" ***************/\n"
+"\n"
+"/*! \\file */\n"
+"\n";
+
+#define TYPENAMES 256
+
+struct cc {
+ struct cc *next;
+ int rdclass;
+ char classname[TYPECLASSLEN];
+} *classes;
+
+struct tt {
+ struct tt *next;
+ int rdclass;
+ int type;
+ char classname[TYPECLASSLEN];
+ char typename[TYPECLASSLEN];
+ char dirname[256]; /* XXX Should be max path length */
+} *types;
+
+struct ttnam {
+ char typename[TYPECLASSLEN];
+ char macroname[TYPECLASSLEN];
+ char attr[256];
+ unsigned int sorted;
+ int type;
+} typenames[TYPENAMES];
+
+int maxtype = -1;
+
+char *
+upper(char *);
+char *
+funname(const char *, char *);
+void
+doswitch(const char *, const char *, const char *, const char *,
+ const char *, const char *);
+void
+dodecl(char *, char *, char *);
+void
+add(int, const char *, int, const char *, const char *);
+void
+sd(int, const char *, const char *, char);
+void
+insert_into_typenames(int, const char *, const char *);
+
+/*%
+ * If you use more than 10 of these in, say, a printf(), you'll have problems.
+ */
+char *
+upper(char *s) {
+ static int buf_to_use = 0;
+ static char buf[10][256];
+ char *b;
+ int c;
+
+ buf_to_use++;
+ if (buf_to_use > 9)
+ buf_to_use = 0;
+
+ b = buf[buf_to_use];
+ memset(b, 0, 256);
+
+ while ((c = (*s++) & 0xff))
+ *b++ = islower(c) ? toupper(c) : c;
+ *b = '\0';
+ return (buf[buf_to_use]);
+}
+
+char *
+funname(const char *s, char *buf) {
+ char *b = buf;
+ char c;
+
+ while ((c = *s++)) {
+ *b++ = (c == '-') ? '_' : c;
+ }
+ *b = '\0';
+ return (buf);
+}
+
+void
+doswitch(const char *name, const char *function, const char *args,
+ const char *tsw, const char *csw, const char *res)
+{
+ struct tt *tt;
+ int first = 1;
+ int lasttype = 0;
+ int subswitch = 0;
+ char buf1[TYPECLASSLEN], buf2[TYPECLASSLEN];
+ const char *result = " result =";
+
+ if (res == NULL)
+ result = "";
+
+ for (tt = types; tt != NULL; tt = tt->next) {
+ if (first) {
+ fprintf(stdout, "\n#define %s \\\n", name);
+ fprintf(stdout, "\tswitch (%s) { \\\n" /*}*/, tsw);
+ first = 0;
+ }
+ if (tt->type != lasttype && subswitch) {
+ if (res == NULL)
+ fprintf(stdout, "\t\tdefault: break; \\\n");
+ else
+ fprintf(stdout,
+ "\t\tdefault: %s; break; \\\n", res);
+ fputs(/*{*/ "\t\t} \\\n", stdout);
+ fputs("\t\tbreak; \\\n", stdout);
+ subswitch = 0;
+ }
+ if (tt->rdclass && tt->type != lasttype) {
+ fprintf(stdout, "\tcase %d: switch (%s) { \\\n" /*}*/,
+ tt->type, csw);
+ subswitch = 1;
+ }
+ if (tt->rdclass == 0)
+ fprintf(stdout,
+ "\tcase %d:%s %s_%s(%s); break;",
+ tt->type, result, function,
+ funname(tt->typename, buf1), args);
+ else
+ fprintf(stdout,
+ "\t\tcase %d:%s %s_%s_%s(%s); break;",
+ tt->rdclass, result, function,
+ funname(tt->classname, buf1),
+ funname(tt->typename, buf2), args);
+ fputs(" \\\n", stdout);
+ lasttype = tt->type;
+ }
+ if (subswitch) {
+ if (res == NULL)
+ fprintf(stdout, "\t\tdefault: break; \\\n");
+ else
+ fprintf(stdout, "\t\tdefault: %s; break; \\\n", res);
+ fputs(/*{*/ "\t\t} \\\n", stdout);
+ fputs("\t\tbreak; \\\n", stdout);
+ }
+ if (first) {
+ if (res == NULL)
+ fprintf(stdout, "\n#define %s\n", name);
+ else
+ fprintf(stdout, "\n#define %s %s;\n", name, res);
+ } else {
+ if (res == NULL)
+ fprintf(stdout, "\tdefault: break; \\\n");
+ else
+ fprintf(stdout, "\tdefault: %s; break; \\\n", res);
+ fputs(/*{*/ "\t}\n", stdout);
+ }
+}
+
+void
+dodecl(char *type, char *function, char *args) {
+ struct tt *tt;
+ char buf1[TYPECLASSLEN], buf2[TYPECLASSLEN];
+
+ fputs("\n", stdout);
+ for (tt = types; tt; tt = tt->next)
+ if (tt->rdclass)
+ fprintf(stdout,
+ "static inline %s %s_%s_%s(%s);\n",
+ type, function,
+ funname(tt->classname, buf1),
+ funname(tt->typename, buf2), args);
+ else
+ fprintf(stdout,
+ "static inline %s %s_%s(%s);\n",
+ type, function,
+ funname(tt->typename, buf1), args);
+}
+
+static struct ttnam *
+find_typename(int type) {
+ int i;
+
+ for (i = 0; i < TYPENAMES; i++) {
+ if (typenames[i].typename[0] != 0 &&
+ typenames[i].type == type)
+ return (&typenames[i]);
+ }
+ return (NULL);
+}
+
+void
+insert_into_typenames(int type, const char *typename, const char *attr) {
+ struct ttnam *ttn = NULL;
+ int c, i;
+ char tmp[256];
+
+ for (i = 0; i < TYPENAMES; i++) {
+ if (typenames[i].typename[0] != 0 &&
+ typenames[i].type == type &&
+ strcmp(typename, typenames[i].typename) != 0) {
+ fprintf(stderr,
+ "Error: type %d has two names: %s, %s\n",
+ type, typenames[i].typename, typename);
+ exit(1);
+ }
+ if (typenames[i].typename[0] == 0 && ttn == NULL)
+ ttn = &typenames[i];
+ }
+ if (ttn == NULL) {
+ fprintf(stderr, "Error: typenames array too small\n");
+ exit(1);
+ }
+
+ if (strlen(typename) > sizeof(ttn->typename) - 1) {
+ fprintf(stderr, "Error: type name %s is too long\n",
+ typename);
+ exit(1);
+ }
+ strcpy(ttn->typename, typename);
+ ttn->type = type;
+
+ strcpy(ttn->macroname, ttn->typename);
+ c = strlen(ttn->macroname);
+ while (c > 0) {
+ if (ttn->macroname[c - 1] == '-')
+ ttn->macroname[c - 1] = '_';
+ c--;
+ }
+
+ if (attr == NULL) {
+ sprintf(tmp, "RRTYPE_%s_ATTRIBUTES", upper(ttn->macroname));
+ attr = tmp;
+ }
+
+ if (ttn->attr[0] != 0 && strcmp(attr, ttn->attr) != 0) {
+ fprintf(stderr, "Error: type %d has different attributes: "
+ "%s, %s\n", type, ttn->attr, attr);
+ exit(1);
+ }
+
+ if (strlen(attr) > sizeof(ttn->attr) - 1) {
+ fprintf(stderr, "Error: attr (%s) [name %s] is too long\n",
+ attr, typename);
+ exit(1);
+ }
+ strcpy(ttn->attr, attr);
+ ttn->sorted = 0;
+ if (maxtype < type)
+ maxtype = type;
+}
+
+void
+add(int rdclass, const char *classname, int type, const char *typename,
+ const char *dirname)
+{
+ struct tt *newtt = (struct tt *)malloc(sizeof(*newtt));
+ struct tt *tt, *oldtt;
+ struct cc *newcc;
+ struct cc *cc, *oldcc;
+
+ insert_into_typenames(type, typename, NULL);
+
+ if (newtt == NULL) {
+ fprintf(stderr, "malloc() failed\n");
+ exit(1);
+ }
+
+ newtt->next = NULL;
+ newtt->rdclass = rdclass;
+ newtt->type = type;
+ strcpy(newtt->classname, classname);
+ strcpy(newtt->typename, typename);
+ if (strncmp(dirname, "./", 2) == 0)
+ dirname += 2;
+ strcpy(newtt->dirname, dirname);
+
+ tt = types;
+ oldtt = NULL;
+
+ while ((tt != NULL) && (tt->type < type)) {
+ oldtt = tt;
+ tt = tt->next;
+ }
+
+ while ((tt != NULL) && (tt->type == type) && (tt->rdclass < rdclass)) {
+ if (strcmp(tt->typename, typename) != 0)
+ exit(1);
+ oldtt = tt;
+ tt = tt->next;
+ }
+
+ if ((tt != NULL) && (tt->type == type) && (tt->rdclass == rdclass))
+ exit(1);
+
+ newtt->next = tt;
+ if (oldtt != NULL)
+ oldtt->next = newtt;
+ else
+ types = newtt;
+
+ /*
+ * Do a class switch for this type.
+ */
+ if (rdclass == 0)
+ return;
+
+ newcc = (struct cc *)malloc(sizeof(*newcc));
+ newcc->rdclass = rdclass;
+ strcpy(newcc->classname, classname);
+ cc = classes;
+ oldcc = NULL;
+
+ while ((cc != NULL) && (cc->rdclass < rdclass)) {
+ oldcc = cc;
+ cc = cc->next;
+ }
+
+ if ((cc != NULL) && cc->rdclass == rdclass) {
+ free((char *)newcc);
+ return;
+ }
+
+ newcc->next = cc;
+ if (oldcc != NULL)
+ oldcc->next = newcc;
+ else
+ classes = newcc;
+}
+
+void
+sd(int rdclass, const char *classname, const char *dirname, char filetype) {
+ char buf[sizeof("01234567890123456789_65535.h")];
+ char fmt[sizeof("%20[-0-9a-z]_%d.h")];
+ int type;
+ char typename[TYPECLASSLEN];
+ isc_dir_t dir;
+
+ if (!start_directory(dirname, &dir))
+ return;
+
+ sprintf(fmt,"%s%c", "%20[-0-9a-z]_%d.", filetype);
+ while (next_file(&dir)) {
+ if (sscanf(dir.filename, fmt, typename, &type) != 2)
+ continue;
+ if ((type > 65535) || (type < 0))
+ continue;
+
+ sprintf(buf, "%s_%d.%c", typename, type, filetype);
+ if (strcmp(buf, dir.filename) != 0)
+ continue;
+ add(rdclass, classname, type, typename, dirname);
+ }
+
+ end_directory(&dir);
+}
+
+static unsigned int
+HASH(char *string) {
+ unsigned int n;
+ unsigned char a, b;
+
+ n = strlen(string);
+ if (n == 0) {
+ fprintf(stderr, "n == 0?\n");
+ exit(1);
+ }
+ a = tolower((unsigned char)string[0]);
+ b = tolower((unsigned char)string[n - 1]);
+
+ return ((a + n) * b) % 256;
+}
+
+int
+main(int argc, char **argv) {
+ char buf[256]; /* XXX Should be max path length */
+ char srcdir[256]; /* XXX Should be max path length */
+ int rdclass;
+ char classname[TYPECLASSLEN];
+ struct tt *tt;
+ struct cc *cc;
+ struct ttnam *ttn, *ttn2;
+ unsigned int hash;
+ struct tm *tm;
+ time_t now;
+ char year[11];
+ int lasttype;
+ int code = 1;
+ int class_enum = 0;
+ int type_enum = 0;
+ int structs = 0;
+ int depend = 0;
+ int c, i, j;
+ char buf1[TYPECLASSLEN];
+ char filetype = 'c';
+ FILE *fd;
+ char *prefix = NULL;
+ char *suffix = NULL;
+ char *file = NULL;
+ isc_dir_t dir;
+
+ for (i = 0; i < TYPENAMES; i++)
+ memset(&typenames[i], 0, sizeof(typenames[i]));
+
+ strcpy(srcdir, "");
+ while ((c = isc_commandline_parse(argc, argv, "cdits:F:P:S:")) != -1)
+ switch (c) {
+ case 'c':
+ code = 0;
+ depend = 0;
+ type_enum = 0;
+ class_enum = 1;
+ filetype = 'c';
+ structs = 0;
+ break;
+ case 'd':
+ code = 0;
+ depend = 1;
+ class_enum = 0;
+ type_enum = 0;
+ structs = 0;
+ filetype = 'h';
+ break;
+ case 't':
+ code = 0;
+ depend = 0;
+ class_enum = 0;
+ type_enum = 1;
+ filetype = 'c';
+ structs = 0;
+ break;
+ case 'i':
+ code = 0;
+ depend = 0;
+ class_enum = 0;
+ type_enum = 0;
+ structs = 1;
+ filetype = 'h';
+ break;
+ case 's':
+ sprintf(srcdir, "%s/", isc_commandline_argument);
+ break;
+ case 'F':
+ file = isc_commandline_argument;
+ break;
+ case 'P':
+ prefix = isc_commandline_argument;
+ break;
+ case 'S':
+ suffix = isc_commandline_argument;
+ break;
+ case '?':
+ exit(1);
+ }
+
+ sprintf(buf, "%srdata", srcdir);
+
+ if (!start_directory(buf, &dir))
+ exit(1);
+
+ while (next_file(&dir)) {
+ if (sscanf(dir.filename, "%10[0-9a-z]_%d",
+ classname, &rdclass) != 2)
+ continue;
+ if ((rdclass > 65535) || (rdclass < 0))
+ continue;
+
+ sprintf(buf, "%srdata/%s_%d", srcdir, classname, rdclass);
+ if (strcmp(buf + 6 + strlen(srcdir), dir.filename) != 0)
+ continue;
+ sd(rdclass, classname, buf, filetype);
+ }
+ end_directory(&dir);
+ sprintf(buf, "%srdata/generic", srcdir);
+ sd(0, "", buf, filetype);
+
+ if (time(&now) != -1) {
+ if ((tm = localtime(&now)) != NULL && tm->tm_year > 104)
+ sprintf(year, "-%d", tm->tm_year + 1900);
+ else
+ year[0] = 0;
+ } else
+ year[0] = 0;
+
+ if (!depend) fprintf(stdout, copyright, year);
+
+ if (code) {
+ fputs("#ifndef DNS_CODE_H\n", stdout);
+ fputs("#define DNS_CODE_H 1\n\n", stdout);
+
+ fputs("#include <isc/boolean.h>\n", stdout);
+ fputs("#include <isc/result.h>\n\n", stdout);
+ fputs("#include <dns/name.h>\n\n", stdout);
+
+ for (tt = types; tt != NULL; tt = tt->next)
+ fprintf(stdout, "#include \"%s/%s_%d.c\"\n",
+ tt->dirname, tt->typename, tt->type);
+
+ fputs("\n\n", stdout);
+
+ doswitch("FROMTEXTSWITCH", "fromtext", FROMTEXTARGS,
+ FROMTEXTTYPE, FROMTEXTCLASS, FROMTEXTDEF);
+ doswitch("TOTEXTSWITCH", "totext", TOTEXTARGS,
+ TOTEXTTYPE, TOTEXTCLASS, TOTEXTDEF);
+ doswitch("FROMWIRESWITCH", "fromwire", FROMWIREARGS,
+ FROMWIRETYPE, FROMWIRECLASS, FROMWIREDEF);
+ doswitch("TOWIRESWITCH", "towire", TOWIREARGS,
+ TOWIRETYPE, TOWIRECLASS, TOWIREDEF);
+ doswitch("COMPARESWITCH", "compare", COMPAREARGS,
+ COMPARETYPE, COMPARECLASS, COMPAREDEF);
+ doswitch("FROMSTRUCTSWITCH", "fromstruct", FROMSTRUCTARGS,
+ FROMSTRUCTTYPE, FROMSTRUCTCLASS, FROMSTRUCTDEF);
+ doswitch("TOSTRUCTSWITCH", "tostruct", TOSTRUCTARGS,
+ TOSTRUCTTYPE, TOSTRUCTCLASS, TOSTRUCTDEF);
+ doswitch("FREESTRUCTSWITCH", "freestruct", FREESTRUCTARGS,
+ FREESTRUCTTYPE, FREESTRUCTCLASS, FREESTRUCTDEF);
+ doswitch("ADDITIONALDATASWITCH", "additionaldata",
+ ADDITIONALDATAARGS, ADDITIONALDATATYPE,
+ ADDITIONALDATACLASS, ADDITIONALDATADEF);
+ doswitch("DIGESTSWITCH", "digest",
+ DIGESTARGS, DIGESTTYPE,
+ DIGESTCLASS, DIGESTDEF);
+ doswitch("CHECKOWNERSWITCH", "checkowner",
+ CHECKOWNERARGS, CHECKOWNERTYPE,
+ CHECKOWNERCLASS, CHECKOWNERDEF);
+ doswitch("CHECKNAMESSWITCH", "checknames",
+ CHECKNAMESARGS, CHECKNAMESTYPE,
+ CHECKNAMESCLASS, CHECKNAMESDEF);
+
+ /*
+ * From here down, we are processing the rdata names and
+ * attributes.
+ */
+
+#define PRINT_COMMA(x) (x == maxtype ? "" : ",")
+
+#define METANOTQUESTION "DNS_RDATATYPEATTR_META | " \
+ "DNS_RDATATYPEATTR_NOTQUESTION"
+#define METAQUESTIONONLY "DNS_RDATATYPEATTR_META | " \
+ "DNS_RDATATYPEATTR_QUESTIONONLY"
+#define RESERVED "DNS_RDATATYPEATTR_RESERVED"
+
+ /*
+ * Add in reserved/special types. This will let us
+ * sort them without special cases.
+ */
+ insert_into_typenames(0, "reserved0", RESERVED);
+ insert_into_typenames(31, "eid", RESERVED);
+ insert_into_typenames(32, "nimloc", RESERVED);
+ insert_into_typenames(34, "atma", RESERVED);
+ insert_into_typenames(100, "uinfo", RESERVED);
+ insert_into_typenames(101, "uid", RESERVED);
+ insert_into_typenames(102, "gid", RESERVED);
+ insert_into_typenames(251, "ixfr", METAQUESTIONONLY);
+ insert_into_typenames(252, "axfr", METAQUESTIONONLY);
+ insert_into_typenames(253, "mailb", METAQUESTIONONLY);
+ insert_into_typenames(254, "maila", METAQUESTIONONLY);
+ insert_into_typenames(255, "any", METAQUESTIONONLY);
+
+ /*
+ * Spit out a quick and dirty hash function. Here,
+ * we walk through the list of type names, and calculate
+ * a hash. This isn't perfect, but it will generate "pretty
+ * good" estimates. Lowercase the characters before
+ * computing in all cases.
+ *
+ * Here, walk the list from top to bottom, calculating
+ * the hash (mod 256) for each name.
+ */
+ fprintf(stdout, "#define RDATATYPE_COMPARE(_s, _d, _tn, _n, _tp) \\\n");
+ fprintf(stdout, "\tdo { \\\n");
+ fprintf(stdout, "\t\tif (sizeof(_s) - 1 == _n && \\\n"
+ "\t\t strncasecmp(_s,(_tn),"
+ "(sizeof(_s) - 1)) == 0) { \\\n");
+ fprintf(stdout, "\t\t\tif ((dns_rdatatype_attributes(_d) & "
+ "DNS_RDATATYPEATTR_RESERVED) != 0) \\\n");
+ fprintf(stdout, "\t\t\t\treturn (ISC_R_NOTIMPLEMENTED); \\\n");
+ fprintf(stdout, "\t\t\t*(_tp) = _d; \\\n");
+ fprintf(stdout, "\t\t\treturn (ISC_R_SUCCESS); \\\n");
+ fprintf(stdout, "\t\t} \\\n");
+ fprintf(stdout, "\t} while (0)\n\n");
+
+ fprintf(stdout, "#define RDATATYPE_FROMTEXT_SW(_hash,"
+ "_typename,_length,_typep) \\\n");
+ fprintf(stdout, "\tswitch (_hash) { \\\n");
+ for (i = 0; i <= maxtype; i++) {
+ ttn = find_typename(i);
+ if (ttn == NULL)
+ continue;
+
+ /*
+ * Skip entries we already processed.
+ */
+ if (ttn->sorted != 0)
+ continue;
+
+ hash = HASH(ttn->typename);
+ fprintf(stdout, "\t\tcase %u: \\\n", hash);
+
+ /*
+ * Find all other entries that happen to match
+ * this hash.
+ */
+ for (j = 0; j <= maxtype; j++) {
+ ttn2 = find_typename(j);
+ if (ttn2 == NULL)
+ continue;
+ if (hash == HASH(ttn2->typename)) {
+ fprintf(stdout, "\t\t\tRDATATYPE_COMPARE"
+ "(\"%s\", %u, "
+ "_typename, _length, _typep); \\\n",
+ ttn2->typename, ttn2->type);
+ ttn2->sorted = 1;
+ }
+ }
+ fprintf(stdout, "\t\t\tbreak; \\\n");
+ }
+ fprintf(stdout, "\t}\n");
+
+ fprintf(stdout, "#define RDATATYPE_ATTRIBUTE_SW \\\n");
+ fprintf(stdout, "\tswitch (type) { \\\n");
+ for (i = 0; i <= maxtype; i++) {
+ ttn = find_typename(i);
+ if (ttn == NULL)
+ continue;
+ fprintf(stdout, "\tcase %u: return (%s); \\\n",
+ i, upper(ttn->attr));
+ }
+ fprintf(stdout, "\t}\n");
+
+ fprintf(stdout, "#define RDATATYPE_TOTEXT_SW \\\n");
+ fprintf(stdout, "\tswitch (type) { \\\n");
+ for (i = 0; i <= maxtype; i++) {
+ ttn = find_typename(i);
+ if (ttn == NULL)
+ continue;
+ fprintf(stdout, "\tcase %u: return "
+ "(str_totext(\"%s\", target)); \\\n",
+ i, upper(ttn->typename));
+ }
+ fprintf(stdout, "\t}\n");
+
+ fputs("#endif /* DNS_CODE_H */\n", stdout);
+ } else if (type_enum) {
+ char *s;
+
+ fprintf(stdout, "#ifndef DNS_ENUMTYPE_H\n");
+ fprintf(stdout, "#define DNS_ENUMTYPE_H 1\n\n");
+
+ fprintf(stdout, "enum {\n");
+ fprintf(stdout, "\tdns_rdatatype_none = 0,\n");
+
+ lasttype = 0;
+ for (tt = types; tt != NULL; tt = tt->next)
+ if (tt->type != lasttype)
+ fprintf(stdout,
+ "\tdns_rdatatype_%s = %d,\n",
+ funname(tt->typename, buf1),
+ lasttype = tt->type);
+
+ fprintf(stdout, "\tdns_rdatatype_ixfr = 251,\n");
+ fprintf(stdout, "\tdns_rdatatype_axfr = 252,\n");
+ fprintf(stdout, "\tdns_rdatatype_mailb = 253,\n");
+ fprintf(stdout, "\tdns_rdatatype_maila = 254,\n");
+ fprintf(stdout, "\tdns_rdatatype_any = 255\n");
+
+ fprintf(stdout, "};\n\n");
+
+ fprintf(stdout, "#define dns_rdatatype_none\t"
+ "((dns_rdatatype_t)dns_rdatatype_none)\n");
+
+ for (tt = types; tt != NULL; tt = tt->next)
+ if (tt->type != lasttype) {
+ s = funname(tt->typename, buf1);
+ fprintf(stdout,
+ "#define dns_rdatatype_%s\t%s"
+ "((dns_rdatatype_t)dns_rdatatype_%s)"
+ "\n",
+ s, strlen(s) < 2U ? "\t" : "", s);
+ lasttype = tt->type;
+ }
+
+ fprintf(stdout, "#define dns_rdatatype_ixfr\t"
+ "((dns_rdatatype_t)dns_rdatatype_ixfr)\n");
+ fprintf(stdout, "#define dns_rdatatype_axfr\t"
+ "((dns_rdatatype_t)dns_rdatatype_axfr)\n");
+ fprintf(stdout, "#define dns_rdatatype_mailb\t"
+ "((dns_rdatatype_t)dns_rdatatype_mailb)\n");
+ fprintf(stdout, "#define dns_rdatatype_maila\t"
+ "((dns_rdatatype_t)dns_rdatatype_maila)\n");
+ fprintf(stdout, "#define dns_rdatatype_any\t"
+ "((dns_rdatatype_t)dns_rdatatype_any)\n");
+
+ fprintf(stdout, "\n#endif /* DNS_ENUMTYPE_H */\n");
+
+ } else if (class_enum) {
+ char *s;
+ int classnum;
+
+ fprintf(stdout, "#ifndef DNS_ENUMCLASS_H\n");
+ fprintf(stdout, "#define DNS_ENUMCLASS_H 1\n\n");
+
+ fprintf(stdout, "enum {\n");
+
+ fprintf(stdout, "\tdns_rdataclass_reserved0 = 0,\n");
+ fprintf(stdout, "#define dns_rdataclass_reserved0 \\\n\t\t\t\t"
+ "((dns_rdataclass_t)dns_rdataclass_reserved0)\n");
+
+#define PRINTCLASS(name, num) \
+ do { \
+ s = funname(name, buf1); \
+ classnum = num; \
+ fprintf(stdout, "\tdns_rdataclass_%s = %d%s\n", s, classnum, \
+ classnum != 255 ? "," : ""); \
+ fprintf(stdout, "#define dns_rdataclass_%s\t" \
+ "((dns_rdataclass_t)dns_rdataclass_%s)\n", s, s); \
+ } while (0)
+
+ for (cc = classes; cc != NULL; cc = cc->next) {
+ if (cc->rdclass == 3)
+ PRINTCLASS("chaos", 3);
+ else if (cc->rdclass == 255)
+ PRINTCLASS("none", 254);
+ PRINTCLASS(cc->classname, cc->rdclass);
+ }
+
+#undef PRINTCLASS
+
+ fprintf(stdout, "};\n\n");
+ fprintf(stdout, "#endif /* DNS_ENUMCLASS_H */\n");
+ } else if (structs) {
+ if (prefix != NULL) {
+ if ((fd = fopen(prefix,"r")) != NULL) {
+ while (fgets(buf, sizeof(buf), fd) != NULL)
+ fputs(buf, stdout);
+ fclose(fd);
+ }
+ }
+ for (tt = types; tt != NULL; tt = tt->next) {
+ sprintf(buf, "%s/%s_%d.h",
+ tt->dirname, tt->typename, tt->type);
+ if ((fd = fopen(buf,"r")) != NULL) {
+ while (fgets(buf, sizeof(buf), fd) != NULL)
+ fputs(buf, stdout);
+ fclose(fd);
+ }
+ }
+ if (suffix != NULL) {
+ if ((fd = fopen(suffix,"r")) != NULL) {
+ while (fgets(buf, sizeof(buf), fd) != NULL)
+ fputs(buf, stdout);
+ fclose(fd);
+ }
+ }
+ } else if (depend) {
+ for (tt = types; tt != NULL; tt = tt->next)
+ fprintf(stdout, "%s:\t%s/%s_%d.h\n", file,
+ tt->dirname, tt->typename, tt->type);
+ }
+
+ if (ferror(stdout) != 0)
+ exit(1);
+
+ return (0);
+}
diff --git a/lib/dns/gssapi_link.c b/lib/dns/gssapi_link.c
new file mode 100644
index 0000000..0dd27bb
--- /dev/null
+++ b/lib/dns/gssapi_link.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: gssapi_link.c,v 1.12 2008/11/11 03:55:01 marka Exp $
+ */
+
+#include <config.h>
+
+#ifdef GSSAPI
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dst/result.h>
+
+#include "dst_internal.h"
+#include "dst_parse.h"
+
+#include <dst/gssapi.h>
+
+#define INITIAL_BUFFER_SIZE 1024
+#define BUFFER_EXTRA 1024
+
+#define REGION_TO_GBUFFER(r, gb) \
+ do { \
+ (gb).length = (r).length; \
+ (gb).value = (r).base; \
+ } while (0)
+
+
+struct dst_gssapi_signverifyctx {
+ isc_buffer_t *buffer;
+};
+
+/*%
+ * Allocate a temporary "context" for use in gathering data for signing
+ * or verifying.
+ */
+static isc_result_t
+gssapi_create_signverify_ctx(dst_key_t *key, dst_context_t *dctx) {
+ dst_gssapi_signverifyctx_t *ctx;
+ isc_result_t result;
+
+ UNUSED(key);
+
+ ctx = isc_mem_get(dctx->mctx, sizeof(dst_gssapi_signverifyctx_t));
+ if (ctx == NULL)
+ return (ISC_R_NOMEMORY);
+ ctx->buffer = NULL;
+ result = isc_buffer_allocate(dctx->mctx, &ctx->buffer,
+ INITIAL_BUFFER_SIZE);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
+ return (result);
+ }
+
+ dctx->ctxdata.gssctx = ctx;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Destroy the temporary sign/verify context.
+ */
+static void
+gssapi_destroy_signverify_ctx(dst_context_t *dctx) {
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
+
+ if (ctx != NULL) {
+ if (ctx->buffer != NULL)
+ isc_buffer_free(&ctx->buffer);
+ isc_mem_put(dctx->mctx, ctx, sizeof(dst_gssapi_signverifyctx_t));
+ dctx->ctxdata.gssctx = NULL;
+ }
+}
+
+/*%
+ * Add data to our running buffer of data we will be signing or verifying.
+ * This code will see if the new data will fit in our existing buffer, and
+ * copy it in if it will. If not, it will attempt to allocate a larger
+ * buffer and copy old+new into it, and free the old buffer.
+ */
+static isc_result_t
+gssapi_adddata(dst_context_t *dctx, const isc_region_t *data) {
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
+ isc_buffer_t *newbuffer = NULL;
+ isc_region_t r;
+ unsigned int length;
+ isc_result_t result;
+
+ result = isc_buffer_copyregion(ctx->buffer, data);
+ if (result == ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+
+ length = isc_buffer_length(ctx->buffer) + data->length + BUFFER_EXTRA;
+
+ result = isc_buffer_allocate(dctx->mctx, &newbuffer, length);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ isc_buffer_usedregion(ctx->buffer, &r);
+ (void)isc_buffer_copyregion(newbuffer, &r);
+ (void)isc_buffer_copyregion(newbuffer, data);
+
+ isc_buffer_free(&ctx->buffer);
+ ctx->buffer = newbuffer;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Sign.
+ */
+static isc_result_t
+gssapi_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
+ isc_region_t message;
+ gss_buffer_desc gmessage, gsig;
+ OM_uint32 minor, gret;
+ gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
+ char buf[1024];
+
+ /*
+ * Convert the data we wish to sign into a structure gssapi can
+ * understand.
+ */
+ isc_buffer_usedregion(ctx->buffer, &message);
+ REGION_TO_GBUFFER(message, gmessage);
+
+ /*
+ * Generate the signature.
+ */
+ gret = gss_get_mic(&minor, gssctx, GSS_C_QOP_DEFAULT, &gmessage,
+ &gsig);
+
+ /*
+ * If it did not complete, we log the result and return a generic
+ * failure code.
+ */
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "GSS sign error: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ return (ISC_R_FAILURE);
+ }
+
+ /*
+ * If it will not fit in our allocated buffer, return that we need
+ * more space.
+ */
+ if (gsig.length > isc_buffer_availablelength(sig)) {
+ gss_release_buffer(&minor, &gsig);
+ return (ISC_R_NOSPACE);
+ }
+
+ /*
+ * Copy the output into our buffer space, and release the gssapi
+ * allocated space.
+ */
+ isc_buffer_putmem(sig, gsig.value, gsig.length);
+ if (gsig.length != 0)
+ gss_release_buffer(&minor, &gsig);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Verify.
+ */
+static isc_result_t
+gssapi_verify(dst_context_t *dctx, const isc_region_t *sig) {
+ dst_gssapi_signverifyctx_t *ctx = dctx->ctxdata.gssctx;
+ isc_region_t message, r;
+ gss_buffer_desc gmessage, gsig;
+ OM_uint32 minor, gret;
+ gss_ctx_id_t gssctx = dctx->key->keydata.gssctx;
+ unsigned char *buf;
+ char err[1024];
+
+ /*
+ * Convert the data we wish to sign into a structure gssapi can
+ * understand.
+ */
+ isc_buffer_usedregion(ctx->buffer, &message);
+ REGION_TO_GBUFFER(message, gmessage);
+
+ /*
+ * XXXMLG
+ * It seem that gss_verify_mic() modifies the signature buffer,
+ * at least on Heimdal's implementation. Copy it here to an allocated
+ * buffer.
+ */
+ buf = isc_mem_allocate(dst__memory_pool, sig->length);
+ if (buf == NULL)
+ return (ISC_R_FAILURE);
+ memcpy(buf, sig->base, sig->length);
+ r.base = buf;
+ r.length = sig->length;
+ REGION_TO_GBUFFER(r, gsig);
+
+ /*
+ * Verify the data.
+ */
+ gret = gss_verify_mic(&minor, gssctx, &gmessage, &gsig, NULL);
+
+ isc_mem_free(dst__memory_pool, buf);
+
+ /*
+ * Convert return codes into something useful to us.
+ */
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "GSS verify error: %s",
+ gss_error_tostring(gret, minor, err, sizeof(err)));
+ if (gret == GSS_S_DEFECTIVE_TOKEN ||
+ gret == GSS_S_BAD_SIG ||
+ gret == GSS_S_DUPLICATE_TOKEN ||
+ gret == GSS_S_OLD_TOKEN ||
+ gret == GSS_S_UNSEQ_TOKEN ||
+ gret == GSS_S_GAP_TOKEN ||
+ gret == GSS_S_CONTEXT_EXPIRED ||
+ gret == GSS_S_NO_CONTEXT ||
+ gret == GSS_S_FAILURE)
+ return(DST_R_VERIFYFAILURE);
+ else
+ return (ISC_R_FAILURE);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+gssapi_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ gss_ctx_id_t gsskey1 = key1->keydata.gssctx;
+ gss_ctx_id_t gsskey2 = key2->keydata.gssctx;
+
+ /* No idea */
+ return (ISC_TF(gsskey1 == gsskey2));
+}
+
+static isc_result_t
+gssapi_generate(dst_key_t *key, int unused) {
+ UNUSED(key);
+ UNUSED(unused);
+
+ /* No idea */
+ return (ISC_R_FAILURE);
+}
+
+static isc_boolean_t
+gssapi_isprivate(const dst_key_t *key) {
+ UNUSED(key);
+ return (ISC_TRUE);
+}
+
+static void
+gssapi_destroy(dst_key_t *key) {
+ REQUIRE(key != NULL);
+ dst_gssapi_deletectx(key->mctx, &key->keydata.gssctx);
+ key->keydata.gssctx = NULL;
+}
+
+static dst_func_t gssapi_functions = {
+ gssapi_create_signverify_ctx,
+ gssapi_destroy_signverify_ctx,
+ gssapi_adddata,
+ gssapi_sign,
+ gssapi_verify,
+ NULL, /*%< computesecret */
+ gssapi_compare,
+ NULL, /*%< paramcompare */
+ gssapi_generate,
+ gssapi_isprivate,
+ gssapi_destroy,
+ NULL, /*%< todns */
+ NULL, /*%< fromdns */
+ NULL, /*%< tofile */
+ NULL, /*%< parse */
+ NULL, /*%< cleanup */
+ NULL /*%< fromlabel */
+};
+
+isc_result_t
+dst__gssapi_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+ if (*funcp == NULL)
+ *funcp = &gssapi_functions;
+ return (ISC_R_SUCCESS);
+}
+
+#else
+int gssapi_link_unneeded = 1;
+#endif
+
+/*! \file */
diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c
new file mode 100644
index 0000000..11eadb9
--- /dev/null
+++ b/lib/dns/gssapictx.c
@@ -0,0 +1,738 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: gssapictx.c,v 1.12 2008/04/03 06:09:04 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/types.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+
+#include <dst/gssapi.h>
+#include <dst/result.h>
+
+#include "dst_internal.h"
+
+/*
+ * If we're using our own SPNEGO implementation (see configure.in),
+ * pull it in now. Otherwise, we just use whatever GSSAPI supplies.
+ */
+#if defined(GSSAPI) && defined(USE_ISC_SPNEGO)
+#include "spnego.h"
+#define gss_accept_sec_context gss_accept_sec_context_spnego
+#define gss_init_sec_context gss_init_sec_context_spnego
+#endif
+
+/*
+ * Solaris8 apparently needs an explicit OID set, and Solaris10 needs
+ * one for anything but Kerberos. Supplying an explicit OID set
+ * doesn't appear to hurt anything in other implementations, so we
+ * always use one. If we're not using our own SPNEGO implementation,
+ * we include SPNEGO's OID.
+ */
+#if defined(GSSAPI)
+
+static unsigned char krb5_mech_oid_bytes[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02
+};
+
+#ifndef USE_ISC_SPNEGO
+static unsigned char spnego_mech_oid_bytes[] = {
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02
+};
+#endif
+
+static gss_OID_desc mech_oid_set_array[] = {
+ { sizeof(krb5_mech_oid_bytes), krb5_mech_oid_bytes },
+#ifndef USE_ISC_SPNEGO
+ { sizeof(spnego_mech_oid_bytes), spnego_mech_oid_bytes },
+#endif
+};
+
+static gss_OID_set_desc mech_oid_set = {
+ sizeof(mech_oid_set_array) / sizeof(*mech_oid_set_array),
+ mech_oid_set_array
+};
+
+#endif
+
+#define REGION_TO_GBUFFER(r, gb) \
+ do { \
+ (gb).length = (r).length; \
+ (gb).value = (r).base; \
+ } while (0)
+
+#define GBUFFER_TO_REGION(gb, r) \
+ do { \
+ (r).length = (gb).length; \
+ (r).base = (gb).value; \
+ } while (0)
+
+
+#define RETERR(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto out; \
+ } while (0)
+
+#ifdef GSSAPI
+static inline void
+name_to_gbuffer(dns_name_t *name, isc_buffer_t *buffer,
+ gss_buffer_desc *gbuffer)
+{
+ dns_name_t tname, *namep;
+ isc_region_t r;
+ isc_result_t result;
+
+ if (!dns_name_isabsolute(name))
+ namep = name;
+ else
+ {
+ unsigned int labels;
+ dns_name_init(&tname, NULL);
+ labels = dns_name_countlabels(name);
+ dns_name_getlabelsequence(name, 0, labels - 1, &tname);
+ namep = &tname;
+ }
+
+ result = dns_name_totext(namep, ISC_FALSE, buffer);
+ isc_buffer_putuint8(buffer, 0);
+ isc_buffer_usedregion(buffer, &r);
+ REGION_TO_GBUFFER(r, *gbuffer);
+}
+
+static void
+log_cred(const gss_cred_id_t cred) {
+ OM_uint32 gret, minor, lifetime;
+ gss_name_t gname;
+ gss_buffer_desc gbuffer;
+ gss_cred_usage_t usage;
+ const char *usage_text;
+ char buf[1024];
+
+ gret = gss_inquire_cred(&minor, cred, &gname, &lifetime, &usage, NULL);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_inquire_cred: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ return;
+ }
+
+ gret = gss_display_name(&minor, gname, &gbuffer, NULL);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_display_name: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ else {
+ switch (usage) {
+ case GSS_C_BOTH:
+ usage_text = "GSS_C_BOTH";
+ break;
+ case GSS_C_INITIATE:
+ usage_text = "GSS_C_INITIATE";
+ break;
+ case GSS_C_ACCEPT:
+ usage_text = "GSS_C_ACCEPT";
+ break;
+ default:
+ usage_text = "???";
+ }
+ gss_log(3, "gss cred: \"%s\", %s, %lu", (char *)gbuffer.value,
+ usage_text, (unsigned long)lifetime);
+ }
+
+ if (gret == GSS_S_COMPLETE) {
+ if (gbuffer.length != 0) {
+ gret = gss_release_buffer(&minor, &gbuffer);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_buffer: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+ }
+
+ gret = gss_release_name(&minor, &gname);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_name: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+}
+#endif
+
+isc_result_t
+dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
+ gss_cred_id_t *cred)
+{
+#ifdef GSSAPI
+ isc_buffer_t namebuf;
+ gss_name_t gname;
+ gss_buffer_desc gnamebuf;
+ unsigned char array[DNS_NAME_MAXTEXT + 1];
+ OM_uint32 gret, minor;
+ gss_OID_set mechs;
+ OM_uint32 lifetime;
+ gss_cred_usage_t usage;
+ char buf[1024];
+
+ REQUIRE(cred != NULL && *cred == NULL);
+
+ /*
+ * XXXSRA In theory we could use GSS_C_NT_HOSTBASED_SERVICE
+ * 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
+ * dependency due to DNS-based realm lookup in at least one
+ * GSSAPI implementation (Heimdal). Oh well.
+ */
+ if (name != NULL) {
+ isc_buffer_init(&namebuf, array, sizeof(array));
+ name_to_gbuffer(name, &namebuf, &gnamebuf);
+ gret = gss_import_name(&minor, &gnamebuf,
+ GSS_C_NO_OID, &gname);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_import_name: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ return (ISC_R_FAILURE);
+ }
+ } else
+ gname = NULL;
+
+ /* Get the credentials. */
+ if (gname != NULL)
+ gss_log(3, "acquiring credentials for %s",
+ (char *)gnamebuf.value);
+ else {
+ /* XXXDCL does this even make any sense? */
+ gss_log(3, "acquiring credentials for ?");
+ }
+
+ if (initiate)
+ usage = GSS_C_INITIATE;
+ else
+ usage = GSS_C_ACCEPT;
+
+ gret = gss_acquire_cred(&minor, gname, GSS_C_INDEFINITE,
+ &mech_oid_set,
+ usage, cred, &mechs, &lifetime);
+
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed to acquire %s credentials for %s: %s",
+ initiate ? "initiate" : "accept",
+ (char *)gnamebuf.value,
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ return (ISC_R_FAILURE);
+ }
+
+ gss_log(4, "acquired %s credentials for %s",
+ initiate ? "initiate" : "accept",
+ (char *)gnamebuf.value);
+
+ log_cred(*cred);
+
+ return (ISC_R_SUCCESS);
+#else
+ UNUSED(name);
+ UNUSED(initiate);
+ UNUSED(cred);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm)
+{
+#ifdef GSSAPI
+ char sbuf[DNS_NAME_FORMATSIZE];
+ char nbuf[DNS_NAME_FORMATSIZE];
+ char rbuf[DNS_NAME_FORMATSIZE];
+ char *sname;
+ char *rname;
+
+ /*
+ * It is far, far easier to write the names we are looking at into
+ * a string, and do string operations on them.
+ */
+ dns_name_format(signer, sbuf, sizeof(sbuf));
+ if (name != NULL)
+ dns_name_format(name, nbuf, sizeof(nbuf));
+ dns_name_format(realm, rbuf, sizeof(rbuf));
+
+ /*
+ * Find the realm portion. This is the part after the @. If it
+ * does not exist, we don't have something we like, so we fail our
+ * compare.
+ */
+ rname = strstr(sbuf, "\\@");
+ if (rname == NULL)
+ return (isc_boolean_false);
+ *rname = '\0';
+ rname += 2;
+
+ /*
+ * 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"
+ *
+ * This will work for
+ * host/example.com@EXAMPLE.COM
+ */
+ sname = strchr(sbuf, '/');
+ if (sname == NULL)
+ return (isc_boolean_false);
+ *sname = '\0';
+ sname++;
+ if (strcmp(sbuf, "host") != 0)
+ return (isc_boolean_false);
+
+ /*
+ * Now, we do a simple comparison between the name and the realm.
+ */
+ if (name != NULL) {
+ if ((strcasecmp(sname, nbuf) == 0)
+ && (strcmp(rname, rbuf) == 0))
+ return (isc_boolean_true);
+ } else {
+ if (strcmp(rname, rbuf) == 0)
+ return (isc_boolean_true);
+ }
+
+ return (isc_boolean_false);
+#else
+ UNUSED(signer);
+ UNUSED(name);
+ UNUSED(realm);
+ return (isc_boolean_false);
+#endif
+}
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm)
+{
+#ifdef GSSAPI
+ char sbuf[DNS_NAME_FORMATSIZE];
+ char nbuf[DNS_NAME_FORMATSIZE];
+ char rbuf[DNS_NAME_FORMATSIZE];
+ char *sname;
+ char *nname;
+ char *rname;
+
+ /*
+ * It is far, far easier to write the names we are looking at into
+ * a string, and do string operations on them.
+ */
+ dns_name_format(signer, sbuf, sizeof(sbuf));
+ if (name != NULL)
+ dns_name_format(name, nbuf, sizeof(nbuf));
+ dns_name_format(realm, rbuf, sizeof(rbuf));
+
+ /*
+ * Find the realm portion. This is the part after the @. If it
+ * does not exist, we don't have something we like, so we fail our
+ * compare.
+ */
+ rname = strstr(sbuf, "\\@");
+ if (rname == NULL)
+ return (isc_boolean_false);
+ sname = strstr(sbuf, "\\$");
+ if (sname == NULL)
+ return (isc_boolean_false);
+
+ /*
+ * Verify that the $ and @ follow one another.
+ */
+ if (rname - sname != 2)
+ return (isc_boolean_false);
+
+ /*
+ * 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.
+ *
+ * All service principals in Microsoft format seem to be in
+ * machinename$@EXAMPLE.COM
+ * format.
+ */
+ *rname = '\0';
+ rname += 2;
+ *sname = '\0';
+ sname = sbuf;
+
+ /*
+ * 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.
+ */
+ if (name != NULL) {
+ nname = strchr(nbuf, '.');
+ if (nname == NULL)
+ return (isc_boolean_false);
+ *nname++ = '\0';
+ }
+
+ /*
+ * Now, we do a simple comparison between the name and the realm.
+ */
+ if (name != NULL) {
+ if ((strcasecmp(sname, nbuf) == 0)
+ && (strcmp(rname, rbuf) == 0)
+ && (strcasecmp(nname, rbuf) == 0))
+ return (isc_boolean_true);
+ } else {
+ if (strcmp(rname, rbuf) == 0)
+ return (isc_boolean_true);
+ }
+
+
+ return (isc_boolean_false);
+#else
+ UNUSED(signer);
+ UNUSED(name);
+ UNUSED(realm);
+ return (isc_boolean_false);
+#endif
+}
+
+isc_result_t
+dst_gssapi_releasecred(gss_cred_id_t *cred) {
+#ifdef GSSAPI
+ OM_uint32 gret, minor;
+ char buf[1024];
+
+ REQUIRE(cred != NULL && *cred != NULL);
+
+ gret = gss_release_cred(&minor, cred);
+ if (gret != GSS_S_COMPLETE) {
+ /* Log the error, but still free the credential's memory */
+ gss_log(3, "failed releasing credential: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ }
+ *cred = NULL;
+
+ return(ISC_R_SUCCESS);
+#else
+ UNUSED(cred);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_result_t
+dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
+ isc_buffer_t *outtoken, gss_ctx_id_t *gssctx)
+{
+#ifdef GSSAPI
+ isc_region_t r;
+ isc_buffer_t namebuf;
+ gss_name_t gname;
+ OM_uint32 gret, minor, ret_flags, flags;
+ gss_buffer_desc gintoken, *gintokenp, gouttoken = GSS_C_EMPTY_BUFFER;
+ 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);
+
+ isc_buffer_init(&namebuf, array, sizeof(array));
+ name_to_gbuffer(name, &namebuf, &gnamebuf);
+
+ /* Get the name as a GSS name */
+ gret = gss_import_name(&minor, &gnamebuf, GSS_C_NO_OID, &gname);
+ if (gret != GSS_S_COMPLETE) {
+ result = ISC_R_FAILURE;
+ goto out;
+ }
+
+ if (intoken != NULL) {
+ /* Don't call gss_release_buffer for gintoken! */
+ REGION_TO_GBUFFER(*intoken, gintoken);
+ gintokenp = &gintoken;
+ } else {
+ gintokenp = NULL;
+ }
+
+ flags = GSS_C_REPLAY_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG |
+ GSS_C_SEQUENCE_FLAG | GSS_C_INTEG_FLAG;
+
+ gret = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, gssctx,
+ gname, GSS_SPNEGO_MECHANISM, flags,
+ 0, NULL, gintokenp,
+ 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)));
+ result = ISC_R_FAILURE;
+ goto out;
+ }
+
+ /*
+ * XXXSRA Not handled yet: RFC 3645 3.1.1: check ret_flags
+ * MUTUAL and INTEG flags, fail if either not set.
+ */
+
+ /*
+ * RFC 2744 states the a valid output token has a non-zero length.
+ */
+ if (gouttoken.length != 0) {
+ GBUFFER_TO_REGION(gouttoken, r);
+ RETERR(isc_buffer_copyregion(outtoken, &r));
+ (void)gss_release_buffer(&minor, &gouttoken);
+ }
+ (void)gss_release_name(&minor, &gname);
+
+ if (gret == GSS_S_COMPLETE)
+ result = ISC_R_SUCCESS;
+ else
+ result = DNS_R_CONTINUE;
+
+ out:
+ return (result);
+#else
+ UNUSED(name);
+ UNUSED(intoken);
+ UNUSED(outtoken);
+ UNUSED(gssctx);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_result_t
+dst_gssapi_acceptctx(gss_cred_id_t cred,
+ isc_region_t *intoken, isc_buffer_t **outtoken,
+ gss_ctx_id_t *ctxout, dns_name_t *principal,
+ isc_mem_t *mctx)
+{
+#ifdef GSSAPI
+ isc_region_t r;
+ isc_buffer_t namebuf;
+ gss_buffer_desc gnamebuf = GSS_C_EMPTY_BUFFER, gintoken,
+ gouttoken = GSS_C_EMPTY_BUFFER;
+ OM_uint32 gret, minor;
+ gss_ctx_id_t context = GSS_C_NO_CONTEXT;
+ gss_name_t gname = NULL;
+ isc_result_t result;
+ char buf[1024];
+
+ REQUIRE(outtoken != NULL && *outtoken == NULL);
+
+ log_cred(cred);
+
+ REGION_TO_GBUFFER(*intoken, gintoken);
+
+ if (*ctxout == NULL)
+ context = GSS_C_NO_CONTEXT;
+ else
+ context = *ctxout;
+
+ gret = gss_accept_sec_context(&minor, &context, cred, &gintoken,
+ GSS_C_NO_CHANNEL_BINDINGS, &gname,
+ NULL, &gouttoken, NULL, NULL, NULL);
+
+ result = ISC_R_FAILURE;
+
+ switch (gret) {
+ case GSS_S_COMPLETE:
+ result = ISC_R_SUCCESS;
+ break;
+ case GSS_S_CONTINUE_NEEDED:
+ result = DNS_R_CONTINUE;
+ break;
+ case GSS_S_DEFECTIVE_TOKEN:
+ case GSS_S_DEFECTIVE_CREDENTIAL:
+ case GSS_S_BAD_SIG:
+ case GSS_S_DUPLICATE_TOKEN:
+ case GSS_S_OLD_TOKEN:
+ case GSS_S_NO_CRED:
+ case GSS_S_CREDENTIALS_EXPIRED:
+ case GSS_S_BAD_BINDINGS:
+ case GSS_S_NO_CONTEXT:
+ case GSS_S_BAD_MECH:
+ case GSS_S_FAILURE:
+ result = DNS_R_INVALIDTKEY;
+ /* fall through */
+ default:
+ gss_log(3, "failed gss_accept_sec_context: %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ return (result);
+ }
+
+ if (gouttoken.length > 0) {
+ RETERR(isc_buffer_allocate(mctx, outtoken, gouttoken.length));
+ GBUFFER_TO_REGION(gouttoken, r);
+ RETERR(isc_buffer_copyregion(*outtoken, &r));
+ (void)gss_release_buffer(&minor, &gouttoken);
+ }
+
+ if (gret == GSS_S_COMPLETE) {
+ gret = gss_display_name(&minor, gname, &gnamebuf, NULL);
+ if (gret != GSS_S_COMPLETE) {
+ gss_log(3, "failed gss_display_name: %s",
+ gss_error_tostring(gret, minor,
+ buf, sizeof(buf)));
+ RETERR(ISC_R_FAILURE);
+ }
+
+ /*
+ * Compensate for a bug in Solaris8's implementation
+ * of gss_display_name(). Should be harmless in any
+ * case, since principal names really should not
+ * contain null characters.
+ */
+ if (gnamebuf.length > 0 &&
+ ((char *)gnamebuf.value)[gnamebuf.length - 1] == '\0')
+ gnamebuf.length--;
+
+ gss_log(3, "gss-api source name (accept) is %.*s",
+ (int)gnamebuf.length, (char *)gnamebuf.value);
+
+ GBUFFER_TO_REGION(gnamebuf, r);
+ isc_buffer_init(&namebuf, r.base, r.length);
+ isc_buffer_add(&namebuf, r.length);
+
+ RETERR(dns_name_fromtext(principal, &namebuf, dns_rootname,
+ ISC_FALSE, NULL));
+
+ if (gnamebuf.length != 0) {
+ gret = gss_release_buffer(&minor, &gnamebuf);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_buffer: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+ }
+
+ *ctxout = context;
+
+ out:
+ if (gname != NULL) {
+ gret = gss_release_name(&minor, &gname);
+ if (gret != GSS_S_COMPLETE)
+ gss_log(3, "failed gss_release_name: %s",
+ gss_error_tostring(gret, minor, buf,
+ sizeof(buf)));
+ }
+
+ return (result);
+#else
+ UNUSED(cred);
+ UNUSED(intoken);
+ UNUSED(outtoken);
+ UNUSED(ctxout);
+ UNUSED(principal);
+ UNUSED(mctx);
+
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_result_t
+dst_gssapi_deletectx(isc_mem_t *mctx, gss_ctx_id_t *gssctx)
+{
+#ifdef GSSAPI
+ OM_uint32 gret, minor;
+ char buf[1024];
+
+ UNUSED(mctx);
+
+ REQUIRE(gssctx != NULL && *gssctx != NULL);
+
+ /* Delete the context from the GSS provider */
+ gret = gss_delete_sec_context(&minor, gssctx, GSS_C_NO_BUFFER);
+ if (gret != GSS_S_COMPLETE) {
+ /* Log the error, but still free the context's memory */
+ gss_log(3, "Failure deleting security context %s",
+ gss_error_tostring(gret, minor, buf, sizeof(buf)));
+ }
+ return(ISC_R_SUCCESS);
+#else
+ UNUSED(mctx);
+ UNUSED(gssctx);
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+char *
+gss_error_tostring(isc_uint32_t major, isc_uint32_t minor,
+ char *buf, size_t buflen) {
+#ifdef GSSAPI
+ gss_buffer_desc msg_minor = GSS_C_EMPTY_BUFFER,
+ msg_major = GSS_C_EMPTY_BUFFER;
+ OM_uint32 msg_ctx, minor_stat;
+
+ /* Handle major status */
+ msg_ctx = 0;
+ (void)gss_display_status(&minor_stat, major, GSS_C_GSS_CODE,
+ GSS_C_NULL_OID, &msg_ctx, &msg_major);
+
+ /* Handle minor status */
+ msg_ctx = 0;
+ (void)gss_display_status(&minor_stat, minor, GSS_C_MECH_CODE,
+ GSS_C_NULL_OID, &msg_ctx, &msg_minor);
+
+ snprintf(buf, buflen, "GSSAPI error: Major = %s, Minor = %s.",
+ (char *)msg_major.value, (char *)msg_minor.value);
+
+ if (msg_major.length != 0)
+ (void)gss_release_buffer(&minor_stat, &msg_major);
+ if (msg_minor.length != 0)
+ (void)gss_release_buffer(&minor_stat, &msg_minor);
+ return(buf);
+#else
+ snprintf(buf, buflen, "GSSAPI error: Major = %u, Minor = %u.",
+ major, minor);
+
+ return (buf);
+#endif
+}
+
+void
+gss_log(int level, const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_TKEY, ISC_LOG_DEBUG(level), fmt, ap);
+ va_end(ap);
+}
+
+/*! \file */
diff --git a/lib/dns/hmac_link.c b/lib/dns/hmac_link.c
new file mode 100644
index 0000000..fce98d7
--- /dev/null
+++ b/lib/dns/hmac_link.c
@@ -0,0 +1,1687 @@
+/*
+ * Portions Copyright (C) 2004-2008 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
+ * 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 AND NETWORK ASSOCIATES 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.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 AND NETWORK ASSOCIATES 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.
+ */
+
+/*
+ * Principal Author: Brian Wellington
+ * $Id: hmac_link.c,v 1.11 2008/04/01 23:47:10 tbox Exp $
+ */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/hmacmd5.h>
+#include <isc/hmacsha.h>
+#include <isc/md5.h>
+#include <isc/sha1.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dst/result.h>
+
+#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];
+};
+
+static isc_result_t
+getkeybits(dst_key_t *key, struct dst_private_element *element) {
+
+ if (element->length != 2)
+ return (DST_R_INVALIDPRIVATEKEY);
+
+ key->key_bits = (element->data[0] << 8) + element->data[1];
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
+ isc_hmacmd5_t *hmacmd5ctx;
+ dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
+
+ 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);
+ dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+hmacmd5_destroyctx(dst_context_t *dctx) {
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
+
+ if (hmacmd5ctx != NULL) {
+ isc_hmacmd5_invalidate(hmacmd5ctx);
+ isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
+ dctx->ctxdata.hmacmd5ctx = NULL;
+ }
+}
+
+static isc_result_t
+hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
+
+ isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
+ unsigned char *digest;
+
+ if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
+ return (ISC_R_NOSPACE);
+ digest = isc_buffer_used(sig);
+ isc_hmacmd5_sign(hmacmd5ctx, digest);
+ isc_buffer_add(sig, ISC_MD5_DIGESTLENGTH);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
+ isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
+
+ if (sig->length > ISC_MD5_DIGESTLENGTH)
+ return (DST_R_VERIFYFAILURE);
+
+ if (isc_hmacmd5_verify2(hmacmd5ctx, sig->base, sig->length))
+ return (ISC_R_SUCCESS);
+ else
+ return (DST_R_VERIFYFAILURE);
+}
+
+static isc_boolean_t
+hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ dst_hmacmd5_key_t *hkey1, *hkey2;
+
+ hkey1 = key1->keydata.hmacmd5;
+ hkey2 = key2->keydata.hmacmd5;
+
+ if (hkey1 == NULL && hkey2 == NULL)
+ return (ISC_TRUE);
+ else if (hkey1 == NULL || hkey2 == NULL)
+ return (ISC_FALSE);
+
+ if (memcmp(hkey1->key, hkey2->key, HMAC_LEN) == 0)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+hmacmd5_generate(dst_key_t *key, int pseudorandom_ok) {
+ isc_buffer_t b;
+ isc_result_t ret;
+ int bytes;
+ unsigned char data[HMAC_LEN];
+
+ bytes = (key->key_size + 7) / 8;
+ if (bytes > HMAC_LEN) {
+ bytes = HMAC_LEN;
+ key->key_size = HMAC_LEN * 8;
+ }
+
+ memset(data, 0, HMAC_LEN);
+ ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
+
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ isc_buffer_init(&b, data, bytes);
+ isc_buffer_add(&b, bytes);
+ ret = hmacmd5_fromdns(key, &b);
+ memset(data, 0, HMAC_LEN);
+
+ return (ret);
+}
+
+static isc_boolean_t
+hmacmd5_isprivate(const dst_key_t *key) {
+ UNUSED(key);
+ return (ISC_TRUE);
+}
+
+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;
+}
+
+static isc_result_t
+hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacmd5_key_t *hkey;
+ unsigned int bytes;
+
+ REQUIRE(key->keydata.hmacmd5 != NULL);
+
+ hkey = key->keydata.hmacmd5;
+
+ bytes = (key->key_size + 7) / 8;
+ if (isc_buffer_availablelength(data) < bytes)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putmem(data, hkey->key, bytes);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacmd5_key_t *hkey;
+ int keylen;
+ isc_region_t r;
+ isc_md5_t md5ctx;
+
+ isc_buffer_remainingregion(data, &r);
+ if (r.length == 0)
+ return (ISC_R_SUCCESS);
+
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
+ if (hkey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(hkey->key, 0, sizeof(hkey->key));
+
+ if (r.length > HMAC_LEN) {
+ isc_md5_init(&md5ctx);
+ isc_md5_update(&md5ctx, r.base, r.length);
+ isc_md5_final(&md5ctx, hkey->key);
+ keylen = ISC_MD5_DIGESTLENGTH;
+ }
+ else {
+ memcpy(hkey->key, r.base, r.length);
+ keylen = r.length;
+ }
+
+ key->key_size = keylen * 8;
+ key->keydata.hmacmd5 = hkey;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacmd5_tofile(const dst_key_t *key, const char *directory) {
+ int cnt = 0;
+ dst_hmacmd5_key_t *hkey;
+ dst_private_t priv;
+ int bytes = (key->key_size + 7) / 8;
+ unsigned char buf[2];
+
+ if (key->keydata.hmacmd5 == NULL)
+ return (DST_R_NULLKEY);
+
+ hkey = key->keydata.hmacmd5;
+
+ priv.elements[cnt].tag = TAG_HMACMD5_KEY;
+ priv.elements[cnt].length = bytes;
+ priv.elements[cnt++].data = hkey->key;
+
+ buf[0] = (key->key_bits >> 8) & 0xffU;
+ buf[1] = key->key_bits & 0xffU;
+ priv.elements[cnt].tag = TAG_HMACMD5_BITS;
+ priv.elements[cnt].data = buf;
+ priv.elements[cnt++].length = 2;
+
+ priv.nelements = cnt;
+ return (dst__privstruct_writefile(key, &priv, directory));
+}
+
+static isc_result_t
+hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer) {
+ dst_private_t priv;
+ isc_result_t result, tresult;
+ isc_buffer_t b;
+ isc_mem_t *mctx = key->mctx;
+ unsigned int i;
+
+ /* read private key file */
+ result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx, &priv);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ key->key_bits = 0;
+ for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_HMACMD5_KEY:
+ isc_buffer_init(&b, priv.elements[i].data,
+ priv.elements[i].length);
+ isc_buffer_add(&b, priv.elements[i].length);
+ tresult = hmacmd5_fromdns(key, &b);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ case TAG_HMACMD5_BITS:
+ tresult = getkeybits(key, &priv.elements[i]);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ default:
+ result = DST_R_INVALIDPRIVATEKEY;
+ break;
+ }
+ }
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (result);
+}
+
+static dst_func_t hmacmd5_functions = {
+ hmacmd5_createctx,
+ hmacmd5_destroyctx,
+ hmacmd5_adddata,
+ hmacmd5_sign,
+ hmacmd5_verify,
+ NULL, /*%< computesecret */
+ hmacmd5_compare,
+ NULL, /*%< paramcompare */
+ hmacmd5_generate,
+ hmacmd5_isprivate,
+ hmacmd5_destroy,
+ hmacmd5_todns,
+ hmacmd5_fromdns,
+ hmacmd5_tofile,
+ hmacmd5_parse,
+ NULL, /*%< cleanup */
+ NULL, /*%< fromlabel */
+};
+
+isc_result_t
+dst__hmacmd5_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+ if (*funcp == NULL)
+ *funcp = &hmacmd5_functions;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
+
+struct dst_hmacsha1_key {
+ unsigned char key[ISC_SHA1_DIGESTLENGTH];
+};
+
+static isc_result_t
+hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
+ isc_hmacsha1_t *hmacsha1ctx;
+ dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
+
+ 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);
+ dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+hmacsha1_destroyctx(dst_context_t *dctx) {
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
+
+ if (hmacsha1ctx != NULL) {
+ isc_hmacsha1_invalidate(hmacsha1ctx);
+ isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
+ dctx->ctxdata.hmacsha1ctx = NULL;
+ }
+}
+
+static isc_result_t
+hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
+
+ isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
+ unsigned char *digest;
+
+ if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
+ return (ISC_R_NOSPACE);
+ digest = isc_buffer_used(sig);
+ isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
+ isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
+ isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
+
+ if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
+ return (DST_R_VERIFYFAILURE);
+
+ if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
+ return (ISC_R_SUCCESS);
+ else
+ return (DST_R_VERIFYFAILURE);
+}
+
+static isc_boolean_t
+hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ dst_hmacsha1_key_t *hkey1, *hkey2;
+
+ hkey1 = key1->keydata.hmacsha1;
+ hkey2 = key2->keydata.hmacsha1;
+
+ if (hkey1 == NULL && hkey2 == NULL)
+ return (ISC_TRUE);
+ else if (hkey1 == NULL || hkey2 == NULL)
+ return (ISC_FALSE);
+
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_DIGESTLENGTH) == 0)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+hmacsha1_generate(dst_key_t *key, int pseudorandom_ok) {
+ isc_buffer_t b;
+ isc_result_t ret;
+ int bytes;
+ unsigned char data[HMAC_LEN];
+
+ bytes = (key->key_size + 7) / 8;
+ if (bytes > HMAC_LEN) {
+ bytes = HMAC_LEN;
+ key->key_size = HMAC_LEN * 8;
+ }
+
+ memset(data, 0, HMAC_LEN);
+ ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
+
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ isc_buffer_init(&b, data, bytes);
+ isc_buffer_add(&b, bytes);
+ ret = hmacsha1_fromdns(key, &b);
+ memset(data, 0, ISC_SHA1_DIGESTLENGTH);
+
+ return (ret);
+}
+
+static isc_boolean_t
+hmacsha1_isprivate(const dst_key_t *key) {
+ UNUSED(key);
+ return (ISC_TRUE);
+}
+
+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;
+}
+
+static isc_result_t
+hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacsha1_key_t *hkey;
+ unsigned int bytes;
+
+ REQUIRE(key->keydata.hmacsha1 != NULL);
+
+ hkey = key->keydata.hmacsha1;
+
+ bytes = (key->key_size + 7) / 8;
+ if (isc_buffer_availablelength(data) < bytes)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putmem(data, hkey->key, bytes);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacsha1_key_t *hkey;
+ int keylen;
+ isc_region_t r;
+ isc_sha1_t sha1ctx;
+
+ isc_buffer_remainingregion(data, &r);
+ if (r.length == 0)
+ return (ISC_R_SUCCESS);
+
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
+ if (hkey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(hkey->key, 0, sizeof(hkey->key));
+
+ if (r.length > ISC_SHA1_DIGESTLENGTH) {
+ isc_sha1_init(&sha1ctx);
+ isc_sha1_update(&sha1ctx, r.base, r.length);
+ isc_sha1_final(&sha1ctx, hkey->key);
+ keylen = ISC_SHA1_DIGESTLENGTH;
+ }
+ else {
+ memcpy(hkey->key, r.base, r.length);
+ keylen = r.length;
+ }
+
+ key->key_size = keylen * 8;
+ key->keydata.hmacsha1 = hkey;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha1_tofile(const dst_key_t *key, const char *directory) {
+ int cnt = 0;
+ dst_hmacsha1_key_t *hkey;
+ dst_private_t priv;
+ int bytes = (key->key_size + 7) / 8;
+ unsigned char buf[2];
+
+ if (key->keydata.hmacsha1 == NULL)
+ return (DST_R_NULLKEY);
+
+ hkey = key->keydata.hmacsha1;
+
+ priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
+ priv.elements[cnt].length = bytes;
+ priv.elements[cnt++].data = hkey->key;
+
+ buf[0] = (key->key_bits >> 8) & 0xffU;
+ buf[1] = key->key_bits & 0xffU;
+ priv.elements[cnt].tag = TAG_HMACSHA1_BITS;
+ priv.elements[cnt].data = buf;
+ priv.elements[cnt++].length = 2;
+
+ priv.nelements = cnt;
+ return (dst__privstruct_writefile(key, &priv, directory));
+}
+
+static isc_result_t
+hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer) {
+ dst_private_t priv;
+ isc_result_t result, tresult;
+ isc_buffer_t b;
+ isc_mem_t *mctx = key->mctx;
+ unsigned int i;
+
+ /* read private key file */
+ result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
+ &priv);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ key->key_bits = 0;
+ for (i = 0; i < priv.nelements; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_HMACSHA1_KEY:
+ isc_buffer_init(&b, priv.elements[i].data,
+ priv.elements[i].length);
+ isc_buffer_add(&b, priv.elements[i].length);
+ tresult = hmacsha1_fromdns(key, &b);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ case TAG_HMACSHA1_BITS:
+ tresult = getkeybits(key, &priv.elements[i]);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ default:
+ result = DST_R_INVALIDPRIVATEKEY;
+ break;
+ }
+ }
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (result);
+}
+
+static dst_func_t hmacsha1_functions = {
+ hmacsha1_createctx,
+ hmacsha1_destroyctx,
+ hmacsha1_adddata,
+ hmacsha1_sign,
+ hmacsha1_verify,
+ NULL, /* computesecret */
+ hmacsha1_compare,
+ NULL, /* paramcompare */
+ hmacsha1_generate,
+ hmacsha1_isprivate,
+ hmacsha1_destroy,
+ hmacsha1_todns,
+ hmacsha1_fromdns,
+ hmacsha1_tofile,
+ hmacsha1_parse,
+ NULL, /* cleanup */
+ NULL, /* fromlabel */
+};
+
+isc_result_t
+dst__hmacsha1_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+ if (*funcp == NULL)
+ *funcp = &hmacsha1_functions;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
+
+struct dst_hmacsha224_key {
+ unsigned char key[ISC_SHA224_DIGESTLENGTH];
+};
+
+static isc_result_t
+hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
+ isc_hmacsha224_t *hmacsha224ctx;
+ dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
+
+ 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);
+ dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+hmacsha224_destroyctx(dst_context_t *dctx) {
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
+
+ if (hmacsha224ctx != NULL) {
+ isc_hmacsha224_invalidate(hmacsha224ctx);
+ isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
+ dctx->ctxdata.hmacsha224ctx = NULL;
+ }
+}
+
+static isc_result_t
+hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
+
+ isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
+ unsigned char *digest;
+
+ if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
+ return (ISC_R_NOSPACE);
+ digest = isc_buffer_used(sig);
+ isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
+ isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
+ isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
+
+ if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
+ return (DST_R_VERIFYFAILURE);
+
+ if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
+ return (ISC_R_SUCCESS);
+ else
+ return (DST_R_VERIFYFAILURE);
+}
+
+static isc_boolean_t
+hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ dst_hmacsha224_key_t *hkey1, *hkey2;
+
+ hkey1 = key1->keydata.hmacsha224;
+ hkey2 = key2->keydata.hmacsha224;
+
+ if (hkey1 == NULL && hkey2 == NULL)
+ return (ISC_TRUE);
+ else if (hkey1 == NULL || hkey2 == NULL)
+ return (ISC_FALSE);
+
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA224_DIGESTLENGTH) == 0)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+hmacsha224_generate(dst_key_t *key, int pseudorandom_ok) {
+ isc_buffer_t b;
+ isc_result_t ret;
+ int bytes;
+ unsigned char data[HMAC_LEN];
+
+ bytes = (key->key_size + 7) / 8;
+ if (bytes > HMAC_LEN) {
+ bytes = HMAC_LEN;
+ key->key_size = HMAC_LEN * 8;
+ }
+
+ memset(data, 0, HMAC_LEN);
+ ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
+
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ isc_buffer_init(&b, data, bytes);
+ isc_buffer_add(&b, bytes);
+ ret = hmacsha224_fromdns(key, &b);
+ memset(data, 0, ISC_SHA224_DIGESTLENGTH);
+
+ return (ret);
+}
+
+static isc_boolean_t
+hmacsha224_isprivate(const dst_key_t *key) {
+ UNUSED(key);
+ return (ISC_TRUE);
+}
+
+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;
+}
+
+static isc_result_t
+hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacsha224_key_t *hkey;
+ unsigned int bytes;
+
+ REQUIRE(key->keydata.hmacsha224 != NULL);
+
+ hkey = key->keydata.hmacsha224;
+
+ bytes = (key->key_size + 7) / 8;
+ if (isc_buffer_availablelength(data) < bytes)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putmem(data, hkey->key, bytes);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacsha224_key_t *hkey;
+ int keylen;
+ isc_region_t r;
+ isc_sha224_t sha224ctx;
+
+ isc_buffer_remainingregion(data, &r);
+ if (r.length == 0)
+ return (ISC_R_SUCCESS);
+
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
+ if (hkey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(hkey->key, 0, sizeof(hkey->key));
+
+ if (r.length > ISC_SHA224_DIGESTLENGTH) {
+ isc_sha224_init(&sha224ctx);
+ isc_sha224_update(&sha224ctx, r.base, r.length);
+ isc_sha224_final(hkey->key, &sha224ctx);
+ keylen = ISC_SHA224_DIGESTLENGTH;
+ }
+ else {
+ memcpy(hkey->key, r.base, r.length);
+ keylen = r.length;
+ }
+
+ key->key_size = keylen * 8;
+ key->keydata.hmacsha224 = hkey;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha224_tofile(const dst_key_t *key, const char *directory) {
+ int cnt = 0;
+ dst_hmacsha224_key_t *hkey;
+ dst_private_t priv;
+ int bytes = (key->key_size + 7) / 8;
+ unsigned char buf[2];
+
+ if (key->keydata.hmacsha224 == NULL)
+ return (DST_R_NULLKEY);
+
+ hkey = key->keydata.hmacsha224;
+
+ priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
+ priv.elements[cnt].length = bytes;
+ priv.elements[cnt++].data = hkey->key;
+
+ buf[0] = (key->key_bits >> 8) & 0xffU;
+ buf[1] = key->key_bits & 0xffU;
+ priv.elements[cnt].tag = TAG_HMACSHA224_BITS;
+ priv.elements[cnt].data = buf;
+ priv.elements[cnt++].length = 2;
+
+ priv.nelements = cnt;
+ return (dst__privstruct_writefile(key, &priv, directory));
+}
+
+static isc_result_t
+hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer) {
+ dst_private_t priv;
+ isc_result_t result, tresult;
+ isc_buffer_t b;
+ isc_mem_t *mctx = key->mctx;
+ unsigned int i;
+
+ /* read private key file */
+ result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
+ &priv);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ key->key_bits = 0;
+ for (i = 0; i < priv.nelements; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_HMACSHA224_KEY:
+ isc_buffer_init(&b, priv.elements[i].data,
+ priv.elements[i].length);
+ isc_buffer_add(&b, priv.elements[i].length);
+ tresult = hmacsha224_fromdns(key, &b);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ case TAG_HMACSHA224_BITS:
+ tresult = getkeybits(key, &priv.elements[i]);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ default:
+ result = DST_R_INVALIDPRIVATEKEY;
+ break;
+ }
+ }
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (result);
+}
+
+static dst_func_t hmacsha224_functions = {
+ hmacsha224_createctx,
+ hmacsha224_destroyctx,
+ hmacsha224_adddata,
+ hmacsha224_sign,
+ hmacsha224_verify,
+ NULL, /* computesecret */
+ hmacsha224_compare,
+ NULL, /* paramcompare */
+ hmacsha224_generate,
+ hmacsha224_isprivate,
+ hmacsha224_destroy,
+ hmacsha224_todns,
+ hmacsha224_fromdns,
+ hmacsha224_tofile,
+ hmacsha224_parse,
+ NULL, /* cleanup */
+ NULL, /* fromlabel */
+};
+
+isc_result_t
+dst__hmacsha224_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+ if (*funcp == NULL)
+ *funcp = &hmacsha224_functions;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
+
+struct dst_hmacsha256_key {
+ unsigned char key[ISC_SHA256_DIGESTLENGTH];
+};
+
+static isc_result_t
+hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
+ isc_hmacsha256_t *hmacsha256ctx;
+ dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
+
+ 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);
+ dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+hmacsha256_destroyctx(dst_context_t *dctx) {
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
+
+ if (hmacsha256ctx != NULL) {
+ isc_hmacsha256_invalidate(hmacsha256ctx);
+ isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
+ dctx->ctxdata.hmacsha256ctx = NULL;
+ }
+}
+
+static isc_result_t
+hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
+
+ isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
+ unsigned char *digest;
+
+ if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
+ return (ISC_R_NOSPACE);
+ digest = isc_buffer_used(sig);
+ isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
+ isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
+ isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
+
+ if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
+ return (DST_R_VERIFYFAILURE);
+
+ if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
+ return (ISC_R_SUCCESS);
+ else
+ return (DST_R_VERIFYFAILURE);
+}
+
+static isc_boolean_t
+hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ dst_hmacsha256_key_t *hkey1, *hkey2;
+
+ hkey1 = key1->keydata.hmacsha256;
+ hkey2 = key2->keydata.hmacsha256;
+
+ if (hkey1 == NULL && hkey2 == NULL)
+ return (ISC_TRUE);
+ else if (hkey1 == NULL || hkey2 == NULL)
+ return (ISC_FALSE);
+
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA256_DIGESTLENGTH) == 0)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+hmacsha256_generate(dst_key_t *key, int pseudorandom_ok) {
+ isc_buffer_t b;
+ isc_result_t ret;
+ int bytes;
+ unsigned char data[HMAC_LEN];
+
+ bytes = (key->key_size + 7) / 8;
+ if (bytes > HMAC_LEN) {
+ bytes = HMAC_LEN;
+ key->key_size = HMAC_LEN * 8;
+ }
+
+ memset(data, 0, HMAC_LEN);
+ ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
+
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ isc_buffer_init(&b, data, bytes);
+ isc_buffer_add(&b, bytes);
+ ret = hmacsha256_fromdns(key, &b);
+ memset(data, 0, ISC_SHA256_DIGESTLENGTH);
+
+ return (ret);
+}
+
+static isc_boolean_t
+hmacsha256_isprivate(const dst_key_t *key) {
+ UNUSED(key);
+ return (ISC_TRUE);
+}
+
+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;
+}
+
+static isc_result_t
+hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacsha256_key_t *hkey;
+ unsigned int bytes;
+
+ REQUIRE(key->keydata.hmacsha256 != NULL);
+
+ hkey = key->keydata.hmacsha256;
+
+ bytes = (key->key_size + 7) / 8;
+ if (isc_buffer_availablelength(data) < bytes)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putmem(data, hkey->key, bytes);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacsha256_key_t *hkey;
+ int keylen;
+ isc_region_t r;
+ isc_sha256_t sha256ctx;
+
+ isc_buffer_remainingregion(data, &r);
+ if (r.length == 0)
+ return (ISC_R_SUCCESS);
+
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
+ if (hkey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(hkey->key, 0, sizeof(hkey->key));
+
+ if (r.length > ISC_SHA256_DIGESTLENGTH) {
+ isc_sha256_init(&sha256ctx);
+ isc_sha256_update(&sha256ctx, r.base, r.length);
+ isc_sha256_final(hkey->key, &sha256ctx);
+ keylen = ISC_SHA256_DIGESTLENGTH;
+ }
+ else {
+ memcpy(hkey->key, r.base, r.length);
+ keylen = r.length;
+ }
+
+ key->key_size = keylen * 8;
+ key->keydata.hmacsha256 = hkey;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha256_tofile(const dst_key_t *key, const char *directory) {
+ int cnt = 0;
+ dst_hmacsha256_key_t *hkey;
+ dst_private_t priv;
+ int bytes = (key->key_size + 7) / 8;
+ unsigned char buf[2];
+
+ if (key->keydata.hmacsha256 == NULL)
+ return (DST_R_NULLKEY);
+
+ hkey = key->keydata.hmacsha256;
+
+ priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
+ priv.elements[cnt].length = bytes;
+ priv.elements[cnt++].data = hkey->key;
+
+ buf[0] = (key->key_bits >> 8) & 0xffU;
+ buf[1] = key->key_bits & 0xffU;
+ priv.elements[cnt].tag = TAG_HMACSHA256_BITS;
+ priv.elements[cnt].data = buf;
+ priv.elements[cnt++].length = 2;
+
+ priv.nelements = cnt;
+ return (dst__privstruct_writefile(key, &priv, directory));
+}
+
+static isc_result_t
+hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer) {
+ dst_private_t priv;
+ isc_result_t result, tresult;
+ isc_buffer_t b;
+ isc_mem_t *mctx = key->mctx;
+ unsigned int i;
+
+ /* read private key file */
+ result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
+ &priv);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ key->key_bits = 0;
+ for (i = 0; i < priv.nelements; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_HMACSHA256_KEY:
+ isc_buffer_init(&b, priv.elements[i].data,
+ priv.elements[i].length);
+ isc_buffer_add(&b, priv.elements[i].length);
+ tresult = hmacsha256_fromdns(key, &b);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ case TAG_HMACSHA256_BITS:
+ tresult = getkeybits(key, &priv.elements[i]);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ default:
+ result = DST_R_INVALIDPRIVATEKEY;
+ break;
+ }
+ }
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (result);
+}
+
+static dst_func_t hmacsha256_functions = {
+ hmacsha256_createctx,
+ hmacsha256_destroyctx,
+ hmacsha256_adddata,
+ hmacsha256_sign,
+ hmacsha256_verify,
+ NULL, /* computesecret */
+ hmacsha256_compare,
+ NULL, /* paramcompare */
+ hmacsha256_generate,
+ hmacsha256_isprivate,
+ hmacsha256_destroy,
+ hmacsha256_todns,
+ hmacsha256_fromdns,
+ hmacsha256_tofile,
+ hmacsha256_parse,
+ NULL, /* cleanup */
+ NULL, /* fromlabel */
+};
+
+isc_result_t
+dst__hmacsha256_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+ if (*funcp == NULL)
+ *funcp = &hmacsha256_functions;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
+
+struct dst_hmacsha384_key {
+ unsigned char key[ISC_SHA384_DIGESTLENGTH];
+};
+
+static isc_result_t
+hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
+ isc_hmacsha384_t *hmacsha384ctx;
+ dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
+
+ 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);
+ dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+hmacsha384_destroyctx(dst_context_t *dctx) {
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
+
+ if (hmacsha384ctx != NULL) {
+ isc_hmacsha384_invalidate(hmacsha384ctx);
+ isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
+ dctx->ctxdata.hmacsha384ctx = NULL;
+ }
+}
+
+static isc_result_t
+hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
+
+ isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
+ unsigned char *digest;
+
+ if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
+ return (ISC_R_NOSPACE);
+ digest = isc_buffer_used(sig);
+ isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
+ isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
+ isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
+
+ if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
+ return (DST_R_VERIFYFAILURE);
+
+ if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
+ return (ISC_R_SUCCESS);
+ else
+ return (DST_R_VERIFYFAILURE);
+}
+
+static isc_boolean_t
+hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ dst_hmacsha384_key_t *hkey1, *hkey2;
+
+ hkey1 = key1->keydata.hmacsha384;
+ hkey2 = key2->keydata.hmacsha384;
+
+ if (hkey1 == NULL && hkey2 == NULL)
+ return (ISC_TRUE);
+ else if (hkey1 == NULL || hkey2 == NULL)
+ return (ISC_FALSE);
+
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA384_DIGESTLENGTH) == 0)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+hmacsha384_generate(dst_key_t *key, int pseudorandom_ok) {
+ isc_buffer_t b;
+ isc_result_t ret;
+ int bytes;
+ unsigned char data[HMAC_LEN];
+
+ bytes = (key->key_size + 7) / 8;
+ if (bytes > HMAC_LEN) {
+ bytes = HMAC_LEN;
+ key->key_size = HMAC_LEN * 8;
+ }
+
+ memset(data, 0, HMAC_LEN);
+ ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
+
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ isc_buffer_init(&b, data, bytes);
+ isc_buffer_add(&b, bytes);
+ ret = hmacsha384_fromdns(key, &b);
+ memset(data, 0, ISC_SHA384_DIGESTLENGTH);
+
+ return (ret);
+}
+
+static isc_boolean_t
+hmacsha384_isprivate(const dst_key_t *key) {
+ UNUSED(key);
+ return (ISC_TRUE);
+}
+
+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;
+}
+
+static isc_result_t
+hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacsha384_key_t *hkey;
+ unsigned int bytes;
+
+ REQUIRE(key->keydata.hmacsha384 != NULL);
+
+ hkey = key->keydata.hmacsha384;
+
+ bytes = (key->key_size + 7) / 8;
+ if (isc_buffer_availablelength(data) < bytes)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putmem(data, hkey->key, bytes);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacsha384_key_t *hkey;
+ int keylen;
+ isc_region_t r;
+ isc_sha384_t sha384ctx;
+
+ isc_buffer_remainingregion(data, &r);
+ if (r.length == 0)
+ return (ISC_R_SUCCESS);
+
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
+ if (hkey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(hkey->key, 0, sizeof(hkey->key));
+
+ if (r.length > ISC_SHA384_DIGESTLENGTH) {
+ isc_sha384_init(&sha384ctx);
+ isc_sha384_update(&sha384ctx, r.base, r.length);
+ isc_sha384_final(hkey->key, &sha384ctx);
+ keylen = ISC_SHA384_DIGESTLENGTH;
+ }
+ else {
+ memcpy(hkey->key, r.base, r.length);
+ keylen = r.length;
+ }
+
+ key->key_size = keylen * 8;
+ key->keydata.hmacsha384 = hkey;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha384_tofile(const dst_key_t *key, const char *directory) {
+ int cnt = 0;
+ dst_hmacsha384_key_t *hkey;
+ dst_private_t priv;
+ int bytes = (key->key_size + 7) / 8;
+ unsigned char buf[2];
+
+ if (key->keydata.hmacsha384 == NULL)
+ return (DST_R_NULLKEY);
+
+ hkey = key->keydata.hmacsha384;
+
+ priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
+ priv.elements[cnt].length = bytes;
+ priv.elements[cnt++].data = hkey->key;
+
+ buf[0] = (key->key_bits >> 8) & 0xffU;
+ buf[1] = key->key_bits & 0xffU;
+ priv.elements[cnt].tag = TAG_HMACSHA384_BITS;
+ priv.elements[cnt].data = buf;
+ priv.elements[cnt++].length = 2;
+
+ priv.nelements = cnt;
+ return (dst__privstruct_writefile(key, &priv, directory));
+}
+
+static isc_result_t
+hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer) {
+ dst_private_t priv;
+ isc_result_t result, tresult;
+ isc_buffer_t b;
+ isc_mem_t *mctx = key->mctx;
+ unsigned int i;
+
+ /* read private key file */
+ result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
+ &priv);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ key->key_bits = 0;
+ for (i = 0; i < priv.nelements; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_HMACSHA384_KEY:
+ isc_buffer_init(&b, priv.elements[i].data,
+ priv.elements[i].length);
+ isc_buffer_add(&b, priv.elements[i].length);
+ tresult = hmacsha384_fromdns(key, &b);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ case TAG_HMACSHA384_BITS:
+ tresult = getkeybits(key, &priv.elements[i]);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ default:
+ result = DST_R_INVALIDPRIVATEKEY;
+ break;
+ }
+ }
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (result);
+}
+
+static dst_func_t hmacsha384_functions = {
+ hmacsha384_createctx,
+ hmacsha384_destroyctx,
+ hmacsha384_adddata,
+ hmacsha384_sign,
+ hmacsha384_verify,
+ NULL, /* computesecret */
+ hmacsha384_compare,
+ NULL, /* paramcompare */
+ hmacsha384_generate,
+ hmacsha384_isprivate,
+ hmacsha384_destroy,
+ hmacsha384_todns,
+ hmacsha384_fromdns,
+ hmacsha384_tofile,
+ hmacsha384_parse,
+ NULL, /* cleanup */
+ NULL, /* fromlabel */
+};
+
+isc_result_t
+dst__hmacsha384_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+ if (*funcp == NULL)
+ *funcp = &hmacsha384_functions;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
+
+struct dst_hmacsha512_key {
+ unsigned char key[ISC_SHA512_DIGESTLENGTH];
+};
+
+static isc_result_t
+hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
+ isc_hmacsha512_t *hmacsha512ctx;
+ dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
+
+ 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);
+ dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+hmacsha512_destroyctx(dst_context_t *dctx) {
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
+
+ if (hmacsha512ctx != NULL) {
+ isc_hmacsha512_invalidate(hmacsha512ctx);
+ isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
+ dctx->ctxdata.hmacsha512ctx = NULL;
+ }
+}
+
+static isc_result_t
+hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
+
+ isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
+ unsigned char *digest;
+
+ if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
+ return (ISC_R_NOSPACE);
+ digest = isc_buffer_used(sig);
+ isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
+ isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
+ isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
+
+ if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
+ return (DST_R_VERIFYFAILURE);
+
+ if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
+ return (ISC_R_SUCCESS);
+ else
+ return (DST_R_VERIFYFAILURE);
+}
+
+static isc_boolean_t
+hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ dst_hmacsha512_key_t *hkey1, *hkey2;
+
+ hkey1 = key1->keydata.hmacsha512;
+ hkey2 = key2->keydata.hmacsha512;
+
+ if (hkey1 == NULL && hkey2 == NULL)
+ return (ISC_TRUE);
+ else if (hkey1 == NULL || hkey2 == NULL)
+ return (ISC_FALSE);
+
+ if (memcmp(hkey1->key, hkey2->key, ISC_SHA512_DIGESTLENGTH) == 0)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+hmacsha512_generate(dst_key_t *key, int pseudorandom_ok) {
+ isc_buffer_t b;
+ isc_result_t ret;
+ int bytes;
+ unsigned char data[HMAC_LEN];
+
+ bytes = (key->key_size + 7) / 8;
+ if (bytes > HMAC_LEN) {
+ bytes = HMAC_LEN;
+ key->key_size = HMAC_LEN * 8;
+ }
+
+ memset(data, 0, HMAC_LEN);
+ ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
+
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ isc_buffer_init(&b, data, bytes);
+ isc_buffer_add(&b, bytes);
+ ret = hmacsha512_fromdns(key, &b);
+ memset(data, 0, ISC_SHA512_DIGESTLENGTH);
+
+ return (ret);
+}
+
+static isc_boolean_t
+hmacsha512_isprivate(const dst_key_t *key) {
+ UNUSED(key);
+ return (ISC_TRUE);
+}
+
+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;
+}
+
+static isc_result_t
+hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacsha512_key_t *hkey;
+ unsigned int bytes;
+
+ REQUIRE(key->keydata.hmacsha512 != NULL);
+
+ hkey = key->keydata.hmacsha512;
+
+ bytes = (key->key_size + 7) / 8;
+ if (isc_buffer_availablelength(data) < bytes)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putmem(data, hkey->key, bytes);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
+ dst_hmacsha512_key_t *hkey;
+ int keylen;
+ isc_region_t r;
+ isc_sha512_t sha512ctx;
+
+ isc_buffer_remainingregion(data, &r);
+ if (r.length == 0)
+ return (ISC_R_SUCCESS);
+
+ hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
+ if (hkey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(hkey->key, 0, sizeof(hkey->key));
+
+ if (r.length > ISC_SHA512_DIGESTLENGTH) {
+ isc_sha512_init(&sha512ctx);
+ isc_sha512_update(&sha512ctx, r.base, r.length);
+ isc_sha512_final(hkey->key, &sha512ctx);
+ keylen = ISC_SHA512_DIGESTLENGTH;
+ }
+ else {
+ memcpy(hkey->key, r.base, r.length);
+ keylen = r.length;
+ }
+
+ key->key_size = keylen * 8;
+ key->keydata.hmacsha512 = hkey;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+hmacsha512_tofile(const dst_key_t *key, const char *directory) {
+ int cnt = 0;
+ dst_hmacsha512_key_t *hkey;
+ dst_private_t priv;
+ int bytes = (key->key_size + 7) / 8;
+ unsigned char buf[2];
+
+ if (key->keydata.hmacsha512 == NULL)
+ return (DST_R_NULLKEY);
+
+ hkey = key->keydata.hmacsha512;
+
+ priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
+ priv.elements[cnt].length = bytes;
+ priv.elements[cnt++].data = hkey->key;
+
+ buf[0] = (key->key_bits >> 8) & 0xffU;
+ buf[1] = key->key_bits & 0xffU;
+ priv.elements[cnt].tag = TAG_HMACSHA512_BITS;
+ priv.elements[cnt].data = buf;
+ priv.elements[cnt++].length = 2;
+
+ priv.nelements = cnt;
+ return (dst__privstruct_writefile(key, &priv, directory));
+}
+
+static isc_result_t
+hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer) {
+ dst_private_t priv;
+ isc_result_t result, tresult;
+ isc_buffer_t b;
+ isc_mem_t *mctx = key->mctx;
+ unsigned int i;
+
+ /* read private key file */
+ result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
+ &priv);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ key->key_bits = 0;
+ for (i = 0; i < priv.nelements; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_HMACSHA512_KEY:
+ isc_buffer_init(&b, priv.elements[i].data,
+ priv.elements[i].length);
+ isc_buffer_add(&b, priv.elements[i].length);
+ tresult = hmacsha512_fromdns(key, &b);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ case TAG_HMACSHA512_BITS:
+ tresult = getkeybits(key, &priv.elements[i]);
+ if (tresult != ISC_R_SUCCESS)
+ result = tresult;
+ break;
+ default:
+ result = DST_R_INVALIDPRIVATEKEY;
+ break;
+ }
+ }
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (result);
+}
+
+static dst_func_t hmacsha512_functions = {
+ hmacsha512_createctx,
+ hmacsha512_destroyctx,
+ hmacsha512_adddata,
+ hmacsha512_sign,
+ hmacsha512_verify,
+ NULL, /* computesecret */
+ hmacsha512_compare,
+ NULL, /* paramcompare */
+ hmacsha512_generate,
+ hmacsha512_isprivate,
+ hmacsha512_destroy,
+ hmacsha512_todns,
+ hmacsha512_fromdns,
+ hmacsha512_tofile,
+ hmacsha512_parse,
+ NULL, /* cleanup */
+ NULL, /* fromlabel */
+};
+
+isc_result_t
+dst__hmacsha512_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+ if (*funcp == NULL)
+ *funcp = &hmacsha512_functions;
+ return (ISC_R_SUCCESS);
+}
+
+/*! \file */
diff --git a/lib/dns/include/Makefile.in b/lib/dns/include/Makefile.in
new file mode 100644
index 0000000..b52cb98
--- /dev/null
+++ b/lib/dns/include/Makefile.in
@@ -0,0 +1,25 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.15 2007/06/19 23:47:16 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = dns dst
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in
new file mode 100644
index 0000000..e9e049e
--- /dev/null
+++ b/lib/dns/include/dns/Makefile.in
@@ -0,0 +1,54 @@
+# Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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: Makefile.in,v 1.55 2008/11/14 23:47:33 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+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 \
+ 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
+
+GENHEADERS = enumclass.h enumtype.h rdatastruct.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/dns
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/dns ; \
+ done
+ for i in ${GENHEADERS}; do \
+ ${INSTALL_DATA} $$i ${DESTDIR}${includedir}/dns ; \
+ done
diff --git a/lib/dns/include/dns/acache.h b/lib/dns/include/dns/acache.h
new file mode 100644
index 0000000..28990c2
--- /dev/null
+++ b/lib/dns/include/dns/acache.h
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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: acache.h,v 1.8 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_ACACHE_H
+#define DNS_ACACHE_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Acache
+ *
+ * The Additional Cache Object
+ *
+ * This module manages internal caching entries that correspond to
+ * the additional section data of a DNS DB node (an RRset header, more
+ * accurately). An additional cache entry is expected to be (somehow)
+ * attached to a particular RR in a particular DB node, and contains a set
+ * of information of an additional data for the DB node.
+ *
+ * An additional cache object is intended to be created as a per-view
+ * object, and manages all cache entries within the view.
+ *
+ * The intended usage of the additional caching is to provide a short cut
+ * to additional glue RRs of an NS RR. For each NS RR, it is often
+ * necessary to look for glue RRs to make a proper response. Once the
+ * glue RRs are known, the additional caching allows the client to
+ * associate the information to the original NS RR so that further
+ * expensive lookups can be avoided for the NS RR.
+ *
+ * Each additional cache entry contains information to identify a
+ * particular DB node and (optionally) an associated RRset. The
+ * information consists of its zone, database, the version of the
+ * database, database node, and RRset.
+ *
+ * A "negative" information can also be cached. For example, if a glue
+ * RR does not exist as an authoritative data in the same zone as that
+ * of the NS RR, this fact can be cached by specifying a NULL pointer
+ * for the database, version, and node. (See the description for
+ * dns_acache_getentry() below for more details.)
+ *
+ * Since each member stored in an additional cache entry holds a reference
+ * to a corresponding object, a stale cache entry may cause unnecessary
+ * memory consumption. For instance, when a zone is reloaded, additional
+ * cache entries that have a reference to the zone (and its DB and/or
+ * DB nodes) can delay the cleanup of the referred objects. In order to
+ * minimize such a bad effect, this module provides several cleanup
+ * mechanisms.
+ *
+ * The first one is a shutdown procedure called when the associated view
+ * is shut down. In this case, dns_acache_shutdown() will be called and
+ * all cache entries will be purged. This mechanism will help the
+ * situation when the configuration is reloaded or the main server is
+ * stopped.
+ *
+ * Per-DB cleanup mechanism is also provided. Each additional cache entry
+ * is associated with related DB, which is expected to have been
+ * registered when the DB was created by dns_acache_setdb(). If a
+ * particular DB is going to be destroyed, the primary holder of the DB,
+ * a typical example of which is a zone, will call dns_acache_putdb().
+ * Then this module will clean-up all cache entries associated with the
+ * DB. This mechanism is effective when a secondary zone DB is going to
+ * be stale after a zone transfer.
+ *
+ * Finally, this module supports for periodic clean-up of stale entries.
+ * Each cache entry has a timestamp field, which is updated every time
+ * the entry is referred. A periodically invoked cleaner checks the
+ * timestamp of each entry, and purge entries that have not been referred
+ * for a certain period. The cleaner interval can be specified by
+ * dns_acache_setcleaninginterval(). If the periodic clean-up is not
+ * enough, it is also possible to specify the upper limit of entries
+ * in terms of the memory consumption. If the maximum value is
+ * specified, the cleaner is invoked when the memory consumption reaches
+ * the high watermark inferred from the maximum value. In this case,
+ * the cleaner will use more aggressive algorithm to decide the "victim"
+ * entries. The maximum value can be specified by
+ * dns_acache_setcachesize().
+ *
+ * When a cache entry is going to be purged within this module, the
+ * callback function specified at the creation time will be called.
+ * The callback function is expected to release all internal resources
+ * related to the entry, which will typically be specific to DB
+ * implementation, and to call dns_acache_detachentry(). The callback
+ * mechanism is very important, since the holder of an additional cache
+ * entry may not be able to initiate the clean-up of the entry, due to
+ * the reference ordering. For example, as long as an additional cache
+ * entry has a reference to a DB object, the DB cannot be freed, in which
+ * a DB node may have a reference to the cache entry.
+ *
+ * Credits:
+ * The basic idea of this kind of short-cut for frequently used
+ * information is similar to the "pre-compiled answer" approach adopted
+ * in nsd by NLnet LABS with RIPE NCC. Our work here is an independent
+ * effort, but the success of nsd encouraged us to pursue this path.
+ *
+ * The design and implementation of the periodic memory management and
+ * the upper limitation of memory consumption was derived from the cache
+ * DB implementation of BIND9.
+ *
+ * MP:
+ * There are two main locks in this module. One is for each entry, and
+ * the other is for the additional cache object.
+ *
+ * Reliability:
+ * The callback function for a cache entry is called with holding the
+ * entry lock. Thus, it implicitly assumes the callback function does not
+ * call a function that can require the lock. Typically, the only
+ * function that can be called from the callback function safely is
+ * dns_acache_detachentry(). The breakage of this implicit assumption
+ * may cause a deadlock.
+ *
+ * Resources:
+ * In a 32-bit architecture (such as i386), the following additional
+ * memory is required comparing to the case that disables this module.
+ * - 76 bytes for each additional cache entry
+ * - if the entry has a DNS name and associated RRset,
+ * * 44 bytes + size of the name (1-255 bytes)
+ * * 52 bytes x number_of_RRs
+ * - 28 bytes for each DB related to this module
+ *
+ * Using the additional cache also requires extra memory consumption in
+ * the DB implementation. In the current implementation for rbtdb, we
+ * need:
+ * - two additional pointers for each DB node (8 bytes for a 32-bit
+ * architecture
+ * - for each RR associated to an RR in a DB node, we also need
+ * a pointer and management objects to support the additional cache
+ * function. These are allocated on-demand. The total size is
+ * 32 bytes for a 32-bit architecture.
+ *
+ * Security:
+ * Since this module does not handle any low-level data directly,
+ * no security issue specific to this module is anticipated.
+ *
+ * Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/mutex.h>
+#include <isc/lang.h>
+#include <isc/refcount.h>
+#include <isc/stdtime.h>
+
+#include <dns/types.h>
+
+/***
+ *** Functions
+ ***/
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_acache_create(dns_acache_t **acachep, isc_mem_t *mctx,
+ isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr);
+/*
+ * Create a new DNS additional cache object.
+ *
+ * Requires:
+ *
+ * 'mctx' is a valid memory context
+ *
+ * 'taskmgr' is a valid task manager
+ *
+ * 'timermgr' is a valid timer or NULL. If NULL, no periodic cleaning of
+ * the cache will take place.
+ *
+ * 'acachep' is a valid pointer, and *acachep == NULL
+ *
+ * Ensures:
+ *
+ * '*acachep' is attached to the newly created cache
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS
+ * ISC_R_NOMEMORY
+ * ISC_R_UNEXPECTED
+ */
+
+void
+dns_acache_attach(dns_acache_t *source, dns_acache_t **targetp);
+/*
+ * Attach *targetp to cache.
+ *
+ * Requires:
+ *
+ * 'acache' is a valid additional cache.
+ *
+ * 'targetp' points to a NULL dns_acache_t *.
+ *
+ * Ensures:
+ *
+ * *targetp is attached to the 'source' additional cache.
+ */
+
+void
+dns_acache_detach(dns_acache_t **acachep);
+/*
+ * Detach *acachep from its cache.
+ *
+ * Requires:
+ *
+ * '*acachep' points to a valid additional cache.
+ *
+ * Ensures:
+ *
+ * *acachep is NULL.
+ *
+ * If '*acachep' is the last reference to the cache and the additional
+ * cache does not have an outstanding task, all resources used by the
+ * cache will be freed.
+ */
+
+void
+dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t);
+/*
+ * Set the periodic cleaning interval of an additional cache to 'interval'
+ * seconds.
+ */
+
+void
+dns_acache_setcachesize(dns_acache_t *acache, isc_uint32_t size);
+/*
+ * Set the maximum additional cache size. 0 means unlimited.
+ */
+
+isc_result_t
+dns_acache_setdb(dns_acache_t *acache, dns_db_t *db);
+/*
+ * Set 'db' in 'acache' when the db can be referred from acache, in order
+ * to provide a hint for resolving the back reference.
+ *
+ * Requires:
+ * 'acache' is a valid acache pointer.
+ * 'db' is a valid DNS DB pointer.
+ *
+ * Ensures:
+ * 'acache' will have a reference to 'db'.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_EXISTS (which means the specified 'db' is already set)
+ * ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_acache_putdb(dns_acache_t *acache, dns_db_t *db);
+/*
+ * Release 'db' from 'acache' if it has been set by dns_acache_setdb().
+ *
+ * Requires:
+ * 'acache' is a valid acache pointer.
+ * 'db' is a valid DNS DB pointer.
+ *
+ * Ensures:
+ * 'acache' will release the reference to 'db'. Additionally, the content
+ * of each cache entry that is related to the 'db' will be released via
+ * the callback function.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOTFOUND (which means the specified 'db' is not set in 'acache')
+ * ISC_R_NOMEMORY
+ */
+
+void
+dns_acache_shutdown(dns_acache_t *acache);
+/*
+ * Shutdown 'acache'.
+ *
+ * Requires:
+ *
+ * '*acache' is a valid additional cache.
+ */
+
+isc_result_t
+dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb,
+ void (*callback)(dns_acacheentry_t *, void **),
+ void *cbarg, dns_acacheentry_t **entryp);
+/*
+ * Create an additional cache entry. A new entry is created and attached to
+ * the given additional cache object. A callback function is also associated
+ * with the created entry, which will be called when the cache entry is purged
+ * for some reason.
+ *
+ * Requires:
+ *
+ * 'acache' is a valid additional cache.
+ * 'entryp' is a valid pointer, and *entryp == NULL
+ * 'origdb' is a valid DNS DB pointer.
+ * 'callback' and 'cbarg' can be NULL. In this case, however, the entry
+ * is meaningless (and will be cleaned-up in the next periodical
+ * cleaning).
+ *
+ * Ensures:
+ * '*entryp' will point to a new additional cache entry.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_acache_getentry(dns_acacheentry_t *entry, dns_zone_t **zonep,
+ dns_db_t **dbp, dns_dbversion_t **versionp,
+ dns_dbnode_t **nodep, dns_name_t *fname,
+ dns_message_t *msg, isc_stdtime_t now);
+/*
+ * Get content from a particular additional cache entry.
+ *
+ * Requires:
+ *
+ * 'entry' is a valid additional cache entry.
+ * 'zonep' is a NULL pointer or '*zonep' == NULL (this is the only
+ * optional parameter.)
+ * 'dbp' is a valid pointer, and '*dbp' == NULL
+ * 'versionp' is a valid pointer, and '*versionp' == NULL
+ * 'nodep' is a valid pointer, and '*nodep' == NULL
+ * 'fname' is a valid DNS name.
+ * 'msg' is a valid DNS message.
+ *
+ * Ensures:
+ * Several possible cases can happen according to the content.
+ * 1. For a positive cache entry,
+ * '*zonep' will point to the corresponding zone (if zonep is a valid
+ * pointer),
+ * '*dbp' will point to a DB for the zone,
+ * '*versionp' will point to its version, and
+ * '*nodep' will point to the corresponding DB node.
+ * 'fname' will have the DNS name of the DB node and contain a list of
+ * rdataset for the node (which can be an empty list).
+ *
+ * 2. For a negative cache entry that means no corresponding zone exists,
+ * '*zonep' == NULL (if zonep is a valid pointer)
+ * '*dbp', '*versionp', and '*nodep' will be NULL.
+ *
+ * 3. For a negative cache entry that means no corresponding DB node
+ * exists, '*zonep' will point to the corresponding zone (if zonep is a
+ * valid pointer),
+ * '*dbp' will point to a corresponding DB for zone,
+ * '*versionp' will point to its version.
+ * '*nodep' will be kept as NULL.
+ * 'fname' will not change.
+ *
+ * On failure, no new references will be created.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_acache_setentry(dns_acache_t *acache, dns_acacheentry_t *entry,
+ dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
+ dns_dbnode_t *node, dns_name_t *fname);
+/*
+ * Set content to a particular additional cache entry.
+ *
+ * Requires:
+ * 'acache' is a valid additional cache.
+ * 'entry' is a valid additional cache entry.
+ * All the others pointers are NULL or a valid pointer of the
+ * corresponding type.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOMEMORY
+ * ISC_R_NOTFOUND
+ */
+
+void
+dns_acache_cancelentry(dns_acacheentry_t *entry);
+/*
+ * Cancel the use of the cache entry 'entry'. This function is supposed to
+ * be called when the node that holds the entry finds the content is not
+ * correct any more. This function will try to release as much dependency as
+ * possible, and will be ready to be cleaned-up. The registered callback
+ * function will be canceled and will never called.
+ *
+ * Requires:
+ * 'entry' is a valid additional cache entry.
+ */
+
+void
+dns_acache_attachentry(dns_acacheentry_t *source, dns_acacheentry_t **targetp);
+/*
+ * Attach *targetp to the cache entry 'source'.
+ *
+ * Requires:
+ *
+ * 'source' is a valid additional cache entry.
+ *
+ * 'targetp' points to a NULL dns_acacheentry_t *.
+ *
+ * Ensures:
+ *
+ * *targetp is attached to 'source'.
+ */
+
+void
+dns_acache_detachentry(dns_acacheentry_t **entryp);
+/*
+ * Detach *entryp from its cache.
+ *
+ * Requires:
+ *
+ * '*entryp' points to a valid additional cache entry.
+ *
+ * Ensures:
+ *
+ * *entryp is NULL.
+ *
+ * If '*entryp' is the last reference to the entry,
+ * cache does not have an outstanding task, all resources used by the
+ * entry (including the entry object itself) will be freed.
+ */
+
+void
+dns_acache_countquerymiss(dns_acache_t *acache);
+/*
+ * Count up a missed acache query. XXXMLG need more docs.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_ACACHE_H */
diff --git a/lib/dns/include/dns/acl.h b/lib/dns/include/dns/acl.h
new file mode 100644
index 0000000..94537a5
--- /dev/null
+++ b/lib/dns/include/dns/acl.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: acl.h,v 1.31 2007/12/21 06:46:47 marka Exp $ */
+
+#ifndef DNS_ACL_H
+#define DNS_ACL_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/acl.h
+ * \brief
+ * Address match list handling.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/netaddr.h>
+#include <isc/refcount.h>
+
+#include <dns/name.h>
+#include <dns/types.h>
+#include <dns/iptable.h>
+
+/***
+ *** Types
+ ***/
+
+typedef enum {
+ dns_aclelementtype_ipprefix,
+ dns_aclelementtype_keyname,
+ dns_aclelementtype_nestedacl,
+ dns_aclelementtype_localhost,
+ dns_aclelementtype_localnets,
+ dns_aclelementtype_any
+} dns_aclelemettype_t;
+
+typedef struct dns_aclipprefix dns_aclipprefix_t;
+
+struct dns_aclipprefix {
+ isc_netaddr_t address; /* IP4/IP6 */
+ unsigned int prefixlen;
+};
+
+struct dns_aclelement {
+ dns_aclelemettype_t type;
+ isc_boolean_t negative;
+ dns_name_t keyname;
+ dns_acl_t *nestedacl;
+ int node_num;
+};
+
+struct dns_acl {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_refcount_t refcount;
+ dns_iptable_t *iptable;
+#define node_count iptable->radix->num_added_node
+ dns_aclelement_t *elements;
+ isc_boolean_t has_negatives;
+ unsigned int alloc; /*%< Elements allocated */
+ unsigned int length; /*%< Elements initialized */
+ char *name; /*%< Temporary use only */
+ ISC_LINK(dns_acl_t) nextincache; /*%< Ditto */
+};
+
+struct dns_aclenv {
+ dns_acl_t *localhost;
+ dns_acl_t *localnets;
+ isc_boolean_t match_mapped;
+};
+
+#define DNS_ACL_MAGIC ISC_MAGIC('D','a','c','l')
+#define DNS_ACL_VALID(a) ISC_MAGIC_VALID(a, DNS_ACL_MAGIC)
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target);
+/*%<
+ * Create a new ACL, including an IP table and an array with room
+ * for 'n' ACL elements. The elements are uninitialized and the
+ * length is 0.
+ */
+
+isc_result_t
+dns_acl_any(isc_mem_t *mctx, dns_acl_t **target);
+/*%<
+ * Create a new ACL that matches everything.
+ */
+
+isc_result_t
+dns_acl_none(isc_mem_t *mctx, dns_acl_t **target);
+/*%<
+ * Create a new ACL that matches nothing.
+ */
+
+isc_boolean_t
+dns_acl_isany(dns_acl_t *acl);
+/*%<
+ * Test whether ACL is set to "{ any; }"
+ */
+
+isc_boolean_t
+dns_acl_isnone(dns_acl_t *acl);
+/*%<
+ * Test whether ACL is set to "{ none; }"
+ */
+
+isc_result_t
+dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos);
+/*%<
+ * Merge the contents of one ACL into another. Call dns_iptable_merge()
+ * for the IP tables, then concatenate the element arrays.
+ *
+ * If pos is set to false, then the nested ACL is to be negated. This
+ * means reverse the sense of each *positive* element or IP table node,
+ * but leave negatives alone, so as to prevent a double-negative causing
+ * an unexpected postive match in the parent ACL.
+ */
+
+void
+dns_acl_attach(dns_acl_t *source, dns_acl_t **target);
+
+void
+dns_acl_detach(dns_acl_t **aclp);
+
+isc_boolean_t
+dns_acl_isinsecure(const dns_acl_t *a);
+/*%<
+ * Return #ISC_TRUE iff the acl 'a' is considered insecure, that is,
+ * if it contains IP addresses other than those of the local host.
+ * This is intended for applications such as printing warning
+ * messages for suspect ACLs; it is not intended for making access
+ * control decisions. We make no guarantee that an ACL for which
+ * this function returns #ISC_FALSE is safe.
+ */
+
+isc_result_t
+dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env);
+/*%<
+ * Initialize ACL environment, setting up localhost and localnets ACLs
+ */
+
+void
+dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s);
+
+void
+dns_aclenv_destroy(dns_aclenv_t *env);
+
+isc_result_t
+dns_acl_match(const isc_netaddr_t *reqaddr,
+ const dns_name_t *reqsigner,
+ const dns_acl_t *acl,
+ const dns_aclenv_t *env,
+ int *match,
+ const dns_aclelement_t **matchelt);
+/*%<
+ * General, low-level ACL matching. This is expected to
+ * be useful even for weird stuff like the topology and sortlist statements.
+ *
+ * Match the address 'reqaddr', and optionally the key name 'reqsigner',
+ * against 'acl'. 'reqsigner' may be NULL.
+ *
+ * If there is a match, '*match' will be set to an integer whose absolute
+ * value corresponds to the order in which the matching value was inserted
+ * into the ACL. For a positive match, this value will be positive; for a
+ * negative match, it will be negative.
+ *
+ * If there is no match, *match will be set to zero.
+ *
+ * If there is a match in the element list (either positive or negative)
+ * and 'matchelt' is non-NULL, *matchelt will be pointed to the matching
+ * element.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Always succeeds.
+ */
+
+isc_boolean_t
+dns_aclelement_match(const isc_netaddr_t *reqaddr,
+ const dns_name_t *reqsigner,
+ const dns_aclelement_t *e,
+ const dns_aclenv_t *env,
+ const dns_aclelement_t **matchelt);
+/*%<
+ * Like dns_acl_match, but matches against the single ACL element 'e'
+ * rather than a complete ACL, and returns ISC_TRUE iff it matched.
+ *
+ * To determine whether the match was prositive or negative, the
+ * caller should examine e->negative. Since the element 'e' may be
+ * a reference to a named ACL or a nested ACL, a matching element
+ * returned through 'matchelt' is not necessarily 'e' itself.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_ACL_H */
diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h
new file mode 100644
index 0000000..d4ac40c
--- /dev/null
+++ b/lib/dns/include/dns/adb.h
@@ -0,0 +1,634 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: adb.h,v 1.85 2008/04/03 06:09:04 tbox Exp $ */
+
+#ifndef DNS_ADB_H
+#define DNS_ADB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/adb.h
+ *\brief
+ * DNS Address Database
+ *
+ * This module implements an address database (ADB) for mapping a name
+ * to an isc_sockaddr_t. It also provides statistical information on
+ * how good that address might be.
+ *
+ * A client will pass in a dns_name_t, and the ADB will walk through
+ * the rdataset looking up addresses associated with the name. If it
+ * is found on the internal lists, a structure is filled in with the
+ * address information and stats for found addresses.
+ *
+ * If the name cannot be found on the internal lists, a new entry will
+ * be created for a name if all the information needed can be found
+ * in the zone table or cache. This new address will then be returned.
+ *
+ * If a request must be made to remote servers to satisfy a name lookup,
+ * this module will start fetches to try to complete these addresses. When
+ * at least one more completes, an event is sent to the caller. If none of
+ * them resolve before the fetch times out, an event indicating this is
+ * sent instead.
+ *
+ * Records are stored internally until a timer expires. The timer is the
+ * smaller of the TTL or signature validity period.
+ *
+ * Lameness is stored per <qname,qtype> tuple, and this data hangs off each
+ * address field. When an address is marked lame for a given tuple the address
+ * will not be returned to a caller.
+ *
+ *
+ * MP:
+ *
+ *\li The ADB takes care of all necessary locking.
+ *
+ *\li Only the task which initiated the name lookup can cancel the lookup.
+ *
+ *
+ * Security:
+ *
+ *\li None, since all data stored is required to be pre-filtered.
+ * (Cache needs to be sane, fetches return bounds-checked and sanity-
+ * checked data, caller passes a good dns_name_t for the zone, etc)
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/sockaddr.h>
+
+#include <dns/types.h>
+#include <dns/view.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Magic number checks
+ ***/
+
+#define DNS_ADBFIND_MAGIC ISC_MAGIC('a','d','b','H')
+#define DNS_ADBFIND_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFIND_MAGIC)
+#define DNS_ADBADDRINFO_MAGIC ISC_MAGIC('a','d','A','I')
+#define DNS_ADBADDRINFO_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBADDRINFO_MAGIC)
+
+
+/***
+ *** TYPES
+ ***/
+
+typedef struct dns_adbname dns_adbname_t;
+
+/*!
+ *\brief
+ * Represents a lookup for a single name.
+ *
+ * On return, the client can safely use "list", and can reorder the list.
+ * Items may not be _deleted_ from this list, however, or added to it
+ * other than by using the dns_adb_*() API.
+ */
+struct dns_adbfind {
+ /* Public */
+ unsigned int magic; /*%< RO: magic */
+ dns_adbaddrinfolist_t list; /*%< RO: list of addrs */
+ unsigned int query_pending; /*%< RO: partial list */
+ unsigned int partial_result; /*%< RO: addrs missing */
+ unsigned int options; /*%< RO: options */
+ isc_result_t result_v4; /*%< RO: v4 result */
+ isc_result_t result_v6; /*%< RO: v6 result */
+ ISC_LINK(dns_adbfind_t) publink; /*%< RW: client use */
+
+ /* Private */
+ isc_mutex_t lock; /* locks all below */
+ in_port_t port;
+ int name_bucket;
+ unsigned int flags;
+ dns_adbname_t *adbname;
+ dns_adb_t *adb;
+ isc_event_t event;
+ ISC_LINK(dns_adbfind_t) plink;
+};
+
+/*
+ * _INET:
+ * _INET6:
+ * return addresses of that type.
+ *
+ * _EMPTYEVENT:
+ * Only schedule an event if no addresses are known.
+ * Must set _WANTEVENT for this to be meaningful.
+ *
+ * _WANTEVENT:
+ * An event is desired. Check this bit in the returned find to see
+ * if one will actually be generated.
+ *
+ * _AVOIDFETCHES:
+ * If set, fetches will not be generated unless no addresses are
+ * available in any of the address families requested.
+ *
+ * _STARTATZONE:
+ * Fetches will start using the closest zone data or use the root servers.
+ * This is useful for reestablishing glue that has expired.
+ *
+ * _GLUEOK:
+ * _HINTOK:
+ * Glue or hints are ok. These are used when matching names already
+ * in the adb, and when dns databases are searched.
+ *
+ * _RETURNLAME:
+ * Return lame servers in a find, so that all addresses are returned.
+ *
+ * _LAMEPRUNED:
+ * At least one address was omitted from the list because it was lame.
+ * This bit will NEVER be set if _RETURNLAME is set in the createfind().
+ */
+/*% Return addresses of type INET. */
+#define DNS_ADBFIND_INET 0x00000001
+/*% Return addresses of type INET6. */
+#define DNS_ADBFIND_INET6 0x00000002
+#define DNS_ADBFIND_ADDRESSMASK 0x00000003
+/*%
+ * Only schedule an event if no addresses are known.
+ * Must set _WANTEVENT for this to be meaningful.
+ */
+#define DNS_ADBFIND_EMPTYEVENT 0x00000004
+/*%
+ * An event is desired. Check this bit in the returned find to see
+ * if one will actually be generated.
+ */
+#define DNS_ADBFIND_WANTEVENT 0x00000008
+/*%
+ * If set, fetches will not be generated unless no addresses are
+ * available in any of the address families requested.
+ */
+#define DNS_ADBFIND_AVOIDFETCHES 0x00000010
+/*%
+ * Fetches will start using the closest zone data or use the root servers.
+ * This is useful for reestablishing glue that has expired.
+ */
+#define DNS_ADBFIND_STARTATZONE 0x00000020
+/*%
+ * Glue or hints are ok. These are used when matching names already
+ * in the adb, and when dns databases are searched.
+ */
+#define DNS_ADBFIND_GLUEOK 0x00000040
+/*%
+ * Glue or hints are ok. These are used when matching names already
+ * in the adb, and when dns databases are searched.
+ */
+#define DNS_ADBFIND_HINTOK 0x00000080
+/*%
+ * Return lame servers in a find, so that all addresses are returned.
+ */
+#define DNS_ADBFIND_RETURNLAME 0x00000100
+/*%
+ * Only schedule an event if no addresses are known.
+ * Must set _WANTEVENT for this to be meaningful.
+ */
+#define DNS_ADBFIND_LAMEPRUNED 0x00000200
+
+/*%
+ * The answers to queries come back as a list of these.
+ */
+struct dns_adbaddrinfo {
+ unsigned int magic; /*%< private */
+
+ isc_sockaddr_t sockaddr; /*%< [rw] */
+ unsigned int srtt; /*%< [rw] microseconds */
+ unsigned int flags; /*%< [rw] */
+ dns_adbentry_t *entry; /*%< private */
+ ISC_LINK(dns_adbaddrinfo_t) publink;
+};
+
+/*!<
+ * The event sent to the caller task is just a plain old isc_event_t. It
+ * contains no data other than a simple status, passed in the "type" field
+ * to indicate that another address resolved, or all partially resolved
+ * addresses have failed to resolve.
+ *
+ * "sender" is the dns_adbfind_t used to issue this query.
+ *
+ * This is simply a standard event, with the "type" set to:
+ *
+ *\li #DNS_EVENT_ADBMOREADDRESSES -- another address resolved.
+ *\li #DNS_EVENT_ADBNOMOREADDRESSES -- all pending addresses failed,
+ * were canceled, or otherwise will
+ * not be usable.
+ *\li #DNS_EVENT_ADBCANCELED -- The request was canceled by a
+ * 3rd party.
+ *\li #DNS_EVENT_ADBNAMEDELETED -- The name was deleted, so this request
+ * was canceled.
+ *
+ * In each of these cases, the addresses returned by the initial call
+ * to dns_adb_createfind() can still be used until they are no longer needed.
+ */
+
+/****
+ **** FUNCTIONS
+ ****/
+
+
+isc_result_t
+dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *tmgr,
+ isc_taskmgr_t *taskmgr, dns_adb_t **newadb);
+/*%<
+ * Create a new ADB.
+ *
+ * Notes:
+ *
+ *\li Generally, applications should not create an ADB directly, but
+ * should instead call dns_view_createresolver().
+ *
+ * Requires:
+ *
+ *\li 'mem' must be a valid memory context.
+ *
+ *\li 'view' be a pointer to a valid view.
+ *
+ *\li 'tmgr' be a pointer to a valid timer manager.
+ *
+ *\li 'taskmgr' be a pointer to a valid task manager.
+ *
+ *\li 'newadb' != NULL && '*newadb' == NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS after happiness.
+ *\li #ISC_R_NOMEMORY after resource allocation failure.
+ */
+
+void
+dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbp);
+/*%
+ * Attach to an 'adb' to 'adbp'.
+ *
+ * Requires:
+ *\li 'adb' to be a valid dns_adb_t, created via dns_adb_create().
+ *\li 'adbp' to be a valid pointer to a *dns_adb_t which is initialized
+ * to NULL.
+ */
+
+void
+dns_adb_detach(dns_adb_t **adb);
+/*%
+ * Delete the ADB. Sets *ADB to NULL. Cancels any outstanding requests.
+ *
+ * Requires:
+ *
+ *\li 'adb' be non-NULL and '*adb' be a valid dns_adb_t, created via
+ * dns_adb_create().
+ */
+
+void
+dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp);
+/*%
+ * Send '*eventp' to 'task' when 'adb' has shutdown.
+ *
+ * Requires:
+ *
+ *\li '*adb' is a valid dns_adb_t.
+ *
+ *\li eventp != NULL && *eventp is a valid event.
+ *
+ * Ensures:
+ *
+ *\li *eventp == NULL
+ *
+ *\li The event's sender field is set to the value of adb when the event
+ * is sent.
+ */
+
+void
+dns_adb_shutdown(dns_adb_t *adb);
+/*%<
+ * Shutdown 'adb'.
+ *
+ * Requires:
+ *
+ * \li '*adb' is a valid dns_adb_t.
+ */
+
+isc_result_t
+dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
+ void *arg, dns_name_t *name, dns_name_t *qname,
+ dns_rdatatype_t qtype, unsigned int options,
+ isc_stdtime_t now, dns_name_t *target,
+ in_port_t port, dns_adbfind_t **find);
+/*%<
+ * Main interface for clients. The adb will look up the name given in
+ * "name" and will build up a list of found addresses, and perhaps start
+ * internal fetches to resolve names that are unknown currently.
+ *
+ * If other addresses resolve after this call completes, an event will
+ * be sent to the <task, taskaction, arg> with the sender of that event
+ * set to a pointer to the dns_adbfind_t returned by this function.
+ *
+ * If no events will be generated, the *find->result_v4 and/or result_v6
+ * members may be examined for address lookup status. The usual #ISC_R_SUCCESS,
+ * #ISC_R_FAILURE, #DNS_R_NXDOMAIN, and #DNS_R_NXRRSET are returned, along with
+ * #ISC_R_NOTFOUND meaning the ADB has not _yet_ found the values. In this
+ * latter case, retrying may produce more addresses.
+ *
+ * If events will be returned, the result_v[46] members are only valid
+ * when that event is actually returned.
+ *
+ * The list of addresses returned is unordered. The caller must impose
+ * any ordering required. The list will not contain "known bad" addresses,
+ * however. For instance, it will not return hosts that are known to be
+ * lame for the zone in question.
+ *
+ * The caller cannot (directly) modify the contents of the address list's
+ * fields other than the "link" field. All values can be read at any
+ * time, however.
+ *
+ * The "now" parameter is used only for determining which entries that
+ * have a specific time to live or expire time should be removed from
+ * the running database. If specified as zero, the current time will
+ * be retrieved and used.
+ *
+ * If 'target' is not NULL and 'name' is an alias (i.e. the name is
+ * CNAME'd or DNAME'd to another name), then 'target' will be updated with
+ * the domain name that 'name' is aliased to.
+ *
+ * All addresses returned will have the sockaddr's port set to 'port.'
+ * The caller may change them directly in the dns_adbaddrinfo_t since
+ * they are copies of the internal address only.
+ *
+ * XXXMLG Document options, especially the flags which control how
+ * events are sent.
+ *
+ * Requires:
+ *
+ *\li *adb be a valid isc_adb_t object.
+ *
+ *\li If events are to be sent, *task be a valid task,
+ * and isc_taskaction_t != NULL.
+ *
+ *\li *name is a valid dns_name_t.
+ *
+ *\li qname != NULL and *qname be a valid dns_name_t.
+ *
+ *\li target == NULL or target is a valid name with a buffer.
+ *
+ *\li find != NULL && *find == NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS Addresses might have been returned, and events will be
+ * delivered for unresolved addresses.
+ *\li #ISC_R_NOMORE Addresses might have been returned, but no events
+ * will ever be posted for this context. This is only
+ * returned if task != NULL.
+ *\li #ISC_R_NOMEMORY insufficient resources
+ *\li #DNS_R_ALIAS 'name' is an alias for another name.
+ *
+ * Calls, and returns error codes from:
+ *
+ *\li isc_stdtime_get()
+ *
+ * Notes:
+ *
+ *\li No internal reference to "name" exists after this function
+ * returns.
+ */
+
+void
+dns_adb_cancelfind(dns_adbfind_t *find);
+/*%<
+ * Cancels the find, and sends the event off to the caller.
+ *
+ * It is an error to call dns_adb_cancelfind() on a find where
+ * no event is wanted, or will ever be sent.
+ *
+ * Note:
+ *
+ *\li It is possible that the real completion event was posted just
+ * before the dns_adb_cancelfind() call was made. In this case,
+ * dns_adb_cancelfind() will do nothing. The event callback needs
+ * to be prepared to find this situation (i.e. result is valid but
+ * the caller expects it to be canceled).
+ *
+ * Requires:
+ *
+ *\li 'find' be a valid dns_adbfind_t pointer.
+ *
+ *\li events would have been posted to the task. This can be checked
+ * with (find->options & DNS_ADBFIND_WANTEVENT).
+ *
+ * Ensures:
+ *
+ *\li The event was posted to the task.
+ */
+
+void
+dns_adb_destroyfind(dns_adbfind_t **find);
+/*%<
+ * Destroys the find reference.
+ *
+ * Note:
+ *
+ *\li This can only be called after the event was delivered for a
+ * find. Additionally, the event MUST have been freed via
+ * isc_event_free() BEFORE this function is called.
+ *
+ * Requires:
+ *
+ *\li 'find' != NULL and *find be valid dns_adbfind_t pointer.
+ *
+ * Ensures:
+ *
+ *\li No "address found" events will be posted to the originating task
+ * after this function returns.
+ */
+
+void
+dns_adb_dump(dns_adb_t *adb, FILE *f);
+/*%<
+ * This function is only used for debugging. It will dump as much of the
+ * state of the running system as possible.
+ *
+ * Requires:
+ *
+ *\li adb be valid.
+ *
+ *\li f != NULL, and is a file open for writing.
+ */
+
+void
+dns_adb_dumpfind(dns_adbfind_t *find, FILE *f);
+/*%<
+ * This function is only used for debugging. Dump the data associated
+ * with a find.
+ *
+ * Requires:
+ *
+ *\li find is valid.
+ *
+ * \li f != NULL, and is a file open for writing.
+ */
+
+isc_result_t
+dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname,
+ dns_rdatatype_t type, isc_stdtime_t expire_time);
+/*%<
+ * Mark the given address as lame for the <qname,qtype>. expire_time should
+ * be set to the time when the entry should expire. That is, if it is to
+ * expire 10 minutes in the future, it should set it to (now + 10 * 60).
+ *
+ * Requires:
+ *
+ *\li adb be valid.
+ *
+ *\li addr be valid.
+ *
+ *\li qname be the qname used in the dns_adb_createfind() call.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS -- all is well.
+ *\li #ISC_R_NOMEMORY -- could not mark address as lame.
+ */
+
+/*
+ * A reasonable default for RTT adjustments
+ */
+#define DNS_ADB_RTTADJDEFAULT 7 /*%< default scale */
+#define DNS_ADB_RTTADJREPLACE 0 /*%< replace with our rtt */
+#define DNS_ADB_RTTADJAGE 10 /*%< age this rtt */
+
+void
+dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
+ unsigned int rtt, unsigned int factor);
+/*%<
+ * Mix the round trip time into the existing smoothed rtt.
+
+ * The formula used
+ * (where srtt is the existing rtt value, and rtt and factor are arguments to
+ * this function):
+ *
+ *\code
+ * new_srtt = (old_srtt / 10 * factor) + (rtt / 10 * (10 - factor));
+ *\endcode
+ *
+ * XXXRTH Do we want to publish the formula? What if we want to change how
+ * this works later on? Recommend/require that the units are
+ * microseconds?
+ *
+ * Requires:
+ *
+ *\li adb be valid.
+ *
+ *\li addr be valid.
+ *
+ *\li 0 <= factor <= 10
+ *
+ * Note:
+ *
+ *\li The srtt in addr will be updated to reflect the new global
+ * srtt value. This may include changes made by others.
+ */
+
+void
+dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
+ unsigned int bits, unsigned int mask);
+/*%
+ * Change Flags.
+ *
+ * Set the flags as given by:
+ *
+ *\li newflags = (oldflags & ~mask) | (bits & mask);
+ *
+ * Requires:
+ *
+ *\li adb be valid.
+ *
+ *\li addr be valid.
+ */
+
+isc_result_t
+dns_adb_findaddrinfo(dns_adb_t *adb, isc_sockaddr_t *sa,
+ dns_adbaddrinfo_t **addrp, isc_stdtime_t now);
+/*%<
+ * Return a dns_adbaddrinfo_t that is associated with address 'sa'.
+ *
+ * Requires:
+ *
+ *\li adb is valid.
+ *
+ *\li sa is valid.
+ *
+ *\li addrp != NULL && *addrp == NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_SHUTTINGDOWN
+ */
+
+void
+dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp);
+/*%<
+ * Free a dns_adbaddrinfo_t allocated by dns_adb_findaddrinfo().
+ *
+ * Requires:
+ *
+ *\li adb is valid.
+ *
+ *\li *addrp is a valid dns_adbaddrinfo_t *.
+ */
+
+void
+dns_adb_flush(dns_adb_t *adb);
+/*%<
+ * Flushes all cached data from the adb.
+ *
+ * Requires:
+ *\li adb is valid.
+ */
+
+void
+dns_adb_setadbsize(dns_adb_t *adb, isc_uint32_t size);
+/*%<
+ * Set a target memory size. If memory usage exceeds the target
+ * size entries will be removed before they would have expired on
+ * a random basis.
+ *
+ * If 'size' is 0 then memory usage is unlimited.
+ *
+ * Requires:
+ *\li 'adb' is valid.
+ */
+
+void
+dns_adb_flushname(dns_adb_t *adb, dns_name_t *name);
+/*%<
+ * Flush 'name' from the adb cache.
+ *
+ * Requires:
+ *\li 'adb' is valid.
+ *\li 'name' is valid.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_ADB_H */
diff --git a/lib/dns/include/dns/bit.h b/lib/dns/include/dns/bit.h
new file mode 100644
index 0000000..28c733d
--- /dev/null
+++ b/lib/dns/include/dns/bit.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004-2007 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: bit.h,v 1.14 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_BIT_H
+#define DNS_BIT_H 1
+
+/*! \file dns/bit.h */
+
+#include <isc/int.h>
+#include <isc/boolean.h>
+
+typedef isc_uint64_t dns_bitset_t;
+
+#define DNS_BIT_SET(bit, bitset) \
+ (*(bitset) |= ((dns_bitset_t)1 << (bit)))
+#define DNS_BIT_CLEAR(bit, bitset) \
+ (*(bitset) &= ~((dns_bitset_t)1 << (bit)))
+#define DNS_BIT_CHECK(bit, bitset) \
+ ISC_TF((*(bitset) & ((dns_bitset_t)1 << (bit))) \
+ == ((dns_bitset_t)1 << (bit)))
+
+#endif /* DNS_BIT_H */
+
diff --git a/lib/dns/include/dns/byaddr.h b/lib/dns/include/dns/byaddr.h
new file mode 100644
index 0000000..edf8430
--- /dev/null
+++ b/lib/dns/include/dns/byaddr.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2004-2007 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: byaddr.h,v 1.22 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_BYADDR_H
+#define DNS_BYADDR_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/byaddr.h
+ * \brief
+ * The byaddr module provides reverse lookup services for IPv4 and IPv6
+ * addresses.
+ *
+ * MP:
+ *\li The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li RFCs: 1034, 1035, 2181, TBS
+ *\li Drafts: TBS
+ */
+
+#include <isc/lang.h>
+#include <isc/event.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * A 'dns_byaddrevent_t' is returned when a byaddr completes.
+ * The sender field will be set to the byaddr that completed. If 'result'
+ * is ISC_R_SUCCESS, then 'names' will contain a list of names associated
+ * with the address. The recipient of the event must not change the list
+ * and must not refer to any of the name data after the event is freed.
+ */
+typedef struct dns_byaddrevent {
+ ISC_EVENT_COMMON(struct dns_byaddrevent);
+ isc_result_t result;
+ dns_namelist_t names;
+} dns_byaddrevent_t;
+
+/*
+ * This option is deprecated since we now only consider nibbles.
+#define DNS_BYADDROPT_IPV6NIBBLE 0x0001
+ */
+/*% Note DNS_BYADDROPT_IPV6NIBBLE is now deprecated. */
+#define DNS_BYADDROPT_IPV6INT 0x0002
+
+isc_result_t
+dns_byaddr_create(isc_mem_t *mctx, isc_netaddr_t *address, dns_view_t *view,
+ unsigned int options, isc_task_t *task,
+ isc_taskaction_t action, void *arg, dns_byaddr_t **byaddrp);
+/*%<
+ * Find the domain name of 'address'.
+ *
+ * Notes:
+ *
+ *\li There is a reverse lookup format for IPv6 addresses, 'nibble'
+ *
+ *\li The 'nibble' format for that address is
+ *
+ * \code
+ * 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa.
+ * \endcode
+ *
+ *\li #DNS_BYADDROPT_IPV6INT can be used to get nibble lookups under ip6.int.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid mctx.
+ *
+ *\li 'address' is a valid IPv4 or IPv6 address.
+ *
+ *\li 'view' is a valid view which has a resolver.
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li byaddrp != NULL && *byaddrp == NULL
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *
+ *\li Any resolver-related error (e.g. #ISC_R_SHUTTINGDOWN) may also be
+ * returned.
+ */
+
+void
+dns_byaddr_cancel(dns_byaddr_t *byaddr);
+/*%<
+ * Cancel 'byaddr'.
+ *
+ * Notes:
+ *
+ *\li If 'byaddr' has not completed, post its #DNS_EVENT_BYADDRDONE
+ * event with a result code of #ISC_R_CANCELED.
+ *
+ * Requires:
+ *
+ *\li 'byaddr' is a valid byaddr.
+ */
+
+void
+dns_byaddr_destroy(dns_byaddr_t **byaddrp);
+/*%<
+ * Destroy 'byaddr'.
+ *
+ * Requires:
+ *
+ *\li '*byaddrp' is a valid byaddr.
+ *
+ *\li The caller has received the #DNS_EVENT_BYADDRDONE event (either because
+ * the byaddr completed or because dns_byaddr_cancel() was called).
+ *
+ * Ensures:
+ *
+ *\li *byaddrp == NULL.
+ */
+
+isc_result_t
+dns_byaddr_createptrname(isc_netaddr_t *address, isc_boolean_t nibble,
+ dns_name_t *name);
+
+isc_result_t
+dns_byaddr_createptrname2(isc_netaddr_t *address, unsigned int options,
+ dns_name_t *name);
+/*%<
+ * Creates a name that would be used in a PTR query for this address. The
+ * nibble flag indicates that the 'nibble' format is to be used if an IPv6
+ * address is provided, instead of the 'bitstring' format. Since we dropped
+ * the support of the bitstring labels, it is expected that the flag is always
+ * set. 'options' are the same as for dns_byaddr_create().
+ *
+ * Requires:
+ *
+ * \li 'address' is a valid address.
+ * \li 'name' is a valid name with a dedicated buffer.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_BYADDR_H */
diff --git a/lib/dns/include/dns/cache.h b/lib/dns/include/dns/cache.h
new file mode 100644
index 0000000..7b37235
--- /dev/null
+++ b/lib/dns/include/dns/cache.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: cache.h,v 1.26 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_CACHE_H
+#define DNS_CACHE_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/cache.h
+ * \brief
+ * Defines dns_cache_t, the cache object.
+ *
+ * Notes:
+ *\li A cache object contains DNS data of a single class.
+ * Multiple classes will be handled by creating multiple
+ * views, each with a different class and its own cache.
+ *
+ * MP:
+ *\li See notes at the individual functions.
+ *
+ * Reliability:
+ *
+ * Resources:
+ *
+ * Security:
+ *
+ * Standards:
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/stdtime.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+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);
+/*%<
+ * Create a new DNS cache.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context
+ *
+ *\li 'taskmgr' is a valid task manager and 'timermgr' is a valid timer
+ * manager, or both are NULL. If NULL, no periodic cleaning of the
+ * cache will take place.
+ *
+ *\li 'cachep' is a valid pointer, and *cachep == NULL
+ *
+ * Ensures:
+ *
+ *\li '*cachep' is attached to the newly created cache
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+dns_cache_attach(dns_cache_t *cache, dns_cache_t **targetp);
+/*%<
+ * Attach *targetp to cache.
+ *
+ * Requires:
+ *
+ *\li 'cache' is a valid cache.
+ *
+ *\li 'targetp' points to a NULL dns_cache_t *.
+ *
+ * Ensures:
+ *
+ *\li *targetp is attached to cache.
+ */
+
+void
+dns_cache_detach(dns_cache_t **cachep);
+/*%<
+ * Detach *cachep from its cache.
+ *
+ * Requires:
+ *
+ *\li 'cachep' points to a valid cache.
+ *
+ * Ensures:
+ *
+ *\li *cachep is NULL.
+ *
+ *\li If '*cachep' is the last reference to the cache,
+ * all resources used by the cache will be freed
+ */
+
+void
+dns_cache_attachdb(dns_cache_t *cache, dns_db_t **dbp);
+/*%<
+ * Attach *dbp to the cache's database.
+ *
+ * Notes:
+ *
+ *\li This may be used to get a reference to the database for
+ * the purpose of cache lookups (XXX currently it is also
+ * the way to add data to the cache, but having a
+ * separate dns_cache_add() interface instead would allow
+ * more control over memory usage).
+ * The caller should call dns_db_detach() on the reference
+ * when it is no longer needed.
+ *
+ * Requires:
+ *
+ *\li 'cache' is a valid cache.
+ *
+ *\li 'dbp' points to a NULL dns_db *.
+ *
+ * Ensures:
+ *
+ *\li *dbp is attached to the database.
+ */
+
+
+isc_result_t
+dns_cache_setfilename(dns_cache_t *cache, const char *filename);
+/*%<
+ * If 'filename' is non-NULL, make the cache persistent.
+ * The cache's data will be stored in the given file.
+ * If 'filename' is NULL, make the cache non-persistent.
+ * Files that are no longer used are not unlinked automatically.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li Various file-related failures
+ */
+
+isc_result_t
+dns_cache_load(dns_cache_t *cache);
+/*%<
+ * If the cache has a file name, load the cache contents from the file.
+ * Previous cache contents are not discarded.
+ * If no file name has been set, do nothing and return success.
+ *
+ * MT:
+ *\li Multiple simultaneous attempts to load or dump the cache
+ * will be serialized with respect to one another, but
+ * the cache may be read and updated while the dump is
+ * in progress. Updates performed during loading
+ * may or may not be preserved, and reads may return
+ * either the old or the newly loaded data.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ * \li Various failures depending on the database implementation type
+ */
+
+isc_result_t
+dns_cache_dump(dns_cache_t *cache);
+/*%<
+ * If the cache has a file name, write the cache contents to disk,
+ * overwriting any preexisting file. If no file name has been set,
+ * do nothing and return success.
+ *
+ * MT:
+ *\li Multiple simultaneous attempts to load or dump the cache
+ * will be serialized with respect to one another, but
+ * the cache may be read and updated while the dump is
+ * in progress. Updates performed during the dump may
+ * or may not be reflected in the dumped file.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ * \li Various failures depending on the database implementation type
+ */
+
+isc_result_t
+dns_cache_clean(dns_cache_t *cache, isc_stdtime_t now);
+/*%<
+ * Force immediate cleaning of the cache, freeing all rdatasets
+ * whose TTL has expired as of 'now' and that have no pending
+ * references.
+ */
+
+void
+dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int interval);
+/*%<
+ * Set the periodic cache cleaning interval to 'interval' seconds.
+ */
+
+void
+dns_cache_setcachesize(dns_cache_t *cache, isc_uint32_t size);
+/*%<
+ * Set the maximum cache size. 0 means unlimited.
+ */
+
+isc_result_t
+dns_cache_flush(dns_cache_t *cache);
+/*%<
+ * Flushes all data from the cache.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_cache_flushname(dns_cache_t *cache, dns_name_t *name);
+/*
+ * Flushes a given name from the cache.
+ *
+ * Requires:
+ *\li 'cache' to be valid.
+ *\li 'name' to be valid.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li other error returns.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_CACHE_H */
diff --git a/lib/dns/include/dns/callbacks.h b/lib/dns/include/dns/callbacks.h
new file mode 100644
index 0000000..8a8385a
--- /dev/null
+++ b/lib/dns/include/dns/callbacks.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: callbacks.h,v 1.24 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_CALLBACKS_H
+#define DNS_CALLBACKS_H 1
+
+/*! \file dns/callbacks.h */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+struct dns_rdatacallbacks {
+ /*%
+ * dns_load_master calls this when it has rdatasets to commit.
+ */
+ dns_addrdatasetfunc_t add;
+ /*%
+ * dns_load_master / dns_rdata_fromtext call this to issue a error.
+ */
+ void (*error)(struct dns_rdatacallbacks *, const char *, ...);
+ /*%
+ * dns_load_master / dns_rdata_fromtext call this to issue a warning.
+ */
+ void (*warn)(struct dns_rdatacallbacks *, const char *, ...);
+ /*%
+ * Private data handles for use by the above callback functions.
+ */
+ void *add_private;
+ void *error_private;
+ void *warn_private;
+};
+
+/***
+ *** Initialization
+ ***/
+
+void
+dns_rdatacallbacks_init(dns_rdatacallbacks_t *callbacks);
+/*%<
+ * Initialize 'callbacks'.
+ *
+ *
+ * \li 'error' and 'warn' are set to default callbacks that print the
+ * error message through the DNS library log context.
+ *
+ *\li All other elements are initialized to NULL.
+ *
+ * Requires:
+ * \li 'callbacks' is a valid dns_rdatacallbacks_t,
+ */
+
+void
+dns_rdatacallbacks_init_stdio(dns_rdatacallbacks_t *callbacks);
+/*%<
+ * Like dns_rdatacallbacks_init, but logs to stdio.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_CALLBACKS_H */
diff --git a/lib/dns/include/dns/cert.h b/lib/dns/include/dns/cert.h
new file mode 100644
index 0000000..1cda848
--- /dev/null
+++ b/lib/dns/include/dns/cert.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: cert.h,v 1.19 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_CERT_H
+#define DNS_CERT_H 1
+
+/*! \file dns/cert.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_cert_fromtext(dns_cert_t *certp, isc_textregion_t *source);
+/*%<
+ * Convert the text 'source' refers to into a certificate type.
+ * The text may contain either a mnemonic type name or a decimal type number.
+ *
+ * Requires:
+ *\li 'certp' is a valid pointer.
+ *
+ *\li 'source' is a valid text region.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #ISC_R_RANGE numeric type is out of range
+ *\li #DNS_R_UNKNOWN mnemonic type is unknown
+ */
+
+isc_result_t
+dns_cert_totext(dns_cert_t cert, isc_buffer_t *target);
+/*%<
+ * Put a textual representation of certificate type 'cert' into 'target'.
+ *
+ * Requires:
+ *\li 'cert' is a valid cert.
+ *
+ *\li 'target' is a valid text buffer.
+ *
+ * Ensures:
+ *\li If the result is success:
+ * The used space in 'target' is updated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #ISC_R_NOSPACE target buffer is too small
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_CERT_H */
diff --git a/lib/dns/include/dns/compress.h b/lib/dns/include/dns/compress.h
new file mode 100644
index 0000000..0b2c9c3
--- /dev/null
+++ b/lib/dns/include/dns/compress.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: compress.h,v 1.40 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_COMPRESS_H
+#define DNS_COMPRESS_H 1
+
+#include <isc/lang.h>
+#include <isc/region.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+#define DNS_COMPRESS_NONE 0x00 /*%< no compression */
+#define DNS_COMPRESS_GLOBAL14 0x01 /*%< "normal" compression. */
+#define DNS_COMPRESS_ALL 0x01 /*%< all compression. */
+#define DNS_COMPRESS_CASESENSITIVE 0x02 /*%< case sensitive compression. */
+
+/*! \file dns/compress.h
+ * Direct manipulation of the structures is strongly discouraged.
+ */
+
+#define DNS_COMPRESS_TABLESIZE 64
+#define DNS_COMPRESS_INITIALNODES 16
+
+typedef struct dns_compressnode dns_compressnode_t;
+
+struct dns_compressnode {
+ isc_region_t r;
+ isc_uint16_t offset;
+ isc_uint16_t count;
+ isc_uint8_t labels;
+ dns_compressnode_t *next;
+};
+
+struct dns_compress {
+ unsigned int magic; /*%< Magic number. */
+ unsigned int allowed; /*%< Allowed methods. */
+ int edns; /*%< Edns version or -1. */
+ /*% Global compression table. */
+ dns_compressnode_t *table[DNS_COMPRESS_TABLESIZE];
+ /*% Preallocated nodes for the table. */
+ dns_compressnode_t initialnodes[DNS_COMPRESS_INITIALNODES];
+ isc_uint16_t count; /*%< Number of nodes. */
+ isc_mem_t *mctx; /*%< Memory context. */
+};
+
+typedef enum {
+ DNS_DECOMPRESS_ANY, /*%< Any compression */
+ DNS_DECOMPRESS_STRICT, /*%< Allowed compression */
+ DNS_DECOMPRESS_NONE /*%< No compression */
+} dns_decompresstype_t;
+
+struct dns_decompress {
+ unsigned int magic; /*%< Magic number. */
+ unsigned int allowed; /*%< Allowed methods. */
+ int edns; /*%< Edns version or -1. */
+ dns_decompresstype_t type; /*%< Strict checking */
+};
+
+isc_result_t
+dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx);
+/*%<
+ * Inialise the compression context structure pointed to by 'cctx'.
+ *
+ * Requires:
+ * \li 'cctx' is a valid dns_compress_t structure.
+ * \li 'mctx' is an initialized memory context.
+ * Ensures:
+ * \li cctx->global is initialized.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li failures from dns_rbt_create()
+ */
+
+void
+dns_compress_invalidate(dns_compress_t *cctx);
+
+/*%<
+ * Invalidate the compression structure pointed to by cctx.
+ *
+ * Requires:
+ *\li 'cctx' to be initialized.
+ */
+
+void
+dns_compress_setmethods(dns_compress_t *cctx, unsigned int allowed);
+
+/*%<
+ * Sets allowed compression methods.
+ *
+ * Requires:
+ *\li 'cctx' to be initialized.
+ */
+
+unsigned int
+dns_compress_getmethods(dns_compress_t *cctx);
+
+/*%<
+ * Gets allowed compression methods.
+ *
+ * Requires:
+ *\li 'cctx' to be initialized.
+ *
+ * Returns:
+ *\li allowed compression bitmap.
+ */
+
+void
+dns_compress_setsensitive(dns_compress_t *cctx, isc_boolean_t sensitive);
+
+/*
+ * Preserve the case of compressed domain names.
+ *
+ * Requires:
+ * 'cctx' to be initialized.
+ */
+
+isc_boolean_t
+dns_compress_getsensitive(dns_compress_t *cctx);
+/*
+ * Return whether case is to be preservered when compressing
+ * domain names.
+ *
+ * Requires:
+ * 'cctx' to be initialized.
+ */
+
+int
+dns_compress_getedns(dns_compress_t *cctx);
+
+/*%<
+ * Gets edns value.
+ *
+ * Requires:
+ *\li 'cctx' to be initialized.
+ *
+ * Returns:
+ *\li -1 .. 255
+ */
+
+isc_boolean_t
+dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name,
+ dns_name_t *prefix, isc_uint16_t *offset);
+/*%<
+ * Finds longest possible match of 'name' in the global compression table.
+ *
+ * Requires:
+ *\li 'cctx' to be initialized.
+ *\li 'name' to be a absolute name.
+ *\li 'prefix' to be initialized.
+ *\li 'offset' to point to an isc_uint16_t.
+ *
+ * Ensures:
+ *\li 'prefix' and 'offset' are valid if ISC_TRUE is returned.
+ *
+ * Returns:
+ *\li #ISC_TRUE / #ISC_FALSE
+ */
+
+void
+dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
+ const dns_name_t *prefix, isc_uint16_t offset);
+/*%<
+ * Add compression pointers for 'name' to the compression table,
+ * not replacing existing pointers.
+ *
+ * Requires:
+ *\li 'cctx' initialized
+ *
+ *\li 'name' must be initialized and absolute, and must remain
+ * valid until the message compression is complete.
+ *
+ *\li 'prefix' must be a prefix returned by
+ * dns_compress_findglobal(), or the same as 'name'.
+ */
+
+void
+dns_compress_rollback(dns_compress_t *cctx, isc_uint16_t offset);
+
+/*%<
+ * Remove any compression pointers from global table >= offset.
+ *
+ * Requires:
+ *\li 'cctx' is initialized.
+ */
+
+void
+dns_decompress_init(dns_decompress_t *dctx, int edns,
+ dns_decompresstype_t type);
+
+/*%<
+ * Initializes 'dctx'.
+ * Records 'edns' and 'type' into the structure.
+ *
+ * Requires:
+ *\li 'dctx' to be a valid pointer.
+ */
+
+void
+dns_decompress_invalidate(dns_decompress_t *dctx);
+
+/*%<
+ * Invalidates 'dctx'.
+ *
+ * Requires:
+ *\li 'dctx' to be initialized
+ */
+
+void
+dns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed);
+
+/*%<
+ * Sets 'dctx->allowed' to 'allowed'.
+ *
+ * Requires:
+ *\li 'dctx' to be initialized
+ */
+
+unsigned int
+dns_decompress_getmethods(dns_decompress_t *dctx);
+
+/*%<
+ * Returns 'dctx->allowed'
+ *
+ * Requires:
+ *\li 'dctx' to be initialized
+ */
+
+int
+dns_decompress_edns(dns_decompress_t *dctx);
+
+/*%<
+ * Returns 'dctx->edns'
+ *
+ * Requires:
+ *\li 'dctx' to be initialized
+ */
+
+dns_decompresstype_t
+dns_decompress_type(dns_decompress_t *dctx);
+
+/*%<
+ * Returns 'dctx->type'
+ *
+ * Requires:
+ *\li 'dctx' to be initialized
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_COMPRESS_H */
diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h
new file mode 100644
index 0000000..8e22463
--- /dev/null
+++ b/lib/dns/include/dns/db.h
@@ -0,0 +1,1477 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: db.h,v 1.93 2008/09/24 02:46:22 marka Exp $ */
+
+#ifndef DNS_DB_H
+#define DNS_DB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/db.h
+ * \brief
+ * The DNS DB interface allows named rdatasets to be stored and retrieved.
+ *
+ * The dns_db_t type is like a "virtual class". To actually use
+ * DBs, an implementation of the class is required.
+ *
+ * XXX more XXX
+ *
+ * MP:
+ * \li The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ *
+ * Reliability:
+ * \li No anticipated impact.
+ *
+ * Resources:
+ * \li TBS
+ *
+ * Security:
+ * \li No anticipated impact.
+ *
+ * Standards:
+ * \li None.
+ */
+
+/*****
+ ***** Imports
+ *****/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/ondestroy.h>
+#include <isc/stdtime.h>
+
+#include <dns/name.h>
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Types
+ *****/
+
+typedef struct dns_dbmethods {
+ void (*attach)(dns_db_t *source, dns_db_t **targetp);
+ void (*detach)(dns_db_t **dbp);
+ isc_result_t (*beginload)(dns_db_t *db, dns_addrdatasetfunc_t *addp,
+ dns_dbload_t **dbloadp);
+ isc_result_t (*endload)(dns_db_t *db, dns_dbload_t **dbloadp);
+ isc_result_t (*dump)(dns_db_t *db, dns_dbversion_t *version,
+ const char *filename,
+ dns_masterformat_t masterformat);
+ void (*currentversion)(dns_db_t *db,
+ dns_dbversion_t **versionp);
+ isc_result_t (*newversion)(dns_db_t *db,
+ dns_dbversion_t **versionp);
+ void (*attachversion)(dns_db_t *db, dns_dbversion_t *source,
+ dns_dbversion_t **targetp);
+ void (*closeversion)(dns_db_t *db,
+ dns_dbversion_t **versionp,
+ isc_boolean_t commit);
+ isc_result_t (*findnode)(dns_db_t *db, dns_name_t *name,
+ isc_boolean_t create,
+ dns_dbnode_t **nodep);
+ 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);
+ 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);
+ void (*attachnode)(dns_db_t *db,
+ dns_dbnode_t *source,
+ dns_dbnode_t **targetp);
+ void (*detachnode)(dns_db_t *db,
+ dns_dbnode_t **targetp);
+ isc_result_t (*expirenode)(dns_db_t *db, dns_dbnode_t *node,
+ isc_stdtime_t now);
+ void (*printnode)(dns_db_t *db, dns_dbnode_t *node,
+ FILE *out);
+ isc_result_t (*createiterator)(dns_db_t *db, unsigned int options,
+ dns_dbiterator_t **iteratorp);
+ isc_result_t (*findrdataset)(dns_db_t *db, dns_dbnode_t *node,
+ dns_dbversion_t *version,
+ dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ isc_stdtime_t now,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset);
+ isc_result_t (*allrdatasets)(dns_db_t *db, dns_dbnode_t *node,
+ dns_dbversion_t *version,
+ isc_stdtime_t now,
+ dns_rdatasetiter_t **iteratorp);
+ 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);
+ 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);
+ isc_result_t (*deleterdataset)(dns_db_t *db, dns_dbnode_t *node,
+ dns_dbversion_t *version,
+ dns_rdatatype_t type,
+ dns_rdatatype_t covers);
+ isc_boolean_t (*issecure)(dns_db_t *db);
+ unsigned int (*nodecount)(dns_db_t *db);
+ isc_boolean_t (*ispersistent)(dns_db_t *db);
+ void (*overmem)(dns_db_t *db, isc_boolean_t overmem);
+ void (*settask)(dns_db_t *db, isc_task_t *);
+ isc_result_t (*getoriginnode)(dns_db_t *db, dns_dbnode_t **nodep);
+ void (*transfernode)(dns_db_t *db, dns_dbnode_t **sourcep,
+ dns_dbnode_t **targetp);
+ isc_result_t (*getnsec3parameters)(dns_db_t *db,
+ dns_dbversion_t *version,
+ dns_hash_t *hash,
+ isc_uint8_t *flags,
+ isc_uint16_t *iterations,
+ unsigned char *salt,
+ size_t *salt_len);
+ isc_result_t (*findnsec3node)(dns_db_t *db, dns_name_t *name,
+ isc_boolean_t create,
+ dns_dbnode_t **nodep);
+ isc_result_t (*setsigningtime)(dns_db_t *db,
+ dns_rdataset_t *rdataset,
+ isc_stdtime_t resign);
+ isc_result_t (*getsigningtime)(dns_db_t *db,
+ dns_rdataset_t *rdataset,
+ dns_name_t *name);
+ void (*resigned)(dns_db_t *db, dns_rdataset_t *rdataset,
+ dns_dbversion_t *version);
+ isc_boolean_t (*isdnssec)(dns_db_t *db);
+ dns_stats_t *(*getrrsetstats)(dns_db_t *db);
+} dns_dbmethods_t;
+
+typedef isc_result_t
+(*dns_dbcreatefunc_t)(isc_mem_t *mctx, dns_name_t *name,
+ dns_dbtype_t type, dns_rdataclass_t rdclass,
+ unsigned int argc, char *argv[], void *driverarg,
+ dns_db_t **dbp);
+
+#define DNS_DB_MAGIC ISC_MAGIC('D','N','S','D')
+#define DNS_DB_VALID(db) ISC_MAGIC_VALID(db, DNS_DB_MAGIC)
+
+/*%
+ * This structure is actually just the common prefix of a DNS db
+ * implementation's version of a dns_db_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden. DB implementations
+ * may change the structure. 'magic' must be DNS_DB_MAGIC for any of the
+ * dns_db_ routines to work. DB implementations must maintain all DB
+ * invariants.
+ */
+struct dns_db {
+ unsigned int magic;
+ unsigned int impmagic;
+ dns_dbmethods_t * methods;
+ isc_uint16_t attributes;
+ dns_rdataclass_t rdclass;
+ dns_name_t origin;
+ isc_ondestroy_t ondest;
+ isc_mem_t * mctx;
+};
+
+#define DNS_DBATTR_CACHE 0x01
+#define DNS_DBATTR_STUB 0x02
+
+/*@{*/
+/*%
+ * Options that can be specified for dns_db_find().
+ */
+#define DNS_DBFIND_GLUEOK 0x01
+#define DNS_DBFIND_VALIDATEGLUE 0x02
+#define DNS_DBFIND_NOWILD 0x04
+#define DNS_DBFIND_PENDINGOK 0x08
+#define DNS_DBFIND_NOEXACT 0x10
+#define DNS_DBFIND_FORCENSEC 0x20
+#define DNS_DBFIND_COVERINGNSEC 0x40
+#define DNS_DBFIND_FORCENSEC3 0x80
+/*@}*/
+
+/*@{*/
+/*%
+ * Options that can be specified for dns_db_addrdataset().
+ */
+#define DNS_DBADD_MERGE 0x01
+#define DNS_DBADD_FORCE 0x02
+#define DNS_DBADD_EXACT 0x04
+#define DNS_DBADD_EXACTTTL 0x08
+/*@}*/
+
+/*%
+ * Options that can be specified for dns_db_subtractrdataset().
+ */
+#define DNS_DBSUB_EXACT 0x01
+
+/*@{*/
+/*%
+ * Iterator options
+ */
+#define DNS_DB_RELATIVENAMES 0x1
+#define DNS_DB_NSEC3ONLY 0x2
+#define DNS_DB_NONSEC3 0x4
+/*@}*/
+
+/*****
+ ***** Methods
+ *****/
+
+/***
+ *** Basic DB Methods
+ ***/
+
+isc_result_t
+dns_db_create(isc_mem_t *mctx, const char *db_type, dns_name_t *origin,
+ dns_dbtype_t type, dns_rdataclass_t rdclass,
+ unsigned int argc, char *argv[], dns_db_t **dbp);
+/*%<
+ * Create a new database using implementation 'db_type'.
+ *
+ * Notes:
+ * \li All names in the database must be subdomains of 'origin' and in class
+ * 'rdclass'. The database makes its own copy of the origin, so the
+ * caller may do whatever they like with 'origin' and its storage once the
+ * call returns.
+ *
+ * \li DB implementation-specific parameters are passed using argc and argv.
+ *
+ * Requires:
+ *
+ * \li dbp != NULL and *dbp == NULL
+ *
+ * \li 'origin' is a valid absolute domain name.
+ *
+ * \li mctx is a valid memory context
+ *
+ * Ensures:
+ *
+ * \li A copy of 'origin' has been made for the databases use, and the
+ * caller is free to do whatever they want with the name and storage
+ * associated with 'origin'.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ * \li #ISC_R_NOTFOUND db_type not found
+ *
+ * \li Many other errors are possible, depending on what db_type was
+ * specified.
+ */
+
+void
+dns_db_attach(dns_db_t *source, dns_db_t **targetp);
+/*%<
+ * Attach *targetp to source.
+ *
+ * Requires:
+ *
+ * \li 'source' is a valid database.
+ *
+ * \li 'targetp' points to a NULL dns_db_t *.
+ *
+ * Ensures:
+ *
+ * \li *targetp is attached to source.
+ */
+
+void
+dns_db_detach(dns_db_t **dbp);
+/*%<
+ * Detach *dbp from its database.
+ *
+ * Requires:
+ *
+ * \li 'dbp' points to a valid database.
+ *
+ * Ensures:
+ *
+ * \li *dbp is NULL.
+ *
+ * \li If '*dbp' is the last reference to the database,
+ * all resources used by the database will be freed
+ */
+
+isc_result_t
+dns_db_ondestroy(dns_db_t *db, isc_task_t *task, isc_event_t **eventp);
+/*%<
+ * Causes 'eventp' to be sent to be sent to 'task' when the database is
+ * destroyed.
+ *
+ * Note; ownership of the eventp is taken from the caller (and *eventp is
+ * set to NULL). The sender field of the event is set to 'db' before it is
+ * sent to the task.
+ */
+
+isc_boolean_t
+dns_db_iscache(dns_db_t *db);
+/*%<
+ * Does 'db' have cache semantics?
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * Returns:
+ * \li #ISC_TRUE 'db' has cache semantics
+ * \li #ISC_FALSE otherwise
+ */
+
+isc_boolean_t
+dns_db_iszone(dns_db_t *db);
+/*%<
+ * Does 'db' have zone semantics?
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * Returns:
+ * \li #ISC_TRUE 'db' has zone semantics
+ * \li #ISC_FALSE otherwise
+ */
+
+isc_boolean_t
+dns_db_isstub(dns_db_t *db);
+/*%<
+ * Does 'db' have stub semantics?
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * Returns:
+ * \li #ISC_TRUE 'db' has zone semantics
+ * \li #ISC_FALSE otherwise
+ */
+
+isc_boolean_t
+dns_db_issecure(dns_db_t *db);
+/*%<
+ * Is 'db' secure?
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database with zone semantics.
+ *
+ * Returns:
+ * \li #ISC_TRUE 'db' is secure.
+ * \li #ISC_FALSE 'db' is not secure.
+ */
+
+isc_boolean_t
+dns_db_isdnssec(dns_db_t *db);
+/*%<
+ * Is 'db' secure or partially secure?
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database with zone semantics.
+ *
+ * Returns:
+ * \li #ISC_TRUE 'db' is secure or is partially.
+ * \li #ISC_FALSE 'db' is not secure.
+ */
+
+dns_name_t *
+dns_db_origin(dns_db_t *db);
+/*%<
+ * The origin of the database.
+ *
+ * Note: caller must not try to change this name.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * Returns:
+ *
+ * \li The origin of the database.
+ */
+
+dns_rdataclass_t
+dns_db_class(dns_db_t *db);
+/*%<
+ * The class of the database.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * Returns:
+ *
+ * \li The class of the database.
+ */
+
+isc_result_t
+dns_db_beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp,
+ dns_dbload_t **dbloadp);
+/*%<
+ * Begin loading 'db'.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li This is the first attempt to load 'db'.
+ *
+ * \li addp != NULL && *addp == NULL
+ *
+ * \li dbloadp != NULL && *dbloadp == NULL
+ *
+ * Ensures:
+ *
+ * \li On success, *addp will be a valid dns_addrdatasetfunc_t suitable
+ * for loading 'db'. *dbloadp will be a valid DB load context which
+ * should be used as 'arg' when *addp is called.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used, syntax errors in the master file, etc.
+ */
+
+isc_result_t
+dns_db_endload(dns_db_t *db, dns_dbload_t **dbloadp);
+/*%<
+ * Finish loading 'db'.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database that is being loaded.
+ *
+ * \li dbloadp != NULL and *dbloadp is a valid database load context.
+ *
+ * Ensures:
+ *
+ * \li *dbloadp == NULL
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used, syntax errors in the master file, etc.
+ */
+
+isc_result_t
+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);
+/*%<
+ * Load master file 'filename' into 'db'.
+ *
+ * Notes:
+ * \li This routine is equivalent to calling
+ *
+ *\code
+ * dns_db_beginload();
+ * dns_master_loadfile();
+ * dns_db_endload();
+ *\endcode
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li This is the first attempt to load 'db'.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used, syntax errors in the master file, etc.
+ */
+
+isc_result_t
+dns_db_dump(dns_db_t *db, dns_dbversion_t *version, const char *filename);
+
+isc_result_t
+dns_db_dump2(dns_db_t *db, dns_dbversion_t *version, const char *filename,
+ dns_masterformat_t masterformat);
+/*%<
+ * Dump version 'version' of 'db' to master file 'filename'.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'version' is a valid version.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used, OS file errors, etc.
+ */
+
+/***
+ *** Version Methods
+ ***/
+
+void
+dns_db_currentversion(dns_db_t *db, dns_dbversion_t **versionp);
+/*%<
+ * Open the current version for reading.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database with zone semantics.
+ *
+ * \li versionp != NULL && *verisonp == NULL
+ *
+ * Ensures:
+ *
+ * \li On success, '*versionp' is attached to the current version.
+ *
+ */
+
+isc_result_t
+dns_db_newversion(dns_db_t *db, dns_dbversion_t **versionp);
+/*%<
+ * Open a new version for reading and writing.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database with zone semantics.
+ *
+ * \li versionp != NULL && *verisonp == NULL
+ *
+ * Ensures:
+ *
+ * \li On success, '*versionp' is attached to the current version.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used.
+ */
+
+void
+dns_db_attachversion(dns_db_t *db, dns_dbversion_t *source,
+ dns_dbversion_t **targetp);
+/*%<
+ * Attach '*targetp' to 'source'.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database with zone semantics.
+ *
+ * \li source is a valid open version
+ *
+ * \li targetp != NULL && *targetp == NULL
+ *
+ * Ensures:
+ *
+ * \li '*targetp' is attached to source.
+ */
+
+void
+dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp,
+ isc_boolean_t commit);
+/*%<
+ * Close version '*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
+ * versions.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database with zone semantics.
+ *
+ * \li '*versionp' refers to a valid version.
+ *
+ * \li If committing a writable version, then there must be no other
+ * outstanding references to the version (e.g. an active rdataset
+ * iterator).
+ *
+ * Ensures:
+ *
+ * \li *versionp == NULL
+ *
+ * \li If *versionp is a read-write version, and commit is ISC_TRUE, then
+ * the version will become the current version. If !commit, then all
+ * changes made in the version will be undone, and the version will
+ * not become the current version.
+ */
+
+/***
+ *** Node Methods
+ ***/
+
+isc_result_t
+dns_db_findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
+ dns_dbnode_t **nodep);
+/*%<
+ * Find the node with name 'name'.
+ *
+ * Notes:
+ * \li If 'create' is ISC_TRUE and no node with name 'name' exists, then
+ * such a node will be created.
+ *
+ * \li This routine is for finding or creating a node with the specified
+ * name. There are no partial matches. It is not suitable for use
+ * in building responses to ordinary DNS queries; clients which wish
+ * to do that should use dns_db_find() instead.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'name' is a valid, non-empty, absolute name.
+ *
+ * \li nodep != NULL && *nodep == NULL
+ *
+ * Ensures:
+ *
+ * \li On success, *nodep is attached to the node with name 'name'.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND If !create and name not found.
+ * \li #ISC_R_NOMEMORY Can only happen if create is ISC_TRUE.
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used.
+ */
+
+isc_result_t
+dns_db_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);
+/*%<
+ * Find the best match for 'name' and 'type' in version 'version' of 'db'.
+ *
+ * Notes:
+ *
+ * \li If type == dns_rdataset_any, then rdataset will not be bound.
+ *
+ * \li If 'options' does not have #DNS_DBFIND_GLUEOK set, then no glue will
+ * be returned. For zone databases, glue is as defined in RFC2181.
+ * For cache databases, glue is any rdataset with a trust of
+ * dns_trust_glue.
+ *
+ * \li If 'options' does not have #DNS_DBFIND_PENDINGOK set, then no
+ * pending data will be returned. This option is only meaningful for
+ * cache databases.
+ *
+ * \li If the #DNS_DBFIND_NOWILD option is set, then wildcard matching will
+ * be disabled. This option is only meaningful for zone databases.
+ *
+ * \li If the #DNS_DBFIND_FORCENSEC option is set, the database is assumed to
+ * have NSEC records, and these will be returned when appropriate. This
+ * is only necessary when querying a database that was not secure
+ * when created.
+ *
+ * \li If the DNS_DBFIND_COVERINGNSEC option is set, then look for a
+ * NSEC record that potentially covers 'name' if a answer cannot
+ * be found. Note the returned NSEC needs to be checked to ensure
+ * that it is correct. This only affects answers returned from the
+ * cache.
+ *
+ * \li To respond to a query for SIG records, the caller should create a
+ * rdataset iterator and extract the signatures from each rdataset.
+ *
+ * \li Making queries of type ANY with #DNS_DBFIND_GLUEOK is not recommended,
+ * because the burden of determining whether a given rdataset is valid
+ * glue or not falls upon the caller.
+ *
+ * \li The 'now' field is ignored if 'db' is a zone database. If 'db' is a
+ * cache database, an rdataset will not be found unless it expires after
+ * 'now'. Any ANY query will not match unless at least one rdataset at
+ * the node expires after 'now'. If 'now' is zero, then the current time
+ * will be used.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'type' is not SIG, or a meta-RR type other than 'ANY' (e.g. 'OPT').
+ *
+ * \li 'nodep' is NULL, or nodep is a valid pointer and *nodep == NULL.
+ *
+ * \li 'foundname' is a valid name with a dedicated buffer.
+ *
+ * \li 'rdataset' is NULL, or is a valid unassociated rdataset.
+ *
+ * Ensures,
+ * on a non-error completion:
+ *
+ * \li If nodep != NULL, then it is bound to the found node.
+ *
+ * \li If foundname != NULL, then it contains the full name of the
+ * found node.
+ *
+ * \li If rdataset != NULL and type != dns_rdatatype_any, then
+ * rdataset is bound to the found rdataset.
+ *
+ * Non-error results are:
+ *
+ * \li #ISC_R_SUCCESS The desired node and type were
+ * found.
+ *
+ * \li #DNS_R_WILDCARD The desired node and type were
+ * found after performing
+ * wildcard matching. This is
+ * only returned if the
+ * #DNS_DBFIND_INDICATEWILD
+ * option is set; otherwise
+ * #ISC_R_SUCCESS is returned.
+ *
+ * \li #DNS_R_GLUE The desired node and type were
+ * found, but are glue. This
+ * result can only occur if
+ * the DNS_DBFIND_GLUEOK option
+ * is set. This result can only
+ * occur if 'db' is a zone
+ * database. If type ==
+ * dns_rdatatype_any, then the
+ * node returned may contain, or
+ * consist entirely of invalid
+ * glue (i.e. data occluded by a
+ * zone cut). The caller must
+ * take care not to return invalid
+ * glue to a client.
+ *
+ * \li #DNS_R_DELEGATION The data requested is beneath
+ * a zone cut. node, foundname,
+ * and rdataset reference the
+ * NS RRset of the zone cut.
+ * If 'db' is a cache database,
+ * then this is the deepest known
+ * delegation.
+ *
+ * \li #DNS_R_ZONECUT type == dns_rdatatype_any, and
+ * the desired node is a zonecut.
+ * The caller must take care not
+ * to return inappropriate glue
+ * to a client. This result can
+ * only occur if 'db' is a zone
+ * database and DNS_DBFIND_GLUEOK
+ * is set.
+ *
+ * \li #DNS_R_DNAME The data requested is beneath
+ * a DNAME. node, foundname,
+ * and rdataset reference the
+ * DNAME RRset.
+ *
+ * \li #DNS_R_CNAME The rdataset requested was not
+ * found, but there is a CNAME
+ * at the desired name. node,
+ * foundname, and rdataset
+ * reference the CNAME RRset.
+ *
+ * \li #DNS_R_NXDOMAIN The desired name does not
+ * exist.
+ *
+ * \li #DNS_R_NXRRSET The desired name exists, but
+ * the desired type does not.
+ *
+ * \li #ISC_R_NOTFOUND The desired name does not
+ * exist, and no delegation could
+ * be found. This result can only
+ * occur if 'db' is a cache
+ * database. The caller should
+ * use its nameserver(s) of last
+ * resort (e.g. root hints).
+ *
+ * \li #DNS_R_NCACHENXDOMAIN The desired name does not
+ * exist. 'node' is bound to the
+ * cache node with the desired
+ * name, and 'rdataset' contains
+ * the negative caching proof.
+ *
+ * \li #DNS_R_NCACHENXRRSET The desired type does not
+ * exist. 'node' is bound to the
+ * cache node with the desired
+ * name, and 'rdataset' contains
+ * the negative caching proof.
+ *
+ * \li #DNS_R_EMPTYNAME The name exists but there is
+ * no data at the name.
+ *
+ * \li #DNS_R_COVERINGNSEC The returned data is a NSEC
+ * that potentially covers 'name'.
+ *
+ * Error results:
+ *
+ * \li #ISC_R_NOMEMORY
+ *
+ * \li #DNS_R_BADDB Data that is required to be
+ * present in the DB, e.g. an NSEC
+ * record in a secure zone, is not
+ * present.
+ *
+ * \li Other results are possible, and should all be treated as
+ * errors.
+ */
+
+isc_result_t
+dns_db_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);
+/*%<
+ * Find the deepest known zonecut which encloses 'name' in 'db'.
+ *
+ * Notes:
+ *
+ * \li If the #DNS_DBFIND_NOEXACT option is set, then the zonecut returned
+ * (if any) will be the deepest known ancestor of 'name'.
+ *
+ * \li If 'now' is zero, then the current time will be used.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database with cache semantics.
+ *
+ * \li 'nodep' is NULL, or nodep is a valid pointer and *nodep == NULL.
+ *
+ * \li 'foundname' is a valid name with a dedicated buffer.
+ *
+ * \li 'rdataset' is NULL, or is a valid unassociated rdataset.
+ *
+ * Ensures, on a non-error completion:
+ *
+ * \li If nodep != NULL, then it is bound to the found node.
+ *
+ * \li If foundname != NULL, then it contains the full name of the
+ * found node.
+ *
+ * \li If rdataset != NULL and type != dns_rdatatype_any, then
+ * rdataset is bound to the found rdataset.
+ *
+ * Non-error results are:
+ *
+ * \li #ISC_R_SUCCESS
+ *
+ * \li #ISC_R_NOTFOUND
+ *
+ * \li Other results are possible, and should all be treated as
+ * errors.
+ */
+
+void
+dns_db_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp);
+/*%<
+ * Attach *targetp to source.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'source' is a valid node.
+ *
+ * \li 'targetp' points to a NULL dns_dbnode_t *.
+ *
+ * Ensures:
+ *
+ * \li *targetp is attached to source.
+ */
+
+void
+dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep);
+/*%<
+ * Detach *nodep from its node.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'nodep' points to a valid node.
+ *
+ * Ensures:
+ *
+ * \li *nodep is NULL.
+ */
+
+void
+dns_db_transfernode(dns_db_t *db, dns_dbnode_t **sourcep,
+ dns_dbnode_t **targetp);
+/*%<
+ * Transfer a node between pointer.
+ *
+ * This is equivalent to calling dns_db_attachnode() then dns_db_detachnode().
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li '*sourcep' is a valid node.
+ *
+ * \li 'targetp' points to a NULL dns_dbnode_t *.
+ *
+ * Ensures:
+ *
+ * \li '*sourcep' is NULL.
+ */
+
+isc_result_t
+dns_db_expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now);
+/*%<
+ * Mark as stale all records at 'node' which expire at or before 'now'.
+ *
+ * Note: if 'now' is zero, then the current time will be used.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid cache database.
+ *
+ * \li 'node' is a valid node.
+ */
+
+void
+dns_db_printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out);
+/*%<
+ * Print a textual representation of the contents of the node to
+ * 'out'.
+ *
+ * Note: this function is intended for debugging, not general use.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'node' is a valid node.
+ */
+
+/***
+ *** DB Iterator Creation
+ ***/
+
+isc_result_t
+dns_db_createiterator(dns_db_t *db, unsigned int options,
+ dns_dbiterator_t **iteratorp);
+/*%<
+ * Create an iterator for version 'version' of 'db'.
+ *
+ * Notes:
+ *
+ * \li One or more of the following options can be set.
+ * #DNS_DB_RELATIVENAMES
+ * #DNS_DB_NSEC3ONLY
+ * #DNS_DB_NONSEC3
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li iteratorp != NULL && *iteratorp == NULL
+ *
+ * Ensures:
+ *
+ * \li On success, *iteratorp will be a valid database iterator.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ */
+
+/***
+ *** Rdataset Methods
+ ***/
+
+/*
+ * XXXRTH Should we check for glue and pending data in dns_db_findrdataset()?
+ */
+
+isc_result_t
+dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset);
+/*%<
+ * Search for an rdataset of type 'type' at 'node' that are in version
+ * 'version' of 'db'. If found, make 'rdataset' refer to it.
+ *
+ * Notes:
+ *
+ * \li If 'version' is NULL, then the current version will be used.
+ *
+ * \li Care must be used when using this routine to build a DNS response:
+ * 'node' should have been found with dns_db_find(), not
+ * dns_db_findnode(). No glue checking is done. No checking for
+ * pending data is done.
+ *
+ * \li The 'now' field is ignored if 'db' is a zone database. If 'db' is a
+ * cache database, an rdataset will not be found unless it expires after
+ * 'now'. If 'now' is zero, then the current time will be used.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'node' is a valid node.
+ *
+ * \li 'rdataset' is a valid, disassociated rdataset.
+ *
+ * \li 'sigrdataset' is a valid, disassociated rdataset, or it is NULL.
+ *
+ * \li If 'covers' != 0, 'type' must be SIG.
+ *
+ * \li 'type' is not a meta-RR type such as 'ANY' or 'OPT'.
+ *
+ * Ensures:
+ *
+ * \li On success, 'rdataset' is associated with the found rdataset.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used.
+ */
+
+isc_result_t
+dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ isc_stdtime_t now, dns_rdatasetiter_t **iteratorp);
+/*%<
+ * Make '*iteratorp' an rdataset iteratator for all rdatasets at 'node' in
+ * version 'version' of 'db'.
+ *
+ * Notes:
+ *
+ * \li If 'version' is NULL, then the current version will be used.
+ *
+ * \li The 'now' field is ignored if 'db' is a zone database. If 'db' is a
+ * cache database, an rdataset will not be found unless it expires after
+ * 'now'. Any ANY query will not match unless at least one rdataset at
+ * the node expires after 'now'. If 'now' is zero, then the current time
+ * will be used.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'node' is a valid node.
+ *
+ * \li iteratorp != NULL && *iteratorp == NULL
+ *
+ * Ensures:
+ *
+ * \li On success, '*iteratorp' is a valid rdataset iterator.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used.
+ */
+
+isc_result_t
+dns_db_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);
+/*%<
+ * Add 'rdataset' to 'node' in version 'version' of 'db'.
+ *
+ * Notes:
+ *
+ * \li If the database has zone semantics, the #DNS_DBADD_MERGE option is set,
+ * and an rdataset of the same type as 'rdataset' already exists at
+ * 'node' then the contents of 'rdataset' will be merged with the existing
+ * rdataset. If the option is not set, then rdataset will replace any
+ * existing rdataset of the same type. If not merging and the
+ * #DNS_DBADD_FORCE option is set, then the data will update the database
+ * without regard to trust levels. If not forcing the data, then the
+ * rdataset will only be added if its trust level is >= the trust level of
+ * any existing rdataset. Forcing is only meaningful for cache databases.
+ * If #DNS_DBADD_EXACT is set then there must be no rdata in common between
+ * the old and new rdata sets. If #DNS_DBADD_EXACTTTL is set then both
+ * the old and new rdata sets must have the same ttl.
+ *
+ * \li The 'now' field is ignored if 'db' is a zone database. If 'db' is
+ * a cache database, then the added rdataset will expire no later than
+ * now + rdataset->ttl.
+ *
+ * \li If 'addedrdataset' is not NULL, then it will be attached to the
+ * resulting new rdataset in the database, or to the existing data if
+ * the existing data was better.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'node' is a valid node.
+ *
+ * \li 'rdataset' is a valid, associated rdataset with the same class
+ * as 'db'.
+ *
+ * \li 'addedrdataset' is NULL, or a valid, unassociated rdataset.
+ *
+ * \li The database has zone semantics and 'version' is a valid
+ * read-write version, or the database has cache semantics
+ * and version is NULL.
+ *
+ * \li If the database has cache semantics, the #DNS_DBADD_MERGE option must
+ * not be set.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #DNS_R_UNCHANGED The operation did not change anything.
+ * \li #ISC_R_NOMEMORY
+ * \li #DNS_R_NOTEXACT
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used.
+ */
+
+isc_result_t
+dns_db_subtractrdataset(dns_db_t *db, dns_dbnode_t *node,
+ dns_dbversion_t *version, dns_rdataset_t *rdataset,
+ unsigned int options, dns_rdataset_t *newrdataset);
+/*%<
+ * Remove any rdata in 'rdataset' from 'node' in version 'version' of
+ * 'db'.
+ *
+ * Notes:
+ *
+ * \li If 'newrdataset' is not NULL, then it will be attached to the
+ * resulting new rdataset in the database, unless the rdataset has
+ * become nonexistent. If DNS_DBSUB_EXACT is set then all elements
+ * of 'rdataset' must exist at 'node'.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'node' is a valid node.
+ *
+ * \li 'rdataset' is a valid, associated rdataset with the same class
+ * as 'db'.
+ *
+ * \li 'newrdataset' is NULL, or a valid, unassociated rdataset.
+ *
+ * \li The database has zone semantics and 'version' is a valid
+ * read-write version.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #DNS_R_UNCHANGED The operation did not change anything.
+ * \li #DNS_R_NXRRSET All rdata of the same type as those
+ * in 'rdataset' have been deleted.
+ * \li #DNS_R_NOTEXACT Some part of 'rdataset' did not
+ * exist and DNS_DBSUB_EXACT was set.
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used.
+ */
+
+isc_result_t
+dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
+ dns_dbversion_t *version, dns_rdatatype_t type,
+ dns_rdatatype_t covers);
+/*%<
+ * Make it so that no rdataset of type 'type' exists at 'node' in version
+ * version 'version' of 'db'.
+ *
+ * Notes:
+ *
+ * \li If 'type' is dns_rdatatype_any, then no rdatasets will exist in
+ * 'version' (provided that the dns_db_deleterdataset() isn't followed
+ * by one or more dns_db_addrdataset() calls).
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'node' is a valid node.
+ *
+ * \li The database has zone semantics and 'version' is a valid
+ * read-write version, or the database has cache semantics
+ * and version is NULL.
+ *
+ * \li 'type' is not a meta-RR type, except for dns_rdatatype_any, which is
+ * allowed.
+ *
+ * \li If 'covers' != 0, 'type' must be SIG.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #DNS_R_UNCHANGED No rdatasets of 'type' existed before
+ * the operation was attempted.
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used.
+ */
+
+isc_result_t
+dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, isc_uint32_t *serialp);
+/*%<
+ * Get the current SOA serial number from a zone database.
+ *
+ * Requires:
+ * \li 'db' is a valid database with zone semantics.
+ * \li 'ver' is a valid version.
+ */
+
+void
+dns_db_overmem(dns_db_t *db, isc_boolean_t overmem);
+/*%<
+ * Enable / disable agressive cache cleaning.
+ */
+
+unsigned int
+dns_db_nodecount(dns_db_t *db);
+/*%<
+ * Count the number of nodes in 'db'.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * Returns:
+ * \li The number of nodes in the database
+ */
+
+void
+dns_db_settask(dns_db_t *db, isc_task_t *task);
+/*%<
+ * If task is set then the final detach maybe performed asynchronously.
+ *
+ * Requires:
+ * \li 'db' is a valid database.
+ * \li 'task' to be valid or NULL.
+ */
+
+isc_boolean_t
+dns_db_ispersistent(dns_db_t *db);
+/*%<
+ * Is 'db' persistent? A persistent database does not need to be loaded
+ * from disk or written to disk.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * Returns:
+ * \li #ISC_TRUE 'db' is persistent.
+ * \li #ISC_FALSE 'db' is not persistent.
+ */
+
+isc_result_t
+dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg,
+ isc_mem_t *mctx, dns_dbimplementation_t **dbimp);
+
+/*%<
+ * Register a new database implementation and add it to the list of
+ * supported implementations.
+ *
+ * Requires:
+ *
+ * \li 'name' is not NULL
+ * \li 'order' is a valid function pointer
+ * \li 'mctx' is a valid memory context
+ * \li dbimp != NULL && *dbimp == NULL
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS The registration succeeded
+ * \li #ISC_R_NOMEMORY Out of memory
+ * \li #ISC_R_EXISTS A database implementation with the same name exists
+ *
+ * Ensures:
+ *
+ * \li *dbimp points to an opaque structure which must be passed to
+ * dns_db_unregister().
+ */
+
+void
+dns_db_unregister(dns_dbimplementation_t **dbimp);
+/*%<
+ * Remove a database implementation from the the list of supported
+ * implementations. No databases of this type can be active when this
+ * is called.
+ *
+ * Requires:
+ * \li dbimp != NULL && *dbimp == NULL
+ *
+ * Ensures:
+ *
+ * \li Any memory allocated in *dbimp will be freed.
+ */
+
+isc_result_t
+dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep);
+/*%<
+ * Get the origin DB node corresponding to the DB's zone. This function
+ * should typically succeed unless the underlying DB implementation doesn't
+ * support the feature.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid zone database.
+ * \li 'nodep' != NULL && '*nodep' == NULL
+ *
+ * Ensures:
+ * \li On success, '*nodep' will point to the DB node of the zone's origin.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND - the DB implementation does not support this feature.
+ */
+
+isc_result_t
+dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version,
+ dns_hash_t *hash, isc_uint8_t *flags,
+ isc_uint16_t *interations,
+ unsigned char *salt, size_t *salt_length);
+/*%<
+ * Get the NSEC3 parameters that are associated with this zone.
+ *
+ * Requires:
+ * \li 'db' is a valid zone database.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND - the DB implementation does not support this feature
+ * or this zone does not have NSEC3 records.
+ */
+
+isc_result_t
+dns_db_findnsec3node(dns_db_t *db, dns_name_t *name,
+ isc_boolean_t create, dns_dbnode_t **nodep);
+/*%<
+ * Find the NSEC3 node with name 'name'.
+ *
+ * Notes:
+ * \li If 'create' is ISC_TRUE and no node with name 'name' exists, then
+ * such a node will be created.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database.
+ *
+ * \li 'name' is a valid, non-empty, absolute name.
+ *
+ * \li nodep != NULL && *nodep == NULL
+ *
+ * Ensures:
+ *
+ * \li On success, *nodep is attached to the node with name 'name'.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND If !create and name not found.
+ * \li #ISC_R_NOMEMORY Can only happen if create is ISC_TRUE.
+ *
+ * \li Other results are possible, depending upon the database
+ * implementation used.
+ */
+
+isc_result_t
+dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
+ isc_stdtime_t resign);
+/*%<
+ * Sets the re-signing time associated with 'rdataset' to 'resign'.
+ *
+ * Requires:
+ * \li 'db' is a valid zone database.
+ * \li 'rdataset' to be associated with 'db'.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ * \li #ISC_R_NOTIMPLEMENTED - Not supported by this DB implementation.
+ */
+
+isc_result_t
+dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name);
+/*%<
+ * Return the rdataset with the earliest signing time in the zone.
+ * Note: the rdataset is version agnostic.
+ *
+ * Requires:
+ * \li 'db' is a valid zone database.
+ * \li 'rdataset' to be initialized but not associated.
+ * \li 'name' to be NULL or have a buffer associated with it.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND - No dataset exists.
+ */
+
+void
+dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset,
+ dns_dbversion_t *version);
+/*%<
+ * Mark 'rdataset' as not being available to be returned by
+ * dns_db_getsigningtime(). If the changes associated with 'version'
+ * are committed this will be permanent. If the version is not committed
+ * this change will be rolled back when the version is closed.
+ *
+ * Requires:
+ * \li 'db' is a valid zone database.
+ * \li 'rdataset' to be associated with 'db'.
+ * \li 'version' to be open for writing.
+ */
+
+dns_stats_t *
+dns_db_getrrsetstats(dns_db_t *db);
+/*%<
+ * Get statistics information counting RRsets stored in the DB, when available.
+ * The statistics may not be available depending on the DB implementation.
+ *
+ * Requires:
+ *
+ * \li 'db' is a valid database (zone or cache).
+ *
+ * Returns:
+ * \li when available, a pointer to a statistics object created by
+ * dns_rdatasetstats_create(); otherwise NULL.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_DB_H */
diff --git a/lib/dns/include/dns/dbiterator.h b/lib/dns/include/dns/dbiterator.h
new file mode 100644
index 0000000..366d676
--- /dev/null
+++ b/lib/dns/include/dns/dbiterator.h
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: dbiterator.h,v 1.25 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_DBITERATOR_H
+#define DNS_DBITERATOR_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/dbiterator.h
+ * \brief
+ * The DNS DB Iterator interface allows iteration of all of the nodes in a
+ * database.
+ *
+ * The dns_dbiterator_t type is like a "virtual class". To actually use
+ * it, an implementation of the class is required. This implementation is
+ * supplied by the database.
+ *
+ * It is the client's responsibility to call dns_db_detachnode() on all
+ * nodes returned.
+ *
+ * XXX &lt;more&gt; XXX
+ *
+ * MP:
+ *\li The iterator itself is not locked. The caller must ensure
+ * synchronization.
+ *
+ *\li The iterator methods ensure appropriate database locking.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li None.
+ */
+
+/*****
+ ***** Imports
+ *****/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Types
+ *****/
+
+typedef struct dns_dbiteratormethods {
+ void (*destroy)(dns_dbiterator_t **iteratorp);
+ isc_result_t (*first)(dns_dbiterator_t *iterator);
+ isc_result_t (*last)(dns_dbiterator_t *iterator);
+ isc_result_t (*seek)(dns_dbiterator_t *iterator, dns_name_t *name);
+ isc_result_t (*prev)(dns_dbiterator_t *iterator);
+ isc_result_t (*next)(dns_dbiterator_t *iterator);
+ isc_result_t (*current)(dns_dbiterator_t *iterator,
+ dns_dbnode_t **nodep, dns_name_t *name);
+ isc_result_t (*pause)(dns_dbiterator_t *iterator);
+ isc_result_t (*origin)(dns_dbiterator_t *iterator,
+ dns_name_t *name);
+} dns_dbiteratormethods_t;
+
+#define DNS_DBITERATOR_MAGIC ISC_MAGIC('D','N','S','I')
+#define DNS_DBITERATOR_VALID(dbi) ISC_MAGIC_VALID(dbi, DNS_DBITERATOR_MAGIC)
+/*%
+ * This structure is actually just the common prefix of a DNS db
+ * implementation's version of a dns_dbiterator_t.
+ *
+ * Clients may use the 'db' field of this structure. Except for that field,
+ * direct use of this structure by clients is forbidden. DB implementations
+ * may change the structure. 'magic' must be DNS_DBITERATOR_MAGIC for any of
+ * the dns_dbiterator routines to work. DB iterator implementations must
+ * maintain all DB iterator invariants.
+ */
+struct dns_dbiterator {
+ /* Unlocked. */
+ unsigned int magic;
+ dns_dbiteratormethods_t * methods;
+ dns_db_t * db;
+ isc_boolean_t relative_names;
+ isc_boolean_t cleaning;
+};
+
+void
+dns_dbiterator_destroy(dns_dbiterator_t **iteratorp);
+/*%<
+ * Destroy '*iteratorp'.
+ *
+ * Requires:
+ *
+ *\li '*iteratorp' is a valid iterator.
+ *
+ * Ensures:
+ *
+ *\li All resources used by the iterator are freed.
+ *
+ *\li *iteratorp == NULL.
+ */
+
+isc_result_t
+dns_dbiterator_first(dns_dbiterator_t *iterator);
+/*%<
+ * Move the node cursor to the first node in the database (if any).
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMORE There are no nodes in the database.
+ *
+ *\li Other results are possible, depending on the DB implementation.
+ */
+
+isc_result_t
+dns_dbiterator_last(dns_dbiterator_t *iterator);
+/*%<
+ * Move the node cursor to the last node in the database (if any).
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMORE There are no nodes in the database.
+ *
+ *\li Other results are possible, depending on the DB implementation.
+ */
+
+isc_result_t
+dns_dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name);
+/*%<
+ * Move the node cursor to the node with name 'name'.
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ *
+ *\li 'name' is a valid name.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOTFOUND
+ *
+ *\li Other results are possible, depending on the DB implementation.
+ */
+
+isc_result_t
+dns_dbiterator_prev(dns_dbiterator_t *iterator);
+/*%<
+ * Move the node cursor to the previous node in the database (if any).
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMORE There are no more nodes in the
+ * database.
+ *
+ *\li Other results are possible, depending on the DB implementation.
+ */
+
+isc_result_t
+dns_dbiterator_next(dns_dbiterator_t *iterator);
+/*%<
+ * Move the node cursor to the next node in the database (if any).
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMORE There are no more nodes in the
+ * database.
+ *
+ *\li Other results are possible, depending on the DB implementation.
+ */
+
+isc_result_t
+dns_dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
+ dns_name_t *name);
+/*%<
+ * Return the current node.
+ *
+ * Notes:
+ *\li If 'name' is not NULL, it will be set to the name of the node.
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ *
+ *\li nodep != NULL && *nodep == NULL
+ *
+ *\li The node cursor of 'iterator' is at a valid location (i.e. the
+ * result of last call to a cursor movement command was ISC_R_SUCCESS).
+ *
+ *\li 'name' is NULL, or is a valid name with a dedicated buffer.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #DNS_R_NEWORIGIN If this iterator was created with
+ * 'relative_names' set to ISC_TRUE,
+ * then #DNS_R_NEWORIGIN will be returned
+ * when the origin the names are
+ * relative to changes. This result
+ * can occur only when 'name' is not
+ * NULL. This is also a successful
+ * result.
+ *
+ *\li Other results are possible, depending on the DB implementation.
+ */
+
+isc_result_t
+dns_dbiterator_pause(dns_dbiterator_t *iterator);
+/*%<
+ * Pause iteration.
+ *
+ * Calling a cursor movement method or dns_dbiterator_current() may cause
+ * database locks to be acquired. Rather than reacquire these locks every
+ * time one of these routines is called, the locks may simply be held.
+ * Calling dns_dbiterator_pause() releases any such locks. Iterator clients
+ * should call this routine any time they are not going to execute another
+ * iterator method in the immediate future.
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ *
+ * Ensures:
+ *\li Any database locks being held for efficiency of iterator access are
+ * released.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *
+ *\li Other results are possible, depending on the DB implementation.
+ */
+
+isc_result_t
+dns_dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
+/*%<
+ * Return the origin to which returned node names are relative.
+ *
+ * Requires:
+ *
+ *\li 'iterator' is a valid relative_names iterator.
+ *
+ *\li 'name' is a valid name with a dedicated buffer.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE
+ *
+ *\li Other results are possible, depending on the DB implementation.
+ */
+
+void
+dns_dbiterator_setcleanmode(dns_dbiterator_t *iterator, isc_boolean_t mode);
+/*%<
+ * Indicate that the given iterator is/is not cleaning the DB.
+ *
+ * Notes:
+ *\li When 'mode' is ISC_TRUE,
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_DBITERATOR_H */
diff --git a/lib/dns/include/dns/dbtable.h b/lib/dns/include/dns/dbtable.h
new file mode 100644
index 0000000..503de95
--- /dev/null
+++ b/lib/dns/include/dns/dbtable.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: dbtable.h,v 1.23 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_DBTABLE_H
+#define DNS_DBTABLE_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/dbtable.h
+ * \brief
+ * DNS DB Tables
+ *
+ * XXX TBS XXX
+ *
+ * MP:
+ *\li The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li None.
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li None.
+ */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+#define DNS_DBTABLEFIND_NOEXACT 0x01
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_dbtable_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
+ dns_dbtable_t **dbtablep);
+/*%<
+ * Make a new dbtable of class 'rdclass'
+ *
+ * Requires:
+ *\li mctx != NULL
+ * \li dbtablep != NULL && *dptablep == NULL
+ *\li 'rdclass' is a valid class
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ */
+
+void
+dns_dbtable_attach(dns_dbtable_t *source, dns_dbtable_t **targetp);
+/*%<
+ * Attach '*targetp' to 'source'.
+ *
+ * Requires:
+ *
+ *\li 'source' is a valid dbtable.
+ *
+ *\li 'targetp' points to a NULL dns_dbtable_t *.
+ *
+ * Ensures:
+ *
+ *\li *targetp is attached to source.
+ */
+
+void
+dns_dbtable_detach(dns_dbtable_t **dbtablep);
+/*%<
+ * Detach *dbtablep from its dbtable.
+ *
+ * Requires:
+ *
+ *\li '*dbtablep' points to a valid dbtable.
+ *
+ * Ensures:
+ *
+ *\li *dbtablep is NULL.
+ *
+ *\li If '*dbtablep' is the last reference to the dbtable,
+ * all resources used by the dbtable will be freed
+ */
+
+isc_result_t
+dns_dbtable_add(dns_dbtable_t *dbtable, dns_db_t *db);
+/*%<
+ * Add 'db' to 'dbtable'.
+ *
+ * Requires:
+ *\li 'dbtable' is a valid dbtable.
+ *
+ *\li 'db' is a valid database with the same class as 'dbtable'
+ */
+
+void
+dns_dbtable_remove(dns_dbtable_t *dbtable, dns_db_t *db);
+/*%<
+ * Remove 'db' from 'dbtable'.
+ *
+ * Requires:
+ *\li 'db' was previously added to 'dbtable'.
+ */
+
+void
+dns_dbtable_adddefault(dns_dbtable_t *dbtable, dns_db_t *db);
+/*%<
+ * Use 'db' as the result of a dns_dbtable_find() if no better match is
+ * available.
+ */
+
+void
+dns_dbtable_getdefault(dns_dbtable_t *dbtable, dns_db_t **db);
+/*%<
+ * Get the 'db' used as the result of a dns_dbtable_find()
+ * if no better match is available.
+ */
+
+void
+dns_dbtable_removedefault(dns_dbtable_t *dbtable);
+/*%<
+ * Remove the default db from 'dbtable'.
+ */
+
+isc_result_t
+dns_dbtable_find(dns_dbtable_t *dbtable, dns_name_t *name,
+ unsigned int options, dns_db_t **dbp);
+/*%<
+ * Find the deepest match to 'name' in the dbtable, and return it
+ *
+ * Notes:
+ *\li If the DNS_DBTABLEFIND_NOEXACT option is set, the best partial
+ * match (if any) to 'name' will be returned.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS on success
+ *\li something else: no default and match
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_DBTABLE_H */
diff --git a/lib/dns/include/dns/diff.h b/lib/dns/include/dns/diff.h
new file mode 100644
index 0000000..a60343e
--- /dev/null
+++ b/lib/dns/include/dns/diff.h
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: diff.h,v 1.15 2008/04/02 02:37:42 marka Exp $ */
+
+#ifndef DNS_DIFF_H
+#define DNS_DIFF_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/diff.h
+ * \brief
+ * A diff is a convenience type representing a list of changes to be
+ * made to a database.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/types.h>
+
+/***
+ *** Types
+ ***/
+
+/*%
+ * A dns_difftuple_t represents a single RR being added or deleted.
+ * The RR type and class are in the 'rdata' member; the class is always
+ * the real one, not a DynDNS meta-class, so that the rdatas can be
+ * compared using dns_rdata_compare(). The TTL is significant
+ * even for deletions, because a deletion/addition pair cannot
+ * be canceled out if the TTL differs (it might be an explicit
+ * TTL update).
+ *
+ * Tuples are also used to represent complete RRs with owner
+ * names for a couple of other purposes, such as the
+ * individual RRs of a "RRset exists (value dependent)"
+ * prerequisite set. In this case, op==DNS_DIFFOP_EXISTS,
+ * and the TTL is ignored.
+ *
+ * DNS_DIFFOP_*RESIGN will cause the 'resign' attribute of the resulting
+ * RRset to be recomputed to be 'resign' seconds before the earliest RRSIG
+ * timeexpire.
+ */
+
+typedef enum {
+ DNS_DIFFOP_ADD = 0, /*%< Add an RR. */
+ DNS_DIFFOP_DEL = 1, /*%< Delete an RR. */
+ DNS_DIFFOP_EXISTS = 2, /*%< Assert RR existence. */
+ DNS_DIFFOP_ADDRESIGN = 4, /*%< ADD + RESIGN. */
+ DNS_DIFFOP_DELRESIGN = 5, /*%< DEL + RESIGN. */
+} dns_diffop_t;
+
+typedef struct dns_difftuple dns_difftuple_t;
+
+#define DNS_DIFFTUPLE_MAGIC ISC_MAGIC('D','I','F','T')
+#define DNS_DIFFTUPLE_VALID(t) ISC_MAGIC_VALID(t, DNS_DIFFTUPLE_MAGIC)
+
+struct dns_difftuple {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ dns_diffop_t op;
+ dns_name_t name;
+ dns_ttl_t ttl;
+ dns_rdata_t rdata;
+ ISC_LINK(dns_difftuple_t) link;
+ /* Variable-size name data and rdata follows. */
+};
+
+/*%
+ * A dns_diff_t represents a set of changes being applied to
+ * a zone. Diffs are also used to represent "RRset exists
+ * (value dependent)" prerequisites.
+ */
+typedef struct dns_diff dns_diff_t;
+
+#define DNS_DIFF_MAGIC ISC_MAGIC('D','I','F','F')
+#define DNS_DIFF_VALID(t) ISC_MAGIC_VALID(t, DNS_DIFF_MAGIC)
+
+struct dns_diff {
+ unsigned int magic;
+ isc_mem_t * mctx;
+ /*
+ * Set the 'resign' attribute to this many second before the
+ * earliest RRSIG timeexpire.
+ */
+ isc_uint32_t resign;
+ ISC_LIST(dns_difftuple_t) tuples;
+};
+
+/* Type of comparision function for sorting diffs. */
+typedef int dns_diff_compare_func(const void *, const void *);
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+/**************************************************************************/
+/*
+ * Maniuplation of diffs and tuples.
+ */
+
+isc_result_t
+dns_difftuple_create(isc_mem_t *mctx,
+ dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
+ dns_rdata_t *rdata, dns_difftuple_t **tp);
+/*%<
+ * Create a tuple. Deep copies are made of the name and rdata, so
+ * they need not remain valid after the call.
+ *
+ * Requires:
+ *\li *tp != NULL && *tp == NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ * \li ISC_R_NOMEMORY
+ */
+
+void
+dns_difftuple_free(dns_difftuple_t **tp);
+/*%<
+ * Free a tuple.
+ *
+ * Requires:
+ * \li **tp is a valid tuple.
+ *
+ * Ensures:
+ * \li *tp == NULL
+ * \li All memory used by the tuple is freed.
+ */
+
+isc_result_t
+dns_difftuple_copy(dns_difftuple_t *orig, dns_difftuple_t **copyp);
+/*%<
+ * Copy a tuple.
+ *
+ * Requires:
+ * \li 'orig' points to a valid tuple
+ *\li copyp != NULL && *copyp == NULL
+ */
+
+void
+dns_diff_init(isc_mem_t *mctx, dns_diff_t *diff);
+/*%<
+ * Initialize a diff.
+ *
+ * Requires:
+ * \li 'diff' points to an uninitialized dns_diff_t
+ * \li allocated by the caller.
+ *
+ * Ensures:
+ * \li '*diff' is a valid, empty diff.
+ */
+
+void
+dns_diff_clear(dns_diff_t *diff);
+/*%<
+ * Clear a diff, destroying all its tuples.
+ *
+ * Requires:
+ * \li 'diff' points to a valid dns_diff_t.
+ *
+ * Ensures:
+ * \li Any tuples in the diff are destroyed.
+ * The diff now empty, but it is still valid
+ * and may be reused without calling dns_diff_init
+ * again. The only memory used is that of the
+ * dns_diff_t structure itself.
+ *
+ * Notes:
+ * \li Managing the memory of the dns_diff_t structure itself
+ * is the caller's responsibility.
+ */
+
+void
+dns_diff_append(dns_diff_t *diff, dns_difftuple_t **tuple);
+/*%<
+ * Append a single tuple to a diff.
+ *
+ *\li 'diff' is a valid diff.
+ * \li '*tuple' is a valid tuple.
+ *
+ * Ensures:
+ *\li *tuple is NULL.
+ *\li The tuple has been freed, or will be freed when the diff is cleared.
+ */
+
+void
+dns_diff_appendminimal(dns_diff_t *diff, dns_difftuple_t **tuple);
+/*%<
+ * Append 'tuple' to 'diff', removing any duplicate
+ * or conflicting updates as needed to create a minimal diff.
+ *
+ * Requires:
+ *\li 'diff' is a minimal diff.
+ *
+ * Ensures:
+ *\li 'diff' is still a minimal diff.
+ * \li *tuple is NULL.
+ * \li The tuple has been freed, or will be freed when the diff is cleared.
+ *
+ */
+
+isc_result_t
+dns_diff_sort(dns_diff_t *diff, dns_diff_compare_func *compare);
+/*%<
+ * Sort 'diff' in-place according to the comparison function 'compare'.
+ */
+
+isc_result_t
+dns_diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver);
+isc_result_t
+dns_diff_applysilently(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver);
+/*%<
+ * Apply 'diff' to the database 'db'.
+ *
+ * dns_diff_apply() logs warnings about updates with no effect or
+ * with inconsistent TTLs; dns_diff_applysilently() does not.
+ *
+ * For efficiency, the diff should be sorted by owner name.
+ * If it is not sorted, operation will still be correct,
+ * but less efficient.
+ *
+ * Requires:
+ *\li *diff is a valid diff (possibly empty), containing
+ * tuples of type #DNS_DIFFOP_ADD and/or
+ * For #DNS_DIFFOP_DEL tuples, the TTL is ignored.
+ *
+ */
+
+isc_result_t
+dns_diff_load(dns_diff_t *diff, dns_addrdatasetfunc_t addfunc,
+ void *add_private);
+/*%<
+ * Like dns_diff_apply, but for use when loading a new database
+ * instead of modifying an existing one. This bypasses the
+ * database transaction mechanisms.
+ *
+ * Requires:
+ *\li 'addfunc' is a valid dns_addradatasetfunc_t obtained from
+ * dns_db_beginload()
+ *
+ *\li 'add_private' points to a corresponding dns_dbload_t *
+ * (XXX why is it a void pointer, then?)
+ */
+
+isc_result_t
+dns_diff_print(dns_diff_t *diff, FILE *file);
+
+/*%<
+ * Print the differences to 'file' or if 'file' is NULL via the
+ * logging system.
+ *
+ * Require:
+ *\li 'diff' to be valid.
+ *\li 'file' to refer to a open file or NULL.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ *\li any error from dns_rdataset_totext()
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_DIFF_H */
diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h
new file mode 100644
index 0000000..8a0094e
--- /dev/null
+++ b/lib/dns/include/dns/dispatch.h
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: dispatch.h,v 1.60 2008/06/23 23:47:11 tbox Exp $ */
+
+#ifndef DNS_DISPATCH_H
+#define DNS_DISPATCH_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/dispatch.h
+ * \brief
+ * DNS Dispatch Management
+ * Shared UDP and single-use TCP dispatches for queries and responses.
+ *
+ * MP:
+ *
+ *\li All locking is performed internally to each dispatch.
+ * Restrictions apply to dns_dispatch_removeresponse().
+ *
+ * Reliability:
+ *
+ * Resources:
+ *
+ * Security:
+ *
+ *\li Depends on the isc_socket_t and dns_message_t for prevention of
+ * buffer overruns.
+ *
+ * Standards:
+ *
+ *\li None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/buffer.h>
+#include <isc/lang.h>
+#include <isc/socket.h>
+#include <dns/types.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * This event is sent to a task when a response comes in.
+ * No part of this structure should ever be modified by the caller,
+ * other than parts of the buffer. The holy parts of the buffer are
+ * the base and size of the buffer. All other parts of the buffer may
+ * be used. On event delivery the used region contains the packet.
+ *
+ * "id" is the received message id,
+ *
+ * "addr" is the host that sent it to us,
+ *
+ * "buffer" holds state on the received data.
+ *
+ * The "free" routine for this event will clean up itself as well as
+ * any buffer space allocated from common pools.
+ */
+
+struct dns_dispatchevent {
+ ISC_EVENT_COMMON(dns_dispatchevent_t); /*%< standard event common */
+ isc_result_t result; /*%< result code */
+ isc_int32_t id; /*%< message id */
+ isc_sockaddr_t addr; /*%< address recv'd from */
+ struct in6_pktinfo pktinfo; /*%< reply info for v6 */
+ isc_buffer_t buffer; /*%< data buffer */
+ isc_uint32_t attributes; /*%< mirrored from socket.h */
+};
+
+/*@{*/
+/*%
+ * Attributes for added dispatchers.
+ *
+ * Values with the mask 0xffff0000 are application defined.
+ * Values with the mask 0x0000ffff are library defined.
+ *
+ * Insane values (like setting both TCP and UDP) are not caught. Don't
+ * do that.
+ *
+ * _PRIVATE
+ * The dispatcher cannot be shared.
+ *
+ * _TCP, _UDP
+ * The dispatcher is a TCP or UDP socket.
+ *
+ * _IPV4, _IPV6
+ * The dispatcher uses an IPv4 or IPv6 socket.
+ *
+ * _NOLISTEN
+ * The dispatcher should not listen on the socket.
+ *
+ * _MAKEQUERY
+ * The dispatcher can be used to issue queries to other servers, and
+ * accept replies from them.
+ *
+ * _RANDOMPORT
+ * Previously used to indicate that the port of a dispatch UDP must be
+ * chosen randomly. This behavior now always applies and the attribute
+ * is obsoleted.
+ *
+ * _EXCLUSIVE
+ * A separate socket will be used on-demand for each transaction.
+ */
+#define DNS_DISPATCHATTR_PRIVATE 0x00000001U
+#define DNS_DISPATCHATTR_TCP 0x00000002U
+#define DNS_DISPATCHATTR_UDP 0x00000004U
+#define DNS_DISPATCHATTR_IPV4 0x00000008U
+#define DNS_DISPATCHATTR_IPV6 0x00000010U
+#define DNS_DISPATCHATTR_NOLISTEN 0x00000020U
+#define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U
+#define DNS_DISPATCHATTR_CONNECTED 0x00000080U
+/*#define DNS_DISPATCHATTR_RANDOMPORT 0x00000100U*/
+#define DNS_DISPATCHATTR_EXCLUSIVE 0x00000200U
+/*@}*/
+
+isc_result_t
+dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
+ dns_dispatchmgr_t **mgrp);
+/*%<
+ * Creates a new dispatchmgr object.
+ *
+ * Requires:
+ *\li "mctx" be a valid memory context.
+ *
+ *\li mgrp != NULL && *mgrp == NULL
+ *
+ *\li "entropy" may be NULL, in which case an insecure random generator
+ * will be used. If it is non-NULL, it must be a valid entropy
+ * source.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- all ok
+ *
+ *\li anything else -- failure
+ */
+
+
+void
+dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp);
+/*%<
+ * Destroys the dispatchmgr when it becomes empty. This could be
+ * immediately.
+ *
+ * Requires:
+ *\li mgrp != NULL && *mgrp is a valid dispatchmgr.
+ */
+
+
+void
+dns_dispatchmgr_setblackhole(dns_dispatchmgr_t *mgr, dns_acl_t *blackhole);
+/*%<
+ * Sets the dispatcher's "blackhole list," a list of addresses that will
+ * be ignored by all dispatchers created by the dispatchmgr.
+ *
+ * Requires:
+ * \li mgrp is a valid dispatchmgr
+ * \li blackhole is a valid acl
+ */
+
+
+dns_acl_t *
+dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr);
+/*%<
+ * Gets a pointer to the dispatcher's current blackhole list,
+ * without incrementing its reference count.
+ *
+ * Requires:
+ *\li mgr is a valid dispatchmgr
+ * Returns:
+ *\li A pointer to the current blackhole list, or NULL.
+ */
+
+void
+dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr,
+ dns_portlist_t *portlist);
+/*%<
+ * This function is deprecated. Use dns_dispatchmgr_setavailports() instead.
+ *
+ * Requires:
+ *\li mgr is a valid dispatchmgr
+ */
+
+dns_portlist_t *
+dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr);
+/*%<
+ * This function is deprecated and always returns NULL.
+ *
+ * Requires:
+ *\li mgr is a valid dispatchmgr
+ */
+
+isc_result_t
+dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
+ isc_portset_t *v6portset);
+/*%<
+ * Sets a list of UDP ports that can be used for outgoing UDP messages.
+ *
+ * Requires:
+ *\li mgr is a valid dispatchmgr
+ *\li v4portset is NULL or a valid port set
+ *\li v6portset is NULL or a valid port set
+ */
+
+void
+dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, dns_stats_t *stats);
+/*%<
+ * Sets statistics counter for the dispatchmgr. This function is expected to
+ * be called only on zone creation (when necessary).
+ * Once installed, it cannot be removed or replaced. Also, there is no
+ * interface to get the installed stats from the zone; the caller must keep the
+ * stats to reference (e.g. dump) it later.
+ *
+ * Requires:
+ *\li mgr is a valid dispatchmgr with no managed dispatch.
+ *\li stats is a valid statistics supporting resolver statistics counters
+ * (see dns/stats.h).
+ */
+
+isc_result_t
+dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
+ isc_taskmgr_t *taskmgr, isc_sockaddr_t *localaddr,
+ unsigned int buffersize,
+ unsigned int maxbuffers, unsigned int maxrequests,
+ unsigned int buckets, unsigned int increment,
+ unsigned int attributes, unsigned int mask,
+ dns_dispatch_t **dispp);
+/*%<
+ * Attach to existing dns_dispatch_t if one is found with dns_dispatchmgr_find,
+ * otherwise create a new UDP dispatch.
+ *
+ * Requires:
+ *\li All pointer parameters be valid for their respective types.
+ *
+ *\li dispp != NULL && *disp == NULL
+ *
+ *\li 512 <= buffersize <= 64k
+ *
+ *\li maxbuffers > 0
+ *
+ *\li buckets < 2097169
+ *
+ *\li increment > buckets
+ *
+ *\li (attributes & DNS_DISPATCHATTR_TCP) == 0
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- success.
+ *
+ *\li Anything else -- failure.
+ */
+
+isc_result_t
+dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
+ isc_taskmgr_t *taskmgr, unsigned int buffersize,
+ unsigned int maxbuffers, unsigned int maxrequests,
+ unsigned int buckets, unsigned int increment,
+ unsigned int attributes, dns_dispatch_t **dispp);
+/*%<
+ * Create a new dns_dispatch and attach it to the provided isc_socket_t.
+ *
+ * For all dispatches, "buffersize" is the maximum packet size we will
+ * accept.
+ *
+ * "maxbuffers" and "maxrequests" control the number of buffers in the
+ * overall system and the number of buffers which can be allocated to
+ * requests.
+ *
+ * "buckets" is the number of buckets to use, and should be prime.
+ *
+ * "increment" is used in a collision avoidance function, and needs to be
+ * a prime > buckets, and not 2.
+ *
+ * Requires:
+ *
+ *\li mgr is a valid dispatch manager.
+ *
+ *\li sock is a valid.
+ *
+ *\li task is a valid task that can be used internally to this dispatcher.
+ *
+ * \li 512 <= buffersize <= 64k
+ *
+ *\li maxbuffers > 0.
+ *
+ *\li maxrequests <= maxbuffers.
+ *
+ *\li buckets < 2097169 (the next prime after 65536 * 32)
+ *
+ *\li increment > buckets (and prime).
+ *
+ *\li attributes includes #DNS_DISPATCHATTR_TCP and does not include
+ * #DNS_DISPATCHATTR_UDP.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- success.
+ *
+ *\li Anything else -- failure.
+ */
+
+void
+dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp);
+/*%<
+ * Attach to a dispatch handle.
+ *
+ * Requires:
+ *\li disp is valid.
+ *
+ *\li dispp != NULL && *dispp == NULL
+ */
+
+void
+dns_dispatch_detach(dns_dispatch_t **dispp);
+/*%<
+ * Detaches from the dispatch.
+ *
+ * Requires:
+ *\li dispp != NULL and *dispp be a valid dispatch.
+ */
+
+void
+dns_dispatch_starttcp(dns_dispatch_t *disp);
+/*%<
+ * Start processing of a TCP dispatch once the socket connects.
+ *
+ * Requires:
+ *\li 'disp' is valid.
+ */
+
+isc_result_t
+dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ isc_uint16_t *idp, dns_dispentry_t **resp,
+ isc_socketmgr_t *sockmgr);
+
+isc_result_t
+dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ isc_uint16_t *idp, dns_dispentry_t **resp);
+/*%<
+ * Add a response entry for this dispatch.
+ *
+ * "*idp" is filled in with the assigned message ID, and *resp is filled in
+ * to contain the magic token used to request event flow stop.
+ *
+ * Arranges for the given task to get a callback for response packets. When
+ * the event is delivered, it must be returned using dns_dispatch_freeevent()
+ * or through dns_dispatch_removeresponse() for another to be delivered.
+ *
+ * Requires:
+ *\li "idp" be non-NULL.
+ *
+ *\li "task" "action" and "arg" be set as appropriate.
+ *
+ *\li "dest" be non-NULL and valid.
+ *
+ *\li "resp" be non-NULL and *resp be NULL
+ *
+ *\li "sockmgr" be NULL or a valid socket manager. If 'disp' has
+ * the DNS_DISPATCHATTR_EXCLUSIVE attribute, this must not be NULL,
+ * which also means dns_dispatch_addresponse() cannot be used.
+ *
+ * Ensures:
+ *
+ *\li &lt;id, dest> is a unique tuple. That means incoming messages
+ * are identifiable.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS -- all is well.
+ *\li ISC_R_NOMEMORY -- memory could not be allocated.
+ *\li ISC_R_NOMORE -- no more message ids can be allocated
+ * for this destination.
+ */
+
+
+void
+dns_dispatch_removeresponse(dns_dispentry_t **resp,
+ dns_dispatchevent_t **sockevent);
+/*%<
+ * Stops the flow of responses for the provided id and destination.
+ * If "sockevent" is non-NULL, the dispatch event and associated buffer is
+ * also returned to the system.
+ *
+ * Requires:
+ *\li "resp" != NULL and "*resp" contain a value previously allocated
+ * by dns_dispatch_addresponse();
+ *
+ *\li May only be called from within the task given as the 'task'
+ * argument to dns_dispatch_addresponse() when allocating '*resp'.
+ */
+
+isc_socket_t *
+dns_dispatch_getentrysocket(dns_dispentry_t *resp);
+
+isc_socket_t *
+dns_dispatch_getsocket(dns_dispatch_t *disp);
+/*%<
+ * Return the socket associated with this dispatcher.
+ *
+ * Requires:
+ *\li disp is valid.
+ *
+ * Returns:
+ *\li The socket the dispatcher is using.
+ */
+
+isc_result_t
+dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp);
+/*%<
+ * Return the local address for this dispatch.
+ * This currently only works for dispatches using UDP sockets.
+ *
+ * Requires:
+ *\li disp is valid.
+ *\li addrp to be non null.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOTIMPLEMENTED
+ */
+
+void
+dns_dispatch_cancel(dns_dispatch_t *disp);
+/*%<
+ * cancel outstanding clients
+ *
+ * Requires:
+ *\li disp is valid.
+ */
+
+unsigned int
+dns_dispatch_getattributes(dns_dispatch_t *disp);
+/*%<
+ * Return the attributes (DNS_DISPATCHATTR_xxx) of this dispatch. Only the
+ * non-changeable attributes are expected to be referenced by the caller.
+ *
+ * Requires:
+ *\li disp is valid.
+ */
+
+void
+dns_dispatch_changeattributes(dns_dispatch_t *disp,
+ unsigned int attributes, unsigned int mask);
+/*%<
+ * Set the bits described by "mask" to the corresponding values in
+ * "attributes".
+ *
+ * That is:
+ *
+ * \code
+ * new = (old & ~mask) | (attributes & mask)
+ * \endcode
+ *
+ * This function has a side effect when #DNS_DISPATCHATTR_NOLISTEN changes.
+ * When the flag becomes off, the dispatch will start receiving on the
+ * corresponding socket. When the flag becomes on, receive events on the
+ * corresponding socket will be canceled.
+ *
+ * Requires:
+ *\li disp is valid.
+ *
+ *\li attributes are reasonable for the dispatch. That is, setting the UDP
+ * attribute on a TCP socket isn't reasonable.
+ */
+
+void
+dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event);
+/*%<
+ * Inform the dispatcher of a socket receive. This is used for sockets
+ * shared between dispatchers and clients. If the dispatcher fails to copy
+ * or send the event, nothing happens.
+ *
+ * Requires:
+ *\li disp is valid, and the attribute DNS_DISPATCHATTR_NOLISTEN is set.
+ * event != NULL
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_DISPATCH_H */
diff --git a/lib/dns/include/dns/dlz.h b/lib/dns/include/dns/dlz.h
new file mode 100644
index 0000000..66c5899
--- /dev/null
+++ b/lib/dns/include/dns/dlz.h
@@ -0,0 +1,290 @@
+/*
+ * Portions Copyright (C) 2005-2007 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
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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: dlz.h,v 1.7 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file dns/dlz.h */
+
+#ifndef DLZ_H
+#define DLZ_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * DLZ Interface
+ *
+ * The DLZ interface allows zones to be looked up using a driver instead of
+ * Bind's default in memory zone table.
+ *
+ *
+ * Reliability:
+ * No anticipated impact.
+ *
+ * Resources:
+ *
+ * Security:
+ * No anticipated impact.
+ *
+ * Standards:
+ * None.
+ */
+
+/*****
+ ***** Imports
+ *****/
+
+#include <dns/name.h>
+#include <dns/types.h>
+#include <dns/view.h>
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+#define DNS_DLZ_MAGIC ISC_MAGIC('D','L','Z','D')
+#define DNS_DLZ_VALID(dlz) ISC_MAGIC_VALID(dlz, DNS_DLZ_MAGIC)
+
+typedef isc_result_t
+(*dns_dlzallowzonexfr_t)(void *driverarg, void *dbdata, isc_mem_t *mctx,
+ dns_rdataclass_t rdclass, dns_name_t *name,
+ isc_sockaddr_t *clientaddr,
+ dns_db_t **dbp);
+
+/*%<
+ * Method prototype. Drivers implementing the DLZ interface MUST
+ * supply an allow zone transfer method. This method is called when
+ * the DNS server is performing a zone transfer query. The driver's
+ * method should return ISC_R_SUCCESS and a database pointer to the
+ * name server if the zone is supported by the database, and zone
+ * transfer is allowed. Otherwise it will return ISC_R_NOTFOUND if
+ * the zone is not supported by the database, or ISC_R_NOPERM if zone
+ * transfers are not allowed. If an error occurs it should return a
+ * result code indicating the type of error.
+ */
+
+typedef isc_result_t
+(*dns_dlzcreate_t)(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
+ char *argv[], void *driverarg, void **dbdata);
+
+/*%<
+ * Method prototype. Drivers implementing the DLZ interface MUST
+ * supply a create method. This method is called when the DNS server
+ * is starting up and creating drivers for use later.
+ */
+
+typedef void
+(*dns_dlzdestroy_t)(void *driverarg, void **dbdata);
+
+/*%<
+ * Method prototype. Drivers implementing the DLZ interface MUST
+ * supply a destroy method. This method is called when the DNS server
+ * is shuting down and no longer needs the driver.
+ */
+
+typedef isc_result_t
+(*dns_dlzfindzone_t)(void *driverarg, void *dbdata, isc_mem_t *mctx,
+ dns_rdataclass_t rdclass, dns_name_t *name,
+ dns_db_t **dbp);
+
+/*%<
+
+ * Method prototype. Drivers implementing the DLZ interface MUST
+ * supply a find zone method. This method is called when the DNS
+ * server is performing a query. The find zone method will be called
+ * with the longest possible name first, and continue to be called
+ * with successively shorter domain names, until any of the following
+ * occur:
+ *
+ * \li 1) a match is found, and the function returns (ISC_R_SUCCESS)
+ *
+ * \li 2) a problem occurs, and the functions returns anything other
+ * than (ISC_R_NOTFOUND)
+ * \li 3) we run out of domain name labels. I.E. we have tried the
+ * shortest domain name
+ * \li 4) the number of labels in the domain name is less than
+ * min_lables for dns_dlzfindzone
+ *
+ * The driver's find zone method should return ISC_R_SUCCESS and a
+ * database pointer to the name server if the zone is supported by the
+ * database. Otherwise it will return ISC_R_NOTFOUND, and a null
+ * pointer if the zone is not supported. If an error occurs it should
+ * return a result code indicating the type of error.
+ */
+
+/*% 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_dlzmethods_t;
+
+/*% information about a DLZ driver */
+struct dns_dlzimplementation {
+ const char *name;
+ const dns_dlzmethods_t *methods;
+ isc_mem_t *mctx;
+ void *driverarg;
+ ISC_LINK(dns_dlzimplementation_t) link;
+};
+
+/*% an instance of a DLZ driver */
+struct dns_dlzdb {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ dns_dlzimplementation_t *implementation;
+ void *dbdata;
+};
+
+
+/***
+ *** Method declarations
+ ***/
+
+isc_result_t
+dns_dlzallowzonexfr(dns_view_t *view, dns_name_t *name,
+ isc_sockaddr_t *clientaddr, dns_db_t **dbp);
+
+/*%<
+ * This method is called when the DNS server is performing a zone
+ * transfer query. It will call the DLZ driver's allow zone tranfer
+ * method.
+ */
+
+isc_result_t
+dns_dlzcreate(isc_mem_t *mctx, const char *dlzname,
+ const char *drivername, unsigned int argc,
+ char *argv[], dns_dlzdb_t **dbp);
+
+/*%<
+ * This method is called when the DNS server is starting up and
+ * creating drivers for use later. It will search the DLZ driver list
+ * for 'drivername' and return a DLZ driver via dbp if a match is
+ * found. If the DLZ driver supplies a create method, this function
+ * will call it.
+ */
+
+void
+dns_dlzdestroy(dns_dlzdb_t **dbp);
+
+/*%<
+ * This method is called when the DNS server is shuting down and no
+ * longer needs the driver. If the DLZ driver supplies a destroy
+ * methods, this function will call it.
+ */
+
+isc_result_t
+dns_dlzfindzone(dns_view_t *view, dns_name_t *name,
+ unsigned int minlabels, dns_db_t **dbp);
+
+/*%<
+ * This method is called when the DNS server is performing a query.
+ * It will call the DLZ driver's find zone method.
+ */
+
+isc_result_t
+dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
+ void *driverarg, isc_mem_t *mctx,
+ dns_dlzimplementation_t **dlzimp);
+
+/*%<
+ * Register a dynamically loadable zones (DLZ) driver for the database
+ * type 'drivername', implemented by the functions in '*methods'.
+ *
+ * dlzimp must point to a NULL dlz_implementation_t pointer. That is,
+ * dlzimp != NULL && *dlzimp == NULL. It will be assigned a value that
+ * will later be used to identify the driver when deregistering it.
+ */
+
+isc_result_t
+dns_dlzstrtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp);
+
+/*%<
+ * This method is called when the name server is starting up to parse
+ * the DLZ driver command line from named.conf. Basically it splits
+ * up a string into and argc / argv. The primary difference of this
+ * method is items between braces { } are considered only 1 word. for
+ * example the command line "this is { one grouped phrase } and this
+ * isn't" would be parsed into:
+ *
+ * \li argv[0]: "this"
+ * \li argv[1]: "is"
+ * \li argv{2]: " one grouped phrase "
+ * \li argv[3]: "and"
+ * \li argv[4]: "this"
+ * \li argv{5}: "isn't"
+ *
+ * braces should NOT be nested, more than one grouping in the command
+ * line is allowed. Notice, argv[2] has an extra space at the
+ * beginning and end. Extra spaces are not stripped between a
+ * grouping. You can do so in your driver if needed, or be sure not
+ * to put extra spaces before / after the braces.
+ */
+
+void
+dns_dlzunregister(dns_dlzimplementation_t **dlzimp);
+
+/*%<
+ * Removes the dlz driver from the list of registered dlz drivers.
+ * There must be no active dlz drivers of this type when this function
+ * is called.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DLZ_H */
diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h
new file mode 100644
index 0000000..f8a59d0
--- /dev/null
+++ b/lib/dns/include/dns/dnssec.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: dnssec.h,v 1.32 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_DNSSEC_H
+#define DNS_DNSSEC_H 1
+
+/*! \file dns/dnssec.h */
+
+#include <isc/lang.h>
+#include <isc/stdtime.h>
+
+#include <dns/types.h>
+
+#include <dst/dst.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx,
+ dst_key_t **key);
+/*%<
+ * Creates a DST key from a DNS record. Basically a wrapper around
+ * dst_key_fromdns().
+ *
+ * Requires:
+ *\li 'name' is not NULL
+ *\li 'rdata' is not NULL
+ *\li 'mctx' is not NULL
+ *\li 'key' is not NULL
+ *\li '*key' is NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li DST_R_INVALIDPUBLICKEY
+ *\li various errors from dns_name_totext
+ */
+
+isc_result_t
+dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
+ isc_stdtime_t *inception, isc_stdtime_t *expire,
+ isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata);
+/*%<
+ * Generates a SIG record covering this rdataset. This has no effect
+ * on existing SIG records.
+ *
+ * Requires:
+ *\li 'name' (the owner name of the record) is a valid name
+ *\li 'set' is a valid rdataset
+ *\li 'key' is a valid key
+ *\li 'inception' is not NULL
+ *\li 'expire' is not NULL
+ *\li 'mctx' is not NULL
+ *\li 'buffer' is not NULL
+ *\li 'sigrdata' is not NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_NOSPACE
+ *\li #DNS_R_INVALIDTIME - the expiration is before the inception
+ *\li #DNS_R_KEYUNAUTHORIZED - the key cannot sign this data (either
+ * it is not a zone key or its flags prevent
+ * authentication)
+ *\li DST_R_*
+ */
+
+isc_result_t
+dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
+ isc_boolean_t ignoretime, isc_mem_t *mctx,
+ dns_rdata_t *sigrdata);
+
+isc_result_t
+dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
+ isc_boolean_t ignoretime, isc_mem_t *mctx,
+ dns_rdata_t *sigrdata, dns_name_t *wild);
+/*%<
+ * Verifies the SIG record covering this rdataset signed by a specific
+ * key. This does not determine if the key's owner is authorized to
+ * sign this record, as this requires a resolver or database.
+ * If 'ignoretime' is ISC_TRUE, temporal validity will not be checked.
+ *
+ * Requires:
+ *\li 'name' (the owner name of the record) is a valid name
+ *\li 'set' is a valid rdataset
+ *\li 'key' is a valid key
+ *\li 'mctx' is not NULL
+ *\li 'sigrdata' is a valid rdata containing a SIG record
+ *\li 'wild' if non-NULL then is a valid and has a buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #DNS_R_FROMWILDCARD - the signature is valid and is from
+ * a wildcard expansion. dns_dnssec_verify2() only.
+ * 'wild' contains the name of the wildcard if non-NULL.
+ *\li #DNS_R_SIGINVALID - the signature fails to verify
+ *\li #DNS_R_SIGEXPIRED - the signature has expired
+ *\li #DNS_R_SIGFUTURE - the signature's validity period has not begun
+ *\li #DNS_R_KEYUNAUTHORIZED - the key cannot sign this data (either
+ * it is not a zone key or its flags prevent
+ * authentication)
+ *\li DST_R_*
+ */
+
+/*@{*/
+isc_result_t
+dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
+ dns_name_t *name, isc_mem_t *mctx,
+ unsigned int maxkeys, dst_key_t **keys,
+ unsigned int *nkeys);
+isc_result_t
+dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
+ dns_dbnode_t *node, dns_name_t *name,
+ const char *directory, isc_mem_t *mctx,
+ unsigned int maxkeys, dst_key_t **keys,
+ unsigned int *nkeys);
+/*%<
+ * Finds a set of zone keys.
+ * XXX temporary - this should be handled in dns_zone_t.
+ */
+/*@}*/
+
+isc_result_t
+dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key);
+/*%<
+ * Signs a message with a SIG(0) record. This is implicitly called by
+ * dns_message_renderend() if msg->sig0key is not NULL.
+ *
+ * Requires:
+ *\li 'msg' is a valid message
+ *\li 'key' is a valid key that can be used for signing
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li DST_R_*
+ */
+
+isc_result_t
+dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
+ dst_key_t *key);
+/*%<
+ * Verifies a message signed by a SIG(0) record. This is not
+ * called implicitly by dns_message_parse(). If dns_message_signer()
+ * is called before dns_dnssec_verifymessage(), it will return
+ * #DNS_R_NOTVERIFIEDYET. dns_dnssec_verifymessage() will set
+ * the verified_sig0 flag in msg if the verify succeeds, and
+ * the sig0status field otherwise.
+ *
+ * Requires:
+ *\li 'source' is a valid buffer containing the unparsed message
+ *\li 'msg' is a valid message
+ *\li 'key' is a valid key
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_NOTFOUND - no SIG(0) was found
+ *\li #DNS_R_SIGINVALID - the SIG record is not well-formed or
+ * was not generated by the key.
+ *\li DST_R_*
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_DNSSEC_H */
diff --git a/lib/dns/include/dns/ds.h b/lib/dns/include/dns/ds.h
new file mode 100644
index 0000000..b59fb83
--- /dev/null
+++ b/lib/dns/include/dns/ds.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: ds.h,v 1.10 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_DS_H
+#define DNS_DS_H 1
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+#define DNS_DSDIGEST_SHA1 (1)
+#define DNS_DSDIGEST_SHA256 (2)
+
+/*
+ * Assuming SHA-256 digest type.
+ */
+#define DNS_DS_BUFFERSIZE (36)
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
+ unsigned int digest_type, unsigned char *buffer,
+ dns_rdata_t *rdata);
+/*%<
+ * Build the rdata of a DS record.
+ *
+ * Requires:
+ *\li key Points to a valid DNS KEY record.
+ *\li buffer Points to a temporary buffer of at least
+ * #DNS_DS_BUFFERSIZE bytes.
+ *\li rdata Points to an initialized dns_rdata_t.
+ *
+ * Ensures:
+ * \li *rdata Contains a valid DS rdata. The 'data' member refers
+ * to 'buffer'.
+ */
+
+isc_boolean_t
+dns_ds_digest_supported(unsigned int digest_type);
+/*%<
+ * Is this digest algorithm supported by dns_ds_buildrdata()?
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_DS_H */
diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h
new file mode 100644
index 0000000..7692c1b
--- /dev/null
+++ b/lib/dns/include/dns/events.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: events.h,v 1.49 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_EVENTS_H
+#define DNS_EVENTS_H 1
+
+#include <isc/eventclass.h>
+
+/*! \file dns/events.h
+ * \brief
+ * Registry of DNS event numbers.
+ */
+
+#define DNS_EVENT_FETCHCONTROL (ISC_EVENTCLASS_DNS + 0)
+#define DNS_EVENT_FETCHDONE (ISC_EVENTCLASS_DNS + 1)
+#define DNS_EVENT_VIEWRESSHUTDOWN (ISC_EVENTCLASS_DNS + 2)
+#define DNS_EVENT_VIEWADBSHUTDOWN (ISC_EVENTCLASS_DNS + 3)
+#define DNS_EVENT_UPDATE (ISC_EVENTCLASS_DNS + 4)
+#define DNS_EVENT_UPDATEDONE (ISC_EVENTCLASS_DNS + 5)
+#define DNS_EVENT_DISPATCH (ISC_EVENTCLASS_DNS + 6)
+#define DNS_EVENT_TCPMSG (ISC_EVENTCLASS_DNS + 7)
+#define DNS_EVENT_ADBMOREADDRESSES (ISC_EVENTCLASS_DNS + 8)
+#define DNS_EVENT_ADBNOMOREADDRESSES (ISC_EVENTCLASS_DNS + 9)
+#define DNS_EVENT_ADBCANCELED (ISC_EVENTCLASS_DNS + 10)
+#define DNS_EVENT_ADBNAMEDELETED (ISC_EVENTCLASS_DNS + 11)
+#define DNS_EVENT_ADBSHUTDOWN (ISC_EVENTCLASS_DNS + 12)
+#define DNS_EVENT_ADBEXPIRED (ISC_EVENTCLASS_DNS + 13)
+#define DNS_EVENT_ADBCONTROL (ISC_EVENTCLASS_DNS + 14)
+#define DNS_EVENT_CACHECLEAN (ISC_EVENTCLASS_DNS + 15)
+#define DNS_EVENT_BYADDRDONE (ISC_EVENTCLASS_DNS + 16)
+#define DNS_EVENT_ZONECONTROL (ISC_EVENTCLASS_DNS + 17)
+#define DNS_EVENT_DBDESTROYED (ISC_EVENTCLASS_DNS + 18)
+#define DNS_EVENT_VALIDATORDONE (ISC_EVENTCLASS_DNS + 19)
+#define DNS_EVENT_REQUESTDONE (ISC_EVENTCLASS_DNS + 20)
+#define DNS_EVENT_VALIDATORSTART (ISC_EVENTCLASS_DNS + 21)
+#define DNS_EVENT_VIEWREQSHUTDOWN (ISC_EVENTCLASS_DNS + 22)
+#define DNS_EVENT_NOTIFYSENDTOADDR (ISC_EVENTCLASS_DNS + 23)
+#define DNS_EVENT_ZONE (ISC_EVENTCLASS_DNS + 24)
+#define DNS_EVENT_ZONESTARTXFRIN (ISC_EVENTCLASS_DNS + 25)
+#define DNS_EVENT_MASTERQUANTUM (ISC_EVENTCLASS_DNS + 26)
+#define DNS_EVENT_CACHEOVERMEM (ISC_EVENTCLASS_DNS + 27)
+#define DNS_EVENT_MASTERNEXTZONE (ISC_EVENTCLASS_DNS + 28)
+#define DNS_EVENT_IOREADY (ISC_EVENTCLASS_DNS + 29)
+#define DNS_EVENT_LOOKUPDONE (ISC_EVENTCLASS_DNS + 30)
+/* #define DNS_EVENT_unused (ISC_EVENTCLASS_DNS + 31) */
+#define DNS_EVENT_DISPATCHCONTROL (ISC_EVENTCLASS_DNS + 32)
+#define DNS_EVENT_REQUESTCONTROL (ISC_EVENTCLASS_DNS + 33)
+#define DNS_EVENT_DUMPQUANTUM (ISC_EVENTCLASS_DNS + 34)
+#define DNS_EVENT_IMPORTRECVDONE (ISC_EVENTCLASS_DNS + 35)
+#define DNS_EVENT_FREESTORAGE (ISC_EVENTCLASS_DNS + 36)
+#define DNS_EVENT_VIEWACACHESHUTDOWN (ISC_EVENTCLASS_DNS + 37)
+#define DNS_EVENT_ACACHECONTROL (ISC_EVENTCLASS_DNS + 38)
+#define DNS_EVENT_ACACHECLEAN (ISC_EVENTCLASS_DNS + 39)
+#define DNS_EVENT_ACACHEOVERMEM (ISC_EVENTCLASS_DNS + 40)
+
+#define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0)
+#define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535)
+
+#endif /* DNS_EVENTS_H */
diff --git a/lib/dns/include/dns/fixedname.h b/lib/dns/include/dns/fixedname.h
new file mode 100644
index 0000000..5a2aaf3
--- /dev/null
+++ b/lib/dns/include/dns/fixedname.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: fixedname.h,v 1.19 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_FIXEDNAME_H
+#define DNS_FIXEDNAME_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/fixedname.h
+ * \brief
+ * Fixed-size Names
+ *
+ * dns_fixedname_t is a convenience type containing a name, an offsets table,
+ * and a dedicated buffer big enough for the longest possible name.
+ *
+ * MP:
+ *\li The caller must ensure any required synchronization.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li Per dns_fixedname_t:
+ *\code
+ * sizeof(dns_name_t) + sizeof(dns_offsets_t) +
+ * sizeof(isc_buffer_t) + 255 bytes + structure padding
+ *\endcode
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li None.
+ */
+
+/*****
+ ***** Imports
+ *****/
+
+#include <isc/buffer.h>
+
+#include <dns/name.h>
+
+/*****
+ ***** Types
+ *****/
+
+struct dns_fixedname {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_buffer_t buffer;
+ unsigned char data[DNS_NAME_MAXWIRE];
+};
+
+#define dns_fixedname_init(fn) \
+ do { \
+ dns_name_init(&((fn)->name), (fn)->offsets); \
+ isc_buffer_init(&((fn)->buffer), (fn)->data, \
+ DNS_NAME_MAXWIRE); \
+ dns_name_setbuffer(&((fn)->name), &((fn)->buffer)); \
+ } while (0)
+
+#define dns_fixedname_invalidate(fn) \
+ dns_name_invalidate(&((fn)->name))
+
+#define dns_fixedname_name(fn) (&((fn)->name))
+
+#endif /* DNS_FIXEDNAME_H */
diff --git a/lib/dns/include/dns/forward.h b/lib/dns/include/dns/forward.h
new file mode 100644
index 0000000..512c5e3
--- /dev/null
+++ b/lib/dns/include/dns/forward.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2004-2007 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: forward.h,v 1.11 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_FORWARD_H
+#define DNS_FORWARD_H 1
+
+/*! \file dns/forward.h */
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+struct dns_forwarders {
+ isc_sockaddrlist_t addrs;
+ dns_fwdpolicy_t fwdpolicy;
+};
+
+isc_result_t
+dns_fwdtable_create(isc_mem_t *mctx, dns_fwdtable_t **fwdtablep);
+/*%<
+ * Creates a new forwarding table.
+ *
+ * Requires:
+ * \li mctx is a valid memory context.
+ * \li fwdtablep != NULL && *fwdtablep == NULL
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_fwdtable_add(dns_fwdtable_t *fwdtable, dns_name_t *name,
+ isc_sockaddrlist_t *addrs, dns_fwdpolicy_t policy);
+/*%<
+ * Adds an entry to the forwarding table. The entry associates
+ * a domain with a list of forwarders and a forwarding policy. The
+ * addrs list is copied if not empty, so the caller should free its copy.
+ *
+ * Requires:
+ * \li fwdtable is a valid forwarding table.
+ * \li name is a valid name
+ * \li addrs is a valid list of sockaddrs, which may be empty.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_fwdtable_find(dns_fwdtable_t *fwdtable, dns_name_t *name,
+ dns_forwarders_t **forwardersp);
+/*%<
+ * Finds a domain in the forwarding table. The closest matching parent
+ * domain is returned.
+ *
+ * Requires:
+ * \li fwdtable is a valid forwarding table.
+ * \li name is a valid name
+ * \li forwardersp != NULL && *forwardersp == NULL
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND
+ */
+
+isc_result_t
+dns_fwdtable_find2(dns_fwdtable_t *fwdtable, dns_name_t *name,
+ dns_name_t *foundname, dns_forwarders_t **forwardersp);
+/*%<
+ * Finds a domain in the forwarding table. The closest matching parent
+ * domain is returned.
+ *
+ * Requires:
+ * \li fwdtable is a valid forwarding table.
+ * \li name is a valid name
+ * \li forwardersp != NULL && *forwardersp == NULL
+ * \li foundname to be NULL or a valid name with buffer.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND
+ */
+
+void
+dns_fwdtable_destroy(dns_fwdtable_t **fwdtablep);
+/*%<
+ * Destroys a forwarding table.
+ *
+ * Requires:
+ * \li fwtablep != NULL && *fwtablep != NULL
+ *
+ * Ensures:
+ * \li all memory associated with the forwarding table is freed.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_FORWARD_H */
diff --git a/lib/dns/include/dns/iptable.h b/lib/dns/include/dns/iptable.h
new file mode 100644
index 0000000..d7eb140
--- /dev/null
+++ b/lib/dns/include/dns/iptable.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007 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: iptable.h,v 1.4 2007/09/14 01:46:05 marka Exp $ */
+
+#ifndef DNS_IPTABLE_H
+#define DNS_IPTABLE_H 1
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/radix.h>
+
+struct dns_iptable {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_refcount_t refcount;
+ isc_radix_tree_t *radix;
+ ISC_LINK(dns_iptable_t) nextincache;
+};
+
+#define DNS_IPTABLE_MAGIC ISC_MAGIC('T','a','b','l')
+#define DNS_IPTABLE_VALID(a) ISC_MAGIC_VALID(a, DNS_IPTABLE_MAGIC)
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_iptable_create(isc_mem_t *mctx, dns_iptable_t **target);
+/*
+ * Create a new IP table and the underlying radix structure
+ */
+
+isc_result_t
+dns_iptable_addprefix(dns_iptable_t *tab, isc_netaddr_t *addr,
+ isc_uint16_t bitlen, isc_boolean_t pos);
+/*
+ * Add an IP prefix to an existing IP table
+ */
+
+isc_result_t
+dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, isc_boolean_t pos);
+/*
+ * Merge one IP table into another one.
+ */
+
+void
+dns_iptable_attach(dns_iptable_t *source, dns_iptable_t **target);
+
+void
+dns_iptable_detach(dns_iptable_t **tabp);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_IPTABLE_H */
diff --git a/lib/dns/include/dns/journal.h b/lib/dns/include/dns/journal.h
new file mode 100644
index 0000000..72468f2
--- /dev/null
+++ b/lib/dns/include/dns/journal.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: journal.h,v 1.33 2008/04/01 23:47:10 tbox Exp $ */
+
+#ifndef DNS_JOURNAL_H
+#define DNS_JOURNAL_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/journal.h
+ * \brief
+ * Database journalling.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+
+#include <dns/name.h>
+#include <dns/diff.h>
+#include <dns/rdata.h>
+#include <dns/types.h>
+
+/***
+ *** Defines.
+ ***/
+#define DNS_JOURNALOPT_RESIGN 0x00000001
+
+/***
+ *** Types
+ ***/
+
+/*%
+ * A dns_journal_t represents an open journal file. This is an opaque type.
+ *
+ * A particular dns_journal_t object may be opened for writing, in which case
+ * it can be used for writing transactions to a journal file, or it can be
+ * opened for reading, in which case it can be used for reading transactions
+ * from (iterating over) a journal file. A single dns_journal_t object may
+ * not be used for both purposes.
+ */
+typedef struct dns_journal dns_journal_t;
+
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+/**************************************************************************/
+
+isc_result_t
+dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
+ dns_diffop_t op, dns_difftuple_t **tp);
+/*!< brief
+ * Create a diff tuple for the current database SOA.
+ * XXX this probably belongs somewhere else.
+ */
+
+
+/*@{*/
+#define DNS_SERIAL_GT(a, b) ((int)(((a) - (b)) & 0xFFFFFFFF) > 0)
+#define DNS_SERIAL_GE(a, b) ((int)(((a) - (b)) & 0xFFFFFFFF) >= 0)
+/*!< brief
+ * Compare SOA serial numbers. DNS_SERIAL_GT(a, b) returns true iff
+ * a is "greater than" b where "greater than" is as defined in RFC1982.
+ * DNS_SERIAL_GE(a, b) returns true iff a is "greater than or equal to" b.
+ */
+/*@}*/
+
+/**************************************************************************/
+/*
+ * Journal object creation and destruction.
+ */
+
+isc_result_t
+dns_journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,
+ dns_journal_t **journalp);
+/*%<
+ * Open the journal file 'filename' and create a dns_journal_t object for it.
+ *
+ * If 'write' is ISC_TRUE, the journal is open for writing. If it does
+ * not exist, it is created.
+ *
+ * If 'write' is ISC_FALSE, the journal is open for reading. If it does
+ * not exist, ISC_R_NOTFOUND is returned.
+ */
+
+void
+dns_journal_destroy(dns_journal_t **journalp);
+/*%<
+ * Destroy a dns_journal_t, closing any open files and freeing its memory.
+ */
+
+/**************************************************************************/
+/*
+ * Writing transactions to journals.
+ */
+
+isc_result_t
+dns_journal_begin_transaction(dns_journal_t *j);
+/*%<
+ * Prepare to write a new transaction to the open journal file 'j'.
+ *
+ * Requires:
+ * \li 'j' is open for writing.
+ */
+
+isc_result_t
+dns_journal_writediff(dns_journal_t *j, dns_diff_t *diff);
+/*%<
+ * Write 'diff' to the current transaction of journal file 'j'.
+ *
+ * Requires:
+ * \li 'j' is open for writing and dns_journal_begin_transaction()
+ * has been called.
+ *
+ *\li 'diff' is a full or partial, correctly ordered IXFR
+ * difference sequence.
+ */
+
+isc_result_t
+dns_journal_commit(dns_journal_t *j);
+/*%<
+ * Commit the current transaction of journal file 'j'.
+ *
+ * Requires:
+ * \li 'j' is open for writing and dns_journal_begin_transaction()
+ * has been called.
+ *
+ * \li dns_journal_writediff() has been called one or more times
+ * to form a complete, correctly ordered IXFR difference
+ * sequence.
+ */
+
+isc_result_t
+dns_journal_write_transaction(dns_journal_t *j, dns_diff_t *diff);
+/*%
+ * Write a complete transaction at once to a journal file,
+ * sorting it if necessary, and commit it. Equivalent to calling
+ * dns_diff_sort(), dns_journal_begin_transaction(),
+ * dns_journal_writediff(), and dns_journal_commit().
+ *
+ * Requires:
+ *\li 'j' is open for writing.
+ *
+ * \li 'diff' contains exactly one SOA deletion, one SOA addition
+ * with a greater serial number, and possibly other changes,
+ * in arbitrary order.
+ */
+
+/**************************************************************************/
+/*
+ * Reading transactions from journals.
+ */
+
+isc_uint32_t
+dns_journal_first_serial(dns_journal_t *j);
+isc_uint32_t
+dns_journal_last_serial(dns_journal_t *j);
+/*%<
+ * Get the first and last addressable serial number in the journal.
+ */
+
+isc_result_t
+dns_journal_iter_init(dns_journal_t *j,
+ isc_uint32_t begin_serial, isc_uint32_t end_serial);
+/*%<
+ * Prepare to iterate over the transactions that will bring the database
+ * from SOA serial number 'begin_serial' to 'end_serial'.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_RANGE begin_serial is outside the addressable range.
+ *\li ISC_R_NOTFOUND begin_serial is within the range of adressable
+ * serial numbers covered by the journal, but
+ * this particular serial number does not exist.
+ */
+
+/*@{*/
+isc_result_t
+dns_journal_first_rr(dns_journal_t *j);
+isc_result_t
+dns_journal_next_rr(dns_journal_t *j);
+/*%<
+ * Position the iterator at the first/next RR in a journal
+ * transaction sequence established using dns_journal_iter_init().
+ *
+ * Requires:
+ * \li dns_journal_iter_init() has been called.
+ *
+ */
+/*@}*/
+
+void
+dns_journal_current_rr(dns_journal_t *j, dns_name_t **name, isc_uint32_t *ttl,
+ dns_rdata_t **rdata);
+/*%<
+ * Get the name, ttl, and rdata of the current journal RR.
+ *
+ * Requires:
+ * \li The last call to dns_journal_first_rr() or dns_journal_next_rr()
+ * returned ISC_R_SUCCESS.
+ */
+
+/**************************************************************************/
+/*
+ * Database roll-forward.
+ */
+
+isc_result_t
+dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db, unsigned int options,
+ const char *filename);
+/*%<
+ * Roll forward (play back) the journal file "filename" into the
+ * database "db". This should be called when the server starts
+ * after a shutdown or crash.
+ *
+ * Requires:
+ *\li 'mctx' is a valid memory context.
+ *\li 'db' is a valid database which does not have a version
+ * open for writing.
+ *\li 'filename' is the name of the journal file belonging to 'db'.
+ *
+ * Returns:
+ *\li DNS_R_NOJOURNAL when journal does not exist.
+ *\li ISC_R_NOTFOUND when current serial in not in journal.
+ *\li ISC_R_RANGE when current serial in not in journals range.
+ *\li ISC_R_SUCCESS journal has been applied successfully to database.
+ * others
+ */
+
+isc_result_t
+dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file);
+/* For debugging not general use */
+
+isc_result_t
+dns_db_diff(isc_mem_t *mctx,
+ dns_db_t *dba, dns_dbversion_t *dbvera,
+ dns_db_t *dbb, dns_dbversion_t *dbverb,
+ const char *journal_filename);
+/*%<
+ * Compare the databases 'dba' and 'dbb' and generate a journal
+ * entry containing the changes to make 'dba' from 'dbb' (note
+ * the order). This journal entry will consist of a single,
+ * possibly very large transaction. Append the journal
+ * entry to the journal file specified by 'journal_filename'.
+ */
+
+isc_result_t
+dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial,
+ isc_uint32_t target_size);
+/*%<
+ * Attempt to compact the journal if it is greater that 'target_size'.
+ * Changes from 'serial' onwards will be preserved. If the journal
+ * exists and is non-empty 'serial' must exist in the journal.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_JOURNAL_H */
diff --git a/lib/dns/include/dns/keyflags.h b/lib/dns/include/dns/keyflags.h
new file mode 100644
index 0000000..74a1740
--- /dev/null
+++ b/lib/dns/include/dns/keyflags.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: keyflags.h,v 1.16 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_KEYFLAGS_H
+#define DNS_KEYFLAGS_H 1
+
+/*! \file dns/keyflags.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source);
+/*%<
+ * Convert the text 'source' refers to into a DNSSEC KEY flags value.
+ * The text may contain either a set of flag mnemonics separated by
+ * vertical bars or a decimal flags value. For compatibility with
+ * older versions of BIND and the DNSSEC signer, octal values
+ * prefixed with a zero and hexadecimal values prefixed with "0x"
+ * are also accepted.
+ *
+ * Requires:
+ *\li 'flagsp' is a valid pointer.
+ *
+ *\li 'source' is a valid text region.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS on success
+ *\li ISC_R_RANGE numeric flag value is out of range
+ *\li DNS_R_UNKNOWN mnemonic flag is unknown
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_KEYFLAGS_H */
diff --git a/lib/dns/include/dns/keytable.h b/lib/dns/include/dns/keytable.h
new file mode 100644
index 0000000..553aa99
--- /dev/null
+++ b/lib/dns/include/dns/keytable.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: keytable.h,v 1.16 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_KEYTABLE_H
+#define DNS_KEYTABLE_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * The keytable module provides services for storing and retrieving DNSSEC
+ * trusted keys, as well as the ability to find the deepest matching key
+ * for a given domain name.
+ *
+ * MP:
+ *\li The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+#include <dst/dst.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep);
+/*%<
+ * Create a keytable.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li keytablep != NULL && *keytablep == NULL
+ *
+ * Ensures:
+ *
+ *\li On success, *keytablep is a valid, empty key table.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *
+ *\li Any other result indicates failure.
+ */
+
+
+void
+dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp);
+/*%<
+ * Attach *targetp to source.
+ *
+ * Requires:
+ *
+ *\li 'source' is a valid keytable.
+ *
+ *\li 'targetp' points to a NULL dns_keytable_t *.
+ *
+ * Ensures:
+ *
+ *\li *targetp is attached to source.
+ */
+
+void
+dns_keytable_detach(dns_keytable_t **keytablep);
+/*%<
+ * Detach *keytablep from its keytable.
+ *
+ * Requires:
+ *
+ *\li 'keytablep' points to a valid keytable.
+ *
+ * Ensures:
+ *
+ *\li *keytablep is NULL.
+ *
+ *\li If '*keytablep' is the last reference to the keytable,
+ * all resources used by the keytable will be freed
+ */
+
+isc_result_t
+dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp);
+/*%<
+ * Add '*keyp' to 'keytable'.
+ *
+ * Notes:
+ *
+ *\li Ownership of *keyp is transferred to the keytable.
+ *
+ * Requires:
+ *
+ *\li keyp != NULL && *keyp is a valid dst_key_t *.
+ *
+ * Ensures:
+ *
+ *\li On success, *keyp == NULL
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *
+ *\li Any other result indicates failure.
+ */
+
+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);
+/*%<
+ * Search for a key named 'name', matching 'algorithm' and 'tag' in
+ * 'keytable'. This finds the first instance which matches. Use
+ * dns_keytable_findnextkeynode() to find other 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 DNS_R_PARTIALMATCH the name existed in the keytable.
+ *\li ISC_R_NOTFOUND
+ *
+ *\li Any other result indicates an error.
+ */
+
+isc_result_t
+dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
+ dns_keynode_t **nextnodep);
+/*%<
+ * Search for the next key with the same properties as 'keynode' in
+ * 'keytable' as found by dns_keytable_findkeynode().
+ *
+ * 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_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name,
+ dns_name_t *foundname);
+/*%<
+ * Search for the deepest match of 'name' in 'keytable'.
+ *
+ * Requires:
+ *
+ *\li 'keytable' is a valid keytable.
+ *
+ *\li 'name' is a valid absolute name.
+ *
+ *\li 'foundname' is a name with a dedicated buffer.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOTFOUND
+ *
+ *\li Any other result indicates an error.
+ */
+
+void
+dns_keytable_detachkeynode(dns_keytable_t *keytable,
+ dns_keynode_t **keynodep);
+/*%<
+ * Give back a keynode found via dns_keytable_findkeynode().
+ *
+ * Requires:
+ *
+ *\li 'keytable' is a valid keytable.
+ *
+ *\li *keynodep is a valid keynode returned by a call to
+ * dns_keytable_findkeynode().
+ *
+ * Ensures:
+ *
+ *\li *keynodep == NULL
+ */
+
+isc_result_t
+dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
+ isc_boolean_t *wantdnssecp);
+/*%<
+ * Is 'name' at or beneath a trusted key?
+ *
+ * Requires:
+ *
+ *\li 'keytable' is a valid keytable.
+ *
+ *\li 'name' is a valid absolute name.
+ *
+ *\li '*wantsdnssecp' is a valid isc_boolean_t.
+ *
+ * Ensures:
+ *
+ *\li On success, *wantsdnssecp will be ISC_TRUE if and only if 'name'
+ * is at or beneath a trusted key.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *
+ *\li Any other result is an error.
+ */
+
+dst_key_t *
+dns_keynode_key(dns_keynode_t *keynode);
+/*%<
+ * Get the DST key associated with keynode.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_KEYTABLE_H */
diff --git a/lib/dns/include/dns/keyvalues.h b/lib/dns/include/dns/keyvalues.h
new file mode 100644
index 0000000..7040389
--- /dev/null
+++ b/lib/dns/include/dns/keyvalues.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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: keyvalues.h,v 1.23 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef DNS_KEYVALUES_H
+#define DNS_KEYVALUES_H 1
+
+/*! \file dns/keyvalues.h */
+
+/*
+ * Flags field of the KEY RR rdata
+ */
+#define DNS_KEYFLAG_TYPEMASK 0xC000 /*%< Mask for "type" bits */
+#define DNS_KEYTYPE_AUTHCONF 0x0000 /*%< Key usable for both */
+#define DNS_KEYTYPE_CONFONLY 0x8000 /*%< Key usable for confidentiality */
+#define DNS_KEYTYPE_AUTHONLY 0x4000 /*%< Key usable for authentication */
+#define DNS_KEYTYPE_NOKEY 0xC000 /*%< No key usable for either; no key */
+#define DNS_KEYTYPE_NOAUTH DNS_KEYTYPE_CONFONLY
+#define DNS_KEYTYPE_NOCONF DNS_KEYTYPE_AUTHONLY
+
+#define DNS_KEYFLAG_RESERVED2 0x2000 /*%< reserved - must be zero */
+#define DNS_KEYFLAG_EXTENDED 0x1000 /*%< key has extended flags */
+#define DNS_KEYFLAG_RESERVED4 0x0800 /*%< reserved - must be zero */
+#define DNS_KEYFLAG_RESERVED5 0x0400 /*%< reserved - must be zero */
+#define DNS_KEYFLAG_OWNERMASK 0x0300 /*%< these bits determine the type */
+#define DNS_KEYOWNER_USER 0x0000 /*%< key is assoc. with user */
+#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_RESERVED8 0x0080 /*%< reserved - must be zero */
+#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 */
+#define DNS_KEYFLAG_SIGNATORYMASK 0x000F /*%< key can sign RR's of same name */
+
+#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 )
+#define DNS_KEYFLAG_KSK 0x0001 /*%< key signing key */
+
+#define DNS_KEYFLAG_RESERVEDMASK2 0xFFFF /*%< no bits defined here */
+
+/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
+#define DNS_KEYALG_RSAMD5 1 /*%< RSA with MD5 */
+#define DNS_KEYALG_RSA DNS_KEYALG_RSAMD5
+#define DNS_KEYALG_DH 2 /*%< Diffie Hellman KEY */
+#define DNS_KEYALG_DSA 3 /*%< DSA KEY */
+#define DNS_KEYALG_NSEC3DSA 6
+#define DNS_KEYALG_DSS DNS_ALG_DSA
+#define DNS_KEYALG_ECC 4
+#define DNS_KEYALG_RSASHA1 5
+#define DNS_KEYALG_NSEC3RSASHA1 7
+#define DNS_KEYALG_INDIRECT 252
+#define DNS_KEYALG_PRIVATEDNS 253
+#define DNS_KEYALG_PRIVATEOID 254 /*%< Key begins with OID giving alg */
+
+/* Protocol values */
+#define DNS_KEYPROTO_RESERVED 0
+#define DNS_KEYPROTO_TLS 1
+#define DNS_KEYPROTO_EMAIL 2
+#define DNS_KEYPROTO_DNSSEC 3
+#define DNS_KEYPROTO_IPSEC 4
+#define DNS_KEYPROTO_ANY 255
+
+/* Signatures */
+#define DNS_SIG_RSAMINBITS 512 /*%< Size of a mod or exp in bits */
+#define DNS_SIG_RSAMAXBITS 2552
+ /* Total of binary mod and exp */
+#define DNS_SIG_RSAMAXBYTES ((DNS_SIG_RSAMAXBITS+7/8)*2+3)
+ /*%< Max length of text sig block */
+#define DNS_SIG_RSAMAXBASE64 (((DNS_SIG_RSAMAXBYTES+2)/3)*4)
+#define DNS_SIG_RSAMINSIZE ((DNS_SIG_RSAMINBITS+7)/8)
+#define DNS_SIG_RSAMAXSIZE ((DNS_SIG_RSAMAXBITS+7)/8)
+
+#define DNS_SIG_DSASIGSIZE 41
+#define DNS_SIG_DSAMINBITS 512
+#define DNS_SIG_DSAMAXBITS 1024
+#define DNS_SIG_DSAMINBYTES 213
+#define DNS_SIG_DSAMAXBYTES 405
+
+#endif /* DNS_KEYVALUES_H */
diff --git a/lib/dns/include/dns/lib.h b/lib/dns/include/dns/lib.h
new file mode 100644
index 0000000..fd3325b
--- /dev/null
+++ b/lib/dns/include/dns/lib.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: lib.h,v 1.16 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_LIB_H
+#define DNS_LIB_H 1
+
+/*! \file dns/lib.h */
+
+#include <isc/types.h>
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * Tuning: external query load in packets per seconds.
+ */
+LIBDNS_EXTERNAL_DATA extern unsigned int dns_pps;
+LIBDNS_EXTERNAL_DATA extern isc_msgcat_t *dns_msgcat;
+
+void
+dns_lib_initmsgcat(void);
+/*%<
+ * Initialize the DNS library's message catalog, dns_msgcat, if it
+ * has not already been initialized.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_LIB_H */
diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h
new file mode 100644
index 0000000..5adcedd
--- /dev/null
+++ b/lib/dns/include/dns/log.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2004-2007 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
+ * 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: log.h,v 1.42 2007/06/18 23:47:42 tbox Exp $ */
+
+/*! \file dns/log.h
+ * \author Principal Authors: DCL */
+
+#ifndef DNS_LOG_H
+#define DNS_LOG_H 1
+
+#include <isc/lang.h>
+#include <isc/log.h>
+
+LIBDNS_EXTERNAL_DATA extern isc_log_t *dns_lctx;
+LIBDNS_EXTERNAL_DATA extern isc_logcategory_t dns_categories[];
+LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[];
+
+#define DNS_LOGCATEGORY_NOTIFY (&dns_categories[0])
+#define DNS_LOGCATEGORY_DATABASE (&dns_categories[1])
+#define DNS_LOGCATEGORY_SECURITY (&dns_categories[2])
+/* DNS_LOGCATEGORY_CONFIG superseded by CFG_LOGCATEGORY_CONFIG */
+#define DNS_LOGCATEGORY_DNSSEC (&dns_categories[4])
+#define DNS_LOGCATEGORY_RESOLVER (&dns_categories[5])
+#define DNS_LOGCATEGORY_XFER_IN (&dns_categories[6])
+#define DNS_LOGCATEGORY_XFER_OUT (&dns_categories[7])
+#define DNS_LOGCATEGORY_DISPATCH (&dns_categories[8])
+#define DNS_LOGCATEGORY_LAME_SERVERS (&dns_categories[9])
+#define DNS_LOGCATEGORY_DELEGATION_ONLY (&dns_categories[10])
+#define DNS_LOGCATEGORY_EDNS_DISABLED (&dns_categories[11])
+
+/* Backwards compatibility. */
+#define DNS_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL
+
+#define DNS_LOGMODULE_DB (&dns_modules[0])
+#define DNS_LOGMODULE_RBTDB (&dns_modules[1])
+#define DNS_LOGMODULE_RBTDB64 (&dns_modules[2])
+#define DNS_LOGMODULE_RBT (&dns_modules[3])
+#define DNS_LOGMODULE_RDATA (&dns_modules[4])
+#define DNS_LOGMODULE_MASTER (&dns_modules[5])
+#define DNS_LOGMODULE_MESSAGE (&dns_modules[6])
+#define DNS_LOGMODULE_CACHE (&dns_modules[7])
+#define DNS_LOGMODULE_CONFIG (&dns_modules[8])
+#define DNS_LOGMODULE_RESOLVER (&dns_modules[9])
+#define DNS_LOGMODULE_ZONE (&dns_modules[10])
+#define DNS_LOGMODULE_JOURNAL (&dns_modules[11])
+#define DNS_LOGMODULE_ADB (&dns_modules[12])
+#define DNS_LOGMODULE_XFER_IN (&dns_modules[13])
+#define DNS_LOGMODULE_XFER_OUT (&dns_modules[14])
+#define DNS_LOGMODULE_ACL (&dns_modules[15])
+#define DNS_LOGMODULE_VALIDATOR (&dns_modules[16])
+#define DNS_LOGMODULE_DISPATCH (&dns_modules[17])
+#define DNS_LOGMODULE_REQUEST (&dns_modules[18])
+#define DNS_LOGMODULE_MASTERDUMP (&dns_modules[19])
+#define DNS_LOGMODULE_TSIG (&dns_modules[20])
+#define DNS_LOGMODULE_TKEY (&dns_modules[21])
+#define DNS_LOGMODULE_SDB (&dns_modules[22])
+#define DNS_LOGMODULE_DIFF (&dns_modules[23])
+#define DNS_LOGMODULE_HINTS (&dns_modules[24])
+#define DNS_LOGMODULE_ACACHE (&dns_modules[25])
+#define DNS_LOGMODULE_DLZ (&dns_modules[26])
+
+ISC_LANG_BEGINDECLS
+
+void
+dns_log_init(isc_log_t *lctx);
+/*%
+ * Make the libdns categories and modules available for use with the
+ * ISC logging library.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ *\li dns_log_init() is called only once.
+ *
+ * Ensures:
+ * \li The catgories and modules defined above are available for
+ * use by isc_log_usechannnel() and isc_log_write().
+ */
+
+void
+dns_log_setcontext(isc_log_t *lctx);
+/*%
+ * Make the libdns library use the provided context for logging internal
+ * messages.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_LOG_H */
diff --git a/lib/dns/include/dns/lookup.h b/lib/dns/include/dns/lookup.h
new file mode 100644
index 0000000..10f816f
--- /dev/null
+++ b/lib/dns/include/dns/lookup.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2004-2007 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: lookup.h,v 1.12 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_LOOKUP_H
+#define DNS_LOOKUP_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/lookup.h
+ * \brief
+ * The lookup module performs simple DNS lookups. It implements
+ * the full resolver algorithm, both looking for local data and
+ * resoving external names as necessary.
+ *
+ * MP:
+ *\li The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li RFCs: 1034, 1035, 2181, TBS
+ *\li Drafts: TBS
+ */
+
+#include <isc/lang.h>
+#include <isc/event.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * A 'dns_lookupevent_t' is returned when a lookup completes.
+ * The sender field will be set to the lookup that completed. If 'result'
+ * is ISC_R_SUCCESS, then 'names' will contain a list of names associated
+ * with the address. The recipient of the event must not change the list
+ * and must not refer to any of the name data after the event is freed.
+ */
+typedef struct dns_lookupevent {
+ ISC_EVENT_COMMON(struct dns_lookupevent);
+ isc_result_t result;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ dns_db_t *db;
+ dns_dbnode_t *node;
+} dns_lookupevent_t;
+
+isc_result_t
+dns_lookup_create(isc_mem_t *mctx, dns_name_t *name, dns_rdatatype_t type,
+ dns_view_t *view, unsigned int options, isc_task_t *task,
+ isc_taskaction_t action, void *arg, dns_lookup_t **lookupp);
+/*%<
+ * Finds the rrsets matching 'name' and 'type'.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid mctx.
+ *
+ *\li 'name' is a valid name.
+ *
+ *\li 'view' is a valid view which has a resolver.
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li lookupp != NULL && *lookupp == NULL
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOMEMORY
+ *
+ *\li Any resolver-related error (e.g. ISC_R_SHUTTINGDOWN) may also be
+ * returned.
+ */
+
+void
+dns_lookup_cancel(dns_lookup_t *lookup);
+/*%<
+ * Cancel 'lookup'.
+ *
+ * Notes:
+ *
+ *\li If 'lookup' has not completed, post its LOOKUPDONE event with a
+ * result code of ISC_R_CANCELED.
+ *
+ * Requires:
+ *
+ *\li 'lookup' is a valid lookup.
+ */
+
+void
+dns_lookup_destroy(dns_lookup_t **lookupp);
+/*%<
+ * Destroy 'lookup'.
+ *
+ * Requires:
+ *
+ *\li '*lookupp' is a valid lookup.
+ *
+ *\li The caller has received the LOOKUPDONE event (either because the
+ * lookup completed or because dns_lookup_cancel() was called).
+ *
+ * Ensures:
+ *
+ *\li *lookupp == NULL.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_LOOKUP_H */
diff --git a/lib/dns/include/dns/master.h b/lib/dns/include/dns/master.h
new file mode 100644
index 0000000..93a782d
--- /dev/null
+++ b/lib/dns/include/dns/master.h
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: master.h,v 1.51 2008/04/02 02:37:42 marka Exp $ */
+
+#ifndef DNS_MASTER_H
+#define DNS_MASTER_H 1
+
+/*! \file dns/master.h */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+/*
+ * Flags to be passed in the 'options' argument in the functions below.
+ */
+#define DNS_MASTER_AGETTL 0x00000001 /*%< Age the ttl based on $DATE. */
+#define DNS_MASTER_MANYERRORS 0x00000002 /*%< Continue processing on errors. */
+#define DNS_MASTER_NOINCLUDE 0x00000004 /*%< Disallow $INCLUDE directives. */
+#define DNS_MASTER_ZONE 0x00000008 /*%< Loading a zone master file. */
+#define DNS_MASTER_HINT 0x00000010 /*%< Loading a hint master file. */
+#define DNS_MASTER_SLAVE 0x00000020 /*%< Loading a slave master file. */
+#define DNS_MASTER_CHECKNS 0x00000040 /*%<
+ * Check NS records to see
+ * if they are an address
+ */
+#define DNS_MASTER_FATALNS 0x00000080 /*%<
+ * Treat DNS_MASTER_CHECKNS
+ * matches as fatal
+ */
+#define DNS_MASTER_CHECKNAMES 0x00000100
+#define DNS_MASTER_CHECKNAMESFAIL 0x00000200
+#define DNS_MASTER_CHECKWILDCARD 0x00000400 /* Check for internal wildcards. */
+#define DNS_MASTER_CHECKMX 0x00000800
+#define DNS_MASTER_CHECKMXFAIL 0x00001000
+
+#define DNS_MASTER_RESIGN 0x00002000
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Structures that implement the "raw" format for master dump.
+ * These are provided for a reference purpose only; in the actual
+ * encoding, we directly read/write each field so that the encoded data
+ * is always "packed", regardless of the hardware architecture.
+ */
+#define DNS_RAWFORMAT_VERSION 0
+
+/* Common header */
+typedef struct {
+ isc_uint32_t format; /* must be
+ * dns_masterformat_raw */
+ isc_uint32_t version; /* compatibility for future
+ * extensions */
+ isc_uint32_t dumptime; /* timestamp on creation
+ * (currently unused)
+ */
+} dns_masterrawheader_t;
+
+/* The structure for each RRset */
+typedef struct {
+ isc_uint32_t totallen; /* length of the data for this
+ * RRset, including the
+ * "header" part */
+ dns_rdataclass_t rdclass; /* 16-bit class */
+ dns_rdatatype_t type; /* 16-bit type */
+ dns_rdatatype_t covers; /* same as type */
+ dns_ttl_t ttl; /* 32-bit TTL */
+ isc_uint32_t nrdata; /* number of RRs in this set */
+ /* followed by encoded owner name, and then rdata */
+} dns_masterrawrdataset_t;
+
+/***
+ *** Function
+ ***/
+
+isc_result_t
+dns_master_loadfile(const char *master_file,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks,
+ isc_mem_t *mctx);
+
+isc_result_t
+dns_master_loadfile2(const char *master_file,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks,
+ isc_mem_t *mctx,
+ dns_masterformat_t format);
+
+isc_result_t
+dns_master_loadfile3(const char *master_file,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ isc_uint32_t resign,
+ dns_rdatacallbacks_t *callbacks,
+ isc_mem_t *mctx,
+ dns_masterformat_t format);
+
+isc_result_t
+dns_master_loadstream(FILE *stream,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks,
+ isc_mem_t *mctx);
+
+isc_result_t
+dns_master_loadbuffer(isc_buffer_t *buffer,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks,
+ isc_mem_t *mctx);
+
+isc_result_t
+dns_master_loadlexer(isc_lex_t *lex,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks,
+ isc_mem_t *mctx);
+
+isc_result_t
+dns_master_loadfileinc(const char *master_file,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks,
+ isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **ctxp, isc_mem_t *mctx);
+
+isc_result_t
+dns_master_loadfileinc2(const char *master_file,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks,
+ isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **ctxp, isc_mem_t *mctx,
+ dns_masterformat_t format);
+
+isc_result_t
+dns_master_loadfileinc3(const char *master_file,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ isc_uint32_t resign,
+ dns_rdatacallbacks_t *callbacks,
+ isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **ctxp, isc_mem_t *mctx,
+ dns_masterformat_t format);
+
+isc_result_t
+dns_master_loadstreaminc(FILE *stream,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks,
+ isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **ctxp, isc_mem_t *mctx);
+
+isc_result_t
+dns_master_loadbufferinc(isc_buffer_t *buffer,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks,
+ isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **ctxp, isc_mem_t *mctx);
+
+isc_result_t
+dns_master_loadlexerinc(isc_lex_t *lex,
+ dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks,
+ isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **ctxp, isc_mem_t *mctx);
+
+/*%<
+ * Loads a RFC1305 master file from a file, stream, buffer, or existing
+ * lexer into rdatasets and then calls 'callbacks->commit' to commit the
+ * rdatasets. Rdata memory belongs to dns_master_load and will be
+ * reused / released when the callback completes. dns_load_master will
+ * abort if callbacks->commit returns any value other than ISC_R_SUCCESS.
+ *
+ * If 'DNS_MASTER_AGETTL' is set and the master file contains one or more
+ * $DATE directives, the TTLs of the data will be aged accordingly.
+ *
+ * 'callbacks->commit' is assumed to call 'callbacks->error' or
+ * 'callbacks->warn' to generate any error messages required.
+ *
+ * 'done' is called with 'done_arg' and a result code when the loading
+ * is completed or has failed. If the initial setup fails 'done' is
+ * not called.
+ *
+ * 'resign' the number of seconds before a RRSIG expires that it should
+ * be re-signed. 0 is used if not provided.
+ *
+ * Requires:
+ *\li 'master_file' points to a valid string.
+ *\li 'lexer' points to a valid lexer.
+ *\li 'top' points to a valid name.
+ *\li 'origin' points to a valid name.
+ *\li 'callbacks->commit' points to a valid function.
+ *\li 'callbacks->error' points to a valid function.
+ *\li 'callbacks->warn' points to a valid function.
+ *\li 'mctx' points to a valid memory context.
+ *\li 'task' and 'done' to be valid.
+ *\li 'lmgr' to be valid.
+ *\li 'ctxp != NULL && ctxp == NULL'.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS upon successfully loading the master file.
+ *\li ISC_R_SEENINCLUDE upon successfully loading the master file with
+ * a $INCLUDE statement.
+ *\li ISC_R_NOMEMORY out of memory.
+ *\li ISC_R_UNEXPECTEDEND expected to be able to read a input token and
+ * there was not one.
+ *\li ISC_R_UNEXPECTED
+ *\li DNS_R_NOOWNER failed to specify a ownername.
+ *\li DNS_R_NOTTL failed to specify a ttl.
+ *\li DNS_R_BADCLASS record class did not match zone class.
+ *\li DNS_R_CONTINUE load still in progress (dns_master_load*inc() only).
+ *\li Any dns_rdata_fromtext() error code.
+ *\li Any error code from callbacks->commit().
+ */
+
+void
+dns_loadctx_detach(dns_loadctx_t **ctxp);
+/*%<
+ * Detach from the load context.
+ *
+ * Requires:
+ *\li '*ctxp' to be valid.
+ *
+ * Ensures:
+ *\li '*ctxp == NULL'
+ */
+
+void
+dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target);
+/*%<
+ * Attach to the load context.
+ *
+ * Requires:
+ *\li 'source' to be valid.
+ *\li 'target != NULL && *target == NULL'.
+ */
+
+void
+dns_loadctx_cancel(dns_loadctx_t *ctx);
+/*%<
+ * Cancel loading the zone file associated with this load context.
+ *
+ * Requires:
+ *\li 'ctx' to be valid
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_MASTER_H */
diff --git a/lib/dns/include/dns/masterdump.h b/lib/dns/include/dns/masterdump.h
new file mode 100644
index 0000000..42521b3
--- /dev/null
+++ b/lib/dns/include/dns/masterdump.h
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: masterdump.h,v 1.42 2008/09/24 02:46:23 marka Exp $ */
+
+#ifndef DNS_MASTERDUMP_H
+#define DNS_MASTERDUMP_H 1
+
+/*! \file dns/masterdump.h */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+/***
+ *** Types
+ ***/
+
+typedef struct dns_master_style dns_master_style_t;
+
+/***
+ *** Definitions
+ ***/
+
+/*
+ * Flags affecting master file formatting. Flags 0x0000FFFF
+ * define the formatting of the rdata part and are defined in
+ * rdata.h.
+ */
+
+/*% Omit the owner name when possible. */
+#define DNS_STYLEFLAG_OMIT_OWNER 0x00010000U
+
+/*%
+ * Omit the TTL when possible. If DNS_STYLEFLAG_TTL is
+ * also set, this means no TTLs are ever printed
+ * because $TTL directives are generated before every
+ * change in the TTL. In this case, no columns need to
+ * be reserved for the TTL. Master files generated with
+ * these options will be rejected by BIND 4.x because it
+ * does not recognize the $TTL directive.
+ *
+ * If DNS_STYLEFLAG_TTL is not also set, the TTL will be
+ * omitted when it is equal to the previous TTL.
+ * This is correct according to RFC1035, but the
+ * TTLs may be silently misinterpreted by older
+ * versions of BIND which use the SOA MINTTL as a
+ * default TTL value.
+ */
+#define DNS_STYLEFLAG_OMIT_TTL 0x00020000U
+
+/*% Omit the class when possible. */
+#define DNS_STYLEFLAG_OMIT_CLASS 0x00040000U
+
+/*% Output $TTL directives. */
+#define DNS_STYLEFLAG_TTL 0x00080000U
+
+/*%
+ * Output $ORIGIN directives and print owner names relative to
+ * the origin when possible.
+ */
+#define DNS_STYLEFLAG_REL_OWNER 0x00100000U
+
+/*% Print domain names in RR data in relative form when possible.
+ For this to take effect, DNS_STYLEFLAG_REL_OWNER must also be set. */
+#define DNS_STYLEFLAG_REL_DATA 0x00200000U
+
+/*% Print the trust level of each rdataset. */
+#define DNS_STYLEFLAG_TRUST 0x00400000U
+
+/*% Print negative caching entries. */
+#define DNS_STYLEFLAG_NCACHE 0x00800000U
+
+/*% Never print the TTL. */
+#define DNS_STYLEFLAG_NO_TTL 0x01000000U
+
+/*% Never print the CLASS. */
+#define DNS_STYLEFLAG_NO_CLASS 0x02000000U
+
+/*% Report re-signing time. */
+#define DNS_STYLEFLAG_RESIGN 0x04000000U
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Constants
+ ***/
+
+/*%
+ * The default master file style.
+ *
+ * This uses $TTL directives to avoid the need to dedicate a
+ * tab stop for the TTL. The class is only printed for the first
+ * rrset in the file and shares a tab stop with the RR type.
+ */
+LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_default;
+
+/*%
+ * A master file style that dumps zones to a very generic format easily
+ * imported/checked with external tools.
+ */
+LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_full;
+
+/*%
+ * A master file style that prints explicit TTL values on each
+ * record line, never using $TTL statements. The TTL has a tab
+ * stop of its own, but the class and type share one.
+ */
+LIBDNS_EXTERNAL_DATA extern const dns_master_style_t
+ dns_master_style_explicitttl;
+
+/*%
+ * A master style format designed for cache files. It prints explicit TTL
+ * values on each record line and never uses $ORIGIN or relative names.
+ */
+LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_cache;
+
+/*%
+ * A master style that prints name, ttl, class, type, and value on
+ * every line. Similar to explicitttl above, but more verbose.
+ * Intended for generating master files which can be easily parsed
+ * by perl scripts and similar applications.
+ */
+LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_simple;
+
+/*%
+ * The style used for debugging, "dig" output, etc.
+ */
+LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_debug;
+
+/***
+ *** Functions
+ ***/
+
+void
+dns_dumpctx_attach(dns_dumpctx_t *source, dns_dumpctx_t **target);
+/*%<
+ * Attach to a dump context.
+ *
+ * Require:
+ *\li 'source' to be valid.
+ *\li 'target' to be non NULL and '*target' to be NULL.
+ */
+
+void
+dns_dumpctx_detach(dns_dumpctx_t **dctxp);
+/*%<
+ * Detach from a dump context.
+ *
+ * Require:
+ *\li 'dctxp' to point to a valid dump context.
+ *
+ * Ensures:
+ *\li '*dctxp' is NULL.
+ */
+
+void
+dns_dumpctx_cancel(dns_dumpctx_t *dctx);
+/*%<
+ * Cancel a in progress dump.
+ *
+ * Require:
+ *\li 'dctx' to be valid.
+ */
+
+dns_dbversion_t *
+dns_dumpctx_version(dns_dumpctx_t *dctx);
+/*%<
+ * Return the version handle (if any) of the database being dumped.
+ *
+ * Require:
+ *\li 'dctx' to be valid.
+ */
+
+dns_db_t *
+dns_dumpctx_db(dns_dumpctx_t *dctx);
+/*%<
+ * Return the database being dumped.
+ *
+ * Require:
+ *\li 'dctx' to be valid.
+ */
+
+
+/*@{*/
+isc_result_t
+dns_master_dumptostreaminc(isc_mem_t *mctx, dns_db_t *db,
+ dns_dbversion_t *version,
+ const dns_master_style_t *style, FILE *f,
+ isc_task_t *task, dns_dumpdonefunc_t done,
+ void *done_arg, dns_dumpctx_t **dctxp);
+
+isc_result_t
+dns_master_dumptostream(isc_mem_t *mctx, dns_db_t *db,
+ dns_dbversion_t *version,
+ const dns_master_style_t *style, FILE *f);
+
+isc_result_t
+dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db,
+ dns_dbversion_t *version,
+ const dns_master_style_t *style,
+ dns_masterformat_t format, FILE *f);
+/*%<
+ * Dump the database 'db' to the steam 'f' in the specified format by
+ * 'format'. If the format is dns_masterformat_text (the RFC1035 format),
+ * 'style' specifies the file style (e.g., &dns_master_style_default).
+ *
+ * dns_master_dumptostream() is an old form of dns_master_dumptostream2(),
+ * which always specifies the dns_masterformat_text format.
+ *
+ * Temporary dynamic memory may be allocated from 'mctx'.
+ *
+ * Require:
+ *\li 'task' to be valid.
+ *\li 'done' to be non NULL.
+ *\li 'dctxp' to be non NULL && '*dctxp' to be NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_CONTINUE dns_master_dumptostreaminc() only.
+ *\li ISC_R_NOMEMORY
+ *\li Any database or rrset iterator error.
+ *\li Any dns_rdata_totext() error code.
+ */
+/*@}*/
+
+/*@{*/
+isc_result_t
+dns_master_dumpinc(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
+ const dns_master_style_t *style, const char *filename,
+ isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,
+ dns_dumpctx_t **dctxp);
+
+isc_result_t
+dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
+ const dns_master_style_t *style, const char *filename,
+ isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg, dns_dumpctx_t **dctxp, dns_masterformat_t format);
+
+isc_result_t
+dns_master_dump(isc_mem_t *mctx, dns_db_t *db,
+ dns_dbversion_t *version,
+ const dns_master_style_t *style, const char *filename);
+
+isc_result_t
+dns_master_dump2(isc_mem_t *mctx, dns_db_t *db,
+ dns_dbversion_t *version,
+ const dns_master_style_t *style, const char *filename,
+ dns_masterformat_t format);
+
+/*%<
+ * Dump the database 'db' to the file 'filename' in the specified format by
+ * 'format'. If the format is dns_masterformat_text (the RFC1035 format),
+ * 'style' specifies the file style (e.g., &dns_master_style_default).
+ *
+ * dns_master_dumpinc() and dns_master_dump() are old forms of _dumpinc2()
+ * and _dump2(), respectively, which always specify the dns_masterformat_text
+ * format.
+ *
+ * Temporary dynamic memory may be allocated from 'mctx'.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_CONTINUE dns_master_dumpinc() only.
+ *\li ISC_R_NOMEMORY
+ *\li Any database or rrset iterator error.
+ *\li Any dns_rdata_totext() error code.
+ */
+/*@}*/
+
+isc_result_t
+dns_master_rdatasettotext(dns_name_t *owner_name,
+ dns_rdataset_t *rdataset,
+ const dns_master_style_t *style,
+ isc_buffer_t *target);
+/*%<
+ * Convert 'rdataset' to text format, storing the result in 'target'.
+ *
+ * Notes:
+ *\li The rdata cursor position will be changed.
+ *
+ * Requires:
+ *\li 'rdataset' is a valid non-question rdataset.
+ *
+ *\li 'rdataset' is not empty.
+ */
+
+isc_result_t
+dns_master_questiontotext(dns_name_t *owner_name,
+ dns_rdataset_t *rdataset,
+ const dns_master_style_t *style,
+ isc_buffer_t *target);
+
+isc_result_t
+dns_master_dumpnodetostream(isc_mem_t *mctx, dns_db_t *db,
+ dns_dbversion_t *version,
+ dns_dbnode_t *node, dns_name_t *name,
+ const dns_master_style_t *style,
+ FILE *f);
+
+isc_result_t
+dns_master_dumpnode(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
+ dns_dbnode_t *node, dns_name_t *name,
+ const dns_master_style_t *style, const char *filename);
+
+isc_result_t
+dns_master_stylecreate(dns_master_style_t **style, unsigned int flags,
+ unsigned int ttl_column, unsigned int class_column,
+ unsigned int type_column, unsigned int rdata_column,
+ unsigned int line_length, unsigned int tab_width,
+ isc_mem_t *mctx);
+
+void
+dns_master_styledestroy(dns_master_style_t **style, isc_mem_t *mctx);
+
+const char *
+dns_trust_totext(dns_trust_t trust);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_MASTERDUMP_H */
diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h
new file mode 100644
index 0000000..0ed2ef7
--- /dev/null
+++ b/lib/dns/include/dns/message.h
@@ -0,0 +1,1343 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: message.h,v 1.125 2008/04/03 06:09:04 tbox Exp $ */
+
+#ifndef DNS_MESSAGE_H
+#define DNS_MESSAGE_H 1
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+
+#include <dns/compress.h>
+#include <dns/masterdump.h>
+#include <dns/types.h>
+
+#include <dst/dst.h>
+
+/*! \file dns/message.h
+ * \brief Message Handling Module
+ *
+ * How this beast works:
+ *
+ * When a dns message is received in a buffer, dns_message_fromwire() is called
+ * on the memory region. Various items are checked including the format
+ * of the message (if counts are right, if counts consume the entire sections,
+ * and if sections consume the entire message) and known pseudo-RRs in the
+ * additional data section are analyzed and removed.
+ *
+ * TSIG checking is also done at this layer, and any DNSSEC transaction
+ * signatures should also be checked here.
+ *
+ * Notes on using the gettemp*() and puttemp*() functions:
+ *
+ * These functions return items (names, rdatasets, etc) allocated from some
+ * internal state of the dns_message_t.
+ *
+ * Names and rdatasets must be put back into the dns_message_t in
+ * one of two ways. Assume a name was allocated via
+ * dns_message_gettempname():
+ *
+ *\li (1) insert it into a section, using dns_message_addname().
+ *
+ *\li (2) return it to the message using dns_message_puttempname().
+ *
+ * The same applies to rdatasets.
+ *
+ * On the other hand, offsets, rdatalists and rdatas allocated using
+ * dns_message_gettemp*() will always be freed automatically
+ * when the message is reset or destroyed; calling dns_message_puttemp*()
+ * on rdatalists and rdatas is optional and serves only to enable the item
+ * to be reused multiple times during the lifetime of the message; offsets
+ * cannot be reused.
+ *
+ * Buffers allocated using isc_buffer_allocate() can be automatically freed
+ * as well by giving the buffer to the message using dns_message_takebuffer().
+ * Doing this will cause the buffer to be freed using isc_buffer_free()
+ * when the section lists are cleared, such as in a reset or in a destroy.
+ * Since the buffer itself exists until the message is destroyed, this sort
+ * of code can be written:
+ *
+ * \code
+ * buffer = isc_buffer_allocate(mctx, 512);
+ * name = NULL;
+ * name = dns_message_gettempname(message, &name);
+ * dns_name_init(name, NULL);
+ * result = dns_name_fromtext(name, &source, dns_rootname, ISC_FALSE,
+ * buffer);
+ * dns_message_takebuffer(message, &buffer);
+ * \endcode
+ *
+ *
+ * TODO:
+ *
+ * XXX Needed: ways to set and retrieve EDNS information, add rdata to a
+ * section, move rdata from one section to another, remove rdata, etc.
+ */
+
+#define DNS_MESSAGEFLAG_QR 0x8000U
+#define DNS_MESSAGEFLAG_AA 0x0400U
+#define DNS_MESSAGEFLAG_TC 0x0200U
+#define DNS_MESSAGEFLAG_RD 0x0100U
+#define DNS_MESSAGEFLAG_RA 0x0080U
+#define DNS_MESSAGEFLAG_AD 0x0020U
+#define DNS_MESSAGEFLAG_CD 0x0010U
+
+/*%< EDNS0 extended message flags */
+#define DNS_MESSAGEEXTFLAG_DO 0x8000U
+
+/*%< EDNS0 extended OPT codes */
+#define DNS_OPT_NSID 0x0003 /*%< NSID opt code */
+
+#define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD)
+#define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO)
+
+#define DNS_MESSAGE_HEADERLEN 12 /*%< 6 isc_uint16_t's */
+
+#define DNS_MESSAGE_MAGIC ISC_MAGIC('M','S','G','@')
+#define DNS_MESSAGE_VALID(msg) ISC_MAGIC_VALID(msg, DNS_MESSAGE_MAGIC)
+
+/*
+ * Ordering here matters. DNS_SECTION_ANY must be the lowest and negative,
+ * and DNS_SECTION_MAX must be one greater than the last used section.
+ */
+typedef int dns_section_t;
+#define DNS_SECTION_ANY (-1)
+#define DNS_SECTION_QUESTION 0
+#define DNS_SECTION_ANSWER 1
+#define DNS_SECTION_AUTHORITY 2
+#define DNS_SECTION_ADDITIONAL 3
+#define DNS_SECTION_MAX 4
+
+typedef int dns_pseudosection_t;
+#define DNS_PSEUDOSECTION_ANY (-1)
+#define DNS_PSEUDOSECTION_OPT 0
+#define DNS_PSEUDOSECTION_TSIG 1
+#define DNS_PSEUDOSECTION_SIG0 2
+#define DNS_PSEUDOSECTION_MAX 3
+
+typedef int dns_messagetextflag_t;
+#define DNS_MESSAGETEXTFLAG_NOCOMMENTS 0x0001
+#define DNS_MESSAGETEXTFLAG_NOHEADERS 0x0002
+
+/*
+ * Dynamic update names for these sections.
+ */
+#define DNS_SECTION_ZONE DNS_SECTION_QUESTION
+#define DNS_SECTION_PREREQUISITE DNS_SECTION_ANSWER
+#define DNS_SECTION_UPDATE DNS_SECTION_AUTHORITY
+
+/*
+ * These tell the message library how the created dns_message_t will be used.
+ */
+#define DNS_MESSAGE_INTENTUNKNOWN 0 /*%< internal use only */
+#define DNS_MESSAGE_INTENTPARSE 1 /*%< parsing messages */
+#define DNS_MESSAGE_INTENTRENDER 2 /*%< rendering */
+
+/*
+ * Control behavior of parsing
+ */
+#define DNS_MESSAGEPARSE_PRESERVEORDER 0x0001 /*%< preserve rdata order */
+#define DNS_MESSAGEPARSE_BESTEFFORT 0x0002 /*%< return a message if a
+ recoverable parse error
+ occurs */
+#define DNS_MESSAGEPARSE_CLONEBUFFER 0x0004 /*%< save a copy of the
+ source buffer */
+#define DNS_MESSAGEPARSE_IGNORETRUNCATION 0x0008 /*%< trucation errors are
+ * not fatal. */
+
+/*
+ * Control behavior of rendering
+ */
+#define DNS_MESSAGERENDER_ORDERED 0x0001 /*%< don't change order */
+#define DNS_MESSAGERENDER_PARTIAL 0x0002 /*%< allow a partial rdataset */
+#define DNS_MESSAGERENDER_OMITDNSSEC 0x0004 /*%< omit DNSSEC records */
+#define DNS_MESSAGERENDER_PREFER_A 0x0008 /*%< prefer A records in
+ additional section. */
+#define DNS_MESSAGERENDER_PREFER_AAAA 0x0010 /*%< prefer AAAA records in
+ additional section. */
+
+typedef struct dns_msgblock dns_msgblock_t;
+
+struct dns_message {
+ /* public from here down */
+ unsigned int magic;
+
+ dns_messageid_t id;
+ unsigned int flags;
+ dns_rcode_t rcode;
+ unsigned int opcode;
+ dns_rdataclass_t rdclass;
+
+ /* 4 real, 1 pseudo */
+ unsigned int counts[DNS_SECTION_MAX];
+
+ /* private from here down */
+ dns_namelist_t sections[DNS_SECTION_MAX];
+ dns_name_t *cursors[DNS_SECTION_MAX];
+ dns_rdataset_t *opt;
+ dns_rdataset_t *sig0;
+ dns_rdataset_t *tsig;
+
+ int state;
+ unsigned int from_to_wire : 2;
+ unsigned int header_ok : 1;
+ unsigned int question_ok : 1;
+ unsigned int tcp_continuation : 1;
+ unsigned int verified_sig : 1;
+ unsigned int verify_attempted : 1;
+ unsigned int free_query : 1;
+ unsigned int free_saved : 1;
+
+ unsigned int opt_reserved;
+ unsigned int sig_reserved;
+ unsigned int reserved; /* reserved space (render) */
+
+ isc_buffer_t *buffer;
+ dns_compress_t *cctx;
+
+ isc_mem_t *mctx;
+ isc_mempool_t *namepool;
+ isc_mempool_t *rdspool;
+
+ isc_bufferlist_t scratchpad;
+ isc_bufferlist_t cleanup;
+
+ ISC_LIST(dns_msgblock_t) rdatas;
+ ISC_LIST(dns_msgblock_t) rdatalists;
+ ISC_LIST(dns_msgblock_t) offsets;
+
+ ISC_LIST(dns_rdata_t) freerdata;
+ ISC_LIST(dns_rdatalist_t) freerdatalist;
+
+ dns_rcode_t tsigstatus;
+ dns_rcode_t querytsigstatus;
+ dns_name_t *tsigname; /* Owner name of TSIG, if any */
+ dns_rdataset_t *querytsig;
+ dns_tsigkey_t *tsigkey;
+ dst_context_t *tsigctx;
+ int sigstart;
+ int timeadjust;
+
+ dns_name_t *sig0name; /* Owner name of SIG0, if any */
+ dst_key_t *sig0key;
+ dns_rcode_t sig0status;
+ isc_region_t query;
+ isc_region_t saved;
+
+ dns_rdatasetorderfunc_t order;
+ const void * order_arg;
+};
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp);
+
+/*%<
+ * Create msg structure.
+ *
+ * This function will allocate some internal blocks of memory that are
+ * expected to be needed for parsing or rendering nearly any type of message.
+ *
+ * Requires:
+ *\li 'mctx' be a valid memory context.
+ *
+ *\li 'msgp' be non-null and '*msg' be NULL.
+ *
+ *\li 'intent' must be one of DNS_MESSAGE_INTENTPARSE or
+ * #DNS_MESSAGE_INTENTRENDER.
+ *
+ * Ensures:
+ *\li The data in "*msg" is set to indicate an unused and empty msg
+ * structure.
+ *
+ * Returns:
+ *\li #ISC_R_NOMEMORY -- out of memory
+ *\li #ISC_R_SUCCESS -- success
+ */
+
+void
+dns_message_reset(dns_message_t *msg, unsigned int intent);
+/*%<
+ * Reset a message structure to default state. All internal lists are freed
+ * or reset to a default state as well. This is simply a more efficient
+ * way to call dns_message_destroy() followed by dns_message_allocate(),
+ * since it avoid many memory allocations.
+ *
+ * If any data loanouts (buffers, names, rdatas, etc) were requested,
+ * the caller must no longer use them after this call.
+ *
+ * The intended next use of the message will be 'intent'.
+ *
+ * Requires:
+ *
+ *\li 'msg' be valid.
+ *
+ *\li 'intent' is DNS_MESSAGE_INTENTPARSE or DNS_MESSAGE_INTENTRENDER
+ */
+
+void
+dns_message_destroy(dns_message_t **msgp);
+/*%<
+ * Destroy all state in the message.
+ *
+ * Requires:
+ *
+ *\li 'msgp' be valid.
+ *
+ * Ensures:
+ *\li '*msgp' == NULL
+ */
+
+isc_result_t
+dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
+ const dns_master_style_t *style,
+ dns_messagetextflag_t flags,
+ isc_buffer_t *target);
+
+isc_result_t
+dns_message_pseudosectiontotext(dns_message_t *msg,
+ dns_pseudosection_t section,
+ const dns_master_style_t *style,
+ dns_messagetextflag_t flags,
+ isc_buffer_t *target);
+/*%<
+ * Convert section 'section' or 'pseudosection' of message 'msg' to
+ * a cleartext representation
+ *
+ * Notes:
+ * \li See dns_message_totext for meanings of flags.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message.
+ *
+ *\li 'style' is a valid master dump style.
+ *
+ *\li 'target' is a valid buffer.
+ *
+ *\li 'section' is a valid section label.
+ *
+ * Ensures:
+ *
+ *\li If the result is success:
+ * The used space in 'target' is updated.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE
+ *\li #ISC_R_NOMORE
+ *
+ *\li Note: On error return, *target may be partially filled with data.
+*/
+
+isc_result_t
+dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
+ dns_messagetextflag_t flags, isc_buffer_t *target);
+/*%<
+ * Convert all sections of message 'msg' to a cleartext representation
+ *
+ * Notes:
+ * \li In flags, If #DNS_MESSAGETEXTFLAG_OMITDOT is set, then the
+ * final '.' in absolute names will not be emitted. If
+ * #DNS_MESSAGETEXTFLAG_NOCOMMENTS is cleared, lines beginning
+ * with ";;" will be emitted indicating section name. If
+ * #DNS_MESSAGETEXTFLAG_NOHEADERS is cleared, header lines will
+ * be emitted.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message.
+ *
+ *\li 'style' is a valid master dump style.
+ *
+ *\li 'target' is a valid buffer.
+ *
+ * Ensures:
+ *
+ *\li If the result is success:
+ * The used space in 'target' is updated.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE
+ *\li #ISC_R_NOMORE
+ *
+ *\li Note: On error return, *target may be partially filled with data.
+ */
+
+isc_result_t
+dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
+ unsigned int options);
+/*%<
+ * Parse raw wire data in 'source' as a DNS message.
+ *
+ * OPT records are detected and stored in the pseudo-section "opt".
+ * TSIGs are detected and stored in the pseudo-section "tsig".
+ *
+ * If #DNS_MESSAGEPARSE_PRESERVEORDER is set, or if the opcode of the message
+ * is UPDATE, a separate dns_name_t object will be created for each RR in the
+ * message. Each such dns_name_t will have a single rdataset containing the
+ * single RR, and the order of the RRs in the message is preserved.
+ * Otherwise, only one dns_name_t object will be created for each unique
+ * owner name in the section, and each such dns_name_t will have a list
+ * of rdatasets. To access the names and their data, use
+ * dns_message_firstname() and dns_message_nextname().
+ *
+ * If #DNS_MESSAGEPARSE_BESTEFFORT is set, errors in message content will
+ * not be considered FORMERRs. If the entire message can be parsed, it
+ * will be returned and DNS_R_RECOVERABLE will be returned.
+ *
+ * If #DNS_MESSAGEPARSE_IGNORETRUNCATION is set then return as many complete
+ * RR's as possible, DNS_R_RECOVERABLE will be returned.
+ *
+ * OPT and TSIG records are always handled specially, regardless of the
+ * 'preserve_order' setting.
+ *
+ * Requires:
+ *\li "msg" be valid.
+ *
+ *\li "buffer" be a wire format buffer.
+ *
+ * Ensures:
+ *\li The buffer's data format is correct.
+ *
+ *\li The buffer's contents verify as correct regarding header bits, buffer
+ * and rdata sizes, etc.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- all is well
+ *\li #ISC_R_NOMEMORY -- no memory
+ *\li #DNS_R_RECOVERABLE -- the message parsed properly, but contained
+ * errors.
+ *\li Many other errors possible XXXMLG
+ */
+
+isc_result_t
+dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
+ isc_buffer_t *buffer);
+/*%<
+ * Begin rendering on a message. Only one call can be made to this function
+ * per message.
+ *
+ * The compression context is "owned" by the message library until
+ * dns_message_renderend() is called. It must be invalidated by the caller.
+ *
+ * The buffer is "owned" by the message library until dns_message_renderend()
+ * is called.
+ *
+ * Requires:
+ *
+ *\li 'msg' be valid.
+ *
+ *\li 'cctx' be valid.
+ *
+ *\li 'buffer' is a valid buffer.
+ *
+ * Side Effects:
+ *
+ *\li The buffer is cleared before it is used.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- all is well
+ *\li #ISC_R_NOSPACE -- output buffer is too small
+ */
+
+isc_result_t
+dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer);
+/*%<
+ * Reset the buffer. This can be used after growing the old buffer
+ * on a ISC_R_NOSPACE return from most of the render functions.
+ *
+ * On successful completion, the old buffer is no longer used by the
+ * library. The new buffer is owned by the library until
+ * dns_message_renderend() is called.
+ *
+ * Requires:
+ *
+ *\li 'msg' be valid.
+ *
+ *\li dns_message_renderbegin() was called.
+ *
+ *\li buffer != NULL.
+ *
+ * Returns:
+ *\li #ISC_R_NOSPACE -- new buffer is too small
+ *\li #ISC_R_SUCCESS -- all is well.
+ */
+
+isc_result_t
+dns_message_renderreserve(dns_message_t *msg, unsigned int space);
+/*%<
+ * XXXMLG should use size_t rather than unsigned int once the buffer
+ * API is cleaned up
+ *
+ * Reserve "space" bytes in the given buffer.
+ *
+ * Requires:
+ *
+ *\li 'msg' be valid.
+ *
+ *\li dns_message_renderbegin() was called.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- all is well.
+ *\li #ISC_R_NOSPACE -- not enough free space in the buffer.
+ */
+
+void
+dns_message_renderrelease(dns_message_t *msg, unsigned int space);
+/*%<
+ * XXXMLG should use size_t rather than unsigned int once the buffer
+ * API is cleaned up
+ *
+ * Release "space" bytes in the given buffer that was previously reserved.
+ *
+ * Requires:
+ *
+ *\li 'msg' be valid.
+ *
+ *\li 'space' is less than or equal to the total amount of space reserved
+ * via prior calls to dns_message_renderreserve().
+ *
+ *\li dns_message_renderbegin() was called.
+ */
+
+isc_result_t
+dns_message_rendersection(dns_message_t *msg, dns_section_t section,
+ unsigned int options);
+/*%<
+ * Render all names, rdatalists, etc from the given section at the
+ * specified priority or higher.
+ *
+ * Requires:
+ *\li 'msg' be valid.
+ *
+ *\li 'section' be a valid section.
+ *
+ *\li dns_message_renderbegin() was called.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- all records were written, and there are
+ * no more records for this section.
+ *\li #ISC_R_NOSPACE -- Not enough room in the buffer to write
+ * all records requested.
+ *\li #DNS_R_MOREDATA -- All requested records written, and there
+ * are records remaining for this section.
+ */
+
+void
+dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target);
+/*%<
+ * Render the message header. This is implicitly called by
+ * dns_message_renderend().
+ *
+ * Requires:
+ *
+ *\li 'msg' be a valid message.
+ *
+ *\li dns_message_renderbegin() was called.
+ *
+ *\li 'target' is a valid buffer with enough space to hold a message header
+ */
+
+isc_result_t
+dns_message_renderend(dns_message_t *msg);
+/*%<
+ * Finish rendering to the buffer. Note that more data can be in the
+ * 'msg' structure. Destroying the structure will free this, or in a multi-
+ * part EDNS1 message this data can be rendered to another buffer later.
+ *
+ * Requires:
+ *
+ *\li 'msg' be a valid message.
+ *
+ *\li dns_message_renderbegin() was called.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- all is well.
+ */
+
+void
+dns_message_renderreset(dns_message_t *msg);
+/*%<
+ * Reset the message so that it may be rendered again.
+ *
+ * Notes:
+ *
+ *\li If dns_message_renderbegin() has been called, dns_message_renderend()
+ * must be called before calling this function.
+ *
+ * Requires:
+ *
+ *\li 'msg' be a valid message with rendering intent.
+ */
+
+isc_result_t
+dns_message_firstname(dns_message_t *msg, dns_section_t section);
+/*%<
+ * Set internal per-section name pointer to the beginning of the section.
+ *
+ * The functions dns_message_firstname() and dns_message_nextname() may
+ * be used for iterating over the owner names in a section.
+ *
+ * Requires:
+ *
+ *\li 'msg' be valid.
+ *
+ *\li 'section' be a valid section.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- All is well.
+ *\li #ISC_R_NOMORE -- No names on given section.
+ */
+
+isc_result_t
+dns_message_nextname(dns_message_t *msg, dns_section_t section);
+/*%<
+ * Sets the internal per-section name pointer to point to the next name
+ * in that section.
+ *
+ * Requires:
+ *
+ * \li 'msg' be valid.
+ *
+ *\li 'section' be a valid section.
+ *
+ *\li dns_message_firstname() must have been called on this section,
+ * and the result was ISC_R_SUCCESS.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- All is well.
+ *\li #ISC_R_NOMORE -- No more names in given section.
+ */
+
+void
+dns_message_currentname(dns_message_t *msg, dns_section_t section,
+ dns_name_t **name);
+/*%<
+ * Sets 'name' to point to the name where the per-section internal name
+ * pointer is currently set.
+ *
+ * This function returns the name in the database, so any data associated
+ * with it (via the name's "list" member) contains the actual rdatasets.
+ *
+ * Requires:
+ *
+ *\li 'msg' be valid.
+ *
+ *\li 'name' be non-NULL, and *name be NULL.
+ *
+ *\li 'section' be a valid section.
+ *
+ *\li dns_message_firstname() must have been called on this section,
+ * and the result of it and any dns_message_nextname() calls was
+ * #ISC_R_SUCCESS.
+ */
+
+isc_result_t
+dns_message_findname(dns_message_t *msg, dns_section_t section,
+ dns_name_t *target, dns_rdatatype_t type,
+ dns_rdatatype_t covers, dns_name_t **foundname,
+ dns_rdataset_t **rdataset);
+/*%<
+ * Search for a name in the specified section. If it is found, *name is
+ * set to point to the name, and *rdataset is set to point to the found
+ * rdataset (if type is specified as other than dns_rdatatype_any).
+ *
+ * Requires:
+ *\li 'msg' be valid.
+ *
+ *\li 'section' be a valid section.
+ *
+ *\li If a pointer to the name is desired, 'foundname' should be non-NULL.
+ * If it is non-NULL, '*foundname' MUST be NULL.
+ *
+ *\li If a type other than dns_datatype_any is searched for, 'rdataset'
+ * may be non-NULL, '*rdataset' be NULL, and will point at the found
+ * rdataset. If the type is dns_datatype_any, 'rdataset' must be NULL.
+ *
+ *\li 'target' be a valid name.
+ *
+ *\li 'type' be a valid type.
+ *
+ *\li If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type.
+ * Otherwise it should be 0.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- all is well.
+ *\li #DNS_R_NXDOMAIN -- name does not exist in that section.
+ *\li #DNS_R_NXRRSET -- The name does exist, but the desired
+ * type does not.
+ */
+
+isc_result_t
+dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
+ dns_rdatatype_t covers, dns_rdataset_t **rdataset);
+/*%<
+ * Search the name for the specified type. If it is found, *rdataset is
+ * filled in with a pointer to that rdataset.
+ *
+ * Requires:
+ *\li if '**rdataset' is non-NULL, *rdataset needs to be NULL.
+ *
+ *\li 'type' be a valid type, and NOT dns_rdatatype_any.
+ *
+ *\li If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type.
+ * Otherwise it should be 0.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- all is well.
+ *\li #ISC_R_NOTFOUND -- the desired type does not exist.
+ */
+
+isc_result_t
+dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ dns_rdataset_t **rdataset);
+/*%<
+ * Search the name for the specified rdclass and type. If it is found,
+ * *rdataset is filled in with a pointer to that rdataset.
+ *
+ * Requires:
+ *\li if '**rdataset' is non-NULL, *rdataset needs to be NULL.
+ *
+ *\li 'type' be a valid type, and NOT dns_rdatatype_any.
+ *
+ *\li If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type.
+ * Otherwise it should be 0.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- all is well.
+ *\li #ISC_R_NOTFOUND -- the desired type does not exist.
+ */
+
+void
+dns_message_movename(dns_message_t *msg, dns_name_t *name,
+ dns_section_t fromsection,
+ dns_section_t tosection);
+/*%<
+ * Move a name from one section to another.
+ *
+ * Requires:
+ *
+ *\li 'msg' be valid.
+ *
+ *\li 'name' must be a name already in 'fromsection'.
+ *
+ *\li 'fromsection' must be a valid section.
+ *
+ *\li 'tosection' must be a valid section.
+ */
+
+void
+dns_message_addname(dns_message_t *msg, dns_name_t *name,
+ dns_section_t section);
+/*%<
+ * Adds the name to the given section.
+ *
+ * It is the caller's responsibility to enforce any unique name requirements
+ * in a section.
+ *
+ * Requires:
+ *
+ *\li 'msg' be valid, and be a renderable message.
+ *
+ *\li 'name' be a valid absolute name.
+ *
+ *\li 'section' be a named section.
+ */
+
+void
+dns_message_removename(dns_message_t *msg, dns_name_t *name,
+ dns_section_t section);
+/*%<
+ * Remove a existing name from a given section.
+ *
+ * It is the caller's responsibility to ensure the name is part of the
+ * given section.
+ *
+ * Requires:
+ *
+ *\li 'msg' be valid, and be a renderable message.
+ *
+ *\li 'name' be a valid absolute name.
+ *
+ *\li 'section' be a named section.
+ */
+
+
+/*
+ * LOANOUT FUNCTIONS
+ *
+ * Each of these functions loan a particular type of data to the caller.
+ * The storage for these will vanish when the message is destroyed or
+ * reset, and must NOT be used after these operations.
+ */
+
+isc_result_t
+dns_message_gettempname(dns_message_t *msg, dns_name_t **item);
+/*%<
+ * Return a name that can be used for any temporary purpose, including
+ * inserting into the message's linked lists. The name must be returned
+ * to the message code using dns_message_puttempname() or inserted into
+ * one of the message's sections before the message is destroyed.
+ *
+ * It is the caller's responsibility to initialize this name.
+ *
+ * Requires:
+ *\li msg be a valid message
+ *
+ *\li item != NULL && *item == NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- All is well.
+ *\li #ISC_R_NOMEMORY -- No item can be allocated.
+ */
+
+isc_result_t
+dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item);
+/*%<
+ * Return an offsets array that can be used for any temporary purpose,
+ * such as attaching to a temporary name. The offsets will be freed
+ * when the message is destroyed or reset.
+ *
+ * Requires:
+ *\li msg be a valid message
+ *
+ *\li item != NULL && *item == NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- All is well.
+ *\li #ISC_R_NOMEMORY -- No item can be allocated.
+ */
+
+isc_result_t
+dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item);
+/*%<
+ * Return a rdata that can be used for any temporary purpose, including
+ * inserting into the message's linked lists. The rdata will be freed
+ * when the message is destroyed or reset.
+ *
+ * Requires:
+ *\li msg be a valid message
+ *
+ *\li item != NULL && *item == NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- All is well.
+ *\li #ISC_R_NOMEMORY -- No item can be allocated.
+ */
+
+isc_result_t
+dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item);
+/*%<
+ * Return a rdataset that can be used for any temporary purpose, including
+ * inserting into the message's linked lists. The name must be returned
+ * to the message code using dns_message_puttempname() or inserted into
+ * one of the message's sections before the message is destroyed.
+ *
+ * Requires:
+ *\li msg be a valid message
+ *
+ *\li item != NULL && *item == NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- All is well.
+ *\li #ISC_R_NOMEMORY -- No item can be allocated.
+ */
+
+isc_result_t
+dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item);
+/*%<
+ * Return a rdatalist that can be used for any temporary purpose, including
+ * inserting into the message's linked lists. The rdatalist will be
+ * destroyed when the message is destroyed or reset.
+ *
+ * Requires:
+ *\li msg be a valid message
+ *
+ *\li item != NULL && *item == NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- All is well.
+ *\li #ISC_R_NOMEMORY -- No item can be allocated.
+ */
+
+void
+dns_message_puttempname(dns_message_t *msg, dns_name_t **item);
+/*%<
+ * Return a borrowed name to the message's name free list.
+ *
+ * Requires:
+ *\li msg be a valid message
+ *
+ *\li item != NULL && *item point to a name returned by
+ * dns_message_gettempname()
+ *
+ * Ensures:
+ *\li *item == NULL
+ */
+
+void
+dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item);
+/*%<
+ * Return a borrowed rdata to the message's rdata free list.
+ *
+ * Requires:
+ *\li msg be a valid message
+ *
+ *\li item != NULL && *item point to a rdata returned by
+ * dns_message_gettemprdata()
+ *
+ * Ensures:
+ *\li *item == NULL
+ */
+
+void
+dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item);
+/*%<
+ * Return a borrowed rdataset to the message's rdataset free list.
+ *
+ * Requires:
+ *\li msg be a valid message
+ *
+ *\li item != NULL && *item point to a rdataset returned by
+ * dns_message_gettemprdataset()
+ *
+ * Ensures:
+ *\li *item == NULL
+ */
+
+void
+dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item);
+/*%<
+ * Return a borrowed rdatalist to the message's rdatalist free list.
+ *
+ * Requires:
+ *\li msg be a valid message
+ *
+ *\li item != NULL && *item point to a rdatalist returned by
+ * dns_message_gettemprdatalist()
+ *
+ * Ensures:
+ *\li *item == NULL
+ */
+
+isc_result_t
+dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
+ unsigned int *flagsp);
+/*%<
+ * Assume the remaining region of "source" is a DNS message. Peek into
+ * it and fill in "*idp" with the message id, and "*flagsp" with the flags.
+ *
+ * Requires:
+ *
+ *\li source != NULL
+ *
+ * Ensures:
+ *
+ *\li if (idp != NULL) *idp == message id.
+ *
+ *\li if (flagsp != NULL) *flagsp == message flags.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS -- all is well.
+ *
+ *\li #ISC_R_UNEXPECTEDEND -- buffer doesn't contain enough for a header.
+ */
+
+isc_result_t
+dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section);
+/*%<
+ * Start formatting a reply to the query in 'msg'.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message with parsing intent, and contains a query.
+ *
+ * Ensures:
+ *
+ *\li The message will have a rendering intent. If 'want_question_section'
+ * is true, the message opcode is query or notify, and the question
+ * section is present and properly formatted, then the question section
+ * will be included in the reply. All other sections will be cleared.
+ * The QR flag will be set, the RD flag will be preserved, and all other
+ * flags will be cleared.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS -- all is well.
+ *
+ *\li #DNS_R_FORMERR -- the header or question section of the
+ * message is invalid, replying is impossible.
+ * If DNS_R_FORMERR is returned when
+ * want_question_section is ISC_FALSE, then
+ * it's the header section that's bad;
+ * otherwise either of the header or question
+ * sections may be bad.
+ */
+
+dns_rdataset_t *
+dns_message_getopt(dns_message_t *msg);
+/*%<
+ * Get the OPT record for 'msg'.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message.
+ *
+ * Returns:
+ *
+ *\li The OPT rdataset of 'msg', or NULL if there isn't one.
+ */
+
+isc_result_t
+dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt);
+/*%<
+ * Set the OPT record for 'msg'.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message with rendering intent
+ * and no sections have been rendered.
+ *
+ *\li 'opt' is a valid OPT record.
+ *
+ * Ensures:
+ *
+ *\li The OPT record has either been freed or ownership of it has
+ * been transferred to the message.
+ *
+ *\li If ISC_R_SUCCESS was returned, the OPT record will be rendered
+ * when dns_message_renderend() is called.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS -- all is well.
+ *
+ *\li #ISC_R_NOSPACE -- there is no space for the OPT record.
+ */
+
+dns_rdataset_t *
+dns_message_gettsig(dns_message_t *msg, dns_name_t **owner);
+/*%<
+ * Get the TSIG record and owner for 'msg'.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message.
+ *\li 'owner' is NULL or *owner is NULL.
+ *
+ * Returns:
+ *
+ *\li The TSIG rdataset of 'msg', or NULL if there isn't one.
+ *
+ * Ensures:
+ *
+ * \li If 'owner' is not NULL, it will point to the owner name.
+ */
+
+isc_result_t
+dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key);
+/*%<
+ * Set the tsig key for 'msg'. This is only necessary for when rendering a
+ * query or parsing a response. The key (if non-NULL) is attached to, and
+ * will be detached when the message is destroyed.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message with rendering intent,
+ * dns_message_renderbegin() has been called, and no sections have been
+ * rendered.
+ *\li 'key' is a valid tsig key or NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS -- all is well.
+ *
+ *\li #ISC_R_NOSPACE -- there is no space for the TSIG record.
+ */
+
+dns_tsigkey_t *
+dns_message_gettsigkey(dns_message_t *msg);
+/*%<
+ * Gets the tsig key for 'msg'.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message
+ */
+
+isc_result_t
+dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig);
+/*%<
+ * Indicates that 'querytsig' is the TSIG from the signed query for which
+ * 'msg' is the response. This is also used for chained TSIGs in TCP
+ * responses.
+ *
+ * Requires:
+ *
+ *\li 'querytsig' is a valid buffer as returned by dns_message_getquerytsig()
+ * or NULL
+ *
+ *\li 'msg' is a valid message
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
+ isc_buffer_t **querytsig);
+/*%<
+ * Gets the tsig from the TSIG from the signed query 'msg'. This is also used
+ * for chained TSIGs in TCP responses. Unlike dns_message_gettsig, this makes
+ * a copy of the data, so can be used if the message is destroyed.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid signed message
+ *\li 'mctx' is a valid memory context
+ *\li querytsig != NULL && *querytsig == NULL
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *
+ * Ensures:
+ *\li 'tsig' points to NULL or an allocated buffer which must be freed
+ * by the caller.
+ */
+
+dns_rdataset_t *
+dns_message_getsig0(dns_message_t *msg, dns_name_t **owner);
+/*%<
+ * Get the SIG(0) record and owner for 'msg'.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message.
+ *\li 'owner' is NULL or *owner is NULL.
+ *
+ * Returns:
+ *
+ *\li The SIG(0) rdataset of 'msg', or NULL if there isn't one.
+ *
+ * Ensures:
+ *
+ * \li If 'owner' is not NULL, it will point to the owner name.
+ */
+
+isc_result_t
+dns_message_setsig0key(dns_message_t *msg, dst_key_t *key);
+/*%<
+ * Set the SIG(0) key for 'msg'.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message with rendering intent,
+ * dns_message_renderbegin() has been called, and no sections have been
+ * rendered.
+ *\li 'key' is a valid sig key or NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS -- all is well.
+ *
+ *\li #ISC_R_NOSPACE -- there is no space for the SIG(0) record.
+ */
+
+dst_key_t *
+dns_message_getsig0key(dns_message_t *msg);
+/*%<
+ * Gets the SIG(0) key for 'msg'.
+ *
+ * Requires:
+ *
+ *\li 'msg' is a valid message
+ */
+
+void
+dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer);
+/*%<
+ * Give the *buffer to the message code to clean up when it is no
+ * longer needed. This is usually when the message is reset or
+ * destroyed.
+ *
+ * Requires:
+ *
+ *\li msg be a valid message.
+ *
+ *\li buffer != NULL && *buffer is a valid isc_buffer_t, which was
+ * dynamincally allocated via isc_buffer_allocate().
+ */
+
+isc_result_t
+dns_message_signer(dns_message_t *msg, dns_name_t *signer);
+/*%<
+ * If this message was signed, return the identity of the signer.
+ * Unless ISC_R_NOTFOUND is returned, signer will reflect the name of the
+ * key that signed the message.
+ *
+ * Requires:
+ *
+ *\li msg is a valid parsed message.
+ *\li signer is a valid name
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS - the message was signed, and *signer
+ * contains the signing identity
+ *
+ *\li #ISC_R_NOTFOUND - no TSIG or SIG(0) record is present in the
+ * message
+ *
+ *\li #DNS_R_TSIGVERIFYFAILURE - the message was signed by a TSIG, but the
+ * signature failed to verify
+ *
+ *\li #DNS_R_TSIGERRORSET - the message was signed by a TSIG and
+ * verified, but the query was rejected by
+ * the server
+ *
+ *\li #DNS_R_NOIDENTITY - the message was signed by a TSIG and
+ * verified, but the key has no identity since
+ * it was generated by an unsigned TKEY process
+ *
+ *\li #DNS_R_SIGINVALID - the message was signed by a SIG(0), but
+ * the signature failed to verify
+ *
+ *\li #DNS_R_NOTVERIFIEDYET - the message was signed by a TSIG or SIG(0),
+ * but the signature has not been verified yet
+ */
+
+isc_result_t
+dns_message_checksig(dns_message_t *msg, dns_view_t *view);
+/*%<
+ * If this message was signed, verify the signature.
+ *
+ * Requires:
+ *
+ *\li msg is a valid parsed message.
+ *\li view is a valid view or NULL
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS - the message was unsigned, or the message
+ * was signed correctly.
+ *
+ *\li #DNS_R_EXPECTEDTSIG - A TSIG was expected, but not seen
+ *\li #DNS_R_UNEXPECTEDTSIG - A TSIG was seen but not expected
+ *\li #DNS_R_TSIGVERIFYFAILURE - The TSIG failed to verify
+ */
+
+isc_result_t
+dns_message_rechecksig(dns_message_t *msg, dns_view_t *view);
+/*%<
+ * Reset the signature state and then if the message was signed,
+ * verify the message.
+ *
+ * Requires:
+ *
+ *\li msg is a valid parsed message.
+ *\li view is a valid view or NULL
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS - the message was unsigned, or the message
+ * was signed correctly.
+ *
+ *\li #DNS_R_EXPECTEDTSIG - A TSIG was expected, but not seen
+ *\li #DNS_R_UNEXPECTEDTSIG - A TSIG was seen but not expected
+ *\li #DNS_R_TSIGVERIFYFAILURE - The TSIG failed to verify
+ */
+
+void
+dns_message_resetsig(dns_message_t *msg);
+/*%<
+ * Reset the signature state.
+ *
+ * Requires:
+ *\li 'msg' is a valid parsed message.
+ */
+
+isc_region_t *
+dns_message_getrawmessage(dns_message_t *msg);
+/*%<
+ * Retrieve the raw message in compressed wire format. The message must
+ * have been successfully parsed for it to have been saved.
+ *
+ * Requires:
+ *\li msg is a valid parsed message.
+ *
+ * Returns:
+ *\li NULL if there is no saved message.
+ * a pointer to a region which refers the dns message.
+ */
+
+void
+dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
+ const void *order_arg);
+/*%<
+ * Define the order in which RR sets get rendered by
+ * dns_message_rendersection() to be the ascending order
+ * defined by the integer value returned by 'order' when
+ * given each RR and 'arg' as arguments. If 'order' and
+ * 'order_arg' are NULL, a default order is used.
+ *
+ * Requires:
+ *\li msg be a valid message.
+ *\li order_arg is NULL if and only if order is NULL.
+ */
+
+void
+dns_message_settimeadjust(dns_message_t *msg, int timeadjust);
+/*%<
+ * Adjust the time used to sign/verify a message by timeadjust.
+ * Currently only TSIG.
+ *
+ * Requires:
+ *\li msg be a valid message.
+ */
+
+int
+dns_message_gettimeadjust(dns_message_t *msg);
+/*%<
+ * Return the current time adjustment.
+ *
+ * Requires:
+ *\li msg be a valid message.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_MESSAGE_H */
diff --git a/lib/dns/include/dns/name.h b/lib/dns/include/dns/name.h
new file mode 100644
index 0000000..97c9efe
--- /dev/null
+++ b/lib/dns/include/dns/name.h
@@ -0,0 +1,1297 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: name.h,v 1.126 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_NAME_H
+#define DNS_NAME_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/name.h
+ * \brief
+ * Provides facilities for manipulating DNS names and labels, including
+ * conversions to and from wire format and text format.
+ *
+ * Given the large number of names possible in a nameserver, and because
+ * names occur in rdata, it was important to come up with a very efficient
+ * way of storing name data, but at the same time allow names to be
+ * manipulated. The decision was to store names in uncompressed wire format,
+ * and not to make them fully abstracted objects; i.e. certain parts of the
+ * server know names are stored that way. This saves a lot of memory, and
+ * makes adding names to messages easy. Having much of the server know
+ * the representation would be perilous, and we certainly don't want each
+ * user of names to be manipulating such a low-level structure. This is
+ * where the Names and Labels module comes in. The module allows name or
+ * label handles to be created and attached to uncompressed wire format
+ * regions. All name operations and conversions are done through these
+ * handles.
+ *
+ * MP:
+ *\li Clients of this module must impose any required synchronization.
+ *
+ * Reliability:
+ *\li This module deals with low-level byte streams. Errors in any of
+ * the functions are likely to crash the server or corrupt memory.
+ *
+ * Resources:
+ *\li None.
+ *
+ * Security:
+ *
+ *\li *** WARNING ***
+ *
+ *\li dns_name_fromwire() deals with raw network data. An error in
+ * this routine could result in the failure or hijacking of the server.
+ *
+ * Standards:
+ *\li RFC1035
+ *\li Draft EDNS0 (0)
+ *\li Draft Binary Labels (2)
+ *
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdio.h>
+
+#include <isc/boolean.h>
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/region.h> /* Required for storage size of dns_label_t. */
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Labels
+ *****
+ ***** A 'label' is basically a region. It contains one DNS wire format
+ ***** label of type 00 (ordinary).
+ *****/
+
+/*****
+ ***** Names
+ *****
+ ***** A 'name' is a handle to a binary region. It contains a sequence of one
+ ***** or more DNS wire format labels of type 00 (ordinary).
+ ***** Note that all names are not required to end with the root label,
+ ***** as they are in the actual DNS wire protocol.
+ *****/
+
+/***
+ *** Compression pointer chaining limit
+ ***/
+
+#define DNS_POINTER_MAXHOPS 16
+
+/***
+ *** Types
+ ***/
+
+/*%
+ * Clients are strongly discouraged from using this type directly, with
+ * the exception of the 'link' and 'list' fields which may be used directly
+ * for whatever purpose the client desires.
+ */
+struct dns_name {
+ unsigned int magic;
+ unsigned char * ndata;
+ unsigned int length;
+ unsigned int labels;
+ unsigned int attributes;
+ unsigned char * offsets;
+ isc_buffer_t * buffer;
+ ISC_LINK(dns_name_t) link;
+ ISC_LIST(dns_rdataset_t) list;
+};
+
+#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
+/*
+ * 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_NAME_DOWNCASE 0x0001
+#define DNS_NAME_CHECKNAMES 0x0002 /*%< Used by rdata. */
+#define DNS_NAME_CHECKNAMESFAIL 0x0004 /*%< Used by rdata. */
+#define DNS_NAME_CHECKREVERSE 0x0008 /*%< Used by rdata. */
+#define DNS_NAME_CHECKMX 0x0010 /*%< Used by rdata. */
+#define DNS_NAME_CHECKMXFAIL 0x0020 /*%< Used by rdata. */
+
+LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_rootname;
+LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_wildcardname;
+
+/*%
+ * Standard size of a wire format name
+ */
+#define DNS_NAME_MAXWIRE 255
+
+/*
+ * Text output filter procedure.
+ * 'target' is the buffer to be converted. The region to be converted
+ * is from 'buffer'->base + 'used_org' to the end of the used region.
+ */
+typedef isc_result_t (*dns_name_totextfilter_t)(isc_buffer_t *target,
+ unsigned int used_org,
+ isc_boolean_t absolute);
+
+/***
+ *** Initialization
+ ***/
+
+void
+dns_name_init(dns_name_t *name, unsigned char *offsets);
+/*%<
+ * Initialize 'name'.
+ *
+ * Notes:
+ * \li 'offsets' is never required to be non-NULL, but specifying a
+ * dns_offsets_t for 'offsets' will improve the performance of most
+ * name operations if the name is used more than once.
+ *
+ * Requires:
+ * \li 'name' is not NULL and points to a struct dns_name.
+ *
+ * \li offsets == NULL or offsets is a dns_offsets_t.
+ *
+ * Ensures:
+ * \li 'name' is a valid name.
+ * \li dns_name_countlabels(name) == 0
+ * \li dns_name_isabsolute(name) == ISC_FALSE
+ */
+
+void
+dns_name_reset(dns_name_t *name);
+/*%<
+ * Reinitialize 'name'.
+ *
+ * Notes:
+ * \li This function distinguishes itself from dns_name_init() in two
+ * key ways:
+ *
+ * \li + If any buffer is associated with 'name' (via dns_name_setbuffer()
+ * or by being part of a dns_fixedname_t) the link to the buffer
+ * is retained but the buffer itself is cleared.
+ *
+ * \li + Of the attributes associated with 'name', all are retained except
+ * DNS_NAMEATTR_ABSOLUTE.
+ *
+ * Requires:
+ * \li 'name' is a valid name.
+ *
+ * Ensures:
+ * \li 'name' is a valid name.
+ * \li dns_name_countlabels(name) == 0
+ * \li dns_name_isabsolute(name) == ISC_FALSE
+ */
+
+void
+dns_name_invalidate(dns_name_t *name);
+/*%<
+ * Make 'name' invalid.
+ *
+ * Requires:
+ * \li 'name' is a valid name.
+ *
+ * Ensures:
+ * \li If assertion checking is enabled, future attempts to use 'name'
+ * without initializing it will cause an assertion failure.
+ *
+ * \li If the name had a dedicated buffer, that association is ended.
+ */
+
+
+/***
+ *** Dedicated Buffers
+ ***/
+
+void
+dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer);
+/*%<
+ * Dedicate a buffer for use with 'name'.
+ *
+ * Notes:
+ * \li Specification of a target buffer in dns_name_fromwire(),
+ * dns_name_fromtext(), and dns_name_concatentate() is optional if
+ * 'name' has a dedicated buffer.
+ *
+ * \li The caller must not write to buffer until the name has been
+ * invalidated or is otherwise known not to be in use.
+ *
+ * \li If buffer is NULL and the name previously had a dedicated buffer,
+ * than that buffer is no longer dedicated to use with this name.
+ * The caller is responsible for ensuring that the storage used by
+ * the name remains valid.
+ *
+ * Requires:
+ * \li 'name' is a valid name.
+ *
+ * \li 'buffer' is a valid binary buffer and 'name' doesn't have a
+ * dedicated buffer already, or 'buffer' is NULL.
+ */
+
+isc_boolean_t
+dns_name_hasbuffer(const dns_name_t *name);
+/*%<
+ * Does 'name' have a dedicated buffer?
+ *
+ * Requires:
+ * \li 'name' is a valid name.
+ *
+ * Returns:
+ * \li ISC_TRUE 'name' has a dedicated buffer.
+ * \li ISC_FALSE 'name' does not have a dedicated buffer.
+ */
+
+/***
+ *** Properties
+ ***/
+
+isc_boolean_t
+dns_name_isabsolute(const dns_name_t *name);
+/*%<
+ * Does 'name' end in the root label?
+ *
+ * Requires:
+ * \li 'name' is a valid name
+ *
+ * Returns:
+ * \li TRUE The last label in 'name' is the root label.
+ * \li FALSE The last label in 'name' is not the root label.
+ */
+
+isc_boolean_t
+dns_name_iswildcard(const dns_name_t *name);
+/*%<
+ * Is 'name' a wildcard name?
+ *
+ * Requires:
+ * \li 'name' is a valid name
+ *
+ * \li dns_name_countlabels(name) > 0
+ *
+ * Returns:
+ * \li TRUE The least significant label of 'name' is '*'.
+ * \li FALSE The least significant label of 'name' is not '*'.
+ */
+
+unsigned int
+dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive);
+/*%<
+ * Provide a hash value for 'name'.
+ *
+ * Note: if 'case_sensitive' is ISC_FALSE, then names which differ only in
+ * case will have the same hash value.
+ *
+ * Requires:
+ * \li 'name' is a valid name
+ *
+ * Returns:
+ * \li A hash value
+ */
+
+unsigned int
+dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive);
+/*%<
+ * Provide a hash value for 'name'. Unlike dns_name_hash(), this function
+ * always takes into account of the entire name to calculate the hash value.
+ *
+ * Note: if 'case_sensitive' is ISC_FALSE, then names which differ only in
+ * case will have the same hash value.
+ *
+ * Requires:
+ *\li 'name' is a valid name
+ *
+ * Returns:
+ *\li A hash value
+ */
+
+unsigned int
+dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive);
+/*%<
+ * Provide a hash value for 'name', where the hash value is the sum
+ * of the hash values of each label.
+ *
+ * Note: if 'case_sensitive' is ISC_FALSE, then names which differ only in
+ * case will have the same hash value.
+ *
+ * Requires:
+ *\li 'name' is a valid name
+ *
+ * Returns:
+ *\li A hash value
+ */
+
+/*
+ *** Comparisons
+ ***/
+
+dns_namereln_t
+dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
+ int *orderp, unsigned int *nlabelsp);
+/*%<
+ * Determine the relative ordering under the DNSSEC order relation of
+ * 'name1' and 'name2', and also determine the hierarchical
+ * relationship of the names.
+ *
+ * Note: It makes no sense for one of the names to be relative and the
+ * other absolute. If both names are relative, then to be meaningfully
+ * compared the caller must ensure that they are both relative to the
+ * same domain.
+ *
+ * Requires:
+ *\li 'name1' is a valid name
+ *
+ *\li dns_name_countlabels(name1) > 0
+ *
+ *\li 'name2' is a valid name
+ *
+ *\li dns_name_countlabels(name2) > 0
+ *
+ *\li orderp and nlabelsp are valid pointers.
+ *
+ *\li Either name1 is absolute and name2 is absolute, or neither is.
+ *
+ * Ensures:
+ *
+ *\li *orderp is < 0 if name1 < name2, 0 if name1 = name2, > 0 if
+ * name1 > name2.
+ *
+ *\li *nlabelsp is the number of common significant labels.
+ *
+ * Returns:
+ *\li dns_namereln_none There's no hierarchical relationship
+ * between name1 and name2.
+ *\li dns_namereln_contains name1 properly contains name2; i.e.
+ * name2 is a proper subdomain of name1.
+ *\li dns_namereln_subdomain name1 is a proper subdomain of name2.
+ *\li dns_namereln_equal name1 and name2 are equal.
+ *\li dns_namereln_commonancestor name1 and name2 share a common
+ * ancestor.
+ */
+
+int
+dns_name_compare(const dns_name_t *name1, const dns_name_t *name2);
+/*%<
+ * Determine the relative ordering under the DNSSEC order relation of
+ * 'name1' and 'name2'.
+ *
+ * Note: It makes no sense for one of the names to be relative and the
+ * other absolute. If both names are relative, then to be meaningfully
+ * compared the caller must ensure that they are both relative to the
+ * same domain.
+ *
+ * Requires:
+ * \li 'name1' is a valid name
+ *
+ * \li 'name2' is a valid name
+ *
+ * \li Either name1 is absolute and name2 is absolute, or neither is.
+ *
+ * Returns:
+ * \li < 0 'name1' is less than 'name2'
+ * \li 0 'name1' is equal to 'name2'
+ * \li > 0 'name1' is greater than 'name2'
+ */
+
+isc_boolean_t
+dns_name_equal(const dns_name_t *name1, const dns_name_t *name2);
+/*%<
+ * Are 'name1' and 'name2' equal?
+ *
+ * Notes:
+ * \li Because it only needs to test for equality, dns_name_equal() can be
+ * significantly faster than dns_name_fullcompare() or dns_name_compare().
+ *
+ * \li Offsets tables are not used in the comparision.
+ *
+ * \li It makes no sense for one of the names to be relative and the
+ * other absolute. If both names are relative, then to be meaningfully
+ * compared the caller must ensure that they are both relative to the
+ * same domain.
+ *
+ * Requires:
+ * \li 'name1' is a valid name
+ *
+ * \li 'name2' is a valid name
+ *
+ * \li Either name1 is absolute and name2 is absolute, or neither is.
+ *
+ * Returns:
+ * \li ISC_TRUE 'name1' and 'name2' are equal
+ * \li ISC_FALSE 'name1' and 'name2' are not equal
+ */
+
+isc_boolean_t
+dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2);
+/*%<
+ * Case sensitive version of dns_name_equal().
+ */
+
+int
+dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2);
+/*%<
+ * Compare two names as if they are part of rdata in DNSSEC canonical
+ * form.
+ *
+ * Requires:
+ * \li 'name1' is a valid absolute name
+ *
+ * \li dns_name_countlabels(name1) > 0
+ *
+ * \li 'name2' is a valid absolute name
+ *
+ * \li dns_name_countlabels(name2) > 0
+ *
+ * Returns:
+ * \li < 0 'name1' is less than 'name2'
+ * \li 0 'name1' is equal to 'name2'
+ * \li > 0 'name1' is greater than 'name2'
+ */
+
+isc_boolean_t
+dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2);
+/*%<
+ * Is 'name1' a subdomain of 'name2'?
+ *
+ * Notes:
+ * \li name1 is a subdomain of name2 if name1 is contained in name2, or
+ * name1 equals name2.
+ *
+ * \li It makes no sense for one of the names to be relative and the
+ * other absolute. If both names are relative, then to be meaningfully
+ * compared the caller must ensure that they are both relative to the
+ * same domain.
+ *
+ * Requires:
+ * \li 'name1' is a valid name
+ *
+ * \li 'name2' is a valid name
+ *
+ * \li Either name1 is absolute and name2 is absolute, or neither is.
+ *
+ * Returns:
+ * \li TRUE 'name1' is a subdomain of 'name2'
+ * \li FALSE 'name1' is not a subdomain of 'name2'
+ */
+
+isc_boolean_t
+dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname);
+/*%<
+ * Does 'name' match the wildcard specified in 'wname'?
+ *
+ * Notes:
+ * \li name matches the wildcard specified in wname if all labels
+ * following the wildcard in wname are identical to the same number
+ * of labels at the end of name.
+ *
+ * \li It makes no sense for one of the names to be relative and the
+ * other absolute. If both names are relative, then to be meaningfully
+ * compared the caller must ensure that they are both relative to the
+ * same domain.
+ *
+ * Requires:
+ * \li 'name' is a valid name
+ *
+ * \li dns_name_countlabels(name) > 0
+ *
+ * \li 'wname' is a valid name
+ *
+ * \li dns_name_countlabels(wname) > 0
+ *
+ * \li dns_name_iswildcard(wname) is true
+ *
+ * \li Either name is absolute and wname is absolute, or neither is.
+ *
+ * Returns:
+ * \li TRUE 'name' matches the wildcard specified in 'wname'
+ * \li FALSE 'name' does not match the wildcard specified in 'wname'
+ */
+
+/***
+ *** Labels
+ ***/
+
+unsigned int
+dns_name_countlabels(const dns_name_t *name);
+/*%<
+ * How many labels does 'name' have?
+ *
+ * Notes:
+ * \li In this case, as in other places, a 'label' is an ordinary label.
+ *
+ * Requires:
+ * \li 'name' is a valid name
+ *
+ * Ensures:
+ * \li The result is <= 128.
+ *
+ * Returns:
+ * \li The number of labels in 'name'.
+ */
+
+void
+dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label);
+/*%<
+ * Make 'label' refer to the 'n'th least significant label of 'name'.
+ *
+ * Notes:
+ * \li Numbering starts at 0.
+ *
+ * \li Given "rc.vix.com.", the label 0 is "rc", and label 3 is the
+ * root label.
+ *
+ * \li 'label' refers to the same memory as 'name', so 'name' must not
+ * be changed while 'label' is still in use.
+ *
+ * Requires:
+ * \li n < dns_name_countlabels(name)
+ */
+
+void
+dns_name_getlabelsequence(const dns_name_t *source, unsigned int first,
+ unsigned int n, dns_name_t *target);
+/*%<
+ * Make 'target' refer to the 'n' labels including and following 'first'
+ * in 'source'.
+ *
+ * Notes:
+ * \li Numbering starts at 0.
+ *
+ * \li Given "rc.vix.com.", the label 0 is "rc", and label 3 is the
+ * root label.
+ *
+ * \li 'target' refers to the same memory as 'source', so 'source'
+ * must not be changed while 'target' is still in use.
+ *
+ * Requires:
+ * \li 'source' and 'target' are valid names.
+ *
+ * \li first < dns_name_countlabels(name)
+ *
+ * \li first + n <= dns_name_countlabels(name)
+ */
+
+
+void
+dns_name_clone(const dns_name_t *source, dns_name_t *target);
+/*%<
+ * Make 'target' refer to the same name as 'source'.
+ *
+ * Notes:
+ *
+ * \li 'target' refers to the same memory as 'source', so 'source'
+ * must not be changed while 'target' is still in use.
+ *
+ * \li This call is functionally equivalent to:
+ *
+ * \code
+ * dns_name_getlabelsequence(source, 0,
+ * dns_name_countlabels(source),
+ * target);
+ * \endcode
+ *
+ * but is more efficient. Also, dns_name_clone() works even if 'source'
+ * is empty.
+ *
+ * Requires:
+ *
+ * \li 'source' is a valid name.
+ *
+ * \li 'target' is a valid name that is not read-only.
+ */
+
+/***
+ *** Conversions
+ ***/
+
+void
+dns_name_fromregion(dns_name_t *name, const isc_region_t *r);
+/*%<
+ * Make 'name' refer to region 'r'.
+ *
+ * Note:
+ * \li If the conversion encounters a root label before the end of the
+ * region the conversion stops and the length is set to the length
+ * so far converted. A maximum of 255 bytes is converted.
+ *
+ * Requires:
+ * \li The data in 'r' is a sequence of one or more type 00 or type 01000001
+ * labels.
+ */
+
+void
+dns_name_toregion(dns_name_t *name, isc_region_t *r);
+/*%<
+ * Make 'r' refer to 'name'.
+ *
+ * Requires:
+ *
+ * \li 'name' is a valid name.
+ *
+ * \li 'r' is a valid region.
+ */
+
+isc_result_t
+dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
+ dns_decompress_t *dctx, unsigned int options,
+ isc_buffer_t *target);
+/*%<
+ * Copy the possibly-compressed name at source (active region) into target,
+ * decompressing it.
+ *
+ * Notes:
+ * \li Decompression policy is controlled by 'dctx'.
+ *
+ * \li If DNS_NAME_DOWNCASE is set, any uppercase letters in 'source' will be
+ * downcased when they are copied into 'target'.
+ *
+ * Security:
+ *
+ * \li *** WARNING ***
+ *
+ * \li This routine will often be used when 'source' contains raw network
+ * data. A programming error in this routine could result in a denial
+ * of service, or in the hijacking of the server.
+ *
+ * Requires:
+ *
+ * \li 'name' is a valid name.
+ *
+ * \li 'source' is a valid buffer and the first byte of the active
+ * region should be the first byte of a DNS wire format domain name.
+ *
+ * \li 'target' is a valid buffer or 'target' is NULL and 'name' has
+ * a dedicated buffer.
+ *
+ * \li 'dctx' is a valid decompression context.
+ *
+ * Ensures:
+ *
+ * If result is success:
+ * \li If 'target' is not NULL, 'name' is attached to it.
+ *
+ * \li Uppercase letters are downcased in the copy iff
+ * DNS_NAME_DOWNCASE is set in options.
+ *
+ * \li The current location in source is advanced, and the used space
+ * in target is updated.
+ *
+ * Result:
+ * \li Success
+ * \li Bad Form: Label Length
+ * \li Bad Form: Unknown Label Type
+ * \li Bad Form: Name Length
+ * \li Bad Form: Compression type not allowed
+ * \li Bad Form: Bad compression pointer
+ * \li Bad Form: Input too short
+ * \li Resource Limit: Too many compression pointers
+ * \li Resource Limit: Not enough space in buffer
+ */
+
+isc_result_t
+dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
+ isc_buffer_t *target);
+/*%<
+ * Convert 'name' into wire format, compressing it as specified by the
+ * compression context 'cctx', and storing the result in 'target'.
+ *
+ * Notes:
+ * \li If the compression context allows global compression, then the
+ * global compression table may be updated.
+ *
+ * Requires:
+ * \li 'name' is a valid name
+ *
+ * \li dns_name_countlabels(name) > 0
+ *
+ * \li dns_name_isabsolute(name) == TRUE
+ *
+ * \li target is a valid buffer.
+ *
+ * \li Any offsets specified in a global compression table are valid
+ * for buffer.
+ *
+ * Ensures:
+ *
+ * If the result is success:
+ *
+ * \li The used space in target is updated.
+ *
+ * Returns:
+ * \li Success
+ * \li Resource Limit: Not enough space in buffer
+ */
+
+isc_result_t
+dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
+ dns_name_t *origin, unsigned int options,
+ isc_buffer_t *target);
+/*%<
+ * Convert the textual representation of a DNS name at source
+ * into uncompressed wire form stored in target.
+ *
+ * Notes:
+ * \li Relative domain names will have 'origin' appended to them
+ * unless 'origin' is NULL, in which case relative domain names
+ * will remain relative.
+ *
+ * \li If DNS_NAME_DOWNCASE is set in 'options', any uppercase letters
+ * in 'source' will be downcased when they are copied into 'target'.
+ *
+ * Requires:
+ *
+ * \li 'name' is a valid name.
+ *
+ * \li 'source' is a valid buffer.
+ *
+ * \li 'target' is a valid buffer or 'target' is NULL and 'name' has
+ * a dedicated buffer.
+ *
+ * Ensures:
+ *
+ * If result is success:
+ * \li If 'target' is not NULL, 'name' is attached to it.
+ *
+ * \li Uppercase letters are downcased in the copy iff
+ * DNS_NAME_DOWNCASE is set in 'options'.
+ *
+ * \li The current location in source is advanced, and the used space
+ * in target is updated.
+ *
+ * Result:
+ *\li #ISC_R_SUCCESS
+ *\li #DNS_R_EMPTYLABEL
+ *\li #DNS_R_LABELTOOLONG
+ *\li #DNS_R_BADESCAPE
+ *\li (#DNS_R_BADBITSTRING: should not be returned)
+ *\li (#DNS_R_BITSTRINGTOOLONG: should not be returned)
+ *\li #DNS_R_BADDOTTEDQUAD
+ *\li #ISC_R_NOSPACE
+ *\li #ISC_R_UNEXPECTEDEND
+ */
+
+isc_result_t
+dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
+ isc_buffer_t *target);
+/*%<
+ * Convert 'name' into text format, storing the result in 'target'.
+ *
+ * Notes:
+ *\li If 'omit_final_dot' is true, then the final '.' in absolute
+ * names other than the root name will be omitted.
+ *
+ *\li If dns_name_countlabels == 0, the name will be "@", representing the
+ * current origin as described by RFC1035.
+ *
+ *\li The name is not NUL terminated.
+ *
+ * Requires:
+ *
+ *\li 'name' is a valid name
+ *
+ *\li 'target' is a valid buffer.
+ *
+ *\li if dns_name_isabsolute == FALSE, then omit_final_dot == FALSE
+ *
+ * Ensures:
+ *
+ *\li If the result is success:
+ * the used space in target is updated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE
+ */
+
+#define DNS_NAME_MAXTEXT 1023
+/*%<
+ * The maximum length of the text representation of a domain
+ * name as generated by dns_name_totext(). This does not
+ * include space for a terminating NULL.
+ *
+ * This definition is conservative - the actual maximum
+ * is 1004, derived as follows:
+ *
+ * A backslash-decimal escaped character takes 4 bytes.
+ * A wire-encoded name can be up to 255 bytes and each
+ * label is one length byte + at most 63 bytes of data.
+ * Maximizing the label lengths gives us a name of
+ * three 63-octet labels, one 61-octet label, and the
+ * root label:
+ *
+ * 1 + 63 + 1 + 63 + 1 + 63 + 1 + 61 + 1 = 255
+ *
+ * When printed, this is (3 * 63 + 61) * 4
+ * bytes for the escaped label data + 4 bytes for the
+ * dot terminating each label = 1004 bytes total.
+ */
+
+isc_result_t
+dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
+ isc_buffer_t *target);
+/*%<
+ * Convert 'name' into an alternate text format appropriate for filenames,
+ * storing the result in 'target'. The name data is downcased, guaranteeing
+ * that the filename does not depend on the case of the converted name.
+ *
+ * Notes:
+ *\li If 'omit_final_dot' is true, then the final '.' in absolute
+ * names other than the root name will be omitted.
+ *
+ *\li The name is not NUL terminated.
+ *
+ * Requires:
+ *
+ *\li 'name' is a valid absolute name
+ *
+ *\li 'target' is a valid buffer.
+ *
+ * Ensures:
+ *
+ *\li If the result is success:
+ * the used space in target is updated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE
+ */
+
+isc_result_t
+dns_name_downcase(dns_name_t *source, dns_name_t *name,
+ isc_buffer_t *target);
+/*%<
+ * Downcase 'source'.
+ *
+ * Requires:
+ *
+ *\li 'source' and 'name' are valid names.
+ *
+ *\li If source == name, then
+ * 'source' must not be read-only
+ *
+ *\li Otherwise,
+ * 'target' is a valid buffer or 'target' is NULL and
+ * 'name' has a dedicated buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE
+ *
+ * Note: if source == name, then the result will always be ISC_R_SUCCESS.
+ */
+
+isc_result_t
+dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix,
+ dns_name_t *name, isc_buffer_t *target);
+/*%<
+ * Concatenate 'prefix' and 'suffix'.
+ *
+ * Requires:
+ *
+ *\li 'prefix' is a valid name or NULL.
+ *
+ *\li 'suffix' is a valid name or NULL.
+ *
+ *\li 'name' is a valid name or NULL.
+ *
+ *\li 'target' is a valid buffer or 'target' is NULL and 'name' has
+ * a dedicated buffer.
+ *
+ *\li If 'prefix' is absolute, 'suffix' must be NULL or the empty name.
+ *
+ * Ensures:
+ *
+ *\li On success,
+ * If 'target' is not NULL and 'name' is not NULL, then 'name'
+ * is attached to it.
+ * The used space in target is updated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE
+ *\li #DNS_R_NAMETOOLONG
+ */
+
+void
+dns_name_split(dns_name_t *name, unsigned int suffixlabels,
+ dns_name_t *prefix, dns_name_t *suffix);
+/*%<
+ *
+ * Split 'name' into two pieces on a label boundary.
+ *
+ * Notes:
+ * \li 'name' is split such that 'suffix' holds the most significant
+ * 'suffixlabels' labels. All other labels are stored in 'prefix'.
+ *
+ *\li Copying name data is avoided as much as possible, so 'prefix'
+ * and 'suffix' will end up pointing at the data for 'name'.
+ *
+ *\li It is legitimate to pass a 'prefix' or 'suffix' that has
+ * its name data stored someplace other than the dedicated buffer.
+ * This is useful to avoid name copying in the calling function.
+ *
+ *\li It is also legitimate to pass a 'prefix' or 'suffix' that is
+ * the same dns_name_t as 'name'.
+ *
+ * Requires:
+ *\li 'name' is a valid name.
+ *
+ *\li 'suffixlabels' cannot exceed the number of labels in 'name'.
+ *
+ * \li 'prefix' is a valid name or NULL, and cannot be read-only.
+ *
+ *\li 'suffix' is a valid name or NULL, and cannot be read-only.
+ *
+ *\li If non-NULL, 'prefix' and 'suffix' must have dedicated buffers.
+ *
+ *\li 'prefix' and 'suffix' cannot point to the same buffer.
+ *
+ * Ensures:
+ *
+ *\li On success:
+ * If 'prefix' is not NULL it will contain the least significant
+ * labels.
+ * If 'suffix' is not NULL it will contain the most significant
+ * labels. dns_name_countlabels(suffix) will be equal to
+ * suffixlabels.
+ *
+ *\li On failure:
+ * Either 'prefix' or 'suffix' is invalidated (depending
+ * on which one the problem was encountered with).
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS No worries. (This function should always success).
+ */
+
+isc_result_t
+dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
+ dns_name_t *target);
+/*%<
+ * Make 'target' a dynamically allocated copy of 'source'.
+ *
+ * Requires:
+ *
+ *\li 'source' is a valid non-empty name.
+ *
+ *\li 'target' is a valid name that is not read-only.
+ *
+ *\li 'mctx' is a valid memory context.
+ */
+
+isc_result_t
+dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
+ dns_name_t *target);
+/*%<
+ * Make 'target' a read-only dynamically allocated copy of 'source'.
+ * 'target' will also have a dynamically allocated offsets table.
+ *
+ * Requires:
+ *
+ *\li 'source' is a valid non-empty name.
+ *
+ *\li 'target' is a valid name that is not read-only.
+ *
+ *\li 'target' has no offsets table.
+ *
+ *\li 'mctx' is a valid memory context.
+ */
+
+void
+dns_name_free(dns_name_t *name, isc_mem_t *mctx);
+/*%<
+ * Free 'name'.
+ *
+ * Requires:
+ *
+ *\li 'name' is a valid name created previously in 'mctx' by dns_name_dup().
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ * Ensures:
+ *
+ *\li All dynamic resources used by 'name' are freed and the name is
+ * invalidated.
+ */
+
+isc_result_t
+dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg);
+/*%<
+ * Send 'name' in DNSSEC canonical form to 'digest'.
+ *
+ * Requires:
+ *
+ *\li 'name' is a valid name.
+ *
+ *\li 'digest' is a valid dns_digestfunc_t.
+ *
+ * Ensures:
+ *
+ *\li If successful, the DNSSEC canonical form of 'name' will have been
+ * sent to 'digest'.
+ *
+ *\li If digest() returns something other than ISC_R_SUCCESS, that result
+ * will be returned as the result of dns_name_digest().
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *
+ *\li Many other results are possible if not successful.
+ *
+ */
+
+isc_boolean_t
+dns_name_dynamic(dns_name_t *name);
+/*%<
+ * Returns whether there is dynamic memory associated with this name.
+ *
+ * Requires:
+ *
+ *\li 'name' is a valid name.
+ *
+ * Returns:
+ *
+ *\li 'ISC_TRUE' if the name is dynamic othewise 'ISC_FALSE'.
+ */
+
+isc_result_t
+dns_name_print(dns_name_t *name, FILE *stream);
+/*%<
+ * Print 'name' on 'stream'.
+ *
+ * Requires:
+ *
+ *\li 'name' is a valid name.
+ *
+ *\li 'stream' is a valid stream.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *
+ *\li Any error that dns_name_totext() can return.
+ */
+
+void
+dns_name_format(dns_name_t *name, char *cp, unsigned int size);
+/*%<
+ * Format 'name' as text appropriate for use in log messages.
+ *
+ * Store the formatted name at 'cp', writing no more than
+ * 'size' bytes. The resulting string is guaranteed to be
+ * null terminated.
+ *
+ * The formatted name will have a terminating dot only if it is
+ * the root.
+ *
+ * This function cannot fail, instead any errors are indicated
+ * in the returned text.
+ *
+ * Requires:
+ *
+ *\li 'name' is a valid name.
+ *
+ *\li 'cp' points a valid character array of size 'size'.
+ *
+ *\li 'size' > 0.
+ *
+ */
+
+isc_result_t
+dns_name_settotextfilter(dns_name_totextfilter_t proc);
+/*%<
+ * Set / clear a thread specific function 'proc' to be called at the
+ * end of dns_name_totext().
+ *
+ * Note: Under Windows you need to call "dns_name_settotextfilter(NULL);"
+ * prior to exiting the thread otherwise memory will be leaked.
+ * For other platforms, which are pthreads based, this is still a good
+ * idea but not required.
+ *
+ * Returns
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_UNEXPECTED
+ */
+
+#define DNS_NAME_FORMATSIZE (DNS_NAME_MAXTEXT + 1)
+/*%<
+ * Suggested size of buffer passed to dns_name_format().
+ * Includes space for the terminating NULL.
+ */
+
+isc_result_t
+dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target);
+/*%<
+ * Makes 'dest' refer to a copy of the name in 'source'. The data are
+ * either copied to 'target' or the dedicated buffer in 'dest'.
+ *
+ * Requires:
+ * \li 'source' is a valid name.
+ *
+ * \li 'dest' is an initialized name with a dedicated buffer.
+ *
+ * \li 'target' is NULL or an initialized buffer.
+ *
+ * \li Either dest has a dedicated buffer or target != NULL.
+ *
+ * Ensures:
+ *
+ *\li On success, the used space in target is updated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE
+ */
+
+isc_boolean_t
+dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard);
+/*%<
+ * Return if 'name' is a valid hostname. RFC 952 / RFC 1123.
+ * If 'wildcard' is ISC_TRUE then allow the first label of name to
+ * be a wildcard.
+ * The root is also accepted.
+ *
+ * Requires:
+ * 'name' to be valid.
+ */
+
+
+isc_boolean_t
+dns_name_ismailbox(const dns_name_t *name);
+/*%<
+ * Return if 'name' is a valid mailbox. RFC 821.
+ *
+ * Requires:
+ * \li 'name' to be valid.
+ */
+
+isc_boolean_t
+dns_name_internalwildcard(const dns_name_t *name);
+/*%<
+ * Return if 'name' contains a internal wildcard name.
+ *
+ * Requires:
+ * \li 'name' to be valid.
+ */
+
+void
+dns_name_destroy(void);
+/*%<
+ * Cleanup dns_name_settotextfilter() / dns_name_totext() state.
+ *
+ * This should be called as part of the final cleanup process.
+ *
+ * Note: dns_name_settotextfilter(NULL); should be called for all
+ * threads which have called dns_name_settotextfilter() with a
+ * non-NULL argument prior to calling dns_name_destroy();
+ */
+
+ISC_LANG_ENDDECLS
+
+/*
+ *** High Peformance Macros
+ ***/
+
+/*
+ * WARNING: Use of these macros by applications may require recompilation
+ * of the application in some situations where calling the function
+ * would not.
+ *
+ * WARNING: No assertion checking is done for these macros.
+ */
+
+#define DNS_NAME_INIT(n, o) \
+do { \
+ (n)->magic = DNS_NAME_MAGIC; \
+ (n)->ndata = NULL; \
+ (n)->length = 0; \
+ (n)->labels = 0; \
+ (n)->attributes = 0; \
+ (n)->offsets = (o); \
+ (n)->buffer = NULL; \
+ ISC_LINK_INIT((n), link); \
+ ISC_LIST_INIT((n)->list); \
+} while (0)
+
+#define DNS_NAME_RESET(n) \
+do { \
+ (n)->ndata = NULL; \
+ (n)->length = 0; \
+ (n)->labels = 0; \
+ (n)->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
+ if ((n)->buffer != NULL) \
+ isc_buffer_clear((n)->buffer); \
+} while (0)
+
+#define DNS_NAME_SETBUFFER(n, b) \
+ (n)->buffer = (b)
+
+#define DNS_NAME_ISABSOLUTE(n) \
+ (((n)->attributes & DNS_NAMEATTR_ABSOLUTE) != 0 ? ISC_TRUE : ISC_FALSE)
+
+#define DNS_NAME_COUNTLABELS(n) \
+ ((n)->labels)
+
+#define DNS_NAME_TOREGION(n, r) \
+do { \
+ (r)->base = (n)->ndata; \
+ (r)->length = (n)->length; \
+} while (0)
+
+#define DNS_NAME_SPLIT(n, l, p, s) \
+do { \
+ dns_name_t *_n = (n); \
+ dns_name_t *_p = (p); \
+ dns_name_t *_s = (s); \
+ unsigned int _l = (l); \
+ if (_p != NULL) \
+ dns_name_getlabelsequence(_n, 0, _n->labels - _l, _p); \
+ if (_s != NULL) \
+ dns_name_getlabelsequence(_n, _n->labels - _l, _l, _s); \
+} while (0)
+
+#ifdef DNS_NAME_USEINLINE
+
+#define dns_name_init(n, o) DNS_NAME_INIT(n, o)
+#define dns_name_reset(n) DNS_NAME_RESET(n)
+#define dns_name_setbuffer(n, b) DNS_NAME_SETBUFFER(n, b)
+#define dns_name_countlabels(n) DNS_NAME_COUNTLABELS(n)
+#define dns_name_isabsolute(n) DNS_NAME_ISABSOLUTE(n)
+#define dns_name_toregion(n, r) DNS_NAME_TOREGION(n, r)
+#define dns_name_split(n, l, p, s) DNS_NAME_SPLIT(n, l, p, s)
+
+#endif /* DNS_NAME_USEINLINE */
+
+#endif /* DNS_NAME_H */
diff --git a/lib/dns/include/dns/ncache.h b/lib/dns/include/dns/ncache.h
new file mode 100644
index 0000000..a818fe6
--- /dev/null
+++ b/lib/dns/include/dns/ncache.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: ncache.h,v 1.25 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef DNS_NCACHE_H
+#define DNS_NCACHE_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/ncache.h
+ *\brief
+ * DNS Ncache
+ *
+ * XXX TBS XXX
+ *
+ * MP:
+ *\li The caller must ensure any required synchronization.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li RFC2308
+ */
+
+#include <isc/lang.h>
+#include <isc/stdtime.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * _OMITDNSSEC:
+ * Omit DNSSEC records when rendering.
+ */
+#define DNS_NCACHETOWIRE_OMITDNSSEC 0x0001
+
+isc_result_t
+dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
+ dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
+ dns_rdataset_t *addedrdataset);
+isc_result_t
+dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
+ dns_dbnode_t *node, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_ttl_t maxttl,
+ isc_boolean_t optout, dns_rdataset_t *addedrdataset);
+/*%<
+ * Convert the authority data from 'message' into a negative cache
+ * rdataset, and store it in 'cache' at 'node' with a TTL limited to
+ * 'maxttl'.
+ *
+ * The 'covers' argument is the RR type whose nonexistence we are caching,
+ * or dns_rdatatype_any when caching a NXDOMAIN response.
+ *
+ * 'optout' indicates a DNS_RATASETATTR_OPTOUT should be set.
+ *
+ * Note:
+ *\li If 'addedrdataset' is not NULL, then it will be attached to the added
+ * rdataset. See dns_db_addrdataset() for more details.
+ *
+ * Requires:
+ *\li 'message' is a valid message with a properly formatting negative cache
+ * authority section.
+ *
+ *\li The requirements of dns_db_addrdataset() apply to 'cache', 'node',
+ * 'now', and 'addedrdataset'.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE
+ *
+ *\li Any result code of dns_db_addrdataset() is a possible result code
+ * of dns_ncache_add().
+ */
+
+isc_result_t
+dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
+ isc_buffer_t *target, unsigned int options,
+ unsigned int *countp);
+/*%<
+ * Convert the negative caching rdataset 'rdataset' to wire format,
+ * compressing names as specified in 'cctx', and storing the result in
+ * 'target'. If 'omit_dnssec' is set, DNSSEC records will not
+ * be added to 'target'.
+ *
+ * Notes:
+ *\li The number of RRs added to target will be added to *countp.
+ *
+ * Requires:
+ *\li 'rdataset' is a valid negative caching rdataset.
+ *
+ *\li 'rdataset' is not empty.
+ *
+ *\li 'countp' is a valid pointer.
+ *
+ * Ensures:
+ *\li On a return of ISC_R_SUCCESS, 'target' contains a wire format
+ * for the data contained in 'rdataset'. Any error return leaves
+ * the buffer unchanged.
+ *
+ *\li *countp has been incremented by the number of RRs added to
+ * target.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS - all ok
+ *\li #ISC_R_NOSPACE - 'target' doesn't have enough room
+ *
+ *\li Any error returned by dns_rdata_towire(), dns_rdataset_next(),
+ * dns_name_towire().
+ */
+
+isc_result_t
+dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdataset_t *rdataset);
+/*%<
+ * Search the negative caching rdataset for an rdataset with the
+ * specified name and type.
+ *
+ * Requires:
+ *\li 'ncacherdataset' is a valid negative caching rdataset.
+ *
+ *\li 'ncacherdataset' is not empty.
+ *
+ *\li 'name' is a valid name.
+ *
+ *\li 'type' is not SIG, or a meta-RR type.
+ *
+ *\li 'rdataset' is a valid disassociated rdataset.
+ *
+ * Ensures:
+ *\li On a return of ISC_R_SUCCESS, 'rdataset' is bound to the found
+ * rdataset.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS - the rdataset was found.
+ *\li #ISC_R_NOTFOUND - the rdataset was not found.
+ *
+ */
+
+void
+dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
+ dns_rdataset_t *rdataset);
+
+/*%<
+ * Extract the current rdataset and name from a ncache entry.
+ *
+ * Requires:
+ * \li 'ncacherdataset' to be valid and to be a negative cache entry
+ * \li 'found' to be valid.
+ * \li 'rdataset' to be unassociated.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_NCACHE_H */
diff --git a/lib/dns/include/dns/nsec.h b/lib/dns/include/dns/nsec.h
new file mode 100644
index 0000000..335a463
--- /dev/null
+++ b/lib/dns/include/dns/nsec.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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: nsec.h,v 1.12 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef DNS_NSEC_H
+#define DNS_NSEC_H 1
+
+/*! \file dns/nsec.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+#include <dns/name.h>
+
+#define DNS_NSEC_BUFFERSIZE (DNS_NAME_MAXWIRE + 8192 + 512)
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
+ dns_dbnode_t *node, dns_name_t *target,
+ unsigned char *buffer, dns_rdata_t *rdata);
+/*%<
+ * Build the rdata of a NSEC record.
+ *
+ * Requires:
+ *\li buffer Points to a temporary buffer of at least
+ * DNS_NSEC_BUFFERSIZE bytes.
+ *\li rdata Points to an initialized dns_rdata_t.
+ *
+ * Ensures:
+ * \li *rdata Contains a valid NSEC rdata. The 'data' member refers
+ * to 'buffer'.
+ */
+
+isc_result_t
+dns_nsec_build(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
+ dns_name_t *target, dns_ttl_t ttl);
+/*%<
+ * Build a NSEC record and add it to a database.
+ */
+
+isc_boolean_t
+dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type);
+/*%<
+ * Determine if a type is marked as present in an NSEC record.
+ *
+ * Requires:
+ *\li 'nsec' points to a valid rdataset of type NSEC
+ */
+
+isc_result_t
+dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version,
+ isc_boolean_t *answer);
+/*
+ * Report whether the DNSKEY RRset has a NSEC only algorithm. Unknown
+ * algorithms are assumed to support NSEC3.
+ *
+ * Requires:
+ * 'answer' to be non NULL.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_NSEC_H */
diff --git a/lib/dns/include/dns/nsec3.h b/lib/dns/include/dns/nsec3.h
new file mode 100644
index 0000000..5bf911a
--- /dev/null
+++ b/lib/dns/include/dns/nsec3.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2008 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: nsec3.h,v 1.5 2008/09/24 03:16:58 tbox Exp $ */
+
+#ifndef DNS_NSEC3_H
+#define DNS_NSEC3_H 1
+
+#include <isc/lang.h>
+#include <isc/iterated_hash.h>
+
+#include <dns/db.h>
+#include <dns/diff.h>
+#include <dns/name.h>
+#include <dns/rdatastruct.h>
+#include <dns/types.h>
+
+/*
+ * hash = 1, flags =1, iterations = 2, salt length = 1, salt = 255 (max)
+ * hash length = 1, hash = 255 (max), bitmap = 8192 + 512 (max)
+ */
+#define DNS_NSEC3_BUFFERSIZE (6 + 255 + 255 + 8192 + 512)
+/*
+ * hash = 1, flags = 1, iterations = 2, salt length = 1, salt = 255 (max)
+ */
+#define DNS_NSEC3PARAM_BUFFERSIZE (5 + 255)
+
+/*
+ * Test "unknown" algorithm. Is mapped to dns_hash_sha1.
+ */
+#define DNS_NSEC3_UNKNOWNALG 245U
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
+ dns_dbnode_t *node, unsigned int hashalg,
+ unsigned int optin, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length,
+ const unsigned char *nexthash, size_t hash_length,
+ unsigned char *buffer, dns_rdata_t *rdata);
+/*%<
+ * Build the rdata of a NSEC3 record for the data at 'node'.
+ * Note: 'node' is not the node where the NSEC3 record will be stored.
+ *
+ * Requires:
+ * buffer Points to a temporary buffer of at least
+ * DNS_NSEC_BUFFERSIZE bytes.
+ * rdata Points to an initialized dns_rdata_t.
+ *
+ * Ensures:
+ * *rdata Contains a valid NSEC3 rdata. The 'data' member refers
+ * to 'buffer'.
+ */
+
+isc_boolean_t
+dns_nsec3_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type);
+/*%<
+ * Determine if a type is marked as present in an NSEC3 record.
+ *
+ * Requires:
+ * 'nsec' points to a valid rdataset of type NSEC3
+ */
+
+isc_result_t
+dns_nsec3_hashname(dns_fixedname_t *result,
+ unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
+ size_t *hash_length, dns_name_t *name, dns_name_t *origin,
+ dns_hash_t hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t saltlength);
+/*%<
+ * Make a hashed domain name from an unhashed one. If rethash is not NULL
+ * the raw hash is stored there.
+ */
+
+unsigned int
+dns_nsec3_hashlength(dns_hash_t hash);
+/*%<
+ * Return the length of the hash produced by the specified algorithm
+ * or zero when unknown.
+ */
+
+isc_boolean_t
+dns_nsec3_supportedhash(dns_hash_t hash);
+/*%<
+ * Return whether we support this hash algorithm or not.
+ */
+
+isc_result_t
+dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
+ dns_name_t *name, const dns_rdata_nsec3param_t *nsec3param,
+ dns_ttl_t nsecttl, isc_boolean_t unsecure, dns_diff_t *diff);
+
+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);
+/*%<
+ * Add NSEC3 records for 'name', recording the change in 'diff'.
+ * Adjust previous NSEC3 records, if any, to reflect the addition.
+ * The existing NSEC3 records are removed.
+ *
+ * dns_nsec3_addnsec3() will only add records to the chain identified by
+ * 'nsec3param'.
+ *
+ * 'unsecure' should be set to reflect if this is a potentially
+ * unsecure delegation (no DS record).
+ *
+ * dns_nsec3_addnsec3s() will examine the NSEC3PARAM RRset to determine which
+ * chains to be updated. NSEC3PARAM records with the DNS_NSEC3FLAG_CREATE
+ * will be preferentially choosen over NSEC3PARAM records without
+ * DNS_NSEC3FLAG_CREATE set. NSEC3PARAM records with DNS_NSEC3FLAG_REMOVE
+ * set will be ignored by dns_nsec3_addnsec3s(). If DNS_NSEC3FLAG_CREATE
+ * is set then the new NSEC3 will have OPTOUT set to match the that in the
+ * NSEC3PARAM record otherwise OPTOUT will be inherited from the previous
+ * record in the chain.
+ *
+ * Requires:
+ * 'db' to be valid.
+ * 'version' to be valid or NULL.
+ * 'name' to be valid.
+ * 'nsec3param' to be valid.
+ * 'diff' to be valid.
+ */
+
+isc_result_t
+dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff);
+
+isc_result_t
+dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_diff_t *diff);
+/*%<
+ * Remove NSEC3 records for 'name', recording the change in 'diff'.
+ * Adjust previous NSEC3 records, if any, to reflect the removal.
+ *
+ * dns_nsec3_delnsec3() performs the above for the chain identified by
+ * 'nsec3param'.
+ *
+ * dns_nsec3_delnsec3s() examines the NSEC3PARAM RRset in a similar manner
+ * to dns_nsec3_addnsec3s(). Unlike dns_nsec3_addnsec3s() updated NSEC3
+ * records have the OPTOUT flag preserved.
+ *
+ * Requires:
+ * 'db' to be valid.
+ * 'version' to be valid or NULL.
+ * 'name' to be valid.
+ * 'nsec3param' to be valid.
+ * 'diff' to be valid.
+ */
+
+isc_result_t
+dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
+ isc_boolean_t complete, 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 recognised.
+ *
+ * Requires:
+ * 'db' to be valid.
+ * 'version' to be valid or NULL.
+ * 'answer' to be non NULL.
+ */
+
+isc_result_t
+dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
+ isc_mem_t *mctx, unsigned int *iterationsp);
+/*%<
+ * Find the maximum permissible number of iterations allowed based on
+ * the key strength.
+ *
+ * Requires:
+ * 'db' to be valid.
+ * 'version' to be valid or NULL.
+ * 'mctx' to be valid.
+ * 'iterationsp' to be non NULL.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_NSEC3_H */
diff --git a/lib/dns/include/dns/opcode.h b/lib/dns/include/dns/opcode.h
new file mode 100644
index 0000000..368b2b2
--- /dev/null
+++ b/lib/dns/include/dns/opcode.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: opcode.h,v 1.8 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_OPCODE_H
+#define DNS_OPCODE_H 1
+
+/*! \file dns/opcode.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target);
+/*%<
+ * Put a textual representation of error 'opcode' into 'target'.
+ *
+ * Requires:
+ *\li 'opcode' is a valid opcode.
+ *
+ *\li 'target' is a valid text buffer.
+ *
+ * Ensures:
+ *\li If the result is success:
+ * The used space in 'target' is updated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #ISC_R_NOSPACE target buffer is too small
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_OPCODE_H */
diff --git a/lib/dns/include/dns/order.h b/lib/dns/include/dns/order.h
new file mode 100644
index 0000000..85663c3
--- /dev/null
+++ b/lib/dns/include/dns/order.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: order.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_ORDER_H
+#define DNS_ORDER_H 1
+
+/*! \file dns/order.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_order_create(isc_mem_t *mctx, dns_order_t **orderp);
+/*%<
+ * Create a order object.
+ *
+ * Requires:
+ * \li 'orderp' to be non NULL and '*orderp == NULL'.
+ *\li 'mctx' to be valid.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_order_add(dns_order_t *order, dns_name_t *name,
+ dns_rdatatype_t rdtype, dns_rdataclass_t rdclass,
+ unsigned int mode);
+/*%<
+ * Add a entry to the end of the order list.
+ *
+ * Requires:
+ * \li 'order' to be valid.
+ *\li 'name' to be valid.
+ *\li 'mode' to be one of #DNS_RDATASERATTR_RANDOMIZE,
+ * #DNS_RDATASERATTR_RANDOMIZE or zero (#DNS_RDATASERATTR_CYCLIC).
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+unsigned int
+dns_order_find(dns_order_t *order, dns_name_t *name,
+ dns_rdatatype_t rdtype, dns_rdataclass_t rdclass);
+/*%<
+ * Find the first matching entry on the list.
+ *
+ * Requires:
+ *\li 'order' to be valid.
+ *\li 'name' to be valid.
+ *
+ * Returns the mode set by dns_order_add() or zero.
+ */
+
+void
+dns_order_attach(dns_order_t *source, dns_order_t **target);
+/*%<
+ * Attach to the 'source' object.
+ *
+ * Requires:
+ * \li 'source' to be valid.
+ *\li 'target' to be non NULL and '*target == NULL'.
+ */
+
+void
+dns_order_detach(dns_order_t **orderp);
+/*%<
+ * Detach from the object. Clean up if last this was the last
+ * reference.
+ *
+ * Requires:
+ *\li '*orderp' to be valid.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_ORDER_H */
diff --git a/lib/dns/include/dns/peer.h b/lib/dns/include/dns/peer.h
new file mode 100644
index 0000000..c4b95c9
--- /dev/null
+++ b/lib/dns/include/dns/peer.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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: peer.h,v 1.33 2008/04/03 06:09:05 tbox Exp $ */
+
+#ifndef DNS_PEER_H
+#define DNS_PEER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/peer.h
+ * \brief
+ * Data structures for peers (e.g. a 'server' config file statement)
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/netaddr.h>
+
+#include <dns/types.h>
+
+#define DNS_PEERLIST_MAGIC ISC_MAGIC('s','e','R','L')
+#define DNS_PEER_MAGIC ISC_MAGIC('S','E','r','v')
+
+#define DNS_PEERLIST_VALID(ptr) ISC_MAGIC_VALID(ptr, DNS_PEERLIST_MAGIC)
+#define DNS_PEER_VALID(ptr) ISC_MAGIC_VALID(ptr, DNS_PEER_MAGIC)
+
+/***
+ *** Types
+ ***/
+
+struct dns_peerlist {
+ unsigned int magic;
+ isc_uint32_t refs;
+
+ isc_mem_t *mem;
+
+ ISC_LIST(dns_peer_t) elements;
+};
+
+struct dns_peer {
+ unsigned int magic;
+ isc_uint32_t refs;
+
+ isc_mem_t *mem;
+
+ isc_netaddr_t address;
+ unsigned int prefixlen;
+ isc_boolean_t bogus;
+ dns_transfer_format_t transfer_format;
+ isc_uint32_t transfers;
+ isc_boolean_t support_ixfr;
+ isc_boolean_t provide_ixfr;
+ isc_boolean_t request_ixfr;
+ isc_boolean_t support_edns;
+ isc_boolean_t request_nsid;
+ dns_name_t *key;
+ isc_sockaddr_t *transfer_source;
+ isc_sockaddr_t *notify_source;
+ isc_sockaddr_t *query_source;
+ isc_uint16_t udpsize; /* recieve size */
+ isc_uint16_t maxudp; /* transmit size */
+
+ isc_uint32_t bitflags;
+
+ ISC_LINK(dns_peer_t) next;
+};
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_peerlist_new(isc_mem_t *mem, dns_peerlist_t **list);
+
+void
+dns_peerlist_attach(dns_peerlist_t *source, dns_peerlist_t **target);
+
+void
+dns_peerlist_detach(dns_peerlist_t **list);
+
+/*
+ * After return caller still holds a reference to peer.
+ */
+void
+dns_peerlist_addpeer(dns_peerlist_t *peers, dns_peer_t *peer);
+
+/*
+ * Ditto. */
+isc_result_t
+dns_peerlist_peerbyaddr(dns_peerlist_t *peers, isc_netaddr_t *addr,
+ dns_peer_t **retval);
+
+/*
+ * What he said.
+ */
+isc_result_t
+dns_peerlist_currpeer(dns_peerlist_t *peers, dns_peer_t **retval);
+
+isc_result_t
+dns_peer_new(isc_mem_t *mem, isc_netaddr_t *ipaddr, dns_peer_t **peer);
+
+isc_result_t
+dns_peer_newprefix(isc_mem_t *mem, isc_netaddr_t *ipaddr,
+ unsigned int prefixlen, dns_peer_t **peer);
+
+void
+dns_peer_attach(dns_peer_t *source, dns_peer_t **target);
+
+void
+dns_peer_detach(dns_peer_t **list);
+
+isc_result_t
+dns_peer_setbogus(dns_peer_t *peer, isc_boolean_t newval);
+
+isc_result_t
+dns_peer_getbogus(dns_peer_t *peer, isc_boolean_t *retval);
+
+isc_result_t
+dns_peer_setrequestixfr(dns_peer_t *peer, isc_boolean_t newval);
+
+isc_result_t
+dns_peer_getrequestixfr(dns_peer_t *peer, isc_boolean_t *retval);
+
+isc_result_t
+dns_peer_setprovideixfr(dns_peer_t *peer, isc_boolean_t newval);
+
+isc_result_t
+dns_peer_getprovideixfr(dns_peer_t *peer, isc_boolean_t *retval);
+
+isc_result_t
+dns_peer_setrequestnsid(dns_peer_t *peer, isc_boolean_t newval);
+
+isc_result_t
+dns_peer_getrequestnsid(dns_peer_t *peer, isc_boolean_t *retval);
+
+isc_result_t
+dns_peer_setsupportedns(dns_peer_t *peer, isc_boolean_t newval);
+
+isc_result_t
+dns_peer_getsupportedns(dns_peer_t *peer, isc_boolean_t *retval);
+
+isc_result_t
+dns_peer_settransfers(dns_peer_t *peer, isc_uint32_t newval);
+
+isc_result_t
+dns_peer_gettransfers(dns_peer_t *peer, isc_uint32_t *retval);
+
+isc_result_t
+dns_peer_settransferformat(dns_peer_t *peer, dns_transfer_format_t newval);
+
+isc_result_t
+dns_peer_gettransferformat(dns_peer_t *peer, dns_transfer_format_t *retval);
+
+isc_result_t
+dns_peer_setkeybycharp(dns_peer_t *peer, const char *keyval);
+
+isc_result_t
+dns_peer_getkey(dns_peer_t *peer, dns_name_t **retval);
+
+isc_result_t
+dns_peer_setkey(dns_peer_t *peer, dns_name_t **keyval);
+
+isc_result_t
+dns_peer_settransfersource(dns_peer_t *peer,
+ const isc_sockaddr_t *transfer_source);
+
+isc_result_t
+dns_peer_gettransfersource(dns_peer_t *peer, isc_sockaddr_t *transfer_source);
+
+isc_result_t
+dns_peer_setudpsize(dns_peer_t *peer, isc_uint16_t udpsize);
+
+isc_result_t
+dns_peer_getudpsize(dns_peer_t *peer, isc_uint16_t *udpsize);
+
+isc_result_t
+dns_peer_setmaxudp(dns_peer_t *peer, isc_uint16_t maxudp);
+
+isc_result_t
+dns_peer_getmaxudp(dns_peer_t *peer, isc_uint16_t *maxudp);
+
+isc_result_t
+dns_peer_setnotifysource(dns_peer_t *peer, const isc_sockaddr_t *notify_source);
+
+isc_result_t
+dns_peer_getnotifysource(dns_peer_t *peer, isc_sockaddr_t *notify_source);
+
+isc_result_t
+dns_peer_setquerysource(dns_peer_t *peer, const isc_sockaddr_t *query_source);
+
+isc_result_t
+dns_peer_getquerysource(dns_peer_t *peer, isc_sockaddr_t *query_source);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_PEER_H */
diff --git a/lib/dns/include/dns/portlist.h b/lib/dns/include/dns/portlist.h
new file mode 100644
index 0000000..f76731a
--- /dev/null
+++ b/lib/dns/include/dns/portlist.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: portlist.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file dns/portlist.h */
+
+#include <isc/lang.h>
+#include <isc/net.h>
+#include <isc/types.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_portlist_create(isc_mem_t *mctx, dns_portlist_t **portlistp);
+/*%<
+ * Create a port list.
+ *
+ * Requires:
+ *\li 'mctx' to be valid.
+ *\li 'portlistp' to be non NULL and '*portlistp' to be NULL;
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+dns_portlist_add(dns_portlist_t *portlist, int af, in_port_t port);
+/*%<
+ * Add the given <port,af> tuple to the portlist.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ *\li 'af' to be AF_INET or AF_INET6
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+dns_portlist_remove(dns_portlist_t *portlist, int af, in_port_t port);
+/*%<
+ * Remove the given <port,af> tuple to the portlist.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ *\li 'af' to be AF_INET or AF_INET6
+ */
+
+isc_boolean_t
+dns_portlist_match(dns_portlist_t *portlist, int af, in_port_t port);
+/*%<
+ * Find the given <port,af> tuple to the portlist.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ *\li 'af' to be AF_INET or AF_INET6
+ *
+ * Returns
+ * \li #ISC_TRUE if the tuple is found, ISC_FALSE otherwise.
+ */
+
+void
+dns_portlist_attach(dns_portlist_t *portlist, dns_portlist_t **portlistp);
+/*%<
+ * Attach to a port list.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ *\li 'portlistp' to be non NULL and '*portlistp' to be NULL;
+ */
+
+void
+dns_portlist_detach(dns_portlist_t **portlistp);
+/*%<
+ * Detach from a port list.
+ *
+ * Requires:
+ *\li '*portlistp' to be valid.
+ */
+
+ISC_LANG_ENDDECLS
diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h
new file mode 100644
index 0000000..06b55d5
--- /dev/null
+++ b/lib/dns/include/dns/rbt.h
@@ -0,0 +1,939 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: rbt.h,v 1.71 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef DNS_RBT_H
+#define DNS_RBT_H 1
+
+/*! \file dns/rbt.h */
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/refcount.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+#define DNS_RBT_USEHASH 1
+
+/*@{*/
+/*%
+ * Option values for dns_rbt_findnode() and dns_rbt_findname().
+ * These are used to form a bitmask.
+ */
+#define DNS_RBTFIND_NOOPTIONS 0x00
+#define DNS_RBTFIND_EMPTYDATA 0x01
+#define DNS_RBTFIND_NOEXACT 0x02
+#define DNS_RBTFIND_NOPREDECESSOR 0x04
+/*@}*/
+
+#ifndef DNS_RBT_USEISCREFCOUNT
+#ifdef ISC_REFCOUNT_HAVEATOMIC
+#define DNS_RBT_USEISCREFCOUNT 1
+#endif
+#endif
+
+/*
+ * These should add up to 30.
+ */
+#define DNS_RBT_LOCKLENGTH 10
+#define DNS_RBT_REFLENGTH 20
+
+#define DNS_RBTNODE_MAGIC ISC_MAGIC('R','B','N','O')
+#if DNS_RBT_USEMAGIC
+#define DNS_RBTNODE_VALID(n) ISC_MAGIC_VALID(n, DNS_RBTNODE_MAGIC)
+#else
+#define DNS_RBTNODE_VALID(n) ISC_TRUE
+#endif
+
+/*%
+ * This is the structure that is used for each node in the red/black
+ * tree of trees. NOTE WELL: the implementation manages this as a variable
+ * length structure, with the actual wire-format name and other data
+ * appended to this structure. Allocating a contiguous block of memory for
+ * multiple dns_rbtnode structures will not work.
+ */
+typedef struct dns_rbtnode dns_rbtnode_t;
+struct dns_rbtnode {
+#if DNS_RBT_USEMAGIC
+ unsigned int magic;
+#endif
+ dns_rbtnode_t *parent;
+ dns_rbtnode_t *left;
+ dns_rbtnode_t *right;
+ dns_rbtnode_t *down;
+#ifdef DNS_RBT_USEHASH
+ dns_rbtnode_t *hashnext;
+#endif
+
+ /*%
+ * Used for LRU cache. This linked list is used to mark nodes which
+ * have no data any longer, but we cannot unlink at that exact moment
+ * because we did not or could not obtain a write lock on the tree.
+ */
+ ISC_LINK(dns_rbtnode_t) deadlink;
+
+ /*@{*/
+ /*!
+ * 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 accomodate
+ * 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).
+ *
+ * In each case below the "range" indicated is what's _necessary_ for
+ * the bitfield to hold, not what it actually _can_ hold.
+ */
+ 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 : 3; /*%< range is 0..2 */
+ unsigned int nsec3 : 1; /*%< range is 0..1 */
+ unsigned int namelen : 8; /*%< range is 1..255 */
+ unsigned int offsetlen : 8; /*%< range is 1..128 */
+ unsigned int padbytes : 9; /*%< range is 0..380 */
+ /*@}*/
+
+#ifdef DNS_RBT_USEHASH
+ unsigned int hashval;
+#endif
+
+ /*@{*/
+ /*!
+ * These values are used in the RBT DB implementation. The appropriate
+ * node lock must be held before accessing them.
+ */
+ void *data;
+ unsigned int dirty:1;
+ unsigned int wild:1;
+ unsigned int locknum:DNS_RBT_LOCKLENGTH;
+#ifndef DNS_RBT_USEISCREFCOUNT
+ unsigned int references:DNS_RBT_REFLENGTH;
+#else
+ isc_refcount_t references; /* note that this is not in the bitfield */
+#endif
+ /*@}*/
+};
+
+typedef isc_result_t (*dns_rbtfindcallback_t)(dns_rbtnode_t *node,
+ dns_name_t *name,
+ void *callback_arg);
+
+/*****
+ ***** Chain Info
+ *****/
+
+/*!
+ * A chain is used to keep track of the sequence of nodes to reach any given
+ * node from the root of the tree. Originally nodes did not have parent
+ * pointers in them (for memory usage reasons) so there was no way to find
+ * the path back to the root from any given node. Now that nodes have parent
+ * pointers, chains might be going away in a future release, though the
+ * movement functionality would remain.
+ *
+ * In any event, parent information, whether via parent pointers or chains, is
+ * necessary information for iterating through the tree or for basic internal
+ * tree maintenance issues (ie, the rotations that are done to rebalance the
+ * tree when a node is added). The obvious implication of this is that for a
+ * chain to remain valid, the tree has to be locked down against writes for the
+ * duration of the useful life of the chain, because additions or removals can
+ * change the path from the root to the node the chain has targetted.
+ *
+ * The dns_rbtnodechain_ functions _first, _last, _prev and _next all take
+ * dns_name_t parameters for the name and the origin, which can be NULL. If
+ * non-NULL, 'name' will end up pointing to the name data and offsets that are
+ * stored at the node (and thus it will be read-only), so it should be a
+ * regular dns_name_t that has been initialized with dns_name_init. When
+ * 'origin' is non-NULL, it will get the name of the origin stored in it, so it
+ * needs to have its own buffer space and offsets, which is most easily
+ * accomplished with a dns_fixedname_t. It is _not_ necessary to reinitialize
+ * either 'name' or 'origin' between calls to the chain functions.
+ *
+ * NOTE WELL: even though the name data at the root of the tree of trees will
+ * be absolute (typically just "."), it will will be made into a relative name
+ * with an origin of "." -- an empty name when the node is ".". This is
+ * because a common on operation on 'name' and 'origin' is to use
+ * dns_name_concatenate() on them to generate the complete name. An empty name
+ * can be detected when dns_name_countlabels == 0, and is printed by
+ * dns_name_totext()/dns_name_format() as "@", consistent with RFC1035's
+ * definition of "@" as the current origin.
+ *
+ * dns_rbtnodechain_current is similar to the _first, _last, _prev and _next
+ * functions but additionally can provide the node to which the chain points.
+ */
+
+/*%
+ * The number of level blocks to allocate at a time. Currently the maximum
+ * number of levels is allocated directly in the structure, but future
+ * revisions of this code might have a static initial block with dynamic
+ * growth. Allocating space for 256 levels when the tree is almost never that
+ * deep is wasteful, but it's not clear that it matters, since the waste is
+ * only 2MB for 1000 concurrently active chains on a system with 64-bit
+ * pointers.
+ */
+#define DNS_RBT_LEVELBLOCK 254
+
+typedef struct dns_rbtnodechain {
+ unsigned int magic;
+ isc_mem_t * mctx;
+ /*%
+ * The terminal node of the chain. It is not in levels[].
+ * This is ostensibly private ... but in a pinch it could be
+ * used tell that the chain points nowhere without needing to
+ * call dns_rbtnodechain_current().
+ */
+ dns_rbtnode_t * end;
+ /*%
+ * The maximum number of labels in a name is 128; bitstrings mean
+ * a conceptually very large number (which I have not bothered to
+ * compute) of logical levels because splitting can potentially occur
+ * at each bit. However, DNSSEC restricts the number of "logical"
+ * labels in a name to 255, meaning only 254 pointers are needed
+ * in the worst case.
+ */
+ dns_rbtnode_t * levels[DNS_RBT_LEVELBLOCK];
+ /*%
+ * level_count indicates how deep the chain points into the
+ * tree of trees, and is the index into the levels[] array.
+ * Thus, levels[level_count - 1] is the last level node stored.
+ * A chain that points to the top level of the tree of trees has
+ * a level_count of 0, the first level has a level_count of 1, and
+ * so on.
+ */
+ unsigned int level_count;
+ /*%
+ * level_matches tells how many levels matched above the node
+ * returned by dns_rbt_findnode(). A match (partial or exact) found
+ * in the first level thus results in level_matches being set to 1.
+ * This is used by the rbtdb to set the start point for a recursive
+ * search of superdomains until the RR it is looking for is found.
+ */
+ unsigned int level_matches;
+} dns_rbtnodechain_t;
+
+/*****
+ ***** Public interfaces.
+ *****/
+isc_result_t
+dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
+ void *deleter_arg, dns_rbt_t **rbtp);
+/*%<
+ * Initialize a red-black tree of trees.
+ *
+ * Notes:
+ *\li The deleter argument, if non-null, points to a function that is
+ * responsible for cleaning up any memory associated with the data
+ * pointer of a node when the node is deleted. It is passed the
+ * deleted node's data pointer as its first argument and deleter_arg
+ * as its second argument.
+ *
+ * Requires:
+ * \li mctx is a pointer to a valid memory context.
+ *\li rbtp != NULL && *rbtp == NULL
+ *\li arg == NULL iff deleter == NULL
+ *
+ * Ensures:
+ *\li If result is ISC_R_SUCCESS:
+ * *rbtp points to a valid red-black tree manager
+ *
+ *\li If result is failure:
+ * *rbtp does not point to a valid red-black tree manager.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource limit: Out of Memory
+ */
+
+isc_result_t
+dns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data);
+/*%<
+ * Add 'name' to the tree of trees, associated with 'data'.
+ *
+ * Notes:
+ *\li 'data' is never required to be non-NULL, but specifying it
+ * when the name is added is faster than searching for 'name'
+ * again and then setting the data pointer. The lack of a data pointer
+ * for a node also has other ramifications regarding whether
+ * dns_rbt_findname considers a node to exist, or dns_rbt_deletename
+ * joins nodes.
+ *
+ * Requires:
+ *\li rbt is a valid rbt manager.
+ *\li dns_name_isabsolute(name) == TRUE
+ *
+ * Ensures:
+ *\li 'name' is not altered in any way.
+ *
+ *\li Any external references to nodes in the tree are unaffected by
+ * node splits that are necessary to insert the new name.
+ *
+ *\li If result is #ISC_R_SUCCESS:
+ * 'name' is findable in the red/black tree of trees in O(log N).
+ * The data pointer of the node for 'name' is set to 'data'.
+ *
+ *\li If result is #ISC_R_EXISTS or #ISC_R_NOSPACE:
+ * The tree of trees is unaltered.
+ *
+ *\li If result is #ISC_R_NOMEMORY:
+ * No guarantees.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_EXISTS The name already exists with associated data.
+ *\li #ISC_R_NOSPACE The name had more logical labels than are allowed.
+ *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory
+ */
+
+isc_result_t
+dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep);
+
+/*%<
+ * Just like dns_rbt_addname, but returns the address of the node.
+ *
+ * Requires:
+ *\li rbt is a valid rbt structure.
+ *\li dns_name_isabsolute(name) == TRUE
+ *\li nodep != NULL && *nodep == NULL
+ *
+ * Ensures:
+ *\li 'name' is not altered in any way.
+ *
+ *\li Any external references to nodes in the tree are unaffected by
+ * node splits that are necessary to insert the new name.
+ *
+ *\li If result is ISC_R_SUCCESS:
+ * 'name' is findable in the red/black tree of trees in O(log N).
+ * *nodep is the node that was added for 'name'.
+ *
+ *\li If result is ISC_R_EXISTS:
+ * The tree of trees is unaltered.
+ * *nodep is the existing node for 'name'.
+ *
+ *\li If result is ISC_R_NOMEMORY:
+ * No guarantees.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_EXISTS The name already exists, possibly without data.
+ *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory
+ */
+
+isc_result_t
+dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
+ dns_name_t *foundname, void **data);
+/*%<
+ * Get the data pointer associated with 'name'.
+ *
+ * Notes:
+ *\li When #DNS_RBTFIND_NOEXACT is set, the closest matching superdomain is
+ * returned (also subject to #DNS_RBTFIND_EMPTYDATA), even when there is
+ * an exact match in the tree.
+ *
+ *\li A node that has no data is considered not to exist for this function,
+ * unless the #DNS_RBTFIND_EMPTYDATA option is set.
+ *
+ * Requires:
+ *\li rbt is a valid rbt manager.
+ *\li dns_name_isabsolute(name) == TRUE
+ *\li data != NULL && *data == NULL
+ *
+ * Ensures:
+ *\li 'name' and the tree are not altered in any way.
+ *
+ *\li If result is ISC_R_SUCCESS:
+ * *data is the data associated with 'name'.
+ *
+ *\li If result is DNS_R_PARTIALMATCH:
+ * *data is the data associated with the deepest superdomain
+ * of 'name' which has data.
+ *
+ *\li If result is ISC_R_NOTFOUND:
+ * Neither the name nor a superdomain was found with data.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #DNS_R_PARTIALMATCH Superdomain found with data
+ *\li #ISC_R_NOTFOUND No match
+ *\li #ISC_R_NOSPACE Concatenating nodes to form foundname failed
+ */
+
+isc_result_t
+dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
+ dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
+ unsigned int options, dns_rbtfindcallback_t callback,
+ void *callback_arg);
+/*%<
+ * Find the node for 'name'.
+ *
+ * Notes:
+ *\li A node that has no data is considered not to exist for this function,
+ * unless the DNS_RBTFIND_EMPTYDATA option is set. This applies to both
+ * exact matches and partial matches.
+ *
+ *\li If the chain parameter is non-NULL, then the path through the tree
+ * to the DNSSEC predecessor of the searched for name is maintained,
+ * unless the DNS_RBTFIND_NOPREDECESSOR or DNS_RBTFIND_NOEXACT option
+ * is used. (For more details on those options, see below.)
+ *
+ *\li If there is no predecessor, then the chain will point to nowhere, as
+ * indicated by chain->end being NULL or dns_rbtnodechain_current
+ * returning ISC_R_NOTFOUND. Note that in a normal Internet DNS RBT
+ * there will always be a predecessor for all names except the root
+ * name, because '.' will exist and '.' is the predecessor of
+ * everything. But you can certainly construct a trivial tree and a
+ * search for it that has no predecessor.
+ *
+ *\li Within the chain structure, the 'levels' member of the structure holds
+ * the root node of each level except the first.
+ *
+ *\li The 'level_count' of the chain indicates how deep the chain to the
+ * predecessor name is, as an index into the 'levels[]' array. It does
+ * not count name elements, per se, but only levels of the tree of trees,
+ * the distinction arrising because multiple labels from a name can be
+ * stored on only one level. It is also does not include the level
+ * that has the node, since that level is not stored in levels[].
+ *
+ *\li The chain's 'level_matches' is not directly related to the predecessor.
+ * It is the number of levels above the level of the found 'node',
+ * regardless of whether it was a partial match or exact match. When
+ * the node is found in the top level tree, or no node is found at all,
+ * level_matches is 0.
+ *
+ *\li When DNS_RBTFIND_NOEXACT is set, the closest matching superdomain is
+ * returned (also subject to DNS_RBTFIND_EMPTYDATA), even when
+ * there is an exact match in the tree. In this case, the chain
+ * will not point to the DNSSEC predecessor, but will instead point
+ * to the exact match, if there was any. Thus the preceding paragraphs
+ * should have "exact match" substituted for "predecessor" to describe
+ * how the various elements of the chain are set. This was done to
+ * ensure that the chain's state was sane, and to prevent problems that
+ * occurred when running the predecessor location code under conditions
+ * it was not designed for. It is not clear *where* the chain should
+ * point when DNS_RBTFIND_NOEXACT is set, so if you end up using a chain
+ * with this option because you want a particular node, let us know
+ * where you want the chain pointed, so this can be made more firm.
+ *
+ * Requires:
+ *\li rbt is a valid rbt manager.
+ *\li dns_name_isabsolute(name) == TRUE.
+ *\li node != NULL && *node == NULL.
+ *\li #DNS_RBTFIND_NOEXACT and DNS_RBTFIND_NOPREDECESSOR are mutally
+ * exclusive.
+ *
+ * Ensures:
+ *\li 'name' and the tree are not altered in any way.
+ *
+ *\li If result is ISC_R_SUCCESS:
+ *\verbatim
+ * *node is the terminal node for 'name'.
+
+ * 'foundname' and 'name' represent the same name (though not
+ * the same memory).
+
+ * 'chain' points to the DNSSEC predecessor, if any, of 'name'.
+ *
+ * chain->level_matches and chain->level_count are equal.
+ *\endverbatim
+ *
+ * If result is DNS_R_PARTIALMATCH:
+ *\verbatim
+ * *node is the data associated with the deepest superdomain
+ * of 'name' which has data.
+ *
+ * 'foundname' is the name of deepest superdomain (which has
+ * data, unless the DNS_RBTFIND_EMPTYDATA option is set).
+ *
+ * 'chain' points to the DNSSEC predecessor, if any, of 'name'.
+ *\endverbatim
+ *
+ *\li If result is ISC_R_NOTFOUND:
+ *\verbatim
+ * Neither the name nor a superdomain was found. *node is NULL.
+ *
+ * 'chain' points to the DNSSEC predecessor, if any, of 'name'.
+ *
+ * chain->level_matches is 0.
+ *\endverbatim
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #DNS_R_PARTIALMATCH Superdomain found with data
+ *\li #ISC_R_NOTFOUND No match, or superdomain with no data
+ *\li #ISC_R_NOSPACE Concatenating nodes to form foundname failed
+ */
+
+isc_result_t
+dns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse);
+/*%<
+ * Delete 'name' from the tree of trees.
+ *
+ * Notes:
+ *\li When 'name' is removed, if recurse is ISC_TRUE then all of its
+ * subnames are removed too.
+ *
+ * Requires:
+ *\li rbt is a valid rbt manager.
+ *\li dns_name_isabsolute(name) == TRUE
+ *
+ * Ensures:
+ *\li 'name' is not altered in any way.
+ *
+ *\li Does NOT ensure that any external references to nodes in the tree
+ * are unaffected by node joins.
+ *
+ *\li If result is ISC_R_SUCCESS:
+ * 'name' does not appear in the tree with data; however,
+ * the node for the name might still exist which can be
+ * found with dns_rbt_findnode (but not dns_rbt_findname).
+ *
+ *\li If result is ISC_R_NOTFOUND:
+ * 'name' does not appear in the tree with data, because
+ * it did not appear in the tree before the function was called.
+ *
+ *\li If result is something else:
+ * See result codes for dns_rbt_findnode (if it fails, the
+ * node is not deleted) or dns_rbt_deletenode (if it fails,
+ * the node is deleted, but the tree is not optimized when
+ * it could have been).
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOTFOUND No match
+ *\li something_else Any return code from dns_rbt_findnode except
+ * DNS_R_PARTIALMATCH (which causes ISC_R_NOTFOUND
+ * to be returned instead), and any code from
+ * dns_rbt_deletenode.
+ */
+
+isc_result_t
+dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse);
+/*%<
+ * Delete 'node' from the tree of trees.
+ *
+ * Notes:
+ *\li When 'node' is removed, if recurse is ISC_TRUE then all nodes
+ * in levels down from it are removed too.
+ *
+ * Requires:
+ *\li rbt is a valid rbt manager.
+ *\li node != NULL.
+ *
+ * Ensures:
+ *\li Does NOT ensure that any external references to nodes in the tree
+ * are unaffected by node joins.
+ *
+ *\li If result is ISC_R_SUCCESS:
+ * 'node' does not appear in the tree with data; however,
+ * the node might still exist if it serves as a pointer to
+ * a lower tree level as long as 'recurse' was false, hence
+ * the node could can be found with dns_rbt_findnode whem
+ * that function's empty_data_ok parameter is true.
+ *
+ *\li If result is ISC_R_NOMEMORY or ISC_R_NOSPACE:
+ * The node was deleted, but the tree structure was not
+ * optimized.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory when joining nodes.
+ *\li #ISC_R_NOSPACE dns_name_concatenate failed when joining nodes.
+ */
+
+void
+dns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name);
+/*%<
+ * Convert the sequence of labels stored at 'node' into a 'name'.
+ *
+ * Notes:
+ *\li This function does not return the full name, from the root, but
+ * just the labels at the indicated node.
+ *
+ *\li The name data pointed to by 'name' is the information stored
+ * in the node, not a copy. Altering the data at this pointer
+ * will likely cause grief.
+ *
+ * Requires:
+ * \li name->offsets == NULL
+ *
+ * Ensures:
+ * \li 'name' is DNS_NAMEATTR_READONLY.
+ *
+ * \li 'name' will point directly to the labels stored after the
+ * dns_rbtnode_t struct.
+ *
+ * \li 'name' will have offsets that also point to the information stored
+ * as part of the node.
+ */
+
+isc_result_t
+dns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name);
+/*%<
+ * Like dns_rbt_namefromnode, but returns the full name from the root.
+ *
+ * Notes:
+ * \li Unlike dns_rbt_namefromnode, the name will not point directly
+ * to node data. Rather, dns_name_concatenate will be used to copy
+ * the name data from each node into the 'name' argument.
+ *
+ * Requires:
+ * \li name != NULL
+ * \li name has a dedicated buffer.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOSPACE (possible via dns_name_concatenate)
+ * \li DNS_R_NAMETOOLONG (possible via dns_name_concatenate)
+ */
+
+char *
+dns_rbt_formatnodename(dns_rbtnode_t *node, char *printname,
+ unsigned int size);
+/*%<
+ * Format the full name of a node for printing, using dns_name_format().
+ *
+ * Notes:
+ * \li 'size' is the length of the printname buffer. This should be
+ * DNS_NAME_FORMATSIZE or larger.
+ *
+ * Requires:
+ * \li node and printname are not NULL.
+ *
+ * Returns:
+ * \li The 'printname' pointer.
+ */
+
+unsigned int
+dns_rbt_nodecount(dns_rbt_t *rbt);
+/*%<
+ * Obtain the number of nodes in the tree of trees.
+ *
+ * Requires:
+ * \li rbt is a valid rbt manager.
+ */
+
+void
+dns_rbt_destroy(dns_rbt_t **rbtp);
+isc_result_t
+dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum);
+/*%<
+ * Stop working with a red-black tree of trees.
+ * If 'quantum' is zero then the entire tree will be destroyed.
+ * If 'quantum' is non zero then up to 'quantum' nodes will be destroyed
+ * allowing the rbt to be incrementally destroyed by repeated calls to
+ * dns_rbt_destroy2(). Once dns_rbt_destroy2() has been called no other
+ * operations than dns_rbt_destroy()/dns_rbt_destroy2() should be
+ * performed on the tree of trees.
+ *
+ * Requires:
+ * \li *rbt is a valid rbt manager.
+ *
+ * Ensures on ISC_R_SUCCESS:
+ * \li All space allocated by the RBT library has been returned.
+ *
+ * \li *rbt is invalidated as an rbt manager.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_QUOTA if 'quantum' nodes have been destroyed.
+ */
+
+void
+dns_rbt_printall(dns_rbt_t *rbt);
+/*%<
+ * Print an ASCII representation of the internal structure of the red-black
+ * tree of trees.
+ *
+ * Notes:
+ * \li The name stored at each node, along with the node's color, is printed.
+ * Then the down pointer, left and right pointers are displayed
+ * recursively in turn. NULL down pointers are silently omitted;
+ * NULL left and right pointers are printed.
+ */
+
+/*****
+ ***** Chain Functions
+ *****/
+
+void
+dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx);
+/*%<
+ * Initialize 'chain'.
+ *
+ * Requires:
+ *\li 'chain' is a valid pointer.
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ * Ensures:
+ *\li 'chain' is suitable for use.
+ */
+
+void
+dns_rbtnodechain_reset(dns_rbtnodechain_t *chain);
+/*%<
+ * Free any dynamic storage associated with 'chain', and then reinitialize
+ * 'chain'.
+ *
+ * Requires:
+ *\li 'chain' is a valid pointer.
+ *
+ * Ensures:
+ *\li 'chain' is suitable for use, and uses no dynamic storage.
+ */
+
+void
+dns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain);
+/*%<
+ * Free any dynamic storage associated with 'chain', and then invalidates it.
+ *
+ * Notes:
+ *\li Future calls to any dns_rbtnodechain_ function will need to call
+ * dns_rbtnodechain_init on the chain first (except, of course,
+ * dns_rbtnodechain_init itself).
+ *
+ * Requires:
+ *\li 'chain' is a valid chain.
+ *
+ * Ensures:
+ *\li 'chain' is no longer suitable for use, and uses no dynamic storage.
+ */
+
+isc_result_t
+dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin, dns_rbtnode_t **node);
+/*%<
+ * Provide the name, origin and node to which the chain is currently pointed.
+ *
+ * Notes:
+ *\li The tree need not have be locked against additions for the chain
+ * to remain valid, however there are no guarantees if any deletion
+ * has been made since the chain was established.
+ *
+ * Requires:
+ *\li 'chain' is a valid chain.
+ *
+ * Ensures:
+ *\li 'node', if non-NULL, is the node to which the chain was pointed
+ * by dns_rbt_findnode, dns_rbtnodechain_first or dns_rbtnodechain_last.
+ * If none were called for the chain since it was initialized or reset,
+ * or if the was no predecessor to the name searched for with
+ * dns_rbt_findnode, then '*node' is NULL and ISC_R_NOTFOUND is returned.
+ *
+ *\li 'name', if non-NULL, is the name stored at the terminal level of
+ * the chain. This is typically a single label, like the "www" of
+ * "www.isc.org", but need not be so. At the root of the tree of trees,
+ * if the node is "." then 'name' is ".", otherwise it is relative to ".".
+ * (Minimalist and atypical case: if the tree has just the name
+ * "isc.org." then the root node's stored name is "isc.org." but 'name'
+ * will be "isc.org".)
+ *
+ *\li 'origin', if non-NULL, is the sequence of labels in the levels
+ * above the terminal level, such as "isc.org." in the above example.
+ * 'origin' is always "." for the root node.
+ *
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS name, origin & node were successfully set.
+ *\li #ISC_R_NOTFOUND The chain does not point to any node.
+ *\li &lt;something_else> Any error return from dns_name_concatenate.
+ */
+
+isc_result_t
+dns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
+ dns_name_t *name, dns_name_t *origin);
+/*%<
+ * Set the chain to the lexically first node in the tree of trees.
+ *
+ * Notes:
+ *\li By the definition of ordering for DNS names, the root of the tree of
+ * trees is the very first node, since everything else in the megatree
+ * uses it as a common suffix.
+ *
+ * Requires:
+ *\li 'chain' is a valid chain.
+ *\li 'rbt' is a valid rbt manager.
+ *
+ * Ensures:
+ *\li The chain points to the very first node of the tree.
+ *
+ *\li 'name' and 'origin', if non-NULL, are set as described for
+ * dns_rbtnodechain_current. Thus 'origin' will always be ".".
+ *
+ * Returns:
+ *\li #DNS_R_NEWORIGIN The name & origin were successfully set.
+ *\li &lt;something_else> Any error result from dns_rbtnodechain_current.
+ */
+
+isc_result_t
+dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
+ dns_name_t *name, dns_name_t *origin);
+/*%<
+ * Set the chain to the lexically last node in the tree of trees.
+ *
+ * Requires:
+ *\li 'chain' is a valid chain.
+ *\li 'rbt' is a valid rbt manager.
+ *
+ * Ensures:
+ *\li The chain points to the very last node of the tree.
+ *
+ *\li 'name' and 'origin', if non-NULL, are set as described for
+ * dns_rbtnodechain_current.
+ *
+ * Returns:
+ *\li #DNS_R_NEWORIGIN The name & origin were successfully set.
+ *\li #ISC_R_NOMEMORY Resource Limit: Out of Memory building chain.
+ *\li &lt;something_else> Any error result from dns_name_concatenate.
+ */
+
+isc_result_t
+dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin);
+/*%<
+ * Adjusts chain to point the DNSSEC predecessor of the name to which it
+ * is currently pointed.
+ *
+ * Requires:
+ *\li 'chain' is a valid chain.
+ *\li 'chain' has been pointed somewhere in the tree with dns_rbt_findnode,
+ * dns_rbtnodechain_first or dns_rbtnodechain_last -- and remember that
+ * dns_rbt_findnode is not guaranteed to point the chain somewhere,
+ * since there may have been no predecessor to the searched for name.
+ *
+ * Ensures:
+ *\li The chain is pointed to the predecessor of its current target.
+ *
+ *\li 'name' and 'origin', if non-NULL, are set as described for
+ * dns_rbtnodechain_current.
+ *
+ *\li 'origin' is only if a new origin was found.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS The predecessor was found and 'name' was set.
+ *\li #DNS_R_NEWORIGIN The predecessor was found with a different
+ * origin and 'name' and 'origin' were set.
+ *\li #ISC_R_NOMORE There was no predecessor.
+ *\li &lt;something_else> Any error result from dns_rbtnodechain_current.
+ */
+
+isc_result_t
+dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin);
+/*%<
+ * Adjusts chain to point the DNSSEC successor of the name to which it
+ * is currently pointed.
+ *
+ * Requires:
+ *\li 'chain' is a valid chain.
+ *\li 'chain' has been pointed somewhere in the tree with dns_rbt_findnode,
+ * dns_rbtnodechain_first or dns_rbtnodechain_last -- and remember that
+ * dns_rbt_findnode is not guaranteed to point the chain somewhere,
+ * since there may have been no predecessor to the searched for name.
+ *
+ * Ensures:
+ *\li The chain is pointed to the successor of its current target.
+ *
+ *\li 'name' and 'origin', if non-NULL, are set as described for
+ * dns_rbtnodechain_current.
+ *
+ *\li 'origin' is only if a new origin was found.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS The successor was found and 'name' was set.
+ *\li #DNS_R_NEWORIGIN The successor was found with a different
+ * origin and 'name' and 'origin' were set.
+ *\li #ISC_R_NOMORE There was no successor.
+ *\li &lt;something_else> Any error result from dns_name_concatenate.
+ */
+
+isc_result_t
+dns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin);
+/*%<
+ * Decend down if possible.
+ */
+
+isc_result_t
+dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name);
+/*%<
+ * Find the next node at the current depth in DNSSEC order.
+ */
+
+/*
+ * Wrapper macros for manipulating the rbtnode reference counter:
+ * Since we selectively use isc_refcount_t for the reference counter of
+ * a rbtnode, operations on the counter depend on the actual type of it.
+ * The following macros provide a common interface to these operations,
+ * hiding the back-end. The usage is the same as that of isc_refcount_xxx().
+ */
+#ifdef DNS_RBT_USEISCREFCOUNT
+#define dns_rbtnode_refinit(node, n) \
+ do { \
+ isc_refcount_init(&(node)->references, (n)); \
+ } while (0)
+#define dns_rbtnode_refdestroy(node) \
+ do { \
+ isc_refcount_destroy(&(node)->references); \
+ } while (0)
+#define dns_rbtnode_refcurrent(node) \
+ isc_refcount_current(&(node)->references)
+#define dns_rbtnode_refincrement0(node, refs) \
+ do { \
+ isc_refcount_increment0(&(node)->references, (refs)); \
+ } while (0)
+#define dns_rbtnode_refincrement(node, refs) \
+ do { \
+ isc_refcount_increment(&(node)->references, (refs)); \
+ } while (0)
+#define dns_rbtnode_refdecrement(node, refs) \
+ do { \
+ isc_refcount_decrement(&(node)->references, (refs)); \
+ } 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_refcurrent(node) ((node)->references)
+#define dns_rbtnode_refincrement0(node, refs) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(refs); \
+ (node)->references++; \
+ if ((_tmp) != NULL) \
+ (*_tmp) = (node)->references; \
+ } while (0)
+#define dns_rbtnode_refincrement(node, refs) \
+ do { \
+ REQUIRE((node)->references > 0); \
+ (node)->references++; \
+ if ((refs) != NULL) \
+ (*refs) = (node)->references; \
+ } while (0)
+#define dns_rbtnode_refdecrement(node, refs) \
+ do { \
+ REQUIRE((node)->references > 0); \
+ (node)->references--; \
+ if ((refs) != NULL) \
+ (*refs) = (node)->references; \
+ } while (0)
+#endif /* DNS_RBT_USEISCREFCOUNT */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RBT_H */
diff --git a/lib/dns/include/dns/rcode.h b/lib/dns/include/dns/rcode.h
new file mode 100644
index 0000000..94e831b
--- /dev/null
+++ b/lib/dns/include/dns/rcode.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rcode.h,v 1.21 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef DNS_RCODE_H
+#define DNS_RCODE_H 1
+
+/*! \file dns/rcode.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t dns_rcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source);
+/*%<
+ * Convert the text 'source' refers to into a DNS error value.
+ *
+ * Requires:
+ *\li 'rcodep' is a valid pointer.
+ *
+ *\li 'source' is a valid text region.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #DNS_R_UNKNOWN type is unknown
+ */
+
+isc_result_t dns_rcode_totext(dns_rcode_t rcode, isc_buffer_t *target);
+/*%<
+ * Put a textual representation of error 'rcode' into 'target'.
+ *
+ * Requires:
+ *\li 'rcode' is a valid rcode.
+ *
+ *\li 'target' is a valid text buffer.
+ *
+ * Ensures:
+ *\li If the result is success:
+ * The used space in 'target' is updated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #ISC_R_NOSPACE target buffer is too small
+ */
+
+isc_result_t dns_tsigrcode_fromtext(dns_rcode_t *rcodep,
+ isc_textregion_t *source);
+/*%<
+ * Convert the text 'source' refers to into a TSIG/TKEY error value.
+ *
+ * Requires:
+ *\li 'rcodep' is a valid pointer.
+ *
+ *\li 'source' is a valid text region.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #DNS_R_UNKNOWN type is unknown
+ */
+
+isc_result_t dns_tsigrcode_totext(dns_rcode_t rcode, isc_buffer_t *target);
+/*%<
+ * Put a textual representation of TSIG/TKEY error 'rcode' into 'target'.
+ *
+ * Requires:
+ *\li 'rcode' is a valid TSIG/TKEY error code.
+ *
+ *\li 'target' is a valid text buffer.
+ *
+ * Ensures:
+ *\li If the result is success:
+ * The used space in 'target' is updated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #ISC_R_NOSPACE target buffer is too small
+ */
+
+isc_result_t
+dns_hashalg_fromtext(unsigned char *hashalg, isc_textregion_t *source);
+/*%<
+ * Convert the text 'source' refers to into a has algorithm value.
+ *
+ * Requires:
+ *\li 'hashalg' is a valid pointer.
+ *
+ *\li 'source' is a valid text region.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #DNS_R_UNKNOWN type is unknown
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RCODE_H */
diff --git a/lib/dns/include/dns/rdata.h b/lib/dns/include/dns/rdata.h
new file mode 100644
index 0000000..6ea1850
--- /dev/null
+++ b/lib/dns/include/dns/rdata.h
@@ -0,0 +1,702 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: rdata.h,v 1.70 2008/04/02 02:37:42 marka Exp $ */
+
+#ifndef DNS_RDATA_H
+#define DNS_RDATA_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/rdata.h
+ * \brief
+ * Provides facilities for manipulating DNS rdata, including conversions to
+ * and from wire format and text format.
+ *
+ * Given the large amount of rdata possible in a nameserver, it was important
+ * to come up with a very efficient way of storing rdata, but at the same
+ * time allow it to be manipulated.
+ *
+ * The decision was to store rdata in uncompressed wire format,
+ * and not to make it a fully abstracted object; i.e. certain parts of the
+ * server know rdata is stored that way. This saves a lot of memory, and
+ * makes adding rdata to messages easy. Having much of the server know
+ * the representation would be perilous, and we certainly don't want each
+ * user of rdata to be manipulating such a low-level structure. This is
+ * where the rdata module comes in. The module allows rdata handles to be
+ * created and attached to uncompressed wire format regions. All rdata
+ * operations and conversions are done through these handles.
+ *
+ * Implementation Notes:
+ *
+ *\li The routines in this module are expected to be synthesized by the
+ * build process from a set of source files, one per rdata type. For
+ * portability, it's probably best that the building be done by a C
+ * program. Adding a new rdata type will be a simple matter of adding
+ * a file to a directory and rebuilding the server. *All* knowlege of
+ * the format of a particular rdata type is in this file.
+ *
+ * MP:
+ *\li Clients of this module must impose any required synchronization.
+ *
+ * Reliability:
+ *\li This module deals with low-level byte streams. Errors in any of
+ * the functions are likely to crash the server or corrupt memory.
+ *
+ *\li Rdata is typed, and the caller must know what type of rdata it has.
+ * A caller that gets this wrong could crash the server.
+ *
+ *\li The fromstruct() and tostruct() routines use a void * pointer to
+ * represent the structure. The caller must ensure that it passes a
+ * pointer to the appropriate type, or the server could crash or memory
+ * could be corrupted.
+ *
+ * Resources:
+ *\li None.
+ *
+ * Security:
+ *
+ *\li *** WARNING ***
+ * dns_rdata_fromwire() deals with raw network data. An error in
+ * this routine could result in the failure or hijacking of the server.
+ *
+ * Standards:
+ *\li RFC1035
+ *\li Draft EDNS0 (0)
+ *\li Draft EDNS1 (0)
+ *\li Draft Binary Labels (2)
+ *\li Draft Local Compression (1)
+ *\li Various RFCs for particular types; these will be documented in the
+ * sources files of the types.
+ *
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+#include <dns/name.h>
+
+ISC_LANG_BEGINDECLS
+
+
+/***
+ *** Types
+ ***/
+
+/*%
+ ***** An 'rdata' is a handle to a binary region. The handle has an RR
+ ***** class and type, and the data in the binary region is in the format
+ ***** of the given class and type.
+ *****/
+/*%
+ * Clients are strongly discouraged from using this type directly, with
+ * the exception of the 'link' field which may be used directly for whatever
+ * purpose the client desires.
+ */
+struct dns_rdata {
+ unsigned char * data;
+ unsigned int length;
+ dns_rdataclass_t rdclass;
+ dns_rdatatype_t type;
+ unsigned int flags;
+ ISC_LINK(dns_rdata_t) link;
+};
+
+#define DNS_RDATA_INIT { NULL, 0, 0, 0, 0, {(void*)(-1), (void *)(-1)}}
+
+#define DNS_RDATA_UPDATE 0x0001 /*%< update pseudo record. */
+#define DNS_RDATA_OFFLINE 0x0002 /*%< RRSIG has a offline key. */
+
+/*
+ * Flags affecting rdata formatting style. Flags 0xFFFF0000
+ * are used by masterfile-level formatting and defined elsewhere.
+ * See additional comments at dns_rdata_tofmttext().
+ */
+
+/*% Split the rdata into multiple lines to try to keep it
+ within the "width". */
+#define DNS_STYLEFLAG_MULTILINE 0x00000001U
+
+/*% Output explanatory comments. */
+#define DNS_STYLEFLAG_COMMENT 0x00000002U
+
+#define DNS_RDATA_DOWNCASE DNS_NAME_DOWNCASE
+#define DNS_RDATA_CHECKNAMES DNS_NAME_CHECKNAMES
+#define DNS_RDATA_CHECKNAMESFAIL DNS_NAME_CHECKNAMESFAIL
+#define DNS_RDATA_CHECKREVERSE DNS_NAME_CHECKREVERSE
+#define DNS_RDATA_CHECKMX DNS_NAME_CHECKMX
+#define DNS_RDATA_CHECKMXFAIL DNS_NAME_CHECKMXFAIL
+
+/***
+ *** Initialization
+ ***/
+
+void
+dns_rdata_init(dns_rdata_t *rdata);
+/*%<
+ * Make 'rdata' empty.
+ *
+ * Requires:
+ * 'rdata' is a valid rdata (i.e. not NULL, points to a struct dns_rdata)
+ */
+
+void
+dns_rdata_reset(dns_rdata_t *rdata);
+/*%<
+ * Make 'rdata' empty.
+ *
+ * Requires:
+ *\li 'rdata' is a previously initialized rdata and is not linked.
+ */
+
+void
+dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target);
+/*%<
+ * Clone 'target' from 'src'.
+ *
+ * Requires:
+ *\li 'src' to be initialized.
+ *\li 'target' to be initialized.
+ */
+
+/***
+ *** Comparisons
+ ***/
+
+int
+dns_rdata_compare(const dns_rdata_t *rdata1, const dns_rdata_t *rdata2);
+/*%<
+ * Determine the relative ordering under the DNSSEC order relation of
+ * 'rdata1' and 'rdata2'.
+ *
+ * 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
+ ***/
+
+void
+dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, isc_region_t *r);
+/*%<
+ * Make 'rdata' refer to region 'r'.
+ *
+ * Requires:
+ *
+ *\li The data in 'r' is properly formatted for whatever type it is.
+ */
+
+void
+dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r);
+/*%<
+ * Make 'r' refer to 'rdata'.
+ */
+
+isc_result_t
+dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, isc_buffer_t *source,
+ dns_decompress_t *dctx, unsigned int options,
+ isc_buffer_t *target);
+/*%<
+ * Copy the possibly-compressed rdata at source into the target region.
+ *
+ * Notes:
+ *\li Name decompression policy is controlled by 'dctx'.
+ *
+ * 'options'
+ *\li DNS_RDATA_DOWNCASE downcase domain names when they are copied
+ * into target.
+ *
+ * Requires:
+ *
+ *\li 'rdclass' and 'type' are valid.
+ *
+ *\li 'source' is a valid buffer, and the active region of 'source'
+ * references the rdata to be processed.
+ *
+ *\li 'target' is a valid buffer.
+ *
+ *\li 'dctx' is a valid decompression context.
+ *
+ * Ensures,
+ * if result is success:
+ * \li If 'rdata' is not NULL, it is attached to the target.
+ * \li The conditions dns_name_fromwire() ensures for names hold
+ * for all names in the rdata.
+ * \li The current location in source is advanced, and the used space
+ * in target is updated.
+ *
+ * Result:
+ *\li Success
+ *\li Any non-success status from dns_name_fromwire()
+ *\li Various 'Bad Form' class failures depending on class and type
+ *\li Bad Form: Input too short
+ *\li Resource Limit: Not enough space
+ */
+
+isc_result_t
+dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
+ isc_buffer_t *target);
+/*%<
+ * Convert 'rdata' into wire format, compressing it as specified by the
+ * compression context 'cctx', and storing the result in 'target'.
+ *
+ * Notes:
+ *\li If the compression context allows global compression, then the
+ * global compression table may be updated.
+ *
+ * Requires:
+ *\li 'rdata' is a valid, non-empty rdata
+ *
+ *\li target is a valid buffer
+ *
+ *\li Any offsets specified in a global compression table are valid
+ * for target.
+ *
+ * Ensures,
+ * if the result is success:
+ * \li The used space in target is updated.
+ *
+ * Returns:
+ *\li Success
+ *\li Any non-success status from dns_name_towire()
+ *\li Resource Limit: Not enough space
+ */
+
+isc_result_t
+dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, isc_lex_t *lexer, dns_name_t *origin,
+ unsigned int options, isc_mem_t *mctx,
+ isc_buffer_t *target, dns_rdatacallbacks_t *callbacks);
+/*%<
+ * Convert the textual representation of a DNS rdata into uncompressed wire
+ * form stored in the target region. Tokens constituting the text of the rdata
+ * are taken from 'lexer'.
+ *
+ * Notes:
+ *\li Relative domain names in the rdata will have 'origin' appended to them.
+ * A NULL origin implies "origin == dns_rootname".
+ *
+ *
+ * 'options'
+ *\li DNS_RDATA_DOWNCASE downcase domain names when they are copied
+ * into target.
+ *\li DNS_RDATA_CHECKNAMES perform checknames checks.
+ *\li DNS_RDATA_CHECKNAMESFAIL fail if the checknames check fail. If
+ * not set a warning will be issued.
+ *\li DNS_RDATA_CHECKREVERSE this should set if the owner name ends
+ * in IP6.ARPA, IP6.INT or IN-ADDR.ARPA.
+ *
+ * Requires:
+ *
+ *\li 'rdclass' and 'type' are valid.
+ *
+ *\li 'lexer' is a valid isc_lex_t.
+ *
+ *\li 'mctx' is a valid isc_mem_t.
+ *
+ *\li 'target' is a valid region.
+ *
+ *\li 'origin' if non NULL it must be absolute.
+ *
+ *\li 'callbacks' to be NULL or callbacks->warn and callbacks->error be
+ * initialized.
+ *
+ * Ensures,
+ * if result is success:
+ *\li If 'rdata' is not NULL, it is attached to the target.
+
+ *\li The conditions dns_name_fromtext() ensures for names hold
+ * for all names in the rdata.
+
+ *\li The used space in target is updated.
+ *
+ * Result:
+ *\li Success
+ *\li Translated result codes from isc_lex_gettoken
+ *\li Various 'Bad Form' class failures depending on class and type
+ *\li Bad Form: Input too short
+ *\li Resource Limit: Not enough space
+ *\li Resource Limit: Not enough memory
+ */
+
+isc_result_t
+dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target);
+/*%<
+ * Convert 'rdata' into text format, storing the result in 'target'.
+ * The text will consist of a single line, with fields separated by
+ * single spaces.
+ *
+ * Notes:
+ *\li If 'origin' is not NULL, then any names in the rdata that are
+ * subdomains of 'origin' will be made relative it.
+ *
+ *\li XXX Do we *really* want to support 'origin'? I'm inclined towards "no"
+ * at the moment.
+ *
+ * Requires:
+ *
+ *\li 'rdata' is a valid, non-empty rdata
+ *
+ *\li 'origin' is NULL, or is a valid name
+ *
+ *\li 'target' is a valid text buffer
+ *
+ * Ensures,
+ * if the result is success:
+ *
+ * \li The used space in target is updated.
+ *
+ * Returns:
+ *\li Success
+ *\li Any non-success status from dns_name_totext()
+ *\li Resource Limit: Not enough space
+ */
+
+isc_result_t
+dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin, unsigned int flags,
+ unsigned int width, char *linebreak, isc_buffer_t *target);
+/*%<
+ * Like dns_rdata_totext, but do formatted output suitable for
+ * database dumps. This is intended for use by dns_db_dump();
+ * library users are discouraged from calling it directly.
+ *
+ * If (flags & #DNS_STYLEFLAG_MULTILINE) != 0, attempt to stay
+ * within 'width' by breaking the text into multiple lines.
+ * The string 'linebreak' is inserted between lines, and parentheses
+ * are added when necessary. Because RRs contain unbreakable elements
+ * such as domain names whose length is variable, unpredictable, and
+ * potentially large, there is no guarantee that the lines will
+ * not exceed 'width' anyway.
+ *
+ * If (flags & #DNS_STYLEFLAG_MULTILINE) == 0, the rdata is always
+ * printed as a single line, and no parentheses are used.
+ * The 'width' and 'linebreak' arguments are ignored.
+ *
+ * If (flags & #DNS_STYLEFLAG_COMMENT) != 0, output explanatory
+ * comments next to things like the SOA timer fields. Some
+ * comments (e.g., the SOA ones) are only printed when multiline
+ * output is selected.
+ */
+
+isc_result_t
+dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, void *source, isc_buffer_t *target);
+/*%<
+ * Convert the C structure representation of an rdata into uncompressed wire
+ * format in 'target'.
+ *
+ * XXX Should we have a 'size' parameter as a sanity check on target?
+ *
+ * Requires:
+ *
+ *\li 'rdclass' and 'type' are valid.
+ *
+ *\li 'source' points to a valid C struct for the class and type.
+ *
+ *\li 'target' is a valid buffer.
+ *
+ *\li All structure pointers to memory blocks should be NULL if their
+ * corresponding length values are zero.
+ *
+ * Ensures,
+ * if result is success:
+ * \li If 'rdata' is not NULL, it is attached to the target.
+ *
+ * \li The used space in 'target' is updated.
+ *
+ * Result:
+ *\li Success
+ *\li Various 'Bad Form' class failures depending on class and type
+ *\li Resource Limit: Not enough space
+ */
+
+isc_result_t
+dns_rdata_tostruct(dns_rdata_t *rdata, void *target, isc_mem_t *mctx);
+/*%<
+ * Convert an rdata into its C structure representation.
+ *
+ * If 'mctx' is NULL then 'rdata' must persist while 'target' is being used.
+ *
+ * If 'mctx' is non NULL then memory will be allocated if required.
+ *
+ * Requires:
+ *
+ *\li 'rdata' is a valid, non-empty rdata.
+ *
+ *\li 'target' to point to a valid pointer for the type and class.
+ *
+ * Result:
+ *\li Success
+ *\li Resource Limit: Not enough memory
+ */
+
+void
+dns_rdata_freestruct(void *source);
+/*%<
+ * Free dynamic memory attached to 'source' (if any).
+ *
+ * Requires:
+ *
+ *\li 'source' to point to the structure previously filled in by
+ * dns_rdata_tostruct().
+ */
+
+isc_boolean_t
+dns_rdatatype_ismeta(dns_rdatatype_t type);
+/*%<
+ * Return true iff the rdata type 'type' is a meta-type
+ * like ANY or AXFR.
+ */
+
+isc_boolean_t
+dns_rdatatype_issingleton(dns_rdatatype_t type);
+/*%<
+ * Return true iff the rdata type 'type' is a singleton type,
+ * like CNAME or SOA.
+ *
+ * Requires:
+ * \li 'type' is a valid rdata type.
+ *
+ */
+
+isc_boolean_t
+dns_rdataclass_ismeta(dns_rdataclass_t rdclass);
+/*%<
+ * Return true iff the rdata class 'rdclass' is a meta-class
+ * like ANY or NONE.
+ */
+
+isc_boolean_t
+dns_rdatatype_isdnssec(dns_rdatatype_t type);
+/*%<
+ * Return true iff 'type' is one of the DNSSEC
+ * rdata types that may exist alongside a CNAME record.
+ *
+ * Requires:
+ * \li 'type' is a valid rdata type.
+ */
+
+isc_boolean_t
+dns_rdatatype_iszonecutauth(dns_rdatatype_t type);
+/*%<
+ * Return true iff rdata of type 'type' is considered authoritative
+ * data (not glue) in the NSEC chain when it occurs in the parent zone
+ * at a zone cut.
+ *
+ * Requires:
+ * \li 'type' is a valid rdata type.
+ *
+ */
+
+isc_boolean_t
+dns_rdatatype_isknown(dns_rdatatype_t type);
+/*%<
+ * Return true iff the rdata type 'type' is known.
+ *
+ * Requires:
+ * \li 'type' is a valid rdata type.
+ *
+ */
+
+
+isc_result_t
+dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add,
+ void *arg);
+/*%<
+ * Call 'add' for each name and type from 'rdata' which is subject to
+ * additional section processing.
+ *
+ * Requires:
+ *
+ *\li 'rdata' is a valid, non-empty rdata.
+ *
+ *\li 'add' is a valid dns_additionalfunc_t.
+ *
+ * Ensures:
+ *
+ *\li If successful, then add() will have been called for each name
+ * and type subject to additional section processing.
+ *
+ *\li If add() returns something other than #ISC_R_SUCCESS, that result
+ * will be returned as the result of dns_rdata_additionaldata().
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *
+ *\li Many other results are possible if not successful.
+ */
+
+isc_result_t
+dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg);
+/*%<
+ * Send 'rdata' in DNSSEC canonical form to 'digest'.
+ *
+ * Note:
+ *\li 'digest' may be called more than once by dns_rdata_digest(). The
+ * concatenation of all the regions, in the order they were given
+ * to 'digest', will be the DNSSEC canonical form of 'rdata'.
+ *
+ * Requires:
+ *
+ *\li 'rdata' is a valid, non-empty rdata.
+ *
+ *\li 'digest' is a valid dns_digestfunc_t.
+ *
+ * Ensures:
+ *
+ *\li If successful, then all of the rdata's data has been sent, in
+ * DNSSEC canonical form, to 'digest'.
+ *
+ *\li If digest() returns something other than ISC_R_SUCCESS, that result
+ * will be returned as the result of dns_rdata_digest().
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *
+ *\li Many other results are possible if not successful.
+ */
+
+isc_boolean_t
+dns_rdatatype_questiononly(dns_rdatatype_t type);
+/*%<
+ * Return true iff rdata of type 'type' can only appear in the question
+ * section of a properly formatted message.
+ *
+ * Requires:
+ * \li 'type' is a valid rdata type.
+ *
+ */
+
+isc_boolean_t
+dns_rdatatype_notquestion(dns_rdatatype_t type);
+/*%<
+ * Return true iff rdata of type 'type' can not appear in the question
+ * section of a properly formatted message.
+ *
+ * Requires:
+ * \li 'type' is a valid rdata type.
+ *
+ */
+
+isc_boolean_t
+dns_rdatatype_atparent(dns_rdatatype_t type);
+/*%<
+ * Return true iff rdata of type 'type' should appear at the parent of
+ * a zone cut.
+ *
+ * Requires:
+ * \li 'type' is a valid rdata type.
+ *
+ */
+
+unsigned int
+dns_rdatatype_attributes(dns_rdatatype_t rdtype);
+/*%<
+ * Return attributes for the given type.
+ *
+ * Requires:
+ *\li 'rdtype' are known.
+ *
+ * Returns:
+ *\li a bitmask consisting of the following flags.
+ */
+
+/*% only one may exist for a name */
+#define DNS_RDATATYPEATTR_SINGLETON 0x00000001U
+/*% requires no other data be present */
+#define DNS_RDATATYPEATTR_EXCLUSIVE 0x00000002U
+/*% Is a meta type */
+#define DNS_RDATATYPEATTR_META 0x00000004U
+/*% Is a DNSSEC type, like RRSIG or NSEC */
+#define DNS_RDATATYPEATTR_DNSSEC 0x00000008U
+/*% Is a zone cut authority type */
+#define DNS_RDATATYPEATTR_ZONECUTAUTH 0x00000010U
+/*% Is reserved (unusable) */
+#define DNS_RDATATYPEATTR_RESERVED 0x00000020U
+/*% Is an unknown type */
+#define DNS_RDATATYPEATTR_UNKNOWN 0x00000040U
+/*% Is META, and can only be in a question section */
+#define DNS_RDATATYPEATTR_QUESTIONONLY 0x00000080U
+/*% is META, and can NOT be in a question section */
+#define DNS_RDATATYPEATTR_NOTQUESTION 0x00000100U
+/*% Is present at zone cuts in the parent, not the child */
+#define DNS_RDATATYPEATTR_ATPARENT 0x00000200U
+
+dns_rdatatype_t
+dns_rdata_covers(dns_rdata_t *rdata);
+/*%<
+ * Return the rdatatype that this type covers.
+ *
+ * Requires:
+ *\li 'rdata' is a valid, non-empty rdata.
+ *
+ *\li 'rdata' is a type that covers other rdata types.
+ *
+ * Returns:
+ *\li The type covered.
+ */
+
+isc_boolean_t
+dns_rdata_checkowner(dns_name_t* name, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, isc_boolean_t wildcard);
+/*
+ * Returns whether this is a valid ownername for this <type,class>.
+ * If wildcard is true allow the first label to be a wildcard if
+ * appropriate.
+ *
+ * Requires:
+ * 'name' is a valid name.
+ */
+
+isc_boolean_t
+dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad);
+/*
+ * Returns whether 'rdata' contains valid domain names. The checks are
+ * sensitive to the owner name.
+ *
+ * If 'bad' is non-NULL and a domain name fails the check the
+ * the offending name will be return in 'bad' by cloning from
+ * the 'rdata' contents.
+ *
+ * Requires:
+ * 'rdata' to be valid.
+ * 'owner' to be valid.
+ * 'bad' to be NULL or valid.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RDATA_H */
diff --git a/lib/dns/include/dns/rdataclass.h b/lib/dns/include/dns/rdataclass.h
new file mode 100644
index 0000000..786eb6a
--- /dev/null
+++ b/lib/dns/include/dns/rdataclass.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: rdataclass.h,v 1.24 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_RDATACLASS_H
+#define DNS_RDATACLASS_H 1
+
+/*! \file dns/rdataclass.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source);
+/*%<
+ * Convert the text 'source' refers to into a DNS class.
+ *
+ * Requires:
+ *\li 'classp' is a valid pointer.
+ *
+ *\li 'source' is a valid text region.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #DNS_R_UNKNOWN class is unknown
+ */
+
+isc_result_t
+dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target);
+/*%<
+ * Put a textual representation of class 'rdclass' into 'target'.
+ *
+ * Requires:
+ *\li 'rdclass' is a valid class.
+ *
+ *\li 'target' is a valid text buffer.
+ *
+ * Ensures,
+ * if the result is success:
+ *\li The used space in 'target' is updated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #ISC_R_NOSPACE target buffer is too small
+ */
+
+void
+dns_rdataclass_format(dns_rdataclass_t rdclass,
+ char *array, unsigned int size);
+/*%<
+ * Format a human-readable representation of the class 'rdclass'
+ * into the character array 'array', which is of size 'size'.
+ * The resulting string is guaranteed to be null-terminated.
+ */
+
+#define DNS_RDATACLASS_FORMATSIZE sizeof("CLASS65535")
+/*%<
+ * Minimum size of array to pass to dns_rdataclass_format().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RDATACLASS_H */
diff --git a/lib/dns/include/dns/rdatalist.h b/lib/dns/include/dns/rdatalist.h
new file mode 100644
index 0000000..57debc3
--- /dev/null
+++ b/lib/dns/include/dns/rdatalist.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rdatalist.h,v 1.22 2008/04/03 06:09:05 tbox Exp $ */
+
+#ifndef DNS_RDATALIST_H
+#define DNS_RDATALIST_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/rdatalist.h
+ * \brief
+ * A DNS rdatalist is a list of rdata of a common type and class.
+ *
+ * MP:
+ *\li Clients of this module must impose any required synchronization.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li None.
+ */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+/*%
+ * Clients may use this type directly.
+ */
+struct dns_rdatalist {
+ dns_rdataclass_t rdclass;
+ dns_rdatatype_t type;
+ dns_rdatatype_t covers;
+ dns_ttl_t ttl;
+ ISC_LIST(dns_rdata_t) rdata;
+ ISC_LINK(dns_rdatalist_t) link;
+};
+
+ISC_LANG_BEGINDECLS
+
+void
+dns_rdatalist_init(dns_rdatalist_t *rdatalist);
+/*%<
+ * Initialize rdatalist.
+ *
+ * Ensures:
+ *\li All fields of rdatalist have been initialized to their default
+ * values.
+ */
+
+isc_result_t
+dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
+ dns_rdataset_t *rdataset);
+/*%<
+ * Make 'rdataset' refer to the rdata in 'rdatalist'.
+ *
+ * Note:
+ *\li The caller must ensure that 'rdatalist' remains valid and unchanged
+ * while 'rdataset' is associated with it.
+ *
+ * Requires:
+ *
+ *\li 'rdatalist' is a valid rdatalist.
+ *
+ *\li 'rdataset' is a valid rdataset that is not currently associated with
+ * any rdata.
+ *
+ * Ensures,
+ * on success,
+ *
+ *\li 'rdataset' is associated with the rdata in rdatalist.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ */
+
+isc_result_t
+dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
+ dns_rdatalist_t **rdatalist);
+/*%<
+ * Point 'rdatalist' to the rdatalist in 'rdataset'.
+ *
+ * Requires:
+ *
+ *\li 'rdatalist' is a pointer to a NULL dns_rdatalist_t pointer.
+ *
+ *\li 'rdataset' is a valid rdataset associated with an rdatalist.
+ *
+ * Ensures,
+ * on success,
+ *
+ *\li 'rdatalist' is pointed to the rdatalist in rdataset.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RDATALIST_H */
diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h
new file mode 100644
index 0000000..bfb6cd4
--- /dev/null
+++ b/lib/dns/include/dns/rdataset.h
@@ -0,0 +1,639 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: rdataset.h,v 1.65 2008/09/24 02:46:23 marka Exp $ */
+
+#ifndef DNS_RDATASET_H
+#define DNS_RDATASET_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/rdataset.h
+ * \brief
+ * A DNS rdataset is a handle that can be associated with a collection of
+ * rdata all having a common owner name, class, and type.
+ *
+ * The dns_rdataset_t type is like a "virtual class". To actually use
+ * rdatasets, an implementation of the method suite (e.g. "slabbed rdata") is
+ * required.
+ *
+ * XXX &lt;more&gt; XXX
+ *
+ * MP:
+ *\li Clients of this module must impose any required synchronization.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li None.
+ */
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/stdtime.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef enum {
+ dns_rdatasetadditional_fromauth,
+ dns_rdatasetadditional_fromcache,
+ dns_rdatasetadditional_fromglue
+} dns_rdatasetadditional_t;
+
+typedef struct dns_rdatasetmethods {
+ void (*disassociate)(dns_rdataset_t *rdataset);
+ isc_result_t (*first)(dns_rdataset_t *rdataset);
+ isc_result_t (*next)(dns_rdataset_t *rdataset);
+ void (*current)(dns_rdataset_t *rdataset,
+ dns_rdata_t *rdata);
+ void (*clone)(dns_rdataset_t *source,
+ dns_rdataset_t *target);
+ unsigned int (*count)(dns_rdataset_t *rdataset);
+ isc_result_t (*addnoqname)(dns_rdataset_t *rdataset,
+ dns_name_t *name);
+ isc_result_t (*getnoqname)(dns_rdataset_t *rdataset,
+ dns_name_t *name,
+ dns_rdataset_t *neg,
+ dns_rdataset_t *negsig);
+ isc_result_t (*addclosest)(dns_rdataset_t *rdataset,
+ dns_name_t *name);
+ isc_result_t (*getclosest)(dns_rdataset_t *rdataset,
+ dns_name_t *name,
+ dns_rdataset_t *neg,
+ dns_rdataset_t *negsig);
+ isc_result_t (*getadditional)(dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype,
+ dns_acache_t *acache,
+ dns_zone_t **zonep,
+ dns_db_t **dbp,
+ dns_dbversion_t **versionp,
+ dns_dbnode_t **nodep,
+ dns_name_t *fname,
+ dns_message_t *msg,
+ isc_stdtime_t now);
+ isc_result_t (*setadditional)(dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype,
+ dns_acache_t *acache,
+ dns_zone_t *zone,
+ dns_db_t *db,
+ dns_dbversion_t *version,
+ dns_dbnode_t *node,
+ dns_name_t *fname);
+ isc_result_t (*putadditional)(dns_acache_t *acache,
+ dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype);
+} dns_rdatasetmethods_t;
+
+#define DNS_RDATASET_MAGIC ISC_MAGIC('D','N','S','R')
+#define DNS_RDATASET_VALID(set) ISC_MAGIC_VALID(set, DNS_RDATASET_MAGIC)
+
+/*%
+ * Direct use of this structure by clients is strongly discouraged, except
+ * for the 'link' field which may be used however the client wishes. The
+ * 'private', 'current', and 'index' fields MUST NOT be changed by clients.
+ * rdataset implementations may change any of the fields.
+ */
+struct dns_rdataset {
+ unsigned int magic; /* XXX ? */
+ dns_rdatasetmethods_t * methods;
+ ISC_LINK(dns_rdataset_t) link;
+ /*
+ * XXX do we need these, or should they be retrieved by methods?
+ * Leaning towards the latter, since they are not frequently required
+ * once you have the rdataset.
+ */
+ dns_rdataclass_t rdclass;
+ dns_rdatatype_t type;
+ dns_ttl_t ttl;
+ dns_trust_t trust;
+ dns_rdatatype_t covers;
+ /*
+ * attributes
+ */
+ unsigned int attributes;
+ /*%
+ * the counter provides the starting point in the "cyclic" order.
+ * The value ISC_UINT32_MAX has a special meaning of "picking up a
+ * random value." in order to take care of databases that do not
+ * increment the counter.
+ */
+ isc_uint32_t count;
+ /*
+ * This RRSIG RRset should be re-generated around this time.
+ * Only valid if DNS_RDATASETATTR_RESIGN is set in attributes.
+ */
+ isc_stdtime_t resign;
+ /*@{*/
+ /*%
+ * These are for use by the rdataset implementation, and MUST NOT
+ * be changed by clients.
+ */
+ void * private1;
+ void * private2;
+ void * private3;
+ unsigned int privateuint4;
+ void * private5;
+ void * private6;
+ void * private7;
+ /*@}*/
+
+};
+
+/*!
+ * \def DNS_RDATASETATTR_RENDERED
+ * Used by message.c to indicate that the rdataset was rendered.
+ *
+ * \def DNS_RDATASETATTR_TTLADJUSTED
+ * Used by message.c to indicate that the rdataset's rdata had differing
+ * TTL values, and the rdataset->ttl holds the smallest.
+ *
+ * \def DNS_RDATASETATTR_LOADORDER
+ * Output the RRset in load order.
+ */
+
+#define DNS_RDATASETATTR_QUESTION 0x00000001
+#define DNS_RDATASETATTR_RENDERED 0x00000002 /*%< Used by message.c */
+#define DNS_RDATASETATTR_ANSWERED 0x00000004 /*%< Used by server. */
+#define DNS_RDATASETATTR_CACHE 0x00000008 /*%< Used by resolver. */
+#define DNS_RDATASETATTR_ANSWER 0x00000010 /*%< Used by resolver. */
+#define DNS_RDATASETATTR_ANSWERSIG 0x00000020 /*%< Used by resolver. */
+#define DNS_RDATASETATTR_EXTERNAL 0x00000040 /*%< Used by resolver. */
+#define DNS_RDATASETATTR_NCACHE 0x00000080 /*%< Used by resolver. */
+#define DNS_RDATASETATTR_CHAINING 0x00000100 /*%< Used by resolver. */
+#define DNS_RDATASETATTR_TTLADJUSTED 0x00000200 /*%< Used by message.c */
+#define DNS_RDATASETATTR_FIXEDORDER 0x00000400
+#define DNS_RDATASETATTR_RANDOMIZE 0x00000800
+#define DNS_RDATASETATTR_CHASE 0x00001000 /*%< Used by resolver. */
+#define DNS_RDATASETATTR_NXDOMAIN 0x00002000
+#define DNS_RDATASETATTR_NOQNAME 0x00004000
+#define DNS_RDATASETATTR_CHECKNAMES 0x00008000 /*%< Used by resolver. */
+#define DNS_RDATASETATTR_REQUIREDGLUE 0x00010000
+#define DNS_RDATASETATTR_LOADORDER 0x00020000
+#define DNS_RDATASETATTR_RESIGN 0x00040000
+#define DNS_RDATASETATTR_CLOSEST 0x00080000
+#define DNS_RDATASETATTR_OPTOUT 0x00100000 /*%< OPTOUT proof */
+
+/*%
+ * _OMITDNSSEC:
+ * Omit DNSSEC records when rendering ncache records.
+ */
+#define DNS_RDATASETTOWIRE_OMITDNSSEC 0x0001
+
+void
+dns_rdataset_init(dns_rdataset_t *rdataset);
+/*%<
+ * Make 'rdataset' a valid, disassociated rdataset.
+ *
+ * Requires:
+ *\li 'rdataset' is not NULL.
+ *
+ * Ensures:
+ *\li 'rdataset' is a valid, disassociated rdataset.
+ */
+
+void
+dns_rdataset_invalidate(dns_rdataset_t *rdataset);
+/*%<
+ * Invalidate 'rdataset'.
+ *
+ * Requires:
+ *\li 'rdataset' is a valid, disassociated rdataset.
+ *
+ * Ensures:
+ *\li If assertion checking is enabled, future attempts to use 'rdataset'
+ * without initializing it will cause an assertion failure.
+ */
+
+void
+dns_rdataset_disassociate(dns_rdataset_t *rdataset);
+/*%<
+ * Disassociate 'rdataset' from its rdata, allowing it to be reused.
+ *
+ * Notes:
+ *\li The client must ensure it has no references to rdata in the rdataset
+ * before disassociating.
+ *
+ * Requires:
+ *\li 'rdataset' is a valid, associated rdataset.
+ *
+ * Ensures:
+ *\li 'rdataset' is a valid, disassociated rdataset.
+ */
+
+isc_boolean_t
+dns_rdataset_isassociated(dns_rdataset_t *rdataset);
+/*%<
+ * Is 'rdataset' associated?
+ *
+ * Requires:
+ *\li 'rdataset' is a valid rdataset.
+ *
+ * Returns:
+ *\li #ISC_TRUE 'rdataset' is associated.
+ *\li #ISC_FALSE 'rdataset' is not associated.
+ */
+
+void
+dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type);
+/*%<
+ * Make 'rdataset' a valid, associated, question rdataset, with a
+ * question class of 'rdclass' and type 'type'.
+ *
+ * Notes:
+ *\li Question rdatasets have a class and type, but no rdata.
+ *
+ * Requires:
+ *\li 'rdataset' is a valid, disassociated rdataset.
+ *
+ * Ensures:
+ *\li 'rdataset' is a valid, associated, question rdataset.
+ */
+
+void
+dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
+/*%<
+ * Make 'target' refer to the same rdataset as 'source'.
+ *
+ * Requires:
+ *\li 'source' is a valid, associated rdataset.
+ *
+ *\li 'target' is a valid, dissociated rdataset.
+ *
+ * Ensures:
+ *\li 'target' references the same rdataset as 'source'.
+ */
+
+unsigned int
+dns_rdataset_count(dns_rdataset_t *rdataset);
+/*%<
+ * Return the number of records in 'rdataset'.
+ *
+ * Requires:
+ *\li 'rdataset' is a valid, associated rdataset.
+ *
+ * Returns:
+ *\li The number of records in 'rdataset'.
+ */
+
+isc_result_t
+dns_rdataset_first(dns_rdataset_t *rdataset);
+/*%<
+ * Move the rdata cursor to the first rdata in the rdataset (if any).
+ *
+ * Requires:
+ *\li 'rdataset' is a valid, associated rdataset.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMORE There are no rdata in the set.
+ */
+
+isc_result_t
+dns_rdataset_next(dns_rdataset_t *rdataset);
+/*%<
+ * Move the rdata cursor to the next rdata in the rdataset (if any).
+ *
+ * Requires:
+ *\li 'rdataset' is a valid, associated rdataset.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMORE There are no more rdata in the set.
+ */
+
+void
+dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
+/*%<
+ * Make 'rdata' refer to the current rdata.
+ *
+ * Notes:
+ *
+ *\li The data returned in 'rdata' is valid for the life of the
+ * rdataset; in particular, subsequent changes in the cursor position
+ * do not invalidate 'rdata'.
+ *
+ * Requires:
+ *\li 'rdataset' is a valid, associated rdataset.
+ *
+ *\li The rdata cursor of 'rdataset' is at a valid location (i.e. the
+ * result of last call to a cursor movement command was ISC_R_SUCCESS).
+ *
+ * Ensures:
+ *\li 'rdata' refers to the rdata at the rdata cursor location of
+ *\li 'rdataset'.
+ */
+
+isc_result_t
+dns_rdataset_totext(dns_rdataset_t *rdataset,
+ dns_name_t *owner_name,
+ isc_boolean_t omit_final_dot,
+ isc_boolean_t question,
+ isc_buffer_t *target);
+/*%<
+ * Convert 'rdataset' to text format, storing the result in 'target'.
+ *
+ * Notes:
+ *\li The rdata cursor position will be changed.
+ *
+ *\li The 'question' flag should normally be #ISC_FALSE. If it is
+ * #ISC_TRUE, the TTL and rdata fields are not printed. This is
+ * for use when printing an rdata representing a question section.
+ *
+ *\li This interface is deprecated; use dns_master_rdatasettottext()
+ * and/or dns_master_questiontotext() instead.
+ *
+ * Requires:
+ *\li 'rdataset' is a valid rdataset.
+ *
+ *\li 'rdataset' is not empty.
+ */
+
+isc_result_t
+dns_rdataset_towire(dns_rdataset_t *rdataset,
+ dns_name_t *owner_name,
+ dns_compress_t *cctx,
+ isc_buffer_t *target,
+ unsigned int options,
+ unsigned int *countp);
+/*%<
+ * Convert 'rdataset' to wire format, compressing names as specified
+ * in 'cctx', and storing the result in 'target'.
+ *
+ * Notes:
+ *\li The rdata cursor position will be changed.
+ *
+ *\li The number of RRs added to target will be added to *countp.
+ *
+ * Requires:
+ *\li 'rdataset' is a valid rdataset.
+ *
+ *\li 'rdataset' is not empty.
+ *
+ *\li 'countp' is a valid pointer.
+ *
+ * Ensures:
+ *\li On a return of ISC_R_SUCCESS, 'target' contains a wire format
+ * for the data contained in 'rdataset'. Any error return leaves
+ * the buffer unchanged.
+ *
+ *\li *countp has been incremented by the number of RRs added to
+ * target.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS - all ok
+ *\li #ISC_R_NOSPACE - 'target' doesn't have enough room
+ *
+ *\li Any error returned by dns_rdata_towire(), dns_rdataset_next(),
+ * dns_name_towire().
+ */
+
+isc_result_t
+dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
+ const dns_name_t *owner_name,
+ dns_compress_t *cctx,
+ isc_buffer_t *target,
+ dns_rdatasetorderfunc_t order,
+ const void *order_arg,
+ unsigned int options,
+ unsigned int *countp);
+/*%<
+ * Like dns_rdataset_towire(), but sorting the rdatasets according to
+ * the integer value returned by 'order' when called witih the rdataset
+ * and 'order_arg' as arguments.
+ *
+ * Requires:
+ *\li All the requirements of dns_rdataset_towire(), and
+ * that order_arg is NULL if and only if order is NULL.
+ */
+
+isc_result_t
+dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
+ const dns_name_t *owner_name,
+ dns_compress_t *cctx,
+ isc_buffer_t *target,
+ dns_rdatasetorderfunc_t order,
+ const void *order_arg,
+ unsigned int options,
+ unsigned int *countp,
+ void **state);
+/*%<
+ * Like dns_rdataset_towiresorted() except that a partial rdataset
+ * may be written.
+ *
+ * Requires:
+ *\li All the requirements of dns_rdataset_towiresorted().
+ * If 'state' is non NULL then the current position in the
+ * rdataset will be remembered if the rdataset in not
+ * completely written and should be passed on on subsequent
+ * calls (NOT CURRENTLY IMPLEMENTED).
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS if all of the records were written.
+ *\li #ISC_R_NOSPACE if unable to fit in all of the records. *countp
+ * will be updated to reflect the number of records
+ * written.
+ */
+
+isc_result_t
+dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
+ dns_additionaldatafunc_t add, void *arg);
+/*%<
+ * For each rdata in rdataset, call 'add' for each name and type in the
+ * rdata which is subject to additional section processing.
+ *
+ * Requires:
+ *
+ *\li 'rdataset' is a valid, non-question rdataset.
+ *
+ *\li 'add' is a valid dns_additionaldatafunc_t
+ *
+ * Ensures:
+ *
+ *\li If successful, dns_rdata_additionaldata() will have been called for
+ * each rdata in 'rdataset'.
+ *
+ *\li If a call to dns_rdata_additionaldata() is not successful, the
+ * result returned will be the result of dns_rdataset_additionaldata().
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *
+ *\li Any error that dns_rdata_additionaldata() can return.
+ */
+
+isc_result_t
+dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *neg, dns_rdataset_t *negsig);
+/*%<
+ * Return the noqname proof for this record.
+ *
+ * Requires:
+ *\li 'rdataset' to be valid and #DNS_RDATASETATTR_NOQNAME to be set.
+ *\li 'name' to be valid.
+ *\li 'neg' and 'negsig' to be valid and not associated.
+ */
+
+isc_result_t
+dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name);
+/*%<
+ * Associate a noqname proof with this record.
+ * Sets #DNS_RDATASETATTR_NOQNAME if successful.
+ * Adjusts the 'rdataset->ttl' to minimum of the 'rdataset->ttl' and
+ * the 'nsec'/'nsec3' and 'rrsig(nsec)'/'rrsig(nsec3)' ttl.
+ *
+ * Requires:
+ *\li 'rdataset' to be valid and #DNS_RDATASETATTR_NOQNAME to be set.
+ *\li 'name' to be valid and have NSEC or NSEC3 and associated RRSIG
+ * rdatasets.
+ */
+
+isc_result_t
+dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *nsec, dns_rdataset_t *nsecsig);
+/*%<
+ * Return the closest encloser for this record.
+ *
+ * Requires:
+ *\li 'rdataset' to be valid and #DNS_RDATASETATTR_CLOSEST to be set.
+ *\li 'name' to be valid.
+ *\li 'nsec' and 'nsecsig' to be valid and not associated.
+ */
+
+isc_result_t
+dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name);
+/*%<
+ * Associate a closest encloset proof with this record.
+ * Sets #DNS_RDATASETATTR_CLOSEST if successful.
+ * Adjusts the 'rdataset->ttl' to minimum of the 'rdataset->ttl' and
+ * the 'nsec' and 'rrsig(nsec)' ttl.
+ *
+ * Requires:
+ *\li 'rdataset' to be valid and #DNS_RDATASETATTR_CLOSEST to be set.
+ *\li 'name' to be valid and have NSEC3 and RRSIG(NSEC3) rdatasets.
+ */
+
+isc_result_t
+dns_rdataset_getadditional(dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype,
+ dns_acache_t *acache,
+ dns_zone_t **zonep,
+ dns_db_t **dbp,
+ dns_dbversion_t **versionp,
+ dns_dbnode_t **nodep,
+ dns_name_t *fname,
+ dns_message_t *msg,
+ isc_stdtime_t now);
+/*%<
+ * Get cached additional information from the DB node for a particular
+ * 'rdataset.' 'type' is one of dns_rdatasetadditional_fromauth,
+ * dns_rdatasetadditional_fromcache, and dns_rdatasetadditional_fromglue,
+ * which specifies the origin of the information. 'qtype' is intended to
+ * be used for specifying a particular rdata type in the cached information.
+ *
+ * Requires:
+ * \li 'rdataset' is a valid rdataset.
+ * \li 'acache' can be NULL, in which case this function will simply return
+ * ISC_R_FAILURE.
+ * \li For the other pointers, see dns_acache_getentry().
+ *
+ * Ensures:
+ * \li See dns_acache_getentry().
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_FAILURE - additional information caching is not supported.
+ * \li #ISC_R_NOTFOUND - the corresponding DB node has not cached additional
+ * information for 'rdataset.'
+ * \li Any error that dns_acache_getentry() can return.
+ */
+
+isc_result_t
+dns_rdataset_setadditional(dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype,
+ dns_acache_t *acache,
+ dns_zone_t *zone,
+ dns_db_t *db,
+ dns_dbversion_t *version,
+ dns_dbnode_t *node,
+ dns_name_t *fname);
+/*%<
+ * Set cached additional information to the DB node for a particular
+ * 'rdataset.' See dns_rdataset_getadditional for the semantics of 'type'
+ * and 'qtype'.
+ *
+ * Requires:
+ * \li 'rdataset' is a valid rdataset.
+ * \li 'acache' can be NULL, in which case this function will simply return
+ * ISC_R_FAILURE.
+ * \li For the other pointers, see dns_acache_setentry().
+ *
+ * Ensures:
+ * \li See dns_acache_setentry().
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_FAILURE - additional information caching is not supported.
+ * \li #ISC_R_NOMEMORY
+ * \li Any error that dns_acache_setentry() can return.
+ */
+
+isc_result_t
+dns_rdataset_putadditional(dns_acache_t *acache,
+ dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype);
+/*%<
+ * Discard cached additional information stored in the DB node for a particular
+ * 'rdataset.' See dns_rdataset_getadditional for the semantics of 'type'
+ * and 'qtype'.
+ *
+ * Requires:
+ * \li 'rdataset' is a valid rdataset.
+ * \li 'acache' can be NULL, in which case this function will simply return
+ * ISC_R_FAILURE.
+ *
+ * Ensures:
+ * \li See dns_acache_cancelentry().
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_FAILURE - additional information caching is not supported.
+ * \li #ISC_R_NOTFOUND - the corresponding DB node has not cached additional
+ * information for 'rdataset.'
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RDATASET_H */
diff --git a/lib/dns/include/dns/rdatasetiter.h b/lib/dns/include/dns/rdatasetiter.h
new file mode 100644
index 0000000..dcde367
--- /dev/null
+++ b/lib/dns/include/dns/rdatasetiter.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rdatasetiter.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_RDATASETITER_H
+#define DNS_RDATASETITER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/rdatasetiter.h
+ * \brief
+ * The DNS Rdataset Iterator interface allows iteration of all of the
+ * rdatasets at a node.
+ *
+ * The dns_rdatasetiter_t type is like a "virtual class". To actually use
+ * it, an implementation of the class is required. This implementation is
+ * supplied by the database.
+ *
+ * It is the client's responsibility to call dns_rdataset_disassociate()
+ * on all rdatasets returned.
+ *
+ * XXX more XXX
+ *
+ * MP:
+ *\li The iterator itself is not locked. The caller must ensure
+ * synchronization.
+ *
+ *\li The iterator methods ensure appropriate database locking.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li None.
+ */
+
+/*****
+ ***** Imports
+ *****/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/stdtime.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Types
+ *****/
+
+typedef struct dns_rdatasetitermethods {
+ void (*destroy)(dns_rdatasetiter_t **iteratorp);
+ isc_result_t (*first)(dns_rdatasetiter_t *iterator);
+ isc_result_t (*next)(dns_rdatasetiter_t *iterator);
+ void (*current)(dns_rdatasetiter_t *iterator,
+ dns_rdataset_t *rdataset);
+} dns_rdatasetitermethods_t;
+
+#define DNS_RDATASETITER_MAGIC ISC_MAGIC('D','N','S','i')
+#define DNS_RDATASETITER_VALID(i) ISC_MAGIC_VALID(i, DNS_RDATASETITER_MAGIC)
+
+/*%
+ * This structure is actually just the common prefix of a DNS db
+ * implementation's version of a dns_rdatasetiter_t.
+ * \brief
+ * Direct use of this structure by clients is forbidden. DB implementations
+ * may change the structure. 'magic' must be #DNS_RDATASETITER_MAGIC for
+ * any of the dns_rdatasetiter routines to work. DB implementations must
+ * maintain all DB rdataset iterator invariants.
+ */
+struct dns_rdatasetiter {
+ /* Unlocked. */
+ unsigned int magic;
+ dns_rdatasetitermethods_t * methods;
+ dns_db_t * db;
+ dns_dbnode_t * node;
+ dns_dbversion_t * version;
+ isc_stdtime_t now;
+};
+
+void
+dns_rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
+/*%<
+ * Destroy '*iteratorp'.
+ *
+ * Requires:
+ *
+ *\li '*iteratorp' is a valid iterator.
+ *
+ * Ensures:
+ *
+ *\li All resources used by the iterator are freed.
+ *
+ *\li *iteratorp == NULL.
+ */
+
+isc_result_t
+dns_rdatasetiter_first(dns_rdatasetiter_t *iterator);
+/*%<
+ * Move the rdataset cursor to the first rdataset at the node (if any).
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOMORE There are no rdatasets at the node.
+ *
+ *\li Other results are possible, depending on the DB implementation.
+ */
+
+isc_result_t
+dns_rdatasetiter_next(dns_rdatasetiter_t *iterator);
+/*%<
+ * Move the rdataset cursor to the next rdataset at the node (if any).
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOMORE There are no more rdatasets at the
+ * node.
+ *
+ *\li Other results are possible, depending on the DB implementation.
+ */
+
+void
+dns_rdatasetiter_current(dns_rdatasetiter_t *iterator,
+ dns_rdataset_t *rdataset);
+/*%<
+ * Return the current rdataset.
+ *
+ * Requires:
+ *\li 'iterator' is a valid iterator.
+ *
+ *\li 'rdataset' is a valid, disassociated rdataset.
+ *
+ *\li The rdataset cursor of 'iterator' is at a valid location (i.e. the
+ * result of last call to a cursor movement command was #ISC_R_SUCCESS).
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RDATASETITER_H */
diff --git a/lib/dns/include/dns/rdataslab.h b/lib/dns/include/dns/rdataslab.h
new file mode 100644
index 0000000..3ac44b8
--- /dev/null
+++ b/lib/dns/include/dns/rdataslab.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: rdataslab.h,v 1.33 2008/04/01 23:47:10 tbox Exp $ */
+
+#ifndef DNS_RDATASLAB_H
+#define DNS_RDATASLAB_H 1
+
+/*! \file dns/rdataslab.h
+ * \brief
+ * Implements storage of rdatasets into slabs of memory.
+ *
+ * MP:
+ *\li Clients of this module must impose any required synchronization.
+ *
+ * Reliability:
+ *\li This module deals with low-level byte streams. Errors in any of
+ * the functions are likely to crash the server or corrupt memory.
+ *
+ *\li If the caller passes invalid memory references, these functions are
+ * likely to crash the server or corrupt memory.
+ *
+ * Resources:
+ *\li None.
+ *
+ * Security:
+ *\li None.
+ *
+ * Standards:
+ *\li None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+#define DNS_RDATASLAB_FORCE 0x1
+#define DNS_RDATASLAB_EXACT 0x2
+
+#define DNS_RDATASLAB_OFFLINE 0x01 /* RRSIG is for offline DNSKEY */
+#define DNS_RDATASLAB_WARNMASK 0x0E /*%< RRSIG(DNSKEY) expired
+ * warnings number mask. */
+#define DNS_RDATASLAB_WARNSHIFT 1 /*%< How many bits to shift to find
+ * remaining expired warning number. */
+
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
+ isc_region_t *region, unsigned int reservelen);
+/*%<
+ * Slabify a rdataset. The slab area will be allocated and returned
+ * in 'region'.
+ *
+ * Requires:
+ *\li 'rdataset' is valid.
+ *
+ * Ensures:
+ *\li 'region' will have base pointing to the start of allocated memory,
+ * with the slabified region beginning at region->base + reservelen.
+ * region->length contains the total length allocated.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS - successful completion
+ *\li ISC_R_NOMEMORY - no memory.
+ *\li XXX others
+ */
+
+void
+dns_rdataslab_tordataset(unsigned char *slab, unsigned int reservelen,
+ dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
+ dns_rdatatype_t covers, dns_ttl_t ttl,
+ dns_rdataset_t *rdataset);
+/*%<
+ * Construct an rdataset from a slab.
+ *
+ * Requires:
+ *\li 'slab' points to a slab.
+ *\li 'rdataset' is disassociated.
+ *
+ * Ensures:
+ *\li 'rdataset' is associated and points to a valid rdataest.
+ */
+unsigned int
+dns_rdataslab_size(unsigned char *slab, unsigned int reservelen);
+/*%<
+ * Return the total size of an rdataslab.
+ *
+ * Requires:
+ *\li 'slab' points to a slab.
+ *
+ * Returns:
+ *\li The number of bytes in the slab, including the reservelen.
+ */
+
+isc_result_t
+dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
+ unsigned int reservelen, isc_mem_t *mctx,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ unsigned int flags, unsigned char **tslabp);
+/*%<
+ * Merge 'oslab' and 'nslab'.
+ */
+
+isc_result_t
+dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
+ unsigned int reservelen, isc_mem_t *mctx,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ unsigned int flags, unsigned char **tslabp);
+/*%<
+ * Subtract 'sslab' from 'mslab'. If 'exact' is true then all elements
+ * of 'sslab' must exist in 'mslab'.
+ *
+ * XXX
+ * valid flags are DNS_RDATASLAB_EXACT
+ */
+
+isc_boolean_t
+dns_rdataslab_equal(unsigned char *slab1, unsigned char *slab2,
+ unsigned int reservelen);
+/*%<
+ * Compare two rdataslabs for equality. This does _not_ do a full
+ * DNSSEC comparison.
+ *
+ * Requires:
+ *\li 'slab1' and 'slab2' point to slabs.
+ *
+ * Returns:
+ *\li ISC_TRUE if the slabs are equal, ISC_FALSE otherwise.
+ */
+isc_boolean_t
+dns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2,
+ unsigned int reservelen, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type);
+/*%<
+ * Compare two rdataslabs for DNSSEC equality.
+ *
+ * Requires:
+ *\li 'slab1' and 'slab2' point to slabs.
+ *
+ * Returns:
+ *\li ISC_TRUE if the slabs are equal, #ISC_FALSE otherwise.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RDATASLAB_H */
diff --git a/lib/dns/include/dns/rdatatype.h b/lib/dns/include/dns/rdatatype.h
new file mode 100644
index 0000000..ba9a92c
--- /dev/null
+++ b/lib/dns/include/dns/rdatatype.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: rdatatype.h,v 1.26 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef DNS_RDATATYPE_H
+#define DNS_RDATATYPE_H 1
+
+/*! \file dns/rdatatype.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source);
+/*%<
+ * Convert the text 'source' refers to into a DNS rdata type.
+ *
+ * Requires:
+ *\li 'typep' is a valid pointer.
+ *
+ *\li 'source' is a valid text region.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS on success
+ *\li DNS_R_UNKNOWN type is unknown
+ */
+
+isc_result_t
+dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target);
+/*%<
+ * Put a textual representation of type 'type' into 'target'.
+ *
+ * Requires:
+ *\li 'type' is a valid type.
+ *
+ *\li 'target' is a valid text buffer.
+ *
+ * Ensures,
+ * if the result is success:
+ *\li The used space in 'target' is updated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS on success
+ *\li #ISC_R_NOSPACE target buffer is too small
+ */
+
+void
+dns_rdatatype_format(dns_rdatatype_t rdtype,
+ char *array, unsigned int size);
+/*%<
+ * Format a human-readable representation of the type 'rdtype'
+ * into the character array 'array', which is of size 'size'.
+ * The resulting string is guaranteed to be null-terminated.
+ */
+
+#define DNS_RDATATYPE_FORMATSIZE sizeof("NSEC3PARAM")
+
+/*%<
+ * Minimum size of array to pass to dns_rdatatype_format().
+ * May need to be adjusted if a new RR type with a very long
+ * name is defined.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RDATATYPE_H */
diff --git a/lib/dns/include/dns/request.h b/lib/dns/include/dns/request.h
new file mode 100644
index 0000000..9f115d0
--- /dev/null
+++ b/lib/dns/include/dns/request.h
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: request.h,v 1.27 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_REQUEST_H
+#define DNS_REQUEST_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/request.h
+ *
+ * \brief
+ * The request module provides simple request/response services useful for
+ * sending SOA queries, DNS Notify messages, and dynamic update requests.
+ *
+ * MP:
+ *\li The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ */
+
+#include <isc/lang.h>
+#include <isc/event.h>
+
+#include <dns/types.h>
+
+#define DNS_REQUESTOPT_TCP 0x00000001U
+
+typedef struct dns_requestevent {
+ ISC_EVENT_COMMON(struct dns_requestevent);
+ isc_result_t result;
+ dns_request_t *request;
+} dns_requestevent_t;
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
+ isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr,
+ dns_dispatchmgr_t *dispatchmgr,
+ dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6,
+ dns_requestmgr_t **requestmgrp);
+/*%<
+ * Create a request manager.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'timermgr' is a valid timer manager.
+ *
+ *\li 'socketmgr' is a valid socket manager.
+ *
+ *\li 'taskmgr' is a valid task manager.
+ *
+ *\li 'dispatchv4' is a valid dispatcher with an IPv4 UDP socket, or is NULL.
+ *
+ *\li 'dispatchv6' is a valid dispatcher with an IPv6 UDP socket, or is NULL.
+ *
+ *\li requestmgrp != NULL && *requestmgrp == NULL
+ *
+ * Ensures:
+ *
+ *\li On success, *requestmgrp is a valid request manager.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *
+ *\li Any other result indicates failure.
+ */
+
+void
+dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
+ isc_event_t **eventp);
+/*%<
+ * Send '*eventp' to 'task' when 'requestmgr' has completed shutdown.
+ *
+ * Notes:
+ *
+ *\li It is not safe to detach the last reference to 'requestmgr' until
+ * shutdown is complete.
+ *
+ * Requires:
+ *
+ *\li 'requestmgr' is a valid request manager.
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li *eventp is a valid event.
+ *
+ * Ensures:
+ *
+ *\li *eventp == NULL.
+ */
+
+void
+dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr);
+/*%<
+ * Start the shutdown process for 'requestmgr'.
+ *
+ * Notes:
+ *
+ *\li This call has no effect if the request manager is already shutting
+ * down.
+ *
+ * Requires:
+ *
+ *\li 'requestmgr' is a valid requestmgr.
+ */
+
+void
+dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp);
+/*%<
+ * Attach to the request manager. dns_requestmgr_shutdown() must not
+ * have been called on 'source' prior to calling dns_requestmgr_attach().
+ *
+ * Requires:
+ *
+ *\li 'source' is a valid requestmgr.
+ *
+ *\li 'targetp' to be non NULL and '*targetp' to be NULL.
+ */
+
+void
+dns_requestmgr_detach(dns_requestmgr_t **requestmgrp);
+/*%<
+ * Detach from the given requestmgr. If this is the final detach
+ * requestmgr will be destroyed. dns_requestmgr_shutdown() must
+ * be called before the final detach.
+ *
+ * Requires:
+ *
+ *\li '*requestmgrp' is a valid requestmgr.
+ *
+ * Ensures:
+ *\li '*requestmgrp' is NULL.
+ */
+
+isc_result_t
+dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
+ isc_sockaddr_t *address, unsigned int options,
+ dns_tsigkey_t *key,
+ unsigned int timeout, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_request_t **requestp);
+/*%<
+ * Create and send a request.
+ *
+ * Notes:
+ *
+ *\li 'message' will be rendered and sent to 'address'. If the
+ * #DNS_REQUESTOPT_TCP option is set, TCP will be used. The request
+ * will timeout after 'timeout' seconds.
+ *
+ *\li When the request completes, successfully, due to a timeout, or
+ * because it was canceled, a completion event will be sent to 'task'.
+ *
+ * Requires:
+ *
+ *\li 'message' is a valid DNS message.
+ *
+ *\li 'address' is a valid sockaddr.
+ *
+ *\li 'timeout' > 0
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li requestp != NULL && *requestp == NULL
+ */
+
+/*% See dns_request_createvia3() */
+isc_result_t
+dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, dns_tsigkey_t *key,
+ unsigned int timeout, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_request_t **requestp);
+
+/*% See dns_request_createvia3() */
+isc_result_t
+dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, dns_tsigkey_t *key,
+ unsigned int timeout, unsigned int udptimeout,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_request_t **requestp);
+
+isc_result_t
+dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, dns_tsigkey_t *key,
+ unsigned int timeout, unsigned int udptimeout,
+ unsigned int udpretries, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_request_t **requestp);
+/*%<
+ * Create and send a request.
+ *
+ * Notes:
+ *
+ *\li 'message' will be rendered and sent to 'address'. If the
+ * #DNS_REQUESTOPT_TCP option is set, TCP will be used. The request
+ * will timeout after 'timeout' seconds. UDP requests will be resent
+ * at 'udptimeout' intervals if non-zero or 'udpretries' is non-zero.
+ *
+ *\li When the request completes, successfully, due to a timeout, or
+ * because it was canceled, a completion event will be sent to 'task'.
+ *
+ * Requires:
+ *
+ *\li 'message' is a valid DNS message.
+ *
+ *\li 'dstaddr' is a valid sockaddr.
+ *
+ *\li 'srcaddr' is a valid sockaddr or NULL.
+ *
+ *\li 'srcaddr' and 'dstaddr' are the same protocol family.
+ *
+ *\li 'timeout' > 0
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li requestp != NULL && *requestp == NULL
+ */
+
+/*% See dns_request_createraw3() */
+isc_result_t
+dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, unsigned int timeout,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_request_t **requestp);
+
+/*% See dns_request_createraw3() */
+isc_result_t
+dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, unsigned int timeout,
+ unsigned int udptimeout, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_request_t **requestp);
+
+isc_result_t
+dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, unsigned int timeout,
+ unsigned int udptimeout, unsigned int udpretries,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_request_t **requestp);
+/*!<
+ * \brief Create and send a request.
+ *
+ * Notes:
+ *
+ *\li 'msgbuf' will be sent to 'destaddr' after setting the id. If the
+ * #DNS_REQUESTOPT_TCP option is set, TCP will be used. The request
+ * will timeout after 'timeout' seconds. UDP requests will be resent
+ * at 'udptimeout' intervals if non-zero or if 'udpretries' is not zero.
+ *
+ *\li When the request completes, successfully, due to a timeout, or
+ * because it was canceled, a completion event will be sent to 'task'.
+ *
+ * Requires:
+ *
+ *\li 'msgbuf' is a valid DNS message in compressed wire format.
+ *
+ *\li 'destaddr' is a valid sockaddr.
+ *
+ *\li 'srcaddr' is a valid sockaddr or NULL.
+ *
+ *\li 'srcaddr' and 'dstaddr' are the same protocol family.
+ *
+ *\li 'timeout' > 0
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li requestp != NULL && *requestp == NULL
+ */
+
+void
+dns_request_cancel(dns_request_t *request);
+/*%<
+ * Cancel 'request'.
+ *
+ * Requires:
+ *
+ *\li 'request' is a valid request.
+ *
+ * Ensures:
+ *
+ *\li If the completion event for 'request' has not yet been sent, it
+ * will be sent, and the result code will be ISC_R_CANCELED.
+ */
+
+isc_result_t
+dns_request_getresponse(dns_request_t *request, dns_message_t *message,
+ unsigned int options);
+/*%<
+ * Get the response to 'request' by filling in 'message'.
+ *
+ * 'options' is passed to dns_message_parse(). See dns_message_parse()
+ * for more details.
+ *
+ * Requires:
+ *
+ *\li 'request' is a valid request for which the caller has received the
+ * completion event.
+ *
+ *\li The result code of the completion event was #ISC_R_SUCCESS.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *
+ *\li Any result that dns_message_parse() can return.
+ */
+
+isc_boolean_t
+dns_request_usedtcp(dns_request_t *request);
+/*%<
+ * Return whether this query used TCP or not. Setting #DNS_REQUESTOPT_TCP
+ * in the call to dns_request_create() will cause the function to return
+ * #ISC_TRUE, othewise the result is based on the query message size.
+ *
+ * Requires:
+ *\li 'request' is a valid request.
+ *
+ * Returns:
+ *\li ISC_TRUE if TCP was used.
+ *\li ISC_FALSE if UDP was used.
+ */
+
+void
+dns_request_destroy(dns_request_t **requestp);
+/*%<
+ * Destroy 'request'.
+ *
+ * Requires:
+ *
+ *\li 'request' is a valid request for which the caller has received the
+ * completion event.
+ *
+ * Ensures:
+ *
+ *\li *requestp == NULL
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_REQUEST_H */
diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h
new file mode 100644
index 0000000..2318e20
--- /dev/null
+++ b/lib/dns/include/dns/resolver.h
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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: resolver.h,v 1.60 2008/09/08 05:41:22 marka Exp $ */
+
+#ifndef DNS_RESOLVER_H
+#define DNS_RESOLVER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/resolver.h
+ *
+ * \brief
+ * This is the BIND 9 resolver, the module responsible for resolving DNS
+ * requests by iteratively querying authoritative servers and following
+ * referrals. This is a "full resolver", not to be confused with
+ * the stub resolvers most people associate with the word "resolver".
+ * The full resolver is part of the caching name server or resolver
+ * daemon the stub resolver talks to.
+ *
+ * MP:
+ *\li The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li RFCs: 1034, 1035, 2181, TBS
+ *\li Drafts: TBS
+ */
+
+#include <isc/lang.h>
+#include <isc/socket.h>
+
+#include <dns/types.h>
+#include <dns/fixedname.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * A dns_fetchevent_t is sent when a 'fetch' completes. Any of 'db',
+ * 'node', 'rdataset', and 'sigrdataset' may be bound. It is the
+ * receiver's responsibility to detach before freeing the event.
+ * \brief
+ * 'rdataset', 'sigrdataset', 'client' and 'id' are the values that were
+ * supplied when dns_resolver_createfetch() was called. They are returned
+ * to the caller so that they may be freed.
+ */
+typedef struct dns_fetchevent {
+ ISC_EVENT_COMMON(struct dns_fetchevent);
+ dns_fetch_t * fetch;
+ isc_result_t result;
+ dns_rdatatype_t qtype;
+ dns_db_t * db;
+ dns_dbnode_t * node;
+ dns_rdataset_t * rdataset;
+ dns_rdataset_t * sigrdataset;
+ dns_fixedname_t foundname;
+ isc_sockaddr_t * client;
+ dns_messageid_t id;
+} dns_fetchevent_t;
+
+/*
+ * Options that modify how a 'fetch' is done.
+ */
+#define DNS_FETCHOPT_TCP 0x01 /*%< Use TCP. */
+#define DNS_FETCHOPT_UNSHARED 0x02 /*%< See below. */
+#define DNS_FETCHOPT_RECURSIVE 0x04 /*%< Set RD? */
+#define DNS_FETCHOPT_NOEDNS0 0x08 /*%< Do not use EDNS. */
+#define DNS_FETCHOPT_FORWARDONLY 0x10 /*%< Only use forwarders. */
+#define DNS_FETCHOPT_NOVALIDATE 0x20 /*%< Disable validation. */
+#define DNS_FETCHOPT_EDNS512 0x40 /*%< Advertise a 512 byte
+ UDP buffer. */
+#define DNS_FETCHOPT_WANTNSID 0x80 /*%< Request NSID */
+
+#define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000
+#define DNS_FETCHOPT_EDNSVERSIONMASK 0xff000000
+#define DNS_FETCHOPT_EDNSVERSIONSHIFT 24
+
+/*
+ * XXXRTH Should this API be made semi-private? (I.e.
+ * _dns_resolver_create()).
+ */
+
+#define DNS_RESOLVER_CHECKNAMES 0x01
+#define DNS_RESOLVER_CHECKNAMESFAIL 0x02
+
+isc_result_t
+dns_resolver_create(dns_view_t *view,
+ isc_taskmgr_t *taskmgr, unsigned int ntasks,
+ isc_socketmgr_t *socketmgr,
+ isc_timermgr_t *timermgr,
+ unsigned int options,
+ dns_dispatchmgr_t *dispatchmgr,
+ dns_dispatch_t *dispatchv4,
+ dns_dispatch_t *dispatchv6,
+ dns_resolver_t **resp);
+
+/*%<
+ * Create a resolver.
+ *
+ * Notes:
+ *
+ *\li Generally, applications should not create a resolver directly, but
+ * should instead call dns_view_createresolver().
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid view.
+ *
+ *\li 'taskmgr' is a valid task manager.
+ *
+ *\li 'ntasks' > 0.
+ *
+ *\li 'socketmgr' is a valid socket manager.
+ *
+ *\li 'timermgr' is a valid timer manager.
+ *
+ *\li 'dispatchv4' is a valid dispatcher with an IPv4 UDP socket, or is NULL.
+ *
+ *\li 'dispatchv6' is a valid dispatcher with an IPv6 UDP socket, or is NULL.
+ *
+ *\li resp != NULL && *resp == NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS On success.
+ *
+ *\li Anything else Failure.
+ */
+
+void
+dns_resolver_freeze(dns_resolver_t *res);
+/*%<
+ * Freeze resolver.
+ *
+ * Notes:
+ *
+ *\li Certain configuration changes cannot be made after the resolver
+ * is frozen. Fetches cannot be created until the resolver is frozen.
+ *
+ * Requires:
+ *
+ *\li 'res' is a valid, unfrozen resolver.
+ *
+ * Ensures:
+ *
+ *\li 'res' is frozen.
+ */
+
+void
+dns_resolver_prime(dns_resolver_t *res);
+/*%<
+ * Prime resolver.
+ *
+ * Notes:
+ *
+ *\li Resolvers which have a forwarding policy other than dns_fwdpolicy_only
+ * need to be primed with the root nameservers, otherwise the root
+ * nameserver hints data may be used indefinitely. This function requests
+ * that the resolver start a priming fetch, if it isn't already priming.
+ *
+ * Requires:
+ *
+ *\li 'res' is a valid, frozen resolver.
+ */
+
+
+void
+dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
+ isc_event_t **eventp);
+/*%<
+ * Send '*eventp' to 'task' when 'res' has completed shutdown.
+ *
+ * Notes:
+ *
+ *\li It is not safe to detach the last reference to 'res' until
+ * shutdown is complete.
+ *
+ * Requires:
+ *
+ *\li 'res' is a valid resolver.
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li *eventp is a valid event.
+ *
+ * Ensures:
+ *
+ *\li *eventp == NULL.
+ */
+
+void
+dns_resolver_shutdown(dns_resolver_t *res);
+/*%<
+ * Start the shutdown process for 'res'.
+ *
+ * Notes:
+ *
+ *\li This call has no effect if the resolver is already shutting down.
+ *
+ * Requires:
+ *
+ *\li 'res' is a valid resolver.
+ */
+
+void
+dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp);
+
+void
+dns_resolver_detach(dns_resolver_t **resp);
+
+isc_result_t
+dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_name_t *domain, dns_rdataset_t *nameservers,
+ dns_forwarders_t *forwarders,
+ unsigned int options, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset,
+ dns_fetch_t **fetchp);
+
+isc_result_t
+dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_name_t *domain, dns_rdataset_t *nameservers,
+ dns_forwarders_t *forwarders,
+ isc_sockaddr_t *client, isc_uint16_t id,
+ unsigned int options, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset,
+ dns_fetch_t **fetchp);
+/*%<
+ * Recurse to answer a question.
+ *
+ * Notes:
+ *
+ *\li This call starts a query for 'name', type 'type'.
+ *
+ *\li The 'domain' is a parent domain of 'name' for which
+ * a set of name servers 'nameservers' is known. If no
+ * such name server information is available, set
+ * 'domain' and 'nameservers' to NULL.
+ *
+ *\li 'forwarders' is unimplemented, and subject to change when
+ * we figure out how selective forwarding will work.
+ *
+ *\li When the fetch completes (successfully or otherwise), a
+ * #DNS_EVENT_FETCHDONE event with action 'action' and arg 'arg' will be
+ * posted to 'task'.
+ *
+ *\li The values of 'rdataset' and 'sigrdataset' will be returned in
+ * the FETCHDONE event.
+ *
+ *\li 'client' and 'id' are used for duplicate query detection. '*client'
+ * must remain stable until after 'action' has been called or
+ * dns_resolver_cancelfetch() is called.
+ *
+ * Requires:
+ *
+ *\li 'res' is a valid resolver that has been frozen.
+ *
+ *\li 'name' is a valid name.
+ *
+ *\li 'type' is not a meta type other than ANY.
+ *
+ *\li 'domain' is a valid name or NULL.
+ *
+ *\li 'nameservers' is a valid NS rdataset (whose owner name is 'domain')
+ * iff. 'domain' is not NULL.
+ *
+ *\li 'forwarders' is NULL.
+ *
+ *\li 'client' is a valid sockaddr or NULL.
+ *
+ *\li 'options' contains valid options.
+ *
+ *\li 'rdataset' is a valid, disassociated rdataset.
+ *
+ *\li 'sigrdataset' is NULL, or is a valid, disassociated rdataset.
+ *
+ *\li fetchp != NULL && *fetchp == NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS Success
+ *\li #DNS_R_DUPLICATE
+ *\li #DNS_R_DROP
+ *
+ *\li Many other values are possible, all of which indicate failure.
+ */
+
+void
+dns_resolver_cancelfetch(dns_fetch_t *fetch);
+/*%<
+ * Cancel 'fetch'.
+ *
+ * Notes:
+ *
+ *\li If 'fetch' has not completed, post its FETCHDONE event with a
+ * result code of #ISC_R_CANCELED.
+ *
+ * Requires:
+ *
+ *\li 'fetch' is a valid fetch.
+ */
+
+void
+dns_resolver_destroyfetch(dns_fetch_t **fetchp);
+/*%<
+ * Destroy 'fetch'.
+ *
+ * Requires:
+ *
+ *\li '*fetchp' is a valid fetch.
+ *
+ *\li The caller has received the FETCHDONE event (either because the
+ * fetch completed or because dns_resolver_cancelfetch() was called).
+ *
+ * Ensures:
+ *
+ *\li *fetchp == NULL.
+ */
+
+dns_dispatchmgr_t *
+dns_resolver_dispatchmgr(dns_resolver_t *resolver);
+
+dns_dispatch_t *
+dns_resolver_dispatchv4(dns_resolver_t *resolver);
+
+dns_dispatch_t *
+dns_resolver_dispatchv6(dns_resolver_t *resolver);
+
+isc_socketmgr_t *
+dns_resolver_socketmgr(dns_resolver_t *resolver);
+
+isc_taskmgr_t *
+dns_resolver_taskmgr(dns_resolver_t *resolver);
+
+isc_uint32_t
+dns_resolver_getlamettl(dns_resolver_t *resolver);
+/*%<
+ * Get the resolver's lame-ttl. zero => no lame processing.
+ *
+ * Requires:
+ *\li 'resolver' to be valid.
+ */
+
+void
+dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl);
+/*%<
+ * Set the resolver's lame-ttl. zero => no lame processing.
+ *
+ * Requires:
+ *\li 'resolver' to be valid.
+ */
+
+unsigned int
+dns_resolver_nrunning(dns_resolver_t *resolver);
+/*%<
+ * Return the number of currently running resolutions in this
+ * resolver. This is may be less than the number of outstanding
+ * fetches due to multiple identical fetches, or more than the
+ * number of of outstanding fetches due to the fact that resolution
+ * can continue even though a fetch has been canceled.
+ */
+
+isc_result_t
+dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
+ dns_name_t *name, in_port_t port);
+/*%<
+ * Add alternate addresses to be tried in the event that the nameservers
+ * for a zone are not available in the address families supported by the
+ * operating system.
+ *
+ * Require:
+ * \li only one of 'name' or 'alt' to be valid.
+ */
+
+void
+dns_resolver_setudpsize(dns_resolver_t *resolver, isc_uint16_t udpsize);
+/*%<
+ * Set the EDNS UDP buffer size advertised by the server.
+ */
+
+isc_uint16_t
+dns_resolver_getudpsize(dns_resolver_t *resolver);
+/*%<
+ * Get the current EDNS UDP buffer size.
+ */
+
+void
+dns_resolver_reset_algorithms(dns_resolver_t *resolver);
+/*%<
+ * Clear the disabled DNSSEC algorithms.
+ */
+
+isc_result_t
+dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
+ unsigned int alg);
+/*%<
+ * Mark the give DNSSEC algorithm as disabled and below 'name'.
+ * Valid algorithms are less than 256.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_RANGE
+ *\li #ISC_R_NOMEMORY
+ */
+
+isc_boolean_t
+dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
+ unsigned int alg);
+/*%<
+ * Check if the given algorithm is supported by this resolver.
+ * This checks if the algorithm has been disabled via
+ * dns_resolver_disable_algorithm() then the underlying
+ * crypto libraries if not specifically disabled.
+ */
+
+isc_boolean_t
+dns_resolver_digest_supported(dns_resolver_t *resolver, unsigned int digest_type);
+/*%<
+ * Is this digest type supported.
+ */
+
+void
+dns_resolver_resetmustbesecure(dns_resolver_t *resolver);
+
+isc_result_t
+dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
+ isc_boolean_t value);
+
+isc_boolean_t
+dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name);
+
+void
+dns_resolver_setclientsperquery(dns_resolver_t *resolver,
+ isc_uint32_t min, isc_uint32_t max);
+
+void
+dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
+ isc_uint32_t *min, isc_uint32_t *max);
+
+isc_boolean_t
+dns_resolver_getzeronosoattl(dns_resolver_t *resolver);
+
+void
+dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state);
+
+unsigned int
+dns_resolver_getoptions(dns_resolver_t *resolver);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RESOLVER_H */
diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h
new file mode 100644
index 0000000..ed29bcd
--- /dev/null
+++ b/lib/dns/include/dns/result.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: result.h,v 1.116 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef DNS_RESULT_H
+#define DNS_RESULT_H 1
+
+/*! \file dns/result.h */
+
+#include <isc/lang.h>
+#include <isc/resultclass.h>
+
+#include <dns/types.h>
+
+/*
+ * Nothing in this file truly depends on <isc/result.h>, but the
+ * DNS result codes are considered to be publicly derived from
+ * the ISC result codes, so including this file buys you the ISC_R_
+ * namespace too.
+ */
+#include <isc/result.h> /* Contractual promise. */
+
+/*
+ * DNS library result codes
+ */
+#define DNS_R_LABELTOOLONG (ISC_RESULTCLASS_DNS + 0)
+#define DNS_R_BADESCAPE (ISC_RESULTCLASS_DNS + 1)
+/*
+ * Since we dropped the support of bitstring labels, deprecate the related
+ * result codes too.
+
+#define DNS_R_BADBITSTRING (ISC_RESULTCLASS_DNS + 2)
+#define DNS_R_BITSTRINGTOOLONG (ISC_RESULTCLASS_DNS + 3)
+*/
+#define DNS_R_EMPTYLABEL (ISC_RESULTCLASS_DNS + 4)
+#define DNS_R_BADDOTTEDQUAD (ISC_RESULTCLASS_DNS + 5)
+#define DNS_R_INVALIDNS (ISC_RESULTCLASS_DNS + 6)
+#define DNS_R_UNKNOWN (ISC_RESULTCLASS_DNS + 7)
+#define DNS_R_BADLABELTYPE (ISC_RESULTCLASS_DNS + 8)
+#define DNS_R_BADPOINTER (ISC_RESULTCLASS_DNS + 9)
+#define DNS_R_TOOMANYHOPS (ISC_RESULTCLASS_DNS + 10)
+#define DNS_R_DISALLOWED (ISC_RESULTCLASS_DNS + 11)
+#define DNS_R_EXTRATOKEN (ISC_RESULTCLASS_DNS + 12)
+#define DNS_R_EXTRADATA (ISC_RESULTCLASS_DNS + 13)
+#define DNS_R_TEXTTOOLONG (ISC_RESULTCLASS_DNS + 14)
+#define DNS_R_NOTZONETOP (ISC_RESULTCLASS_DNS + 15)
+#define DNS_R_SYNTAX (ISC_RESULTCLASS_DNS + 16)
+#define DNS_R_BADCKSUM (ISC_RESULTCLASS_DNS + 17)
+#define DNS_R_BADAAAA (ISC_RESULTCLASS_DNS + 18)
+#define DNS_R_NOOWNER (ISC_RESULTCLASS_DNS + 19)
+#define DNS_R_NOTTL (ISC_RESULTCLASS_DNS + 20)
+#define DNS_R_BADCLASS (ISC_RESULTCLASS_DNS + 21)
+#define DNS_R_NAMETOOLONG (ISC_RESULTCLASS_DNS + 22)
+#define DNS_R_PARTIALMATCH (ISC_RESULTCLASS_DNS + 23)
+#define DNS_R_NEWORIGIN (ISC_RESULTCLASS_DNS + 24)
+#define DNS_R_UNCHANGED (ISC_RESULTCLASS_DNS + 25)
+#define DNS_R_BADTTL (ISC_RESULTCLASS_DNS + 26)
+#define DNS_R_NOREDATA (ISC_RESULTCLASS_DNS + 27)
+#define DNS_R_CONTINUE (ISC_RESULTCLASS_DNS + 28)
+#define DNS_R_DELEGATION (ISC_RESULTCLASS_DNS + 29)
+#define DNS_R_GLUE (ISC_RESULTCLASS_DNS + 30)
+#define DNS_R_DNAME (ISC_RESULTCLASS_DNS + 31)
+#define DNS_R_CNAME (ISC_RESULTCLASS_DNS + 32)
+#define DNS_R_BADDB (ISC_RESULTCLASS_DNS + 33)
+#define DNS_R_ZONECUT (ISC_RESULTCLASS_DNS + 34)
+#define DNS_R_BADZONE (ISC_RESULTCLASS_DNS + 35)
+#define DNS_R_MOREDATA (ISC_RESULTCLASS_DNS + 36)
+#define DNS_R_UPTODATE (ISC_RESULTCLASS_DNS + 37)
+#define DNS_R_TSIGVERIFYFAILURE (ISC_RESULTCLASS_DNS + 38)
+#define DNS_R_TSIGERRORSET (ISC_RESULTCLASS_DNS + 39)
+#define DNS_R_SIGINVALID (ISC_RESULTCLASS_DNS + 40)
+#define DNS_R_SIGEXPIRED (ISC_RESULTCLASS_DNS + 41)
+#define DNS_R_SIGFUTURE (ISC_RESULTCLASS_DNS + 42)
+#define DNS_R_KEYUNAUTHORIZED (ISC_RESULTCLASS_DNS + 43)
+#define DNS_R_INVALIDTIME (ISC_RESULTCLASS_DNS + 44)
+#define DNS_R_EXPECTEDTSIG (ISC_RESULTCLASS_DNS + 45)
+#define DNS_R_UNEXPECTEDTSIG (ISC_RESULTCLASS_DNS + 46)
+#define DNS_R_INVALIDTKEY (ISC_RESULTCLASS_DNS + 47)
+#define DNS_R_HINT (ISC_RESULTCLASS_DNS + 48)
+#define DNS_R_DROP (ISC_RESULTCLASS_DNS + 49)
+#define DNS_R_NOTLOADED (ISC_RESULTCLASS_DNS + 50)
+#define DNS_R_NCACHENXDOMAIN (ISC_RESULTCLASS_DNS + 51)
+#define DNS_R_NCACHENXRRSET (ISC_RESULTCLASS_DNS + 52)
+#define DNS_R_WAIT (ISC_RESULTCLASS_DNS + 53)
+#define DNS_R_NOTVERIFIEDYET (ISC_RESULTCLASS_DNS + 54)
+#define DNS_R_NOIDENTITY (ISC_RESULTCLASS_DNS + 55)
+#define DNS_R_NOJOURNAL (ISC_RESULTCLASS_DNS + 56)
+#define DNS_R_ALIAS (ISC_RESULTCLASS_DNS + 57)
+#define DNS_R_USETCP (ISC_RESULTCLASS_DNS + 58)
+#define DNS_R_NOVALIDSIG (ISC_RESULTCLASS_DNS + 59)
+#define DNS_R_NOVALIDNSEC (ISC_RESULTCLASS_DNS + 60)
+#define DNS_R_NOTINSECURE (ISC_RESULTCLASS_DNS + 61)
+#define DNS_R_UNKNOWNSERVICE (ISC_RESULTCLASS_DNS + 62)
+#define DNS_R_RECOVERABLE (ISC_RESULTCLASS_DNS + 63)
+#define DNS_R_UNKNOWNOPT (ISC_RESULTCLASS_DNS + 64)
+#define DNS_R_UNEXPECTEDID (ISC_RESULTCLASS_DNS + 65)
+#define DNS_R_SEENINCLUDE (ISC_RESULTCLASS_DNS + 66)
+#define DNS_R_NOTEXACT (ISC_RESULTCLASS_DNS + 67)
+#define DNS_R_BLACKHOLED (ISC_RESULTCLASS_DNS + 68)
+#define DNS_R_BADALG (ISC_RESULTCLASS_DNS + 69)
+#define DNS_R_METATYPE (ISC_RESULTCLASS_DNS + 70)
+#define DNS_R_CNAMEANDOTHER (ISC_RESULTCLASS_DNS + 71)
+#define DNS_R_SINGLETON (ISC_RESULTCLASS_DNS + 72)
+#define DNS_R_HINTNXRRSET (ISC_RESULTCLASS_DNS + 73)
+#define DNS_R_NOMASTERFILE (ISC_RESULTCLASS_DNS + 74)
+#define DNS_R_UNKNOWNPROTO (ISC_RESULTCLASS_DNS + 75)
+#define DNS_R_CLOCKSKEW (ISC_RESULTCLASS_DNS + 76)
+#define DNS_R_BADIXFR (ISC_RESULTCLASS_DNS + 77)
+#define DNS_R_NOTAUTHORITATIVE (ISC_RESULTCLASS_DNS + 78)
+#define DNS_R_NOVALIDKEY (ISC_RESULTCLASS_DNS + 79)
+#define DNS_R_OBSOLETE (ISC_RESULTCLASS_DNS + 80)
+#define DNS_R_FROZEN (ISC_RESULTCLASS_DNS + 81)
+#define DNS_R_UNKNOWNFLAG (ISC_RESULTCLASS_DNS + 82)
+#define DNS_R_EXPECTEDRESPONSE (ISC_RESULTCLASS_DNS + 83)
+#define DNS_R_NOVALIDDS (ISC_RESULTCLASS_DNS + 84)
+#define DNS_R_NSISADDRESS (ISC_RESULTCLASS_DNS + 85)
+#define DNS_R_REMOTEFORMERR (ISC_RESULTCLASS_DNS + 86)
+#define DNS_R_TRUNCATEDTCP (ISC_RESULTCLASS_DNS + 87)
+#define DNS_R_LAME (ISC_RESULTCLASS_DNS + 88)
+#define DNS_R_UNEXPECTEDRCODE (ISC_RESULTCLASS_DNS + 89)
+#define DNS_R_UNEXPECTEDOPCODE (ISC_RESULTCLASS_DNS + 90)
+#define DNS_R_CHASEDSSERVERS (ISC_RESULTCLASS_DNS + 91)
+#define DNS_R_EMPTYNAME (ISC_RESULTCLASS_DNS + 92)
+#define DNS_R_EMPTYWILD (ISC_RESULTCLASS_DNS + 93)
+#define DNS_R_BADBITMAP (ISC_RESULTCLASS_DNS + 94)
+#define DNS_R_FROMWILDCARD (ISC_RESULTCLASS_DNS + 95)
+#define DNS_R_BADOWNERNAME (ISC_RESULTCLASS_DNS + 96)
+#define DNS_R_BADNAME (ISC_RESULTCLASS_DNS + 97)
+#define DNS_R_DYNAMIC (ISC_RESULTCLASS_DNS + 98)
+#define DNS_R_UNKNOWNCOMMAND (ISC_RESULTCLASS_DNS + 99)
+#define DNS_R_MUSTBESECURE (ISC_RESULTCLASS_DNS + 100)
+#define DNS_R_COVERINGNSEC (ISC_RESULTCLASS_DNS + 101)
+#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_NRESULTS 105 /*%< Number of results */
+
+/*
+ * DNS wire format rcodes.
+ *
+ * By making these their own class we can easily convert them into the
+ * wire-format rcode value simply by masking off the resultclass.
+ */
+#define DNS_R_NOERROR (ISC_RESULTCLASS_DNSRCODE + 0)
+#define DNS_R_FORMERR (ISC_RESULTCLASS_DNSRCODE + 1)
+#define DNS_R_SERVFAIL (ISC_RESULTCLASS_DNSRCODE + 2)
+#define DNS_R_NXDOMAIN (ISC_RESULTCLASS_DNSRCODE + 3)
+#define DNS_R_NOTIMP (ISC_RESULTCLASS_DNSRCODE + 4)
+#define DNS_R_REFUSED (ISC_RESULTCLASS_DNSRCODE + 5)
+#define DNS_R_YXDOMAIN (ISC_RESULTCLASS_DNSRCODE + 6)
+#define DNS_R_YXRRSET (ISC_RESULTCLASS_DNSRCODE + 7)
+#define DNS_R_NXRRSET (ISC_RESULTCLASS_DNSRCODE + 8)
+#define DNS_R_NOTAUTH (ISC_RESULTCLASS_DNSRCODE + 9)
+#define DNS_R_NOTZONE (ISC_RESULTCLASS_DNSRCODE + 10)
+#define DNS_R_BADVERS (ISC_RESULTCLASS_DNSRCODE + 16)
+
+#define DNS_R_NRCODERESULTS 17 /*%< Number of rcode results */
+
+#define DNS_RESULT_ISRCODE(result) \
+ (ISC_RESULTCLASS_INCLASS(ISC_RESULTCLASS_DNSRCODE, (result)))
+
+ISC_LANG_BEGINDECLS
+
+const char *
+dns_result_totext(isc_result_t);
+
+void
+dns_result_register(void);
+
+dns_rcode_t
+dns_result_torcode(isc_result_t result);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RESULT_H */
diff --git a/lib/dns/include/dns/rootns.h b/lib/dns/include/dns/rootns.h
new file mode 100644
index 0000000..6da3f79
--- /dev/null
+++ b/lib/dns/include/dns/rootns.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rootns.h,v 1.16 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_ROOTNS_H
+#define DNS_ROOTNS_H 1
+
+/*! \file dns/rootns.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
+ const char *filename, dns_db_t **target);
+
+void
+dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db);
+/*
+ * Reports differences between hints and the real roots.
+ *
+ * Requires view, hints and (cache) db to be valid.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_ROOTNS_H */
diff --git a/lib/dns/include/dns/sdb.h b/lib/dns/include/dns/sdb.h
new file mode 100644
index 0000000..3914295
--- /dev/null
+++ b/lib/dns/include/dns/sdb.h
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2004-2007 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: sdb.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_SDB_H
+#define DNS_SDB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/sdb.h
+ * \brief
+ * Simple database API.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+/***
+ *** Types
+ ***/
+
+/*%
+ * A simple database. This is an opaque type.
+ */
+typedef struct dns_sdb dns_sdb_t;
+
+/*%
+ * A simple database lookup in progress. This is an opaque type.
+ */
+typedef struct dns_sdblookup dns_sdblookup_t;
+
+/*%
+ * A simple database traversal in progress. This is an opaque type.
+ */
+typedef struct dns_sdballnodes dns_sdballnodes_t;
+
+typedef isc_result_t
+(*dns_sdblookupfunc_t)(const char *zone, const char *name, void *dbdata,
+ dns_sdblookup_t *);
+
+typedef isc_result_t
+(*dns_sdbauthorityfunc_t)(const char *zone, void *dbdata, dns_sdblookup_t *);
+
+typedef isc_result_t
+(*dns_sdballnodesfunc_t)(const char *zone, void *dbdata,
+ dns_sdballnodes_t *allnodes);
+
+typedef isc_result_t
+(*dns_sdbcreatefunc_t)(const char *zone, int argc, char **argv,
+ void *driverdata, void **dbdata);
+
+typedef void
+(*dns_sdbdestroyfunc_t)(const char *zone, void *driverdata, void **dbdata);
+
+
+typedef struct dns_sdbmethods {
+ dns_sdblookupfunc_t lookup;
+ dns_sdbauthorityfunc_t authority;
+ dns_sdballnodesfunc_t allnodes;
+ dns_sdbcreatefunc_t create;
+ dns_sdbdestroyfunc_t destroy;
+} dns_sdbmethods_t;
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+#define DNS_SDBFLAG_RELATIVEOWNER 0x00000001U
+#define DNS_SDBFLAG_RELATIVERDATA 0x00000002U
+#define DNS_SDBFLAG_THREADSAFE 0x00000004U
+
+isc_result_t
+dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
+ void *driverdata, unsigned int flags, isc_mem_t *mctx,
+ dns_sdbimplementation_t **sdbimp);
+/*%<
+ * Register a simple database driver for the database type 'drivername',
+ * implemented by the functions in '*methods'.
+ *
+ * sdbimp must point to a NULL dns_sdbimplementation_t pointer. That is,
+ * sdbimp != NULL && *sdbimp == NULL. It will be assigned a value that
+ * will later be used to identify the driver when deregistering it.
+ *
+ * The name server will perform lookups in the database by calling the
+ * function 'lookup', passing it a printable zone name 'zone', a printable
+ * domain name 'name', and a copy of the argument 'dbdata' that
+ * was potentially returned by the create function. The 'dns_sdblookup_t'
+ * argument to 'lookup' and 'authority' is an opaque pointer to be passed to
+ * ns_sdb_putrr().
+ *
+ * The lookup function returns the lookup results to the name server
+ * by calling ns_sdb_putrr() once for each record found. On success,
+ * the return value of the lookup function should be ISC_R_SUCCESS.
+ * If the domain name 'name' does not exist, the lookup function should
+ * ISC_R_NOTFOUND. Any other return value is treated as an error.
+ *
+ * Lookups at the zone apex will cause the server to also call the
+ * function 'authority' (if non-NULL), which must provide an SOA record
+ * and NS records for the zone by calling ns_sdb_putrr() once for each of
+ * these records. The 'authority' function may be NULL if invoking
+ * the 'lookup' function on the zone apex will return SOA and NS records.
+ *
+ * The allnodes function, if non-NULL, fills in an opaque structure to be
+ * used by a database iterator. This allows the zone to be transferred.
+ * This may use a considerable amount of memory for large zones, and the
+ * zone transfer may not be fully RFC1035 compliant if the zone is
+ * frequently changed.
+ *
+ * The create function will be called for each zone configured
+ * into the name server using this database type. It can be used
+ * to create a "database object" containg zone specific data,
+ * which can make use of the database arguments specified in the
+ * name server configuration.
+ *
+ * The destroy function will be called to free the database object
+ * when its zone is destroyed.
+ *
+ * The create and destroy functions may be NULL.
+ *
+ * If flags includes DNS_SDBFLAG_RELATIVEOWNER, the lookup and authority
+ * functions will be called with relative names rather than absolute names.
+ * The string "@" represents the zone apex in this case.
+ *
+ * If flags includes DNS_SDBFLAG_RELATIVERDATA, the rdata strings may
+ * include relative names. Otherwise, all names in the rdata string must
+ * be absolute. Be aware that if relative names are allowed, any
+ * absolute names must contain a trailing dot.
+ *
+ * If flags includes DNS_SDBFLAG_THREADSAFE, the driver must be able to
+ * handle multiple lookups in parallel. Otherwise, calls into the driver
+ * are serialized.
+ */
+
+void
+dns_sdb_unregister(dns_sdbimplementation_t **sdbimp);
+/*%<
+ * Removes the simple database driver from the list of registered database
+ * types. There must be no active databases of this type when this function
+ * is called.
+ */
+
+/*% See dns_sdb_putradata() */
+isc_result_t
+dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
+ const char *data);
+isc_result_t
+dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t type, dns_ttl_t ttl,
+ const unsigned char *rdata, unsigned int rdlen);
+/*%<
+ * Add a single resource record to the lookup structure to be
+ * returned in the query response. dns_sdb_putrr() takes the
+ * resource record in master file text format as a null-terminated
+ * string, and dns_sdb_putrdata() takes the raw RDATA in
+ * uncompressed wire format.
+ */
+
+/*% See dns_sdb_putnamerdata() */
+isc_result_t
+dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
+ const char *type, dns_ttl_t ttl, const char *data);
+isc_result_t
+dns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
+ dns_rdatatype_t type, dns_ttl_t ttl,
+ const void *rdata, unsigned int rdlen);
+/*%<
+ * Add a single resource record to the allnodes structure to be
+ * included in a zone transfer response, in text or wire
+ * format as above.
+ */
+
+isc_result_t
+dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
+ isc_uint32_t serial);
+/*%<
+ * This function may optionally be called from the 'authority' callback
+ * to simplify construction of the SOA record for 'zone'. It will
+ * provide a SOA listing 'mname' as as the master server and 'rname' as
+ * the responsible person mailbox. It is the responsibility of the
+ * driver to increment the serial number between responses if necessary.
+ * All other SOA fields will have reasonable default values.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_SDB_H */
diff --git a/lib/dns/include/dns/sdlz.h b/lib/dns/include/dns/sdlz.h
new file mode 100644
index 0000000..6f14e6f
--- /dev/null
+++ b/lib/dns/include/dns/sdlz.h
@@ -0,0 +1,266 @@
+/*
+ * Portions Copyright (C) 2005-2007 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
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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: sdlz.h,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file dns/sdlz.h */
+
+#ifndef SDLZ_H
+#define SDLZ_H 1
+
+#include <dns/dlz.h>
+
+ISC_LANG_BEGINDECLS
+
+#define DNS_SDLZFLAG_THREADSAFE 0x00000001U
+#define DNS_SDLZFLAG_RELATIVEOWNER 0x00000002U
+#define DNS_SDLZFLAG_RELATIVERDATA 0x00000004U
+
+ /* A simple DLZ database. */
+typedef struct dns_sdlz_db dns_sdlz_db_t;
+
+ /* A simple DLZ database lookup in progress. */
+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);
+
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface may
+ * supply an all nodes method. This method is called when the DNS
+ * server is performing a zone transfer query, after the allow zone
+ * transfer method has been called. This method is only called if the
+ * allow zone transfer method returned ISC_R_SUCCESS. This method and
+ * the allow zone transfer method are both required for zone transfers
+ * to be supported. If the driver generates data dynamically (instead
+ * of searching in a database for it) it should not implement this
+ * function as a zone transfer would be meaningless. A SDLZ driver
+ * 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);
+
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface may
+ * supply an allow zone transfer method. This method is called when
+ * the DNS server is performing a zone transfer query, before the all
+ * nodes method can be called. This method and the all node method
+ * are both required for zone transfers to be supported. If the
+ * driver generates data dynamically (instead of searching in a
+ * database for it) it should not implement this function as a zone
+ * transfer would be meaningless. A SDLZ driver does not have to
+ * implement an allow zone transfer method.
+ *
+ * This method should return ISC_R_SUCCESS if the zone is supported by
+ * the database and a zone transfer is allowed for the specified
+ * client. If the zone is supported by the database, but zone
+ * transfers are not allowed for the specified client this method
+ * should return ISC_R_NOPERM.. Lastly the method should return
+ * ISC_R_NOTFOUND if the zone is not supported by the database. If an
+ * error occurs it should return a result code indicating the type of
+ * error.
+ */
+
+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
+ * supply an authority method. This method is called when the DNS
+ * server is performing a query, after both the find zone and lookup
+ * methods have been called. This method is required if the lookup
+ * function does not supply authority information for the dns
+ * record. A SDLZ driver does not have to implement an authority
+ * method.
+ */
+
+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
+ * supply a create method. This method is called when the DNS server
+ * is starting up and creating drivers for use later. A SDLZ driver
+ * does not have to implement a create method.
+ */
+
+typedef void
+(*dns_sdlzdestroy_t)(void *driverarg, void *dbdata);
+
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface may
+ * supply a destroy method. This method is called when the DNS server
+ * is shuting down and no longer needs the driver. A SDLZ driver does
+ * not have to implement a destroy method.
+ */
+
+typedef isc_result_t
+(*dns_sdlzfindzone_t)(void *driverarg, void *dbdata, const char *name);
+
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface MUST
+ * supply a find zone method. This method is called when the DNS
+ * server is performing a query to to determine if 'name' is a
+ * supported dns zone. The find zone method will be called with the
+ * longest possible name first, and continue to be called with
+ * successively shorter domain names, until any of the following
+ * occur:
+ *
+ * \li 1) the function returns (ISC_R_SUCCESS) indicating a zone name
+ * match.
+ *
+ * \li 2) a problem occurs, and the functions returns anything other than
+ * (ISC_R_NOTFOUND)
+ *
+ * \li 3) we run out of domain name labels. I.E. we have tried the
+ * shortest domain name
+ *
+ * \li 4) the number of labels in the domain name is less than min_lables
+ * for dns_dlzfindzone
+ *
+ * The driver's find zone method should return ISC_R_SUCCESS if the
+ * zone is supported by the database. Otherwise it should return
+ * ISC_R_NOTFOUND, if the zone is not supported. If an error occurs
+ * it should return a result code indicating the type of error.
+ */
+
+typedef isc_result_t
+(*dns_sdlzlookupfunc_t)(const char *zone, const char *name, void *driverarg,
+ void *dbdata, dns_sdlzlookup_t *lookup);
+
+/*%<
+ * Method prototype. Drivers implementing the SDLZ interface MUST
+ * supply a lookup method. This method is called when the DNS server
+ * is performing a query, after the find zone and before any other
+ * methods have been called. This function returns record DNS record
+ * information using the dns_sdlz_putrr and dns_sdlz_putsoa functions.
+ * If this function supplies authority information for the DNS record
+ * the authority method is not required. If it does not, the
+ * authority function is required. A SDLZ driver must implement a
+ * lookup method.
+ */
+
+typedef struct dns_sdlzmethods {
+ dns_sdlzcreate_t create;
+ dns_sdlzdestroy_t destroy;
+ dns_sdlzfindzone_t findzone;
+ dns_sdlzlookupfunc_t lookup;
+ dns_sdlzauthorityfunc_t authority;
+ dns_sdlzallnodesfunc_t allnodes;
+ dns_sdlzallowzonexfr_t allowzonexfr;
+} dns_sdlzmethods_t;
+
+isc_result_t
+dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
+ void *driverarg, unsigned int flags, isc_mem_t *mctx,
+ dns_sdlzimplementation_t **sdlzimp);
+/*%<
+ * Register a dynamically loadable zones (dlz) driver for the database
+ * type 'drivername', implemented by the functions in '*methods'.
+ *
+ * sdlzimp must point to a NULL dns_sdlzimplementation_t pointer.
+ * That is, sdlzimp != NULL && *sdlzimp == NULL. It will be assigned
+ * a value that will later be used to identify the driver when
+ * deregistering it.
+ */
+
+void
+dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp);
+
+/*%<
+ * Removes the sdlz driver from the list of registered sdlz drivers.
+ * There must be no active sdlz drivers of this type when this
+ * function is called.
+ */
+
+isc_result_t
+dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
+ const char *type, dns_ttl_t ttl, const char *data);
+/*%<
+ * Add a single resource record to the allnodes structure to be later
+ * parsed into a zone transfer response.
+ */
+
+isc_result_t
+dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
+ const char *data);
+/*%<
+ * Add a single resource record to the lookup structure to be later
+ * parsed into a query response.
+ */
+
+isc_result_t
+dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
+ isc_uint32_t serial);
+/*%<
+ * This function may optionally be called from the 'authority'
+ * callback to simplify construction of the SOA record for 'zone'. It
+ * will provide a SOA listing 'mname' as as the master server and
+ * 'rname' as the responsible person mailbox. It is the
+ * responsibility of the driver to increment the serial number between
+ * responses if necessary. All other SOA fields will have reasonable
+ * default values.
+ */
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* SDLZ_H */
diff --git a/lib/dns/include/dns/secalg.h b/lib/dns/include/dns/secalg.h
new file mode 100644
index 0000000..2e4fe3e
--- /dev/null
+++ b/lib/dns/include/dns/secalg.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: secalg.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_SECALG_H
+#define DNS_SECALG_H 1
+
+/*! \file dns/secalg.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source);
+/*%<
+ * Convert the text 'source' refers to into a DNSSEC security algorithm value.
+ * The text may contain either a mnemonic algorithm name or a decimal algorithm
+ * number.
+ *
+ * Requires:
+ *\li 'secalgp' is a valid pointer.
+ *
+ *\li 'source' is a valid text region.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS on success
+ *\li ISC_R_RANGE numeric type is out of range
+ *\li DNS_R_UNKNOWN mnemonic type is unknown
+ */
+
+isc_result_t
+dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target);
+/*%<
+ * Put a textual representation of the DNSSEC security algorithm 'secalg'
+ * into 'target'.
+ *
+ * Requires:
+ *\li 'secalg' is a valid secalg.
+ *
+ *\li 'target' is a valid text buffer.
+ *
+ * Ensures,
+ * if the result is success:
+ *\li The used space in 'target' is updated.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS on success
+ *\li ISC_R_NOSPACE target buffer is too small
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_SECALG_H */
diff --git a/lib/dns/include/dns/secproto.h b/lib/dns/include/dns/secproto.h
new file mode 100644
index 0000000..b9179c0
--- /dev/null
+++ b/lib/dns/include/dns/secproto.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: secproto.h,v 1.16 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_SECPROTO_H
+#define DNS_SECPROTO_H 1
+
+/*! \file dns/secproto.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source);
+/*%<
+ * Convert the text 'source' refers to into a DNSSEC security protocol value.
+ * The text may contain either a mnemonic protocol name or a decimal protocol
+ * number.
+ *
+ * Requires:
+ *\li 'secprotop' is a valid pointer.
+ *
+ *\li 'source' is a valid text region.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS on success
+ *\li ISC_R_RANGE numeric type is out of range
+ *\li DNS_R_UNKNOWN mnemonic type is unknown
+ */
+
+isc_result_t
+dns_secproto_totext(dns_secproto_t secproto, isc_buffer_t *target);
+/*%<
+ * Put a textual representation of the DNSSEC security protocol 'secproto'
+ * into 'target'.
+ *
+ * Requires:
+ *\li 'secproto' is a valid secproto.
+ *
+ *\li 'target' is a valid text buffer.
+ *
+ * Ensures,
+ * if the result is success:
+ * \li The used space in 'target' is updated.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS on success
+ *\li ISC_R_NOSPACE target buffer is too small
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_SECPROTO_H */
diff --git a/lib/dns/include/dns/soa.h b/lib/dns/include/dns/soa.h
new file mode 100644
index 0000000..bb56365
--- /dev/null
+++ b/lib/dns/include/dns/soa.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2007 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: soa.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_SOA_H
+#define DNS_SOA_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/soa.h
+ * \brief
+ * SOA utilities.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_uint32_t
+dns_soa_getserial(dns_rdata_t *rdata);
+isc_uint32_t
+dns_soa_getrefresh(dns_rdata_t *rdata);
+isc_uint32_t
+dns_soa_getretry(dns_rdata_t *rdata);
+isc_uint32_t
+dns_soa_getexpire(dns_rdata_t *rdata);
+isc_uint32_t
+dns_soa_getminimum(dns_rdata_t *rdata);
+/*
+ * Extract an integer field from the rdata of a SOA record.
+ *
+ * Requires:
+ * rdata refers to the rdata of a well-formed SOA record.
+ */
+
+void
+dns_soa_setserial(isc_uint32_t val, dns_rdata_t *rdata);
+void
+dns_soa_setrefresh(isc_uint32_t val, dns_rdata_t *rdata);
+void
+dns_soa_setretry(isc_uint32_t val, dns_rdata_t *rdata);
+void
+dns_soa_setexpire(isc_uint32_t val, dns_rdata_t *rdata);
+void
+dns_soa_setminimum(isc_uint32_t val, dns_rdata_t *rdata);
+/*
+ * Change an integer field of a SOA record by modifying the
+ * rdata in-place.
+ *
+ * Requires:
+ * rdata refers to the rdata of a well-formed SOA record.
+ */
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_SOA_H */
diff --git a/lib/dns/include/dns/ssu.h b/lib/dns/include/dns/ssu.h
new file mode 100644
index 0000000..f013bd0
--- /dev/null
+++ b/lib/dns/include/dns/ssu.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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.h,v 1.24 2008/01/18 23:46:58 tbox Exp $ */
+
+#ifndef DNS_SSU_H
+#define DNS_SSU_H 1
+
+/*! \file dns/ssu.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+#define DNS_SSUMATCHTYPE_NAME 0
+#define DNS_SSUMATCHTYPE_SUBDOMAIN 1
+#define DNS_SSUMATCHTYPE_WILDCARD 2
+#define DNS_SSUMATCHTYPE_SELF 3
+#define DNS_SSUMATCHTYPE_SELFSUB 4
+#define DNS_SSUMATCHTYPE_SELFWILD 5
+#define DNS_SSUMATCHTYPE_SELFKRB5 6
+#define DNS_SSUMATCHTYPE_SELFMS 7
+#define DNS_SSUMATCHTYPE_SUBDOMAINMS 8
+#define DNS_SSUMATCHTYPE_SUBDOMAINKRB5 9
+#define DNS_SSUMATCHTYPE_TCPSELF 10
+#define DNS_SSUMATCHTYPE_6TO4SELF 11
+#define DNS_SSUMATCHTYPE_MAX 11 /* max value */
+
+isc_result_t
+dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **table);
+/*%<
+ * Creates a table that will be used to store simple-secure-update rules.
+ * Note: all locking must be provided by the client.
+ *
+ * Requires:
+ *\li 'mctx' is a valid memory context
+ *\li 'table' is not NULL, and '*table' is NULL
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOMEMORY
+ */
+
+void
+dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp);
+/*%<
+ * Attach '*targetp' to 'source'.
+ *
+ * Requires:
+ *\li 'source' is a valid SSU table
+ *\li 'targetp' points to a NULL dns_ssutable_t *.
+ *
+ * Ensures:
+ *\li *targetp is attached to source.
+ */
+
+void
+dns_ssutable_detach(dns_ssutable_t **tablep);
+/*%<
+ * Detach '*tablep' from its simple-secure-update rule table.
+ *
+ * Requires:
+ *\li 'tablep' points to a valid dns_ssutable_t
+ *
+ * Ensures:
+ *\li *tablep is NULL
+ *\li If '*tablep' is the last reference to the SSU table, all
+ * resources used by the table will be freed.
+ */
+
+isc_result_t
+dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
+ dns_name_t *identity, unsigned int matchtype,
+ dns_name_t *name, unsigned int ntypes,
+ dns_rdatatype_t *types);
+/*%<
+ * Adds a new rule to a simple-secure-update rule table. The rule
+ * either grants or denies update privileges of an identity (or set of
+ * identities) to modify a name (or set of names) or certain types present
+ * at that name.
+ *
+ * Notes:
+ *\li If 'matchtype' is of SELF type, this rule only matches if the
+ * name to be updated matches the signing identity.
+ *
+ *\li If 'ntypes' is 0, this rule applies to all types except
+ * NS, SOA, RRSIG, and NSEC.
+ *
+ *\li If 'types' includes ANY, this rule applies to all types
+ * except NSEC.
+ *
+ * Requires:
+ *\li 'table' is a valid SSU table
+ *\li 'identity' is a valid absolute name
+ *\li 'matchtype' must be one of the defined constants.
+ *\li 'name' is a valid absolute name
+ *\li If 'ntypes' > 0, 'types' must not be NULL
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOMEMORY
+ */
+
+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);
+/*%<
+ * Checks that the attempted update of (name, type) is allowed according
+ * to the rules specified in the simple-secure-update rule table. If
+ * no rules are matched, access is denied.
+ *
+ * Notes:
+ * 'tcpaddr' should only be set if the request received
+ * via TCP. This provides a weak assurance that the
+ * request was not spoofed. 'tcpaddr' is to to validate
+ * DNS_SSUMATCHTYPE_TCPSELF and DNS_SSUMATCHTYPE_6TO4SELF
+ * rules.
+ *
+ * For DNS_SSUMATCHTYPE_TCPSELF the addresses are mapped to
+ * the standard reverse names under IN-ADDR.ARPA and IP6.ARPA.
+ * RFC 1035, Section 3.5, "IN-ADDR.ARPA domain" and RFC 3596,
+ * Section 2.5, "IP6.ARPA Domain".
+ *
+ * For DNS_SSUMATCHTYPE_6TO4SELF, IPv4 address are converted
+ * to a 6to4 prefix (48 bits) per the rules in RFC 3056. Only
+ * the top 48 bits of the IPv6 address are mapped to the reverse
+ * name. This is independent of whether the most significant 16
+ * bits match 2002::/16, assigned for 6to4 prefixes, or not.
+ *
+ * Requires:
+ *\li 'table' is a valid SSU table
+ *\li 'signer' is NULL or a valid absolute name
+ *\li 'tcpaddr' is NULL or a valid network address.
+ *\li 'name' is a valid absolute name
+ */
+
+
+/*% Accessor functions to extract rule components */
+isc_boolean_t dns_ssurule_isgrant(const dns_ssurule_t *rule);
+/*% Accessor functions to extract rule components */
+dns_name_t * dns_ssurule_identity(const dns_ssurule_t *rule);
+/*% Accessor functions to extract rule components */
+unsigned int dns_ssurule_matchtype(const dns_ssurule_t *rule);
+/*% Accessor functions to extract rule components */
+dns_name_t * dns_ssurule_name(const dns_ssurule_t *rule);
+/*% Accessor functions to extract rule components */
+unsigned int dns_ssurule_types(const dns_ssurule_t *rule,
+ dns_rdatatype_t **types);
+
+isc_result_t dns_ssutable_firstrule(const dns_ssutable_t *table,
+ dns_ssurule_t **rule);
+/*%<
+ * Initiates a rule iterator. There is no need to maintain any state.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMORE
+ */
+
+isc_result_t dns_ssutable_nextrule(dns_ssurule_t *rule,
+ dns_ssurule_t **nextrule);
+/*%<
+ * Returns the next rule in the table.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMORE
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_SSU_H */
diff --git a/lib/dns/include/dns/stats.h b/lib/dns/include/dns/stats.h
new file mode 100644
index 0000000..8f8e38a
--- /dev/null
+++ b/lib/dns/include/dns/stats.h
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: stats.h,v 1.18 2008/09/08 05:59:11 marka Exp $ */
+
+#ifndef DNS_STATS_H
+#define DNS_STATS_H 1
+
+/*! \file dns/stats.h */
+
+#include <dns/types.h>
+
+/*%
+ * Statistics counters. Used as dns_statscounter_t values.
+ */
+enum {
+ /*%
+ * Resolver statistics counters.
+ */
+ dns_resstatscounter_queryv4 = 0,
+ dns_resstatscounter_queryv6 = 1,
+ dns_resstatscounter_responsev4 = 2,
+ dns_resstatscounter_responsev6 = 3,
+ dns_resstatscounter_nxdomain = 4,
+ dns_resstatscounter_servfail = 5,
+ dns_resstatscounter_formerr = 6,
+ dns_resstatscounter_othererror = 7,
+ dns_resstatscounter_edns0fail = 8,
+ dns_resstatscounter_mismatch = 9,
+ dns_resstatscounter_truncated = 10,
+ dns_resstatscounter_lame = 11,
+ dns_resstatscounter_retry = 12,
+ dns_resstatscounter_gluefetchv4 = 13,
+ dns_resstatscounter_gluefetchv6 = 14,
+ dns_resstatscounter_gluefetchv4fail = 15,
+ dns_resstatscounter_gluefetchv6fail = 16,
+ dns_resstatscounter_val = 17,
+ dns_resstatscounter_valsuccess = 18,
+ dns_resstatscounter_valnegsuccess = 19,
+ dns_resstatscounter_valfail = 20,
+
+ dns_resstatscounter_max = 21,
+
+ /*%
+ * Zone statistics counters.
+ */
+ dns_zonestatscounter_notifyoutv4 = 0,
+ dns_zonestatscounter_notifyoutv6 = 1,
+ dns_zonestatscounter_notifyinv4 = 2,
+ dns_zonestatscounter_notifyinv6 = 3,
+ dns_zonestatscounter_notifyrej = 4,
+ dns_zonestatscounter_soaoutv4 = 5,
+ dns_zonestatscounter_soaoutv6 = 6,
+ dns_zonestatscounter_axfrreqv4 = 7,
+ dns_zonestatscounter_axfrreqv6 = 8,
+ dns_zonestatscounter_ixfrreqv4 = 9,
+ dns_zonestatscounter_ixfrreqv6 = 10,
+ dns_zonestatscounter_xfrsuccess = 11,
+ dns_zonestatscounter_xfrfail = 12,
+
+ dns_zonestatscounter_max = 13,
+
+ /*%
+ * Query statistics counters (obsolete).
+ */
+ dns_statscounter_success = 0, /*%< Successful lookup */
+ dns_statscounter_referral = 1, /*%< Referral result */
+ dns_statscounter_nxrrset = 2, /*%< NXRRSET result */
+ dns_statscounter_nxdomain = 3, /*%< NXDOMAIN result */
+ dns_statscounter_recursion = 4, /*%< Recursion was used */
+ dns_statscounter_failure = 5, /*%< Some other failure */
+ dns_statscounter_duplicate = 6, /*%< Duplicate query */
+ dns_statscounter_dropped = 7 /*%< Duplicate query (dropped) */
+};
+
+#define DNS_STATS_NCOUNTERS 8
+
+/*%<
+ * Flag(s) for dns_xxxstats_dump().
+ */
+#define DNS_STATSDUMP_VERBOSE 0x00000001 /*%< dump 0-value counters */
+
+/*%<
+ * (Obsoleted)
+ */
+LIBDNS_EXTERNAL_DATA extern const char *dns_statscounter_names[];
+
+/*%
+ * Attributes for statistics counters of RRset and Rdatatype types.
+ *
+ * _OTHERTYPE
+ * The rdata type is not explicitly supported and the corresponding counter
+ * is counted for other such types, too. When this attribute is set,
+ * the base type is of no use.
+ *
+ * _NXRRSET
+ * RRset type counters only. Indicates the RRset is non existent.
+ *
+ * _NXDOMAIN
+ * RRset type counters only. Indicates a non existent name. When this
+ * attribute is set, the base type is of no use.
+ */
+#define DNS_RDATASTATSTYPE_ATTR_OTHERTYPE 0x0001
+#define DNS_RDATASTATSTYPE_ATTR_NXRRSET 0x0002
+#define DNS_RDATASTATSTYPE_ATTR_NXDOMAIN 0x0004
+
+/*%<
+ * Conversion macros among dns_rdatatype_t, attributes and dns_statscounter_t.
+ */
+#define DNS_RDATASTATSTYPE_BASE(type) ((dns_rdatatype_t)((type) & 0xFFFF))
+#define DNS_RDATASTATSTYPE_ATTR(type) ((type) >> 16)
+#define DNS_RDATASTATSTYPE_VALUE(b, a) (((a) << 16) | (b))
+
+/*%<
+ * Types of dump callbacks.
+ */
+typedef void (*dns_generalstats_dumper_t)(dns_statscounter_t, isc_uint64_t,
+ void *);
+typedef void (*dns_rdatatypestats_dumper_t)(dns_rdatastatstype_t, isc_uint64_t,
+ void *);
+typedef void (*dns_opcodestats_dumper_t)(dns_opcode_t, isc_uint64_t, void *);
+
+isc_result_t
+dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters);
+/*%<
+ * Create a statistics counter structure of general type. It counts a general
+ * set of counters indexed by an ID between 0 and ncounters -1.
+ *
+ * Requires:
+ *\li 'mctx' must be a valid memory context.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- all ok
+ *
+ *\li anything else -- failure
+ */
+
+isc_result_t
+dns_rdatatypestats_create(isc_mem_t *mctx, dns_stats_t **statsp);
+/*%<
+ * Create a statistics counter structure per rdatatype.
+ *
+ * Requires:
+ *\li 'mctx' must be a valid memory context.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- all ok
+ *
+ *\li anything else -- failure
+ */
+
+isc_result_t
+dns_rdatasetstats_create(isc_mem_t *mctx, dns_stats_t **statsp);
+/*%<
+ * Create a statistics counter structure per RRset.
+ *
+ * Requires:
+ *\li 'mctx' must be a valid memory context.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- all ok
+ *
+ *\li anything else -- failure
+ */
+
+isc_result_t
+dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp);
+/*%<
+ * Create a statistics counter structure per opcode.
+ *
+ * Requires:
+ *\li 'mctx' must be a valid memory context.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS -- all ok
+ *
+ *\li anything else -- failure
+ */
+
+void
+dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp);
+/*%<
+ * Attach to a statistics set.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t.
+ *
+ *\li 'statsp' != NULL && '*statsp' == NULL
+ */
+
+void
+dns_stats_detach(dns_stats_t **statsp);
+/*%<
+ * Detaches from the statistics set.
+ *
+ * Requires:
+ *\li 'statsp' != NULL and '*statsp' is a valid dns_stats_t.
+ */
+
+void
+dns_generalstats_increment(dns_stats_t *stats, dns_statscounter_t counter);
+/*%<
+ * Increment the counter-th counter of stats.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ *
+ *\li counter is less than the maximum available ID for the stats specified
+ * on creation.
+ */
+
+void
+dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type);
+/*%<
+ * Increment the statistics counter for 'type'.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_rdatatypestats_create().
+ */
+
+void
+dns_rdatasetstats_increment(dns_stats_t *stats, dns_rdatastatstype_t rrsettype);
+/*%<
+ * Increment the statistics counter for 'rrsettype'.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_rdatasetstats_create().
+ */
+
+void
+dns_rdatasetstats_decrement(dns_stats_t *stats, dns_rdatastatstype_t rrsettype);
+/*%<
+ * Decrement the statistics counter for 'rrsettype'.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_rdatasetstats_create().
+ */
+
+void
+dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code);
+/*%<
+ * Increment the statistics counter for 'code'.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_opcodestats_create().
+ */
+
+void
+dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
+ void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way. For each counter
+ * in stats, dump_fn is called with its current value and the given argument
+ * arg. By default counters that have a value of 0 is skipped; if options has
+ * the DNS_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+void
+dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+ void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way. For each counter
+ * in stats, dump_fn is called with the corresponding type in the form of
+ * dns_rdatastatstype_t, the current counter value and the given argument
+ * arg. By default counters that have a value of 0 is skipped; if options has
+ * the DNS_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+void
+dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+ void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way. For each counter
+ * in stats, dump_fn is called with the corresponding type in the form of
+ * dns_rdatastatstype_t, the current counter value and the given argument
+ * arg. By default counters that have a value of 0 is skipped; if options has
+ * the DNS_STATSDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+void
+dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
+ void *arg, unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way. For each counter
+ * in stats, dump_fn is called with the corresponding opcode, the current
+ * counter value and the given argument arg. By default counters that have a
+ * value of 0 is skipped; if options has the DNS_STATSDUMP_VERBOSE flag, even
+ * such counters are dumped.
+ *
+ * Requires:
+ *\li 'stats' is a valid dns_stats_t created by dns_generalstats_create().
+ */
+
+isc_result_t
+dns_stats_alloccounters(isc_mem_t *mctx, isc_uint64_t **ctrp);
+/*%<
+ * Allocate an array of query statistics counters from the memory
+ * context 'mctx'.
+ *
+ * This function is obsoleted. Use dns_xxxstats_create() instead.
+ */
+
+void
+dns_stats_freecounters(isc_mem_t *mctx, isc_uint64_t **ctrp);
+/*%<
+ * Free an array of query statistics counters allocated from the memory
+ * context 'mctx'.
+ *
+ * This function is obsoleted. Use dns_stats_destroy() instead.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_STATS_H */
diff --git a/lib/dns/include/dns/tcpmsg.h b/lib/dns/include/dns/tcpmsg.h
new file mode 100644
index 0000000..fe83c53
--- /dev/null
+++ b/lib/dns/include/dns/tcpmsg.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: tcpmsg.h,v 1.22 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_TCPMSG_H
+#define DNS_TCPMSG_H 1
+
+/*! \file dns/tcpmsg.h */
+
+#include <isc/buffer.h>
+#include <isc/lang.h>
+#include <isc/socket.h>
+
+typedef struct dns_tcpmsg {
+ /* private (don't touch!) */
+ unsigned int magic;
+ isc_uint16_t size;
+ isc_buffer_t buffer;
+ unsigned int maxsize;
+ isc_mem_t *mctx;
+ isc_socket_t *sock;
+ isc_task_t *task;
+ isc_taskaction_t action;
+ void *arg;
+ isc_event_t event;
+ /* public (read-only) */
+ isc_result_t result;
+ isc_sockaddr_t address;
+} dns_tcpmsg_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+dns_tcpmsg_init(isc_mem_t *mctx, isc_socket_t *sock, dns_tcpmsg_t *tcpmsg);
+/*%<
+ * Associate a tcp message state with a given memory context and
+ * TCP socket.
+ *
+ * Requires:
+ *
+ *\li "mctx" and "sock" be non-NULL and valid types.
+ *
+ *\li "sock" be a read/write TCP socket.
+ *
+ *\li "tcpmsg" be non-NULL and an uninitialized or invalidated structure.
+ *
+ * Ensures:
+ *
+ *\li "tcpmsg" is a valid structure.
+ */
+
+void
+dns_tcpmsg_setmaxsize(dns_tcpmsg_t *tcpmsg, unsigned int maxsize);
+/*%<
+ * Set the maximum packet size to "maxsize"
+ *
+ * Requires:
+ *
+ *\li "tcpmsg" be valid.
+ *
+ *\li 512 <= "maxsize" <= 65536
+ */
+
+isc_result_t
+dns_tcpmsg_readmessage(dns_tcpmsg_t *tcpmsg,
+ isc_task_t *task, isc_taskaction_t action, void *arg);
+/*%<
+ * Schedule an event to be delivered when a DNS message is readable, or
+ * when an error occurs on the socket.
+ *
+ * Requires:
+ *
+ *\li "tcpmsg" be valid.
+ *
+ *\li "task", "taskaction", and "arg" be valid.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS -- no error
+ *\li Anything that the isc_socket_recv() call can return. XXXMLG
+ *
+ * Notes:
+ *
+ *\li The event delivered is a fully generic event. It will contain no
+ * actual data. The sender will be a pointer to the dns_tcpmsg_t.
+ * The result code inside that structure should be checked to see
+ * what the final result was.
+ */
+
+void
+dns_tcpmsg_cancelread(dns_tcpmsg_t *tcpmsg);
+/*%<
+ * Cancel a readmessage() call. The event will still be posted with a
+ * CANCELED result code.
+ *
+ * Requires:
+ *
+ *\li "tcpmsg" be valid.
+ */
+
+void
+dns_tcpmsg_keepbuffer(dns_tcpmsg_t *tcpmsg, isc_buffer_t *buffer);
+/*%<
+ * If a dns buffer is to be kept between calls, this function marks the
+ * internal state-machine buffer as invalid, and copies all the contents
+ * of the state into "buffer".
+ *
+ * Requires:
+ *
+ *\li "tcpmsg" be valid.
+ *
+ *\li "buffer" be non-NULL.
+ */
+
+void
+dns_tcpmsg_invalidate(dns_tcpmsg_t *tcpmsg);
+/*%<
+ * Clean up all allocated state, and invalidate the structure.
+ *
+ * Requires:
+ *
+ *\li "tcpmsg" be valid.
+ *
+ * Ensures:
+ *
+ *\li "tcpmsg" is invalidated and disassociated with all memory contexts,
+ * sockets, etc.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_TCPMSG_H */
diff --git a/lib/dns/include/dns/time.h b/lib/dns/include/dns/time.h
new file mode 100644
index 0000000..5b47d11
--- /dev/null
+++ b/lib/dns/include/dns/time.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: time.h,v 1.17 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_TIME_H
+#define DNS_TIME_H 1
+
+/*! \file dns/time.h */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/buffer.h>
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+dns_time64_fromtext(const char *source, isc_int64_t *target);
+/*%<
+ * Convert a date and time in YYYYMMDDHHMMSS text format at 'source'
+ * into to a 64-bit count of seconds since Jan 1 1970 0:00 GMT.
+ * Store the count at 'target'.
+ */
+
+isc_result_t
+dns_time32_fromtext(const char *source, isc_uint32_t *target);
+/*%<
+ * Like dns_time64_fromtext, but returns the second count modulo 2^32
+ * as per RFC2535.
+ */
+
+
+isc_result_t
+dns_time64_totext(isc_int64_t value, isc_buffer_t *target);
+/*%<
+ * Convert a 64-bit count of seconds since Jan 1 1970 0:00 GMT into
+ * a YYYYMMDDHHMMSS text representation and append it to 'target'.
+ */
+
+isc_result_t
+dns_time32_totext(isc_uint32_t value, isc_buffer_t *target);
+/*%<
+ * Like dns_time64_totext, but for a 32-bit cyclic time value.
+ * Of those dates whose counts of seconds since Jan 1 1970 0:00 GMT
+ * are congruent with 'value' modulo 2^32, the one closest to the
+ * current date is chosen.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_TIME_H */
diff --git a/lib/dns/include/dns/timer.h b/lib/dns/include/dns/timer.h
new file mode 100644
index 0000000..48d6d56
--- /dev/null
+++ b/lib/dns/include/dns/timer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004-2007 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: timer.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_TIMER_H
+#define DNS_TIMER_H 1
+
+/*! \file dns/timer.h */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/buffer.h>
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+dns_timer_setidle(isc_timer_t *timer, unsigned int maxtime,
+ unsigned int idletime, isc_boolean_t purge);
+/*%<
+ * Convenience function for setting up simple, one-second-granularity
+ * idle timers as used by zone transfers.
+ * \brief
+ * Set the timer 'timer' to go off after 'idletime' seconds of inactivity,
+ * or after 'maxtime' at the very latest. Events are purged iff
+ * 'purge' is ISC_TRUE.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_TIMER_H */
diff --git a/lib/dns/include/dns/tkey.h b/lib/dns/include/dns/tkey.h
new file mode 100644
index 0000000..1eecc98
--- /dev/null
+++ b/lib/dns/include/dns/tkey.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: tkey.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_TKEY_H
+#define DNS_TKEY_H 1
+
+/*! \file dns/tkey.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+#include <dst/dst.h>
+#include <dst/gssapi.h>
+
+ISC_LANG_BEGINDECLS
+
+/* Key agreement modes */
+#define DNS_TKEYMODE_SERVERASSIGNED 1
+#define DNS_TKEYMODE_DIFFIEHELLMAN 2
+#define DNS_TKEYMODE_GSSAPI 3
+#define DNS_TKEYMODE_RESOLVERASSIGNED 4
+#define DNS_TKEYMODE_DELETE 5
+
+struct dns_tkeyctx {
+ dst_key_t *dhkey;
+ dns_name_t *domain;
+ gss_cred_id_t gsscred;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+};
+
+isc_result_t
+dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx,
+ dns_tkeyctx_t **tctxp);
+/*%<
+ * Create an empty TKEY context.
+ *
+ * Requires:
+ *\li 'mctx' is not NULL
+ *\li 'tctx' is not NULL
+ *\li '*tctx' is NULL
+ *
+ * Returns
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li return codes from dns_name_fromtext()
+ */
+
+void
+dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp);
+/*%<
+ * Frees all data associated with the TKEY context
+ *
+ * Requires:
+ *\li 'tctx' is not NULL
+ *\li '*tctx' is not NULL
+ */
+
+isc_result_t
+dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
+ dns_tsig_keyring_t *ring);
+/*%<
+ * Processes a query containing a TKEY record, adding or deleting TSIG
+ * keys if necessary, and modifies the message to contain the response.
+ *
+ * Requires:
+ *\li 'msg' is a valid message
+ *\li 'tctx' is a valid TKEY context
+ *\li 'ring' is a valid TSIG keyring
+ *
+ * Returns
+ *\li #ISC_R_SUCCESS msg was updated (the TKEY operation succeeded,
+ * or msg now includes a TKEY with an error set)
+ * DNS_R_FORMERR the packet was malformed (missing a TKEY
+ * or KEY).
+ *\li other An error occurred while processing the message
+ */
+
+isc_result_t
+dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
+ dns_name_t *algorithm, isc_buffer_t *nonce,
+ isc_uint32_t lifetime);
+/*%<
+ * Builds a query containing a TKEY that will generate a shared
+ * secret using a Diffie-Hellman key exchange. The shared key
+ * will be of the specified algorithm (only DNS_TSIG_HMACMD5_NAME
+ * is supported), and will be named either 'name',
+ * 'name' + server chosen domain, or random data + server chosen domain
+ * if 'name' == dns_rootname. If nonce is not NULL, it supplies
+ * random data used in the shared secret computation. The key is
+ * requested to have the specified lifetime (in seconds)
+ *
+ *
+ * Requires:
+ *\li 'msg' is a valid message
+ *\li 'key' is a valid Diffie Hellman dst key
+ *\li 'name' is a valid name
+ *\li 'algorithm' is a valid name
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ *\li other an error occurred while building the message
+ */
+
+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);
+/*%<
+ * Builds a query containing a TKEY that will generate a GSSAPI context.
+ * The key is requested to have the specified lifetime (in seconds).
+ *
+ * Requires:
+ *\li 'msg' is a valid message
+ *\li 'name' is a valid name
+ *\li 'gname' is a valid name
+ *\li 'context' is a pointer to a valid gss_ctx_id_t
+ * (which may have the value GSS_C_NO_CONTEXT)
+ *\li 'win2k' when true says to turn on some hacks to work
+ * with the non-standard GSS-TSIG of Windows 2000
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ *\li other an error occurred while building the message
+ */
+
+
+isc_result_t
+dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key);
+/*%<
+ * Builds a query containing a TKEY record that will delete the
+ * specified shared secret from the server.
+ *
+ * Requires:
+ *\li 'msg' is a valid message
+ *\li 'key' is a valid TSIG key
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ *\li other an error occurred while building the message
+ */
+
+isc_result_t
+dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
+ dst_key_t *key, isc_buffer_t *nonce,
+ dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring);
+/*%<
+ * Processes a response to a query containing a TKEY that was
+ * designed to generate a shared secret using a Diffie-Hellman key
+ * exchange. If the query was successful, a new shared key
+ * is created and added to the list of shared keys.
+ *
+ * Requires:
+ *\li 'qmsg' is a valid message (the query)
+ *\li 'rmsg' is a valid message (the response)
+ *\li 'key' is a valid Diffie Hellman dst key
+ *\li 'outkey' is either NULL or a pointer to NULL
+ *\li 'ring' is a valid keyring or NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS the shared key was successfully added
+ *\li #ISC_R_NOTFOUND an error occurred while looking for a
+ * component of the query or response
+ */
+
+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);
+/*%<
+ * XXX
+ */
+
+isc_result_t
+dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
+ dns_tsig_keyring_t *ring);
+/*%<
+ * Processes a response to a query containing a TKEY that was
+ * designed to delete a shared secret. If the query was successful,
+ * the shared key is deleted from the list of shared keys.
+ *
+ * Requires:
+ *\li 'qmsg' is a valid message (the query)
+ *\li 'rmsg' is a valid message (the response)
+ *\li 'ring' is not NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS the shared key was successfully deleted
+ *\li #ISC_R_NOTFOUND an error occurred while looking for a
+ * 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);
+
+/*
+ * Client side negotiation of GSS-TSIG. Process the respsonse
+ * to a TKEY, and establish a TSIG key if negotiation was successful.
+ * Build a response to the input TKEY message. Can take multiple
+ * calls to successfully establish the context.
+ *
+ * Requires:
+ * 'qmsg' is a valid message, the original TKEY request;
+ * it will be filled with the new message to send
+ * 'rmsg' is a valid message, the incoming TKEY message
+ * 'server' is the server name
+ * 'context' is the input context handle
+ * 'outkey' receives the established key, if non-NULL;
+ * if non-NULL must point to NULL
+ * 'ring' is the keyring in which to establish the key,
+ * or NULL
+ * 'win2k' when true says to turn on some hacks to work
+ * with the non-standard GSS-TSIG of Windows 2000
+ *
+ * Returns:
+ * ISC_R_SUCCESS context was successfully established
+ * ISC_R_NOTFOUND couldn't find a needed part of the query
+ * or response
+ * DNS_R_CONTINUE additional context negotiation is required;
+ * send the new qmsg to the server
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_TKEY_H */
diff --git a/lib/dns/include/dns/tsig.h b/lib/dns/include/dns/tsig.h
new file mode 100644
index 0000000..e8c0e2c
--- /dev/null
+++ b/lib/dns/include/dns/tsig.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: tsig.h,v 1.51 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_TSIG_H
+#define DNS_TSIG_H 1
+
+/*! \file dns/tsig.h */
+
+#include <isc/lang.h>
+#include <isc/refcount.h>
+#include <isc/rwlock.h>
+#include <isc/stdtime.h>
+
+#include <dns/types.h>
+#include <dns/name.h>
+
+#include <dst/dst.h>
+
+/*
+ * Algorithms.
+ */
+LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacmd5_name;
+#define DNS_TSIG_HMACMD5_NAME dns_tsig_hmacmd5_name
+LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_gssapi_name;
+#define DNS_TSIG_GSSAPI_NAME dns_tsig_gssapi_name
+LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_gssapims_name;
+#define DNS_TSIG_GSSAPIMS_NAME dns_tsig_gssapims_name
+LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha1_name;
+#define DNS_TSIG_HMACSHA1_NAME dns_tsig_hmacsha1_name
+LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha224_name;
+#define DNS_TSIG_HMACSHA224_NAME dns_tsig_hmacsha224_name
+LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha256_name;
+#define DNS_TSIG_HMACSHA256_NAME dns_tsig_hmacsha256_name
+LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha384_name;
+#define DNS_TSIG_HMACSHA384_NAME dns_tsig_hmacsha384_name
+LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_tsig_hmacsha512_name;
+#define DNS_TSIG_HMACSHA512_NAME dns_tsig_hmacsha512_name
+
+/*%
+ * Default fudge value.
+ */
+#define DNS_TSIG_FUDGE 300
+
+struct dns_tsig_keyring {
+ dns_rbt_t *keys;
+ unsigned int writecount;
+ isc_rwlock_t lock;
+ isc_mem_t *mctx;
+};
+
+struct dns_tsigkey {
+ /* Unlocked */
+ unsigned int magic; /*%< Magic number. */
+ isc_mem_t *mctx;
+ dst_key_t *key; /*%< Key */
+ dns_name_t name; /*%< Key name */
+ dns_name_t *algorithm; /*%< Algorithm name */
+ dns_name_t *creator; /*%< name that created secret */
+ isc_boolean_t generated; /*%< was this generated? */
+ isc_stdtime_t inception; /*%< start of validity period */
+ isc_stdtime_t expire; /*%< end of validity period */
+ dns_tsig_keyring_t *ring; /*%< the enclosing keyring */
+ isc_refcount_t refs; /*%< reference counter */
+};
+
+#define dns_tsigkey_identity(tsigkey) \
+ ((tsigkey) == NULL ? NULL : \
+ (tsigkey)->generated ? ((tsigkey)->creator) : \
+ (&((tsigkey)->name)))
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
+ unsigned char *secret, int length, isc_boolean_t generated,
+ dns_name_t *creator, isc_stdtime_t inception,
+ isc_stdtime_t expire, isc_mem_t *mctx,
+ dns_tsig_keyring_t *ring, dns_tsigkey_t **key);
+
+isc_result_t
+dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
+ dst_key_t *dstkey, isc_boolean_t generated,
+ dns_name_t *creator, isc_stdtime_t inception,
+ isc_stdtime_t expire, isc_mem_t *mctx,
+ dns_tsig_keyring_t *ring, dns_tsigkey_t **key);
+/*%<
+ * Creates a tsig key structure and saves it in the keyring. If key is
+ * not NULL, *key will contain a copy of the key. The keys validity
+ * period is specified by (inception, expire), and will not expire if
+ * inception == expire. If the key was generated, the creating identity,
+ * if there is one, should be in the creator parameter. Specifying an
+ * unimplemented algorithm will cause failure only if dstkey != NULL; this
+ * allows a transient key with an invalid algorithm to exist long enough
+ * to generate a BADKEY response.
+ *
+ * Requires:
+ *\li 'name' is a valid dns_name_t
+ *\li 'algorithm' is a valid dns_name_t
+ *\li 'secret' is a valid pointer
+ *\li 'length' is an integer >= 0
+ *\li 'key' is a valid dst key or NULL
+ *\li 'creator' points to a valid dns_name_t or is NULL
+ *\li 'mctx' is a valid memory context
+ *\li 'ring' is a valid TSIG keyring or NULL
+ *\li 'key' or '*key' must be NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_EXISTS - a key with this name already exists
+ *\li #ISC_R_NOTIMPLEMENTED - algorithm is not implemented
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp);
+/*%<
+ * Attach '*targetp' to 'source'.
+ *
+ * Requires:
+ *\li 'key' is a valid TSIG key
+ *
+ * Ensures:
+ *\li *targetp is attached to source.
+ */
+
+void
+dns_tsigkey_detach(dns_tsigkey_t **keyp);
+/*%<
+ * Detaches from the tsig key structure pointed to by '*key'.
+ *
+ * Requires:
+ *\li 'keyp' is not NULL and '*keyp' is a valid TSIG key
+ *
+ * Ensures:
+ *\li 'keyp' points to NULL
+ */
+
+void
+dns_tsigkey_setdeleted(dns_tsigkey_t *key);
+/*%<
+ * Prevents this key from being used again. It will be deleted when
+ * no references exist.
+ *
+ * Requires:
+ *\li 'key' is a valid TSIG key on a keyring
+ */
+
+isc_result_t
+dns_tsig_sign(dns_message_t *msg);
+/*%<
+ * Generates a TSIG record for this message
+ *
+ * Requires:
+ *\li 'msg' is a valid message
+ *\li 'msg->tsigkey' is a valid TSIG key
+ *\li 'msg->tsig' is NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_NOSPACE
+ *\li #DNS_R_EXPECTEDTSIG
+ * - this is a response & msg->querytsig is NULL
+ */
+
+isc_result_t
+dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
+ dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2);
+/*%<
+ * Verifies the TSIG record in this message
+ *
+ * Requires:
+ *\li 'source' is a valid buffer containing the unparsed message
+ *\li 'msg' is a valid message
+ *\li 'msg->tsigkey' is a valid TSIG key if this is a response
+ *\li 'msg->tsig' is NULL
+ *\li 'msg->querytsig' is not NULL if this is a response
+ *\li 'ring1' and 'ring2' are each either a valid keyring or NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #DNS_R_EXPECTEDTSIG - A TSIG was expected but not seen
+ *\li #DNS_R_UNEXPECTEDTSIG - A TSIG was seen but not expected
+ *\li #DNS_R_TSIGERRORSET - the TSIG verified but ->error was set
+ * and this is a query
+ *\li #DNS_R_CLOCKSKEW - the TSIG failed to verify because of
+ * the time was out of the allowed range.
+ *\li #DNS_R_TSIGVERIFYFAILURE - the TSIG failed to verify
+ *\li #DNS_R_EXPECTEDRESPONSE - the message was set over TCP and
+ * should have been a response,
+ * but was not.
+ */
+
+isc_result_t
+dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
+ dns_name_t *algorithm, dns_tsig_keyring_t *ring);
+/*%<
+ * Returns the TSIG key corresponding to this name and (possibly)
+ * algorithm. Also increments the key's reference counter.
+ *
+ * Requires:
+ *\li 'tsigkey' is not NULL
+ *\li '*tsigkey' is NULL
+ *\li 'name' is a valid dns_name_t
+ *\li 'algorithm' is a valid dns_name_t or NULL
+ *\li 'ring' is a valid keyring
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOTFOUND
+ */
+
+
+isc_result_t
+dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp);
+/*%<
+ * Create an empty TSIG key ring.
+ *
+ * Requires:
+ *\li 'mctx' is not NULL
+ *\li 'ringp' is not NULL, and '*ringp' is NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+
+void
+dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp);
+/*%<
+ * Destroy a TSIG key ring.
+ *
+ * Requires:
+ *\li 'ringp' is not NULL
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_TSIG_H */
diff --git a/lib/dns/include/dns/ttl.h b/lib/dns/include/dns/ttl.h
new file mode 100644
index 0000000..c252518
--- /dev/null
+++ b/lib/dns/include/dns/ttl.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: ttl.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_TTL_H
+#define DNS_TTL_H 1
+
+/*! \file dns/ttl.h */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+dns_ttl_totext(isc_uint32_t src, isc_boolean_t verbose,
+ isc_buffer_t *target);
+/*%<
+ * Output a TTL or other time interval in a human-readable form.
+ * The time interval is given as a count of seconds in 'src'.
+ * The text representation is appended to 'target'.
+ *
+ * If 'verbose' is ISC_FALSE, use the terse BIND 8 style, like "1w2d3h4m5s".
+ *
+ * If 'verbose' is ISC_TRUE, use a verbose style like the SOA comments
+ * in "dig", like "1 week 2 days 3 hours 4 minutes 5 seconds".
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOSPACE
+ */
+
+isc_result_t
+dns_counter_fromtext(isc_textregion_t *source, isc_uint32_t *ttl);
+/*%<
+ * Converts a counter from either a plain number or a BIND 8 style value.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li DNS_R_SYNTAX
+ */
+
+isc_result_t
+dns_ttl_fromtext(isc_textregion_t *source, isc_uint32_t *ttl);
+/*%<
+ * Converts a ttl from either a plain number or a BIND 8 style value.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li DNS_R_BADTTL
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_TTL_H */
diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h
new file mode 100644
index 0000000..5223397
--- /dev/null
+++ b/lib/dns/include/dns/types.h
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: types.h,v 1.130 2008/09/24 02:46:23 marka Exp $ */
+
+#ifndef DNS_TYPES_H
+#define DNS_TYPES_H 1
+
+/*! \file dns/types.h
+ * \brief
+ * Including this file gives you type declarations suitable for use in
+ * .h files, which lets us avoid circular type reference problems.
+ * \brief
+ * To actually use a type or get declarations of its methods, you must
+ * include the appropriate .h file too.
+ */
+
+#include <isc/types.h>
+
+typedef struct dns_acache dns_acache_t;
+typedef struct dns_acacheentry dns_acacheentry_t;
+typedef struct dns_acachestats dns_acachestats_t;
+typedef struct dns_acl dns_acl_t;
+typedef struct dns_aclelement dns_aclelement_t;
+typedef struct dns_aclenv dns_aclenv_t;
+typedef struct dns_adb dns_adb_t;
+typedef struct dns_adbaddrinfo dns_adbaddrinfo_t;
+typedef ISC_LIST(dns_adbaddrinfo_t) dns_adbaddrinfolist_t;
+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_cache dns_cache_t;
+typedef isc_uint16_t dns_cert_t;
+typedef struct dns_compress dns_compress_t;
+typedef struct dns_db dns_db_t;
+typedef struct dns_dbimplementation dns_dbimplementation_t;
+typedef struct dns_dbiterator dns_dbiterator_t;
+typedef void dns_dbload_t;
+typedef void dns_dbnode_t;
+typedef struct dns_dbtable dns_dbtable_t;
+typedef void dns_dbversion_t;
+typedef struct dns_dlzimplementation dns_dlzimplementation_t;
+typedef struct dns_dlzdb dns_dlzdb_t;
+typedef struct dns_sdlzimplementation dns_sdlzimplementation_t;
+typedef struct dns_decompress dns_decompress_t;
+typedef struct dns_dispatch dns_dispatch_t;
+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_dumpctx dns_dumpctx_t;
+typedef struct dns_fetch dns_fetch_t;
+typedef struct dns_fixedname dns_fixedname_t;
+typedef struct dns_forwarders dns_forwarders_t;
+typedef struct dns_fwdtable dns_fwdtable_t;
+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 struct dns_keytable dns_keytable_t;
+typedef isc_uint16_t dns_keytag_t;
+typedef struct dns_loadctx dns_loadctx_t;
+typedef struct dns_loadmgr dns_loadmgr_t;
+typedef struct dns_message dns_message_t;
+typedef isc_uint16_t dns_messageid_t;
+typedef isc_region_t dns_label_t;
+typedef struct dns_lookup dns_lookup_t;
+typedef struct dns_name dns_name_t;
+typedef ISC_LIST(dns_name_t) dns_namelist_t;
+typedef isc_uint16_t dns_opcode_t;
+typedef unsigned char dns_offsets_t[128];
+typedef struct dns_order dns_order_t;
+typedef struct dns_peer dns_peer_t;
+typedef struct dns_peerlist dns_peerlist_t;
+typedef struct dns_portlist dns_portlist_t;
+typedef struct dns_rbt dns_rbt_t;
+typedef isc_uint16_t dns_rcode_t;
+typedef struct dns_rdata dns_rdata_t;
+typedef struct dns_rdatacallbacks dns_rdatacallbacks_t;
+typedef isc_uint16_t dns_rdataclass_t;
+typedef struct dns_rdatalist dns_rdatalist_t;
+typedef struct dns_rdataset dns_rdataset_t;
+typedef ISC_LIST(dns_rdataset_t) dns_rdatasetlist_t;
+typedef struct dns_rdatasetiter dns_rdatasetiter_t;
+typedef isc_uint16_t dns_rdatatype_t;
+typedef struct dns_request dns_request_t;
+typedef struct dns_requestmgr dns_requestmgr_t;
+typedef struct dns_resolver dns_resolver_t;
+typedef struct dns_sdbimplementation dns_sdbimplementation_t;
+typedef isc_uint8_t dns_secalg_t;
+typedef isc_uint8_t dns_secproto_t;
+typedef struct dns_signature dns_signature_t;
+typedef struct dns_ssurule dns_ssurule_t;
+typedef struct dns_ssutable dns_ssutable_t;
+typedef struct dns_stats dns_stats_t;
+typedef int dns_statscounter_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_tsig_keyring dns_tsig_keyring_t;
+typedef struct dns_tsigkey dns_tsigkey_t;
+typedef isc_uint32_t dns_ttl_t;
+typedef struct dns_validator dns_validator_t;
+typedef struct dns_view dns_view_t;
+typedef ISC_LIST(dns_view_t) dns_viewlist_t;
+typedef struct dns_zone dns_zone_t;
+typedef ISC_LIST(dns_zone_t) dns_zonelist_t;
+typedef struct dns_zonemgr dns_zonemgr_t;
+typedef struct dns_zt dns_zt_t;
+
+/*
+ * If we are not using GSSAPI, define the types we use as opaque types here.
+ */
+#ifndef GSSAPI
+typedef struct not_defined_gss_cred_id *gss_cred_id_t;
+typedef struct not_defined_gss_ctx *gss_ctx_id_t;
+#endif
+typedef struct dst_gssapi_signverifyctx dst_gssapi_signverifyctx_t;
+
+typedef enum {
+ dns_hash_sha1 = 1
+} dns_hash_t;
+
+typedef enum {
+ dns_fwdpolicy_none = 0,
+ dns_fwdpolicy_first = 1,
+ dns_fwdpolicy_only = 2
+} dns_fwdpolicy_t;
+
+typedef enum {
+ dns_namereln_none = 0,
+ dns_namereln_contains = 1,
+ dns_namereln_subdomain = 2,
+ dns_namereln_equal = 3,
+ dns_namereln_commonancestor = 4
+} dns_namereln_t;
+
+typedef enum {
+ dns_one_answer, dns_many_answers
+} dns_transfer_format_t;
+
+typedef enum {
+ dns_dbtype_zone = 0, dns_dbtype_cache = 1, dns_dbtype_stub = 3
+} dns_dbtype_t;
+
+typedef enum {
+ dns_notifytype_no = 0,
+ dns_notifytype_yes = 1,
+ dns_notifytype_explicit = 2,
+ dns_notifytype_masteronly = 3
+} dns_notifytype_t;
+
+typedef enum {
+ dns_dialuptype_no = 0,
+ dns_dialuptype_yes = 1,
+ dns_dialuptype_notify = 2,
+ dns_dialuptype_notifypassive = 3,
+ dns_dialuptype_refresh = 4,
+ dns_dialuptype_passive = 5
+} dns_dialuptype_t;
+
+typedef enum {
+ dns_masterformat_none = 0,
+ dns_masterformat_text = 1,
+ dns_masterformat_raw = 2
+} dns_masterformat_t;
+
+/*
+ * These are generated by gen.c.
+ */
+#include <dns/enumtype.h> /* Provides dns_rdatatype_t. */
+#include <dns/enumclass.h> /* Provides dns_rdataclass_t. */
+
+/*%
+ * rcodes.
+ */
+enum {
+ /*
+ * Standard rcodes.
+ */
+ dns_rcode_noerror = 0,
+#define dns_rcode_noerror ((dns_rcode_t)dns_rcode_noerror)
+ dns_rcode_formerr = 1,
+#define dns_rcode_formerr ((dns_rcode_t)dns_rcode_formerr)
+ dns_rcode_servfail = 2,
+#define dns_rcode_servfail ((dns_rcode_t)dns_rcode_servfail)
+ dns_rcode_nxdomain = 3,
+#define dns_rcode_nxdomain ((dns_rcode_t)dns_rcode_nxdomain)
+ dns_rcode_notimp = 4,
+#define dns_rcode_notimp ((dns_rcode_t)dns_rcode_notimp)
+ dns_rcode_refused = 5,
+#define dns_rcode_refused ((dns_rcode_t)dns_rcode_refused)
+ dns_rcode_yxdomain = 6,
+#define dns_rcode_yxdomain ((dns_rcode_t)dns_rcode_yxdomain)
+ dns_rcode_yxrrset = 7,
+#define dns_rcode_yxrrset ((dns_rcode_t)dns_rcode_yxrrset)
+ dns_rcode_nxrrset = 8,
+#define dns_rcode_nxrrset ((dns_rcode_t)dns_rcode_nxrrset)
+ dns_rcode_notauth = 9,
+#define dns_rcode_notauth ((dns_rcode_t)dns_rcode_notauth)
+ dns_rcode_notzone = 10,
+#define dns_rcode_notzone ((dns_rcode_t)dns_rcode_notzone)
+ /*
+ * Extended rcodes.
+ */
+ dns_rcode_badvers = 16
+#define dns_rcode_badvers ((dns_rcode_t)dns_rcode_badvers)
+};
+
+/*%
+ * TSIG errors.
+ */
+enum {
+ dns_tsigerror_badsig = 16,
+ dns_tsigerror_badkey = 17,
+ dns_tsigerror_badtime = 18,
+ dns_tsigerror_badmode = 19,
+ dns_tsigerror_badname = 20,
+ dns_tsigerror_badalg = 21,
+ dns_tsigerror_badtrunc = 22
+};
+
+/*%
+ * Opcodes.
+ */
+enum {
+ dns_opcode_query = 0,
+#define dns_opcode_query ((dns_opcode_t)dns_opcode_query)
+ dns_opcode_iquery = 1,
+#define dns_opcode_iquery ((dns_opcode_t)dns_opcode_iquery)
+ dns_opcode_status = 2,
+#define dns_opcode_status ((dns_opcode_t)dns_opcode_status)
+ dns_opcode_notify = 4,
+#define dns_opcode_notify ((dns_opcode_t)dns_opcode_notify)
+ dns_opcode_update = 5 /* dynamic update */
+#define dns_opcode_update ((dns_opcode_t)dns_opcode_update)
+};
+
+/*%
+ * Trust levels. Must be kept in sync with trustnames[] in masterdump.c.
+ */
+enum {
+ /* Sentinel value; no data should have this trust level. */
+ dns_trust_none = 0,
+#define dns_trust_none ((dns_trust_t)dns_trust_none)
+
+ /*% Subject to DNSSEC validation but has not yet been validated */
+ dns_trust_pending = 1,
+#define dns_trust_pending ((dns_trust_t)dns_trust_pending)
+
+ /*% Received in the additional section of a response. */
+ dns_trust_additional = 2,
+#define dns_trust_additional ((dns_trust_t)dns_trust_additional)
+
+ /* Received in a referral response. */
+ dns_trust_glue = 3,
+#define dns_trust_glue ((dns_trust_t)dns_trust_glue)
+
+ /* Answser from a non-authoritative server */
+ dns_trust_answer = 4,
+#define dns_trust_answer ((dns_trust_t)dns_trust_answer)
+
+ /* Received in the authority section as part of an
+ authoritative response */
+ dns_trust_authauthority = 5,
+#define dns_trust_authauthority ((dns_trust_t)dns_trust_authauthority)
+
+ /* Answser from an authoritative server */
+ dns_trust_authanswer = 6,
+#define dns_trust_authanswer ((dns_trust_t)dns_trust_authanswer)
+
+ /* Successfully DNSSEC validated */
+ dns_trust_secure = 7,
+#define dns_trust_secure ((dns_trust_t)dns_trust_secure)
+
+ /* This server is authoritative */
+ dns_trust_ultimate = 8
+#define dns_trust_ultimate ((dns_trust_t)dns_trust_ultimate)
+};
+
+/*%
+ * Name checking severites.
+ */
+typedef enum {
+ dns_severity_ignore,
+ dns_severity_warn,
+ dns_severity_fail
+} dns_severity_t;
+
+/*
+ * Functions.
+ */
+typedef void
+(*dns_dumpdonefunc_t)(void *, isc_result_t);
+
+typedef void
+(*dns_loaddonefunc_t)(void *, isc_result_t);
+
+typedef isc_result_t
+(*dns_addrdatasetfunc_t)(void *, dns_name_t *, dns_rdataset_t *);
+
+typedef isc_result_t
+(*dns_additionaldatafunc_t)(void *, dns_name_t *, dns_rdatatype_t);
+
+typedef isc_result_t
+(*dns_digestfunc_t)(void *, isc_region_t *);
+
+typedef void
+(*dns_xfrindone_t)(dns_zone_t *, isc_result_t);
+
+typedef void
+(*dns_updatecallback_t)(void *, isc_result_t, dns_message_t *);
+
+typedef int
+(*dns_rdatasetorderfunc_t)(const dns_rdata_t *, const void *);
+
+typedef isc_boolean_t
+(*dns_checkmxfunc_t)(dns_zone_t *, dns_name_t *, dns_name_t *);
+
+typedef isc_boolean_t
+(*dns_checksrvfunc_t)(dns_zone_t *, dns_name_t *, dns_name_t *);
+
+typedef isc_boolean_t
+(*dns_checknsfunc_t)(dns_zone_t *, dns_name_t *, dns_name_t *,
+ dns_rdataset_t *, dns_rdataset_t *);
+
+typedef isc_boolean_t
+(*dns_isselffunc_t)(dns_view_t *, dns_tsigkey_t *, isc_sockaddr_t *,
+ isc_sockaddr_t *, dns_rdataclass_t, void *);
+
+#endif /* DNS_TYPES_H */
diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h
new file mode 100644
index 0000000..0a2417b
--- /dev/null
+++ b/lib/dns/include/dns/validator.h
@@ -0,0 +1,255 @@
+/*
+ * 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
+ * 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: validator.h,v 1.41 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef DNS_VALIDATOR_H
+#define DNS_VALIDATOR_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/validator.h
+ *
+ * \brief
+ * DNS Validator
+ * This is the BIND 9 validator, the module responsible for validating the
+ * rdatasets and negative responses (messages). It makes use of zones in
+ * the view and may fetch RRset to complete trust chains. It implements
+ * DNSSEC as specified in RFC 4033, 4034 and 4035.
+ *
+ * It can also optionally implement ISC's DNSSEC look-aside validation.
+ *
+ * Correct operation is critical to preventing spoofed answers from secure
+ * zones being accepted.
+ *
+ * MP:
+ *\li The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li RFCs: 1034, 1035, 2181, 4033, 4034, 4035.
+ */
+
+#include <isc/lang.h>
+#include <isc/event.h>
+#include <isc/mutex.h>
+
+#include <dns/fixedname.h>
+#include <dns/types.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h> /* for dns_rdata_rrsig_t */
+
+#include <dst/dst.h>
+
+/*%
+ * A dns_validatorevent_t is sent when a 'validation' completes.
+ * \brief
+ * 'name', 'rdataset', 'sigrdataset', and 'message' are the values that were
+ * supplied when dns_validator_create() was called. They are returned to the
+ * caller so that they may be freed.
+ *
+ * If the RESULT is ISC_R_SUCCESS and the answer is secure then
+ * proofs[] will contain the the names of the NSEC records that hold the
+ * various proofs. Note the same name may appear multiple times.
+ */
+typedef struct dns_validatorevent {
+ ISC_EVENT_COMMON(struct dns_validatorevent);
+ dns_validator_t * validator;
+ isc_result_t result;
+ /*
+ * Name and type of the response to be validated.
+ */
+ dns_name_t * name;
+ dns_rdatatype_t type;
+ /*
+ * Rdata and RRSIG (if any) for positive responses.
+ */
+ dns_rdataset_t * rdataset;
+ dns_rdataset_t * sigrdataset;
+ /*
+ * The full response. Required for negative responses.
+ * Also required for positive wildcard responses.
+ */
+ dns_message_t * message;
+ /*
+ * Proofs to be cached.
+ */
+ dns_name_t * proofs[4];
+ /*
+ * Optout proof seen.
+ */
+ isc_boolean_t optout;
+} dns_validatorevent_t;
+
+#define DNS_VALIDATOR_NOQNAMEPROOF 0
+#define DNS_VALIDATOR_NODATAPROOF 1
+#define DNS_VALIDATOR_NOWILDCARDPROOF 2
+#define DNS_VALIDATOR_CLOSESTENCLOSER 3
+
+/*%
+ * A validator object represents a validation in progress.
+ * \brief
+ * Clients are strongly discouraged from using this type directly, with
+ * the exception of the 'link' field, which may be used directly for
+ * whatever purpose the client desires.
+ */
+struct dns_validator {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mutex_t lock;
+ dns_view_t * view;
+ /* Locked by lock. */
+ unsigned int options;
+ unsigned int attributes;
+ dns_validatorevent_t * event;
+ dns_fetch_t * fetch;
+ dns_validator_t * subvalidator;
+ dns_validator_t * parent;
+ dns_keytable_t * keytable;
+ dns_keynode_t * keynode;
+ dst_key_t * key;
+ dns_rdata_rrsig_t * siginfo;
+ isc_task_t * task;
+ isc_taskaction_t action;
+ void * arg;
+ unsigned int labels;
+ dns_rdataset_t * currentset;
+ isc_boolean_t seensig;
+ dns_rdataset_t * keyset;
+ dns_rdataset_t * dsset;
+ dns_rdataset_t * soaset;
+ dns_rdataset_t * nsecset;
+ dns_rdataset_t * nsec3set;
+ dns_name_t * soaname;
+ dns_rdataset_t frdataset;
+ dns_rdataset_t fsigrdataset;
+ dns_fixedname_t fname;
+ dns_fixedname_t wild;
+ dns_fixedname_t nearest;
+ dns_fixedname_t closest;
+ ISC_LINK(dns_validator_t) link;
+ dns_rdataset_t dlv;
+ dns_fixedname_t dlvsep;
+ isc_boolean_t havedlvsep;
+ isc_boolean_t mustbesecure;
+ unsigned int dlvlabels;
+ unsigned int depth;
+};
+
+/*%
+ * dns_validator_create() options.
+ */
+#define DNS_VALIDATOR_DLV 1U
+#define DNS_VALIDATOR_DEFER 2U
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_message_t *message, unsigned int options,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_validator_t **validatorp);
+/*%<
+ * Start a DNSSEC validation.
+ *
+ * This validates a response to the question given by
+ * 'name' and 'type'.
+ *
+ * To validate a positive response, the response data is
+ * given by 'rdataset' and 'sigrdataset'. If 'sigrdataset'
+ * is NULL, the data is presumed insecure and an attempt
+ * is made to prove its insecurity by finding the appropriate
+ * null key.
+ *
+ * The complete response message may be given in 'message',
+ * to make available any authority section NSECs that may be
+ * needed for validation of a response resulting from a
+ * wildcard expansion (though no such wildcard validation
+ * is implemented yet). If the complete response message
+ * is not available, 'message' is NULL.
+ *
+ * To validate a negative response, the complete negative response
+ * message is given in 'message'. The 'rdataset', and
+ * 'sigrdataset' arguments must be NULL, but the 'name' and 'type'
+ * arguments must be provided.
+ *
+ * The validation is performed in the context of 'view'.
+ *
+ * When the validation finishes, a dns_validatorevent_t with
+ * the given 'action' and 'arg' are sent to 'task'.
+ * Its 'result' field will be ISC_R_SUCCESS iff the
+ * response was successfully proven to be either secure or
+ * part of a known insecure domain.
+ *
+ * options:
+ * If DNS_VALIDATOR_DLV is set the caller knows there is not a
+ * trusted key and the validator should immediately attempt to validate
+ * the answer by looking for a appopriate DLV RRset.
+ */
+
+void
+dns_validator_send(dns_validator_t *validator);
+/*%<
+ * Send a deferred validation request
+ *
+ * Requires:
+ * 'validator' to points to a valid DNSSEC validator.
+ */
+
+void
+dns_validator_cancel(dns_validator_t *validator);
+/*%<
+ * Cancel a DNSSEC validation in progress.
+ *
+ * Requires:
+ *\li 'validator' points to a valid DNSSEC validator, which
+ * may or may not already have completed.
+ *
+ * Ensures:
+ *\li It the validator has not already sent its completion
+ * event, it will send it with result code ISC_R_CANCELED.
+ */
+
+void
+dns_validator_destroy(dns_validator_t **validatorp);
+/*%<
+ * Destroy a DNSSEC validator.
+ *
+ * Requires:
+ *\li '*validatorp' points to a valid DNSSEC validator.
+ * \li The validator must have completed and sent its completion
+ * event.
+ *
+ * Ensures:
+ *\li All resources used by the validator are freed.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_VALIDATOR_H */
diff --git a/lib/dns/include/dns/version.h b/lib/dns/include/dns/version.h
new file mode 100644
index 0000000..2a33dcf
--- /dev/null
+++ b/lib/dns/include/dns/version.h
@@ -0,0 +1,28 @@
+/*
+ * 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: version.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file dns/version.h */
+
+#include <isc/platform.h>
+
+LIBDNS_EXTERNAL_DATA extern const char dns_version[];
+
+LIBDNS_EXTERNAL_DATA extern const unsigned int dns_libinterface;
+LIBDNS_EXTERNAL_DATA extern const unsigned int dns_librevision;
+LIBDNS_EXTERNAL_DATA extern const unsigned int dns_libage;
diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h
new file mode 100644
index 0000000..8329523
--- /dev/null
+++ b/lib/dns/include/dns/view.h
@@ -0,0 +1,879 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: view.h,v 1.111 2008/05/21 23:17:21 each Exp $ */
+
+#ifndef DNS_VIEW_H
+#define DNS_VIEW_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/view.h
+ * \brief
+ * DNS View
+ *
+ * A "view" is a DNS namespace, together with an optional resolver and a
+ * forwarding policy. A "DNS namespace" is a (possibly empty) set of
+ * authoritative zones together with an optional cache and optional
+ * "hints" information.
+ *
+ * Views start out "unfrozen". In this state, core attributes like
+ * the cache, set of zones, and forwarding policy may be set. While
+ * "unfrozen", the caller (e.g. nameserver configuration loading
+ * code), must ensure exclusive access to the view. When the view is
+ * "frozen", the core attributes become immutable, and the view module
+ * will ensure synchronization. Freezing allows the view's core attributes
+ * to be accessed without locking.
+ *
+ * MP:
+ *\li Before the view is frozen, the caller must ensure synchronization.
+ *
+ *\li After the view is frozen, the module guarantees appropriate
+ * synchronization of any data structures it creates and manipulates.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li None.
+ */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/event.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/refcount.h>
+#include <isc/rwlock.h>
+#include <isc/stdtime.h>
+
+#include <dns/acl.h>
+#include <dns/fixedname.h>
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+struct dns_view {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ dns_rdataclass_t rdclass;
+ char * name;
+ dns_zt_t * zonetable;
+ dns_dlzdb_t * dlzdatabase;
+ dns_resolver_t * resolver;
+ dns_adb_t * adb;
+ dns_requestmgr_t * requestmgr;
+ dns_acache_t * acache;
+ dns_cache_t * cache;
+ dns_db_t * cachedb;
+ dns_db_t * hints;
+ dns_keytable_t * secroots;
+ dns_keytable_t * trustedkeys;
+ isc_mutex_t lock;
+ isc_boolean_t frozen;
+ isc_task_t * task;
+ isc_event_t resevent;
+ isc_event_t adbevent;
+ isc_event_t reqevent;
+ dns_stats_t * resstats;
+ dns_stats_t * resquerystats;
+
+ /* Configurable data. */
+ dns_tsig_keyring_t * statickeys;
+ dns_tsig_keyring_t * dynamickeys;
+ dns_peerlist_t * peers;
+ dns_order_t * order;
+ dns_fwdtable_t * fwdtable;
+ isc_boolean_t recursion;
+ isc_boolean_t auth_nxdomain;
+ isc_boolean_t additionalfromcache;
+ isc_boolean_t additionalfromauth;
+ isc_boolean_t minimalresponses;
+ isc_boolean_t enablednssec;
+ isc_boolean_t enablevalidation;
+ isc_boolean_t acceptexpired;
+ dns_transfer_format_t transfer_format;
+ dns_acl_t * queryacl;
+ dns_acl_t * queryonacl;
+ dns_acl_t * recursionacl;
+ dns_acl_t * recursiononacl;
+ dns_acl_t * sortlist;
+ dns_acl_t * notifyacl;
+ dns_acl_t * transferacl;
+ dns_acl_t * updateacl;
+ dns_acl_t * upfwdacl;
+ isc_boolean_t requestixfr;
+ isc_boolean_t provideixfr;
+ isc_boolean_t requestnsid;
+ dns_ttl_t maxcachettl;
+ dns_ttl_t maxncachettl;
+ in_port_t dstport;
+ dns_aclenv_t aclenv;
+ dns_rdatatype_t preferred_glue;
+ isc_boolean_t flush;
+ dns_namelist_t * delonly;
+ isc_boolean_t rootdelonly;
+ dns_namelist_t * rootexclude;
+ isc_boolean_t checknames;
+ dns_name_t * dlv;
+ dns_fixedname_t dlv_fixed;
+ isc_uint16_t maxudp;
+
+ /*
+ * Configurable data for server use only,
+ * locked by server configuration lock.
+ */
+ dns_acl_t * matchclients;
+ dns_acl_t * matchdestinations;
+ isc_boolean_t matchrecursiveonly;
+
+ /* Locked by themselves. */
+ isc_refcount_t references;
+
+ /* Locked by lock. */
+ unsigned int weakrefs;
+ unsigned int attributes;
+ /* Under owner's locking control. */
+ ISC_LINK(struct dns_view) link;
+};
+
+#define DNS_VIEW_MAGIC ISC_MAGIC('V','i','e','w')
+#define DNS_VIEW_VALID(view) ISC_MAGIC_VALID(view, DNS_VIEW_MAGIC)
+
+#define DNS_VIEWATTR_RESSHUTDOWN 0x01
+#define DNS_VIEWATTR_ADBSHUTDOWN 0x02
+#define DNS_VIEWATTR_REQSHUTDOWN 0x04
+
+isc_result_t
+dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
+ const char *name, dns_view_t **viewp);
+/*%<
+ * Create a view.
+ *
+ * Notes:
+ *
+ *\li The newly created view has no cache, no resolver, and an empty
+ * zone table. The view is not frozen.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'rdclass' is a valid class.
+ *
+ *\li 'name' is a valid C string.
+ *
+ *\li viewp != NULL && *viewp == NULL
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *
+ *\li Other errors are possible.
+ */
+
+void
+dns_view_attach(dns_view_t *source, dns_view_t **targetp);
+/*%<
+ * Attach '*targetp' to 'source'.
+ *
+ * Requires:
+ *
+ *\li 'source' is a valid, frozen view.
+ *
+ *\li 'targetp' points to a NULL dns_view_t *.
+ *
+ * Ensures:
+ *
+ *\li *targetp is attached to source.
+ *
+ *\li While *targetp is attached, the view will not shut down.
+ */
+
+void
+dns_view_detach(dns_view_t **viewp);
+/*%<
+ * Detach '*viewp' from its view.
+ *
+ * Requires:
+ *
+ *\li 'viewp' points to a valid dns_view_t *
+ *
+ * Ensures:
+ *
+ *\li *viewp is NULL.
+ */
+
+void
+dns_view_flushanddetach(dns_view_t **viewp);
+/*%<
+ * Detach '*viewp' from its view. If this was the last reference
+ * uncommited changed in zones will be flushed to disk.
+ *
+ * Requires:
+ *
+ *\li 'viewp' points to a valid dns_view_t *
+ *
+ * Ensures:
+ *
+ *\li *viewp is NULL.
+ */
+
+void
+dns_view_weakattach(dns_view_t *source, dns_view_t **targetp);
+/*%<
+ * Weakly attach '*targetp' to 'source'.
+ *
+ * Requires:
+ *
+ *\li 'source' is a valid, frozen view.
+ *
+ *\li 'targetp' points to a NULL dns_view_t *.
+ *
+ * Ensures:
+ *
+ *\li *targetp is attached to source.
+ *
+ * \li While *targetp is attached, the view will not be freed.
+ */
+
+void
+dns_view_weakdetach(dns_view_t **targetp);
+/*%<
+ * Detach '*viewp' from its view.
+ *
+ * Requires:
+ *
+ *\li 'viewp' points to a valid dns_view_t *.
+ *
+ * Ensures:
+ *
+ *\li *viewp is NULL.
+ */
+
+isc_result_t
+dns_view_createresolver(dns_view_t *view,
+ isc_taskmgr_t *taskmgr, unsigned int ntasks,
+ isc_socketmgr_t *socketmgr,
+ isc_timermgr_t *timermgr,
+ unsigned int options,
+ dns_dispatchmgr_t *dispatchmgr,
+ dns_dispatch_t *dispatchv4,
+ dns_dispatch_t *dispatchv6);
+/*%<
+ * Create a resolver and address database for the view.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid, unfrozen view.
+ *
+ *\li 'view' does not have a resolver already.
+ *
+ *\li The requirements of dns_resolver_create() apply to 'taskmgr',
+ * 'ntasks', 'socketmgr', 'timermgr', 'options', 'dispatchv4', and
+ * 'dispatchv6'.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *
+ *\li Any error that dns_resolver_create() can return.
+ */
+
+void
+dns_view_setcache(dns_view_t *view, dns_cache_t *cache);
+/*%<
+ * Set the view's cache database.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid, unfrozen view.
+ *
+ *\li 'cache' is a valid cache.
+ *
+ * Ensures:
+ *
+ * \li The cache of 'view' is 'cached.
+ *
+ *\li If this is not the first call to dns_view_setcache() for this
+ * view, then previously set cache is detached.
+ */
+
+void
+dns_view_sethints(dns_view_t *view, dns_db_t *hints);
+/*%<
+ * Set the view's hints database.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid, unfrozen view, whose hints database has not been
+ * set.
+ *
+ *\li 'hints' is a valid zone database.
+ *
+ * Ensures:
+ *
+ * \li The hints database of 'view' is 'hints'.
+ */
+
+void
+dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring);
+/*%<
+ * Set the view's static TSIG keys
+ *
+ * Requires:
+ *
+ * \li 'view' is a valid, unfrozen view, whose static TSIG keyring has not
+ * been set.
+ *
+ *\li 'ring' is a valid TSIG keyring
+ *
+ * Ensures:
+ *
+ *\li The static TSIG keyring of 'view' is 'ring'.
+ */
+
+void
+dns_view_setdstport(dns_view_t *view, in_port_t dstport);
+/*%<
+ * Set the view's destination port. This is the port to
+ * which outgoing queries are sent. The default is 53,
+ * the standard DNS port.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid view.
+ *
+ *\li 'dstport' is a valid TCP/UDP port number.
+ *
+ * Ensures:
+ *\li External name servers will be assumed to be listning
+ * on 'dstport'. For servers whose address has already
+ * obtained obtained at the time of the call, the view may
+ * continue to use the previously set port until the address
+ * times out from the view's address database.
+ */
+
+
+isc_result_t
+dns_view_addzone(dns_view_t *view, dns_zone_t *zone);
+/*%<
+ * Add zone 'zone' to 'view'.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid, unfrozen view.
+ *
+ *\li 'zone' is a valid zone.
+ */
+
+void
+dns_view_freeze(dns_view_t *view);
+/*%<
+ * Freeze view.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid, unfrozen view.
+ *
+ * Ensures:
+ *
+ *\li 'view' is 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);
+/*%<
+ * Find an rdataset whose owner name is 'name', and whose type is
+ * 'type'.
+ *
+ * Notes:
+ *
+ *\li See the description of dns_db_find() for information about 'options'.
+ * If the caller sets #DNS_DBFIND_GLUEOK, it must ensure that 'name'
+ * and 'type' are appropriate for glue retrieval.
+ *
+ *\li If 'now' is zero, then the current time will be used.
+ *
+ *\li If 'use_hints' is ISC_TRUE, and the view has a hints database, then
+ * it will be searched last. If the answer is found in the hints
+ * database, the result code will be DNS_R_HINT. If the name is found
+ * in the hints database but not the type, the result code will be
+ * #DNS_R_HINTNXRRSET.
+ *
+ *\li 'foundname' must meet the requirements of dns_db_find().
+ *
+ *\li If 'sigrdataset' is not NULL, and there is a SIG rdataset which
+ * covers 'type', then 'sigrdataset' will be bound to it.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid, frozen view.
+ *
+ *\li 'name' is valid name.
+ *
+ *\li 'type' is a valid dns_rdatatype_t, and is not a meta query type
+ * except dns_rdatatype_any.
+ *
+ *\li dbp == NULL || *dbp == NULL
+ *
+ *\li nodep == NULL || *nodep == NULL. If nodep != NULL, dbp != NULL.
+ *
+ *\li 'foundname' is a valid name with a dedicated buffer or NULL.
+ *
+ *\li 'rdataset' is a valid, disassociated rdataset.
+ *
+ *\li 'sigrdataset' is NULL, or is a valid, disassociated rdataset.
+ *
+ * Ensures:
+ *
+ *\li In successful cases, 'rdataset', and possibly 'sigrdataset', are
+ * bound to the found data.
+ *
+ *\li If dbp != NULL, it points to the database containing the data.
+ *
+ *\li If nodep != NULL, it points to the database node containing the data.
+ *
+ *\li If foundname != NULL, it contains the full name of the found data.
+ *
+ * Returns:
+ *
+ *\li Any result that dns_db_find() can return, with the exception of
+ * #DNS_R_DELEGATION.
+ */
+
+isc_result_t
+dns_view_simplefind(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_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
+/*%<
+ * Find an rdataset whose owner name is 'name', and whose type is
+ * 'type'.
+ *
+ * Notes:
+ *
+ *\li This routine is appropriate for simple, exact-match queries of the
+ * view. 'name' must be a canonical name; there is no DNAME or CNAME
+ * processing.
+ *
+ *\li See the description of dns_db_find() for information about 'options'.
+ * If the caller sets DNS_DBFIND_GLUEOK, it must ensure that 'name'
+ * and 'type' are appropriate for glue retrieval.
+ *
+ *\li If 'now' is zero, then the current time will be used.
+ *
+ *\li If 'use_hints' is ISC_TRUE, and the view has a hints database, then
+ * it will be searched last. If the answer is found in the hints
+ * database, the result code will be DNS_R_HINT. If the name is found
+ * in the hints database but not the type, the result code will be
+ * DNS_R_HINTNXRRSET.
+ *
+ *\li If 'sigrdataset' is not NULL, and there is a SIG rdataset which
+ * covers 'type', then 'sigrdataset' will be bound to it.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid, frozen view.
+ *
+ *\li 'name' is valid name.
+ *
+ *\li 'type' is a valid dns_rdatatype_t, and is not a meta query type
+ * (e.g. dns_rdatatype_any), or dns_rdatatype_rrsig.
+ *
+ *\li 'rdataset' is a valid, disassociated rdataset.
+ *
+ *\li 'sigrdataset' is NULL, or is a valid, disassociated rdataset.
+ *
+ * Ensures:
+ *
+ *\li In successful cases, 'rdataset', and possibly 'sigrdataset', are
+ * bound to the found data.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS Success; result is desired type.
+ *\li DNS_R_GLUE Success; result is glue.
+ *\li DNS_R_HINT Success; result is a hint.
+ *\li DNS_R_NCACHENXDOMAIN Success; result is a ncache entry.
+ *\li DNS_R_NCACHENXRRSET Success; result is a ncache entry.
+ *\li DNS_R_NXDOMAIN The name does not exist.
+ *\li DNS_R_NXRRSET The rrset does not exist.
+ *\li #ISC_R_NOTFOUND No matching data found,
+ * or an error occurred.
+ */
+
+/*% See dns_view_findzonecut2() */
+isc_result_t
+dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
+ isc_stdtime_t now, unsigned int options,
+ isc_boolean_t use_hints,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
+
+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,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
+/*%<
+ * Find the best known zonecut containing 'name'.
+ *
+ * This uses local authority, cache, and optionally hints data.
+ * No external queries are performed.
+ *
+ * Notes:
+ *
+ *\li If 'now' is zero, then the current time will be used.
+ *
+ *\li If 'use_hints' is ISC_TRUE, and the view has a hints database, then
+ * it will be searched last.
+ *
+ *\li If 'use_cache' is ISC_TRUE, and the view has a cache, then it will be
+ * searched.
+ *
+ *\li If 'sigrdataset' is not NULL, and there is a SIG rdataset which
+ * covers 'type', then 'sigrdataset' will be bound to it.
+ *
+ *\li If the DNS_DBFIND_NOEXACT option is set, then the zonecut returned
+ * (if any) will be the deepest known ancestor of 'name'.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid, frozen view.
+ *
+ *\li 'name' is valid name.
+ *
+ *\li 'rdataset' is a valid, disassociated rdataset.
+ *
+ *\li 'sigrdataset' is NULL, or is a valid, disassociated rdataset.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS Success.
+ *
+ *\li Many other results are possible.
+ */
+
+isc_result_t
+dns_viewlist_find(dns_viewlist_t *list, const char *name,
+ dns_rdataclass_t rdclass, dns_view_t **viewp);
+/*%<
+ * Search for a view with name 'name' and class 'rdclass' in 'list'.
+ * If found, '*viewp' is (strongly) attached to it.
+ *
+ * Requires:
+ *
+ *\li 'viewp' points to a NULL dns_view_t *.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS A matching view was found.
+ *\li #ISC_R_NOTFOUND No matching view was found.
+ */
+
+isc_result_t
+dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, isc_boolean_t allclasses,
+ dns_rdataclass_t rdclass, dns_zone_t **zonep);
+
+/*%<
+ * Search zone with 'name' in view with 'rdclass' in viewlist 'list'
+ * If found, zone is returned in *zonep. If allclasses is set rdclass is ignored
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS A matching zone was found.
+ *\li #ISC_R_NOTFOUND No matching zone was found.
+ */
+
+isc_result_t
+dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep);
+/*%<
+ * Search for the zone 'name' in the zone table of 'view'.
+ * If found, 'zonep' is (strongly) attached to it. There
+ * are no partial matches.
+ *
+ * Requires:
+ *
+ *\li 'zonep' points to a NULL dns_zone_t *.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS A matching zone was found.
+ *\li #ISC_R_NOTFOUND No matching zone was found.
+ *\li others An error occurred.
+ */
+
+isc_result_t
+dns_view_load(dns_view_t *view, isc_boolean_t stop);
+
+isc_result_t
+dns_view_loadnew(dns_view_t *view, isc_boolean_t stop);
+/*%<
+ * Load zones attached to this view. dns_view_load() loads
+ * all zones whose master file has changed since the last
+ * load; dns_view_loadnew() loads only zones that have never
+ * been loaded.
+ *
+ * If 'stop' is ISC_TRUE, stop on the first error and return it.
+ * If 'stop' is ISC_FALSE, ignore errors.
+ *
+ * Requires:
+ *
+ *\li 'view' is valid.
+ */
+
+isc_result_t
+dns_view_gettsig(dns_view_t *view, dns_name_t *keyname,
+ dns_tsigkey_t **keyp);
+/*%<
+ * Find the TSIG key configured in 'view' with name 'keyname',
+ * if any.
+ *
+ * Reqires:
+ *\li keyp points to a NULL dns_tsigkey_t *.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS A key was found and '*keyp' now points to it.
+ *\li #ISC_R_NOTFOUND No key was found.
+ *\li others An error occurred.
+ */
+
+isc_result_t
+dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr,
+ dns_tsigkey_t **keyp);
+/*%<
+ * Find the TSIG key configured in 'view' for the server whose
+ * address is 'peeraddr', if any.
+ *
+ * Reqires:
+ * keyp points to a NULL dns_tsigkey_t *.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS A key was found and '*keyp' now points to it.
+ *\li #ISC_R_NOTFOUND No key was found.
+ *\li others An error occurred.
+ */
+
+isc_result_t
+dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg);
+/*%<
+ * Verifies the signature of a message.
+ *
+ * Requires:
+ *
+ *\li 'view' is a valid view.
+ *\li 'source' is a valid buffer containing the message
+ *\li 'msg' is a valid message
+ *
+ * Returns:
+ *\li see dns_tsig_verify()
+ */
+
+void
+dns_view_dialup(dns_view_t *view);
+/*%<
+ * Perform dialup-time maintenance on the zones of 'view'.
+ */
+
+isc_result_t
+dns_view_dumpdbtostream(dns_view_t *view, FILE *fp);
+/*%<
+ * Dump the current state of the view 'view' to the stream 'fp'
+ * for purposes of analysis or debugging.
+ *
+ * Currently the dumped state includes the view's cache; in the future
+ * it may also include other state such as the address database.
+ * It will not not include authoritative data since it is voluminous and
+ * easily obtainable by other means.
+ *
+ * Requires:
+ *
+ *\li 'view' is valid.
+ *
+ *\li 'fp' refers to a file open for writing.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS The cache was successfully dumped.
+ * \li others An error occurred (see dns_master_dump)
+ */
+
+isc_result_t
+dns_view_flushcache(dns_view_t *view);
+/*%<
+ * Flush the view's cache (and ADB).
+ *
+ * Requires:
+ * 'view' is valid.
+ *
+ * No other tasks are executing.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_view_flushname(dns_view_t *view, dns_name_t *);
+/*%<
+ * Flush the given name from the view's cache (and ADB).
+ *
+ * Requires:
+ *\li 'view' is valid.
+ *\li 'name' is valid.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ * other returns are failures.
+ */
+
+isc_result_t
+dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name);
+/*%<
+ * Add the given name to the delegation only table.
+ *
+ *
+ * Requires:
+ *\li 'view' is valid.
+ *\li 'name' is valid.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name);
+/*%<
+ * Add the given name to be excluded from the root-delegation-only.
+ *
+ *
+ * Requires:
+ *\li 'view' is valid.
+ *\li 'name' is valid.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+isc_boolean_t
+dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name);
+/*%<
+ * Check if 'name' is in the delegation only table or if
+ * rootdelonly is set that name is not being excluded.
+ *
+ * Requires:
+ *\li 'view' is valid.
+ *\li 'name' is valid.
+ *
+ * Returns:
+ *\li #ISC_TRUE if the name is is the table.
+ *\li #ISC_FALSE othewise.
+ */
+
+void
+dns_view_setrootdelonly(dns_view_t *view, isc_boolean_t value);
+/*%<
+ * Set the root delegation only flag.
+ *
+ * Requires:
+ *\li 'view' is valid.
+ */
+
+isc_boolean_t
+dns_view_getrootdelonly(dns_view_t *view);
+/*%<
+ * Get the root delegation only flag.
+ *
+ * Requires:
+ *\li 'view' is valid.
+ */
+
+isc_result_t
+dns_view_freezezones(dns_view_t *view, isc_boolean_t freeze);
+/*%<
+ * Freeze/thaw updates to master zones.
+ *
+ * Requires:
+ * \li 'view' is valid.
+ */
+
+void
+dns_view_setresstats(dns_view_t *view, dns_stats_t *stats);
+/*%<
+ * Set a general resolver statistics counter set 'stats' for 'view'.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li stats is a valid statistics supporting resolver statistics counters
+ * (see dns/stats.h).
+ */
+
+void
+dns_view_getresstats(dns_view_t *view, dns_stats_t **statsp);
+/*%<
+ * Get the general statistics counter set for 'view'. If a statistics set is
+ * set '*statsp' will be attached to the set; otherwise, '*statsp' will be
+ * untouched.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li 'statsp' != NULL && '*statsp' != NULL
+ */
+
+void
+dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats);
+/*%<
+ * Set a statistics counter set of rdata type, 'stats', for 'view'. Once the
+ * statistic set is installed, view's resolver will count outgoing queries
+ * per rdata type.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li stats is a valid statistics created by dns_rdatatypestats_create().
+ */
+
+void
+dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp);
+/*%<
+ * Get the rdatatype statistics counter set for 'view'. If a statistics set is
+ * set '*statsp' will be attached to the set; otherwise, '*statsp' will be
+ * untouched.
+ *
+ * Requires:
+ * \li 'view' is valid and is not frozen.
+ *
+ *\li 'statsp' != NULL && '*statsp' != NULL
+ */
+
+#endif /* DNS_VIEW_H */
diff --git a/lib/dns/include/dns/xfrin.h b/lib/dns/include/dns/xfrin.h
new file mode 100644
index 0000000..9dd4dc9
--- /dev/null
+++ b/lib/dns/include/dns/xfrin.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2004-2007 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
+ * 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: xfrin.h,v 1.28 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_XFRIN_H
+#define DNS_XFRIN_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file dns/xfrin.h
+ * \brief
+ * Incoming zone transfers (AXFR + IXFR).
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+/***
+ *** Types
+ ***/
+
+/*%
+ * A transfer in progress. This is an opaque type.
+ */
+typedef struct dns_xfrin_ctx dns_xfrin_ctx_t;
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+/*% see dns_xfrin_create2() */
+isc_result_t
+dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
+ isc_sockaddr_t *masteraddr, dns_tsigkey_t *tsigkey,
+ isc_mem_t *mctx, isc_timermgr_t *timermgr,
+ isc_socketmgr_t *socketmgr, isc_task_t *task,
+ dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp);
+
+isc_result_t
+dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
+ isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
+ dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
+ isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
+ isc_task_t *task, dns_xfrindone_t done,
+ dns_xfrin_ctx_t **xfrp);
+/*%<
+ * Attempt to start an incoming zone transfer of 'zone'
+ * from 'masteraddr', creating a dns_xfrin_ctx_t object to
+ * manage it. Attach '*xfrp' to the newly created object.
+ *
+ * Iff ISC_R_SUCCESS is returned, '*done' is guaranteed to be
+ * called in the context of 'task', with 'zone' and a result
+ * code as arguments when the transfer finishes.
+ *
+ * Requires:
+ *\li 'xfrtype' is dns_rdatatype_axfr, dns_rdatatype_ixfr
+ * or dns_rdatatype_soa (soa query followed by axfr if
+ * serial is greater than current serial).
+ *
+ *\li If 'xfrtype' is dns_rdatatype_ixfr or dns_rdatatype_soa,
+ * the zone has a database.
+ */
+
+void
+dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr);
+/*%<
+ * If the zone transfer 'xfr' has already finished,
+ * do nothing. Otherwise, abort it and cause it to call
+ * its done callback with a status of ISC_R_CANCELLED.
+ */
+
+void
+dns_xfrin_detach(dns_xfrin_ctx_t **xfrp);
+/*%<
+ * Detach a reference to a zone transfer object.
+ * Caller to maintain external locking if required.
+ */
+
+void
+dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target);
+/*%<
+ * Caller to maintain external locking if required.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_XFRIN_H */
diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h
new file mode 100644
index 0000000..c6f4444
--- /dev/null
+++ b/lib/dns/include/dns/zone.h
@@ -0,0 +1,1736 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: zone.h,v 1.160 2008/09/24 02:46:23 marka Exp $ */
+
+#ifndef DNS_ZONE_H
+#define DNS_ZONE_H 1
+
+/*! \file dns/zone.h */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdio.h>
+
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/rwlock.h>
+
+#include <dns/masterdump.h>
+#include <dns/rdatastruct.h>
+#include <dns/types.h>
+
+typedef enum {
+ dns_zone_none,
+ dns_zone_master,
+ dns_zone_slave,
+ dns_zone_stub
+} dns_zonetype_t;
+
+#define DNS_ZONEOPT_SERVERS 0x00000001U /*%< perform server checks */
+#define DNS_ZONEOPT_PARENTS 0x00000002U /*%< perform parent checks */
+#define DNS_ZONEOPT_CHILDREN 0x00000004U /*%< perform child checks */
+#define DNS_ZONEOPT_NOTIFY 0x00000008U /*%< perform NOTIFY */
+#define DNS_ZONEOPT_MANYERRORS 0x00000010U /*%< return many errors on load */
+#define DNS_ZONEOPT_IXFRFROMDIFFS 0x00000020U /*%< calculate differences */
+#define DNS_ZONEOPT_NOMERGE 0x00000040U /*%< don't merge journal */
+#define DNS_ZONEOPT_CHECKNS 0x00000080U /*%< check if NS's are addresses */
+#define DNS_ZONEOPT_FATALNS 0x00000100U /*%< DNS_ZONEOPT_CHECKNS is fatal */
+#define DNS_ZONEOPT_MULTIMASTER 0x00000200U /*%< this zone has multiple masters */
+#define DNS_ZONEOPT_USEALTXFRSRC 0x00000400U /*%< use alternate transfer sources */
+#define DNS_ZONEOPT_CHECKNAMES 0x00000800U /*%< check-names */
+#define DNS_ZONEOPT_CHECKNAMESFAIL 0x00001000U /*%< fatal check-name failures */
+#define DNS_ZONEOPT_CHECKWILDCARD 0x00002000U /*%< check for internal wildcards */
+#define DNS_ZONEOPT_CHECKMX 0x00004000U /*%< check-mx */
+#define DNS_ZONEOPT_CHECKMXFAIL 0x00008000U /*%< fatal check-mx failures */
+#define DNS_ZONEOPT_CHECKINTEGRITY 0x00010000U /*%< perform integrity checks */
+#define DNS_ZONEOPT_CHECKSIBLING 0x00020000U /*%< perform sibling glue checks */
+#define DNS_ZONEOPT_NOCHECKNS 0x00040000U /*%< disable IN NS address checks */
+#define DNS_ZONEOPT_WARNMXCNAME 0x00080000U /*%< warn on MX CNAME check */
+#define DNS_ZONEOPT_IGNOREMXCNAME 0x00100000U /*%< ignore MX CNAME check */
+#define DNS_ZONEOPT_WARNSRVCNAME 0x00200000U /*%< warn on SRV CNAME check */
+#define DNS_ZONEOPT_IGNORESRVCNAME 0x00400000U /*%< ignore SRV CNAME check */
+#define DNS_ZONEOPT_UPDATECHECKKSK 0x00800000U /*%< check dnskey KSK flag */
+#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 */
+
+#ifndef NOMINUM_PUBLIC
+/*
+ * Nominum specific options build down.
+ */
+#define DNS_ZONEOPT_NOTIFYFORWARD 0x80000000U /* forward notify to master */
+#endif /* NOMINUM_PUBLIC */
+
+#ifndef DNS_ZONE_MINREFRESH
+#define DNS_ZONE_MINREFRESH 300 /*%< 5 minutes */
+#endif
+#ifndef DNS_ZONE_MAXREFRESH
+#define DNS_ZONE_MAXREFRESH 2419200 /*%< 4 weeks */
+#endif
+#ifndef DNS_ZONE_DEFAULTREFRESH
+#define DNS_ZONE_DEFAULTREFRESH 3600 /*%< 1 hour */
+#endif
+#ifndef DNS_ZONE_MINRETRY
+#define DNS_ZONE_MINRETRY 300 /*%< 5 minutes */
+#endif
+#ifndef DNS_ZONE_MAXRETRY
+#define DNS_ZONE_MAXRETRY 1209600 /*%< 2 weeks */
+#endif
+#ifndef DNS_ZONE_DEFAULTRETRY
+#define DNS_ZONE_DEFAULTRETRY 60 /*%< 1 minute, subject to
+ exponential backoff */
+#endif
+
+#define DNS_ZONESTATE_XFERRUNNING 1
+#define DNS_ZONESTATE_XFERDEFERRED 2
+#define DNS_ZONESTATE_SOAQUERY 3
+#define DNS_ZONESTATE_ANY 4
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx);
+/*%<
+ * Creates a new empty zone and attach '*zonep' to it.
+ *
+ * Requires:
+ *\li 'zonep' to point to a NULL pointer.
+ *\li 'mctx' to be a valid memory context.
+ *
+ * Ensures:
+ *\li '*zonep' refers to a valid zone.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ */
+
+void
+dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass);
+/*%<
+ * Sets the class of a zone. This operation can only be performed
+ * once on a zone.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li dns_zone_setclass() not to have been called since the zone was
+ * created.
+ *\li 'rdclass' != dns_rdataclass_none.
+ */
+
+dns_rdataclass_t
+dns_zone_getclass(dns_zone_t *zone);
+/*%<
+ * Returns the current zone class.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_uint32_t
+dns_zone_getserial(dns_zone_t *zone);
+/*%<
+ * Returns the current serial number of the zone.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type);
+/*%<
+ * Sets the zone type. This operation can only be performed once on
+ * a zone.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ *\li dns_zone_settype() not to have been called since the zone was
+ * created.
+ *\li 'type' != dns_zone_none
+ */
+
+void
+dns_zone_setview(dns_zone_t *zone, dns_view_t *view);
+/*%<
+ * Associate the zone with a view.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+dns_view_t *
+dns_zone_getview(dns_zone_t *zone);
+/*%<
+ * Returns the zone's associated view.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin);
+/*%<
+ * Sets the zones origin to 'origin'.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'origin' to be non NULL.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+dns_name_t *
+dns_zone_getorigin(dns_zone_t *zone);
+/*%<
+ * Returns the value of the origin.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_setfile(dns_zone_t *zone, const char *file);
+
+isc_result_t
+dns_zone_setfile2(dns_zone_t *zone, const char *file,
+ dns_masterformat_t format);
+/*%<
+ * Sets the name of the master file in the format of 'format' from which
+ * the zone loads its database to 'file'.
+ *
+ * For zones that have no associated master file, 'file' will be NULL.
+ *
+ * For zones with persistent databases, the file name
+ * setting is ignored.
+ *
+ * dns_zone_setfile() is a backward-compatible form of
+ * dns_zone_setfile2(), which always specifies the
+ * dns_masterformat_text (RFC1035) format.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_SUCCESS
+ */
+
+const char *
+dns_zone_getfile(dns_zone_t *zone);
+/*%<
+ * Gets the name of the zone's master file, if any.
+ *
+ * Requires:
+ *\li 'zone' to be valid initialised zone.
+ *
+ * Returns:
+ *\li Pointer to null-terminated file name, or NULL.
+ */
+
+isc_result_t
+dns_zone_load(dns_zone_t *zone);
+
+isc_result_t
+dns_zone_loadnew(dns_zone_t *zone);
+/*%<
+ * Cause the database to be loaded from its backing store.
+ * Confirm that the minimum requirements for the zone type are
+ * met, otherwise DNS_R_BADZONE is returned.
+ *
+ * dns_zone_loadnew() only loads zones that are not yet loaded.
+ * dns_zone_load() also loads zones that are already loaded and
+ * and whose master file has changed since the last load.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li #ISC_R_UNEXPECTED
+ *\li #ISC_R_SUCCESS
+ *\li DNS_R_CONTINUE Incremental load has been queued.
+ *\li DNS_R_UPTODATE The zone has already been loaded based on
+ * file system timestamps.
+ *\li DNS_R_BADZONE
+ *\li Any result value from dns_db_load().
+ */
+
+void
+dns_zone_attach(dns_zone_t *source, dns_zone_t **target);
+/*%<
+ * Attach '*target' to 'source' incrementing its external
+ * reference count.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'target' to be non NULL and '*target' to be NULL.
+ */
+
+void
+dns_zone_detach(dns_zone_t **zonep);
+/*%<
+ * Detach from a zone decrementing its external reference count.
+ * If this was the last external reference to the zone it will be
+ * shut down and eventually freed.
+ *
+ * Require:
+ *\li 'zonep' to point to a valid zone.
+ */
+
+void
+dns_zone_iattach(dns_zone_t *source, dns_zone_t **target);
+/*%<
+ * Attach '*target' to 'source' incrementing its internal
+ * reference count. This is intended for use by operations
+ * such as zone transfers that need to prevent the zone
+ * object from being freed but not from shutting down.
+ *
+ * Require:
+ *\li The caller is running in the context of the zone's task.
+ *\li 'zone' to be a valid zone.
+ *\li 'target' to be non NULL and '*target' to be NULL.
+ */
+
+void
+dns_zone_idetach(dns_zone_t **zonep);
+/*%<
+ * Detach from a zone decrementing its internal reference count.
+ * If there are no more internal or external references to the
+ * zone, it will be freed.
+ *
+ * Require:
+ *\li The caller is running in the context of the zone's task.
+ *\li 'zonep' to point to a valid zone.
+ */
+
+void
+dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value);
+/*%<
+ * Sets ('value' == 'ISC_TRUE') / clears ('value' == 'IS_FALSE')
+ * zone flags. Valid flag bits are DNS_ZONE_F_*.
+ *
+ * Requires
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_getdb(dns_zone_t *zone, dns_db_t **dbp);
+/*%<
+ * Attach '*dbp' to the database to if it exists otherwise
+ * return DNS_R_NOTLOADED.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'dbp' to be != NULL && '*dbp' == NULL.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li DNS_R_NOTLOADED
+ */
+
+isc_result_t
+dns_zone_setdbtype(dns_zone_t *zone,
+ unsigned int dbargc, const char * const *dbargv);
+/*%<
+ * Sets the database type to dbargv[0] and database arguments
+ * to subsequent dbargv elements.
+ * 'db_type' is not checked to see if it is a valid database type.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'database' to be non NULL.
+ *\li 'dbargc' to be >= 1
+ *\li 'dbargv' to point to dbargc NULL-terminated strings
+ *
+ * Returns:
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_SUCCESS
+ */
+
+isc_result_t
+dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx);
+/*%<
+ * Returns the current dbtype. isc_mem_free() should be used
+ * to free 'argv' after use.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'argv' to be non NULL and *argv to be NULL.
+ *\li 'mctx' to be valid.
+ *
+ * Returns:
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_SUCCESS
+ */
+
+void
+dns_zone_markdirty(dns_zone_t *zone);
+/*%<
+ * Mark a zone as 'dirty'.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_expire(dns_zone_t *zone);
+/*%<
+ * Mark the zone as expired. If the zone requires dumping cause it to
+ * be initiated. Set the refresh and retry intervals to there default
+ * values and unload the zone.
+ *
+ * Require
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_refresh(dns_zone_t *zone);
+/*%<
+ * Initiate zone up to date checks. The zone must already be being
+ * managed.
+ *
+ * Require
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_flush(dns_zone_t *zone);
+/*%<
+ * Write the zone to database if there are uncommited changes.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_dump(dns_zone_t *zone);
+/*%<
+ * Write the zone to database.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_dumptostream(dns_zone_t *zone, FILE *fd);
+
+isc_result_t
+dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
+ const dns_master_style_t *style);
+/*%<
+ * Write the zone to stream 'fd' in the specified 'format'.
+ * If the 'format' is dns_masterformat_text (RFC1035), 'style' also
+ * specifies the file style (e.g., &dns_master_style_default).
+ *
+ * dns_zone_dumptostream() is a backward-compatible form of
+ * dns_zone_dumptostream2(), which always uses the dns_masterformat_text
+ * format and the dns_master_style_default style.
+ *
+ * Note that dns_zone_dumptostream2() is the most flexible form. It
+ * can also provide the functionality of dns_zone_fulldumptostream().
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'fd' to be a stream open for writing.
+ */
+
+isc_result_t
+dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd);
+/*%<
+ * The same as dns_zone_dumptostream, but dumps the zone with
+ * different dump settings (dns_master_style_full).
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'fd' to be a stream open for writing.
+ */
+
+void
+dns_zone_maintenance(dns_zone_t *zone);
+/*%<
+ * Perform regular maintenace on the zone. This is called as a
+ * result of a zone being managed.
+ *
+ * Require
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
+ isc_uint32_t count);
+isc_result_t
+dns_zone_setmasterswithkeys(dns_zone_t *zone,
+ const isc_sockaddr_t *masters,
+ dns_name_t **keynames,
+ isc_uint32_t count);
+/*%<
+ * Set the list of master servers for the zone.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'masters' array of isc_sockaddr_t with port set or NULL.
+ *\li 'count' the number of masters.
+ *\li 'keynames' array of dns_name_t's for tsig keys or NULL.
+ *
+ * \li dns_zone_setmasters() is just a wrapper to setmasterswithkeys(),
+ * passing NULL in the keynames field.
+ *
+ * \li If 'masters' is NULL then 'count' must be zero.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li Any result dns_name_dup() can return, if keynames!=NULL
+ */
+
+isc_result_t
+dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
+ isc_uint32_t count);
+/*%<
+ * Set the list of additional servers to be notified when
+ * a zone changes. To clear the list use 'count = 0'.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'notify' to be non-NULL if count != 0.
+ *\li 'count' to be the number of notifyees.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+dns_zone_unload(dns_zone_t *zone);
+/*%<
+ * detach the database from the zone structure.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value);
+/*%<
+ * Set given options on ('value' == ISC_TRUE) or off ('value' ==
+ * #ISC_FALSE).
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+unsigned int
+dns_zone_getoptions(dns_zone_t *zone);
+/*%<
+ * Returns the current zone 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.
+ *
+ * Requires:
+ *\li 'zone' is valid.
+ *\li val > 0.
+ */
+
+void
+dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val);
+/*%<
+ * Set the maximum refresh time.
+ *
+ * Requires:
+ *\li 'zone' is valid.
+ *\li val > 0.
+ */
+
+void
+dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val);
+/*%<
+ * Set the minimum retry time.
+ *
+ * Requires:
+ *\li 'zone' is valid.
+ *\li val > 0.
+ */
+
+void
+dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val);
+/*%<
+ * Set the maximum retry time.
+ *
+ * Requires:
+ *\li 'zone' is valid.
+ * val > 0.
+ */
+
+isc_result_t
+dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource);
+isc_result_t
+dns_zone_setaltxfrsource4(dns_zone_t *zone,
+ const isc_sockaddr_t *xfrsource);
+/*%<
+ * Set the source address to be used in IPv4 zone transfers.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'xfrsource' to contain the address.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ */
+
+isc_sockaddr_t *
+dns_zone_getxfrsource4(dns_zone_t *zone);
+isc_sockaddr_t *
+dns_zone_getaltxfrsource4(dns_zone_t *zone);
+/*%<
+ * Returns the source address set by a previous dns_zone_setxfrsource4
+ * call, or the default of inaddr_any, port 0.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource);
+isc_result_t
+dns_zone_setaltxfrsource6(dns_zone_t *zone,
+ const isc_sockaddr_t *xfrsource);
+/*%<
+ * Set the source address to be used in IPv6 zone transfers.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'xfrsource' to contain the address.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ */
+
+isc_sockaddr_t *
+dns_zone_getxfrsource6(dns_zone_t *zone);
+isc_sockaddr_t *
+dns_zone_getaltxfrsource6(dns_zone_t *zone);
+/*%<
+ * Returns the source address set by a previous dns_zone_setxfrsource6
+ * call, or the default of in6addr_any, port 0.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc);
+/*%<
+ * Set the source address to be used with IPv4 NOTIFY messages.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'notifysrc' to contain the address.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ */
+
+isc_sockaddr_t *
+dns_zone_getnotifysrc4(dns_zone_t *zone);
+/*%<
+ * Returns the source address set by a previous dns_zone_setnotifysrc4
+ * call, or the default of inaddr_any, port 0.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc);
+/*%<
+ * Set the source address to be used with IPv6 NOTIFY messages.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'notifysrc' to contain the address.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ */
+
+isc_sockaddr_t *
+dns_zone_getnotifysrc6(dns_zone_t *zone);
+/*%<
+ * Returns the source address set by a previous dns_zone_setnotifysrc6
+ * call, or the default of in6addr_any, port 0.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl);
+/*%<
+ * Sets the notify acl list for the zone.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'acl' to be a valid acl.
+ */
+
+void
+dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl);
+/*%<
+ * Sets the query acl list for the zone.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'acl' to be a valid acl.
+ */
+
+void
+dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl);
+/*%<
+ * Sets the query-on acl list for the zone.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'acl' to be a valid acl.
+ */
+
+void
+dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl);
+/*%<
+ * Sets the update acl list for the zone.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'acl' to be valid acl.
+ */
+
+void
+dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl);
+/*%<
+ * Sets the forward unsigned updates acl list for the zone.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'acl' to be valid acl.
+ */
+
+void
+dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl);
+/*%<
+ * Sets the transfer acl list for the zone.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'acl' to be valid acl.
+ */
+
+dns_acl_t *
+dns_zone_getnotifyacl(dns_zone_t *zone);
+/*%<
+ * Returns the current notify acl or NULL.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li acl a pointer to the acl.
+ *\li NULL
+ */
+
+dns_acl_t *
+dns_zone_getqueryacl(dns_zone_t *zone);
+/*%<
+ * Returns the current query acl or NULL.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li acl a pointer to the acl.
+ *\li NULL
+ */
+
+dns_acl_t *
+dns_zone_getqueryonacl(dns_zone_t *zone);
+/*%<
+ * Returns the current query-on acl or NULL.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li acl a pointer to the acl.
+ *\li NULL
+ */
+
+dns_acl_t *
+dns_zone_getupdateacl(dns_zone_t *zone);
+/*%<
+ * Returns the current update acl or NULL.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li acl a pointer to the acl.
+ *\li NULL
+ */
+
+dns_acl_t *
+dns_zone_getforwardacl(dns_zone_t *zone);
+/*%<
+ * Returns the current forward unsigned updates acl or NULL.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li acl a pointer to the acl.
+ *\li NULL
+ */
+
+dns_acl_t *
+dns_zone_getxfracl(dns_zone_t *zone);
+/*%<
+ * Returns the current transfer acl or NULL.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li acl a pointer to the acl.
+ *\li NULL
+ */
+
+void
+dns_zone_clearupdateacl(dns_zone_t *zone);
+/*%<
+ * Clear the current update acl.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_clearforwardacl(dns_zone_t *zone);
+/*%<
+ * Clear the current forward unsigned updates acl.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_clearnotifyacl(dns_zone_t *zone);
+/*%<
+ * Clear the current notify acl.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_clearqueryacl(dns_zone_t *zone);
+/*%<
+ * Clear the current query acl.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_clearqueryonacl(dns_zone_t *zone);
+/*%<
+ * Clear the current query-on acl.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_clearxfracl(dns_zone_t *zone);
+/*%<
+ * Clear the current transfer acl.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_boolean_t
+dns_zone_getupdatedisabled(dns_zone_t *zone);
+/*%<
+ * Return update disabled.
+ * Transient unless called when running in isc_task_exclusive() mode.
+ */
+
+void
+dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state);
+/*%<
+ * Set update disabled.
+ * Should only be called only when running in isc_task_exclusive() mode.
+ * Failure to do so may result in updates being committed after the
+ * call has been made.
+ */
+
+isc_boolean_t
+dns_zone_getzeronosoattl(dns_zone_t *zone);
+/*%<
+ * Return zero-no-soa-ttl status.
+ */
+
+void
+dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state);
+/*%<
+ * Set zero-no-soa-ttl status.
+ */
+
+void
+dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity);
+/*%<
+ * Set the severity of name checking when loading a zone.
+ *
+ * Require:
+ * \li 'zone' to be a valid zone.
+ */
+
+dns_severity_t
+dns_zone_getchecknames(dns_zone_t *zone);
+/*%<
+ * Return the current severity of name checking.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size);
+/*%<
+ * Sets the journal size for the zone.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_int32_t
+dns_zone_getjournalsize(dns_zone_t *zone);
+/*%<
+ * Return the journal size as set with a previous call to
+ * dns_zone_setjournalsize().
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
+ dns_message_t *msg);
+/*%<
+ * Tell the zone that it has recieved a NOTIFY message from another
+ * server. This may cause some zone maintainence activity to occur.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ *\li '*from' to contain the address of the server from which 'msg'
+ * was recieved.
+ *\li 'msg' a message with opcode NOTIFY and qr clear.
+ *
+ * Returns:
+ *\li DNS_R_REFUSED
+ *\li DNS_R_NOTIMP
+ *\li DNS_R_FORMERR
+ *\li DNS_R_SUCCESS
+ */
+
+void
+dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin);
+/*%<
+ * Set the maximum time (in seconds) that a zone transfer in (AXFR/IXFR)
+ * of this zone will use before being aborted.
+ *
+ * Requires:
+ * \li 'zone' to be valid initialised zone.
+ */
+
+isc_uint32_t
+dns_zone_getmaxxfrin(dns_zone_t *zone);
+/*%<
+ * Returns the maximum transfer time for this zone. This will be
+ * either the value set by the last call to dns_zone_setmaxxfrin() or
+ * the default value of 1 hour.
+ *
+ * Requires:
+ *\li 'zone' to be valid initialised zone.
+ */
+
+void
+dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout);
+/*%<
+ * Set the maximum time (in seconds) that a zone transfer out (AXFR/IXFR)
+ * of this zone will use before being aborted.
+ *
+ * Requires:
+ * \li 'zone' to be valid initialised zone.
+ */
+
+isc_uint32_t
+dns_zone_getmaxxfrout(dns_zone_t *zone);
+/*%<
+ * Returns the maximum transfer time for this zone. This will be
+ * either the value set by the last call to dns_zone_setmaxxfrout() or
+ * the default value of 1 hour.
+ *
+ * Requires:
+ *\li 'zone' to be valid initialised zone.
+ */
+
+isc_result_t
+dns_zone_setjournal(dns_zone_t *zone, const char *journal);
+/*%<
+ * Sets the filename used for journaling updates / IXFR transfers.
+ * The default journal name is set by dns_zone_setfile() to be
+ * "file.jnl". If 'journal' is NULL, the zone will have no
+ * journal name.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+char *
+dns_zone_getjournal(dns_zone_t *zone);
+/*%<
+ * Returns the journal name associated with this zone.
+ * If no journal has been set this will be NULL.
+ *
+ * Requires:
+ *\li 'zone' to be valid initialised zone.
+ */
+
+dns_zonetype_t
+dns_zone_gettype(dns_zone_t *zone);
+/*%<
+ * Returns the type of the zone (master/slave/etc.)
+ *
+ * Requires:
+ *\li 'zone' to be valid initialised zone.
+ */
+
+void
+dns_zone_settask(dns_zone_t *zone, isc_task_t *task);
+/*%<
+ * Give a zone a task to work with. Any current task will be detached.
+ *
+ * Requires:
+ *\li 'zone' to be valid.
+ *\li 'task' to be valid.
+ */
+
+void
+dns_zone_gettask(dns_zone_t *zone, isc_task_t **target);
+/*%<
+ * Attach '*target' to the zone's task.
+ *
+ * Requires:
+ *\li 'zone' to be valid initialised zone.
+ *\li 'zone' to have a task.
+ *\li 'target' to be != NULL && '*target' == NULL.
+ */
+
+void
+dns_zone_notify(dns_zone_t *zone);
+/*%<
+ * Generate notify events for this zone.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump);
+/*%<
+ * Replace the database of "zone" with a new database "db".
+ *
+ * If "dump" is ISC_TRUE, then the new zone contents are dumped
+ * into to the zone's master file for persistence. When replacing
+ * a zone database by one just loaded from a master file, set
+ * "dump" to ISC_FALSE to avoid a redunant redump of the data just
+ * loaded. Otherwise, it should be set to ISC_TRUE.
+ *
+ * If the "diff-on-reload" option is enabled in the configuration file,
+ * the differences between the old and the new database are added to the
+ * journal file, and the master file dump is postponed.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ *
+ * Returns:
+ * \li DNS_R_SUCCESS
+ * \li DNS_R_BADZONE zone failed basic consistancy checks:
+ * * a single SOA must exist
+ * * some NS records must exist.
+ * Others
+ */
+
+isc_uint32_t
+dns_zone_getidlein(dns_zone_t *zone);
+/*%<
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ *
+ * Returns:
+ * \li number of seconds of idle time before we abort the transfer in.
+ */
+
+void
+dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein);
+/*%<
+ * \li Set the idle timeout for transfer the.
+ * \li Zero set the default value, 1 hour.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+isc_uint32_t
+dns_zone_getidleout(dns_zone_t *zone);
+/*%<
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ *
+ * Returns:
+ * \li number of seconds of idle time before we abort a transfer out.
+ */
+
+void
+dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout);
+/*%<
+ * \li Set the idle timeout for transfers out.
+ * \li Zero set the default value, 1 hour.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table);
+/*%<
+ * Get the simple-secure-update policy table.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table);
+/*%<
+ * Set / clear the simple-secure-update policy table.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+isc_mem_t *
+dns_zone_getmctx(dns_zone_t *zone);
+/*%<
+ * Get the memory context of a zone.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+dns_zonemgr_t *
+dns_zone_getmgr(dns_zone_t *zone);
+/*%<
+ * If 'zone' is managed return the zone manager otherwise NULL.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval);
+/*%<
+ * Set the zone's RRSIG validity interval. This is the length of time
+ * for which DNSSEC signatures created as a result of dynamic updates
+ * to secure zones will remain valid, in seconds.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+isc_uint32_t
+dns_zone_getsigvalidityinterval(dns_zone_t *zone);
+/*%<
+ * Get the zone's RRSIG validity interval.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval);
+/*%<
+ * Set the zone's RRSIG re-signing interval. A dynamic zone's RRSIG's
+ * will be re-signed 'interval' amount of time before they expire.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+isc_uint32_t
+dns_zone_getsigresigninginterval(dns_zone_t *zone);
+/*%<
+ * Get the zone's RRSIG re-signing interval.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype);
+/*%<
+ * Sets zone notify method to "notifytype"
+ */
+
+isc_result_t
+dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
+ dns_updatecallback_t callback, void *callback_arg);
+/*%<
+ * Forward 'msg' to each master in turn until we get an answer or we
+ * have exausted the list of masters. 'callback' will be called with
+ * ISC_R_SUCCESS if we get an answer and the returned message will be
+ * passed as 'answer_message', otherwise a non ISC_R_SUCCESS result code
+ * will be passed and answer_message will be NULL. The callback function
+ * is responsible for destroying 'answer_message'.
+ * (callback)(callback_arg, result, answer_message);
+ *
+ * Require:
+ *\li 'zone' to be valid
+ *\li 'msg' to be valid.
+ *\li 'callback' to be non NULL.
+ * Returns:
+ *\li #ISC_R_SUCCESS if the message has been forwarded,
+ *\li #ISC_R_NOMEMORY
+ *\li Others
+ */
+
+isc_result_t
+dns_zone_next(dns_zone_t *zone, dns_zone_t **next);
+/*%<
+ * Find the next zone in the list of managed zones.
+ *
+ * Requires:
+ *\li 'zone' to be valid
+ *\li The zone manager for the indicated zone MUST be locked
+ * by the caller. This is not checked.
+ *\li 'next' be non-NULL, and '*next' be NULL.
+ *
+ * Ensures:
+ *\li 'next' points to a valid zone (result ISC_R_SUCCESS) or to NULL
+ * (result ISC_R_NOMORE).
+ */
+
+
+
+isc_result_t
+dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first);
+/*%<
+ * Find the first zone in the list of managed zones.
+ *
+ * Requires:
+ *\li 'zonemgr' to be valid
+ *\li The zone manager for the indicated zone MUST be locked
+ * by the caller. This is not checked.
+ *\li 'first' be non-NULL, and '*first' be NULL
+ *
+ * Ensures:
+ *\li 'first' points to a valid zone (result ISC_R_SUCCESS) or to NULL
+ * (result ISC_R_NOMORE).
+ */
+
+isc_result_t
+dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory);
+/*%<
+ * Sets the name of the directory where private keys used for
+ * online signing of dynamic zones are found.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *
+ * Returns:
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_SUCCESS
+ */
+
+const char *
+dns_zone_getkeydirectory(dns_zone_t *zone);
+/*%<
+ * Gets the name of the directory where private keys used for
+ * online signing of dynamic zones are found.
+ *
+ * Requires:
+ *\li 'zone' to be valid initialised zone.
+ *
+ * Returns:
+ * Pointer to null-terminated file name, or NULL.
+ */
+
+
+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);
+/*%<
+ * Create a zone manager.
+ *
+ * Requires:
+ *\li 'mctx' to be a valid memory context.
+ *\li 'taskmgr' to be a valid task manager.
+ *\li 'timermgr' to be a valid timer manager.
+ *\li 'zmgrp' to point to a NULL pointer.
+ */
+
+isc_result_t
+dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone);
+/*%<
+ * Bring the zone under control of a zone manager.
+ *
+ * Require:
+ *\li 'zmgr' to be a valid zone manager.
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr);
+/*%<
+ * Force zone maintenance of all zones managed by 'zmgr' at its
+ * earliest conveniene.
+ */
+
+void
+dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr);
+/*%<
+ * Attempt to start any stalled zone transfers.
+ */
+
+void
+dns_zonemgr_shutdown(dns_zonemgr_t *zmgr);
+/*%<
+ * Shut down the zone manager.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ */
+
+void
+dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target);
+/*%<
+ * Attach '*target' to 'source' incrementing its external
+ * reference count.
+ *
+ * Require:
+ *\li 'zone' to be a valid zone.
+ *\li 'target' to be non NULL and '*target' to be NULL.
+ */
+
+void
+dns_zonemgr_detach(dns_zonemgr_t **zmgrp);
+/*%<
+ * Detach from a zone manager.
+ *
+ * Requires:
+ *\li '*zmgrp' is a valid, non-NULL zone manager pointer.
+ *
+ * Ensures:
+ *\li '*zmgrp' is NULL.
+ */
+
+void
+dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone);
+/*%<
+ * Release 'zone' from the managed by 'zmgr'. 'zmgr' is implicitly
+ * detached from 'zone'.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ *\li 'zone' to be a valid zone.
+ *\li 'zmgr' == 'zone->zmgr'
+ *
+ * Ensures:
+ *\li 'zone->zmgr' == NULL;
+ */
+
+void
+dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value);
+/*%<
+ * Set the maximum number of simultaneous transfers in allowed by
+ * the zone manager.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ */
+
+isc_uint32_t
+dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr);
+/*%<
+ * Return the the maximum number of simultaneous transfers in allowed.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ */
+
+void
+dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value);
+/*%<
+ * Set the number of zone transfers allowed per nameserver.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager
+ */
+
+isc_uint32_t
+dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr);
+/*%<
+ * Return the number of transfers allowed per nameserver.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ */
+
+void
+dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit);
+/*%<
+ * Set the number of simultaneous file descriptors available for
+ * reading and writing masterfiles.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ *\li 'iolimit' to be positive.
+ */
+
+isc_uint32_t
+dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr);
+/*%<
+ * Get the number of simultaneous file descriptors available for
+ * reading and writing masterfiles.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ */
+
+void
+dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value);
+/*%<
+ * Set the number of SOA queries sent per second.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager
+ */
+
+unsigned int
+dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr);
+/*%<
+ * Return the number of SOA queries sent per second.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ */
+
+unsigned int
+dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state);
+/*%<
+ * Returns the number of zones in the specified state.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ *\li 'state' to be a valid DNS_ZONESTATE_ constant.
+ */
+
+void
+dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
+ isc_sockaddr_t *local, isc_time_t *now);
+/*%<
+ * Add the pair of addresses to the unreachable cache.
+ *
+ * Requires:
+ *\li 'zmgr' to be a valid zone manager.
+ *\li 'remote' to be a valid sockaddr.
+ *\li 'local' to be a valid sockaddr.
+ */
+
+void
+dns_zone_forcereload(dns_zone_t *zone);
+/*%<
+ * Force a reload of specified zone.
+ *
+ * Requires:
+ *\li 'zone' to be a valid zone.
+ */
+
+isc_boolean_t
+dns_zone_isforced(dns_zone_t *zone);
+/*%<
+ * Check if the zone is waiting a forced reload.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ */
+
+isc_result_t
+dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on);
+/*%<
+ * This function is obsoleted by dns_zone_setrequeststats().
+ */
+
+isc_uint64_t *
+dns_zone_getstatscounters(dns_zone_t *zone);
+/*%<
+ * This function is obsoleted by dns_zone_getrequeststats().
+ */
+
+void
+dns_zone_setstats(dns_zone_t *zone, dns_stats_t *stats);
+/*%<
+ * Set a general zone-maintenance statistics set 'stats' for 'zone'. This
+ * function is expected to be called only on zone creation (when necessary).
+ * Once installed, it cannot be removed or replaced. Also, there is no
+ * interface to get the installed stats from the zone; the caller must keep the
+ * stats to reference (e.g. dump) it later.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone and does not have a statistics set already
+ * installed.
+ *
+ *\li stats is a valid statistics supporting zone statistics counters
+ * (see dns/stats.h).
+ */
+
+void
+dns_zone_setrequeststats(dns_zone_t *zone, dns_stats_t *stats);
+/*%<
+ * Set an additional statistics set to zone. It is attached in the zone
+ * but is not counted in the zone module; only the caller updates the counters.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ *
+ *\li stats is a valid statistics.
+ */
+
+dns_stats_t *
+dns_zone_getrequeststats(dns_zone_t *zone);
+/*%<
+ * Get the additional statistics for zone, if one is installed.
+ *
+ * Requires:
+ * \li 'zone' to be a valid zone.
+ *
+ * Returns:
+ * \li when available, a pointer to the statistics set installed in zone;
+ * otherwise NULL.
+ */
+
+void
+dns_zone_dialup(dns_zone_t *zone);
+/*%<
+ * Perform dialup-time maintenance on 'zone'.
+ */
+
+void
+dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup);
+/*%<
+ * Set the dialup type of 'zone' to 'dialup'.
+ *
+ * Requires:
+ * \li 'zone' to be valid initialised zone.
+ *\li 'dialup' to be a valid dialup type.
+ */
+
+void
+dns_zone_log(dns_zone_t *zone, int level, const char *msg, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+/*%<
+ * Log the message 'msg...' at 'level', including text that identifies
+ * the message as applying to 'zone'.
+ */
+
+void
+dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
+ const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
+/*%<
+ * Log the message 'msg...' at 'level', including text that identifies
+ * the message as applying to 'zone'.
+ */
+
+void
+dns_zone_name(dns_zone_t *zone, char *buf, size_t len);
+/*%<
+ * Return the name of the zone with class and view.
+ *
+ * Requires:
+ *\li 'zone' to be valid.
+ *\li 'buf' to be non NULL.
+ */
+
+isc_result_t
+dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata);
+/*%<
+ * Check if this record meets the check-names policy.
+ *
+ * Requires:
+ * 'zone' to be valid.
+ * 'name' to be valid.
+ * 'rdata' to be valid.
+ *
+ * Returns:
+ * DNS_R_SUCCESS passed checks.
+ * DNS_R_BADOWNERNAME failed ownername checks.
+ * DNS_R_BADNAME failed rdata checks.
+ */
+
+void
+dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache);
+/*%<
+ * Associate the zone with an additional cache.
+ *
+ * Require:
+ * 'zone' to be a valid zone.
+ * 'acache' to be a non NULL pointer.
+ *
+ * Ensures:
+ * 'zone' will have a reference to 'acache'
+ */
+
+void
+dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx);
+/*%<
+ * Set the post load integrity callback function 'checkmx'.
+ * 'checkmx' will be called if the MX is not within the zone.
+ *
+ * Require:
+ * 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setchecksrv(dns_zone_t *zone, dns_checkmxfunc_t checksrv);
+/*%<
+ * Set the post load integrity callback function 'checksrv'.
+ * 'checksrv' will be called if the SRV TARGET is not within the zone.
+ *
+ * Require:
+ * 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns);
+/*%<
+ * Set the post load integrity callback function 'checkmx'.
+ * 'checkmx' will be called if the MX is not within the zone.
+ *
+ * Require:
+ * 'zone' to be a valid zone.
+ */
+
+void
+dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay);
+/*%<
+ * Set the minimum delay between sets of notify messages.
+ *
+ * Requires:
+ * 'zone' to be valid.
+ */
+
+isc_uint32_t
+dns_zone_getnotifydelay(dns_zone_t *zone);
+/*%<
+ * Get the minimum delay between sets of notify messages.
+ *
+ * Requires:
+ * 'zone' to be valid.
+ */
+
+void
+dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg);
+/*%<
+ * Set the isself callback function and argument.
+ *
+ * isc_boolean_t
+ * isself(dns_view_t *myview, dns_tsigkey_t *mykey, isc_netaddr_t *srcaddr,
+ * isc_netaddr_t *destaddr, dns_rdataclass_t rdclass, void *arg);
+ *
+ * 'isself' returns ISC_TRUE if a non-recursive query from 'srcaddr' to
+ * 'destaddr' with optional key 'mykey' for class 'rdclass' would be
+ * delivered to 'myview'.
+ */
+
+void
+dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes);
+/*%<
+ * Set the number of nodes that will be checked per quantum.
+ */
+
+void
+dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures);
+/*%<
+ * Set the number of signatures that will be generated per quantum.
+ */
+
+isc_result_t
+dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
+ isc_uint16_t keyid, isc_boolean_t delete);
+/*%<
+ * Initiate/resume signing of the entire zone with the zone DNSKEY(s)
+ * that match the given algorithm and keyid.
+ */
+
+isc_result_t
+dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param);
+/*%<
+ * Incrementally add a NSEC3 chain that corresponds to 'nsec3param'.
+ */
+
+void
+dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type);
+dns_rdatatype_t
+dns_zone_getprivatetype(dns_zone_t *zone);
+/*
+ * Get/Set the private record type. It is expected that these interfaces
+ * will not be permanent.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_ZONE_H */
diff --git a/lib/dns/include/dns/zonekey.h b/lib/dns/include/dns/zonekey.h
new file mode 100644
index 0000000..d9ba862
--- /dev/null
+++ b/lib/dns/include/dns/zonekey.h
@@ -0,0 +1,42 @@
+/*
+ * 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: zonekey.h,v 1.10 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_ZONEKEY_H
+#define DNS_ZONEKEY_H 1
+
+/*! \file dns/zonekey.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_boolean_t
+dns_zonekey_iszonekey(dns_rdata_t *keyrdata);
+/*%<
+ * Determines if the key record contained in the rdata is a zone key.
+ *
+ * Requires:
+ * 'keyrdata' is not NULL.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_ZONEKEY_H */
diff --git a/lib/dns/include/dns/zt.h b/lib/dns/include/dns/zt.h
new file mode 100644
index 0000000..6cfe3d3
--- /dev/null
+++ b/lib/dns/include/dns/zt.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: zt.h,v 1.38 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_ZT_H
+#define DNS_ZT_H 1
+
+/*! \file dns/zt.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+#define DNS_ZTFIND_NOEXACT 0x01
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **zt);
+/*%<
+ * Creates a new zone table.
+ *
+ * Requires:
+ * \li 'mctx' to be initialized.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS on success.
+ * \li #ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_zt_mount(dns_zt_t *zt, dns_zone_t *zone);
+/*%<
+ * Mounts the zone on the zone table.
+ *
+ * Requires:
+ * \li 'zt' to be valid
+ * \li 'zone' to be valid
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_EXISTS
+ * \li #ISC_R_NOSPACE
+ * \li #ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone);
+/*%<
+ * Unmount the given zone from the table.
+ *
+ * Requires:
+ * 'zt' to be valid
+ * \li 'zone' to be valid
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND
+ * \li #ISC_R_NOMEMORY
+ */
+
+isc_result_t
+dns_zt_find(dns_zt_t *zt, dns_name_t *name, unsigned int options,
+ dns_name_t *foundname, dns_zone_t **zone);
+/*%<
+ * Find the best match for 'name' in 'zt'. If foundname is non NULL
+ * then the name of the zone found is returned.
+ *
+ * Notes:
+ * \li If the DNS_ZTFIND_NOEXACT is set, the best partial match (if any)
+ * to 'name' will be returned.
+ *
+ * Requires:
+ * \li 'zt' to be valid
+ * \li 'name' to be valid
+ * \li 'foundname' to be initialized and associated with a fixedname or NULL
+ * \li 'zone' to be non NULL and '*zone' to be NULL
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #DNS_R_PARTIALMATCH
+ * \li #ISC_R_NOTFOUND
+ * \li #ISC_R_NOSPACE
+ */
+
+void
+dns_zt_detach(dns_zt_t **ztp);
+/*%<
+ * Detach the given zonetable, if the reference count goes to zero the
+ * zonetable will be freed. In either case 'ztp' is set to NULL.
+ *
+ * Requires:
+ * \li '*ztp' to be valid
+ */
+
+void
+dns_zt_flushanddetach(dns_zt_t **ztp);
+/*%<
+ * Detach the given zonetable, if the reference count goes to zero the
+ * zonetable will be flushed and then freed. In either case 'ztp' is
+ * set to NULL.
+ *
+ * Requires:
+ * \li '*ztp' to be valid
+ */
+
+void
+dns_zt_attach(dns_zt_t *zt, dns_zt_t **ztp);
+/*%<
+ * Attach 'zt' to '*ztp'.
+ *
+ * Requires:
+ * \li 'zt' to be valid
+ * \li '*ztp' to be NULL
+ */
+
+isc_result_t
+dns_zt_load(dns_zt_t *zt, isc_boolean_t stop);
+
+isc_result_t
+dns_zt_loadnew(dns_zt_t *zt, isc_boolean_t stop);
+/*%<
+ * Load all zones in the table. If 'stop' is ISC_TRUE,
+ * stop on the first error and return it. If 'stop'
+ * is ISC_FALSE, ignore errors.
+ *
+ * dns_zt_loadnew() only loads zones that are not yet loaded.
+ * dns_zt_load() also loads zones that are already loaded and
+ * and whose master file has changed since the last load.
+ *
+ * Requires:
+ * \li 'zt' to be valid
+ */
+
+isc_result_t
+dns_zt_freezezones(dns_zt_t *zt, isc_boolean_t freeze);
+/*%<
+ * Freeze/thaw updates to master zones.
+ * Any pending updates will be flushed.
+ * Zones will be reloaded on thaw.
+ */
+
+isc_result_t
+dns_zt_apply(dns_zt_t *zt, isc_boolean_t stop,
+ isc_result_t (*action)(dns_zone_t *, void *), void *uap);
+
+isc_result_t
+dns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub,
+ isc_result_t (*action)(dns_zone_t *, void *), void *uap);
+/*%<
+ * Apply a given 'action' to all zone zones in the table.
+ * If 'stop' is 'ISC_TRUE' then walking the zone tree will stop if
+ * 'action' does not return ISC_R_SUCCESS.
+ *
+ * Requires:
+ * \li 'zt' to be valid.
+ * \li 'action' to be non NULL.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS if action was applied to all nodes. If 'stop' is
+ * ISC_FALSE and 'sub' is non NULL then the first error (if any)
+ * reported by 'action' is returned in '*sub';
+ * any error code from 'action'.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_ZT_H */
diff --git a/lib/dns/include/dst/Makefile.in b/lib/dns/include/dst/Makefile.in
new file mode 100644
index 0000000..4ed4ec0
--- /dev/null
+++ b/lib/dns/include/dst/Makefile.in
@@ -0,0 +1,37 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.4 2007/12/11 20:28:55 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @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}${includedir}/dst
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/dst ; \
+ done
diff --git a/lib/dns/include/dst/dst.h b/lib/dns/include/dst/dst.h
new file mode 100644
index 0000000..702ad71
--- /dev/null
+++ b/lib/dns/include/dst/dst.h
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: dst.h,v 1.12 2008/09/24 02:46:23 marka Exp $ */
+
+#ifndef DST_DST_H
+#define DST_DST_H 1
+
+/*! \file dst/dst.h */
+
+#include <isc/lang.h>
+
+#include <dns/types.h>
+
+#include <dst/gssapi.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+/*%
+ * The dst_key structure is opaque. Applications should use the accessor
+ * functions provided to retrieve key attributes. If an application needs
+ * to set attributes, new accessor functions will be written.
+ */
+
+typedef struct dst_key dst_key_t;
+typedef struct dst_context dst_context_t;
+
+/* DST algorithm codes */
+#define DST_ALG_UNKNOWN 0
+#define DST_ALG_RSAMD5 1
+#define DST_ALG_RSA DST_ALG_RSAMD5 /*%< backwards compatibility */
+#define DST_ALG_DH 2
+#define DST_ALG_DSA 3
+#define DST_ALG_ECC 4
+#define DST_ALG_RSASHA1 5
+#define DST_ALG_NSEC3DSA 6
+#define DST_ALG_NSEC3RSASHA1 7
+#define DST_ALG_HMACMD5 157
+#define DST_ALG_GSSAPI 160
+#define DST_ALG_HMACSHA1 161 /* XXXMPA */
+#define DST_ALG_HMACSHA224 162 /* XXXMPA */
+#define DST_ALG_HMACSHA256 163 /* XXXMPA */
+#define DST_ALG_HMACSHA384 164 /* XXXMPA */
+#define DST_ALG_HMACSHA512 165 /* XXXMPA */
+#define DST_ALG_PRIVATE 254
+#define DST_ALG_EXPAND 255
+#define DST_MAX_ALGS 255
+
+/*% A buffer of this size is large enough to hold any key */
+#define DST_KEY_MAXSIZE 1280
+
+/*%
+ * A buffer of this size is large enough to hold the textual representation
+ * of any key
+ */
+#define DST_KEY_MAXTEXTSIZE 2048
+
+/*% 'Type' for dst_read_key() */
+#define DST_TYPE_KEY 0x1000000 /* KEY key */
+#define DST_TYPE_PRIVATE 0x2000000
+#define DST_TYPE_PUBLIC 0x4000000
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+dst_lib_init(isc_mem_t *mctx, isc_entropy_t *ectx, unsigned int eflags);
+/*%<
+ * Initializes the DST subsystem.
+ *
+ * Requires:
+ * \li "mctx" is a valid memory context
+ * \li "ectx" is a valid entropy context
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOMEMORY
+ *
+ * Ensures:
+ * \li DST is properly initialized.
+ */
+
+void
+dst_lib_destroy(void);
+/*%<
+ * Releases all resources allocated by DST.
+ */
+
+isc_boolean_t
+dst_algorithm_supported(unsigned int alg);
+/*%<
+ * Checks that a given algorithm is supported by DST.
+ *
+ * Returns:
+ * \li ISC_TRUE
+ * \li ISC_FALSE
+ */
+
+isc_result_t
+dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp);
+/*%<
+ * Creates a context to be used for a sign or verify operation.
+ *
+ * Requires:
+ * \li "key" is a valid key.
+ * \li "mctx" is a valid memory context.
+ * \li dctxp != NULL && *dctxp == NULL
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOMEMORY
+ *
+ * Ensures:
+ * \li *dctxp will contain a usable context.
+ */
+
+void
+dst_context_destroy(dst_context_t **dctxp);
+/*%<
+ * Destroys all memory associated with a context.
+ *
+ * Requires:
+ * \li *dctxp != NULL && *dctxp == NULL
+ *
+ * Ensures:
+ * \li *dctxp == NULL
+ */
+
+isc_result_t
+dst_context_adddata(dst_context_t *dctx, const isc_region_t *data);
+/*%<
+ * Incrementally adds data to the context to be used in a sign or verify
+ * operation.
+ *
+ * Requires:
+ * \li "dctx" is a valid context
+ * \li "data" is a valid region
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li DST_R_SIGNFAILURE
+ * \li all other errors indicate failure
+ */
+
+isc_result_t
+dst_context_sign(dst_context_t *dctx, isc_buffer_t *sig);
+/*%<
+ * Computes a signature using the data and key stored in the context.
+ *
+ * Requires:
+ * \li "dctx" is a valid context.
+ * \li "sig" is a valid buffer.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li DST_R_VERIFYFAILURE
+ * \li all other errors indicate failure
+ *
+ * Ensures:
+ * \li "sig" will contain the signature
+ */
+
+isc_result_t
+dst_context_verify(dst_context_t *dctx, isc_region_t *sig);
+/*%<
+ * Verifies the signature using the data and key stored in the context.
+ *
+ * Requires:
+ * \li "dctx" is a valid context.
+ * \li "sig" is a valid region.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li all other errors indicate failure
+ *
+ * Ensures:
+ * \li "sig" will contain the signature
+ */
+
+isc_result_t
+dst_key_computesecret(const dst_key_t *pub, const dst_key_t *priv,
+ isc_buffer_t *secret);
+/*%<
+ * Computes a shared secret from two (Diffie-Hellman) keys.
+ *
+ * Requires:
+ * \li "pub" is a valid key that can be used to derive a shared secret
+ * \li "priv" is a valid private key that can be used to derive a shared secret
+ * \li "secret" is a valid buffer
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ * \li If successful, secret will contain the derived shared secret.
+ */
+
+isc_result_t
+dst_key_fromfile(dns_name_t *name, dns_keytag_t id, unsigned int alg, int type,
+ const char *directory, isc_mem_t *mctx, dst_key_t **keyp);
+/*%<
+ * Reads a key from permanent storage. The key can either be a public or
+ * private key, and is specified by name, algorithm, and id. If a private key
+ * is specified, the public key must also be present. If directory is NULL,
+ * the current directory is assumed.
+ *
+ * Requires:
+ * \li "name" is a valid absolute dns name.
+ * \li "id" is a valid key tag identifier.
+ * \li "alg" is a supported key algorithm.
+ * \li "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or the bitwise union.
+ * DST_TYPE_KEY look for a KEY record otherwise DNSKEY
+ * \li "mctx" is a valid memory context.
+ * \li "keyp" is not NULL and "*keyp" is NULL.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ * \li If successful, *keyp will contain a valid key.
+ */
+
+isc_result_t
+dst_key_fromnamedfile(const char *filename, 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.
+ *
+ * Requires:
+ * \li "filename" is not NULL
+ * \li "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or the bitwise union
+ * DST_TYPE_KEY look for a KEY record otherwise DNSKEY
+ * \li "mctx" is a valid memory context
+ * \li "keyp" is not NULL and "*keyp" is NULL.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ * \li If successful, *keyp will contain a valid key.
+ */
+
+
+isc_result_t
+dst_key_read_public(const char *filename, int type,
+ isc_mem_t *mctx, dst_key_t **keyp);
+/*%<
+ * Reads a public key from permanent storage. The key must be a public key.
+ *
+ * Requires:
+ * \li "filename" is not NULL
+ * \li "type" is DST_TYPE_KEY look for a KEY record otherwise DNSKEY
+ * \li "mctx" is a valid memory context
+ * \li "keyp" is not NULL and "*keyp" is NULL.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li DST_R_BADKEYTYPE if the key type is not the expected one
+ * \li ISC_R_UNEXPECTEDTOKEN if the file can not be parsed as a public key
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ * \li If successful, *keyp will contain a valid key.
+ */
+
+isc_result_t
+dst_key_tofile(const dst_key_t *key, int type, const char *directory);
+/*%<
+ * Writes a key to permanent storage. The key can either be a public or
+ * private key. Public keys are written in DNS format and private keys
+ * are written as a set of base64 encoded values. If directory is NULL,
+ * the current directory is assumed.
+ *
+ * Requires:
+ * \li "key" is a valid key.
+ * \li "type" is DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or the bitwise union
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ */
+
+isc_result_t
+dst_key_fromdns(dns_name_t *name, dns_rdataclass_t rdclass,
+ isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
+/*%<
+ * Converts a DNS KEY record into a DST key.
+ *
+ * Requires:
+ * \li "name" is a valid absolute dns name.
+ * \li "source" is a valid buffer. There must be at least 4 bytes available.
+ * \li "mctx" is a valid memory context.
+ * \li "keyp" is not NULL and "*keyp" is NULL.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ * \li If successful, *keyp will contain a valid key, and the consumed
+ * pointer in data will be advanced.
+ */
+
+isc_result_t
+dst_key_todns(const dst_key_t *key, isc_buffer_t *target);
+/*%<
+ * Converts a DST key into a DNS KEY record.
+ *
+ * Requires:
+ * \li "key" is a valid key.
+ * \li "target" is a valid buffer. There must be at least 4 bytes unused.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ * \li If successful, the used pointer in 'target' is advanced by at least 4.
+ */
+
+isc_result_t
+dst_key_frombuffer(dns_name_t *name, unsigned int alg,
+ unsigned int flags, unsigned int protocol,
+ dns_rdataclass_t rdclass,
+ isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
+/*%<
+ * Converts a buffer containing DNS KEY RDATA into a DST key.
+ *
+ * Requires:
+ *\li "name" is a valid absolute dns name.
+ *\li "alg" is a supported key algorithm.
+ *\li "source" is a valid buffer.
+ *\li "mctx" is a valid memory context.
+ *\li "keyp" is not NULL and "*keyp" is NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ *\li If successful, *keyp will contain a valid key, and the consumed
+ * pointer in source will be advanced.
+ */
+
+isc_result_t
+dst_key_tobuffer(const dst_key_t *key, isc_buffer_t *target);
+/*%<
+ * Converts a DST key into DNS KEY RDATA format.
+ *
+ * Requires:
+ *\li "key" is a valid key.
+ *\li "target" is a valid buffer.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ *\li If successful, the used pointer in 'target' is advanced.
+ */
+
+isc_result_t
+dst_key_privatefrombuffer(dst_key_t *key, isc_buffer_t *buffer);
+/*%<
+ * Converts a public key into a private key, reading the private key
+ * information from the buffer. The buffer should contain the same data
+ * as the .private key file would.
+ *
+ * Requires:
+ *\li "key" is a valid public key.
+ *\li "buffer" is not NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ *\li If successful, key will contain a valid private key.
+ */
+
+gss_ctx_id_t
+dst_key_getgssctx(const dst_key_t *key);
+/*%<
+ * Returns the opaque key data.
+ * Be cautions when using this value unless you know what you are doing.
+ *
+ * Requires:
+ *\li "key" is not NULL.
+ *
+ * Returns:
+ *\li gssctx key data, possibly NULL.
+ */
+
+isc_result_t
+dst_key_fromgssapi(dns_name_t *name, gss_ctx_id_t gssctx, isc_mem_t *mctx,
+ dst_key_t **keyp);
+/*%<
+ * Converts a GSSAPI opaque context id into a DST key.
+ *
+ * Requires:
+ *\li "name" is a valid absolute dns name.
+ *\li "gssctx" is a GSSAPI context id.
+ *\li "mctx" is a valid memory context.
+ *\li "keyp" is not NULL and "*keyp" is NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ *\li If successful, *keyp will contain a valid key and be responsible for
+ * the context id.
+ */
+
+isc_result_t
+dst_key_fromlabel(dns_name_t *name, int alg, unsigned int flags,
+ unsigned int protocol, dns_rdataclass_t rdclass,
+ const char *engine, const char *label, const char *pin,
+ isc_mem_t *mctx, dst_key_t **keyp);
+
+isc_result_t
+dst_key_generate(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);
+/*%<
+ * Generate a DST key (or keypair) with the supplied parameters. The
+ * interpretation of the "param" field depends on the algorithm:
+ * \code
+ * RSA: exponent
+ * 0 use exponent 3
+ * !0 use Fermat4 (2^16 + 1)
+ * DH: generator
+ * 0 default - use well known prime if bits == 768 or 1024,
+ * otherwise use 2 as the generator.
+ * !0 use this value as the generator.
+ * DSA: unused
+ * HMACMD5: entropy
+ * 0 default - require good entropy
+ * !0 lack of good entropy is ok
+ *\endcode
+ *
+ * Requires:
+ *\li "name" is a valid absolute dns name.
+ *\li "keyp" is not NULL and "*keyp" is NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ * \li any other result indicates failure
+ *
+ * Ensures:
+ *\li If successful, *keyp will contain a valid key.
+ */
+
+isc_boolean_t
+dst_key_compare(const dst_key_t *key1, const dst_key_t *key2);
+/*%<
+ * Compares two DST keys.
+ *
+ * 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_paramcompare(const dst_key_t *key1, const dst_key_t *key2);
+/*%<
+ * Compares the parameters of two DST keys. This is used to determine if
+ * two (Diffie-Hellman) keys can be used to derive a shared secret.
+ *
+ * Requires:
+ *\li "key1" is a valid key.
+ *\li "key2" is a valid key.
+ *
+ * Returns:
+ *\li ISC_TRUE
+ * \li ISC_FALSE
+ */
+
+void
+dst_key_free(dst_key_t **keyp);
+/*%<
+ * Release all memory associated with the key.
+ *
+ * Requires:
+ *\li "keyp" is not NULL and "*keyp" is a valid key.
+ *
+ * Ensures:
+ *\li All memory associated with "*keyp" will be freed.
+ *\li *keyp == NULL
+ */
+
+/*%<
+ * Accessor functions to obtain key fields.
+ *
+ * Require:
+ *\li "key" is a valid key.
+ */
+dns_name_t *
+dst_key_name(const dst_key_t *key);
+
+unsigned int
+dst_key_size(const dst_key_t *key);
+
+unsigned int
+dst_key_proto(const dst_key_t *key);
+
+unsigned int
+dst_key_alg(const dst_key_t *key);
+
+isc_uint32_t
+dst_key_flags(const dst_key_t *key);
+
+dns_keytag_t
+dst_key_id(const dst_key_t *key);
+
+dns_rdataclass_t
+dst_key_class(const dst_key_t *key);
+
+isc_boolean_t
+dst_key_isprivate(const dst_key_t *key);
+
+isc_boolean_t
+dst_key_iszonekey(const dst_key_t *key);
+
+isc_boolean_t
+dst_key_isnullkey(const dst_key_t *key);
+
+isc_result_t
+dst_key_buildfilename(const dst_key_t *key, int type,
+ const char *directory, isc_buffer_t *out);
+/*%<
+ * Generates the filename used by dst to store the specified key.
+ * If directory is NULL, the current directory is assumed.
+ *
+ * Requires:
+ *\li "key" is a valid key
+ *\li "type" is either DST_TYPE_PUBLIC, DST_TYPE_PRIVATE, or 0 for no suffix.
+ *\li "out" is a valid buffer
+ *
+ * Ensures:
+ *\li the file name will be written to "out", and the used pointer will
+ * be advanced.
+ */
+
+isc_result_t
+dst_key_sigsize(const dst_key_t *key, unsigned int *n);
+/*%<
+ * Computes the size of a signature generated by the given key.
+ *
+ * Requires:
+ *\li "key" is a valid key.
+ *\li "n" is not NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li DST_R_UNSUPPORTEDALG
+ *
+ * Ensures:
+ *\li "n" stores the size of a generated signature
+ */
+
+isc_result_t
+dst_key_secretsize(const dst_key_t *key, unsigned int *n);
+/*%<
+ * Computes the size of a shared secret generated by the given key.
+ *
+ * Requires:
+ *\li "key" is a valid key.
+ *\li "n" is not NULL
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li DST_R_UNSUPPORTEDALG
+ *
+ * Ensures:
+ *\li "n" stores the size of a generated shared secret
+ */
+
+isc_uint16_t
+dst_region_computeid(const isc_region_t *source, unsigned int alg);
+/*%<
+ * Computes the key id of the key stored in the provided region with the
+ * given algorithm.
+ *
+ * Requires:
+ *\li "source" contains a valid, non-NULL region.
+ *
+ * Returns:
+ *\li the key id
+ */
+
+isc_uint16_t
+dst_key_getbits(const dst_key_t *key);
+/*
+ * Get the number of digest bits required (0 == MAX).
+ *
+ * Requires:
+ * "key" is a valid 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_LANG_ENDDECLS
+
+#endif /* DST_DST_H */
diff --git a/lib/dns/include/dst/gssapi.h b/lib/dns/include/dst/gssapi.h
new file mode 100644
index 0000000..7d1d487
--- /dev/null
+++ b/lib/dns/include/dst/gssapi.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2004-2007 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: gssapi.h,v 1.9 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DST_GSSAPI_H
+#define DST_GSSAPI_H 1
+
+/*! \file dst/gssapi.h */
+
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+#include <dns/types.h>
+
+#ifdef GSSAPI
+#ifdef _WINDOWS
+/*
+ * MSVC does not like macros in #include lines.
+ */
+#include <gssapi/gssapi.h>
+#else
+#include ISC_PLATFORM_GSSAPIHEADER
+#endif
+#ifndef GSS_SPNEGO_MECHANISM
+#define GSS_SPNEGO_MECHANISM ((void*)0)
+#endif
+#endif
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+dst_gssapi_acquirecred(dns_name_t *name, isc_boolean_t initiate,
+ gss_cred_id_t *cred);
+/*
+ * Acquires GSS credentials.
+ *
+ * Requires:
+ * 'name' is a valid name, preferably one known by the GSS provider
+ * 'initiate' indicates whether the credentials are for initiating or
+ * accepting contexts
+ * 'cred' is a pointer to NULL, which will be allocated with the
+ * credential handle. Call dst_gssapi_releasecred to free
+ * the memory.
+ *
+ * Returns:
+ * ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ * other an error occurred while building the message
+ */
+
+isc_result_t
+dst_gssapi_releasecred(gss_cred_id_t *cred);
+/*
+ * Releases GSS credentials. Calling this function does release the
+ * memory allocated for the credential in dst_gssapi_acquirecred()
+ *
+ * Requires:
+ * 'mctx' is a valid memory context
+ * 'cred' is a pointer to the credential to be released
+ *
+ * Returns:
+ * ISC_R_SUCCESS credential was released successfully
+ * other an error occurred while releaseing
+ * the credential
+ */
+
+isc_result_t
+dst_gssapi_initctx(dns_name_t *name, isc_buffer_t *intoken,
+ isc_buffer_t *outtoken, gss_ctx_id_t *gssctx);
+/*
+ * Initiates a GSS context.
+ *
+ * Requires:
+ * 'name' is a valid name, preferably one known by the GSS
+ * provider
+ * 'intoken' is a token received from the acceptor, or NULL if
+ * there isn't one
+ * 'outtoken' is a buffer to receive the token generated by
+ * gss_init_sec_context() to be sent to the acceptor
+ * 'context' is a pointer to a valid gss_ctx_id_t
+ * (which may have the value GSS_C_NO_CONTEXT)
+ *
+ * Returns:
+ * ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ * other an error occurred while building the message
+ */
+
+isc_result_t
+dst_gssapi_acceptctx(gss_cred_id_t cred,
+ isc_region_t *intoken, isc_buffer_t **outtoken,
+ gss_ctx_id_t *context, dns_name_t *principal,
+ isc_mem_t *mctx);
+/*
+ * Accepts a GSS context.
+ *
+ * Requires:
+ * 'mctx' is a valid memory context
+ * 'cred' is the acceptor's valid GSS credential handle
+ * 'intoken' is a token received from the initiator
+ * 'outtoken' is a pointer a buffer pointer used to return the token
+ * generated by gss_accept_sec_context() to be sent to the
+ * initiator
+ * 'context' is a valid pointer to receive the generated context handle.
+ * On the initial call, it should be a pointer to NULL, which
+ * will be allocated as a gss_ctx_id_t. Subsequent calls
+ * should pass in the handle generated on the first call.
+ * Call dst_gssapi_releasecred to delete the context and free
+ * the memory.
+ *
+ * Requires:
+ * 'outtoken' to != NULL && *outtoken == NULL.
+ *
+ * Returns:
+ * ISC_R_SUCCESS msg was successfully updated to include the
+ * query to be sent
+ * other an error occurred while building the message
+ */
+
+isc_result_t
+dst_gssapi_deletectx(isc_mem_t *mctx, gss_ctx_id_t *gssctx);
+/*
+ * Destroys a GSS context. This function deletes the context from the GSS
+ * provider and then frees the memory used by the context pointer.
+ *
+ * Requires:
+ * 'mctx' is a valid memory context
+ * 'context' is a valid GSS context
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ */
+
+
+void
+gss_log(int level, const char *fmt, ...)
+ISC_FORMAT_PRINTF(2, 3);
+/*
+ * Loging function for GSS.
+ *
+ * Requires
+ * 'level' is the log level to be used, as an integer
+ * 'fmt' is a printf format specifier
+ */
+
+char *
+gss_error_tostring(isc_uint32_t major, isc_uint32_t minor,
+ char *buf, size_t buflen);
+/*
+ * Render a GSS major status/minor status pair into a string
+ *
+ * Requires:
+ * 'major' is a GSS major status code
+ * 'minor' is a GSS minor status code
+ *
+ * Returns:
+ * A string containing the text representation of the error codes.
+ * Users should copy the string if they wish to keep it.
+ */
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmkrb5(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm);
+/*
+ * Compare a "signer" (in the format of a Kerberos-format Kerberos5
+ * printipal: host/example.com@EXAMPLE.COM) to the realm name stored
+ * in "name" (which represents the realm name).
+ *
+ */
+
+isc_boolean_t
+dst_gssapi_identitymatchesrealmms(dns_name_t *signer, dns_name_t *name,
+ dns_name_t *realm);
+/*
+ * Compare a "signer" (in the format of a Kerberos-format Kerberos5
+ * printipal: host/example.com@EXAMPLE.COM) to the realm name stored
+ * in "name" (which represents the realm name).
+ *
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DST_GSSAPI_H */
diff --git a/lib/dns/include/dst/lib.h b/lib/dns/include/dst/lib.h
new file mode 100644
index 0000000..886575e
--- /dev/null
+++ b/lib/dns/include/dst/lib.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: lib.h,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DST_LIB_H
+#define DST_LIB_H 1
+
+/*! \file dst/lib.h */
+
+#include <isc/types.h>
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+LIBDNS_EXTERNAL_DATA extern isc_msgcat_t *dst_msgcat;
+
+void
+dst_lib_initmsgcat(void);
+/*
+ * Initialize the DST library's message catalog, dst_msgcat, if it
+ * has not already been initialized.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DST_LIB_H */
diff --git a/lib/dns/include/dst/result.h b/lib/dns/include/dst/result.h
new file mode 100644
index 0000000..d77b72e
--- /dev/null
+++ b/lib/dns/include/dst/result.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: result.h,v 1.9 2008/04/01 23:47:10 tbox Exp $ */
+
+#ifndef DST_RESULT_H
+#define DST_RESULT_H 1
+
+/*! \file dst/result.h */
+
+#include <isc/lang.h>
+#include <isc/resultclass.h>
+
+/*
+ * Nothing in this file truly depends on <isc/result.h>, but the
+ * DST result codes are considered to be publicly derived from
+ * the ISC result codes, so including this file buys you the ISC_R_
+ * namespace too.
+ */
+#include <isc/result.h> /* Contractual promise. */
+
+#define DST_R_UNSUPPORTEDALG (ISC_RESULTCLASS_DST + 0)
+#define DST_R_OPENSSLFAILURE (ISC_RESULTCLASS_DST + 1)
+#define DST_R_NOCRYPTO (ISC_RESULTCLASS_DST + 2)
+#define DST_R_NULLKEY (ISC_RESULTCLASS_DST + 3)
+#define DST_R_INVALIDPUBLICKEY (ISC_RESULTCLASS_DST + 4)
+#define DST_R_INVALIDPRIVATEKEY (ISC_RESULTCLASS_DST + 5)
+/* 6 is unused */
+#define DST_R_WRITEERROR (ISC_RESULTCLASS_DST + 7)
+#define DST_R_INVALIDPARAM (ISC_RESULTCLASS_DST + 8)
+/* 9 is unused */
+/* 10 is unused */
+#define DST_R_SIGNFAILURE (ISC_RESULTCLASS_DST + 11)
+/* 12 is unused */
+/* 13 is unused */
+#define DST_R_VERIFYFAILURE (ISC_RESULTCLASS_DST + 14)
+#define DST_R_NOTPUBLICKEY (ISC_RESULTCLASS_DST + 15)
+#define DST_R_NOTPRIVATEKEY (ISC_RESULTCLASS_DST + 16)
+#define DST_R_KEYCANNOTCOMPUTESECRET (ISC_RESULTCLASS_DST + 17)
+#define DST_R_COMPUTESECRETFAILURE (ISC_RESULTCLASS_DST + 18)
+#define DST_R_NORANDOMNESS (ISC_RESULTCLASS_DST + 19)
+#define DST_R_BADKEYTYPE (ISC_RESULTCLASS_DST + 20)
+#define DST_R_NOENGINE (ISC_RESULTCLASS_DST + 21)
+
+#define DST_R_NRESULTS 22 /* Number of results */
+
+ISC_LANG_BEGINDECLS
+
+const char *
+dst_result_totext(isc_result_t);
+
+void
+dst_result_register(void);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DST_RESULT_H */
diff --git a/lib/dns/iptable.c b/lib/dns/iptable.c
new file mode 100644
index 0000000..5e9c63f
--- /dev/null
+++ b/lib/dns/iptable.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2007, 2008 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: iptable.c,v 1.12 2008/09/26 21:12:02 each Exp $ */
+
+#include <isc/mem.h>
+#include <isc/radix.h>
+
+#include <dns/acl.h>
+
+static void destroy_iptable(dns_iptable_t *dtab);
+
+/*
+ * Create a new IP table and the underlying radix structure
+ */
+isc_result_t
+dns_iptable_create(isc_mem_t *mctx, dns_iptable_t **target) {
+ isc_result_t result;
+ dns_iptable_t *tab;
+
+ tab = isc_mem_get(mctx, sizeof(*tab));
+ if (tab == NULL)
+ return (ISC_R_NOMEMORY);
+ tab->mctx = mctx;
+ isc_refcount_init(&tab->refcount, 1);
+ tab->magic = DNS_IPTABLE_MAGIC;
+
+ result = isc_radix_create(mctx, &tab->radix, RADIX_MAXBITS);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ *target = tab;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_iptable_detach(&tab);
+ return (result);
+}
+
+isc_boolean_t dns_iptable_neg = ISC_FALSE;
+isc_boolean_t dns_iptable_pos = ISC_TRUE;
+
+/*
+ * Add an IP prefix to an existing IP table
+ */
+isc_result_t
+dns_iptable_addprefix(dns_iptable_t *tab, isc_netaddr_t *addr,
+ isc_uint16_t bitlen, isc_boolean_t pos)
+{
+ isc_result_t result;
+ isc_prefix_t pfx;
+ isc_radix_node_t *node = NULL;
+ int family;
+
+ INSIST(DNS_IPTABLE_VALID(tab));
+ INSIST(tab->radix);
+
+ NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
+
+ result = isc_radix_insert(tab->radix, &node, NULL, &pfx);
+ if (result != ISC_R_SUCCESS) {
+ isc_refcount_destroy(&pfx.refcount);
+ return(result);
+ }
+
+ /* If a node already contains data, don't overwrite it */
+ family = pfx.family;
+ if (family == AF_UNSPEC) {
+ /* "any" or "none" */
+ INSIST(pfx.bitlen == 0);
+ if (pos) {
+ if (node->data[0] == NULL)
+ node->data[0] = &dns_iptable_pos;
+ if (node->data[1] == NULL)
+ node->data[1] = &dns_iptable_pos;
+ } else {
+ if (node->data[0] == NULL)
+ node->data[0] = &dns_iptable_neg;
+ if (node->data[1] == NULL)
+ node->data[1] = &dns_iptable_neg;
+ }
+ } else {
+ /* any other prefix */
+ if (node->data[ISC_IS6(family)] == NULL) {
+ if (pos)
+ node->data[ISC_IS6(family)] = &dns_iptable_pos;
+ else
+ node->data[ISC_IS6(family)] = &dns_iptable_neg;
+ }
+ }
+
+ isc_refcount_destroy(&pfx.refcount);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Merge one IP table into another one.
+ */
+isc_result_t
+dns_iptable_merge(dns_iptable_t *tab, dns_iptable_t *source, isc_boolean_t pos)
+{
+ isc_result_t result;
+ isc_radix_node_t *node, *new_node;
+ int max_node = 0;
+
+ RADIX_WALK (source->radix->head, node) {
+ new_node = NULL;
+ result = isc_radix_insert (tab->radix, &new_node, node, NULL);
+
+ if (result != ISC_R_SUCCESS)
+ return(result);
+
+ /*
+ * If we're negating a nested ACL, then we should
+ * reverse the sense of every node. However, this
+ * could lead to a negative node in a nested ACL
+ * becoming a positive match in the parent, which
+ * could be a security risk. To prevent this, we
+ * just leave the negative nodes negative.
+ */
+ if (!pos) {
+ if (node->data[0] &&
+ *(isc_boolean_t *) node->data[0] == ISC_TRUE)
+ new_node->data[0] = &dns_iptable_neg;
+
+ if (node->data[1] &&
+ *(isc_boolean_t *) node->data[1] == ISC_TRUE)
+ new_node->data[1] = &dns_iptable_neg;
+ }
+
+ if (node->node_num[0] > max_node)
+ max_node = node->node_num[0];
+ if (node->node_num[1] > max_node)
+ max_node = node->node_num[1];
+ } RADIX_WALK_END;
+
+ tab->radix->num_added_node += max_node;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_iptable_attach(dns_iptable_t *source, dns_iptable_t **target) {
+ REQUIRE(DNS_IPTABLE_VALID(source));
+ isc_refcount_increment(&source->refcount, NULL);
+ *target = source;
+}
+
+void
+dns_iptable_detach(dns_iptable_t **tabp) {
+ dns_iptable_t *tab = *tabp;
+ unsigned int refs;
+ REQUIRE(DNS_IPTABLE_VALID(tab));
+ isc_refcount_decrement(&tab->refcount, &refs);
+ if (refs == 0)
+ destroy_iptable(tab);
+ *tabp = NULL;
+}
+
+static void
+destroy_iptable(dns_iptable_t *dtab) {
+
+ REQUIRE(DNS_IPTABLE_VALID(dtab));
+
+ if (dtab->radix != NULL) {
+ isc_radix_destroy(dtab->radix, NULL);
+ dtab->radix = NULL;
+ }
+
+ isc_refcount_destroy(&dtab->refcount);
+ dtab->magic = 0;
+ isc_mem_put(dtab->mctx, dtab, sizeof(*dtab));
+}
diff --git a/lib/dns/journal.c b/lib/dns/journal.c
new file mode 100644
index 0000000..e84ade3
--- /dev/null
+++ b/lib/dns/journal.c
@@ -0,0 +1,2217 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: journal.c,v 1.103 2008/09/25 02:01:45 marka Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <isc/file.h>
+#include <isc/mem.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/compress.h>
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/diff.h>
+#include <dns/fixedname.h>
+#include <dns/journal.h>
+#include <dns/log.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+#include <dns/soa.h>
+
+/*! \file
+ * \brief Journalling.
+ *
+ * A journal file consists of
+ *
+ * \li A fixed-size header of type journal_rawheader_t.
+ *
+ * \li The index. This is an unordered array of index entries
+ * of type journal_rawpos_t giving the locations
+ * of some arbitrary subset of the journal's addressable
+ * transactions. The index entries are used as hints to
+ * speed up the process of locating a transaction with a given
+ * serial number. Unused index entries have an "offset"
+ * field of zero. The size of the index can vary between
+ * journal files, but does not change during the lifetime
+ * of a file. The size can be zero.
+ *
+ * \li The journal data. This consists of one or more transactions.
+ * Each transaction begins with a transaction header of type
+ * journal_rawxhdr_t. The transaction header is followed by a
+ * sequence of RRs, similar in structure to an IXFR difference
+ * sequence (RFC1995). That is, the pre-transaction SOA,
+ * zero or more other deleted RRs, the post-transaction SOA,
+ * and zero or more other added RRs. Unlike in IXFR, each RR
+ * is prefixed with a 32-bit length.
+ *
+ * The journal data part grows as new transactions are
+ * appended to the file. Only those transactions
+ * whose serial number is current-(2^31-1) to current
+ * are considered "addressable" and may be pointed
+ * to from the header or index. They may be preceded
+ * by old transactions that are no longer addressable,
+ * and they may be followed by transactions that were
+ * appended to the journal but never committed by updating
+ * the "end" position in the header. The latter will
+ * be overwritten when new transactions are added.
+ */
+/*%
+ * When true, accept IXFR difference sequences where the
+ * SOA serial number does not change (BIND 8 sends such
+ * sequences).
+ */
+static isc_boolean_t bind8_compat = ISC_TRUE; /* XXX config */
+
+/**************************************************************************/
+/*
+ * Miscellaneous utilities.
+ */
+
+#define JOURNAL_COMMON_LOGARGS \
+ dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_JOURNAL
+
+#define JOURNAL_DEBUG_LOGARGS(n) \
+ JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
+
+/*%
+ * It would be non-sensical (or at least obtuse) to use FAIL() with an
+ * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+#define FAIL(code) \
+ do { result = (code); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+static isc_result_t index_to_disk(dns_journal_t *);
+
+static inline isc_uint32_t
+decode_uint32(unsigned char *p) {
+ return ((p[0] << 24) +
+ (p[1] << 16) +
+ (p[2] << 8) +
+ (p[3] << 0));
+}
+
+static inline void
+encode_uint32(isc_uint32_t val, unsigned char *p) {
+ p[0] = (isc_uint8_t)(val >> 24);
+ p[1] = (isc_uint8_t)(val >> 16);
+ p[2] = (isc_uint8_t)(val >> 8);
+ p[3] = (isc_uint8_t)(val >> 0);
+}
+
+isc_result_t
+dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
+ dns_diffop_t op, dns_difftuple_t **tp)
+{
+ isc_result_t result;
+ dns_dbnode_t *node;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_name_t *zonename;
+
+ zonename = dns_db_origin(db);
+
+ node = NULL;
+ result = dns_db_findnode(db, zonename, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ goto nonode;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0,
+ (isc_stdtime_t)0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto freenode;
+
+ result = dns_rdataset_first(&rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto freenode;
+
+ dns_rdataset_current(&rdataset, &rdata);
+
+ result = dns_difftuple_create(mctx, op, zonename, rdataset.ttl,
+ &rdata, tp);
+
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+ return (ISC_R_SUCCESS);
+
+ freenode:
+ dns_db_detachnode(db, &node);
+ nonode:
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "missing SOA");
+ return (result);
+}
+
+/* Journalling */
+
+/*%
+ * On-disk representation of a "pointer" to a journal entry.
+ * These are used in the journal header to locate the beginning
+ * and end of the journal, and in the journal index to locate
+ * other transactions.
+ */
+typedef struct {
+ unsigned char serial[4]; /*%< SOA serial before update. */
+ /*
+ * XXXRTH Should offset be 8 bytes?
+ * XXXDCL ... probably, since isc_offset_t is 8 bytes on many OSs.
+ * XXXAG ... but we will not be able to seek >2G anyway on many
+ * platforms as long as we are using fseek() rather
+ * than lseek().
+ */
+ unsigned char offset[4]; /*%< Offset from beginning of file. */
+} journal_rawpos_t;
+
+
+/*%
+ * The header is of a fixed size, with some spare room for future
+ * extensions.
+ */
+#define JOURNAL_HEADER_SIZE 64 /* Bytes. */
+
+/*%
+ * The on-disk representation of the journal header.
+ * All numbers are stored in big-endian order.
+ */
+typedef union {
+ struct {
+ /*% File format version ID. */
+ unsigned char format[16];
+ /*% Position of the first addressable transaction */
+ journal_rawpos_t begin;
+ /*% Position of the next (yet nonexistent) transaction. */
+ journal_rawpos_t end;
+ /*% Number of index entries following the header. */
+ unsigned char index_size[4];
+ } h;
+ /* Pad the header to a fixed size. */
+ unsigned char pad[JOURNAL_HEADER_SIZE];
+} journal_rawheader_t;
+
+/*%
+ * The on-disk representation of the transaction header.
+ * There is one of these at the beginning of each transaction.
+ */
+typedef struct {
+ unsigned char size[4]; /*%< In bytes, excluding header. */
+ unsigned char serial0[4]; /*%< SOA serial before update. */
+ unsigned char serial1[4]; /*%< SOA serial after update. */
+} journal_rawxhdr_t;
+
+/*%
+ * The on-disk representation of the RR header.
+ * There is one of these at the beginning of each RR.
+ */
+typedef struct {
+ unsigned char size[4]; /*%< In bytes, excluding header. */
+} journal_rawrrhdr_t;
+
+/*%
+ * The in-core representation of the journal header.
+ */
+typedef struct {
+ isc_uint32_t serial;
+ isc_offset_t offset;
+} journal_pos_t;
+
+#define POS_VALID(pos) ((pos).offset != 0)
+#define POS_INVALIDATE(pos) ((pos).offset = 0, (pos).serial = 0)
+
+typedef struct {
+ unsigned char format[16];
+ journal_pos_t begin;
+ journal_pos_t end;
+ isc_uint32_t index_size;
+} journal_header_t;
+
+/*%
+ * The in-core representation of the transaction header.
+ */
+
+typedef struct {
+ isc_uint32_t size;
+ isc_uint32_t serial0;
+ isc_uint32_t serial1;
+} journal_xhdr_t;
+
+/*%
+ * The in-core representation of the RR header.
+ */
+typedef struct {
+ isc_uint32_t size;
+} journal_rrhdr_t;
+
+
+/*%
+ * Initial contents to store in the header of a newly created
+ * journal file.
+ *
+ * The header starts with the magic string ";BIND LOG V9\n"
+ * to identify the file as a BIND 9 journal file. An ASCII
+ * identification string is used rather than a binary magic
+ * number to be consistent with BIND 8 (BIND 8 journal files
+ * are ASCII text files).
+ */
+
+static journal_header_t
+initial_journal_header = { ";BIND LOG V9\n", { 0, 0 }, { 0, 0 }, 0 };
+
+#define JOURNAL_EMPTY(h) ((h)->begin.offset == (h)->end.offset)
+
+typedef enum {
+ JOURNAL_STATE_INVALID,
+ JOURNAL_STATE_READ,
+ JOURNAL_STATE_WRITE,
+ JOURNAL_STATE_TRANSACTION
+} journal_state_t;
+
+struct dns_journal {
+ unsigned int magic; /*%< JOUR */
+ isc_mem_t *mctx; /*%< Memory context */
+ journal_state_t state;
+ const char *filename; /*%< Journal file name */
+ FILE * fp; /*%< File handle */
+ isc_offset_t offset; /*%< Current file offset */
+ journal_header_t header; /*%< In-core journal header */
+ unsigned char *rawindex; /*%< In-core buffer for journal index in on-disk format */
+ journal_pos_t *index; /*%< In-core journal index */
+
+ /*% Current transaction state (when writing). */
+ struct {
+ unsigned int n_soa; /*%< Number of SOAs seen */
+ journal_pos_t pos[2]; /*%< Begin/end position */
+ } x;
+
+ /*% Iteration state (when reading). */
+ struct {
+ /* These define the part of the journal we iterate over. */
+ journal_pos_t bpos; /*%< Position before first, */
+ journal_pos_t epos; /*%< and after last transaction */
+ /* The rest is iterator state. */
+ isc_uint32_t current_serial; /*%< Current SOA serial */
+ isc_buffer_t source; /*%< Data from disk */
+ isc_buffer_t target; /*%< Data from _fromwire check */
+ dns_decompress_t dctx; /*%< Dummy decompression ctx */
+ dns_name_t name; /*%< Current domain name */
+ dns_rdata_t rdata; /*%< Current rdata */
+ isc_uint32_t ttl; /*%< Current TTL */
+ unsigned int xsize; /*%< Size of transaction data */
+ unsigned int xpos; /*%< Current position in it */
+ isc_result_t result; /*%< Result of last call */
+ } it;
+};
+
+#define DNS_JOURNAL_MAGIC ISC_MAGIC('J', 'O', 'U', 'R')
+#define DNS_JOURNAL_VALID(t) ISC_MAGIC_VALID(t, DNS_JOURNAL_MAGIC)
+
+static void
+journal_pos_decode(journal_rawpos_t *raw, journal_pos_t *cooked) {
+ cooked->serial = decode_uint32(raw->serial);
+ cooked->offset = decode_uint32(raw->offset);
+}
+
+static void
+journal_pos_encode(journal_rawpos_t *raw, journal_pos_t *cooked) {
+ encode_uint32(cooked->serial, raw->serial);
+ encode_uint32(cooked->offset, raw->offset);
+}
+
+static void
+journal_header_decode(journal_rawheader_t *raw, journal_header_t *cooked) {
+ INSIST(sizeof(cooked->format) == sizeof(raw->h.format));
+ memcpy(cooked->format, raw->h.format, sizeof(cooked->format));
+ journal_pos_decode(&raw->h.begin, &cooked->begin);
+ journal_pos_decode(&raw->h.end, &cooked->end);
+ cooked->index_size = decode_uint32(raw->h.index_size);
+}
+
+static void
+journal_header_encode(journal_header_t *cooked, journal_rawheader_t *raw) {
+ INSIST(sizeof(cooked->format) == sizeof(raw->h.format));
+ memset(raw->pad, 0, sizeof(raw->pad));
+ memcpy(raw->h.format, cooked->format, sizeof(raw->h.format));
+ journal_pos_encode(&raw->h.begin, &cooked->begin);
+ journal_pos_encode(&raw->h.end, &cooked->end);
+ encode_uint32(cooked->index_size, raw->h.index_size);
+}
+
+/*
+ * Journal file I/O subroutines, with error checking and reporting.
+ */
+static isc_result_t
+journal_seek(dns_journal_t *j, isc_uint32_t offset) {
+ isc_result_t result;
+ result = isc_stdio_seek(j->fp, (long)offset, SEEK_SET);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: seek: %s", j->filename,
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+ j->offset = offset;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+journal_read(dns_journal_t *j, void *mem, size_t nbytes) {
+ isc_result_t result;
+
+ result = isc_stdio_read(mem, 1, nbytes, j->fp, NULL);
+ if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_EOF)
+ return (ISC_R_NOMORE);
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: read: %s",
+ j->filename, isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+ j->offset += nbytes;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+journal_write(dns_journal_t *j, void *mem, size_t nbytes) {
+ isc_result_t result;
+
+ result = isc_stdio_write(mem, 1, nbytes, j->fp, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: write: %s",
+ j->filename, isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+ j->offset += nbytes;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+journal_fsync(dns_journal_t *j) {
+ isc_result_t result;
+ result = isc_stdio_flush(j->fp);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: flush: %s",
+ j->filename, isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+ result = isc_stdio_sync(j->fp);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: fsync: %s",
+ j->filename, isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Read/write a transaction header at the current file position.
+ */
+
+static isc_result_t
+journal_read_xhdr(dns_journal_t *j, journal_xhdr_t *xhdr) {
+ journal_rawxhdr_t raw;
+ isc_result_t result;
+ result = journal_read(j, &raw, sizeof(raw));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ xhdr->size = decode_uint32(raw.size);
+ xhdr->serial0 = decode_uint32(raw.serial0);
+ xhdr->serial1 = decode_uint32(raw.serial1);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+journal_write_xhdr(dns_journal_t *j, isc_uint32_t size,
+ isc_uint32_t serial0, isc_uint32_t serial1)
+{
+ journal_rawxhdr_t raw;
+ encode_uint32(size, raw.size);
+ encode_uint32(serial0, raw.serial0);
+ encode_uint32(serial1, raw.serial1);
+ return (journal_write(j, &raw, sizeof(raw)));
+}
+
+
+/*
+ * Read an RR header at the current file position.
+ */
+
+static isc_result_t
+journal_read_rrhdr(dns_journal_t *j, journal_rrhdr_t *rrhdr) {
+ journal_rawrrhdr_t raw;
+ isc_result_t result;
+ result = journal_read(j, &raw, sizeof(raw));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ rrhdr->size = decode_uint32(raw.size);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+journal_file_create(isc_mem_t *mctx, const char *filename) {
+ FILE *fp = NULL;
+ isc_result_t result;
+ journal_header_t header;
+ journal_rawheader_t rawheader;
+ int index_size = 56; /* XXX configurable */
+ int size;
+ void *mem; /* Memory for temporary index image. */
+
+ INSIST(sizeof(journal_rawheader_t) == JOURNAL_HEADER_SIZE);
+
+ result = isc_stdio_open(filename, "wb", &fp);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: create: %s",
+ filename, isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ header = initial_journal_header;
+ header.index_size = index_size;
+ journal_header_encode(&header, &rawheader);
+
+ size = sizeof(journal_rawheader_t) +
+ index_size * sizeof(journal_rawpos_t);
+
+ mem = isc_mem_get(mctx, size);
+ if (mem == NULL) {
+ (void)isc_stdio_close(fp);
+ (void)isc_file_remove(filename);
+ return (ISC_R_NOMEMORY);
+ }
+ memset(mem, 0, size);
+ memcpy(mem, &rawheader, sizeof(rawheader));
+
+ result = isc_stdio_write(mem, 1, (size_t) size, fp, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: write: %s",
+ filename, isc_result_totext(result));
+ (void)isc_stdio_close(fp);
+ (void)isc_file_remove(filename);
+ isc_mem_put(mctx, mem, size);
+ return (ISC_R_UNEXPECTED);
+ }
+ isc_mem_put(mctx, mem, size);
+
+ result = isc_stdio_close(fp);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: close: %s",
+ filename, isc_result_totext(result));
+ (void)isc_file_remove(filename);
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,
+ isc_boolean_t create, dns_journal_t **journalp) {
+ FILE *fp = NULL;
+ isc_result_t result;
+ journal_rawheader_t rawheader;
+ dns_journal_t *j;
+
+ INSIST(journalp != NULL && *journalp == NULL);
+ j = isc_mem_get(mctx, sizeof(*j));
+ if (j == NULL)
+ return (ISC_R_NOMEMORY);
+
+ j->mctx = mctx;
+ j->state = JOURNAL_STATE_INVALID;
+ j->fp = NULL;
+ j->filename = filename;
+ j->index = NULL;
+ j->rawindex = NULL;
+
+ result = isc_stdio_open(j->filename, write ? "rb+" : "rb", &fp);
+
+ if (result == ISC_R_FILENOTFOUND) {
+ if (create) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS,
+ ISC_LOG_INFO,
+ "journal file %s does not exist, "
+ "creating it",
+ j->filename);
+ CHECK(journal_file_create(mctx, filename));
+ /*
+ * Retry.
+ */
+ result = isc_stdio_open(j->filename, "rb+", &fp);
+ } else {
+ FAIL(ISC_R_NOTFOUND);
+ }
+ }
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: open: %s",
+ j->filename, isc_result_totext(result));
+ FAIL(ISC_R_UNEXPECTED);
+ }
+
+ j->fp = fp;
+
+ /*
+ * Set magic early so that seek/read can succeed.
+ */
+ j->magic = DNS_JOURNAL_MAGIC;
+
+ CHECK(journal_seek(j, 0));
+ CHECK(journal_read(j, &rawheader, sizeof(rawheader)));
+
+ if (memcmp(rawheader.h.format, initial_journal_header.format,
+ sizeof(initial_journal_header.format)) != 0) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: journal format not recognized",
+ j->filename);
+ FAIL(ISC_R_UNEXPECTED);
+ }
+ journal_header_decode(&rawheader, &j->header);
+
+ /*
+ * If there is an index, read the raw index into a dynamically
+ * allocated buffer and then convert it into a cooked index.
+ */
+ if (j->header.index_size != 0) {
+ unsigned int i;
+ unsigned int rawbytes;
+ unsigned char *p;
+
+ rawbytes = j->header.index_size * sizeof(journal_rawpos_t);
+ j->rawindex = isc_mem_get(mctx, rawbytes);
+ if (j->rawindex == NULL)
+ FAIL(ISC_R_NOMEMORY);
+
+ CHECK(journal_read(j, j->rawindex, rawbytes));
+
+ j->index = isc_mem_get(mctx, j->header.index_size *
+ sizeof(journal_pos_t));
+ if (j->index == NULL)
+ FAIL(ISC_R_NOMEMORY);
+
+ p = j->rawindex;
+ for (i = 0; i < j->header.index_size; i++) {
+ j->index[i].serial = decode_uint32(p);
+ p += 4;
+ j->index[i].offset = decode_uint32(p);
+ p += 4;
+ }
+ INSIST(p == j->rawindex + rawbytes);
+ }
+ j->offset = -1; /* Invalid, must seek explicitly. */
+
+ /*
+ * Initialize the iterator.
+ */
+ dns_name_init(&j->it.name, NULL);
+ dns_rdata_init(&j->it.rdata);
+
+ /*
+ * Set up empty initial buffers for uncheched and checked
+ * wire format RR data. They will be reallocated
+ * later.
+ */
+ isc_buffer_init(&j->it.source, NULL, 0);
+ isc_buffer_init(&j->it.target, NULL, 0);
+ dns_decompress_init(&j->it.dctx, -1, DNS_DECOMPRESS_NONE);
+
+ j->state =
+ write ? JOURNAL_STATE_WRITE : JOURNAL_STATE_READ;
+
+ *journalp = j;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ j->magic = 0;
+ if (j->index != NULL) {
+ isc_mem_put(j->mctx, j->index, j->header.index_size *
+ sizeof(journal_rawpos_t));
+ j->index = NULL;
+ }
+ if (j->fp != NULL)
+ (void)isc_stdio_close(j->fp);
+ isc_mem_put(j->mctx, j, sizeof(*j));
+ return (result);
+}
+
+isc_result_t
+dns_journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,
+ dns_journal_t **journalp) {
+ isc_result_t result;
+ int namelen;
+ char backup[1024];
+
+ result = journal_open(mctx, filename, write, write, journalp);
+ if (result == ISC_R_NOTFOUND) {
+ namelen = strlen(filename);
+ if (namelen > 4 && strcmp(filename + namelen - 4, ".jnl") == 0)
+ namelen -= 4;
+
+ result = isc_string_printf(backup, sizeof(backup), "%.*s.jbk",
+ namelen, filename);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = journal_open(mctx, backup, write, write, journalp);
+ }
+ return (result);
+}
+
+/*
+ * A comparison function defining the sorting order for
+ * entries in the IXFR-style journal file.
+ *
+ * The IXFR format requires that deletions are sorted before
+ * additions, and within either one, SOA records are sorted
+ * before others.
+ *
+ * Also sort the non-SOA records by type as a courtesy to the
+ * server receiving the IXFR - it may help reduce the amount of
+ * rdataset merging it has to do.
+ */
+static int
+ixfr_order(const void *av, const void *bv) {
+ dns_difftuple_t const * const *ap = av;
+ dns_difftuple_t const * const *bp = bv;
+ dns_difftuple_t const *a = *ap;
+ dns_difftuple_t const *b = *bp;
+ int r;
+ int bop = 0, aop = 0;
+
+ switch (a->op) {
+ case DNS_DIFFOP_DEL:
+ case DNS_DIFFOP_DELRESIGN:
+ aop = 1;
+ break;
+ case DNS_DIFFOP_ADD:
+ case DNS_DIFFOP_ADDRESIGN:
+ aop = 0;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ switch (b->op) {
+ case DNS_DIFFOP_DEL:
+ case DNS_DIFFOP_DELRESIGN:
+ bop = 1;
+ break;
+ case DNS_DIFFOP_ADD:
+ case DNS_DIFFOP_ADDRESIGN:
+ bop = 0;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ r = bop - aop;
+ if (r != 0)
+ return (r);
+
+ r = (b->rdata.type == dns_rdatatype_soa) -
+ (a->rdata.type == dns_rdatatype_soa);
+ if (r != 0)
+ return (r);
+
+ r = (a->rdata.type - b->rdata.type);
+ return (r);
+}
+
+/*
+ * Advance '*pos' to the next journal transaction.
+ *
+ * Requires:
+ * *pos refers to a valid journal transaction.
+ *
+ * Ensures:
+ * When ISC_R_SUCCESS is returned,
+ * *pos refers to the next journal transaction.
+ *
+ * Returns one of:
+ *
+ * ISC_R_SUCCESS
+ * ISC_R_NOMORE *pos pointed at the last transaction
+ * Other results due to file errors are possible.
+ */
+static isc_result_t
+journal_next(dns_journal_t *j, journal_pos_t *pos) {
+ isc_result_t result;
+ journal_xhdr_t xhdr;
+ REQUIRE(DNS_JOURNAL_VALID(j));
+
+ result = journal_seek(j, pos->offset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (pos->serial == j->header.end.serial)
+ return (ISC_R_NOMORE);
+ /*
+ * Read the header of the current transaction.
+ * This will return ISC_R_NOMORE if we are at EOF.
+ */
+ result = journal_read_xhdr(j, &xhdr);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Check serial number consistency.
+ */
+ if (xhdr.serial0 != pos->serial) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: journal file corrupt: "
+ "expected serial %u, got %u",
+ j->filename, pos->serial, xhdr.serial0);
+ return (ISC_R_UNEXPECTED);
+ }
+
+ /*
+ * Check for offset wraparound.
+ */
+ if ((isc_offset_t)(pos->offset + sizeof(journal_rawxhdr_t) + xhdr.size)
+ < pos->offset) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: offset too large", j->filename);
+ return (ISC_R_UNEXPECTED);
+ }
+
+ pos->offset += sizeof(journal_rawxhdr_t) + xhdr.size;
+ pos->serial = xhdr.serial1;
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * If the index of the journal 'j' contains an entry "better"
+ * than '*best_guess', replace '*best_guess' with it.
+ *
+ * "Better" means having a serial number closer to 'serial'
+ * but not greater than 'serial'.
+ */
+static void
+index_find(dns_journal_t *j, isc_uint32_t serial, journal_pos_t *best_guess) {
+ unsigned int i;
+ if (j->index == NULL)
+ return;
+ for (i = 0; i < j->header.index_size; i++) {
+ if (POS_VALID(j->index[i]) &&
+ DNS_SERIAL_GE(serial, j->index[i].serial) &&
+ DNS_SERIAL_GT(j->index[i].serial, best_guess->serial))
+ *best_guess = j->index[i];
+ }
+}
+
+/*
+ * Add a new index entry. If there is no room, make room by removing
+ * the odd-numbered entries and compacting the others into the first
+ * half of the index. This decimates old index entries exponentially
+ * over time, so that the index always contains a much larger fraction
+ * of recent serial numbers than of old ones. This is deliberate -
+ * most index searches are for outgoing IXFR, and IXFR tends to request
+ * recent versions more often than old ones.
+ */
+static void
+index_add(dns_journal_t *j, journal_pos_t *pos) {
+ unsigned int i;
+ if (j->index == NULL)
+ return;
+ /*
+ * Search for a vacant position.
+ */
+ for (i = 0; i < j->header.index_size; i++) {
+ if (! POS_VALID(j->index[i]))
+ break;
+ }
+ if (i == j->header.index_size) {
+ unsigned int k = 0;
+ /*
+ * Found no vacant position. Make some room.
+ */
+ for (i = 0; i < j->header.index_size; i += 2) {
+ j->index[k++] = j->index[i];
+ }
+ i = k; /* 'i' identifies the first vacant position. */
+ while (k < j->header.index_size) {
+ POS_INVALIDATE(j->index[k]);
+ k++;
+ }
+ }
+ INSIST(i < j->header.index_size);
+ INSIST(! POS_VALID(j->index[i]));
+
+ /*
+ * Store the new index entry.
+ */
+ j->index[i] = *pos;
+}
+
+/*
+ * Invalidate any existing index entries that could become
+ * ambiguous when a new transaction with number 'serial' is added.
+ */
+static void
+index_invalidate(dns_journal_t *j, isc_uint32_t serial) {
+ unsigned int i;
+ if (j->index == NULL)
+ return;
+ for (i = 0; i < j->header.index_size; i++) {
+ if (! DNS_SERIAL_GT(serial, j->index[i].serial))
+ POS_INVALIDATE(j->index[i]);
+ }
+}
+
+/*
+ * Try to find a transaction with initial serial number 'serial'
+ * in the journal 'j'.
+ *
+ * If found, store its position at '*pos' and return ISC_R_SUCCESS.
+ *
+ * If 'serial' is current (= the ending serial number of the
+ * last transaction in the journal), set '*pos' to
+ * the position immediately following the last transaction and
+ * return ISC_R_SUCCESS.
+ *
+ * If 'serial' is within the range of addressable serial numbers
+ * covered by the journal but that particular serial number is missing
+ * (from the journal, not just from the index), return ISC_R_NOTFOUND.
+ *
+ * If 'serial' is outside the range of addressable serial numbers
+ * covered by the journal, return ISC_R_RANGE.
+ *
+ */
+static isc_result_t
+journal_find(dns_journal_t *j, isc_uint32_t serial, journal_pos_t *pos) {
+ isc_result_t result;
+ journal_pos_t current_pos;
+ REQUIRE(DNS_JOURNAL_VALID(j));
+
+ if (DNS_SERIAL_GT(j->header.begin.serial, serial))
+ return (ISC_R_RANGE);
+ if (DNS_SERIAL_GT(serial, j->header.end.serial))
+ return (ISC_R_RANGE);
+ if (serial == j->header.end.serial) {
+ *pos = j->header.end;
+ return (ISC_R_SUCCESS);
+ }
+
+ current_pos = j->header.begin;
+ index_find(j, serial, &current_pos);
+
+ while (current_pos.serial != serial) {
+ if (DNS_SERIAL_GT(current_pos.serial, serial))
+ return (ISC_R_NOTFOUND);
+ result = journal_next(j, &current_pos);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ *pos = current_pos;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_journal_begin_transaction(dns_journal_t *j) {
+ isc_uint32_t offset;
+ isc_result_t result;
+ journal_rawxhdr_t hdr;
+
+ REQUIRE(DNS_JOURNAL_VALID(j));
+ REQUIRE(j->state == JOURNAL_STATE_WRITE);
+
+ /*
+ * Find the file offset where the new transaction should
+ * be written, and seek there.
+ */
+ if (JOURNAL_EMPTY(&j->header)) {
+ offset = sizeof(journal_rawheader_t) +
+ j->header.index_size * sizeof(journal_rawpos_t);
+ } else {
+ offset = j->header.end.offset;
+ }
+ j->x.pos[0].offset = offset;
+ j->x.pos[1].offset = offset; /* Initial value, will be incremented. */
+ j->x.n_soa = 0;
+
+ CHECK(journal_seek(j, offset));
+
+ /*
+ * Write a dummy transaction header of all zeroes to reserve
+ * space. It will be filled in when the transaction is
+ * finished.
+ */
+ memset(&hdr, 0, sizeof(hdr));
+ CHECK(journal_write(j, &hdr, sizeof(hdr)));
+ j->x.pos[1].offset = j->offset;
+
+ j->state = JOURNAL_STATE_TRANSACTION;
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+isc_result_t
+dns_journal_writediff(dns_journal_t *j, dns_diff_t *diff) {
+ dns_difftuple_t *t;
+ isc_buffer_t buffer;
+ void *mem = NULL;
+ unsigned int size;
+ isc_result_t result;
+ isc_region_t used;
+
+ REQUIRE(DNS_DIFF_VALID(diff));
+ REQUIRE(j->state == JOURNAL_STATE_TRANSACTION);
+
+ isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "writing to journal");
+ (void)dns_diff_print(diff, NULL);
+
+ /*
+ * Pass 1: determine the buffer size needed, and
+ * keep track of SOA serial numbers.
+ */
+ size = 0;
+ for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
+ t = ISC_LIST_NEXT(t, link))
+ {
+ if (t->rdata.type == dns_rdatatype_soa) {
+ if (j->x.n_soa < 2)
+ j->x.pos[j->x.n_soa].serial =
+ dns_soa_getserial(&t->rdata);
+ j->x.n_soa++;
+ }
+ size += sizeof(journal_rawrrhdr_t);
+ size += t->name.length; /* XXX should have access macro? */
+ size += 10;
+ size += t->rdata.length;
+ }
+
+ mem = isc_mem_get(j->mctx, size);
+ if (mem == NULL)
+ return (ISC_R_NOMEMORY);
+
+ isc_buffer_init(&buffer, mem, size);
+
+ /*
+ * Pass 2. Write RRs to buffer.
+ */
+ for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
+ t = ISC_LIST_NEXT(t, link))
+ {
+ /*
+ * Write the RR header.
+ */
+ isc_buffer_putuint32(&buffer, t->name.length + 10 +
+ t->rdata.length);
+ /*
+ * Write the owner name, RR header, and RR data.
+ */
+ isc_buffer_putmem(&buffer, t->name.ndata, t->name.length);
+ isc_buffer_putuint16(&buffer, t->rdata.type);
+ isc_buffer_putuint16(&buffer, t->rdata.rdclass);
+ isc_buffer_putuint32(&buffer, t->ttl);
+ INSIST(t->rdata.length < 65536);
+ isc_buffer_putuint16(&buffer, (isc_uint16_t)t->rdata.length);
+ INSIST(isc_buffer_availablelength(&buffer) >= t->rdata.length);
+ isc_buffer_putmem(&buffer, t->rdata.data, t->rdata.length);
+ }
+
+ isc_buffer_usedregion(&buffer, &used);
+ INSIST(used.length == size);
+
+ j->x.pos[1].offset += used.length;
+
+ /*
+ * Write the buffer contents to the journal file.
+ */
+ CHECK(journal_write(j, used.base, used.length));
+
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (mem != NULL)
+ isc_mem_put(j->mctx, mem, size);
+ return (result);
+
+}
+
+isc_result_t
+dns_journal_commit(dns_journal_t *j) {
+ isc_result_t result;
+ journal_rawheader_t rawheader;
+
+ REQUIRE(DNS_JOURNAL_VALID(j));
+ REQUIRE(j->state == JOURNAL_STATE_TRANSACTION);
+
+ /*
+ * Perform some basic consistency checks.
+ */
+ if (j->x.n_soa != 2) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: malformed transaction: %d SOAs",
+ j->filename, j->x.n_soa);
+ return (ISC_R_UNEXPECTED);
+ }
+ if (! (DNS_SERIAL_GT(j->x.pos[1].serial, j->x.pos[0].serial) ||
+ (bind8_compat &&
+ j->x.pos[1].serial == j->x.pos[0].serial)))
+ {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: malformed transaction: serial number "
+ "would decrease", j->filename);
+ return (ISC_R_UNEXPECTED);
+ }
+ if (! JOURNAL_EMPTY(&j->header)) {
+ if (j->x.pos[0].serial != j->header.end.serial) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "malformed transaction: "
+ "%s last serial %u != "
+ "transaction first serial %u",
+ j->filename,
+ j->header.end.serial,
+ j->x.pos[0].serial);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+
+ /*
+ * Some old journal entries may become non-addressable
+ * when we increment the current serial number. Purge them
+ * by stepping header.begin forward to the first addressable
+ * transaction. Also purge them from the index.
+ */
+ if (! JOURNAL_EMPTY(&j->header)) {
+ while (! DNS_SERIAL_GT(j->x.pos[1].serial,
+ j->header.begin.serial)) {
+ CHECK(journal_next(j, &j->header.begin));
+ }
+ index_invalidate(j, j->x.pos[1].serial);
+ }
+#ifdef notyet
+ if (DNS_SERIAL_GT(last_dumped_serial, j->x.pos[1].serial)) {
+ force_dump(...);
+ }
+#endif
+
+ /*
+ * Commit the transaction data to stable storage.
+ */
+ CHECK(journal_fsync(j));
+
+ /*
+ * Update the transaction header.
+ */
+ CHECK(journal_seek(j, j->x.pos[0].offset));
+ CHECK(journal_write_xhdr(j, (j->x.pos[1].offset - j->x.pos[0].offset) -
+ sizeof(journal_rawxhdr_t),
+ j->x.pos[0].serial, j->x.pos[1].serial));
+
+ /*
+ * Update the journal header.
+ */
+ if (JOURNAL_EMPTY(&j->header)) {
+ j->header.begin = j->x.pos[0];
+ }
+ j->header.end = j->x.pos[1];
+ journal_header_encode(&j->header, &rawheader);
+ CHECK(journal_seek(j, 0));
+ CHECK(journal_write(j, &rawheader, sizeof(rawheader)));
+
+ /*
+ * Update the index.
+ */
+ index_add(j, &j->x.pos[0]);
+
+ /*
+ * Convert the index into on-disk format and write
+ * it to disk.
+ */
+ CHECK(index_to_disk(j));
+
+ /*
+ * Commit the header to stable storage.
+ */
+ CHECK(journal_fsync(j));
+
+ /*
+ * We no longer have a transaction open.
+ */
+ j->state = JOURNAL_STATE_WRITE;
+
+ result = ISC_R_SUCCESS;
+
+ failure:
+ return (result);
+}
+
+isc_result_t
+dns_journal_write_transaction(dns_journal_t *j, dns_diff_t *diff) {
+ isc_result_t result;
+ CHECK(dns_diff_sort(diff, ixfr_order));
+ CHECK(dns_journal_begin_transaction(j));
+ CHECK(dns_journal_writediff(j, diff));
+ CHECK(dns_journal_commit(j));
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+void
+dns_journal_destroy(dns_journal_t **journalp) {
+ dns_journal_t *j = *journalp;
+ REQUIRE(DNS_JOURNAL_VALID(j));
+
+ j->it.result = ISC_R_FAILURE;
+ dns_name_invalidate(&j->it.name);
+ dns_decompress_invalidate(&j->it.dctx);
+ if (j->rawindex != NULL)
+ isc_mem_put(j->mctx, j->rawindex, j->header.index_size *
+ sizeof(journal_rawpos_t));
+ if (j->index != NULL)
+ isc_mem_put(j->mctx, j->index, j->header.index_size *
+ sizeof(journal_pos_t));
+ if (j->it.target.base != NULL)
+ isc_mem_put(j->mctx, j->it.target.base, j->it.target.length);
+ if (j->it.source.base != NULL)
+ isc_mem_put(j->mctx, j->it.source.base, j->it.source.length);
+
+ if (j->fp != NULL)
+ (void)isc_stdio_close(j->fp);
+ j->magic = 0;
+ isc_mem_put(j->mctx, j, sizeof(*j));
+ *journalp = NULL;
+}
+
+/*
+ * Roll the open journal 'j' into the database 'db'.
+ * A new database version will be created.
+ */
+
+/* XXX Share code with incoming IXFR? */
+
+static isc_result_t
+roll_forward(dns_journal_t *j, dns_db_t *db, unsigned int options) {
+ isc_buffer_t source; /* Transaction data from disk */
+ isc_buffer_t target; /* Ditto after _fromwire check */
+ isc_uint32_t db_serial; /* Database SOA serial */
+ isc_uint32_t end_serial; /* Last journal SOA serial */
+ isc_result_t result;
+ dns_dbversion_t *ver = NULL;
+ journal_pos_t pos;
+ dns_diff_t diff;
+ unsigned int n_soa = 0;
+ unsigned int n_put = 0;
+ dns_diffop_t op;
+
+ REQUIRE(DNS_JOURNAL_VALID(j));
+ REQUIRE(DNS_DB_VALID(db));
+
+ dns_diff_init(j->mctx, &diff);
+
+ /*
+ * Set up empty initial buffers for uncheched and checked
+ * wire format transaction data. They will be reallocated
+ * later.
+ */
+ isc_buffer_init(&source, NULL, 0);
+ isc_buffer_init(&target, NULL, 0);
+
+ /*
+ * Create the new database version.
+ */
+ CHECK(dns_db_newversion(db, &ver));
+
+ /*
+ * Get the current database SOA serial number.
+ */
+ CHECK(dns_db_getsoaserial(db, ver, &db_serial));
+
+ /*
+ * Locate a journal entry for the current database serial.
+ */
+ CHECK(journal_find(j, db_serial, &pos));
+ /*
+ * XXX do more drastic things, like marking zone stale,
+ * if this fails?
+ */
+ /*
+ * XXXRTH The zone code should probably mark the zone as bad and
+ * scream loudly into the log if this is a dynamic update
+ * log reply that failed.
+ */
+
+ end_serial = dns_journal_last_serial(j);
+ if (db_serial == end_serial)
+ CHECK(DNS_R_UPTODATE);
+
+ CHECK(dns_journal_iter_init(j, db_serial, end_serial));
+
+ for (result = dns_journal_first_rr(j);
+ result == ISC_R_SUCCESS;
+ result = dns_journal_next_rr(j))
+ {
+ dns_name_t *name;
+ isc_uint32_t ttl;
+ dns_rdata_t *rdata;
+ dns_difftuple_t *tuple = NULL;
+
+ name = NULL;
+ rdata = NULL;
+ dns_journal_current_rr(j, &name, &ttl, &rdata);
+
+ if (rdata->type == dns_rdatatype_soa) {
+ n_soa++;
+ if (n_soa == 2)
+ db_serial = j->it.current_serial;
+ }
+
+ if (n_soa == 3)
+ n_soa = 1;
+ if (n_soa == 0) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: journal file corrupt: missing "
+ "initial SOA", j->filename);
+ FAIL(ISC_R_UNEXPECTED);
+ }
+ if ((options & DNS_JOURNALOPT_RESIGN) != 0)
+ op = (n_soa == 1) ? DNS_DIFFOP_DELRESIGN :
+ DNS_DIFFOP_ADDRESIGN;
+ else
+ op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
+
+ CHECK(dns_difftuple_create(diff.mctx, op, name, ttl, rdata,
+ &tuple));
+ dns_diff_append(&diff, &tuple);
+
+ if (++n_put > 100) {
+ isc_log_write(JOURNAL_DEBUG_LOGARGS(3),
+ "%s: applying diff to database (%u)",
+ j->filename, db_serial);
+ (void)dns_diff_print(&diff, NULL);
+ CHECK(dns_diff_apply(&diff, db, ver));
+ dns_diff_clear(&diff);
+ n_put = 0;
+ }
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ CHECK(result);
+
+ if (n_put != 0) {
+ isc_log_write(JOURNAL_DEBUG_LOGARGS(3),
+ "%s: applying final diff to database (%u)",
+ j->filename, db_serial);
+ (void)dns_diff_print(&diff, NULL);
+ CHECK(dns_diff_apply(&diff, db, ver));
+ dns_diff_clear(&diff);
+ }
+
+ failure:
+ if (ver != NULL)
+ dns_db_closeversion(db, &ver, result == ISC_R_SUCCESS ?
+ ISC_TRUE : ISC_FALSE);
+
+ if (source.base != NULL)
+ isc_mem_put(j->mctx, source.base, source.length);
+ if (target.base != NULL)
+ isc_mem_put(j->mctx, target.base, target.length);
+
+ dns_diff_clear(&diff);
+
+ return (result);
+}
+
+isc_result_t
+dns_journal_rollforward(isc_mem_t *mctx, dns_db_t *db,
+ unsigned int options, const char *filename)
+{
+ dns_journal_t *j;
+ isc_result_t result;
+
+ REQUIRE(DNS_DB_VALID(db));
+ REQUIRE(filename != NULL);
+
+ j = NULL;
+ result = dns_journal_open(mctx, filename, ISC_FALSE, &j);
+ if (result == ISC_R_NOTFOUND) {
+ isc_log_write(JOURNAL_DEBUG_LOGARGS(3),
+ "no journal file, but that's OK");
+ return (DNS_R_NOJOURNAL);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (JOURNAL_EMPTY(&j->header))
+ result = DNS_R_UPTODATE;
+ else
+ result = roll_forward(j, db, options);
+
+ dns_journal_destroy(&j);
+
+ return (result);
+}
+
+isc_result_t
+dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file) {
+ dns_journal_t *j;
+ isc_buffer_t source; /* Transaction data from disk */
+ isc_buffer_t target; /* Ditto after _fromwire check */
+ isc_uint32_t start_serial; /* Database SOA serial */
+ isc_uint32_t end_serial; /* Last journal SOA serial */
+ isc_result_t result;
+ dns_diff_t diff;
+ unsigned int n_soa = 0;
+ unsigned int n_put = 0;
+
+ REQUIRE(filename != NULL);
+
+ j = NULL;
+ result = dns_journal_open(mctx, filename, ISC_FALSE, &j);
+ if (result == ISC_R_NOTFOUND) {
+ isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no journal file");
+ return (DNS_R_NOJOURNAL);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "journal open failure: %s: %s",
+ isc_result_totext(result), filename);
+ return (result);
+ }
+
+ dns_diff_init(j->mctx, &diff);
+
+ /*
+ * Set up empty initial buffers for uncheched and checked
+ * wire format transaction data. They will be reallocated
+ * later.
+ */
+ isc_buffer_init(&source, NULL, 0);
+ isc_buffer_init(&target, NULL, 0);
+
+ start_serial = dns_journal_first_serial(j);
+ end_serial = dns_journal_last_serial(j);
+
+ CHECK(dns_journal_iter_init(j, start_serial, end_serial));
+
+ for (result = dns_journal_first_rr(j);
+ result == ISC_R_SUCCESS;
+ result = dns_journal_next_rr(j))
+ {
+ dns_name_t *name;
+ isc_uint32_t ttl;
+ dns_rdata_t *rdata;
+ dns_difftuple_t *tuple = NULL;
+
+ name = NULL;
+ rdata = NULL;
+ dns_journal_current_rr(j, &name, &ttl, &rdata);
+
+ if (rdata->type == dns_rdatatype_soa)
+ n_soa++;
+
+ if (n_soa == 3)
+ n_soa = 1;
+ if (n_soa == 0) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: journal file corrupt: missing "
+ "initial SOA", j->filename);
+ FAIL(ISC_R_UNEXPECTED);
+ }
+ CHECK(dns_difftuple_create(diff.mctx, n_soa == 1 ?
+ DNS_DIFFOP_DEL : DNS_DIFFOP_ADD,
+ name, ttl, rdata, &tuple));
+ dns_diff_append(&diff, &tuple);
+
+ if (++n_put > 100) {
+ result = dns_diff_print(&diff, file);
+ dns_diff_clear(&diff);
+ n_put = 0;
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ CHECK(result);
+
+ if (n_put != 0) {
+ result = dns_diff_print(&diff, file);
+ dns_diff_clear(&diff);
+ }
+ goto cleanup;
+
+ failure:
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: cannot print: journal file corrupt", j->filename);
+
+ cleanup:
+ if (source.base != NULL)
+ isc_mem_put(j->mctx, source.base, source.length);
+ if (target.base != NULL)
+ isc_mem_put(j->mctx, target.base, target.length);
+
+ dns_diff_clear(&diff);
+ dns_journal_destroy(&j);
+
+ return (result);
+}
+
+/**************************************************************************/
+/*
+ * Miscellaneous accessors.
+ */
+isc_uint32_t dns_journal_first_serial(dns_journal_t *j) {
+ return (j->header.begin.serial);
+}
+
+isc_uint32_t dns_journal_last_serial(dns_journal_t *j) {
+ return (j->header.end.serial);
+}
+
+/**************************************************************************/
+/*
+ * Iteration support.
+ *
+ * When serving an outgoing IXFR, we transmit a part the journal starting
+ * at the serial number in the IXFR request and ending at the serial
+ * number that is current when the IXFR request arrives. The ending
+ * serial number is not necessarily at the end of the journal:
+ * the journal may grow while the IXFR is in progress, but we stop
+ * when we reach the serial number that was current when the IXFR started.
+ */
+
+static isc_result_t read_one_rr(dns_journal_t *j);
+
+/*
+ * Make sure the buffer 'b' is has at least 'size' bytes
+ * allocated, and clear it.
+ *
+ * Requires:
+ * Either b->base is NULL, or it points to b->length bytes of memory
+ * previously allocated by isc_mem_get().
+ */
+
+static isc_result_t
+size_buffer(isc_mem_t *mctx, isc_buffer_t *b, unsigned size) {
+ if (b->length < size) {
+ void *mem = isc_mem_get(mctx, size);
+ if (mem == NULL)
+ return (ISC_R_NOMEMORY);
+ if (b->base != NULL)
+ isc_mem_put(mctx, b->base, b->length);
+ b->base = mem;
+ b->length = size;
+ }
+ isc_buffer_clear(b);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_journal_iter_init(dns_journal_t *j,
+ isc_uint32_t begin_serial, isc_uint32_t end_serial)
+{
+ isc_result_t result;
+
+ CHECK(journal_find(j, begin_serial, &j->it.bpos));
+ INSIST(j->it.bpos.serial == begin_serial);
+
+ CHECK(journal_find(j, end_serial, &j->it.epos));
+ INSIST(j->it.epos.serial == end_serial);
+
+ result = ISC_R_SUCCESS;
+ failure:
+ j->it.result = result;
+ return (j->it.result);
+}
+
+
+isc_result_t
+dns_journal_first_rr(dns_journal_t *j) {
+ isc_result_t result;
+
+ /*
+ * Seek to the beginning of the first transaction we are
+ * interested in.
+ */
+ CHECK(journal_seek(j, j->it.bpos.offset));
+ j->it.current_serial = j->it.bpos.serial;
+
+ j->it.xsize = 0; /* We have no transaction data yet... */
+ j->it.xpos = 0; /* ...and haven't used any of it. */
+
+ return (read_one_rr(j));
+
+ failure:
+ return (result);
+}
+
+static isc_result_t
+read_one_rr(dns_journal_t *j) {
+ isc_result_t result;
+
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ unsigned int rdlen;
+ isc_uint32_t ttl;
+ journal_xhdr_t xhdr;
+ journal_rrhdr_t rrhdr;
+
+ INSIST(j->offset <= j->it.epos.offset);
+ if (j->offset == j->it.epos.offset)
+ return (ISC_R_NOMORE);
+ if (j->it.xpos == j->it.xsize) {
+ /*
+ * We are at a transaction boundary.
+ * Read another transaction header.
+ */
+ CHECK(journal_read_xhdr(j, &xhdr));
+ if (xhdr.size == 0) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: journal corrupt: empty transaction",
+ j->filename);
+ FAIL(ISC_R_UNEXPECTED);
+ }
+ if (xhdr.serial0 != j->it.current_serial) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: journal file corrupt: "
+ "expected serial %u, got %u",
+ j->filename,
+ j->it.current_serial, xhdr.serial0);
+ FAIL(ISC_R_UNEXPECTED);
+ }
+ j->it.xsize = xhdr.size;
+ j->it.xpos = 0;
+ }
+ /*
+ * Read an RR.
+ */
+ CHECK(journal_read_rrhdr(j, &rrhdr));
+ /*
+ * Perform a sanity check on the journal RR size.
+ * The smallest possible RR has a 1-byte owner name
+ * and a 10-byte header. The largest possible
+ * RR has 65535 bytes of data, a header, and a maximum-
+ * size owner name, well below 70 k total.
+ */
+ if (rrhdr.size < 1+10 || rrhdr.size > 70000) {
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: journal corrupt: impossible RR size "
+ "(%d bytes)", j->filename, rrhdr.size);
+ FAIL(ISC_R_UNEXPECTED);
+ }
+
+ CHECK(size_buffer(j->mctx, &j->it.source, rrhdr.size));
+ CHECK(journal_read(j, j->it.source.base, rrhdr.size));
+ isc_buffer_add(&j->it.source, rrhdr.size);
+
+ /*
+ * The target buffer is made the same size
+ * as the source buffer, with the assumption that when
+ * no compression in present, the output of dns_*_fromwire()
+ * is no larger than the input.
+ */
+ CHECK(size_buffer(j->mctx, &j->it.target, rrhdr.size));
+
+ /*
+ * Parse the owner name. We don't know where it
+ * ends yet, so we make the entire "remaining"
+ * part of the buffer "active".
+ */
+ isc_buffer_setactive(&j->it.source,
+ j->it.source.used - j->it.source.current);
+ CHECK(dns_name_fromwire(&j->it.name, &j->it.source,
+ &j->it.dctx, 0, &j->it.target));
+
+ /*
+ * Check that the RR header is there, and parse it.
+ */
+ if (isc_buffer_remaininglength(&j->it.source) < 10)
+ FAIL(DNS_R_FORMERR);
+
+ rdtype = isc_buffer_getuint16(&j->it.source);
+ rdclass = isc_buffer_getuint16(&j->it.source);
+ ttl = isc_buffer_getuint32(&j->it.source);
+ rdlen = isc_buffer_getuint16(&j->it.source);
+
+ /*
+ * Parse the rdata.
+ */
+ if (isc_buffer_remaininglength(&j->it.source) != rdlen)
+ FAIL(DNS_R_FORMERR);
+ isc_buffer_setactive(&j->it.source, rdlen);
+ dns_rdata_reset(&j->it.rdata);
+ CHECK(dns_rdata_fromwire(&j->it.rdata, rdclass,
+ rdtype, &j->it.source, &j->it.dctx,
+ 0, &j->it.target));
+ j->it.ttl = ttl;
+
+ j->it.xpos += sizeof(journal_rawrrhdr_t) + rrhdr.size;
+ if (rdtype == dns_rdatatype_soa) {
+ /* XXX could do additional consistency checks here */
+ j->it.current_serial = dns_soa_getserial(&j->it.rdata);
+ }
+
+ result = ISC_R_SUCCESS;
+
+ failure:
+ j->it.result = result;
+ return (result);
+}
+
+isc_result_t
+dns_journal_next_rr(dns_journal_t *j) {
+ j->it.result = read_one_rr(j);
+ return (j->it.result);
+}
+
+void
+dns_journal_current_rr(dns_journal_t *j, dns_name_t **name, isc_uint32_t *ttl,
+ dns_rdata_t **rdata)
+{
+ REQUIRE(j->it.result == ISC_R_SUCCESS);
+ *name = &j->it.name;
+ *ttl = j->it.ttl;
+ *rdata = &j->it.rdata;
+}
+
+/**************************************************************************/
+/*
+ * Generating diffs from databases
+ */
+
+/*
+ * Construct a diff containing all the RRs at the current name of the
+ * database iterator 'dbit' in database 'db', version 'ver'.
+ * Set '*name' to the current name, and append the diff to 'diff'.
+ * All new tuples will have the operation 'op'.
+ *
+ * Requires: 'name' must have buffer large enough to hold the name.
+ * Typically, a dns_fixedname_t would be used.
+ */
+static isc_result_t
+get_name_diff(dns_db_t *db, dns_dbversion_t *ver, isc_stdtime_t now,
+ dns_dbiterator_t *dbit, dns_name_t *name, dns_diffop_t op,
+ dns_diff_t *diff)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_difftuple_t *tuple = NULL;
+
+ result = dns_dbiterator_current(dbit, &node, name);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_allrdatasets(db, node, ver, now, &rdsiter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter))
+ {
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+
+ 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_difftuple_create(diff->mctx, op, name,
+ rdataset.ttl, &rdata,
+ &tuple);
+ if (result != ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&rdataset);
+ goto cleanup_iterator;
+ }
+ dns_diff_append(diff, &tuple);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_NOMORE)
+ goto cleanup_iterator;
+ }
+ if (result != ISC_R_NOMORE)
+ goto cleanup_iterator;
+
+ result = ISC_R_SUCCESS;
+
+ cleanup_iterator:
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ cleanup_node:
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+/*
+ * Comparison function for use by dns_diff_subtract when sorting
+ * the diffs to be subtracted. The sort keys are the rdata type
+ * and the rdata itself. The owner name is ignored, because
+ * it is known to be the same for all tuples.
+ */
+static int
+rdata_order(const void *av, const void *bv) {
+ dns_difftuple_t const * const *ap = av;
+ dns_difftuple_t const * const *bp = bv;
+ dns_difftuple_t const *a = *ap;
+ dns_difftuple_t const *b = *bp;
+ int r;
+ r = (b->rdata.type - a->rdata.type);
+ if (r != 0)
+ return (r);
+ r = dns_rdata_compare(&a->rdata, &b->rdata);
+ return (r);
+}
+
+static isc_result_t
+dns_diff_subtract(dns_diff_t diff[2], dns_diff_t *r) {
+ isc_result_t result;
+ dns_difftuple_t *p[2];
+ int i, t;
+ isc_boolean_t append;
+
+ CHECK(dns_diff_sort(&diff[0], rdata_order));
+ CHECK(dns_diff_sort(&diff[1], rdata_order));
+
+ for (;;) {
+ p[0] = ISC_LIST_HEAD(diff[0].tuples);
+ p[1] = ISC_LIST_HEAD(diff[1].tuples);
+ if (p[0] == NULL && p[1] == NULL)
+ break;
+
+ for (i = 0; i < 2; i++)
+ if (p[!i] == NULL) {
+ ISC_LIST_UNLINK(diff[i].tuples, p[i], link);
+ ISC_LIST_APPEND(r->tuples, p[i], link);
+ goto next;
+ }
+ t = rdata_order(&p[0], &p[1]);
+ if (t < 0) {
+ ISC_LIST_UNLINK(diff[0].tuples, p[0], link);
+ ISC_LIST_APPEND(r->tuples, p[0], link);
+ goto next;
+ }
+ if (t > 0) {
+ ISC_LIST_UNLINK(diff[1].tuples, p[1], link);
+ ISC_LIST_APPEND(r->tuples, p[1], link);
+ goto next;
+ }
+ INSIST(t == 0);
+ /*
+ * Identical RRs in both databases; skip them both
+ * if the ttl differs.
+ */
+ append = ISC_TF(p[0]->ttl != p[1]->ttl);
+ for (i = 0; i < 2; i++) {
+ ISC_LIST_UNLINK(diff[i].tuples, p[i], link);
+ if (append) {
+ ISC_LIST_APPEND(r->tuples, p[i], link);
+ } else {
+ dns_difftuple_free(&p[i]);
+ }
+ }
+ next: ;
+ }
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+/*
+ * Compare the databases 'dba' and 'dbb' and generate a journal
+ * entry containing the changes to make 'dba' from 'dbb' (note
+ * the order). This journal entry will consist of a single,
+ * possibly very large transaction.
+ */
+
+isc_result_t
+dns_db_diff(isc_mem_t *mctx,
+ dns_db_t *dba, dns_dbversion_t *dbvera,
+ dns_db_t *dbb, dns_dbversion_t *dbverb,
+ const char *journal_filename)
+{
+ dns_db_t *db[2];
+ dns_dbversion_t *ver[2];
+ dns_dbiterator_t *dbit[2] = { NULL, NULL };
+ isc_boolean_t have[2] = { ISC_FALSE, ISC_FALSE };
+ dns_fixedname_t fixname[2];
+ isc_result_t result, itresult[2];
+ dns_diff_t diff[2], resultdiff;
+ int i, t;
+ dns_journal_t *journal = NULL;
+
+ db[0] = dba, db[1] = dbb;
+ ver[0] = dbvera, ver[1] = dbverb;
+
+ dns_diff_init(mctx, &diff[0]);
+ dns_diff_init(mctx, &diff[1]);
+ dns_diff_init(mctx, &resultdiff);
+
+ dns_fixedname_init(&fixname[0]);
+ dns_fixedname_init(&fixname[1]);
+
+ result = dns_journal_open(mctx, journal_filename, ISC_TRUE, &journal);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_createiterator(db[0], 0, &dbit[0]);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_journal;
+ result = dns_db_createiterator(db[1], 0, &dbit[1]);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_interator0;
+
+ itresult[0] = dns_dbiterator_first(dbit[0]);
+ itresult[1] = dns_dbiterator_first(dbit[1]);
+
+ for (;;) {
+ for (i = 0; i < 2; i++) {
+ if (! have[i] && itresult[i] == ISC_R_SUCCESS) {
+ CHECK(get_name_diff(db[i], ver[i], 0, dbit[i],
+ dns_fixedname_name(&fixname[i]),
+ i == 0 ?
+ DNS_DIFFOP_ADD :
+ DNS_DIFFOP_DEL,
+ &diff[i]));
+ itresult[i] = dns_dbiterator_next(dbit[i]);
+ have[i] = ISC_TRUE;
+ }
+ }
+
+ if (! have[0] && ! have[1]) {
+ INSIST(ISC_LIST_EMPTY(diff[0].tuples));
+ INSIST(ISC_LIST_EMPTY(diff[1].tuples));
+ break;
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (! have[!i]) {
+ ISC_LIST_APPENDLIST(resultdiff.tuples,
+ diff[i].tuples, link);
+ INSIST(ISC_LIST_EMPTY(diff[i].tuples));
+ have[i] = ISC_FALSE;
+ goto next;
+ }
+ }
+
+ t = dns_name_compare(dns_fixedname_name(&fixname[0]),
+ dns_fixedname_name(&fixname[1]));
+ if (t < 0) {
+ ISC_LIST_APPENDLIST(resultdiff.tuples,
+ diff[0].tuples, link);
+ INSIST(ISC_LIST_EMPTY(diff[0].tuples));
+ have[0] = ISC_FALSE;
+ continue;
+ }
+ if (t > 0) {
+ ISC_LIST_APPENDLIST(resultdiff.tuples,
+ diff[1].tuples, link);
+ INSIST(ISC_LIST_EMPTY(diff[1].tuples));
+ have[1] = ISC_FALSE;
+ continue;
+ }
+ INSIST(t == 0);
+ CHECK(dns_diff_subtract(diff, &resultdiff));
+ INSIST(ISC_LIST_EMPTY(diff[0].tuples));
+ INSIST(ISC_LIST_EMPTY(diff[1].tuples));
+ have[0] = have[1] = ISC_FALSE;
+ next: ;
+ }
+ if (itresult[0] != ISC_R_NOMORE)
+ FAIL(itresult[0]);
+ if (itresult[1] != ISC_R_NOMORE)
+ FAIL(itresult[1]);
+
+ if (ISC_LIST_EMPTY(resultdiff.tuples)) {
+ isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no changes");
+ } else {
+ CHECK(dns_journal_write_transaction(journal, &resultdiff));
+ }
+ INSIST(ISC_LIST_EMPTY(diff[0].tuples));
+ INSIST(ISC_LIST_EMPTY(diff[1].tuples));
+
+ failure:
+ dns_diff_clear(&resultdiff);
+ dns_dbiterator_destroy(&dbit[1]);
+ cleanup_interator0:
+ dns_dbiterator_destroy(&dbit[0]);
+ cleanup_journal:
+ dns_journal_destroy(&journal);
+ return (result);
+}
+
+isc_result_t
+dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial,
+ isc_uint32_t target_size)
+{
+ unsigned int i;
+ journal_pos_t best_guess;
+ journal_pos_t current_pos;
+ dns_journal_t *j = NULL;
+ dns_journal_t *new = NULL;
+ journal_rawheader_t rawheader;
+ unsigned int copy_length;
+ int namelen;
+ char *buf = NULL;
+ unsigned int size = 0;
+ isc_result_t result;
+ unsigned int indexend;
+ char newname[1024];
+ char backup[1024];
+ isc_boolean_t is_backup = ISC_FALSE;
+
+ namelen = strlen(filename);
+ if (namelen > 4 && strcmp(filename + namelen - 4, ".jnl") == 0)
+ namelen -= 4;
+
+ result = isc_string_printf(newname, sizeof(newname), "%.*s.jnw",
+ namelen, filename);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = isc_string_printf(backup, sizeof(backup), "%.*s.jbk",
+ namelen, filename);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = journal_open(mctx, filename, ISC_FALSE, ISC_FALSE, &j);
+ if (result == ISC_R_NOTFOUND) {
+ is_backup = ISC_TRUE;
+ result = journal_open(mctx, backup, ISC_FALSE, ISC_FALSE, &j);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (JOURNAL_EMPTY(&j->header)) {
+ dns_journal_destroy(&j);
+ return (ISC_R_SUCCESS);
+ }
+
+ if (DNS_SERIAL_GT(j->header.begin.serial, serial) ||
+ DNS_SERIAL_GT(serial, j->header.end.serial)) {
+ dns_journal_destroy(&j);
+ return (ISC_R_RANGE);
+ }
+
+ /*
+ * Cope with very small target sizes.
+ */
+ indexend = sizeof(journal_rawheader_t) +
+ j->header.index_size * sizeof(journal_rawpos_t);
+ if (target_size < indexend * 2)
+ target_size = target_size/2 + indexend;
+
+ /*
+ * See if there is any work to do.
+ */
+ if ((isc_uint32_t) j->header.end.offset < target_size) {
+ dns_journal_destroy(&j);
+ return (ISC_R_SUCCESS);
+ }
+
+ CHECK(journal_open(mctx, newname, ISC_TRUE, ISC_TRUE, &new));
+
+ /*
+ * Remove overhead so space test below can succeed.
+ */
+ if (target_size >= indexend)
+ target_size -= indexend;
+
+ /*
+ * Find if we can create enough free space.
+ */
+ best_guess = j->header.begin;
+ for (i = 0; i < j->header.index_size; i++) {
+ if (POS_VALID(j->index[i]) &&
+ DNS_SERIAL_GE(serial, j->index[i].serial) &&
+ ((isc_uint32_t)(j->header.end.offset - j->index[i].offset)
+ >= target_size / 2) &&
+ j->index[i].offset > best_guess.offset)
+ best_guess = j->index[i];
+ }
+
+ current_pos = best_guess;
+ while (current_pos.serial != serial) {
+ CHECK(journal_next(j, &current_pos));
+ if (current_pos.serial == j->header.end.serial)
+ break;
+
+ if (DNS_SERIAL_GE(serial, current_pos.serial) &&
+ ((isc_uint32_t)(j->header.end.offset - current_pos.offset)
+ >= (target_size / 2)) &&
+ current_pos.offset > best_guess.offset)
+ best_guess = current_pos;
+ else
+ break;
+ }
+
+ INSIST(best_guess.serial != j->header.end.serial);
+ if (best_guess.serial != serial)
+ CHECK(journal_next(j, &best_guess));
+
+ /*
+ * We should now be roughly half target_size provided
+ * we did not reach 'serial'. If not we will just copy
+ * all uncommitted deltas regardless of the size.
+ */
+ copy_length = j->header.end.offset - best_guess.offset;
+
+ if (copy_length != 0) {
+ /*
+ * Copy best_guess to end into space just freed.
+ */
+ size = 64*1024;
+ if (copy_length < size)
+ size = copy_length;
+ buf = isc_mem_get(mctx, size);
+ if (buf == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+
+ CHECK(journal_seek(j, best_guess.offset));
+ CHECK(journal_seek(new, indexend));
+ for (i = 0; i < copy_length; i += size) {
+ unsigned int len = (copy_length - i) > size ? size :
+ (copy_length - i);
+ CHECK(journal_read(j, buf, len));
+ CHECK(journal_write(new, buf, len));
+ }
+
+ CHECK(journal_fsync(new));
+
+ /*
+ * Compute new header.
+ */
+ new->header.begin.serial = best_guess.serial;
+ new->header.begin.offset = indexend;
+ new->header.end.serial = j->header.end.serial;
+ new->header.end.offset = indexend + copy_length;
+
+ /*
+ * Update the journal header.
+ */
+ journal_header_encode(&new->header, &rawheader);
+ CHECK(journal_seek(new, 0));
+ CHECK(journal_write(new, &rawheader, sizeof(rawheader)));
+ CHECK(journal_fsync(new));
+
+ /*
+ * Build new index.
+ */
+ current_pos = new->header.begin;
+ while (current_pos.serial != new->header.end.serial) {
+ index_add(new, &current_pos);
+ CHECK(journal_next(new, &current_pos));
+ }
+
+ /*
+ * Write index.
+ */
+ CHECK(index_to_disk(new));
+ CHECK(journal_fsync(new));
+
+ indexend = new->header.end.offset;
+ }
+ dns_journal_destroy(&new);
+
+ /*
+ * With a UFS file system this should just succeed and be atomic.
+ * Any IXFR outs will just continue and the old journal will be
+ * removed on final close.
+ *
+ * With MSDOS / NTFS we need to do a two stage rename triggered
+ * bu EEXISTS. Hopefully all IXFR's that were active at the last
+ * rename are now complete.
+ */
+ if (rename(newname, filename) == -1) {
+ if (errno == EACCES && !is_backup) {
+ result = isc_file_remove(backup);
+ if (result != ISC_R_SUCCESS &&
+ result != ISC_R_FILENOTFOUND)
+ goto failure;
+ if (rename(filename, backup) == -1)
+ goto maperrno;
+ if (rename(newname, filename) == -1)
+ goto maperrno;
+ (void)isc_file_remove(backup);
+ } else {
+ maperrno:
+ result = ISC_R_FAILURE;
+ goto failure;
+ }
+ }
+
+ dns_journal_destroy(&j);
+ result = ISC_R_SUCCESS;
+
+ failure:
+ (void)isc_file_remove(newname);
+ if (buf != NULL)
+ isc_mem_put(mctx, buf, size);
+ if (j != NULL)
+ dns_journal_destroy(&j);
+ if (new != NULL)
+ dns_journal_destroy(&new);
+ return (result);
+}
+
+static isc_result_t
+index_to_disk(dns_journal_t *j) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ if (j->header.index_size != 0) {
+ unsigned int i;
+ unsigned char *p;
+ unsigned int rawbytes;
+
+ rawbytes = j->header.index_size * sizeof(journal_rawpos_t);
+
+ p = j->rawindex;
+ for (i = 0; i < j->header.index_size; i++) {
+ encode_uint32(j->index[i].serial, p);
+ p += 4;
+ encode_uint32(j->index[i].offset, p);
+ p += 4;
+ }
+ INSIST(p == j->rawindex + rawbytes);
+
+ CHECK(journal_seek(j, sizeof(journal_rawheader_t)));
+ CHECK(journal_write(j, j->rawindex, rawbytes));
+ }
+failure:
+ return (result);
+}
diff --git a/lib/dns/key.c b/lib/dns/key.c
new file mode 100644
index 0000000..5cf4442
--- /dev/null
+++ b/lib/dns/key.c
@@ -0,0 +1,147 @@
+/*
+ * 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: key.c,v 1.8 2007/06/19 23:47:16 tbox Exp $ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <isc/region.h>
+#include <isc/util.h>
+
+#include <dns/keyvalues.h>
+
+#include <dst/dst.h>
+
+#include "dst_internal.h"
+
+isc_uint16_t
+dst_region_computeid(const isc_region_t *source, unsigned int alg) {
+ isc_uint32_t ac;
+ const unsigned char *p;
+ int size;
+
+ REQUIRE(source != NULL);
+ REQUIRE(source->length >= 4);
+
+ p = source->base;
+ size = source->length;
+
+ if (alg == DST_ALG_RSAMD5)
+ return ((p[size - 3] << 8) + p[size - 2]);
+
+ for (ac = 0; size > 1; size -= 2, p += 2)
+ ac += ((*p) << 8) + *(p + 1);
+
+ if (size > 0)
+ ac += ((*p) << 8);
+ ac += (ac >> 16) & 0xffff;
+
+ return ((isc_uint16_t)(ac & 0xffff));
+}
+
+dns_name_t *
+dst_key_name(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+ return (key->key_name);
+}
+
+unsigned int
+dst_key_size(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+ return (key->key_size);
+}
+
+unsigned int
+dst_key_proto(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+ return (key->key_proto);
+}
+
+unsigned int
+dst_key_alg(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+ return (key->key_alg);
+}
+
+isc_uint32_t
+dst_key_flags(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+ return (key->key_flags);
+}
+
+dns_keytag_t
+dst_key_id(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+ return (key->key_id);
+}
+
+dns_rdataclass_t
+dst_key_class(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+ return (key->key_class);
+}
+
+isc_boolean_t
+dst_key_iszonekey(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+
+ if ((key->key_flags & DNS_KEYTYPE_NOAUTH) != 0)
+ return (ISC_FALSE);
+ if ((key->key_flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
+ return (ISC_FALSE);
+ if (key->key_proto != DNS_KEYPROTO_DNSSEC &&
+ key->key_proto != DNS_KEYPROTO_ANY)
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+}
+
+isc_boolean_t
+dst_key_isnullkey(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+
+ if ((key->key_flags & DNS_KEYFLAG_TYPEMASK) != DNS_KEYTYPE_NOKEY)
+ return (ISC_FALSE);
+ if ((key->key_flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
+ return (ISC_FALSE);
+ if (key->key_proto != DNS_KEYPROTO_DNSSEC &&
+ key->key_proto != DNS_KEYPROTO_ANY)
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+}
+
+void
+dst_key_setbits(dst_key_t *key, isc_uint16_t bits) {
+ unsigned int maxbits;
+ REQUIRE(VALID_KEY(key));
+ if (bits != 0) {
+ RUNTIME_CHECK(dst_key_sigsize(key, &maxbits) == ISC_R_SUCCESS);
+ maxbits *= 8;
+ REQUIRE(bits <= maxbits);
+ }
+ key->key_bits = bits;
+}
+
+isc_uint16_t
+dst_key_getbits(const dst_key_t *key) {
+ REQUIRE(VALID_KEY(key));
+ return (key->key_bits);
+}
+
+/*! \file */
diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c
new file mode 100644
index 0000000..bffd2d3
--- /dev/null
+++ b/lib/dns/keytable.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: keytable.c,v 1.34 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/rwlock.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/keytable.h>
+#include <dns/fixedname.h>
+#include <dns/rbt.h>
+#include <dns/result.h>
+
+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));
+}
+
+isc_result_t
+dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
+ dns_keytable_t *keytable;
+ isc_result_t result;
+
+ /*
+ * Create a keytable.
+ */
+
+ REQUIRE(keytablep != NULL && *keytablep == NULL);
+
+ keytable = isc_mem_get(mctx, sizeof(*keytable));
+ if (keytable == NULL)
+ return (ISC_R_NOMEMORY);
+
+ keytable->table = NULL;
+ result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_keytable;
+
+ result = isc_mutex_init(&keytable->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_rbt;
+
+ result = isc_rwlock_init(&keytable->rwlock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lock;
+
+ keytable->mctx = mctx;
+ keytable->active_nodes = 0;
+ keytable->references = 1;
+ keytable->magic = KEYTABLE_MAGIC;
+ *keytablep = keytable;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_lock:
+ DESTROYLOCK(&keytable->lock);
+
+ cleanup_rbt:
+ dns_rbt_destroy(&keytable->table);
+
+ cleanup_keytable:
+ isc_mem_put(mctx, keytable, sizeof(*keytable));
+
+ return (result);
+}
+
+
+void
+dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
+
+ /*
+ * Attach *targetp to source.
+ */
+
+ REQUIRE(VALID_KEYTABLE(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ RWLOCK(&source->rwlock, isc_rwlocktype_write);
+
+ INSIST(source->references > 0);
+ source->references++;
+ INSIST(source->references != 0);
+
+ RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
+
+ *targetp = source;
+}
+
+void
+dns_keytable_detach(dns_keytable_t **keytablep) {
+ isc_boolean_t destroy = ISC_FALSE;
+ dns_keytable_t *keytable;
+
+ /*
+ * Detach *keytablep from its keytable.
+ */
+
+ REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep));
+
+ keytable = *keytablep;
+
+ RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
+
+ INSIST(keytable->references > 0);
+ keytable->references--;
+ LOCK(&keytable->lock);
+ if (keytable->references == 0 && keytable->active_nodes == 0)
+ destroy = ISC_TRUE;
+ UNLOCK(&keytable->lock);
+
+ RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
+
+ if (destroy) {
+ dns_rbt_destroy(&keytable->table);
+ isc_rwlock_destroy(&keytable->rwlock);
+ DESTROYLOCK(&keytable->lock);
+ keytable->magic = 0;
+ isc_mem_put(keytable->mctx, keytable, sizeof(*keytable));
+ }
+
+ *keytablep = NULL;
+}
+
+isc_result_t
+dns_keytable_add(dns_keytable_t *keytable, dst_key_t **keyp) {
+ isc_result_t result;
+ dns_keynode_t *knode;
+ dns_rbtnode_t *node;
+ dns_name_t *keyname;
+
+ /*
+ * Add '*keyp' to 'keytable'.
+ */
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(keyp != NULL);
+
+ keyname = dst_key_name(*keyp);
+
+ knode = isc_mem_get(keytable->mctx, sizeof(*knode));
+ if (knode == NULL)
+ return (ISC_R_NOMEMORY);
+
+ 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;
+ node->data = knode;
+ *keyp = NULL;
+ knode = NULL;
+ result = ISC_R_SUCCESS;
+ }
+
+ RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
+
+ if (knode != NULL)
+ isc_mem_put(keytable->mctx, knode, sizeof(*knode));
+
+ return (result);
+}
+
+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)
+{
+ isc_result_t result;
+ dns_keynode_t *knode;
+ void *data;
+
+ /*
+ * Search for a key named 'name', matching 'algorithm' and 'tag' in
+ * 'keytable'.
+ */
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE(keynodep != NULL && *keynodep == NULL);
+
+ RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
+
+ /*
+ * Note we don't want the DNS_R_PARTIALMATCH from dns_rbt_findname()
+ * as that indicates that 'name' was not found.
+ *
+ * DNS_R_PARTIALMATCH indicates that the name was found but we
+ * didn't get a match on algorithm and key id arguments.
+ */
+ knode = NULL;
+ data = NULL;
+ result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
+
+ if (result == ISC_R_SUCCESS) {
+ INSIST(data != NULL);
+ for (knode = data; knode != NULL; knode = knode->next) {
+ if (algorithm == dst_key_alg(knode->key)
+ && tag == dst_key_id(knode->key))
+ break;
+ }
+ if (knode != NULL) {
+ LOCK(&keytable->lock);
+ keytable->active_nodes++;
+ UNLOCK(&keytable->lock);
+ *keynodep = knode;
+ } else
+ result = DNS_R_PARTIALMATCH;
+ } else if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_NOTFOUND;
+
+ RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
+
+ return (result);
+}
+
+isc_result_t
+dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
+ dns_keynode_t **nextnodep)
+{
+ isc_result_t result;
+ dns_keynode_t *knode;
+
+ /*
+ * Search for the next key with the same properties as 'keynode' in
+ * 'keytable'.
+ */
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(VALID_KEYNODE(keynode));
+ REQUIRE(nextnodep != NULL && *nextnodep == NULL);
+
+ for (knode = keynode->next; knode != NULL; knode = knode->next) {
+ if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) &&
+ dst_key_id(keynode->key) == dst_key_id(knode->key))
+ break;
+ }
+ if (knode != NULL) {
+ LOCK(&keytable->lock);
+ keytable->active_nodes++;
+ UNLOCK(&keytable->lock);
+ result = ISC_R_SUCCESS;
+ *nextnodep = knode;
+ } else
+ result = ISC_R_NOTFOUND;
+
+ return (result);
+}
+
+isc_result_t
+dns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name,
+ dns_name_t *foundname)
+{
+ isc_result_t result;
+ void *data;
+
+ /*
+ * Search for the deepest match in 'keytable'.
+ */
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE(foundname != NULL);
+
+ RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
+
+ data = NULL;
+ result = dns_rbt_findname(keytable->table, name, 0, foundname, &data);
+
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+ result = ISC_R_SUCCESS;
+
+ RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
+
+ return (result);
+}
+
+void
+dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
+{
+ /*
+ * Give back a keynode found via dns_keytable_findkeynode().
+ */
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
+
+ LOCK(&keytable->lock);
+ INSIST(keytable->active_nodes > 0);
+ keytable->active_nodes--;
+ UNLOCK(&keytable->lock);
+
+ *keynodep = NULL;
+}
+
+isc_result_t
+dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
+ isc_boolean_t *wantdnssecp)
+{
+ isc_result_t result;
+ void *data;
+
+ /*
+ * Is 'name' at or beneath a trusted key?
+ */
+
+ REQUIRE(VALID_KEYTABLE(keytable));
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE(wantdnssecp != NULL);
+
+ RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
+
+ data = NULL;
+ result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
+
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
+ INSIST(data != NULL);
+ *wantdnssecp = ISC_TRUE;
+ result = ISC_R_SUCCESS;
+ } else if (result == ISC_R_NOTFOUND) {
+ *wantdnssecp = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ }
+
+ RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
+
+ return (result);
+}
+
+dst_key_t *
+dns_keynode_key(dns_keynode_t *keynode) {
+
+ /*
+ * Get the DST key associated with keynode.
+ */
+
+ REQUIRE(VALID_KEYNODE(keynode));
+
+ return (keynode->key);
+}
diff --git a/lib/dns/lib.c b/lib/dns/lib.c
new file mode 100644
index 0000000..6f98b53
--- /dev/null
+++ b/lib/dns/lib.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: lib.c,v 1.16 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/once.h>
+#include <isc/msgcat.h>
+#include <isc/util.h>
+
+#include <dns/lib.h>
+
+/***
+ *** Globals
+ ***/
+
+LIBDNS_EXTERNAL_DATA unsigned int dns_pps = 0U;
+LIBDNS_EXTERNAL_DATA isc_msgcat_t * dns_msgcat = NULL;
+
+
+/***
+ *** Private
+ ***/
+
+static isc_once_t msgcat_once = ISC_ONCE_INIT;
+
+
+/***
+ *** Functions
+ ***/
+
+static void
+open_msgcat(void) {
+ isc_msgcat_open("libdns.cat", &dns_msgcat);
+}
+
+void
+dns_lib_initmsgcat(void) {
+
+ /*
+ * Initialize the DNS library's message catalog, dns_msgcat, if it
+ * has not already been initialized.
+ */
+
+ RUNTIME_CHECK(isc_once_do(&msgcat_once, open_msgcat) == ISC_R_SUCCESS);
+}
diff --git a/lib/dns/log.c b/lib/dns/log.c
new file mode 100644
index 0000000..7551e15
--- /dev/null
+++ b/lib/dns/log.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004-2007 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
+ * 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: log.c,v 1.45 2007/06/18 23:47:40 tbox Exp $ */
+
+/*! \file */
+
+/* Principal Authors: DCL */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+#include <dns/log.h>
+
+/*%
+ * When adding a new category, be sure to add the appropriate
+ * \#define to <dns/log.h>.
+ */
+LIBDNS_EXTERNAL_DATA isc_logcategory_t dns_categories[] = {
+ { "notify", 0 },
+ { "database", 0 },
+ { "security", 0 },
+ { "_placeholder", 0 },
+ { "dnssec", 0 },
+ { "resolver", 0 },
+ { "xfer-in", 0 },
+ { "xfer-out", 0 },
+ { "dispatch", 0 },
+ { "lame-servers", 0 },
+ { "delegation-only", 0 },
+ { "edns-disabled", 0 },
+ { NULL, 0 }
+};
+
+/*%
+ * When adding a new module, be sure to add the appropriate
+ * \#define to <dns/log.h>.
+ */
+LIBDNS_EXTERNAL_DATA isc_logmodule_t dns_modules[] = {
+ { "dns/db", 0 },
+ { "dns/rbtdb", 0 },
+ { "dns/rbtdb64", 0 },
+ { "dns/rbt", 0 },
+ { "dns/rdata", 0 },
+ { "dns/master", 0 },
+ { "dns/message", 0 },
+ { "dns/cache", 0 },
+ { "dns/config", 0 },
+ { "dns/resolver", 0 },
+ { "dns/zone", 0 },
+ { "dns/journal", 0 },
+ { "dns/adb", 0 },
+ { "dns/xfrin", 0 },
+ { "dns/xfrout", 0 },
+ { "dns/acl", 0 },
+ { "dns/validator", 0 },
+ { "dns/dispatch", 0 },
+ { "dns/request", 0 },
+ { "dns/masterdump", 0 },
+ { "dns/tsig", 0 },
+ { "dns/tkey", 0 },
+ { "dns/sdb", 0 },
+ { "dns/diff", 0 },
+ { "dns/hints", 0 },
+ { "dns/acache", 0 },
+ { "dns/dlz", 0 },
+ { NULL, 0 }
+};
+
+LIBDNS_EXTERNAL_DATA isc_log_t *dns_lctx = NULL;
+
+void
+dns_log_init(isc_log_t *lctx) {
+ REQUIRE(lctx != NULL);
+
+ isc_log_registercategories(lctx, dns_categories);
+ isc_log_registermodules(lctx, dns_modules);
+}
+
+void
+dns_log_setcontext(isc_log_t *lctx) {
+ dns_lctx = lctx;
+}
diff --git a/lib/dns/lookup.c b/lib/dns/lookup.c
new file mode 100644
index 0000000..d5fc7aa
--- /dev/null
+++ b/lib/dns/lookup.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: lookup.c,v 1.21 2007/06/18 23:47:40 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/events.h>
+#include <dns/lookup.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/view.h>
+
+struct dns_lookup {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ isc_mutex_t lock;
+ dns_rdatatype_t type;
+ dns_fixedname_t name;
+ /* Locked by lock. */
+ unsigned int options;
+ isc_task_t * task;
+ dns_view_t * view;
+ dns_lookupevent_t * event;
+ dns_fetch_t * fetch;
+ unsigned int restarts;
+ isc_boolean_t canceled;
+ dns_rdataset_t rdataset;
+ dns_rdataset_t sigrdataset;
+};
+
+#define LOOKUP_MAGIC ISC_MAGIC('l', 'o', 'o', 'k')
+#define VALID_LOOKUP(l) ISC_MAGIC_VALID((l), LOOKUP_MAGIC)
+
+#define MAX_RESTARTS 16
+
+static void lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event);
+
+static void
+fetch_done(isc_task_t *task, isc_event_t *event) {
+ dns_lookup_t *lookup = event->ev_arg;
+ dns_fetchevent_t *fevent;
+
+ UNUSED(task);
+ REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
+ REQUIRE(VALID_LOOKUP(lookup));
+ REQUIRE(lookup->task == task);
+ fevent = (dns_fetchevent_t *)event;
+ REQUIRE(fevent->fetch == lookup->fetch);
+
+ lookup_find(lookup, fevent);
+}
+
+static inline isc_result_t
+start_fetch(dns_lookup_t *lookup) {
+ isc_result_t result;
+
+ /*
+ * The caller must be holding the lookup's lock.
+ */
+
+ REQUIRE(lookup->fetch == NULL);
+
+ result = dns_resolver_createfetch(lookup->view->resolver,
+ dns_fixedname_name(&lookup->name),
+ lookup->type,
+ NULL, NULL, NULL, 0,
+ lookup->task, fetch_done, lookup,
+ &lookup->rdataset,
+ &lookup->sigrdataset,
+ &lookup->fetch);
+
+ return (result);
+}
+
+static isc_result_t
+build_event(dns_lookup_t *lookup) {
+ dns_name_t *name = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdataset_t *sigrdataset = NULL;
+ isc_result_t result;
+
+ name = isc_mem_get(lookup->mctx, sizeof(dns_name_t));
+ if (name == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto fail;
+ }
+ dns_name_init(name, NULL);
+ result = dns_name_dup(dns_fixedname_name(&lookup->name),
+ lookup->mctx, name);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ if (dns_rdataset_isassociated(&lookup->rdataset)) {
+ rdataset = isc_mem_get(lookup->mctx, sizeof(dns_rdataset_t));
+ if (rdataset == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto fail;
+ }
+ dns_rdataset_init(rdataset);
+ dns_rdataset_clone(&lookup->rdataset, rdataset);
+ }
+
+ if (dns_rdataset_isassociated(&lookup->sigrdataset)) {
+ sigrdataset = isc_mem_get(lookup->mctx,
+ sizeof(dns_rdataset_t));
+ if (sigrdataset == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto fail;
+ }
+ dns_rdataset_init(sigrdataset);
+ dns_rdataset_clone(&lookup->sigrdataset, sigrdataset);
+ }
+
+ lookup->event->name = name;
+ lookup->event->rdataset = rdataset;
+ lookup->event->sigrdataset = sigrdataset;
+
+ return (ISC_R_SUCCESS);
+
+ fail:
+ if (name != NULL) {
+ if (dns_name_dynamic(name))
+ dns_name_free(name, lookup->mctx);
+ isc_mem_put(lookup->mctx, name, sizeof(dns_name_t));
+ }
+ if (rdataset != NULL) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ isc_mem_put(lookup->mctx, rdataset, sizeof(dns_rdataset_t));
+ }
+ return (result);
+}
+
+static isc_result_t
+view_find(dns_lookup_t *lookup, dns_name_t *foundname) {
+ isc_result_t result;
+ dns_name_t *name = dns_fixedname_name(&lookup->name);
+ dns_rdatatype_t type;
+
+ if (lookup->type == dns_rdatatype_rrsig)
+ type = dns_rdatatype_any;
+ else
+ type = lookup->type;
+
+ result = dns_view_find(lookup->view, name, type, 0, 0, ISC_FALSE,
+ &lookup->event->db, &lookup->event->node,
+ foundname, &lookup->rdataset,
+ &lookup->sigrdataset);
+ return (result);
+}
+
+static void
+lookup_find(dns_lookup_t *lookup, dns_fetchevent_t *event) {
+ isc_result_t result;
+ isc_boolean_t want_restart;
+ isc_boolean_t send_event;
+ dns_name_t *name, *fname, *prefix;
+ dns_fixedname_t foundname, fixed;
+ 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(VALID_LOOKUP(lookup));
+
+ LOCK(&lookup->lock);
+
+ result = ISC_R_SUCCESS;
+ name = dns_fixedname_name(&lookup->name);
+
+ do {
+ lookup->restarts++;
+ want_restart = ISC_FALSE;
+ send_event = ISC_TRUE;
+
+ if (event == NULL && !lookup->canceled) {
+ dns_fixedname_init(&foundname);
+ fname = dns_fixedname_name(&foundname);
+ INSIST(!dns_rdataset_isassociated(&lookup->rdataset));
+ INSIST(!dns_rdataset_isassociated
+ (&lookup->sigrdataset));
+ /*
+ * If we have restarted then clear the old node. */
+ if (lookup->event->node != NULL) {
+ INSIST(lookup->event->db != NULL);
+ dns_db_detachnode(lookup->event->db,
+ &lookup->event->node);
+ }
+ if (lookup->event->db != NULL)
+ dns_db_detach(&lookup->event->db);
+ result = view_find(lookup, fname);
+ if (result == ISC_R_NOTFOUND) {
+ /*
+ * We don't know anything about the name.
+ * Launch a fetch.
+ */
+ if (lookup->event->node != NULL) {
+ INSIST(lookup->event->db != NULL);
+ dns_db_detachnode(lookup->event->db,
+ &lookup->event->node);
+ }
+ if (lookup->event->db != NULL)
+ dns_db_detach(&lookup->event->db);
+ result = start_fetch(lookup);
+ if (result == ISC_R_SUCCESS)
+ send_event = ISC_FALSE;
+ goto done;
+ }
+ } else if (event != NULL) {
+ result = event->result;
+ fname = dns_fixedname_name(&event->foundname);
+ dns_resolver_destroyfetch(&lookup->fetch);
+ INSIST(event->rdataset == &lookup->rdataset);
+ INSIST(event->sigrdataset == &lookup->sigrdataset);
+ } else
+ fname = NULL; /* Silence compiler warning. */
+
+ /*
+ * If we've been canceled, forget about the result.
+ */
+ if (lookup->canceled)
+ result = ISC_R_CANCELED;
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ result = build_event(lookup);
+ if (event == NULL)
+ break;
+ if (event->db != NULL)
+ dns_db_attach(event->db, &lookup->event->db);
+ if (event->node != NULL)
+ dns_db_attachnode(lookup->event->db,
+ event->node,
+ &lookup->event->node);
+ break;
+ case DNS_R_CNAME:
+ /*
+ * Copy the CNAME's target into the lookup's
+ * query name and start over.
+ */
+ result = dns_rdataset_first(&lookup->rdataset);
+ if (result != ISC_R_SUCCESS)
+ break;
+ dns_rdataset_current(&lookup->rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS)
+ break;
+ result = dns_name_copy(&cname.cname, name, NULL);
+ dns_rdata_freestruct(&cname);
+ if (result == ISC_R_SUCCESS) {
+ want_restart = ISC_TRUE;
+ send_event = ISC_FALSE;
+ }
+ break;
+ case DNS_R_DNAME:
+ namereln = dns_name_fullcompare(name, fname, &order,
+ &nlabels);
+ INSIST(namereln == dns_namereln_subdomain);
+ /*
+ * Get the target name of the DNAME.
+ */
+ result = dns_rdataset_first(&lookup->rdataset);
+ if (result != ISC_R_SUCCESS)
+ break;
+ dns_rdataset_current(&lookup->rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &dname, NULL);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS)
+ break;
+ /*
+ * Construct the new query name and start over.
+ */
+ dns_fixedname_init(&fixed);
+ prefix = dns_fixedname_name(&fixed);
+ dns_name_split(name, nlabels, prefix, NULL);
+ result = dns_name_concatenate(prefix, &dname.dname,
+ name, NULL);
+ dns_rdata_freestruct(&dname);
+ if (result == ISC_R_SUCCESS) {
+ want_restart = ISC_TRUE;
+ send_event = ISC_FALSE;
+ }
+ break;
+ default:
+ send_event = ISC_TRUE;
+ }
+
+ if (dns_rdataset_isassociated(&lookup->rdataset))
+ dns_rdataset_disassociate(&lookup->rdataset);
+ if (dns_rdataset_isassociated(&lookup->sigrdataset))
+ dns_rdataset_disassociate(&lookup->sigrdataset);
+
+ done:
+ if (event != NULL) {
+ if (event->node != NULL)
+ dns_db_detachnode(event->db, &event->node);
+ if (event->db != NULL)
+ dns_db_detach(&event->db);
+ isc_event_free(ISC_EVENT_PTR(&event));
+ }
+
+ /*
+ * Limit the number of restarts.
+ */
+ if (want_restart && lookup->restarts == MAX_RESTARTS) {
+ want_restart = ISC_FALSE;
+ result = ISC_R_QUOTA;
+ send_event = ISC_TRUE;
+ }
+
+ } while (want_restart);
+
+ if (send_event) {
+ lookup->event->result = result;
+ lookup->event->ev_sender = lookup;
+ isc_task_sendanddetach(&lookup->task,
+ (isc_event_t **)&lookup->event);
+ dns_view_detach(&lookup->view);
+ }
+
+ UNLOCK(&lookup->lock);
+}
+
+static void
+levent_destroy(isc_event_t *event) {
+ dns_lookupevent_t *levent;
+ isc_mem_t *mctx;
+
+ REQUIRE(event->ev_type == DNS_EVENT_LOOKUPDONE);
+ mctx = event->ev_destroy_arg;
+ levent = (dns_lookupevent_t *)event;
+
+ if (levent->name != NULL) {
+ if (dns_name_dynamic(levent->name))
+ dns_name_free(levent->name, mctx);
+ isc_mem_put(mctx, levent->name, sizeof(dns_name_t));
+ }
+ if (levent->rdataset != NULL) {
+ dns_rdataset_disassociate(levent->rdataset);
+ isc_mem_put(mctx, levent->rdataset, sizeof(dns_rdataset_t));
+ }
+ if (levent->sigrdataset != NULL) {
+ dns_rdataset_disassociate(levent->sigrdataset);
+ isc_mem_put(mctx, levent->sigrdataset, sizeof(dns_rdataset_t));
+ }
+ if (levent->node != NULL)
+ dns_db_detachnode(levent->db, &levent->node);
+ if (levent->db != NULL)
+ dns_db_detach(&levent->db);
+ isc_mem_put(mctx, event, event->ev_size);
+}
+
+isc_result_t
+dns_lookup_create(isc_mem_t *mctx, dns_name_t *name, dns_rdatatype_t type,
+ dns_view_t *view, unsigned int options, isc_task_t *task,
+ isc_taskaction_t action, void *arg, dns_lookup_t **lookupp)
+{
+ isc_result_t result;
+ dns_lookup_t *lookup;
+ isc_event_t *ievent;
+
+ lookup = isc_mem_get(mctx, sizeof(*lookup));
+ if (lookup == NULL)
+ return (ISC_R_NOMEMORY);
+ lookup->mctx = mctx;
+ lookup->options = options;
+
+ ievent = isc_event_allocate(mctx, lookup, DNS_EVENT_LOOKUPDONE,
+ action, arg, sizeof(*lookup->event));
+ if (ievent == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_lookup;
+ }
+ lookup->event = (dns_lookupevent_t *)ievent;
+ lookup->event->ev_destroy = levent_destroy;
+ lookup->event->ev_destroy_arg = mctx;
+ lookup->event->result = ISC_R_FAILURE;
+ lookup->event->name = NULL;
+ lookup->event->rdataset = NULL;
+ lookup->event->sigrdataset = NULL;
+ lookup->event->db = NULL;
+ lookup->event->node = NULL;
+
+ lookup->task = NULL;
+ isc_task_attach(task, &lookup->task);
+
+ result = isc_mutex_init(&lookup->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_event;
+
+ dns_fixedname_init(&lookup->name);
+
+ result = dns_name_copy(name, dns_fixedname_name(&lookup->name), NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lock;
+
+ lookup->type = type;
+ lookup->view = NULL;
+ dns_view_attach(view, &lookup->view);
+ lookup->fetch = NULL;
+ lookup->restarts = 0;
+ lookup->canceled = ISC_FALSE;
+ dns_rdataset_init(&lookup->rdataset);
+ dns_rdataset_init(&lookup->sigrdataset);
+ lookup->magic = LOOKUP_MAGIC;
+
+ *lookupp = lookup;
+
+ lookup_find(lookup, NULL);
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_lock:
+ DESTROYLOCK(&lookup->lock);
+
+ cleanup_event:
+ ievent = (isc_event_t *)lookup->event;
+ isc_event_free(&ievent);
+ lookup->event = NULL;
+
+ isc_task_detach(&lookup->task);
+
+ cleanup_lookup:
+ isc_mem_put(mctx, lookup, sizeof(*lookup));
+
+ return (result);
+}
+
+void
+dns_lookup_cancel(dns_lookup_t *lookup) {
+ REQUIRE(VALID_LOOKUP(lookup));
+
+ LOCK(&lookup->lock);
+
+ if (!lookup->canceled) {
+ lookup->canceled = ISC_TRUE;
+ if (lookup->fetch != NULL) {
+ INSIST(lookup->view != NULL);
+ dns_resolver_cancelfetch(lookup->fetch);
+ }
+ }
+
+ UNLOCK(&lookup->lock);
+}
+
+void
+dns_lookup_destroy(dns_lookup_t **lookupp) {
+ dns_lookup_t *lookup;
+
+ REQUIRE(lookupp != NULL);
+ lookup = *lookupp;
+ REQUIRE(VALID_LOOKUP(lookup));
+ REQUIRE(lookup->event == NULL);
+ REQUIRE(lookup->task == NULL);
+ REQUIRE(lookup->view == NULL);
+ if (dns_rdataset_isassociated(&lookup->rdataset))
+ dns_rdataset_disassociate(&lookup->rdataset);
+ if (dns_rdataset_isassociated(&lookup->sigrdataset))
+ dns_rdataset_disassociate(&lookup->sigrdataset);
+
+ DESTROYLOCK(&lookup->lock);
+ lookup->magic = 0;
+ isc_mem_put(lookup->mctx, lookup, sizeof(*lookup));
+
+ *lookupp = NULL;
+}
diff --git a/lib/dns/master.c b/lib/dns/master.c
new file mode 100644
index 0000000..743e87b
--- /dev/null
+++ b/lib/dns/master.c
@@ -0,0 +1,2892 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: master.c,v 1.171 2008/04/02 02:37:42 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/event.h>
+#include <isc/lex.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/serial.h>
+#include <isc/stdio.h>
+#include <isc/stdtime.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/master.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/soa.h>
+#include <dns/time.h>
+#include <dns/ttl.h>
+
+/*!
+ * Grow the number of dns_rdatalist_t (#RDLSZ) and dns_rdata_t (#RDSZ) structures
+ * by these sizes when we need to.
+ *
+ */
+/*% RDLSZ reflects the number of different types with the same name expected. */
+#define RDLSZ 32
+/*%
+ * RDSZ reflects the number of rdata expected at a give name that can fit into
+ * 64k.
+ */
+#define RDSZ 512
+
+#define NBUFS 4
+#define MAXWIRESZ 255
+
+/*%
+ * Target buffer size and minimum target size.
+ * MINTSIZ must be big enough to hold the largest rdata record.
+ * \brief
+ * TSIZ >= MINTSIZ
+ */
+#define TSIZ (128*1024)
+/*%
+ * max message size - header - root - type - class - ttl - rdlen
+ */
+#define MINTSIZ (65535 - 12 - 1 - 2 - 2 - 4 - 2)
+/*%
+ * Size for tokens in the presentation format,
+ * The largest tokens are the base64 blocks in KEY and CERT records,
+ * Largest key allowed is about 1372 bytes but
+ * there is no fixed upper bound on CERT records.
+ * 2K is too small for some X.509s, 8K is overkill.
+ */
+#define TOKENSIZ (8*1024)
+
+#define DNS_MASTER_BUFSZ 2048
+
+typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t;
+
+typedef struct dns_incctx dns_incctx_t;
+
+/*%
+ * Master file load state.
+ */
+
+struct dns_loadctx {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ dns_masterformat_t format;
+
+ dns_rdatacallbacks_t *callbacks;
+ isc_task_t *task;
+ dns_loaddonefunc_t done;
+ void *done_arg;
+
+ /* Common methods */
+ isc_result_t (*openfile)(dns_loadctx_t *lctx,
+ const char *filename);
+ isc_result_t (*load)(dns_loadctx_t *lctx);
+
+ /* Members specific to the text format: */
+ isc_lex_t *lex;
+ isc_boolean_t keep_lex;
+ unsigned int options;
+ isc_boolean_t ttl_known;
+ isc_boolean_t default_ttl_known;
+ isc_boolean_t warn_1035;
+ isc_boolean_t warn_tcr;
+ isc_boolean_t warn_sigexpired;
+ isc_boolean_t seen_include;
+ isc_uint32_t ttl;
+ isc_uint32_t default_ttl;
+ dns_rdataclass_t zclass;
+ dns_fixedname_t fixed_top;
+ dns_name_t *top; /*%< top of zone */
+
+ /* Members specific to the raw format: */
+ FILE *f;
+ isc_boolean_t first;
+
+ /* Which fixed buffers we are using? */
+ unsigned int loop_cnt; /*% records per quantum,
+ * 0 => all. */
+ isc_boolean_t canceled;
+ isc_mutex_t lock;
+ isc_result_t result;
+ /* locked by lock */
+ isc_uint32_t references;
+ dns_incctx_t *inc;
+ isc_uint32_t resign;
+};
+
+struct dns_incctx {
+ dns_incctx_t *parent;
+ dns_name_t *origin;
+ dns_name_t *current;
+ dns_name_t *glue;
+ dns_fixedname_t fixed[NBUFS]; /* working buffers */
+ unsigned int in_use[NBUFS]; /* covert to bitmap? */
+ int glue_in_use;
+ int current_in_use;
+ int origin_in_use;
+ isc_boolean_t drop;
+ unsigned int glue_line;
+ unsigned int current_line;
+};
+
+#define DNS_LCTX_MAGIC ISC_MAGIC('L','c','t','x')
+#define DNS_LCTX_VALID(lctx) ISC_MAGIC_VALID(lctx, DNS_LCTX_MAGIC)
+
+#define DNS_AS_STR(t) ((t).value.as_textregion.base)
+
+static isc_result_t
+openfile_text(dns_loadctx_t *lctx, const char *master_file);
+
+static isc_result_t
+openfile_raw(dns_loadctx_t *lctx, const char *master_file);
+
+static isc_result_t
+load_text(dns_loadctx_t *lctx);
+
+static isc_result_t
+load_raw(dns_loadctx_t *lctx);
+
+static isc_result_t
+pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx);
+
+static isc_result_t
+commit(dns_rdatacallbacks_t *, dns_loadctx_t *, rdatalist_head_t *,
+ dns_name_t *, const char *, unsigned int);
+
+static isc_boolean_t
+is_glue(rdatalist_head_t *, dns_name_t *);
+
+static dns_rdatalist_t *
+grow_rdatalist(int, dns_rdatalist_t *, int, rdatalist_head_t *,
+ rdatalist_head_t *, isc_mem_t *mctx);
+
+static dns_rdata_t *
+grow_rdata(int, dns_rdata_t *, int, rdatalist_head_t *, rdatalist_head_t *,
+ isc_mem_t *);
+
+static void
+load_quantum(isc_task_t *task, isc_event_t *event);
+
+static isc_result_t
+task_send(dns_loadctx_t *lctx);
+
+static void
+loadctx_destroy(dns_loadctx_t *lctx);
+
+#define GETTOKEN(lexer, options, token, eol) \
+ do { \
+ result = gettoken(lexer, options, token, eol, callbacks); \
+ switch (result) { \
+ case ISC_R_SUCCESS: \
+ break; \
+ case ISC_R_UNEXPECTED: \
+ goto insist_and_cleanup; \
+ default: \
+ if (MANYERRS(lctx, result)) { \
+ SETRESULT(lctx, result); \
+ LOGIT(result); \
+ read_till_eol = ISC_TRUE; \
+ goto next_line; \
+ } else \
+ goto log_and_cleanup; \
+ } \
+ if ((token)->type == isc_tokentype_special) { \
+ result = DNS_R_SYNTAX; \
+ if (MANYERRS(lctx, result)) { \
+ SETRESULT(lctx, result); \
+ LOGIT(result); \
+ read_till_eol = ISC_TRUE; \
+ goto next_line; \
+ } else \
+ goto log_and_cleanup; \
+ } \
+ } while (0)
+
+#define COMMITALL \
+ do { \
+ result = commit(callbacks, lctx, &current_list, \
+ ictx->current, source, ictx->current_line); \
+ if (MANYERRS(lctx, result)) { \
+ SETRESULT(lctx, result); \
+ } else if (result != ISC_R_SUCCESS) \
+ goto insist_and_cleanup; \
+ result = commit(callbacks, lctx, &glue_list, \
+ ictx->glue, source, ictx->glue_line); \
+ if (MANYERRS(lctx, result)) { \
+ SETRESULT(lctx, result); \
+ } else if (result != ISC_R_SUCCESS) \
+ goto insist_and_cleanup; \
+ rdcount = 0; \
+ rdlcount = 0; \
+ isc_buffer_init(&target, target_mem, target_size); \
+ rdcount_save = rdcount; \
+ rdlcount_save = rdlcount; \
+ } while (0)
+
+#define WARNUNEXPECTEDEOF(lexer) \
+ do { \
+ if (isc_lex_isfile(lexer)) \
+ (*callbacks->warn)(callbacks, \
+ "%s: file does not end with newline", \
+ source); \
+ } while (0)
+
+#define EXPECTEOL \
+ do { \
+ GETTOKEN(lctx->lex, 0, &token, ISC_TRUE); \
+ if (token.type != isc_tokentype_eol) { \
+ isc_lex_ungettoken(lctx->lex, &token); \
+ result = DNS_R_EXTRATOKEN; \
+ if (MANYERRS(lctx, result)) { \
+ SETRESULT(lctx, result); \
+ LOGIT(result); \
+ read_till_eol = ISC_TRUE; \
+ continue; \
+ } else if (result != ISC_R_SUCCESS) \
+ goto log_and_cleanup; \
+ } \
+ } while (0)
+
+#define MANYERRS(lctx, result) \
+ ((result != ISC_R_SUCCESS) && \
+ (result != ISC_R_IOERROR) && \
+ ((lctx)->options & DNS_MASTER_MANYERRORS) != 0)
+
+#define SETRESULT(lctx, r) \
+ do { \
+ if ((lctx)->result == ISC_R_SUCCESS) \
+ (lctx)->result = r; \
+ } while (0)
+
+#define LOGITFILE(result, filename) \
+ if (result == ISC_R_INVALIDFILE || result == ISC_R_FILENOTFOUND || \
+ result == ISC_R_IOERROR || result == ISC_R_TOOMANYOPENFILES || \
+ result == ISC_R_NOPERM) \
+ (*callbacks->error)(callbacks, "%s: %s:%lu: %s: %s", \
+ "dns_master_load", source, line, \
+ filename, dns_result_totext(result)); \
+ else LOGIT(result)
+
+#define LOGIT(result) \
+ if (result == ISC_R_NOMEMORY) \
+ (*callbacks->error)(callbacks, "dns_master_load: %s", \
+ dns_result_totext(result)); \
+ else \
+ (*callbacks->error)(callbacks, "%s: %s:%lu: %s", \
+ "dns_master_load", \
+ source, line, dns_result_totext(result))
+
+
+static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA";
+static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
+static const dns_name_t in_addr_arpa =
+{
+ DNS_NAME_MAGIC,
+ in_addr_arpa_data, 14, 3,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ in_addr_arpa_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+static unsigned char ip6_int_data[] = "\003IP6\003INT";
+static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
+static const dns_name_t ip6_int =
+{
+ DNS_NAME_MAGIC,
+ ip6_int_data, 9, 3,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ ip6_int_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";
+static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
+static const dns_name_t ip6_arpa =
+{
+ DNS_NAME_MAGIC,
+ ip6_arpa_data, 10, 3,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ ip6_arpa_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+
+static inline isc_result_t
+gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token,
+ isc_boolean_t eol, dns_rdatacallbacks_t *callbacks)
+{
+ isc_result_t result;
+
+ options |= ISC_LEXOPT_EOL | ISC_LEXOPT_EOF | ISC_LEXOPT_DNSMULTILINE |
+ ISC_LEXOPT_ESCAPE;
+ result = isc_lex_gettoken(lex, options, token);
+ if (result != ISC_R_SUCCESS) {
+ switch (result) {
+ case ISC_R_NOMEMORY:
+ return (ISC_R_NOMEMORY);
+ default:
+ (*callbacks->error)(callbacks,
+ "dns_master_load: %s:%lu:"
+ " isc_lex_gettoken() failed: %s",
+ isc_lex_getsourcename(lex),
+ isc_lex_getsourceline(lex),
+ isc_result_totext(result));
+ return (result);
+ }
+ /*NOTREACHED*/
+ }
+ if (eol != ISC_TRUE)
+ if (token->type == isc_tokentype_eol ||
+ token->type == isc_tokentype_eof) {
+ (*callbacks->error)(callbacks,
+ "dns_master_load: %s:%lu: unexpected end of %s",
+ isc_lex_getsourcename(lex),
+ isc_lex_getsourceline(lex),
+ (token->type ==
+ isc_tokentype_eol) ?
+ "line" : "file");
+ return (ISC_R_UNEXPECTEDEND);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+
+void
+dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
+
+ REQUIRE(target != NULL && *target == NULL);
+ REQUIRE(DNS_LCTX_VALID(source));
+
+ LOCK(&source->lock);
+ INSIST(source->references > 0);
+ source->references++;
+ INSIST(source->references != 0); /* Overflow? */
+ UNLOCK(&source->lock);
+
+ *target = source;
+}
+
+void
+dns_loadctx_detach(dns_loadctx_t **lctxp) {
+ dns_loadctx_t *lctx;
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(lctxp != NULL);
+ lctx = *lctxp;
+ REQUIRE(DNS_LCTX_VALID(lctx));
+
+ LOCK(&lctx->lock);
+ INSIST(lctx->references > 0);
+ lctx->references--;
+ if (lctx->references == 0)
+ need_destroy = ISC_TRUE;
+ UNLOCK(&lctx->lock);
+
+ if (need_destroy)
+ loadctx_destroy(lctx);
+ *lctxp = NULL;
+}
+
+static void
+incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
+ dns_incctx_t *parent;
+
+ again:
+ parent = ictx->parent;
+ ictx->parent = NULL;
+
+ isc_mem_put(mctx, ictx, sizeof(*ictx));
+
+ if (parent != NULL) {
+ ictx = parent;
+ goto again;
+ }
+}
+
+static void
+loadctx_destroy(dns_loadctx_t *lctx) {
+ isc_mem_t *mctx;
+ isc_result_t result;
+
+ REQUIRE(DNS_LCTX_VALID(lctx));
+
+ lctx->magic = 0;
+ if (lctx->inc != NULL)
+ incctx_destroy(lctx->mctx, lctx->inc);
+
+ if (lctx->f != NULL) {
+ result = isc_stdio_close(lctx->f);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_stdio_close() failed: %s",
+ isc_result_totext(result));
+ }
+ }
+
+ /* isc_lex_destroy() will close all open streams */
+ if (lctx->lex != NULL && !lctx->keep_lex)
+ isc_lex_destroy(&lctx->lex);
+
+ if (lctx->task != NULL)
+ isc_task_detach(&lctx->task);
+ DESTROYLOCK(&lctx->lock);
+ mctx = NULL;
+ isc_mem_attach(lctx->mctx, &mctx);
+ isc_mem_detach(&lctx->mctx);
+ isc_mem_put(mctx, lctx, sizeof(*lctx));
+ isc_mem_detach(&mctx);
+}
+
+static isc_result_t
+incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) {
+ dns_incctx_t *ictx;
+ isc_region_t r;
+ int i;
+
+ ictx = isc_mem_get(mctx, sizeof(*ictx));
+ if (ictx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ for (i = 0; i < NBUFS; i++) {
+ dns_fixedname_init(&ictx->fixed[i]);
+ ictx->in_use[i] = ISC_FALSE;
+ }
+
+ ictx->origin_in_use = 0;
+ ictx->origin = dns_fixedname_name(&ictx->fixed[ictx->origin_in_use]);
+ ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
+ dns_name_toregion(origin, &r);
+ dns_name_fromregion(ictx->origin, &r);
+
+ ictx->glue = NULL;
+ ictx->current = NULL;
+ ictx->glue_in_use = -1;
+ ictx->current_in_use = -1;
+ ictx->parent = NULL;
+ ictx->drop = ISC_FALSE;
+ ictx->glue_line = 0;
+ ictx->current_line = 0;
+
+ *ictxp = ictx;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
+ unsigned int options, isc_uint32_t resign, dns_name_t *top,
+ dns_rdataclass_t zclass, dns_name_t *origin,
+ dns_rdatacallbacks_t *callbacks, isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg, isc_lex_t *lex,
+ dns_loadctx_t **lctxp)
+{
+ dns_loadctx_t *lctx;
+ isc_result_t result;
+ isc_region_t r;
+ isc_lexspecials_t specials;
+
+ REQUIRE(lctxp != NULL && *lctxp == NULL);
+ REQUIRE(callbacks != NULL);
+ REQUIRE(callbacks->add != NULL);
+ REQUIRE(callbacks->error != NULL);
+ REQUIRE(callbacks->warn != NULL);
+ REQUIRE(mctx != NULL);
+ REQUIRE(dns_name_isabsolute(top));
+ REQUIRE(dns_name_isabsolute(origin));
+ REQUIRE((task == NULL && done == NULL) ||
+ (task != NULL && done != NULL));
+
+ lctx = isc_mem_get(mctx, sizeof(*lctx));
+ if (lctx == NULL)
+ return (ISC_R_NOMEMORY);
+ result = isc_mutex_init(&lctx->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, lctx, sizeof(*lctx));
+ return (result);
+ }
+
+ lctx->inc = NULL;
+ result = incctx_create(mctx, origin, &lctx->inc);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_ctx;
+
+ lctx->format = format;
+ switch (format) {
+ default:
+ INSIST(0);
+ case dns_masterformat_text:
+ lctx->openfile = openfile_text;
+ lctx->load = load_text;
+ break;
+ case dns_masterformat_raw:
+ lctx->openfile = openfile_raw;
+ lctx->load = load_raw;
+ break;
+ }
+
+ if (lex != NULL) {
+ lctx->lex = lex;
+ lctx->keep_lex = ISC_TRUE;
+ } else {
+ lctx->lex = NULL;
+ result = isc_lex_create(mctx, TOKENSIZ, &lctx->lex);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_inc;
+ lctx->keep_lex = ISC_FALSE;
+ memset(specials, 0, sizeof(specials));
+ specials['('] = 1;
+ specials[')'] = 1;
+ specials['"'] = 1;
+ isc_lex_setspecials(lctx->lex, specials);
+ isc_lex_setcomments(lctx->lex, ISC_LEXCOMMENT_DNSMASTERFILE);
+ }
+
+ lctx->ttl_known = ISC_FALSE;
+ lctx->ttl = 0;
+ lctx->default_ttl_known = ISC_FALSE;
+ lctx->default_ttl = 0;
+ lctx->warn_1035 = ISC_TRUE; /* XXX Argument? */
+ lctx->warn_tcr = ISC_TRUE; /* XXX Argument? */
+ lctx->warn_sigexpired = ISC_TRUE; /* XXX Argument? */
+ lctx->options = options;
+ lctx->seen_include = ISC_FALSE;
+ lctx->zclass = zclass;
+ lctx->resign = resign;
+ lctx->result = ISC_R_SUCCESS;
+
+ dns_fixedname_init(&lctx->fixed_top);
+ lctx->top = dns_fixedname_name(&lctx->fixed_top);
+ dns_name_toregion(top, &r);
+ dns_name_fromregion(lctx->top, &r);
+
+ lctx->f = NULL;
+ lctx->first = ISC_TRUE;
+
+ lctx->loop_cnt = (done != NULL) ? 100 : 0;
+ lctx->callbacks = callbacks;
+ lctx->task = NULL;
+ if (task != NULL)
+ isc_task_attach(task, &lctx->task);
+ lctx->done = done;
+ lctx->done_arg = done_arg;
+ lctx->canceled = ISC_FALSE;
+ lctx->mctx = NULL;
+ isc_mem_attach(mctx, &lctx->mctx);
+ lctx->references = 1; /* Implicit attach. */
+ lctx->magic = DNS_LCTX_MAGIC;
+ *lctxp = lctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup_inc:
+ incctx_destroy(mctx, lctx->inc);
+ cleanup_ctx:
+ isc_mem_put(mctx, lctx, sizeof(*lctx));
+ return (result);
+}
+
+static isc_result_t
+genname(char *name, int it, char *buffer, size_t length) {
+ char fmt[sizeof("%04000000000d")];
+ char numbuf[128];
+ char *cp;
+ char mode[2];
+ int delta = 0;
+ isc_textregion_t r;
+ unsigned int n;
+ unsigned int width;
+
+ r.base = buffer;
+ r.length = length;
+
+ while (*name != '\0') {
+ if (*name == '$') {
+ name++;
+ if (*name == '$') {
+ if (r.length == 0)
+ return (ISC_R_NOSPACE);
+ r.base[0] = *name++;
+ isc_textregion_consume(&r, 1);
+ continue;
+ }
+ strcpy(fmt, "%d");
+ /* Get format specifier. */
+ if (*name == '{' ) {
+ n = sscanf(name, "{%d,%u,%1[doxX]}",
+ &delta, &width, mode);
+ switch (n) {
+ case 1:
+ break;
+ case 2:
+ n = snprintf(fmt, sizeof(fmt),
+ "%%0%ud", width);
+ break;
+ case 3:
+ n = snprintf(fmt, sizeof(fmt),
+ "%%0%u%c", width, mode[0]);
+ break;
+ default:
+ return (DNS_R_SYNTAX);
+ }
+ if (n >= sizeof(fmt))
+ return (ISC_R_NOSPACE);
+ /* Skip past closing brace. */
+ while (*name != '\0' && *name++ != '}')
+ continue;
+ }
+ n = snprintf(numbuf, sizeof(numbuf), fmt, it + delta);
+ if (n >= sizeof(numbuf))
+ return (ISC_R_NOSPACE);
+ cp = numbuf;
+ while (*cp != '\0') {
+ if (r.length == 0)
+ return (ISC_R_NOSPACE);
+ r.base[0] = *cp++;
+ isc_textregion_consume(&r, 1);
+ }
+ } else if (*name == '\\') {
+ if (r.length == 0)
+ return (ISC_R_NOSPACE);
+ r.base[0] = *name++;
+ isc_textregion_consume(&r, 1);
+ if (*name == '\0')
+ continue;
+ if (r.length == 0)
+ return (ISC_R_NOSPACE);
+ r.base[0] = *name++;
+ isc_textregion_consume(&r, 1);
+ } else {
+ if (r.length == 0)
+ return (ISC_R_NOSPACE);
+ r.base[0] = *name++;
+ isc_textregion_consume(&r, 1);
+ }
+ }
+ if (r.length == 0)
+ return (ISC_R_NOSPACE);
+ r.base[0] = '\0';
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+openfile_text(dns_loadctx_t *lctx, const char *master_file) {
+ return (isc_lex_openfile(lctx->lex, master_file));
+}
+
+static isc_result_t
+openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
+ isc_result_t result;
+
+ result = isc_stdio_open(master_file, "r", &lctx->f);
+ if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_stdio_open() failed: %s",
+ isc_result_totext(result));
+ }
+
+ return (result);
+}
+
+static isc_result_t
+generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs,
+ const char *source, unsigned int line)
+{
+ char *target_mem = NULL;
+ char *lhsbuf = NULL;
+ char *rhsbuf = NULL;
+ dns_fixedname_t ownerfixed;
+ dns_name_t *owner;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdatacallbacks_t *callbacks;
+ dns_rdatalist_t rdatalist;
+ dns_rdatatype_t type;
+ rdatalist_head_t head;
+ int n;
+ int target_size = MINTSIZ; /* only one rdata at a time */
+ isc_buffer_t buffer;
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_textregion_t r;
+ unsigned int start, stop, step, i;
+ dns_incctx_t *ictx;
+
+ ictx = lctx->inc;
+ callbacks = lctx->callbacks;
+ dns_fixedname_init(&ownerfixed);
+ owner = dns_fixedname_name(&ownerfixed);
+ 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);
+ if (target_mem == NULL || rhsbuf == NULL || lhsbuf == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto error_cleanup;
+ }
+ isc_buffer_init(&target, target_mem, target_size);
+
+ n = sscanf(range, "%u-%u/%u", &start, &stop, &step);
+ if (n < 2 || stop < start) {
+ (*callbacks->error)(callbacks,
+ "%s: %s:%lu: invalid range '%s'",
+ "$GENERATE", source, line, range);
+ result = DNS_R_SYNTAX;
+ goto insist_cleanup;
+ }
+ if (n == 2)
+ step = 1;
+
+ /*
+ * Get type.
+ */
+ r.base = gtype;
+ r.length = strlen(gtype);
+ result = dns_rdatatype_fromtext(&type, &r);
+ if (result != ISC_R_SUCCESS) {
+ (*callbacks->error)(callbacks,
+ "%s: %s:%lu: unknown RR type '%s'",
+ "$GENERATE", source, line, gtype);
+ 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);
+ if (result != ISC_R_SUCCESS)
+ goto error_cleanup;
+ result = genname(rhs, i, rhsbuf, DNS_MASTER_BUFSZ);
+ if (result != ISC_R_SUCCESS)
+ goto error_cleanup;
+
+ isc_buffer_init(&buffer, lhsbuf, strlen(lhsbuf));
+ isc_buffer_add(&buffer, strlen(lhsbuf));
+ isc_buffer_setactive(&buffer, strlen(lhsbuf));
+ result = dns_name_fromtext(owner, &buffer, ictx->origin,
+ 0, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto error_cleanup;
+
+ if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
+ (lctx->options & DNS_MASTER_SLAVE) == 0 &&
+ !dns_name_issubdomain(owner, lctx->top))
+ {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(owner, namebuf, sizeof(namebuf));
+ /*
+ * Ignore out-of-zone data.
+ */
+ (*callbacks->warn)(callbacks,
+ "%s:%lu: "
+ "ignoring out-of-zone data (%s)",
+ source, line, namebuf);
+ continue;
+ }
+
+ isc_buffer_init(&buffer, rhsbuf, strlen(rhsbuf));
+ isc_buffer_add(&buffer, strlen(rhsbuf));
+ isc_buffer_setactive(&buffer, strlen(rhsbuf));
+
+ result = isc_lex_openbuffer(lctx->lex, &buffer);
+ if (result != ISC_R_SUCCESS)
+ goto error_cleanup;
+
+ isc_buffer_init(&target, target_mem, target_size);
+ result = dns_rdata_fromtext(&rdata, lctx->zclass, type,
+ lctx->lex, ictx->origin, 0,
+ lctx->mctx, &target, callbacks);
+ RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ goto error_cleanup;
+
+ rdatalist.type = type;
+ rdatalist.covers = 0;
+ rdatalist.rdclass = lctx->zclass;
+ rdatalist.ttl = lctx->ttl;
+ ISC_LIST_PREPEND(head, &rdatalist, link);
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ result = commit(callbacks, lctx, &head, owner, source, line);
+ ISC_LIST_UNLINK(rdatalist.rdata, &rdata, link);
+ if (result != ISC_R_SUCCESS)
+ goto error_cleanup;
+ dns_rdata_reset(&rdata);
+ }
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+
+ error_cleanup:
+ if (result == ISC_R_NOMEMORY)
+ (*callbacks->error)(callbacks, "$GENERATE: %s",
+ dns_result_totext(result));
+ else
+ (*callbacks->error)(callbacks, "$GENERATE: %s:%lu: %s",
+ source, line, dns_result_totext(result));
+
+ insist_cleanup:
+ INSIST(result != ISC_R_SUCCESS);
+
+ cleanup:
+ 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);
+ if (rhsbuf != NULL)
+ isc_mem_put(lctx->mctx, rhsbuf, DNS_MASTER_BUFSZ);
+ return (result);
+}
+
+static void
+limit_ttl(dns_rdatacallbacks_t *callbacks, const char *source, unsigned int line,
+ isc_uint32_t *ttlp)
+{
+ if (*ttlp > 0x7fffffffUL) {
+ (callbacks->warn)(callbacks,
+ "%s: %s:%lu: "
+ "$TTL %lu > MAXTTL, "
+ "setting $TTL to 0",
+ "dns_master_load",
+ source, line,
+ *ttlp);
+ *ttlp = 0;
+ }
+}
+
+static isc_result_t
+check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
+ unsigned long line)
+{
+ char *tmp = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ void (*callback)(struct dns_rdatacallbacks *, const char *, ...);
+
+ if ((lctx->options & DNS_MASTER_FATALNS) != 0)
+ callback = lctx->callbacks->error;
+ else
+ callback = lctx->callbacks->warn;
+
+ if (token->type == isc_tokentype_string) {
+ struct in_addr addr;
+ struct in6_addr addr6;
+
+ tmp = isc_mem_strdup(lctx->mctx, DNS_AS_STR(*token));
+ if (tmp == NULL)
+ return (ISC_R_NOMEMORY);
+ /*
+ * Catch both "1.2.3.4" and "1.2.3.4."
+ */
+ if (tmp[strlen(tmp) - 1] == '.')
+ tmp[strlen(tmp) - 1] = '\0';
+ if (inet_aton(tmp, &addr) == 1 ||
+ inet_pton(AF_INET6, tmp, &addr6) == 1)
+ result = DNS_R_NSISADDRESS;
+ }
+ if (result != ISC_R_SUCCESS)
+ (*callback)(lctx->callbacks, "%s:%lu: NS record '%s' "
+ "appears to be an address",
+ source, line, DNS_AS_STR(*token));
+ if (tmp != NULL)
+ isc_mem_free(lctx->mctx, tmp);
+ return (result);
+}
+
+static void
+check_wildcard(dns_incctx_t *ictx, const char *source, unsigned long line,
+ dns_rdatacallbacks_t *callbacks)
+{
+ dns_name_t *name;
+
+ name = (ictx->glue != NULL) ? ictx->glue : ictx->current;
+ if (dns_name_internalwildcard(name)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ (*callbacks->warn)(callbacks, "%s:%lu: warning: ownername "
+ "'%s' contains an non-terminal wildcard",
+ source, line, namebuf);
+ }
+}
+
+static isc_result_t
+load_text(dns_loadctx_t *lctx) {
+ dns_rdataclass_t rdclass;
+ dns_rdatatype_t type, covers;
+ isc_uint32_t ttl_offset = 0;
+ dns_name_t *new_name;
+ isc_boolean_t current_has_delegation = ISC_FALSE;
+ isc_boolean_t done = ISC_FALSE;
+ isc_boolean_t finish_origin = ISC_FALSE;
+ isc_boolean_t finish_include = ISC_FALSE;
+ isc_boolean_t read_till_eol = ISC_FALSE;
+ isc_boolean_t initialws;
+ char *include_file = NULL;
+ isc_token_t token;
+ isc_result_t result = ISC_R_UNEXPECTED;
+ rdatalist_head_t glue_list;
+ rdatalist_head_t current_list;
+ dns_rdatalist_t *this;
+ dns_rdatalist_t *rdatalist = NULL;
+ dns_rdatalist_t *new_rdatalist;
+ int rdlcount = 0;
+ int rdlcount_save = 0;
+ int rdatalist_size = 0;
+ isc_buffer_t buffer;
+ isc_buffer_t target;
+ isc_buffer_t target_ft;
+ isc_buffer_t target_save;
+ dns_rdata_t *rdata = NULL;
+ dns_rdata_t *new_rdata;
+ int rdcount = 0;
+ int rdcount_save = 0;
+ int rdata_size = 0;
+ unsigned char *target_mem = NULL;
+ int target_size = TSIZ;
+ int new_in_use;
+ unsigned int loop_cnt = 0;
+ isc_mem_t *mctx;
+ dns_rdatacallbacks_t *callbacks;
+ dns_incctx_t *ictx;
+ char *range = NULL;
+ char *lhs = NULL;
+ char *gtype = NULL;
+ char *rhs = NULL;
+ const char *source = "";
+ unsigned long line = 0;
+ isc_boolean_t explicit_ttl;
+ isc_stdtime_t now;
+ char classname1[DNS_RDATACLASS_FORMATSIZE];
+ char classname2[DNS_RDATACLASS_FORMATSIZE];
+ unsigned int options = 0;
+
+ REQUIRE(DNS_LCTX_VALID(lctx));
+ callbacks = lctx->callbacks;
+ mctx = lctx->mctx;
+ ictx = lctx->inc;
+
+ ISC_LIST_INIT(glue_list);
+ ISC_LIST_INIT(current_list);
+
+ isc_stdtime_get(&now);
+
+ /*
+ * Allocate target_size of buffer space. This is greater than twice
+ * the maximum individual RR data size.
+ */
+ target_mem = isc_mem_get(mctx, target_size);
+ if (target_mem == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto log_and_cleanup;
+ }
+ isc_buffer_init(&target, target_mem, target_size);
+ target_save = target;
+
+ if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0)
+ options |= DNS_RDATA_CHECKNAMES;
+ if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0)
+ options |= DNS_RDATA_CHECKNAMESFAIL;
+ if ((lctx->options & DNS_MASTER_CHECKMX) != 0)
+ options |= DNS_RDATA_CHECKMX;
+ if ((lctx->options & DNS_MASTER_CHECKMXFAIL) != 0)
+ options |= DNS_RDATA_CHECKMXFAIL;
+ source = isc_lex_getsourcename(lctx->lex);
+ do {
+ initialws = ISC_FALSE;
+ line = isc_lex_getsourceline(lctx->lex);
+ GETTOKEN(lctx->lex, ISC_LEXOPT_INITIALWS | ISC_LEXOPT_QSTRING,
+ &token, ISC_TRUE);
+ line = isc_lex_getsourceline(lctx->lex);
+
+ if (token.type == isc_tokentype_eof) {
+ if (read_till_eol)
+ WARNUNEXPECTEDEOF(lctx->lex);
+ /* Pop the include stack? */
+ if (ictx->parent != NULL) {
+ COMMITALL;
+ lctx->inc = ictx->parent;
+ ictx->parent = NULL;
+ incctx_destroy(lctx->mctx, ictx);
+ RUNTIME_CHECK(isc_lex_close(lctx->lex) == ISC_R_SUCCESS);
+ line = isc_lex_getsourceline(lctx->lex);
+ source = isc_lex_getsourcename(lctx->lex);
+ ictx = lctx->inc;
+ EXPECTEOL;
+ continue;
+ }
+ done = ISC_TRUE;
+ continue;
+ }
+
+ if (token.type == isc_tokentype_eol) {
+ read_till_eol = ISC_FALSE;
+ continue; /* blank line */
+ }
+
+ if (read_till_eol)
+ continue;
+
+ if (token.type == isc_tokentype_initialws) {
+ /*
+ * Still working on the same name.
+ */
+ initialws = ISC_TRUE;
+ } else if (token.type == isc_tokentype_string ||
+ token.type == isc_tokentype_qstring) {
+
+ /*
+ * "$" Support.
+ *
+ * "$ORIGIN" and "$INCLUDE" can both take domain names.
+ * The processing of "$ORIGIN" and "$INCLUDE" extends
+ * across the normal domain name processing.
+ */
+
+ if (strcasecmp(DNS_AS_STR(token), "$ORIGIN") == 0) {
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+ finish_origin = ISC_TRUE;
+ } else if (strcasecmp(DNS_AS_STR(token),
+ "$TTL") == 0) {
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+ result =
+ dns_ttl_fromtext(&token.value.as_textregion,
+ &lctx->ttl);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ lctx->ttl = 0;
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ limit_ttl(callbacks, source, line, &lctx->ttl);
+ lctx->default_ttl = lctx->ttl;
+ lctx->default_ttl_known = ISC_TRUE;
+ EXPECTEOL;
+ continue;
+ } else if (strcasecmp(DNS_AS_STR(token),
+ "$INCLUDE") == 0) {
+ COMMITALL;
+ if ((lctx->options & DNS_MASTER_NOINCLUDE)
+ != 0)
+ {
+ (callbacks->error)(callbacks,
+ "%s: %s:%lu: $INCLUDE not allowed",
+ "dns_master_load",
+ source, line);
+ result = DNS_R_REFUSED;
+ goto insist_and_cleanup;
+ }
+ if (ttl_offset != 0) {
+ (callbacks->error)(callbacks,
+ "%s: %s:%lu: $INCLUDE "
+ "may not be used with $DATE",
+ "dns_master_load",
+ source, line);
+ result = DNS_R_SYNTAX;
+ goto insist_and_cleanup;
+ }
+ GETTOKEN(lctx->lex, ISC_LEXOPT_QSTRING, &token,
+ ISC_FALSE);
+ if (include_file != NULL)
+ isc_mem_free(mctx, include_file);
+ include_file = isc_mem_strdup(mctx,
+ DNS_AS_STR(token));
+ if (include_file == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto log_and_cleanup;
+ }
+ GETTOKEN(lctx->lex, 0, &token, ISC_TRUE);
+
+ if (token.type == isc_tokentype_eol ||
+ token.type == isc_tokentype_eof) {
+ if (token.type == isc_tokentype_eof)
+ WARNUNEXPECTEDEOF(lctx->lex);
+ isc_lex_ungettoken(lctx->lex, &token);
+ /*
+ * No origin field.
+ */
+ result = pushfile(include_file,
+ ictx->origin, lctx);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ LOGITFILE(result, include_file);
+ continue;
+ } else if (result != ISC_R_SUCCESS) {
+ LOGITFILE(result, include_file);
+ goto insist_and_cleanup;
+ }
+ ictx = lctx->inc;
+ line = isc_lex_getsourceline(lctx->lex);
+ source =
+ isc_lex_getsourcename(lctx->lex);
+ continue;
+ }
+ /*
+ * There is an origin field. Fall through
+ * to domain name processing code and do
+ * the actual inclusion later.
+ */
+ finish_include = ISC_TRUE;
+ } else if (strcasecmp(DNS_AS_STR(token),
+ "$DATE") == 0) {
+ isc_int64_t dump_time64;
+ isc_stdtime_t dump_time, current_time;
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+ isc_stdtime_get(&current_time);
+ result = dns_time64_fromtext(DNS_AS_STR(token),
+ &dump_time64);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ LOGIT(result);
+ dump_time64 = 0;
+ } else if (result != ISC_R_SUCCESS)
+ goto log_and_cleanup;
+ dump_time = (isc_stdtime_t)dump_time64;
+ if (dump_time != dump_time64) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "%s: %s:%lu: $DATE outside epoch",
+ "dns_master_load", source, line);
+ result = ISC_R_UNEXPECTED;
+ goto insist_and_cleanup;
+ }
+ if (dump_time > current_time) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "%s: %s:%lu: "
+ "$DATE in future, using current date",
+ "dns_master_load", source, line);
+ dump_time = current_time;
+ }
+ ttl_offset = current_time - dump_time;
+ EXPECTEOL;
+ continue;
+ } else if (strcasecmp(DNS_AS_STR(token),
+ "$GENERATE") == 0) {
+ /*
+ * Lazy cleanup.
+ */
+ if (range != NULL)
+ isc_mem_free(mctx, range);
+ if (lhs != NULL)
+ isc_mem_free(mctx, lhs);
+ if (gtype != NULL)
+ isc_mem_free(mctx, gtype);
+ if (rhs != NULL)
+ isc_mem_free(mctx, rhs);
+ range = lhs = gtype = rhs = NULL;
+ /* RANGE */
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+ range = isc_mem_strdup(mctx,
+ DNS_AS_STR(token));
+ if (range == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto log_and_cleanup;
+ }
+ /* LHS */
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+ lhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
+ if (lhs == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto log_and_cleanup;
+ }
+ rdclass = 0;
+ explicit_ttl = ISC_FALSE;
+ /* CLASS? */
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+ if (dns_rdataclass_fromtext(&rdclass,
+ &token.value.as_textregion)
+ == ISC_R_SUCCESS) {
+ GETTOKEN(lctx->lex, 0, &token,
+ ISC_FALSE);
+ }
+ /* TTL? */
+ if (dns_ttl_fromtext(&token.value.as_textregion,
+ &lctx->ttl)
+ == ISC_R_SUCCESS) {
+ limit_ttl(callbacks, source, line,
+ &lctx->ttl);
+ lctx->ttl_known = ISC_TRUE;
+ explicit_ttl = ISC_TRUE;
+ GETTOKEN(lctx->lex, 0, &token,
+ ISC_FALSE);
+ }
+ /* CLASS? */
+ if (rdclass == 0 &&
+ dns_rdataclass_fromtext(&rdclass,
+ &token.value.as_textregion)
+ == ISC_R_SUCCESS)
+ GETTOKEN(lctx->lex, 0, &token,
+ ISC_FALSE);
+ /* TYPE */
+ gtype = isc_mem_strdup(mctx,
+ DNS_AS_STR(token));
+ if (gtype == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto log_and_cleanup;
+ }
+ /* RHS */
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+ rhs = isc_mem_strdup(mctx, DNS_AS_STR(token));
+ if (rhs == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto log_and_cleanup;
+ }
+ if (!lctx->ttl_known &&
+ !lctx->default_ttl_known) {
+ (*callbacks->error)(callbacks,
+ "%s: %s:%lu: no TTL specified",
+ "dns_master_load", source, line);
+ result = DNS_R_NOTTL;
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ lctx->ttl = 0;
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ } else if (!explicit_ttl &&
+ lctx->default_ttl_known) {
+ lctx->ttl = lctx->default_ttl;
+ }
+ /*
+ * If the class specified does not match the
+ * zone's class print out a error message and
+ * exit.
+ */
+ if (rdclass != 0 && rdclass != lctx->zclass) {
+ goto bad_class;
+ }
+ result = generate(lctx, range, lhs, gtype, rhs,
+ source, line);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ EXPECTEOL;
+ continue;
+ } else if (strncasecmp(DNS_AS_STR(token),
+ "$", 1) == 0) {
+ (callbacks->error)(callbacks,
+ "%s: %s:%lu: "
+ "unknown $ directive '%s'",
+ "dns_master_load", source, line,
+ DNS_AS_STR(token));
+ result = DNS_R_SYNTAX;
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ }
+
+ /*
+ * Normal processing resumes.
+ *
+ * Find a free name buffer.
+ */
+ for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
+ if (!ictx->in_use[new_in_use])
+ break;
+ INSIST(new_in_use < NBUFS);
+ dns_fixedname_init(&ictx->fixed[new_in_use]);
+ new_name = dns_fixedname_name(&ictx->fixed[new_in_use]);
+ isc_buffer_init(&buffer, token.value.as_region.base,
+ token.value.as_region.length);
+ isc_buffer_add(&buffer, token.value.as_region.length);
+ isc_buffer_setactive(&buffer,
+ token.value.as_region.length);
+ result = dns_name_fromtext(new_name, &buffer,
+ ictx->origin, ISC_FALSE, NULL);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ LOGIT(result);
+ read_till_eol = ISC_TRUE;
+ continue;
+ } else if (result != ISC_R_SUCCESS)
+ goto log_and_cleanup;
+
+ /*
+ * Finish $ORIGIN / $INCLUDE processing if required.
+ */
+ if (finish_origin) {
+ if (ictx->origin_in_use != -1)
+ ictx->in_use[ictx->origin_in_use] =
+ ISC_FALSE;
+ ictx->origin_in_use = new_in_use;
+ ictx->in_use[ictx->origin_in_use] = ISC_TRUE;
+ ictx->origin = new_name;
+ finish_origin = ISC_FALSE;
+ EXPECTEOL;
+ continue;
+ }
+ if (finish_include) {
+ finish_include = ISC_FALSE;
+ result = pushfile(include_file, new_name, lctx);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ LOGITFILE(result, include_file);
+ continue;
+ } else if (result != ISC_R_SUCCESS) {
+ LOGITFILE(result, include_file);
+ goto insist_and_cleanup;
+ }
+ ictx = lctx->inc;
+ line = isc_lex_getsourceline(lctx->lex);
+ source = isc_lex_getsourcename(lctx->lex);
+ continue;
+ }
+
+ /*
+ * "$" Processing Finished
+ */
+
+ /*
+ * If we are processing glue and the new name does
+ * not match the current glue name, commit the glue
+ * and pop stacks leaving us in 'normal' processing
+ * state. Linked lists are undone by commit().
+ */
+ if (ictx->glue != NULL &&
+ dns_name_compare(ictx->glue, new_name) != 0) {
+ result = commit(callbacks, lctx, &glue_list,
+ ictx->glue, source,
+ ictx->glue_line);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ if (ictx->glue_in_use != -1)
+ ictx->in_use[ictx->glue_in_use] =
+ ISC_FALSE;
+ ictx->glue_in_use = -1;
+ ictx->glue = NULL;
+ rdcount = rdcount_save;
+ rdlcount = rdlcount_save;
+ target = target_save;
+ }
+
+ /*
+ * If we are in 'normal' processing state and the new
+ * name does not match the current name, see if the
+ * new name is for glue and treat it as such,
+ * otherwise we have a new name so commit what we
+ * have.
+ */
+ if ((ictx->glue == NULL) && (ictx->current == NULL ||
+ dns_name_compare(ictx->current, new_name) != 0)) {
+ if (current_has_delegation &&
+ is_glue(&current_list, new_name)) {
+ rdcount_save = rdcount;
+ rdlcount_save = rdlcount;
+ target_save = target;
+ ictx->glue = new_name;
+ ictx->glue_in_use = new_in_use;
+ ictx->in_use[ictx->glue_in_use] =
+ ISC_TRUE;
+ } else {
+ result = commit(callbacks, lctx,
+ &current_list,
+ ictx->current,
+ source,
+ ictx->current_line);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ rdcount = 0;
+ rdlcount = 0;
+ if (ictx->current_in_use != -1)
+ ictx->in_use[ictx->current_in_use] =
+ ISC_FALSE;
+ ictx->current_in_use = new_in_use;
+ ictx->in_use[ictx->current_in_use] =
+ ISC_TRUE;
+ ictx->current = new_name;
+ current_has_delegation = ISC_FALSE;
+ isc_buffer_init(&target, target_mem,
+ target_size);
+ }
+ /*
+ * Check for internal wildcards.
+ */
+ if ((lctx->options & DNS_MASTER_CHECKWILDCARD)
+ != 0)
+ check_wildcard(ictx, source, line,
+ callbacks);
+
+ }
+ if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
+ (lctx->options & DNS_MASTER_SLAVE) == 0 &&
+ !dns_name_issubdomain(new_name, lctx->top))
+ {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(new_name, namebuf,
+ sizeof(namebuf));
+ /*
+ * Ignore out-of-zone data.
+ */
+ (*callbacks->warn)(callbacks,
+ "%s:%lu: "
+ "ignoring out-of-zone data (%s)",
+ source, line, namebuf);
+ ictx->drop = ISC_TRUE;
+ } else
+ ictx->drop = ISC_FALSE;
+ } else {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "%s:%lu: isc_lex_gettoken() returned "
+ "unexpected token type (%d)",
+ source, line, token.type);
+ result = ISC_R_UNEXPECTED;
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ LOGIT(result);
+ continue;
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ }
+
+ /*
+ * Find TTL, class and type. Both TTL and class are optional
+ * and may occur in any order if they exist. TTL and class
+ * come before type which must exist.
+ *
+ * [<TTL>] [<class>] <type> <RDATA>
+ * [<class>] [<TTL>] <type> <RDATA>
+ */
+
+ type = 0;
+ rdclass = 0;
+
+ GETTOKEN(lctx->lex, 0, &token, initialws);
+
+ if (initialws) {
+ if (token.type == isc_tokentype_eol) {
+ read_till_eol = ISC_FALSE;
+ continue; /* blank line */
+ }
+
+ if (token.type == isc_tokentype_eof) {
+ WARNUNEXPECTEDEOF(lctx->lex);
+ read_till_eol = ISC_FALSE;
+ isc_lex_ungettoken(lctx->lex, &token);
+ continue;
+ }
+
+ if (ictx->current == NULL) {
+ (*callbacks->error)(callbacks,
+ "%s:%lu: no current owner name",
+ source, line);
+ result = DNS_R_NOOWNER;
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ read_till_eol = ISC_TRUE;
+ continue;
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ }
+ }
+
+ if (dns_rdataclass_fromtext(&rdclass,
+ &token.value.as_textregion)
+ == ISC_R_SUCCESS)
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+
+ explicit_ttl = ISC_FALSE;
+ if (dns_ttl_fromtext(&token.value.as_textregion, &lctx->ttl)
+ == ISC_R_SUCCESS) {
+ limit_ttl(callbacks, source, line, &lctx->ttl);
+ explicit_ttl = ISC_TRUE;
+ lctx->ttl_known = ISC_TRUE;
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+ }
+
+ if (token.type != isc_tokentype_string) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_lex_gettoken() returned unexpected token type");
+ result = ISC_R_UNEXPECTED;
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ read_till_eol = ISC_TRUE;
+ continue;
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ }
+
+ if (rdclass == 0 &&
+ dns_rdataclass_fromtext(&rdclass,
+ &token.value.as_textregion)
+ == ISC_R_SUCCESS)
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+
+ if (token.type != isc_tokentype_string) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_lex_gettoken() returned unexpected token type");
+ result = ISC_R_UNEXPECTED;
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ read_till_eol = ISC_TRUE;
+ continue;
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ }
+
+ result = dns_rdatatype_fromtext(&type,
+ &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS) {
+ (*callbacks->warn)(callbacks,
+ "%s:%lu: unknown RR type '%.*s'",
+ source, line,
+ token.value.as_textregion.length,
+ token.value.as_textregion.base);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ read_till_eol = ISC_TRUE;
+ continue;
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ }
+
+ /*
+ * If the class specified does not match the zone's class
+ * print out a error message and exit.
+ */
+ if (rdclass != 0 && rdclass != lctx->zclass) {
+ bad_class:
+
+ dns_rdataclass_format(rdclass, classname1,
+ sizeof(classname1));
+ dns_rdataclass_format(lctx->zclass, classname2,
+ sizeof(classname2));
+ (*callbacks->error)(callbacks,
+ "%s:%lu: class '%s' != "
+ "zone class '%s'",
+ source, line,
+ classname1, classname2);
+ result = DNS_R_BADCLASS;
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ read_till_eol = ISC_TRUE;
+ continue;
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ }
+
+ if (type == dns_rdatatype_ns && ictx->glue == NULL)
+ current_has_delegation = ISC_TRUE;
+
+ /*
+ * RFC1123: MD and MF are not allowed to be loaded from
+ * master files.
+ */
+ if ((lctx->options & DNS_MASTER_ZONE) != 0 &&
+ (lctx->options & DNS_MASTER_SLAVE) == 0 &&
+ (type == dns_rdatatype_md || type == dns_rdatatype_mf)) {
+ char typename[DNS_RDATATYPE_FORMATSIZE];
+
+ result = DNS_R_OBSOLETE;
+
+ dns_rdatatype_format(type, typename, sizeof(typename));
+ (*callbacks->error)(callbacks,
+ "%s:%lu: %s '%s': %s",
+ source, line,
+ "type", typename,
+ dns_result_totext(result));
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ } else
+ goto insist_and_cleanup;
+ }
+
+ /*
+ * Find a rdata structure.
+ */
+ if (rdcount == rdata_size) {
+ new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
+ rdata_size, &current_list,
+ &glue_list, mctx);
+ if (new_rdata == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto log_and_cleanup;
+ }
+ rdata_size += RDSZ;
+ rdata = new_rdata;
+ }
+
+ /*
+ * Peek at the NS record.
+ */
+ if (type == dns_rdatatype_ns &&
+ lctx->zclass == dns_rdataclass_in &&
+ (lctx->options & DNS_MASTER_CHECKNS) != 0) {
+
+ GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
+ result = check_ns(lctx, &token, source, line);
+ isc_lex_ungettoken(lctx->lex, &token);
+ if ((lctx->options & DNS_MASTER_FATALNS) != 0) {
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ }
+ }
+
+ /*
+ * Check owner name.
+ */
+ options &= ~DNS_RDATA_CHECKREVERSE;
+ if ((lctx->options & DNS_MASTER_CHECKNAMES) != 0) {
+ isc_boolean_t ok;
+ dns_name_t *name;
+
+ name = (ictx->glue != NULL) ? ictx->glue :
+ ictx->current;
+ ok = dns_rdata_checkowner(name, lctx->zclass, type,
+ ISC_TRUE);
+ if (!ok) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ const char *desc;
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ result = DNS_R_BADOWNERNAME;
+ desc = dns_result_totext(result);
+ if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
+ (*callbacks->error)(callbacks,
+ "%s:%lu: %s: %s",
+ source, line,
+ namebuf, desc);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ } else if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ } else {
+ (*callbacks->warn)(callbacks,
+ "%s:%lu: %s: %s",
+ source, line,
+ namebuf, desc);
+ }
+ }
+ if (type == dns_rdatatype_ptr &&
+ (dns_name_issubdomain(name, &in_addr_arpa) ||
+ dns_name_issubdomain(name, &ip6_arpa) ||
+ dns_name_issubdomain(name, &ip6_int)))
+ options |= DNS_RDATA_CHECKREVERSE;
+ }
+
+ /*
+ * Read rdata contents.
+ */
+ dns_rdata_init(&rdata[rdcount]);
+ target_ft = target;
+ result = dns_rdata_fromtext(&rdata[rdcount], lctx->zclass,
+ type, lctx->lex, ictx->origin,
+ options, lctx->mctx, &target,
+ callbacks);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ continue;
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+
+ if (ictx->drop) {
+ target = target_ft;
+ continue;
+ }
+
+ if (type == dns_rdatatype_soa &&
+ (lctx->options & DNS_MASTER_ZONE) != 0 &&
+ dns_name_compare(ictx->current, lctx->top) != 0) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_name_format(ictx->current, namebuf,
+ sizeof(namebuf));
+ (*callbacks->error)(callbacks, "%s:%lu: SOA "
+ "record not at top of zone (%s)",
+ source, line, namebuf);
+ result = DNS_R_NOTZONETOP;
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ read_till_eol = ISC_TRUE;
+ target = target_ft;
+ continue;
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ }
+
+
+ if (type == dns_rdatatype_rrsig ||
+ type == dns_rdatatype_sig)
+ covers = dns_rdata_covers(&rdata[rdcount]);
+ else
+ covers = 0;
+
+ if (!lctx->ttl_known && !lctx->default_ttl_known) {
+ if (type == dns_rdatatype_soa) {
+ (*callbacks->warn)(callbacks,
+ "%s:%lu: no TTL specified; "
+ "using SOA MINTTL instead",
+ source, line);
+ lctx->ttl = dns_soa_getminimum(&rdata[rdcount]);
+ limit_ttl(callbacks, source, line, &lctx->ttl);
+ lctx->default_ttl = lctx->ttl;
+ lctx->default_ttl_known = ISC_TRUE;
+ } else if ((lctx->options & DNS_MASTER_HINT) != 0) {
+ /*
+ * Zero TTL's are fine for hints.
+ */
+ lctx->ttl = 0;
+ lctx->default_ttl = lctx->ttl;
+ lctx->default_ttl_known = ISC_TRUE;
+ } else {
+ (*callbacks->warn)(callbacks,
+ "%s:%lu: no TTL specified; "
+ "zone rejected",
+ source, line);
+ result = DNS_R_NOTTL;
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ lctx->ttl = 0;
+ } else {
+ goto insist_and_cleanup;
+ }
+ }
+ } else if (!explicit_ttl && lctx->default_ttl_known) {
+ lctx->ttl = lctx->default_ttl;
+ } else if (!explicit_ttl && lctx->warn_1035) {
+ (*callbacks->warn)(callbacks,
+ "%s:%lu: "
+ "using RFC1035 TTL semantics",
+ source, line);
+ lctx->warn_1035 = ISC_FALSE;
+ }
+
+ if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
+ dns_rdata_rrsig_t sig;
+ result = dns_rdata_tostruct(&rdata[rdcount], &sig,
+ NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (isc_serial_lt(sig.timeexpire, now)) {
+ (*callbacks->warn)(callbacks,
+ "%s:%lu: "
+ "signature has expired",
+ source, line);
+ lctx->warn_sigexpired = ISC_FALSE;
+ }
+ }
+
+ if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
+ lctx->warn_tcr && (lctx->options & DNS_MASTER_ZONE) != 0 &&
+ (lctx->options & DNS_MASTER_SLAVE) == 0) {
+ (*callbacks->warn)(callbacks, "%s:%lu: old style DNSSEC "
+ " zone detected", source, line);
+ lctx->warn_tcr = ISC_FALSE;
+ }
+
+ if ((lctx->options & DNS_MASTER_AGETTL) != 0) {
+ /*
+ * Adjust the TTL for $DATE. If the RR has already
+ * expired, ignore it.
+ */
+ if (lctx->ttl < ttl_offset)
+ continue;
+ lctx->ttl -= ttl_offset;
+ }
+
+ /*
+ * Find type in rdatalist.
+ * If it does not exist create new one and prepend to list
+ * as this will mimimise list traversal.
+ */
+ if (ictx->glue != NULL)
+ this = ISC_LIST_HEAD(glue_list);
+ else
+ this = ISC_LIST_HEAD(current_list);
+
+ while (this != NULL) {
+ if (this->type == type && this->covers == covers)
+ break;
+ this = ISC_LIST_NEXT(this, link);
+ }
+
+ if (this == NULL) {
+ if (rdlcount == rdatalist_size) {
+ new_rdatalist =
+ grow_rdatalist(rdatalist_size + RDLSZ,
+ rdatalist,
+ rdatalist_size,
+ &current_list,
+ &glue_list,
+ mctx);
+ if (new_rdatalist == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto log_and_cleanup;
+ }
+ rdatalist = new_rdatalist;
+ rdatalist_size += RDLSZ;
+ }
+ this = &rdatalist[rdlcount++];
+ this->type = type;
+ this->covers = covers;
+ this->rdclass = lctx->zclass;
+ this->ttl = lctx->ttl;
+ ISC_LIST_INIT(this->rdata);
+ if (ictx->glue != NULL)
+ ISC_LIST_INITANDPREPEND(glue_list, this, link);
+ else
+ ISC_LIST_INITANDPREPEND(current_list, this,
+ link);
+ } else if (this->ttl != lctx->ttl) {
+ (*callbacks->warn)(callbacks,
+ "%s:%lu: "
+ "TTL set to prior TTL (%lu)",
+ source, line, this->ttl);
+ lctx->ttl = this->ttl;
+ }
+
+ ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
+ if (ictx->glue != NULL)
+ ictx->glue_line = line;
+ else
+ ictx->current_line = line;
+ rdcount++;
+
+ /*
+ * We must have at least 64k as rdlen is 16 bits.
+ * If we don't commit everything we have so far.
+ */
+ if ((target.length - target.used) < MINTSIZ)
+ COMMITALL;
+ next_line:
+ ;
+ } while (!done && (lctx->loop_cnt == 0 || loop_cnt++ < lctx->loop_cnt));
+
+ /*
+ * Commit what has not yet been committed.
+ */
+ result = commit(callbacks, lctx, &current_list, ictx->current,
+ source, ictx->current_line);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+ result = commit(callbacks, lctx, &glue_list, ictx->glue,
+ source, ictx->glue_line);
+ if (MANYERRS(lctx, result)) {
+ SETRESULT(lctx, result);
+ } else if (result != ISC_R_SUCCESS)
+ goto insist_and_cleanup;
+
+ if (!done) {
+ INSIST(lctx->done != NULL && lctx->task != NULL);
+ result = DNS_R_CONTINUE;
+ } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS) {
+ result = lctx->result;
+ } else if (result == ISC_R_SUCCESS && lctx->seen_include)
+ result = DNS_R_SEENINCLUDE;
+ goto cleanup;
+
+ log_and_cleanup:
+ LOGIT(result);
+
+ insist_and_cleanup:
+ INSIST(result != ISC_R_SUCCESS);
+
+ cleanup:
+ while ((this = ISC_LIST_HEAD(current_list)) != NULL)
+ ISC_LIST_UNLINK(current_list, this, link);
+ while ((this = ISC_LIST_HEAD(glue_list)) != NULL)
+ ISC_LIST_UNLINK(glue_list, this, link);
+ if (rdatalist != NULL)
+ isc_mem_put(mctx, rdatalist,
+ rdatalist_size * sizeof(*rdatalist));
+ if (rdata != NULL)
+ isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
+ if (target_mem != NULL)
+ isc_mem_put(mctx, target_mem, target_size);
+ if (include_file != NULL)
+ isc_mem_free(mctx, include_file);
+ if (range != NULL)
+ isc_mem_free(mctx, range);
+ if (lhs != NULL)
+ isc_mem_free(mctx, lhs);
+ if (gtype != NULL)
+ isc_mem_free(mctx, gtype);
+ if (rhs != NULL)
+ isc_mem_free(mctx, rhs);
+ return (result);
+}
+
+static isc_result_t
+pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) {
+ isc_result_t result;
+ dns_incctx_t *ictx;
+ dns_incctx_t *new = NULL;
+ isc_region_t r;
+ int new_in_use;
+
+ REQUIRE(master_file != NULL);
+ REQUIRE(DNS_LCTX_VALID(lctx));
+
+ ictx = lctx->inc;
+ lctx->seen_include = ISC_TRUE;
+
+ result = incctx_create(lctx->mctx, origin, &new);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /* Set current domain. */
+ if (ictx->glue != NULL || ictx->current != NULL) {
+ for (new_in_use = 0; new_in_use < NBUFS; new_in_use++)
+ if (!new->in_use[new_in_use])
+ break;
+ INSIST(new_in_use < NBUFS);
+ new->current_in_use = new_in_use;
+ new->current =
+ dns_fixedname_name(&new->fixed[new->current_in_use]);
+ new->in_use[new->current_in_use] = ISC_TRUE;
+ dns_name_toregion((ictx->glue != NULL) ?
+ ictx->glue : ictx->current, &r);
+ dns_name_fromregion(new->current, &r);
+ new->drop = ictx->drop;
+ }
+
+ result = (lctx->openfile)(lctx, master_file);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ new->parent = ictx;
+ lctx->inc = new;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (new != NULL)
+ incctx_destroy(lctx->mctx, new);
+ return (result);
+}
+
+static inline isc_result_t
+read_and_check(isc_boolean_t do_read, isc_buffer_t *buffer,
+ size_t len, FILE *f)
+{
+ isc_result_t result;
+
+ if (do_read) {
+ INSIST(isc_buffer_availablelength(buffer) >= len);
+ result = isc_stdio_read(isc_buffer_used(buffer), 1, len,
+ f, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_add(buffer, len);
+ } else if (isc_buffer_remaininglength(buffer) < len)
+ return (ISC_R_RANGE);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+load_raw(dns_loadctx_t *lctx) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t done = ISC_FALSE;
+ unsigned int loop_cnt = 0;
+ dns_rdatacallbacks_t *callbacks;
+ unsigned char namebuf[DNS_NAME_MAXWIRE];
+ isc_region_t r;
+ dns_name_t name;
+ rdatalist_head_t head, dummy;
+ dns_rdatalist_t rdatalist;
+ isc_mem_t *mctx = lctx->mctx;
+ dns_rdata_t *rdata = NULL;
+ unsigned int rdata_size = 0;
+ int target_size = TSIZ;
+ isc_buffer_t target;
+ unsigned char *target_mem = NULL;
+
+ REQUIRE(DNS_LCTX_VALID(lctx));
+ callbacks = lctx->callbacks;
+
+ if (lctx->first) {
+ dns_masterrawheader_t header;
+ isc_uint32_t format, version, dumptime;
+ size_t hdrlen = sizeof(format) + sizeof(version) +
+ sizeof(dumptime);
+
+ INSIST(hdrlen <= sizeof(header));
+ isc_buffer_init(&target, &header, sizeof(header));
+
+ result = isc_stdio_read(&header, 1, hdrlen, lctx->f, NULL);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_stdio_read failed: %s",
+ isc_result_totext(result));
+ return (result);
+ }
+ isc_buffer_add(&target, hdrlen);
+ format = isc_buffer_getuint32(&target);
+ if (format != dns_masterformat_raw) {
+ (*callbacks->error)(callbacks,
+ "dns_master_load: "
+ "file format mismatch");
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ version = isc_buffer_getuint32(&target);
+ if (version > DNS_RAWFORMAT_VERSION) {
+ (*callbacks->error)(callbacks,
+ "dns_master_load: "
+ "unsupported file format version");
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ /* Empty read: currently, we do not use dumptime */
+ dumptime = isc_buffer_getuint32(&target);
+
+ lctx->first = ISC_FALSE;
+ }
+
+ ISC_LIST_INIT(head);
+ ISC_LIST_INIT(dummy);
+ dns_rdatalist_init(&rdatalist);
+
+ /*
+ * Allocate target_size of buffer space. This is greater than twice
+ * the maximum individual RR data size.
+ */
+ target_mem = isc_mem_get(mctx, target_size);
+ if (target_mem == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ isc_buffer_init(&target, target_mem, target_size);
+
+ /*
+ * In the following loop, we regard any error fatal regardless of
+ * whether "MANYERRORS" is set in the context option. This is because
+ * normal errors should already have been checked at creation time.
+ * Besides, it is very unlikely that we can recover from an error
+ * in this format, and so trying to continue parsing erroneous data
+ * does not really make sense.
+ */
+ for (loop_cnt = 0;
+ (lctx->loop_cnt == 0 || loop_cnt < lctx->loop_cnt);
+ loop_cnt++) {
+ unsigned int i, rdcount, consumed_name;
+ isc_uint16_t namelen;
+ isc_uint32_t totallen;
+ size_t minlen, readlen;
+ isc_boolean_t sequential_read = ISC_FALSE;
+
+ /* Read the data length */
+ isc_buffer_clear(&target);
+ INSIST(isc_buffer_availablelength(&target) >=
+ sizeof(totallen));
+ result = isc_stdio_read(target.base, 1, sizeof(totallen),
+ lctx->f, NULL);
+ if (result == ISC_R_EOF) {
+ result = ISC_R_SUCCESS;
+ done = ISC_TRUE;
+ break;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_buffer_add(&target, sizeof(totallen));
+ totallen = isc_buffer_getuint32(&target);
+ /*
+ * Validation: the input data must at least contain the common
+ * header.
+ */
+ minlen = sizeof(totallen) + sizeof(isc_uint16_t) +
+ sizeof(isc_uint16_t) + sizeof(isc_uint16_t) +
+ sizeof(isc_uint32_t) + sizeof(isc_uint32_t);
+ if (totallen < minlen) {
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ totallen -= sizeof(totallen);
+
+ isc_buffer_clear(&target);
+ if (totallen > isc_buffer_availablelength(&target)) {
+ /*
+ * The default buffer size should typically be large
+ * enough to store the entire RRset. We could try to
+ * allocate enough space if this is not the case, but
+ * it might cause a hazardous result when "totallen"
+ * is forged. Thus, we'd rather take an inefficient
+ * but robust approach in this atypical case: read
+ * data step by step, and commit partial data when
+ * necessary. Note that the buffer must be large
+ * enough to store the "header part", owner name, and
+ * at least one rdata (however large it is).
+ */
+ sequential_read = ISC_TRUE;
+ readlen = minlen - sizeof(totallen);
+ } else {
+ /*
+ * Typical case. We can read the whole RRset at once
+ * with the default buffer.
+ */
+ readlen = totallen;
+ }
+ result = isc_stdio_read(target.base, 1, readlen,
+ lctx->f, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_buffer_add(&target, readlen);
+
+ /* Construct RRset headers */
+ rdatalist.rdclass = isc_buffer_getuint16(&target);
+ rdatalist.type = isc_buffer_getuint16(&target);
+ rdatalist.covers = isc_buffer_getuint16(&target);
+ rdatalist.ttl = isc_buffer_getuint32(&target);
+ rdcount = isc_buffer_getuint32(&target);
+ if (rdcount == 0) {
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ INSIST(isc_buffer_consumedlength(&target) <= readlen);
+
+ /* Owner name: length followed by name */
+ result = read_and_check(sequential_read, &target,
+ sizeof(namelen), lctx->f);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ namelen = isc_buffer_getuint16(&target);
+ if (namelen > sizeof(namebuf)) {
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+
+ result = read_and_check(sequential_read, &target, namelen,
+ lctx->f);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_buffer_setactive(&target, (unsigned int)namelen);
+ isc_buffer_activeregion(&target, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ isc_buffer_forward(&target, (unsigned int)namelen);
+ consumed_name = isc_buffer_consumedlength(&target);
+
+ /* Rdata contents. */
+ if (rdcount > rdata_size) {
+ dns_rdata_t *new_rdata = NULL;
+
+ new_rdata = grow_rdata(rdata_size + RDSZ, rdata,
+ rdata_size, &head,
+ &dummy, mctx);
+ if (new_rdata == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ rdata_size += RDSZ;
+ rdata = new_rdata;
+ }
+
+ continue_read:
+ for (i = 0; i < rdcount; i++) {
+ isc_uint16_t rdlen;
+
+ dns_rdata_init(&rdata[i]);
+
+ if (sequential_read &&
+ isc_buffer_availablelength(&target) < MINTSIZ) {
+ unsigned int j;
+
+ INSIST(i > 0); /* detect an infinite loop */
+
+ /* Partial Commit. */
+ ISC_LIST_APPEND(head, &rdatalist, link);
+ result = commit(callbacks, lctx, &head, &name,
+ NULL, 0);
+ for (j = 0; j < i; j++) {
+ ISC_LIST_UNLINK(rdatalist.rdata,
+ &rdata[j], link);
+ dns_rdata_reset(&rdata[j]);
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Rewind the buffer and continue */
+ isc_buffer_clear(&target);
+ isc_buffer_add(&target, consumed_name);
+ isc_buffer_forward(&target, consumed_name);
+
+ rdcount -= i;
+ i = 0;
+
+ goto continue_read;
+ }
+
+ /* rdata length */
+ result = read_and_check(sequential_read, &target,
+ sizeof(rdlen), lctx->f);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ rdlen = isc_buffer_getuint16(&target);
+
+ /* rdata */
+ result = read_and_check(sequential_read, &target,
+ rdlen, lctx->f);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_buffer_setactive(&target, (unsigned int)rdlen);
+ isc_buffer_activeregion(&target, &r);
+ isc_buffer_forward(&target, (unsigned int)rdlen);
+ dns_rdata_fromregion(&rdata[i], rdatalist.rdclass,
+ rdatalist.type, &r);
+
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata[i], link);
+ }
+
+ /*
+ * Sanity check. Still having remaining space is not
+ * necessarily critical, but it very likely indicates broken
+ * or malformed data.
+ */
+ if (isc_buffer_remaininglength(&target) != 0) {
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+
+ ISC_LIST_APPEND(head, &rdatalist, link);
+
+ /* Commit this RRset. rdatalist will be unlinked. */
+ result = commit(callbacks, lctx, &head, &name, NULL, 0);
+
+ for (i = 0; i < rdcount; i++) {
+ ISC_LIST_UNLINK(rdatalist.rdata, &rdata[i], link);
+ dns_rdata_reset(&rdata[i]);
+ }
+
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ if (!done) {
+ INSIST(lctx->done != NULL && lctx->task != NULL);
+ result = DNS_R_CONTINUE;
+ } else if (result == ISC_R_SUCCESS && lctx->result != ISC_R_SUCCESS)
+ result = lctx->result;
+
+ cleanup:
+ if (rdata != NULL)
+ isc_mem_put(mctx, rdata, rdata_size * sizeof(*rdata));
+ if (target_mem != NULL)
+ isc_mem_put(mctx, target_mem, target_size);
+ if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE) {
+ (*callbacks->error)(callbacks, "dns_master_load: %s",
+ dns_result_totext(result));
+ }
+
+ return (result);
+}
+
+isc_result_t
+dns_master_loadfile(const char *master_file, dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass, unsigned int options,
+ dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
+{
+ return (dns_master_loadfile3(master_file, top, origin, zclass, options,
+ 0, callbacks, mctx, dns_masterformat_text));
+}
+
+isc_result_t
+dns_master_loadfile2(const char *master_file, dns_name_t *top,
+ dns_name_t *origin,
+ dns_rdataclass_t zclass, unsigned int options,
+ dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
+ dns_masterformat_t format)
+{
+ return (dns_master_loadfile3(master_file, top, origin, zclass, options,
+ 0, callbacks, mctx, format));
+}
+
+isc_result_t
+dns_master_loadfile3(const char *master_file, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options, isc_uint32_t resign,
+ dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx,
+ dns_masterformat_t format)
+{
+ dns_loadctx_t *lctx = NULL;
+ isc_result_t result;
+
+ result = loadctx_create(format, mctx, options, resign, top, zclass,
+ origin, callbacks, NULL, NULL, NULL, NULL,
+ &lctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = (lctx->openfile)(lctx, master_file);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = (lctx->load)(lctx);
+ INSIST(result != DNS_R_CONTINUE);
+
+ cleanup:
+ dns_loadctx_detach(&lctx);
+ return (result);
+}
+
+isc_result_t
+dns_master_loadfileinc(const char *master_file, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options, dns_rdatacallbacks_t *callbacks,
+ isc_task_t *task, dns_loaddonefunc_t done,
+ void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx)
+{
+ return (dns_master_loadfileinc3(master_file, top, origin, zclass,
+ options, 0, callbacks, task, done,
+ done_arg, lctxp, mctx,
+ dns_masterformat_text));
+}
+
+isc_result_t
+dns_master_loadfileinc2(const char *master_file, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options, dns_rdatacallbacks_t *callbacks,
+ isc_task_t *task, dns_loaddonefunc_t done,
+ void *done_arg, dns_loadctx_t **lctxp, isc_mem_t *mctx,
+ dns_masterformat_t format)
+{
+ return (dns_master_loadfileinc3(master_file, top, origin, zclass,
+ options, 0, callbacks, task, done,
+ done_arg, lctxp, mctx, format));
+}
+
+isc_result_t
+dns_master_loadfileinc3(const char *master_file, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options, isc_uint32_t resign,
+ dns_rdatacallbacks_t *callbacks, isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **lctxp, isc_mem_t *mctx,
+ dns_masterformat_t format)
+{
+ dns_loadctx_t *lctx = NULL;
+ isc_result_t result;
+
+ REQUIRE(task != NULL);
+ REQUIRE(done != NULL);
+
+ result = loadctx_create(format, mctx, options, resign, top, zclass,
+ origin, callbacks, task, done, done_arg, NULL,
+ &lctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = (lctx->openfile)(lctx, master_file);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = task_send(lctx);
+ if (result == ISC_R_SUCCESS) {
+ dns_loadctx_attach(lctx, lctxp);
+ return (DNS_R_CONTINUE);
+ }
+
+ cleanup:
+ dns_loadctx_detach(&lctx);
+ return (result);
+}
+
+isc_result_t
+dns_master_loadstream(FILE *stream, dns_name_t *top, dns_name_t *origin,
+ dns_rdataclass_t zclass, unsigned int options,
+ dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_loadctx_t *lctx = NULL;
+
+ REQUIRE(stream != NULL);
+
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
+ zclass, origin, callbacks, NULL, NULL, NULL,
+ NULL, &lctx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = isc_lex_openstream(lctx->lex, stream);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = (lctx->load)(lctx);
+ INSIST(result != DNS_R_CONTINUE);
+
+ cleanup:
+ if (lctx != NULL)
+ dns_loadctx_detach(&lctx);
+ return (result);
+}
+
+isc_result_t
+dns_master_loadstreaminc(FILE *stream, dns_name_t *top, dns_name_t *origin,
+ dns_rdataclass_t zclass, unsigned int options,
+ dns_rdatacallbacks_t *callbacks, isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **lctxp, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_loadctx_t *lctx = NULL;
+
+ REQUIRE(stream != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(done != NULL);
+
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
+ zclass, origin, callbacks, task, done,
+ done_arg, NULL, &lctx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = isc_lex_openstream(lctx->lex, stream);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = task_send(lctx);
+ if (result == ISC_R_SUCCESS) {
+ dns_loadctx_attach(lctx, lctxp);
+ return (DNS_R_CONTINUE);
+ }
+
+ cleanup:
+ if (lctx != NULL)
+ dns_loadctx_detach(&lctx);
+ return (result);
+}
+
+isc_result_t
+dns_master_loadbuffer(isc_buffer_t *buffer, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_loadctx_t *lctx = NULL;
+
+ REQUIRE(buffer != NULL);
+
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
+ zclass, origin, callbacks, NULL, NULL, NULL,
+ NULL, &lctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = isc_lex_openbuffer(lctx->lex, buffer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = (lctx->load)(lctx);
+ INSIST(result != DNS_R_CONTINUE);
+
+ cleanup:
+ dns_loadctx_detach(&lctx);
+ return (result);
+}
+
+isc_result_t
+dns_master_loadbufferinc(isc_buffer_t *buffer, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks, isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **lctxp, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_loadctx_t *lctx = NULL;
+
+ REQUIRE(buffer != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(done != NULL);
+
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
+ zclass, origin, callbacks, task, done,
+ done_arg, NULL, &lctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = isc_lex_openbuffer(lctx->lex, buffer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = task_send(lctx);
+ if (result == ISC_R_SUCCESS) {
+ dns_loadctx_attach(lctx, lctxp);
+ return (DNS_R_CONTINUE);
+ }
+
+ cleanup:
+ dns_loadctx_detach(&lctx);
+ return (result);
+}
+
+isc_result_t
+dns_master_loadlexer(isc_lex_t *lex, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_loadctx_t *lctx = NULL;
+
+ REQUIRE(lex != NULL);
+
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
+ zclass, origin, callbacks, NULL, NULL, NULL,
+ lex, &lctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = (lctx->load)(lctx);
+ INSIST(result != DNS_R_CONTINUE);
+
+ dns_loadctx_detach(&lctx);
+ return (result);
+}
+
+isc_result_t
+dns_master_loadlexerinc(isc_lex_t *lex, dns_name_t *top,
+ dns_name_t *origin, dns_rdataclass_t zclass,
+ unsigned int options,
+ dns_rdatacallbacks_t *callbacks, isc_task_t *task,
+ dns_loaddonefunc_t done, void *done_arg,
+ dns_loadctx_t **lctxp, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_loadctx_t *lctx = NULL;
+
+ REQUIRE(lex != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(done != NULL);
+
+ result = loadctx_create(dns_masterformat_text, mctx, options, 0, top,
+ zclass, origin, callbacks, task, done,
+ done_arg, lex, &lctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = task_send(lctx);
+ if (result == ISC_R_SUCCESS) {
+ dns_loadctx_attach(lctx, lctxp);
+ return (DNS_R_CONTINUE);
+ }
+
+ dns_loadctx_detach(&lctx);
+ return (result);
+}
+
+/*
+ * Grow the slab of dns_rdatalist_t structures.
+ * Re-link glue and current list.
+ */
+static dns_rdatalist_t *
+grow_rdatalist(int new_len, dns_rdatalist_t *old, int old_len,
+ rdatalist_head_t *current, rdatalist_head_t *glue,
+ isc_mem_t *mctx)
+{
+ dns_rdatalist_t *new;
+ int rdlcount = 0;
+ ISC_LIST(dns_rdatalist_t) save;
+ dns_rdatalist_t *this;
+
+ new = isc_mem_get(mctx, new_len * sizeof(*new));
+ if (new == NULL)
+ return (NULL);
+
+ ISC_LIST_INIT(save);
+ this = ISC_LIST_HEAD(*current);
+ while ((this = ISC_LIST_HEAD(*current)) != NULL) {
+ ISC_LIST_UNLINK(*current, this, link);
+ ISC_LIST_APPEND(save, this, link);
+ }
+ while ((this = ISC_LIST_HEAD(save)) != NULL) {
+ ISC_LIST_UNLINK(save, this, link);
+ new[rdlcount] = *this;
+ ISC_LIST_APPEND(*current, &new[rdlcount], link);
+ rdlcount++;
+ }
+
+ ISC_LIST_INIT(save);
+ this = ISC_LIST_HEAD(*glue);
+ while ((this = ISC_LIST_HEAD(*glue)) != NULL) {
+ ISC_LIST_UNLINK(*glue, this, link);
+ ISC_LIST_APPEND(save, this, link);
+ }
+ while ((this = ISC_LIST_HEAD(save)) != NULL) {
+ ISC_LIST_UNLINK(save, this, link);
+ new[rdlcount] = *this;
+ ISC_LIST_APPEND(*glue, &new[rdlcount], link);
+ rdlcount++;
+ }
+
+ INSIST(rdlcount == old_len);
+ if (old != NULL)
+ isc_mem_put(mctx, old, old_len * sizeof(*old));
+ return (new);
+}
+
+/*
+ * Grow the slab of rdata structs.
+ * Re-link the current and glue chains.
+ */
+static dns_rdata_t *
+grow_rdata(int new_len, dns_rdata_t *old, int old_len,
+ rdatalist_head_t *current, rdatalist_head_t *glue,
+ isc_mem_t *mctx)
+{
+ dns_rdata_t *new;
+ int rdcount = 0;
+ ISC_LIST(dns_rdata_t) save;
+ dns_rdatalist_t *this;
+ dns_rdata_t *rdata;
+
+ new = isc_mem_get(mctx, new_len * sizeof(*new));
+ if (new == NULL)
+ return (NULL);
+ memset(new, 0, new_len * sizeof(*new));
+
+ /*
+ * Copy current relinking.
+ */
+ this = ISC_LIST_HEAD(*current);
+ while (this != NULL) {
+ ISC_LIST_INIT(save);
+ while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
+ ISC_LIST_UNLINK(this->rdata, rdata, link);
+ ISC_LIST_APPEND(save, rdata, link);
+ }
+ while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
+ ISC_LIST_UNLINK(save, rdata, link);
+ new[rdcount] = *rdata;
+ ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
+ rdcount++;
+ }
+ this = ISC_LIST_NEXT(this, link);
+ }
+
+ /*
+ * Copy glue relinking.
+ */
+ this = ISC_LIST_HEAD(*glue);
+ while (this != NULL) {
+ ISC_LIST_INIT(save);
+ while ((rdata = ISC_LIST_HEAD(this->rdata)) != NULL) {
+ ISC_LIST_UNLINK(this->rdata, rdata, link);
+ ISC_LIST_APPEND(save, rdata, link);
+ }
+ while ((rdata = ISC_LIST_HEAD(save)) != NULL) {
+ ISC_LIST_UNLINK(save, rdata, link);
+ new[rdcount] = *rdata;
+ ISC_LIST_APPEND(this->rdata, &new[rdcount], link);
+ rdcount++;
+ }
+ this = ISC_LIST_NEXT(this, link);
+ }
+ INSIST(rdcount == old_len);
+ if (old != NULL)
+ isc_mem_put(mctx, old, old_len * sizeof(*old));
+ return (new);
+}
+
+static isc_uint32_t
+resign_fromlist(dns_rdatalist_t *this, isc_uint32_t resign) {
+ dns_rdata_t *rdata;
+ dns_rdata_rrsig_t sig;
+ isc_uint32_t when;
+
+ rdata = ISC_LIST_HEAD(this->rdata);
+ INSIST(rdata != NULL);
+ (void)dns_rdata_tostruct(rdata, &sig, NULL);
+ when = sig.timeexpire - resign;
+
+ rdata = ISC_LIST_NEXT(rdata, link);
+ while (rdata != NULL) {
+ (void)dns_rdata_tostruct(rdata, &sig, NULL);
+ if (sig.timeexpire - resign < when)
+ when = sig.timeexpire - resign;
+ rdata = ISC_LIST_NEXT(rdata, link);
+ }
+ return (when);
+}
+
+/*
+ * Convert each element from a rdatalist_t to rdataset then call commit.
+ * Unlink each element as we go.
+ */
+
+static isc_result_t
+commit(dns_rdatacallbacks_t *callbacks, dns_loadctx_t *lctx,
+ rdatalist_head_t *head, dns_name_t *owner,
+ const char *source, unsigned int line)
+{
+ dns_rdatalist_t *this;
+ dns_rdataset_t dataset;
+ isc_result_t result;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ void (*error)(struct dns_rdatacallbacks *, const char *, ...);
+
+ this = ISC_LIST_HEAD(*head);
+ error = callbacks->error;
+
+ if (this == NULL)
+ return (ISC_R_SUCCESS);
+ do {
+ dns_rdataset_init(&dataset);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(this, &dataset)
+ == ISC_R_SUCCESS);
+ dataset.trust = dns_trust_ultimate;
+ /*
+ * If this is a secure dynamic zone set the re-signing time.
+ */
+ if (dataset.type == dns_rdatatype_rrsig &&
+ (lctx->options & DNS_MASTER_RESIGN) != 0) {
+ dataset.attributes |= DNS_RDATASETATTR_RESIGN;
+ dns_name_format(owner, namebuf, sizeof(namebuf));
+ dataset.resign = resign_fromlist(this, lctx->resign);
+ }
+ result = ((*callbacks->add)(callbacks->add_private, owner,
+ &dataset));
+ if (result == ISC_R_NOMEMORY) {
+ (*error)(callbacks, "dns_master_load: %s",
+ dns_result_totext(result));
+ } else if (result != ISC_R_SUCCESS) {
+ dns_name_format(owner, namebuf, sizeof(namebuf));
+ if (source != NULL) {
+ (*error)(callbacks, "%s: %s:%lu: %s: %s",
+ "dns_master_load", source, line,
+ namebuf, dns_result_totext(result));
+ } else {
+ (*error)(callbacks, "%s: %s: %s",
+ "dns_master_load", namebuf,
+ dns_result_totext(result));
+ }
+ }
+ if (MANYERRS(lctx, result))
+ SETRESULT(lctx, result);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ ISC_LIST_UNLINK(*head, this, link);
+ this = ISC_LIST_HEAD(*head);
+ } while (this != NULL);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Returns ISC_TRUE if one of the NS rdata's contains 'owner'.
+ */
+
+static isc_boolean_t
+is_glue(rdatalist_head_t *head, dns_name_t *owner) {
+ dns_rdatalist_t *this;
+ dns_rdata_t *rdata;
+ isc_region_t region;
+ dns_name_t name;
+
+ /*
+ * Find NS rrset.
+ */
+ this = ISC_LIST_HEAD(*head);
+ while (this != NULL) {
+ if (this->type == dns_rdatatype_ns)
+ break;
+ this = ISC_LIST_NEXT(this, link);
+ }
+ if (this == NULL)
+ return (ISC_FALSE);
+
+ rdata = ISC_LIST_HEAD(this->rdata);
+ while (rdata != NULL) {
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ if (dns_name_compare(&name, owner) == 0)
+ return (ISC_TRUE);
+ rdata = ISC_LIST_NEXT(rdata, link);
+ }
+ return (ISC_FALSE);
+}
+
+static void
+load_quantum(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ dns_loadctx_t *lctx;
+
+ REQUIRE(event != NULL);
+ lctx = event->ev_arg;
+ REQUIRE(DNS_LCTX_VALID(lctx));
+
+ if (lctx->canceled)
+ result = ISC_R_CANCELED;
+ else
+ result = (lctx->load)(lctx);
+ if (result == DNS_R_CONTINUE) {
+ event->ev_arg = lctx;
+ isc_task_send(task, &event);
+ } else {
+ (lctx->done)(lctx->done_arg, result);
+ isc_event_free(&event);
+ dns_loadctx_detach(&lctx);
+ }
+}
+
+static isc_result_t
+task_send(dns_loadctx_t *lctx) {
+ isc_event_t *event;
+
+ event = isc_event_allocate(lctx->mctx, NULL,
+ DNS_EVENT_MASTERQUANTUM,
+ load_quantum, lctx, sizeof(*event));
+ if (event == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_task_send(lctx->task, &event);
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_loadctx_cancel(dns_loadctx_t *lctx) {
+ REQUIRE(DNS_LCTX_VALID(lctx));
+
+ LOCK(&lctx->lock);
+ lctx->canceled = ISC_TRUE;
+ UNLOCK(&lctx->lock);
+}
diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c
new file mode 100644
index 0000000..3d46458
--- /dev/null
+++ b/lib/dns/masterdump.c
@@ -0,0 +1,1754 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: masterdump.c,v 1.94 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/event.h>
+#include <isc/file.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/lib.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/time.h>
+#include <dns/ttl.h>
+
+#define DNS_DCTX_MAGIC ISC_MAGIC('D', 'c', 't', 'x')
+#define DNS_DCTX_VALID(d) ISC_MAGIC_VALID(d, DNS_DCTX_MAGIC)
+
+#define RETERR(x) do { \
+ isc_result_t _r = (x); \
+ if (_r != ISC_R_SUCCESS) \
+ return (_r); \
+ } while (0)
+
+struct dns_master_style {
+ unsigned int flags; /* DNS_STYLEFLAG_* */
+ unsigned int ttl_column;
+ unsigned int class_column;
+ unsigned int type_column;
+ unsigned int rdata_column;
+ unsigned int line_length;
+ unsigned int tab_width;
+};
+
+/*%
+ * The maximum length of the newline+indentation that is output
+ * when inserting a line break in an RR. This effectively puts an
+ * upper limits on the value of "rdata_column", because if it is
+ * very large, the tabs and spaces needed to reach it will not fit.
+ */
+#define DNS_TOTEXT_LINEBREAK_MAXLEN 100
+
+/*%
+ * Context structure for a masterfile dump in progress.
+ */
+typedef struct dns_totext_ctx {
+ dns_master_style_t style;
+ isc_boolean_t class_printed;
+ char * linebreak;
+ char linebreak_buf[DNS_TOTEXT_LINEBREAK_MAXLEN];
+ dns_name_t * origin;
+ dns_name_t * neworigin;
+ dns_fixedname_t origin_fixname;
+ isc_uint32_t current_ttl;
+ isc_boolean_t current_ttl_valid;
+} dns_totext_ctx_t;
+
+LIBDNS_EXTERNAL_DATA const dns_master_style_t
+dns_master_style_default = {
+ DNS_STYLEFLAG_OMIT_OWNER |
+ DNS_STYLEFLAG_OMIT_CLASS |
+ DNS_STYLEFLAG_REL_OWNER |
+ DNS_STYLEFLAG_REL_DATA |
+ DNS_STYLEFLAG_OMIT_TTL |
+ DNS_STYLEFLAG_TTL |
+ DNS_STYLEFLAG_COMMENT |
+ DNS_STYLEFLAG_MULTILINE,
+ 24, 24, 24, 32, 80, 8
+};
+
+LIBDNS_EXTERNAL_DATA const dns_master_style_t
+dns_master_style_full = {
+ DNS_STYLEFLAG_COMMENT |
+ DNS_STYLEFLAG_RESIGN,
+ 46, 46, 46, 64, 120, 8
+};
+
+LIBDNS_EXTERNAL_DATA const dns_master_style_t
+dns_master_style_explicitttl = {
+ DNS_STYLEFLAG_OMIT_OWNER |
+ DNS_STYLEFLAG_OMIT_CLASS |
+ DNS_STYLEFLAG_REL_OWNER |
+ DNS_STYLEFLAG_REL_DATA |
+ DNS_STYLEFLAG_COMMENT |
+ DNS_STYLEFLAG_MULTILINE,
+ 24, 32, 32, 40, 80, 8
+};
+
+LIBDNS_EXTERNAL_DATA const dns_master_style_t
+dns_master_style_cache = {
+ DNS_STYLEFLAG_OMIT_OWNER |
+ DNS_STYLEFLAG_OMIT_CLASS |
+ DNS_STYLEFLAG_MULTILINE |
+ DNS_STYLEFLAG_TRUST |
+ DNS_STYLEFLAG_NCACHE,
+ 24, 32, 32, 40, 80, 8
+};
+
+LIBDNS_EXTERNAL_DATA const dns_master_style_t
+dns_master_style_simple = {
+ 0,
+ 24, 32, 32, 40, 80, 8
+};
+
+/*%
+ * A style suitable for dns_rdataset_totext().
+ */
+LIBDNS_EXTERNAL_DATA const dns_master_style_t
+dns_master_style_debug = {
+ DNS_STYLEFLAG_REL_OWNER,
+ 24, 32, 40, 48, 80, 8
+};
+
+
+#define N_SPACES 10
+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";
+
+struct dns_dumpctx {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_mutex_t lock;
+ unsigned int references;
+ isc_boolean_t canceled;
+ isc_boolean_t first;
+ isc_boolean_t do_date;
+ isc_stdtime_t now;
+ FILE *f;
+ dns_db_t *db;
+ dns_dbversion_t *version;
+ dns_dbiterator_t *dbiter;
+ dns_totext_ctx_t tctx;
+ isc_task_t *task;
+ dns_dumpdonefunc_t done;
+ void *done_arg;
+ unsigned int nodes;
+ /* dns_master_dumpinc() */
+ char *file;
+ char *tmpfile;
+ dns_masterformat_t format;
+ isc_result_t (*dumpsets)(isc_mem_t *mctx, dns_name_t *name,
+ dns_rdatasetiter_t *rdsiter,
+ dns_totext_ctx_t *ctx,
+ isc_buffer_t *buffer, FILE *f);
+};
+
+#define NXDOMAIN(x) (((x)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
+
+/*%
+ * Output tabs and spaces to go from column '*current' to
+ * column 'to', and update '*current' to reflect the new
+ * current column.
+ */
+static isc_result_t
+indent(unsigned int *current, unsigned int to, int tabwidth,
+ isc_buffer_t *target)
+{
+ isc_region_t r;
+ unsigned char *p;
+ unsigned int from;
+ int ntabs, nspaces, t;
+
+ from = *current;
+
+ if (to < from + 1)
+ to = from + 1;
+
+ ntabs = to / tabwidth - from / tabwidth;
+ if (ntabs < 0)
+ ntabs = 0;
+
+ if (ntabs > 0) {
+ isc_buffer_availableregion(target, &r);
+ if (r.length < (unsigned) ntabs)
+ return (ISC_R_NOSPACE);
+ p = r.base;
+
+ t = ntabs;
+ while (t) {
+ int n = t;
+ if (n > N_TABS)
+ n = N_TABS;
+ memcpy(p, tabs, n);
+ p += n;
+ t -= n;
+ }
+ isc_buffer_add(target, ntabs);
+ from = (to / tabwidth) * tabwidth;
+ }
+
+ nspaces = to - from;
+ INSIST(nspaces >= 0);
+
+ isc_buffer_availableregion(target, &r);
+ if (r.length < (unsigned) nspaces)
+ return (ISC_R_NOSPACE);
+ p = r.base;
+
+ t = nspaces;
+ while (t) {
+ int n = t;
+ if (n > N_SPACES)
+ n = N_SPACES;
+ memcpy(p, spaces, n);
+ p += n;
+ t -= n;
+ }
+ isc_buffer_add(target, nspaces);
+
+ *current = to;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) {
+ isc_result_t result;
+
+ REQUIRE(style->tab_width != 0);
+
+ ctx->style = *style;
+ ctx->class_printed = ISC_FALSE;
+
+ dns_fixedname_init(&ctx->origin_fixname);
+
+ /*
+ * Set up the line break string if needed.
+ */
+ if ((ctx->style.flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ isc_buffer_t buf;
+ isc_region_t r;
+ unsigned int col = 0;
+
+ isc_buffer_init(&buf, ctx->linebreak_buf,
+ sizeof(ctx->linebreak_buf));
+
+ isc_buffer_availableregion(&buf, &r);
+ if (r.length < 1)
+ return (DNS_R_TEXTTOOLONG);
+ r.base[0] = '\n';
+ isc_buffer_add(&buf, 1);
+
+ result = indent(&col, ctx->style.rdata_column,
+ ctx->style.tab_width, &buf);
+ /*
+ * Do not return ISC_R_NOSPACE if the line break string
+ * buffer is too small, because that would just make
+ * dump_rdataset() retry indenfinitely with ever
+ * bigger target buffers. That's a different buffer,
+ * so it won't help. Use DNS_R_TEXTTOOLONG as a substitute.
+ */
+ if (result == ISC_R_NOSPACE)
+ return (DNS_R_TEXTTOOLONG);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ isc_buffer_availableregion(&buf, &r);
+ if (r.length < 1)
+ return (DNS_R_TEXTTOOLONG);
+ r.base[0] = '\0';
+ isc_buffer_add(&buf, 1);
+ ctx->linebreak = ctx->linebreak_buf;
+ } else {
+ ctx->linebreak = NULL;
+ }
+
+ ctx->origin = NULL;
+ ctx->neworigin = NULL;
+ ctx->current_ttl = 0;
+ ctx->current_ttl_valid = ISC_FALSE;
+
+ return (ISC_R_SUCCESS);
+}
+
+#define INDENT_TO(col) \
+ do { \
+ if ((result = indent(&column, ctx->style.col, \
+ ctx->style.tab_width, target)) \
+ != ISC_R_SUCCESS) \
+ return (result); \
+ } while (0)
+
+
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target) {
+ unsigned int l;
+ isc_region_t region;
+
+ isc_buffer_availableregion(target, &region);
+ l = strlen(source);
+
+ if (l > region.length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(region.base, source, l);
+ isc_buffer_add(target, l);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Convert 'rdataset' to master file text format according to 'ctx',
+ * storing the result in 'target'. If 'owner_name' is NULL, it
+ * is omitted; otherwise 'owner_name' must be valid and have at least
+ * one label.
+ */
+
+static isc_result_t
+rdataset_totext(dns_rdataset_t *rdataset,
+ dns_name_t *owner_name,
+ dns_totext_ctx_t *ctx,
+ isc_boolean_t omit_final_dot,
+ isc_buffer_t *target)
+{
+ isc_result_t result;
+ unsigned int column;
+ isc_boolean_t first = ISC_TRUE;
+ isc_uint32_t current_ttl;
+ isc_boolean_t current_ttl_valid;
+ dns_rdatatype_t type;
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+
+ rdataset->attributes |= DNS_RDATASETATTR_LOADORDER;
+ result = dns_rdataset_first(rdataset);
+ REQUIRE(result == ISC_R_SUCCESS);
+
+ current_ttl = ctx->current_ttl;
+ current_ttl_valid = ctx->current_ttl_valid;
+
+ do {
+ column = 0;
+
+ /*
+ * Owner name.
+ */
+ if (owner_name != NULL &&
+ ! ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0 &&
+ !first))
+ {
+ unsigned int name_start = target->used;
+ RETERR(dns_name_totext(owner_name,
+ omit_final_dot,
+ target));
+ column += target->used - name_start;
+ }
+
+ /*
+ * TTL.
+ */
+ if ((ctx->style.flags & DNS_STYLEFLAG_NO_TTL) == 0 &&
+ !((ctx->style.flags & DNS_STYLEFLAG_OMIT_TTL) != 0 &&
+ current_ttl_valid &&
+ rdataset->ttl == current_ttl))
+ {
+ char ttlbuf[64];
+ isc_region_t r;
+ unsigned int length;
+
+ INDENT_TO(ttl_column);
+ length = snprintf(ttlbuf, sizeof(ttlbuf), "%u",
+ rdataset->ttl);
+ INSIST(length <= sizeof(ttlbuf));
+ isc_buffer_availableregion(target, &r);
+ if (r.length < length)
+ return (ISC_R_NOSPACE);
+ memcpy(r.base, ttlbuf, length);
+ isc_buffer_add(target, length);
+ column += length;
+
+ /*
+ * If the $TTL directive is not in use, the TTL we
+ * just printed becomes the default for subsequent RRs.
+ */
+ if ((ctx->style.flags & DNS_STYLEFLAG_TTL) == 0) {
+ current_ttl = rdataset->ttl;
+ current_ttl_valid = ISC_TRUE;
+ }
+ }
+
+ /*
+ * Class.
+ */
+ if ((ctx->style.flags & DNS_STYLEFLAG_NO_CLASS) == 0 &&
+ ((ctx->style.flags & DNS_STYLEFLAG_OMIT_CLASS) == 0 ||
+ ctx->class_printed == ISC_FALSE))
+ {
+ unsigned int class_start;
+ INDENT_TO(class_column);
+ class_start = target->used;
+ result = dns_rdataclass_totext(rdataset->rdclass,
+ target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ column += (target->used - class_start);
+ }
+
+ /*
+ * Type.
+ */
+
+ if (rdataset->type == 0) {
+ type = rdataset->covers;
+ } else {
+ type = rdataset->type;
+ }
+
+ {
+ unsigned int type_start;
+ INDENT_TO(type_column);
+ type_start = target->used;
+ if (rdataset->type == 0)
+ RETERR(str_totext("\\-", target));
+ result = dns_rdatatype_totext(type, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ column += (target->used - type_start);
+ }
+
+ /*
+ * Rdata.
+ */
+ INDENT_TO(rdata_column);
+ if (rdataset->type == 0) {
+ if (NXDOMAIN(rdataset))
+ RETERR(str_totext(";-$NXDOMAIN\n", target));
+ else
+ RETERR(str_totext(";-$NXRRSET\n", target));
+ } else {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t r;
+
+ dns_rdataset_current(rdataset, &rdata);
+
+ RETERR(dns_rdata_tofmttext(&rdata,
+ ctx->origin,
+ ctx->style.flags,
+ ctx->style.line_length -
+ ctx->style.rdata_column,
+ ctx->linebreak,
+ target));
+
+ isc_buffer_availableregion(target, &r);
+ if (r.length < 1)
+ return (ISC_R_NOSPACE);
+ r.base[0] = '\n';
+ isc_buffer_add(target, 1);
+ }
+
+ first = ISC_FALSE;
+ result = dns_rdataset_next(rdataset);
+ } while (result == ISC_R_SUCCESS);
+
+ if (result != ISC_R_NOMORE)
+ return (result);
+
+ /*
+ * Update the ctx state to reflect what we just printed.
+ * This is done last, only when we are sure we will return
+ * success, because this function may be called multiple
+ * times with increasing buffer sizes until it succeeds,
+ * and failed attempts must not update the state prematurely.
+ */
+ ctx->class_printed = ISC_TRUE;
+ ctx->current_ttl= current_ttl;
+ ctx->current_ttl_valid = current_ttl_valid;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Print the name, type, and class of an empty rdataset,
+ * such as those used to represent the question section
+ * of a DNS message.
+ */
+static isc_result_t
+question_totext(dns_rdataset_t *rdataset,
+ dns_name_t *owner_name,
+ dns_totext_ctx_t *ctx,
+ isc_boolean_t omit_final_dot,
+ isc_buffer_t *target)
+{
+ unsigned int column;
+ isc_result_t result;
+ isc_region_t r;
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ result = dns_rdataset_first(rdataset);
+ REQUIRE(result == ISC_R_NOMORE);
+
+ column = 0;
+
+ /* Owner name */
+ {
+ unsigned int name_start = target->used;
+ RETERR(dns_name_totext(owner_name,
+ omit_final_dot,
+ target));
+ column += target->used - name_start;
+ }
+
+ /* Class */
+ {
+ unsigned int class_start;
+ INDENT_TO(class_column);
+ class_start = target->used;
+ result = dns_rdataclass_totext(rdataset->rdclass, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ column += (target->used - class_start);
+ }
+
+ /* Type */
+ {
+ unsigned int type_start;
+ INDENT_TO(type_column);
+ type_start = target->used;
+ result = dns_rdatatype_totext(rdataset->type, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ column += (target->used - type_start);
+ }
+
+ isc_buffer_availableregion(target, &r);
+ if (r.length < 1)
+ return (ISC_R_NOSPACE);
+ r.base[0] = '\n';
+ isc_buffer_add(target, 1);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdataset_totext(dns_rdataset_t *rdataset,
+ dns_name_t *owner_name,
+ isc_boolean_t omit_final_dot,
+ isc_boolean_t question,
+ isc_buffer_t *target)
+{
+ dns_totext_ctx_t ctx;
+ isc_result_t result;
+ result = totext_ctx_init(&dns_master_style_debug, &ctx);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "could not set master file style");
+ return (ISC_R_UNEXPECTED);
+ }
+
+ /*
+ * The caller might want to give us an empty owner
+ * name (e.g. if they are outputting into a master
+ * file and this rdataset has the same name as the
+ * previous one.)
+ */
+ if (dns_name_countlabels(owner_name) == 0)
+ owner_name = NULL;
+
+ if (question)
+ return (question_totext(rdataset, owner_name, &ctx,
+ omit_final_dot, target));
+ else
+ return (rdataset_totext(rdataset, owner_name, &ctx,
+ omit_final_dot, target));
+}
+
+isc_result_t
+dns_master_rdatasettotext(dns_name_t *owner_name,
+ dns_rdataset_t *rdataset,
+ const dns_master_style_t *style,
+ isc_buffer_t *target)
+{
+ dns_totext_ctx_t ctx;
+ isc_result_t result;
+ result = totext_ctx_init(style, &ctx);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "could not set master file style");
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (rdataset_totext(rdataset, owner_name, &ctx,
+ ISC_FALSE, target));
+}
+
+isc_result_t
+dns_master_questiontotext(dns_name_t *owner_name,
+ dns_rdataset_t *rdataset,
+ const dns_master_style_t *style,
+ isc_buffer_t *target)
+{
+ dns_totext_ctx_t ctx;
+ isc_result_t result;
+ result = totext_ctx_init(style, &ctx);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "could not set master file style");
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (question_totext(rdataset, owner_name, &ctx,
+ ISC_FALSE, target));
+}
+
+/*
+ * Print an rdataset. 'buffer' is a scratch buffer, which must have been
+ * dynamically allocated by the caller. It must be large enough to
+ * hold the result from dns_ttl_totext(). If more than that is needed,
+ * the buffer will be grown automatically.
+ */
+
+static isc_result_t
+dump_rdataset(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_totext_ctx_t *ctx,
+ isc_buffer_t *buffer, FILE *f)
+{
+ isc_region_t r;
+ isc_result_t result;
+
+ REQUIRE(buffer->length > 0);
+
+ /*
+ * Output a $TTL directive if needed.
+ */
+
+ if ((ctx->style.flags & DNS_STYLEFLAG_TTL) != 0) {
+ if (ctx->current_ttl_valid == ISC_FALSE ||
+ ctx->current_ttl != rdataset->ttl)
+ {
+ if ((ctx->style.flags & DNS_STYLEFLAG_COMMENT) != 0)
+ {
+ isc_buffer_clear(buffer);
+ result = dns_ttl_totext(rdataset->ttl,
+ ISC_TRUE, buffer);
+ INSIST(result == ISC_R_SUCCESS);
+ isc_buffer_usedregion(buffer, &r);
+ fprintf(f, "$TTL %u\t; %.*s\n", rdataset->ttl,
+ (int) r.length, (char *) r.base);
+ } else {
+ fprintf(f, "$TTL %u\n", rdataset->ttl);
+ }
+ ctx->current_ttl = rdataset->ttl;
+ ctx->current_ttl_valid = ISC_TRUE;
+ }
+ }
+
+ isc_buffer_clear(buffer);
+
+ /*
+ * Generate the text representation of the rdataset into
+ * the buffer. If the buffer is too small, grow it.
+ */
+ for (;;) {
+ int newlength;
+ void *newmem;
+ result = rdataset_totext(rdataset, name, ctx,
+ ISC_FALSE, buffer);
+ if (result != ISC_R_NOSPACE)
+ break;
+
+ newlength = buffer->length * 2;
+ newmem = isc_mem_get(mctx, newlength);
+ if (newmem == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_mem_put(mctx, buffer->base, buffer->length);
+ isc_buffer_init(buffer, newmem, newlength);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Write the buffer contents to the master file.
+ */
+ isc_buffer_usedregion(buffer, &r);
+ result = isc_stdio_write(r.base, 1, (size_t)r.length, f, NULL);
+
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "master file write failed: %s",
+ isc_result_totext(result));
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Define the order in which rdatasets should be printed in zone
+ * files. We will print SOA and NS records before others, SIGs
+ * immediately following the things they sign, and order everything
+ * else by RR number. This is all just for aesthetics and
+ * compatibility with buggy software that expects the SOA to be first;
+ * the DNS specifications allow any order.
+ */
+
+static int
+dump_order(const dns_rdataset_t *rds) {
+ int t;
+ int sig;
+ if (rds->type == dns_rdatatype_rrsig) {
+ t = rds->covers;
+ sig = 1;
+ } else {
+ t = rds->type;
+ sig = 0;
+ }
+ switch (t) {
+ case dns_rdatatype_soa:
+ t = 0;
+ break;
+ case dns_rdatatype_ns:
+ t = 1;
+ break;
+ default:
+ t += 2;
+ break;
+ }
+ return (t << 1) + sig;
+}
+
+static int
+dump_order_compare(const void *a, const void *b) {
+ return (dump_order(*((const dns_rdataset_t * const *) a)) -
+ dump_order(*((const dns_rdataset_t * const *) b)));
+}
+
+/*
+ * Dump all the rdatasets of a domain name to a master file. We make
+ * a "best effort" attempt to sort the RRsets in a nice order, but if
+ * there are more than MAXSORT RRsets, we punt and only sort them in
+ * groups of MAXSORT. This is not expected to ever happen in practice
+ * since much less than 64 RR types have been registered with the
+ * IANA, so far, and the output will be correct (though not
+ * aesthetically pleasing) even if it does happen.
+ */
+
+#define MAXSORT 64
+
+static const char *trustnames[] = {
+ "none",
+ "pending",
+ "additional",
+ "glue",
+ "answer",
+ "authauthority",
+ "authanswer",
+ "secure",
+ "local" /* aka ultimate */
+};
+
+const char *
+dns_trust_totext(dns_trust_t trust) {
+ if (trust >= sizeof(trustnames)/sizeof(*trustnames))
+ return ("bad");
+ return (trustnames[trust]);
+}
+
+static isc_result_t
+dump_rdatasets_text(isc_mem_t *mctx, dns_name_t *name,
+ dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx,
+ isc_buffer_t *buffer, FILE *f)
+{
+ isc_result_t itresult, dumpresult;
+ isc_region_t r;
+ dns_rdataset_t rdatasets[MAXSORT];
+ dns_rdataset_t *sorted[MAXSORT];
+ int i, n;
+
+ itresult = dns_rdatasetiter_first(rdsiter);
+ dumpresult = ISC_R_SUCCESS;
+
+ if (itresult == ISC_R_SUCCESS && ctx->neworigin != NULL) {
+ isc_buffer_clear(buffer);
+ itresult = dns_name_totext(ctx->neworigin, ISC_FALSE, buffer);
+ RUNTIME_CHECK(itresult == ISC_R_SUCCESS);
+ isc_buffer_usedregion(buffer, &r);
+ fprintf(f, "$ORIGIN %.*s\n", (int) r.length, (char *) r.base);
+ ctx->neworigin = NULL;
+ }
+
+ again:
+ for (i = 0;
+ itresult == ISC_R_SUCCESS && i < MAXSORT;
+ itresult = dns_rdatasetiter_next(rdsiter), i++) {
+ dns_rdataset_init(&rdatasets[i]);
+ dns_rdatasetiter_current(rdsiter, &rdatasets[i]);
+ sorted[i] = &rdatasets[i];
+ }
+ n = i;
+ INSIST(n <= MAXSORT);
+
+ qsort(sorted, n, sizeof(sorted[0]), dump_order_compare);
+
+ for (i = 0; i < n; i++) {
+ dns_rdataset_t *rds = sorted[i];
+ if (ctx->style.flags & DNS_STYLEFLAG_TRUST) {
+ unsigned int trust = rds->trust;
+ INSIST(trust < (sizeof(trustnames) /
+ sizeof(trustnames[0])));
+ fprintf(f, "; %s\n", trustnames[trust]);
+ }
+ if (rds->type == 0 &&
+ (ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) {
+ /* Omit negative cache entries */
+ } else {
+ isc_result_t result =
+ dump_rdataset(mctx, name, rds, ctx,
+ buffer, f);
+ if (result != ISC_R_SUCCESS)
+ dumpresult = result;
+ if ((ctx->style.flags & DNS_STYLEFLAG_OMIT_OWNER) != 0)
+ name = NULL;
+ }
+ if (ctx->style.flags & DNS_STYLEFLAG_RESIGN &&
+ rds->attributes & DNS_RDATASETATTR_RESIGN) {
+ isc_buffer_t b;
+ char buf[sizeof("YYYYMMDDHHMMSS")];
+ memset(buf, 0, sizeof(buf));
+ isc_buffer_init(&b, buf, sizeof(buf) - 1);
+ dns_time64_totext((isc_uint64_t)rds->resign, &b);
+ fprintf(f, "; resign=%s\n", buf);
+ }
+ dns_rdataset_disassociate(rds);
+ }
+
+ if (dumpresult != ISC_R_SUCCESS)
+ return (dumpresult);
+
+ /*
+ * If we got more data than could be sorted at once,
+ * go handle the rest.
+ */
+ if (itresult == ISC_R_SUCCESS)
+ goto again;
+
+ if (itresult == ISC_R_NOMORE)
+ itresult = ISC_R_SUCCESS;
+
+ return (itresult);
+}
+
+/*
+ * Dump given RRsets in the "raw" format.
+ */
+static isc_result_t
+dump_rdataset_raw(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *rdataset,
+ isc_buffer_t *buffer, FILE *f)
+{
+ isc_result_t result;
+ isc_uint32_t totallen;
+ isc_uint16_t dlen;
+ isc_region_t r, r_hdr;
+
+ REQUIRE(buffer->length > 0);
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+
+ restart:
+ totallen = 0;
+ result = dns_rdataset_first(rdataset);
+ REQUIRE(result == ISC_R_SUCCESS);
+
+ isc_buffer_clear(buffer);
+
+ /*
+ * Common header and owner name (length followed by name)
+ * These fields should be in a moderate length, so we assume we
+ * can store all of them in the initial buffer.
+ */
+ isc_buffer_availableregion(buffer, &r_hdr);
+ INSIST(r_hdr.length >= sizeof(dns_masterrawrdataset_t));
+ isc_buffer_putuint32(buffer, totallen); /* XXX: leave space */
+ isc_buffer_putuint16(buffer, rdataset->rdclass); /* 16-bit class */
+ isc_buffer_putuint16(buffer, rdataset->type); /* 16-bit type */
+ isc_buffer_putuint16(buffer, rdataset->covers); /* same as type */
+ isc_buffer_putuint32(buffer, rdataset->ttl); /* 32-bit TTL */
+ isc_buffer_putuint32(buffer, dns_rdataset_count(rdataset));
+ totallen = isc_buffer_usedlength(buffer);
+ INSIST(totallen <= sizeof(dns_masterrawrdataset_t));
+
+ dns_name_toregion(name, &r);
+ INSIST(isc_buffer_availablelength(buffer) >=
+ (sizeof(dlen) + r.length));
+ dlen = (isc_uint16_t)r.length;
+ isc_buffer_putuint16(buffer, dlen);
+ isc_buffer_copyregion(buffer, &r);
+ totallen += sizeof(dlen) + r.length;
+
+ do {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t r;
+
+ dns_rdataset_current(rdataset, &rdata);
+ dns_rdata_toregion(&rdata, &r);
+ INSIST(r.length <= 0xffffU);
+ dlen = (isc_uint16_t)r.length;
+
+ /*
+ * Copy the rdata into the buffer. If the buffer is too small,
+ * grow it. This should be rare, so we'll simply restart the
+ * entire procedure (or should we copy the old data and
+ * continue?).
+ */
+ if (isc_buffer_availablelength(buffer) <
+ sizeof(dlen) + r.length) {
+ int newlength;
+ void *newmem;
+
+ newlength = buffer->length * 2;
+ newmem = isc_mem_get(mctx, newlength);
+ if (newmem == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_mem_put(mctx, buffer->base, buffer->length);
+ isc_buffer_init(buffer, newmem, newlength);
+ goto restart;
+ }
+ isc_buffer_putuint16(buffer, dlen);
+ isc_buffer_copyregion(buffer, &r);
+ totallen += sizeof(dlen) + r.length;
+
+ result = dns_rdataset_next(rdataset);
+ } while (result == ISC_R_SUCCESS);
+
+ if (result != ISC_R_NOMORE)
+ return (result);
+
+ /*
+ * Fill in the total length field.
+ * XXX: this is a bit tricky. Since we have already "used" the space
+ * for the total length in the buffer, we first remember the entire
+ * buffer length in the region, "rewind", and then write the value.
+ */
+ isc_buffer_usedregion(buffer, &r);
+ isc_buffer_clear(buffer);
+ isc_buffer_putuint32(buffer, totallen);
+ INSIST(isc_buffer_usedlength(buffer) < totallen);
+
+ /*
+ * Write the buffer contents to the raw master file.
+ */
+ result = isc_stdio_write(r.base, 1, (size_t)r.length, f, NULL);
+
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "raw master file write failed: %s",
+ isc_result_totext(result));
+ return (result);
+ }
+
+ return (result);
+}
+
+static isc_result_t
+dump_rdatasets_raw(isc_mem_t *mctx, dns_name_t *name,
+ dns_rdatasetiter_t *rdsiter, dns_totext_ctx_t *ctx,
+ isc_buffer_t *buffer, FILE *f)
+{
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter)) {
+
+ dns_rdataset_init(&rdataset);
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+
+ if (rdataset.type == 0 &&
+ (ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) {
+ /* Omit negative cache entries */
+ } else {
+ result = dump_rdataset_raw(mctx, name, &rdataset,
+ buffer, f);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ }
+
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ return (result);
+}
+
+/*
+ * Initial size of text conversion buffer. The buffer is used
+ * for several purposes: converting origin names, rdatasets,
+ * $DATE timestamps, and comment strings for $TTL directives.
+ *
+ * When converting rdatasets, it is dynamically resized, but
+ * when converting origins, timestamps, etc it is not. Therefore,
+ * the initial size must large enough to hold the longest possible
+ * text representation of any domain name (for $ORIGIN).
+ */
+static const int initial_buffer_length = 1200;
+
+static isc_result_t
+dumptostreaminc(dns_dumpctx_t *dctx);
+
+static void
+dumpctx_destroy(dns_dumpctx_t *dctx) {
+
+ dctx->magic = 0;
+ DESTROYLOCK(&dctx->lock);
+ dns_dbiterator_destroy(&dctx->dbiter);
+ if (dctx->version != NULL)
+ dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
+ dns_db_detach(&dctx->db);
+ if (dctx->task != NULL)
+ isc_task_detach(&dctx->task);
+ if (dctx->file != NULL)
+ isc_mem_free(dctx->mctx, dctx->file);
+ if (dctx->tmpfile != NULL)
+ isc_mem_free(dctx->mctx, dctx->tmpfile);
+ isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(*dctx));
+}
+
+void
+dns_dumpctx_attach(dns_dumpctx_t *source, dns_dumpctx_t **target) {
+
+ REQUIRE(DNS_DCTX_VALID(source));
+ REQUIRE(target != NULL && *target == NULL);
+
+ LOCK(&source->lock);
+ INSIST(source->references > 0);
+ source->references++;
+ INSIST(source->references != 0); /* Overflow? */
+ UNLOCK(&source->lock);
+
+ *target = source;
+}
+
+void
+dns_dumpctx_detach(dns_dumpctx_t **dctxp) {
+ dns_dumpctx_t *dctx;
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(dctxp != NULL);
+ dctx = *dctxp;
+ REQUIRE(DNS_DCTX_VALID(dctx));
+
+ *dctxp = NULL;
+
+ LOCK(&dctx->lock);
+ INSIST(dctx->references != 0);
+ dctx->references--;
+ if (dctx->references == 0)
+ need_destroy = ISC_TRUE;
+ UNLOCK(&dctx->lock);
+ if (need_destroy)
+ dumpctx_destroy(dctx);
+}
+
+dns_dbversion_t *
+dns_dumpctx_version(dns_dumpctx_t *dctx) {
+ REQUIRE(DNS_DCTX_VALID(dctx));
+ return (dctx->version);
+}
+
+dns_db_t *
+dns_dumpctx_db(dns_dumpctx_t *dctx) {
+ REQUIRE(DNS_DCTX_VALID(dctx));
+ return (dctx->db);
+}
+
+void
+dns_dumpctx_cancel(dns_dumpctx_t *dctx) {
+ REQUIRE(DNS_DCTX_VALID(dctx));
+
+ LOCK(&dctx->lock);
+ dctx->canceled = ISC_TRUE;
+ UNLOCK(&dctx->lock);
+}
+
+static isc_result_t
+closeandrename(FILE *f, isc_result_t result, const char *temp, const char *file)
+{
+ isc_result_t tresult;
+ isc_boolean_t logit = ISC_TF(result == ISC_R_SUCCESS);
+
+ if (result == ISC_R_SUCCESS)
+ result = isc_stdio_sync(f);
+ if (result != ISC_R_SUCCESS && logit) {
+ isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
+ "dumping master file: %s: fsync: %s",
+ temp, isc_result_totext(result));
+ logit = ISC_FALSE;
+ }
+ tresult = isc_stdio_close(f);
+ if (result == ISC_R_SUCCESS)
+ result = tresult;
+ if (result != ISC_R_SUCCESS && logit) {
+ isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
+ "dumping master file: %s: fclose: %s",
+ temp, isc_result_totext(result));
+ logit = ISC_FALSE;
+ }
+ if (result == ISC_R_SUCCESS)
+ result = isc_file_rename(temp, file);
+ else
+ (void)isc_file_remove(temp);
+ if (result != ISC_R_SUCCESS && logit) {
+ isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
+ "dumping master file: rename: %s: %s",
+ file, isc_result_totext(result));
+ }
+ return (result);
+}
+
+static void
+dump_quantum(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ isc_result_t tresult;
+ dns_dumpctx_t *dctx;
+
+ REQUIRE(event != NULL);
+ dctx = event->ev_arg;
+ REQUIRE(DNS_DCTX_VALID(dctx));
+ if (dctx->canceled)
+ result = ISC_R_CANCELED;
+ else
+ result = dumptostreaminc(dctx);
+ if (result == DNS_R_CONTINUE) {
+ event->ev_arg = dctx;
+ isc_task_send(task, &event);
+ return;
+ }
+
+ if (dctx->file != NULL) {
+ tresult = closeandrename(dctx->f, result,
+ dctx->tmpfile, dctx->file);
+ if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
+ result = tresult;
+ }
+ (dctx->done)(dctx->done_arg, result);
+ isc_event_free(&event);
+ dns_dumpctx_detach(&dctx);
+}
+
+static isc_result_t
+task_send(dns_dumpctx_t *dctx) {
+ isc_event_t *event;
+
+ event = isc_event_allocate(dctx->mctx, NULL, DNS_EVENT_DUMPQUANTUM,
+ dump_quantum, dctx, sizeof(*event));
+ if (event == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_task_send(dctx->task, &event);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
+ const dns_master_style_t *style, FILE *f, dns_dumpctx_t **dctxp,
+ dns_masterformat_t format)
+{
+ dns_dumpctx_t *dctx;
+ isc_result_t result;
+ unsigned int options;
+
+ dctx = isc_mem_get(mctx, sizeof(*dctx));
+ if (dctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dctx->mctx = NULL;
+ dctx->f = f;
+ dctx->dbiter = NULL;
+ dctx->db = NULL;
+ dctx->version = NULL;
+ dctx->done = NULL;
+ dctx->done_arg = NULL;
+ dctx->task = NULL;
+ dctx->nodes = 0;
+ dctx->first = ISC_TRUE;
+ dctx->canceled = ISC_FALSE;
+ dctx->file = NULL;
+ dctx->tmpfile = NULL;
+ dctx->format = format;
+
+ switch (format) {
+ case dns_masterformat_text:
+ dctx->dumpsets = dump_rdatasets_text;
+ break;
+ case dns_masterformat_raw:
+ dctx->dumpsets = dump_rdatasets_raw;
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+
+ result = totext_ctx_init(style, &dctx->tctx);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "could not set master file style");
+ goto cleanup;
+ }
+
+ isc_stdtime_get(&dctx->now);
+ dns_db_attach(db, &dctx->db);
+
+ dctx->do_date = dns_db_iscache(dctx->db);
+
+ if (dctx->format == dns_masterformat_text &&
+ (dctx->tctx.style.flags & DNS_STYLEFLAG_REL_OWNER) != 0) {
+ options = DNS_DB_RELATIVENAMES;
+ } else
+ options = 0;
+ result = dns_db_createiterator(dctx->db, options, &dctx->dbiter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = isc_mutex_init(&dctx->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ if (version != NULL)
+ dns_db_attachversion(dctx->db, version, &dctx->version);
+ else if (!dns_db_iscache(db))
+ dns_db_currentversion(dctx->db, &dctx->version);
+ isc_mem_attach(mctx, &dctx->mctx);
+ dctx->references = 1;
+ dctx->magic = DNS_DCTX_MAGIC;
+ *dctxp = dctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (dctx->dbiter != NULL)
+ dns_dbiterator_destroy(&dctx->dbiter);
+ if (dctx->db != NULL)
+ dns_db_detach(&dctx->db);
+ if (dctx != NULL)
+ isc_mem_put(mctx, dctx, sizeof(*dctx));
+ return (result);
+}
+
+static isc_result_t
+dumptostreaminc(dns_dumpctx_t *dctx) {
+ isc_result_t result;
+ isc_buffer_t buffer;
+ char *bufmem;
+ isc_region_t r;
+ dns_name_t *name;
+ dns_fixedname_t fixname;
+ unsigned int nodes;
+ dns_masterrawheader_t rawheader;
+ isc_uint32_t now32;
+ isc_time_t start;
+
+ bufmem = isc_mem_get(dctx->mctx, initial_buffer_length);
+ if (bufmem == NULL)
+ return (ISC_R_NOMEMORY);
+
+ isc_buffer_init(&buffer, bufmem, initial_buffer_length);
+
+ dns_fixedname_init(&fixname);
+ name = dns_fixedname_name(&fixname);
+
+ if (dctx->first) {
+ switch (dctx->format) {
+ case dns_masterformat_text:
+ /*
+ * If the database has cache semantics, output an
+ * RFC2540 $DATE directive so that the TTLs can be
+ * adjusted when it is reloaded. For zones it is not
+ * really needed, and it would make the file
+ * incompatible with pre-RFC2540 software, so we omit
+ * it in the zone case.
+ */
+ if (dctx->do_date) {
+ result = dns_time32_totext(dctx->now, &buffer);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ isc_buffer_usedregion(&buffer, &r);
+ fprintf(dctx->f, "$DATE %.*s\n",
+ (int) r.length, (char *) r.base);
+ }
+ break;
+ case dns_masterformat_raw:
+ r.base = (unsigned char *)&rawheader;
+ r.length = sizeof(rawheader);
+ isc_buffer_region(&buffer, &r);
+ isc_buffer_putuint32(&buffer, dns_masterformat_raw);
+ isc_buffer_putuint32(&buffer, DNS_RAWFORMAT_VERSION);
+ if (sizeof(now32) != sizeof(dctx->now)) {
+ /*
+ * We assume isc_stdtime_t is a 32-bit integer,
+ * which should be the case on most cases.
+ * If it turns out to be uncommon, we'll need
+ * to bump the version number and revise the
+ * header format.
+ */
+ isc_log_write(dns_lctx,
+ ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTERDUMP,
+ ISC_LOG_INFO,
+ "dumping master file in raw "
+ "format: stdtime is not 32bits");
+ now32 = 0;
+ } else
+ now32 = dctx->now;
+ isc_buffer_putuint32(&buffer, now32);
+ INSIST(isc_buffer_usedlength(&buffer) <=
+ sizeof(rawheader));
+ result = isc_stdio_write(buffer.base, 1,
+ isc_buffer_usedlength(&buffer),
+ dctx->f, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_clear(&buffer);
+ break;
+ default:
+ INSIST(0);
+ }
+
+ result = dns_dbiterator_first(dctx->dbiter);
+ dctx->first = ISC_FALSE;
+ } else
+ result = ISC_R_SUCCESS;
+
+ nodes = dctx->nodes;
+ isc_time_now(&start);
+ while (result == ISC_R_SUCCESS && (dctx->nodes == 0 || nodes--)) {
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_dbnode_t *node = NULL;
+
+ result = dns_dbiterator_current(dctx->dbiter, &node, name);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+ break;
+ if (result == DNS_R_NEWORIGIN) {
+ dns_name_t *origin =
+ dns_fixedname_name(&dctx->tctx.origin_fixname);
+ result = dns_dbiterator_origin(dctx->dbiter, origin);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if ((dctx->tctx.style.flags & DNS_STYLEFLAG_REL_DATA) != 0)
+ dctx->tctx.origin = origin;
+ dctx->tctx.neworigin = origin;
+ }
+ result = dns_db_allrdatasets(dctx->db, node, dctx->version,
+ dctx->now, &rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(dctx->db, &node);
+ goto fail;
+ }
+ result = (dctx->dumpsets)(dctx->mctx, name, rdsiter,
+ &dctx->tctx, &buffer, dctx->f);
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(dctx->db, &node);
+ goto fail;
+ }
+ dns_db_detachnode(dctx->db, &node);
+ result = dns_dbiterator_next(dctx->dbiter);
+ }
+
+ /*
+ * Work out how many nodes can be written in the time between
+ * two requests to the nameserver. Smooth the resulting number and
+ * use it as a estimate for the number of nodes to be written in the
+ * next iteration.
+ */
+ if (dctx->nodes != 0 && result == ISC_R_SUCCESS) {
+ unsigned int pps = dns_pps; /* packets per second */
+ unsigned int interval;
+ isc_uint64_t usecs;
+ isc_time_t end;
+
+ isc_time_now(&end);
+ if (pps < 100)
+ pps = 100;
+ interval = 1000000 / pps; /* interval in usecs */
+ if (interval == 0)
+ interval = 1;
+ usecs = isc_time_microdiff(&end, &start);
+ if (usecs == 0) {
+ dctx->nodes = dctx->nodes * 2;
+ if (dctx->nodes > 1000)
+ dctx->nodes = 1000;
+ } else {
+ nodes = dctx->nodes * interval;
+ nodes /= (unsigned int)usecs;
+ if (nodes == 0)
+ nodes = 1;
+ else if (nodes > 1000)
+ nodes = 1000;
+
+ /* Smooth and assign. */
+ dctx->nodes = (nodes + dctx->nodes * 7) / 8;
+
+ isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTERDUMP,
+ ISC_LOG_DEBUG(1),
+ "dumptostreaminc(%p) new nodes -> %d\n",
+ dctx, dctx->nodes);
+ }
+ result = DNS_R_CONTINUE;
+ } else if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ fail:
+ RUNTIME_CHECK(dns_dbiterator_pause(dctx->dbiter) == ISC_R_SUCCESS);
+ isc_mem_put(dctx->mctx, buffer.base, buffer.length);
+ return (result);
+}
+
+isc_result_t
+dns_master_dumptostreaminc(isc_mem_t *mctx, dns_db_t *db,
+ dns_dbversion_t *version,
+ const dns_master_style_t *style,
+ FILE *f, isc_task_t *task,
+ dns_dumpdonefunc_t done, void *done_arg,
+ dns_dumpctx_t **dctxp)
+{
+ dns_dumpctx_t *dctx = NULL;
+ isc_result_t result;
+
+ REQUIRE(task != NULL);
+ REQUIRE(f != NULL);
+ REQUIRE(done != NULL);
+
+ result = dumpctx_create(mctx, db, version, style, f, &dctx,
+ dns_masterformat_text);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_task_attach(task, &dctx->task);
+ dctx->done = done;
+ dctx->done_arg = done_arg;
+ dctx->nodes = 100;
+
+ result = task_send(dctx);
+ if (result == ISC_R_SUCCESS) {
+ dns_dumpctx_attach(dctx, dctxp);
+ return (DNS_R_CONTINUE);
+ }
+
+ dns_dumpctx_detach(&dctx);
+ return (result);
+}
+
+/*
+ * Dump an entire database into a master file.
+ */
+isc_result_t
+dns_master_dumptostream(isc_mem_t *mctx, dns_db_t *db,
+ dns_dbversion_t *version,
+ const dns_master_style_t *style,
+ FILE *f)
+{
+ return (dns_master_dumptostream2(mctx, db, version, style,
+ dns_masterformat_text, f));
+}
+
+isc_result_t
+dns_master_dumptostream2(isc_mem_t *mctx, dns_db_t *db,
+ dns_dbversion_t *version,
+ const dns_master_style_t *style,
+ dns_masterformat_t format, FILE *f)
+{
+ dns_dumpctx_t *dctx = NULL;
+ isc_result_t result;
+
+ result = dumpctx_create(mctx, db, version, style, f, &dctx, format);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dumptostreaminc(dctx);
+ INSIST(result != DNS_R_CONTINUE);
+ dns_dumpctx_detach(&dctx);
+ return (result);
+}
+
+static isc_result_t
+opentmp(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) {
+ FILE *f = NULL;
+ isc_result_t result;
+ char *tempname = NULL;
+ int tempnamelen;
+
+ tempnamelen = strlen(file) + 20;
+ tempname = isc_mem_allocate(mctx, tempnamelen);
+ if (tempname == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_file_mktemplate(file, tempname, tempnamelen);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = isc_file_openunique(tempname, &f);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
+ "dumping master file: %s: open: %s",
+ tempname, isc_result_totext(result));
+ goto cleanup;
+ }
+ *tempp = tempname;
+ *fp = f;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ isc_mem_free(mctx, tempname);
+ return (result);
+}
+
+isc_result_t
+dns_master_dumpinc(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
+ const dns_master_style_t *style, const char *filename,
+ isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,
+ dns_dumpctx_t **dctxp)
+{
+ return (dns_master_dumpinc2(mctx, db, version, style, filename, task,
+ done, done_arg, dctxp,
+ dns_masterformat_text));
+}
+
+isc_result_t
+dns_master_dumpinc2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
+ const dns_master_style_t *style, const char *filename,
+ isc_task_t *task, dns_dumpdonefunc_t done, void *done_arg,
+ dns_dumpctx_t **dctxp, dns_masterformat_t format)
+{
+ FILE *f = NULL;
+ isc_result_t result;
+ char *tempname = NULL;
+ char *file = NULL;
+ dns_dumpctx_t *dctx = NULL;
+
+ file = isc_mem_strdup(mctx, filename);
+ if (file == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = opentmp(mctx, filename, &tempname, &f);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dumpctx_create(mctx, db, version, style, f, &dctx, format);
+ if (result != ISC_R_SUCCESS) {
+ (void)isc_stdio_close(f);
+ (void)isc_file_remove(tempname);
+ goto cleanup;
+ }
+
+ isc_task_attach(task, &dctx->task);
+ dctx->done = done;
+ dctx->done_arg = done_arg;
+ dctx->nodes = 100;
+ dctx->file = file;
+ file = NULL;
+ dctx->tmpfile = tempname;
+ tempname = NULL;
+
+ result = task_send(dctx);
+ if (result == ISC_R_SUCCESS) {
+ dns_dumpctx_attach(dctx, dctxp);
+ return (DNS_R_CONTINUE);
+ }
+
+ cleanup:
+ if (dctx != NULL)
+ dns_dumpctx_detach(&dctx);
+ if (file != NULL)
+ isc_mem_free(mctx, file);
+ if (tempname != NULL)
+ isc_mem_free(mctx, tempname);
+ return (result);
+}
+
+isc_result_t
+dns_master_dump(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
+ const dns_master_style_t *style, const char *filename)
+{
+ return (dns_master_dump2(mctx, db, version, style, filename,
+ dns_masterformat_text));
+}
+
+isc_result_t
+dns_master_dump2(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
+ const dns_master_style_t *style, const char *filename,
+ dns_masterformat_t format)
+{
+ FILE *f = NULL;
+ isc_result_t result;
+ char *tempname;
+ dns_dumpctx_t *dctx = NULL;
+
+ result = opentmp(mctx, filename, &tempname, &f);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dumpctx_create(mctx, db, version, style, f, &dctx, format);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dumptostreaminc(dctx);
+ INSIST(result != DNS_R_CONTINUE);
+ dns_dumpctx_detach(&dctx);
+
+ result = closeandrename(f, result, tempname, filename);
+
+ cleanup:
+ isc_mem_free(mctx, tempname);
+ return (result);
+}
+
+/*
+ * Dump a database node into a master file.
+ * XXX: this function assumes the text format.
+ */
+isc_result_t
+dns_master_dumpnodetostream(isc_mem_t *mctx, dns_db_t *db,
+ dns_dbversion_t *version,
+ dns_dbnode_t *node, dns_name_t *name,
+ const dns_master_style_t *style,
+ FILE *f)
+{
+ isc_result_t result;
+ isc_buffer_t buffer;
+ char *bufmem;
+ isc_stdtime_t now;
+ dns_totext_ctx_t ctx;
+ dns_rdatasetiter_t *rdsiter = NULL;
+
+ result = totext_ctx_init(style, &ctx);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "could not set master file style");
+ return (ISC_R_UNEXPECTED);
+ }
+
+ isc_stdtime_get(&now);
+
+ bufmem = isc_mem_get(mctx, initial_buffer_length);
+ if (bufmem == NULL)
+ return (ISC_R_NOMEMORY);
+
+ isc_buffer_init(&buffer, bufmem, initial_buffer_length);
+
+ result = dns_db_allrdatasets(db, node, version, now, &rdsiter);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ result = dump_rdatasets_text(mctx, name, rdsiter, &ctx, &buffer, f);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ dns_rdatasetiter_destroy(&rdsiter);
+
+ result = ISC_R_SUCCESS;
+
+ failure:
+ isc_mem_put(mctx, buffer.base, buffer.length);
+ return (result);
+}
+
+isc_result_t
+dns_master_dumpnode(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
+ dns_dbnode_t *node, dns_name_t *name,
+ const dns_master_style_t *style, const char *filename)
+{
+ FILE *f = NULL;
+ isc_result_t result;
+
+ result = isc_stdio_open(filename, "w", &f);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
+ "dumping node to file: %s: open: %s", filename,
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ result = dns_master_dumpnodetostream(mctx, db, version, node, name,
+ style, f);
+
+ result = isc_stdio_close(f);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MASTERDUMP, ISC_LOG_ERROR,
+ "dumping master file: %s: close: %s", filename,
+ isc_result_totext(result));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (result);
+}
+
+isc_result_t
+dns_master_stylecreate(dns_master_style_t **stylep, unsigned int flags,
+ unsigned int ttl_column, unsigned int class_column,
+ unsigned int type_column, unsigned int rdata_column,
+ unsigned int line_length, unsigned int tab_width,
+ isc_mem_t *mctx)
+{
+ dns_master_style_t *style;
+
+ REQUIRE(stylep != NULL && *stylep == NULL);
+ style = isc_mem_get(mctx, sizeof(*style));
+ if (style == NULL)
+ return (ISC_R_NOMEMORY);
+
+ style->flags = flags;
+ style->ttl_column = ttl_column;
+ style->class_column = class_column;
+ style->type_column = type_column;
+ style->rdata_column = rdata_column;
+ style->line_length = line_length;
+ style->tab_width = tab_width;
+
+ *stylep = style;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_master_styledestroy(dns_master_style_t **stylep, isc_mem_t *mctx) {
+ dns_master_style_t *style;
+
+ REQUIRE(stylep != NULL && *stylep != NULL);
+ style = *stylep;
+ *stylep = NULL;
+ isc_mem_put(mctx, style, sizeof(*style));
+}
diff --git a/lib/dns/message.c b/lib/dns/message.c
new file mode 100644
index 0000000..3420e55
--- /dev/null
+++ b/lib/dns/message.c
@@ -0,0 +1,3378 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: message.c,v 1.245 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+/***
+ *** Imports
+ ***/
+
+#include <config.h>
+#include <ctype.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/dnssec.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/opcode.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+
+#ifdef SKAN_MSG_DEBUG
+static void
+hexdump(const char *msg, const char *msg2, void *base, size_t len) {
+ unsigned char *p;
+ unsigned int cnt;
+
+ p = base;
+ cnt = 0;
+
+ printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, len, base);
+
+ while (cnt < len) {
+ if (cnt % 16 == 0)
+ printf("%p: ", p);
+ else if (cnt % 8 == 0)
+ printf(" |");
+ printf(" %02x %c", *p, (isprint(*p) ? *p : ' '));
+ p++;
+ cnt++;
+
+ if (cnt % 16 == 0)
+ printf("\n");
+ }
+
+ if (cnt % 16 != 0)
+ printf("\n");
+}
+#endif
+
+#define DNS_MESSAGE_OPCODE_MASK 0x7800U
+#define DNS_MESSAGE_OPCODE_SHIFT 11
+#define DNS_MESSAGE_RCODE_MASK 0x000fU
+#define DNS_MESSAGE_FLAG_MASK 0x8ff0U
+#define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
+#define DNS_MESSAGE_EDNSRCODE_SHIFT 24
+#define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
+#define DNS_MESSAGE_EDNSVERSION_SHIFT 16
+
+#define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
+ && ((s) < DNS_SECTION_MAX))
+#define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
+ && ((s) < DNS_SECTION_MAX))
+#define ADD_STRING(b, s) {if (strlen(s) >= \
+ isc_buffer_availablelength(b)) \
+ return(ISC_R_NOSPACE); else \
+ isc_buffer_putstr(b, s);}
+#define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
+ && ((s) < DNS_PSEUDOSECTION_MAX))
+
+#define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
+
+/*%
+ * This is the size of each individual scratchpad buffer, and the numbers
+ * of various block allocations used within the server.
+ * XXXMLG These should come from a config setting.
+ */
+#define SCRATCHPAD_SIZE 512
+#define NAME_COUNT 8
+#define OFFSET_COUNT 4
+#define RDATA_COUNT 8
+#define RDATALIST_COUNT 8
+#define RDATASET_COUNT RDATALIST_COUNT
+
+/*%
+ * Text representation of the different items, for message_totext
+ * functions.
+ */
+static const char *sectiontext[] = {
+ "QUESTION",
+ "ANSWER",
+ "AUTHORITY",
+ "ADDITIONAL"
+};
+
+static const char *updsectiontext[] = {
+ "ZONE",
+ "PREREQUISITE",
+ "UPDATE",
+ "ADDITIONAL"
+};
+
+static const char *opcodetext[] = {
+ "QUERY",
+ "IQUERY",
+ "STATUS",
+ "RESERVED3",
+ "NOTIFY",
+ "UPDATE",
+ "RESERVED6",
+ "RESERVED7",
+ "RESERVED8",
+ "RESERVED9",
+ "RESERVED10",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15"
+};
+
+static const char *rcodetext[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15",
+ "BADVERS"
+};
+
+
+/*%
+ * "helper" type, which consists of a block of some type, and is linkable.
+ * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
+ * size, or the allocated elements will not be alligned correctly.
+ */
+struct dns_msgblock {
+ unsigned int count;
+ unsigned int remaining;
+ ISC_LINK(dns_msgblock_t) link;
+}; /* dynamically sized */
+
+static inline dns_msgblock_t *
+msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
+
+#define msgblock_get(block, type) \
+ ((type *)msgblock_internalget(block, sizeof(type)))
+
+static inline void *
+msgblock_internalget(dns_msgblock_t *, unsigned int);
+
+static inline void
+msgblock_reset(dns_msgblock_t *);
+
+static inline void
+msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
+
+/*
+ * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
+ * is free, return NULL.
+ */
+static inline dns_msgblock_t *
+msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
+ unsigned int count)
+{
+ dns_msgblock_t *block;
+ unsigned int length;
+
+ length = sizeof(dns_msgblock_t) + (sizeof_type * count);
+
+ block = isc_mem_get(mctx, length);
+ if (block == NULL)
+ return (NULL);
+
+ block->count = count;
+ block->remaining = count;
+
+ ISC_LINK_INIT(block, link);
+
+ return (block);
+}
+
+/*
+ * Return an element from the msgblock. If no more are available, return
+ * NULL.
+ */
+static inline void *
+msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
+ void *ptr;
+
+ if (block == NULL || block->remaining == 0)
+ return (NULL);
+
+ block->remaining--;
+
+ ptr = (((unsigned char *)block)
+ + sizeof(dns_msgblock_t)
+ + (sizeof_type * block->remaining));
+
+ return (ptr);
+}
+
+static inline void
+msgblock_reset(dns_msgblock_t *block) {
+ block->remaining = block->count;
+}
+
+/*
+ * Release memory associated with a message block.
+ */
+static inline void
+msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
+{
+ unsigned int length;
+
+ length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
+
+ isc_mem_put(mctx, block, length);
+}
+
+/*
+ * Allocate a new dynamic buffer, and attach it to this message as the
+ * "current" buffer. (which is always the last on the list, for our
+ * uses)
+ */
+static inline isc_result_t
+newbuffer(dns_message_t *msg, unsigned int size) {
+ isc_result_t result;
+ isc_buffer_t *dynbuf;
+
+ dynbuf = NULL;
+ result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_NOMEMORY);
+
+ ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_buffer_t *
+currentbuffer(dns_message_t *msg) {
+ isc_buffer_t *dynbuf;
+
+ dynbuf = ISC_LIST_TAIL(msg->scratchpad);
+ INSIST(dynbuf != NULL);
+
+ return (dynbuf);
+}
+
+static inline void
+releaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
+ ISC_LIST_PREPEND(msg->freerdata, rdata, link);
+}
+
+static inline dns_rdata_t *
+newrdata(dns_message_t *msg) {
+ dns_msgblock_t *msgblock;
+ dns_rdata_t *rdata;
+
+ rdata = ISC_LIST_HEAD(msg->freerdata);
+ if (rdata != NULL) {
+ ISC_LIST_UNLINK(msg->freerdata, rdata, link);
+ return (rdata);
+ }
+
+ msgblock = ISC_LIST_TAIL(msg->rdatas);
+ rdata = msgblock_get(msgblock, dns_rdata_t);
+ if (rdata == NULL) {
+ msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
+ RDATA_COUNT);
+ if (msgblock == NULL)
+ return (NULL);
+
+ ISC_LIST_APPEND(msg->rdatas, msgblock, link);
+
+ rdata = msgblock_get(msgblock, dns_rdata_t);
+ }
+
+ dns_rdata_init(rdata);
+ return (rdata);
+}
+
+static inline void
+releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
+ ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
+}
+
+static inline dns_rdatalist_t *
+newrdatalist(dns_message_t *msg) {
+ dns_msgblock_t *msgblock;
+ dns_rdatalist_t *rdatalist;
+
+ rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
+ if (rdatalist != NULL) {
+ ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
+ return (rdatalist);
+ }
+
+ msgblock = ISC_LIST_TAIL(msg->rdatalists);
+ rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
+ if (rdatalist == NULL) {
+ msgblock = msgblock_allocate(msg->mctx,
+ sizeof(dns_rdatalist_t),
+ RDATALIST_COUNT);
+ if (msgblock == NULL)
+ return (NULL);
+
+ ISC_LIST_APPEND(msg->rdatalists, msgblock, link);
+
+ rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
+ }
+
+ return (rdatalist);
+}
+
+static inline dns_offsets_t *
+newoffsets(dns_message_t *msg) {
+ dns_msgblock_t *msgblock;
+ dns_offsets_t *offsets;
+
+ msgblock = ISC_LIST_TAIL(msg->offsets);
+ offsets = msgblock_get(msgblock, dns_offsets_t);
+ if (offsets == NULL) {
+ msgblock = msgblock_allocate(msg->mctx,
+ sizeof(dns_offsets_t),
+ OFFSET_COUNT);
+ if (msgblock == NULL)
+ return (NULL);
+
+ ISC_LIST_APPEND(msg->offsets, msgblock, link);
+
+ offsets = msgblock_get(msgblock, dns_offsets_t);
+ }
+
+ return (offsets);
+}
+
+static inline void
+msginitheader(dns_message_t *m) {
+ m->id = 0;
+ m->flags = 0;
+ m->rcode = 0;
+ m->opcode = 0;
+ m->rdclass = 0;
+}
+
+static inline void
+msginitprivate(dns_message_t *m) {
+ unsigned int i;
+
+ for (i = 0; i < DNS_SECTION_MAX; i++) {
+ m->cursors[i] = NULL;
+ m->counts[i] = 0;
+ }
+ m->opt = NULL;
+ m->sig0 = NULL;
+ m->sig0name = NULL;
+ m->tsig = NULL;
+ m->tsigname = NULL;
+ m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
+ m->opt_reserved = 0;
+ m->sig_reserved = 0;
+ m->reserved = 0;
+ m->buffer = NULL;
+}
+
+static inline void
+msginittsig(dns_message_t *m) {
+ m->tsigstatus = dns_rcode_noerror;
+ m->querytsigstatus = dns_rcode_noerror;
+ m->tsigkey = NULL;
+ m->tsigctx = NULL;
+ m->sigstart = -1;
+ m->sig0key = NULL;
+ m->sig0status = dns_rcode_noerror;
+ m->timeadjust = 0;
+}
+
+/*
+ * Init elements to default state. Used both when allocating a new element
+ * and when resetting one.
+ */
+static inline void
+msginit(dns_message_t *m) {
+ msginitheader(m);
+ msginitprivate(m);
+ msginittsig(m);
+ m->header_ok = 0;
+ m->question_ok = 0;
+ m->tcp_continuation = 0;
+ m->verified_sig = 0;
+ m->verify_attempted = 0;
+ m->order = NULL;
+ m->order_arg = NULL;
+ m->query.base = NULL;
+ m->query.length = 0;
+ m->free_query = 0;
+ m->saved.base = NULL;
+ m->saved.length = 0;
+ m->free_saved = 0;
+ m->querytsig = NULL;
+}
+
+static inline void
+msgresetnames(dns_message_t *msg, unsigned int first_section) {
+ unsigned int i;
+ dns_name_t *name, *next_name;
+ dns_rdataset_t *rds, *next_rds;
+
+ /*
+ * Clean up name lists by calling the rdataset disassociate function.
+ */
+ for (i = first_section; i < DNS_SECTION_MAX; i++) {
+ name = ISC_LIST_HEAD(msg->sections[i]);
+ while (name != NULL) {
+ next_name = ISC_LIST_NEXT(name, link);
+ ISC_LIST_UNLINK(msg->sections[i], name, link);
+
+ rds = ISC_LIST_HEAD(name->list);
+ while (rds != NULL) {
+ next_rds = ISC_LIST_NEXT(rds, link);
+ ISC_LIST_UNLINK(name->list, rds, link);
+
+ INSIST(dns_rdataset_isassociated(rds));
+ dns_rdataset_disassociate(rds);
+ isc_mempool_put(msg->rdspool, rds);
+ rds = next_rds;
+ }
+ if (dns_name_dynamic(name))
+ dns_name_free(name, msg->mctx);
+ isc_mempool_put(msg->namepool, name);
+ name = next_name;
+ }
+ }
+}
+
+static void
+msgresetopt(dns_message_t *msg)
+{
+ if (msg->opt != NULL) {
+ if (msg->opt_reserved > 0) {
+ dns_message_renderrelease(msg, msg->opt_reserved);
+ msg->opt_reserved = 0;
+ }
+ INSIST(dns_rdataset_isassociated(msg->opt));
+ dns_rdataset_disassociate(msg->opt);
+ isc_mempool_put(msg->rdspool, msg->opt);
+ msg->opt = NULL;
+ }
+}
+
+static void
+msgresetsigs(dns_message_t *msg, isc_boolean_t replying) {
+ if (msg->sig_reserved > 0) {
+ dns_message_renderrelease(msg, msg->sig_reserved);
+ msg->sig_reserved = 0;
+ }
+ if (msg->tsig != NULL) {
+ INSIST(dns_rdataset_isassociated(msg->tsig));
+ INSIST(msg->namepool != NULL);
+ if (replying) {
+ INSIST(msg->querytsig == NULL);
+ msg->querytsig = msg->tsig;
+ } else {
+ dns_rdataset_disassociate(msg->tsig);
+ isc_mempool_put(msg->rdspool, msg->tsig);
+ if (msg->querytsig != NULL) {
+ dns_rdataset_disassociate(msg->querytsig);
+ isc_mempool_put(msg->rdspool, msg->querytsig);
+ }
+ }
+ if (dns_name_dynamic(msg->tsigname))
+ dns_name_free(msg->tsigname, msg->mctx);
+ isc_mempool_put(msg->namepool, msg->tsigname);
+ msg->tsig = NULL;
+ msg->tsigname = NULL;
+ } else if (msg->querytsig != NULL && !replying) {
+ dns_rdataset_disassociate(msg->querytsig);
+ isc_mempool_put(msg->rdspool, msg->querytsig);
+ msg->querytsig = NULL;
+ }
+ if (msg->sig0 != NULL) {
+ INSIST(dns_rdataset_isassociated(msg->sig0));
+ dns_rdataset_disassociate(msg->sig0);
+ isc_mempool_put(msg->rdspool, msg->sig0);
+ if (msg->sig0name != NULL) {
+ if (dns_name_dynamic(msg->sig0name))
+ dns_name_free(msg->sig0name, msg->mctx);
+ isc_mempool_put(msg->namepool, msg->sig0name);
+ }
+ msg->sig0 = NULL;
+ msg->sig0name = NULL;
+ }
+}
+
+/*
+ * Free all but one (or everything) for this message. This is used by
+ * both dns_message_reset() and dns_message_destroy().
+ */
+static void
+msgreset(dns_message_t *msg, isc_boolean_t everything) {
+ dns_msgblock_t *msgblock, *next_msgblock;
+ isc_buffer_t *dynbuf, *next_dynbuf;
+ dns_rdata_t *rdata;
+ dns_rdatalist_t *rdatalist;
+
+ msgresetnames(msg, 0);
+ msgresetopt(msg);
+ msgresetsigs(msg, ISC_FALSE);
+
+ /*
+ * Clean up linked lists.
+ */
+
+ /*
+ * Run through the free lists, and just unlink anything found there.
+ * The memory isn't lost since these are part of message blocks we
+ * have allocated.
+ */
+ rdata = ISC_LIST_HEAD(msg->freerdata);
+ while (rdata != NULL) {
+ ISC_LIST_UNLINK(msg->freerdata, rdata, link);
+ rdata = ISC_LIST_HEAD(msg->freerdata);
+ }
+ rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
+ while (rdatalist != NULL) {
+ ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
+ rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
+ }
+
+ dynbuf = ISC_LIST_HEAD(msg->scratchpad);
+ INSIST(dynbuf != NULL);
+ if (!everything) {
+ isc_buffer_clear(dynbuf);
+ dynbuf = ISC_LIST_NEXT(dynbuf, link);
+ }
+ while (dynbuf != NULL) {
+ next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
+ ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
+ isc_buffer_free(&dynbuf);
+ dynbuf = next_dynbuf;
+ }
+
+ msgblock = ISC_LIST_HEAD(msg->rdatas);
+ if (!everything && msgblock != NULL) {
+ msgblock_reset(msgblock);
+ msgblock = ISC_LIST_NEXT(msgblock, link);
+ }
+ while (msgblock != NULL) {
+ next_msgblock = ISC_LIST_NEXT(msgblock, link);
+ ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
+ msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
+ msgblock = next_msgblock;
+ }
+
+ /*
+ * rdatalists could be empty.
+ */
+
+ msgblock = ISC_LIST_HEAD(msg->rdatalists);
+ if (!everything && msgblock != NULL) {
+ msgblock_reset(msgblock);
+ msgblock = ISC_LIST_NEXT(msgblock, link);
+ }
+ while (msgblock != NULL) {
+ next_msgblock = ISC_LIST_NEXT(msgblock, link);
+ ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
+ msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
+ msgblock = next_msgblock;
+ }
+
+ msgblock = ISC_LIST_HEAD(msg->offsets);
+ if (!everything && msgblock != NULL) {
+ msgblock_reset(msgblock);
+ msgblock = ISC_LIST_NEXT(msgblock, link);
+ }
+ while (msgblock != NULL) {
+ next_msgblock = ISC_LIST_NEXT(msgblock, link);
+ ISC_LIST_UNLINK(msg->offsets, msgblock, link);
+ msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t));
+ msgblock = next_msgblock;
+ }
+
+ if (msg->tsigkey != NULL) {
+ dns_tsigkey_detach(&msg->tsigkey);
+ msg->tsigkey = NULL;
+ }
+
+ if (msg->tsigctx != NULL)
+ dst_context_destroy(&msg->tsigctx);
+
+ if (msg->query.base != NULL) {
+ if (msg->free_query != 0)
+ isc_mem_put(msg->mctx, msg->query.base,
+ msg->query.length);
+ msg->query.base = NULL;
+ msg->query.length = 0;
+ }
+
+ if (msg->saved.base != NULL) {
+ if (msg->free_saved != 0)
+ isc_mem_put(msg->mctx, msg->saved.base,
+ msg->saved.length);
+ msg->saved.base = NULL;
+ msg->saved.length = 0;
+ }
+
+ /*
+ * cleanup the buffer cleanup list
+ */
+ dynbuf = ISC_LIST_HEAD(msg->cleanup);
+ while (dynbuf != NULL) {
+ next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
+ ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
+ isc_buffer_free(&dynbuf);
+ dynbuf = next_dynbuf;
+ }
+
+ /*
+ * Set other bits to normal default values.
+ */
+ if (!everything)
+ msginit(msg);
+
+ ENSURE(isc_mempool_getallocated(msg->namepool) == 0);
+ ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);
+}
+
+static unsigned int
+spacefortsig(dns_tsigkey_t *key, int otherlen) {
+ isc_region_t r1, r2;
+ unsigned int x;
+ isc_result_t result;
+
+ /*
+ * The space required for an TSIG record is:
+ *
+ * n1 bytes for the name
+ * 2 bytes for the type
+ * 2 bytes for the class
+ * 4 bytes for the ttl
+ * 2 bytes for the rdlength
+ * n2 bytes for the algorithm name
+ * 6 bytes for the time signed
+ * 2 bytes for the fudge
+ * 2 bytes for the MAC size
+ * x bytes for the MAC
+ * 2 bytes for the original id
+ * 2 bytes for the error
+ * 2 bytes for the other data length
+ * y bytes for the other data (at most)
+ * ---------------------------------
+ * 26 + n1 + n2 + x + y bytes
+ */
+
+ dns_name_toregion(&key->name, &r1);
+ dns_name_toregion(key->algorithm, &r2);
+ if (key->key == NULL)
+ x = 0;
+ else {
+ result = dst_key_sigsize(key->key, &x);
+ if (result != ISC_R_SUCCESS)
+ x = 0;
+ }
+ return (26 + r1.length + r2.length + x + otherlen);
+}
+
+isc_result_t
+dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
+{
+ dns_message_t *m;
+ isc_result_t result;
+ isc_buffer_t *dynbuf;
+ unsigned int i;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(msgp != NULL);
+ REQUIRE(*msgp == NULL);
+ REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
+ || intent == DNS_MESSAGE_INTENTRENDER);
+
+ m = isc_mem_get(mctx, sizeof(dns_message_t));
+ if (m == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /*
+ * No allocations until further notice. Just initialize all lists
+ * and other members that are freed in the cleanup phase here.
+ */
+
+ m->magic = DNS_MESSAGE_MAGIC;
+ m->from_to_wire = intent;
+ msginit(m);
+
+ for (i = 0; i < DNS_SECTION_MAX; i++)
+ ISC_LIST_INIT(m->sections[i]);
+ m->mctx = mctx;
+
+ ISC_LIST_INIT(m->scratchpad);
+ ISC_LIST_INIT(m->cleanup);
+ m->namepool = NULL;
+ m->rdspool = NULL;
+ ISC_LIST_INIT(m->rdatas);
+ ISC_LIST_INIT(m->rdatalists);
+ ISC_LIST_INIT(m->offsets);
+ ISC_LIST_INIT(m->freerdata);
+ ISC_LIST_INIT(m->freerdatalist);
+
+ /*
+ * Ok, it is safe to allocate (and then "goto cleanup" if failure)
+ */
+
+ result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_mempool_setfreemax(m->namepool, NAME_COUNT);
+ isc_mempool_setname(m->namepool, "msg:names");
+
+ result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
+ &m->rdspool);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
+ isc_mempool_setname(m->rdspool, "msg:rdataset");
+
+ dynbuf = NULL;
+ result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
+
+ m->cctx = NULL;
+
+ *msgp = m;
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Cleanup for error returns.
+ */
+ cleanup:
+ dynbuf = ISC_LIST_HEAD(m->scratchpad);
+ if (dynbuf != NULL) {
+ ISC_LIST_UNLINK(m->scratchpad, dynbuf, link);
+ isc_buffer_free(&dynbuf);
+ }
+ if (m->namepool != NULL)
+ isc_mempool_destroy(&m->namepool);
+ if (m->rdspool != NULL)
+ isc_mempool_destroy(&m->rdspool);
+ m->magic = 0;
+ isc_mem_put(mctx, m, sizeof(dns_message_t));
+
+ return (ISC_R_NOMEMORY);
+}
+
+void
+dns_message_reset(dns_message_t *msg, unsigned int intent) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
+ || intent == DNS_MESSAGE_INTENTRENDER);
+
+ msgreset(msg, ISC_FALSE);
+ msg->from_to_wire = intent;
+}
+
+void
+dns_message_destroy(dns_message_t **msgp) {
+ dns_message_t *msg;
+
+ REQUIRE(msgp != NULL);
+ REQUIRE(DNS_MESSAGE_VALID(*msgp));
+
+ msg = *msgp;
+ *msgp = NULL;
+
+ msgreset(msg, ISC_TRUE);
+ isc_mempool_destroy(&msg->namepool);
+ isc_mempool_destroy(&msg->rdspool);
+ msg->magic = 0;
+ isc_mem_put(msg->mctx, msg, sizeof(dns_message_t));
+}
+
+static isc_result_t
+findname(dns_name_t **foundname, dns_name_t *target,
+ dns_namelist_t *section)
+{
+ dns_name_t *curr;
+
+ for (curr = ISC_LIST_TAIL(*section);
+ curr != NULL;
+ curr = ISC_LIST_PREV(curr, link)) {
+ if (dns_name_equal(curr, target)) {
+ if (foundname != NULL)
+ *foundname = curr;
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ dns_rdataset_t **rdataset)
+{
+ dns_rdataset_t *curr;
+
+ if (rdataset != NULL) {
+ REQUIRE(*rdataset == NULL);
+ }
+
+ for (curr = ISC_LIST_TAIL(name->list);
+ curr != NULL;
+ curr = ISC_LIST_PREV(curr, link)) {
+ if (curr->rdclass == rdclass &&
+ curr->type == type && curr->covers == covers) {
+ if (rdataset != NULL)
+ *rdataset = curr;
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
+ dns_rdatatype_t covers, dns_rdataset_t **rdataset)
+{
+ dns_rdataset_t *curr;
+
+ REQUIRE(name != NULL);
+ if (rdataset != NULL) {
+ REQUIRE(*rdataset == NULL);
+ }
+
+ for (curr = ISC_LIST_TAIL(name->list);
+ curr != NULL;
+ curr = ISC_LIST_PREV(curr, link)) {
+ if (curr->type == type && curr->covers == covers) {
+ if (rdataset != NULL)
+ *rdataset = curr;
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+/*
+ * Read a name from buffer "source".
+ */
+static isc_result_t
+getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
+ dns_decompress_t *dctx)
+{
+ isc_buffer_t *scratch;
+ isc_result_t result;
+ unsigned int tries;
+
+ scratch = currentbuffer(msg);
+
+ /*
+ * First try: use current buffer.
+ * Second try: allocate a new buffer and use that.
+ */
+ tries = 0;
+ while (tries < 2) {
+ result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
+ scratch);
+
+ if (result == ISC_R_NOSPACE) {
+ tries++;
+
+ result = newbuffer(msg, SCRATCHPAD_SIZE);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ scratch = currentbuffer(msg);
+ dns_name_reset(name);
+ } else {
+ return (result);
+ }
+ }
+
+ INSIST(0); /* Cannot get here... */
+ return (ISC_R_UNEXPECTED);
+}
+
+static isc_result_t
+getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
+ dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
+ unsigned int rdatalen, dns_rdata_t *rdata)
+{
+ isc_buffer_t *scratch;
+ isc_result_t result;
+ unsigned int tries;
+ unsigned int trysize;
+
+ scratch = currentbuffer(msg);
+
+ isc_buffer_setactive(source, rdatalen);
+
+ /*
+ * First try: use current buffer.
+ * Second try: allocate a new buffer of size
+ * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
+ * (the data will fit if it was not more than 50% compressed)
+ * Subsequent tries: double buffer size on each try.
+ */
+ tries = 0;
+ trysize = 0;
+ /* XXX possibly change this to a while (tries < 2) loop */
+ for (;;) {
+ result = dns_rdata_fromwire(rdata, rdclass, rdtype,
+ source, dctx, 0,
+ scratch);
+
+ if (result == ISC_R_NOSPACE) {
+ if (tries == 0) {
+ trysize = 2 * rdatalen;
+ if (trysize < SCRATCHPAD_SIZE)
+ trysize = SCRATCHPAD_SIZE;
+ } else {
+ INSIST(trysize != 0);
+ if (trysize >= 65535)
+ return (ISC_R_NOSPACE);
+ /* XXX DNS_R_RRTOOLONG? */
+ trysize *= 2;
+ }
+ tries++;
+ result = newbuffer(msg, trysize);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ scratch = currentbuffer(msg);
+ } else {
+ return (result);
+ }
+ }
+}
+
+#define DO_FORMERR \
+ do { \
+ if (best_effort) \
+ seen_problem = ISC_TRUE; \
+ else { \
+ result = DNS_R_FORMERR; \
+ goto cleanup; \
+ } \
+ } while (0)
+
+static isc_result_t
+getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
+ unsigned int options)
+{
+ isc_region_t r;
+ unsigned int count;
+ dns_name_t *name;
+ dns_name_t *name2;
+ dns_offsets_t *offsets;
+ dns_rdataset_t *rdataset;
+ dns_rdatalist_t *rdatalist;
+ isc_result_t result;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ dns_namelist_t *section;
+ isc_boolean_t free_name;
+ isc_boolean_t best_effort;
+ isc_boolean_t seen_problem;
+
+ section = &msg->sections[DNS_SECTION_QUESTION];
+
+ best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
+ seen_problem = ISC_FALSE;
+
+ name = NULL;
+ rdataset = NULL;
+ rdatalist = NULL;
+
+ for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
+ name = isc_mempool_get(msg->namepool);
+ if (name == NULL)
+ return (ISC_R_NOMEMORY);
+ free_name = ISC_TRUE;
+
+ offsets = newoffsets(msg);
+ if (offsets == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ dns_name_init(name, *offsets);
+
+ /*
+ * Parse the name out of this packet.
+ */
+ isc_buffer_remainingregion(source, &r);
+ isc_buffer_setactive(source, r.length);
+ result = getname(name, source, msg, dctx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * Run through the section, looking to see if this name
+ * is already there. If it is found, put back the allocated
+ * name since we no longer need it, and set our name pointer
+ * to point to the name we found.
+ */
+ result = findname(&name2, name, section);
+
+ /*
+ * If it is the first name in the section, accept it.
+ *
+ * If it is not, but is not the same as the name already
+ * in the question section, append to the section. Note that
+ * here in the question section this is illegal, so return
+ * FORMERR. In the future, check the opcode to see if
+ * this should be legal or not. In either case we no longer
+ * need this name pointer.
+ */
+ if (result != ISC_R_SUCCESS) {
+ if (!ISC_LIST_EMPTY(*section))
+ DO_FORMERR;
+ ISC_LIST_APPEND(*section, name, link);
+ free_name = ISC_FALSE;
+ } else {
+ isc_mempool_put(msg->namepool, name);
+ name = name2;
+ name2 = NULL;
+ free_name = ISC_FALSE;
+ }
+
+ /*
+ * Get type and class.
+ */
+ isc_buffer_remainingregion(source, &r);
+ if (r.length < 4) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto cleanup;
+ }
+ rdtype = isc_buffer_getuint16(source);
+ rdclass = isc_buffer_getuint16(source);
+
+ /*
+ * If this class is different than the one we already read,
+ * this is an error.
+ */
+ if (msg->state == DNS_SECTION_ANY) {
+ msg->state = DNS_SECTION_QUESTION;
+ msg->rdclass = rdclass;
+ } else if (msg->rdclass != rdclass)
+ DO_FORMERR;
+
+ /*
+ * Can't ask the same question twice.
+ */
+ result = dns_message_find(name, rdclass, rdtype, 0, NULL);
+ if (result == ISC_R_SUCCESS)
+ DO_FORMERR;
+
+ /*
+ * Allocate a new rdatalist.
+ */
+ rdatalist = newrdatalist(msg);
+ if (rdatalist == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ rdataset = isc_mempool_get(msg->rdspool);
+ if (rdataset == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ /*
+ * Convert rdatalist to rdataset, and attach the latter to
+ * the name.
+ */
+ rdatalist->type = rdtype;
+ rdatalist->covers = 0;
+ rdatalist->rdclass = rdclass;
+ rdatalist->ttl = 0;
+ ISC_LIST_INIT(rdatalist->rdata);
+
+ dns_rdataset_init(rdataset);
+ result = dns_rdatalist_tordataset(rdatalist, rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
+
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ rdataset = NULL;
+ }
+
+ if (seen_problem)
+ return (DNS_R_RECOVERABLE);
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (rdataset != NULL) {
+ INSIST(!dns_rdataset_isassociated(rdataset));
+ isc_mempool_put(msg->rdspool, rdataset);
+ }
+#if 0
+ if (rdatalist != NULL)
+ isc_mempool_put(msg->rdlpool, rdatalist);
+#endif
+ if (free_name)
+ isc_mempool_put(msg->namepool, name);
+
+ return (result);
+}
+
+static isc_boolean_t
+update(dns_section_t section, dns_rdataclass_t rdclass) {
+ if (section == DNS_SECTION_PREREQUISITE)
+ return (ISC_TF(rdclass == dns_rdataclass_any ||
+ rdclass == dns_rdataclass_none));
+ if (section == DNS_SECTION_UPDATE)
+ return (ISC_TF(rdclass == dns_rdataclass_any));
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
+ dns_section_t sectionid, unsigned int options)
+{
+ isc_region_t r;
+ unsigned int count, rdatalen;
+ dns_name_t *name;
+ dns_name_t *name2;
+ dns_offsets_t *offsets;
+ dns_rdataset_t *rdataset;
+ dns_rdatalist_t *rdatalist;
+ isc_result_t result;
+ dns_rdatatype_t rdtype, covers;
+ dns_rdataclass_t rdclass;
+ dns_rdata_t *rdata;
+ dns_ttl_t ttl;
+ dns_namelist_t *section;
+ isc_boolean_t free_name, free_rdataset;
+ isc_boolean_t preserve_order, best_effort, seen_problem;
+ isc_boolean_t issigzero;
+
+ preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER);
+ best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
+ seen_problem = ISC_FALSE;
+
+ for (count = 0; count < msg->counts[sectionid]; count++) {
+ int recstart = source->current;
+ isc_boolean_t skip_name_search, skip_type_search;
+
+ section = &msg->sections[sectionid];
+
+ skip_name_search = ISC_FALSE;
+ skip_type_search = ISC_FALSE;
+ free_name = ISC_FALSE;
+ free_rdataset = ISC_FALSE;
+
+ name = isc_mempool_get(msg->namepool);
+ if (name == NULL)
+ return (ISC_R_NOMEMORY);
+ free_name = ISC_TRUE;
+
+ offsets = newoffsets(msg);
+ if (offsets == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ dns_name_init(name, *offsets);
+
+ /*
+ * Parse the name out of this packet.
+ */
+ isc_buffer_remainingregion(source, &r);
+ isc_buffer_setactive(source, r.length);
+ result = getname(name, source, msg, dctx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * Get type, class, ttl, and rdatalen. Verify that at least
+ * rdatalen bytes remain. (Some of this is deferred to
+ * later.)
+ */
+ isc_buffer_remainingregion(source, &r);
+ if (r.length < 2 + 2 + 4 + 2) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto cleanup;
+ }
+ rdtype = isc_buffer_getuint16(source);
+ rdclass = isc_buffer_getuint16(source);
+
+ /*
+ * If there was no question section, we may not yet have
+ * established a class. Do so now.
+ */
+ if (msg->state == DNS_SECTION_ANY &&
+ rdtype != dns_rdatatype_opt && /* class is UDP SIZE */
+ rdtype != dns_rdatatype_tsig && /* class is ANY */
+ rdtype != dns_rdatatype_tkey) { /* class is undefined */
+ msg->rdclass = rdclass;
+ msg->state = DNS_SECTION_QUESTION;
+ }
+
+ /*
+ * If this class is different than the one in the question
+ * section, bail.
+ */
+ if (msg->opcode != dns_opcode_update
+ && rdtype != dns_rdatatype_tsig
+ && rdtype != dns_rdatatype_opt
+ && rdtype != dns_rdatatype_dnskey /* in a TKEY query */
+ && rdtype != dns_rdatatype_sig /* SIG(0) */
+ && rdtype != dns_rdatatype_tkey /* Win2000 TKEY */
+ && msg->rdclass != dns_rdataclass_any
+ && msg->rdclass != rdclass)
+ DO_FORMERR;
+
+ /*
+ * Special type handling for TSIG, OPT, and TKEY.
+ */
+ if (rdtype == dns_rdatatype_tsig) {
+ /*
+ * If it is a tsig, verify that it is in the
+ * additional data section.
+ */
+ if (sectionid != DNS_SECTION_ADDITIONAL ||
+ rdclass != dns_rdataclass_any ||
+ count != msg->counts[sectionid] - 1)
+ DO_FORMERR;
+ msg->sigstart = recstart;
+ skip_name_search = ISC_TRUE;
+ skip_type_search = ISC_TRUE;
+ } else if (rdtype == dns_rdatatype_opt) {
+ /*
+ * The name of an OPT record must be ".", it
+ * must be in the additional data section, and
+ * it must be the first OPT we've seen.
+ */
+ if (!dns_name_equal(dns_rootname, name) ||
+ msg->opt != NULL)
+ DO_FORMERR;
+ skip_name_search = ISC_TRUE;
+ skip_type_search = ISC_TRUE;
+ } else if (rdtype == dns_rdatatype_tkey) {
+ /*
+ * A TKEY must be in the additional section if this
+ * is a query, and the answer section if this is a
+ * response. Unless it's a Win2000 client.
+ *
+ * Its class is ignored.
+ */
+ dns_section_t tkeysection;
+
+ if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0)
+ tkeysection = DNS_SECTION_ADDITIONAL;
+ else
+ tkeysection = DNS_SECTION_ANSWER;
+ if (sectionid != tkeysection &&
+ sectionid != DNS_SECTION_ANSWER)
+ DO_FORMERR;
+ }
+
+ /*
+ * ... now get ttl and rdatalen, and check buffer.
+ */
+ ttl = isc_buffer_getuint32(source);
+ rdatalen = isc_buffer_getuint16(source);
+ r.length -= (2 + 2 + 4 + 2);
+ if (r.length < rdatalen) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto cleanup;
+ }
+
+ /*
+ * Read the rdata from the wire format. Interpret the
+ * rdata according to its actual class, even if it had a
+ * DynDNS meta-class in the packet (unless this is a TSIG).
+ * Then put the meta-class back into the finished rdata.
+ */
+ rdata = newrdata(msg);
+ if (rdata == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ if (msg->opcode == dns_opcode_update &&
+ update(sectionid, rdclass)) {
+ if (rdatalen != 0) {
+ result = DNS_R_FORMERR;
+ goto cleanup;
+ }
+ /*
+ * When the rdata is empty, the data pointer is
+ * never dereferenced, but it must still be non-NULL.
+ * Casting 1 rather than "" avoids warnings about
+ * discarding the const attribute of a string,
+ * for compilers that would warn about such things.
+ */
+ rdata->data = (unsigned char *)1;
+ rdata->length = 0;
+ rdata->rdclass = rdclass;
+ rdata->type = rdtype;
+ rdata->flags = DNS_RDATA_UPDATE;
+ result = ISC_R_SUCCESS;
+ } else if (rdclass == dns_rdataclass_none &&
+ msg->opcode == dns_opcode_update &&
+ sectionid == DNS_SECTION_UPDATE) {
+ result = getrdata(source, msg, dctx, msg->rdclass,
+ rdtype, rdatalen, rdata);
+ } else
+ result = getrdata(source, msg, dctx, rdclass,
+ rdtype, rdatalen, rdata);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ rdata->rdclass = rdclass;
+ issigzero = ISC_FALSE;
+ if (rdtype == dns_rdatatype_rrsig &&
+ rdata->flags == 0) {
+ covers = dns_rdata_covers(rdata);
+ if (covers == 0)
+ DO_FORMERR;
+ } else if (rdtype == dns_rdatatype_sig /* SIG(0) */ &&
+ rdata->flags == 0) {
+ covers = dns_rdata_covers(rdata);
+ if (covers == 0) {
+ if (sectionid != DNS_SECTION_ADDITIONAL ||
+ count != msg->counts[sectionid] - 1)
+ DO_FORMERR;
+ msg->sigstart = recstart;
+ skip_name_search = ISC_TRUE;
+ skip_type_search = ISC_TRUE;
+ issigzero = ISC_TRUE;
+ }
+ } else
+ covers = 0;
+
+ /*
+ * If we are doing a dynamic update or this is a meta-type,
+ * don't bother searching for a name, just append this one
+ * to the end of the message.
+ */
+ if (preserve_order || msg->opcode == dns_opcode_update ||
+ skip_name_search) {
+ if (rdtype != dns_rdatatype_opt &&
+ rdtype != dns_rdatatype_tsig &&
+ !issigzero)
+ {
+ ISC_LIST_APPEND(*section, name, link);
+ free_name = ISC_FALSE;
+ }
+ } else {
+ /*
+ * Run through the section, looking to see if this name
+ * is already there. If it is found, put back the
+ * allocated name since we no longer need it, and set
+ * our name pointer to point to the name we found.
+ */
+ result = findname(&name2, name, section);
+
+ /*
+ * If it is a new name, append to the section.
+ */
+ if (result == ISC_R_SUCCESS) {
+ isc_mempool_put(msg->namepool, name);
+ name = name2;
+ } else {
+ ISC_LIST_APPEND(*section, name, link);
+ }
+ free_name = ISC_FALSE;
+ }
+
+ /*
+ * Search name for the particular type and class.
+ * Skip this stage if in update mode or this is a meta-type.
+ */
+ if (preserve_order || msg->opcode == dns_opcode_update ||
+ skip_type_search)
+ result = ISC_R_NOTFOUND;
+ else {
+ /*
+ * If this is a type that can only occur in
+ * the question section, fail.
+ */
+ if (dns_rdatatype_questiononly(rdtype))
+ DO_FORMERR;
+
+ rdataset = NULL;
+ result = dns_message_find(name, rdclass, rdtype,
+ covers, &rdataset);
+ }
+
+ /*
+ * If we found an rdataset that matches, we need to
+ * append this rdata to that set. If we did not, we need
+ * to create a new rdatalist, store the important bits there,
+ * convert it to an rdataset, and link the latter to the name.
+ * Yuck. When appending, make certain that the type isn't
+ * a singleton type, such as SOA or CNAME.
+ *
+ * Note that this check will be bypassed when preserving order,
+ * the opcode is an update, or the type search is skipped.
+ */
+ if (result == ISC_R_SUCCESS) {
+ if (dns_rdatatype_issingleton(rdtype))
+ DO_FORMERR;
+ }
+
+ if (result == ISC_R_NOTFOUND) {
+ rdataset = isc_mempool_get(msg->rdspool);
+ if (rdataset == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ free_rdataset = ISC_TRUE;
+
+ rdatalist = newrdatalist(msg);
+ if (rdatalist == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+
+ rdatalist->type = rdtype;
+ rdatalist->covers = covers;
+ rdatalist->rdclass = rdclass;
+ rdatalist->ttl = ttl;
+ ISC_LIST_INIT(rdatalist->rdata);
+
+ dns_rdataset_init(rdataset);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist,
+ rdataset)
+ == ISC_R_SUCCESS);
+
+ if (rdtype != dns_rdatatype_opt &&
+ rdtype != dns_rdatatype_tsig &&
+ !issigzero)
+ {
+ ISC_LIST_APPEND(name->list, rdataset, link);
+ free_rdataset = ISC_FALSE;
+ }
+ }
+
+ /*
+ * Minimize TTLs.
+ *
+ * Section 5.2 of RFC2181 says we should drop
+ * nonauthoritative rrsets where the TTLs differ, but we
+ * currently treat them the as if they were authoritative and
+ * minimize them.
+ */
+ if (ttl != rdataset->ttl) {
+ rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
+ if (ttl < rdataset->ttl)
+ rdataset->ttl = ttl;
+ }
+
+ /* Append this rdata to the rdataset. */
+ dns_rdatalist_fromrdataset(rdataset, &rdatalist);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+
+ /*
+ * If this is an OPT record, remember it. Also, set
+ * the extended rcode. Note that msg->opt will only be set
+ * if best-effort parsing is enabled.
+ */
+ if (rdtype == dns_rdatatype_opt && msg->opt == NULL) {
+ dns_rcode_t ercode;
+
+ msg->opt = rdataset;
+ rdataset = NULL;
+ free_rdataset = ISC_FALSE;
+ ercode = (dns_rcode_t)
+ ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
+ >> 20);
+ msg->rcode |= ercode;
+ isc_mempool_put(msg->namepool, name);
+ free_name = ISC_FALSE;
+ }
+
+ /*
+ * If this is an SIG(0) or TSIG record, remember it. Note
+ * that msg->sig0 or msg->tsig will only be set if best-effort
+ * parsing is enabled.
+ */
+ if (issigzero && msg->sig0 == NULL) {
+ msg->sig0 = rdataset;
+ msg->sig0name = name;
+ rdataset = NULL;
+ free_rdataset = ISC_FALSE;
+ free_name = ISC_FALSE;
+ } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) {
+ msg->tsig = rdataset;
+ msg->tsigname = name;
+ rdataset = NULL;
+ free_rdataset = ISC_FALSE;
+ free_name = ISC_FALSE;
+ }
+
+ if (seen_problem) {
+ if (free_name)
+ isc_mempool_put(msg->namepool, name);
+ if (free_rdataset)
+ isc_mempool_put(msg->rdspool, rdataset);
+ free_name = free_rdataset = ISC_FALSE;
+ }
+ INSIST(free_name == ISC_FALSE);
+ INSIST(free_rdataset == ISC_FALSE);
+ }
+
+ if (seen_problem)
+ return (DNS_R_RECOVERABLE);
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (free_name)
+ isc_mempool_put(msg->namepool, name);
+ if (free_rdataset)
+ isc_mempool_put(msg->rdspool, rdataset);
+
+ return (result);
+}
+
+isc_result_t
+dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
+ unsigned int options)
+{
+ isc_region_t r;
+ dns_decompress_t dctx;
+ isc_result_t ret;
+ isc_uint16_t tmpflags;
+ isc_buffer_t origsource;
+ isc_boolean_t seen_problem;
+ isc_boolean_t ignore_tc;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(source != NULL);
+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
+
+ seen_problem = ISC_FALSE;
+ ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION);
+
+ origsource = *source;
+
+ msg->header_ok = 0;
+ msg->question_ok = 0;
+
+ isc_buffer_remainingregion(source, &r);
+ if (r.length < DNS_MESSAGE_HEADERLEN)
+ return (ISC_R_UNEXPECTEDEND);
+
+ msg->id = isc_buffer_getuint16(source);
+ tmpflags = isc_buffer_getuint16(source);
+ msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
+ >> DNS_MESSAGE_OPCODE_SHIFT);
+ msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK);
+ msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
+ msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
+ msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
+ msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
+ msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
+
+ msg->header_ok = 1;
+
+ /*
+ * -1 means no EDNS.
+ */
+ dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
+
+ dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
+
+ ret = getquestions(source, msg, &dctx, options);
+ if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
+ goto truncated;
+ if (ret == DNS_R_RECOVERABLE) {
+ seen_problem = ISC_TRUE;
+ ret = ISC_R_SUCCESS;
+ }
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ msg->question_ok = 1;
+
+ ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options);
+ if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
+ goto truncated;
+ if (ret == DNS_R_RECOVERABLE) {
+ seen_problem = ISC_TRUE;
+ ret = ISC_R_SUCCESS;
+ }
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options);
+ if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
+ goto truncated;
+ if (ret == DNS_R_RECOVERABLE) {
+ seen_problem = ISC_TRUE;
+ ret = ISC_R_SUCCESS;
+ }
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options);
+ if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
+ goto truncated;
+ if (ret == DNS_R_RECOVERABLE) {
+ seen_problem = ISC_TRUE;
+ ret = ISC_R_SUCCESS;
+ }
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ isc_buffer_remainingregion(source, &r);
+ if (r.length != 0) {
+ isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
+ "message has %u byte(s) of trailing garbage",
+ r.length);
+ }
+
+ truncated:
+ if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0)
+ isc_buffer_usedregion(&origsource, &msg->saved);
+ else {
+ msg->saved.length = isc_buffer_usedlength(&origsource);
+ msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length);
+ if (msg->saved.base == NULL)
+ return (ISC_R_NOMEMORY);
+ memcpy(msg->saved.base, isc_buffer_base(&origsource),
+ msg->saved.length);
+ msg->free_saved = 1;
+ }
+
+ if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
+ return (DNS_R_RECOVERABLE);
+ if (seen_problem == ISC_TRUE)
+ return (DNS_R_RECOVERABLE);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
+ isc_buffer_t *buffer)
+{
+ isc_region_t r;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(buffer != NULL);
+ REQUIRE(msg->buffer == NULL);
+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
+
+ msg->cctx = cctx;
+
+ /*
+ * Erase the contents of this buffer.
+ */
+ isc_buffer_clear(buffer);
+
+ /*
+ * Make certain there is enough for at least the header in this
+ * buffer.
+ */
+ isc_buffer_availableregion(buffer, &r);
+ if (r.length < DNS_MESSAGE_HEADERLEN)
+ return (ISC_R_NOSPACE);
+
+ if (r.length < msg->reserved)
+ return (ISC_R_NOSPACE);
+
+ /*
+ * Reserve enough space for the header in this buffer.
+ */
+ isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
+
+ msg->buffer = buffer;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
+ isc_region_t r, rn;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(buffer != NULL);
+ REQUIRE(msg->buffer != NULL);
+
+ /*
+ * Ensure that the new buffer is empty, and has enough space to
+ * hold the current contents.
+ */
+ isc_buffer_clear(buffer);
+
+ isc_buffer_availableregion(buffer, &rn);
+ isc_buffer_usedregion(msg->buffer, &r);
+ REQUIRE(rn.length > r.length);
+
+ /*
+ * Copy the contents from the old to the new buffer.
+ */
+ isc_buffer_add(buffer, r.length);
+ memcpy(rn.base, r.base, r.length);
+
+ msg->buffer = buffer;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(space <= msg->reserved);
+
+ msg->reserved -= space;
+}
+
+isc_result_t
+dns_message_renderreserve(dns_message_t *msg, unsigned int space) {
+ isc_region_t r;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+
+ if (msg->buffer != NULL) {
+ isc_buffer_availableregion(msg->buffer, &r);
+ if (r.length < (space + msg->reserved))
+ return (ISC_R_NOSPACE);
+ }
+
+ msg->reserved += space;
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_boolean_t
+wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) {
+ int pass_needed;
+
+ /*
+ * If we are not rendering class IN, this ordering is bogus.
+ */
+ if (rds->rdclass != dns_rdataclass_in)
+ return (ISC_FALSE);
+
+ switch (rds->type) {
+ case dns_rdatatype_a:
+ case dns_rdatatype_aaaa:
+ if (preferred_glue == rds->type)
+ pass_needed = 4;
+ else
+ pass_needed = 3;
+ break;
+ case dns_rdatatype_rrsig:
+ case dns_rdatatype_dnskey:
+ pass_needed = 2;
+ break;
+ default:
+ pass_needed = 1;
+ }
+
+ if (pass_needed >= pass)
+ return (ISC_FALSE);
+
+ return (ISC_TRUE);
+}
+
+isc_result_t
+dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
+ unsigned int options)
+{
+ dns_namelist_t *section;
+ dns_name_t *name, *next_name;
+ dns_rdataset_t *rdataset, *next_rdataset;
+ unsigned int count, total;
+ isc_result_t result;
+ isc_buffer_t st; /* for rollbacks */
+ int pass;
+ isc_boolean_t partial = ISC_FALSE;
+ unsigned int rd_options;
+ dns_rdatatype_t preferred_glue = 0;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(msg->buffer != NULL);
+ REQUIRE(VALID_NAMED_SECTION(sectionid));
+
+ section = &msg->sections[sectionid];
+
+ if ((sectionid == DNS_SECTION_ADDITIONAL)
+ && (options & DNS_MESSAGERENDER_ORDERED) == 0) {
+ if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) {
+ preferred_glue = dns_rdatatype_a;
+ pass = 4;
+ } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) {
+ preferred_glue = dns_rdatatype_aaaa;
+ pass = 4;
+ } else
+ pass = 3;
+ } else
+ pass = 1;
+
+ if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0)
+ rd_options = 0;
+ else
+ rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC;
+
+ /*
+ * Shrink the space in the buffer by the reserved amount.
+ */
+ msg->buffer->length -= msg->reserved;
+
+ total = 0;
+ if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0)
+ partial = ISC_TRUE;
+
+ /*
+ * Render required glue first. Set TC if it won't fit.
+ */
+ name = ISC_LIST_HEAD(*section);
+ if (name != NULL) {
+ rdataset = ISC_LIST_HEAD(name->list);
+ if (rdataset != NULL &&
+ (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 &&
+ (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) {
+ const void *order_arg = msg->order_arg;
+ st = *(msg->buffer);
+ count = 0;
+ if (partial)
+ result = dns_rdataset_towirepartial(rdataset,
+ name,
+ msg->cctx,
+ msg->buffer,
+ msg->order,
+ order_arg,
+ rd_options,
+ &count,
+ NULL);
+ else
+ result = dns_rdataset_towiresorted(rdataset,
+ name,
+ msg->cctx,
+ msg->buffer,
+ msg->order,
+ order_arg,
+ rd_options,
+ &count);
+ total += count;
+ if (partial && result == ISC_R_NOSPACE) {
+ msg->flags |= DNS_MESSAGEFLAG_TC;
+ msg->buffer->length += msg->reserved;
+ msg->counts[sectionid] += total;
+ return (result);
+ }
+ if (result != ISC_R_SUCCESS) {
+ INSIST(st.used < 65536);
+ dns_compress_rollback(msg->cctx,
+ (isc_uint16_t)st.used);
+ *(msg->buffer) = st; /* rollback */
+ msg->buffer->length += msg->reserved;
+ msg->counts[sectionid] += total;
+ return (result);
+ }
+ rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
+ }
+ }
+
+ do {
+ name = ISC_LIST_HEAD(*section);
+ if (name == NULL) {
+ msg->buffer->length += msg->reserved;
+ msg->counts[sectionid] += total;
+ return (ISC_R_SUCCESS);
+ }
+
+ while (name != NULL) {
+ next_name = ISC_LIST_NEXT(name, link);
+
+ rdataset = ISC_LIST_HEAD(name->list);
+ while (rdataset != NULL) {
+ next_rdataset = ISC_LIST_NEXT(rdataset, link);
+
+ if ((rdataset->attributes &
+ DNS_RDATASETATTR_RENDERED) != 0)
+ goto next;
+
+ if (((options & DNS_MESSAGERENDER_ORDERED)
+ == 0)
+ && (sectionid == DNS_SECTION_ADDITIONAL)
+ && wrong_priority(rdataset, pass,
+ preferred_glue))
+ goto next;
+
+ st = *(msg->buffer);
+
+ count = 0;
+ if (partial)
+ result = dns_rdataset_towirepartial(
+ rdataset,
+ name,
+ msg->cctx,
+ msg->buffer,
+ msg->order,
+ msg->order_arg,
+ rd_options,
+ &count,
+ NULL);
+ else
+ result = dns_rdataset_towiresorted(
+ rdataset,
+ name,
+ msg->cctx,
+ msg->buffer,
+ msg->order,
+ msg->order_arg,
+ rd_options,
+ &count);
+
+ total += count;
+
+ /*
+ * If out of space, record stats on what we
+ * rendered so far, and return that status.
+ *
+ * XXXMLG Need to change this when
+ * dns_rdataset_towire() can render partial
+ * sets starting at some arbitary point in the
+ * set. This will include setting a bit in the
+ * rdataset to indicate that a partial
+ * rendering was done, and some state saved
+ * somewhere (probably in the message struct)
+ * to indicate where to continue from.
+ */
+ if (partial && result == ISC_R_NOSPACE) {
+ msg->buffer->length += msg->reserved;
+ msg->counts[sectionid] += total;
+ return (result);
+ }
+ if (result != ISC_R_SUCCESS) {
+ INSIST(st.used < 65536);
+ dns_compress_rollback(msg->cctx,
+ (isc_uint16_t)st.used);
+ *(msg->buffer) = st; /* rollback */
+ msg->buffer->length += msg->reserved;
+ msg->counts[sectionid] += total;
+ return (result);
+ }
+
+ /*
+ * If we have rendered non-validated data,
+ * ensure that the AD bit is not set.
+ */
+ if (rdataset->trust != dns_trust_secure &&
+ (sectionid == DNS_SECTION_ANSWER ||
+ sectionid == DNS_SECTION_AUTHORITY))
+ msg->flags &= ~DNS_MESSAGEFLAG_AD;
+ if (OPTOUT(rdataset))
+ msg->flags &= ~DNS_MESSAGEFLAG_AD;
+
+ rdataset->attributes |=
+ DNS_RDATASETATTR_RENDERED;
+
+ next:
+ rdataset = next_rdataset;
+ }
+
+ name = next_name;
+ }
+ } while (--pass != 0);
+
+ msg->buffer->length += msg->reserved;
+ msg->counts[sectionid] += total;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
+ isc_uint16_t tmp;
+ isc_region_t r;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(target != NULL);
+
+ isc_buffer_availableregion(target, &r);
+ REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
+
+ isc_buffer_putuint16(target, msg->id);
+
+ tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
+ & DNS_MESSAGE_OPCODE_MASK);
+ tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
+ tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
+
+ INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
+ msg->counts[DNS_SECTION_ANSWER] < 65536 &&
+ msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
+ msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
+
+ isc_buffer_putuint16(target, tmp);
+ isc_buffer_putuint16(target,
+ (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
+ isc_buffer_putuint16(target,
+ (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
+ isc_buffer_putuint16(target,
+ (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
+ isc_buffer_putuint16(target,
+ (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
+}
+
+isc_result_t
+dns_message_renderend(dns_message_t *msg) {
+ isc_buffer_t tmpbuf;
+ isc_region_t r;
+ int result;
+ unsigned int count;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(msg->buffer != NULL);
+
+ if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
+ /*
+ * We have an extended rcode but are not using EDNS.
+ */
+ return (DNS_R_FORMERR);
+ }
+
+ /*
+ * If we've got an OPT record, render it.
+ */
+ if (msg->opt != NULL) {
+ dns_message_renderrelease(msg, msg->opt_reserved);
+ msg->opt_reserved = 0;
+ /*
+ * Set the extended rcode.
+ */
+ msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
+ msg->opt->ttl |= ((msg->rcode << 20) &
+ DNS_MESSAGE_EDNSRCODE_MASK);
+ /*
+ * Render.
+ */
+ count = 0;
+ result = dns_rdataset_towire(msg->opt, dns_rootname,
+ msg->cctx, msg->buffer, 0,
+ &count);
+ msg->counts[DNS_SECTION_ADDITIONAL] += count;
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ /*
+ * If we're adding a TSIG or SIG(0) to a truncated message,
+ * clear all rdatasets from the message except for the question
+ * before adding the TSIG or SIG(0). If the question doesn't fit,
+ * don't include it.
+ */
+ if ((msg->tsigkey != NULL || msg->sig0key != NULL) &&
+ (msg->flags & DNS_MESSAGEFLAG_TC) != 0)
+ {
+ isc_buffer_t *buf;
+
+ msgresetnames(msg, DNS_SECTION_ANSWER);
+ buf = msg->buffer;
+ dns_message_renderreset(msg);
+ msg->buffer = buf;
+ isc_buffer_clear(msg->buffer);
+ isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
+ dns_compress_rollback(msg->cctx, 0);
+ result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
+ 0);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
+ return (result);
+ }
+
+ /*
+ * If we're adding a TSIG record, generate and render it.
+ */
+ if (msg->tsigkey != NULL) {
+ dns_message_renderrelease(msg, msg->sig_reserved);
+ msg->sig_reserved = 0;
+ result = dns_tsig_sign(msg);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ count = 0;
+ result = dns_rdataset_towire(msg->tsig, msg->tsigname,
+ msg->cctx, msg->buffer, 0,
+ &count);
+ msg->counts[DNS_SECTION_ADDITIONAL] += count;
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ /*
+ * If we're adding a SIG(0) record, generate and render it.
+ */
+ if (msg->sig0key != NULL) {
+ dns_message_renderrelease(msg, msg->sig_reserved);
+ msg->sig_reserved = 0;
+ result = dns_dnssec_signmessage(msg, msg->sig0key);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ count = 0;
+ /*
+ * Note: dns_rootname is used here, not msg->sig0name, since
+ * the owner name of a SIG(0) is irrelevant, and will not
+ * be set in a message being rendered.
+ */
+ result = dns_rdataset_towire(msg->sig0, dns_rootname,
+ msg->cctx, msg->buffer, 0,
+ &count);
+ msg->counts[DNS_SECTION_ADDITIONAL] += count;
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ isc_buffer_usedregion(msg->buffer, &r);
+ isc_buffer_init(&tmpbuf, r.base, r.length);
+
+ dns_message_renderheader(msg, &tmpbuf);
+
+ msg->buffer = NULL; /* forget about this buffer only on success XXX */
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_message_renderreset(dns_message_t *msg) {
+ unsigned int i;
+ dns_name_t *name;
+ dns_rdataset_t *rds;
+
+ /*
+ * Reset the message so that it may be rendered again.
+ */
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
+
+ msg->buffer = NULL;
+
+ for (i = 0; i < DNS_SECTION_MAX; i++) {
+ msg->cursors[i] = NULL;
+ msg->counts[i] = 0;
+ for (name = ISC_LIST_HEAD(msg->sections[i]);
+ name != NULL;
+ name = ISC_LIST_NEXT(name, link)) {
+ for (rds = ISC_LIST_HEAD(name->list);
+ rds != NULL;
+ rds = ISC_LIST_NEXT(rds, link)) {
+ rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
+ }
+ }
+ }
+ if (msg->tsigname != NULL)
+ dns_message_puttempname(msg, &msg->tsigname);
+ if (msg->tsig != NULL) {
+ dns_rdataset_disassociate(msg->tsig);
+ dns_message_puttemprdataset(msg, &msg->tsig);
+ }
+ if (msg->sig0 != NULL) {
+ dns_rdataset_disassociate(msg->sig0);
+ dns_message_puttemprdataset(msg, &msg->sig0);
+ }
+}
+
+isc_result_t
+dns_message_firstname(dns_message_t *msg, dns_section_t section) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(VALID_NAMED_SECTION(section));
+
+ msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
+
+ if (msg->cursors[section] == NULL)
+ return (ISC_R_NOMORE);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_message_nextname(dns_message_t *msg, dns_section_t section) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(VALID_NAMED_SECTION(section));
+ REQUIRE(msg->cursors[section] != NULL);
+
+ msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
+
+ if (msg->cursors[section] == NULL)
+ return (ISC_R_NOMORE);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_message_currentname(dns_message_t *msg, dns_section_t section,
+ dns_name_t **name)
+{
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(VALID_NAMED_SECTION(section));
+ REQUIRE(name != NULL && *name == NULL);
+ REQUIRE(msg->cursors[section] != NULL);
+
+ *name = msg->cursors[section];
+}
+
+isc_result_t
+dns_message_findname(dns_message_t *msg, dns_section_t section,
+ dns_name_t *target, dns_rdatatype_t type,
+ dns_rdatatype_t covers, dns_name_t **name,
+ dns_rdataset_t **rdataset)
+{
+ dns_name_t *foundname;
+ isc_result_t result;
+
+ /*
+ * XXX These requirements are probably too intensive, especially
+ * where things can be NULL, but as they are they ensure that if
+ * something is NON-NULL, indicating that the caller expects it
+ * to be filled in, that we can in fact fill it in.
+ */
+ REQUIRE(msg != NULL);
+ REQUIRE(VALID_SECTION(section));
+ REQUIRE(target != NULL);
+ if (name != NULL)
+ REQUIRE(*name == NULL);
+ if (type == dns_rdatatype_any) {
+ REQUIRE(rdataset == NULL);
+ } else {
+ if (rdataset != NULL)
+ REQUIRE(*rdataset == NULL);
+ }
+
+ result = findname(&foundname, target,
+ &msg->sections[section]);
+
+ if (result == ISC_R_NOTFOUND)
+ return (DNS_R_NXDOMAIN);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (name != NULL)
+ *name = foundname;
+
+ /*
+ * And now look for the type.
+ */
+ if (type == dns_rdatatype_any)
+ return (ISC_R_SUCCESS);
+
+ result = dns_message_findtype(foundname, type, covers, rdataset);
+ if (result == ISC_R_NOTFOUND)
+ return (DNS_R_NXRRSET);
+
+ return (result);
+}
+
+void
+dns_message_movename(dns_message_t *msg, dns_name_t *name,
+ dns_section_t fromsection,
+ dns_section_t tosection)
+{
+ REQUIRE(msg != NULL);
+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
+ REQUIRE(name != NULL);
+ REQUIRE(VALID_NAMED_SECTION(fromsection));
+ REQUIRE(VALID_NAMED_SECTION(tosection));
+
+ /*
+ * Unlink the name from the old section
+ */
+ ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
+ ISC_LIST_APPEND(msg->sections[tosection], name, link);
+}
+
+void
+dns_message_addname(dns_message_t *msg, dns_name_t *name,
+ dns_section_t section)
+{
+ REQUIRE(msg != NULL);
+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
+ REQUIRE(name != NULL);
+ REQUIRE(VALID_NAMED_SECTION(section));
+
+ ISC_LIST_APPEND(msg->sections[section], name, link);
+}
+
+void
+dns_message_removename(dns_message_t *msg, dns_name_t *name,
+ dns_section_t section)
+{
+ REQUIRE(msg != NULL);
+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
+ REQUIRE(name != NULL);
+ REQUIRE(VALID_NAMED_SECTION(section));
+
+ ISC_LIST_UNLINK(msg->sections[section], name, link);
+}
+
+isc_result_t
+dns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(item != NULL && *item == NULL);
+
+ *item = isc_mempool_get(msg->namepool);
+ if (*item == NULL)
+ return (ISC_R_NOMEMORY);
+ dns_name_init(*item, NULL);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(item != NULL && *item == NULL);
+
+ *item = newoffsets(msg);
+ if (*item == NULL)
+ return (ISC_R_NOMEMORY);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(item != NULL && *item == NULL);
+
+ *item = newrdata(msg);
+ if (*item == NULL)
+ return (ISC_R_NOMEMORY);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(item != NULL && *item == NULL);
+
+ *item = isc_mempool_get(msg->rdspool);
+ if (*item == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dns_rdataset_init(*item);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(item != NULL && *item == NULL);
+
+ *item = newrdatalist(msg);
+ if (*item == NULL)
+ return (ISC_R_NOMEMORY);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_message_puttempname(dns_message_t *msg, dns_name_t **item) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(item != NULL && *item != NULL);
+
+ if (dns_name_dynamic(*item))
+ dns_name_free(*item, msg->mctx);
+ isc_mempool_put(msg->namepool, *item);
+ *item = NULL;
+}
+
+void
+dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(item != NULL && *item != NULL);
+
+ releaserdata(msg, *item);
+ *item = NULL;
+}
+
+void
+dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(item != NULL && *item != NULL);
+
+ REQUIRE(!dns_rdataset_isassociated(*item));
+ isc_mempool_put(msg->rdspool, *item);
+ *item = NULL;
+}
+
+void
+dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(item != NULL && *item != NULL);
+
+ releaserdatalist(msg, *item);
+ *item = NULL;
+}
+
+isc_result_t
+dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
+ unsigned int *flagsp)
+{
+ isc_region_t r;
+ isc_buffer_t buffer;
+ dns_messageid_t id;
+ unsigned int flags;
+
+ REQUIRE(source != NULL);
+
+ buffer = *source;
+
+ isc_buffer_remainingregion(&buffer, &r);
+ if (r.length < DNS_MESSAGE_HEADERLEN)
+ return (ISC_R_UNEXPECTEDEND);
+
+ id = isc_buffer_getuint16(&buffer);
+ flags = isc_buffer_getuint16(&buffer);
+ flags &= DNS_MESSAGE_FLAG_MASK;
+
+ if (flagsp != NULL)
+ *flagsp = flags;
+ if (idp != NULL)
+ *idp = id;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
+ unsigned int first_section;
+ isc_result_t result;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
+
+ if (!msg->header_ok)
+ return (DNS_R_FORMERR);
+ if (msg->opcode != dns_opcode_query &&
+ msg->opcode != dns_opcode_notify)
+ want_question_section = ISC_FALSE;
+ if (want_question_section) {
+ if (!msg->question_ok)
+ return (DNS_R_FORMERR);
+ first_section = DNS_SECTION_ANSWER;
+ } else
+ first_section = DNS_SECTION_QUESTION;
+ msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
+ msgresetnames(msg, first_section);
+ msgresetopt(msg);
+ msgresetsigs(msg, ISC_TRUE);
+ msginitprivate(msg);
+ /*
+ * We now clear most flags and then set QR, ensuring that the
+ * reply's flags will be in a reasonable state.
+ */
+ msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
+ msg->flags |= DNS_MESSAGEFLAG_QR;
+
+ /*
+ * This saves the query TSIG status, if the query was signed, and
+ * reserves space in the reply for the TSIG.
+ */
+ if (msg->tsigkey != NULL) {
+ unsigned int otherlen = 0;
+ msg->querytsigstatus = msg->tsigstatus;
+ msg->tsigstatus = dns_rcode_noerror;
+ if (msg->querytsigstatus == dns_tsigerror_badtime)
+ otherlen = 6;
+ msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
+ result = dns_message_renderreserve(msg, msg->sig_reserved);
+ if (result != ISC_R_SUCCESS) {
+ msg->sig_reserved = 0;
+ return (result);
+ }
+ }
+ if (msg->saved.base != NULL) {
+ msg->query.base = msg->saved.base;
+ msg->query.length = msg->saved.length;
+ msg->free_query = msg->free_saved;
+ msg->saved.base = NULL;
+ msg->saved.length = 0;
+ msg->free_saved = 0;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+dns_rdataset_t *
+dns_message_getopt(dns_message_t *msg) {
+
+ /*
+ * Get the OPT record for 'msg'.
+ */
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+
+ return (msg->opt);
+}
+
+isc_result_t
+dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ /*
+ * Set the OPT record for 'msg'.
+ */
+
+ /*
+ * The space required for an OPT record is:
+ *
+ * 1 byte for the name
+ * 2 bytes for the type
+ * 2 bytes for the class
+ * 4 bytes for the ttl
+ * 2 bytes for the rdata length
+ * ---------------------------------
+ * 11 bytes
+ *
+ * plus the length of the rdata.
+ */
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(opt->type == dns_rdatatype_opt);
+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
+ REQUIRE(msg->state == DNS_SECTION_ANY);
+
+ msgresetopt(msg);
+
+ result = dns_rdataset_first(opt);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdataset_current(opt, &rdata);
+ msg->opt_reserved = 11 + rdata.length;
+ result = dns_message_renderreserve(msg, msg->opt_reserved);
+ if (result != ISC_R_SUCCESS) {
+ msg->opt_reserved = 0;
+ goto cleanup;
+ }
+
+ msg->opt = opt;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_message_puttemprdataset(msg, &opt);
+ return (result);
+
+}
+
+dns_rdataset_t *
+dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {
+
+ /*
+ * Get the TSIG record and owner for 'msg'.
+ */
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(owner == NULL || *owner == NULL);
+
+ if (owner != NULL)
+ *owner = msg->tsigname;
+ return (msg->tsig);
+}
+
+isc_result_t
+dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
+ isc_result_t result;
+
+ /*
+ * Set the TSIG key for 'msg'
+ */
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(msg->state == DNS_SECTION_ANY);
+
+ if (key == NULL && msg->tsigkey != NULL) {
+ if (msg->sig_reserved != 0) {
+ dns_message_renderrelease(msg, msg->sig_reserved);
+ msg->sig_reserved = 0;
+ }
+ dns_tsigkey_detach(&msg->tsigkey);
+ }
+ if (key != NULL) {
+ REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
+ dns_tsigkey_attach(key, &msg->tsigkey);
+ if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
+ msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
+ result = dns_message_renderreserve(msg,
+ msg->sig_reserved);
+ if (result != ISC_R_SUCCESS) {
+ dns_tsigkey_detach(&msg->tsigkey);
+ msg->sig_reserved = 0;
+ return (result);
+ }
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+dns_tsigkey_t *
+dns_message_gettsigkey(dns_message_t *msg) {
+
+ /*
+ * Get the TSIG key for 'msg'
+ */
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+
+ return (msg->tsigkey);
+}
+
+isc_result_t
+dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
+ dns_rdata_t *rdata = NULL;
+ dns_rdatalist_t *list = NULL;
+ dns_rdataset_t *set = NULL;
+ isc_buffer_t *buf = NULL;
+ isc_region_t r;
+ isc_result_t result;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(msg->querytsig == NULL);
+
+ if (querytsig == NULL)
+ return (ISC_R_SUCCESS);
+
+ result = dns_message_gettemprdata(msg, &rdata);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_message_gettemprdatalist(msg, &list);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_gettemprdataset(msg, &set);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ isc_buffer_usedregion(querytsig, &r);
+ result = isc_buffer_allocate(msg->mctx, &buf, r.length);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ isc_buffer_putmem(buf, r.base, r.length);
+ isc_buffer_usedregion(buf, &r);
+ dns_rdata_init(rdata);
+ dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
+ dns_message_takebuffer(msg, &buf);
+ ISC_LIST_INIT(list->rdata);
+ ISC_LIST_APPEND(list->rdata, rdata, link);
+ result = dns_rdatalist_tordataset(list, set);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ msg->querytsig = set;
+
+ return (result);
+
+ cleanup:
+ if (rdata != NULL)
+ dns_message_puttemprdata(msg, &rdata);
+ if (list != NULL)
+ dns_message_puttemprdatalist(msg, &list);
+ if (set != NULL)
+ dns_message_puttemprdataset(msg, &set);
+ return (ISC_R_NOMEMORY);
+}
+
+isc_result_t
+dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
+ isc_buffer_t **querytsig) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t r;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(mctx != NULL);
+ REQUIRE(querytsig != NULL && *querytsig == NULL);
+
+ if (msg->tsig == NULL)
+ return (ISC_R_SUCCESS);
+
+ result = dns_rdataset_first(msg->tsig);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_current(msg->tsig, &rdata);
+ dns_rdata_toregion(&rdata, &r);
+
+ result = isc_buffer_allocate(mctx, querytsig, r.length);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_putmem(*querytsig, r.base, r.length);
+ return (ISC_R_SUCCESS);
+}
+
+dns_rdataset_t *
+dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) {
+
+ /*
+ * Get the SIG(0) record for 'msg'.
+ */
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(owner == NULL || *owner == NULL);
+
+ if (msg->sig0 != NULL && owner != NULL) {
+ /* If dns_message_getsig0 is called on a rendered message
+ * after the SIG(0) has been applied, we need to return the
+ * root name, not NULL.
+ */
+ if (msg->sig0name == NULL)
+ *owner = dns_rootname;
+ else
+ *owner = msg->sig0name;
+ }
+ return (msg->sig0);
+}
+
+isc_result_t
+dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
+ isc_region_t r;
+ unsigned int x;
+ isc_result_t result;
+
+ /*
+ * Set the SIG(0) key for 'msg'
+ */
+
+ /*
+ * The space required for an SIG(0) record is:
+ *
+ * 1 byte for the name
+ * 2 bytes for the type
+ * 2 bytes for the class
+ * 4 bytes for the ttl
+ * 2 bytes for the type covered
+ * 1 byte for the algorithm
+ * 1 bytes for the labels
+ * 4 bytes for the original ttl
+ * 4 bytes for the signature expiration
+ * 4 bytes for the signature inception
+ * 2 bytes for the key tag
+ * n bytes for the signer's name
+ * x bytes for the signature
+ * ---------------------------------
+ * 27 + n + x bytes
+ */
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
+ REQUIRE(msg->state == DNS_SECTION_ANY);
+
+ if (key != NULL) {
+ REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL);
+ dns_name_toregion(dst_key_name(key), &r);
+ result = dst_key_sigsize(key, &x);
+ if (result != ISC_R_SUCCESS) {
+ msg->sig_reserved = 0;
+ return (result);
+ }
+ msg->sig_reserved = 27 + r.length + x;
+ result = dns_message_renderreserve(msg, msg->sig_reserved);
+ if (result != ISC_R_SUCCESS) {
+ msg->sig_reserved = 0;
+ return (result);
+ }
+ msg->sig0key = key;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+dst_key_t *
+dns_message_getsig0key(dns_message_t *msg) {
+
+ /*
+ * Get the SIG(0) key for 'msg'
+ */
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+
+ return (msg->sig0key);
+}
+
+void
+dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(buffer != NULL);
+ REQUIRE(ISC_BUFFER_VALID(*buffer));
+
+ ISC_LIST_APPEND(msg->cleanup, *buffer, link);
+ *buffer = NULL;
+}
+
+isc_result_t
+dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(signer != NULL);
+ REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
+
+ if (msg->tsig == NULL && msg->sig0 == NULL)
+ return (ISC_R_NOTFOUND);
+
+ if (msg->verify_attempted == 0)
+ return (DNS_R_NOTVERIFIEDYET);
+
+ if (!dns_name_hasbuffer(signer)) {
+ isc_buffer_t *dynbuf = NULL;
+ result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_name_setbuffer(signer, dynbuf);
+ dns_message_takebuffer(msg, &dynbuf);
+ }
+
+ if (msg->sig0 != NULL) {
+ dns_rdata_sig_t sig;
+
+ result = dns_rdataset_first(msg->sig0);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdataset_current(msg->sig0, &rdata);
+
+ result = dns_rdata_tostruct(&rdata, &sig, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
+ result = ISC_R_SUCCESS;
+ else
+ result = DNS_R_SIGINVALID;
+ dns_name_clone(&sig.signer, signer);
+ dns_rdata_freestruct(&sig);
+ } else {
+ dns_name_t *identity;
+ dns_rdata_any_tsig_t tsig;
+
+ result = dns_rdataset_first(msg->tsig);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdataset_current(msg->tsig, &rdata);
+
+ result = dns_rdata_tostruct(&rdata, &tsig, NULL);
+ if (msg->tsigstatus != dns_rcode_noerror)
+ result = DNS_R_TSIGVERIFYFAILURE;
+ else if (tsig.error != dns_rcode_noerror)
+ result = DNS_R_TSIGERRORSET;
+ else
+ result = ISC_R_SUCCESS;
+ dns_rdata_freestruct(&tsig);
+
+ if (msg->tsigkey == NULL) {
+ /*
+ * If msg->tsigstatus & tsig.error are both
+ * dns_rcode_noerror, the message must have been
+ * verified, which means msg->tsigkey will be
+ * non-NULL.
+ */
+ INSIST(result != ISC_R_SUCCESS);
+ } else {
+ identity = dns_tsigkey_identity(msg->tsigkey);
+ if (identity == NULL) {
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_NOIDENTITY;
+ identity = &msg->tsigkey->name;
+ }
+ dns_name_clone(identity, signer);
+ }
+ }
+
+ return (result);
+}
+
+void
+dns_message_resetsig(dns_message_t *msg) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ msg->verified_sig = 0;
+ msg->verify_attempted = 0;
+ msg->tsigstatus = dns_rcode_noerror;
+ msg->sig0status = dns_rcode_noerror;
+ msg->timeadjust = 0;
+ if (msg->tsigkey != NULL) {
+ dns_tsigkey_detach(&msg->tsigkey);
+ msg->tsigkey = NULL;
+ }
+}
+
+isc_result_t
+dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) {
+ dns_message_resetsig(msg);
+ return (dns_message_checksig(msg, view));
+}
+
+#ifdef SKAN_MSG_DEBUG
+void
+dns_message_dumpsig(dns_message_t *msg, char *txt1) {
+ dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
+ dns_rdata_any_tsig_t querytsig;
+ isc_result_t result;
+
+ if (msg->tsig != NULL) {
+ result = dns_rdataset_first(msg->tsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(msg->tsig, &querytsigrdata);
+ result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ hexdump(txt1, "TSIG", querytsig.signature,
+ querytsig.siglen);
+ }
+
+ if (msg->querytsig != NULL) {
+ result = dns_rdataset_first(msg->querytsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdataset_current(msg->querytsig, &querytsigrdata);
+ result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ hexdump(txt1, "QUERYTSIG", querytsig.signature,
+ querytsig.siglen);
+ }
+}
+#endif
+
+isc_result_t
+dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
+ isc_buffer_t b, msgb;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+
+ if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
+ return (ISC_R_SUCCESS);
+
+ INSIST(msg->saved.base != NULL);
+ isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
+ isc_buffer_add(&msgb, msg->saved.length);
+ if (msg->tsigkey != NULL || msg->tsig != NULL) {
+#ifdef SKAN_MSG_DEBUG
+ dns_message_dumpsig(msg, "dns_message_checksig#1");
+#endif
+ if (view != NULL)
+ return (dns_view_checksig(view, &msgb, msg));
+ else
+ return (dns_tsig_verify(&msgb, msg, NULL, NULL));
+ } else {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_sig_t sig;
+ dns_rdataset_t keyset;
+ isc_result_t result;
+
+ result = dns_rdataset_first(msg->sig0);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdataset_current(msg->sig0, &rdata);
+
+ /*
+ * This can occur when the message is a dynamic update, since
+ * the rdata length checking is relaxed. This should not
+ * happen in a well-formed message, since the SIG(0) is only
+ * looked for in the additional section, and the dynamic update
+ * meta-records are in the prerequisite and update sections.
+ */
+ if (rdata.length == 0)
+ return (ISC_R_UNEXPECTEDEND);
+
+ result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_rdataset_init(&keyset);
+ if (view == NULL)
+ return (DNS_R_KEYUNAUTHORIZED);
+ result = dns_view_simplefind(view, &sig.signer,
+ dns_rdatatype_key /* SIG(0) */,
+ 0, 0, ISC_FALSE, &keyset, NULL);
+
+ if (result != ISC_R_SUCCESS) {
+ /* XXXBEW Should possibly create a fetch here */
+ result = DNS_R_KEYUNAUTHORIZED;
+ goto freesig;
+ } else if (keyset.trust < dns_trust_secure) {
+ /* XXXBEW Should call a validator here */
+ result = DNS_R_KEYUNAUTHORIZED;
+ goto freesig;
+ }
+ result = dns_rdataset_first(&keyset);
+ INSIST(result == ISC_R_SUCCESS);
+ for (;
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&keyset))
+ {
+ dst_key_t *key = NULL;
+
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&keyset, &rdata);
+ isc_buffer_init(&b, rdata.data, rdata.length);
+ isc_buffer_add(&b, rdata.length);
+
+ result = dst_key_fromdns(&sig.signer, rdata.rdclass,
+ &b, view->mctx, &key);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if (dst_key_alg(key) != sig.algorithm ||
+ dst_key_id(key) != sig.keyid ||
+ !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
+ dst_key_proto(key) == DNS_KEYPROTO_ANY))
+ {
+ dst_key_free(&key);
+ continue;
+ }
+ result = dns_dnssec_verifymessage(&msgb, msg, key);
+ dst_key_free(&key);
+ if (result == ISC_R_SUCCESS)
+ break;
+ }
+ if (result == ISC_R_NOMORE)
+ result = DNS_R_KEYUNAUTHORIZED;
+
+ freesig:
+ if (dns_rdataset_isassociated(&keyset))
+ dns_rdataset_disassociate(&keyset);
+ dns_rdata_freestruct(&sig);
+ return (result);
+ }
+}
+
+isc_result_t
+dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
+ const dns_master_style_t *style,
+ dns_messagetextflag_t flags,
+ isc_buffer_t *target) {
+ dns_name_t *name, empty_name;
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(target != NULL);
+ REQUIRE(VALID_SECTION(section));
+
+ if (ISC_LIST_EMPTY(msg->sections[section]))
+ return (ISC_R_SUCCESS);
+
+ if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
+ ADD_STRING(target, ";; ");
+ if (msg->opcode != dns_opcode_update) {
+ ADD_STRING(target, sectiontext[section]);
+ } else {
+ ADD_STRING(target, updsectiontext[section]);
+ }
+ ADD_STRING(target, " SECTION:\n");
+ }
+
+ dns_name_init(&empty_name, NULL);
+ result = dns_message_firstname(msg, section);
+ if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ do {
+ name = NULL;
+ dns_message_currentname(msg, section, &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (section == DNS_SECTION_QUESTION) {
+ ADD_STRING(target, ";");
+ result = dns_master_questiontotext(name,
+ rdataset,
+ style,
+ target);
+ } else {
+ result = dns_master_rdatasettotext(name,
+ rdataset,
+ style,
+ target);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ result = dns_message_nextname(msg, section);
+ } while (result == ISC_R_SUCCESS);
+ if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
+ (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
+ ADD_STRING(target, "\n");
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
+isc_result_t
+dns_message_pseudosectiontotext(dns_message_t *msg,
+ dns_pseudosection_t section,
+ const dns_master_style_t *style,
+ dns_messagetextflag_t flags,
+ isc_buffer_t *target) {
+ dns_rdataset_t *ps = NULL;
+ dns_name_t *name = NULL;
+ isc_result_t result;
+ char buf[sizeof("1234567890")];
+ isc_uint32_t mbz;
+ dns_rdata_t rdata;
+ isc_buffer_t optbuf;
+ isc_uint16_t optcode, optlen;
+ unsigned char *optdata;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(target != NULL);
+ REQUIRE(VALID_PSEUDOSECTION(section));
+
+ switch (section) {
+ case DNS_PSEUDOSECTION_OPT:
+ ps = dns_message_getopt(msg);
+ if (ps == NULL)
+ return (ISC_R_SUCCESS);
+ if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
+ ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
+ ADD_STRING(target, "; EDNS: version: ");
+ snprintf(buf, sizeof(buf), "%u",
+ (unsigned int)((ps->ttl & 0x00ff0000) >> 16));
+ ADD_STRING(target, buf);
+ ADD_STRING(target, ", flags:");
+ if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0)
+ ADD_STRING(target, " do");
+ mbz = ps->ttl & ~DNS_MESSAGEEXTFLAG_DO & 0xffff;
+ if (mbz != 0) {
+ ADD_STRING(target, "; MBZ: ");
+ snprintf(buf, sizeof(buf), "%.4x ", mbz);
+ ADD_STRING(target, buf);
+ ADD_STRING(target, ", udp: ");
+ } else
+ ADD_STRING(target, "; udp: ");
+ snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
+ ADD_STRING(target, buf);
+
+ result = dns_rdataset_first(ps);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_SUCCESS);
+
+ /* Print EDNS info, if any */
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(ps, &rdata);
+ if (rdata.length < 4)
+ return (ISC_R_SUCCESS);
+
+ isc_buffer_init(&optbuf, rdata.data, rdata.length);
+ isc_buffer_add(&optbuf, rdata.length);
+ optcode = isc_buffer_getuint16(&optbuf);
+ optlen = isc_buffer_getuint16(&optbuf);
+
+ if (optcode == DNS_OPT_NSID) {
+ ADD_STRING(target, "; NSID");
+ } else {
+ ADD_STRING(target, "; OPT=");
+ sprintf(buf, "%u", optcode);
+ ADD_STRING(target, buf);
+ }
+
+ if (optlen != 0) {
+ int i;
+ ADD_STRING(target, ": ");
+
+ optdata = rdata.data + 4;
+ for (i = 0; i < optlen; i++) {
+ sprintf(buf, "%02x ", optdata[i]);
+ ADD_STRING(target, buf);
+ }
+ for (i = 0; i < optlen; i++) {
+ ADD_STRING(target, " (");
+ if (isprint(optdata[i]))
+ isc_buffer_putmem(target, &optdata[i],
+ 1);
+ else
+ isc_buffer_putstr(target, ".");
+ ADD_STRING(target, ")");
+ }
+ }
+ ADD_STRING(target, "\n");
+ return (ISC_R_SUCCESS);
+ case DNS_PSEUDOSECTION_TSIG:
+ ps = dns_message_gettsig(msg, &name);
+ if (ps == NULL)
+ return (ISC_R_SUCCESS);
+ if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
+ ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
+ result = dns_master_rdatasettotext(name, ps, style, target);
+ if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
+ (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
+ ADD_STRING(target, "\n");
+ return (result);
+ case DNS_PSEUDOSECTION_SIG0:
+ ps = dns_message_getsig0(msg, &name);
+ if (ps == NULL)
+ return (ISC_R_SUCCESS);
+ if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
+ ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
+ result = dns_master_rdatasettotext(name, ps, style, target);
+ if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
+ (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
+ ADD_STRING(target, "\n");
+ return (result);
+ }
+ return (ISC_R_UNEXPECTED);
+}
+
+isc_result_t
+dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
+ dns_messagetextflag_t flags, isc_buffer_t *target) {
+ char buf[sizeof("1234567890")];
+ isc_result_t result;
+
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ REQUIRE(target != NULL);
+
+ if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) {
+ ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
+ ADD_STRING(target, opcodetext[msg->opcode]);
+ ADD_STRING(target, ", status: ");
+ if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
+ ADD_STRING(target, rcodetext[msg->rcode]);
+ } else {
+ snprintf(buf, sizeof(buf), "%4u", msg->rcode);
+ ADD_STRING(target, buf);
+ }
+ ADD_STRING(target, ", id: ");
+ snprintf(buf, sizeof(buf), "%6u", msg->id);
+ ADD_STRING(target, buf);
+ ADD_STRING(target, "\n;; flags: ");
+ if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
+ ADD_STRING(target, "qr ");
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
+ ADD_STRING(target, "aa ");
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
+ ADD_STRING(target, "tc ");
+ if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
+ ADD_STRING(target, "rd ");
+ if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
+ ADD_STRING(target, "ra ");
+ if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
+ ADD_STRING(target, "ad ");
+ if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
+ ADD_STRING(target, "cd ");
+ if (msg->opcode != dns_opcode_update) {
+ ADD_STRING(target, "; QUESTION: ");
+ } else {
+ ADD_STRING(target, "; ZONE: ");
+ }
+ snprintf(buf, sizeof(buf), "%1u",
+ msg->counts[DNS_SECTION_QUESTION]);
+ ADD_STRING(target, buf);
+ if (msg->opcode != dns_opcode_update) {
+ ADD_STRING(target, ", ANSWER: ");
+ } else {
+ ADD_STRING(target, ", PREREQ: ");
+ }
+ snprintf(buf, sizeof(buf), "%1u",
+ msg->counts[DNS_SECTION_ANSWER]);
+ ADD_STRING(target, buf);
+ if (msg->opcode != dns_opcode_update) {
+ ADD_STRING(target, ", AUTHORITY: ");
+ } else {
+ ADD_STRING(target, ", UPDATE: ");
+ }
+ snprintf(buf, sizeof(buf), "%1u",
+ msg->counts[DNS_SECTION_AUTHORITY]);
+ ADD_STRING(target, buf);
+ ADD_STRING(target, ", ADDITIONAL: ");
+ snprintf(buf, sizeof(buf), "%1u",
+ msg->counts[DNS_SECTION_ADDITIONAL]);
+ ADD_STRING(target, buf);
+ ADD_STRING(target, "\n");
+ }
+ result = dns_message_pseudosectiontotext(msg,
+ DNS_PSEUDOSECTION_OPT,
+ style, flags, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
+ style, flags, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
+ style, flags, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
+ style, flags, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL,
+ style, flags, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_message_pseudosectiontotext(msg,
+ DNS_PSEUDOSECTION_TSIG,
+ style, flags, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_message_pseudosectiontotext(msg,
+ DNS_PSEUDOSECTION_SIG0,
+ style, flags, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_region_t *
+dns_message_getrawmessage(dns_message_t *msg) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ return (&msg->saved);
+}
+
+void
+dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
+ const void *order_arg)
+{
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ msg->order = order;
+ msg->order_arg = order_arg;
+}
+
+void
+dns_message_settimeadjust(dns_message_t *msg, int timeadjust) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ msg->timeadjust = timeadjust;
+}
+
+int
+dns_message_gettimeadjust(dns_message_t *msg) {
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ return (msg->timeadjust);
+}
+
+isc_result_t
+dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) {
+
+ REQUIRE(opcode < 16);
+
+ if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode]))
+ return (ISC_R_NOSPACE);
+ isc_buffer_putstr(target, opcodetext[opcode]);
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/dns/name.c b/lib/dns/name.c
new file mode 100644
index 0000000..f4ea3e9
--- /dev/null
+++ b/lib/dns/name.c
@@ -0,0 +1,2408 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: name.c,v 1.165 2008/04/01 23:47:10 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+
+#include <dns/compress.h>
+#include <dns/name.h>
+#include <dns/result.h>
+
+#define VALID_NAME(n) ISC_MAGIC_VALID(n, DNS_NAME_MAGIC)
+
+typedef enum {
+ ft_init = 0,
+ ft_start,
+ ft_ordinary,
+ ft_initialescape,
+ ft_escape,
+ ft_escdecimal,
+ ft_at
+} ft_state;
+
+typedef enum {
+ fw_start = 0,
+ fw_ordinary,
+ fw_copy,
+ fw_newcurrent
+} fw_state;
+
+static char digitvalue[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
+};
+
+static unsigned char maptolower[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+#define CONVERTTOASCII(c)
+#define CONVERTFROMASCII(c)
+
+#define INIT_OFFSETS(name, var, default) \
+ if (name->offsets != NULL) \
+ var = name->offsets; \
+ else \
+ var = default;
+
+#define SETUP_OFFSETS(name, var, default) \
+ if (name->offsets != NULL) \
+ var = name->offsets; \
+ else { \
+ var = default; \
+ set_offsets(name, var, NULL); \
+ }
+
+/*%
+ * Note: If additional attributes are added that should not be set for
+ * empty names, MAKE_EMPTY() must be changed so it clears them.
+ */
+#define MAKE_EMPTY(name) \
+do { \
+ name->ndata = NULL; \
+ name->length = 0; \
+ name->labels = 0; \
+ name->attributes &= ~DNS_NAMEATTR_ABSOLUTE; \
+} while (0);
+
+/*%
+ * A name is "bindable" if it can be set to point to a new value, i.e.
+ * name->ndata and name->length may be changed.
+ */
+#define BINDABLE(name) \
+ ((name->attributes & (DNS_NAMEATTR_READONLY|DNS_NAMEATTR_DYNAMIC)) \
+ == 0)
+
+/*%
+ * Note that the name data must be a char array, not a string
+ * literal, to avoid compiler warnings about discarding
+ * the const attribute of a string.
+ */
+static unsigned char root_ndata[] = { '\0' };
+static unsigned char root_offsets[] = { 0 };
+
+static dns_name_t root =
+{
+ DNS_NAME_MAGIC,
+ root_ndata, 1, 1,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ root_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+/* XXXDCL make const? */
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_rootname = &root;
+
+static unsigned char wild_ndata[] = { '\001', '*' };
+static unsigned char wild_offsets[] = { 0 };
+
+static dns_name_t wild =
+{
+ DNS_NAME_MAGIC,
+ wild_ndata, 2, 1,
+ DNS_NAMEATTR_READONLY,
+ wild_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+/* XXXDCL make const? */
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_wildcardname = &wild;
+
+unsigned int
+dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive);
+
+/*
+ * dns_name_t to text post-conversion procedure.
+ */
+#ifdef ISC_PLATFORM_USETHREADS
+static int thread_key_initialized = 0;
+static isc_mutex_t thread_key_mutex;
+static isc_mem_t *thread_key_mctx = NULL;
+static isc_thread_key_t totext_filter_proc_key;
+static isc_once_t once = ISC_ONCE_INIT;
+#else
+static dns_name_totextfilter_t totext_filter_proc = NULL;
+#endif
+
+static void
+set_offsets(const dns_name_t *name, unsigned char *offsets,
+ dns_name_t *set_name);
+
+void
+dns_name_init(dns_name_t *name, unsigned char *offsets) {
+ /*
+ * Initialize 'name'.
+ */
+ DNS_NAME_INIT(name, offsets);
+}
+
+void
+dns_name_reset(dns_name_t *name) {
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(BINDABLE(name));
+
+ DNS_NAME_RESET(name);
+}
+
+void
+dns_name_invalidate(dns_name_t *name) {
+ /*
+ * Make 'name' invalid.
+ */
+
+ REQUIRE(VALID_NAME(name));
+
+ name->magic = 0;
+ name->ndata = NULL;
+ name->length = 0;
+ name->labels = 0;
+ name->attributes = 0;
+ name->offsets = NULL;
+ name->buffer = NULL;
+ ISC_LINK_INIT(name, link);
+}
+
+void
+dns_name_setbuffer(dns_name_t *name, isc_buffer_t *buffer) {
+ /*
+ * Dedicate a buffer for use with 'name'.
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE((buffer != NULL && name->buffer == NULL) ||
+ (buffer == NULL));
+
+ name->buffer = buffer;
+}
+
+isc_boolean_t
+dns_name_hasbuffer(const dns_name_t *name) {
+ /*
+ * Does 'name' have a dedicated buffer?
+ */
+
+ REQUIRE(VALID_NAME(name));
+
+ if (name->buffer != NULL)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_name_isabsolute(const dns_name_t *name) {
+
+ /*
+ * Does 'name' end in the root label?
+ */
+
+ REQUIRE(VALID_NAME(name));
+
+ if ((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+#define hyphenchar(c) ((c) == 0x2d)
+#define asterchar(c) ((c) == 0x2a)
+#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
+ || ((c) >= 0x61 && (c) <= 0x7a))
+#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+#define borderchar(c) (alphachar(c) || digitchar(c))
+#define middlechar(c) (borderchar(c) || hyphenchar(c))
+#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+
+isc_boolean_t
+dns_name_ismailbox(const dns_name_t *name) {
+ unsigned char *ndata, ch;
+ unsigned int n;
+ isc_boolean_t first;
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(name->labels > 0);
+ REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
+
+ /*
+ * Root label.
+ */
+ if (name->length == 1)
+ return (ISC_TRUE);
+
+ ndata = name->ndata;
+ n = *ndata++;
+ INSIST(n <= 63);
+ while (n--) {
+ ch = *ndata++;
+ if (!domainchar(ch))
+ return (ISC_FALSE);
+ }
+
+ if (ndata == name->ndata + name->length)
+ return (ISC_FALSE);
+
+ /*
+ * RFC292/RFC1123 hostname.
+ */
+ while (ndata < (name->ndata + name->length)) {
+ n = *ndata++;
+ INSIST(n <= 63);
+ first = ISC_TRUE;
+ while (n--) {
+ ch = *ndata++;
+ if (first || n == 0) {
+ if (!borderchar(ch))
+ return (ISC_FALSE);
+ } else {
+ if (!middlechar(ch))
+ return (ISC_FALSE);
+ }
+ first = ISC_FALSE;
+ }
+ }
+ return (ISC_TRUE);
+}
+
+isc_boolean_t
+dns_name_ishostname(const dns_name_t *name, isc_boolean_t wildcard) {
+ unsigned char *ndata, ch;
+ unsigned int n;
+ isc_boolean_t first;
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(name->labels > 0);
+ REQUIRE(name->attributes & DNS_NAMEATTR_ABSOLUTE);
+
+ /*
+ * Root label.
+ */
+ if (name->length == 1)
+ return (ISC_TRUE);
+
+ /*
+ * Skip wildcard if this is a ownername.
+ */
+ ndata = name->ndata;
+ if (wildcard && ndata[0] == 1 && ndata[1] == '*')
+ ndata += 2;
+
+ /*
+ * RFC292/RFC1123 hostname.
+ */
+ while (ndata < (name->ndata + name->length)) {
+ n = *ndata++;
+ INSIST(n <= 63);
+ first = ISC_TRUE;
+ while (n--) {
+ ch = *ndata++;
+ if (first || n == 0) {
+ if (!borderchar(ch))
+ return (ISC_FALSE);
+ } else {
+ if (!middlechar(ch))
+ return (ISC_FALSE);
+ }
+ first = ISC_FALSE;
+ }
+ }
+ return (ISC_TRUE);
+}
+
+isc_boolean_t
+dns_name_iswildcard(const dns_name_t *name) {
+ unsigned char *ndata;
+
+ /*
+ * Is 'name' a wildcard name?
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(name->labels > 0);
+
+ if (name->length >= 2) {
+ ndata = name->ndata;
+ if (ndata[0] == 1 && ndata[1] == '*')
+ return (ISC_TRUE);
+ }
+
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_name_internalwildcard(const dns_name_t *name) {
+ unsigned char *ndata;
+ unsigned int count;
+ unsigned int label;
+
+ /*
+ * Does 'name' contain a internal wildcard?
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(name->labels > 0);
+
+ /*
+ * Skip first label.
+ */
+ ndata = name->ndata;
+ count = *ndata++;
+ INSIST(count <= 63);
+ ndata += count;
+ label = 1;
+ /*
+ * Check all but the last of the remaining labels.
+ */
+ while (label + 1 < name->labels) {
+ count = *ndata++;
+ INSIST(count <= 63);
+ if (count == 1 && *ndata == '*')
+ return (ISC_TRUE);
+ ndata += count;
+ label++;
+ }
+ return (ISC_FALSE);
+}
+
+static inline unsigned int
+name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
+ unsigned int length;
+ const unsigned char *s;
+ unsigned int h = 0;
+ unsigned char c;
+
+ length = name->length;
+ if (length > 16)
+ length = 16;
+
+ /*
+ * This hash function is similar to the one Ousterhout
+ * uses in Tcl.
+ */
+ s = name->ndata;
+ if (case_sensitive) {
+ while (length > 0) {
+ h += ( h << 3 ) + *s;
+ s++;
+ length--;
+ }
+ } else {
+ while (length > 0) {
+ c = maptolower[*s];
+ h += ( h << 3 ) + c;
+ s++;
+ length--;
+ }
+ }
+
+ return (h);
+}
+
+unsigned int
+dns_name_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
+ /*
+ * Provide a hash value for 'name'.
+ */
+ REQUIRE(VALID_NAME(name));
+
+ if (name->labels == 0)
+ return (0);
+
+ return (name_hash(name, case_sensitive));
+}
+
+unsigned int
+dns_name_fullhash(dns_name_t *name, isc_boolean_t case_sensitive) {
+ /*
+ * Provide a hash value for 'name'.
+ */
+ REQUIRE(VALID_NAME(name));
+
+ if (name->labels == 0)
+ return (0);
+
+ return (isc_hash_calc((const unsigned char *)name->ndata,
+ name->length, case_sensitive));
+}
+
+unsigned int
+dns_fullname_hash(dns_name_t *name, isc_boolean_t case_sensitive) {
+ /*
+ * This function was deprecated due to the breakage of the name space
+ * convention. We only keep this internally to provide binary backward
+ * compatibility.
+ */
+ REQUIRE(VALID_NAME(name));
+
+ return (dns_name_fullhash(name, case_sensitive));
+}
+
+unsigned int
+dns_name_hashbylabel(dns_name_t *name, isc_boolean_t case_sensitive) {
+ unsigned char *offsets;
+ dns_offsets_t odata;
+ dns_name_t tname;
+ unsigned int h = 0;
+ unsigned int i;
+
+ /*
+ * Provide a hash value for 'name'.
+ */
+ REQUIRE(VALID_NAME(name));
+
+ if (name->labels == 0)
+ return (0);
+ else if (name->labels == 1)
+ return (name_hash(name, case_sensitive));
+
+ SETUP_OFFSETS(name, offsets, odata);
+ DNS_NAME_INIT(&tname, NULL);
+ tname.labels = 1;
+ h = 0;
+ for (i = 0; i < name->labels; i++) {
+ tname.ndata = name->ndata + offsets[i];
+ if (i == name->labels - 1)
+ tname.length = name->length - offsets[i];
+ else
+ tname.length = offsets[i + 1] - offsets[i];
+ h += name_hash(&tname, case_sensitive);
+ }
+
+ return (h);
+}
+
+dns_namereln_t
+dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
+ int *orderp, unsigned int *nlabelsp)
+{
+ unsigned int l1, l2, l, count1, count2, count, nlabels;
+ int cdiff, ldiff, chdiff;
+ unsigned char *label1, *label2;
+ unsigned char *offsets1, *offsets2;
+ dns_offsets_t odata1, odata2;
+ dns_namereln_t namereln = dns_namereln_none;
+
+ /*
+ * Determine the relative ordering under the DNSSEC order relation of
+ * 'name1' and 'name2', and also determine the hierarchical
+ * relationship of the names.
+ *
+ * Note: It makes no sense for one of the names to be relative and the
+ * other absolute. If both names are relative, then to be meaningfully
+ * compared the caller must ensure that they are both relative to the
+ * same domain.
+ */
+
+ REQUIRE(VALID_NAME(name1));
+ REQUIRE(VALID_NAME(name2));
+ REQUIRE(orderp != NULL);
+ REQUIRE(nlabelsp != NULL);
+ /*
+ * Either name1 is absolute and name2 is absolute, or neither is.
+ */
+ REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
+ (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
+
+ SETUP_OFFSETS(name1, offsets1, odata1);
+ SETUP_OFFSETS(name2, offsets2, odata2);
+
+ nlabels = 0;
+ l1 = name1->labels;
+ l2 = name2->labels;
+ ldiff = (int)l1 - (int)l2;
+ if (ldiff < 0)
+ l = l1;
+ else
+ l = l2;
+
+ while (l > 0) {
+ l--;
+ l1--;
+ l2--;
+ label1 = &name1->ndata[offsets1[l1]];
+ label2 = &name2->ndata[offsets2[l2]];
+ count1 = *label1++;
+ count2 = *label2++;
+
+ /*
+ * We dropped bitstring labels, and we don't support any
+ * other extended label types.
+ */
+ INSIST(count1 <= 63 && count2 <= 63);
+
+ cdiff = (int)count1 - (int)count2;
+ if (cdiff < 0)
+ count = count1;
+ else
+ count = count2;
+
+ while (count > 0) {
+ chdiff = (int)maptolower[*label1] -
+ (int)maptolower[*label2];
+ if (chdiff != 0) {
+ *orderp = chdiff;
+ goto done;
+ }
+ count--;
+ label1++;
+ label2++;
+ }
+ if (cdiff != 0) {
+ *orderp = cdiff;
+ goto done;
+ }
+ nlabels++;
+ }
+
+ *orderp = ldiff;
+ if (ldiff < 0)
+ namereln = dns_namereln_contains;
+ else if (ldiff > 0)
+ namereln = dns_namereln_subdomain;
+ else
+ namereln = dns_namereln_equal;
+
+ done:
+ *nlabelsp = nlabels;
+
+ if (nlabels > 0 && namereln == dns_namereln_none)
+ namereln = dns_namereln_commonancestor;
+
+ return (namereln);
+}
+
+int
+dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
+ int order;
+ unsigned int nlabels;
+
+ /*
+ * Determine the relative ordering under the DNSSEC order relation of
+ * 'name1' and 'name2'.
+ *
+ * Note: It makes no sense for one of the names to be relative and the
+ * other absolute. If both names are relative, then to be meaningfully
+ * compared the caller must ensure that they are both relative to the
+ * same domain.
+ */
+
+ (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
+
+ return (order);
+}
+
+isc_boolean_t
+dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
+ unsigned int l, count;
+ unsigned char c;
+ unsigned char *label1, *label2;
+
+ /*
+ * Are 'name1' and 'name2' equal?
+ *
+ * Note: It makes no sense for one of the names to be relative and the
+ * other absolute. If both names are relative, then to be meaningfully
+ * compared the caller must ensure that they are both relative to the
+ * same domain.
+ */
+
+ REQUIRE(VALID_NAME(name1));
+ REQUIRE(VALID_NAME(name2));
+ /*
+ * Either name1 is absolute and name2 is absolute, or neither is.
+ */
+ REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
+ (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
+
+ if (name1->length != name2->length)
+ return (ISC_FALSE);
+
+ l = name1->labels;
+
+ if (l != name2->labels)
+ return (ISC_FALSE);
+
+ label1 = name1->ndata;
+ label2 = name2->ndata;
+ while (l > 0) {
+ l--;
+ count = *label1++;
+ if (count != *label2++)
+ return (ISC_FALSE);
+
+ INSIST(count <= 63); /* no bitstring support */
+
+ while (count > 0) {
+ count--;
+ c = maptolower[*label1++];
+ if (c != maptolower[*label2++])
+ return (ISC_FALSE);
+ }
+ }
+
+ return (ISC_TRUE);
+}
+
+isc_boolean_t
+dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
+
+ /*
+ * Are 'name1' and 'name2' equal?
+ *
+ * Note: It makes no sense for one of the names to be relative and the
+ * other absolute. If both names are relative, then to be meaningfully
+ * compared the caller must ensure that they are both relative to the
+ * same domain.
+ */
+
+ REQUIRE(VALID_NAME(name1));
+ REQUIRE(VALID_NAME(name2));
+ /*
+ * Either name1 is absolute and name2 is absolute, or neither is.
+ */
+ REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) ==
+ (name2->attributes & DNS_NAMEATTR_ABSOLUTE));
+
+ if (name1->length != name2->length)
+ return (ISC_FALSE);
+
+ if (memcmp(name1->ndata, name2->ndata, name1->length) != 0)
+ return (ISC_FALSE);
+
+ return (ISC_TRUE);
+}
+
+int
+dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
+ unsigned int l1, l2, l, count1, count2, count;
+ unsigned char c1, c2;
+ unsigned char *label1, *label2;
+
+ /*
+ * Compare two absolute names as rdata.
+ */
+
+ REQUIRE(VALID_NAME(name1));
+ REQUIRE(name1->labels > 0);
+ REQUIRE((name1->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
+ REQUIRE(VALID_NAME(name2));
+ REQUIRE(name2->labels > 0);
+ REQUIRE((name2->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
+
+ l1 = name1->labels;
+ l2 = name2->labels;
+
+ l = (l1 < l2) ? l1 : l2;
+
+ label1 = name1->ndata;
+ label2 = name2->ndata;
+ while (l > 0) {
+ l--;
+ count1 = *label1++;
+ count2 = *label2++;
+
+ /* no bitstring support */
+ INSIST(count1 <= 63 && count2 <= 63);
+
+ if (count1 != count2)
+ return ((count1 < count2) ? -1 : 1);
+ count = count1;
+ while (count > 0) {
+ count--;
+ c1 = maptolower[*label1++];
+ c2 = maptolower[*label2++];
+ if (c1 < c2)
+ return (-1);
+ else if (c1 > c2)
+ return (1);
+ }
+ }
+
+ /*
+ * If one name had more labels than the other, their common
+ * prefix must have been different because the shorter name
+ * ended with the root label and the longer one can't have
+ * a root label in the middle of it. Therefore, if we get
+ * to this point, the lengths must be equal.
+ */
+ INSIST(l1 == l2);
+
+ return (0);
+}
+
+isc_boolean_t
+dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
+ int order;
+ unsigned int nlabels;
+ dns_namereln_t namereln;
+
+ /*
+ * Is 'name1' a subdomain of 'name2'?
+ *
+ * Note: It makes no sense for one of the names to be relative and the
+ * other absolute. If both names are relative, then to be meaningfully
+ * compared the caller must ensure that they are both relative to the
+ * same domain.
+ */
+
+ namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
+ if (namereln == dns_namereln_subdomain ||
+ namereln == dns_namereln_equal)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
+ int order;
+ unsigned int nlabels, labels;
+ dns_name_t tname;
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(name->labels > 0);
+ REQUIRE(VALID_NAME(wname));
+ labels = wname->labels;
+ REQUIRE(labels > 0);
+ REQUIRE(dns_name_iswildcard(wname));
+
+ DNS_NAME_INIT(&tname, NULL);
+ dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
+ if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
+ dns_namereln_subdomain)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+unsigned int
+dns_name_countlabels(const dns_name_t *name) {
+ /*
+ * How many labels does 'name' have?
+ */
+
+ REQUIRE(VALID_NAME(name));
+
+ ENSURE(name->labels <= 128);
+
+ return (name->labels);
+}
+
+void
+dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
+ unsigned char *offsets;
+ dns_offsets_t odata;
+
+ /*
+ * Make 'label' refer to the 'n'th least significant label of 'name'.
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(name->labels > 0);
+ REQUIRE(n < name->labels);
+ REQUIRE(label != NULL);
+
+ SETUP_OFFSETS(name, offsets, odata);
+
+ label->base = &name->ndata[offsets[n]];
+ if (n == name->labels - 1)
+ label->length = name->length - offsets[n];
+ else
+ label->length = offsets[n + 1] - offsets[n];
+}
+
+void
+dns_name_getlabelsequence(const dns_name_t *source,
+ unsigned int first, unsigned int n,
+ dns_name_t *target)
+{
+ unsigned char *offsets;
+ dns_offsets_t odata;
+ unsigned int firstoffset, endoffset;
+
+ /*
+ * Make 'target' refer to the 'n' labels including and following
+ * 'first' in 'source'.
+ */
+
+ REQUIRE(VALID_NAME(source));
+ REQUIRE(VALID_NAME(target));
+ REQUIRE(first <= source->labels);
+ REQUIRE(first + n <= source->labels);
+ REQUIRE(BINDABLE(target));
+
+ SETUP_OFFSETS(source, offsets, odata);
+
+ if (first == source->labels)
+ firstoffset = source->length;
+ else
+ firstoffset = offsets[first];
+
+ if (first + n == source->labels)
+ endoffset = source->length;
+ else
+ endoffset = offsets[first + n];
+
+ target->ndata = &source->ndata[firstoffset];
+ target->length = endoffset - firstoffset;
+
+ if (first + n == source->labels && n > 0 &&
+ (source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
+ target->attributes |= DNS_NAMEATTR_ABSOLUTE;
+ else
+ target->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
+
+ target->labels = n;
+
+ /*
+ * If source and target are the same, and we're making target
+ * a prefix of source, the offsets table is correct already
+ * so we don't need to call set_offsets().
+ */
+ if (target->offsets != NULL &&
+ (target != source || first != 0))
+ set_offsets(target, target->offsets, NULL);
+}
+
+void
+dns_name_clone(const dns_name_t *source, dns_name_t *target) {
+
+ /*
+ * Make 'target' refer to the same name as 'source'.
+ */
+
+ REQUIRE(VALID_NAME(source));
+ REQUIRE(VALID_NAME(target));
+ REQUIRE(BINDABLE(target));
+
+ target->ndata = source->ndata;
+ target->length = source->length;
+ target->labels = source->labels;
+ target->attributes = source->attributes &
+ (unsigned int)~(DNS_NAMEATTR_READONLY | DNS_NAMEATTR_DYNAMIC |
+ DNS_NAMEATTR_DYNOFFSETS);
+ if (target->offsets != NULL && source->labels > 0) {
+ if (source->offsets != NULL)
+ memcpy(target->offsets, source->offsets,
+ source->labels);
+ else
+ set_offsets(target, target->offsets, NULL);
+ }
+}
+
+void
+dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
+ unsigned char *offsets;
+ dns_offsets_t odata;
+ unsigned int len;
+ isc_region_t r2;
+
+ /*
+ * Make 'name' refer to region 'r'.
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(r != NULL);
+ REQUIRE(BINDABLE(name));
+
+ INIT_OFFSETS(name, offsets, odata);
+
+ if (name->buffer != NULL) {
+ isc_buffer_clear(name->buffer);
+ isc_buffer_availableregion(name->buffer, &r2);
+ len = (r->length < r2.length) ? r->length : r2.length;
+ if (len > DNS_NAME_MAXWIRE)
+ len = DNS_NAME_MAXWIRE;
+ memcpy(r2.base, r->base, len);
+ name->ndata = r2.base;
+ name->length = len;
+ } else {
+ name->ndata = r->base;
+ name->length = (r->length <= DNS_NAME_MAXWIRE) ?
+ r->length : DNS_NAME_MAXWIRE;
+ }
+
+ if (r->length > 0)
+ set_offsets(name, offsets, name);
+ else {
+ name->labels = 0;
+ name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
+ }
+
+ if (name->buffer != NULL)
+ isc_buffer_add(name->buffer, name->length);
+}
+
+void
+dns_name_toregion(dns_name_t *name, isc_region_t *r) {
+ /*
+ * Make 'r' refer to 'name'.
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(r != NULL);
+
+ 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,
+ isc_buffer_t *target)
+{
+ unsigned char *ndata, *label;
+ char *tdata;
+ char c;
+ ft_state state;
+ unsigned int value, count;
+ unsigned int n1, n2, tlen, nrem, nused, digits, labels, tused;
+ isc_boolean_t done;
+ unsigned char *offsets;
+ dns_offsets_t odata;
+ isc_boolean_t downcase;
+
+ /*
+ * Convert the textual representation of a DNS name at source
+ * into uncompressed wire form stored in target.
+ *
+ * Notes:
+ * Relative domain names will have 'origin' appended to them
+ * unless 'origin' is NULL, in which case relative domain names
+ * will remain relative.
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(ISC_BUFFER_VALID(source));
+ REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
+ (target == NULL && ISC_BUFFER_VALID(name->buffer)));
+
+ downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
+
+ if (target == NULL && name->buffer != NULL) {
+ target = name->buffer;
+ isc_buffer_clear(target);
+ }
+
+ REQUIRE(BINDABLE(name));
+
+ INIT_OFFSETS(name, offsets, odata);
+ offsets[0] = 0;
+
+ /*
+ * Initialize things to make the compiler happy; they're not required.
+ */
+ n1 = 0;
+ n2 = 0;
+ label = NULL;
+ digits = 0;
+ value = 0;
+ count = 0;
+
+ /*
+ * Make 'name' empty in case of failure.
+ */
+ MAKE_EMPTY(name);
+
+ /*
+ * Set up the state machine.
+ */
+ tdata = (char *)source->base + source->current;
+ tlen = isc_buffer_remaininglength(source);
+ tused = 0;
+ ndata = isc_buffer_used(target);
+ nrem = isc_buffer_availablelength(target);
+ if (nrem > 255)
+ nrem = 255;
+ nused = 0;
+ labels = 0;
+ done = ISC_FALSE;
+ state = ft_init;
+
+ while (nrem > 0 && tlen > 0 && !done) {
+ c = *tdata++;
+ tlen--;
+ tused++;
+
+ switch (state) {
+ case ft_init:
+ /*
+ * Is this the root name?
+ */
+ if (c == '.') {
+ if (tlen != 0)
+ return (DNS_R_EMPTYLABEL);
+ labels++;
+ *ndata++ = 0;
+ nrem--;
+ nused++;
+ done = ISC_TRUE;
+ break;
+ }
+ if (c == '@' && tlen == 0) {
+ state = ft_at;
+ break;
+ }
+
+ /* FALLTHROUGH */
+ case ft_start:
+ label = ndata;
+ ndata++;
+ nrem--;
+ nused++;
+ count = 0;
+ if (c == '\\') {
+ state = ft_initialescape;
+ break;
+ }
+ state = ft_ordinary;
+ if (nrem == 0)
+ return (ISC_R_NOSPACE);
+ /* FALLTHROUGH */
+ case ft_ordinary:
+ if (c == '.') {
+ if (count == 0)
+ return (DNS_R_EMPTYLABEL);
+ *label = count;
+ labels++;
+ INSIST(labels <= 127);
+ offsets[labels] = nused;
+ if (tlen == 0) {
+ labels++;
+ *ndata++ = 0;
+ nrem--;
+ nused++;
+ done = ISC_TRUE;
+ }
+ state = ft_start;
+ } else if (c == '\\') {
+ state = ft_escape;
+ } else {
+ if (count >= 63)
+ return (DNS_R_LABELTOOLONG);
+ count++;
+ CONVERTTOASCII(c);
+ if (downcase)
+ c = maptolower[(int)c];
+ *ndata++ = c;
+ nrem--;
+ nused++;
+ }
+ break;
+ case ft_initialescape:
+ if (c == '[') {
+ /*
+ * This looks like a bitstring label, which
+ * was deprecated. Intentionally drop it.
+ */
+ return (DNS_R_BADLABELTYPE);
+ }
+ state = ft_escape;
+ /* FALLTHROUGH */
+ case ft_escape:
+ if (!isdigit(c & 0xff)) {
+ if (count >= 63)
+ return (DNS_R_LABELTOOLONG);
+ count++;
+ CONVERTTOASCII(c);
+ if (downcase)
+ c = maptolower[(int)c];
+ *ndata++ = c;
+ nrem--;
+ nused++;
+ state = ft_ordinary;
+ break;
+ }
+ digits = 0;
+ value = 0;
+ state = ft_escdecimal;
+ /* FALLTHROUGH */
+ case ft_escdecimal:
+ if (!isdigit(c & 0xff))
+ return (DNS_R_BADESCAPE);
+ value *= 10;
+ value += digitvalue[(int)c];
+ digits++;
+ if (digits == 3) {
+ if (value > 255)
+ return (DNS_R_BADESCAPE);
+ if (count >= 63)
+ return (DNS_R_LABELTOOLONG);
+ count++;
+ if (downcase)
+ value = maptolower[value];
+ *ndata++ = value;
+ nrem--;
+ nused++;
+ state = ft_ordinary;
+ }
+ break;
+ default:
+ FATAL_ERROR(__FILE__, __LINE__,
+ "Unexpected state %d", state);
+ /* Does not return. */
+ }
+ }
+
+ if (!done) {
+ if (nrem == 0)
+ return (ISC_R_NOSPACE);
+ INSIST(tlen == 0);
+ if (state != ft_ordinary && state != ft_at)
+ return (ISC_R_UNEXPECTEDEND);
+ if (state == ft_ordinary) {
+ INSIST(count != 0);
+ *label = count;
+ labels++;
+ INSIST(labels <= 127);
+ offsets[labels] = nused;
+ }
+ if (origin != NULL) {
+ if (nrem < origin->length)
+ return (ISC_R_NOSPACE);
+ label = origin->ndata;
+ n1 = origin->length;
+ nrem -= n1;
+ while (n1 > 0) {
+ n2 = *label++;
+ INSIST(n2 <= 63); /* no bitstring support */
+ *ndata++ = n2;
+ n1 -= n2 + 1;
+ nused += n2 + 1;
+ while (n2 > 0) {
+ c = *label++;
+ if (downcase)
+ c = maptolower[(int)c];
+ *ndata++ = c;
+ n2--;
+ }
+ labels++;
+ if (n1 > 0) {
+ INSIST(labels <= 127);
+ offsets[labels] = nused;
+ }
+ }
+ if ((origin->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
+ name->attributes |= DNS_NAMEATTR_ABSOLUTE;
+ }
+ } else
+ name->attributes |= DNS_NAMEATTR_ABSOLUTE;
+
+ name->ndata = (unsigned char *)target->base + target->used;
+ name->labels = labels;
+ name->length = nused;
+
+ isc_buffer_forward(source, tused);
+ isc_buffer_add(target, name->length);
+
+ return (ISC_R_SUCCESS);
+}
+
+#ifdef ISC_PLATFORM_USETHREADS
+static void
+free_specific(void *arg) {
+ dns_name_totextfilter_t *mem = arg;
+ isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
+ /* Stop use being called again. */
+ (void)isc_thread_key_setspecific(totext_filter_proc_key, NULL);
+}
+
+static void
+thread_key_mutex_init(void) {
+ RUNTIME_CHECK(isc_mutex_init(&thread_key_mutex) == ISC_R_SUCCESS);
+}
+
+static isc_result_t
+totext_filter_proc_key_init(void) {
+ isc_result_t result;
+
+ /*
+ * We need the call to isc_once_do() to support profiled mutex
+ * otherwise thread_key_mutex could be initialized at compile time.
+ */
+ 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_mctx == NULL)
+ result = isc_mem_create2(0, 0, &thread_key_mctx, 0);
+ if (result != ISC_R_SUCCESS)
+ goto unlock;
+ isc_mem_setname(thread_key_mctx, "threadkey", NULL);
+ isc_mem_setdestroycheck(thread_key_mctx, ISC_FALSE);
+
+ if (!thread_key_initialized &&
+ isc_thread_key_create(&totext_filter_proc_key,
+ free_specific) != 0) {
+ result = ISC_R_FAILURE;
+ isc_mem_detach(&thread_key_mctx);
+ } else
+ thread_key_initialized = 1;
+ unlock:
+ UNLOCK(&thread_key_mutex);
+ }
+ return (result);
+}
+#endif
+
+isc_result_t
+dns_name_totext(dns_name_t *name, isc_boolean_t omit_final_dot,
+ isc_buffer_t *target)
+{
+ unsigned char *ndata;
+ char *tdata;
+ unsigned int nlen, tlen;
+ unsigned char c;
+ unsigned int trem, count;
+ unsigned int labels;
+ isc_boolean_t saw_root = ISC_FALSE;
+ unsigned int oused = target->used;
+#ifdef ISC_PLATFORM_USETHREADS
+ dns_name_totextfilter_t *mem;
+ dns_name_totextfilter_t totext_filter_proc = NULL;
+ isc_result_t result;
+#endif
+
+ /*
+ * This function assumes the name is in proper uncompressed
+ * wire format.
+ */
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(ISC_BUFFER_VALID(target));
+
+#ifdef ISC_PLATFORM_USETHREADS
+ result = totext_filter_proc_key_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#endif
+ ndata = name->ndata;
+ nlen = name->length;
+ labels = name->labels;
+ tdata = isc_buffer_used(target);
+ tlen = isc_buffer_availablelength(target);
+
+ trem = tlen;
+
+ if (labels == 0 && nlen == 0) {
+ /*
+ * Special handling for an empty name.
+ */
+ if (trem == 0)
+ return (ISC_R_NOSPACE);
+
+ /*
+ * The names of these booleans are misleading in this case.
+ * This empty name is not necessarily from the root node of
+ * the DNS root zone, nor is a final dot going to be included.
+ * They need to be set this way, though, to keep the "@"
+ * from being trounced.
+ */
+ saw_root = ISC_TRUE;
+ omit_final_dot = ISC_FALSE;
+ *tdata++ = '@';
+ trem--;
+
+ /*
+ * Skip the while() loop.
+ */
+ nlen = 0;
+ } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
+ /*
+ * Special handling for the root label.
+ */
+ if (trem == 0)
+ return (ISC_R_NOSPACE);
+
+ saw_root = ISC_TRUE;
+ omit_final_dot = ISC_FALSE;
+ *tdata++ = '.';
+ trem--;
+
+ /*
+ * Skip the while() loop.
+ */
+ nlen = 0;
+ }
+
+ while (labels > 0 && nlen > 0 && trem > 0) {
+ labels--;
+ count = *ndata++;
+ nlen--;
+ if (count == 0) {
+ saw_root = ISC_TRUE;
+ break;
+ }
+ if (count < 64) {
+ INSIST(nlen >= count);
+ while (count > 0) {
+ c = *ndata;
+ switch (c) {
+ case 0x22: /* '"' */
+ case 0x28: /* '(' */
+ case 0x29: /* ')' */
+ case 0x2E: /* '.' */
+ case 0x3B: /* ';' */
+ case 0x5C: /* '\\' */
+ /* Special modifiers in zone files. */
+ case 0x40: /* '@' */
+ case 0x24: /* '$' */
+ if (trem < 2)
+ return (ISC_R_NOSPACE);
+ *tdata++ = '\\';
+ CONVERTFROMASCII(c);
+ *tdata++ = c;
+ ndata++;
+ trem -= 2;
+ nlen--;
+ break;
+ default:
+ if (c > 0x20 && c < 0x7f) {
+ if (trem == 0)
+ return (ISC_R_NOSPACE);
+ CONVERTFROMASCII(c);
+ *tdata++ = c;
+ ndata++;
+ trem--;
+ nlen--;
+ } else {
+ if (trem < 4)
+ return (ISC_R_NOSPACE);
+ *tdata++ = 0x5c;
+ *tdata++ = 0x30 +
+ ((c / 100) % 10);
+ *tdata++ = 0x30 +
+ ((c / 10) % 10);
+ *tdata++ = 0x30 + (c % 10);
+ trem -= 4;
+ ndata++;
+ nlen--;
+ }
+ }
+ count--;
+ }
+ } else {
+ FATAL_ERROR(__FILE__, __LINE__,
+ "Unexpected label type %02x", count);
+ /* NOTREACHED */
+ }
+
+ /*
+ * The following assumes names are absolute. If not, we
+ * fix things up later. Note that this means that in some
+ * cases one more byte of text buffer is required than is
+ * needed in the final output.
+ */
+ if (trem == 0)
+ return (ISC_R_NOSPACE);
+ *tdata++ = '.';
+ trem--;
+ }
+
+ if (nlen != 0 && trem == 0)
+ return (ISC_R_NOSPACE);
+
+ if (!saw_root || omit_final_dot)
+ trem++;
+
+ isc_buffer_add(target, tlen - trem);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ mem = isc_thread_key_getspecific(totext_filter_proc_key);
+ if (mem != NULL)
+ totext_filter_proc = *mem;
+#endif
+ if (totext_filter_proc != NULL)
+ return ((*totext_filter_proc)(target, oused, saw_root));
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_name_tofilenametext(dns_name_t *name, isc_boolean_t omit_final_dot,
+ isc_buffer_t *target)
+{
+ unsigned char *ndata;
+ char *tdata;
+ unsigned int nlen, tlen;
+ unsigned char c;
+ unsigned int trem, count;
+ unsigned int labels;
+
+ /*
+ * This function assumes the name is in proper uncompressed
+ * wire format.
+ */
+ REQUIRE(VALID_NAME(name));
+ REQUIRE((name->attributes & DNS_NAMEATTR_ABSOLUTE) != 0);
+ REQUIRE(ISC_BUFFER_VALID(target));
+
+ ndata = name->ndata;
+ nlen = name->length;
+ labels = name->labels;
+ tdata = isc_buffer_used(target);
+ tlen = isc_buffer_availablelength(target);
+
+ trem = tlen;
+
+ if (nlen == 1 && labels == 1 && *ndata == '\0') {
+ /*
+ * Special handling for the root label.
+ */
+ if (trem == 0)
+ return (ISC_R_NOSPACE);
+
+ omit_final_dot = ISC_FALSE;
+ *tdata++ = '.';
+ trem--;
+
+ /*
+ * Skip the while() loop.
+ */
+ nlen = 0;
+ }
+
+ while (labels > 0 && nlen > 0 && trem > 0) {
+ labels--;
+ count = *ndata++;
+ nlen--;
+ if (count == 0)
+ break;
+ if (count < 64) {
+ INSIST(nlen >= count);
+ while (count > 0) {
+ c = *ndata;
+ if ((c >= 0x30 && c <= 0x39) || /* digit */
+ (c >= 0x41 && c <= 0x5A) || /* uppercase */
+ (c >= 0x61 && c <= 0x7A) || /* lowercase */
+ c == 0x2D || /* hyphen */
+ c == 0x5F) /* underscore */
+ {
+ if (trem == 0)
+ return (ISC_R_NOSPACE);
+ /* downcase */
+ if (c >= 0x41 && c <= 0x5A)
+ c += 0x20;
+ CONVERTFROMASCII(c);
+ *tdata++ = c;
+ ndata++;
+ trem--;
+ nlen--;
+ } else {
+ if (trem < 3)
+ return (ISC_R_NOSPACE);
+ sprintf(tdata, "%%%02X", c);
+ tdata += 3;
+ trem -= 3;
+ ndata++;
+ nlen--;
+ }
+ count--;
+ }
+ } else {
+ FATAL_ERROR(__FILE__, __LINE__,
+ "Unexpected label type %02x", count);
+ /* NOTREACHED */
+ }
+
+ /*
+ * The following assumes names are absolute. If not, we
+ * fix things up later. Note that this means that in some
+ * cases one more byte of text buffer is required than is
+ * needed in the final output.
+ */
+ if (trem == 0)
+ return (ISC_R_NOSPACE);
+ *tdata++ = '.';
+ trem--;
+ }
+
+ if (nlen != 0 && trem == 0)
+ return (ISC_R_NOSPACE);
+
+ if (omit_final_dot)
+ trem++;
+
+ isc_buffer_add(target, tlen - trem);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_name_downcase(dns_name_t *source, dns_name_t *name, isc_buffer_t *target) {
+ unsigned char *sndata, *ndata;
+ unsigned int nlen, count, labels;
+ isc_buffer_t buffer;
+
+ /*
+ * Downcase 'source'.
+ */
+
+ REQUIRE(VALID_NAME(source));
+ REQUIRE(VALID_NAME(name));
+ if (source == name) {
+ REQUIRE((name->attributes & DNS_NAMEATTR_READONLY) == 0);
+ isc_buffer_init(&buffer, source->ndata, source->length);
+ target = &buffer;
+ ndata = source->ndata;
+ } else {
+ REQUIRE(BINDABLE(name));
+ REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
+ (target == NULL && ISC_BUFFER_VALID(name->buffer)));
+ if (target == NULL) {
+ target = name->buffer;
+ isc_buffer_clear(name->buffer);
+ }
+ ndata = (unsigned char *)target->base + target->used;
+ name->ndata = ndata;
+ }
+
+ sndata = source->ndata;
+ nlen = source->length;
+ labels = source->labels;
+
+ if (nlen > (target->length - target->used)) {
+ MAKE_EMPTY(name);
+ return (ISC_R_NOSPACE);
+ }
+
+ while (labels > 0 && nlen > 0) {
+ labels--;
+ count = *sndata++;
+ *ndata++ = count;
+ nlen--;
+ if (count < 64) {
+ INSIST(nlen >= count);
+ while (count > 0) {
+ *ndata++ = maptolower[(*sndata++)];
+ nlen--;
+ count--;
+ }
+ } else {
+ FATAL_ERROR(__FILE__, __LINE__,
+ "Unexpected label type %02x", count);
+ /* Does not return. */
+ }
+ }
+
+ if (source != name) {
+ name->labels = source->labels;
+ name->length = source->length;
+ if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
+ name->attributes = DNS_NAMEATTR_ABSOLUTE;
+ else
+ name->attributes = 0;
+ if (name->labels > 0 && name->offsets != NULL)
+ set_offsets(name, name->offsets, NULL);
+ }
+
+ isc_buffer_add(target, name->length);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+set_offsets(const dns_name_t *name, unsigned char *offsets,
+ dns_name_t *set_name)
+{
+ unsigned int offset, count, length, nlabels;
+ unsigned char *ndata;
+ isc_boolean_t absolute;
+
+ ndata = name->ndata;
+ length = name->length;
+ offset = 0;
+ nlabels = 0;
+ absolute = ISC_FALSE;
+ while (offset != length) {
+ INSIST(nlabels < 128);
+ offsets[nlabels++] = offset;
+ count = *ndata++;
+ offset++;
+ INSIST(count <= 63);
+ offset += count;
+ ndata += count;
+ INSIST(offset <= length);
+ if (count == 0) {
+ absolute = ISC_TRUE;
+ break;
+ }
+ }
+ if (set_name != NULL) {
+ INSIST(set_name == name);
+
+ set_name->labels = nlabels;
+ set_name->length = offset;
+ if (absolute)
+ set_name->attributes |= DNS_NAMEATTR_ABSOLUTE;
+ else
+ set_name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
+ }
+ INSIST(nlabels == name->labels);
+ INSIST(offset == name->length);
+}
+
+isc_result_t
+dns_name_fromwire(dns_name_t *name, isc_buffer_t *source,
+ dns_decompress_t *dctx, unsigned int options,
+ isc_buffer_t *target)
+{
+ unsigned char *cdata, *ndata;
+ unsigned int cused; /* Bytes of compressed name data used */
+ unsigned int nused, labels, n, nmax;
+ unsigned int current, new_current, biggest_pointer;
+ isc_boolean_t done;
+ fw_state state = fw_start;
+ unsigned int c;
+ unsigned char *offsets;
+ dns_offsets_t odata;
+ isc_boolean_t downcase;
+ isc_boolean_t seen_pointer;
+
+ /*
+ * Copy the possibly-compressed name at source into target,
+ * decompressing it. Loop prevention is performed by checking
+ * the new pointer against biggest_pointer.
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
+ (target == NULL && ISC_BUFFER_VALID(name->buffer)));
+
+ downcase = ISC_TF((options & DNS_NAME_DOWNCASE) != 0);
+
+ if (target == NULL && name->buffer != NULL) {
+ target = name->buffer;
+ isc_buffer_clear(target);
+ }
+
+ REQUIRE(dctx != NULL);
+ REQUIRE(BINDABLE(name));
+
+ INIT_OFFSETS(name, offsets, odata);
+
+ /*
+ * Make 'name' empty in case of failure.
+ */
+ MAKE_EMPTY(name);
+
+ /*
+ * Initialize things to make the compiler happy; they're not required.
+ */
+ n = 0;
+ new_current = 0;
+
+ /*
+ * Set up.
+ */
+ labels = 0;
+ done = ISC_FALSE;
+
+ ndata = isc_buffer_used(target);
+ nused = 0;
+ seen_pointer = ISC_FALSE;
+
+ /*
+ * Find the maximum number of uncompressed target name
+ * bytes we are willing to generate. This is the smaller
+ * of the available target buffer length and the
+ * maximum legal domain name length (255).
+ */
+ nmax = isc_buffer_availablelength(target);
+ if (nmax > DNS_NAME_MAXWIRE)
+ nmax = DNS_NAME_MAXWIRE;
+
+ cdata = isc_buffer_current(source);
+ cused = 0;
+
+ current = source->current;
+ biggest_pointer = current;
+
+ /*
+ * Note: The following code is not optimized for speed, but
+ * rather for correctness. Speed will be addressed in the future.
+ */
+
+ while (current < source->active && !done) {
+ c = *cdata++;
+ current++;
+ if (!seen_pointer)
+ cused++;
+
+ switch (state) {
+ case fw_start:
+ if (c < 64) {
+ offsets[labels] = nused;
+ labels++;
+ if (nused + c + 1 > nmax)
+ goto full;
+ nused += c + 1;
+ *ndata++ = c;
+ if (c == 0)
+ done = ISC_TRUE;
+ n = c;
+ state = fw_ordinary;
+ } else if (c >= 128 && c < 192) {
+ /*
+ * 14 bit local compression pointer.
+ * Local compression is no longer an
+ * IETF draft.
+ */
+ return (DNS_R_BADLABELTYPE);
+ } else if (c >= 192) {
+ /*
+ * Ordinary 14-bit pointer.
+ */
+ if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) ==
+ 0)
+ return (DNS_R_DISALLOWED);
+ new_current = c & 0x3F;
+ n = 1;
+ state = fw_newcurrent;
+ } else
+ return (DNS_R_BADLABELTYPE);
+ break;
+ case fw_ordinary:
+ if (downcase)
+ c = maptolower[c];
+ /* FALLTHROUGH */
+ case fw_copy:
+ *ndata++ = c;
+ n--;
+ if (n == 0)
+ state = fw_start;
+ break;
+ case fw_newcurrent:
+ new_current *= 256;
+ new_current += c;
+ n--;
+ if (n != 0)
+ break;
+ if (new_current >= biggest_pointer)
+ return (DNS_R_BADPOINTER);
+ biggest_pointer = new_current;
+ current = new_current;
+ cdata = (unsigned char *)source->base + current;
+ seen_pointer = ISC_TRUE;
+ state = fw_start;
+ break;
+ default:
+ FATAL_ERROR(__FILE__, __LINE__,
+ "Unknown state %d", state);
+ /* Does not return. */
+ }
+ }
+
+ if (!done)
+ return (ISC_R_UNEXPECTEDEND);
+
+ name->ndata = (unsigned char *)target->base + target->used;
+ name->labels = labels;
+ name->length = nused;
+ name->attributes |= DNS_NAMEATTR_ABSOLUTE;
+
+ isc_buffer_forward(source, cused);
+ isc_buffer_add(target, name->length);
+
+ return (ISC_R_SUCCESS);
+
+ full:
+ if (nmax == DNS_NAME_MAXWIRE)
+ /*
+ * The name did not fit even though we had a buffer
+ * big enough to fit a maximum-length name.
+ */
+ return (DNS_R_NAMETOOLONG);
+ else
+ /*
+ * The name might fit if only the caller could give us a
+ * big enough buffer.
+ */
+ return (ISC_R_NOSPACE);
+}
+
+isc_result_t
+dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
+ isc_buffer_t *target)
+{
+ unsigned int methods;
+ isc_uint16_t offset;
+ dns_name_t gp; /* Global compression prefix */
+ isc_boolean_t gf; /* Global compression target found */
+ isc_uint16_t go; /* Global compression offset */
+ dns_offsets_t clo;
+ dns_name_t clname;
+
+ /*
+ * Convert 'name' into wire format, compressing it as specified by the
+ * compression context 'cctx', and storing the result in 'target'.
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(cctx != NULL);
+ REQUIRE(ISC_BUFFER_VALID(target));
+
+ /*
+ * If 'name' doesn't have an offsets table, make a clone which
+ * has one.
+ */
+ if (name->offsets == NULL) {
+ DNS_NAME_INIT(&clname, clo);
+ dns_name_clone(name, &clname);
+ name = &clname;
+ }
+ DNS_NAME_INIT(&gp, NULL);
+
+ offset = target->used; /*XXX*/
+
+ methods = dns_compress_getmethods(cctx);
+
+ if ((name->attributes & DNS_NAMEATTR_NOCOMPRESS) == 0 &&
+ (methods & DNS_COMPRESS_GLOBAL14) != 0)
+ gf = dns_compress_findglobal(cctx, name, &gp, &go);
+ else
+ gf = ISC_FALSE;
+
+ /*
+ * If the offset is too high for 14 bit global compression, we're
+ * out of luck.
+ */
+ if (gf && go >= 0x4000)
+ gf = ISC_FALSE;
+
+ /*
+ * Will the compression pointer reduce the message size?
+ */
+ if (gf && (gp.length + 2) >= name->length)
+ gf = ISC_FALSE;
+
+ if (gf) {
+ if (target->length - target->used < gp.length)
+ return (ISC_R_NOSPACE);
+ (void)memcpy((unsigned char *)target->base + target->used,
+ gp.ndata, (size_t)gp.length);
+ isc_buffer_add(target, gp.length);
+ go |= 0xc000;
+ if (target->length - target->used < 2)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putuint16(target, go);
+ if (gp.length != 0)
+ dns_compress_add(cctx, name, &gp, offset);
+ } else {
+ if (target->length - target->used < name->length)
+ return (ISC_R_NOSPACE);
+ (void)memcpy((unsigned char *)target->base + target->used,
+ name->ndata, (size_t)name->length);
+ isc_buffer_add(target, name->length);
+ dns_compress_add(cctx, name, name, offset);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name,
+ isc_buffer_t *target)
+{
+ unsigned char *ndata, *offsets;
+ unsigned int nrem, labels, prefix_length, length;
+ isc_boolean_t copy_prefix = ISC_TRUE;
+ isc_boolean_t copy_suffix = ISC_TRUE;
+ isc_boolean_t absolute = ISC_FALSE;
+ dns_name_t tmp_name;
+ dns_offsets_t odata;
+
+ /*
+ * Concatenate 'prefix' and 'suffix'.
+ */
+
+ REQUIRE(prefix == NULL || VALID_NAME(prefix));
+ REQUIRE(suffix == NULL || VALID_NAME(suffix));
+ REQUIRE(name == NULL || VALID_NAME(name));
+ REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
+ (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer)));
+ if (prefix == NULL || prefix->labels == 0)
+ copy_prefix = ISC_FALSE;
+ if (suffix == NULL || suffix->labels == 0)
+ copy_suffix = ISC_FALSE;
+ if (copy_prefix &&
+ (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) {
+ absolute = ISC_TRUE;
+ REQUIRE(!copy_suffix);
+ }
+ if (name == NULL) {
+ DNS_NAME_INIT(&tmp_name, odata);
+ name = &tmp_name;
+ }
+ if (target == NULL) {
+ INSIST(name->buffer != NULL);
+ target = name->buffer;
+ isc_buffer_clear(name->buffer);
+ }
+
+ REQUIRE(BINDABLE(name));
+
+ /*
+ * Set up.
+ */
+ nrem = target->length - target->used;
+ ndata = (unsigned char *)target->base + target->used;
+ if (nrem > DNS_NAME_MAXWIRE)
+ nrem = DNS_NAME_MAXWIRE;
+ length = 0;
+ prefix_length = 0;
+ labels = 0;
+ if (copy_prefix) {
+ prefix_length = prefix->length;
+ length += prefix_length;
+ labels += prefix->labels;
+ }
+ if (copy_suffix) {
+ length += suffix->length;
+ labels += suffix->labels;
+ }
+ if (length > DNS_NAME_MAXWIRE) {
+ MAKE_EMPTY(name);
+ return (DNS_R_NAMETOOLONG);
+ }
+ if (length > nrem) {
+ MAKE_EMPTY(name);
+ return (ISC_R_NOSPACE);
+ }
+
+ if (copy_suffix) {
+ if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
+ absolute = ISC_TRUE;
+ if (suffix == name && suffix->buffer == target)
+ memmove(ndata + prefix_length, suffix->ndata,
+ suffix->length);
+ else
+ memcpy(ndata + prefix_length, suffix->ndata,
+ suffix->length);
+ }
+
+ /*
+ * If 'prefix' and 'name' are the same object, and the object has
+ * a dedicated buffer, and we're using it, then we don't have to
+ * copy anything.
+ */
+ if (copy_prefix && (prefix != name || prefix->buffer != target))
+ memcpy(ndata, prefix->ndata, prefix_length);
+
+ name->ndata = ndata;
+ name->labels = labels;
+ name->length = length;
+ if (absolute)
+ name->attributes = DNS_NAMEATTR_ABSOLUTE;
+ else
+ name->attributes = 0;
+
+ if (name->labels > 0 && name->offsets != NULL) {
+ INIT_OFFSETS(name, offsets, odata);
+ set_offsets(name, offsets, NULL);
+ }
+
+ isc_buffer_add(target, name->length);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_name_split(dns_name_t *name, unsigned int suffixlabels,
+ dns_name_t *prefix, dns_name_t *suffix)
+
+{
+ unsigned int splitlabel;
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(suffixlabels > 0);
+ REQUIRE(suffixlabels < name->labels);
+ REQUIRE(prefix != NULL || suffix != NULL);
+ REQUIRE(prefix == NULL ||
+ (VALID_NAME(prefix) &&
+ prefix->buffer != NULL &&
+ BINDABLE(prefix)));
+ REQUIRE(suffix == NULL ||
+ (VALID_NAME(suffix) &&
+ suffix->buffer != NULL &&
+ BINDABLE(suffix)));
+
+ splitlabel = name->labels - suffixlabels;
+
+ if (prefix != NULL)
+ dns_name_getlabelsequence(name, 0, splitlabel, prefix);
+
+ if (suffix != NULL)
+ dns_name_getlabelsequence(name, splitlabel,
+ suffixlabels, suffix);
+
+ return;
+}
+
+isc_result_t
+dns_name_dup(const dns_name_t *source, isc_mem_t *mctx,
+ dns_name_t *target)
+{
+ /*
+ * Make 'target' a dynamically allocated copy of 'source'.
+ */
+
+ REQUIRE(VALID_NAME(source));
+ REQUIRE(source->length > 0);
+ REQUIRE(VALID_NAME(target));
+ REQUIRE(BINDABLE(target));
+
+ /*
+ * Make 'target' empty in case of failure.
+ */
+ MAKE_EMPTY(target);
+
+ target->ndata = isc_mem_get(mctx, source->length);
+ if (target->ndata == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memcpy(target->ndata, source->ndata, source->length);
+
+ target->length = source->length;
+ target->labels = source->labels;
+ target->attributes = DNS_NAMEATTR_DYNAMIC;
+ if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
+ target->attributes |= DNS_NAMEATTR_ABSOLUTE;
+ if (target->offsets != NULL) {
+ if (source->offsets != NULL)
+ memcpy(target->offsets, source->offsets,
+ source->labels);
+ else
+ set_offsets(target, target->offsets, NULL);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_name_dupwithoffsets(dns_name_t *source, isc_mem_t *mctx,
+ dns_name_t *target)
+{
+ /*
+ * Make 'target' a read-only dynamically allocated copy of 'source'.
+ * 'target' will also have a dynamically allocated offsets table.
+ */
+
+ REQUIRE(VALID_NAME(source));
+ REQUIRE(source->length > 0);
+ REQUIRE(VALID_NAME(target));
+ REQUIRE(BINDABLE(target));
+ REQUIRE(target->offsets == NULL);
+
+ /*
+ * Make 'target' empty in case of failure.
+ */
+ MAKE_EMPTY(target);
+
+ target->ndata = isc_mem_get(mctx, source->length + source->labels);
+ if (target->ndata == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memcpy(target->ndata, source->ndata, source->length);
+
+ target->length = source->length;
+ target->labels = source->labels;
+ target->attributes = DNS_NAMEATTR_DYNAMIC | DNS_NAMEATTR_DYNOFFSETS |
+ DNS_NAMEATTR_READONLY;
+ if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
+ target->attributes |= DNS_NAMEATTR_ABSOLUTE;
+ target->offsets = target->ndata + source->length;
+ if (source->offsets != NULL)
+ memcpy(target->offsets, source->offsets, source->labels);
+ else
+ set_offsets(target, target->offsets, NULL);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
+ size_t size;
+
+ /*
+ * Free 'name'.
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0);
+
+ size = name->length;
+ if ((name->attributes & DNS_NAMEATTR_DYNOFFSETS) != 0)
+ size += name->labels;
+ isc_mem_put(mctx, name->ndata, size);
+ dns_name_invalidate(name);
+}
+
+isc_result_t
+dns_name_digest(dns_name_t *name, dns_digestfunc_t digest, void *arg) {
+ dns_name_t downname;
+ unsigned char data[256];
+ isc_buffer_t buffer;
+ isc_result_t result;
+ isc_region_t r;
+
+ /*
+ * Send 'name' in DNSSEC canonical form to 'digest'.
+ */
+
+ REQUIRE(VALID_NAME(name));
+ REQUIRE(digest != NULL);
+
+ DNS_NAME_INIT(&downname, NULL);
+ isc_buffer_init(&buffer, data, sizeof(data));
+
+ result = dns_name_downcase(name, &downname, &buffer);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ isc_buffer_usedregion(&buffer, &r);
+
+ return ((digest)(arg, &r));
+}
+
+isc_boolean_t
+dns_name_dynamic(dns_name_t *name) {
+ REQUIRE(VALID_NAME(name));
+
+ /*
+ * Returns whether there is dynamic memory associated with this name.
+ */
+
+ return ((name->attributes & DNS_NAMEATTR_DYNAMIC) != 0 ?
+ ISC_TRUE : ISC_FALSE);
+}
+
+isc_result_t
+dns_name_print(dns_name_t *name, FILE *stream) {
+ isc_result_t result;
+ isc_buffer_t b;
+ isc_region_t r;
+ char t[1024];
+
+ /*
+ * Print 'name' on 'stream'.
+ */
+
+ REQUIRE(VALID_NAME(name));
+
+ isc_buffer_init(&b, t, sizeof(t));
+ result = dns_name_totext(name, ISC_FALSE, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_usedregion(&b, &r);
+ fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_name_settotextfilter(dns_name_totextfilter_t proc) {
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_result_t result;
+ dns_name_totextfilter_t *mem;
+ int res;
+
+ result = totext_filter_proc_key_init();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * If we already have been here set / clear as appropriate.
+ * Otherwise allocate memory.
+ */
+ mem = isc_thread_key_getspecific(totext_filter_proc_key);
+ if (mem != NULL && proc != NULL) {
+ *mem = proc;
+ return (ISC_R_SUCCESS);
+ }
+ if (proc == NULL) {
+ isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
+ res = isc_thread_key_setspecific(totext_filter_proc_key, NULL);
+ if (res != 0)
+ result = ISC_R_UNEXPECTED;
+ return (result);
+ }
+
+ mem = isc_mem_get(thread_key_mctx, sizeof(*mem));
+ if (mem == NULL)
+ return (ISC_R_NOMEMORY);
+ *mem = proc;
+ if (isc_thread_key_setspecific(totext_filter_proc_key, mem) != 0) {
+ isc_mem_put(thread_key_mctx, mem, sizeof(*mem));
+ result = ISC_R_UNEXPECTED;
+ }
+ return (result);
+#else
+ totext_filter_proc = proc;
+ return (ISC_R_SUCCESS);
+#endif
+}
+
+void
+dns_name_format(dns_name_t *name, char *cp, unsigned int size) {
+ isc_result_t result;
+ isc_buffer_t buf;
+
+ REQUIRE(size > 0);
+
+ /*
+ * Leave room for null termination after buffer.
+ */
+ isc_buffer_init(&buf, cp, size - 1);
+ result = dns_name_totext(name, ISC_TRUE, &buf);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Null terminate.
+ */
+ isc_region_t r;
+ isc_buffer_usedregion(&buf, &r);
+ ((char *) r.base)[r.length] = '\0';
+
+ } else
+ snprintf(cp, size, "<unknown>");
+}
+
+isc_result_t
+dns_name_copy(dns_name_t *source, dns_name_t *dest, isc_buffer_t *target) {
+ unsigned char *ndata;
+
+ /*
+ * Make dest a copy of source.
+ */
+
+ REQUIRE(VALID_NAME(source));
+ REQUIRE(VALID_NAME(dest));
+ REQUIRE(target != NULL || dest->buffer != NULL);
+
+ if (target == NULL) {
+ target = dest->buffer;
+ isc_buffer_clear(dest->buffer);
+ }
+
+ REQUIRE(BINDABLE(dest));
+
+ /*
+ * Set up.
+ */
+ if (target->length - target->used < source->length)
+ return (ISC_R_NOSPACE);
+
+ ndata = (unsigned char *)target->base + target->used;
+ dest->ndata = target->base;
+
+ memcpy(ndata, source->ndata, source->length);
+
+ dest->ndata = ndata;
+ dest->labels = source->labels;
+ dest->length = source->length;
+ if ((source->attributes & DNS_NAMEATTR_ABSOLUTE) != 0)
+ dest->attributes = DNS_NAMEATTR_ABSOLUTE;
+ else
+ dest->attributes = 0;
+
+ if (dest->labels > 0 && dest->offsets != NULL) {
+ if (source->offsets != NULL)
+ memcpy(dest->offsets, source->offsets, source->labels);
+ else
+ set_offsets(dest, dest->offsets, NULL);
+ }
+
+ isc_buffer_add(target, dest->length);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_name_destroy(void) {
+#ifdef ISC_PLATFORM_USETHREADS
+ RUNTIME_CHECK(isc_once_do(&once, thread_key_mutex_init)
+ == ISC_R_SUCCESS);
+
+ LOCK(&thread_key_mutex);
+ if (thread_key_initialized) {
+ isc_mem_detach(&thread_key_mctx);
+ isc_thread_key_delete(totext_filter_proc_key);
+ thread_key_initialized = 0;
+ }
+ UNLOCK(&thread_key_mutex);
+
+#endif
+}
diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c
new file mode 100644
index 0000000..af0450b
--- /dev/null
+++ b/lib/dns/ncache.c
@@ -0,0 +1,658 @@
+/*
+ * 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
+ * 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: ncache.c,v 1.43 2008/09/25 04:02:38 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/message.h>
+#include <dns/ncache.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+
+#define DNS_NCACHE_RDATA 20U
+
+/*
+ * The format of an ncache rdata is a sequence of one or more records of
+ * the following format:
+ *
+ * owner name
+ * type
+ * rdata count
+ * rdata length These two occur 'rdata count'
+ * rdata times.
+ *
+ */
+
+static inline isc_result_t
+copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
+ isc_result_t result;
+ unsigned int count;
+ isc_region_t ar, r;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ /*
+ * Copy the rdataset count to the buffer.
+ */
+ isc_buffer_availableregion(buffer, &ar);
+ if (ar.length < 2)
+ return (ISC_R_NOSPACE);
+ count = dns_rdataset_count(rdataset);
+ INSIST(count <= 65535);
+ isc_buffer_putuint16(buffer, (isc_uint16_t)count);
+
+ result = dns_rdataset_first(rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ dns_rdata_toregion(&rdata, &r);
+ INSIST(r.length <= 65535);
+ isc_buffer_availableregion(buffer, &ar);
+ if (ar.length < 2)
+ return (ISC_R_NOSPACE);
+ /*
+ * Copy the rdata length to the buffer.
+ */
+ isc_buffer_putuint16(buffer, (isc_uint16_t)r.length);
+ /*
+ * Copy the rdata to the buffer.
+ */
+ result = isc_buffer_copyregion(buffer, &r);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ return (result);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
+ dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
+ dns_rdataset_t *addedrdataset)
+{
+ return (dns_ncache_addoptout(message, cache, node, covers, now, maxttl,
+ ISC_FALSE, addedrdataset));
+}
+
+isc_result_t
+dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
+ dns_dbnode_t *node, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_ttl_t maxttl,
+ isc_boolean_t optout, dns_rdataset_t *addedrdataset)
+{
+ isc_result_t result;
+ isc_buffer_t buffer;
+ isc_region_t r;
+ dns_rdataset_t *rdataset;
+ dns_rdatatype_t type;
+ dns_name_t *name;
+ dns_ttl_t ttl;
+ dns_trust_t trust;
+ dns_rdata_t rdata[DNS_NCACHE_RDATA];
+ dns_rdataset_t ncrdataset;
+ dns_rdatalist_t ncrdatalist;
+ unsigned char data[4096];
+ unsigned int next = 0;
+
+ /*
+ * Convert the authority data from 'message' into a negative cache
+ * rdataset, and store it in 'cache' at 'node'.
+ */
+
+ REQUIRE(message != NULL);
+
+ /*
+ * We assume that all data in the authority section has been
+ * validated by the caller.
+ */
+
+ /*
+ * Initialize the list.
+ */
+ ncrdatalist.rdclass = dns_db_class(cache);
+ ncrdatalist.type = 0;
+ ncrdatalist.covers = covers;
+ ncrdatalist.ttl = maxttl;
+ ISC_LIST_INIT(ncrdatalist.rdata);
+ ISC_LINK_INIT(&ncrdatalist, link);
+
+ /*
+ * Build an ncache rdatas into buffer.
+ */
+ ttl = maxttl;
+ trust = 0xffff;
+ isc_buffer_init(&buffer, data, sizeof(data));
+ if (message->counts[DNS_SECTION_AUTHORITY])
+ result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ else
+ result = ISC_R_NOMORE;
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY,
+ &name);
+ if ((name->attributes & DNS_NAMEATTR_NCACHE) != 0) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if ((rdataset->attributes &
+ DNS_RDATASETATTR_NCACHE) == 0)
+ continue;
+ type = rdataset->type;
+ if (type == dns_rdatatype_rrsig)
+ type = rdataset->covers;
+ if (type == dns_rdatatype_soa ||
+ type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3) {
+ if (ttl > rdataset->ttl)
+ ttl = rdataset->ttl;
+ if (trust > rdataset->trust)
+ trust = rdataset->trust;
+ /*
+ * Copy the owner name to the buffer.
+ */
+ dns_name_toregion(name, &r);
+ result = isc_buffer_copyregion(&buffer,
+ &r);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ /*
+ * Copy the type to the buffer.
+ */
+ isc_buffer_availableregion(&buffer,
+ &r);
+ if (r.length < 2)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putuint16(&buffer,
+ rdataset->type);
+ /*
+ * Copy the rdataset into the buffer.
+ */
+ result = copy_rdataset(rdataset,
+ &buffer);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ 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);
+ isc_buffer_forward(&buffer, r.length);
+ next++;
+ }
+ }
+ }
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
+ }
+ if (result != ISC_R_NOMORE)
+ 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 < 4)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putuint16(&buffer, 0);
+ isc_buffer_putuint16(&buffer, 0);
+ /*
+ * 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) {
+ /*
+ * The response has aa set and we haven't followed
+ * any CNAME or DNAME chains.
+ */
+ trust = dns_trust_authauthority;
+ } else
+ trust = dns_trust_additional;
+ /*
+ * 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);
+ }
+
+ INSIST(trust != 0xffff);
+
+ ncrdatalist.ttl = ttl;
+
+ dns_rdataset_init(&ncrdataset);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
+ == ISC_R_SUCCESS);
+ ncrdataset.trust = trust;
+ if (message->rcode == dns_rcode_nxdomain)
+ ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN;
+ if (optout)
+ ncrdataset.attributes |= DNS_RDATASETATTR_OPTOUT;
+
+ return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset,
+ 0, addedrdataset));
+}
+
+isc_result_t
+dns_ncache_towire(dns_rdataset_t *rdataset, dns_compress_t *cctx,
+ isc_buffer_t *target, unsigned int options,
+ unsigned int *countp)
+{
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ isc_region_t remaining, tavailable;
+ isc_buffer_t source, savedbuffer, rdlen;
+ dns_name_t name;
+ dns_rdatatype_t type;
+ unsigned int i, rcount, count;
+
+ /*
+ * Convert the negative caching rdataset 'rdataset' to wire format,
+ * compressing names as specified in 'cctx', and storing the result in
+ * 'target'.
+ */
+
+ REQUIRE(rdataset != NULL);
+ REQUIRE(rdataset->type == 0);
+
+ savedbuffer = *target;
+ count = 0;
+
+ result = dns_rdataset_first(rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
+ dns_name_init(&name, NULL);
+ isc_buffer_remainingregion(&source, &remaining);
+ dns_name_fromregion(&name, &remaining);
+ INSIST(remaining.length >= name.length);
+ isc_buffer_forward(&source, name.length);
+ remaining.length -= name.length;
+
+ INSIST(remaining.length >= 4);
+ type = isc_buffer_getuint16(&source);
+ rcount = isc_buffer_getuint16(&source);
+
+ for (i = 0; i < rcount; i++) {
+ /*
+ * Get the length of this rdata and set up an
+ * rdata structure for it.
+ */
+ isc_buffer_remainingregion(&source, &remaining);
+ INSIST(remaining.length >= 2);
+ dns_rdata_reset(&rdata);
+ rdata.length = isc_buffer_getuint16(&source);
+ isc_buffer_remainingregion(&source, &remaining);
+ rdata.data = remaining.base;
+ rdata.type = type;
+ rdata.rdclass = rdataset->rdclass;
+ INSIST(remaining.length >= rdata.length);
+ isc_buffer_forward(&source, rdata.length);
+
+ if ((options & DNS_NCACHETOWIRE_OMITDNSSEC) != 0 &&
+ dns_rdatatype_isdnssec(type))
+ continue;
+
+ /*
+ * Write the name.
+ */
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+ result = dns_name_towire(&name, cctx, target);
+ if (result != ISC_R_SUCCESS)
+ goto rollback;
+
+ /*
+ * See if we have space for type, class, ttl, and
+ * rdata length. Write the type, class, and ttl.
+ */
+ isc_buffer_availableregion(target, &tavailable);
+ if (tavailable.length < 10) {
+ result = ISC_R_NOSPACE;
+ goto rollback;
+ }
+ isc_buffer_putuint16(target, type);
+ isc_buffer_putuint16(target, rdataset->rdclass);
+ isc_buffer_putuint32(target, rdataset->ttl);
+
+ /*
+ * Save space for rdata length.
+ */
+ rdlen = *target;
+ isc_buffer_add(target, 2);
+
+ /*
+ * Write the rdata.
+ */
+ result = dns_rdata_towire(&rdata, cctx, target);
+ if (result != ISC_R_SUCCESS)
+ goto rollback;
+
+ /*
+ * Set the rdata length field to the compressed
+ * length.
+ */
+ INSIST((target->used >= rdlen.used + 2) &&
+ (target->used - rdlen.used - 2 < 65536));
+ isc_buffer_putuint16(&rdlen,
+ (isc_uint16_t)(target->used -
+ rdlen.used - 2));
+
+ count++;
+ }
+ INSIST(isc_buffer_remaininglength(&source) == 0);
+ result = dns_rdataset_next(rdataset);
+ dns_rdata_reset(&rdata);
+ }
+ if (result != ISC_R_NOMORE)
+ goto rollback;
+
+ *countp = count;
+
+ return (ISC_R_SUCCESS);
+
+ rollback:
+ INSIST(savedbuffer.used < 65536);
+ dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
+ *countp = 0;
+ *target = savedbuffer;
+
+ return (result);
+}
+
+static void
+rdataset_disassociate(dns_rdataset_t *rdataset) {
+ UNUSED(rdataset);
+}
+
+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;
+
+ REQUIRE(raw != NULL);
+
+ r.length = raw[0] * 256 + raw[1];
+ raw += 2;
+ r.base = raw;
+ dns_rdata_fromregion(rdata, rdataset->rdclass, rdataset->type, &r);
+}
+
+static void
+rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
+ *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 dns_rdatasetmethods_t rdataset_methods = {
+ rdataset_disassociate,
+ rdataset_first,
+ rdataset_next,
+ rdataset_current,
+ rdataset_clone,
+ rdataset_count,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+isc_result_t
+dns_ncache_getrdataset(dns_rdataset_t *ncacherdataset, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdataset_t *rdataset)
+{
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t remaining;
+ isc_buffer_t source;
+ dns_name_t tname;
+ dns_rdatatype_t ttype;
+
+ REQUIRE(ncacherdataset != NULL);
+ REQUIRE(ncacherdataset->type == 0);
+ REQUIRE(name != NULL);
+ REQUIRE(!dns_rdataset_isassociated(rdataset));
+ REQUIRE(type != dns_rdatatype_rrsig);
+
+ result = dns_rdataset_first(ncacherdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(ncacherdataset, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
+ dns_name_init(&tname, NULL);
+ isc_buffer_remainingregion(&source, &remaining);
+ dns_name_fromregion(&tname, &remaining);
+ INSIST(remaining.length >= tname.length);
+ isc_buffer_forward(&source, tname.length);
+ remaining.length -= tname.length;
+
+ INSIST(remaining.length >= 4);
+ ttype = isc_buffer_getuint16(&source);
+
+ if (ttype == type && dns_name_equal(&tname, name)) {
+ isc_buffer_remainingregion(&source, &remaining);
+ break;
+ }
+ result = dns_rdataset_next(ncacherdataset);
+ dns_rdata_reset(&rdata);
+ }
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_NOTFOUND);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ INSIST(remaining.length != 0);
+
+ rdataset->methods = &rdataset_methods;
+ rdataset->rdclass = ncacherdataset->rdclass;
+ rdataset->type = type;
+ rdataset->covers = 0;
+ rdataset->ttl = ncacherdataset->ttl;
+ rdataset->trust = ncacherdataset->trust;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+
+ rdataset->private3 = remaining.base;
+
+ /*
+ * Reset iterator state.
+ */
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+ rdataset->private6 = NULL;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_ncache_current(dns_rdataset_t *ncacherdataset, dns_name_t *found,
+ dns_rdataset_t *rdataset)
+{
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t remaining, sigregion;
+ isc_buffer_t source;
+ dns_name_t tname;
+ dns_rdatatype_t type;
+ unsigned int count;
+ dns_rdata_rrsig_t rrsig;
+ unsigned char *raw;
+
+ REQUIRE(ncacherdataset != NULL);
+ REQUIRE(ncacherdataset->type == 0);
+ REQUIRE(found != NULL);
+ REQUIRE(!dns_rdataset_isassociated(rdataset));
+
+ dns_rdataset_current(ncacherdataset, &rdata);
+ isc_buffer_init(&source, rdata.data, rdata.length);
+ isc_buffer_add(&source, rdata.length);
+
+ dns_name_init(&tname, NULL);
+ isc_buffer_remainingregion(&source, &remaining);
+ dns_name_fromregion(found, &remaining);
+ INSIST(remaining.length >= found->length);
+ isc_buffer_forward(&source, found->length);
+ remaining.length -= found->length;
+
+ INSIST(remaining.length >= 4);
+ type = isc_buffer_getuint16(&source);
+ isc_buffer_remainingregion(&source, &remaining);
+
+ rdataset->methods = &rdataset_methods;
+ rdataset->rdclass = ncacherdataset->rdclass;
+ rdataset->type = type;
+ if (type == dns_rdatatype_rrsig) {
+ /*
+ * Extract covers from RRSIG.
+ */
+ raw = remaining.base;
+ count = raw[0] * 256 + raw[1];
+ INSIST(count > 0);
+ raw += 2;
+ sigregion.length = raw[0] * 256 + raw[1];
+ raw += 2;
+ sigregion.base = raw;
+ dns_rdata_reset(&rdata);
+ dns_rdata_fromregion(&rdata, rdataset->rdclass,
+ rdataset->type, &sigregion);
+ (void)dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ rdataset->covers = rrsig.covered;
+ } else
+ rdataset->covers = 0;
+ rdataset->ttl = ncacherdataset->ttl;
+ rdataset->trust = ncacherdataset->trust;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+
+ rdataset->private3 = remaining.base;
+
+ /*
+ * Reset iterator state.
+ */
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+ rdataset->private6 = NULL;
+}
diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c
new file mode 100644
index 0000000..53a3b5e
--- /dev/null
+++ b/lib/dns/nsec.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 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
+ * 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: nsec.c,v 1.11 2008/09/25 04:02:38 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/nsec.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+
+#include <dst/dst.h>
+
+#define RETERR(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
+static void
+set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
+ unsigned int shift, mask;
+
+ shift = 7 - (index % 8);
+ mask = 1 << shift;
+
+ if (bit != 0)
+ array[index / 8] |= mask;
+ else
+ array[index / 8] &= (~mask & 0xFF);
+}
+
+static unsigned int
+bit_isset(unsigned char *array, unsigned int index) {
+ unsigned int byte, shift, mask;
+
+ byte = array[index / 8];
+ shift = 7 - (index % 8);
+ mask = 1 << shift;
+
+ return ((byte & mask) != 0);
+}
+
+isc_result_t
+dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
+ dns_dbnode_t *node, dns_name_t *target,
+ unsigned char *buffer, dns_rdata_t *rdata)
+{
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ isc_region_t r;
+ unsigned int i, window;
+ int octet;
+
+ unsigned char *nsec_bits, *bm;
+ unsigned int max_type;
+ dns_rdatasetiter_t *rdsiter;
+
+ memset(buffer, 0, DNS_NSEC_BUFFERSIZE);
+ dns_name_toregion(target, &r);
+ memcpy(buffer, r.base, r.length);
+ r.base = buffer;
+ /*
+ * Use the end of the space for a raw bitmap leaving enough
+ * space for the window identifiers and length octets.
+ */
+ bm = r.base + r.length + 512;
+ nsec_bits = r.base + r.length;
+ set_bit(bm, dns_rdatatype_rrsig, 1);
+ set_bit(bm, dns_rdatatype_nsec, 1);
+ max_type = dns_rdatatype_nsec;
+ dns_rdataset_init(&rdataset);
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ 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_nsec &&
+ rdataset.type != dns_rdatatype_nsec3 &&
+ rdataset.type != dns_rdatatype_rrsig) {
+ if (rdataset.type > max_type)
+ max_type = rdataset.type;
+ set_bit(bm, rdataset.type, 1);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ }
+
+ /*
+ * At zone cuts, deny the existence of glue in the parent zone.
+ */
+ if (bit_isset(bm, dns_rdatatype_ns) &&
+ ! bit_isset(bm, dns_rdatatype_soa)) {
+ for (i = 0; i <= max_type; i++) {
+ if (bit_isset(bm, i) &&
+ ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
+ set_bit(bm, i, 0);
+ }
+ }
+
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result != ISC_R_NOMORE)
+ return (result);
+
+ for (window = 0; window < 256; window++) {
+ if (window * 256 > max_type)
+ break;
+ for (octet = 31; octet >= 0; octet--)
+ if (bm[window * 32 + octet] != 0)
+ break;
+ if (octet < 0)
+ continue;
+ nsec_bits[0] = window;
+ nsec_bits[1] = octet + 1;
+ /*
+ * Note: potential overlapping move.
+ */
+ memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
+ nsec_bits += 3 + octet;
+ }
+ r.length = nsec_bits - r.base;
+ INSIST(r.length <= DNS_NSEC_BUFFERSIZE);
+ dns_rdata_fromregion(rdata,
+ dns_db_class(db),
+ dns_rdatatype_nsec,
+ &r);
+
+ return (ISC_R_SUCCESS);
+}
+
+
+isc_result_t
+dns_nsec_build(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
+ dns_name_t *target, dns_ttl_t ttl)
+{
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned char data[DNS_NSEC_BUFFERSIZE];
+ dns_rdatalist_t rdatalist;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ dns_rdata_init(&rdata);
+
+ RETERR(dns_nsec_buildrdata(db, version, node, target, data, &rdata));
+
+ rdatalist.rdclass = dns_db_class(db);
+ rdatalist.type = dns_rdatatype_nsec;
+ rdatalist.covers = 0;
+ rdatalist.ttl = ttl;
+ ISC_LIST_INIT(rdatalist.rdata);
+ ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
+ RETERR(dns_rdatalist_tordataset(&rdatalist, &rdataset));
+ result = dns_db_addrdataset(db, node, version, 0, &rdataset,
+ 0, NULL);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ RETERR(result);
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+isc_boolean_t
+dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type) {
+ dns_rdata_nsec_t nsecstruct;
+ isc_result_t result;
+ isc_boolean_t present;
+ unsigned int i, len, window;
+
+ REQUIRE(nsec != NULL);
+ REQUIRE(nsec->type == dns_rdatatype_nsec);
+
+ /* This should never fail */
+ result = dns_rdata_tostruct(nsec, &nsecstruct, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+
+ present = ISC_FALSE;
+ for (i = 0; i < nsecstruct.len; i += len) {
+ INSIST(i + 2 <= nsecstruct.len);
+ window = nsecstruct.typebits[i];
+ len = nsecstruct.typebits[i + 1];
+ INSIST(len > 0 && len <= 32);
+ i += 2;
+ INSIST(i + len <= nsecstruct.len);
+ if (window * 256 > type)
+ break;
+ if ((window + 1) * 256 <= type)
+ continue;
+ if (type < (window * 256) + len * 8)
+ present = ISC_TF(bit_isset(&nsecstruct.typebits[i],
+ type % 256));
+ break;
+ }
+ dns_rdata_freestruct(&nsec);
+ return (present);
+}
+
+isc_result_t
+dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version,
+ isc_boolean_t *answer)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_dnskey_t dnskey;
+ isc_result_t result;
+
+ REQUIRE(answer != NULL);
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
+ 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_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (dnskey.algorithm == DST_ALG_RSAMD5 ||
+ dnskey.algorithm == DST_ALG_RSASHA1 ||
+ dnskey.algorithm == DST_ALG_DSA ||
+ dnskey.algorithm == DST_ALG_ECC)
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_SUCCESS)
+ *answer = ISC_TRUE;
+ if (result == ISC_R_NOMORE) {
+ *answer = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ }
+ return (result);
+}
diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c
new file mode 100644
index 0000000..54a6993
--- /dev/null
+++ b/lib/dns/nsec3.c
@@ -0,0 +1,1377 @@
+/*
+ * Copyright (C) 2006, 2008 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: nsec3.c,v 1.6 2008/11/17 23:46:42 marka Exp $ */
+
+#include <config.h>
+
+#include <isc/base32.h>
+#include <isc/buffer.h>
+#include <isc/hex.h>
+#include <isc/iterated_hash.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dst/dst.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/diff.h>
+#include <dns/fixedname.h>
+#include <dns/nsec3.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+
+#define CHECK(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
+#define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
+#define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
+#define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
+
+static void
+set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
+ unsigned int shift, mask;
+
+ shift = 7 - (index % 8);
+ mask = 1 << shift;
+
+ if (bit != 0)
+ array[index / 8] |= mask;
+ else
+ array[index / 8] &= (~mask & 0xFF);
+}
+
+static unsigned int
+bit_isset(unsigned char *array, unsigned int index) {
+ unsigned int byte, shift, mask;
+
+ byte = array[index / 8];
+ shift = 7 - (index % 8);
+ mask = 1 << shift;
+
+ return ((byte & mask) != 0);
+}
+
+isc_result_t
+dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
+ dns_dbnode_t *node, unsigned int hashalg,
+ unsigned int flags, unsigned int iterations,
+ const unsigned char *salt, size_t salt_length,
+ const unsigned char *nexthash, size_t hash_length,
+ unsigned char *buffer, dns_rdata_t *rdata)
+{
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ isc_region_t r;
+ unsigned int i, window;
+ int octet;
+ isc_boolean_t found;
+
+ unsigned char *nsec_bits, *bm;
+ unsigned int max_type;
+ dns_rdatasetiter_t *rdsiter;
+ unsigned char *p;
+
+ REQUIRE(salt_length < 256U);
+ REQUIRE(hash_length < 256U);
+ REQUIRE(flags <= 0xffU);
+ REQUIRE(hashalg <= 0xffU);
+ REQUIRE(iterations <= 0xffffU);
+
+ switch (hashalg) {
+ case dns_hash_sha1:
+ REQUIRE(hash_length == ISC_SHA1_DIGESTLENGTH);
+ break;
+ }
+
+ memset(buffer, 0, DNS_NSEC3_BUFFERSIZE);
+
+ p = buffer;
+
+ *p++ = hashalg;
+ *p++ = flags;
+
+ *p++ = iterations >> 8;
+ *p++ = iterations;
+
+ *p++ = salt_length;
+ memcpy(p, salt, salt_length);
+ p += salt_length;
+
+ *p++ = hash_length;
+ memcpy(p, nexthash, hash_length);
+ p += hash_length;
+
+ r.length = p - buffer;
+ r.base = buffer;
+
+ /*
+ * Use the end of the space for a raw bitmap leaving enough
+ * space for the window identifiers and length octets.
+ */
+ bm = r.base + r.length + 512;
+ nsec_bits = r.base + r.length;
+ max_type = 0;
+ if (node == NULL)
+ goto collapse_bitmap;
+ dns_rdataset_init(&rdataset);
+ rdsiter = NULL;
+ result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ found = ISC_FALSE;
+ 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_nsec &&
+ rdataset.type != dns_rdatatype_nsec3 &&
+ rdataset.type != dns_rdatatype_rrsig) {
+ if (rdataset.type > max_type)
+ max_type = rdataset.type;
+ set_bit(bm, rdataset.type, 1);
+ /* Don't set RRSIG for insecure delegation. */
+ if (rdataset.type != dns_rdatatype_ns)
+ found = ISC_TRUE;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (found) {
+ if (dns_rdatatype_rrsig > max_type)
+ max_type = dns_rdatatype_rrsig;
+ set_bit(bm, dns_rdatatype_rrsig, 1);
+ }
+
+ /*
+ * At zone cuts, deny the existence of glue in the parent zone.
+ */
+ if (bit_isset(bm, dns_rdatatype_ns) &&
+ ! bit_isset(bm, dns_rdatatype_soa)) {
+ for (i = 0; i <= max_type; i++) {
+ if (bit_isset(bm, i) &&
+ ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
+ set_bit(bm, i, 0);
+ }
+ }
+
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (result != ISC_R_NOMORE)
+ return (result);
+
+ collapse_bitmap:
+ for (window = 0; window < 256; window++) {
+ if (window * 256 > max_type)
+ break;
+ for (octet = 31; octet >= 0; octet--)
+ if (bm[window * 32 + octet] != 0)
+ break;
+ if (octet < 0)
+ continue;
+ nsec_bits[0] = window;
+ nsec_bits[1] = octet + 1;
+ /*
+ * Note: potentially overlapping move.
+ */
+ memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
+ nsec_bits += 3 + octet;
+ }
+ r.length = nsec_bits - r.base;
+ INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
+ dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+dns_nsec3_typepresent(dns_rdata_t *rdata, dns_rdatatype_t type) {
+ dns_rdata_nsec3_t nsec3;
+ isc_result_t result;
+ isc_boolean_t present;
+ unsigned int i, len, window;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(rdata->type == dns_rdatatype_nsec3);
+
+ /* This should never fail */
+ result = dns_rdata_tostruct(rdata, &nsec3, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+
+ present = ISC_FALSE;
+ for (i = 0; i < nsec3.len; i += len) {
+ INSIST(i + 2 <= nsec3.len);
+ window = nsec3.typebits[i];
+ len = nsec3.typebits[i + 1];
+ INSIST(len > 0 && len <= 32);
+ i += 2;
+ INSIST(i + len <= nsec3.len);
+ if (window * 256 > type)
+ break;
+ if ((window + 1) * 256 <= type)
+ continue;
+ if (type < (window * 256) + len * 8)
+ present = ISC_TF(bit_isset(&nsec3.typebits[i],
+ type % 256));
+ break;
+ }
+ dns_rdata_freestruct(&nsec3);
+ return (present);
+}
+
+isc_result_t
+dns_nsec3_hashname(dns_fixedname_t *result,
+ unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
+ size_t *hash_length, dns_name_t *name, dns_name_t *origin,
+ dns_hash_t hashalg, unsigned int iterations,
+ const unsigned char *salt, size_t saltlength)
+{
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char nametext[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fixed;
+ dns_name_t *downcased;
+ isc_buffer_t namebuffer;
+ isc_region_t region;
+ size_t len;
+
+ if (rethash == NULL)
+ rethash = hash;
+
+ memset(rethash, 0, NSEC3_MAX_HASH_LENGTH);
+
+ dns_fixedname_init(&fixed);
+ downcased = dns_fixedname_name(&fixed);
+ dns_name_downcase(name, downcased, NULL);
+
+ /* hash the node name */
+ len = isc_iterated_hash(rethash, hashalg, iterations, salt, saltlength,
+ downcased->ndata, downcased->length);
+ if (len == 0U)
+ return (DNS_R_BADALG);
+
+ if (hash_length != NULL)
+ *hash_length = len;
+
+ /* convert the hash to base32hex */
+ region.base = rethash;
+ region.length = len;
+ isc_buffer_init(&namebuffer, nametext, sizeof nametext);
+ isc_base32hex_totext(&region, 1, "", &namebuffer);
+
+ /* convert the hex to a domain name */
+ dns_fixedname_init(result);
+ return (dns_name_fromtext(dns_fixedname_name(result), &namebuffer,
+ origin, 0, NULL));
+}
+
+unsigned int
+dns_nsec3_hashlength(dns_hash_t hash) {
+
+ switch (hash) {
+ case dns_hash_sha1: return(ISC_SHA1_DIGESTLENGTH);
+ }
+ return (0);
+}
+
+isc_boolean_t
+dns_nsec3_supportedhash(dns_hash_t hash) {
+ switch (hash) {
+ case dns_hash_sha1: return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
+/*%
+ * Update a single RR in version 'ver' of 'db' and log the
+ * update in 'diff'.
+ *
+ * Ensures:
+ * \li '*tuple' == NULL. Either the tuple is freed, or its
+ * ownership has been transferred to the diff.
+ */
+static isc_result_t
+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;
+
+ /*
+ * 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);
+ if (result != ISC_R_SUCCESS) {
+ dns_difftuple_free(tuple);
+ return (result);
+ }
+
+ /*
+ * Merge it into the current pending journal entry.
+ */
+ dns_diff_appendminimal(diff, tuple);
+
+ /*
+ * Do not clear temp_diff.
+ */
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Set '*exists' to true iff the given name exists, to false otherwise.
+ */
+static isc_result_t
+name_exists(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ isc_boolean_t *exists)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdatasetiter_t *iter = NULL;
+
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND) {
+ *exists = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_allrdatasets(db, node, version,
+ (isc_stdtime_t) 0, &iter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ result = dns_rdatasetiter_first(iter);
+ if (result == ISC_R_SUCCESS) {
+ *exists = ISC_TRUE;
+ } else if (result == ISC_R_NOMORE) {
+ *exists = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ } else
+ *exists = ISC_FALSE;
+ dns_rdatasetiter_destroy(&iter);
+
+ cleanup_node:
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+static isc_boolean_t
+match_nsec3param(const dns_rdata_nsec3_t *nsec3,
+ const dns_rdata_nsec3param_t *nsec3param)
+{
+ if (nsec3->hash == nsec3param->hash &&
+ nsec3->iterations == nsec3param->iterations &&
+ nsec3->salt_length == nsec3param->salt_length &&
+ !memcmp(nsec3->salt, nsec3param->salt, nsec3->salt_length))
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+/*%
+ * Delete NSEC3 records at "name" which match "param", recording the
+ * change in "diff".
+ */
+static isc_result_t
+delete(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
+{
+ dns_dbnode_t *node = NULL ;
+ dns_difftuple_t *tuple = NULL;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ goto cleanup_node;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node;
+
+ 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, &nsec3, NULL));
+
+ if (!match_nsec3param(&nsec3, nsec3param))
+ continue;
+
+ result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata, &tuple);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ result = do_one_tuple(&tuple, db, version, diff);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ result = ISC_R_SUCCESS;
+
+ failure:
+ dns_rdataset_disassociate(&rdataset);
+ cleanup_node:
+ dns_db_detachnode(db, &node);
+
+ return (result);
+}
+
+#ifndef RFC5155_STRICT
+static isc_boolean_t
+better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ if (REMOVE(param->data[1]))
+ return (ISC_TRUE);
+
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_clone(nsec3paramset, &rdataset);
+ 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);
+ if (rdata.length != param->length)
+ continue;
+ if (rdata.data[0] != param->data[0] ||
+ REMOVE(rdata.data[1]) ||
+ rdata.data[2] != param->data[2] ||
+ rdata.data[3] != param->data[3] ||
+ rdata.data[4] != param->data[4] ||
+ memcmp(&rdata.data[5], &param->data[5], param->data[4]))
+ continue;
+ if (CREATE(rdata.data[1]) && !CREATE(param->data[1])) {
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_TRUE);
+ }
+ }
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_FALSE);
+}
+#endif
+
+static isc_result_t
+find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset,
+ const dns_rdata_nsec3param_t *nsec3param)
+{
+ isc_result_t 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);
+ CHECK(dns_rdata_tostruct(&rdata, nsec3, NULL));
+ dns_rdata_reset(&rdata);
+ if (match_nsec3param(nsec3, nsec3param))
+ break;
+ }
+ failure:
+ return (result);
+}
+
+isc_result_t
+dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
+ dns_name_t *name, const dns_rdata_nsec3param_t *nsec3param,
+ dns_ttl_t nsecttl, isc_boolean_t unsecure, dns_diff_t *diff)
+{
+ dns_dbiterator_t *dbit = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_dbnode_t *newnode = NULL;
+ dns_difftuple_t *tuple = NULL;
+ dns_fixedname_t fixed;
+ dns_fixedname_t fprev;
+ dns_hash_t hash;
+ dns_name_t *hashname;
+ dns_name_t *origin;
+ dns_name_t *prev;
+ dns_name_t empty;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ int pass;
+ isc_boolean_t exists;
+ isc_boolean_t remove_unsecure = ISC_FALSE;
+ isc_uint8_t flags;
+ isc_buffer_t buffer;
+ isc_result_t result;
+ unsigned char *old_next;
+ unsigned char *salt;
+ unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
+ unsigned int iterations;
+ unsigned int labels;
+ size_t next_length;
+ unsigned int old_length;
+ unsigned int salt_length;
+
+ dns_fixedname_init(&fixed);
+ hashname = dns_fixedname_name(&fixed);
+ dns_fixedname_init(&fprev);
+ prev = dns_fixedname_name(&fprev);
+
+ dns_rdataset_init(&rdataset);
+
+ origin = dns_db_origin(db);
+
+ /*
+ * Chain parameters.
+ */
+ hash = nsec3param->hash;
+ iterations = nsec3param->iterations;
+ salt_length = nsec3param->salt_length;
+ salt = nsec3param->salt;
+
+ /*
+ * Default flags for a new chain.
+ */
+ flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
+
+ /*
+ * If this is the first NSEC3 in the chain nexthash will
+ * remain pointing to itself.
+ */
+ next_length = sizeof(nexthash);
+ CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
+ name, origin, hash, iterations,
+ salt, salt_length));
+
+ /*
+ * Create the node if it doesn't exist and hold
+ * a reference to it until we have added the NSEC3.
+ */
+ CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
+
+ /*
+ * Seek the iterator to the 'newnode'.
+ */
+ CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
+ CHECK(dns_dbiterator_seek(dbit, hashname));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, newnode, version, dns_rdatatype_nsec3,
+ 0, (isc_stdtime_t) 0, &rdataset, NULL);
+ /*
+ * If we updating a existing NSEC3 then find its
+ * next field.
+ */
+ if (result == ISC_R_SUCCESS) {
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_SUCCESS) {
+ if (!CREATE(nsec3param->flags))
+ flags = nsec3.flags;
+ next_length = nsec3.next_length;
+ INSIST(next_length <= sizeof(nexthash));
+ memcpy(nexthash, nsec3.next, next_length);
+ dns_rdataset_disassociate(&rdataset);
+ /*
+ * If the NSEC3 is not for a unsecure delegation then
+ * we are just updating it. If it is for a unsecure
+ * delegation then we need find out if we need to
+ * remove the NSEC3 record or not by examining the
+ * previous NSEC3 record.
+ */
+ if (!unsecure)
+ goto addnsec3;
+ else
+ remove_unsecure = ISC_TRUE;
+ } else {
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ }
+ }
+
+ /*
+ * Find the previous NSEC3 (if any) and update it if required.
+ */
+ pass = 0;
+ do {
+ result = dns_dbiterator_prev(dbit);
+ if (result == ISC_R_NOMORE) {
+ pass++;
+ CHECK(dns_dbiterator_last(dbit));
+ }
+ CHECK(dns_dbiterator_current(dbit, &node, prev));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0, &rdataset,
+ NULL);
+ dns_db_detachnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_NOMORE) {
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ if (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 (!OPTOUT(nsec3.flags)) {
+ /*
+ * Just update the NSEC3 record.
+ */
+ goto addnsec3;
+ } else {
+ /*
+ * This is actually a deletion not a add.
+ */
+ result = dns_nsec3_delnsec3(db, version, name,
+ nsec3param, diff);
+ goto failure;
+ }
+ } else {
+ /*
+ * Is this is a unsecure delegation we are adding?
+ * If so no change is required.
+ */
+ if (OPTOUT(nsec3.flags) && unsecure) {
+ dns_rdataset_disassociate(&rdataset);
+ goto failure;
+ }
+ }
+
+ old_next = nsec3.next;
+ old_length = nsec3.next_length;
+
+ /*
+ * Delete the old previous NSEC3.
+ */
+ CHECK(delete(db, version, prev, nsec3param, diff));
+
+ /*
+ * Fixup the previous NSEC3.
+ */
+ nsec3.next = nexthash;
+ nsec3.next_length = next_length;
+ isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
+ CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
+ dns_rdatatype_nsec3, &nsec3,
+ &buffer));
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
+ rdataset.ttl, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ INSIST(old_length <= sizeof(nexthash));
+ memcpy(nexthash, old_next, old_length);
+ if (!CREATE(nsec3param->flags))
+ flags = nsec3.flags;
+ dns_rdata_reset(&rdata);
+ dns_rdataset_disassociate(&rdataset);
+ break;
+ } while (pass < 2);
+
+ addnsec3:
+ /*
+ * Create the NSEC3 RDATA.
+ */
+ CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
+ CHECK(dns_nsec3_buildrdata(db, version, node, hash, flags, iterations,
+ salt, salt_length, nexthash, next_length,
+ nsec3buf, &rdata));
+ dns_db_detachnode(db, &node);
+
+ /*
+ * Delete the old NSEC3 and record the change.
+ */
+ CHECK(delete(db, version, hashname, nsec3param, diff));
+ /*
+ * Add the new NSEC3 and record the change.
+ */
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ hashname, nsecttl, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ INSIST(tuple == NULL);
+ dns_rdata_reset(&rdata);
+ dns_db_detachnode(db, &newnode);
+
+ /*
+ * Add missing NSEC3 records for empty nodes
+ */
+ dns_name_init(&empty, NULL);
+ dns_name_clone(name, &empty);
+ do {
+ labels = dns_name_countlabels(&empty) - 1;
+ if (labels <= dns_name_countlabels(origin))
+ break;
+ dns_name_getlabelsequence(&empty, 1, labels, &empty);
+ CHECK(name_exists(db, version, &empty, &exists));
+ if (exists)
+ break;
+ CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
+ &empty, origin, hash, iterations,
+ salt, salt_length));
+
+ /*
+ * Create the node if it doesn't exist and hold
+ * a reference to it until we have added the NSEC3
+ * or we discover we don't need to add make a change.
+ */
+ CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
+ result = dns_db_findrdataset(db, newnode, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0, &rdataset,
+ NULL);
+ if (result == ISC_R_SUCCESS) {
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_SUCCESS) {
+ dns_db_detachnode(db, &newnode);
+ break;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ }
+
+ /*
+ * Find the previous NSEC3 and update it.
+ */
+ CHECK(dns_dbiterator_seek(dbit, hashname));
+ pass = 0;
+ do {
+ result = dns_dbiterator_prev(dbit);
+ if (result == ISC_R_NOMORE) {
+ pass++;
+ CHECK(dns_dbiterator_last(dbit));
+ }
+ CHECK(dns_dbiterator_current(dbit, &node, prev));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0,
+ &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_NOMORE) {
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ old_next = nsec3.next;
+ old_length = nsec3.next_length;
+
+ /*
+ * Delete the old previous NSEC3.
+ */
+ CHECK(delete(db, version, prev, nsec3param, diff));
+
+ /*
+ * Fixup the previous NSEC3.
+ */
+ nsec3.next = nexthash;
+ nsec3.next_length = next_length;
+ isc_buffer_init(&buffer, nsec3buf,
+ sizeof(nsec3buf));
+ CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
+ dns_rdatatype_nsec3, &nsec3,
+ &buffer));
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ prev, rdataset.ttl, &rdata,
+ &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ INSIST(old_length <= sizeof(nexthash));
+ memcpy(nexthash, old_next, old_length);
+ if (!CREATE(nsec3param->flags))
+ flags = nsec3.flags;
+ dns_rdata_reset(&rdata);
+ dns_rdataset_disassociate(&rdataset);
+ break;
+ } while (pass < 2);
+
+ INSIST(pass < 2);
+
+ /*
+ * Create the NSEC3 RDATA for the empty node.
+ */
+ CHECK(dns_nsec3_buildrdata(db, version, NULL, hash, flags,
+ iterations, salt, salt_length,
+ nexthash, next_length, nsec3buf,
+ &rdata));
+ /*
+ * Delete the old NSEC3 and record the change.
+ */
+ CHECK(delete(db, version, hashname, nsec3param, diff));
+
+ /*
+ * Add the new NSEC3 and record the change.
+ */
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ hashname, nsecttl, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ INSIST(tuple == NULL);
+ dns_rdata_reset(&rdata);
+ dns_db_detachnode(db, &newnode);
+ } while (1);
+
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dbit != NULL)
+ dns_dbiterator_destroy(&dbit);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (newnode != NULL)
+ dns_db_detachnode(db, &newnode);
+ return (result);
+}
+
+/*%
+ * Add NSEC3 records for "name", recording the change in "diff".
+ * The existing NSEC3 records are removed.
+ */
+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)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+
+ /*
+ * 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,
+ dns_rdatatype_nsec3param, 0, 0,
+ &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * 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);
+ dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+
+#ifdef RFC5155_STRICT
+ if (nsec3param.flags != 0)
+ continue;
+#else
+ if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
+ continue;
+ if (better_param(&rdataset, &rdata))
+ continue;
+#endif
+
+ /*
+ * 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_result_t
+dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
+{
+ dns_dbiterator_t *dbit = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_difftuple_t *tuple = NULL;
+ dns_fixedname_t fixed;
+ dns_fixedname_t fprev;
+ dns_hash_t hash;
+ dns_name_t *hashname;
+ dns_name_t *origin;
+ dns_name_t *prev;
+ dns_name_t empty;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ int pass;
+ isc_boolean_t exists;
+ isc_buffer_t buffer;
+ isc_result_t result;
+ unsigned char *salt;
+ unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
+ unsigned int iterations;
+ unsigned int labels;
+ size_t next_length;
+ unsigned int salt_length;
+
+ dns_fixedname_init(&fixed);
+ hashname = dns_fixedname_name(&fixed);
+ dns_fixedname_init(&fprev);
+ prev = dns_fixedname_name(&fprev);
+
+ dns_rdataset_init(&rdataset);
+
+ origin = dns_db_origin(db);
+
+ /*
+ * Chain parameters.
+ */
+ hash = nsec3param->hash;
+ iterations = nsec3param->iterations;
+ salt_length = nsec3param->salt_length;
+ salt = nsec3param->salt;
+
+ /*
+ * If this is the first NSEC3 in the chain nexthash will
+ * remain pointing to itself.
+ */
+ next_length = sizeof(nexthash);
+ CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
+ name, origin, hash, iterations,
+ salt, salt_length));
+
+ CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
+
+ result = dns_dbiterator_seek(dbit, hashname);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ CHECK(dns_dbiterator_current(dbit, &node, NULL));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3,
+ 0, (isc_stdtime_t) 0, &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * If we find a existing NSEC3 for this chain then save the
+ * next field.
+ */
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_SUCCESS) {
+ next_length = nsec3.next_length;
+ INSIST(next_length <= sizeof(nexthash));
+ memcpy(nexthash, nsec3.next, next_length);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_NOMORE)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Find the previous NSEC3 and update it.
+ */
+ pass = 0;
+ do {
+ result = dns_dbiterator_prev(dbit);
+ if (result == ISC_R_NOMORE) {
+ pass++;
+ CHECK(dns_dbiterator_last(dbit));
+ }
+ CHECK(dns_dbiterator_current(dbit, &node, prev));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0, &rdataset,
+ NULL);
+ dns_db_detachnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_NOMORE) {
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Delete the old previous NSEC3.
+ */
+ CHECK(delete(db, version, prev, nsec3param, diff));
+
+ /*
+ * Fixup the previous NSEC3.
+ */
+ nsec3.next = nexthash;
+ nsec3.next_length = next_length;
+ isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
+ CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
+ dns_rdatatype_nsec3, &nsec3,
+ &buffer));
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
+ rdataset.ttl, &rdata, &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ dns_rdata_reset(&rdata);
+ dns_rdataset_disassociate(&rdataset);
+ break;
+ } while (pass < 2);
+
+ /*
+ * Delete the old NSEC3 and record the change.
+ */
+ CHECK(delete(db, version, hashname, nsec3param, diff));
+
+ /*
+ * Delete NSEC3 records for now non active nodes.
+ */
+ dns_name_init(&empty, NULL);
+ dns_name_clone(name, &empty);
+ do {
+ labels = dns_name_countlabels(&empty) - 1;
+ if (labels <= dns_name_countlabels(origin))
+ break;
+ dns_name_getlabelsequence(&empty, 1, labels, &empty);
+ CHECK(name_exists(db, version, &empty, &exists));
+ if (exists)
+ break;
+
+ CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
+ &empty, origin, hash, iterations,
+ salt, salt_length));
+ result = dns_dbiterator_seek(dbit, hashname);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ CHECK(dns_dbiterator_current(dbit, &node, NULL));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0, &rdataset,
+ NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_SUCCESS) {
+ next_length = nsec3.next_length;
+ INSIST(next_length <= sizeof(nexthash));
+ memcpy(nexthash, nsec3.next, next_length);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_NOMORE)
+ goto success;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ pass = 0;
+ do {
+ result = dns_dbiterator_prev(dbit);
+ if (result == ISC_R_NOMORE) {
+ pass++;
+ CHECK(dns_dbiterator_last(dbit));
+ }
+ CHECK(dns_dbiterator_current(dbit, &node, prev));
+ CHECK(dns_dbiterator_pause(dbit));
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3, 0,
+ (isc_stdtime_t) 0,
+ &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ result = find_nsec3(&nsec3, &rdataset, nsec3param);
+ if (result == ISC_R_NOMORE) {
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Delete the old previous NSEC3.
+ */
+ CHECK(delete(db, version, prev, nsec3param, diff));
+
+ /*
+ * Fixup the previous NSEC3.
+ */
+ nsec3.next = nexthash;
+ nsec3.next_length = next_length;
+ isc_buffer_init(&buffer, nsec3buf,
+ sizeof(nsec3buf));
+ CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
+ dns_rdatatype_nsec3, &nsec3,
+ &buffer));
+ CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
+ prev, rdataset.ttl, &rdata,
+ &tuple));
+ CHECK(do_one_tuple(&tuple, db, version, diff));
+ dns_rdata_reset(&rdata);
+ dns_rdataset_disassociate(&rdataset);
+ break;
+ } while (pass < 2);
+
+ INSIST(pass < 2);
+
+ /*
+ * Delete the old NSEC3 and record the change.
+ */
+ CHECK(delete(db, version, hashname, nsec3param, diff));
+ } while (1);
+
+ success:
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dbit != NULL)
+ dns_dbiterator_destroy(&dbit);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+isc_result_t
+dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_diff_t *diff)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+
+ /*
+ * 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,
+ dns_rdatatype_nsec3param, 0, 0,
+ &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * 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);
+ dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+
+#ifdef RFC5155_STRICT
+ if (nsec3param.flags != 0)
+ continue;
+#else
+ if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
+ continue;
+ if (better_param(&rdataset, &rdata))
+ continue;
+#endif
+
+ /*
+ * We have a active chain. Update it.
+ */
+ CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, 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_result_t
+dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
+ isc_boolean_t complete, isc_boolean_t *answer)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_nsec3param_t nsec3param;
+ isc_result_t result;
+
+ REQUIRE(answer != NULL);
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3param, 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_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if ((nsec3param.flags) == 0 ||
+ (!complete && CREATE(nsec3param.flags)))
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_SUCCESS)
+ *answer = ISC_TRUE;
+ if (result == ISC_R_NOMORE) {
+ *answer = ISC_FALSE;
+ result = ISC_R_SUCCESS;
+ }
+ return (result);
+}
+
+isc_result_t
+dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
+ isc_mem_t *mctx, unsigned int *iterationsp)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dst_key_t *key = NULL;
+ isc_buffer_t buffer;
+ isc_result_t result;
+ isc_uint16_t bits, minbits = 4096;
+
+ result = dns_db_getoriginnode(db, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
+ 0, 0, &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_NOTFOUND) {
+ *iterationsp = 0;
+ return (ISC_R_SUCCESS);
+ }
+ 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);
+ isc_buffer_init(&buffer, rdata.data, rdata.length);
+ isc_buffer_add(&buffer, rdata.length);
+ CHECK(dst_key_fromdns(dns_db_origin(db), rdataset.rdclass,
+ &buffer, mctx, &key));
+ bits = dst_key_getbits(key);
+ dst_key_free(&key);
+ if (minbits > bits)
+ minbits = bits;
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
+ if (minbits <= 1024)
+ *iterationsp = 150;
+ else if (minbits <= 2048)
+ *iterationsp = 500;
+ else
+ *iterationsp = 2500;
+ result = ISC_R_SUCCESS;
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
diff --git a/lib/dns/openssl_link.c b/lib/dns/openssl_link.c
new file mode 100644
index 0000000..1ddb75d
--- /dev/null
+++ b/lib/dns/openssl_link.c
@@ -0,0 +1,447 @@
+/*
+ * Portions Copyright (C) 2004-2008 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
+ * 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 AND NETWORK ASSOCIATES 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.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 AND NETWORK ASSOCIATES 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.
+ */
+
+/*
+ * Principal Author: Brian Wellington
+ * $Id: openssl_link.c,v 1.22 2008/04/05 23:47:11 tbox Exp $
+ */
+#ifdef OPENSSL
+
+#include <config.h>
+
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/mutexblock.h>
+#include <isc/string.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+
+#include "dst_internal.h"
+#include "dst_openssl.h"
+
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include <openssl/conf.h>
+#include <openssl/crypto.h>
+
+#if defined(CRYPTO_LOCK_ENGINE) && (OPENSSL_VERSION_NUMBER >= 0x0090707f)
+#define USE_ENGINE 1
+#endif
+
+#ifdef USE_ENGINE
+#include <openssl/engine.h>
+
+#ifdef ENGINE_ID
+const char *engine_id = ENGINE_ID;
+#else
+const char *engine_id;
+#endif
+#endif
+
+static RAND_METHOD *rm = NULL;
+
+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);
+#endif
+
+static int
+entropy_get(unsigned char *buf, int num) {
+ isc_result_t result;
+ if (num < 0)
+ return (-1);
+ result = dst__entropy_getdata(buf, (unsigned int) num, ISC_FALSE);
+ return (result == ISC_R_SUCCESS ? num : -1);
+}
+
+static int
+entropy_status(void) {
+ return (dst__entropy_status() > 32);
+}
+
+static int
+entropy_getpseudo(unsigned char *buf, int num) {
+ isc_result_t result;
+ if (num < 0)
+ return (-1);
+ result = dst__entropy_getdata(buf, (unsigned int) num, ISC_TRUE);
+ return (result == ISC_R_SUCCESS ? num : -1);
+}
+
+static void
+entropy_add(const void *buf, int num, double entropy) {
+ /*
+ * Do nothing. The only call to this provides no useful data anyway.
+ */
+ UNUSED(buf);
+ UNUSED(num);
+ UNUSED(entropy);
+}
+
+static void
+lock_callback(int mode, int type, const char *file, int line) {
+ UNUSED(file);
+ UNUSED(line);
+ if ((mode & CRYPTO_LOCK) != 0)
+ LOCK(&locks[type]);
+ else
+ UNLOCK(&locks[type]);
+}
+
+static unsigned long
+id_callback(void) {
+ return ((unsigned long)isc_thread_self());
+}
+
+static void *
+mem_alloc(size_t size) {
+ INSIST(dst__memory_pool != NULL);
+ return (isc_mem_allocate(dst__memory_pool, size));
+}
+
+static void
+mem_free(void *ptr) {
+ INSIST(dst__memory_pool != NULL);
+ if (ptr != NULL)
+ isc_mem_free(dst__memory_pool, ptr);
+}
+
+static void *
+mem_realloc(void *ptr, size_t size) {
+ void *p;
+
+ INSIST(dst__memory_pool != NULL);
+ p = NULL;
+ if (size > 0U) {
+ p = mem_alloc(size);
+ if (p != NULL && ptr != NULL)
+ memcpy(p, ptr, size);
+ }
+ if (ptr != NULL)
+ mem_free(ptr);
+ return (p);
+}
+
+isc_result_t
+dst__openssl_init() {
+ isc_result_t result;
+#ifdef USE_ENGINE
+ /* const char *name; */
+ ENGINE *re;
+#endif
+
+#ifdef DNS_CRYPTO_LEAKS
+ CRYPTO_malloc_debug_init();
+ CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+#endif
+ CRYPTO_set_mem_functions(mem_alloc, mem_realloc, mem_free);
+ nlocks = CRYPTO_num_locks();
+ locks = mem_alloc(sizeof(isc_mutex_t) * nlocks);
+ if (locks == NULL)
+ return (ISC_R_NOMEMORY);
+ result = isc_mutexblock_init(locks, nlocks);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mutexalloc;
+ CRYPTO_set_locking_callback(lock_callback);
+ CRYPTO_set_id_callback(id_callback);
+
+ rm = mem_alloc(sizeof(RAND_METHOD));
+ if (rm == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_mutexinit;
+ }
+ rm->seed = NULL;
+ rm->bytes = entropy_get;
+ rm->cleanup = NULL;
+ 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 (e == NULL) {
+ result = ISC_R_NOTFOUND;
+ goto cleanup_rm;
+ }
+ if (!ENGINE_init(e)) {
+ result = ISC_R_FAILURE;
+ ENGINE_free(e);
+ 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 wierd 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();
+ if (re == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_rm;
+ }
+ ENGINE_set_RAND(re, rm);
+ ENGINE_set_default_RAND(re);
+ ENGINE_free(re);
+ } else
+ ENGINE_finish(re);
+
+#else
+ RAND_set_rand_method(rm);
+#endif /* USE_ENGINE */
+ return (ISC_R_SUCCESS);
+
+#ifdef USE_ENGINE
+ cleanup_rm:
+ mem_free(rm);
+#endif
+ cleanup_mutexinit:
+ CRYPTO_set_locking_callback(NULL);
+ DESTROYMUTEXBLOCK(locks, nlocks);
+ cleanup_mutexalloc:
+ mem_free(locks);
+ return (result);
+}
+
+void
+dst__openssl_destroy() {
+
+ /*
+ * Sequence taken from apps_shutdown() in <apps/apps.h>.
+ */
+#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
+ CONF_modules_unload(1);
+#endif
+ EVP_cleanup();
+#if defined(USE_ENGINE)
+ if (e != NULL) {
+ ENGINE_finish(e);
+ e = NULL;
+ }
+#if defined(USE_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L
+ ENGINE_cleanup();
+#endif
+#endif
+#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
+ CRYPTO_cleanup_all_ex_data();
+#endif
+ ERR_clear_error();
+ ERR_free_strings();
+ ERR_remove_state(0);
+
+#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);
+ }
+}
+
+isc_result_t
+dst__openssl_toresult(isc_result_t fallback) {
+ isc_result_t result = fallback;
+ int err = ERR_get_error();
+
+ switch (ERR_GET_REASON(err)) {
+ case ERR_R_MALLOC_FAILURE:
+ result = ISC_R_NOMEMORY;
+ break;
+ default:
+ break;
+ }
+ ERR_clear_error();
+ return (result);
+}
+
+ENGINE *
+dst__openssl_getengine(const char *name) {
+
+ UNUSED(name);
+
+
+#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 arguement 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);
+}
+#endif /* USE_PKCS11 */
+
+#else /* OPENSSL */
+
+#include <isc/util.h>
+
+EMPTY_TRANSLATION_UNIT
+
+#endif /* OPENSSL */
+/*! \file */
diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c
new file mode 100644
index 0000000..abc3b7c
--- /dev/null
+++ b/lib/dns/openssldh_link.c
@@ -0,0 +1,638 @@
+/*
+ * Portions Copyright (C) 2004-2008 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
+ * 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 AND NETWORK ASSOCIATES 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.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 AND NETWORK ASSOCIATES 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.
+ */
+
+/*
+ * Principal Author: Brian Wellington
+ * $Id: openssldh_link.c,v 1.14 2008/04/01 23:47:10 tbox Exp $
+ */
+
+#ifdef OPENSSL
+
+#include <config.h>
+
+#include <ctype.h>
+
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dst/result.h>
+
+#include "dst_internal.h"
+#include "dst_openssl.h"
+#include "dst_parse.h"
+
+#define PRIME768 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \
+ "A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \
+ "F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
+
+#define PRIME1024 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" \
+ "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF2" \
+ "5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \
+ "B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
+
+#define PRIME1536 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
+ "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
+ "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
+ "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
+ "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
+ "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
+ "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
+ "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
+
+
+static isc_result_t openssldh_todns(const dst_key_t *key, isc_buffer_t *data);
+
+static BIGNUM bn2, bn768, bn1024, bn1536;
+
+static isc_result_t
+openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
+ isc_buffer_t *secret)
+{
+ DH *dhpub, *dhpriv;
+ int ret;
+ isc_region_t r;
+ unsigned int len;
+
+ REQUIRE(pub->keydata.dh != NULL);
+ REQUIRE(priv->keydata.dh != NULL);
+
+ dhpub = pub->keydata.dh;
+ dhpriv = priv->keydata.dh;
+
+ len = DH_size(dhpriv);
+ isc_buffer_availableregion(secret, &r);
+ if (r.length < len)
+ return (ISC_R_NOSPACE);
+ ret = DH_compute_key(r.base, dhpub->pub_key, dhpriv);
+ if (ret == 0)
+ return (dst__openssl_toresult(DST_R_COMPUTESECRETFAILURE));
+ isc_buffer_add(secret, len);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ int status;
+ DH *dh1, *dh2;
+
+ dh1 = key1->keydata.dh;
+ dh2 = key2->keydata.dh;
+
+ if (dh1 == NULL && dh2 == NULL)
+ return (ISC_TRUE);
+ else if (dh1 == NULL || dh2 == NULL)
+ return (ISC_FALSE);
+
+ status = BN_cmp(dh1->p, dh2->p) ||
+ BN_cmp(dh1->g, dh2->g) ||
+ BN_cmp(dh1->pub_key, dh2->pub_key);
+
+ if (status != 0)
+ return (ISC_FALSE);
+
+ if (dh1->priv_key != NULL || dh2->priv_key != NULL) {
+ if (dh1->priv_key == NULL || dh2->priv_key == NULL)
+ return (ISC_FALSE);
+ if (BN_cmp(dh1->priv_key, dh2->priv_key) != 0)
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+static isc_boolean_t
+openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
+ int status;
+ DH *dh1, *dh2;
+
+ dh1 = key1->keydata.dh;
+ dh2 = key2->keydata.dh;
+
+ if (dh1 == NULL && dh2 == NULL)
+ return (ISC_TRUE);
+ else if (dh1 == NULL || dh2 == NULL)
+ return (ISC_FALSE);
+
+ status = BN_cmp(dh1->p, dh2->p) ||
+ BN_cmp(dh1->g, dh2->g);
+
+ if (status != 0)
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+}
+
+static isc_result_t
+openssldh_generate(dst_key_t *key, int generator) {
+#if OPENSSL_VERSION_NUMBER > 0x00908000L
+ BN_GENCB cb;
+#endif
+ DH *dh = NULL;
+
+ if (generator == 0) {
+ if (key->key_size == 768 ||
+ key->key_size == 1024 ||
+ key->key_size == 1536)
+ {
+ dh = DH_new();
+ if (dh == NULL)
+ return (dst__openssl_toresult(ISC_R_NOMEMORY));
+ if (key->key_size == 768)
+ dh->p = &bn768;
+ else if (key->key_size == 1024)
+ dh->p = &bn1024;
+ else
+ dh->p = &bn1536;
+ dh->g = &bn2;
+ } else
+ generator = 2;
+ }
+
+ if (generator != 0) {
+#if OPENSSL_VERSION_NUMBER > 0x00908000L
+ dh = DH_new();
+ if (dh == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+
+ BN_GENCB_set_old(&cb, NULL, NULL);
+
+ if (!DH_generate_parameters_ex(dh, key->key_size, generator,
+ &cb)) {
+ DH_free(dh);
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
+#else
+ dh = DH_generate_parameters(key->key_size, generator,
+ NULL, NULL);
+#endif
+ }
+
+ if (dh == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+
+ if (DH_generate_key(dh) == 0) {
+ DH_free(dh);
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
+ dh->flags &= ~DH_FLAG_CACHE_MONT_P;
+
+ key->keydata.dh = dh;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+openssldh_isprivate(const dst_key_t *key) {
+ DH *dh = key->keydata.dh;
+ return (ISC_TF(dh != NULL && dh->priv_key != NULL));
+}
+
+static void
+openssldh_destroy(dst_key_t *key) {
+ DH *dh = key->keydata.dh;
+
+ if (dh == NULL)
+ return;
+
+ if (dh->p == &bn768 || dh->p == &bn1024 || dh->p == &bn1536)
+ dh->p = NULL;
+ if (dh->g == &bn2)
+ dh->g = NULL;
+ DH_free(dh);
+ key->keydata.dh = NULL;
+}
+
+static void
+uint16_toregion(isc_uint16_t val, isc_region_t *region) {
+ *region->base++ = (val & 0xff00) >> 8;
+ *region->base++ = (val & 0x00ff);
+}
+
+static isc_uint16_t
+uint16_fromregion(isc_region_t *region) {
+ isc_uint16_t val;
+ unsigned char *cp = region->base;
+
+ val = ((unsigned int)(cp[0])) << 8;
+ val |= ((unsigned int)(cp[1]));
+
+ region->base += 2;
+ return (val);
+}
+
+static isc_result_t
+openssldh_todns(const dst_key_t *key, isc_buffer_t *data) {
+ DH *dh;
+ isc_region_t r;
+ isc_uint16_t dnslen, plen, glen, publen;
+
+ REQUIRE(key->keydata.dh != NULL);
+
+ dh = key->keydata.dh;
+
+ isc_buffer_availableregion(data, &r);
+
+ if (dh->g == &bn2 &&
+ (dh->p == &bn768 || dh->p == &bn1024 || dh->p == &bn1536)) {
+ plen = 1;
+ glen = 0;
+ }
+ else {
+ plen = BN_num_bytes(dh->p);
+ glen = BN_num_bytes(dh->g);
+ }
+ publen = BN_num_bytes(dh->pub_key);
+ dnslen = plen + glen + publen + 6;
+ if (r.length < (unsigned int) dnslen)
+ return (ISC_R_NOSPACE);
+
+ uint16_toregion(plen, &r);
+ if (plen == 1) {
+ if (dh->p == &bn768)
+ *r.base = 1;
+ else if (dh->p == &bn1024)
+ *r.base = 2;
+ else
+ *r.base = 3;
+ }
+ else
+ BN_bn2bin(dh->p, r.base);
+ r.base += plen;
+
+ uint16_toregion(glen, &r);
+ if (glen > 0)
+ BN_bn2bin(dh->g, r.base);
+ r.base += glen;
+
+ uint16_toregion(publen, &r);
+ BN_bn2bin(dh->pub_key, r.base);
+ r.base += publen;
+
+ isc_buffer_add(data, dnslen);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) {
+ DH *dh;
+ isc_region_t r;
+ isc_uint16_t plen, glen, publen;
+ int special = 0;
+
+ isc_buffer_remainingregion(data, &r);
+ if (r.length == 0)
+ return (ISC_R_SUCCESS);
+
+ dh = DH_new();
+ if (dh == NULL)
+ return (dst__openssl_toresult(ISC_R_NOMEMORY));
+ dh->flags &= ~DH_FLAG_CACHE_MONT_P;
+
+ /*
+ * Read the prime length. 1 & 2 are table entries, > 16 means a
+ * prime follows, otherwise an error.
+ */
+ if (r.length < 2) {
+ DH_free(dh);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ plen = uint16_fromregion(&r);
+ if (plen < 16 && plen != 1 && plen != 2) {
+ DH_free(dh);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ if (r.length < plen) {
+ DH_free(dh);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ if (plen == 1 || plen == 2) {
+ if (plen == 1)
+ special = *r.base++;
+ else
+ special = uint16_fromregion(&r);
+ switch (special) {
+ case 1:
+ dh->p = &bn768;
+ break;
+ case 2:
+ dh->p = &bn1024;
+ break;
+ case 3:
+ dh->p = &bn1536;
+ break;
+ default:
+ DH_free(dh);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ }
+ else {
+ dh->p = BN_bin2bn(r.base, plen, NULL);
+ r.base += plen;
+ }
+
+ /*
+ * Read the generator length. This should be 0 if the prime was
+ * special, but it might not be. If it's 0 and the prime is not
+ * special, we have a problem.
+ */
+ if (r.length < 2) {
+ DH_free(dh);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ glen = uint16_fromregion(&r);
+ if (r.length < glen) {
+ DH_free(dh);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ if (special != 0) {
+ if (glen == 0)
+ dh->g = &bn2;
+ else {
+ dh->g = BN_bin2bn(r.base, glen, NULL);
+ if (BN_cmp(dh->g, &bn2) == 0) {
+ BN_free(dh->g);
+ dh->g = &bn2;
+ }
+ else {
+ DH_free(dh);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ }
+ }
+ else {
+ if (glen == 0) {
+ DH_free(dh);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ dh->g = BN_bin2bn(r.base, glen, NULL);
+ }
+ r.base += glen;
+
+ if (r.length < 2) {
+ DH_free(dh);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ publen = uint16_fromregion(&r);
+ if (r.length < publen) {
+ DH_free(dh);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ dh->pub_key = BN_bin2bn(r.base, publen, NULL);
+ r.base += publen;
+
+ key->key_size = BN_num_bits(dh->p);
+
+ isc_buffer_forward(data, plen + glen + publen + 6);
+
+ key->keydata.dh = dh;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+openssldh_tofile(const dst_key_t *key, const char *directory) {
+ int i;
+ DH *dh;
+ dst_private_t priv;
+ unsigned char *bufs[4];
+ isc_result_t result;
+
+ if (key->keydata.dh == NULL)
+ return (DST_R_NULLKEY);
+
+ dh = key->keydata.dh;
+
+ for (i = 0; i < 4; i++) {
+ bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(dh->p));
+ if (bufs[i] == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto fail;
+ }
+ }
+
+ i = 0;
+
+ priv.elements[i].tag = TAG_DH_PRIME;
+ priv.elements[i].length = BN_num_bytes(dh->p);
+ BN_bn2bin(dh->p, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+
+ priv.elements[i].tag = TAG_DH_GENERATOR;
+ priv.elements[i].length = BN_num_bytes(dh->g);
+ BN_bn2bin(dh->g, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+
+ priv.elements[i].tag = TAG_DH_PRIVATE;
+ priv.elements[i].length = BN_num_bytes(dh->priv_key);
+ BN_bn2bin(dh->priv_key, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+
+ priv.elements[i].tag = TAG_DH_PUBLIC;
+ priv.elements[i].length = BN_num_bytes(dh->pub_key);
+ BN_bn2bin(dh->pub_key, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+
+ priv.nelements = i;
+ result = dst__privstruct_writefile(key, &priv, directory);
+ fail:
+ for (i = 0; i < 4; i++) {
+ if (bufs[i] == NULL)
+ break;
+ isc_mem_put(key->mctx, bufs[i], BN_num_bytes(dh->p));
+ }
+ return (result);
+}
+
+static isc_result_t
+openssldh_parse(dst_key_t *key, isc_lex_t *lexer) {
+ dst_private_t priv;
+ isc_result_t ret;
+ int i;
+ DH *dh = NULL;
+ isc_mem_t *mctx;
+#define DST_RET(a) {ret = a; goto err;}
+
+ mctx = key->mctx;
+
+ /* read private key file */
+ ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ dh = DH_new();
+ if (dh == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ dh->flags &= ~DH_FLAG_CACHE_MONT_P;
+ key->keydata.dh = dh;
+
+ for (i = 0; i < priv.nelements; i++) {
+ BIGNUM *bn;
+ bn = BN_bin2bn(priv.elements[i].data,
+ priv.elements[i].length, NULL);
+ if (bn == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+
+ switch (priv.elements[i].tag) {
+ case TAG_DH_PRIME:
+ dh->p = bn;
+ break;
+ case TAG_DH_GENERATOR:
+ dh->g = bn;
+ break;
+ case TAG_DH_PRIVATE:
+ dh->priv_key = bn;
+ break;
+ case TAG_DH_PUBLIC:
+ dh->pub_key = bn;
+ break;
+ }
+ }
+ dst__privstruct_free(&priv, mctx);
+
+ key->key_size = BN_num_bits(dh->p);
+
+ if ((key->key_size == 768 ||
+ key->key_size == 1024 ||
+ key->key_size == 1536) &&
+ BN_cmp(dh->g, &bn2) == 0)
+ {
+ if (key->key_size == 768 && BN_cmp(dh->p, &bn768) == 0) {
+ BN_free(dh->p);
+ BN_free(dh->g);
+ dh->p = &bn768;
+ dh->g = &bn2;
+ } else if (key->key_size == 1024 &&
+ BN_cmp(dh->p, &bn1024) == 0) {
+ BN_free(dh->p);
+ BN_free(dh->g);
+ dh->p = &bn1024;
+ dh->g = &bn2;
+ } else if (key->key_size == 1536 &&
+ BN_cmp(dh->p, &bn1536) == 0) {
+ BN_free(dh->p);
+ BN_free(dh->g);
+ dh->p = &bn1536;
+ dh->g = &bn2;
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+
+ err:
+ openssldh_destroy(key);
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (ret);
+}
+
+static void
+BN_fromhex(BIGNUM *b, const char *str) {
+ static const char hexdigits[] = "0123456789abcdef";
+ unsigned char data[512];
+ unsigned int i;
+ BIGNUM *out;
+
+ RUNTIME_CHECK(strlen(str) < 1024U && strlen(str) % 2 == 0U);
+ for (i = 0; i < strlen(str); i += 2) {
+ char *s;
+ unsigned int high, low;
+
+ s = strchr(hexdigits, tolower((unsigned char)str[i]));
+ RUNTIME_CHECK(s != NULL);
+ high = s - hexdigits;
+
+ s = strchr(hexdigits, tolower((unsigned char)str[i + 1]));
+ RUNTIME_CHECK(s != NULL);
+ low = s - hexdigits;
+
+ data[i/2] = (unsigned char)((high << 4) + low);
+ }
+ out = BN_bin2bn(data, strlen(str)/2, b);
+ RUNTIME_CHECK(out != NULL);
+}
+
+static void
+openssldh_cleanup(void) {
+ BN_free(&bn2);
+ BN_free(&bn768);
+ BN_free(&bn1024);
+ BN_free(&bn1536);
+}
+
+static dst_func_t openssldh_functions = {
+ NULL, /*%< createctx */
+ NULL, /*%< destroyctx */
+ NULL, /*%< adddata */
+ NULL, /*%< openssldh_sign */
+ NULL, /*%< openssldh_verify */
+ openssldh_computesecret,
+ openssldh_compare,
+ openssldh_paramcompare,
+ openssldh_generate,
+ openssldh_isprivate,
+ openssldh_destroy,
+ openssldh_todns,
+ openssldh_fromdns,
+ openssldh_tofile,
+ openssldh_parse,
+ openssldh_cleanup,
+ NULL, /*%< fromlabel */
+};
+
+isc_result_t
+dst__openssldh_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+ if (*funcp == NULL) {
+ BN_init(&bn2);
+ BN_init(&bn768);
+ BN_init(&bn1024);
+ BN_init(&bn1536);
+ BN_set_word(&bn2, 2);
+ BN_fromhex(&bn768, PRIME768);
+ BN_fromhex(&bn1024, PRIME1024);
+ BN_fromhex(&bn1536, PRIME1536);
+ *funcp = &openssldh_functions;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+#else /* OPENSSL */
+
+#include <isc/util.h>
+
+EMPTY_TRANSLATION_UNIT
+
+#endif /* OPENSSL */
+/*! \file */
diff --git a/lib/dns/openssldsa_link.c b/lib/dns/openssldsa_link.c
new file mode 100644
index 0000000..f4eb112
--- /dev/null
+++ b/lib/dns/openssldsa_link.c
@@ -0,0 +1,607 @@
+/*
+ * Portions Copyright (C) 2004-2008 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
+ * 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 AND NETWORK ASSOCIATES 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.
+ *
+ * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
+ *
+ * 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 AND NETWORK ASSOCIATES 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: openssldsa_link.c,v 1.13 2008/04/01 23:47:10 tbox Exp $ */
+
+#ifdef OPENSSL
+#ifndef USE_EVP
+#define USE_EVP 1
+#endif
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/sha1.h>
+#include <isc/util.h>
+
+#include <dst/result.h>
+
+#include "dst_internal.h"
+#include "dst_openssl.h"
+#include "dst_parse.h"
+
+#include <openssl/dsa.h>
+
+static isc_result_t openssldsa_todns(const dst_key_t *key, isc_buffer_t *data);
+
+static isc_result_t
+openssldsa_createctx(dst_key_t *key, dst_context_t *dctx) {
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx;
+
+ UNUSED(key);
+
+ evp_md_ctx = EVP_MD_CTX_create();
+ if (evp_md_ctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (!EVP_DigestInit_ex(evp_md_ctx, EVP_dss1(), NULL)) {
+ EVP_MD_CTX_destroy(evp_md_ctx);
+ return (ISC_R_FAILURE);
+ }
+
+ dctx->ctxdata.evp_md_ctx = evp_md_ctx;
+
+ return (ISC_R_SUCCESS);
+#else
+ isc_sha1_t *sha1ctx;
+
+ UNUSED(key);
+
+ sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
+ isc_sha1_init(sha1ctx);
+ dctx->ctxdata.sha1ctx = sha1ctx;
+ return (ISC_R_SUCCESS);
+#endif
+}
+
+static void
+openssldsa_destroyctx(dst_context_t *dctx) {
+#if USE_EVP
+ 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;
+ }
+#else
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
+
+ if (sha1ctx != NULL) {
+ isc_sha1_invalidate(sha1ctx);
+ isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
+ dctx->ctxdata.sha1ctx = NULL;
+ }
+#endif
+}
+
+static isc_result_t
+openssldsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
+#if USE_EVP
+ 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);
+ }
+#else
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
+
+ isc_sha1_update(sha1ctx, data->base, data->length);
+#endif
+ return (ISC_R_SUCCESS);
+}
+
+static int
+BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
+ int bytes = size - BN_num_bytes(bn);
+ while (bytes-- > 0)
+ *buf++ = 0;
+ BN_bn2bin(bn, buf);
+ return (size);
+}
+
+static isc_result_t
+openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ dst_key_t *key = dctx->key;
+ DSA *dsa = key->keydata.dsa;
+ isc_region_t r;
+ DSA_SIG *dsasig;
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+ EVP_PKEY *pkey;
+ unsigned char *sigbuf;
+ const unsigned char *sb;
+ unsigned int siglen;
+#else
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
+ unsigned char digest[ISC_SHA1_DIGESTLENGTH];
+#endif
+
+ isc_buffer_availableregion(sig, &r);
+ if (r.length < ISC_SHA1_DIGESTLENGTH * 2 + 1)
+ return (ISC_R_NOSPACE);
+
+#if USE_EVP
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL)
+ return (ISC_R_NOMEMORY);
+ if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
+ EVP_PKEY_free(pkey);
+ return (ISC_R_FAILURE);
+ }
+ sigbuf = malloc(EVP_PKEY_size(pkey));
+ if (sigbuf == NULL) {
+ EVP_PKEY_free(pkey);
+ return (ISC_R_NOMEMORY);
+ }
+ if (!EVP_SignFinal(evp_md_ctx, sigbuf, &siglen, pkey)) {
+ EVP_PKEY_free(pkey);
+ free(sigbuf);
+ return (ISC_R_FAILURE);
+ }
+ INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
+ EVP_PKEY_free(pkey);
+ /* Convert from Dss-Sig-Value (RFC2459). */
+ dsasig = DSA_SIG_new();
+ if (dsasig == NULL) {
+ free(sigbuf);
+ return (ISC_R_NOMEMORY);
+ }
+ sb = sigbuf;
+ if (d2i_DSA_SIG(&dsasig, &sb, (long) siglen) == NULL) {
+ free(sigbuf);
+ return (ISC_R_FAILURE);
+ }
+ free(sigbuf);
+#elif 0
+ /* Only use EVP for the Digest */
+ if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
+ return (ISC_R_FAILURE);
+ }
+ dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
+ if (dsasig == NULL)
+ return (dst__openssl_toresult(DST_R_SIGNFAILURE));
+#else
+ isc_sha1_final(sha1ctx, digest);
+
+ dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
+ if (dsasig == NULL)
+ return (dst__openssl_toresult(DST_R_SIGNFAILURE));
+#endif
+ *r.base++ = (key->key_size - 512)/64;
+ BN_bn2bin_fixed(dsasig->r, r.base, ISC_SHA1_DIGESTLENGTH);
+ r.base += ISC_SHA1_DIGESTLENGTH;
+ BN_bn2bin_fixed(dsasig->s, r.base, ISC_SHA1_DIGESTLENGTH);
+ r.base += ISC_SHA1_DIGESTLENGTH;
+ DSA_SIG_free(dsasig);
+ isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+openssldsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
+ dst_key_t *key = dctx->key;
+ DSA *dsa = key->keydata.dsa;
+ int status = 0;
+ unsigned char *cp = sig->base;
+ DSA_SIG *dsasig;
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+#if 0
+ EVP_PKEY *pkey;
+ unsigned char *sigbuf;
+#endif
+ unsigned int siglen;
+#else
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
+#endif
+ unsigned char digest[ISC_SHA1_DIGESTLENGTH];
+
+
+#if USE_EVP
+#if 1
+ /* Only use EVP for the digest */
+ if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
+ return (ISC_R_FAILURE);
+ }
+#endif
+#else
+ isc_sha1_final(sha1ctx, digest);
+#endif
+
+ if (sig->length != 2 * ISC_SHA1_DIGESTLENGTH + 1) {
+ return (DST_R_VERIFYFAILURE);
+ }
+
+ cp++; /*%< Skip T */
+ dsasig = DSA_SIG_new();
+ if (dsasig == NULL)
+ return (ISC_R_NOMEMORY);
+ dsasig->r = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
+ cp += ISC_SHA1_DIGESTLENGTH;
+ dsasig->s = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
+ cp += ISC_SHA1_DIGESTLENGTH;
+
+#if 0
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL)
+ return (ISC_R_NOMEMORY);
+ if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
+ EVP_PKEY_free(pkey);
+ return (ISC_R_FAILURE);
+ }
+ /* Convert to Dss-Sig-Value (RFC2459). */
+ sigbuf = malloc(EVP_PKEY_size(pkey) + 50);
+ if (sigbuf == NULL) {
+ EVP_PKEY_free(pkey);
+ return (ISC_R_NOMEMORY);
+ }
+ siglen = (unsigned) i2d_DSA_SIG(dsasig, &sigbuf);
+ INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
+ status = EVP_VerifyFinal(evp_md_ctx, sigbuf, siglen, pkey);
+ EVP_PKEY_free(pkey);
+ free(sigbuf);
+#else
+ status = DSA_do_verify(digest, ISC_SHA1_DIGESTLENGTH, dsasig, dsa);
+#endif
+ DSA_SIG_free(dsasig);
+ if (status == 0)
+ return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ int status;
+ DSA *dsa1, *dsa2;
+
+ dsa1 = key1->keydata.dsa;
+ dsa2 = key2->keydata.dsa;
+
+ if (dsa1 == NULL && dsa2 == NULL)
+ return (ISC_TRUE);
+ else if (dsa1 == NULL || dsa2 == NULL)
+ return (ISC_FALSE);
+
+ status = BN_cmp(dsa1->p, dsa2->p) ||
+ BN_cmp(dsa1->q, dsa2->q) ||
+ BN_cmp(dsa1->g, dsa2->g) ||
+ BN_cmp(dsa1->pub_key, dsa2->pub_key);
+
+ if (status != 0)
+ return (ISC_FALSE);
+
+ if (dsa1->priv_key != NULL || dsa2->priv_key != NULL) {
+ if (dsa1->priv_key == NULL || dsa2->priv_key == NULL)
+ return (ISC_FALSE);
+ if (BN_cmp(dsa1->priv_key, dsa2->priv_key))
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+static isc_result_t
+openssldsa_generate(dst_key_t *key, int unused) {
+#if OPENSSL_VERSION_NUMBER > 0x00908000L
+ BN_GENCB cb;
+#endif
+ DSA *dsa;
+ unsigned char rand_array[ISC_SHA1_DIGESTLENGTH];
+ isc_result_t result;
+
+ UNUSED(unused);
+
+ result = dst__entropy_getdata(rand_array, sizeof(rand_array),
+ ISC_FALSE);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+#if OPENSSL_VERSION_NUMBER > 0x00908000L
+ dsa = DSA_new();
+ if (dsa == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+
+ BN_GENCB_set_old(&cb, NULL, NULL);
+
+ if (!DSA_generate_parameters_ex(dsa, key->key_size, rand_array,
+ ISC_SHA1_DIGESTLENGTH, NULL, NULL,
+ &cb))
+ {
+ DSA_free(dsa);
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
+#else
+ dsa = DSA_generate_parameters(key->key_size, rand_array,
+ ISC_SHA1_DIGESTLENGTH, NULL, NULL,
+ NULL, NULL);
+ if (dsa == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+#endif
+
+ if (DSA_generate_key(dsa) == 0) {
+ DSA_free(dsa);
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
+ dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
+
+ key->keydata.dsa = dsa;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+openssldsa_isprivate(const dst_key_t *key) {
+ DSA *dsa = key->keydata.dsa;
+ return (ISC_TF(dsa != NULL && dsa->priv_key != NULL));
+}
+
+static void
+openssldsa_destroy(dst_key_t *key) {
+ DSA *dsa = key->keydata.dsa;
+ DSA_free(dsa);
+ key->keydata.dsa = NULL;
+}
+
+
+static isc_result_t
+openssldsa_todns(const dst_key_t *key, isc_buffer_t *data) {
+ DSA *dsa;
+ isc_region_t r;
+ int dnslen;
+ unsigned int t, p_bytes;
+
+ REQUIRE(key->keydata.dsa != NULL);
+
+ dsa = key->keydata.dsa;
+
+ isc_buffer_availableregion(data, &r);
+
+ t = (BN_num_bytes(dsa->p) - 64) / 8;
+ if (t > 8)
+ return (DST_R_INVALIDPUBLICKEY);
+ p_bytes = 64 + 8 * t;
+
+ dnslen = 1 + (key->key_size * 3)/8 + ISC_SHA1_DIGESTLENGTH;
+ if (r.length < (unsigned int) dnslen)
+ return (ISC_R_NOSPACE);
+
+ *r.base++ = t;
+ BN_bn2bin_fixed(dsa->q, r.base, ISC_SHA1_DIGESTLENGTH);
+ r.base += ISC_SHA1_DIGESTLENGTH;
+ BN_bn2bin_fixed(dsa->p, r.base, key->key_size/8);
+ r.base += p_bytes;
+ BN_bn2bin_fixed(dsa->g, r.base, key->key_size/8);
+ r.base += p_bytes;
+ BN_bn2bin_fixed(dsa->pub_key, r.base, key->key_size/8);
+ r.base += p_bytes;
+
+ isc_buffer_add(data, dnslen);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+openssldsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
+ DSA *dsa;
+ isc_region_t r;
+ unsigned int t, p_bytes;
+ isc_mem_t *mctx = key->mctx;
+
+ UNUSED(mctx);
+
+ isc_buffer_remainingregion(data, &r);
+ if (r.length == 0)
+ return (ISC_R_SUCCESS);
+
+ dsa = DSA_new();
+ if (dsa == NULL)
+ return (ISC_R_NOMEMORY);
+ dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
+
+ t = (unsigned int) *r.base++;
+ if (t > 8) {
+ DSA_free(dsa);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ p_bytes = 64 + 8 * t;
+
+ if (r.length < 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) {
+ DSA_free(dsa);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+
+ dsa->q = BN_bin2bn(r.base, ISC_SHA1_DIGESTLENGTH, NULL);
+ r.base += ISC_SHA1_DIGESTLENGTH;
+
+ dsa->p = BN_bin2bn(r.base, p_bytes, NULL);
+ r.base += p_bytes;
+
+ dsa->g = BN_bin2bn(r.base, p_bytes, NULL);
+ r.base += p_bytes;
+
+ dsa->pub_key = BN_bin2bn(r.base, p_bytes, NULL);
+ r.base += p_bytes;
+
+ key->key_size = p_bytes * 8;
+
+ isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes);
+
+ key->keydata.dsa = dsa;
+
+ return (ISC_R_SUCCESS);
+}
+
+
+static isc_result_t
+openssldsa_tofile(const dst_key_t *key, const char *directory) {
+ int cnt = 0;
+ DSA *dsa;
+ dst_private_t priv;
+ unsigned char bufs[5][128];
+
+ if (key->keydata.dsa == NULL)
+ return (DST_R_NULLKEY);
+
+ dsa = key->keydata.dsa;
+
+ priv.elements[cnt].tag = TAG_DSA_PRIME;
+ priv.elements[cnt].length = BN_num_bytes(dsa->p);
+ BN_bn2bin(dsa->p, bufs[cnt]);
+ priv.elements[cnt].data = bufs[cnt];
+ cnt++;
+
+ priv.elements[cnt].tag = TAG_DSA_SUBPRIME;
+ priv.elements[cnt].length = BN_num_bytes(dsa->q);
+ BN_bn2bin(dsa->q, bufs[cnt]);
+ priv.elements[cnt].data = bufs[cnt];
+ cnt++;
+
+ priv.elements[cnt].tag = TAG_DSA_BASE;
+ priv.elements[cnt].length = BN_num_bytes(dsa->g);
+ BN_bn2bin(dsa->g, bufs[cnt]);
+ priv.elements[cnt].data = bufs[cnt];
+ cnt++;
+
+ priv.elements[cnt].tag = TAG_DSA_PRIVATE;
+ priv.elements[cnt].length = BN_num_bytes(dsa->priv_key);
+ BN_bn2bin(dsa->priv_key, bufs[cnt]);
+ priv.elements[cnt].data = bufs[cnt];
+ cnt++;
+
+ priv.elements[cnt].tag = TAG_DSA_PUBLIC;
+ priv.elements[cnt].length = BN_num_bytes(dsa->pub_key);
+ BN_bn2bin(dsa->pub_key, bufs[cnt]);
+ priv.elements[cnt].data = bufs[cnt];
+ cnt++;
+
+ priv.nelements = cnt;
+ return (dst__privstruct_writefile(key, &priv, directory));
+}
+
+static isc_result_t
+openssldsa_parse(dst_key_t *key, isc_lex_t *lexer) {
+ dst_private_t priv;
+ isc_result_t ret;
+ int i;
+ DSA *dsa = NULL;
+ isc_mem_t *mctx = key->mctx;
+#define DST_RET(a) {ret = a; goto err;}
+
+ /* read private key file */
+ ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ dsa = DSA_new();
+ if (dsa == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
+ key->keydata.dsa = dsa;
+
+ for (i=0; i < priv.nelements; i++) {
+ BIGNUM *bn;
+ bn = BN_bin2bn(priv.elements[i].data,
+ priv.elements[i].length, NULL);
+ if (bn == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+
+ switch (priv.elements[i].tag) {
+ case TAG_DSA_PRIME:
+ dsa->p = bn;
+ break;
+ case TAG_DSA_SUBPRIME:
+ dsa->q = bn;
+ break;
+ case TAG_DSA_BASE:
+ dsa->g = bn;
+ break;
+ case TAG_DSA_PRIVATE:
+ dsa->priv_key = bn;
+ break;
+ case TAG_DSA_PUBLIC:
+ dsa->pub_key = bn;
+ break;
+ }
+ }
+ dst__privstruct_free(&priv, mctx);
+
+ key->key_size = BN_num_bits(dsa->p);
+
+ return (ISC_R_SUCCESS);
+
+ err:
+ openssldsa_destroy(key);
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (ret);
+}
+
+static dst_func_t openssldsa_functions = {
+ openssldsa_createctx,
+ openssldsa_destroyctx,
+ openssldsa_adddata,
+ openssldsa_sign,
+ openssldsa_verify,
+ NULL, /*%< computesecret */
+ openssldsa_compare,
+ NULL, /*%< paramcompare */
+ openssldsa_generate,
+ openssldsa_isprivate,
+ openssldsa_destroy,
+ openssldsa_todns,
+ openssldsa_fromdns,
+ openssldsa_tofile,
+ openssldsa_parse,
+ NULL, /*%< cleanup */
+ NULL, /*%< fromlabel */
+};
+
+isc_result_t
+dst__openssldsa_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+ if (*funcp == NULL)
+ *funcp = &openssldsa_functions;
+ return (ISC_R_SUCCESS);
+}
+
+#else /* OPENSSL */
+
+#include <isc/util.h>
+
+EMPTY_TRANSLATION_UNIT
+
+#endif /* OPENSSL */
+/*! \file */
diff --git a/lib/dns/opensslrsa_link.c b/lib/dns/opensslrsa_link.c
new file mode 100644
index 0000000..aee7d21
--- /dev/null
+++ b/lib/dns/opensslrsa_link.c
@@ -0,0 +1,986 @@
+/*
+ * 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
+ * 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.
+ */
+
+/*
+ * Principal Author: Brian Wellington
+ * $Id: opensslrsa_link.c,v 1.20 2008/09/24 02:46:22 marka Exp $
+ */
+#ifdef OPENSSL
+#ifndef USE_EVP
+#define USE_EVP 1
+#endif
+#if USE_EVP
+#define USE_EVP_RSA 1
+#endif
+
+#include <config.h>
+
+#include <isc/entropy.h>
+#include <isc/md5.h>
+#include <isc/sha1.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dst/result.h>
+
+#include "dst_internal.h"
+#include "dst_openssl.h"
+#include "dst_parse.h"
+
+#include <openssl/err.h>
+#include <openssl/objects.h>
+#include <openssl/rsa.h>
+#if OPENSSL_VERSION_NUMBER > 0x00908000L
+#include <openssl/bn.h>
+#endif
+#include <openssl/engine.h>
+
+/*
+ * We don't use configure for windows so enforce the OpenSSL version
+ * here. Unlike with configure we don't support overriding this test.
+ */
+#ifdef WIN32
+#if !((OPENSSL_VERSION_NUMBER >= 0x009070cfL && \
+ OPENSSL_VERSION_NUMBER < 0x00908000L) || \
+ OPENSSL_VERSION_NUMBER >= 0x0090804fL)
+#error Please upgrade OpenSSL to 0.9.8d/0.9.7l or greater.
+#endif
+#endif
+
+
+ /*
+ * XXXMPA Temporarially disable RSA_BLINDING as it requires
+ * good quality random data that cannot currently be guarenteed.
+ * XXXMPA Find which versions of openssl use pseudo random data
+ * and set RSA_FLAG_BLINDING for those.
+ */
+
+#if 0
+#if OPENSSL_VERSION_NUMBER < 0x0090601fL
+#define SET_FLAGS(rsa) \
+ do { \
+ (rsa)->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE); \
+ (rsa)->flags |= RSA_FLAG_BLINDING; \
+ } while (0)
+#else
+#define SET_FLAGS(rsa) \
+ do { \
+ (rsa)->flags |= RSA_FLAG_BLINDING; \
+ } while (0)
+#endif
+#endif
+
+#if OPENSSL_VERSION_NUMBER < 0x0090601fL
+#define SET_FLAGS(rsa) \
+ do { \
+ (rsa)->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE); \
+ (rsa)->flags &= ~RSA_FLAG_BLINDING; \
+ } while (0)
+#elif defined(RSA_FLAG_NO_BLINDING)
+#define SET_FLAGS(rsa) \
+ do { \
+ (rsa)->flags &= ~RSA_FLAG_BLINDING; \
+ (rsa)->flags |= RSA_FLAG_NO_BLINDING; \
+ } while (0)
+#else
+#define SET_FLAGS(rsa) \
+ do { \
+ (rsa)->flags &= ~RSA_FLAG_BLINDING; \
+ } while (0)
+#endif
+
+#define DST_RET(a) {ret = a; goto err;}
+
+static isc_result_t opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data);
+
+static isc_result_t
+opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx;
+ const EVP_MD *type;
+#endif
+
+ UNUSED(key);
+ REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
+ dctx->key->key_alg == DST_ALG_RSASHA1 ||
+ dctx->key->key_alg == DST_ALG_NSEC3RSASHA1);
+
+#if USE_EVP
+ evp_md_ctx = EVP_MD_CTX_create();
+ if (evp_md_ctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (dctx->key->key_alg == DST_ALG_RSAMD5)
+ type = EVP_md5(); /* MD5 + RSA */
+ else
+ type = EVP_sha1(); /* SHA1 + RSA */
+
+ if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) {
+ EVP_MD_CTX_destroy(evp_md_ctx);
+ return (ISC_R_FAILURE);
+ }
+ dctx->ctxdata.evp_md_ctx = evp_md_ctx;
+#else
+ if (dctx->key->key_alg == DST_ALG_RSAMD5) {
+ isc_md5_t *md5ctx;
+
+ md5ctx = isc_mem_get(dctx->mctx, sizeof(isc_md5_t));
+ if (md5ctx == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_md5_init(md5ctx);
+ dctx->ctxdata.md5ctx = md5ctx;
+ } else {
+ isc_sha1_t *sha1ctx;
+
+ sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
+ if (sha1ctx == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_sha1_init(sha1ctx);
+ dctx->ctxdata.sha1ctx = sha1ctx;
+ }
+#endif
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+opensslrsa_destroyctx(dst_context_t *dctx) {
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+#endif
+
+ REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
+ dctx->key->key_alg == DST_ALG_RSASHA1 ||
+ dctx->key->key_alg == DST_ALG_NSEC3RSASHA1);
+
+#if USE_EVP
+ if (evp_md_ctx != NULL) {
+ EVP_MD_CTX_destroy(evp_md_ctx);
+ dctx->ctxdata.evp_md_ctx = NULL;
+ }
+#else
+ if (dctx->key->key_alg == DST_ALG_RSAMD5) {
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
+
+ if (md5ctx != NULL) {
+ isc_md5_invalidate(md5ctx);
+ isc_mem_put(dctx->mctx, md5ctx, sizeof(isc_md5_t));
+ dctx->ctxdata.md5ctx = NULL;
+ }
+ } else {
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
+
+ if (sha1ctx != NULL) {
+ isc_sha1_invalidate(sha1ctx);
+ isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
+ dctx->ctxdata.sha1ctx = NULL;
+ }
+ }
+#endif
+}
+
+static isc_result_t
+opensslrsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+#endif
+
+ REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
+ dctx->key->key_alg == DST_ALG_RSASHA1 ||
+ dctx->key->key_alg == DST_ALG_NSEC3RSASHA1);
+
+#if USE_EVP
+ if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) {
+ return (ISC_R_FAILURE);
+ }
+#else
+ if (dctx->key->key_alg == DST_ALG_RSAMD5) {
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
+ isc_md5_update(md5ctx, data->base, data->length);
+ } else {
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
+ isc_sha1_update(sha1ctx, data->base, data->length);
+ }
+#endif
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
+ dst_key_t *key = dctx->key;
+ isc_region_t r;
+ unsigned int siglen = 0;
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+ EVP_PKEY *pkey = key->keydata.pkey;
+#else
+ RSA *rsa = key->keydata.rsa;
+ /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
+ unsigned char digest[ISC_SHA1_DIGESTLENGTH];
+ int status;
+ int type;
+ unsigned int digestlen;
+ char *message;
+ unsigned long err;
+ const char* file;
+ int line;
+#endif
+
+ REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
+ dctx->key->key_alg == DST_ALG_RSASHA1 ||
+ dctx->key->key_alg == DST_ALG_NSEC3RSASHA1);
+
+ isc_buffer_availableregion(sig, &r);
+
+#if USE_EVP
+ 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);
+ }
+#else
+ if (r.length < (unsigned int) RSA_size(rsa))
+ return (ISC_R_NOSPACE);
+
+ if (dctx->key->key_alg == DST_ALG_RSAMD5) {
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
+ isc_md5_final(md5ctx, digest);
+ type = NID_md5;
+ digestlen = ISC_MD5_DIGESTLENGTH;
+ } else {
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
+ isc_sha1_final(sha1ctx, digest);
+ type = NID_sha1;
+ digestlen = ISC_SHA1_DIGESTLENGTH;
+ }
+
+ status = RSA_sign(type, digest, digestlen, r.base, &siglen, rsa);
+ if (status == 0) {
+ err = ERR_peek_error_line(&file, &line);
+ if (err != 0U) {
+ message = ERR_error_string(err, NULL);
+ }
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
+#endif
+
+ isc_buffer_add(sig, siglen);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
+ dst_key_t *key = dctx->key;
+ int status = 0;
+#if USE_EVP
+ EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
+ EVP_PKEY *pkey = key->keydata.pkey;
+#else
+ /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
+ unsigned char digest[ISC_SHA1_DIGESTLENGTH];
+ int type;
+ unsigned int digestlen;
+ RSA *rsa = key->keydata.rsa;
+#endif
+
+ REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
+ dctx->key->key_alg == DST_ALG_RSASHA1 ||
+ dctx->key->key_alg == DST_ALG_NSEC3RSASHA1);
+
+#if USE_EVP
+ status = EVP_VerifyFinal(evp_md_ctx, sig->base, sig->length, pkey);
+#else
+ if (dctx->key->key_alg == DST_ALG_RSAMD5) {
+ isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
+ isc_md5_final(md5ctx, digest);
+ type = NID_md5;
+ digestlen = ISC_MD5_DIGESTLENGTH;
+ } else {
+ isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
+ isc_sha1_final(sha1ctx, digest);
+ type = NID_sha1;
+ digestlen = ISC_SHA1_DIGESTLENGTH;
+ }
+
+ if (sig->length < (unsigned int) RSA_size(rsa))
+ return (DST_R_VERIFYFAILURE);
+
+ status = RSA_verify(type, digest, digestlen, sig->base,
+ RSA_size(rsa), rsa);
+#endif
+ if (status == 0)
+ return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
+ int status;
+ RSA *rsa1 = NULL, *rsa2 = NULL;
+#if USE_EVP
+ EVP_PKEY *pkey1, *pkey2;
+#endif
+
+#if USE_EVP
+ pkey1 = key1->keydata.pkey;
+ pkey2 = key2->keydata.pkey;
+ /*
+ * The pkey reference will keep these around after
+ * the RSA_free() call.
+ */
+ if (pkey1 != NULL) {
+ rsa1 = EVP_PKEY_get1_RSA(pkey1);
+ RSA_free(rsa1);
+ }
+ if (pkey2 != NULL) {
+ rsa2 = EVP_PKEY_get1_RSA(pkey2);
+ RSA_free(rsa2);
+ }
+#else
+ rsa1 = key1->keydata.rsa;
+ rsa2 = key2->keydata.rsa;
+#endif
+
+ if (rsa1 == NULL && rsa2 == NULL)
+ return (ISC_TRUE);
+ else if (rsa1 == NULL || rsa2 == NULL)
+ return (ISC_FALSE);
+
+ status = BN_cmp(rsa1->n, rsa2->n) ||
+ BN_cmp(rsa1->e, rsa2->e);
+
+ if (status != 0)
+ return (ISC_FALSE);
+
+#if USE_EVP
+ if ((rsa1->flags & RSA_FLAG_EXT_PKEY) != 0 ||
+ (rsa2->flags & RSA_FLAG_EXT_PKEY) != 0) {
+ if ((rsa1->flags & RSA_FLAG_EXT_PKEY) == 0 ||
+ (rsa2->flags & RSA_FLAG_EXT_PKEY) == 0)
+ return (ISC_FALSE);
+ /*
+ * Can't compare private parameters, BTW does it make sense?
+ */
+ return (ISC_TRUE);
+ }
+#endif
+
+ if (rsa1->d != NULL || rsa2->d != NULL) {
+ if (rsa1->d == NULL || rsa2->d == NULL)
+ return (ISC_FALSE);
+ status = BN_cmp(rsa1->d, rsa2->d) ||
+ BN_cmp(rsa1->p, rsa2->p) ||
+ BN_cmp(rsa1->q, rsa2->q);
+
+ if (status != 0)
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+static isc_result_t
+opensslrsa_generate(dst_key_t *key, int exp) {
+#if OPENSSL_VERSION_NUMBER > 0x00908000L
+ BN_GENCB cb;
+ RSA *rsa = RSA_new();
+ BIGNUM *e = BN_new();
+#if USE_EVP
+ EVP_PKEY *pkey = EVP_PKEY_new();
+#endif
+
+ if (rsa == NULL || e == NULL)
+ goto err;
+#if USE_EVP
+ if (pkey == NULL)
+ goto err;
+ if (!EVP_PKEY_set1_RSA(pkey, rsa))
+ goto err;
+#endif
+
+ if (exp == 0) {
+ /* RSA_F4 0x10001 */
+ BN_set_bit(e, 0);
+ BN_set_bit(e, 16);
+ } else {
+ /* F5 0x100000001 */
+ BN_set_bit(e, 0);
+ BN_set_bit(e, 32);
+ }
+
+ BN_GENCB_set_old(&cb, NULL, NULL);
+
+ if (RSA_generate_key_ex(rsa, key->key_size, e, &cb)) {
+ BN_free(e);
+ SET_FLAGS(rsa);
+#if USE_EVP
+ key->keydata.pkey = pkey;
+
+ RSA_free(rsa);
+#else
+ key->keydata.rsa = rsa;
+#endif
+ return (ISC_R_SUCCESS);
+ }
+
+err:
+#if USE_EVP
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+#endif
+ if (e != NULL)
+ BN_free(e);
+ if (rsa != NULL)
+ RSA_free(rsa);
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+#else
+ RSA *rsa;
+ unsigned long e;
+#if USE_EVP
+ EVP_PKEY *pkey = EVP_PKEY_new();
+
+ if (pkey == NULL)
+ return (ISC_R_NOMEMORY);
+#endif
+
+ if (exp == 0)
+ e = RSA_F4;
+ else
+ e = 0x40000003;
+ rsa = RSA_generate_key(key->key_size, e, NULL, NULL);
+ if (rsa == NULL) {
+#if USE_EVP
+ EVP_PKEY_free(pkey);
+#endif
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
+ SET_FLAGS(rsa);
+#if USE_EVP
+ if (!EVP_PKEY_set1_RSA(pkey, rsa)) {
+ EVP_PKEY_free(pkey);
+ RSA_free(rsa);
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
+ key->keydata.pkey = pkey;
+ RSA_free(rsa);
+#else
+ key->keydata.rsa = rsa;
+#endif
+
+ return (ISC_R_SUCCESS);
+#endif
+}
+
+static isc_boolean_t
+opensslrsa_isprivate(const dst_key_t *key) {
+#if USE_EVP
+ RSA *rsa = EVP_PKEY_get1_RSA(key->keydata.pkey);
+ INSIST(rsa != NULL);
+ RSA_free(rsa);
+ /* key->keydata.pkey still has a reference so rsa is still valid. */
+#else
+ RSA *rsa = key->keydata.rsa;
+#endif
+ if (rsa != NULL && (rsa->flags & RSA_FLAG_EXT_PKEY) != 0)
+ return (ISC_TRUE);
+ return (ISC_TF(rsa != NULL && rsa->d != NULL));
+}
+
+static void
+opensslrsa_destroy(dst_key_t *key) {
+#if USE_EVP
+ EVP_PKEY *pkey = key->keydata.pkey;
+ EVP_PKEY_free(pkey);
+ key->keydata.pkey = NULL;
+#else
+ RSA *rsa = key->keydata.rsa;
+ RSA_free(rsa);
+ key->keydata.rsa = NULL;
+#endif
+}
+
+
+static isc_result_t
+opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
+ isc_region_t r;
+ unsigned int e_bytes;
+ unsigned int mod_bytes;
+ isc_result_t ret;
+ RSA *rsa;
+#if USE_EVP
+ EVP_PKEY *pkey;
+#endif
+
+#if USE_EVP
+ REQUIRE(key->keydata.pkey != NULL);
+#else
+ REQUIRE(key->keydata.rsa != NULL);
+#endif
+
+#if USE_EVP
+ pkey = key->keydata.pkey;
+ rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+#else
+ rsa = key->keydata.rsa;
+#endif
+
+ isc_buffer_availableregion(data, &r);
+
+ e_bytes = BN_num_bytes(rsa->e);
+ mod_bytes = BN_num_bytes(rsa->n);
+
+ if (e_bytes < 256) { /*%< key exponent is <= 2040 bits */
+ if (r.length < 1)
+ DST_RET(ISC_R_NOSPACE);
+ isc_buffer_putuint8(data, (isc_uint8_t) e_bytes);
+ } else {
+ if (r.length < 3)
+ DST_RET(ISC_R_NOSPACE);
+ isc_buffer_putuint8(data, 0);
+ isc_buffer_putuint16(data, (isc_uint16_t) e_bytes);
+ }
+
+ if (r.length < e_bytes + mod_bytes)
+ return (ISC_R_NOSPACE);
+ isc_buffer_availableregion(data, &r);
+
+ BN_bn2bin(rsa->e, r.base);
+ r.base += e_bytes;
+ BN_bn2bin(rsa->n, r.base);
+
+ isc_buffer_add(data, e_bytes + mod_bytes);
+
+ ret = ISC_R_SUCCESS;
+ err:
+#if USE_EVP
+ if (rsa != NULL)
+ RSA_free(rsa);
+#endif
+ return (ret);
+}
+
+static isc_result_t
+opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
+ RSA *rsa;
+ isc_region_t r;
+ unsigned int e_bytes;
+#if USE_EVP
+ EVP_PKEY *pkey;
+#endif
+
+ isc_buffer_remainingregion(data, &r);
+ if (r.length == 0)
+ return (ISC_R_SUCCESS);
+
+ rsa = RSA_new();
+ if (rsa == NULL)
+ return (dst__openssl_toresult(ISC_R_NOMEMORY));
+ SET_FLAGS(rsa);
+
+ if (r.length < 1) {
+ RSA_free(rsa);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ e_bytes = *r.base++;
+ r.length--;
+
+ if (e_bytes == 0) {
+ if (r.length < 2) {
+ RSA_free(rsa);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ e_bytes = ((*r.base++) << 8);
+ e_bytes += *r.base++;
+ r.length -= 2;
+ }
+
+ if (r.length < e_bytes) {
+ RSA_free(rsa);
+ return (DST_R_INVALIDPUBLICKEY);
+ }
+ rsa->e = BN_bin2bn(r.base, e_bytes, NULL);
+ r.base += e_bytes;
+ r.length -= e_bytes;
+
+ rsa->n = BN_bin2bn(r.base, r.length, NULL);
+
+ key->key_size = BN_num_bits(rsa->n);
+
+ isc_buffer_forward(data, r.length);
+
+#if USE_EVP
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL) {
+ RSA_free(rsa);
+ return (ISC_R_NOMEMORY);
+ }
+ if (!EVP_PKEY_set1_RSA(pkey, rsa)) {
+ EVP_PKEY_free(pkey);
+ RSA_free(rsa);
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ }
+ key->keydata.pkey = pkey;
+ RSA_free(rsa);
+#else
+ key->keydata.rsa = rsa;
+#endif
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+opensslrsa_tofile(const dst_key_t *key, const char *directory) {
+ int i;
+ RSA *rsa;
+ dst_private_t priv;
+ unsigned char *bufs[8];
+ isc_result_t result;
+
+#if USE_EVP
+ if (key->keydata.pkey == NULL)
+ return (DST_R_NULLKEY);
+ rsa = EVP_PKEY_get1_RSA(key->keydata.pkey);
+ if (rsa == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+#else
+ if (key->keydata.rsa == NULL)
+ return (DST_R_NULLKEY);
+ rsa = key->keydata.rsa;
+#endif
+
+ for (i = 0; i < 8; i++) {
+ bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n));
+ if (bufs[i] == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto fail;
+ }
+ }
+
+ i = 0;
+
+ priv.elements[i].tag = TAG_RSA_MODULUS;
+ priv.elements[i].length = BN_num_bytes(rsa->n);
+ BN_bn2bin(rsa->n, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+
+ priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT;
+ priv.elements[i].length = BN_num_bytes(rsa->e);
+ BN_bn2bin(rsa->e, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+
+ if (rsa->d != NULL) {
+ priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
+ priv.elements[i].length = BN_num_bytes(rsa->d);
+ BN_bn2bin(rsa->d, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
+
+ if (rsa->p != NULL) {
+ priv.elements[i].tag = TAG_RSA_PRIME1;
+ priv.elements[i].length = BN_num_bytes(rsa->p);
+ BN_bn2bin(rsa->p, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
+
+ if (rsa->q != NULL) {
+ priv.elements[i].tag = TAG_RSA_PRIME2;
+ priv.elements[i].length = BN_num_bytes(rsa->q);
+ BN_bn2bin(rsa->q, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
+
+ if (rsa->dmp1 != NULL) {
+ priv.elements[i].tag = TAG_RSA_EXPONENT1;
+ priv.elements[i].length = BN_num_bytes(rsa->dmp1);
+ BN_bn2bin(rsa->dmp1, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
+
+ if (rsa->dmq1 != NULL) {
+ priv.elements[i].tag = TAG_RSA_EXPONENT2;
+ priv.elements[i].length = BN_num_bytes(rsa->dmq1);
+ BN_bn2bin(rsa->dmq1, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
+
+ if (rsa->iqmp != NULL) {
+ priv.elements[i].tag = TAG_RSA_COEFFICIENT;
+ priv.elements[i].length = BN_num_bytes(rsa->iqmp);
+ BN_bn2bin(rsa->iqmp, bufs[i]);
+ priv.elements[i].data = bufs[i];
+ i++;
+ }
+
+ if (key->engine != NULL) {
+ priv.elements[i].tag = TAG_RSA_ENGINE;
+ priv.elements[i].length = strlen(key->engine) + 1;
+ priv.elements[i].data = (unsigned char *)key->engine;
+ i++;
+ }
+
+ if (key->label != NULL) {
+ priv.elements[i].tag = TAG_RSA_LABEL;
+ priv.elements[i].length = strlen(key->label) + 1;
+ priv.elements[i].data = (unsigned char *)key->label;
+ i++;
+ }
+
+ priv.nelements = i;
+ result = dst__privstruct_writefile(key, &priv, directory);
+ fail:
+#if USE_EVP
+ RSA_free(rsa);
+#endif
+ for (i = 0; i < 8; i++) {
+ if (bufs[i] == NULL)
+ break;
+ isc_mem_put(key->mctx, bufs[i], BN_num_bytes(rsa->n));
+ }
+ return (result);
+}
+
+static isc_result_t
+opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
+ dst_private_t priv;
+ isc_result_t ret;
+ int i;
+ RSA *rsa = NULL;
+ ENGINE *e = NULL;
+ isc_mem_t *mctx = key->mctx;
+ const char *name = NULL, *label = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ /* read private key file */
+ ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ for (i = 0; i < priv.nelements; i++) {
+ switch (priv.elements[i].tag) {
+ case TAG_RSA_ENGINE:
+ name = (char *)priv.elements[i].data;
+ break;
+ case TAG_RSA_LABEL:
+ label = (char *)priv.elements[i].data;
+ break;
+ default:
+ break;
+ }
+ }
+ /*
+ * 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 (e == NULL)
+ DST_RET(DST_R_NOENGINE);
+ pkey = ENGINE_load_private_key(e, label, NULL, NULL);
+ if (pkey == NULL) {
+ ERR_print_errors_fp(stderr);
+ DST_RET(ISC_R_FAILURE);
+ }
+ key->engine = isc_mem_strdup(key->mctx, name);
+ 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);
+ key->key_size = EVP_PKEY_bits(pkey);
+#if USE_EVP
+ key->keydata.pkey = pkey;
+#else
+ key->keydata.rsa = EVP_PKEY_get1_RSA(pkey);
+ if (rsa == NULL)
+ DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+ EVP_PKEY_free(pkey);
+#endif
+ dst__privstruct_free(&priv, mctx);
+ return (ISC_R_SUCCESS);
+ }
+
+ rsa = RSA_new();
+ if (rsa == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ SET_FLAGS(rsa);
+
+#if USE_EVP
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ if (!EVP_PKEY_set1_RSA(pkey, rsa)) {
+ DST_RET(ISC_R_FAILURE);
+ }
+ key->keydata.pkey = pkey;
+#else
+ key->keydata.rsa = rsa;
+#endif
+
+ for (i = 0; i < priv.nelements; i++) {
+ BIGNUM *bn;
+ switch (priv.elements[i].tag) {
+ case TAG_RSA_ENGINE:
+ continue;
+ case TAG_RSA_LABEL:
+ continue;
+ case TAG_RSA_PIN:
+ continue;
+ default:
+ bn = BN_bin2bn(priv.elements[i].data,
+ priv.elements[i].length, NULL);
+ if (bn == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ }
+
+ switch (priv.elements[i].tag) {
+ case TAG_RSA_MODULUS:
+ rsa->n = bn;
+ break;
+ case TAG_RSA_PUBLICEXPONENT:
+ rsa->e = bn;
+ break;
+ case TAG_RSA_PRIVATEEXPONENT:
+ rsa->d = bn;
+ break;
+ case TAG_RSA_PRIME1:
+ rsa->p = bn;
+ break;
+ case TAG_RSA_PRIME2:
+ rsa->q = bn;
+ break;
+ case TAG_RSA_EXPONENT1:
+ rsa->dmp1 = bn;
+ break;
+ case TAG_RSA_EXPONENT2:
+ rsa->dmq1 = bn;
+ break;
+ case TAG_RSA_COEFFICIENT:
+ rsa->iqmp = bn;
+ break;
+ }
+ }
+ dst__privstruct_free(&priv, mctx);
+
+ key->key_size = BN_num_bits(rsa->n);
+#if USE_EVP
+ RSA_free(rsa);
+#endif
+
+ return (ISC_R_SUCCESS);
+
+ err:
+#if USE_EVP
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+#endif
+ if (rsa != NULL)
+ RSA_free(rsa);
+ opensslrsa_destroy(key);
+ dst__privstruct_free(&priv, mctx);
+ memset(&priv, 0, sizeof(priv));
+ return (ret);
+}
+
+static isc_result_t
+opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
+ const char *pin)
+{
+ ENGINE *e = NULL;
+ isc_result_t ret;
+ EVP_PKEY *pkey = NULL;
+
+ UNUSED(pin);
+
+ e = dst__openssl_getengine(engine);
+ if (e == NULL)
+ DST_RET(DST_R_NOENGINE);
+ pkey = ENGINE_load_private_key(e, label, NULL, NULL);
+ if (pkey == NULL)
+ DST_RET(ISC_R_NOMEMORY);
+ key->engine = isc_mem_strdup(key->mctx, label);
+ 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);
+ key->key_size = EVP_PKEY_bits(pkey);
+#if USE_EVP
+ key->keydata.pkey = pkey;
+#else
+ key->keydata.rsa = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (key->keydata.rsa == NULL)
+ return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
+#endif
+ return (ISC_R_SUCCESS);
+
+ err:
+ if (pkey != NULL)
+ EVP_PKEY_free(pkey);
+ return (ret);
+}
+
+static dst_func_t opensslrsa_functions = {
+ opensslrsa_createctx,
+ opensslrsa_destroyctx,
+ opensslrsa_adddata,
+ opensslrsa_sign,
+ opensslrsa_verify,
+ NULL, /*%< computesecret */
+ opensslrsa_compare,
+ NULL, /*%< paramcompare */
+ opensslrsa_generate,
+ opensslrsa_isprivate,
+ opensslrsa_destroy,
+ opensslrsa_todns,
+ opensslrsa_fromdns,
+ opensslrsa_tofile,
+ opensslrsa_parse,
+ NULL, /*%< cleanup */
+ opensslrsa_fromlabel,
+};
+
+isc_result_t
+dst__opensslrsa_init(dst_func_t **funcp) {
+ REQUIRE(funcp != NULL);
+ if (*funcp == NULL)
+ *funcp = &opensslrsa_functions;
+ return (ISC_R_SUCCESS);
+}
+
+#else /* OPENSSL */
+
+#include <isc/util.h>
+
+EMPTY_TRANSLATION_UNIT
+
+#endif /* OPENSSL */
+/*! \file */
diff --git a/lib/dns/order.c b/lib/dns/order.c
new file mode 100644
index 0000000..853b001
--- /dev/null
+++ b/lib/dns/order.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: order.c,v 1.10 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/types.h>
+#include <isc/util.h>
+#include <isc/refcount.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/order.h>
+#include <dns/rdataset.h>
+#include <dns/types.h>
+
+typedef struct dns_order_ent dns_order_ent_t;
+struct dns_order_ent {
+ dns_fixedname_t name;
+ dns_rdataclass_t rdclass;
+ dns_rdatatype_t rdtype;
+ unsigned int mode;
+ ISC_LINK(dns_order_ent_t) link;
+};
+
+struct dns_order {
+ unsigned int magic;
+ isc_refcount_t references;
+ ISC_LIST(dns_order_ent_t) ents;
+ isc_mem_t *mctx;
+};
+
+#define DNS_ORDER_MAGIC ISC_MAGIC('O','r','d','r')
+#define DNS_ORDER_VALID(order) ISC_MAGIC_VALID(order, DNS_ORDER_MAGIC)
+
+isc_result_t
+dns_order_create(isc_mem_t *mctx, dns_order_t **orderp) {
+ dns_order_t *order;
+ isc_result_t result;
+
+ REQUIRE(orderp != NULL && *orderp == NULL);
+
+ order = isc_mem_get(mctx, sizeof(*order));
+ if (order == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ISC_LIST_INIT(order->ents);
+
+ /* Implicit attach. */
+ result = isc_refcount_init(&order->references, 1);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, order, sizeof(*order));
+ return (result);
+ }
+
+ order->mctx = NULL;
+ isc_mem_attach(mctx, &order->mctx);
+ order->magic = DNS_ORDER_MAGIC;
+ *orderp = order;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_order_add(dns_order_t *order, dns_name_t *name,
+ dns_rdatatype_t rdtype, dns_rdataclass_t rdclass,
+ unsigned int mode)
+{
+ dns_order_ent_t *ent;
+
+ REQUIRE(DNS_ORDER_VALID(order));
+ REQUIRE(mode == DNS_RDATASETATTR_RANDOMIZE ||
+ mode == DNS_RDATASETATTR_FIXEDORDER ||
+ mode == 0 /* DNS_RDATASETATTR_CYCLIC */ );
+
+ ent = isc_mem_get(order->mctx, sizeof(*ent));
+ if (ent == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dns_fixedname_init(&ent->name);
+ RUNTIME_CHECK(dns_name_copy(name, dns_fixedname_name(&ent->name), NULL)
+ == ISC_R_SUCCESS);
+ ent->rdtype = rdtype;
+ ent->rdclass = rdclass;
+ ent->mode = mode;
+ ISC_LINK_INIT(ent, link);
+ ISC_LIST_INITANDAPPEND(order->ents, ent, link);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_boolean_t
+match(dns_name_t *name1, dns_name_t *name2) {
+
+ if (dns_name_iswildcard(name2))
+ return(dns_name_matcheswildcard(name1, name2));
+ return (dns_name_equal(name1, name2));
+}
+
+unsigned int
+dns_order_find(dns_order_t *order, dns_name_t *name,
+ dns_rdatatype_t rdtype, dns_rdataclass_t rdclass)
+{
+ dns_order_ent_t *ent;
+ REQUIRE(DNS_ORDER_VALID(order));
+
+ for (ent = ISC_LIST_HEAD(order->ents);
+ ent != NULL;
+ ent = ISC_LIST_NEXT(ent, link)) {
+ if (ent->rdtype != rdtype && ent->rdtype != dns_rdatatype_any)
+ continue;
+ if (ent->rdclass != rdclass &&
+ ent->rdclass != dns_rdataclass_any)
+ continue;
+ if (match(name, dns_fixedname_name(&ent->name)))
+ return (ent->mode);
+ }
+ return (0);
+}
+
+void
+dns_order_attach(dns_order_t *source, dns_order_t **target) {
+ REQUIRE(DNS_ORDER_VALID(source));
+ REQUIRE(target != NULL && *target == NULL);
+ isc_refcount_increment(&source->references, NULL);
+ *target = source;
+}
+
+void
+dns_order_detach(dns_order_t **orderp) {
+ dns_order_t *order;
+ dns_order_ent_t *ent;
+ unsigned int references;
+
+ REQUIRE(orderp != NULL);
+ order = *orderp;
+ REQUIRE(DNS_ORDER_VALID(order));
+ isc_refcount_decrement(&order->references, &references);
+ *orderp = NULL;
+ if (references != 0)
+ return;
+
+ order->magic = 0;
+ while ((ent = ISC_LIST_HEAD(order->ents)) != NULL) {
+ ISC_LIST_UNLINK(order->ents, ent, link);
+ isc_mem_put(order->mctx, ent, sizeof(*ent));
+ }
+ isc_refcount_destroy(&order->references);
+ isc_mem_putanddetach(&order->mctx, order, sizeof(*order));
+}
diff --git a/lib/dns/peer.c b/lib/dns/peer.c
new file mode 100644
index 0000000..12474cb
--- /dev/null
+++ b/lib/dns/peer.c
@@ -0,0 +1,712 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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: peer.c,v 1.31 2008/04/03 06:09:04 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+#include <isc/sockaddr.h>
+
+#include <dns/bit.h>
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/peer.h>
+
+/*%
+ * Bit positions in the dns_peer_t structure flags field
+ */
+#define BOGUS_BIT 0
+#define SERVER_TRANSFER_FORMAT_BIT 1
+#define TRANSFERS_BIT 2
+#define PROVIDE_IXFR_BIT 3
+#define REQUEST_IXFR_BIT 4
+#define SUPPORT_EDNS_BIT 5
+#define SERVER_UDPSIZE_BIT 6
+#define SERVER_MAXUDP_BIT 7
+#define REQUEST_NSID_BIT 8
+
+static void
+peerlist_delete(dns_peerlist_t **list);
+
+static void
+peer_delete(dns_peer_t **peer);
+
+isc_result_t
+dns_peerlist_new(isc_mem_t *mem, dns_peerlist_t **list) {
+ dns_peerlist_t *l;
+
+ REQUIRE(list != NULL);
+
+ l = isc_mem_get(mem, sizeof(*l));
+ if (l == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ISC_LIST_INIT(l->elements);
+ l->mem = mem;
+ l->refs = 1;
+ l->magic = DNS_PEERLIST_MAGIC;
+
+ *list = l;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_peerlist_attach(dns_peerlist_t *source, dns_peerlist_t **target) {
+ REQUIRE(DNS_PEERLIST_VALID(source));
+ REQUIRE(target != NULL);
+ REQUIRE(*target == NULL);
+
+ source->refs++;
+
+ ENSURE(source->refs != 0xffffffffU);
+
+ *target = source;
+}
+
+void
+dns_peerlist_detach(dns_peerlist_t **list) {
+ dns_peerlist_t *plist;
+
+ REQUIRE(list != NULL);
+ REQUIRE(*list != NULL);
+ REQUIRE(DNS_PEERLIST_VALID(*list));
+
+ plist = *list;
+ *list = NULL;
+
+ REQUIRE(plist->refs > 0);
+
+ plist->refs--;
+
+ if (plist->refs == 0)
+ peerlist_delete(&plist);
+}
+
+static void
+peerlist_delete(dns_peerlist_t **list) {
+ dns_peerlist_t *l;
+ dns_peer_t *server, *stmp;
+
+ REQUIRE(list != NULL);
+ REQUIRE(DNS_PEERLIST_VALID(*list));
+
+ l = *list;
+
+ REQUIRE(l->refs == 0);
+
+ server = ISC_LIST_HEAD(l->elements);
+ while (server != NULL) {
+ stmp = ISC_LIST_NEXT(server, next);
+ ISC_LIST_UNLINK(l->elements, server, next);
+ dns_peer_detach(&server);
+ server = stmp;
+ }
+
+ l->magic = 0;
+ isc_mem_put(l->mem, l, sizeof(*l));
+
+ *list = NULL;
+}
+
+void
+dns_peerlist_addpeer(dns_peerlist_t *peers, dns_peer_t *peer) {
+ dns_peer_t *p = NULL;
+
+ dns_peer_attach(peer, &p);
+
+ /*
+ * More specifics to front of list.
+ */
+ for (p = ISC_LIST_HEAD(peers->elements);
+ p != NULL;
+ p = ISC_LIST_NEXT(p, next))
+ if (p->prefixlen < peer->prefixlen)
+ break;
+
+ if (p != NULL)
+ ISC_LIST_INSERTBEFORE(peers->elements, p, peer, next);
+ else
+ ISC_LIST_APPEND(peers->elements, peer, next);
+
+}
+
+isc_result_t
+dns_peerlist_peerbyaddr(dns_peerlist_t *servers,
+ isc_netaddr_t *addr, dns_peer_t **retval)
+{
+ dns_peer_t *server;
+ isc_result_t res;
+
+ REQUIRE(retval != NULL);
+ REQUIRE(DNS_PEERLIST_VALID(servers));
+
+ server = ISC_LIST_HEAD(servers->elements);
+ while (server != NULL) {
+ if (isc_netaddr_eqprefix(addr, &server->address,
+ server->prefixlen))
+ break;
+
+ server = ISC_LIST_NEXT(server, next);
+ }
+
+ if (server != NULL) {
+ *retval = server;
+ res = ISC_R_SUCCESS;
+ } else {
+ res = ISC_R_NOTFOUND;
+ }
+
+ return (res);
+}
+
+
+
+isc_result_t
+dns_peerlist_currpeer(dns_peerlist_t *peers, dns_peer_t **retval) {
+ dns_peer_t *p = NULL;
+
+ p = ISC_LIST_TAIL(peers->elements);
+
+ dns_peer_attach(p, retval);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_new(isc_mem_t *mem, isc_netaddr_t *addr, dns_peer_t **peerptr) {
+ unsigned int prefixlen = 0;
+
+ REQUIRE(peerptr != NULL);
+ switch(addr->family) {
+ case AF_INET:
+ prefixlen = 32;
+ break;
+ case AF_INET6:
+ prefixlen = 128;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ return (dns_peer_newprefix(mem, addr, prefixlen, peerptr));
+}
+
+isc_result_t
+dns_peer_newprefix(isc_mem_t *mem, isc_netaddr_t *addr, unsigned int prefixlen,
+ dns_peer_t **peerptr)
+{
+ dns_peer_t *peer;
+
+ REQUIRE(peerptr != NULL);
+
+ peer = isc_mem_get(mem, sizeof(*peer));
+ if (peer == NULL)
+ return (ISC_R_NOMEMORY);
+
+ peer->magic = DNS_PEER_MAGIC;
+ peer->address = *addr;
+ peer->prefixlen = prefixlen;
+ peer->mem = mem;
+ peer->bogus = ISC_FALSE;
+ peer->transfer_format = dns_one_answer;
+ peer->transfers = 0;
+ peer->request_ixfr = ISC_FALSE;
+ peer->provide_ixfr = ISC_FALSE;
+ peer->key = NULL;
+ peer->refs = 1;
+ peer->transfer_source = NULL;
+ peer->notify_source = NULL;
+ peer->query_source = NULL;
+
+ memset(&peer->bitflags, 0x0, sizeof(peer->bitflags));
+
+ ISC_LINK_INIT(peer, next);
+
+ *peerptr = peer;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_peer_attach(dns_peer_t *source, dns_peer_t **target) {
+ REQUIRE(DNS_PEER_VALID(source));
+ REQUIRE(target != NULL);
+ REQUIRE(*target == NULL);
+
+ source->refs++;
+
+ ENSURE(source->refs != 0xffffffffU);
+
+ *target = source;
+}
+
+void
+dns_peer_detach(dns_peer_t **peer) {
+ dns_peer_t *p;
+
+ REQUIRE(peer != NULL);
+ REQUIRE(*peer != NULL);
+ REQUIRE(DNS_PEER_VALID(*peer));
+
+ p = *peer;
+
+ REQUIRE(p->refs > 0);
+
+ *peer = NULL;
+ p->refs--;
+
+ if (p->refs == 0)
+ peer_delete(&p);
+}
+
+static void
+peer_delete(dns_peer_t **peer) {
+ dns_peer_t *p;
+ isc_mem_t *mem;
+
+ REQUIRE(peer != NULL);
+ REQUIRE(DNS_PEER_VALID(*peer));
+
+ p = *peer;
+
+ REQUIRE(p->refs == 0);
+
+ mem = p->mem;
+ p->mem = NULL;
+ p->magic = 0;
+
+ if (p->key != NULL) {
+ dns_name_free(p->key, mem);
+ isc_mem_put(mem, p->key, sizeof(dns_name_t));
+ }
+
+ if (p->transfer_source != NULL) {
+ isc_mem_put(mem, p->transfer_source,
+ sizeof(*p->transfer_source));
+ }
+
+ isc_mem_put(mem, p, sizeof(*p));
+
+ *peer = NULL;
+}
+
+isc_result_t
+dns_peer_setbogus(dns_peer_t *peer, isc_boolean_t newval) {
+ isc_boolean_t existed;
+
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ existed = DNS_BIT_CHECK(BOGUS_BIT, &peer->bitflags);
+
+ peer->bogus = newval;
+ DNS_BIT_SET(BOGUS_BIT, &peer->bitflags);
+
+ return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getbogus(dns_peer_t *peer, isc_boolean_t *retval) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(retval != NULL);
+
+ if (DNS_BIT_CHECK(BOGUS_BIT, &peer->bitflags)) {
+ *retval = peer->bogus;
+ return (ISC_R_SUCCESS);
+ } else
+ return (ISC_R_NOTFOUND);
+}
+
+
+isc_result_t
+dns_peer_setprovideixfr(dns_peer_t *peer, isc_boolean_t newval) {
+ isc_boolean_t existed;
+
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ existed = DNS_BIT_CHECK(PROVIDE_IXFR_BIT, &peer->bitflags);
+
+ peer->provide_ixfr = newval;
+ DNS_BIT_SET(PROVIDE_IXFR_BIT, &peer->bitflags);
+
+ return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getprovideixfr(dns_peer_t *peer, isc_boolean_t *retval) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(retval != NULL);
+
+ if (DNS_BIT_CHECK(PROVIDE_IXFR_BIT, &peer->bitflags)) {
+ *retval = peer->provide_ixfr;
+ return (ISC_R_SUCCESS);
+ } else {
+ return (ISC_R_NOTFOUND);
+ }
+}
+
+isc_result_t
+dns_peer_setrequestixfr(dns_peer_t *peer, isc_boolean_t newval) {
+ isc_boolean_t existed;
+
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ existed = DNS_BIT_CHECK(REQUEST_IXFR_BIT, &peer->bitflags);
+
+ peer->request_ixfr = newval;
+ DNS_BIT_SET(REQUEST_IXFR_BIT, &peer->bitflags);
+
+ return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getrequestixfr(dns_peer_t *peer, isc_boolean_t *retval) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(retval != NULL);
+
+ if (DNS_BIT_CHECK(REQUEST_IXFR_BIT, &peer->bitflags)) {
+ *retval = peer->request_ixfr;
+ return (ISC_R_SUCCESS);
+ } else
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+dns_peer_setsupportedns(dns_peer_t *peer, isc_boolean_t newval) {
+ isc_boolean_t existed;
+
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ existed = DNS_BIT_CHECK(SUPPORT_EDNS_BIT, &peer->bitflags);
+
+ peer->support_edns = newval;
+ DNS_BIT_SET(SUPPORT_EDNS_BIT, &peer->bitflags);
+
+ return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getsupportedns(dns_peer_t *peer, isc_boolean_t *retval) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(retval != NULL);
+
+ if (DNS_BIT_CHECK(SUPPORT_EDNS_BIT, &peer->bitflags)) {
+ *retval = peer->support_edns;
+ return (ISC_R_SUCCESS);
+ } else
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+dns_peer_setrequestnsid(dns_peer_t *peer, isc_boolean_t newval) {
+ isc_boolean_t existed;
+
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ existed = DNS_BIT_CHECK(REQUEST_NSID_BIT, &peer->bitflags);
+
+ peer->request_nsid = newval;
+ DNS_BIT_SET(REQUEST_NSID_BIT, &peer->bitflags);
+
+ return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getrequestnsid(dns_peer_t *peer, isc_boolean_t *retval) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(retval != NULL);
+
+ if (DNS_BIT_CHECK(REQUEST_NSID_BIT, &peer->bitflags)) {
+ *retval = peer->request_nsid;
+ return (ISC_R_SUCCESS);
+ } else
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+dns_peer_settransfers(dns_peer_t *peer, isc_uint32_t newval) {
+ isc_boolean_t existed;
+
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ existed = DNS_BIT_CHECK(TRANSFERS_BIT, &peer->bitflags);
+
+ peer->transfers = newval;
+ DNS_BIT_SET(TRANSFERS_BIT, &peer->bitflags);
+
+ return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_gettransfers(dns_peer_t *peer, isc_uint32_t *retval) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(retval != NULL);
+
+ if (DNS_BIT_CHECK(TRANSFERS_BIT, &peer->bitflags)) {
+ *retval = peer->transfers;
+ return (ISC_R_SUCCESS);
+ } else {
+ return (ISC_R_NOTFOUND);
+ }
+}
+
+isc_result_t
+dns_peer_settransferformat(dns_peer_t *peer, dns_transfer_format_t newval) {
+ isc_boolean_t existed;
+
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ existed = DNS_BIT_CHECK(SERVER_TRANSFER_FORMAT_BIT,
+ &peer->bitflags);
+
+ peer->transfer_format = newval;
+ DNS_BIT_SET(SERVER_TRANSFER_FORMAT_BIT, &peer->bitflags);
+
+ return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_gettransferformat(dns_peer_t *peer, dns_transfer_format_t *retval) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(retval != NULL);
+
+ if (DNS_BIT_CHECK(SERVER_TRANSFER_FORMAT_BIT, &peer->bitflags)) {
+ *retval = peer->transfer_format;
+ return (ISC_R_SUCCESS);
+ } else {
+ return (ISC_R_NOTFOUND);
+ }
+}
+
+isc_result_t
+dns_peer_getkey(dns_peer_t *peer, dns_name_t **retval) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(retval != NULL);
+
+ if (peer->key != NULL) {
+ *retval = peer->key;
+ }
+
+ return (peer->key == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_setkey(dns_peer_t *peer, dns_name_t **keyval) {
+ isc_boolean_t exists = ISC_FALSE;
+
+ if (peer->key != NULL) {
+ dns_name_free(peer->key, peer->mem);
+ isc_mem_put(peer->mem, peer->key, sizeof(dns_name_t));
+ exists = ISC_TRUE;
+ }
+
+ peer->key = *keyval;
+ *keyval = NULL;
+
+ return (exists ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_setkeybycharp(dns_peer_t *peer, const char *keyval) {
+ isc_buffer_t b;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ isc_result_t result;
+
+ dns_fixedname_init(&fname);
+ 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);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ name = isc_mem_get(peer->mem, sizeof(dns_name_t));
+ if (name == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dns_name_init(name, NULL);
+ result = dns_name_dup(dns_fixedname_name(&fname), peer->mem, name);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(peer->mem, name, sizeof(dns_name_t));
+ return (result);
+ }
+
+ result = dns_peer_setkey(peer, &name);
+ if (result != ISC_R_SUCCESS)
+ isc_mem_put(peer->mem, name, sizeof(dns_name_t));
+
+ return (result);
+}
+
+isc_result_t
+dns_peer_settransfersource(dns_peer_t *peer,
+ const isc_sockaddr_t *transfer_source)
+{
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ if (peer->transfer_source != NULL) {
+ isc_mem_put(peer->mem, peer->transfer_source,
+ sizeof(*peer->transfer_source));
+ peer->transfer_source = NULL;
+ }
+ if (transfer_source != NULL) {
+ peer->transfer_source = isc_mem_get(peer->mem,
+ sizeof(*peer->transfer_source));
+ if (peer->transfer_source == NULL)
+ return (ISC_R_NOMEMORY);
+
+ *peer->transfer_source = *transfer_source;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_gettransfersource(dns_peer_t *peer, isc_sockaddr_t *transfer_source) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(transfer_source != NULL);
+
+ if (peer->transfer_source == NULL)
+ return (ISC_R_NOTFOUND);
+ *transfer_source = *peer->transfer_source;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_setnotifysource(dns_peer_t *peer,
+ const isc_sockaddr_t *notify_source)
+{
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ if (peer->notify_source != NULL) {
+ isc_mem_put(peer->mem, peer->notify_source,
+ sizeof(*peer->notify_source));
+ peer->notify_source = NULL;
+ }
+ if (notify_source != NULL) {
+ peer->notify_source = isc_mem_get(peer->mem,
+ sizeof(*peer->notify_source));
+ if (peer->notify_source == NULL)
+ return (ISC_R_NOMEMORY);
+
+ *peer->notify_source = *notify_source;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getnotifysource(dns_peer_t *peer, isc_sockaddr_t *notify_source) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(notify_source != NULL);
+
+ if (peer->notify_source == NULL)
+ return (ISC_R_NOTFOUND);
+ *notify_source = *peer->notify_source;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_setquerysource(dns_peer_t *peer, const isc_sockaddr_t *query_source) {
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ if (peer->query_source != NULL) {
+ isc_mem_put(peer->mem, peer->query_source,
+ sizeof(*peer->query_source));
+ peer->query_source = NULL;
+ }
+ if (query_source != NULL) {
+ peer->query_source = isc_mem_get(peer->mem,
+ sizeof(*peer->query_source));
+ if (peer->query_source == NULL)
+ return (ISC_R_NOMEMORY);
+
+ *peer->query_source = *query_source;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getquerysource(dns_peer_t *peer, isc_sockaddr_t *query_source) {
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(query_source != NULL);
+
+ if (peer->query_source == NULL)
+ return (ISC_R_NOTFOUND);
+ *query_source = *peer->query_source;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_setudpsize(dns_peer_t *peer, isc_uint16_t udpsize) {
+ isc_boolean_t existed;
+
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ existed = DNS_BIT_CHECK(SERVER_UDPSIZE_BIT, &peer->bitflags);
+
+ peer->udpsize = udpsize;
+ DNS_BIT_SET(SERVER_UDPSIZE_BIT, &peer->bitflags);
+
+ return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getudpsize(dns_peer_t *peer, isc_uint16_t *udpsize) {
+
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(udpsize != NULL);
+
+ if (DNS_BIT_CHECK(SERVER_UDPSIZE_BIT, &peer->bitflags)) {
+ *udpsize = peer->udpsize;
+ return (ISC_R_SUCCESS);
+ } else {
+ return (ISC_R_NOTFOUND);
+ }
+}
+
+isc_result_t
+dns_peer_setmaxudp(dns_peer_t *peer, isc_uint16_t maxudp) {
+ isc_boolean_t existed;
+
+ REQUIRE(DNS_PEER_VALID(peer));
+
+ existed = DNS_BIT_CHECK(SERVER_MAXUDP_BIT, &peer->bitflags);
+
+ peer->maxudp = maxudp;
+ DNS_BIT_SET(SERVER_MAXUDP_BIT, &peer->bitflags);
+
+ return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_peer_getmaxudp(dns_peer_t *peer, isc_uint16_t *maxudp) {
+
+ REQUIRE(DNS_PEER_VALID(peer));
+ REQUIRE(maxudp != NULL);
+
+ if (DNS_BIT_CHECK(SERVER_MAXUDP_BIT, &peer->bitflags)) {
+ *maxudp = peer->maxudp;
+ return (ISC_R_SUCCESS);
+ } else {
+ return (ISC_R_NOTFOUND);
+ }
+}
diff --git a/lib/dns/portlist.c b/lib/dns/portlist.c
new file mode 100644
index 0000000..5bc89f4
--- /dev/null
+++ b/lib/dns/portlist.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: portlist.c,v 1.13 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/refcount.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/types.h>
+#include <dns/portlist.h>
+
+#define DNS_PORTLIST_MAGIC ISC_MAGIC('P','L','S','T')
+#define DNS_VALID_PORTLIST(p) ISC_MAGIC_VALID(p, DNS_PORTLIST_MAGIC)
+
+typedef struct dns_element {
+ in_port_t port;
+ isc_uint16_t flags;
+} dns_element_t;
+
+struct dns_portlist {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_refcount_t refcount;
+ isc_mutex_t lock;
+ dns_element_t *list;
+ unsigned int allocated;
+ unsigned int active;
+};
+
+#define DNS_PL_INET 0x0001
+#define DNS_PL_INET6 0x0002
+#define DNS_PL_ALLOCATE 16
+
+static int
+compare(const void *arg1, const void *arg2) {
+ const dns_element_t *e1 = (const dns_element_t *)arg1;
+ const dns_element_t *e2 = (const dns_element_t *)arg2;
+
+ if (e1->port < e2->port)
+ return (-1);
+ if (e1->port > e2->port)
+ return (1);
+ return (0);
+}
+
+isc_result_t
+dns_portlist_create(isc_mem_t *mctx, dns_portlist_t **portlistp) {
+ dns_portlist_t *portlist;
+ isc_result_t result;
+
+ REQUIRE(portlistp != NULL && *portlistp == NULL);
+
+ portlist = isc_mem_get(mctx, sizeof(*portlist));
+ if (portlist == NULL)
+ return (ISC_R_NOMEMORY);
+ result = isc_mutex_init(&portlist->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, portlist, sizeof(*portlist));
+ return (result);
+ }
+ result = isc_refcount_init(&portlist->refcount, 1);
+ if (result != ISC_R_SUCCESS) {
+ DESTROYLOCK(&portlist->lock);
+ isc_mem_put(mctx, portlist, sizeof(*portlist));
+ return (result);
+ }
+ portlist->list = NULL;
+ portlist->allocated = 0;
+ portlist->active = 0;
+ portlist->mctx = NULL;
+ isc_mem_attach(mctx, &portlist->mctx);
+ portlist->magic = DNS_PORTLIST_MAGIC;
+ *portlistp = portlist;
+ return (ISC_R_SUCCESS);
+}
+
+static dns_element_t *
+find_port(dns_element_t *list, unsigned int len, in_port_t port) {
+ unsigned int xtry = len / 2;
+ unsigned int min = 0;
+ unsigned int max = len - 1;
+ unsigned int last = len;
+
+ for (;;) {
+ if (list[xtry].port == port)
+ return (&list[xtry]);
+ if (port > list[xtry].port) {
+ if (xtry == max)
+ break;
+ min = xtry;
+ xtry = xtry + (max - xtry + 1) / 2;
+ INSIST(xtry <= max);
+ if (xtry == last)
+ break;
+ last = min;
+ } else {
+ if (xtry == min)
+ break;
+ max = xtry;
+ xtry = xtry - (xtry - min + 1) / 2;
+ INSIST(xtry >= min);
+ if (xtry == last)
+ break;
+ last = max;
+ }
+ }
+ return (NULL);
+}
+
+isc_result_t
+dns_portlist_add(dns_portlist_t *portlist, int af, in_port_t port) {
+ dns_element_t *el;
+ isc_result_t result;
+
+ REQUIRE(DNS_VALID_PORTLIST(portlist));
+ REQUIRE(af == AF_INET || af == AF_INET6);
+
+ LOCK(&portlist->lock);
+ if (portlist->active != 0) {
+ el = find_port(portlist->list, portlist->active, port);
+ if (el != NULL) {
+ if (af == AF_INET)
+ el->flags |= DNS_PL_INET;
+ else
+ el->flags |= DNS_PL_INET6;
+ result = ISC_R_SUCCESS;
+ goto unlock;
+ }
+ }
+
+ if (portlist->allocated <= portlist->active) {
+ unsigned int allocated;
+ allocated = portlist->allocated + DNS_PL_ALLOCATE;
+ el = isc_mem_get(portlist->mctx, sizeof(*el) * allocated);
+ if (el == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto unlock;
+ }
+ if (portlist->list != NULL) {
+ memcpy(el, portlist->list,
+ portlist->allocated * sizeof(*el));
+ isc_mem_put(portlist->mctx, portlist->list,
+ portlist->allocated * sizeof(*el));
+ }
+ portlist->list = el;
+ portlist->allocated = allocated;
+ }
+ portlist->list[portlist->active].port = port;
+ if (af == AF_INET)
+ portlist->list[portlist->active].flags = DNS_PL_INET;
+ else
+ portlist->list[portlist->active].flags = DNS_PL_INET6;
+ portlist->active++;
+ qsort(portlist->list, portlist->active, sizeof(*el), compare);
+ result = ISC_R_SUCCESS;
+ unlock:
+ UNLOCK(&portlist->lock);
+ return (result);
+}
+
+void
+dns_portlist_remove(dns_portlist_t *portlist, int af, in_port_t port) {
+ dns_element_t *el;
+
+ REQUIRE(DNS_VALID_PORTLIST(portlist));
+ REQUIRE(af == AF_INET || af == AF_INET6);
+
+ LOCK(&portlist->lock);
+ if (portlist->active != 0) {
+ el = find_port(portlist->list, portlist->active, port);
+ if (el != NULL) {
+ if (af == AF_INET)
+ el->flags &= ~DNS_PL_INET;
+ else
+ el->flags &= ~DNS_PL_INET6;
+ if (el->flags == 0) {
+ *el = portlist->list[portlist->active];
+ portlist->active--;
+ qsort(portlist->list, portlist->active,
+ sizeof(*el), compare);
+ }
+ }
+ }
+ UNLOCK(&portlist->lock);
+}
+
+isc_boolean_t
+dns_portlist_match(dns_portlist_t *portlist, int af, in_port_t port) {
+ dns_element_t *el;
+ isc_boolean_t result = ISC_FALSE;
+
+ REQUIRE(DNS_VALID_PORTLIST(portlist));
+ REQUIRE(af == AF_INET || af == AF_INET6);
+ LOCK(&portlist->lock);
+ if (portlist->active != 0) {
+ el = find_port(portlist->list, portlist->active, port);
+ if (el != NULL) {
+ if (af == AF_INET && (el->flags & DNS_PL_INET) != 0)
+ result = ISC_TRUE;
+ if (af == AF_INET6 && (el->flags & DNS_PL_INET6) != 0)
+ result = ISC_TRUE;
+ }
+ }
+ UNLOCK(&portlist->lock);
+ return (result);
+}
+
+void
+dns_portlist_attach(dns_portlist_t *portlist, dns_portlist_t **portlistp) {
+
+ REQUIRE(DNS_VALID_PORTLIST(portlist));
+ REQUIRE(portlistp != NULL && *portlistp == NULL);
+
+ isc_refcount_increment(&portlist->refcount, NULL);
+ *portlistp = portlist;
+}
+
+void
+dns_portlist_detach(dns_portlist_t **portlistp) {
+ dns_portlist_t *portlist;
+ unsigned int count;
+
+ REQUIRE(portlistp != NULL);
+ portlist = *portlistp;
+ REQUIRE(DNS_VALID_PORTLIST(portlist));
+ *portlistp = NULL;
+ isc_refcount_decrement(&portlist->refcount, &count);
+ if (count == 0) {
+ portlist->magic = 0;
+ isc_refcount_destroy(&portlist->refcount);
+ if (portlist->list != NULL)
+ isc_mem_put(portlist->mctx, portlist->list,
+ portlist->allocated *
+ sizeof(*portlist->list));
+ DESTROYLOCK(&portlist->lock);
+ isc_mem_putanddetach(&portlist->mctx, portlist,
+ sizeof(*portlist));
+ }
+}
diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c
new file mode 100644
index 0000000..112591e
--- /dev/null
+++ b/lib/dns/rbt.c
@@ -0,0 +1,2657 @@
+/*
+ * 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
+ * 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: rbt.c,v 1.142 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+/* Principal Authors: DCL */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/refcount.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/*%
+ * This define is so dns/name.h (included by dns/fixedname.h) uses more
+ * efficient macro calls instead of functions for a few operations.
+ */
+#define DNS_NAME_USEINLINE 1
+
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/rbt.h>
+#include <dns/result.h>
+
+#define RBT_MAGIC ISC_MAGIC('R', 'B', 'T', '+')
+#define VALID_RBT(rbt) ISC_MAGIC_VALID(rbt, RBT_MAGIC)
+
+/*
+ * XXXDCL Since parent pointers were added in again, I could remove all of the
+ * chain junk, and replace with dns_rbt_firstnode, _previousnode, _nextnode,
+ * _lastnode. This would involve pretty major change to the API.
+ */
+#define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-')
+#define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
+
+#define RBT_HASH_SIZE 64
+
+#ifdef RBT_MEM_TEST
+#undef RBT_HASH_SIZE
+#define RBT_HASH_SIZE 2 /*%< To give the reallocation code a workout. */
+#endif
+
+struct dns_rbt {
+ unsigned int magic;
+ isc_mem_t * mctx;
+ dns_rbtnode_t * root;
+ void (*data_deleter)(void *, void *);
+ void * deleter_arg;
+ unsigned int nodecount;
+ unsigned int hashsize;
+ dns_rbtnode_t ** hashtable;
+};
+
+#define RED 0
+#define BLACK 1
+
+/*%
+ * Elements of the rbtnode structure.
+ */
+#define PARENT(node) ((node)->parent)
+#define LEFT(node) ((node)->left)
+#define RIGHT(node) ((node)->right)
+#define DOWN(node) ((node)->down)
+#define DATA(node) ((node)->data)
+#define HASHNEXT(node) ((node)->hashnext)
+#define HASHVAL(node) ((node)->hashval)
+#define COLOR(node) ((node)->color)
+#define NAMELEN(node) ((node)->namelen)
+#define OFFSETLEN(node) ((node)->offsetlen)
+#define ATTRS(node) ((node)->attributes)
+#define PADBYTES(node) ((node)->padbytes)
+#define IS_ROOT(node) ISC_TF((node)->is_root == 1)
+#define FINDCALLBACK(node) ISC_TF((node)->find_callback == 1)
+
+/*%
+ * Structure elements from the rbtdb.c, not
+ * used as part of the rbt.c algorithms.
+ */
+#define DIRTY(node) ((node)->dirty)
+#define WILD(node) ((node)->wild)
+#define LOCKNUM(node) ((node)->locknum)
+
+/*%
+ * The variable length stuff stored after the node.
+ */
+#define NAME(node) ((unsigned char *)((node) + 1))
+#define OFFSETS(node) (NAME(node) + NAMELEN(node))
+
+#define NODE_SIZE(node) (sizeof(*node) + \
+ NAMELEN(node) + OFFSETLEN(node) + PADBYTES(node))
+
+/*%
+ * Color management.
+ */
+#define IS_RED(node) ((node) != NULL && (node)->color == RED)
+#define IS_BLACK(node) ((node) == NULL || (node)->color == BLACK)
+#define MAKE_RED(node) ((node)->color = RED)
+#define MAKE_BLACK(node) ((node)->color = BLACK)
+
+/*%
+ * Chain management.
+ *
+ * The "ancestors" member of chains were removed, with their job now
+ * being wholy handled by parent pointers (which didn't exist, because
+ * of memory concerns, when chains were first implemented).
+ */
+#define ADD_LEVEL(chain, node) \
+ (chain)->levels[(chain)->level_count++] = (node)
+
+/*%
+ * The following macros directly access normally private name variables.
+ * These macros are used to avoid a lot of function calls in the critical
+ * path of the tree traversal code.
+ */
+
+#define NODENAME(node, name) \
+do { \
+ (name)->length = NAMELEN(node); \
+ (name)->labels = OFFSETLEN(node); \
+ (name)->ndata = NAME(node); \
+ (name)->offsets = OFFSETS(node); \
+ (name)->attributes = ATTRS(node); \
+ (name)->attributes |= DNS_NAMEATTR_READONLY; \
+} while (0)
+
+#ifdef DNS_RBT_USEHASH
+static isc_result_t
+inithash(dns_rbt_t *rbt);
+#endif
+
+#ifdef DEBUG
+#define inline
+/*
+ * A little something to help out in GDB.
+ */
+dns_name_t Name(dns_rbtnode_t *node);
+dns_name_t
+Name(dns_rbtnode_t *node) {
+ dns_name_t name;
+
+ dns_name_init(&name, NULL);
+ if (node != NULL)
+ NODENAME(node, &name);
+
+ return (name);
+}
+
+static void dns_rbt_printnodename(dns_rbtnode_t *node);
+#endif
+
+static inline dns_rbtnode_t *
+find_up(dns_rbtnode_t *node) {
+ dns_rbtnode_t *root;
+
+ /*
+ * Return the node in the level above the argument node that points
+ * to the level the argument node is in. If the argument node is in
+ * the top level, the return value is NULL.
+ */
+ for (root = node; ! IS_ROOT(root); root = PARENT(root))
+ ; /* Nothing. */
+
+ return (PARENT(root));
+}
+
+/*
+ * Forward declarations.
+ */
+static isc_result_t
+create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep);
+
+#ifdef DNS_RBT_USEHASH
+static inline void
+hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name);
+static inline void
+unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
+#else
+#define hash_node(rbt, node, name) (ISC_R_SUCCESS)
+#define unhash_node(rbt, node)
+#endif
+
+static inline void
+rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
+static inline void
+rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
+
+static void
+dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
+ dns_rbtnode_t **rootp);
+
+static void
+dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp);
+
+static isc_result_t
+dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node);
+
+static void
+dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
+ dns_rbtnode_t **nodep);
+
+/*
+ * Initialize a red/black tree of trees.
+ */
+isc_result_t
+dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
+ void *deleter_arg, dns_rbt_t **rbtp)
+{
+#ifdef DNS_RBT_USEHASH
+ isc_result_t result;
+#endif
+ dns_rbt_t *rbt;
+
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(rbtp != NULL && *rbtp == NULL);
+ REQUIRE(deleter == NULL ? deleter_arg == NULL : 1);
+
+ rbt = (dns_rbt_t *)isc_mem_get(mctx, sizeof(*rbt));
+ if (rbt == NULL)
+ return (ISC_R_NOMEMORY);
+
+ rbt->mctx = mctx;
+ rbt->data_deleter = deleter;
+ rbt->deleter_arg = deleter_arg;
+ rbt->root = NULL;
+ rbt->nodecount = 0;
+ rbt->hashtable = NULL;
+ rbt->hashsize = 0;
+
+#ifdef DNS_RBT_USEHASH
+ result = inithash(rbt);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, rbt, sizeof(*rbt));
+ return (result);
+ }
+#endif
+
+ rbt->magic = RBT_MAGIC;
+
+ *rbtp = rbt;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Deallocate a red/black tree of trees.
+ */
+void
+dns_rbt_destroy(dns_rbt_t **rbtp) {
+ RUNTIME_CHECK(dns_rbt_destroy2(rbtp, 0) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
+ dns_rbt_t *rbt;
+
+ REQUIRE(rbtp != NULL && VALID_RBT(*rbtp));
+
+ rbt = *rbtp;
+
+ dns_rbt_deletetreeflat(rbt, quantum, &rbt->root);
+ if (rbt->root != NULL)
+ return (ISC_R_QUOTA);
+
+ INSIST(rbt->nodecount == 0);
+
+ if (rbt->hashtable != NULL)
+ isc_mem_put(rbt->mctx, rbt->hashtable,
+ rbt->hashsize * sizeof(dns_rbtnode_t *));
+
+ rbt->magic = 0;
+
+ isc_mem_put(rbt->mctx, rbt, sizeof(*rbt));
+ *rbtp = NULL;
+ return (ISC_R_SUCCESS);
+}
+
+unsigned int
+dns_rbt_nodecount(dns_rbt_t *rbt) {
+ REQUIRE(VALID_RBT(rbt));
+ return (rbt->nodecount);
+}
+
+static inline isc_result_t
+chain_name(dns_rbtnodechain_t *chain, dns_name_t *name,
+ isc_boolean_t include_chain_end)
+{
+ dns_name_t nodename;
+ isc_result_t result = ISC_R_SUCCESS;
+ int i;
+
+ dns_name_init(&nodename, NULL);
+
+ if (include_chain_end && chain->end != NULL) {
+ NODENAME(chain->end, &nodename);
+ result = dns_name_copy(&nodename, name, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else
+ dns_name_reset(name);
+
+ for (i = (int)chain->level_count - 1; i >= 0; i--) {
+ NODENAME(chain->levels[i], &nodename);
+ result = dns_name_concatenate(name, &nodename, name, NULL);
+
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ return (result);
+}
+
+static inline isc_result_t
+move_chain_to_last(dns_rbtnodechain_t *chain, dns_rbtnode_t *node) {
+ do {
+ /*
+ * Go as far right and then down as much as possible,
+ * as long as the rightmost node has a down pointer.
+ */
+ while (RIGHT(node) != NULL)
+ node = RIGHT(node);
+
+ if (DOWN(node) == NULL)
+ break;
+
+ ADD_LEVEL(chain, node);
+ node = DOWN(node);
+ } while (1);
+
+ chain->end = node;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Add 'name' to tree, initializing its data pointer with 'data'.
+ */
+
+isc_result_t
+dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
+ /*
+ * Does this thing have too many variables or what?
+ */
+ dns_rbtnode_t **root, *parent, *child, *current, *new_current;
+ dns_name_t *add_name, *new_name, current_name, *prefix, *suffix;
+ dns_fixedname_t fixedcopy, fixedprefix, fixedsuffix, fnewname;
+ dns_offsets_t current_offsets;
+ dns_namereln_t compared;
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rbtnodechain_t chain;
+ unsigned int common_labels;
+ unsigned int nlabels, hlabels;
+ int order;
+
+ REQUIRE(VALID_RBT(rbt));
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE(nodep != NULL && *nodep == NULL);
+
+ /*
+ * Create a copy of the name so the original name structure is
+ * not modified.
+ */
+ dns_fixedname_init(&fixedcopy);
+ add_name = dns_fixedname_name(&fixedcopy);
+ dns_name_clone(name, add_name);
+
+ if (rbt->root == NULL) {
+ result = create_node(rbt->mctx, add_name, &new_current);
+ if (result == ISC_R_SUCCESS) {
+ rbt->nodecount++;
+ new_current->is_root = 1;
+ rbt->root = new_current;
+ *nodep = new_current;
+ hash_node(rbt, new_current, name);
+ }
+ return (result);
+ }
+
+ dns_rbtnodechain_init(&chain, rbt->mctx);
+
+ dns_fixedname_init(&fixedprefix);
+ dns_fixedname_init(&fixedsuffix);
+ prefix = dns_fixedname_name(&fixedprefix);
+ suffix = dns_fixedname_name(&fixedsuffix);
+
+ root = &rbt->root;
+ INSIST(IS_ROOT(*root));
+ parent = NULL;
+ current = NULL;
+ child = *root;
+ dns_name_init(&current_name, current_offsets);
+ dns_fixedname_init(&fnewname);
+ new_name = dns_fixedname_name(&fnewname);
+ nlabels = dns_name_countlabels(name);
+ hlabels = 0;
+
+ do {
+ current = child;
+
+ NODENAME(current, &current_name);
+ compared = dns_name_fullcompare(add_name, &current_name,
+ &order, &common_labels);
+
+ if (compared == dns_namereln_equal) {
+ *nodep = current;
+ result = ISC_R_EXISTS;
+ break;
+
+ }
+
+ if (compared == dns_namereln_none) {
+
+ if (order < 0) {
+ parent = current;
+ child = LEFT(current);
+
+ } else if (order > 0) {
+ parent = current;
+ child = RIGHT(current);
+
+ }
+
+ } else {
+ /*
+ * This name has some suffix in common with the
+ * name at the current node. If the name at
+ * the current node is shorter, that means the
+ * new name should be in a subtree. If the
+ * name at the current node is longer, that means
+ * the down pointer to this tree should point
+ * to a new tree that has the common suffix, and
+ * the non-common parts of these two names should
+ * start a new tree.
+ */
+ hlabels += common_labels;
+ if (compared == dns_namereln_subdomain) {
+ /*
+ * All of the existing labels are in common,
+ * so the new name is in a subtree.
+ * Whack off the common labels for the
+ * not-in-common part to be searched for
+ * in the next level.
+ */
+ dns_name_split(add_name, common_labels,
+ add_name, NULL);
+
+ /*
+ * Follow the down pointer (possibly NULL).
+ */
+ root = &DOWN(current);
+
+ INSIST(*root == NULL ||
+ (IS_ROOT(*root) &&
+ PARENT(*root) == current));
+
+ parent = NULL;
+ child = DOWN(current);
+ ADD_LEVEL(&chain, current);
+
+ } else {
+ /*
+ * The number of labels in common is fewer
+ * than the number of labels at the current
+ * node, so the current node must be adjusted
+ * to have just the common suffix, and a down
+ * pointer made to a new tree.
+ */
+
+ INSIST(compared == dns_namereln_commonancestor
+ || compared == dns_namereln_contains);
+
+ /*
+ * Ensure the number of levels in the tree
+ * does not exceed the number of logical
+ * levels allowed by DNSSEC.
+ *
+ * XXXDCL need a better error result?
+ *
+ * XXXDCL Since chain ancestors were removed,
+ * no longer used by dns_rbt_addonlevel(),
+ * this is the only real use of chains in the
+ * function. It could be done instead with
+ * a simple integer variable, but I am pressed
+ * for time.
+ */
+ if (chain.level_count ==
+ (sizeof(chain.levels) /
+ sizeof(*chain.levels))) {
+ result = ISC_R_NOSPACE;
+ break;
+ }
+
+ /*
+ * Split the name into two parts, a prefix
+ * which is the not-in-common parts of the
+ * two names and a suffix that is the common
+ * parts of them.
+ */
+ dns_name_split(&current_name, common_labels,
+ prefix, suffix);
+ result = create_node(rbt->mctx, suffix,
+ &new_current);
+
+ if (result != ISC_R_SUCCESS)
+ break;
+
+ /*
+ * Reproduce the tree attributes of the
+ * current node.
+ */
+ new_current->is_root = current->is_root;
+ new_current->nsec3 = current->nsec3;
+ PARENT(new_current) = PARENT(current);
+ LEFT(new_current) = LEFT(current);
+ RIGHT(new_current) = RIGHT(current);
+ COLOR(new_current) = COLOR(current);
+
+ /*
+ * Fix pointers that were to the current node.
+ */
+ if (parent != NULL) {
+ if (LEFT(parent) == current)
+ LEFT(parent) = new_current;
+ else
+ RIGHT(parent) = new_current;
+ }
+ if (LEFT(new_current) != NULL)
+ PARENT(LEFT(new_current)) =
+ new_current;
+ if (RIGHT(new_current) != NULL)
+ PARENT(RIGHT(new_current)) =
+ new_current;
+ if (*root == current)
+ *root = new_current;
+
+ NAMELEN(current) = prefix->length;
+ OFFSETLEN(current) = prefix->labels;
+ memcpy(OFFSETS(current), prefix->offsets,
+ prefix->labels);
+ PADBYTES(current) +=
+ (current_name.length - prefix->length) +
+ (current_name.labels - prefix->labels);
+
+ /*
+ * Set up the new root of the next level.
+ * By definition it will not be the top
+ * level tree, so clear DNS_NAMEATTR_ABSOLUTE.
+ */
+ current->is_root = 1;
+ PARENT(current) = new_current;
+ DOWN(new_current) = current;
+ root = &DOWN(new_current);
+
+ ADD_LEVEL(&chain, new_current);
+
+ LEFT(current) = NULL;
+ RIGHT(current) = NULL;
+
+ MAKE_BLACK(current);
+ ATTRS(current) &= ~DNS_NAMEATTR_ABSOLUTE;
+
+ rbt->nodecount++;
+ dns_name_getlabelsequence(name,
+ nlabels - hlabels,
+ hlabels, new_name);
+ hash_node(rbt, new_current, new_name);
+
+ if (common_labels ==
+ dns_name_countlabels(add_name)) {
+ /*
+ * The name has been added by pushing
+ * the not-in-common parts down to
+ * a new level.
+ */
+ *nodep = new_current;
+ return (ISC_R_SUCCESS);
+
+ } else {
+ /*
+ * The current node has no data,
+ * because it is just a placeholder.
+ * Its data pointer is already NULL
+ * from create_node()), so there's
+ * nothing more to do to it.
+ */
+
+ /*
+ * The not-in-common parts of the new
+ * name will be inserted into the new
+ * level following this loop (unless
+ * result != ISC_R_SUCCESS, which
+ * is tested after the loop ends).
+ */
+ dns_name_split(add_name, common_labels,
+ add_name, NULL);
+
+ break;
+ }
+
+ }
+
+ }
+
+ } while (child != NULL);
+
+ if (result == ISC_R_SUCCESS)
+ result = create_node(rbt->mctx, add_name, &new_current);
+
+ if (result == ISC_R_SUCCESS) {
+ dns_rbt_addonlevel(new_current, current, order, root);
+ rbt->nodecount++;
+ *nodep = new_current;
+ hash_node(rbt, new_current, name);
+ }
+
+ return (result);
+}
+
+/*
+ * Add a name to the tree of trees, associating it with some data.
+ */
+isc_result_t
+dns_rbt_addname(dns_rbt_t *rbt, dns_name_t *name, void *data) {
+ isc_result_t result;
+ dns_rbtnode_t *node;
+
+ REQUIRE(VALID_RBT(rbt));
+ REQUIRE(dns_name_isabsolute(name));
+
+ node = NULL;
+
+ result = dns_rbt_addnode(rbt, name, &node);
+
+ /*
+ * dns_rbt_addnode will report the node exists even when
+ * it does not have data associated with it, but the
+ * dns_rbt_*name functions all behave depending on whether
+ * there is data associated with a node.
+ */
+ if (result == ISC_R_SUCCESS ||
+ (result == ISC_R_EXISTS && DATA(node) == NULL)) {
+ DATA(node) = data;
+ result = ISC_R_SUCCESS;
+ }
+
+ return (result);
+}
+
+/*
+ * Find the node for "name" in the tree of trees.
+ */
+isc_result_t
+dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
+ dns_rbtnode_t **node, dns_rbtnodechain_t *chain,
+ unsigned int options, dns_rbtfindcallback_t callback,
+ void *callback_arg)
+{
+ dns_rbtnode_t *current, *last_compared, *current_root;
+ dns_rbtnodechain_t localchain;
+ dns_name_t *search_name, current_name, *callback_name;
+ dns_fixedname_t fixedcallbackname, fixedsearchname;
+ dns_namereln_t compared;
+ isc_result_t result, saved_result;
+ unsigned int common_labels;
+ unsigned int hlabels = 0;
+ int order;
+
+ REQUIRE(VALID_RBT(rbt));
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE(node != NULL && *node == NULL);
+ REQUIRE((options & (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR))
+ != (DNS_RBTFIND_NOEXACT | DNS_RBTFIND_NOPREDECESSOR));
+
+ /*
+ * If there is a chain it needs to appear to be in a sane state,
+ * otherwise a chain is still needed to generate foundname and
+ * callback_name.
+ */
+ if (chain == NULL) {
+ options |= DNS_RBTFIND_NOPREDECESSOR;
+ chain = &localchain;
+ dns_rbtnodechain_init(chain, rbt->mctx);
+ } else
+ dns_rbtnodechain_reset(chain);
+
+ if (rbt->root == NULL)
+ return (ISC_R_NOTFOUND);
+ else {
+ /*
+ * Appease GCC about variables it incorrectly thinks are
+ * possibly used uninitialized.
+ */
+ compared = dns_namereln_none;
+ last_compared = NULL;
+ }
+
+ dns_fixedname_init(&fixedcallbackname);
+ callback_name = dns_fixedname_name(&fixedcallbackname);
+
+ /*
+ * search_name is the name segment being sought in each tree level.
+ * By using a fixedname, the search_name will definitely have offsets
+ * for use by any splitting.
+ * By using dns_name_clone, no name data should be copied thanks to
+ * the lack of bitstring labels.
+ */
+ dns_fixedname_init(&fixedsearchname);
+ search_name = dns_fixedname_name(&fixedsearchname);
+ dns_name_clone(name, search_name);
+
+ dns_name_init(&current_name, NULL);
+
+ saved_result = ISC_R_SUCCESS;
+ current = rbt->root;
+ current_root = rbt->root;
+
+ while (current != NULL) {
+ NODENAME(current, &current_name);
+ compared = dns_name_fullcompare(search_name, &current_name,
+ &order, &common_labels);
+ last_compared = current;
+
+ if (compared == dns_namereln_equal)
+ break;
+
+ if (compared == dns_namereln_none) {
+#ifdef DNS_RBT_USEHASH
+ dns_name_t hash_name;
+ dns_rbtnode_t *hnode;
+ dns_rbtnode_t *up_current;
+ unsigned int nlabels;
+ unsigned int tlabels = 1;
+ unsigned int hash;
+
+ /*
+ * If there is no hash table, hashing can't be done.
+ */
+ if (rbt->hashtable == NULL)
+ goto nohash;
+
+ /*
+ * The case of current != current_root, that
+ * means a left or right pointer was followed,
+ * only happens when the algorithm fell through to
+ * the traditional binary search because of a
+ * bitstring label. Since we dropped the bitstring
+ * support, this should not happen.
+ */
+ INSIST(current == current_root);
+
+ nlabels = dns_name_countlabels(search_name);
+
+ /*
+ * current_root is the root of the current level, so
+ * it's parent is the same as it's "up" pointer.
+ */
+ up_current = PARENT(current_root);
+ dns_name_init(&hash_name, NULL);
+
+ hashagain:
+ /*
+ * Hash includes tail.
+ */
+ dns_name_getlabelsequence(name,
+ nlabels - tlabels,
+ hlabels + tlabels,
+ &hash_name);
+ hash = dns_name_fullhash(&hash_name, ISC_FALSE);
+ dns_name_getlabelsequence(search_name,
+ nlabels - tlabels,
+ tlabels, &hash_name);
+
+ for (hnode = rbt->hashtable[hash % rbt->hashsize];
+ hnode != NULL;
+ hnode = hnode->hashnext)
+ {
+ dns_name_t hnode_name;
+
+ if (hash != HASHVAL(hnode))
+ continue;
+ if (find_up(hnode) != up_current)
+ continue;
+ dns_name_init(&hnode_name, NULL);
+ NODENAME(hnode, &hnode_name);
+ if (dns_name_equal(&hnode_name, &hash_name))
+ break;
+ }
+
+ if (hnode != NULL) {
+ current = hnode;
+ /*
+ * This is an optimization. If hashing found
+ * the right node, the next call to
+ * dns_name_fullcompare() would obviously
+ * return _equal or _subdomain. Determine
+ * which of those would be the case by
+ * checking if the full name was hashed. Then
+ * make it look like dns_name_fullcompare
+ * was called and jump to the right place.
+ */
+ if (tlabels == nlabels) {
+ compared = dns_namereln_equal;
+ break;
+ } else {
+ common_labels = tlabels;
+ compared = dns_namereln_subdomain;
+ goto subdomain;
+ }
+ }
+
+ if (tlabels++ < nlabels)
+ goto hashagain;
+
+ /*
+ * All of the labels have been tried against the hash
+ * table. Since we dropped the support of bitstring
+ * labels, the name isn't in the table.
+ */
+ current = NULL;
+ continue;
+
+ nohash:
+#endif /* DNS_RBT_USEHASH */
+ /*
+ * Standard binary search tree movement.
+ */
+ if (order < 0)
+ current = LEFT(current);
+ else
+ current = RIGHT(current);
+
+ } else {
+ /*
+ * The names have some common suffix labels.
+ *
+ * If the number in common are equal in length to
+ * the current node's name length, then follow the
+ * down pointer and search in the new tree.
+ */
+ if (compared == dns_namereln_subdomain) {
+ subdomain:
+ /*
+ * Whack off the current node's common parts
+ * for the name to search in the next level.
+ */
+ dns_name_split(search_name, common_labels,
+ search_name, NULL);
+ hlabels += common_labels;
+ /*
+ * This might be the closest enclosing name.
+ */
+ if (DATA(current) != NULL ||
+ (options & DNS_RBTFIND_EMPTYDATA) != 0)
+ *node = current;
+
+ /*
+ * Point the chain to the next level. This
+ * needs to be done before 'current' is pointed
+ * there because the callback in the next
+ * block of code needs the current 'current',
+ * but in the event the callback requests that
+ * the search be stopped then the
+ * DNS_R_PARTIALMATCH code at the end of this
+ * function needs the chain pointed to the
+ * next level.
+ */
+ ADD_LEVEL(chain, current);
+
+ /*
+ * The caller may want to interrupt the
+ * downward search when certain special nodes
+ * are traversed. If this is a special node,
+ * the callback is used to learn what the
+ * caller wants to do.
+ */
+ if (callback != NULL &&
+ FINDCALLBACK(current)) {
+ result = chain_name(chain,
+ callback_name,
+ ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ dns_rbtnodechain_reset(chain);
+ return (result);
+ }
+
+ result = (callback)(current,
+ callback_name,
+ callback_arg);
+ if (result != DNS_R_CONTINUE) {
+ saved_result = result;
+ /*
+ * Treat this node as if it
+ * had no down pointer.
+ */
+ current = NULL;
+ break;
+ }
+ }
+
+ /*
+ * Finally, head to the next tree level.
+ */
+ current = DOWN(current);
+ current_root = current;
+
+ } else {
+ /*
+ * Though there are labels in common, the
+ * entire name at this node is not common
+ * with the search name so the search
+ * name does not exist in the tree.
+ */
+ INSIST(compared == dns_namereln_commonancestor
+ || compared == dns_namereln_contains);
+
+ current = NULL;
+ }
+ }
+ }
+
+ /*
+ * If current is not NULL, NOEXACT is not disallowing exact matches,
+ * and either the node has data or an empty node is ok, return
+ * ISC_R_SUCCESS to indicate an exact match.
+ */
+ if (current != NULL && (options & DNS_RBTFIND_NOEXACT) == 0 &&
+ (DATA(current) != NULL ||
+ (options & DNS_RBTFIND_EMPTYDATA) != 0)) {
+ /*
+ * Found an exact match.
+ */
+ chain->end = current;
+ chain->level_matches = chain->level_count;
+
+ if (foundname != NULL)
+ result = chain_name(chain, foundname, ISC_TRUE);
+ else
+ result = ISC_R_SUCCESS;
+
+ if (result == ISC_R_SUCCESS) {
+ *node = current;
+ result = saved_result;
+ } else
+ *node = NULL;
+ } else {
+ /*
+ * Did not find an exact match (or did not want one).
+ */
+ if (*node != NULL) {
+ /*
+ * ... but found a partially matching superdomain.
+ * Unwind the chain to the partial match node
+ * to set level_matches to the level above the node,
+ * and then to derive the name.
+ *
+ * chain->level_count is guaranteed to be at least 1
+ * here because by definition of finding a superdomain,
+ * the chain is pointed to at least the first subtree.
+ */
+ chain->level_matches = chain->level_count - 1;
+
+ while (chain->levels[chain->level_matches] != *node) {
+ INSIST(chain->level_matches > 0);
+ chain->level_matches--;
+ }
+
+ if (foundname != NULL) {
+ unsigned int saved_count = chain->level_count;
+
+ chain->level_count = chain->level_matches + 1;
+
+ result = chain_name(chain, foundname,
+ ISC_FALSE);
+
+ chain->level_count = saved_count;
+ } else
+ result = ISC_R_SUCCESS;
+
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_PARTIALMATCH;
+
+ } else
+ result = ISC_R_NOTFOUND;
+
+ if (current != NULL) {
+ /*
+ * There was an exact match but either
+ * DNS_RBTFIND_NOEXACT was set, or
+ * DNS_RBTFIND_EMPTYDATA was set and the node had no
+ * data. A policy decision was made to set the
+ * chain to the exact match, but this is subject
+ * to change if it becomes apparent that something
+ * else would be more useful. It is important that
+ * this case is handled here, because the predecessor
+ * setting code below assumes the match was not exact.
+ */
+ INSIST(((options & DNS_RBTFIND_NOEXACT) != 0) ||
+ ((options & DNS_RBTFIND_EMPTYDATA) == 0 &&
+ DATA(current) == NULL));
+ chain->end = current;
+
+ } else if ((options & DNS_RBTFIND_NOPREDECESSOR) != 0) {
+ /*
+ * Ensure the chain points nowhere.
+ */
+ chain->end = NULL;
+
+ } else {
+ /*
+ * Since there was no exact match, the chain argument
+ * needs to be pointed at the DNSSEC predecessor of
+ * the search name.
+ */
+ if (compared == dns_namereln_subdomain) {
+ /*
+ * Attempted to follow a down pointer that was
+ * NULL, which means the searched for name was
+ * a subdomain of a terminal name in the tree.
+ * Since there are no existing subdomains to
+ * order against, the terminal name is the
+ * predecessor.
+ */
+ INSIST(chain->level_count > 0);
+ INSIST(chain->level_matches <
+ chain->level_count);
+ chain->end =
+ chain->levels[--chain->level_count];
+
+ } else {
+ isc_result_t result2;
+
+ /*
+ * Point current to the node that stopped
+ * the search.
+ *
+ * With the hashing modification that has been
+ * added to the algorithm, the stop node of a
+ * standard binary search is not known. So it
+ * has to be found. There is probably a more
+ * clever way of doing this.
+ *
+ * The assignment of current to NULL when
+ * the relationship is *not* dns_namereln_none,
+ * even though it later gets set to the same
+ * last_compared anyway, is simply to not push
+ * the while loop in one more level of
+ * indentation.
+ */
+ if (compared == dns_namereln_none)
+ current = last_compared;
+ else
+ current = NULL;
+
+ while (current != NULL) {
+ NODENAME(current, &current_name);
+ compared = dns_name_fullcompare(
+ search_name,
+ &current_name,
+ &order,
+ &common_labels);
+
+ last_compared = current;
+
+ /*
+ * Standard binary search movement.
+ */
+ if (order < 0)
+ current = LEFT(current);
+ else
+ current = RIGHT(current);
+
+ }
+
+ current = last_compared;
+
+ /*
+ * Reached a point within a level tree that
+ * positively indicates the name is not
+ * present, but the stop node could be either
+ * less than the desired name (order > 0) or
+ * greater than the desired name (order < 0).
+ *
+ * If the stop node is less, it is not
+ * necessarily the predecessor. If the stop
+ * node has a down pointer, then the real
+ * predecessor is at the end of a level below
+ * (not necessarily the next level).
+ * Move down levels until the rightmost node
+ * does not have a down pointer.
+ *
+ * When the stop node is greater, it is
+ * the successor. All the logic for finding
+ * the predecessor is handily encapsulated
+ * in dns_rbtnodechain_prev. In the event
+ * that the search name is less than anything
+ * else in the tree, the chain is reset.
+ * XXX DCL What is the best way for the caller
+ * to know that the search name has
+ * no predecessor?
+ */
+
+
+ if (order > 0) {
+ if (DOWN(current) != NULL) {
+ ADD_LEVEL(chain, current);
+
+ result2 =
+ move_chain_to_last(chain,
+ DOWN(current));
+
+ if (result2 != ISC_R_SUCCESS)
+ result = result2;
+ } else
+ /*
+ * Ah, the pure and simple
+ * case. The stop node is the
+ * predecessor.
+ */
+ chain->end = current;
+
+ } else {
+ INSIST(order < 0);
+
+ chain->end = current;
+
+ result2 = dns_rbtnodechain_prev(chain,
+ NULL,
+ NULL);
+ if (result2 == ISC_R_SUCCESS ||
+ result2 == DNS_R_NEWORIGIN)
+ ; /* Nothing. */
+ else if (result2 == ISC_R_NOMORE)
+ /*
+ * There is no predecessor.
+ */
+ dns_rbtnodechain_reset(chain);
+ else
+ result = result2;
+ }
+
+ }
+ }
+ }
+
+ ENSURE(*node == NULL || DNS_RBTNODE_VALID(*node));
+
+ return (result);
+}
+
+/*
+ * Get the data pointer associated with 'name'.
+ */
+isc_result_t
+dns_rbt_findname(dns_rbt_t *rbt, dns_name_t *name, unsigned int options,
+ dns_name_t *foundname, void **data) {
+ dns_rbtnode_t *node = NULL;
+ isc_result_t result;
+
+ REQUIRE(data != NULL && *data == NULL);
+
+ result = dns_rbt_findnode(rbt, name, foundname, &node, NULL,
+ options, NULL, NULL);
+
+ if (node != NULL &&
+ (DATA(node) != NULL || (options & DNS_RBTFIND_EMPTYDATA) != 0))
+ *data = DATA(node);
+ else
+ result = ISC_R_NOTFOUND;
+
+ return (result);
+}
+
+/*
+ * Delete a name from the tree of trees.
+ */
+isc_result_t
+dns_rbt_deletename(dns_rbt_t *rbt, dns_name_t *name, isc_boolean_t recurse) {
+ dns_rbtnode_t *node = NULL;
+ isc_result_t result;
+
+ REQUIRE(VALID_RBT(rbt));
+ REQUIRE(dns_name_isabsolute(name));
+
+ /*
+ * First, find the node.
+ *
+ * When searching, the name might not have an exact match:
+ * consider a.b.a.com, b.b.a.com and c.b.a.com as the only
+ * elements of a tree, which would make layer 1 a single
+ * node tree of "b.a.com" and layer 2 a three node tree of
+ * a, b, and c. Deleting a.com would find only a partial depth
+ * match in the first layer. Should it be a requirement that
+ * that the name to be deleted have data? For now, it is.
+ *
+ * ->dirty, ->locknum and ->references are ignored; they are
+ * solely the province of rbtdb.c.
+ */
+ result = dns_rbt_findnode(rbt, name, NULL, &node, NULL,
+ DNS_RBTFIND_NOOPTIONS, NULL, NULL);
+
+ if (result == ISC_R_SUCCESS) {
+ if (DATA(node) != NULL)
+ result = dns_rbt_deletenode(rbt, node, recurse);
+ else
+ result = ISC_R_NOTFOUND;
+
+ } else if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_NOTFOUND;
+
+ return (result);
+}
+
+/*
+ * Remove a node from the tree of trees.
+ *
+ * NOTE WELL: deletion is *not* symmetric with addition; that is, reversing
+ * a sequence of additions to be deletions will not generally get the
+ * tree back to the state it started in. For example, if the addition
+ * of "b.c" caused the node "a.b.c" to be split, pushing "a" to its own level,
+ * then the subsequent deletion of "b.c" will not cause "a" to be pulled up,
+ * restoring "a.b.c". The RBT *used* to do this kind of rejoining, but it
+ * turned out to be a bad idea because it could corrupt an active nodechain
+ * that had "b.c" as one of its levels -- and the RBT has no idea what
+ * nodechains are in use by callers, so it can't even *try* to helpfully
+ * fix them up (which would probably be doomed to failure anyway).
+ *
+ * Similarly, it is possible to leave the tree in a state where a supposedly
+ * deleted node still exists. The first case of this is obvious; take
+ * the tree which has "b.c" on one level, pointing to "a". Now deleted "b.c".
+ * It was just established in the previous paragraph why we can't pull "a"
+ * back up to its parent level. But what happens when "a" then gets deleted?
+ * "b.c" is left hanging around without data or children. This condition
+ * is actually pretty easy to detect, but ... should it really be removed?
+ * Is a chain pointing to it? An iterator? Who knows! (Note that the
+ * references structure member cannot be looked at because it is private to
+ * rbtdb.) This is ugly and makes me unhappy, but after hours of trying to
+ * make it more aesthetically proper and getting nowhere, this is the way it
+ * is going to stay until such time as it proves to be a *real* problem.
+ *
+ * Finally, for reference, note that the original routine that did node
+ * joining was called join_nodes(). It has been excised, living now only
+ * in the CVS history, but comments have been left behind that point to it just
+ * in case someone wants to muck with this some more.
+ *
+ * The one positive aspect of all of this is that joining used to have a
+ * case where it might fail. Without trying to join, now this function always
+ * succeeds. It still returns isc_result_t, though, so the API wouldn't change.
+ */
+isc_result_t
+dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse)
+{
+ dns_rbtnode_t *parent;
+
+ REQUIRE(VALID_RBT(rbt));
+ REQUIRE(DNS_RBTNODE_VALID(node));
+
+ if (DOWN(node) != NULL) {
+ if (recurse)
+ RUNTIME_CHECK(dns_rbt_deletetree(rbt, DOWN(node))
+ == ISC_R_SUCCESS);
+ else {
+ if (DATA(node) != NULL && rbt->data_deleter != NULL)
+ rbt->data_deleter(DATA(node), rbt->deleter_arg);
+ DATA(node) = NULL;
+
+ /*
+ * Since there is at least one node below this one and
+ * no recursion was requested, the deletion is
+ * complete. The down node from this node might be all
+ * by itself on a single level, so join_nodes() could
+ * be used to collapse the tree (with all the caveats
+ * of the comment at the start of this function).
+ */
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ /*
+ * Note the node that points to the level of the node that is being
+ * deleted. If the deleted node is the top level, parent will be set
+ * to NULL.
+ */
+ parent = find_up(node);
+
+ /*
+ * This node now has no down pointer (either because it didn't
+ * have one to start, or because it was recursively removed).
+ * So now the node needs to be removed from this level.
+ */
+ dns_rbt_deletefromlevel(node, parent == NULL ? &rbt->root :
+ &DOWN(parent));
+
+ if (DATA(node) != NULL && rbt->data_deleter != NULL)
+ rbt->data_deleter(DATA(node), rbt->deleter_arg);
+
+ unhash_node(rbt, node);
+#if DNS_RBT_USEMAGIC
+ node->magic = 0;
+#endif
+ dns_rbtnode_refdestroy(node);
+ isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
+ rbt->nodecount--;
+
+ /*
+ * There are now two special cases that can exist that would
+ * not have existed if the tree had been created using only
+ * the names that now exist in it. (This is all related to
+ * join_nodes() as described in this function's introductory comment.)
+ * Both cases exist when the deleted node's parent (the node
+ * that pointed to the deleted node's level) is not null but
+ * it has no data: parent != NULL && DATA(parent) == NULL.
+ *
+ * The first case is that the deleted node was the last on its level:
+ * DOWN(parent) == NULL. This case can only exist if the parent was
+ * previously deleted -- and so now, apparently, the parent should go
+ * away. That can't be done though because there might be external
+ * references to it, such as through a nodechain.
+ *
+ * The other case also involves a parent with no data, but with the
+ * deleted node being the next-to-last node instead of the last:
+ * LEFT(DOWN(parent)) == NULL && RIGHT(DOWN(parent)) == NULL.
+ * Presumably now the remaining node on the level should be joined
+ * with the parent, but it's already been described why that can't be
+ * done.
+ */
+
+ /*
+ * This function never fails.
+ */
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_rbt_namefromnode(dns_rbtnode_t *node, dns_name_t *name) {
+
+ REQUIRE(DNS_RBTNODE_VALID(node));
+ REQUIRE(name != NULL);
+ REQUIRE(name->offsets == NULL);
+
+ NODENAME(node, name);
+}
+
+isc_result_t
+dns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name) {
+ dns_name_t current;
+ isc_result_t result;
+
+ REQUIRE(DNS_RBTNODE_VALID(node));
+ REQUIRE(name != NULL);
+ REQUIRE(name->buffer != NULL);
+
+ dns_name_init(&current, NULL);
+ dns_name_reset(name);
+
+ do {
+ INSIST(node != NULL);
+
+ NODENAME(node, &current);
+
+ result = dns_name_concatenate(name, &current, name, NULL);
+ if (result != ISC_R_SUCCESS)
+ break;
+
+ node = find_up(node);
+ } while (! dns_name_isabsolute(name));
+
+ return (result);
+}
+
+char *
+dns_rbt_formatnodename(dns_rbtnode_t *node, char *printname, unsigned int size)
+{
+ dns_fixedname_t fixedname;
+ dns_name_t *name;
+ isc_result_t result;
+
+ REQUIRE(DNS_RBTNODE_VALID(node));
+ REQUIRE(printname != NULL);
+
+ dns_fixedname_init(&fixedname);
+ name = dns_fixedname_name(&fixedname);
+ result = dns_rbt_fullnamefromnode(node, name);
+ if (result == ISC_R_SUCCESS)
+ dns_name_format(name, printname, size);
+ else
+ snprintf(printname, size, "<error building name: %s>",
+ dns_result_totext(result));
+
+ return (printname);
+}
+
+static isc_result_t
+create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) {
+ dns_rbtnode_t *node;
+ isc_region_t region;
+ unsigned int labels;
+
+ REQUIRE(name->offsets != NULL);
+
+ dns_name_toregion(name, &region);
+ labels = dns_name_countlabels(name);
+ ENSURE(labels > 0);
+
+ /*
+ * Allocate space for the node structure, the name, and the offsets.
+ */
+ node = (dns_rbtnode_t *)isc_mem_get(mctx, sizeof(*node) +
+ region.length + labels);
+
+ if (node == NULL)
+ return (ISC_R_NOMEMORY);
+
+ node->is_root = 0;
+ PARENT(node) = NULL;
+ RIGHT(node) = NULL;
+ LEFT(node) = NULL;
+ DOWN(node) = NULL;
+ DATA(node) = NULL;
+#ifdef DNS_RBT_USEHASH
+ HASHNEXT(node) = NULL;
+ HASHVAL(node) = 0;
+#endif
+
+ ISC_LINK_INIT(node, deadlink);
+
+ LOCKNUM(node) = 0;
+ WILD(node) = 0;
+ DIRTY(node) = 0;
+ dns_rbtnode_refinit(node, 0);
+ node->find_callback = 0;
+ node->nsec3 = 0;
+
+ MAKE_BLACK(node);
+
+ /*
+ * The following is stored to make reconstructing a name from the
+ * stored value in the node easy: the length of the name, the number
+ * of labels, whether the name is absolute or not, the name itself,
+ * and the name's offsets table.
+ *
+ * XXX RTH
+ * The offsets table could be made smaller by eliminating the
+ * first offset, which is always 0. This requires changes to
+ * lib/dns/name.c.
+ */
+ NAMELEN(node) = region.length;
+ PADBYTES(node) = 0;
+ OFFSETLEN(node) = labels;
+ ATTRS(node) = name->attributes;
+
+ memcpy(NAME(node), region.base, region.length);
+ memcpy(OFFSETS(node), name->offsets, labels);
+
+#if DNS_RBT_USEMAGIC
+ node->magic = DNS_RBTNODE_MAGIC;
+#endif
+ *nodep = node;
+
+ return (ISC_R_SUCCESS);
+}
+
+#ifdef DNS_RBT_USEHASH
+static inline void
+hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
+ unsigned int hash;
+
+ HASHVAL(node) = dns_name_fullhash(name, ISC_FALSE);
+
+ hash = HASHVAL(node) % rbt->hashsize;
+ HASHNEXT(node) = rbt->hashtable[hash];
+
+ rbt->hashtable[hash] = node;
+}
+
+static isc_result_t
+inithash(dns_rbt_t *rbt) {
+ unsigned int bytes;
+
+ rbt->hashsize = RBT_HASH_SIZE;
+ bytes = rbt->hashsize * sizeof(dns_rbtnode_t *);
+ rbt->hashtable = isc_mem_get(rbt->mctx, bytes);
+
+ if (rbt->hashtable == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(rbt->hashtable, 0, bytes);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rehash(dns_rbt_t *rbt) {
+ unsigned int oldsize;
+ dns_rbtnode_t **oldtable;
+ dns_rbtnode_t *node;
+ unsigned int hash;
+ unsigned int i;
+
+ oldsize = rbt->hashsize;
+ oldtable = rbt->hashtable;
+ rbt->hashsize *= 2 + 1;
+ rbt->hashtable = isc_mem_get(rbt->mctx,
+ rbt->hashsize * sizeof(dns_rbtnode_t *));
+ if (rbt->hashtable == NULL) {
+ rbt->hashtable = oldtable;
+ rbt->hashsize = oldsize;
+ return;
+ }
+
+ for (i = 0; i < rbt->hashsize; i++)
+ rbt->hashtable[i] = NULL;
+
+ for (i = 0; i < oldsize; i++) {
+ node = oldtable[i];
+ while (node != NULL) {
+ hash = HASHVAL(node) % rbt->hashsize;
+ oldtable[i] = HASHNEXT(node);
+ HASHNEXT(node) = rbt->hashtable[hash];
+ rbt->hashtable[hash] = node;
+ node = oldtable[i];
+ }
+ }
+
+ isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *));
+}
+
+static inline void
+hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, dns_name_t *name) {
+
+ REQUIRE(DNS_RBTNODE_VALID(node));
+
+ if (rbt->nodecount >= (rbt->hashsize *3))
+ rehash(rbt);
+
+ hash_add_node(rbt, node, name);
+}
+
+static inline void
+unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
+ unsigned int bucket;
+ dns_rbtnode_t *bucket_node;
+
+ REQUIRE(DNS_RBTNODE_VALID(node));
+
+ if (rbt->hashtable != NULL) {
+ bucket = HASHVAL(node) % rbt->hashsize;
+ bucket_node = rbt->hashtable[bucket];
+
+ if (bucket_node == node)
+ rbt->hashtable[bucket] = HASHNEXT(node);
+ else {
+ while (HASHNEXT(bucket_node) != node) {
+ INSIST(HASHNEXT(bucket_node) != NULL);
+ bucket_node = HASHNEXT(bucket_node);
+ }
+ HASHNEXT(bucket_node) = HASHNEXT(node);
+ }
+ }
+}
+#endif /* DNS_RBT_USEHASH */
+
+static inline void
+rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
+ dns_rbtnode_t *child;
+
+ REQUIRE(DNS_RBTNODE_VALID(node));
+ REQUIRE(rootp != NULL);
+
+ child = RIGHT(node);
+ INSIST(child != NULL);
+
+ RIGHT(node) = LEFT(child);
+ if (LEFT(child) != NULL)
+ PARENT(LEFT(child)) = node;
+ LEFT(child) = node;
+
+ if (child != NULL)
+ PARENT(child) = PARENT(node);
+
+ if (IS_ROOT(node)) {
+ *rootp = child;
+ child->is_root = 1;
+ node->is_root = 0;
+
+ } else {
+ if (LEFT(PARENT(node)) == node)
+ LEFT(PARENT(node)) = child;
+ else
+ RIGHT(PARENT(node)) = child;
+ }
+
+ PARENT(node) = child;
+}
+
+static inline void
+rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
+ dns_rbtnode_t *child;
+
+ REQUIRE(DNS_RBTNODE_VALID(node));
+ REQUIRE(rootp != NULL);
+
+ child = LEFT(node);
+ INSIST(child != NULL);
+
+ LEFT(node) = RIGHT(child);
+ if (RIGHT(child) != NULL)
+ PARENT(RIGHT(child)) = node;
+ RIGHT(child) = node;
+
+ if (child != NULL)
+ PARENT(child) = PARENT(node);
+
+ if (IS_ROOT(node)) {
+ *rootp = child;
+ child->is_root = 1;
+ node->is_root = 0;
+
+ } else {
+ if (LEFT(PARENT(node)) == node)
+ LEFT(PARENT(node)) = child;
+ else
+ RIGHT(PARENT(node)) = child;
+ }
+
+ PARENT(node) = child;
+}
+
+/*
+ * This is the real workhorse of the insertion code, because it does the
+ * true red/black tree on a single level.
+ */
+static void
+dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
+ dns_rbtnode_t **rootp)
+{
+ dns_rbtnode_t *child, *root, *parent, *grandparent;
+ dns_name_t add_name, current_name;
+ dns_offsets_t add_offsets, current_offsets;
+
+ REQUIRE(rootp != NULL);
+ REQUIRE(DNS_RBTNODE_VALID(node) && LEFT(node) == NULL &&
+ RIGHT(node) == NULL);
+ REQUIRE(current != NULL);
+
+ root = *rootp;
+ if (root == NULL) {
+ /*
+ * First node of a level.
+ */
+ MAKE_BLACK(node);
+ node->is_root = 1;
+ PARENT(node) = current;
+ *rootp = node;
+ return;
+ }
+
+ child = root;
+
+ dns_name_init(&add_name, add_offsets);
+ NODENAME(node, &add_name);
+
+ dns_name_init(&current_name, current_offsets);
+ NODENAME(current, &current_name);
+
+ if (order < 0) {
+ INSIST(LEFT(current) == NULL);
+ LEFT(current) = node;
+ } else {
+ INSIST(RIGHT(current) == NULL);
+ RIGHT(current) = node;
+ }
+
+ INSIST(PARENT(node) == NULL);
+ PARENT(node) = current;
+
+ MAKE_RED(node);
+
+ while (node != root && IS_RED(PARENT(node))) {
+ /*
+ * XXXDCL could do away with separate parent and grandparent
+ * variables. They are vestiges of the days before parent
+ * pointers. However, they make the code a little clearer.
+ */
+
+ parent = PARENT(node);
+ grandparent = PARENT(parent);
+
+ if (parent == LEFT(grandparent)) {
+ child = RIGHT(grandparent);
+ if (child != NULL && IS_RED(child)) {
+ MAKE_BLACK(parent);
+ MAKE_BLACK(child);
+ MAKE_RED(grandparent);
+ node = grandparent;
+ } else {
+ if (node == RIGHT(parent)) {
+ rotate_left(parent, &root);
+ node = parent;
+ parent = PARENT(node);
+ grandparent = PARENT(parent);
+ }
+ MAKE_BLACK(parent);
+ MAKE_RED(grandparent);
+ rotate_right(grandparent, &root);
+ }
+ } else {
+ child = LEFT(grandparent);
+ if (child != NULL && IS_RED(child)) {
+ MAKE_BLACK(parent);
+ MAKE_BLACK(child);
+ MAKE_RED(grandparent);
+ node = grandparent;
+ } else {
+ if (node == LEFT(parent)) {
+ rotate_right(parent, &root);
+ node = parent;
+ parent = PARENT(node);
+ grandparent = PARENT(parent);
+ }
+ MAKE_BLACK(parent);
+ MAKE_RED(grandparent);
+ rotate_left(grandparent, &root);
+ }
+ }
+ }
+
+ MAKE_BLACK(root);
+ ENSURE(IS_ROOT(root));
+ *rootp = root;
+
+ return;
+}
+
+/*
+ * This is the real workhorse of the deletion code, because it does the
+ * true red/black tree on a single level.
+ */
+static void
+dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) {
+ dns_rbtnode_t *child, *sibling, *parent;
+ dns_rbtnode_t *successor;
+
+ REQUIRE(delete != NULL);
+
+ /*
+ * Verify that the parent history is (apparently) correct.
+ */
+ INSIST((IS_ROOT(delete) && *rootp == delete) ||
+ (! IS_ROOT(delete) &&
+ (LEFT(PARENT(delete)) == delete ||
+ RIGHT(PARENT(delete)) == delete)));
+
+ child = NULL;
+
+ if (LEFT(delete) == NULL) {
+ if (RIGHT(delete) == NULL) {
+ if (IS_ROOT(delete)) {
+ /*
+ * This is the only item in the tree.
+ */
+ *rootp = NULL;
+ return;
+ }
+ } else
+ /*
+ * This node has one child, on the right.
+ */
+ child = RIGHT(delete);
+
+ } else if (RIGHT(delete) == NULL)
+ /*
+ * This node has one child, on the left.
+ */
+ child = LEFT(delete);
+ else {
+ dns_rbtnode_t holder, *tmp = &holder;
+
+ /*
+ * This node has two children, so it cannot be directly
+ * deleted. Find its immediate in-order successor and
+ * move it to this location, then do the deletion at the
+ * old site of the successor.
+ */
+ successor = RIGHT(delete);
+ while (LEFT(successor) != NULL)
+ successor = LEFT(successor);
+
+ /*
+ * The successor cannot possibly have a left child;
+ * if there is any child, it is on the right.
+ */
+ if (RIGHT(successor) != NULL)
+ child = RIGHT(successor);
+
+ /*
+ * Swap the two nodes; it would be simpler to just replace
+ * the value being deleted with that of the successor,
+ * but this rigamarole is done so the caller has complete
+ * control over the pointers (and memory allocation) of
+ * all of nodes. If just the key value were removed from
+ * the tree, the pointer to the node would be unchanged.
+ */
+
+ /*
+ * First, put the successor in the tree location of the
+ * node to be deleted. Save its existing tree pointer
+ * information, which will be needed when linking up
+ * delete to the successor's old location.
+ */
+ memcpy(tmp, successor, sizeof(dns_rbtnode_t));
+
+ if (IS_ROOT(delete)) {
+ *rootp = successor;
+ successor->is_root = ISC_TRUE;
+ delete->is_root = ISC_FALSE;
+
+ } else
+ if (LEFT(PARENT(delete)) == delete)
+ LEFT(PARENT(delete)) = successor;
+ else
+ RIGHT(PARENT(delete)) = successor;
+
+ PARENT(successor) = PARENT(delete);
+ LEFT(successor) = LEFT(delete);
+ RIGHT(successor) = RIGHT(delete);
+ COLOR(successor) = COLOR(delete);
+
+ if (LEFT(successor) != NULL)
+ PARENT(LEFT(successor)) = successor;
+ if (RIGHT(successor) != successor)
+ PARENT(RIGHT(successor)) = successor;
+
+ /*
+ * Now relink the node to be deleted into the
+ * successor's previous tree location. PARENT(tmp)
+ * is the successor's original parent.
+ */
+ INSIST(! IS_ROOT(delete));
+
+ if (PARENT(tmp) == delete) {
+ /*
+ * Node being deleted was successor's parent.
+ */
+ RIGHT(successor) = delete;
+ PARENT(delete) = successor;
+
+ } else {
+ LEFT(PARENT(tmp)) = delete;
+ PARENT(delete) = PARENT(tmp);
+ }
+
+ /*
+ * Original location of successor node has no left.
+ */
+ LEFT(delete) = NULL;
+ RIGHT(delete) = RIGHT(tmp);
+ COLOR(delete) = COLOR(tmp);
+ }
+
+ /*
+ * Remove the node by removing the links from its parent.
+ */
+ if (! IS_ROOT(delete)) {
+ if (LEFT(PARENT(delete)) == delete)
+ LEFT(PARENT(delete)) = child;
+ else
+ RIGHT(PARENT(delete)) = child;
+
+ if (child != NULL)
+ PARENT(child) = PARENT(delete);
+
+ } else {
+ /*
+ * This is the root being deleted, and at this point
+ * it is known to have just one child.
+ */
+ *rootp = child;
+ child->is_root = 1;
+ PARENT(child) = PARENT(delete);
+ }
+
+ /*
+ * Fix color violations.
+ */
+ if (IS_BLACK(delete)) {
+ parent = PARENT(delete);
+
+ while (child != *rootp && IS_BLACK(child)) {
+ INSIST(child == NULL || ! IS_ROOT(child));
+
+ if (LEFT(parent) == child) {
+ sibling = RIGHT(parent);
+
+ if (IS_RED(sibling)) {
+ MAKE_BLACK(sibling);
+ MAKE_RED(parent);
+ rotate_left(parent, rootp);
+ sibling = RIGHT(parent);
+ }
+
+ if (IS_BLACK(LEFT(sibling)) &&
+ IS_BLACK(RIGHT(sibling))) {
+ MAKE_RED(sibling);
+ child = parent;
+
+ } else {
+
+ if (IS_BLACK(RIGHT(sibling))) {
+ MAKE_BLACK(LEFT(sibling));
+ MAKE_RED(sibling);
+ rotate_right(sibling, rootp);
+ sibling = RIGHT(parent);
+ }
+
+ COLOR(sibling) = COLOR(parent);
+ MAKE_BLACK(parent);
+ MAKE_BLACK(RIGHT(sibling));
+ rotate_left(parent, rootp);
+ child = *rootp;
+ }
+
+ } else {
+ /*
+ * Child is parent's right child.
+ * Everything is doen the same as above,
+ * except mirrored.
+ */
+ sibling = LEFT(parent);
+
+ if (IS_RED(sibling)) {
+ MAKE_BLACK(sibling);
+ MAKE_RED(parent);
+ rotate_right(parent, rootp);
+ sibling = LEFT(parent);
+ }
+
+ if (IS_BLACK(LEFT(sibling)) &&
+ IS_BLACK(RIGHT(sibling))) {
+ MAKE_RED(sibling);
+ child = parent;
+
+ } else {
+ if (IS_BLACK(LEFT(sibling))) {
+ MAKE_BLACK(RIGHT(sibling));
+ MAKE_RED(sibling);
+ rotate_left(sibling, rootp);
+ sibling = LEFT(parent);
+ }
+
+ COLOR(sibling) = COLOR(parent);
+ MAKE_BLACK(parent);
+ MAKE_BLACK(LEFT(sibling));
+ rotate_right(parent, rootp);
+ child = *rootp;
+ }
+ }
+
+ parent = PARENT(child);
+ }
+
+ if (IS_RED(child))
+ MAKE_BLACK(child);
+ }
+}
+
+/*
+ * This should only be used on the root of a tree, because no color fixup
+ * is done at all.
+ *
+ * NOTE: No root pointer maintenance is done, because the function is only
+ * used for two cases:
+ * + deleting everything DOWN from a node that is itself being deleted, and
+ * + deleting the entire tree of trees from dns_rbt_destroy.
+ * In each case, the root pointer is no longer relevant, so there
+ * is no need for a root parameter to this function.
+ *
+ * If the function is ever intended to be used to delete something where
+ * a pointer needs to be told that this tree no longer exists,
+ * this function would need to adjusted accordingly.
+ */
+static isc_result_t
+dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) {
+ isc_result_t result = ISC_R_SUCCESS;
+ REQUIRE(VALID_RBT(rbt));
+
+ if (node == NULL)
+ return (result);
+
+ if (LEFT(node) != NULL) {
+ result = dns_rbt_deletetree(rbt, LEFT(node));
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ LEFT(node) = NULL;
+ }
+ if (RIGHT(node) != NULL) {
+ result = dns_rbt_deletetree(rbt, RIGHT(node));
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ RIGHT(node) = NULL;
+ }
+ if (DOWN(node) != NULL) {
+ result = dns_rbt_deletetree(rbt, DOWN(node));
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ DOWN(node) = NULL;
+ }
+ done:
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (DATA(node) != NULL && rbt->data_deleter != NULL)
+ rbt->data_deleter(DATA(node), rbt->deleter_arg);
+
+ unhash_node(rbt, node);
+#if DNS_RBT_USEMAGIC
+ node->magic = 0;
+#endif
+
+ isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
+ rbt->nodecount--;
+ return (result);
+}
+
+static void
+dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
+ dns_rbtnode_t **nodep)
+{
+ dns_rbtnode_t *parent;
+ dns_rbtnode_t *node = *nodep;
+ REQUIRE(VALID_RBT(rbt));
+
+ again:
+ if (node == NULL) {
+ *nodep = NULL;
+ return;
+ }
+
+ traverse:
+ if (LEFT(node) != NULL) {
+ node = LEFT(node);
+ goto traverse;
+ }
+ if (DOWN(node) != NULL) {
+ node = DOWN(node);
+ goto traverse;
+ }
+
+ if (DATA(node) != NULL && rbt->data_deleter != NULL)
+ rbt->data_deleter(DATA(node), rbt->deleter_arg);
+
+ /*
+ * Note: we don't call unhash_node() here as we are destroying
+ * the complete rbt tree.
+ */
+#if DNS_RBT_USEMAGIC
+ node->magic = 0;
+#endif
+ parent = PARENT(node);
+ if (RIGHT(node) != NULL)
+ PARENT(RIGHT(node)) = parent;
+ if (parent != NULL) {
+ if (LEFT(parent) == node)
+ LEFT(parent) = RIGHT(node);
+ else if (DOWN(parent) == node)
+ DOWN(parent) = RIGHT(node);
+ } else
+ parent = RIGHT(node);
+
+ isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
+ rbt->nodecount--;
+ node = parent;
+ if (quantum != 0 && --quantum == 0) {
+ *nodep = node;
+ return;
+ }
+ goto again;
+}
+
+static void
+dns_rbt_indent(int depth) {
+ int i;
+
+ for (i = 0; i < depth; i++)
+ putchar('\t');
+}
+
+static void
+dns_rbt_printnodename(dns_rbtnode_t *node) {
+ isc_region_t r;
+ dns_name_t name;
+ char buffer[DNS_NAME_FORMATSIZE];
+ dns_offsets_t offsets;
+
+ r.length = NAMELEN(node);
+ r.base = NAME(node);
+
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &r);
+
+ dns_name_format(&name, buffer, sizeof(buffer));
+
+ printf("%s", buffer);
+}
+
+static void
+dns_rbt_printtree(dns_rbtnode_t *root, dns_rbtnode_t *parent, int depth) {
+ dns_rbt_indent(depth);
+
+ if (root != NULL) {
+ dns_rbt_printnodename(root);
+ printf(" (%s", IS_RED(root) ? "RED" : "black");
+ if (parent) {
+ printf(" from ");
+ dns_rbt_printnodename(parent);
+ }
+
+ if ((! IS_ROOT(root) && PARENT(root) != parent) ||
+ ( IS_ROOT(root) && depth > 0 &&
+ DOWN(PARENT(root)) != root)) {
+
+ printf(" (BAD parent pointer! -> ");
+ if (PARENT(root) != NULL)
+ dns_rbt_printnodename(PARENT(root));
+ else
+ printf("NULL");
+ printf(")");
+ }
+
+ printf(")\n");
+
+
+ depth++;
+
+ if (DOWN(root)) {
+ dns_rbt_indent(depth);
+ printf("++ BEG down from ");
+ dns_rbt_printnodename(root);
+ printf("\n");
+ dns_rbt_printtree(DOWN(root), NULL, depth);
+ dns_rbt_indent(depth);
+ printf("-- END down from ");
+ dns_rbt_printnodename(root);
+ printf("\n");
+ }
+
+ if (IS_RED(root) && IS_RED(LEFT(root)))
+ printf("** Red/Red color violation on left\n");
+ dns_rbt_printtree(LEFT(root), root, depth);
+
+ if (IS_RED(root) && IS_RED(RIGHT(root)))
+ printf("** Red/Red color violation on right\n");
+ dns_rbt_printtree(RIGHT(root), root, depth);
+
+ } else
+ printf("NULL\n");
+}
+
+void
+dns_rbt_printall(dns_rbt_t *rbt) {
+ REQUIRE(VALID_RBT(rbt));
+
+ dns_rbt_printtree(rbt->root, NULL, 0);
+}
+
+/*
+ * Chain Functions
+ */
+
+void
+dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
+ /*
+ * Initialize 'chain'.
+ */
+
+ REQUIRE(chain != NULL);
+
+ chain->mctx = mctx;
+ chain->end = NULL;
+ chain->level_count = 0;
+ chain->level_matches = 0;
+ memset(chain->levels, 0, sizeof(chain->levels));
+
+ chain->magic = CHAIN_MAGIC;
+}
+
+isc_result_t
+dns_rbtnodechain_current(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin, dns_rbtnode_t **node)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(VALID_CHAIN(chain));
+
+ if (node != NULL)
+ *node = chain->end;
+
+ if (chain->end == NULL)
+ return (ISC_R_NOTFOUND);
+
+ if (name != NULL) {
+ NODENAME(chain->end, name);
+
+ if (chain->level_count == 0) {
+ /*
+ * Names in the top level tree are all absolute.
+ * Always make 'name' relative.
+ */
+ INSIST(dns_name_isabsolute(name));
+
+ /*
+ * This is cheaper than dns_name_getlabelsequence().
+ */
+ name->labels--;
+ name->length--;
+ name->attributes &= ~DNS_NAMEATTR_ABSOLUTE;
+ }
+ }
+
+ if (origin != NULL) {
+ if (chain->level_count > 0)
+ result = chain_name(chain, origin, ISC_FALSE);
+ else
+ result = dns_name_copy(dns_rootname, origin, NULL);
+ }
+
+ return (result);
+}
+
+isc_result_t
+dns_rbtnodechain_prev(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin)
+{
+ dns_rbtnode_t *current, *previous, *predecessor;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t new_origin = ISC_FALSE;
+
+ REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
+
+ predecessor = NULL;
+
+ current = chain->end;
+
+ if (LEFT(current) != NULL) {
+ /*
+ * Moving left one then right as far as possible is the
+ * previous node, at least for this level.
+ */
+ current = LEFT(current);
+
+ while (RIGHT(current) != NULL)
+ current = RIGHT(current);
+
+ predecessor = current;
+
+ } else {
+ /*
+ * No left links, so move toward the root. If at any point on
+ * the way there the link from parent to child is a right
+ * link, then the parent is the previous node, at least
+ * for this level.
+ */
+ while (! IS_ROOT(current)) {
+ previous = current;
+ current = PARENT(current);
+
+ if (RIGHT(current) == previous) {
+ predecessor = current;
+ break;
+ }
+ }
+ }
+
+ if (predecessor != NULL) {
+ /*
+ * Found a predecessor node in this level. It might not
+ * really be the predecessor, however.
+ */
+ if (DOWN(predecessor) != NULL) {
+ /*
+ * The predecessor is really down at least one level.
+ * Go down and as far right as possible, and repeat
+ * as long as the rightmost node has a down pointer.
+ */
+ do {
+ /*
+ * XXX DCL Need to do something about origins
+ * here. See whether to go down, and if so
+ * whether it is truly what Bob calls a
+ * new origin.
+ */
+ ADD_LEVEL(chain, predecessor);
+ predecessor = DOWN(predecessor);
+
+ /* XXX DCL duplicated from above; clever
+ * way to unduplicate? */
+
+ while (RIGHT(predecessor) != NULL)
+ predecessor = RIGHT(predecessor);
+ } while (DOWN(predecessor) != NULL);
+
+ /* XXX DCL probably needs work on the concept */
+ if (origin != NULL)
+ new_origin = ISC_TRUE;
+ }
+
+ } else if (chain->level_count > 0) {
+ /*
+ * Dang, didn't find a predecessor in this level.
+ * Got to the root of this level without having traversed
+ * any right links. Ascend the tree one level; the
+ * node that points to this tree is the predecessor.
+ */
+ INSIST(chain->level_count > 0 && IS_ROOT(current));
+ predecessor = chain->levels[--chain->level_count];
+
+ /* XXX DCL probably needs work on the concept */
+ /*
+ * Don't declare an origin change when the new origin is "."
+ * at the top level tree, because "." is declared as the origin
+ * for the second level tree.
+ */
+ if (origin != NULL &&
+ (chain->level_count > 0 || OFFSETLEN(predecessor) > 1))
+ new_origin = ISC_TRUE;
+ }
+
+ if (predecessor != NULL) {
+ chain->end = predecessor;
+
+ if (new_origin) {
+ result = dns_rbtnodechain_current(chain, name, origin,
+ NULL);
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_NEWORIGIN;
+
+ } else
+ result = dns_rbtnodechain_current(chain, name, NULL,
+ NULL);
+
+ } else
+ result = ISC_R_NOMORE;
+
+ return (result);
+}
+
+isc_result_t
+dns_rbtnodechain_down(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin)
+{
+ dns_rbtnode_t *current, *successor;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t new_origin = ISC_FALSE;
+
+ REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
+
+ successor = NULL;
+
+ current = chain->end;
+
+ if (DOWN(current) != NULL) {
+ /*
+ * Don't declare an origin change when the new origin is "."
+ * at the second level tree, because "." is already declared
+ * as the origin for the top level tree.
+ */
+ if (chain->level_count > 0 ||
+ OFFSETLEN(current) > 1)
+ new_origin = ISC_TRUE;
+
+ ADD_LEVEL(chain, current);
+ current = DOWN(current);
+
+ while (LEFT(current) != NULL)
+ current = LEFT(current);
+
+ successor = current;
+ }
+
+ if (successor != NULL) {
+ chain->end = successor;
+
+ /*
+ * It is not necessary to use dns_rbtnodechain_current like
+ * the other functions because this function will never
+ * find a node in the topmost level. This is because the
+ * root level will never be more than one name, and everything
+ * in the megatree is a successor to that node, down at
+ * the second level or below.
+ */
+
+ if (name != NULL)
+ NODENAME(chain->end, name);
+
+ if (new_origin) {
+ if (origin != NULL)
+ result = chain_name(chain, origin, ISC_FALSE);
+
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_NEWORIGIN;
+
+ } else
+ result = ISC_R_SUCCESS;
+
+ } else
+ result = ISC_R_NOMORE;
+
+ return (result);
+}
+
+isc_result_t
+dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name) {
+ dns_rbtnode_t *current, *previous, *successor;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
+
+ successor = NULL;
+
+ current = chain->end;
+
+ if (RIGHT(current) == NULL) {
+ while (! IS_ROOT(current)) {
+ previous = current;
+ current = PARENT(current);
+
+ if (LEFT(current) == previous) {
+ successor = current;
+ break;
+ }
+ }
+ } else {
+ current = RIGHT(current);
+
+ while (LEFT(current) != NULL)
+ current = LEFT(current);
+
+ successor = current;
+ }
+
+ if (successor != NULL) {
+ chain->end = successor;
+
+ if (name != NULL)
+ NODENAME(chain->end, name);
+
+ result = ISC_R_SUCCESS;
+ } else
+ result = ISC_R_NOMORE;
+
+ return (result);
+}
+
+isc_result_t
+dns_rbtnodechain_next(dns_rbtnodechain_t *chain, dns_name_t *name,
+ dns_name_t *origin)
+{
+ dns_rbtnode_t *current, *previous, *successor;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t new_origin = ISC_FALSE;
+
+ REQUIRE(VALID_CHAIN(chain) && chain->end != NULL);
+
+ successor = NULL;
+
+ current = chain->end;
+
+ /*
+ * If there is a level below this node, the next node is the leftmost
+ * node of the next level.
+ */
+ if (DOWN(current) != NULL) {
+ /*
+ * Don't declare an origin change when the new origin is "."
+ * at the second level tree, because "." is already declared
+ * as the origin for the top level tree.
+ */
+ if (chain->level_count > 0 ||
+ OFFSETLEN(current) > 1)
+ new_origin = ISC_TRUE;
+
+ ADD_LEVEL(chain, current);
+ current = DOWN(current);
+
+ while (LEFT(current) != NULL)
+ current = LEFT(current);
+
+ successor = current;
+
+ } else if (RIGHT(current) == NULL) {
+ /*
+ * The successor is up, either in this level or a previous one.
+ * Head back toward the root of the tree, looking for any path
+ * that was via a left link; the successor is the node that has
+ * that left link. In the event the root of the level is
+ * reached without having traversed any left links, ascend one
+ * level and look for either a right link off the point of
+ * ascent, or search for a left link upward again, repeating
+ * ascents until either case is true.
+ */
+ do {
+ while (! IS_ROOT(current)) {
+ previous = current;
+ current = PARENT(current);
+
+ if (LEFT(current) == previous) {
+ successor = current;
+ break;
+ }
+ }
+
+ if (successor == NULL) {
+ /*
+ * Reached the root without having traversed
+ * any left pointers, so this level is done.
+ */
+ if (chain->level_count == 0)
+ break;
+
+ current = chain->levels[--chain->level_count];
+ new_origin = ISC_TRUE;
+
+ if (RIGHT(current) != NULL)
+ break;
+ }
+ } while (successor == NULL);
+ }
+
+ if (successor == NULL && RIGHT(current) != NULL) {
+ current = RIGHT(current);
+
+ while (LEFT(current) != NULL)
+ current = LEFT(current);
+
+ successor = current;
+ }
+
+ if (successor != NULL) {
+ chain->end = successor;
+
+ /*
+ * It is not necessary to use dns_rbtnodechain_current like
+ * the other functions because this function will never
+ * find a node in the topmost level. This is because the
+ * root level will never be more than one name, and everything
+ * in the megatree is a successor to that node, down at
+ * the second level or below.
+ */
+
+ if (name != NULL)
+ NODENAME(chain->end, name);
+
+ if (new_origin) {
+ if (origin != NULL)
+ result = chain_name(chain, origin, ISC_FALSE);
+
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_NEWORIGIN;
+
+ } else
+ result = ISC_R_SUCCESS;
+
+ } else
+ result = ISC_R_NOMORE;
+
+ return (result);
+}
+
+isc_result_t
+dns_rbtnodechain_first(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
+ dns_name_t *name, dns_name_t *origin)
+
+{
+ isc_result_t result;
+
+ REQUIRE(VALID_RBT(rbt));
+ REQUIRE(VALID_CHAIN(chain));
+
+ dns_rbtnodechain_reset(chain);
+
+ chain->end = rbt->root;
+
+ result = dns_rbtnodechain_current(chain, name, origin, NULL);
+
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_NEWORIGIN;
+
+ return (result);
+}
+
+isc_result_t
+dns_rbtnodechain_last(dns_rbtnodechain_t *chain, dns_rbt_t *rbt,
+ dns_name_t *name, dns_name_t *origin)
+
+{
+ isc_result_t result;
+
+ REQUIRE(VALID_RBT(rbt));
+ REQUIRE(VALID_CHAIN(chain));
+
+ dns_rbtnodechain_reset(chain);
+
+ result = move_chain_to_last(chain, rbt->root);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_rbtnodechain_current(chain, name, origin, NULL);
+
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_NEWORIGIN;
+
+ return (result);
+}
+
+
+void
+dns_rbtnodechain_reset(dns_rbtnodechain_t *chain) {
+ /*
+ * Free any dynamic storage associated with 'chain', and then
+ * reinitialize 'chain'.
+ */
+
+ REQUIRE(VALID_CHAIN(chain));
+
+ chain->end = NULL;
+ chain->level_count = 0;
+ chain->level_matches = 0;
+}
+
+void
+dns_rbtnodechain_invalidate(dns_rbtnodechain_t *chain) {
+ /*
+ * Free any dynamic storage associated with 'chain', and then
+ * invalidate 'chain'.
+ */
+
+ dns_rbtnodechain_reset(chain);
+
+ chain->magic = 0;
+}
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
new file mode 100644
index 0000000..5cdbcad
--- /dev/null
+++ b/lib/dns/rbtdb.c
@@ -0,0 +1,8435 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: rbtdb.c,v 1.270 2008/11/14 14:07:48 marka Exp $ */
+
+/*! \file */
+
+/*
+ * Principal Author: Bob Halley
+ */
+
+#include <config.h>
+
+/* #define inline */
+
+#include <isc/event.h>
+#include <isc/heap.h>
+#include <isc/mem.h>
+#include <isc/mutex.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/refcount.h>
+#include <isc/rwlock.h>
+#include <isc/serial.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/acache.h>
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/lib.h>
+#include <dns/log.h>
+#include <dns/masterdump.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
+#include <dns/rbt.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdataslab.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+#include <dns/stats.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zonekey.h>
+
+#ifdef DNS_RBTDB_VERSION64
+#include "rbtdb64.h"
+#else
+#include "rbtdb.h"
+#endif
+
+#ifdef DNS_RBTDB_VERSION64
+#define RBTDB_MAGIC ISC_MAGIC('R', 'B', 'D', '8')
+#else
+#define RBTDB_MAGIC ISC_MAGIC('R', 'B', 'D', '4')
+#endif
+
+/*%
+ * Note that "impmagic" is not the first four bytes of the struct, so
+ * ISC_MAGIC_VALID cannot be used.
+ */
+#define VALID_RBTDB(rbtdb) ((rbtdb) != NULL && \
+ (rbtdb)->common.impmagic == RBTDB_MAGIC)
+
+#ifdef DNS_RBTDB_VERSION64
+typedef isc_uint64_t rbtdb_serial_t;
+/*%
+ * Make casting easier in symbolic debuggers by using different names
+ * for the 64 bit version.
+ */
+#define dns_rbtdb_t dns_rbtdb64_t
+#define rdatasetheader_t rdatasetheader64_t
+#define rbtdb_version_t rbtdb_version64_t
+#else
+typedef isc_uint32_t rbtdb_serial_t;
+#endif
+
+typedef isc_uint32_t rbtdb_rdatatype_t;
+
+#define RBTDB_RDATATYPE_BASE(type) ((dns_rdatatype_t)((type) & 0xFFFF))
+#define RBTDB_RDATATYPE_EXT(type) ((dns_rdatatype_t)((type) >> 16))
+#define RBTDB_RDATATYPE_VALUE(b, e) ((rbtdb_rdatatype_t)((e) << 16) | (b))
+
+#define RBTDB_RDATATYPE_SIGNSEC \
+ RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec)
+#define RBTDB_RDATATYPE_SIGNSEC3 \
+ RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec3)
+#define RBTDB_RDATATYPE_SIGNS \
+ RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ns)
+#define RBTDB_RDATATYPE_SIGCNAME \
+ RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_cname)
+#define RBTDB_RDATATYPE_SIGDNAME \
+ RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dname)
+#define RBTDB_RDATATYPE_NCACHEANY \
+ RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_any)
+
+/*
+ * We use rwlock for DB lock only when ISC_RWLOCK_USEATOMIC is non 0.
+ * Using rwlock is effective with regard to lookup performance only when
+ * it is implemented in an efficient way.
+ * Otherwise, it is generally wise to stick to the simple locking since rwlock
+ * would require more memory or can even make lookups slower due to its own
+ * overhead (when it internally calls mutex locks).
+ */
+#ifdef ISC_RWLOCK_USEATOMIC
+#define DNS_RBTDB_USERWLOCK 1
+#else
+#define DNS_RBTDB_USERWLOCK 0
+#endif
+
+#if DNS_RBTDB_USERWLOCK
+#define RBTDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
+#define RBTDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
+#define RBTDB_LOCK(l, t) RWLOCK((l), (t))
+#define RBTDB_UNLOCK(l, t) RWUNLOCK((l), (t))
+#else
+#define RBTDB_INITLOCK(l) isc_mutex_init(l)
+#define RBTDB_DESTROYLOCK(l) DESTROYLOCK(l)
+#define RBTDB_LOCK(l, t) LOCK(l)
+#define RBTDB_UNLOCK(l, t) UNLOCK(l)
+#endif
+
+/*
+ * Since node locking is sensitive to both performance and memory footprint,
+ * we need some trick here. If we have both high-performance rwlock and
+ * high performance and small-memory reference counters, we use rwlock for
+ * node lock and isc_refcount for node references. In this case, we don't have
+ * to protect the access to the counters by locks.
+ * Otherwise, we simply use ordinary mutex lock for node locking, and use
+ * simple integers as reference counters which is protected by the lock.
+ * In most cases, we can simply use wrapper macros such as NODE_LOCK and
+ * NODE_UNLOCK. In some other cases, however, we need to protect reference
+ * counters first and then protect other parts of a node as read-only data.
+ * Special additional macros, NODE_STRONGLOCK(), NODE_WEAKLOCK(), etc, are also
+ * provided for these special cases. When we can use the efficient backend
+ * routines, we should only protect the "other members" by NODE_WEAKLOCK(read).
+ * Otherwise, we should use NODE_STRONGLOCK() to protect the entire critical
+ * section including the access to the reference counter.
+ * Note that we cannot use NODE_LOCK()/NODE_UNLOCK() wherever the protected
+ * section is also protected by NODE_STRONGLOCK().
+ */
+#if defined(ISC_RWLOCK_USEATOMIC) && defined(DNS_RBT_USEISCREFCOUNT)
+typedef isc_rwlock_t nodelock_t;
+
+#define NODE_INITLOCK(l) isc_rwlock_init((l), 0, 0)
+#define NODE_DESTROYLOCK(l) isc_rwlock_destroy(l)
+#define NODE_LOCK(l, t) RWLOCK((l), (t))
+#define NODE_UNLOCK(l, t) RWUNLOCK((l), (t))
+#define NODE_TRYUPGRADE(l) isc_rwlock_tryupgrade(l)
+
+#define NODE_STRONGLOCK(l) ((void)0)
+#define NODE_STRONGUNLOCK(l) ((void)0)
+#define NODE_WEAKLOCK(l, t) NODE_LOCK(l, t)
+#define NODE_WEAKUNLOCK(l, t) NODE_UNLOCK(l, t)
+#define NODE_WEAKDOWNGRADE(l) isc_rwlock_downgrade(l)
+#else
+typedef isc_mutex_t nodelock_t;
+
+#define NODE_INITLOCK(l) isc_mutex_init(l)
+#define NODE_DESTROYLOCK(l) DESTROYLOCK(l)
+#define NODE_LOCK(l, t) LOCK(l)
+#define NODE_UNLOCK(l, t) UNLOCK(l)
+#define NODE_TRYUPGRADE(l) ISC_R_SUCCESS
+
+#define NODE_STRONGLOCK(l) LOCK(l)
+#define NODE_STRONGUNLOCK(l) UNLOCK(l)
+#define NODE_WEAKLOCK(l, t) ((void)0)
+#define NODE_WEAKUNLOCK(l, t) ((void)0)
+#define NODE_WEAKDOWNGRADE(l) ((void)0)
+#endif
+
+/*
+ * Allow clients with a virtual time of up to 5 minutes in the past to see
+ * records that would have otherwise have expired.
+ */
+#define RBTDB_VIRTUAL 300
+
+struct noqname {
+ dns_name_t name;
+ void * neg;
+ void * negsig;
+ dns_rdatatype_t type;
+};
+
+typedef struct acachectl acachectl_t;
+
+typedef struct rdatasetheader {
+ /*%
+ * Locked by the owning node's lock.
+ */
+ rbtdb_serial_t serial;
+ dns_ttl_t rdh_ttl;
+ rbtdb_rdatatype_t type;
+ isc_uint16_t attributes;
+ dns_trust_t trust;
+ struct noqname *noqname;
+ struct noqname *closest;
+ /*%<
+ * We don't use the LIST macros, because the LIST structure has
+ * both head and tail pointers, and is doubly linked.
+ */
+
+ struct rdatasetheader *next;
+ /*%<
+ * If this is the top header for an rdataset, 'next' points
+ * to the top header for the next rdataset (i.e., the next type).
+ * Otherwise, it points up to the header whose down pointer points
+ * at this header.
+ */
+
+ struct rdatasetheader *down;
+ /*%<
+ * Points to the header for the next older version of
+ * this rdataset.
+ */
+
+ isc_uint32_t count;
+ /*%<
+ * Monotonously increased every time this rdataset is bound so that
+ * it is used as the base of the starting point in DNS responses
+ * when the "cyclic" rrset-order is required. Since the ordering
+ * should not be so crucial, no lock is set for the counter for
+ * performance reasons.
+ */
+
+ acachectl_t *additional_auth;
+ acachectl_t *additional_glue;
+
+ dns_rbtnode_t *node;
+ isc_stdtime_t last_used;
+ ISC_LINK(struct rdatasetheader) lru_link;
+ /*%<
+ * Used for LRU-based cache management. We should probably make
+ * these cache-DB specific. We might also make it a pointer and
+ * ensure only the top header has a valid link to save memory.
+ * The linked-list is locked by the rbtdb->lrulock.
+ */
+
+ /*
+ * It's possible this should not be here anymore, but instead
+ * referenced from the bucket's heap directly.
+ */
+#if 0
+ isc_heap_t *heap;
+#endif
+ unsigned int heap_index;
+ /*%<
+ * Used for TTL-based cache cleaning.
+ */
+ isc_stdtime_t resign;
+} rdatasetheader_t;
+
+typedef ISC_LIST(rdatasetheader_t) rdatasetheaderlist_t;
+typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
+
+#define RDATASET_ATTR_NONEXISTENT 0x0001
+#define RDATASET_ATTR_STALE 0x0002
+#define RDATASET_ATTR_IGNORE 0x0004
+#define RDATASET_ATTR_RETAIN 0x0008
+#define RDATASET_ATTR_NXDOMAIN 0x0010
+#define RDATASET_ATTR_RESIGN 0x0020
+#define RDATASET_ATTR_STATCOUNT 0x0040
+#define RDATASET_ATTR_OPTOUT 0x0080
+
+typedef struct acache_cbarg {
+ dns_rdatasetadditional_t type;
+ unsigned int count;
+ dns_db_t *db;
+ dns_dbnode_t *node;
+ rdatasetheader_t *header;
+} acache_cbarg_t;
+
+struct acachectl {
+ dns_acacheentry_t *entry;
+ acache_cbarg_t *cbarg;
+};
+
+/*
+ * XXX
+ * When the cache will pre-expire data (due to memory low or other
+ * situations) before the rdataset's TTL has expired, it MUST
+ * respect the RETAIN bit and not expire the data until its TTL is
+ * expired.
+ */
+
+#undef IGNORE /* WIN32 winbase.h defines this. */
+
+#define EXISTS(header) \
+ (((header)->attributes & RDATASET_ATTR_NONEXISTENT) == 0)
+#define NONEXISTENT(header) \
+ (((header)->attributes & RDATASET_ATTR_NONEXISTENT) != 0)
+#define IGNORE(header) \
+ (((header)->attributes & RDATASET_ATTR_IGNORE) != 0)
+#define RETAIN(header) \
+ (((header)->attributes & RDATASET_ATTR_RETAIN) != 0)
+#define NXDOMAIN(header) \
+ (((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
+#define RESIGN(header) \
+ (((header)->attributes & RDATASET_ATTR_RESIGN) != 0)
+#define OPTOUT(header) \
+ (((header)->attributes & RDATASET_ATTR_OPTOUT) != 0)
+
+#define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */
+
+/*%
+ * Number of buckets for cache DB entries (locks, LRU lists, TTL heaps).
+ * There is a tradeoff issue about configuring this value: if this is too
+ * small, it may cause heavier contention between threads; if this is too large,
+ * LRU purge algorithm won't work well (entries tend to be purged prematurely).
+ * The default value should work well for most environments, but this can
+ * also be configurable at compilation time via the
+ * DNS_RBTDB_CACHE_NODE_LOCK_COUNT variable. This value must be larger than
+ * 1 due to the assumption of overmem_purge().
+ */
+#ifdef DNS_RBTDB_CACHE_NODE_LOCK_COUNT
+#if DNS_RBTDB_CACHE_NODE_LOCK_COUNT <= 1
+#error "DNS_RBTDB_CACHE_NODE_LOCK_COUNT must be larger 1"
+#else
+#define DEFAULT_CACHE_NODE_LOCK_COUNT DNS_RBTDB_CACHE_NODE_LOCK_COUNT
+#endif
+#else
+#define DEFAULT_CACHE_NODE_LOCK_COUNT 16
+#endif /* DNS_RBTDB_CACHE_NODE_LOCK_COUNT */
+
+typedef struct {
+ nodelock_t lock;
+ /* Protected in the refcount routines. */
+ isc_refcount_t references;
+ /* Locked by lock. */
+ isc_boolean_t exiting;
+} rbtdb_nodelock_t;
+
+typedef struct rbtdb_changed {
+ dns_rbtnode_t * node;
+ isc_boolean_t dirty;
+ ISC_LINK(struct rbtdb_changed) link;
+} rbtdb_changed_t;
+
+typedef ISC_LIST(rbtdb_changed_t) rbtdb_changedlist_t;
+
+typedef enum {
+ dns_db_insecure,
+ dns_db_partial,
+ dns_db_secure
+} dns_db_secure_t;
+
+typedef struct rbtdb_version {
+ /* Not locked */
+ rbtdb_serial_t serial;
+ /*
+ * Protected in the refcount routines.
+ * XXXJT: should we change the lock policy based on the refcount
+ * performance?
+ */
+ isc_refcount_t references;
+ /* Locked by database lock. */
+ isc_boolean_t writer;
+ isc_boolean_t commit_ok;
+ rbtdb_changedlist_t changed_list;
+ rdatasetheaderlist_t resigned_list;
+ ISC_LINK(struct rbtdb_version) link;
+ dns_db_secure_t secure;
+ isc_boolean_t havensec3;
+ /* NSEC3 parameters */
+ dns_hash_t hash;
+ isc_uint8_t flags;
+ isc_uint16_t iterations;
+ isc_uint8_t salt_length;
+ unsigned char salt[NSEC3_MAX_HASH_LENGTH];
+} rbtdb_version_t;
+
+typedef ISC_LIST(rbtdb_version_t) rbtdb_versionlist_t;
+
+typedef struct {
+ /* Unlocked. */
+ dns_db_t common;
+#if DNS_RBTDB_USERWLOCK
+ isc_rwlock_t lock;
+#else
+ isc_mutex_t lock;
+#endif
+ isc_rwlock_t tree_lock;
+ unsigned int node_lock_count;
+ rbtdb_nodelock_t * node_locks;
+ dns_rbtnode_t * origin_node;
+ dns_stats_t * rrsetstats; /* cache DB only */
+ /* Locked by lock. */
+ unsigned int active;
+ isc_refcount_t references;
+ unsigned int attributes;
+ rbtdb_serial_t current_serial;
+ rbtdb_serial_t least_serial;
+ rbtdb_serial_t next_serial;
+ rbtdb_version_t * current_version;
+ rbtdb_version_t * future_version;
+ rbtdb_versionlist_t open_versions;
+ isc_boolean_t overmem;
+ isc_task_t * task;
+ dns_dbnode_t *soanode;
+ dns_dbnode_t *nsnode;
+
+ /*
+ * This is a linked list used to implement the LRU cache. There will
+ * be node_lock_count linked lists here. Nodes in bucket 1 will be
+ * placed on the linked list rdatasets[1].
+ */
+ rdatasetheaderlist_t *rdatasets;
+
+ /*%
+ * Temporary storage for stale cache nodes and dynamically deleted
+ * nodes that await being cleaned up.
+ */
+ rbtnodelist_t *deadnodes;
+
+ /*
+ * Heaps. Each of these is used for TTL based expiry.
+ */
+ isc_heap_t **heaps;
+
+ /* Locked by tree_lock. */
+ dns_rbt_t * tree;
+ dns_rbt_t * nsec3;
+
+ /* Unlocked */
+ unsigned int quantum;
+} dns_rbtdb_t;
+
+#define RBTDB_ATTR_LOADED 0x01
+#define RBTDB_ATTR_LOADING 0x02
+
+/*%
+ * Search Context
+ */
+typedef struct {
+ dns_rbtdb_t * rbtdb;
+ rbtdb_version_t * rbtversion;
+ rbtdb_serial_t serial;
+ unsigned int options;
+ dns_rbtnodechain_t chain;
+ isc_boolean_t copy_name;
+ isc_boolean_t need_cleanup;
+ isc_boolean_t wild;
+ dns_rbtnode_t * zonecut;
+ rdatasetheader_t * zonecut_rdataset;
+ rdatasetheader_t * zonecut_sigrdataset;
+ dns_fixedname_t zonecut_name;
+ isc_stdtime_t now;
+} rbtdb_search_t;
+
+/*%
+ * Load Context
+ */
+typedef struct {
+ dns_rbtdb_t * rbtdb;
+ isc_stdtime_t now;
+} rbtdb_load_t;
+
+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 isc_result_t rdataset_getnoqname(dns_rdataset_t *rdataset,
+ dns_name_t *name,
+ dns_rdataset_t *neg,
+ dns_rdataset_t *negsig);
+static isc_result_t rdataset_getclosest(dns_rdataset_t *rdataset,
+ dns_name_t *name,
+ dns_rdataset_t *neg,
+ dns_rdataset_t *negsig);
+static isc_result_t rdataset_getadditional(dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype,
+ dns_acache_t *acache,
+ dns_zone_t **zonep,
+ dns_db_t **dbp,
+ dns_dbversion_t **versionp,
+ dns_dbnode_t **nodep,
+ dns_name_t *fname,
+ dns_message_t *msg,
+ isc_stdtime_t now);
+static isc_result_t rdataset_setadditional(dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype,
+ dns_acache_t *acache,
+ dns_zone_t *zone,
+ dns_db_t *db,
+ dns_dbversion_t *version,
+ dns_dbnode_t *node,
+ dns_name_t *fname);
+static isc_result_t rdataset_putadditional(dns_acache_t *acache,
+ dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype);
+static inline isc_boolean_t need_headerupdate(rdatasetheader_t *header,
+ isc_stdtime_t now);
+static void update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+ isc_stdtime_t now);
+static void expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+ isc_boolean_t tree_locked);
+static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
+ isc_stdtime_t now, isc_boolean_t tree_locked);
+static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx,
+ rdatasetheader_t *newheader);
+
+static dns_rdatasetmethods_t rdataset_methods = {
+ rdataset_disassociate,
+ rdataset_first,
+ rdataset_next,
+ rdataset_current,
+ rdataset_clone,
+ rdataset_count,
+ NULL,
+ rdataset_getnoqname,
+ NULL,
+ rdataset_getclosest,
+ rdataset_getadditional,
+ rdataset_setadditional,
+ rdataset_putadditional
+};
+
+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
+};
+
+typedef struct rbtdb_rdatasetiter {
+ dns_rdatasetiter_t common;
+ rdatasetheader_t * current;
+} rbtdb_rdatasetiter_t;
+
+static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
+static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
+ dns_name_t *name);
+static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
+ dns_dbnode_t **nodep,
+ dns_name_t *name);
+static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
+ dns_name_t *name);
+
+static dns_dbiteratormethods_t dbiterator_methods = {
+ dbiterator_destroy,
+ dbiterator_first,
+ dbiterator_last,
+ dbiterator_seek,
+ dbiterator_prev,
+ dbiterator_next,
+ dbiterator_current,
+ dbiterator_pause,
+ dbiterator_origin
+};
+
+#define DELETION_BATCH_MAX 64
+
+/*
+ * If 'paused' is ISC_TRUE, then the tree lock is not being held.
+ */
+typedef struct rbtdb_dbiterator {
+ dns_dbiterator_t common;
+ isc_boolean_t paused;
+ isc_boolean_t new_origin;
+ isc_rwlocktype_t tree_locked;
+ isc_result_t result;
+ dns_fixedname_t name;
+ dns_fixedname_t origin;
+ dns_rbtnodechain_t chain;
+ dns_rbtnodechain_t nsec3chain;
+ dns_rbtnodechain_t *current;
+ dns_rbtnode_t *node;
+ dns_rbtnode_t *deletions[DELETION_BATCH_MAX];
+ int delete;
+ isc_boolean_t nsec3only;
+ isc_boolean_t nonsec3;
+} rbtdb_dbiterator_t;
+
+
+#define IS_STUB(rbtdb) (((rbtdb)->common.attributes & DNS_DBATTR_STUB) != 0)
+#define IS_CACHE(rbtdb) (((rbtdb)->common.attributes & DNS_DBATTR_CACHE) != 0)
+
+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);
+
+/*%
+ * 'init_count' is used to initialize 'newheader->count' which inturn
+ * is used to determine where in the cycle rrset-order cyclic starts.
+ * We don't lock this as we don't care about simultanious updates.
+ *
+ * Note:
+ * Both init_count and header->count can be ISC_UINT32_MAX.
+ * The count on the returned rdataset however can't be as
+ * that indicates that the database does not implement cyclic
+ * processing.
+ */
+static unsigned int init_count;
+
+/*
+ * Locking
+ *
+ * If a routine is going to lock more than one lock in this module, then
+ * the locking must be done in the following order:
+ *
+ * Tree Lock
+ *
+ * Node Lock (Only one from the set may be locked at one time by
+ * any caller)
+ *
+ * Database Lock
+ *
+ * Failure to follow this hierarchy can result in deadlock.
+ */
+
+/*
+ * Deleting Nodes
+ *
+ * For zone databases the node for the origin of the zone MUST NOT be deleted.
+ */
+
+
+/*
+ * DB Routines
+ */
+
+static void
+attach(dns_db_t *source, dns_db_t **targetp) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)source;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ isc_refcount_increment(&rbtdb->references, NULL);
+
+ *targetp = source;
+}
+
+static void
+free_rbtdb_callback(isc_task_t *task, isc_event_t *event) {
+ dns_rbtdb_t *rbtdb = event->ev_arg;
+
+ UNUSED(task);
+
+ free_rbtdb(rbtdb, ISC_TRUE, event);
+}
+
+static void
+update_rrsetstats(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+ isc_boolean_t increment)
+{
+ dns_rdatastatstype_t statattributes = 0;
+ dns_rdatastatstype_t base = 0;
+ dns_rdatastatstype_t type;
+
+ /* At the moment we count statistics only for cache DB */
+ INSIST(IS_CACHE(rbtdb));
+
+ if (NXDOMAIN(header))
+ statattributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN;
+ else if (RBTDB_RDATATYPE_BASE(header->type) == 0) {
+ statattributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET;
+ base = RBTDB_RDATATYPE_EXT(header->type);
+ } else
+ base = RBTDB_RDATATYPE_BASE(header->type);
+
+ type = DNS_RDATASTATSTYPE_VALUE(base, statattributes);
+ if (increment)
+ dns_rdatasetstats_increment(rbtdb->rrsetstats, type);
+ else
+ dns_rdatasetstats_decrement(rbtdb->rrsetstats, type);
+}
+
+static void
+set_ttl(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, dns_ttl_t newttl) {
+ int idx;
+ isc_heap_t *heap;
+ dns_ttl_t oldttl;
+
+ oldttl = header->rdh_ttl;
+ header->rdh_ttl = newttl;
+
+ if (!IS_CACHE(rbtdb))
+ return;
+
+ /*
+ * It's possible the rbtdb is not a cache. If this is the case,
+ * we will not have a heap, and we move on. If we do, though,
+ * we might need to adjust things.
+ */
+ if (header->heap_index == 0 || newttl == oldttl)
+ return;
+ idx = header->node->locknum;
+ if (rbtdb->heaps == NULL || rbtdb->heaps[idx] == NULL)
+ return;
+ heap = rbtdb->heaps[idx];
+
+ if (newttl < oldttl)
+ isc_heap_increased(heap, header->heap_index);
+ else
+ isc_heap_decreased(heap, header->heap_index);
+}
+
+/*%
+ * These functions allow the heap code to rank the priority of each
+ * element. It returns ISC_TRUE if v1 happens "sooner" than v2.
+ */
+static isc_boolean_t
+ttl_sooner(void *v1, void *v2) {
+ rdatasetheader_t *h1 = v1;
+ rdatasetheader_t *h2 = v2;
+
+ if (h1->rdh_ttl < h2->rdh_ttl)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+static isc_boolean_t
+resign_sooner(void *v1, void *v2) {
+ rdatasetheader_t *h1 = v1;
+ rdatasetheader_t *h2 = v2;
+
+ if (h1->resign < h2->resign)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+/*%
+ * This function sets the heap index into the header.
+ */
+static void
+set_index(void *what, unsigned int index) {
+ rdatasetheader_t *h = what;
+
+ h->heap_index = index;
+}
+
+/*%
+ * Work out how many nodes can be deleted in the time between two
+ * requests to the nameserver. Smooth the resulting number and use it
+ * as a estimate for the number of nodes to be deleted in the next
+ * iteration.
+ */
+static unsigned int
+adjust_quantum(unsigned int old, isc_time_t *start) {
+ unsigned int pps = dns_pps; /* packets per second */
+ unsigned int interval;
+ isc_uint64_t usecs;
+ isc_time_t end;
+ unsigned int new;
+
+ if (pps < 100)
+ pps = 100;
+ isc_time_now(&end);
+
+ interval = 1000000 / pps; /* interval in usec */
+ if (interval == 0)
+ interval = 1;
+ usecs = isc_time_microdiff(&end, start);
+ if (usecs == 0) {
+ /*
+ * We were unable to measure the amount of time taken.
+ * Double the nodes deleted next time.
+ */
+ old *= 2;
+ if (old > 1000)
+ old = 1000;
+ return (old);
+ }
+ new = old * interval;
+ new /= (unsigned int)usecs;
+ if (new == 0)
+ new = 1;
+ else if (new > 1000)
+ new = 1000;
+
+ /* Smooth */
+ new = (new + old * 3) / 4;
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
+ ISC_LOG_DEBUG(1), "adjust_quantum -> %d", new);
+
+ return (new);
+}
+
+static void
+free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
+ unsigned int i;
+ isc_ondestroy_t ondest;
+ isc_result_t result;
+ char buf[DNS_NAME_FORMATSIZE];
+ isc_time_t start;
+
+ if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
+ overmem((dns_db_t *)rbtdb, (isc_boolean_t)-1);
+
+ REQUIRE(rbtdb->current_version != NULL || EMPTY(rbtdb->open_versions));
+ REQUIRE(rbtdb->future_version == NULL);
+
+ if (rbtdb->current_version != NULL) {
+ unsigned int refs;
+
+ isc_refcount_decrement(&rbtdb->current_version->references,
+ &refs);
+ INSIST(refs == 0);
+ UNLINK(rbtdb->open_versions, rbtdb->current_version, link);
+ isc_refcount_destroy(&rbtdb->current_version->references);
+ isc_mem_put(rbtdb->common.mctx, rbtdb->current_version,
+ sizeof(rbtdb_version_t));
+ }
+
+ /*
+ * We assume the number of remaining dead nodes is reasonably small;
+ * the overhead of unlinking all nodes here should be negligible.
+ */
+ for (i = 0; i < rbtdb->node_lock_count; i++) {
+ dns_rbtnode_t *node;
+
+ node = ISC_LIST_HEAD(rbtdb->deadnodes[i]);
+ while (node != NULL) {
+ ISC_LIST_UNLINK(rbtdb->deadnodes[i], node, deadlink);
+ node = ISC_LIST_HEAD(rbtdb->deadnodes[i]);
+ }
+ }
+
+ 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;
+ }
+ INSIST(result == ISC_R_SUCCESS && rbtdb->tree == NULL);
+ }
+
+ if (rbtdb->nsec3 != NULL) {
+ isc_time_now(&start);
+ result = dns_rbt_destroy2(&rbtdb->nsec3, 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;
+ }
+ INSIST(result == ISC_R_SUCCESS && rbtdb->nsec3 == NULL);
+ }
+
+ if (event != NULL)
+ isc_event_free(&event);
+ if (log) {
+ if (dns_name_dynamic(&rbtdb->common.origin))
+ dns_name_format(&rbtdb->common.origin, buf,
+ sizeof(buf));
+ else
+ strcpy(buf, "<UNKNOWN>");
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
+ "done free_rbtdb(%s)", buf);
+ }
+ if (dns_name_dynamic(&rbtdb->common.origin))
+ dns_name_free(&rbtdb->common.origin, rbtdb->common.mctx);
+ for (i = 0; i < rbtdb->node_lock_count; i++) {
+ isc_refcount_destroy(&rbtdb->node_locks[i].references);
+ NODE_DESTROYLOCK(&rbtdb->node_locks[i].lock);
+ }
+
+ /*
+ * Clean up LRU / re-signing order lists.
+ */
+ if (rbtdb->rdatasets != NULL) {
+ for (i = 0; i < rbtdb->node_lock_count; i++)
+ INSIST(ISC_LIST_EMPTY(rbtdb->rdatasets[i]));
+ isc_mem_put(rbtdb->common.mctx, rbtdb->rdatasets,
+ rbtdb->node_lock_count *
+ sizeof(rdatasetheaderlist_t));
+ }
+ /*
+ * Clean up dead node buckets.
+ */
+ if (rbtdb->deadnodes != NULL) {
+ for (i = 0; i < rbtdb->node_lock_count; i++)
+ INSIST(ISC_LIST_EMPTY(rbtdb->deadnodes[i]));
+ isc_mem_put(rbtdb->common.mctx, rbtdb->deadnodes,
+ rbtdb->node_lock_count * sizeof(rbtnodelist_t));
+ }
+ /*
+ * Clean up heap objects.
+ */
+ if (rbtdb->heaps != NULL) {
+ for (i = 0; i < rbtdb->node_lock_count; i++)
+ isc_heap_destroy(&rbtdb->heaps[i]);
+ isc_mem_put(rbtdb->common.mctx, rbtdb->heaps,
+ rbtdb->node_lock_count *
+ sizeof(isc_heap_t *));
+ }
+
+ if (rbtdb->rrsetstats != NULL)
+ dns_stats_detach(&rbtdb->rrsetstats);
+
+ isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks,
+ rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t));
+ isc_rwlock_destroy(&rbtdb->tree_lock);
+ isc_refcount_destroy(&rbtdb->references);
+ if (rbtdb->task != NULL)
+ isc_task_detach(&rbtdb->task);
+
+ RBTDB_DESTROYLOCK(&rbtdb->lock);
+ rbtdb->common.magic = 0;
+ rbtdb->common.impmagic = 0;
+ ondest = rbtdb->common.ondest;
+ isc_mem_putanddetach(&rbtdb->common.mctx, rbtdb, sizeof(*rbtdb));
+ isc_ondestroy_notify(&ondest, rbtdb);
+}
+
+static inline void
+maybe_free_rbtdb(dns_rbtdb_t *rbtdb) {
+ isc_boolean_t want_free = ISC_FALSE;
+ unsigned int i;
+ unsigned int inactive = 0;
+
+ /* XXX check for open versions here */
+
+ if (rbtdb->soanode != NULL)
+ dns_db_detachnode((dns_db_t *)rbtdb, &rbtdb->soanode);
+ if (rbtdb->nsnode != NULL)
+ dns_db_detachnode((dns_db_t *)rbtdb, &rbtdb->nsnode);
+
+ /*
+ * Even though there are no external direct references, there still
+ * may be nodes in use.
+ */
+ for (i = 0; i < rbtdb->node_lock_count; i++) {
+ NODE_LOCK(&rbtdb->node_locks[i].lock, isc_rwlocktype_write);
+ rbtdb->node_locks[i].exiting = ISC_TRUE;
+ NODE_UNLOCK(&rbtdb->node_locks[i].lock, isc_rwlocktype_write);
+ if (isc_refcount_current(&rbtdb->node_locks[i].references)
+ == 0) {
+ inactive++;
+ }
+ }
+
+ if (inactive != 0) {
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
+ rbtdb->active -= inactive;
+ if (rbtdb->active == 0)
+ want_free = ISC_TRUE;
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
+ if (want_free) {
+ char buf[DNS_NAME_FORMATSIZE];
+ if (dns_name_dynamic(&rbtdb->common.origin))
+ dns_name_format(&rbtdb->common.origin, buf,
+ sizeof(buf));
+ else
+ strcpy(buf, "<UNKNOWN>");
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
+ "calling free_rbtdb(%s)", buf);
+ free_rbtdb(rbtdb, ISC_TRUE, NULL);
+ }
+ }
+}
+
+static void
+detach(dns_db_t **dbp) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)(*dbp);
+ unsigned int refs;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ isc_refcount_decrement(&rbtdb->references, &refs);
+
+ if (refs == 0)
+ maybe_free_rbtdb(rbtdb);
+
+ *dbp = NULL;
+}
+
+static void
+currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ rbtdb_version_t *version;
+ unsigned int refs;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
+ version = rbtdb->current_version;
+ isc_refcount_increment(&version->references, &refs);
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
+
+ *versionp = (dns_dbversion_t *)version;
+}
+
+static inline rbtdb_version_t *
+allocate_version(isc_mem_t *mctx, rbtdb_serial_t serial,
+ unsigned int references, isc_boolean_t writer)
+{
+ isc_result_t result;
+ rbtdb_version_t *version;
+
+ version = isc_mem_get(mctx, sizeof(*version));
+ if (version == NULL)
+ return (NULL);
+ version->serial = serial;
+ result = isc_refcount_init(&version->references, references);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, version, sizeof(*version));
+ return (NULL);
+ }
+ version->writer = writer;
+ version->commit_ok = ISC_FALSE;
+ ISC_LIST_INIT(version->changed_list);
+ ISC_LIST_INIT(version->resigned_list);
+ ISC_LINK_INIT(version, link);
+
+ return (version);
+}
+
+static isc_result_t
+newversion(dns_db_t *db, dns_dbversion_t **versionp) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ rbtdb_version_t *version;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(versionp != NULL && *versionp == NULL);
+ REQUIRE(rbtdb->future_version == NULL);
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
+ RUNTIME_CHECK(rbtdb->next_serial != 0); /* XXX Error? */
+ version = allocate_version(rbtdb->common.mctx, rbtdb->next_serial, 1,
+ ISC_TRUE);
+ if (version != NULL) {
+ version->commit_ok = ISC_TRUE;
+ version->secure = rbtdb->current_version->secure;
+ version->havensec3 = rbtdb->current_version->havensec3;
+ if (version->havensec3) {
+ version->flags = rbtdb->current_version->flags;
+ version->iterations =
+ rbtdb->current_version->iterations;
+ version->hash = rbtdb->current_version->hash;
+ version->salt_length =
+ rbtdb->current_version->salt_length;
+ memcpy(version->salt, rbtdb->current_version->salt,
+ version->salt_length);
+ } else {
+ version->flags = 0;
+ version->iterations = 0;
+ version->hash = 0;
+ version->salt_length = 0;
+ memset(version->salt, 0, sizeof(version->salt));
+ }
+ rbtdb->next_serial++;
+ rbtdb->future_version = version;
+ }
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
+
+ if (version == NULL)
+ return (ISC_R_NOMEMORY);
+
+ *versionp = version;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+attachversion(dns_db_t *db, dns_dbversion_t *source,
+ dns_dbversion_t **targetp)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ rbtdb_version_t *rbtversion = source;
+ unsigned int refs;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ isc_refcount_increment(&rbtversion->references, &refs);
+ INSIST(refs > 1);
+
+ *targetp = rbtversion;
+}
+
+static rbtdb_changed_t *
+add_changed(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,
+ dns_rbtnode_t *node)
+{
+ rbtdb_changed_t *changed;
+ unsigned int refs;
+
+ /*
+ * Caller must be holding the node lock if its reference must be
+ * protected by the lock.
+ */
+
+ changed = isc_mem_get(rbtdb->common.mctx, sizeof(*changed));
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
+
+ REQUIRE(version->writer);
+
+ if (changed != NULL) {
+ dns_rbtnode_refincrement(node, &refs);
+ INSIST(refs != 0);
+ changed->node = node;
+ changed->dirty = ISC_FALSE;
+ ISC_LIST_INITANDAPPEND(version->changed_list, changed, link);
+ } else
+ version->commit_ok = ISC_FALSE;
+
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
+
+ return (changed);
+}
+
+static void
+free_acachearray(isc_mem_t *mctx, rdatasetheader_t *header,
+ acachectl_t *array)
+{
+ unsigned int count;
+ unsigned int i;
+ unsigned char *raw; /* RDATASLAB */
+
+ /*
+ * The caller must be holding the corresponding node lock.
+ */
+
+ if (array == NULL)
+ return;
+
+ raw = (unsigned char *)header + sizeof(*header);
+ count = raw[0] * 256 + raw[1];
+
+ /*
+ * Sanity check: since an additional cache entry has a reference to
+ * the original DB node (in the callback arg), there should be no
+ * acache entries when the node can be freed.
+ */
+ for (i = 0; i < count; i++)
+ INSIST(array[i].entry == NULL && array[i].cbarg == NULL);
+
+ isc_mem_put(mctx, array, count * sizeof(acachectl_t));
+}
+
+static inline void
+free_noqname(isc_mem_t *mctx, struct noqname **noqname) {
+
+ if (dns_name_dynamic(&(*noqname)->name))
+ dns_name_free(&(*noqname)->name, mctx);
+ if ((*noqname)->neg != NULL)
+ isc_mem_put(mctx, (*noqname)->neg,
+ dns_rdataslab_size((*noqname)->neg, 0));
+ if ((*noqname)->negsig != NULL)
+ isc_mem_put(mctx, (*noqname)->negsig,
+ dns_rdataslab_size((*noqname)->negsig, 0));
+ isc_mem_put(mctx, *noqname, sizeof(**noqname));
+ *noqname = NULL;
+}
+
+static inline void
+init_rdataset(dns_rbtdb_t *rbtdb, rdatasetheader_t *h)
+{
+ ISC_LINK_INIT(h, lru_link);
+ h->heap_index = 0;
+
+#if TRACE_HEADER
+ if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
+ fprintf(stderr, "initialized header: %p\n", h);
+#else
+ UNUSED(rbtdb);
+#endif
+}
+
+static inline rdatasetheader_t *
+new_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx)
+{
+ rdatasetheader_t *h;
+
+ h = isc_mem_get(mctx, sizeof(*h));
+ if (h == NULL)
+ return (NULL);
+
+#if TRACE_HEADER
+ if (IS_CACHE(rbtdb) && rbtdb->common.rdclass == dns_rdataclass_in)
+ fprintf(stderr, "allocated header: %p\n", h);
+#endif
+ init_rdataset(rbtdb, h);
+ return (h);
+}
+
+static inline void
+free_rdataset(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *rdataset)
+{
+ unsigned int size;
+ int idx;
+
+ if (EXISTS(rdataset) &&
+ (rdataset->attributes & RDATASET_ATTR_STATCOUNT) != 0) {
+ update_rrsetstats(rbtdb, rdataset, ISC_FALSE);
+ }
+
+ idx = rdataset->node->locknum;
+ if (ISC_LINK_LINKED(rdataset, lru_link))
+ ISC_LIST_UNLINK(rbtdb->rdatasets[idx], rdataset, lru_link);
+ if (rdataset->heap_index != 0)
+ isc_heap_delete(rbtdb->heaps[idx], rdataset->heap_index);
+ rdataset->heap_index = 0;
+
+ if (rdataset->noqname != NULL)
+ free_noqname(mctx, &rdataset->noqname);
+ if (rdataset->closest != NULL)
+ free_noqname(mctx, &rdataset->closest);
+
+ free_acachearray(mctx, rdataset, rdataset->additional_auth);
+ free_acachearray(mctx, rdataset, rdataset->additional_glue);
+
+ if ((rdataset->attributes & RDATASET_ATTR_NONEXISTENT) != 0)
+ size = sizeof(*rdataset);
+ else
+ size = dns_rdataslab_size((unsigned char *)rdataset,
+ sizeof(*rdataset));
+ isc_mem_put(mctx, rdataset, size);
+}
+
+static inline void
+rollback_node(dns_rbtnode_t *node, rbtdb_serial_t serial) {
+ rdatasetheader_t *header, *dcurrent;
+ isc_boolean_t make_dirty = ISC_FALSE;
+
+ /*
+ * Caller must hold the node lock.
+ */
+
+ /*
+ * We set the IGNORE attribute on rdatasets with serial number
+ * 'serial'. When the reference count goes to zero, these rdatasets
+ * will be cleaned up; until that time, they will be ignored.
+ */
+ for (header = node->data; header != NULL; header = header->next) {
+ if (header->serial == serial) {
+ header->attributes |= RDATASET_ATTR_IGNORE;
+ make_dirty = ISC_TRUE;
+ }
+ for (dcurrent = header->down;
+ dcurrent != NULL;
+ dcurrent = dcurrent->down) {
+ if (dcurrent->serial == serial) {
+ dcurrent->attributes |= RDATASET_ATTR_IGNORE;
+ make_dirty = ISC_TRUE;
+ }
+ }
+ }
+ if (make_dirty)
+ node->dirty = 1;
+}
+
+static inline void
+clean_stale_headers(dns_rbtdb_t *rbtdb, isc_mem_t *mctx, rdatasetheader_t *top)
+{
+ rdatasetheader_t *d, *down_next;
+
+ for (d = top->down; d != NULL; d = down_next) {
+ down_next = d->down;
+ free_rdataset(rbtdb, mctx, d);
+ }
+ top->down = NULL;
+}
+
+static inline void
+clean_cache_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
+ rdatasetheader_t *current, *top_prev, *top_next;
+ isc_mem_t *mctx = rbtdb->common.mctx;
+
+ /*
+ * Caller must be holding the node lock.
+ */
+
+ top_prev = NULL;
+ for (current = node->data; current != NULL; current = top_next) {
+ top_next = current->next;
+ clean_stale_headers(rbtdb, mctx, current);
+ /*
+ * If current is nonexistent or stale, we can clean it up.
+ */
+ if ((current->attributes &
+ (RDATASET_ATTR_NONEXISTENT|RDATASET_ATTR_STALE)) != 0) {
+ if (top_prev != NULL)
+ top_prev->next = current->next;
+ else
+ node->data = current->next;
+ free_rdataset(rbtdb, mctx, current);
+ } else
+ top_prev = current;
+ }
+ node->dirty = 0;
+}
+
+static inline void
+clean_zone_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
+ rbtdb_serial_t least_serial)
+{
+ rdatasetheader_t *current, *dcurrent, *down_next, *dparent;
+ rdatasetheader_t *top_prev, *top_next;
+ isc_mem_t *mctx = rbtdb->common.mctx;
+ isc_boolean_t still_dirty = ISC_FALSE;
+
+ /*
+ * Caller must be holding the node lock.
+ */
+ REQUIRE(least_serial != 0);
+
+ top_prev = NULL;
+ for (current = node->data; current != NULL; current = top_next) {
+ top_next = current->next;
+
+ /*
+ * First, we clean up any instances of multiple rdatasets
+ * with the same serial number, or that have the IGNORE
+ * attribute.
+ */
+ dparent = current;
+ for (dcurrent = current->down;
+ dcurrent != NULL;
+ dcurrent = down_next) {
+ down_next = dcurrent->down;
+ INSIST(dcurrent->serial <= dparent->serial);
+ if (dcurrent->serial == dparent->serial ||
+ IGNORE(dcurrent)) {
+ if (down_next != NULL)
+ down_next->next = dparent;
+ dparent->down = down_next;
+ free_rdataset(rbtdb, mctx, dcurrent);
+ } else
+ dparent = dcurrent;
+ }
+
+ /*
+ * We've now eliminated all IGNORE datasets with the possible
+ * exception of current, which we now check.
+ */
+ if (IGNORE(current)) {
+ down_next = current->down;
+ if (down_next == NULL) {
+ if (top_prev != NULL)
+ top_prev->next = current->next;
+ else
+ node->data = current->next;
+ free_rdataset(rbtdb, mctx, current);
+ /*
+ * current no longer exists, so we can
+ * just continue with the loop.
+ */
+ continue;
+ } else {
+ /*
+ * Pull up current->down, making it the new
+ * current.
+ */
+ if (top_prev != NULL)
+ top_prev->next = down_next;
+ else
+ node->data = down_next;
+ down_next->next = top_next;
+ free_rdataset(rbtdb, mctx, current);
+ current = down_next;
+ }
+ }
+
+ /*
+ * We now try to find the first down node less than the
+ * least serial.
+ */
+ dparent = current;
+ for (dcurrent = current->down;
+ dcurrent != NULL;
+ dcurrent = down_next) {
+ down_next = dcurrent->down;
+ if (dcurrent->serial < least_serial)
+ break;
+ dparent = dcurrent;
+ }
+
+ /*
+ * If there is a such an rdataset, delete it and any older
+ * versions.
+ */
+ if (dcurrent != NULL) {
+ do {
+ down_next = dcurrent->down;
+ INSIST(dcurrent->serial <= least_serial);
+ free_rdataset(rbtdb, mctx, dcurrent);
+ dcurrent = down_next;
+ } while (dcurrent != NULL);
+ dparent->down = NULL;
+ }
+
+ /*
+ * Note. The serial number of 'current' might be less than
+ * least_serial too, but we cannot delete it because it is
+ * the most recent version, unless it is a NONEXISTENT
+ * rdataset.
+ */
+ if (current->down != NULL) {
+ still_dirty = ISC_TRUE;
+ top_prev = current;
+ } else {
+ /*
+ * If this is a NONEXISTENT rdataset, we can delete it.
+ */
+ if (NONEXISTENT(current)) {
+ if (top_prev != NULL)
+ top_prev->next = current->next;
+ else
+ node->data = current->next;
+ free_rdataset(rbtdb, mctx, current);
+ } else
+ top_prev = current;
+ }
+ }
+ if (!still_dirty)
+ node->dirty = 0;
+}
+
+/*%
+ * 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
+ * them when we deleted all the data at that node because we did not want
+ * to wait for the tree write lock.
+ *
+ * The caller must hold a tree write lock and bucketnum'th node (write) lock.
+ */
+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]);
+ while (node != NULL && count > 0) {
+ ISC_LIST_UNLINK(rbtdb->deadnodes[bucketnum], node, deadlink);
+
+ /*
+ * Since we're holding a tree write lock, it should be
+ * impossible for this node to be referenced by others.
+ */
+ 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));
+ node = ISC_LIST_HEAD(rbtdb->deadnodes[bucketnum]);
+ count--;
+ }
+}
+
+/*
+ * Caller must be holding the node lock if its reference must be protected
+ * by the lock.
+ */
+static inline void
+new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
+ unsigned int lockrefs, noderefs;
+ isc_refcount_t *lockref;
+
+ dns_rbtnode_refincrement0(node, &noderefs);
+ if (noderefs == 1) { /* this is the first reference to the node */
+ lockref = &rbtdb->node_locks[node->locknum].references;
+ isc_refcount_increment0(lockref, &lockrefs);
+ INSIST(lockrefs != 0);
+ }
+ INSIST(noderefs != 0);
+}
+
+/*
+ * This function is assumed to be called when a node is newly referenced
+ * and can be in the deadnode list. In that case the node must be retrieved
+ * from the list because the it is going to be used. In addition, if the caller
+ * happens to hold a write lock on the tree, it's a good chance to purge dead
+ * nodes.
+ * Note: while a new reference is gained in multiple places, there are only very
+ * few cases where the node can be in the deadnode list (only empty nodes can
+ * have been added to the list).
+ */
+static inline void
+reactivate_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
+ isc_rwlocktype_t treelocktype)
+{
+ isc_boolean_t need_relock = ISC_FALSE;
+
+ NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
+ new_reference(rbtdb, node);
+
+ NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_read);
+ if (ISC_LINK_LINKED(node, deadlink))
+ need_relock = ISC_TRUE;
+ else if (!ISC_LIST_EMPTY(rbtdb->deadnodes[node->locknum]) &&
+ treelocktype == isc_rwlocktype_write)
+ need_relock = ISC_TRUE;
+ NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_read);
+ if (need_relock) {
+ NODE_WEAKLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_write);
+ if (ISC_LINK_LINKED(node, deadlink))
+ ISC_LIST_UNLINK(rbtdb->deadnodes[node->locknum],
+ node, deadlink);
+ if (treelocktype == isc_rwlocktype_write)
+ cleanup_dead_nodes(rbtdb, node->locknum);
+ NODE_WEAKUNLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_write);
+ }
+
+ NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
+}
+
+/*
+ * Caller must be holding the node lock; either the "strong", read or write
+ * lock. Note that the lock must be held even when node references are
+ * atomically modified; in that case the decrement operation itself does not
+ * have to be protected, but we must avoid a race condition where multiple
+ * threads are decreasing the reference to zero simultaneously and at least
+ * one of them is going to free the node.
+ * This function returns ISC_TRUE if and only if the node reference decreases
+ * to zero.
+ */
+static isc_boolean_t
+decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
+ rbtdb_serial_t least_serial,
+ isc_rwlocktype_t nlock, isc_rwlocktype_t tlock)
+{
+ isc_result_t result;
+ isc_boolean_t write_locked;
+ rbtdb_nodelock_t *nodelock;
+ unsigned int refs, nrefs;
+ int bucket = node->locknum;
+
+ nodelock = &rbtdb->node_locks[bucket];
+
+ /* Handle easy and typical case first. */
+ if (!node->dirty && (node->data != NULL || node->down != NULL)) {
+ dns_rbtnode_refdecrement(node, &nrefs);
+ INSIST((int)nrefs >= 0);
+ if (nrefs == 0) {
+ isc_refcount_decrement(&nodelock->references, &refs);
+ INSIST((int)refs >= 0);
+ }
+ return ((nrefs == 0) ? ISC_TRUE : ISC_FALSE);
+ }
+
+ /* Upgrade the lock? */
+ if (nlock == isc_rwlocktype_read) {
+ NODE_WEAKUNLOCK(&nodelock->lock, isc_rwlocktype_read);
+ NODE_WEAKLOCK(&nodelock->lock, isc_rwlocktype_write);
+ }
+ dns_rbtnode_refdecrement(node, &nrefs);
+ INSIST((int)nrefs >= 0);
+ if (nrefs > 0) {
+ /* Restore the lock? */
+ if (nlock == isc_rwlocktype_read)
+ NODE_WEAKDOWNGRADE(&nodelock->lock);
+ return (ISC_FALSE);
+ }
+
+ if (node->dirty && dns_rbtnode_refcurrent(node) == 0) {
+ if (IS_CACHE(rbtdb))
+ clean_cache_node(rbtdb, node);
+ else {
+ if (least_serial == 0) {
+ /*
+ * Caller doesn't know the least serial.
+ * Get it.
+ */
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
+ least_serial = rbtdb->least_serial;
+ RBTDB_UNLOCK(&rbtdb->lock,
+ isc_rwlocktype_read);
+ }
+ clean_zone_node(rbtdb, node, least_serial);
+ }
+ }
+
+ isc_refcount_decrement(&nodelock->references, &refs);
+ INSIST((int)refs >= 0);
+
+ /*
+ * XXXDCL should this only be done for cache zones?
+ */
+ if (node->data != NULL || node->down != NULL) {
+ /* Restore the lock? */
+ if (nlock == isc_rwlocktype_read)
+ NODE_WEAKDOWNGRADE(&nodelock->lock);
+ return (ISC_TRUE);
+ }
+
+ /*
+ * Attempt to switch to a write lock on the tree. If this fails,
+ * we will add this node to a linked list of nodes in this locking
+ * bucket which we will free later.
+ */
+ if (tlock != isc_rwlocktype_write) {
+ /*
+ * Locking hierarchy notwithstanding, we don't need to free
+ * the node lock before acquiring the tree write lock because
+ * we only do a trylock.
+ */
+ if (tlock == isc_rwlocktype_read)
+ result = isc_rwlock_tryupgrade(&rbtdb->tree_lock);
+ else
+ result = isc_rwlock_trylock(&rbtdb->tree_lock,
+ isc_rwlocktype_write);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS ||
+ result == ISC_R_LOCKBUSY);
+
+ write_locked = ISC_TF(result == ISC_R_SUCCESS);
+ } else
+ write_locked = ISC_TRUE;
+
+ if (write_locked && dns_rbtnode_refcurrent(node) == 0) {
+ /*
+ * We can now delete the node if the reference counter is
+ * zero. This should be typically the case, but a different
+ * thread may still gain a (new) reference just before the
+ * current thread locks the tree (e.g., in findnode()).
+ */
+
+ if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(1))) {
+ char printname[DNS_NAME_FORMATSIZE];
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
+ "decrement_reference: "
+ "delete from rbt: %p %s",
+ node,
+ dns_rbt_formatnodename(node, printname,
+ 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));
+ } else if (dns_rbtnode_refcurrent(node) == 0) {
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
+ ISC_LIST_APPEND(rbtdb->deadnodes[bucket], node, deadlink);
+ }
+
+ /* Restore the lock? */
+ if (nlock == isc_rwlocktype_read)
+ NODE_WEAKDOWNGRADE(&nodelock->lock);
+
+ /*
+ * Relock a read lock, or unlock the write lock if no lock was held.
+ */
+ if (tlock == isc_rwlocktype_none)
+ if (write_locked)
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+
+ if (tlock == isc_rwlocktype_read)
+ if (write_locked)
+ isc_rwlock_downgrade(&rbtdb->tree_lock);
+
+ return (ISC_TRUE);
+}
+
+static inline void
+make_least_version(dns_rbtdb_t *rbtdb, rbtdb_version_t *version,
+ rbtdb_changedlist_t *cleanup_list)
+{
+ /*
+ * Caller must be holding the database lock.
+ */
+
+ rbtdb->least_serial = version->serial;
+ *cleanup_list = version->changed_list;
+ ISC_LIST_INIT(version->changed_list);
+}
+
+static inline void
+cleanup_nondirty(rbtdb_version_t *version, rbtdb_changedlist_t *cleanup_list) {
+ rbtdb_changed_t *changed, *next_changed;
+
+ /*
+ * If the changed record is dirty, then
+ * an update created multiple versions of
+ * a given rdataset. We keep this list
+ * until we're the least open version, at
+ * which point it's safe to get rid of any
+ * older versions.
+ *
+ * If the changed record isn't dirty, then
+ * we don't need it anymore since we're
+ * committing and not rolling back.
+ *
+ * The caller must be holding the database lock.
+ */
+ for (changed = HEAD(version->changed_list);
+ changed != NULL;
+ changed = next_changed) {
+ next_changed = NEXT(changed, link);
+ if (!changed->dirty) {
+ UNLINK(version->changed_list,
+ changed, link);
+ APPEND(*cleanup_list,
+ changed, link);
+ }
+ }
+}
+
+static void
+iszonesecure(dns_db_t *db, rbtdb_version_t *version, dns_dbnode_t *origin) {
+ 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);
+ result = dns_db_findrdataset(db, origin, version, dns_rdatatype_dnskey,
+ 0, 0, &keyset, NULL);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_t keyrdata = DNS_RDATA_INIT;
+ result = dns_rdataset_first(&keyset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&keyset, &keyrdata);
+ if (dns_zonekey_iszonekey(&keyrdata)) {
+ haszonekey = ISC_TRUE;
+ break;
+ }
+ result = dns_rdataset_next(&keyset);
+ }
+ dns_rdataset_disassociate(&keyset);
+ }
+ if (!haszonekey) {
+ version->secure = dns_db_insecure;
+ version->havensec3 = ISC_FALSE;
+ return;
+ }
+
+ dns_rdataset_init(&nsecset);
+ dns_rdataset_init(&signsecset);
+ result = dns_db_findrdataset(db, origin, version, dns_rdatatype_nsec,
+ 0, 0, &nsecset, &signsecset);
+ 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);
+
+ /*
+ * Do we have a valid NSEC/NSEC3 chain?
+ */
+ if (version->havensec3 || (hasnsec && !hasoptbit))
+ 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;
+}
+
+/*%<
+ * Walk the origin node looking for NSEC3PARAM records.
+ * Cache the nsec3 parameters.
+ */
+static void
+setnsec3parameters(dns_db_t *db, rbtdb_version_t *version,
+ isc_boolean_t *nsec3createflag)
+{
+ dns_rbtnode_t *node;
+ dns_rdata_nsec3param_t nsec3param;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t region;
+ isc_result_t result;
+ rdatasetheader_t *header, *header_next;
+ unsigned char *raw; /* RDATASLAB */
+ unsigned int count, length;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ version->havensec3 = ISC_FALSE;
+ node = rbtdb->origin_node;
+ NODE_LOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ for (header = node->data;
+ header != NULL;
+ header = header_next) {
+ header_next = header->next;
+ do {
+ if (header->serial <= version->serial &&
+ !IGNORE(header)) {
+ if (NONEXISTENT(header))
+ header = NULL;
+ break;
+ } else
+ header = header->down;
+ } while (header != NULL);
+
+ if (header != NULL &&
+ header->type == dns_rdatatype_nsec3param) {
+ /*
+ * Find A NSEC3PARAM with a supported algorithm.
+ */
+ raw = (unsigned char *)header + sizeof(*header);
+ count = raw[0] * 256 + raw[1]; /* count */
+#if DNS_RDATASET_FIXED
+ raw += count * 4 + 2;
+#else
+ raw += 2;
+#endif
+ while (count-- > 0U) {
+ length = raw[0] * 256 + raw[1];
+#if DNS_RDATASET_FIXED
+ raw += 4;
+#else
+ raw += 2;
+#endif
+ region.base = raw;
+ region.length = length;
+ raw += length;
+ dns_rdata_fromregion(&rdata,
+ rbtdb->common.rdclass,
+ dns_rdatatype_nsec3param,
+ &region);
+ result = dns_rdata_tostruct(&rdata,
+ &nsec3param,
+ NULL);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdata_reset(&rdata);
+
+ if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG &&
+ !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
+
+ INSIST(nsec3param.salt_length <=
+ sizeof(version->salt));
+ memcpy(version->salt, nsec3param.salt,
+ nsec3param.salt_length);
+ version->hash = nsec3param.hash;
+ version->salt_length = nsec3param.salt_length;
+ version->iterations = nsec3param.iterations;
+ version->flags = nsec3param.flags;
+ version->havensec3 = ISC_TRUE;
+ /*
+ * Look for a better algorithm than the
+ * unknown test algorithm.
+ */
+ if (nsec3param.hash != DNS_NSEC3_UNKNOWNALG)
+ goto unlock;
+ }
+ }
+ }
+ unlock:
+ NODE_UNLOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+}
+
+static void
+closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ rbtdb_version_t *version, *cleanup_version, *least_greater;
+ isc_boolean_t rollback = ISC_FALSE;
+ rbtdb_changedlist_t cleanup_list;
+ rdatasetheaderlist_t resigned_list;
+ rbtdb_changed_t *changed, *next_changed;
+ rbtdb_serial_t serial, least_serial;
+ dns_rbtnode_t *rbtnode;
+ unsigned int refs;
+ rdatasetheader_t *header;
+ isc_boolean_t writer;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ version = (rbtdb_version_t *)*versionp;
+
+ cleanup_version = NULL;
+ ISC_LIST_INIT(cleanup_list);
+ ISC_LIST_INIT(resigned_list);
+
+ isc_refcount_decrement(&version->references, &refs);
+ if (refs > 0) { /* typical and easy case first */
+ if (commit) {
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
+ INSIST(!version->writer);
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
+ }
+ goto end;
+ }
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
+ serial = version->serial;
+ writer = version->writer;
+ if (version->writer) {
+ if (commit) {
+ unsigned cur_ref;
+ rbtdb_version_t *cur_version;
+
+ INSIST(version->commit_ok);
+ INSIST(version == rbtdb->future_version);
+ /*
+ * The current version is going to be replaced.
+ * Release the (likely last) reference to it from the
+ * DB itself and unlink it from the open list.
+ */
+ cur_version = rbtdb->current_version;
+ isc_refcount_decrement(&cur_version->references,
+ &cur_ref);
+ if (cur_ref == 0) {
+ if (cur_version->serial == rbtdb->least_serial)
+ INSIST(EMPTY(cur_version->changed_list));
+ UNLINK(rbtdb->open_versions,
+ cur_version, link);
+ }
+ if (EMPTY(rbtdb->open_versions)) {
+ /*
+ * We're going to become the least open
+ * version.
+ */
+ make_least_version(rbtdb, version,
+ &cleanup_list);
+ } else {
+ /*
+ * Some other open version is the
+ * least version. We can't cleanup
+ * records that were changed in this
+ * version because the older versions
+ * may still be in use by an open
+ * version.
+ *
+ * We can, however, discard the
+ * changed records for things that
+ * we've added that didn't exist in
+ * prior versions.
+ */
+ cleanup_nondirty(version, &cleanup_list);
+ }
+ /*
+ * If the (soon to be former) current version
+ * isn't being used by anyone, we can clean
+ * it up.
+ */
+ if (cur_ref == 0) {
+ cleanup_version = cur_version;
+ APPENDLIST(version->changed_list,
+ cleanup_version->changed_list,
+ link);
+ }
+ /*
+ * Become the current version.
+ */
+ version->writer = ISC_FALSE;
+ rbtdb->current_version = version;
+ rbtdb->current_serial = version->serial;
+ rbtdb->future_version = NULL;
+
+ /*
+ * Keep the current version in the open list, and
+ * gain a reference for the DB itself (see the DB
+ * creation function below). This must be the only
+ * case where we need to increment the counter from
+ * zero and need to use isc_refcount_increment0().
+ */
+ isc_refcount_increment0(&version->references,
+ &cur_ref);
+ INSIST(cur_ref == 1);
+ PREPEND(rbtdb->open_versions,
+ rbtdb->current_version, link);
+ resigned_list = version->resigned_list;
+ ISC_LIST_INIT(version->resigned_list);
+ } else {
+ /*
+ * We're rolling back this transaction.
+ */
+ cleanup_list = version->changed_list;
+ ISC_LIST_INIT(version->changed_list);
+ resigned_list = version->resigned_list;
+ ISC_LIST_INIT(version->resigned_list);
+ rollback = ISC_TRUE;
+ cleanup_version = version;
+ rbtdb->future_version = NULL;
+ }
+ } else {
+ if (version != rbtdb->current_version) {
+ /*
+ * There are no external or internal references
+ * to this version and it can be cleaned up.
+ */
+ cleanup_version = version;
+
+ /*
+ * Find the version with the least serial
+ * number greater than ours.
+ */
+ least_greater = PREV(version, link);
+ if (least_greater == NULL)
+ least_greater = rbtdb->current_version;
+
+ INSIST(version->serial < least_greater->serial);
+ /*
+ * Is this the least open version?
+ */
+ if (version->serial == rbtdb->least_serial) {
+ /*
+ * Yes. Install the new least open
+ * version.
+ */
+ make_least_version(rbtdb,
+ least_greater,
+ &cleanup_list);
+ } else {
+ /*
+ * Add any unexecuted cleanups to
+ * those of the least greater version.
+ */
+ APPENDLIST(least_greater->changed_list,
+ version->changed_list,
+ link);
+ }
+ } else if (version->serial == rbtdb->least_serial)
+ INSIST(EMPTY(version->changed_list));
+ UNLINK(rbtdb->open_versions, version, link);
+ }
+ least_serial = rbtdb->least_serial;
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
+
+ /*
+ * Update the zone's secure status.
+ */
+ if (writer && commit && !IS_CACHE(rbtdb))
+ iszonesecure(db, version, rbtdb->origin_node);
+
+ if (cleanup_version != NULL) {
+ INSIST(EMPTY(cleanup_version->changed_list));
+ isc_mem_put(rbtdb->common.mctx, cleanup_version,
+ sizeof(*cleanup_version));
+ }
+
+ /*
+ * Commit/rollback re-signed headers.
+ */
+ for (header = HEAD(resigned_list);
+ header != NULL;
+ header = HEAD(resigned_list)) {
+ ISC_LIST_UNLINK(resigned_list, header, lru_link);
+ if (rollback) {
+ nodelock_t *lock;
+ lock = &rbtdb->node_locks[header->node->locknum].lock;
+ NODE_LOCK(lock, isc_rwlocktype_write);
+ resign_insert(rbtdb, header->node->locknum, header);
+ NODE_UNLOCK(lock, isc_rwlocktype_write);
+ }
+ decrement_reference(rbtdb, header->node, least_serial,
+ isc_rwlocktype_write,
+ isc_rwlocktype_none);
+ }
+
+ if (!EMPTY(cleanup_list)) {
+ /*
+ * We acquire a tree write lock here in order to make sure
+ * that stale nodes will be removed in decrement_reference().
+ * If we didn't have the lock, those nodes could miss the
+ * chance to be removed until the server stops. The write lock
+ * is expensive, but this event should be rare enough to justify
+ * the cost.
+ */
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+ for (changed = HEAD(cleanup_list);
+ changed != NULL;
+ changed = next_changed) {
+ nodelock_t *lock;
+
+ next_changed = NEXT(changed, link);
+ rbtnode = changed->node;
+ lock = &rbtdb->node_locks[rbtnode->locknum].lock;
+
+ NODE_LOCK(lock, isc_rwlocktype_write);
+ /*
+ * This is a good opportunity to purge any dead nodes,
+ * so use it.
+ */
+ cleanup_dead_nodes(rbtdb, rbtnode->locknum);
+
+ if (rollback)
+ rollback_node(rbtnode, serial);
+ decrement_reference(rbtdb, rbtnode, least_serial,
+ isc_rwlocktype_write,
+ isc_rwlocktype_write);
+
+ NODE_UNLOCK(lock, isc_rwlocktype_write);
+
+ isc_mem_put(rbtdb->common.mctx, changed,
+ sizeof(*changed));
+ }
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+ }
+
+ end:
+ *versionp = NULL;
+}
+
+/*
+ * Add the necessary magic for the wildcard name 'name'
+ * to be found in 'rbtdb'.
+ *
+ * In order for wildcard matching to work correctly in
+ * zone_find(), we must ensure that a node for the wildcarding
+ * level exists in the database, and has its 'find_callback'
+ * and 'wild' bits set.
+ *
+ * E.g. if the wildcard name is "*.sub.example." then we
+ * must ensure that "sub.example." exists and is marked as
+ * a wildcard level.
+ */
+static isc_result_t
+add_wildcard_magic(dns_rbtdb_t *rbtdb, dns_name_t *name) {
+ isc_result_t result;
+ dns_name_t foundname;
+ dns_offsets_t offsets;
+ unsigned int n;
+ dns_rbtnode_t *node = NULL;
+
+ dns_name_init(&foundname, offsets);
+ n = dns_name_countlabels(name);
+ INSIST(n >= 2);
+ n--;
+ dns_name_getlabelsequence(name, 1, n, &foundname);
+ result = dns_rbt_addnode(rbtdb->tree, &foundname, &node);
+ if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
+ return (result);
+ node->nsec3 = 0;
+ node->find_callback = 1;
+ node->wild = 1;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+add_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) {
+ isc_result_t result;
+ dns_name_t foundname;
+ dns_offsets_t offsets;
+ unsigned int n, l, i;
+
+ dns_name_init(&foundname, offsets);
+ n = dns_name_countlabels(name);
+ l = dns_name_countlabels(&rbtdb->common.origin);
+ i = l + 1;
+ while (i < n) {
+ dns_rbtnode_t *node = NULL; /* dummy */
+ dns_name_getlabelsequence(name, n - i, i, &foundname);
+ if (dns_name_iswildcard(&foundname)) {
+ result = add_wildcard_magic(rbtdb, &foundname);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_rbt_addnode(rbtdb->tree, &foundname,
+ &node);
+ if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
+ return (result);
+ node->nsec3 = 0;
+ }
+ i++;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
+ dns_dbnode_t **nodep)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *node = NULL;
+ dns_name_t nodename;
+ isc_result_t result;
+ isc_rwlocktype_t locktype = isc_rwlocktype_read;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ dns_name_init(&nodename, NULL);
+ RWLOCK(&rbtdb->tree_lock, locktype);
+ result = dns_rbt_findnode(rbtdb->tree, name, NULL, &node, NULL,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ RWUNLOCK(&rbtdb->tree_lock, locktype);
+ if (!create) {
+ if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_NOTFOUND;
+ return (result);
+ }
+ /*
+ * It would be nice to try to upgrade the lock instead of
+ * unlocking then relocking.
+ */
+ locktype = isc_rwlocktype_write;
+ RWLOCK(&rbtdb->tree_lock, locktype);
+ node = NULL;
+ result = dns_rbt_addnode(rbtdb->tree, name, &node);
+ if (result == ISC_R_SUCCESS) {
+ dns_rbt_namefromnode(node, &nodename);
+#ifdef DNS_RBT_USEHASH
+ node->locknum = node->hashval % rbtdb->node_lock_count;
+#else
+ 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)) {
+ result = add_wildcard_magic(rbtdb, name);
+ if (result != ISC_R_SUCCESS) {
+ RWUNLOCK(&rbtdb->tree_lock, locktype);
+ return (result);
+ }
+ }
+ } else if (result != ISC_R_EXISTS) {
+ RWUNLOCK(&rbtdb->tree_lock, locktype);
+ return (result);
+ }
+ }
+ reactivate_node(rbtdb, node, locktype);
+ RWUNLOCK(&rbtdb->tree_lock, locktype);
+
+ *nodep = (dns_dbnode_t *)node;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+findnsec3node(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
+ dns_dbnode_t **nodep)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *node = NULL;
+ dns_name_t nodename;
+ isc_result_t result;
+ isc_rwlocktype_t locktype = isc_rwlocktype_read;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ dns_name_init(&nodename, NULL);
+ RWLOCK(&rbtdb->tree_lock, locktype);
+ result = dns_rbt_findnode(rbtdb->nsec3, name, NULL, &node, NULL,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ RWUNLOCK(&rbtdb->tree_lock, locktype);
+ if (!create) {
+ if (result == DNS_R_PARTIALMATCH)
+ result = ISC_R_NOTFOUND;
+ return (result);
+ }
+ /*
+ * It would be nice to try to upgrade the lock instead of
+ * unlocking then relocking.
+ */
+ locktype = isc_rwlocktype_write;
+ RWLOCK(&rbtdb->tree_lock, locktype);
+ node = NULL;
+ result = dns_rbt_addnode(rbtdb->nsec3, name, &node);
+ if (result == ISC_R_SUCCESS) {
+ dns_rbt_namefromnode(node, &nodename);
+#ifdef DNS_RBT_USEHASH
+ node->locknum = node->hashval % rbtdb->node_lock_count;
+#else
+ node->locknum = dns_name_hash(&nodename, ISC_TRUE) %
+ rbtdb->node_lock_count;
+#endif
+ node->nsec3 = 1U;
+ } else if (result != ISC_R_EXISTS) {
+ RWUNLOCK(&rbtdb->tree_lock, locktype);
+ return (result);
+ }
+ } else
+ INSIST(node->nsec3);
+ NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
+ new_reference(rbtdb, node);
+ NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
+ RWUNLOCK(&rbtdb->tree_lock, locktype);
+
+ *nodep = (dns_dbnode_t *)node;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+zone_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
+ rbtdb_search_t *search = arg;
+ rdatasetheader_t *header, *header_next;
+ rdatasetheader_t *dname_header, *sigdname_header, *ns_header;
+ rdatasetheader_t *found;
+ isc_result_t result;
+ dns_rbtnode_t *onode;
+
+ /*
+ * We only want to remember the topmost zone cut, since it's the one
+ * that counts, so we'll just continue if we've already found a
+ * zonecut.
+ */
+ if (search->zonecut != NULL)
+ return (DNS_R_CONTINUE);
+
+ found = NULL;
+ result = DNS_R_CONTINUE;
+ onode = search->rbtdb->origin_node;
+
+ NODE_LOCK(&(search->rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+
+ /*
+ * Look for an NS or DNAME rdataset active in our version.
+ */
+ ns_header = NULL;
+ dname_header = NULL;
+ sigdname_header = NULL;
+ for (header = node->data; header != NULL; header = header_next) {
+ header_next = header->next;
+ if (header->type == dns_rdatatype_ns ||
+ header->type == dns_rdatatype_dname ||
+ header->type == RBTDB_RDATATYPE_SIGDNAME) {
+ do {
+ if (header->serial <= search->serial &&
+ !IGNORE(header)) {
+ /*
+ * Is this a "this rdataset doesn't
+ * exist" record?
+ */
+ if (NONEXISTENT(header))
+ header = NULL;
+ break;
+ } else
+ header = header->down;
+ } while (header != NULL);
+ if (header != NULL) {
+ if (header->type == dns_rdatatype_dname)
+ dname_header = header;
+ else if (header->type ==
+ RBTDB_RDATATYPE_SIGDNAME)
+ sigdname_header = header;
+ else if (node != onode ||
+ IS_STUB(search->rbtdb)) {
+ /*
+ * We've found an NS rdataset that
+ * isn't at the origin node. We check
+ * that they're not at the origin node,
+ * because otherwise we'd erroneously
+ * treat the zone top as if it were
+ * a delegation.
+ */
+ ns_header = header;
+ }
+ }
+ }
+ }
+
+ /*
+ * Did we find anything?
+ */
+ if (dname_header != NULL) {
+ /*
+ * Note that DNAME has precedence over NS if both exist.
+ */
+ found = dname_header;
+ search->zonecut_sigrdataset = sigdname_header;
+ } else if (ns_header != NULL) {
+ found = ns_header;
+ search->zonecut_sigrdataset = NULL;
+ }
+
+ if (found != NULL) {
+ /*
+ * We increment the reference count on node to ensure that
+ * search->zonecut_rdataset will still be valid later.
+ */
+ new_reference(search->rbtdb, node);
+ search->zonecut = node;
+ search->zonecut_rdataset = found;
+ search->need_cleanup = ISC_TRUE;
+ /*
+ * Since we've found a zonecut, anything beneath it is
+ * glue and is not subject to wildcard matching, so we
+ * may clear search->wild.
+ */
+ search->wild = ISC_FALSE;
+ if ((search->options & DNS_DBFIND_GLUEOK) == 0) {
+ /*
+ * If the caller does not want to find glue, then
+ * this is the best answer and the search should
+ * stop now.
+ */
+ result = DNS_R_PARTIALMATCH;
+ } else {
+ dns_name_t *zcname;
+
+ /*
+ * The search will continue beneath the zone cut.
+ * This may or may not be the best match. In case it
+ * is, we need to remember the node name.
+ */
+ zcname = dns_fixedname_name(&search->zonecut_name);
+ RUNTIME_CHECK(dns_name_copy(name, zcname, NULL) ==
+ ISC_R_SUCCESS);
+ search->copy_name = ISC_TRUE;
+ }
+ } else {
+ /*
+ * There is no zonecut at this node which is active in this
+ * version.
+ *
+ * If this is a "wild" node and the caller hasn't disabled
+ * wildcard matching, remember that we've seen a wild node
+ * in case we need to go searching for wildcard matches
+ * later on.
+ */
+ if (node->wild && (search->options & DNS_DBFIND_NOWILD) == 0)
+ search->wild = ISC_TRUE;
+ }
+
+ NODE_UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+
+ return (result);
+}
+
+static inline void
+bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
+ rdatasetheader_t *header, isc_stdtime_t now,
+ dns_rdataset_t *rdataset)
+{
+ unsigned char *raw; /* RDATASLAB */
+
+ /*
+ * Caller must be holding the node reader lock.
+ * XXXJT: technically, we need a writer lock, since we'll increment
+ * the header count below. However, since the actual counter value
+ * doesn't matter, we prioritize performance here. (We may want to
+ * use atomic increment when available).
+ */
+
+ if (rdataset == NULL)
+ return;
+
+ new_reference(rbtdb, node);
+
+ INSIST(rdataset->methods == NULL); /* We must be disassociated. */
+
+ rdataset->methods = &rdataset_methods;
+ rdataset->rdclass = rbtdb->common.rdclass;
+ rdataset->type = RBTDB_RDATATYPE_BASE(header->type);
+ rdataset->covers = RBTDB_RDATATYPE_EXT(header->type);
+ rdataset->ttl = header->rdh_ttl - now;
+ rdataset->trust = header->trust;
+ if (NXDOMAIN(header))
+ rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;
+ if (OPTOUT(header))
+ rdataset->attributes |= DNS_RDATASETATTR_OPTOUT;
+ rdataset->private1 = rbtdb;
+ rdataset->private2 = node;
+ raw = (unsigned char *)header + sizeof(*header);
+ rdataset->private3 = raw;
+ rdataset->count = header->count++;
+ if (rdataset->count == ISC_UINT32_MAX)
+ rdataset->count = 0;
+
+ /*
+ * Reset iterator state.
+ */
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+
+ /*
+ * Add noqname proof.
+ */
+ rdataset->private6 = header->noqname;
+ if (rdataset->private6 != NULL)
+ rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
+ rdataset->private7 = header->closest;
+ if (rdataset->private7 != NULL)
+ rdataset->attributes |= DNS_RDATASETATTR_CLOSEST;
+
+ /*
+ * Copy out re-signing information.
+ */
+ if (RESIGN(header)) {
+ rdataset->attributes |= DNS_RDATASETATTR_RESIGN;
+ rdataset->resign = header->resign;
+ } else
+ rdataset->resign = 0;
+}
+
+static inline isc_result_t
+setup_delegation(rbtdb_search_t *search, dns_dbnode_t **nodep,
+ dns_name_t *foundname, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ isc_result_t result;
+ dns_name_t *zcname;
+ rbtdb_rdatatype_t type;
+ dns_rbtnode_t *node;
+
+ /*
+ * The caller MUST NOT be holding any node locks.
+ */
+
+ node = search->zonecut;
+ type = search->zonecut_rdataset->type;
+
+ /*
+ * If we have to set foundname, we do it before anything else.
+ * If we were to set foundname after we had set nodep or bound the
+ * rdataset, then we'd have to undo that work if dns_name_copy()
+ * failed. By setting foundname first, there's nothing to undo if
+ * we have trouble.
+ */
+ if (foundname != NULL && search->copy_name) {
+ zcname = dns_fixedname_name(&search->zonecut_name);
+ result = dns_name_copy(zcname, foundname, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (nodep != NULL) {
+ /*
+ * Note that we don't have to increment the node's reference
+ * count here because we're going to use the reference we
+ * already have in the search block.
+ */
+ *nodep = node;
+ search->need_cleanup = ISC_FALSE;
+ }
+ if (rdataset != NULL) {
+ NODE_LOCK(&(search->rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ bind_rdataset(search->rbtdb, node, search->zonecut_rdataset,
+ search->now, rdataset);
+ if (sigrdataset != NULL && search->zonecut_sigrdataset != NULL)
+ bind_rdataset(search->rbtdb, node,
+ search->zonecut_sigrdataset,
+ search->now, sigrdataset);
+ NODE_UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ }
+
+ if (type == dns_rdatatype_dname)
+ return (DNS_R_DNAME);
+ return (DNS_R_DELEGATION);
+}
+
+static inline isc_boolean_t
+valid_glue(rbtdb_search_t *search, dns_name_t *name, rbtdb_rdatatype_t type,
+ dns_rbtnode_t *node)
+{
+ unsigned char *raw; /* RDATASLAB */
+ unsigned int count, size;
+ dns_name_t ns_name;
+ isc_boolean_t valid = ISC_FALSE;
+ dns_offsets_t offsets;
+ isc_region_t region;
+ rdatasetheader_t *header;
+
+ /*
+ * No additional locking is required.
+ */
+
+ /*
+ * Valid glue types are A, AAAA, A6. NS is also a valid glue type
+ * if it occurs at a zone cut, but is not valid below it.
+ */
+ if (type == dns_rdatatype_ns) {
+ if (node != search->zonecut) {
+ return (ISC_FALSE);
+ }
+ } else if (type != dns_rdatatype_a &&
+ type != dns_rdatatype_aaaa &&
+ type != dns_rdatatype_a6) {
+ return (ISC_FALSE);
+ }
+
+ header = search->zonecut_rdataset;
+ raw = (unsigned char *)header + sizeof(*header);
+ count = raw[0] * 256 + raw[1];
+#if DNS_RDATASET_FIXED
+ raw += 2 + (4 * count);
+#else
+ raw += 2;
+#endif
+
+ while (count > 0) {
+ count--;
+ size = raw[0] * 256 + raw[1];
+#if DNS_RDATASET_FIXED
+ raw += 4;
+#else
+ raw += 2;
+#endif
+ region.base = raw;
+ region.length = size;
+ raw += size;
+ /*
+ * XXX Until we have rdata structures, we have no choice but
+ * to directly access the rdata format.
+ */
+ dns_name_init(&ns_name, offsets);
+ dns_name_fromregion(&ns_name, &region);
+ if (dns_name_compare(&ns_name, name) == 0) {
+ valid = ISC_TRUE;
+ break;
+ }
+ }
+
+ return (valid);
+}
+
+static inline isc_boolean_t
+activeempty(rbtdb_search_t *search, dns_rbtnodechain_t *chain,
+ dns_name_t *name)
+{
+ dns_fixedname_t fnext;
+ dns_fixedname_t forigin;
+ dns_name_t *next;
+ dns_name_t *origin;
+ dns_name_t prefix;
+ dns_rbtdb_t *rbtdb;
+ dns_rbtnode_t *node;
+ isc_result_t result;
+ isc_boolean_t answer = ISC_FALSE;
+ rdatasetheader_t *header;
+
+ rbtdb = search->rbtdb;
+
+ dns_name_init(&prefix, NULL);
+ dns_fixedname_init(&fnext);
+ next = dns_fixedname_name(&fnext);
+ dns_fixedname_init(&forigin);
+ origin = dns_fixedname_name(&forigin);
+
+ result = dns_rbtnodechain_next(chain, NULL, NULL);
+ while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
+ node = NULL;
+ result = dns_rbtnodechain_current(chain, &prefix,
+ origin, &node);
+ if (result != ISC_R_SUCCESS)
+ break;
+ NODE_LOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ for (header = node->data;
+ header != NULL;
+ header = header->next) {
+ if (header->serial <= search->serial &&
+ !IGNORE(header) && EXISTS(header))
+ break;
+ }
+ NODE_UNLOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ if (header != NULL)
+ break;
+ result = dns_rbtnodechain_next(chain, NULL, NULL);
+ }
+ if (result == ISC_R_SUCCESS)
+ result = dns_name_concatenate(&prefix, origin, next, NULL);
+ if (result == ISC_R_SUCCESS && dns_name_issubdomain(next, name))
+ answer = ISC_TRUE;
+ return (answer);
+}
+
+static inline isc_boolean_t
+activeemtpynode(rbtdb_search_t *search, dns_name_t *qname, dns_name_t *wname) {
+ dns_fixedname_t fnext;
+ dns_fixedname_t forigin;
+ dns_fixedname_t fprev;
+ dns_name_t *next;
+ dns_name_t *origin;
+ dns_name_t *prev;
+ dns_name_t name;
+ dns_name_t rname;
+ dns_name_t tname;
+ dns_rbtdb_t *rbtdb;
+ dns_rbtnode_t *node;
+ dns_rbtnodechain_t chain;
+ isc_boolean_t check_next = ISC_TRUE;
+ isc_boolean_t check_prev = ISC_TRUE;
+ isc_boolean_t answer = ISC_FALSE;
+ isc_result_t result;
+ rdatasetheader_t *header;
+ unsigned int n;
+
+ rbtdb = search->rbtdb;
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&tname, NULL);
+ dns_name_init(&rname, NULL);
+ dns_fixedname_init(&fnext);
+ next = dns_fixedname_name(&fnext);
+ dns_fixedname_init(&fprev);
+ prev = dns_fixedname_name(&fprev);
+ dns_fixedname_init(&forigin);
+ origin = dns_fixedname_name(&forigin);
+
+ /*
+ * Find if qname is at or below a empty node.
+ * Use our own copy of the chain.
+ */
+
+ chain = search->chain;
+ do {
+ node = NULL;
+ result = dns_rbtnodechain_current(&chain, &name,
+ origin, &node);
+ if (result != ISC_R_SUCCESS)
+ break;
+ NODE_LOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ for (header = node->data;
+ header != NULL;
+ header = header->next) {
+ if (header->serial <= search->serial &&
+ !IGNORE(header) && EXISTS(header))
+ break;
+ }
+ NODE_UNLOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ if (header != NULL)
+ break;
+ result = dns_rbtnodechain_prev(&chain, NULL, NULL);
+ } while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN);
+ if (result == ISC_R_SUCCESS)
+ result = dns_name_concatenate(&name, origin, prev, NULL);
+ if (result != ISC_R_SUCCESS)
+ check_prev = ISC_FALSE;
+
+ result = dns_rbtnodechain_next(&chain, NULL, NULL);
+ while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
+ node = NULL;
+ result = dns_rbtnodechain_current(&chain, &name,
+ origin, &node);
+ if (result != ISC_R_SUCCESS)
+ break;
+ NODE_LOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ for (header = node->data;
+ header != NULL;
+ header = header->next) {
+ if (header->serial <= search->serial &&
+ !IGNORE(header) && EXISTS(header))
+ break;
+ }
+ NODE_UNLOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ if (header != NULL)
+ break;
+ result = dns_rbtnodechain_next(&chain, NULL, NULL);
+ }
+ if (result == ISC_R_SUCCESS)
+ result = dns_name_concatenate(&name, origin, next, NULL);
+ if (result != ISC_R_SUCCESS)
+ check_next = ISC_FALSE;
+
+ dns_name_clone(qname, &rname);
+
+ /*
+ * Remove the wildcard label to find the terminal name.
+ */
+ n = dns_name_countlabels(wname);
+ dns_name_getlabelsequence(wname, 1, n - 1, &tname);
+
+ do {
+ if ((check_prev && dns_name_issubdomain(prev, &rname)) ||
+ (check_next && dns_name_issubdomain(next, &rname))) {
+ answer = ISC_TRUE;
+ break;
+ }
+ /*
+ * Remove the left hand label.
+ */
+ n = dns_name_countlabels(&rname);
+ dns_name_getlabelsequence(&rname, 1, n - 1, &rname);
+ } while (!dns_name_equal(&rname, &tname));
+ return (answer);
+}
+
+static inline isc_result_t
+find_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep,
+ dns_name_t *qname)
+{
+ unsigned int i, j;
+ dns_rbtnode_t *node, *level_node, *wnode;
+ rdatasetheader_t *header;
+ isc_result_t result = ISC_R_NOTFOUND;
+ dns_name_t name;
+ dns_name_t *wname;
+ dns_fixedname_t fwname;
+ dns_rbtdb_t *rbtdb;
+ isc_boolean_t done, wild, active;
+ dns_rbtnodechain_t wchain;
+
+ /*
+ * Caller must be holding the tree lock and MUST NOT be holding
+ * any node locks.
+ */
+
+ /*
+ * Examine each ancestor level. If the level's wild bit
+ * is set, then construct the corresponding wildcard name and
+ * search for it. If the wildcard node exists, and is active in
+ * this version, we're done. If not, then we next check to see
+ * if the ancestor is active in this version. If so, then there
+ * can be no possible wildcard match and again we're done. If not,
+ * continue the search.
+ */
+
+ rbtdb = search->rbtdb;
+ i = search->chain.level_matches;
+ done = ISC_FALSE;
+ node = *nodep;
+ do {
+ NODE_LOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+
+ /*
+ * First we try to figure out if this node is active in
+ * the search's version. We do this now, even though we
+ * may not need the information, because it simplifies the
+ * locking and code flow.
+ */
+ for (header = node->data;
+ header != NULL;
+ header = header->next) {
+ if (header->serial <= search->serial &&
+ !IGNORE(header) && EXISTS(header))
+ break;
+ }
+ if (header != NULL)
+ active = ISC_TRUE;
+ else
+ active = ISC_FALSE;
+
+ if (node->wild)
+ wild = ISC_TRUE;
+ else
+ wild = ISC_FALSE;
+
+ NODE_UNLOCK(&(rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+
+ if (wild) {
+ /*
+ * Construct the wildcard name for this level.
+ */
+ dns_name_init(&name, NULL);
+ dns_rbt_namefromnode(node, &name);
+ dns_fixedname_init(&fwname);
+ wname = dns_fixedname_name(&fwname);
+ result = dns_name_concatenate(dns_wildcardname, &name,
+ wname, NULL);
+ j = i;
+ while (result == ISC_R_SUCCESS && j != 0) {
+ j--;
+ level_node = search->chain.levels[j];
+ dns_name_init(&name, NULL);
+ dns_rbt_namefromnode(level_node, &name);
+ result = dns_name_concatenate(wname,
+ &name,
+ wname,
+ NULL);
+ }
+ if (result != ISC_R_SUCCESS)
+ break;
+
+ wnode = NULL;
+ dns_rbtnodechain_init(&wchain, NULL);
+ result = dns_rbt_findnode(rbtdb->tree, wname,
+ NULL, &wnode, &wchain,
+ DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS) {
+ nodelock_t *lock;
+
+ /*
+ * We have found the wildcard node. If it
+ * is active in the search's version, we're
+ * done.
+ */
+ lock = &rbtdb->node_locks[wnode->locknum].lock;
+ NODE_LOCK(lock, isc_rwlocktype_read);
+ for (header = wnode->data;
+ header != NULL;
+ header = header->next) {
+ if (header->serial <= search->serial &&
+ !IGNORE(header) && EXISTS(header))
+ break;
+ }
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
+ if (header != NULL ||
+ activeempty(search, &wchain, wname)) {
+ if (activeemtpynode(search, qname,
+ wname)) {
+ return (ISC_R_NOTFOUND);
+ }
+ /*
+ * The wildcard node is active!
+ *
+ * Note: result is still ISC_R_SUCCESS
+ * so we don't have to set it.
+ */
+ *nodep = wnode;
+ break;
+ }
+ } else if (result != ISC_R_NOTFOUND &&
+ result != DNS_R_PARTIALMATCH) {
+ /*
+ * An error has occurred. Bail out.
+ */
+ break;
+ }
+ }
+
+ if (active) {
+ /*
+ * The level node is active. Any wildcarding
+ * present at higher levels has no
+ * effect and we're done.
+ */
+ result = ISC_R_NOTFOUND;
+ break;
+ }
+
+ if (i > 0) {
+ i--;
+ node = search->chain.levels[i];
+ } else
+ done = ISC_TRUE;
+ } while (!done);
+
+ return (result);
+}
+
+static isc_boolean_t
+matchparams(rdatasetheader_t *header, rbtdb_search_t *search)
+{
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec3_t nsec3;
+ unsigned char *raw; /* RDATASLAB */
+ unsigned int rdlen, count;
+ isc_region_t region;
+ isc_result_t result;
+
+ REQUIRE(header->type == dns_rdatatype_nsec3);
+
+ raw = (unsigned char *)header + sizeof(*header);
+ count = raw[0] * 256 + raw[1]; /* count */
+#if DNS_RDATASET_FIXED
+ raw += count * 4 + 2;
+#else
+ raw += 2;
+#endif
+ while (count-- > 0) {
+ rdlen = raw[0] * 256 + raw[1];
+#if DNS_RDATASET_FIXED
+ raw += 4;
+#else
+ raw += 2;
+#endif
+ region.base = raw;
+ region.length = rdlen;
+ dns_rdata_fromregion(&rdata, search->rbtdb->common.rdclass,
+ dns_rdatatype_nsec3, &region);
+ raw += rdlen;
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+ if (nsec3.hash == search->rbtversion->hash &&
+ nsec3.iterations == search->rbtversion->iterations &&
+ nsec3.salt_length == search->rbtversion->salt_length &&
+ memcmp(nsec3.salt, search->rbtversion->salt,
+ nsec3.salt_length) == 0)
+ return (ISC_TRUE);
+ dns_rdata_reset(&rdata);
+ }
+ return (ISC_FALSE);
+}
+
+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;
+ rdatasetheader_t *header, *header_next, *found, *foundsig;
+ isc_boolean_t empty_node;
+ isc_result_t result;
+ dns_fixedname_t fname, forigin;
+ dns_name_t *name, *origin;
+ dns_rdatatype_t type;
+ rbtdb_rdatatype_t sigtype;
+ isc_boolean_t wraps;
+ isc_boolean_t need_sig = ISC_TF(secure == dns_db_secure);
+
+ if (tree == search->rbtdb->nsec3) {
+ type = dns_rdatatype_nsec3;
+ sigtype = RBTDB_RDATATYPE_SIGNSEC3;
+ wraps = ISC_TRUE;
+ } else {
+ type = dns_rdatatype_nsec;
+ sigtype = RBTDB_RDATATYPE_SIGNSEC;
+ wraps = ISC_FALSE;
+ }
+
+ again:
+ 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;
+ foundsig = NULL;
+ empty_node = ISC_TRUE;
+ for (header = node->data;
+ header != NULL;
+ header = header_next) {
+ header_next = header->next;
+ /*
+ * Look for an active, extant NSEC or RRSIG NSEC.
+ */
+ do {
+ if (header->serial <= search->serial &&
+ !IGNORE(header)) {
+ /*
+ * Is this a "this rdataset doesn't
+ * exist" record?
+ */
+ if (NONEXISTENT(header))
+ header = NULL;
+ break;
+ } else
+ header = header->down;
+ } while (header != NULL);
+ if (header != NULL) {
+ /*
+ * We now know that there is at least one
+ * active rdataset at this node.
+ */
+ empty_node = ISC_FALSE;
+ if (header->type == type) {
+ found = header;
+ if (foundsig != NULL)
+ break;
+ } else if (header->type == sigtype) {
+ foundsig = header;
+ if (found != NULL)
+ break;
+ }
+ }
+ }
+ if (!empty_node) {
+ if (found != NULL && search->rbtversion->havensec3 &&
+ found->type == dns_rdatatype_nsec3 &&
+ !matchparams(found, search)) {
+ empty_node = ISC_TRUE;
+ found = NULL;
+ foundsig = NULL;
+ result = dns_rbtnodechain_prev(&search->chain,
+ NULL, NULL);
+ } else if (found != NULL &&
+ (foundsig != NULL || !need_sig))
+ {
+ /*
+ * We've found the right NSEC/NSEC3 record.
+ *
+ * Note: for this to really be the right
+ * NSEC record, it's essential that the NSEC
+ * records of any nodes obscured by a zone
+ * cut have been removed; we assume this is
+ * the case.
+ */
+ result = dns_name_concatenate(name, origin,
+ foundname, NULL);
+ if (result == ISC_R_SUCCESS) {
+ if (nodep != NULL) {
+ new_reference(search->rbtdb,
+ node);
+ *nodep = node;
+ }
+ bind_rdataset(search->rbtdb, node,
+ found, search->now,
+ rdataset);
+ if (foundsig != NULL)
+ bind_rdataset(search->rbtdb,
+ node,
+ foundsig,
+ search->now,
+ sigrdataset);
+ }
+ } else if (found == NULL && foundsig == NULL) {
+ /*
+ * This node is active, but has no NSEC or
+ * RRSIG NSEC. That means it's glue or
+ * other obscured zone data that isn't
+ * relevant for our search. Treat the
+ * node as if it were empty and keep looking.
+ */
+ empty_node = ISC_TRUE;
+ result = dns_rbtnodechain_prev(&search->chain,
+ NULL, NULL);
+ } else {
+ /*
+ * We found an active node, but either the
+ * NSEC or the RRSIG NSEC is missing. This
+ * shouldn't happen.
+ */
+ result = DNS_R_BADDB;
+ }
+ } else {
+ /*
+ * This node isn't active. We've got to keep
+ * looking.
+ */
+ result = dns_rbtnodechain_prev(&search->chain, NULL,
+ NULL);
+ }
+ NODE_UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+ } while (empty_node && result == ISC_R_SUCCESS);
+
+ if (result == ISC_R_NOMORE && wraps) {
+ result = dns_rbtnodechain_last(&search->chain, tree,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
+ wraps = ISC_FALSE;
+ goto again;
+ }
+ }
+
+ /*
+ * If the result is ISC_R_NOMORE, then we got to the beginning of
+ * the database and didn't find a NSEC record. This shouldn't
+ * happen.
+ */
+ if (result == ISC_R_NOMORE)
+ result = DNS_R_BADDB;
+
+ return (result);
+}
+
+static isc_result_t
+zone_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_rbtnode_t *node = NULL;
+ isc_result_t result;
+ rbtdb_search_t search;
+ isc_boolean_t cname_ok = ISC_TRUE;
+ isc_boolean_t close_version = ISC_FALSE;
+ isc_boolean_t maybe_zonecut = ISC_FALSE;
+ isc_boolean_t at_zonecut = ISC_FALSE;
+ isc_boolean_t wild;
+ isc_boolean_t empty_node;
+ rdatasetheader_t *header, *header_next, *found, *nsecheader;
+ rdatasetheader_t *foundsig, *cnamesig, *nsecsig;
+ rbtdb_rdatatype_t sigtype;
+ isc_boolean_t active;
+ dns_rbtnodechain_t chain;
+ nodelock_t *lock;
+ dns_rbt_t *tree;
+
+ search.rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(search.rbtdb));
+
+ /*
+ * We don't care about 'now'.
+ */
+ UNUSED(now);
+
+ /*
+ * If the caller didn't supply a version, attach to the current
+ * version.
+ */
+ if (version == NULL) {
+ currentversion(db, &version);
+ close_version = ISC_TRUE;
+ }
+
+ search.rbtversion = version;
+ search.serial = search.rbtversion->serial;
+ search.options = options;
+ search.copy_name = ISC_FALSE;
+ search.need_cleanup = ISC_FALSE;
+ search.wild = ISC_FALSE;
+ search.zonecut = NULL;
+ dns_fixedname_init(&search.zonecut_name);
+ dns_rbtnodechain_init(&search.chain, search.rbtdb->common.mctx);
+ search.now = 0;
+
+ /*
+ * 'wild' will be true iff. we've matched a wildcard.
+ */
+ wild = ISC_FALSE;
+
+ RWLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read);
+
+ /*
+ * Search down from the root of the tree. If, while going down, we
+ * encounter a callback node, zone_zonecut_callback() will search the
+ * rdatasets at the zone cut for active DNAME or NS rdatasets.
+ */
+ tree = (options & DNS_DBFIND_FORCENSEC3) != 0 ? search.rbtdb->nsec3 :
+ search.rbtdb->tree;
+ result = dns_rbt_findnode(tree, name, foundname, &node,
+ &search.chain, DNS_RBTFIND_EMPTYDATA,
+ zone_zonecut_callback, &search);
+
+ if (result == DNS_R_PARTIALMATCH) {
+ partial_match:
+ if (search.zonecut != NULL) {
+ result = setup_delegation(&search, nodep, foundname,
+ rdataset, sigrdataset);
+ goto tree_exit;
+ }
+
+ if (search.wild) {
+ /*
+ * At least one of the levels in the search chain
+ * potentially has a wildcard. For each such level,
+ * we must see if there's a matching wildcard active
+ * in the current version.
+ */
+ result = find_wildcard(&search, &node, name);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_name_copy(name, foundname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto tree_exit;
+ wild = ISC_TRUE;
+ goto found;
+ }
+ else if (result != ISC_R_NOTFOUND)
+ goto tree_exit;
+ }
+
+ chain = search.chain;
+ active = activeempty(&search, &chain, name);
+
+ /*
+ * If we're here, then the name does not exist, is not
+ * beneath a zonecut, and there's no matching wildcard.
+ */
+ if ((search.rbtversion->secure == dns_db_secure &&
+ !search.rbtversion->havensec3) ||
+ (search.options & DNS_DBFIND_FORCENSEC) != 0 ||
+ (search.options & DNS_DBFIND_FORCENSEC3) != 0)
+ {
+ result = find_closest_nsec(&search, nodep, foundname,
+ rdataset, sigrdataset, tree,
+ search.rbtversion->secure);
+ if (result == ISC_R_SUCCESS)
+ result = active ? DNS_R_EMPTYNAME :
+ DNS_R_NXDOMAIN;
+ } else
+ result = active ? DNS_R_EMPTYNAME : DNS_R_NXDOMAIN;
+ goto tree_exit;
+ } else if (result != ISC_R_SUCCESS)
+ goto tree_exit;
+
+ found:
+ /*
+ * We have found a node whose name is the desired name, or we
+ * have matched a wildcard.
+ */
+
+ if (search.zonecut != NULL) {
+ /*
+ * If we're beneath a zone cut, we don't want to look for
+ * CNAMEs because they're not legitimate zone glue.
+ */
+ cname_ok = ISC_FALSE;
+ } else {
+ /*
+ * The node may be a zone cut itself. If it might be one,
+ * make sure we check for it later.
+ */
+ if (node->find_callback &&
+ (node != search.rbtdb->origin_node ||
+ IS_STUB(search.rbtdb)) &&
+ !dns_rdatatype_atparent(type))
+ maybe_zonecut = ISC_TRUE;
+ }
+
+ /*
+ * Certain DNSSEC types are not subject to CNAME matching
+ * (RFC4035, section 2.5 and RFC3007).
+ *
+ * We don't check for RRSIG, because we don't store RRSIG records
+ * directly.
+ */
+ if (type == dns_rdatatype_key || type == dns_rdatatype_nsec)
+ cname_ok = ISC_FALSE;
+
+ /*
+ * We now go looking for rdata...
+ */
+
+ NODE_LOCK(&(search.rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+
+ found = NULL;
+ foundsig = NULL;
+ sigtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, type);
+ nsecheader = NULL;
+ nsecsig = NULL;
+ cnamesig = NULL;
+ empty_node = ISC_TRUE;
+ for (header = node->data; header != NULL; header = header_next) {
+ header_next = header->next;
+ /*
+ * Look for an active, extant rdataset.
+ */
+ do {
+ if (header->serial <= search.serial &&
+ !IGNORE(header)) {
+ /*
+ * Is this a "this rdataset doesn't
+ * exist" record?
+ */
+ if (NONEXISTENT(header))
+ header = NULL;
+ break;
+ } else
+ header = header->down;
+ } while (header != NULL);
+ if (header != NULL) {
+ /*
+ * We now know that there is at least one active
+ * rdataset at this node.
+ */
+ empty_node = ISC_FALSE;
+
+ /*
+ * Do special zone cut handling, if requested.
+ */
+ if (maybe_zonecut &&
+ header->type == dns_rdatatype_ns) {
+ /*
+ * We increment the reference count on node to
+ * ensure that search->zonecut_rdataset will
+ * still be valid later.
+ */
+ new_reference(search.rbtdb, node);
+ search.zonecut = node;
+ search.zonecut_rdataset = header;
+ search.zonecut_sigrdataset = NULL;
+ search.need_cleanup = ISC_TRUE;
+ maybe_zonecut = ISC_FALSE;
+ at_zonecut = ISC_TRUE;
+ /*
+ * It is not clear if KEY should still be
+ * allowed at the parent side of the zone
+ * cut or not. It is needed for RFC3007
+ * validated updates.
+ */
+ if ((search.options & DNS_DBFIND_GLUEOK) == 0
+ && type != dns_rdatatype_nsec
+ && type != dns_rdatatype_key) {
+ /*
+ * Glue is not OK, but any answer we
+ * could return would be glue. Return
+ * the delegation.
+ */
+ found = NULL;
+ break;
+ }
+ if (found != NULL && foundsig != NULL)
+ break;
+ }
+
+
+ /*
+ * If the NSEC3 record doesn't match the chain
+ * we are using behave as if it isn't here.
+ */
+ if (header->type == dns_rdatatype_nsec3 &&
+ !matchparams(header, &search))
+ goto partial_match;
+ /*
+ * If we found a type we were looking for,
+ * remember it.
+ */
+ if (header->type == type ||
+ type == dns_rdatatype_any ||
+ (header->type == dns_rdatatype_cname &&
+ cname_ok)) {
+ /*
+ * We've found the answer!
+ */
+ found = header;
+ if (header->type == dns_rdatatype_cname &&
+ cname_ok) {
+ /*
+ * We may be finding a CNAME instead
+ * of the desired type.
+ *
+ * If we've already got the CNAME RRSIG,
+ * use it, otherwise change sigtype
+ * so that we find it.
+ */
+ if (cnamesig != NULL)
+ foundsig = cnamesig;
+ else
+ sigtype =
+ RBTDB_RDATATYPE_SIGCNAME;
+ }
+ /*
+ * If we've got all we need, end the search.
+ */
+ if (!maybe_zonecut && foundsig != NULL)
+ break;
+ } else if (header->type == sigtype) {
+ /*
+ * We've found the RRSIG rdataset for our
+ * target type. Remember it.
+ */
+ foundsig = header;
+ /*
+ * If we've got all we need, end the search.
+ */
+ if (!maybe_zonecut && found != NULL)
+ break;
+ } else if (header->type == dns_rdatatype_nsec &&
+ !search.rbtversion->havensec3) {
+ /*
+ * Remember a NSEC rdataset even if we're
+ * not specifically looking for it, because
+ * we might need it later.
+ */
+ nsecheader = header;
+ } else if (header->type == RBTDB_RDATATYPE_SIGNSEC &&
+ !search.rbtversion->havensec3) {
+ /*
+ * If we need the NSEC rdataset, we'll also
+ * need its signature.
+ */
+ nsecsig = header;
+ } else if (cname_ok &&
+ header->type == RBTDB_RDATATYPE_SIGCNAME) {
+ /*
+ * If we get a CNAME match, we'll also need
+ * its signature.
+ */
+ cnamesig = header;
+ }
+ }
+ }
+
+ if (empty_node) {
+ /*
+ * We have an exact match for the name, but there are no
+ * active rdatasets in the desired version. That means that
+ * this node doesn't exist in the desired version, and that
+ * we really have a partial match.
+ */
+ if (!wild) {
+ lock = &search.rbtdb->node_locks[node->locknum].lock;
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
+ goto partial_match;
+ }
+ }
+
+ /*
+ * If we didn't find what we were looking for...
+ */
+ if (found == NULL) {
+ if (search.zonecut != NULL) {
+ /*
+ * We were trying to find glue at a node beneath a
+ * zone cut, but didn't.
+ *
+ * Return the delegation.
+ */
+ lock = &search.rbtdb->node_locks[node->locknum].lock;
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
+ result = setup_delegation(&search, nodep, foundname,
+ rdataset, sigrdataset);
+ goto tree_exit;
+ }
+ /*
+ * The desired type doesn't exist.
+ */
+ result = DNS_R_NXRRSET;
+ if (search.rbtversion->secure == dns_db_secure &&
+ !search.rbtversion->havensec3 &&
+ (nsecheader == NULL || nsecsig == NULL)) {
+ /*
+ * The zone is secure but there's no NSEC,
+ * or the NSEC has no signature!
+ */
+ if (!wild) {
+ result = DNS_R_BADDB;
+ goto node_exit;
+ }
+
+ lock = &search.rbtdb->node_locks[node->locknum].lock;
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
+ result = find_closest_nsec(&search, nodep, foundname,
+ rdataset, sigrdataset,
+ search.rbtdb->tree,
+ search.rbtversion->secure);
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_EMPTYWILD;
+ goto tree_exit;
+ }
+ if ((search.options & DNS_DBFIND_FORCENSEC) != 0 &&
+ nsecheader == NULL)
+ {
+ /*
+ * There's no NSEC record, and we were told
+ * to find one.
+ */
+ result = DNS_R_BADDB;
+ goto node_exit;
+ }
+ if (nodep != NULL) {
+ new_reference(search.rbtdb, node);
+ *nodep = node;
+ }
+ if ((search.rbtversion->secure == dns_db_secure &&
+ !search.rbtversion->havensec3) ||
+ (search.options & DNS_DBFIND_FORCENSEC) != 0)
+ {
+ bind_rdataset(search.rbtdb, node, nsecheader,
+ 0, rdataset);
+ if (nsecsig != NULL)
+ bind_rdataset(search.rbtdb, node,
+ nsecsig, 0, sigrdataset);
+ }
+ if (wild)
+ foundname->attributes |= DNS_NAMEATTR_WILDCARD;
+ goto node_exit;
+ }
+
+ /*
+ * We found what we were looking for, or we found a CNAME.
+ */
+
+ if (type != found->type &&
+ type != dns_rdatatype_any &&
+ found->type == dns_rdatatype_cname) {
+ /*
+ * We weren't doing an ANY query and we found a CNAME instead
+ * of the type we were looking for, so we need to indicate
+ * that result to the caller.
+ */
+ result = DNS_R_CNAME;
+ } else if (search.zonecut != NULL) {
+ /*
+ * If we're beneath a zone cut, we must indicate that the
+ * result is glue, unless we're actually at the zone cut
+ * and the type is NSEC or KEY.
+ */
+ if (search.zonecut == node) {
+ /*
+ * It is not clear if KEY should still be
+ * allowed at the parent side of the zone
+ * cut or not. It is needed for RFC3007
+ * validated updates.
+ */
+ if (type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3 ||
+ type == dns_rdatatype_key)
+ result = ISC_R_SUCCESS;
+ else if (type == dns_rdatatype_any)
+ result = DNS_R_ZONECUT;
+ else
+ result = DNS_R_GLUE;
+ } else
+ result = DNS_R_GLUE;
+ /*
+ * We might have found data that isn't glue, but was occluded
+ * by a dynamic update. If the caller cares about this, they
+ * will have told us to validate glue.
+ *
+ * XXX We should cache the glue validity state!
+ */
+ if (result == DNS_R_GLUE &&
+ (search.options & DNS_DBFIND_VALIDATEGLUE) != 0 &&
+ !valid_glue(&search, foundname, type, node)) {
+ lock = &search.rbtdb->node_locks[node->locknum].lock;
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
+ result = setup_delegation(&search, nodep, foundname,
+ rdataset, sigrdataset);
+ goto tree_exit;
+ }
+ } else {
+ /*
+ * An ordinary successful query!
+ */
+ result = ISC_R_SUCCESS;
+ }
+
+ if (nodep != NULL) {
+ if (!at_zonecut)
+ new_reference(search.rbtdb, node);
+ else
+ search.need_cleanup = ISC_FALSE;
+ *nodep = node;
+ }
+
+ if (type != dns_rdatatype_any) {
+ bind_rdataset(search.rbtdb, node, found, 0, rdataset);
+ if (foundsig != NULL)
+ bind_rdataset(search.rbtdb, node, foundsig, 0,
+ sigrdataset);
+ }
+
+ if (wild)
+ foundname->attributes |= DNS_NAMEATTR_WILDCARD;
+
+ node_exit:
+ NODE_UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock),
+ isc_rwlocktype_read);
+
+ tree_exit:
+ RWUNLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read);
+
+ /*
+ * If we found a zonecut but aren't going to use it, we have to
+ * let go of it.
+ */
+ if (search.need_cleanup) {
+ node = search.zonecut;
+ lock = &(search.rbtdb->node_locks[node->locknum].lock);
+
+ NODE_LOCK(lock, isc_rwlocktype_read);
+ decrement_reference(search.rbtdb, node, 0,
+ isc_rwlocktype_read, isc_rwlocktype_none);
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
+ }
+
+ if (close_version)
+ closeversion(db, &version, ISC_FALSE);
+
+ dns_rbtnodechain_reset(&search.chain);
+
+ return (result);
+}
+
+static isc_result_t
+zone_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)
+{
+ UNUSED(db);
+ UNUSED(name);
+ UNUSED(options);
+ UNUSED(now);
+ UNUSED(nodep);
+ UNUSED(foundname);
+ UNUSED(rdataset);
+ UNUSED(sigrdataset);
+
+ FATAL_ERROR(__FILE__, __LINE__, "zone_findzonecut() called!");
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t
+cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
+ rbtdb_search_t *search = arg;
+ rdatasetheader_t *header, *header_prev, *header_next;
+ rdatasetheader_t *dname_header, *sigdname_header;
+ isc_result_t result;
+ nodelock_t *lock;
+ isc_rwlocktype_t locktype;
+
+ /* XXX comment */
+
+ REQUIRE(search->zonecut == NULL);
+
+ /*
+ * Keep compiler silent.
+ */
+ UNUSED(name);
+
+ lock = &(search->rbtdb->node_locks[node->locknum].lock);
+ locktype = isc_rwlocktype_read;
+ NODE_LOCK(lock, locktype);
+
+ /*
+ * Look for a DNAME or RRSIG DNAME rdataset.
+ */
+ dname_header = NULL;
+ sigdname_header = NULL;
+ header_prev = NULL;
+ for (header = node->data; header != NULL; header = header_next) {
+ header_next = header->next;
+ if (header->rdh_ttl <= search->now) {
+ /*
+ * This rdataset is stale. If no one else is
+ * using the node, we can clean it up right
+ * now, otherwise we mark it as stale, and
+ * the node as dirty, so it will get cleaned
+ * up later.
+ */
+ if ((header->rdh_ttl <= search->now - RBTDB_VIRTUAL) &&
+ (locktype == isc_rwlocktype_write ||
+ NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
+ /*
+ * We update the node's status only when we
+ * can get write access; otherwise, we leave
+ * others to this work. Periodical cleaning
+ * will eventually take the job as the last
+ * resort.
+ * We won't downgrade the lock, since other
+ * rdatasets are probably stale, too.
+ */
+ locktype = isc_rwlocktype_write;
+
+ if (dns_rbtnode_refcurrent(node) == 0) {
+ isc_mem_t *mctx;
+
+ /*
+ * header->down can be non-NULL if the
+ * refcount has just decremented to 0
+ * but decrement_reference() has not
+ * performed clean_cache_node(), in
+ * which case we need to purge the
+ * stale headers first.
+ */
+ mctx = search->rbtdb->common.mctx;
+ clean_stale_headers(search->rbtdb,
+ mctx,
+ header);
+ if (header_prev != NULL)
+ header_prev->next =
+ header->next;
+ else
+ node->data = header->next;
+ free_rdataset(search->rbtdb, mctx,
+ header);
+ } else {
+ header->attributes |=
+ RDATASET_ATTR_STALE;
+ node->dirty = 1;
+ header_prev = header;
+ }
+ } else
+ header_prev = header;
+ } else if (header->type == dns_rdatatype_dname &&
+ EXISTS(header)) {
+ dname_header = header;
+ header_prev = header;
+ } else if (header->type == RBTDB_RDATATYPE_SIGDNAME &&
+ EXISTS(header)) {
+ sigdname_header = header;
+ header_prev = header;
+ } else
+ header_prev = header;
+ }
+
+ if (dname_header != NULL &&
+ (dname_header->trust != dns_trust_pending ||
+ (search->options & DNS_DBFIND_PENDINGOK) != 0)) {
+ /*
+ * We increment the reference count on node to ensure that
+ * search->zonecut_rdataset will still be valid later.
+ */
+ new_reference(search->rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
+ search->zonecut = node;
+ search->zonecut_rdataset = dname_header;
+ search->zonecut_sigrdataset = sigdname_header;
+ search->need_cleanup = ISC_TRUE;
+ result = DNS_R_PARTIALMATCH;
+ } else
+ result = DNS_R_CONTINUE;
+
+ NODE_UNLOCK(lock, locktype);
+
+ return (result);
+}
+
+static inline isc_result_t
+find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node,
+ dns_dbnode_t **nodep, dns_name_t *foundname,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ unsigned int i;
+ dns_rbtnode_t *level_node;
+ rdatasetheader_t *header, *header_prev, *header_next;
+ rdatasetheader_t *found, *foundsig;
+ isc_result_t result = ISC_R_NOTFOUND;
+ dns_name_t name;
+ dns_rbtdb_t *rbtdb;
+ isc_boolean_t done;
+ nodelock_t *lock;
+ isc_rwlocktype_t locktype;
+
+ /*
+ * Caller must be holding the tree lock.
+ */
+
+ rbtdb = search->rbtdb;
+ i = search->chain.level_matches;
+ done = ISC_FALSE;
+ do {
+ locktype = isc_rwlocktype_read;
+ lock = &rbtdb->node_locks[node->locknum].lock;
+ NODE_LOCK(lock, locktype);
+
+ /*
+ * Look for NS and RRSIG NS rdatasets.
+ */
+ found = NULL;
+ foundsig = NULL;
+ header_prev = NULL;
+ for (header = node->data;
+ header != NULL;
+ header = header_next) {
+ header_next = header->next;
+ if (header->rdh_ttl <= search->now) {
+ /*
+ * This rdataset is stale. If no one else is
+ * using the node, we can clean it up right
+ * now, otherwise we mark it as stale, and
+ * the node as dirty, so it will get cleaned
+ * up later.
+ */
+ if ((header->rdh_ttl <= search->now -
+ RBTDB_VIRTUAL) &&
+ (locktype == isc_rwlocktype_write ||
+ NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
+ /*
+ * We update the node's status only
+ * when we can get write access.
+ */
+ locktype = isc_rwlocktype_write;
+
+ if (dns_rbtnode_refcurrent(node)
+ == 0) {
+ isc_mem_t *m;
+
+ m = search->rbtdb->common.mctx;
+ clean_stale_headers(
+ search->rbtdb,
+ m, header);
+ if (header_prev != NULL)
+ header_prev->next =
+ header->next;
+ else
+ node->data =
+ header->next;
+ free_rdataset(rbtdb, m,
+ header);
+ } else {
+ header->attributes |=
+ RDATASET_ATTR_STALE;
+ node->dirty = 1;
+ header_prev = header;
+ }
+ } else
+ header_prev = header;
+ } else if (EXISTS(header)) {
+ /*
+ * We've found an extant rdataset. See if
+ * we're interested in it.
+ */
+ if (header->type == dns_rdatatype_ns) {
+ found = header;
+ if (foundsig != NULL)
+ break;
+ } else if (header->type ==
+ RBTDB_RDATATYPE_SIGNS) {
+ foundsig = header;
+ if (found != NULL)
+ break;
+ }
+ header_prev = header;
+ } else
+ header_prev = header;
+ }
+
+ if (found != NULL) {
+ /*
+ * If we have to set foundname, we do it before
+ * anything else. If we were to set foundname after
+ * we had set nodep or bound the rdataset, then we'd
+ * have to undo that work if dns_name_concatenate()
+ * failed. By setting foundname first, there's
+ * nothing to undo if we have trouble.
+ */
+ if (foundname != NULL) {
+ dns_name_init(&name, NULL);
+ dns_rbt_namefromnode(node, &name);
+ result = dns_name_copy(&name, foundname, NULL);
+ while (result == ISC_R_SUCCESS && i > 0) {
+ i--;
+ level_node = search->chain.levels[i];
+ dns_name_init(&name, NULL);
+ dns_rbt_namefromnode(level_node,
+ &name);
+ result =
+ dns_name_concatenate(foundname,
+ &name,
+ foundname,
+ NULL);
+ }
+ if (result != ISC_R_SUCCESS) {
+ *nodep = NULL;
+ goto node_exit;
+ }
+ }
+ result = DNS_R_DELEGATION;
+ if (nodep != NULL) {
+ new_reference(search->rbtdb, node);
+ *nodep = node;
+ }
+ bind_rdataset(search->rbtdb, node, found, search->now,
+ rdataset);
+ if (foundsig != NULL)
+ bind_rdataset(search->rbtdb, node, foundsig,
+ search->now, sigrdataset);
+ if (need_headerupdate(found, search->now) ||
+ (foundsig != NULL &&
+ need_headerupdate(foundsig, search->now))) {
+ if (locktype != isc_rwlocktype_write) {
+ NODE_UNLOCK(lock, locktype);
+ NODE_LOCK(lock, isc_rwlocktype_write);
+ locktype = isc_rwlocktype_write;
+ }
+ if (need_headerupdate(found, search->now))
+ update_header(search->rbtdb, found,
+ search->now);
+ if (foundsig != NULL &&
+ need_headerupdate(foundsig, search->now)) {
+ update_header(search->rbtdb, foundsig,
+ search->now);
+ }
+ }
+ }
+
+ node_exit:
+ NODE_UNLOCK(lock, locktype);
+
+ if (found == NULL && i > 0) {
+ i--;
+ node = search->chain.levels[i];
+ } else
+ done = ISC_TRUE;
+
+ } while (!done);
+
+ return (result);
+}
+
+static isc_result_t
+find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
+ isc_stdtime_t now, dns_name_t *foundname,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ dns_rbtnode_t *node;
+ rdatasetheader_t *header, *header_next, *header_prev;
+ rdatasetheader_t *found, *foundsig;
+ isc_boolean_t empty_node;
+ isc_result_t result;
+ dns_fixedname_t fname, forigin;
+ dns_name_t *name, *origin;
+ rbtdb_rdatatype_t matchtype, sigmatchtype;
+ nodelock_t *lock;
+ isc_rwlocktype_t locktype;
+
+ matchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_nsec, 0);
+ sigmatchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig,
+ dns_rdatatype_nsec);
+
+ 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);
+ locktype = isc_rwlocktype_read;
+ lock = &(search->rbtdb->node_locks[node->locknum].lock);
+ NODE_LOCK(lock, locktype);
+ found = NULL;
+ foundsig = NULL;
+ empty_node = ISC_TRUE;
+ header_prev = NULL;
+ for (header = node->data;
+ header != NULL;
+ header = header_next) {
+ header_next = header->next;
+ if (header->rdh_ttl <= now) {
+ /*
+ * This rdataset is stale. If no one else is
+ * using the node, we can clean it up right
+ * now, otherwise we mark it as stale, and the
+ * node as dirty, so it will get cleaned up
+ * later.
+ */
+ if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
+ (locktype == isc_rwlocktype_write ||
+ NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
+ /*
+ * We update the node's status only
+ * when we can get write access.
+ */
+ locktype = isc_rwlocktype_write;
+
+ if (dns_rbtnode_refcurrent(node)
+ == 0) {
+ isc_mem_t *m;
+
+ m = search->rbtdb->common.mctx;
+ clean_stale_headers(
+ search->rbtdb,
+ m, header);
+ if (header_prev != NULL)
+ header_prev->next =
+ header->next;
+ else
+ node->data = header->next;
+ free_rdataset(search->rbtdb, m,
+ header);
+ } else {
+ header->attributes |=
+ RDATASET_ATTR_STALE;
+ node->dirty = 1;
+ header_prev = header;
+ }
+ } else
+ header_prev = header;
+ continue;
+ }
+ if (NONEXISTENT(header) ||
+ RBTDB_RDATATYPE_BASE(header->type) == 0) {
+ header_prev = header;
+ continue;
+ }
+ empty_node = ISC_FALSE;
+ if (header->type == matchtype)
+ found = header;
+ else if (header->type == sigmatchtype)
+ foundsig = header;
+ header_prev = header;
+ }
+ if (found != NULL) {
+ result = dns_name_concatenate(name, origin,
+ foundname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto unlock_node;
+ bind_rdataset(search->rbtdb, node, found,
+ now, rdataset);
+ if (foundsig != NULL)
+ bind_rdataset(search->rbtdb, node, foundsig,
+ now, sigrdataset);
+ new_reference(search->rbtdb, node);
+ *nodep = node;
+ result = DNS_R_COVERINGNSEC;
+ } else if (!empty_node) {
+ result = ISC_R_NOTFOUND;
+ } else
+ result = dns_rbtnodechain_prev(&search->chain, NULL,
+ NULL);
+ unlock_node:
+ NODE_UNLOCK(lock, locktype);
+ } while (empty_node && result == ISC_R_SUCCESS);
+ return (result);
+}
+
+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,
+ dns_dbnode_t **nodep, dns_name_t *foundname,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ dns_rbtnode_t *node = NULL;
+ isc_result_t result;
+ rbtdb_search_t search;
+ isc_boolean_t cname_ok = ISC_TRUE;
+ isc_boolean_t empty_node;
+ nodelock_t *lock;
+ isc_rwlocktype_t locktype;
+ rdatasetheader_t *header, *header_prev, *header_next;
+ rdatasetheader_t *found, *nsheader;
+ rdatasetheader_t *foundsig, *nssig, *cnamesig;
+ rdatasetheader_t *update, *updatesig;
+ rbtdb_rdatatype_t sigtype, negtype;
+
+ UNUSED(version);
+
+ search.rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(search.rbtdb));
+ REQUIRE(version == NULL);
+
+ if (now == 0)
+ isc_stdtime_get(&now);
+
+ search.rbtversion = NULL;
+ search.serial = 1;
+ search.options = options;
+ search.copy_name = ISC_FALSE;
+ search.need_cleanup = ISC_FALSE;
+ search.wild = ISC_FALSE;
+ search.zonecut = NULL;
+ dns_fixedname_init(&search.zonecut_name);
+ dns_rbtnodechain_init(&search.chain, search.rbtdb->common.mctx);
+ search.now = now;
+ update = NULL;
+ updatesig = NULL;
+
+ RWLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read);
+
+ /*
+ * Search down from the root of the tree. If, while going down, we
+ * encounter a callback node, cache_zonecut_callback() will search the
+ * rdatasets at the zone cut for a DNAME rdataset.
+ */
+ result = dns_rbt_findnode(search.rbtdb->tree, name, foundname, &node,
+ &search.chain, DNS_RBTFIND_EMPTYDATA,
+ cache_zonecut_callback, &search);
+
+ if (result == DNS_R_PARTIALMATCH) {
+ if ((search.options & DNS_DBFIND_COVERINGNSEC) != 0) {
+ result = find_coveringnsec(&search, nodep, now,
+ foundname, rdataset,
+ sigrdataset);
+ if (result == DNS_R_COVERINGNSEC)
+ goto tree_exit;
+ }
+ if (search.zonecut != NULL) {
+ result = setup_delegation(&search, nodep, foundname,
+ rdataset, sigrdataset);
+ goto tree_exit;
+ } else {
+ find_ns:
+ result = find_deepest_zonecut(&search, node, nodep,
+ foundname, rdataset,
+ sigrdataset);
+ goto tree_exit;
+ }
+ } else if (result != ISC_R_SUCCESS)
+ goto tree_exit;
+
+ /*
+ * Certain DNSSEC types are not subject to CNAME matching
+ * (RFC4035, section 2.5 and RFC3007).
+ *
+ * We don't check for RRSIG, because we don't store RRSIG records
+ * directly.
+ */
+ if (type == dns_rdatatype_key || type == dns_rdatatype_nsec)
+ cname_ok = ISC_FALSE;
+
+ /*
+ * We now go looking for rdata...
+ */
+
+ lock = &(search.rbtdb->node_locks[node->locknum].lock);
+ locktype = isc_rwlocktype_read;
+ NODE_LOCK(lock, locktype);
+
+ found = NULL;
+ foundsig = NULL;
+ sigtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, type);
+ negtype = RBTDB_RDATATYPE_VALUE(0, type);
+ nsheader = NULL;
+ nssig = NULL;
+ cnamesig = NULL;
+ empty_node = ISC_TRUE;
+ header_prev = NULL;
+ for (header = node->data; header != NULL; header = header_next) {
+ header_next = header->next;
+ if (header->rdh_ttl <= now) {
+ /*
+ * This rdataset is stale. If no one else is using the
+ * node, we can clean it up right now, otherwise we
+ * mark it as stale, and the node as dirty, so it will
+ * get cleaned up later.
+ */
+ if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
+ (locktype == isc_rwlocktype_write ||
+ NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
+ /*
+ * We update the node's status only when we
+ * can get write access.
+ */
+ locktype = isc_rwlocktype_write;
+
+ if (dns_rbtnode_refcurrent(node) == 0) {
+ isc_mem_t *mctx;
+
+ mctx = search.rbtdb->common.mctx;
+ clean_stale_headers(search.rbtdb, mctx,
+ header);
+ if (header_prev != NULL)
+ header_prev->next =
+ header->next;
+ else
+ node->data = header->next;
+ free_rdataset(search.rbtdb, mctx,
+ header);
+ } else {
+ header->attributes |=
+ RDATASET_ATTR_STALE;
+ node->dirty = 1;
+ header_prev = header;
+ }
+ } else
+ header_prev = header;
+ } else if (EXISTS(header)) {
+ /*
+ * We now know that there is at least one active
+ * non-stale rdataset at this node.
+ */
+ empty_node = ISC_FALSE;
+
+ /*
+ * If we found a type we were looking for, remember
+ * it.
+ */
+ if (header->type == type ||
+ (type == dns_rdatatype_any &&
+ RBTDB_RDATATYPE_BASE(header->type) != 0) ||
+ (cname_ok && header->type ==
+ dns_rdatatype_cname)) {
+ /*
+ * We've found the answer.
+ */
+ found = header;
+ if (header->type == dns_rdatatype_cname &&
+ cname_ok &&
+ cnamesig != NULL) {
+ /*
+ * If we've already got the CNAME RRSIG,
+ * use it, otherwise change sigtype
+ * so that we find it.
+ */
+ if (cnamesig != NULL)
+ foundsig = cnamesig;
+ else
+ sigtype =
+ RBTDB_RDATATYPE_SIGCNAME;
+ foundsig = cnamesig;
+ }
+ } else if (header->type == sigtype) {
+ /*
+ * We've found the RRSIG rdataset for our
+ * target type. Remember it.
+ */
+ foundsig = header;
+ } else if (header->type == RBTDB_RDATATYPE_NCACHEANY ||
+ header->type == negtype) {
+ /*
+ * We've found a negative cache entry.
+ */
+ found = header;
+ } else if (header->type == dns_rdatatype_ns) {
+ /*
+ * Remember a NS rdataset even if we're
+ * not specifically looking for it, because
+ * we might need it later.
+ */
+ nsheader = header;
+ } else if (header->type == RBTDB_RDATATYPE_SIGNS) {
+ /*
+ * If we need the NS rdataset, we'll also
+ * need its signature.
+ */
+ nssig = header;
+ } else if (cname_ok &&
+ header->type == RBTDB_RDATATYPE_SIGCNAME) {
+ /*
+ * If we get a CNAME match, we'll also need
+ * its signature.
+ */
+ cnamesig = header;
+ }
+ header_prev = header;
+ } else
+ header_prev = header;
+ }
+
+ if (empty_node) {
+ /*
+ * We have an exact match for the name, but there are no
+ * extant rdatasets. That means that this node doesn't
+ * meaningfully exist, and that we really have a partial match.
+ */
+ NODE_UNLOCK(lock, locktype);
+ goto find_ns;
+ }
+
+ /*
+ * If we didn't find what we were looking for...
+ */
+ if (found == NULL ||
+ (found->trust == dns_trust_glue &&
+ ((options & DNS_DBFIND_GLUEOK) == 0)) ||
+ (found->trust == dns_trust_pending &&
+ ((options & DNS_DBFIND_PENDINGOK) == 0))) {
+ /*
+ * If there is an NS rdataset at this node, then this is the
+ * deepest zone cut.
+ */
+ if (nsheader != NULL) {
+ if (nodep != NULL) {
+ new_reference(search.rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
+ *nodep = node;
+ }
+ bind_rdataset(search.rbtdb, node, nsheader, search.now,
+ rdataset);
+ if (need_headerupdate(nsheader, search.now))
+ update = nsheader;
+ if (nssig != NULL) {
+ bind_rdataset(search.rbtdb, node, nssig,
+ search.now, sigrdataset);
+ if (need_headerupdate(nssig, search.now))
+ updatesig = nssig;
+ }
+ result = DNS_R_DELEGATION;
+ goto node_exit;
+ }
+
+ /*
+ * Go find the deepest zone cut.
+ */
+ NODE_UNLOCK(lock, locktype);
+ goto find_ns;
+ }
+
+ /*
+ * We found what we were looking for, or we found a CNAME.
+ */
+
+ if (nodep != NULL) {
+ new_reference(search.rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
+ *nodep = node;
+ }
+
+ if (RBTDB_RDATATYPE_BASE(found->type) == 0) {
+ /*
+ * We found a negative cache entry.
+ */
+ if (NXDOMAIN(found))
+ result = DNS_R_NCACHENXDOMAIN;
+ else
+ result = DNS_R_NCACHENXRRSET;
+ } else if (type != found->type &&
+ type != dns_rdatatype_any &&
+ found->type == dns_rdatatype_cname) {
+ /*
+ * We weren't doing an ANY query and we found a CNAME instead
+ * of the type we were looking for, so we need to indicate
+ * that result to the caller.
+ */
+ result = DNS_R_CNAME;
+ } else {
+ /*
+ * An ordinary successful query!
+ */
+ result = ISC_R_SUCCESS;
+ }
+
+ if (type != dns_rdatatype_any || result == DNS_R_NCACHENXDOMAIN ||
+ result == DNS_R_NCACHENXRRSET) {
+ bind_rdataset(search.rbtdb, node, found, search.now,
+ rdataset);
+ if (need_headerupdate(found, search.now))
+ update = found;
+ if (foundsig != NULL) {
+ bind_rdataset(search.rbtdb, node, foundsig, search.now,
+ sigrdataset);
+ if (need_headerupdate(foundsig, search.now))
+ updatesig = foundsig;
+ }
+ }
+
+ node_exit:
+ if ((update != NULL || updatesig != NULL) &&
+ locktype != isc_rwlocktype_write) {
+ NODE_UNLOCK(lock, locktype);
+ NODE_LOCK(lock, isc_rwlocktype_write);
+ locktype = isc_rwlocktype_write;
+ }
+ if (update != NULL && need_headerupdate(update, search.now))
+ update_header(search.rbtdb, update, search.now);
+ if (updatesig != NULL && need_headerupdate(updatesig, search.now))
+ update_header(search.rbtdb, updatesig, search.now);
+
+ NODE_UNLOCK(lock, locktype);
+
+ tree_exit:
+ RWUNLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read);
+
+ /*
+ * If we found a zonecut but aren't going to use it, we have to
+ * let go of it.
+ */
+ if (search.need_cleanup) {
+ node = search.zonecut;
+ lock = &(search.rbtdb->node_locks[node->locknum].lock);
+
+ NODE_LOCK(lock, isc_rwlocktype_read);
+ decrement_reference(search.rbtdb, node, 0,
+ isc_rwlocktype_read, isc_rwlocktype_none);
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
+ }
+
+ dns_rbtnodechain_reset(&search.chain);
+
+ return (result);
+}
+
+static isc_result_t
+cache_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_rbtnode_t *node = NULL;
+ nodelock_t *lock;
+ isc_result_t result;
+ rbtdb_search_t search;
+ rdatasetheader_t *header, *header_prev, *header_next;
+ rdatasetheader_t *found, *foundsig;
+ unsigned int rbtoptions = DNS_RBTFIND_EMPTYDATA;
+ isc_rwlocktype_t locktype;
+
+ search.rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(search.rbtdb));
+
+ if (now == 0)
+ isc_stdtime_get(&now);
+
+ search.rbtversion = NULL;
+ search.serial = 1;
+ search.options = options;
+ search.copy_name = ISC_FALSE;
+ search.need_cleanup = ISC_FALSE;
+ search.wild = ISC_FALSE;
+ search.zonecut = NULL;
+ dns_fixedname_init(&search.zonecut_name);
+ dns_rbtnodechain_init(&search.chain, search.rbtdb->common.mctx);
+ search.now = now;
+
+ if ((options & DNS_DBFIND_NOEXACT) != 0)
+ rbtoptions |= DNS_RBTFIND_NOEXACT;
+
+ RWLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read);
+
+ /*
+ * Search down from the root of the tree.
+ */
+ result = dns_rbt_findnode(search.rbtdb->tree, name, foundname, &node,
+ &search.chain, rbtoptions, NULL, &search);
+
+ if (result == DNS_R_PARTIALMATCH) {
+ find_ns:
+ result = find_deepest_zonecut(&search, node, nodep, foundname,
+ rdataset, sigrdataset);
+ goto tree_exit;
+ } else if (result != ISC_R_SUCCESS)
+ goto tree_exit;
+
+ /*
+ * We now go looking for an NS rdataset at the node.
+ */
+
+ lock = &(search.rbtdb->node_locks[node->locknum].lock);
+ locktype = isc_rwlocktype_read;
+ NODE_LOCK(lock, locktype);
+
+ found = NULL;
+ foundsig = NULL;
+ header_prev = NULL;
+ for (header = node->data; header != NULL; header = header_next) {
+ header_next = header->next;
+ if (header->rdh_ttl <= now) {
+ /*
+ * This rdataset is stale. If no one else is using the
+ * node, we can clean it up right now, otherwise we
+ * mark it as stale, and the node as dirty, so it will
+ * get cleaned up later.
+ */
+ if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
+ (locktype == isc_rwlocktype_write ||
+ NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
+ /*
+ * We update the node's status only when we
+ * can get write access.
+ */
+ locktype = isc_rwlocktype_write;
+
+ if (dns_rbtnode_refcurrent(node) == 0) {
+ isc_mem_t *mctx;
+
+ mctx = search.rbtdb->common.mctx;
+ clean_stale_headers(search.rbtdb, mctx,
+ header);
+ if (header_prev != NULL)
+ header_prev->next =
+ header->next;
+ else
+ node->data = header->next;
+ free_rdataset(search.rbtdb, mctx,
+ header);
+ } else {
+ header->attributes |=
+ RDATASET_ATTR_STALE;
+ node->dirty = 1;
+ header_prev = header;
+ }
+ } else
+ header_prev = header;
+ } else if (EXISTS(header)) {
+ /*
+ * If we found a type we were looking for, remember
+ * it.
+ */
+ if (header->type == dns_rdatatype_ns) {
+ /*
+ * Remember a NS rdataset even if we're
+ * not specifically looking for it, because
+ * we might need it later.
+ */
+ found = header;
+ } else if (header->type == RBTDB_RDATATYPE_SIGNS) {
+ /*
+ * If we need the NS rdataset, we'll also
+ * need its signature.
+ */
+ foundsig = header;
+ }
+ header_prev = header;
+ } else
+ header_prev = header;
+ }
+
+ if (found == NULL) {
+ /*
+ * No NS records here.
+ */
+ NODE_UNLOCK(lock, locktype);
+ goto find_ns;
+ }
+
+ if (nodep != NULL) {
+ new_reference(search.rbtdb, node);
+ INSIST(!ISC_LINK_LINKED(node, deadlink));
+ *nodep = node;
+ }
+
+ bind_rdataset(search.rbtdb, node, found, search.now, rdataset);
+ if (foundsig != NULL)
+ bind_rdataset(search.rbtdb, node, foundsig, search.now,
+ sigrdataset);
+
+ if (need_headerupdate(found, search.now) ||
+ (foundsig != NULL && need_headerupdate(foundsig, search.now))) {
+ if (locktype != isc_rwlocktype_write) {
+ NODE_UNLOCK(lock, locktype);
+ NODE_LOCK(lock, isc_rwlocktype_write);
+ locktype = isc_rwlocktype_write;
+ }
+ if (need_headerupdate(found, search.now))
+ update_header(search.rbtdb, found, search.now);
+ if (foundsig != NULL &&
+ need_headerupdate(foundsig, search.now)) {
+ update_header(search.rbtdb, foundsig, search.now);
+ }
+ }
+
+ NODE_UNLOCK(lock, locktype);
+
+ tree_exit:
+ RWUNLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read);
+
+ INSIST(!search.need_cleanup);
+
+ dns_rbtnodechain_reset(&search.chain);
+
+ if (result == DNS_R_DELEGATION)
+ result = ISC_R_SUCCESS;
+
+ return (result);
+}
+
+static void
+attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *node = (dns_rbtnode_t *)source;
+ unsigned int refs;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
+ dns_rbtnode_refincrement(node, &refs);
+ INSIST(refs != 0);
+ NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
+
+ *targetp = source;
+}
+
+static void
+detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *node;
+ isc_boolean_t want_free = ISC_FALSE;
+ isc_boolean_t inactive = ISC_FALSE;
+ rbtdb_nodelock_t *nodelock;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(targetp != NULL && *targetp != NULL);
+
+ node = (dns_rbtnode_t *)(*targetp);
+ nodelock = &rbtdb->node_locks[node->locknum];
+
+ NODE_LOCK(&nodelock->lock, isc_rwlocktype_read);
+
+ if (decrement_reference(rbtdb, node, 0, isc_rwlocktype_read,
+ isc_rwlocktype_none)) {
+ if (isc_refcount_current(&nodelock->references) == 0 &&
+ nodelock->exiting) {
+ inactive = ISC_TRUE;
+ }
+ }
+
+ NODE_UNLOCK(&nodelock->lock, isc_rwlocktype_read);
+
+ *targetp = NULL;
+
+ if (inactive) {
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
+ rbtdb->active--;
+ if (rbtdb->active == 0)
+ want_free = ISC_TRUE;
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
+ if (want_free) {
+ char buf[DNS_NAME_FORMATSIZE];
+ if (dns_name_dynamic(&rbtdb->common.origin))
+ dns_name_format(&rbtdb->common.origin, buf,
+ sizeof(buf));
+ else
+ strcpy(buf, "<UNKNOWN>");
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
+ "calling free_rbtdb(%s)", buf);
+ free_rbtdb(rbtdb, ISC_TRUE, NULL);
+ }
+ }
+}
+
+static isc_result_t
+expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *rbtnode = node;
+ rdatasetheader_t *header;
+ isc_boolean_t force_expire = ISC_FALSE;
+ /*
+ * These are the category and module used by the cache cleaner.
+ */
+ isc_boolean_t log = ISC_FALSE;
+ isc_logcategory_t *category = DNS_LOGCATEGORY_DATABASE;
+ isc_logmodule_t *module = DNS_LOGMODULE_CACHE;
+ int level = ISC_LOG_DEBUG(2);
+ char printname[DNS_NAME_FORMATSIZE];
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ /*
+ * Caller must hold a tree lock.
+ */
+
+ if (now == 0)
+ isc_stdtime_get(&now);
+
+ if (rbtdb->overmem) {
+ isc_uint32_t val;
+
+ isc_random_get(&val);
+ /*
+ * XXXDCL Could stand to have a better policy, like LRU.
+ */
+ force_expire = ISC_TF(rbtnode->down == NULL && val % 4 == 0);
+
+ /*
+ * Note that 'log' can be true IFF rbtdb->overmem is also true.
+ * rbtdb->ovemem can currently only be true for cache databases
+ * -- hence all of the "overmem cache" log strings.
+ */
+ log = ISC_TF(isc_log_wouldlog(dns_lctx, level));
+ if (log)
+ isc_log_write(dns_lctx, category, module, level,
+ "overmem cache: %s %s",
+ force_expire ? "FORCE" : "check",
+ dns_rbt_formatnodename(rbtnode,
+ printname,
+ sizeof(printname)));
+ }
+
+ /*
+ * We may not need write access, but this code path is not performance
+ * sensitive, so it should be okay to always lock as a writer.
+ */
+ NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_write);
+
+ for (header = rbtnode->data; header != NULL; header = header->next)
+ if (header->rdh_ttl <= now - RBTDB_VIRTUAL) {
+ /*
+ * We don't check if refcurrent(rbtnode) == 0 and try
+ * to free like we do in cache_find(), because
+ * refcurrent(rbtnode) must be non-zero. This is so
+ * because 'node' is an argument to the function.
+ */
+ header->attributes |= RDATASET_ATTR_STALE;
+ rbtnode->dirty = 1;
+ if (log)
+ isc_log_write(dns_lctx, category, module,
+ level, "overmem cache: stale %s",
+ printname);
+ } else if (force_expire) {
+ if (! RETAIN(header)) {
+ set_ttl(rbtdb, header, 0);
+ header->attributes |= RDATASET_ATTR_STALE;
+ rbtnode->dirty = 1;
+ } else if (log) {
+ isc_log_write(dns_lctx, category, module,
+ level, "overmem cache: "
+ "reprieve by RETAIN() %s",
+ printname);
+ }
+ } else if (rbtdb->overmem && log)
+ isc_log_write(dns_lctx, category, module, level,
+ "overmem cache: saved %s", printname);
+
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_write);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+overmem(dns_db_t *db, isc_boolean_t overmem) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+
+ if (IS_CACHE(rbtdb))
+ rbtdb->overmem = overmem;
+}
+
+static void
+printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *rbtnode = node;
+ isc_boolean_t first;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_read);
+
+ fprintf(out, "node %p, %u references, locknum = %u\n",
+ rbtnode, dns_rbtnode_refcurrent(rbtnode),
+ rbtnode->locknum);
+ if (rbtnode->data != NULL) {
+ rdatasetheader_t *current, *top_next;
+
+ for (current = rbtnode->data; current != NULL;
+ current = top_next) {
+ top_next = current->next;
+ first = ISC_TRUE;
+ fprintf(out, "\ttype %u", current->type);
+ do {
+ if (!first)
+ fprintf(out, "\t");
+ first = ISC_FALSE;
+ fprintf(out,
+ "\tserial = %lu, ttl = %u, "
+ "trust = %u, attributes = %u, "
+ "resign = %u\n",
+ (unsigned long)current->serial,
+ current->rdh_ttl,
+ current->trust,
+ current->attributes,
+ current->resign);
+ current = current->down;
+ } while (current != NULL);
+ }
+ } else
+ fprintf(out, "(empty)\n");
+
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_read);
+}
+
+static isc_result_t
+createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ rbtdb_dbiterator_t *rbtdbiter;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ rbtdbiter = isc_mem_get(rbtdb->common.mctx, sizeof(*rbtdbiter));
+ if (rbtdbiter == NULL)
+ return (ISC_R_NOMEMORY);
+
+ rbtdbiter->common.methods = &dbiterator_methods;
+ rbtdbiter->common.db = NULL;
+ dns_db_attach(db, &rbtdbiter->common.db);
+ rbtdbiter->common.relative_names =
+ ISC_TF((options & DNS_DB_RELATIVENAMES) != 0);
+ rbtdbiter->common.magic = DNS_DBITERATOR_MAGIC;
+ rbtdbiter->common.cleaning = ISC_FALSE;
+ rbtdbiter->paused = ISC_TRUE;
+ rbtdbiter->tree_locked = isc_rwlocktype_none;
+ rbtdbiter->result = ISC_R_SUCCESS;
+ dns_fixedname_init(&rbtdbiter->name);
+ dns_fixedname_init(&rbtdbiter->origin);
+ rbtdbiter->node = NULL;
+ rbtdbiter->delete = 0;
+ rbtdbiter->nsec3only = ISC_TF((options & DNS_DB_NSEC3ONLY) != 0);
+ rbtdbiter->nonsec3 = ISC_TF((options & DNS_DB_NONSEC3) != 0);
+ memset(rbtdbiter->deletions, 0, sizeof(rbtdbiter->deletions));
+ dns_rbtnodechain_init(&rbtdbiter->chain, db->mctx);
+ dns_rbtnodechain_init(&rbtdbiter->nsec3chain, db->mctx);
+ if (rbtdbiter->nsec3only)
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ else
+ rbtdbiter->current = &rbtdbiter->chain;
+
+ *iteratorp = (dns_dbiterator_t *)rbtdbiter;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+zone_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
+ rdatasetheader_t *header, *header_next, *found, *foundsig;
+ rbtdb_serial_t serial;
+ rbtdb_version_t *rbtversion = version;
+ isc_boolean_t close_version = ISC_FALSE;
+ rbtdb_rdatatype_t matchtype, sigmatchtype;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(type != dns_rdatatype_any);
+
+ if (rbtversion == NULL) {
+ currentversion(db, (dns_dbversion_t **) (void *)(&rbtversion));
+ close_version = ISC_TRUE;
+ }
+ serial = rbtversion->serial;
+ now = 0;
+
+ NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_read);
+
+ found = NULL;
+ foundsig = NULL;
+ matchtype = RBTDB_RDATATYPE_VALUE(type, covers);
+ if (covers == 0)
+ sigmatchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, type);
+ else
+ sigmatchtype = 0;
+
+ for (header = rbtnode->data; header != NULL; header = header_next) {
+ header_next = header->next;
+ do {
+ if (header->serial <= serial &&
+ !IGNORE(header)) {
+ /*
+ * Is this a "this rdataset doesn't
+ * exist" record?
+ */
+ if (NONEXISTENT(header))
+ header = NULL;
+ break;
+ } else
+ header = header->down;
+ } while (header != NULL);
+ if (header != NULL) {
+ /*
+ * We have an active, extant rdataset. If it's a
+ * type we're looking for, remember it.
+ */
+ if (header->type == matchtype) {
+ found = header;
+ if (foundsig != NULL)
+ break;
+ } else if (header->type == sigmatchtype) {
+ foundsig = header;
+ if (found != NULL)
+ break;
+ }
+ }
+ }
+ if (found != NULL) {
+ bind_rdataset(rbtdb, rbtnode, found, now, rdataset);
+ if (foundsig != NULL)
+ bind_rdataset(rbtdb, rbtnode, foundsig, now,
+ sigrdataset);
+ }
+
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_read);
+
+ if (close_version)
+ closeversion(db, (dns_dbversion_t **) (void *)(&rbtversion),
+ ISC_FALSE);
+
+ if (found == NULL)
+ return (ISC_R_NOTFOUND);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
+ rdatasetheader_t *header, *header_next, *found, *foundsig;
+ rbtdb_rdatatype_t matchtype, sigmatchtype, negtype;
+ isc_result_t result;
+ nodelock_t *lock;
+ isc_rwlocktype_t locktype;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(type != dns_rdatatype_any);
+
+ UNUSED(version);
+
+ result = ISC_R_SUCCESS;
+
+ if (now == 0)
+ isc_stdtime_get(&now);
+
+ lock = &rbtdb->node_locks[rbtnode->locknum].lock;
+ locktype = isc_rwlocktype_read;
+ NODE_LOCK(lock, locktype);
+
+ found = NULL;
+ foundsig = NULL;
+ matchtype = RBTDB_RDATATYPE_VALUE(type, covers);
+ negtype = RBTDB_RDATATYPE_VALUE(0, type);
+ if (covers == 0)
+ sigmatchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, type);
+ else
+ sigmatchtype = 0;
+
+ for (header = rbtnode->data; header != NULL; header = header_next) {
+ header_next = header->next;
+ if (header->rdh_ttl <= now) {
+ if ((header->rdh_ttl <= now - RBTDB_VIRTUAL) &&
+ (locktype == isc_rwlocktype_write ||
+ NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
+ /*
+ * We update the node's status only when we
+ * can get write access.
+ */
+ locktype = isc_rwlocktype_write;
+
+ /*
+ * We don't check if refcurrent(rbtnode) == 0
+ * and try to free like we do in cache_find(),
+ * because refcurrent(rbtnode) must be
+ * non-zero. This is so because 'node' is an
+ * argument to the function.
+ */
+ header->attributes |= RDATASET_ATTR_STALE;
+ rbtnode->dirty = 1;
+ }
+ } else if (EXISTS(header)) {
+ if (header->type == matchtype)
+ found = header;
+ else if (header->type == RBTDB_RDATATYPE_NCACHEANY ||
+ header->type == negtype)
+ found = header;
+ else if (header->type == sigmatchtype)
+ foundsig = header;
+ }
+ }
+ if (found != NULL) {
+ bind_rdataset(rbtdb, rbtnode, found, now, rdataset);
+ if (foundsig != NULL)
+ bind_rdataset(rbtdb, rbtnode, foundsig, now,
+ sigrdataset);
+ }
+
+ NODE_UNLOCK(lock, locktype);
+
+ if (found == NULL)
+ return (ISC_R_NOTFOUND);
+
+ if (RBTDB_RDATATYPE_BASE(found->type) == 0) {
+ /*
+ * We found a negative cache entry.
+ */
+ if (NXDOMAIN(found))
+ result = DNS_R_NCACHENXDOMAIN;
+ else
+ result = DNS_R_NCACHENXRRSET;
+ }
+
+ return (result);
+}
+
+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_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
+ rbtdb_version_t *rbtversion = version;
+ rbtdb_rdatasetiter_t *iterator;
+ unsigned int refs;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ iterator = isc_mem_get(rbtdb->common.mctx, sizeof(*iterator));
+ if (iterator == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if ((db->attributes & DNS_DBATTR_CACHE) == 0) {
+ now = 0;
+ if (rbtversion == NULL)
+ currentversion(db,
+ (dns_dbversion_t **) (void *)(&rbtversion));
+ else {
+ unsigned int refs;
+
+ isc_refcount_increment(&rbtversion->references,
+ &refs);
+ INSIST(refs > 1);
+ }
+ } else {
+ if (now == 0)
+ isc_stdtime_get(&now);
+ rbtversion = NULL;
+ }
+
+ iterator->common.magic = DNS_RDATASETITER_MAGIC;
+ iterator->common.methods = &rdatasetiter_methods;
+ iterator->common.db = db;
+ iterator->common.node = node;
+ iterator->common.version = (dns_dbversion_t *)rbtversion;
+ iterator->common.now = now;
+
+ NODE_STRONGLOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
+
+ dns_rbtnode_refincrement(rbtnode, &refs);
+ INSIST(refs != 0);
+
+ iterator->current = NULL;
+
+ NODE_STRONGUNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock);
+
+ *iteratorp = (dns_rdatasetiter_t *)iterator;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+cname_and_other_data(dns_rbtnode_t *node, rbtdb_serial_t serial) {
+ rdatasetheader_t *header, *header_next;
+ isc_boolean_t cname, other_data;
+ dns_rdatatype_t rdtype;
+
+ /*
+ * The caller must hold the node lock.
+ */
+
+ /*
+ * Look for CNAME and "other data" rdatasets active in our version.
+ */
+ cname = ISC_FALSE;
+ other_data = ISC_FALSE;
+ for (header = node->data; header != NULL; header = header_next) {
+ header_next = header->next;
+ if (header->type == dns_rdatatype_cname) {
+ /*
+ * Look for an active extant CNAME.
+ */
+ do {
+ if (header->serial <= serial &&
+ !IGNORE(header)) {
+ /*
+ * Is this a "this rdataset doesn't
+ * exist" record?
+ */
+ if (NONEXISTENT(header))
+ header = NULL;
+ break;
+ } else
+ header = header->down;
+ } while (header != NULL);
+ if (header != NULL)
+ cname = ISC_TRUE;
+ } else {
+ /*
+ * Look for active extant "other data".
+ *
+ * "Other data" is any rdataset whose type is not
+ * KEY, RRSIG KEY, NSEC, RRSIG NSEC or RRSIG CNAME.
+ */
+ rdtype = RBTDB_RDATATYPE_BASE(header->type);
+ if (rdtype == dns_rdatatype_rrsig ||
+ rdtype == dns_rdatatype_sig)
+ rdtype = RBTDB_RDATATYPE_EXT(header->type);
+ if (rdtype != dns_rdatatype_nsec &&
+ rdtype != dns_rdatatype_key &&
+ rdtype != dns_rdatatype_cname) {
+ /*
+ * We've found a type that isn't
+ * NSEC, KEY, CNAME, or one of their
+ * signatures. Is it active and extant?
+ */
+ do {
+ if (header->serial <= serial &&
+ !IGNORE(header)) {
+ /*
+ * Is this a "this rdataset
+ * doesn't exist" record?
+ */
+ if (NONEXISTENT(header))
+ header = NULL;
+ break;
+ } else
+ header = header->down;
+ } while (header != NULL);
+ if (header != NULL)
+ other_data = ISC_TRUE;
+ }
+ }
+ }
+
+ if (cname && other_data)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader) {
+ isc_result_t result;
+
+ INSIST(newheader->heap_index == 0);
+ INSIST(!ISC_LINK_LINKED(newheader, lru_link));
+ result = isc_heap_insert(rbtdb->heaps[idx], newheader);
+ return (result);
+}
+
+static isc_result_t
+add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
+ rdatasetheader_t *newheader, unsigned int options, isc_boolean_t loading,
+ dns_rdataset_t *addedrdataset, isc_stdtime_t now)
+{
+ rbtdb_changed_t *changed = NULL;
+ rdatasetheader_t *topheader, *topheader_prev, *header;
+ unsigned char *merged;
+ isc_result_t result;
+ isc_boolean_t header_nx;
+ isc_boolean_t newheader_nx;
+ isc_boolean_t merge;
+ dns_rdatatype_t rdtype, covers;
+ rbtdb_rdatatype_t negtype;
+ dns_trust_t trust;
+ int idx;
+
+ /*
+ * Add an rdatasetheader_t to a node.
+ */
+
+ /*
+ * Caller must be holding the node lock.
+ */
+
+ if ((options & DNS_DBADD_MERGE) != 0) {
+ REQUIRE(rbtversion != NULL);
+ merge = ISC_TRUE;
+ } else
+ merge = ISC_FALSE;
+
+ if ((options & DNS_DBADD_FORCE) != 0)
+ trust = dns_trust_ultimate;
+ else
+ trust = newheader->trust;
+
+ if (rbtversion != NULL && !loading) {
+ /*
+ * We always add a changed record, even if no changes end up
+ * being made to this node, because it's harmless and
+ * simplifies the code.
+ */
+ changed = add_changed(rbtdb, rbtversion, rbtnode);
+ if (changed == NULL) {
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ return (ISC_R_NOMEMORY);
+ }
+ }
+
+ newheader_nx = NONEXISTENT(newheader) ? ISC_TRUE : ISC_FALSE;
+ topheader_prev = NULL;
+
+ negtype = 0;
+ if (rbtversion == NULL && !newheader_nx) {
+ rdtype = RBTDB_RDATATYPE_BASE(newheader->type);
+ if (rdtype == 0) {
+ /*
+ * We're adding a negative cache entry.
+ */
+ covers = RBTDB_RDATATYPE_EXT(newheader->type);
+ if (covers == dns_rdatatype_any) {
+ /*
+ * We're adding an negative cache entry
+ * which covers all types (NXDOMAIN,
+ * NODATA(QTYPE=ANY)).
+ *
+ * We make all other data stale so that the
+ * only rdataset that can be found at this
+ * node is the negative cache entry.
+ */
+ for (topheader = rbtnode->data;
+ topheader != NULL;
+ topheader = topheader->next) {
+ set_ttl(rbtdb, topheader, 0);
+ topheader->attributes |=
+ RDATASET_ATTR_STALE;
+ }
+ rbtnode->dirty = 1;
+ goto find_header;
+ }
+ negtype = RBTDB_RDATATYPE_VALUE(covers, 0);
+ } else {
+ /*
+ * We're adding something that isn't a
+ * negative cache entry. Look for an extant
+ * non-stale NXDOMAIN/NODATA(QTYPE=ANY) negative
+ * cache entry.
+ */
+ for (topheader = rbtnode->data;
+ topheader != NULL;
+ topheader = topheader->next) {
+ if (topheader->type ==
+ RBTDB_RDATATYPE_NCACHEANY)
+ break;
+ }
+ if (topheader != NULL && EXISTS(topheader) &&
+ topheader->rdh_ttl > now) {
+ /*
+ * Found one.
+ */
+ if (trust < topheader->trust) {
+ /*
+ * The NXDOMAIN/NODATA(QTYPE=ANY)
+ * is more trusted.
+ */
+ free_rdataset(rbtdb,
+ rbtdb->common.mctx,
+ newheader);
+ if (addedrdataset != NULL)
+ bind_rdataset(rbtdb, rbtnode,
+ topheader, now,
+ addedrdataset);
+ return (DNS_R_UNCHANGED);
+ }
+ /*
+ * The new rdataset is better. Expire the
+ * NXDOMAIN/NODATA(QTYPE=ANY).
+ */
+ set_ttl(rbtdb, topheader, 0);
+ topheader->attributes |= RDATASET_ATTR_STALE;
+ rbtnode->dirty = 1;
+ topheader = NULL;
+ goto find_header;
+ }
+ negtype = RBTDB_RDATATYPE_VALUE(0, rdtype);
+ }
+ }
+
+ for (topheader = rbtnode->data;
+ topheader != NULL;
+ topheader = topheader->next) {
+ if (topheader->type == newheader->type ||
+ topheader->type == negtype)
+ break;
+ topheader_prev = topheader;
+ }
+
+ find_header:
+ /*
+ * If header isn't NULL, we've found the right type. There may be
+ * IGNORE rdatasets between the top of the chain and the first real
+ * data. We skip over them.
+ */
+ header = topheader;
+ while (header != NULL && IGNORE(header))
+ header = header->down;
+ if (header != NULL) {
+ header_nx = NONEXISTENT(header) ? ISC_TRUE : ISC_FALSE;
+
+ /*
+ * Deleting an already non-existent rdataset has no effect.
+ */
+ if (header_nx && newheader_nx) {
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ return (DNS_R_UNCHANGED);
+ }
+
+ /*
+ * Trying to add an rdataset with lower trust to a cache DB
+ * has no effect, provided that the cache data isn't stale.
+ */
+ if (rbtversion == NULL && trust < header->trust &&
+ (header->rdh_ttl > now || header_nx)) {
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ if (addedrdataset != NULL)
+ bind_rdataset(rbtdb, rbtnode, header, now,
+ addedrdataset);
+ return (DNS_R_UNCHANGED);
+ }
+
+ /*
+ * Don't merge if a nonexistent rdataset is involved.
+ */
+ if (merge && (header_nx || newheader_nx))
+ merge = ISC_FALSE;
+
+ /*
+ * If 'merge' is ISC_TRUE, we'll try to create a new rdataset
+ * that is the union of 'newheader' and 'header'.
+ */
+ if (merge) {
+ unsigned int flags = 0;
+ INSIST(rbtversion->serial >= header->serial);
+ merged = NULL;
+ result = ISC_R_SUCCESS;
+
+ if ((options & DNS_DBADD_EXACT) != 0)
+ flags |= DNS_RDATASLAB_EXACT;
+ if ((options & DNS_DBADD_EXACTTTL) != 0 &&
+ newheader->rdh_ttl != header->rdh_ttl)
+ result = DNS_R_NOTEXACT;
+ else if (newheader->rdh_ttl != header->rdh_ttl)
+ flags |= DNS_RDATASLAB_FORCE;
+ if (result == ISC_R_SUCCESS)
+ result = dns_rdataslab_merge(
+ (unsigned char *)header,
+ (unsigned char *)newheader,
+ (unsigned int)(sizeof(*newheader)),
+ rbtdb->common.mctx,
+ rbtdb->common.rdclass,
+ (dns_rdatatype_t)header->type,
+ flags, &merged);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * If 'header' has the same serial number as
+ * we do, we could clean it up now if we knew
+ * that our caller had no references to it.
+ * We don't know this, however, so we leave it
+ * alone. It will get cleaned up when
+ * clean_zone_node() runs.
+ */
+ free_rdataset(rbtdb, rbtdb->common.mctx,
+ newheader);
+ newheader = (rdatasetheader_t *)merged;
+ if (loading && RESIGN(newheader) &&
+ RESIGN(header) &&
+ header->resign < newheader->resign)
+ newheader->resign = header->resign;
+ } else {
+ free_rdataset(rbtdb, rbtdb->common.mctx,
+ newheader);
+ return (result);
+ }
+ }
+ /*
+ * Don't replace existing NS, A and AAAA RRsets
+ * in the cache if they are already exist. This
+ * prevents named being locked to old servers.
+ * Don't lower trust of existing record if the
+ * update is forced.
+ */
+ if (IS_CACHE(rbtdb) && header->rdh_ttl > now &&
+ header->type == dns_rdatatype_ns &&
+ !header_nx && !newheader_nx &&
+ header->trust >= newheader->trust &&
+ dns_rdataslab_equalx((unsigned char *)header,
+ (unsigned char *)newheader,
+ (unsigned int)(sizeof(*newheader)),
+ rbtdb->common.rdclass,
+ (dns_rdatatype_t)header->type)) {
+ /*
+ * Honour the new ttl if it is less than the
+ * older one.
+ */
+ if (header->rdh_ttl > newheader->rdh_ttl)
+ set_ttl(rbtdb, header, newheader->rdh_ttl);
+ if (header->noqname == NULL &&
+ newheader->noqname != NULL) {
+ header->noqname = newheader->noqname;
+ newheader->noqname = NULL;
+ }
+ if (header->closest == NULL &&
+ newheader->closest != NULL) {
+ header->closest = newheader->closest;
+ newheader->closest = NULL;
+ }
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ if (addedrdataset != NULL)
+ bind_rdataset(rbtdb, rbtnode, header, now,
+ addedrdataset);
+ return (ISC_R_SUCCESS);
+ }
+ if (IS_CACHE(rbtdb) && header->rdh_ttl > now &&
+ (header->type == dns_rdatatype_a ||
+ header->type == dns_rdatatype_aaaa) &&
+ !header_nx && !newheader_nx &&
+ header->trust >= newheader->trust &&
+ dns_rdataslab_equal((unsigned char *)header,
+ (unsigned char *)newheader,
+ (unsigned int)(sizeof(*newheader)))) {
+ /*
+ * Honour the new ttl if it is less than the
+ * older one.
+ */
+ if (header->rdh_ttl > newheader->rdh_ttl)
+ set_ttl(rbtdb, header, newheader->rdh_ttl);
+ if (header->noqname == NULL &&
+ newheader->noqname != NULL) {
+ header->noqname = newheader->noqname;
+ newheader->noqname = NULL;
+ }
+ if (header->closest == NULL &&
+ newheader->closest != NULL) {
+ header->closest = newheader->closest;
+ newheader->closest = NULL;
+ }
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ if (addedrdataset != NULL)
+ bind_rdataset(rbtdb, rbtnode, header, now,
+ addedrdataset);
+ return (ISC_R_SUCCESS);
+ }
+ INSIST(rbtversion == NULL ||
+ rbtversion->serial >= topheader->serial);
+ if (topheader_prev != NULL)
+ topheader_prev->next = newheader;
+ else
+ rbtnode->data = newheader;
+ newheader->next = topheader->next;
+ if (loading) {
+ /*
+ * There are no other references to 'header' when
+ * loading, so we MAY clean up 'header' now.
+ * Since we don't generate changed records when
+ * loading, we MUST clean up 'header' now.
+ */
+ newheader->down = NULL;
+ free_rdataset(rbtdb, rbtdb->common.mctx, header);
+ } else {
+ newheader->down = topheader;
+ topheader->next = newheader;
+ rbtnode->dirty = 1;
+ if (changed != NULL)
+ changed->dirty = ISC_TRUE;
+ if (rbtversion == NULL) {
+ set_ttl(rbtdb, header, 0);
+ header->attributes |= RDATASET_ATTR_STALE;
+ }
+ idx = newheader->node->locknum;
+ if (IS_CACHE(rbtdb)) {
+ ISC_LIST_PREPEND(rbtdb->rdatasets[idx],
+ newheader, lru_link);
+ /*
+ * XXXMLG We don't check the return value
+ * here. If it fails, we will not do TTL
+ * based expiry on this node. However, we
+ * will do it on the LRU side, so memory
+ * will not leak... for long.
+ */
+ isc_heap_insert(rbtdb->heaps[idx], newheader);
+ } else if (RESIGN(newheader))
+ resign_insert(rbtdb, idx, newheader);
+ }
+ } else {
+ /*
+ * No non-IGNORED rdatasets of the given type exist at
+ * this node.
+ */
+
+ /*
+ * If we're trying to delete the type, don't bother.
+ */
+ if (newheader_nx) {
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ return (DNS_R_UNCHANGED);
+ }
+
+ if (topheader != NULL) {
+ /*
+ * We have an list of rdatasets of the given type,
+ * but they're all marked IGNORE. We simply insert
+ * the new rdataset at the head of the list.
+ *
+ * Ignored rdatasets cannot occur during loading, so
+ * we INSIST on it.
+ */
+ INSIST(!loading);
+ INSIST(rbtversion == NULL ||
+ rbtversion->serial >= topheader->serial);
+ if (topheader_prev != NULL)
+ topheader_prev->next = newheader;
+ else
+ rbtnode->data = newheader;
+ newheader->next = topheader->next;
+ newheader->down = topheader;
+ topheader->next = newheader;
+ rbtnode->dirty = 1;
+ if (changed != NULL)
+ changed->dirty = ISC_TRUE;
+ } else {
+ /*
+ * No rdatasets of the given type exist at the node.
+ */
+ newheader->next = rbtnode->data;
+ newheader->down = NULL;
+ rbtnode->data = newheader;
+ }
+ idx = newheader->node->locknum;
+ if (IS_CACHE(rbtdb)) {
+ ISC_LIST_PREPEND(rbtdb->rdatasets[idx],
+ newheader, lru_link);
+ isc_heap_insert(rbtdb->heaps[idx], newheader);
+ } else if (RESIGN(newheader)) {
+ resign_insert(rbtdb, idx, newheader);
+ }
+ }
+
+ /*
+ * Check if the node now contains CNAME and other data.
+ */
+ if (rbtversion != NULL &&
+ cname_and_other_data(rbtnode, rbtversion->serial))
+ return (DNS_R_CNAMEANDOTHER);
+
+ if (addedrdataset != NULL)
+ bind_rdataset(rbtdb, rbtnode, newheader, now, addedrdataset);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_boolean_t
+delegating_type(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
+ rbtdb_rdatatype_t type)
+{
+ if (IS_CACHE(rbtdb)) {
+ if (type == dns_rdatatype_dname)
+ return (ISC_TRUE);
+ else
+ return (ISC_FALSE);
+ } else if (type == dns_rdatatype_dname ||
+ (type == dns_rdatatype_ns &&
+ (node != rbtdb->origin_node || IS_STUB(rbtdb))))
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+static inline isc_result_t
+addnoqname(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
+ dns_rdataset_t *rdataset)
+{
+ struct noqname *noqname;
+ isc_mem_t *mctx = rbtdb->common.mctx;
+ dns_name_t name;
+ dns_rdataset_t neg, negsig;
+ isc_result_t result;
+ isc_region_t r;
+
+ dns_name_init(&name, NULL);
+ dns_rdataset_init(&neg);
+ dns_rdataset_init(&negsig);
+
+ result = dns_rdataset_getnoqname(rdataset, &name, &neg, &negsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ noqname = isc_mem_get(mctx, sizeof(*noqname));
+ if (noqname == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ dns_name_init(&noqname->name, NULL);
+ noqname->neg = NULL;
+ noqname->negsig = NULL;
+ noqname->type = neg.type;
+ result = dns_name_dup(&name, mctx, &noqname->name);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_rdataslab_fromrdataset(&neg, mctx, &r, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ noqname->neg = r.base;
+ result = dns_rdataslab_fromrdataset(&negsig, mctx, &r, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ noqname->negsig = r.base;
+ dns_rdataset_disassociate(&neg);
+ dns_rdataset_disassociate(&negsig);
+ newheader->noqname = noqname;
+ return (ISC_R_SUCCESS);
+
+cleanup:
+ dns_rdataset_disassociate(&neg);
+ dns_rdataset_disassociate(&negsig);
+ free_noqname(mctx, &noqname);
+ return(result);
+}
+
+static inline isc_result_t
+addclosest(dns_rbtdb_t *rbtdb, rdatasetheader_t *newheader,
+ dns_rdataset_t *rdataset)
+{
+ struct noqname *closest;
+ isc_mem_t *mctx = rbtdb->common.mctx;
+ dns_name_t name;
+ dns_rdataset_t neg, negsig;
+ isc_result_t result;
+ isc_region_t r;
+
+ dns_name_init(&name, NULL);
+ dns_rdataset_init(&neg);
+ dns_rdataset_init(&negsig);
+
+ result = dns_rdataset_getclosest(rdataset, &name, &neg, &negsig);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ closest = isc_mem_get(mctx, sizeof(*closest));
+ if (closest == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ dns_name_init(&closest->name, NULL);
+ closest->neg = NULL;
+ closest->negsig = NULL;
+ closest->type = neg.type;
+ result = dns_name_dup(&name, mctx, &closest->name);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_rdataslab_fromrdataset(&neg, mctx, &r, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ closest->neg = r.base;
+ result = dns_rdataslab_fromrdataset(&negsig, mctx, &r, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ closest->negsig = r.base;
+ dns_rdataset_disassociate(&neg);
+ dns_rdataset_disassociate(&negsig);
+ newheader->closest = closest;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_rdataset_disassociate(&neg);
+ dns_rdataset_disassociate(&negsig);
+ free_noqname(mctx, &closest);
+ return(result);
+}
+
+static dns_dbmethods_t zone_methods;
+
+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_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
+ rbtdb_version_t *rbtversion = version;
+ isc_region_t region;
+ rdatasetheader_t *newheader;
+ rdatasetheader_t *header;
+ isc_result_t result;
+ isc_boolean_t delegating;
+ isc_boolean_t tree_locked = ISC_FALSE;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ if (rbtdb->common.methods == &zone_methods)
+ REQUIRE(((rbtnode->nsec3 &&
+ (rdataset->type == dns_rdatatype_nsec3 ||
+ rdataset->covers == dns_rdatatype_nsec3)) ||
+ (!rbtnode->nsec3 &&
+ rdataset->type != dns_rdatatype_nsec3 &&
+ rdataset->covers != dns_rdatatype_nsec3)));
+
+ if (rbtversion == NULL) {
+ if (now == 0)
+ isc_stdtime_get(&now);
+ } else
+ now = 0;
+
+ result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
+ &region,
+ sizeof(rdatasetheader_t));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ newheader = (rdatasetheader_t *)region.base;
+ init_rdataset(rbtdb, newheader);
+ set_ttl(rbtdb, newheader, rdataset->ttl + now);
+ newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type,
+ rdataset->covers);
+ newheader->attributes = 0;
+ newheader->noqname = NULL;
+ newheader->closest = NULL;
+ newheader->count = init_count++;
+ newheader->trust = rdataset->trust;
+ newheader->additional_auth = NULL;
+ newheader->additional_glue = NULL;
+ newheader->last_used = now;
+ newheader->node = rbtnode;
+ if (rbtversion != NULL) {
+ newheader->serial = rbtversion->serial;
+ now = 0;
+
+ if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
+ newheader->attributes |= RDATASET_ATTR_RESIGN;
+ newheader->resign = rdataset->resign;
+ } else
+ newheader->resign = 0;
+ } else {
+ newheader->serial = 1;
+ newheader->resign = 0;
+ if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
+ newheader->attributes |= RDATASET_ATTR_NXDOMAIN;
+ if ((rdataset->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
+ newheader->attributes |= RDATASET_ATTR_OPTOUT;
+ if ((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0) {
+ result = addnoqname(rbtdb, newheader, rdataset);
+ if (result != ISC_R_SUCCESS) {
+ free_rdataset(rbtdb, rbtdb->common.mctx,
+ newheader);
+ return (result);
+ }
+ }
+ if ((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0) {
+ result = addclosest(rbtdb, newheader, rdataset);
+ if (result != ISC_R_SUCCESS) {
+ free_rdataset(rbtdb, rbtdb->common.mctx,
+ newheader);
+ return (result);
+ }
+ }
+ }
+
+ /*
+ * If we're adding a delegation type (e.g. NS or DNAME for a zone,
+ * just DNAME for the cache), then we need to set the callback bit
+ * on the node.
+ */
+ if (delegating_type(rbtdb, rbtnode, rdataset->type))
+ delegating = ISC_TRUE;
+ else
+ 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.
+ */
+ if (delegating || (IS_CACHE(rbtdb) && rbtdb->overmem)) {
+ tree_locked = ISC_TRUE;
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+ }
+
+ if (IS_CACHE(rbtdb) && rbtdb->overmem)
+ overmem_purge(rbtdb, rbtnode->locknum, now, tree_locked);
+
+ NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_write);
+
+ if (rbtdb->rrsetstats != NULL) {
+ newheader->attributes |= RDATASET_ATTR_STATCOUNT;
+ update_rrsetstats(rbtdb, newheader, ISC_TRUE);
+ }
+
+ if (IS_CACHE(rbtdb)) {
+ if (tree_locked)
+ cleanup_dead_nodes(rbtdb, rbtnode->locknum);
+
+ header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1);
+ if (header && header->rdh_ttl <= now - RBTDB_VIRTUAL)
+ expire_header(rbtdb, header, tree_locked);
+
+ /*
+ * If we've been holding a write lock on the tree just for
+ * cleaning, we can release it now. However, we still need the
+ * node lock.
+ */
+ if (tree_locked && !delegating) {
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+ tree_locked = ISC_FALSE;
+ }
+ }
+
+ result = add(rbtdb, rbtnode, rbtversion, newheader, options, ISC_FALSE,
+ addedrdataset, now);
+ if (result == ISC_R_SUCCESS && delegating)
+ rbtnode->find_callback = 1;
+
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_write);
+
+ if (tree_locked)
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+
+ /*
+ * Update the zone's secure status. If version is non-NULL
+ * this is defered until closeversion() is called.
+ */
+ if (result == ISC_R_SUCCESS && version == NULL && !IS_CACHE(rbtdb))
+ iszonesecure(db, version, rbtdb->origin_node);
+
+ 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)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
+ rbtdb_version_t *rbtversion = version;
+ rdatasetheader_t *topheader, *topheader_prev, *header, *newheader;
+ unsigned char *subresult;
+ isc_region_t region;
+ isc_result_t result;
+ rbtdb_changed_t *changed;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ if (rbtdb->common.methods == &zone_methods)
+ REQUIRE(((rbtnode->nsec3 &&
+ (rdataset->type == dns_rdatatype_nsec3 ||
+ rdataset->covers == dns_rdatatype_nsec3)) ||
+ (!rbtnode->nsec3 &&
+ rdataset->type != dns_rdatatype_nsec3 &&
+ rdataset->covers != dns_rdatatype_nsec3)));
+
+ result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
+ &region,
+ sizeof(rdatasetheader_t));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ newheader = (rdatasetheader_t *)region.base;
+ init_rdataset(rbtdb, newheader);
+ set_ttl(rbtdb, newheader, rdataset->ttl);
+ newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type,
+ rdataset->covers);
+ newheader->attributes = 0;
+ newheader->serial = rbtversion->serial;
+ newheader->trust = 0;
+ newheader->noqname = NULL;
+ newheader->closest = NULL;
+ newheader->count = init_count++;
+ newheader->additional_auth = NULL;
+ newheader->additional_glue = NULL;
+ newheader->last_used = 0;
+ newheader->node = rbtnode;
+ if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
+ newheader->attributes |= RDATASET_ATTR_RESIGN;
+ newheader->resign = rdataset->resign;
+ } else
+ newheader->resign = 0;
+
+ NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_write);
+
+ changed = add_changed(rbtdb, rbtversion, rbtnode);
+ if (changed == NULL) {
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_write);
+ return (ISC_R_NOMEMORY);
+ }
+
+ topheader_prev = NULL;
+ for (topheader = rbtnode->data;
+ topheader != NULL;
+ topheader = topheader->next) {
+ if (topheader->type == newheader->type)
+ break;
+ topheader_prev = topheader;
+ }
+ /*
+ * If header isn't NULL, we've found the right type. There may be
+ * IGNORE rdatasets between the top of the chain and the first real
+ * data. We skip over them.
+ */
+ header = topheader;
+ while (header != NULL && IGNORE(header))
+ header = header->down;
+ if (header != NULL && EXISTS(header)) {
+ unsigned int flags = 0;
+ subresult = NULL;
+ result = ISC_R_SUCCESS;
+ if ((options & DNS_DBSUB_EXACT) != 0) {
+ flags |= DNS_RDATASLAB_EXACT;
+ if (newheader->rdh_ttl != header->rdh_ttl)
+ result = DNS_R_NOTEXACT;
+ }
+ if (result == ISC_R_SUCCESS)
+ result = dns_rdataslab_subtract(
+ (unsigned char *)header,
+ (unsigned char *)newheader,
+ (unsigned int)(sizeof(*newheader)),
+ rbtdb->common.mctx,
+ rbtdb->common.rdclass,
+ (dns_rdatatype_t)header->type,
+ flags, &subresult);
+ if (result == ISC_R_SUCCESS) {
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ newheader = (rdatasetheader_t *)subresult;
+ init_rdataset(rbtdb, newheader);
+ /*
+ * We have to set the serial since the rdataslab
+ * subtraction routine copies the reserved portion of
+ * header, not newheader.
+ */
+ newheader->serial = rbtversion->serial;
+ /*
+ * XXXJT: dns_rdataslab_subtract() copied the pointers
+ * to additional info. We need to clear these fields
+ * to avoid having duplicated references.
+ */
+ newheader->additional_auth = NULL;
+ newheader->additional_glue = NULL;
+ } else if (result == DNS_R_NXRRSET) {
+ /*
+ * This subtraction would remove all of the rdata;
+ * add a nonexistent header instead.
+ */
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ newheader = new_rdataset(rbtdb, rbtdb->common.mctx);
+ if (newheader == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto unlock;
+ }
+ set_ttl(rbtdb, newheader, 0);
+ newheader->type = topheader->type;
+ newheader->attributes = RDATASET_ATTR_NONEXISTENT;
+ newheader->trust = 0;
+ newheader->serial = rbtversion->serial;
+ newheader->noqname = NULL;
+ newheader->closest = NULL;
+ newheader->count = 0;
+ newheader->additional_auth = NULL;
+ newheader->additional_glue = NULL;
+ newheader->node = rbtnode;
+ newheader->resign = 0;
+ newheader->last_used = 0;
+ } else {
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ goto unlock;
+ }
+
+ /*
+ * If we're here, we want to link newheader in front of
+ * topheader.
+ */
+ INSIST(rbtversion->serial >= topheader->serial);
+ if (topheader_prev != NULL)
+ topheader_prev->next = newheader;
+ else
+ rbtnode->data = newheader;
+ newheader->next = topheader->next;
+ newheader->down = topheader;
+ topheader->next = newheader;
+ rbtnode->dirty = 1;
+ changed->dirty = ISC_TRUE;
+ } else {
+ /*
+ * The rdataset doesn't exist, so we don't need to do anything
+ * to satisfy the deletion request.
+ */
+ free_rdataset(rbtdb, rbtdb->common.mctx, newheader);
+ if ((options & DNS_DBSUB_EXACT) != 0)
+ result = DNS_R_NOTEXACT;
+ else
+ result = DNS_R_UNCHANGED;
+ }
+
+ if (result == ISC_R_SUCCESS && newrdataset != NULL)
+ bind_rdataset(rbtdb, rbtnode, newheader, 0, newrdataset);
+
+ unlock:
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_write);
+
+ /*
+ * Update the zone's secure status. If version is non-NULL
+ * this is defered until closeversion() is called.
+ */
+ if (result == ISC_R_SUCCESS && version == NULL && !IS_CACHE(rbtdb))
+ iszonesecure(db, rbtdb->current_version, rbtdb->origin_node);
+
+ 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)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *rbtnode = (dns_rbtnode_t *)node;
+ rbtdb_version_t *rbtversion = version;
+ isc_result_t result;
+ rdatasetheader_t *newheader;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ if (type == dns_rdatatype_any)
+ return (ISC_R_NOTIMPLEMENTED);
+ if (type == dns_rdatatype_rrsig && covers == 0)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ newheader = new_rdataset(rbtdb, rbtdb->common.mctx);
+ if (newheader == NULL)
+ return (ISC_R_NOMEMORY);
+ set_ttl(rbtdb, newheader, 0);
+ newheader->type = RBTDB_RDATATYPE_VALUE(type, covers);
+ newheader->attributes = RDATASET_ATTR_NONEXISTENT;
+ newheader->trust = 0;
+ newheader->noqname = NULL;
+ newheader->closest = NULL;
+ newheader->additional_auth = NULL;
+ newheader->additional_glue = NULL;
+ if (rbtversion != NULL)
+ newheader->serial = rbtversion->serial;
+ else
+ newheader->serial = 0;
+ newheader->count = 0;
+ newheader->last_used = 0;
+ newheader->node = rbtnode;
+
+ NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_write);
+
+ result = add(rbtdb, rbtnode, rbtversion, newheader, DNS_DBADD_FORCE,
+ ISC_FALSE, NULL, 0);
+
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_write);
+
+ /*
+ * Update the zone's secure status. If version is non-NULL
+ * this is defered until closeversion() is called.
+ */
+ if (result == ISC_R_SUCCESS && version == NULL && !IS_CACHE(rbtdb))
+ iszonesecure(db, rbtdb->current_version, rbtdb->origin_node);
+
+ return (result);
+}
+
+static isc_result_t
+loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
+ rbtdb_load_t *loadctx = arg;
+ dns_rbtdb_t *rbtdb = loadctx->rbtdb;
+ dns_rbtnode_t *node;
+ isc_result_t result;
+ isc_region_t region;
+ rdatasetheader_t *newheader;
+
+ /*
+ * This routine does no node locking. See comments in
+ * 'load' below for more information on loading and
+ * locking.
+ */
+
+
+ /*
+ * SOA records are only allowed at top of zone.
+ */
+ if (rdataset->type == dns_rdatatype_soa &&
+ !IS_CACHE(rbtdb) && !dns_name_equal(name, &rbtdb->common.origin))
+ return (DNS_R_NOTZONETOP);
+
+ if (rdataset->type != dns_rdatatype_nsec3 &&
+ rdataset->covers != dns_rdatatype_nsec3)
+ add_empty_wildcards(rbtdb, name);
+
+ if (dns_name_iswildcard(name)) {
+ /*
+ * NS record owners cannot legally be wild cards.
+ */
+ if (rdataset->type == dns_rdatatype_ns)
+ return (DNS_R_INVALIDNS);
+ /*
+ * NSEC3 record owners cannot legally be wild cards.
+ */
+ if (rdataset->type == dns_rdatatype_nsec3)
+ return (DNS_R_INVALIDNSEC3);
+ result = add_wildcard_magic(rbtdb, name);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ node = NULL;
+ if (rdataset->type == dns_rdatatype_nsec3 ||
+ rdataset->covers == dns_rdatatype_nsec3) {
+ result = dns_rbt_addnode(rbtdb->nsec3, name, &node);
+ if (result == ISC_R_SUCCESS)
+ node->nsec3 = 1;
+ } else {
+ result = dns_rbt_addnode(rbtdb->tree, name, &node);
+ if (result == ISC_R_SUCCESS)
+ node->nsec3 = 0;
+ }
+ if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
+ return (result);
+ if (result != ISC_R_EXISTS) {
+ dns_name_t foundname;
+ dns_name_init(&foundname, NULL);
+ dns_rbt_namefromnode(node, &foundname);
+#ifdef DNS_RBT_USEHASH
+ node->locknum = node->hashval % rbtdb->node_lock_count;
+#else
+ node->locknum = dns_name_hash(&foundname, ISC_TRUE) %
+ rbtdb->node_lock_count;
+#endif
+ }
+
+ result = dns_rdataslab_fromrdataset(rdataset, rbtdb->common.mctx,
+ &region,
+ sizeof(rdatasetheader_t));
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ newheader = (rdatasetheader_t *)region.base;
+ init_rdataset(rbtdb, newheader);
+ set_ttl(rbtdb, newheader,
+ rdataset->ttl + loadctx->now); /* XXX overflow check */
+ newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type,
+ rdataset->covers);
+ newheader->attributes = 0;
+ newheader->trust = rdataset->trust;
+ newheader->serial = 1;
+ newheader->noqname = NULL;
+ newheader->closest = NULL;
+ newheader->count = init_count++;
+ newheader->additional_auth = NULL;
+ newheader->additional_glue = NULL;
+ newheader->last_used = 0;
+ newheader->node = node;
+ if ((rdataset->attributes & DNS_RDATASETATTR_RESIGN) != 0) {
+ newheader->attributes |= RDATASET_ATTR_RESIGN;
+ newheader->resign = rdataset->resign;
+ } else
+ newheader->resign = 0;
+
+ result = add(rbtdb, node, rbtdb->current_version, newheader,
+ DNS_DBADD_MERGE, ISC_TRUE, NULL, 0);
+ if (result == ISC_R_SUCCESS &&
+ delegating_type(rbtdb, node, rdataset->type))
+ node->find_callback = 1;
+ else if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+
+ return (result);
+}
+
+static isc_result_t
+beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
+ rbtdb_load_t *loadctx;
+ dns_rbtdb_t *rbtdb;
+
+ rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ loadctx = isc_mem_get(rbtdb->common.mctx, sizeof(*loadctx));
+ if (loadctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ loadctx->rbtdb = rbtdb;
+ if (IS_CACHE(rbtdb))
+ isc_stdtime_get(&loadctx->now);
+ else
+ loadctx->now = 0;
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
+
+ REQUIRE((rbtdb->attributes & (RBTDB_ATTR_LOADED|RBTDB_ATTR_LOADING))
+ == 0);
+ rbtdb->attributes |= RBTDB_ATTR_LOADING;
+
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
+
+ *addp = loading_addrdataset;
+ *dbloadp = loadctx;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+endload(dns_db_t *db, dns_dbload_t **dbloadp) {
+ rbtdb_load_t *loadctx;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(dbloadp != NULL);
+ loadctx = *dbloadp;
+ REQUIRE(loadctx->rbtdb == rbtdb);
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
+
+ REQUIRE((rbtdb->attributes & RBTDB_ATTR_LOADING) != 0);
+ REQUIRE((rbtdb->attributes & RBTDB_ATTR_LOADED) == 0);
+
+ rbtdb->attributes &= ~RBTDB_ATTR_LOADING;
+ rbtdb->attributes |= RBTDB_ATTR_LOADED;
+
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
+
+ /*
+ * If there's a KEY rdataset at the zone origin containing a
+ * zone key, we consider the zone secure.
+ */
+ if (! IS_CACHE(rbtdb))
+ iszonesecure(db, rbtdb->current_version, rbtdb->origin_node);
+
+ *dbloadp = NULL;
+
+ isc_mem_put(rbtdb->common.mctx, loadctx, sizeof(*loadctx));
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
+ dns_masterformat_t masterformat) {
+ dns_rbtdb_t *rbtdb;
+
+ rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ return (dns_master_dump2(rbtdb->common.mctx, db, version,
+ &dns_master_style_default,
+ filename, masterformat));
+}
+
+static void
+delete_callback(void *data, void *arg) {
+ dns_rbtdb_t *rbtdb = arg;
+ rdatasetheader_t *current, *next;
+
+ for (current = data; current != NULL; current = next) {
+ next = current->next;
+ free_rdataset(rbtdb, rbtdb->common.mctx, current);
+ }
+}
+
+static isc_boolean_t
+issecure(dns_db_t *db) {
+ dns_rbtdb_t *rbtdb;
+ isc_boolean_t secure;
+
+ rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ secure = ISC_TF(rbtdb->current_version->secure == dns_db_secure);
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+
+ return (secure);
+}
+
+static isc_boolean_t
+isdnssec(dns_db_t *db) {
+ dns_rbtdb_t *rbtdb;
+ isc_boolean_t dnssec;
+
+ rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ dnssec = ISC_TF(rbtdb->current_version->secure != dns_db_insecure);
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+
+ return (dnssec);
+}
+
+static unsigned int
+nodecount(dns_db_t *db) {
+ dns_rbtdb_t *rbtdb;
+ unsigned int count;
+
+ rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ count = dns_rbt_nodecount(rbtdb->tree);
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+
+ return (count);
+}
+
+static void
+settask(dns_db_t *db, isc_task_t *task) {
+ dns_rbtdb_t *rbtdb;
+
+ rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
+ if (rbtdb->task != NULL)
+ isc_task_detach(&rbtdb->task);
+ if (task != NULL)
+ isc_task_attach(task, &rbtdb->task);
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
+}
+
+static isc_boolean_t
+ispersistent(dns_db_t *db) {
+ UNUSED(db);
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *onode;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(nodep != NULL && *nodep == NULL);
+
+ /* Note that the access to origin_node doesn't require a DB lock */
+ onode = (dns_rbtnode_t *)rbtdb->origin_node;
+ if (onode != NULL) {
+ NODE_STRONGLOCK(&rbtdb->node_locks[onode->locknum].lock);
+ new_reference(rbtdb, onode);
+ NODE_STRONGUNLOCK(&rbtdb->node_locks[onode->locknum].lock);
+
+ *nodep = rbtdb->origin_node;
+ } else {
+ INSIST(IS_CACHE(rbtdb));
+ result = ISC_R_NOTFOUND;
+ }
+
+ return (result);
+}
+
+static isc_result_t
+getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, dns_hash_t *hash,
+ isc_uint8_t *flags, isc_uint16_t *iterations,
+ unsigned char *salt, size_t *salt_length)
+{
+ dns_rbtdb_t *rbtdb;
+ isc_result_t result = ISC_R_NOTFOUND;
+ rbtdb_version_t *rbtversion = version;
+
+ rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+
+ if (rbtversion == NULL)
+ rbtversion = rbtdb->current_version;
+
+ if (rbtversion->havensec3) {
+ if (hash != NULL)
+ *hash = rbtversion->hash;
+ if (salt != NULL && salt_length != 0) {
+ REQUIRE(*salt_length > rbtversion->salt_length);
+ memcpy(salt, rbtversion->salt, rbtversion->salt_length);
+ }
+ if (salt_length != NULL)
+ *salt_length = rbtversion->salt_length;
+ if (iterations != NULL)
+ *iterations = rbtversion->iterations;
+ if (flags != NULL)
+ *flags = rbtversion->flags;
+ result = ISC_R_SUCCESS;
+ }
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+
+ return (result);
+}
+
+static isc_result_t
+setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ isc_stdtime_t oldresign;
+ isc_result_t result = ISC_R_SUCCESS;
+ rdatasetheader_t *header;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(!IS_CACHE(rbtdb));
+ REQUIRE(rdataset != NULL);
+
+ header = rdataset->private3;
+ header--;
+
+ NODE_LOCK(&rbtdb->node_locks[header->node->locknum].lock,
+ isc_rwlocktype_write);
+
+ oldresign = header->resign;
+ header->resign = resign;
+ if (header->heap_index != 0) {
+ INSIST(RESIGN(header));
+ if (resign == 0) {
+ isc_heap_delete(rbtdb->heaps[header->node->locknum],
+ header->heap_index);
+ header->heap_index = 0;
+ } else if (resign < oldresign)
+ isc_heap_increased(rbtdb->heaps[header->node->locknum],
+ header->heap_index);
+ else
+ isc_heap_decreased(rbtdb->heaps[header->node->locknum],
+ header->heap_index);
+ } else if (resign && header->heap_index == 0) {
+ header->attributes |= RDATASET_ATTR_RESIGN;
+ result = resign_insert(rbtdb, header->node->locknum, header);
+ }
+ NODE_UNLOCK(&rbtdb->node_locks[header->node->locknum].lock,
+ isc_rwlocktype_write);
+ return (result);
+}
+
+static isc_result_t
+getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
+ dns_name_t *foundname)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ rdatasetheader_t *header = NULL, *this;
+ unsigned int i;
+ isc_result_t result = ISC_R_NOTFOUND;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
+
+ for (i = 0; i < rbtdb->node_lock_count; i++) {
+ this = isc_heap_element(rbtdb->heaps[i], 1);
+ if (this == NULL)
+ continue;
+ if (header == NULL)
+ header = this;
+ else if (isc_serial_lt(this->resign, header->resign))
+ header = this;
+ }
+
+ if (header == NULL)
+ goto unlock;
+
+ NODE_LOCK(&rbtdb->node_locks[header->node->locknum].lock,
+ isc_rwlocktype_read);
+
+ bind_rdataset(rbtdb, header->node, header, 0, rdataset);
+
+ if (foundname != NULL)
+ dns_rbt_fullnamefromnode(header->node, foundname);
+
+ NODE_UNLOCK(&rbtdb->node_locks[header->node->locknum].lock,
+ isc_rwlocktype_read);
+
+ result = ISC_R_SUCCESS;
+
+ unlock:
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
+
+ return (result);
+}
+
+static void
+resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version)
+{
+ rbtdb_version_t *rbtversion = (rbtdb_version_t *)version;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+ dns_rbtnode_t *node;
+ rdatasetheader_t *header;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(rdataset != NULL);
+ REQUIRE(rbtdb->future_version == rbtversion);
+ REQUIRE(rbtversion->writer);
+
+ node = rdataset->private2;
+ header = rdataset->private3;
+ header--;
+
+ RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_read);
+ NODE_LOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_write);
+ /*
+ * Delete from heap and save to re-signed list so that it can
+ * be restored if we backout of this change.
+ */
+ new_reference(rbtdb, node);
+ isc_heap_delete(rbtdb->heaps[node->locknum], header->heap_index);
+ header->heap_index = 0;
+ ISC_LIST_APPEND(rbtversion->resigned_list, header, lru_link);
+
+ NODE_UNLOCK(&rbtdb->node_locks[node->locknum].lock,
+ isc_rwlocktype_write);
+ RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_read);
+}
+
+static dns_stats_t *
+getrrsetstats(dns_db_t *db) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;
+
+ REQUIRE(VALID_RBTDB(rbtdb));
+ REQUIRE(IS_CACHE(rbtdb)); /* current restriction */
+
+ return (rbtdb->rrsetstats);
+}
+
+static dns_dbmethods_t zone_methods = {
+ attach,
+ detach,
+ beginload,
+ endload,
+ dump,
+ currentversion,
+ newversion,
+ attachversion,
+ closeversion,
+ findnode,
+ zone_find,
+ zone_findzonecut,
+ attachnode,
+ detachnode,
+ expirenode,
+ printnode,
+ createiterator,
+ zone_findrdataset,
+ allrdatasets,
+ addrdataset,
+ subtractrdataset,
+ deleterdataset,
+ issecure,
+ nodecount,
+ ispersistent,
+ overmem,
+ settask,
+ getoriginnode,
+ NULL,
+ getnsec3parameters,
+ findnsec3node,
+ setsigningtime,
+ getsigningtime,
+ resigned,
+ isdnssec,
+ NULL
+};
+
+static dns_dbmethods_t cache_methods = {
+ attach,
+ detach,
+ beginload,
+ endload,
+ dump,
+ currentversion,
+ newversion,
+ attachversion,
+ closeversion,
+ findnode,
+ cache_find,
+ cache_findzonecut,
+ attachnode,
+ detachnode,
+ expirenode,
+ printnode,
+ createiterator,
+ cache_findrdataset,
+ allrdatasets,
+ addrdataset,
+ subtractrdataset,
+ deleterdataset,
+ issecure,
+ nodecount,
+ ispersistent,
+ overmem,
+ settask,
+ getoriginnode,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ isdnssec,
+ getrrsetstats
+};
+
+isc_result_t
+#ifdef DNS_RBTDB_VERSION64
+dns_rbtdb64_create
+#else
+dns_rbtdb_create
+#endif
+ (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_rbtdb_t *rbtdb;
+ isc_result_t result;
+ int i;
+ dns_name_t name;
+ isc_boolean_t (*sooner)(void *, void *);
+
+ /* Keep the compiler happy. */
+ UNUSED(argc);
+ UNUSED(argv);
+ UNUSED(driverarg);
+
+ rbtdb = isc_mem_get(mctx, sizeof(*rbtdb));
+ if (rbtdb == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(rbtdb, '\0', sizeof(*rbtdb));
+ dns_name_init(&rbtdb->common.origin, NULL);
+ rbtdb->common.attributes = 0;
+ if (type == dns_dbtype_cache) {
+ rbtdb->common.methods = &cache_methods;
+ rbtdb->common.attributes |= DNS_DBATTR_CACHE;
+ } else if (type == dns_dbtype_stub) {
+ rbtdb->common.methods = &zone_methods;
+ rbtdb->common.attributes |= DNS_DBATTR_STUB;
+ } else
+ rbtdb->common.methods = &zone_methods;
+ rbtdb->common.rdclass = rdclass;
+ rbtdb->common.mctx = NULL;
+
+ result = RBTDB_INITLOCK(&rbtdb->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_rbtdb;
+
+ result = isc_rwlock_init(&rbtdb->tree_lock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lock;
+
+ /*
+ * Initialize node_lock_count in a generic way to support future
+ * extension which allows the user to specify this value on creation.
+ * Note that when specified for a cache DB it must be larger than 1
+ * as commented with the definition of DEFAULT_CACHE_NODE_LOCK_COUNT.
+ */
+ if (rbtdb->node_lock_count == 0) {
+ if (IS_CACHE(rbtdb))
+ rbtdb->node_lock_count = DEFAULT_CACHE_NODE_LOCK_COUNT;
+ else
+ rbtdb->node_lock_count = DEFAULT_NODE_LOCK_COUNT;
+ } else if (rbtdb->node_lock_count < 2 && IS_CACHE(rbtdb)) {
+ result = ISC_R_RANGE;
+ goto cleanup_tree_lock;
+ }
+ INSIST(rbtdb->node_lock_count < (1 << DNS_RBT_LOCKLENGTH));
+ rbtdb->node_locks = isc_mem_get(mctx, rbtdb->node_lock_count *
+ sizeof(rbtdb_nodelock_t));
+ if (rbtdb->node_locks == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_tree_lock;
+ }
+
+ rbtdb->rrsetstats = NULL;
+ if (IS_CACHE(rbtdb)) {
+ result = dns_rdatasetstats_create(mctx, &rbtdb->rrsetstats);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_node_locks;
+ rbtdb->rdatasets = isc_mem_get(mctx, rbtdb->node_lock_count *
+ sizeof(rdatasetheaderlist_t));
+ if (rbtdb->rdatasets == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_rrsetstats;
+ }
+ for (i = 0; i < (int)rbtdb->node_lock_count; i++)
+ ISC_LIST_INIT(rbtdb->rdatasets[i]);
+ } else
+ rbtdb->rdatasets = NULL;
+
+ /*
+ * Create the heaps.
+ */
+ rbtdb->heaps = isc_mem_get(mctx, rbtdb->node_lock_count *
+ sizeof(isc_heap_t *));
+ if (rbtdb->heaps == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_rdatasets;
+ }
+ for (i = 0; i < (int)rbtdb->node_lock_count; i++)
+ rbtdb->heaps[i] = NULL;
+ sooner = IS_CACHE(rbtdb) ? ttl_sooner : resign_sooner;
+ for (i = 0; i < (int)rbtdb->node_lock_count; i++) {
+ result = isc_heap_create(mctx, sooner, set_index, 0,
+ &rbtdb->heaps[i]);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_heaps;
+ }
+
+ /*
+ * Create deadnode lists.
+ */
+ rbtdb->deadnodes = isc_mem_get(mctx, rbtdb->node_lock_count *
+ sizeof(rbtnodelist_t));
+ if (rbtdb->deadnodes == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_heaps;
+ }
+ for (i = 0; i < (int)rbtdb->node_lock_count; i++)
+ ISC_LIST_INIT(rbtdb->deadnodes[i]);
+
+ rbtdb->active = rbtdb->node_lock_count;
+
+ for (i = 0; i < (int)(rbtdb->node_lock_count); i++) {
+ result = NODE_INITLOCK(&rbtdb->node_locks[i].lock);
+ if (result == ISC_R_SUCCESS) {
+ result = isc_refcount_init(&rbtdb->node_locks[i].references, 0);
+ if (result != ISC_R_SUCCESS)
+ NODE_DESTROYLOCK(&rbtdb->node_locks[i].lock);
+ }
+ if (result != ISC_R_SUCCESS) {
+ while (i-- > 0) {
+ NODE_DESTROYLOCK(&rbtdb->node_locks[i].lock);
+ isc_refcount_decrement(&rbtdb->node_locks[i].references, NULL);
+ isc_refcount_destroy(&rbtdb->node_locks[i].references);
+ }
+ goto cleanup_deadnodes;
+ }
+ rbtdb->node_locks[i].exiting = ISC_FALSE;
+ }
+
+ /*
+ * Attach to the mctx. The database will persist so long as there
+ * are references to it, and attaching to the mctx ensures that our
+ * mctx won't disappear out from under us.
+ */
+ isc_mem_attach(mctx, &rbtdb->common.mctx);
+
+ /*
+ * Must be initalized before free_rbtdb() is called.
+ */
+ isc_ondestroy_init(&rbtdb->common.ondest);
+
+ /*
+ * Make a copy of the origin name.
+ */
+ result = dns_name_dupwithoffsets(origin, mctx, &rbtdb->common.origin);
+ if (result != ISC_R_SUCCESS) {
+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
+ return (result);
+ }
+
+ /*
+ * Make the Red-Black Trees.
+ */
+ result = dns_rbt_create(mctx, delete_callback, rbtdb, &rbtdb->tree);
+ 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);
+ }
+
+ /*
+ * 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.
+ * In loading_addrdataset() we could simply compare the new name
+ * to the origin name, but this is expensive. Also, we don't know the
+ * node name in addrdataset(), so we need another way of knowing the
+ * zone's top.
+ *
+ * We now explicitly create a node for the zone's origin, and then
+ * we simply remember the node's address. This is safe, because
+ * the top-of-zone node can never be deleted, nor can its address
+ * change.
+ */
+ if (!IS_CACHE(rbtdb)) {
+ rbtdb->origin_node = NULL;
+ result = dns_rbt_addnode(rbtdb->tree, &rbtdb->common.origin,
+ &rbtdb->origin_node);
+ if (result != ISC_R_SUCCESS) {
+ INSIST(result != ISC_R_EXISTS);
+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
+ return (result);
+ }
+ rbtdb->origin_node->nsec3 = 0;
+ /*
+ * We need to give the origin node the right locknum.
+ */
+ dns_name_init(&name, NULL);
+ dns_rbt_namefromnode(rbtdb->origin_node, &name);
+#ifdef DNS_RBT_USEHASH
+ rbtdb->origin_node->locknum =
+ rbtdb->origin_node->hashval %
+ rbtdb->node_lock_count;
+#else
+ rbtdb->origin_node->locknum =
+ dns_name_hash(&name, ISC_TRUE) %
+ rbtdb->node_lock_count;
+#endif
+ }
+
+ /*
+ * Misc. Initialization.
+ */
+ result = isc_refcount_init(&rbtdb->references, 1);
+ if (result != ISC_R_SUCCESS) {
+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
+ return (result);
+ }
+ rbtdb->attributes = 0;
+ rbtdb->overmem = ISC_FALSE;
+ rbtdb->task = NULL;
+
+ /*
+ * Version Initialization.
+ */
+ rbtdb->current_serial = 1;
+ rbtdb->least_serial = 1;
+ rbtdb->next_serial = 2;
+ rbtdb->current_version = allocate_version(mctx, 1, 1, ISC_FALSE);
+ if (rbtdb->current_version == NULL) {
+ isc_refcount_decrement(&rbtdb->references, NULL);
+ isc_refcount_destroy(&rbtdb->references);
+ free_rbtdb(rbtdb, ISC_FALSE, NULL);
+ return (ISC_R_NOMEMORY);
+ }
+ rbtdb->current_version->secure = dns_db_insecure;
+ rbtdb->current_version->havensec3 = ISC_FALSE;
+ rbtdb->current_version->flags = 0;
+ rbtdb->current_version->iterations = 0;
+ rbtdb->current_version->hash = 0;
+ rbtdb->current_version->salt_length = 0;
+ memset(rbtdb->current_version->salt, 0,
+ sizeof(rbtdb->current_version->salt));
+ rbtdb->future_version = NULL;
+ ISC_LIST_INIT(rbtdb->open_versions);
+ /*
+ * Keep the current version in the open list so that list operation
+ * won't happen in normal lookup operations.
+ */
+ PREPEND(rbtdb->open_versions, rbtdb->current_version, link);
+
+ rbtdb->common.magic = DNS_DB_MAGIC;
+ rbtdb->common.impmagic = RBTDB_MAGIC;
+
+ *dbp = (dns_db_t *)rbtdb;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_deadnodes:
+ isc_mem_put(mctx, rbtdb->deadnodes,
+ rbtdb->node_lock_count * sizeof(rbtnodelist_t));
+
+ cleanup_heaps:
+ if (rbtdb->heaps != NULL) {
+ for (i = 0 ; i < (int)rbtdb->node_lock_count ; i++)
+ if (rbtdb->heaps[i] != NULL)
+ isc_heap_destroy(&rbtdb->heaps[i]);
+ isc_mem_put(mctx, rbtdb->heaps,
+ rbtdb->node_lock_count * sizeof(isc_heap_t *));
+ }
+
+ cleanup_rdatasets:
+ if (rbtdb->rdatasets != NULL)
+ isc_mem_put(mctx, rbtdb->rdatasets, rbtdb->node_lock_count *
+ sizeof(rdatasetheaderlist_t));
+ cleanup_rrsetstats:
+ if (rbtdb->rrsetstats != NULL)
+ dns_stats_detach(&rbtdb->rrsetstats);
+
+ cleanup_node_locks:
+ isc_mem_put(mctx, rbtdb->node_locks,
+ rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t));
+
+ cleanup_tree_lock:
+ isc_rwlock_destroy(&rbtdb->tree_lock);
+
+ cleanup_lock:
+ RBTDB_DESTROYLOCK(&rbtdb->lock);
+
+ cleanup_rbtdb:
+ isc_mem_put(mctx, rbtdb, sizeof(*rbtdb));
+ return (result);
+}
+
+
+/*
+ * Slabbed Rdataset Methods
+ */
+
+static void
+rdataset_disassociate(dns_rdataset_t *rdataset) {
+ dns_db_t *db = rdataset->private1;
+ dns_dbnode_t *node = rdataset->private2;
+
+ detachnode(db, &node);
+}
+
+static isc_result_t
+rdataset_first(dns_rdataset_t *rdataset) {
+ unsigned char *raw = rdataset->private3; /* RDATASLAB */
+ unsigned int count;
+
+ count = raw[0] * 256 + raw[1];
+ if (count == 0) {
+ rdataset->private5 = NULL;
+ return (ISC_R_NOMORE);
+ }
+
+#if DNS_RDATASET_FIXED
+ if ((rdataset->attributes & DNS_RDATASETATTR_LOADORDER) == 0)
+ raw += 2 + (4 * count);
+ else
+#endif
+ 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.
+ *
+ * If DNS_RDATASETATTR_LOADORDER is not set 'raw' points to the
+ * first record. If DNS_RDATASETATTR_LOADORDER is set 'raw' points
+ * to the first entry in the offset table.
+ */
+ 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; /* RDATASLAB */
+
+ count = rdataset->privateuint4;
+ if (count == 0)
+ return (ISC_R_NOMORE);
+ count--;
+ rdataset->privateuint4 = count;
+
+ /*
+ * Skip forward one record (length + 4) or one offset (4).
+ */
+ raw = rdataset->private5;
+#if DNS_RDATASET_FIXED
+ if ((rdataset->attributes & DNS_RDATASETATTR_LOADORDER) == 0) {
+#endif
+ length = raw[0] * 256 + raw[1];
+ raw += length;
+#if DNS_RDATASET_FIXED
+ }
+ rdataset->private5 = raw + 4; /* length(2) + order(2) */
+#else
+ rdataset->private5 = raw + 2; /* length(2) */
+#endif
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
+ unsigned char *raw = rdataset->private5; /* RDATASLAB */
+#if DNS_RDATASET_FIXED
+ unsigned int offset;
+#endif
+ unsigned int length;
+ isc_region_t r;
+ unsigned int flags = 0;
+
+ REQUIRE(raw != NULL);
+
+ /*
+ * Find the start of the record if not already in private5
+ * then skip the length and order fields.
+ */
+#if DNS_RDATASET_FIXED
+ if ((rdataset->attributes & DNS_RDATASETATTR_LOADORDER) != 0) {
+ offset = (raw[0] << 24) + (raw[1] << 16) +
+ (raw[2] << 8) + raw[3];
+ raw = rdataset->private3;
+ raw += offset;
+ }
+#endif
+ length = raw[0] * 256 + raw[1];
+#if DNS_RDATASET_FIXED
+ raw += 4;
+#else
+ raw += 2;
+#endif
+ 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; /* RDATASLAB */
+ unsigned int count;
+
+ count = raw[0] * 256 + raw[1];
+
+ return (count);
+}
+
+static isc_result_t
+rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *nsec, dns_rdataset_t *nsecsig)
+{
+ dns_db_t *db = rdataset->private1;
+ dns_dbnode_t *node = rdataset->private2;
+ dns_dbnode_t *cloned_node;
+ struct noqname *noqname = rdataset->private6;
+
+ cloned_node = NULL;
+ attachnode(db, node, &cloned_node);
+ nsec->methods = &rdataset_methods;
+ nsec->rdclass = db->rdclass;
+ nsec->type = noqname->type;
+ nsec->covers = 0;
+ nsec->ttl = rdataset->ttl;
+ nsec->trust = rdataset->trust;
+ nsec->private1 = rdataset->private1;
+ nsec->private2 = rdataset->private2;
+ nsec->private3 = noqname->neg;
+ nsec->privateuint4 = 0;
+ nsec->private5 = NULL;
+ nsec->private6 = NULL;
+ nsec->private7 = NULL;
+
+ cloned_node = NULL;
+ attachnode(db, node, &cloned_node);
+ nsecsig->methods = &rdataset_methods;
+ nsecsig->rdclass = db->rdclass;
+ nsecsig->type = dns_rdatatype_rrsig;
+ nsecsig->covers = noqname->type;
+ nsecsig->ttl = rdataset->ttl;
+ nsecsig->trust = rdataset->trust;
+ nsecsig->private1 = rdataset->private1;
+ nsecsig->private2 = rdataset->private2;
+ nsecsig->private3 = noqname->negsig;
+ nsecsig->privateuint4 = 0;
+ nsecsig->private5 = NULL;
+ nsec->private6 = NULL;
+ nsec->private7 = NULL;
+
+ dns_name_clone(&noqname->name, name);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *nsec, dns_rdataset_t *nsecsig)
+{
+ dns_db_t *db = rdataset->private1;
+ dns_dbnode_t *node = rdataset->private2;
+ dns_dbnode_t *cloned_node;
+ struct noqname *closest = rdataset->private7;
+
+ cloned_node = NULL;
+ attachnode(db, node, &cloned_node);
+ nsec->methods = &rdataset_methods;
+ nsec->rdclass = db->rdclass;
+ nsec->type = closest->type;
+ nsec->covers = 0;
+ nsec->ttl = rdataset->ttl;
+ nsec->trust = rdataset->trust;
+ nsec->private1 = rdataset->private1;
+ nsec->private2 = rdataset->private2;
+ nsec->private3 = closest->neg;
+ nsec->privateuint4 = 0;
+ nsec->private5 = NULL;
+ nsec->private6 = NULL;
+ nsec->private7 = NULL;
+
+ cloned_node = NULL;
+ attachnode(db, node, &cloned_node);
+ nsecsig->methods = &rdataset_methods;
+ nsecsig->rdclass = db->rdclass;
+ nsecsig->type = dns_rdatatype_rrsig;
+ nsecsig->covers = closest->type;
+ nsecsig->ttl = rdataset->ttl;
+ nsecsig->trust = rdataset->trust;
+ nsecsig->private1 = rdataset->private1;
+ nsecsig->private2 = rdataset->private2;
+ nsecsig->private3 = closest->negsig;
+ nsecsig->privateuint4 = 0;
+ nsecsig->private5 = NULL;
+ nsec->private6 = NULL;
+ nsec->private7 = NULL;
+
+ dns_name_clone(&closest->name, name);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Rdataset Iterator Methods
+ */
+
+static void
+rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
+ rbtdb_rdatasetiter_t *rbtiterator;
+
+ rbtiterator = (rbtdb_rdatasetiter_t *)(*iteratorp);
+
+ if (rbtiterator->common.version != NULL)
+ closeversion(rbtiterator->common.db,
+ &rbtiterator->common.version, ISC_FALSE);
+ detachnode(rbtiterator->common.db, &rbtiterator->common.node);
+ isc_mem_put(rbtiterator->common.db->mctx, rbtiterator,
+ sizeof(*rbtiterator));
+
+ *iteratorp = NULL;
+}
+
+static isc_result_t
+rdatasetiter_first(dns_rdatasetiter_t *iterator) {
+ rbtdb_rdatasetiter_t *rbtiterator = (rbtdb_rdatasetiter_t *)iterator;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)(rbtiterator->common.db);
+ dns_rbtnode_t *rbtnode = rbtiterator->common.node;
+ rbtdb_version_t *rbtversion = rbtiterator->common.version;
+ rdatasetheader_t *header, *top_next;
+ rbtdb_serial_t serial;
+ isc_stdtime_t now;
+
+ if (IS_CACHE(rbtdb)) {
+ serial = 1;
+ now = rbtiterator->common.now;
+ } else {
+ serial = rbtversion->serial;
+ now = 0;
+ }
+
+ NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_read);
+
+ for (header = rbtnode->data; header != NULL; header = top_next) {
+ top_next = header->next;
+ do {
+ if (header->serial <= serial && !IGNORE(header)) {
+ /*
+ * Is this a "this rdataset doesn't exist"
+ * record? Or is it too old in the cache?
+ *
+ * Note: unlike everywhere else, we
+ * check for now > header->rdh_ttl instead
+ * of now >= header->rdh_ttl. This allows
+ * ANY and RRSIG queries for 0 TTL
+ * rdatasets to work.
+ */
+ if (NONEXISTENT(header) ||
+ (now != 0 && now > header->rdh_ttl))
+ header = NULL;
+ break;
+ } else
+ header = header->down;
+ } while (header != NULL);
+ if (header != NULL)
+ break;
+ }
+
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_read);
+
+ rbtiterator->current = header;
+
+ if (header == NULL)
+ return (ISC_R_NOMORE);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+rdatasetiter_next(dns_rdatasetiter_t *iterator) {
+ rbtdb_rdatasetiter_t *rbtiterator = (rbtdb_rdatasetiter_t *)iterator;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)(rbtiterator->common.db);
+ dns_rbtnode_t *rbtnode = rbtiterator->common.node;
+ rbtdb_version_t *rbtversion = rbtiterator->common.version;
+ rdatasetheader_t *header, *top_next;
+ rbtdb_serial_t serial;
+ isc_stdtime_t now;
+ rbtdb_rdatatype_t type, negtype;
+ dns_rdatatype_t rdtype, covers;
+
+ header = rbtiterator->current;
+ if (header == NULL)
+ return (ISC_R_NOMORE);
+
+ if (IS_CACHE(rbtdb)) {
+ serial = 1;
+ now = rbtiterator->common.now;
+ } else {
+ serial = rbtversion->serial;
+ now = 0;
+ }
+
+ NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_read);
+
+ type = header->type;
+ rdtype = RBTDB_RDATATYPE_BASE(header->type);
+ if (rdtype == 0) {
+ covers = RBTDB_RDATATYPE_EXT(header->type);
+ negtype = RBTDB_RDATATYPE_VALUE(covers, 0);
+ } else
+ negtype = RBTDB_RDATATYPE_VALUE(0, rdtype);
+ for (header = header->next; header != NULL; header = top_next) {
+ top_next = header->next;
+ /*
+ * If not walking back up the down list.
+ */
+ if (header->type != type && header->type != negtype) {
+ do {
+ if (header->serial <= serial &&
+ !IGNORE(header)) {
+ /*
+ * Is this a "this rdataset doesn't
+ * exist" record?
+ *
+ * Note: unlike everywhere else, we
+ * check for now > header->ttl instead
+ * of now >= header->ttl. This allows
+ * ANY and RRSIG queries for 0 TTL
+ * rdatasets to work.
+ */
+ if ((header->attributes &
+ RDATASET_ATTR_NONEXISTENT) != 0 ||
+ (now != 0 && now > header->rdh_ttl))
+ header = NULL;
+ break;
+ } else
+ header = header->down;
+ } while (header != NULL);
+ if (header != NULL)
+ break;
+ }
+ }
+
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_read);
+
+ rbtiterator->current = header;
+
+ if (header == NULL)
+ return (ISC_R_NOMORE);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
+ rbtdb_rdatasetiter_t *rbtiterator = (rbtdb_rdatasetiter_t *)iterator;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)(rbtiterator->common.db);
+ dns_rbtnode_t *rbtnode = rbtiterator->common.node;
+ rdatasetheader_t *header;
+
+ header = rbtiterator->current;
+ REQUIRE(header != NULL);
+
+ NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_read);
+
+ bind_rdataset(rbtdb, rbtnode, header, rbtiterator->common.now,
+ rdataset);
+
+ NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
+ isc_rwlocktype_read);
+}
+
+
+/*
+ * Database Iterator Methods
+ */
+
+static inline void
+reference_iter_node(rbtdb_dbiterator_t *rbtdbiter) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)rbtdbiter->common.db;
+ dns_rbtnode_t *node = rbtdbiter->node;
+
+ if (node == NULL)
+ return;
+
+ INSIST(rbtdbiter->tree_locked != isc_rwlocktype_none);
+ reactivate_node(rbtdb, node, rbtdbiter->tree_locked);
+}
+
+static inline void
+dereference_iter_node(rbtdb_dbiterator_t *rbtdbiter) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)rbtdbiter->common.db;
+ dns_rbtnode_t *node = rbtdbiter->node;
+ nodelock_t *lock;
+
+ if (node == NULL)
+ return;
+
+ lock = &rbtdb->node_locks[node->locknum].lock;
+ NODE_LOCK(lock, isc_rwlocktype_read);
+ decrement_reference(rbtdb, node, 0, isc_rwlocktype_read,
+ rbtdbiter->tree_locked);
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
+
+ rbtdbiter->node = NULL;
+}
+
+static void
+flush_deletions(rbtdb_dbiterator_t *rbtdbiter) {
+ dns_rbtnode_t *node;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)rbtdbiter->common.db;
+ isc_boolean_t was_read_locked = ISC_FALSE;
+ nodelock_t *lock;
+ int i;
+
+ if (rbtdbiter->delete != 0) {
+ /*
+ * Note that "%d node of %d in tree" can report things like
+ * "flush_deletions: 59 nodes of 41 in tree". This means
+ * That some nodes appear on the deletions list more than
+ * once. Only the last occurence will actually be deleted.
+ */
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
+ "flush_deletions: %d nodes of %d in tree",
+ rbtdbiter->delete,
+ dns_rbt_nodecount(rbtdb->tree));
+
+ if (rbtdbiter->tree_locked == isc_rwlocktype_read) {
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ was_read_locked = ISC_TRUE;
+ }
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+ rbtdbiter->tree_locked = isc_rwlocktype_write;
+
+ for (i = 0; i < rbtdbiter->delete; i++) {
+ node = rbtdbiter->deletions[i];
+ lock = &rbtdb->node_locks[node->locknum].lock;
+
+ NODE_LOCK(lock, isc_rwlocktype_read);
+ decrement_reference(rbtdb, node, 0,
+ isc_rwlocktype_read,
+ rbtdbiter->tree_locked);
+ NODE_UNLOCK(lock, isc_rwlocktype_read);
+ }
+
+ rbtdbiter->delete = 0;
+
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
+ if (was_read_locked) {
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ rbtdbiter->tree_locked = isc_rwlocktype_read;
+
+ } else {
+ rbtdbiter->tree_locked = isc_rwlocktype_none;
+ }
+ }
+}
+
+static inline void
+resume_iteration(rbtdb_dbiterator_t *rbtdbiter) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)rbtdbiter->common.db;
+
+ REQUIRE(rbtdbiter->paused);
+ REQUIRE(rbtdbiter->tree_locked == isc_rwlocktype_none);
+
+ RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ rbtdbiter->tree_locked = isc_rwlocktype_read;
+
+ rbtdbiter->paused = ISC_FALSE;
+}
+
+static void
+dbiterator_destroy(dns_dbiterator_t **iteratorp) {
+ rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)(*iteratorp);
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)rbtdbiter->common.db;
+ dns_db_t *db = NULL;
+
+ if (rbtdbiter->tree_locked == isc_rwlocktype_read) {
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ rbtdbiter->tree_locked = isc_rwlocktype_none;
+ } else
+ INSIST(rbtdbiter->tree_locked == isc_rwlocktype_none);
+
+ dereference_iter_node(rbtdbiter);
+
+ flush_deletions(rbtdbiter);
+
+ dns_db_attach(rbtdbiter->common.db, &db);
+ dns_db_detach(&rbtdbiter->common.db);
+
+ dns_rbtnodechain_reset(&rbtdbiter->chain);
+ dns_rbtnodechain_reset(&rbtdbiter->nsec3chain);
+ isc_mem_put(db->mctx, rbtdbiter, sizeof(*rbtdbiter));
+ dns_db_detach(&db);
+
+ *iteratorp = NULL;
+}
+
+static isc_result_t
+dbiterator_first(dns_dbiterator_t *iterator) {
+ isc_result_t result;
+ rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
+ dns_name_t *name, *origin;
+
+ if (rbtdbiter->result != ISC_R_SUCCESS &&
+ rbtdbiter->result != ISC_R_NOMORE)
+ return (rbtdbiter->result);
+
+ if (rbtdbiter->paused)
+ resume_iteration(rbtdbiter);
+
+ dereference_iter_node(rbtdbiter);
+
+ name = dns_fixedname_name(&rbtdbiter->name);
+ origin = dns_fixedname_name(&rbtdbiter->origin);
+ dns_rbtnodechain_reset(&rbtdbiter->chain);
+ dns_rbtnodechain_reset(&rbtdbiter->nsec3chain);
+
+ if (rbtdbiter->nsec3only) {
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ result = dns_rbtnodechain_first(rbtdbiter->current,
+ rbtdb->nsec3, name, origin);
+ } else {
+ rbtdbiter->current = &rbtdbiter->chain;
+ result = dns_rbtnodechain_first(rbtdbiter->current,
+ rbtdb->tree, name, origin);
+ if (!rbtdbiter->nonsec3 && result == ISC_R_NOTFOUND) {
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ result = dns_rbtnodechain_first(rbtdbiter->current,
+ rbtdb->nsec3, name,
+ origin);
+ }
+ }
+ if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
+ result = dns_rbtnodechain_current(rbtdbiter->current, NULL,
+ NULL, &rbtdbiter->node);
+ if (result == ISC_R_SUCCESS) {
+ rbtdbiter->new_origin = ISC_TRUE;
+ reference_iter_node(rbtdbiter);
+ }
+ } else {
+ INSIST(result == ISC_R_NOTFOUND);
+ result = ISC_R_NOMORE; /* The tree is empty. */
+ }
+
+ rbtdbiter->result = result;
+
+ return (result);
+}
+
+static isc_result_t
+dbiterator_last(dns_dbiterator_t *iterator) {
+ isc_result_t result;
+ rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
+ dns_name_t *name, *origin;
+
+ if (rbtdbiter->result != ISC_R_SUCCESS &&
+ rbtdbiter->result != ISC_R_NOMORE)
+ return (rbtdbiter->result);
+
+ if (rbtdbiter->paused)
+ resume_iteration(rbtdbiter);
+
+ dereference_iter_node(rbtdbiter);
+
+ name = dns_fixedname_name(&rbtdbiter->name);
+ origin = dns_fixedname_name(&rbtdbiter->origin);
+ dns_rbtnodechain_reset(&rbtdbiter->chain);
+ dns_rbtnodechain_reset(&rbtdbiter->nsec3chain);
+
+ result = ISC_R_NOTFOUND;
+ if (rbtdbiter->nsec3only && !rbtdbiter->nonsec3) {
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ result = dns_rbtnodechain_last(rbtdbiter->current,
+ rbtdb->nsec3, name, origin);
+ }
+ if (!rbtdbiter->nsec3only && result == ISC_R_NOTFOUND) {
+ rbtdbiter->current = &rbtdbiter->chain;
+ result = dns_rbtnodechain_last(rbtdbiter->current, rbtdb->tree,
+ name, origin);
+ }
+ if (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
+ result = dns_rbtnodechain_current(rbtdbiter->current, NULL,
+ NULL, &rbtdbiter->node);
+ if (result == ISC_R_SUCCESS) {
+ rbtdbiter->new_origin = ISC_TRUE;
+ reference_iter_node(rbtdbiter);
+ }
+ } else {
+ INSIST(result == ISC_R_NOTFOUND);
+ result = ISC_R_NOMORE; /* The tree is empty. */
+ }
+
+ rbtdbiter->result = result;
+
+ return (result);
+}
+
+static isc_result_t
+dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
+ isc_result_t result;
+ rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
+ dns_name_t *iname, *origin;
+
+ if (rbtdbiter->result != ISC_R_SUCCESS &&
+ rbtdbiter->result != ISC_R_NOTFOUND &&
+ rbtdbiter->result != ISC_R_NOMORE)
+ return (rbtdbiter->result);
+
+ if (rbtdbiter->paused)
+ resume_iteration(rbtdbiter);
+
+ dereference_iter_node(rbtdbiter);
+
+ iname = dns_fixedname_name(&rbtdbiter->name);
+ origin = dns_fixedname_name(&rbtdbiter->origin);
+ dns_rbtnodechain_reset(&rbtdbiter->chain);
+ dns_rbtnodechain_reset(&rbtdbiter->nsec3chain);
+
+ if (rbtdbiter->nsec3only) {
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ result = dns_rbt_findnode(rbtdb->nsec3, name, NULL,
+ &rbtdbiter->node,
+ rbtdbiter->current,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+ } else if (rbtdbiter->nonsec3) {
+ rbtdbiter->current = &rbtdbiter->chain;
+ result = dns_rbt_findnode(rbtdb->tree, name, NULL,
+ &rbtdbiter->node,
+ rbtdbiter->current,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+ } else {
+ /*
+ * Stay on main chain if not found on either chain.
+ */
+ rbtdbiter->current = &rbtdbiter->chain;
+ result = dns_rbt_findnode(rbtdb->tree, name, NULL,
+ &rbtdbiter->node,
+ rbtdbiter->current,
+ DNS_RBTFIND_EMPTYDATA, NULL, NULL);
+ if (result == DNS_R_PARTIALMATCH) {
+ dns_rbtnode_t *node = NULL;
+ result = dns_rbt_findnode(rbtdb->nsec3, name, NULL,
+ &node, &rbtdbiter->nsec3chain,
+ DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+ if (result == ISC_R_SUCCESS) {
+ rbtdbiter->node = node;
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ }
+ }
+ }
+
+#if 1
+ if (result == ISC_R_SUCCESS) {
+ result = dns_rbtnodechain_current(rbtdbiter->current, iname,
+ origin, NULL);
+ if (result == ISC_R_SUCCESS) {
+ rbtdbiter->new_origin = ISC_TRUE;
+ reference_iter_node(rbtdbiter);
+ }
+ } else if (result == DNS_R_PARTIALMATCH) {
+ result = ISC_R_NOTFOUND;
+ rbtdbiter->node = NULL;
+ }
+
+ rbtdbiter->result = result;
+#else
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
+ isc_result_t tresult;
+ tresult = dns_rbtnodechain_current(rbtdbiter->current, iname,
+ origin, NULL);
+ if (tresult == ISC_R_SUCCESS) {
+ rbtdbiter->new_origin = ISC_TRUE;
+ reference_iter_node(rbtdbiter);
+ } else {
+ result = tresult;
+ rbtdbiter->node = NULL;
+ }
+ } else
+ rbtdbiter->node = NULL;
+
+ rbtdbiter->result = (result == DNS_R_PARTIALMATCH) ?
+ ISC_R_SUCCESS : result;
+#endif
+
+ return (result);
+}
+
+static isc_result_t
+dbiterator_prev(dns_dbiterator_t *iterator) {
+ isc_result_t result;
+ rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
+ dns_name_t *name, *origin;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
+
+ REQUIRE(rbtdbiter->node != NULL);
+
+ if (rbtdbiter->result != ISC_R_SUCCESS)
+ return (rbtdbiter->result);
+
+ if (rbtdbiter->paused)
+ resume_iteration(rbtdbiter);
+
+ name = dns_fixedname_name(&rbtdbiter->name);
+ origin = dns_fixedname_name(&rbtdbiter->origin);
+ result = dns_rbtnodechain_prev(rbtdbiter->current, name, origin);
+ if (result == ISC_R_NOMORE && !rbtdbiter->nsec3only &&
+ !rbtdbiter->nonsec3 &&
+ &rbtdbiter->nsec3chain == rbtdbiter->current) {
+ rbtdbiter->current = &rbtdbiter->chain;
+ dns_rbtnodechain_reset(rbtdbiter->current);
+ result = dns_rbtnodechain_last(rbtdbiter->current, rbtdb->tree,
+ name, origin);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_NOMORE;
+ }
+
+ dereference_iter_node(rbtdbiter);
+
+ if (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
+ rbtdbiter->new_origin = ISC_TF(result == DNS_R_NEWORIGIN);
+ result = dns_rbtnodechain_current(rbtdbiter->current, NULL,
+ NULL, &rbtdbiter->node);
+ }
+
+ if (result == ISC_R_SUCCESS)
+ reference_iter_node(rbtdbiter);
+
+ rbtdbiter->result = result;
+
+ return (result);
+}
+
+static isc_result_t
+dbiterator_next(dns_dbiterator_t *iterator) {
+ isc_result_t result;
+ rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
+ dns_name_t *name, *origin;
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
+
+ REQUIRE(rbtdbiter->node != NULL);
+
+ if (rbtdbiter->result != ISC_R_SUCCESS)
+ return (rbtdbiter->result);
+
+ if (rbtdbiter->paused)
+ resume_iteration(rbtdbiter);
+
+ name = dns_fixedname_name(&rbtdbiter->name);
+ origin = dns_fixedname_name(&rbtdbiter->origin);
+ result = dns_rbtnodechain_next(rbtdbiter->current, name, origin);
+ if (result == ISC_R_NOMORE && !rbtdbiter->nsec3only &&
+ !rbtdbiter->nonsec3 && &rbtdbiter->chain == rbtdbiter->current) {
+ rbtdbiter->current = &rbtdbiter->nsec3chain;
+ dns_rbtnodechain_reset(rbtdbiter->current);
+ result = dns_rbtnodechain_first(rbtdbiter->current,
+ rbtdb->nsec3, name, origin);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_NOMORE;
+ }
+
+ dereference_iter_node(rbtdbiter);
+
+ if (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
+ rbtdbiter->new_origin = ISC_TF(result == DNS_R_NEWORIGIN);
+ result = dns_rbtnodechain_current(rbtdbiter->current, NULL,
+ NULL, &rbtdbiter->node);
+ }
+ if (result == ISC_R_SUCCESS)
+ reference_iter_node(rbtdbiter);
+
+ rbtdbiter->result = result;
+
+ return (result);
+}
+
+static isc_result_t
+dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
+ dns_name_t *name)
+{
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
+ rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
+ dns_rbtnode_t *node = rbtdbiter->node;
+ isc_result_t result;
+ dns_name_t *nodename = dns_fixedname_name(&rbtdbiter->name);
+ dns_name_t *origin = dns_fixedname_name(&rbtdbiter->origin);
+
+ REQUIRE(rbtdbiter->result == ISC_R_SUCCESS);
+ REQUIRE(rbtdbiter->node != NULL);
+
+ if (rbtdbiter->paused)
+ resume_iteration(rbtdbiter);
+
+ if (name != NULL) {
+ if (rbtdbiter->common.relative_names)
+ origin = NULL;
+ result = dns_name_concatenate(nodename, origin, name, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (rbtdbiter->common.relative_names && rbtdbiter->new_origin)
+ result = DNS_R_NEWORIGIN;
+ } else
+ result = ISC_R_SUCCESS;
+
+ NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
+ new_reference(rbtdb, node);
+ NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
+
+ *nodep = rbtdbiter->node;
+
+ if (iterator->cleaning && result == ISC_R_SUCCESS) {
+ isc_result_t expire_result;
+
+ /*
+ * If the deletion array is full, flush it before trying
+ * to expire the current node. The current node can't
+ * fully deleted while the iteration cursor is still on it.
+ */
+ if (rbtdbiter->delete == DELETION_BATCH_MAX)
+ flush_deletions(rbtdbiter);
+
+ expire_result = expirenode(iterator->db, *nodep, 0);
+
+ /*
+ * expirenode() currently always returns success.
+ */
+ if (expire_result == ISC_R_SUCCESS && node->down == NULL) {
+ unsigned int refs;
+
+ rbtdbiter->deletions[rbtdbiter->delete++] = node;
+ NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);
+ dns_rbtnode_refincrement(node, &refs);
+ INSIST(refs != 0);
+ NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);
+ }
+ }
+
+ return (result);
+}
+
+static isc_result_t
+dbiterator_pause(dns_dbiterator_t *iterator) {
+ dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)iterator->db;
+ rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
+
+ if (rbtdbiter->result != ISC_R_SUCCESS &&
+ rbtdbiter->result != ISC_R_NOMORE)
+ return (rbtdbiter->result);
+
+ if (rbtdbiter->paused)
+ return (ISC_R_SUCCESS);
+
+ rbtdbiter->paused = ISC_TRUE;
+
+ if (rbtdbiter->tree_locked != isc_rwlocktype_none) {
+ INSIST(rbtdbiter->tree_locked == isc_rwlocktype_read);
+ RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read);
+ rbtdbiter->tree_locked = isc_rwlocktype_none;
+ }
+
+ flush_deletions(rbtdbiter);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
+ rbtdb_dbiterator_t *rbtdbiter = (rbtdb_dbiterator_t *)iterator;
+ dns_name_t *origin = dns_fixedname_name(&rbtdbiter->origin);
+
+ if (rbtdbiter->result != ISC_R_SUCCESS)
+ return (rbtdbiter->result);
+
+ return (dns_name_copy(origin, name, NULL));
+}
+
+/*%
+ * Additional cache routines.
+ */
+static isc_result_t
+rdataset_getadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype, dns_acache_t *acache,
+ dns_zone_t **zonep, dns_db_t **dbp,
+ dns_dbversion_t **versionp, dns_dbnode_t **nodep,
+ dns_name_t *fname, dns_message_t *msg,
+ isc_stdtime_t now)
+{
+ dns_rbtdb_t *rbtdb = rdataset->private1;
+ dns_rbtnode_t *rbtnode = rdataset->private2;
+ unsigned char *raw = rdataset->private3; /* RDATASLAB */
+ unsigned int current_count = rdataset->privateuint4;
+ unsigned int count;
+ rdatasetheader_t *header;
+ nodelock_t *nodelock;
+ unsigned int total_count;
+ acachectl_t *acarray;
+ dns_acacheentry_t *entry;
+ isc_result_t result;
+
+ UNUSED(qtype); /* we do not use this value at least for now */
+ UNUSED(acache);
+
+ header = (struct rdatasetheader *)(raw - sizeof(*header));
+
+ total_count = raw[0] * 256 + raw[1];
+ INSIST(total_count > current_count);
+ count = total_count - current_count - 1;
+
+ acarray = NULL;
+
+ nodelock = &rbtdb->node_locks[rbtnode->locknum].lock;
+ NODE_LOCK(nodelock, isc_rwlocktype_read);
+
+ switch (type) {
+ case dns_rdatasetadditional_fromauth:
+ acarray = header->additional_auth;
+ break;
+ case dns_rdatasetadditional_fromcache:
+ acarray = NULL;
+ break;
+ case dns_rdatasetadditional_fromglue:
+ acarray = header->additional_glue;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ if (acarray == NULL) {
+ if (type != dns_rdatasetadditional_fromcache)
+ dns_acache_countquerymiss(acache);
+ NODE_UNLOCK(nodelock, isc_rwlocktype_read);
+ return (ISC_R_NOTFOUND);
+ }
+
+ if (acarray[count].entry == NULL) {
+ dns_acache_countquerymiss(acache);
+ NODE_UNLOCK(nodelock, isc_rwlocktype_read);
+ return (ISC_R_NOTFOUND);
+ }
+
+ entry = NULL;
+ dns_acache_attachentry(acarray[count].entry, &entry);
+
+ NODE_UNLOCK(nodelock, isc_rwlocktype_read);
+
+ result = dns_acache_getentry(entry, zonep, dbp, versionp,
+ nodep, fname, msg, now);
+
+ dns_acache_detachentry(&entry);
+
+ return (result);
+}
+
+static void
+acache_callback(dns_acacheentry_t *entry, void **arg) {
+ dns_rbtdb_t *rbtdb;
+ dns_rbtnode_t *rbtnode;
+ nodelock_t *nodelock;
+ acachectl_t *acarray = NULL;
+ acache_cbarg_t *cbarg;
+ unsigned int count;
+
+ REQUIRE(arg != NULL);
+ cbarg = *arg;
+
+ /*
+ * The caller must hold the entry lock.
+ */
+
+ rbtdb = (dns_rbtdb_t *)cbarg->db;
+ rbtnode = (dns_rbtnode_t *)cbarg->node;
+
+ nodelock = &rbtdb->node_locks[rbtnode->locknum].lock;
+ NODE_LOCK(nodelock, isc_rwlocktype_write);
+
+ switch (cbarg->type) {
+ case dns_rdatasetadditional_fromauth:
+ acarray = cbarg->header->additional_auth;
+ break;
+ case dns_rdatasetadditional_fromglue:
+ acarray = cbarg->header->additional_glue;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ count = cbarg->count;
+ if (acarray != NULL && acarray[count].entry == entry) {
+ acarray[count].entry = NULL;
+ INSIST(acarray[count].cbarg == cbarg);
+ isc_mem_put(rbtdb->common.mctx, cbarg, sizeof(acache_cbarg_t));
+ acarray[count].cbarg = NULL;
+ } else
+ isc_mem_put(rbtdb->common.mctx, cbarg, sizeof(acache_cbarg_t));
+
+ dns_acache_detachentry(&entry);
+
+ NODE_UNLOCK(nodelock, isc_rwlocktype_write);
+
+ dns_db_detachnode((dns_db_t *)rbtdb, (dns_dbnode_t **)(void*)&rbtnode);
+ dns_db_detach((dns_db_t **)(void*)&rbtdb);
+
+ *arg = NULL;
+}
+
+static void
+acache_cancelentry(isc_mem_t *mctx, dns_acacheentry_t *entry,
+ acache_cbarg_t **cbargp)
+{
+ acache_cbarg_t *cbarg;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(entry != NULL);
+ REQUIRE(cbargp != NULL && *cbargp != NULL);
+
+ cbarg = *cbargp;
+
+ dns_acache_cancelentry(entry);
+ dns_db_detachnode(cbarg->db, &cbarg->node);
+ dns_db_detach(&cbarg->db);
+
+ isc_mem_put(mctx, cbarg, sizeof(acache_cbarg_t));
+
+ *cbargp = NULL;
+}
+
+static isc_result_t
+rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype, dns_acache_t *acache,
+ dns_zone_t *zone, dns_db_t *db,
+ dns_dbversion_t *version, dns_dbnode_t *node,
+ dns_name_t *fname)
+{
+ dns_rbtdb_t *rbtdb = rdataset->private1;
+ dns_rbtnode_t *rbtnode = rdataset->private2;
+ unsigned char *raw = rdataset->private3; /* RDATASLAB */
+ unsigned int current_count = rdataset->privateuint4;
+ rdatasetheader_t *header;
+ unsigned int total_count, count;
+ nodelock_t *nodelock;
+ isc_result_t result;
+ acachectl_t *acarray;
+ dns_acacheentry_t *newentry, *oldentry = NULL;
+ acache_cbarg_t *newcbarg, *oldcbarg = NULL;
+
+ UNUSED(qtype);
+
+ if (type == dns_rdatasetadditional_fromcache)
+ return (ISC_R_SUCCESS);
+
+ header = (struct rdatasetheader *)(raw - sizeof(*header));
+
+ total_count = raw[0] * 256 + raw[1];
+ INSIST(total_count > current_count);
+ count = total_count - current_count - 1; /* should be private data */
+
+ newcbarg = isc_mem_get(rbtdb->common.mctx, sizeof(*newcbarg));
+ if (newcbarg == NULL)
+ return (ISC_R_NOMEMORY);
+ newcbarg->type = type;
+ newcbarg->count = count;
+ newcbarg->header = header;
+ newcbarg->db = NULL;
+ dns_db_attach((dns_db_t *)rbtdb, &newcbarg->db);
+ newcbarg->node = NULL;
+ dns_db_attachnode((dns_db_t *)rbtdb, (dns_dbnode_t *)rbtnode,
+ &newcbarg->node);
+ newentry = NULL;
+ result = dns_acache_createentry(acache, (dns_db_t *)rbtdb,
+ acache_callback, newcbarg, &newentry);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+ /* Set cache data in the new entry. */
+ result = dns_acache_setentry(acache, newentry, zone, db,
+ version, node, fname);
+ if (result != ISC_R_SUCCESS)
+ goto fail;
+
+ nodelock = &rbtdb->node_locks[rbtnode->locknum].lock;
+ NODE_LOCK(nodelock, isc_rwlocktype_write);
+
+ acarray = NULL;
+ switch (type) {
+ case dns_rdatasetadditional_fromauth:
+ acarray = header->additional_auth;
+ break;
+ case dns_rdatasetadditional_fromglue:
+ acarray = header->additional_glue;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ if (acarray == NULL) {
+ unsigned int i;
+
+ acarray = isc_mem_get(rbtdb->common.mctx, total_count *
+ sizeof(acachectl_t));
+
+ if (acarray == NULL) {
+ NODE_UNLOCK(nodelock, isc_rwlocktype_write);
+ goto fail;
+ }
+
+ for (i = 0; i < total_count; i++) {
+ acarray[i].entry = NULL;
+ acarray[i].cbarg = NULL;
+ }
+ }
+ switch (type) {
+ case dns_rdatasetadditional_fromauth:
+ header->additional_auth = acarray;
+ break;
+ case dns_rdatasetadditional_fromglue:
+ header->additional_glue = acarray;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ if (acarray[count].entry != NULL) {
+ /*
+ * Swap the entry. Delay cleaning-up the old entry since
+ * it would require a node lock.
+ */
+ oldentry = acarray[count].entry;
+ INSIST(acarray[count].cbarg != NULL);
+ oldcbarg = acarray[count].cbarg;
+ }
+ acarray[count].entry = newentry;
+ acarray[count].cbarg = newcbarg;
+
+ NODE_UNLOCK(nodelock, isc_rwlocktype_write);
+
+ if (oldentry != NULL) {
+ acache_cancelentry(rbtdb->common.mctx, oldentry, &oldcbarg);
+ dns_acache_detachentry(&oldentry);
+ }
+
+ return (ISC_R_SUCCESS);
+
+ fail:
+ if (newcbarg != NULL) {
+ if (newentry != NULL) {
+ acache_cancelentry(rbtdb->common.mctx, newentry,
+ &newcbarg);
+ dns_acache_detachentry(&newentry);
+ } else {
+ dns_db_detachnode((dns_db_t *)rbtdb, &newcbarg->node);
+ dns_db_detach(&newcbarg->db);
+ isc_mem_put(rbtdb->common.mctx, newcbarg,
+ sizeof(*newcbarg));
+ }
+ }
+
+ return (result);
+}
+
+static isc_result_t
+rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type, dns_rdatatype_t qtype)
+{
+ dns_rbtdb_t *rbtdb = rdataset->private1;
+ dns_rbtnode_t *rbtnode = rdataset->private2;
+ unsigned char *raw = rdataset->private3; /* RDATASLAB */
+ unsigned int current_count = rdataset->privateuint4;
+ rdatasetheader_t *header;
+ nodelock_t *nodelock;
+ unsigned int total_count, count;
+ acachectl_t *acarray;
+ dns_acacheentry_t *entry;
+ acache_cbarg_t *cbarg;
+
+ UNUSED(qtype); /* we do not use this value at least for now */
+ UNUSED(acache);
+
+ if (type == dns_rdatasetadditional_fromcache)
+ return (ISC_R_SUCCESS);
+
+ header = (struct rdatasetheader *)(raw - sizeof(*header));
+
+ total_count = raw[0] * 256 + raw[1];
+ INSIST(total_count > current_count);
+ count = total_count - current_count - 1;
+
+ acarray = NULL;
+ entry = NULL;
+
+ nodelock = &rbtdb->node_locks[rbtnode->locknum].lock;
+ NODE_LOCK(nodelock, isc_rwlocktype_write);
+
+ switch (type) {
+ case dns_rdatasetadditional_fromauth:
+ acarray = header->additional_auth;
+ break;
+ case dns_rdatasetadditional_fromglue:
+ acarray = header->additional_glue;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ if (acarray == NULL) {
+ NODE_UNLOCK(nodelock, isc_rwlocktype_write);
+ return (ISC_R_NOTFOUND);
+ }
+
+ entry = acarray[count].entry;
+ if (entry == NULL) {
+ NODE_UNLOCK(nodelock, isc_rwlocktype_write);
+ return (ISC_R_NOTFOUND);
+ }
+
+ acarray[count].entry = NULL;
+ cbarg = acarray[count].cbarg;
+ acarray[count].cbarg = NULL;
+
+ NODE_UNLOCK(nodelock, isc_rwlocktype_write);
+
+ if (entry != NULL) {
+ if (cbarg != NULL)
+ acache_cancelentry(rbtdb->common.mctx, entry, &cbarg);
+ dns_acache_detachentry(&entry);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Routines for LRU-based cache management.
+ */
+
+/*%
+ * See if a given cache entry that is being reused needs to be updated
+ * in the LRU-list. For the non-threaded case this is always true unless the
+ * entry has already been marked as stale; for the threaded case, updating
+ * the entry every time it is referenced might be expensive because it requires
+ * a node write lock. Thus this function returns true if the entry has not been
+ * updated for some period of time. We differentiate the NS or glue address
+ * case and the others since experiments have shown that the former tends to be
+ * accessed relatively infrequently and the cost of cache miss is higher
+ * (e.g., a missing NS records may cause external queries at a higher level
+ * zone, involving more transactions).
+ *
+ * Caller must hold the node (read or write) lock.
+ */
+static inline isc_boolean_t
+need_headerupdate(rdatasetheader_t *header, isc_stdtime_t now) {
+ if ((header->attributes &
+ (RDATASET_ATTR_NONEXISTENT|RDATASET_ATTR_STALE)) != 0)
+ return (ISC_FALSE);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ if (header->type == dns_rdatatype_ns ||
+ (header->trust == dns_trust_glue &&
+ (header->type == dns_rdatatype_a ||
+ header->type == dns_rdatatype_aaaa))) {
+ /*
+ * Glue records are updated if at least 60 seconds have passed
+ * since the previous update time.
+ */
+ return (header->last_used + 60 <= now);
+ }
+
+ /* Other records are updated if 5 minutes have passed. */
+ return (header->last_used + 300 <= now);
+#else
+ UNUSED(now);
+
+ return (ISC_TRUE);
+#endif
+}
+
+/*%
+ * Update the timestamp of a given cache entry and move it to the head
+ * of the corresponding LRU list.
+ *
+ * Caller must hold the node (write) lock.
+ *
+ * Note that the we do NOT touch the heap here, as the TTL has not changed.
+ */
+static void
+update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+ isc_stdtime_t now)
+{
+ INSIST(IS_CACHE(rbtdb));
+
+ /* To be checked: can we really assume this? XXXMLG */
+ INSIST(ISC_LINK_LINKED(header, lru_link));
+
+ ISC_LIST_UNLINK(rbtdb->rdatasets[header->node->locknum],
+ header, lru_link);
+ header->last_used = now;
+ ISC_LIST_PREPEND(rbtdb->rdatasets[header->node->locknum],
+ header, lru_link);
+}
+
+/*%
+ * Purge some expired and/or stale (i.e. unused for some period) cache entries
+ * under an overmem condition. To recover from this condition quickly, up to
+ * 2 entries will be purged. This process is triggered while adding a new
+ * entry, and we specifically avoid purging entries in the same LRU bucket as
+ * the one to which the new entry will belong. Otherwise, we might purge
+ * entries of the same name of different RR types while adding RRsets from a
+ * single response (consider the case where we're adding A and AAAA glue records
+ * of the same NS name).
+ */
+static void
+overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start,
+ isc_stdtime_t now, isc_boolean_t tree_locked)
+{
+ rdatasetheader_t *header, *header_prev;
+ unsigned int locknum;
+ int purgecount = 2;
+
+ for (locknum = (locknum_start + 1) % rbtdb->node_lock_count;
+ locknum != locknum_start && purgecount > 0;
+ locknum = (locknum + 1) % rbtdb->node_lock_count) {
+ NODE_LOCK(&rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_write);
+
+ header = isc_heap_element(rbtdb->heaps[locknum], 1);
+ if (header && header->rdh_ttl <= now - RBTDB_VIRTUAL) {
+ expire_header(rbtdb, header, tree_locked);
+ purgecount--;
+ }
+
+ for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]);
+ header != NULL && purgecount > 0;
+ header = header_prev) {
+ header_prev = ISC_LIST_PREV(header, lru_link);
+ expire_header(rbtdb, header, tree_locked);
+ purgecount--;
+ }
+
+ NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
+ isc_rwlocktype_write);
+ }
+}
+
+static void
+expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header,
+ isc_boolean_t tree_locked)
+{
+ set_ttl(rbtdb, header, 0);
+ header->attributes |= RDATASET_ATTR_STALE;
+ header->node->dirty = 1;
+
+ /*
+ * Caller must hold the node (write) lock.
+ */
+
+ if (dns_rbtnode_refcurrent(header->node) == 0) {
+ /*
+ * If no one else is using the node, we can clean it up now.
+ * We first need to gain a new reference to the node to meet a
+ * requirement of decrement_reference().
+ */
+ new_reference(rbtdb, header->node);
+ decrement_reference(rbtdb, header->node, 0,
+ isc_rwlocktype_write,
+ tree_locked ? isc_rwlocktype_write :
+ isc_rwlocktype_none);
+ }
+}
diff --git a/lib/dns/rbtdb.h b/lib/dns/rbtdb.h
new file mode 100644
index 0000000..b024d13
--- /dev/null
+++ b/lib/dns/rbtdb.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rbtdb.h,v 1.18 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_RBTDB_H
+#define DNS_RBTDB_H 1
+
+#include <isc/lang.h>
+#include <dns/types.h>
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * DNS Red-Black Tree DB Implementation
+ */
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_rbtdb_create(isc_mem_t *mctx, dns_name_t *base, dns_dbtype_t type,
+ dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
+ void *driverarg, dns_db_t **dbp);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RBTDB_H */
diff --git a/lib/dns/rbtdb64.c b/lib/dns/rbtdb64.c
new file mode 100644
index 0000000..5e325fa
--- /dev/null
+++ b/lib/dns/rbtdb64.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rbtdb64.c,v 1.11 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#define DNS_RBTDB_VERSION64 1
+#include "rbtdb.c"
diff --git a/lib/dns/rbtdb64.h b/lib/dns/rbtdb64.h
new file mode 100644
index 0000000..fe11622
--- /dev/null
+++ b/lib/dns/rbtdb64.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rbtdb64.h,v 1.17 2007/06/19 23:47:16 tbox Exp $ */
+
+#ifndef DNS_RBTDB64_H
+#define DNS_RBTDB64_H 1
+
+#include <isc/lang.h>
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * DNS Red-Black Tree DB Implementation with 64-bit version numbers
+ */
+
+#include <dns/db.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+dns_rbtdb64_create(isc_mem_t *mctx, dns_name_t *base, dns_dbtype_t type,
+ dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
+ void *driverarg, dns_db_t **dbp);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RBTDB64_H */
diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c
new file mode 100644
index 0000000..58ade85
--- /dev/null
+++ b/lib/dns/rcode.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: rcode.c,v 1.8 2008/09/25 04:02:38 tbox Exp $ */
+
+#include <config.h>
+#include <ctype.h>
+
+#include <isc/buffer.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/result.h>
+#include <isc/stdio.h>
+#include <isc/stdlib.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/cert.h>
+#include <dns/keyflags.h>
+#include <dns/keyvalues.h>
+#include <dns/rcode.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+#include <dns/secproto.h>
+
+#define RETERR(x) \
+ do { \
+ isc_result_t _r = (x); \
+ if (_r != ISC_R_SUCCESS) \
+ return (_r); \
+ } while (0)
+
+#define NUMBERSIZE sizeof("037777777777") /* 2^32-1 octal + NUL */
+
+#define RCODENAMES \
+ /* standard rcodes */ \
+ { dns_rcode_noerror, "NOERROR", 0}, \
+ { dns_rcode_formerr, "FORMERR", 0}, \
+ { dns_rcode_servfail, "SERVFAIL", 0}, \
+ { dns_rcode_nxdomain, "NXDOMAIN", 0}, \
+ { dns_rcode_notimp, "NOTIMP", 0}, \
+ { dns_rcode_refused, "REFUSED", 0}, \
+ { dns_rcode_yxdomain, "YXDOMAIN", 0}, \
+ { dns_rcode_yxrrset, "YXRRSET", 0}, \
+ { dns_rcode_nxrrset, "NXRRSET", 0}, \
+ { dns_rcode_notauth, "NOTAUTH", 0}, \
+ { dns_rcode_notzone, "NOTZONE", 0},
+
+#define ERCODENAMES \
+ /* extended rcodes */ \
+ { dns_rcode_badvers, "BADVERS", 0}, \
+ { 0, NULL, 0 }
+
+#define TSIGRCODENAMES \
+ /* extended rcodes */ \
+ { dns_tsigerror_badsig, "BADSIG", 0}, \
+ { dns_tsigerror_badkey, "BADKEY", 0}, \
+ { dns_tsigerror_badtime, "BADTIME", 0}, \
+ { dns_tsigerror_badmode, "BADMODE", 0}, \
+ { dns_tsigerror_badname, "BADNAME", 0}, \
+ { dns_tsigerror_badalg, "BADALG", 0}, \
+ { dns_tsigerror_badtrunc, "BADTRUNC", 0}, \
+ { 0, NULL, 0 }
+
+/* RFC2538 section 2.1 */
+
+#define CERTNAMES \
+ { 1, "PKIX", 0}, \
+ { 2, "SPKI", 0}, \
+ { 3, "PGP", 0}, \
+ { 253, "URI", 0}, \
+ { 254, "OID", 0}, \
+ { 0, NULL, 0}
+
+/* RFC2535 section 7, RFC3110 */
+
+#define SECALGNAMES \
+ { DNS_KEYALG_RSAMD5, "RSAMD5", 0 }, \
+ { DNS_KEYALG_RSAMD5, "RSA", 0 }, \
+ { DNS_KEYALG_DH, "DH", 0 }, \
+ { DNS_KEYALG_DSA, "DSA", 0 }, \
+ { DNS_KEYALG_NSEC3DSA, "NSEC3DSA", 0 }, \
+ { DNS_KEYALG_ECC, "ECC", 0 }, \
+ { DNS_KEYALG_RSASHA1, "RSASHA1", 0 }, \
+ { DNS_KEYALG_NSEC3RSASHA1, "NSEC3RSASHA1", 0 }, \
+ { DNS_KEYALG_INDIRECT, "INDIRECT", 0 }, \
+ { DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 }, \
+ { DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, \
+ { 0, NULL, 0}
+
+/* RFC2535 section 7.1 */
+
+#define SECPROTONAMES \
+ { 0, "NONE", 0 }, \
+ { 1, "TLS", 0 }, \
+ { 2, "EMAIL", 0 }, \
+ { 3, "DNSSEC", 0 }, \
+ { 4, "IPSEC", 0 }, \
+ { 255, "ALL", 0 }, \
+ { 0, NULL, 0}
+
+#define HASHALGNAMES \
+ { 1, "SHA-1", 0 }, \
+ { 0, NULL, 0 }
+
+struct tbl {
+ unsigned int value;
+ const char *name;
+ int flags;
+};
+
+static struct tbl rcodes[] = { RCODENAMES ERCODENAMES };
+static struct tbl tsigrcodes[] = { RCODENAMES TSIGRCODENAMES };
+static struct tbl certs[] = { CERTNAMES };
+static struct tbl secalgs[] = { SECALGNAMES };
+static struct tbl secprotos[] = { SECPROTONAMES };
+static struct tbl hashalgs[] = { HASHALGNAMES };
+
+static struct keyflag {
+ const char *name;
+ unsigned int value;
+ unsigned int mask;
+} keyflags[] = {
+ { "NOCONF", 0x4000, 0xC000 },
+ { "NOAUTH", 0x8000, 0xC000 },
+ { "NOKEY", 0xC000, 0xC000 },
+ { "FLAG2", 0x2000, 0x2000 },
+ { "EXTEND", 0x1000, 0x1000 },
+ { "FLAG4", 0x0800, 0x0800 },
+ { "FLAG5", 0x0400, 0x0400 },
+ { "USER", 0x0000, 0x0300 },
+ { "ZONE", 0x0100, 0x0300 },
+ { "HOST", 0x0200, 0x0300 },
+ { "NTYP3", 0x0300, 0x0300 },
+ { "FLAG8", 0x0080, 0x0080 },
+ { "FLAG9", 0x0040, 0x0040 },
+ { "FLAG10", 0x0020, 0x0020 },
+ { "FLAG11", 0x0010, 0x0010 },
+ { "SIG0", 0x0000, 0x000F },
+ { "SIG1", 0x0001, 0x000F },
+ { "SIG2", 0x0002, 0x000F },
+ { "SIG3", 0x0003, 0x000F },
+ { "SIG4", 0x0004, 0x000F },
+ { "SIG5", 0x0005, 0x000F },
+ { "SIG6", 0x0006, 0x000F },
+ { "SIG7", 0x0007, 0x000F },
+ { "SIG8", 0x0008, 0x000F },
+ { "SIG9", 0x0009, 0x000F },
+ { "SIG10", 0x000A, 0x000F },
+ { "SIG11", 0x000B, 0x000F },
+ { "SIG12", 0x000C, 0x000F },
+ { "SIG13", 0x000D, 0x000F },
+ { "SIG14", 0x000E, 0x000F },
+ { "SIG15", 0x000F, 0x000F },
+ { "KSK", DNS_KEYFLAG_KSK, DNS_KEYFLAG_KSK },
+ { NULL, 0, 0 }
+};
+
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target) {
+ unsigned int l;
+ isc_region_t region;
+
+ isc_buffer_availableregion(target, &region);
+ l = strlen(source);
+
+ if (l > region.length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(region.base, source, l);
+ isc_buffer_add(target, l);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+maybe_numeric(unsigned int *valuep, isc_textregion_t *source,
+ unsigned int max, isc_boolean_t hex_allowed)
+{
+ isc_result_t result;
+ isc_uint32_t n;
+ char buffer[NUMBERSIZE];
+
+ if (! isdigit(source->base[0] & 0xff) ||
+ source->length > NUMBERSIZE - 1)
+ return (ISC_R_BADNUMBER);
+
+ /*
+ * We have a potential number. Try to parse it with
+ * isc_parse_uint32(). isc_parse_uint32() requires
+ * null termination, so we must make a copy.
+ */
+ strncpy(buffer, source->base, NUMBERSIZE);
+ INSIST(buffer[source->length] == '\0');
+
+ result = isc_parse_uint32(&n, buffer, 10);
+ if (result == ISC_R_BADNUMBER && hex_allowed)
+ result = isc_parse_uint32(&n, buffer, 16);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (n > max)
+ return (ISC_R_RANGE);
+ *valuep = n;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dns_mnemonic_fromtext(unsigned int *valuep, isc_textregion_t *source,
+ struct tbl *table, unsigned int max)
+{
+ isc_result_t result;
+ int i;
+
+ result = maybe_numeric(valuep, source, max, ISC_FALSE);
+ if (result != ISC_R_BADNUMBER)
+ return (result);
+
+ for (i = 0; table[i].name != NULL; i++) {
+ unsigned int n;
+ n = strlen(table[i].name);
+ if (n == source->length &&
+ strncasecmp(source->base, table[i].name, n) == 0) {
+ *valuep = table[i].value;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (DNS_R_UNKNOWN);
+}
+
+static isc_result_t
+dns_mnemonic_totext(unsigned int value, isc_buffer_t *target,
+ struct tbl *table)
+{
+ int i = 0;
+ char buf[sizeof("4294967296")];
+ while (table[i].name != NULL) {
+ if (table[i].value == value) {
+ return (str_totext(table[i].name, target));
+ }
+ i++;
+ }
+ snprintf(buf, sizeof(buf), "%u", value);
+ return (str_totext(buf, target));
+}
+
+isc_result_t
+dns_rcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) {
+ unsigned int value;
+ RETERR(dns_mnemonic_fromtext(&value, source, rcodes, 0xffff));
+ *rcodep = value;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
+ return (dns_mnemonic_totext(rcode, target, rcodes));
+}
+
+isc_result_t
+dns_tsigrcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) {
+ unsigned int value;
+ RETERR(dns_mnemonic_fromtext(&value, source, tsigrcodes, 0xffff));
+ *rcodep = value;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_tsigrcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
+ return (dns_mnemonic_totext(rcode, target, tsigrcodes));
+}
+
+isc_result_t
+dns_cert_fromtext(dns_cert_t *certp, isc_textregion_t *source) {
+ unsigned int value;
+ RETERR(dns_mnemonic_fromtext(&value, source, certs, 0xffff));
+ *certp = value;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_cert_totext(dns_cert_t cert, isc_buffer_t *target) {
+ return (dns_mnemonic_totext(cert, target, certs));
+}
+
+isc_result_t
+dns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source) {
+ unsigned int value;
+ RETERR(dns_mnemonic_fromtext(&value, source, secalgs, 0xff));
+ *secalgp = value;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) {
+ return (dns_mnemonic_totext(secalg, target, secalgs));
+}
+
+isc_result_t
+dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source) {
+ unsigned int value;
+ RETERR(dns_mnemonic_fromtext(&value, source, secprotos, 0xff));
+ *secprotop = value;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_secproto_totext(dns_secproto_t secproto, isc_buffer_t *target) {
+ return (dns_mnemonic_totext(secproto, target, secprotos));
+}
+
+isc_result_t
+dns_hashalg_fromtext(unsigned char *hashalg, isc_textregion_t *source) {
+ unsigned int value;
+ RETERR(dns_mnemonic_fromtext(&value, source, hashalgs, 0xff));
+ *hashalg = value;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source)
+{
+ isc_result_t result;
+ char *text, *end;
+ unsigned int value, mask;
+
+ result = maybe_numeric(&value, source, 0xffff, ISC_TRUE);
+ if (result == ISC_R_SUCCESS) {
+ *flagsp = value;
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_BADNUMBER)
+ return (result);
+
+ text = source->base;
+ end = source->base + source->length;
+ value = mask = 0;
+
+ while (text < end) {
+ struct keyflag *p;
+ unsigned int len;
+ char *delim = memchr(text, '|', end - text);
+ if (delim != NULL)
+ len = delim - text;
+ else
+ len = end - text;
+ for (p = keyflags; p->name != NULL; p++) {
+ if (strncasecmp(p->name, text, len) == 0)
+ break;
+ }
+ if (p->name == NULL)
+ return (DNS_R_UNKNOWNFLAG);
+ value |= p->value;
+#ifdef notyet
+ if ((mask & p->mask) != 0)
+ warn("overlapping key flags");
+#endif
+ mask |= p->mask;
+ text += len;
+ if (delim != NULL)
+ text++; /* Skip "|" */
+ }
+ *flagsp = value;
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This uses lots of hard coded values, but how often do we actually
+ * add classes?
+ */
+isc_result_t
+dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source) {
+#define COMPARE(string, rdclass) \
+ if (((sizeof(string) - 1) == source->length) \
+ && (strncasecmp(source->base, string, source->length) == 0)) { \
+ *classp = rdclass; \
+ return (ISC_R_SUCCESS); \
+ }
+
+ switch (tolower((unsigned char)source->base[0])) {
+ case 'a':
+ COMPARE("any", dns_rdataclass_any);
+ break;
+ case 'c':
+ /*
+ * RFC1035 says the mnemonic for the CHAOS class is CH,
+ * but historical BIND practice is to call it CHAOS.
+ * We will accept both forms, but only generate CH.
+ */
+ COMPARE("ch", dns_rdataclass_chaos);
+ COMPARE("chaos", dns_rdataclass_chaos);
+
+ if (source->length > 5 &&
+ source->length < (5 + sizeof("65000")) &&
+ strncasecmp("class", source->base, 5) == 0) {
+ char buf[sizeof("65000")];
+ char *endp;
+ unsigned int val;
+
+ strncpy(buf, source->base + 5, source->length - 5);
+ buf[source->length - 5] = '\0';
+ val = strtoul(buf, &endp, 10);
+ if (*endp == '\0' && val <= 0xffff) {
+ *classp = (dns_rdataclass_t)val;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ break;
+ case 'h':
+ COMPARE("hs", dns_rdataclass_hs);
+ COMPARE("hesiod", dns_rdataclass_hs);
+ break;
+ case 'i':
+ COMPARE("in", dns_rdataclass_in);
+ break;
+ case 'n':
+ COMPARE("none", dns_rdataclass_none);
+ break;
+ case 'r':
+ COMPARE("reserved0", dns_rdataclass_reserved0);
+ break;
+ }
+
+#undef COMPARE
+
+ return (DNS_R_UNKNOWN);
+}
+
+isc_result_t
+dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target) {
+ char buf[sizeof("CLASS65535")];
+
+ switch (rdclass) {
+ case dns_rdataclass_any:
+ return (str_totext("ANY", target));
+ case dns_rdataclass_chaos:
+ return (str_totext("CH", target));
+ case dns_rdataclass_hs:
+ return (str_totext("HS", target));
+ case dns_rdataclass_in:
+ return (str_totext("IN", target));
+ case dns_rdataclass_none:
+ return (str_totext("NONE", target));
+ case dns_rdataclass_reserved0:
+ return (str_totext("RESERVED0", target));
+ default:
+ snprintf(buf, sizeof(buf), "CLASS%u", rdclass);
+ return (str_totext(buf, target));
+ }
+}
+
+void
+dns_rdataclass_format(dns_rdataclass_t rdclass,
+ char *array, unsigned int size)
+{
+ isc_result_t result;
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, array, size);
+ result = dns_rdataclass_totext(rdclass, &buf);
+ /*
+ * Null terminate.
+ */
+ if (result == ISC_R_SUCCESS) {
+ if (isc_buffer_availablelength(&buf) >= 1)
+ isc_buffer_putuint8(&buf, 0);
+ else
+ result = ISC_R_NOSPACE;
+ }
+ if (result != ISC_R_SUCCESS) {
+ snprintf(array, size, "<unknown>");
+ array[size - 1] = '\0';
+ }
+}
diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c
new file mode 100644
index 0000000..d35900b
--- /dev/null
+++ b/lib/dns/rdata.c
@@ -0,0 +1,1769 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: rdata.c,v 1.199 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+#include <ctype.h>
+
+#include <isc/base64.h>
+#include <isc/hex.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/stdlib.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/cert.h>
+#include <dns/compress.h>
+#include <dns/enumtype.h>
+#include <dns/keyflags.h>
+#include <dns/keyvalues.h>
+#include <dns/rcode.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/secalg.h>
+#include <dns/secproto.h>
+#include <dns/time.h>
+#include <dns/ttl.h>
+
+#define RETERR(x) \
+ do { \
+ isc_result_t _r = (x); \
+ if (_r != ISC_R_SUCCESS) \
+ return (_r); \
+ } while (0)
+
+#define RETTOK(x) \
+ do { \
+ isc_result_t _r = (x); \
+ if (_r != ISC_R_SUCCESS) { \
+ isc_lex_ungettoken(lexer, &token); \
+ return (_r); \
+ } \
+ } while (0)
+
+#define DNS_AS_STR(t) ((t).value.as_textregion.base)
+
+#define ARGS_FROMTEXT int rdclass, dns_rdatatype_t type, \
+ isc_lex_t *lexer, dns_name_t *origin, \
+ unsigned int options, isc_buffer_t *target, \
+ dns_rdatacallbacks_t *callbacks
+
+#define ARGS_TOTEXT dns_rdata_t *rdata, dns_rdata_textctx_t *tctx, \
+ isc_buffer_t *target
+
+#define ARGS_FROMWIRE int rdclass, dns_rdatatype_t type, \
+ isc_buffer_t *source, dns_decompress_t *dctx, \
+ unsigned int options, isc_buffer_t *target
+
+#define ARGS_TOWIRE dns_rdata_t *rdata, dns_compress_t *cctx, \
+ isc_buffer_t *target
+
+#define ARGS_COMPARE const dns_rdata_t *rdata1, const dns_rdata_t *rdata2
+
+#define ARGS_FROMSTRUCT int rdclass, dns_rdatatype_t type, \
+ void *source, isc_buffer_t *target
+
+#define ARGS_TOSTRUCT dns_rdata_t *rdata, void *target, isc_mem_t *mctx
+
+#define ARGS_FREESTRUCT void *source
+
+#define ARGS_ADDLDATA dns_rdata_t *rdata, dns_additionaldatafunc_t add, \
+ void *arg
+
+#define ARGS_DIGEST dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg
+
+#define ARGS_CHECKOWNER dns_name_t *name, dns_rdataclass_t rdclass, \
+ dns_rdatatype_t type, isc_boolean_t wildcard
+
+#define ARGS_CHECKNAMES dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad
+
+
+/*%
+ * Context structure for the totext_ functions.
+ * Contains formatting options for rdata-to-text
+ * conversion.
+ */
+typedef struct dns_rdata_textctx {
+ dns_name_t *origin; /*%< Current origin, or NULL. */
+ unsigned int flags; /*%< DNS_STYLEFLAG_* */
+ unsigned int width; /*%< Width of rdata column. */
+ const char *linebreak; /*%< Line break string. */
+} dns_rdata_textctx_t;
+
+static isc_result_t
+txt_totext(isc_region_t *source, isc_buffer_t *target);
+
+static isc_result_t
+txt_fromtext(isc_textregion_t *source, isc_buffer_t *target);
+
+static isc_result_t
+txt_fromwire(isc_buffer_t *source, isc_buffer_t *target);
+
+static isc_boolean_t
+name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target);
+
+static unsigned int
+name_length(dns_name_t *name);
+
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target);
+
+static isc_result_t
+inet_totext(int af, isc_region_t *src, isc_buffer_t *target);
+
+static isc_boolean_t
+buffer_empty(isc_buffer_t *source);
+
+static void
+buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region);
+
+static isc_result_t
+uint32_tobuffer(isc_uint32_t, isc_buffer_t *target);
+
+static isc_result_t
+uint16_tobuffer(isc_uint32_t, isc_buffer_t *target);
+
+static isc_result_t
+uint8_tobuffer(isc_uint32_t, isc_buffer_t *target);
+
+static isc_result_t
+name_tobuffer(dns_name_t *name, isc_buffer_t *target);
+
+static isc_uint32_t
+uint32_fromregion(isc_region_t *region);
+
+static isc_uint16_t
+uint16_fromregion(isc_region_t *region);
+
+static isc_uint8_t
+uint8_fromregion(isc_region_t *region);
+
+static isc_uint8_t
+uint8_consume_fromregion(isc_region_t *region);
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
+
+static int
+hexvalue(char value);
+
+static int
+decvalue(char value);
+
+static isc_result_t
+btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target);
+
+static isc_result_t
+atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target);
+
+static void
+default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *, ...)
+ ISC_FORMAT_PRINTF(2, 3);
+
+static void
+fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
+ dns_rdatacallbacks_t *callbacks, const char *name,
+ unsigned long line, isc_token_t *token, isc_result_t result);
+
+static void
+fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks);
+
+static isc_result_t
+rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
+ isc_buffer_t *target);
+
+static void
+warn_badname(dns_name_t *name, isc_lex_t *lexer,
+ dns_rdatacallbacks_t *callbacks);
+
+static void
+warn_badmx(isc_token_t *token, isc_lex_t *lexer,
+ dns_rdatacallbacks_t *callbacks);
+
+static isc_uint16_t
+uint16_consume_fromregion(isc_region_t *region);
+
+static inline int
+getquad(const void *src, struct in_addr *dst,
+ isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks)
+{
+ int result;
+ struct in_addr *tmp;
+
+ result = inet_aton(src, dst);
+ if (result == 1 && callbacks != NULL &&
+ inet_pton(AF_INET, src, &tmp) != 1) {
+ const char *name = isc_lex_getsourcename(lexer);
+ if (name == NULL)
+ name = "UNKNOWN";
+ (*callbacks->warn)(callbacks, "%s:%lu: \"%s\" "
+ "is not a decimal dotted quad", name,
+ isc_lex_getsourceline(lexer), src);
+ }
+ return (result);
+}
+
+static inline isc_result_t
+name_duporclone(dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
+
+ if (mctx != NULL)
+ return (dns_name_dup(source, mctx, target));
+ dns_name_clone(source, target);
+ return (ISC_R_SUCCESS);
+}
+
+static inline void *
+mem_maybedup(isc_mem_t *mctx, void *source, size_t length) {
+ void *new;
+
+ if (mctx == NULL)
+ return (source);
+ new = isc_mem_allocate(mctx, length);
+ if (new != NULL)
+ memcpy(new, source, length);
+
+ return (new);
+}
+
+static const char hexdigits[] = "0123456789abcdef";
+static const char decdigits[] = "0123456789";
+
+#include "code.h"
+
+#define META 0x0001
+#define RESERVED 0x0002
+
+/***
+ *** Initialization
+ ***/
+
+void
+dns_rdata_init(dns_rdata_t *rdata) {
+
+ REQUIRE(rdata != NULL);
+
+ rdata->data = NULL;
+ rdata->length = 0;
+ rdata->rdclass = 0;
+ rdata->type = 0;
+ rdata->flags = 0;
+ ISC_LINK_INIT(rdata, link);
+ /* 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) {
+
+ REQUIRE(rdata != NULL);
+
+ REQUIRE(!ISC_LINK_LINKED(rdata, link));
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+
+ rdata->data = NULL;
+ rdata->length = 0;
+ rdata->rdclass = 0;
+ rdata->type = 0;
+ rdata->flags = 0;
+}
+
+/***
+ ***
+ ***/
+
+void
+dns_rdata_clone(const dns_rdata_t *src, dns_rdata_t *target) {
+
+ REQUIRE(src != NULL);
+ REQUIRE(target != NULL);
+
+ REQUIRE(DNS_RDATA_INITIALIZED(target));
+
+ REQUIRE(DNS_RDATA_VALIDFLAGS(src));
+ REQUIRE(DNS_RDATA_VALIDFLAGS(target));
+
+ target->data = src->data;
+ target->length = src->length;
+ target->rdclass = src->rdclass;
+ target->type = src->type;
+ target->flags = src->flags;
+}
+
+
+/***
+ *** Comparisons
+ ***/
+
+int
+dns_rdata_compare(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);
+
+ COMPARESWITCH
+
+ 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
+ ***/
+
+void
+dns_rdata_fromregion(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, isc_region_t *r)
+{
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(DNS_RDATA_INITIALIZED(rdata));
+ REQUIRE(r != NULL);
+
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+
+ rdata->data = r->base;
+ rdata->length = r->length;
+ rdata->rdclass = rdclass;
+ rdata->type = type;
+ rdata->flags = 0;
+}
+
+void
+dns_rdata_toregion(const dns_rdata_t *rdata, isc_region_t *r) {
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(r != NULL);
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+
+ r->base = rdata->data;
+ r->length = rdata->length;
+}
+
+isc_result_t
+dns_rdata_fromwire(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, isc_buffer_t *source,
+ dns_decompress_t *dctx, unsigned int options,
+ isc_buffer_t *target)
+{
+ isc_result_t result = ISC_R_NOTIMPLEMENTED;
+ isc_region_t region;
+ isc_buffer_t ss;
+ isc_buffer_t st;
+ isc_boolean_t use_default = ISC_FALSE;
+ isc_uint32_t activelength;
+
+ REQUIRE(dctx != NULL);
+ if (rdata != NULL) {
+ REQUIRE(DNS_RDATA_INITIALIZED(rdata));
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+ }
+
+ if (type == 0)
+ return (DNS_R_FORMERR);
+
+ ss = *source;
+ st = *target;
+
+ activelength = isc_buffer_activelength(source);
+ INSIST(activelength < 65536);
+
+ FROMWIRESWITCH
+
+ if (use_default) {
+ if (activelength > isc_buffer_availablelength(target))
+ result = ISC_R_NOSPACE;
+ else {
+ isc_buffer_putmem(target, isc_buffer_current(source),
+ activelength);
+ isc_buffer_forward(source, activelength);
+ result = ISC_R_SUCCESS;
+ }
+ }
+
+ /*
+ * We should have consumed all of our buffer.
+ */
+ if (result == ISC_R_SUCCESS && !buffer_empty(source))
+ result = DNS_R_EXTRADATA;
+
+ if (rdata != NULL && result == ISC_R_SUCCESS) {
+ region.base = isc_buffer_used(&st);
+ region.length = isc_buffer_usedlength(target) -
+ isc_buffer_usedlength(&st);
+ dns_rdata_fromregion(rdata, rdclass, type, &region);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ *source = ss;
+ *target = st;
+ }
+ return (result);
+}
+
+isc_result_t
+dns_rdata_towire(dns_rdata_t *rdata, dns_compress_t *cctx,
+ isc_buffer_t *target)
+{
+ isc_result_t result = ISC_R_NOTIMPLEMENTED;
+ isc_boolean_t use_default = ISC_FALSE;
+ isc_region_t tr;
+ isc_buffer_t st;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+
+ /*
+ * Some DynDNS meta-RRs have empty rdata.
+ */
+ if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
+ INSIST(rdata->length == 0);
+ return (ISC_R_SUCCESS);
+ }
+
+ st = *target;
+
+ TOWIRESWITCH
+
+ if (use_default) {
+ isc_buffer_availableregion(target, &tr);
+ if (tr.length < rdata->length)
+ return (ISC_R_NOSPACE);
+ memcpy(tr.base, rdata->data, rdata->length);
+ isc_buffer_add(target, rdata->length);
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS) {
+ *target = st;
+ INSIST(target->used < 65536);
+ dns_compress_rollback(cctx, (isc_uint16_t)target->used);
+ }
+ return (result);
+}
+
+/*
+ * If the binary data in 'src' is valid uncompressed wire format
+ * rdata of class 'rdclass' and type 'type', return ISC_R_SUCCESS
+ * and copy the validated rdata to 'dest'. Otherwise return an error.
+ */
+static isc_result_t
+rdata_validate(isc_buffer_t *src, isc_buffer_t *dest, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type)
+{
+ dns_decompress_t dctx;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+
+ dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
+ isc_buffer_setactive(src, isc_buffer_usedlength(src));
+ result = dns_rdata_fromwire(&rdata, rdclass, type, src,
+ &dctx, 0, dest);
+ dns_decompress_invalidate(&dctx);
+
+ return (result);
+}
+
+static isc_result_t
+unknown_fromtext(dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ isc_lex_t *lexer, isc_mem_t *mctx, isc_buffer_t *target)
+{
+ isc_result_t result;
+ isc_buffer_t *buf = NULL;
+ isc_token_t token;
+
+ if (type == 0 || dns_rdatatype_ismeta(type))
+ return (DNS_R_METATYPE);
+
+ result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE);
+ if (result == ISC_R_SUCCESS && token.value.as_ulong > 65535U)
+ return (ISC_R_RANGE);
+ result = isc_buffer_allocate(mctx, &buf, token.value.as_ulong);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = isc_hex_tobuffer(lexer, buf,
+ (unsigned int)token.value.as_ulong);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ if (isc_buffer_usedlength(buf) != token.value.as_ulong) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto failure;
+ }
+
+ if (dns_rdatatype_isknown(type)) {
+ result = rdata_validate(buf, target, rdclass, type);
+ } else {
+ isc_region_t r;
+ isc_buffer_usedregion(buf, &r);
+ result = isc_buffer_copyregion(target, &r);
+ }
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ isc_buffer_free(&buf);
+ return (ISC_R_SUCCESS);
+
+ failure:
+ isc_buffer_free(&buf);
+ return (result);
+}
+
+isc_result_t
+dns_rdata_fromtext(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, isc_lex_t *lexer,
+ dns_name_t *origin, unsigned int options, isc_mem_t *mctx,
+ isc_buffer_t *target, dns_rdatacallbacks_t *callbacks)
+{
+ isc_result_t result = ISC_R_NOTIMPLEMENTED;
+ isc_region_t region;
+ isc_buffer_t st;
+ isc_token_t token;
+ unsigned int lexoptions = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
+ ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
+ char *name;
+ unsigned long line;
+ void (*callback)(dns_rdatacallbacks_t *, const char *, ...);
+ isc_result_t tresult;
+
+ REQUIRE(origin == NULL || dns_name_isabsolute(origin) == ISC_TRUE);
+ if (rdata != NULL) {
+ REQUIRE(DNS_RDATA_INITIALIZED(rdata));
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+ }
+ if (callbacks != NULL) {
+ REQUIRE(callbacks->warn != NULL);
+ REQUIRE(callbacks->error != NULL);
+ }
+
+ st = *target;
+
+ if (callbacks != NULL)
+ callback = callbacks->error;
+ else
+ callback = default_fromtext_callback;
+
+ result = isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ ISC_FALSE);
+ if (result != ISC_R_SUCCESS) {
+ name = isc_lex_getsourcename(lexer);
+ line = isc_lex_getsourceline(lexer);
+ fromtext_error(callback, callbacks, name, line,
+ &token, result);
+ return (result);
+ }
+
+ if (strcmp(DNS_AS_STR(token), "\\#") == 0)
+ result = unknown_fromtext(rdclass, type, lexer, mctx, target);
+ else {
+ isc_lex_ungettoken(lexer, &token);
+
+ FROMTEXTSWITCH
+ }
+
+ /*
+ * Consume to end of line / file.
+ * If not at end of line initially set error code.
+ * Call callback via fromtext_error once if there was an error.
+ */
+ do {
+ name = isc_lex_getsourcename(lexer);
+ line = isc_lex_getsourceline(lexer);
+ tresult = isc_lex_gettoken(lexer, lexoptions, &token);
+ if (tresult != ISC_R_SUCCESS) {
+ if (result == ISC_R_SUCCESS)
+ result = tresult;
+ if (callback != NULL)
+ fromtext_error(callback, callbacks, name,
+ line, NULL, result);
+ break;
+ } else if (token.type != isc_tokentype_eol &&
+ token.type != isc_tokentype_eof) {
+ if (result == ISC_R_SUCCESS)
+ result = DNS_R_EXTRATOKEN;
+ if (callback != NULL) {
+ fromtext_error(callback, callbacks, name,
+ line, &token, result);
+ callback = NULL;
+ }
+ } else if (result != ISC_R_SUCCESS && callback != NULL) {
+ fromtext_error(callback, callbacks, name, line,
+ &token, result);
+ break;
+ } else {
+ if (token.type == isc_tokentype_eof)
+ fromtext_warneof(lexer, callbacks);
+ break;
+ }
+ } while (1);
+
+ if (rdata != NULL && result == ISC_R_SUCCESS) {
+ region.base = isc_buffer_used(&st);
+ region.length = isc_buffer_usedlength(target) -
+ isc_buffer_usedlength(&st);
+ dns_rdata_fromregion(rdata, rdclass, type, &region);
+ }
+ if (result != ISC_R_SUCCESS) {
+ *target = st;
+ }
+ return (result);
+}
+
+static isc_result_t
+rdata_totext(dns_rdata_t *rdata, dns_rdata_textctx_t *tctx,
+ isc_buffer_t *target)
+{
+ isc_result_t result = ISC_R_NOTIMPLEMENTED;
+ isc_boolean_t use_default = ISC_FALSE;
+ char buf[sizeof("65535")];
+ isc_region_t sr;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(tctx->origin == NULL ||
+ dns_name_isabsolute(tctx->origin) == ISC_TRUE);
+
+ /*
+ * Some DynDNS meta-RRs have empty rdata.
+ */
+ if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
+ INSIST(rdata->length == 0);
+ return (ISC_R_SUCCESS);
+ }
+
+ TOTEXTSWITCH
+
+ if (use_default) {
+ strlcpy(buf, "\\# ", sizeof(buf));
+ result = str_totext(buf, target);
+ dns_rdata_toregion(rdata, &sr);
+ INSIST(sr.length < 65536);
+ snprintf(buf, sizeof(buf), "%u", sr.length);
+ result = str_totext(buf, target);
+ if (sr.length != 0 && result == ISC_R_SUCCESS) {
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ result = str_totext(" ( ", target);
+ else
+ result = str_totext(" ", target);
+ if (result == ISC_R_SUCCESS)
+ result = isc_hex_totext(&sr, tctx->width - 2,
+ tctx->linebreak,
+ target);
+ if (result == ISC_R_SUCCESS &&
+ (tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ result = str_totext(" )", target);
+ }
+ }
+
+ return (result);
+}
+
+isc_result_t
+dns_rdata_totext(dns_rdata_t *rdata, dns_name_t *origin, isc_buffer_t *target)
+{
+ dns_rdata_textctx_t tctx;
+
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+
+ /*
+ * Set up formatting options for single-line output.
+ */
+ tctx.origin = origin;
+ tctx.flags = 0;
+ tctx.width = 60;
+ tctx.linebreak = " ";
+ return (rdata_totext(rdata, &tctx, target));
+}
+
+isc_result_t
+dns_rdata_tofmttext(dns_rdata_t *rdata, dns_name_t *origin,
+ unsigned int flags, unsigned int width,
+ char *linebreak, isc_buffer_t *target)
+{
+ dns_rdata_textctx_t tctx;
+
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+
+ /*
+ * Set up formatting options for formatted output.
+ */
+ tctx.origin = origin;
+ tctx.flags = flags;
+ if ((flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ tctx.width = width;
+ tctx.linebreak = linebreak;
+ } else {
+ tctx.width = 60; /* Used for hex word length only. */
+ tctx.linebreak = " ";
+ }
+ return (rdata_totext(rdata, &tctx, target));
+}
+
+isc_result_t
+dns_rdata_fromstruct(dns_rdata_t *rdata, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, void *source,
+ isc_buffer_t *target)
+{
+ isc_result_t result = ISC_R_NOTIMPLEMENTED;
+ isc_buffer_t st;
+ isc_region_t region;
+ isc_boolean_t use_default = ISC_FALSE;
+
+ REQUIRE(source != NULL);
+ if (rdata != NULL) {
+ REQUIRE(DNS_RDATA_INITIALIZED(rdata));
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+ }
+
+ st = *target;
+
+ FROMSTRUCTSWITCH
+
+ if (use_default)
+ (void)NULL;
+
+ if (rdata != NULL && result == ISC_R_SUCCESS) {
+ region.base = isc_buffer_used(&st);
+ region.length = isc_buffer_usedlength(target) -
+ isc_buffer_usedlength(&st);
+ dns_rdata_fromregion(rdata, rdclass, type, &region);
+ }
+ if (result != ISC_R_SUCCESS)
+ *target = st;
+ return (result);
+}
+
+isc_result_t
+dns_rdata_tostruct(dns_rdata_t *rdata, void *target, isc_mem_t *mctx) {
+ isc_result_t result = ISC_R_NOTIMPLEMENTED;
+ isc_boolean_t use_default = ISC_FALSE;
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+
+ TOSTRUCTSWITCH
+
+ if (use_default)
+ (void)NULL;
+
+ return (result);
+}
+
+void
+dns_rdata_freestruct(void *source) {
+ dns_rdatacommon_t *common = source;
+ REQUIRE(source != NULL);
+
+ FREESTRUCTSWITCH
+}
+
+isc_result_t
+dns_rdata_additionaldata(dns_rdata_t *rdata, dns_additionaldatafunc_t add,
+ void *arg)
+{
+ isc_result_t result = ISC_R_NOTIMPLEMENTED;
+ isc_boolean_t use_default = ISC_FALSE;
+
+ /*
+ * Call 'add' for each name and type from 'rdata' which is subject to
+ * additional section processing.
+ */
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(add != NULL);
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+
+ ADDITIONALDATASWITCH
+
+ /* No additional processing for unknown types */
+ if (use_default)
+ result = ISC_R_SUCCESS;
+
+ return (result);
+}
+
+isc_result_t
+dns_rdata_digest(dns_rdata_t *rdata, dns_digestfunc_t digest, void *arg) {
+ isc_result_t result = ISC_R_NOTIMPLEMENTED;
+ isc_boolean_t use_default = ISC_FALSE;
+ isc_region_t r;
+
+ /*
+ * Send 'rdata' in DNSSEC canonical form to 'digest'.
+ */
+
+ REQUIRE(rdata != NULL);
+ REQUIRE(digest != NULL);
+ REQUIRE(DNS_RDATA_VALIDFLAGS(rdata));
+
+ DIGESTSWITCH
+
+ if (use_default) {
+ dns_rdata_toregion(rdata, &r);
+ result = (digest)(arg, &r);
+ }
+
+ return (result);
+}
+
+isc_boolean_t
+dns_rdata_checkowner(dns_name_t *name, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, isc_boolean_t wildcard)
+{
+ isc_boolean_t result;
+
+ CHECKOWNERSWITCH
+ return (result);
+}
+
+isc_boolean_t
+dns_rdata_checknames(dns_rdata_t *rdata, dns_name_t *owner, dns_name_t *bad)
+{
+ isc_boolean_t result;
+
+ CHECKNAMESSWITCH
+ return (result);
+}
+
+unsigned int
+dns_rdatatype_attributes(dns_rdatatype_t type)
+{
+ RDATATYPE_ATTRIBUTE_SW
+ if (type >= (dns_rdatatype_t)128 && type < (dns_rdatatype_t)255)
+ return (DNS_RDATATYPEATTR_UNKNOWN | DNS_RDATATYPEATTR_META);
+ return (DNS_RDATATYPEATTR_UNKNOWN);
+}
+
+isc_result_t
+dns_rdatatype_fromtext(dns_rdatatype_t *typep, isc_textregion_t *source) {
+ unsigned int hash;
+ unsigned int n;
+ unsigned char a, b;
+
+ n = source->length;
+
+ if (n == 0)
+ return (DNS_R_UNKNOWN);
+
+ a = tolower((unsigned char)source->base[0]);
+ b = tolower((unsigned char)source->base[n - 1]);
+
+ hash = ((a + n) * b) % 256;
+
+ /*
+ * This switch block is inlined via \#define, and will use "return"
+ * to return a result to the caller if it is a valid (known)
+ * rdatatype name.
+ */
+ RDATATYPE_FROMTEXT_SW(hash, source->base, n, typep);
+
+ if (source->length > 4 && source->length < (4 + sizeof("65000")) &&
+ strncasecmp("type", source->base, 4) == 0) {
+ char buf[sizeof("65000")];
+ char *endp;
+ unsigned int val;
+
+ strncpy(buf, source->base + 4, source->length - 4);
+ buf[source->length - 4] = '\0';
+ val = strtoul(buf, &endp, 10);
+ if (*endp == '\0' && val <= 0xffff) {
+ *typep = (dns_rdatatype_t)val;
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ return (DNS_R_UNKNOWN);
+}
+
+isc_result_t
+dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target) {
+ char buf[sizeof("TYPE65535")];
+
+ RDATATYPE_TOTEXT_SW
+ snprintf(buf, sizeof(buf), "TYPE%u", type);
+ return (str_totext(buf, target));
+}
+
+void
+dns_rdatatype_format(dns_rdatatype_t rdtype,
+ char *array, unsigned int size)
+{
+ isc_result_t result;
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, array, size);
+ result = dns_rdatatype_totext(rdtype, &buf);
+ /*
+ * Null terminate.
+ */
+ if (result == ISC_R_SUCCESS) {
+ if (isc_buffer_availablelength(&buf) >= 1)
+ isc_buffer_putuint8(&buf, 0);
+ else
+ result = ISC_R_NOSPACE;
+ }
+ if (result != ISC_R_SUCCESS) {
+ snprintf(array, size, "<unknown>");
+ array[size - 1] = '\0';
+ }
+}
+
+/*
+ * Private function.
+ */
+
+static unsigned int
+name_length(dns_name_t *name) {
+ return (name->length);
+}
+
+static isc_result_t
+txt_totext(isc_region_t *source, isc_buffer_t *target) {
+ unsigned int tl;
+ unsigned int n;
+ unsigned char *sp;
+ char *tp;
+ isc_region_t region;
+
+ isc_buffer_availableregion(target, &region);
+ sp = source->base;
+ tp = (char *)region.base;
+ tl = region.length;
+
+ n = *sp++;
+
+ REQUIRE(n + 1 <= source->length);
+
+ if (tl < 1)
+ return (ISC_R_NOSPACE);
+ *tp++ = '"';
+ tl--;
+ while (n--) {
+ if (*sp < 0x20 || *sp >= 0x7f) {
+ if (tl < 4)
+ return (ISC_R_NOSPACE);
+ *tp++ = 0x5c;
+ *tp++ = 0x30 + ((*sp / 100) % 10);
+ *tp++ = 0x30 + ((*sp / 10) % 10);
+ *tp++ = 0x30 + (*sp % 10);
+ sp++;
+ tl -= 4;
+ continue;
+ }
+ /* double quote, semi-colon, backslash */
+ if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c) {
+ if (tl < 2)
+ return (ISC_R_NOSPACE);
+ *tp++ = '\\';
+ tl--;
+ }
+ if (tl < 1)
+ return (ISC_R_NOSPACE);
+ *tp++ = *sp++;
+ tl--;
+ }
+ if (tl < 1)
+ return (ISC_R_NOSPACE);
+ *tp++ = '"';
+ tl--;
+ isc_buffer_add(target, tp - (char *)region.base);
+ isc_region_consume(source, *source->base + 1);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+txt_fromtext(isc_textregion_t *source, isc_buffer_t *target) {
+ isc_region_t tregion;
+ isc_boolean_t escape;
+ unsigned int n, nrem;
+ char *s;
+ unsigned char *t;
+ int d;
+ int c;
+
+ isc_buffer_availableregion(target, &tregion);
+ s = source->base;
+ n = source->length;
+ t = tregion.base;
+ nrem = tregion.length;
+ escape = ISC_FALSE;
+ if (nrem < 1)
+ return (ISC_R_NOSPACE);
+ /*
+ * Length byte.
+ */
+ nrem--;
+ t++;
+ /*
+ * Maximum text string length.
+ */
+ if (nrem > 255)
+ nrem = 255;
+ while (n-- != 0) {
+ c = (*s++) & 0xff;
+ if (escape && (d = decvalue((char)c)) != -1) {
+ c = d;
+ if (n == 0)
+ return (DNS_R_SYNTAX);
+ n--;
+ if ((d = decvalue(*s++)) != -1)
+ c = c * 10 + d;
+ else
+ return (DNS_R_SYNTAX);
+ if (n == 0)
+ return (DNS_R_SYNTAX);
+ n--;
+ if ((d = decvalue(*s++)) != -1)
+ c = c * 10 + d;
+ else
+ return (DNS_R_SYNTAX);
+ if (c > 255)
+ return (DNS_R_SYNTAX);
+ } else if (!escape && c == '\\') {
+ escape = ISC_TRUE;
+ continue;
+ }
+ escape = ISC_FALSE;
+ if (nrem == 0)
+ return (ISC_R_NOSPACE);
+ *t++ = c;
+ nrem--;
+ }
+ if (escape)
+ return (DNS_R_SYNTAX);
+ *tregion.base = t - tregion.base - 1;
+ isc_buffer_add(target, *tregion.base + 1);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) {
+ unsigned int n;
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length == 0)
+ return(ISC_R_UNEXPECTEDEND);
+ n = *sregion.base + 1;
+ if (n > sregion.length)
+ return (ISC_R_UNEXPECTEDEND);
+
+ isc_buffer_availableregion(target, &tregion);
+ if (n > tregion.length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(tregion.base, sregion.base, n);
+ isc_buffer_forward(source, n);
+ isc_buffer_add(target, n);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target) {
+ int l1, l2;
+
+ if (origin == NULL)
+ goto return_false;
+
+ if (dns_name_compare(origin, dns_rootname) == 0)
+ goto return_false;
+
+ if (!dns_name_issubdomain(name, origin))
+ goto return_false;
+
+ l1 = dns_name_countlabels(name);
+ l2 = dns_name_countlabels(origin);
+
+ if (l1 == l2)
+ goto return_false;
+
+ dns_name_getlabelsequence(name, 0, l1 - l2, target);
+ return (ISC_TRUE);
+
+return_false:
+ *target = *name;
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target) {
+ unsigned int l;
+ isc_region_t region;
+
+ isc_buffer_availableregion(target, &region);
+ l = strlen(source);
+
+ if (l > region.length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(region.base, source, l);
+ isc_buffer_add(target, l);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+inet_totext(int af, isc_region_t *src, isc_buffer_t *target) {
+ char tmpbuf[64];
+
+ /* Note - inet_ntop doesn't do size checking on its input. */
+ if (inet_ntop(af, src->base, tmpbuf, sizeof(tmpbuf)) == NULL)
+ return (ISC_R_NOSPACE);
+ if (strlen(tmpbuf) > isc_buffer_availablelength(target))
+ return (ISC_R_NOSPACE);
+ isc_buffer_putstr(target, tmpbuf);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_boolean_t
+buffer_empty(isc_buffer_t *source) {
+ return((source->current == source->active) ? ISC_TRUE : ISC_FALSE);
+}
+
+static void
+buffer_fromregion(isc_buffer_t *buffer, isc_region_t *region) {
+ isc_buffer_init(buffer, region->base, region->length);
+ isc_buffer_add(buffer, region->length);
+ isc_buffer_setactive(buffer, region->length);
+}
+
+static isc_result_t
+uint32_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
+ isc_region_t region;
+
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 4)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putuint32(target, value);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+uint16_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
+ isc_region_t region;
+
+ if (value > 0xffff)
+ return (ISC_R_RANGE);
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 2)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putuint16(target, (isc_uint16_t)value);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+uint8_tobuffer(isc_uint32_t value, isc_buffer_t *target) {
+ isc_region_t region;
+
+ if (value > 0xff)
+ return (ISC_R_RANGE);
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 1)
+ return (ISC_R_NOSPACE);
+ isc_buffer_putuint8(target, (isc_uint8_t)value);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+name_tobuffer(dns_name_t *name, isc_buffer_t *target) {
+ isc_region_t r;
+ dns_name_toregion(name, &r);
+ return (isc_buffer_copyregion(target, &r));
+}
+
+static isc_uint32_t
+uint32_fromregion(isc_region_t *region) {
+ isc_uint32_t value;
+
+ REQUIRE(region->length >= 4);
+ value = region->base[0] << 24;
+ value |= region->base[1] << 16;
+ value |= region->base[2] << 8;
+ value |= region->base[3];
+ return(value);
+}
+
+static isc_uint16_t
+uint16_consume_fromregion(isc_region_t *region) {
+ isc_uint16_t r = uint16_fromregion(region);
+
+ isc_region_consume(region, 2);
+ return r;
+}
+
+static isc_uint16_t
+uint16_fromregion(isc_region_t *region) {
+
+ REQUIRE(region->length >= 2);
+
+ return ((region->base[0] << 8) | region->base[1]);
+}
+
+static isc_uint8_t
+uint8_fromregion(isc_region_t *region) {
+
+ REQUIRE(region->length >= 1);
+
+ return (region->base[0]);
+}
+
+static isc_uint8_t
+uint8_consume_fromregion(isc_region_t *region) {
+ isc_uint8_t r = uint8_fromregion(region);
+
+ isc_region_consume(region, 1);
+ return r;
+}
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
+ isc_region_t tr;
+
+ isc_buffer_availableregion(target, &tr);
+ if (length > tr.length)
+ return (ISC_R_NOSPACE);
+ memcpy(tr.base, base, length);
+ isc_buffer_add(target, length);
+ return (ISC_R_SUCCESS);
+}
+
+static int
+hexvalue(char value) {
+ char *s;
+ unsigned char c;
+
+ c = (unsigned char)value;
+
+ if (!isascii(c))
+ return (-1);
+ if (isupper(c))
+ c = tolower(c);
+ if ((s = strchr(hexdigits, c)) == NULL)
+ return (-1);
+ return (s - hexdigits);
+}
+
+static int
+decvalue(char value) {
+ char *s;
+
+ /*
+ * isascii() is valid for full range of int values, no need to
+ * mask or cast.
+ */
+ if (!isascii(value))
+ return (-1);
+ if ((s = strchr(decdigits, value)) == NULL)
+ return (-1);
+ return (s - decdigits);
+}
+
+static const char atob_digits[86] =
+ "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" \
+ "abcdefghijklmnopqrstu";
+/*
+ * Subroutines to convert between 8 bit binary bytes and printable ASCII.
+ * Computes the number of bytes, and three kinds of simple checksums.
+ * Incoming bytes are collected into 32-bit words, then printed in base 85:
+ * exp(85,5) > exp(2,32)
+ * The ASCII characters used are between '!' and 'u';
+ * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
+ *
+ * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
+ * the atob/btoa programs, released with the compress program, in mod.sources.
+ * Modified by Mike Schwartz 8/19/86 for use in BIND.
+ * Modified to be re-entrant 3/2/99.
+ */
+
+
+struct state {
+ isc_int32_t Ceor;
+ isc_int32_t Csum;
+ isc_int32_t Crot;
+ isc_int32_t word;
+ isc_int32_t bcount;
+};
+
+#define Ceor state->Ceor
+#define Csum state->Csum
+#define Crot state->Crot
+#define word state->word
+#define bcount state->bcount
+
+#define times85(x) ((((((x<<2)+x)<<2)+x)<<2)+x)
+
+static isc_result_t byte_atob(int c, isc_buffer_t *target,
+ struct state *state);
+static isc_result_t putbyte(int c, isc_buffer_t *, struct state *state);
+static isc_result_t byte_btoa(int c, isc_buffer_t *, struct state *state);
+
+/*
+ * Decode ASCII-encoded byte c into binary representation and
+ * place into *bufp, advancing bufp.
+ */
+static isc_result_t
+byte_atob(int c, isc_buffer_t *target, struct state *state) {
+ char *s;
+ if (c == 'z') {
+ if (bcount != 0)
+ return(DNS_R_SYNTAX);
+ else {
+ RETERR(putbyte(0, target, state));
+ RETERR(putbyte(0, target, state));
+ RETERR(putbyte(0, target, state));
+ RETERR(putbyte(0, target, state));
+ }
+ } else if ((s = strchr(atob_digits, c)) != NULL) {
+ if (bcount == 0) {
+ word = s - atob_digits;
+ ++bcount;
+ } else if (bcount < 4) {
+ word = times85(word);
+ word += s - atob_digits;
+ ++bcount;
+ } else {
+ word = times85(word);
+ word += s - atob_digits;
+ RETERR(putbyte((word >> 24) & 0xff, target, state));
+ RETERR(putbyte((word >> 16) & 0xff, target, state));
+ RETERR(putbyte((word >> 8) & 0xff, target, state));
+ RETERR(putbyte(word & 0xff, target, state));
+ word = 0;
+ bcount = 0;
+ }
+ } else
+ return(DNS_R_SYNTAX);
+ return(ISC_R_SUCCESS);
+}
+
+/*
+ * Compute checksum info and place c into target.
+ */
+static isc_result_t
+putbyte(int c, isc_buffer_t *target, struct state *state) {
+ isc_region_t tr;
+
+ Ceor ^= c;
+ Csum += c;
+ Csum += 1;
+ if ((Crot & 0x80000000)) {
+ Crot <<= 1;
+ Crot += 1;
+ } else {
+ Crot <<= 1;
+ }
+ Crot += c;
+ isc_buffer_availableregion(target, &tr);
+ if (tr.length < 1)
+ return (ISC_R_NOSPACE);
+ tr.base[0] = c;
+ isc_buffer_add(target, 1);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Read the ASCII-encoded data from inbuf, of length inbuflen, and convert
+ * it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes;
+ * outbuflen must be divisible by 4. (Note: this is because outbuf is filled
+ * in 4 bytes at a time. If the actual data doesn't end on an even 4-byte
+ * boundary, there will be no problem...it will be padded with 0 bytes, and
+ * numbytes will indicate the correct number of bytes. The main point is
+ * that since the buffer is filled in 4 bytes at a time, even if there is
+ * not a full 4 bytes of data at the end, there has to be room to 0-pad the
+ * data, so the buffer must be of size divisible by 4). Place the number of
+ * output bytes in numbytes, and return a failure/success status.
+ */
+
+static isc_result_t
+atob_tobuffer(isc_lex_t *lexer, isc_buffer_t *target) {
+ long oeor, osum, orot;
+ struct state statebuf, *state= &statebuf;
+ isc_token_t token;
+ char c;
+ char *e;
+
+ Ceor = Csum = Crot = word = bcount = 0;
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ while (token.value.as_textregion.length != 0) {
+ if ((c = token.value.as_textregion.base[0]) == 'x') {
+ break;
+ } else
+ RETERR(byte_atob(c, target, state));
+ isc_textregion_consume(&token.value.as_textregion, 1);
+ }
+
+ /*
+ * Number of bytes.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if ((token.value.as_ulong % 4) != 0U)
+ isc_buffer_subtract(target, 4 - (token.value.as_ulong % 4));
+
+ /*
+ * Checksum.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ oeor = strtol(DNS_AS_STR(token), &e, 16);
+ if (*e != 0)
+ return (DNS_R_SYNTAX);
+
+ /*
+ * Checksum.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ osum = strtol(DNS_AS_STR(token), &e, 16);
+ if (*e != 0)
+ return (DNS_R_SYNTAX);
+
+ /*
+ * Checksum.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ orot = strtol(DNS_AS_STR(token), &e, 16);
+ if (*e != 0)
+ return (DNS_R_SYNTAX);
+
+ if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
+ return(DNS_R_BADCKSUM);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Encode binary byte c into ASCII representation and place into *bufp,
+ * advancing bufp.
+ */
+static isc_result_t
+byte_btoa(int c, isc_buffer_t *target, struct state *state) {
+ isc_region_t tr;
+
+ isc_buffer_availableregion(target, &tr);
+ Ceor ^= c;
+ Csum += c;
+ Csum += 1;
+ if ((Crot & 0x80000000)) {
+ Crot <<= 1;
+ Crot += 1;
+ } else {
+ Crot <<= 1;
+ }
+ Crot += c;
+
+ word <<= 8;
+ word |= c;
+ if (bcount == 3) {
+ if (word == 0) {
+ if (tr.length < 1)
+ return (ISC_R_NOSPACE);
+ tr.base[0] = 'z';
+ isc_buffer_add(target, 1);
+ } else {
+ register int tmp = 0;
+ register isc_int32_t tmpword = word;
+
+ if (tmpword < 0) {
+ /*
+ * Because some don't support u_long.
+ */
+ tmp = 32;
+ tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
+ }
+ if (tmpword < 0) {
+ tmp = 64;
+ tmpword -= (isc_int32_t)(85 * 85 * 85 * 85 * 32);
+ }
+ if (tr.length < 5)
+ return (ISC_R_NOSPACE);
+ tr.base[0] = atob_digits[(tmpword /
+ (isc_int32_t)(85 * 85 * 85 * 85))
+ + tmp];
+ tmpword %= (isc_int32_t)(85 * 85 * 85 * 85);
+ tr.base[1] = atob_digits[tmpword / (85 * 85 * 85)];
+ tmpword %= (85 * 85 * 85);
+ tr.base[2] = atob_digits[tmpword / (85 * 85)];
+ tmpword %= (85 * 85);
+ tr.base[3] = atob_digits[tmpword / 85];
+ tmpword %= 85;
+ tr.base[4] = atob_digits[tmpword];
+ isc_buffer_add(target, 5);
+ }
+ bcount = 0;
+ } else {
+ bcount += 1;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+
+/*
+ * Encode the binary data from inbuf, of length inbuflen, into a
+ * target. Return success/failure status
+ */
+static isc_result_t
+btoa_totext(unsigned char *inbuf, int inbuflen, isc_buffer_t *target) {
+ int inc;
+ struct state statebuf, *state = &statebuf;
+ char buf[sizeof("x 2000000000 ffffffff ffffffff ffffffff")];
+
+ Ceor = Csum = Crot = word = bcount = 0;
+ for (inc = 0; inc < inbuflen; inbuf++, inc++)
+ RETERR(byte_btoa(*inbuf, target, state));
+
+ while (bcount != 0)
+ RETERR(byte_btoa(0, target, state));
+
+ /*
+ * Put byte count and checksum information at end of buffer,
+ * delimited by 'x'
+ */
+ snprintf(buf, sizeof(buf), "x %d %x %x %x", inbuflen, Ceor, Csum, Crot);
+ return (str_totext(buf, target));
+}
+
+
+static void
+default_fromtext_callback(dns_rdatacallbacks_t *callbacks, const char *fmt,
+ ...)
+{
+ va_list ap;
+
+ UNUSED(callbacks);
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+}
+
+static void
+fromtext_warneof(isc_lex_t *lexer, dns_rdatacallbacks_t *callbacks) {
+ if (isc_lex_isfile(lexer) && callbacks != NULL) {
+ const char *name = isc_lex_getsourcename(lexer);
+ if (name == NULL)
+ name = "UNKNOWN";
+ (*callbacks->warn)(callbacks,
+ "%s:%lu: file does not end with newline",
+ name, isc_lex_getsourceline(lexer));
+ }
+}
+
+static void
+warn_badmx(isc_token_t *token, isc_lex_t *lexer,
+ dns_rdatacallbacks_t *callbacks)
+{
+ const char *file;
+ unsigned long line;
+
+ if (lexer != NULL) {
+ file = isc_lex_getsourcename(lexer);
+ line = isc_lex_getsourceline(lexer);
+ (*callbacks->warn)(callbacks, "%s:%u: warning: '%s': %s",
+ file, line, DNS_AS_STR(*token),
+ dns_result_totext(DNS_R_MXISADDRESS));
+ }
+}
+
+static void
+warn_badname(dns_name_t *name, isc_lex_t *lexer,
+ dns_rdatacallbacks_t *callbacks)
+{
+ const char *file;
+ unsigned long line;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ if (lexer != NULL) {
+ file = isc_lex_getsourcename(lexer);
+ line = isc_lex_getsourceline(lexer);
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ (*callbacks->warn)(callbacks, "%s:%u: warning: %s: %s",
+ file, line, namebuf,
+ dns_result_totext(DNS_R_BADNAME));
+ }
+}
+
+static void
+fromtext_error(void (*callback)(dns_rdatacallbacks_t *, const char *, ...),
+ dns_rdatacallbacks_t *callbacks, const char *name,
+ unsigned long line, isc_token_t *token, isc_result_t result)
+{
+ if (name == NULL)
+ name = "UNKNOWN";
+
+ if (token != NULL) {
+ switch (token->type) {
+ case isc_tokentype_eol:
+ (*callback)(callbacks, "%s: %s:%lu: near eol: %s",
+ "dns_rdata_fromtext", name, line,
+ dns_result_totext(result));
+ break;
+ case isc_tokentype_eof:
+ (*callback)(callbacks, "%s: %s:%lu: near eof: %s",
+ "dns_rdata_fromtext", name, line,
+ dns_result_totext(result));
+ break;
+ case isc_tokentype_number:
+ (*callback)(callbacks, "%s: %s:%lu: near %lu: %s",
+ "dns_rdata_fromtext", name, line,
+ token->value.as_ulong,
+ dns_result_totext(result));
+ break;
+ case isc_tokentype_string:
+ case isc_tokentype_qstring:
+ (*callback)(callbacks, "%s: %s:%lu: near '%s': %s",
+ "dns_rdata_fromtext", name, line,
+ DNS_AS_STR(*token),
+ dns_result_totext(result));
+ break;
+ default:
+ (*callback)(callbacks, "%s: %s:%lu: %s",
+ "dns_rdata_fromtext", name, line,
+ dns_result_totext(result));
+ break;
+ }
+ } else {
+ (*callback)(callbacks, "dns_rdata_fromtext: %s:%lu: %s",
+ name, line, dns_result_totext(result));
+ }
+}
+
+dns_rdatatype_t
+dns_rdata_covers(dns_rdata_t *rdata) {
+ if (rdata->type == 46)
+ return (covers_rrsig(rdata));
+ return (covers_sig(rdata));
+}
+
+isc_boolean_t
+dns_rdatatype_ismeta(dns_rdatatype_t type) {
+ if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_META) != 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_rdatatype_issingleton(dns_rdatatype_t type) {
+ if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_SINGLETON)
+ != 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_rdatatype_notquestion(dns_rdatatype_t type) {
+ if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_NOTQUESTION)
+ != 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_rdatatype_questiononly(dns_rdatatype_t type) {
+ if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_QUESTIONONLY)
+ != 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_rdatatype_atparent(dns_rdatatype_t type) {
+ if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_ATPARENT) != 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_rdataclass_ismeta(dns_rdataclass_t rdclass) {
+
+ if (rdclass == dns_rdataclass_reserved0
+ || rdclass == dns_rdataclass_none
+ || rdclass == dns_rdataclass_any)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE); /* Assume it is not a meta class. */
+}
+
+isc_boolean_t
+dns_rdatatype_isdnssec(dns_rdatatype_t type) {
+ if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_DNSSEC) != 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_rdatatype_iszonecutauth(dns_rdatatype_t type) {
+ if ((dns_rdatatype_attributes(type)
+ & (DNS_RDATATYPEATTR_DNSSEC | DNS_RDATATYPEATTR_ZONECUTAUTH))
+ != 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_rdatatype_isknown(dns_rdatatype_t type) {
+ if ((dns_rdatatype_attributes(type) & DNS_RDATATYPEATTR_UNKNOWN)
+ == 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
diff --git a/lib/dns/rdata/any_255/tsig_250.c b/lib/dns/rdata/any_255/tsig_250.c
new file mode 100644
index 0000000..3121f78
--- /dev/null
+++ b/lib/dns/rdata/any_255/tsig_250.c
@@ -0,0 +1,597 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: tsig_250.c,v 1.63 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 13:39:43 PST 2000 by gson */
+
+#ifndef RDATA_ANY_255_TSIG_250_C
+#define RDATA_ANY_255_TSIG_250_C
+
+#define RRTYPE_TSIG_ATTRIBUTES \
+ (DNS_RDATATYPEATTR_META | DNS_RDATATYPEATTR_NOTQUESTION)
+
+static inline isc_result_t
+fromtext_any_tsig(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_uint64_t sigtime;
+ isc_buffer_t buffer;
+ dns_rcode_t rcode;
+ long i;
+ char *e;
+
+ REQUIRE(type == 250);
+ REQUIRE(rdclass == 255);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Algorithm Name.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ /*
+ * Time Signed: 48 bits.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ sigtime = isc_string_touint64(DNS_AS_STR(token), &e, 10);
+ if (*e != 0)
+ RETTOK(DNS_R_SYNTAX);
+ if ((sigtime >> 48) != 0)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer((isc_uint16_t)(sigtime >> 32), target));
+ RETERR(uint32_tobuffer((isc_uint32_t)(sigtime & 0xffffffffU), target));
+
+ /*
+ * Fudge.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Signature Size.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Signature.
+ */
+ RETERR(isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong));
+
+ /*
+ * Original ID.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Error.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (dns_tsigrcode_fromtext(&rcode, &token.value.as_textregion)
+ != ISC_R_SUCCESS)
+ {
+ i = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0)
+ RETTOK(DNS_R_UNKNOWN);
+ if (i < 0 || i > 0xffff)
+ RETTOK(ISC_R_RANGE);
+ rcode = (dns_rcode_t)i;
+ }
+ RETERR(uint16_tobuffer(rcode, target));
+
+ /*
+ * Other Len.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Other Data.
+ */
+ return (isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong));
+}
+
+static inline isc_result_t
+totext_any_tsig(ARGS_TOTEXT) {
+ isc_region_t sr;
+ isc_region_t sigr;
+ char buf[sizeof("281474976710655 ")];
+ char *bufp;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ isc_uint64_t sigtime;
+ unsigned short n;
+
+ REQUIRE(rdata->type == 250);
+ REQUIRE(rdata->rdclass == 255);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+ /*
+ * Algorithm Name.
+ */
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_name_fromregion(&name, &sr);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+ RETERR(str_totext(" ", target));
+ isc_region_consume(&sr, name_length(&name));
+
+ /*
+ * Time Signed.
+ */
+ sigtime = ((isc_uint64_t)sr.base[0] << 40) |
+ ((isc_uint64_t)sr.base[1] << 32) |
+ ((isc_uint64_t)sr.base[2] << 24) |
+ ((isc_uint64_t)sr.base[3] << 16) |
+ ((isc_uint64_t)sr.base[4] << 8) |
+ (isc_uint64_t)sr.base[5];
+ isc_region_consume(&sr, 6);
+ bufp = &buf[sizeof(buf) - 1];
+ *bufp-- = 0;
+ *bufp-- = ' ';
+ do {
+ *bufp-- = decdigits[sigtime % 10];
+ sigtime /= 10;
+ } while (sigtime != 0);
+ bufp++;
+ RETERR(str_totext(bufp, target));
+
+ /*
+ * Fudge.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Signature Size.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%u", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Signature.
+ */
+ REQUIRE(n <= sr.length);
+ sigr = sr;
+ sigr.length = n;
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(isc_base64_totext(&sigr, tctx->width - 2,
+ tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" ) ", target));
+ else
+ RETERR(str_totext(" ", target));
+ isc_region_consume(&sr, n);
+
+ /*
+ * Original ID.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Error.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ if (dns_tsigrcode_totext((dns_rcode_t)n, target) == ISC_R_SUCCESS)
+ RETERR(str_totext(" ", target));
+ else {
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+ }
+
+ /*
+ * Other Size.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Other.
+ */
+ return (isc_base64_totext(&sr, 60, " ", target));
+}
+
+static inline isc_result_t
+fromwire_any_tsig(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ unsigned long n;
+
+ REQUIRE(type == 250);
+ REQUIRE(rdclass == 255);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ /*
+ * Algorithm Name.
+ */
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ isc_buffer_activeregion(source, &sr);
+ /*
+ * Time Signed + Fudge.
+ */
+ if (sr.length < 8)
+ return (ISC_R_UNEXPECTEDEND);
+ RETERR(mem_tobuffer(target, sr.base, 8));
+ isc_region_consume(&sr, 8);
+ isc_buffer_forward(source, 8);
+
+ /*
+ * Signature Length + Signature.
+ */
+ if (sr.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ n = uint16_fromregion(&sr);
+ if (sr.length < n + 2)
+ return (ISC_R_UNEXPECTEDEND);
+ RETERR(mem_tobuffer(target, sr.base, n + 2));
+ isc_region_consume(&sr, n + 2);
+ isc_buffer_forward(source, n + 2);
+
+ /*
+ * Original ID + Error.
+ */
+ if (sr.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+ RETERR(mem_tobuffer(target, sr.base, 4));
+ isc_region_consume(&sr, 4);
+ isc_buffer_forward(source, 4);
+
+ /*
+ * Other Length + Other.
+ */
+ if (sr.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ n = uint16_fromregion(&sr);
+ if (sr.length < n + 2)
+ return (ISC_R_UNEXPECTEDEND);
+ isc_buffer_forward(source, n + 2);
+ return (mem_tobuffer(target, sr.base, n + 2));
+}
+
+static inline isc_result_t
+towire_any_tsig(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == 250);
+ REQUIRE(rdata->rdclass == 255);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ RETERR(dns_name_towire(&name, cctx, target));
+ isc_region_consume(&sr, name_length(&name));
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_any_tsig(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 == 250);
+ REQUIRE(rdata1->rdclass == 255);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ 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));
+}
+
+static inline isc_result_t
+fromstruct_any_tsig(ARGS_FROMSTRUCT) {
+ dns_rdata_any_tsig_t *tsig = source;
+ isc_region_t tr;
+
+ REQUIRE(type == 250);
+ REQUIRE(rdclass == 255);
+ REQUIRE(source != NULL);
+ REQUIRE(tsig->common.rdclass == rdclass);
+ REQUIRE(tsig->common.rdtype == type);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Algorithm Name.
+ */
+ RETERR(name_tobuffer(&tsig->algorithm, target));
+
+ isc_buffer_availableregion(target, &tr);
+ if (tr.length < 6 + 2 + 2)
+ return (ISC_R_NOSPACE);
+
+ /*
+ * Time Signed: 48 bits.
+ */
+ RETERR(uint16_tobuffer((isc_uint16_t)(tsig->timesigned >> 32),
+ target));
+ RETERR(uint32_tobuffer((isc_uint32_t)(tsig->timesigned & 0xffffffffU),
+ target));
+
+ /*
+ * Fudge.
+ */
+ RETERR(uint16_tobuffer(tsig->fudge, target));
+
+ /*
+ * Signature Size.
+ */
+ RETERR(uint16_tobuffer(tsig->siglen, target));
+
+ /*
+ * Signature.
+ */
+ RETERR(mem_tobuffer(target, tsig->signature, tsig->siglen));
+
+ isc_buffer_availableregion(target, &tr);
+ if (tr.length < 2 + 2 + 2)
+ return (ISC_R_NOSPACE);
+
+ /*
+ * Original ID.
+ */
+ RETERR(uint16_tobuffer(tsig->originalid, target));
+
+ /*
+ * Error.
+ */
+ RETERR(uint16_tobuffer(tsig->error, target));
+
+ /*
+ * Other Len.
+ */
+ RETERR(uint16_tobuffer(tsig->otherlen, target));
+
+ /*
+ * Other Data.
+ */
+ return (mem_tobuffer(target, tsig->other, tsig->otherlen));
+}
+
+static inline isc_result_t
+tostruct_any_tsig(ARGS_TOSTRUCT) {
+ dns_rdata_any_tsig_t *tsig;
+ dns_name_t alg;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 250);
+ REQUIRE(rdata->rdclass == 255);
+ REQUIRE(rdata->length != 0);
+
+ tsig = (dns_rdata_any_tsig_t *) target;
+ tsig->common.rdclass = rdata->rdclass;
+ tsig->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&tsig->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Algorithm Name.
+ */
+ dns_name_init(&alg, NULL);
+ dns_name_fromregion(&alg, &sr);
+ dns_name_init(&tsig->algorithm, NULL);
+ RETERR(name_duporclone(&alg, mctx, &tsig->algorithm));
+
+ isc_region_consume(&sr, name_length(&tsig->algorithm));
+
+ /*
+ * Time Signed.
+ */
+ INSIST(sr.length >= 6);
+ tsig->timesigned = ((isc_uint64_t)sr.base[0] << 40) |
+ ((isc_uint64_t)sr.base[1] << 32) |
+ ((isc_uint64_t)sr.base[2] << 24) |
+ ((isc_uint64_t)sr.base[3] << 16) |
+ ((isc_uint64_t)sr.base[4] << 8) |
+ (isc_uint64_t)sr.base[5];
+ isc_region_consume(&sr, 6);
+
+ /*
+ * Fudge.
+ */
+ tsig->fudge = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Signature Size.
+ */
+ tsig->siglen = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Signature.
+ */
+ INSIST(sr.length >= tsig->siglen);
+ tsig->signature = mem_maybedup(mctx, sr.base, tsig->siglen);
+ if (tsig->signature == NULL)
+ goto cleanup;
+ isc_region_consume(&sr, tsig->siglen);
+
+ /*
+ * Original ID.
+ */
+ tsig->originalid = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Error.
+ */
+ tsig->error = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Other Size.
+ */
+ tsig->otherlen = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Other.
+ */
+ INSIST(sr.length == tsig->otherlen);
+ tsig->other = mem_maybedup(mctx, sr.base, tsig->otherlen);
+ if (tsig->other == NULL)
+ goto cleanup;
+
+ tsig->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL)
+ dns_name_free(&tsig->algorithm, tsig->mctx);
+ if (mctx != NULL && tsig->signature != NULL)
+ isc_mem_free(mctx, tsig->signature);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_any_tsig(ARGS_FREESTRUCT) {
+ dns_rdata_any_tsig_t *tsig = (dns_rdata_any_tsig_t *) source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(tsig->common.rdclass == 255);
+ REQUIRE(tsig->common.rdtype == 250);
+
+ if (tsig->mctx == NULL)
+ return;
+
+ dns_name_free(&tsig->algorithm, tsig->mctx);
+ if (tsig->signature != NULL)
+ isc_mem_free(tsig->mctx, tsig->signature);
+ if (tsig->other != NULL)
+ isc_mem_free(tsig->mctx, tsig->other);
+ tsig->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_any_tsig(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 250);
+ REQUIRE(rdata->rdclass == 255);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_any_tsig(ARGS_DIGEST) {
+
+ REQUIRE(rdata->type == 250);
+ REQUIRE(rdata->rdclass == 255);
+
+ UNUSED(rdata);
+ UNUSED(digest);
+ UNUSED(arg);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline isc_boolean_t
+checkowner_any_tsig(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 250);
+ REQUIRE(rdclass == 255);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_any_tsig(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 250);
+ REQUIRE(rdata->rdclass == 250);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_ANY_255_TSIG_250_C */
diff --git a/lib/dns/rdata/any_255/tsig_250.h b/lib/dns/rdata/any_255/tsig_250.h
new file mode 100644
index 0000000..0c01667
--- /dev/null
+++ b/lib/dns/rdata/any_255/tsig_250.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: tsig_250.h,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef ANY_255_TSIG_250_H
+#define ANY_255_TSIG_250_H 1
+
+/*% RFC2845 */
+typedef struct dns_rdata_any_tsig {
+ dns_rdatacommon_t common;
+ isc_mem_t * mctx;
+ dns_name_t algorithm;
+ isc_uint64_t timesigned;
+ isc_uint16_t fudge;
+ isc_uint16_t siglen;
+ unsigned char * signature;
+ isc_uint16_t originalid;
+ isc_uint16_t error;
+ isc_uint16_t otherlen;
+ unsigned char * other;
+} dns_rdata_any_tsig_t;
+
+#endif /* ANY_255_TSIG_250_H */
diff --git a/lib/dns/rdata/ch_3/a_1.c b/lib/dns/rdata/ch_3/a_1.c
new file mode 100644
index 0000000..78d4ecd
--- /dev/null
+++ b/lib/dns/rdata/ch_3/a_1.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2005, 2007 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: a_1.c,v 1.6 2007/06/19 23:47:17 tbox Exp $ */
+
+/* by Bjorn.Victor@it.uu.se, 2005-05-07 */
+/* Based on generic/soa_6.c and generic/mx_15.c */
+
+#ifndef RDATA_CH_3_A_1_C
+#define RDATA_CH_3_A_1_C
+
+#include <isc/net.h>
+
+#define RRTYPE_A_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_ch_a(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == dns_rdataclass_ch); /* 3 */
+
+ UNUSED(type);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ /* get domain name */
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ if ((options & DNS_RDATA_CHECKNAMES) != 0 &&
+ (options & DNS_RDATA_CHECKREVERSE) != 0) {
+ isc_boolean_t ok;
+ ok = dns_name_ishostname(&name, ISC_FALSE);
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ }
+
+ /* 16-bit octal address */
+ RETERR(isc_lex_getoctaltoken(lexer, &token, ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ return (uint16_tobuffer(token.value.as_ulong, target));
+}
+
+static inline isc_result_t
+totext_ch_a(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ char buf[sizeof("0177777")];
+ isc_uint16_t addr;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == dns_rdataclass_ch); /* 3 */
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ addr = uint16_fromregion(&region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ sprintf(buf, "%o", addr); /* note octal */
+ RETERR(str_totext(" ", target));
+ return (str_totext(buf, target));
+}
+
+static inline isc_result_t
+fromwire_ch_a(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+ isc_region_t tregion;
+ dns_name_t name;
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == dns_rdataclass_ch);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ 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);
+ isc_buffer_availableregion(target, &tregion);
+ if (sregion.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ if (tregion.length < 2)
+ return (ISC_R_NOSPACE);
+
+ memcpy(tregion.base, sregion.base, 2);
+ isc_buffer_forward(source, 2);
+ isc_buffer_add(target, 2);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_ch_a(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == dns_rdataclass_ch);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+
+ dns_rdata_toregion(rdata, &sregion);
+
+ dns_name_fromregion(&name, &sregion);
+ isc_region_consume(&sregion, name_length(&name));
+ RETERR(dns_name_towire(&name, cctx, target));
+
+ isc_buffer_availableregion(target, &tregion);
+ if (tregion.length < 2)
+ return (ISC_R_NOSPACE);
+
+ memcpy(tregion.base, sregion.base, 2);
+ isc_buffer_add(target, 2);
+ return (ISC_R_SUCCESS);
+}
+
+static inline int
+compare_ch_a(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 1);
+ REQUIRE(rdata1->rdclass == dns_rdataclass_ch);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ order = memcmp(rdata1->data, rdata2->data, 2);
+ if (order != 0)
+ order = (order < 0) ? -1 : 1;
+ return (order);
+}
+
+static inline isc_result_t
+fromstruct_ch_a(ARGS_FROMSTRUCT) {
+ dns_rdata_ch_a_t *a = source;
+ isc_region_t region;
+
+ REQUIRE(type == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(a->common.rdtype == type);
+ REQUIRE(a->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&a->ch_addr_dom, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+
+ return (uint16_tobuffer(ntohs(a->ch_addr), target));
+}
+
+static inline isc_result_t
+tostruct_ch_a(ARGS_TOSTRUCT) {
+ dns_rdata_ch_a_t *a = target;
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == dns_rdataclass_ch);
+ REQUIRE(rdata->length != 0);
+
+ a->common.rdclass = rdata->rdclass;
+ a->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&a->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+
+ dns_name_init(&a->ch_addr_dom, NULL);
+ RETERR(name_duporclone(&name, mctx, &a->ch_addr_dom));
+ a->ch_addr = htons(uint16_fromregion(&region));
+ a->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_ch_a(ARGS_FREESTRUCT) {
+ dns_rdata_ch_a_t *a = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(a->common.rdtype == 1);
+
+ if (a->mctx == NULL)
+ return;
+
+ dns_name_free(&a->ch_addr_dom, a->mctx);
+ a->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_ch_a(ARGS_ADDLDATA) {
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == dns_rdataclass_ch);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_ch_a(ARGS_DIGEST) {
+ isc_region_t r;
+
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == dns_rdataclass_ch);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ isc_region_consume(&r, name_length(&name));
+ RETERR(dns_name_digest(&name, digest, arg));
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_ch_a(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == dns_rdataclass_ch);
+
+ UNUSED(type);
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static inline isc_boolean_t
+checknames_ch_a(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == dns_rdataclass_ch);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, ISC_FALSE)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_CH_3_A_1_C */
diff --git a/lib/dns/rdata/ch_3/a_1.h b/lib/dns/rdata/ch_3/a_1.h
new file mode 100644
index 0000000..a279d0e
--- /dev/null
+++ b/lib/dns/rdata/ch_3/a_1.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2005, 2007 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: a_1.h,v 1.5 2007/06/19 23:47:17 tbox Exp $ */
+
+/* by Bjorn.Victor@it.uu.se, 2005-05-07 */
+/* Based on generic/mx_15.h */
+
+#ifndef CH_3_A_1_H
+#define CH_3_A_1_H 1
+
+typedef isc_uint16_t ch_addr_t;
+
+typedef struct dns_rdata_ch_a {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t ch_addr_dom; /* ch-addr domain for back mapping */
+ ch_addr_t ch_addr; /* chaos address (16 bit) network order */
+} dns_rdata_ch_a_t;
+
+#endif /* CH_3_A_1_H */
diff --git a/lib/dns/rdata/generic/afsdb_18.c b/lib/dns/rdata/generic/afsdb_18.c
new file mode 100644
index 0000000..2230efb
--- /dev/null
+++ b/lib/dns/rdata/generic/afsdb_18.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: afsdb_18.c,v 1.47 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Wed Mar 15 14:59:00 PST 2000 by explorer */
+
+/* RFC1183 */
+
+#ifndef RDATA_GENERIC_AFSDB_18_C
+#define RDATA_GENERIC_AFSDB_18_C
+
+#define RRTYPE_AFSDB_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_afsdb(ARGS_FROMTEXT) {
+ isc_token_t token;
+ isc_buffer_t buffer;
+ dns_name_t name;
+ isc_boolean_t ok;
+
+ REQUIRE(type == 18);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Subtype.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Hostname.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ ok = ISC_TRUE;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0)
+ ok = dns_name_ishostname(&name, ISC_FALSE);
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_afsdb(ARGS_TOTEXT) {
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_region_t region;
+ char buf[sizeof("64000 ")];
+ isc_boolean_t sub;
+ unsigned int num;
+
+ REQUIRE(rdata->type == 18);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ sprintf(buf, "%u ", num);
+ RETERR(str_totext(buf, target));
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_afsdb(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sr;
+ isc_region_t tr;
+
+ REQUIRE(type == 18);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_availableregion(target, &tr);
+ if (tr.length < 2)
+ return (ISC_R_NOSPACE);
+ if (sr.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ memcpy(tr.base, sr.base, 2);
+ isc_buffer_forward(source, 2);
+ isc_buffer_add(target, 2);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_afsdb(ARGS_TOWIRE) {
+ isc_region_t tr;
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == 18);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ isc_buffer_availableregion(target, &tr);
+ dns_rdata_toregion(rdata, &sr);
+ if (tr.length < 2)
+ return (ISC_R_NOSPACE);
+ memcpy(tr.base, sr.base, 2);
+ isc_region_consume(&sr, 2);
+ isc_buffer_add(target, 2);
+
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_afsdb(ARGS_COMPARE) {
+ int result;
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 18);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ result = memcmp(rdata1->data, rdata2->data, 2);
+ if (result != 0)
+ return (result < 0 ? -1 : 1);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 2);
+ isc_region_consume(&region2, 2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_afsdb(ARGS_FROMSTRUCT) {
+ dns_rdata_afsdb_t *afsdb = source;
+ isc_region_t region;
+
+ REQUIRE(type == 18);
+ REQUIRE(source != NULL);
+ REQUIRE(afsdb->common.rdclass == rdclass);
+ REQUIRE(afsdb->common.rdtype == type);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(afsdb->subtype, target));
+ dns_name_toregion(&afsdb->server, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_afsdb(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_afsdb_t *afsdb = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 18);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ afsdb->common.rdclass = rdata->rdclass;
+ afsdb->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&afsdb->common, link);
+
+ dns_name_init(&afsdb->server, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ afsdb->subtype = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+
+ RETERR(name_duporclone(&name, mctx, &afsdb->server));
+ afsdb->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_afsdb(ARGS_FREESTRUCT) {
+ dns_rdata_afsdb_t *afsdb = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(afsdb->common.rdtype == 18);
+
+ if (afsdb->mctx == NULL)
+ return;
+
+ dns_name_free(&afsdb->server, afsdb->mctx);
+ afsdb->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_afsdb(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 18);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a));
+}
+
+static inline isc_result_t
+digest_afsdb(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 18);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ isc_region_consume(&r2, 2);
+ r1.length = 2;
+ RETERR((digest)(arg, &r1));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_afsdb(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 18);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_afsdb(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 18);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, ISC_FALSE)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_AFSDB_18_C */
diff --git a/lib/dns/rdata/generic/afsdb_18.h b/lib/dns/rdata/generic/afsdb_18.h
new file mode 100644
index 0000000..ccccc11
--- /dev/null
+++ b/lib/dns/rdata/generic/afsdb_18.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef GENERIC_AFSDB_18_H
+#define GENERIC_AFSDB_18_H 1
+
+/* $Id: afsdb_18.h,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC1183 */
+
+typedef struct dns_rdata_afsdb {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t subtype;
+ dns_name_t server;
+} dns_rdata_afsdb_t;
+
+#endif /* GENERIC_AFSDB_18_H */
+
diff --git a/lib/dns/rdata/generic/cert_37.c b/lib/dns/rdata/generic/cert_37.c
new file mode 100644
index 0000000..2c45230
--- /dev/null
+++ b/lib/dns/rdata/generic/cert_37.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: cert_37.c,v 1.50 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Wed Mar 15 21:14:32 EST 2000 by tale */
+
+/* RFC2538 */
+
+#ifndef RDATA_GENERIC_CERT_37_C
+#define RDATA_GENERIC_CERT_37_C
+
+#define RRTYPE_CERT_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_cert(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_secalg_t secalg;
+ dns_cert_t cert;
+
+ REQUIRE(type == 37);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Cert type.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_cert_fromtext(&cert, &token.value.as_textregion));
+ RETERR(uint16_tobuffer(cert, target));
+
+ /*
+ * Key tag.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_secalg_fromtext(&secalg, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &secalg, 1));
+
+ return (isc_base64_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_cert(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000 ")];
+ unsigned int n;
+
+ REQUIRE(rdata->type == 37);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Type.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ RETERR(dns_cert_totext((dns_cert_t)n, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Key tag.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(dns_secalg_totext(sr.base[0], target));
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Cert.
+ */
+ 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_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_cert(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 37);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 5)
+ return (ISC_R_UNEXPECTEDEND);
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_cert(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 37);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_cert(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 37);
+ 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_cert(ARGS_FROMSTRUCT) {
+ dns_rdata_cert_t *cert = source;
+
+ REQUIRE(type == 37);
+ REQUIRE(source != NULL);
+ REQUIRE(cert->common.rdtype == type);
+ REQUIRE(cert->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(cert->type, target));
+ RETERR(uint16_tobuffer(cert->key_tag, target));
+ RETERR(uint8_tobuffer(cert->algorithm, target));
+
+ return (mem_tobuffer(target, cert->certificate, cert->length));
+}
+
+static inline isc_result_t
+tostruct_cert(ARGS_TOSTRUCT) {
+ dns_rdata_cert_t *cert = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 37);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ cert->common.rdclass = rdata->rdclass;
+ cert->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&cert->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ cert->type = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ cert->key_tag = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ cert->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ cert->length = region.length;
+
+ cert->certificate = mem_maybedup(mctx, region.base, region.length);
+ if (cert->certificate == NULL)
+ return (ISC_R_NOMEMORY);
+
+ cert->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_cert(ARGS_FREESTRUCT) {
+ dns_rdata_cert_t *cert = source;
+
+ REQUIRE(cert != NULL);
+ REQUIRE(cert->common.rdtype == 37);
+
+ if (cert->mctx == NULL)
+ return;
+
+ if (cert->certificate != NULL)
+ isc_mem_free(cert->mctx, cert->certificate);
+ cert->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_cert(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 37);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_cert(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 37);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_cert(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 37);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_cert(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 37);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_CERT_37_C */
+
diff --git a/lib/dns/rdata/generic/cert_37.h b/lib/dns/rdata/generic/cert_37.h
new file mode 100644
index 0000000..ddfaa4f
--- /dev/null
+++ b/lib/dns/rdata/generic/cert_37.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: cert_37.h,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef GENERIC_CERT_37_H
+#define GENERIC_CERT_37_H 1
+
+/*% RFC2538 */
+typedef struct dns_rdata_cert {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t type;
+ isc_uint16_t key_tag;
+ isc_uint8_t algorithm;
+ isc_uint16_t length;
+ unsigned char *certificate;
+} dns_rdata_cert_t;
+
+#endif /* GENERIC_CERT_37_H */
diff --git a/lib/dns/rdata/generic/cname_5.c b/lib/dns/rdata/generic/cname_5.c
new file mode 100644
index 0000000..28c3d60
--- /dev/null
+++ b/lib/dns/rdata/generic/cname_5.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: cname_5.c,v 1.47 2007/06/19 23:47:17 tbox Exp $ */
+
+/* reviewed: Wed Mar 15 16:48:45 PST 2000 by brister */
+
+#ifndef RDATA_GENERIC_CNAME_5_C
+#define RDATA_GENERIC_CNAME_5_C
+
+#define RRTYPE_CNAME_ATTRIBUTES \
+ (DNS_RDATATYPEATTR_EXCLUSIVE | DNS_RDATATYPEATTR_SINGLETON)
+
+static inline isc_result_t
+fromtext_cname(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 5);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_cname(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 5);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_cname(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == 5);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_cname(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 5);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_cname(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 5);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_cname(ARGS_FROMSTRUCT) {
+ dns_rdata_cname_t *cname = source;
+ isc_region_t region;
+
+ REQUIRE(type == 5);
+ REQUIRE(source != NULL);
+ REQUIRE(cname->common.rdtype == type);
+ REQUIRE(cname->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&cname->cname, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_cname(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_cname_t *cname = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 5);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ cname->common.rdclass = rdata->rdclass;
+ cname->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&cname->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&cname->cname, NULL);
+ RETERR(name_duporclone(&name, mctx, &cname->cname));
+ cname->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_cname(ARGS_FREESTRUCT) {
+ dns_rdata_cname_t *cname = source;
+
+ REQUIRE(source != NULL);
+
+ if (cname->mctx == NULL)
+ return;
+
+ dns_name_free(&cname->cname, cname->mctx);
+ cname->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_cname(ARGS_ADDLDATA) {
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ REQUIRE(rdata->type == 5);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_cname(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 5);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_cname(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 5);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_cname(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 5);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_CNAME_5_C */
diff --git a/lib/dns/rdata/generic/cname_5.h b/lib/dns/rdata/generic/cname_5.h
new file mode 100644
index 0000000..516f8d3
--- /dev/null
+++ b/lib/dns/rdata/generic/cname_5.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: cname_5.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef GENERIC_CNAME_5_H
+#define GENERIC_CNAME_5_H 1
+
+typedef struct dns_rdata_cname {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t cname;
+} dns_rdata_cname_t;
+
+#endif /* GENERIC_CNAME_5_H */
diff --git a/lib/dns/rdata/generic/dlv_32769.c b/lib/dns/rdata/generic/dlv_32769.c
new file mode 100644
index 0000000..957f038
--- /dev/null
+++ b/lib/dns/rdata/generic/dlv_32769.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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: dlv_32769.c,v 1.6 2007/06/18 23:47:43 tbox Exp $ */
+
+/* draft-ietf-dnsext-delegation-signer-05.txt */
+
+#ifndef RDATA_GENERIC_DLV_32769_C
+#define RDATA_GENERIC_DLV_32769_C
+
+#define RRTYPE_DLV_ATTRIBUTES 0
+
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+
+#include <dns/ds.h>
+
+
+static inline isc_result_t
+fromtext_dlv(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char c;
+ int length;
+
+ REQUIRE(type == 32769);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Key tag.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, 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));
+
+ /*
+ * Digest type.
+ */
+ 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));
+ c = (unsigned char) token.value.as_ulong;
+
+ /*
+ * Digest.
+ */
+ if (c == DNS_DSDIGEST_SHA1)
+ length = ISC_SHA1_DIGESTLENGTH;
+ else if (c == DNS_DSDIGEST_SHA256)
+ length = ISC_SHA256_DIGESTLENGTH;
+ else
+ length = -1;
+ return (isc_hex_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_dlv(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000 ")];
+ unsigned int n;
+
+ REQUIRE(rdata->type == 32769);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Key tag.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Algorithm.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest type.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest.
+ */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_dlv(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 32769);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+
+ /*
+ * Check digest lengths if we know them.
+ */
+ if (sr.length < 4 ||
+ (sr.base[3] == DNS_DSDIGEST_SHA1 &&
+ sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_SHA256 &&
+ sr.length < 4 + ISC_SHA256_DIGESTLENGTH))
+ return (ISC_R_UNEXPECTEDEND);
+
+ /*
+ * Only copy digest lengths if we know them.
+ * If there is extra data dns_rdata_fromwire() will
+ * detect that.
+ */
+ if (sr.base[3] == DNS_DSDIGEST_SHA1)
+ sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
+ else if (sr.base[3] == DNS_DSDIGEST_SHA256)
+ sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_dlv(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 32769);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_dlv(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 32769);
+ 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_dlv(ARGS_FROMSTRUCT) {
+ dns_rdata_dlv_t *dlv = source;
+
+ REQUIRE(type == 32769);
+ REQUIRE(source != NULL);
+ REQUIRE(dlv->common.rdtype == type);
+ REQUIRE(dlv->common.rdclass == rdclass);
+ switch (dlv->digest_type) {
+ case DNS_DSDIGEST_SHA1:
+ REQUIRE(dlv->length == ISC_SHA1_DIGESTLENGTH);
+ break;
+ case DNS_DSDIGEST_SHA256:
+ REQUIRE(dlv->length == ISC_SHA256_DIGESTLENGTH);
+ break;
+ }
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(dlv->key_tag, target));
+ RETERR(uint8_tobuffer(dlv->algorithm, target));
+ RETERR(uint8_tobuffer(dlv->digest_type, target));
+
+ return (mem_tobuffer(target, dlv->digest, dlv->length));
+}
+
+static inline isc_result_t
+tostruct_dlv(ARGS_TOSTRUCT) {
+ dns_rdata_dlv_t *dlv = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 32769);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ dlv->common.rdclass = rdata->rdclass;
+ dlv->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dlv->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dlv->key_tag = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ dlv->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ dlv->digest_type = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ dlv->length = region.length;
+
+ dlv->digest = mem_maybedup(mctx, region.base, region.length);
+ if (dlv->digest == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dlv->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_dlv(ARGS_FREESTRUCT) {
+ dns_rdata_dlv_t *dlv = source;
+
+ REQUIRE(dlv != NULL);
+ REQUIRE(dlv->common.rdtype == 32769);
+
+ if (dlv->mctx == NULL)
+ return;
+
+ if (dlv->digest != NULL)
+ isc_mem_free(dlv->mctx, dlv->digest);
+ dlv->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_dlv(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 32769);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_dlv(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 32769);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_dlv(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 32769);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_dlv(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 32769);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_DLV_32769_C */
diff --git a/lib/dns/rdata/generic/dlv_32769.h b/lib/dns/rdata/generic/dlv_32769.h
new file mode 100644
index 0000000..2313c57
--- /dev/null
+++ b/lib/dns/rdata/generic/dlv_32769.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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: dlv_32769.h,v 1.5 2007/06/19 23:47:17 tbox Exp $ */
+
+/* draft-ietf-dnsext-delegation-signer-05.txt */
+#ifndef GENERIC_DLV_32769_H
+#define GENERIC_DLV_32769_H 1
+
+typedef struct dns_rdata_dlv {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t key_tag;
+ isc_uint8_t algorithm;
+ isc_uint8_t digest_type;
+ isc_uint16_t length;
+ unsigned char *digest;
+} dns_rdata_dlv_t;
+
+#endif /* GENERIC_DLV_32769_H */
diff --git a/lib/dns/rdata/generic/dname_39.c b/lib/dns/rdata/generic/dname_39.c
new file mode 100644
index 0000000..c399f1e
--- /dev/null
+++ b/lib/dns/rdata/generic/dname_39.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: dname_39.c,v 1.38 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Wed Mar 15 16:52:38 PST 2000 by explorer */
+
+/* RFC2672 */
+
+#ifndef RDATA_GENERIC_DNAME_39_C
+#define RDATA_GENERIC_DNAME_39_C
+
+#define RRTYPE_DNAME_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON)
+
+static inline isc_result_t
+fromtext_dname(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 39);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_dname(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 39);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_dname(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == 39);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+ return(dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_dname(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 39);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_dname(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 39);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_dname(ARGS_FROMSTRUCT) {
+ dns_rdata_dname_t *dname = source;
+ isc_region_t region;
+
+ REQUIRE(type == 39);
+ REQUIRE(source != NULL);
+ REQUIRE(dname->common.rdtype == type);
+ REQUIRE(dname->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&dname->dname, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_dname(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_dname_t *dname = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 39);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ dname->common.rdclass = rdata->rdclass;
+ dname->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dname->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&dname->dname, NULL);
+ RETERR(name_duporclone(&name, mctx, &dname->dname));
+ dname->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_dname(ARGS_FREESTRUCT) {
+ dns_rdata_dname_t *dname = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(dname->common.rdtype == 39);
+
+ if (dname->mctx == NULL)
+ return;
+
+ dns_name_free(&dname->dname, dname->mctx);
+ dname->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_dname(ARGS_ADDLDATA) {
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ REQUIRE(rdata->type == 39);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_dname(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 39);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_dname(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 39);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_dname(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 39);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_DNAME_39_C */
diff --git a/lib/dns/rdata/generic/dname_39.h b/lib/dns/rdata/generic/dname_39.h
new file mode 100644
index 0000000..f8aca27
--- /dev/null
+++ b/lib/dns/rdata/generic/dname_39.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef GENERIC_DNAME_39_H
+#define GENERIC_DNAME_39_H 1
+
+/* $Id: dname_39.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief per RFC2672 */
+
+typedef struct dns_rdata_dname {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t dname;
+} dns_rdata_dname_t;
+
+#endif /* GENERIC_DNAME_39_H */
diff --git a/lib/dns/rdata/generic/dnskey_48.c b/lib/dns/rdata/generic/dnskey_48.c
new file mode 100644
index 0000000..2e11cba
--- /dev/null
+++ b/lib/dns/rdata/generic/dnskey_48.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: dnskey_48.c,v 1.8 2007/06/19 23:47:17 tbox Exp $ */
+
+/*
+ * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
+ */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_DNSKEY_48_C
+#define RDATA_GENERIC_DNSKEY_48_C
+
+#include <dst/dst.h>
+
+#define RRTYPE_DNSKEY_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static inline isc_result_t
+fromtext_dnskey(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_secalg_t alg;
+ dns_secproto_t proto;
+ dns_keyflags_t flags;
+
+ REQUIRE(type == 48);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* 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_dnskey(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000")];
+ unsigned int flags;
+ unsigned char algorithm;
+
+ REQUIRE(rdata->type == 48);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* 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);
+ sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm));
+ RETERR(str_totext(buf, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_dnskey(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 48);
+
+ 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_dnskey(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 48);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_dnskey(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 48);
+ 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_dnskey(ARGS_FROMSTRUCT) {
+ dns_rdata_dnskey_t *dnskey = source;
+
+ REQUIRE(type == 48);
+ REQUIRE(source != NULL);
+ REQUIRE(dnskey->common.rdtype == type);
+ REQUIRE(dnskey->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /* Flags */
+ RETERR(uint16_tobuffer(dnskey->flags, target));
+
+ /* Protocol */
+ RETERR(uint8_tobuffer(dnskey->protocol, target));
+
+ /* Algorithm */
+ RETERR(uint8_tobuffer(dnskey->algorithm, target));
+
+ /* Data */
+ return (mem_tobuffer(target, dnskey->data, dnskey->datalen));
+}
+
+static inline isc_result_t
+tostruct_dnskey(ARGS_TOSTRUCT) {
+ dns_rdata_dnskey_t *dnskey = target;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 48);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ dnskey->common.rdclass = rdata->rdclass;
+ dnskey->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dnskey->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* Flags */
+ if (sr.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ dnskey->flags = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /* Protocol */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ dnskey->protocol = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Algorithm */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ dnskey->algorithm = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Data */
+ dnskey->datalen = sr.length;
+ dnskey->data = mem_maybedup(mctx, sr.base, dnskey->datalen);
+ if (dnskey->data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dnskey->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_dnskey(ARGS_FREESTRUCT) {
+ dns_rdata_dnskey_t *dnskey = (dns_rdata_dnskey_t *) source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(dnskey->common.rdtype == 48);
+
+ if (dnskey->mctx == NULL)
+ return;
+
+ if (dnskey->data != NULL)
+ isc_mem_free(dnskey->mctx, dnskey->data);
+ dnskey->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_dnskey(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 48);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_dnskey(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 48);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_dnskey(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 48);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_dnskey(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 48);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_DNSKEY_48_C */
diff --git a/lib/dns/rdata/generic/dnskey_48.h b/lib/dns/rdata/generic/dnskey_48.h
new file mode 100644
index 0000000..ce88cd1
--- /dev/null
+++ b/lib/dns/rdata/generic/dnskey_48.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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.
+ */
+
+#ifndef GENERIC_DNSKEY_48_H
+#define GENERIC_DNSKEY_48_H 1
+
+/* $Id: dnskey_48.h,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief per RFC2535 */
+
+typedef struct dns_rdata_dnskey {
+ dns_rdatacommon_t common;
+ isc_mem_t * mctx;
+ isc_uint16_t flags;
+ isc_uint8_t protocol;
+ isc_uint8_t algorithm;
+ isc_uint16_t datalen;
+ unsigned char * data;
+} dns_rdata_dnskey_t;
+
+
+#endif /* GENERIC_DNSKEY_48_H */
diff --git a/lib/dns/rdata/generic/ds_43.c b/lib/dns/rdata/generic/ds_43.c
new file mode 100644
index 0000000..08e5d5f
--- /dev/null
+++ b/lib/dns/rdata/generic/ds_43.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: ds_43.c,v 1.12 2007/06/18 23:47:43 tbox Exp $ */
+
+/* draft-ietf-dnsext-delegation-signer-05.txt */
+
+#ifndef RDATA_GENERIC_DS_43_C
+#define RDATA_GENERIC_DS_43_C
+
+#define RRTYPE_DS_ATTRIBUTES \
+ (DNS_RDATATYPEATTR_DNSSEC|DNS_RDATATYPEATTR_ATPARENT)
+
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+
+#include <dns/ds.h>
+
+static inline isc_result_t
+fromtext_ds(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char c;
+ int length;
+
+ REQUIRE(type == 43);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * Key tag.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Digest type.
+ */
+ 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));
+ c = (unsigned char) token.value.as_ulong;
+
+ /*
+ * Digest.
+ */
+ if (c == DNS_DSDIGEST_SHA1)
+ length = ISC_SHA1_DIGESTLENGTH;
+ else if (c == DNS_DSDIGEST_SHA256)
+ length = ISC_SHA256_DIGESTLENGTH;
+ else
+ length = -1;
+ return (isc_hex_tobuffer(lexer, target, length));
+}
+
+static inline isc_result_t
+totext_ds(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000 ")];
+ unsigned int n;
+
+ REQUIRE(rdata->type == 43);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Key tag.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Algorithm.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest type.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest.
+ */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_ds(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 43);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+
+ /*
+ * Check digest lengths if we know them.
+ */
+ if (sr.length < 4 ||
+ (sr.base[3] == DNS_DSDIGEST_SHA1 &&
+ sr.length < 4 + ISC_SHA1_DIGESTLENGTH) ||
+ (sr.base[3] == DNS_DSDIGEST_SHA256 &&
+ sr.length < 4 + ISC_SHA256_DIGESTLENGTH))
+ return (ISC_R_UNEXPECTEDEND);
+
+ /*
+ * Only copy digest lengths if we know them.
+ * If there is extra data dns_rdata_fromwire() will
+ * detect that.
+ */
+ if (sr.base[3] == DNS_DSDIGEST_SHA1)
+ sr.length = 4 + ISC_SHA1_DIGESTLENGTH;
+ else if (sr.base[3] == DNS_DSDIGEST_SHA256)
+ sr.length = 4 + ISC_SHA256_DIGESTLENGTH;
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_ds(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 43);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_ds(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 43);
+ 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_ds(ARGS_FROMSTRUCT) {
+ dns_rdata_ds_t *ds = source;
+
+ REQUIRE(type == 43);
+ REQUIRE(source != NULL);
+ REQUIRE(ds->common.rdtype == type);
+ REQUIRE(ds->common.rdclass == rdclass);
+ switch (ds->digest_type) {
+ case DNS_DSDIGEST_SHA1:
+ REQUIRE(ds->length == ISC_SHA1_DIGESTLENGTH);
+ break;
+ case DNS_DSDIGEST_SHA256:
+ REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH);
+ break;
+ }
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(ds->key_tag, target));
+ RETERR(uint8_tobuffer(ds->algorithm, target));
+ RETERR(uint8_tobuffer(ds->digest_type, target));
+
+ return (mem_tobuffer(target, ds->digest, ds->length));
+}
+
+static inline isc_result_t
+tostruct_ds(ARGS_TOSTRUCT) {
+ dns_rdata_ds_t *ds = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 43);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ ds->common.rdclass = rdata->rdclass;
+ ds->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ds->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ ds->key_tag = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ ds->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ ds->digest_type = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ ds->length = region.length;
+
+ ds->digest = mem_maybedup(mctx, region.base, region.length);
+ if (ds->digest == NULL)
+ return (ISC_R_NOMEMORY);
+
+ ds->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_ds(ARGS_FREESTRUCT) {
+ dns_rdata_ds_t *ds = source;
+
+ REQUIRE(ds != NULL);
+ REQUIRE(ds->common.rdtype == 43);
+
+ if (ds->mctx == NULL)
+ return;
+
+ if (ds->digest != NULL)
+ isc_mem_free(ds->mctx, ds->digest);
+ ds->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_ds(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 43);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_ds(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 43);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_ds(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 43);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_ds(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 43);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_DS_43_C */
diff --git a/lib/dns/rdata/generic/ds_43.h b/lib/dns/rdata/generic/ds_43.h
new file mode 100644
index 0000000..3a409a1
--- /dev/null
+++ b/lib/dns/rdata/generic/ds_43.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: ds_43.h,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef GENERIC_DS_43_H
+#define GENERIC_DS_43_H 1
+
+/*!
+ * \brief per draft-ietf-dnsext-delegation-signer-05.txt */
+typedef struct dns_rdata_ds {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t key_tag;
+ isc_uint8_t algorithm;
+ isc_uint8_t digest_type;
+ isc_uint16_t length;
+ unsigned char *digest;
+} dns_rdata_ds_t;
+
+#endif /* GENERIC_DS_43_H */
diff --git a/lib/dns/rdata/generic/gpos_27.c b/lib/dns/rdata/generic/gpos_27.c
new file mode 100644
index 0000000..18effb5
--- /dev/null
+++ b/lib/dns/rdata/generic/gpos_27.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: gpos_27.c,v 1.41 2007/06/19 23:47:17 tbox Exp $ */
+
+/* reviewed: Wed Mar 15 16:48:45 PST 2000 by brister */
+
+/* RFC1712 */
+
+#ifndef RDATA_GENERIC_GPOS_27_C
+#define RDATA_GENERIC_GPOS_27_C
+
+#define RRTYPE_GPOS_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_gpos(ARGS_FROMTEXT) {
+ isc_token_t token;
+ int i;
+
+ REQUIRE(type == 27);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ for (i = 0; i < 3; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_qstring,
+ ISC_FALSE));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_gpos(ARGS_TOTEXT) {
+ isc_region_t region;
+ int i;
+
+ REQUIRE(rdata->type == 27);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+
+ for (i = 0; i < 3; i++) {
+ RETERR(txt_totext(&region, target));
+ if (i != 2)
+ RETERR(str_totext(" ", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_gpos(ARGS_FROMWIRE) {
+ int i;
+
+ REQUIRE(type == 27);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ for (i = 0; i < 3; i++)
+ RETERR(txt_fromwire(source, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_gpos(ARGS_TOWIRE) {
+
+ REQUIRE(rdata->type == 27);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static inline int
+compare_gpos(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 27);
+ 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_gpos(ARGS_FROMSTRUCT) {
+ dns_rdata_gpos_t *gpos = source;
+
+ REQUIRE(type == 27);
+ REQUIRE(source != NULL);
+ REQUIRE(gpos->common.rdtype == type);
+ REQUIRE(gpos->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(gpos->long_len, target));
+ RETERR(mem_tobuffer(target, gpos->longitude, gpos->long_len));
+ RETERR(uint8_tobuffer(gpos->lat_len, target));
+ RETERR(mem_tobuffer(target, gpos->latitude, gpos->lat_len));
+ RETERR(uint8_tobuffer(gpos->alt_len, target));
+ return (mem_tobuffer(target, gpos->altitude, gpos->alt_len));
+}
+
+static inline isc_result_t
+tostruct_gpos(ARGS_TOSTRUCT) {
+ dns_rdata_gpos_t *gpos = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 27);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ gpos->common.rdclass = rdata->rdclass;
+ gpos->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&gpos->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ gpos->long_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ gpos->longitude = mem_maybedup(mctx, region.base, gpos->long_len);
+ if (gpos->longitude == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_region_consume(&region, gpos->long_len);
+
+ gpos->lat_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ gpos->latitude = mem_maybedup(mctx, region.base, gpos->lat_len);
+ if (gpos->latitude == NULL)
+ goto cleanup_longitude;
+ isc_region_consume(&region, gpos->lat_len);
+
+ gpos->alt_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ if (gpos->lat_len > 0) {
+ gpos->altitude =
+ mem_maybedup(mctx, region.base, gpos->alt_len);
+ if (gpos->altitude == NULL)
+ goto cleanup_latitude;
+ } else
+ gpos->altitude = NULL;
+
+ gpos->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup_latitude:
+ if (mctx != NULL && gpos->longitude != NULL)
+ isc_mem_free(mctx, gpos->longitude);
+
+ cleanup_longitude:
+ if (mctx != NULL && gpos->latitude != NULL)
+ isc_mem_free(mctx, gpos->latitude);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_gpos(ARGS_FREESTRUCT) {
+ dns_rdata_gpos_t *gpos = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(gpos->common.rdtype == 27);
+
+ if (gpos->mctx == NULL)
+ return;
+
+ if (gpos->longitude != NULL)
+ isc_mem_free(gpos->mctx, gpos->longitude);
+ if (gpos->latitude != NULL)
+ isc_mem_free(gpos->mctx, gpos->latitude);
+ if (gpos->altitude != NULL)
+ isc_mem_free(gpos->mctx, gpos->altitude);
+ gpos->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_gpos(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 27);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_gpos(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 27);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_gpos(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 27);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_gpos(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 27);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_GPOS_27_C */
diff --git a/lib/dns/rdata/generic/gpos_27.h b/lib/dns/rdata/generic/gpos_27.h
new file mode 100644
index 0000000..f5df4fa
--- /dev/null
+++ b/lib/dns/rdata/generic/gpos_27.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef GENERIC_GPOS_27_H
+#define GENERIC_GPOS_27_H 1
+
+/* $Id: gpos_27.h,v 1.17 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief per RFC1712 */
+
+typedef struct dns_rdata_gpos {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ char *longitude;
+ char *latitude;
+ char *altitude;
+ isc_uint8_t long_len;
+ isc_uint8_t lat_len;
+ isc_uint8_t alt_len;
+} dns_rdata_gpos_t;
+
+#endif /* GENERIC_GPOS_27_H */
diff --git a/lib/dns/rdata/generic/hinfo_13.c b/lib/dns/rdata/generic/hinfo_13.c
new file mode 100644
index 0000000..5321357
--- /dev/null
+++ b/lib/dns/rdata/generic/hinfo_13.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: hinfo_13.c,v 1.44 2007/06/19 23:47:17 tbox Exp $ */
+
+/*
+ * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
+ */
+
+#ifndef RDATA_GENERIC_HINFO_13_C
+#define RDATA_GENERIC_HINFO_13_C
+
+#define RRTYPE_HINFO_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_hinfo(ARGS_FROMTEXT) {
+ isc_token_t token;
+ int i;
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ REQUIRE(type == 13);
+
+ for (i = 0; i < 2; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_qstring,
+ ISC_FALSE));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_hinfo(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == 13);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &region);
+ RETERR(txt_totext(&region, target));
+ RETERR(str_totext(" ", target));
+ return (txt_totext(&region, target));
+}
+
+static inline isc_result_t
+fromwire_hinfo(ARGS_FROMWIRE) {
+
+ REQUIRE(type == 13);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ RETERR(txt_fromwire(source, target));
+ return (txt_fromwire(source, target));
+}
+
+static inline isc_result_t
+towire_hinfo(ARGS_TOWIRE) {
+
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == 13);
+ REQUIRE(rdata->length != 0);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static inline int
+compare_hinfo(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 13);
+ 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_hinfo(ARGS_FROMSTRUCT) {
+ dns_rdata_hinfo_t *hinfo = source;
+
+ REQUIRE(type == 13);
+ REQUIRE(source != NULL);
+ REQUIRE(hinfo->common.rdtype == type);
+ REQUIRE(hinfo->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(hinfo->cpu_len, target));
+ RETERR(mem_tobuffer(target, hinfo->cpu, hinfo->cpu_len));
+ RETERR(uint8_tobuffer(hinfo->os_len, target));
+ return (mem_tobuffer(target, hinfo->os, hinfo->os_len));
+}
+
+static inline isc_result_t
+tostruct_hinfo(ARGS_TOSTRUCT) {
+ dns_rdata_hinfo_t *hinfo = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 13);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ hinfo->common.rdclass = rdata->rdclass;
+ hinfo->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&hinfo->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ hinfo->cpu_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ hinfo->cpu = mem_maybedup(mctx, region.base, hinfo->cpu_len);
+ if (hinfo->cpu == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_region_consume(&region, hinfo->cpu_len);
+
+ hinfo->os_len = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ hinfo->os = mem_maybedup(mctx, region.base, hinfo->os_len);
+ if (hinfo->os == NULL)
+ goto cleanup;
+
+ hinfo->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL && hinfo->cpu != NULL)
+ isc_mem_free(mctx, hinfo->cpu);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_hinfo(ARGS_FREESTRUCT) {
+ dns_rdata_hinfo_t *hinfo = source;
+
+ REQUIRE(source != NULL);
+
+ if (hinfo->mctx == NULL)
+ return;
+
+ if (hinfo->cpu != NULL)
+ isc_mem_free(hinfo->mctx, hinfo->cpu);
+ if (hinfo->os != NULL)
+ isc_mem_free(hinfo->mctx, hinfo->os);
+ hinfo->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_hinfo(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 13);
+
+ UNUSED(add);
+ UNUSED(arg);
+ UNUSED(rdata);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_hinfo(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 13);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_hinfo(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 13);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_hinfo(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 13);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_HINFO_13_C */
diff --git a/lib/dns/rdata/generic/hinfo_13.h b/lib/dns/rdata/generic/hinfo_13.h
new file mode 100644
index 0000000..66766df
--- /dev/null
+++ b/lib/dns/rdata/generic/hinfo_13.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+#ifndef GENERIC_HINFO_13_H
+#define GENERIC_HINFO_13_H 1
+
+/* $Id: hinfo_13.h,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_hinfo {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ char *cpu;
+ char *os;
+ isc_uint8_t cpu_len;
+ isc_uint8_t os_len;
+} dns_rdata_hinfo_t;
+
+#endif /* GENERIC_HINFO_13_H */
diff --git a/lib/dns/rdata/generic/ipseckey_45.c b/lib/dns/rdata/generic/ipseckey_45.c
new file mode 100644
index 0000000..92f5e21
--- /dev/null
+++ b/lib/dns/rdata/generic/ipseckey_45.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2005, 2007 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: ipseckey_45.c,v 1.4 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef RDATA_GENERIC_IPSECKEY_45_C
+#define RDATA_GENERIC_IPSECKEY_45_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#define RRTYPE_IPSECKEY_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_ipseckey(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ unsigned int gateway;
+ struct in_addr addr;
+ unsigned char addr6[16];
+ isc_region_t region;
+
+ REQUIRE(type == 45);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Precedence.
+ */
+ 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));
+
+ /*
+ * Gateway type.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0x3U)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(token.value.as_ulong, target));
+ gateway = token.value.as_ulong;
+
+ /*
+ * 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));
+
+ /*
+ * Gateway.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ switch (gateway) {
+ case 0:
+ if (strcmp(DNS_AS_STR(token), ".") != 0)
+ RETTOK(DNS_R_SYNTAX);
+ break;
+
+ case 1:
+ if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1)
+ RETTOK(DNS_R_BADDOTTEDQUAD);
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 4)
+ return (ISC_R_NOSPACE);
+ memcpy(region.base, &addr, 4);
+ isc_buffer_add(target, 4);
+ break;
+
+ case 2:
+ if (inet_pton(AF_INET6, DNS_AS_STR(token), addr6) != 1)
+ RETTOK(DNS_R_BADAAAA);
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 16)
+ return (ISC_R_NOSPACE);
+ memcpy(region.base, addr6, 16);
+ isc_buffer_add(target, 16);
+ break;
+
+ case 3:
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin,
+ options, target));
+ break;
+ }
+
+ /*
+ * Public key.
+ */
+ return (isc_base64_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_ipseckey(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ char buf[sizeof("255 ")];
+ unsigned short num;
+ unsigned short gateway;
+
+ REQUIRE(rdata->type == 45);
+ REQUIRE(rdata->length >= 3);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ if (rdata->data[1] > 3U)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext("( ", target));
+
+ /*
+ * Precendence.
+ */
+ dns_rdata_toregion(rdata, &region);
+ num = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ sprintf(buf, "%u ", num);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Gateway type.
+ */
+ gateway = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ sprintf(buf, "%u ", gateway);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Algorithm.
+ */
+ num = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ sprintf(buf, "%u ", num);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Gateway.
+ */
+ switch (gateway) {
+ case 0:
+ RETERR(str_totext(".", target));
+ break;
+
+ case 1:
+ RETERR(inet_totext(AF_INET, &region, target));
+ isc_region_consume(&region, 4);
+ break;
+
+ case 2:
+ RETERR(inet_totext(AF_INET6, &region, target));
+ isc_region_consume(&region, 16);
+ break;
+
+ case 3:
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+ isc_region_consume(&region, name_length(&name));
+ break;
+ }
+
+ /*
+ * Key.
+ */
+ if (region.length > 0U) {
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(isc_base64_totext(&region, tctx->width - 2,
+ tctx->linebreak, target));
+ }
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_ipseckey(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t region;
+
+ REQUIRE(type == 45);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 3)
+ return (ISC_R_UNEXPECTEDEND);
+
+ switch (region.base[1]) {
+ case 0:
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+
+ case 1:
+ if (region.length < 7)
+ return (ISC_R_UNEXPECTEDEND);
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+
+ case 2:
+ if (region.length < 19)
+ return (ISC_R_UNEXPECTEDEND);
+ isc_buffer_forward(source, region.length);
+ return (mem_tobuffer(target, region.base, region.length));
+
+ case 3:
+ RETERR(mem_tobuffer(target, region.base, 3));
+ isc_buffer_forward(source, 3);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+ isc_buffer_activeregion(source, &region);
+ return(mem_tobuffer(target, region.base, region.length));
+
+ default:
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+}
+
+static inline isc_result_t
+towire_ipseckey(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 45);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (mem_tobuffer(target, region.base, region.length));
+}
+
+static inline int
+compare_ipseckey(ARGS_COMPARE) {
+ isc_region_t region1;
+ isc_region_t region2;
+
+ 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, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ return (isc_region_compare(&region1, &region2));
+}
+
+static inline isc_result_t
+fromstruct_ipseckey(ARGS_FROMSTRUCT) {
+ dns_rdata_ipseckey_t *ipseckey = source;
+ isc_region_t region;
+ isc_uint32_t n;
+
+ REQUIRE(type == 45);
+ REQUIRE(source != NULL);
+ REQUIRE(ipseckey->common.rdtype == type);
+ REQUIRE(ipseckey->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ if (ipseckey->gateway_type > 3U)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ RETERR(uint8_tobuffer(ipseckey->precedence, target));
+ RETERR(uint8_tobuffer(ipseckey->gateway_type, target));
+ RETERR(uint8_tobuffer(ipseckey->algorithm, target));
+
+ switch (ipseckey->gateway_type) {
+ case 0:
+ break;
+
+ case 1:
+ n = ntohl(ipseckey->in_addr.s_addr);
+ RETERR(uint32_tobuffer(n, target));
+ break;
+
+ case 2:
+ RETERR(mem_tobuffer(target, ipseckey->in6_addr.s6_addr, 16));
+ break;
+
+ case 3:
+ dns_name_toregion(&ipseckey->gateway, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ break;
+ }
+
+ return (mem_tobuffer(target, ipseckey->key, ipseckey->keylength));
+}
+
+static inline isc_result_t
+tostruct_ipseckey(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_ipseckey_t *ipseckey = target;
+ dns_name_t name;
+ isc_uint32_t n;
+
+ REQUIRE(rdata->type == 45);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length >= 3);
+
+ if (rdata->data[1] > 3U)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ ipseckey->common.rdclass = rdata->rdclass;
+ ipseckey->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ipseckey->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+
+ ipseckey->precedence = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ ipseckey->gateway_type = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ ipseckey->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+
+ switch (ipseckey->gateway_type) {
+ case 0:
+ break;
+
+ case 1:
+ n = uint32_fromregion(&region);
+ ipseckey->in_addr.s_addr = htonl(n);
+ isc_region_consume(&region, 4);
+ break;
+
+ case 2:
+ memcpy(ipseckey->in6_addr.s6_addr, region.base, 16);
+ isc_region_consume(&region, 16);
+ break;
+
+ case 3:
+ dns_name_init(&ipseckey->gateway, NULL);
+ dns_name_fromregion(&name, &region);
+ RETERR(name_duporclone(&name, mctx, &ipseckey->gateway));
+ isc_region_consume(&region, name_length(&name));
+ break;
+ }
+
+ ipseckey->keylength = region.length;
+ if (ipseckey->keylength != 0U) {
+ ipseckey->key = mem_maybedup(mctx, region.base,
+ ipseckey->keylength);
+ if (ipseckey->key == NULL) {
+ if (ipseckey->gateway_type == 3)
+ dns_name_free(&ipseckey->gateway,
+ ipseckey->mctx);
+ return (ISC_R_NOMEMORY);
+ }
+ } else
+ ipseckey->key = NULL;
+
+ ipseckey->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_ipseckey(ARGS_FREESTRUCT) {
+ dns_rdata_ipseckey_t *ipseckey = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(ipseckey->common.rdtype == 45);
+
+ if (ipseckey->mctx == NULL)
+ return;
+
+ if (ipseckey->gateway_type == 3)
+ dns_name_free(&ipseckey->gateway, ipseckey->mctx);
+
+ if (ipseckey->key != NULL)
+ isc_mem_free(ipseckey->mctx, ipseckey->key);
+
+ ipseckey->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_ipseckey(ARGS_ADDLDATA) {
+
+ REQUIRE(rdata->type == 45);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_ipseckey(ARGS_DIGEST) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 45);
+
+ dns_rdata_toregion(rdata, &region);
+ return ((digest)(arg, &region));
+}
+
+static inline isc_boolean_t
+checkowner_ipseckey(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 45);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_ipseckey(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 45);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_IPSECKEY_45_C */
diff --git a/lib/dns/rdata/generic/ipseckey_45.h b/lib/dns/rdata/generic/ipseckey_45.h
new file mode 100644
index 0000000..2a6201f
--- /dev/null
+++ b/lib/dns/rdata/generic/ipseckey_45.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2005, 2007 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: ipseckey_45.h,v 1.4 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef GENERIC_IPSECKEY_45_H
+#define GENERIC_IPSECKEY_45_H 1
+
+typedef struct dns_rdata_ipseckey {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint8_t precedence;
+ isc_uint8_t gateway_type;
+ isc_uint8_t algorithm;
+ struct in_addr in_addr; /* gateway type 1 */
+ struct in6_addr in6_addr; /* gateway type 2 */
+ dns_name_t gateway; /* gateway type 3 */
+ unsigned char *key;
+ isc_uint16_t keylength;
+} dns_rdata_ipseckey_t;
+
+#endif /* GENERIC_IPSECKEY_45_H */
diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c
new file mode 100644
index 0000000..d7333d1
--- /dev/null
+++ b/lib/dns/rdata/generic/isdn_20.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: isdn_20.c,v 1.38 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Wed Mar 15 16:53:11 PST 2000 by bwelling */
+
+/* RFC1183 */
+
+#ifndef RDATA_GENERIC_ISDN_20_C
+#define RDATA_GENERIC_ISDN_20_C
+
+#define RRTYPE_ISDN_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_isdn(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ REQUIRE(type == 20);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* ISDN-address */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ ISC_FALSE));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+
+ /* sa: optional */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ ISC_TRUE));
+ if (token.type != isc_tokentype_string &&
+ token.type != isc_tokentype_qstring) {
+ isc_lex_ungettoken(lexer, &token);
+ return (ISC_R_SUCCESS);
+ }
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_isdn(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 20);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ RETERR(txt_totext(&region, target));
+ if (region.length == 0)
+ return (ISC_R_SUCCESS);
+ RETERR(str_totext(" ", target));
+ return (txt_totext(&region, target));
+}
+
+static inline isc_result_t
+fromwire_isdn(ARGS_FROMWIRE) {
+ REQUIRE(type == 20);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ RETERR(txt_fromwire(source, target));
+ if (buffer_empty(source))
+ return (ISC_R_SUCCESS);
+ return (txt_fromwire(source, target));
+}
+
+static inline isc_result_t
+towire_isdn(ARGS_TOWIRE) {
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == 20);
+ REQUIRE(rdata->length != 0);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static inline int
+compare_isdn(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 20);
+ 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_isdn(ARGS_FROMSTRUCT) {
+ dns_rdata_isdn_t *isdn = source;
+
+ REQUIRE(type == 20);
+ REQUIRE(source != NULL);
+ REQUIRE(isdn->common.rdtype == type);
+ REQUIRE(isdn->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(isdn->isdn_len, target));
+ RETERR(mem_tobuffer(target, isdn->isdn, isdn->isdn_len));
+ RETERR(uint8_tobuffer(isdn->subaddress_len, target));
+ return (mem_tobuffer(target, isdn->subaddress, isdn->subaddress_len));
+}
+
+static inline isc_result_t
+tostruct_isdn(ARGS_TOSTRUCT) {
+ dns_rdata_isdn_t *isdn = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 20);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ isdn->common.rdclass = rdata->rdclass;
+ isdn->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&isdn->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+
+ isdn->isdn_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ isdn->isdn = mem_maybedup(mctx, r.base, isdn->isdn_len);
+ if (isdn->isdn == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_region_consume(&r, isdn->isdn_len);
+
+ isdn->subaddress_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ isdn->subaddress = mem_maybedup(mctx, r.base, isdn->subaddress_len);
+ if (isdn->subaddress == NULL)
+ goto cleanup;
+
+ isdn->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL && isdn->isdn != NULL)
+ isc_mem_free(mctx, isdn->isdn);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_isdn(ARGS_FREESTRUCT) {
+ dns_rdata_isdn_t *isdn = source;
+
+ REQUIRE(source != NULL);
+
+ if (isdn->mctx == NULL)
+ return;
+
+ if (isdn->isdn != NULL)
+ isc_mem_free(isdn->mctx, isdn->isdn);
+ if (isdn->subaddress != NULL)
+ isc_mem_free(isdn->mctx, isdn->subaddress);
+ isdn->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_isdn(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 20);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_isdn(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 20);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_isdn(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 20);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_isdn(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 20);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_ISDN_20_C */
diff --git a/lib/dns/rdata/generic/isdn_20.h b/lib/dns/rdata/generic/isdn_20.h
new file mode 100644
index 0000000..a1f65ca
--- /dev/null
+++ b/lib/dns/rdata/generic/isdn_20.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef GENERIC_ISDN_20_H
+#define GENERIC_ISDN_20_H 1
+
+/* $Id: isdn_20.h,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC1183 */
+
+typedef struct dns_rdata_isdn {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ char *isdn;
+ char *subaddress;
+ isc_uint8_t isdn_len;
+ isc_uint8_t subaddress_len;
+} dns_rdata_isdn_t;
+
+#endif /* GENERIC_ISDN_20_H */
diff --git a/lib/dns/rdata/generic/key_25.c b/lib/dns/rdata/generic/key_25.c
new file mode 100644
index 0000000..9acfe95
--- /dev/null
+++ b/lib/dns/rdata/generic/key_25.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: key_25.c,v 1.51 2007/06/19 23:47:17 tbox Exp $ */
+
+/*
+ * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley.
+ */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_KEY_25_C
+#define RDATA_GENERIC_KEY_25_C
+
+#include <dst/dst.h>
+
+#define RRTYPE_KEY_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_key(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_secalg_t alg;
+ dns_secproto_t proto;
+ dns_keyflags_t flags;
+
+ REQUIRE(type == 25);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /* 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_key(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000")];
+ unsigned int flags;
+ unsigned char algorithm;
+
+ REQUIRE(rdata->type == 25);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* 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);
+ sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm));
+ RETERR(str_totext(buf, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_key(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 25);
+
+ 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_key(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 25);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_key(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 25);
+ 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_key(ARGS_FROMSTRUCT) {
+ dns_rdata_key_t *key = source;
+
+ REQUIRE(type == 25);
+ REQUIRE(source != NULL);
+ REQUIRE(key->common.rdtype == type);
+ REQUIRE(key->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /* Flags */
+ RETERR(uint16_tobuffer(key->flags, target));
+
+ /* Protocol */
+ RETERR(uint8_tobuffer(key->protocol, target));
+
+ /* Algorithm */
+ RETERR(uint8_tobuffer(key->algorithm, target));
+
+ /* Data */
+ return (mem_tobuffer(target, key->data, key->datalen));
+}
+
+static inline isc_result_t
+tostruct_key(ARGS_TOSTRUCT) {
+ dns_rdata_key_t *key = target;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 25);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ key->common.rdclass = rdata->rdclass;
+ key->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&key->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* Flags */
+ if (sr.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ key->flags = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /* Protocol */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ key->protocol = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Algorithm */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ key->algorithm = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /* Data */
+ key->datalen = sr.length;
+ key->data = mem_maybedup(mctx, sr.base, key->datalen);
+ if (key->data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ key->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_key(ARGS_FREESTRUCT) {
+ dns_rdata_key_t *key = (dns_rdata_key_t *) source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(key->common.rdtype == 25);
+
+ if (key->mctx == NULL)
+ return;
+
+ if (key->data != NULL)
+ isc_mem_free(key->mctx, key->data);
+ key->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_key(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 25);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_key(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 25);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_key(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 25);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_key(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 25);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_KEY_25_C */
diff --git a/lib/dns/rdata/generic/key_25.h b/lib/dns/rdata/generic/key_25.h
new file mode 100644
index 0000000..bcf9cb6
--- /dev/null
+++ b/lib/dns/rdata/generic/key_25.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef GENERIC_KEY_25_H
+#define GENERIC_KEY_25_H 1
+
+/* $Id: key_25.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC2535 */
+
+typedef struct dns_rdata_key_t {
+ dns_rdatacommon_t common;
+ isc_mem_t * mctx;
+ isc_uint16_t flags;
+ isc_uint8_t protocol;
+ isc_uint8_t algorithm;
+ isc_uint16_t datalen;
+ unsigned char * data;
+} dns_rdata_key_t;
+
+
+#endif /* GENERIC_KEY_25_H */
diff --git a/lib/dns/rdata/generic/loc_29.c b/lib/dns/rdata/generic/loc_29.c
new file mode 100644
index 0000000..54b55a3
--- /dev/null
+++ b/lib/dns/rdata/generic/loc_29.c
@@ -0,0 +1,794 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: loc_29.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Wed Mar 15 18:13:09 PST 2000 by explorer */
+
+/* RFC1876 */
+
+#ifndef RDATA_GENERIC_LOC_29_C
+#define RDATA_GENERIC_LOC_29_C
+
+#define RRTYPE_LOC_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_loc(ARGS_FROMTEXT) {
+ isc_token_t token;
+ int d1, m1, s1;
+ int d2, m2, s2;
+ unsigned char size;
+ unsigned char hp;
+ unsigned char vp;
+ unsigned char version;
+ isc_boolean_t east = ISC_FALSE;
+ isc_boolean_t north = ISC_FALSE;
+ long tmp;
+ long m;
+ long cm;
+ long poweroften[8] = { 1, 10, 100, 1000,
+ 10000, 100000, 1000000, 10000000 };
+ int man;
+ int exp;
+ char *e;
+ int i;
+ unsigned long latitude;
+ unsigned long longitude;
+ unsigned long altitude;
+
+ REQUIRE(type == 29);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+
+ /*
+ * Defaults.
+ */
+ m1 = s1 = 0;
+ m2 = s2 = 0;
+ size = 0x12; /* 1.00m */
+ hp = 0x16; /* 10000.00 m */
+ vp = 0x13; /* 10.00 m */
+ version = 0;
+
+ /*
+ * Degrees.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 90U)
+ RETTOK(ISC_R_RANGE);
+ d1 = (int)token.value.as_ulong;
+ /*
+ * Minutes.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (strcasecmp(DNS_AS_STR(token), "N") == 0)
+ north = ISC_TRUE;
+ if (north || strcasecmp(DNS_AS_STR(token), "S") == 0)
+ goto getlong;
+ m1 = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0)
+ RETTOK(DNS_R_SYNTAX);
+ if (m1 < 0 || m1 > 59)
+ RETTOK(ISC_R_RANGE);
+ if (d1 == 90 && m1 != 0)
+ RETTOK(ISC_R_RANGE);
+
+ /*
+ * Seconds.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (strcasecmp(DNS_AS_STR(token), "N") == 0)
+ north = ISC_TRUE;
+ if (north || strcasecmp(DNS_AS_STR(token), "S") == 0)
+ goto getlong;
+ s1 = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0 && *e != '.')
+ RETTOK(DNS_R_SYNTAX);
+ if (s1 < 0 || s1 > 59)
+ RETTOK(ISC_R_RANGE);
+ if (*e == '.') {
+ const char *l;
+ e++;
+ for (i = 0; i < 3; i++) {
+ if (*e == 0)
+ break;
+ if ((tmp = decvalue(*e++)) < 0)
+ RETTOK(DNS_R_SYNTAX);
+ s1 *= 10;
+ s1 += tmp;
+ }
+ for (; i < 3; i++)
+ s1 *= 10;
+ l = e;
+ while (*e != 0) {
+ if (decvalue(*e++) < 0)
+ RETTOK(DNS_R_SYNTAX);
+ }
+ if (*l != '\0' && callbacks != NULL) {
+ const char *file = isc_lex_getsourcename(lexer);
+ unsigned long line = isc_lex_getsourceline(lexer);
+
+ if (file == NULL)
+ file = "UNKNOWN";
+ (*callbacks->warn)(callbacks, "%s: %s:%u: '%s' extra "
+ "precision digits ignored",
+ "dns_rdata_fromtext", file, line,
+ DNS_AS_STR(token));
+ }
+ } else
+ s1 *= 1000;
+ if (d1 == 90 && s1 != 0)
+ RETTOK(ISC_R_RANGE);
+
+ /*
+ * Direction.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (strcasecmp(DNS_AS_STR(token), "N") == 0)
+ north = ISC_TRUE;
+ if (!north && strcasecmp(DNS_AS_STR(token), "S") != 0)
+ RETTOK(DNS_R_SYNTAX);
+
+ getlong:
+ /*
+ * Degrees.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 180U)
+ RETTOK(ISC_R_RANGE);
+ d2 = (int)token.value.as_ulong;
+
+ /*
+ * Minutes.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (strcasecmp(DNS_AS_STR(token), "E") == 0)
+ east = ISC_TRUE;
+ if (east || strcasecmp(DNS_AS_STR(token), "W") == 0)
+ goto getalt;
+ m2 = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0)
+ RETTOK(DNS_R_SYNTAX);
+ if (m2 < 0 || m2 > 59)
+ RETTOK(ISC_R_RANGE);
+ if (d2 == 180 && m2 != 0)
+ RETTOK(ISC_R_RANGE);
+
+ /*
+ * Seconds.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (strcasecmp(DNS_AS_STR(token), "E") == 0)
+ east = ISC_TRUE;
+ if (east || strcasecmp(DNS_AS_STR(token), "W") == 0)
+ goto getalt;
+ s2 = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0 && *e != '.')
+ RETTOK(DNS_R_SYNTAX);
+ if (s2 < 0 || s2 > 59)
+ RETTOK(ISC_R_RANGE);
+ if (*e == '.') {
+ const char *l;
+ e++;
+ for (i = 0; i < 3; i++) {
+ if (*e == 0)
+ break;
+ if ((tmp = decvalue(*e++)) < 0)
+ RETTOK(DNS_R_SYNTAX);
+ s2 *= 10;
+ s2 += tmp;
+ }
+ for (; i < 3; i++)
+ s2 *= 10;
+ l = e;
+ while (*e != 0) {
+ if (decvalue(*e++) < 0)
+ RETTOK(DNS_R_SYNTAX);
+ }
+ if (*l != '\0' && callbacks != NULL) {
+ const char *file = isc_lex_getsourcename(lexer);
+ unsigned long line = isc_lex_getsourceline(lexer);
+
+ if (file == NULL)
+ file = "UNKNOWN";
+ (*callbacks->warn)(callbacks, "%s: %s:%u: '%s' extra "
+ "precision digits ignored",
+ "dns_rdata_fromtext",
+ file, line, DNS_AS_STR(token));
+ }
+ } else
+ s2 *= 1000;
+ if (d2 == 180 && s2 != 0)
+ RETTOK(ISC_R_RANGE);
+
+ /*
+ * Direction.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (strcasecmp(DNS_AS_STR(token), "E") == 0)
+ east = ISC_TRUE;
+ if (!east && strcasecmp(DNS_AS_STR(token), "W") != 0)
+ RETTOK(DNS_R_SYNTAX);
+
+ getalt:
+ /*
+ * Altitude.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ m = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0 && *e != '.' && *e != 'm')
+ RETTOK(DNS_R_SYNTAX);
+ if (m < -100000 || m > 42849672)
+ RETTOK(ISC_R_RANGE);
+ cm = 0;
+ if (*e == '.') {
+ e++;
+ for (i = 0; i < 2; i++) {
+ if (*e == 0 || *e == 'm')
+ break;
+ if ((tmp = decvalue(*e++)) < 0)
+ return (DNS_R_SYNTAX);
+ cm *= 10;
+ if (m < 0)
+ cm -= tmp;
+ else
+ cm += tmp;
+ }
+ for (; i < 2; i++)
+ cm *= 10;
+ }
+ if (*e == 'm')
+ e++;
+ if (*e != 0)
+ RETTOK(DNS_R_SYNTAX);
+ if (m == -100000 && cm != 0)
+ RETTOK(ISC_R_RANGE);
+ if (m == 42849672 && cm > 95)
+ RETTOK(ISC_R_RANGE);
+ /*
+ * Adjust base.
+ */
+ altitude = m + 100000;
+ altitude *= 100;
+ altitude += cm;
+
+ /*
+ * Size: optional.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_TRUE));
+ if (token.type == isc_tokentype_eol ||
+ token.type == isc_tokentype_eof) {
+ isc_lex_ungettoken(lexer, &token);
+ goto encode;
+ }
+ m = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0 && *e != '.' && *e != 'm')
+ RETTOK(DNS_R_SYNTAX);
+ if (m < 0 || m > 90000000)
+ RETTOK(ISC_R_RANGE);
+ cm = 0;
+ if (*e == '.') {
+ e++;
+ for (i = 0; i < 2; i++) {
+ if (*e == 0 || *e == 'm')
+ break;
+ if ((tmp = decvalue(*e++)) < 0)
+ RETTOK(DNS_R_SYNTAX);
+ cm *= 10;
+ cm += tmp;
+ }
+ for (; i < 2; i++)
+ cm *= 10;
+ }
+ if (*e == 'm')
+ e++;
+ if (*e != 0)
+ RETTOK(DNS_R_SYNTAX);
+ /*
+ * We don't just multiply out as we will overflow.
+ */
+ if (m > 0) {
+ for (exp = 0; exp < 7; exp++)
+ if (m < poweroften[exp+1])
+ break;
+ man = m / poweroften[exp];
+ exp += 2;
+ } else {
+ if (cm >= 10) {
+ man = cm / 10;
+ exp = 1;
+ } else {
+ man = cm;
+ exp = 0;
+ }
+ }
+ size = (man << 4) + exp;
+
+ /*
+ * Horizontal precision: optional.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_TRUE));
+ if (token.type == isc_tokentype_eol ||
+ token.type == isc_tokentype_eof) {
+ isc_lex_ungettoken(lexer, &token);
+ goto encode;
+ }
+ m = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0 && *e != '.' && *e != 'm')
+ RETTOK(DNS_R_SYNTAX);
+ if (m < 0 || m > 90000000)
+ RETTOK(ISC_R_RANGE);
+ cm = 0;
+ if (*e == '.') {
+ e++;
+ for (i = 0; i < 2; i++) {
+ if (*e == 0 || *e == 'm')
+ break;
+ if ((tmp = decvalue(*e++)) < 0)
+ RETTOK(DNS_R_SYNTAX);
+ cm *= 10;
+ cm += tmp;
+ }
+ for (; i < 2; i++)
+ cm *= 10;
+ }
+ if (*e == 'm')
+ e++;
+ if (*e != 0)
+ RETTOK(DNS_R_SYNTAX);
+ /*
+ * We don't just multiply out as we will overflow.
+ */
+ if (m > 0) {
+ for (exp = 0; exp < 7; exp++)
+ if (m < poweroften[exp+1])
+ break;
+ man = m / poweroften[exp];
+ exp += 2;
+ } else if (cm >= 10) {
+ man = cm / 10;
+ exp = 1;
+ } else {
+ man = cm;
+ exp = 0;
+ }
+ hp = (man << 4) + exp;
+
+ /*
+ * Vertical precision: optional.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_TRUE));
+ if (token.type == isc_tokentype_eol ||
+ token.type == isc_tokentype_eof) {
+ isc_lex_ungettoken(lexer, &token);
+ goto encode;
+ }
+ m = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0 && *e != '.' && *e != 'm')
+ RETTOK(DNS_R_SYNTAX);
+ if (m < 0 || m > 90000000)
+ RETTOK(ISC_R_RANGE);
+ cm = 0;
+ if (*e == '.') {
+ e++;
+ for (i = 0; i < 2; i++) {
+ if (*e == 0 || *e == 'm')
+ break;
+ if ((tmp = decvalue(*e++)) < 0)
+ RETTOK(DNS_R_SYNTAX);
+ cm *= 10;
+ cm += tmp;
+ }
+ for (; i < 2; i++)
+ cm *= 10;
+ }
+ if (*e == 'm')
+ e++;
+ if (*e != 0)
+ RETTOK(DNS_R_SYNTAX);
+ /*
+ * We don't just multiply out as we will overflow.
+ */
+ if (m > 0) {
+ for (exp = 0; exp < 7; exp++)
+ if (m < poweroften[exp+1])
+ break;
+ man = m / poweroften[exp];
+ exp += 2;
+ } else if (cm >= 10) {
+ man = cm / 10;
+ exp = 1;
+ } else {
+ man = cm;
+ exp = 0;
+ }
+ vp = (man << 4) + exp;
+
+ encode:
+ RETERR(mem_tobuffer(target, &version, 1));
+ RETERR(mem_tobuffer(target, &size, 1));
+ RETERR(mem_tobuffer(target, &hp, 1));
+ RETERR(mem_tobuffer(target, &vp, 1));
+ if (north)
+ latitude = 0x80000000 + ( d1 * 3600 + m1 * 60 ) * 1000 + s1;
+ else
+ latitude = 0x80000000 - ( d1 * 3600 + m1 * 60 ) * 1000 - s1;
+ RETERR(uint32_tobuffer(latitude, target));
+
+ if (east)
+ longitude = 0x80000000 + ( d2 * 3600 + m2 * 60 ) * 1000 + s2;
+ else
+ longitude = 0x80000000 - ( d2 * 3600 + m2 * 60 ) * 1000 - s2;
+ RETERR(uint32_tobuffer(longitude, target));
+
+ return (uint32_tobuffer(altitude, target));
+}
+
+static inline isc_result_t
+totext_loc(ARGS_TOTEXT) {
+ int d1, m1, s1, fs1;
+ int d2, m2, s2, fs2;
+ unsigned long latitude;
+ unsigned long longitude;
+ unsigned long altitude;
+ isc_boolean_t north;
+ isc_boolean_t east;
+ isc_boolean_t below;
+ isc_region_t sr;
+ char buf[sizeof("89 59 59.999 N 179 59 59.999 E "
+ "42849672.95m 90000000m 90000000m 90000000m")];
+ char sbuf[sizeof("90000000m")];
+ char hbuf[sizeof("90000000m")];
+ char vbuf[sizeof("90000000m")];
+ unsigned char size, hp, vp;
+ unsigned long poweroften[8] = { 1, 10, 100, 1000,
+ 10000, 100000, 1000000, 10000000 };
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == 29);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /* version = sr.base[0]; */
+ size = sr.base[1];
+ if ((size&0x0f)> 1)
+ sprintf(sbuf, "%lum", (size>>4) * poweroften[(size&0x0f)-2]);
+ else
+ sprintf(sbuf, "0.%02lum", (size>>4) * poweroften[(size&0x0f)]);
+ hp = sr.base[2];
+ if ((hp&0x0f)> 1)
+ sprintf(hbuf, "%lum", (hp>>4) * poweroften[(hp&0x0f)-2]);
+ else
+ sprintf(hbuf, "0.%02lum", (hp>>4) * poweroften[(hp&0x0f)]);
+ vp = sr.base[3];
+ if ((vp&0x0f)> 1)
+ sprintf(vbuf, "%lum", (vp>>4) * poweroften[(vp&0x0f)-2]);
+ else
+ sprintf(vbuf, "0.%02lum", (vp>>4) * poweroften[(vp&0x0f)]);
+ isc_region_consume(&sr, 4);
+
+ latitude = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ if (latitude >= 0x80000000) {
+ north = ISC_TRUE;
+ latitude -= 0x80000000;
+ } else {
+ north = ISC_FALSE;
+ latitude = 0x80000000 - latitude;
+ }
+ fs1 = (int)(latitude % 1000);
+ latitude /= 1000;
+ s1 = (int)(latitude % 60);
+ latitude /= 60;
+ m1 = (int)(latitude % 60);
+ latitude /= 60;
+ d1 = (int)latitude;
+
+ longitude = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ if (longitude >= 0x80000000) {
+ east = ISC_TRUE;
+ longitude -= 0x80000000;
+ } else {
+ east = ISC_FALSE;
+ longitude = 0x80000000 - longitude;
+ }
+ fs2 = (int)(longitude % 1000);
+ longitude /= 1000;
+ s2 = (int)(longitude % 60);
+ longitude /= 60;
+ m2 = (int)(longitude % 60);
+ longitude /= 60;
+ d2 = (int)longitude;
+
+ altitude = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ if (altitude < 10000000U) {
+ below = ISC_TRUE;
+ altitude = 10000000 - altitude;
+ } else {
+ below =ISC_FALSE;
+ altitude -= 10000000;
+ }
+
+ sprintf(buf, "%d %d %d.%03d %s %d %d %d.%03d %s %s%ld.%02ldm %s %s %s",
+ d1, m1, s1, fs1, north ? "N" : "S",
+ d2, m2, s2, fs2, east ? "E" : "W",
+ below ? "-" : "", altitude/100, altitude % 100,
+ sbuf, hbuf, vbuf);
+
+ return (str_totext(buf, target));
+}
+
+static inline isc_result_t
+fromwire_loc(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ unsigned char c;
+ unsigned long latitude;
+ unsigned long longitude;
+
+ REQUIRE(type == 29);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ if (sr.base[0] != 0)
+ return (ISC_R_NOTIMPLEMENTED);
+ if (sr.length < 16)
+ return (ISC_R_UNEXPECTEDEND);
+
+ /*
+ * Size.
+ */
+ c = sr.base[1];
+ if (c != 0)
+ if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
+ return (ISC_R_RANGE);
+
+ /*
+ * Horizontal precision.
+ */
+ c = sr.base[2];
+ if (c != 0)
+ if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
+ return (ISC_R_RANGE);
+
+ /*
+ * Vertical precision.
+ */
+ c = sr.base[3];
+ if (c != 0)
+ if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
+ return (ISC_R_RANGE);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Latitude.
+ */
+ latitude = uint32_fromregion(&sr);
+ if (latitude < (0x80000000UL - 90 * 3600000) ||
+ latitude > (0x80000000UL + 90 * 3600000))
+ return (ISC_R_RANGE);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Longitude.
+ */
+ longitude = uint32_fromregion(&sr);
+ if (longitude < (0x80000000UL - 180 * 3600000) ||
+ longitude > (0x80000000UL + 180 * 3600000))
+ return (ISC_R_RANGE);
+
+ /*
+ * Altitiude.
+ * All values possible.
+ */
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_forward(source, 16);
+ return (mem_tobuffer(target, sr.base, 16));
+}
+
+static inline isc_result_t
+towire_loc(ARGS_TOWIRE) {
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == 29);
+ REQUIRE(rdata->length != 0);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static inline int
+compare_loc(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 29);
+ 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_loc(ARGS_FROMSTRUCT) {
+ dns_rdata_loc_t *loc = source;
+ isc_uint8_t c;
+
+ REQUIRE(type == 29);
+ REQUIRE(source != NULL);
+ REQUIRE(loc->common.rdtype == type);
+ REQUIRE(loc->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ if (loc->v.v0.version != 0)
+ return (ISC_R_NOTIMPLEMENTED);
+ RETERR(uint8_tobuffer(loc->v.v0.version, target));
+
+ c = loc->v.v0.size;
+ if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
+ return (ISC_R_RANGE);
+ RETERR(uint8_tobuffer(loc->v.v0.size, target));
+
+ c = loc->v.v0.horizontal;
+ if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
+ return (ISC_R_RANGE);
+ RETERR(uint8_tobuffer(loc->v.v0.horizontal, target));
+
+ c = loc->v.v0.vertical;
+ if ((c&0xf) > 9 || ((c>>4)&0xf) > 9 || ((c>>4)&0xf) == 0)
+ return (ISC_R_RANGE);
+ RETERR(uint8_tobuffer(loc->v.v0.vertical, target));
+
+ if (loc->v.v0.latitude < (0x80000000UL - 90 * 3600000) ||
+ loc->v.v0.latitude > (0x80000000UL + 90 * 3600000))
+ return (ISC_R_RANGE);
+ RETERR(uint32_tobuffer(loc->v.v0.latitude, target));
+
+ if (loc->v.v0.longitude < (0x80000000UL - 180 * 3600000) ||
+ loc->v.v0.longitude > (0x80000000UL + 180 * 3600000))
+ return (ISC_R_RANGE);
+ RETERR(uint32_tobuffer(loc->v.v0.longitude, target));
+ return (uint32_tobuffer(loc->v.v0.altitude, target));
+}
+
+static inline isc_result_t
+tostruct_loc(ARGS_TOSTRUCT) {
+ dns_rdata_loc_t *loc = target;
+ isc_region_t r;
+ isc_uint8_t version;
+
+ REQUIRE(rdata->type == 29);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(mctx);
+
+ dns_rdata_toregion(rdata, &r);
+ version = uint8_fromregion(&r);
+ if (version != 0)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ loc->common.rdclass = rdata->rdclass;
+ loc->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&loc->common, link);
+
+ loc->v.v0.version = version;
+ isc_region_consume(&r, 1);
+ loc->v.v0.size = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ loc->v.v0.horizontal = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ loc->v.v0.vertical = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ loc->v.v0.latitude = uint32_fromregion(&r);
+ isc_region_consume(&r, 4);
+ loc->v.v0.longitude = uint32_fromregion(&r);
+ isc_region_consume(&r, 4);
+ loc->v.v0.altitude = uint32_fromregion(&r);
+ isc_region_consume(&r, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_loc(ARGS_FREESTRUCT) {
+ dns_rdata_loc_t *loc = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(loc->common.rdtype == 29);
+
+ UNUSED(source);
+ UNUSED(loc);
+}
+
+static inline isc_result_t
+additionaldata_loc(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 29);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_loc(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 29);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_loc(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 29);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_loc(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 29);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_LOC_29_C */
diff --git a/lib/dns/rdata/generic/loc_29.h b/lib/dns/rdata/generic/loc_29.h
new file mode 100644
index 0000000..f053c60
--- /dev/null
+++ b/lib/dns/rdata/generic/loc_29.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef GENERIC_LOC_29_H
+#define GENERIC_LOC_29_H 1
+
+/* $Id: loc_29.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC1876 */
+
+typedef struct dns_rdata_loc_0 {
+ isc_uint8_t version; /* must be first and zero */
+ isc_uint8_t size;
+ isc_uint8_t horizontal;
+ isc_uint8_t vertical;
+ isc_uint32_t latitude;
+ isc_uint32_t longitude;
+ isc_uint32_t altitude;
+} dns_rdata_loc_0_t;
+
+typedef struct dns_rdata_loc {
+ dns_rdatacommon_t common;
+ union {
+ dns_rdata_loc_0_t v0;
+ } v;
+} dns_rdata_loc_t;
+
+#endif /* GENERIC_LOC_29_H */
diff --git a/lib/dns/rdata/generic/mb_7.c b/lib/dns/rdata/generic/mb_7.c
new file mode 100644
index 0000000..fc3a7b6
--- /dev/null
+++ b/lib/dns/rdata/generic/mb_7.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: mb_7.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Wed Mar 15 17:31:26 PST 2000 by bwelling */
+
+#ifndef RDATA_GENERIC_MB_7_C
+#define RDATA_GENERIC_MB_7_C
+
+#define RRTYPE_MB_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_mb(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 7);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_mb(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 7);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_mb(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == 7);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_mb(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 7);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_mb(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 7);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_mb(ARGS_FROMSTRUCT) {
+ dns_rdata_mb_t *mb = source;
+ isc_region_t region;
+
+ REQUIRE(type == 7);
+ REQUIRE(source != NULL);
+ REQUIRE(mb->common.rdtype == type);
+ REQUIRE(mb->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&mb->mb, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_mb(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_mb_t *mb = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 7);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ mb->common.rdclass = rdata->rdclass;
+ mb->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&mb->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&mb->mb, NULL);
+ RETERR(name_duporclone(&name, mctx, &mb->mb));
+ mb->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_mb(ARGS_FREESTRUCT) {
+ dns_rdata_mb_t *mb = source;
+
+ REQUIRE(source != NULL);
+
+ if (mb->mctx == NULL)
+ return;
+
+ dns_name_free(&mb->mb, mb->mctx);
+ mb->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_mb(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 7);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a));
+}
+
+static inline isc_result_t
+digest_mb(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 7);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_mb(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 7);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (dns_name_ismailbox(name));
+}
+
+static inline isc_boolean_t
+checknames_mb(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 7);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_MB_7_C */
diff --git a/lib/dns/rdata/generic/mb_7.h b/lib/dns/rdata/generic/mb_7.h
new file mode 100644
index 0000000..b427ee9
--- /dev/null
+++ b/lib/dns/rdata/generic/mb_7.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_MB_7_H
+#define GENERIC_MB_7_H 1
+
+/* $Id: mb_7.h,v 1.27 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_mb {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t mb;
+} dns_rdata_mb_t;
+
+#endif /* GENERIC_MB_7_H */
diff --git a/lib/dns/rdata/generic/md_3.c b/lib/dns/rdata/generic/md_3.c
new file mode 100644
index 0000000..0f8560f
--- /dev/null
+++ b/lib/dns/rdata/generic/md_3.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: md_3.c,v 1.47 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Wed Mar 15 17:48:20 PST 2000 by bwelling */
+
+#ifndef RDATA_GENERIC_MD_3_C
+#define RDATA_GENERIC_MD_3_C
+
+#define RRTYPE_MD_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_md(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 3);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_md(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 3);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_md(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == 3);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_md(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 3);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_md(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 3);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_md(ARGS_FROMSTRUCT) {
+ dns_rdata_md_t *md = source;
+ isc_region_t region;
+
+ REQUIRE(type == 3);
+ REQUIRE(source != NULL);
+ REQUIRE(md->common.rdtype == type);
+ REQUIRE(md->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&md->md, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_md(ARGS_TOSTRUCT) {
+ dns_rdata_md_t *md = target;
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 3);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ md->common.rdclass = rdata->rdclass;
+ md->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&md->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &r);
+ dns_name_fromregion(&name, &r);
+ dns_name_init(&md->md, NULL);
+ RETERR(name_duporclone(&name, mctx, &md->md));
+ md->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_md(ARGS_FREESTRUCT) {
+ dns_rdata_md_t *md = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(md->common.rdtype == 3);
+
+ if (md->mctx == NULL)
+ return;
+
+ dns_name_free(&md->md, md->mctx);
+ md->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_md(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 3);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a));
+}
+
+static inline isc_result_t
+digest_md(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 3);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_md(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 3);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_md(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 3);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_MD_3_C */
diff --git a/lib/dns/rdata/generic/md_3.h b/lib/dns/rdata/generic/md_3.h
new file mode 100644
index 0000000..ba70d18
--- /dev/null
+++ b/lib/dns/rdata/generic/md_3.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_MD_3_H
+#define GENERIC_MD_3_H 1
+
+/* $Id: md_3.h,v 1.28 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_md {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t md;
+} dns_rdata_md_t;
+
+
+#endif /* GENERIC_MD_3_H */
diff --git a/lib/dns/rdata/generic/mf_4.c b/lib/dns/rdata/generic/mf_4.c
new file mode 100644
index 0000000..dffcec2
--- /dev/null
+++ b/lib/dns/rdata/generic/mf_4.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: mf_4.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
+
+/* reviewed: Wed Mar 15 17:47:33 PST 2000 by brister */
+
+#ifndef RDATA_GENERIC_MF_4_C
+#define RDATA_GENERIC_MF_4_C
+
+#define RRTYPE_MF_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_mf(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 4);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_mf(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 4);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_mf(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == 4);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_mf(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 4);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_mf(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 4);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_mf(ARGS_FROMSTRUCT) {
+ dns_rdata_mf_t *mf = source;
+ isc_region_t region;
+
+ REQUIRE(type == 4);
+ REQUIRE(source != NULL);
+ REQUIRE(mf->common.rdtype == type);
+ REQUIRE(mf->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&mf->mf, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_mf(ARGS_TOSTRUCT) {
+ dns_rdata_mf_t *mf = target;
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 4);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ mf->common.rdclass = rdata->rdclass;
+ mf->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&mf->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &r);
+ dns_name_fromregion(&name, &r);
+ dns_name_init(&mf->mf, NULL);
+ RETERR(name_duporclone(&name, mctx, &mf->mf));
+ mf->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_mf(ARGS_FREESTRUCT) {
+ dns_rdata_mf_t *mf = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(mf->common.rdtype == 4);
+
+ if (mf->mctx == NULL)
+ return;
+ dns_name_free(&mf->mf, mf->mctx);
+ mf->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_mf(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 4);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a));
+}
+
+static inline isc_result_t
+digest_mf(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 4);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_mf(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 4);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_mf(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 4);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_MF_4_C */
diff --git a/lib/dns/rdata/generic/mf_4.h b/lib/dns/rdata/generic/mf_4.h
new file mode 100644
index 0000000..32d2493
--- /dev/null
+++ b/lib/dns/rdata/generic/mf_4.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_MF_4_H
+#define GENERIC_MF_4_H 1
+
+/* $Id: mf_4.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_mf {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t mf;
+} dns_rdata_mf_t;
+
+#endif /* GENERIC_MF_4_H */
diff --git a/lib/dns/rdata/generic/mg_8.c b/lib/dns/rdata/generic/mg_8.c
new file mode 100644
index 0000000..e4dca1d
--- /dev/null
+++ b/lib/dns/rdata/generic/mg_8.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: mg_8.c,v 1.43 2007/06/19 23:47:17 tbox Exp $ */
+
+/* reviewed: Wed Mar 15 17:49:21 PST 2000 by brister */
+
+#ifndef RDATA_GENERIC_MG_8_C
+#define RDATA_GENERIC_MG_8_C
+
+#define RRTYPE_MG_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_mg(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 8);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_mg(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 8);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_mg(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == 8);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_mg(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 8);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_mg(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 8);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_mg(ARGS_FROMSTRUCT) {
+ dns_rdata_mg_t *mg = source;
+ isc_region_t region;
+
+ REQUIRE(type == 8);
+ REQUIRE(source != NULL);
+ REQUIRE(mg->common.rdtype == type);
+ REQUIRE(mg->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&mg->mg, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_mg(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_mg_t *mg = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 8);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ mg->common.rdclass = rdata->rdclass;
+ mg->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&mg->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&mg->mg, NULL);
+ RETERR(name_duporclone(&name, mctx, &mg->mg));
+ mg->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_mg(ARGS_FREESTRUCT) {
+ dns_rdata_mg_t *mg = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(mg->common.rdtype == 8);
+
+ if (mg->mctx == NULL)
+ return;
+ dns_name_free(&mg->mg, mg->mctx);
+ mg->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_mg(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 8);
+
+ UNUSED(add);
+ UNUSED(arg);
+ UNUSED(rdata);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_mg(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 8);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_mg(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 8);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (dns_name_ismailbox(name));
+}
+
+static inline isc_boolean_t
+checknames_mg(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 8);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_MG_8_C */
diff --git a/lib/dns/rdata/generic/mg_8.h b/lib/dns/rdata/generic/mg_8.h
new file mode 100644
index 0000000..8fa143a
--- /dev/null
+++ b/lib/dns/rdata/generic/mg_8.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_MG_8_H
+#define GENERIC_MG_8_H 1
+
+/* $Id: mg_8.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_mg {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t mg;
+} dns_rdata_mg_t;
+
+#endif /* GENERIC_MG_8_H */
diff --git a/lib/dns/rdata/generic/minfo_14.c b/lib/dns/rdata/generic/minfo_14.c
new file mode 100644
index 0000000..6645bbc
--- /dev/null
+++ b/lib/dns/rdata/generic/minfo_14.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: minfo_14.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
+
+/* reviewed: Wed Mar 15 17:45:32 PST 2000 by brister */
+
+#ifndef RDATA_GENERIC_MINFO_14_C
+#define RDATA_GENERIC_MINFO_14_C
+
+#define RRTYPE_MINFO_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_minfo(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ int i;
+ isc_boolean_t ok;
+
+ REQUIRE(type == 14);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ for (i = 0; i < 2; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin,
+ options, target));
+ ok = ISC_TRUE;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0)
+ ok = dns_name_ismailbox(&name);
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_minfo(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t rmail;
+ dns_name_t email;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 14);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&rmail, NULL);
+ dns_name_init(&email, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, rmail.length);
+
+ dns_name_fromregion(&email, &region);
+ isc_region_consume(&region, email.length);
+
+ sub = name_prefix(&rmail, tctx->origin, &prefix);
+
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ RETERR(str_totext(" ", target));
+
+ sub = name_prefix(&email, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_minfo(ARGS_FROMWIRE) {
+ dns_name_t rmail;
+ dns_name_t email;
+
+ REQUIRE(type == 14);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ 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));
+}
+
+static inline isc_result_t
+towire_minfo(ARGS_TOWIRE) {
+ isc_region_t region;
+ dns_name_t rmail;
+ dns_name_t email;
+ dns_offsets_t roffsets;
+ dns_offsets_t eoffsets;
+
+ REQUIRE(rdata->type == 14);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&rmail, roffsets);
+ dns_name_init(&email, eoffsets);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, name_length(&rmail));
+
+ RETERR(dns_name_towire(&rmail, cctx, target));
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, rmail.length);
+
+ return (dns_name_towire(&rmail, cctx, target));
+}
+
+static inline int
+compare_minfo(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 == 14);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ return (order);
+}
+
+static inline isc_result_t
+fromstruct_minfo(ARGS_FROMSTRUCT) {
+ dns_rdata_minfo_t *minfo = source;
+ isc_region_t region;
+
+ REQUIRE(type == 14);
+ REQUIRE(source != NULL);
+ REQUIRE(minfo->common.rdtype == type);
+ REQUIRE(minfo->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&minfo->rmailbox, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ dns_name_toregion(&minfo->emailbox, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_minfo(ARGS_TOSTRUCT) {
+ dns_rdata_minfo_t *minfo = target;
+ isc_region_t region;
+ dns_name_t name;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == 14);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ minfo->common.rdclass = rdata->rdclass;
+ minfo->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&minfo->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&minfo->rmailbox, NULL);
+ RETERR(name_duporclone(&name, mctx, &minfo->rmailbox));
+ isc_region_consume(&region, name_length(&name));
+
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&minfo->emailbox, NULL);
+ result = name_duporclone(&name, mctx, &minfo->emailbox);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ minfo->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL)
+ dns_name_free(&minfo->rmailbox, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_minfo(ARGS_FREESTRUCT) {
+ dns_rdata_minfo_t *minfo = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(minfo->common.rdtype == 14);
+
+ if (minfo->mctx == NULL)
+ return;
+
+ dns_name_free(&minfo->rmailbox, minfo->mctx);
+ dns_name_free(&minfo->emailbox, minfo->mctx);
+ minfo->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_minfo(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 14);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_minfo(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == 14);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ result = dns_name_digest(&name, digest, arg);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_region_consume(&r, name_length(&name));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_minfo(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 14);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_minfo(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 14);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ismailbox(&name)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ isc_region_consume(&region, name_length(&name));
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ismailbox(&name)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_MINFO_14_C */
diff --git a/lib/dns/rdata/generic/minfo_14.h b/lib/dns/rdata/generic/minfo_14.h
new file mode 100644
index 0000000..76195c5
--- /dev/null
+++ b/lib/dns/rdata/generic/minfo_14.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_MINFO_14_H
+#define GENERIC_MINFO_14_H 1
+
+/* $Id: minfo_14.h,v 1.27 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_minfo {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t rmailbox;
+ dns_name_t emailbox;
+} dns_rdata_minfo_t;
+
+#endif /* GENERIC_MINFO_14_H */
diff --git a/lib/dns/rdata/generic/mr_9.c b/lib/dns/rdata/generic/mr_9.c
new file mode 100644
index 0000000..289d739
--- /dev/null
+++ b/lib/dns/rdata/generic/mr_9.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: mr_9.c,v 1.42 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Wed Mar 15 21:30:35 EST 2000 by tale */
+
+#ifndef RDATA_GENERIC_MR_9_C
+#define RDATA_GENERIC_MR_9_C
+
+#define RRTYPE_MR_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_mr(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 9);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_mr(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 9);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_mr(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == 9);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_mr(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 9);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_mr(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 9);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_mr(ARGS_FROMSTRUCT) {
+ dns_rdata_mr_t *mr = source;
+ isc_region_t region;
+
+ REQUIRE(type == 9);
+ REQUIRE(source != NULL);
+ REQUIRE(mr->common.rdtype == type);
+ REQUIRE(mr->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&mr->mr, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_mr(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_mr_t *mr = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 9);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ mr->common.rdclass = rdata->rdclass;
+ mr->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&mr->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&mr->mr, NULL);
+ RETERR(name_duporclone(&name, mctx, &mr->mr));
+ mr->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_mr(ARGS_FREESTRUCT) {
+ dns_rdata_mr_t *mr = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(mr->common.rdtype == 9);
+
+ if (mr->mctx == NULL)
+ return;
+ dns_name_free(&mr->mr, mr->mctx);
+ mr->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_mr(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 9);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_mr(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 9);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_mr(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 9);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_mr(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 9);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_MR_9_C */
diff --git a/lib/dns/rdata/generic/mr_9.h b/lib/dns/rdata/generic/mr_9.h
new file mode 100644
index 0000000..3d81bdd
--- /dev/null
+++ b/lib/dns/rdata/generic/mr_9.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_MR_9_H
+#define GENERIC_MR_9_H 1
+
+/* $Id: mr_9.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_mr {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t mr;
+} dns_rdata_mr_t;
+
+#endif /* GENERIC_MR_9_H */
diff --git a/lib/dns/rdata/generic/mx_15.c b/lib/dns/rdata/generic/mx_15.c
new file mode 100644
index 0000000..086c043
--- /dev/null
+++ b/lib/dns/rdata/generic/mx_15.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: mx_15.c,v 1.56 2007/06/19 23:47:17 tbox Exp $ */
+
+/* reviewed: Wed Mar 15 18:05:46 PST 2000 by brister */
+
+#ifndef RDATA_GENERIC_MX_15_C
+#define RDATA_GENERIC_MX_15_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#define RRTYPE_MX_ATTRIBUTES (0)
+
+static isc_boolean_t
+check_mx(isc_token_t *token) {
+ char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123.")];
+ struct in_addr addr;
+ struct in6_addr addr6;
+
+ if (strlcpy(tmp, DNS_AS_STR(*token), sizeof(tmp)) >= sizeof(tmp))
+ return (ISC_TRUE);
+
+ if (tmp[strlen(tmp) - 1] == '.')
+ tmp[strlen(tmp) - 1] = '\0';
+ if (inet_aton(tmp, &addr) == 1 ||
+ inet_pton(AF_INET6, tmp, &addr6) == 1)
+ return (ISC_FALSE);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_result_t
+fromtext_mx(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ isc_boolean_t ok;
+
+ REQUIRE(type == 15);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ ok = ISC_TRUE;
+ if ((options & DNS_RDATA_CHECKMX) != 0)
+ ok = check_mx(&token);
+ if (!ok && (options & DNS_RDATA_CHECKMXFAIL) != 0)
+ RETTOK(DNS_R_MXISADDRESS);
+ if (!ok && callbacks != NULL)
+ warn_badmx(&token, lexer, callbacks);
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ ok = ISC_TRUE;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0)
+ ok = dns_name_ishostname(&name, ISC_FALSE);
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_mx(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ char buf[sizeof("64000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == 15);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ sprintf(buf, "%u", num);
+ RETERR(str_totext(buf, target));
+
+ RETERR(str_totext(" ", target));
+
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_mx(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sregion;
+
+ REQUIRE(type == 15);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ RETERR(mem_tobuffer(target, sregion.base, 2));
+ isc_buffer_forward(source, 2);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_mx(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 15);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_rdata_toregion(rdata, &region);
+ RETERR(mem_tobuffer(target, region.base, 2));
+ isc_region_consume(&region, 2);
+
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_mx(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 15);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ order = memcmp(rdata1->data, rdata2->data, 2);
+ if (order != 0)
+ return (order < 0 ? -1 : 1);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 2);
+ isc_region_consume(&region2, 2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_mx(ARGS_FROMSTRUCT) {
+ dns_rdata_mx_t *mx = source;
+ isc_region_t region;
+
+ REQUIRE(type == 15);
+ REQUIRE(source != NULL);
+ REQUIRE(mx->common.rdtype == type);
+ REQUIRE(mx->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(mx->pref, target));
+ dns_name_toregion(&mx->mx, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_mx(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_mx_t *mx = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 15);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ mx->common.rdclass = rdata->rdclass;
+ mx->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&mx->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ mx->pref = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&mx->mx, NULL);
+ RETERR(name_duporclone(&name, mctx, &mx->mx));
+ mx->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_mx(ARGS_FREESTRUCT) {
+ dns_rdata_mx_t *mx = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(mx->common.rdtype == 15);
+
+ if (mx->mctx == NULL)
+ return;
+
+ dns_name_free(&mx->mx, mx->mctx);
+ mx->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_mx(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 15);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a));
+}
+
+static inline isc_result_t
+digest_mx(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 15);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ isc_region_consume(&r2, 2);
+ r1.length = 2;
+ RETERR((digest)(arg, &r1));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_mx(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 15);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static inline isc_boolean_t
+checknames_mx(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 15);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, ISC_FALSE)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_MX_15_C */
diff --git a/lib/dns/rdata/generic/mx_15.h b/lib/dns/rdata/generic/mx_15.h
new file mode 100644
index 0000000..25d5ac5
--- /dev/null
+++ b/lib/dns/rdata/generic/mx_15.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_MX_15_H
+#define GENERIC_MX_15_H 1
+
+/* $Id: mx_15.h,v 1.29 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_mx {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t pref;
+ dns_name_t mx;
+} dns_rdata_mx_t;
+
+#endif /* GENERIC_MX_15_H */
diff --git a/lib/dns/rdata/generic/ns_2.c b/lib/dns/rdata/generic/ns_2.c
new file mode 100644
index 0000000..9a2ee8c
--- /dev/null
+++ b/lib/dns/rdata/generic/ns_2.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: ns_2.c,v 1.46 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Wed Mar 15 18:15:00 PST 2000 by bwelling */
+
+#ifndef RDATA_GENERIC_NS_2_C
+#define RDATA_GENERIC_NS_2_C
+
+#define RRTYPE_NS_ATTRIBUTES (DNS_RDATATYPEATTR_ZONECUTAUTH)
+
+static inline isc_result_t
+fromtext_ns(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ isc_boolean_t ok;
+
+ REQUIRE(type == 2);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token,isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ ok = ISC_TRUE;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0)
+ ok = dns_name_ishostname(&name, ISC_FALSE);
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_ns(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 2);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_ns(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == 2);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_ns(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 2);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_ns(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 2);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_ns(ARGS_FROMSTRUCT) {
+ dns_rdata_ns_t *ns = source;
+ isc_region_t region;
+
+ REQUIRE(type == 2);
+ REQUIRE(source != NULL);
+ REQUIRE(ns->common.rdtype == type);
+ REQUIRE(ns->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&ns->name, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_ns(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_ns_t *ns = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 2);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ ns->common.rdclass = rdata->rdclass;
+ ns->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ns->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&ns->name, NULL);
+ RETERR(name_duporclone(&name, mctx, &ns->name));
+ ns->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_ns(ARGS_FREESTRUCT) {
+ dns_rdata_ns_t *ns = source;
+
+ REQUIRE(source != NULL);
+
+ if (ns->mctx == NULL)
+ return;
+
+ dns_name_free(&ns->name, ns->mctx);
+ ns->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_ns(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 2);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a));
+}
+
+static inline isc_result_t
+digest_ns(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 2);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_ns(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 2);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_ns(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 2);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, ISC_FALSE)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_NS_2_C */
diff --git a/lib/dns/rdata/generic/ns_2.h b/lib/dns/rdata/generic/ns_2.h
new file mode 100644
index 0000000..546e71a
--- /dev/null
+++ b/lib/dns/rdata/generic/ns_2.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_NS_2_H
+#define GENERIC_NS_2_H 1
+
+/* $Id: ns_2.h,v 1.27 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_ns {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t name;
+} dns_rdata_ns_t;
+
+
+#endif /* GENERIC_NS_2_H */
diff --git a/lib/dns/rdata/generic/nsec3_50.c b/lib/dns/rdata/generic/nsec3_50.c
new file mode 100644
index 0000000..3d79451
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3_50.c
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2008 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: nsec3_50.c,v 1.4 2008/09/25 04:02:39 tbox Exp $ */
+
+/*
+ * Copyright (C) 2004 Nominet, Ltd.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET 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.
+ */
+
+/* RFC 5155 */
+
+#ifndef RDATA_GENERIC_NSEC3_50_C
+#define RDATA_GENERIC_NSEC3_50_C
+
+#include <isc/iterated_hash.h>
+#include <isc/base32.h>
+
+#define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
+
+static inline isc_result_t
+fromtext_nsec3(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char bm[8*1024]; /* 64k bits */
+ dns_rdatatype_t covered;
+ int octet;
+ int window;
+ unsigned int flags;
+ unsigned char hashalg;
+ isc_buffer_t b;
+
+ REQUIRE(type == 50);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+ UNUSED(origin);
+ UNUSED(options);
+
+ /* Hash. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
+ RETERR(uint8_tobuffer(hashalg, target));
+
+ /* Flags. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ flags = token.value.as_ulong;
+ if (flags > 255U)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(flags, target));
+
+ /* Iterations. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /* salt */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (token.value.as_textregion.length > (255*2))
+ RETTOK(DNS_R_TEXTTOOLONG);
+ if (strcmp(DNS_AS_STR(token), "-") == 0) {
+ RETERR(uint8_tobuffer(0, target));
+ } else {
+ RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
+ RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
+ }
+
+ /*
+ * Next hash a single base32hex word.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ isc_buffer_init(&b, bm, sizeof(bm));
+ RETTOK(isc_base32hex_decodestring(DNS_AS_STR(token), &b));
+ if (isc_buffer_usedlength(&b) > 0xffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
+ RETERR(mem_tobuffer(target, &bm, isc_buffer_usedlength(&b)));
+
+ memset(bm, 0, sizeof(bm));
+ do {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, ISC_TRUE));
+ if (token.type != isc_tokentype_string)
+ break;
+ RETTOK(dns_rdatatype_fromtext(&covered,
+ &token.value.as_textregion));
+ bm[covered/8] |= (0x80>>(covered%8));
+ } while (1);
+ isc_lex_ungettoken(lexer, &token);
+ for (window = 0; window < 256 ; window++) {
+ /*
+ * Find if we have a type in this window.
+ */
+ for (octet = 31; octet >= 0; octet--)
+ if (bm[window * 32 + octet] != 0)
+ break;
+ if (octet < 0)
+ continue;
+ RETERR(uint8_tobuffer(window, target));
+ RETERR(uint8_tobuffer(octet + 1, target));
+ RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_nsec3(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned int i, j, k;
+ unsigned int window, len;
+ unsigned char hash;
+ unsigned char flags;
+ char buf[sizeof("65535 ")];
+ isc_uint32_t iterations;
+
+ REQUIRE(rdata->type == 50);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ hash = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ flags = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ iterations = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ sprintf(buf, "%u ", hash);
+ RETERR(str_totext(buf, target));
+
+ sprintf(buf, "%u ", flags);
+ RETERR(str_totext(buf, target));
+
+ sprintf(buf, "%u ", iterations);
+ RETERR(str_totext(buf, target));
+
+ j = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ INSIST(j <= sr.length);
+
+ if (j != 0) {
+ i = sr.length;
+ sr.length = j;
+ RETERR(isc_hex_totext(&sr, 1, "", target));
+ sr.length = i - j;
+ RETERR(str_totext(" ", target));
+ } else
+ RETERR(str_totext("- ", target));
+
+ j = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ INSIST(j <= sr.length);
+
+ i = sr.length;
+ sr.length = j;
+ RETERR(isc_base32hex_totext(&sr, 1, "", target));
+ sr.length = i - j;
+
+ for (i = 0; i < sr.length; i += len) {
+ INSIST(i + 2 <= sr.length);
+ window = sr.base[i];
+ len = sr.base[i + 1];
+ INSIST(len > 0 && len <= 32);
+ i += 2;
+ INSIST(i + len <= sr.length);
+ for (j = 0; j < len; j++) {
+ dns_rdatatype_t t;
+ if (sr.base[i + j] == 0)
+ continue;
+ for (k = 0; k < 8; k++) {
+ if ((sr.base[i + j] & (0x80 >> k)) == 0)
+ continue;
+ t = window * 256 + j * 8 + k;
+ RETERR(str_totext(" ", target));
+ if (dns_rdatatype_isknown(t)) {
+ RETERR(dns_rdatatype_totext(t, target));
+ } else {
+ char buf[sizeof("TYPE65535")];
+ sprintf(buf, "TYPE%u", t);
+ RETERR(str_totext(buf, target));
+ }
+ }
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_nsec3(ARGS_FROMWIRE) {
+ isc_region_t sr, rr;
+ unsigned int window, lastwindow = 0;
+ unsigned int len;
+ unsigned int saltlen, hashlen;
+ isc_boolean_t first = ISC_TRUE;
+ unsigned int i;
+
+ REQUIRE(type == 50);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(options);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sr);
+ rr = sr;
+
+ /* hash(1), flags(1), interation(2), saltlen(1) */
+ if (sr.length < 5U)
+ RETERR(DNS_R_FORMERR);
+ saltlen = sr.base[4];
+ isc_region_consume(&sr, 5);
+
+ if (sr.length < saltlen)
+ RETERR(DNS_R_FORMERR);
+ isc_region_consume(&sr, saltlen);
+
+ if (sr.length < 1U)
+ RETERR(DNS_R_FORMERR);
+ hashlen = sr.base[0];
+ isc_region_consume(&sr, 1);
+
+ if (sr.length < hashlen)
+ RETERR(DNS_R_FORMERR);
+ isc_region_consume(&sr, hashlen);
+
+ for (i = 0; i < sr.length; i += len) {
+ /*
+ * Check for overflow.
+ */
+ if (i + 2 > sr.length)
+ RETERR(DNS_R_FORMERR);
+ window = sr.base[i];
+ len = sr.base[i + 1];
+ i += 2;
+ /*
+ * Check that bitmap windows are in the correct order.
+ */
+ if (!first && window <= lastwindow)
+ RETERR(DNS_R_FORMERR);
+ /*
+ * Check for legal lengths.
+ */
+ if (len < 1 || len > 32)
+ RETERR(DNS_R_FORMERR);
+ /*
+ * Check for overflow.
+ */
+ if (i + len > sr.length)
+ RETERR(DNS_R_FORMERR);
+ /*
+ * The last octet of the bitmap must be non zero.
+ */
+ if (sr.base[i + len - 1] == 0)
+ RETERR(DNS_R_FORMERR);
+ lastwindow = window;
+ first = ISC_FALSE;
+ }
+ if (i != sr.length)
+ return (DNS_R_EXTRADATA);
+ RETERR(mem_tobuffer(target, rr.base, rr.length));
+ isc_buffer_forward(source, rr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_nsec3(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 50);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_nsec3(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 50);
+ 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_nsec3(ARGS_FROMSTRUCT) {
+ dns_rdata_nsec3_t *nsec3 = source;
+ unsigned int i, len, window, lastwindow = 0;
+ isc_boolean_t first = ISC_TRUE;
+
+ REQUIRE(type == 50);
+ REQUIRE(source != NULL);
+ REQUIRE(nsec3->common.rdtype == type);
+ REQUIRE(nsec3->common.rdclass == rdclass);
+ REQUIRE(nsec3->typebits != NULL || nsec3->len == 0);
+ REQUIRE(nsec3->hash == dns_hash_sha1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(nsec3->hash, target));
+ RETERR(uint8_tobuffer(nsec3->flags, target));
+ RETERR(uint16_tobuffer(nsec3->iterations, target));
+ RETERR(uint8_tobuffer(nsec3->salt_length, target));
+ RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length));
+ RETERR(uint8_tobuffer(nsec3->next_length, target));
+ RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length));
+
+ /*
+ * Perform sanity check.
+ */
+ for (i = 0; i < nsec3->len ; i += len) {
+ INSIST(i + 2 <= nsec3->len);
+ window = nsec3->typebits[i];
+ len = nsec3->typebits[i+1];
+ i += 2;
+ INSIST(first || window > lastwindow);
+ INSIST(len > 0 && len <= 32);
+ INSIST(i + len <= nsec3->len);
+ INSIST(nsec3->typebits[i + len - 1] != 0);
+ lastwindow = window;
+ first = ISC_FALSE;
+ }
+ return (mem_tobuffer(target, nsec3->typebits, nsec3->len));
+}
+
+static inline isc_result_t
+tostruct_nsec3(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nsec3_t *nsec3 = target;
+
+ REQUIRE(rdata->type == 50);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsec3->common.rdclass = rdata->rdclass;
+ nsec3->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsec3->common, link);
+
+ region.base = rdata->data;
+ region.length = rdata->length;
+ nsec3->hash = uint8_consume_fromregion(&region);
+ nsec3->flags = uint8_consume_fromregion(&region);
+ nsec3->iterations = uint16_consume_fromregion(&region);
+
+ nsec3->salt_length = uint8_consume_fromregion(&region);
+ nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
+ if (nsec3->salt == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_region_consume(&region, nsec3->salt_length);
+
+ nsec3->next_length = uint8_consume_fromregion(&region);
+ nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
+ if (nsec3->next == NULL)
+ goto cleanup;
+ isc_region_consume(&region, nsec3->next_length);
+
+ nsec3->len = region.length;
+ nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
+ if (nsec3->typebits == NULL)
+ goto cleanup;
+
+ nsec3->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (nsec3->next != NULL)
+ isc_mem_free(mctx, nsec3->next);
+ isc_mem_free(mctx, nsec3->salt);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_nsec3(ARGS_FREESTRUCT) {
+ dns_rdata_nsec3_t *nsec3 = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(nsec3->common.rdtype == 50);
+
+ if (nsec3->mctx == NULL)
+ return;
+
+ if (nsec3->salt != NULL)
+ isc_mem_free(nsec3->mctx, nsec3->salt);
+ if (nsec3->next != NULL)
+ isc_mem_free(nsec3->mctx, nsec3->next);
+ if (nsec3->typebits != NULL)
+ isc_mem_free(nsec3->mctx, nsec3->typebits);
+ nsec3->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_nsec3(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 50);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_nsec3(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 50);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_nsec3(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 50);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_nsec3(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 50);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_NSEC3_50_C */
diff --git a/lib/dns/rdata/generic/nsec3_50.h b/lib/dns/rdata/generic/nsec3_50.h
new file mode 100644
index 0000000..658dd9d
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3_50.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008 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_NSEC3_50_H
+#define GENERIC_NSEC3_50_H 1
+
+/* $Id: nsec3_50.h,v 1.4 2008/09/25 04:02:39 tbox Exp $ */
+
+/*!
+ * \brief Per RFC 5155 */
+
+#include <isc/iterated_hash.h>
+
+typedef struct dns_rdata_nsec3 {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_hash_t hash;
+ unsigned char flags;
+ dns_iterations_t iterations;
+ unsigned char salt_length;
+ unsigned char next_length;
+ isc_uint16_t len;
+ unsigned char *salt;
+ unsigned char *next;
+ unsigned char *typebits;
+} dns_rdata_nsec3_t;
+
+/*
+ * The corresponding NSEC3 interval is OPTOUT indicating possible
+ * insecure delegations.
+ */
+#define DNS_NSEC3FLAG_OPTOUT 0x01U
+
+/*%
+ * Non-standard, NSEC3PARAM only.
+ *
+ * Create a corresponding NSEC3 chain.
+ * Once the NSEC3 chain is complete this flag will be removed to signal
+ * that there is a complete chain.
+ *
+ * This flag is automatically set when a NSEC3PARAM record is added to
+ * the zone via UPDATE.
+ *
+ * NSEC3PARAM records with this flag set are supposed to be ignored by
+ * RFC 5155 compliant nameservers.
+ */
+#define DNS_NSEC3FLAG_CREATE 0x80U
+
+/*%
+ * Non-standard, NSEC3PARAM only.
+ *
+ * The corresponding NSEC3 set is to be removed once the NSEC chain
+ * has been generated.
+ *
+ * This flag is automatically set when the last active NSEC3PARAM record
+ * is removed from the zone via UPDATE.
+ *
+ * NSEC3PARAM records with this flag set are supposed to be ignored by
+ * RFC 5155 compliant nameservers.
+ */
+#define DNS_NSEC3FLAG_REMOVE 0x40U
+
+/*%
+ * Non-standard, NSEC3PARAM only.
+ *
+ * Used to identify NSEC3PARAM records added in this UPDATE request.
+ */
+#define DNS_NSEC3FLAG_UPDATE 0x20U
+
+/*%
+ * Non-standard, NSEC3PARAM only.
+ *
+ * Prevent the creation of a NSEC chain before the last NSEC3 chain
+ * is removed. This will normally only be set when the zone is
+ * transitioning from secure with NSEC3 chains to insecure.
+ */
+#define DNS_NSEC3FLAG_NONSEC 0x10U
+
+#endif /* GENERIC_NSEC3_50_H */
diff --git a/lib/dns/rdata/generic/nsec3param_51.c b/lib/dns/rdata/generic/nsec3param_51.c
new file mode 100644
index 0000000..90de724
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3param_51.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2008 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: nsec3param_51.c,v 1.4 2008/09/25 04:02:39 tbox Exp $ */
+
+/*
+ * Copyright (C) 2004 Nominet, Ltd.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET 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.
+ */
+
+/* RFC 5155 */
+
+#ifndef RDATA_GENERIC_NSEC3PARAM_51_C
+#define RDATA_GENERIC_NSEC3PARAM_51_C
+
+#include <isc/iterated_hash.h>
+#include <isc/base32.h>
+
+#define RRTYPE_NSEC3PARAM_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static inline isc_result_t
+fromtext_nsec3param(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned int flags = 0;
+ unsigned char hashalg;
+
+ REQUIRE(type == 51);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+ UNUSED(origin);
+ UNUSED(options);
+
+ /* Hash. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
+ RETERR(uint8_tobuffer(hashalg, target));
+
+ /* Flags. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ flags = token.value.as_ulong;
+ if (flags > 255U)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint8_tobuffer(flags, target));
+
+ /* Iterations. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /* Salt. */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (token.value.as_textregion.length > (255*2))
+ RETTOK(DNS_R_TEXTTOOLONG);
+ if (strcmp(DNS_AS_STR(token), "-") == 0) {
+ RETERR(uint8_tobuffer(0, target));
+ } else {
+ RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
+ RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_nsec3param(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned int i, j;
+ unsigned char hash;
+ unsigned char flags;
+ char buf[sizeof("65535 ")];
+ isc_uint32_t iterations;
+
+ REQUIRE(rdata->type == 51);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ hash = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ flags = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ iterations = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ sprintf(buf, "%u ", hash);
+ RETERR(str_totext(buf, target));
+
+ sprintf(buf, "%u ", flags);
+ RETERR(str_totext(buf, target));
+
+ sprintf(buf, "%u ", iterations);
+ RETERR(str_totext(buf, target));
+
+ j = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ INSIST(j <= sr.length);
+
+ if (j != 0) {
+ i = sr.length;
+ sr.length = j;
+ RETERR(isc_hex_totext(&sr, 1, "", target));
+ sr.length = i - j;
+ } else
+ RETERR(str_totext("-", target));
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_nsec3param(ARGS_FROMWIRE) {
+ isc_region_t sr, rr;
+ unsigned int saltlen;
+
+ REQUIRE(type == 51);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(options);
+ UNUSED(dctx);
+
+ isc_buffer_activeregion(source, &sr);
+ rr = sr;
+
+ /* hash(1), flags(1), interations(2), saltlen(1) */
+ if (sr.length < 5U)
+ RETERR(DNS_R_FORMERR);
+ saltlen = sr.base[4];
+ isc_region_consume(&sr, 5);
+
+ if (sr.length < saltlen)
+ RETERR(DNS_R_FORMERR);
+ isc_region_consume(&sr, saltlen);
+ RETERR(mem_tobuffer(target, rr.base, rr.length));
+ isc_buffer_forward(source, rr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_nsec3param(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 51);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_nsec3param(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 51);
+ 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_nsec3param(ARGS_FROMSTRUCT) {
+ dns_rdata_nsec3param_t *nsec3param = source;
+
+ REQUIRE(type == 51);
+ REQUIRE(source != NULL);
+ REQUIRE(nsec3param->common.rdtype == type);
+ REQUIRE(nsec3param->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(nsec3param->hash, target));
+ RETERR(uint8_tobuffer(nsec3param->flags, target));
+ RETERR(uint16_tobuffer(nsec3param->iterations, target));
+ RETERR(uint8_tobuffer(nsec3param->salt_length, target));
+ RETERR(mem_tobuffer(target, nsec3param->salt,
+ nsec3param->salt_length));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+tostruct_nsec3param(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nsec3param_t *nsec3param = target;
+
+ REQUIRE(rdata->type == 51);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsec3param->common.rdclass = rdata->rdclass;
+ nsec3param->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsec3param->common, link);
+
+ region.base = rdata->data;
+ region.length = rdata->length;
+ nsec3param->hash = uint8_consume_fromregion(&region);
+ nsec3param->flags = uint8_consume_fromregion(&region);
+ nsec3param->iterations = uint16_consume_fromregion(&region);
+
+ nsec3param->salt_length = uint8_consume_fromregion(&region);
+ nsec3param->salt = mem_maybedup(mctx, region.base,
+ nsec3param->salt_length);
+ if (nsec3param->salt == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_region_consume(&region, nsec3param->salt_length);
+
+ nsec3param->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_nsec3param(ARGS_FREESTRUCT) {
+ dns_rdata_nsec3param_t *nsec3param = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(nsec3param->common.rdtype == 51);
+
+ if (nsec3param->mctx == NULL)
+ return;
+
+ if (nsec3param->salt != NULL)
+ isc_mem_free(nsec3param->mctx, nsec3param->salt);
+ nsec3param->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_nsec3param(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 51);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_nsec3param(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 51);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_nsec3param(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 51);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_nsec3param(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 51);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_NSEC3PARAM_51_C */
diff --git a/lib/dns/rdata/generic/nsec3param_51.h b/lib/dns/rdata/generic/nsec3param_51.h
new file mode 100644
index 0000000..2efd7e6
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec3param_51.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2008 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_NSEC3PARAM_51_H
+#define GENERIC_NSEC3PARAM_51_H 1
+
+/* $Id: nsec3param_51.h,v 1.4 2008/09/25 04:02:39 tbox Exp $ */
+
+/*!
+ * \brief Per RFC 5155 */
+
+#include <isc/iterated_hash.h>
+
+typedef struct dns_rdata_nsec3param {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_hash_t hash;
+ unsigned char flags; /* DNS_NSEC3FLAG_* */
+ dns_iterations_t iterations;
+ unsigned char salt_length;
+ unsigned char *salt;
+} dns_rdata_nsec3param_t;
+
+#endif /* GENERIC_NSEC3PARAM_51_H */
diff --git a/lib/dns/rdata/generic/nsec_47.c b/lib/dns/rdata/generic/nsec_47.c
new file mode 100644
index 0000000..7e443d9
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec_47.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: nsec_47.c,v 1.11 2008/07/15 23:47:21 tbox Exp $ */
+
+/* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
+
+/* RFC 3845 */
+
+#ifndef RDATA_GENERIC_NSEC_47_C
+#define RDATA_GENERIC_NSEC_47_C
+
+/*
+ * The attributes do not include DNS_RDATATYPEATTR_SINGLETON
+ * because we must be able to handle a parent/child NSEC pair.
+ */
+#define RRTYPE_NSEC_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static inline isc_result_t
+fromtext_nsec(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ unsigned char bm[8*1024]; /* 64k bits */
+ dns_rdatatype_t covered;
+ int octet;
+ int window;
+
+ REQUIRE(type == 47);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Next domain.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ memset(bm, 0, sizeof(bm));
+ do {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, ISC_TRUE));
+ if (token.type != isc_tokentype_string)
+ break;
+ RETTOK(dns_rdatatype_fromtext(&covered,
+ &token.value.as_textregion));
+ bm[covered/8] |= (0x80>>(covered%8));
+ } while (1);
+ isc_lex_ungettoken(lexer, &token);
+ for (window = 0; window < 256 ; window++) {
+ /*
+ * Find if we have a type in this window.
+ */
+ for (octet = 31; octet >= 0; octet--)
+ if (bm[window * 32 + octet] != 0)
+ break;
+ if (octet < 0)
+ continue;
+ RETERR(uint8_tobuffer(window, target));
+ RETERR(uint8_tobuffer(octet + 1, target));
+ RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_nsec(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned int i, j, k;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ unsigned int window, len;
+
+ REQUIRE(rdata->type == 47);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+
+ for (i = 0; i < sr.length; i += len) {
+ INSIST(i + 2 <= sr.length);
+ window = sr.base[i];
+ len = sr.base[i + 1];
+ INSIST(len > 0 && len <= 32);
+ i += 2;
+ INSIST(i + len <= sr.length);
+ for (j = 0; j < len; j++) {
+ dns_rdatatype_t t;
+ if (sr.base[i + j] == 0)
+ continue;
+ for (k = 0; k < 8; k++) {
+ if ((sr.base[i + j] & (0x80 >> k)) == 0)
+ continue;
+ t = window * 256 + j * 8 + k;
+ RETERR(str_totext(" ", target));
+ if (dns_rdatatype_isknown(t)) {
+ RETERR(dns_rdatatype_totext(t, target));
+ } else {
+ char buf[sizeof("TYPE65535")];
+ sprintf(buf, "TYPE%u", t);
+ RETERR(str_totext(buf, target));
+ }
+ }
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static /* inline */ isc_result_t
+fromwire_nsec(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ unsigned int window, lastwindow = 0;
+ unsigned int len;
+ isc_boolean_t first = ISC_TRUE;
+ unsigned int i;
+
+ REQUIRE(type == 47);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ 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);
+ for (i = 0; i < sr.length; i += len) {
+ /*
+ * Check for overflow.
+ */
+ if (i + 2 > sr.length)
+ RETERR(DNS_R_FORMERR);
+ window = sr.base[i];
+ len = sr.base[i + 1];
+ i += 2;
+ /*
+ * Check that bitmap windows are in the correct order.
+ */
+ if (!first && window <= lastwindow)
+ RETERR(DNS_R_FORMERR);
+ /*
+ * Check for legal lengths.
+ */
+ if (len < 1 || len > 32)
+ RETERR(DNS_R_FORMERR);
+ /*
+ * Check for overflow.
+ */
+ if (i + len > sr.length)
+ RETERR(DNS_R_FORMERR);
+ /*
+ * The last octet of the bitmap must be non zero.
+ */
+ if (sr.base[i + len - 1] == 0)
+ RETERR(DNS_R_FORMERR);
+ lastwindow = window;
+ first = ISC_FALSE;
+ }
+ if (i != sr.length)
+ return (DNS_R_EXTRADATA);
+ if (first)
+ RETERR(DNS_R_FORMERR);
+ RETERR(mem_tobuffer(target, sr.base, sr.length));
+ isc_buffer_forward(source, sr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_nsec(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == 47);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ RETERR(dns_name_towire(&name, cctx, target));
+
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_nsec(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 47);
+ 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_nsec(ARGS_FROMSTRUCT) {
+ dns_rdata_nsec_t *nsec = source;
+ isc_region_t region;
+ unsigned int i, len, window, lastwindow = 0;
+ isc_boolean_t first = ISC_TRUE;
+
+ REQUIRE(type == 47);
+ REQUIRE(source != NULL);
+ REQUIRE(nsec->common.rdtype == type);
+ REQUIRE(nsec->common.rdclass == rdclass);
+ REQUIRE(nsec->typebits != NULL || nsec->len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&nsec->next, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ /*
+ * Perform sanity check.
+ */
+ for (i = 0; i < nsec->len ; i += len) {
+ INSIST(i + 2 <= nsec->len);
+ window = nsec->typebits[i];
+ len = nsec->typebits[i+1];
+ i += 2;
+ INSIST(first || window > lastwindow);
+ INSIST(len > 0 && len <= 32);
+ INSIST(i + len <= nsec->len);
+ INSIST(nsec->typebits[i + len - 1] != 0);
+ lastwindow = window;
+ first = ISC_FALSE;
+ }
+ INSIST(!first);
+ return (mem_tobuffer(target, nsec->typebits, nsec->len));
+}
+
+static inline isc_result_t
+tostruct_nsec(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nsec_t *nsec = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 47);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsec->common.rdclass = rdata->rdclass;
+ nsec->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsec->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_init(&nsec->next, NULL);
+ RETERR(name_duporclone(&name, mctx, &nsec->next));
+
+ nsec->len = region.length;
+ nsec->typebits = mem_maybedup(mctx, region.base, region.length);
+ if (nsec->typebits == NULL)
+ goto cleanup;
+
+ nsec->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL)
+ dns_name_free(&nsec->next, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_nsec(ARGS_FREESTRUCT) {
+ dns_rdata_nsec_t *nsec = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(nsec->common.rdtype == 47);
+
+ if (nsec->mctx == NULL)
+ return;
+
+ dns_name_free(&nsec->next, nsec->mctx);
+ if (nsec->typebits != NULL)
+ isc_mem_free(nsec->mctx, nsec->typebits);
+ nsec->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_nsec(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 47);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_nsec(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 47);
+
+ dns_rdata_toregion(rdata, &r);
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_nsec(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 47);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_nsec(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 47);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_NSEC_47_C */
diff --git a/lib/dns/rdata/generic/nsec_47.h b/lib/dns/rdata/generic/nsec_47.h
new file mode 100644
index 0000000..2b3c6b6
--- /dev/null
+++ b/lib/dns/rdata/generic/nsec_47.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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.
+ */
+
+#ifndef GENERIC_NSEC_47_H
+#define GENERIC_NSEC_47_H 1
+
+/* $Id: nsec_47.h,v 1.10 2008/07/15 23:47:21 tbox Exp $ */
+
+/*!
+ * \brief Per RFC 3845 */
+
+typedef struct dns_rdata_nsec {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t next;
+ unsigned char *typebits;
+ isc_uint16_t len;
+} dns_rdata_nsec_t;
+
+#endif /* GENERIC_NSEC_47_H */
diff --git a/lib/dns/rdata/generic/null_10.c b/lib/dns/rdata/generic/null_10.c
new file mode 100644
index 0000000..00bb542
--- /dev/null
+++ b/lib/dns/rdata/generic/null_10.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: null_10.c,v 1.42 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 13:57:50 PST 2000 by explorer */
+
+#ifndef RDATA_GENERIC_NULL_10_C
+#define RDATA_GENERIC_NULL_10_C
+
+#define RRTYPE_NULL_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_null(ARGS_FROMTEXT) {
+ REQUIRE(type == 10);
+
+ UNUSED(rdclass);
+ UNUSED(type);
+ UNUSED(lexer);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(target);
+ UNUSED(callbacks);
+
+ return (DNS_R_SYNTAX);
+}
+
+static inline isc_result_t
+totext_null(ARGS_TOTEXT) {
+ REQUIRE(rdata->type == 10);
+
+ UNUSED(rdata);
+ UNUSED(tctx);
+ UNUSED(target);
+
+ return (DNS_R_SYNTAX);
+}
+
+static inline isc_result_t
+fromwire_null(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 10);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_null(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == 10);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static inline int
+compare_null(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 10);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_null(ARGS_FROMSTRUCT) {
+ dns_rdata_null_t *null = source;
+
+ REQUIRE(type == 10);
+ REQUIRE(source != NULL);
+ REQUIRE(null->common.rdtype == type);
+ REQUIRE(null->common.rdclass == rdclass);
+ REQUIRE(null->data != NULL || null->length == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, null->data, null->length));
+}
+
+static inline isc_result_t
+tostruct_null(ARGS_TOSTRUCT) {
+ dns_rdata_null_t *null = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 10);
+ REQUIRE(target != NULL);
+
+ null->common.rdclass = rdata->rdclass;
+ null->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&null->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ null->length = r.length;
+ null->data = mem_maybedup(mctx, r.base, r.length);
+ if (null->data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ null->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_null(ARGS_FREESTRUCT) {
+ dns_rdata_null_t *null = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(null->common.rdtype == 10);
+
+ if (null->mctx == NULL)
+ return;
+
+ if (null->data != NULL)
+ isc_mem_free(null->mctx, null->data);
+ null->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_null(ARGS_ADDLDATA) {
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ REQUIRE(rdata->type == 10);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_null(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 10);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_null(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 10);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_null(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 10);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_NULL_10_C */
diff --git a/lib/dns/rdata/generic/null_10.h b/lib/dns/rdata/generic/null_10.h
new file mode 100644
index 0000000..ceeb018
--- /dev/null
+++ b/lib/dns/rdata/generic/null_10.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_NULL_10_H
+#define GENERIC_NULL_10_H 1
+
+/* $Id: null_10.h,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_null {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t length;
+ unsigned char *data;
+} dns_rdata_null_t;
+
+
+#endif /* GENERIC_NULL_10_H */
diff --git a/lib/dns/rdata/generic/nxt_30.c b/lib/dns/rdata/generic/nxt_30.c
new file mode 100644
index 0000000..7ffb86c
--- /dev/null
+++ b/lib/dns/rdata/generic/nxt_30.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: nxt_30.c,v 1.63 2007/06/19 23:47:17 tbox Exp $ */
+
+/* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_NXT_30_C
+#define RDATA_GENERIC_NXT_30_C
+
+/*
+ * The attributes do not include DNS_RDATATYPEATTR_SINGLETON
+ * because we must be able to handle a parent/child NXT pair.
+ */
+#define RRTYPE_NXT_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_nxt(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ char *e;
+ unsigned char bm[8*1024]; /* 64k bits */
+ dns_rdatatype_t covered;
+ dns_rdatatype_t maxcovered = 0;
+ isc_boolean_t first = ISC_TRUE;
+ long n;
+
+ REQUIRE(type == 30);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Next domain.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ memset(bm, 0, sizeof(bm));
+ do {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, ISC_TRUE));
+ if (token.type != isc_tokentype_string)
+ break;
+ n = strtol(DNS_AS_STR(token), &e, 10);
+ if (e != DNS_AS_STR(token) && *e == '\0') {
+ covered = (dns_rdatatype_t)n;
+ } else if (dns_rdatatype_fromtext(&covered,
+ &token.value.as_textregion) == DNS_R_UNKNOWN)
+ RETTOK(DNS_R_UNKNOWN);
+ /*
+ * NXT is only specified for types 1..127.
+ */
+ if (covered < 1 || covered > 127)
+ return (ISC_R_RANGE);
+ if (first || covered > maxcovered)
+ maxcovered = covered;
+ first = ISC_FALSE;
+ bm[covered/8] |= (0x80>>(covered%8));
+ } while (1);
+ isc_lex_ungettoken(lexer, &token);
+ if (first)
+ return (ISC_R_SUCCESS);
+ n = (maxcovered + 8) / 8;
+ return (mem_tobuffer(target, bm, n));
+}
+
+static inline isc_result_t
+totext_nxt(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned int i, j;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 30);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ for (i = 0; i < sr.length; i++) {
+ if (sr.base[i] != 0)
+ for (j = 0; j < 8; j++)
+ if ((sr.base[i] & (0x80 >> j)) != 0) {
+ dns_rdatatype_t t = i * 8 + j;
+ RETERR(str_totext(" ", target));
+ if (dns_rdatatype_isknown(t)) {
+ RETERR(dns_rdatatype_totext(t,
+ target));
+ } else {
+ char buf[sizeof("65535")];
+ sprintf(buf, "%u", t);
+ RETERR(str_totext(buf,
+ target));
+ }
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_nxt(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+
+ REQUIRE(type == 30);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ 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);
+ if (sr.length > 0 && (sr.base[0] & 0x80) == 0 &&
+ ((sr.length > 16) || sr.base[sr.length - 1] == 0))
+ return (DNS_R_BADBITMAP);
+ RETERR(mem_tobuffer(target, sr.base, sr.length));
+ isc_buffer_forward(source, sr.length);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_nxt(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == 30);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ RETERR(dns_name_towire(&name, cctx, target));
+
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_nxt(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 == 30);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ dns_name_fromregion(&name1, &r1);
+ dns_name_fromregion(&name2, &r2);
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_nxt(ARGS_FROMSTRUCT) {
+ dns_rdata_nxt_t *nxt = source;
+ isc_region_t region;
+
+ REQUIRE(type == 30);
+ REQUIRE(source != NULL);
+ REQUIRE(nxt->common.rdtype == type);
+ REQUIRE(nxt->common.rdclass == rdclass);
+ REQUIRE(nxt->typebits != NULL || nxt->len == 0);
+ if (nxt->typebits != NULL && (nxt->typebits[0] & 0x80) == 0) {
+ REQUIRE(nxt->len <= 16);
+ REQUIRE(nxt->typebits[nxt->len - 1] != 0);
+ }
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&nxt->next, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+
+ return (mem_tobuffer(target, nxt->typebits, nxt->len));
+}
+
+static inline isc_result_t
+tostruct_nxt(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_nxt_t *nxt = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 30);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nxt->common.rdclass = rdata->rdclass;
+ nxt->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nxt->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_init(&nxt->next, NULL);
+ RETERR(name_duporclone(&name, mctx, &nxt->next));
+
+ nxt->len = region.length;
+ nxt->typebits = mem_maybedup(mctx, region.base, region.length);
+ if (nxt->typebits == NULL)
+ goto cleanup;
+
+ nxt->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL)
+ dns_name_free(&nxt->next, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_nxt(ARGS_FREESTRUCT) {
+ dns_rdata_nxt_t *nxt = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(nxt->common.rdtype == 30);
+
+ if (nxt->mctx == NULL)
+ return;
+
+ dns_name_free(&nxt->next, nxt->mctx);
+ if (nxt->typebits != NULL)
+ isc_mem_free(nxt->mctx, nxt->typebits);
+ nxt->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_nxt(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 30);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_nxt(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == 30);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ result = dns_name_digest(&name, digest, arg);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_region_consume(&r, name_length(&name));
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_nxt(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 30);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_nxt(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 30);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_NXT_30_C */
diff --git a/lib/dns/rdata/generic/nxt_30.h b/lib/dns/rdata/generic/nxt_30.h
new file mode 100644
index 0000000..e2e8688
--- /dev/null
+++ b/lib/dns/rdata/generic/nxt_30.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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.
+ */
+
+#ifndef GENERIC_NXT_30_H
+#define GENERIC_NXT_30_H 1
+
+/* $Id: nxt_30.h,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief RFC2535 */
+
+typedef struct dns_rdata_nxt {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t next;
+ unsigned char *typebits;
+ isc_uint16_t len;
+} dns_rdata_nxt_t;
+
+#endif /* GENERIC_NXT_30_H */
diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c
new file mode 100644
index 0000000..d2cfc2e
--- /dev/null
+++ b/lib/dns/rdata/generic/opt_41.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: opt_41.c,v 1.33 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 14:06:44 PST 2000 by gson */
+
+/* RFC2671 */
+
+#ifndef RDATA_GENERIC_OPT_41_C
+#define RDATA_GENERIC_OPT_41_C
+
+#define RRTYPE_OPT_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON | \
+ DNS_RDATATYPEATTR_META | \
+ DNS_RDATATYPEATTR_NOTQUESTION)
+
+static inline isc_result_t
+fromtext_opt(ARGS_FROMTEXT) {
+ /*
+ * OPT records do not have a text format.
+ */
+
+ REQUIRE(type == 41);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(lexer);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(target);
+ UNUSED(callbacks);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline isc_result_t
+totext_opt(ARGS_TOTEXT) {
+ isc_region_t r;
+ isc_region_t or;
+ isc_uint16_t option;
+ isc_uint16_t length;
+ char buf[sizeof("64000 64000")];
+
+ /*
+ * OPT records do not have a text format.
+ */
+
+ REQUIRE(rdata->type == 41);
+
+ dns_rdata_toregion(rdata, &r);
+ while (r.length > 0) {
+ option = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+ length = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+ sprintf(buf, "%u %u", option, length);
+ RETERR(str_totext(buf, target));
+ INSIST(r.length >= length);
+ if (length > 0) {
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+ or = r;
+ or.length = length;
+ RETERR(isc_base64_totext(&or, tctx->width - 2,
+ tctx->linebreak, target));
+ isc_region_consume(&r, length);
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+ }
+ if (r.length > 0)
+ RETERR(str_totext(" ", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_opt(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+ isc_region_t tregion;
+ isc_uint16_t length;
+ unsigned int total;
+
+ REQUIRE(type == 41);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sregion);
+ total = 0;
+ while (sregion.length != 0) {
+ if (sregion.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+ /*
+ * Eat the 16bit option code. There is nothing to
+ * be done with it currently.
+ */
+ isc_region_consume(&sregion, 2);
+ length = uint16_fromregion(&sregion);
+ isc_region_consume(&sregion, 2);
+ total += 4;
+ if (sregion.length < length)
+ return (ISC_R_UNEXPECTEDEND);
+ isc_region_consume(&sregion, length);
+ total += length;
+ }
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+ if (tregion.length < total)
+ return (ISC_R_NOSPACE);
+ memcpy(tregion.base, sregion.base, total);
+ isc_buffer_forward(source, total);
+ isc_buffer_add(target, total);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_opt(ARGS_TOWIRE) {
+
+ REQUIRE(rdata->type == 41);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static inline int
+compare_opt(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 41);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_opt(ARGS_FROMSTRUCT) {
+ dns_rdata_opt_t *opt = source;
+ isc_region_t region;
+ isc_uint16_t length;
+
+ REQUIRE(type == 41);
+ REQUIRE(source != NULL);
+ REQUIRE(opt->common.rdtype == type);
+ REQUIRE(opt->common.rdclass == rdclass);
+ REQUIRE(opt->options != NULL || opt->length == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ region.base = opt->options;
+ region.length = opt->length;
+ while (region.length >= 4) {
+ isc_region_consume(&region, 2); /* opt */
+ length = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ if (region.length < length)
+ return (ISC_R_UNEXPECTEDEND);
+ isc_region_consume(&region, length);
+ }
+ if (region.length != 0)
+ return (ISC_R_UNEXPECTEDEND);
+
+ return (mem_tobuffer(target, opt->options, opt->length));
+}
+
+static inline isc_result_t
+tostruct_opt(ARGS_TOSTRUCT) {
+ dns_rdata_opt_t *opt = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 41);
+ REQUIRE(target != NULL);
+
+ opt->common.rdclass = rdata->rdclass;
+ opt->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&opt->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ opt->length = r.length;
+ opt->options = mem_maybedup(mctx, r.base, r.length);
+ if (opt->options == NULL)
+ return (ISC_R_NOMEMORY);
+
+ opt->offset = 0;
+ opt->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_opt(ARGS_FREESTRUCT) {
+ dns_rdata_opt_t *opt = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(opt->common.rdtype == 41);
+
+ if (opt->mctx == NULL)
+ return;
+
+ if (opt->options != NULL)
+ isc_mem_free(opt->mctx, opt->options);
+ opt->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_opt(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 41);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_opt(ARGS_DIGEST) {
+
+ /*
+ * OPT records are not digested.
+ */
+
+ REQUIRE(rdata->type == 41);
+
+ UNUSED(rdata);
+ UNUSED(digest);
+ UNUSED(arg);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline isc_boolean_t
+checkowner_opt(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 41);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (dns_name_equal(name, dns_rootname));
+}
+
+static inline isc_boolean_t
+checknames_opt(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 41);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_OPT_41_C */
diff --git a/lib/dns/rdata/generic/opt_41.h b/lib/dns/rdata/generic/opt_41.h
new file mode 100644
index 0000000..d6539cf
--- /dev/null
+++ b/lib/dns/rdata/generic/opt_41.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+#ifndef GENERIC_OPT_41_H
+#define GENERIC_OPT_41_H 1
+
+/* $Id: opt_41.h,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC2671 */
+
+typedef struct dns_rdata_opt_opcode {
+ isc_uint16_t opcode;
+ isc_uint16_t length;
+ unsigned char *data;
+} dns_rdata_opt_opcode_t;
+
+typedef struct dns_rdata_opt {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *options;
+ isc_uint16_t length;
+ /* private */
+ isc_uint16_t offset;
+} dns_rdata_opt_t;
+
+/*
+ * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
+ * via rdatastructpre.h and rdatastructsuf.h.
+ */
+
+isc_result_t
+dns_rdata_opt_first(dns_rdata_opt_t *);
+
+isc_result_t
+dns_rdata_opt_next(dns_rdata_opt_t *);
+
+isc_result_t
+dns_rdata_opt_current(dns_rdata_opt_t *, dns_rdata_opt_opcode_t *);
+
+#endif /* GENERIC_OPT_41_H */
diff --git a/lib/dns/rdata/generic/proforma.c b/lib/dns/rdata/generic/proforma.c
new file mode 100644
index 0000000..879b761
--- /dev/null
+++ b/lib/dns/rdata/generic/proforma.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: proforma.c,v 1.36 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef RDATA_GENERIC_#_#_C
+#define RDATA_GENERIC_#_#_C
+
+#define RRTYPE_#_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_#(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ REQUIRE(type == #);
+ REQUIRE(rdclass == #);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline isc_result_t
+totext_#(ARGS_TOTEXT) {
+
+ REQUIRE(rdata->type == #);
+ REQUIRE(rdata->rdclass == #);
+ REQUIRE(rdata->length != 0); /* XXX */
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline isc_result_t
+fromwire_#(ARGS_FROMWIRE) {
+
+ REQUIRE(type == #);
+ REQUIRE(rdclass == #);
+
+ /* NONE or GLOBAL14 */
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline isc_result_t
+towire_#(ARGS_TOWIRE) {
+
+ REQUIRE(rdata->type == #);
+ REQUIRE(rdata->rdclass == #);
+ REQUIRE(rdata->length != 0); /* XXX */
+
+ /* NONE or GLOBAL14 */
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline int
+compare_#(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));
+}
+
+static inline isc_result_t
+fromstruct_#(ARGS_FROMSTRUCT) {
+ dns_rdata_#_t *# = source;
+
+ REQUIRE(type == #);
+ REQUIRE(rdclass == #);
+ REQUIRE(source != NULL);
+ REQUIRE(#->common.rdtype == type);
+ REQUIRE(#->common.rdclass == rdclass);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline isc_result_t
+tostruct_#(ARGS_TOSTRUCT) {
+
+ REQUIRE(rdata->type == #);
+ REQUIRE(rdata->rdclass == #);
+ REQUIRE(rdata->length != 0); /* XXX */
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline void
+freestruct_#(ARGS_FREESTRUCT) {
+ dns_rdata_#_t *# = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(#->common.rdtype == #);
+ REQUIRE(#->common.rdclass == #);
+
+}
+
+static inline isc_result_t
+additionaldata_#(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == #);
+ REQUIRE(rdata->rdclass == #);
+
+ (void)add;
+ (void)arg;
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_#(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == #);
+ REQUIRE(rdata->rdclass == #);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_#(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == #);
+ REQUIRE(rdclass == #);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_#(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == #);
+ REQUIRE(rdata->rdclass == #);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_#_#_C */
diff --git a/lib/dns/rdata/generic/proforma.h b/lib/dns/rdata/generic/proforma.h
new file mode 100644
index 0000000..e5c420a
--- /dev/null
+++ b/lib/dns/rdata/generic/proforma.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_PROFORMA_H
+#define GENERIC_PROFORMA_H 1
+
+/* $Id: proforma.h,v 1.23 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_# {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx; /* if required */
+ /* type & class specific elements */
+} dns_rdata_#_t;
+
+#endif /* GENERIC_PROFORMA_H */
diff --git a/lib/dns/rdata/generic/ptr_12.c b/lib/dns/rdata/generic/ptr_12.c
new file mode 100644
index 0000000..fbabcbf
--- /dev/null
+++ b/lib/dns/rdata/generic/ptr_12.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: ptr_12.c,v 1.43 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 14:05:12 PST 2000 by explorer */
+
+#ifndef RDATA_GENERIC_PTR_12_C
+#define RDATA_GENERIC_PTR_12_C
+
+#define RRTYPE_PTR_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_ptr(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 12);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ if (rdclass == dns_rdataclass_in &&
+ (options & DNS_RDATA_CHECKNAMES) != 0 &&
+ (options & DNS_RDATA_CHECKREVERSE) != 0) {
+ isc_boolean_t ok;
+ ok = dns_name_ishostname(&name, ISC_FALSE);
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_ptr(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 12);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_ptr(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == 12);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_ptr(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 12);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_ptr(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 12);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_ptr(ARGS_FROMSTRUCT) {
+ dns_rdata_ptr_t *ptr = source;
+ isc_region_t region;
+
+ REQUIRE(type == 12);
+ REQUIRE(source != NULL);
+ REQUIRE(ptr->common.rdtype == type);
+ REQUIRE(ptr->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&ptr->ptr, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_ptr(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_ptr_t *ptr = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 12);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ ptr->common.rdclass = rdata->rdclass;
+ ptr->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&ptr->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&ptr->ptr, NULL);
+ RETERR(name_duporclone(&name, mctx, &ptr->ptr));
+ ptr->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_ptr(ARGS_FREESTRUCT) {
+ dns_rdata_ptr_t *ptr = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(ptr->common.rdtype == 12);
+
+ if (ptr->mctx == NULL)
+ return;
+
+ dns_name_free(&ptr->ptr, ptr->mctx);
+ ptr->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_ptr(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 12);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_ptr(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 12);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_ptr(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 12);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static unsigned char ip6_arpa_data[] = "\003IP6\004ARPA";
+static unsigned char ip6_arpa_offsets[] = { 0, 4, 9 };
+static const dns_name_t ip6_arpa =
+{
+ DNS_NAME_MAGIC,
+ ip6_arpa_data, 10, 3,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ ip6_arpa_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+static unsigned char ip6_int_data[] = "\003IP6\003INT";
+static unsigned char ip6_int_offsets[] = { 0, 4, 8 };
+static const dns_name_t ip6_int =
+{
+ DNS_NAME_MAGIC,
+ ip6_int_data, 9, 3,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ ip6_int_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+static unsigned char in_addr_arpa_data[] = "\007IN-ADDR\004ARPA";
+static unsigned char in_addr_arpa_offsets[] = { 0, 8, 13 };
+static const dns_name_t in_addr_arpa =
+{
+ DNS_NAME_MAGIC,
+ in_addr_arpa_data, 14, 3,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ in_addr_arpa_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+static inline isc_boolean_t
+checknames_ptr(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 12);
+
+ if (rdata->rdclass != dns_rdataclass_in)
+ return (ISC_TRUE);
+
+ if (dns_name_issubdomain(owner, &in_addr_arpa) ||
+ dns_name_issubdomain(owner, &ip6_arpa) ||
+ dns_name_issubdomain(owner, &ip6_int)) {
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, ISC_FALSE)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ }
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_PTR_12_C */
diff --git a/lib/dns/rdata/generic/ptr_12.h b/lib/dns/rdata/generic/ptr_12.h
new file mode 100644
index 0000000..304dcc4
--- /dev/null
+++ b/lib/dns/rdata/generic/ptr_12.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_PTR_12_H
+#define GENERIC_PTR_12_H 1
+
+/* $Id: ptr_12.h,v 1.27 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_ptr {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t ptr;
+} dns_rdata_ptr_t;
+
+#endif /* GENERIC_PTR_12_H */
diff --git a/lib/dns/rdata/generic/rp_17.c b/lib/dns/rdata/generic/rp_17.c
new file mode 100644
index 0000000..557cb04
--- /dev/null
+++ b/lib/dns/rdata/generic/rp_17.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rp_17.c,v 1.42 2007/06/19 23:47:17 tbox Exp $ */
+
+/* RFC1183 */
+
+#ifndef RDATA_GENERIC_RP_17_C
+#define RDATA_GENERIC_RP_17_C
+
+#define RRTYPE_RP_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_rp(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ int i;
+ isc_boolean_t ok;
+
+ REQUIRE(type == 17);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ origin = (origin != NULL) ? origin : dns_rootname;
+
+ for (i = 0; i < 2; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ RETTOK(dns_name_fromtext(&name, &buffer, origin,
+ options, target));
+ ok = ISC_TRUE;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0 && i == 0)
+ ok = dns_name_ismailbox(&name);
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_rp(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t rmail;
+ dns_name_t email;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 17);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&rmail, NULL);
+ dns_name_init(&email, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, rmail.length);
+
+ dns_name_fromregion(&email, &region);
+ isc_region_consume(&region, email.length);
+
+ sub = name_prefix(&rmail, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ RETERR(str_totext(" ", target));
+
+ sub = name_prefix(&email, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_rp(ARGS_FROMWIRE) {
+ dns_name_t rmail;
+ dns_name_t email;
+
+ REQUIRE(type == 17);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ 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));
+}
+
+static inline isc_result_t
+towire_rp(ARGS_TOWIRE) {
+ isc_region_t region;
+ dns_name_t rmail;
+ dns_name_t email;
+ dns_offsets_t roffsets;
+ dns_offsets_t eoffsets;
+
+ REQUIRE(rdata->type == 17);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_name_init(&rmail, roffsets);
+ dns_name_init(&email, eoffsets);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, rmail.length);
+
+ RETERR(dns_name_towire(&rmail, cctx, target));
+
+ dns_name_fromregion(&rmail, &region);
+ isc_region_consume(&region, rmail.length);
+
+ return (dns_name_towire(&rmail, cctx, target));
+}
+
+static inline int
+compare_rp(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 == 17);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_rp(ARGS_FROMSTRUCT) {
+ dns_rdata_rp_t *rp = source;
+ isc_region_t region;
+
+ REQUIRE(type == 17);
+ REQUIRE(source != NULL);
+ REQUIRE(rp->common.rdtype == type);
+ REQUIRE(rp->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&rp->mail, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ dns_name_toregion(&rp->text, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_rp(ARGS_TOSTRUCT) {
+ isc_result_t result;
+ isc_region_t region;
+ dns_rdata_rp_t *rp = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 17);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ rp->common.rdclass = rdata->rdclass;
+ rp->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&rp->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&rp->mail, NULL);
+ RETERR(name_duporclone(&name, mctx, &rp->mail));
+ isc_region_consume(&region, name_length(&name));
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&rp->text, NULL);
+ result = name_duporclone(&name, mctx, &rp->text);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ rp->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL)
+ dns_name_free(&rp->mail, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_rp(ARGS_FREESTRUCT) {
+ dns_rdata_rp_t *rp = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(rp->common.rdtype == 17);
+
+ if (rp->mctx == NULL)
+ return;
+
+ dns_name_free(&rp->mail, rp->mctx);
+ dns_name_free(&rp->text, rp->mctx);
+ rp->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_rp(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 17);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_rp(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 17);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+
+ dns_name_fromregion(&name, &r);
+ RETERR(dns_name_digest(&name, digest, arg));
+ isc_region_consume(&r, name_length(&name));
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_rp(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 17);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_rp(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 17);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ismailbox(&name)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_RP_17_C */
diff --git a/lib/dns/rdata/generic/rp_17.h b/lib/dns/rdata/generic/rp_17.h
new file mode 100644
index 0000000..6223038
--- /dev/null
+++ b/lib/dns/rdata/generic/rp_17.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef GENERIC_RP_17_H
+#define GENERIC_RP_17_H 1
+
+/* $Id: rp_17.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC1183 */
+
+typedef struct dns_rdata_rp {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t mail;
+ dns_name_t text;
+} dns_rdata_rp_t;
+
+
+#endif /* GENERIC_RP_17_H */
diff --git a/lib/dns/rdata/generic/rrsig_46.c b/lib/dns/rdata/generic/rrsig_46.c
new file mode 100644
index 0000000..a9af4bd
--- /dev/null
+++ b/lib/dns/rdata/generic/rrsig_46.c
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: rrsig_46.c,v 1.10 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Fri Mar 17 09:05:02 PST 2000 by gson */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_RRSIG_46_C
+#define RDATA_GENERIC_RRSIG_46_C
+
+#define RRTYPE_RRSIG_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
+
+static inline isc_result_t
+fromtext_rrsig(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char c;
+ long i;
+ dns_rdatatype_t covered;
+ char *e;
+ isc_result_t result;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ isc_uint32_t time_signed, time_expire;
+
+ REQUIRE(type == 46);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Type covered.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ result = dns_rdatatype_fromtext(&covered, &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
+ i = strtol(DNS_AS_STR(token), &e, 10);
+ if (i < 0 || i > 65535)
+ RETTOK(ISC_R_RANGE);
+ if (*e != 0)
+ RETTOK(result);
+ covered = (dns_rdatatype_t)i;
+ }
+ RETERR(uint16_tobuffer(covered, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Labels.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffU)
+ RETTOK(ISC_R_RANGE);
+ c = (unsigned char)token.value.as_ulong;
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Original ttl.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Signature expiration.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire));
+ RETERR(uint32_tobuffer(time_expire, target));
+
+ /*
+ * Time signed.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed));
+ RETERR(uint32_tobuffer(time_signed, target));
+
+ /*
+ * Key footprint.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Signer.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ /*
+ * Sig.
+ */
+ return (isc_base64_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_rrsig(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("4294967295")];
+ dns_rdatatype_t covered;
+ unsigned long ttl;
+ unsigned long when;
+ unsigned long exp;
+ unsigned long foot;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 46);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Type covered.
+ */
+ covered = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ /*
+ * XXXAG We should have something like dns_rdatatype_isknown()
+ * that does the right thing with type 0.
+ */
+ if (dns_rdatatype_isknown(covered) && covered != 0) {
+ RETERR(dns_rdatatype_totext(covered, target));
+ } else {
+ char buf[sizeof("TYPE65535")];
+ sprintf(buf, "TYPE%u", covered);
+ RETERR(str_totext(buf, target));
+ }
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Algorithm.
+ */
+ sprintf(buf, "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Labels.
+ */
+ sprintf(buf, "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Ttl.
+ */
+ ttl = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ sprintf(buf, "%lu", ttl);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Sig exp.
+ */
+ exp = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(exp, target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+
+ /*
+ * Time signed.
+ */
+ when = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(when, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Footprint.
+ */
+ foot = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%lu", foot);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ /*
+ * Sig.
+ */
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(isc_base64_totext(&sr, tctx->width - 2,
+ tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_rrsig(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+
+ REQUIRE(type == 46);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ isc_buffer_activeregion(source, &sr);
+ /*
+ * type covered: 2
+ * algorithm: 1
+ * labels: 1
+ * original ttl: 4
+ * signature expiration: 4
+ * time signed: 4
+ * key footprint: 2
+ */
+ if (sr.length < 18)
+ return (ISC_R_UNEXPECTEDEND);
+
+ isc_buffer_forward(source, 18);
+ RETERR(mem_tobuffer(target, sr.base, 18));
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ /*
+ * Sig.
+ */
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_rrsig(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == 46);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_rdata_toregion(rdata, &sr);
+ /*
+ * type covered: 2
+ * algorithm: 1
+ * labels: 1
+ * original ttl: 4
+ * signature expiration: 4
+ * time signed: 4
+ * key footprint: 2
+ */
+ RETERR(mem_tobuffer(target, sr.base, 18));
+ isc_region_consume(&sr, 18);
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ RETERR(dns_name_towire(&name, cctx, target));
+
+ /*
+ * Signature.
+ */
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_rrsig(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ 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);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_rrsig(ARGS_FROMSTRUCT) {
+ dns_rdata_rrsig_t *sig = source;
+
+ REQUIRE(type == 46);
+ REQUIRE(source != NULL);
+ REQUIRE(sig->common.rdtype == type);
+ REQUIRE(sig->common.rdclass == rdclass);
+ REQUIRE(sig->signature != NULL || sig->siglen == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Type covered.
+ */
+ RETERR(uint16_tobuffer(sig->covered, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(uint8_tobuffer(sig->algorithm, target));
+
+ /*
+ * Labels.
+ */
+ RETERR(uint8_tobuffer(sig->labels, target));
+
+ /*
+ * Original TTL.
+ */
+ RETERR(uint32_tobuffer(sig->originalttl, target));
+
+ /*
+ * Expire time.
+ */
+ RETERR(uint32_tobuffer(sig->timeexpire, target));
+
+ /*
+ * Time signed.
+ */
+ RETERR(uint32_tobuffer(sig->timesigned, target));
+
+ /*
+ * Key ID.
+ */
+ RETERR(uint16_tobuffer(sig->keyid, target));
+
+ /*
+ * Signer name.
+ */
+ RETERR(name_tobuffer(&sig->signer, target));
+
+ /*
+ * Signature.
+ */
+ return (mem_tobuffer(target, sig->signature, sig->siglen));
+}
+
+static inline isc_result_t
+tostruct_rrsig(ARGS_TOSTRUCT) {
+ isc_region_t sr;
+ dns_rdata_rrsig_t *sig = target;
+ dns_name_t signer;
+
+ REQUIRE(rdata->type == 46);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ sig->common.rdclass = rdata->rdclass;
+ sig->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&sig->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Type covered.
+ */
+ sig->covered = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Algorithm.
+ */
+ sig->algorithm = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Labels.
+ */
+ sig->labels = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Original TTL.
+ */
+ sig->originalttl = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Expire time.
+ */
+ sig->timeexpire = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Time signed.
+ */
+ sig->timesigned = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Key ID.
+ */
+ sig->keyid = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ dns_name_init(&signer, NULL);
+ dns_name_fromregion(&signer, &sr);
+ dns_name_init(&sig->signer, NULL);
+ RETERR(name_duporclone(&signer, mctx, &sig->signer));
+ isc_region_consume(&sr, name_length(&sig->signer));
+
+ /*
+ * Signature.
+ */
+ sig->siglen = sr.length;
+ sig->signature = mem_maybedup(mctx, sr.base, sig->siglen);
+ if (sig->signature == NULL)
+ goto cleanup;
+
+
+ sig->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL)
+ dns_name_free(&sig->signer, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_rrsig(ARGS_FREESTRUCT) {
+ dns_rdata_rrsig_t *sig = (dns_rdata_rrsig_t *) source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(sig->common.rdtype == 46);
+
+ if (sig->mctx == NULL)
+ return;
+
+ dns_name_free(&sig->signer, sig->mctx);
+ if (sig->signature != NULL)
+ isc_mem_free(sig->mctx, sig->signature);
+ sig->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_rrsig(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 46);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_rrsig(ARGS_DIGEST) {
+
+ REQUIRE(rdata->type == 46);
+
+ UNUSED(rdata);
+ UNUSED(digest);
+ UNUSED(arg);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline dns_rdatatype_t
+covers_rrsig(dns_rdata_t *rdata) {
+ dns_rdatatype_t type;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 46);
+
+ dns_rdata_toregion(rdata, &r);
+ type = uint16_fromregion(&r);
+
+ return (type);
+}
+
+static inline isc_boolean_t
+checkowner_rrsig(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 46);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_rrsig(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 46);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_RRSIG_46_C */
diff --git a/lib/dns/rdata/generic/rrsig_46.h b/lib/dns/rdata/generic/rrsig_46.h
new file mode 100644
index 0000000..8e8dc4e
--- /dev/null
+++ b/lib/dns/rdata/generic/rrsig_46.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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.
+ */
+
+#ifndef GENERIC_DNSSIG_46_H
+#define GENERIC_DNSSIG_46_H 1
+
+/* $Id: rrsig_46.h,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC2535 */
+typedef struct dns_rdata_rrsig {
+ dns_rdatacommon_t common;
+ isc_mem_t * mctx;
+ dns_rdatatype_t covered;
+ dns_secalg_t algorithm;
+ isc_uint8_t labels;
+ isc_uint32_t originalttl;
+ isc_uint32_t timeexpire;
+ isc_uint32_t timesigned;
+ isc_uint16_t keyid;
+ dns_name_t signer;
+ isc_uint16_t siglen;
+ unsigned char * signature;
+} dns_rdata_rrsig_t;
+
+
+#endif /* GENERIC_DNSSIG_46_H */
diff --git a/lib/dns/rdata/generic/rt_21.c b/lib/dns/rdata/generic/rt_21.c
new file mode 100644
index 0000000..6444102
--- /dev/null
+++ b/lib/dns/rdata/generic/rt_21.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: rt_21.c,v 1.46 2007/06/19 23:47:17 tbox Exp $ */
+
+/* reviewed: Thu Mar 16 15:02:31 PST 2000 by brister */
+
+/* RFC1183 */
+
+#ifndef RDATA_GENERIC_RT_21_C
+#define RDATA_GENERIC_RT_21_C
+
+#define RRTYPE_RT_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_rt(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ isc_boolean_t ok;
+
+ REQUIRE(type == 21);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ ok = ISC_TRUE;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0)
+ ok = dns_name_ishostname(&name, ISC_FALSE);
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_rt(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ char buf[sizeof("64000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == 21);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ sprintf(buf, "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_rt(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ REQUIRE(type == 21);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+ if (tregion.length < 2)
+ return (ISC_R_NOSPACE);
+ if (sregion.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ memcpy(tregion.base, sregion.base, 2);
+ isc_buffer_forward(source, 2);
+ isc_buffer_add(target, 2);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_rt(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+ isc_region_t tr;
+
+ REQUIRE(rdata->type == 21);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ isc_buffer_availableregion(target, &tr);
+ dns_rdata_toregion(rdata, &region);
+ if (tr.length < 2)
+ return (ISC_R_NOSPACE);
+ memcpy(tr.base, region.base, 2);
+ isc_region_consume(&region, 2);
+ isc_buffer_add(target, 2);
+
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_rt(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 21);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ order = memcmp(rdata1->data, rdata2->data, 2);
+ if (order != 0)
+ return (order < 0 ? -1 : 1);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 2);
+ isc_region_consume(&region2, 2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_rt(ARGS_FROMSTRUCT) {
+ dns_rdata_rt_t *rt = source;
+ isc_region_t region;
+
+ REQUIRE(type == 21);
+ REQUIRE(source != NULL);
+ REQUIRE(rt->common.rdtype == type);
+ REQUIRE(rt->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(rt->preference, target));
+ dns_name_toregion(&rt->host, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_rt(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_rt_t *rt = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 21);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ rt->common.rdclass = rdata->rdclass;
+ rt->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&rt->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ rt->preference = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&rt->host, NULL);
+ RETERR(name_duporclone(&name, mctx, &rt->host));
+
+ rt->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_rt(ARGS_FREESTRUCT) {
+ dns_rdata_rt_t *rt = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(rt->common.rdtype == 21);
+
+ if (rt->mctx == NULL)
+ return;
+
+ dns_name_free(&rt->host, rt->mctx);
+ rt->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_rt(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == 21);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+
+ result = (add)(arg, &name, dns_rdatatype_x25);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = (add)(arg, &name, dns_rdatatype_isdn);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return ((add)(arg, &name, dns_rdatatype_a));
+}
+
+static inline isc_result_t
+digest_rt(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ isc_result_t result;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 21);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ isc_region_consume(&r2, 2);
+ r1.length = 2;
+ result = (digest)(arg, &r1);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_rt(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 21);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_rt(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 21);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, ISC_FALSE)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_RT_21_C */
diff --git a/lib/dns/rdata/generic/rt_21.h b/lib/dns/rdata/generic/rt_21.h
new file mode 100644
index 0000000..2c0e9fc
--- /dev/null
+++ b/lib/dns/rdata/generic/rt_21.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef GENERIC_RT_21_H
+#define GENERIC_RT_21_H 1
+
+/* $Id: rt_21.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC1183 */
+
+typedef struct dns_rdata_rt {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t preference;
+ dns_name_t host;
+} dns_rdata_rt_t;
+
+#endif /* GENERIC_RT_21_H */
diff --git a/lib/dns/rdata/generic/sig_24.c b/lib/dns/rdata/generic/sig_24.c
new file mode 100644
index 0000000..e79e1e4
--- /dev/null
+++ b/lib/dns/rdata/generic/sig_24.c
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: sig_24.c,v 1.66 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Fri Mar 17 09:05:02 PST 2000 by gson */
+
+/* RFC2535 */
+
+#ifndef RDATA_GENERIC_SIG_24_C
+#define RDATA_GENERIC_SIG_24_C
+
+#define RRTYPE_SIG_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_sig(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char c;
+ long i;
+ dns_rdatatype_t covered;
+ char *e;
+ isc_result_t result;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ isc_uint32_t time_signed, time_expire;
+
+ REQUIRE(type == 24);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Type covered.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ result = dns_rdatatype_fromtext(&covered, &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
+ i = strtol(DNS_AS_STR(token), &e, 10);
+ if (i < 0 || i > 65535)
+ RETTOK(ISC_R_RANGE);
+ if (*e != 0)
+ RETTOK(result);
+ covered = (dns_rdatatype_t)i;
+ }
+ RETERR(uint16_tobuffer(covered, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion));
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Labels.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffU)
+ RETTOK(ISC_R_RANGE);
+ c = (unsigned char)token.value.as_ulong;
+ RETERR(mem_tobuffer(target, &c, 1));
+
+ /*
+ * Original ttl.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Signature expiration.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_expire));
+ RETERR(uint32_tobuffer(time_expire, target));
+
+ /*
+ * Time signed.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_time32_fromtext(DNS_AS_STR(token), &time_signed));
+ RETERR(uint32_tobuffer(time_signed, target));
+
+ /*
+ * Key footprint.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Signer.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ /*
+ * Sig.
+ */
+ return (isc_base64_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_sig(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("4294967295")];
+ dns_rdatatype_t covered;
+ unsigned long ttl;
+ unsigned long when;
+ unsigned long exp;
+ unsigned long foot;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 24);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Type covered.
+ */
+ covered = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ /*
+ * XXXAG We should have something like dns_rdatatype_isknown()
+ * that does the right thing with type 0.
+ */
+ if (dns_rdatatype_isknown(covered) && covered != 0) {
+ RETERR(dns_rdatatype_totext(covered, target));
+ } else {
+ char buf[sizeof("65535")];
+ sprintf(buf, "%u", covered);
+ RETERR(str_totext(buf, target));
+ }
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Algorithm.
+ */
+ sprintf(buf, "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Labels.
+ */
+ sprintf(buf, "%u", sr.base[0]);
+ isc_region_consume(&sr, 1);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Ttl.
+ */
+ ttl = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ sprintf(buf, "%lu", ttl);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Sig exp.
+ */
+ exp = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(exp, target));
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+
+ /*
+ * Time signed.
+ */
+ when = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ RETERR(dns_time32_totext(when, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Footprint.
+ */
+ foot = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%lu", foot);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ /*
+ * Sig.
+ */
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(isc_base64_totext(&sr, tctx->width - 2,
+ tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_sig(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+
+ REQUIRE(type == 24);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ isc_buffer_activeregion(source, &sr);
+ /*
+ * type covered: 2
+ * algorithm: 1
+ * labels: 1
+ * original ttl: 4
+ * signature expiration: 4
+ * time signed: 4
+ * key footprint: 2
+ */
+ if (sr.length < 18)
+ return (ISC_R_UNEXPECTEDEND);
+
+ isc_buffer_forward(source, 18);
+ RETERR(mem_tobuffer(target, sr.base, 18));
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ /*
+ * Sig.
+ */
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_sig(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == 24);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_rdata_toregion(rdata, &sr);
+ /*
+ * type covered: 2
+ * algorithm: 1
+ * labels: 1
+ * original ttl: 4
+ * signature expiration: 4
+ * time signed: 4
+ * key footprint: 2
+ */
+ RETERR(mem_tobuffer(target, sr.base, 18));
+ isc_region_consume(&sr, 18);
+
+ /*
+ * Signer.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ isc_region_consume(&sr, name_length(&name));
+ RETERR(dns_name_towire(&name, cctx, target));
+
+ /*
+ * Signature.
+ */
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_sig(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 == 24);
+ 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));
+}
+
+static inline isc_result_t
+fromstruct_sig(ARGS_FROMSTRUCT) {
+ dns_rdata_sig_t *sig = source;
+
+ REQUIRE(type == 24);
+ REQUIRE(source != NULL);
+ REQUIRE(sig->common.rdtype == type);
+ REQUIRE(sig->common.rdclass == rdclass);
+ REQUIRE(sig->signature != NULL || sig->siglen == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Type covered.
+ */
+ RETERR(uint16_tobuffer(sig->covered, target));
+
+ /*
+ * Algorithm.
+ */
+ RETERR(uint8_tobuffer(sig->algorithm, target));
+
+ /*
+ * Labels.
+ */
+ RETERR(uint8_tobuffer(sig->labels, target));
+
+ /*
+ * Original TTL.
+ */
+ RETERR(uint32_tobuffer(sig->originalttl, target));
+
+ /*
+ * Expire time.
+ */
+ RETERR(uint32_tobuffer(sig->timeexpire, target));
+
+ /*
+ * Time signed.
+ */
+ RETERR(uint32_tobuffer(sig->timesigned, target));
+
+ /*
+ * Key ID.
+ */
+ RETERR(uint16_tobuffer(sig->keyid, target));
+
+ /*
+ * Signer name.
+ */
+ RETERR(name_tobuffer(&sig->signer, target));
+
+ /*
+ * Signature.
+ */
+ return (mem_tobuffer(target, sig->signature, sig->siglen));
+}
+
+static inline isc_result_t
+tostruct_sig(ARGS_TOSTRUCT) {
+ isc_region_t sr;
+ dns_rdata_sig_t *sig = target;
+ dns_name_t signer;
+
+ REQUIRE(rdata->type == 24);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ sig->common.rdclass = rdata->rdclass;
+ sig->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&sig->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Type covered.
+ */
+ sig->covered = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Algorithm.
+ */
+ sig->algorithm = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Labels.
+ */
+ sig->labels = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+
+ /*
+ * Original TTL.
+ */
+ sig->originalttl = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Expire time.
+ */
+ sig->timeexpire = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Time signed.
+ */
+ sig->timesigned = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Key ID.
+ */
+ sig->keyid = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ dns_name_init(&signer, NULL);
+ dns_name_fromregion(&signer, &sr);
+ dns_name_init(&sig->signer, NULL);
+ RETERR(name_duporclone(&signer, mctx, &sig->signer));
+ isc_region_consume(&sr, name_length(&sig->signer));
+
+ /*
+ * Signature.
+ */
+ sig->siglen = sr.length;
+ sig->signature = mem_maybedup(mctx, sr.base, sig->siglen);
+ if (sig->signature == NULL)
+ goto cleanup;
+
+
+ sig->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL)
+ dns_name_free(&sig->signer, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_sig(ARGS_FREESTRUCT) {
+ dns_rdata_sig_t *sig = (dns_rdata_sig_t *) source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(sig->common.rdtype == 24);
+
+ if (sig->mctx == NULL)
+ return;
+
+ dns_name_free(&sig->signer, sig->mctx);
+ if (sig->signature != NULL)
+ isc_mem_free(sig->mctx, sig->signature);
+ sig->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_sig(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 24);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_sig(ARGS_DIGEST) {
+
+ REQUIRE(rdata->type == 24);
+
+ UNUSED(rdata);
+ UNUSED(digest);
+ UNUSED(arg);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline dns_rdatatype_t
+covers_sig(dns_rdata_t *rdata) {
+ dns_rdatatype_t type;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 24);
+
+ dns_rdata_toregion(rdata, &r);
+ type = uint16_fromregion(&r);
+
+ return (type);
+}
+
+static inline isc_boolean_t
+checkowner_sig(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 24);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_sig(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 24);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_SIG_24_C */
diff --git a/lib/dns/rdata/generic/sig_24.h b/lib/dns/rdata/generic/sig_24.h
new file mode 100644
index 0000000..7212d4d
--- /dev/null
+++ b/lib/dns/rdata/generic/sig_24.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef GENERIC_SIG_24_H
+#define GENERIC_SIG_24_H 1
+
+/* $Id: sig_24.h,v 1.26 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC2535 */
+
+typedef struct dns_rdata_sig_t {
+ dns_rdatacommon_t common;
+ isc_mem_t * mctx;
+ dns_rdatatype_t covered;
+ dns_secalg_t algorithm;
+ isc_uint8_t labels;
+ isc_uint32_t originalttl;
+ isc_uint32_t timeexpire;
+ isc_uint32_t timesigned;
+ isc_uint16_t keyid;
+ dns_name_t signer;
+ isc_uint16_t siglen;
+ unsigned char * signature;
+} dns_rdata_sig_t;
+
+
+#endif /* GENERIC_SIG_24_H */
diff --git a/lib/dns/rdata/generic/soa_6.c b/lib/dns/rdata/generic/soa_6.c
new file mode 100644
index 0000000..b135adf
--- /dev/null
+++ b/lib/dns/rdata/generic/soa_6.c
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: soa_6.c,v 1.61 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 15:18:32 PST 2000 by explorer */
+
+#ifndef RDATA_GENERIC_SOA_6_C
+#define RDATA_GENERIC_SOA_6_C
+
+#define RRTYPE_SOA_ATTRIBUTES (DNS_RDATATYPEATTR_SINGLETON)
+
+static inline isc_result_t
+fromtext_soa(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ int i;
+ isc_uint32_t n;
+ isc_boolean_t ok;
+
+ REQUIRE(type == 6);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ origin = (origin != NULL) ? origin : dns_rootname;
+
+ for (i = 0; i < 2; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ RETTOK(dns_name_fromtext(&name, &buffer, origin,
+ options, target));
+ ok = ISC_TRUE;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0)
+ switch (i) {
+ case 0:
+ ok = dns_name_ishostname(&name, ISC_FALSE);
+ break;
+ case 1:
+ ok = dns_name_ismailbox(&name);
+ break;
+
+ }
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ }
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ for (i = 0; i < 4; i++) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string,
+ ISC_FALSE));
+ RETTOK(dns_counter_fromtext(&token.value.as_textregion, &n));
+ RETERR(uint32_tobuffer(n, target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static const char *soa_fieldnames[5] = {
+ "serial", "refresh", "retry", "expire", "minimum"
+};
+
+static inline isc_result_t
+totext_soa(ARGS_TOTEXT) {
+ isc_region_t dregion;
+ dns_name_t mname;
+ dns_name_t rname;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ int i;
+ isc_boolean_t multiline;
+ isc_boolean_t comment;
+
+ REQUIRE(rdata->type == 6);
+ REQUIRE(rdata->length != 0);
+
+ multiline = ISC_TF((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0);
+ comment = ISC_TF((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0);
+
+ dns_name_init(&mname, NULL);
+ dns_name_init(&rname, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &dregion);
+
+ dns_name_fromregion(&mname, &dregion);
+ isc_region_consume(&dregion, name_length(&mname));
+
+ dns_name_fromregion(&rname, &dregion);
+ isc_region_consume(&dregion, name_length(&rname));
+
+ sub = name_prefix(&mname, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ RETERR(str_totext(" ", target));
+
+ sub = name_prefix(&rname, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+
+ if (multiline)
+ RETERR(str_totext(" (" , target));
+ RETERR(str_totext(tctx->linebreak, target));
+
+ for (i = 0; i < 5; i++) {
+ char buf[sizeof("2147483647")];
+ unsigned long num;
+ unsigned int numlen;
+ num = uint32_fromregion(&dregion);
+ isc_region_consume(&dregion, 4);
+ numlen = sprintf(buf, "%lu", num);
+ INSIST(numlen > 0 && numlen < sizeof("2147483647"));
+ RETERR(str_totext(buf, target));
+ if (multiline && comment) {
+ RETERR(str_totext(" ; " + numlen, target));
+ RETERR(str_totext(soa_fieldnames[i], target));
+ /* Print times in week/day/hour/minute/second form */
+ if (i >= 1) {
+ RETERR(str_totext(" (", target));
+ RETERR(dns_ttl_totext(num, ISC_TRUE, target));
+ RETERR(str_totext(")", target));
+ }
+ RETERR(str_totext(tctx->linebreak, target));
+ } else if (i < 4) {
+ RETERR(str_totext(tctx->linebreak, target));
+ }
+ }
+
+ if (multiline)
+ RETERR(str_totext(")", target));
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_soa(ARGS_FROMWIRE) {
+ dns_name_t mname;
+ dns_name_t rname;
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ REQUIRE(type == 6);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&mname, NULL);
+ dns_name_init(&rname, NULL);
+
+ RETERR(dns_name_fromwire(&mname, source, dctx, options, target));
+ RETERR(dns_name_fromwire(&rname, source, dctx, options, target));
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+
+ if (sregion.length < 20)
+ return (ISC_R_UNEXPECTEDEND);
+ if (tregion.length < 20)
+ return (ISC_R_NOSPACE);
+
+ memcpy(tregion.base, sregion.base, 20);
+ isc_buffer_forward(source, 20);
+ isc_buffer_add(target, 20);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_soa(ARGS_TOWIRE) {
+ isc_region_t sregion;
+ isc_region_t tregion;
+ dns_name_t mname;
+ dns_name_t rname;
+ dns_offsets_t moffsets;
+ dns_offsets_t roffsets;
+
+ REQUIRE(rdata->type == 6);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+
+ dns_name_init(&mname, moffsets);
+ dns_name_init(&rname, roffsets);
+
+ dns_rdata_toregion(rdata, &sregion);
+
+ dns_name_fromregion(&mname, &sregion);
+ isc_region_consume(&sregion, name_length(&mname));
+ RETERR(dns_name_towire(&mname, cctx, target));
+
+ dns_name_fromregion(&rname, &sregion);
+ isc_region_consume(&sregion, name_length(&rname));
+ RETERR(dns_name_towire(&rname, cctx, target));
+
+ isc_buffer_availableregion(target, &tregion);
+ if (tregion.length < 20)
+ return (ISC_R_NOSPACE);
+
+ memcpy(tregion.base, sregion.base, 20);
+ isc_buffer_add(target, 20);
+ return (ISC_R_SUCCESS);
+}
+
+static inline int
+compare_soa(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 == 6);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ return (isc_region_compare(&region1, &region2));
+}
+
+static inline isc_result_t
+fromstruct_soa(ARGS_FROMSTRUCT) {
+ dns_rdata_soa_t *soa = source;
+ isc_region_t region;
+
+ REQUIRE(type == 6);
+ REQUIRE(source != NULL);
+ REQUIRE(soa->common.rdtype == type);
+ REQUIRE(soa->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&soa->origin, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ dns_name_toregion(&soa->contact, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ RETERR(uint32_tobuffer(soa->serial, target));
+ RETERR(uint32_tobuffer(soa->refresh, target));
+ RETERR(uint32_tobuffer(soa->retry, target));
+ RETERR(uint32_tobuffer(soa->expire, target));
+ return (uint32_tobuffer(soa->minimum, target));
+}
+
+static inline isc_result_t
+tostruct_soa(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_soa_t *soa = target;
+ dns_name_t name;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == 6);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ soa->common.rdclass = rdata->rdclass;
+ soa->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&soa->common, link);
+
+
+ dns_rdata_toregion(rdata, &region);
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_init(&soa->origin, NULL);
+ RETERR(name_duporclone(&name, mctx, &soa->origin));
+
+ dns_name_fromregion(&name, &region);
+ isc_region_consume(&region, name_length(&name));
+ dns_name_init(&soa->contact, NULL);
+ result = name_duporclone(&name, mctx, &soa->contact);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ soa->serial = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ soa->refresh = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ soa->retry = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ soa->expire = uint32_fromregion(&region);
+ isc_region_consume(&region, 4);
+
+ soa->minimum = uint32_fromregion(&region);
+
+ soa->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL)
+ dns_name_free(&soa->origin, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_soa(ARGS_FREESTRUCT) {
+ dns_rdata_soa_t *soa = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(soa->common.rdtype == 6);
+
+ if (soa->mctx == NULL)
+ return;
+
+ dns_name_free(&soa->origin, soa->mctx);
+ dns_name_free(&soa->contact, soa->mctx);
+ soa->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_soa(ARGS_ADDLDATA) {
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ REQUIRE(rdata->type == 6);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_soa(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 6);
+
+ dns_rdata_toregion(rdata, &r);
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ RETERR(dns_name_digest(&name, digest, arg));
+ isc_region_consume(&r, name_length(&name));
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ RETERR(dns_name_digest(&name, digest, arg));
+ isc_region_consume(&r, name_length(&name));
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_soa(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 6);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_soa(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 6);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, ISC_FALSE)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ isc_region_consume(&region, name_length(&name));
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ismailbox(&name)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_SOA_6_C */
diff --git a/lib/dns/rdata/generic/soa_6.h b/lib/dns/rdata/generic/soa_6.h
new file mode 100644
index 0000000..7443b04
--- /dev/null
+++ b/lib/dns/rdata/generic/soa_6.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_SOA_6_H
+#define GENERIC_SOA_6_H 1
+
+/* $Id: soa_6.h,v 1.32 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_soa {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t origin;
+ dns_name_t contact;
+ isc_uint32_t serial; /*%< host order */
+ isc_uint32_t refresh; /*%< host order */
+ isc_uint32_t retry; /*%< host order */
+ isc_uint32_t expire; /*%< host order */
+ isc_uint32_t minimum; /*%< host order */
+} dns_rdata_soa_t;
+
+
+#endif /* GENERIC_SOA_6_H */
diff --git a/lib/dns/rdata/generic/spf_99.c b/lib/dns/rdata/generic/spf_99.c
new file mode 100644
index 0000000..12e813e
--- /dev/null
+++ b/lib/dns/rdata/generic/spf_99.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: spf_99.c,v 1.4 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 15:40:00 PST 2000 by bwelling */
+
+#ifndef RDATA_GENERIC_SPF_99_C
+#define RDATA_GENERIC_SPF_99_C
+
+#define RRTYPE_SPF_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_spf(ARGS_FROMTEXT) {
+ isc_token_t token;
+ int strings;
+
+ REQUIRE(type == 99);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ strings = 0;
+ for (;;) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_qstring,
+ ISC_TRUE));
+ if (token.type != isc_tokentype_qstring &&
+ token.type != isc_tokentype_string)
+ break;
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ strings++;
+ }
+ /* Let upper layer handle eol/eof. */
+ isc_lex_ungettoken(lexer, &token);
+ return (strings == 0 ? ISC_R_UNEXPECTEDEND : ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_spf(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == 99);
+
+ dns_rdata_toregion(rdata, &region);
+
+ while (region.length > 0) {
+ RETERR(txt_totext(&region, target));
+ if (region.length > 0)
+ RETERR(str_totext(" ", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_spf(ARGS_FROMWIRE) {
+ isc_result_t result;
+
+ REQUIRE(type == 99);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ do {
+ result = txt_fromwire(source, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } while (!buffer_empty(source));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_spf(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 99);
+
+ UNUSED(cctx);
+
+ isc_buffer_availableregion(target, &region);
+ if (region.length < rdata->length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(region.base, rdata->data, rdata->length);
+ isc_buffer_add(target, rdata->length);
+ return (ISC_R_SUCCESS);
+}
+
+static inline int
+compare_spf(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 99);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_spf(ARGS_FROMSTRUCT) {
+ dns_rdata_spf_t *txt = source;
+ isc_region_t region;
+ isc_uint8_t length;
+
+ REQUIRE(type == 99);
+ REQUIRE(source != NULL);
+ REQUIRE(txt->common.rdtype == type);
+ REQUIRE(txt->common.rdclass == rdclass);
+ REQUIRE(txt->txt != NULL && txt->txt_len != 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ region.base = txt->txt;
+ region.length = txt->txt_len;
+ while (region.length > 0) {
+ length = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ if (region.length <= length)
+ return (ISC_R_UNEXPECTEDEND);
+ isc_region_consume(&region, length);
+ }
+
+ return (mem_tobuffer(target, txt->txt, txt->txt_len));
+}
+
+static inline isc_result_t
+tostruct_spf(ARGS_TOSTRUCT) {
+ dns_rdata_spf_t *txt = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 99);
+ REQUIRE(target != NULL);
+
+ txt->common.rdclass = rdata->rdclass;
+ txt->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&txt->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ txt->txt_len = r.length;
+ txt->txt = mem_maybedup(mctx, r.base, r.length);
+ if (txt->txt == NULL)
+ return (ISC_R_NOMEMORY);
+
+ txt->offset = 0;
+ txt->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_spf(ARGS_FREESTRUCT) {
+ dns_rdata_spf_t *txt = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(txt->common.rdtype == 99);
+
+ if (txt->mctx == NULL)
+ return;
+
+ if (txt->txt != NULL)
+ isc_mem_free(txt->mctx, txt->txt);
+ txt->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_spf(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 99);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_spf(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 99);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_spf(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 99);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_spf(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 99);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_SPF_99_C */
diff --git a/lib/dns/rdata/generic/spf_99.h b/lib/dns/rdata/generic/spf_99.h
new file mode 100644
index 0000000..be5e978
--- /dev/null
+++ b/lib/dns/rdata/generic/spf_99.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+#ifndef GENERIC_SPF_99_H
+#define GENERIC_SPF_99_H 1
+
+/* $Id: spf_99.h,v 1.4 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_spf_string {
+ isc_uint8_t length;
+ unsigned char *data;
+} dns_rdata_spf_string_t;
+
+typedef struct dns_rdata_spf {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *txt;
+ isc_uint16_t txt_len;
+ /* private */
+ isc_uint16_t offset;
+} dns_rdata_spf_t;
+
+/*
+ * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
+ * via rdatastructpre.h and rdatastructsuf.h.
+ */
+
+isc_result_t
+dns_rdata_spf_first(dns_rdata_spf_t *);
+
+isc_result_t
+dns_rdata_spf_next(dns_rdata_spf_t *);
+
+isc_result_t
+dns_rdata_spf_current(dns_rdata_spf_t *, dns_rdata_spf_string_t *);
+
+#endif /* GENERIC_SPF_99_H */
diff --git a/lib/dns/rdata/generic/sshfp_44.c b/lib/dns/rdata/generic/sshfp_44.c
new file mode 100644
index 0000000..570a3b7
--- /dev/null
+++ b/lib/dns/rdata/generic/sshfp_44.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: sshfp_44.c,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
+
+/* RFC 4255 */
+
+#ifndef RDATA_GENERIC_SSHFP_44_C
+#define RDATA_GENERIC_SSHFP_44_C
+
+#define RRTYPE_SSHFP_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_sshfp(ARGS_FROMTEXT) {
+ isc_token_t token;
+
+ REQUIRE(type == 44);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ /*
+ * 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));
+
+ /*
+ * Digest type.
+ */
+ 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));
+ type = (isc_uint16_t) token.value.as_ulong;
+
+ /*
+ * Digest.
+ */
+ return (isc_hex_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_sshfp(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof("64000 ")];
+ unsigned int n;
+
+ REQUIRE(rdata->type == 44);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Algorithm.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest type.
+ */
+ n = uint8_fromregion(&sr);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Digest.
+ */
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(isc_hex_totext(&sr, tctx->width - 2, tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_sshfp(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 44);
+
+ 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_sshfp(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 44);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_sshfp(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 44);
+ 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_sshfp(ARGS_FROMSTRUCT) {
+ dns_rdata_sshfp_t *sshfp = source;
+
+ REQUIRE(type == 44);
+ REQUIRE(source != NULL);
+ REQUIRE(sshfp->common.rdtype == type);
+ REQUIRE(sshfp->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint8_tobuffer(sshfp->algorithm, target));
+ RETERR(uint8_tobuffer(sshfp->digest_type, target));
+
+ return (mem_tobuffer(target, sshfp->digest, sshfp->length));
+}
+
+static inline isc_result_t
+tostruct_sshfp(ARGS_TOSTRUCT) {
+ dns_rdata_sshfp_t *sshfp = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 44);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ sshfp->common.rdclass = rdata->rdclass;
+ sshfp->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&sshfp->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ sshfp->algorithm = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ sshfp->digest_type = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ sshfp->length = region.length;
+
+ sshfp->digest = mem_maybedup(mctx, region.base, region.length);
+ if (sshfp->digest == NULL)
+ return (ISC_R_NOMEMORY);
+
+ sshfp->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_sshfp(ARGS_FREESTRUCT) {
+ dns_rdata_sshfp_t *sshfp = source;
+
+ REQUIRE(sshfp != NULL);
+ REQUIRE(sshfp->common.rdtype == 44);
+
+ if (sshfp->mctx == NULL)
+ return;
+
+ if (sshfp->digest != NULL)
+ isc_mem_free(sshfp->mctx, sshfp->digest);
+ sshfp->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_sshfp(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 44);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_sshfp(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 44);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_sshfp(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 44);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_sshfp(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 44);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_SSHFP_44_C */
diff --git a/lib/dns/rdata/generic/sshfp_44.h b/lib/dns/rdata/generic/sshfp_44.h
new file mode 100644
index 0000000..daea74c
--- /dev/null
+++ b/lib/dns/rdata/generic/sshfp_44.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: sshfp_44.h,v 1.8 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC 4255 */
+
+#ifndef GENERIC_SSHFP_44_H
+#define GENERIC_SSHFP_44_H 1
+
+typedef struct dns_rdata_sshfp {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint8_t algorithm;
+ isc_uint8_t digest_type;
+ isc_uint16_t length;
+ unsigned char *digest;
+} dns_rdata_sshfp_t;
+
+#endif /* GENERIC_SSHFP_44_H */
diff --git a/lib/dns/rdata/generic/tkey_249.c b/lib/dns/rdata/generic/tkey_249.c
new file mode 100644
index 0000000..2412c85
--- /dev/null
+++ b/lib/dns/rdata/generic/tkey_249.c
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: tkey_249.c,v 1.57 2007/06/19 23:47:17 tbox Exp $ */
+
+/*
+ * Reviewed: Thu Mar 16 17:35:30 PST 2000 by halley.
+ */
+
+/* draft-ietf-dnsext-tkey-01.txt */
+
+#ifndef RDATA_GENERIC_TKEY_249_C
+#define RDATA_GENERIC_TKEY_249_C
+
+#define RRTYPE_TKEY_ATTRIBUTES (DNS_RDATATYPEATTR_META)
+
+static inline isc_result_t
+fromtext_tkey(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_rcode_t rcode;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ long i;
+ char *e;
+
+ REQUIRE(type == 249);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Algorithm.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+
+ /*
+ * Inception.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Expiration.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ RETERR(uint32_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Mode.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Error.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ if (dns_tsigrcode_fromtext(&rcode, &token.value.as_textregion)
+ != ISC_R_SUCCESS)
+ {
+ i = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e != 0)
+ RETTOK(DNS_R_UNKNOWN);
+ if (i < 0 || i > 0xffff)
+ RETTOK(ISC_R_RANGE);
+ rcode = (dns_rcode_t)i;
+ }
+ RETERR(uint16_tobuffer(rcode, target));
+
+ /*
+ * Key Size.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Key Data.
+ */
+ RETERR(isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong));
+
+ /*
+ * Other Size.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Other Data.
+ */
+ return (isc_base64_tobuffer(lexer, target, (int)token.value.as_ulong));
+}
+
+static inline isc_result_t
+totext_tkey(ARGS_TOTEXT) {
+ isc_region_t sr, dr;
+ char buf[sizeof("4294967295 ")];
+ unsigned long n;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 249);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Algorithm.
+ */
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_name_fromregion(&name, &sr);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ RETERR(dns_name_totext(&prefix, sub, target));
+ RETERR(str_totext(" ", target));
+ isc_region_consume(&sr, name_length(&name));
+
+ /*
+ * Inception.
+ */
+ n = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ sprintf(buf, "%lu ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Expiration.
+ */
+ n = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+ sprintf(buf, "%lu ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Mode.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%lu ", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Error.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ if (dns_tsigrcode_totext((dns_rcode_t)n, target) == ISC_R_SUCCESS)
+ RETERR(str_totext(" ", target));
+ else {
+ sprintf(buf, "%lu ", n);
+ RETERR(str_totext(buf, target));
+ }
+
+ /*
+ * Key Size.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%lu", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Key Data.
+ */
+ REQUIRE(n <= sr.length);
+ dr = sr;
+ dr.length = n;
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(isc_base64_totext(&dr, tctx->width - 2,
+ tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" ) ", target));
+ else
+ RETERR(str_totext(" ", target));
+ isc_region_consume(&sr, n);
+
+ /*
+ * Other Size.
+ */
+ n = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ sprintf(buf, "%lu", n);
+ RETERR(str_totext(buf, target));
+
+ /*
+ * Other Data.
+ */
+ REQUIRE(n <= sr.length);
+ if (n != 0U) {
+ dr = sr;
+ dr.length = n;
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" (", target));
+ RETERR(str_totext(tctx->linebreak, target));
+ RETERR(isc_base64_totext(&dr, tctx->width - 2,
+ tctx->linebreak, target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext(" )", target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_tkey(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ unsigned long n;
+ dns_name_t name;
+
+ REQUIRE(type == 249);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ /*
+ * Algorithm.
+ */
+ dns_name_init(&name, NULL);
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ /*
+ * Inception: 4
+ * Expiration: 4
+ * Mode: 2
+ * Error: 2
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 12)
+ return (ISC_R_UNEXPECTEDEND);
+ RETERR(mem_tobuffer(target, sr.base, 12));
+ isc_region_consume(&sr, 12);
+ isc_buffer_forward(source, 12);
+
+ /*
+ * Key Length + Key Data.
+ */
+ if (sr.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ n = uint16_fromregion(&sr);
+ if (sr.length < n + 2)
+ return (ISC_R_UNEXPECTEDEND);
+ RETERR(mem_tobuffer(target, sr.base, n + 2));
+ isc_region_consume(&sr, n + 2);
+ isc_buffer_forward(source, n + 2);
+
+ /*
+ * Other Length + Other Data.
+ */
+ if (sr.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ n = uint16_fromregion(&sr);
+ if (sr.length < n + 2)
+ return (ISC_R_UNEXPECTEDEND);
+ isc_buffer_forward(source, n + 2);
+ return (mem_tobuffer(target, sr.base, n + 2));
+}
+
+static inline isc_result_t
+towire_tkey(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+
+ REQUIRE(rdata->type == 249);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ /*
+ * Algorithm.
+ */
+ dns_rdata_toregion(rdata, &sr);
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ RETERR(dns_name_towire(&name, cctx, target));
+ isc_region_consume(&sr, name_length(&name));
+
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_tkey(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 == 249);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ /*
+ * Algorithm.
+ */
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ dns_name_fromregion(&name1, &r1);
+ dns_name_fromregion(&name2, &r2);
+ if ((order = dns_name_rdatacompare(&name1, &name2)) != 0)
+ return (order);
+ isc_region_consume(&r1, name_length(&name1));
+ isc_region_consume(&r2, name_length(&name2));
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_tkey(ARGS_FROMSTRUCT) {
+ dns_rdata_tkey_t *tkey = source;
+
+ REQUIRE(type == 249);
+ REQUIRE(source != NULL);
+ REQUIRE(tkey->common.rdtype == type);
+ REQUIRE(tkey->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ /*
+ * Algorithm Name.
+ */
+ RETERR(name_tobuffer(&tkey->algorithm, target));
+
+ /*
+ * Inception: 32 bits.
+ */
+ RETERR(uint32_tobuffer(tkey->inception, target));
+
+ /*
+ * Expire: 32 bits.
+ */
+ RETERR(uint32_tobuffer(tkey->expire, target));
+
+ /*
+ * Mode: 16 bits.
+ */
+ RETERR(uint16_tobuffer(tkey->mode, target));
+
+ /*
+ * Error: 16 bits.
+ */
+ RETERR(uint16_tobuffer(tkey->error, target));
+
+ /*
+ * Key size: 16 bits.
+ */
+ RETERR(uint16_tobuffer(tkey->keylen, target));
+
+ /*
+ * Key.
+ */
+ RETERR(mem_tobuffer(target, tkey->key, tkey->keylen));
+
+ /*
+ * Other size: 16 bits.
+ */
+ RETERR(uint16_tobuffer(tkey->otherlen, target));
+
+ /*
+ * Other data.
+ */
+ return (mem_tobuffer(target, tkey->other, tkey->otherlen));
+}
+
+static inline isc_result_t
+tostruct_tkey(ARGS_TOSTRUCT) {
+ dns_rdata_tkey_t *tkey = target;
+ dns_name_t alg;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 249);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ tkey->common.rdclass = rdata->rdclass;
+ tkey->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&tkey->common, link);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ /*
+ * Algorithm Name.
+ */
+ dns_name_init(&alg, NULL);
+ dns_name_fromregion(&alg, &sr);
+ dns_name_init(&tkey->algorithm, NULL);
+ RETERR(name_duporclone(&alg, mctx, &tkey->algorithm));
+ isc_region_consume(&sr, name_length(&tkey->algorithm));
+
+ /*
+ * Inception.
+ */
+ tkey->inception = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Expire.
+ */
+ tkey->expire = uint32_fromregion(&sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Mode.
+ */
+ tkey->mode = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Error.
+ */
+ tkey->error = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Key size.
+ */
+ tkey->keylen = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Key.
+ */
+ tkey->key = mem_maybedup(mctx, sr.base, tkey->keylen);
+ if (tkey->key == NULL)
+ goto cleanup;
+ isc_region_consume(&sr, tkey->keylen);
+
+ /*
+ * Other size.
+ */
+ tkey->otherlen = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+
+ /*
+ * Other.
+ */
+ tkey->other = mem_maybedup(mctx, sr.base, tkey->otherlen);
+ if (tkey->other == NULL)
+ goto cleanup;
+
+ tkey->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL)
+ dns_name_free(&tkey->algorithm, mctx);
+ if (mctx != NULL && tkey->key != NULL)
+ isc_mem_free(mctx, tkey->key);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_tkey(ARGS_FREESTRUCT) {
+ dns_rdata_tkey_t *tkey = (dns_rdata_tkey_t *) source;
+
+ REQUIRE(source != NULL);
+
+ if (tkey->mctx == NULL)
+ return;
+
+ dns_name_free(&tkey->algorithm, tkey->mctx);
+ if (tkey->key != NULL)
+ isc_mem_free(tkey->mctx, tkey->key);
+ if (tkey->other != NULL)
+ isc_mem_free(tkey->mctx, tkey->other);
+ tkey->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_tkey(ARGS_ADDLDATA) {
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ REQUIRE(rdata->type == 249);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_tkey(ARGS_DIGEST) {
+ UNUSED(rdata);
+ UNUSED(digest);
+ UNUSED(arg);
+
+ REQUIRE(rdata->type == 249);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static inline isc_boolean_t
+checkowner_tkey(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 249);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_tkey(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 249);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_TKEY_249_C */
diff --git a/lib/dns/rdata/generic/tkey_249.h b/lib/dns/rdata/generic/tkey_249.h
new file mode 100644
index 0000000..34d5646
--- /dev/null
+++ b/lib/dns/rdata/generic/tkey_249.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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_TKEY_249_H
+#define GENERIC_TKEY_249_H 1
+
+/* $Id: tkey_249.h,v 1.24 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per draft-ietf-dnsind-tkey-00.txt */
+
+typedef struct dns_rdata_tkey {
+ dns_rdatacommon_t common;
+ isc_mem_t * mctx;
+ dns_name_t algorithm;
+ isc_uint32_t inception;
+ isc_uint32_t expire;
+ isc_uint16_t mode;
+ isc_uint16_t error;
+ isc_uint16_t keylen;
+ unsigned char * key;
+ isc_uint16_t otherlen;
+ unsigned char * other;
+} dns_rdata_tkey_t;
+
+
+#endif /* GENERIC_TKEY_249_H */
diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c
new file mode 100644
index 0000000..a158a59
--- /dev/null
+++ b/lib/dns/rdata/generic/txt_16.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: txt_16.c,v 1.45 2008/02/15 23:46:51 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 15:40:00 PST 2000 by bwelling */
+
+#ifndef RDATA_GENERIC_TXT_16_C
+#define RDATA_GENERIC_TXT_16_C
+
+#define RRTYPE_TXT_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_txt(ARGS_FROMTEXT) {
+ isc_token_t token;
+ int strings;
+
+ REQUIRE(type == 16);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ strings = 0;
+ for (;;) {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_qstring,
+ ISC_TRUE));
+ if (token.type != isc_tokentype_qstring &&
+ token.type != isc_tokentype_string)
+ break;
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ strings++;
+ }
+ /* Let upper layer handle eol/eof. */
+ isc_lex_ungettoken(lexer, &token);
+ return (strings == 0 ? ISC_R_UNEXPECTEDEND : ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_txt(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == 16);
+
+ dns_rdata_toregion(rdata, &region);
+
+ while (region.length > 0) {
+ RETERR(txt_totext(&region, target));
+ if (region.length > 0)
+ RETERR(str_totext(" ", target));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_txt(ARGS_FROMWIRE) {
+ isc_result_t result;
+
+ REQUIRE(type == 16);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ do {
+ result = txt_fromwire(source, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } while (!buffer_empty(source));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_txt(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 16);
+
+ UNUSED(cctx);
+
+ isc_buffer_availableregion(target, &region);
+ if (region.length < rdata->length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(region.base, rdata->data, rdata->length);
+ isc_buffer_add(target, rdata->length);
+ return (ISC_R_SUCCESS);
+}
+
+static inline int
+compare_txt(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 16);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_txt(ARGS_FROMSTRUCT) {
+ dns_rdata_txt_t *txt = source;
+ isc_region_t region;
+ isc_uint8_t length;
+
+ REQUIRE(type == 16);
+ REQUIRE(source != NULL);
+ REQUIRE(txt->common.rdtype == type);
+ REQUIRE(txt->common.rdclass == rdclass);
+ REQUIRE(txt->txt != NULL && txt->txt_len != 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ region.base = txt->txt;
+ region.length = txt->txt_len;
+ while (region.length > 0) {
+ length = uint8_fromregion(&region);
+ isc_region_consume(&region, 1);
+ if (region.length < length)
+ return (ISC_R_UNEXPECTEDEND);
+ isc_region_consume(&region, length);
+ }
+
+ return (mem_tobuffer(target, txt->txt, txt->txt_len));
+}
+
+static inline isc_result_t
+tostruct_txt(ARGS_TOSTRUCT) {
+ dns_rdata_txt_t *txt = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 16);
+ REQUIRE(target != NULL);
+
+ txt->common.rdclass = rdata->rdclass;
+ txt->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&txt->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ txt->txt_len = r.length;
+ txt->txt = mem_maybedup(mctx, r.base, r.length);
+ if (txt->txt == NULL)
+ return (ISC_R_NOMEMORY);
+
+ txt->offset = 0;
+ txt->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_txt(ARGS_FREESTRUCT) {
+ dns_rdata_txt_t *txt = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(txt->common.rdtype == 16);
+
+ if (txt->mctx == NULL)
+ return;
+
+ if (txt->txt != NULL)
+ isc_mem_free(txt->mctx, txt->txt);
+ txt->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_txt(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 16);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_txt(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 16);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_txt(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 16);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_txt(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 16);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_TXT_16_C */
diff --git a/lib/dns/rdata/generic/txt_16.h b/lib/dns/rdata/generic/txt_16.h
new file mode 100644
index 0000000..fc46486
--- /dev/null
+++ b/lib/dns/rdata/generic/txt_16.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef GENERIC_TXT_16_H
+#define GENERIC_TXT_16_H 1
+
+/* $Id: txt_16.h,v 1.28 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_txt_string {
+ isc_uint8_t length;
+ unsigned char *data;
+} dns_rdata_txt_string_t;
+
+typedef struct dns_rdata_txt {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *txt;
+ isc_uint16_t txt_len;
+ /* private */
+ isc_uint16_t offset;
+} dns_rdata_txt_t;
+
+/*
+ * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
+ * via rdatastructpre.h and rdatastructsuf.h.
+ */
+
+isc_result_t
+dns_rdata_txt_first(dns_rdata_txt_t *);
+
+isc_result_t
+dns_rdata_txt_next(dns_rdata_txt_t *);
+
+isc_result_t
+dns_rdata_txt_current(dns_rdata_txt_t *, dns_rdata_txt_string_t *);
+
+#endif /* GENERIC_TXT_16_H */
diff --git a/lib/dns/rdata/generic/unspec_103.c b/lib/dns/rdata/generic/unspec_103.c
new file mode 100644
index 0000000..384863e
--- /dev/null
+++ b/lib/dns/rdata/generic/unspec_103.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: unspec_103.c,v 1.35 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef RDATA_GENERIC_UNSPEC_103_C
+#define RDATA_GENERIC_UNSPEC_103_C
+
+#define RRTYPE_UNSPEC_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_unspec(ARGS_FROMTEXT) {
+
+ REQUIRE(type == 103);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ return (atob_tobuffer(lexer, target));
+}
+
+static inline isc_result_t
+totext_unspec(ARGS_TOTEXT) {
+
+ REQUIRE(rdata->type == 103);
+
+ UNUSED(tctx);
+
+ return (btoa_totext(rdata->data, rdata->length, target));
+}
+
+static inline isc_result_t
+fromwire_unspec(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 103);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_unspec(ARGS_TOWIRE) {
+
+ REQUIRE(rdata->type == 103);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static inline int
+compare_unspec(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 103);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_unspec(ARGS_FROMSTRUCT) {
+ dns_rdata_unspec_t *unspec = source;
+
+ REQUIRE(type == 103);
+ REQUIRE(source != NULL);
+ REQUIRE(unspec->common.rdtype == type);
+ REQUIRE(unspec->common.rdclass == rdclass);
+ REQUIRE(unspec->data != NULL || unspec->datalen == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, unspec->data, unspec->datalen));
+}
+
+static inline isc_result_t
+tostruct_unspec(ARGS_TOSTRUCT) {
+ dns_rdata_unspec_t *unspec = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 103);
+ REQUIRE(target != NULL);
+
+ unspec->common.rdclass = rdata->rdclass;
+ unspec->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&unspec->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ unspec->datalen = r.length;
+ unspec->data = mem_maybedup(mctx, r.base, r.length);
+ if (unspec->data == NULL)
+ return (ISC_R_NOMEMORY);
+
+ unspec->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_unspec(ARGS_FREESTRUCT) {
+ dns_rdata_unspec_t *unspec = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(unspec->common.rdtype == 103);
+
+ if (unspec->mctx == NULL)
+ return;
+
+ if (unspec->data != NULL)
+ isc_mem_free(unspec->mctx, unspec->data);
+ unspec->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_unspec(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 103);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_unspec(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 103);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_unspec(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 103);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_unspec(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 103);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_UNSPEC_103_C */
diff --git a/lib/dns/rdata/generic/unspec_103.h b/lib/dns/rdata/generic/unspec_103.h
new file mode 100644
index 0000000..4b2d310
--- /dev/null
+++ b/lib/dns/rdata/generic/unspec_103.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+/* */
+#ifndef GENERIC_UNSPEC_103_H
+#define GENERIC_UNSPEC_103_H 1
+
+/* $Id: unspec_103.h,v 1.17 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_unspec_t {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *data;
+ isc_uint16_t datalen;
+} dns_rdata_unspec_t;
+
+#endif /* GENERIC_UNSPEC_103_H */
diff --git a/lib/dns/rdata/generic/x25_19.c b/lib/dns/rdata/generic/x25_19.c
new file mode 100644
index 0000000..c496aaf
--- /dev/null
+++ b/lib/dns/rdata/generic/x25_19.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: x25_19.c,v 1.39 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 16:15:57 PST 2000 by bwelling */
+
+/* RFC1183 */
+
+#ifndef RDATA_GENERIC_X25_19_C
+#define RDATA_GENERIC_X25_19_C
+
+#define RRTYPE_X25_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_x25(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned int i;
+
+ REQUIRE(type == 19);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ ISC_FALSE));
+ if (token.value.as_textregion.length < 4)
+ RETTOK(DNS_R_SYNTAX);
+ for (i = 0; i < token.value.as_textregion.length; i++)
+ if (!isdigit(token.value.as_textregion.base[i] & 0xff))
+ RETTOK(ISC_R_RANGE);
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_x25(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == 19);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &region);
+ return (txt_totext(&region, target));
+}
+
+static inline isc_result_t
+fromwire_x25(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 19);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 5)
+ return (DNS_R_FORMERR);
+ return (txt_fromwire(source, target));
+}
+
+static inline isc_result_t
+towire_x25(ARGS_TOWIRE) {
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == 19);
+ REQUIRE(rdata->length != 0);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static inline int
+compare_x25(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 19);
+ 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_x25(ARGS_FROMSTRUCT) {
+ dns_rdata_x25_t *x25 = source;
+ isc_uint8_t i;
+
+ REQUIRE(type == 19);
+ REQUIRE(source != NULL);
+ REQUIRE(x25->common.rdtype == type);
+ REQUIRE(x25->common.rdclass == rdclass);
+ REQUIRE(x25->x25 != NULL && x25->x25_len != 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ if (x25->x25_len < 4)
+ return (ISC_R_RANGE);
+
+ for (i = 0; i < x25->x25_len; i++)
+ if (!isdigit(x25->x25[i] & 0xff))
+ return (ISC_R_RANGE);
+
+ RETERR(uint8_tobuffer(x25->x25_len, target));
+ return (mem_tobuffer(target, x25->x25, x25->x25_len));
+}
+
+static inline isc_result_t
+tostruct_x25(ARGS_TOSTRUCT) {
+ dns_rdata_x25_t *x25 = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 19);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ x25->common.rdclass = rdata->rdclass;
+ x25->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&x25->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ x25->x25_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ x25->x25 = mem_maybedup(mctx, r.base, x25->x25_len);
+ if (x25->x25 == NULL)
+ return (ISC_R_NOMEMORY);
+
+ x25->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_x25(ARGS_FREESTRUCT) {
+ dns_rdata_x25_t *x25 = source;
+ REQUIRE(source != NULL);
+ REQUIRE(x25->common.rdtype == 19);
+
+ if (x25->mctx == NULL)
+ return;
+
+ if (x25->x25 != NULL)
+ isc_mem_free(x25->mctx, x25->x25);
+ x25->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_x25(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 19);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_x25(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 19);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_x25(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 19);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_x25(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 19);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_GENERIC_X25_19_C */
diff --git a/lib/dns/rdata/generic/x25_19.h b/lib/dns/rdata/generic/x25_19.h
new file mode 100644
index 0000000..5ebc230
--- /dev/null
+++ b/lib/dns/rdata/generic/x25_19.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef GENERIC_X25_19_H
+#define GENERIC_X25_19_H 1
+
+/* $Id: x25_19.h,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC1183 */
+
+typedef struct dns_rdata_x25 {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *x25;
+ isc_uint8_t x25_len;
+} dns_rdata_x25_t;
+
+#endif /* GENERIC_X25_19_H */
diff --git a/lib/dns/rdata/hs_4/a_1.c b/lib/dns/rdata/hs_4/a_1.c
new file mode 100644
index 0000000..487e8bc
--- /dev/null
+++ b/lib/dns/rdata/hs_4/a_1.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: a_1.c,v 1.31 2007/06/19 23:47:17 tbox Exp $ */
+
+/* reviewed: Thu Mar 16 15:58:36 PST 2000 by brister */
+
+#ifndef RDATA_HS_4_A_1_C
+#define RDATA_HS_4_A_1_C
+
+#include <isc/net.h>
+
+#define RRTYPE_A_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_hs_a(ARGS_FROMTEXT) {
+ isc_token_t token;
+ struct in_addr addr;
+ isc_region_t region;
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == 4);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1)
+ RETTOK(DNS_R_BADDOTTEDQUAD);
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 4)
+ return (ISC_R_NOSPACE);
+ memcpy(region.base, &addr, 4);
+ isc_buffer_add(target, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_hs_a(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 4);
+ REQUIRE(rdata->length == 4);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (inet_totext(AF_INET, &region, target));
+}
+
+static inline isc_result_t
+fromwire_hs_a(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == 4);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+ if (sregion.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+ if (tregion.length < 4)
+ return (ISC_R_NOSPACE);
+
+ memcpy(tregion.base, sregion.base, 4);
+ isc_buffer_forward(source, 4);
+ isc_buffer_add(target, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_hs_a(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 4);
+ REQUIRE(rdata->length == 4);
+
+ UNUSED(cctx);
+
+ isc_buffer_availableregion(target, &region);
+ if (region.length < rdata->length)
+ return (ISC_R_NOSPACE);
+ memcpy(region.base, rdata->data, rdata->length);
+ isc_buffer_add(target, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static inline int
+compare_hs_a(ARGS_COMPARE) {
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 1);
+ REQUIRE(rdata1->rdclass == 4);
+ REQUIRE(rdata1->length == 4);
+ REQUIRE(rdata2->length == 4);
+
+ order = memcmp(rdata1->data, rdata2->data, 4);
+ if (order != 0)
+ order = (order < 0) ? -1 : 1;
+
+ return (order);
+}
+
+static inline isc_result_t
+fromstruct_hs_a(ARGS_FROMSTRUCT) {
+ dns_rdata_hs_a_t *a = source;
+ isc_uint32_t n;
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == 4);
+ REQUIRE(source != NULL);
+ REQUIRE(a->common.rdtype == type);
+ REQUIRE(a->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ n = ntohl(a->in_addr.s_addr);
+
+ return (uint32_tobuffer(n, target));
+}
+
+static inline isc_result_t
+tostruct_hs_a(ARGS_TOSTRUCT) {
+ dns_rdata_hs_a_t *a = target;
+ isc_uint32_t n;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 4);
+ REQUIRE(rdata->length == 4);
+
+ UNUSED(mctx);
+
+ a->common.rdclass = rdata->rdclass;
+ a->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&a->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ n = uint32_fromregion(&region);
+ a->in_addr.s_addr = htonl(n);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_hs_a(ARGS_FREESTRUCT) {
+ UNUSED(source);
+
+ REQUIRE(source != NULL);
+}
+
+static inline isc_result_t
+additionaldata_hs_a(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 4);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_hs_a(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 4);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_hs_a(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == 4);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_hs_a(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 4);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_HS_4_A_1_C */
diff --git a/lib/dns/rdata/hs_4/a_1.h b/lib/dns/rdata/hs_4/a_1.h
new file mode 100644
index 0000000..dee812f
--- /dev/null
+++ b/lib/dns/rdata/hs_4/a_1.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+/* */
+#ifndef HS_4_A_1_H
+#define HS_4_A_1_H 1
+
+/* $Id: a_1.h,v 1.12 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_hs_a {
+ dns_rdatacommon_t common;
+ struct in_addr in_addr;
+} dns_rdata_hs_a_t;
+
+#endif /* HS_4_A_1_H */
diff --git a/lib/dns/rdata/in_1/a6_38.c b/lib/dns/rdata/in_1/a6_38.c
new file mode 100644
index 0000000..d4d42bb
--- /dev/null
+++ b/lib/dns/rdata/in_1/a6_38.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: a6_38.c,v 1.54 2007/06/19 23:47:17 tbox Exp $ */
+
+/* RFC2874 */
+
+#ifndef RDATA_IN_1_A6_28_C
+#define RDATA_IN_1_A6_28_C
+
+#include <isc/net.h>
+
+#define RRTYPE_A6_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_a6(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char addr[16];
+ unsigned char prefixlen;
+ unsigned char octets;
+ unsigned char mask;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ isc_boolean_t ok;
+
+ REQUIRE(type == 38);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Prefix length.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 128U)
+ RETTOK(ISC_R_RANGE);
+
+ prefixlen = (unsigned char)token.value.as_ulong;
+ RETERR(mem_tobuffer(target, &prefixlen, 1));
+
+ /*
+ * Suffix.
+ */
+ if (prefixlen != 128) {
+ /*
+ * Prefix 0..127.
+ */
+ octets = prefixlen/8;
+ /*
+ * Octets 0..15.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string,
+ ISC_FALSE));
+ if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1)
+ RETTOK(DNS_R_BADAAAA);
+ mask = 0xff >> (prefixlen % 8);
+ addr[octets] &= mask;
+ RETERR(mem_tobuffer(target, &addr[octets], 16 - octets));
+ }
+
+ if (prefixlen == 0)
+ return (ISC_R_SUCCESS);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ ok = ISC_TRUE;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0)
+ ok = dns_name_ishostname(&name, ISC_FALSE);
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_in_a6(ARGS_TOTEXT) {
+ isc_region_t sr, ar;
+ unsigned char addr[16];
+ unsigned char prefixlen;
+ unsigned char octets;
+ unsigned char mask;
+ char buf[sizeof("128")];
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 38);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+ prefixlen = sr.base[0];
+ INSIST(prefixlen <= 128);
+ isc_region_consume(&sr, 1);
+ sprintf(buf, "%u", prefixlen);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ if (prefixlen != 128) {
+ octets = prefixlen/8;
+ memset(addr, 0, sizeof(addr));
+ memcpy(&addr[octets], sr.base, 16 - octets);
+ mask = 0xff >> (prefixlen % 8);
+ addr[octets] &= mask;
+ ar.base = addr;
+ ar.length = sizeof(addr);
+ RETERR(inet_totext(AF_INET6, &ar, target));
+ isc_region_consume(&sr, 16 - octets);
+ }
+
+ if (prefixlen == 0)
+ return (ISC_R_SUCCESS);
+
+ RETERR(str_totext(" ", target));
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+ dns_name_fromregion(&name, &sr);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_in_a6(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ unsigned char prefixlen;
+ unsigned char octets;
+ unsigned char mask;
+ dns_name_t name;
+
+ REQUIRE(type == 38);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ isc_buffer_activeregion(source, &sr);
+ /*
+ * Prefix length.
+ */
+ if (sr.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+ prefixlen = sr.base[0];
+ if (prefixlen > 128)
+ return (ISC_R_RANGE);
+ isc_region_consume(&sr, 1);
+ RETERR(mem_tobuffer(target, &prefixlen, 1));
+ isc_buffer_forward(source, 1);
+
+ /*
+ * Suffix.
+ */
+ if (prefixlen != 128) {
+ octets = 16 - prefixlen / 8;
+ if (sr.length < octets)
+ return (ISC_R_UNEXPECTEDEND);
+ mask = 0xff >> (prefixlen % 8);
+ sr.base[0] &= mask; /* Ensure pad bits are zero. */
+ RETERR(mem_tobuffer(target, sr.base, octets));
+ isc_buffer_forward(source, octets);
+ }
+
+ if (prefixlen == 0)
+ return (ISC_R_SUCCESS);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_in_a6(ARGS_TOWIRE) {
+ isc_region_t sr;
+ dns_name_t name;
+ dns_offsets_t offsets;
+ unsigned char prefixlen;
+ unsigned char octets;
+
+ REQUIRE(rdata->type == 38);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_rdata_toregion(rdata, &sr);
+ prefixlen = sr.base[0];
+ INSIST(prefixlen <= 128);
+
+ octets = 1 + 16 - prefixlen / 8;
+ RETERR(mem_tobuffer(target, sr.base, octets));
+ isc_region_consume(&sr, octets);
+
+ if (prefixlen == 0)
+ return (ISC_R_SUCCESS);
+
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_in_a6(ARGS_COMPARE) {
+ int order;
+ unsigned char prefixlen1, prefixlen2;
+ unsigned char octets;
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 38);
+ REQUIRE(rdata1->rdclass == 1);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+ prefixlen1 = region1.base[0];
+ prefixlen2 = region2.base[0];
+ isc_region_consume(&region1, 1);
+ isc_region_consume(&region2, 1);
+ if (prefixlen1 < prefixlen2)
+ return (-1);
+ else if (prefixlen1 > prefixlen2)
+ return (1);
+ /*
+ * Prefix lengths are equal.
+ */
+ octets = 16 - prefixlen1 / 8;
+
+ if (octets > 0) {
+ order = memcmp(region1.base, region2.base, octets);
+ if (order < 0)
+ return (-1);
+ else if (order > 0)
+ return (1);
+ /*
+ * Address suffixes are equal.
+ */
+ if (prefixlen1 == 0)
+ return (order);
+ isc_region_consume(&region1, octets);
+ isc_region_consume(&region2, octets);
+ }
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_in_a6(ARGS_FROMSTRUCT) {
+ dns_rdata_in_a6_t *a6 = source;
+ isc_region_t region;
+ int octets;
+ isc_uint8_t bits;
+ isc_uint8_t first;
+ isc_uint8_t mask;
+
+ REQUIRE(type == 38);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(a6->common.rdtype == type);
+ REQUIRE(a6->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ if (a6->prefixlen > 128)
+ return (ISC_R_RANGE);
+
+ RETERR(uint8_tobuffer(a6->prefixlen, target));
+
+ /* Suffix */
+ if (a6->prefixlen != 128) {
+ octets = 16 - a6->prefixlen / 8;
+ bits = a6->prefixlen % 8;
+ if (bits != 0) {
+ mask = 0xffU >> bits;
+ first = a6->in6_addr.s6_addr[16 - octets] & mask;
+ RETERR(uint8_tobuffer(first, target));
+ octets--;
+ }
+ if (octets > 0)
+ RETERR(mem_tobuffer(target,
+ a6->in6_addr.s6_addr + 16 - octets,
+ octets));
+ }
+
+ if (a6->prefixlen == 0)
+ return (ISC_R_SUCCESS);
+ dns_name_toregion(&a6->prefix, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_in_a6(ARGS_TOSTRUCT) {
+ dns_rdata_in_a6_t *a6 = target;
+ unsigned char octets;
+ dns_name_t name;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 38);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ a6->common.rdclass = rdata->rdclass;
+ a6->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&a6->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+
+ a6->prefixlen = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ memset(a6->in6_addr.s6_addr, 0, sizeof(a6->in6_addr.s6_addr));
+
+ /*
+ * Suffix.
+ */
+ if (a6->prefixlen != 128) {
+ octets = 16 - a6->prefixlen / 8;
+ INSIST(r.length >= octets);
+ memcpy(a6->in6_addr.s6_addr + 16 - octets, r.base, octets);
+ isc_region_consume(&r, octets);
+ }
+
+ /*
+ * Prefix.
+ */
+ dns_name_init(&a6->prefix, NULL);
+ if (a6->prefixlen != 0) {
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ RETERR(name_duporclone(&name, mctx, &a6->prefix));
+ }
+ a6->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_a6(ARGS_FREESTRUCT) {
+ dns_rdata_in_a6_t *a6 = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(a6->common.rdclass == 1);
+ REQUIRE(a6->common.rdtype == 38);
+
+ if (a6->mctx == NULL)
+ return;
+
+ if (dns_name_dynamic(&a6->prefix))
+ dns_name_free(&a6->prefix, a6->mctx);
+ a6->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_in_a6(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 38);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_a6(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ unsigned char prefixlen, octets;
+ isc_result_t result;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 38);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ prefixlen = r1.base[0];
+ octets = 1 + 16 - prefixlen / 8;
+
+ r1.length = octets;
+ result = (digest)(arg, &r1);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (prefixlen == 0)
+ return (ISC_R_SUCCESS);
+
+ isc_region_consume(&r2, octets);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_in_a6(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 38);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static inline isc_boolean_t
+checknames_in_a6(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+ unsigned int prefixlen;
+
+ REQUIRE(rdata->type == 38);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ prefixlen = uint8_fromregion(&region);
+ if (prefixlen == 0)
+ return (ISC_TRUE);
+ isc_region_consume(&region, 1 + 16 - prefixlen / 8);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, ISC_FALSE)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_A6_38_C */
diff --git a/lib/dns/rdata/in_1/a6_38.h b/lib/dns/rdata/in_1/a6_38.h
new file mode 100644
index 0000000..75e53f1
--- /dev/null
+++ b/lib/dns/rdata/in_1/a6_38.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef IN_1_A6_38_H
+#define IN_1_A6_38_H 1
+
+/* $Id: a6_38.h,v 1.24 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC2874 */
+
+typedef struct dns_rdata_in_a6 {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t prefix;
+ isc_uint8_t prefixlen;
+ struct in6_addr in6_addr;
+} dns_rdata_in_a6_t;
+
+#endif /* IN_1_A6_38_H */
diff --git a/lib/dns/rdata/in_1/a_1.c b/lib/dns/rdata/in_1/a_1.c
new file mode 100644
index 0000000..d7644bc
--- /dev/null
+++ b/lib/dns/rdata/in_1/a_1.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: a_1.c,v 1.53 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
+
+#ifndef RDATA_IN_1_A_1_C
+#define RDATA_IN_1_A_1_C
+
+#include <string.h>
+
+#include <isc/net.h>
+
+#define RRTYPE_A_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_a(ARGS_FROMTEXT) {
+ isc_token_t token;
+ struct in_addr addr;
+ isc_region_t region;
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1)
+ RETTOK(DNS_R_BADDOTTEDQUAD);
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 4)
+ return (ISC_R_NOSPACE);
+ memcpy(region.base, &addr, 4);
+ isc_buffer_add(target, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_in_a(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length == 4);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ return (inet_totext(AF_INET, &region, target));
+}
+
+static inline isc_result_t
+fromwire_in_a(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+ if (sregion.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+ if (tregion.length < 4)
+ return (ISC_R_NOSPACE);
+
+ memcpy(tregion.base, sregion.base, 4);
+ isc_buffer_forward(source, 4);
+ isc_buffer_add(target, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_in_a(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length == 4);
+
+ UNUSED(cctx);
+
+ isc_buffer_availableregion(target, &region);
+ if (region.length < rdata->length)
+ return (ISC_R_NOSPACE);
+ memcpy(region.base, rdata->data, rdata->length);
+ isc_buffer_add(target, 4);
+ return (ISC_R_SUCCESS);
+}
+
+static inline int
+compare_in_a(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 1);
+ REQUIRE(rdata1->rdclass == 1);
+ REQUIRE(rdata1->length == 4);
+ REQUIRE(rdata2->length == 4);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_in_a(ARGS_FROMSTRUCT) {
+ dns_rdata_in_a_t *a = source;
+ isc_uint32_t n;
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(a->common.rdtype == type);
+ REQUIRE(a->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ n = ntohl(a->in_addr.s_addr);
+
+ return (uint32_tobuffer(n, target));
+}
+
+
+static inline isc_result_t
+tostruct_in_a(ARGS_TOSTRUCT) {
+ dns_rdata_in_a_t *a = target;
+ isc_uint32_t n;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length == 4);
+
+ UNUSED(mctx);
+
+ a->common.rdclass = rdata->rdclass;
+ a->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&a->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ n = uint32_fromregion(&region);
+ a->in_addr.s_addr = htonl(n);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_a(ARGS_FREESTRUCT) {
+ dns_rdata_in_a_t *a = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(a->common.rdtype == 1);
+ REQUIRE(a->common.rdclass == 1);
+
+ UNUSED(a);
+}
+
+static inline isc_result_t
+additionaldata_in_a(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_a(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_in_a(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 1);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static inline isc_boolean_t
+checknames_in_a(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 1);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_A_1_C */
diff --git a/lib/dns/rdata/in_1/a_1.h b/lib/dns/rdata/in_1/a_1.h
new file mode 100644
index 0000000..c192d1a
--- /dev/null
+++ b/lib/dns/rdata/in_1/a_1.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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.
+ */
+
+/* */
+#ifndef IN_1_A_1_H
+#define IN_1_A_1_H 1
+
+/* $Id: a_1.h,v 1.28 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_in_a {
+ dns_rdatacommon_t common;
+ struct in_addr in_addr;
+} dns_rdata_in_a_t;
+
+#endif /* IN_1_A_1_H */
diff --git a/lib/dns/rdata/in_1/aaaa_28.c b/lib/dns/rdata/in_1/aaaa_28.c
new file mode 100644
index 0000000..d0503a9
--- /dev/null
+++ b/lib/dns/rdata/in_1/aaaa_28.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: aaaa_28.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
+
+/* RFC1886 */
+
+#ifndef RDATA_IN_1_AAAA_28_C
+#define RDATA_IN_1_AAAA_28_C
+
+#include <isc/net.h>
+
+#define RRTYPE_AAAA_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_aaaa(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char addr[16];
+ isc_region_t region;
+
+ REQUIRE(type == 28);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1)
+ RETTOK(DNS_R_BADAAAA);
+ isc_buffer_availableregion(target, &region);
+ if (region.length < 16)
+ return (ISC_R_NOSPACE);
+ memcpy(region.base, addr, 16);
+ isc_buffer_add(target, 16);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_in_aaaa(ARGS_TOTEXT) {
+ isc_region_t region;
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == 28);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length == 16);
+
+ dns_rdata_toregion(rdata, &region);
+ return (inet_totext(AF_INET6, &region, target));
+}
+
+static inline isc_result_t
+fromwire_in_aaaa(ARGS_FROMWIRE) {
+ isc_region_t sregion;
+ isc_region_t tregion;
+
+ REQUIRE(type == 28);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &sregion);
+ isc_buffer_availableregion(target, &tregion);
+ if (sregion.length < 16)
+ return (ISC_R_UNEXPECTEDEND);
+ if (tregion.length < 16)
+ return (ISC_R_NOSPACE);
+
+ memcpy(tregion.base, sregion.base, 16);
+ isc_buffer_forward(source, 16);
+ isc_buffer_add(target, 16);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_in_aaaa(ARGS_TOWIRE) {
+ isc_region_t region;
+
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == 28);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length == 16);
+
+ isc_buffer_availableregion(target, &region);
+ if (region.length < rdata->length)
+ return (ISC_R_NOSPACE);
+ memcpy(region.base, rdata->data, rdata->length);
+ isc_buffer_add(target, 16);
+ return (ISC_R_SUCCESS);
+}
+
+static inline int
+compare_in_aaaa(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 28);
+ REQUIRE(rdata1->rdclass == 1);
+ REQUIRE(rdata1->length == 16);
+ REQUIRE(rdata2->length == 16);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_in_aaaa(ARGS_FROMSTRUCT) {
+ dns_rdata_in_aaaa_t *aaaa = source;
+
+ REQUIRE(type == 28);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(aaaa->common.rdtype == type);
+ REQUIRE(aaaa->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, aaaa->in6_addr.s6_addr, 16));
+}
+
+static inline isc_result_t
+tostruct_in_aaaa(ARGS_TOSTRUCT) {
+ dns_rdata_in_aaaa_t *aaaa = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 28);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length == 16);
+
+ UNUSED(mctx);
+
+ aaaa->common.rdclass = rdata->rdclass;
+ aaaa->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&aaaa->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ INSIST(r.length == 16);
+ memcpy(aaaa->in6_addr.s6_addr, r.base, 16);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_aaaa(ARGS_FREESTRUCT) {
+ dns_rdata_in_aaaa_t *aaaa = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(aaaa->common.rdclass == 1);
+ REQUIRE(aaaa->common.rdtype == 28);
+
+ UNUSED(aaaa);
+}
+
+static inline isc_result_t
+additionaldata_in_aaaa(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 28);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_aaaa(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 28);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_in_aaaa(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 28);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static inline isc_boolean_t
+checknames_in_aaaa(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 28);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_AAAA_28_C */
diff --git a/lib/dns/rdata/in_1/aaaa_28.h b/lib/dns/rdata/in_1/aaaa_28.h
new file mode 100644
index 0000000..54a0cb3
--- /dev/null
+++ b/lib/dns/rdata/in_1/aaaa_28.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef IN_1_AAAA_28_H
+#define IN_1_AAAA_28_H 1
+
+/* $Id: aaaa_28.h,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC1886 */
+
+typedef struct dns_rdata_in_aaaa {
+ dns_rdatacommon_t common;
+ struct in6_addr in6_addr;
+} dns_rdata_in_aaaa_t;
+
+#endif /* IN_1_AAAA_28_H */
diff --git a/lib/dns/rdata/in_1/apl_42.c b/lib/dns/rdata/in_1/apl_42.c
new file mode 100644
index 0000000..28ca68e
--- /dev/null
+++ b/lib/dns/rdata/in_1/apl_42.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: apl_42.c,v 1.14 2008/01/22 23:28:04 tbox Exp $ */
+
+/* RFC3123 */
+
+#ifndef RDATA_IN_1_APL_42_C
+#define RDATA_IN_1_APL_42_C
+
+#define RRTYPE_APL_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_apl(ARGS_FROMTEXT) {
+ isc_token_t token;
+ unsigned char addr[16];
+ unsigned long afi;
+ isc_uint8_t prefix;
+ isc_uint8_t len;
+ isc_boolean_t neg;
+ char *cp, *ap, *slash;
+ int n;
+
+ REQUIRE(type == 42);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ do {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, ISC_TRUE));
+ if (token.type != isc_tokentype_string)
+ break;
+
+ cp = DNS_AS_STR(token);
+ neg = ISC_TF(*cp == '!');
+ if (neg)
+ cp++;
+ afi = strtoul(cp, &ap, 10);
+ if (*ap++ != ':' || cp == ap)
+ RETTOK(DNS_R_SYNTAX);
+ if (afi > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ slash = strchr(ap, '/');
+ if (slash == NULL || slash == ap)
+ RETTOK(DNS_R_SYNTAX);
+ RETTOK(isc_parse_uint8(&prefix, slash + 1, 10));
+ switch (afi) {
+ case 1:
+ *slash = '\0';
+ n = inet_pton(AF_INET, ap, addr);
+ *slash = '/';
+ if (n != 1)
+ RETTOK(DNS_R_BADDOTTEDQUAD);
+ if (prefix > 32)
+ RETTOK(ISC_R_RANGE);
+ for (len = 4; len > 0; len--)
+ if (addr[len - 1] != 0)
+ break;
+ break;
+
+ case 2:
+ *slash = '\0';
+ n = inet_pton(AF_INET6, ap, addr);
+ *slash = '/';
+ if (n != 1)
+ RETTOK(DNS_R_BADAAAA);
+ if (prefix > 128)
+ RETTOK(ISC_R_RANGE);
+ for (len = 16; len > 0; len--)
+ if (addr[len - 1] != 0)
+ break;
+ break;
+
+ default:
+ RETTOK(ISC_R_NOTIMPLEMENTED);
+ }
+ RETERR(uint16_tobuffer(afi, target));
+ RETERR(uint8_tobuffer(prefix, target));
+ RETERR(uint8_tobuffer(len | ((neg) ? 0x80 : 0), target));
+ RETERR(mem_tobuffer(target, addr, len));
+ } while (1);
+
+ /*
+ * Let upper layer handle eol/eof.
+ */
+ isc_lex_ungettoken(lexer, &token);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_in_apl(ARGS_TOTEXT) {
+ isc_region_t sr;
+ isc_region_t ir;
+ isc_uint16_t afi;
+ isc_uint8_t prefix;
+ isc_uint8_t len;
+ isc_boolean_t neg;
+ unsigned char buf[16];
+ char txt[sizeof(" !64000")];
+ const char *sep = "";
+ int n;
+
+ REQUIRE(rdata->type == 42);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ ir.base = buf;
+ ir.length = sizeof(buf);
+
+ while (sr.length > 0) {
+ INSIST(sr.length >= 4);
+ afi = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ prefix = *sr.base;
+ isc_region_consume(&sr, 1);
+ len = (*sr.base & 0x7f);
+ neg = ISC_TF((*sr.base & 0x80) != 0);
+ isc_region_consume(&sr, 1);
+ INSIST(len <= sr.length);
+ n = snprintf(txt, sizeof(txt), "%s%s%u:", sep,
+ neg ? "!": "", afi);
+ INSIST(n < (int)sizeof(txt));
+ RETERR(str_totext(txt, target));
+ switch (afi) {
+ case 1:
+ INSIST(len <= 4);
+ INSIST(prefix <= 32);
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, sr.base, len);
+ RETERR(inet_totext(AF_INET, &ir, target));
+ break;
+
+ case 2:
+ INSIST(len <= 16);
+ INSIST(prefix <= 128);
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, sr.base, len);
+ RETERR(inet_totext(AF_INET6, &ir, target));
+ break;
+
+ default:
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+ n = snprintf(txt, sizeof(txt), "/%u", prefix);
+ INSIST(n < (int)sizeof(txt));
+ RETERR(str_totext(txt, target));
+ isc_region_consume(&sr, len);
+ sep = " ";
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_in_apl(ARGS_FROMWIRE) {
+ isc_region_t sr, sr2;
+ isc_region_t tr;
+ isc_uint16_t afi;
+ isc_uint8_t prefix;
+ isc_uint8_t len;
+
+ REQUIRE(type == 42);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(rdclass);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_availableregion(target, &tr);
+ if (sr.length > tr.length)
+ return (ISC_R_NOSPACE);
+ sr2 = sr;
+
+ /* Zero or more items */
+ while (sr.length > 0) {
+ if (sr.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+ afi = uint16_fromregion(&sr);
+ isc_region_consume(&sr, 2);
+ prefix = *sr.base;
+ isc_region_consume(&sr, 1);
+ len = (*sr.base & 0x7f);
+ isc_region_consume(&sr, 1);
+ if (len > sr.length)
+ return (ISC_R_UNEXPECTEDEND);
+ switch (afi) {
+ case 1:
+ if (prefix > 32 || len > 4)
+ return (ISC_R_RANGE);
+ break;
+ case 2:
+ if (prefix > 128 || len > 16)
+ return (ISC_R_RANGE);
+ }
+ if (len > 0 && sr.base[len - 1] == 0)
+ return (DNS_R_FORMERR);
+ isc_region_consume(&sr, len);
+ }
+ isc_buffer_forward(source, sr2.length);
+ return (mem_tobuffer(target, sr2.base, sr2.length));
+}
+
+static inline isc_result_t
+towire_in_apl(ARGS_TOWIRE) {
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == 42);
+ REQUIRE(rdata->rdclass == 1);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static inline int
+compare_in_apl(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 42);
+ REQUIRE(rdata1->rdclass == 1);
+
+ dns_rdata_toregion(rdata1, &r1);
+ dns_rdata_toregion(rdata2, &r2);
+ return (isc_region_compare(&r1, &r2));
+}
+
+static inline isc_result_t
+fromstruct_in_apl(ARGS_FROMSTRUCT) {
+ dns_rdata_in_apl_t *apl = source;
+ isc_buffer_t b;
+
+ REQUIRE(type == 42);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(apl->common.rdtype == type);
+ REQUIRE(apl->common.rdclass == rdclass);
+ REQUIRE(apl->apl != NULL || apl->apl_len == 0);
+
+ isc_buffer_init(&b, apl->apl, apl->apl_len);
+ isc_buffer_add(&b, apl->apl_len);
+ isc_buffer_setactive(&b, apl->apl_len);
+ return(fromwire_in_apl(rdclass, type, &b, NULL, ISC_FALSE, target));
+}
+
+static inline isc_result_t
+tostruct_in_apl(ARGS_TOSTRUCT) {
+ dns_rdata_in_apl_t *apl = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 42);
+ REQUIRE(rdata->rdclass == 1);
+
+ apl->common.rdclass = rdata->rdclass;
+ apl->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&apl->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ apl->apl_len = r.length;
+ apl->apl = mem_maybedup(mctx, r.base, r.length);
+ if (apl->apl == NULL)
+ return (ISC_R_NOMEMORY);
+
+ apl->offset = 0;
+ apl->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_apl(ARGS_FREESTRUCT) {
+ dns_rdata_in_apl_t *apl = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(apl->common.rdtype == 42);
+ REQUIRE(apl->common.rdclass == 1);
+
+ if (apl->mctx == NULL)
+ return;
+ if (apl->apl != NULL)
+ isc_mem_free(apl->mctx, apl->apl);
+ apl->mctx = NULL;
+}
+
+isc_result_t
+dns_rdata_apl_first(dns_rdata_in_apl_t *apl) {
+ isc_uint32_t length;
+
+ REQUIRE(apl != NULL);
+ REQUIRE(apl->common.rdtype == 42);
+ REQUIRE(apl->common.rdclass == 1);
+ REQUIRE(apl->apl != NULL || apl->apl_len == 0);
+
+ /*
+ * If no APL return ISC_R_NOMORE.
+ */
+ if (apl->apl == NULL)
+ return (ISC_R_NOMORE);
+
+ /*
+ * Sanity check data.
+ */
+ INSIST(apl->apl_len > 3U);
+ length = apl->apl[apl->offset + 3] & 0x7f;
+ INSIST(length <= apl->apl_len);
+
+ apl->offset = 0;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdata_apl_next(dns_rdata_in_apl_t *apl) {
+ isc_uint32_t length;
+
+ REQUIRE(apl != NULL);
+ REQUIRE(apl->common.rdtype == 42);
+ REQUIRE(apl->common.rdclass == 1);
+ REQUIRE(apl->apl != NULL || apl->apl_len == 0);
+
+ /*
+ * No APL or have already reached the end return ISC_R_NOMORE.
+ */
+ if (apl->apl == NULL || apl->offset == apl->apl_len)
+ return (ISC_R_NOMORE);
+
+ /*
+ * Sanity check data.
+ */
+ INSIST(apl->offset < apl->apl_len);
+ INSIST(apl->apl_len > 3U);
+ INSIST(apl->offset <= apl->apl_len - 4U);
+ length = apl->apl[apl->offset + 3] & 0x7f;
+ /*
+ * 16 to 32 bits promotion as 'length' is 32 bits so there is
+ * no overflow problems.
+ */
+ INSIST(length + apl->offset <= apl->apl_len);
+
+ apl->offset += apl->apl[apl->offset + 3] & 0x7f;
+ return ((apl->offset >= apl->apl_len) ? ISC_R_SUCCESS : ISC_R_NOMORE);
+}
+
+isc_result_t
+dns_rdata_apl_current(dns_rdata_in_apl_t *apl, dns_rdata_apl_ent_t *ent) {
+ isc_uint32_t length;
+
+ REQUIRE(apl != NULL);
+ REQUIRE(apl->common.rdtype == 42);
+ REQUIRE(apl->common.rdclass == 1);
+ REQUIRE(ent != NULL);
+ REQUIRE(apl->apl != NULL || apl->apl_len == 0);
+ REQUIRE(apl->offset <= apl->apl_len);
+
+ if (apl->offset == apl->apl_len)
+ return (ISC_R_NOMORE);
+
+ /*
+ * Sanity check data.
+ */
+ INSIST(apl->apl_len > 3U);
+ INSIST(apl->offset <= apl->apl_len - 4U);
+ length = apl->apl[apl->offset + 3] & 0x7f;
+ /*
+ * 16 to 32 bits promotion as 'length' is 32 bits so there is
+ * no overflow problems.
+ */
+ INSIST(length + apl->offset <= apl->apl_len);
+
+ ent->family = (apl->apl[apl->offset] << 8) + apl->apl[apl->offset + 1];
+ ent->prefix = apl->apl[apl->offset + 2];
+ ent->length = apl->apl[apl->offset + 3] & 0x7f;
+ ent->negative = ISC_TF((apl->apl[apl->offset + 3] & 0x80) != 0);
+ if (ent->length != 0)
+ ent->data = &apl->apl[apl->offset + 4];
+ else
+ ent->data = NULL;
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+additionaldata_in_apl(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 42);
+ REQUIRE(rdata->rdclass == 1);
+
+ (void)add;
+ (void)arg;
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_apl(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 42);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_in_apl(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 42);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+
+static inline isc_boolean_t
+checknames_in_apl(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 42);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_APL_42_C */
diff --git a/lib/dns/rdata/in_1/apl_42.h b/lib/dns/rdata/in_1/apl_42.h
new file mode 100644
index 0000000..2d01040
--- /dev/null
+++ b/lib/dns/rdata/in_1/apl_42.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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.
+ */
+
+/* */
+#ifndef IN_1_APL_42_H
+#define IN_1_APL_42_H 1
+
+/* $Id: apl_42.h,v 1.6 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_apl_ent {
+ isc_boolean_t negative;
+ isc_uint16_t family;
+ isc_uint8_t prefix;
+ isc_uint8_t length;
+ unsigned char *data;
+} dns_rdata_apl_ent_t;
+
+typedef struct dns_rdata_in_apl {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ /* type & class specific elements */
+ unsigned char *apl;
+ isc_uint16_t apl_len;
+ /* private */
+ isc_uint16_t offset;
+} dns_rdata_in_apl_t;
+
+/*
+ * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done
+ * via rdatastructpre.h and rdatastructsuf.h.
+ */
+
+isc_result_t
+dns_rdata_apl_first(dns_rdata_in_apl_t *);
+
+isc_result_t
+dns_rdata_apl_next(dns_rdata_in_apl_t *);
+
+isc_result_t
+dns_rdata_apl_current(dns_rdata_in_apl_t *, dns_rdata_apl_ent_t *);
+
+#endif /* IN_1_APL_42_H */
diff --git a/lib/dns/rdata/in_1/dhcid_49.c b/lib/dns/rdata/in_1/dhcid_49.c
new file mode 100644
index 0000000..27c4e4e
--- /dev/null
+++ b/lib/dns/rdata/in_1/dhcid_49.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2006, 2007 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: dhcid_49.c,v 1.5 2007/06/19 23:47:17 tbox Exp $ */
+
+/* RFC 4701 */
+
+#ifndef RDATA_IN_1_DHCID_49_C
+#define RDATA_IN_1_DHCID_49_C 1
+
+#define RRTYPE_DHCID_ATTRIBUTES 0
+
+static inline isc_result_t
+fromtext_in_dhcid(ARGS_FROMTEXT) {
+
+ REQUIRE(type == 49);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(callbacks);
+
+ return (isc_base64_tobuffer(lexer, target, -1));
+}
+
+static inline isc_result_t
+totext_in_dhcid(ARGS_TOTEXT) {
+ isc_region_t sr;
+ char buf[sizeof(" ; 64000 255 64000")];
+ size_t n;
+
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
+ RETERR(str_totext("( " /*)*/, target));
+ RETERR(isc_base64_totext(&sr, tctx->width - 2, tctx->linebreak,
+ target));
+ if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
+ RETERR(str_totext(/* ( */ " )", target));
+ if (rdata->length > 2) {
+ n = snprintf(buf, sizeof(buf), " ; %u %u %u",
+ sr.base[0] * 256 + sr.base[1],
+ sr.base[2], rdata->length - 3);
+ INSIST(n < sizeof(buf));
+ RETERR(str_totext(buf, target));
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_in_dhcid(ARGS_FROMWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(type == 49);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(dctx);
+ UNUSED(options);
+
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length == 0)
+ return (ISC_R_UNEXPECTEDEND);
+
+ isc_buffer_forward(source, sr.length);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline isc_result_t
+towire_in_dhcid(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_in_dhcid(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 49);
+ REQUIRE(rdata1->rdclass == 1);
+ 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_in_dhcid(ARGS_FROMSTRUCT) {
+ dns_rdata_in_dhcid_t *dhcid = source;
+
+ REQUIRE(type == 49);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(dhcid->common.rdtype == type);
+ REQUIRE(dhcid->common.rdclass == rdclass);
+ REQUIRE(dhcid->length != 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, dhcid->dhcid, dhcid->length));
+}
+
+static inline isc_result_t
+tostruct_in_dhcid(ARGS_TOSTRUCT) {
+ dns_rdata_in_dhcid_t *dhcid = target;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ dhcid->common.rdclass = rdata->rdclass;
+ dhcid->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&dhcid->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+
+ dhcid->dhcid = mem_maybedup(mctx, region.base, region.length);
+ if (dhcid->dhcid == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dhcid->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_dhcid(ARGS_FREESTRUCT) {
+ dns_rdata_in_dhcid_t *dhcid = source;
+
+ REQUIRE(dhcid != NULL);
+ REQUIRE(dhcid->common.rdtype == 49);
+ REQUIRE(dhcid->common.rdclass == 1);
+
+ if (dhcid->mctx == NULL)
+ return;
+
+ if (dhcid->dhcid != NULL)
+ isc_mem_free(dhcid->mctx, dhcid->dhcid);
+ dhcid->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_in_dhcid(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_dhcid(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_in_dhcid(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 49);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_in_dhcid(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 49);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_DHCID_49_C */
diff --git a/lib/dns/rdata/in_1/dhcid_49.h b/lib/dns/rdata/in_1/dhcid_49.h
new file mode 100644
index 0000000..2797192
--- /dev/null
+++ b/lib/dns/rdata/in_1/dhcid_49.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2006, 2007 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 IN_1_DHCID_49_H
+#define IN_1_DHCID_49_H 1
+
+/* $Id: dhcid_49.h,v 1.5 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_in_dhcid {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *dhcid;
+ unsigned int length;
+} dns_rdata_in_dhcid_t;
+
+#endif /* IN_1_DHCID_49_H */
diff --git a/lib/dns/rdata/in_1/kx_36.c b/lib/dns/rdata/in_1/kx_36.c
new file mode 100644
index 0000000..9df2e5e
--- /dev/null
+++ b/lib/dns/rdata/in_1/kx_36.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: kx_36.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 17:24:54 PST 2000 by explorer */
+
+/* RFC2230 */
+
+#ifndef RDATA_IN_1_KX_36_C
+#define RDATA_IN_1_KX_36_C
+
+#define RRTYPE_KX_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_kx(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 36);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_in_kx(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ char buf[sizeof("64000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == 36);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ sprintf(buf, "%u", num);
+ RETERR(str_totext(buf, target));
+
+ RETERR(str_totext(" ", target));
+
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_in_kx(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sregion;
+
+ REQUIRE(type == 36);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ RETERR(mem_tobuffer(target, sregion.base, 2));
+ isc_buffer_forward(source, 2);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_in_kx(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 36);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_rdata_toregion(rdata, &region);
+ RETERR(mem_tobuffer(target, region.base, 2));
+ isc_region_consume(&region, 2);
+
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_in_kx(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 36);
+ REQUIRE(rdata1->rdclass == 1);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ order = memcmp(rdata1->data, rdata2->data, 2);
+ if (order != 0)
+ return (order < 0 ? -1 : 1);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 2);
+ isc_region_consume(&region2, 2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_in_kx(ARGS_FROMSTRUCT) {
+ dns_rdata_in_kx_t *kx = source;
+ isc_region_t region;
+
+ REQUIRE(type == 36);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(kx->common.rdtype == type);
+ REQUIRE(kx->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(kx->preference, target));
+ dns_name_toregion(&kx->exchange, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_in_kx(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_in_kx_t *kx = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 36);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ kx->common.rdclass = rdata->rdclass;
+ kx->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&kx->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+
+ kx->preference = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&kx->exchange, NULL);
+ RETERR(name_duporclone(&name, mctx, &kx->exchange));
+ kx->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_kx(ARGS_FREESTRUCT) {
+ dns_rdata_in_kx_t *kx = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(kx->common.rdclass == 1);
+ REQUIRE(kx->common.rdtype == 36);
+
+ if (kx->mctx == NULL)
+ return;
+
+ dns_name_free(&kx->exchange, kx->mctx);
+ kx->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_in_kx(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 36);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a));
+}
+
+static inline isc_result_t
+digest_in_kx(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 36);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ isc_region_consume(&r2, 2);
+ r1.length = 2;
+ RETERR((digest)(arg, &r1));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_in_kx(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 36);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_in_kx(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 36);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_KX_36_C */
diff --git a/lib/dns/rdata/in_1/kx_36.h b/lib/dns/rdata/in_1/kx_36.h
new file mode 100644
index 0000000..391ae27
--- /dev/null
+++ b/lib/dns/rdata/in_1/kx_36.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef IN_1_KX_36_H
+#define IN_1_KX_36_H 1
+
+/* $Id: kx_36.h,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC2230 */
+
+typedef struct dns_rdata_in_kx {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t preference;
+ dns_name_t exchange;
+} dns_rdata_in_kx_t;
+
+#endif /* IN_1_KX_36_H */
diff --git a/lib/dns/rdata/in_1/naptr_35.c b/lib/dns/rdata/in_1/naptr_35.c
new file mode 100644
index 0000000..21ab44c
--- /dev/null
+++ b/lib/dns/rdata/in_1/naptr_35.c
@@ -0,0 +1,578 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 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
+ * 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: naptr_35.c,v 1.53 2008/02/15 23:46:51 tbox Exp $ */
+
+/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
+
+/* RFC2915 */
+
+#ifndef RDATA_IN_1_NAPTR_35_C
+#define RDATA_IN_1_NAPTR_35_C
+
+#define RRTYPE_NAPTR_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_naptr(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 35);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Order.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Preference.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Flags.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ ISC_FALSE));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+
+ /*
+ * Service.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ ISC_FALSE));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+
+ /*
+ * Regexp.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring,
+ ISC_FALSE));
+ RETTOK(txt_fromtext(&token.value.as_textregion, target));
+
+ /*
+ * Replacement.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_in_naptr(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ char buf[sizeof("64000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == 35);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+
+ /*
+ * Order.
+ */
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ sprintf(buf, "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Preference.
+ */
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ sprintf(buf, "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Flags.
+ */
+ RETERR(txt_totext(&region, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Service.
+ */
+ RETERR(txt_totext(&region, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Regexp.
+ */
+ RETERR(txt_totext(&region, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Replacement.
+ */
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_in_naptr(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sr;
+
+ REQUIRE(type == 35);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ /*
+ * Order, preference.
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 4)
+ return (ISC_R_UNEXPECTEDEND);
+ RETERR(mem_tobuffer(target, sr.base, 4));
+ isc_buffer_forward(source, 4);
+
+ /*
+ * Flags.
+ */
+ RETERR(txt_fromwire(source, target));
+
+ /*
+ * Service.
+ */
+ RETERR(txt_fromwire(source, target));
+
+ /*
+ * Regexp.
+ */
+ RETERR(txt_fromwire(source, target));
+
+ /*
+ * Replacement.
+ */
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_in_naptr(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 35);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ /*
+ * Order, preference.
+ */
+ dns_rdata_toregion(rdata, &sr);
+ RETERR(mem_tobuffer(target, sr.base, 4));
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Flags.
+ */
+ RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
+ isc_region_consume(&sr, sr.base[0] + 1);
+
+ /*
+ * Service.
+ */
+ RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
+ isc_region_consume(&sr, sr.base[0] + 1);
+
+ /*
+ * Regexp.
+ */
+ RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1));
+ isc_region_consume(&sr, sr.base[0] + 1);
+
+ /*
+ * Replacement.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_in_naptr(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order, len;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 35);
+ REQUIRE(rdata1->rdclass == 1);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ /*
+ * Order, preference.
+ */
+ order = memcmp(region1.base, region2.base, 4);
+ if (order != 0)
+ return (order < 0 ? -1 : 1);
+ isc_region_consume(&region1, 4);
+ isc_region_consume(&region2, 4);
+
+ /*
+ * Flags.
+ */
+ len = ISC_MIN(region1.base[0], region2.base[0]);
+ order = memcmp(region1.base, region2.base, len + 1);
+ if (order != 0)
+ return (order < 0 ? -1 : 1);
+ isc_region_consume(&region1, region1.base[0] + 1);
+ isc_region_consume(&region2, region2.base[0] + 1);
+
+ /*
+ * Service.
+ */
+ len = ISC_MIN(region1.base[0], region2.base[0]);
+ order = memcmp(region1.base, region2.base, len + 1);
+ if (order != 0)
+ return (order < 0 ? -1 : 1);
+ isc_region_consume(&region1, region1.base[0] + 1);
+ isc_region_consume(&region2, region2.base[0] + 1);
+
+ /*
+ * Regexp.
+ */
+ len = ISC_MIN(region1.base[0], region2.base[0]);
+ order = memcmp(region1.base, region2.base, len + 1);
+ if (order != 0)
+ return (order < 0 ? -1 : 1);
+ isc_region_consume(&region1, region1.base[0] + 1);
+ isc_region_consume(&region2, region2.base[0] + 1);
+
+ /*
+ * Replacement.
+ */
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_in_naptr(ARGS_FROMSTRUCT) {
+ dns_rdata_in_naptr_t *naptr = source;
+ isc_region_t region;
+
+ REQUIRE(type == 35);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(naptr->common.rdtype == type);
+ REQUIRE(naptr->common.rdclass == rdclass);
+ REQUIRE(naptr->flags != NULL || naptr->flags_len == 0);
+ REQUIRE(naptr->service != NULL || naptr->service_len == 0);
+ REQUIRE(naptr->regexp != NULL || naptr->regexp_len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(naptr->order, target));
+ RETERR(uint16_tobuffer(naptr->preference, target));
+ RETERR(uint8_tobuffer(naptr->flags_len, target));
+ RETERR(mem_tobuffer(target, naptr->flags, naptr->flags_len));
+ RETERR(uint8_tobuffer(naptr->service_len, target));
+ RETERR(mem_tobuffer(target, naptr->service, naptr->service_len));
+ RETERR(uint8_tobuffer(naptr->regexp_len, target));
+ RETERR(mem_tobuffer(target, naptr->regexp, naptr->regexp_len));
+ dns_name_toregion(&naptr->replacement, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_in_naptr(ARGS_TOSTRUCT) {
+ dns_rdata_in_naptr_t *naptr = target;
+ isc_region_t r;
+ isc_result_t result;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 35);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ naptr->common.rdclass = rdata->rdclass;
+ naptr->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&naptr->common, link);
+
+ naptr->flags = NULL;
+ naptr->service = NULL;
+ naptr->regexp = NULL;
+
+ dns_rdata_toregion(rdata, &r);
+
+ naptr->order = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+
+ naptr->preference = uint16_fromregion(&r);
+ isc_region_consume(&r, 2);
+
+ naptr->flags_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ INSIST(naptr->flags_len <= r.length);
+ naptr->flags = mem_maybedup(mctx, r.base, naptr->flags_len);
+ if (naptr->flags == NULL)
+ goto cleanup;
+ isc_region_consume(&r, naptr->flags_len);
+
+ naptr->service_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ INSIST(naptr->service_len <= r.length);
+ naptr->service = mem_maybedup(mctx, r.base, naptr->service_len);
+ if (naptr->service == NULL)
+ goto cleanup;
+ isc_region_consume(&r, naptr->service_len);
+
+ naptr->regexp_len = uint8_fromregion(&r);
+ isc_region_consume(&r, 1);
+ INSIST(naptr->regexp_len <= r.length);
+ naptr->regexp = mem_maybedup(mctx, r.base, naptr->regexp_len);
+ if (naptr->regexp == NULL)
+ goto cleanup;
+ isc_region_consume(&r, naptr->regexp_len);
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+ dns_name_init(&naptr->replacement, NULL);
+ result = name_duporclone(&name, mctx, &naptr->replacement);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ naptr->mctx = mctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (mctx != NULL && naptr->flags != NULL)
+ isc_mem_free(mctx, naptr->flags);
+ if (mctx != NULL && naptr->service != NULL)
+ isc_mem_free(mctx, naptr->service);
+ if (mctx != NULL && naptr->regexp != NULL)
+ isc_mem_free(mctx, naptr->regexp);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_in_naptr(ARGS_FREESTRUCT) {
+ dns_rdata_in_naptr_t *naptr = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(naptr->common.rdclass == 1);
+ REQUIRE(naptr->common.rdtype == 35);
+
+ if (naptr->mctx == NULL)
+ return;
+
+ if (naptr->flags != NULL)
+ isc_mem_free(naptr->mctx, naptr->flags);
+ if (naptr->service != NULL)
+ isc_mem_free(naptr->mctx, naptr->service);
+ if (naptr->regexp != NULL)
+ isc_mem_free(naptr->mctx, naptr->regexp);
+ dns_name_free(&naptr->replacement, naptr->mctx);
+ naptr->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_in_naptr(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t sr;
+ dns_rdatatype_t atype;
+ unsigned int i, flagslen;
+ char *cp;
+
+ REQUIRE(rdata->type == 35);
+ REQUIRE(rdata->rdclass == 1);
+
+ /*
+ * Order, preference.
+ */
+ dns_rdata_toregion(rdata, &sr);
+ isc_region_consume(&sr, 4);
+
+ /*
+ * Flags.
+ */
+ atype = 0;
+ flagslen = sr.base[0];
+ cp = (char *)&sr.base[1];
+ for (i = 0; i < flagslen; i++, cp++) {
+ if (*cp == 'S' || *cp == 's') {
+ atype = dns_rdatatype_srv;
+ break;
+ }
+ if (*cp == 'A' || *cp == 'a') {
+ atype = dns_rdatatype_a;
+ break;
+ }
+ }
+ isc_region_consume(&sr, flagslen + 1);
+
+ /*
+ * Service.
+ */
+ isc_region_consume(&sr, sr.base[0] + 1);
+
+ /*
+ * Regexp.
+ */
+ isc_region_consume(&sr, sr.base[0] + 1);
+
+ /*
+ * Replacement.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+
+ if (atype != 0)
+ return ((add)(arg, &name, atype));
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_naptr(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ unsigned int length, n;
+ isc_result_t result;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 35);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ length = 0;
+
+ /*
+ * Order, preference.
+ */
+ length += 4;
+ isc_region_consume(&r2, 4);
+
+ /*
+ * Flags.
+ */
+ n = r2.base[0] + 1;
+ length += n;
+ isc_region_consume(&r2, n);
+
+ /*
+ * Service.
+ */
+ n = r2.base[0] + 1;
+ length += n;
+ isc_region_consume(&r2, n);
+
+ /*
+ * Regexp.
+ */
+ n = r2.base[0] + 1;
+ length += n;
+ isc_region_consume(&r2, n);
+
+ /*
+ * Digest the RR up to the replacement name.
+ */
+ r1.length = length;
+ result = (digest)(arg, &r1);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Replacement.
+ */
+
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_in_naptr(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 35);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_in_naptr(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 35);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_NAPTR_35_C */
diff --git a/lib/dns/rdata/in_1/naptr_35.h b/lib/dns/rdata/in_1/naptr_35.h
new file mode 100644
index 0000000..503f7a8
--- /dev/null
+++ b/lib/dns/rdata/in_1/naptr_35.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef IN_1_NAPTR_35_H
+#define IN_1_NAPTR_35_H 1
+
+/* $Id: naptr_35.h,v 1.23 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC2915 */
+
+typedef struct dns_rdata_in_naptr {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t order;
+ isc_uint16_t preference;
+ char *flags;
+ isc_uint8_t flags_len;
+ char *service;
+ isc_uint8_t service_len;
+ char *regexp;
+ isc_uint8_t regexp_len;
+ dns_name_t replacement;
+} dns_rdata_in_naptr_t;
+
+#endif /* IN_1_NAPTR_35_H */
diff --git a/lib/dns/rdata/in_1/nsap-ptr_23.c b/lib/dns/rdata/in_1/nsap-ptr_23.c
new file mode 100644
index 0000000..2da7869
--- /dev/null
+++ b/lib/dns/rdata/in_1/nsap-ptr_23.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: nsap-ptr_23.c,v 1.38 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Fri Mar 17 10:16:02 PST 2000 by gson */
+
+/* RFC1348. Obsoleted in RFC 1706 - use PTR instead. */
+
+#ifndef RDATA_IN_1_NSAP_PTR_23_C
+#define RDATA_IN_1_NSAP_PTR_23_C
+
+#define RRTYPE_NSAP_PTR_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_nsap_ptr(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 23);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_in_nsap_ptr(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+
+ REQUIRE(rdata->type == 23);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ sub = name_prefix(&name, tctx->origin, &prefix);
+
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_in_nsap_ptr(ARGS_FROMWIRE) {
+ dns_name_t name;
+
+ REQUIRE(type == 23);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_in_nsap_ptr(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 23);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_in_nsap_ptr(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 23);
+ REQUIRE(rdata1->rdclass == 1);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_in_nsap_ptr(ARGS_FROMSTRUCT) {
+ dns_rdata_in_nsap_ptr_t *nsap_ptr = source;
+ isc_region_t region;
+
+ REQUIRE(type == 23);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(nsap_ptr->common.rdtype == type);
+ REQUIRE(nsap_ptr->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_name_toregion(&nsap_ptr->owner, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_in_nsap_ptr(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_in_nsap_ptr_t *nsap_ptr = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 23);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsap_ptr->common.rdclass = rdata->rdclass;
+ nsap_ptr->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsap_ptr->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&nsap_ptr->owner, NULL);
+ RETERR(name_duporclone(&name, mctx, &nsap_ptr->owner));
+ nsap_ptr->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_nsap_ptr(ARGS_FREESTRUCT) {
+ dns_rdata_in_nsap_ptr_t *nsap_ptr = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(nsap_ptr->common.rdclass == 1);
+ REQUIRE(nsap_ptr->common.rdtype == 23);
+
+ if (nsap_ptr->mctx == NULL)
+ return;
+
+ dns_name_free(&nsap_ptr->owner, nsap_ptr->mctx);
+ nsap_ptr->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_in_nsap_ptr(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 23);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_nsap_ptr(ARGS_DIGEST) {
+ isc_region_t r;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 23);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_in_nsap_ptr(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 23);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_in_nsap_ptr(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 23);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_NSAP_PTR_23_C */
diff --git a/lib/dns/rdata/in_1/nsap-ptr_23.h b/lib/dns/rdata/in_1/nsap-ptr_23.h
new file mode 100644
index 0000000..14a8b19
--- /dev/null
+++ b/lib/dns/rdata/in_1/nsap-ptr_23.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef IN_1_NSAP_PTR_23_H
+#define IN_1_NSAP_PTR_23_H 1
+
+/* $Id: nsap-ptr_23.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC1348. Obsoleted in RFC 1706 - use PTR instead. */
+
+typedef struct dns_rdata_in_nsap_ptr {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ dns_name_t owner;
+} dns_rdata_in_nsap_ptr_t;
+
+#endif /* IN_1_NSAP_PTR_23_H */
diff --git a/lib/dns/rdata/in_1/nsap_22.c b/lib/dns/rdata/in_1/nsap_22.c
new file mode 100644
index 0000000..c25f560
--- /dev/null
+++ b/lib/dns/rdata/in_1/nsap_22.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: nsap_22.c,v 1.42 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Fri Mar 17 10:41:07 PST 2000 by gson */
+
+/* RFC1706 */
+
+#ifndef RDATA_IN_1_NSAP_22_C
+#define RDATA_IN_1_NSAP_22_C
+
+#define RRTYPE_NSAP_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_nsap(ARGS_FROMTEXT) {
+ isc_token_t token;
+ isc_textregion_t *sr;
+ int n;
+ int digits;
+ unsigned char c = 0;
+
+ REQUIRE(type == 22);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /* 0x<hex.string.with.periods> */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ sr = &token.value.as_textregion;
+ if (sr->length < 2)
+ RETTOK(ISC_R_UNEXPECTEDEND);
+ if (sr->base[0] != '0' || (sr->base[1] != 'x' && sr->base[1] != 'X'))
+ RETTOK(DNS_R_SYNTAX);
+ isc_textregion_consume(sr, 2);
+ digits = 0;
+ n = 0;
+ while (sr->length > 0) {
+ if (sr->base[0] == '.') {
+ isc_textregion_consume(sr, 1);
+ continue;
+ }
+ if ((n = hexvalue(sr->base[0])) == -1)
+ RETTOK(DNS_R_SYNTAX);
+ c <<= 4;
+ c += n;
+ if (++digits == 2) {
+ RETERR(mem_tobuffer(target, &c, 1));
+ digits = 0;
+ }
+ isc_textregion_consume(sr, 1);
+ }
+ if (digits)
+ RETTOK(ISC_R_UNEXPECTEDEND);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_in_nsap(ARGS_TOTEXT) {
+ isc_region_t region;
+ char buf[sizeof("xx")];
+
+ REQUIRE(rdata->type == 22);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(tctx);
+
+ dns_rdata_toregion(rdata, &region);
+ RETERR(str_totext("0x", target));
+ while (region.length != 0) {
+ sprintf(buf, "%02x", region.base[0]);
+ isc_region_consume(&region, 1);
+ RETERR(str_totext(buf, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_in_nsap(ARGS_FROMWIRE) {
+ isc_region_t region;
+
+ REQUIRE(type == 22);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &region);
+ if (region.length < 1)
+ return (ISC_R_UNEXPECTEDEND);
+
+ RETERR(mem_tobuffer(target, region.base, region.length));
+ isc_buffer_forward(source, region.length);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_in_nsap(ARGS_TOWIRE) {
+ REQUIRE(rdata->type == 22);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ UNUSED(cctx);
+
+ return (mem_tobuffer(target, rdata->data, rdata->length));
+}
+
+static inline int
+compare_in_nsap(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 22);
+ REQUIRE(rdata1->rdclass == 1);
+ 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_in_nsap(ARGS_FROMSTRUCT) {
+ dns_rdata_in_nsap_t *nsap = source;
+
+ REQUIRE(type == 22);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(nsap->common.rdtype == type);
+ REQUIRE(nsap->common.rdclass == rdclass);
+ REQUIRE(nsap->nsap != NULL || nsap->nsap_len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (mem_tobuffer(target, nsap->nsap, nsap->nsap_len));
+}
+
+static inline isc_result_t
+tostruct_in_nsap(ARGS_TOSTRUCT) {
+ dns_rdata_in_nsap_t *nsap = target;
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 22);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ nsap->common.rdclass = rdata->rdclass;
+ nsap->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&nsap->common, link);
+
+ dns_rdata_toregion(rdata, &r);
+ nsap->nsap_len = r.length;
+ nsap->nsap = mem_maybedup(mctx, r.base, r.length);
+ if (nsap->nsap == NULL)
+ return (ISC_R_NOMEMORY);
+
+ nsap->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_nsap(ARGS_FREESTRUCT) {
+ dns_rdata_in_nsap_t *nsap = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(nsap->common.rdclass == 1);
+ REQUIRE(nsap->common.rdtype == 22);
+
+ if (nsap->mctx == NULL)
+ return;
+
+ if (nsap->nsap != NULL)
+ isc_mem_free(nsap->mctx, nsap->nsap);
+ nsap->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_in_nsap(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 22);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_nsap(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 22);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_in_nsap(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 22);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_in_nsap(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 22);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_NSAP_22_C */
diff --git a/lib/dns/rdata/in_1/nsap_22.h b/lib/dns/rdata/in_1/nsap_22.h
new file mode 100644
index 0000000..11e3f66
--- /dev/null
+++ b/lib/dns/rdata/in_1/nsap_22.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef IN_1_NSAP_22_H
+#define IN_1_NSAP_22_H 1
+
+/* $Id: nsap_22.h,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC1706 */
+
+typedef struct dns_rdata_in_nsap {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ unsigned char *nsap;
+ isc_uint16_t nsap_len;
+} dns_rdata_in_nsap_t;
+
+#endif /* IN_1_NSAP_22_H */
diff --git a/lib/dns/rdata/in_1/px_26.c b/lib/dns/rdata/in_1/px_26.c
new file mode 100644
index 0000000..1d17f2f
--- /dev/null
+++ b/lib/dns/rdata/in_1/px_26.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: px_26.c,v 1.43 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Mon Mar 20 10:44:27 PST 2000 */
+
+/* RFC2163 */
+
+#ifndef RDATA_IN_1_PX_26_C
+#define RDATA_IN_1_PX_26_C
+
+#define RRTYPE_PX_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_px(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+
+ REQUIRE(type == 26);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Preference.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * MAP822.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+
+ /*
+ * MAPX400.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_in_px(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ char buf[sizeof("64000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == 26);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ /*
+ * Preference.
+ */
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ sprintf(buf, "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * MAP822.
+ */
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ isc_region_consume(&region, name_length(&name));
+ RETERR(dns_name_totext(&prefix, sub, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * MAPX400.
+ */
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return(dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_in_px(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sregion;
+
+ REQUIRE(type == 26);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ /*
+ * Preference.
+ */
+ isc_buffer_activeregion(source, &sregion);
+ if (sregion.length < 2)
+ return (ISC_R_UNEXPECTEDEND);
+ RETERR(mem_tobuffer(target, sregion.base, 2));
+ isc_buffer_forward(source, 2);
+
+ /*
+ * MAP822.
+ */
+ RETERR(dns_name_fromwire(&name, source, dctx, options, target));
+
+ /*
+ * MAPX400.
+ */
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_in_px(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 26);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ /*
+ * Preference.
+ */
+ dns_rdata_toregion(rdata, &region);
+ RETERR(mem_tobuffer(target, region.base, 2));
+ isc_region_consume(&region, 2);
+
+ /*
+ * MAP822.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &region);
+ RETERR(dns_name_towire(&name, cctx, target));
+ isc_region_consume(&region, name_length(&name));
+
+ /*
+ * MAPX400.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &region);
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_in_px(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 26);
+ REQUIRE(rdata1->rdclass == 1);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ order = memcmp(rdata1->data, rdata2->data, 2);
+ if (order != 0)
+ return (order < 0 ? -1 : 1);
+
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 2);
+ isc_region_consume(&region2, 2);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ order = dns_name_rdatacompare(&name1, &name2);
+ if (order != 0)
+ return (order);
+
+ isc_region_consume(&region1, name_length(&name1));
+ isc_region_consume(&region2, name_length(&name2));
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_in_px(ARGS_FROMSTRUCT) {
+ dns_rdata_in_px_t *px = source;
+ isc_region_t region;
+
+ REQUIRE(type == 26);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(px->common.rdtype == type);
+ REQUIRE(px->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(px->preference, target));
+ dns_name_toregion(&px->map822, &region);
+ RETERR(isc_buffer_copyregion(target, &region));
+ dns_name_toregion(&px->mapx400, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_in_px(ARGS_TOSTRUCT) {
+ dns_rdata_in_px_t *px = target;
+ dns_name_t name;
+ isc_region_t region;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == 26);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ px->common.rdclass = rdata->rdclass;
+ px->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&px->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+
+ px->preference = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+
+ dns_name_fromregion(&name, &region);
+
+ dns_name_init(&px->map822, NULL);
+ RETERR(name_duporclone(&name, mctx, &px->map822));
+ isc_region_consume(&region, name_length(&px->map822));
+
+ dns_name_init(&px->mapx400, NULL);
+ result = name_duporclone(&name, mctx, &px->mapx400);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ px->mctx = mctx;
+ return (result);
+
+ cleanup:
+ dns_name_free(&px->map822, mctx);
+ return (ISC_R_NOMEMORY);
+}
+
+static inline void
+freestruct_in_px(ARGS_FREESTRUCT) {
+ dns_rdata_in_px_t *px = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(px->common.rdclass == 1);
+ REQUIRE(px->common.rdtype == 26);
+
+ if (px->mctx == NULL)
+ return;
+
+ dns_name_free(&px->map822, px->mctx);
+ dns_name_free(&px->mapx400, px->mctx);
+ px->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_in_px(ARGS_ADDLDATA) {
+ REQUIRE(rdata->type == 26);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_px(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ dns_name_t name;
+ isc_result_t result;
+
+ REQUIRE(rdata->type == 26);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ isc_region_consume(&r2, 2);
+ r1.length = 2;
+ result = (digest)(arg, &r1);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+ result = dns_name_digest(&name, digest, arg);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_region_consume(&r2, name_length(&name));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_in_px(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 26);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_in_px(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 26);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_PX_26_C */
diff --git a/lib/dns/rdata/in_1/px_26.h b/lib/dns/rdata/in_1/px_26.h
new file mode 100644
index 0000000..69a7bae
--- /dev/null
+++ b/lib/dns/rdata/in_1/px_26.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef IN_1_PX_26_H
+#define IN_1_PX_26_H 1
+
+/* $Id: px_26.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \brief Per RFC2163 */
+
+typedef struct dns_rdata_in_px {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t preference;
+ dns_name_t map822;
+ dns_name_t mapx400;
+} dns_rdata_in_px_t;
+
+#endif /* IN_1_PX_26_H */
diff --git a/lib/dns/rdata/in_1/srv_33.c b/lib/dns/rdata/in_1/srv_33.c
new file mode 100644
index 0000000..7bc85cd
--- /dev/null
+++ b/lib/dns/rdata/in_1/srv_33.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: srv_33.c,v 1.45 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Fri Mar 17 13:01:00 PST 2000 by bwelling */
+
+/* RFC2782 */
+
+#ifndef RDATA_IN_1_SRV_33_C
+#define RDATA_IN_1_SRV_33_C
+
+#define RRTYPE_SRV_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_srv(ARGS_FROMTEXT) {
+ isc_token_t token;
+ dns_name_t name;
+ isc_buffer_t buffer;
+ isc_boolean_t ok;
+
+ REQUIRE(type == 33);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(callbacks);
+
+ /*
+ * Priority.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Weight.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Port.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+ ISC_FALSE));
+ if (token.value.as_ulong > 0xffffU)
+ RETTOK(ISC_R_RANGE);
+ RETERR(uint16_tobuffer(token.value.as_ulong, target));
+
+ /*
+ * Target.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+ dns_name_init(&name, NULL);
+ buffer_fromregion(&buffer, &token.value.as_region);
+ origin = (origin != NULL) ? origin : dns_rootname;
+ RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target));
+ ok = ISC_TRUE;
+ if ((options & DNS_RDATA_CHECKNAMES) != 0)
+ ok = dns_name_ishostname(&name, ISC_FALSE);
+ if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0)
+ RETTOK(DNS_R_BADNAME);
+ if (!ok && callbacks != NULL)
+ warn_badname(&name, lexer, callbacks);
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+totext_in_srv(ARGS_TOTEXT) {
+ isc_region_t region;
+ dns_name_t name;
+ dns_name_t prefix;
+ isc_boolean_t sub;
+ char buf[sizeof("64000")];
+ unsigned short num;
+
+ REQUIRE(rdata->type == 33);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_name_init(&name, NULL);
+ dns_name_init(&prefix, NULL);
+
+ /*
+ * Priority.
+ */
+ dns_rdata_toregion(rdata, &region);
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ sprintf(buf, "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Weight.
+ */
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ sprintf(buf, "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Port.
+ */
+ num = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ sprintf(buf, "%u", num);
+ RETERR(str_totext(buf, target));
+ RETERR(str_totext(" ", target));
+
+ /*
+ * Target.
+ */
+ dns_name_fromregion(&name, &region);
+ sub = name_prefix(&name, tctx->origin, &prefix);
+ return (dns_name_totext(&prefix, sub, target));
+}
+
+static inline isc_result_t
+fromwire_in_srv(ARGS_FROMWIRE) {
+ dns_name_t name;
+ isc_region_t sr;
+
+ REQUIRE(type == 33);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
+
+ dns_name_init(&name, NULL);
+
+ /*
+ * Priority, weight, port.
+ */
+ isc_buffer_activeregion(source, &sr);
+ if (sr.length < 6)
+ return (ISC_R_UNEXPECTEDEND);
+ RETERR(mem_tobuffer(target, sr.base, 6));
+ isc_buffer_forward(source, 6);
+
+ /*
+ * Target.
+ */
+ return (dns_name_fromwire(&name, source, dctx, options, target));
+}
+
+static inline isc_result_t
+towire_in_srv(ARGS_TOWIRE) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t sr;
+
+ REQUIRE(rdata->type == 33);
+ REQUIRE(rdata->length != 0);
+
+ dns_compress_setmethods(cctx, DNS_COMPRESS_NONE);
+ /*
+ * Priority, weight, port.
+ */
+ dns_rdata_toregion(rdata, &sr);
+ RETERR(mem_tobuffer(target, sr.base, 6));
+ isc_region_consume(&sr, 6);
+
+ /*
+ * Target.
+ */
+ dns_name_init(&name, offsets);
+ dns_name_fromregion(&name, &sr);
+ return (dns_name_towire(&name, cctx, target));
+}
+
+static inline int
+compare_in_srv(ARGS_COMPARE) {
+ dns_name_t name1;
+ dns_name_t name2;
+ isc_region_t region1;
+ isc_region_t region2;
+ int order;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 33);
+ REQUIRE(rdata1->rdclass == 1);
+ REQUIRE(rdata1->length != 0);
+ REQUIRE(rdata2->length != 0);
+
+ /*
+ * Priority, weight, port.
+ */
+ order = memcmp(rdata1->data, rdata2->data, 6);
+ if (order != 0)
+ return (order < 0 ? -1 : 1);
+
+ /*
+ * Target.
+ */
+ dns_name_init(&name1, NULL);
+ dns_name_init(&name2, NULL);
+
+ dns_rdata_toregion(rdata1, &region1);
+ dns_rdata_toregion(rdata2, &region2);
+
+ isc_region_consume(&region1, 6);
+ isc_region_consume(&region2, 6);
+
+ dns_name_fromregion(&name1, &region1);
+ dns_name_fromregion(&name2, &region2);
+
+ return (dns_name_rdatacompare(&name1, &name2));
+}
+
+static inline isc_result_t
+fromstruct_in_srv(ARGS_FROMSTRUCT) {
+ dns_rdata_in_srv_t *srv = source;
+ isc_region_t region;
+
+ REQUIRE(type == 33);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(srv->common.rdtype == type);
+ REQUIRE(srv->common.rdclass == rdclass);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ RETERR(uint16_tobuffer(srv->priority, target));
+ RETERR(uint16_tobuffer(srv->weight, target));
+ RETERR(uint16_tobuffer(srv->port, target));
+ dns_name_toregion(&srv->target, &region);
+ return (isc_buffer_copyregion(target, &region));
+}
+
+static inline isc_result_t
+tostruct_in_srv(ARGS_TOSTRUCT) {
+ isc_region_t region;
+ dns_rdata_in_srv_t *srv = target;
+ dns_name_t name;
+
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->type == 33);
+ REQUIRE(target != NULL);
+ REQUIRE(rdata->length != 0);
+
+ srv->common.rdclass = rdata->rdclass;
+ srv->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&srv->common, link);
+
+ dns_name_init(&name, NULL);
+ dns_rdata_toregion(rdata, &region);
+ srv->priority = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ srv->weight = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ srv->port = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ dns_name_fromregion(&name, &region);
+ dns_name_init(&srv->target, NULL);
+ RETERR(name_duporclone(&name, mctx, &srv->target));
+ srv->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_srv(ARGS_FREESTRUCT) {
+ dns_rdata_in_srv_t *srv = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(srv->common.rdclass == 1);
+ REQUIRE(srv->common.rdtype == 33);
+
+ if (srv->mctx == NULL)
+ return;
+
+ dns_name_free(&srv->target, srv->mctx);
+ srv->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_in_srv(ARGS_ADDLDATA) {
+ dns_name_t name;
+ dns_offsets_t offsets;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 33);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_name_init(&name, offsets);
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 6);
+ dns_name_fromregion(&name, &region);
+
+ return ((add)(arg, &name, dns_rdatatype_a));
+}
+
+static inline isc_result_t
+digest_in_srv(ARGS_DIGEST) {
+ isc_region_t r1, r2;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 33);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r1);
+ r2 = r1;
+ isc_region_consume(&r2, 6);
+ r1.length = 6;
+ RETERR((digest)(arg, &r1));
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &r2);
+ return (dns_name_digest(&name, digest, arg));
+}
+
+static inline isc_boolean_t
+checkowner_in_srv(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 33);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(name);
+ UNUSED(type);
+ UNUSED(rdclass);
+ UNUSED(wildcard);
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+checknames_in_srv(ARGS_CHECKNAMES) {
+ isc_region_t region;
+ dns_name_t name;
+
+ REQUIRE(rdata->type == 33);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(owner);
+
+ dns_rdata_toregion(rdata, &region);
+ isc_region_consume(&region, 6);
+ dns_name_init(&name, NULL);
+ dns_name_fromregion(&name, &region);
+ if (!dns_name_ishostname(&name, ISC_FALSE)) {
+ if (bad != NULL)
+ dns_name_clone(&name, bad);
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_SRV_33_C */
diff --git a/lib/dns/rdata/in_1/srv_33.h b/lib/dns/rdata/in_1/srv_33.h
new file mode 100644
index 0000000..e019698
--- /dev/null
+++ b/lib/dns/rdata/in_1/srv_33.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef IN_1_SRV_33_H
+#define IN_1_SRV_33_H 1
+
+/* $Id: srv_33.h,v 1.19 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Fri Mar 17 13:01:00 PST 2000 by bwelling */
+
+/*!
+ * \brief Per RFC2782 */
+
+typedef struct dns_rdata_in_srv {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ isc_uint16_t priority;
+ isc_uint16_t weight;
+ isc_uint16_t port;
+ dns_name_t target;
+} dns_rdata_in_srv_t;
+
+#endif /* IN_1_SRV_33_H */
diff --git a/lib/dns/rdata/in_1/wks_11.c b/lib/dns/rdata/in_1/wks_11.c
new file mode 100644
index 0000000..fca9011
--- /dev/null
+++ b/lib/dns/rdata/in_1/wks_11.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: wks_11.c,v 1.54 2007/06/19 23:47:17 tbox Exp $ */
+
+/* Reviewed: Fri Mar 17 15:01:49 PST 2000 by explorer */
+
+#ifndef RDATA_IN_1_WKS_11_C
+#define RDATA_IN_1_WKS_11_C
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include <isc/net.h>
+#include <isc/netdb.h>
+
+#define RRTYPE_WKS_ATTRIBUTES (0)
+
+static inline isc_result_t
+fromtext_in_wks(ARGS_FROMTEXT) {
+ isc_token_t token;
+ isc_region_t region;
+ struct in_addr addr;
+ struct protoent *pe;
+ struct servent *se;
+ char *e;
+ long proto;
+ unsigned char bm[8*1024]; /* 64k bits */
+ long port;
+ long maxport = -1;
+ const char *ps = NULL;
+ unsigned int n;
+ char service[32];
+ int i;
+
+ REQUIRE(type == 11);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(origin);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ /*
+ * IPv4 dotted quad.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ isc_buffer_availableregion(target, &region);
+ if (getquad(DNS_AS_STR(token), &addr, lexer, callbacks) != 1)
+ RETTOK(DNS_R_BADDOTTEDQUAD);
+ if (region.length < 4)
+ return (ISC_R_NOSPACE);
+ memcpy(region.base, &addr, 4);
+ isc_buffer_add(target, 4);
+
+ /*
+ * Protocol.
+ */
+ RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
+ ISC_FALSE));
+
+ proto = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e == 0)
+ ;
+ else if ((pe = getprotobyname(DNS_AS_STR(token))) != NULL)
+ proto = pe->p_proto;
+ else
+ RETTOK(DNS_R_UNKNOWNPROTO);
+ if (proto < 0 || proto > 0xff)
+ RETTOK(ISC_R_RANGE);
+
+ if (proto == IPPROTO_TCP)
+ ps = "tcp";
+ else if (proto == IPPROTO_UDP)
+ ps = "udp";
+
+ RETERR(uint8_tobuffer(proto, target));
+
+ memset(bm, 0, sizeof(bm));
+ do {
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, ISC_TRUE));
+ if (token.type != isc_tokentype_string)
+ break;
+
+ /*
+ * Lowercase the service string as some getservbyname() are
+ * case sensitive and the database is usually in lowercase.
+ */
+ strncpy(service, DNS_AS_STR(token), sizeof(service));
+ service[sizeof(service)-1] = '\0';
+ for (i = strlen(service) - 1; i >= 0; i--)
+ if (isupper(service[i]&0xff))
+ service[i] = tolower(service[i]&0xff);
+
+ port = strtol(DNS_AS_STR(token), &e, 10);
+ if (*e == 0)
+ ;
+ else if ((se = getservbyname(service, ps)) != NULL)
+ port = ntohs(se->s_port);
+ else if ((se = getservbyname(DNS_AS_STR(token), ps))
+ != NULL)
+ port = ntohs(se->s_port);
+ else
+ RETTOK(DNS_R_UNKNOWNSERVICE);
+ if (port < 0 || port > 0xffff)
+ RETTOK(ISC_R_RANGE);
+ if (port > maxport)
+ maxport = port;
+ bm[port / 8] |= (0x80 >> (port % 8));
+ } while (1);
+
+ /*
+ * Let upper layer handle eol/eof.
+ */
+ isc_lex_ungettoken(lexer, &token);
+
+ n = (maxport + 8) / 8;
+ return (mem_tobuffer(target, bm, n));
+}
+
+static inline isc_result_t
+totext_in_wks(ARGS_TOTEXT) {
+ isc_region_t sr;
+ unsigned short proto;
+ char buf[sizeof("65535")];
+ unsigned int i, j;
+
+ UNUSED(tctx);
+
+ REQUIRE(rdata->type == 11);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length >= 5);
+
+ dns_rdata_toregion(rdata, &sr);
+ RETERR(inet_totext(AF_INET, &sr, target));
+ isc_region_consume(&sr, 4);
+
+ proto = uint8_fromregion(&sr);
+ sprintf(buf, "%u", proto);
+ RETERR(str_totext(" ", target));
+ RETERR(str_totext(buf, target));
+ isc_region_consume(&sr, 1);
+
+ for (i = 0; i < sr.length; i++) {
+ if (sr.base[i] != 0)
+ for (j = 0; j < 8; j++)
+ if ((sr.base[i] & (0x80 >> j)) != 0) {
+ sprintf(buf, "%u", i * 8 + j);
+ RETERR(str_totext(" ", target));
+ RETERR(str_totext(buf, target));
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+fromwire_in_wks(ARGS_FROMWIRE) {
+ isc_region_t sr;
+ isc_region_t tr;
+
+ REQUIRE(type == 11);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(dctx);
+ UNUSED(options);
+ UNUSED(rdclass);
+
+ isc_buffer_activeregion(source, &sr);
+ isc_buffer_availableregion(target, &tr);
+
+ if (sr.length < 5)
+ return (ISC_R_UNEXPECTEDEND);
+ if (sr.length > 8 * 1024 + 5)
+ return (DNS_R_EXTRADATA);
+ if (tr.length < sr.length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(tr.base, sr.base, sr.length);
+ isc_buffer_add(target, sr.length);
+ isc_buffer_forward(source, sr.length);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+towire_in_wks(ARGS_TOWIRE) {
+ isc_region_t sr;
+
+ UNUSED(cctx);
+
+ REQUIRE(rdata->type == 11);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ dns_rdata_toregion(rdata, &sr);
+ return (mem_tobuffer(target, sr.base, sr.length));
+}
+
+static inline int
+compare_in_wks(ARGS_COMPARE) {
+ isc_region_t r1;
+ isc_region_t r2;
+
+ REQUIRE(rdata1->type == rdata2->type);
+ REQUIRE(rdata1->rdclass == rdata2->rdclass);
+ REQUIRE(rdata1->type == 11);
+ REQUIRE(rdata1->rdclass == 1);
+ 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_in_wks(ARGS_FROMSTRUCT) {
+ dns_rdata_in_wks_t *wks = source;
+ isc_uint32_t a;
+
+ REQUIRE(type == 11);
+ REQUIRE(rdclass == 1);
+ REQUIRE(source != NULL);
+ REQUIRE(wks->common.rdtype == type);
+ REQUIRE(wks->common.rdclass == rdclass);
+ REQUIRE(wks->map != NULL || wks->map_len == 0);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ a = ntohl(wks->in_addr.s_addr);
+ RETERR(uint32_tobuffer(a, target));
+ RETERR(uint16_tobuffer(wks->protocol, target));
+ return (mem_tobuffer(target, wks->map, wks->map_len));
+}
+
+static inline isc_result_t
+tostruct_in_wks(ARGS_TOSTRUCT) {
+ dns_rdata_in_wks_t *wks = target;
+ isc_uint32_t n;
+ isc_region_t region;
+
+ REQUIRE(rdata->type == 11);
+ REQUIRE(rdata->rdclass == 1);
+ REQUIRE(rdata->length != 0);
+
+ wks->common.rdclass = rdata->rdclass;
+ wks->common.rdtype = rdata->type;
+ ISC_LINK_INIT(&wks->common, link);
+
+ dns_rdata_toregion(rdata, &region);
+ n = uint32_fromregion(&region);
+ wks->in_addr.s_addr = htonl(n);
+ isc_region_consume(&region, 4);
+ wks->protocol = uint16_fromregion(&region);
+ isc_region_consume(&region, 2);
+ wks->map_len = region.length;
+ wks->map = mem_maybedup(mctx, region.base, region.length);
+ if (wks->map == NULL)
+ return (ISC_R_NOMEMORY);
+ wks->mctx = mctx;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+freestruct_in_wks(ARGS_FREESTRUCT) {
+ dns_rdata_in_wks_t *wks = source;
+
+ REQUIRE(source != NULL);
+ REQUIRE(wks->common.rdtype == 11);
+ REQUIRE(wks->common.rdclass == 1);
+
+ if (wks->mctx == NULL)
+ return;
+
+ if (wks->map != NULL)
+ isc_mem_free(wks->mctx, wks->map);
+ wks->mctx = NULL;
+}
+
+static inline isc_result_t
+additionaldata_in_wks(ARGS_ADDLDATA) {
+ UNUSED(rdata);
+ UNUSED(add);
+ UNUSED(arg);
+
+ REQUIRE(rdata->type == 11);
+ REQUIRE(rdata->rdclass == 1);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+digest_in_wks(ARGS_DIGEST) {
+ isc_region_t r;
+
+ REQUIRE(rdata->type == 11);
+ REQUIRE(rdata->rdclass == 1);
+
+ dns_rdata_toregion(rdata, &r);
+
+ return ((digest)(arg, &r));
+}
+
+static inline isc_boolean_t
+checkowner_in_wks(ARGS_CHECKOWNER) {
+
+ REQUIRE(type == 11);
+ REQUIRE(rdclass == 1);
+
+ UNUSED(type);
+ UNUSED(rdclass);
+
+ return (dns_name_ishostname(name, wildcard));
+}
+
+static inline isc_boolean_t
+checknames_in_wks(ARGS_CHECKNAMES) {
+
+ REQUIRE(rdata->type == 11);
+ REQUIRE(rdata->rdclass == 1);
+
+ UNUSED(rdata);
+ UNUSED(owner);
+ UNUSED(bad);
+
+ return (ISC_TRUE);
+}
+
+#endif /* RDATA_IN_1_WKS_11_C */
diff --git a/lib/dns/rdata/in_1/wks_11.h b/lib/dns/rdata/in_1/wks_11.h
new file mode 100644
index 0000000..2fd26e8
--- /dev/null
+++ b/lib/dns/rdata/in_1/wks_11.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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.
+ */
+
+#ifndef IN_1_WKS_11_H
+#define IN_1_WKS_11_H 1
+
+/* $Id: wks_11.h,v 1.22 2007/06/19 23:47:17 tbox Exp $ */
+
+typedef struct dns_rdata_in_wks {
+ dns_rdatacommon_t common;
+ isc_mem_t *mctx;
+ struct in_addr in_addr;
+ isc_uint16_t protocol;
+ unsigned char *map;
+ isc_uint16_t map_len;
+} dns_rdata_in_wks_t;
+
+#endif /* IN_1_WKS_11_H */
diff --git a/lib/dns/rdata/rdatastructpre.h b/lib/dns/rdata/rdatastructpre.h
new file mode 100644
index 0000000..ab7e051
--- /dev/null
+++ b/lib/dns/rdata/rdatastructpre.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rdatastructpre.h,v 1.16 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef DNS_RDATASTRUCT_H
+#define DNS_RDATASTRUCT_H 1
+
+#include <isc/lang.h>
+#include <isc/sockaddr.h>
+
+#include <dns/name.h>
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef struct dns_rdatacommon {
+ dns_rdataclass_t rdclass;
+ dns_rdatatype_t rdtype;
+ ISC_LINK(struct dns_rdatacommon) link;
+} dns_rdatacommon_t;
+
+#define DNS_RDATACOMMON_INIT(_data, _rdtype, _rdclass) \
+ do { \
+ (_data)->common.rdtype = (_rdtype); \
+ (_data)->common.rdclass = (_rdclass); \
+ ISC_LINK_INIT(&(_data)->common, link); \
+ } while (0)
diff --git a/lib/dns/rdata/rdatastructsuf.h b/lib/dns/rdata/rdatastructsuf.h
new file mode 100644
index 0000000..3ba1275
--- /dev/null
+++ b/lib/dns/rdata/rdatastructsuf.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rdatastructsuf.h,v 1.10 2007/06/19 23:47:17 tbox Exp $ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RDATASTRUCT_H */
diff --git a/lib/dns/rdatalist.c b/lib/dns/rdatalist.c
new file mode 100644
index 0000000..d6f11ae
--- /dev/null
+++ b/lib/dns/rdatalist.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 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
+ * 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: rdatalist.c,v 1.36 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/util.h>
+
+#include <dns/name.h>
+#include <dns/nsec3.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+
+#include "rdatalist_p.h"
+
+static dns_rdatasetmethods_t methods = {
+ isc__rdatalist_disassociate,
+ isc__rdatalist_first,
+ isc__rdatalist_next,
+ isc__rdatalist_current,
+ isc__rdatalist_clone,
+ isc__rdatalist_count,
+ isc__rdatalist_addnoqname,
+ isc__rdatalist_getnoqname,
+ isc__rdatalist_addclosest,
+ isc__rdatalist_getclosest,
+ NULL,
+ NULL,
+ NULL
+};
+
+void
+dns_rdatalist_init(dns_rdatalist_t *rdatalist) {
+
+ /*
+ * Initialize rdatalist.
+ */
+
+ rdatalist->rdclass = 0;
+ rdatalist->type = 0;
+ rdatalist->covers = 0;
+ rdatalist->ttl = 0;
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LINK_INIT(rdatalist, link);
+}
+
+isc_result_t
+dns_rdatalist_tordataset(dns_rdatalist_t *rdatalist,
+ dns_rdataset_t *rdataset)
+{
+ /*
+ * Make 'rdataset' refer to the rdata in 'rdatalist'.
+ */
+
+ REQUIRE(rdatalist != NULL);
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(! dns_rdataset_isassociated(rdataset));
+
+ rdataset->methods = &methods;
+ rdataset->rdclass = rdatalist->rdclass;
+ rdataset->type = rdatalist->type;
+ rdataset->covers = rdatalist->covers;
+ rdataset->ttl = rdatalist->ttl;
+ rdataset->trust = 0;
+ rdataset->private1 = rdatalist;
+ rdataset->private2 = NULL;
+ rdataset->private3 = NULL;
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdatalist_fromrdataset(dns_rdataset_t *rdataset,
+ dns_rdatalist_t **rdatalist)
+{
+ REQUIRE(rdatalist != NULL && rdataset != NULL);
+ *rdatalist = rdataset->private1;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc__rdatalist_disassociate(dns_rdataset_t *rdataset) {
+ UNUSED(rdataset);
+}
+
+isc_result_t
+isc__rdatalist_first(dns_rdataset_t *rdataset) {
+ dns_rdatalist_t *rdatalist;
+
+ rdatalist = rdataset->private1;
+ rdataset->private2 = ISC_LIST_HEAD(rdatalist->rdata);
+
+ if (rdataset->private2 == NULL)
+ return (ISC_R_NOMORE);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__rdatalist_next(dns_rdataset_t *rdataset) {
+ dns_rdata_t *rdata;
+
+ rdata = rdataset->private2;
+ if (rdata == NULL)
+ return (ISC_R_NOMORE);
+
+ rdataset->private2 = ISC_LIST_NEXT(rdata, link);
+
+ if (rdataset->private2 == NULL)
+ return (ISC_R_NOMORE);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
+ dns_rdata_t *list_rdata;
+
+ list_rdata = rdataset->private2;
+ INSIST(list_rdata != NULL);
+
+ dns_rdata_clone(list_rdata, rdata);
+}
+
+void
+isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
+ *target = *source;
+
+ /*
+ * Reset iterator state.
+ */
+ target->private2 = NULL;
+}
+
+unsigned int
+isc__rdatalist_count(dns_rdataset_t *rdataset) {
+ dns_rdatalist_t *rdatalist;
+ dns_rdata_t *rdata;
+ unsigned int count;
+
+ rdatalist = rdataset->private1;
+
+ count = 0;
+ for (rdata = ISC_LIST_HEAD(rdatalist->rdata);
+ rdata != NULL;
+ rdata = ISC_LIST_NEXT(rdata, link))
+ count++;
+
+ return (count);
+}
+
+isc_result_t
+isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
+ dns_rdataset_t *neg = NULL;
+ dns_rdataset_t *negsig = NULL;
+ dns_rdataset_t *rdset;
+ dns_ttl_t ttl;
+
+ for (rdset = ISC_LIST_HEAD(name->list);
+ rdset != NULL;
+ rdset = ISC_LIST_NEXT(rdset, link))
+ {
+ if (rdset->rdclass != rdataset->rdclass)
+ continue;
+ if (rdset->type == dns_rdatatype_nsec ||
+ rdset->type == dns_rdatatype_nsec3)
+ neg = rdset;
+ }
+ if (neg == NULL)
+ return (ISC_R_NOTFOUND);
+
+ for (rdset = ISC_LIST_HEAD(name->list);
+ rdset != NULL;
+ rdset = ISC_LIST_NEXT(rdset, link))
+ {
+ if (rdset->type == dns_rdatatype_rrsig &&
+ rdset->covers == neg->type)
+ negsig = rdset;
+ }
+
+ if (negsig == NULL)
+ return (ISC_R_NOTFOUND);
+ /*
+ * Minimise ttl.
+ */
+ ttl = rdataset->ttl;
+ if (neg->ttl < ttl)
+ ttl = neg->ttl;
+ if (negsig->ttl < ttl)
+ ttl = negsig->ttl;
+ rdataset->ttl = neg->ttl = negsig->ttl = ttl;
+ rdataset->attributes |= DNS_RDATASETATTR_NOQNAME;
+ rdataset->private6 = name;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *neg, dns_rdataset_t *negsig)
+{
+ dns_rdataclass_t rdclass = rdataset->rdclass;
+ dns_rdataset_t *tneg = NULL;
+ dns_rdataset_t *tnegsig = NULL;
+ dns_name_t *noqname = rdataset->private6;
+
+ REQUIRE((rdataset->attributes & DNS_RDATASETATTR_NOQNAME) != 0);
+ (void)dns_name_dynamic(noqname); /* Sanity Check. */
+
+ for (rdataset = ISC_LIST_HEAD(noqname->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->rdclass != rdclass)
+ continue;
+ if (rdataset->type == dns_rdatatype_nsec ||
+ rdataset->type == dns_rdatatype_nsec3)
+ tneg = rdataset;
+ }
+ if (tneg == NULL)
+ return (ISC_R_NOTFOUND);
+
+ for (rdataset = ISC_LIST_HEAD(noqname->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->type == dns_rdatatype_rrsig &&
+ rdataset->covers == tneg->type)
+ tnegsig = rdataset;
+ }
+ if (tnegsig == NULL)
+ return (ISC_R_NOTFOUND);
+
+ dns_name_clone(noqname, name);
+ dns_rdataset_clone(tneg, neg);
+ dns_rdataset_clone(tnegsig, negsig);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__rdatalist_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
+ dns_rdataset_t *neg = NULL;
+ dns_rdataset_t *negsig = NULL;
+ dns_rdataset_t *rdset;
+ dns_ttl_t ttl;
+
+ for (rdset = ISC_LIST_HEAD(name->list);
+ rdset != NULL;
+ rdset = ISC_LIST_NEXT(rdset, link))
+ {
+ if (rdset->rdclass != rdataset->rdclass)
+ continue;
+ if (rdset->type == dns_rdatatype_nsec ||
+ rdset->type == dns_rdatatype_nsec3)
+ neg = rdset;
+ }
+ if (neg == NULL)
+ return (ISC_R_NOTFOUND);
+
+ for (rdset = ISC_LIST_HEAD(name->list);
+ rdset != NULL;
+ rdset = ISC_LIST_NEXT(rdset, link))
+ {
+ if (rdset->type == dns_rdatatype_rrsig &&
+ rdset->covers == neg->type)
+ negsig = rdset;
+ }
+
+ if (negsig == NULL)
+ return (ISC_R_NOTFOUND);
+ /*
+ * Minimise ttl.
+ */
+ ttl = rdataset->ttl;
+ if (neg->ttl < ttl)
+ ttl = neg->ttl;
+ if (negsig->ttl < ttl)
+ ttl = negsig->ttl;
+ rdataset->ttl = neg->ttl = negsig->ttl = ttl;
+ rdataset->attributes |= DNS_RDATASETATTR_CLOSEST;
+ rdataset->private7 = name;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *neg, dns_rdataset_t *negsig)
+{
+ dns_rdataclass_t rdclass = rdataset->rdclass;
+ dns_rdataset_t *tneg = NULL;
+ dns_rdataset_t *tnegsig = NULL;
+ dns_name_t *closest = rdataset->private7;
+
+ REQUIRE((rdataset->attributes & DNS_RDATASETATTR_CLOSEST) != 0);
+ (void)dns_name_dynamic(closest); /* Sanity Check. */
+
+ for (rdataset = ISC_LIST_HEAD(closest->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->rdclass != rdclass)
+ continue;
+ if (rdataset->type == dns_rdatatype_nsec ||
+ rdataset->type == dns_rdatatype_nsec3)
+ tneg = rdataset;
+ }
+ if (tneg == NULL)
+ return (ISC_R_NOTFOUND);
+
+ for (rdataset = ISC_LIST_HEAD(closest->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->type == dns_rdatatype_rrsig &&
+ rdataset->covers == tneg->type)
+ tnegsig = rdataset;
+ }
+ if (tnegsig == NULL)
+ return (ISC_R_NOTFOUND);
+
+ dns_name_clone(closest, name);
+ dns_rdataset_clone(tneg, neg);
+ dns_rdataset_clone(tnegsig, negsig);
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/dns/rdatalist_p.h b/lib/dns/rdatalist_p.h
new file mode 100644
index 0000000..3e73e20
--- /dev/null
+++ b/lib/dns/rdatalist_p.h
@@ -0,0 +1,64 @@
+/*
+ * 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
+ * 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: rdatalist_p.h,v 1.11 2008/09/25 04:02:38 tbox Exp $ */
+
+#ifndef DNS_RDATALIST_P_H
+#define DNS_RDATALIST_P_H
+
+/*! \file */
+
+#include <isc/result.h>
+#include <dns/types.h>
+
+ISC_LANG_BEGINDECLS
+
+void
+isc__rdatalist_disassociate(dns_rdataset_t *rdatasetp);
+
+isc_result_t
+isc__rdatalist_first(dns_rdataset_t *rdataset);
+
+isc_result_t
+isc__rdatalist_next(dns_rdataset_t *rdataset);
+
+void
+isc__rdatalist_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
+
+void
+isc__rdatalist_clone(dns_rdataset_t *source, dns_rdataset_t *target);
+
+unsigned int
+isc__rdatalist_count(dns_rdataset_t *rdataset);
+
+isc_result_t
+isc__rdatalist_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name);
+
+isc_result_t
+isc__rdatalist_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *neg, dns_rdataset_t *negsig);
+
+isc_result_t
+isc__rdatalist_addclosest(dns_rdataset_t *rdataset, dns_name_t *name);
+
+isc_result_t
+isc__rdatalist_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *neg, dns_rdataset_t *negsig);
+
+ISC_LANG_ENDDECLS
+
+#endif /* DNS_RDATALIST_P_H */
diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c
new file mode 100644
index 0000000..451c6b8
--- /dev/null
+++ b/lib/dns/rdataset.c
@@ -0,0 +1,734 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: rdataset.c,v 1.82 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/random.h>
+#include <isc/util.h>
+
+#include <dns/name.h>
+#include <dns/ncache.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/compress.h>
+
+void
+dns_rdataset_init(dns_rdataset_t *rdataset) {
+
+ /*
+ * Make 'rdataset' a valid, disassociated rdataset.
+ */
+
+ REQUIRE(rdataset != NULL);
+
+ rdataset->magic = DNS_RDATASET_MAGIC;
+ rdataset->methods = NULL;
+ ISC_LINK_INIT(rdataset, link);
+ rdataset->rdclass = 0;
+ rdataset->type = 0;
+ rdataset->ttl = 0;
+ rdataset->trust = 0;
+ rdataset->covers = 0;
+ rdataset->attributes = 0;
+ rdataset->count = ISC_UINT32_MAX;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+ rdataset->private3 = NULL;
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+ rdataset->private6 = NULL;
+ rdataset->resign = 0;
+}
+
+void
+dns_rdataset_invalidate(dns_rdataset_t *rdataset) {
+
+ /*
+ * Invalidate 'rdataset'.
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods == NULL);
+
+ rdataset->magic = 0;
+ ISC_LINK_INIT(rdataset, link);
+ rdataset->rdclass = 0;
+ rdataset->type = 0;
+ rdataset->ttl = 0;
+ rdataset->trust = 0;
+ rdataset->covers = 0;
+ rdataset->attributes = 0;
+ rdataset->count = ISC_UINT32_MAX;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+ rdataset->private3 = NULL;
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+}
+
+void
+dns_rdataset_disassociate(dns_rdataset_t *rdataset) {
+
+ /*
+ * Disassociate 'rdataset' from its rdata, allowing it to be reused.
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+
+ (rdataset->methods->disassociate)(rdataset);
+ rdataset->methods = NULL;
+ ISC_LINK_INIT(rdataset, link);
+ rdataset->rdclass = 0;
+ rdataset->type = 0;
+ rdataset->ttl = 0;
+ rdataset->trust = 0;
+ rdataset->covers = 0;
+ rdataset->attributes = 0;
+ rdataset->count = ISC_UINT32_MAX;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+ rdataset->private3 = NULL;
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+ rdataset->private6 = NULL;
+}
+
+isc_boolean_t
+dns_rdataset_isassociated(dns_rdataset_t *rdataset) {
+ /*
+ * Is 'rdataset' associated?
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+
+ if (rdataset->methods != NULL)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+static void
+question_disassociate(dns_rdataset_t *rdataset) {
+ UNUSED(rdataset);
+}
+
+static isc_result_t
+question_cursor(dns_rdataset_t *rdataset) {
+ UNUSED(rdataset);
+
+ return (ISC_R_NOMORE);
+}
+
+static void
+question_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
+ /*
+ * This routine should never be called.
+ */
+ UNUSED(rdataset);
+ UNUSED(rdata);
+
+ REQUIRE(0);
+}
+
+static void
+question_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
+ *target = *source;
+}
+
+static unsigned int
+question_count(dns_rdataset_t *rdataset) {
+ /*
+ * This routine should never be called.
+ */
+ UNUSED(rdataset);
+ REQUIRE(0);
+
+ return (0);
+}
+
+static dns_rdatasetmethods_t question_methods = {
+ question_disassociate,
+ question_cursor,
+ question_cursor,
+ question_current,
+ question_clone,
+ question_count,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+void
+dns_rdataset_makequestion(dns_rdataset_t *rdataset, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type)
+{
+
+ /*
+ * Make 'rdataset' a valid, associated, question rdataset, with a
+ * question class of 'rdclass' and type 'type'.
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods == NULL);
+
+ rdataset->methods = &question_methods;
+ rdataset->rdclass = rdclass;
+ rdataset->type = type;
+ rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
+}
+
+unsigned int
+dns_rdataset_count(dns_rdataset_t *rdataset) {
+
+ /*
+ * Return the number of records in 'rdataset'.
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+
+ return ((rdataset->methods->count)(rdataset));
+}
+
+void
+dns_rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
+
+ /*
+ * Make 'target' refer to the same rdataset as 'source'.
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(source));
+ REQUIRE(source->methods != NULL);
+ REQUIRE(DNS_RDATASET_VALID(target));
+ REQUIRE(target->methods == NULL);
+
+ (source->methods->clone)(source, target);
+}
+
+isc_result_t
+dns_rdataset_first(dns_rdataset_t *rdataset) {
+
+ /*
+ * Move the rdata cursor to the first rdata in the rdataset (if any).
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+
+ return ((rdataset->methods->first)(rdataset));
+}
+
+isc_result_t
+dns_rdataset_next(dns_rdataset_t *rdataset) {
+
+ /*
+ * Move the rdata cursor to the next rdata in the rdataset (if any).
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+
+ return ((rdataset->methods->next)(rdataset));
+}
+
+void
+dns_rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
+
+ /*
+ * Make 'rdata' refer to the current rdata.
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+
+ (rdataset->methods->current)(rdataset, rdata);
+}
+
+#define MAX_SHUFFLE 32
+#define WANT_FIXED(r) (((r)->attributes & DNS_RDATASETATTR_FIXEDORDER) != 0)
+#define WANT_RANDOM(r) (((r)->attributes & DNS_RDATASETATTR_RANDOMIZE) != 0)
+
+struct towire_sort {
+ int key;
+ dns_rdata_t *rdata;
+};
+
+static int
+towire_compare(const void *av, const void *bv) {
+ const struct towire_sort *a = (const struct towire_sort *) av;
+ const struct towire_sort *b = (const struct towire_sort *) bv;
+ return (a->key - b->key);
+}
+
+static isc_result_t
+towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name,
+ dns_compress_t *cctx, isc_buffer_t *target,
+ dns_rdatasetorderfunc_t order, const void *order_arg,
+ isc_boolean_t partial, unsigned int options,
+ unsigned int *countp, void **state)
+{
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_region_t r;
+ isc_result_t result;
+ unsigned int i, count, added, choice;
+ isc_buffer_t savedbuffer, rdlen, rrbuffer;
+ unsigned int headlen;
+ isc_boolean_t question = ISC_FALSE;
+ isc_boolean_t shuffle = ISC_FALSE;
+ dns_rdata_t *shuffled = NULL, shuffled_fixed[MAX_SHUFFLE];
+ struct towire_sort *sorted = NULL, sorted_fixed[MAX_SHUFFLE];
+
+ UNUSED(state);
+
+ /*
+ * Convert 'rdataset' to wire format, compressing names as specified
+ * in cctx, and storing the result in 'target'.
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(countp != NULL);
+ REQUIRE((order == NULL) == (order_arg == NULL));
+ REQUIRE(cctx != NULL && cctx->mctx != NULL);
+
+ count = 0;
+ if ((rdataset->attributes & DNS_RDATASETATTR_QUESTION) != 0) {
+ question = ISC_TRUE;
+ count = 1;
+ result = dns_rdataset_first(rdataset);
+ INSIST(result == ISC_R_NOMORE);
+ } else if (rdataset->type == 0) {
+ /*
+ * This is a negative caching rdataset.
+ */
+ unsigned int ncache_opts = 0;
+ if ((options & DNS_RDATASETTOWIRE_OMITDNSSEC) != 0)
+ ncache_opts |= DNS_NCACHETOWIRE_OMITDNSSEC;
+ return (dns_ncache_towire(rdataset, cctx, target, ncache_opts,
+ countp));
+ } else {
+ count = (rdataset->methods->count)(rdataset);
+ result = dns_rdataset_first(rdataset);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ /*
+ * Do we want to shuffle this anwer?
+ */
+ if (!question && count > 1 &&
+ (!WANT_FIXED(rdataset) || order != NULL) &&
+ rdataset->type != dns_rdatatype_rrsig)
+ shuffle = ISC_TRUE;
+
+ if (shuffle && count > MAX_SHUFFLE) {
+ shuffled = isc_mem_get(cctx->mctx, count * sizeof(*shuffled));
+ sorted = isc_mem_get(cctx->mctx, count * sizeof(*sorted));
+ if (shuffled == NULL || sorted == NULL)
+ shuffle = ISC_FALSE;
+ } else {
+ shuffled = shuffled_fixed;
+ sorted = sorted_fixed;
+ }
+
+ if (shuffle) {
+ /*
+ * First we get handles to all of the rdata.
+ */
+ i = 0;
+ do {
+ INSIST(i < count);
+ dns_rdata_init(&shuffled[i]);
+ dns_rdataset_current(rdataset, &shuffled[i]);
+ i++;
+ result = dns_rdataset_next(rdataset);
+ } while (result == ISC_R_SUCCESS);
+ if (result != ISC_R_NOMORE)
+ goto cleanup;
+ INSIST(i == count);
+
+ /*
+ * Now we shuffle.
+ */
+ if (WANT_FIXED(rdataset)) {
+ /*
+ * 'Fixed' order.
+ */
+ INSIST(order != NULL);
+ for (i = 0; i < count; i++) {
+ sorted[i].key = (*order)(&shuffled[i],
+ order_arg);
+ sorted[i].rdata = &shuffled[i];
+ }
+ } else if (WANT_RANDOM(rdataset)) {
+ /*
+ * 'Random' order.
+ */
+ for (i = 0; i < count; i++) {
+ dns_rdata_t rdata;
+ isc_uint32_t val;
+
+ isc_random_get(&val);
+ choice = i + (val % (count - i));
+ rdata = shuffled[i];
+ shuffled[i] = shuffled[choice];
+ shuffled[choice] = rdata;
+ if (order != NULL)
+ sorted[i].key = (*order)(&shuffled[i],
+ order_arg);
+ else
+ sorted[i].key = 0; /* Unused */
+ sorted[i].rdata = &shuffled[i];
+ }
+ } else {
+ /*
+ * "Cyclic" order.
+ */
+ isc_uint32_t val;
+ unsigned int j;
+
+ val = rdataset->count;
+ if (val == ISC_UINT32_MAX)
+ isc_random_get(&val);
+ j = val % count;
+ for (i = 0; i < count; i++) {
+ if (order != NULL)
+ sorted[j].key = (*order)(&shuffled[i],
+ order_arg);
+ else
+ sorted[j].key = 0; /* Unused */
+ sorted[j].rdata = &shuffled[i];
+ j++;
+ if (j == count)
+ j = 0; /* Wrap around. */
+ }
+ }
+
+ /*
+ * Sorted order.
+ */
+ if (order != NULL)
+ qsort(sorted, count, sizeof(sorted[0]),
+ towire_compare);
+ }
+
+ savedbuffer = *target;
+ i = 0;
+ added = 0;
+
+ do {
+ /*
+ * Copy out the name, type, class, ttl.
+ */
+
+ rrbuffer = *target;
+ dns_compress_setmethods(cctx, DNS_COMPRESS_GLOBAL14);
+ result = dns_name_towire(owner_name, cctx, target);
+ if (result != ISC_R_SUCCESS)
+ goto rollback;
+ headlen = sizeof(dns_rdataclass_t) + sizeof(dns_rdatatype_t);
+ if (!question)
+ headlen += sizeof(dns_ttl_t)
+ + 2; /* XXX 2 for rdata len */
+ isc_buffer_availableregion(target, &r);
+ if (r.length < headlen) {
+ result = ISC_R_NOSPACE;
+ goto rollback;
+ }
+ isc_buffer_putuint16(target, rdataset->type);
+ isc_buffer_putuint16(target, rdataset->rdclass);
+ if (!question) {
+ isc_buffer_putuint32(target, rdataset->ttl);
+
+ /*
+ * Save space for rdlen.
+ */
+ rdlen = *target;
+ isc_buffer_add(target, 2);
+
+ /*
+ * Copy out the rdata
+ */
+ if (shuffle)
+ rdata = *(sorted[i].rdata);
+ else {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ }
+ result = dns_rdata_towire(&rdata, cctx, target);
+ if (result != ISC_R_SUCCESS)
+ goto rollback;
+ INSIST((target->used >= rdlen.used + 2) &&
+ (target->used - rdlen.used - 2 < 65536));
+ isc_buffer_putuint16(&rdlen,
+ (isc_uint16_t)(target->used -
+ rdlen.used - 2));
+ added++;
+ }
+
+ if (shuffle) {
+ i++;
+ if (i == count)
+ result = ISC_R_NOMORE;
+ else
+ result = ISC_R_SUCCESS;
+ } else {
+ result = dns_rdataset_next(rdataset);
+ }
+ } while (result == ISC_R_SUCCESS);
+
+ if (result != ISC_R_NOMORE)
+ goto rollback;
+
+ *countp += count;
+
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+
+ rollback:
+ if (partial && result == ISC_R_NOSPACE) {
+ INSIST(rrbuffer.used < 65536);
+ dns_compress_rollback(cctx, (isc_uint16_t)rrbuffer.used);
+ *countp += added;
+ *target = rrbuffer;
+ goto cleanup;
+ }
+ INSIST(savedbuffer.used < 65536);
+ dns_compress_rollback(cctx, (isc_uint16_t)savedbuffer.used);
+ *countp = 0;
+ *target = savedbuffer;
+
+ cleanup:
+ if (sorted != NULL && sorted != sorted_fixed)
+ isc_mem_put(cctx->mctx, sorted, count * sizeof(*sorted));
+ if (shuffled != NULL && shuffled != shuffled_fixed)
+ isc_mem_put(cctx->mctx, shuffled, count * sizeof(*shuffled));
+ return (result);
+}
+
+isc_result_t
+dns_rdataset_towiresorted(dns_rdataset_t *rdataset,
+ const dns_name_t *owner_name,
+ dns_compress_t *cctx,
+ isc_buffer_t *target,
+ dns_rdatasetorderfunc_t order,
+ const void *order_arg,
+ unsigned int options,
+ unsigned int *countp)
+{
+ return (towiresorted(rdataset, owner_name, cctx, target,
+ order, order_arg, ISC_FALSE, options,
+ countp, NULL));
+}
+
+isc_result_t
+dns_rdataset_towirepartial(dns_rdataset_t *rdataset,
+ const dns_name_t *owner_name,
+ dns_compress_t *cctx,
+ isc_buffer_t *target,
+ dns_rdatasetorderfunc_t order,
+ const void *order_arg,
+ unsigned int options,
+ unsigned int *countp,
+ void **state)
+{
+ REQUIRE(state == NULL); /* XXX remove when implemented */
+ return (towiresorted(rdataset, owner_name, cctx, target,
+ order, order_arg, ISC_TRUE, options,
+ countp, state));
+}
+
+isc_result_t
+dns_rdataset_towire(dns_rdataset_t *rdataset,
+ dns_name_t *owner_name,
+ dns_compress_t *cctx,
+ isc_buffer_t *target,
+ unsigned int options,
+ unsigned int *countp)
+{
+ return (towiresorted(rdataset, owner_name, cctx, target,
+ NULL, NULL, ISC_FALSE, options, countp, NULL));
+}
+
+isc_result_t
+dns_rdataset_additionaldata(dns_rdataset_t *rdataset,
+ dns_additionaldatafunc_t add, void *arg)
+{
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+
+ /*
+ * For each rdata in rdataset, call 'add' for each name and type in the
+ * rdata which is subject to additional section processing.
+ */
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE((rdataset->attributes & DNS_RDATASETATTR_QUESTION) == 0);
+
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ do {
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_additionaldata(&rdata, add, arg);
+ if (result == ISC_R_SUCCESS)
+ result = dns_rdataset_next(rdataset);
+ dns_rdata_reset(&rdata);
+ } while (result == ISC_R_SUCCESS);
+
+ if (result != ISC_R_NOMORE)
+ return (result);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdataset_addnoqname(dns_rdataset_t *rdataset, dns_name_t *name) {
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+ if (rdataset->methods->addnoqname == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+ return((rdataset->methods->addnoqname)(rdataset, name));
+}
+
+isc_result_t
+dns_rdataset_getnoqname(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *neg, dns_rdataset_t *negsig)
+{
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+
+ if (rdataset->methods->getnoqname == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+ return((rdataset->methods->getnoqname)(rdataset, name, neg, negsig));
+}
+
+isc_result_t
+dns_rdataset_addclosest(dns_rdataset_t *rdataset, dns_name_t *name) {
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+ if (rdataset->methods->addclosest == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+ return((rdataset->methods->addclosest)(rdataset, name));
+}
+
+isc_result_t
+dns_rdataset_getclosest(dns_rdataset_t *rdataset, dns_name_t *name,
+ dns_rdataset_t *neg, dns_rdataset_t *negsig)
+{
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+
+ if (rdataset->methods->getclosest == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+ return((rdataset->methods->getclosest)(rdataset, name, neg, negsig));
+}
+
+/*
+ * Additional cache stuff
+ */
+isc_result_t
+dns_rdataset_getadditional(dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype,
+ dns_acache_t *acache,
+ dns_zone_t **zonep,
+ dns_db_t **dbp,
+ dns_dbversion_t **versionp,
+ dns_dbnode_t **nodep,
+ dns_name_t *fname,
+ dns_message_t *msg,
+ isc_stdtime_t now)
+{
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+ REQUIRE(zonep == NULL || *zonep == NULL);
+ REQUIRE(dbp != NULL && *dbp == NULL);
+ REQUIRE(versionp != NULL && *versionp == NULL);
+ REQUIRE(nodep != NULL && *nodep == NULL);
+ REQUIRE(fname != NULL);
+ REQUIRE(msg != NULL);
+
+ if (acache != NULL && rdataset->methods->getadditional != NULL) {
+ return ((rdataset->methods->getadditional)(rdataset, type,
+ qtype, acache,
+ zonep, dbp,
+ versionp, nodep,
+ fname, msg, now));
+ }
+
+ return (ISC_R_FAILURE);
+}
+
+isc_result_t
+dns_rdataset_setadditional(dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype,
+ dns_acache_t *acache,
+ dns_zone_t *zone,
+ dns_db_t *db,
+ dns_dbversion_t *version,
+ dns_dbnode_t *node,
+ dns_name_t *fname)
+{
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+
+ if (acache != NULL && rdataset->methods->setadditional != NULL) {
+ return ((rdataset->methods->setadditional)(rdataset, type,
+ qtype, acache, zone,
+ db, version,
+ node, fname));
+ }
+
+ return (ISC_R_FAILURE);
+}
+
+isc_result_t
+dns_rdataset_putadditional(dns_acache_t *acache,
+ dns_rdataset_t *rdataset,
+ dns_rdatasetadditional_t type,
+ dns_rdatatype_t qtype)
+{
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(rdataset->methods != NULL);
+
+ if (acache != NULL && rdataset->methods->putadditional != NULL) {
+ return ((rdataset->methods->putadditional)(acache, rdataset,
+ type, qtype));
+ }
+
+ return (ISC_R_FAILURE);
+}
+
diff --git a/lib/dns/rdatasetiter.c b/lib/dns/rdatasetiter.c
new file mode 100644
index 0000000..7ed3030
--- /dev/null
+++ b/lib/dns/rdatasetiter.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: rdatasetiter.c,v 1.16 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/util.h>
+
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+
+void
+dns_rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
+ /*
+ * Destroy '*iteratorp'.
+ */
+
+ REQUIRE(iteratorp != NULL);
+ REQUIRE(DNS_RDATASETITER_VALID(*iteratorp));
+
+ (*iteratorp)->methods->destroy(iteratorp);
+
+ ENSURE(*iteratorp == NULL);
+}
+
+isc_result_t
+dns_rdatasetiter_first(dns_rdatasetiter_t *iterator) {
+ /*
+ * Move the rdataset cursor to the first rdataset at the node (if any).
+ */
+
+ REQUIRE(DNS_RDATASETITER_VALID(iterator));
+
+ return (iterator->methods->first(iterator));
+}
+
+isc_result_t
+dns_rdatasetiter_next(dns_rdatasetiter_t *iterator) {
+ /*
+ * Move the rdataset cursor to the next rdataset at the node (if any).
+ */
+
+ REQUIRE(DNS_RDATASETITER_VALID(iterator));
+
+ return (iterator->methods->next(iterator));
+}
+
+void
+dns_rdatasetiter_current(dns_rdatasetiter_t *iterator,
+ dns_rdataset_t *rdataset)
+{
+ /*
+ * Return the current rdataset.
+ */
+
+ REQUIRE(DNS_RDATASETITER_VALID(iterator));
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(! dns_rdataset_isassociated(rdataset));
+
+ iterator->methods->current(iterator, rdataset);
+}
diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c
new file mode 100644
index 0000000..610d44f
--- /dev/null
+++ b/lib/dns/rdataslab.c
@@ -0,0 +1,1092 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: rdataslab.c,v 1.48 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/result.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdataslab.h>
+
+/*
+ * The rdataslab structure allows iteration to occur in both load order
+ * and DNSSEC order. The structure is as follows:
+ *
+ * header (reservelen bytes)
+ * record count (2 bytes)
+ * offset table (4 x record count bytes in load order)
+ * data records
+ * data length (2 bytes)
+ * order (2 bytes)
+ * meta data (1 byte for RRSIG's)
+ * data (data length bytes)
+ *
+ * If DNS_RDATASET_FIXED is defined to be zero (0) the format of a
+ * rdataslab is as follows:
+ *
+ * header (reservelen bytes)
+ * record count (2 bytes)
+ * data records
+ * data length (2 bytes)
+ * data (data length bytes)
+ *
+ * Offsets are from the end of the header.
+ *
+ * Load order traversal is performed by walking the offset table to find
+ * the start of the record (DNS_RDATASET_FIXED = 1).
+ *
+ * DNSSEC order traversal is performed by walking the data records.
+ *
+ * The order is stored with record to allow for efficient reconstuction of
+ * of the offset table following a merge or subtraction.
+ *
+ * The iterator methods here currently only support DNSSEC order iteration.
+ *
+ * The iterator methods in rbtdb support both load order and DNSSEC order
+ * iteration.
+ *
+ * WARNING:
+ * rbtdb.c directly interacts with the slab's raw structures. If the
+ * structure changes then rbtdb.c also needs to be updated to reflect
+ * the changes. See the areas tagged with "RDATASLAB".
+ */
+
+struct xrdata {
+ dns_rdata_t rdata;
+ unsigned int order;
+};
+
+/*% Note: the "const void *" are just to make qsort happy. */
+static int
+compare_rdata(const void *p1, const void *p2) {
+ const struct xrdata *x1 = p1;
+ const struct xrdata *x2 = p2;
+ return (dns_rdata_compare(&x1->rdata, &x2->rdata));
+}
+
+#if DNS_RDATASET_FIXED
+static void
+fillin_offsets(unsigned char *offsetbase, unsigned int *offsettable,
+ unsigned length)
+{
+ unsigned int i, j;
+ unsigned char *raw;
+
+ for (i = 0, j = 0; i < length; i++) {
+
+ if (offsettable[i] == 0)
+ continue;
+
+ /*
+ * Fill in offset table.
+ */
+ raw = &offsetbase[j*4 + 2];
+ *raw++ = (offsettable[i] & 0xff000000) >> 24;
+ *raw++ = (offsettable[i] & 0xff0000) >> 16;
+ *raw++ = (offsettable[i] & 0xff00) >> 8;
+ *raw = offsettable[i] & 0xff;
+
+ /*
+ * Fill in table index.
+ */
+ raw = offsetbase + offsettable[i] + 2;
+ *raw++ = (j & 0xff00) >> 8;
+ *raw = j++ & 0xff;
+ }
+}
+#endif
+
+isc_result_t
+dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
+ isc_region_t *region, unsigned int reservelen)
+{
+ struct xrdata *x;
+ unsigned char *rawbuf;
+#if DNS_RDATASET_FIXED
+ unsigned char *offsetbase;
+#endif
+ unsigned int buflen;
+ isc_result_t result;
+ unsigned int nitems;
+ unsigned int nalloc;
+ unsigned int i;
+#if DNS_RDATASET_FIXED
+ unsigned int *offsettable;
+#endif
+ unsigned int length;
+
+ buflen = reservelen + 2;
+
+ nalloc = dns_rdataset_count(rdataset);
+ nitems = nalloc;
+ if (nitems == 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);
+
+ /*
+ * Save all of the rdata members into an array.
+ */
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto free_rdatas;
+ for (i = 0; i < nalloc && result == ISC_R_SUCCESS; i++) {
+ INSIST(result == ISC_R_SUCCESS);
+ dns_rdata_init(&x[i].rdata);
+ dns_rdataset_current(rdataset, &x[i].rdata);
+#if DNS_RDATASET_FIXED
+ x[i].order = i;
+#endif
+ result = dns_rdataset_next(rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ goto free_rdatas;
+ if (i != nalloc) {
+ /*
+ * Somehow we iterated over fewer rdatas than
+ * dns_rdataset_count() said there were!
+ */
+ result = ISC_R_FAILURE;
+ goto free_rdatas;
+ }
+
+ /*
+ * Put into DNSSEC order.
+ */
+ qsort(x, nalloc, sizeof(struct xrdata), compare_rdata);
+
+ /*
+ * Remove duplicates and compute the total storage required.
+ *
+ * If an rdata is not a duplicate, accumulate the storage size
+ * required for the rdata. We do not store the class, type, etc,
+ * just the rdata, so our overhead is 2 bytes for the number of
+ * records, and 8 for each rdata, (length(2), offset(4) and order(2))
+ * and then the rdata itself.
+ */
+ for (i = 1; i < nalloc; i++) {
+ if (compare_rdata(&x[i-1].rdata, &x[i].rdata) == 0) {
+ x[i-1].rdata.data = NULL;
+ x[i-1].rdata.length = 0;
+#if DNS_RDATASET_FIXED
+ /*
+ * Preserve the least order so A, B, A -> A, B
+ * after duplicate removal.
+ */
+ if (x[i-1].order < x[i].order)
+ x[i].order = x[i-1].order;
+#endif
+ nitems--;
+ } else {
+#if DNS_RDATASET_FIXED
+ buflen += (8 + x[i-1].rdata.length);
+#else
+ buflen += (2 + x[i-1].rdata.length);
+#endif
+ /*
+ * Provide space to store the per RR meta data.
+ */
+ if (rdataset->type == dns_rdatatype_rrsig)
+ buflen++;
+ }
+ }
+ /*
+ * Don't forget the last item!
+ */
+#if DNS_RDATASET_FIXED
+ buflen += (8 + x[i-1].rdata.length);
+#else
+ buflen += (2 + x[i-1].rdata.length);
+#endif
+ /*
+ * Provide space to store the per RR meta data.
+ */
+ if (rdataset->type == dns_rdatatype_rrsig)
+ buflen++;
+
+ /*
+ * Ensure that singleton types are actually singletons.
+ */
+ if (nitems > 1 && dns_rdatatype_issingleton(rdataset->type)) {
+ /*
+ * We have a singleton type, but there's more than one
+ * RR in the rdataset.
+ */
+ result = DNS_R_SINGLETON;
+ goto free_rdatas;
+ }
+
+ /*
+ * Allocate the memory, set up a buffer, start copying in
+ * data.
+ */
+ rawbuf = isc_mem_get(mctx, buflen);
+ if (rawbuf == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto free_rdatas;
+ }
+
+#if DNS_RDATASET_FIXED
+ /* Allocate temporary offset table. */
+ offsettable = isc_mem_get(mctx, nalloc * sizeof(unsigned int));
+ if (offsettable == NULL) {
+ isc_mem_put(mctx, rawbuf, buflen);
+ result = ISC_R_NOMEMORY;
+ goto free_rdatas;
+ }
+ memset(offsettable, 0, nalloc * sizeof(unsigned int));
+#endif
+
+ region->base = rawbuf;
+ region->length = buflen;
+
+ rawbuf += reservelen;
+#if DNS_RDATASET_FIXED
+ offsetbase = rawbuf;
+#endif
+
+ *rawbuf++ = (nitems & 0xff00) >> 8;
+ *rawbuf++ = (nitems & 0x00ff);
+
+#if DNS_RDATASET_FIXED
+ /* Skip load order table. Filled in later. */
+ rawbuf += nitems * 4;
+#endif
+
+ for (i = 0; i < nalloc; i++) {
+ if (x[i].rdata.data == NULL)
+ continue;
+#if DNS_RDATASET_FIXED
+ offsettable[x[i].order] = rawbuf - offsetbase;
+#endif
+ length = x[i].rdata.length;
+ if (rdataset->type == dns_rdatatype_rrsig)
+ length++;
+ *rawbuf++ = (length & 0xff00) >> 8;
+ *rawbuf++ = (length & 0x00ff);
+#if DNS_RDATASET_FIXED
+ rawbuf += 2; /* filled in later */
+#endif
+ /*
+ * Store the per RR meta data.
+ */
+ if (rdataset->type == dns_rdatatype_rrsig) {
+ *rawbuf++ |= (x[i].rdata.flags & DNS_RDATA_OFFLINE) ?
+ DNS_RDATASLAB_OFFLINE : 0;
+ }
+ memcpy(rawbuf, x[i].rdata.data, x[i].rdata.length);
+ rawbuf += x[i].rdata.length;
+ }
+
+#if DNS_RDATASET_FIXED
+ fillin_offsets(offsetbase, offsettable, nalloc);
+ isc_mem_put(mctx, offsettable, nalloc * sizeof(unsigned int));
+#endif
+
+ result = ISC_R_SUCCESS;
+
+ free_rdatas:
+ isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata));
+ return (result);
+}
+
+static void
+rdataset_disassociate(dns_rdataset_t *rdataset) {
+ UNUSED(rdataset);
+}
+
+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);
+ }
+#if DNS_RDATASET_FIXED
+ raw += 2 + (4 * count);
+#else
+ raw += 2;
+#endif
+ /*
+ * 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];
+#if DNS_RDATASET_FIXED
+ raw += length + 4;
+#else
+ raw += length + 2;
+#endif
+ 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];
+#if DNS_RDATASET_FIXED
+ raw += 4;
+#else
+ raw += 2;
+#endif
+ 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) {
+ *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 dns_rdatasetmethods_t rdataset_methods = {
+ rdataset_disassociate,
+ rdataset_first,
+ rdataset_next,
+ rdataset_current,
+ rdataset_clone,
+ rdataset_count,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+void
+dns_rdataslab_tordataset(unsigned char *slab, unsigned int reservelen,
+ dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
+ dns_rdatatype_t covers, dns_ttl_t ttl,
+ dns_rdataset_t *rdataset)
+{
+ REQUIRE(slab != NULL);
+ REQUIRE(!dns_rdataset_isassociated(rdataset));
+
+ rdataset->methods = &rdataset_methods;
+ rdataset->rdclass = rdclass;
+ rdataset->type = rdtype;
+ rdataset->covers = covers;
+ rdataset->ttl = ttl;
+ rdataset->trust = 0;
+ rdataset->private1 = NULL;
+ rdataset->private2 = NULL;
+ rdataset->private3 = slab + reservelen;
+
+ /*
+ * Reset iterator state.
+ */
+ rdataset->privateuint4 = 0;
+ rdataset->private5 = NULL;
+}
+
+unsigned int
+dns_rdataslab_size(unsigned char *slab, unsigned int reservelen) {
+ unsigned int count, length;
+ unsigned char *current;
+
+ REQUIRE(slab != NULL);
+
+ current = slab + reservelen;
+ count = *current++ * 256;
+ count += *current++;
+#if DNS_RDATASET_FIXED
+ current += (4 * count);
+#endif
+ while (count > 0) {
+ count--;
+ length = *current++ * 256;
+ length += *current++;
+#if DNS_RDATASET_FIXED
+ current += length + 2;
+#else
+ current += length;
+#endif
+ }
+
+ return ((unsigned int)(current - slab));
+}
+
+/*
+ * Make the dns_rdata_t 'rdata' refer to the slab item
+ * beginning at '*current', which is part of a slab of type
+ * 'type' and class 'rdclass', and advance '*current' to
+ * point to the next item in the slab.
+ */
+static inline void
+rdata_from_slab(unsigned char **current,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ dns_rdata_t *rdata)
+{
+ unsigned char *tcurrent = *current;
+ isc_region_t region;
+ unsigned int length;
+ isc_boolean_t offline = ISC_FALSE;
+
+ length = *tcurrent++ * 256;
+ length += *tcurrent++;
+
+ if (type == dns_rdatatype_rrsig) {
+ if ((*tcurrent & DNS_RDATASLAB_OFFLINE) != 0)
+ offline = ISC_TRUE;
+ length--;
+ tcurrent++;
+ }
+ region.length = length;
+#if DNS_RDATASET_FIXED
+ tcurrent += 2;
+#endif
+ region.base = tcurrent;
+ tcurrent += region.length;
+ dns_rdata_fromregion(rdata, rdclass, type, &region);
+ if (offline)
+ rdata->flags |= DNS_RDATA_OFFLINE;
+ *current = tcurrent;
+}
+
+/*
+ * Return true iff 'slab' (slab data of type 'type' and class 'rdclass')
+ * contains an rdata identical to 'rdata'. This does case insensitive
+ * comparisons per DNSSEC.
+ */
+static inline isc_boolean_t
+rdata_in_slab(unsigned char *slab, unsigned int reservelen,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ dns_rdata_t *rdata)
+{
+ unsigned int count, i;
+ unsigned char *current;
+ dns_rdata_t trdata = DNS_RDATA_INIT;
+ int n;
+
+ current = slab + reservelen;
+ count = *current++ * 256;
+ count += *current++;
+
+#if DNS_RDATASET_FIXED
+ current += (4 * count);
+#endif
+
+ for (i = 0; i < count; i++) {
+ rdata_from_slab(&current, rdclass, type, &trdata);
+
+ n = dns_rdata_compare(&trdata, rdata);
+ if (n == 0)
+ return (ISC_TRUE);
+ if (n > 0) /* In DNSSEC order. */
+ break;
+ dns_rdata_reset(&trdata);
+ }
+ return (ISC_FALSE);
+}
+
+isc_result_t
+dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab,
+ unsigned int reservelen, isc_mem_t *mctx,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ unsigned int flags, unsigned char **tslabp)
+{
+ unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent, *data;
+ unsigned int ocount, ncount, count, olength, tlength, tcount, length;
+ dns_rdata_t ordata = DNS_RDATA_INIT;
+ dns_rdata_t nrdata = DNS_RDATA_INIT;
+ isc_boolean_t added_something = ISC_FALSE;
+ unsigned int oadded = 0;
+ unsigned int nadded = 0;
+ unsigned int nncount = 0;
+#if DNS_RDATASET_FIXED
+ unsigned int oncount;
+ unsigned int norder = 0;
+ unsigned int oorder = 0;
+ unsigned char *offsetbase;
+ unsigned int *offsettable;
+#endif
+
+ /*
+ * XXX Need parameter to allow "delete rdatasets in nslab" merge,
+ * or perhaps another merge routine for this purpose.
+ */
+
+ REQUIRE(tslabp != NULL && *tslabp == NULL);
+ REQUIRE(oslab != NULL && nslab != NULL);
+
+ ocurrent = oslab + reservelen;
+ ocount = *ocurrent++ * 256;
+ ocount += *ocurrent++;
+#if DNS_RDATASET_FIXED
+ ocurrent += (4 * ocount);
+#endif
+ ostart = ocurrent;
+ ncurrent = nslab + reservelen;
+ ncount = *ncurrent++ * 256;
+ ncount += *ncurrent++;
+#if DNS_RDATASET_FIXED
+ ncurrent += (4 * ncount);
+#endif
+ INSIST(ocount > 0 && ncount > 0);
+
+#if DNS_RDATASET_FIXED
+ oncount = ncount;
+#endif
+
+ /*
+ * Yes, this is inefficient!
+ */
+
+ /*
+ * Figure out the length of the old slab's data.
+ */
+ olength = 0;
+ for (count = 0; count < ocount; count++) {
+ length = *ocurrent++ * 256;
+ length += *ocurrent++;
+#if DNS_RDATASET_FIXED
+ olength += length + 8;
+ ocurrent += length + 2;
+#else
+ olength += length + 2;
+ ocurrent += length;
+#endif
+ }
+
+ /*
+ * Start figuring out the target length and count.
+ */
+ tlength = reservelen + 2 + olength;
+ tcount = ocount;
+
+ /*
+ * Add in the length of rdata in the new slab that aren't in
+ * the old slab.
+ */
+ do {
+ dns_rdata_init(&nrdata);
+ rdata_from_slab(&ncurrent, rdclass, type, &nrdata);
+ if (!rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata))
+ {
+ /*
+ * This rdata isn't in the old slab.
+ */
+#if DNS_RDATASET_FIXED
+ tlength += nrdata.length + 8;
+#else
+ tlength += nrdata.length + 2;
+#endif
+ if (type == dns_rdatatype_rrsig)
+ tlength++;
+ tcount++;
+ nncount++;
+ added_something = ISC_TRUE;
+ }
+ ncount--;
+ } while (ncount > 0);
+ ncount = nncount;
+
+ if (((flags & DNS_RDATASLAB_EXACT) != 0) &&
+ (tcount != ncount + ocount))
+ return (DNS_R_NOTEXACT);
+
+ if (!added_something && (flags & DNS_RDATASLAB_FORCE) == 0)
+ return (DNS_R_UNCHANGED);
+
+ /*
+ * Ensure that singleton types are actually singletons.
+ */
+ if (tcount > 1 && dns_rdatatype_issingleton(type)) {
+ /*
+ * We have a singleton type, but there's more than one
+ * RR in the rdataset.
+ */
+ return (DNS_R_SINGLETON);
+ }
+
+ if (tcount > 0xffff)
+ return (ISC_R_NOSPACE);
+
+ /*
+ * Copy the reserved area from the new slab.
+ */
+ tstart = isc_mem_get(mctx, tlength);
+ if (tstart == NULL)
+ return (ISC_R_NOMEMORY);
+ memcpy(tstart, nslab, reservelen);
+ tcurrent = tstart + reservelen;
+#if DNS_RDATASET_FIXED
+ offsetbase = tcurrent;
+#endif
+
+ /*
+ * Write the new count.
+ */
+ *tcurrent++ = (tcount & 0xff00) >> 8;
+ *tcurrent++ = (tcount & 0x00ff);
+
+#if DNS_RDATASET_FIXED
+ /*
+ * Skip offset table.
+ */
+ tcurrent += (tcount * 4);
+
+ offsettable = isc_mem_get(mctx,
+ (ocount + oncount) * sizeof(unsigned int));
+ if (offsettable == NULL) {
+ isc_mem_put(mctx, tstart, tlength);
+ return (ISC_R_NOMEMORY);
+ }
+ memset(offsettable, 0, (ocount + oncount) * sizeof(unsigned int));
+#endif
+
+ /*
+ * Merge the two slabs.
+ */
+ ocurrent = ostart;
+ INSIST(ocount != 0);
+#if DNS_RDATASET_FIXED
+ oorder = ocurrent[2] * 256 + ocurrent[3];
+ INSIST(oorder < ocount);
+#endif
+ rdata_from_slab(&ocurrent, rdclass, type, &ordata);
+
+ ncurrent = nslab + reservelen + 2;
+#if DNS_RDATASET_FIXED
+ ncurrent += (4 * oncount);
+#endif
+
+ if (ncount > 0) {
+ do {
+ dns_rdata_reset(&nrdata);
+#if DNS_RDATASET_FIXED
+ norder = ncurrent[2] * 256 + ncurrent[3];
+
+ INSIST(norder < oncount);
+#endif
+ rdata_from_slab(&ncurrent, rdclass, type, &nrdata);
+ } while (rdata_in_slab(oslab, reservelen, rdclass,
+ type, &nrdata));
+ }
+
+ while (oadded < ocount || nadded < ncount) {
+ isc_boolean_t fromold;
+ if (oadded == ocount)
+ fromold = ISC_FALSE;
+ else if (nadded == ncount)
+ fromold = ISC_TRUE;
+ else
+ fromold = ISC_TF(compare_rdata(&ordata, &nrdata) < 0);
+ if (fromold) {
+#if DNS_RDATASET_FIXED
+ offsettable[oorder] = tcurrent - offsetbase;
+#endif
+ length = ordata.length;
+ data = ordata.data;
+ if (type == dns_rdatatype_rrsig) {
+ length++;
+ data--;
+ }
+ *tcurrent++ = (length & 0xff00) >> 8;
+ *tcurrent++ = (length & 0x00ff);
+#if DNS_RDATASET_FIXED
+ tcurrent += 2; /* fill in later */
+#endif
+ memcpy(tcurrent, data, length);
+ tcurrent += length;
+ oadded++;
+ if (oadded < ocount) {
+ dns_rdata_reset(&ordata);
+#if DNS_RDATASET_FIXED
+ oorder = ocurrent[2] * 256 + ocurrent[3];
+ INSIST(oorder < ocount);
+#endif
+ rdata_from_slab(&ocurrent, rdclass, type,
+ &ordata);
+ }
+ } else {
+#if DNS_RDATASET_FIXED
+ offsettable[ocount + norder] = tcurrent - offsetbase;
+#endif
+ length = nrdata.length;
+ data = nrdata.data;
+ if (type == dns_rdatatype_rrsig) {
+ length++;
+ data--;
+ }
+ *tcurrent++ = (length & 0xff00) >> 8;
+ *tcurrent++ = (length & 0x00ff);
+#if DNS_RDATASET_FIXED
+ tcurrent += 2; /* fill in later */
+#endif
+ memcpy(tcurrent, data, length);
+ tcurrent += length;
+ nadded++;
+ if (nadded < ncount) {
+ do {
+ dns_rdata_reset(&nrdata);
+#if DNS_RDATASET_FIXED
+ norder = ncurrent[2] * 256 + ncurrent[3];
+ INSIST(norder < oncount);
+#endif
+ rdata_from_slab(&ncurrent, rdclass,
+ type, &nrdata);
+ } while (rdata_in_slab(oslab, reservelen,
+ rdclass, type,
+ &nrdata));
+ }
+ }
+ }
+
+#if DNS_RDATASET_FIXED
+ fillin_offsets(offsetbase, offsettable, ocount + oncount);
+
+ isc_mem_put(mctx, offsettable,
+ (ocount + oncount) * sizeof(unsigned int));
+#endif
+
+ INSIST(tcurrent == tstart + tlength);
+
+ *tslabp = tstart;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_rdataslab_subtract(unsigned char *mslab, unsigned char *sslab,
+ unsigned int reservelen, isc_mem_t *mctx,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ unsigned int flags, unsigned char **tslabp)
+{
+ unsigned char *mcurrent, *sstart, *scurrent, *tstart, *tcurrent;
+ unsigned int mcount, scount, rcount ,count, tlength, tcount, i;
+ dns_rdata_t srdata = DNS_RDATA_INIT;
+ dns_rdata_t mrdata = DNS_RDATA_INIT;
+#if DNS_RDATASET_FIXED
+ unsigned char *offsetbase;
+ unsigned int *offsettable;
+ unsigned int order;
+#endif
+
+ REQUIRE(tslabp != NULL && *tslabp == NULL);
+ REQUIRE(mslab != NULL && sslab != NULL);
+
+ mcurrent = mslab + reservelen;
+ mcount = *mcurrent++ * 256;
+ mcount += *mcurrent++;
+ scurrent = sslab + reservelen;
+ scount = *scurrent++ * 256;
+ scount += *scurrent++;
+ INSIST(mcount > 0 && scount > 0);
+
+ /*
+ * Yes, this is inefficient!
+ */
+
+ /*
+ * Start figuring out the target length and count.
+ */
+ tlength = reservelen + 2;
+ tcount = 0;
+ rcount = 0;
+
+#if DNS_RDATASET_FIXED
+ mcurrent += 4 * mcount;
+ scurrent += 4 * scount;
+#endif
+ sstart = scurrent;
+
+ /*
+ * Add in the length of rdata in the mslab that aren't in
+ * the sslab.
+ */
+ for (i = 0; i < mcount; i++) {
+ unsigned char *mrdatabegin = mcurrent;
+ rdata_from_slab(&mcurrent, rdclass, type, &mrdata);
+ scurrent = sstart;
+ for (count = 0; count < scount; count++) {
+ dns_rdata_reset(&srdata);
+ rdata_from_slab(&scurrent, rdclass, type, &srdata);
+ if (dns_rdata_compare(&mrdata, &srdata) == 0)
+ break;
+ }
+ if (count == scount) {
+ /*
+ * This rdata isn't in the sslab, and thus isn't
+ * being subtracted.
+ */
+ tlength += mcurrent - mrdatabegin;
+ tcount++;
+ } else
+ rcount++;
+ dns_rdata_reset(&mrdata);
+ }
+
+#if DNS_RDATASET_FIXED
+ tlength += (4 * tcount);
+#endif
+
+ /*
+ * Check that all the records originally existed. The numeric
+ * check only works as rdataslabs do not contain duplicates.
+ */
+ if (((flags & DNS_RDATASLAB_EXACT) != 0) && (rcount != scount))
+ return (DNS_R_NOTEXACT);
+
+ /*
+ * Don't continue if the new rdataslab would be empty.
+ */
+ if (tcount == 0)
+ return (DNS_R_NXRRSET);
+
+ /*
+ * If nothing is going to change, we can stop.
+ */
+ if (rcount == 0)
+ return (DNS_R_UNCHANGED);
+
+ /*
+ * Copy the reserved area from the mslab.
+ */
+ tstart = isc_mem_get(mctx, tlength);
+ if (tstart == NULL)
+ return (ISC_R_NOMEMORY);
+ memcpy(tstart, mslab, reservelen);
+ tcurrent = tstart + reservelen;
+#if DNS_RDATASET_FIXED
+ offsetbase = tcurrent;
+
+ offsettable = isc_mem_get(mctx, mcount * sizeof(unsigned int));
+ if (offsettable == NULL) {
+ isc_mem_put(mctx, tstart, tlength);
+ return (ISC_R_NOMEMORY);
+ }
+ memset(offsettable, 0, mcount * sizeof(unsigned int));
+#endif
+
+ /*
+ * Write the new count.
+ */
+ *tcurrent++ = (tcount & 0xff00) >> 8;
+ *tcurrent++ = (tcount & 0x00ff);
+
+#if DNS_RDATASET_FIXED
+ tcurrent += (4 * tcount);
+#endif
+
+ /*
+ * Copy the parts of mslab not in sslab.
+ */
+ mcurrent = mslab + reservelen;
+ mcount = *mcurrent++ * 256;
+ mcount += *mcurrent++;
+#if DNS_RDATASET_FIXED
+ mcurrent += (4 * mcount);
+#endif
+ for (i = 0; i < mcount; i++) {
+ unsigned char *mrdatabegin = mcurrent;
+#if DNS_RDATASET_FIXED
+ order = mcurrent[2] * 256 + mcurrent[3];
+ INSIST(order < mcount);
+#endif
+ rdata_from_slab(&mcurrent, rdclass, type, &mrdata);
+ scurrent = sstart;
+ for (count = 0; count < scount; count++) {
+ dns_rdata_reset(&srdata);
+ rdata_from_slab(&scurrent, rdclass, type, &srdata);
+ if (dns_rdata_compare(&mrdata, &srdata) == 0)
+ break;
+ }
+ if (count == scount) {
+ /*
+ * This rdata isn't in the sslab, and thus should be
+ * copied to the tslab.
+ */
+ unsigned int length = mcurrent - mrdatabegin;
+#if DNS_RDATASET_FIXED
+ offsettable[order] = tcurrent - offsetbase;
+#endif
+ memcpy(tcurrent, mrdatabegin, length);
+ tcurrent += length;
+ }
+ dns_rdata_reset(&mrdata);
+ }
+
+#if DNS_RDATASET_FIXED
+ fillin_offsets(offsetbase, offsettable, mcount);
+
+ isc_mem_put(mctx, offsettable, mcount * sizeof(unsigned int));
+#endif
+
+ INSIST(tcurrent == tstart + tlength);
+
+ *tslabp = tstart;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+dns_rdataslab_equal(unsigned char *slab1, unsigned char *slab2,
+ unsigned int reservelen)
+{
+ unsigned char *current1, *current2;
+ unsigned int count1, count2;
+ unsigned int length1, length2;
+
+ current1 = slab1 + reservelen;
+ count1 = *current1++ * 256;
+ count1 += *current1++;
+
+ current2 = slab2 + reservelen;
+ count2 = *current2++ * 256;
+ count2 += *current2++;
+
+ if (count1 != count2)
+ return (ISC_FALSE);
+
+#if DNS_RDATASET_FIXED
+ current1 += (4 * count1);
+ current2 += (4 * count2);
+#endif
+
+ while (count1 > 0) {
+ length1 = *current1++ * 256;
+ length1 += *current1++;
+
+ length2 = *current2++ * 256;
+ length2 += *current2++;
+
+#if DNS_RDATASET_FIXED
+ current1 += 2;
+ current2 += 2;
+#endif
+
+ if (length1 != length2 ||
+ memcmp(current1, current2, length1) != 0)
+ return (ISC_FALSE);
+
+ current1 += length1;
+ current2 += length1;
+
+ count1--;
+ }
+ return (ISC_TRUE);
+}
+
+isc_boolean_t
+dns_rdataslab_equalx(unsigned char *slab1, unsigned char *slab2,
+ unsigned int reservelen, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type)
+{
+ unsigned char *current1, *current2;
+ unsigned int count1, count2;
+ dns_rdata_t rdata1 = DNS_RDATA_INIT;
+ dns_rdata_t rdata2 = DNS_RDATA_INIT;
+
+ current1 = slab1 + reservelen;
+ count1 = *current1++ * 256;
+ count1 += *current1++;
+
+ current2 = slab2 + reservelen;
+ count2 = *current2++ * 256;
+ count2 += *current2++;
+
+ if (count1 != count2)
+ return (ISC_FALSE);
+
+#if DNS_RDATASET_FIXED
+ current1 += (4 * count1);
+ current2 += (4 * count2);
+#endif
+
+ while (count1-- > 0) {
+ rdata_from_slab(&current1, rdclass, type, &rdata1);
+ rdata_from_slab(&current2, rdclass, type, &rdata2);
+ if (dns_rdata_compare(&rdata1, &rdata2) != 0)
+ return (ISC_FALSE);
+ dns_rdata_reset(&rdata1);
+ dns_rdata_reset(&rdata2);
+ }
+ return (ISC_TRUE);
+}
diff --git a/lib/dns/request.c b/lib/dns/request.c
new file mode 100644
index 0000000..af75668
--- /dev/null
+++ b/lib/dns/request.c
@@ -0,0 +1,1497 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: request.c,v 1.82 2008/07/22 03:43:04 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/compress.h>
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/rdata.h>
+#include <dns/rdatastruct.h>
+#include <dns/request.h>
+#include <dns/result.h>
+#include <dns/tsig.h>
+
+#define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M')
+#define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC)
+
+#define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!')
+#define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC)
+
+typedef ISC_LIST(dns_request_t) dns_requestlist_t;
+
+#define DNS_REQUEST_NLOCKS 7
+
+struct dns_requestmgr {
+ unsigned int magic;
+ isc_mutex_t lock;
+ isc_mem_t *mctx;
+
+ /* locked */
+ isc_int32_t eref;
+ isc_int32_t iref;
+ isc_timermgr_t *timermgr;
+ isc_socketmgr_t *socketmgr;
+ isc_taskmgr_t *taskmgr;
+ dns_dispatchmgr_t *dispatchmgr;
+ dns_dispatch_t *dispatchv4;
+ dns_dispatch_t *dispatchv6;
+ isc_boolean_t exiting;
+ isc_eventlist_t whenshutdown;
+ unsigned int hash;
+ isc_mutex_t locks[DNS_REQUEST_NLOCKS];
+ dns_requestlist_t requests;
+};
+
+struct dns_request {
+ unsigned int magic;
+ unsigned int hash;
+ isc_mem_t *mctx;
+ isc_int32_t flags;
+ ISC_LINK(dns_request_t) link;
+ isc_buffer_t *query;
+ isc_buffer_t *answer;
+ dns_requestevent_t *event;
+ dns_dispatch_t *dispatch;
+ dns_dispentry_t *dispentry;
+ isc_timer_t *timer;
+ dns_requestmgr_t *requestmgr;
+ isc_buffer_t *tsig;
+ dns_tsigkey_t *tsigkey;
+ isc_event_t ctlevent;
+ isc_boolean_t canceling; /* ctlevent outstanding */
+ isc_sockaddr_t destaddr;
+ unsigned int udpcount;
+};
+
+#define DNS_REQUEST_F_CONNECTING 0x0001
+#define DNS_REQUEST_F_SENDING 0x0002
+#define DNS_REQUEST_F_CANCELED 0x0004 /*%< ctlevent received, or otherwise
+ synchronously canceled */
+#define DNS_REQUEST_F_TIMEDOUT 0x0008 /*%< cancelled due to a timeout */
+#define DNS_REQUEST_F_TCP 0x0010 /*%< This request used TCP */
+#define DNS_REQUEST_CANCELED(r) \
+ (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)
+#define DNS_REQUEST_CONNECTING(r) \
+ (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)
+#define DNS_REQUEST_SENDING(r) \
+ (((r)->flags & DNS_REQUEST_F_SENDING) != 0)
+#define DNS_REQUEST_TIMEDOUT(r) \
+ (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)
+
+
+/***
+ *** Forward
+ ***/
+
+static void mgr_destroy(dns_requestmgr_t *requestmgr);
+static void mgr_shutdown(dns_requestmgr_t *requestmgr);
+static unsigned int mgr_gethash(dns_requestmgr_t *requestmgr);
+static void send_shutdown_events(dns_requestmgr_t *requestmgr);
+
+static isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer,
+ unsigned int options, isc_mem_t *mctx);
+static void req_senddone(isc_task_t *task, isc_event_t *event);
+static void req_response(isc_task_t *task, isc_event_t *event);
+static void req_timeout(isc_task_t *task, isc_event_t *event);
+static isc_socket_t * req_getsocket(dns_request_t *request);
+static void req_connected(isc_task_t *task, isc_event_t *event);
+static void req_sendevent(dns_request_t *request, isc_result_t result);
+static void req_cancel(dns_request_t *request);
+static void req_destroy(dns_request_t *request);
+static void req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
+static void do_cancel(isc_task_t *task, isc_event_t *event);
+
+/***
+ *** Public
+ ***/
+
+isc_result_t
+dns_requestmgr_create(isc_mem_t *mctx,
+ isc_timermgr_t *timermgr,
+ isc_socketmgr_t *socketmgr,
+ isc_taskmgr_t *taskmgr,
+ dns_dispatchmgr_t *dispatchmgr,
+ dns_dispatch_t *dispatchv4,
+ dns_dispatch_t *dispatchv6,
+ dns_requestmgr_t **requestmgrp)
+{
+ dns_requestmgr_t *requestmgr;
+ isc_socket_t *socket;
+ isc_result_t result;
+ int i;
+ unsigned int dispattr;
+
+ req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
+
+ REQUIRE(requestmgrp != NULL && *requestmgrp == NULL);
+ REQUIRE(timermgr != NULL);
+ REQUIRE(socketmgr != NULL);
+ REQUIRE(taskmgr != NULL);
+ REQUIRE(dispatchmgr != NULL);
+ UNUSED(socket);
+ if (dispatchv4 != NULL) {
+ dispattr = dns_dispatch_getattributes(dispatchv4);
+ REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
+ }
+ if (dispatchv6 != NULL) {
+ dispattr = dns_dispatch_getattributes(dispatchv6);
+ REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
+ }
+
+ requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
+ if (requestmgr == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&requestmgr->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
+ return (result);
+ }
+ for (i = 0; i < DNS_REQUEST_NLOCKS; i++) {
+ result = isc_mutex_init(&requestmgr->locks[i]);
+ if (result != ISC_R_SUCCESS) {
+ while (--i >= 0)
+ DESTROYLOCK(&requestmgr->locks[i]);
+ DESTROYLOCK(&requestmgr->lock);
+ isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
+ return (result);
+ }
+ }
+ requestmgr->timermgr = timermgr;
+ requestmgr->socketmgr = socketmgr;
+ requestmgr->taskmgr = taskmgr;
+ requestmgr->dispatchmgr = dispatchmgr;
+ requestmgr->dispatchv4 = NULL;
+ if (dispatchv4 != NULL)
+ dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4);
+ requestmgr->dispatchv6 = NULL;
+ if (dispatchv6 != NULL)
+ dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6);
+ requestmgr->mctx = NULL;
+ isc_mem_attach(mctx, &requestmgr->mctx);
+ requestmgr->eref = 1; /* implict attach */
+ requestmgr->iref = 0;
+ ISC_LIST_INIT(requestmgr->whenshutdown);
+ ISC_LIST_INIT(requestmgr->requests);
+ requestmgr->exiting = ISC_FALSE;
+ requestmgr->hash = 0;
+ requestmgr->magic = REQUESTMGR_MAGIC;
+
+ req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr);
+
+ *requestmgrp = requestmgr;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task,
+ isc_event_t **eventp)
+{
+ isc_task_t *clone;
+ isc_event_t *event;
+
+ req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown");
+
+ REQUIRE(VALID_REQUESTMGR(requestmgr));
+ REQUIRE(eventp != NULL);
+
+ event = *eventp;
+ *eventp = NULL;
+
+ LOCK(&requestmgr->lock);
+
+ if (requestmgr->exiting) {
+ /*
+ * We're already shutdown. Send the event.
+ */
+ event->ev_sender = requestmgr;
+ isc_task_send(task, &event);
+ } else {
+ clone = NULL;
+ isc_task_attach(task, &clone);
+ event->ev_sender = clone;
+ ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link);
+ }
+ UNLOCK(&requestmgr->lock);
+}
+
+void
+dns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) {
+
+ REQUIRE(VALID_REQUESTMGR(requestmgr));
+
+ req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr);
+
+ LOCK(&requestmgr->lock);
+ mgr_shutdown(requestmgr);
+ UNLOCK(&requestmgr->lock);
+}
+
+static void
+mgr_shutdown(dns_requestmgr_t *requestmgr) {
+ dns_request_t *request;
+
+ /*
+ * Caller holds lock.
+ */
+ if (!requestmgr->exiting) {
+ requestmgr->exiting = ISC_TRUE;
+ for (request = ISC_LIST_HEAD(requestmgr->requests);
+ request != NULL;
+ request = ISC_LIST_NEXT(request, link)) {
+ dns_request_cancel(request);
+ }
+ if (requestmgr->iref == 0) {
+ INSIST(ISC_LIST_EMPTY(requestmgr->requests));
+ send_shutdown_events(requestmgr);
+ }
+ }
+}
+
+static void
+requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
+
+ /*
+ * Locked by caller.
+ */
+
+ REQUIRE(VALID_REQUESTMGR(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ REQUIRE(!source->exiting);
+
+ source->iref++;
+ *targetp = source;
+
+ req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d",
+ source, source->eref, source->iref);
+}
+
+static void
+requestmgr_detach(dns_requestmgr_t **requestmgrp) {
+ dns_requestmgr_t *requestmgr;
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(requestmgrp != NULL);
+ requestmgr = *requestmgrp;
+ REQUIRE(VALID_REQUESTMGR(requestmgr));
+
+ *requestmgrp = NULL;
+ LOCK(&requestmgr->lock);
+ INSIST(requestmgr->iref > 0);
+ requestmgr->iref--;
+
+ req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d",
+ requestmgr, requestmgr->eref, requestmgr->iref);
+
+ if (requestmgr->iref == 0 && requestmgr->exiting) {
+ INSIST(ISC_LIST_HEAD(requestmgr->requests) == NULL);
+ send_shutdown_events(requestmgr);
+ if (requestmgr->eref == 0)
+ need_destroy = ISC_TRUE;
+ }
+ UNLOCK(&requestmgr->lock);
+
+ if (need_destroy)
+ mgr_destroy(requestmgr);
+}
+
+void
+dns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) {
+
+ REQUIRE(VALID_REQUESTMGR(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+ REQUIRE(!source->exiting);
+
+ LOCK(&source->lock);
+ source->eref++;
+ *targetp = source;
+ UNLOCK(&source->lock);
+
+ req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d",
+ source, source->eref, source->iref);
+}
+
+void
+dns_requestmgr_detach(dns_requestmgr_t **requestmgrp) {
+ dns_requestmgr_t *requestmgr;
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(requestmgrp != NULL);
+ requestmgr = *requestmgrp;
+ REQUIRE(VALID_REQUESTMGR(requestmgr));
+
+ LOCK(&requestmgr->lock);
+ INSIST(requestmgr->eref > 0);
+ requestmgr->eref--;
+
+ req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d",
+ requestmgr, requestmgr->eref, requestmgr->iref);
+
+ if (requestmgr->eref == 0 && requestmgr->iref == 0) {
+ INSIST(requestmgr->exiting &&
+ ISC_LIST_HEAD(requestmgr->requests) == NULL);
+ need_destroy = ISC_TRUE;
+ }
+ UNLOCK(&requestmgr->lock);
+
+ if (need_destroy)
+ mgr_destroy(requestmgr);
+
+ *requestmgrp = NULL;
+}
+
+static void
+send_shutdown_events(dns_requestmgr_t *requestmgr) {
+ isc_event_t *event, *next_event;
+ isc_task_t *etask;
+
+ req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr);
+
+ /*
+ * Caller must be holding the manager lock.
+ */
+ for (event = ISC_LIST_HEAD(requestmgr->whenshutdown);
+ event != NULL;
+ event = next_event) {
+ next_event = ISC_LIST_NEXT(event, ev_link);
+ ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link);
+ etask = event->ev_sender;
+ event->ev_sender = requestmgr;
+ isc_task_sendanddetach(&etask, &event);
+ }
+}
+
+static void
+mgr_destroy(dns_requestmgr_t *requestmgr) {
+ int i;
+ isc_mem_t *mctx;
+
+ req_log(ISC_LOG_DEBUG(3), "mgr_destroy");
+
+ REQUIRE(requestmgr->eref == 0);
+ REQUIRE(requestmgr->iref == 0);
+
+ DESTROYLOCK(&requestmgr->lock);
+ for (i = 0; i < DNS_REQUEST_NLOCKS; i++)
+ DESTROYLOCK(&requestmgr->locks[i]);
+ if (requestmgr->dispatchv4 != NULL)
+ dns_dispatch_detach(&requestmgr->dispatchv4);
+ if (requestmgr->dispatchv6 != NULL)
+ dns_dispatch_detach(&requestmgr->dispatchv6);
+ requestmgr->magic = 0;
+ mctx = requestmgr->mctx;
+ isc_mem_put(mctx, requestmgr, sizeof(*requestmgr));
+ isc_mem_detach(&mctx);
+}
+
+static unsigned int
+mgr_gethash(dns_requestmgr_t *requestmgr) {
+ req_log(ISC_LOG_DEBUG(3), "mgr_gethash");
+ /*
+ * Locked by caller.
+ */
+ requestmgr->hash++;
+ return (requestmgr->hash % DNS_REQUEST_NLOCKS);
+}
+
+static inline isc_result_t
+req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
+ isc_region_t r;
+ isc_socket_t *socket;
+ isc_result_t result;
+ unsigned int dispattr;
+
+ req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request);
+
+ REQUIRE(VALID_REQUEST(request));
+ dispattr = dns_dispatch_getattributes(request->dispatch);
+ socket = req_getsocket(request);
+ isc_buffer_usedregion(request->query, &r);
+ /*
+ * We could connect the socket when we are using an exclusive dispatch
+ * as we do in resolver.c, but we prefer implementation simplicity
+ * at this moment.
+ */
+ result = isc_socket_sendto(socket, &r, task, req_senddone,
+ request, address, NULL);
+ if (result == ISC_R_SUCCESS)
+ request->flags |= DNS_REQUEST_F_SENDING;
+ return (result);
+}
+
+static isc_result_t
+new_request(isc_mem_t *mctx, dns_request_t **requestp) {
+ dns_request_t *request;
+
+ request = isc_mem_get(mctx, sizeof(*request));
+ if (request == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /*
+ * Zero structure.
+ */
+ request->magic = 0;
+ request->mctx = NULL;
+ request->flags = 0;
+ ISC_LINK_INIT(request, link);
+ request->query = NULL;
+ request->answer = NULL;
+ request->event = NULL;
+ request->dispatch = NULL;
+ request->dispentry = NULL;
+ request->timer = NULL;
+ request->requestmgr = NULL;
+ request->tsig = NULL;
+ request->tsigkey = NULL;
+ ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL,
+ DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL,
+ NULL, NULL);
+ request->canceling = ISC_FALSE;
+ request->udpcount = 0;
+
+ isc_mem_attach(mctx, &request->mctx);
+
+ request->magic = REQUEST_MAGIC;
+ *requestp = request;
+ return (ISC_R_SUCCESS);
+}
+
+
+static isc_boolean_t
+isblackholed(dns_dispatchmgr_t *dispatchmgr, isc_sockaddr_t *destaddr) {
+ dns_acl_t *blackhole;
+ isc_netaddr_t netaddr;
+ int match;
+ isc_boolean_t drop = ISC_FALSE;
+ char netaddrstr[ISC_NETADDR_FORMATSIZE];
+
+ blackhole = dns_dispatchmgr_getblackhole(dispatchmgr);
+ if (blackhole != NULL) {
+ isc_netaddr_fromsockaddr(&netaddr, destaddr);
+ if (dns_acl_match(&netaddr, NULL, blackhole,
+ NULL, &match, NULL) == ISC_R_SUCCESS &&
+ match > 0)
+ drop = ISC_TRUE;
+ }
+ if (drop) {
+ isc_netaddr_format(&netaddr, netaddrstr, sizeof(netaddrstr));
+ req_log(ISC_LOG_DEBUG(10), "blackholed address %s", netaddrstr);
+ }
+ return (drop);
+}
+
+static isc_result_t
+create_tcp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
+ isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
+{
+ isc_result_t result;
+ isc_socket_t *socket = NULL;
+ isc_sockaddr_t src;
+ unsigned int attrs;
+ isc_sockaddr_t bind_any;
+
+ result = isc_socket_create(requestmgr->socketmgr,
+ isc_sockaddr_pf(destaddr),
+ isc_sockettype_tcp, &socket);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
+ if (srcaddr == NULL) {
+ isc_sockaddr_anyofpf(&bind_any,
+ isc_sockaddr_pf(destaddr));
+ result = isc_socket_bind(socket, &bind_any, 0);
+ } else {
+ src = *srcaddr;
+ isc_sockaddr_setport(&src, 0);
+ result = isc_socket_bind(socket, &src, 0);
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+#endif
+ attrs = 0;
+ attrs |= DNS_DISPATCHATTR_TCP;
+ attrs |= DNS_DISPATCHATTR_PRIVATE;
+ if (isc_sockaddr_pf(destaddr) == AF_INET)
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ else
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ attrs |= DNS_DISPATCHATTR_MAKEQUERY;
+ result = dns_dispatch_createtcp(requestmgr->dispatchmgr,
+ socket, requestmgr->taskmgr,
+ 4096, 2, 1, 1, 3, attrs,
+ dispatchp);
+cleanup:
+ isc_socket_detach(&socket);
+ return (result);
+}
+
+static isc_result_t
+find_udp_dispatch(dns_requestmgr_t *requestmgr, isc_sockaddr_t *srcaddr,
+ isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp)
+{
+ dns_dispatch_t *disp = NULL;
+ unsigned int attrs, attrmask;
+
+ if (srcaddr == NULL) {
+ switch (isc_sockaddr_pf(destaddr)) {
+ case PF_INET:
+ disp = requestmgr->dispatchv4;
+ break;
+
+ case PF_INET6:
+ disp = requestmgr->dispatchv6;
+ break;
+
+ default:
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+ if (disp == NULL)
+ return (ISC_R_FAMILYNOSUPPORT);
+ dns_dispatch_attach(disp, dispatchp);
+ return (ISC_R_SUCCESS);
+ }
+ attrs = 0;
+ attrs |= DNS_DISPATCHATTR_UDP;
+ switch (isc_sockaddr_pf(srcaddr)) {
+ case PF_INET:
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ break;
+
+ case PF_INET6:
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ break;
+
+ default:
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+ attrmask = 0;
+ attrmask |= DNS_DISPATCHATTR_UDP;
+ attrmask |= DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4;
+ attrmask |= DNS_DISPATCHATTR_IPV6;
+ return (dns_dispatch_getudp(requestmgr->dispatchmgr,
+ requestmgr->socketmgr,
+ requestmgr->taskmgr,
+ srcaddr, 4096,
+ 1000, 32768, 16411, 16433,
+ attrs, attrmask,
+ dispatchp));
+}
+
+static isc_result_t
+get_dispatch(isc_boolean_t tcp, dns_requestmgr_t *requestmgr,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ dns_dispatch_t **dispatchp)
+{
+ isc_result_t result;
+ if (tcp)
+ result = create_tcp_dispatch(requestmgr, srcaddr,
+ destaddr, dispatchp);
+ else
+ result = find_udp_dispatch(requestmgr, srcaddr,
+ destaddr, dispatchp);
+ return (result);
+}
+
+static isc_result_t
+set_timer(isc_timer_t *timer, unsigned int timeout, unsigned int udpresend) {
+ isc_time_t expires;
+ isc_interval_t interval;
+ isc_result_t result;
+ isc_timertype_t timertype;
+
+ isc_interval_set(&interval, timeout, 0);
+ result = isc_time_nowplusinterval(&expires, &interval);
+ isc_interval_set(&interval, udpresend, 0);
+
+ timertype = udpresend != 0 ? isc_timertype_limited : isc_timertype_once;
+ if (result == ISC_R_SUCCESS)
+ result = isc_timer_reset(timer, timertype, &expires,
+ &interval, ISC_FALSE);
+ return (result);
+}
+
+isc_result_t
+dns_request_createraw(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, unsigned int timeout,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_request_t **requestp)
+{
+ return(dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr,
+ options, timeout, 0, 0, task, action,
+ arg, requestp));
+}
+
+isc_result_t
+dns_request_createraw2(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, unsigned int timeout,
+ unsigned int udptimeout, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_request_t **requestp)
+{
+ unsigned int udpretries = 0;
+
+ if (udptimeout != 0)
+ udpretries = timeout / udptimeout;
+
+ return (dns_request_createraw3(requestmgr, msgbuf, srcaddr, destaddr,
+ options, timeout, udptimeout,
+ udpretries, task, action, arg,
+ requestp));
+}
+
+isc_result_t
+dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, unsigned int timeout,
+ unsigned int udptimeout, unsigned int udpretries,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_request_t **requestp)
+{
+ dns_request_t *request = NULL;
+ isc_task_t *tclone = NULL;
+ isc_socket_t *socket = NULL;
+ isc_result_t result;
+ isc_mem_t *mctx;
+ dns_messageid_t id;
+ isc_boolean_t tcp = ISC_FALSE;
+ isc_region_t r;
+
+ REQUIRE(VALID_REQUESTMGR(requestmgr));
+ REQUIRE(msgbuf != NULL);
+ REQUIRE(destaddr != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+ REQUIRE(requestp != NULL && *requestp == NULL);
+ REQUIRE(timeout > 0);
+ if (srcaddr != NULL)
+ REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
+
+ mctx = requestmgr->mctx;
+
+ req_log(ISC_LOG_DEBUG(3), "dns_request_createraw");
+
+ if (isblackholed(requestmgr->dispatchmgr, destaddr))
+ return (DNS_R_BLACKHOLED);
+
+ request = NULL;
+ result = new_request(mctx, &request);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (udptimeout == 0 && udpretries != 0) {
+ udptimeout = timeout / (udpretries + 1);
+ if (udptimeout == 0)
+ udptimeout = 1;
+ }
+ request->udpcount = udpretries;
+
+ /*
+ * Create timer now. We will set it below once.
+ */
+ result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
+ NULL, NULL, task, req_timeout, request,
+ &request->timer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ request->event = (dns_requestevent_t *)
+ isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
+ action, arg, sizeof(dns_requestevent_t));
+ if (request->event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ isc_task_attach(task, &tclone);
+ request->event->ev_sender = task;
+ request->event->request = request;
+ request->event->result = ISC_R_FAILURE;
+
+ isc_buffer_usedregion(msgbuf, &r);
+ if (r.length < DNS_MESSAGE_HEADERLEN || r.length > 65535) {
+ result = DNS_R_FORMERR;
+ goto cleanup;
+ }
+
+ if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
+ tcp = ISC_TRUE;
+
+ result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
+ &request->dispatch);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_dispatch_addresponse2(request->dispatch, destaddr, task,
+ req_response, request, &id,
+ &request->dispentry,
+ requestmgr->socketmgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ socket = req_getsocket(request);
+ INSIST(socket != NULL);
+
+ result = isc_buffer_allocate(mctx, &request->query,
+ r.length + (tcp ? 2 : 0));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ if (tcp)
+ isc_buffer_putuint16(request->query, (isc_uint16_t)r.length);
+ result = isc_buffer_copyregion(request->query, &r);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Add message ID. */
+ isc_buffer_usedregion(request->query, &r);
+ if (tcp)
+ isc_region_consume(&r, 2);
+ r.base[0] = (id>>8) & 0xff;
+ r.base[1] = id & 0xff;
+
+ LOCK(&requestmgr->lock);
+ if (requestmgr->exiting) {
+ UNLOCK(&requestmgr->lock);
+ result = ISC_R_SHUTTINGDOWN;
+ goto cleanup;
+ }
+ requestmgr_attach(requestmgr, &request->requestmgr);
+ request->hash = mgr_gethash(requestmgr);
+ ISC_LIST_APPEND(requestmgr->requests, request, link);
+ UNLOCK(&requestmgr->lock);
+
+ result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
+ if (result != ISC_R_SUCCESS)
+ goto unlink;
+
+ request->destaddr = *destaddr;
+ if (tcp) {
+ result = isc_socket_connect(socket, destaddr, task,
+ req_connected, request);
+ if (result != ISC_R_SUCCESS)
+ goto unlink;
+ request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
+ } else {
+ result = req_send(request, task, destaddr);
+ if (result != ISC_R_SUCCESS)
+ goto unlink;
+ }
+
+ req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p",
+ request);
+ *requestp = request;
+ return (ISC_R_SUCCESS);
+
+ unlink:
+ LOCK(&requestmgr->lock);
+ ISC_LIST_UNLINK(requestmgr->requests, request, link);
+ UNLOCK(&requestmgr->lock);
+
+ cleanup:
+ if (tclone != NULL)
+ isc_task_detach(&tclone);
+ req_destroy(request);
+ req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: failed %s",
+ dns_result_totext(result));
+ return (result);
+}
+
+isc_result_t
+dns_request_create(dns_requestmgr_t *requestmgr, dns_message_t *message,
+ isc_sockaddr_t *address, unsigned int options,
+ dns_tsigkey_t *key,
+ unsigned int timeout, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_request_t **requestp)
+{
+ return (dns_request_createvia3(requestmgr, message, NULL, address,
+ options, key, timeout, 0, 0, task,
+ action, arg, requestp));
+}
+
+isc_result_t
+dns_request_createvia(dns_requestmgr_t *requestmgr, dns_message_t *message,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, dns_tsigkey_t *key,
+ unsigned int timeout, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_request_t **requestp)
+{
+ return(dns_request_createvia3(requestmgr, message, srcaddr, destaddr,
+ options, key, timeout, 0, 0, task,
+ action, arg, requestp));
+}
+
+isc_result_t
+dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, dns_tsigkey_t *key,
+ unsigned int timeout, unsigned int udptimeout,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_request_t **requestp)
+{
+ unsigned int udpretries = 0;
+
+ if (udptimeout != 0)
+ udpretries = timeout / udptimeout;
+ return (dns_request_createvia3(requestmgr, message, srcaddr, destaddr,
+ options, key, timeout, udptimeout,
+ udpretries, task, action, arg,
+ requestp));
+}
+
+isc_result_t
+dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
+ isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
+ unsigned int options, dns_tsigkey_t *key,
+ unsigned int timeout, unsigned int udptimeout,
+ unsigned int udpretries, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_request_t **requestp)
+{
+ dns_request_t *request = NULL;
+ isc_task_t *tclone = NULL;
+ isc_socket_t *socket = NULL;
+ isc_result_t result;
+ isc_mem_t *mctx;
+ dns_messageid_t id;
+ isc_boolean_t tcp;
+ isc_boolean_t setkey = ISC_TRUE;
+
+ REQUIRE(VALID_REQUESTMGR(requestmgr));
+ REQUIRE(message != NULL);
+ REQUIRE(destaddr != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+ REQUIRE(requestp != NULL && *requestp == NULL);
+ REQUIRE(timeout > 0);
+ if (srcaddr != NULL)
+ REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
+
+ mctx = requestmgr->mctx;
+
+ req_log(ISC_LOG_DEBUG(3), "dns_request_createvia");
+
+ if (isblackholed(requestmgr->dispatchmgr, destaddr))
+ return (DNS_R_BLACKHOLED);
+
+ request = NULL;
+ result = new_request(mctx, &request);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (udptimeout == 0 && udpretries != 0) {
+ udptimeout = timeout / (udpretries + 1);
+ if (udptimeout == 0)
+ udptimeout = 1;
+ }
+ request->udpcount = udpretries;
+
+ /*
+ * Create timer now. We will set it below once.
+ */
+ result = isc_timer_create(requestmgr->timermgr, isc_timertype_inactive,
+ NULL, NULL, task, req_timeout, request,
+ &request->timer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ request->event = (dns_requestevent_t *)
+ isc_event_allocate(mctx, task, DNS_EVENT_REQUESTDONE,
+ action, arg, sizeof(dns_requestevent_t));
+ if (request->event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ isc_task_attach(task, &tclone);
+ request->event->ev_sender = task;
+ request->event->request = request;
+ request->event->result = ISC_R_FAILURE;
+ if (key != NULL)
+ dns_tsigkey_attach(key, &request->tsigkey);
+
+ use_tcp:
+ tcp = ISC_TF((options & DNS_REQUESTOPT_TCP) != 0);
+ result = get_dispatch(tcp, requestmgr, srcaddr, destaddr,
+ &request->dispatch);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_dispatch_addresponse2(request->dispatch, destaddr, task,
+ req_response, request, &id,
+ &request->dispentry,
+ requestmgr->socketmgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ socket = req_getsocket(request);
+ INSIST(socket != NULL);
+
+ message->id = id;
+ if (setkey) {
+ result = dns_message_settsigkey(message, request->tsigkey);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ result = req_render(message, &request->query, options, mctx);
+ if (result == DNS_R_USETCP &&
+ (options & DNS_REQUESTOPT_TCP) == 0) {
+ /*
+ * Try again using TCP.
+ */
+ dns_message_renderreset(message);
+ dns_dispatch_removeresponse(&request->dispentry, NULL);
+ dns_dispatch_detach(&request->dispatch);
+ socket = NULL;
+ options |= DNS_REQUESTOPT_TCP;
+ setkey = ISC_FALSE;
+ goto use_tcp;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_message_getquerytsig(message, mctx, &request->tsig);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ LOCK(&requestmgr->lock);
+ if (requestmgr->exiting) {
+ UNLOCK(&requestmgr->lock);
+ result = ISC_R_SHUTTINGDOWN;
+ goto cleanup;
+ }
+ requestmgr_attach(requestmgr, &request->requestmgr);
+ request->hash = mgr_gethash(requestmgr);
+ ISC_LIST_APPEND(requestmgr->requests, request, link);
+ UNLOCK(&requestmgr->lock);
+
+ result = set_timer(request->timer, timeout, tcp ? 0 : udptimeout);
+ if (result != ISC_R_SUCCESS)
+ goto unlink;
+
+ request->destaddr = *destaddr;
+ if (tcp) {
+ result = isc_socket_connect(socket, destaddr, task,
+ req_connected, request);
+ if (result != ISC_R_SUCCESS)
+ goto unlink;
+ request->flags |= DNS_REQUEST_F_CONNECTING|DNS_REQUEST_F_TCP;
+ } else {
+ result = req_send(request, task, destaddr);
+ if (result != ISC_R_SUCCESS)
+ goto unlink;
+ }
+
+ req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p",
+ request);
+ *requestp = request;
+ return (ISC_R_SUCCESS);
+
+ unlink:
+ LOCK(&requestmgr->lock);
+ ISC_LIST_UNLINK(requestmgr->requests, request, link);
+ UNLOCK(&requestmgr->lock);
+
+ cleanup:
+ if (tclone != NULL)
+ isc_task_detach(&tclone);
+ req_destroy(request);
+ req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s",
+ dns_result_totext(result));
+ return (result);
+}
+
+static isc_result_t
+req_render(dns_message_t *message, isc_buffer_t **bufferp,
+ unsigned int options, isc_mem_t *mctx)
+{
+ isc_buffer_t *buf1 = NULL;
+ isc_buffer_t *buf2 = NULL;
+ isc_result_t result;
+ isc_region_t r;
+ isc_boolean_t tcp = ISC_FALSE;
+ dns_compress_t cctx;
+ isc_boolean_t cleanup_cctx = ISC_FALSE;
+
+ REQUIRE(bufferp != NULL && *bufferp == NULL);
+
+ req_log(ISC_LOG_DEBUG(3), "request_render");
+
+ /*
+ * Create buffer able to hold largest possible message.
+ */
+ result = isc_buffer_allocate(mctx, &buf1, 65535);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_compress_init(&cctx, -1, mctx);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ cleanup_cctx = ISC_TRUE;
+
+ /*
+ * Render message.
+ */
+ result = dns_message_renderbegin(message, &cctx, buf1);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_message_renderend(message);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_compress_invalidate(&cctx);
+ cleanup_cctx = ISC_FALSE;
+
+ /*
+ * Copy rendered message to exact sized buffer.
+ */
+ isc_buffer_usedregion(buf1, &r);
+ if ((options & DNS_REQUESTOPT_TCP) != 0) {
+ tcp = ISC_TRUE;
+ } else if (r.length > 512) {
+ result = DNS_R_USETCP;
+ goto cleanup;
+ }
+ result = isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ if (tcp)
+ isc_buffer_putuint16(buf2, (isc_uint16_t)r.length);
+ result = isc_buffer_copyregion(buf2, &r);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * Cleanup and return.
+ */
+ isc_buffer_free(&buf1);
+ *bufferp = buf2;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ dns_message_renderreset(message);
+ if (buf1 != NULL)
+ isc_buffer_free(&buf1);
+ if (buf2 != NULL)
+ isc_buffer_free(&buf2);
+ if (cleanup_cctx)
+ dns_compress_invalidate(&cctx);
+ return (result);
+}
+
+
+/*
+ * If this request is no longer waiting for events,
+ * send the completion event. This will ultimately
+ * cause the request to be destroyed.
+ *
+ * Requires:
+ * 'request' is locked by the caller.
+ */
+static void
+send_if_done(dns_request_t *request, isc_result_t result) {
+ if (!DNS_REQUEST_CONNECTING(request) &&
+ !DNS_REQUEST_SENDING(request) &&
+ !request->canceling)
+ req_sendevent(request, result);
+}
+
+/*
+ * Handle the control event.
+ */
+static void
+do_cancel(isc_task_t *task, isc_event_t *event) {
+ dns_request_t *request = event->ev_arg;
+ UNUSED(task);
+ INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL);
+ LOCK(&request->requestmgr->locks[request->hash]);
+ request->canceling = ISC_FALSE;
+ if (!DNS_REQUEST_CANCELED(request))
+ req_cancel(request);
+ send_if_done(request, ISC_R_CANCELED);
+ UNLOCK(&request->requestmgr->locks[request->hash]);
+}
+
+void
+dns_request_cancel(dns_request_t *request) {
+ REQUIRE(VALID_REQUEST(request));
+
+ req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request);
+
+ REQUIRE(VALID_REQUEST(request));
+
+ LOCK(&request->requestmgr->locks[request->hash]);
+ if (!request->canceling && !DNS_REQUEST_CANCELED(request)) {
+ isc_event_t *ev = &request->ctlevent;
+ isc_task_send(request->event->ev_sender, &ev);
+ request->canceling = ISC_TRUE;
+ }
+ UNLOCK(&request->requestmgr->locks[request->hash]);
+}
+
+isc_result_t
+dns_request_getresponse(dns_request_t *request, dns_message_t *message,
+ unsigned int options)
+{
+ isc_result_t result;
+
+ REQUIRE(VALID_REQUEST(request));
+ REQUIRE(request->answer != NULL);
+
+ req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p",
+ request);
+
+ result = dns_message_setquerytsig(message, request->tsig);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_message_settsigkey(message, request->tsigkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_message_parse(message, request->answer, options);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (request->tsigkey != NULL)
+ result = dns_tsig_verify(request->answer, message, NULL, NULL);
+ return (result);
+}
+
+isc_boolean_t
+dns_request_usedtcp(dns_request_t *request) {
+ REQUIRE(VALID_REQUEST(request));
+
+ return (ISC_TF((request->flags & DNS_REQUEST_F_TCP) != 0));
+}
+
+void
+dns_request_destroy(dns_request_t **requestp) {
+ dns_request_t *request;
+
+ REQUIRE(requestp != NULL && VALID_REQUEST(*requestp));
+
+ request = *requestp;
+
+ req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request);
+
+ LOCK(&request->requestmgr->lock);
+ LOCK(&request->requestmgr->locks[request->hash]);
+ ISC_LIST_UNLINK(request->requestmgr->requests, request, link);
+ INSIST(!DNS_REQUEST_CONNECTING(request));
+ INSIST(!DNS_REQUEST_SENDING(request));
+ UNLOCK(&request->requestmgr->locks[request->hash]);
+ UNLOCK(&request->requestmgr->lock);
+
+ /*
+ * These should have been cleaned up by req_cancel() before
+ * the completion event was sent.
+ */
+ INSIST(!ISC_LINK_LINKED(request, link));
+ INSIST(request->dispentry == NULL);
+ INSIST(request->dispatch == NULL);
+ INSIST(request->timer == NULL);
+
+ req_destroy(request);
+
+ *requestp = NULL;
+}
+
+/***
+ *** Private: request.
+ ***/
+
+static isc_socket_t *
+req_getsocket(dns_request_t *request) {
+ unsigned int dispattr;
+ isc_socket_t *socket;
+
+ dispattr = dns_dispatch_getattributes(request->dispatch);
+ if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
+ INSIST(request->dispentry != NULL);
+ socket = dns_dispatch_getentrysocket(request->dispentry);
+ } else
+ socket = dns_dispatch_getsocket(request->dispatch);
+
+ return (socket);
+}
+
+static void
+req_connected(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ isc_result_t result;
+ dns_request_t *request = event->ev_arg;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
+ REQUIRE(VALID_REQUEST(request));
+ REQUIRE(DNS_REQUEST_CONNECTING(request));
+
+ req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request);
+
+ LOCK(&request->requestmgr->locks[request->hash]);
+ request->flags &= ~DNS_REQUEST_F_CONNECTING;
+
+ if (DNS_REQUEST_CANCELED(request)) {
+ /*
+ * Send delayed event.
+ */
+ if (DNS_REQUEST_TIMEDOUT(request))
+ send_if_done(request, ISC_R_TIMEDOUT);
+ else
+ send_if_done(request, ISC_R_CANCELED);
+ } else {
+ dns_dispatch_starttcp(request->dispatch);
+ result = sevent->result;
+ if (result == ISC_R_SUCCESS)
+ result = req_send(request, task, NULL);
+
+ if (result != ISC_R_SUCCESS) {
+ req_cancel(request);
+ send_if_done(request, ISC_R_CANCELED);
+ }
+ }
+ UNLOCK(&request->requestmgr->locks[request->hash]);
+ isc_event_free(&event);
+}
+
+static void
+req_senddone(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ dns_request_t *request = event->ev_arg;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+ REQUIRE(VALID_REQUEST(request));
+ REQUIRE(DNS_REQUEST_SENDING(request));
+
+ req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request);
+
+ UNUSED(task);
+
+ LOCK(&request->requestmgr->locks[request->hash]);
+ request->flags &= ~DNS_REQUEST_F_SENDING;
+
+ if (DNS_REQUEST_CANCELED(request)) {
+ /*
+ * Send delayed event.
+ */
+ if (DNS_REQUEST_TIMEDOUT(request))
+ send_if_done(request, ISC_R_TIMEDOUT);
+ else
+ send_if_done(request, ISC_R_CANCELED);
+ } else if (sevent->result != ISC_R_SUCCESS) {
+ req_cancel(request);
+ send_if_done(request, ISC_R_CANCELED);
+ }
+ UNLOCK(&request->requestmgr->locks[request->hash]);
+
+ isc_event_free(&event);
+}
+
+static void
+req_response(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result;
+ dns_request_t *request = event->ev_arg;
+ dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
+ isc_region_t r;
+
+ REQUIRE(VALID_REQUEST(request));
+ REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
+
+ UNUSED(task);
+
+ req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request,
+ dns_result_totext(devent->result));
+
+ LOCK(&request->requestmgr->locks[request->hash]);
+ result = devent->result;
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+ /*
+ * Copy buffer to request.
+ */
+ isc_buffer_usedregion(&devent->buffer, &r);
+ result = isc_buffer_allocate(request->mctx, &request->answer,
+ r.length);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ result = isc_buffer_copyregion(request->answer, &r);
+ if (result != ISC_R_SUCCESS)
+ isc_buffer_free(&request->answer);
+ done:
+ /*
+ * Cleanup.
+ */
+ dns_dispatch_removeresponse(&request->dispentry, &devent);
+ req_cancel(request);
+ /*
+ * Send completion event.
+ */
+ send_if_done(request, result);
+ UNLOCK(&request->requestmgr->locks[request->hash]);
+}
+
+static void
+req_timeout(isc_task_t *task, isc_event_t *event) {
+ dns_request_t *request = event->ev_arg;
+ isc_result_t result;
+
+ REQUIRE(VALID_REQUEST(request));
+
+ req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
+
+ UNUSED(task);
+ LOCK(&request->requestmgr->locks[request->hash]);
+ if (event->ev_type == ISC_TIMEREVENT_TICK &&
+ request->udpcount-- != 0) {
+ if (! DNS_REQUEST_SENDING(request)) {
+ result = req_send(request, task, &request->destaddr);
+ if (result != ISC_R_SUCCESS) {
+ req_cancel(request);
+ send_if_done(request, result);
+ }
+ }
+ } else {
+ request->flags |= DNS_REQUEST_F_TIMEDOUT;
+ req_cancel(request);
+ send_if_done(request, ISC_R_TIMEDOUT);
+ }
+ UNLOCK(&request->requestmgr->locks[request->hash]);
+ isc_event_free(&event);
+}
+
+static void
+req_sendevent(dns_request_t *request, isc_result_t result) {
+ isc_task_t *task;
+
+ REQUIRE(VALID_REQUEST(request));
+
+ req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request);
+
+ /*
+ * Lock held by caller.
+ */
+ task = request->event->ev_sender;
+ request->event->ev_sender = request;
+ request->event->result = result;
+ isc_task_sendanddetach(&task, (isc_event_t **)&request->event);
+}
+
+static void
+req_destroy(dns_request_t *request) {
+ isc_mem_t *mctx;
+
+ REQUIRE(VALID_REQUEST(request));
+
+ req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request);
+
+ request->magic = 0;
+ if (request->query != NULL)
+ isc_buffer_free(&request->query);
+ if (request->answer != NULL)
+ isc_buffer_free(&request->answer);
+ if (request->event != NULL)
+ isc_event_free((isc_event_t **)&request->event);
+ if (request->dispentry != NULL)
+ dns_dispatch_removeresponse(&request->dispentry, NULL);
+ if (request->dispatch != NULL)
+ dns_dispatch_detach(&request->dispatch);
+ if (request->timer != NULL)
+ isc_timer_detach(&request->timer);
+ if (request->tsig != NULL)
+ isc_buffer_free(&request->tsig);
+ if (request->tsigkey != NULL)
+ dns_tsigkey_detach(&request->tsigkey);
+ if (request->requestmgr != NULL)
+ requestmgr_detach(&request->requestmgr);
+ mctx = request->mctx;
+ isc_mem_put(mctx, request, sizeof(*request));
+ isc_mem_detach(&mctx);
+}
+
+/*
+ * Stop the current request. Must be called from the request's task.
+ */
+static void
+req_cancel(dns_request_t *request) {
+ isc_socket_t *socket;
+ unsigned int dispattr;
+
+ REQUIRE(VALID_REQUEST(request));
+
+ req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request);
+
+ /*
+ * Lock held by caller.
+ */
+ request->flags |= DNS_REQUEST_F_CANCELED;
+
+ if (request->timer != NULL)
+ isc_timer_detach(&request->timer);
+ dispattr = dns_dispatch_getattributes(request->dispatch);
+ socket = NULL;
+ if (DNS_REQUEST_CONNECTING(request) || DNS_REQUEST_SENDING(request)) {
+ if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
+ if (request->dispentry != NULL) {
+ socket = dns_dispatch_getentrysocket(
+ request->dispentry);
+ }
+ } else
+ socket = dns_dispatch_getsocket(request->dispatch);
+ if (DNS_REQUEST_CONNECTING(request) && socket != NULL)
+ isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT);
+ if (DNS_REQUEST_SENDING(request) && socket != NULL)
+ isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
+ }
+ if (request->dispentry != NULL)
+ dns_dispatch_removeresponse(&request->dispentry, NULL);
+ dns_dispatch_detach(&request->dispatch);
+}
+
+static void
+req_log(int level, const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_REQUEST, level, fmt, ap);
+ va_end(ap);
+}
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
new file mode 100644
index 0000000..9d1c2fe
--- /dev/null
+++ b/lib/dns/resolver.c
@@ -0,0 +1,7602 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: resolver.c,v 1.384 2008/11/07 00:52:34 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/random.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/acl.h>
+#include <dns/adb.h>
+#include <dns/cache.h>
+#include <dns/db.h>
+#include <dns/dispatch.h>
+#include <dns/ds.h>
+#include <dns/events.h>
+#include <dns/forward.h>
+#include <dns/keytable.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/ncache.h>
+#include <dns/opcode.h>
+#include <dns/peer.h>
+#include <dns/rbt.h>
+#include <dns/rcode.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/rootns.h>
+#include <dns/stats.h>
+#include <dns/tsig.h>
+#include <dns/validator.h>
+
+#define DNS_RESOLVER_TRACE
+#ifdef DNS_RESOLVER_TRACE
+#define RTRACE(m) isc_log_write(dns_lctx, \
+ DNS_LOGCATEGORY_RESOLVER, \
+ DNS_LOGMODULE_RESOLVER, \
+ ISC_LOG_DEBUG(3), \
+ "res %p: %s", res, (m))
+#define RRTRACE(r, m) isc_log_write(dns_lctx, \
+ DNS_LOGCATEGORY_RESOLVER, \
+ DNS_LOGMODULE_RESOLVER, \
+ ISC_LOG_DEBUG(3), \
+ "res %p: %s", (r), (m))
+#define FCTXTRACE(m) isc_log_write(dns_lctx, \
+ DNS_LOGCATEGORY_RESOLVER, \
+ DNS_LOGMODULE_RESOLVER, \
+ ISC_LOG_DEBUG(3), \
+ "fctx %p(%s'): %s", fctx, fctx->info, (m))
+#define FCTXTRACE2(m1, m2) \
+ isc_log_write(dns_lctx, \
+ DNS_LOGCATEGORY_RESOLVER, \
+ DNS_LOGMODULE_RESOLVER, \
+ ISC_LOG_DEBUG(3), \
+ "fctx %p(%s): %s %s", \
+ fctx, fctx->info, (m1), (m2))
+#define FTRACE(m) isc_log_write(dns_lctx, \
+ DNS_LOGCATEGORY_RESOLVER, \
+ DNS_LOGMODULE_RESOLVER, \
+ ISC_LOG_DEBUG(3), \
+ "fetch %p (fctx %p(%s)): %s", \
+ fetch, fetch->private, \
+ fetch->private->info, (m))
+#define QTRACE(m) isc_log_write(dns_lctx, \
+ DNS_LOGCATEGORY_RESOLVER, \
+ DNS_LOGMODULE_RESOLVER, \
+ ISC_LOG_DEBUG(3), \
+ "resquery %p (fctx %p(%s)): %s", \
+ query, query->fctx, \
+ query->fctx->info, (m))
+#else
+#define RTRACE(m)
+#define RRTRACE(r, m)
+#define FCTXTRACE(m)
+#define FTRACE(m)
+#define QTRACE(m)
+#endif
+
+/*%
+ * Maximum EDNS0 input packet size.
+ */
+#define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
+
+/*%
+ * This defines the maximum number of timeouts we will permit before we
+ * disable EDNS0 on the query.
+ */
+#define MAX_EDNS0_TIMEOUTS 3
+
+typedef struct fetchctx fetchctx_t;
+
+typedef struct query {
+ /* Locked by task event serialization. */
+ unsigned int magic;
+ fetchctx_t * fctx;
+ isc_mem_t * mctx;
+ dns_dispatchmgr_t * dispatchmgr;
+ dns_dispatch_t * dispatch;
+ isc_boolean_t exclusivesocket;
+ dns_adbaddrinfo_t * addrinfo;
+ isc_socket_t * tcpsocket;
+ isc_time_t start;
+ dns_messageid_t id;
+ dns_dispentry_t * dispentry;
+ ISC_LINK(struct query) link;
+ isc_buffer_t buffer;
+ isc_buffer_t *tsig;
+ dns_tsigkey_t *tsigkey;
+ unsigned int options;
+ unsigned int attributes;
+ unsigned int sends;
+ unsigned int connects;
+ unsigned char data[512];
+} resquery_t;
+
+#define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
+#define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
+
+#define RESQUERY_ATTR_CANCELED 0x02
+
+#define RESQUERY_CONNECTING(q) ((q)->connects > 0)
+#define RESQUERY_CANCELED(q) (((q)->attributes & \
+ RESQUERY_ATTR_CANCELED) != 0)
+#define RESQUERY_SENDING(q) ((q)->sends > 0)
+
+typedef enum {
+ fetchstate_init = 0, /*%< Start event has not run yet. */
+ fetchstate_active,
+ fetchstate_done /*%< FETCHDONE events posted. */
+} fetchstate;
+
+struct fetchctx {
+ /*% Not locked. */
+ unsigned int magic;
+ dns_resolver_t * res;
+ dns_name_t name;
+ dns_rdatatype_t type;
+ unsigned int options;
+ unsigned int bucketnum;
+ char * info;
+ /*% Locked by appropriate bucket lock. */
+ fetchstate state;
+ isc_boolean_t want_shutdown;
+ isc_boolean_t cloned;
+ isc_boolean_t spilled;
+ unsigned int references;
+ isc_event_t control_event;
+ ISC_LINK(struct fetchctx) link;
+ ISC_LIST(dns_fetchevent_t) events;
+ /*% Locked by task event serialization. */
+ dns_name_t domain;
+ dns_rdataset_t nameservers;
+ unsigned int attributes;
+ isc_timer_t * timer;
+ isc_time_t expires;
+ isc_interval_t interval;
+ dns_message_t * qmessage;
+ dns_message_t * rmessage;
+ ISC_LIST(resquery_t) queries;
+ dns_adbfindlist_t finds;
+ dns_adbfind_t * find;
+ dns_adbfindlist_t altfinds;
+ dns_adbfind_t * altfind;
+ dns_adbaddrinfolist_t forwaddrs;
+ dns_adbaddrinfolist_t altaddrs;
+ isc_sockaddrlist_t forwarders;
+ dns_fwdpolicy_t fwdpolicy;
+ isc_sockaddrlist_t bad;
+ isc_sockaddrlist_t edns;
+ isc_sockaddrlist_t edns512;
+ dns_validator_t *validator;
+ ISC_LIST(dns_validator_t) validators;
+ dns_db_t * cache;
+ dns_adb_t * adb;
+
+ /*%
+ * The number of events we're waiting for.
+ */
+ unsigned int pending;
+
+ /*%
+ * The number of times we've "restarted" the current
+ * nameserver set. This acts as a failsafe to prevent
+ * us from pounding constantly on a particular set of
+ * servers that, for whatever reason, are not giving
+ * us useful responses, but are responding in such a
+ * way that they are not marked "bad".
+ */
+ unsigned int restarts;
+
+ /*%
+ * The number of timeouts that have occurred since we
+ * last successfully received a response packet. This
+ * is used for EDNS0 black hole detection.
+ */
+ unsigned int timeouts;
+ /*%
+ * Look aside state for DS lookups.
+ */
+ dns_name_t nsname;
+ dns_fetch_t * nsfetch;
+ dns_rdataset_t nsrrset;
+
+ /*%
+ * Number of queries that reference this context.
+ */
+ unsigned int nqueries;
+
+ /*%
+ * The reason to print when logging a successful
+ * response to a query.
+ */
+ const char * reason;
+
+ /*%
+ * Random numbers to use for mixing up server addresses.
+ */
+ isc_uint32_t rand_buf;
+ isc_uint32_t rand_bits;
+};
+
+#define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!')
+#define VALID_FCTX(fctx) ISC_MAGIC_VALID(fctx, FCTX_MAGIC)
+
+#define FCTX_ATTR_HAVEANSWER 0x0001
+#define FCTX_ATTR_GLUING 0x0002
+#define FCTX_ATTR_ADDRWAIT 0x0004
+#define FCTX_ATTR_SHUTTINGDOWN 0x0008
+#define FCTX_ATTR_WANTCACHE 0x0010
+#define FCTX_ATTR_WANTNCACHE 0x0020
+#define FCTX_ATTR_NEEDEDNS0 0x0040
+#define FCTX_ATTR_TRIEDFIND 0x0080
+#define FCTX_ATTR_TRIEDALT 0x0100
+
+#define HAVE_ANSWER(f) (((f)->attributes & FCTX_ATTR_HAVEANSWER) != \
+ 0)
+#define GLUING(f) (((f)->attributes & FCTX_ATTR_GLUING) != \
+ 0)
+#define ADDRWAIT(f) (((f)->attributes & FCTX_ATTR_ADDRWAIT) != \
+ 0)
+#define SHUTTINGDOWN(f) (((f)->attributes & FCTX_ATTR_SHUTTINGDOWN) \
+ != 0)
+#define WANTCACHE(f) (((f)->attributes & FCTX_ATTR_WANTCACHE) != 0)
+#define WANTNCACHE(f) (((f)->attributes & FCTX_ATTR_WANTNCACHE) != 0)
+#define NEEDEDNS0(f) (((f)->attributes & FCTX_ATTR_NEEDEDNS0) != 0)
+#define TRIEDFIND(f) (((f)->attributes & FCTX_ATTR_TRIEDFIND) != 0)
+#define TRIEDALT(f) (((f)->attributes & FCTX_ATTR_TRIEDALT) != 0)
+
+typedef struct {
+ dns_adbaddrinfo_t * addrinfo;
+ fetchctx_t * fctx;
+} dns_valarg_t;
+
+struct dns_fetch {
+ unsigned int magic;
+ fetchctx_t * private;
+};
+
+#define DNS_FETCH_MAGIC ISC_MAGIC('F', 't', 'c', 'h')
+#define DNS_FETCH_VALID(fetch) ISC_MAGIC_VALID(fetch, DNS_FETCH_MAGIC)
+
+typedef struct fctxbucket {
+ isc_task_t * task;
+ isc_mutex_t lock;
+ ISC_LIST(fetchctx_t) fctxs;
+ isc_boolean_t exiting;
+ isc_mem_t * mctx;
+} fctxbucket_t;
+
+typedef struct alternate {
+ isc_boolean_t isaddress;
+ union {
+ isc_sockaddr_t addr;
+ struct {
+ dns_name_t name;
+ in_port_t port;
+ } _n;
+ } _u;
+ ISC_LINK(struct alternate) link;
+} alternate_t;
+
+struct dns_resolver {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ isc_mutex_t lock;
+ isc_mutex_t nlock;
+ isc_mutex_t primelock;
+ dns_rdataclass_t rdclass;
+ isc_socketmgr_t * socketmgr;
+ isc_timermgr_t * timermgr;
+ isc_taskmgr_t * taskmgr;
+ dns_view_t * view;
+ isc_boolean_t frozen;
+ unsigned int options;
+ dns_dispatchmgr_t * dispatchmgr;
+ dns_dispatch_t * dispatchv4;
+ isc_boolean_t exclusivev4;
+ dns_dispatch_t * dispatchv6;
+ isc_boolean_t exclusivev6;
+ unsigned int ndisps;
+ unsigned int nbuckets;
+ fctxbucket_t * buckets;
+ isc_uint32_t lame_ttl;
+ ISC_LIST(alternate_t) alternates;
+ isc_uint16_t udpsize;
+#if USE_ALGLOCK
+ isc_rwlock_t alglock;
+#endif
+ dns_rbt_t * algorithms;
+#if USE_MBSLOCK
+ isc_rwlock_t mbslock;
+#endif
+ dns_rbt_t * mustbesecure;
+ unsigned int spillatmax;
+ unsigned int spillatmin;
+ isc_timer_t * spillattimer;
+ isc_boolean_t zero_no_soa_ttl;
+
+ /* Locked by lock. */
+ unsigned int references;
+ isc_boolean_t exiting;
+ isc_eventlist_t whenshutdown;
+ unsigned int activebuckets;
+ isc_boolean_t priming;
+ unsigned int spillat; /* clients-per-query */
+ unsigned int nextdisp;
+ /* Locked by primelock. */
+ dns_fetch_t * primefetch;
+ /* Locked by nlock. */
+ unsigned int nfctx;
+};
+
+#define RES_MAGIC ISC_MAGIC('R', 'e', 's', '!')
+#define VALID_RESOLVER(res) ISC_MAGIC_VALID(res, RES_MAGIC)
+
+/*%
+ * Private addrinfo flags. These must not conflict with DNS_FETCHOPT_NOEDNS0,
+ * which we also use as an addrinfo flag.
+ */
+#define FCTX_ADDRINFO_MARK 0x0001
+#define FCTX_ADDRINFO_FORWARDER 0x1000
+#define FCTX_ADDRINFO_TRIED 0x2000
+#define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \
+ == 0)
+#define ISFORWARDER(a) (((a)->flags & \
+ FCTX_ADDRINFO_FORWARDER) != 0)
+#define TRIED(a) (((a)->flags & \
+ FCTX_ADDRINFO_TRIED) != 0)
+
+#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
+
+static void destroy(dns_resolver_t *res);
+static void empty_bucket(dns_resolver_t *res);
+static isc_result_t resquery_send(resquery_t *query);
+static void resquery_response(isc_task_t *task, isc_event_t *event);
+static void resquery_connected(isc_task_t *task, isc_event_t *event);
+static void fctx_try(fetchctx_t *fctx, isc_boolean_t retrying);
+static isc_boolean_t fctx_destroy(fetchctx_t *fctx);
+static isc_result_t ncache_adderesult(dns_message_t *message,
+ dns_db_t *cache, dns_dbnode_t *node,
+ dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_ttl_t maxttl,
+ isc_boolean_t optout,
+ dns_rdataset_t *ardataset,
+ isc_result_t *eresultp);
+static void validated(isc_task_t *task, isc_event_t *event);
+static void maybe_destroy(fetchctx_t *fctx);
+static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
+ isc_result_t reason);
+
+/*%
+ * Increment resolver-related statistics counters.
+ */
+static inline void
+inc_stats(dns_resolver_t *res, dns_statscounter_t counter) {
+ if (res->view->resstats != NULL)
+ dns_generalstats_increment(res->view->resstats, counter);
+}
+
+static isc_result_t
+valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset, unsigned int valoptions,
+ isc_task_t *task)
+{
+ dns_validator_t *validator = NULL;
+ dns_valarg_t *valarg;
+ isc_result_t result;
+
+ valarg = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
+ sizeof(*valarg));
+ if (valarg == NULL)
+ return (ISC_R_NOMEMORY);
+
+ valarg->fctx = fctx;
+ valarg->addrinfo = addrinfo;
+
+ if (!ISC_LIST_EMPTY(fctx->validators))
+ INSIST((valoptions & DNS_VALIDATOR_DEFER) != 0);
+
+ result = dns_validator_create(fctx->res->view, name, type, rdataset,
+ sigrdataset, fctx->rmessage,
+ valoptions, task, validated, valarg,
+ &validator);
+ if (result == ISC_R_SUCCESS) {
+ inc_stats(fctx->res, dns_resstatscounter_val);
+ if ((valoptions & DNS_VALIDATOR_DEFER) == 0) {
+ INSIST(fctx->validator == NULL);
+ fctx->validator = validator;
+ }
+ ISC_LIST_APPEND(fctx->validators, validator, link);
+ } else
+ isc_mem_put(fctx->res->buckets[fctx->bucketnum].mctx,
+ valarg, sizeof(*valarg));
+ return (result);
+}
+
+static isc_boolean_t
+fix_mustbedelegationornxdomain(dns_message_t *message, fetchctx_t *fctx) {
+ dns_name_t *name;
+ dns_name_t *domain = &fctx->domain;
+ dns_rdataset_t *rdataset;
+ dns_rdatatype_t type;
+ isc_result_t result;
+ isc_boolean_t keep_auth = ISC_FALSE;
+
+ if (message->rcode == dns_rcode_nxdomain)
+ return (ISC_FALSE);
+
+ /*
+ * Look for BIND 8 style delegations.
+ * Also look for answers to ANY queries where the duplicate NS RRset
+ * may have been stripped from the authority section.
+ */
+ if (message->counts[DNS_SECTION_ANSWER] != 0 &&
+ (fctx->type == dns_rdatatype_ns ||
+ fctx->type == dns_rdatatype_any)) {
+ result = dns_message_firstname(message, DNS_SECTION_ANSWER);
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_ANSWER,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ type = rdataset->type;
+ if (type != dns_rdatatype_ns)
+ continue;
+ if (dns_name_issubdomain(name, domain))
+ return (ISC_FALSE);
+ }
+ result = dns_message_nextname(message,
+ DNS_SECTION_ANSWER);
+ }
+ }
+
+ /* Look for referral. */
+ if (message->counts[DNS_SECTION_AUTHORITY] == 0)
+ goto munge;
+
+ result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ type = rdataset->type;
+ if (type == dns_rdatatype_soa &&
+ dns_name_equal(name, domain))
+ keep_auth = ISC_TRUE;
+ if (type != dns_rdatatype_ns &&
+ type != dns_rdatatype_soa)
+ continue;
+ if (dns_name_equal(name, domain))
+ goto munge;
+ if (dns_name_issubdomain(name, domain))
+ return (ISC_FALSE);
+ }
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
+ }
+
+ munge:
+ message->rcode = dns_rcode_nxdomain;
+ message->counts[DNS_SECTION_ANSWER] = 0;
+ if (!keep_auth)
+ message->counts[DNS_SECTION_AUTHORITY] = 0;
+ message->counts[DNS_SECTION_ADDITIONAL] = 0;
+ return (ISC_TRUE);
+}
+
+static inline isc_result_t
+fctx_starttimer(fetchctx_t *fctx) {
+ /*
+ * Start the lifetime timer for fctx.
+ *
+ * This is also used for stopping the idle timer; in that
+ * case we must purge events already posted to ensure that
+ * no further idle events are delivered.
+ */
+ return (isc_timer_reset(fctx->timer, isc_timertype_once,
+ &fctx->expires, NULL, ISC_TRUE));
+}
+
+static inline void
+fctx_stoptimer(fetchctx_t *fctx) {
+ isc_result_t result;
+
+ /*
+ * We don't return a result if resetting the timer to inactive fails
+ * since there's nothing to be done about it. Resetting to inactive
+ * should never fail anyway, since the code as currently written
+ * cannot fail in that case.
+ */
+ result = isc_timer_reset(fctx->timer, isc_timertype_inactive,
+ NULL, NULL, ISC_TRUE);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_timer_reset(): %s",
+ isc_result_totext(result));
+ }
+}
+
+
+static inline isc_result_t
+fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) {
+ /*
+ * Start the idle timer for fctx. The lifetime timer continues
+ * to be in effect.
+ */
+ return (isc_timer_reset(fctx->timer, isc_timertype_once,
+ &fctx->expires, interval, ISC_FALSE));
+}
+
+/*
+ * Stopping the idle timer is equivalent to calling fctx_starttimer(), but
+ * we use fctx_stopidletimer for readability in the code below.
+ */
+#define fctx_stopidletimer fctx_starttimer
+
+
+static inline void
+resquery_destroy(resquery_t **queryp) {
+ resquery_t *query;
+
+ REQUIRE(queryp != NULL);
+ query = *queryp;
+ REQUIRE(!ISC_LINK_LINKED(query, link));
+
+ INSIST(query->tcpsocket == NULL);
+
+ query->fctx->nqueries--;
+ if (SHUTTINGDOWN(query->fctx))
+ maybe_destroy(query->fctx); /* Locks bucket. */
+ query->magic = 0;
+ isc_mem_put(query->mctx, query, sizeof(*query));
+ *queryp = NULL;
+}
+
+static void
+fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
+ isc_time_t *finish, isc_boolean_t no_response)
+{
+ fetchctx_t *fctx;
+ resquery_t *query;
+ unsigned int rtt;
+ unsigned int factor;
+ dns_adbfind_t *find;
+ dns_adbaddrinfo_t *addrinfo;
+ isc_socket_t *socket;
+
+ query = *queryp;
+ fctx = query->fctx;
+
+ FCTXTRACE("cancelquery");
+
+ REQUIRE(!RESQUERY_CANCELED(query));
+
+ query->attributes |= RESQUERY_ATTR_CANCELED;
+
+ /*
+ * Should we update the RTT?
+ */
+ if (finish != NULL || no_response) {
+ if (finish != NULL) {
+ /*
+ * We have both the start and finish times for this
+ * packet, so we can compute a real RTT.
+ */
+ rtt = (unsigned int)isc_time_microdiff(finish,
+ &query->start);
+ factor = DNS_ADB_RTTADJDEFAULT;
+ } else {
+ /*
+ * We don't have an RTT for this query. Maybe the
+ * packet was lost, or maybe this server is very
+ * slow. We don't know. Increase the RTT.
+ */
+ INSIST(no_response);
+ rtt = query->addrinfo->srtt + 200000;
+ if (rtt > 10000000)
+ rtt = 10000000;
+ /*
+ * Replace the current RTT with our value.
+ */
+ factor = DNS_ADB_RTTADJREPLACE;
+ }
+ dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);
+ }
+
+ /* Remember that the server has been tried. */
+ if (!TRIED(query->addrinfo)) {
+ dns_adb_changeflags(fctx->adb, query->addrinfo,
+ FCTX_ADDRINFO_TRIED, FCTX_ADDRINFO_TRIED);
+ }
+
+ /*
+ * Age RTTs of servers not tried.
+ */
+ factor = DNS_ADB_RTTADJAGE;
+ if (finish != NULL)
+ for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink))
+ if (UNMARKED(addrinfo))
+ dns_adb_adjustsrtt(fctx->adb, addrinfo,
+ 0, factor);
+
+ if (finish != NULL && TRIEDFIND(fctx))
+ for (find = ISC_LIST_HEAD(fctx->finds);
+ find != NULL;
+ find = ISC_LIST_NEXT(find, publink))
+ for (addrinfo = ISC_LIST_HEAD(find->list);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink))
+ if (UNMARKED(addrinfo))
+ dns_adb_adjustsrtt(fctx->adb, addrinfo,
+ 0, factor);
+
+ if (finish != NULL && TRIEDALT(fctx)) {
+ for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink))
+ if (UNMARKED(addrinfo))
+ dns_adb_adjustsrtt(fctx->adb, addrinfo,
+ 0, factor);
+ for (find = ISC_LIST_HEAD(fctx->altfinds);
+ find != NULL;
+ find = ISC_LIST_NEXT(find, publink))
+ for (addrinfo = ISC_LIST_HEAD(find->list);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink))
+ if (UNMARKED(addrinfo))
+ dns_adb_adjustsrtt(fctx->adb, addrinfo,
+ 0, factor);
+ }
+
+ /*
+ * Check for any outstanding socket events. If they exist, cancel
+ * them and let the event handlers finish the cleanup. The resolver
+ * only needs to worry about managing the connect and send events;
+ * the dispatcher manages the recv events.
+ */
+ if (RESQUERY_CONNECTING(query)) {
+ /*
+ * Cancel the connect.
+ */
+ if (query->tcpsocket != NULL) {
+ isc_socket_cancel(query->tcpsocket, NULL,
+ ISC_SOCKCANCEL_CONNECT);
+ } else if (query->dispentry != NULL) {
+ INSIST(query->exclusivesocket);
+ socket = dns_dispatch_getentrysocket(query->dispentry);
+ if (socket != NULL)
+ isc_socket_cancel(socket, NULL,
+ ISC_SOCKCANCEL_CONNECT);
+ }
+ } else if (RESQUERY_SENDING(query)) {
+ /*
+ * Cancel the pending send.
+ */
+ if (query->exclusivesocket && query->dispentry != NULL)
+ socket = dns_dispatch_getentrysocket(query->dispentry);
+ else
+ socket = dns_dispatch_getsocket(query->dispatch);
+ if (socket != NULL)
+ isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
+ }
+
+ if (query->dispentry != NULL)
+ dns_dispatch_removeresponse(&query->dispentry, deventp);
+
+ ISC_LIST_UNLINK(fctx->queries, query, link);
+
+ if (query->tsig != NULL)
+ isc_buffer_free(&query->tsig);
+
+ if (query->tsigkey != NULL)
+ dns_tsigkey_detach(&query->tsigkey);
+
+ if (query->dispatch != NULL)
+ dns_dispatch_detach(&query->dispatch);
+
+ if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))
+ /*
+ * It's safe to destroy the query now.
+ */
+ resquery_destroy(&query);
+}
+
+static void
+fctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {
+ resquery_t *query, *next_query;
+
+ FCTXTRACE("cancelqueries");
+
+ for (query = ISC_LIST_HEAD(fctx->queries);
+ query != NULL;
+ query = next_query) {
+ next_query = ISC_LIST_NEXT(query, link);
+ fctx_cancelquery(&query, NULL, NULL, no_response);
+ }
+}
+
+static void
+fctx_cleanupfinds(fetchctx_t *fctx) {
+ dns_adbfind_t *find, *next_find;
+
+ REQUIRE(ISC_LIST_EMPTY(fctx->queries));
+
+ for (find = ISC_LIST_HEAD(fctx->finds);
+ find != NULL;
+ find = next_find) {
+ next_find = ISC_LIST_NEXT(find, publink);
+ ISC_LIST_UNLINK(fctx->finds, find, publink);
+ dns_adb_destroyfind(&find);
+ }
+ fctx->find = NULL;
+}
+
+static void
+fctx_cleanupaltfinds(fetchctx_t *fctx) {
+ dns_adbfind_t *find, *next_find;
+
+ REQUIRE(ISC_LIST_EMPTY(fctx->queries));
+
+ for (find = ISC_LIST_HEAD(fctx->altfinds);
+ find != NULL;
+ find = next_find) {
+ next_find = ISC_LIST_NEXT(find, publink);
+ ISC_LIST_UNLINK(fctx->altfinds, find, publink);
+ dns_adb_destroyfind(&find);
+ }
+ fctx->altfind = NULL;
+}
+
+static void
+fctx_cleanupforwaddrs(fetchctx_t *fctx) {
+ dns_adbaddrinfo_t *addr, *next_addr;
+
+ REQUIRE(ISC_LIST_EMPTY(fctx->queries));
+
+ for (addr = ISC_LIST_HEAD(fctx->forwaddrs);
+ addr != NULL;
+ addr = next_addr) {
+ next_addr = ISC_LIST_NEXT(addr, publink);
+ ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);
+ dns_adb_freeaddrinfo(fctx->adb, &addr);
+ }
+}
+
+static void
+fctx_cleanupaltaddrs(fetchctx_t *fctx) {
+ dns_adbaddrinfo_t *addr, *next_addr;
+
+ REQUIRE(ISC_LIST_EMPTY(fctx->queries));
+
+ for (addr = ISC_LIST_HEAD(fctx->altaddrs);
+ addr != NULL;
+ addr = next_addr) {
+ next_addr = ISC_LIST_NEXT(addr, publink);
+ ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);
+ dns_adb_freeaddrinfo(fctx->adb, &addr);
+ }
+}
+
+static inline void
+fctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {
+ FCTXTRACE("stopeverything");
+ fctx_cancelqueries(fctx, no_response);
+ fctx_cleanupfinds(fctx);
+ fctx_cleanupaltfinds(fctx);
+ fctx_cleanupforwaddrs(fctx);
+ fctx_cleanupaltaddrs(fctx);
+ fctx_stoptimer(fctx);
+}
+
+static inline void
+fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
+ dns_fetchevent_t *event, *next_event;
+ isc_task_t *task;
+ unsigned int count = 0;
+ isc_interval_t i;
+ isc_boolean_t logit = ISC_FALSE;
+ unsigned int old_spillat;
+ unsigned int new_spillat = 0; /* initialized to silence
+ compiler warnings */
+
+ /*
+ * Caller must be holding the appropriate bucket lock.
+ */
+ REQUIRE(fctx->state == fetchstate_done);
+
+ FCTXTRACE("sendevents");
+
+ for (event = ISC_LIST_HEAD(fctx->events);
+ event != NULL;
+ event = next_event) {
+ next_event = ISC_LIST_NEXT(event, ev_link);
+ ISC_LIST_UNLINK(fctx->events, event, ev_link);
+ task = event->ev_sender;
+ event->ev_sender = fctx;
+ if (!HAVE_ANSWER(fctx))
+ event->result = result;
+
+ INSIST(result != ISC_R_SUCCESS ||
+ dns_rdataset_isassociated(event->rdataset) ||
+ fctx->type == dns_rdatatype_any ||
+ fctx->type == dns_rdatatype_rrsig ||
+ fctx->type == dns_rdatatype_sig);
+
+ /*
+ * Negative results must be indicated in event->result.
+ */
+ if (dns_rdataset_isassociated(event->rdataset) &&
+ event->rdataset->type == dns_rdatatype_none) {
+ INSIST(event->result == DNS_R_NCACHENXDOMAIN ||
+ event->result == DNS_R_NCACHENXRRSET);
+ }
+
+ isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));
+ count++;
+ }
+
+ if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&
+ fctx->spilled &&
+ (count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
+ LOCK(&fctx->res->lock);
+ if (count == fctx->res->spillat && !fctx->res->exiting) {
+ old_spillat = fctx->res->spillat;
+ fctx->res->spillat += 5;
+ if (fctx->res->spillat > fctx->res->spillatmax &&
+ fctx->res->spillatmax != 0)
+ fctx->res->spillat = fctx->res->spillatmax;
+ new_spillat = fctx->res->spillat;
+ if (new_spillat != old_spillat) {
+ logit = ISC_TRUE;
+ }
+ isc_interval_set(&i, 20 * 60, 0);
+ result = isc_timer_reset(fctx->res->spillattimer,
+ isc_timertype_ticker, NULL,
+ &i, ISC_TRUE);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
+ UNLOCK(&fctx->res->lock);
+ if (logit)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
+ "clients-per-query increased to %u",
+ new_spillat);
+ }
+}
+
+static inline void
+log_edns(fetchctx_t *fctx) {
+ char domainbuf[DNS_NAME_FORMATSIZE];
+
+ if (fctx->reason == NULL)
+ return;
+
+ dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_EDNS_DISABLED,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
+ "success resolving '%s' (in '%s'?) after %s",
+ fctx->info, domainbuf, fctx->reason);
+
+ fctx->reason = NULL;
+}
+
+static void
+fctx_done(fetchctx_t *fctx, isc_result_t result) {
+ dns_resolver_t *res;
+ isc_boolean_t no_response;
+
+ FCTXTRACE("done");
+
+ res = fctx->res;
+
+ if (result == ISC_R_SUCCESS) {
+ /*%
+ * Log any deferred EDNS timeout messages.
+ */
+ log_edns(fctx);
+ no_response = ISC_TRUE;
+ } else
+ no_response = ISC_FALSE;
+
+ fctx->reason = NULL;
+ fctx_stopeverything(fctx, no_response);
+
+ LOCK(&res->buckets[fctx->bucketnum].lock);
+
+ fctx->state = fetchstate_done;
+ fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ fctx_sendevents(fctx, result);
+
+ UNLOCK(&res->buckets[fctx->bucketnum].lock);
+}
+
+static void
+process_sendevent(resquery_t *query, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ isc_boolean_t retry = ISC_FALSE;
+ isc_result_t result;
+ fetchctx_t *fctx;
+
+ fctx = query->fctx;
+
+ if (RESQUERY_CANCELED(query)) {
+ if (query->sends == 0 && query->connects == 0) {
+ /*
+ * This query was canceled while the
+ * isc_socket_sendto/connect() was in progress.
+ */
+ if (query->tcpsocket != NULL)
+ isc_socket_detach(&query->tcpsocket);
+ resquery_destroy(&query);
+ }
+ } else {
+ switch (sevent->result) {
+ case ISC_R_SUCCESS:
+ break;
+
+ case ISC_R_HOSTUNREACH:
+ case ISC_R_NETUNREACH:
+ case ISC_R_NOPERM:
+ case ISC_R_ADDRNOTAVAIL:
+ case ISC_R_CONNREFUSED:
+
+ /*
+ * No route to remote.
+ */
+ add_bad(fctx, query->addrinfo, sevent->result);
+ fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
+ retry = ISC_TRUE;
+ break;
+
+ default:
+ fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
+ break;
+ }
+ }
+
+ isc_event_free(&event);
+
+ if (retry) {
+ /*
+ * Behave as if the idle timer has expired. For TCP
+ * this may not actually reflect the latest timer.
+ */
+ fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ result = fctx_stopidletimer(fctx);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result);
+ else
+ fctx_try(fctx, ISC_TRUE);
+ }
+}
+
+static void
+resquery_udpconnected(isc_task_t *task, isc_event_t *event) {
+ resquery_t *query = event->ev_arg;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
+
+ QTRACE("udpconnected");
+
+ UNUSED(task);
+
+ INSIST(RESQUERY_CONNECTING(query));
+
+ query->connects--;
+
+ process_sendevent(query, event);
+}
+
+static void
+resquery_senddone(isc_task_t *task, isc_event_t *event) {
+ resquery_t *query = event->ev_arg;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+
+ QTRACE("senddone");
+
+ /*
+ * XXXRTH
+ *
+ * Currently we don't wait for the senddone event before retrying
+ * a query. This means that if we get really behind, we may end
+ * up doing extra work!
+ */
+
+ UNUSED(task);
+
+ INSIST(RESQUERY_SENDING(query));
+
+ query->sends--;
+
+ process_sendevent(query, event);
+}
+
+static inline isc_result_t
+fctx_addopt(dns_message_t *message, unsigned int version,
+ isc_uint16_t udpsize, isc_boolean_t request_nsid)
+{
+ dns_rdataset_t *rdataset;
+ dns_rdatalist_t *rdatalist;
+ dns_rdata_t *rdata;
+ isc_result_t result;
+
+ rdatalist = NULL;
+ result = dns_message_gettemprdatalist(message, &rdatalist);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ rdata = NULL;
+ result = dns_message_gettemprdata(message, &rdata);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ rdataset = NULL;
+ result = dns_message_gettemprdataset(message, &rdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_init(rdataset);
+
+ rdatalist->type = dns_rdatatype_opt;
+ rdatalist->covers = 0;
+
+ /*
+ * Set Maximum UDP buffer size.
+ */
+ rdatalist->rdclass = udpsize;
+
+ /*
+ * Set EXTENDED-RCODE and Z to 0, DO to 1.
+ */
+ rdatalist->ttl = (version << 16);
+ rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
+
+ /*
+ * Set EDNS options if applicable
+ */
+ if (request_nsid) {
+ /* Send empty NSID option (RFC5001) */
+ unsigned char data[4];
+ isc_buffer_t buf;
+
+ 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;
+ }
+
+ rdata->rdclass = rdatalist->rdclass;
+ rdata->type = rdatalist->type;
+ rdata->flags = 0;
+
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS);
+
+ return (dns_message_setopt(message, rdataset));
+}
+
+static inline void
+fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
+ unsigned int seconds;
+ unsigned int us;
+
+ /*
+ * We retry every .8 seconds the first two times through the address
+ * list, and then we do exponential back-off.
+ */
+ if (fctx->restarts < 3)
+ us = 800000;
+ else
+ us = (800000 << (fctx->restarts - 2));
+
+ /*
+ * Double the round-trip time.
+ */
+ rtt *= 2;
+
+ /*
+ * Always wait for at least the doubled round-trip time.
+ */
+ if (us < rtt)
+ us = rtt;
+
+ /*
+ * But don't ever wait for more than 10 seconds.
+ */
+ if (us > 10000000)
+ us = 10000000;
+
+ seconds = us / 1000000;
+ us -= seconds * 1000000;
+ isc_interval_set(&fctx->interval, seconds, us * 1000);
+}
+
+static isc_result_t
+fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
+ unsigned int options)
+{
+ dns_resolver_t *res;
+ isc_task_t *task;
+ isc_result_t result;
+ resquery_t *query;
+ isc_sockaddr_t addr;
+ isc_boolean_t have_addr = ISC_FALSE;
+ unsigned int srtt;
+
+ FCTXTRACE("query");
+
+ res = fctx->res;
+ task = res->buckets[fctx->bucketnum].task;
+
+ srtt = addrinfo->srtt;
+ if (ISFORWARDER(addrinfo) && srtt < 1000000)
+ srtt = 1000000;
+
+ fctx_setretryinterval(fctx, srtt);
+ result = fctx_startidletimer(fctx, &fctx->interval);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ INSIST(ISC_LIST_EMPTY(fctx->validators));
+
+ dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);
+
+ query = isc_mem_get(res->buckets[fctx->bucketnum].mctx,
+ sizeof(*query));
+ if (query == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto stop_idle_timer;
+ }
+ query->mctx = res->buckets[fctx->bucketnum].mctx;
+ query->options = options;
+ query->attributes = 0;
+ query->sends = 0;
+ query->connects = 0;
+ /*
+ * Note that the caller MUST guarantee that 'addrinfo' will remain
+ * valid until this query is canceled.
+ */
+ query->addrinfo = addrinfo;
+ TIME_NOW(&query->start);
+
+ /*
+ * If this is a TCP query, then we need to make a socket and
+ * a dispatch for it here. Otherwise we use the resolver's
+ * shared dispatch.
+ */
+ query->dispatchmgr = res->dispatchmgr;
+ query->dispatch = NULL;
+ query->exclusivesocket = ISC_FALSE;
+ query->tcpsocket = NULL;
+ if (res->view->peers != NULL) {
+ dns_peer_t *peer = NULL;
+ isc_netaddr_t dstip;
+ isc_netaddr_fromsockaddr(&dstip, &addrinfo->sockaddr);
+ result = dns_peerlist_peerbyaddr(res->view->peers,
+ &dstip, &peer);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_peer_getquerysource(peer, &addr);
+ if (result == ISC_R_SUCCESS)
+ have_addr = ISC_TRUE;
+ }
+ }
+
+ if ((query->options & DNS_FETCHOPT_TCP) != 0) {
+ int pf;
+
+ pf = isc_sockaddr_pf(&addrinfo->sockaddr);
+ if (!have_addr) {
+ switch (pf) {
+ case PF_INET:
+ result =
+ dns_dispatch_getlocaladdress(res->dispatchv4,
+ &addr);
+ break;
+ case PF_INET6:
+ result =
+ dns_dispatch_getlocaladdress(res->dispatchv6,
+ &addr);
+ break;
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ break;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_query;
+ }
+ isc_sockaddr_setport(&addr, 0);
+
+ result = isc_socket_create(res->socketmgr, pf,
+ isc_sockettype_tcp,
+ &query->tcpsocket);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_query;
+
+#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
+ result = isc_socket_bind(query->tcpsocket, &addr, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_socket;
+#endif
+
+ /*
+ * A dispatch will be created once the connect succeeds.
+ */
+ } else {
+ if (have_addr) {
+ unsigned int attrs, attrmask;
+ attrs = DNS_DISPATCHATTR_UDP;
+ switch (isc_sockaddr_pf(&addr)) {
+ case AF_INET:
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ break;
+ case AF_INET6:
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ break;
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup_query;
+ }
+ attrmask = DNS_DISPATCHATTR_UDP;
+ attrmask |= DNS_DISPATCHATTR_TCP;
+ attrmask |= DNS_DISPATCHATTR_IPV4;
+ attrmask |= DNS_DISPATCHATTR_IPV6;
+ result = dns_dispatch_getudp(res->dispatchmgr,
+ res->socketmgr,
+ res->taskmgr, &addr,
+ 4096, 1000, 32768, 16411,
+ 16433, attrs, attrmask,
+ &query->dispatch);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_query;
+ } else {
+ switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
+ case PF_INET:
+ dns_dispatch_attach(res->dispatchv4,
+ &query->dispatch);
+ query->exclusivesocket = res->exclusivev4;
+ break;
+ case PF_INET6:
+ dns_dispatch_attach(res->dispatchv6,
+ &query->dispatch);
+ query->exclusivesocket = res->exclusivev6;
+ break;
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup_query;
+ }
+ }
+ /*
+ * We should always have a valid dispatcher here. If we
+ * don't support a protocol family, then its dispatcher
+ * will be NULL, but we shouldn't be finding addresses for
+ * protocol types we don't support, so the dispatcher
+ * we found should never be NULL.
+ */
+ INSIST(query->dispatch != NULL);
+ }
+
+ query->dispentry = NULL;
+ query->fctx = fctx;
+ query->tsig = NULL;
+ query->tsigkey = NULL;
+ ISC_LINK_INIT(query, link);
+ query->magic = QUERY_MAGIC;
+
+ if ((query->options & DNS_FETCHOPT_TCP) != 0) {
+ /*
+ * Connect to the remote server.
+ *
+ * XXXRTH Should we attach to the socket?
+ */
+ result = isc_socket_connect(query->tcpsocket,
+ &addrinfo->sockaddr, task,
+ resquery_connected, query);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_socket;
+ query->connects++;
+ QTRACE("connecting via TCP");
+ } else {
+ result = resquery_send(query);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_dispatch;
+ }
+
+ ISC_LIST_APPEND(fctx->queries, query, link);
+ query->fctx->nqueries++;
+ if (isc_sockaddr_pf(&addrinfo->sockaddr) == PF_INET)
+ inc_stats(res, dns_resstatscounter_queryv4);
+ else
+ inc_stats(res, dns_resstatscounter_queryv6);
+ if (res->view->resquerystats != NULL)
+ dns_rdatatypestats_increment(res->view->resquerystats,
+ fctx->type);
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_socket:
+ isc_socket_detach(&query->tcpsocket);
+
+ cleanup_dispatch:
+ if (query->dispatch != NULL)
+ dns_dispatch_detach(&query->dispatch);
+
+ cleanup_query:
+ query->magic = 0;
+ isc_mem_put(res->buckets[fctx->bucketnum].mctx,
+ query, sizeof(*query));
+
+ stop_idle_timer:
+ RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
+
+ return (result);
+}
+
+static isc_boolean_t
+triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
+ isc_sockaddr_t *sa;
+
+ for (sa = ISC_LIST_HEAD(fctx->edns);
+ sa != NULL;
+ sa = ISC_LIST_NEXT(sa, link)) {
+ if (isc_sockaddr_equal(sa, address))
+ return (ISC_TRUE);
+ }
+
+ return (ISC_FALSE);
+}
+
+static void
+add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
+ isc_sockaddr_t *sa;
+
+ if (triededns(fctx, address))
+ return;
+
+ sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
+ sizeof(*sa));
+ if (sa == NULL)
+ return;
+
+ *sa = *address;
+ ISC_LIST_INITANDAPPEND(fctx->edns, sa, link);
+}
+
+static isc_boolean_t
+triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
+ isc_sockaddr_t *sa;
+
+ for (sa = ISC_LIST_HEAD(fctx->edns512);
+ sa != NULL;
+ sa = ISC_LIST_NEXT(sa, link)) {
+ if (isc_sockaddr_equal(sa, address))
+ return (ISC_TRUE);
+ }
+
+ return (ISC_FALSE);
+}
+
+static void
+add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
+ isc_sockaddr_t *sa;
+
+ if (triededns512(fctx, address))
+ return;
+
+ sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
+ sizeof(*sa));
+ if (sa == NULL)
+ return;
+
+ *sa = *address;
+ ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link);
+}
+
+static isc_result_t
+resquery_send(resquery_t *query) {
+ fetchctx_t *fctx;
+ isc_result_t result;
+ dns_name_t *qname = NULL;
+ dns_rdataset_t *qrdataset = NULL;
+ isc_region_t r;
+ dns_resolver_t *res;
+ isc_task_t *task;
+ isc_socket_t *socket;
+ isc_buffer_t tcpbuffer;
+ isc_sockaddr_t *address;
+ isc_buffer_t *buffer;
+ isc_netaddr_t ipaddr;
+ dns_tsigkey_t *tsigkey = NULL;
+ dns_peer_t *peer = NULL;
+ isc_boolean_t useedns;
+ dns_compress_t cctx;
+ isc_boolean_t cleanup_cctx = ISC_FALSE;
+ isc_boolean_t secure_domain;
+
+ fctx = query->fctx;
+ QTRACE("send");
+
+ res = fctx->res;
+ task = res->buckets[fctx->bucketnum].task;
+ address = NULL;
+
+ if ((query->options & DNS_FETCHOPT_TCP) != 0) {
+ /*
+ * Reserve space for the TCP message length.
+ */
+ isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));
+ isc_buffer_init(&query->buffer, query->data + 2,
+ sizeof(query->data) - 2);
+ buffer = &tcpbuffer;
+ } else {
+ isc_buffer_init(&query->buffer, query->data,
+ sizeof(query->data));
+ buffer = &query->buffer;
+ }
+
+ result = dns_message_gettempname(fctx->qmessage, &qname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_temps;
+ result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_temps;
+
+ /*
+ * Get a query id from the dispatch.
+ */
+ result = dns_dispatch_addresponse2(query->dispatch,
+ &query->addrinfo->sockaddr,
+ task,
+ resquery_response,
+ query,
+ &query->id,
+ &query->dispentry,
+ res->socketmgr);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_temps;
+
+ fctx->qmessage->opcode = dns_opcode_query;
+
+ /*
+ * Set up question.
+ */
+ dns_name_init(qname, NULL);
+ dns_name_clone(&fctx->name, qname);
+ dns_rdataset_init(qrdataset);
+ dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+ dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);
+ qname = NULL;
+ qrdataset = NULL;
+
+ /*
+ * Set RD if the client has requested that we do a recursive query,
+ * or if we're sending to a forwarder.
+ */
+ if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||
+ ISFORWARDER(query->addrinfo))
+ fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;
+
+ /*
+ * Set CD if the client says don't validate or the question is
+ * under a secure entry point.
+ */
+ 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);
+ if (result != ISC_R_SUCCESS)
+ secure_domain = ISC_FALSE;
+ if (res->view->dlv != NULL)
+ secure_domain = ISC_TRUE;
+ if (secure_domain)
+ fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;
+ }
+
+ /*
+ * We don't have to set opcode because it defaults to query.
+ */
+ fctx->qmessage->id = query->id;
+
+ /*
+ * Convert the question to wire format.
+ */
+ result = dns_compress_init(&cctx, -1, fctx->res->mctx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+ cleanup_cctx = ISC_TRUE;
+
+ result = dns_message_renderbegin(fctx->qmessage, &cctx,
+ &query->buffer);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+
+ result = dns_message_rendersection(fctx->qmessage,
+ DNS_SECTION_QUESTION, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+
+ peer = NULL;
+ isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
+ (void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
+
+ /*
+ * The ADB does not know about servers with "edns no". Check this,
+ * and then inform the ADB for future use.
+ */
+ if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&
+ peer != NULL &&
+ dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&
+ !useedns)
+ {
+ query->options |= DNS_FETCHOPT_NOEDNS0;
+ dns_adb_changeflags(fctx->adb, query->addrinfo,
+ DNS_FETCHOPT_NOEDNS0,
+ DNS_FETCHOPT_NOEDNS0);
+ }
+
+ /* Sync NOEDNS0 flag in addrinfo->flags and options now */
+ if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) != 0)
+ query->options |= DNS_FETCHOPT_NOEDNS0;
+
+ /*
+ * Use EDNS0, unless the caller doesn't want it, or we know that
+ * the remote server doesn't like it.
+ */
+
+ if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
+ fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
+ (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
+ query->options |= DNS_FETCHOPT_NOEDNS0;
+ fctx->reason = "disabling EDNS";
+ } else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
+ fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
+ (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
+ query->options |= DNS_FETCHOPT_EDNS512;
+ fctx->reason = "reducing the advertised EDNS UDP packet "
+ "size to 512 octets";
+ }
+
+ if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
+ if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {
+ unsigned int version = 0; /* Default version. */
+ unsigned int flags;
+ isc_uint16_t udpsize = res->udpsize;
+ isc_boolean_t reqnsid = res->view->requestnsid;
+
+ flags = query->addrinfo->flags;
+ if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
+ version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
+ version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;
+ }
+ if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
+ udpsize = 512;
+ else if (peer != NULL)
+ (void)dns_peer_getudpsize(peer, &udpsize);
+
+ /* request NSID for current view or peer? */
+ if (peer != NULL)
+ (void) dns_peer_getrequestnsid(peer, &reqnsid);
+ result = fctx_addopt(fctx->qmessage, version,
+ udpsize, reqnsid);
+ if (reqnsid && result == ISC_R_SUCCESS) {
+ query->options |= DNS_FETCHOPT_WANTNSID;
+ } else if (result != ISC_R_SUCCESS) {
+ /*
+ * We couldn't add the OPT, but we'll press on.
+ * We're not using EDNS0, so set the NOEDNS0
+ * bit.
+ */
+ query->options |= DNS_FETCHOPT_NOEDNS0;
+ }
+ } else {
+ /*
+ * We know this server doesn't like EDNS0, so we
+ * won't use it. Set the NOEDNS0 bit since we're
+ * not using EDNS0.
+ */
+ query->options |= DNS_FETCHOPT_NOEDNS0;
+ }
+ }
+
+ /*
+ * If we need EDNS0 to do this query and aren't using it, we lose.
+ */
+ if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {
+ result = DNS_R_SERVFAIL;
+ goto cleanup_message;
+ }
+
+ if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
+ add_triededns(fctx, &query->addrinfo->sockaddr);
+
+ if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
+ add_triededns512(fctx, &query->addrinfo->sockaddr);
+
+ /*
+ * Clear CD if EDNS is not in use.
+ */
+ if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0)
+ fctx->qmessage->flags &= ~DNS_MESSAGEFLAG_CD;
+
+ /*
+ * Add TSIG record tailored to the current recipient.
+ */
+ result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
+ goto cleanup_message;
+
+ if (tsigkey != NULL) {
+ result = dns_message_settsigkey(fctx->qmessage, tsigkey);
+ dns_tsigkey_detach(&tsigkey);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+ }
+
+ result = dns_message_rendersection(fctx->qmessage,
+ DNS_SECTION_ADDITIONAL, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+
+ result = dns_message_renderend(fctx->qmessage);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+
+ dns_compress_invalidate(&cctx);
+ cleanup_cctx = ISC_FALSE;
+
+ if (dns_message_gettsigkey(fctx->qmessage) != NULL) {
+ dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),
+ &query->tsigkey);
+ result = dns_message_getquerytsig(fctx->qmessage,
+ fctx->res->mctx,
+ &query->tsig);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+ }
+
+ /*
+ * If using TCP, write the length of the message at the beginning
+ * of the buffer.
+ */
+ if ((query->options & DNS_FETCHOPT_TCP) != 0) {
+ isc_buffer_usedregion(&query->buffer, &r);
+ isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);
+ isc_buffer_add(&tcpbuffer, r.length);
+ }
+
+ /*
+ * We're now done with the query message.
+ */
+ dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
+
+ if (query->exclusivesocket)
+ socket = dns_dispatch_getentrysocket(query->dispentry);
+ else
+ socket = dns_dispatch_getsocket(query->dispatch);
+ /*
+ * Send the query!
+ */
+ if ((query->options & DNS_FETCHOPT_TCP) == 0) {
+ address = &query->addrinfo->sockaddr;
+ if (query->exclusivesocket) {
+ result = isc_socket_connect(socket, address, task,
+ resquery_udpconnected,
+ query);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+ query->connects++;
+ }
+ }
+ isc_buffer_usedregion(buffer, &r);
+
+ /*
+ * XXXRTH Make sure we don't send to ourselves! We should probably
+ * prune out these addresses when we get them from the ADB.
+ */
+ result = isc_socket_sendto(socket, &r, task, resquery_senddone,
+ query, address, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+
+ query->sends++;
+
+ QTRACE("sent");
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_message:
+ if (cleanup_cctx)
+ dns_compress_invalidate(&cctx);
+
+ dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
+
+ /*
+ * Stop the dispatcher from listening.
+ */
+ dns_dispatch_removeresponse(&query->dispentry, NULL);
+
+ cleanup_temps:
+ if (qname != NULL)
+ dns_message_puttempname(fctx->qmessage, &qname);
+ if (qrdataset != NULL)
+ dns_message_puttemprdataset(fctx->qmessage, &qrdataset);
+
+ return (result);
+}
+
+static void
+resquery_connected(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ resquery_t *query = event->ev_arg;
+ isc_boolean_t retry = ISC_FALSE;
+ isc_interval_t interval;
+ isc_result_t result;
+ unsigned int attrs;
+ fetchctx_t *fctx;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
+ REQUIRE(VALID_QUERY(query));
+
+ QTRACE("connected");
+
+ UNUSED(task);
+
+ /*
+ * XXXRTH
+ *
+ * Currently we don't wait for the connect event before retrying
+ * a query. This means that if we get really behind, we may end
+ * up doing extra work!
+ */
+
+ query->connects--;
+ fctx = query->fctx;
+
+ if (RESQUERY_CANCELED(query)) {
+ /*
+ * This query was canceled while the connect() was in
+ * progress.
+ */
+ isc_socket_detach(&query->tcpsocket);
+ resquery_destroy(&query);
+ } else {
+ switch (sevent->result) {
+ case ISC_R_SUCCESS:
+
+ /*
+ * Extend the idle timer for TCP. 20 seconds
+ * should be long enough for a TCP connection to be
+ * established, a single DNS request to be sent,
+ * and the response received.
+ */
+ isc_interval_set(&interval, 20, 0);
+ result = fctx_startidletimer(query->fctx, &interval);
+ if (result != ISC_R_SUCCESS) {
+ fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
+ fctx_done(fctx, result);
+ break;
+ }
+ /*
+ * We are connected. Create a dispatcher and
+ * send the query.
+ */
+ attrs = 0;
+ attrs |= DNS_DISPATCHATTR_TCP;
+ attrs |= DNS_DISPATCHATTR_PRIVATE;
+ attrs |= DNS_DISPATCHATTR_CONNECTED;
+ if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==
+ AF_INET)
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ else
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ attrs |= DNS_DISPATCHATTR_MAKEQUERY;
+
+ result = dns_dispatch_createtcp(query->dispatchmgr,
+ query->tcpsocket,
+ query->fctx->res->taskmgr,
+ 4096, 2, 1, 1, 3, attrs,
+ &query->dispatch);
+
+ /*
+ * Regardless of whether dns_dispatch_create()
+ * succeeded or not, we don't need our reference
+ * to the socket anymore.
+ */
+ isc_socket_detach(&query->tcpsocket);
+
+ if (result == ISC_R_SUCCESS)
+ result = resquery_send(query);
+
+ if (result != ISC_R_SUCCESS) {
+ fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
+ fctx_done(fctx, result);
+ }
+ break;
+
+ case ISC_R_NETUNREACH:
+ case ISC_R_HOSTUNREACH:
+ case ISC_R_CONNREFUSED:
+ case ISC_R_NOPERM:
+ case ISC_R_ADDRNOTAVAIL:
+ case ISC_R_CONNECTIONRESET:
+ /*
+ * No route to remote.
+ */
+ isc_socket_detach(&query->tcpsocket);
+ fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
+ retry = ISC_TRUE;
+ break;
+
+ default:
+ isc_socket_detach(&query->tcpsocket);
+ fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
+ break;
+ }
+ }
+
+ isc_event_free(&event);
+
+ if (retry) {
+ /*
+ * Behave as if the idle timer has expired. For TCP
+ * connections this may not actually reflect the latest timer.
+ */
+ fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ result = fctx_stopidletimer(fctx);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result);
+ else
+ fctx_try(fctx, ISC_TRUE);
+ }
+}
+
+static void
+fctx_finddone(isc_task_t *task, isc_event_t *event) {
+ fetchctx_t *fctx;
+ dns_adbfind_t *find;
+ dns_resolver_t *res;
+ isc_boolean_t want_try = ISC_FALSE;
+ isc_boolean_t want_done = ISC_FALSE;
+ isc_boolean_t bucket_empty = ISC_FALSE;
+ unsigned int bucketnum;
+
+ find = event->ev_sender;
+ fctx = event->ev_arg;
+ REQUIRE(VALID_FCTX(fctx));
+ res = fctx->res;
+
+ UNUSED(task);
+
+ FCTXTRACE("finddone");
+
+ INSIST(fctx->pending > 0);
+ fctx->pending--;
+
+ if (ADDRWAIT(fctx)) {
+ /*
+ * The fetch is waiting for a name to be found.
+ */
+ INSIST(!SHUTTINGDOWN(fctx));
+ fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)
+ want_try = ISC_TRUE;
+ else if (fctx->pending == 0) {
+ /*
+ * We've got nothing else to wait for and don't
+ * know the answer. There's nothing to do but
+ * fail the fctx.
+ */
+ want_done = ISC_TRUE;
+ }
+ } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
+ fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
+ bucketnum = fctx->bucketnum;
+ LOCK(&res->buckets[bucketnum].lock);
+ /*
+ * Note that we had to wait until we had the lock before
+ * looking at fctx->references.
+ */
+ if (fctx->references == 0)
+ bucket_empty = fctx_destroy(fctx);
+ UNLOCK(&res->buckets[bucketnum].lock);
+ }
+
+ isc_event_free(&event);
+ dns_adb_destroyfind(&find);
+
+ if (want_try)
+ fctx_try(fctx, ISC_TRUE);
+ else if (want_done)
+ fctx_done(fctx, ISC_R_FAILURE);
+ else if (bucket_empty)
+ empty_bucket(res);
+}
+
+
+static inline isc_boolean_t
+bad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {
+ isc_sockaddr_t *sa;
+
+ for (sa = ISC_LIST_HEAD(fctx->bad);
+ sa != NULL;
+ sa = ISC_LIST_NEXT(sa, link)) {
+ if (isc_sockaddr_equal(sa, address))
+ return (ISC_TRUE);
+ }
+
+ return (ISC_FALSE);
+}
+
+static inline isc_boolean_t
+mark_bad(fetchctx_t *fctx) {
+ dns_adbfind_t *curr;
+ dns_adbaddrinfo_t *addrinfo;
+ isc_boolean_t all_bad = ISC_TRUE;
+
+ /*
+ * Mark all known bad servers, so we don't try to talk to them
+ * again.
+ */
+
+ /*
+ * Mark any bad nameservers.
+ */
+ for (curr = ISC_LIST_HEAD(fctx->finds);
+ curr != NULL;
+ curr = ISC_LIST_NEXT(curr, publink)) {
+ for (addrinfo = ISC_LIST_HEAD(curr->list);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
+ if (bad_server(fctx, &addrinfo->sockaddr))
+ addrinfo->flags |= FCTX_ADDRINFO_MARK;
+ else
+ all_bad = ISC_FALSE;
+ }
+ }
+
+ /*
+ * Mark any bad forwarders.
+ */
+ for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
+ if (bad_server(fctx, &addrinfo->sockaddr))
+ addrinfo->flags |= FCTX_ADDRINFO_MARK;
+ else
+ all_bad = ISC_FALSE;
+ }
+
+ /*
+ * Mark any bad alternates.
+ */
+ for (curr = ISC_LIST_HEAD(fctx->altfinds);
+ curr != NULL;
+ curr = ISC_LIST_NEXT(curr, publink)) {
+ for (addrinfo = ISC_LIST_HEAD(curr->list);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
+ if (bad_server(fctx, &addrinfo->sockaddr))
+ addrinfo->flags |= FCTX_ADDRINFO_MARK;
+ else
+ all_bad = ISC_FALSE;
+ }
+ }
+
+ for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
+ if (bad_server(fctx, &addrinfo->sockaddr))
+ addrinfo->flags |= FCTX_ADDRINFO_MARK;
+ else
+ all_bad = ISC_FALSE;
+ }
+
+ return (all_bad);
+}
+
+static void
+add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ char classbuf[64];
+ char typebuf[64];
+ char code[64];
+ isc_buffer_t b;
+ isc_sockaddr_t *sa;
+ const char *sep1, *sep2;
+ isc_sockaddr_t *address = &addrinfo->sockaddr;
+
+ if (bad_server(fctx, address)) {
+ /*
+ * We already know this server is bad.
+ */
+ return;
+ }
+
+ FCTXTRACE("add_bad");
+
+ sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
+ sizeof(*sa));
+ if (sa == NULL)
+ return;
+ *sa = *address;
+ ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);
+
+ if (reason == DNS_R_LAME) /* already logged */
+ return;
+
+ if (reason == DNS_R_UNEXPECTEDRCODE &&
+ fctx->rmessage->rcode == dns_rcode_servfail &&
+ ISFORWARDER(addrinfo))
+ return;
+
+ if (reason == DNS_R_UNEXPECTEDRCODE) {
+ isc_buffer_init(&b, code, sizeof(code) - 1);
+ dns_rcode_totext(fctx->rmessage->rcode, &b);
+ code[isc_buffer_usedlength(&b)] = '\0';
+ sep1 = "(";
+ sep2 = ") ";
+ } 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 = ") ";
+ } else {
+ code[0] = '\0';
+ sep1 = "";
+ sep2 = "";
+ }
+ dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
+ dns_rdataclass_format(fctx->res->rdclass, classbuf, sizeof(classbuf));
+ 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,
+ 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)
+ */
+static void
+sort_adbfind(fetchctx_t *fctx, 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)) {
+ best = ISC_LIST_HEAD(find->list);
+ curr = ISC_LIST_NEXT(best, publink);
+ while (curr != NULL) {
+ if (curr->srtt < best->srtt)
+ best = curr;
+ curr = ISC_LIST_NEXT(curr, publink);
+ }
+ ISC_LIST_UNLINK(find->list, best, publink);
+ ISC_LIST_APPEND(sorted, best, publink);
+ }
+ find->list = sorted;
+}
+
+/*
+ * Sort a list of finds by server RTT (with random jitter)
+ */
+static void
+sort_finds(fetchctx_t *fctx, 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) */
+ for (curr = ISC_LIST_HEAD(*findlist);
+ curr != NULL;
+ curr = ISC_LIST_NEXT(curr, publink))
+ sort_adbfind(fctx, curr);
+
+ /* Lame N^2 bubble sort. */
+ ISC_LIST_INIT(sorted);
+ while (!ISC_LIST_EMPTY(*findlist)) {
+ best = ISC_LIST_HEAD(*findlist);
+ bestaddrinfo = ISC_LIST_HEAD(best->list);
+ INSIST(bestaddrinfo != NULL);
+ curr = ISC_LIST_NEXT(best, publink);
+ while (curr != NULL) {
+ addrinfo = ISC_LIST_HEAD(curr->list);
+ INSIST(addrinfo != NULL);
+ if (addrinfo->srtt < bestaddrinfo->srtt) {
+ best = curr;
+ bestaddrinfo = addrinfo;
+ }
+ curr = ISC_LIST_NEXT(curr, publink);
+ }
+ ISC_LIST_UNLINK(*findlist, best, publink);
+ ISC_LIST_APPEND(sorted, best, publink);
+ }
+ *findlist = sorted;
+}
+
+static void
+findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,
+ unsigned int options, unsigned int flags, isc_stdtime_t now,
+ isc_boolean_t *need_alternate)
+{
+ dns_adbaddrinfo_t *ai;
+ dns_adbfind_t *find;
+ dns_resolver_t *res;
+ isc_boolean_t unshared;
+ isc_result_t result;
+
+ res = fctx->res;
+ unshared = ISC_TF((fctx->options | DNS_FETCHOPT_UNSHARED) != 0);
+ /*
+ * If this name is a subdomain of the query domain, tell
+ * the ADB to start looking using zone/hint data. This keeps us
+ * from getting stuck if the nameserver is beneath the zone cut
+ * and we don't know its address (e.g. because the A record has
+ * expired).
+ */
+ if (dns_name_issubdomain(name, &fctx->domain))
+ options |= DNS_ADBFIND_STARTATZONE;
+ options |= DNS_ADBFIND_GLUEOK;
+ options |= DNS_ADBFIND_HINTOK;
+
+ /*
+ * See what we know about this address.
+ */
+ find = NULL;
+ result = dns_adb_createfind(fctx->adb,
+ res->buckets[fctx->bucketnum].task,
+ fctx_finddone, fctx, name,
+ &fctx->name, fctx->type,
+ options, now, NULL,
+ res->view->dstport, &find);
+ if (result != ISC_R_SUCCESS) {
+ if (result == DNS_R_ALIAS) {
+ /*
+ * XXXRTH Follow the CNAME/DNAME chain?
+ */
+ dns_adb_destroyfind(&find);
+ }
+ } else if (!ISC_LIST_EMPTY(find->list)) {
+ /*
+ * We have at least some of the addresses for the
+ * name.
+ */
+ INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);
+ if (flags != 0 || port != 0) {
+ for (ai = ISC_LIST_HEAD(find->list);
+ ai != NULL;
+ ai = ISC_LIST_NEXT(ai, publink)) {
+ ai->flags |= flags;
+ if (port != 0)
+ isc_sockaddr_setport(&ai->sockaddr,
+ port);
+ }
+ }
+ if ((flags & FCTX_ADDRINFO_FORWARDER) != 0)
+ ISC_LIST_APPEND(fctx->altfinds, find, publink);
+ else
+ ISC_LIST_APPEND(fctx->finds, find, publink);
+ } else {
+ /*
+ * We don't know any of the addresses for this
+ * name.
+ */
+ if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {
+ /*
+ * We're looking for them and will get an
+ * event about it later.
+ */
+ fctx->pending++;
+ /*
+ * Bootstrap.
+ */
+ if (need_alternate != NULL &&
+ !*need_alternate && unshared &&
+ ((res->dispatchv4 == NULL &&
+ find->result_v6 != DNS_R_NXDOMAIN) ||
+ (res->dispatchv6 == NULL &&
+ find->result_v4 != DNS_R_NXDOMAIN)))
+ *need_alternate = ISC_TRUE;
+ } else {
+ /*
+ * If we know there are no addresses for
+ * the family we are using then try to add
+ * an alternative server.
+ */
+ if (need_alternate != NULL && !*need_alternate &&
+ ((res->dispatchv4 == NULL &&
+ find->result_v6 == DNS_R_NXRRSET) ||
+ (res->dispatchv6 == NULL &&
+ find->result_v4 == DNS_R_NXRRSET)))
+ *need_alternate = ISC_TRUE;
+ dns_adb_destroyfind(&find);
+ }
+ }
+}
+
+static isc_result_t
+fctx_getaddresses(fetchctx_t *fctx) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ dns_resolver_t *res;
+ isc_stdtime_t now;
+ unsigned int stdoptions;
+ isc_sockaddr_t *sa;
+ dns_adbaddrinfo_t *ai;
+ isc_boolean_t all_bad;
+ dns_rdata_ns_t ns;
+ isc_boolean_t need_alternate = ISC_FALSE;
+
+ FCTXTRACE("getaddresses");
+
+ /*
+ * Don't pound on remote servers. (Failsafe!)
+ */
+ fctx->restarts++;
+ if (fctx->restarts > 10) {
+ FCTXTRACE("too many restarts");
+ return (DNS_R_SERVFAIL);
+ }
+
+ res = fctx->res;
+ stdoptions = 0; /* Keep compiler happy. */
+
+ /*
+ * Forwarders.
+ */
+
+ INSIST(ISC_LIST_EMPTY(fctx->forwaddrs));
+ INSIST(ISC_LIST_EMPTY(fctx->altaddrs));
+
+ /*
+ * If this fctx has forwarders, use them; otherwise use any
+ * selective forwarders specified in the view; otherwise use the
+ * resolver's forwarders (if any).
+ */
+ sa = ISC_LIST_HEAD(fctx->forwarders);
+ if (sa == NULL) {
+ dns_forwarders_t *forwarders = NULL;
+ dns_name_t *name = &fctx->name;
+ dns_name_t suffix;
+ unsigned int labels;
+
+ /*
+ * DS records are found in the parent server.
+ * Strip label to get the correct forwarder (if any).
+ */
+ if (fctx->type == dns_rdatatype_ds &&
+ dns_name_countlabels(name) > 1) {
+ dns_name_init(&suffix, NULL);
+ labels = dns_name_countlabels(name);
+ dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
+ name = &suffix;
+ }
+ result = dns_fwdtable_find(fctx->res->view->fwdtable, name,
+ &forwarders);
+ if (result == ISC_R_SUCCESS) {
+ sa = ISC_LIST_HEAD(forwarders->addrs);
+ fctx->fwdpolicy = forwarders->fwdpolicy;
+ }
+ }
+
+ while (sa != NULL) {
+ if ((isc_sockaddr_pf(sa) == AF_INET &&
+ fctx->res->dispatchv4 == NULL) ||
+ (isc_sockaddr_pf(sa) == AF_INET6 &&
+ fctx->res->dispatchv6 == NULL)) {
+ sa = ISC_LIST_NEXT(sa, link);
+ continue;
+ }
+ ai = NULL;
+ result = dns_adb_findaddrinfo(fctx->adb,
+ sa, &ai, 0); /* XXXMLG */
+ if (result == ISC_R_SUCCESS) {
+ dns_adbaddrinfo_t *cur;
+ ai->flags |= FCTX_ADDRINFO_FORWARDER;
+ cur = ISC_LIST_HEAD(fctx->forwaddrs);
+ while (cur != NULL && cur->srtt < ai->srtt)
+ cur = ISC_LIST_NEXT(cur, publink);
+ if (cur != NULL)
+ ISC_LIST_INSERTBEFORE(fctx->forwaddrs, cur,
+ ai, publink);
+ else
+ ISC_LIST_APPEND(fctx->forwaddrs, ai, publink);
+ }
+ sa = ISC_LIST_NEXT(sa, link);
+ }
+
+ /*
+ * If the forwarding policy is "only", we don't need the addresses
+ * of the nameservers.
+ */
+ if (fctx->fwdpolicy == dns_fwdpolicy_only)
+ goto out;
+
+ /*
+ * Normal nameservers.
+ */
+
+ stdoptions = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT;
+ if (fctx->restarts == 1) {
+ /*
+ * To avoid sending out a flood of queries likely to
+ * result in NXRRSET, we suppress fetches for address
+ * families we don't have the first time through,
+ * provided that we have addresses in some family we
+ * can use.
+ *
+ * We don't want to set this option all the time, since
+ * if fctx->restarts > 1, we've clearly been having trouble
+ * with the addresses we had, so getting more could help.
+ */
+ stdoptions |= DNS_ADBFIND_AVOIDFETCHES;
+ }
+ if (res->dispatchv4 != NULL)
+ stdoptions |= DNS_ADBFIND_INET;
+ if (res->dispatchv6 != NULL)
+ stdoptions |= DNS_ADBFIND_INET6;
+ isc_stdtime_get(&now);
+
+ INSIST(ISC_LIST_EMPTY(fctx->finds));
+ INSIST(ISC_LIST_EMPTY(fctx->altfinds));
+
+ for (result = dns_rdataset_first(&fctx->nameservers);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&fctx->nameservers))
+ {
+ dns_rdataset_current(&fctx->nameservers, &rdata);
+ /*
+ * Extract the name from the NS record.
+ */
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ findname(fctx, &ns.name, 0, stdoptions, 0, now,
+ &need_alternate);
+ dns_rdata_reset(&rdata);
+ dns_rdata_freestruct(&ns);
+ }
+ if (result != ISC_R_NOMORE)
+ return (result);
+
+ /*
+ * Do we need to use 6 to 4?
+ */
+ if (need_alternate) {
+ int family;
+ alternate_t *a;
+ family = (res->dispatchv6 != NULL) ? AF_INET6 : AF_INET;
+ for (a = ISC_LIST_HEAD(fctx->res->alternates);
+ a != NULL;
+ a = ISC_LIST_NEXT(a, link)) {
+ if (!a->isaddress) {
+ findname(fctx, &a->_u._n.name, a->_u._n.port,
+ stdoptions, FCTX_ADDRINFO_FORWARDER,
+ now, NULL);
+ continue;
+ }
+ if (isc_sockaddr_pf(&a->_u.addr) != family)
+ continue;
+ ai = NULL;
+ result = dns_adb_findaddrinfo(fctx->adb, &a->_u.addr,
+ &ai, 0);
+ if (result == ISC_R_SUCCESS) {
+ dns_adbaddrinfo_t *cur;
+ ai->flags |= FCTX_ADDRINFO_FORWARDER;
+ cur = ISC_LIST_HEAD(fctx->altaddrs);
+ while (cur != NULL && cur->srtt < ai->srtt)
+ cur = ISC_LIST_NEXT(cur, publink);
+ if (cur != NULL)
+ ISC_LIST_INSERTBEFORE(fctx->altaddrs,
+ cur, ai, publink);
+ else
+ ISC_LIST_APPEND(fctx->altaddrs, ai,
+ publink);
+ }
+ }
+ }
+
+ out:
+ /*
+ * Mark all known bad servers.
+ */
+ all_bad = mark_bad(fctx);
+
+ /*
+ * How are we doing?
+ */
+ if (all_bad) {
+ /*
+ * We've got no addresses.
+ */
+ if (fctx->pending > 0) {
+ /*
+ * We're fetching the addresses, but don't have any
+ * yet. Tell the caller to wait for an answer.
+ */
+ result = DNS_R_WAIT;
+ } else {
+ /*
+ * We've lost completely. We don't know any
+ * addresses, and the ADB has told us it can't get
+ * them.
+ */
+ FCTXTRACE("no addresses");
+ result = ISC_R_FAILURE;
+ }
+ } else {
+ /*
+ * We've found some addresses. We might still be looking
+ * for more addresses.
+ */
+ sort_finds(fctx, &fctx->finds);
+ sort_finds(fctx, &fctx->altfinds);
+ result = ISC_R_SUCCESS;
+ }
+
+ return (result);
+}
+
+static inline void
+possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
+{
+ isc_netaddr_t na;
+ char buf[ISC_NETADDR_FORMATSIZE];
+ isc_sockaddr_t *sa;
+ isc_boolean_t aborted = ISC_FALSE;
+ isc_boolean_t bogus;
+ dns_acl_t *blackhole;
+ isc_netaddr_t ipaddr;
+ dns_peer_t *peer = NULL;
+ dns_resolver_t *res;
+ const char *msg = NULL;
+
+ sa = &addr->sockaddr;
+
+ res = fctx->res;
+ isc_netaddr_fromsockaddr(&ipaddr, sa);
+ blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
+ (void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
+
+ if (blackhole != NULL) {
+ int match;
+
+ if (dns_acl_match(&ipaddr, NULL, blackhole,
+ &res->view->aclenv,
+ &match, NULL) == ISC_R_SUCCESS &&
+ match > 0)
+ aborted = ISC_TRUE;
+ }
+
+ if (peer != NULL &&
+ dns_peer_getbogus(peer, &bogus) == ISC_R_SUCCESS &&
+ bogus)
+ aborted = ISC_TRUE;
+
+ if (aborted) {
+ addr->flags |= FCTX_ADDRINFO_MARK;
+ msg = "ignoring blackholed / bogus server: ";
+ } else if (isc_sockaddr_ismulticast(sa)) {
+ addr->flags |= FCTX_ADDRINFO_MARK;
+ msg = "ignoring multicast address: ";
+ } else if (isc_sockaddr_isexperimental(sa)) {
+ addr->flags |= FCTX_ADDRINFO_MARK;
+ msg = "ignoring experimental address: ";
+ } else if (sa->type.sa.sa_family != AF_INET6) {
+ return;
+ } else if (IN6_IS_ADDR_V4MAPPED(&sa->type.sin6.sin6_addr)) {
+ addr->flags |= FCTX_ADDRINFO_MARK;
+ msg = "ignoring IPv6 mapped IPV4 address: ";
+ } else if (IN6_IS_ADDR_V4COMPAT(&sa->type.sin6.sin6_addr)) {
+ addr->flags |= FCTX_ADDRINFO_MARK;
+ msg = "ignoring IPv6 compatibility IPV4 address: ";
+ } else
+ return;
+
+ if (!isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3)))
+ return;
+
+ isc_netaddr_fromsockaddr(&na, sa);
+ isc_netaddr_format(&na, buf, sizeof(buf));
+ FCTXTRACE2(msg, buf);
+}
+
+static inline dns_adbaddrinfo_t *
+fctx_nextaddress(fetchctx_t *fctx) {
+ dns_adbfind_t *find, *start;
+ dns_adbaddrinfo_t *addrinfo;
+ dns_adbaddrinfo_t *faddrinfo;
+
+ /*
+ * Return the next untried address, if any.
+ */
+
+ /*
+ * Find the first unmarked forwarder (if any).
+ */
+ for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
+ if (!UNMARKED(addrinfo))
+ continue;
+ possibly_mark(fctx, addrinfo);
+ if (UNMARKED(addrinfo)) {
+ addrinfo->flags |= FCTX_ADDRINFO_MARK;
+ fctx->find = NULL;
+ return (addrinfo);
+ }
+ }
+
+ /*
+ * No forwarders. Move to the next find.
+ */
+
+ fctx->attributes |= FCTX_ATTR_TRIEDFIND;
+
+ find = fctx->find;
+ if (find == NULL)
+ find = ISC_LIST_HEAD(fctx->finds);
+ else {
+ find = ISC_LIST_NEXT(find, publink);
+ if (find == NULL)
+ find = ISC_LIST_HEAD(fctx->finds);
+ }
+
+ /*
+ * Find the first unmarked addrinfo.
+ */
+ addrinfo = NULL;
+ if (find != NULL) {
+ start = find;
+ do {
+ for (addrinfo = ISC_LIST_HEAD(find->list);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
+ if (!UNMARKED(addrinfo))
+ continue;
+ possibly_mark(fctx, addrinfo);
+ if (UNMARKED(addrinfo)) {
+ addrinfo->flags |= FCTX_ADDRINFO_MARK;
+ break;
+ }
+ }
+ if (addrinfo != NULL)
+ break;
+ find = ISC_LIST_NEXT(find, publink);
+ if (find == NULL)
+ find = ISC_LIST_HEAD(fctx->finds);
+ } while (find != start);
+ }
+
+ fctx->find = find;
+ if (addrinfo != NULL)
+ return (addrinfo);
+
+ /*
+ * No nameservers left. Try alternates.
+ */
+
+ fctx->attributes |= FCTX_ATTR_TRIEDALT;
+
+ find = fctx->altfind;
+ if (find == NULL)
+ find = ISC_LIST_HEAD(fctx->altfinds);
+ else {
+ find = ISC_LIST_NEXT(find, publink);
+ if (find == NULL)
+ find = ISC_LIST_HEAD(fctx->altfinds);
+ }
+
+ /*
+ * Find the first unmarked addrinfo.
+ */
+ addrinfo = NULL;
+ if (find != NULL) {
+ start = find;
+ do {
+ for (addrinfo = ISC_LIST_HEAD(find->list);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
+ if (!UNMARKED(addrinfo))
+ continue;
+ possibly_mark(fctx, addrinfo);
+ if (UNMARKED(addrinfo)) {
+ addrinfo->flags |= FCTX_ADDRINFO_MARK;
+ break;
+ }
+ }
+ if (addrinfo != NULL)
+ break;
+ find = ISC_LIST_NEXT(find, publink);
+ if (find == NULL)
+ find = ISC_LIST_HEAD(fctx->altfinds);
+ } while (find != start);
+ }
+
+ faddrinfo = addrinfo;
+
+ /*
+ * See if we have a better alternate server by address.
+ */
+
+ for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);
+ addrinfo != NULL;
+ addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {
+ if (!UNMARKED(addrinfo))
+ continue;
+ possibly_mark(fctx, addrinfo);
+ if (UNMARKED(addrinfo) &&
+ (faddrinfo == NULL ||
+ addrinfo->srtt < faddrinfo->srtt)) {
+ if (faddrinfo != NULL)
+ faddrinfo->flags &= ~FCTX_ADDRINFO_MARK;
+ addrinfo->flags |= FCTX_ADDRINFO_MARK;
+ break;
+ }
+ }
+
+ if (addrinfo == NULL) {
+ addrinfo = faddrinfo;
+ fctx->altfind = find;
+ }
+
+ return (addrinfo);
+}
+
+static void
+fctx_try(fetchctx_t *fctx, isc_boolean_t retrying) {
+ isc_result_t result;
+ dns_adbaddrinfo_t *addrinfo;
+
+ FCTXTRACE("try");
+
+ REQUIRE(!ADDRWAIT(fctx));
+
+ addrinfo = fctx_nextaddress(fctx);
+ if (addrinfo == NULL) {
+ /*
+ * We have no more addresses. Start over.
+ */
+ fctx_cancelqueries(fctx, ISC_TRUE);
+ fctx_cleanupfinds(fctx);
+ fctx_cleanupaltfinds(fctx);
+ fctx_cleanupforwaddrs(fctx);
+ fctx_cleanupaltaddrs(fctx);
+ result = fctx_getaddresses(fctx);
+ if (result == DNS_R_WAIT) {
+ /*
+ * Sleep waiting for addresses.
+ */
+ FCTXTRACE("addrwait");
+ fctx->attributes |= FCTX_ATTR_ADDRWAIT;
+ return;
+ } else if (result != ISC_R_SUCCESS) {
+ /*
+ * Something bad happened.
+ */
+ fctx_done(fctx, result);
+ return;
+ }
+
+ addrinfo = fctx_nextaddress(fctx);
+ /*
+ * While we may have addresses from the ADB, they
+ * might be bad ones. In this case, return SERVFAIL.
+ */
+ if (addrinfo == NULL) {
+ fctx_done(fctx, DNS_R_SERVFAIL);
+ return;
+ }
+ }
+
+ result = fctx_query(fctx, addrinfo, fctx->options);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result);
+ else if (retrying)
+ inc_stats(fctx->res, dns_resstatscounter_retry);
+}
+
+static isc_boolean_t
+fctx_destroy(fetchctx_t *fctx) {
+ dns_resolver_t *res;
+ unsigned int bucketnum;
+ isc_sockaddr_t *sa, *next_sa;
+
+ /*
+ * Caller must be holding the bucket lock.
+ */
+
+ REQUIRE(VALID_FCTX(fctx));
+ REQUIRE(fctx->state == fetchstate_done ||
+ fctx->state == fetchstate_init);
+ REQUIRE(ISC_LIST_EMPTY(fctx->events));
+ REQUIRE(ISC_LIST_EMPTY(fctx->queries));
+ REQUIRE(ISC_LIST_EMPTY(fctx->finds));
+ REQUIRE(ISC_LIST_EMPTY(fctx->altfinds));
+ REQUIRE(fctx->pending == 0);
+ REQUIRE(fctx->references == 0);
+ REQUIRE(ISC_LIST_EMPTY(fctx->validators));
+
+ FCTXTRACE("destroy");
+
+ res = fctx->res;
+ bucketnum = fctx->bucketnum;
+
+ ISC_LIST_UNLINK(res->buckets[bucketnum].fctxs, fctx, link);
+
+ /*
+ * Free bad.
+ */
+ for (sa = ISC_LIST_HEAD(fctx->bad);
+ sa != NULL;
+ sa = next_sa) {
+ next_sa = ISC_LIST_NEXT(sa, link);
+ ISC_LIST_UNLINK(fctx->bad, sa, link);
+ isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
+ }
+
+ for (sa = ISC_LIST_HEAD(fctx->edns);
+ sa != NULL;
+ sa = next_sa) {
+ next_sa = ISC_LIST_NEXT(sa, link);
+ ISC_LIST_UNLINK(fctx->edns, sa, link);
+ isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
+ }
+
+ for (sa = ISC_LIST_HEAD(fctx->edns512);
+ sa != NULL;
+ sa = next_sa) {
+ next_sa = ISC_LIST_NEXT(sa, link);
+ ISC_LIST_UNLINK(fctx->edns512, sa, link);
+ isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
+ }
+
+ isc_timer_detach(&fctx->timer);
+ dns_message_destroy(&fctx->rmessage);
+ dns_message_destroy(&fctx->qmessage);
+ if (dns_name_countlabels(&fctx->domain) > 0)
+ dns_name_free(&fctx->domain, res->buckets[bucketnum].mctx);
+ if (dns_rdataset_isassociated(&fctx->nameservers))
+ dns_rdataset_disassociate(&fctx->nameservers);
+ dns_name_free(&fctx->name, res->buckets[bucketnum].mctx);
+ dns_db_detach(&fctx->cache);
+ dns_adb_detach(&fctx->adb);
+ isc_mem_free(res->buckets[bucketnum].mctx, fctx->info);
+ isc_mem_put(res->buckets[bucketnum].mctx, fctx, sizeof(*fctx));
+
+ LOCK(&res->nlock);
+ res->nfctx--;
+ UNLOCK(&res->nlock);
+
+ if (res->buckets[bucketnum].exiting &&
+ ISC_LIST_EMPTY(res->buckets[bucketnum].fctxs))
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+/*
+ * Fetch event handlers.
+ */
+
+static void
+fctx_timeout(isc_task_t *task, isc_event_t *event) {
+ fetchctx_t *fctx = event->ev_arg;
+ isc_timerevent_t *tevent = (isc_timerevent_t *)event;
+ resquery_t *query;
+
+ REQUIRE(VALID_FCTX(fctx));
+
+ UNUSED(task);
+
+ FCTXTRACE("timeout");
+
+ if (event->ev_type == ISC_TIMEREVENT_LIFE) {
+ fctx->reason = NULL;
+ fctx_done(fctx, ISC_R_TIMEDOUT);
+ } else {
+ isc_result_t result;
+
+ fctx->timeouts++;
+ /*
+ * We could cancel the running queries here, or we could let
+ * them keep going. Since we normally use separate sockets for
+ * different queries, we adopt the former approach to reduce
+ * the number of open sockets: cancel the oldest query if it
+ * expired after the query had started (this is usually the
+ * case but is not always so, depending on the task schedule
+ * timing).
+ */
+ query = ISC_LIST_HEAD(fctx->queries);
+ if (query != NULL &&
+ isc_time_compare(&tevent->due, &query->start) >= 0) {
+ fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
+ }
+ fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+ /*
+ * Our timer has triggered. Reestablish the fctx lifetime
+ * timer.
+ */
+ result = fctx_starttimer(fctx);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result);
+ else
+ /*
+ * Keep trying.
+ */
+ fctx_try(fctx, ISC_TRUE);
+ }
+
+ isc_event_free(&event);
+}
+
+static void
+fctx_shutdown(fetchctx_t *fctx) {
+ isc_event_t *cevent;
+
+ /*
+ * Start the shutdown process for fctx, if it isn't already underway.
+ */
+
+ FCTXTRACE("shutdown");
+
+ /*
+ * The caller must be holding the appropriate bucket lock.
+ */
+
+ if (fctx->want_shutdown)
+ return;
+
+ fctx->want_shutdown = ISC_TRUE;
+
+ /*
+ * Unless we're still initializing (in which case the
+ * control event is still outstanding), we need to post
+ * the control event to tell the fetch we want it to
+ * exit.
+ */
+ if (fctx->state != fetchstate_init) {
+ cevent = &fctx->control_event;
+ isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
+ &cevent);
+ }
+}
+
+static void
+fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
+ fetchctx_t *fctx = event->ev_arg;
+ isc_boolean_t bucket_empty = ISC_FALSE;
+ dns_resolver_t *res;
+ unsigned int bucketnum;
+ dns_validator_t *validator;
+
+ REQUIRE(VALID_FCTX(fctx));
+
+ UNUSED(task);
+
+ res = fctx->res;
+ bucketnum = fctx->bucketnum;
+
+ FCTXTRACE("doshutdown");
+
+ /*
+ * An fctx that is shutting down is no longer in ADDRWAIT mode.
+ */
+ fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
+
+ /*
+ * Cancel all pending validators. Note that this must be done
+ * without the bucket lock held, since that could cause deadlock.
+ */
+ validator = ISC_LIST_HEAD(fctx->validators);
+ while (validator != NULL) {
+ dns_validator_cancel(validator);
+ validator = ISC_LIST_NEXT(validator, link);
+ }
+
+ if (fctx->nsfetch != NULL)
+ dns_resolver_cancelfetch(fctx->nsfetch);
+
+ /*
+ * Shut down anything that is still running on behalf of this
+ * fetch. To avoid deadlock with the ADB, we must do this
+ * before we lock the bucket lock.
+ */
+ fctx_stopeverything(fctx, ISC_FALSE);
+
+ LOCK(&res->buckets[bucketnum].lock);
+
+ fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
+
+ INSIST(fctx->state == fetchstate_active ||
+ fctx->state == fetchstate_done);
+ INSIST(fctx->want_shutdown);
+
+ if (fctx->state != fetchstate_done) {
+ fctx->state = fetchstate_done;
+ fctx_sendevents(fctx, ISC_R_CANCELED);
+ }
+
+ if (fctx->references == 0 && fctx->pending == 0 &&
+ fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators))
+ bucket_empty = fctx_destroy(fctx);
+
+ UNLOCK(&res->buckets[bucketnum].lock);
+
+ if (bucket_empty)
+ empty_bucket(res);
+}
+
+static void
+fctx_start(isc_task_t *task, isc_event_t *event) {
+ fetchctx_t *fctx = event->ev_arg;
+ isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;
+ dns_resolver_t *res;
+ unsigned int bucketnum;
+
+ REQUIRE(VALID_FCTX(fctx));
+
+ UNUSED(task);
+
+ res = fctx->res;
+ bucketnum = fctx->bucketnum;
+
+ FCTXTRACE("start");
+
+ LOCK(&res->buckets[bucketnum].lock);
+
+ INSIST(fctx->state == fetchstate_init);
+ if (fctx->want_shutdown) {
+ /*
+ * We haven't started this fctx yet, and we've been requested
+ * to shut it down.
+ */
+ fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;
+ fctx->state = fetchstate_done;
+ fctx_sendevents(fctx, ISC_R_CANCELED);
+ /*
+ * Since we haven't started, we INSIST that we have no
+ * pending ADB finds and no pending validations.
+ */
+ INSIST(fctx->pending == 0);
+ INSIST(fctx->nqueries == 0);
+ INSIST(ISC_LIST_EMPTY(fctx->validators));
+ if (fctx->references == 0) {
+ /*
+ * It's now safe to destroy this fctx.
+ */
+ bucket_empty = fctx_destroy(fctx);
+ }
+ done = ISC_TRUE;
+ } else {
+ /*
+ * Normal fctx startup.
+ */
+ fctx->state = fetchstate_active;
+ /*
+ * Reset the control event for later use in shutting down
+ * the fctx.
+ */
+ ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
+ DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,
+ NULL, NULL, NULL);
+ }
+
+ UNLOCK(&res->buckets[bucketnum].lock);
+
+ if (!done) {
+ isc_result_t result;
+
+ /*
+ * All is well. Start working on the fetch.
+ */
+ result = fctx_starttimer(fctx);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result);
+ else
+ fctx_try(fctx, ISC_FALSE);
+ } else if (bucket_empty)
+ empty_bucket(res);
+}
+
+/*
+ * Fetch Creation, Joining, and Cancelation.
+ */
+
+static inline isc_result_t
+fctx_join(fetchctx_t *fctx, isc_task_t *task, isc_sockaddr_t *client,
+ dns_messageid_t id, isc_taskaction_t action, void *arg,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_fetch_t *fetch)
+{
+ isc_task_t *clone;
+ dns_fetchevent_t *event;
+
+ FCTXTRACE("join");
+
+ /*
+ * We store the task we're going to send this event to in the
+ * sender field. We'll make the fetch the sender when we actually
+ * send the event.
+ */
+ clone = NULL;
+ isc_task_attach(task, &clone);
+ event = (dns_fetchevent_t *)
+ isc_event_allocate(fctx->res->mctx, clone, DNS_EVENT_FETCHDONE,
+ action, arg, sizeof(*event));
+ if (event == NULL) {
+ isc_task_detach(&clone);
+ return (ISC_R_NOMEMORY);
+ }
+ event->result = DNS_R_SERVFAIL;
+ event->qtype = fctx->type;
+ event->db = NULL;
+ event->node = NULL;
+ event->rdataset = rdataset;
+ event->sigrdataset = sigrdataset;
+ event->fetch = fetch;
+ event->client = client;
+ event->id = id;
+ dns_fixedname_init(&event->foundname);
+
+ /*
+ * Make sure that we can store the sigrdataset in the
+ * first event if it is needed by any of the events.
+ */
+ if (event->sigrdataset != NULL)
+ ISC_LIST_PREPEND(fctx->events, event, ev_link);
+ else
+ ISC_LIST_APPEND(fctx->events, event, ev_link);
+ fctx->references++;
+
+ fetch->magic = DNS_FETCH_MAGIC;
+ fetch->private = fctx;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
+ dns_name_t *domain, dns_rdataset_t *nameservers,
+ unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp)
+{
+ fetchctx_t *fctx;
+ isc_result_t result;
+ isc_result_t iresult;
+ isc_interval_t interval;
+ dns_fixedname_t fixed;
+ unsigned int findoptions = 0;
+ char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ dns_name_t suffix;
+
+ /*
+ * Caller must be holding the lock for bucket number 'bucketnum'.
+ */
+ REQUIRE(fctxp != NULL && *fctxp == NULL);
+
+ fctx = isc_mem_get(res->buckets[bucketnum].mctx, sizeof(*fctx));
+ if (fctx == NULL)
+ return (ISC_R_NOMEMORY);
+ dns_name_format(name, buf, sizeof(buf));
+ dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+ strcat(buf, "/"); /* checked */
+ strcat(buf, typebuf); /* checked */
+ fctx->info = isc_mem_strdup(res->buckets[bucketnum].mctx, buf);
+ if (fctx->info == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_fetch;
+ }
+ FCTXTRACE("create");
+ dns_name_init(&fctx->name, NULL);
+ result = dns_name_dup(name, res->buckets[bucketnum].mctx, &fctx->name);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_info;
+ dns_name_init(&fctx->domain, NULL);
+ dns_rdataset_init(&fctx->nameservers);
+
+ fctx->type = type;
+ fctx->options = options;
+ /*
+ * Note! We do not attach to the task. We are relying on the
+ * resolver to ensure that this task doesn't go away while we are
+ * using it.
+ */
+ fctx->res = res;
+ fctx->references = 0;
+ fctx->bucketnum = bucketnum;
+ fctx->state = fetchstate_init;
+ fctx->want_shutdown = ISC_FALSE;
+ fctx->cloned = ISC_FALSE;
+ ISC_LIST_INIT(fctx->queries);
+ ISC_LIST_INIT(fctx->finds);
+ ISC_LIST_INIT(fctx->altfinds);
+ ISC_LIST_INIT(fctx->forwaddrs);
+ ISC_LIST_INIT(fctx->altaddrs);
+ ISC_LIST_INIT(fctx->forwarders);
+ fctx->fwdpolicy = dns_fwdpolicy_none;
+ ISC_LIST_INIT(fctx->bad);
+ ISC_LIST_INIT(fctx->edns);
+ ISC_LIST_INIT(fctx->edns512);
+ ISC_LIST_INIT(fctx->validators);
+ fctx->validator = NULL;
+ fctx->find = NULL;
+ fctx->altfind = NULL;
+ fctx->pending = 0;
+ fctx->restarts = 0;
+ fctx->timeouts = 0;
+ fctx->attributes = 0;
+ fctx->spilled = ISC_FALSE;
+ fctx->nqueries = 0;
+ fctx->reason = NULL;
+ fctx->rand_buf = 0;
+ fctx->rand_bits = 0;
+
+ dns_name_init(&fctx->nsname, NULL);
+ fctx->nsfetch = NULL;
+ dns_rdataset_init(&fctx->nsrrset);
+
+ if (domain == NULL) {
+ dns_forwarders_t *forwarders = NULL;
+ unsigned int labels;
+
+ /*
+ * DS records are found in the parent server.
+ * Strip label to get the correct forwarder (if any).
+ */
+ if (fctx->type == dns_rdatatype_ds &&
+ dns_name_countlabels(name) > 1) {
+ dns_name_init(&suffix, NULL);
+ labels = dns_name_countlabels(name);
+ dns_name_getlabelsequence(name, 1, labels - 1, &suffix);
+ name = &suffix;
+ }
+ dns_fixedname_init(&fixed);
+ domain = dns_fixedname_name(&fixed);
+ result = dns_fwdtable_find2(fctx->res->view->fwdtable, name,
+ domain, &forwarders);
+ if (result == ISC_R_SUCCESS)
+ fctx->fwdpolicy = forwarders->fwdpolicy;
+
+ if (fctx->fwdpolicy != dns_fwdpolicy_only) {
+ /*
+ * The caller didn't supply a query domain and
+ * nameservers, and we're not in forward-only mode,
+ * so find the best nameservers to use.
+ */
+ if (dns_rdatatype_atparent(type))
+ findoptions |= DNS_DBFIND_NOEXACT;
+ result = dns_view_findzonecut(res->view, name, domain,
+ 0, findoptions, ISC_TRUE,
+ &fctx->nameservers,
+ NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_name;
+ result = dns_name_dup(domain,
+ res->buckets[bucketnum].mctx,
+ &fctx->domain);
+ if (result != ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&fctx->nameservers);
+ goto cleanup_name;
+ }
+ } else {
+ /*
+ * We're in forward-only mode. Set the query domain.
+ */
+ result = dns_name_dup(domain,
+ res->buckets[bucketnum].mctx,
+ &fctx->domain);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_name;
+ }
+ } else {
+ result = dns_name_dup(domain,
+ res->buckets[bucketnum].mctx,
+ &fctx->domain);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_name;
+ dns_rdataset_clone(nameservers, &fctx->nameservers);
+ }
+
+ INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
+
+ fctx->qmessage = NULL;
+ result = dns_message_create(res->buckets[bucketnum].mctx,
+ DNS_MESSAGE_INTENTRENDER,
+ &fctx->qmessage);
+
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_domain;
+
+ fctx->rmessage = NULL;
+ result = dns_message_create(res->buckets[bucketnum].mctx,
+ DNS_MESSAGE_INTENTPARSE,
+ &fctx->rmessage);
+
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_qmessage;
+
+ /*
+ * Compute an expiration time for the entire fetch.
+ */
+ isc_interval_set(&interval, 30, 0); /* XXXRTH constant */
+ iresult = isc_time_nowplusinterval(&fctx->expires, &interval);
+ if (iresult != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_time_nowplusinterval: %s",
+ isc_result_totext(iresult));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup_rmessage;
+ }
+
+ /*
+ * Default retry interval initialization. We set the interval now
+ * mostly so it won't be uninitialized. It will be set to the
+ * correct value before a query is issued.
+ */
+ isc_interval_set(&fctx->interval, 2, 0);
+
+ /*
+ * Create an inactive timer. It will be made active when the fetch
+ * is actually started.
+ */
+ fctx->timer = NULL;
+ iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,
+ NULL, NULL,
+ res->buckets[bucketnum].task, fctx_timeout,
+ fctx, &fctx->timer);
+ if (iresult != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_timer_create: %s",
+ isc_result_totext(iresult));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup_rmessage;
+ }
+
+ /*
+ * Attach to the view's cache and adb.
+ */
+ fctx->cache = NULL;
+ dns_db_attach(res->view->cachedb, &fctx->cache);
+ fctx->adb = NULL;
+ dns_adb_attach(res->view->adb, &fctx->adb);
+
+ ISC_LIST_INIT(fctx->events);
+ ISC_LINK_INIT(fctx, link);
+ fctx->magic = FCTX_MAGIC;
+
+ ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);
+
+ LOCK(&res->nlock);
+ res->nfctx++;
+ UNLOCK(&res->nlock);
+
+ *fctxp = fctx;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_rmessage:
+ dns_message_destroy(&fctx->rmessage);
+
+ cleanup_qmessage:
+ dns_message_destroy(&fctx->qmessage);
+
+ cleanup_domain:
+ if (dns_name_countlabels(&fctx->domain) > 0)
+ dns_name_free(&fctx->domain, res->buckets[bucketnum].mctx);
+ if (dns_rdataset_isassociated(&fctx->nameservers))
+ dns_rdataset_disassociate(&fctx->nameservers);
+
+ cleanup_name:
+ dns_name_free(&fctx->name, res->buckets[bucketnum].mctx);
+
+ cleanup_info:
+ isc_mem_free(res->buckets[bucketnum].mctx, fctx->info);
+
+ cleanup_fetch:
+ isc_mem_put(res->buckets[bucketnum].mctx, fctx, sizeof(*fctx));
+
+ return (result);
+}
+
+/*
+ * Handle Responses
+ */
+static inline isc_boolean_t
+is_lame(fetchctx_t *fctx) {
+ dns_message_t *message = fctx->rmessage;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+
+ if (message->rcode != dns_rcode_noerror &&
+ message->rcode != dns_rcode_nxdomain)
+ return (ISC_FALSE);
+
+ if (message->counts[DNS_SECTION_ANSWER] != 0)
+ return (ISC_FALSE);
+
+ if (message->counts[DNS_SECTION_AUTHORITY] == 0)
+ return (ISC_FALSE);
+
+ result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ dns_namereln_t namereln;
+ int order;
+ unsigned int labels;
+ if (rdataset->type != dns_rdatatype_ns)
+ continue;
+ namereln = dns_name_fullcompare(name, &fctx->domain,
+ &order, &labels);
+ if (namereln == dns_namereln_equal &&
+ (message->flags & DNS_MESSAGEFLAG_AA) != 0)
+ return (ISC_FALSE);
+ if (namereln == dns_namereln_subdomain)
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+ }
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
+ }
+
+ return (ISC_FALSE);
+}
+
+static inline void
+log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char domainbuf[DNS_NAME_FORMATSIZE];
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+
+ dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
+ dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
+ isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
+ "lame server resolving '%s' (in '%s'?): %s",
+ namebuf, domainbuf, addrbuf);
+}
+
+static inline isc_result_t
+same_question(fetchctx_t *fctx) {
+ isc_result_t result;
+ dns_message_t *message = fctx->rmessage;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+
+ /*
+ * Caller must be holding the fctx lock.
+ */
+
+ /*
+ * XXXRTH Currently we support only one question.
+ */
+ if (message->counts[DNS_SECTION_QUESTION] != 1)
+ return (DNS_R_FORMERR);
+
+ result = dns_message_firstname(message, DNS_SECTION_QUESTION);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_QUESTION, &name);
+ 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))
+ return (DNS_R_FORMERR);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+clone_results(fetchctx_t *fctx) {
+ dns_fetchevent_t *event, *hevent;
+ isc_result_t result;
+ dns_name_t *name, *hname;
+
+ FCTXTRACE("clone_results");
+
+ /*
+ * Set up any other events to have the same data as the first
+ * event.
+ *
+ * Caller must be holding the appropriate lock.
+ */
+
+ fctx->cloned = ISC_TRUE;
+ hevent = ISC_LIST_HEAD(fctx->events);
+ if (hevent == NULL)
+ return;
+ hname = dns_fixedname_name(&hevent->foundname);
+ for (event = ISC_LIST_NEXT(hevent, ev_link);
+ event != NULL;
+ event = ISC_LIST_NEXT(event, ev_link)) {
+ name = dns_fixedname_name(&event->foundname);
+ result = dns_name_copy(hname, name, NULL);
+ if (result != ISC_R_SUCCESS)
+ event->result = result;
+ else
+ event->result = hevent->result;
+ dns_db_attach(hevent->db, &event->db);
+ dns_db_attachnode(hevent->db, hevent->node, &event->node);
+ INSIST(hevent->rdataset != NULL);
+ INSIST(event->rdataset != NULL);
+ if (dns_rdataset_isassociated(hevent->rdataset))
+ dns_rdataset_clone(hevent->rdataset, event->rdataset);
+ INSIST(! (hevent->sigrdataset == NULL &&
+ event->sigrdataset != NULL));
+ if (hevent->sigrdataset != NULL &&
+ dns_rdataset_isassociated(hevent->sigrdataset) &&
+ event->sigrdataset != NULL)
+ dns_rdataset_clone(hevent->sigrdataset,
+ event->sigrdataset);
+ }
+}
+
+#define CACHE(r) (((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)
+#define ANSWER(r) (((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)
+#define ANSWERSIG(r) (((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)
+#define EXTERNAL(r) (((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)
+#define CHAINING(r) (((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)
+#define CHASE(r) (((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)
+#define CHECKNAMES(r) (((r)->attributes & DNS_RDATASETATTR_CHECKNAMES) != 0)
+
+
+/*
+ * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
+ * no references and is no longer waiting for any events). If this
+ * was the last fctx in the resolver, destroy the resolver.
+ *
+ * Requires:
+ * '*fctx' is shutting down.
+ */
+static void
+maybe_destroy(fetchctx_t *fctx) {
+ unsigned int bucketnum;
+ isc_boolean_t bucket_empty = ISC_FALSE;
+ dns_resolver_t *res = fctx->res;
+ dns_validator_t *validator, *next_validator;
+
+ REQUIRE(SHUTTINGDOWN(fctx));
+
+ if (fctx->pending != 0 || fctx->nqueries != 0)
+ return;
+
+ for (validator = ISC_LIST_HEAD(fctx->validators);
+ validator != NULL; validator = next_validator) {
+ next_validator = ISC_LIST_NEXT(validator, link);
+ dns_validator_cancel(validator);
+ /*
+ * If this is a active validator wait for the cancel
+ * to complete before calling dns_validator_destroy().
+ */
+ if (validator == fctx->validator)
+ continue;
+ ISC_LIST_UNLINK(fctx->validators, validator, link);
+ dns_validator_destroy(&validator);
+ }
+
+ bucketnum = fctx->bucketnum;
+ LOCK(&res->buckets[bucketnum].lock);
+ if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators))
+ bucket_empty = fctx_destroy(fctx);
+ UNLOCK(&res->buckets[bucketnum].lock);
+
+ if (bucket_empty)
+ empty_bucket(res);
+}
+
+/*
+ * The validator has finished.
+ */
+static void
+validated(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t eresult = ISC_R_SUCCESS;
+ isc_stdtime_t now;
+ fetchctx_t *fctx;
+ dns_validatorevent_t *vevent;
+ dns_fetchevent_t *hevent;
+ dns_rdataset_t *ardataset = NULL;
+ dns_rdataset_t *asigrdataset = NULL;
+ dns_dbnode_t *node = NULL;
+ isc_boolean_t negative;
+ isc_boolean_t chaining;
+ isc_boolean_t sentresponse;
+ isc_uint32_t ttl;
+ dns_dbnode_t *nsnode = NULL;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ dns_valarg_t *valarg;
+ dns_adbaddrinfo_t *addrinfo;
+
+ UNUSED(task); /* for now */
+
+ REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
+ valarg = event->ev_arg;
+ fctx = valarg->fctx;
+ addrinfo = valarg->addrinfo;
+ REQUIRE(VALID_FCTX(fctx));
+ REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
+
+ vevent = (dns_validatorevent_t *)event;
+
+ FCTXTRACE("received validation completion event");
+
+ ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
+ fctx->validator = NULL;
+
+ /*
+ * Destroy the validator early so that we can
+ * destroy the fctx if necessary.
+ */
+ dns_validator_destroy(&vevent->validator);
+ isc_mem_put(fctx->res->buckets[fctx->bucketnum].mctx,
+ valarg, sizeof(*valarg));
+
+ negative = ISC_TF(vevent->rdataset == NULL);
+
+ sentresponse = ISC_TF((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0);
+
+ /*
+ * If shutting down, ignore the results. Check to see if we're
+ * done waiting for validator completions and ADB pending events; if
+ * so, destroy the fctx.
+ */
+ if (SHUTTINGDOWN(fctx) && !sentresponse) {
+ maybe_destroy(fctx); /* Locks bucket. */
+ goto cleanup_event;
+ }
+
+ LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+
+ /*
+ * If chaining, we need to make sure that the right result code is
+ * returned, and that the rdatasets are bound.
+ */
+ if (vevent->result == ISC_R_SUCCESS &&
+ !negative &&
+ vevent->rdataset != NULL &&
+ CHAINING(vevent->rdataset))
+ {
+ if (vevent->rdataset->type == dns_rdatatype_cname)
+ eresult = DNS_R_CNAME;
+ else {
+ INSIST(vevent->rdataset->type == dns_rdatatype_dname);
+ eresult = DNS_R_DNAME;
+ }
+ chaining = ISC_TRUE;
+ } else
+ chaining = ISC_FALSE;
+
+ /*
+ * Either we're not shutting down, or we are shutting down but want
+ * to cache the result anyway (if this was a validation started by
+ * a query with cd set)
+ */
+
+ hevent = ISC_LIST_HEAD(fctx->events);
+ if (hevent != NULL) {
+ if (!negative && !chaining &&
+ (fctx->type == dns_rdatatype_any ||
+ fctx->type == dns_rdatatype_rrsig ||
+ fctx->type == dns_rdatatype_sig)) {
+ /*
+ * Don't bind rdatasets; the caller
+ * will iterate the node.
+ */
+ } else {
+ ardataset = hevent->rdataset;
+ asigrdataset = hevent->sigrdataset;
+ }
+ }
+
+ if (vevent->result != ISC_R_SUCCESS) {
+ FCTXTRACE("validation failed");
+ inc_stats(fctx->res, dns_resstatscounter_valfail);
+ result = ISC_R_NOTFOUND;
+ if (vevent->rdataset != NULL)
+ result = dns_db_findnode(fctx->cache, vevent->name,
+ ISC_TRUE, &node);
+ if (result == ISC_R_SUCCESS)
+ (void)dns_db_deleterdataset(fctx->cache, node, NULL,
+ vevent->type, 0);
+ if (result == ISC_R_SUCCESS && vevent->sigrdataset != NULL)
+ (void)dns_db_deleterdataset(fctx->cache, node, NULL,
+ dns_rdatatype_rrsig,
+ vevent->type);
+ if (result == ISC_R_SUCCESS)
+ dns_db_detachnode(fctx->cache, &node);
+ result = vevent->result;
+ add_bad(fctx, addrinfo, result);
+ isc_event_free(&event);
+ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+ INSIST(fctx->validator == NULL);
+ fctx->validator = ISC_LIST_HEAD(fctx->validators);
+ if (fctx->validator != NULL) {
+ dns_validator_send(fctx->validator);
+ } else if (sentresponse)
+ fctx_done(fctx, result); /* Locks bucket. */
+ else
+ fctx_try(fctx, ISC_TRUE); /* Locks bucket. */
+ return;
+ }
+
+ isc_stdtime_get(&now);
+
+ if (negative) {
+ dns_rdatatype_t covers;
+ FCTXTRACE("nonexistence validation OK");
+
+ inc_stats(fctx->res, dns_resstatscounter_valnegsuccess);
+
+ if (fctx->rmessage->rcode == dns_rcode_nxdomain)
+ covers = dns_rdatatype_any;
+ else
+ covers = fctx->type;
+
+ result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE,
+ &node);
+ if (result != ISC_R_SUCCESS)
+ goto noanswer_response;
+
+ /*
+ * If we are asking for a SOA record set the cache time
+ * to zero to facilitate locating the containing zone of
+ * a arbitary zone.
+ */
+ ttl = fctx->res->view->maxncachettl;
+ if (fctx->type == dns_rdatatype_soa &&
+ covers == dns_rdatatype_any &&
+ fctx->res->zero_no_soa_ttl)
+ ttl = 0;
+
+ result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
+ covers, now, ttl, vevent->optout,
+ ardataset, &eresult);
+ if (result != ISC_R_SUCCESS)
+ goto noanswer_response;
+ goto answer_response;
+ } else
+ inc_stats(fctx->res, dns_resstatscounter_valsuccess);
+
+ FCTXTRACE("validation OK");
+
+ if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
+
+ result = dns_rdataset_addnoqname(vevent->rdataset,
+ vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ INSIST(vevent->sigrdataset != NULL);
+ vevent->sigrdataset->ttl = vevent->rdataset->ttl;
+ if (vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER] != NULL) {
+ result = dns_rdataset_addclosest(vevent->rdataset,
+ vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
+ }
+
+ /*
+ * The data was already cached as pending data.
+ * Re-cache it as secure and bind the cached
+ * rdatasets to the first event on the fetch
+ * event list.
+ */
+ result = dns_db_findnode(fctx->cache, vevent->name, ISC_TRUE, &node);
+ if (result != ISC_R_SUCCESS)
+ goto noanswer_response;
+
+ result = dns_db_addrdataset(fctx->cache, node, NULL, now,
+ vevent->rdataset, 0, ardataset);
+ if (result != ISC_R_SUCCESS &&
+ result != DNS_R_UNCHANGED)
+ goto noanswer_response;
+ if (ardataset != NULL && ardataset->type == 0) {
+ if (NXDOMAIN(ardataset))
+ eresult = DNS_R_NCACHENXDOMAIN;
+ else
+ eresult = DNS_R_NCACHENXRRSET;
+ } else if (vevent->sigrdataset != NULL) {
+ result = dns_db_addrdataset(fctx->cache, node, NULL, now,
+ vevent->sigrdataset, 0,
+ asigrdataset);
+ if (result != ISC_R_SUCCESS &&
+ result != DNS_R_UNCHANGED)
+ goto noanswer_response;
+ }
+
+ if (sentresponse) {
+ /*
+ * If we only deferred the destroy because we wanted to cache
+ * the data, destroy now.
+ */
+ dns_db_detachnode(fctx->cache, &node);
+ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+ if (SHUTTINGDOWN(fctx))
+ maybe_destroy(fctx); /* Locks bucket. */
+ goto cleanup_event;
+ }
+
+ if (!ISC_LIST_EMPTY(fctx->validators)) {
+ INSIST(!negative);
+ INSIST(fctx->type == dns_rdatatype_any ||
+ fctx->type == dns_rdatatype_rrsig ||
+ fctx->type == dns_rdatatype_sig);
+ /*
+ * Don't send a response yet - we have
+ * more rdatasets that still need to
+ * be validated.
+ */
+ dns_db_detachnode(fctx->cache, &node);
+ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+ dns_validator_send(ISC_LIST_HEAD(fctx->validators));
+ goto cleanup_event;
+ }
+
+ answer_response:
+ /*
+ * Cache any NS/NSEC records that happened to be validated.
+ */
+ result = dns_message_firstname(fctx->rmessage, DNS_SECTION_AUTHORITY);
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(fctx->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_ns &&
+ rdataset->type != dns_rdatatype_nsec) ||
+ rdataset->trust != dns_trust_secure)
+ continue;
+ for (sigrdataset = ISC_LIST_HEAD(name->list);
+ sigrdataset != NULL;
+ sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
+ if (sigrdataset->type != dns_rdatatype_rrsig ||
+ sigrdataset->covers != rdataset->type)
+ continue;
+ break;
+ }
+ if (sigrdataset == NULL ||
+ sigrdataset->trust != dns_trust_secure)
+ continue;
+ result = dns_db_findnode(fctx->cache, name, ISC_TRUE,
+ &nsnode);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ result = dns_db_addrdataset(fctx->cache, nsnode, NULL,
+ now, rdataset, 0, NULL);
+ if (result == ISC_R_SUCCESS)
+ result = dns_db_addrdataset(fctx->cache, nsnode,
+ NULL, now,
+ sigrdataset, 0,
+ NULL);
+ dns_db_detachnode(fctx->cache, &nsnode);
+ }
+ result = dns_message_nextname(fctx->rmessage,
+ DNS_SECTION_AUTHORITY);
+ }
+
+ result = ISC_R_SUCCESS;
+
+ /*
+ * Respond with an answer, positive or negative,
+ * as opposed to an error. 'node' must be non-NULL.
+ */
+
+ fctx->attributes |= FCTX_ATTR_HAVEANSWER;
+
+ if (hevent != NULL) {
+ hevent->result = eresult;
+ RUNTIME_CHECK(dns_name_copy(vevent->name,
+ dns_fixedname_name(&hevent->foundname), NULL)
+ == ISC_R_SUCCESS);
+ dns_db_attach(fctx->cache, &hevent->db);
+ dns_db_transfernode(fctx->cache, &node, &hevent->node);
+ clone_results(fctx);
+ }
+
+ noanswer_response:
+ if (node != NULL)
+ dns_db_detachnode(fctx->cache, &node);
+
+ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+
+ fctx_done(fctx, result); /* Locks bucket. */
+
+ cleanup_event:
+ INSIST(node == NULL);
+ isc_event_free(&event);
+}
+
+static inline isc_result_t
+cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
+ isc_stdtime_t now)
+{
+ dns_rdataset_t *rdataset, *sigrdataset;
+ dns_rdataset_t *addedrdataset, *ardataset, *asigrdataset;
+ dns_rdataset_t *valrdataset = NULL, *valsigrdataset = NULL;
+ dns_dbnode_t *node, **anodep;
+ dns_db_t **adbp;
+ dns_name_t *aname;
+ dns_resolver_t *res;
+ isc_boolean_t need_validation, secure_domain, have_answer;
+ isc_result_t result, eresult;
+ dns_fetchevent_t *event;
+ unsigned int options;
+ isc_task_t *task;
+ isc_boolean_t fail;
+ unsigned int valoptions = 0;
+
+ /*
+ * The appropriate bucket lock must be held.
+ */
+
+ res = fctx->res;
+ need_validation = ISC_FALSE;
+ secure_domain = ISC_FALSE;
+ have_answer = ISC_FALSE;
+ eresult = ISC_R_SUCCESS;
+ task = res->buckets[fctx->bucketnum].task;
+
+ /*
+ * Is DNSSEC validation required for this name?
+ */
+ if (res->view->enablevalidation) {
+ result = dns_keytable_issecuredomain(res->view->secroots, name,
+ &secure_domain);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (!secure_domain && res->view->dlv != NULL) {
+ valoptions = DNS_VALIDATOR_DLV;
+ secure_domain = ISC_TRUE;
+ }
+ }
+
+ if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
+ need_validation = ISC_FALSE;
+ else
+ need_validation = secure_domain;
+
+ adbp = NULL;
+ aname = NULL;
+ anodep = NULL;
+ ardataset = NULL;
+ asigrdataset = NULL;
+ event = NULL;
+ if ((name->attributes & DNS_NAMEATTR_ANSWER) != 0 &&
+ !need_validation) {
+ have_answer = ISC_TRUE;
+ event = ISC_LIST_HEAD(fctx->events);
+ if (event != NULL) {
+ adbp = &event->db;
+ aname = dns_fixedname_name(&event->foundname);
+ result = dns_name_copy(name, aname, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ anodep = &event->node;
+ /*
+ * If this is an ANY, SIG or RRSIG query, we're not
+ * going to return any rdatasets, unless we encountered
+ * a CNAME or DNAME as "the answer". In this case,
+ * we're going to return DNS_R_CNAME or DNS_R_DNAME
+ * and we must set up the rdatasets.
+ */
+ if ((fctx->type != dns_rdatatype_any &&
+ fctx->type != dns_rdatatype_rrsig &&
+ fctx->type != dns_rdatatype_sig) ||
+ (name->attributes & DNS_NAMEATTR_CHAINING) != 0) {
+ ardataset = event->rdataset;
+ asigrdataset = event->sigrdataset;
+ }
+ }
+ }
+
+ /*
+ * Find or create the cache node.
+ */
+ node = NULL;
+ result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Cache or validate each cacheable rdataset.
+ */
+ fail = ISC_TF((fctx->res->options & DNS_RESOLVER_CHECKNAMESFAIL) != 0);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (!CACHE(rdataset))
+ continue;
+ if (CHECKNAMES(rdataset)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char classbuf[DNS_RDATATYPE_FORMATSIZE];
+
+ 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,
+ "check-names %s %s/%s/%s",
+ fail ? "failure" : "warning",
+ namebuf, typebuf, classbuf);
+ if (fail) {
+ if (ANSWER(rdataset)) {
+ dns_db_detachnode(fctx->cache, &node);
+ return (DNS_R_BADNAME);
+ }
+ continue;
+ }
+ }
+
+ /*
+ * Enforce the configure maximum cache TTL.
+ */
+ if (rdataset->ttl > res->view->maxcachettl)
+ rdataset->ttl = res->view->maxcachettl;
+
+ /*
+ * If this rrset is in a secure domain, do DNSSEC validation
+ * for it, unless it is glue.
+ */
+ if (secure_domain && rdataset->trust != dns_trust_glue) {
+ /*
+ * RRSIGs are validated as part of validating the
+ * type they cover.
+ */
+ if (rdataset->type == dns_rdatatype_rrsig)
+ continue;
+ /*
+ * Find the SIG for this rdataset, if we have it.
+ */
+ for (sigrdataset = ISC_LIST_HEAD(name->list);
+ sigrdataset != NULL;
+ sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
+ if (sigrdataset->type == dns_rdatatype_rrsig &&
+ sigrdataset->covers == rdataset->type)
+ break;
+ }
+ if (sigrdataset == NULL) {
+ if (!ANSWER(rdataset) && need_validation) {
+ /*
+ * Ignore non-answer rdatasets that
+ * are missing signatures.
+ */
+ continue;
+ }
+ }
+
+ /*
+ * Normalize the rdataset and sigrdataset TTLs.
+ */
+ if (sigrdataset != NULL) {
+ rdataset->ttl = ISC_MIN(rdataset->ttl,
+ sigrdataset->ttl);
+ sigrdataset->ttl = rdataset->ttl;
+ }
+
+ /*
+ * Cache this rdataset/sigrdataset pair as
+ * pending data.
+ */
+ rdataset->trust = dns_trust_pending;
+ if (sigrdataset != NULL)
+ sigrdataset->trust = dns_trust_pending;
+ if (!need_validation)
+ addedrdataset = ardataset;
+ else
+ addedrdataset = NULL;
+ result = dns_db_addrdataset(fctx->cache, node, NULL,
+ now, rdataset, 0,
+ addedrdataset);
+ if (result == DNS_R_UNCHANGED) {
+ result = ISC_R_SUCCESS;
+ if (!need_validation &&
+ ardataset != NULL &&
+ ardataset->type == 0) {
+ /*
+ * The answer in the cache is better
+ * than the answer we found, and is
+ * a negative cache entry, so we
+ * must set eresult appropriately.
+ */
+ if (NXDOMAIN(ardataset))
+ eresult = DNS_R_NCACHENXDOMAIN;
+ else
+ eresult = DNS_R_NCACHENXRRSET;
+ /*
+ * We have a negative response from
+ * the cache so don't attempt to
+ * add the RRSIG rrset.
+ */
+ continue;
+ }
+ }
+ if (result != ISC_R_SUCCESS)
+ break;
+ if (sigrdataset != NULL) {
+ if (!need_validation)
+ addedrdataset = asigrdataset;
+ else
+ addedrdataset = NULL;
+ result = dns_db_addrdataset(fctx->cache,
+ node, NULL, now,
+ sigrdataset, 0,
+ addedrdataset);
+ if (result == DNS_R_UNCHANGED)
+ result = ISC_R_SUCCESS;
+ if (result != ISC_R_SUCCESS)
+ break;
+ } else if (!ANSWER(rdataset))
+ continue;
+
+ if (ANSWER(rdataset) && need_validation) {
+ if (fctx->type != dns_rdatatype_any &&
+ fctx->type != dns_rdatatype_rrsig &&
+ fctx->type != dns_rdatatype_sig) {
+ /*
+ * This is The Answer. We will
+ * validate it, but first we cache
+ * the rest of the response - it may
+ * contain useful keys.
+ */
+ INSIST(valrdataset == NULL &&
+ valsigrdataset == NULL);
+ valrdataset = rdataset;
+ valsigrdataset = sigrdataset;
+ } else {
+ /*
+ * This is one of (potentially)
+ * multiple answers to an ANY
+ * or SIG query. To keep things
+ * simple, we just start the
+ * validator right away rather
+ * than caching first and
+ * having to remember which
+ * rdatasets needed validation.
+ */
+ result = valcreate(fctx, addrinfo,
+ name, rdataset->type,
+ rdataset,
+ sigrdataset,
+ valoptions, task);
+ /*
+ * Defer any further validations.
+ * This prevents multiple validators
+ * from manipulating fctx->rmessage
+ * simultaniously.
+ */
+ valoptions |= DNS_VALIDATOR_DEFER;
+ }
+ } else if (CHAINING(rdataset)) {
+ if (rdataset->type == dns_rdatatype_cname)
+ eresult = DNS_R_CNAME;
+ else {
+ INSIST(rdataset->type ==
+ dns_rdatatype_dname);
+ eresult = DNS_R_DNAME;
+ }
+ }
+ } else if (!EXTERNAL(rdataset)) {
+ /*
+ * It's OK to cache this rdataset now.
+ */
+ if (ANSWER(rdataset))
+ addedrdataset = ardataset;
+ else if (ANSWERSIG(rdataset))
+ addedrdataset = asigrdataset;
+ else
+ addedrdataset = NULL;
+ if (CHAINING(rdataset)) {
+ if (rdataset->type == dns_rdatatype_cname)
+ eresult = DNS_R_CNAME;
+ else {
+ INSIST(rdataset->type ==
+ dns_rdatatype_dname);
+ eresult = DNS_R_DNAME;
+ }
+ }
+ if (rdataset->trust == dns_trust_glue &&
+ (rdataset->type == dns_rdatatype_ns ||
+ (rdataset->type == dns_rdatatype_rrsig &&
+ rdataset->covers == dns_rdatatype_ns))) {
+ /*
+ * If the trust level is 'dns_trust_glue'
+ * then we are adding data from a referral
+ * we got while executing the search algorithm.
+ * New referral data always takes precedence
+ * over the existing cache contents.
+ */
+ options = DNS_DBADD_FORCE;
+ } else
+ options = 0;
+ /*
+ * Now we can add the rdataset.
+ */
+ result = dns_db_addrdataset(fctx->cache,
+ node, NULL, now,
+ rdataset,
+ options,
+ addedrdataset);
+ if (result == DNS_R_UNCHANGED) {
+ if (ANSWER(rdataset) &&
+ ardataset != NULL &&
+ ardataset->type == 0) {
+ /*
+ * The answer in the cache is better
+ * than the answer we found, and is
+ * a negative cache entry, so we
+ * must set eresult appropriately.
+ */
+ if (NXDOMAIN(ardataset))
+ eresult = DNS_R_NCACHENXDOMAIN;
+ else
+ eresult = DNS_R_NCACHENXRRSET;
+ }
+ result = ISC_R_SUCCESS;
+ } else if (result != ISC_R_SUCCESS)
+ break;
+ }
+ }
+
+ if (valrdataset != NULL)
+ result = valcreate(fctx, addrinfo, name, fctx->type,
+ valrdataset, valsigrdataset, valoptions,
+ task);
+
+ if (result == ISC_R_SUCCESS && have_answer) {
+ fctx->attributes |= FCTX_ATTR_HAVEANSWER;
+ if (event != NULL) {
+ /*
+ * Negative results must be indicated in event->result.
+ */
+ if (dns_rdataset_isassociated(event->rdataset) &&
+ event->rdataset->type == dns_rdatatype_none) {
+ INSIST(eresult == DNS_R_NCACHENXDOMAIN ||
+ eresult == DNS_R_NCACHENXRRSET);
+ }
+ event->result = eresult;
+ dns_db_attach(fctx->cache, adbp);
+ dns_db_transfernode(fctx->cache, &node, anodep);
+ clone_results(fctx);
+ }
+ }
+
+ if (node != NULL)
+ dns_db_detachnode(fctx->cache, &node);
+
+ return (result);
+}
+
+static inline isc_result_t
+cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
+{
+ isc_result_t result;
+ dns_section_t section;
+ dns_name_t *name;
+
+ FCTXTRACE("cache_message");
+
+ fctx->attributes &= ~FCTX_ATTR_WANTCACHE;
+
+ LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+
+ for (section = DNS_SECTION_ANSWER;
+ section <= DNS_SECTION_ADDITIONAL;
+ section++) {
+ result = dns_message_firstname(fctx->rmessage, section);
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(fctx->rmessage, section,
+ &name);
+ if ((name->attributes & DNS_NAMEATTR_CACHE) != 0) {
+ result = cache_name(fctx, name, addrinfo, now);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ result = dns_message_nextname(fctx->rmessage, section);
+ }
+ if (result != ISC_R_NOMORE)
+ break;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+
+ return (result);
+}
+
+/*
+ * Do what dns_ncache_addoptout() does, and then compute an appropriate eresult.
+ */
+static isc_result_t
+ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
+ dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
+ isc_boolean_t optout, dns_rdataset_t *ardataset,
+ isc_result_t *eresultp)
+{
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+
+ if (ardataset == NULL) {
+ dns_rdataset_init(&rdataset);
+ ardataset = &rdataset;
+ }
+ result = dns_ncache_addoptout(message, cache, node, covers, now,
+ maxttl, optout, ardataset);
+ if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
+ /*
+ * If the cache now contains a negative entry and we
+ * care about whether it is DNS_R_NCACHENXDOMAIN or
+ * DNS_R_NCACHENXRRSET then extract it.
+ */
+ if (ardataset->type == 0) {
+ /*
+ * The cache data is a negative cache entry.
+ */
+ if (NXDOMAIN(ardataset))
+ *eresultp = DNS_R_NCACHENXDOMAIN;
+ else
+ *eresultp = DNS_R_NCACHENXRRSET;
+ } else {
+ /*
+ * Either we don't care about the nature of the
+ * cache rdataset (because no fetch is interested
+ * in the outcome), or the cache rdataset is not
+ * a negative cache entry. Whichever case it is,
+ * we can return success.
+ *
+ * XXXRTH There's a CNAME/DNAME problem here.
+ */
+ *eresultp = ISC_R_SUCCESS;
+ }
+ result = ISC_R_SUCCESS;
+ }
+ if (ardataset == &rdataset && dns_rdataset_isassociated(ardataset))
+ dns_rdataset_disassociate(ardataset);
+
+ return (result);
+}
+
+static inline isc_result_t
+ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
+ dns_rdatatype_t covers, isc_stdtime_t now)
+{
+ isc_result_t result, eresult;
+ dns_name_t *name;
+ dns_resolver_t *res;
+ dns_db_t **adbp;
+ dns_dbnode_t *node, **anodep;
+ dns_rdataset_t *ardataset;
+ isc_boolean_t need_validation, secure_domain;
+ dns_name_t *aname;
+ dns_fetchevent_t *event;
+ isc_uint32_t ttl;
+ unsigned int valoptions = 0;
+
+ FCTXTRACE("ncache_message");
+
+ fctx->attributes &= ~FCTX_ATTR_WANTNCACHE;
+
+ res = fctx->res;
+ need_validation = ISC_FALSE;
+ secure_domain = ISC_FALSE;
+ eresult = ISC_R_SUCCESS;
+ name = &fctx->name;
+ node = NULL;
+
+ /*
+ * XXXMPA remove when we follow cnames and adjust the setting
+ * of FCTX_ATTR_WANTNCACHE in noanswer_response().
+ */
+ INSIST(fctx->rmessage->counts[DNS_SECTION_ANSWER] == 0);
+
+ /*
+ * Is DNSSEC validation required for this name?
+ */
+ if (fctx->res->view->enablevalidation) {
+ result = dns_keytable_issecuredomain(res->view->secroots, name,
+ &secure_domain);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (!secure_domain && res->view->dlv != NULL) {
+ valoptions = DNS_VALIDATOR_DLV;
+ secure_domain = ISC_TRUE;
+ }
+ }
+
+ if ((fctx->options & DNS_FETCHOPT_NOVALIDATE) != 0)
+ need_validation = ISC_FALSE;
+ else
+ need_validation = secure_domain;
+
+ if (secure_domain) {
+ /*
+ * Mark all rdatasets as pending.
+ */
+ dns_rdataset_t *trdataset;
+ dns_name_t *tname;
+
+ result = dns_message_firstname(fctx->rmessage,
+ DNS_SECTION_AUTHORITY);
+ while (result == ISC_R_SUCCESS) {
+ tname = NULL;
+ dns_message_currentname(fctx->rmessage,
+ DNS_SECTION_AUTHORITY,
+ &tname);
+ for (trdataset = ISC_LIST_HEAD(tname->list);
+ trdataset != NULL;
+ trdataset = ISC_LIST_NEXT(trdataset, link))
+ trdataset->trust = dns_trust_pending;
+ result = dns_message_nextname(fctx->rmessage,
+ DNS_SECTION_AUTHORITY);
+ }
+ if (result != ISC_R_NOMORE)
+ return (result);
+
+ }
+
+ if (need_validation) {
+ /*
+ * Do negative response validation.
+ */
+ result = valcreate(fctx, addrinfo, name, fctx->type,
+ NULL, NULL, valoptions,
+ res->buckets[fctx->bucketnum].task);
+ /*
+ * If validation is necessary, return now. Otherwise continue
+ * to process the message, letting the validation complete
+ * in its own good time.
+ */
+ return (result);
+ }
+
+ LOCK(&res->buckets[fctx->bucketnum].lock);
+
+ adbp = NULL;
+ aname = NULL;
+ anodep = NULL;
+ ardataset = NULL;
+ if (!HAVE_ANSWER(fctx)) {
+ event = ISC_LIST_HEAD(fctx->events);
+ if (event != NULL) {
+ adbp = &event->db;
+ aname = dns_fixedname_name(&event->foundname);
+ result = dns_name_copy(name, aname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto unlock;
+ anodep = &event->node;
+ ardataset = event->rdataset;
+ }
+ } else
+ event = NULL;
+
+ result = dns_db_findnode(fctx->cache, name, ISC_TRUE, &node);
+ if (result != ISC_R_SUCCESS)
+ goto unlock;
+
+ /*
+ * If we are asking for a SOA record set the cache time
+ * to zero to facilitate locating the containing zone of
+ * a arbitary zone.
+ */
+ ttl = fctx->res->view->maxncachettl;
+ if (fctx->type == dns_rdatatype_soa &&
+ covers == dns_rdatatype_any)
+ ttl = 0;
+
+ result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
+ covers, now, ttl, ISC_FALSE,
+ ardataset, &eresult);
+ if (result != ISC_R_SUCCESS)
+ goto unlock;
+
+ if (!HAVE_ANSWER(fctx)) {
+ fctx->attributes |= FCTX_ATTR_HAVEANSWER;
+ if (event != NULL) {
+ event->result = eresult;
+ dns_db_attach(fctx->cache, adbp);
+ dns_db_transfernode(fctx->cache, &node, anodep);
+ clone_results(fctx);
+ }
+ }
+
+ unlock:
+ UNLOCK(&res->buckets[fctx->bucketnum].lock);
+
+ if (node != NULL)
+ dns_db_detachnode(fctx->cache, &node);
+
+ return (result);
+}
+
+static inline void
+mark_related(dns_name_t *name, dns_rdataset_t *rdataset,
+ isc_boolean_t external, isc_boolean_t gluing)
+{
+ name->attributes |= DNS_NAMEATTR_CACHE;
+ if (gluing) {
+ rdataset->trust = dns_trust_glue;
+ /*
+ * Glue with 0 TTL causes problems. We force the TTL to
+ * 1 second to prevent this.
+ */
+ if (rdataset->ttl == 0)
+ rdataset->ttl = 1;
+ } else
+ rdataset->trust = dns_trust_additional;
+ /*
+ * Avoid infinite loops by only marking new rdatasets.
+ */
+ if (!CACHE(rdataset)) {
+ name->attributes |= DNS_NAMEATTR_CHASE;
+ rdataset->attributes |= DNS_RDATASETATTR_CHASE;
+ }
+ rdataset->attributes |= DNS_RDATASETATTR_CACHE;
+ if (external)
+ rdataset->attributes |= DNS_RDATASETATTR_EXTERNAL;
+}
+
+static isc_result_t
+check_related(void *arg, dns_name_t *addname, dns_rdatatype_t type) {
+ fetchctx_t *fctx = arg;
+ isc_result_t result;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ isc_boolean_t external;
+ dns_rdatatype_t rtype;
+ isc_boolean_t gluing;
+
+ REQUIRE(VALID_FCTX(fctx));
+
+ 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);
+ if (result == ISC_R_SUCCESS) {
+ external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
+ if (type == dns_rdatatype_a) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (rdataset->type == dns_rdatatype_rrsig)
+ rtype = rdataset->covers;
+ else
+ rtype = rdataset->type;
+ if (rtype == dns_rdatatype_a ||
+ rtype == dns_rdatatype_aaaa)
+ mark_related(name, rdataset, external,
+ gluing);
+ }
+ } else {
+ result = dns_message_findtype(name, type, 0,
+ &rdataset);
+ if (result == ISC_R_SUCCESS) {
+ mark_related(name, rdataset, external, gluing);
+ /*
+ * Do we have its SIG too?
+ */
+ rdataset = NULL;
+ result = dns_message_findtype(name,
+ dns_rdatatype_rrsig,
+ type, &rdataset);
+ if (result == ISC_R_SUCCESS)
+ mark_related(name, rdataset, external,
+ gluing);
+ }
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+chase_additional(fetchctx_t *fctx) {
+ isc_boolean_t rescan;
+ dns_section_t section = DNS_SECTION_ADDITIONAL;
+ isc_result_t result;
+
+ again:
+ rescan = ISC_FALSE;
+
+ for (result = dns_message_firstname(fctx->rmessage, section);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(fctx->rmessage, section)) {
+ dns_name_t *name = NULL;
+ dns_rdataset_t *rdataset;
+ dns_message_currentname(fctx->rmessage, DNS_SECTION_ADDITIONAL,
+ &name);
+ if ((name->attributes & DNS_NAMEATTR_CHASE) == 0)
+ continue;
+ name->attributes &= ~DNS_NAMEATTR_CHASE;
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (CHASE(rdataset)) {
+ rdataset->attributes &= ~DNS_RDATASETATTR_CHASE;
+ (void)dns_rdataset_additionaldata(rdataset,
+ check_related,
+ fctx);
+ rescan = ISC_TRUE;
+ }
+ }
+ }
+ if (rescan)
+ goto again;
+}
+
+static inline isc_result_t
+cname_target(dns_rdataset_t *rdataset, dns_name_t *tname) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_cname_t cname;
+
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_name_init(tname, NULL);
+ dns_name_clone(&cname.cname, tname);
+ dns_rdata_freestruct(&cname);
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+dname_target(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;
+ unsigned int nlabels;
+ int order;
+ dns_namereln_t namereln;
+ dns_rdata_dname_t dname;
+ dns_fixedname_t prefix;
+
+ /*
+ * Get the target name of the DNAME.
+ */
+
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &dname, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Get the prefix of qname.
+ */
+ namereln = dns_name_fullcompare(qname, oname, &order, &nlabels);
+ if (namereln != dns_namereln_subdomain) {
+ dns_rdata_freestruct(&dname);
+ return (DNS_R_FORMERR);
+ }
+ dns_fixedname_init(&prefix);
+ dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
+ dns_fixedname_init(fixeddname);
+ result = dns_name_concatenate(dns_fixedname_name(&prefix),
+ &dname.dname,
+ dns_fixedname_name(fixeddname), NULL);
+ dns_rdata_freestruct(&dname);
+ return (result);
+}
+
+/*
+ * 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.
+ */
+static isc_result_t
+noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
+ isc_boolean_t bind8_ns_resp)
+{
+ isc_result_t result;
+ dns_message_t *message;
+ dns_name_t *name, *qname, *ns_name, *soa_name, *ds_name;
+ 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;
+
+ FCTXTRACE("noanswer_response");
+
+ message = fctx->rmessage;
+
+ /*
+ * Setup qname.
+ */
+ if (oqname == NULL) {
+ /*
+ * We have a normal, non-chained negative response or
+ * referral.
+ */
+ if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
+ aa = ISC_TRUE;
+ else
+ aa = ISC_FALSE;
+ qname = &fctx->name;
+ } else {
+ /*
+ * We're being invoked by answer_response() after it has
+ * followed a CNAME/DNAME chain.
+ */
+ qname = oqname;
+ aa = ISC_FALSE;
+ /*
+ * If the current qname is not a subdomain of the query
+ * domain, there's no point in looking at the authority
+ * section without doing DNSSEC validation.
+ *
+ * Until we do that validation, we'll just return success
+ * in this case.
+ */
+ if (!dns_name_issubdomain(qname, &fctx->domain))
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * We have to figure out if this is a negative response, or a
+ * referral.
+ */
+
+ /*
+ * Sometimes we can tell if its a negative response by looking at
+ * the message header.
+ */
+ negative_response = ISC_FALSE;
+ if (message->rcode == dns_rcode_nxdomain ||
+ (message->counts[DNS_SECTION_ANSWER] == 0 &&
+ message->counts[DNS_SECTION_AUTHORITY] == 0))
+ negative_response = ISC_TRUE;
+
+ /*
+ * Process the authority section.
+ */
+ ns_name = NULL;
+ ns_rdataset = NULL;
+ soa_name = NULL;
+ ds_name = NULL;
+ result = dns_message_firstname(message, section);
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(message, section, &name);
+ if (dns_name_issubdomain(name, &fctx->domain)) {
+ /*
+ * Look for NS/SOA RRsets first.
+ */
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ type = rdataset->type;
+ if (type == dns_rdatatype_rrsig)
+ type = rdataset->covers;
+ if (((type == dns_rdatatype_ns ||
+ type == dns_rdatatype_soa) &&
+ !dns_name_issubdomain(qname, name)))
+ return (DNS_R_FORMERR);
+ if (type == dns_rdatatype_ns) {
+ /*
+ * NS or RRSIG NS.
+ *
+ * Only one set of NS RRs is allowed.
+ */
+ if (rdataset->type ==
+ dns_rdatatype_ns) {
+ if (ns_name != NULL &&
+ name != ns_name)
+ return (DNS_R_FORMERR);
+ ns_name = name;
+ ns_rdataset = rdataset;
+ }
+ name->attributes |=
+ DNS_NAMEATTR_CACHE;
+ rdataset->attributes |=
+ DNS_RDATASETATTR_CACHE;
+ rdataset->trust = dns_trust_glue;
+ }
+ if (type == dns_rdatatype_soa) {
+ /*
+ * SOA, or RRSIG SOA.
+ *
+ * Only one SOA is allowed.
+ */
+ if (rdataset->type ==
+ dns_rdatatype_soa) {
+ if (soa_name != NULL &&
+ name != soa_name)
+ return (DNS_R_FORMERR);
+ soa_name = name;
+ }
+ name->attributes |=
+ DNS_NAMEATTR_NCACHE;
+ rdataset->attributes |=
+ DNS_RDATASETATTR_NCACHE;
+ if (aa)
+ rdataset->trust =
+ dns_trust_authauthority;
+ else
+ rdataset->trust =
+ dns_trust_additional;
+ }
+ }
+ }
+ result = dns_message_nextname(message, section);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ /*
+ * A negative response has a SOA record (Type 2)
+ * and a optional NS RRset (Type 1) or it has neither
+ * a SOA or a NS RRset (Type 3, handled above) or
+ * rcode is NXDOMAIN (handled above) in which case
+ * the NS RRset is allowed (Type 4).
+ */
+ if (soa_name != NULL)
+ negative_response = ISC_TRUE;
+
+ result = dns_message_firstname(message, section);
+ while (result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(message, section, &name);
+ if (dns_name_issubdomain(name, &fctx->domain)) {
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ type = rdataset->type;
+ if (type == dns_rdatatype_rrsig)
+ type = rdataset->covers;
+ if (type == dns_rdatatype_nsec ||
+ type == dns_rdatatype_nsec3) {
+ /*
+ * NSEC or RRSIG NSEC.
+ */
+ if (negative_response) {
+ name->attributes |=
+ DNS_NAMEATTR_NCACHE;
+ rdataset->attributes |=
+ DNS_RDATASETATTR_NCACHE;
+ } else if (type == dns_rdatatype_nsec) {
+ name->attributes |=
+ DNS_NAMEATTR_CACHE;
+ rdataset->attributes |=
+ DNS_RDATASETATTR_CACHE;
+ }
+ if (aa)
+ rdataset->trust =
+ dns_trust_authauthority;
+ else
+ rdataset->trust =
+ dns_trust_additional;
+ /*
+ * No additional data needs to be
+ * marked.
+ */
+ } else if (type == dns_rdatatype_ds) {
+ /*
+ * DS or SIG DS.
+ *
+ * These should only be here if
+ * this is a referral, and there
+ * should only be one DS.
+ */
+ if (ns_name == NULL)
+ return (DNS_R_FORMERR);
+ if (rdataset->type ==
+ dns_rdatatype_ds) {
+ if (ds_name != NULL &&
+ name != ds_name)
+ return (DNS_R_FORMERR);
+ ds_name = name;
+ }
+ name->attributes |=
+ DNS_NAMEATTR_CACHE;
+ rdataset->attributes |=
+ DNS_RDATASETATTR_CACHE;
+ if (aa)
+ rdataset->trust =
+ dns_trust_authauthority;
+ else
+ rdataset->trust =
+ dns_trust_additional;
+ }
+ }
+ }
+ result = dns_message_nextname(message, section);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ /*
+ * Trigger lookups for DNS nameservers.
+ */
+ if (negative_response && message->rcode == dns_rcode_noerror &&
+ fctx->type == dns_rdatatype_ds && soa_name != NULL &&
+ dns_name_equal(soa_name, qname) &&
+ !dns_name_equal(qname, dns_rootname))
+ return (DNS_R_CHASEDSSERVERS);
+
+ /*
+ * Did we find anything?
+ */
+ if (!negative_response && ns_name == NULL) {
+ /*
+ * Nope.
+ */
+ if (oqname != NULL) {
+ /*
+ * We've already got a partial CNAME/DNAME chain,
+ * and haven't found else anything useful here, but
+ * no error has occurred since we have an answer.
+ */
+ return (ISC_R_SUCCESS);
+ } else {
+ /*
+ * The responder is insane.
+ */
+ return (DNS_R_FORMERR);
+ }
+ }
+
+ /*
+ * If we found both NS and SOA, they should be the same name.
+ */
+ if (ns_name != NULL && soa_name != NULL && ns_name != soa_name)
+ return (DNS_R_FORMERR);
+
+ /*
+ * Do we have a referral? (We only want to follow a referral if
+ * we're not following a chain.)
+ */
+ if (!negative_response && ns_name != NULL && oqname == NULL) {
+ /*
+ * We already know ns_name is a subdomain of fctx->domain.
+ * If ns_name is equal to fctx->domain, we're not making
+ * progress. We return DNS_R_FORMERR so that we'll keep
+ * trying other servers.
+ */
+ if (dns_name_equal(ns_name, &fctx->domain))
+ 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)) {
+ FCTXTRACE("referral to non-parent");
+ return (DNS_R_FORMERR);
+ }
+
+ /*
+ * Mark any additional data related to this rdataset.
+ * It's important that we do this before we change the
+ * query domain.
+ */
+ INSIST(ns_rdataset != NULL);
+ fctx->attributes |= FCTX_ATTR_GLUING;
+ (void)dns_rdataset_additionaldata(ns_rdataset, check_related,
+ fctx);
+ fctx->attributes &= ~FCTX_ATTR_GLUING;
+ /*
+ * NS rdatasets with 0 TTL cause problems.
+ * dns_view_findzonecut() will not find them when we
+ * try to follow the referral, and we'll SERVFAIL
+ * because the best nameservers are now above QDOMAIN.
+ * We force the TTL to 1 second to prevent this.
+ */
+ if (ns_rdataset->ttl == 0)
+ ns_rdataset->ttl = 1;
+ /*
+ * Set the current query domain to the referral name.
+ *
+ * XXXRTH We should check if we're in forward-only mode, and
+ * if so we should bail out.
+ */
+ INSIST(dns_name_countlabels(&fctx->domain) > 0);
+ dns_name_free(&fctx->domain,
+ fctx->res->buckets[fctx->bucketnum].mctx);
+ if (dns_rdataset_isassociated(&fctx->nameservers))
+ dns_rdataset_disassociate(&fctx->nameservers);
+ dns_name_init(&fctx->domain, NULL);
+ result = dns_name_dup(ns_name,
+ fctx->res->buckets[fctx->bucketnum].mctx,
+ &fctx->domain);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ fctx->attributes |= FCTX_ATTR_WANTCACHE;
+ return (DNS_R_DELEGATION);
+ }
+
+ /*
+ * Since we're not doing a referral, we don't want to cache any
+ * NS RRs we may have found.
+ */
+ if (ns_name != NULL)
+ ns_name->attributes &= ~DNS_NAMEATTR_CACHE;
+
+ if (negative_response && oqname == NULL)
+ fctx->attributes |= FCTX_ATTR_WANTNCACHE;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+answer_response(fetchctx_t *fctx) {
+ isc_result_t result;
+ dns_message_t *message;
+ dns_name_t *name, *qname, tname;
+ dns_rdataset_t *rdataset;
+ isc_boolean_t done, external, chaining, aa, found, want_chaining;
+ isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
+ unsigned int aflag;
+ dns_rdatatype_t type;
+ dns_fixedname_t dname, fqname;
+
+ FCTXTRACE("answer_response");
+
+ message = fctx->rmessage;
+
+ /*
+ * Examine the answer section, marking those rdatasets which are
+ * part of the answer and should be cached.
+ */
+
+ done = ISC_FALSE;
+ found_cname = ISC_FALSE;
+ found_type = ISC_FALSE;
+ chaining = ISC_FALSE;
+ have_answer = ISC_FALSE;
+ want_chaining = ISC_FALSE;
+ if ((message->flags & DNS_MESSAGEFLAG_AA) != 0)
+ aa = ISC_TRUE;
+ else
+ aa = ISC_FALSE;
+ qname = &fctx->name;
+ type = fctx->type;
+ result = dns_message_firstname(message, DNS_SECTION_ANSWER);
+ while (!done && result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
+ external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
+ if (dns_name_equal(name, qname)) {
+ wanted_chaining = ISC_FALSE;
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ found = ISC_FALSE;
+ want_chaining = ISC_FALSE;
+ aflag = 0;
+ if (rdataset->type == dns_rdatatype_nsec3) {
+ /*
+ * NSEC3 records are not allowed to
+ * appear in the answer section.
+ */
+ return (DNS_R_FORMERR);
+ }
+ if (rdataset->type == type && !found_cname) {
+ /*
+ * We've found an ordinary answer.
+ */
+ found = ISC_TRUE;
+ found_type = ISC_TRUE;
+ done = ISC_TRUE;
+ aflag = DNS_RDATASETATTR_ANSWER;
+ } else if (type == dns_rdatatype_any) {
+ /*
+ * We've found an answer matching
+ * an ANY query. There may be
+ * more.
+ */
+ found = ISC_TRUE;
+ aflag = DNS_RDATASETATTR_ANSWER;
+ } else if (rdataset->type == dns_rdatatype_rrsig
+ && rdataset->covers == type
+ && !found_cname) {
+ /*
+ * We've found a signature that
+ * covers the type we're looking for.
+ */
+ found = ISC_TRUE;
+ found_type = ISC_TRUE;
+ aflag = DNS_RDATASETATTR_ANSWERSIG;
+ } else if (rdataset->type ==
+ dns_rdatatype_cname
+ && !found_type) {
+ /*
+ * We're looking for something else,
+ * but we found a CNAME.
+ *
+ * Getting a CNAME response for some
+ * query types is an error.
+ */
+ if (type == dns_rdatatype_rrsig ||
+ type == dns_rdatatype_dnskey ||
+ type == dns_rdatatype_nsec)
+ return (DNS_R_FORMERR);
+ found = ISC_TRUE;
+ found_cname = ISC_TRUE;
+ want_chaining = ISC_TRUE;
+ aflag = DNS_RDATASETATTR_ANSWER;
+ result = cname_target(rdataset,
+ &tname);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else if (rdataset->type == dns_rdatatype_rrsig
+ && rdataset->covers ==
+ dns_rdatatype_cname
+ && !found_type) {
+ /*
+ * We're looking for something else,
+ * but we found a SIG CNAME.
+ */
+ found = ISC_TRUE;
+ found_cname = ISC_TRUE;
+ aflag = DNS_RDATASETATTR_ANSWERSIG;
+ }
+
+ if (found) {
+ /*
+ * We've found an answer to our
+ * question.
+ */
+ name->attributes |=
+ DNS_NAMEATTR_CACHE;
+ rdataset->attributes |=
+ DNS_RDATASETATTR_CACHE;
+ rdataset->trust = dns_trust_answer;
+ if (!chaining) {
+ /*
+ * This data is "the" answer
+ * to our question only if
+ * we're not chaining (i.e.
+ * if we haven't followed
+ * a CNAME or DNAME).
+ */
+ INSIST(!external);
+ if (aflag ==
+ DNS_RDATASETATTR_ANSWER)
+ have_answer = ISC_TRUE;
+ name->attributes |=
+ DNS_NAMEATTR_ANSWER;
+ rdataset->attributes |= aflag;
+ if (aa)
+ rdataset->trust =
+ dns_trust_authanswer;
+ } else if (external) {
+ /*
+ * This data is outside of
+ * our query domain, and
+ * may only be cached if it
+ * comes from a secure zone
+ * and validates.
+ */
+ rdataset->attributes |=
+ DNS_RDATASETATTR_EXTERNAL;
+ }
+
+ /*
+ * Mark any additional data related
+ * to this rdataset.
+ */
+ (void)dns_rdataset_additionaldata(
+ rdataset,
+ check_related,
+ fctx);
+
+ /*
+ * CNAME chaining.
+ */
+ if (want_chaining) {
+ wanted_chaining = ISC_TRUE;
+ name->attributes |=
+ DNS_NAMEATTR_CHAINING;
+ rdataset->attributes |=
+ DNS_RDATASETATTR_CHAINING;
+ qname = &tname;
+ }
+ }
+ /*
+ * We could add an "else" clause here and
+ * log that we're ignoring this rdataset.
+ */
+ }
+ /*
+ * If wanted_chaining is true, we've done
+ * some chaining as the result of processing
+ * this node, and thus we need to set
+ * chaining to true.
+ *
+ * We don't set chaining inside of the
+ * rdataset loop because doing that would
+ * cause us to ignore the signatures of
+ * CNAMEs.
+ */
+ if (wanted_chaining)
+ chaining = ISC_TRUE;
+ } else {
+ /*
+ * Look for a DNAME (or its SIG). Anything else is
+ * ignored.
+ */
+ wanted_chaining = ISC_FALSE;
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ isc_boolean_t found_dname = ISC_FALSE;
+ found = ISC_FALSE;
+ aflag = 0;
+ if (rdataset->type == dns_rdatatype_dname) {
+ /*
+ * We're looking for something else,
+ * but we found a DNAME.
+ *
+ * If we're not chaining, then the
+ * DNAME should not be external.
+ */
+ if (!chaining && external)
+ return (DNS_R_FORMERR);
+ found = ISC_TRUE;
+ want_chaining = ISC_TRUE;
+ aflag = DNS_RDATASETATTR_ANSWER;
+ result = dname_target(rdataset,
+ qname, name,
+ &dname);
+ if (result == ISC_R_NOSPACE) {
+ /*
+ * We can't construct the
+ * DNAME target. Do not
+ * try to continue.
+ */
+ want_chaining = ISC_FALSE;
+ } else if (result != ISC_R_SUCCESS)
+ return (result);
+ else
+ found_dname = ISC_TRUE;
+ } else if (rdataset->type == dns_rdatatype_rrsig
+ && rdataset->covers ==
+ dns_rdatatype_dname) {
+ /*
+ * We've found a signature that
+ * covers the DNAME.
+ */
+ found = ISC_TRUE;
+ aflag = DNS_RDATASETATTR_ANSWERSIG;
+ }
+
+ if (found) {
+ /*
+ * We've found an answer to our
+ * question.
+ */
+ name->attributes |=
+ DNS_NAMEATTR_CACHE;
+ rdataset->attributes |=
+ DNS_RDATASETATTR_CACHE;
+ rdataset->trust = dns_trust_answer;
+ if (!chaining) {
+ /*
+ * This data is "the" answer
+ * to our question only if
+ * we're not chaining.
+ */
+ INSIST(!external);
+ if (aflag ==
+ DNS_RDATASETATTR_ANSWER)
+ have_answer = ISC_TRUE;
+ name->attributes |=
+ DNS_NAMEATTR_ANSWER;
+ rdataset->attributes |= aflag;
+ if (aa)
+ rdataset->trust =
+ dns_trust_authanswer;
+ } else if (external) {
+ rdataset->attributes |=
+ DNS_RDATASETATTR_EXTERNAL;
+ }
+
+ /*
+ * DNAME chaining.
+ */
+ if (found_dname) {
+ /*
+ * Copy the the dname into the
+ * qname fixed name.
+ *
+ * Although we check for
+ * failure of the copy
+ * operation, in practice it
+ * should never fail since
+ * we already know that the
+ * result fits in a fixedname.
+ */
+ dns_fixedname_init(&fqname);
+ result = dns_name_copy(
+ dns_fixedname_name(&dname),
+ dns_fixedname_name(&fqname),
+ NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ wanted_chaining = ISC_TRUE;
+ name->attributes |=
+ DNS_NAMEATTR_CHAINING;
+ rdataset->attributes |=
+ DNS_RDATASETATTR_CHAINING;
+ qname = dns_fixedname_name(
+ &fqname);
+ }
+ }
+ }
+ if (wanted_chaining)
+ chaining = ISC_TRUE;
+ }
+ result = dns_message_nextname(message, DNS_SECTION_ANSWER);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * We should have found an answer.
+ */
+ if (!have_answer)
+ return (DNS_R_FORMERR);
+
+ /*
+ * This response is now potentially cacheable.
+ */
+ fctx->attributes |= FCTX_ATTR_WANTCACHE;
+
+ /*
+ * Did chaining end before we got the final answer?
+ */
+ if (chaining) {
+ /*
+ * Yes. This may be a negative reply, so hand off
+ * authority section processing to the noanswer code.
+ * If it isn't a noanswer response, no harm will be
+ * done.
+ */
+ return (noanswer_response(fctx, qname, ISC_FALSE));
+ }
+
+ /*
+ * We didn't end with an incomplete chain, so the rcode should be
+ * "no error".
+ */
+ if (message->rcode != dns_rcode_noerror)
+ return (DNS_R_FORMERR);
+
+ /*
+ * Examine the authority section (if there is one).
+ *
+ * We expect there to be only one owner name for all the rdatasets
+ * in this section, and we expect that it is not external.
+ */
+ done = ISC_FALSE;
+ result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ while (!done && result == ISC_R_SUCCESS) {
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+ external = ISC_TF(!dns_name_issubdomain(name, &fctx->domain));
+ if (!external) {
+ /*
+ * We expect to find NS or SIG NS rdatasets, and
+ * nothing else.
+ */
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (rdataset->type == dns_rdatatype_ns ||
+ (rdataset->type == dns_rdatatype_rrsig &&
+ rdataset->covers == dns_rdatatype_ns)) {
+ name->attributes |=
+ DNS_NAMEATTR_CACHE;
+ rdataset->attributes |=
+ DNS_RDATASETATTR_CACHE;
+ if (aa && !chaining)
+ rdataset->trust =
+ dns_trust_authauthority;
+ else
+ rdataset->trust =
+ dns_trust_additional;
+
+ /*
+ * Mark any additional data related
+ * to this rdataset.
+ */
+ (void)dns_rdataset_additionaldata(
+ rdataset,
+ check_related,
+ fctx);
+ done = ISC_TRUE;
+ }
+ }
+ }
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ return (result);
+}
+
+static void
+resume_dslookup(isc_task_t *task, isc_event_t *event) {
+ dns_fetchevent_t *fevent;
+ dns_resolver_t *res;
+ fetchctx_t *fctx;
+ isc_result_t result;
+ isc_boolean_t bucket_empty = ISC_FALSE;
+ isc_boolean_t locked = ISC_FALSE;
+ unsigned int bucketnum;
+ dns_rdataset_t nameservers;
+ dns_fixedname_t fixed;
+ dns_name_t *domain;
+
+ REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
+ fevent = (dns_fetchevent_t *)event;
+ fctx = event->ev_arg;
+ REQUIRE(VALID_FCTX(fctx));
+ res = fctx->res;
+
+ UNUSED(task);
+ FCTXTRACE("resume_dslookup");
+
+ if (fevent->node != NULL)
+ dns_db_detachnode(fevent->db, &fevent->node);
+ if (fevent->db != NULL)
+ dns_db_detach(&fevent->db);
+
+ dns_rdataset_init(&nameservers);
+
+ bucketnum = fctx->bucketnum;
+ if (fevent->result == ISC_R_CANCELED) {
+ dns_resolver_destroyfetch(&fctx->nsfetch);
+ fctx_done(fctx, ISC_R_CANCELED);
+ } else if (fevent->result == ISC_R_SUCCESS) {
+
+ FCTXTRACE("resuming DS lookup");
+
+ dns_resolver_destroyfetch(&fctx->nsfetch);
+ if (dns_rdataset_isassociated(&fctx->nameservers))
+ dns_rdataset_disassociate(&fctx->nameservers);
+ dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
+ dns_name_free(&fctx->domain,
+ fctx->res->buckets[bucketnum].mctx);
+ dns_name_init(&fctx->domain, NULL);
+ result = dns_name_dup(&fctx->nsname,
+ fctx->res->buckets[bucketnum].mctx,
+ &fctx->domain);
+ if (result != ISC_R_SUCCESS) {
+ fctx_done(fctx, DNS_R_SERVFAIL);
+ goto cleanup;
+ }
+ /*
+ * Try again.
+ */
+ fctx_try(fctx, ISC_TRUE);
+ } else {
+ unsigned int n;
+ dns_rdataset_t *nsrdataset = NULL;
+
+ /*
+ * Retrieve state from fctx->nsfetch before we destroy it.
+ */
+ dns_fixedname_init(&fixed);
+ domain = dns_fixedname_name(&fixed);
+ dns_name_copy(&fctx->nsfetch->private->domain, domain, NULL);
+ if (dns_name_equal(&fctx->nsname, domain)) {
+ fctx_done(fctx, DNS_R_SERVFAIL);
+ dns_resolver_destroyfetch(&fctx->nsfetch);
+ goto cleanup;
+ }
+ if (dns_rdataset_isassociated(
+ &fctx->nsfetch->private->nameservers)) {
+ dns_rdataset_clone(
+ &fctx->nsfetch->private->nameservers,
+ &nameservers);
+ nsrdataset = &nameservers;
+ } else
+ domain = NULL;
+ dns_resolver_destroyfetch(&fctx->nsfetch);
+ n = dns_name_countlabels(&fctx->nsname);
+ dns_name_getlabelsequence(&fctx->nsname, 1, n - 1,
+ &fctx->nsname);
+
+ if (dns_rdataset_isassociated(fevent->rdataset))
+ dns_rdataset_disassociate(fevent->rdataset);
+ FCTXTRACE("continuing to look for parent's NS records");
+ result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
+ dns_rdatatype_ns, domain,
+ nsrdataset, NULL, 0, task,
+ resume_dslookup, fctx,
+ &fctx->nsrrset, NULL,
+ &fctx->nsfetch);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result);
+ else {
+ LOCK(&res->buckets[bucketnum].lock);
+ locked = ISC_TRUE;
+ fctx->references++;
+ }
+ }
+
+ cleanup:
+ if (dns_rdataset_isassociated(&nameservers))
+ dns_rdataset_disassociate(&nameservers);
+ if (dns_rdataset_isassociated(fevent->rdataset))
+ dns_rdataset_disassociate(fevent->rdataset);
+ INSIST(fevent->sigrdataset == NULL);
+ isc_event_free(&event);
+ if (!locked)
+ LOCK(&res->buckets[bucketnum].lock);
+ fctx->references--;
+ if (fctx->references == 0)
+ bucket_empty = fctx_destroy(fctx);
+ UNLOCK(&res->buckets[bucketnum].lock);
+ if (bucket_empty)
+ empty_bucket(res);
+}
+
+static inline void
+checknamessection(dns_message_t *message, dns_section_t section) {
+ isc_result_t result;
+ dns_name_t *name;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t *rdataset;
+
+ for (result = dns_message_firstname(message, section);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(message, section))
+ {
+ name = NULL;
+ dns_message_currentname(message, section, &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdataset_current(rdataset, &rdata);
+ if (!dns_rdata_checkowner(name, rdata.rdclass,
+ rdata.type,
+ ISC_FALSE) ||
+ !dns_rdata_checknames(&rdata, name, NULL))
+ {
+ rdataset->attributes |=
+ DNS_RDATASETATTR_CHECKNAMES;
+ }
+ dns_rdata_reset(&rdata);
+ }
+ }
+ }
+}
+
+static void
+checknames(dns_message_t *message) {
+
+ checknamessection(message, DNS_SECTION_ANSWER);
+ checknamessection(message, DNS_SECTION_AUTHORITY);
+ checknamessection(message, DNS_SECTION_ADDITIONAL);
+}
+
+/*
+ * Log server NSID at log level 'level'
+ */
+static isc_result_t
+log_nsid(dns_rdataset_t *opt, resquery_t *query, int level, isc_mem_t *mctx)
+{
+ static const char hex[17] = "0123456789abcdef";
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ isc_uint16_t optcode, nsid_len, buflen, i;
+ isc_result_t result;
+ isc_buffer_t nsidbuf;
+ dns_rdata_t rdata;
+ unsigned char *p, *buf, *nsid;
+
+ /* Extract rdata from OPT rdataset */
+ result = dns_rdataset_first(opt);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(opt, &rdata);
+ if (rdata.length < 4)
+ return (ISC_R_FAILURE);
+
+ /* Check for NSID */
+ isc_buffer_init(&nsidbuf, rdata.data, rdata.length);
+ isc_buffer_add(&nsidbuf, rdata.length);
+ optcode = isc_buffer_getuint16(&nsidbuf);
+ nsid_len = isc_buffer_getuint16(&nsidbuf);
+ if (optcode != DNS_OPT_NSID || nsid_len == 0)
+ return (ISC_R_FAILURE);
+
+ /* Allocate buffer for storing hex version of the NSID */
+ buflen = nsid_len * 2 + 1;
+ buf = isc_mem_get(mctx, buflen);
+ if (buf == NULL)
+ return (ISC_R_NOSPACE);
+
+ /* Convert to hex */
+ p = buf;
+ nsid = rdata.data + 4;
+ for (i = 0; i < nsid_len; i++) {
+ *p++ = hex[(nsid[0] >> 4) & 0xf];
+ *p++ = hex[nsid[0] & 0xf];
+ nsid++;
+ }
+ *p = '\0';
+
+ isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
+ sizeof(addrbuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, level,
+ "received NSID '%s' from %s", buf, addrbuf);
+
+ /* Clean up */
+ isc_mem_put(mctx, buf, buflen);
+ return (ISC_R_SUCCESS);
+}
+
+static void
+log_packet(dns_message_t *message, int level, isc_mem_t *mctx) {
+ isc_buffer_t buffer;
+ char *buf = NULL;
+ int len = 1024;
+ isc_result_t result;
+
+ if (! isc_log_wouldlog(dns_lctx, level))
+ return;
+
+ /*
+ * Note that these are multiline debug messages. We want a newline
+ * to appear in the log after each message.
+ */
+
+ do {
+ buf = isc_mem_get(mctx, len);
+ if (buf == NULL)
+ break;
+ isc_buffer_init(&buffer, buf, len);
+ result = dns_message_totext(message, &dns_master_style_debug,
+ 0, &buffer);
+ if (result == ISC_R_NOSPACE) {
+ isc_mem_put(mctx, buf, len);
+ len += 1024;
+ } else if (result == ISC_R_SUCCESS)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, level,
+ "received packet:\n%.*s",
+ (int)isc_buffer_usedlength(&buffer),
+ buf);
+ } while (result == ISC_R_NOSPACE);
+
+ if (buf != NULL)
+ isc_mem_put(mctx, buf, len);
+}
+
+static void
+resquery_response(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result = ISC_R_SUCCESS;
+ resquery_t *query = event->ev_arg;
+ dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
+ isc_boolean_t keep_trying, get_nameservers, resend;
+ isc_boolean_t truncated;
+ dns_message_t *message;
+ dns_rdataset_t *opt;
+ fetchctx_t *fctx;
+ dns_name_t *fname;
+ dns_fixedname_t foundname;
+ isc_stdtime_t now;
+ isc_time_t tnow, *finish;
+ dns_adbaddrinfo_t *addrinfo;
+ unsigned int options;
+ unsigned int findoptions;
+ isc_result_t broken_server;
+
+ REQUIRE(VALID_QUERY(query));
+ fctx = query->fctx;
+ options = query->options;
+ REQUIRE(VALID_FCTX(fctx));
+ REQUIRE(event->ev_type == DNS_EVENT_DISPATCH);
+
+ QTRACE("response");
+
+ if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == PF_INET)
+ inc_stats(fctx->res, dns_resstatscounter_responsev4);
+ else
+ inc_stats(fctx->res, dns_resstatscounter_responsev6);
+
+ (void)isc_timer_touch(fctx->timer);
+
+ keep_trying = ISC_FALSE;
+ broken_server = ISC_R_SUCCESS;
+ get_nameservers = ISC_FALSE;
+ resend = ISC_FALSE;
+ truncated = ISC_FALSE;
+ finish = NULL;
+
+ if (fctx->res->exiting) {
+ result = ISC_R_SHUTTINGDOWN;
+ goto done;
+ }
+
+ fctx->timeouts = 0;
+
+ /*
+ * XXXRTH We should really get the current time just once. We
+ * need a routine to convert from an isc_time_t to an
+ * isc_stdtime_t.
+ */
+ TIME_NOW(&tnow);
+ finish = &tnow;
+ isc_stdtime_get(&now);
+
+ /*
+ * Did the dispatcher have a problem?
+ */
+ if (devent->result != ISC_R_SUCCESS) {
+ if (devent->result == ISC_R_EOF &&
+ (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
+ /*
+ * The problem might be that they
+ * don't understand EDNS0. Turn it
+ * off and try again.
+ */
+ options |= DNS_FETCHOPT_NOEDNS0;
+ resend = ISC_TRUE;
+ /*
+ * Remember that they don't like EDNS0.
+ */
+ dns_adb_changeflags(fctx->adb,
+ query->addrinfo,
+ DNS_FETCHOPT_NOEDNS0,
+ DNS_FETCHOPT_NOEDNS0);
+ } else {
+ /*
+ * There's no hope for this query.
+ */
+ keep_trying = ISC_TRUE;
+
+ /*
+ * If this is a network error on an exclusive query
+ * socket, mark the server as bad so that we won't try
+ * it for this fetch again.
+ */
+ if (query->exclusivesocket &&
+ (devent->result == ISC_R_HOSTUNREACH ||
+ devent->result == ISC_R_NETUNREACH ||
+ devent->result == ISC_R_CONNREFUSED ||
+ devent->result == ISC_R_CANCELED)) {
+ broken_server = devent->result;
+ }
+ }
+ goto done;
+ }
+
+ message = fctx->rmessage;
+
+ if (query->tsig != NULL) {
+ result = dns_message_setquerytsig(message, query->tsig);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ }
+
+ if (query->tsigkey) {
+ result = dns_message_settsigkey(message, query->tsigkey);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ }
+
+ result = dns_message_parse(message, &devent->buffer, 0);
+ if (result != ISC_R_SUCCESS) {
+ switch (result) {
+ case ISC_R_UNEXPECTEDEND:
+ if (!message->question_ok ||
+ (message->flags & DNS_MESSAGEFLAG_TC) == 0 ||
+ (options & DNS_FETCHOPT_TCP) != 0) {
+ /*
+ * Either the message ended prematurely,
+ * and/or wasn't marked as being truncated,
+ * and/or this is a response to a query we
+ * sent over TCP. In all of these cases,
+ * something is wrong with the remote
+ * server and we don't want to retry using
+ * TCP.
+ */
+ if ((query->options & DNS_FETCHOPT_NOEDNS0)
+ == 0) {
+ /*
+ * The problem might be that they
+ * don't understand EDNS0. Turn it
+ * off and try again.
+ */
+ options |= DNS_FETCHOPT_NOEDNS0;
+ resend = ISC_TRUE;
+ /*
+ * Remember that they don't like EDNS0.
+ */
+ dns_adb_changeflags(
+ fctx->adb,
+ query->addrinfo,
+ DNS_FETCHOPT_NOEDNS0,
+ DNS_FETCHOPT_NOEDNS0);
+ inc_stats(fctx->res,
+ dns_resstatscounter_edns0fail);
+ } else {
+ broken_server = result;
+ keep_trying = ISC_TRUE;
+ }
+ goto done;
+ }
+ /*
+ * We defer retrying via TCP for a bit so we can
+ * check out this message further.
+ */
+ truncated = ISC_TRUE;
+ break;
+ case DNS_R_FORMERR:
+ if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
+ /*
+ * The problem might be that they
+ * don't understand EDNS0. Turn it
+ * off and try again.
+ */
+ options |= DNS_FETCHOPT_NOEDNS0;
+ resend = ISC_TRUE;
+ /*
+ * Remember that they don't like EDNS0.
+ */
+ dns_adb_changeflags(fctx->adb,
+ query->addrinfo,
+ DNS_FETCHOPT_NOEDNS0,
+ DNS_FETCHOPT_NOEDNS0);
+ inc_stats(fctx->res,
+ dns_resstatscounter_edns0fail);
+ } else {
+ broken_server = DNS_R_UNEXPECTEDRCODE;
+ keep_trying = ISC_TRUE;
+ }
+ goto done;
+ default:
+ /*
+ * Something bad has happened.
+ */
+ goto done;
+ }
+ }
+
+
+ /*
+ * Log the incoming packet.
+ */
+ log_packet(message, ISC_LOG_DEBUG(10), fctx->res->mctx);
+
+ /*
+ * Did we request NSID? If so, and if the response contains
+ * NSID data, log it at INFO level.
+ */
+ opt = dns_message_getopt(message);
+ if (opt != NULL && (query->options & DNS_FETCHOPT_WANTNSID) != 0)
+ log_nsid(opt, query, ISC_LOG_INFO, fctx->res->mctx);
+
+ /*
+ * If the message is signed, check the signature. If not, this
+ * returns success anyway.
+ */
+ result = dns_message_checksig(message, fctx->res->view);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+
+ /*
+ * The dispatcher should ensure we only get responses with QR set.
+ */
+ INSIST((message->flags & DNS_MESSAGEFLAG_QR) != 0);
+ /*
+ * INSIST() that the message comes from the place we sent it to,
+ * since the dispatch code should ensure this.
+ *
+ * INSIST() that the message id is correct (this should also be
+ * ensured by the dispatch code).
+ */
+
+
+ /*
+ * Deal with truncated responses by retrying using TCP.
+ */
+ if ((message->flags & DNS_MESSAGEFLAG_TC) != 0)
+ truncated = ISC_TRUE;
+
+ if (truncated) {
+ inc_stats(fctx->res, dns_resstatscounter_truncated);
+ if ((options & DNS_FETCHOPT_TCP) != 0) {
+ broken_server = DNS_R_TRUNCATEDTCP;
+ keep_trying = ISC_TRUE;
+ } else {
+ options |= DNS_FETCHOPT_TCP;
+ resend = ISC_TRUE;
+ }
+ goto done;
+ }
+
+ /*
+ * Is it a query response?
+ */
+ if (message->opcode != dns_opcode_query) {
+ /* XXXRTH Log */
+ broken_server = DNS_R_UNEXPECTEDOPCODE;
+ keep_trying = ISC_TRUE;
+ goto done;
+ }
+
+ /*
+ * Update statistics about erroneous responses.
+ */
+ if (message->rcode != dns_rcode_noerror) {
+ switch (message->rcode) {
+ case dns_rcode_nxdomain:
+ inc_stats(fctx->res, dns_resstatscounter_nxdomain);
+ break;
+ case dns_rcode_servfail:
+ inc_stats(fctx->res, dns_resstatscounter_servfail);
+ break;
+ case dns_rcode_formerr:
+ inc_stats(fctx->res, dns_resstatscounter_formerr);
+ break;
+ default:
+ inc_stats(fctx->res, dns_resstatscounter_othererror);
+ break;
+ }
+ }
+
+ /*
+ * Is the remote server broken, or does it dislike us?
+ */
+ if (message->rcode != dns_rcode_noerror &&
+ message->rcode != dns_rcode_nxdomain) {
+ if (((message->rcode == dns_rcode_formerr ||
+ message->rcode == dns_rcode_notimp) ||
+ (message->rcode == dns_rcode_servfail &&
+ dns_message_getopt(message) == NULL)) &&
+ (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
+ /*
+ * It's very likely they don't like EDNS0.
+ * If the response code is SERVFAIL, also check if the
+ * response contains an OPT RR and don't cache the
+ * failure since it can be returned for various other
+ * reasons.
+ *
+ * XXXRTH We should check if the question
+ * we're asking requires EDNS0, and
+ * if so, we should bail out.
+ */
+ options |= DNS_FETCHOPT_NOEDNS0;
+ resend = ISC_TRUE;
+ /*
+ * Remember that they don't like EDNS0.
+ */
+ if (message->rcode != dns_rcode_servfail)
+ dns_adb_changeflags(fctx->adb, query->addrinfo,
+ DNS_FETCHOPT_NOEDNS0,
+ DNS_FETCHOPT_NOEDNS0);
+ inc_stats(fctx->res, dns_resstatscounter_edns0fail);
+ } else if (message->rcode == dns_rcode_formerr) {
+ if (ISFORWARDER(query->addrinfo)) {
+ /*
+ * This forwarder doesn't understand us,
+ * but other forwarders might. Keep trying.
+ */
+ broken_server = DNS_R_REMOTEFORMERR;
+ keep_trying = ISC_TRUE;
+ } else {
+ /*
+ * The server doesn't understand us. Since
+ * all servers for a zone need similar
+ * capabilities, we assume that we will get
+ * FORMERR from all servers, and thus we
+ * cannot make any more progress with this
+ * fetch.
+ */
+ result = DNS_R_FORMERR;
+ }
+ } else if (message->rcode == dns_rcode_yxdomain) {
+ /*
+ * DNAME mapping failed because the new name
+ * was too long. There's no chance of success
+ * for this fetch.
+ */
+ result = DNS_R_YXDOMAIN;
+ } else if (message->rcode == dns_rcode_badvers) {
+ unsigned int flags, mask;
+ unsigned int version;
+
+ resend = ISC_TRUE;
+ version = (opt->ttl >> 16) & 0xff;
+ flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) |
+ DNS_FETCHOPT_EDNSVERSIONSET;
+ mask = DNS_FETCHOPT_EDNSVERSIONMASK |
+ DNS_FETCHOPT_EDNSVERSIONSET;
+ switch (version) {
+ case 0:
+ dns_adb_changeflags(fctx->adb, query->addrinfo,
+ flags, mask);
+ break;
+ default:
+ broken_server = DNS_R_BADVERS;
+ keep_trying = ISC_TRUE;
+ break;
+ }
+ } else {
+ /*
+ * XXXRTH log.
+ */
+ broken_server = DNS_R_UNEXPECTEDRCODE;
+ INSIST(broken_server != ISC_R_SUCCESS);
+ keep_trying = ISC_TRUE;
+ }
+ goto done;
+ }
+
+ /*
+ * Is the question the same as the one we asked?
+ */
+ result = same_question(fctx);
+ if (result != ISC_R_SUCCESS) {
+ /* XXXRTH Log */
+ if (result == DNS_R_FORMERR)
+ keep_trying = ISC_TRUE;
+ goto done;
+ }
+
+ /*
+ * Is the server lame?
+ */
+ if (fctx->res->lame_ttl != 0 && !ISFORWARDER(query->addrinfo) &&
+ is_lame(fctx)) {
+ inc_stats(fctx->res, dns_resstatscounter_lame);
+ log_lame(fctx, query->addrinfo);
+ result = dns_adb_marklame(fctx->adb, query->addrinfo,
+ &fctx->name, fctx->type,
+ now + fctx->res->lame_ttl);
+ if (result != ISC_R_SUCCESS)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_ERROR,
+ "could not mark server as lame: %s",
+ isc_result_totext(result));
+ broken_server = DNS_R_LAME;
+ keep_trying = ISC_TRUE;
+ goto done;
+ }
+
+ /*
+ * Enforce delegations only zones like NET and COM.
+ */
+ if (!ISFORWARDER(query->addrinfo) &&
+ dns_view_isdelegationonly(fctx->res->view, &fctx->domain) &&
+ !dns_name_equal(&fctx->domain, &fctx->name) &&
+ fix_mustbedelegationornxdomain(message, fctx)) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char domainbuf[DNS_NAME_FORMATSIZE];
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ char classbuf[64];
+ char typebuf[64];
+
+ dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
+ dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
+ dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));
+ dns_rdataclass_format(fctx->res->rdclass, classbuf,
+ sizeof(classbuf));
+ isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
+ sizeof(addrbuf));
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
+ "enforced delegation-only for '%s' (%s/%s/%s) "
+ "from %s",
+ domainbuf, namebuf, typebuf, classbuf, addrbuf);
+ }
+
+ if ((fctx->res->options & DNS_RESOLVER_CHECKNAMES) != 0)
+ checknames(message);
+
+ /*
+ * Clear cache bits.
+ */
+ fctx->attributes &= ~(FCTX_ATTR_WANTNCACHE | FCTX_ATTR_WANTCACHE);
+
+ /*
+ * Did we get any answers?
+ */
+ if (message->counts[DNS_SECTION_ANSWER] > 0 &&
+ (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.
+ */
+ if (fctx->type == dns_rdatatype_ns &&
+ (message->flags & DNS_MESSAGEFLAG_AA) == 0 &&
+ !ISFORWARDER(query->addrinfo))
+ {
+ result = noanswer_response(fctx, NULL, ISC_TRUE);
+ 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
+ * some more elaborate course of action.
+ */
+ broken_server = DNS_R_LAME;
+ keep_trying = ISC_TRUE;
+ goto done;
+ }
+ goto force_referral;
+ }
+ result = answer_response(fctx);
+ if (result != ISC_R_SUCCESS) {
+ if (result == DNS_R_FORMERR)
+ keep_trying = ISC_TRUE;
+ goto done;
+ }
+ } else if (message->counts[DNS_SECTION_AUTHORITY] > 0 ||
+ message->rcode == dns_rcode_noerror ||
+ message->rcode == dns_rcode_nxdomain) {
+ /*
+ * NXDOMAIN, NXRDATASET, or referral.
+ */
+ result = noanswer_response(fctx, NULL, ISC_FALSE);
+ if (result == DNS_R_CHASEDSSERVERS) {
+ } else if (result == DNS_R_DELEGATION) {
+ force_referral:
+ /*
+ * We don't have the answer, but we know a better
+ * place to look.
+ */
+ get_nameservers = ISC_TRUE;
+ keep_trying = ISC_TRUE;
+ /*
+ * We have a new set of name servers, and it
+ * has not experienced any restarts yet.
+ */
+ fctx->restarts = 0;
+ result = ISC_R_SUCCESS;
+ } else if (result != ISC_R_SUCCESS) {
+ /*
+ * Something has gone wrong.
+ */
+ if (result == DNS_R_FORMERR)
+ keep_trying = ISC_TRUE;
+ goto done;
+ }
+ } else {
+ /*
+ * The server is insane.
+ */
+ /* XXXRTH Log */
+ broken_server = DNS_R_UNEXPECTEDRCODE;
+ keep_trying = ISC_TRUE;
+ goto done;
+ }
+
+ /*
+ * Follow additional section data chains.
+ */
+ chase_additional(fctx);
+
+ /*
+ * Cache the cacheable parts of the message. This may also cause
+ * work to be queued to the DNSSEC validator.
+ */
+ if (WANTCACHE(fctx)) {
+ result = cache_message(fctx, query->addrinfo, now);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ }
+
+ /*
+ * Ncache the negatively cacheable parts of the message. This may
+ * also cause work to be queued to the DNSSEC validator.
+ */
+ if (WANTNCACHE(fctx)) {
+ dns_rdatatype_t covers;
+ if (message->rcode == dns_rcode_nxdomain)
+ covers = dns_rdatatype_any;
+ else
+ covers = fctx->type;
+
+ /*
+ * Cache any negative cache entries in the message.
+ */
+ result = ncache_message(fctx, query->addrinfo, covers, now);
+ }
+
+ done:
+ /*
+ * Remember the query's addrinfo, in case we need to mark the
+ * server as broken.
+ */
+ addrinfo = query->addrinfo;
+
+ /*
+ * Cancel the query.
+ *
+ * XXXRTH Don't cancel the query if waiting for validation?
+ */
+ fctx_cancelquery(&query, &devent, finish, ISC_FALSE);
+
+ if (keep_trying) {
+ if (result == DNS_R_FORMERR)
+ broken_server = DNS_R_FORMERR;
+ if (broken_server != ISC_R_SUCCESS) {
+ /*
+ * Add this server to the list of bad servers for
+ * this fctx.
+ */
+ add_bad(fctx, addrinfo, broken_server);
+ }
+
+ if (get_nameservers) {
+ dns_name_t *name;
+ dns_fixedname_init(&foundname);
+ fname = dns_fixedname_name(&foundname);
+ if (result != ISC_R_SUCCESS) {
+ fctx_done(fctx, DNS_R_SERVFAIL);
+ return;
+ }
+ findoptions = 0;
+ if (dns_rdatatype_atparent(fctx->type))
+ findoptions |= DNS_DBFIND_NOEXACT;
+ if ((options & DNS_FETCHOPT_UNSHARED) == 0)
+ name = &fctx->name;
+ else
+ name = &fctx->domain;
+ result = dns_view_findzonecut(fctx->res->view,
+ name, fname,
+ now, findoptions,
+ ISC_TRUE,
+ &fctx->nameservers,
+ NULL);
+ if (result != ISC_R_SUCCESS) {
+ FCTXTRACE("couldn't find a zonecut");
+ fctx_done(fctx, DNS_R_SERVFAIL);
+ return;
+ }
+ if (!dns_name_issubdomain(fname, &fctx->domain)) {
+ /*
+ * The best nameservers are now above our
+ * QDOMAIN.
+ */
+ FCTXTRACE("nameservers now above QDOMAIN");
+ fctx_done(fctx, DNS_R_SERVFAIL);
+ return;
+ }
+ dns_name_free(&fctx->domain,
+ fctx->res->buckets[fctx->bucketnum].mctx);
+ dns_name_init(&fctx->domain, NULL);
+ result = dns_name_dup(fname,
+ fctx->res->buckets[fctx->bucketnum].mctx,
+ &fctx->domain);
+ if (result != ISC_R_SUCCESS) {
+ fctx_done(fctx, DNS_R_SERVFAIL);
+ return;
+ }
+ fctx_cancelqueries(fctx, ISC_TRUE);
+ fctx_cleanupfinds(fctx);
+ fctx_cleanupaltfinds(fctx);
+ fctx_cleanupforwaddrs(fctx);
+ fctx_cleanupaltaddrs(fctx);
+ }
+ /*
+ * Try again.
+ */
+ fctx_try(fctx, !get_nameservers);
+ } else if (resend) {
+ /*
+ * Resend (probably with changed options).
+ */
+ FCTXTRACE("resend");
+ inc_stats(fctx->res, dns_resstatscounter_retry);
+ result = fctx_query(fctx, addrinfo, options);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result);
+ } else if (result == ISC_R_SUCCESS && !HAVE_ANSWER(fctx)) {
+ /*
+ * All has gone well so far, but we are waiting for the
+ * DNSSEC validator to validate the answer.
+ */
+ FCTXTRACE("wait for validator");
+ fctx_cancelqueries(fctx, ISC_TRUE);
+ /*
+ * We must not retransmit while the validator is working;
+ * it has references to the current rmessage.
+ */
+ result = fctx_stopidletimer(fctx);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result);
+ } else if (result == DNS_R_CHASEDSSERVERS) {
+ unsigned int n;
+ add_bad(fctx, addrinfo, result);
+ fctx_cancelqueries(fctx, ISC_TRUE);
+ fctx_cleanupfinds(fctx);
+ fctx_cleanupforwaddrs(fctx);
+
+ n = dns_name_countlabels(&fctx->name);
+ dns_name_getlabelsequence(&fctx->name, 1, n - 1, &fctx->nsname);
+
+ FCTXTRACE("suspending DS lookup to find parent's NS records");
+
+ result = dns_resolver_createfetch(fctx->res, &fctx->nsname,
+ dns_rdatatype_ns,
+ NULL, NULL, NULL, 0, task,
+ resume_dslookup, fctx,
+ &fctx->nsrrset, NULL,
+ &fctx->nsfetch);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result);
+ LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+ fctx->references++;
+ UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+ result = fctx_stopidletimer(fctx);
+ if (result != ISC_R_SUCCESS)
+ fctx_done(fctx, result);
+ } else {
+ /*
+ * We're done.
+ */
+ fctx_done(fctx, result);
+ }
+}
+
+
+/***
+ *** Resolver Methods
+ ***/
+
+static void
+destroy(dns_resolver_t *res) {
+ unsigned int i;
+ alternate_t *a;
+
+ REQUIRE(res->references == 0);
+ REQUIRE(!res->priming);
+ REQUIRE(res->primefetch == NULL);
+
+ RTRACE("destroy");
+
+ INSIST(res->nfctx == 0);
+
+ DESTROYLOCK(&res->primelock);
+ DESTROYLOCK(&res->nlock);
+ DESTROYLOCK(&res->lock);
+ for (i = 0; i < res->nbuckets; i++) {
+ INSIST(ISC_LIST_EMPTY(res->buckets[i].fctxs));
+ isc_task_shutdown(res->buckets[i].task);
+ isc_task_detach(&res->buckets[i].task);
+ DESTROYLOCK(&res->buckets[i].lock);
+ isc_mem_detach(&res->buckets[i].mctx);
+ }
+ isc_mem_put(res->mctx, res->buckets,
+ res->nbuckets * sizeof(fctxbucket_t));
+ if (res->dispatchv4 != NULL)
+ dns_dispatch_detach(&res->dispatchv4);
+ if (res->dispatchv6 != NULL)
+ dns_dispatch_detach(&res->dispatchv6);
+ while ((a = ISC_LIST_HEAD(res->alternates)) != NULL) {
+ ISC_LIST_UNLINK(res->alternates, a, link);
+ if (!a->isaddress)
+ dns_name_free(&a->_u._n.name, res->mctx);
+ isc_mem_put(res->mctx, a, sizeof(*a));
+ }
+ dns_resolver_reset_algorithms(res);
+ dns_resolver_resetmustbesecure(res);
+#if USE_ALGLOCK
+ isc_rwlock_destroy(&res->alglock);
+#endif
+#if USE_MBSLOCK
+ isc_rwlock_destroy(&res->mbslock);
+#endif
+ isc_timer_detach(&res->spillattimer);
+ res->magic = 0;
+ isc_mem_put(res->mctx, res, sizeof(*res));
+}
+
+static void
+send_shutdown_events(dns_resolver_t *res) {
+ isc_event_t *event, *next_event;
+ isc_task_t *etask;
+
+ /*
+ * Caller must be holding the resolver lock.
+ */
+
+ for (event = ISC_LIST_HEAD(res->whenshutdown);
+ event != NULL;
+ event = next_event) {
+ next_event = ISC_LIST_NEXT(event, ev_link);
+ ISC_LIST_UNLINK(res->whenshutdown, event, ev_link);
+ etask = event->ev_sender;
+ event->ev_sender = res;
+ isc_task_sendanddetach(&etask, &event);
+ }
+}
+
+static void
+empty_bucket(dns_resolver_t *res) {
+ RTRACE("empty_bucket");
+
+ LOCK(&res->lock);
+
+ INSIST(res->activebuckets > 0);
+ res->activebuckets--;
+ if (res->activebuckets == 0)
+ send_shutdown_events(res);
+
+ UNLOCK(&res->lock);
+}
+
+static void
+spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
+ dns_resolver_t *res = event->ev_arg;
+ isc_result_t result;
+ unsigned int count;
+ isc_boolean_t logit = ISC_FALSE;
+
+ REQUIRE(VALID_RESOLVER(res));
+
+ UNUSED(task);
+
+ LOCK(&res->lock);
+ INSIST(!res->exiting);
+ if (res->spillat > res->spillatmin) {
+ res->spillat--;
+ logit = ISC_TRUE;
+ }
+ if (res->spillat <= res->spillatmin) {
+ result = isc_timer_reset(res->spillattimer,
+ isc_timertype_inactive, NULL,
+ NULL, ISC_TRUE);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
+ count = res->spillat;
+ UNLOCK(&res->lock);
+ if (logit)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
+ "clients-per-query decreased to %u", count);
+
+ isc_event_free(&event);
+}
+
+isc_result_t
+dns_resolver_create(dns_view_t *view,
+ isc_taskmgr_t *taskmgr, unsigned int ntasks,
+ isc_socketmgr_t *socketmgr,
+ isc_timermgr_t *timermgr,
+ unsigned int options,
+ dns_dispatchmgr_t *dispatchmgr,
+ dns_dispatch_t *dispatchv4,
+ dns_dispatch_t *dispatchv6,
+ dns_resolver_t **resp)
+{
+ dns_resolver_t *res;
+ isc_result_t result = ISC_R_SUCCESS;
+ unsigned int i, buckets_created = 0;
+ isc_task_t *task = NULL;
+ char name[16];
+ unsigned dispattr;
+
+ /*
+ * Create a resolver.
+ */
+
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(ntasks > 0);
+ REQUIRE(resp != NULL && *resp == NULL);
+ REQUIRE(dispatchmgr != NULL);
+ REQUIRE(dispatchv4 != NULL || dispatchv6 != NULL);
+
+ res = isc_mem_get(view->mctx, sizeof(*res));
+ if (res == NULL)
+ return (ISC_R_NOMEMORY);
+ RTRACE("create");
+ res->mctx = view->mctx;
+ res->rdclass = view->rdclass;
+ res->socketmgr = socketmgr;
+ res->timermgr = timermgr;
+ res->taskmgr = taskmgr;
+ res->dispatchmgr = dispatchmgr;
+ res->view = view;
+ res->options = options;
+ res->lame_ttl = 0;
+ ISC_LIST_INIT(res->alternates);
+ res->udpsize = RECV_BUFFER_SIZE;
+ res->algorithms = NULL;
+ res->mustbesecure = NULL;
+ res->spillatmin = res->spillat = 10;
+ res->spillatmax = 100;
+ res->spillattimer = NULL;
+ res->zero_no_soa_ttl = ISC_FALSE;
+ res->ndisps = 0;
+ res->nextdisp = 0; /* meaningless at this point, but init it */
+ res->nbuckets = ntasks;
+ res->activebuckets = ntasks;
+ res->buckets = isc_mem_get(view->mctx,
+ ntasks * sizeof(fctxbucket_t));
+ if (res->buckets == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_res;
+ }
+ for (i = 0; i < ntasks; i++) {
+ result = isc_mutex_init(&res->buckets[i].lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_buckets;
+ res->buckets[i].task = NULL;
+ result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
+ if (result != ISC_R_SUCCESS) {
+ DESTROYLOCK(&res->buckets[i].lock);
+ goto cleanup_buckets;
+ }
+ res->buckets[i].mctx = NULL;
+ snprintf(name, sizeof(name), "res%u", i);
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * Use a separate memory context for each bucket to reduce
+ * contention among multiple threads. Do this only when
+ * enabling threads because it will be require more memory.
+ */
+ result = isc_mem_create(0, 0, &res->buckets[i].mctx);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_detach(&res->buckets[i].task);
+ DESTROYLOCK(&res->buckets[i].lock);
+ goto cleanup_buckets;
+ }
+ isc_mem_setname(res->buckets[i].mctx, name, NULL);
+#else
+ isc_mem_attach(view->mctx, &res->buckets[i].mctx);
+#endif
+ isc_task_setname(res->buckets[i].task, name, res);
+ ISC_LIST_INIT(res->buckets[i].fctxs);
+ res->buckets[i].exiting = ISC_FALSE;
+ buckets_created++;
+ }
+
+ res->dispatchv4 = NULL;
+ if (dispatchv4 != NULL) {
+ dns_dispatch_attach(dispatchv4, &res->dispatchv4);
+ dispattr = dns_dispatch_getattributes(dispatchv4);
+ res->exclusivev4 =
+ ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
+ }
+
+ res->dispatchv6 = NULL;
+ if (dispatchv6 != NULL) {
+ dns_dispatch_attach(dispatchv6, &res->dispatchv6);
+ dispattr = dns_dispatch_getattributes(dispatchv6);
+ res->exclusivev6 =
+ ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
+ }
+
+ res->references = 1;
+ res->exiting = ISC_FALSE;
+ res->frozen = ISC_FALSE;
+ ISC_LIST_INIT(res->whenshutdown);
+ res->priming = ISC_FALSE;
+ res->primefetch = NULL;
+ res->nfctx = 0;
+
+ result = isc_mutex_init(&res->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_dispatches;
+
+ result = isc_mutex_init(&res->nlock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lock;
+
+ result = isc_mutex_init(&res->primelock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_nlock;
+
+ task = NULL;
+ result = isc_task_create(taskmgr, 0, &task);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_primelock;
+
+ result = isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
+ task, spillattimer_countdown, res,
+ &res->spillattimer);
+ isc_task_detach(&task);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_primelock;
+
+#if USE_ALGLOCK
+ result = isc_rwlock_init(&res->alglock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_spillattimer;
+#endif
+#if USE_MBSLOCK
+ result = isc_rwlock_init(&res->mbslock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_alglock;
+#endif
+
+ res->magic = RES_MAGIC;
+
+ *resp = res;
+
+ return (ISC_R_SUCCESS);
+
+#if USE_MBSLOCK
+ cleanup_alglock:
+#if USE_ALGLOCK
+ isc_rwlock_destroy(&res->alglock);
+#endif
+#endif
+#if USE_ALGLOCK || USE_MBSLOCK
+ cleanup_spillattimer:
+ isc_timer_detach(&res->spillattimer);
+#endif
+
+ cleanup_primelock:
+ DESTROYLOCK(&res->primelock);
+
+ cleanup_nlock:
+ DESTROYLOCK(&res->nlock);
+
+ cleanup_lock:
+ DESTROYLOCK(&res->lock);
+
+ cleanup_dispatches:
+ if (res->dispatchv6 != NULL)
+ dns_dispatch_detach(&res->dispatchv6);
+ if (res->dispatchv4 != NULL)
+ dns_dispatch_detach(&res->dispatchv4);
+
+ cleanup_buckets:
+ for (i = 0; i < buckets_created; i++) {
+ isc_mem_detach(&res->buckets[i].mctx);
+ DESTROYLOCK(&res->buckets[i].lock);
+ isc_task_shutdown(res->buckets[i].task);
+ isc_task_detach(&res->buckets[i].task);
+ }
+ isc_mem_put(view->mctx, res->buckets,
+ res->nbuckets * sizeof(fctxbucket_t));
+
+ cleanup_res:
+ isc_mem_put(view->mctx, res, sizeof(*res));
+
+ return (result);
+}
+
+static void
+prime_done(isc_task_t *task, isc_event_t *event) {
+ dns_resolver_t *res;
+ dns_fetchevent_t *fevent;
+ dns_fetch_t *fetch;
+ dns_db_t *db = NULL;
+
+ REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
+ fevent = (dns_fetchevent_t *)event;
+ res = event->ev_arg;
+ REQUIRE(VALID_RESOLVER(res));
+
+ UNUSED(task);
+
+ LOCK(&res->lock);
+
+ INSIST(res->priming);
+ res->priming = ISC_FALSE;
+ LOCK(&res->primelock);
+ fetch = res->primefetch;
+ res->primefetch = NULL;
+ UNLOCK(&res->primelock);
+
+ UNLOCK(&res->lock);
+
+ if (fevent->result == ISC_R_SUCCESS &&
+ res->view->cache != NULL && res->view->hints != NULL) {
+ dns_cache_attachdb(res->view->cache, &db);
+ dns_root_checkhints(res->view, res->view->hints, db);
+ dns_db_detach(&db);
+ }
+
+ if (fevent->node != NULL)
+ dns_db_detachnode(fevent->db, &fevent->node);
+ if (fevent->db != NULL)
+ dns_db_detach(&fevent->db);
+ if (dns_rdataset_isassociated(fevent->rdataset))
+ dns_rdataset_disassociate(fevent->rdataset);
+ INSIST(fevent->sigrdataset == NULL);
+
+ isc_mem_put(res->mctx, fevent->rdataset, sizeof(*fevent->rdataset));
+
+ isc_event_free(&event);
+ dns_resolver_destroyfetch(&fetch);
+}
+
+void
+dns_resolver_prime(dns_resolver_t *res) {
+ isc_boolean_t want_priming = ISC_FALSE;
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+
+ REQUIRE(VALID_RESOLVER(res));
+ REQUIRE(res->frozen);
+
+ RTRACE("dns_resolver_prime");
+
+ LOCK(&res->lock);
+
+ if (!res->exiting && !res->priming) {
+ INSIST(res->primefetch == NULL);
+ res->priming = ISC_TRUE;
+ want_priming = ISC_TRUE;
+ }
+
+ UNLOCK(&res->lock);
+
+ if (want_priming) {
+ /*
+ * To avoid any possible recursive locking problems, we
+ * start the priming fetch like any other fetch, and holding
+ * no resolver locks. No one else will try to start it
+ * because we're the ones who set res->priming to true.
+ * Any other callers of dns_resolver_prime() while we're
+ * running will see that res->priming is already true and
+ * do nothing.
+ */
+ RTRACE("priming");
+ rdataset = isc_mem_get(res->mctx, sizeof(*rdataset));
+ if (rdataset == NULL) {
+ LOCK(&res->lock);
+ INSIST(res->priming);
+ INSIST(res->primefetch == NULL);
+ res->priming = ISC_FALSE;
+ UNLOCK(&res->lock);
+ return;
+ }
+ dns_rdataset_init(rdataset);
+ LOCK(&res->primelock);
+ result = dns_resolver_createfetch(res, dns_rootname,
+ dns_rdatatype_ns,
+ NULL, NULL, NULL, 0,
+ res->buckets[0].task,
+ prime_done,
+ res, rdataset, NULL,
+ &res->primefetch);
+ UNLOCK(&res->primelock);
+ if (result != ISC_R_SUCCESS) {
+ LOCK(&res->lock);
+ INSIST(res->priming);
+ res->priming = ISC_FALSE;
+ UNLOCK(&res->lock);
+ }
+ }
+}
+
+void
+dns_resolver_freeze(dns_resolver_t *res) {
+
+ /*
+ * Freeze resolver.
+ */
+
+ REQUIRE(VALID_RESOLVER(res));
+ REQUIRE(!res->frozen);
+
+ res->frozen = ISC_TRUE;
+}
+
+void
+dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
+ REQUIRE(VALID_RESOLVER(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ RRTRACE(source, "attach");
+ LOCK(&source->lock);
+ REQUIRE(!source->exiting);
+
+ INSIST(source->references > 0);
+ source->references++;
+ INSIST(source->references != 0);
+ UNLOCK(&source->lock);
+
+ *targetp = source;
+}
+
+void
+dns_resolver_whenshutdown(dns_resolver_t *res, isc_task_t *task,
+ isc_event_t **eventp)
+{
+ isc_task_t *clone;
+ isc_event_t *event;
+
+ REQUIRE(VALID_RESOLVER(res));
+ REQUIRE(eventp != NULL);
+
+ event = *eventp;
+ *eventp = NULL;
+
+ LOCK(&res->lock);
+
+ if (res->exiting && res->activebuckets == 0) {
+ /*
+ * We're already shutdown. Send the event.
+ */
+ event->ev_sender = res;
+ isc_task_send(task, &event);
+ } else {
+ clone = NULL;
+ isc_task_attach(task, &clone);
+ event->ev_sender = clone;
+ ISC_LIST_APPEND(res->whenshutdown, event, ev_link);
+ }
+
+ UNLOCK(&res->lock);
+}
+
+void
+dns_resolver_shutdown(dns_resolver_t *res) {
+ unsigned int i;
+ fetchctx_t *fctx;
+ isc_socket_t *sock;
+ isc_result_t result;
+
+ REQUIRE(VALID_RESOLVER(res));
+
+ RTRACE("shutdown");
+
+ LOCK(&res->lock);
+
+ if (!res->exiting) {
+ RTRACE("exiting");
+ res->exiting = ISC_TRUE;
+
+ for (i = 0; i < res->nbuckets; i++) {
+ LOCK(&res->buckets[i].lock);
+ for (fctx = ISC_LIST_HEAD(res->buckets[i].fctxs);
+ fctx != NULL;
+ fctx = ISC_LIST_NEXT(fctx, link))
+ fctx_shutdown(fctx);
+ if (res->dispatchv4 != NULL && !res->exclusivev4) {
+ sock = dns_dispatch_getsocket(res->dispatchv4);
+ isc_socket_cancel(sock, res->buckets[i].task,
+ ISC_SOCKCANCEL_ALL);
+ }
+ if (res->dispatchv6 != NULL && !res->exclusivev6) {
+ sock = dns_dispatch_getsocket(res->dispatchv6);
+ isc_socket_cancel(sock, res->buckets[i].task,
+ ISC_SOCKCANCEL_ALL);
+ }
+ res->buckets[i].exiting = ISC_TRUE;
+ if (ISC_LIST_EMPTY(res->buckets[i].fctxs)) {
+ INSIST(res->activebuckets > 0);
+ res->activebuckets--;
+ }
+ UNLOCK(&res->buckets[i].lock);
+ }
+ if (res->activebuckets == 0)
+ send_shutdown_events(res);
+ result = isc_timer_reset(res->spillattimer,
+ isc_timertype_inactive, NULL,
+ NULL, ISC_TRUE);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ }
+
+ UNLOCK(&res->lock);
+}
+
+void
+dns_resolver_detach(dns_resolver_t **resp) {
+ dns_resolver_t *res;
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(resp != NULL);
+ res = *resp;
+ REQUIRE(VALID_RESOLVER(res));
+
+ RTRACE("detach");
+
+ LOCK(&res->lock);
+
+ INSIST(res->references > 0);
+ res->references--;
+ if (res->references == 0) {
+ INSIST(res->exiting && res->activebuckets == 0);
+ need_destroy = ISC_TRUE;
+ }
+
+ UNLOCK(&res->lock);
+
+ if (need_destroy)
+ destroy(res);
+
+ *resp = NULL;
+}
+
+static inline isc_boolean_t
+fctx_match(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
+ unsigned int options)
+{
+ if (fctx->type != type || fctx->options != options)
+ return (ISC_FALSE);
+ return (dns_name_equal(&fctx->name, name));
+}
+
+static inline void
+log_fetch(dns_name_t *name, dns_rdatatype_t type) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ int level = ISC_LOG_DEBUG(1);
+
+ if (! isc_log_wouldlog(dns_lctx, level))
+ return;
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ DNS_LOGMODULE_RESOLVER, level,
+ "createfetch: %s %s", namebuf, typebuf);
+}
+
+isc_result_t
+dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_name_t *domain, dns_rdataset_t *nameservers,
+ dns_forwarders_t *forwarders,
+ unsigned int options, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset,
+ dns_fetch_t **fetchp)
+{
+ return (dns_resolver_createfetch2(res, name, type, domain,
+ nameservers, forwarders, NULL, 0,
+ options, task, action, arg,
+ rdataset, sigrdataset, fetchp));
+}
+
+isc_result_t
+dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_name_t *domain, dns_rdataset_t *nameservers,
+ dns_forwarders_t *forwarders,
+ isc_sockaddr_t *client, dns_messageid_t id,
+ unsigned int options, isc_task_t *task,
+ isc_taskaction_t action, void *arg,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset,
+ dns_fetch_t **fetchp)
+{
+ dns_fetch_t *fetch;
+ fetchctx_t *fctx = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ unsigned int bucketnum;
+ isc_boolean_t new_fctx = ISC_FALSE;
+ isc_event_t *event;
+ unsigned int count = 0;
+ unsigned int spillat;
+ unsigned int spillatmin;
+
+ UNUSED(forwarders);
+
+ REQUIRE(VALID_RESOLVER(res));
+ REQUIRE(res->frozen);
+ /* XXXRTH Check for meta type */
+ if (domain != NULL) {
+ REQUIRE(DNS_RDATASET_VALID(nameservers));
+ REQUIRE(nameservers->type == dns_rdatatype_ns);
+ } else
+ REQUIRE(nameservers == NULL);
+ REQUIRE(forwarders == NULL);
+ REQUIRE(!dns_rdataset_isassociated(rdataset));
+ REQUIRE(sigrdataset == NULL ||
+ !dns_rdataset_isassociated(sigrdataset));
+ REQUIRE(fetchp != NULL && *fetchp == NULL);
+
+ log_fetch(name, type);
+
+ /*
+ * XXXRTH use a mempool?
+ */
+ fetch = isc_mem_get(res->mctx, sizeof(*fetch));
+ if (fetch == NULL)
+ return (ISC_R_NOMEMORY);
+
+ bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets;
+
+ LOCK(&res->lock);
+ spillat = res->spillat;
+ spillatmin = res->spillatmin;
+ UNLOCK(&res->lock);
+ LOCK(&res->buckets[bucketnum].lock);
+
+ if (res->buckets[bucketnum].exiting) {
+ result = ISC_R_SHUTTINGDOWN;
+ goto unlock;
+ }
+
+ if ((options & DNS_FETCHOPT_UNSHARED) == 0) {
+ for (fctx = ISC_LIST_HEAD(res->buckets[bucketnum].fctxs);
+ fctx != NULL;
+ fctx = ISC_LIST_NEXT(fctx, link)) {
+ if (fctx_match(fctx, name, type, options))
+ break;
+ }
+ }
+
+ /*
+ * Is this a duplicate?
+ */
+ if (fctx != NULL && client != NULL) {
+ dns_fetchevent_t *fevent;
+ for (fevent = ISC_LIST_HEAD(fctx->events);
+ fevent != NULL;
+ fevent = ISC_LIST_NEXT(fevent, ev_link)) {
+ if (fevent->client != NULL && fevent->id == id &&
+ isc_sockaddr_equal(fevent->client, client)) {
+ result = DNS_R_DUPLICATE;
+ goto unlock;
+ }
+ count++;
+ }
+ }
+ if (count >= spillatmin && spillatmin != 0) {
+ INSIST(fctx != NULL);
+ if (count >= spillat)
+ fctx->spilled = ISC_TRUE;
+ if (fctx->spilled) {
+ result = DNS_R_DROP;
+ goto unlock;
+ }
+ }
+
+ /*
+ * If we didn't have a fetch, would attach to a done fetch, this
+ * fetch has already cloned its results, or if the fetch has gone
+ * "idle" (no one was interested in it), we need to start a new
+ * fetch instead of joining with the existing one.
+ */
+ if (fctx == NULL ||
+ fctx->state == fetchstate_done ||
+ fctx->cloned ||
+ ISC_LIST_EMPTY(fctx->events)) {
+ fctx = NULL;
+ result = fctx_create(res, name, type, domain, nameservers,
+ options, bucketnum, &fctx);
+ if (result != ISC_R_SUCCESS)
+ goto unlock;
+ new_fctx = ISC_TRUE;
+ }
+
+ result = fctx_join(fctx, task, client, id, action, arg,
+ rdataset, sigrdataset, fetch);
+ if (new_fctx) {
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Launch this fctx.
+ */
+ event = &fctx->control_event;
+ ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,
+ DNS_EVENT_FETCHCONTROL,
+ fctx_start, fctx, NULL,
+ NULL, NULL);
+ isc_task_send(res->buckets[bucketnum].task, &event);
+ } else {
+ /*
+ * We don't care about the result of fctx_destroy()
+ * since we know we're not exiting.
+ */
+ (void)fctx_destroy(fctx);
+ }
+ }
+
+ unlock:
+ UNLOCK(&res->buckets[bucketnum].lock);
+
+ if (result == ISC_R_SUCCESS) {
+ FTRACE("created");
+ *fetchp = fetch;
+ } else
+ isc_mem_put(res->mctx, fetch, sizeof(*fetch));
+
+ return (result);
+}
+
+void
+dns_resolver_cancelfetch(dns_fetch_t *fetch) {
+ fetchctx_t *fctx;
+ dns_resolver_t *res;
+ dns_fetchevent_t *event, *next_event;
+ isc_task_t *etask;
+
+ REQUIRE(DNS_FETCH_VALID(fetch));
+ fctx = fetch->private;
+ REQUIRE(VALID_FCTX(fctx));
+ res = fctx->res;
+
+ FTRACE("cancelfetch");
+
+ LOCK(&res->buckets[fctx->bucketnum].lock);
+
+ /*
+ * Find the completion event for this fetch (as opposed
+ * to those for other fetches that have joined the same
+ * fctx) and send it with result = ISC_R_CANCELED.
+ */
+ event = NULL;
+ if (fctx->state != fetchstate_done) {
+ for (event = ISC_LIST_HEAD(fctx->events);
+ event != NULL;
+ event = next_event) {
+ next_event = ISC_LIST_NEXT(event, ev_link);
+ if (event->fetch == fetch) {
+ ISC_LIST_UNLINK(fctx->events, event, ev_link);
+ break;
+ }
+ }
+ }
+ if (event != NULL) {
+ etask = event->ev_sender;
+ event->ev_sender = fctx;
+ event->result = ISC_R_CANCELED;
+ isc_task_sendanddetach(&etask, ISC_EVENT_PTR(&event));
+ }
+ /*
+ * The fctx continues running even if no fetches remain;
+ * the answer is still cached.
+ */
+
+ UNLOCK(&res->buckets[fctx->bucketnum].lock);
+}
+
+void
+dns_resolver_destroyfetch(dns_fetch_t **fetchp) {
+ dns_fetch_t *fetch;
+ dns_resolver_t *res;
+ dns_fetchevent_t *event, *next_event;
+ fetchctx_t *fctx;
+ unsigned int bucketnum;
+ isc_boolean_t bucket_empty = ISC_FALSE;
+
+ REQUIRE(fetchp != NULL);
+ fetch = *fetchp;
+ REQUIRE(DNS_FETCH_VALID(fetch));
+ fctx = fetch->private;
+ REQUIRE(VALID_FCTX(fctx));
+ res = fctx->res;
+
+ FTRACE("destroyfetch");
+
+ bucketnum = fctx->bucketnum;
+ LOCK(&res->buckets[bucketnum].lock);
+
+ /*
+ * Sanity check: the caller should have gotten its event before
+ * trying to destroy the fetch.
+ */
+ event = NULL;
+ if (fctx->state != fetchstate_done) {
+ for (event = ISC_LIST_HEAD(fctx->events);
+ event != NULL;
+ event = next_event) {
+ next_event = ISC_LIST_NEXT(event, ev_link);
+ RUNTIME_CHECK(event->fetch != fetch);
+ }
+ }
+
+ INSIST(fctx->references > 0);
+ fctx->references--;
+ if (fctx->references == 0) {
+ /*
+ * No one cares about the result of this fetch anymore.
+ */
+ if (fctx->pending == 0 && fctx->nqueries == 0 &&
+ ISC_LIST_EMPTY(fctx->validators) &&
+ SHUTTINGDOWN(fctx)) {
+ /*
+ * This fctx is already shutdown; we were just
+ * waiting for the last reference to go away.
+ */
+ bucket_empty = fctx_destroy(fctx);
+ } else {
+ /*
+ * Initiate shutdown.
+ */
+ fctx_shutdown(fctx);
+ }
+ }
+
+ UNLOCK(&res->buckets[bucketnum].lock);
+
+ isc_mem_put(res->mctx, fetch, sizeof(*fetch));
+ *fetchp = NULL;
+
+ if (bucket_empty)
+ empty_bucket(res);
+}
+
+dns_dispatchmgr_t *
+dns_resolver_dispatchmgr(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ return (resolver->dispatchmgr);
+}
+
+dns_dispatch_t *
+dns_resolver_dispatchv4(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ return (resolver->dispatchv4);
+}
+
+dns_dispatch_t *
+dns_resolver_dispatchv6(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ return (resolver->dispatchv6);
+}
+
+isc_socketmgr_t *
+dns_resolver_socketmgr(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ return (resolver->socketmgr);
+}
+
+isc_taskmgr_t *
+dns_resolver_taskmgr(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ return (resolver->taskmgr);
+}
+
+isc_uint32_t
+dns_resolver_getlamettl(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ return (resolver->lame_ttl);
+}
+
+void
+dns_resolver_setlamettl(dns_resolver_t *resolver, isc_uint32_t lame_ttl) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ resolver->lame_ttl = lame_ttl;
+}
+
+unsigned int
+dns_resolver_nrunning(dns_resolver_t *resolver) {
+ unsigned int n;
+ LOCK(&resolver->nlock);
+ n = resolver->nfctx;
+ UNLOCK(&resolver->nlock);
+ return (n);
+}
+
+isc_result_t
+dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
+ dns_name_t *name, in_port_t port) {
+ alternate_t *a;
+ isc_result_t result;
+
+ REQUIRE(VALID_RESOLVER(resolver));
+ REQUIRE(!resolver->frozen);
+ REQUIRE((alt == NULL) ^ (name == NULL));
+
+ a = isc_mem_get(resolver->mctx, sizeof(*a));
+ if (a == NULL)
+ return (ISC_R_NOMEMORY);
+ if (alt != NULL) {
+ a->isaddress = ISC_TRUE;
+ a->_u.addr = *alt;
+ } else {
+ a->isaddress = ISC_FALSE;
+ a->_u._n.port = port;
+ dns_name_init(&a->_u._n.name, NULL);
+ result = dns_name_dup(name, resolver->mctx, &a->_u._n.name);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(resolver->mctx, a, sizeof(*a));
+ return (result);
+ }
+ }
+ ISC_LINK_INIT(a, link);
+ ISC_LIST_APPEND(resolver->alternates, a, link);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_resolver_setudpsize(dns_resolver_t *resolver, isc_uint16_t udpsize) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ resolver->udpsize = udpsize;
+}
+
+isc_uint16_t
+dns_resolver_getudpsize(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+ return (resolver->udpsize);
+}
+
+static void
+free_algorithm(void *node, void *arg) {
+ unsigned char *algorithms = node;
+ isc_mem_t *mctx = arg;
+
+ isc_mem_put(mctx, algorithms, *algorithms);
+}
+
+void
+dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
+
+ REQUIRE(VALID_RESOLVER(resolver));
+
+#if USE_ALGLOCK
+ RWLOCK(&resolver->alglock, isc_rwlocktype_write);
+#endif
+ if (resolver->algorithms != NULL)
+ dns_rbt_destroy(&resolver->algorithms);
+#if USE_ALGLOCK
+ RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
+#endif
+}
+
+isc_result_t
+dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
+ unsigned int alg)
+{
+ unsigned int len, mask;
+ unsigned char *new;
+ unsigned char *algorithms;
+ isc_result_t result;
+ dns_rbtnode_t *node = NULL;
+
+ REQUIRE(VALID_RESOLVER(resolver));
+ if (alg > 255)
+ return (ISC_R_RANGE);
+
+#if USE_ALGLOCK
+ RWLOCK(&resolver->alglock, isc_rwlocktype_write);
+#endif
+ if (resolver->algorithms == NULL) {
+ result = dns_rbt_create(resolver->mctx, free_algorithm,
+ resolver->mctx, &resolver->algorithms);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+
+ len = alg/8 + 2;
+ mask = 1 << (alg%8);
+
+ result = dns_rbt_addnode(resolver->algorithms, name, &node);
+
+ if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
+ algorithms = node->data;
+ if (algorithms == NULL || len > *algorithms) {
+ new = isc_mem_get(resolver->mctx, len);
+ if (new == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ memset(new, 0, len);
+ if (algorithms != NULL)
+ memcpy(new, algorithms, *algorithms);
+ new[len-1] |= mask;
+ *new = len;
+ node->data = new;
+ if (algorithms != NULL)
+ isc_mem_put(resolver->mctx, algorithms,
+ *algorithms);
+ } else
+ algorithms[len-1] |= mask;
+ }
+ result = ISC_R_SUCCESS;
+ cleanup:
+#if USE_ALGLOCK
+ RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
+#endif
+ return (result);
+}
+
+isc_boolean_t
+dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
+ unsigned int alg)
+{
+ unsigned int len, mask;
+ unsigned char *algorithms;
+ void *data = NULL;
+ isc_result_t result;
+ isc_boolean_t found = ISC_FALSE;
+
+ REQUIRE(VALID_RESOLVER(resolver));
+
+#if USE_ALGLOCK
+ RWLOCK(&resolver->alglock, isc_rwlocktype_read);
+#endif
+ if (resolver->algorithms == NULL)
+ goto unlock;
+ result = dns_rbt_findname(resolver->algorithms, name, 0, NULL, &data);
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
+ len = alg/8 + 2;
+ mask = 1 << (alg%8);
+ algorithms = data;
+ if (len <= *algorithms && (algorithms[len-1] & mask) != 0)
+ found = ISC_TRUE;
+ }
+ unlock:
+#if USE_ALGLOCK
+ RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
+#endif
+ if (found)
+ return (ISC_FALSE);
+ return (dst_algorithm_supported(alg));
+}
+
+isc_boolean_t
+dns_resolver_digest_supported(dns_resolver_t *resolver, unsigned int digest) {
+
+ UNUSED(resolver);
+ return (dns_ds_digest_supported(digest));
+}
+
+void
+dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
+
+ REQUIRE(VALID_RESOLVER(resolver));
+
+#if USE_MBSLOCK
+ RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
+#endif
+ if (resolver->mustbesecure != NULL)
+ dns_rbt_destroy(&resolver->mustbesecure);
+#if USE_MBSLOCK
+ RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
+#endif
+}
+
+static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
+
+isc_result_t
+dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
+ isc_boolean_t value)
+{
+ isc_result_t result;
+
+ REQUIRE(VALID_RESOLVER(resolver));
+
+#if USE_MBSLOCK
+ RWLOCK(&resolver->mbslock, isc_rwlocktype_write);
+#endif
+ if (resolver->mustbesecure == NULL) {
+ result = dns_rbt_create(resolver->mctx, NULL, NULL,
+ &resolver->mustbesecure);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ result = dns_rbt_addname(resolver->mustbesecure, name,
+ value ? &yes : &no);
+ cleanup:
+#if USE_MBSLOCK
+ RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
+#endif
+ return (result);
+}
+
+isc_boolean_t
+dns_resolver_getmustbesecure(dns_resolver_t *resolver, dns_name_t *name) {
+ void *data = NULL;
+ isc_boolean_t value = ISC_FALSE;
+ isc_result_t result;
+
+ REQUIRE(VALID_RESOLVER(resolver));
+
+#if USE_MBSLOCK
+ RWLOCK(&resolver->mbslock, isc_rwlocktype_read);
+#endif
+ if (resolver->mustbesecure == NULL)
+ goto unlock;
+ result = dns_rbt_findname(resolver->mustbesecure, name, 0, NULL, &data);
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+ value = *(isc_boolean_t*)data;
+ unlock:
+#if USE_MBSLOCK
+ RWUNLOCK(&resolver->mbslock, isc_rwlocktype_read);
+#endif
+ return (value);
+}
+
+void
+dns_resolver_getclientsperquery(dns_resolver_t *resolver, isc_uint32_t *cur,
+ isc_uint32_t *min, isc_uint32_t *max)
+{
+ REQUIRE(VALID_RESOLVER(resolver));
+
+ LOCK(&resolver->lock);
+ if (cur != NULL)
+ *cur = resolver->spillat;
+ if (min != NULL)
+ *min = resolver->spillatmin;
+ if (max != NULL)
+ *max = resolver->spillatmax;
+ UNLOCK(&resolver->lock);
+}
+
+void
+dns_resolver_setclientsperquery(dns_resolver_t *resolver, isc_uint32_t min,
+ isc_uint32_t max)
+{
+ REQUIRE(VALID_RESOLVER(resolver));
+
+ LOCK(&resolver->lock);
+ resolver->spillatmin = resolver->spillat = min;
+ resolver->spillatmax = max;
+ UNLOCK(&resolver->lock);
+}
+
+isc_boolean_t
+dns_resolver_getzeronosoattl(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+
+ return (resolver->zero_no_soa_ttl);
+}
+
+void
+dns_resolver_setzeronosoattl(dns_resolver_t *resolver, isc_boolean_t state) {
+ REQUIRE(VALID_RESOLVER(resolver));
+
+ resolver->zero_no_soa_ttl = state;
+}
+
+unsigned int
+dns_resolver_getoptions(dns_resolver_t *resolver) {
+ REQUIRE(VALID_RESOLVER(resolver));
+
+ return (resolver->options);
+}
diff --git a/lib/dns/result.c b/lib/dns/result.c
new file mode 100644
index 0000000..54c70e0
--- /dev/null
+++ b/lib/dns/result.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: result.c,v 1.125 2008/09/25 04:02:38 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/once.h>
+#include <isc/util.h>
+
+#include <dns/result.h>
+#include <dns/lib.h>
+
+static const char *text[DNS_R_NRESULTS] = {
+ "label too long", /*%< 0 DNS_R_LABELTOOLONG */
+ "bad escape", /*%< 1 DNS_R_BADESCAPE */
+ /*!
+ * Note that DNS_R_BADBITSTRING and DNS_R_BITSTRINGTOOLONG are
+ * deprecated.
+ */
+ "bad bitstring", /*%< 2 DNS_R_BADBITSTRING */
+ "bitstring too long", /*%< 3 DNS_R_BITSTRINGTOOLONG */
+ "empty label", /*%< 4 DNS_R_EMPTYLABEL */
+
+ "bad dotted quad", /*%< 5 DNS_R_BADDOTTEDQUAD */
+ "invalid NS owner name (wildcard)", /*%< 6 DNS_R_INVALIDNS */
+ "unknown class/type", /*%< 7 DNS_R_UNKNOWN */
+ "bad label type", /*%< 8 DNS_R_BADLABELTYPE */
+ "bad compression pointer", /*%< 9 DNS_R_BADPOINTER */
+
+ "too many hops", /*%< 10 DNS_R_TOOMANYHOPS */
+ "disallowed (by application policy)", /*%< 11 DNS_R_DISALLOWED */
+ "extra input text", /*%< 12 DNS_R_EXTRATOKEN */
+ "extra input data", /*%< 13 DNS_R_EXTRADATA */
+ "text too long", /*%< 14 DNS_R_TEXTTOOLONG */
+
+ "not at top of zone", /*%< 15 DNS_R_NOTZONETOP */
+ "syntax error", /*%< 16 DNS_R_SYNTAX */
+ "bad checksum", /*%< 17 DNS_R_BADCKSUM */
+ "bad IPv6 address", /*%< 18 DNS_R_BADAAAA */
+ "no owner", /*%< 19 DNS_R_NOOWNER */
+
+ "no ttl", /*%< 20 DNS_R_NOTTL */
+ "bad class", /*%< 21 DNS_R_BADCLASS */
+ "name too long", /*%< 22 DNS_R_NAMETOOLONG */
+ "partial match", /*%< 23 DNS_R_PARTIALMATCH */
+ "new origin", /*%< 24 DNS_R_NEWORIGIN */
+
+ "unchanged", /*%< 25 DNS_R_UNCHANGED */
+ "bad ttl", /*%< 26 DNS_R_BADTTL */
+ "more data needed/to be rendered", /*%< 27 DNS_R_NOREDATA */
+ "continue", /*%< 28 DNS_R_CONTINUE */
+ "delegation", /*%< 29 DNS_R_DELEGATION */
+
+ "glue", /*%< 30 DNS_R_GLUE */
+ "dname", /*%< 31 DNS_R_DNAME */
+ "cname", /*%< 32 DNS_R_CNAME */
+ "bad database", /*%< 33 DNS_R_BADDB */
+ "zonecut", /*%< 34 DNS_R_ZONECUT */
+
+ "bad zone", /*%< 35 DNS_R_BADZONE */
+ "more data", /*%< 36 DNS_R_MOREDATA */
+ "up to date", /*%< 37 DNS_R_UPTODATE */
+ "tsig verify failure", /*%< 38 DNS_R_TSIGVERIFYFAILURE */
+ "tsig indicates error", /*%< 39 DNS_R_TSIGERRORSET */
+
+ "RRSIG failed to verify", /*%< 40 DNS_R_SIGINVALID */
+ "RRSIG has expired", /*%< 41 DNS_R_SIGEXPIRED */
+ "RRSIG validity period has not begun", /*%< 42 DNS_R_SIGFUTURE */
+ "key is unauthorized to sign data", /*%< 43 DNS_R_KEYUNAUTHORIZED */
+ "invalid time", /*%< 44 DNS_R_INVALIDTIME */
+
+ "expected a TSIG or SIG(0)", /*%< 45 DNS_R_EXPECTEDTSIG */
+ "did not expect a TSIG or SIG(0)", /*%< 46 DNS_R_UNEXPECTEDTSIG */
+ "TKEY is unacceptable", /*%< 47 DNS_R_INVALIDTKEY */
+ "hint", /*%< 48 DNS_R_HINT */
+ "drop", /*%< 49 DNS_R_DROP */
+
+ "zone not loaded", /*%< 50 DNS_R_NOTLOADED */
+ "ncache nxdomain", /*%< 51 DNS_R_NCACHENXDOMAIN */
+ "ncache nxrrset", /*%< 52 DNS_R_NCACHENXRRSET */
+ "wait", /*%< 53 DNS_R_WAIT */
+ "not verified yet", /*%< 54 DNS_R_NOTVERIFIEDYET */
+
+ "no identity", /*%< 55 DNS_R_NOIDENTITY */
+ "no journal", /*%< 56 DNS_R_NOJOURNAL */
+ "alias", /*%< 57 DNS_R_ALIAS */
+ "use TCP", /*%< 58 DNS_R_USETCP */
+ "no valid RRSIG", /*%< 59 DNS_R_NOVALIDSIG */
+
+ "no valid NSEC", /*%< 60 DNS_R_NOVALIDNSEC */
+ "not insecure", /*%< 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 */
+
+ "unexpected message id", /*%< 65 DNS_R_UNEXPECTEDID */
+ "seen include file", /*%< 66 DNS_R_SEENINCLUDE */
+ "not exact", /*%< 67 DNS_R_NOTEXACT */
+ "address blackholed", /*%< 68 DNS_R_BLACKHOLED */
+ "bad algorithm", /*%< 69 DNS_R_BADALG */
+
+ "invalid use of a meta type", /*%< 70 DNS_R_METATYPE */
+ "CNAME and other data", /*%< 71 DNS_R_CNAMEANDOTHER */
+ "multiple RRs of singleton type", /*%< 72 DNS_R_SINGLETON */
+ "hint nxrrset", /*%< 73 DNS_R_HINTNXRRSET */
+ "no master file configured", /*%< 74 DNS_R_NOMASTERFILE */
+
+ "unknown protocol", /*%< 75 DNS_R_UNKNOWNPROTO */
+ "clocks are unsynchronized", /*%< 76 DNS_R_CLOCKSKEW */
+ "IXFR failed", /*%< 77 DNS_R_BADIXFR */
+ "not authoritative", /*%< 78 DNS_R_NOTAUTHORITATIVE */
+ "no valid KEY", /*%< 79 DNS_R_NOVALIDKEY */
+
+ "obsolete", /*%< 80 DNS_R_OBSOLETE */
+ "already frozen", /*%< 81 DNS_R_FROZEN */
+ "unknown flag", /*%< 82 DNS_R_UNKNOWNFLAG */
+ "expected a response", /*%< 83 DNS_R_EXPECTEDRESPONSE */
+ "no valid DS", /*%< 84 DNS_R_NOVALIDDS */
+
+ "NS is an address", /*%< 85 DNS_R_NSISADDRESS */
+ "received FORMERR", /*%< 86 DNS_R_REMOTEFORMERR */
+ "truncated TCP response", /*%< 87 DNS_R_TRUNCATEDTCP */
+ "lame server detected", /*%< 88 DNS_R_LAME */
+ "unexpected RCODE", /*%< 89 DNS_R_UNEXPECTEDRCODE */
+
+ "unexpected OPCODE", /*%< 90 DNS_R_UNEXPECTEDOPCODE */
+ "chase DS servers", /*%< 91 DNS_R_CHASEDSSERVERS */
+ "empty name", /*%< 92 DNS_R_EMPTYNAME */
+ "empty wild", /*%< 93 DNS_R_EMPTYWILD */
+ "bad bitmap", /*%< 94 DNS_R_BADBITMAP */
+
+ "from wildcard", /*%< 95 DNS_R_FROMWILDCARD */
+ "bad owner name (check-names)", /*%< 96 DNS_R_BADOWNERNAME */
+ "bad name (check-names)", /*%< 97 DNS_R_BADNAME */
+ "dynamic zone", /*%< 98 DNS_R_DYNAMIC */
+ "unknown command", /*%< 99 DNS_R_UNKNOWNCOMMAND */
+
+ "must-be-secure", /*%< 100 DNS_R_MUSTBESECURE */
+ "covering NSEC record returned", /*%< 101 DNS_R_COVERINGNSEC */
+ "MX is an address", /*%< 102 DNS_R_MXISADDRESS */
+ "duplicate query", /*%< 103 DNS_R_DUPLICATE */
+ "invalid NSEC3 owner name (wildcard)", /*%< 104 DNS_R_INVALIDNSEC3 */
+};
+
+static const char *rcode_text[DNS_R_NRCODERESULTS] = {
+ "NOERROR", /*%< 0 DNS_R_NOEROR */
+ "FORMERR", /*%< 1 DNS_R_FORMERR */
+ "SERVFAIL", /*%< 2 DNS_R_SERVFAIL */
+ "NXDOMAIN", /*%< 3 DNS_R_NXDOMAIN */
+ "NOTIMP", /*%< 4 DNS_R_NOTIMP */
+
+ "REFUSED", /*%< 5 DNS_R_REFUSED */
+ "YXDOMAIN", /*%< 6 DNS_R_YXDOMAIN */
+ "YXRRSET", /*%< 7 DNS_R_YXRRSET */
+ "NXRRSET", /*%< 8 DNS_R_NXRRSET */
+ "NOTAUTH", /*%< 9 DNS_R_NOTAUTH */
+
+ "NOTZONE", /*%< 10 DNS_R_NOTZONE */
+ "<rcode 11>", /*%< 11 has no macro */
+ "<rcode 12>", /*%< 12 has no macro */
+ "<rcode 13>", /*%< 13 has no macro */
+ "<rcode 14>", /*%< 14 has no macro */
+
+ "<rcode 15>", /*%< 15 has no macro */
+ "BADVERS", /*%< 16 DNS_R_BADVERS */
+};
+
+#define DNS_RESULT_RESULTSET 2
+#define DNS_RESULT_RCODERESULTSET 3
+
+static isc_once_t once = ISC_ONCE_INIT;
+
+static void
+initialize_action(void) {
+ isc_result_t result;
+
+ result = isc_result_register(ISC_RESULTCLASS_DNS, DNS_R_NRESULTS,
+ text, dns_msgcat, DNS_RESULT_RESULTSET);
+ if (result == ISC_R_SUCCESS)
+ result = isc_result_register(ISC_RESULTCLASS_DNSRCODE,
+ DNS_R_NRCODERESULTS,
+ rcode_text, dns_msgcat,
+ DNS_RESULT_RCODERESULTSET);
+ if (result != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_result_register() failed: %u", result);
+}
+
+static void
+initialize(void) {
+ dns_lib_initmsgcat();
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+}
+
+const char *
+dns_result_totext(isc_result_t result) {
+ initialize();
+
+ return (isc_result_totext(result));
+}
+
+void
+dns_result_register(void) {
+ initialize();
+}
+
+dns_rcode_t
+dns_result_torcode(isc_result_t result) {
+ dns_rcode_t rcode = dns_rcode_servfail;
+
+ if (DNS_RESULT_ISRCODE(result)) {
+ /*
+ * Rcodes can't be bigger than 12 bits, which is why we
+ * AND with 0xFFF instead of 0xFFFF.
+ */
+ return ((dns_rcode_t)((result) & 0xFFF));
+ }
+ /*
+ * Try to supply an appropriate rcode.
+ */
+ switch (result) {
+ case ISC_R_SUCCESS:
+ rcode = dns_rcode_noerror;
+ break;
+ case ISC_R_BADBASE64:
+ case ISC_R_NOSPACE:
+ case ISC_R_RANGE:
+ case ISC_R_UNEXPECTEDEND:
+ case DNS_R_BADAAAA:
+ /* case DNS_R_BADBITSTRING: deprecated */
+ case DNS_R_BADCKSUM:
+ case DNS_R_BADCLASS:
+ case DNS_R_BADLABELTYPE:
+ case DNS_R_BADPOINTER:
+ case DNS_R_BADTTL:
+ case DNS_R_BADZONE:
+ /* case DNS_R_BITSTRINGTOOLONG: deprecated */
+ case DNS_R_EXTRADATA:
+ case DNS_R_LABELTOOLONG:
+ case DNS_R_NOREDATA:
+ case DNS_R_SYNTAX:
+ case DNS_R_TEXTTOOLONG:
+ case DNS_R_TOOMANYHOPS:
+ case DNS_R_TSIGERRORSET:
+ case DNS_R_UNKNOWN:
+ rcode = dns_rcode_formerr;
+ break;
+ case DNS_R_DISALLOWED:
+ rcode = dns_rcode_refused;
+ break;
+ case DNS_R_TSIGVERIFYFAILURE:
+ case DNS_R_CLOCKSKEW:
+ rcode = dns_rcode_notauth;
+ break;
+ default:
+ rcode = dns_rcode_servfail;
+ }
+
+ return (rcode);
+}
diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c
new file mode 100644
index 0000000..3c50a18
--- /dev/null
+++ b/lib/dns/rootns.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: rootns.c,v 1.36 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/rdata.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/rootns.h>
+#include <dns/view.h>
+
+static char root_ns[] =
+";\n"
+"; Internet Root Nameservers\n"
+";\n"
+"$TTL 518400\n"
+". 518400 IN NS A.ROOT-SERVERS.NET.\n"
+". 518400 IN NS B.ROOT-SERVERS.NET.\n"
+". 518400 IN NS C.ROOT-SERVERS.NET.\n"
+". 518400 IN NS D.ROOT-SERVERS.NET.\n"
+". 518400 IN NS E.ROOT-SERVERS.NET.\n"
+". 518400 IN NS F.ROOT-SERVERS.NET.\n"
+". 518400 IN NS G.ROOT-SERVERS.NET.\n"
+". 518400 IN NS H.ROOT-SERVERS.NET.\n"
+". 518400 IN NS I.ROOT-SERVERS.NET.\n"
+". 518400 IN NS J.ROOT-SERVERS.NET.\n"
+". 518400 IN NS K.ROOT-SERVERS.NET.\n"
+". 518400 IN NS L.ROOT-SERVERS.NET.\n"
+". 518400 IN NS M.ROOT-SERVERS.NET.\n"
+"A.ROOT-SERVERS.NET. 3600000 IN A 198.41.0.4\n"
+"A.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:BA3E::2:30\n"
+"B.ROOT-SERVERS.NET. 3600000 IN A 192.228.79.201\n"
+"C.ROOT-SERVERS.NET. 3600000 IN A 192.33.4.12\n"
+"D.ROOT-SERVERS.NET. 3600000 IN A 128.8.10.90\n"
+"E.ROOT-SERVERS.NET. 3600000 IN A 192.203.230.10\n"
+"F.ROOT-SERVERS.NET. 3600000 IN A 192.5.5.241\n"
+"F.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2F::F\n"
+"G.ROOT-SERVERS.NET. 3600000 IN A 192.112.36.4\n"
+"H.ROOT-SERVERS.NET. 3600000 IN A 128.63.2.53\n"
+"H.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:1::803F:235\n"
+"I.ROOT-SERVERS.NET. 3600000 IN A 192.36.148.17\n"
+"J.ROOT-SERVERS.NET. 3600000 IN A 192.58.128.30\n"
+"J.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:C27::2:30\n"
+"K.ROOT-SERVERS.NET. 3600000 IN A 193.0.14.129\n"
+"K.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:7FD::1\n"
+"L.ROOT-SERVERS.NET. 3600000 IN A 199.7.83.42\n"
+"M.ROOT-SERVERS.NET. 3600000 IN A 202.12.27.33\n"
+"M.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:DC3::35\n";
+
+static isc_result_t
+in_rootns(dns_rdataset_t *rootns, dns_name_t *name) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_ns_t ns;
+
+ if (!dns_rdataset_isassociated(rootns))
+ return (ISC_R_NOTFOUND);
+
+ result = dns_rdataset_first(rootns);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(rootns, &rdata);
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (dns_name_compare(name, &ns.name) == 0)
+ return (ISC_R_SUCCESS);
+ result = dns_rdataset_next(rootns);
+ dns_rdata_reset(&rdata);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_NOTFOUND;
+ return (result);
+}
+
+static isc_result_t
+check_node(dns_rdataset_t *rootns, dns_name_t *name,
+ dns_rdatasetiter_t *rdsiter) {
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ switch (rdataset.type) {
+ case dns_rdatatype_a:
+ case dns_rdatatype_aaaa:
+ result = in_rootns(rootns, name);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ break;
+ case dns_rdatatype_ns:
+ if (dns_name_compare(name, dns_rootname) == 0)
+ break;
+ /*FALLTHROUGH*/
+ default:
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ cleanup:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+static isc_result_t
+check_hints(dns_db_t *db) {
+ isc_result_t result;
+ dns_rdataset_t rootns;
+ dns_dbiterator_t *dbiter = NULL;
+ dns_dbnode_t *node = NULL;
+ isc_stdtime_t now;
+ dns_fixedname_t fixname;
+ dns_name_t *name;
+ dns_rdatasetiter_t *rdsiter = NULL;
+
+ isc_stdtime_get(&now);
+
+ dns_fixedname_init(&fixname);
+ name = dns_fixedname_name(&fixname);
+
+ dns_rdataset_init(&rootns);
+ (void)dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0,
+ now, NULL, name, &rootns, NULL);
+ result = dns_db_createiterator(db, 0, &dbiter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_dbiterator_first(dbiter);
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbiter, &node, name);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = dns_db_allrdatasets(db, node, NULL, now, &rdsiter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = check_node(&rootns, name, rdsiter);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdatasetiter_destroy(&rdsiter);
+ dns_db_detachnode(db, &node);
+ result = dns_dbiterator_next(dbiter);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (dns_rdataset_isassociated(&rootns))
+ dns_rdataset_disassociate(&rootns);
+ if (rdsiter != NULL)
+ dns_rdatasetiter_destroy(&rdsiter);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (dbiter != NULL)
+ dns_dbiterator_destroy(&dbiter);
+ return (result);
+}
+
+isc_result_t
+dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
+ const char *filename, dns_db_t **target)
+{
+ isc_result_t result, eresult;
+ isc_buffer_t source;
+ size_t len;
+ dns_rdatacallbacks_t callbacks;
+ dns_db_t *db = NULL;
+
+ REQUIRE(target != NULL && *target == NULL);
+
+ result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
+ rdclass, 0, NULL, &db);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ dns_rdatacallbacks_init(&callbacks);
+
+ len = strlen(root_ns);
+ isc_buffer_init(&source, root_ns, len);
+ isc_buffer_add(&source, len);
+
+ result = dns_db_beginload(db, &callbacks.add,
+ &callbacks.add_private);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (filename != NULL) {
+ /*
+ * Load the hints from the specified filename.
+ */
+ result = dns_master_loadfile(filename, &db->origin,
+ &db->origin, db->rdclass,
+ DNS_MASTER_HINT,
+ &callbacks, db->mctx);
+ } else if (rdclass == dns_rdataclass_in) {
+ /*
+ * Default to using the Internet root servers.
+ */
+ result = dns_master_loadbuffer(&source, &db->origin,
+ &db->origin, db->rdclass,
+ DNS_MASTER_HINT,
+ &callbacks, db->mctx);
+ } else
+ result = ISC_R_NOTFOUND;
+ eresult = dns_db_endload(db, &callbacks.add_private);
+ if (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE)
+ result = eresult;
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
+ goto db_detach;
+ if (check_hints(db) != ISC_R_SUCCESS)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
+ "extra data in root hints '%s'",
+ (filename != NULL) ? filename : "<BUILT-IN>");
+ *target = db;
+ return (ISC_R_SUCCESS);
+
+ db_detach:
+ dns_db_detach(&db);
+
+ return (result);
+}
+
+static void
+report(dns_view_t *view, dns_name_t *name, isc_boolean_t missing,
+ dns_rdata_t *rdata)
+{
+ const char *viewname = "", *sep = "";
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char databuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
+ isc_buffer_t buffer;
+ isc_result_t result;
+
+ if (strcmp(view->name, "_bind") != 0 &&
+ strcmp(view->name, "_default") != 0) {
+ viewname = view->name;
+ sep = ": view ";
+ }
+
+ dns_name_format(name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
+ isc_buffer_init(&buffer, databuf, sizeof(databuf) - 1);
+ result = dns_rdata_totext(rdata, NULL, &buffer);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ databuf[isc_buffer_usedlength(&buffer)] = '\0';
+
+ if (missing)
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
+ "checkhints%s%s: %s/%s (%s) missing from hints",
+ sep, viewname, namebuf, typebuf, databuf);
+ else
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
+ "checkhints%s%s: %s/%s (%s) extra record "
+ "in hints", sep, viewname, namebuf, typebuf,
+ databuf);
+}
+
+static isc_boolean_t
+inrrset(dns_rdataset_t *rrset, dns_rdata_t *rdata) {
+ isc_result_t result;
+ dns_rdata_t current = DNS_RDATA_INIT;
+
+ result = dns_rdataset_first(rrset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(rrset, &current);
+ if (dns_rdata_compare(rdata, &current) == 0)
+ return (ISC_TRUE);
+ dns_rdata_reset(&current);
+ result = dns_rdataset_next(rrset);
+ }
+ return (ISC_FALSE);
+}
+
+/*
+ * Check that the address RRsets match.
+ *
+ * Note we don't complain about missing glue records.
+ */
+
+static void
+check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
+ dns_name_t *name, isc_stdtime_t now)
+{
+ isc_result_t hresult, rresult, result;
+ dns_rdataset_t hintrrset, rootrrset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_name_t *foundname;
+ dns_fixedname_t fixed;
+
+ dns_rdataset_init(&hintrrset);
+ dns_rdataset_init(&rootrrset);
+ dns_fixedname_init(&fixed);
+ foundname = dns_fixedname_name(&fixed);
+
+ hresult = dns_db_find(hints, name, NULL, dns_rdatatype_a, 0,
+ now, NULL, foundname, &hintrrset, NULL);
+ rresult = dns_db_find(db, name, NULL, dns_rdatatype_a,
+ DNS_DBFIND_GLUEOK, now, NULL, foundname,
+ &rootrrset, NULL);
+ if (hresult == ISC_R_SUCCESS &&
+ (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
+ result = dns_rdataset_first(&rootrrset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&rootrrset, &rdata);
+ if (!inrrset(&hintrrset, &rdata))
+ report(view, name, ISC_TRUE, &rdata);
+ result = dns_rdataset_next(&rootrrset);
+ }
+ result = dns_rdataset_first(&hintrrset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&hintrrset, &rdata);
+ if (!inrrset(&rootrrset, &rdata))
+ report(view, name, ISC_FALSE, &rdata);
+ result = dns_rdataset_next(&hintrrset);
+ }
+ }
+ if (hresult == ISC_R_NOTFOUND &&
+ (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
+ result = dns_rdataset_first(&rootrrset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&rootrrset, &rdata);
+ report(view, name, ISC_TRUE, &rdata);
+ result = dns_rdataset_next(&rootrrset);
+ }
+ }
+ if (dns_rdataset_isassociated(&rootrrset))
+ dns_rdataset_disassociate(&rootrrset);
+ if (dns_rdataset_isassociated(&hintrrset))
+ dns_rdataset_disassociate(&hintrrset);
+
+ /*
+ * Check AAAA records.
+ */
+ hresult = dns_db_find(hints, name, NULL, dns_rdatatype_aaaa, 0,
+ now, NULL, foundname, &hintrrset, NULL);
+ rresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
+ DNS_DBFIND_GLUEOK, now, NULL, foundname,
+ &rootrrset, NULL);
+ if (hresult == ISC_R_SUCCESS &&
+ (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
+ result = dns_rdataset_first(&rootrrset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&rootrrset, &rdata);
+ if (!inrrset(&hintrrset, &rdata))
+ report(view, name, ISC_TRUE, &rdata);
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&rootrrset);
+ }
+ result = dns_rdataset_first(&hintrrset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&hintrrset, &rdata);
+ if (!inrrset(&rootrrset, &rdata))
+ report(view, name, ISC_FALSE, &rdata);
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&hintrrset);
+ }
+ }
+ if (hresult == ISC_R_NOTFOUND &&
+ (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
+ result = dns_rdataset_first(&rootrrset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&rootrrset, &rdata);
+ report(view, name, ISC_TRUE, &rdata);
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&rootrrset);
+ }
+ }
+ if (dns_rdataset_isassociated(&rootrrset))
+ dns_rdataset_disassociate(&rootrrset);
+ if (dns_rdataset_isassociated(&hintrrset))
+ dns_rdataset_disassociate(&hintrrset);
+}
+
+void
+dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db) {
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_ns_t ns;
+ dns_rdataset_t hintns, rootns;
+ const char *viewname = "", *sep = "";
+ isc_stdtime_t now;
+ dns_name_t *name;
+ dns_fixedname_t fixed;
+
+ REQUIRE(hints != NULL);
+ REQUIRE(db != NULL);
+ REQUIRE(view != NULL);
+
+ isc_stdtime_get(&now);
+
+ if (strcmp(view->name, "_bind") != 0 &&
+ strcmp(view->name, "_default") != 0) {
+ viewname = view->name;
+ sep = ": view ";
+ }
+
+ dns_rdataset_init(&hintns);
+ dns_rdataset_init(&rootns);
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+
+ result = dns_db_find(hints, dns_rootname, NULL, dns_rdatatype_ns, 0,
+ now, NULL, name, &hintns, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
+ "checkhints%s%s: unable to get root NS rrset "
+ "from hints: %s", sep, viewname,
+ dns_result_totext(result));
+ goto cleanup;
+ }
+
+ result = dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0,
+ now, NULL, name, &rootns, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
+ "checkhints%s%s: unable to get root NS rrset "
+ "from cache: %s", sep, viewname,
+ dns_result_totext(result));
+ goto cleanup;
+ }
+
+ /*
+ * Look for missing root NS names.
+ */
+ result = dns_rdataset_first(&rootns);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&rootns, &rdata);
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = in_rootns(&hintns, &ns.name);
+ if (result != ISC_R_SUCCESS) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ /* missing from hints */
+ dns_name_format(&ns.name, namebuf, sizeof(namebuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
+ "checkhints%s%s: unable to find root "
+ "NS '%s' in hints", sep, viewname,
+ namebuf);
+ } else
+ check_address_records(view, hints, db, &ns.name, now);
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&rootns);
+ }
+ if (result != ISC_R_NOMORE) {
+ goto cleanup;
+ }
+
+ /*
+ * Look for extra root NS names.
+ */
+ result = dns_rdataset_first(&hintns);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&hintns, &rdata);
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = in_rootns(&rootns, &ns.name);
+ if (result != ISC_R_SUCCESS) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ /* extra entry in hints */
+ dns_name_format(&ns.name, namebuf, sizeof(namebuf));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
+ "checkhints%s%s: extra NS '%s' in hints",
+ sep, viewname, namebuf);
+ }
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&hintns);
+ }
+ if (result != ISC_R_NOMORE) {
+ goto cleanup;
+ }
+
+ cleanup:
+ if (dns_rdataset_isassociated(&rootns))
+ dns_rdataset_disassociate(&rootns);
+ if (dns_rdataset_isassociated(&hintns))
+ dns_rdataset_disassociate(&hintns);
+}
diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c
new file mode 100644
index 0000000..f141a10
--- /dev/null
+++ b/lib/dns/sdb.c
@@ -0,0 +1,1551 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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: sdb.c,v 1.66 2008/09/24 03:16:58 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/lex.h>
+#include <isc/log.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/util.h>
+
+#include <dns/callbacks.h>
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/sdb.h>
+#include <dns/types.h>
+
+#include "rdatalist_p.h"
+
+struct dns_sdbimplementation {
+ const dns_sdbmethods_t *methods;
+ void *driverdata;
+ unsigned int flags;
+ isc_mem_t *mctx;
+ isc_mutex_t driverlock;
+ dns_dbimplementation_t *dbimp;
+};
+
+struct dns_sdb {
+ /* Unlocked */
+ dns_db_t common;
+ char *zone;
+ dns_sdbimplementation_t *implementation;
+ void *dbdata;
+ isc_mutex_t lock;
+ /* Locked */
+ unsigned int references;
+};
+
+struct dns_sdblookup {
+ /* Unlocked */
+ unsigned int magic;
+ dns_sdb_t *sdb;
+ ISC_LIST(dns_rdatalist_t) lists;
+ ISC_LIST(isc_buffer_t) buffers;
+ dns_name_t *name;
+ ISC_LINK(dns_sdblookup_t) link;
+ isc_mutex_t lock;
+ dns_rdatacallbacks_t callbacks;
+ /* Locked */
+ unsigned int references;
+};
+
+typedef struct dns_sdblookup dns_sdbnode_t;
+
+struct dns_sdballnodes {
+ dns_dbiterator_t common;
+ ISC_LIST(dns_sdbnode_t) nodelist;
+ dns_sdbnode_t *current;
+ dns_sdbnode_t *origin;
+};
+
+typedef dns_sdballnodes_t sdb_dbiterator_t;
+
+typedef struct sdb_rdatasetiter {
+ dns_rdatasetiter_t common;
+ dns_rdatalist_t *current;
+} sdb_rdatasetiter_t;
+
+#define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-')
+
+/*%
+ * Note that "impmagic" is not the first four bytes of the struct, so
+ * ISC_MAGIC_VALID cannot be used.
+ */
+#define VALID_SDB(sdb) ((sdb) != NULL && \
+ (sdb)->common.impmagic == SDB_MAGIC)
+
+#define SDBLOOKUP_MAGIC ISC_MAGIC('S','D','B','L')
+#define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
+#define VALID_SDBNODE(sdbn) VALID_SDBLOOKUP(sdbn)
+
+/* These values are taken from RFC1537 */
+#define SDB_DEFAULT_REFRESH (60 * 60 * 8)
+#define SDB_DEFAULT_RETRY (60 * 60 * 2)
+#define SDB_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
+#define SDB_DEFAULT_MINIMUM (60 * 60 * 24)
+
+/* This is a reasonable value */
+#define SDB_DEFAULT_TTL (60 * 60 * 24)
+
+#ifdef __COVERITY__
+#define MAYBE_LOCK(sdb) LOCK(&sdb->implementation->driverlock)
+#define MAYBE_UNLOCK(sdb) UNLOCK(&sdb->implementation->driverlock)
+#else
+#define MAYBE_LOCK(sdb) \
+ do { \
+ unsigned int flags = sdb->implementation->flags; \
+ if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
+ LOCK(&sdb->implementation->driverlock); \
+ } while (0)
+
+#define MAYBE_UNLOCK(sdb) \
+ do { \
+ unsigned int flags = sdb->implementation->flags; \
+ if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
+ UNLOCK(&sdb->implementation->driverlock); \
+ } while (0)
+#endif
+
+static int dummy;
+
+static isc_result_t dns_sdb_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 isc_result_t findrdataset(dns_db_t *db, dns_dbnode_t *node,
+ dns_dbversion_t *version,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset);
+
+static isc_result_t createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
+
+static void destroynode(dns_sdbnode_t *node);
+
+static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
+
+
+static void list_tordataset(dns_rdatalist_t *rdatalist,
+ dns_db_t *db, dns_dbnode_t *node,
+ dns_rdataset_t *rdataset);
+
+static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
+static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
+ dns_name_t *name);
+static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
+ dns_dbnode_t **nodep,
+ dns_name_t *name);
+static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
+ dns_name_t *name);
+
+static dns_dbiteratormethods_t dbiterator_methods = {
+ dbiterator_destroy,
+ dbiterator_first,
+ dbiterator_last,
+ dbiterator_seek,
+ dbiterator_prev,
+ dbiterator_next,
+ dbiterator_current,
+ dbiterator_pause,
+ dbiterator_origin
+};
+
+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
+};
+
+/*
+ * Functions used by implementors of simple databases
+ */
+isc_result_t
+dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
+ void *driverdata, unsigned int flags, isc_mem_t *mctx,
+ dns_sdbimplementation_t **sdbimp)
+{
+ dns_sdbimplementation_t *imp;
+ isc_result_t result;
+
+ REQUIRE(drivername != NULL);
+ REQUIRE(methods != NULL);
+ REQUIRE(methods->lookup != NULL);
+ REQUIRE(mctx != NULL);
+ REQUIRE(sdbimp != NULL && *sdbimp == NULL);
+ REQUIRE((flags & ~(DNS_SDBFLAG_RELATIVEOWNER |
+ DNS_SDBFLAG_RELATIVERDATA |
+ DNS_SDBFLAG_THREADSAFE)) == 0);
+
+ imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
+ if (imp == NULL)
+ return (ISC_R_NOMEMORY);
+ imp->methods = methods;
+ imp->driverdata = driverdata;
+ imp->flags = flags;
+ imp->mctx = NULL;
+ isc_mem_attach(mctx, &imp->mctx);
+ result = isc_mutex_init(&imp->driverlock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mctx;
+
+ imp->dbimp = NULL;
+ result = dns_db_register(drivername, dns_sdb_create, imp, mctx,
+ &imp->dbimp);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mutex;
+ *sdbimp = imp;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_mutex:
+ DESTROYLOCK(&imp->driverlock);
+ cleanup_mctx:
+ isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
+ return (result);
+}
+
+void
+dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
+ dns_sdbimplementation_t *imp;
+ isc_mem_t *mctx;
+
+ REQUIRE(sdbimp != NULL && *sdbimp != NULL);
+
+ imp = *sdbimp;
+ dns_db_unregister(&imp->dbimp);
+ DESTROYLOCK(&imp->driverlock);
+
+ mctx = imp->mctx;
+ isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
+ isc_mem_detach(&mctx);
+
+ *sdbimp = NULL;
+}
+
+static inline unsigned int
+initial_size(unsigned int len) {
+ unsigned int size;
+
+ for (size = 1024; size < (64 * 1024); size *= 2)
+ if (len < size)
+ return (size);
+ return (65535);
+}
+
+isc_result_t
+dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval, dns_ttl_t ttl,
+ const unsigned char *rdatap, unsigned int rdlen)
+{
+ dns_rdatalist_t *rdatalist;
+ dns_rdata_t *rdata;
+ isc_buffer_t *rdatabuf = NULL;
+ isc_result_t result;
+ isc_mem_t *mctx;
+ isc_region_t region;
+
+ mctx = lookup->sdb->common.mctx;
+
+ rdatalist = ISC_LIST_HEAD(lookup->lists);
+ while (rdatalist != NULL) {
+ if (rdatalist->type == typeval)
+ break;
+ rdatalist = ISC_LIST_NEXT(rdatalist, link);
+ }
+
+ if (rdatalist == NULL) {
+ rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
+ if (rdatalist == NULL)
+ return (ISC_R_NOMEMORY);
+ rdatalist->rdclass = lookup->sdb->common.rdclass;
+ rdatalist->type = typeval;
+ rdatalist->covers = 0;
+ rdatalist->ttl = ttl;
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LINK_INIT(rdatalist, link);
+ ISC_LIST_APPEND(lookup->lists, rdatalist, link);
+ } else
+ if (rdatalist->ttl != ttl)
+ return (DNS_R_BADTTL);
+
+ rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
+ if (rdata == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_buffer_allocate(mctx, &rdatabuf, rdlen);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ DE_CONST(rdatap, region.base);
+ region.length = rdlen;
+ isc_buffer_copyregion(rdatabuf, &region);
+ isc_buffer_usedregion(rdatabuf, &region);
+ dns_rdata_init(rdata);
+ dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
+ &region);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
+ rdata = NULL;
+
+ failure:
+ if (rdata != NULL)
+ isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
+ return (result);
+}
+
+
+isc_result_t
+dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
+ const char *data)
+{
+ unsigned int datalen;
+ dns_rdatatype_t typeval;
+ isc_textregion_t r;
+ isc_lex_t *lex = NULL;
+ isc_result_t result;
+ unsigned char *p = NULL;
+ unsigned int size = 0; /* Init to suppress compiler warning */
+ isc_mem_t *mctx;
+ dns_sdbimplementation_t *imp;
+ dns_name_t *origin;
+ isc_buffer_t b;
+ isc_buffer_t rb;
+
+ REQUIRE(VALID_SDBLOOKUP(lookup));
+ REQUIRE(type != NULL);
+ REQUIRE(data != NULL);
+
+ mctx = lookup->sdb->common.mctx;
+
+ DE_CONST(type, r.base);
+ r.length = strlen(type);
+ result = dns_rdatatype_fromtext(&typeval, &r);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ imp = lookup->sdb->implementation;
+ if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
+ origin = &lookup->sdb->common.origin;
+ else
+ origin = dns_rootname;
+
+ result = isc_lex_create(mctx, 64, &lex);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ datalen = strlen(data);
+ size = initial_size(datalen);
+ do {
+ isc_buffer_init(&b, data, datalen);
+ isc_buffer_add(&b, datalen);
+ result = isc_lex_openbuffer(lex, &b);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ if (size >= 65535)
+ size = 65535;
+ p = isc_mem_get(mctx, size);
+ if (p == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ isc_buffer_init(&rb, p, size);
+ result = dns_rdata_fromtext(NULL,
+ lookup->sdb->common.rdclass,
+ typeval, lex,
+ origin, 0,
+ mctx, &rb,
+ &lookup->callbacks);
+ if (result != ISC_R_NOSPACE)
+ break;
+
+ /*
+ * Is the RR too big?
+ */
+ if (size >= 65535)
+ break;
+ isc_mem_put(mctx, p, size);
+ p = NULL;
+ size *= 2;
+ } while (result == ISC_R_NOSPACE);
+
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ result = dns_sdb_putrdata(lookup, typeval, ttl,
+ isc_buffer_base(&rb),
+ isc_buffer_usedlength(&rb));
+ failure:
+ if (p != NULL)
+ isc_mem_put(mctx, p, size);
+ if (lex != NULL)
+ isc_lex_destroy(&lex);
+
+ return (result);
+}
+
+static isc_result_t
+getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) {
+ dns_name_t *newname, *origin;
+ dns_fixedname_t fnewname;
+ dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db;
+ dns_sdbimplementation_t *imp = sdb->implementation;
+ dns_sdbnode_t *sdbnode;
+ isc_mem_t *mctx = sdb->common.mctx;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ dns_fixedname_init(&fnewname);
+ newname = dns_fixedname_name(&fnewname);
+
+ if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0)
+ origin = &sdb->common.origin;
+ else
+ origin = dns_rootname;
+ isc_buffer_init(&b, name, strlen(name));
+ isc_buffer_add(&b, strlen(name));
+
+ result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (allnodes->common.relative_names) {
+ /* All names are relative to the root */
+ unsigned int nlabels = dns_name_countlabels(newname);
+ dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
+ }
+
+ sdbnode = ISC_LIST_HEAD(allnodes->nodelist);
+ if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) {
+ sdbnode = NULL;
+ result = createnode(sdb, &sdbnode);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (sdbnode->name == NULL) {
+ destroynode(sdbnode);
+ return (ISC_R_NOMEMORY);
+ }
+ dns_name_init(sdbnode->name, NULL);
+ result = dns_name_dup(newname, mctx, sdbnode->name);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, sdbnode->name, sizeof(dns_name_t));
+ destroynode(sdbnode);
+ return (result);
+ }
+ ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link);
+ if (allnodes->origin == NULL &&
+ dns_name_equal(newname, &sdb->common.origin))
+ allnodes->origin = sdbnode;
+ }
+ *nodep = sdbnode;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
+ const char *type, dns_ttl_t ttl, const char *data)
+{
+ isc_result_t result;
+ dns_sdbnode_t *sdbnode = NULL;
+ result = getnode(allnodes, name, &sdbnode);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (dns_sdb_putrr(sdbnode, type, ttl, data));
+}
+
+isc_result_t
+dns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
+ dns_rdatatype_t type, dns_ttl_t ttl,
+ const void *rdata, unsigned int rdlen)
+{
+ isc_result_t result;
+ dns_sdbnode_t *sdbnode = NULL;
+ result = getnode(allnodes, name, &sdbnode);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen));
+}
+
+isc_result_t
+dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
+ isc_uint32_t serial)
+{
+ char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
+ int n;
+
+ REQUIRE(mname != NULL);
+ REQUIRE(rname != NULL);
+
+ n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u",
+ mname, rname, serial,
+ SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
+ SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
+ if (n >= (int)sizeof(str) || n < 0)
+ return (ISC_R_NOSPACE);
+ return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
+}
+
+/*
+ * DB routines
+ */
+
+static void
+attach(dns_db_t *source, dns_db_t **targetp) {
+ dns_sdb_t *sdb = (dns_sdb_t *) source;
+
+ REQUIRE(VALID_SDB(sdb));
+
+ LOCK(&sdb->lock);
+ REQUIRE(sdb->references > 0);
+ sdb->references++;
+ UNLOCK(&sdb->lock);
+
+ *targetp = source;
+}
+
+static void
+destroy(dns_sdb_t *sdb) {
+ isc_mem_t *mctx;
+ dns_sdbimplementation_t *imp = sdb->implementation;
+
+ mctx = sdb->common.mctx;
+
+ if (imp->methods->destroy != NULL) {
+ MAYBE_LOCK(sdb);
+ imp->methods->destroy(sdb->zone, imp->driverdata,
+ &sdb->dbdata);
+ MAYBE_UNLOCK(sdb);
+ }
+
+ isc_mem_free(mctx, sdb->zone);
+ DESTROYLOCK(&sdb->lock);
+
+ sdb->common.magic = 0;
+ sdb->common.impmagic = 0;
+
+ dns_name_free(&sdb->common.origin, mctx);
+
+ isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
+ isc_mem_detach(&mctx);
+}
+
+static void
+detach(dns_db_t **dbp) {
+ dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(VALID_SDB(sdb));
+ LOCK(&sdb->lock);
+ REQUIRE(sdb->references > 0);
+ sdb->references--;
+ if (sdb->references == 0)
+ need_destroy = ISC_TRUE;
+ UNLOCK(&sdb->lock);
+
+ if (need_destroy)
+ destroy(sdb);
+
+ *dbp = NULL;
+}
+
+static isc_result_t
+beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
+ UNUSED(db);
+ UNUSED(addp);
+ UNUSED(dbloadp);
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t
+endload(dns_db_t *db, dns_dbload_t **dbloadp) {
+ UNUSED(db);
+ UNUSED(dbloadp);
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t
+dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
+ dns_masterformat_t masterformat) {
+ UNUSED(db);
+ UNUSED(version);
+ UNUSED(filename);
+ UNUSED(masterformat);
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static void
+currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
+ REQUIRE(versionp != NULL && *versionp == NULL);
+
+ UNUSED(db);
+
+ *versionp = (void *) &dummy;
+ return;
+}
+
+static isc_result_t
+newversion(dns_db_t *db, dns_dbversion_t **versionp) {
+ UNUSED(db);
+ UNUSED(versionp);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static void
+attachversion(dns_db_t *db, dns_dbversion_t *source,
+ dns_dbversion_t **targetp)
+{
+ REQUIRE(source != NULL && source == (void *) &dummy);
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ UNUSED(db);
+ *targetp = source;
+ return;
+}
+
+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);
+
+ UNUSED(db);
+ UNUSED(commit);
+
+ *versionp = NULL;
+}
+
+static isc_result_t
+createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
+ dns_sdbnode_t *node;
+ isc_result_t result;
+
+ node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
+ if (node == NULL)
+ return (ISC_R_NOMEMORY);
+
+ node->sdb = NULL;
+ attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
+ ISC_LIST_INIT(node->lists);
+ ISC_LIST_INIT(node->buffers);
+ ISC_LINK_INIT(node, link);
+ node->name = NULL;
+ result = isc_mutex_init(&node->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(sdb->common.mctx, node, sizeof(dns_sdbnode_t));
+ return (result);
+ }
+ dns_rdatacallbacks_init(&node->callbacks);
+ node->references = 1;
+ node->magic = SDBLOOKUP_MAGIC;
+
+ *nodep = node;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+destroynode(dns_sdbnode_t *node) {
+ dns_rdatalist_t *list;
+ dns_rdata_t *rdata;
+ isc_buffer_t *b;
+ dns_sdb_t *sdb;
+ isc_mem_t *mctx;
+
+ sdb = node->sdb;
+ mctx = sdb->common.mctx;
+
+ while (!ISC_LIST_EMPTY(node->lists)) {
+ list = ISC_LIST_HEAD(node->lists);
+ while (!ISC_LIST_EMPTY(list->rdata)) {
+ rdata = ISC_LIST_HEAD(list->rdata);
+ ISC_LIST_UNLINK(list->rdata, rdata, link);
+ isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
+ }
+ ISC_LIST_UNLINK(node->lists, list, link);
+ isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
+ }
+
+ while (!ISC_LIST_EMPTY(node->buffers)) {
+ b = ISC_LIST_HEAD(node->buffers);
+ ISC_LIST_UNLINK(node->buffers, b, link);
+ isc_buffer_free(&b);
+ }
+
+ if (node->name != NULL) {
+ dns_name_free(node->name, mctx);
+ isc_mem_put(mctx, node->name, sizeof(dns_name_t));
+ }
+ DESTROYLOCK(&node->lock);
+ node->magic = 0;
+ isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
+ detach((dns_db_t **) (void *)&sdb);
+}
+
+static isc_result_t
+findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
+ dns_dbnode_t **nodep)
+{
+ dns_sdb_t *sdb = (dns_sdb_t *)db;
+ dns_sdbnode_t *node = NULL;
+ isc_result_t result;
+ isc_buffer_t b;
+ char namestr[DNS_NAME_MAXTEXT + 1];
+ isc_boolean_t isorigin;
+ dns_sdbimplementation_t *imp;
+
+ REQUIRE(VALID_SDB(sdb));
+ REQUIRE(create == ISC_FALSE);
+ REQUIRE(nodep != NULL && *nodep == NULL);
+
+ UNUSED(name);
+ UNUSED(create);
+
+ imp = sdb->implementation;
+
+ isc_buffer_init(&b, namestr, sizeof(namestr));
+ if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
+ dns_name_t relname;
+ unsigned int labels;
+
+ labels = dns_name_countlabels(name) -
+ dns_name_countlabels(&db->origin);
+ dns_name_init(&relname, NULL);
+ dns_name_getlabelsequence(name, 0, labels, &relname);
+ result = dns_name_totext(&relname, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else {
+ result = dns_name_totext(name, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ isc_buffer_putuint8(&b, 0);
+
+ result = createnode(sdb, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ isorigin = dns_name_equal(name, &sdb->common.origin);
+
+ MAYBE_LOCK(sdb);
+ result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata, node);
+ MAYBE_UNLOCK(sdb);
+ if (result != ISC_R_SUCCESS &&
+ !(result == ISC_R_NOTFOUND &&
+ isorigin && imp->methods->authority != NULL))
+ {
+ destroynode(node);
+ return (result);
+ }
+
+ if (isorigin && imp->methods->authority != NULL) {
+ MAYBE_LOCK(sdb);
+ result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
+ MAYBE_UNLOCK(sdb);
+ if (result != ISC_R_SUCCESS) {
+ destroynode(node);
+ return (result);
+ }
+ }
+
+ *nodep = node;
+ return (ISC_R_SUCCESS);
+}
+
+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_sdb_t *sdb = (dns_sdb_t *)db;
+ dns_dbnode_t *node = NULL;
+ dns_fixedname_t fname;
+ dns_rdataset_t xrdataset;
+ dns_name_t *xname;
+ unsigned int nlabels, olabels;
+ isc_result_t result;
+ unsigned int i;
+
+ REQUIRE(VALID_SDB(sdb));
+ REQUIRE(nodep == NULL || *nodep == NULL);
+ REQUIRE(version == NULL || version == (void *) &dummy);
+
+ UNUSED(options);
+ UNUSED(sdb);
+
+ if (!dns_name_issubdomain(name, &db->origin))
+ return (DNS_R_NXDOMAIN);
+
+ olabels = dns_name_countlabels(&db->origin);
+ nlabels = dns_name_countlabels(name);
+
+ dns_fixedname_init(&fname);
+ xname = dns_fixedname_name(&fname);
+
+ if (rdataset == NULL) {
+ dns_rdataset_init(&xrdataset);
+ rdataset = &xrdataset;
+ }
+
+ result = DNS_R_NXDOMAIN;
+
+ for (i = olabels; i <= nlabels; i++) {
+ /*
+ * Unless this is an explicit lookup at the origin, don't
+ * look at the origin.
+ */
+ if (i == olabels && i != nlabels)
+ continue;
+
+ /*
+ * Look up the next label.
+ */
+ dns_name_getlabelsequence(name, nlabels - i, i, xname);
+ result = findnode(db, xname, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS) {
+ result = DNS_R_NXDOMAIN;
+ continue;
+ }
+
+ /*
+ * Look for a DNAME at the current label, unless this is
+ * the qname.
+ */
+ if (i < nlabels) {
+ result = findrdataset(db, node, version,
+ dns_rdatatype_dname,
+ 0, now, rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ result = DNS_R_DNAME;
+ break;
+ }
+ }
+
+ /*
+ * Look for an NS at the current label, unless this is the
+ * origin or glue is ok.
+ */
+ if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
+ result = findrdataset(db, node, version,
+ dns_rdatatype_ns,
+ 0, now, rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ if (i == nlabels && type == dns_rdatatype_any)
+ {
+ result = DNS_R_ZONECUT;
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL)
+ dns_rdataset_disassociate
+ (sigrdataset);
+ } else
+ result = DNS_R_DELEGATION;
+ break;
+ }
+ }
+
+ /*
+ * If the current name is not the qname, add another label
+ * and try again.
+ */
+ if (i < nlabels) {
+ destroynode(node);
+ node = NULL;
+ continue;
+ }
+
+ /*
+ * If we're looking for ANY, we're done.
+ */
+ if (type == dns_rdatatype_any) {
+ result = ISC_R_SUCCESS;
+ break;
+ }
+
+ /*
+ * Look for the qtype.
+ */
+ result = findrdataset(db, node, version, type,
+ 0, now, rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS)
+ break;
+
+ /*
+ * Look for a CNAME
+ */
+ if (type != dns_rdatatype_cname) {
+ result = findrdataset(db, node, version,
+ dns_rdatatype_cname,
+ 0, now, rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ result = DNS_R_CNAME;
+ break;
+ }
+ }
+
+ result = DNS_R_NXRRSET;
+ break;
+ }
+
+ if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+
+ if (foundname != NULL) {
+ isc_result_t xresult;
+
+ xresult = dns_name_copy(xname, foundname, NULL);
+ if (xresult != ISC_R_SUCCESS) {
+ if (node != NULL)
+ destroynode(node);
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ return (DNS_R_BADDB);
+ }
+ }
+
+ if (nodep != NULL)
+ *nodep = node;
+ else if (node != NULL)
+ detachnode(db, &node);
+
+ return (result);
+}
+
+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)
+{
+ UNUSED(db);
+ UNUSED(name);
+ UNUSED(options);
+ UNUSED(now);
+ UNUSED(nodep);
+ UNUSED(foundname);
+ UNUSED(rdataset);
+ UNUSED(sigrdataset);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static void
+attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
+ dns_sdb_t *sdb = (dns_sdb_t *)db;
+ dns_sdbnode_t *node = (dns_sdbnode_t *)source;
+
+ REQUIRE(VALID_SDB(sdb));
+
+ UNUSED(sdb);
+
+ LOCK(&node->lock);
+ INSIST(node->references > 0);
+ node->references++;
+ INSIST(node->references != 0); /* Catch overflow. */
+ UNLOCK(&node->lock);
+
+ *targetp = source;
+}
+
+static void
+detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
+ dns_sdb_t *sdb = (dns_sdb_t *)db;
+ dns_sdbnode_t *node;
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(VALID_SDB(sdb));
+ REQUIRE(targetp != NULL && *targetp != NULL);
+
+ UNUSED(sdb);
+
+ node = (dns_sdbnode_t *)(*targetp);
+
+ 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);
+
+ *targetp = NULL;
+}
+
+static isc_result_t
+expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
+ UNUSED(db);
+ UNUSED(node);
+ UNUSED(now);
+ INSIST(0);
+ return (ISC_R_UNEXPECTED);
+}
+
+static void
+printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
+ UNUSED(db);
+ UNUSED(node);
+ UNUSED(out);
+ return;
+}
+
+static isc_result_t
+createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
+{
+ dns_sdb_t *sdb = (dns_sdb_t *)db;
+ sdb_dbiterator_t *sdbiter;
+ dns_sdbimplementation_t *imp = sdb->implementation;
+ isc_result_t result;
+
+ REQUIRE(VALID_SDB(sdb));
+
+ if (imp->methods->allnodes == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ if ((options & DNS_DB_NSEC3ONLY) != 0 ||
+ (options & DNS_DB_NONSEC3) != 0)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
+ if (sdbiter == NULL)
+ return (ISC_R_NOMEMORY);
+
+ sdbiter->common.methods = &dbiterator_methods;
+ sdbiter->common.db = NULL;
+ dns_db_attach(db, &sdbiter->common.db);
+ sdbiter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
+ sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
+ ISC_LIST_INIT(sdbiter->nodelist);
+ sdbiter->current = NULL;
+ sdbiter->origin = NULL;
+
+ MAYBE_LOCK(sdb);
+ result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter);
+ MAYBE_UNLOCK(sdb);
+ if (result != ISC_R_SUCCESS) {
+ dbiterator_destroy((dns_dbiterator_t **) (void *)&sdbiter);
+ return (result);
+ }
+
+ if (sdbiter->origin != NULL) {
+ ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link);
+ ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link);
+ }
+
+ *iteratorp = (dns_dbiterator_t *)sdbiter;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ dns_rdatalist_t *list;
+ dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
+
+ REQUIRE(VALID_SDBNODE(node));
+
+ UNUSED(db);
+ UNUSED(version);
+ UNUSED(covers);
+ UNUSED(now);
+ UNUSED(sigrdataset);
+
+ if (type == dns_rdatatype_rrsig)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ list = ISC_LIST_HEAD(sdbnode->lists);
+ while (list != NULL) {
+ if (list->type == type)
+ break;
+ list = ISC_LIST_NEXT(list, link);
+ }
+ if (list == NULL)
+ return (ISC_R_NOTFOUND);
+
+ list_tordataset(list, db, node, rdataset);
+
+ return (ISC_R_SUCCESS);
+}
+
+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)
+{
+ sdb_rdatasetiter_t *iterator;
+
+ REQUIRE(version == NULL || version == &dummy);
+
+ UNUSED(version);
+ UNUSED(now);
+
+ iterator = isc_mem_get(db->mctx, sizeof(sdb_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 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);
+ UNUSED(now);
+ UNUSED(rdataset);
+ UNUSED(options);
+ UNUSED(addedrdataset);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+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);
+ UNUSED(newrdataset);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+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_boolean_t
+issecure(dns_db_t *db) {
+ UNUSED(db);
+
+ return (ISC_FALSE);
+}
+
+static unsigned int
+nodecount(dns_db_t *db) {
+ UNUSED(db);
+
+ return (0);
+}
+
+static isc_boolean_t
+ispersistent(dns_db_t *db) {
+ UNUSED(db);
+ return (ISC_TRUE);
+}
+
+static void
+overmem(dns_db_t *db, isc_boolean_t overmem) {
+ UNUSED(db);
+ UNUSED(overmem);
+}
+
+static void
+settask(dns_db_t *db, isc_task_t *task) {
+ UNUSED(db);
+ UNUSED(task);
+}
+
+
+static dns_dbmethods_t sdb_methods = {
+ attach,
+ detach,
+ beginload,
+ endload,
+ dump,
+ currentversion,
+ newversion,
+ attachversion,
+ closeversion,
+ findnode,
+ find,
+ findzonecut,
+ attachnode,
+ detachnode,
+ expirenode,
+ printnode,
+ createiterator,
+ findrdataset,
+ allrdatasets,
+ addrdataset,
+ subtractrdataset,
+ deleterdataset,
+ issecure,
+ nodecount,
+ ispersistent,
+ overmem,
+ settask,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static isc_result_t
+dns_sdb_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_sdb_t *sdb;
+ isc_result_t result;
+ char zonestr[DNS_NAME_MAXTEXT + 1];
+ isc_buffer_t b;
+ dns_sdbimplementation_t *imp;
+
+ REQUIRE(driverarg != NULL);
+
+ imp = driverarg;
+
+ if (type != dns_dbtype_zone)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ sdb = isc_mem_get(mctx, sizeof(dns_sdb_t));
+ if (sdb == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(sdb, 0, sizeof(dns_sdb_t));
+
+ dns_name_init(&sdb->common.origin, NULL);
+ sdb->common.attributes = 0;
+ sdb->common.methods = &sdb_methods;
+ sdb->common.rdclass = rdclass;
+ sdb->common.mctx = NULL;
+ sdb->implementation = imp;
+
+ isc_mem_attach(mctx, &sdb->common.mctx);
+
+ result = isc_mutex_init(&sdb->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mctx;
+
+ result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lock;
+
+ isc_buffer_init(&b, zonestr, sizeof(zonestr));
+ result = dns_name_totext(origin, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_origin;
+ isc_buffer_putuint8(&b, 0);
+
+ sdb->zone = isc_mem_strdup(mctx, zonestr);
+ if (sdb->zone == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_origin;
+ }
+
+ sdb->dbdata = NULL;
+ if (imp->methods->create != NULL) {
+ MAYBE_LOCK(sdb);
+ result = imp->methods->create(sdb->zone, argc, argv,
+ imp->driverdata, &sdb->dbdata);
+ MAYBE_UNLOCK(sdb);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_zonestr;
+ }
+
+ sdb->references = 1;
+
+ sdb->common.magic = DNS_DB_MAGIC;
+ sdb->common.impmagic = SDB_MAGIC;
+
+ *dbp = (dns_db_t *)sdb;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_zonestr:
+ isc_mem_free(mctx, sdb->zone);
+ cleanup_origin:
+ dns_name_free(&sdb->common.origin, mctx);
+ cleanup_lock:
+ isc_mutex_destroy(&sdb->lock);
+ cleanup_mctx:
+ isc_mem_put(mctx, sdb, sizeof(dns_sdb_t));
+ isc_mem_detach(&mctx);
+
+ return (result);
+}
+
+
+/*
+ * Rdataset Methods
+ */
+
+static void
+disassociate(dns_rdataset_t *rdataset) {
+ dns_dbnode_t *node = rdataset->private5;
+ dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
+ dns_db_t *db = (dns_db_t *) sdbnode->sdb;
+
+ detachnode(db, &node);
+ isc__rdatalist_disassociate(rdataset);
+}
+
+static void
+rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
+ dns_dbnode_t *node = source->private5;
+ dns_sdbnode_t *sdbnode = (dns_sdbnode_t *) node;
+ dns_db_t *db = (dns_db_t *) sdbnode->sdb;
+ dns_dbnode_t *tempdb = NULL;
+
+ isc__rdatalist_clone(source, target);
+ attachnode(db, node, &tempdb);
+ source->private5 = tempdb;
+}
+
+static dns_rdatasetmethods_t methods = {
+ disassociate,
+ isc__rdatalist_first,
+ isc__rdatalist_next,
+ isc__rdatalist_current,
+ rdataset_clone,
+ isc__rdatalist_count,
+ isc__rdatalist_addnoqname,
+ isc__rdatalist_getnoqname,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+list_tordataset(dns_rdatalist_t *rdatalist,
+ dns_db_t *db, dns_dbnode_t *node,
+ dns_rdataset_t *rdataset)
+{
+ /*
+ * The sdb rdataset is an rdatalist with some additions.
+ * - private1 & private2 are used by the rdatalist.
+ * - private3 & private 4 are unused.
+ * - private5 is the node.
+ */
+
+ /* This should never fail. */
+ RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
+ ISC_R_SUCCESS);
+
+ rdataset->methods = &methods;
+ dns_db_attachnode(db, node, &rdataset->private5);
+}
+
+/*
+ * Database Iterator Methods
+ */
+static void
+dbiterator_destroy(dns_dbiterator_t **iteratorp) {
+ sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp);
+ dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db;
+
+ while (!ISC_LIST_EMPTY(sdbiter->nodelist)) {
+ dns_sdbnode_t *node;
+ node = ISC_LIST_HEAD(sdbiter->nodelist);
+ ISC_LIST_UNLINK(sdbiter->nodelist, node, link);
+ destroynode(node);
+ }
+
+ dns_db_detach(&sdbiter->common.db);
+ isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t));
+
+ *iteratorp = NULL;
+}
+
+static isc_result_t
+dbiterator_first(dns_dbiterator_t *iterator) {
+ sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
+
+ sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
+ if (sdbiter->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_last(dns_dbiterator_t *iterator) {
+ sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
+
+ sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist);
+ if (sdbiter->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
+ sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
+
+ sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
+ while (sdbiter->current != NULL)
+ if (dns_name_equal(sdbiter->current->name, name))
+ return (ISC_R_SUCCESS);
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+dbiterator_prev(dns_dbiterator_t *iterator) {
+ sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
+
+ sdbiter->current = ISC_LIST_PREV(sdbiter->current, link);
+ if (sdbiter->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_next(dns_dbiterator_t *iterator) {
+ sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
+
+ sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
+ if (sdbiter->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
+ dns_name_t *name)
+{
+ sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
+
+ attachnode(iterator->db, sdbiter->current, nodep);
+ if (name != NULL)
+ return (dns_name_copy(sdbiter->current->name, name, NULL));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_pause(dns_dbiterator_t *iterator) {
+ UNUSED(iterator);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
+ UNUSED(iterator);
+ return (dns_name_copy(dns_rootname, name, NULL));
+}
+
+/*
+ * Rdataset Iterator Methods
+ */
+
+static void
+rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
+ sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
+ detachnode(sdbiterator->common.db, &sdbiterator->common.node);
+ isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
+ sizeof(sdb_rdatasetiter_t));
+ *iteratorp = NULL;
+}
+
+static isc_result_t
+rdatasetiter_first(dns_rdatasetiter_t *iterator) {
+ sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
+ dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
+
+ if (ISC_LIST_EMPTY(sdbnode->lists))
+ return (ISC_R_NOMORE);
+ sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+rdatasetiter_next(dns_rdatasetiter_t *iterator) {
+ sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
+
+ sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
+ if (sdbiterator->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
+ sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
+
+ list_tordataset(sdbiterator->current, iterator->db, iterator->node,
+ rdataset);
+}
diff --git a/lib/dns/sdlz.c b/lib/dns/sdlz.c
new file mode 100644
index 0000000..ec82c3e
--- /dev/null
+++ b/lib/dns/sdlz.c
@@ -0,0 +1,1799 @@
+/*
+ * Portions Copyright (C) 2005-2008 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
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * STICHTING NLNET 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.
+ *
+ * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
+ * conceived and contributed by Rob Butler.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * ROB BUTLER 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: sdlz.c,v 1.18 2008/09/24 02:46:22 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+#include <string.h>
+
+#include <isc/buffer.h>
+#include <isc/lex.h>
+#include <isc/log.h>
+#include <isc/rwlock.h>
+#include <isc/string.h>
+#include <isc/util.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/region.h>
+
+#include <dns/callbacks.h>
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/dlz.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/master.h>
+#include <dns/sdlz.h>
+#include <dns/types.h>
+
+#include "rdatalist_p.h"
+
+/*
+ * Private Types
+ */
+
+struct dns_sdlzimplementation {
+ const dns_sdlzmethods_t *methods;
+ isc_mem_t *mctx;
+ void *driverarg;
+ unsigned int flags;
+ isc_mutex_t driverlock;
+ dns_dlzimplementation_t *dlz_imp;
+};
+
+struct dns_sdlz_db {
+ /* Unlocked */
+ dns_db_t common;
+ void *dbdata;
+ dns_sdlzimplementation_t *dlzimp;
+ isc_mutex_t refcnt_lock;
+ /* Locked */
+ unsigned int references;
+};
+
+struct dns_sdlzlookup {
+ /* Unlocked */
+ unsigned int magic;
+ dns_sdlz_db_t *sdlz;
+ ISC_LIST(dns_rdatalist_t) lists;
+ ISC_LIST(isc_buffer_t) buffers;
+ dns_name_t *name;
+ ISC_LINK(dns_sdlzlookup_t) link;
+ isc_mutex_t lock;
+ dns_rdatacallbacks_t callbacks;
+ /* Locked */
+ unsigned int references;
+};
+
+typedef struct dns_sdlzlookup dns_sdlznode_t;
+
+struct dns_sdlzallnodes {
+ dns_dbiterator_t common;
+ ISC_LIST(dns_sdlznode_t) nodelist;
+ dns_sdlznode_t *current;
+ dns_sdlznode_t *origin;
+};
+
+typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
+
+typedef struct sdlz_rdatasetiter {
+ dns_rdatasetiter_t common;
+ dns_rdatalist_t *current;
+} sdlz_rdatasetiter_t;
+
+
+#define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
+
+/*
+ * Note that "impmagic" is not the first four bytes of the struct, so
+ * ISC_MAGIC_VALID cannot be used.
+ */
+
+#define VALID_SDLZDB(sdlzdb) ((sdlzdb) != NULL && \
+ (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
+
+#define SDLZLOOKUP_MAGIC ISC_MAGIC('D','L','Z','L')
+#define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
+#define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn)
+
+/* These values are taken from RFC 1537 */
+#define SDLZ_DEFAULT_REFRESH (60 * 60 * 8)
+#define SDLZ_DEFAULT_RETRY (60 * 60 * 2)
+#define SDLZ_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
+#define SDLZ_DEFAULT_MINIMUM (60 * 60 * 24)
+
+/* 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)
+#else
+#define MAYBE_LOCK(imp) \
+ do { \
+ unsigned int flags = imp->flags; \
+ if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
+ LOCK(&imp->driverlock); \
+ } while (0)
+
+#define MAYBE_UNLOCK(imp) \
+ do { \
+ unsigned int flags = imp->flags; \
+ if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
+ UNLOCK(&imp->driverlock); \
+ } while (0)
+#endif
+
+/*
+ * Forward references. Try to keep these to a minimum.
+ */
+
+static void list_tordataset(dns_rdatalist_t *rdatalist,
+ dns_db_t *db, dns_dbnode_t *node,
+ dns_rdataset_t *rdataset);
+
+static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
+
+static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
+static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
+ dns_name_t *name);
+static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
+ dns_dbnode_t **nodep,
+ dns_name_t *name);
+static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
+static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
+ dns_name_t *name);
+
+static dns_dbiteratormethods_t dbiterator_methods = {
+ dbiterator_destroy,
+ dbiterator_first,
+ dbiterator_last,
+ dbiterator_seek,
+ dbiterator_prev,
+ dbiterator_next,
+ dbiterator_current,
+ dbiterator_pause,
+ dbiterator_origin
+};
+
+/*
+ * Utility functions
+ */
+
+/*% Converts the input string to lowercase, in place. */
+
+static void
+dns_sdlz_tolower(char *str) {
+
+ unsigned int len = strlen(str);
+ unsigned int i;
+
+ for (i = 0; i < len; i++) {
+ if (str[i] >= 'A' && str[i] <= 'Z')
+ str[i] += 32;
+ }
+
+}
+
+static inline unsigned int
+initial_size(const char *data) {
+ unsigned int len = (strlen(data) / 64) + 1;
+ return (len * 64 + 64);
+}
+
+/*
+ * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
+ * driver interface. See the SDB driver interface documentation for more info.
+ */
+
+static void
+rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
+ sdlz_rdatasetiter_t *sdlziterator =
+ (sdlz_rdatasetiter_t *)(*iteratorp);
+
+ detachnode(sdlziterator->common.db, &sdlziterator->common.node);
+ isc_mem_put(sdlziterator->common.db->mctx, sdlziterator,
+ sizeof(sdlz_rdatasetiter_t));
+ *iteratorp = NULL;
+}
+
+static isc_result_t
+rdatasetiter_first(dns_rdatasetiter_t *iterator) {
+ sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
+ dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node;
+
+ if (ISC_LIST_EMPTY(sdlznode->lists))
+ return (ISC_R_NOMORE);
+ sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+rdatasetiter_next(dns_rdatasetiter_t *iterator) {
+ sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
+
+ sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
+ if (sdlziterator->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static void
+rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
+ sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
+
+ list_tordataset(sdlziterator->current, iterator->db, iterator->node,
+ rdataset);
+}
+
+static dns_rdatasetitermethods_t rdatasetiter_methods = {
+ rdatasetiter_destroy,
+ rdatasetiter_first,
+ rdatasetiter_next,
+ rdatasetiter_current
+};
+
+/*
+ * DB routines. These methods were "borrowed" from the SDB driver interface.
+ * See the SDB driver interface documentation for more info.
+ */
+
+static void
+attach(dns_db_t *source, dns_db_t **targetp) {
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) source;
+
+ REQUIRE(VALID_SDLZDB(sdlz));
+
+ LOCK(&sdlz->refcnt_lock);
+ REQUIRE(sdlz->references > 0);
+ sdlz->references++;
+ UNLOCK(&sdlz->refcnt_lock);
+
+ *targetp = source;
+}
+
+static void
+destroy(dns_sdlz_db_t *sdlz) {
+ isc_mem_t *mctx;
+ mctx = sdlz->common.mctx;
+
+ sdlz->common.magic = 0;
+ sdlz->common.impmagic = 0;
+
+ isc_mutex_destroy(&sdlz->refcnt_lock);
+
+ dns_name_free(&sdlz->common.origin, mctx);
+
+ isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t));
+ isc_mem_detach(&mctx);
+}
+
+static void
+detach(dns_db_t **dbp) {
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(VALID_SDLZDB(sdlz));
+ LOCK(&sdlz->refcnt_lock);
+ REQUIRE(sdlz->references > 0);
+ sdlz->references--;
+ if (sdlz->references == 0)
+ need_destroy = ISC_TRUE;
+ UNLOCK(&sdlz->refcnt_lock);
+
+ if (need_destroy)
+ destroy(sdlz);
+
+ *dbp = NULL;
+}
+
+static isc_result_t
+beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
+ UNUSED(db);
+ UNUSED(addp);
+ UNUSED(dbloadp);
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t
+endload(dns_db_t *db, dns_dbload_t **dbloadp) {
+ UNUSED(db);
+ UNUSED(dbloadp);
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t
+dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
+ dns_masterformat_t masterformat)
+{
+ UNUSED(db);
+ UNUSED(version);
+ UNUSED(filename);
+ UNUSED(masterformat);
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static void
+currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
+ REQUIRE(versionp != NULL && *versionp == NULL);
+
+ UNUSED(db);
+
+ *versionp = (void *) &dummy;
+ return;
+}
+
+static isc_result_t
+newversion(dns_db_t *db, dns_dbversion_t **versionp) {
+ UNUSED(db);
+ UNUSED(versionp);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static void
+attachversion(dns_db_t *db, dns_dbversion_t *source,
+ dns_dbversion_t **targetp)
+{
+ REQUIRE(source != NULL && source == (void *) &dummy);
+
+ 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);
+
+ UNUSED(db);
+ UNUSED(commit);
+
+ *versionp = NULL;
+}
+
+static isc_result_t
+createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
+ dns_sdlznode_t *node;
+ isc_result_t result;
+
+ node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
+ if (node == NULL)
+ return (ISC_R_NOMEMORY);
+
+ node->sdlz = NULL;
+ attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz);
+ ISC_LIST_INIT(node->lists);
+ ISC_LIST_INIT(node->buffers);
+ ISC_LINK_INIT(node, link);
+ node->name = NULL;
+ 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(sdlz->common.mctx, node, sizeof(dns_sdlznode_t));
+ return (ISC_R_UNEXPECTED);
+ }
+ dns_rdatacallbacks_init(&node->callbacks);
+ node->references = 1;
+ node->magic = SDLZLOOKUP_MAGIC;
+
+ *nodep = node;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+destroynode(dns_sdlznode_t *node) {
+ dns_rdatalist_t *list;
+ dns_rdata_t *rdata;
+ isc_buffer_t *b;
+ dns_sdlz_db_t *sdlz;
+ dns_db_t *db;
+ isc_mem_t *mctx;
+
+ sdlz = node->sdlz;
+ mctx = sdlz->common.mctx;
+
+ while (!ISC_LIST_EMPTY(node->lists)) {
+ list = ISC_LIST_HEAD(node->lists);
+ while (!ISC_LIST_EMPTY(list->rdata)) {
+ rdata = ISC_LIST_HEAD(list->rdata);
+ ISC_LIST_UNLINK(list->rdata, rdata, link);
+ isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
+ }
+ ISC_LIST_UNLINK(node->lists, list, link);
+ isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
+ }
+
+ while (!ISC_LIST_EMPTY(node->buffers)) {
+ b = ISC_LIST_HEAD(node->buffers);
+ ISC_LIST_UNLINK(node->buffers, b, link);
+ isc_buffer_free(&b);
+ }
+
+ if (node->name != NULL) {
+ dns_name_free(node->name, mctx);
+ isc_mem_put(mctx, node->name, sizeof(dns_name_t));
+ }
+ DESTROYLOCK(&node->lock);
+ node->magic = 0;
+ isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
+ db = &sdlz->common;
+ detach(&db);
+}
+
+static isc_result_t
+findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
+ dns_dbnode_t **nodep)
+{
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ dns_sdlznode_t *node = NULL;
+ isc_result_t result;
+ isc_buffer_t b;
+ char namestr[DNS_NAME_MAXTEXT + 1];
+ isc_buffer_t b2;
+ char zonestr[DNS_NAME_MAXTEXT + 1];
+ isc_boolean_t isorigin;
+ dns_sdlzauthorityfunc_t authority;
+
+ REQUIRE(VALID_SDLZDB(sdlz));
+ REQUIRE(create == ISC_FALSE);
+ REQUIRE(nodep != NULL && *nodep == NULL);
+
+ UNUSED(name);
+ UNUSED(create);
+
+ isc_buffer_init(&b, namestr, sizeof(namestr));
+ if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
+ dns_name_t relname;
+ unsigned int labels;
+
+ labels = dns_name_countlabels(name) -
+ dns_name_countlabels(&db->origin);
+ dns_name_init(&relname, NULL);
+ dns_name_getlabelsequence(name, 0, labels, &relname);
+ result = dns_name_totext(&relname, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else {
+ result = dns_name_totext(name, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ isc_buffer_putuint8(&b, 0);
+
+ isc_buffer_init(&b2, zonestr, sizeof(zonestr));
+ result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b2);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_putuint8(&b2, 0);
+
+ result = createnode(sdlz, &node);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ isorigin = dns_name_equal(name, &sdlz->common.origin);
+
+ /* make sure strings are always lowercase */
+ dns_sdlz_tolower(zonestr);
+ dns_sdlz_tolower(namestr);
+
+ MAYBE_LOCK(sdlz->dlzimp);
+
+ /* try to lookup the host (namestr) */
+ result = sdlz->dlzimp->methods->lookup(zonestr, namestr,
+ sdlz->dlzimp->driverarg,
+ sdlz->dbdata, node);
+
+ /*
+ * if the host (namestr) was not found, try to lookup a
+ * "wildcard" host.
+ */
+ if (result != ISC_R_SUCCESS) {
+ result = sdlz->dlzimp->methods->lookup(zonestr, "*",
+ sdlz->dlzimp->driverarg,
+ sdlz->dbdata, node);
+ }
+
+ MAYBE_UNLOCK(sdlz->dlzimp);
+
+ if (result != ISC_R_SUCCESS && !isorigin) {
+ destroynode(node);
+ return (result);
+ }
+
+ if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
+ MAYBE_LOCK(sdlz->dlzimp);
+ authority = sdlz->dlzimp->methods->authority;
+ result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
+ sdlz->dbdata, node);
+ MAYBE_UNLOCK(sdlz->dlzimp);
+ if (result != ISC_R_SUCCESS &&
+ result != ISC_R_NOTIMPLEMENTED) {
+ destroynode(node);
+ return (result);
+ }
+ }
+
+ *nodep = node;
+ return (ISC_R_SUCCESS);
+}
+
+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)
+{
+ UNUSED(db);
+ UNUSED(name);
+ UNUSED(options);
+ UNUSED(now);
+ UNUSED(nodep);
+ UNUSED(foundname);
+ UNUSED(rdataset);
+ UNUSED(sigrdataset);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static void
+attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ dns_sdlznode_t *node = (dns_sdlznode_t *)source;
+
+ REQUIRE(VALID_SDLZDB(sdlz));
+
+ UNUSED(sdlz);
+
+ LOCK(&node->lock);
+ INSIST(node->references > 0);
+ node->references++;
+ INSIST(node->references != 0); /* Catch overflow. */
+ UNLOCK(&node->lock);
+
+ *targetp = source;
+}
+
+static void
+detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ dns_sdlznode_t *node;
+ isc_boolean_t need_destroy = ISC_FALSE;
+
+ REQUIRE(VALID_SDLZDB(sdlz));
+ REQUIRE(targetp != NULL && *targetp != NULL);
+
+ UNUSED(sdlz);
+
+ node = (dns_sdlznode_t *)(*targetp);
+
+ 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);
+
+ *targetp = NULL;
+}
+
+static isc_result_t
+expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
+ UNUSED(db);
+ UNUSED(node);
+ UNUSED(now);
+ INSIST(0);
+ return (ISC_R_UNEXPECTED);
+}
+
+static void
+printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
+ UNUSED(db);
+ UNUSED(node);
+ UNUSED(out);
+ return;
+}
+
+static isc_result_t
+createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
+{
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ sdlz_dbiterator_t *sdlziter;
+ isc_result_t result;
+ isc_buffer_t b;
+ char zonestr[DNS_NAME_MAXTEXT + 1];
+
+ REQUIRE(VALID_SDLZDB(sdlz));
+
+ if (sdlz->dlzimp->methods->allnodes == NULL)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ if ((options & DNS_DB_NSEC3ONLY) != 0 ||
+ (options & DNS_DB_NONSEC3) != 0)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ isc_buffer_init(&b, zonestr, sizeof(zonestr));
+ result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_putuint8(&b, 0);
+
+ sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
+ if (sdlziter == NULL)
+ return (ISC_R_NOMEMORY);
+
+ sdlziter->common.methods = &dbiterator_methods;
+ sdlziter->common.db = NULL;
+ dns_db_attach(db, &sdlziter->common.db);
+ sdlziter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
+ sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
+ ISC_LIST_INIT(sdlziter->nodelist);
+ sdlziter->current = NULL;
+ sdlziter->origin = NULL;
+
+ /* make sure strings are always lowercase */
+ dns_sdlz_tolower(zonestr);
+
+ MAYBE_LOCK(sdlz->dlzimp);
+ result = sdlz->dlzimp->methods->allnodes(zonestr,
+ sdlz->dlzimp->driverarg,
+ sdlz->dbdata, sdlziter);
+ MAYBE_UNLOCK(sdlz->dlzimp);
+ if (result != ISC_R_SUCCESS) {
+ dns_dbiterator_t *iter = &sdlziter->common;
+ dbiterator_destroy(&iter);
+ return (result);
+ }
+
+ if (sdlziter->origin != NULL) {
+ ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
+ ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
+ }
+
+ *iteratorp = (dns_dbiterator_t *)sdlziter;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ isc_stdtime_t now, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ dns_rdatalist_t *list;
+ dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
+
+ REQUIRE(VALID_SDLZNODE(node));
+
+ UNUSED(db);
+ UNUSED(version);
+ UNUSED(covers);
+ UNUSED(now);
+ UNUSED(sigrdataset);
+
+ if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ list = ISC_LIST_HEAD(sdlznode->lists);
+ while (list != NULL) {
+ if (list->type == type)
+ break;
+ list = ISC_LIST_NEXT(list, link);
+ }
+ if (list == NULL)
+ return (ISC_R_NOTFOUND);
+
+ list_tordataset(list, db, node, rdataset);
+
+ return (ISC_R_SUCCESS);
+}
+
+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_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
+ dns_dbnode_t *node = NULL;
+ dns_fixedname_t fname;
+ dns_rdataset_t xrdataset;
+ dns_name_t *xname;
+ unsigned int nlabels, olabels;
+ isc_result_t result;
+ unsigned int i;
+
+ REQUIRE(VALID_SDLZDB(sdlz));
+ REQUIRE(nodep == NULL || *nodep == NULL);
+ REQUIRE(version == NULL || version == (void *) &dummy);
+
+ UNUSED(options);
+ UNUSED(sdlz);
+
+ if (!dns_name_issubdomain(name, &db->origin))
+ return (DNS_R_NXDOMAIN);
+
+ olabels = dns_name_countlabels(&db->origin);
+ nlabels = dns_name_countlabels(name);
+
+ dns_fixedname_init(&fname);
+ xname = dns_fixedname_name(&fname);
+
+ if (rdataset == NULL) {
+ dns_rdataset_init(&xrdataset);
+ rdataset = &xrdataset;
+ }
+
+ result = DNS_R_NXDOMAIN;
+
+ for (i = olabels; i <= nlabels; i++) {
+ /*
+ * Unless this is an explicit lookup at the origin, don't
+ * look at the origin.
+ */
+ if (i == olabels && i != nlabels)
+ continue;
+
+ /*
+ * Look up the next label.
+ */
+ dns_name_getlabelsequence(name, nlabels - i, i, xname);
+ result = findnode(db, xname, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS) {
+ result = DNS_R_NXDOMAIN;
+ continue;
+ }
+
+ /*
+ * Look for a DNAME at the current label, unless this is
+ * the qname.
+ */
+ if (i < nlabels) {
+ result = findrdataset(db, node, version,
+ dns_rdatatype_dname,
+ 0, now, rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ result = DNS_R_DNAME;
+ break;
+ }
+ }
+
+ /*
+ * Look for an NS at the current label, unless this is the
+ * origin or glue is ok.
+ */
+ if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
+ result = findrdataset(db, node, version,
+ dns_rdatatype_ns,
+ 0, now, rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ if (i == nlabels && type == dns_rdatatype_any)
+ {
+ result = DNS_R_ZONECUT;
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL)
+ dns_rdataset_disassociate
+ (sigrdataset);
+ } else
+ result = DNS_R_DELEGATION;
+ break;
+ }
+ }
+
+ /*
+ * If the current name is not the qname, add another label
+ * and try again.
+ */
+ if (i < nlabels) {
+ destroynode(node);
+ node = NULL;
+ continue;
+ }
+
+ /*
+ * If we're looking for ANY, we're done.
+ */
+ if (type == dns_rdatatype_any) {
+ result = ISC_R_SUCCESS;
+ break;
+ }
+
+ /*
+ * Look for the qtype.
+ */
+ result = findrdataset(db, node, version, type,
+ 0, now, rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS)
+ break;
+
+ /*
+ * Look for a CNAME
+ */
+ if (type != dns_rdatatype_cname) {
+ result = findrdataset(db, node, version,
+ dns_rdatatype_cname,
+ 0, now, rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ result = DNS_R_CNAME;
+ break;
+ }
+ }
+
+ result = DNS_R_NXRRSET;
+ break;
+ }
+
+ if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+
+ if (foundname != NULL) {
+ isc_result_t xresult;
+
+ xresult = dns_name_copy(xname, foundname, NULL);
+ if (xresult != ISC_R_SUCCESS) {
+ if (node != NULL)
+ destroynode(node);
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ return (DNS_R_BADDB);
+ }
+ }
+
+ if (nodep != NULL)
+ *nodep = node;
+ else if (node != NULL)
+ detachnode(db, &node);
+
+ return (result);
+}
+
+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)
+{
+ sdlz_rdatasetiter_t *iterator;
+
+ REQUIRE(version == NULL || version == &dummy);
+
+ UNUSED(version);
+ UNUSED(now);
+
+ iterator = isc_mem_get(db->mctx, sizeof(sdlz_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 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);
+ UNUSED(now);
+ UNUSED(rdataset);
+ UNUSED(options);
+ UNUSED(addedrdataset);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+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);
+ UNUSED(newrdataset);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+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_boolean_t
+issecure(dns_db_t *db) {
+ UNUSED(db);
+
+ return (ISC_FALSE);
+}
+
+static unsigned int
+nodecount(dns_db_t *db) {
+ UNUSED(db);
+
+ return (0);
+}
+
+static isc_boolean_t
+ispersistent(dns_db_t *db) {
+ UNUSED(db);
+ return (ISC_TRUE);
+}
+
+static void
+overmem(dns_db_t *db, isc_boolean_t overmem) {
+ UNUSED(db);
+ UNUSED(overmem);
+}
+
+static void
+settask(dns_db_t *db, isc_task_t *task) {
+ UNUSED(db);
+ UNUSED(task);
+}
+
+
+static dns_dbmethods_t sdlzdb_methods = {
+ attach,
+ detach,
+ beginload,
+ endload,
+ dump,
+ currentversion,
+ newversion,
+ attachversion,
+ closeversion,
+ findnode,
+ find,
+ findzonecut,
+ attachnode,
+ detachnode,
+ expirenode,
+ printnode,
+ createiterator,
+ findrdataset,
+ allrdatasets,
+ addrdataset,
+ subtractrdataset,
+ deleterdataset,
+ issecure,
+ nodecount,
+ ispersistent,
+ overmem,
+ settask,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Database Iterator Methods. These methods were "borrowed" from the SDB
+ * driver interface. See the SDB driver interface documentation for more info.
+ */
+
+static void
+dbiterator_destroy(dns_dbiterator_t **iteratorp) {
+ sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
+
+ while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
+ dns_sdlznode_t *node;
+ node = ISC_LIST_HEAD(sdlziter->nodelist);
+ ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
+ destroynode(node);
+ }
+
+ dns_db_detach(&sdlziter->common.db);
+ isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
+
+ *iteratorp = NULL;
+}
+
+static isc_result_t
+dbiterator_first(dns_dbiterator_t *iterator) {
+ sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
+
+ sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
+ if (sdlziter->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_last(dns_dbiterator_t *iterator) {
+ sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
+
+ sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
+ if (sdlziter->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
+ sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
+
+ sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
+ while (sdlziter->current != NULL)
+ if (dns_name_equal(sdlziter->current->name, name))
+ return (ISC_R_SUCCESS);
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+dbiterator_prev(dns_dbiterator_t *iterator) {
+ sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
+
+ sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
+ if (sdlziter->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_next(dns_dbiterator_t *iterator) {
+ sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
+
+ sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
+ if (sdlziter->current == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
+ dns_name_t *name)
+{
+ sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
+
+ attachnode(iterator->db, sdlziter->current, nodep);
+ if (name != NULL)
+ return (dns_name_copy(sdlziter->current->name, name, NULL));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_pause(dns_dbiterator_t *iterator) {
+ UNUSED(iterator);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
+ UNUSED(iterator);
+ return (dns_name_copy(dns_rootname, name, NULL));
+}
+
+/*
+ * Rdataset Methods. These methods were "borrowed" from the SDB driver
+ * interface. See the SDB driver interface documentation for more info.
+ */
+
+static void
+disassociate(dns_rdataset_t *rdataset) {
+ dns_dbnode_t *node = rdataset->private5;
+ dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
+ dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
+
+ detachnode(db, &node);
+ isc__rdatalist_disassociate(rdataset);
+}
+
+static void
+rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
+ dns_dbnode_t *node = source->private5;
+ dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
+ dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
+ dns_dbnode_t *tempdb = NULL;
+
+ isc__rdatalist_clone(source, target);
+ attachnode(db, node, &tempdb);
+ source->private5 = tempdb;
+}
+
+static dns_rdatasetmethods_t rdataset_methods = {
+ disassociate,
+ isc__rdatalist_first,
+ isc__rdatalist_next,
+ isc__rdatalist_current,
+ rdataset_clone,
+ isc__rdatalist_count,
+ isc__rdatalist_addnoqname,
+ isc__rdatalist_getnoqname,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+list_tordataset(dns_rdatalist_t *rdatalist,
+ dns_db_t *db, dns_dbnode_t *node,
+ dns_rdataset_t *rdataset)
+{
+ /*
+ * The sdlz rdataset is an rdatalist with some additions.
+ * - private1 & private2 are used by the rdatalist.
+ * - private3 & private 4 are unused.
+ * - private5 is the node.
+ */
+
+ /* This should never fail. */
+ RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
+ ISC_R_SUCCESS);
+
+ rdataset->methods = &rdataset_methods;
+ dns_db_attachnode(db, node, &rdataset->private5);
+}
+
+/*
+ * SDLZ core methods. This is the core of the new DLZ functionality.
+ */
+
+/*%
+ * Build a 'bind' database driver structure to be returned by
+ * either the find zone or the allow zone transfer method.
+ * This method is only available in this source file, it is
+ * not made available anywhere else.
+ */
+
+static isc_result_t
+dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
+ dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp)
+{
+ isc_result_t result;
+ dns_sdlz_db_t *sdlzdb;
+ dns_sdlzimplementation_t *imp;
+
+ /* check that things are as we expect */
+ REQUIRE(dbp != NULL && *dbp == NULL);
+ REQUIRE(name != NULL);
+
+ imp = (dns_sdlzimplementation_t *) driverarg;
+
+ /* allocate and zero memory for driver structure */
+ sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
+ if (sdlzdb == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
+
+ /* initialize and set origin */
+ dns_name_init(&sdlzdb->common.origin, NULL);
+ result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
+ if (result != ISC_R_SUCCESS)
+ goto mem_cleanup;
+
+ /* initialize the reference count mutex */
+ result = isc_mutex_init(&sdlzdb->refcnt_lock);
+ if (result != ISC_R_SUCCESS)
+ goto name_cleanup;
+
+ /* set the rest of the database structure attributes */
+ sdlzdb->dlzimp = imp;
+ sdlzdb->common.methods = &sdlzdb_methods;
+ sdlzdb->common.attributes = 0;
+ sdlzdb->common.rdclass = rdclass;
+ sdlzdb->common.mctx = NULL;
+ sdlzdb->dbdata = dbdata;
+ sdlzdb->references = 1;
+
+ /* attach to the memory context */
+ isc_mem_attach(mctx, &sdlzdb->common.mctx);
+
+ /* mark structure as valid */
+ sdlzdb->common.magic = DNS_DB_MAGIC;
+ sdlzdb->common.impmagic = SDLZDB_MAGIC;
+ *dbp = (dns_db_t *) sdlzdb;
+
+ return (result);
+
+ /*
+ * reference count mutex could not be initialized, clean up
+ * name memory
+ */
+ name_cleanup:
+ dns_name_free(&sdlzdb->common.origin, mctx);
+ mem_cleanup:
+ isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
+ return (result);
+}
+
+static isc_result_t
+dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
+ dns_rdataclass_t rdclass, dns_name_t *name,
+ isc_sockaddr_t *clientaddr, dns_db_t **dbp)
+{
+ isc_buffer_t b;
+ isc_buffer_t b2;
+ char namestr[DNS_NAME_MAXTEXT + 1];
+ char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
+ + 1];
+ isc_netaddr_t netaddr;
+ isc_result_t result;
+ dns_sdlzimplementation_t *imp;
+
+ /*
+ * Perform checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(driverarg != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(clientaddr != NULL);
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ imp = (dns_sdlzimplementation_t *) driverarg;
+
+ /* Convert DNS name to ascii text */
+ isc_buffer_init(&b, namestr, sizeof(namestr));
+ result = dns_name_totext(name, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_putuint8(&b, 0);
+
+ /* convert client address to ascii text */
+ isc_buffer_init(&b2, clientstr, sizeof(clientstr));
+ isc_netaddr_fromsockaddr(&netaddr, clientaddr);
+ result = isc_netaddr_totext(&netaddr, &b2);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_putuint8(&b2, 0);
+
+ /* make sure strings are always lowercase */
+ dns_sdlz_tolower(namestr);
+ dns_sdlz_tolower(clientstr);
+
+ /* Call SDLZ driver's find zone method */
+ if (imp->methods->allowzonexfr != NULL) {
+ MAYBE_LOCK(imp);
+ result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
+ namestr, clientstr);
+ MAYBE_UNLOCK(imp);
+ /*
+ * if zone is supported and transfers allowed build a 'bind'
+ * database driver
+ */
+ if (result == ISC_R_SUCCESS)
+ result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
+ name, rdclass, dbp);
+ return (result);
+ }
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+static isc_result_t
+dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
+ char *argv[], void *driverarg, void **dbdata)
+{
+ dns_sdlzimplementation_t *imp;
+ 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.");
+
+ /*
+ * Performs checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(driverarg != NULL);
+ REQUIRE(dlzname != NULL);
+ REQUIRE(dbdata != NULL);
+ UNUSED(mctx);
+
+ imp = driverarg;
+
+ /* If the create method exists, call it. */
+ if (imp->methods->create != NULL) {
+ MAYBE_LOCK(imp);
+ result = imp->methods->create(dlzname, argc, argv,
+ imp->driverarg, dbdata);
+ MAYBE_UNLOCK(imp);
+ }
+
+ /* 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.");
+ } else {
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
+ DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
+ "SDLZ driver failed to load.");
+ }
+
+ return (result);
+}
+
+static void
+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.");
+
+ imp = driverdata;
+
+ /* If the destroy method exists, call it. */
+ if (imp->methods->destroy != NULL) {
+ MAYBE_LOCK(imp);
+ imp->methods->destroy(imp->driverarg, dbdata);
+ MAYBE_UNLOCK(imp);
+ }
+}
+
+static isc_result_t
+dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
+ dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp)
+{
+ isc_buffer_t b;
+ char namestr[DNS_NAME_MAXTEXT + 1];
+ isc_result_t result;
+ dns_sdlzimplementation_t *imp;
+
+ /*
+ * Perform checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(driverarg != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(dbp != NULL && *dbp == NULL);
+
+ imp = (dns_sdlzimplementation_t *) driverarg;
+
+ /* Convert DNS name to ascii text */
+ isc_buffer_init(&b, namestr, sizeof(namestr));
+ result = dns_name_totext(name, ISC_TRUE, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_putuint8(&b, 0);
+
+ /* make sure strings are always lowercase */
+ dns_sdlz_tolower(namestr);
+
+ /* Call SDLZ driver's find zone method */
+ MAYBE_LOCK(imp);
+ result = imp->methods->findzone(imp->driverarg, dbdata, namestr);
+ MAYBE_UNLOCK(imp);
+
+ /*
+ * if zone is supported build a 'bind' database driver
+ * structure to return
+ */
+ if (result == ISC_R_SUCCESS)
+ result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
+ rdclass, dbp);
+
+ return (result);
+}
+
+static dns_dlzmethods_t sdlzmethods = {
+ dns_sdlzcreate,
+ dns_sdlzdestroy,
+ dns_sdlzfindzone,
+ dns_sdlzallowzonexfr
+};
+
+/*
+ * Public functions.
+ */
+
+isc_result_t
+dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
+ const char *data)
+{
+ dns_rdatalist_t *rdatalist;
+ dns_rdata_t *rdata;
+ dns_rdatatype_t typeval;
+ isc_consttextregion_t r;
+ isc_buffer_t b;
+ isc_buffer_t *rdatabuf = NULL;
+ isc_lex_t *lex;
+ isc_result_t result;
+ unsigned int size;
+ isc_mem_t *mctx;
+ dns_name_t *origin;
+
+ REQUIRE(VALID_SDLZLOOKUP(lookup));
+ REQUIRE(type != NULL);
+ REQUIRE(data != NULL);
+
+ mctx = lookup->sdlz->common.mctx;
+
+ r.base = type;
+ r.length = strlen(type);
+ result = dns_rdatatype_fromtext(&typeval, (void *) &r);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ rdatalist = ISC_LIST_HEAD(lookup->lists);
+ while (rdatalist != NULL) {
+ if (rdatalist->type == typeval)
+ break;
+ rdatalist = ISC_LIST_NEXT(rdatalist, link);
+ }
+
+ if (rdatalist == NULL) {
+ rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
+ if (rdatalist == NULL)
+ return (ISC_R_NOMEMORY);
+ rdatalist->rdclass = lookup->sdlz->common.rdclass;
+ rdatalist->type = typeval;
+ rdatalist->covers = 0;
+ rdatalist->ttl = ttl;
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LINK_INIT(rdatalist, link);
+ ISC_LIST_APPEND(lookup->lists, rdatalist, link);
+ } else
+ if (rdatalist->ttl != ttl)
+ return (DNS_R_BADTTL);
+
+ rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
+ if (rdata == NULL)
+ return (ISC_R_NOMEMORY);
+ dns_rdata_init(rdata);
+
+ if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
+ origin = &lookup->sdlz->common.origin;
+ else
+ origin = dns_rootname;
+
+ lex = NULL;
+ result = isc_lex_create(mctx, 64, &lex);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ size = initial_size(data);
+ do {
+ isc_buffer_init(&b, data, strlen(data));
+ isc_buffer_add(&b, strlen(data));
+
+ result = isc_lex_openbuffer(lex, &b);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ rdatabuf = NULL;
+ result = isc_buffer_allocate(mctx, &rdatabuf, size);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
+ rdatalist->type, lex,
+ origin, ISC_FALSE,
+ mctx, rdatabuf,
+ &lookup->callbacks);
+ if (result != ISC_R_SUCCESS)
+ isc_buffer_free(&rdatabuf);
+ size *= 2;
+ } while (result == ISC_R_NOSPACE);
+
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
+
+ if (lex != NULL)
+ isc_lex_destroy(&lex);
+
+ return (ISC_R_SUCCESS);
+
+ failure:
+ if (rdatabuf != NULL)
+ isc_buffer_free(&rdatabuf);
+ if (lex != NULL)
+ isc_lex_destroy(&lex);
+ isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
+
+ return (result);
+}
+
+isc_result_t
+dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
+ const char *type, dns_ttl_t ttl, const char *data)
+{
+ dns_name_t *newname, *origin;
+ dns_fixedname_t fnewname;
+ dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
+ dns_sdlznode_t *sdlznode;
+ isc_mem_t *mctx = sdlz->common.mctx;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ dns_fixedname_init(&fnewname);
+ newname = dns_fixedname_name(&fnewname);
+
+ if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
+ origin = &sdlz->common.origin;
+ else
+ origin = dns_rootname;
+ isc_buffer_init(&b, name, strlen(name));
+ isc_buffer_add(&b, strlen(name));
+
+ result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (allnodes->common.relative_names) {
+ /* All names are relative to the root */
+ unsigned int nlabels = dns_name_countlabels(newname);
+ dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
+ }
+
+ sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
+ if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
+ sdlznode = NULL;
+ result = createnode(sdlz, &sdlznode);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (sdlznode->name == NULL) {
+ destroynode(sdlznode);
+ return (ISC_R_NOMEMORY);
+ }
+ dns_name_init(sdlznode->name, NULL);
+ result = dns_name_dup(newname, mctx, sdlznode->name);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
+ destroynode(sdlznode);
+ return (result);
+ }
+ ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
+ if (allnodes->origin == NULL &&
+ dns_name_equal(newname, &sdlz->common.origin))
+ allnodes->origin = sdlznode;
+ }
+ return (dns_sdlz_putrr(sdlznode, type, ttl, data));
+
+}
+
+isc_result_t
+dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
+ isc_uint32_t serial)
+{
+ char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
+ int n;
+
+ REQUIRE(mname != NULL);
+ REQUIRE(rname != NULL);
+
+ n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
+ mname, rname, serial,
+ SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
+ SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
+ if (n >= (int)sizeof(str) || n < 0)
+ return (ISC_R_NOSPACE);
+ return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
+}
+
+isc_result_t
+dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
+ void *driverarg, unsigned int flags, isc_mem_t *mctx,
+ dns_sdlzimplementation_t **sdlzimp)
+{
+
+ dns_sdlzimplementation_t *imp;
+ isc_result_t result;
+
+ /*
+ * Performs checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(drivername != NULL);
+ REQUIRE(methods != NULL);
+ REQUIRE(methods->findzone != NULL);
+ REQUIRE(methods->lookup != NULL);
+ REQUIRE(mctx != NULL);
+ REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
+ REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
+ DNS_SDLZFLAG_RELATIVERDATA |
+ 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);
+
+ /*
+ * Allocate memory for a sdlz_implementation object. Error if
+ * we cannot.
+ */
+ imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
+ if (imp == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /* Make sure memory region is set to all 0's */
+ memset(imp, 0, sizeof(dns_sdlzimplementation_t));
+
+ /* Store the data passed into this method */
+ imp->methods = methods;
+ imp->driverarg = driverarg;
+ imp->flags = flags;
+ imp->mctx = NULL;
+
+ /* attach the new sdlz_implementation object to a memory context */
+ isc_mem_attach(mctx, &imp->mctx);
+
+ /*
+ * initialize the driver lock, error if we cannot
+ * (used if a driver does not support multiple threads)
+ */
+ result = isc_mutex_init(&imp->driverlock);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_mutex_init() failed: %s",
+ isc_result_totext(result));
+ goto cleanup_mctx;
+ }
+
+ imp->dlz_imp = NULL;
+
+ /*
+ * register the DLZ driver. Pass in our "extra" sdlz information as
+ * a driverarg. (that's why we stored the passed in driver arg in our
+ * sdlz_implementation structure) Also, store the dlz_implementation
+ * structure in our sdlz_implementation.
+ */
+ result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
+ &imp->dlz_imp);
+
+ /* if registration fails, cleanup and get outta here. */
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mutex;
+
+ *sdlzimp = imp;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_mutex:
+ /* destroy the driver lock, we don't need it anymore */
+ DESTROYLOCK(&imp->driverlock);
+
+ cleanup_mctx:
+ /*
+ * return the memory back to the available memory pool and
+ * remove it from the memory context.
+ */
+ isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
+ isc_mem_detach(&mctx);
+ return (result);
+}
+
+void
+dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
+ dns_sdlzimplementation_t *imp;
+ 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.");
+
+ /*
+ * Performs checks to make sure data is as we expect it to be.
+ */
+ REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
+
+ imp = *sdlzimp;
+
+ /* Unregister the DLZ driver implementation */
+ dns_dlzunregister(&imp->dlz_imp);
+
+ /* destroy the driver lock, we don't need it anymore */
+ DESTROYLOCK(&imp->driverlock);
+
+ mctx = imp->mctx;
+
+ /*
+ * return the memory back to the available memory pool and
+ * remove it from the memory context.
+ */
+ isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
+ isc_mem_detach(&mctx);
+
+ *sdlzimp = NULL;
+}
diff --git a/lib/dns/soa.c b/lib/dns/soa.c
new file mode 100644
index 0000000..83a1c17
--- /dev/null
+++ b/lib/dns/soa.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: soa.c,v 1.8 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+#include <dns/rdata.h>
+#include <dns/soa.h>
+
+static inline isc_uint32_t
+decode_uint32(unsigned char *p) {
+ return ((p[0] << 24) +
+ (p[1] << 16) +
+ (p[2] << 8) +
+ (p[3] << 0));
+}
+
+static inline void
+encode_uint32(isc_uint32_t val, unsigned char *p) {
+ p[0] = (isc_uint8_t)(val >> 24);
+ p[1] = (isc_uint8_t)(val >> 16);
+ p[2] = (isc_uint8_t)(val >> 8);
+ p[3] = (isc_uint8_t)(val >> 0);
+}
+
+static isc_uint32_t
+soa_get(dns_rdata_t *rdata, int offset) {
+ INSIST(rdata->type == dns_rdatatype_soa);
+ /*
+ * Locate the field within the SOA RDATA based
+ * on its position relative to the end of the data.
+ *
+ * This is a bit of a kludge, but the alternative approach of
+ * using dns_rdata_tostruct() and dns_rdata_fromstruct() would
+ * involve a lot of unnecessary work (like building domain
+ * names and allocating temporary memory) when all we really
+ * want to do is to get 32 bits of fixed-sized data.
+ */
+ INSIST(rdata->length >= 20);
+ INSIST(offset >= 0 && offset <= 16);
+ return (decode_uint32(rdata->data + rdata->length - 20 + offset));
+}
+
+isc_uint32_t
+dns_soa_getserial(dns_rdata_t *rdata) {
+ return soa_get(rdata, 0);
+}
+isc_uint32_t
+dns_soa_getrefresh(dns_rdata_t *rdata) {
+ return soa_get(rdata, 4);
+}
+isc_uint32_t
+dns_soa_getretry(dns_rdata_t *rdata) {
+ return soa_get(rdata, 8);
+}
+isc_uint32_t
+dns_soa_getexpire(dns_rdata_t *rdata) {
+ return soa_get(rdata, 12);
+}
+isc_uint32_t
+dns_soa_getminimum(dns_rdata_t *rdata) {
+ return soa_get(rdata, 16);
+}
+
+static void
+soa_set(dns_rdata_t *rdata, isc_uint32_t val, int offset) {
+ INSIST(rdata->type == dns_rdatatype_soa);
+ INSIST(rdata->length >= 20);
+ INSIST(offset >= 0 && offset <= 16);
+ encode_uint32(val, rdata->data + rdata->length - 20 + offset);
+}
+
+void
+dns_soa_setserial(isc_uint32_t val, dns_rdata_t *rdata) {
+ soa_set(rdata, val, 0);
+}
+void
+dns_soa_setrefresh(isc_uint32_t val, dns_rdata_t *rdata) {
+ soa_set(rdata, val, 4);
+}
+void
+dns_soa_setretry(isc_uint32_t val, dns_rdata_t *rdata) {
+ soa_set(rdata, val, 8);
+}
+void
+dns_soa_setexpire(isc_uint32_t val, dns_rdata_t *rdata) {
+ soa_set(rdata, val, 12);
+}
+void
+dns_soa_setminimum(isc_uint32_t val, dns_rdata_t *rdata) {
+ soa_set(rdata, val, 16);
+}
diff --git a/lib/dns/spnego.asn1 b/lib/dns/spnego.asn1
new file mode 100644
index 0000000..43d152b
--- /dev/null
+++ b/lib/dns/spnego.asn1
@@ -0,0 +1,52 @@
+-- Copyright (C) The Internet Society 2005. This version of
+-- this module is part of RFC 4178; see the RFC itself for
+-- full legal notices.
+
+-- (The above copyright notice is per RFC 3978 5.6 (a), q.v.)
+
+-- $Id: spnego.asn1,v 1.2 2006/12/04 01:52:46 marka Exp $
+
+-- This is the SPNEGO ASN.1 module from RFC 4178, tweaked
+-- to get the Heimdal ASN.1 compiler to accept it.
+
+SPNEGOASNOneSpec DEFINITIONS ::= BEGIN
+
+MechType ::= OBJECT IDENTIFIER
+
+MechTypeList ::= SEQUENCE OF MechType
+
+ContextFlags ::= BIT STRING {
+ delegFlag (0),
+ mutualFlag (1),
+ replayFlag (2),
+ sequenceFlag (3),
+ anonFlag (4),
+ confFlag (5),
+ integFlag (6)
+}
+
+NegTokenInit ::= SEQUENCE {
+ mechTypes [0] MechTypeList,
+ reqFlags [1] ContextFlags OPTIONAL,
+ mechToken [2] OCTET STRING OPTIONAL,
+ mechListMIC [3] OCTET STRING OPTIONAL
+}
+
+NegTokenResp ::= SEQUENCE {
+ negState [0] ENUMERATED {
+ accept-completed (0),
+ accept-incomplete (1),
+ reject (2),
+ request-mic (3)
+ } OPTIONAL,
+ supportedMech [1] MechType OPTIONAL,
+ responseToken [2] OCTET STRING OPTIONAL,
+ mechListMIC [3] OCTET STRING OPTIONAL
+}
+
+NegotiationToken ::= CHOICE {
+ negTokenInit [0] NegTokenInit,
+ negTokenResp [1] NegTokenResp
+}
+
+END
diff --git a/lib/dns/spnego.c b/lib/dns/spnego.c
new file mode 100644
index 0000000..a9dbbbd
--- /dev/null
+++ b/lib/dns/spnego.c
@@ -0,0 +1,1792 @@
+/*
+ * Copyright (C) 2006-2008 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: spnego.c,v 1.8 2008/04/03 06:09:04 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Portable SPNEGO implementation.
+ *
+ * This is part of a portable implementation of the SPNEGO protocol
+ * (RFCs 2478 and 4178). This implementation uses the RFC 4178 ASN.1
+ * module but is not a full implementation of the RFC 4178 protocol;
+ * at the moment, we only support GSS-TSIG with Kerberos
+ * authentication, so we only need enough of the SPNEGO protocol to
+ * support that.
+ *
+ * The files that make up this portable SPNEGO implementation are:
+ * \li spnego.c (this file)
+ * \li spnego.h (API SPNEGO exports to the rest of lib/dns)
+ * \li spnego.asn1 (SPNEGO ASN.1 module)
+ * \li spnego_asn1.c (routines generated from spngo.asn1)
+ * \li spnego_asn1.pl (perl script to generate spnego_asn1.c)
+ *
+ * Everything but the functions exported in spnego.h is static, to
+ * avoid possible conflicts with other libraries (particularly Heimdal,
+ * since much of this code comes from Heimdal by way of mod_auth_kerb).
+ *
+ * spnego_asn1.c is shipped as part of lib/dns because generating it
+ * requires both Perl and the Heimdal ASN.1 compiler. See
+ * spnego_asn1.pl for further details. We've tried to eliminate all
+ * compiler warnings from the generated code, but you may see a few
+ * when using a compiler version we haven't tested yet.
+ */
+
+/*
+ * Portions of this code were derived from mod_auth_kerb and Heimdal.
+ * These packages are available from:
+ *
+ * http://modauthkerb.sourceforge.net/
+ * http://www.pdc.kth.se/heimdal/
+ *
+ * and were released under the following licenses:
+ *
+ * ----------------------------------------------------------------
+ *
+ * Copyright (c) 2004 Masarykova universita
+ * (Masaryk University, Brno, Czech Republic)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------
+ *
+ * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * XXXSRA We should omit this file entirely in Makefile.in via autoconf,
+ * but this will keep it from generating errors until that's written.
+ */
+
+#ifdef GSSAPI
+
+/*
+ * XXXSRA Some of the following files are almost certainly unnecessary,
+ * but using this list (borrowed from gssapictx.c) gets rid of some
+ * whacky compilation errors when building with MSVC and should be
+ * harmless in any case.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <isc/buffer.h>
+#include <isc/dir.h>
+#include <isc/entropy.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/once.h>
+#include <isc/random.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/types.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+
+#include <dst/gssapi.h>
+#include <dst/result.h>
+
+#include "dst_internal.h"
+
+/*
+ * The API we export
+ */
+#include "spnego.h"
+
+/* asn1_err.h */
+/* Generated from ../../../lib/asn1/asn1_err.et */
+
+typedef enum asn1_error_number {
+ ASN1_BAD_TIMEFORMAT = 1859794432,
+ ASN1_MISSING_FIELD = 1859794433,
+ ASN1_MISPLACED_FIELD = 1859794434,
+ ASN1_TYPE_MISMATCH = 1859794435,
+ ASN1_OVERFLOW = 1859794436,
+ ASN1_OVERRUN = 1859794437,
+ ASN1_BAD_ID = 1859794438,
+ ASN1_BAD_LENGTH = 1859794439,
+ ASN1_BAD_FORMAT = 1859794440,
+ ASN1_PARSE_ERROR = 1859794441
+} asn1_error_number;
+
+#define ERROR_TABLE_BASE_asn1 1859794432
+
+#define __asn1_common_definitions__
+
+typedef struct octet_string {
+ size_t length;
+ void *data;
+} octet_string;
+
+typedef char *general_string;
+
+typedef char *utf8_string;
+
+typedef struct oid {
+ size_t length;
+ unsigned *components;
+} oid;
+
+/* der.h */
+
+typedef enum {
+ ASN1_C_UNIV = 0, ASN1_C_APPL = 1,
+ ASN1_C_CONTEXT = 2, ASN1_C_PRIVATE = 3
+} Der_class;
+
+typedef enum {
+ PRIM = 0, CONS = 1
+} Der_type;
+
+/* Universal tags */
+
+enum {
+ UT_Boolean = 1,
+ UT_Integer = 2,
+ UT_BitString = 3,
+ UT_OctetString = 4,
+ UT_Null = 5,
+ UT_OID = 6,
+ UT_Enumerated = 10,
+ UT_Sequence = 16,
+ UT_Set = 17,
+ UT_PrintableString = 19,
+ UT_IA5String = 22,
+ UT_UTCTime = 23,
+ UT_GeneralizedTime = 24,
+ UT_VisibleString = 26,
+ UT_GeneralString = 27
+};
+
+#define ASN1_INDEFINITE 0xdce0deed
+
+static int
+der_get_length(const unsigned char *p, size_t len,
+ size_t * val, size_t * size);
+
+static int
+der_get_octet_string(const unsigned char *p, size_t len,
+ octet_string * data, size_t * size);
+static int
+der_get_oid(const unsigned char *p, size_t len,
+ oid * data, size_t * size);
+static int
+der_get_tag(const unsigned char *p, size_t len,
+ Der_class * class, Der_type * type,
+ int *tag, size_t * size);
+
+static int
+der_match_tag(const unsigned char *p, size_t len,
+ Der_class class, Der_type type,
+ int tag, size_t * size);
+static int
+der_match_tag_and_length(const unsigned char *p, size_t len,
+ Der_class class, Der_type type, int tag,
+ size_t * length_ret, size_t * size);
+
+static int
+decode_oid(const unsigned char *p, size_t len,
+ oid * k, size_t * size);
+
+static int
+decode_enumerated(const unsigned char *p, size_t len,
+ unsigned *num, size_t *size);
+
+static int
+decode_octet_string(const unsigned char *, size_t, octet_string *, size_t *);
+
+static int
+der_put_int(unsigned char *p, size_t len, int val, size_t *);
+
+static int
+der_put_length(unsigned char *p, size_t len, size_t val, size_t *);
+
+static int
+der_put_octet_string(unsigned char *p, size_t len,
+ const octet_string * data, size_t *);
+static int
+der_put_oid(unsigned char *p, size_t len,
+ const oid * data, size_t * size);
+static int
+der_put_tag(unsigned char *p, size_t len, Der_class class, Der_type type,
+ int tag, size_t *);
+static int
+der_put_length_and_tag(unsigned char *, size_t, size_t,
+ Der_class, Der_type, int, size_t *);
+
+static int
+encode_enumerated(unsigned char *p, size_t len,
+ const unsigned *data, size_t *);
+
+static int
+encode_octet_string(unsigned char *p, size_t len,
+ const octet_string * k, size_t *);
+static int
+encode_oid(unsigned char *p, size_t len,
+ const oid * k, size_t *);
+
+static void
+free_octet_string(octet_string * k);
+
+static void
+free_oid (oid * k);
+
+static size_t
+length_len(size_t len);
+
+static int
+fix_dce(size_t reallen, size_t * len);
+
+/*
+ * Include stuff generated by the ASN.1 compiler.
+ */
+
+#include "spnego_asn1.c"
+
+static unsigned char gss_krb5_mech_oid_bytes[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02
+};
+
+static gss_OID_desc gss_krb5_mech_oid_desc = {
+ sizeof(gss_krb5_mech_oid_bytes),
+ gss_krb5_mech_oid_bytes
+};
+
+static gss_OID GSS_KRB5_MECH = &gss_krb5_mech_oid_desc;
+
+static unsigned char gss_mskrb5_mech_oid_bytes[] = {
+ 0x2a, 0x86, 0x48, 0x82, 0xf7, 0x12, 0x01, 0x02, 0x02
+};
+
+static gss_OID_desc gss_mskrb5_mech_oid_desc = {
+ sizeof(gss_mskrb5_mech_oid_bytes),
+ gss_mskrb5_mech_oid_bytes
+};
+
+static gss_OID GSS_MSKRB5_MECH = &gss_mskrb5_mech_oid_desc;
+
+static unsigned char gss_spnego_mech_oid_bytes[] = {
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02
+};
+
+static gss_OID_desc gss_spnego_mech_oid_desc = {
+ sizeof(gss_spnego_mech_oid_bytes),
+ gss_spnego_mech_oid_bytes
+};
+
+static gss_OID GSS_SPNEGO_MECH = &gss_spnego_mech_oid_desc;
+
+/* spnegokrb5_locl.h */
+
+static OM_uint32
+gssapi_spnego_encapsulate(OM_uint32 *,
+ unsigned char *,
+ size_t,
+ gss_buffer_t,
+ const gss_OID);
+
+static OM_uint32
+gssapi_spnego_decapsulate(OM_uint32 *,
+ gss_buffer_t,
+ unsigned char **,
+ size_t *,
+ const gss_OID);
+
+/* mod_auth_kerb.c */
+
+static int
+cmp_gss_type(gss_buffer_t token, gss_OID oid)
+{
+ unsigned char *p;
+ size_t len;
+
+ if (token->length == 0)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ p = token->value;
+ if (*p++ != 0x60)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ len = *p++;
+ if (len & 0x80) {
+ if ((len & 0x7f) > 4)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ p += len & 0x7f;
+ }
+ if (*p++ != 0x06)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ if (((OM_uint32) *p++) != oid->length)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ return (memcmp(p, oid->elements, oid->length));
+}
+
+/* accept_sec_context.c */
+/*
+ * SPNEGO wrapper for Kerberos5 GSS-API kouril@ics.muni.cz, 2003 (mostly
+ * based on Heimdal code)
+ */
+
+static OM_uint32
+code_NegTokenArg(OM_uint32 * minor_status,
+ const NegTokenResp * resp,
+ unsigned char **outbuf,
+ size_t * outbuf_size)
+{
+ OM_uint32 ret;
+ u_char *buf;
+ size_t buf_size, buf_len;
+
+ buf_size = 1024;
+ buf = malloc(buf_size);
+ if (buf == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ do {
+ ret = encode_NegTokenResp(buf + buf_size - 1,
+ buf_size,
+ resp, &buf_len);
+ if (ret == 0) {
+ size_t tmp;
+
+ ret = der_put_length_and_tag(buf + buf_size - buf_len - 1,
+ buf_size - buf_len,
+ buf_len,
+ ASN1_C_CONTEXT,
+ CONS,
+ 1,
+ &tmp);
+ if (ret == 0)
+ buf_len += tmp;
+ }
+ if (ret) {
+ if (ret == ASN1_OVERFLOW) {
+ u_char *tmp;
+
+ buf_size *= 2;
+ tmp = realloc(buf, buf_size);
+ if (tmp == NULL) {
+ *minor_status = ENOMEM;
+ free(buf);
+ return (GSS_S_FAILURE);
+ }
+ buf = tmp;
+ } else {
+ *minor_status = ret;
+ free(buf);
+ return (GSS_S_FAILURE);
+ }
+ }
+ } while (ret == ASN1_OVERFLOW);
+
+ *outbuf = malloc(buf_len);
+ if (*outbuf == NULL) {
+ *minor_status = ENOMEM;
+ free(buf);
+ return (GSS_S_FAILURE);
+ }
+ memcpy(*outbuf, buf + buf_size - buf_len, buf_len);
+ *outbuf_size = buf_len;
+
+ free(buf);
+
+ return (GSS_S_COMPLETE);
+}
+
+static OM_uint32
+send_reject(OM_uint32 * minor_status,
+ gss_buffer_t output_token)
+{
+ NegTokenResp resp;
+ OM_uint32 ret;
+
+ resp.negState = malloc(sizeof(*resp.negState));
+ if (resp.negState == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ *(resp.negState) = reject;
+
+ resp.supportedMech = NULL;
+ resp.responseToken = NULL;
+ resp.mechListMIC = NULL;
+
+ ret = code_NegTokenArg(minor_status, &resp,
+ (unsigned char **)&output_token->value,
+ &output_token->length);
+ free_NegTokenResp(&resp);
+ if (ret)
+ return (ret);
+
+ return (GSS_S_BAD_MECH);
+}
+
+static OM_uint32
+send_accept(OM_uint32 * minor_status,
+ gss_buffer_t output_token,
+ gss_buffer_t mech_token,
+ const gss_OID pref)
+{
+ NegTokenResp resp;
+ OM_uint32 ret;
+
+ memset(&resp, 0, sizeof(resp));
+ resp.negState = malloc(sizeof(*resp.negState));
+ if (resp.negState == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ *(resp.negState) = accept_completed;
+
+ resp.supportedMech = malloc(sizeof(*resp.supportedMech));
+ if (resp.supportedMech == NULL) {
+ free_NegTokenResp(&resp);
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ ret = der_get_oid(pref->elements,
+ pref->length,
+ resp.supportedMech,
+ NULL);
+ if (ret) {
+ free_NegTokenResp(&resp);
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ if (mech_token != NULL && mech_token->length != 0) {
+ resp.responseToken = malloc(sizeof(*resp.responseToken));
+ if (resp.responseToken == NULL) {
+ free_NegTokenResp(&resp);
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ resp.responseToken->length = mech_token->length;
+ resp.responseToken->data = mech_token->value;
+ }
+
+ ret = code_NegTokenArg(minor_status, &resp,
+ (unsigned char **)&output_token->value,
+ &output_token->length);
+ if (resp.responseToken != NULL) {
+ free(resp.responseToken);
+ resp.responseToken = NULL;
+ }
+ free_NegTokenResp(&resp);
+ if (ret)
+ return (ret);
+
+ return (GSS_S_COMPLETE);
+}
+
+OM_uint32
+gss_accept_sec_context_spnego(OM_uint32 *minor_status,
+ gss_ctx_id_t *context_handle,
+ const gss_cred_id_t acceptor_cred_handle,
+ const gss_buffer_t input_token_buffer,
+ const gss_channel_bindings_t input_chan_bindings,
+ gss_name_t *src_name,
+ gss_OID *mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec,
+ gss_cred_id_t *delegated_cred_handle)
+{
+ NegTokenInit init_token;
+ OM_uint32 major_status;
+ OM_uint32 minor_status2;
+ gss_buffer_desc ibuf, obuf;
+ gss_buffer_t ot = NULL;
+ gss_OID pref = GSS_KRB5_MECH;
+ unsigned char *buf;
+ size_t buf_size;
+ size_t len, taglen, ni_len;
+ int found = 0;
+ int ret;
+ unsigned i;
+
+ /*
+ * Before doing anything else, see whether this is a SPNEGO
+ * PDU. If not, dispatch to the GSSAPI library and get out.
+ */
+
+ if (cmp_gss_type(input_token_buffer, GSS_SPNEGO_MECH))
+ return (gss_accept_sec_context(minor_status,
+ context_handle,
+ acceptor_cred_handle,
+ input_token_buffer,
+ input_chan_bindings,
+ src_name,
+ mech_type,
+ output_token,
+ ret_flags,
+ time_rec,
+ delegated_cred_handle));
+
+ /*
+ * If we get here, it's SPNEGO.
+ */
+
+ memset(&init_token, 0, sizeof(init_token));
+
+ ret = gssapi_spnego_decapsulate(minor_status, input_token_buffer,
+ &buf, &buf_size, GSS_SPNEGO_MECH);
+ if (ret)
+ return (ret);
+
+ ret = der_match_tag_and_length(buf, buf_size, ASN1_C_CONTEXT, CONS,
+ 0, &len, &taglen);
+ if (ret)
+ return (ret);
+
+ ret = decode_NegTokenInit(buf + taglen, len, &init_token, &ni_len);
+ if (ret) {
+ *minor_status = EINVAL; /* XXX */
+ return (GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ for (i = 0; !found && i < init_token.mechTypes.len; ++i) {
+ char mechbuf[17];
+ size_t mech_len;
+
+ ret = der_put_oid(mechbuf + sizeof(mechbuf) - 1,
+ sizeof(mechbuf),
+ &init_token.mechTypes.val[i],
+ &mech_len);
+ if (ret)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ if (mech_len == GSS_KRB5_MECH->length &&
+ memcmp(GSS_KRB5_MECH->elements,
+ mechbuf + sizeof(mechbuf) - mech_len,
+ mech_len) == 0) {
+ found = 1;
+ break;
+ }
+ if (mech_len == GSS_MSKRB5_MECH->length &&
+ memcmp(GSS_MSKRB5_MECH->elements,
+ mechbuf + sizeof(mechbuf) - mech_len,
+ mech_len) == 0) {
+ found = 1;
+ if (i == 0)
+ pref = GSS_MSKRB5_MECH;
+ break;
+ }
+ }
+
+ if (!found)
+ return (send_reject(minor_status, output_token));
+
+ if (i == 0 && init_token.mechToken != NULL) {
+ ibuf.length = init_token.mechToken->length;
+ ibuf.value = init_token.mechToken->data;
+
+ major_status = gss_accept_sec_context(minor_status,
+ context_handle,
+ acceptor_cred_handle,
+ &ibuf,
+ input_chan_bindings,
+ src_name,
+ mech_type,
+ &obuf,
+ ret_flags,
+ time_rec,
+ delegated_cred_handle);
+ if (GSS_ERROR(major_status)) {
+ send_reject(&minor_status2, output_token);
+ return (major_status);
+ }
+ ot = &obuf;
+ }
+ ret = send_accept(&minor_status2, output_token, ot, pref);
+ if (ot != NULL && ot->length != 0)
+ gss_release_buffer(&minor_status2, ot);
+
+ return (ret);
+}
+
+/* decapsulate.c */
+
+static OM_uint32
+gssapi_verify_mech_header(u_char ** str,
+ size_t total_len,
+ const gss_OID mech)
+{
+ size_t len, len_len, mech_len, foo;
+ int e;
+ u_char *p = *str;
+
+ if (total_len < 1)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ if (*p++ != 0x60)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ e = der_get_length(p, total_len - 1, &len, &len_len);
+ if (e || 1 + len_len + len != total_len)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ p += len_len;
+ if (*p++ != 0x06)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ e = der_get_length(p, total_len - 1 - len_len - 1,
+ &mech_len, &foo);
+ if (e)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ p += foo;
+ if (mech_len != mech->length)
+ return (GSS_S_BAD_MECH);
+ if (memcmp(p, mech->elements, mech->length) != 0)
+ return (GSS_S_BAD_MECH);
+ p += mech_len;
+ *str = p;
+ return (GSS_S_COMPLETE);
+}
+
+/*
+ * Remove the GSS-API wrapping from `in_token' giving `buf and buf_size' Does
+ * not copy data, so just free `in_token'.
+ */
+
+static OM_uint32
+gssapi_spnego_decapsulate(OM_uint32 *minor_status,
+ gss_buffer_t input_token_buffer,
+ unsigned char **buf,
+ size_t *buf_len,
+ const gss_OID mech)
+{
+ u_char *p;
+ OM_uint32 ret;
+
+ p = input_token_buffer->value;
+ ret = gssapi_verify_mech_header(&p,
+ input_token_buffer->length,
+ mech);
+ if (ret) {
+ *minor_status = ret;
+ return (GSS_S_FAILURE);
+ }
+ *buf_len = input_token_buffer->length -
+ (p - (u_char *) input_token_buffer->value);
+ *buf = p;
+ return (GSS_S_COMPLETE);
+}
+
+/* der_free.c */
+
+static void
+free_octet_string(octet_string *k)
+{
+ free(k->data);
+ k->data = NULL;
+}
+
+static void
+free_oid(oid *k)
+{
+ free(k->components);
+ k->components = NULL;
+}
+
+/* der_get.c */
+
+/*
+ * All decoding functions take a pointer `p' to first position in which to
+ * read, from the left, `len' which means the maximum number of characters we
+ * are able to read, `ret' were the value will be returned and `size' where
+ * the number of used bytes is stored. Either 0 or an error code is returned.
+ */
+
+static int
+der_get_unsigned(const unsigned char *p, size_t len,
+ unsigned *ret, size_t *size)
+{
+ unsigned val = 0;
+ size_t oldlen = len;
+
+ while (len--)
+ val = val * 256 + *p++;
+ *ret = val;
+ if (size)
+ *size = oldlen;
+ return (0);
+}
+
+static int
+der_get_int(const unsigned char *p, size_t len,
+ int *ret, size_t *size)
+{
+ int val = 0;
+ size_t oldlen = len;
+
+ if (len > 0) {
+ val = (signed char)*p++;
+ while (--len)
+ val = val * 256 + *p++;
+ }
+ *ret = val;
+ if (size)
+ *size = oldlen;
+ return (0);
+}
+
+static int
+der_get_length(const unsigned char *p, size_t len,
+ size_t *val, size_t *size)
+{
+ size_t v;
+
+ if (len <= 0)
+ return (ASN1_OVERRUN);
+ --len;
+ v = *p++;
+ if (v < 128) {
+ *val = v;
+ if (size)
+ *size = 1;
+ } else {
+ int e;
+ size_t l;
+ unsigned tmp;
+
+ if (v == 0x80) {
+ *val = ASN1_INDEFINITE;
+ if (size)
+ *size = 1;
+ return (0);
+ }
+ v &= 0x7F;
+ if (len < v)
+ return (ASN1_OVERRUN);
+ e = der_get_unsigned(p, v, &tmp, &l);
+ if (e)
+ return (e);
+ *val = tmp;
+ if (size)
+ *size = l + 1;
+ }
+ return (0);
+}
+
+static int
+der_get_octet_string(const unsigned char *p, size_t len,
+ octet_string *data, size_t *size)
+{
+ data->length = len;
+ data->data = malloc(len);
+ if (data->data == NULL && data->length != 0)
+ return (ENOMEM);
+ memcpy(data->data, p, len);
+ if (size)
+ *size = len;
+ return (0);
+}
+
+static int
+der_get_oid(const unsigned char *p, size_t len,
+ oid *data, size_t *size)
+{
+ int n;
+ size_t oldlen = len;
+
+ if (len < 1)
+ return (ASN1_OVERRUN);
+
+ data->components = malloc(len * sizeof(*data->components));
+ if (data->components == NULL && len != 0)
+ return (ENOMEM);
+ data->components[0] = (*p) / 40;
+ data->components[1] = (*p) % 40;
+ --len;
+ ++p;
+ for (n = 2; len > 0; ++n) {
+ unsigned u = 0;
+
+ do {
+ --len;
+ u = u * 128 + (*p++ % 128);
+ } while (len > 0 && p[-1] & 0x80);
+ data->components[n] = u;
+ }
+ if (p[-1] & 0x80) {
+ free_oid(data);
+ return (ASN1_OVERRUN);
+ }
+ data->length = n;
+ if (size)
+ *size = oldlen;
+ return (0);
+}
+
+static int
+der_get_tag(const unsigned char *p, size_t len,
+ Der_class *class, Der_type *type,
+ int *tag, size_t *size)
+{
+ if (len < 1)
+ return (ASN1_OVERRUN);
+ *class = (Der_class) (((*p) >> 6) & 0x03);
+ *type = (Der_type) (((*p) >> 5) & 0x01);
+ *tag = (*p) & 0x1F;
+ if (size)
+ *size = 1;
+ return (0);
+}
+
+static int
+der_match_tag(const unsigned char *p, size_t len,
+ Der_class class, Der_type type,
+ int tag, size_t *size)
+{
+ size_t l;
+ Der_class thisclass;
+ Der_type thistype;
+ int thistag;
+ int e;
+
+ e = der_get_tag(p, len, &thisclass, &thistype, &thistag, &l);
+ if (e)
+ return (e);
+ if (class != thisclass || type != thistype)
+ return (ASN1_BAD_ID);
+ if (tag > thistag)
+ return (ASN1_MISPLACED_FIELD);
+ if (tag < thistag)
+ return (ASN1_MISSING_FIELD);
+ if (size)
+ *size = l;
+ return (0);
+}
+
+static int
+der_match_tag_and_length(const unsigned char *p, size_t len,
+ Der_class class, Der_type type, int tag,
+ size_t *length_ret, size_t *size)
+{
+ size_t l, ret = 0;
+ int e;
+
+ e = der_match_tag(p, len, class, type, tag, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, length_ret, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+decode_enumerated(const unsigned char *p, size_t len,
+ unsigned *num, size_t *size)
+{
+ size_t ret = 0;
+ size_t l, reallen;
+ int e;
+
+ e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &reallen, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_int(p, reallen, num, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+decode_octet_string(const unsigned char *p, size_t len,
+ octet_string *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+ size_t slen;
+
+ e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+
+ e = der_get_length(p, len, &slen, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (len < slen)
+ return (ASN1_OVERRUN);
+
+ e = der_get_octet_string(p, slen, k, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+decode_oid(const unsigned char *p, size_t len,
+ oid *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+ size_t slen;
+
+ e = der_match_tag(p, len, ASN1_C_UNIV, PRIM, UT_OID, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+
+ e = der_get_length(p, len, &slen, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (len < slen)
+ return (ASN1_OVERRUN);
+
+ e = der_get_oid(p, slen, k, &l);
+ if (e)
+ return (e);
+ p += l;
+ len -= l;
+ ret += l;
+ if (size)
+ *size = ret;
+ return (0);
+}
+
+static int
+fix_dce(size_t reallen, size_t *len)
+{
+ if (reallen == ASN1_INDEFINITE)
+ return (1);
+ if (*len < reallen)
+ return (-1);
+ *len = reallen;
+ return (0);
+}
+
+/* der_length.c */
+
+static size_t
+len_unsigned(unsigned val)
+{
+ size_t ret = 0;
+
+ do {
+ ++ret;
+ val /= 256;
+ } while (val);
+ return (ret);
+}
+
+static size_t
+length_len(size_t len)
+{
+ if (len < 128)
+ return (1);
+ else
+ return (len_unsigned(len) + 1);
+}
+
+
+/* der_put.c */
+
+/*
+ * All encoding functions take a pointer `p' to first position in which to
+ * write, from the right, `len' which means the maximum number of characters
+ * we are able to write. The function returns the number of characters
+ * written in `size' (if non-NULL). The return value is 0 or an error.
+ */
+
+static int
+der_put_unsigned(unsigned char *p, size_t len, unsigned val, size_t *size)
+{
+ unsigned char *base = p;
+
+ if (val) {
+ while (len > 0 && val) {
+ *p-- = val % 256;
+ val /= 256;
+ --len;
+ }
+ if (val != 0)
+ return (ASN1_OVERFLOW);
+ else {
+ *size = base - p;
+ return (0);
+ }
+ } else if (len < 1)
+ return (ASN1_OVERFLOW);
+ else {
+ *p = 0;
+ *size = 1;
+ return (0);
+ }
+}
+
+static int
+der_put_int(unsigned char *p, size_t len, int val, size_t *size)
+{
+ unsigned char *base = p;
+
+ if (val >= 0) {
+ do {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = val % 256;
+ len--;
+ val /= 256;
+ } while (val);
+ if (p[1] >= 128) {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 0;
+ len--;
+ }
+ } else {
+ val = ~val;
+ do {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = ~(val % 256);
+ len--;
+ val /= 256;
+ } while (val);
+ if (p[1] < 128) {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 0xff;
+ len--;
+ }
+ }
+ *size = base - p;
+ return (0);
+}
+
+static int
+der_put_length(unsigned char *p, size_t len, size_t val, size_t *size)
+{
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ if (val < 128) {
+ *p = val;
+ *size = 1;
+ return (0);
+ } else {
+ size_t l;
+ int e;
+
+ e = der_put_unsigned(p, len - 1, val, &l);
+ if (e)
+ return (e);
+ p -= l;
+ *p = 0x80 | l;
+ *size = l + 1;
+ return (0);
+ }
+}
+
+static int
+der_put_octet_string(unsigned char *p, size_t len,
+ const octet_string *data, size_t *size)
+{
+ if (len < data->length)
+ return (ASN1_OVERFLOW);
+ p -= data->length;
+ len -= data->length;
+ memcpy(p + 1, data->data, data->length);
+ *size = data->length;
+ return (0);
+}
+
+static int
+der_put_oid(unsigned char *p, size_t len,
+ const oid *data, size_t *size)
+{
+ unsigned char *base = p;
+ int n;
+
+ for (n = data->length - 1; n >= 2; --n) {
+ unsigned u = data->components[n];
+
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = u % 128;
+ u /= 128;
+ --len;
+ while (u > 0) {
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 128 + u % 128;
+ u /= 128;
+ --len;
+ }
+ }
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p-- = 40 * data->components[0] + data->components[1];
+ *size = base - p;
+ return (0);
+}
+
+static int
+der_put_tag(unsigned char *p, size_t len, Der_class class, Der_type type,
+ int tag, size_t *size)
+{
+ if (len < 1)
+ return (ASN1_OVERFLOW);
+ *p = (class << 6) | (type << 5) | tag; /* XXX */
+ *size = 1;
+ return (0);
+}
+
+static int
+der_put_length_and_tag(unsigned char *p, size_t len, size_t len_val,
+ Der_class class, Der_type type, int tag, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_length(p, len, len_val, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_tag(p, len, class, type, tag, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+static int
+encode_enumerated(unsigned char *p, size_t len, const unsigned *data,
+ size_t *size)
+{
+ unsigned num = *data;
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_int(p, len, num, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+static int
+encode_octet_string(unsigned char *p, size_t len,
+ const octet_string *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_octet_string(p, len, k, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+static int
+encode_oid(unsigned char *p, size_t len,
+ const oid *k, size_t *size)
+{
+ size_t ret = 0;
+ size_t l;
+ int e;
+
+ e = der_put_oid(p, len, k, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ e = der_put_length_and_tag(p, len, l, ASN1_C_UNIV, PRIM, UT_OID, &l);
+ if (e)
+ return (e);
+ p -= l;
+ len -= l;
+ ret += l;
+ *size = ret;
+ return (0);
+}
+
+
+/* encapsulate.c */
+
+static void
+gssapi_encap_length(size_t data_len,
+ size_t *len,
+ size_t *total_len,
+ const gss_OID mech)
+{
+ size_t len_len;
+
+ *len = 1 + 1 + mech->length + data_len;
+
+ len_len = length_len(*len);
+
+ *total_len = 1 + len_len + *len;
+}
+
+static u_char *
+gssapi_mech_make_header(u_char *p,
+ size_t len,
+ const gss_OID mech)
+{
+ int e;
+ size_t len_len, foo;
+
+ *p++ = 0x60;
+ len_len = length_len(len);
+ e = der_put_length(p + len_len - 1, len_len, len, &foo);
+ if (e || foo != len_len)
+ return (NULL);
+ p += len_len;
+ *p++ = 0x06;
+ *p++ = mech->length;
+ memcpy(p, mech->elements, mech->length);
+ p += mech->length;
+ return (p);
+}
+
+/*
+ * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings.
+ */
+
+static OM_uint32
+gssapi_spnego_encapsulate(OM_uint32 * minor_status,
+ unsigned char *buf,
+ size_t buf_size,
+ gss_buffer_t output_token,
+ const gss_OID mech)
+{
+ size_t len, outer_len;
+ u_char *p;
+
+ gssapi_encap_length(buf_size, &len, &outer_len, mech);
+
+ output_token->length = outer_len;
+ output_token->value = malloc(outer_len);
+ if (output_token->value == NULL) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+ p = gssapi_mech_make_header(output_token->value, len, mech);
+ if (p == NULL) {
+ if (output_token->length != 0)
+ gss_release_buffer(minor_status, output_token);
+ return (GSS_S_FAILURE);
+ }
+ memcpy(p, buf, buf_size);
+ return (GSS_S_COMPLETE);
+}
+
+/* init_sec_context.c */
+/*
+ * SPNEGO wrapper for Kerberos5 GSS-API kouril@ics.muni.cz, 2003 (mostly
+ * based on Heimdal code)
+ */
+
+static int
+add_mech(MechTypeList * mech_list, gss_OID mech)
+{
+ MechType *tmp;
+ int ret;
+
+ tmp = realloc(mech_list->val, (mech_list->len + 1) * sizeof(*tmp));
+ if (tmp == NULL)
+ return (ENOMEM);
+ mech_list->val = tmp;
+
+ ret = der_get_oid(mech->elements, mech->length,
+ &mech_list->val[mech_list->len], NULL);
+ if (ret)
+ return (ret);
+
+ mech_list->len++;
+ return (0);
+}
+
+/*
+ * return the length of the mechanism in token or -1
+ * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN
+ */
+
+static ssize_t
+gssapi_krb5_get_mech(const u_char *ptr,
+ size_t total_len,
+ const u_char **mech_ret)
+{
+ size_t len, len_len, mech_len, foo;
+ const u_char *p = ptr;
+ int e;
+
+ if (total_len < 1)
+ return (-1);
+ if (*p++ != 0x60)
+ return (-1);
+ e = der_get_length (p, total_len - 1, &len, &len_len);
+ if (e || 1 + len_len + len != total_len)
+ return (-1);
+ p += len_len;
+ if (*p++ != 0x06)
+ return (-1);
+ e = der_get_length (p, total_len - 1 - len_len - 1,
+ &mech_len, &foo);
+ if (e)
+ return (-1);
+ p += foo;
+ *mech_ret = p;
+ return (mech_len);
+}
+
+static OM_uint32
+spnego_initial(OM_uint32 *minor_status,
+ const gss_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ const gss_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ NegTokenInit token_init;
+ OM_uint32 major_status, minor_status2;
+ gss_buffer_desc krb5_output_token = GSS_C_EMPTY_BUFFER;
+ unsigned char *buf = NULL;
+ size_t buf_size;
+ size_t len;
+ int ret;
+
+ (void)mech_type;
+
+ memset(&token_init, 0, sizeof(token_init));
+
+ ret = add_mech(&token_init.mechTypes, GSS_KRB5_MECH);
+ if (ret) {
+ *minor_status = ret;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+
+ major_status = gss_init_sec_context(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ GSS_KRB5_MECH,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ &krb5_output_token,
+ ret_flags,
+ time_rec);
+ if (GSS_ERROR(major_status)) {
+ ret = major_status;
+ goto end;
+ }
+ if (krb5_output_token.length > 0) {
+ token_init.mechToken = malloc(sizeof(*token_init.mechToken));
+ if (token_init.mechToken == NULL) {
+ *minor_status = ENOMEM;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ token_init.mechToken->data = krb5_output_token.value;
+ token_init.mechToken->length = krb5_output_token.length;
+ }
+ /*
+ * The MS implementation of SPNEGO seems to not like the mechListMIC
+ * field, so we omit it (it's optional anyway)
+ */
+
+ buf_size = 1024;
+ buf = malloc(buf_size);
+
+ do {
+ ret = encode_NegTokenInit(buf + buf_size - 1,
+ buf_size,
+ &token_init, &len);
+ if (ret == 0) {
+ size_t tmp;
+
+ ret = der_put_length_and_tag(buf + buf_size - len - 1,
+ buf_size - len,
+ len,
+ ASN1_C_CONTEXT,
+ CONS,
+ 0,
+ &tmp);
+ if (ret == 0)
+ len += tmp;
+ }
+ if (ret) {
+ if (ret == ASN1_OVERFLOW) {
+ u_char *tmp;
+
+ buf_size *= 2;
+ tmp = realloc(buf, buf_size);
+ if (tmp == NULL) {
+ *minor_status = ENOMEM;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ buf = tmp;
+ } else {
+ *minor_status = ret;
+ ret = GSS_S_FAILURE;
+ goto end;
+ }
+ }
+ } while (ret == ASN1_OVERFLOW);
+
+ ret = gssapi_spnego_encapsulate(minor_status,
+ buf + buf_size - len, len,
+ output_token, GSS_SPNEGO_MECH);
+ if (ret == GSS_S_COMPLETE)
+ ret = major_status;
+
+end:
+ if (token_init.mechToken != NULL) {
+ free(token_init.mechToken);
+ token_init.mechToken = NULL;
+ }
+ free_NegTokenInit(&token_init);
+ if (krb5_output_token.length != 0)
+ gss_release_buffer(&minor_status2, &krb5_output_token);
+ if (buf)
+ free(buf);
+
+ return (ret);
+}
+
+static OM_uint32
+spnego_reply(OM_uint32 *minor_status,
+ const gss_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ const gss_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ OM_uint32 ret;
+ NegTokenResp resp;
+ unsigned char *buf;
+ size_t buf_size;
+ u_char oidbuf[17];
+ size_t oidlen;
+ gss_buffer_desc sub_token;
+ ssize_t mech_len;
+ const u_char *p;
+ size_t len, taglen;
+
+ (void)mech_type;
+
+ output_token->length = 0;
+ output_token->value = NULL;
+
+ /*
+ * SPNEGO doesn't include gss wrapping on SubsequentContextToken
+ * like the Kerberos 5 mech does. But lets check for it anyway.
+ */
+
+ mech_len = gssapi_krb5_get_mech(input_token->value,
+ input_token->length,
+ &p);
+
+ if (mech_len < 0) {
+ buf = input_token->value;
+ buf_size = input_token->length;
+ } else if ((size_t)mech_len == GSS_KRB5_MECH->length &&
+ memcmp(GSS_KRB5_MECH->elements, p, mech_len) == 0)
+ return (gss_init_sec_context(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ GSS_KRB5_MECH,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec));
+ else if ((size_t)mech_len == GSS_SPNEGO_MECH->length &&
+ memcmp(GSS_SPNEGO_MECH->elements, p, mech_len) == 0) {
+ ret = gssapi_spnego_decapsulate(minor_status,
+ input_token,
+ &buf,
+ &buf_size,
+ GSS_SPNEGO_MECH);
+ if (ret)
+ return (ret);
+ } else
+ return (GSS_S_BAD_MECH);
+
+ ret = der_match_tag_and_length(buf, buf_size,
+ ASN1_C_CONTEXT, CONS, 1, &len, &taglen);
+ if (ret)
+ return (ret);
+
+ if(len > buf_size - taglen)
+ return (ASN1_OVERRUN);
+
+ ret = decode_NegTokenResp(buf + taglen, len, &resp, NULL);
+ if (ret) {
+ *minor_status = ENOMEM;
+ return (GSS_S_FAILURE);
+ }
+
+ if (resp.negState == NULL ||
+ *(resp.negState) == reject ||
+ resp.supportedMech == NULL) {
+ free_NegTokenResp(&resp);
+ return (GSS_S_BAD_MECH);
+ }
+
+ ret = der_put_oid(oidbuf + sizeof(oidbuf) - 1,
+ sizeof(oidbuf),
+ resp.supportedMech,
+ &oidlen);
+ if (ret || oidlen != GSS_KRB5_MECH->length ||
+ memcmp(oidbuf + sizeof(oidbuf) - oidlen,
+ GSS_KRB5_MECH->elements,
+ oidlen) != 0) {
+ free_NegTokenResp(&resp);
+ return GSS_S_BAD_MECH;
+ }
+
+ if (resp.responseToken != NULL) {
+ sub_token.length = resp.responseToken->length;
+ sub_token.value = resp.responseToken->data;
+ } else {
+ sub_token.length = 0;
+ sub_token.value = NULL;
+ }
+
+ ret = gss_init_sec_context(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ GSS_KRB5_MECH,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ &sub_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec);
+ if (ret) {
+ free_NegTokenResp(&resp);
+ return (ret);
+ }
+
+ /*
+ * XXXSRA I don't think this limited implementation ever needs
+ * to check the MIC -- our preferred mechanism (Kerberos)
+ * authenticates its own messages and is the only mechanism
+ * we'll accept, so if the mechanism negotiation completes
+ * sucessfully, we don't need the MIC. See RFC 4178.
+ */
+
+ free_NegTokenResp(&resp);
+ return (ret);
+}
+
+
+
+OM_uint32
+gss_init_sec_context_spnego(OM_uint32 *minor_status,
+ const gss_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t *context_handle,
+ const gss_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const gss_buffer_t input_token,
+ gss_OID *actual_mech_type,
+ gss_buffer_t output_token,
+ OM_uint32 *ret_flags,
+ OM_uint32 *time_rec)
+{
+ /* Dirty trick to suppress compiler warnings */
+
+ /* Figure out whether we're starting over or processing a reply */
+
+ if (input_token == GSS_C_NO_BUFFER || input_token->length == 0)
+ return (spnego_initial(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ mech_type,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec));
+ else
+ return (spnego_reply(minor_status,
+ initiator_cred_handle,
+ context_handle,
+ target_name,
+ mech_type,
+ req_flags,
+ time_req,
+ input_chan_bindings,
+ input_token,
+ actual_mech_type,
+ output_token,
+ ret_flags,
+ time_rec));
+}
+
+#endif /* GSSAPI */
diff --git a/lib/dns/spnego.h b/lib/dns/spnego.h
new file mode 100644
index 0000000..c44614b
--- /dev/null
+++ b/lib/dns/spnego.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2006, 2007 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: spnego.h,v 1.4 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Entry points into portable SPNEGO implementation.
+ * See spnego.c for information on the SPNEGO implementation itself.
+ */
+
+#ifndef _SPNEGO_H_
+#define _SPNEGO_H_
+
+/*%
+ * Wrapper for GSSAPI gss_init_sec_context(), using portable SPNEGO
+ * implementation instead of the one that's part of the GSSAPI
+ * library. Takes arguments identical to the standard GSSAPI
+ * function, uses standard gss_init_sec_context() to handle
+ * everything inside the SPNEGO wrapper.
+ */
+OM_uint32
+gss_init_sec_context_spnego(OM_uint32 *,
+ const gss_cred_id_t,
+ gss_ctx_id_t *,
+ const gss_name_t,
+ const gss_OID,
+ OM_uint32,
+ OM_uint32,
+ const gss_channel_bindings_t,
+ const gss_buffer_t,
+ gss_OID *,
+ gss_buffer_t,
+ OM_uint32 *,
+ OM_uint32 *);
+
+/*%
+ * Wrapper for GSSAPI gss_accept_sec_context(), using portable SPNEGO
+ * implementation instead of the one that's part of the GSSAPI
+ * library. Takes arguments identical to the standard GSSAPI
+ * function. Checks the OID of the input token to see if it's SPNEGO;
+ * if so, processes it, otherwise hands the call off to the standard
+ * gss_accept_sec_context() function.
+ */
+OM_uint32 gss_accept_sec_context_spnego(OM_uint32 *,
+ gss_ctx_id_t *,
+ const gss_cred_id_t,
+ const gss_buffer_t,
+ const gss_channel_bindings_t,
+ gss_name_t *,
+ gss_OID *,
+ gss_buffer_t,
+ OM_uint32 *,
+ OM_uint32 *,
+ gss_cred_id_t *);
+
+
+#endif
diff --git a/lib/dns/spnego_asn1.c b/lib/dns/spnego_asn1.c
new file mode 100644
index 0000000..75c2304
--- /dev/null
+++ b/lib/dns/spnego_asn1.c
@@ -0,0 +1,885 @@
+/*
+ * Copyright (C) 2006, 2007 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: spnego_asn1.c,v 1.4 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file
+ * \brief Method routines generated from SPNEGO ASN.1 module.
+ * See spnego_asn1.pl for details. Do not edit.
+ */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+#ifndef __asn1_h__
+#define __asn1_h__
+
+
+#ifndef __asn1_common_definitions__
+#define __asn1_common_definitions__
+
+typedef struct octet_string {
+ size_t length;
+ void *data;
+} octet_string;
+
+typedef char *general_string;
+
+typedef char *utf8_string;
+
+typedef struct oid {
+ size_t length;
+ unsigned *components;
+} oid;
+
+#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \
+ do { \
+ (BL) = length_##T((S)); \
+ (B) = malloc((BL)); \
+ if((B) == NULL) { \
+ (R) = ENOMEM; \
+ } else { \
+ (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \
+ (S), (L)); \
+ if((R) != 0) { \
+ free((B)); \
+ (B) = NULL; \
+ } \
+ } \
+ } while (0)
+
+#endif
+
+/*
+ * MechType ::= OBJECT IDENTIFIER
+ */
+
+typedef oid MechType;
+
+static int encode_MechType(unsigned char *, size_t, const MechType *, size_t *);
+static int decode_MechType(const unsigned char *, size_t, MechType *, size_t *);
+static void free_MechType(MechType *);
+/* unused declaration: length_MechType */
+/* unused declaration: copy_MechType */
+
+
+/*
+ * MechTypeList ::= SEQUENCE OF MechType
+ */
+
+typedef struct MechTypeList {
+ unsigned int len;
+ MechType *val;
+} MechTypeList;
+
+static int encode_MechTypeList(unsigned char *, size_t, const MechTypeList *, size_t *);
+static int decode_MechTypeList(const unsigned char *, size_t, MechTypeList *, size_t *);
+static void free_MechTypeList(MechTypeList *);
+/* unused declaration: length_MechTypeList */
+/* unused declaration: copy_MechTypeList */
+
+
+/*
+ * ContextFlags ::= BIT STRING { delegFlag(0), mutualFlag(1), replayFlag(2),
+ * sequenceFlag(3), anonFlag(4), confFlag(5), integFlag(6) }
+ */
+
+typedef struct ContextFlags {
+ unsigned int delegFlag:1;
+ unsigned int mutualFlag:1;
+ unsigned int replayFlag:1;
+ unsigned int sequenceFlag:1;
+ unsigned int anonFlag:1;
+ unsigned int confFlag:1;
+ unsigned int integFlag:1;
+} ContextFlags;
+
+
+static int encode_ContextFlags(unsigned char *, size_t, const ContextFlags *, size_t *);
+static int decode_ContextFlags(const unsigned char *, size_t, ContextFlags *, size_t *);
+static void free_ContextFlags(ContextFlags *);
+/* unused declaration: length_ContextFlags */
+/* unused declaration: copy_ContextFlags */
+/* unused declaration: ContextFlags2int */
+/* unused declaration: int2ContextFlags */
+/* unused declaration: asn1_ContextFlags_units */
+
+/*
+ * NegTokenInit ::= SEQUENCE { mechTypes[0] MechTypeList, reqFlags[1]
+ * ContextFlags OPTIONAL, mechToken[2] OCTET STRING OPTIONAL,
+ * mechListMIC[3] OCTET STRING OPTIONAL }
+ */
+
+typedef struct NegTokenInit {
+ MechTypeList mechTypes;
+ ContextFlags *reqFlags;
+ octet_string *mechToken;
+ octet_string *mechListMIC;
+} NegTokenInit;
+
+static int encode_NegTokenInit(unsigned char *, size_t, const NegTokenInit *, size_t *);
+static int decode_NegTokenInit(const unsigned char *, size_t, NegTokenInit *, size_t *);
+static void free_NegTokenInit(NegTokenInit *);
+/* unused declaration: length_NegTokenInit */
+/* unused declaration: copy_NegTokenInit */
+
+
+/*
+ * NegTokenResp ::= SEQUENCE { negState[0] ENUMERATED {
+ * accept-completed(0), accept-incomplete(1), reject(2), request-mic(3) }
+ * OPTIONAL, supportedMech[1] MechType OPTIONAL, responseToken[2] OCTET
+ * STRING OPTIONAL, mechListMIC[3] OCTET STRING OPTIONAL }
+ */
+
+typedef struct NegTokenResp {
+ enum {
+ accept_completed = 0,
+ accept_incomplete = 1,
+ reject = 2,
+ request_mic = 3
+ } *negState;
+
+ MechType *supportedMech;
+ octet_string *responseToken;
+ octet_string *mechListMIC;
+} NegTokenResp;
+
+static int encode_NegTokenResp(unsigned char *, size_t, const NegTokenResp *, size_t *);
+static int decode_NegTokenResp(const unsigned char *, size_t, NegTokenResp *, size_t *);
+static void free_NegTokenResp(NegTokenResp *);
+/* unused declaration: length_NegTokenResp */
+/* unused declaration: copy_NegTokenResp */
+
+
+
+
+#endif /* __asn1_h__ */
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_MechType(unsigned char *p, size_t len, const MechType * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ e = encode_oid(p, len, data, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_MechType(const unsigned char *p, size_t len, MechType * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = decode_oid(p, len, data, &l);
+ FORW;
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_MechType(data);
+ return e;
+}
+
+static void
+free_MechType(MechType * data)
+{
+ free_oid(data);
+}
+
+/* unused function: length_MechType */
+
+
+/* unused function: copy_MechType */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_MechTypeList(unsigned char *p, size_t len, const MechTypeList * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ for (i = (data)->len - 1; i >= 0; --i) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_MechType(p, len, &(data)->val[i], &l);
+ BACK;
+ ret += oldret;
+ }
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_MechTypeList(const unsigned char *p, size_t len, MechTypeList * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
+ FORW;
+ if (len < reallen)
+ return ASN1_OVERRUN;
+ len = reallen;
+ {
+ size_t origlen = len;
+ int oldret = ret;
+ ret = 0;
+ (data)->len = 0;
+ (data)->val = NULL;
+ while (ret < origlen) {
+ (data)->len++;
+ (data)->val = realloc((data)->val, sizeof(*((data)->val)) * (data)->len);
+ e = decode_MechType(p, len, &(data)->val[(data)->len - 1], &l);
+ FORW;
+ len = origlen - ret;
+ }
+ ret += oldret;
+ }
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_MechTypeList(data);
+ return e;
+}
+
+static void
+free_MechTypeList(MechTypeList * data)
+{
+ while ((data)->len) {
+ free_MechType(&(data)->val[(data)->len - 1]);
+ (data)->len--;
+ }
+ free((data)->val);
+ (data)->val = NULL;
+}
+
+/* unused function: length_MechTypeList */
+
+
+/* unused function: copy_MechTypeList */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_ContextFlags(unsigned char *p, size_t len, const ContextFlags * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ {
+ unsigned char c = 0;
+ *p-- = c;
+ len--;
+ ret++;
+ c = 0;
+ *p-- = c;
+ len--;
+ ret++;
+ c = 0;
+ *p-- = c;
+ len--;
+ ret++;
+ c = 0;
+ if (data->integFlag)
+ c |= 1 << 1;
+ if (data->confFlag)
+ c |= 1 << 2;
+ if (data->anonFlag)
+ c |= 1 << 3;
+ if (data->sequenceFlag)
+ c |= 1 << 4;
+ if (data->replayFlag)
+ c |= 1 << 5;
+ if (data->mutualFlag)
+ c |= 1 << 6;
+ if (data->delegFlag)
+ c |= 1 << 7;
+ *p-- = c;
+ *p-- = 0;
+ len -= 2;
+ ret += 2;
+ }
+
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, PRIM, UT_BitString, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_ContextFlags(const unsigned char *p, size_t len, ContextFlags * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, PRIM, UT_BitString, &reallen, &l);
+ FORW;
+ if (len < reallen)
+ return ASN1_OVERRUN;
+ p++;
+ len--;
+ reallen--;
+ ret++;
+ data->delegFlag = (*p >> 7) & 1;
+ data->mutualFlag = (*p >> 6) & 1;
+ data->replayFlag = (*p >> 5) & 1;
+ data->sequenceFlag = (*p >> 4) & 1;
+ data->anonFlag = (*p >> 3) & 1;
+ data->confFlag = (*p >> 2) & 1;
+ data->integFlag = (*p >> 1) & 1;
+ p += reallen;
+ len -= reallen;
+ ret += reallen;
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_ContextFlags(data);
+ return e;
+}
+
+static void
+free_ContextFlags(ContextFlags * data)
+{
+ (void)data;
+}
+
+/* unused function: length_ContextFlags */
+
+
+/* unused function: copy_ContextFlags */
+
+
+/* unused function: ContextFlags2int */
+
+
+/* unused function: int2ContextFlags */
+
+
+/* unused variable: ContextFlags_units */
+
+/* unused function: asn1_ContextFlags_units */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_NegTokenInit(unsigned char *p, size_t len, const NegTokenInit * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ if ((data)->mechListMIC) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->mechListMIC, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 3, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->mechToken) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->mechToken, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 2, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->reqFlags) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_ContextFlags(p, len, (data)->reqFlags, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 1, &l);
+ BACK;
+ ret += oldret;
+ } {
+ int oldret = ret;
+ ret = 0;
+ e = encode_MechTypeList(p, len, &(data)->mechTypes, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 0, &l);
+ BACK;
+ ret += oldret;
+ }
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_NegTokenInit(const unsigned char *p, size_t len, NegTokenInit * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
+ FORW;
+ {
+ int dce_fix;
+ if ((dce_fix = fix_dce(reallen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 0, &l);
+ if (e)
+ return e;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ e = decode_MechTypeList(p, len, &(data)->mechTypes, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 1, &l);
+ if (e)
+ (data)->reqFlags = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->reqFlags = malloc(sizeof(*(data)->reqFlags));
+ if ((data)->reqFlags == NULL)
+ return ENOMEM;
+ e = decode_ContextFlags(p, len, (data)->reqFlags, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 2, &l);
+ if (e)
+ (data)->mechToken = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->mechToken = malloc(sizeof(*(data)->mechToken));
+ if ((data)->mechToken == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->mechToken, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 3, &l);
+ if (e)
+ (data)->mechListMIC = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->mechListMIC = malloc(sizeof(*(data)->mechListMIC));
+ if ((data)->mechListMIC == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->mechListMIC, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ }
+ }
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_NegTokenInit(data);
+ return e;
+}
+
+static void
+free_NegTokenInit(NegTokenInit * data)
+{
+ free_MechTypeList(&(data)->mechTypes);
+ if ((data)->reqFlags) {
+ free_ContextFlags((data)->reqFlags);
+ free((data)->reqFlags);
+ (data)->reqFlags = NULL;
+ }
+ if ((data)->mechToken) {
+ free_octet_string((data)->mechToken);
+ free((data)->mechToken);
+ (data)->mechToken = NULL;
+ }
+ if ((data)->mechListMIC) {
+ free_octet_string((data)->mechListMIC);
+ free((data)->mechListMIC);
+ (data)->mechListMIC = NULL;
+ }
+}
+
+/* unused function: length_NegTokenInit */
+
+
+/* unused function: copy_NegTokenInit */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+#define BACK if (e) return e; p -= l; len -= l; ret += l
+
+static int
+encode_NegTokenResp(unsigned char *p, size_t len, const NegTokenResp * data, size_t * size)
+{
+ size_t ret = 0;
+ size_t l;
+ int i, e;
+
+ i = 0;
+ if ((data)->mechListMIC) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->mechListMIC, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 3, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->responseToken) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_octet_string(p, len, (data)->responseToken, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 2, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->supportedMech) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_MechType(p, len, (data)->supportedMech, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 1, &l);
+ BACK;
+ ret += oldret;
+ }
+ if ((data)->negState) {
+ int oldret = ret;
+ ret = 0;
+ e = encode_enumerated(p, len, (data)->negState, &l);
+ BACK;
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_CONTEXT, CONS, 0, &l);
+ BACK;
+ ret += oldret;
+ }
+ e = der_put_length_and_tag(p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);
+ BACK;
+ *size = ret;
+ return 0;
+}
+
+#define FORW if(e) goto fail; p += l; len -= l; ret += l
+
+static int
+decode_NegTokenResp(const unsigned char *p, size_t len, NegTokenResp * data, size_t * size)
+{
+ size_t ret = 0, reallen;
+ size_t l;
+ int e;
+
+ memset(data, 0, sizeof(*data));
+ reallen = 0;
+ e = der_match_tag_and_length(p, len, ASN1_C_UNIV, CONS, UT_Sequence, &reallen, &l);
+ FORW;
+ {
+ int dce_fix;
+ if ((dce_fix = fix_dce(reallen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 0, &l);
+ if (e)
+ (data)->negState = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->negState = malloc(sizeof(*(data)->negState));
+ if ((data)->negState == NULL)
+ return ENOMEM;
+ e = decode_enumerated(p, len, (data)->negState, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 1, &l);
+ if (e)
+ (data)->supportedMech = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->supportedMech = malloc(sizeof(*(data)->supportedMech));
+ if ((data)->supportedMech == NULL)
+ return ENOMEM;
+ e = decode_MechType(p, len, (data)->supportedMech, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 2, &l);
+ if (e)
+ (data)->responseToken = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->responseToken = malloc(sizeof(*(data)->responseToken));
+ if ((data)->responseToken == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->responseToken, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ {
+ size_t newlen, oldlen;
+
+ e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, 3, &l);
+ if (e)
+ (data)->mechListMIC = NULL;
+ else {
+ p += l;
+ len -= l;
+ ret += l;
+ e = der_get_length(p, len, &newlen, &l);
+ FORW;
+ {
+ int dce_fix;
+ oldlen = len;
+ if ((dce_fix = fix_dce(newlen, &len)) < 0)
+ return ASN1_BAD_FORMAT;
+ (data)->mechListMIC = malloc(sizeof(*(data)->mechListMIC));
+ if ((data)->mechListMIC == NULL)
+ return ENOMEM;
+ e = decode_octet_string(p, len, (data)->mechListMIC, &l);
+ FORW;
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ } else
+ len = oldlen - newlen;
+ }
+ }
+ }
+ if (dce_fix) {
+ e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l);
+ FORW;
+ }
+ }
+ if (size)
+ *size = ret;
+ return 0;
+fail:
+ free_NegTokenResp(data);
+ return e;
+}
+
+static void
+free_NegTokenResp(NegTokenResp * data)
+{
+ if ((data)->negState) {
+ free((data)->negState);
+ (data)->negState = NULL;
+ }
+ if ((data)->supportedMech) {
+ free_MechType((data)->supportedMech);
+ free((data)->supportedMech);
+ (data)->supportedMech = NULL;
+ }
+ if ((data)->responseToken) {
+ free_octet_string((data)->responseToken);
+ free((data)->responseToken);
+ (data)->responseToken = NULL;
+ }
+ if ((data)->mechListMIC) {
+ free_octet_string((data)->mechListMIC);
+ free((data)->mechListMIC);
+ (data)->mechListMIC = NULL;
+ }
+}
+
+/* unused function: length_NegTokenResp */
+
+
+/* unused function: copy_NegTokenResp */
+
+/* Generated from spnego.asn1 */
+/* Do not edit */
+
+
+/* CHOICE */
+/* unused variable: asn1_NegotiationToken_dummy_holder */
diff --git a/lib/dns/spnego_asn1.pl b/lib/dns/spnego_asn1.pl
new file mode 100644
index 0000000..93dd676
--- /dev/null
+++ b/lib/dns/spnego_asn1.pl
@@ -0,0 +1,200 @@
+#!/bin/bin/perl -w
+#
+# Copyright (C) 2006, 2007 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: spnego_asn1.pl,v 1.4 2007/06/19 23:47:16 tbox Exp $
+
+# Our SPNEGO implementation uses some functions generated by the
+# Heimdal ASN.1 compiler, which this script then whacks a bit to make
+# them work properly in this stripped down implementation. We don't
+# want to require our users to have a copy of the compiler, so we ship
+# the output of this script, but we need to keep the script around in
+# any case to cope with future changes to the SPNEGO ASN.1 code, so we
+# might as well supply the script for users who want it.
+
+# Overall plan: run the ASN.1 compiler, run each of its output files
+# through indent, fix up symbols and whack everything to be static.
+# We use indent for two reasons: (1) to whack the Heimdal compiler's
+# output into something closer to ISC's coding standard, and (2) to
+# make it easier for this script to parse the result.
+
+# Output from this script is C code which we expect to be #included
+# into another C file, which is why everything generated by this
+# script is marked "static". The intent is to minimize the number of
+# extern symbols exported by the SPNEGO implementation, to avoid
+# potential conflicts with the GSSAPI libraries.
+
+###
+
+# Filename of the ASN.1 specification. Hardcoded for the moment
+# since this script is intended for compiling exactly one module.
+
+my $asn1_source = $ENV{ASN1_SOURCE} || "spnego.asn1";
+
+# Heimdal ASN.1 compiler. This script was written using the version
+# from Heimdal 0.7.1. To build this, download a copy of
+# heimdal-0.7.1.tar.gz, configure and build with the default options,
+# then look for the compiler in heimdal-0.7.1/lib/asn1/asn1_compile.
+
+my $asn1_compile = $ENV{ASN1_COMPILE} || "asn1_compile";
+
+# BSD indent program. This script was written using the version of
+# indent that comes with FreeBSD 4.11-STABLE. The GNU project, as
+# usual, couldn't resist the temptation to monkey with indent's
+# command line syntax, so this probably won't work with GNU indent.
+
+my $indent = $ENV{INDENT} || "indent";
+
+###
+
+# Step 1: run the compiler. Input is the ASN.1 file. Outputs are a
+# header file (name specified on command line without the .h suffix),
+# a file called "asn1_files" listing the names of the other output
+# files, and a set of files containing C code generated by the
+# compiler for each data type that the compiler found.
+
+if (! -r $asn1_source || system($asn1_compile, $asn1_source, "asn1")) {
+ die("Couldn't compile ASN.1 source file $asn1_source\n");
+}
+
+my @files = ("asn1.h");
+
+open(F, "asn1_files")
+ or die("Couldn't open asn1_files: $!\n");
+push(@files, split)
+ while (<F>);
+close(F);
+
+unlink("asn1_files");
+
+###
+
+# Step 2: generate header block.
+
+print(q~/*
+ * Copyright (C) 2006 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND 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: spnego_asn1.pl,v 1.4 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file
+ * \brief Method routines generated from SPNEGO ASN.1 module.
+ * See spnego_asn1.pl for details. Do not edit.
+ */
+
+~);
+
+###
+
+# Step 3: read and process each generated file, then delete it.
+
+my $output;
+
+for my $file (@files) {
+
+ my $is_static = 0;
+
+ system($indent, "-di1", "-ldi1", $file) == 0
+ or die("Couldn't indent $file");
+
+ unlink("$file.BAK");
+
+ open(F, $file)
+ or die("Couldn't open $file: $!");
+
+ while (<F>) {
+
+ # Symbol name fixups
+
+ s/heim_general_string/general_string/g;
+ s/heim_octet_string/octet_string/g;
+ s/heim_oid/oid/g;
+ s/heim_utf8_string/utf8_string/g;
+
+ # Convert all externs to statics
+
+ if (/^static/) {
+ $is_static = 1;
+ }
+
+ if (!/^typedef/ &&
+ !$is_static &&
+ /^[A-Za-z_][0-9A-Za-z_]*[ \t]*($|[^:0-9A-Za-z_])/) {
+ $_ = "static " . $_;
+ $is_static = 1;
+ }
+
+ if (/[{};]/) {
+ $is_static = 0;
+ }
+
+ # Suppress file inclusion, pass anything else through
+
+ if (!/#include/) {
+ $output .= $_;
+ }
+ }
+
+ close(F);
+ unlink($file);
+}
+
+# Step 4: Delete unused stuff to avoid code bloat and compiler warnings.
+
+my @unused_functions = qw(ContextFlags2int
+ int2ContextFlags
+ asn1_ContextFlags_units
+ length_NegTokenInit
+ copy_NegTokenInit
+ length_NegTokenResp
+ copy_NegTokenResp
+ length_MechTypeList
+ length_MechType
+ copy_MechTypeList
+ length_ContextFlags
+ copy_ContextFlags
+ copy_MechType);
+
+$output =~ s<^static [^\n]+\n$_\(.+?^}></* unused function: $_ */\n>ms
+ foreach (@unused_functions);
+
+$output =~ s<^static .+$_\(.*\);$></* unused declaration: $_ */>m
+ foreach (@unused_functions);
+
+$output =~ s<^static struct units ContextFlags_units\[\].+?^};>
+ </* unused variable: ContextFlags_units */>ms;
+
+$output =~ s<^static int asn1_NegotiationToken_dummy_holder = 1;>
+ </* unused variable: asn1_NegotiationToken_dummy_holder */>ms;
+
+$output =~ s<^static void\nfree_ContextFlags\(ContextFlags \* data\)\n{\n>
+ <$&\t(void)data;\n>ms;
+
+# Step 5: Write the result.
+
+print($output);
+
diff --git a/lib/dns/ssu.c b/lib/dns/ssu.c
new file mode 100644
index 0000000..ab69242
--- /dev/null
+++ b/lib/dns/ssu.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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.
+ */
+
+/*! \file */
+/*
+ * $Id: ssu.c,v 1.34 2008/01/18 23:46:58 tbox Exp $
+ * Principal Author: Brian Wellington
+ */
+
+#include <config.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/netaddr.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/ssu.h>
+
+#include <dst/gssapi.h>
+
+#define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T')
+#define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC)
+
+#define SSURULEMAGIC ISC_MAGIC('S', 'S', 'U', 'R')
+#define VALID_SSURULE(table) ISC_MAGIC_VALID(table, SSURULEMAGIC)
+
+struct dns_ssurule {
+ unsigned int magic;
+ isc_boolean_t grant; /*%< is this a grant or a deny? */
+ unsigned int matchtype; /*%< which type of pattern match? */
+ dns_name_t *identity; /*%< the identity to match */
+ dns_name_t *name; /*%< the name being updated */
+ unsigned int ntypes; /*%< number of data types covered */
+ dns_rdatatype_t *types; /*%< the data types. Can include ANY, */
+ /*%< defaults to all but SIG,SOA,NS if NULL */
+ ISC_LINK(dns_ssurule_t) link;
+};
+
+struct dns_ssutable {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ unsigned int references;
+ isc_mutex_t lock;
+ ISC_LIST(dns_ssurule_t) rules;
+};
+
+isc_result_t
+dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **tablep) {
+ isc_result_t result;
+ dns_ssutable_t *table;
+
+ REQUIRE(tablep != NULL && *tablep == NULL);
+ REQUIRE(mctx != NULL);
+
+ table = isc_mem_get(mctx, sizeof(dns_ssutable_t));
+ if (table == NULL)
+ return (ISC_R_NOMEMORY);
+ result = isc_mutex_init(&table->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, table, sizeof(dns_ssutable_t));
+ return (result);
+ }
+ table->references = 1;
+ table->mctx = mctx;
+ ISC_LIST_INIT(table->rules);
+ table->magic = SSUTABLEMAGIC;
+ *tablep = table;
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+destroy(dns_ssutable_t *table) {
+ isc_mem_t *mctx;
+
+ REQUIRE(VALID_SSUTABLE(table));
+
+ mctx = table->mctx;
+ while (!ISC_LIST_EMPTY(table->rules)) {
+ dns_ssurule_t *rule = ISC_LIST_HEAD(table->rules);
+ if (rule->identity != NULL) {
+ dns_name_free(rule->identity, mctx);
+ isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
+ }
+ if (rule->name != NULL) {
+ dns_name_free(rule->name, mctx);
+ isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
+ }
+ if (rule->types != NULL)
+ isc_mem_put(mctx, rule->types,
+ rule->ntypes * sizeof(dns_rdatatype_t));
+ ISC_LIST_UNLINK(table->rules, rule, link);
+ rule->magic = 0;
+ isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
+ }
+ DESTROYLOCK(&table->lock);
+ table->magic = 0;
+ isc_mem_put(mctx, table, sizeof(dns_ssutable_t));
+}
+
+void
+dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp) {
+ REQUIRE(VALID_SSUTABLE(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ LOCK(&source->lock);
+
+ INSIST(source->references > 0);
+ source->references++;
+ INSIST(source->references != 0);
+
+ UNLOCK(&source->lock);
+
+ *targetp = source;
+}
+
+void
+dns_ssutable_detach(dns_ssutable_t **tablep) {
+ dns_ssutable_t *table;
+ isc_boolean_t done = ISC_FALSE;
+
+ REQUIRE(tablep != NULL);
+ table = *tablep;
+ REQUIRE(VALID_SSUTABLE(table));
+
+ LOCK(&table->lock);
+
+ INSIST(table->references > 0);
+ if (--table->references == 0)
+ done = ISC_TRUE;
+ UNLOCK(&table->lock);
+
+ *tablep = NULL;
+
+ if (done)
+ destroy(table);
+}
+
+isc_result_t
+dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
+ dns_name_t *identity, unsigned int matchtype,
+ dns_name_t *name, unsigned int ntypes,
+ dns_rdatatype_t *types)
+{
+ dns_ssurule_t *rule;
+ isc_mem_t *mctx;
+ isc_result_t result;
+
+ REQUIRE(VALID_SSUTABLE(table));
+ REQUIRE(dns_name_isabsolute(identity));
+ REQUIRE(dns_name_isabsolute(name));
+ REQUIRE(matchtype <= DNS_SSUMATCHTYPE_MAX);
+ if (matchtype == DNS_SSUMATCHTYPE_WILDCARD)
+ REQUIRE(dns_name_iswildcard(name));
+ if (ntypes > 0)
+ REQUIRE(types != NULL);
+
+ mctx = table->mctx;
+ rule = isc_mem_get(mctx, sizeof(dns_ssurule_t));
+ if (rule == NULL)
+ return (ISC_R_NOMEMORY);
+
+ rule->identity = NULL;
+ rule->name = NULL;
+ rule->types = NULL;
+
+ rule->grant = grant;
+
+ rule->identity = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (rule->identity == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ dns_name_init(rule->identity, NULL);
+ result = dns_name_dup(identity, mctx, rule->identity);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ rule->name = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (rule->name == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ dns_name_init(rule->name, NULL);
+ result = dns_name_dup(name, mctx, rule->name);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ rule->matchtype = matchtype;
+
+ rule->ntypes = ntypes;
+ if (ntypes > 0) {
+ rule->types = isc_mem_get(mctx,
+ ntypes * sizeof(dns_rdatatype_t));
+ if (rule->types == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ memcpy(rule->types, types, ntypes * sizeof(dns_rdatatype_t));
+ } else
+ rule->types = NULL;
+
+ rule->magic = SSURULEMAGIC;
+ ISC_LIST_INITANDAPPEND(table->rules, rule, link);
+
+ return (ISC_R_SUCCESS);
+
+ failure:
+ if (rule->identity != NULL) {
+ if (dns_name_dynamic(rule->identity))
+ dns_name_free(rule->identity, mctx);
+ isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
+ }
+ if (rule->name != NULL) {
+ if (dns_name_dynamic(rule->name))
+ dns_name_free(rule->name, mctx);
+ isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
+ }
+ if (rule->types != NULL)
+ isc_mem_put(mctx, rule->types,
+ ntypes * sizeof(dns_rdatatype_t));
+ isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
+
+ return (result);
+}
+
+static inline isc_boolean_t
+isusertype(dns_rdatatype_t type) {
+ return (ISC_TF(type != dns_rdatatype_ns &&
+ type != dns_rdatatype_soa &&
+ type != dns_rdatatype_rrsig));
+}
+
+static void
+reverse_from_address(dns_name_t *tcpself, isc_netaddr_t *tcpaddr) {
+ char buf[16 * 4 + sizeof("IP6.ARPA.")];
+ isc_result_t result;
+ unsigned char *ap;
+ isc_buffer_t b;
+ unsigned long l;
+
+ switch (tcpaddr->family) {
+ case AF_INET:
+ l = ntohl(tcpaddr->type.in.s_addr);
+ result = isc_string_printf(buf, sizeof(buf),
+ "%lu.%lu.%lu.%lu.IN-ADDR.ARPA.",
+ (l >> 0) & 0xff, (l >> 8) & 0xff,
+ (l >> 16) & 0xff, (l >> 24) & 0xff);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ break;
+ case AF_INET6:
+ ap = tcpaddr->type.in6.s6_addr;
+ result = isc_string_printf(buf, sizeof(buf),
+ "%x.%x.%x.%x.%x.%x.%x.%x."
+ "%x.%x.%x.%x.%x.%x.%x.%x."
+ "%x.%x.%x.%x.%x.%x.%x.%x."
+ "%x.%x.%x.%x.%x.%x.%x.%x."
+ "IP6.ARPA.",
+ ap[15] & 0x0f, (ap[15] >> 4) & 0x0f,
+ ap[14] & 0x0f, (ap[14] >> 4) & 0x0f,
+ ap[13] & 0x0f, (ap[13] >> 4) & 0x0f,
+ ap[12] & 0x0f, (ap[12] >> 4) & 0x0f,
+ ap[11] & 0x0f, (ap[11] >> 4) & 0x0f,
+ ap[10] & 0x0f, (ap[10] >> 4) & 0x0f,
+ ap[9] & 0x0f, (ap[9] >> 4) & 0x0f,
+ ap[8] & 0x0f, (ap[8] >> 4) & 0x0f,
+ ap[7] & 0x0f, (ap[7] >> 4) & 0x0f,
+ ap[6] & 0x0f, (ap[6] >> 4) & 0x0f,
+ ap[5] & 0x0f, (ap[5] >> 4) & 0x0f,
+ ap[4] & 0x0f, (ap[4] >> 4) & 0x0f,
+ ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
+ ap[2] & 0x0f, (ap[2] >> 4) & 0x0f,
+ ap[1] & 0x0f, (ap[1] >> 4) & 0x0f,
+ ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ break;
+ default:
+ INSIST(0);
+ }
+ isc_buffer_init(&b, buf, strlen(buf));
+ isc_buffer_add(&b, strlen(buf));
+ result = dns_name_fromtext(tcpself, &b, dns_rootname, 0, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+}
+
+static void
+stf_from_address(dns_name_t *stfself, isc_netaddr_t *tcpaddr) {
+ char buf[sizeof("X.X.X.X.Y.Y.Y.Y.2.0.0.2.IP6.ARPA.")];
+ isc_result_t result;
+ unsigned char *ap;
+ isc_buffer_t b;
+ unsigned long l;
+
+ switch(tcpaddr->family) {
+ case AF_INET:
+ l = ntohl(tcpaddr->type.in.s_addr);
+ result = isc_string_printf(buf, sizeof(buf),
+ "%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx"
+ "2.0.0.2.IP6.ARPA.",
+ l & 0xf, (l >> 4) & 0xf,
+ (l >> 8) & 0xf, (l >> 12) & 0xf,
+ (l >> 16) & 0xf, (l >> 20) & 0xf,
+ (l >> 24) & 0xf, (l >> 28) & 0xf);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ break;
+ case AF_INET6:
+ ap = tcpaddr->type.in6.s6_addr;
+ result = isc_string_printf(buf, sizeof(buf),
+ "%x.%x.%x.%x.%x.%x.%x.%x."
+ "%x.%x.%x.%x.IP6.ARPA.",
+ ap[5] & 0x0f, (ap[5] >> 4) & 0x0f,
+ ap[4] & 0x0f, (ap[4] >> 4) & 0x0f,
+ ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
+ ap[2] & 0x0f, (ap[2] >> 4) & 0x0f,
+ ap[1] & 0x0f, (ap[1] >> 4) & 0x0f,
+ ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ break;
+ default:
+ INSIST(0);
+ }
+ isc_buffer_init(&b, buf, strlen(buf));
+ isc_buffer_add(&b, strlen(buf));
+ result = dns_name_fromtext(stfself, &b, dns_rootname, 0, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+}
+
+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_ssurule_t *rule;
+ unsigned int i;
+ dns_fixedname_t fixed;
+ dns_name_t *wildcard;
+ dns_name_t *tcpself;
+ dns_name_t *stfself;
+ isc_result_t result;
+
+ REQUIRE(VALID_SSUTABLE(table));
+ REQUIRE(signer == NULL || dns_name_isabsolute(signer));
+ REQUIRE(dns_name_isabsolute(name));
+
+ if (signer == NULL && tcpaddr == NULL)
+ return (ISC_FALSE);
+
+ for (rule = ISC_LIST_HEAD(table->rules);
+ rule != NULL;
+ rule = ISC_LIST_NEXT(rule, link))
+ {
+ switch (rule->matchtype) {
+ case DNS_SSUMATCHTYPE_NAME:
+ case DNS_SSUMATCHTYPE_SUBDOMAIN:
+ case DNS_SSUMATCHTYPE_WILDCARD:
+ case DNS_SSUMATCHTYPE_SELF:
+ case DNS_SSUMATCHTYPE_SELFSUB:
+ case DNS_SSUMATCHTYPE_SELFWILD:
+ if (signer == NULL)
+ continue;
+ if (dns_name_iswildcard(rule->identity)) {
+ if (!dns_name_matcheswildcard(signer,
+ rule->identity))
+ continue;
+ } else {
+ if (!dns_name_equal(signer, rule->identity))
+ continue;
+ }
+ break;
+ case DNS_SSUMATCHTYPE_SELFKRB5:
+ case DNS_SSUMATCHTYPE_SELFMS:
+ case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
+ case DNS_SSUMATCHTYPE_SUBDOMAINMS:
+ if (signer == NULL)
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_TCPSELF:
+ case DNS_SSUMATCHTYPE_6TO4SELF:
+ if (tcpaddr == NULL)
+ continue;
+ break;
+ }
+
+ switch (rule->matchtype) {
+ case DNS_SSUMATCHTYPE_NAME:
+ if (!dns_name_equal(name, rule->name))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SUBDOMAIN:
+ if (!dns_name_issubdomain(name, rule->name))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_WILDCARD:
+ if (!dns_name_matcheswildcard(name, rule->name))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SELF:
+ if (!dns_name_equal(signer, name))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SELFSUB:
+ if (!dns_name_issubdomain(name, signer))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SELFWILD:
+ dns_fixedname_init(&fixed);
+ wildcard = dns_fixedname_name(&fixed);
+ result = dns_name_concatenate(dns_wildcardname, signer,
+ wildcard, NULL);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if (!dns_name_matcheswildcard(name, wildcard))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SELFKRB5:
+ if (!dst_gssapi_identitymatchesrealmkrb5(signer, name,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SELFMS:
+ if (!dst_gssapi_identitymatchesrealmms(signer, name,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
+ if (!dns_name_issubdomain(name, rule->name))
+ continue;
+ if (!dst_gssapi_identitymatchesrealmkrb5(signer, NULL,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_SUBDOMAINMS:
+ if (!dns_name_issubdomain(name, rule->name))
+ continue;
+ if (!dst_gssapi_identitymatchesrealmms(signer, NULL,
+ rule->identity))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_TCPSELF:
+ dns_fixedname_init(&fixed);
+ tcpself = dns_fixedname_name(&fixed);
+ reverse_from_address(tcpself, tcpaddr);
+ if (dns_name_iswildcard(rule->identity)) {
+ if (!dns_name_matcheswildcard(tcpself,
+ rule->identity))
+ continue;
+ } else {
+ if (!dns_name_equal(tcpself, rule->identity))
+ continue;
+ }
+ if (!dns_name_equal(tcpself, name))
+ continue;
+ break;
+ case DNS_SSUMATCHTYPE_6TO4SELF:
+ dns_fixedname_init(&fixed);
+ stfself = dns_fixedname_name(&fixed);
+ stf_from_address(stfself, tcpaddr);
+ if (dns_name_iswildcard(rule->identity)) {
+ if (!dns_name_matcheswildcard(stfself,
+ rule->identity))
+ continue;
+ } else {
+ if (!dns_name_equal(stfself, rule->identity))
+ continue;
+ }
+ if (!dns_name_equal(stfself, name))
+ continue;
+ break;
+ }
+
+ if (rule->ntypes == 0) {
+ if (!isusertype(type))
+ continue;
+ } else {
+ for (i = 0; i < rule->ntypes; i++) {
+ if (rule->types[i] == dns_rdatatype_any ||
+ rule->types[i] == type)
+ break;
+ }
+ if (i == rule->ntypes)
+ continue;
+ }
+ return (rule->grant);
+ }
+
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+dns_ssurule_isgrant(const dns_ssurule_t *rule) {
+ REQUIRE(VALID_SSURULE(rule));
+ return (rule->grant);
+}
+
+dns_name_t *
+dns_ssurule_identity(const dns_ssurule_t *rule) {
+ REQUIRE(VALID_SSURULE(rule));
+ return (rule->identity);
+}
+
+unsigned int
+dns_ssurule_matchtype(const dns_ssurule_t *rule) {
+ REQUIRE(VALID_SSURULE(rule));
+ return (rule->matchtype);
+}
+
+dns_name_t *
+dns_ssurule_name(const dns_ssurule_t *rule) {
+ REQUIRE(VALID_SSURULE(rule));
+ return (rule->name);
+}
+
+unsigned int
+dns_ssurule_types(const dns_ssurule_t *rule, dns_rdatatype_t **types) {
+ REQUIRE(VALID_SSURULE(rule));
+ REQUIRE(types != NULL && *types != NULL);
+ *types = rule->types;
+ return (rule->ntypes);
+}
+
+isc_result_t
+dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule) {
+ REQUIRE(VALID_SSUTABLE(table));
+ REQUIRE(rule != NULL && *rule == NULL);
+ *rule = ISC_LIST_HEAD(table->rules);
+ return (*rule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
+}
+
+isc_result_t
+dns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) {
+ REQUIRE(VALID_SSURULE(rule));
+ REQUIRE(nextrule != NULL && *nextrule == NULL);
+ *nextrule = ISC_LIST_NEXT(rule, link);
+ return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
+}
diff --git a/lib/dns/stats.c b/lib/dns/stats.c
new file mode 100644
index 0000000..7110883
--- /dev/null
+++ b/lib/dns/stats.c
@@ -0,0 +1,564 @@
+/*
+ * 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
+ * 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: stats.c,v 1.16 2008/04/03 06:09:04 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/atomic.h>
+#include <isc/buffer.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/rwlock.h>
+#include <isc/util.h>
+
+#include <dns/opcode.h>
+#include <dns/rdatatype.h>
+#include <dns/stats.h>
+
+#define DNS_STATS_MAGIC ISC_MAGIC('D', 's', 't', 't')
+#define DNS_STATS_VALID(x) ISC_MAGIC_VALID(x, DNS_STATS_MAGIC)
+
+/*%
+ * Statistics types.
+ */
+typedef enum {
+ dns_statstype_general = 0,
+ dns_statstype_rdtype = 1,
+ dns_statstype_rdataset = 2,
+ dns_statstype_opcode = 3
+} dns_statstype_t;
+
+/*%
+ * It doesn't make sense to have 2^16 counters for all possible types since
+ * most of them won't be used. We have counters for the first 256 types and
+ * those explicitly supported in the rdata implementation.
+ * XXXJT: this introduces tight coupling with the rdata implementation.
+ * Ideally, we should have rdata handle this type of details.
+ */
+enum {
+ /* For 0-255, we use the rdtype value as counter indices */
+ rdtypecounter_dlv = 256, /* for dns_rdatatype_dlv */
+ rdtypecounter_others = 257, /* anything else */
+ rdtypecounter_max = 258,
+ /* The following are used for rdataset */
+ rdtypenxcounter_max = rdtypecounter_max * 2,
+ rdtypecounter_nxdomain = rdtypenxcounter_max,
+ rdatasettypecounter_max = rdtypecounter_nxdomain + 1
+};
+
+#ifndef DNS_STATS_USEMULTIFIELDS
+#if defined(ISC_RWLOCK_USEATOMIC) && defined(ISC_PLATFORM_HAVEXADD) && !defined(ISC_PLATFORM_HAVEXADDQ)
+#define DNS_STATS_USEMULTIFIELDS 1
+#else
+#define DNS_STATS_USEMULTIFIELDS 0
+#endif
+#endif /* DNS_STATS_USEMULTIFIELDS */
+
+#if DNS_STATS_USEMULTIFIELDS
+typedef struct {
+ isc_uint32_t hi;
+ isc_uint32_t lo;
+} dns_stat_t;
+#else
+typedef isc_uint64_t dns_stat_t;
+#endif
+
+struct dns_stats {
+ /*% Unlocked */
+ unsigned int magic;
+ dns_statstype_t type;
+ isc_mem_t *mctx;
+ int ncounters;
+
+ isc_mutex_t lock;
+ unsigned int references; /* locked by lock */
+
+ /*%
+ * Locked by counterlock or unlocked if efficient rwlock is not
+ * available.
+ */
+#ifdef ISC_RWLOCK_USEATOMIC
+ isc_rwlock_t counterlock;
+#endif
+ dns_stat_t *counters;
+
+ /*%
+ * We don't want to lock the counters while we are dumping, so we first
+ * copy the current counter values into a local array. This buffer
+ * will be used as the copy destination. It's allocated on creation
+ * of the stats structure so that the dump operation won't fail due
+ * to memory allocation failure.
+ * XXX: this approach is weird for non-threaded build because the
+ * additional memory and the copy overhead could be avoided. We prefer
+ * simplicity here, however, under the assumption that this function
+ * should be only rarely called.
+ */
+ isc_uint64_t *copiedcounters;
+};
+
+static isc_result_t
+create_stats(isc_mem_t *mctx, dns_statstype_t type, int ncounters,
+ dns_stats_t **statsp)
+{
+ dns_stats_t *stats;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ stats = isc_mem_get(mctx, sizeof(*stats));
+ if (stats == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&stats->lock);
+ if (result != ISC_R_SUCCESS)
+ goto clean_stats;
+
+ stats->counters = isc_mem_get(mctx, sizeof(dns_stat_t) * ncounters);
+ if (stats->counters == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto clean_mutex;
+ }
+ stats->copiedcounters = isc_mem_get(mctx,
+ sizeof(isc_uint64_t) * ncounters);
+ if (stats->copiedcounters == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto clean_counters;
+ }
+
+#ifdef ISC_RWLOCK_USEATOMIC
+ result = isc_rwlock_init(&stats->counterlock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto clean_copiedcounters;
+#endif
+
+ stats->type = type;
+ stats->references = 1;
+ memset(stats->counters, 0, sizeof(dns_stat_t) * ncounters);
+ stats->mctx = NULL;
+ isc_mem_attach(mctx, &stats->mctx);
+ stats->ncounters = ncounters;
+ stats->magic = DNS_STATS_MAGIC;
+
+ *statsp = stats;
+
+ return (result);
+
+clean_counters:
+ isc_mem_put(mctx, stats->counters, sizeof(dns_stat_t) * ncounters);
+
+#ifdef ISC_RWLOCK_USEATOMIC
+clean_copiedcounters:
+ isc_mem_put(mctx, stats->copiedcounters,
+ sizeof(dns_stat_t) * ncounters);
+#endif
+
+clean_mutex:
+ DESTROYLOCK(&stats->lock);
+
+clean_stats:
+ isc_mem_put(mctx, stats, sizeof(*stats));
+
+ return (result);
+}
+
+void
+dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp) {
+ REQUIRE(DNS_STATS_VALID(stats));
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ LOCK(&stats->lock);
+ stats->references++;
+ UNLOCK(&stats->lock);
+
+ *statsp = stats;
+}
+
+void
+dns_stats_detach(dns_stats_t **statsp) {
+ dns_stats_t *stats;
+
+ REQUIRE(statsp != NULL && DNS_STATS_VALID(*statsp));
+
+ stats = *statsp;
+ *statsp = NULL;
+
+ LOCK(&stats->lock);
+ stats->references--;
+ UNLOCK(&stats->lock);
+
+ if (stats->references == 0) {
+ isc_mem_put(stats->mctx, stats->copiedcounters,
+ sizeof(dns_stat_t) * stats->ncounters);
+ isc_mem_put(stats->mctx, stats->counters,
+ sizeof(dns_stat_t) * stats->ncounters);
+ DESTROYLOCK(&stats->lock);
+#ifdef ISC_RWLOCK_USEATOMIC
+ isc_rwlock_destroy(&stats->counterlock);
+#endif
+ isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
+ }
+}
+
+static inline void
+incrementcounter(dns_stats_t *stats, int counter) {
+ isc_int32_t prev;
+
+#ifdef ISC_RWLOCK_USEATOMIC
+ /*
+ * We use a "read" lock to prevent other threads from reading the
+ * counter while we "writing" a counter field. The write access itself
+ * is protected by the atomic operation.
+ */
+ isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read);
+#endif
+
+#if DNS_STATS_USEMULTIFIELDS
+ prev = isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].lo, 1);
+ /*
+ * If the lower 32-bit field overflows, increment the higher field.
+ * Note that it's *theoretically* possible that the lower field
+ * overlaps again before the higher field is incremented. It doesn't
+ * matter, however, because we don't read the value until
+ * dns_stats_copy() is called where the whole process is protected
+ * by the write (exclusive) lock.
+ */
+ if (prev == (isc_int32_t)0xffffffff)
+ isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].hi, 1);
+#elif defined(ISC_PLATFORM_HAVEXADDQ)
+ UNUSED(prev);
+ isc_atomic_xaddq((isc_int64_t *)&stats->counters[counter], 1);
+#else
+ UNUSED(prev);
+ stats->counters[counter]++;
+#endif
+
+#ifdef ISC_RWLOCK_USEATOMIC
+ isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read);
+#endif
+}
+
+static inline void
+decrementcounter(dns_stats_t *stats, int counter) {
+ isc_int32_t prev;
+
+#ifdef ISC_RWLOCK_USEATOMIC
+ isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_read);
+#endif
+
+#if DNS_STATS_USEMULTIFIELDS
+ prev = isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].lo, -1);
+ if (prev == 0)
+ isc_atomic_xadd((isc_int32_t *)&stats->counters[counter].hi,
+ -1);
+#elif defined(ISC_PLATFORM_HAVEXADDQ)
+ UNUSED(prev);
+ isc_atomic_xaddq((isc_int64_t *)&stats->counters[counter], -1);
+#else
+ UNUSED(prev);
+ stats->counters[counter]--;
+#endif
+
+#ifdef ISC_RWLOCK_USEATOMIC
+ isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_read);
+#endif
+}
+
+static void
+copy_counters(dns_stats_t *stats) {
+ int i;
+
+#ifdef ISC_RWLOCK_USEATOMIC
+ /*
+ * We use a "write" lock before "reading" the statistics counters as
+ * an exclusive lock.
+ */
+ isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write);
+#endif
+
+#if DNS_STATS_USEMULTIFIELDS
+ for (i = 0; i < stats->ncounters; i++) {
+ stats->copiedcounters[i] =
+ (isc_uint64_t)(stats->counters[i].hi) << 32 |
+ stats->counters[i].lo;
+ }
+#else
+ UNUSED(i);
+ memcpy(stats->copiedcounters, stats->counters,
+ stats->ncounters * sizeof(dns_stat_t));
+#endif
+
+#ifdef ISC_RWLOCK_USEATOMIC
+ isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
+#endif
+}
+
+/*%
+ * Create methods
+ */
+isc_result_t
+dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters) {
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ return (create_stats(mctx, dns_statstype_general, ncounters, statsp));
+}
+
+isc_result_t
+dns_rdatatypestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ return (create_stats(mctx, dns_statstype_rdtype, rdtypecounter_max,
+ statsp));
+}
+
+isc_result_t
+dns_rdatasetstats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ return (create_stats(mctx, dns_statstype_rdataset,
+ (rdtypecounter_max * 2) + 1, statsp));
+}
+
+isc_result_t
+dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ return (create_stats(mctx, dns_statstype_opcode, 16, statsp));
+}
+
+/*%
+ * Increment/Decrement methods
+ */
+void
+dns_generalstats_increment(dns_stats_t *stats, dns_statscounter_t counter) {
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
+ REQUIRE(counter < stats->ncounters);
+
+ incrementcounter(stats, (int)counter);
+}
+
+void
+dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type) {
+ int counter;
+
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
+
+ if (type == dns_rdatatype_dlv)
+ counter = rdtypecounter_dlv;
+ else if (type > dns_rdatatype_any)
+ counter = rdtypecounter_others;
+ else
+ counter = (int)type;
+
+ incrementcounter(stats, counter);
+}
+
+static inline void
+update_rdatasetstats(dns_stats_t *stats, dns_rdatastatstype_t rrsettype,
+ isc_boolean_t increment)
+{
+ int counter;
+ dns_rdatatype_t rdtype;
+
+ if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
+ DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0) {
+ counter = rdtypecounter_nxdomain;
+ } else {
+ rdtype = DNS_RDATASTATSTYPE_BASE(rrsettype);
+ if (rdtype == dns_rdatatype_dlv)
+ counter = (int)rdtypecounter_dlv;
+ else if (rdtype > dns_rdatatype_any)
+ counter = (int)rdtypecounter_others;
+ else
+ counter = (int)rdtype;
+
+ if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
+ DNS_RDATASTATSTYPE_ATTR_NXRRSET) != 0)
+ counter += rdtypecounter_max;
+ }
+
+ if (increment)
+ incrementcounter(stats, counter);
+ else
+ decrementcounter(stats, counter);
+}
+
+void
+dns_rdatasetstats_increment(dns_stats_t *stats, dns_rdatastatstype_t rrsettype)
+{
+ REQUIRE(DNS_STATS_VALID(stats) &&
+ stats->type == dns_statstype_rdataset);
+
+ update_rdatasetstats(stats, rrsettype, ISC_TRUE);
+}
+
+void
+dns_rdatasetstats_decrement(dns_stats_t *stats, dns_rdatastatstype_t rrsettype)
+{
+ REQUIRE(DNS_STATS_VALID(stats) &&
+ stats->type == dns_statstype_rdataset);
+
+ update_rdatasetstats(stats, rrsettype, ISC_FALSE);
+}
+void
+dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code) {
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
+
+ incrementcounter(stats, (int)code);
+}
+
+/*%
+ * Dump methods
+ */
+void
+dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
+ void *arg, unsigned int options)
+{
+ int i;
+
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
+
+ copy_counters(stats);
+
+ for (i = 0; i < stats->ncounters; i++) {
+ if ((options & DNS_STATSDUMP_VERBOSE) == 0 &&
+ stats->copiedcounters[i] == 0)
+ continue;
+ dump_fn(i, stats->copiedcounters[i], arg);
+ }
+}
+
+static void
+dump_rdentry(dns_stats_t *stats, int counter, int rdcounter,
+ dns_rdatastatstype_t attributes,
+ dns_rdatatypestats_dumper_t dump_fn, void * arg,
+ unsigned int options)
+{
+ dns_rdatatype_t rdtype = dns_rdatatype_none; /* sentinel */
+ dns_rdatastatstype_t type;
+
+ if ((options & DNS_STATSDUMP_VERBOSE) == 0 &&
+ stats->copiedcounters[counter] == 0)
+ return;
+ if (rdcounter == rdtypecounter_others)
+ attributes |= DNS_RDATASTATSTYPE_ATTR_OTHERTYPE;
+ else {
+ if (rdcounter == rdtypecounter_dlv)
+ rdtype = dns_rdatatype_dlv;
+ else
+ rdtype = (dns_rdatatype_t)rdcounter;
+ }
+ type = DNS_RDATASTATSTYPE_VALUE((dns_rdatastatstype_t)rdtype,
+ attributes);
+ dump_fn(type, stats->copiedcounters[counter], arg);
+}
+
+void
+dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+ void *arg, unsigned int options)
+{
+ int i;
+
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
+
+ copy_counters(stats);
+
+ for (i = 0; i < stats->ncounters; i++)
+ dump_rdentry(stats, i, i, 0, dump_fn, arg, options);
+}
+
+void
+dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
+ void *arg, unsigned int options)
+{
+ int i;
+
+ REQUIRE(DNS_STATS_VALID(stats) &&
+ stats->type == dns_statstype_rdataset);
+
+ copy_counters(stats);
+
+ for (i = 0; i < rdtypecounter_max; i++)
+ dump_rdentry(stats, i, i, 0, dump_fn, arg, options);
+ for (i = rdtypecounter_max; i < rdtypenxcounter_max; i++) {
+ dump_rdentry(stats, i, i - rdtypecounter_max,
+ DNS_RDATASTATSTYPE_ATTR_NXRRSET,
+ dump_fn, arg, options);
+ }
+ dump_rdentry(stats, rdtypecounter_nxdomain, 0,
+ DNS_RDATASTATSTYPE_ATTR_NXDOMAIN, dump_fn, arg, options);
+
+ INSIST(i < stats->ncounters);
+}
+
+void
+dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
+ void *arg, unsigned int options)
+{
+ int i;
+
+ REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
+
+ copy_counters(stats);
+
+ for (i = 0; i < stats->ncounters; i++) {
+ if ((options & DNS_STATSDUMP_VERBOSE) == 0 &&
+ stats->copiedcounters[i] == 0)
+ continue;
+ dump_fn((dns_opcode_t)i, stats->copiedcounters[i], arg);
+ }
+}
+
+/***
+ *** Obsolete variables and functions follow:
+ ***/
+LIBDNS_EXTERNAL_DATA const char *dns_statscounter_names[DNS_STATS_NCOUNTERS] =
+ {
+ "success",
+ "referral",
+ "nxrrset",
+ "nxdomain",
+ "recursion",
+ "failure",
+ "duplicate",
+ "dropped"
+ };
+
+isc_result_t
+dns_stats_alloccounters(isc_mem_t *mctx, isc_uint64_t **ctrp) {
+ int i;
+ isc_uint64_t *p =
+ isc_mem_get(mctx, DNS_STATS_NCOUNTERS * sizeof(isc_uint64_t));
+ if (p == NULL)
+ return (ISC_R_NOMEMORY);
+ for (i = 0; i < DNS_STATS_NCOUNTERS; i++)
+ p[i] = 0;
+ *ctrp = p;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_stats_freecounters(isc_mem_t *mctx, isc_uint64_t **ctrp) {
+ isc_mem_put(mctx, *ctrp, DNS_STATS_NCOUNTERS * sizeof(isc_uint64_t));
+ *ctrp = NULL;
+}
diff --git a/lib/dns/tcpmsg.c b/lib/dns/tcpmsg.c
new file mode 100644
index 0000000..49add56
--- /dev/null
+++ b/lib/dns/tcpmsg.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: tcpmsg.c,v 1.31 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/events.h>
+#include <dns/result.h>
+#include <dns/tcpmsg.h>
+
+#ifdef TCPMSG_DEBUG
+#include <stdio.h> /* Required for printf. */
+#define XDEBUG(x) printf x
+#else
+#define XDEBUG(x)
+#endif
+
+#define TCPMSG_MAGIC ISC_MAGIC('T', 'C', 'P', 'm')
+#define VALID_TCPMSG(foo) ISC_MAGIC_VALID(foo, TCPMSG_MAGIC)
+
+static void recv_length(isc_task_t *, isc_event_t *);
+static void recv_message(isc_task_t *, isc_event_t *);
+
+
+static void
+recv_length(isc_task_t *task, isc_event_t *ev_in) {
+ isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
+ isc_event_t *dev;
+ dns_tcpmsg_t *tcpmsg = ev_in->ev_arg;
+ isc_region_t region;
+ isc_result_t result;
+
+ INSIST(VALID_TCPMSG(tcpmsg));
+
+ dev = &tcpmsg->event;
+ tcpmsg->address = ev->address;
+
+ if (ev->result != ISC_R_SUCCESS) {
+ tcpmsg->result = ev->result;
+ goto send_and_free;
+ }
+
+ /*
+ * Success.
+ */
+ tcpmsg->size = ntohs(tcpmsg->size);
+ if (tcpmsg->size == 0) {
+ tcpmsg->result = ISC_R_UNEXPECTEDEND;
+ goto send_and_free;
+ }
+ if (tcpmsg->size > tcpmsg->maxsize) {
+ tcpmsg->result = ISC_R_RANGE;
+ goto send_and_free;
+ }
+
+ region.base = isc_mem_get(tcpmsg->mctx, tcpmsg->size);
+ region.length = tcpmsg->size;
+ if (region.base == NULL) {
+ tcpmsg->result = ISC_R_NOMEMORY;
+ goto send_and_free;
+ }
+ XDEBUG(("Allocated %d bytes\n", tcpmsg->size));
+
+ isc_buffer_init(&tcpmsg->buffer, region.base, region.length);
+ result = isc_socket_recv(tcpmsg->sock, &region, 0,
+ task, recv_message, tcpmsg);
+ if (result != ISC_R_SUCCESS) {
+ tcpmsg->result = result;
+ goto send_and_free;
+ }
+
+ isc_event_free(&ev_in);
+ return;
+
+ send_and_free:
+ isc_task_send(tcpmsg->task, &dev);
+ tcpmsg->task = NULL;
+ isc_event_free(&ev_in);
+ return;
+}
+
+static void
+recv_message(isc_task_t *task, isc_event_t *ev_in) {
+ isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
+ isc_event_t *dev;
+ dns_tcpmsg_t *tcpmsg = ev_in->ev_arg;
+
+ (void)task;
+
+ INSIST(VALID_TCPMSG(tcpmsg));
+
+ dev = &tcpmsg->event;
+ tcpmsg->address = ev->address;
+
+ if (ev->result != ISC_R_SUCCESS) {
+ tcpmsg->result = ev->result;
+ goto send_and_free;
+ }
+
+ tcpmsg->result = ISC_R_SUCCESS;
+ isc_buffer_add(&tcpmsg->buffer, ev->n);
+
+ XDEBUG(("Received %d bytes (of %d)\n", ev->n, tcpmsg->size));
+
+ send_and_free:
+ isc_task_send(tcpmsg->task, &dev);
+ tcpmsg->task = NULL;
+ isc_event_free(&ev_in);
+}
+
+void
+dns_tcpmsg_init(isc_mem_t *mctx, isc_socket_t *sock, dns_tcpmsg_t *tcpmsg) {
+ REQUIRE(mctx != NULL);
+ REQUIRE(sock != NULL);
+ REQUIRE(tcpmsg != NULL);
+
+ tcpmsg->magic = TCPMSG_MAGIC;
+ tcpmsg->size = 0;
+ tcpmsg->buffer.base = NULL;
+ tcpmsg->buffer.length = 0;
+ tcpmsg->maxsize = 65535; /* Largest message possible. */
+ tcpmsg->mctx = mctx;
+ tcpmsg->sock = sock;
+ tcpmsg->task = NULL; /* None yet. */
+ tcpmsg->result = ISC_R_UNEXPECTED; /* None yet. */
+ /*
+ * Should probably initialize the event here, but it can wait.
+ */
+}
+
+
+void
+dns_tcpmsg_setmaxsize(dns_tcpmsg_t *tcpmsg, unsigned int maxsize) {
+ REQUIRE(VALID_TCPMSG(tcpmsg));
+ REQUIRE(maxsize < 65536);
+
+ tcpmsg->maxsize = maxsize;
+}
+
+
+isc_result_t
+dns_tcpmsg_readmessage(dns_tcpmsg_t *tcpmsg,
+ isc_task_t *task, isc_taskaction_t action, void *arg)
+{
+ isc_result_t result;
+ isc_region_t region;
+
+ REQUIRE(VALID_TCPMSG(tcpmsg));
+ REQUIRE(task != NULL);
+ REQUIRE(tcpmsg->task == NULL); /* not currently in use */
+
+ if (tcpmsg->buffer.base != NULL) {
+ isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base,
+ tcpmsg->buffer.length);
+ tcpmsg->buffer.base = NULL;
+ tcpmsg->buffer.length = 0;
+ }
+
+ tcpmsg->task = task;
+ tcpmsg->action = action;
+ tcpmsg->arg = arg;
+ tcpmsg->result = ISC_R_UNEXPECTED; /* unknown right now */
+
+ ISC_EVENT_INIT(&tcpmsg->event, sizeof(isc_event_t), 0, 0,
+ DNS_EVENT_TCPMSG, action, arg, tcpmsg,
+ NULL, NULL);
+
+ region.base = (unsigned char *)&tcpmsg->size;
+ region.length = 2; /* isc_uint16_t */
+ result = isc_socket_recv(tcpmsg->sock, &region, 0,
+ tcpmsg->task, recv_length, tcpmsg);
+
+ if (result != ISC_R_SUCCESS)
+ tcpmsg->task = NULL;
+
+ return (result);
+}
+
+void
+dns_tcpmsg_cancelread(dns_tcpmsg_t *tcpmsg) {
+ REQUIRE(VALID_TCPMSG(tcpmsg));
+
+ isc_socket_cancel(tcpmsg->sock, NULL, ISC_SOCKCANCEL_RECV);
+}
+
+void
+dns_tcpmsg_keepbuffer(dns_tcpmsg_t *tcpmsg, isc_buffer_t *buffer) {
+ REQUIRE(VALID_TCPMSG(tcpmsg));
+ REQUIRE(buffer != NULL);
+
+ *buffer = tcpmsg->buffer;
+ tcpmsg->buffer.base = NULL;
+ tcpmsg->buffer.length = 0;
+}
+
+#if 0
+void
+dns_tcpmsg_freebuffer(dns_tcpmsg_t *tcpmsg) {
+ REQUIRE(VALID_TCPMSG(tcpmsg));
+
+ if (tcpmsg->buffer.base == NULL)
+ return;
+
+ isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base, tcpmsg->buffer.length);
+ tcpmsg->buffer.base = NULL;
+ tcpmsg->buffer.length = 0;
+}
+#endif
+
+void
+dns_tcpmsg_invalidate(dns_tcpmsg_t *tcpmsg) {
+ REQUIRE(VALID_TCPMSG(tcpmsg));
+
+ tcpmsg->magic = 0;
+
+ if (tcpmsg->buffer.base != NULL) {
+ isc_mem_put(tcpmsg->mctx, tcpmsg->buffer.base,
+ tcpmsg->buffer.length);
+ tcpmsg->buffer.base = NULL;
+ tcpmsg->buffer.length = 0;
+ }
+}
diff --git a/lib/dns/time.c b/lib/dns/time.c
new file mode 100644
index 0000000..69b3d2d
--- /dev/null
+++ b/lib/dns/time.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: time.c,v 1.31 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <time.h>
+
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/stdtime.h>
+#include <isc/util.h>
+
+#include <dns/result.h>
+#include <dns/time.h>
+
+static int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+isc_result_t
+dns_time64_totext(isc_int64_t t, isc_buffer_t *target) {
+ struct tm tm;
+ char buf[sizeof("YYYYMMDDHHMMSS")];
+ int secs;
+ unsigned int l;
+ isc_region_t region;
+
+ REQUIRE(t >= 0);
+
+#define is_leap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+#define year_secs(y) ((is_leap(y) ? 366 : 365 ) * 86400)
+#define month_secs(m,y) ((days[m] + ((m == 1 && is_leap(y)) ? 1 : 0 )) * 86400)
+
+ tm.tm_year = 70;
+ while ((secs = year_secs(tm.tm_year + 1900)) <= t) {
+ t -= secs;
+ tm.tm_year++;
+ if (tm.tm_year + 1900 > 9999)
+ return (ISC_R_RANGE);
+ }
+ tm.tm_mon = 0;
+ while ((secs = month_secs(tm.tm_mon, tm.tm_year + 1900)) <= t) {
+ t -= secs;
+ tm.tm_mon++;
+ }
+ tm.tm_mday = 1;
+ while (86400 <= t) {
+ t -= 86400;
+ tm.tm_mday++;
+ }
+ tm.tm_hour = 0;
+ while (3600 <= t) {
+ t -= 3600;
+ tm.tm_hour++;
+ }
+ tm.tm_min = 0;
+ while (60 <= t) {
+ t -= 60;
+ tm.tm_min++;
+ }
+ tm.tm_sec = (int)t;
+ /* yyyy mm dd HH MM SS */
+ snprintf(buf, sizeof(buf), "%04d%02d%02d%02d%02d%02d",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+ isc_buffer_availableregion(target, &region);
+ l = strlen(buf);
+
+ if (l > region.length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(region.base, buf, l);
+ isc_buffer_add(target, l);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_time32_totext(isc_uint32_t value, isc_buffer_t *target) {
+ isc_stdtime_t now;
+ isc_int64_t start;
+ isc_int64_t base;
+ isc_int64_t t;
+
+ /*
+ * Adjust the time to the closest epoch. This should be changed
+ * to use a 64-bit counterpart to isc_stdtime_get() if one ever
+ * is defined, but even the current code is good until the year
+ * 2106.
+ */
+ isc_stdtime_get(&now);
+ start = (isc_int64_t) now;
+ start -= 0x7fffffff;
+ base = 0;
+ while ((t = (base + value)) < start) {
+ base += 0x80000000;
+ base += 0x80000000;
+ }
+ return (dns_time64_totext(t, target));
+}
+
+isc_result_t
+dns_time64_fromtext(const char *source, isc_int64_t *target) {
+ int year, month, day, hour, minute, second;
+ isc_int64_t value;
+ int secs;
+ int i;
+
+#define RANGE(min, max, value) \
+ do { \
+ if (value < (min) || value > (max)) \
+ return (ISC_R_RANGE); \
+ } while (0)
+
+ if (strlen(source) != 14U)
+ return (DNS_R_SYNTAX);
+ if (sscanf(source, "%4d%2d%2d%2d%2d%2d",
+ &year, &month, &day, &hour, &minute, &second) != 6)
+ return (DNS_R_SYNTAX);
+
+ RANGE(1970, 9999, year);
+ RANGE(1, 12, month);
+ RANGE(1, days[month - 1] +
+ ((month == 2 && is_leap(year)) ? 1 : 0), day);
+ RANGE(0, 23, hour);
+ RANGE(0, 59, minute);
+ RANGE(0, 60, second); /* 60 == leap second. */
+
+ /*
+ * Calulate seconds since epoch.
+ */
+ value = second + (60 * minute) + (3600 * hour) + ((day - 1) * 86400);
+ for (i = 0; i < (month - 1); i++)
+ value += days[i] * 86400;
+ if (is_leap(year) && month > 2)
+ value += 86400;
+ for (i = 1970; i < year; i++) {
+ secs = (is_leap(i) ? 366 : 365) * 86400;
+ value += secs;
+ }
+
+ *target = value;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_time32_fromtext(const char *source, isc_uint32_t *target) {
+ isc_int64_t value64;
+ isc_result_t result;
+ result = dns_time64_fromtext(source, &value64);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ *target = (isc_uint32_t)value64;
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/dns/timer.c b/lib/dns/timer.c
new file mode 100644
index 0000000..39e4551
--- /dev/null
+++ b/lib/dns/timer.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: timer.c,v 1.7 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/result.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+
+#include <dns/types.h>
+#include <dns/timer.h>
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+isc_result_t
+dns_timer_setidle(isc_timer_t *timer, unsigned int maxtime,
+ unsigned int idletime, isc_boolean_t purge)
+{
+ isc_result_t result;
+ isc_interval_t maxinterval, idleinterval;
+ isc_time_t expires;
+
+ /* Compute the time of expiry. */
+ isc_interval_set(&maxinterval, maxtime, 0);
+ CHECK(isc_time_nowplusinterval(&expires, &maxinterval));
+
+ /*
+ * Compute the idle interval, and add a spare nanosecond to
+ * work around the silly limitation of the ISC timer interface
+ * that you cannot specify an idle interval of zero.
+ */
+ isc_interval_set(&idleinterval, idletime, 1);
+
+ CHECK(isc_timer_reset(timer, isc_timertype_once,
+ &expires, &idleinterval,
+ purge));
+ failure:
+ return (result);
+}
diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c
new file mode 100644
index 0000000..9e59dfa
--- /dev/null
+++ b/lib/dns/tkey.c
@@ -0,0 +1,1419 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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: tkey.c,v 1.90 2008/04/03 00:45:23 marka Exp $
+ */
+/*! \file */
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/md5.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/dnssec.h>
+#include <dns/fixedname.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+#include <dns/tkey.h>
+#include <dns/tsig.h>
+
+#include <dst/dst.h>
+#include <dst/gssapi.h>
+
+#define TKEY_RANDOM_AMOUNT 16
+
+#define RETERR(x) do { \
+ result = (x); \
+ if (result != ISC_R_SUCCESS) \
+ goto failure; \
+ } while (0)
+
+static void
+tkey_log(const char *fmt, ...) ISC_FORMAT_PRINTF(1, 2);
+
+static void
+tkey_log(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_REQUEST, ISC_LOG_DEBUG(4), fmt, ap);
+ va_end(ap);
+}
+
+static void
+_dns_tkey_dumpmessage(dns_message_t *msg) {
+ isc_buffer_t outbuf;
+ unsigned char output[4096];
+ isc_result_t result;
+
+ isc_buffer_init(&outbuf, output, sizeof(output));
+ result = dns_message_totext(msg, &dns_master_style_debug, 0,
+ &outbuf);
+ /* XXXMLG ignore result */
+ fprintf(stderr, "%.*s\n", (int)isc_buffer_usedlength(&outbuf),
+ (char *)isc_buffer_base(&outbuf));
+}
+
+isc_result_t
+dns_tkeyctx_create(isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp)
+{
+ dns_tkeyctx_t *tctx;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(ectx != NULL);
+ REQUIRE(tctxp != NULL && *tctxp == NULL);
+
+ tctx = isc_mem_get(mctx, sizeof(dns_tkeyctx_t));
+ if (tctx == NULL)
+ return (ISC_R_NOMEMORY);
+ tctx->mctx = NULL;
+ isc_mem_attach(mctx, &tctx->mctx);
+ tctx->ectx = NULL;
+ isc_entropy_attach(ectx, &tctx->ectx);
+ tctx->dhkey = NULL;
+ tctx->domain = NULL;
+ tctx->gsscred = NULL;
+
+ *tctxp = tctx;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_tkeyctx_destroy(dns_tkeyctx_t **tctxp) {
+ isc_mem_t *mctx;
+ dns_tkeyctx_t *tctx;
+
+ REQUIRE(tctxp != NULL && *tctxp != NULL);
+
+ tctx = *tctxp;
+ mctx = tctx->mctx;
+
+ if (tctx->dhkey != NULL)
+ dst_key_free(&tctx->dhkey);
+ if (tctx->domain != NULL) {
+ if (dns_name_dynamic(tctx->domain))
+ dns_name_free(tctx->domain, mctx);
+ isc_mem_put(mctx, tctx->domain, sizeof(dns_name_t));
+ }
+ if (tctx->gsscred != NULL)
+ dst_gssapi_releasecred(&tctx->gsscred);
+ isc_entropy_detach(&tctx->ectx);
+ isc_mem_put(mctx, tctx, sizeof(dns_tkeyctx_t));
+ isc_mem_detach(&mctx);
+ *tctxp = NULL;
+}
+
+static isc_result_t
+add_rdata_to_list(dns_message_t *msg, dns_name_t *name, dns_rdata_t *rdata,
+ isc_uint32_t ttl, dns_namelist_t *namelist)
+{
+ isc_result_t result;
+ isc_region_t r, newr;
+ dns_rdata_t *newrdata = NULL;
+ dns_name_t *newname = NULL;
+ dns_rdatalist_t *newlist = NULL;
+ dns_rdataset_t *newset = NULL;
+ isc_buffer_t *tmprdatabuf = NULL;
+
+ RETERR(dns_message_gettemprdata(msg, &newrdata));
+
+ dns_rdata_toregion(rdata, &r);
+ RETERR(isc_buffer_allocate(msg->mctx, &tmprdatabuf, r.length));
+ isc_buffer_availableregion(tmprdatabuf, &newr);
+ memcpy(newr.base, r.base, r.length);
+ dns_rdata_fromregion(newrdata, rdata->rdclass, rdata->type, &newr);
+ dns_message_takebuffer(msg, &tmprdatabuf);
+
+ RETERR(dns_message_gettempname(msg, &newname));
+ dns_name_init(newname, NULL);
+ RETERR(dns_name_dup(name, msg->mctx, newname));
+
+ RETERR(dns_message_gettemprdatalist(msg, &newlist));
+ newlist->rdclass = newrdata->rdclass;
+ newlist->type = newrdata->type;
+ newlist->covers = 0;
+ newlist->ttl = ttl;
+ ISC_LIST_INIT(newlist->rdata);
+ ISC_LIST_APPEND(newlist->rdata, newrdata, link);
+
+ RETERR(dns_message_gettemprdataset(msg, &newset));
+ dns_rdataset_init(newset);
+ RETERR(dns_rdatalist_tordataset(newlist, newset));
+
+ ISC_LIST_INIT(newname->list);
+ ISC_LIST_APPEND(newname->list, newset, link);
+
+ ISC_LIST_APPEND(*namelist, newname, link);
+
+ return (ISC_R_SUCCESS);
+
+ failure:
+ if (newrdata != NULL) {
+ if (ISC_LINK_LINKED(newrdata, link))
+ ISC_LIST_UNLINK(newlist->rdata, newrdata, link);
+ dns_message_puttemprdata(msg, &newrdata);
+ }
+ if (newname != NULL)
+ dns_message_puttempname(msg, &newname);
+ if (newset != NULL) {
+ dns_rdataset_disassociate(newset);
+ dns_message_puttemprdataset(msg, &newset);
+ }
+ if (newlist != NULL)
+ dns_message_puttemprdatalist(msg, &newlist);
+ return (result);
+}
+
+static void
+free_namelist(dns_message_t *msg, dns_namelist_t *namelist) {
+ dns_name_t *name;
+ dns_rdataset_t *set;
+
+ while (!ISC_LIST_EMPTY(*namelist)) {
+ name = ISC_LIST_HEAD(*namelist);
+ ISC_LIST_UNLINK(*namelist, name, link);
+ while (!ISC_LIST_EMPTY(name->list)) {
+ set = ISC_LIST_HEAD(name->list);
+ ISC_LIST_UNLINK(name->list, set, link);
+ dns_message_puttemprdataset(msg, &set);
+ }
+ dns_message_puttempname(msg, &name);
+ }
+}
+
+static isc_result_t
+compute_secret(isc_buffer_t *shared, isc_region_t *queryrandomness,
+ isc_region_t *serverrandomness, isc_buffer_t *secret)
+{
+ isc_md5_t md5ctx;
+ isc_region_t r, r2;
+ unsigned char digests[32];
+ unsigned int i;
+
+ isc_buffer_usedregion(shared, &r);
+
+ /*
+ * MD5 ( query data | DH value ).
+ */
+ isc_md5_init(&md5ctx);
+ isc_md5_update(&md5ctx, queryrandomness->base,
+ queryrandomness->length);
+ isc_md5_update(&md5ctx, r.base, r.length);
+ isc_md5_final(&md5ctx, digests);
+
+ /*
+ * MD5 ( server data | DH value ).
+ */
+ isc_md5_init(&md5ctx);
+ isc_md5_update(&md5ctx, serverrandomness->base,
+ serverrandomness->length);
+ isc_md5_update(&md5ctx, r.base, r.length);
+ isc_md5_final(&md5ctx, &digests[ISC_MD5_DIGESTLENGTH]);
+
+ /*
+ * XOR ( DH value, MD5-1 | MD5-2).
+ */
+ isc_buffer_availableregion(secret, &r);
+ isc_buffer_usedregion(shared, &r2);
+ if (r.length < sizeof(digests) || r.length < r2.length)
+ return (ISC_R_NOSPACE);
+ if (r2.length > sizeof(digests)) {
+ memcpy(r.base, r2.base, r2.length);
+ for (i = 0; i < sizeof(digests); i++)
+ r.base[i] ^= digests[i];
+ isc_buffer_add(secret, r2.length);
+ } else {
+ memcpy(r.base, digests, sizeof(digests));
+ for (i = 0; i < r2.length; i++)
+ r.base[i] ^= r2.base[i];
+ isc_buffer_add(secret, sizeof(digests));
+ }
+ return (ISC_R_SUCCESS);
+
+}
+
+static isc_result_t
+process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
+ dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx,
+ dns_rdata_tkey_t *tkeyout,
+ dns_tsig_keyring_t *ring, dns_namelist_t *namelist)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_name_t *keyname, ourname;
+ dns_rdataset_t *keyset = NULL;
+ dns_rdata_t keyrdata = DNS_RDATA_INIT, ourkeyrdata = DNS_RDATA_INIT;
+ isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE;
+ dst_key_t *pubkey = NULL;
+ isc_buffer_t ourkeybuf, *shared = NULL;
+ isc_region_t r, r2, ourkeyr;
+ unsigned char keydata[DST_KEY_MAXSIZE];
+ unsigned int sharedsize;
+ isc_buffer_t secret;
+ unsigned char *randomdata = NULL, secretdata[256];
+ dns_ttl_t ttl = 0;
+
+ if (tctx->dhkey == NULL) {
+ tkey_log("process_dhtkey: tkey-dhkey not defined");
+ tkeyout->error = dns_tsigerror_badalg;
+ return (DNS_R_REFUSED);
+ }
+
+ if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) {
+ tkey_log("process_dhtkey: algorithms other than "
+ "hmac-md5 are not supported");
+ tkeyout->error = dns_tsigerror_badalg;
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Look for a DH KEY record that will work with ours.
+ */
+ for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL);
+ result == ISC_R_SUCCESS && !found_key;
+ result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL)) {
+ keyname = NULL;
+ dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname);
+ keyset = NULL;
+ result = dns_message_findtype(keyname, dns_rdatatype_key, 0,
+ &keyset);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ for (result = dns_rdataset_first(keyset);
+ result == ISC_R_SUCCESS && !found_key;
+ result = dns_rdataset_next(keyset)) {
+ dns_rdataset_current(keyset, &keyrdata);
+ pubkey = NULL;
+ result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
+ msg->mctx, &pubkey);
+ if (result != ISC_R_SUCCESS) {
+ dns_rdata_reset(&keyrdata);
+ continue;
+ }
+ if (dst_key_alg(pubkey) == DNS_KEYALG_DH) {
+ if (dst_key_paramcompare(pubkey, tctx->dhkey))
+ {
+ found_key = ISC_TRUE;
+ ttl = keyset->ttl;
+ break;
+ } else
+ found_incompatible = ISC_TRUE;
+ }
+ dst_key_free(&pubkey);
+ dns_rdata_reset(&keyrdata);
+ }
+ }
+
+ if (!found_key) {
+ if (found_incompatible) {
+ tkey_log("process_dhtkey: found an incompatible key");
+ tkeyout->error = dns_tsigerror_badkey;
+ return (ISC_R_SUCCESS);
+ } else {
+ tkey_log("process_dhtkey: failed to find a key");
+ return (DNS_R_FORMERR);
+ }
+ }
+
+ RETERR(add_rdata_to_list(msg, keyname, &keyrdata, ttl, namelist));
+
+ isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata));
+ RETERR(dst_key_todns(tctx->dhkey, &ourkeybuf));
+ isc_buffer_usedregion(&ourkeybuf, &ourkeyr);
+ dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_any,
+ dns_rdatatype_key, &ourkeyr);
+
+ dns_name_init(&ourname, NULL);
+ dns_name_clone(dst_key_name(tctx->dhkey), &ourname);
+
+ /*
+ * XXXBEW The TTL should be obtained from the database, if it exists.
+ */
+ RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, 0, namelist));
+
+ RETERR(dst_key_secretsize(tctx->dhkey, &sharedsize));
+ RETERR(isc_buffer_allocate(msg->mctx, &shared, sharedsize));
+
+ result = dst_key_computesecret(pubkey, tctx->dhkey, shared);
+ if (result != ISC_R_SUCCESS) {
+ tkey_log("process_dhtkey: failed to compute shared secret: %s",
+ isc_result_totext(result));
+ goto failure;
+ }
+ dst_key_free(&pubkey);
+
+ isc_buffer_init(&secret, secretdata, sizeof(secretdata));
+
+ randomdata = isc_mem_get(tkeyout->mctx, TKEY_RANDOM_AMOUNT);
+ if (randomdata == NULL)
+ goto failure;
+
+ result = isc_entropy_getdata(tctx->ectx, randomdata,
+ TKEY_RANDOM_AMOUNT, NULL, 0);
+ if (result != ISC_R_SUCCESS) {
+ tkey_log("process_dhtkey: failed to obtain entropy: %s",
+ isc_result_totext(result));
+ goto failure;
+ }
+
+ r.base = randomdata;
+ r.length = TKEY_RANDOM_AMOUNT;
+ r2.base = tkeyin->key;
+ r2.length = tkeyin->keylen;
+ RETERR(compute_secret(shared, &r2, &r, &secret));
+ isc_buffer_free(&shared);
+
+ RETERR(dns_tsigkey_create(name, &tkeyin->algorithm,
+ isc_buffer_base(&secret),
+ isc_buffer_usedlength(&secret),
+ ISC_TRUE, signer, tkeyin->inception,
+ tkeyin->expire, ring->mctx, ring, NULL));
+
+ /* This key is good for a long time */
+ tkeyout->inception = tkeyin->inception;
+ tkeyout->expire = tkeyin->expire;
+
+ tkeyout->key = randomdata;
+ tkeyout->keylen = TKEY_RANDOM_AMOUNT;
+
+ return (ISC_R_SUCCESS);
+
+ failure:
+ if (!ISC_LIST_EMPTY(*namelist))
+ free_namelist(msg, namelist);
+ if (shared != NULL)
+ isc_buffer_free(&shared);
+ if (pubkey != NULL)
+ dst_key_free(&pubkey);
+ if (randomdata != NULL)
+ isc_mem_put(tkeyout->mctx, randomdata, TKEY_RANDOM_AMOUNT);
+ return (result);
+}
+
+static isc_result_t
+process_gsstkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
+ dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx,
+ dns_rdata_tkey_t *tkeyout,
+ dns_tsig_keyring_t *ring, dns_namelist_t *namelist)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dst_key_t *dstkey = NULL;
+ dns_tsigkey_t *tsigkey = NULL;
+ dns_fixedname_t principal;
+ isc_stdtime_t now;
+ isc_region_t intoken;
+ isc_buffer_t *outtoken = NULL;
+ gss_ctx_id_t gss_ctx = NULL;
+
+ UNUSED(namelist);
+ UNUSED(signer);
+
+ if (tctx->gsscred == NULL)
+ return (ISC_R_NOPERM);
+
+ if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPI_NAME) &&
+ !dns_name_equal(&tkeyin->algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
+ tkeyout->error = dns_tsigerror_badalg;
+ tkey_log("process_gsstkey(): dns_tsigerror_badalg"); /* XXXSRA */
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * XXXDCL need to check for key expiry per 4.1.1
+ * XXXDCL need a way to check fully established, perhaps w/key_flags
+ */
+
+ intoken.base = tkeyin->key;
+ intoken.length = tkeyin->keylen;
+
+ result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
+ if (result == ISC_R_SUCCESS)
+ gss_ctx = dst_key_getgssctx(tsigkey->key);
+
+
+ dns_fixedname_init(&principal);
+
+ result = dst_gssapi_acceptctx(tctx->gsscred, &intoken,
+ &outtoken, &gss_ctx,
+ dns_fixedname_name(&principal),
+ tctx->mctx);
+
+ if (tsigkey != NULL)
+ dns_tsigkey_detach(&tsigkey);
+
+ if (result == DNS_R_INVALIDTKEY) {
+ tkeyout->error = dns_tsigerror_badkey;
+ tkey_log("process_gsstkey(): dns_tsigerror_badkey"); /* XXXSRA */
+ return (ISC_R_SUCCESS);
+ } else if (result == ISC_R_FAILURE)
+ goto failure;
+ ENSURE(result == DNS_R_CONTINUE || result == ISC_R_SUCCESS);
+ /*
+ * XXXDCL Section 4.1.3: Limit GSS_S_CONTINUE_NEEDED to 10 times.
+ */
+
+ if (tsigkey == NULL) {
+ RETERR(dst_key_fromgssapi(name, gss_ctx, msg->mctx, &dstkey));
+ RETERR(dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
+ dstkey, ISC_TRUE,
+ dns_fixedname_name(&principal),
+ tkeyin->inception,
+ tkeyin->expire,
+ ring->mctx, ring, NULL));
+ }
+
+ isc_stdtime_get(&now);
+ tkeyout->inception = tkeyin->inception;
+ tkeyout->expire = tkeyin->expire;
+
+ if (outtoken) {
+ tkeyout->key = isc_mem_get(tkeyout->mctx,
+ isc_buffer_usedlength(outtoken));
+ if (tkeyout->key == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ tkeyout->keylen = isc_buffer_usedlength(outtoken);
+ memcpy(tkeyout->key, isc_buffer_base(outtoken),
+ isc_buffer_usedlength(outtoken));
+ isc_buffer_free(&outtoken);
+ } else {
+ tkeyout->key = isc_mem_get(tkeyout->mctx, tkeyin->keylen);
+ if (tkeyout->key == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+ tkeyout->keylen = tkeyin->keylen;
+ memcpy(tkeyout->key, tkeyin->key, tkeyin->keylen);
+ }
+
+ tkeyout->error = dns_rcode_noerror;
+
+ tkey_log("process_gsstkey(): dns_tsigerror_noerror"); /* XXXSRA */
+
+ return (ISC_R_SUCCESS);
+
+failure:
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+
+ if (outtoken != NULL)
+ isc_buffer_free(&outtoken);
+
+ tkey_log("process_gsstkey(): %s",
+ isc_result_totext(result)); /* XXXSRA */
+
+ return (result);
+}
+
+static isc_result_t
+process_deletetkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
+ dns_rdata_tkey_t *tkeyin,
+ dns_rdata_tkey_t *tkeyout,
+ dns_tsig_keyring_t *ring,
+ dns_namelist_t *namelist)
+{
+ isc_result_t result;
+ dns_tsigkey_t *tsigkey = NULL;
+ dns_name_t *identity;
+
+ UNUSED(msg);
+ UNUSED(namelist);
+
+ result = dns_tsigkey_find(&tsigkey, name, &tkeyin->algorithm, ring);
+ if (result != ISC_R_SUCCESS) {
+ tkeyout->error = dns_tsigerror_badname;
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Only allow a delete if the identity that created the key is the
+ * same as the identity that signed the message.
+ */
+ identity = dns_tsigkey_identity(tsigkey);
+ if (identity == NULL || !dns_name_equal(identity, signer)) {
+ dns_tsigkey_detach(&tsigkey);
+ return (DNS_R_REFUSED);
+ }
+
+ /*
+ * Set the key to be deleted when no references are left. If the key
+ * was not generated with TKEY and is in the config file, it may be
+ * reloaded later.
+ */
+ dns_tsigkey_setdeleted(tsigkey);
+
+ /* Release the reference */
+ dns_tsigkey_detach(&tsigkey);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_tkey_processquery(dns_message_t *msg, dns_tkeyctx_t *tctx,
+ dns_tsig_keyring_t *ring)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rdata_tkey_t tkeyin, tkeyout;
+ isc_boolean_t freetkeyin = ISC_FALSE;
+ dns_name_t *qname, *name, *keyname, *signer, tsigner;
+ dns_fixedname_t fkeyname;
+ dns_rdataset_t *tkeyset;
+ dns_rdata_t rdata;
+ dns_namelist_t namelist;
+ char tkeyoutdata[512];
+ isc_buffer_t tkeyoutbuf;
+
+ REQUIRE(msg != NULL);
+ REQUIRE(tctx != NULL);
+ REQUIRE(ring != NULL);
+
+ ISC_LIST_INIT(namelist);
+
+ /*
+ * Interpret the question section.
+ */
+ result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
+ if (result != ISC_R_SUCCESS)
+ return (DNS_R_FORMERR);
+
+ qname = NULL;
+ dns_message_currentname(msg, DNS_SECTION_QUESTION, &qname);
+
+ /*
+ * Look for a TKEY record that matches the question.
+ */
+ tkeyset = NULL;
+ name = NULL;
+ result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL, qname,
+ dns_rdatatype_tkey, 0, &name, &tkeyset);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * Try the answer section, since that's where Win2000
+ * puts it.
+ */
+ if (dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
+ dns_rdatatype_tkey, 0, &name,
+ &tkeyset) != ISC_R_SUCCESS) {
+ result = DNS_R_FORMERR;
+ tkey_log("dns_tkey_processquery: couldn't find a TKEY "
+ "matching the question");
+ goto failure;
+ }
+ }
+ result = dns_rdataset_first(tkeyset);
+ if (result != ISC_R_SUCCESS) {
+ result = DNS_R_FORMERR;
+ goto failure;
+ }
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(tkeyset, &rdata);
+
+ RETERR(dns_rdata_tostruct(&rdata, &tkeyin, NULL));
+ freetkeyin = ISC_TRUE;
+
+ if (tkeyin.error != dns_rcode_noerror) {
+ result = DNS_R_FORMERR;
+ goto failure;
+ }
+
+ /*
+ * Before we go any farther, verify that the message was signed.
+ * GSSAPI TKEY doesn't require a signature, the rest do.
+ */
+ dns_name_init(&tsigner, NULL);
+ result = dns_message_signer(msg, &tsigner);
+ if (result != ISC_R_SUCCESS) {
+ if (tkeyin.mode == DNS_TKEYMODE_GSSAPI &&
+ result == ISC_R_NOTFOUND)
+ signer = NULL;
+ else {
+ tkey_log("dns_tkey_processquery: query was not "
+ "properly signed - rejecting");
+ result = DNS_R_FORMERR;
+ goto failure;
+ }
+ } else
+ signer = &tsigner;
+
+ tkeyout.common.rdclass = tkeyin.common.rdclass;
+ tkeyout.common.rdtype = tkeyin.common.rdtype;
+ ISC_LINK_INIT(&tkeyout.common, link);
+ tkeyout.mctx = msg->mctx;
+
+ dns_name_init(&tkeyout.algorithm, NULL);
+ dns_name_clone(&tkeyin.algorithm, &tkeyout.algorithm);
+
+ tkeyout.inception = tkeyout.expire = 0;
+ tkeyout.mode = tkeyin.mode;
+ tkeyout.error = 0;
+ tkeyout.keylen = tkeyout.otherlen = 0;
+ tkeyout.key = tkeyout.other = NULL;
+
+ /*
+ * A delete operation must have a fully specified key name. If this
+ * is not a delete, we do the following:
+ * if (qname != ".")
+ * keyname = qname + defaultdomain
+ * else
+ * keyname = <random hex> + defaultdomain
+ */
+ if (tkeyin.mode != DNS_TKEYMODE_DELETE) {
+ dns_tsigkey_t *tsigkey = NULL;
+
+ if (tctx->domain == NULL && tkeyin.mode != DNS_TKEYMODE_GSSAPI) {
+ tkey_log("dns_tkey_processquery: tkey-domain not set");
+ result = DNS_R_REFUSED;
+ goto failure;
+ }
+
+ dns_fixedname_init(&fkeyname);
+ keyname = dns_fixedname_name(&fkeyname);
+
+ if (!dns_name_equal(qname, dns_rootname)) {
+ unsigned int n = dns_name_countlabels(qname);
+ RUNTIME_CHECK(dns_name_copy(qname, keyname, NULL)
+ == ISC_R_SUCCESS);
+ dns_name_getlabelsequence(keyname, 0, n - 1, keyname);
+ } else {
+ static char hexdigits[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+ unsigned char randomdata[16];
+ char randomtext[32];
+ isc_buffer_t b;
+ unsigned int i, j;
+
+ result = isc_entropy_getdata(tctx->ectx,
+ randomdata,
+ sizeof(randomdata),
+ NULL, 0);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ for (i = 0, j = 0; i < sizeof(randomdata); i++) {
+ unsigned char val = randomdata[i];
+ randomtext[j++] = hexdigits[val >> 4];
+ randomtext[j++] = hexdigits[val & 0xF];
+ }
+ isc_buffer_init(&b, randomtext, sizeof(randomtext));
+ isc_buffer_add(&b, sizeof(randomtext));
+ result = dns_name_fromtext(keyname, &b, NULL,
+ ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
+
+ if (tkeyin.mode == DNS_TKEYMODE_GSSAPI) {
+ /* Yup. This is a hack */
+ result = dns_name_concatenate(keyname, dns_rootname,
+ keyname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ } else {
+ result = dns_name_concatenate(keyname, tctx->domain,
+ keyname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
+
+ result = dns_tsigkey_find(&tsigkey, keyname, NULL, ring);
+
+ if (result == ISC_R_SUCCESS) {
+ tkeyout.error = dns_tsigerror_badname;
+ dns_tsigkey_detach(&tsigkey);
+ goto failure_with_tkey;
+ } else if (result != ISC_R_NOTFOUND)
+ goto failure;
+ } else
+ keyname = qname;
+
+ switch (tkeyin.mode) {
+ case DNS_TKEYMODE_DIFFIEHELLMAN:
+ tkeyout.error = dns_rcode_noerror;
+ RETERR(process_dhtkey(msg, signer, keyname, &tkeyin,
+ tctx, &tkeyout, ring,
+ &namelist));
+ break;
+ case DNS_TKEYMODE_GSSAPI:
+ tkeyout.error = dns_rcode_noerror;
+ RETERR(process_gsstkey(msg, signer, keyname, &tkeyin,
+ tctx, &tkeyout, ring,
+ &namelist));
+
+ break;
+ case DNS_TKEYMODE_DELETE:
+ tkeyout.error = dns_rcode_noerror;
+ RETERR(process_deletetkey(msg, signer, keyname,
+ &tkeyin, &tkeyout,
+ ring, &namelist));
+ break;
+ case DNS_TKEYMODE_SERVERASSIGNED:
+ case DNS_TKEYMODE_RESOLVERASSIGNED:
+ result = DNS_R_NOTIMP;
+ goto failure;
+ default:
+ tkeyout.error = dns_tsigerror_badmode;
+ }
+
+ failure_with_tkey:
+ dns_rdata_init(&rdata);
+ isc_buffer_init(&tkeyoutbuf, tkeyoutdata, sizeof(tkeyoutdata));
+ result = dns_rdata_fromstruct(&rdata, tkeyout.common.rdclass,
+ tkeyout.common.rdtype, &tkeyout,
+ &tkeyoutbuf);
+
+ if (freetkeyin) {
+ dns_rdata_freestruct(&tkeyin);
+ freetkeyin = ISC_FALSE;
+ }
+
+ if (tkeyout.key != NULL)
+ isc_mem_put(tkeyout.mctx, tkeyout.key, tkeyout.keylen);
+ if (tkeyout.other != NULL)
+ isc_mem_put(tkeyout.mctx, tkeyout.other, tkeyout.otherlen);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ RETERR(add_rdata_to_list(msg, keyname, &rdata, 0, &namelist));
+
+ RETERR(dns_message_reply(msg, ISC_TRUE));
+
+ name = ISC_LIST_HEAD(namelist);
+ while (name != NULL) {
+ dns_name_t *next = ISC_LIST_NEXT(name, link);
+ ISC_LIST_UNLINK(namelist, name, link);
+ dns_message_addname(msg, name, DNS_SECTION_ANSWER);
+ name = next;
+ }
+
+ return (ISC_R_SUCCESS);
+
+ failure:
+ if (freetkeyin)
+ dns_rdata_freestruct(&tkeyin);
+ if (!ISC_LIST_EMPTY(namelist))
+ free_namelist(msg, &namelist);
+ return (result);
+}
+
+static isc_result_t
+buildquery(dns_message_t *msg, dns_name_t *name,
+ dns_rdata_tkey_t *tkey, isc_boolean_t win2k)
+{
+ dns_name_t *qname = NULL, *aname = NULL;
+ dns_rdataset_t *question = NULL, *tkeyset = NULL;
+ dns_rdatalist_t *tkeylist = NULL;
+ dns_rdata_t *rdata = NULL;
+ isc_buffer_t *dynbuf = NULL;
+ isc_result_t result;
+
+ REQUIRE(msg != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(tkey != NULL);
+
+ RETERR(dns_message_gettempname(msg, &qname));
+ RETERR(dns_message_gettempname(msg, &aname));
+
+ RETERR(dns_message_gettemprdataset(msg, &question));
+ dns_rdataset_init(question);
+ dns_rdataset_makequestion(question, dns_rdataclass_any,
+ dns_rdatatype_tkey);
+
+ RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 4096));
+ RETERR(dns_message_gettemprdata(msg, &rdata));
+
+ RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
+ dns_rdatatype_tkey, tkey, dynbuf));
+ dns_message_takebuffer(msg, &dynbuf);
+
+ RETERR(dns_message_gettemprdatalist(msg, &tkeylist));
+ tkeylist->rdclass = dns_rdataclass_any;
+ tkeylist->type = dns_rdatatype_tkey;
+ tkeylist->covers = 0;
+ tkeylist->ttl = 0;
+ ISC_LIST_INIT(tkeylist->rdata);
+ ISC_LIST_APPEND(tkeylist->rdata, rdata, link);
+
+ RETERR(dns_message_gettemprdataset(msg, &tkeyset));
+ dns_rdataset_init(tkeyset);
+ RETERR(dns_rdatalist_tordataset(tkeylist, tkeyset));
+
+ dns_name_init(qname, NULL);
+ dns_name_clone(name, qname);
+
+ dns_name_init(aname, NULL);
+ dns_name_clone(name, aname);
+
+ ISC_LIST_APPEND(qname->list, question, link);
+ ISC_LIST_APPEND(aname->list, tkeyset, link);
+
+ dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
+
+ /*
+ * Windows 2000 needs this in the answer section, not the additional
+ * section where the RFC specifies.
+ */
+ if (win2k)
+ dns_message_addname(msg, aname, DNS_SECTION_ANSWER);
+ else
+ dns_message_addname(msg, aname, DNS_SECTION_ADDITIONAL);
+
+ return (ISC_R_SUCCESS);
+
+ failure:
+ if (qname != NULL)
+ dns_message_puttempname(msg, &qname);
+ if (aname != NULL)
+ dns_message_puttempname(msg, &aname);
+ if (question != NULL) {
+ dns_rdataset_disassociate(question);
+ dns_message_puttemprdataset(msg, &question);
+ }
+ if (dynbuf != NULL)
+ isc_buffer_free(&dynbuf);
+ printf("buildquery error\n");
+ return (result);
+}
+
+isc_result_t
+dns_tkey_builddhquery(dns_message_t *msg, dst_key_t *key, dns_name_t *name,
+ dns_name_t *algorithm, isc_buffer_t *nonce,
+ isc_uint32_t lifetime)
+{
+ dns_rdata_tkey_t tkey;
+ dns_rdata_t *rdata = NULL;
+ isc_buffer_t *dynbuf = NULL;
+ isc_region_t r;
+ dns_name_t keyname;
+ dns_namelist_t namelist;
+ isc_result_t result;
+ isc_stdtime_t now;
+
+ REQUIRE(msg != NULL);
+ REQUIRE(key != NULL);
+ REQUIRE(dst_key_alg(key) == DNS_KEYALG_DH);
+ REQUIRE(dst_key_isprivate(key));
+ REQUIRE(name != NULL);
+ REQUIRE(algorithm != NULL);
+
+ tkey.common.rdclass = dns_rdataclass_any;
+ tkey.common.rdtype = dns_rdatatype_tkey;
+ ISC_LINK_INIT(&tkey.common, link);
+ tkey.mctx = msg->mctx;
+ dns_name_init(&tkey.algorithm, NULL);
+ dns_name_clone(algorithm, &tkey.algorithm);
+ isc_stdtime_get(&now);
+ tkey.inception = now;
+ tkey.expire = now + lifetime;
+ tkey.mode = DNS_TKEYMODE_DIFFIEHELLMAN;
+ if (nonce != NULL)
+ isc_buffer_usedregion(nonce, &r);
+ else {
+ r.base = isc_mem_get(msg->mctx, 0);
+ r.length = 0;
+ }
+ tkey.error = 0;
+ tkey.key = r.base;
+ tkey.keylen = r.length;
+ tkey.other = NULL;
+ tkey.otherlen = 0;
+
+ RETERR(buildquery(msg, name, &tkey, ISC_FALSE));
+
+ if (nonce == NULL)
+ isc_mem_put(msg->mctx, r.base, 0);
+
+ RETERR(dns_message_gettemprdata(msg, &rdata));
+ RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024));
+ RETERR(dst_key_todns(key, dynbuf));
+ isc_buffer_usedregion(dynbuf, &r);
+ dns_rdata_fromregion(rdata, dns_rdataclass_any,
+ dns_rdatatype_key, &r);
+ dns_message_takebuffer(msg, &dynbuf);
+
+ dns_name_init(&keyname, NULL);
+ dns_name_clone(dst_key_name(key), &keyname);
+
+ ISC_LIST_INIT(namelist);
+ RETERR(add_rdata_to_list(msg, &keyname, rdata, 0, &namelist));
+ dns_message_addname(msg, ISC_LIST_HEAD(namelist),
+ DNS_SECTION_ADDITIONAL);
+
+ return (ISC_R_SUCCESS);
+
+ failure:
+
+ if (dynbuf != NULL)
+ isc_buffer_free(&dynbuf);
+ return (result);
+}
+
+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)
+{
+ dns_rdata_tkey_t tkey;
+ isc_result_t result;
+ isc_stdtime_t now;
+ isc_buffer_t token;
+ unsigned char array[4096];
+
+ UNUSED(intoken);
+
+ REQUIRE(msg != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(gname != NULL);
+ REQUIRE(context != NULL);
+
+ isc_buffer_init(&token, array, sizeof(array));
+ result = dst_gssapi_initctx(gname, NULL, &token, context);
+ if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
+ return (result);
+
+ tkey.common.rdclass = dns_rdataclass_any;
+ tkey.common.rdtype = dns_rdatatype_tkey;
+ ISC_LINK_INIT(&tkey.common, link);
+ tkey.mctx = NULL;
+ dns_name_init(&tkey.algorithm, NULL);
+
+ if (win2k)
+ dns_name_clone(DNS_TSIG_GSSAPIMS_NAME, &tkey.algorithm);
+ else
+ dns_name_clone(DNS_TSIG_GSSAPI_NAME, &tkey.algorithm);
+
+ isc_stdtime_get(&now);
+ tkey.inception = now;
+ tkey.expire = now + lifetime;
+ tkey.mode = DNS_TKEYMODE_GSSAPI;
+ tkey.error = 0;
+ tkey.key = isc_buffer_base(&token);
+ tkey.keylen = isc_buffer_usedlength(&token);
+ tkey.other = NULL;
+ tkey.otherlen = 0;
+
+ RETERR(buildquery(msg, name, &tkey, win2k));
+
+ return (ISC_R_SUCCESS);
+
+ failure:
+ return (result);
+}
+
+isc_result_t
+dns_tkey_builddeletequery(dns_message_t *msg, dns_tsigkey_t *key) {
+ dns_rdata_tkey_t tkey;
+
+ REQUIRE(msg != NULL);
+ REQUIRE(key != NULL);
+
+ tkey.common.rdclass = dns_rdataclass_any;
+ tkey.common.rdtype = dns_rdatatype_tkey;
+ ISC_LINK_INIT(&tkey.common, link);
+ tkey.mctx = msg->mctx;
+ dns_name_init(&tkey.algorithm, NULL);
+ dns_name_clone(key->algorithm, &tkey.algorithm);
+ tkey.inception = tkey.expire = 0;
+ tkey.mode = DNS_TKEYMODE_DELETE;
+ tkey.error = 0;
+ tkey.keylen = tkey.otherlen = 0;
+ tkey.key = tkey.other = NULL;
+
+ return (buildquery(msg, &key->name, &tkey, ISC_FALSE));
+}
+
+static isc_result_t
+find_tkey(dns_message_t *msg, dns_name_t **name, dns_rdata_t *rdata,
+ int section)
+{
+ dns_rdataset_t *tkeyset;
+ isc_result_t result;
+
+ result = dns_message_firstname(msg, section);
+ while (result == ISC_R_SUCCESS) {
+ *name = NULL;
+ dns_message_currentname(msg, section, name);
+ tkeyset = NULL;
+ result = dns_message_findtype(*name, dns_rdatatype_tkey, 0,
+ &tkeyset);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_rdataset_first(tkeyset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_current(tkeyset, rdata);
+ return (ISC_R_SUCCESS);
+ }
+ result = dns_message_nextname(msg, section);
+ }
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_NOTFOUND);
+ return (result);
+}
+
+isc_result_t
+dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
+ dst_key_t *key, isc_buffer_t *nonce,
+ dns_tsigkey_t **outkey, dns_tsig_keyring_t *ring)
+{
+ dns_rdata_t qtkeyrdata = DNS_RDATA_INIT, rtkeyrdata = DNS_RDATA_INIT;
+ dns_name_t keyname, *tkeyname, *theirkeyname, *ourkeyname, *tempname;
+ dns_rdataset_t *theirkeyset = NULL, *ourkeyset = NULL;
+ dns_rdata_t theirkeyrdata = DNS_RDATA_INIT;
+ dst_key_t *theirkey = NULL;
+ dns_rdata_tkey_t qtkey, rtkey;
+ unsigned char secretdata[256];
+ unsigned int sharedsize;
+ isc_buffer_t *shared = NULL, secret;
+ isc_region_t r, r2;
+ isc_result_t result;
+ isc_boolean_t freertkey = ISC_FALSE;
+
+ REQUIRE(qmsg != NULL);
+ REQUIRE(rmsg != NULL);
+ REQUIRE(key != NULL);
+ REQUIRE(dst_key_alg(key) == DNS_KEYALG_DH);
+ REQUIRE(dst_key_isprivate(key));
+ if (outkey != NULL)
+ REQUIRE(*outkey == NULL);
+
+ if (rmsg->rcode != dns_rcode_noerror)
+ return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
+ RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
+ RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
+ freertkey = ISC_TRUE;
+
+ RETERR(find_tkey(qmsg, &tempname, &qtkeyrdata,
+ DNS_SECTION_ADDITIONAL));
+ RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
+
+ if (rtkey.error != dns_rcode_noerror ||
+ rtkey.mode != DNS_TKEYMODE_DIFFIEHELLMAN ||
+ rtkey.mode != qtkey.mode ||
+ !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm) ||
+ rmsg->rcode != dns_rcode_noerror) {
+ tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
+ "or error set(1)");
+ result = DNS_R_INVALIDTKEY;
+ dns_rdata_freestruct(&qtkey);
+ goto failure;
+ }
+
+ dns_rdata_freestruct(&qtkey);
+
+ dns_name_init(&keyname, NULL);
+ dns_name_clone(dst_key_name(key), &keyname);
+
+ ourkeyname = NULL;
+ ourkeyset = NULL;
+ RETERR(dns_message_findname(rmsg, DNS_SECTION_ANSWER, &keyname,
+ dns_rdatatype_key, 0, &ourkeyname,
+ &ourkeyset));
+
+ result = dns_message_firstname(rmsg, DNS_SECTION_ANSWER);
+ while (result == ISC_R_SUCCESS) {
+ theirkeyname = NULL;
+ dns_message_currentname(rmsg, DNS_SECTION_ANSWER,
+ &theirkeyname);
+ if (dns_name_equal(theirkeyname, ourkeyname))
+ goto next;
+ theirkeyset = NULL;
+ result = dns_message_findtype(theirkeyname, dns_rdatatype_key,
+ 0, &theirkeyset);
+ if (result == ISC_R_SUCCESS) {
+ RETERR(dns_rdataset_first(theirkeyset));
+ break;
+ }
+ next:
+ result = dns_message_nextname(rmsg, DNS_SECTION_ANSWER);
+ }
+
+ if (theirkeyset == NULL) {
+ tkey_log("dns_tkey_processdhresponse: failed to find server "
+ "key");
+ result = ISC_R_NOTFOUND;
+ goto failure;
+ }
+
+ dns_rdataset_current(theirkeyset, &theirkeyrdata);
+ RETERR(dns_dnssec_keyfromrdata(theirkeyname, &theirkeyrdata,
+ rmsg->mctx, &theirkey));
+
+ RETERR(dst_key_secretsize(key, &sharedsize));
+ RETERR(isc_buffer_allocate(rmsg->mctx, &shared, sharedsize));
+
+ RETERR(dst_key_computesecret(theirkey, key, shared));
+
+ isc_buffer_init(&secret, secretdata, sizeof(secretdata));
+
+ r.base = rtkey.key;
+ r.length = rtkey.keylen;
+ if (nonce != NULL)
+ isc_buffer_usedregion(nonce, &r2);
+ else {
+ r2.base = isc_mem_get(rmsg->mctx, 0);
+ r2.length = 0;
+ }
+ RETERR(compute_secret(shared, &r2, &r, &secret));
+ if (nonce == NULL)
+ isc_mem_put(rmsg->mctx, r2.base, 0);
+
+ isc_buffer_usedregion(&secret, &r);
+ result = dns_tsigkey_create(tkeyname, &rtkey.algorithm,
+ r.base, r.length, ISC_TRUE,
+ NULL, rtkey.inception, rtkey.expire,
+ rmsg->mctx, ring, outkey);
+ isc_buffer_free(&shared);
+ dns_rdata_freestruct(&rtkey);
+ dst_key_free(&theirkey);
+ return (result);
+
+ failure:
+ if (shared != NULL)
+ isc_buffer_free(&shared);
+
+ if (theirkey != NULL)
+ dst_key_free(&theirkey);
+
+ if (freertkey)
+ dns_rdata_freestruct(&rtkey);
+
+ return (result);
+}
+
+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_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
+ dns_name_t *tkeyname;
+ dns_rdata_tkey_t rtkey, qtkey;
+ dst_key_t *dstkey = NULL;
+ isc_buffer_t intoken;
+ isc_result_t result;
+ unsigned char array[1024];
+
+ REQUIRE(outtoken != NULL);
+ REQUIRE(qmsg != NULL);
+ REQUIRE(rmsg != NULL);
+ REQUIRE(gname != NULL);
+ if (outkey != NULL)
+ REQUIRE(*outkey == NULL);
+
+ if (rmsg->rcode != dns_rcode_noerror)
+ return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
+ RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
+ RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
+
+ /*
+ * Win2k puts the item in the ANSWER section, while the RFC
+ * specifies it should be in the ADDITIONAL section. Check first
+ * where it should be, and then where it may be.
+ */
+ result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ADDITIONAL);
+ if (result == ISC_R_NOTFOUND)
+ result = find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ANSWER);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
+
+ if (rtkey.error != dns_rcode_noerror ||
+ rtkey.mode != DNS_TKEYMODE_GSSAPI ||
+ !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm)) {
+ tkey_log("dns_tkey_processgssresponse: tkey mode invalid "
+ "or error set(2) %d", rtkey.error);
+ _dns_tkey_dumpmessage(qmsg);
+ _dns_tkey_dumpmessage(rmsg);
+ result = DNS_R_INVALIDTKEY;
+ goto failure;
+ }
+
+ isc_buffer_init(outtoken, array, sizeof(array));
+ isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
+ RETERR(dst_gssapi_initctx(gname, &intoken, outtoken, context));
+
+ dstkey = NULL;
+ RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
+ &dstkey));
+
+ RETERR(dns_tsigkey_createfromkey(tkeyname, DNS_TSIG_GSSAPI_NAME,
+ dstkey, ISC_FALSE, NULL,
+ rtkey.inception, rtkey.expire,
+ ring->mctx, ring, outkey));
+
+ dns_rdata_freestruct(&rtkey);
+ return (result);
+
+ failure:
+ /*
+ * XXXSRA This probably leaks memory from rtkey and qtkey.
+ */
+ return (result);
+}
+
+isc_result_t
+dns_tkey_processdeleteresponse(dns_message_t *qmsg, dns_message_t *rmsg,
+ dns_tsig_keyring_t *ring)
+{
+ dns_rdata_t qtkeyrdata = DNS_RDATA_INIT, rtkeyrdata = DNS_RDATA_INIT;
+ dns_name_t *tkeyname, *tempname;
+ dns_rdata_tkey_t qtkey, rtkey;
+ dns_tsigkey_t *tsigkey = NULL;
+ isc_result_t result;
+
+ REQUIRE(qmsg != NULL);
+ REQUIRE(rmsg != NULL);
+
+ if (rmsg->rcode != dns_rcode_noerror)
+ return(ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
+
+ RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
+ RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
+
+ RETERR(find_tkey(qmsg, &tempname, &qtkeyrdata,
+ DNS_SECTION_ADDITIONAL));
+ RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
+
+ if (rtkey.error != dns_rcode_noerror ||
+ rtkey.mode != DNS_TKEYMODE_DELETE ||
+ rtkey.mode != qtkey.mode ||
+ !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm) ||
+ rmsg->rcode != dns_rcode_noerror) {
+ tkey_log("dns_tkey_processdeleteresponse: tkey mode invalid "
+ "or error set(3)");
+ result = DNS_R_INVALIDTKEY;
+ dns_rdata_freestruct(&qtkey);
+ dns_rdata_freestruct(&rtkey);
+ goto failure;
+ }
+
+ dns_rdata_freestruct(&qtkey);
+
+ RETERR(dns_tsigkey_find(&tsigkey, tkeyname, &rtkey.algorithm, ring));
+
+ dns_rdata_freestruct(&rtkey);
+
+ /*
+ * Mark the key as deleted.
+ */
+ dns_tsigkey_setdeleted(tsigkey);
+ /*
+ * Release the reference.
+ */
+ dns_tsigkey_detach(&tsigkey);
+
+ failure:
+ return (result);
+}
+
+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)
+{
+ dns_rdata_t rtkeyrdata = DNS_RDATA_INIT, qtkeyrdata = DNS_RDATA_INIT;
+ dns_name_t *tkeyname;
+ dns_rdata_tkey_t rtkey, qtkey;
+ isc_buffer_t intoken, outtoken;
+ dst_key_t *dstkey = NULL;
+ isc_result_t result;
+ unsigned char array[1024];
+
+ REQUIRE(qmsg != NULL);
+ REQUIRE(rmsg != NULL);
+ REQUIRE(server != NULL);
+ if (outkey != NULL)
+ REQUIRE(*outkey == NULL);
+
+ if (rmsg->rcode != dns_rcode_noerror)
+ return (ISC_RESULTCLASS_DNSRCODE + rmsg->rcode);
+
+ RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER));
+ RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL));
+
+ if (win2k == ISC_TRUE)
+ RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ANSWER));
+ else
+ RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata,
+ DNS_SECTION_ADDITIONAL));
+
+ RETERR(dns_rdata_tostruct(&qtkeyrdata, &qtkey, NULL));
+
+ if (rtkey.error != dns_rcode_noerror ||
+ rtkey.mode != DNS_TKEYMODE_GSSAPI ||
+ !dns_name_equal(&rtkey.algorithm, &qtkey.algorithm))
+ {
+ tkey_log("dns_tkey_processdhresponse: tkey mode invalid "
+ "or error set(4)");
+ result = DNS_R_INVALIDTKEY;
+ goto failure;
+ }
+
+ isc_buffer_init(&intoken, rtkey.key, rtkey.keylen);
+ isc_buffer_init(&outtoken, array, sizeof(array));
+
+ result = dst_gssapi_initctx(server, &intoken, &outtoken, context);
+ if (result != DNS_R_CONTINUE && result != ISC_R_SUCCESS)
+ return (result);
+
+ dstkey = NULL;
+ RETERR(dst_key_fromgssapi(dns_rootname, *context, rmsg->mctx,
+ &dstkey));
+
+ /*
+ * XXXSRA This seems confused. If we got CONTINUE from initctx,
+ * the GSS negotiation hasn't completed yet, so we can't sign
+ * anything yet.
+ */
+
+ RETERR(dns_tsigkey_createfromkey(tkeyname,
+ (win2k
+ ? DNS_TSIG_GSSAPIMS_NAME
+ : DNS_TSIG_GSSAPI_NAME),
+ dstkey, ISC_TRUE, NULL,
+ rtkey.inception, rtkey.expire,
+ ring->mctx, ring, outkey));
+
+ dns_rdata_freestruct(&rtkey);
+ return (result);
+
+ failure:
+ /*
+ * XXXSRA This probably leaks memory from qtkey.
+ */
+ dns_rdata_freestruct(&rtkey);
+ return (result);
+}
diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c
new file mode 100644
index 0000000..74a7af3
--- /dev/null
+++ b/lib/dns/tsig.c
@@ -0,0 +1,1549 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: tsig.c,v 1.136 2008/11/04 21:23:14 marka Exp $
+ */
+/*! \file */
+#include <config.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/refcount.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+#include <isc/time.h>
+
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/fixedname.h>
+#include <dns/rbt.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/result.h>
+#include <dns/tsig.h>
+
+#include <dst/result.h>
+
+#define TSIG_MAGIC ISC_MAGIC('T', 'S', 'I', 'G')
+#define VALID_TSIG_KEY(x) ISC_MAGIC_VALID(x, TSIG_MAGIC)
+
+#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
+#define algname_is_allocated(algname) \
+ ((algname) != dns_tsig_hmacmd5_name && \
+ (algname) != dns_tsig_hmacsha1_name && \
+ (algname) != dns_tsig_hmacsha224_name && \
+ (algname) != dns_tsig_hmacsha256_name && \
+ (algname) != dns_tsig_hmacsha384_name && \
+ (algname) != dns_tsig_hmacsha512_name && \
+ (algname) != dns_tsig_gssapi_name && \
+ (algname) != dns_tsig_gssapims_name)
+
+#define BADTIMELEN 6
+
+static unsigned char hmacmd5_ndata[] = "\010hmac-md5\007sig-alg\003reg\003int";
+static unsigned char hmacmd5_offsets[] = { 0, 9, 17, 21, 25 };
+
+static dns_name_t hmacmd5 = {
+ DNS_NAME_MAGIC,
+ hmacmd5_ndata, 26, 5,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacmd5_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+dns_name_t *dns_tsig_hmacmd5_name = &hmacmd5;
+
+static unsigned char gsstsig_ndata[] = "\010gss-tsig";
+static unsigned char gsstsig_offsets[] = { 0, 9 };
+static dns_name_t gsstsig = {
+ DNS_NAME_MAGIC,
+ gsstsig_ndata, 10, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ gsstsig_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapi_name = &gsstsig;
+
+/*
+ * Since Microsoft doesn't follow its own standard, we will use this
+ * alternate name as a second guess.
+ */
+static unsigned char gsstsigms_ndata[] = "\003gss\011microsoft\003com";
+static unsigned char gsstsigms_offsets[] = { 0, 4, 14, 18 };
+static dns_name_t gsstsigms = {
+ DNS_NAME_MAGIC,
+ gsstsigms_ndata, 19, 4,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ gsstsigms_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_gssapims_name = &gsstsigms;
+
+static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
+static unsigned char hmacsha1_offsets[] = { 0, 10 };
+
+static dns_name_t hmacsha1 = {
+ DNS_NAME_MAGIC,
+ hmacsha1_ndata, 11, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha1_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
+
+static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
+static unsigned char hmacsha224_offsets[] = { 0, 12 };
+
+static dns_name_t hmacsha224 = {
+ DNS_NAME_MAGIC,
+ hmacsha224_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha224_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
+
+static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
+static unsigned char hmacsha256_offsets[] = { 0, 12 };
+
+static dns_name_t hmacsha256 = {
+ DNS_NAME_MAGIC,
+ hmacsha256_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha256_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
+
+static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
+static unsigned char hmacsha384_offsets[] = { 0, 12 };
+
+static dns_name_t hmacsha384 = {
+ DNS_NAME_MAGIC,
+ hmacsha384_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha384_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
+
+static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
+static unsigned char hmacsha512_offsets[] = { 0, 12 };
+
+static dns_name_t hmacsha512 = {
+ DNS_NAME_MAGIC,
+ hmacsha512_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha512_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
+};
+
+LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
+
+static isc_result_t
+tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
+
+static void
+tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+static void
+cleanup_ring(dns_tsig_keyring_t *ring);
+static void
+tsigkey_free(dns_tsigkey_t *key);
+
+static void
+tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
+ va_list ap;
+ char message[4096];
+ char namestr[DNS_NAME_FORMATSIZE];
+ char creatorstr[DNS_NAME_FORMATSIZE];
+
+ if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
+ return;
+ if (key != NULL)
+ dns_name_format(&key->name, namestr, sizeof(namestr));
+ else
+ strcpy(namestr, "<null>");
+
+ if (key != NULL && key->generated)
+ dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
+
+ va_start(ap, fmt);
+ vsnprintf(message, sizeof(message), fmt, ap);
+ va_end(ap);
+ if (key != NULL && key->generated)
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
+ level, "tsig key '%s' (%s): %s",
+ namestr, creatorstr, message);
+ else
+ isc_log_write(dns_lctx,
+ DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
+ level, "tsig key '%s': %s", namestr, message);
+}
+
+isc_result_t
+dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
+ dst_key_t *dstkey, isc_boolean_t generated,
+ dns_name_t *creator, isc_stdtime_t inception,
+ isc_stdtime_t expire, isc_mem_t *mctx,
+ dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
+{
+ dns_tsigkey_t *tkey;
+ isc_result_t ret;
+ unsigned int refs = 0;
+
+ REQUIRE(key == NULL || *key == NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(algorithm != NULL);
+ REQUIRE(mctx != NULL);
+ REQUIRE(key != NULL || ring != NULL);
+
+ tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
+ if (tkey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ dns_name_init(&tkey->name, NULL);
+ ret = dns_name_dup(name, mctx, &tkey->name);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_key;
+ (void)dns_name_downcase(&tkey->name, &tkey->name, NULL);
+
+ if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
+ if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
+ if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
+ if (dstkey != NULL &&
+ dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
+ if (dstkey != NULL &&
+ dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
+ if (dstkey != NULL &&
+ dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
+ tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
+ if (dstkey != NULL &&
+ dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
+ tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
+ if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
+ tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
+ if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ } else {
+ if (dstkey != NULL) {
+ ret = DNS_R_BADALG;
+ goto cleanup_name;
+ }
+ tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (tkey->algorithm == NULL) {
+ ret = ISC_R_NOMEMORY;
+ goto cleanup_name;
+ }
+ dns_name_init(tkey->algorithm, NULL);
+ ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_algorithm;
+ (void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
+ NULL);
+ }
+
+ if (creator != NULL) {
+ tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
+ if (tkey->creator == NULL) {
+ ret = ISC_R_NOMEMORY;
+ goto cleanup_algorithm;
+ }
+ dns_name_init(tkey->creator, NULL);
+ ret = dns_name_dup(creator, mctx, tkey->creator);
+ if (ret != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
+ goto cleanup_algorithm;
+ }
+ } else
+ tkey->creator = NULL;
+
+ tkey->key = dstkey;
+ tkey->ring = ring;
+
+ if (key != NULL)
+ refs++;
+ if (ring != NULL)
+ refs++;
+ ret = isc_refcount_init(&tkey->refs, refs);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_creator;
+
+ tkey->generated = generated;
+ tkey->inception = inception;
+ tkey->expire = expire;
+ tkey->mctx = NULL;
+ isc_mem_attach(mctx, &tkey->mctx);
+
+ 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);
+ goto cleanup_refs;
+ }
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+ }
+
+ /*
+ * Ignore this if it's a GSS key, since the key size is meaningless.
+ */
+ if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
+ !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
+ !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(name, namestr, sizeof(namestr));
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
+ "the key '%s' is too short to be secure",
+ namestr);
+ }
+ if (key != NULL)
+ *key = tkey;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_refs:
+ tkey->magic = 0;
+ while (refs-- > 0)
+ isc_refcount_decrement(&tkey->refs, NULL);
+ isc_refcount_destroy(&tkey->refs);
+ cleanup_creator:
+ if (tkey->creator != NULL) {
+ dns_name_free(tkey->creator, mctx);
+ isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
+ }
+ cleanup_algorithm:
+ if (algname_is_allocated(tkey->algorithm)) {
+ if (dns_name_dynamic(tkey->algorithm))
+ dns_name_free(tkey->algorithm, mctx);
+ isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
+ }
+ cleanup_name:
+ dns_name_free(&tkey->name, mctx);
+ cleanup_key:
+ isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));
+
+ return (ret);
+}
+
+/*
+ * Find a few nodes to destroy if possible.
+ */
+static void
+cleanup_ring(dns_tsig_keyring_t *ring)
+{
+ 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;
+
+ /*
+ * Start up a new iterator each time.
+ */
+ isc_stdtime_get(&now);
+ dns_name_init(&foundname, NULL);
+ dns_fixedname_init(&fixedorigin);
+ origin = dns_fixedname_name(&fixedorigin);
+
+ again:
+ 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);
+ return;
+ }
+
+ for (;;) {
+ node = NULL;
+ dns_rbtnodechain_current(&chain, &foundname, origin, &node);
+ tkey = node->data;
+ if (tkey != NULL) {
+ if (tkey->generated
+ && isc_refcount_current(&tkey->refs) == 1
+ && tkey->inception != tkey->expire
+ && tkey->expire < now) {
+ tsig_log(tkey, 2, "tsig expire: deleting");
+ /* delete the key */
+ dns_rbtnodechain_invalidate(&chain);
+ (void)dns_rbt_deletename(ring->keys,
+ &tkey->name,
+ ISC_FALSE);
+ goto again;
+ }
+ }
+ result = dns_rbtnodechain_next(&chain, &foundname,
+ origin);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
+ dns_rbtnodechain_invalidate(&chain);
+ return;
+ }
+
+ }
+}
+
+isc_result_t
+dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
+ unsigned char *secret, int length, isc_boolean_t generated,
+ dns_name_t *creator, isc_stdtime_t inception,
+ isc_stdtime_t expire, isc_mem_t *mctx,
+ dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
+{
+ dst_key_t *dstkey = NULL;
+ isc_result_t result;
+
+ REQUIRE(length >= 0);
+ if (length > 0)
+ REQUIRE(secret != NULL);
+
+ if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACMD5,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACSHA1,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACSHA224,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACSHA256,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACSHA384,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
+ if (secret != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, secret, length);
+ isc_buffer_add(&b, length);
+ result = dst_key_frombuffer(name, DST_ALG_HMACSHA512,
+ DNS_KEYOWNER_ENTITY,
+ DNS_KEYPROTO_DNSSEC,
+ dns_rdataclass_in,
+ &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ } else if (length > 0)
+ return (DNS_R_BADALG);
+
+ result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
+ generated, creator,
+ inception, expire, mctx, ring, key);
+ if (result != ISC_R_SUCCESS && dstkey != NULL)
+ dst_key_free(&dstkey);
+ return (result);
+}
+
+void
+dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
+ REQUIRE(VALID_TSIG_KEY(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ isc_refcount_increment(&source->refs, NULL);
+ *targetp = source;
+}
+
+static void
+tsigkey_free(dns_tsigkey_t *key) {
+ REQUIRE(VALID_TSIG_KEY(key));
+
+ key->magic = 0;
+ dns_name_free(&key->name, key->mctx);
+ if (algname_is_allocated(key->algorithm)) {
+ dns_name_free(key->algorithm, key->mctx);
+ isc_mem_put(key->mctx, key->algorithm, sizeof(dns_name_t));
+ }
+ if (key->key != NULL)
+ dst_key_free(&key->key);
+ if (key->creator != NULL) {
+ dns_name_free(key->creator, key->mctx);
+ isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
+ }
+ isc_refcount_destroy(&key->refs);
+ isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
+}
+
+void
+dns_tsigkey_detach(dns_tsigkey_t **keyp) {
+ dns_tsigkey_t *key;
+ unsigned int refs;
+
+ REQUIRE(keyp != NULL);
+ REQUIRE(VALID_TSIG_KEY(*keyp));
+
+ key = *keyp;
+ isc_refcount_decrement(&key->refs, &refs);
+
+ if (refs == 0)
+ tsigkey_free(key);
+
+ *keyp = NULL;
+}
+
+void
+dns_tsigkey_setdeleted(dns_tsigkey_t *key) {
+ REQUIRE(VALID_TSIG_KEY(key));
+ REQUIRE(key->ring != NULL);
+
+ RWLOCK(&key->ring->lock, isc_rwlocktype_write);
+ (void)dns_rbt_deletename(key->ring->keys, &key->name, ISC_FALSE);
+ RWUNLOCK(&key->ring->lock, isc_rwlocktype_write);
+}
+
+isc_result_t
+dns_tsig_sign(dns_message_t *msg) {
+ dns_tsigkey_t *key;
+ dns_rdata_any_tsig_t tsig, querytsig;
+ unsigned char data[128];
+ isc_buffer_t databuf, sigbuf;
+ isc_buffer_t *dynbuf;
+ dns_name_t *owner;
+ dns_rdata_t *rdata = NULL;
+ dns_rdatalist_t *datalist;
+ dns_rdataset_t *dataset;
+ isc_region_t r;
+ isc_stdtime_t now;
+ isc_mem_t *mctx;
+ dst_context_t *ctx = NULL;
+ isc_result_t ret;
+ unsigned char badtimedata[BADTIMELEN];
+ unsigned int sigsize = 0;
+
+ REQUIRE(msg != NULL);
+ REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg)));
+
+ /*
+ * If this is a response, there should be a query tsig.
+ */
+ if (is_response(msg) && msg->querytsig == NULL)
+ return (DNS_R_EXPECTEDTSIG);
+
+ dynbuf = NULL;
+
+ mctx = msg->mctx;
+ key = dns_message_gettsigkey(msg);
+
+ tsig.mctx = mctx;
+ tsig.common.rdclass = dns_rdataclass_any;
+ tsig.common.rdtype = dns_rdatatype_tsig;
+ ISC_LINK_INIT(&tsig.common, link);
+ dns_name_init(&tsig.algorithm, NULL);
+ dns_name_clone(key->algorithm, &tsig.algorithm);
+
+ isc_stdtime_get(&now);
+ tsig.timesigned = now + msg->timeadjust;
+ tsig.fudge = DNS_TSIG_FUDGE;
+
+ tsig.originalid = msg->id;
+
+ isc_buffer_init(&databuf, data, sizeof(data));
+
+ if (is_response(msg))
+ tsig.error = msg->querytsigstatus;
+ else
+ tsig.error = dns_rcode_noerror;
+
+ if (tsig.error != dns_tsigerror_badtime) {
+ tsig.otherlen = 0;
+ tsig.other = NULL;
+ } else {
+ isc_buffer_t otherbuf;
+
+ tsig.otherlen = BADTIMELEN;
+ tsig.other = badtimedata;
+ isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
+ isc_buffer_putuint48(&otherbuf, tsig.timesigned);
+ }
+
+ if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
+ unsigned char header[DNS_MESSAGE_HEADERLEN];
+ isc_buffer_t headerbuf;
+ isc_uint16_t digestbits;
+
+ ret = dst_context_create(key->key, mctx, &ctx);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ /*
+ * If this is a response, digest the query signature.
+ */
+ if (is_response(msg)) {
+ dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
+
+ ret = dns_rdataset_first(msg->querytsig);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+ dns_rdataset_current(msg->querytsig, &querytsigrdata);
+ ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
+ NULL);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+ isc_buffer_putuint16(&databuf, querytsig.siglen);
+ if (isc_buffer_availablelength(&databuf) <
+ querytsig.siglen) {
+ ret = ISC_R_NOSPACE;
+ goto cleanup_context;
+ }
+ isc_buffer_putmem(&databuf, querytsig.signature,
+ querytsig.siglen);
+ isc_buffer_usedregion(&databuf, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+ }
+
+ /*
+ * Digest the header.
+ */
+ isc_buffer_init(&headerbuf, header, sizeof(header));
+ dns_message_renderheader(msg, &headerbuf);
+ isc_buffer_usedregion(&headerbuf, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ /*
+ * Digest the remainder of the message.
+ */
+ isc_buffer_usedregion(msg->buffer, &r);
+ isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ if (msg->tcp_continuation == 0) {
+ /*
+ * Digest the name, class, ttl, alg.
+ */
+ dns_name_toregion(&key->name, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ isc_buffer_clear(&databuf);
+ isc_buffer_putuint16(&databuf, dns_rdataclass_any);
+ isc_buffer_putuint32(&databuf, 0); /* ttl */
+ isc_buffer_usedregion(&databuf, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ dns_name_toregion(&tsig.algorithm, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ }
+ /* Digest the timesigned and fudge */
+ isc_buffer_clear(&databuf);
+ if (tsig.error == dns_tsigerror_badtime)
+ tsig.timesigned = querytsig.timesigned;
+ isc_buffer_putuint48(&databuf, tsig.timesigned);
+ isc_buffer_putuint16(&databuf, tsig.fudge);
+ isc_buffer_usedregion(&databuf, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ if (msg->tcp_continuation == 0) {
+ /*
+ * Digest the error and other data length.
+ */
+ isc_buffer_clear(&databuf);
+ isc_buffer_putuint16(&databuf, tsig.error);
+ isc_buffer_putuint16(&databuf, tsig.otherlen);
+
+ isc_buffer_usedregion(&databuf, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ /*
+ * Digest the error and other data.
+ */
+ if (tsig.otherlen > 0) {
+ r.length = tsig.otherlen;
+ r.base = tsig.other;
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+ }
+ }
+
+ ret = dst_key_sigsize(key->key, &sigsize);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+ tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
+ if (tsig.signature == NULL) {
+ ret = ISC_R_NOMEMORY;
+ goto cleanup_context;
+ }
+
+ isc_buffer_init(&sigbuf, tsig.signature, sigsize);
+ ret = dst_context_sign(ctx, &sigbuf);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_signature;
+ dst_context_destroy(&ctx);
+ digestbits = dst_key_getbits(key->key);
+ if (digestbits != 0) {
+ unsigned int bytes = (digestbits + 1) / 8;
+ if (is_response(msg) && bytes < querytsig.siglen)
+ bytes = querytsig.siglen;
+ if (bytes > isc_buffer_usedlength(&sigbuf))
+ bytes = isc_buffer_usedlength(&sigbuf);
+ tsig.siglen = bytes;
+ } else
+ tsig.siglen = isc_buffer_usedlength(&sigbuf);
+ } else {
+ tsig.siglen = 0;
+ tsig.signature = NULL;
+ }
+
+ ret = dns_message_gettemprdata(msg, &rdata);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_signature;
+ ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_rdata;
+ ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any,
+ dns_rdatatype_tsig, &tsig, dynbuf);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_dynbuf;
+
+ dns_message_takebuffer(msg, &dynbuf);
+
+ if (tsig.signature != NULL) {
+ isc_mem_put(mctx, tsig.signature, sigsize);
+ tsig.signature = NULL;
+ }
+
+ owner = NULL;
+ ret = dns_message_gettempname(msg, &owner);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_rdata;
+ dns_name_init(owner, NULL);
+ ret = dns_name_dup(&key->name, msg->mctx, owner);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_owner;
+
+ datalist = NULL;
+ ret = dns_message_gettemprdatalist(msg, &datalist);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_owner;
+ dataset = NULL;
+ ret = dns_message_gettemprdataset(msg, &dataset);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_rdatalist;
+ datalist->rdclass = dns_rdataclass_any;
+ datalist->type = dns_rdatatype_tsig;
+ datalist->covers = 0;
+ datalist->ttl = 0;
+ ISC_LIST_INIT(datalist->rdata);
+ ISC_LIST_APPEND(datalist->rdata, rdata, link);
+ dns_rdataset_init(dataset);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
+ == ISC_R_SUCCESS);
+ msg->tsig = dataset;
+ msg->tsigname = owner;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_rdatalist:
+ dns_message_puttemprdatalist(msg, &datalist);
+ cleanup_owner:
+ dns_message_puttempname(msg, &owner);
+ goto cleanup_rdata;
+ cleanup_dynbuf:
+ isc_buffer_free(&dynbuf);
+ cleanup_rdata:
+ dns_message_puttemprdata(msg, &rdata);
+ cleanup_signature:
+ if (tsig.signature != NULL)
+ isc_mem_put(mctx, tsig.signature, sigsize);
+ cleanup_context:
+ if (ctx != NULL)
+ dst_context_destroy(&ctx);
+ return (ret);
+}
+
+isc_result_t
+dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
+ dns_tsig_keyring_t *ring1, dns_tsig_keyring_t *ring2)
+{
+ dns_rdata_any_tsig_t tsig, querytsig;
+ isc_region_t r, source_r, header_r, sig_r;
+ isc_buffer_t databuf;
+ unsigned char data[32];
+ dns_name_t *keyname;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_stdtime_t now;
+ isc_result_t ret;
+ dns_tsigkey_t *tsigkey;
+ dst_key_t *key = NULL;
+ unsigned char header[DNS_MESSAGE_HEADERLEN];
+ dst_context_t *ctx = NULL;
+ isc_mem_t *mctx;
+ isc_uint16_t addcount, id;
+ unsigned int siglen;
+ unsigned int alg;
+
+ REQUIRE(source != NULL);
+ REQUIRE(DNS_MESSAGE_VALID(msg));
+ tsigkey = dns_message_gettsigkey(msg);
+
+ REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
+
+ msg->verify_attempted = 1;
+
+ if (msg->tcp_continuation) {
+ if (tsigkey == NULL || msg->querytsig == NULL)
+ return (DNS_R_UNEXPECTEDTSIG);
+ return (tsig_verify_tcp(source, msg));
+ }
+
+ /*
+ * There should be a TSIG record...
+ */
+ if (msg->tsig == NULL)
+ return (DNS_R_EXPECTEDTSIG);
+
+ /*
+ * If this is a response and there's no key or query TSIG, there
+ * shouldn't be one on the response.
+ */
+ if (is_response(msg) &&
+ (tsigkey == NULL || msg->querytsig == NULL))
+ return (DNS_R_UNEXPECTEDTSIG);
+
+ mctx = msg->mctx;
+
+ /*
+ * If we're here, we know the message is well formed and contains a
+ * TSIG record.
+ */
+
+ keyname = msg->tsigname;
+ ret = dns_rdataset_first(msg->tsig);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ dns_rdataset_current(msg->tsig, &rdata);
+ ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ dns_rdata_reset(&rdata);
+ if (is_response(msg)) {
+ ret = dns_rdataset_first(msg->querytsig);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ dns_rdataset_current(msg->querytsig, &rdata);
+ ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ }
+
+ /*
+ * Do the key name and algorithm match that of the query?
+ */
+ if (is_response(msg) &&
+ (!dns_name_equal(keyname, &tsigkey->name) ||
+ !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
+ msg->tsigstatus = dns_tsigerror_badkey;
+ tsig_log(msg->tsigkey, 2,
+ "key name and algorithm do not match");
+ return (DNS_R_TSIGVERIFYFAILURE);
+ }
+
+ /*
+ * Get the current time.
+ */
+ isc_stdtime_get(&now);
+
+ /*
+ * Find dns_tsigkey_t based on keyname.
+ */
+ if (tsigkey == NULL) {
+ ret = ISC_R_NOTFOUND;
+ if (ring1 != NULL)
+ ret = dns_tsigkey_find(&tsigkey, keyname,
+ &tsig.algorithm, ring1);
+ if (ret == ISC_R_NOTFOUND && ring2 != NULL)
+ ret = dns_tsigkey_find(&tsigkey, keyname,
+ &tsig.algorithm, ring2);
+ if (ret != ISC_R_SUCCESS) {
+ msg->tsigstatus = dns_tsigerror_badkey;
+ ret = dns_tsigkey_create(keyname, &tsig.algorithm,
+ NULL, 0, ISC_FALSE, NULL,
+ now, now,
+ mctx, NULL, &msg->tsigkey);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ tsig_log(msg->tsigkey, 2, "unknown key");
+ return (DNS_R_TSIGVERIFYFAILURE);
+ }
+ msg->tsigkey = tsigkey;
+ }
+
+ key = tsigkey->key;
+
+ /*
+ * Is the time ok?
+ */
+ if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
+ msg->tsigstatus = dns_tsigerror_badtime;
+ tsig_log(msg->tsigkey, 2, "signature has expired");
+ return (DNS_R_CLOCKSKEW);
+ } else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
+ msg->tsigstatus = dns_tsigerror_badtime;
+ tsig_log(msg->tsigkey, 2, "signature is in the future");
+ return (DNS_R_CLOCKSKEW);
+ }
+
+ /*
+ * Check digest length.
+ */
+ alg = dst_key_alg(key);
+ ret = dst_key_sigsize(key, &siglen);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 ||
+ alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
+ alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) {
+ isc_uint16_t digestbits = dst_key_getbits(key);
+ if (tsig.siglen > siglen) {
+ tsig_log(msg->tsigkey, 2, "signature length to big");
+ return (DNS_R_FORMERR);
+ }
+ if (tsig.siglen > 0 &&
+ (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) {
+ tsig_log(msg->tsigkey, 2,
+ "signature length below minimum");
+ return (DNS_R_FORMERR);
+ }
+ if (tsig.siglen > 0 && digestbits != 0 &&
+ tsig.siglen < ((digestbits + 1) / 8)) {
+ msg->tsigstatus = dns_tsigerror_badtrunc;
+ tsig_log(msg->tsigkey, 2,
+ "truncated signature length too small");
+ return (DNS_R_TSIGVERIFYFAILURE);
+ }
+ if (tsig.siglen > 0 && digestbits == 0 &&
+ tsig.siglen < siglen) {
+ msg->tsigstatus = dns_tsigerror_badtrunc;
+ tsig_log(msg->tsigkey, 2, "signature length too small");
+ return (DNS_R_TSIGVERIFYFAILURE);
+ }
+ }
+
+ if (tsig.siglen > 0) {
+ sig_r.base = tsig.signature;
+ sig_r.length = tsig.siglen;
+
+ ret = dst_context_create(key, mctx, &ctx);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+
+ if (is_response(msg)) {
+ isc_buffer_init(&databuf, data, sizeof(data));
+ isc_buffer_putuint16(&databuf, querytsig.siglen);
+ isc_buffer_usedregion(&databuf, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+ if (querytsig.siglen > 0) {
+ r.length = querytsig.siglen;
+ r.base = querytsig.signature;
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+ }
+ }
+
+ /*
+ * Extract the header.
+ */
+ isc_buffer_usedregion(source, &r);
+ memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
+ isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
+
+ /*
+ * Decrement the additional field counter.
+ */
+ memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
+ addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
+ memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
+
+ /*
+ * Put in the original id.
+ */
+ id = htons(tsig.originalid);
+ memcpy(&header[0], &id, 2);
+
+ /*
+ * Digest the modified header.
+ */
+ header_r.base = (unsigned char *) header;
+ header_r.length = DNS_MESSAGE_HEADERLEN;
+ ret = dst_context_adddata(ctx, &header_r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ /*
+ * Digest all non-TSIG records.
+ */
+ isc_buffer_usedregion(source, &source_r);
+ r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
+ r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ /*
+ * Digest the key name.
+ */
+ dns_name_toregion(&tsigkey->name, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ isc_buffer_init(&databuf, data, sizeof(data));
+ isc_buffer_putuint16(&databuf, tsig.common.rdclass);
+ isc_buffer_putuint32(&databuf, msg->tsig->ttl);
+ isc_buffer_usedregion(&databuf, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ /*
+ * Digest the key algorithm.
+ */
+ dns_name_toregion(tsigkey->algorithm, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ isc_buffer_clear(&databuf);
+ isc_buffer_putuint48(&databuf, tsig.timesigned);
+ isc_buffer_putuint16(&databuf, tsig.fudge);
+ isc_buffer_putuint16(&databuf, tsig.error);
+ isc_buffer_putuint16(&databuf, tsig.otherlen);
+ isc_buffer_usedregion(&databuf, &r);
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ if (tsig.otherlen > 0) {
+ r.base = tsig.other;
+ r.length = tsig.otherlen;
+ ret = dst_context_adddata(ctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+ }
+
+ ret = dst_context_verify(ctx, &sig_r);
+ if (ret == DST_R_VERIFYFAILURE) {
+ msg->tsigstatus = dns_tsigerror_badsig;
+ ret = DNS_R_TSIGVERIFYFAILURE;
+ tsig_log(msg->tsigkey, 2,
+ "signature failed to verify(1)");
+ goto cleanup_context;
+ } else if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ dst_context_destroy(&ctx);
+ } else if (tsig.error != dns_tsigerror_badsig &&
+ tsig.error != dns_tsigerror_badkey) {
+ msg->tsigstatus = dns_tsigerror_badsig;
+ tsig_log(msg->tsigkey, 2, "signature was empty");
+ return (DNS_R_TSIGVERIFYFAILURE);
+ }
+
+ msg->tsigstatus = dns_rcode_noerror;
+
+ if (tsig.error != dns_rcode_noerror) {
+ if (tsig.error == dns_tsigerror_badtime)
+ return (DNS_R_CLOCKSKEW);
+ else
+ return (DNS_R_TSIGERRORSET);
+ }
+
+ msg->verified_sig = 1;
+
+ return (ISC_R_SUCCESS);
+
+cleanup_context:
+ if (ctx != NULL)
+ dst_context_destroy(&ctx);
+
+ return (ret);
+}
+
+static isc_result_t
+tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
+ dns_rdata_any_tsig_t tsig, querytsig;
+ isc_region_t r, source_r, header_r, sig_r;
+ isc_buffer_t databuf;
+ unsigned char data[32];
+ dns_name_t *keyname;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_stdtime_t now;
+ isc_result_t ret;
+ dns_tsigkey_t *tsigkey;
+ dst_key_t *key = NULL;
+ unsigned char header[DNS_MESSAGE_HEADERLEN];
+ isc_uint16_t addcount, id;
+ isc_boolean_t has_tsig = ISC_FALSE;
+ isc_mem_t *mctx;
+
+ REQUIRE(source != NULL);
+ REQUIRE(msg != NULL);
+ REQUIRE(dns_message_gettsigkey(msg) != NULL);
+ REQUIRE(msg->tcp_continuation == 1);
+ REQUIRE(msg->querytsig != NULL);
+
+ if (!is_response(msg))
+ return (DNS_R_EXPECTEDRESPONSE);
+
+ mctx = msg->mctx;
+
+ tsigkey = dns_message_gettsigkey(msg);
+
+ /*
+ * Extract and parse the previous TSIG
+ */
+ ret = dns_rdataset_first(msg->querytsig);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ dns_rdataset_current(msg->querytsig, &rdata);
+ ret = dns_rdata_tostruct(&rdata, &querytsig, NULL);
+ if (ret != ISC_R_SUCCESS)
+ return (ret);
+ dns_rdata_reset(&rdata);
+
+ /*
+ * If there is a TSIG in this message, do some checks.
+ */
+ if (msg->tsig != NULL) {
+ has_tsig = ISC_TRUE;
+
+ keyname = msg->tsigname;
+ ret = dns_rdataset_first(msg->tsig);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_querystruct;
+ dns_rdataset_current(msg->tsig, &rdata);
+ ret = dns_rdata_tostruct(&rdata, &tsig, NULL);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_querystruct;
+
+ /*
+ * Do the key name and algorithm match that of the query?
+ */
+ if (!dns_name_equal(keyname, &tsigkey->name) ||
+ !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) {
+ msg->tsigstatus = dns_tsigerror_badkey;
+ ret = DNS_R_TSIGVERIFYFAILURE;
+ tsig_log(msg->tsigkey, 2,
+ "key name and algorithm do not match");
+ goto cleanup_querystruct;
+ }
+
+ /*
+ * Is the time ok?
+ */
+ isc_stdtime_get(&now);
+
+ if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
+ msg->tsigstatus = dns_tsigerror_badtime;
+ tsig_log(msg->tsigkey, 2, "signature has expired");
+ ret = DNS_R_CLOCKSKEW;
+ goto cleanup_querystruct;
+ } else if (now + msg->timeadjust <
+ tsig.timesigned - tsig.fudge) {
+ msg->tsigstatus = dns_tsigerror_badtime;
+ tsig_log(msg->tsigkey, 2,
+ "signature is in the future");
+ ret = DNS_R_CLOCKSKEW;
+ goto cleanup_querystruct;
+ }
+ }
+
+ key = tsigkey->key;
+
+ if (msg->tsigctx == NULL) {
+ ret = dst_context_create(key, mctx, &msg->tsigctx);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_querystruct;
+
+ /*
+ * Digest the length of the query signature
+ */
+ isc_buffer_init(&databuf, data, sizeof(data));
+ isc_buffer_putuint16(&databuf, querytsig.siglen);
+ isc_buffer_usedregion(&databuf, &r);
+ ret = dst_context_adddata(msg->tsigctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ /*
+ * Digest the data of the query signature
+ */
+ if (querytsig.siglen > 0) {
+ r.length = querytsig.siglen;
+ r.base = querytsig.signature;
+ ret = dst_context_adddata(msg->tsigctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+ }
+ }
+
+ /*
+ * Extract the header.
+ */
+ isc_buffer_usedregion(source, &r);
+ memcpy(header, r.base, DNS_MESSAGE_HEADERLEN);
+ isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
+
+ /*
+ * Decrement the additional field counter if necessary.
+ */
+ if (has_tsig) {
+ memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
+ addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
+ memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
+ }
+
+ /*
+ * Put in the original id.
+ */
+ /* XXX Can TCP transfers be forwarded? How would that work? */
+ if (has_tsig) {
+ id = htons(tsig.originalid);
+ memcpy(&header[0], &id, 2);
+ }
+
+ /*
+ * Digest the modified header.
+ */
+ header_r.base = (unsigned char *) header;
+ header_r.length = DNS_MESSAGE_HEADERLEN;
+ ret = dst_context_adddata(msg->tsigctx, &header_r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ /*
+ * Digest all non-TSIG records.
+ */
+ isc_buffer_usedregion(source, &source_r);
+ r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
+ if (has_tsig)
+ r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
+ else
+ r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
+ ret = dst_context_adddata(msg->tsigctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ /*
+ * Digest the time signed and fudge.
+ */
+ if (has_tsig) {
+ isc_buffer_init(&databuf, data, sizeof(data));
+ isc_buffer_putuint48(&databuf, tsig.timesigned);
+ isc_buffer_putuint16(&databuf, tsig.fudge);
+ isc_buffer_usedregion(&databuf, &r);
+ ret = dst_context_adddata(msg->tsigctx, &r);
+ if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ sig_r.base = tsig.signature;
+ sig_r.length = tsig.siglen;
+ if (tsig.siglen == 0) {
+ if (tsig.error != dns_rcode_noerror) {
+ if (tsig.error == dns_tsigerror_badtime)
+ ret = DNS_R_CLOCKSKEW;
+ else
+ ret = DNS_R_TSIGERRORSET;
+ } else {
+ tsig_log(msg->tsigkey, 2,
+ "signature is empty");
+ ret = DNS_R_TSIGVERIFYFAILURE;
+ }
+ goto cleanup_context;
+ }
+
+ ret = dst_context_verify(msg->tsigctx, &sig_r);
+ if (ret == DST_R_VERIFYFAILURE) {
+ msg->tsigstatus = dns_tsigerror_badsig;
+ tsig_log(msg->tsigkey, 2,
+ "signature failed to verify(2)");
+ ret = DNS_R_TSIGVERIFYFAILURE;
+ goto cleanup_context;
+ }
+ else if (ret != ISC_R_SUCCESS)
+ goto cleanup_context;
+
+ dst_context_destroy(&msg->tsigctx);
+ }
+
+ msg->tsigstatus = dns_rcode_noerror;
+ return (ISC_R_SUCCESS);
+
+ cleanup_context:
+ dst_context_destroy(&msg->tsigctx);
+
+ cleanup_querystruct:
+ dns_rdata_freestruct(&querytsig);
+
+ return (ret);
+
+}
+
+isc_result_t
+dns_tsigkey_find(dns_tsigkey_t **tsigkey, dns_name_t *name,
+ dns_name_t *algorithm, dns_tsig_keyring_t *ring)
+{
+ dns_tsigkey_t *key;
+ isc_stdtime_t now;
+ isc_result_t result;
+
+ REQUIRE(tsigkey != NULL);
+ REQUIRE(*tsigkey == NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(ring != NULL);
+
+ RWLOCK(&ring->lock, isc_rwlocktype_write);
+ cleanup_ring(ring);
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+
+ isc_stdtime_get(&now);
+ RWLOCK(&ring->lock, isc_rwlocktype_read);
+ key = NULL;
+ result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
+ if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
+ RWUNLOCK(&ring->lock, isc_rwlocktype_read);
+ return (ISC_R_NOTFOUND);
+ }
+ if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
+ RWUNLOCK(&ring->lock, isc_rwlocktype_read);
+ return (ISC_R_NOTFOUND);
+ }
+ if (key->inception != key->expire && key->expire < now) {
+ /*
+ * The key has expired.
+ */
+ RWUNLOCK(&ring->lock, isc_rwlocktype_read);
+ RWLOCK(&ring->lock, isc_rwlocktype_write);
+ (void)dns_rbt_deletename(ring->keys, name, ISC_FALSE);
+ RWUNLOCK(&ring->lock, isc_rwlocktype_write);
+ return (ISC_R_NOTFOUND);
+ }
+
+ isc_refcount_increment(&key->refs, NULL);
+ RWUNLOCK(&ring->lock, isc_rwlocktype_read);
+ *tsigkey = key;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+free_tsignode(void *node, void *_unused) {
+ dns_tsigkey_t *key;
+
+ UNUSED(_unused);
+
+ REQUIRE(node != NULL);
+
+ key = node;
+ dns_tsigkey_detach(&key);
+}
+
+isc_result_t
+dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
+ isc_result_t result;
+ dns_tsig_keyring_t *ring;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(ringp != NULL);
+ REQUIRE(*ringp == NULL);
+
+ ring = isc_mem_get(mctx, sizeof(dns_tsig_keyring_t));
+ if (ring == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_rwlock_init(&ring->lock, 0, 0);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
+ return (result);
+ }
+
+ ring->keys = NULL;
+ result = dns_rbt_create(mctx, free_tsignode, NULL, &ring->keys);
+ if (result != ISC_R_SUCCESS) {
+ isc_rwlock_destroy(&ring->lock);
+ isc_mem_put(mctx, ring, sizeof(dns_tsig_keyring_t));
+ return (result);
+ }
+
+ ring->writecount = 0;
+ ring->mctx = NULL;
+ isc_mem_attach(mctx, &ring->mctx);
+
+ *ringp = ring;
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp) {
+ dns_tsig_keyring_t *ring;
+
+ REQUIRE(ringp != NULL);
+ REQUIRE(*ringp != NULL);
+
+ 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));
+}
diff --git a/lib/dns/ttl.c b/lib/dns/ttl.c
new file mode 100644
index 0000000..9d0dec5
--- /dev/null
+++ b/lib/dns/ttl.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: ttl.c,v 1.29 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/result.h>
+#include <dns/ttl.h>
+
+#define RETERR(x) do { \
+ isc_result_t _r = (x); \
+ if (_r != ISC_R_SUCCESS) \
+ return (_r); \
+ } while (0)
+
+
+static isc_result_t bind_ttl(isc_textregion_t *source, isc_uint32_t *ttl);
+
+/*
+ * Helper for dns_ttl_totext().
+ */
+static isc_result_t
+ttlfmt(unsigned int t, const char *s, isc_boolean_t verbose,
+ isc_boolean_t space, isc_buffer_t *target)
+{
+ char tmp[60];
+ size_t len;
+ isc_region_t region;
+
+ if (verbose)
+ len = snprintf(tmp, sizeof(tmp), "%s%u %s%s",
+ space ? " " : "",
+ t, s,
+ t == 1 ? "" : "s");
+ else
+ len = snprintf(tmp, sizeof(tmp), "%u%c", t, s[0]);
+
+ INSIST(len + 1 <= sizeof(tmp));
+ isc_buffer_availableregion(target, &region);
+ if (len > region.length)
+ return (ISC_R_NOSPACE);
+ memcpy(region.base, tmp, len);
+ isc_buffer_add(target, len);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Derived from bind8 ns_format_ttl().
+ */
+isc_result_t
+dns_ttl_totext(isc_uint32_t src, isc_boolean_t verbose, isc_buffer_t *target) {
+ unsigned secs, mins, hours, days, weeks, x;
+
+ secs = src % 60; src /= 60;
+ mins = src % 60; src /= 60;
+ hours = src % 24; src /= 24;
+ days = src % 7; src /= 7;
+ weeks = src; src = 0;
+
+ x = 0;
+ if (weeks != 0) {
+ RETERR(ttlfmt(weeks, "week", verbose, ISC_TF(x > 0), target));
+ x++;
+ }
+ if (days != 0) {
+ RETERR(ttlfmt(days, "day", verbose, ISC_TF(x > 0), target));
+ x++;
+ }
+ if (hours != 0) {
+ RETERR(ttlfmt(hours, "hour", verbose, ISC_TF(x > 0), target));
+ x++;
+ }
+ if (mins != 0) {
+ RETERR(ttlfmt(mins, "minute", verbose, ISC_TF(x > 0), target));
+ x++;
+ }
+ if (secs != 0 ||
+ (weeks == 0 && days == 0 && hours == 0 && mins == 0)) {
+ RETERR(ttlfmt(secs, "second", verbose, ISC_TF(x > 0), target));
+ x++;
+ }
+ INSIST (x > 0);
+ /*
+ * If only a single unit letter is printed, print it
+ * in upper case. (Why? Because BIND 8 does that.
+ * Presumably it has a reason.)
+ */
+ if (x == 1 && !verbose) {
+ isc_region_t region;
+ /*
+ * The unit letter is the last character in the
+ * used region of the buffer.
+ *
+ * toupper() does not need its argument to be masked of cast
+ * here because region.base is type unsigned char *.
+ */
+ isc_buffer_usedregion(target, &region);
+ region.base[region.length - 1] =
+ toupper(region.base[region.length - 1]);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_counter_fromtext(isc_textregion_t *source, isc_uint32_t *ttl) {
+ return (bind_ttl(source, ttl));
+}
+
+isc_result_t
+dns_ttl_fromtext(isc_textregion_t *source, isc_uint32_t *ttl) {
+ isc_result_t result;
+
+ result = bind_ttl(source, ttl);
+ if (result != ISC_R_SUCCESS)
+ result = DNS_R_BADTTL;
+ return (result);
+}
+
+static isc_result_t
+bind_ttl(isc_textregion_t *source, isc_uint32_t *ttl) {
+ isc_uint32_t tmp = 0;
+ isc_uint32_t n;
+ char *s;
+ char buf[64];
+ char nbuf[64]; /* Number buffer */
+
+ /*
+ * Copy the buffer as it may not be NULL terminated.
+ * No legal counter / ttl is longer that 63 characters.
+ */
+ if (source->length > sizeof(buf) - 1)
+ return (DNS_R_SYNTAX);
+ strncpy(buf, source->base, source->length);
+ buf[source->length] = '\0';
+ s = buf;
+
+ do {
+ isc_result_t result;
+
+ char *np = nbuf;
+ while (*s != '\0' && isdigit((unsigned char)*s))
+ *np++ = *s++;
+ *np++ = '\0';
+ INSIST(np - nbuf <= (int)sizeof(nbuf));
+ result = isc_parse_uint32(&n, nbuf, 10);
+ if (result != ISC_R_SUCCESS)
+ return (DNS_R_SYNTAX);
+ switch (*s) {
+ case 'w':
+ case 'W':
+ tmp += n * 7 * 24 * 3600;
+ s++;
+ break;
+ case 'd':
+ case 'D':
+ tmp += n * 24 * 3600;
+ s++;
+ break;
+ case 'h':
+ case 'H':
+ tmp += n * 3600;
+ s++;
+ break;
+ case 'm':
+ case 'M':
+ tmp += n * 60;
+ s++;
+ break;
+ case 's':
+ case 'S':
+ tmp += n;
+ s++;
+ break;
+ case '\0':
+ /* Plain number? */
+ if (tmp != 0)
+ return (DNS_R_SYNTAX);
+ tmp = n;
+ break;
+ default:
+ return (DNS_R_SYNTAX);
+ }
+ } while (*s != '\0');
+ *ttl = tmp;
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/dns/validator.c b/lib/dns/validator.c
new file mode 100644
index 0000000..39c17d5
--- /dev/null
+++ b/lib/dns/validator.c
@@ -0,0 +1,3776 @@
+/*
+ * 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
+ * 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: validator.c,v 1.164 2008/11/14 23:47:33 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/base32.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/sha2.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/ds.h>
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/keytable.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/ncache.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
+#include <dns/rdata.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/validator.h>
+#include <dns/view.h>
+
+/*! \file
+ * \brief
+ * Basic processing sequences.
+ *
+ * \li When called with rdataset and sigrdataset:
+ * validator_start -> validate -> proveunsecure -> startfinddlvsep ->
+ * dlv_validator_start -> validator_start -> validate -> proveunsecure
+ *
+ * validator_start -> validate -> nsecvalidate (secure wildcard answer)
+ *
+ * \li When called with rdataset, sigrdataset and with DNS_VALIDATOR_DLV:
+ * validator_start -> startfinddlvsep -> dlv_validator_start ->
+ * validator_start -> validate -> proveunsecure
+ *
+ * \li When called with rdataset:
+ * validator_start -> proveunsecure -> startfinddlvsep ->
+ * dlv_validator_start -> validator_start -> proveunsecure
+ *
+ * \li When called with rdataset and with DNS_VALIDATOR_DLV:
+ * validator_start -> startfinddlvsep -> dlv_validator_start ->
+ * validator_start -> proveunsecure
+ *
+ * \li When called without a rdataset:
+ * validator_start -> nsecvalidate -> proveunsecure -> startfinddlvsep ->
+ * dlv_validator_start -> validator_start -> nsecvalidate -> proveunsecure
+ *
+ * Note: there isn't a case for DNS_VALIDATOR_DLV here as we want nsecvalidate()
+ * to always validate the authority section even when it does not contain
+ * signatures.
+ *
+ * validator_start: determines what type of validation to do.
+ * validate: attempts to perform a positive validation.
+ * proveunsecure: attempts to prove the answer comes from a unsecure zone.
+ * nsecvalidate: attempts to prove a negative response.
+ * startfinddlvsep: starts the DLV record lookup.
+ * dlv_validator_start: resets state and restarts the lookup using the
+ * DLV RRset found by startfinddlvsep.
+ */
+
+#define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?')
+#define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC)
+
+#define VALATTR_SHUTDOWN 0x0001 /*%< Shutting down. */
+#define VALATTR_CANCELED 0x0002 /*%< Cancelled. */
+#define VALATTR_TRIEDVERIFY 0x0004 /*%< We have found a key and
+ * have attempted a verify. */
+#define VALATTR_INSECURITY 0x0010 /*%< Attempting proveunsecure. */
+#define VALATTR_DLVTRIED 0x0020 /*%< Looked for a DLV record. */
+
+/*!
+ * NSEC proofs to be looked for.
+ */
+#define VALATTR_NEEDNOQNAME 0x00000100
+#define VALATTR_NEEDNOWILDCARD 0x00000200
+#define VALATTR_NEEDNODATA 0x00000400
+
+/*!
+ * NSEC proofs that have been found.
+ */
+#define VALATTR_FOUNDNOQNAME 0x00001000
+#define VALATTR_FOUNDNOWILDCARD 0x00002000
+#define VALATTR_FOUNDNODATA 0x00004000
+#define VALATTR_FOUNDCLOSEST 0x00008000
+
+/*
+ *
+ */
+#define VALATTR_FOUNDOPTOUT 0x00010000
+#define VALATTR_FOUNDUNKNOWN 0x00020000
+
+#define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0)
+#define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0)
+#define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0)
+#define DLVTRIED(val) ((val->attributes & VALATTR_DLVTRIED) != 0)
+
+#define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0)
+#define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0)
+
+static void
+destroy(dns_validator_t *val);
+
+static isc_result_t
+get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
+ dns_rdataset_t *rdataset);
+
+static isc_result_t
+validate(dns_validator_t *val, isc_boolean_t resume);
+
+static isc_result_t
+validatezonekey(dns_validator_t *val);
+
+static isc_result_t
+nsecvalidate(dns_validator_t *val, isc_boolean_t resume);
+
+static isc_result_t
+proveunsecure(dns_validator_t *val, isc_boolean_t have_ds,
+ isc_boolean_t resume);
+
+static void
+validator_logv(dns_validator_t *val, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *fmt, va_list ap)
+ ISC_FORMAT_PRINTF(5, 0);
+
+static void
+validator_log(dns_validator_t *val, int level, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+static void
+validator_logcreate(dns_validator_t *val,
+ dns_name_t *name, dns_rdatatype_t type,
+ const char *caller, const char *operation);
+
+static isc_result_t
+dlv_validatezonekey(dns_validator_t *val);
+
+static void
+dlv_validator_start(dns_validator_t *val);
+
+static isc_result_t
+finddlvsep(dns_validator_t *val, isc_boolean_t resume);
+
+static isc_result_t
+startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure);
+
+/*%
+ * Mark the RRsets as a answer.
+ */
+static inline void
+markanswer(dns_validator_t *val) {
+ validator_log(val, ISC_LOG_DEBUG(3), "marking as answer");
+ if (val->event->rdataset != NULL)
+ val->event->rdataset->trust = dns_trust_answer;
+ if (val->event->sigrdataset != NULL)
+ val->event->sigrdataset->trust = dns_trust_answer;
+}
+
+static void
+validator_done(dns_validator_t *val, isc_result_t result) {
+ isc_task_t *task;
+
+ if (val->event == NULL)
+ return;
+
+ /*
+ * Caller must be holding the lock.
+ */
+
+ val->event->result = result;
+ task = val->event->ev_sender;
+ val->event->ev_sender = val;
+ val->event->ev_type = DNS_EVENT_VALIDATORDONE;
+ val->event->ev_action = val->action;
+ val->event->ev_arg = val->arg;
+ isc_task_sendanddetach(&task, (isc_event_t **)&val->event);
+}
+
+static inline isc_boolean_t
+exit_check(dns_validator_t *val) {
+ /*
+ * Caller must be holding the lock.
+ */
+ if (!SHUTDOWN(val))
+ return (ISC_FALSE);
+
+ INSIST(val->event == NULL);
+
+ if (val->fetch != NULL || val->subvalidator != NULL)
+ return (ISC_FALSE);
+
+ return (ISC_TRUE);
+}
+
+/*%
+ * Look in the NSEC record returned from a DS query to see if there is
+ * a NS RRset at this name. If it is found we are at a delegation point.
+ */
+static isc_boolean_t
+isdelegation(dns_name_t *name, dns_rdataset_t *rdataset,
+ isc_result_t dbresult)
+{
+ dns_label_t hashlabel;
+ dns_name_t nsec3name;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t set;
+ int order;
+ int scope;
+ isc_boolean_t found;
+ isc_buffer_t buffer;
+ isc_result_t result;
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char owner[NSEC3_MAX_HASH_LENGTH];
+ unsigned int length;
+
+ REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET);
+
+ dns_rdataset_init(&set);
+ if (dbresult == DNS_R_NXRRSET)
+ dns_rdataset_clone(rdataset, &set);
+ else {
+ result = dns_ncache_getrdataset(rdataset, name,
+ dns_rdatatype_nsec, &set);
+ if (result == ISC_R_NOTFOUND)
+ goto trynsec3;
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+ }
+
+ INSIST(set.type == dns_rdatatype_nsec);
+
+ found = ISC_FALSE;
+ result = dns_rdataset_first(&set);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&set, &rdata);
+ found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&set);
+ return (found);
+
+ trynsec3:
+ /*
+ * Iterate over the ncache entry.
+ */
+ found = ISC_FALSE;
+ dns_name_init(&nsec3name, NULL);
+ result = dns_rdataset_first(rdataset);
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ dns_ncache_current(rdataset, &nsec3name, &set);
+ if (set.type != dns_rdatatype_nsec3) {
+ dns_rdataset_disassociate(&set);
+ continue;
+ }
+ dns_name_getlabel(&nsec3name, 0, &hashlabel);
+ isc_region_consume(&hashlabel, 1);
+ isc_buffer_init(&buffer, owner, sizeof(owner));
+ result = isc_base32hex_decoderegion(&hashlabel, &buffer);
+ if (result != ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&set);
+ continue;
+ }
+ for (result = dns_rdataset_first(&set);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&set))
+ {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&set, &rdata);
+ (void)dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ if (nsec3.hash != 1)
+ continue;
+ length = isc_iterated_hash(hash, nsec3.hash,
+ nsec3.iterations, nsec3.salt,
+ nsec3.salt_length,
+ name->ndata, name->length);
+ if (length != isc_buffer_usedlength(&buffer))
+ continue;
+ order = memcmp(hash, owner, length);
+ if (order == 0) {
+ found = dns_nsec3_typepresent(&rdata,
+ dns_rdatatype_ns);
+ dns_rdataset_disassociate(&set);
+ return (found);
+ }
+ if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0)
+ continue;
+ /*
+ * Does this optout span cover the name?
+ */
+ scope = memcmp(owner, nsec3.next, nsec3.next_length);
+ if ((scope < 0 && order > 0 &&
+ memcmp(hash, nsec3.next, length) < 0) ||
+ (scope >= 0 && (order > 0 ||
+ memcmp(hash, nsec3.next, length) < 0)))
+ {
+ dns_rdataset_disassociate(&set);
+ return (ISC_TRUE);
+ }
+ }
+ dns_rdataset_disassociate(&set);
+ }
+ return (found);
+}
+
+/*%
+ * We have been asked to to look for a key.
+ * If found resume the validation process.
+ * If not found fail the validation process.
+ */
+static void
+fetch_callback_validator(isc_task_t *task, isc_event_t *event) {
+ dns_fetchevent_t *devent;
+ dns_validator_t *val;
+ dns_rdataset_t *rdataset;
+ isc_boolean_t want_destroy;
+ isc_result_t result;
+ isc_result_t eresult;
+
+ UNUSED(task);
+ INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
+ devent = (dns_fetchevent_t *)event;
+ val = devent->ev_arg;
+ rdataset = &val->frdataset;
+ 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);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ isc_event_free(&event);
+ dns_resolver_destroyfetch(&val->fetch);
+
+ INSIST(val->event != NULL);
+
+ validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_validator");
+ LOCK(&val->lock);
+ if (CANCELED(val)) {
+ validator_done(val, ISC_R_CANCELED);
+ } else if (eresult == ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "keyset with trust %d", rdataset->trust);
+ /*
+ * Only extract the dst key if the keyset is secure.
+ */
+ if (rdataset->trust >= dns_trust_secure) {
+ result = get_dst_key(val, val->siginfo, rdataset);
+ if (result == ISC_R_SUCCESS)
+ val->keyset = &val->frdataset;
+ }
+ result = validate(val, ISC_TRUE);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ } else {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "fetch_callback_validator: got %s",
+ isc_result_totext(eresult));
+ if (eresult == ISC_R_CANCELED)
+ validator_done(val, eresult);
+ else
+ validator_done(val, DNS_R_NOVALIDKEY);
+ }
+ want_destroy = exit_check(val);
+ UNLOCK(&val->lock);
+ if (want_destroy)
+ destroy(val);
+}
+
+/*%
+ * We were asked to look for a DS record as part of following a key chain
+ * upwards. If found resume the validation process. If not found fail the
+ * validation process.
+ */
+static void
+dsfetched(isc_task_t *task, isc_event_t *event) {
+ dns_fetchevent_t *devent;
+ dns_validator_t *val;
+ dns_rdataset_t *rdataset;
+ isc_boolean_t want_destroy;
+ isc_result_t result;
+ isc_result_t eresult;
+
+ UNUSED(task);
+ INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
+ devent = (dns_fetchevent_t *)event;
+ val = devent->ev_arg;
+ rdataset = &val->frdataset;
+ 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);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ isc_event_free(&event);
+ dns_resolver_destroyfetch(&val->fetch);
+
+ INSIST(val->event != NULL);
+
+ validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched");
+ LOCK(&val->lock);
+ if (CANCELED(val)) {
+ validator_done(val, ISC_R_CANCELED);
+ } else if (eresult == ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "dsset with trust %d", rdataset->trust);
+ val->dsset = &val->frdataset;
+ result = validatezonekey(val);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ } else if (eresult == DNS_R_NXRRSET ||
+ eresult == DNS_R_NCACHENXRRSET ||
+ eresult == DNS_R_SERVFAIL) /* RFC 1034 parent? */
+ {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "falling back to insecurity proof (%s)",
+ dns_result_totext(eresult));
+ val->attributes |= VALATTR_INSECURITY;
+ result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ } else {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "dsfetched: got %s",
+ isc_result_totext(eresult));
+ if (eresult == ISC_R_CANCELED)
+ validator_done(val, eresult);
+ else
+ validator_done(val, DNS_R_NOVALIDDS);
+ }
+ want_destroy = exit_check(val);
+ UNLOCK(&val->lock);
+ if (want_destroy)
+ destroy(val);
+}
+
+/*%
+ * We were asked to look for the DS record as part of proving that a
+ * name is unsecure.
+ *
+ * If the DS record doesn't exist and the query name corresponds to
+ * a delegation point we are transitioning from a secure zone to a
+ * unsecure zone.
+ *
+ * If the DS record exists it will be secure. We can continue looking
+ * for the break point in the chain of trust.
+ */
+static void
+dsfetched2(isc_task_t *task, isc_event_t *event) {
+ dns_fetchevent_t *devent;
+ dns_validator_t *val;
+ dns_name_t *tname;
+ isc_boolean_t want_destroy;
+ isc_result_t result;
+ isc_result_t eresult;
+
+ UNUSED(task);
+ INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
+ devent = (dns_fetchevent_t *)event;
+ val = devent->ev_arg;
+ 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);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ dns_resolver_destroyfetch(&val->fetch);
+
+ INSIST(val->event != NULL);
+
+ validator_log(val, ISC_LOG_DEBUG(3), "in dsfetched2: %s",
+ dns_result_totext(eresult));
+ LOCK(&val->lock);
+ if (CANCELED(val)) {
+ validator_done(val, ISC_R_CANCELED);
+ } else if (eresult == DNS_R_NXRRSET || eresult == DNS_R_NCACHENXRRSET) {
+ /*
+ * There is no DS. If this is a delegation, we're done.
+ */
+ tname = dns_fixedname_name(&devent->foundname);
+ if (isdelegation(tname, &val->frdataset, eresult)) {
+ if (val->mustbesecure) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure");
+ validator_done(val, DNS_R_MUSTBESECURE);
+ } else if (val->view->dlv == NULL || DLVTRIED(val)) {
+ markanswer(val);
+ validator_done(val, ISC_R_SUCCESS);
+ } else {
+ result = startfinddlvsep(val, tname);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ }
+ } else {
+ result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ }
+ } else if (eresult == ISC_R_SUCCESS ||
+ eresult == DNS_R_NXDOMAIN ||
+ eresult == DNS_R_NCACHENXDOMAIN)
+ {
+ /*
+ * There is a DS which may or may not be a zone cut.
+ * In either case we are still in a secure zone resume
+ * validation.
+ */
+ result = proveunsecure(val, ISC_TF(eresult == ISC_R_SUCCESS),
+ ISC_TRUE);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ } else {
+ if (eresult == ISC_R_CANCELED)
+ validator_done(val, eresult);
+ else
+ validator_done(val, DNS_R_NOVALIDDS);
+ }
+ isc_event_free(&event);
+ want_destroy = exit_check(val);
+ UNLOCK(&val->lock);
+ if (want_destroy)
+ destroy(val);
+}
+
+/*%
+ * Callback from when a DNSKEY RRset has been validated.
+ *
+ * Resumes the stalled validation process.
+ */
+static void
+keyvalidated(isc_task_t *task, isc_event_t *event) {
+ dns_validatorevent_t *devent;
+ dns_validator_t *val;
+ isc_boolean_t want_destroy;
+ isc_result_t result;
+ isc_result_t eresult;
+
+ UNUSED(task);
+ INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
+
+ devent = (dns_validatorevent_t *)event;
+ val = devent->ev_arg;
+ eresult = devent->result;
+
+ isc_event_free(&event);
+ dns_validator_destroy(&val->subvalidator);
+
+ INSIST(val->event != NULL);
+
+ validator_log(val, ISC_LOG_DEBUG(3), "in keyvalidated");
+ LOCK(&val->lock);
+ if (CANCELED(val)) {
+ validator_done(val, ISC_R_CANCELED);
+ } else if (eresult == ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "keyset with trust %d", val->frdataset.trust);
+ /*
+ * Only extract the dst key if the keyset is secure.
+ */
+ if (val->frdataset.trust >= dns_trust_secure)
+ (void) get_dst_key(val, val->siginfo, &val->frdataset);
+ result = validate(val, ISC_TRUE);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ } else {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "keyvalidated: got %s",
+ isc_result_totext(eresult));
+ validator_done(val, eresult);
+ }
+ want_destroy = exit_check(val);
+ UNLOCK(&val->lock);
+ if (want_destroy)
+ destroy(val);
+}
+
+/*%
+ * Callback when the DS record has been validated.
+ *
+ * Resumes validation of the zone key or the unsecure zone proof.
+ */
+static void
+dsvalidated(isc_task_t *task, isc_event_t *event) {
+ dns_validatorevent_t *devent;
+ dns_validator_t *val;
+ isc_boolean_t want_destroy;
+ isc_result_t result;
+ isc_result_t eresult;
+
+ UNUSED(task);
+ INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
+
+ devent = (dns_validatorevent_t *)event;
+ val = devent->ev_arg;
+ eresult = devent->result;
+
+ isc_event_free(&event);
+ dns_validator_destroy(&val->subvalidator);
+
+ INSIST(val->event != NULL);
+
+ validator_log(val, ISC_LOG_DEBUG(3), "in dsvalidated");
+ LOCK(&val->lock);
+ if (CANCELED(val)) {
+ validator_done(val, ISC_R_CANCELED);
+ } else if (eresult == ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "dsset with trust %d", val->frdataset.trust);
+ if ((val->attributes & VALATTR_INSECURITY) != 0)
+ result = proveunsecure(val, ISC_TRUE, ISC_TRUE);
+ else
+ result = validatezonekey(val);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ } else {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "dsvalidated: got %s",
+ isc_result_totext(eresult));
+ validator_done(val, eresult);
+ }
+ want_destroy = exit_check(val);
+ UNLOCK(&val->lock);
+ if (want_destroy)
+ destroy(val);
+}
+
+/*%
+ * Return ISC_R_SUCCESS if we can determine that the name doesn't exist
+ * or we can determine whether there is data or not at the name.
+ * If the name does not exist return the wildcard name.
+ *
+ * Return ISC_R_IGNORE when the NSEC is not the appropriate one.
+ */
+static isc_result_t
+nsecnoexistnodata(dns_validator_t *val, dns_name_t* name, dns_name_t *nsecname,
+ dns_rdataset_t *nsecset, isc_boolean_t *exists,
+ isc_boolean_t *data, dns_name_t *wild)
+{
+ int order;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ dns_namereln_t relation;
+ unsigned int olabels, nlabels, labels;
+ dns_rdata_nsec_t nsec;
+ isc_boolean_t atparent;
+ isc_boolean_t ns;
+ isc_boolean_t soa;
+
+ REQUIRE(exists != NULL);
+ REQUIRE(data != NULL);
+ REQUIRE(nsecset != NULL &&
+ nsecset->type == dns_rdatatype_nsec);
+
+ result = dns_rdataset_first(nsecset);
+ if (result != ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "failure processing NSEC set");
+ return (result);
+ }
+ dns_rdataset_current(nsecset, &rdata);
+
+ validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nsec");
+ relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
+
+ if (order < 0) {
+ /*
+ * The name is not within the NSEC range.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC does not cover name, before NSEC");
+ return (ISC_R_IGNORE);
+ }
+
+ if (order == 0) {
+ /*
+ * The names are the same.
+ */
+ atparent = dns_rdatatype_atparent(val->event->type);
+ ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
+ soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
+ if (ns && !soa) {
+ if (!atparent) {
+ /*
+ * This NSEC record is from somewhere higher in
+ * the DNS, and at the parent of a delegation.
+ * It can not be legitimately used here.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring parent nsec");
+ return (ISC_R_IGNORE);
+ }
+ } else if (atparent && ns && soa) {
+ /*
+ * This NSEC record is from the child.
+ * It can not be legitimately used here.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring child nsec");
+ return (ISC_R_IGNORE);
+ }
+ if (val->event->type == dns_rdatatype_cname ||
+ val->event->type == dns_rdatatype_nxt ||
+ val->event->type == dns_rdatatype_nsec ||
+ val->event->type == dns_rdatatype_key ||
+ !dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
+ *exists = ISC_TRUE;
+ *data = dns_nsec_typepresent(&rdata, val->event->type);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "nsec proves name exists (owner) data=%d",
+ *data);
+ return (ISC_R_SUCCESS);
+ }
+ validator_log(val, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
+ return (ISC_R_IGNORE);
+ }
+
+ if (relation == dns_namereln_subdomain &&
+ dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
+ !dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
+ {
+ /*
+ * This NSEC record is from somewhere higher in
+ * the DNS, and at the parent of a delegation.
+ * It can not be legitimately used here.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3), "ignoring parent nsec");
+ return (ISC_R_IGNORE);
+ }
+
+ result = dns_rdata_tostruct(&rdata, &nsec, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
+ if (order == 0) {
+ dns_rdata_freestruct(&nsec);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring nsec matches next name");
+ return (ISC_R_IGNORE);
+ }
+
+ if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
+ /*
+ * The name is not within the NSEC range.
+ */
+ dns_rdata_freestruct(&nsec);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring nsec because name is past end of range");
+ return (ISC_R_IGNORE);
+ }
+
+ if (order > 0 && relation == dns_namereln_subdomain) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "nsec proves name exist (empty)");
+ dns_rdata_freestruct(&nsec);
+ *exists = ISC_TRUE;
+ *data = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+ }
+ if (wild != NULL) {
+ dns_name_t common;
+ dns_name_init(&common, NULL);
+ if (olabels > nlabels) {
+ labels = dns_name_countlabels(nsecname);
+ dns_name_getlabelsequence(nsecname, labels - olabels,
+ olabels, &common);
+ } else {
+ labels = dns_name_countlabels(&nsec.next);
+ dns_name_getlabelsequence(&nsec.next, labels - nlabels,
+ nlabels, &common);
+ }
+ result = dns_name_concatenate(dns_wildcardname, &common,
+ wild, NULL);
+ if (result != ISC_R_SUCCESS) {
+ dns_rdata_freestruct(&nsec);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "failure generating wildcard name");
+ return (result);
+ }
+ }
+ dns_rdata_freestruct(&nsec);
+ validator_log(val, ISC_LOG_DEBUG(3), "nsec range ok");
+ *exists = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+nsec3noexistnodata(dns_validator_t *val, dns_name_t* name,
+ dns_name_t *nsec3name, dns_rdataset_t *nsec3set,
+ dns_name_t *zonename, isc_boolean_t *exists,
+ isc_boolean_t *data, isc_boolean_t *optout,
+ isc_boolean_t *unknown, isc_boolean_t *setclosest,
+ isc_boolean_t *setnearest, dns_name_t *closest,
+ dns_name_t *nearest)
+{
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fzone;
+ dns_fixedname_t qfixed;
+ dns_label_t hashlabel;
+ dns_name_t *qname;
+ dns_name_t *zone;
+ dns_rdata_nsec3_t nsec3;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ int order;
+ int scope;
+ isc_boolean_t atparent;
+ isc_boolean_t first;
+ isc_boolean_t ns;
+ isc_boolean_t soa;
+ isc_buffer_t buffer;
+ isc_result_t answer = ISC_R_IGNORE;
+ isc_result_t result;
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char owner[NSEC3_MAX_HASH_LENGTH];
+ unsigned int length;
+ unsigned int qlabels;
+ unsigned int zlabels;
+
+ REQUIRE((exists == NULL && data == NULL) ||
+ (exists != NULL && data != NULL));
+ REQUIRE(nsec3set != NULL && nsec3set->type == dns_rdatatype_nsec3);
+ REQUIRE((setclosest == NULL && closest == NULL) ||
+ (setclosest != NULL && closest != NULL));
+ REQUIRE((setnearest == NULL && nearest == NULL) ||
+ (setnearest != NULL && nearest != NULL));
+
+ result = dns_rdataset_first(nsec3set);
+ if (result != ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "failure processing NSEC3 set");
+ return (result);
+ }
+
+ dns_rdataset_current(nsec3set, &rdata);
+
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant NSEC3");
+
+ dns_fixedname_init(&fzone);
+ zone = dns_fixedname_name(&fzone);
+ zlabels = dns_name_countlabels(nsec3name);
+
+ /*
+ * NSEC3 records must have two or more labels to be valid.
+ */
+ if (zlabels < 2)
+ return (ISC_R_IGNORE);
+
+ /*
+ * Strip off the NSEC3 hash to get the zone.
+ */
+ zlabels--;
+ dns_name_split(nsec3name, zlabels, NULL, zone);
+
+ /*
+ * If not below the zone name we can ignore this record.
+ */
+ if (!dns_name_issubdomain(name, zone))
+ return (ISC_R_IGNORE);
+
+ /*
+ * Is this zone the same or deeper than the current zone?
+ */
+ if (dns_name_countlabels(zonename) == 0 ||
+ dns_name_issubdomain(zone, zonename))
+ dns_name_copy(zone, zonename, NULL);
+
+ if (!dns_name_equal(zone, zonename))
+ return (ISC_R_IGNORE);
+
+ /*
+ * Are we only looking for the most enclosing zone?
+ */
+ if (exists == NULL || data == NULL)
+ return (ISC_R_SUCCESS);
+
+ /*
+ * Only set unknown once we are sure that this NSEC3 is from
+ * the deepest covering zone.
+ */
+ if (!dns_nsec3_supportedhash(nsec3.hash)) {
+ if (unknown != NULL)
+ *unknown = ISC_TRUE;
+ return (ISC_R_IGNORE);
+ }
+
+ /*
+ * Recover the hash from the first label.
+ */
+ dns_name_getlabel(nsec3name, 0, &hashlabel);
+ isc_region_consume(&hashlabel, 1);
+ isc_buffer_init(&buffer, owner, sizeof(owner));
+ result = isc_base32hex_decoderegion(&hashlabel, &buffer);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * The hash lengths should match. If not ignore the record.
+ */
+ if (isc_buffer_usedlength(&buffer) != nsec3.next_length)
+ return (ISC_R_IGNORE);
+
+ /*
+ * Work out what this NSEC3 covers.
+ * Inside (<0) or outside (>=0).
+ */
+ scope = memcmp(owner, nsec3.next, nsec3.next_length);
+
+ /*
+ * Prepare to compute all the hashes.
+ */
+ dns_fixedname_init(&qfixed);
+ qname = dns_fixedname_name(&qfixed);
+ dns_name_downcase(name, qname, NULL);
+ qlabels = dns_name_countlabels(qname);
+ first = ISC_TRUE;
+
+ while (qlabels >= zlabels) {
+ length = isc_iterated_hash(hash, nsec3.hash, nsec3.iterations,
+ nsec3.salt, nsec3.salt_length,
+ qname->ndata, qname->length);
+ /*
+ * The computed hash length should match.
+ */
+ if (length != nsec3.next_length) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring NSEC bad length %u vs %u",
+ length, nsec3.next_length);
+ return (ISC_R_IGNORE);
+ }
+
+ order = memcmp(hash, owner, length);
+ if (first && order == 0) {
+ /*
+ * The hashes are the same.
+ */
+ atparent = dns_rdatatype_atparent(val->event->type);
+ ns = dns_nsec3_typepresent(&rdata, dns_rdatatype_ns);
+ soa = dns_nsec3_typepresent(&rdata, dns_rdatatype_soa);
+ if (ns && !soa) {
+ if (!atparent) {
+ /*
+ * This NSEC record is from somewhere
+ * higher in the DNS, and at the
+ * parent of a delegation. It can not
+ * be legitimately used here.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring parent NSEC3");
+ return (ISC_R_IGNORE);
+ }
+ } else if (atparent && ns && soa) {
+ /*
+ * This NSEC record is from the child.
+ * It can not be legitimately used here.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring child NSEC3");
+ return (ISC_R_IGNORE);
+ }
+ if (val->event->type == dns_rdatatype_cname ||
+ val->event->type == dns_rdatatype_nxt ||
+ val->event->type == dns_rdatatype_nsec ||
+ val->event->type == dns_rdatatype_key ||
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_cname)) {
+ *exists = ISC_TRUE;
+ *data = dns_nsec3_typepresent(&rdata,
+ val->event->type);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 proves name exists (owner) "
+ "data=%d", *data);
+ return (ISC_R_SUCCESS);
+ }
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 proves CNAME exists");
+ return (ISC_R_IGNORE);
+ }
+
+ if (order == 0 &&
+ dns_nsec3_typepresent(&rdata, dns_rdatatype_ns) &&
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_soa))
+ {
+ /*
+ * This NSEC3 record is from somewhere higher in
+ * the DNS, and at the parent of a delegation.
+ * It can not be legitimately used here.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "ignoring parent NSEC3");
+ return (ISC_R_IGNORE);
+ }
+
+ /*
+ * Potential closest encloser.
+ */
+ if (order == 0) {
+ if (closest != NULL &&
+ (dns_name_countlabels(closest) == 0 ||
+ dns_name_issubdomain(qname, closest)) &&
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_dname) &&
+ (dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
+ {
+
+ dns_name_format(qname, namebuf,
+ sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 indicates potential "
+ "closest encloser: '%s'",
+ namebuf);
+ dns_name_copy(qname, closest, NULL);
+ *setclosest = ISC_TRUE;
+ }
+ dns_name_format(qname, namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 at super-domain %s", namebuf);
+ return (answer);
+ }
+
+ /*
+ * Find if the name does not exist.
+ *
+ * We continue as we need to find the name closest to the
+ * closest encloser that doesn't exist.
+ *
+ * We also need to continue to ensure that we are not
+ * proving the non-existance of a record in a sub-zone.
+ * If that would be the case we will return ISC_R_IGNORE
+ * above.
+ */
+ if ((scope < 0 && order > 0 &&
+ memcmp(hash, nsec3.next, length) < 0) ||
+ (scope >= 0 && (order > 0 ||
+ memcmp(hash, nsec3.next, length) < 0)))
+ {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(qname, namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3), "NSEC3 proves "
+ "name does not exist: '%s'", namebuf);
+ if (nearest != NULL &&
+ (dns_name_countlabels(nearest) == 0 ||
+ dns_name_issubdomain(nearest, qname))) {
+ dns_name_copy(qname, nearest, NULL);
+ *setnearest = ISC_TRUE;
+ }
+#if 0
+ /*
+ * The closest encloser may be the zone name.
+ */
+ if (closest != NULL &&
+ dns_name_countlabels(closest) == 0 &&
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_dname) &&
+ (dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
+ !dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
+ {
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_name_format(zone, namebuf,
+ sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 potential closest "
+ "encloser from zone name: '%s'",
+ namebuf);
+ dns_name_copy(zone, closest, NULL);
+ *setclosest = ISC_TRUE;
+ }
+#endif
+ *exists = ISC_FALSE;
+ *data = ISC_FALSE;
+ if (optout != NULL) {
+ if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0)
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "NSEC3 indicates optout");
+ *optout =
+ ISC_TF(nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
+ }
+ answer = ISC_R_SUCCESS;
+ }
+
+ qlabels--;
+ if (qlabels > 0)
+ dns_name_split(qname, qlabels, NULL, qname);
+ first = ISC_FALSE;
+ }
+ return (answer);
+}
+
+/*%
+ * Callback for when NSEC records have been validated.
+ *
+ * Looks for NOQNAME, NODATA and OPTOUT proofs.
+ *
+ * Resumes nsecvalidate.
+ */
+static void
+authvalidated(isc_task_t *task, isc_event_t *event) {
+ dns_validatorevent_t *devent;
+ dns_validator_t *val;
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ isc_boolean_t want_destroy;
+ isc_result_t result;
+ isc_boolean_t exists, data;
+
+ UNUSED(task);
+ INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE);
+
+ devent = (dns_validatorevent_t *)event;
+ rdataset = devent->rdataset;
+ sigrdataset = devent->sigrdataset;
+ val = devent->ev_arg;
+ result = devent->result;
+ dns_validator_destroy(&val->subvalidator);
+
+ INSIST(val->event != NULL);
+
+ validator_log(val, ISC_LOG_DEBUG(3), "in authvalidated");
+ LOCK(&val->lock);
+ if (CANCELED(val)) {
+ validator_done(val, ISC_R_CANCELED);
+ } else if (result != ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "authvalidated: got %s",
+ isc_result_totext(result));
+ if (result == ISC_R_CANCELED)
+ validator_done(val, result);
+ else {
+ result = nsecvalidate(val, ISC_TRUE);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ }
+ } else {
+ dns_name_t **proofs = val->event->proofs;
+ dns_name_t *wild = dns_fixedname_name(&val->wild);
+
+ if (rdataset->trust == dns_trust_secure)
+ val->seensig = ISC_TRUE;
+
+ if (rdataset->type == dns_rdatatype_nsec &&
+ rdataset->trust == dns_trust_secure &&
+ ((val->attributes & VALATTR_NEEDNODATA) != 0 ||
+ (val->attributes & VALATTR_NEEDNOQNAME) != 0) &&
+ (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
+ (val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
+ nsecnoexistnodata(val, val->event->name, devent->name,
+ rdataset, &exists, &data, wild)
+ == ISC_R_SUCCESS)
+ {
+ if (exists && !data) {
+ val->attributes |= VALATTR_FOUNDNODATA;
+ if (NEEDNODATA(val))
+ proofs[DNS_VALIDATOR_NODATAPROOF] =
+ devent->name;
+ }
+ if (!exists) {
+ val->attributes |= VALATTR_FOUNDNOQNAME;
+ val->attributes |= VALATTR_FOUNDCLOSEST;
+ /*
+ * The NSEC noqname proof also contains
+ * the closest encloser.
+
+ */
+ if (NEEDNOQNAME(val))
+ proofs[DNS_VALIDATOR_NOQNAMEPROOF] =
+ devent->name;
+ }
+ }
+
+ result = nsecvalidate(val, ISC_TRUE);
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ }
+ want_destroy = exit_check(val);
+ UNLOCK(&val->lock);
+ if (want_destroy)
+ destroy(val);
+
+ /*
+ * Free stuff from the event.
+ */
+ isc_event_free(&event);
+}
+
+/*%
+ * Looks for the requested name and type in the view (zones and cache).
+ *
+ * When looking for a DLV record also checks to make sure the NSEC record
+ * returns covers the query name as part of aggressive negative caching.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOTFOUND
+ * \li DNS_R_NCACHENXDOMAIN
+ * \li DNS_R_NCACHENXRRSET
+ * \li DNS_R_NXRRSET
+ * \li DNS_R_NXDOMAIN
+ */
+static inline isc_result_t
+view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
+ dns_fixedname_t fixedname;
+ dns_name_t *foundname;
+ dns_rdata_nsec_t nsec;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ unsigned int options;
+ char buf1[DNS_NAME_FORMATSIZE];
+ char buf2[DNS_NAME_FORMATSIZE];
+ char buf3[DNS_NAME_FORMATSIZE];
+
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+
+ if (val->view->zonetable == NULL)
+ return (ISC_R_CANCELED);
+
+ options = DNS_DBFIND_PENDINGOK;
+ if (type == dns_rdatatype_dlv)
+ options |= DNS_DBFIND_COVERINGNSEC;
+ dns_fixedname_init(&fixedname);
+ foundname = dns_fixedname_name(&fixedname);
+ result = dns_view_find(val->view, name, type, 0, options,
+ ISC_FALSE, NULL, NULL, foundname,
+ &val->frdataset, &val->fsigrdataset);
+ if (result == DNS_R_NXDOMAIN) {
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ } else if (result == DNS_R_COVERINGNSEC) {
+ validator_log(val, ISC_LOG_DEBUG(3), "DNS_R_COVERINGNSEC");
+ /*
+ * Check if the returned NSEC covers the name.
+ */
+ INSIST(type == dns_rdatatype_dlv);
+ if (val->frdataset.trust != dns_trust_secure) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "covering nsec: trust %u",
+ val->frdataset.trust);
+ goto notfound;
+ }
+ result = dns_rdataset_first(&val->frdataset);
+ if (result != ISC_R_SUCCESS)
+ goto notfound;
+ dns_rdataset_current(&val->frdataset, &rdata);
+ if (dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
+ !dns_nsec_typepresent(&rdata, dns_rdatatype_soa)) {
+ /* Parent NSEC record. */
+ if (dns_name_issubdomain(name, foundname)) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "covering nsec: for parent");
+ goto notfound;
+ }
+ }
+ result = dns_rdata_tostruct(&rdata, &nsec, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto notfound;
+ if (dns_name_compare(foundname, &nsec.next) >= 0) {
+ /* End of zone chain. */
+ if (!dns_name_issubdomain(name, &nsec.next)) {
+ /*
+ * XXXMPA We could look for a parent NSEC
+ * at nsec.next and if found retest with
+ * this NSEC.
+ */
+ dns_rdata_freestruct(&nsec);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "covering nsec: not in zone");
+ goto notfound;
+ }
+ } else if (dns_name_compare(name, &nsec.next) >= 0) {
+ /*
+ * XXXMPA We could check if this NSEC is at a zone
+ * apex and if the qname is not below it and look for
+ * a parent NSEC with the same name. This requires
+ * that we can cache both NSEC records which we
+ * currently don't support.
+ */
+ dns_rdata_freestruct(&nsec);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "covering nsec: not in range");
+ goto notfound;
+ }
+ if (isc_log_wouldlog(dns_lctx,ISC_LOG_DEBUG(3))) {
+ dns_name_format(name, buf1, sizeof buf1);
+ dns_name_format(foundname, buf2, sizeof buf2);
+ dns_name_format(&nsec.next, buf3, sizeof buf3);
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "covering nsec found: '%s' '%s' '%s'",
+ buf1, buf2, buf3);
+ }
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ dns_rdata_freestruct(&nsec);
+ result = DNS_R_NCACHENXDOMAIN;
+ } else if (result != ISC_R_SUCCESS &&
+ result != DNS_R_NCACHENXDOMAIN &&
+ result != DNS_R_NCACHENXRRSET &&
+ result != DNS_R_EMPTYNAME &&
+ result != DNS_R_NXRRSET &&
+ result != ISC_R_NOTFOUND) {
+ goto notfound;
+ }
+ return (result);
+
+ notfound:
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ return (ISC_R_NOTFOUND);
+}
+
+/*%
+ * Checks to make sure we are not going to loop. As we use a SHARED fetch
+ * the validation process will stall if looping was to occur.
+ */
+static inline isc_boolean_t
+check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ dns_validator_t *parent;
+
+ for (parent = val; parent != NULL; parent = parent->parent) {
+ if (parent->event != NULL &&
+ parent->event->type == type &&
+ dns_name_equal(parent->event->name, name) &&
+ /*
+ * As NSEC3 records are meta data you sometimes
+ * need to prove a NSEC3 record which says that
+ * itself doesn't exist.
+ */
+ (parent->event->type != dns_rdatatype_nsec3 ||
+ rdataset == NULL || sigrdataset == NULL ||
+ parent->event->message == NULL ||
+ parent->event->rdataset != NULL ||
+ parent->event->sigrdataset != NULL))
+ {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "continuing validation would lead to "
+ "deadlock: aborting validation");
+ return (ISC_TRUE);
+ }
+ }
+ return (ISC_FALSE);
+}
+
+/*%
+ * Start a fetch for the requested name and type.
+ */
+static inline isc_result_t
+create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
+ isc_taskaction_t callback, const char *caller)
+{
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+
+ if (check_deadlock(val, name, type, NULL, NULL))
+ return (DNS_R_NOVALIDSIG);
+
+ validator_logcreate(val, name, type, caller, "fetch");
+ return (dns_resolver_createfetch(val->view->resolver, name, type,
+ NULL, NULL, NULL, 0,
+ val->event->ev_sender,
+ callback, val,
+ &val->frdataset,
+ &val->fsigrdataset,
+ &val->fetch));
+}
+
+/*%
+ * Start a subvalidation process.
+ */
+static inline isc_result_t
+create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ isc_taskaction_t action, const char *caller)
+{
+ isc_result_t result;
+
+ if (check_deadlock(val, name, type, rdataset, sigrdataset))
+ return (DNS_R_NOVALIDSIG);
+
+ validator_logcreate(val, name, type, caller, "validator");
+ result = dns_validator_create(val->view, name, type,
+ rdataset, sigrdataset, NULL, 0,
+ val->task, action, val,
+ &val->subvalidator);
+ if (result == ISC_R_SUCCESS) {
+ val->subvalidator->parent = val;
+ val->subvalidator->depth = val->depth + 1;
+ }
+ return (result);
+}
+
+/*%
+ * Try to find a key that could have signed 'siginfo' among those
+ * in 'rdataset'. If found, build a dst_key_t for it and point
+ * val->key at it.
+ *
+ * If val->key is non-NULL, this returns the next matching key.
+ */
+static isc_result_t
+get_dst_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo,
+ dns_rdataset_t *rdataset)
+{
+ isc_result_t result;
+ isc_buffer_t b;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dst_key_t *oldkey = val->key;
+ isc_boolean_t foundold;
+
+ if (oldkey == NULL)
+ foundold = ISC_TRUE;
+ else {
+ foundold = ISC_FALSE;
+ val->key = NULL;
+ }
+
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ do {
+ dns_rdataset_current(rdataset, &rdata);
+
+ isc_buffer_init(&b, rdata.data, rdata.length);
+ isc_buffer_add(&b, rdata.length);
+ INSIST(val->key == NULL);
+ result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
+ val->view->mctx, &val->key);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ if (siginfo->algorithm ==
+ (dns_secalg_t)dst_key_alg(val->key) &&
+ siginfo->keyid ==
+ (dns_keytag_t)dst_key_id(val->key) &&
+ dst_key_iszonekey(val->key))
+ {
+ if (foundold)
+ /*
+ * This is the key we're looking for.
+ */
+ return (ISC_R_SUCCESS);
+ else if (dst_key_compare(oldkey, val->key) == ISC_TRUE)
+ {
+ foundold = ISC_TRUE;
+ dst_key_free(&oldkey);
+ }
+ }
+ dst_key_free(&val->key);
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(rdataset);
+ } while (result == ISC_R_SUCCESS);
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_NOTFOUND;
+
+ failure:
+ if (oldkey != NULL)
+ dst_key_free(&oldkey);
+
+ return (result);
+}
+
+/*%
+ * Get the key that genertated this signature.
+ */
+static isc_result_t
+get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
+ isc_result_t result;
+ unsigned int nlabels;
+ int order;
+ dns_namereln_t namereln;
+
+ /*
+ * Is the signer name appropriate for this signature?
+ *
+ * The signer name must be at the same level as the owner name
+ * or closer to the the DNS root.
+ */
+ namereln = dns_name_fullcompare(val->event->name, &siginfo->signer,
+ &order, &nlabels);
+ if (namereln != dns_namereln_subdomain &&
+ namereln != dns_namereln_equal)
+ return (DNS_R_CONTINUE);
+
+ if (namereln == dns_namereln_equal) {
+ /*
+ * If this is a self-signed keyset, it must not be a zone key
+ * (since get_key is not called from validatezonekey).
+ */
+ if (val->event->rdataset->type == dns_rdatatype_dnskey)
+ return (DNS_R_CONTINUE);
+
+ /*
+ * Records appearing in the parent zone at delegation
+ * points cannot be self-signed.
+ */
+ if (dns_rdatatype_atparent(val->event->rdataset->type))
+ return (DNS_R_CONTINUE);
+ } else {
+ /*
+ * SOA and NS RRsets can only be signed by a key with
+ * the same name.
+ */
+ if (val->event->rdataset->type == dns_rdatatype_soa ||
+ val->event->rdataset->type == dns_rdatatype_ns) {
+ const char *typename;
+
+ if (val->event->rdataset->type == dns_rdatatype_soa)
+ typename = "SOA";
+ else
+ typename = "NS";
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "%s signer mismatch", typename);
+ return (DNS_R_CONTINUE);
+ }
+ }
+
+ /*
+ * Do we know about this key?
+ */
+ result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We have an rrset for the given keyname.
+ */
+ val->keyset = &val->frdataset;
+ if (val->frdataset.trust == dns_trust_pending &&
+ dns_rdataset_isassociated(&val->fsigrdataset))
+ {
+ /*
+ * We know the key but haven't validated it yet.
+ */
+ result = create_validator(val, &siginfo->signer,
+ dns_rdatatype_dnskey,
+ &val->frdataset,
+ &val->fsigrdataset,
+ keyvalidated,
+ "get_key");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (DNS_R_WAIT);
+ } else if (val->frdataset.trust == dns_trust_pending) {
+ /*
+ * Having a pending key with no signature means that
+ * something is broken.
+ */
+ result = DNS_R_CONTINUE;
+ } else if (val->frdataset.trust < dns_trust_secure) {
+ /*
+ * The key is legitimately insecure. There's no
+ * point in even attempting verification.
+ */
+ val->key = NULL;
+ result = ISC_R_SUCCESS;
+ } else {
+ /*
+ * See if we've got the key used in the signature.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "keyset with trust %d",
+ val->frdataset.trust);
+ result = get_dst_key(val, siginfo, val->keyset);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * Either the key we're looking for is not
+ * in the rrset, or something bad happened.
+ * Give up.
+ */
+ result = DNS_R_CONTINUE;
+ }
+ }
+ } else if (result == ISC_R_NOTFOUND) {
+ /*
+ * We don't know anything about this key.
+ */
+ result = create_fetch(val, &siginfo->signer, dns_rdatatype_dnskey,
+ fetch_callback_validator, "get_key");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (DNS_R_WAIT);
+ } else if (result == DNS_R_NCACHENXDOMAIN ||
+ result == DNS_R_NCACHENXRRSET ||
+ result == DNS_R_EMPTYNAME ||
+ result == DNS_R_NXDOMAIN ||
+ result == DNS_R_NXRRSET)
+ {
+ /*
+ * This key doesn't exist.
+ */
+ result = DNS_R_CONTINUE;
+ }
+
+ if (dns_rdataset_isassociated(&val->frdataset) &&
+ val->keyset != &val->frdataset)
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+
+ return (result);
+}
+
+static dns_keytag_t
+compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
+ isc_region_t r;
+
+ dns_rdata_toregion(rdata, &r);
+ return (dst_region_computeid(&r, key->algorithm));
+}
+
+/*%
+ * Is this keyset self-signed?
+ */
+static isc_boolean_t
+isselfsigned(dns_validator_t *val) {
+ 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;
+ isc_result_t result;
+
+ rdataset = val->event->rdataset;
+ sigrdataset = val->event->sigrdataset;
+
+ INSIST(rdataset->type == dns_rdatatype_dnskey);
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset))
+ {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &key, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ keytag = compute_keytag(&rdata, &key);
+ for (result = dns_rdataset_first(sigrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(sigrdataset))
+ {
+ dns_rdata_reset(&sigrdata);
+ dns_rdataset_current(sigrdataset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (sig.algorithm == key.algorithm &&
+ sig.keyid == keytag)
+ return (ISC_TRUE);
+ }
+ }
+ return (ISC_FALSE);
+}
+
+/*%
+ * Attempt to verify the rdataset using the given key and rdata (RRSIG).
+ * The signature was good and from a wildcard record and the QNAME does
+ * not match the wildcard we need to look for a NOQNAME proof.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS if the verification succeeds.
+ * \li Others if the verification fails.
+ */
+static isc_result_t
+verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata,
+ isc_uint16_t keyid)
+{
+ isc_result_t result;
+ dns_fixedname_t fixed;
+ isc_boolean_t ignore = ISC_FALSE;
+
+ val->attributes |= VALATTR_TRIEDVERIFY;
+ dns_fixedname_init(&fixed);
+ again:
+ result = dns_dnssec_verify2(val->event->name, val->event->rdataset,
+ key, ignore, val->view->mctx, rdata,
+ dns_fixedname_name(&fixed));
+ if (result == DNS_R_SIGEXPIRED && val->view->acceptexpired) {
+ ignore = ISC_TRUE;
+ goto again;
+ }
+ if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD))
+ validator_log(val, ISC_LOG_INFO,
+ "accepted expired %sRRSIG (keyid=%u)",
+ (result == DNS_R_FROMWILDCARD) ?
+ "wildcard " : "", keyid);
+ else
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "verify rdataset (keyid=%u): %s",
+ keyid, isc_result_totext(result));
+ if (result == DNS_R_FROMWILDCARD) {
+ if (!dns_name_equal(val->event->name,
+ dns_fixedname_name(&fixed)))
+ val->attributes |= VALATTR_NEEDNOQNAME;
+ result = ISC_R_SUCCESS;
+ }
+ return (result);
+}
+
+/*%
+ * Attempts positive response validation of a normal RRset.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS Validation completed successfully
+ * \li DNS_R_WAIT Validation has started but is waiting
+ * for an event.
+ * \li Other return codes are possible and all indicate failure.
+ */
+static isc_result_t
+validate(dns_validator_t *val, isc_boolean_t resume) {
+ isc_result_t result;
+ dns_validatorevent_t *event;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ /*
+ * Caller must be holding the validator lock.
+ */
+
+ event = val->event;
+
+ if (resume) {
+ /*
+ * We already have a sigrdataset.
+ */
+ result = ISC_R_SUCCESS;
+ validator_log(val, ISC_LOG_DEBUG(3), "resuming validate");
+ } else {
+ result = dns_rdataset_first(event->sigrdataset);
+ }
+
+ for (;
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(event->sigrdataset))
+ {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(event->sigrdataset, &rdata);
+ if (val->siginfo == NULL) {
+ val->siginfo = isc_mem_get(val->view->mctx,
+ sizeof(*val->siginfo));
+ if (val->siginfo == NULL)
+ return (ISC_R_NOMEMORY);
+ }
+ result = dns_rdata_tostruct(&rdata, val->siginfo, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * At this point we could check that the signature algorithm
+ * was known and "sufficiently good".
+ */
+ if (!dns_resolver_algorithm_supported(val->view->resolver,
+ event->name,
+ val->siginfo->algorithm))
+ continue;
+
+ if (!resume) {
+ result = get_key(val, val->siginfo);
+ if (result == DNS_R_CONTINUE)
+ continue; /* Try the next SIG RR. */
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ /*
+ * The key is insecure, so mark the data as insecure also.
+ */
+ if (val->key == NULL) {
+ if (val->mustbesecure) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure");
+ return (DNS_R_MUSTBESECURE);
+ }
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ }
+
+ do {
+ result = verify(val, val->key, &rdata,
+ val->siginfo->keyid);
+ if (result == ISC_R_SUCCESS)
+ break;
+ if (val->keynode != NULL) {
+ dns_keynode_t *nextnode = NULL;
+ result = dns_keytable_findnextkeynode(
+ val->keytable,
+ val->keynode,
+ &nextnode);
+ dns_keytable_detachkeynode(val->keytable,
+ &val->keynode);
+ val->keynode = nextnode;
+ if (result != ISC_R_SUCCESS) {
+ val->key = NULL;
+ break;
+ }
+ val->key = dns_keynode_key(val->keynode);
+ } else {
+ if (get_dst_key(val, val->siginfo, val->keyset)
+ != ISC_R_SUCCESS)
+ break;
+ }
+ } while (1);
+ if (result != ISC_R_SUCCESS)
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "failed to verify rdataset");
+ else {
+ isc_uint32_t ttl;
+ isc_stdtime_t now;
+
+ 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;
+ }
+
+ if (val->keynode != NULL)
+ dns_keytable_detachkeynode(val->keytable,
+ &val->keynode);
+ else {
+ if (val->key != NULL)
+ dst_key_free(&val->key);
+ if (val->keyset != NULL) {
+ dns_rdataset_disassociate(val->keyset);
+ val->keyset = NULL;
+ }
+ }
+ val->key = NULL;
+ if ((val->attributes & VALATTR_NEEDNOQNAME) != 0) {
+ if (val->event->message == NULL) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "no message available for noqname proof");
+ return (DNS_R_NOVALIDSIG);
+ }
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "looking for noqname proof");
+ return (nsecvalidate(val, ISC_FALSE));
+ } else if (result == ISC_R_SUCCESS) {
+ event->rdataset->trust = dns_trust_secure;
+ event->sigrdataset->trust = dns_trust_secure;
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "marking as secure");
+ return (result);
+ } else {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "verify failure: %s",
+ isc_result_totext(result));
+ resume = ISC_FALSE;
+ }
+ }
+ if (result != ISC_R_NOMORE) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "failed to iterate signatures: %s",
+ isc_result_totext(result));
+ return (result);
+ }
+
+ validator_log(val, ISC_LOG_INFO, "no valid signature found");
+ return (DNS_R_NOVALIDSIG);
+}
+
+/*%
+ * 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;
+
+ validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
+
+ /*
+ * Look through the DLV record and find the keys that can sign the
+ * key set and the matching signature. For each such key, attempt
+ * verification.
+ */
+ supported_algorithm = ISC_FALSE;
+
+ /*
+ * If DNS_DSDIGEST_SHA256 is present we are required to prefer
+ * it over DNS_DSDIGEST_SHA1. This in practice means that we
+ * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
+ * is present.
+ */
+ digest_type = DNS_DSDIGEST_SHA1;
+ for (result = dns_rdataset_first(&val->dlv);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&val->dlv)) {
+ dns_rdata_reset(&dlvrdata);
+ dns_rdataset_current(&val->dlv, &dlvrdata);
+ result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (!dns_resolver_algorithm_supported(val->view->resolver,
+ val->event->name,
+ dlv.algorithm))
+ continue;
+
+ if (dlv.digest_type == DNS_DSDIGEST_SHA256 &&
+ dlv.length == ISC_SHA256_DIGESTLENGTH) {
+ digest_type = DNS_DSDIGEST_SHA256;
+ break;
+ }
+ }
+
+ for (result = dns_rdataset_first(&val->dlv);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&val->dlv))
+ {
+ dns_rdata_reset(&dlvrdata);
+ dns_rdataset_current(&val->dlv, &dlvrdata);
+ result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (!dns_resolver_digest_supported(val->view->resolver,
+ dlv.digest_type))
+ continue;
+
+ if (dlv.digest_type != digest_type)
+ continue;
+
+ if (!dns_resolver_algorithm_supported(val->view->resolver,
+ val->event->name,
+ dlv.algorithm))
+ continue;
+
+ supported_algorithm = ISC_TRUE;
+
+ 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;
+ }
+ if (result != ISC_R_SUCCESS) {
+ 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");
+
+ 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;
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "no RRSIG matching DLV key");
+ }
+ if (result == ISC_R_SUCCESS) {
+ val->event->rdataset->trust = dns_trust_secure;
+ val->event->sigrdataset->trust = dns_trust_secure;
+ validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
+ return (result);
+ } else if (result == ISC_R_NOMORE && !supported_algorithm) {
+ if (val->mustbesecure) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure");
+ return (DNS_R_MUSTBESECURE);
+ }
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "no supported algorithm/digest (dlv)");
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ } else
+ return (DNS_R_NOVALIDSIG);
+}
+
+/*%
+ * Attempts positive response validation of an RRset containing zone keys.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS Validation completed successfully
+ * \li DNS_R_WAIT Validation has started but is waiting
+ * for an event.
+ * \li Other return codes are possible and all indicate failure.
+ */
+static isc_result_t
+validatezonekey(dns_validator_t *val) {
+ isc_result_t result;
+ 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;
+
+ /*
+ * Caller must be holding the validator lock.
+ */
+
+ event = val->event;
+
+ if (val->havedlvsep && val->dlv.trust >= dns_trust_secure &&
+ dns_name_equal(event->name, dns_fixedname_name(&val->dlvsep)))
+ return (dlv_validatezonekey(val));
+
+ if (val->dsset == NULL) {
+ /*
+ * First, see if this key was signed by a trusted key.
+ */
+ for (result = dns_rdataset_first(val->event->sigrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(val->event->sigrdataset))
+ {
+ dns_keynode_t *keynode = NULL, *nextnode = NULL;
+
+ 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 (!dns_name_equal(val->event->name, &sig.signer))
+ continue;
+
+ result = dns_keytable_findkeynode(val->keytable,
+ val->event->name,
+ sig.algorithm,
+ sig.keyid,
+ &keynode);
+ if (result == DNS_R_PARTIALMATCH ||
+ result == ISC_R_SUCCESS)
+ atsep = ISC_TRUE;
+ while (result == ISC_R_SUCCESS) {
+ dstkey = dns_keynode_key(keynode);
+ result = verify(val, dstkey, &sigrdata,
+ sig.keyid);
+ if (result == ISC_R_SUCCESS) {
+ dns_keytable_detachkeynode(val->keytable,
+ &keynode);
+ break;
+ }
+ result = dns_keytable_findnextkeynode(
+ val->keytable,
+ keynode,
+ &nextnode);
+ dns_keytable_detachkeynode(val->keytable,
+ &keynode);
+ keynode = nextnode;
+ }
+ if (result == ISC_R_SUCCESS) {
+ event->rdataset->trust = dns_trust_secure;
+ event->sigrdataset->trust = dns_trust_secure;
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "signed by trusted key; "
+ "marking as secure");
+ return (result);
+ }
+ }
+
+ /*
+ * If this is the root name and there was no trusted key,
+ * give up, since there's no DS at the root.
+ */
+ if (dns_name_equal(event->name, dns_rootname)) {
+ if ((val->attributes & VALATTR_TRIEDVERIFY) != 0)
+ return (DNS_R_NOVALIDSIG);
+ else
+ return (DNS_R_NOVALIDDS);
+ }
+
+ if (atsep) {
+ /*
+ * We have not found a key to verify this DNSKEY
+ * RRset. As this is a SEP we have to assume that
+ * the RRset is invalid.
+ */
+ dns_name_format(val->event->name, namebuf,
+ sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(2),
+ "unable to find a DNSKEY which verifies "
+ "the DNSKEY RRset and also matches one "
+ "of specified trusted-keys for '%s'",
+ namebuf);
+ return (DNS_R_NOVALIDKEY);
+ }
+
+ /*
+ * Otherwise, try to find the DS record.
+ */
+ result = view_find(val, val->event->name, dns_rdatatype_ds);
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * We have DS records.
+ */
+ val->dsset = &val->frdataset;
+ if (val->frdataset.trust == dns_trust_pending &&
+ dns_rdataset_isassociated(&val->fsigrdataset))
+ {
+ result = create_validator(val,
+ val->event->name,
+ dns_rdatatype_ds,
+ &val->frdataset,
+ &val->fsigrdataset,
+ dsvalidated,
+ "validatezonekey");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (DNS_R_WAIT);
+ } else if (val->frdataset.trust == dns_trust_pending) {
+ /*
+ * There should never be an unsigned DS.
+ */
+ dns_rdataset_disassociate(&val->frdataset);
+ validator_log(val, ISC_LOG_DEBUG(2),
+ "unsigned DS record");
+ return (DNS_R_NOVALIDSIG);
+ } else
+ result = ISC_R_SUCCESS;
+ } else if (result == ISC_R_NOTFOUND) {
+ /*
+ * We don't have the DS. Find it.
+ */
+ result = create_fetch(val, val->event->name,
+ dns_rdatatype_ds, dsfetched,
+ "validatezonekey");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (DNS_R_WAIT);
+ } else if (result == DNS_R_NCACHENXDOMAIN ||
+ result == DNS_R_NCACHENXRRSET ||
+ result == DNS_R_EMPTYNAME ||
+ result == DNS_R_NXDOMAIN ||
+ result == DNS_R_NXRRSET)
+ {
+ /*
+ * The DS does not exist.
+ */
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ validator_log(val, ISC_LOG_DEBUG(2), "no DS record");
+ return (DNS_R_NOVALIDSIG);
+ }
+ }
+
+ /*
+ * We have a DS set.
+ */
+ INSIST(val->dsset != NULL);
+
+ if (val->dsset->trust < dns_trust_secure) {
+ if (val->mustbesecure) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure");
+ return (DNS_R_MUSTBESECURE);
+ }
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Look through the DS record and find the keys that can sign the
+ * key set and the matching signature. For each such key, attempt
+ * verification.
+ */
+
+ supported_algorithm = ISC_FALSE;
+
+ /*
+ * If DNS_DSDIGEST_SHA256 is present we are required to prefer
+ * it over DNS_DSDIGEST_SHA1. This in practice means that we
+ * need to ignore DNS_DSDIGEST_SHA1 if a DNS_DSDIGEST_SHA256
+ * is present.
+ */
+ digest_type = DNS_DSDIGEST_SHA1;
+ for (result = dns_rdataset_first(val->dsset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(val->dsset)) {
+ dns_rdata_reset(&dsrdata);
+ dns_rdataset_current(val->dsset, &dsrdata);
+ result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (!dns_resolver_algorithm_supported(val->view->resolver,
+ val->event->name,
+ ds.algorithm))
+ continue;
+
+ if (ds.digest_type == DNS_DSDIGEST_SHA256 &&
+ ds.length == ISC_SHA256_DIGESTLENGTH) {
+ digest_type = DNS_DSDIGEST_SHA256;
+ break;
+ }
+ }
+
+ for (result = dns_rdataset_first(val->dsset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(val->dsset))
+ {
+ dns_rdata_reset(&dsrdata);
+ dns_rdataset_current(val->dsset, &dsrdata);
+ result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (!dns_resolver_digest_supported(val->view->resolver,
+ ds.digest_type))
+ continue;
+
+ if (ds.digest_type != digest_type)
+ continue;
+
+ if (!dns_resolver_algorithm_supported(val->view->resolver,
+ val->event->name,
+ ds.algorithm))
+ continue;
+
+ supported_algorithm = ISC_TRUE;
+
+ dns_rdataset_init(&trdataset);
+ dns_rdataset_clone(val->event->rdataset, &trdataset);
+
+ /*
+ * Look for the KEY that matches the DS record.
+ */
+ 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;
+ }
+ if (result != ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "no DNSKEY matching DS");
+ 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;
+ }
+ dns_rdataset_disassociate(&trdataset);
+ if (result == ISC_R_SUCCESS)
+ break;
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "no RRSIG matching DS key");
+ }
+ if (result == ISC_R_SUCCESS) {
+ event->rdataset->trust = dns_trust_secure;
+ event->sigrdataset->trust = dns_trust_secure;
+ validator_log(val, ISC_LOG_DEBUG(3), "marking as secure");
+ return (result);
+ } else if (result == ISC_R_NOMORE && !supported_algorithm) {
+ if (val->mustbesecure) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure");
+ return (DNS_R_MUSTBESECURE);
+ }
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "no supported algorithm/digest (DS)");
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ } else
+ return (DNS_R_NOVALIDSIG);
+}
+
+/*%
+ * Starts a positive response validation.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS Validation completed successfully
+ * \li DNS_R_WAIT Validation has started but is waiting
+ * for an event.
+ * \li Other return codes are possible and all indicate failure.
+ */
+static isc_result_t
+start_positive_validation(dns_validator_t *val) {
+ /*
+ * If this is not a key, go straight into validate().
+ */
+ if (val->event->type != dns_rdatatype_dnskey || !isselfsigned(val))
+ return (validate(val, ISC_FALSE));
+
+ return (validatezonekey(val));
+}
+
+/*%
+ * Look for NODATA at the wildcard and NOWILDCARD proofs in the
+ * previously validated NSEC records. As these proofs are mutually
+ * exclusive we stop when one is found.
+ *
+ * Returns
+ * \li ISC_R_SUCCESS
+ */
+static isc_result_t
+checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
+{
+ dns_name_t *name, *wild;
+ dns_message_t *message = val->event->message;
+ isc_result_t result;
+ isc_boolean_t exists, data;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ wild = dns_fixedname_name(&val->wild);
+
+ if (dns_name_countlabels(wild) == 0) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "in checkwildcard: no wildcard to check");
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_name_format(wild, namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf);
+
+ for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
+ {
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->type != type)
+ continue;
+
+ for (sigrdataset = ISC_LIST_HEAD(name->list);
+ sigrdataset != NULL;
+ sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
+ {
+ if (sigrdataset->type == dns_rdatatype_rrsig &&
+ sigrdataset->covers == rdataset->type)
+ break;
+ }
+ if (sigrdataset == NULL)
+ continue;
+
+ if (rdataset->trust != dns_trust_secure)
+ continue;
+
+ if (rdataset->type == dns_rdatatype_nsec &&
+ ((val->attributes & VALATTR_NEEDNODATA) != 0 ||
+ (val->attributes & VALATTR_NEEDNOWILDCARD) != 0) &&
+ (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
+ (val->attributes & VALATTR_FOUNDNOWILDCARD) == 0 &&
+ nsecnoexistnodata(val, wild, name, rdataset,
+ &exists, &data, NULL)
+ == ISC_R_SUCCESS)
+ {
+ dns_name_t **proofs = val->event->proofs;
+ if (exists && !data)
+ val->attributes |= VALATTR_FOUNDNODATA;
+ if (exists && !data && NEEDNODATA(val))
+ proofs[DNS_VALIDATOR_NODATAPROOF] =
+ name;
+ if (!exists)
+ val->attributes |=
+ VALATTR_FOUNDNOWILDCARD;
+ if (!exists && NEEDNOQNAME(val))
+ proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
+ name;
+ return (ISC_R_SUCCESS);
+ }
+
+ if (rdataset->type == dns_rdatatype_nsec3 &&
+ ((val->attributes & VALATTR_NEEDNODATA) != 0 ||
+ (val->attributes & VALATTR_NEEDNOWILDCARD) != 0) &&
+ (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
+ (val->attributes & VALATTR_FOUNDNOWILDCARD) == 0 &&
+ nsec3noexistnodata(val, wild, name, rdataset,
+ zonename, &exists, &data,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL) == ISC_R_SUCCESS)
+ {
+ dns_name_t **proofs = val->event->proofs;
+ if (exists && !data)
+ val->attributes |= VALATTR_FOUNDNODATA;
+ if (exists && !data && NEEDNODATA(val))
+ proofs[DNS_VALIDATOR_NODATAPROOF] =
+ name;
+ if (!exists)
+ val->attributes |=
+ VALATTR_FOUNDNOWILDCARD;
+ if (!exists && NEEDNOQNAME(val))
+ proofs[DNS_VALIDATOR_NOWILDCARDPROOF] =
+ name;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
+
+static isc_result_t
+findnsec3proofs(dns_validator_t *val) {
+ dns_name_t *name;
+ dns_message_t *message = val->event->message;
+ isc_result_t result;
+ isc_boolean_t exists, data, optout, unknown;
+ isc_boolean_t setclosest, setnearest;
+ dns_fixedname_t fclosest, fnearest, fzonename;
+ dns_name_t *closest, *nearest, *zonename;
+ dns_name_t **proofs = val->event->proofs;
+
+ dns_fixedname_init(&fclosest);
+ dns_fixedname_init(&fnearest);
+ dns_fixedname_init(&fzonename);
+ closest = dns_fixedname_name(&fclosest);
+ nearest = dns_fixedname_name(&fnearest);
+ zonename = dns_fixedname_name(&fzonename);
+
+ for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
+ {
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->type != dns_rdatatype_nsec3)
+ continue;
+
+ for (sigrdataset = ISC_LIST_HEAD(name->list);
+ sigrdataset != NULL;
+ sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
+ {
+ if (sigrdataset->type == dns_rdatatype_rrsig &&
+ sigrdataset->covers == dns_rdatatype_nsec3)
+ break;
+ }
+ if (sigrdataset == NULL)
+ continue;
+
+ if (rdataset->trust != dns_trust_secure)
+ continue;
+
+ result = nsec3noexistnodata(val, val->event->name,
+ name, rdataset,
+ zonename, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL);
+ if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS)
+ return (result);
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ if (dns_name_countlabels(zonename) == 0)
+ return (ISC_R_SUCCESS);
+
+ for (result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
+ {
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->type != dns_rdatatype_nsec3)
+ continue;
+
+ for (sigrdataset = ISC_LIST_HEAD(name->list);
+ sigrdataset != NULL;
+ sigrdataset = ISC_LIST_NEXT(sigrdataset, link))
+ {
+ if (sigrdataset->type == dns_rdatatype_rrsig &&
+ sigrdataset->covers == dns_rdatatype_nsec3)
+ break;
+ }
+ if (sigrdataset == NULL)
+ continue;
+
+ if (rdataset->trust != dns_trust_secure)
+ continue;
+
+ /*
+ * We process all NSEC3 records to find the closest
+ * encloser and nearest name to the closest encloser.
+ */
+ setclosest = setnearest = ISC_FALSE;
+ optout = ISC_FALSE;
+ unknown = ISC_FALSE;
+ result = nsec3noexistnodata(val, val->event->name,
+ name, rdataset,
+ zonename, &exists,
+ &data, &optout, &unknown,
+ &setclosest, &setnearest,
+ closest, nearest);
+ if (setclosest)
+ proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
+ if (unknown)
+ val->attributes |= VALATTR_FOUNDUNKNOWN;
+ if (result != ISC_R_SUCCESS)
+ continue;
+ if (exists && !data && NEEDNODATA(val)) {
+ val->attributes |= VALATTR_FOUNDNODATA;
+ proofs[DNS_VALIDATOR_NODATAPROOF] = name;
+ }
+ if (!exists && setnearest) {
+ val->attributes |= VALATTR_FOUNDNOQNAME;
+ proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
+ if (optout)
+ val->attributes |= VALATTR_FOUNDOPTOUT;
+ }
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ /*
+ * To know we have a valid noqname and optout proofs we need to also
+ * have a valid closest encloser. Otherwise we could still be looking
+ * at proofs from the parent zone.
+ */
+ if (dns_name_countlabels(closest) > 0 &&
+ dns_name_countlabels(nearest) ==
+ dns_name_countlabels(closest) + 1 &&
+ dns_name_issubdomain(nearest, closest))
+ {
+ val->attributes |= VALATTR_FOUNDCLOSEST;
+ result = dns_name_concatenate(dns_wildcardname, closest,
+ dns_fixedname_name(&val->wild),
+ NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ } else {
+ val->attributes &= ~VALATTR_FOUNDNOQNAME;
+ val->attributes &= ~VALATTR_FOUNDOPTOUT;
+ proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL;
+ }
+
+ /*
+ * Do we need to check for the wildcard?
+ */
+ if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
+ (val->attributes & VALATTR_FOUNDCLOSEST) != 0 &&
+ (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
+ (val->attributes & VALATTR_FOUNDNODATA) == 0) ||
+ (val->attributes & VALATTR_NEEDNOWILDCARD) != 0)) {
+ result = checkwildcard(val, dns_rdatatype_nsec3, zonename);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ return (result);
+}
+
+/*%
+ * Prove a negative answer is good or that there is a NOQNAME when the
+ * answer is from a wildcard.
+ *
+ * Loop through the authority section looking for NODATA, NOWILDCARD
+ * and NOQNAME proofs in the NSEC records by calling authvalidated().
+ *
+ * If the required proofs are found we are done.
+ *
+ * If the proofs are not found attempt to prove this is a unsecure
+ * response.
+ */
+static isc_result_t
+nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
+ dns_name_t *name;
+ dns_message_t *message = val->event->message;
+ isc_result_t result;
+
+ if (!resume)
+ result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
+ else {
+ result = ISC_R_SUCCESS;
+ validator_log(val, ISC_LOG_DEBUG(3), "resuming nsecvalidate");
+ }
+
+ for (;
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(message, DNS_SECTION_AUTHORITY))
+ {
+ dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL;
+
+ name = NULL;
+ dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);
+ if (resume) {
+ rdataset = ISC_LIST_NEXT(val->currentset, link);
+ val->currentset = NULL;
+ resume = ISC_FALSE;
+ } else
+ rdataset = ISC_LIST_HEAD(name->list);
+
+ for (;
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ if (rdataset->type == dns_rdatatype_rrsig)
+ continue;
+
+ for (sigrdataset = ISC_LIST_HEAD(name->list);
+ sigrdataset != NULL;
+ sigrdataset = ISC_LIST_NEXT(sigrdataset,
+ link))
+ {
+ if (sigrdataset->type == dns_rdatatype_rrsig &&
+ sigrdataset->covers == rdataset->type)
+ break;
+ }
+ /*
+ * If a signed zone is missing the zone key, bad
+ * things could happen. A query for data in the zone
+ * would lead to a query for the zone key, which
+ * would return a negative answer, which would contain
+ * an SOA and an NSEC signed by the missing key, which
+ * would trigger another query for the DNSKEY (since
+ * the first one is still in progress), and go into an
+ * infinite loop. Avoid that.
+ */
+ if (val->event->type == dns_rdatatype_dnskey &&
+ dns_name_equal(name, val->event->name))
+ {
+ dns_rdata_t nsec = DNS_RDATA_INIT;
+
+ if (rdataset->type != dns_rdatatype_nsec)
+ continue;
+
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_rdataset_current(rdataset, &nsec);
+ if (dns_nsec_typepresent(&nsec,
+ dns_rdatatype_soa))
+ continue;
+ }
+ val->currentset = rdataset;
+ result = create_validator(val, name, rdataset->type,
+ rdataset, sigrdataset,
+ authvalidated,
+ "nsecvalidate");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (DNS_R_WAIT);
+
+ }
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Do we only need to check for NOQNAME? To get here we must have
+ * had a secure wildcard answer.
+ */
+ if ((val->attributes & VALATTR_NEEDNODATA) == 0 &&
+ (val->attributes & VALATTR_NEEDNOWILDCARD) == 0 &&
+ (val->attributes & VALATTR_NEEDNOQNAME) != 0) {
+ if ((val->attributes & VALATTR_FOUNDNOQNAME) == 0)
+ findnsec3proofs(val);
+ if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
+ (val->attributes & VALATTR_FOUNDCLOSEST) != 0) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "noqname proof found");
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "marking as secure");
+ val->event->rdataset->trust = dns_trust_secure;
+ val->event->sigrdataset->trust = dns_trust_secure;
+ return (ISC_R_SUCCESS);
+ } else if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0 &&
+ dns_name_countlabels(dns_fixedname_name(&val->wild))
+ != 0) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "optout proof found");
+ val->event->optout = ISC_TRUE;
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "unknown NSEC3 hash algorithm found");
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ }
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "noqname proof not found");
+ return (DNS_R_NOVALIDNSEC);
+ }
+
+ if ((val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
+ (val->attributes & VALATTR_FOUNDNODATA) == 0)
+ findnsec3proofs(val);
+
+ /*
+ * Do we need to check for the wildcard?
+ */
+ if ((val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
+ (val->attributes & VALATTR_FOUNDCLOSEST) != 0 &&
+ (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
+ (val->attributes & VALATTR_FOUNDNODATA) == 0) ||
+ (val->attributes & VALATTR_NEEDNOWILDCARD) != 0)) {
+ result = checkwildcard(val, dns_rdatatype_nsec, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ if (((val->attributes & VALATTR_NEEDNODATA) != 0 &&
+ ((val->attributes & VALATTR_FOUNDNODATA) != 0 ||
+ (val->attributes & VALATTR_FOUNDOPTOUT) != 0)) ||
+ ((val->attributes & VALATTR_NEEDNOQNAME) != 0 &&
+ (val->attributes & VALATTR_FOUNDNOQNAME) != 0 &&
+ (val->attributes & VALATTR_NEEDNOWILDCARD) != 0 &&
+ (val->attributes & VALATTR_FOUNDNOWILDCARD) != 0 &&
+ (val->attributes & VALATTR_FOUNDCLOSEST) != 0)) {
+ if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0)
+ val->event->optout = ISC_TRUE;
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "nonexistence proof(s) found");
+ return (ISC_R_SUCCESS);
+ }
+ findnsec3proofs(val);
+
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "nonexistence proof(s) not found");
+ val->attributes |= VALATTR_INSECURITY;
+ return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
+}
+
+static isc_boolean_t
+check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
+ dns_rdata_t dsrdata = DNS_RDATA_INIT;
+ dns_rdata_ds_t ds;
+ isc_result_t result;
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdataset_current(rdataset, &dsrdata);
+ result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (dns_resolver_digest_supported(val->view->resolver,
+ ds.digest_type) &&
+ dns_resolver_algorithm_supported(val->view->resolver,
+ name, ds.algorithm)) {
+ dns_rdata_reset(&dsrdata);
+ return (ISC_TRUE);
+ }
+ dns_rdata_reset(&dsrdata);
+ }
+ return (ISC_FALSE);
+}
+
+/*%
+ * Callback from fetching a DLV record.
+ *
+ * Resumes the DLV lookup process.
+ */
+static void
+dlvfetched(isc_task_t *task, isc_event_t *event) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_fetchevent_t *devent;
+ dns_validator_t *val;
+ isc_boolean_t want_destroy;
+ isc_result_t eresult;
+ isc_result_t result;
+
+ UNUSED(task);
+ INSIST(event->ev_type == DNS_EVENT_FETCHDONE);
+ devent = (dns_fetchevent_t *)event;
+ val = devent->ev_arg;
+ 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);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ isc_event_free(&event);
+ dns_resolver_destroyfetch(&val->fetch);
+
+ INSIST(val->event != NULL);
+ validator_log(val, ISC_LOG_DEBUG(3), "in dlvfetched: %s",
+ dns_result_totext(eresult));
+
+ LOCK(&val->lock);
+ if (eresult == ISC_R_SUCCESS) {
+ dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
+ sizeof(namebuf));
+ dns_rdataset_clone(&val->frdataset, &val->dlv);
+ val->havedlvsep = ISC_TRUE;
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
+ dlv_validator_start(val);
+ } else if (eresult == DNS_R_NXRRSET ||
+ eresult == DNS_R_NXDOMAIN ||
+ eresult == DNS_R_NCACHENXRRSET ||
+ eresult == DNS_R_NCACHENXDOMAIN) {
+ result = finddlvsep(val, ISC_TRUE);
+ if (result == ISC_R_SUCCESS) {
+ dns_name_format(dns_fixedname_name(&val->dlvsep),
+ namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
+ namebuf);
+ dlv_validator_start(val);
+ } else if (result == ISC_R_NOTFOUND) {
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
+ markanswer(val);
+ validator_done(val, ISC_R_SUCCESS);
+ } else {
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
+ dns_result_totext(result));
+ if (result != DNS_R_WAIT)
+ validator_done(val, result);
+ }
+ } else {
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
+ dns_result_totext(eresult));
+ validator_done(val, eresult);
+ }
+ want_destroy = exit_check(val);
+ UNLOCK(&val->lock);
+ if (want_destroy)
+ destroy(val);
+}
+
+/*%
+ * Start the DLV lookup proccess.
+ *
+ * Returns
+ * \li ISC_R_SUCCESS
+ * \li DNS_R_WAIT
+ * \li Others on validation failures.
+ */
+static isc_result_t
+startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ isc_result_t result;
+
+ INSIST(!DLVTRIED(val));
+
+ val->attributes |= VALATTR_DLVTRIED;
+
+ dns_name_format(unsecure, namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "plain DNSSEC returns unsecure (%s): looking for DLV",
+ namebuf);
+
+ if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
+ validator_log(val, ISC_LOG_WARNING, "must be secure failure");
+ return (DNS_R_MUSTBESECURE);
+ }
+
+ val->dlvlabels = dns_name_countlabels(unsecure) - 1;
+ result = finddlvsep(val, ISC_FALSE);
+ if (result == ISC_R_NOTFOUND) {
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ }
+ if (result != ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV lookup: %s",
+ dns_result_totext(result));
+ return (result);
+ }
+ dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
+ sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
+ dlv_validator_start(val);
+ return (DNS_R_WAIT);
+}
+
+/*%
+ * Continue the DLV lookup process.
+ *
+ * Returns
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOTFOUND
+ * \li DNS_R_WAIT
+ * \li Others on validation failure.
+ */
+static isc_result_t
+finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t dlvfixed;
+ dns_name_t *dlvname;
+ dns_name_t *dlvsep;
+ dns_name_t noroot;
+ isc_result_t result;
+ unsigned int labels;
+
+ INSIST(val->view->dlv != NULL);
+
+ if (!resume) {
+
+ if (dns_name_issubdomain(val->event->name, val->view->dlv)) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure");
+ return (DNS_R_MUSTBESECURE);
+ }
+
+ dns_fixedname_init(&val->dlvsep);
+ dlvsep = dns_fixedname_name(&val->dlvsep);
+ dns_name_copy(val->event->name, dlvsep, NULL);
+ /*
+ * If this is a response to a DS query, we need to look in
+ * the parent zone for the trust anchor.
+ */
+ if (val->event->type == dns_rdatatype_ds) {
+ labels = dns_name_countlabels(dlvsep);
+ if (labels == 0)
+ return (ISC_R_NOTFOUND);
+ dns_name_getlabelsequence(dlvsep, 1, labels - 1,
+ dlvsep);
+ }
+ } else {
+ dlvsep = dns_fixedname_name(&val->dlvsep);
+ labels = dns_name_countlabels(dlvsep);
+ dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
+ }
+ dns_name_init(&noroot, NULL);
+ dns_fixedname_init(&dlvfixed);
+ dlvname = dns_fixedname_name(&dlvfixed);
+ labels = dns_name_countlabels(dlvsep);
+ if (labels == 0)
+ return (ISC_R_NOTFOUND);
+ dns_name_getlabelsequence(dlvsep, 0, labels - 1, &noroot);
+ result = dns_name_concatenate(&noroot, val->view->dlv, dlvname, NULL);
+ while (result == ISC_R_NOSPACE) {
+ labels = dns_name_countlabels(dlvsep);
+ dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
+ dns_name_getlabelsequence(dlvsep, 0, labels - 2, &noroot);
+ result = dns_name_concatenate(&noroot, val->view->dlv,
+ dlvname, NULL);
+ }
+ if (result != ISC_R_SUCCESS) {
+ validator_log(val, ISC_LOG_DEBUG(2), "DLV concatenate failed");
+ return (DNS_R_NOVALIDSIG);
+ }
+
+ while (dns_name_countlabels(dlvname) >=
+ dns_name_countlabels(val->view->dlv) + val->dlvlabels) {
+ dns_name_format(dlvname, namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV %s",
+ namebuf);
+ result = view_find(val, dlvname, dns_rdatatype_dlv);
+ if (result == ISC_R_SUCCESS) {
+ if (val->frdataset.trust < dns_trust_secure)
+ return (DNS_R_NOVALIDSIG);
+ val->havedlvsep = ISC_TRUE;
+ dns_rdataset_clone(&val->frdataset, &val->dlv);
+ return (ISC_R_SUCCESS);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ result = create_fetch(val, dlvname, dns_rdatatype_dlv,
+ dlvfetched, "finddlvsep");
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (DNS_R_WAIT);
+ }
+ if (result != DNS_R_NXRRSET &&
+ result != DNS_R_NXDOMAIN &&
+ result != DNS_R_EMPTYNAME &&
+ result != DNS_R_NCACHENXRRSET &&
+ result != DNS_R_NCACHENXDOMAIN)
+ return (result);
+ /*
+ * Strip first labels from both dlvsep and dlvname.
+ */
+ labels = dns_name_countlabels(dlvsep);
+ if (labels == 0)
+ break;
+ dns_name_getlabelsequence(dlvsep, 1, labels - 1, dlvsep);
+ labels = dns_name_countlabels(dlvname);
+ dns_name_getlabelsequence(dlvname, 1, labels - 1, dlvname);
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+/*%
+ * proveunsecure walks down from the SEP looking for a break in the
+ * chain of trust. That occurs when we can prove the DS record does
+ * not exist at a delegation point or the DS exists at a delegation
+ * but we don't support the algorithm/digest.
+ *
+ * If DLV is active and we look for a DLV record at or below the
+ * point we go insecure. If found we restart the validation process.
+ * If not found or DLV isn't active we mark the response as a answer.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS val->event->name is in a unsecure zone
+ * \li DNS_R_WAIT validation is in progress.
+ * \li DNS_R_MUSTBESECURE val->event->name is supposed to be secure
+ * (policy) but we proved that it is unsecure.
+ * \li DNS_R_NOVALIDSIG
+ * \li DNS_R_NOVALIDNSEC
+ * \li DNS_R_NOTINSECURE
+ */
+static isc_result_t
+proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
+{
+ isc_result_t result;
+ dns_fixedname_t fixedsecroot;
+ dns_name_t *secroot;
+ dns_name_t *tname;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ dns_fixedname_init(&fixedsecroot);
+ secroot = dns_fixedname_name(&fixedsecroot);
+ if (val->havedlvsep)
+ dns_name_copy(dns_fixedname_name(&val->dlvsep), secroot, NULL);
+ else {
+ dns_name_copy(val->event->name, secroot, NULL);
+ /*
+ * If this is a response to a DS query, we need to look in
+ * the parent zone for the trust anchor.
+ */
+ if (val->event->type == dns_rdatatype_ds &&
+ dns_name_countlabels(secroot) > 1U)
+ dns_name_split(secroot, 1, NULL, secroot);
+ result = dns_keytable_finddeepestmatch(val->keytable,
+ secroot, secroot);
+
+ if (result == ISC_R_NOTFOUND) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "not beneath secure root");
+ if (val->mustbesecure) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure");
+ result = DNS_R_MUSTBESECURE;
+ goto out;
+ }
+ if (val->view->dlv == NULL || DLVTRIED(val)) {
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ }
+ return (startfinddlvsep(val, dns_rootname));
+ } else if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ if (!resume) {
+ /*
+ * We are looking for breaks below the SEP so add a label.
+ */
+ val->labels = dns_name_countlabels(secroot) + 1;
+ } else {
+ validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
+ /*
+ * 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
+ * resolver is concerned. Fall back to DLV if available.
+ */
+ if (have_ds && val->frdataset.trust >= dns_trust_secure &&
+ !check_ds(val, dns_fixedname_name(&val->fname),
+ &val->frdataset)) {
+ dns_name_format(dns_fixedname_name(&val->fname),
+ namebuf, sizeof(namebuf));
+ if ((val->view->dlv == NULL || DLVTRIED(val)) &&
+ val->mustbesecure) {
+ validator_log(val, ISC_LOG_WARNING,
+ "must be secure failure at '%s'",
+ namebuf);
+ result = DNS_R_MUSTBESECURE;
+ goto out;
+ }
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "no supported algorithm/digest (%s/DS)",
+ namebuf);
+ if (val->view->dlv == NULL || DLVTRIED(val)) {
+ markanswer(val);
+ result = ISC_R_SUCCESS;
+ goto out;
+ }
+ result = startfinddlvsep(val,
+ dns_fixedname_name(&val->fname));
+ goto out;
+ }
+ val->labels++;
+ }
+
+ for (;
+ val->labels <= dns_name_countlabels(val->event->name);
+ val->labels++)
+ {
+
+ dns_fixedname_init(&val->fname);
+ tname = dns_fixedname_name(&val->fname);
+ if (val->labels == dns_name_countlabels(val->event->name))
+ dns_name_copy(val->event->name, tname, NULL);
+ else
+ dns_name_split(val->event->name, val->labels,
+ NULL, tname);
+
+ dns_name_format(tname, namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "checking existence of DS at '%s'",
+ namebuf);
+
+ result = view_find(val, tname, dns_rdatatype_ds);
+
+ if (result == DNS_R_NXRRSET || result == DNS_R_NCACHENXRRSET) {
+ /*
+ * There is no DS. If this is a delegation,
+ * we maybe done.
+ */
+ if (val->frdataset.trust == dns_trust_pending) {
+ result = create_fetch(val, tname,
+ dns_rdatatype_ds,
+ dsfetched2,
+ "proveunsecure");
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ return (DNS_R_WAIT);
+ }
+ if (val->frdataset.trust < dns_trust_secure) {
+ /*
+ * This shouldn't happen, since the negative
+ * response should have been validated. Since
+ * there's no way of validating existing
+ * negative response blobs, give up.
+ */
+ 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");
+ return (DNS_R_MUSTBESECURE);
+ }
+ if (val->view->dlv == NULL || DLVTRIED(val)) {
+ markanswer(val);
+ return (ISC_R_SUCCESS);
+ }
+ return (startfinddlvsep(val, tname));
+ }
+ continue;
+ } else if (result == ISC_R_SUCCESS) {
+ /*
+ * There is a DS here. Verify that it's secure and
+ * continue.
+ */
+ if (val->frdataset.trust >= dns_trust_secure) {
+ if (!check_ds(val, tname, &val->frdataset)) {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "no supported algorithm/"
+ "digest (%s/DS)", namebuf);
+ if (val->mustbesecure) {
+ validator_log(val,
+ ISC_LOG_WARNING,
+ "must be secure failure");
+ result = DNS_R_MUSTBESECURE;
+ goto out;
+ }
+ if (val->view->dlv == NULL ||
+ DLVTRIED(val)) {
+ markanswer(val);
+ result = ISC_R_SUCCESS;
+ goto out;
+ }
+ result = startfinddlvsep(val, tname);
+ goto out;
+ }
+ continue;
+ }
+ else if (!dns_rdataset_isassociated(&val->fsigrdataset))
+ {
+ result = DNS_R_NOVALIDSIG;
+ goto out;
+ }
+ result = create_validator(val, tname, dns_rdatatype_ds,
+ &val->frdataset,
+ &val->fsigrdataset,
+ dsvalidated,
+ "proveunsecure");
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ return (DNS_R_WAIT);
+ } else if (result == DNS_R_NXDOMAIN ||
+ result == DNS_R_NCACHENXDOMAIN) {
+ /*
+ * This is not a zone cut. Assuming things are
+ * as expected, continue.
+ */
+ if (!dns_rdataset_isassociated(&val->frdataset)) {
+ /*
+ * There should be an NSEC here, since we
+ * are still in a secure zone.
+ */
+ result = DNS_R_NOVALIDNSEC;
+ goto out;
+ } else if (val->frdataset.trust < dns_trust_secure) {
+ /*
+ * This shouldn't happen, since the negative
+ * response should have been validated. Since
+ * there's no way of validating existing
+ * negative response blobs, give up.
+ */
+ result = DNS_R_NOVALIDSIG;
+ goto out;
+ }
+ continue;
+ } else if (result == ISC_R_NOTFOUND) {
+ /*
+ * We don't know anything about the DS. Find it.
+ */
+ result = create_fetch(val, tname, dns_rdatatype_ds,
+ dsfetched2, "proveunsecure");
+ if (result != ISC_R_SUCCESS)
+ goto out;
+ return (DNS_R_WAIT);
+ }
+ }
+
+/*
+ if ((val->attributes & VALATTR_NEEDOPTOUT) == 0 &&
+ val->event->message != NULL) {
+ val->attributes |= VALATTR_NEEDOPTOUT;
+ return (nsecvalidate(val, ISC_FALSE));
+ }
+*/
+
+ validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed");
+ return (DNS_R_NOTINSECURE); /* Couldn't complete insecurity proof */
+
+ out:
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ return (result);
+}
+
+/*%
+ * Reset state and revalidate the answer using DLV.
+ */
+static void
+dlv_validator_start(dns_validator_t *val) {
+ isc_event_t *event;
+
+ validator_log(val, ISC_LOG_DEBUG(3), "dlv_validator_start");
+
+ /*
+ * Reset state and try again.
+ */
+ val->attributes &= VALATTR_DLVTRIED;
+ val->options &= ~DNS_VALIDATOR_DLV;
+
+ event = (isc_event_t *)val->event;
+ isc_task_send(val->task, &event);
+}
+
+/*%
+ * Start the validation process.
+ *
+ * Attempt to valididate the answer based on the category it appears to
+ * fall in.
+ * \li 1. secure positive answer.
+ * \li 2. unsecure positive answer.
+ * \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.
+ */
+static void
+validator_start(isc_task_t *task, isc_event_t *event) {
+ dns_validator_t *val;
+ dns_validatorevent_t *vevent;
+ isc_boolean_t want_destroy = ISC_FALSE;
+ isc_result_t result = ISC_R_FAILURE;
+
+ UNUSED(task);
+ REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART);
+ vevent = (dns_validatorevent_t *)event;
+ val = vevent->validator;
+
+ /* If the validator has been cancelled, val->event == NULL */
+ if (val->event == NULL)
+ return;
+
+ if (DLVTRIED(val))
+ validator_log(val, ISC_LOG_DEBUG(3), "restarting using DLV");
+ else
+ validator_log(val, ISC_LOG_DEBUG(3), "starting");
+
+ LOCK(&val->lock);
+
+ if ((val->options & DNS_VALIDATOR_DLV) != 0 &&
+ val->event->rdataset != NULL) {
+ validator_log(val, ISC_LOG_DEBUG(3), "looking for DLV");
+ result = startfinddlvsep(val, dns_rootname);
+ } else if (val->event->rdataset != NULL &&
+ val->event->sigrdataset != NULL) {
+ isc_result_t saved_result;
+
+ /*
+ * This looks like a simple validation. We say "looks like"
+ * because it might end up requiring an insecurity proof.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "attempting positive response validation");
+
+ INSIST(dns_rdataset_isassociated(val->event->rdataset));
+ INSIST(dns_rdataset_isassociated(val->event->sigrdataset));
+ result = start_positive_validation(val);
+ if (result == DNS_R_NOVALIDSIG &&
+ (val->attributes & VALATTR_TRIEDVERIFY) == 0)
+ {
+ saved_result = result;
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "falling back to insecurity proof");
+ val->attributes |= VALATTR_INSECURITY;
+ result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
+ if (result == DNS_R_NOTINSECURE)
+ result = saved_result;
+ }
+ } else if (val->event->rdataset != NULL) {
+ /*
+ * This is either an unsecure subdomain or a response from
+ * a broken server.
+ */
+ INSIST(dns_rdataset_isassociated(val->event->rdataset));
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "attempting insecurity proof");
+
+ val->attributes |= VALATTR_INSECURITY;
+ result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
+ } else if (val->event->rdataset == NULL &&
+ val->event->sigrdataset == NULL)
+ {
+ /*
+ * This is a nonexistence validation.
+ */
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "attempting negative response validation");
+
+ if (val->event->message->rcode == dns_rcode_nxdomain) {
+ val->attributes |= VALATTR_NEEDNOQNAME;
+ val->attributes |= VALATTR_NEEDNOWILDCARD;
+ } else
+ val->attributes |= VALATTR_NEEDNODATA;
+ result = nsecvalidate(val, ISC_FALSE);
+ } else {
+ /*
+ * This shouldn't happen.
+ */
+ INSIST(0);
+ }
+
+ if (result != DNS_R_WAIT) {
+ want_destroy = exit_check(val);
+ validator_done(val, result);
+ }
+
+ UNLOCK(&val->lock);
+ if (want_destroy)
+ destroy(val);
+}
+
+isc_result_t
+dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_message_t *message, unsigned int options,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_validator_t **validatorp)
+{
+ isc_result_t result;
+ dns_validator_t *val;
+ isc_task_t *tclone;
+ dns_validatorevent_t *event;
+
+ REQUIRE(name != NULL);
+ REQUIRE(rdataset != NULL ||
+ (rdataset == NULL && sigrdataset == NULL && message != NULL));
+ REQUIRE(validatorp != NULL && *validatorp == NULL);
+
+ tclone = NULL;
+ result = ISC_R_FAILURE;
+
+ val = isc_mem_get(view->mctx, sizeof(*val));
+ if (val == NULL)
+ 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,
+ validator_start, NULL,
+ sizeof(dns_validatorevent_t));
+ if (event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_val;
+ }
+ isc_task_attach(task, &tclone);
+ event->validator = val;
+ event->result = ISC_R_FAILURE;
+ event->name = name;
+ event->type = type;
+ event->rdataset = rdataset;
+ event->sigrdataset = sigrdataset;
+ event->message = message;
+ memset(event->proofs, 0, sizeof(event->proofs));
+ event->optout = ISC_FALSE;
+ result = isc_mutex_init(&val->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_event;
+ val->event = event;
+ val->options = options;
+ val->attributes = 0;
+ val->fetch = NULL;
+ val->subvalidator = NULL;
+ val->parent = NULL;
+ val->keytable = NULL;
+ dns_keytable_attach(val->view->secroots, &val->keytable);
+ val->keynode = NULL;
+ val->key = NULL;
+ val->siginfo = NULL;
+ val->task = task;
+ val->action = action;
+ val->arg = arg;
+ val->labels = 0;
+ val->currentset = NULL;
+ val->keyset = NULL;
+ val->dsset = NULL;
+ dns_rdataset_init(&val->dlv);
+ val->seensig = ISC_FALSE;
+ val->havedlvsep = ISC_FALSE;
+ val->depth = 0;
+ val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
+ dns_rdataset_init(&val->frdataset);
+ dns_rdataset_init(&val->fsigrdataset);
+ dns_fixedname_init(&val->wild);
+ dns_fixedname_init(&val->nearest);
+ dns_fixedname_init(&val->closest);
+ ISC_LINK_INIT(val, link);
+ val->magic = VALIDATOR_MAGIC;
+
+ if ((options & DNS_VALIDATOR_DEFER) == 0)
+ isc_task_send(task, ISC_EVENT_PTR(&event));
+
+ *validatorp = val;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_event:
+ isc_task_detach(&tclone);
+ isc_event_free(ISC_EVENT_PTR(&event));
+
+ cleanup_val:
+ dns_view_weakdetach(&val->view);
+ isc_mem_put(view->mctx, val, sizeof(*val));
+
+ return (result);
+}
+
+void
+dns_validator_send(dns_validator_t *validator) {
+ isc_event_t *event;
+ REQUIRE(VALID_VALIDATOR(validator));
+
+ LOCK(&validator->lock);
+
+ INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0);
+ event = (isc_event_t *)validator->event;
+ validator->options &= ~DNS_VALIDATOR_DEFER;
+ UNLOCK(&validator->lock);
+
+ isc_task_send(validator->task, ISC_EVENT_PTR(&event));
+}
+
+void
+dns_validator_cancel(dns_validator_t *validator) {
+ REQUIRE(VALID_VALIDATOR(validator));
+
+ LOCK(&validator->lock);
+
+ validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel");
+
+ if (validator->event != NULL) {
+ if (validator->fetch != NULL)
+ dns_resolver_cancelfetch(validator->fetch);
+
+ if (validator->subvalidator != NULL)
+ dns_validator_cancel(validator->subvalidator);
+ if ((validator->options & DNS_VALIDATOR_DEFER) != 0) {
+ isc_task_t *task = validator->event->ev_sender;
+ validator->options &= ~DNS_VALIDATOR_DEFER;
+ isc_event_free((isc_event_t **)&validator->event);
+ isc_task_detach(&task);
+ }
+ validator->attributes |= VALATTR_CANCELED;
+ }
+ UNLOCK(&validator->lock);
+}
+
+static void
+destroy(dns_validator_t *val) {
+ isc_mem_t *mctx;
+
+ REQUIRE(SHUTDOWN(val));
+ REQUIRE(val->event == NULL);
+ REQUIRE(val->fetch == NULL);
+
+ if (val->keynode != NULL)
+ dns_keytable_detachkeynode(val->keytable, &val->keynode);
+ else if (val->key != NULL)
+ dst_key_free(&val->key);
+ if (val->keytable != NULL)
+ dns_keytable_detach(&val->keytable);
+ if (val->subvalidator != NULL)
+ dns_validator_destroy(&val->subvalidator);
+ if (val->havedlvsep)
+ dns_rdataset_disassociate(&val->dlv);
+ if (dns_rdataset_isassociated(&val->frdataset))
+ dns_rdataset_disassociate(&val->frdataset);
+ if (dns_rdataset_isassociated(&val->fsigrdataset))
+ dns_rdataset_disassociate(&val->fsigrdataset);
+ mctx = val->view->mctx;
+ if (val->siginfo != NULL)
+ isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo));
+ DESTROYLOCK(&val->lock);
+ dns_view_weakdetach(&val->view);
+ val->magic = 0;
+ isc_mem_put(mctx, val, sizeof(*val));
+}
+
+void
+dns_validator_destroy(dns_validator_t **validatorp) {
+ dns_validator_t *val;
+ isc_boolean_t want_destroy = ISC_FALSE;
+
+ REQUIRE(validatorp != NULL);
+ val = *validatorp;
+ REQUIRE(VALID_VALIDATOR(val));
+
+ LOCK(&val->lock);
+
+ val->attributes |= VALATTR_SHUTDOWN;
+ validator_log(val, ISC_LOG_DEBUG(3), "dns_validator_destroy");
+
+ want_destroy = exit_check(val);
+
+ UNLOCK(&val->lock);
+
+ if (want_destroy)
+ destroy(val);
+
+ *validatorp = NULL;
+}
+
+static void
+validator_logv(dns_validator_t *val, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *fmt, va_list ap)
+{
+ char msgbuf[2048];
+ static const char spaces[] = " *";
+ int depth = val->depth * 2;
+
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+
+ if ((unsigned int) depth >= sizeof spaces)
+ depth = sizeof spaces - 1;
+
+ if (val->event != NULL && val->event->name != NULL) {
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_name_format(val->event->name, namebuf, sizeof(namebuf));
+ dns_rdatatype_format(val->event->type, typebuf,
+ sizeof(typebuf));
+ isc_log_write(dns_lctx, category, module, level,
+ "%.*svalidating @%p: %s %s: %s", depth, spaces,
+ val, namebuf, typebuf, msgbuf);
+ } else {
+ isc_log_write(dns_lctx, category, module, level,
+ "%.*svalidator @%p: %s", depth, spaces,
+ val, msgbuf);
+ }
+}
+
+static void
+validator_log(dns_validator_t *val, int level, const char *fmt, ...) {
+ va_list ap;
+
+ if (! isc_log_wouldlog(dns_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+
+ validator_logv(val, DNS_LOGCATEGORY_DNSSEC,
+ DNS_LOGMODULE_VALIDATOR, level, fmt, ap);
+ va_end(ap);
+}
+
+static void
+validator_logcreate(dns_validator_t *val,
+ dns_name_t *name, dns_rdatatype_t type,
+ const char *caller, const char *operation)
+{
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+
+ dns_name_format(name, namestr, sizeof(namestr));
+ dns_rdatatype_format(type, typestr, sizeof(typestr));
+ validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s",
+ caller, operation, namestr, typestr);
+}
diff --git a/lib/dns/version.c b/lib/dns/version.c
new file mode 100644
index 0000000..fbc8889
--- /dev/null
+++ b/lib/dns/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: version.c,v 1.15 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <dns/version.h>
+
+const char dns_version[] = VERSION;
+
+const unsigned int dns_libinterface = LIBINTERFACE;
+const unsigned int dns_librevision = LIBREVISION;
+const unsigned int dns_libage = LIBAGE;
diff --git a/lib/dns/view.c b/lib/dns/view.c
new file mode 100644
index 0000000..ba5a811
--- /dev/null
+++ b/lib/dns/view.c
@@ -0,0 +1,1467 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: view.c,v 1.150 2008/06/17 03:14:20 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/hash.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <dns/acache.h>
+#include <dns/acl.h>
+#include <dns/adb.h>
+#include <dns/cache.h>
+#include <dns/db.h>
+#include <dns/dlz.h>
+#include <dns/events.h>
+#include <dns/forward.h>
+#include <dns/keytable.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/order.h>
+#include <dns/peer.h>
+#include <dns/rdataset.h>
+#include <dns/request.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/stats.h>
+#include <dns/tsig.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+#define RESSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0)
+#define ADBSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
+#define REQSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
+
+#define DNS_VIEW_DELONLYHASH 111
+
+static void resolver_shutdown(isc_task_t *task, isc_event_t *event);
+static void adb_shutdown(isc_task_t *task, isc_event_t *event);
+static void req_shutdown(isc_task_t *task, isc_event_t *event);
+
+isc_result_t
+dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
+ const char *name, dns_view_t **viewp)
+{
+ dns_view_t *view;
+ isc_result_t result;
+
+ /*
+ * Create a view.
+ */
+
+ REQUIRE(name != NULL);
+ REQUIRE(viewp != NULL && *viewp == NULL);
+
+ view = isc_mem_get(mctx, sizeof(*view));
+ if (view == NULL)
+ return (ISC_R_NOMEMORY);
+ view->name = isc_mem_strdup(mctx, name);
+ if (view->name == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_view;
+ }
+ result = isc_mutex_init(&view->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_name;
+
+ view->zonetable = NULL;
+ result = dns_zt_create(mctx, rdclass, &view->zonetable);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_zt_create() failed: %s",
+ isc_result_totext(result));
+ 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;
+ }
+ view->fwdtable = NULL;
+ result = dns_fwdtable_create(mctx, &view->fwdtable);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_fwdtable_create() failed: %s",
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup_trustedkeys;
+ }
+
+ view->acache = NULL;
+ view->cache = NULL;
+ view->cachedb = NULL;
+ view->dlzdatabase = NULL;
+ view->hints = NULL;
+ view->resolver = NULL;
+ view->adb = NULL;
+ view->requestmgr = NULL;
+ view->mctx = mctx;
+ view->rdclass = rdclass;
+ view->frozen = ISC_FALSE;
+ view->task = NULL;
+ result = isc_refcount_init(&view->references, 1);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_fwdtable;
+ view->weakrefs = 0;
+ view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
+ DNS_VIEWATTR_REQSHUTDOWN);
+ view->statickeys = NULL;
+ view->dynamickeys = NULL;
+ view->matchclients = NULL;
+ view->matchdestinations = NULL;
+ view->matchrecursiveonly = ISC_FALSE;
+ result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_references;
+ view->peers = NULL;
+ view->order = NULL;
+ view->delonly = NULL;
+ view->rootdelonly = ISC_FALSE;
+ view->rootexclude = NULL;
+ view->resstats = NULL;
+ view->resquerystats = NULL;
+
+ /*
+ * Initialize configuration data with default values.
+ */
+ view->recursion = ISC_TRUE;
+ view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */
+ view->additionalfromcache = ISC_TRUE;
+ view->additionalfromauth = ISC_TRUE;
+ view->enablednssec = ISC_TRUE;
+ view->enablevalidation = ISC_TRUE;
+ view->acceptexpired = ISC_FALSE;
+ view->minimalresponses = ISC_FALSE;
+ view->transfer_format = dns_one_answer;
+ view->queryacl = NULL;
+ view->queryonacl = NULL;
+ view->recursionacl = NULL;
+ view->recursiononacl = NULL;
+ view->sortlist = NULL;
+ view->transferacl = NULL;
+ view->notifyacl = NULL;
+ view->updateacl = NULL;
+ view->upfwdacl = NULL;
+ view->requestixfr = ISC_TRUE;
+ view->provideixfr = ISC_TRUE;
+ view->maxcachettl = 7 * 24 * 3600;
+ view->maxncachettl = 3 * 3600;
+ view->dstport = 53;
+ view->preferred_glue = 0;
+ view->flush = ISC_FALSE;
+ view->dlv = NULL;
+ view->maxudp = 0;
+ dns_fixedname_init(&view->dlv_fixed);
+
+ result = dns_order_create(view->mctx, &view->order);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_dynkeys;
+
+ result = dns_peerlist_new(view->mctx, &view->peers);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_order;
+
+ result = dns_aclenv_init(view->mctx, &view->aclenv);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_peerlist;
+
+ ISC_LINK_INIT(view, link);
+ ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
+ DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
+ view, NULL, NULL, NULL);
+ ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
+ DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown,
+ view, NULL, NULL, NULL);
+ ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
+ DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
+ view, NULL, NULL, NULL);
+ view->magic = DNS_VIEW_MAGIC;
+
+ *viewp = view;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_peerlist:
+ dns_peerlist_detach(&view->peers);
+
+ cleanup_order:
+ dns_order_detach(&view->order);
+
+ cleanup_dynkeys:
+ dns_tsigkeyring_destroy(&view->dynamickeys);
+
+ cleanup_references:
+ isc_refcount_destroy(&view->references);
+
+ cleanup_fwdtable:
+ dns_fwdtable_destroy(&view->fwdtable);
+
+ cleanup_trustedkeys:
+ dns_keytable_detach(&view->trustedkeys);
+
+ cleanup_secroots:
+ dns_keytable_detach(&view->secroots);
+
+ cleanup_zt:
+ dns_zt_detach(&view->zonetable);
+
+ cleanup_mutex:
+ DESTROYLOCK(&view->lock);
+
+ cleanup_name:
+ isc_mem_free(mctx, view->name);
+
+ cleanup_view:
+ isc_mem_put(mctx, view, sizeof(*view));
+
+ return (result);
+}
+
+static inline void
+destroy(dns_view_t *view) {
+ REQUIRE(!ISC_LINK_LINKED(view, link));
+ REQUIRE(isc_refcount_current(&view->references) == 0);
+ REQUIRE(view->weakrefs == 0);
+ REQUIRE(RESSHUTDOWN(view));
+ REQUIRE(ADBSHUTDOWN(view));
+ REQUIRE(REQSHUTDOWN(view));
+
+ if (view->order != NULL)
+ dns_order_detach(&view->order);
+ if (view->peers != NULL)
+ dns_peerlist_detach(&view->peers);
+ if (view->dynamickeys != NULL)
+ dns_tsigkeyring_destroy(&view->dynamickeys);
+ if (view->statickeys != NULL)
+ dns_tsigkeyring_destroy(&view->statickeys);
+ if (view->adb != NULL)
+ dns_adb_detach(&view->adb);
+ if (view->resolver != NULL)
+ dns_resolver_detach(&view->resolver);
+ if (view->acache != NULL) {
+ if (view->cachedb != NULL)
+ dns_acache_putdb(view->acache, view->cachedb);
+ dns_acache_detach(&view->acache);
+ }
+ if (view->requestmgr != NULL)
+ dns_requestmgr_detach(&view->requestmgr);
+ if (view->task != NULL)
+ isc_task_detach(&view->task);
+ if (view->hints != NULL)
+ dns_db_detach(&view->hints);
+ if (view->dlzdatabase != NULL)
+ dns_dlzdestroy(&view->dlzdatabase);
+ if (view->cachedb != NULL)
+ dns_db_detach(&view->cachedb);
+ if (view->cache != NULL)
+ dns_cache_detach(&view->cache);
+ if (view->matchclients != NULL)
+ dns_acl_detach(&view->matchclients);
+ if (view->matchdestinations != NULL)
+ dns_acl_detach(&view->matchdestinations);
+ if (view->queryacl != NULL)
+ dns_acl_detach(&view->queryacl);
+ if (view->queryonacl != NULL)
+ dns_acl_detach(&view->queryonacl);
+ if (view->recursionacl != NULL)
+ dns_acl_detach(&view->recursionacl);
+ if (view->recursiononacl != NULL)
+ dns_acl_detach(&view->recursiononacl);
+ if (view->sortlist != NULL)
+ dns_acl_detach(&view->sortlist);
+ if (view->transferacl != NULL)
+ dns_acl_detach(&view->transferacl);
+ if (view->notifyacl != NULL)
+ dns_acl_detach(&view->notifyacl);
+ if (view->updateacl != NULL)
+ dns_acl_detach(&view->updateacl);
+ if (view->upfwdacl != NULL)
+ dns_acl_detach(&view->upfwdacl);
+ if (view->delonly != NULL) {
+ dns_name_t *name;
+ int i;
+
+ for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
+ name = ISC_LIST_HEAD(view->delonly[i]);
+ while (name != NULL) {
+ ISC_LIST_UNLINK(view->delonly[i], name, link);
+ dns_name_free(name, view->mctx);
+ isc_mem_put(view->mctx, name, sizeof(*name));
+ name = ISC_LIST_HEAD(view->delonly[i]);
+ }
+ }
+ isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) *
+ DNS_VIEW_DELONLYHASH);
+ view->delonly = NULL;
+ }
+ if (view->rootexclude != NULL) {
+ dns_name_t *name;
+ int i;
+
+ for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
+ name = ISC_LIST_HEAD(view->rootexclude[i]);
+ while (name != NULL) {
+ ISC_LIST_UNLINK(view->rootexclude[i],
+ name, link);
+ dns_name_free(name, view->mctx);
+ isc_mem_put(view->mctx, name, sizeof(*name));
+ name = ISC_LIST_HEAD(view->rootexclude[i]);
+ }
+ }
+ isc_mem_put(view->mctx, view->rootexclude,
+ sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
+ view->rootexclude = NULL;
+ }
+ if (view->resstats != NULL)
+ dns_stats_detach(&view->resstats);
+ if (view->resquerystats != NULL)
+ dns_stats_detach(&view->resquerystats);
+ dns_keytable_detach(&view->trustedkeys);
+ dns_keytable_detach(&view->secroots);
+ dns_fwdtable_destroy(&view->fwdtable);
+ dns_aclenv_destroy(&view->aclenv);
+ DESTROYLOCK(&view->lock);
+ isc_refcount_destroy(&view->references);
+ isc_mem_free(view->mctx, view->name);
+ isc_mem_put(view->mctx, view, sizeof(*view));
+}
+
+/*
+ * Return true iff 'view' may be freed.
+ * The caller must be holding the view lock.
+ */
+static isc_boolean_t
+all_done(dns_view_t *view) {
+
+ if (isc_refcount_current(&view->references) == 0 &&
+ view->weakrefs == 0 &&
+ RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+void
+dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
+
+ REQUIRE(DNS_VIEW_VALID(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ isc_refcount_increment(&source->references, NULL);
+
+ *targetp = source;
+}
+
+static void
+view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
+ dns_view_t *view;
+ unsigned int refs;
+ isc_boolean_t done = ISC_FALSE;
+
+ REQUIRE(viewp != NULL);
+ view = *viewp;
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ if (flush)
+ view->flush = ISC_TRUE;
+ isc_refcount_decrement(&view->references, &refs);
+ if (refs == 0) {
+ LOCK(&view->lock);
+ if (!RESSHUTDOWN(view))
+ dns_resolver_shutdown(view->resolver);
+ if (!ADBSHUTDOWN(view))
+ dns_adb_shutdown(view->adb);
+ if (!REQSHUTDOWN(view))
+ dns_requestmgr_shutdown(view->requestmgr);
+ if (view->acache != NULL)
+ dns_acache_shutdown(view->acache);
+ if (view->flush)
+ dns_zt_flushanddetach(&view->zonetable);
+ else
+ dns_zt_detach(&view->zonetable);
+ done = all_done(view);
+ UNLOCK(&view->lock);
+ }
+
+ *viewp = NULL;
+
+ if (done)
+ destroy(view);
+}
+
+void
+dns_view_flushanddetach(dns_view_t **viewp) {
+ view_flushanddetach(viewp, ISC_TRUE);
+}
+
+void
+dns_view_detach(dns_view_t **viewp) {
+ view_flushanddetach(viewp, ISC_FALSE);
+}
+
+static isc_result_t
+dialup(dns_zone_t *zone, void *dummy) {
+ UNUSED(dummy);
+ dns_zone_dialup(zone);
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_view_dialup(dns_view_t *view) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ (void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);
+}
+
+void
+dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
+
+ REQUIRE(DNS_VIEW_VALID(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ LOCK(&source->lock);
+ source->weakrefs++;
+ UNLOCK(&source->lock);
+
+ *targetp = source;
+}
+
+void
+dns_view_weakdetach(dns_view_t **viewp) {
+ dns_view_t *view;
+ isc_boolean_t done = ISC_FALSE;
+
+ REQUIRE(viewp != NULL);
+ view = *viewp;
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ LOCK(&view->lock);
+
+ INSIST(view->weakrefs > 0);
+ view->weakrefs--;
+ done = all_done(view);
+
+ UNLOCK(&view->lock);
+
+ *viewp = NULL;
+
+ if (done)
+ destroy(view);
+}
+
+static void
+resolver_shutdown(isc_task_t *task, isc_event_t *event) {
+ dns_view_t *view = event->ev_arg;
+ isc_boolean_t done;
+
+ REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN);
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(view->task == task);
+
+ UNUSED(task);
+
+ LOCK(&view->lock);
+
+ view->attributes |= DNS_VIEWATTR_RESSHUTDOWN;
+ done = all_done(view);
+
+ UNLOCK(&view->lock);
+
+ isc_event_free(&event);
+
+ if (done)
+ destroy(view);
+}
+
+static void
+adb_shutdown(isc_task_t *task, isc_event_t *event) {
+ dns_view_t *view = event->ev_arg;
+ isc_boolean_t done;
+
+ REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN);
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(view->task == task);
+
+ UNUSED(task);
+
+ LOCK(&view->lock);
+
+ view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN;
+ done = all_done(view);
+
+ UNLOCK(&view->lock);
+
+ isc_event_free(&event);
+
+ if (done)
+ destroy(view);
+}
+
+static void
+req_shutdown(isc_task_t *task, isc_event_t *event) {
+ dns_view_t *view = event->ev_arg;
+ isc_boolean_t done;
+
+ REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN);
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(view->task == task);
+
+ UNUSED(task);
+
+ LOCK(&view->lock);
+
+ view->attributes |= DNS_VIEWATTR_REQSHUTDOWN;
+ done = all_done(view);
+
+ UNLOCK(&view->lock);
+
+ isc_event_free(&event);
+
+ if (done)
+ destroy(view);
+}
+
+isc_result_t
+dns_view_createresolver(dns_view_t *view,
+ isc_taskmgr_t *taskmgr, unsigned int ntasks,
+ isc_socketmgr_t *socketmgr,
+ isc_timermgr_t *timermgr,
+ unsigned int options,
+ dns_dispatchmgr_t *dispatchmgr,
+ dns_dispatch_t *dispatchv4,
+ dns_dispatch_t *dispatchv6)
+{
+ isc_result_t result;
+ isc_event_t *event;
+ isc_mem_t *mctx = NULL;
+
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(!view->frozen);
+ REQUIRE(view->resolver == NULL);
+
+ result = isc_task_create(taskmgr, 0, &view->task);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_task_setname(view->task, "view", view);
+
+ result = dns_resolver_create(view, taskmgr, ntasks, socketmgr,
+ timermgr, options, dispatchmgr,
+ dispatchv4, dispatchv6,
+ &view->resolver);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_detach(&view->task);
+ return (result);
+ }
+ event = &view->resevent;
+ dns_resolver_whenshutdown(view->resolver, view->task, &event);
+ view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN;
+
+ result = isc_mem_create(0, 0, &mctx);
+ if (result != ISC_R_SUCCESS) {
+ dns_resolver_shutdown(view->resolver);
+ return (result);
+ }
+
+ result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb);
+ isc_mem_setname(mctx, "ADB", NULL);
+ isc_mem_detach(&mctx);
+ if (result != ISC_R_SUCCESS) {
+ dns_resolver_shutdown(view->resolver);
+ return (result);
+ }
+ event = &view->adbevent;
+ dns_adb_whenshutdown(view->adb, view->task, &event);
+ view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN;
+
+ result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
+ dns_resolver_taskmgr(view->resolver),
+ dns_resolver_dispatchmgr(view->resolver),
+ dns_resolver_dispatchv4(view->resolver),
+ dns_resolver_dispatchv6(view->resolver),
+ &view->requestmgr);
+ if (result != ISC_R_SUCCESS) {
+ dns_adb_shutdown(view->adb);
+ dns_resolver_shutdown(view->resolver);
+ return (result);
+ }
+ event = &view->reqevent;
+ dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event);
+ view->attributes &= ~DNS_VIEWATTR_REQSHUTDOWN;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(!view->frozen);
+
+ if (view->cache != NULL) {
+ if (view->acache != NULL)
+ dns_acache_putdb(view->acache, view->cachedb);
+ dns_db_detach(&view->cachedb);
+ dns_cache_detach(&view->cache);
+ }
+ dns_cache_attach(cache, &view->cache);
+ dns_cache_attachdb(cache, &view->cachedb);
+ INSIST(DNS_DB_VALID(view->cachedb));
+
+ if (view->acache != NULL)
+ dns_acache_setdb(view->acache, view->cachedb);
+}
+
+void
+dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(!view->frozen);
+ REQUIRE(view->hints == NULL);
+ REQUIRE(dns_db_iszone(hints));
+
+ dns_db_attach(hints, &view->hints);
+}
+
+void
+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;
+}
+
+void
+dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ view->dstport = dstport;
+}
+
+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);
+}
+
+void
+dns_view_freeze(dns_view_t *view) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(!view->frozen);
+
+ if (view->resolver != NULL) {
+ INSIST(view->cachedb != NULL);
+ dns_resolver_freeze(view->resolver);
+ }
+ view->frozen = ISC_TRUE;
+}
+
+isc_result_t
+dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
+ isc_result_t result;
+
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
+ if (result == DNS_R_PARTIALMATCH) {
+ dns_zone_detach(zonep);
+ result = ISC_R_NOTFOUND;
+ }
+
+ return (result);
+}
+
+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 result;
+ dns_db_t *db, *zdb;
+ dns_dbnode_t *node, *znode;
+ isc_boolean_t is_cache;
+ dns_rdataset_t zrdataset, zsigrdataset;
+ dns_zone_t *zone;
+
+ /*
+ * Find an rdataset whose owner name is 'name', and whose type is
+ * 'type'.
+ */
+
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(view->frozen);
+ REQUIRE(type != dns_rdatatype_rrsig);
+ REQUIRE(rdataset != NULL); /* XXXBEW - remove this */
+ REQUIRE(nodep == NULL || *nodep == NULL);
+
+ /*
+ * Initialize.
+ */
+ dns_rdataset_init(&zrdataset);
+ dns_rdataset_init(&zsigrdataset);
+ zdb = NULL;
+ znode = NULL;
+
+ /*
+ * Find a database to answer the query.
+ */
+ zone = NULL;
+ db = NULL;
+ node = NULL;
+ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ 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;
+ } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL)
+ dns_db_attach(view->cachedb, &db);
+ else
+ goto cleanup;
+
+ is_cache = dns_db_iscache(db);
+
+ db_find:
+ /*
+ * Now look for an answer in the database.
+ */
+ result = dns_db_find(db, name, NULL, type, options,
+ now, &node, foundname, rdataset, sigrdataset);
+
+ if (result == DNS_R_DELEGATION ||
+ result == ISC_R_NOTFOUND) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (!is_cache) {
+ dns_db_detach(&db);
+ if (view->cachedb != NULL) {
+ /*
+ * Either the answer is in the cache, or we
+ * don't know it.
+ */
+ is_cache = ISC_TRUE;
+ dns_db_attach(view->cachedb, &db);
+ goto db_find;
+ }
+ } else {
+ /*
+ * We don't have the data in the cache. If we've got
+ * glue from the zone, use it.
+ */
+ if (dns_rdataset_isassociated(&zrdataset)) {
+ dns_rdataset_clone(&zrdataset, rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(&zsigrdataset))
+ dns_rdataset_clone(&zsigrdataset,
+ sigrdataset);
+ result = DNS_R_GLUE;
+ if (db != NULL)
+ dns_db_detach(&db);
+ dns_db_attach(zdb, &db);
+ dns_db_attachnode(db, znode, &node);
+ goto cleanup;
+ }
+ }
+ /*
+ * We don't know the answer.
+ */
+ result = ISC_R_NOTFOUND;
+ } else if (result == DNS_R_GLUE) {
+ if (view->cachedb != NULL) {
+ /*
+ * We found an answer, but the cache may be better.
+ * Remember what we've got and go look in the cache.
+ */
+ is_cache = ISC_TRUE;
+ dns_rdataset_clone(rdataset, &zrdataset);
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset)) {
+ dns_rdataset_clone(sigrdataset, &zsigrdataset);
+ dns_rdataset_disassociate(sigrdataset);
+ }
+ dns_db_attach(db, &zdb);
+ dns_db_attachnode(zdb, node, &znode);
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ dns_db_attach(view->cachedb, &db);
+ goto db_find;
+ }
+ /*
+ * Otherwise, the glue is the best answer.
+ */
+ result = ISC_R_SUCCESS;
+ }
+
+ if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ if (db != NULL) {
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ }
+ result = dns_db_find(view->hints, name, NULL, type, options,
+ now, &node, foundname,
+ rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
+ /*
+ * We just used a hint. Let the resolver know it
+ * should consider priming.
+ */
+ dns_resolver_prime(view->resolver);
+ dns_db_attach(view->hints, &db);
+ result = DNS_R_HINT;
+ } else if (result == DNS_R_NXRRSET) {
+ dns_db_attach(view->hints, &db);
+ result = DNS_R_HINTNXRRSET;
+ } else if (result == DNS_R_NXDOMAIN)
+ result = ISC_R_NOTFOUND;
+
+ /*
+ * Cleanup if non-standard hints are used.
+ */
+ if (db == NULL && node != NULL)
+ dns_db_detachnode(view->hints, &node);
+ }
+
+ cleanup:
+ if (dns_rdataset_isassociated(&zrdataset)) {
+ dns_rdataset_disassociate(&zrdataset);
+ if (dns_rdataset_isassociated(&zsigrdataset))
+ dns_rdataset_disassociate(&zsigrdataset);
+ }
+
+ if (zdb != NULL) {
+ if (znode != NULL)
+ dns_db_detachnode(zdb, &znode);
+ dns_db_detach(&zdb);
+ }
+
+ if (db != NULL) {
+ if (node != NULL) {
+ if (nodep != NULL)
+ *nodep = node;
+ else
+ dns_db_detachnode(db, &node);
+ }
+ if (dbp != NULL)
+ *dbp = db;
+ else
+ dns_db_detach(&db);
+ } else
+ INSIST(node == NULL);
+
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ return (result);
+}
+
+isc_result_t
+dns_view_simplefind(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_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ isc_result_t result;
+ dns_fixedname_t foundname;
+
+ dns_fixedname_init(&foundname);
+ result = dns_view_find(view, name, type, now, options, use_hints,
+ NULL, NULL, dns_fixedname_name(&foundname),
+ rdataset, sigrdataset);
+ if (result == DNS_R_NXDOMAIN) {
+ /*
+ * The rdataset and sigrdataset of the relevant NSEC record
+ * may be returned, but the caller cannot use them because
+ * foundname is not returned by this simplified API. We
+ * disassociate them here to prevent any misuse by the caller.
+ */
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ } else if (result != ISC_R_SUCCESS &&
+ result != DNS_R_GLUE &&
+ result != DNS_R_HINT &&
+ result != DNS_R_NCACHENXDOMAIN &&
+ result != DNS_R_NCACHENXRRSET &&
+ result != DNS_R_NXRRSET &&
+ result != DNS_R_HINTNXRRSET &&
+ result != ISC_R_NOTFOUND) {
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ result = ISC_R_NOTFOUND;
+ }
+
+ return (result);
+}
+
+isc_result_t
+dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
+ isc_stdtime_t now, unsigned int options,
+ isc_boolean_t use_hints,
+ dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+{
+ return(dns_view_findzonecut2(view, name, fname, now, options,
+ use_hints, ISC_TRUE,
+ rdataset, sigrdataset));
+}
+
+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,
+ 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;
+ dns_zone_t *zone;
+ dns_name_t *zfname;
+ dns_rdataset_t zrdataset, zsigrdataset;
+ dns_fixedname_t zfixedname;
+
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(view->frozen);
+
+ db = NULL;
+ zone = NULL;
+ use_zone = ISC_FALSE;
+ try_hints = ISC_FALSE;
+ zfname = NULL;
+
+ /*
+ * Initialize.
+ */
+ dns_fixedname_init(&zfixedname);
+ dns_rdataset_init(&zrdataset);
+ dns_rdataset_init(&zsigrdataset);
+
+ /*
+ * Find the right database.
+ */
+ result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+ result = dns_zone_getdb(zone, &db);
+ if (result == ISC_R_NOTFOUND) {
+ /*
+ * We're not directly authoritative for this query name, nor
+ * is it a subdomain of any zone for which we're
+ * authoritative.
+ */
+ if (use_cache && view->cachedb != NULL) {
+ /*
+ * We have a cache; try it.
+ */
+ dns_db_attach(view->cachedb, &db);
+ } else {
+ /*
+ * Maybe we have hints...
+ */
+ try_hints = ISC_TRUE;
+ goto finish;
+ }
+ } else if (result != ISC_R_SUCCESS) {
+ /*
+ * Something is broken.
+ */
+ goto cleanup;
+ }
+ is_cache = dns_db_iscache(db);
+
+ db_find:
+ /*
+ * Look for the zonecut.
+ */
+ if (!is_cache) {
+ result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
+ now, NULL, fname, rdataset, sigrdataset);
+ if (result == DNS_R_DELEGATION)
+ result = ISC_R_SUCCESS;
+ else if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ if (use_cache && view->cachedb != NULL && db != view->hints) {
+ /*
+ * We found an answer, but the cache may be better.
+ */
+ zfname = dns_fixedname_name(&zfixedname);
+ result = dns_name_copy(fname, zfname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdataset_clone(rdataset, &zrdataset);
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset)) {
+ dns_rdataset_clone(sigrdataset, &zsigrdataset);
+ dns_rdataset_disassociate(sigrdataset);
+ }
+ dns_db_detach(&db);
+ dns_db_attach(view->cachedb, &db);
+ is_cache = ISC_TRUE;
+ goto db_find;
+ }
+ } else {
+ result = dns_db_findzonecut(db, name, options, now, NULL,
+ fname, rdataset, sigrdataset);
+ if (result == ISC_R_SUCCESS) {
+ if (zfname != NULL &&
+ !dns_name_issubdomain(fname, zfname)) {
+ /*
+ * We found a zonecut in the cache, but our
+ * zone delegation is better.
+ */
+ use_zone = ISC_TRUE;
+ }
+ } else if (result == ISC_R_NOTFOUND) {
+ if (zfname != NULL) {
+ /*
+ * We didn't find anything in the cache, but we
+ * have a zone delegation, so use it.
+ */
+ use_zone = ISC_TRUE;
+ } else {
+ /*
+ * Maybe we have hints...
+ */
+ try_hints = ISC_TRUE;
+ }
+ } else {
+ /*
+ * Something bad happened.
+ */
+ goto cleanup;
+ }
+ }
+
+ finish:
+ if (use_zone) {
+ if (dns_rdataset_isassociated(rdataset)) {
+ dns_rdataset_disassociate(rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(sigrdataset))
+ dns_rdataset_disassociate(sigrdataset);
+ }
+ result = dns_name_copy(zfname, fname, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ dns_rdataset_clone(&zrdataset, rdataset);
+ if (sigrdataset != NULL &&
+ dns_rdataset_isassociated(&zrdataset))
+ dns_rdataset_clone(&zsigrdataset, sigrdataset);
+ } else if (try_hints && use_hints && view->hints != NULL) {
+ /*
+ * We've found nothing so far, but we have hints.
+ */
+ result = dns_db_find(view->hints, dns_rootname, NULL,
+ dns_rdatatype_ns, 0, now, NULL, fname,
+ rdataset, NULL);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * We can't even find the hints for the root
+ * nameservers!
+ */
+ if (dns_rdataset_isassociated(rdataset))
+ dns_rdataset_disassociate(rdataset);
+ result = ISC_R_NOTFOUND;
+ }
+ }
+
+ cleanup:
+ if (dns_rdataset_isassociated(&zrdataset)) {
+ dns_rdataset_disassociate(&zrdataset);
+ if (dns_rdataset_isassociated(&zsigrdataset))
+ dns_rdataset_disassociate(&zsigrdataset);
+ }
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (zone != NULL)
+ dns_zone_detach(&zone);
+
+ return (result);
+}
+
+isc_result_t
+dns_viewlist_find(dns_viewlist_t *list, const char *name,
+ dns_rdataclass_t rdclass, dns_view_t **viewp)
+{
+ dns_view_t *view;
+
+ REQUIRE(list != NULL);
+
+ for (view = ISC_LIST_HEAD(*list);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ if (strcmp(view->name, name) == 0 && view->rdclass == rdclass)
+ break;
+ }
+ if (view == NULL)
+ return (ISC_R_NOTFOUND);
+
+ dns_view_attach(view, viewp);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name,
+ isc_boolean_t allclasses, dns_rdataclass_t rdclass,
+ dns_zone_t **zonep)
+{
+ dns_view_t *view;
+ isc_result_t result;
+ dns_zone_t *zone1 = NULL, *zone2 = NULL;
+ dns_zone_t **zp = NULL;;
+
+ REQUIRE(list != NULL);
+ for (view = ISC_LIST_HEAD(*list);
+ view != NULL;
+ view = ISC_LIST_NEXT(view, link)) {
+ if (allclasses == ISC_FALSE && view->rdclass != rdclass)
+ continue;
+
+ /*
+ * If the zone is defined in more than one view,
+ * treat it as not found.
+ */
+ zp = (zone1 == NULL) ? &zone1 : &zone2;
+ result = dns_zt_find(view->zonetable, name, 0, NULL, zp);
+ INSIST(result == ISC_R_SUCCESS ||
+ result == ISC_R_NOTFOUND ||
+ result == DNS_R_PARTIALMATCH);
+
+ /* Treat a partial match as no match */
+ if (result == DNS_R_PARTIALMATCH) {
+ dns_zone_detach(zp);
+ result = ISC_R_NOTFOUND;
+ }
+
+ if (zone2 != NULL) {
+ dns_zone_detach(&zone1);
+ dns_zone_detach(&zone2);
+ return (ISC_R_NOTFOUND);
+ }
+ }
+
+ if (zone1 != NULL) {
+ dns_zone_attach(zone1, zonep);
+ dns_zone_detach(&zone1);
+ return (ISC_R_SUCCESS);
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+dns_view_load(dns_view_t *view, isc_boolean_t stop) {
+
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ return (dns_zt_load(view->zonetable, stop));
+}
+
+isc_result_t
+dns_view_loadnew(dns_view_t *view, isc_boolean_t stop) {
+
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ return (dns_zt_loadnew(view->zonetable, stop));
+}
+
+isc_result_t
+dns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp)
+{
+ isc_result_t result;
+ REQUIRE(keyp != NULL && *keyp == NULL);
+
+ result = dns_tsigkey_find(keyp, keyname, NULL,
+ view->statickeys);
+ if (result == ISC_R_NOTFOUND)
+ result = dns_tsigkey_find(keyp, keyname, NULL,
+ view->dynamickeys);
+ return (result);
+}
+
+isc_result_t
+dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr,
+ dns_tsigkey_t **keyp)
+{
+ isc_result_t result;
+ dns_name_t *keyname = NULL;
+ dns_peer_t *peer = NULL;
+
+ result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = dns_peer_getkey(peer, &keyname);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ return (dns_view_gettsig(view, keyname, keyp));
+}
+
+isc_result_t
+dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(source != NULL);
+
+ return (dns_tsig_verify(source, msg, view->statickeys,
+ view->dynamickeys));
+}
+
+isc_result_t
+dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
+ isc_result_t result;
+
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ (void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
+ result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
+ &dns_master_style_cache, fp);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_adb_dump(view->adb, fp);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_view_flushcache(dns_view_t *view) {
+ 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 (view->acache != NULL)
+ dns_acache_putdb(view->acache, view->cachedb);
+ dns_db_detach(&view->cachedb);
+ dns_cache_attachdb(view->cache, &view->cachedb);
+ if (view->acache != NULL)
+ dns_acache_setdb(view->acache, view->cachedb);
+
+ dns_adb_flush(view->adb);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_view_flushname(dns_view_t *view, dns_name_t *name) {
+
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ if (view->adb != NULL)
+ dns_adb_flushname(view->adb, name);
+ if (view->cache == NULL)
+ return (ISC_R_SUCCESS);
+ return (dns_cache_flushname(view->cache, name));
+}
+
+isc_result_t
+dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name) {
+ isc_result_t result;
+ dns_name_t *new;
+ isc_uint32_t hash;
+
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ if (view->delonly == NULL) {
+ view->delonly = isc_mem_get(view->mctx,
+ sizeof(dns_namelist_t) *
+ DNS_VIEW_DELONLYHASH);
+ if (view->delonly == NULL)
+ return (ISC_R_NOMEMORY);
+ for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
+ ISC_LIST_INIT(view->delonly[hash]);
+ }
+ hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
+ new = ISC_LIST_HEAD(view->delonly[hash]);
+ while (new != NULL && !dns_name_equal(new, name))
+ new = ISC_LIST_NEXT(new, link);
+ if (new != NULL)
+ return (ISC_R_SUCCESS);
+ new = isc_mem_get(view->mctx, sizeof(*new));
+ if (new == NULL)
+ return (ISC_R_NOMEMORY);
+ dns_name_init(new, NULL);
+ result = dns_name_dup(name, view->mctx, new);
+ if (result == ISC_R_SUCCESS)
+ ISC_LIST_APPEND(view->delonly[hash], new, link);
+ else
+ isc_mem_put(view->mctx, new, sizeof(*new));
+ return (result);
+}
+
+isc_result_t
+dns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name) {
+ isc_result_t result;
+ dns_name_t *new;
+ isc_uint32_t hash;
+
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ if (view->rootexclude == NULL) {
+ view->rootexclude = isc_mem_get(view->mctx,
+ sizeof(dns_namelist_t) *
+ DNS_VIEW_DELONLYHASH);
+ if (view->rootexclude == NULL)
+ return (ISC_R_NOMEMORY);
+ for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
+ ISC_LIST_INIT(view->rootexclude[hash]);
+ }
+ hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
+ new = ISC_LIST_HEAD(view->rootexclude[hash]);
+ while (new != NULL && !dns_name_equal(new, name))
+ new = ISC_LIST_NEXT(new, link);
+ if (new != NULL)
+ return (ISC_R_SUCCESS);
+ new = isc_mem_get(view->mctx, sizeof(*new));
+ if (new == NULL)
+ return (ISC_R_NOMEMORY);
+ dns_name_init(new, NULL);
+ result = dns_name_dup(name, view->mctx, new);
+ if (result == ISC_R_SUCCESS)
+ ISC_LIST_APPEND(view->rootexclude[hash], new, link);
+ else
+ isc_mem_put(view->mctx, new, sizeof(*new));
+ return (result);
+}
+
+isc_boolean_t
+dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) {
+ dns_name_t *new;
+ isc_uint32_t hash;
+
+ REQUIRE(DNS_VIEW_VALID(view));
+
+ if (!view->rootdelonly && view->delonly == NULL)
+ return (ISC_FALSE);
+
+ hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
+ if (view->rootdelonly && dns_name_countlabels(name) <= 2) {
+ if (view->rootexclude == NULL)
+ return (ISC_TRUE);
+ new = ISC_LIST_HEAD(view->rootexclude[hash]);
+ while (new != NULL && !dns_name_equal(new, name))
+ new = ISC_LIST_NEXT(new, link);
+ if (new == NULL)
+ return (ISC_TRUE);
+ }
+
+ if (view->delonly == NULL)
+ return (ISC_FALSE);
+
+ new = ISC_LIST_HEAD(view->delonly[hash]);
+ while (new != NULL && !dns_name_equal(new, name))
+ new = ISC_LIST_NEXT(new, link);
+ if (new == NULL)
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+}
+
+void
+dns_view_setrootdelonly(dns_view_t *view, isc_boolean_t value) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ view->rootdelonly = value;
+}
+
+isc_boolean_t
+dns_view_getrootdelonly(dns_view_t *view) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ return (view->rootdelonly);
+}
+
+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));
+}
+
+void
+dns_view_setresstats(dns_view_t *view, dns_stats_t *stats) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(!view->frozen);
+ REQUIRE(view->resstats == NULL);
+
+ dns_stats_attach(stats, &view->resstats);
+}
+
+void
+dns_view_getresstats(dns_view_t *view, dns_stats_t **statsp) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ if (view->resstats != NULL)
+ dns_stats_attach(view->resstats, statsp);
+}
+
+void
+dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(!view->frozen);
+ REQUIRE(view->resquerystats == NULL);
+
+ dns_stats_attach(stats, &view->resquerystats);
+}
+
+void
+dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
+ REQUIRE(DNS_VIEW_VALID(view));
+ REQUIRE(statsp != NULL && *statsp == NULL);
+
+ if (view->resquerystats != NULL)
+ dns_stats_attach(view->resquerystats, statsp);
+}
diff --git a/lib/dns/win32/DLLMain.c b/lib/dns/win32/DLLMain.c
new file mode 100644
index 0000000..7c1e129
--- /dev/null
+++ b/lib/dns/win32/DLLMain.c
@@ -0,0 +1,57 @@
+/*
+ * 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: DLLMain.c,v 1.6 2007/06/18 23:47:44 tbox Exp $ */
+
+#include <windows.h>
+#include <signal.h>
+
+/*
+ * Called when we enter the DLL
+ */
+__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason) {
+ /*
+ * The DLL is loading due to process
+ * initialization or a call to LoadLibrary.
+ */
+ case DLL_PROCESS_ATTACH:
+ break;
+
+ /* The attached process creates a new thread. */
+ case DLL_THREAD_ATTACH:
+ break;
+
+ /* The thread of the attached process terminates. */
+ case DLL_THREAD_DETACH:
+ break;
+
+ /*
+ * The DLL is unloading from a process due to
+ * process termination or a call to FreeLibrary.
+ */
+ case DLL_PROCESS_DETACH:
+ break;
+
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
diff --git a/lib/dns/win32/gen.dsp b/lib/dns/win32/gen.dsp
new file mode 100644
index 0000000..1d0fc34
--- /dev/null
+++ b/lib/dns/win32/gen.dsp
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="gen" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gen - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "gen.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gen.mak" CFG="gen - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gen - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gen - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gen - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "LIBISC_EXPORTS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 user32.lib advapi32.lib /nologo /subsystem:console /machine:I386 /out:"../gen.exe"
+
+!ELSEIF "$(CFG)" == "gen - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "LIBISC_EXPORTS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /YX
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /out:"../gen.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "gen - Win32 Release"
+# Name "gen - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\gen.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE="..\gen-win32.h"
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/lib/dns/win32/gen.dsw b/lib/dns/win32/gen.dsw
new file mode 100644
index 0000000..e44f589
--- /dev/null
+++ b/lib/dns/win32/gen.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "gen"=".\gen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/dns/win32/gen.mak b/lib/dns/win32/gen.mak
new file mode 100644
index 0000000..5800af1
--- /dev/null
+++ b/lib/dns/win32/gen.mak
@@ -0,0 +1,267 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on gen.dsp
+!IF "$(CFG)" == ""
+CFG=gen - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to gen - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "gen - Win32 Release" && "$(CFG)" != "gen - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "gen.mak" CFG="gen - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gen - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gen - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gen - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "gen - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\gen.exe"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\gen.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\gen.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "LIBISC_EXPORTS" /Fp"$(INTDIR)\gen.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\gen.pdb" /machine:I386 /out:"../gen.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\gen.obj"
+
+"..\gen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "gen - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\gen.exe" "$(OUTDIR)\gen.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\gen.obj"
+ -@erase "$(INTDIR)\gen.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\gen.bsc"
+ -@erase "$(OUTDIR)\gen.pdb"
+ -@erase "..\gen.exe"
+ -@erase "..\gen.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MLd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "LIBISC_EXPORTS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\gen.sbr"
+
+"$(OUTDIR)\gen.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\gen.pdb" /debug /machine:I386 /out:"../gen.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\gen.obj"
+
+"..\gen.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("gen.dep")
+!INCLUDE "gen.dep"
+!ELSE
+!MESSAGE Warning: cannot find "gen.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "gen - Win32 Release" || "$(CFG)" == "gen - Win32 Debug"
+SOURCE=..\gen.c
+
+!IF "$(CFG)" == "gen - Win32 Release"
+
+
+"$(INTDIR)\gen.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "gen - Win32 Debug"
+
+
+"$(INTDIR)\gen.obj" "$(INTDIR)\gen.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/lib/dns/win32/libdns.def b/lib/dns/win32/libdns.def
new file mode 100644
index 0000000..48a56c7
--- /dev/null
+++ b/lib/dns/win32/libdns.def
@@ -0,0 +1,860 @@
+LIBRARY libdns
+
+; Exported Functions
+EXPORTS
+
+dns_acache_attach
+dns_acache_attachentry
+dns_acache_cancelentry
+dns_acache_create
+dns_acache_createentry
+dns_acache_detach
+dns_acache_detachentry
+dns_acache_getentry
+dns_acache_putdb
+dns_acache_setcachesize
+dns_acache_setcleaninginterval
+dns_acache_setdb
+dns_acache_setentry
+dns_acache_shutdown
+dns_acl_any
+dns_acl_attach
+dns_acl_create
+dns_acl_detach
+dns_acl_isany
+dns_acl_isinsecure
+dns_acl_isnone
+dns_acl_match
+dns_acl_merge
+dns_acl_none
+dns_aclelement_match
+dns_aclenv_copy
+dns_aclenv_destroy
+dns_aclenv_init
+dns_adb_adjustsrtt
+dns_adb_attach
+dns_adb_cancelfind
+dns_adb_changeflags
+dns_adb_create
+dns_adb_createfind
+dns_adb_destroyfind
+dns_adb_detach
+dns_adb_dump
+dns_adb_dumpfind
+dns_adb_findaddrinfo
+dns_adb_flush
+dns_adb_freeaddrinfo
+dns_adb_marklame
+dns_adb_setadbsize
+dns_adb_shutdown
+dns_adb_whenshutdown
+dns_byaddr_cancel
+dns_byaddr_create
+dns_byaddr_createptrname
+dns_byaddr_createptrname2
+dns_byaddr_destroy
+dns_cache_attach
+dns_cache_attachdb
+dns_cache_clean
+dns_cache_create
+dns_cache_detach
+dns_cache_dump
+dns_cache_flush
+dns_cache_load
+dns_cache_setcachesize
+dns_cache_setcleaninginterval
+dns_cache_setfilename
+dns_cert_fromtext
+dns_cert_totext
+dns_compress_add
+dns_compress_findglobal
+dns_compress_getedns
+dns_compress_getmethods
+dns_compress_init
+dns_compress_invalidate
+dns_compress_rollback
+dns_compress_setmethods
+dns_compress_setsensitive
+dns_counter_fromtext
+dns_db_addrdataset
+dns_db_allrdatasets
+dns_db_attach
+dns_db_attachnode
+dns_db_attachversion
+dns_db_beginload
+dns_db_class
+dns_db_closeversion
+dns_db_create
+dns_db_createiterator
+dns_db_createsoatuple
+dns_db_currentversion
+dns_db_deleterdataset
+dns_db_detach
+dns_db_detachnode
+dns_db_diff
+dns_db_dump
+dns_db_endload
+dns_db_expirenode
+dns_db_find
+dns_db_findnode
+dns_db_findnsec3node
+dns_db_findrdataset
+dns_db_findzonecut
+dns_db_getnsec3parameters
+dns_db_getoriginnode
+dns_db_getrrsetstats
+dns_db_getsoaserial
+dns_db_iscache
+dns_db_isdnssec
+dns_db_ispersistent
+dns_db_issecure
+dns_db_isstub
+dns_db_iszone
+dns_db_load
+dns_db_load2
+dns_db_newversion
+dns_db_nodecount
+dns_db_ondestroy
+dns_db_origin
+dns_db_overmem
+dns_db_printnode
+dns_db_register
+dns_db_subtractrdataset
+dns_db_unregister
+dns_dbiterator_current
+dns_dbiterator_destroy
+dns_dbiterator_first
+dns_dbiterator_last
+dns_dbiterator_next
+dns_dbiterator_origin
+dns_dbiterator_pause
+dns_dbiterator_prev
+dns_dbiterator_seek
+dns_dbiterator_setcleanmode
+dns_dbtable_add
+dns_dbtable_adddefault
+dns_dbtable_attach
+dns_dbtable_create
+dns_dbtable_detach
+dns_dbtable_find
+dns_dbtable_getdefault
+dns_dbtable_remove
+dns_dbtable_removedefault
+dns_decompress_edns
+dns_decompress_getmethods
+dns_decompress_init
+dns_decompress_invalidate
+dns_decompress_setmethods
+dns_decompress_type
+dns_diff_append
+dns_diff_appendminimal
+dns_diff_apply
+dns_diff_applysilently
+dns_diff_clear
+dns_diff_init
+dns_diff_load
+dns_diff_print
+dns_diff_sort
+dns_difftuple_copy
+dns_difftuple_create
+dns_difftuple_free
+dns_dispatch_addresponse
+dns_dispatch_attach
+dns_dispatch_cancel
+dns_dispatch_changeattributes
+dns_dispatch_createtcp
+dns_dispatch_detach
+dns_dispatch_getlocaladdress
+dns_dispatch_getsocket
+dns_dispatch_getudp
+dns_dispatch_importrecv
+dns_dispatch_removeresponse
+dns_dispatch_starttcp
+dns_dispatchmgr_create
+dns_dispatchmgr_destroy
+dns_dispatchmgr_getblackhole
+dns_dispatchmgr_setavailports
+dns_dispatchmgr_setblackhole
+dns_dispatchmgr_setblackportlist
+dns_dispatchmgr_setstats
+dns_dlzallowzonexfr
+dns_dlzcreate
+dns_dlzdestroy
+dns_dlzfindzone
+dns_dlzregister
+dns_dlzstrtoargv
+dns_dlzunregister
+dns_dnssec_findzonekeys
+dns_dnssec_findzonekeys2
+dns_dnssec_keyfromrdata
+dns_dnssec_sign
+dns_dnssec_signmessage
+dns_dnssec_verify
+dns_dnssec_verify2
+dns_dnssec_verifymessage
+dns_ds_buildrdata
+dns_ds_digest_supported
+dns_dumpctx_detach
+dns_fwdtable_add
+dns_fwdtable_create
+dns_fwdtable_destroy
+dns_fwdtable_find
+dns_generalstats_create
+dns_generalstats_dump
+dns_generalstats_increment
+dns_iptable_addprefix
+dns_iptable_attach
+dns_iptable_create
+dns_iptable_detach
+dns_iptable_merge
+dns_journal_begin_transaction
+dns_journal_commit
+dns_journal_current_rr
+dns_journal_destroy
+dns_journal_first_rr
+dns_journal_first_serial
+dns_journal_iter_init
+dns_journal_last_serial
+dns_journal_next_rr
+dns_journal_open
+dns_journal_print
+dns_journal_rollforward
+dns_journal_write_transaction
+dns_journal_writediff
+dns_keyflags_fromtext
+dns_keynode_key
+dns_keytable_add
+dns_keytable_attach
+dns_keytable_create
+dns_keytable_detach
+dns_keytable_detachkeynode
+dns_keytable_finddeepestmatch
+dns_keytable_findkeynode
+dns_keytable_findnextkeynode
+dns_keytable_issecuredomain
+dns_lib_initmsgcat
+dns_loadctx_attach
+dns_loadctx_cancel
+dns_loadctx_detach
+dns_log_init
+dns_log_setcontext
+dns_lookup_cancel
+dns_lookup_create
+dns_lookup_destroy
+dns_master_dump
+dns_master_dumpnode
+dns_master_dumpnodetostream
+dns_master_dumptostream
+dns_master_dumptostream2
+dns_master_dumptostreaminc
+dns_master_loadbuffer
+dns_master_loadbufferinc
+dns_master_loadfile
+dns_master_loadfileinc
+dns_master_loadstream
+dns_master_loadstreaminc
+dns_master_questiontotext
+dns_master_rdatasettotext
+dns_master_stylecreate
+dns_master_styledestroy
+dns_message_addname
+dns_message_checksig
+dns_message_create
+dns_message_currentname
+dns_message_destroy
+dns_message_find
+dns_message_findname
+dns_message_findtype
+dns_message_firstname
+dns_message_getopt
+dns_message_getquerytsig
+dns_message_getrawmessage
+dns_message_getsig0
+dns_message_getsig0key
+dns_message_gettempname
+dns_message_gettempoffsets
+dns_message_gettemprdata
+dns_message_gettemprdatalist
+dns_message_gettemprdataset
+dns_message_gettimeadjust
+dns_message_gettsig
+dns_message_gettsigkey
+dns_message_movename
+dns_message_nextname
+dns_message_parse
+dns_message_peekheader
+dns_message_pseudosectiontotext
+dns_message_puttempname
+dns_message_puttemprdata
+dns_message_puttemprdatalist
+dns_message_puttemprdataset
+dns_message_rechecksig
+dns_message_removename
+dns_message_renderbegin
+dns_message_renderchangebuffer
+dns_message_renderend
+dns_message_renderheader
+dns_message_renderrelease
+dns_message_renderreserve
+dns_message_renderreset
+dns_message_rendersection
+dns_message_reply
+dns_message_reset
+dns_message_resetsig
+dns_message_sectiontotext
+dns_message_setopt
+dns_message_setquerytsig
+dns_message_setsig0key
+dns_message_setsortorder
+dns_message_settimeadjust
+dns_message_settsigkey
+dns_message_signer
+dns_message_takebuffer
+dns_message_totext
+dns_name_clone
+dns_name_compare
+dns_name_concatenate
+dns_name_copy
+dns_name_countlabels
+dns_name_destroy
+dns_name_digest
+dns_name_downcase
+dns_name_dup
+dns_name_dupwithoffsets
+dns_name_dynamic
+dns_name_equal
+dns_name_format
+dns_name_free
+dns_name_fromregion
+dns_name_fromtext
+dns_name_fromwire
+dns_name_fullcompare
+dns_name_getlabel
+dns_name_getlabelsequence
+dns_name_hasbuffer
+dns_name_hash
+dns_name_init
+dns_name_internalwildcard
+dns_name_invalidate
+dns_name_isabsolute
+dns_name_issubdomain
+dns_name_iswildcard
+dns_name_matcheswildcard
+dns_name_print
+dns_name_rdatacompare
+dns_name_reset
+dns_name_setbuffer
+dns_name_settotextfilter
+dns_name_split
+dns_name_tofilenametext
+dns_name_toregion
+dns_name_totext
+dns_name_towire
+dns_ncache_add
+dns_ncache_getrdataset
+dns_ncache_towire
+dns_nsec3_active
+dns_nsec3_addnsec3
+dns_nsec3_addnsec3s
+dns_nsec3_buildrdata
+dns_nsec3_delnsec3
+dns_nsec3_delnsec3s
+dns_nsec3_hashlength
+dns_nsec3_hashname
+dns_nsec3_maxiterations
+dns_nsec3_supportedhash
+dns_nsec3_typepresent
+dns_nsec_build
+dns_nsec_buildrdata
+dns_nsec_nseconly
+dns_nsec_typepresent
+dns_opcode_totext
+dns_opcodestats_create
+dns_opcodestats_dump
+dns_opcodestats_increment
+dns_order_add
+dns_order_attach
+dns_order_create
+dns_order_detach
+dns_order_find
+dns_peer_attach
+dns_peer_detach
+dns_peer_getbogus
+dns_peer_getkey
+dns_peer_getmaxudp
+dns_peer_getprovideixfr
+dns_peer_getrequestixfr
+dns_peer_getsupportedns
+dns_peer_gettransferformat
+dns_peer_gettransfers
+dns_peer_new
+dns_peer_newprefix
+dns_peer_setbogus
+dns_peer_setkey
+dns_peer_setkeybycharp
+dns_peer_setmaxudp
+dns_peer_setnotifysource
+dns_peer_setprovideixfr
+dns_peer_setquerysource
+dns_peer_setrequestixfr
+dns_peer_setrequestnsid
+dns_peer_setsupportedns
+dns_peer_settransferformat
+dns_peer_settransfers
+dns_peer_settransfersource
+dns_peer_setudpsize
+dns_peerlist_addpeer
+dns_peerlist_attach
+dns_peerlist_currpeer
+dns_peerlist_detach
+dns_peerlist_new
+dns_peerlist_peerbyaddr
+dns_portlist_add
+dns_portlist_create
+dns_portlist_detach
+dns_rbt_addname
+dns_rbt_addnode
+dns_rbt_create
+dns_rbt_deletename
+dns_rbt_deletenode
+dns_rbt_destroy
+dns_rbt_findname
+dns_rbt_findnode
+dns_rbt_formatnodename
+dns_rbt_fullnamefromnode
+dns_rbt_namefromnode
+dns_rbt_nodecount
+dns_rbt_printall
+dns_rbtnodechain_current
+dns_rbtnodechain_first
+dns_rbtnodechain_init
+dns_rbtnodechain_invalidate
+dns_rbtnodechain_last
+dns_rbtnodechain_next
+dns_rbtnodechain_prev
+dns_rbtnodechain_reset
+dns_rcode_fromtext
+dns_rcode_totext
+dns_rdata_additionaldata
+dns_rdata_checkowner
+dns_rdata_clone
+dns_rdata_compare
+dns_rdata_covers
+dns_rdata_digest
+dns_rdata_freestruct
+dns_rdata_fromregion
+dns_rdata_fromstruct
+dns_rdata_fromtext
+dns_rdata_fromwire
+dns_rdata_init
+dns_rdata_reset
+dns_rdata_tofmttext
+dns_rdata_toregion
+dns_rdata_tostruct
+dns_rdata_totext
+dns_rdata_towire
+dns_rdatacallbacks_init
+dns_rdatacallbacks_init_stdio
+dns_rdataclass_format
+dns_rdataclass_fromtext
+dns_rdataclass_ismeta
+dns_rdataclass_totext
+dns_rdatalist_init
+dns_rdatalist_tordataset
+dns_rdataset_additionaldata
+dns_rdataset_clone
+dns_rdataset_count
+dns_rdataset_current
+dns_rdataset_disassociate
+dns_rdataset_first
+dns_rdataset_getadditional
+dns_rdataset_getclosest
+dns_rdataset_getnoqname
+dns_rdataset_init
+dns_rdataset_invalidate
+dns_rdataset_isassociated
+dns_rdataset_makequestion
+dns_rdataset_next
+dns_rdataset_putadditional
+dns_rdataset_setadditional
+dns_rdataset_totext
+dns_rdataset_towire
+dns_rdataset_towiresorted
+dns_rdatasetiter_current
+dns_rdatasetiter_destroy
+dns_rdatasetiter_first
+dns_rdatasetiter_next
+dns_rdatasetstats_dump
+dns_rdataslab_equal
+dns_rdataslab_fromrdataset
+dns_rdataslab_merge
+dns_rdataslab_size
+dns_rdataslab_subtract
+dns_rdatatype_atparent
+dns_rdatatype_attributes
+dns_rdatatype_format
+dns_rdatatype_fromtext
+dns_rdatatype_isdnssec
+dns_rdatatype_isknown
+dns_rdatatype_ismeta
+dns_rdatatype_issingleton
+dns_rdatatype_iszonecutauth
+dns_rdatatype_notquestion
+dns_rdatatype_questiononly
+dns_rdatatype_totext
+dns_rdatatypestats_create
+dns_rdatatypestats_dump
+dns_rdatatypestats_increment
+dns_request_cancel
+dns_request_create
+dns_request_createraw
+dns_request_createvia
+dns_request_createvia3
+dns_request_destroy
+dns_request_getresponse
+dns_request_usedtcp
+dns_requestmgr_attach
+dns_requestmgr_create
+dns_requestmgr_detach
+dns_requestmgr_shutdown
+dns_requestmgr_whenshutdown
+dns_resolver_addalternate
+dns_resolver_algorithm_supported
+dns_resolver_attach
+dns_resolver_cancelfetch
+dns_resolver_create
+dns_resolver_createfetch
+dns_resolver_createfetch2
+dns_resolver_destroyfetch
+dns_resolver_detach
+dns_resolver_disable_algorithm
+dns_resolver_dispatchmgr
+dns_resolver_dispatchv4
+dns_resolver_dispatchv6
+dns_resolver_freeze
+dns_resolver_getlamettl
+dns_resolver_getoptions
+dns_resolver_getudpsize
+dns_resolver_getzeronosoattl
+dns_resolver_nrunning
+dns_resolver_prime
+dns_resolver_reset_algorithms
+dns_resolver_resetmustbesecure
+dns_resolver_setclientsperquery
+dns_resolver_setlamettl
+dns_resolver_setmustbesecure
+dns_resolver_setudpsize
+dns_resolver_setzeronosoattl
+dns_resolver_shutdown
+dns_resolver_socketmgr
+dns_resolver_taskmgr
+dns_resolver_whenshutdown
+dns_result_register
+dns_result_torcode
+dns_result_totext
+dns_rootns_create
+dns_sdb_putnamedrr
+dns_sdb_putrdata
+dns_sdb_putrr
+dns_sdb_putsoa
+dns_sdb_register
+dns_sdb_unregister
+dns_sdlz_putnamedrr
+dns_sdlz_putrr
+dns_sdlz_putsoa
+dns_sdlzregister
+dns_sdlzunregister
+dns_secalg_fromtext
+dns_secalg_totext
+dns_secproto_fromtext
+dns_secproto_totext
+dns_soa_getminimum
+dns_soa_getserial
+dns_soa_setserial
+dns_ssutable_addrule
+dns_ssutable_attach
+dns_ssutable_checkrules
+dns_ssutable_create
+dns_ssutable_detach
+dns_stats_alloccounters
+dns_stats_detach
+dns_stats_freecounters
+dns_tcpmsg_cancelread
+dns_tcpmsg_init
+dns_tcpmsg_invalidate
+dns_tcpmsg_keepbuffer
+dns_tcpmsg_readmessage
+dns_tcpmsg_setmaxsize
+dns_time32_fromtext
+dns_time32_totext
+dns_time64_fromtext
+dns_time64_totext
+dns_timer_setidle
+dns_tkey_builddeletequery
+dns_tkey_builddhquery
+dns_tkey_buildgssquery
+dns_tkey_processdeleteresponse
+dns_tkey_processdhresponse
+dns_tkey_processgssresponse
+dns_tkey_processquery
+dns_tkeyctx_create
+dns_tkeyctx_destroy
+dns_tsig_sign
+dns_tsig_verify
+dns_tsigkey_attach
+dns_tsigkey_create
+dns_tsigkey_createfromkey
+dns_tsigkey_detach
+dns_tsigkey_find
+dns_tsigkey_setdeleted
+dns_tsigkeyring_create
+dns_tsigkeyring_destroy
+dns_tsigrcode_fromtext
+dns_tsigrcode_totext
+dns_ttl_fromtext
+dns_ttl_totext
+dns_validator_cancel
+dns_validator_create
+dns_validator_destroy
+dns_validator_send
+dns_view_adddelegationonly
+dns_view_addzone
+dns_view_attach
+dns_view_checksig
+dns_view_create
+dns_view_createresolver
+dns_view_detach
+dns_view_dialup
+dns_view_dumpdbtostream
+dns_view_excludedelegationonly
+dns_view_find
+dns_view_findzone
+dns_view_findzonecut
+dns_view_flushanddetach
+dns_view_flushcache
+dns_view_flushname
+dns_view_freeze
+dns_view_freezezones
+dns_view_getpeertsig
+dns_view_getresquerystats
+dns_view_getresstats
+dns_view_gettsig
+dns_view_load
+dns_view_loadnew
+dns_view_setcache
+dns_view_setdstport
+dns_view_sethints
+dns_view_setkeyring
+dns_view_setresquerystats
+dns_view_setresstats
+dns_view_setrootdelonly
+dns_view_simplefind
+dns_view_weakattach
+dns_view_weakdetach
+dns_viewlist_find
+dns_viewlist_findzone
+dns_xfrin_attach
+dns_xfrin_create
+dns_xfrin_detach
+dns_xfrin_shutdown
+dns_zone_attach
+dns_zone_checknames
+dns_zone_clearforwardacl
+dns_zone_clearnotifyacl
+dns_zone_clearqueryacl
+dns_zone_clearupdateacl
+dns_zone_clearxfracl
+dns_zone_create
+dns_zone_detach
+dns_zone_dialup
+dns_zone_dump
+dns_zone_dumptostream
+dns_zone_dumptostream2
+dns_zone_expire
+dns_zone_first
+dns_zone_flush
+dns_zone_forcereload
+dns_zone_forwardupdate
+dns_zone_fulldumptostream
+dns_zone_getchecknames
+dns_zone_getclass
+dns_zone_getdb
+dns_zone_getdbtype
+dns_zone_getfile
+dns_zone_getforwardacl
+dns_zone_getidlein
+dns_zone_getidleout
+dns_zone_getjournal
+dns_zone_getjournalsize
+dns_zone_getkeydirectory
+dns_zone_getmaxxfrin
+dns_zone_getmaxxfrout
+dns_zone_getmctx
+dns_zone_getmgr
+dns_zone_getnotifyacl
+dns_zone_getnotifysrc4
+dns_zone_getnotifysrc6
+dns_zone_getoptions
+dns_zone_getorigin
+dns_zone_getprivatetype
+dns_zone_getqueryacl
+dns_zone_getrequeststats
+dns_zone_getsigresigninginterval
+dns_zone_getsigvalidityinterval
+dns_zone_getssutable
+dns_zone_getstatscounters
+dns_zone_gettask
+dns_zone_gettype
+dns_zone_getupdateacl
+dns_zone_getupdatedisabled
+dns_zone_getview
+dns_zone_getxfracl
+dns_zone_getxfrsource4
+dns_zone_getxfrsource6
+dns_zone_getzeronosoattl
+dns_zone_iattach
+dns_zone_idetach
+dns_zone_isforced
+dns_zone_load
+dns_zone_log
+dns_zone_maintenance
+dns_zone_markdirty
+dns_zone_name
+dns_zone_next
+dns_zone_notify
+dns_zone_notifyreceive
+dns_zone_refresh
+dns_zone_replacedb
+dns_zone_setacache
+dns_zone_setalsonotify
+dns_zone_setaltxfrsource4
+dns_zone_setaltxfrsource6
+dns_zone_setcheckmx
+dns_zone_setchecknames
+dns_zone_setcheckns
+dns_zone_setchecksrv
+dns_zone_setclass
+dns_zone_setdbtype
+dns_zone_setdialup
+dns_zone_setfile
+dns_zone_setfile2
+dns_zone_setflag
+dns_zone_setforwardacl
+dns_zone_setidlein
+dns_zone_setidleout
+dns_zone_setisself
+dns_zone_setjournal
+dns_zone_setjournalsize
+dns_zone_setkeydirectory
+dns_zone_setmasters
+dns_zone_setmasterswithkeys
+dns_zone_setmaxrefreshtime
+dns_zone_setmaxretrytime
+dns_zone_setmaxxfrin
+dns_zone_setmaxxfrout
+dns_zone_setminrefreshtime
+dns_zone_setminretrytime
+dns_zone_setnodes
+dns_zone_setnotifyacl
+dns_zone_setnotifydelay
+dns_zone_setnotifysrc4
+dns_zone_setnotifysrc6
+dns_zone_setnotifytype
+dns_zone_setoption
+dns_zone_setorigin
+dns_zone_setprivatetype
+dns_zone_setqueryacl
+dns_zone_setqueryonacl
+dns_zone_setrequeststats
+dns_zone_setsignatures
+dns_zone_setsigresigninginterval
+dns_zone_setsigvalidityinterval
+dns_zone_setssutable
+dns_zone_setstatistics
+dns_zone_setstats
+dns_zone_settask
+dns_zone_settype
+dns_zone_setupdateacl
+dns_zone_setupdatedisabled
+dns_zone_setview
+dns_zone_setxfracl
+dns_zone_setxfrsource4
+dns_zone_setxfrsource6
+dns_zone_setzeronosoattl
+dns_zone_signwithkey
+dns_zone_unload
+dns_zonekey_iszonekey
+dns_zonemgr_attach
+dns_zonemgr_create
+dns_zonemgr_detach
+dns_zonemgr_forcemaint
+dns_zonemgr_getcount
+dns_zonemgr_getiolimit
+dns_zonemgr_getserialqueryrate
+dns_zonemgr_getttransfersin
+dns_zonemgr_getttransfersperns
+dns_zonemgr_managezone
+dns_zonemgr_releasezone
+dns_zonemgr_resumexfrs
+dns_zonemgr_setiolimit
+dns_zonemgr_setserialqueryrate
+dns_zonemgr_settransfersin
+dns_zonemgr_settransfersperns
+dns_zonemgr_shutdown
+dns_zt_apply
+dns_zt_attach
+dns_zt_create
+dns_zt_detach
+dns_zt_find
+dns_zt_flushanddetach
+dns_zt_load
+dns_zt_mount
+dns_zt_unmount
+dst_algorithm_supported
+dst_context_adddata
+dst_context_create
+dst_context_destroy
+dst_context_sign
+dst_context_verify
+dst_gssapi_acceptctx
+dst_gssapi_acquirecred
+dst_gssapi_initctx
+dst_key_alg
+dst_key_buildfilename
+dst_key_class
+dst_key_compare
+dst_key_computesecret
+dst_key_flags
+dst_key_free
+dst_key_frombuffer
+dst_key_fromdns
+dst_key_fromfile
+dst_key_fromgssapi
+dst_key_fromnamedfile
+dst_key_generate
+dst_key_id
+dst_key_isnullkey
+dst_key_isprivate
+dst_key_iszonekey
+dst_key_name
+dst_key_paramcompare
+dst_key_proto
+dst_key_secretsize
+dst_key_setbits
+dst_key_sigsize
+dst_key_size
+dst_key_tobuffer
+dst_key_todns
+dst_key_tofile
+dst_lib_destroy
+dst_lib_init
+dst_lib_initmsgcat
+dst_region_computeid
+dst_result_register
+dst_result_totext
+
+; Exported Data
+
+EXPORTS
+
+dns_master_style_full DATA
diff --git a/lib/dns/win32/libdns.dsp b/lib/dns/win32/libdns.dsp
new file mode 100644
index 0000000..5399b19
--- /dev/null
+++ b/lib/dns/win32/libdns.dsp
@@ -0,0 +1,737 @@
+# Microsoft Developer Studio Project File - Name="libdns" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libdns - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libdns.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libdns.mak" CFG="libdns - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libdns - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libdns - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "libdns_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../../../../openssl-0.9.8d/inc32/openssl/include" /I "./" /I "../../../" /I "include" /I "../include" /I "../../isc/win32" /I "../../isc/win32/include" /I "../../isc/include" /I "../../isc/noatomic/include" /I "../../../../openssl-0.9.8d/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBDNS_EXPORTS" /YX /FD /c
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../isc/win32/Release/libisc.lib ../../../../openssl-0.9.8d/out32dll/libeay32.lib /nologo /dll /machine:I386 /out:"../../../Build/Release/libdns.dll"
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "libdns_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../isc/win32" /I "../../isc/win32/include" /I "../../isc/include" /I "../../isc/noatomic/include" /I "../../../../openssl-0.9.8d/inc32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBDNS_EXPORTS" /FR /YX /FD /GZ /c
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../isc/win32/debug/libisc.lib ../../../../openssl-0.9.8d/out32dll/libeay32.lib /nologo /dll /map /debug /machine:I386 /out:"../../../Build/Debug/libdns.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "libdns - Win32 Release"
+# Name "libdns - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\dns\acache.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\acl.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\adb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\bit.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\byaddr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\cache.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\callbacks.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\cert.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\code.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\compress.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\db.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\dbiterator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\dbtable.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\diff.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\dispatch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\dlz.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\dnssec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\ds.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\enumclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\enumtype.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\events.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\fixedname.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\forward.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\iptable.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\journal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\keyflags.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\keytable.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\keyvalues.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\lib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\lookup.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\master.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\masterdump.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\message.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\name.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\ncache.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\nsec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\nsec3.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\order.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\peer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\portlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rbt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\rbtdb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\rbtdb64.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rcode.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rdata.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rdataclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rdatalist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rdataset.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rdatasetiter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rdataslab.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rdatastruct.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rdatatype.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\request.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\resolver.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\result.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\rootns.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\sdb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\sdlz.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\secalg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\secproto.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\soa.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\ssu.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\stats.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\tcpmsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\time.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\timer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\tkey.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\tsig.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\ttl.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\validator.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\version.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\view.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\xfrin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\zone.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\zonekey.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\dns\zt.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\acache.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\acl.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\adb.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\byaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\cache.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\callbacks.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\compress.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\db.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dbiterator.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dbtable.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\diff.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dispatch.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dlz.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\DLLMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dnssec.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ds.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\forward.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\iptable.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\journal.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\keytable.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lookup.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\master.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\masterdump.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\message.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\name.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ncache.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nsec.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nsec3.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\order.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\peer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\portlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rbt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rbtdb.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rbtdb64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rcode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rdata.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rdatalist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rdataset.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rdatasetiter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rdataslab.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\request.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\resolver.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\result.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rootns.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sdb.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\soa.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sdlz.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ssu.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\stats.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\tcpmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\time.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\timer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\tkey.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\tsig.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ttl.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\validator.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\view.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\xfrin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zone.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zonekey.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\zt.c
+# End Source File
+# End Group
+# Begin Group "dst"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\dst_api.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dst_lib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dst_parse.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\dst_result.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\gssapi_link.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\gssapictx.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\spnego.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hmac_link.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\key.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\openssl_link.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\openssldh_link.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\openssldsa_link.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\opensslrsa_link.c
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\libdns.def
+# End Source File
+# End Target
+# End Project
diff --git a/lib/dns/win32/libdns.dsw b/lib/dns/win32/libdns.dsw
new file mode 100644
index 0000000..424a2cb
--- /dev/null
+++ b/lib/dns/win32/libdns.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libdns"=".\libdns.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/dns/win32/libdns.mak b/lib/dns/win32/libdns.mak
new file mode 100644
index 0000000..507d083
--- /dev/null
+++ b/lib/dns/win32/libdns.mak
@@ -0,0 +1,2182 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on libdns.dsp
+!IF "$(CFG)" == ""
+CFG=libdns - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to libdns - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "libdns - Win32 Release" && "$(CFG)" != "libdns - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libdns.mak" CFG="libdns - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libdns - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libdns - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\libdns.dll"
+
+!ELSE
+
+ALL : "libisc - Win32 Release" "..\..\..\Build\Release\libdns.dll"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\acache.obj"
+ -@erase "$(INTDIR)\acl.obj"
+ -@erase "$(INTDIR)\adb.obj"
+ -@erase "$(INTDIR)\byaddr.obj"
+ -@erase "$(INTDIR)\cache.obj"
+ -@erase "$(INTDIR)\callbacks.obj"
+ -@erase "$(INTDIR)\compress.obj"
+ -@erase "$(INTDIR)\db.obj"
+ -@erase "$(INTDIR)\dbiterator.obj"
+ -@erase "$(INTDIR)\dbtable.obj"
+ -@erase "$(INTDIR)\diff.obj"
+ -@erase "$(INTDIR)\dispatch.obj"
+ -@erase "$(INTDIR)\dlz.obj"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\dnssec.obj"
+ -@erase "$(INTDIR)\ds.obj"
+ -@erase "$(INTDIR)\dst_api.obj"
+ -@erase "$(INTDIR)\dst_lib.obj"
+ -@erase "$(INTDIR)\dst_parse.obj"
+ -@erase "$(INTDIR)\dst_result.obj"
+ -@erase "$(INTDIR)\forward.obj"
+ -@erase "$(INTDIR)\gssapi_link.obj"
+ -@erase "$(INTDIR)\gssapictx.obj"
+ -@erase "$(INTDIR)\spnego.obj"
+ -@erase "$(INTDIR)\hmac_link.obj"
+ -@erase "$(INTDIR)\journal.obj"
+ -@erase "$(INTDIR)\key.obj"
+ -@erase "$(INTDIR)\keytable.obj"
+ -@erase "$(INTDIR)\lib.obj"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\lookup.obj"
+ -@erase "$(INTDIR)\master.obj"
+ -@erase "$(INTDIR)\masterdump.obj"
+ -@erase "$(INTDIR)\message.obj"
+ -@erase "$(INTDIR)\name.obj"
+ -@erase "$(INTDIR)\ncache.obj"
+ -@erase "$(INTDIR)\nsec.obj"
+ -@erase "$(INTDIR)\nsec3.obj"
+ -@erase "$(INTDIR)\openssl_link.obj"
+ -@erase "$(INTDIR)\openssldh_link.obj"
+ -@erase "$(INTDIR)\openssldsa_link.obj"
+ -@erase "$(INTDIR)\opensslrsa_link.obj"
+ -@erase "$(INTDIR)\order.obj"
+ -@erase "$(INTDIR)\peer.obj"
+ -@erase "$(INTDIR)\portlist.obj"
+ -@erase "$(INTDIR)\rbt.obj"
+ -@erase "$(INTDIR)\rbtdb.obj"
+ -@erase "$(INTDIR)\rbtdb64.obj"
+ -@erase "$(INTDIR)\rcode.obj"
+ -@erase "$(INTDIR)\rdata.obj"
+ -@erase "$(INTDIR)\rdatalist.obj"
+ -@erase "$(INTDIR)\rdataset.obj"
+ -@erase "$(INTDIR)\rdatasetiter.obj"
+ -@erase "$(INTDIR)\rdataslab.obj"
+ -@erase "$(INTDIR)\request.obj"
+ -@erase "$(INTDIR)\resolver.obj"
+ -@erase "$(INTDIR)\result.obj"
+ -@erase "$(INTDIR)\rootns.obj"
+ -@erase "$(INTDIR)\sdb.obj"
+ -@erase "$(INTDIR)\sdlz.obj"
+ -@erase "$(INTDIR)\soa.obj"
+ -@erase "$(INTDIR)\ssu.obj"
+ -@erase "$(INTDIR)\stats.obj"
+ -@erase "$(INTDIR)\tcpmsg.obj"
+ -@erase "$(INTDIR)\time.obj"
+ -@erase "$(INTDIR)\timer.obj"
+ -@erase "$(INTDIR)\tkey.obj"
+ -@erase "$(INTDIR)\tsig.obj"
+ -@erase "$(INTDIR)\ttl.obj"
+ -@erase "$(INTDIR)\validator.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(INTDIR)\view.obj"
+ -@erase "$(INTDIR)\xfrin.obj"
+ -@erase "$(INTDIR)\zone.obj"
+ -@erase "$(INTDIR)\zonekey.obj"
+ -@erase "$(INTDIR)\zt.obj"
+ -@erase "$(OUTDIR)\libdns.exp"
+ -@erase "$(OUTDIR)\libdns.lib"
+ -@erase "..\..\..\Build\Release\libdns.dll"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "../../../../../openssl-0.9.8d/inc32/openssl/include" /I "./" /I "../../../" /I "include" /I "../include" /I "../../isc/win32" /I "../../isc/win32/include" /I "../../isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../../openssl-0.9.8d/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBDNS_EXPORTS" /Fp"$(INTDIR)\libdns.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libdns.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../isc/win32/Release/libisc.lib ../../../../openssl-0.9.8d/out32dll/libeay32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libdns.pdb" /machine:I386 /def:".\libdns.def" /out:"../../../Build/Release/libdns.dll" /implib:"$(OUTDIR)\libdns.lib"
+DEF_FILE= \
+ ".\libdns.def"
+LINK32_OBJS= \
+ "$(INTDIR)\acache.obj" \
+ "$(INTDIR)\acl.obj" \
+ "$(INTDIR)\adb.obj" \
+ "$(INTDIR)\byaddr.obj" \
+ "$(INTDIR)\cache.obj" \
+ "$(INTDIR)\callbacks.obj" \
+ "$(INTDIR)\compress.obj" \
+ "$(INTDIR)\db.obj" \
+ "$(INTDIR)\dbiterator.obj" \
+ "$(INTDIR)\dbtable.obj" \
+ "$(INTDIR)\diff.obj" \
+ "$(INTDIR)\dispatch.obj" \
+ "$(INTDIR)\dlz.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\dnssec.obj" \
+ "$(INTDIR)\ds.obj" \
+ "$(INTDIR)\forward.obj" \
+ "$(INTDIR)\journal.obj" \
+ "$(INTDIR)\keytable.obj" \
+ "$(INTDIR)\lib.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\lookup.obj" \
+ "$(INTDIR)\master.obj" \
+ "$(INTDIR)\masterdump.obj" \
+ "$(INTDIR)\message.obj" \
+ "$(INTDIR)\name.obj" \
+ "$(INTDIR)\ncache.obj" \
+ "$(INTDIR)\nsec.obj" \
+ "$(INTDIR)\nsec3.obj" \
+ "$(INTDIR)\order.obj" \
+ "$(INTDIR)\peer.obj" \
+ "$(INTDIR)\portlist.obj" \
+ "$(INTDIR)\rbt.obj" \
+ "$(INTDIR)\rbtdb.obj" \
+ "$(INTDIR)\rbtdb64.obj" \
+ "$(INTDIR)\rcode.obj" \
+ "$(INTDIR)\rdata.obj" \
+ "$(INTDIR)\rdatalist.obj" \
+ "$(INTDIR)\rdataset.obj" \
+ "$(INTDIR)\rdatasetiter.obj" \
+ "$(INTDIR)\rdataslab.obj" \
+ "$(INTDIR)\request.obj" \
+ "$(INTDIR)\resolver.obj" \
+ "$(INTDIR)\result.obj" \
+ "$(INTDIR)\rootns.obj" \
+ "$(INTDIR)\sdb.obj" \
+ "$(INTDIR)\sdlz.obj" \
+ "$(INTDIR)\soa.obj" \
+ "$(INTDIR)\ssu.obj" \
+ "$(INTDIR)\stats.obj" \
+ "$(INTDIR)\tcpmsg.obj" \
+ "$(INTDIR)\time.obj" \
+ "$(INTDIR)\timer.obj" \
+ "$(INTDIR)\tkey.obj" \
+ "$(INTDIR)\tsig.obj" \
+ "$(INTDIR)\ttl.obj" \
+ "$(INTDIR)\validator.obj" \
+ "$(INTDIR)\version.obj" \
+ "$(INTDIR)\view.obj" \
+ "$(INTDIR)\xfrin.obj" \
+ "$(INTDIR)\zone.obj" \
+ "$(INTDIR)\zonekey.obj" \
+ "$(INTDIR)\zt.obj" \
+ "$(INTDIR)\dst_api.obj" \
+ "$(INTDIR)\dst_lib.obj" \
+ "$(INTDIR)\dst_parse.obj" \
+ "$(INTDIR)\dst_result.obj" \
+ "$(INTDIR)\gssapi_link.obj" \
+ "$(INTDIR)\gssapictx.obj" \
+ "$(INTDIR)\spnego.obj" \
+ "$(INTDIR)\hmac_link.obj" \
+ "$(INTDIR)\key.obj" \
+ "$(INTDIR)\openssl_link.obj" \
+ "$(INTDIR)\openssldh_link.obj" \
+ "$(INTDIR)\openssldsa_link.obj" \
+ "$(INTDIR)\opensslrsa_link.obj" \
+ "..\..\isc\win32\Release\libisc.lib"
+
+"..\..\..\Build\Release\libdns.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\libdns.dll" "$(OUTDIR)\libdns.bsc"
+
+!ELSE
+
+ALL : "libisc - Win32 Debug" "..\..\..\Build\Debug\libdns.dll" "$(OUTDIR)\libdns.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\acache.obj"
+ -@erase "$(INTDIR)\acache.sbr"
+ -@erase "$(INTDIR)\acl.obj"
+ -@erase "$(INTDIR)\acl.sbr"
+ -@erase "$(INTDIR)\adb.obj"
+ -@erase "$(INTDIR)\adb.sbr"
+ -@erase "$(INTDIR)\byaddr.obj"
+ -@erase "$(INTDIR)\byaddr.sbr"
+ -@erase "$(INTDIR)\cache.obj"
+ -@erase "$(INTDIR)\cache.sbr"
+ -@erase "$(INTDIR)\callbacks.obj"
+ -@erase "$(INTDIR)\callbacks.sbr"
+ -@erase "$(INTDIR)\compress.obj"
+ -@erase "$(INTDIR)\compress.sbr"
+ -@erase "$(INTDIR)\db.obj"
+ -@erase "$(INTDIR)\db.sbr"
+ -@erase "$(INTDIR)\dbiterator.obj"
+ -@erase "$(INTDIR)\dbiterator.sbr"
+ -@erase "$(INTDIR)\dbtable.obj"
+ -@erase "$(INTDIR)\dbtable.sbr"
+ -@erase "$(INTDIR)\diff.obj"
+ -@erase "$(INTDIR)\diff.sbr"
+ -@erase "$(INTDIR)\dispatch.obj"
+ -@erase "$(INTDIR)\dispatch.sbr"
+ -@erase "$(INTDIR)\dlz.obj"
+ -@erase "$(INTDIR)\dlz.sbr"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\DLLMain.sbr"
+ -@erase "$(INTDIR)\dnssec.obj"
+ -@erase "$(INTDIR)\dnssec.sbr"
+ -@erase "$(INTDIR)\ds.obj"
+ -@erase "$(INTDIR)\ds.sbr"
+ -@erase "$(INTDIR)\dst_api.obj"
+ -@erase "$(INTDIR)\dst_api.sbr"
+ -@erase "$(INTDIR)\dst_lib.obj"
+ -@erase "$(INTDIR)\dst_lib.sbr"
+ -@erase "$(INTDIR)\dst_parse.obj"
+ -@erase "$(INTDIR)\dst_parse.sbr"
+ -@erase "$(INTDIR)\dst_result.obj"
+ -@erase "$(INTDIR)\dst_result.sbr"
+ -@erase "$(INTDIR)\forward.obj"
+ -@erase "$(INTDIR)\forward.sbr"
+ -@erase "$(INTDIR)\gssapi_link.obj"
+ -@erase "$(INTDIR)\gssapi_link.sbr"
+ -@erase "$(INTDIR)\gssapictx.obj"
+ -@erase "$(INTDIR)\gssapictx.sbr"
+ -@erase "$(INTDIR)\spnego.obj"
+ -@erase "$(INTDIR)\spnego.sbr"
+ -@erase "$(INTDIR)\hmac_link.obj"
+ -@erase "$(INTDIR)\hmac_link.sbr"
+ -@erase "$(INTDIR)\journal.obj"
+ -@erase "$(INTDIR)\journal.sbr"
+ -@erase "$(INTDIR)\key.obj"
+ -@erase "$(INTDIR)\key.sbr"
+ -@erase "$(INTDIR)\keytable.obj"
+ -@erase "$(INTDIR)\keytable.sbr"
+ -@erase "$(INTDIR)\lib.obj"
+ -@erase "$(INTDIR)\lib.sbr"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\log.sbr"
+ -@erase "$(INTDIR)\lookup.obj"
+ -@erase "$(INTDIR)\lookup.sbr"
+ -@erase "$(INTDIR)\master.obj"
+ -@erase "$(INTDIR)\master.sbr"
+ -@erase "$(INTDIR)\masterdump.obj"
+ -@erase "$(INTDIR)\masterdump.sbr"
+ -@erase "$(INTDIR)\message.obj"
+ -@erase "$(INTDIR)\message.sbr"
+ -@erase "$(INTDIR)\name.obj"
+ -@erase "$(INTDIR)\name.sbr"
+ -@erase "$(INTDIR)\ncache.obj"
+ -@erase "$(INTDIR)\ncache.sbr"
+ -@erase "$(INTDIR)\nsec.obj"
+ -@erase "$(INTDIR)\nsec.sbr"
+ -@erase "$(INTDIR)\nsec3.obj"
+ -@erase "$(INTDIR)\nsec3.sbr"
+ -@erase "$(INTDIR)\openssl_link.obj"
+ -@erase "$(INTDIR)\openssl_link.sbr"
+ -@erase "$(INTDIR)\openssldh_link.obj"
+ -@erase "$(INTDIR)\openssldh_link.sbr"
+ -@erase "$(INTDIR)\openssldsa_link.obj"
+ -@erase "$(INTDIR)\openssldsa_link.sbr"
+ -@erase "$(INTDIR)\opensslrsa_link.obj"
+ -@erase "$(INTDIR)\opensslrsa_link.sbr"
+ -@erase "$(INTDIR)\order.obj"
+ -@erase "$(INTDIR)\order.sbr"
+ -@erase "$(INTDIR)\peer.obj"
+ -@erase "$(INTDIR)\peer.sbr"
+ -@erase "$(INTDIR)\portlist.obj"
+ -@erase "$(INTDIR)\portlist.sbr"
+ -@erase "$(INTDIR)\rbt.obj"
+ -@erase "$(INTDIR)\rbt.sbr"
+ -@erase "$(INTDIR)\rbtdb.obj"
+ -@erase "$(INTDIR)\rbtdb.sbr"
+ -@erase "$(INTDIR)\rbtdb64.obj"
+ -@erase "$(INTDIR)\rbtdb64.sbr"
+ -@erase "$(INTDIR)\rcode.obj"
+ -@erase "$(INTDIR)\rcode.sbr"
+ -@erase "$(INTDIR)\rdata.obj"
+ -@erase "$(INTDIR)\rdata.sbr"
+ -@erase "$(INTDIR)\rdatalist.obj"
+ -@erase "$(INTDIR)\rdatalist.sbr"
+ -@erase "$(INTDIR)\rdataset.obj"
+ -@erase "$(INTDIR)\rdataset.sbr"
+ -@erase "$(INTDIR)\rdatasetiter.obj"
+ -@erase "$(INTDIR)\rdatasetiter.sbr"
+ -@erase "$(INTDIR)\rdataslab.obj"
+ -@erase "$(INTDIR)\rdataslab.sbr"
+ -@erase "$(INTDIR)\request.obj"
+ -@erase "$(INTDIR)\request.sbr"
+ -@erase "$(INTDIR)\resolver.obj"
+ -@erase "$(INTDIR)\resolver.sbr"
+ -@erase "$(INTDIR)\result.obj"
+ -@erase "$(INTDIR)\result.sbr"
+ -@erase "$(INTDIR)\rootns.obj"
+ -@erase "$(INTDIR)\rootns.sbr"
+ -@erase "$(INTDIR)\sdb.obj"
+ -@erase "$(INTDIR)\sdb.sbr"
+ -@erase "$(INTDIR)\sdlz.obj"
+ -@erase "$(INTDIR)\sdlz.sbr"
+ -@erase "$(INTDIR)\soa.obj"
+ -@erase "$(INTDIR)\soa.sbr"
+ -@erase "$(INTDIR)\ssu.obj"
+ -@erase "$(INTDIR)\ssu.sbr"
+ -@erase "$(INTDIR)\stats.obj"
+ -@erase "$(INTDIR)\stats.sbr"
+ -@erase "$(INTDIR)\tcpmsg.obj"
+ -@erase "$(INTDIR)\tcpmsg.sbr"
+ -@erase "$(INTDIR)\time.obj"
+ -@erase "$(INTDIR)\time.sbr"
+ -@erase "$(INTDIR)\timer.obj"
+ -@erase "$(INTDIR)\timer.sbr"
+ -@erase "$(INTDIR)\tkey.obj"
+ -@erase "$(INTDIR)\tkey.sbr"
+ -@erase "$(INTDIR)\tsig.obj"
+ -@erase "$(INTDIR)\tsig.sbr"
+ -@erase "$(INTDIR)\ttl.obj"
+ -@erase "$(INTDIR)\ttl.sbr"
+ -@erase "$(INTDIR)\validator.obj"
+ -@erase "$(INTDIR)\validator.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(INTDIR)\version.sbr"
+ -@erase "$(INTDIR)\view.obj"
+ -@erase "$(INTDIR)\view.sbr"
+ -@erase "$(INTDIR)\xfrin.obj"
+ -@erase "$(INTDIR)\xfrin.sbr"
+ -@erase "$(INTDIR)\zone.obj"
+ -@erase "$(INTDIR)\zone.sbr"
+ -@erase "$(INTDIR)\zonekey.obj"
+ -@erase "$(INTDIR)\zonekey.sbr"
+ -@erase "$(INTDIR)\zt.obj"
+ -@erase "$(INTDIR)\zt.sbr"
+ -@erase "$(OUTDIR)\libdns.bsc"
+ -@erase "$(OUTDIR)\libdns.exp"
+ -@erase "$(OUTDIR)\libdns.lib"
+ -@erase "$(OUTDIR)\libdns.map"
+ -@erase "$(OUTDIR)\libdns.pdb"
+ -@erase "..\..\..\Build\Debug\libdns.dll"
+ -@erase "..\..\..\Build\Debug\libdns.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../isc/win32" /I "../../isc/win32/include" /I "../../isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../../openssl-0.9.8d/inc32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBDNS_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libdns.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+MTL=midl.exe
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC=rc.exe
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libdns.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\acache.sbr" \
+ "$(INTDIR)\acl.sbr" \
+ "$(INTDIR)\adb.sbr" \
+ "$(INTDIR)\byaddr.sbr" \
+ "$(INTDIR)\cache.sbr" \
+ "$(INTDIR)\callbacks.sbr" \
+ "$(INTDIR)\compress.sbr" \
+ "$(INTDIR)\db.sbr" \
+ "$(INTDIR)\dbiterator.sbr" \
+ "$(INTDIR)\dbtable.sbr" \
+ "$(INTDIR)\diff.sbr" \
+ "$(INTDIR)\dispatch.sbr" \
+ "$(INTDIR)\dlz.sbr" \
+ "$(INTDIR)\DLLMain.sbr" \
+ "$(INTDIR)\dnssec.sbr" \
+ "$(INTDIR)\ds.sbr" \
+ "$(INTDIR)\forward.sbr" \
+ "$(INTDIR)\journal.sbr" \
+ "$(INTDIR)\keytable.sbr" \
+ "$(INTDIR)\lib.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\lookup.sbr" \
+ "$(INTDIR)\master.sbr" \
+ "$(INTDIR)\masterdump.sbr" \
+ "$(INTDIR)\message.sbr" \
+ "$(INTDIR)\name.sbr" \
+ "$(INTDIR)\ncache.sbr" \
+ "$(INTDIR)\nsec.sbr" \
+ "$(INTDIR)\nsec3.sbr" \
+ "$(INTDIR)\order.sbr" \
+ "$(INTDIR)\peer.sbr" \
+ "$(INTDIR)\portlist.sbr" \
+ "$(INTDIR)\rbt.sbr" \
+ "$(INTDIR)\rbtdb.sbr" \
+ "$(INTDIR)\rbtdb64.sbr" \
+ "$(INTDIR)\rcode.sbr" \
+ "$(INTDIR)\rdata.sbr" \
+ "$(INTDIR)\rdatalist.sbr" \
+ "$(INTDIR)\rdataset.sbr" \
+ "$(INTDIR)\rdatasetiter.sbr" \
+ "$(INTDIR)\rdataslab.sbr" \
+ "$(INTDIR)\request.sbr" \
+ "$(INTDIR)\resolver.sbr" \
+ "$(INTDIR)\result.sbr" \
+ "$(INTDIR)\rootns.sbr" \
+ "$(INTDIR)\sdb.sbr" \
+ "$(INTDIR)\sdlz.sbr" \
+ "$(INTDIR)\soa.sbr" \
+ "$(INTDIR)\ssu.sbr" \
+ "$(INTDIR)\stats.sbr" \
+ "$(INTDIR)\tcpmsg.sbr" \
+ "$(INTDIR)\time.sbr" \
+ "$(INTDIR)\timer.sbr" \
+ "$(INTDIR)\tkey.sbr" \
+ "$(INTDIR)\tsig.sbr" \
+ "$(INTDIR)\ttl.sbr" \
+ "$(INTDIR)\validator.sbr" \
+ "$(INTDIR)\version.sbr" \
+ "$(INTDIR)\view.sbr" \
+ "$(INTDIR)\xfrin.sbr" \
+ "$(INTDIR)\zone.sbr" \
+ "$(INTDIR)\zonekey.sbr" \
+ "$(INTDIR)\zt.sbr" \
+ "$(INTDIR)\dst_api.sbr" \
+ "$(INTDIR)\dst_lib.sbr" \
+ "$(INTDIR)\dst_parse.sbr" \
+ "$(INTDIR)\dst_result.sbr" \
+ "$(INTDIR)\gssapi_link.sbr" \
+ "$(INTDIR)\gssapictx.sbr" \
+ "$(INTDIR)\spnego.sbr" \
+ "$(INTDIR)\hmac_link.sbr" \
+ "$(INTDIR)\key.sbr" \
+ "$(INTDIR)\openssl_link.sbr" \
+ "$(INTDIR)\openssldh_link.sbr" \
+ "$(INTDIR)\openssldsa_link.sbr" \
+ "$(INTDIR)\opensslrsa_link.sbr"
+
+"$(OUTDIR)\libdns.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../isc/win32/debug/libisc.lib ../../../../openssl-0.9.8d/out32dll/libeay32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libdns.pdb" /map:"$(INTDIR)\libdns.map" /debug /machine:I386 /def:".\libdns.def" /out:"../../../Build/Debug/libdns.dll" /implib:"$(OUTDIR)\libdns.lib" /pdbtype:sept
+DEF_FILE= \
+ ".\libdns.def"
+LINK32_OBJS= \
+ "$(INTDIR)\acache.obj" \
+ "$(INTDIR)\acl.obj" \
+ "$(INTDIR)\adb.obj" \
+ "$(INTDIR)\byaddr.obj" \
+ "$(INTDIR)\cache.obj" \
+ "$(INTDIR)\callbacks.obj" \
+ "$(INTDIR)\compress.obj" \
+ "$(INTDIR)\db.obj" \
+ "$(INTDIR)\dbiterator.obj" \
+ "$(INTDIR)\dbtable.obj" \
+ "$(INTDIR)\diff.obj" \
+ "$(INTDIR)\dispatch.obj" \
+ "$(INTDIR)\dlz.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\dnssec.obj" \
+ "$(INTDIR)\ds.obj" \
+ "$(INTDIR)\forward.obj" \
+ "$(INTDIR)\journal.obj" \
+ "$(INTDIR)\keytable.obj" \
+ "$(INTDIR)\lib.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\lookup.obj" \
+ "$(INTDIR)\master.obj" \
+ "$(INTDIR)\masterdump.obj" \
+ "$(INTDIR)\message.obj" \
+ "$(INTDIR)\name.obj" \
+ "$(INTDIR)\ncache.obj" \
+ "$(INTDIR)\nsec.obj" \
+ "$(INTDIR)\nsec3.obj" \
+ "$(INTDIR)\order.obj" \
+ "$(INTDIR)\peer.obj" \
+ "$(INTDIR)\portlist.obj" \
+ "$(INTDIR)\rbt.obj" \
+ "$(INTDIR)\rbtdb.obj" \
+ "$(INTDIR)\rbtdb64.obj" \
+ "$(INTDIR)\rcode.obj" \
+ "$(INTDIR)\rdata.obj" \
+ "$(INTDIR)\rdatalist.obj" \
+ "$(INTDIR)\rdataset.obj" \
+ "$(INTDIR)\rdatasetiter.obj" \
+ "$(INTDIR)\rdataslab.obj" \
+ "$(INTDIR)\request.obj" \
+ "$(INTDIR)\resolver.obj" \
+ "$(INTDIR)\result.obj" \
+ "$(INTDIR)\rootns.obj" \
+ "$(INTDIR)\sdb.obj" \
+ "$(INTDIR)\sdlz.obj" \
+ "$(INTDIR)\soa.obj" \
+ "$(INTDIR)\ssu.obj" \
+ "$(INTDIR)\stats.obj" \
+ "$(INTDIR)\tcpmsg.obj" \
+ "$(INTDIR)\time.obj" \
+ "$(INTDIR)\timer.obj" \
+ "$(INTDIR)\tkey.obj" \
+ "$(INTDIR)\tsig.obj" \
+ "$(INTDIR)\ttl.obj" \
+ "$(INTDIR)\validator.obj" \
+ "$(INTDIR)\version.obj" \
+ "$(INTDIR)\view.obj" \
+ "$(INTDIR)\xfrin.obj" \
+ "$(INTDIR)\zone.obj" \
+ "$(INTDIR)\zonekey.obj" \
+ "$(INTDIR)\zt.obj" \
+ "$(INTDIR)\dst_api.obj" \
+ "$(INTDIR)\dst_lib.obj" \
+ "$(INTDIR)\dst_parse.obj" \
+ "$(INTDIR)\dst_result.obj" \
+ "$(INTDIR)\gssapi_link.obj" \
+ "$(INTDIR)\gssapictx.obj" \
+ "$(INTDIR)\spnego.obj" \
+ "$(INTDIR)\hmac_link.obj" \
+ "$(INTDIR)\key.obj" \
+ "$(INTDIR)\openssl_link.obj" \
+ "$(INTDIR)\openssldh_link.obj" \
+ "$(INTDIR)\openssldsa_link.obj" \
+ "$(INTDIR)\opensslrsa_link.obj" \
+ "..\..\isc\win32\Debug\libisc.lib"
+
+"..\..\..\Build\Debug\libdns.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ENDIF
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("libdns.dep")
+!INCLUDE "libdns.dep"
+!ELSE
+!MESSAGE Warning: cannot find "libdns.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "libdns - Win32 Release" || "$(CFG)" == "libdns - Win32 Debug"
+SOURCE=..\acache.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\acache.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\acache.obj" "$(INTDIR)\acache.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\acl.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\acl.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\acl.obj" "$(INTDIR)\acl.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\adb.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\adb.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\adb.obj" "$(INTDIR)\adb.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\byaddr.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\byaddr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\byaddr.obj" "$(INTDIR)\byaddr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\cache.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\cache.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\cache.obj" "$(INTDIR)\cache.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\callbacks.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\callbacks.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\callbacks.obj" "$(INTDIR)\callbacks.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\compress.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\compress.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\compress.obj" "$(INTDIR)\compress.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\db.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\db.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\db.obj" "$(INTDIR)\db.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dbiterator.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\dbiterator.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\dbiterator.obj" "$(INTDIR)\dbiterator.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dbtable.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\dbtable.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\dbtable.obj" "$(INTDIR)\dbtable.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\diff.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\diff.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\diff.obj" "$(INTDIR)\diff.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dispatch.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+CPP_SWITCHES=/nologo /MD /W3 /GX /O2 /I "../../../../../openssl-0.9.8d/inc32/openssl/include" /I "./" /I "../../../" /I "include" /I "../include" /I "../../isc/win32" /I "../../isc/win32/include" /I "../../isc/include" /I "../../isc/noatomic/include" /I "../../../../openssl-0.9.8d/inc32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBDNS_EXPORTS" /Fp"$(INTDIR)\libdns.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+
+"$(INTDIR)\dispatch.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+CPP_SWITCHES=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../isc/win32" /I "../../isc/win32/include" /I "../../isc/include" /I "../../isc/noatomic/include" /I "../../../../openssl-0.9.8d/inc32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBDNS_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libdns.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+
+"$(INTDIR)\dispatch.obj" "$(INTDIR)\dispatch.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) @<<
+ $(CPP_SWITCHES) $(SOURCE)
+<<
+
+
+!ENDIF
+
+SOURCE=..\dlz.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\dlz.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+"$(INTDIR)\dlz.obj" "$(INTDIR)\dlz.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\DLLMain.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\DLLMain.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\DLLMain.obj" "$(INTDIR)\DLLMain.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\dnssec.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\dnssec.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\dnssec.obj" "$(INTDIR)\dnssec.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ds.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\ds.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\ds.obj" "$(INTDIR)\ds.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\forward.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\forward.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\forward.obj" "$(INTDIR)\forward.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\iptable.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\iptable.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\iptable.obj" "$(INTDIR)\iptable.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\journal.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\journal.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\journal.obj" "$(INTDIR)\journal.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\keytable.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\keytable.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\keytable.obj" "$(INTDIR)\keytable.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lib.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\lib.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\lib.obj" "$(INTDIR)\lib.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\log.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\log.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lookup.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\lookup.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\lookup.obj" "$(INTDIR)\lookup.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\master.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\master.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\master.obj" "$(INTDIR)\master.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\masterdump.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\masterdump.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\masterdump.obj" "$(INTDIR)\masterdump.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\message.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\message.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\message.obj" "$(INTDIR)\message.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\name.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\name.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\name.obj" "$(INTDIR)\name.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ncache.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\ncache.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\ncache.obj" "$(INTDIR)\ncache.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\nsec.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\nsec.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\nsec.obj" "$(INTDIR)\nsec.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\nsec3.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\nsec3.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\nsec3.obj" "$(INTDIR)\nsec3.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\order.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\order.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\order.obj" "$(INTDIR)\order.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\peer.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\peer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\peer.obj" "$(INTDIR)\peer.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+SOURCE=..\portlist.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\portlist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\portlist.obj" "$(INTDIR)\portlist.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rbt.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rbt.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rbt.obj" "$(INTDIR)\rbt.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rbtdb.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rbtdb.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rbtdb.obj" "$(INTDIR)\rbtdb.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rbtdb64.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rbtdb64.obj" : $(SOURCE) "$(INTDIR)" "..\rbtdb.c"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rbtdb64.obj" "$(INTDIR)\rbtdb64.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rcode.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rcode.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rcode.obj" "$(INTDIR)\rcode.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rdata.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rdata.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rdata.obj" "$(INTDIR)\rdata.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rdatalist.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rdatalist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rdatalist.obj" "$(INTDIR)\rdatalist.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rdataset.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rdataset.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rdataset.obj" "$(INTDIR)\rdataset.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rdatasetiter.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rdatasetiter.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rdatasetiter.obj" "$(INTDIR)\rdatasetiter.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rdataslab.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rdataslab.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rdataslab.obj" "$(INTDIR)\rdataslab.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\request.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\request.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\request.obj" "$(INTDIR)\request.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\resolver.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\resolver.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\resolver.obj" "$(INTDIR)\resolver.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\result.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\result.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\result.obj" "$(INTDIR)\result.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rootns.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\rootns.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\rootns.obj" "$(INTDIR)\rootns.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sdb.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\sdb.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\sdb.obj" "$(INTDIR)\sdb.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sdlz.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\sdlz.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\sdlz.obj" "$(INTDIR)\sdlz.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\soa.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\soa.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\soa.obj" "$(INTDIR)\soa.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ssu.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\ssu.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\ssu.obj" "$(INTDIR)\ssu.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\stats.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\stats.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\stats.obj" "$(INTDIR)\stats.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\tcpmsg.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\tcpmsg.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\tcpmsg.obj" "$(INTDIR)\tcpmsg.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\time.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\time.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\time.obj" "$(INTDIR)\time.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\timer.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\timer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\timer.obj" "$(INTDIR)\timer.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\tkey.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\tkey.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\tkey.obj" "$(INTDIR)\tkey.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\tsig.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\tsig.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\tsig.obj" "$(INTDIR)\tsig.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ttl.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\ttl.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\ttl.obj" "$(INTDIR)\ttl.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\validator.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\validator.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\validator.obj" "$(INTDIR)\validator.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\version.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\version.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\version.obj" "$(INTDIR)\version.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\view.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\view.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\view.obj" "$(INTDIR)\view.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\xfrin.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\xfrin.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\xfrin.obj" "$(INTDIR)\xfrin.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\zone.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\zone.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\zone.obj" "$(INTDIR)\zone.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\zonekey.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\zonekey.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\zonekey.obj" "$(INTDIR)\zonekey.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\zt.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\zt.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\zt.obj" "$(INTDIR)\zt.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dst_api.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\dst_api.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\dst_api.obj" "$(INTDIR)\dst_api.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dst_lib.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\dst_lib.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\dst_lib.obj" "$(INTDIR)\dst_lib.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dst_parse.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\dst_parse.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\dst_parse.obj" "$(INTDIR)\dst_parse.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dst_result.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\dst_result.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\dst_result.obj" "$(INTDIR)\dst_result.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\gssapi_link.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\gssapi_link.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\gssapi_link.obj" "$(INTDIR)\gssapi_link.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\gssapictx.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\gssapictx.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\gssapictx.obj" "$(INTDIR)\gssapictx.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\spnego.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\spnego.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\spnego.obj" "$(INTDIR)\spnego.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hmac_link.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\hmac_link.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\hmac_link.obj" "$(INTDIR)\hmac_link.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\key.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\key.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\key.obj" "$(INTDIR)\key.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\openssl_link.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\openssl_link.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\openssl_link.obj" "$(INTDIR)\openssl_link.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\openssldh_link.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\openssldh_link.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\openssldh_link.obj" "$(INTDIR)\openssldh_link.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\openssldsa_link.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\openssldsa_link.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\openssldsa_link.obj" "$(INTDIR)\openssldsa_link.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\opensslrsa_link.c
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+
+"$(INTDIR)\opensslrsa_link.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+
+"$(INTDIR)\opensslrsa_link.obj" "$(INTDIR)\opensslrsa_link.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "libdns - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\dns\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\dns\win32"
+
+!ELSEIF "$(CFG)" == "libdns - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\dns\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\dns\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/lib/dns/win32/version.c b/lib/dns/win32/version.c
new file mode 100644
index 0000000..a570183
--- /dev/null
+++ b/lib/dns/win32/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: version.c,v 1.6 2007/06/19 23:47:17 tbox Exp $ */
+
+#include <versions.h>
+
+#include <dns/version.h>
+
+LIBDNS_EXTERNAL_DATA const char dns_version[] = VERSION;
+
+LIBDNS_EXTERNAL_DATA const unsigned int dns_libinterface = LIBINTERFACE;
+LIBDNS_EXTERNAL_DATA const unsigned int dns_librevision = LIBREVISION;
+LIBDNS_EXTERNAL_DATA const unsigned int dns_libage = LIBAGE;
diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c
new file mode 100644
index 0000000..4e3d2c3
--- /dev/null
+++ b/lib/dns/xfrin.c
@@ -0,0 +1,1532 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: xfrin.c,v 1.166 2008/09/25 04:12:39 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/diff.h>
+#include <dns/events.h>
+#include <dns/journal.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/result.h>
+#include <dns/soa.h>
+#include <dns/tcpmsg.h>
+#include <dns/timer.h>
+#include <dns/tsig.h>
+#include <dns/view.h>
+#include <dns/xfrin.h>
+#include <dns/zone.h>
+
+#include <dst/dst.h>
+
+/*
+ * Incoming AXFR and IXFR.
+ */
+
+/*%
+ * It would be non-sensical (or at least obtuse) to use FAIL() with an
+ * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+#define FAIL(code) \
+ do { result = (code); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+/*%
+ * The states of the *XFR state machine. We handle both IXFR and AXFR
+ * with a single integrated state machine because they cannot be distinguished
+ * immediately - an AXFR response to an IXFR request can only be detected
+ * when the first two (2) response RRs have already been received.
+ */
+typedef enum {
+ XFRST_SOAQUERY,
+ XFRST_GOTSOA,
+ XFRST_INITIALSOA,
+ XFRST_FIRSTDATA,
+ XFRST_IXFR_DELSOA,
+ XFRST_IXFR_DEL,
+ XFRST_IXFR_ADDSOA,
+ XFRST_IXFR_ADD,
+ XFRST_AXFR,
+ XFRST_END
+} xfrin_state_t;
+
+/*%
+ * Incoming zone transfer context.
+ */
+
+struct dns_xfrin_ctx {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ dns_zone_t *zone;
+
+ int refcount;
+
+ isc_task_t *task;
+ isc_timer_t *timer;
+ isc_socketmgr_t *socketmgr;
+
+ int connects; /*%< Connect in progress */
+ int sends; /*%< Send in progress */
+ int recvs; /*%< Receive in progress */
+ isc_boolean_t shuttingdown;
+
+ dns_name_t name; /*%< Name of zone to transfer */
+ dns_rdataclass_t rdclass;
+
+ isc_boolean_t checkid;
+ dns_messageid_t id;
+
+ /*%
+ * Requested transfer type (dns_rdatatype_axfr or
+ * dns_rdatatype_ixfr). The actual transfer type
+ * may differ due to IXFR->AXFR fallback.
+ */
+ dns_rdatatype_t reqtype;
+
+ isc_sockaddr_t masteraddr;
+ isc_sockaddr_t sourceaddr;
+ isc_socket_t *socket;
+
+ /*% Buffer for IXFR/AXFR request message */
+ isc_buffer_t qbuffer;
+ unsigned char qbuffer_data[512];
+
+ /*% Incoming reply TCP message */
+ dns_tcpmsg_t tcpmsg;
+ isc_boolean_t tcpmsg_valid;
+
+ dns_db_t *db;
+ dns_dbversion_t *ver;
+ dns_diff_t diff; /*%< Pending database changes */
+ int difflen; /*%< Number of pending tuples */
+
+ xfrin_state_t state;
+ isc_uint32_t end_serial;
+ isc_boolean_t is_ixfr;
+
+ unsigned int nmsg; /*%< Number of messages recvd */
+ unsigned int nrecs; /*%< Number of records recvd */
+ isc_uint64_t nbytes; /*%< Number of bytes received */
+
+ isc_time_t start; /*%< Start time of the transfer */
+ isc_time_t end; /*%< End time of the transfer */
+
+ dns_tsigkey_t *tsigkey; /*%< Key used to create TSIG */
+ isc_buffer_t *lasttsig; /*%< The last TSIG */
+ dst_context_t *tsigctx; /*%< TSIG verification context */
+ unsigned int sincetsig; /*%< recvd since the last TSIG */
+ dns_xfrindone_t done;
+
+ /*%
+ * AXFR- and IXFR-specific data. Only one is used at a time
+ * according to the is_ixfr flag, so this could be a union,
+ * but keeping them separate makes it a bit simpler to clean
+ * things up when destroying the context.
+ */
+ struct {
+ dns_addrdatasetfunc_t add_func;
+ dns_dbload_t *add_private;
+ } axfr;
+
+ struct {
+ isc_uint32_t request_serial;
+ isc_uint32_t current_serial;
+ dns_journal_t *journal;
+
+ } ixfr;
+};
+
+#define XFRIN_MAGIC ISC_MAGIC('X', 'f', 'r', 'I')
+#define VALID_XFRIN(x) ISC_MAGIC_VALID(x, XFRIN_MAGIC)
+
+/**************************************************************************/
+/*
+ * Forward declarations.
+ */
+
+static isc_result_t
+xfrin_create(isc_mem_t *mctx,
+ dns_zone_t *zone,
+ dns_db_t *db,
+ isc_task_t *task,
+ isc_timermgr_t *timermgr,
+ isc_socketmgr_t *socketmgr,
+ dns_name_t *zonename,
+ dns_rdataclass_t rdclass,
+ dns_rdatatype_t reqtype,
+ isc_sockaddr_t *masteraddr,
+ isc_sockaddr_t *sourceaddr,
+ dns_tsigkey_t *tsigkey,
+ dns_xfrin_ctx_t **xfrp);
+
+static isc_result_t axfr_init(dns_xfrin_ctx_t *xfr);
+static isc_result_t axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
+static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
+ dns_name_t *name, dns_ttl_t ttl,
+ 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 ixfr_init(dns_xfrin_ctx_t *xfr);
+static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);
+static isc_result_t ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
+ dns_name_t *name, dns_ttl_t ttl,
+ dns_rdata_t *rdata);
+static isc_result_t ixfr_commit(dns_xfrin_ctx_t *xfr);
+
+static isc_result_t xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name,
+ isc_uint32_t ttl, dns_rdata_t *rdata);
+
+static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);
+
+static void xfrin_connect_done(isc_task_t *task, isc_event_t *event);
+static isc_result_t xfrin_send_request(dns_xfrin_ctx_t *xfr);
+static void xfrin_send_done(isc_task_t *task, isc_event_t *event);
+static void xfrin_sendlen_done(isc_task_t *task, isc_event_t *event);
+static void xfrin_recv_done(isc_task_t *task, isc_event_t *event);
+static void xfrin_timeout(isc_task_t *task, isc_event_t *event);
+
+static void maybe_free(dns_xfrin_ctx_t *xfr);
+
+static void
+xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);
+static isc_result_t
+render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
+
+static void
+xfrin_logv(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
+ const char *fmt, va_list ap)
+ ISC_FORMAT_PRINTF(4, 0);
+
+static void
+xfrin_log1(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
+ const char *fmt, ...)
+ ISC_FORMAT_PRINTF(4, 5);
+
+static void
+xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+/**************************************************************************/
+/*
+ * AXFR handling
+ */
+
+static isc_result_t
+axfr_init(dns_xfrin_ctx_t *xfr) {
+ isc_result_t result;
+
+ xfr->is_ixfr = ISC_FALSE;
+
+ if (xfr->db != NULL)
+ dns_db_detach(&xfr->db);
+
+ CHECK(axfr_makedb(xfr, &xfr->db));
+ CHECK(dns_db_beginload(xfr->db, &xfr->axfr.add_func,
+ &xfr->axfr.add_private));
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+static isc_result_t
+axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
+ return (dns_db_create(xfr->mctx, /* XXX */
+ "rbt", /* XXX guess */
+ &xfr->name,
+ dns_dbtype_zone,
+ xfr->rdclass,
+ 0, NULL, /* XXX guess */
+ dbp));
+}
+
+static isc_result_t
+axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
+ dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
+{
+ isc_result_t result;
+
+ dns_difftuple_t *tuple = NULL;
+
+ CHECK(dns_zone_checknames(xfr->zone, name, rdata));
+ CHECK(dns_difftuple_create(xfr->diff.mctx, op,
+ name, ttl, rdata, &tuple));
+ dns_diff_append(&xfr->diff, &tuple);
+ if (++xfr->difflen > 100)
+ CHECK(axfr_apply(xfr));
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+/*
+ * Store a set of AXFR RRs in the database.
+ */
+static isc_result_t
+axfr_apply(dns_xfrin_ctx_t *xfr) {
+ isc_result_t result;
+
+ CHECK(dns_diff_load(&xfr->diff,
+ xfr->axfr.add_func, xfr->axfr.add_private));
+ xfr->difflen = 0;
+ dns_diff_clear(&xfr->diff);
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+static isc_result_t
+axfr_commit(dns_xfrin_ctx_t *xfr) {
+ isc_result_t result;
+
+ CHECK(axfr_apply(xfr));
+ CHECK(dns_db_endload(xfr->db, &xfr->axfr.add_private));
+ CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE));
+
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+/**************************************************************************/
+/*
+ * IXFR handling
+ */
+
+static isc_result_t
+ixfr_init(dns_xfrin_ctx_t *xfr) {
+ isc_result_t result;
+ char *journalfile;
+
+ if (xfr->reqtype != dns_rdatatype_ixfr) {
+ xfrin_log(xfr, ISC_LOG_ERROR,
+ "got incremental response to AXFR request");
+ return (DNS_R_FORMERR);
+ }
+
+ xfr->is_ixfr = ISC_TRUE;
+ INSIST(xfr->db != NULL);
+ xfr->difflen = 0;
+
+ journalfile = dns_zone_getjournal(xfr->zone);
+ if (journalfile != NULL)
+ CHECK(dns_journal_open(xfr->mctx, journalfile,
+ ISC_TRUE, &xfr->ixfr.journal));
+
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+static isc_result_t
+ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
+ dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
+{
+ isc_result_t result;
+
+ dns_difftuple_t *tuple = NULL;
+ if (op == DNS_DIFFOP_ADD)
+ CHECK(dns_zone_checknames(xfr->zone, name, rdata));
+ CHECK(dns_difftuple_create(xfr->diff.mctx, op,
+ name, ttl, rdata, &tuple));
+ dns_diff_append(&xfr->diff, &tuple);
+ if (++xfr->difflen > 100)
+ CHECK(ixfr_apply(xfr));
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+/*
+ * Apply a set of IXFR changes to the database.
+ */
+static isc_result_t
+ixfr_apply(dns_xfrin_ctx_t *xfr) {
+ isc_result_t result;
+
+ if (xfr->ver == NULL) {
+ CHECK(dns_db_newversion(xfr->db, &xfr->ver));
+ if (xfr->ixfr.journal != NULL)
+ CHECK(dns_journal_begin_transaction(xfr->ixfr.journal));
+ }
+ CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver));
+ if (xfr->ixfr.journal != NULL) {
+ result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ }
+ dns_diff_clear(&xfr->diff);
+ xfr->difflen = 0;
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+static isc_result_t
+ixfr_commit(dns_xfrin_ctx_t *xfr) {
+ isc_result_t result;
+
+ CHECK(ixfr_apply(xfr));
+ if (xfr->ver != NULL) {
+ /* XXX enter ready-to-commit state here */
+ if (xfr->ixfr.journal != NULL)
+ CHECK(dns_journal_commit(xfr->ixfr.journal));
+ dns_db_closeversion(xfr->db, &xfr->ver, ISC_TRUE);
+ dns_zone_markdirty(xfr->zone);
+ }
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+/**************************************************************************/
+/*
+ * Common AXFR/IXFR protocol code
+ */
+
+/*
+ * Handle a single incoming resource record according to the current
+ * state.
+ */
+static isc_result_t
+xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
+ dns_rdata_t *rdata)
+{
+ isc_result_t result;
+
+ xfr->nrecs++;
+
+ if (rdata->type == dns_rdatatype_none ||
+ dns_rdatatype_ismeta(rdata->type))
+ FAIL(DNS_R_FORMERR);
+
+ redo:
+ switch (xfr->state) {
+ case XFRST_SOAQUERY:
+ if (rdata->type != dns_rdatatype_soa) {
+ xfrin_log(xfr, ISC_LOG_ERROR,
+ "non-SOA response to SOA query");
+ FAIL(DNS_R_FORMERR);
+ }
+ xfr->end_serial = dns_soa_getserial(rdata);
+ if (!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
+ !dns_zone_isforced(xfr->zone)) {
+ xfrin_log(xfr, ISC_LOG_DEBUG(3),
+ "requested serial %u, "
+ "master has %u, not updating",
+ xfr->ixfr.request_serial, xfr->end_serial);
+ FAIL(DNS_R_UPTODATE);
+ }
+ xfr->state = XFRST_GOTSOA;
+ break;
+
+ case XFRST_GOTSOA:
+ /*
+ * Skip other records in the answer section.
+ */
+ break;
+
+ case XFRST_INITIALSOA:
+ if (rdata->type != dns_rdatatype_soa) {
+ xfrin_log(xfr, ISC_LOG_ERROR,
+ "first RR in zone transfer must be SOA");
+ FAIL(DNS_R_FORMERR);
+ }
+ /*
+ * Remember the serial number in the initial SOA.
+ * We need it to recognize the end of an IXFR.
+ */
+ xfr->end_serial = dns_soa_getserial(rdata);
+ if (xfr->reqtype == dns_rdatatype_ixfr &&
+ ! DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial)
+ && !dns_zone_isforced(xfr->zone))
+ {
+ /*
+ * This must be the single SOA record that is
+ * sent when the current version on the master
+ * is not newer than the version in the request.
+ */
+ xfrin_log(xfr, ISC_LOG_DEBUG(3),
+ "requested serial %u, "
+ "master has %u, not updating",
+ xfr->ixfr.request_serial, xfr->end_serial);
+ FAIL(DNS_R_UPTODATE);
+ }
+ if (xfr->reqtype == dns_rdatatype_axfr)
+ xfr->checkid = ISC_FALSE;
+ xfr->state = XFRST_FIRSTDATA;
+ break;
+
+ case XFRST_FIRSTDATA:
+ /*
+ * If the transfer begins with one SOA record, it is an AXFR,
+ * if it begins with two SOAs, it is an IXFR.
+ */
+ if (xfr->reqtype == dns_rdatatype_ixfr &&
+ rdata->type == dns_rdatatype_soa &&
+ xfr->ixfr.request_serial == dns_soa_getserial(rdata)) {
+ xfrin_log(xfr, ISC_LOG_DEBUG(3),
+ "got incremental response");
+ CHECK(ixfr_init(xfr));
+ xfr->state = XFRST_IXFR_DELSOA;
+ } else {
+ xfrin_log(xfr, ISC_LOG_DEBUG(3),
+ "got nonincremental response");
+ CHECK(axfr_init(xfr));
+ xfr->state = XFRST_AXFR;
+ }
+ goto redo;
+
+ case XFRST_IXFR_DELSOA:
+ INSIST(rdata->type == dns_rdatatype_soa);
+ CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
+ xfr->state = XFRST_IXFR_DEL;
+ break;
+
+ case XFRST_IXFR_DEL:
+ if (rdata->type == dns_rdatatype_soa) {
+ isc_uint32_t soa_serial = dns_soa_getserial(rdata);
+ xfr->state = XFRST_IXFR_ADDSOA;
+ xfr->ixfr.current_serial = soa_serial;
+ goto redo;
+ }
+ CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
+ break;
+
+ case XFRST_IXFR_ADDSOA:
+ INSIST(rdata->type == dns_rdatatype_soa);
+ CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
+ xfr->state = XFRST_IXFR_ADD;
+ break;
+
+ case XFRST_IXFR_ADD:
+ if (rdata->type == dns_rdatatype_soa) {
+ isc_uint32_t soa_serial = dns_soa_getserial(rdata);
+ if (soa_serial == xfr->end_serial) {
+ CHECK(ixfr_commit(xfr));
+ xfr->state = XFRST_END;
+ break;
+ } else if (soa_serial != xfr->ixfr.current_serial) {
+ xfrin_log(xfr, ISC_LOG_ERROR,
+ "IXFR out of sync: "
+ "expected serial %u, got %u",
+ xfr->ixfr.current_serial, soa_serial);
+ FAIL(DNS_R_FORMERR);
+ } else {
+ CHECK(ixfr_commit(xfr));
+ xfr->state = XFRST_IXFR_DELSOA;
+ goto redo;
+ }
+ }
+ if (rdata->type == dns_rdatatype_ns &&
+ dns_name_iswildcard(name))
+ FAIL(DNS_R_INVALIDNS);
+ CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
+ break;
+
+ case XFRST_AXFR:
+ /*
+ * Old BINDs sent cross class A records for non IN classes.
+ */
+ if (rdata->type == dns_rdatatype_a &&
+ rdata->rdclass != xfr->rdclass &&
+ xfr->rdclass != dns_rdataclass_in)
+ break;
+ CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
+ if (rdata->type == dns_rdatatype_soa) {
+ CHECK(axfr_commit(xfr));
+ xfr->state = XFRST_END;
+ break;
+ }
+ break;
+ case XFRST_END:
+ FAIL(DNS_R_EXTRADATA);
+ default:
+ INSIST(0);
+ break;
+ }
+ result = ISC_R_SUCCESS;
+ failure:
+ return (result);
+}
+
+isc_result_t
+dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
+ isc_sockaddr_t *masteraddr, dns_tsigkey_t *tsigkey,
+ isc_mem_t *mctx, isc_timermgr_t *timermgr,
+ isc_socketmgr_t *socketmgr, isc_task_t *task,
+ dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
+{
+ isc_sockaddr_t sourceaddr;
+
+ switch (isc_sockaddr_pf(masteraddr)) {
+ case PF_INET:
+ sourceaddr = *dns_zone_getxfrsource4(zone);
+ break;
+ case PF_INET6:
+ sourceaddr = *dns_zone_getxfrsource6(zone);
+ break;
+ default:
+ INSIST(0);
+ }
+
+ return(dns_xfrin_create2(zone, xfrtype, masteraddr, &sourceaddr,
+ tsigkey, mctx, timermgr, socketmgr,
+ task, done, xfrp));
+}
+
+isc_result_t
+dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
+ isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
+ dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
+ isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
+ isc_task_t *task, dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
+{
+ dns_name_t *zonename = dns_zone_getorigin(zone);
+ dns_xfrin_ctx_t *xfr = NULL;
+ isc_result_t result;
+ dns_db_t *db = NULL;
+
+ REQUIRE(xfrp != NULL && *xfrp == NULL);
+
+ (void)dns_zone_getdb(zone, &db);
+
+ if (xfrtype == dns_rdatatype_soa || xfrtype == dns_rdatatype_ixfr)
+ REQUIRE(db != NULL);
+
+ CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
+ dns_zone_getclass(zone), xfrtype, masteraddr,
+ sourceaddr, tsigkey, &xfr));
+
+ CHECK(xfrin_start(xfr));
+
+ xfr->done = done;
+ xfr->refcount++;
+ *xfrp = xfr;
+
+ failure:
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (result != ISC_R_SUCCESS) {
+ char zonetext[DNS_NAME_MAXTEXT+32];
+ dns_zone_name(zone, zonetext, sizeof(zonetext));
+ xfrin_log1(ISC_LOG_ERROR, zonetext, masteraddr,
+ "zone transfer setup failed");
+ }
+ return (result);
+}
+
+void
+dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
+ if (! xfr->shuttingdown)
+ xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
+}
+
+void
+dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) {
+ REQUIRE(target != NULL && *target == NULL);
+ source->refcount++;
+ *target = source;
+}
+
+void
+dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) {
+ dns_xfrin_ctx_t *xfr = *xfrp;
+ INSIST(xfr->refcount > 0);
+ xfr->refcount--;
+ maybe_free(xfr);
+ *xfrp = NULL;
+}
+
+static void
+xfrin_cancelio(dns_xfrin_ctx_t *xfr) {
+ if (xfr->connects > 0) {
+ isc_socket_cancel(xfr->socket, xfr->task,
+ ISC_SOCKCANCEL_CONNECT);
+ } else if (xfr->recvs > 0) {
+ dns_tcpmsg_cancelread(&xfr->tcpmsg);
+ } else if (xfr->sends > 0) {
+ isc_socket_cancel(xfr->socket, xfr->task,
+ ISC_SOCKCANCEL_SEND);
+ }
+}
+
+static void
+xfrin_reset(dns_xfrin_ctx_t *xfr) {
+ REQUIRE(VALID_XFRIN(xfr));
+
+ xfrin_log(xfr, ISC_LOG_INFO, "resetting");
+
+ xfrin_cancelio(xfr);
+
+ if (xfr->socket != NULL)
+ isc_socket_detach(&xfr->socket);
+
+ if (xfr->lasttsig != NULL)
+ isc_buffer_free(&xfr->lasttsig);
+
+ dns_diff_clear(&xfr->diff);
+ xfr->difflen = 0;
+
+ if (xfr->ixfr.journal != NULL)
+ dns_journal_destroy(&xfr->ixfr.journal);
+
+ if (xfr->axfr.add_private != NULL) {
+ (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
+ xfr->axfr.add_func = NULL;
+ }
+
+ if (xfr->tcpmsg_valid) {
+ dns_tcpmsg_invalidate(&xfr->tcpmsg);
+ xfr->tcpmsg_valid = ISC_FALSE;
+ }
+
+ if (xfr->ver != NULL)
+ dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
+}
+
+
+static void
+xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
+ if (result != DNS_R_UPTODATE) {
+ xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s",
+ msg, isc_result_totext(result));
+ if (xfr->is_ixfr)
+ /* Pass special result code to force AXFR retry */
+ result = DNS_R_BADIXFR;
+ }
+ xfrin_cancelio(xfr);
+ /*
+ * Close the journal.
+ */
+ if (xfr->ixfr.journal != NULL)
+ dns_journal_destroy(&xfr->ixfr.journal);
+ if (xfr->done != NULL) {
+ (xfr->done)(xfr->zone, result);
+ xfr->done = NULL;
+ }
+ xfr->shuttingdown = ISC_TRUE;
+ maybe_free(xfr);
+}
+
+static isc_result_t
+xfrin_create(isc_mem_t *mctx,
+ dns_zone_t *zone,
+ dns_db_t *db,
+ isc_task_t *task,
+ isc_timermgr_t *timermgr,
+ isc_socketmgr_t *socketmgr,
+ dns_name_t *zonename,
+ dns_rdataclass_t rdclass,
+ dns_rdatatype_t reqtype,
+ isc_sockaddr_t *masteraddr,
+ isc_sockaddr_t *sourceaddr,
+ dns_tsigkey_t *tsigkey,
+ dns_xfrin_ctx_t **xfrp)
+{
+ dns_xfrin_ctx_t *xfr = NULL;
+ isc_result_t result;
+ isc_uint32_t tmp;
+
+ xfr = isc_mem_get(mctx, sizeof(*xfr));
+ if (xfr == NULL)
+ return (ISC_R_NOMEMORY);
+ xfr->mctx = mctx;
+ xfr->refcount = 0;
+ xfr->zone = NULL;
+ dns_zone_iattach(zone, &xfr->zone);
+ xfr->task = NULL;
+ isc_task_attach(task, &xfr->task);
+ xfr->timer = NULL;
+ xfr->socketmgr = socketmgr;
+ xfr->done = NULL;
+
+ xfr->connects = 0;
+ xfr->sends = 0;
+ xfr->recvs = 0;
+ xfr->shuttingdown = ISC_FALSE;
+
+ dns_name_init(&xfr->name, NULL);
+ xfr->rdclass = rdclass;
+ isc_random_get(&tmp);
+ xfr->checkid = ISC_TRUE;
+ xfr->id = (isc_uint16_t)(tmp & 0xffff);
+ xfr->reqtype = reqtype;
+
+ /* sockaddr */
+ xfr->socket = NULL;
+ /* qbuffer */
+ /* qbuffer_data */
+ /* tcpmsg */
+ xfr->tcpmsg_valid = ISC_FALSE;
+
+ xfr->db = NULL;
+ if (db != NULL)
+ dns_db_attach(db, &xfr->db);
+ xfr->ver = NULL;
+ dns_diff_init(xfr->mctx, &xfr->diff);
+ xfr->difflen = 0;
+
+ if (reqtype == dns_rdatatype_soa)
+ xfr->state = XFRST_SOAQUERY;
+ else
+ xfr->state = XFRST_INITIALSOA;
+ /* end_serial */
+
+ xfr->nmsg = 0;
+ xfr->nrecs = 0;
+ xfr->nbytes = 0;
+ isc_time_now(&xfr->start);
+
+ xfr->tsigkey = NULL;
+ if (tsigkey != NULL)
+ dns_tsigkey_attach(tsigkey, &xfr->tsigkey);
+ xfr->lasttsig = NULL;
+ xfr->tsigctx = NULL;
+ xfr->sincetsig = 0;
+ xfr->is_ixfr = ISC_FALSE;
+
+ /* ixfr.request_serial */
+ /* ixfr.current_serial */
+ xfr->ixfr.journal = NULL;
+
+ xfr->axfr.add_func = NULL;
+ xfr->axfr.add_private = NULL;
+
+ CHECK(dns_name_dup(zonename, mctx, &xfr->name));
+
+ CHECK(isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
+ task, xfrin_timeout, xfr, &xfr->timer));
+ CHECK(dns_timer_setidle(xfr->timer,
+ dns_zone_getmaxxfrin(xfr->zone),
+ dns_zone_getidlein(xfr->zone),
+ ISC_FALSE));
+
+ xfr->masteraddr = *masteraddr;
+
+ INSIST(isc_sockaddr_pf(masteraddr) == isc_sockaddr_pf(sourceaddr));
+ xfr->sourceaddr = *sourceaddr;
+ isc_sockaddr_setport(&xfr->sourceaddr, 0);
+
+ isc_buffer_init(&xfr->qbuffer, xfr->qbuffer_data,
+ sizeof(xfr->qbuffer_data));
+
+ xfr->magic = XFRIN_MAGIC;
+ *xfrp = xfr;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ if (xfr->timer != NULL)
+ isc_timer_detach(&xfr->timer);
+ if (dns_name_dynamic(&xfr->name))
+ dns_name_free(&xfr->name, xfr->mctx);
+ if (xfr->tsigkey != NULL)
+ dns_tsigkey_detach(&xfr->tsigkey);
+ if (xfr->db != NULL)
+ dns_db_detach(&xfr->db);
+ isc_task_detach(&xfr->task);
+ dns_zone_idetach(&xfr->zone);
+ isc_mem_put(mctx, xfr, sizeof(*xfr));
+
+ return (result);
+}
+
+static isc_result_t
+xfrin_start(dns_xfrin_ctx_t *xfr) {
+ isc_result_t result;
+ CHECK(isc_socket_create(xfr->socketmgr,
+ isc_sockaddr_pf(&xfr->sourceaddr),
+ isc_sockettype_tcp,
+ &xfr->socket));
+ isc_socket_setname(xfr->socket, "xfrin", NULL);
+#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
+ CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr,
+ ISC_SOCKET_REUSEADDRESS));
+#endif
+ CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
+ xfrin_connect_done, xfr));
+ xfr->connects++;
+ return (ISC_R_SUCCESS);
+ failure:
+ xfrin_fail(xfr, result, "failed setting up socket");
+ return (result);
+}
+
+/* XXX the resolver could use this, too */
+
+static isc_result_t
+render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) {
+ dns_compress_t cctx;
+ isc_boolean_t cleanup_cctx = ISC_FALSE;
+ isc_result_t result;
+
+ CHECK(dns_compress_init(&cctx, -1, mctx));
+ cleanup_cctx = ISC_TRUE;
+ CHECK(dns_message_renderbegin(msg, &cctx, buf));
+ CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
+ CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
+ CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0));
+ CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0));
+ CHECK(dns_message_renderend(msg));
+ result = ISC_R_SUCCESS;
+ failure:
+ if (cleanup_cctx)
+ dns_compress_invalidate(&cctx);
+ return (result);
+}
+
+/*
+ * A connection has been established.
+ */
+static void
+xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
+ isc_socket_connev_t *cev = (isc_socket_connev_t *) event;
+ dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
+ isc_result_t result = cev->result;
+ char sourcetext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t sockaddr;
+
+ REQUIRE(VALID_XFRIN(xfr));
+
+ UNUSED(task);
+
+ INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT);
+ isc_event_free(&event);
+
+ xfr->connects--;
+ if (xfr->shuttingdown) {
+ maybe_free(xfr);
+ return;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ dns_zonemgr_t * zmgr = dns_zone_getmgr(xfr->zone);
+ isc_time_t now;
+
+ if (zmgr != NULL) {
+ TIME_NOW(&now);
+ dns_zonemgr_unreachableadd(zmgr, &xfr->masteraddr,
+ &xfr->sourceaddr, &now);
+ }
+ goto failure;
+ }
+
+ result = isc_socket_getsockname(xfr->socket, &sockaddr);
+ if (result == ISC_R_SUCCESS) {
+ isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext));
+ } else
+ strcpy(sourcetext, "<UNKNOWN>");
+ xfrin_log(xfr, ISC_LOG_INFO, "connected using %s", sourcetext);
+
+ dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg);
+ xfr->tcpmsg_valid = ISC_TRUE;
+
+ CHECK(xfrin_send_request(xfr));
+ failure:
+ if (result != ISC_R_SUCCESS)
+ xfrin_fail(xfr, result, "failed to connect");
+}
+
+/*
+ * Convert a tuple into a dns_name_t suitable for inserting
+ * into the given dns_message_t.
+ */
+static isc_result_t
+tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target)
+{
+ isc_result_t result;
+ dns_rdata_t *rdata = NULL;
+ dns_rdatalist_t *rdl = NULL;
+ dns_rdataset_t *rds = NULL;
+ dns_name_t *name = NULL;
+
+ REQUIRE(target != NULL && *target == NULL);
+
+ CHECK(dns_message_gettemprdata(msg, &rdata));
+ dns_rdata_init(rdata);
+ dns_rdata_clone(&tuple->rdata, rdata);
+
+ CHECK(dns_message_gettemprdatalist(msg, &rdl));
+ dns_rdatalist_init(rdl);
+ rdl->type = tuple->rdata.type;
+ rdl->rdclass = tuple->rdata.rdclass;
+ rdl->ttl = tuple->ttl;
+ ISC_LIST_APPEND(rdl->rdata, rdata, link);
+
+ CHECK(dns_message_gettemprdataset(msg, &rds));
+ dns_rdataset_init(rds);
+ CHECK(dns_rdatalist_tordataset(rdl, rds));
+
+ CHECK(dns_message_gettempname(msg, &name));
+ dns_name_init(name, NULL);
+ dns_name_clone(&tuple->name, name);
+ ISC_LIST_APPEND(name->list, rds, link);
+
+ *target = name;
+ return (ISC_R_SUCCESS);
+
+ failure:
+
+ if (rds != NULL) {
+ dns_rdataset_disassociate(rds);
+ dns_message_puttemprdataset(msg, &rds);
+ }
+ if (rdl != NULL) {
+ ISC_LIST_UNLINK(rdl->rdata, rdata, link);
+ dns_message_puttemprdatalist(msg, &rdl);
+ }
+ if (rdata != NULL)
+ dns_message_puttemprdata(msg, &rdata);
+
+ return (result);
+}
+
+
+/*
+ * Build an *XFR request and send its length prefix.
+ */
+static isc_result_t
+xfrin_send_request(dns_xfrin_ctx_t *xfr) {
+ isc_result_t result;
+ isc_region_t region;
+ isc_region_t lregion;
+ dns_rdataset_t *qrdataset = NULL;
+ dns_message_t *msg = NULL;
+ unsigned char length[2];
+ dns_difftuple_t *soatuple = NULL;
+ dns_name_t *qname = NULL;
+ dns_dbversion_t *ver = NULL;
+ dns_name_t *msgsoaname = NULL;
+
+ /* Create the request message */
+ CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg));
+ CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
+
+ /* Create a name for the question section. */
+ CHECK(dns_message_gettempname(msg, &qname));
+ dns_name_init(qname, NULL);
+ dns_name_clone(&xfr->name, qname);
+
+ /* Formulate the question and attach it to the question name. */
+ CHECK(dns_message_gettemprdataset(msg, &qrdataset));
+ dns_rdataset_init(qrdataset);
+ dns_rdataset_makequestion(qrdataset, xfr->rdclass, xfr->reqtype);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+ qrdataset = NULL;
+
+ dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
+ qname = NULL;
+
+ if (xfr->reqtype == dns_rdatatype_ixfr) {
+ /* Get the SOA and add it to the authority section. */
+ /* XXX is using the current version the right thing? */
+ dns_db_currentversion(xfr->db, &ver);
+ CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx,
+ DNS_DIFFOP_EXISTS, &soatuple));
+ xfr->ixfr.request_serial = dns_soa_getserial(&soatuple->rdata);
+ xfr->ixfr.current_serial = xfr->ixfr.request_serial;
+ xfrin_log(xfr, ISC_LOG_DEBUG(3),
+ "requesting IXFR for serial %u",
+ xfr->ixfr.request_serial);
+
+ CHECK(tuple2msgname(soatuple, msg, &msgsoaname));
+ dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY);
+ } else if (xfr->reqtype == dns_rdatatype_soa)
+ CHECK(dns_db_getsoaserial(xfr->db, NULL,
+ &xfr->ixfr.request_serial));
+
+ xfr->checkid = ISC_TRUE;
+ xfr->id++;
+ xfr->nmsg = 0;
+ xfr->nrecs = 0;
+ xfr->nbytes = 0;
+ isc_time_now(&xfr->start);
+ msg->id = xfr->id;
+ if (xfr->tsigctx != NULL)
+ dst_context_destroy(&xfr->tsigctx);
+
+ CHECK(render(msg, xfr->mctx, &xfr->qbuffer));
+
+ /*
+ * Free the last tsig, if there is one.
+ */
+ if (xfr->lasttsig != NULL)
+ isc_buffer_free(&xfr->lasttsig);
+
+ /*
+ * Save the query TSIG and don't let message_destroy free it.
+ */
+ CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
+
+ isc_buffer_usedregion(&xfr->qbuffer, &region);
+ INSIST(region.length <= 65535);
+
+ length[0] = region.length >> 8;
+ length[1] = region.length & 0xFF;
+ lregion.base = length;
+ lregion.length = 2;
+ CHECK(isc_socket_send(xfr->socket, &lregion, xfr->task,
+ xfrin_sendlen_done, xfr));
+ xfr->sends++;
+
+ failure:
+ if (qname != NULL)
+ dns_message_puttempname(msg, &qname);
+ if (qrdataset != NULL)
+ dns_message_puttemprdataset(msg, &qrdataset);
+ if (msg != NULL)
+ dns_message_destroy(&msg);
+ if (soatuple != NULL)
+ dns_difftuple_free(&soatuple);
+ if (ver != NULL)
+ dns_db_closeversion(xfr->db, &ver, ISC_FALSE);
+ return (result);
+}
+
+/* XXX there should be library support for sending DNS TCP messages */
+
+static void
+xfrin_sendlen_done(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sev = (isc_socketevent_t *) event;
+ dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
+ isc_result_t evresult = sev->result;
+ isc_result_t result;
+ isc_region_t region;
+
+ REQUIRE(VALID_XFRIN(xfr));
+
+ UNUSED(task);
+
+ INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+ isc_event_free(&event);
+
+ xfr->sends--;
+ if (xfr->shuttingdown) {
+ maybe_free(xfr);
+ return;
+ }
+
+ xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request length prefix");
+ CHECK(evresult);
+
+ isc_buffer_usedregion(&xfr->qbuffer, &region);
+ CHECK(isc_socket_send(xfr->socket, &region, xfr->task,
+ xfrin_send_done, xfr));
+ xfr->sends++;
+ failure:
+ if (result != ISC_R_SUCCESS)
+ xfrin_fail(xfr, result, "failed sending request length prefix");
+}
+
+
+static void
+xfrin_send_done(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sev = (isc_socketevent_t *) event;
+ dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
+ isc_result_t result;
+
+ REQUIRE(VALID_XFRIN(xfr));
+
+ UNUSED(task);
+
+ INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+
+ xfr->sends--;
+ xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data");
+ CHECK(sev->result);
+
+ CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
+ xfrin_recv_done, xfr));
+ xfr->recvs++;
+ failure:
+ isc_event_free(&event);
+ if (result != ISC_R_SUCCESS)
+ xfrin_fail(xfr, result, "failed sending request data");
+}
+
+
+static void
+xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
+ dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) ev->ev_arg;
+ isc_result_t result;
+ dns_message_t *msg = NULL;
+ dns_name_t *name;
+ dns_tcpmsg_t *tcpmsg;
+ dns_name_t *tsigowner = NULL;
+
+ REQUIRE(VALID_XFRIN(xfr));
+
+ UNUSED(task);
+
+ INSIST(ev->ev_type == DNS_EVENT_TCPMSG);
+ tcpmsg = ev->ev_sender;
+ isc_event_free(&ev);
+
+ xfr->recvs--;
+ if (xfr->shuttingdown) {
+ maybe_free(xfr);
+ return;
+ }
+
+ CHECK(tcpmsg->result);
+
+ xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes",
+ tcpmsg->buffer.used);
+
+ CHECK(isc_timer_touch(xfr->timer));
+
+ CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg));
+
+ CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
+ CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
+
+ msg->tsigctx = xfr->tsigctx;
+ xfr->tsigctx = NULL;
+
+ if (xfr->nmsg > 0)
+ msg->tcp_continuation = 1;
+
+ result = dns_message_parse(msg, &tcpmsg->buffer,
+ DNS_MESSAGEPARSE_PRESERVEORDER);
+
+ if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror ||
+ (xfr->checkid && msg->id != xfr->id)) {
+ if (result == ISC_R_SUCCESS)
+ result = ISC_RESULTCLASS_DNSRCODE + msg->rcode; /*XXX*/
+ if (result == ISC_R_SUCCESS || result == DNS_R_NOERROR)
+ result = DNS_R_UNEXPECTEDID;
+ if (xfr->reqtype == dns_rdatatype_axfr ||
+ xfr->reqtype == dns_rdatatype_soa)
+ FAIL(result);
+ xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
+ isc_result_totext(result));
+ try_axfr:
+ dns_message_destroy(&msg);
+ xfrin_reset(xfr);
+ xfr->reqtype = dns_rdatatype_soa;
+ xfr->state = XFRST_SOAQUERY;
+ (void)xfrin_start(xfr);
+ return;
+ }
+
+ /*
+ * Does the server know about IXFR? If it doesn't we will get
+ * a message with a empty answer section or a potentially a CNAME /
+ * DNAME, the later is handled by xfr_rr() which will return FORMERR
+ * if the first RR in the answer section is not a SOA record.
+ */
+ if (xfr->reqtype == dns_rdatatype_ixfr &&
+ xfr->state == XFRST_INITIALSOA &&
+ msg->counts[DNS_SECTION_ANSWER] == 0) {
+ xfrin_log(xfr, ISC_LOG_DEBUG(3),
+ "empty answer section, retrying with AXFR");
+ goto try_axfr;
+ }
+
+ if (xfr->reqtype == dns_rdatatype_soa &&
+ (msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
+ FAIL(DNS_R_NOTAUTHORITATIVE);
+ }
+
+
+ result = dns_message_checksig(msg, dns_zone_getview(xfr->zone));
+ if (result != ISC_R_SUCCESS) {
+ xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
+ isc_result_totext(result));
+ FAIL(result);
+ }
+
+ for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(msg, DNS_SECTION_ANSWER))
+ {
+ dns_rdataset_t *rds;
+
+ name = NULL;
+ dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+ for (rds = ISC_LIST_HEAD(name->list);
+ rds != NULL;
+ rds = ISC_LIST_NEXT(rds, link))
+ {
+ for (result = dns_rdataset_first(rds);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rds))
+ {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_current(rds, &rdata);
+ CHECK(xfr_rr(xfr, name, rds->ttl, &rdata));
+ }
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
+ if (dns_message_gettsig(msg, &tsigowner) != NULL) {
+ /*
+ * Reset the counter.
+ */
+ xfr->sincetsig = 0;
+
+ /*
+ * Free the last tsig, if there is one.
+ */
+ if (xfr->lasttsig != NULL)
+ isc_buffer_free(&xfr->lasttsig);
+
+ /*
+ * Update the last tsig pointer.
+ */
+ CHECK(dns_message_getquerytsig(msg, xfr->mctx,
+ &xfr->lasttsig));
+
+ } else if (dns_message_gettsigkey(msg) != NULL) {
+ xfr->sincetsig++;
+ if (xfr->sincetsig > 100 ||
+ xfr->nmsg == 0 || xfr->state == XFRST_END)
+ {
+ result = DNS_R_EXPECTEDTSIG;
+ goto failure;
+ }
+ }
+
+ /*
+ * Update the number of messages received.
+ */
+ xfr->nmsg++;
+
+ /*
+ * Update the number of bytes received.
+ */
+ xfr->nbytes += tcpmsg->buffer.used;
+
+ /*
+ * Take the context back.
+ */
+ INSIST(xfr->tsigctx == NULL);
+ xfr->tsigctx = msg->tsigctx;
+ msg->tsigctx = NULL;
+
+ dns_message_destroy(&msg);
+
+ if (xfr->state == XFRST_GOTSOA) {
+ xfr->reqtype = dns_rdatatype_axfr;
+ xfr->state = XFRST_INITIALSOA;
+ CHECK(xfrin_send_request(xfr));
+ } else if (xfr->state == XFRST_END) {
+ /*
+ * Close the journal.
+ */
+ if (xfr->ixfr.journal != NULL)
+ dns_journal_destroy(&xfr->ixfr.journal);
+ /*
+ * Inform the caller we succeeded.
+ */
+ if (xfr->done != NULL) {
+ (xfr->done)(xfr->zone, ISC_R_SUCCESS);
+ xfr->done = NULL;
+ }
+ /*
+ * We should have no outstanding events at this
+ * point, thus maybe_free() should succeed.
+ */
+ xfr->shuttingdown = ISC_TRUE;
+ maybe_free(xfr);
+ } else {
+ /*
+ * Read the next message.
+ */
+ CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
+ xfrin_recv_done, xfr));
+ xfr->recvs++;
+ }
+ return;
+
+ failure:
+ if (msg != NULL)
+ dns_message_destroy(&msg);
+ if (result != ISC_R_SUCCESS)
+ xfrin_fail(xfr, result, "failed while receiving responses");
+}
+
+static void
+xfrin_timeout(isc_task_t *task, isc_event_t *event) {
+ dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
+
+ REQUIRE(VALID_XFRIN(xfr));
+
+ UNUSED(task);
+
+ isc_event_free(&event);
+ /*
+ * This will log "giving up: timeout".
+ */
+ xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up");
+}
+
+static void
+maybe_free(dns_xfrin_ctx_t *xfr) {
+ isc_uint64_t msecs;
+ isc_uint64_t persec;
+
+ REQUIRE(VALID_XFRIN(xfr));
+
+ if (! xfr->shuttingdown || xfr->refcount != 0 ||
+ xfr->connects != 0 || xfr->sends != 0 ||
+ xfr->recvs != 0)
+ return;
+
+ /*
+ * Calculate the length of time the transfer took,
+ * and print a log message with the bytes and rate.
+ */
+ isc_time_now(&xfr->end);
+ msecs = isc_time_microdiff(&xfr->end, &xfr->start) / 1000;
+ if (msecs == 0)
+ msecs = 1;
+ persec = (xfr->nbytes * 1000) / msecs;
+ xfrin_log(xfr, ISC_LOG_INFO,
+ "Transfer completed: %d messages, %d records, "
+ "%" ISC_PRINT_QUADFORMAT "u bytes, "
+ "%u.%03u secs (%u bytes/sec)",
+ xfr->nmsg, xfr->nrecs, xfr->nbytes,
+ (unsigned int) (msecs / 1000), (unsigned int) (msecs % 1000),
+ (unsigned int) persec);
+
+ if (xfr->socket != NULL)
+ isc_socket_detach(&xfr->socket);
+
+ if (xfr->timer != NULL)
+ isc_timer_detach(&xfr->timer);
+
+ if (xfr->task != NULL)
+ isc_task_detach(&xfr->task);
+
+ if (xfr->tsigkey != NULL)
+ dns_tsigkey_detach(&xfr->tsigkey);
+
+ if (xfr->lasttsig != NULL)
+ isc_buffer_free(&xfr->lasttsig);
+
+ dns_diff_clear(&xfr->diff);
+
+ if (xfr->ixfr.journal != NULL)
+ dns_journal_destroy(&xfr->ixfr.journal);
+
+ if (xfr->axfr.add_private != NULL)
+ (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
+
+ if (xfr->tcpmsg_valid)
+ dns_tcpmsg_invalidate(&xfr->tcpmsg);
+
+ if (xfr->tsigctx != NULL)
+ dst_context_destroy(&xfr->tsigctx);
+
+ if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0)
+ dns_name_free(&xfr->name, xfr->mctx);
+
+ if (xfr->ver != NULL)
+ dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
+
+ if (xfr->db != NULL)
+ dns_db_detach(&xfr->db);
+
+ if (xfr->zone != NULL)
+ dns_zone_idetach(&xfr->zone);
+
+ isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
+}
+
+/*
+ * Log incoming zone transfer messages in a format like
+ * transfer of <zone> from <address>: <message>
+ */
+static void
+xfrin_logv(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
+ const char *fmt, va_list ap)
+{
+ char mastertext[ISC_SOCKADDR_FORMATSIZE];
+ char msgtext[2048];
+
+ isc_sockaddr_format(masteraddr, mastertext, sizeof(mastertext));
+ vsnprintf(msgtext, sizeof(msgtext), fmt, ap);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN,
+ DNS_LOGMODULE_XFER_IN, level,
+ "transfer of '%s' from %s: %s",
+ zonetext, mastertext, msgtext);
+}
+
+/*
+ * Logging function for use when a xfrin_ctx_t has not yet been created.
+ */
+
+static void
+xfrin_log1(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
+ return;
+
+ va_start(ap, fmt);
+ xfrin_logv(level, zonetext, masteraddr, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Logging function for use when there is a xfrin_ctx_t.
+ */
+
+static void
+xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
+{
+ va_list ap;
+ char zonetext[DNS_NAME_MAXTEXT+32];
+
+ if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
+ return;
+
+ dns_zone_name(xfr->zone, zonetext, sizeof(zonetext));
+
+ va_start(ap, fmt);
+ xfrin_logv(level, zonetext, &xfr->masteraddr, fmt, ap);
+ va_end(ap);
+}
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
new file mode 100644
index 0000000..9c53ab4
--- /dev/null
+++ b/lib/dns/zone.c
@@ -0,0 +1,11502 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: zone.c,v 1.483 2008/10/24 00:28:00 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/file.h>
+#include <isc/mutex.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/ratelimiter.h>
+#include <isc/refcount.h>
+#include <isc/rwlock.h>
+#include <isc/serial.h>
+#include <isc/stdtime.h>
+#include <isc/string.h>
+#include <isc/taskpool.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/acache.h>
+#include <dns/acl.h>
+#include <dns/adb.h>
+#include <dns/callbacks.h>
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/dnssec.h>
+#include <dns/events.h>
+#include <dns/journal.h>
+#include <dns/keyvalues.h>
+#include <dns/log.h>
+#include <dns/master.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/nsec.h>
+#include <dns/nsec3.h>
+#include <dns/peer.h>
+#include <dns/rcode.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/request.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/soa.h>
+#include <dns/ssu.h>
+#include <dns/stats.h>
+#include <dns/tsig.h>
+#include <dns/xfrin.h>
+#include <dns/zone.h>
+
+#include <dst/dst.h>
+
+#define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
+#define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
+
+#define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
+#define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
+
+#define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
+#define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
+
+#define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
+#define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
+
+#define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
+#define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
+
+#define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
+#define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
+
+#define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
+#define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
+
+/*%
+ * Ensure 'a' is at least 'min' but not more than 'max'.
+ */
+#define RANGE(a, min, max) \
+ (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
+
+#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
+
+/*
+ * Default values.
+ */
+#define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
+#define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
+#define MAX_XFER_TIME (2*3600) /*%< Documented default is 2 hours */
+
+#ifndef DNS_MAX_EXPIRE
+#define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
+#endif
+
+#ifndef DNS_DUMP_DELAY
+#define DNS_DUMP_DELAY 900 /*%< 15 minutes */
+#endif
+
+typedef struct dns_notify dns_notify_t;
+typedef struct dns_stub dns_stub_t;
+typedef struct dns_load dns_load_t;
+typedef struct dns_forward dns_forward_t;
+typedef struct dns_io dns_io_t;
+typedef ISC_LIST(dns_io_t) dns_iolist_t;
+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;
+
+#define DNS_ZONE_CHECKLOCK
+#ifdef DNS_ZONE_CHECKLOCK
+#define LOCK_ZONE(z) \
+ do { LOCK(&(z)->lock); \
+ INSIST((z)->locked == ISC_FALSE); \
+ (z)->locked = ISC_TRUE; \
+ } while (0)
+#define UNLOCK_ZONE(z) \
+ do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
+#define LOCKED_ZONE(z) ((z)->locked)
+#else
+#define LOCK_ZONE(z) LOCK(&(z)->lock)
+#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
+#define LOCKED_ZONE(z) ISC_TRUE
+#endif
+
+#ifdef ISC_RWLOCK_USEATOMIC
+#define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
+#define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
+#define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
+#define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
+#else
+#define ZONEDB_INITLOCK(l) isc_mutex_init(l)
+#define ZONEDB_DESTROYLOCK(l) DESTROYLOCK(l)
+#define ZONEDB_LOCK(l, t) LOCK(l)
+#define ZONEDB_UNLOCK(l, t) UNLOCK(l)
+#endif
+
+struct dns_zone {
+ /* Unlocked */
+ unsigned int magic;
+ isc_mutex_t lock;
+#ifdef DNS_ZONE_CHECKLOCK
+ isc_boolean_t locked;
+#endif
+ isc_mem_t *mctx;
+ isc_refcount_t erefs;
+
+#ifdef ISC_RWLOCK_USEATOMIC
+ isc_rwlock_t dblock;
+#else
+ isc_mutex_t dblock;
+#endif
+ dns_db_t *db; /* Locked by dblock */
+
+ /* Locked */
+ dns_zonemgr_t *zmgr;
+ ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
+ isc_timer_t *timer;
+ unsigned int irefs;
+ dns_name_t origin;
+ char *masterfile;
+ dns_masterformat_t masterformat;
+ char *journal;
+ isc_int32_t journalsize;
+ dns_rdataclass_t rdclass;
+ dns_zonetype_t type;
+ unsigned int flags;
+ unsigned int options;
+ unsigned int db_argc;
+ char **db_argv;
+ isc_time_t expiretime;
+ isc_time_t refreshtime;
+ isc_time_t dumptime;
+ isc_time_t loadtime;
+ isc_time_t notifytime;
+ isc_time_t resigntime;
+ isc_time_t keywarntime;
+ isc_time_t signingtime;
+ isc_time_t nsec3chaintime;
+ isc_uint32_t serial;
+ isc_uint32_t refresh;
+ isc_uint32_t retry;
+ isc_uint32_t expire;
+ isc_uint32_t minimum;
+ isc_stdtime_t key_expiry;
+ char *keydirectory;
+
+ isc_uint32_t maxrefresh;
+ isc_uint32_t minrefresh;
+ isc_uint32_t maxretry;
+ isc_uint32_t minretry;
+
+ isc_sockaddr_t *masters;
+ dns_name_t **masterkeynames;
+ isc_boolean_t *mastersok;
+ unsigned int masterscnt;
+ unsigned int curmaster;
+ isc_sockaddr_t masteraddr;
+ dns_notifytype_t notifytype;
+ isc_sockaddr_t *notify;
+ unsigned int notifycnt;
+ isc_sockaddr_t notifyfrom;
+ isc_task_t *task;
+ isc_sockaddr_t notifysrc4;
+ isc_sockaddr_t notifysrc6;
+ isc_sockaddr_t xfrsource4;
+ isc_sockaddr_t xfrsource6;
+ isc_sockaddr_t altxfrsource4;
+ isc_sockaddr_t altxfrsource6;
+ isc_sockaddr_t sourceaddr;
+ dns_xfrin_ctx_t *xfr; /* task locked */
+ dns_tsigkey_t *tsigkey; /* key used for xfr */
+ /* Access Control Lists */
+ dns_acl_t *update_acl;
+ dns_acl_t *forward_acl;
+ dns_acl_t *notify_acl;
+ dns_acl_t *query_acl;
+ dns_acl_t *queryon_acl;
+ dns_acl_t *xfr_acl;
+ isc_boolean_t update_disabled;
+ isc_boolean_t zero_no_soa_ttl;
+ dns_severity_t check_names;
+ ISC_LIST(dns_notify_t) notifies;
+ dns_request_t *request;
+ dns_loadctx_t *lctx;
+ dns_io_t *readio;
+ dns_dumpctx_t *dctx;
+ dns_io_t *writeio;
+ isc_uint32_t maxxfrin;
+ isc_uint32_t maxxfrout;
+ isc_uint32_t idlein;
+ isc_uint32_t idleout;
+ isc_event_t ctlevent;
+ dns_ssutable_t *ssutable;
+ isc_uint32_t sigvalidityinterval;
+ isc_uint32_t sigresigninginterval;
+ dns_view_t *view;
+ dns_acache_t *acache;
+ dns_checkmxfunc_t checkmx;
+ dns_checksrvfunc_t checksrv;
+ dns_checknsfunc_t checkns;
+ /*%
+ * Zones in certain states such as "waiting for zone transfer"
+ * or "zone transfer in progress" are kept on per-state linked lists
+ * in the zone manager using the 'statelink' field. The 'statelist'
+ * field points at the list the zone is currently on. It the zone
+ * is not on any such list, statelist is NULL.
+ */
+ ISC_LINK(dns_zone_t) statelink;
+ dns_zonelist_t *statelist;
+ /*%
+ * Statistics counters about zone management.
+ */
+ dns_stats_t *stats;
+ /*%
+ * Optional per-zone statistics counters. Counted outside of this
+ * module.
+ */
+ isc_boolean_t requeststats_on;
+ dns_stats_t *requeststats;
+ isc_uint32_t notifydelay;
+ dns_isselffunc_t isself;
+ void *isselfarg;
+
+ char * strnamerd;
+ char * strname;
+ char * strrdclass;
+ char * strviewname;
+
+ /*%
+ * Serial number for deferred journal compaction.
+ */
+ isc_uint32_t compact_serial;
+ /*%
+ * Keys that are signing the zone for the first time.
+ */
+ dns_signinglist_t signing;
+ dns_nsec3chainlist_t nsec3chain;
+ /*%
+ * Signing / re-signing quantum stopping parameters.
+ */
+ isc_uint32_t signatures;
+ isc_uint32_t nodes;
+ dns_rdatatype_t privatetype;
+};
+
+#define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
+#define DNS_ZONE_SETFLAG(z,f) do { \
+ INSIST(LOCKED_ZONE(z)); \
+ (z)->flags |= (f); \
+ } while (0)
+#define DNS_ZONE_CLRFLAG(z,f) do { \
+ INSIST(LOCKED_ZONE(z)); \
+ (z)->flags &= ~(f); \
+ } while (0)
+ /* XXX MPA these may need to go back into zone.h */
+#define DNS_ZONEFLG_REFRESH 0x00000001U /*%< refresh check in progress */
+#define DNS_ZONEFLG_NEEDDUMP 0x00000002U /*%< zone need consolidation */
+#define DNS_ZONEFLG_USEVC 0x00000004U /*%< use tcp for refresh query */
+#define DNS_ZONEFLG_DUMPING 0x00000008U /*%< a dump is in progress */
+#define DNS_ZONEFLG_HASINCLUDE 0x00000010U /*%< $INCLUDE in zone file */
+#define DNS_ZONEFLG_LOADED 0x00000020U /*%< database has loaded */
+#define DNS_ZONEFLG_EXITING 0x00000040U /*%< zone is being destroyed */
+#define DNS_ZONEFLG_EXPIRED 0x00000080U /*%< zone has expired */
+#define DNS_ZONEFLG_NEEDREFRESH 0x00000100U /*%< refresh check needed */
+#define DNS_ZONEFLG_UPTODATE 0x00000200U /*%< zone contents are
+ * uptodate */
+#define DNS_ZONEFLG_NEEDNOTIFY 0x00000400U /*%< need to send out notify
+ * messages */
+#define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U /*%< generate a journal diff on
+ * reload */
+#define DNS_ZONEFLG_NOMASTERS 0x00001000U /*%< an attempt to refresh a
+ * zone with no masters
+ * occured */
+#define DNS_ZONEFLG_LOADING 0x00002000U /*%< load from disk in progress*/
+#define DNS_ZONEFLG_HAVETIMERS 0x00004000U /*%< timer values have been set
+ * from SOA (if not set, we
+ * are still using
+ * default timer values) */
+#define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */
+#define DNS_ZONEFLG_NOREFRESH 0x00010000U
+#define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
+#define DNS_ZONEFLG_DIALREFRESH 0x00040000U
+#define DNS_ZONEFLG_SHUTDOWN 0x00080000U
+#define DNS_ZONEFLAG_NOIXFR 0x00100000U /*%< IXFR failed, force AXFR */
+#define DNS_ZONEFLG_FLUSH 0x00200000U
+#define DNS_ZONEFLG_NOEDNS 0x00400000U
+#define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
+#define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
+#define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
+
+#define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
+
+/* Flags for zone_load() */
+#define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
+
+#define UNREACH_CHACHE_SIZE 10U
+#define UNREACH_HOLD_TIME 600 /* 10 minutes */
+
+#define CHECK(op) \
+ do { result = (op); \
+ if (result != ISC_R_SUCCESS) goto failure; \
+ } while (0)
+
+struct dns_unreachable {
+ isc_sockaddr_t remote;
+ isc_sockaddr_t local;
+ isc_uint32_t expire;
+ isc_uint32_t last;
+};
+
+struct dns_zonemgr {
+ unsigned int magic;
+ isc_mem_t * mctx;
+ int refs; /* Locked by rwlock */
+ isc_taskmgr_t * taskmgr;
+ isc_timermgr_t * timermgr;
+ isc_socketmgr_t * socketmgr;
+ isc_taskpool_t * zonetasks;
+ isc_task_t * task;
+ isc_ratelimiter_t * rl;
+ isc_rwlock_t rwlock;
+ isc_mutex_t iolock;
+
+ /* Locked by rwlock. */
+ dns_zonelist_t zones;
+ dns_zonelist_t waiting_for_xfrin;
+ dns_zonelist_t xfrin_in_progress;
+
+ /* Configuration data. */
+ isc_uint32_t transfersin;
+ isc_uint32_t transfersperns;
+ unsigned int serialqueryrate;
+
+ /* Locked by iolock */
+ isc_uint32_t iolimit;
+ isc_uint32_t ioactive;
+ dns_iolist_t high;
+ dns_iolist_t low;
+
+ /* Locked by rwlock. */
+ /* LRU cache */
+ struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
+};
+
+/*%
+ * Hold notify state.
+ */
+struct dns_notify {
+ unsigned int magic;
+ unsigned int flags;
+ isc_mem_t *mctx;
+ dns_zone_t *zone;
+ dns_adbfind_t *find;
+ dns_request_t *request;
+ dns_name_t ns;
+ isc_sockaddr_t dst;
+ ISC_LINK(dns_notify_t) link;
+};
+
+#define DNS_NOTIFY_NOSOA 0x0001U
+
+/*%
+ * dns_stub holds state while performing a 'stub' transfer.
+ * 'db' is the zone's 'db' or a new one if this is the initial
+ * transfer.
+ */
+
+struct dns_stub {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ dns_zone_t *zone;
+ dns_db_t *db;
+ dns_dbversion_t *version;
+};
+
+/*%
+ * Hold load state.
+ */
+struct dns_load {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ dns_zone_t *zone;
+ dns_db_t *db;
+ isc_time_t loadtime;
+ dns_rdatacallbacks_t callbacks;
+};
+
+/*%
+ * Hold forward state.
+ */
+struct dns_forward {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ dns_zone_t *zone;
+ isc_buffer_t *msgbuf;
+ dns_request_t *request;
+ isc_uint32_t which;
+ isc_sockaddr_t addr;
+ dns_updatecallback_t callback;
+ void *callback_arg;
+};
+
+/*%
+ * Hold IO request state.
+ */
+struct dns_io {
+ unsigned int magic;
+ dns_zonemgr_t *zmgr;
+ isc_boolean_t high;
+ isc_task_t *task;
+ ISC_LINK(dns_io_t) link;
+ isc_event_t *event;
+};
+
+/*%
+ * Hold state for when we are signing a zone with a new
+ * DNSKEY as result of an update.
+ */
+struct dns_signing {
+ unsigned int magic;
+ dns_db_t *db;
+ dns_dbiterator_t *dbiterator;
+ dns_secalg_t algorithm;
+ isc_uint16_t keyid;
+ isc_boolean_t delete;
+ isc_boolean_t done;
+ ISC_LINK(dns_signing_t) link;
+};
+
+struct dns_nsec3chain {
+ 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_LINK(dns_nsec3chain_t) link;
+};
+/*%<
+ * 'dbiterator' contains a iterator for the database. If we are creating
+ * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
+ * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
+ * iterated.
+ *
+ * 'nsec3param' contains the parameters of the NSEC3 chain being created
+ * or removed.
+ *
+ * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
+ *
+ * 'seen_nsec' will be set to true if, while iterating the zone to create a
+ * NSEC3 chain, a NSEC record is seen.
+ *
+ * 'delete_nsec' will be set to true if, at the completion of the creation
+ * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
+ * are in the process of deleting the NSEC chain.
+ *
+ * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
+ * so it can be recovered in the event of a error.
+ */
+
+
+#define SEND_BUFFER_SIZE 2048
+
+static void zone_settimer(dns_zone_t *, isc_time_t *);
+static void cancel_refresh(dns_zone_t *);
+static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
+ const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
+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 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);
+static void zone_idetach(dns_zone_t **zonep);
+static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
+ isc_boolean_t dump);
+static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
+static inline void zone_detachdb(dns_zone_t *zone);
+static isc_result_t default_journal(dns_zone_t *zone);
+static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
+static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
+ isc_time_t loadtime, isc_result_t result);
+static void zone_needdump(dns_zone_t *zone, unsigned int delay);
+static void zone_shutdown(isc_task_t *, isc_event_t *);
+static void zone_loaddone(void *arg, isc_result_t result);
+static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
+ isc_time_t loadtime);
+static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
+static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
+static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
+static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
+
+#if 0
+/* ondestroy example */
+static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
+#endif
+
+static void refresh_callback(isc_task_t *, isc_event_t *);
+static void stub_callback(isc_task_t *, isc_event_t *);
+static void queue_soa_query(dns_zone_t *zone);
+static void soa_query(isc_task_t *, isc_event_t *);
+static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
+ dns_stub_t *stub);
+static int message_count(dns_message_t *msg, dns_section_t section,
+ dns_rdatatype_t type);
+static void notify_cancel(dns_zone_t *zone);
+static void notify_find_address(dns_notify_t *notify);
+static void notify_send(dns_notify_t *notify);
+static isc_result_t notify_createmessage(dns_zone_t *zone,
+ unsigned int flags,
+ dns_message_t **messagep);
+static void notify_done(isc_task_t *task, isc_event_t *event);
+static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
+static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
+static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
+static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
+ dns_zone_t *zone);
+static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
+static void zonemgr_free(dns_zonemgr_t *zmgr);
+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);
+static void zonemgr_putio(dns_io_t **iop);
+static void zonemgr_cancelio(dns_io_t *io);
+
+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);
+
+static void zone_freedbargs(dns_zone_t *zone);
+static void forward_callback(isc_task_t *task, isc_event_t *event);
+static void zone_saveunique(dns_zone_t *zone, const char *path,
+ const char *templat);
+static void zone_maintenance(dns_zone_t *zone);
+static void zone_notify(dns_zone_t *zone, isc_time_t *now);
+static void dump_done(void *arg, isc_result_t result);
+static isc_boolean_t dns_zonemgr_unreachable(dns_zonemgr_t *zmgr,
+ isc_sockaddr_t *remote,
+ isc_sockaddr_t *local,
+ 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);
+
+#define ENTER zone_debuglog(zone, me, 1, "enter")
+
+static const unsigned int dbargc_default = 1;
+static const char *dbargv_default[] = { "rbt" };
+
+#define DNS_ZONE_JITTER_ADD(a, b, c) \
+ do { \
+ isc_interval_t _i; \
+ isc_uint32_t _j; \
+ _j = isc_random_jitter((b), (b)/4); \
+ isc_interval_set(&_i, _j, 0); \
+ if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
+ dns_zone_log(zone, ISC_LOG_WARNING, \
+ "epoch approaching: upgrade required: " \
+ "now + %s failed", #b); \
+ isc_interval_set(&_i, _j/2, 0); \
+ (void)isc_time_add((a), &_i, (c)); \
+ } \
+ } while (0)
+
+#define DNS_ZONE_TIME_ADD(a, b, c) \
+ do { \
+ isc_interval_t _i; \
+ isc_interval_set(&_i, (b), 0); \
+ if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
+ dns_zone_log(zone, ISC_LOG_WARNING, \
+ "epoch approaching: upgrade required: " \
+ "now + %s failed", #b); \
+ isc_interval_set(&_i, (b)/2, 0); \
+ (void)isc_time_add((a), &_i, (c)); \
+ } \
+ } while (0)
+
+/*%
+ * Increment resolver-related statistics counters. Zone must be locked.
+ */
+static inline void
+inc_stats(dns_zone_t *zone, dns_statscounter_t counter) {
+ if (zone->stats != NULL)
+ dns_generalstats_increment(zone->stats, counter);
+}
+
+/***
+ *** Public functions.
+ ***/
+
+isc_result_t
+dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
+ isc_result_t result;
+ dns_zone_t *zone;
+ isc_time_t now;
+
+ REQUIRE(zonep != NULL && *zonep == NULL);
+ REQUIRE(mctx != NULL);
+
+ TIME_NOW(&now);
+ zone = isc_mem_get(mctx, sizeof(*zone));
+ if (zone == NULL)
+ return (ISC_R_NOMEMORY);
+
+ zone->mctx = NULL;
+ isc_mem_attach(mctx, &zone->mctx);
+
+ result = isc_mutex_init(&zone->lock);
+ if (result != ISC_R_SUCCESS)
+ goto free_zone;
+
+ result = ZONEDB_INITLOCK(&zone->dblock);
+ if (result != ISC_R_SUCCESS)
+ goto free_mutex;
+
+ /* XXX MPA check that all elements are initialised */
+#ifdef DNS_ZONE_CHECKLOCK
+ zone->locked = ISC_FALSE;
+#endif
+ zone->db = NULL;
+ zone->zmgr = NULL;
+ ISC_LINK_INIT(zone, link);
+ result = isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
+ if (result != ISC_R_SUCCESS)
+ goto free_dblock;
+ zone->irefs = 0;
+ dns_name_init(&zone->origin, NULL);
+ zone->strnamerd = NULL;
+ zone->strname = NULL;
+ zone->strrdclass = NULL;
+ zone->strviewname = NULL;
+ zone->masterfile = NULL;
+ zone->masterformat = dns_masterformat_none;
+ zone->keydirectory = NULL;
+ zone->journalsize = -1;
+ zone->journal = NULL;
+ zone->rdclass = dns_rdataclass_none;
+ zone->type = dns_zone_none;
+ zone->flags = 0;
+ zone->options = 0;
+ zone->db_argc = 0;
+ zone->db_argv = NULL;
+ isc_time_settoepoch(&zone->expiretime);
+ isc_time_settoepoch(&zone->refreshtime);
+ isc_time_settoepoch(&zone->dumptime);
+ isc_time_settoepoch(&zone->loadtime);
+ zone->notifytime = now;
+ isc_time_settoepoch(&zone->resigntime);
+ isc_time_settoepoch(&zone->keywarntime);
+ isc_time_settoepoch(&zone->signingtime);
+ isc_time_settoepoch(&zone->nsec3chaintime);
+ zone->serial = 0;
+ zone->refresh = DNS_ZONE_DEFAULTREFRESH;
+ zone->retry = DNS_ZONE_DEFAULTRETRY;
+ zone->expire = 0;
+ zone->minimum = 0;
+ zone->maxrefresh = DNS_ZONE_MAXREFRESH;
+ zone->minrefresh = DNS_ZONE_MINREFRESH;
+ zone->maxretry = DNS_ZONE_MAXRETRY;
+ zone->minretry = DNS_ZONE_MINRETRY;
+ zone->masters = NULL;
+ zone->masterkeynames = NULL;
+ zone->mastersok = NULL;
+ zone->masterscnt = 0;
+ zone->curmaster = 0;
+ zone->notify = NULL;
+ zone->notifytype = dns_notifytype_yes;
+ zone->notifycnt = 0;
+ zone->task = NULL;
+ zone->update_acl = NULL;
+ zone->forward_acl = NULL;
+ zone->notify_acl = NULL;
+ zone->query_acl = NULL;
+ zone->queryon_acl = NULL;
+ zone->xfr_acl = NULL;
+ zone->update_disabled = ISC_FALSE;
+ zone->zero_no_soa_ttl = ISC_TRUE;
+ zone->check_names = dns_severity_ignore;
+ zone->request = NULL;
+ zone->lctx = NULL;
+ zone->readio = NULL;
+ zone->dctx = NULL;
+ zone->writeio = NULL;
+ zone->timer = NULL;
+ zone->idlein = DNS_DEFAULT_IDLEIN;
+ zone->idleout = DNS_DEFAULT_IDLEOUT;
+ ISC_LIST_INIT(zone->notifies);
+ isc_sockaddr_any(&zone->notifysrc4);
+ isc_sockaddr_any6(&zone->notifysrc6);
+ isc_sockaddr_any(&zone->xfrsource4);
+ isc_sockaddr_any6(&zone->xfrsource6);
+ isc_sockaddr_any(&zone->altxfrsource4);
+ isc_sockaddr_any6(&zone->altxfrsource6);
+ zone->xfr = NULL;
+ zone->tsigkey = NULL;
+ zone->maxxfrin = MAX_XFER_TIME;
+ zone->maxxfrout = MAX_XFER_TIME;
+ zone->ssutable = NULL;
+ zone->sigvalidityinterval = 30 * 24 * 3600;
+ zone->sigresigninginterval = 7 * 24 * 3600;
+ zone->view = NULL;
+ zone->acache = NULL;
+ zone->checkmx = NULL;
+ zone->checksrv = NULL;
+ zone->checkns = NULL;
+ ISC_LINK_INIT(zone, statelink);
+ zone->statelist = NULL;
+ zone->stats = NULL;
+ zone->requeststats_on = ISC_FALSE;
+ zone->requeststats = NULL;
+ zone->notifydelay = 5;
+ zone->isself = NULL;
+ zone->isselfarg = NULL;
+ ISC_LIST_INIT(zone->signing);
+ ISC_LIST_INIT(zone->nsec3chain);
+ zone->signatures = 10;
+ zone->nodes = 100;
+ zone->privatetype = (dns_rdatatype_t)0xffffU;
+
+ zone->magic = ZONE_MAGIC;
+
+ /* Must be after magic is set. */
+ result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
+ if (result != ISC_R_SUCCESS)
+ goto free_erefs;
+
+ ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
+ DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
+ NULL, NULL);
+ *zonep = zone;
+ return (ISC_R_SUCCESS);
+
+ free_erefs:
+ isc_refcount_decrement(&zone->erefs, NULL);
+ isc_refcount_destroy(&zone->erefs);
+
+ free_dblock:
+ ZONEDB_DESTROYLOCK(&zone->dblock);
+
+ free_mutex:
+ DESTROYLOCK(&zone->lock);
+
+ free_zone:
+ isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
+ return (result);
+}
+
+/*
+ * Free a zone. Because we require that there be no more
+ * outstanding events or references, no locking is necessary.
+ */
+static void
+zone_free(dns_zone_t *zone) {
+ isc_mem_t *mctx = NULL;
+ dns_signing_t *signing;
+ dns_nsec3chain_t *nsec3chain;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(isc_refcount_current(&zone->erefs) == 0);
+ REQUIRE(zone->irefs == 0);
+ REQUIRE(!LOCKED_ZONE(zone));
+ REQUIRE(zone->timer == NULL);
+
+ /*
+ * Managed objects. Order is important.
+ */
+ if (zone->request != NULL)
+ dns_request_destroy(&zone->request); /* XXXMPA */
+ INSIST(zone->readio == NULL);
+ INSIST(zone->statelist == NULL);
+ INSIST(zone->writeio == NULL);
+
+ if (zone->task != NULL)
+ isc_task_detach(&zone->task);
+ if (zone->zmgr != NULL)
+ dns_zonemgr_releasezone(zone->zmgr, zone);
+
+ /* Unmanaged objects */
+ for (signing = ISC_LIST_HEAD(zone->signing);
+ signing != NULL;
+ signing = ISC_LIST_HEAD(zone->signing)) {
+ ISC_LIST_UNLINK(zone->signing, signing, link);
+ dns_db_detach(&signing->db);
+ dns_dbiterator_destroy(&signing->dbiterator);
+ isc_mem_put(zone->mctx, signing, sizeof *signing);
+ }
+ for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
+ nsec3chain != NULL;
+ nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
+ ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
+ dns_db_detach(&nsec3chain->db);
+ dns_dbiterator_destroy(&nsec3chain->dbiterator);
+ isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
+ }
+ if (zone->masterfile != NULL)
+ isc_mem_free(zone->mctx, zone->masterfile);
+ zone->masterfile = NULL;
+ if (zone->keydirectory != NULL)
+ isc_mem_free(zone->mctx, zone->keydirectory);
+ zone->keydirectory = NULL;
+ zone->journalsize = -1;
+ if (zone->journal != NULL)
+ isc_mem_free(zone->mctx, zone->journal);
+ zone->journal = NULL;
+ if (zone->stats != NULL)
+ dns_stats_detach(&zone->stats);
+ if (zone->requeststats != NULL)
+ dns_stats_detach(&zone->requeststats);
+ if (zone->db != NULL)
+ zone_detachdb(zone);
+ if (zone->acache != NULL)
+ dns_acache_detach(&zone->acache);
+ zone_freedbargs(zone);
+ RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
+ == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
+ == ISC_R_SUCCESS);
+ zone->check_names = dns_severity_ignore;
+ if (zone->update_acl != NULL)
+ dns_acl_detach(&zone->update_acl);
+ if (zone->forward_acl != NULL)
+ dns_acl_detach(&zone->forward_acl);
+ if (zone->notify_acl != NULL)
+ dns_acl_detach(&zone->notify_acl);
+ if (zone->query_acl != NULL)
+ dns_acl_detach(&zone->query_acl);
+ if (zone->queryon_acl != NULL)
+ dns_acl_detach(&zone->queryon_acl);
+ if (zone->xfr_acl != NULL)
+ dns_acl_detach(&zone->xfr_acl);
+ if (dns_name_dynamic(&zone->origin))
+ dns_name_free(&zone->origin, zone->mctx);
+ if (zone->strnamerd != NULL)
+ isc_mem_free(zone->mctx, zone->strnamerd);
+ if (zone->strname != NULL)
+ isc_mem_free(zone->mctx, zone->strname);
+ if (zone->strrdclass != NULL)
+ isc_mem_free(zone->mctx, zone->strrdclass);
+ if (zone->strviewname != NULL)
+ isc_mem_free(zone->mctx, zone->strviewname);
+ if (zone->ssutable != NULL)
+ dns_ssutable_detach(&zone->ssutable);
+
+ /* last stuff */
+ ZONEDB_DESTROYLOCK(&zone->dblock);
+ DESTROYLOCK(&zone->lock);
+ isc_refcount_destroy(&zone->erefs);
+ zone->magic = 0;
+ mctx = zone->mctx;
+ isc_mem_put(mctx, zone, sizeof(*zone));
+ isc_mem_detach(&mctx);
+}
+
+/*
+ * Single shot.
+ */
+void
+dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
+ char namebuf[1024];
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(rdclass != dns_rdataclass_none);
+
+ /*
+ * Test and set.
+ */
+ LOCK_ZONE(zone);
+ REQUIRE(zone->rdclass == dns_rdataclass_none ||
+ zone->rdclass == rdclass);
+ zone->rdclass = rdclass;
+
+ if (zone->strnamerd != NULL)
+ isc_mem_free(zone->mctx, zone->strnamerd);
+ if (zone->strrdclass != NULL)
+ isc_mem_free(zone->mctx, zone->strrdclass);
+
+ zone_namerd_tostr(zone, namebuf, sizeof namebuf);
+ zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
+ zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
+ zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
+
+ UNLOCK_ZONE(zone);
+}
+
+dns_rdataclass_t
+dns_zone_getclass(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->rdclass);
+}
+
+void
+dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ zone->notifytype = notifytype;
+ UNLOCK_ZONE(zone);
+}
+
+isc_uint32_t
+dns_zone_getserial(dns_zone_t *zone) {
+ isc_uint32_t serial;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ serial = zone->serial;
+ UNLOCK_ZONE(zone);
+
+ return (serial);
+}
+
+/*
+ * Single shot.
+ */
+void
+dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(type != dns_zone_none);
+
+ /*
+ * Test and set.
+ */
+ LOCK_ZONE(zone);
+ REQUIRE(zone->type == dns_zone_none || zone->type == type);
+ zone->type = type;
+ UNLOCK_ZONE(zone);
+}
+
+static void
+zone_freedbargs(dns_zone_t *zone) {
+ unsigned int i;
+
+ /* Free the old database argument list. */
+ if (zone->db_argv != NULL) {
+ for (i = 0; i < zone->db_argc; i++)
+ isc_mem_free(zone->mctx, zone->db_argv[i]);
+ isc_mem_put(zone->mctx, zone->db_argv,
+ zone->db_argc * sizeof(*zone->db_argv));
+ }
+ zone->db_argc = 0;
+ zone->db_argv = NULL;
+}
+
+isc_result_t
+dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
+ size_t size = 0;
+ unsigned int i;
+ isc_result_t result = ISC_R_SUCCESS;
+ void *mem;
+ char **tmp, *tmp2;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(argv != NULL && *argv == NULL);
+
+ LOCK_ZONE(zone);
+ size = (zone->db_argc + 1) * sizeof(char *);
+ for (i = 0; i < zone->db_argc; i++)
+ size += strlen(zone->db_argv[i]) + 1;
+ mem = isc_mem_allocate(mctx, size);
+ if (mem != NULL) {
+ tmp = mem;
+ tmp2 = mem;
+ tmp2 += (zone->db_argc + 1) * sizeof(char *);
+ for (i = 0; i < zone->db_argc; i++) {
+ *tmp++ = tmp2;
+ strcpy(tmp2, zone->db_argv[i]);
+ tmp2 += strlen(tmp2) + 1;
+ }
+ *tmp = NULL;
+ } else
+ result = ISC_R_NOMEMORY;
+ UNLOCK_ZONE(zone);
+ *argv = mem;
+ return (result);
+}
+
+isc_result_t
+dns_zone_setdbtype(dns_zone_t *zone,
+ unsigned int dbargc, const char * const *dbargv) {
+ isc_result_t result = ISC_R_SUCCESS;
+ char **new = NULL;
+ unsigned int i;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(dbargc >= 1);
+ REQUIRE(dbargv != NULL);
+
+ LOCK_ZONE(zone);
+
+ /* Set up a new database argument list. */
+ new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
+ if (new == NULL)
+ goto nomem;
+ for (i = 0; i < dbargc; i++)
+ new[i] = NULL;
+ for (i = 0; i < dbargc; i++) {
+ new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
+ if (new[i] == NULL)
+ goto nomem;
+ }
+
+ /* Free the old list. */
+ zone_freedbargs(zone);
+
+ zone->db_argc = dbargc;
+ zone->db_argv = new;
+ result = ISC_R_SUCCESS;
+ goto unlock;
+
+ nomem:
+ if (new != NULL) {
+ for (i = 0; i < dbargc; i++)
+ if (new[i] != NULL)
+ isc_mem_free(zone->mctx, new[i]);
+ isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
+ }
+ result = ISC_R_NOMEMORY;
+
+ unlock:
+ UNLOCK_ZONE(zone);
+ return (result);
+}
+
+void
+dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
+ char namebuf[1024];
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (zone->view != NULL)
+ dns_view_weakdetach(&zone->view);
+ dns_view_weakattach(view, &zone->view);
+
+ if (zone->strviewname != NULL)
+ isc_mem_free(zone->mctx, zone->strviewname);
+ if (zone->strnamerd != NULL)
+ isc_mem_free(zone->mctx, zone->strnamerd);
+
+ zone_namerd_tostr(zone, namebuf, sizeof namebuf);
+ zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
+ zone_viewname_tostr(zone, namebuf, sizeof namebuf);
+ zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
+
+ UNLOCK_ZONE(zone);
+}
+
+
+dns_view_t *
+dns_zone_getview(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->view);
+}
+
+
+isc_result_t
+dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
+ isc_result_t result;
+ char namebuf[1024];
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(origin != NULL);
+
+ LOCK_ZONE(zone);
+ if (dns_name_dynamic(&zone->origin)) {
+ dns_name_free(&zone->origin, zone->mctx);
+ dns_name_init(&zone->origin, NULL);
+ }
+ result = dns_name_dup(origin, zone->mctx, &zone->origin);
+
+ if (zone->strnamerd != NULL)
+ isc_mem_free(zone->mctx, zone->strnamerd);
+ if (zone->strname != NULL)
+ isc_mem_free(zone->mctx, zone->strname);
+
+ zone_namerd_tostr(zone, namebuf, sizeof namebuf);
+ zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
+ zone_name_tostr(zone, namebuf, sizeof namebuf);
+ zone->strname = isc_mem_strdup(zone->mctx, namebuf);
+
+ UNLOCK_ZONE(zone);
+ return (result);
+}
+
+void
+dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(acache != NULL);
+
+ LOCK_ZONE(zone);
+ if (zone->acache != NULL)
+ dns_acache_detach(&zone->acache);
+ dns_acache_attach(acache, &zone->acache);
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL) {
+ isc_result_t result;
+
+ /*
+ * If the zone reuses an existing DB, the DB needs to be
+ * set in the acache explicitly. We can safely ignore the
+ * case where the DB is already set. If other error happens,
+ * the acache will not work effectively.
+ */
+ result = dns_acache_setdb(acache, zone->db);
+ if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "dns_acache_setdb() failed: %s",
+ isc_result_totext(result));
+ }
+ }
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ UNLOCK_ZONE(zone);
+}
+
+static isc_result_t
+dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
+ char *copy;
+
+ if (value != NULL) {
+ copy = isc_mem_strdup(zone->mctx, value);
+ if (copy == NULL)
+ return (ISC_R_NOMEMORY);
+ } else {
+ copy = NULL;
+ }
+
+ if (*field != NULL)
+ isc_mem_free(zone->mctx, *field);
+
+ *field = copy;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_zone_setfile(dns_zone_t *zone, const char *file) {
+ return (dns_zone_setfile2(zone, file, dns_masterformat_text));
+}
+
+isc_result_t
+dns_zone_setfile2(dns_zone_t *zone, const char *file,
+ dns_masterformat_t format) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ result = dns_zone_setstring(zone, &zone->masterfile, file);
+ if (result == ISC_R_SUCCESS) {
+ zone->masterformat = format;
+ result = default_journal(zone);
+ }
+ UNLOCK_ZONE(zone);
+
+ return (result);
+}
+
+const char *
+dns_zone_getfile(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->masterfile);
+}
+
+static isc_result_t
+default_journal(dns_zone_t *zone) {
+ isc_result_t result;
+ char *journal;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(LOCKED_ZONE(zone));
+
+ if (zone->masterfile != NULL) {
+ /* Calculate string length including '\0'. */
+ int len = strlen(zone->masterfile) + sizeof(".jnl");
+ journal = isc_mem_allocate(zone->mctx, len);
+ if (journal == NULL)
+ return (ISC_R_NOMEMORY);
+ strcpy(journal, zone->masterfile);
+ strcat(journal, ".jnl");
+ } else {
+ journal = NULL;
+ }
+ result = dns_zone_setstring(zone, &zone->journal, journal);
+ if (journal != NULL)
+ isc_mem_free(zone->mctx, journal);
+ return (result);
+}
+
+isc_result_t
+dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ result = dns_zone_setstring(zone, &zone->journal, journal);
+ UNLOCK_ZONE(zone);
+
+ return (result);
+}
+
+char *
+dns_zone_getjournal(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->journal);
+}
+
+/*
+ * Return true iff the zone is "dynamic", in the sense that the zone's
+ * 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")
+ * or an "allow-update" ACL with a value other than exactly "{ none; }".
+ */
+static isc_boolean_t
+zone_isdynamic(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (ISC_TF(zone->type == dns_zone_slave ||
+ zone->type == dns_zone_stub ||
+ (!zone->update_disabled && zone->ssutable != NULL) ||
+ (!zone->update_disabled && zone->update_acl != NULL &&
+ !dns_acl_isnone(zone->update_acl))));
+}
+
+
+static isc_result_t
+zone_load(dns_zone_t *zone, unsigned int flags) {
+ isc_result_t result;
+ isc_time_t now;
+ isc_time_t loadtime, filetime;
+ dns_db_t *db = NULL;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ TIME_NOW(&now);
+
+ INSIST(zone->type != dns_zone_none);
+
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ if (zone->db != NULL && zone->masterfile == NULL) {
+ /*
+ * The zone has no master file configured, but it already
+ * has a database. It could be the built-in
+ * version.bind. CH zone, a zone with a persistent
+ * database being reloaded, or maybe a zone that
+ * used to have a master file but whose configuration
+ * was changed so that it no longer has one. Do nothing.
+ */
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ if (zone->db != NULL && zone_isdynamic(zone)) {
+ /*
+ * This is a slave, stub, or dynamically updated
+ * zone being reloaded. Do nothing - the database
+ * we already have is guaranteed to be up-to-date.
+ */
+ if (zone->type == dns_zone_master)
+ result = DNS_R_DYNAMIC;
+ else
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+
+ /*
+ * Store the current time before the zone is loaded, so that if the
+ * file changes between the time of the load and the time that
+ * zone->loadtime is set, then the file will still be reloaded
+ * the next time dns_zone_load is called.
+ */
+ TIME_NOW(&loadtime);
+
+ /*
+ * Don't do the load if the file that stores the zone is older
+ * than the last time the zone was loaded. If the zone has not
+ * been loaded yet, zone->loadtime will be the epoch.
+ */
+ if (zone->masterfile != NULL) {
+ /*
+ * 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) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ result = isc_file_getmodtime(zone->masterfile, &filetime);
+ 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) {
+ dns_zone_log(zone, ISC_LOG_DEBUG(1),
+ "skipping load: master file "
+ "older than last load");
+ result = DNS_R_UPTODATE;
+ goto cleanup;
+ }
+ loadtime = filetime;
+ }
+ }
+
+ INSIST(zone->db_argc >= 1);
+
+ /*
+ * Built in zones don't need to be reloaded.
+ */
+ if (zone->type == dns_zone_master &&
+ strcmp(zone->db_argv[0], "_builtin") == 0 &&
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+
+ if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
+ (strcmp(zone->db_argv[0], "rbt") == 0 ||
+ strcmp(zone->db_argv[0], "rbt64") == 0)) {
+ if (zone->masterfile == NULL ||
+ !isc_file_exists(zone->masterfile)) {
+ if (zone->masterfile != NULL) {
+ dns_zone_log(zone, ISC_LOG_DEBUG(1),
+ "no master file");
+ }
+ zone->refreshtime = now;
+ if (zone->task != NULL)
+ zone_settimer(zone, &now);
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+ }
+
+ dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
+
+ result = dns_db_create(zone->mctx, zone->db_argv[0],
+ &zone->origin, (zone->type == dns_zone_stub) ?
+ dns_dbtype_stub : dns_dbtype_zone,
+ zone->rdclass,
+ zone->db_argc - 1, zone->db_argv + 1,
+ &db);
+
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "loading zone: creating database: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+ dns_db_settask(db, zone->task);
+
+ if (! dns_db_ispersistent(db)) {
+ if (zone->masterfile != NULL) {
+ result = zone_startload(db, zone, loadtime);
+ } else {
+ result = DNS_R_NOMASTERFILE;
+ if (zone->type == dns_zone_master) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "loading zone: "
+ "no master file configured");
+ goto cleanup;
+ }
+ dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
+ "no master file configured: continuing");
+ }
+ }
+
+ if (result == DNS_R_CONTINUE) {
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
+ goto cleanup;
+ }
+
+ result = zone_postload(zone, db, loadtime, result);
+
+ cleanup:
+ UNLOCK_ZONE(zone);
+ if (db != NULL)
+ dns_db_detach(&db);
+ return (result);
+}
+
+isc_result_t
+dns_zone_load(dns_zone_t *zone) {
+ return (zone_load(zone, 0));
+}
+
+isc_result_t
+dns_zone_loadnew(dns_zone_t *zone) {
+ return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
+}
+
+static unsigned int
+get_master_options(dns_zone_t *zone) {
+ unsigned int options;
+
+ options = DNS_MASTER_ZONE;
+ if (zone->type == dns_zone_slave)
+ options |= DNS_MASTER_SLAVE;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
+ options |= DNS_MASTER_CHECKNS;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
+ options |= DNS_MASTER_FATALNS;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
+ options |= DNS_MASTER_CHECKNAMES;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
+ options |= DNS_MASTER_CHECKNAMESFAIL;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
+ options |= DNS_MASTER_CHECKMX;
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
+ options |= DNS_MASTER_CHECKMXFAIL;
+ 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))
+ options |= DNS_MASTER_RESIGN;
+ return (options);
+}
+
+static void
+zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
+ dns_load_t *load = event->ev_arg;
+ isc_result_t result = ISC_R_SUCCESS;
+ unsigned int options;
+
+ REQUIRE(DNS_LOAD_VALID(load));
+
+ if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
+ result = ISC_R_CANCELED;
+ isc_event_free(&event);
+ if (result == ISC_R_CANCELED)
+ goto fail;
+
+ options = get_master_options(load->zone);
+
+ result = dns_master_loadfileinc3(load->zone->masterfile,
+ dns_db_origin(load->db),
+ dns_db_origin(load->db),
+ load->zone->rdclass,
+ options,
+ load->zone->sigresigninginterval,
+ &load->callbacks, task,
+ zone_loaddone, load,
+ &load->zone->lctx, load->zone->mctx,
+ load->zone->masterformat);
+ if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
+ result != DNS_R_SEENINCLUDE)
+ goto fail;
+ return;
+
+ fail:
+ zone_loaddone(load, result);
+}
+
+static void
+zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
+ const char me[] = "zone_gotwritehandle";
+ dns_zone_t *zone = event->ev_arg;
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_dbversion_t *version = NULL;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ INSIST(task == zone->task);
+ ENTER;
+
+ if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
+ result = ISC_R_CANCELED;
+ isc_event_free(&event);
+ if (result == ISC_R_CANCELED)
+ goto fail;
+
+ LOCK_ZONE(zone);
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ dns_db_currentversion(zone->db, &version);
+ result = dns_master_dumpinc2(zone->mctx, zone->db, version,
+ &dns_master_style_default,
+ zone->masterfile, zone->task, dump_done,
+ zone, &zone->dctx, zone->masterformat);
+ dns_db_closeversion(zone->db, &version, ISC_FALSE);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ UNLOCK_ZONE(zone);
+ if (result != DNS_R_CONTINUE)
+ goto fail;
+ return;
+
+ fail:
+ dump_done(zone, result);
+}
+
+static isc_result_t
+zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
+ dns_load_t *load;
+ isc_result_t result;
+ isc_result_t tresult;
+ unsigned int options;
+
+ options = get_master_options(zone);
+
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
+ options |= DNS_MASTER_MANYERRORS;
+
+ if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
+ load = isc_mem_get(zone->mctx, sizeof(*load));
+ if (load == NULL)
+ return (ISC_R_NOMEMORY);
+
+ load->mctx = NULL;
+ load->zone = NULL;
+ load->db = NULL;
+ load->loadtime = loadtime;
+ load->magic = LOAD_MAGIC;
+
+ isc_mem_attach(zone->mctx, &load->mctx);
+ zone_iattach(zone, &load->zone);
+ dns_db_attach(db, &load->db);
+ dns_rdatacallbacks_init(&load->callbacks);
+ result = dns_db_beginload(db, &load->callbacks.add,
+ &load->callbacks.add_private);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
+ zone_gotreadhandle, load,
+ &zone->readio);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * We can't report multiple errors so ignore
+ * the result of dns_db_endload().
+ */
+ (void)dns_db_endload(load->db,
+ &load->callbacks.add_private);
+ goto cleanup;
+ } else
+ result = DNS_R_CONTINUE;
+ } else {
+ dns_rdatacallbacks_t callbacks;
+
+ dns_rdatacallbacks_init(&callbacks);
+ result = dns_db_beginload(db, &callbacks.add,
+ &callbacks.add_private);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = dns_master_loadfile3(zone->masterfile, &zone->origin,
+ &zone->origin, zone->rdclass,
+ options, zone->sigresigninginterval,
+ &callbacks, zone->mctx,
+ zone->masterformat);
+ tresult = dns_db_endload(db, &callbacks.add_private);
+ if (result == ISC_R_SUCCESS)
+ result = tresult;
+ }
+
+ return (result);
+
+ cleanup:
+ load->magic = 0;
+ dns_db_detach(&load->db);
+ zone_idetach(&load->zone);
+ isc_mem_detach(&load->mctx);
+ isc_mem_put(zone->mctx, load, sizeof(*load));
+ return (result);
+}
+
+static isc_boolean_t
+zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
+ dns_name_t *owner)
+{
+ isc_result_t result;
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char altbuf[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fixed;
+ dns_name_t *foundname;
+ int level;
+
+ /*
+ * Outside of zone.
+ */
+ if (!dns_name_issubdomain(name, &zone->origin)) {
+ if (zone->checkmx != NULL)
+ return ((zone->checkmx)(zone, name, owner));
+ return (ISC_TRUE);
+ }
+
+ 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, NULL, 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, NULL, dns_rdatatype_aaaa,
+ 0, 0, NULL, foundname, NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+ }
+
+ dns_name_format(owner, ownerbuf, sizeof ownerbuf);
+ 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,
+ "%s/MX '%s' has no address records (A or AAAA)",
+ ownerbuf, namebuf);
+ /* XXX950 make fatal for 9.5.0. */
+ return (ISC_TRUE);
+ }
+
+ if (result == DNS_R_CNAME) {
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
+ DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
+ level = ISC_LOG_WARNING;
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
+ dns_zone_log(zone, level,
+ "%s/MX '%s' is a CNAME (illegal)",
+ ownerbuf, namebuf);
+ return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
+ }
+
+ if (result == DNS_R_DNAME) {
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
+ DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
+ level = ISC_LOG_WARNING;
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
+ dns_name_format(foundname, altbuf, sizeof altbuf);
+ dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
+ " '%s' (illegal)", ownerbuf, namebuf,
+ altbuf);
+ }
+ return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
+ }
+
+ if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
+ return ((zone->checkmx)(zone, name, owner));
+
+ return (ISC_TRUE);
+}
+
+static isc_boolean_t
+zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
+ dns_name_t *owner)
+{
+ isc_result_t result;
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char altbuf[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fixed;
+ dns_name_t *foundname;
+ int level;
+
+ /*
+ * "." means the services does not exist.
+ */
+ if (dns_name_equal(name, dns_rootname))
+ return (ISC_TRUE);
+
+ /*
+ * Outside of zone.
+ */
+ if (!dns_name_issubdomain(name, &zone->origin)) {
+ if (zone->checksrv != NULL)
+ return ((zone->checksrv)(zone, name, owner));
+ return (ISC_TRUE);
+ }
+
+ 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, NULL, 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, NULL, dns_rdatatype_aaaa,
+ 0, 0, NULL, foundname, NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+ }
+
+ dns_name_format(owner, ownerbuf, sizeof ownerbuf);
+ 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,
+ "%s/SRV '%s' has no address records (A or AAAA)",
+ ownerbuf, namebuf);
+ /* XXX950 make fatal for 9.5.0. */
+ return (ISC_TRUE);
+ }
+
+ if (result == DNS_R_CNAME) {
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
+ DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
+ level = ISC_LOG_WARNING;
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
+ dns_zone_log(zone, level,
+ "%s/SRV '%s' is a CNAME (illegal)",
+ ownerbuf, namebuf);
+ return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
+ }
+
+ if (result == DNS_R_DNAME) {
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
+ DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
+ level = ISC_LOG_WARNING;
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
+ dns_name_format(foundname, altbuf, sizeof altbuf);
+ dns_zone_log(zone, level, "%s/SRV '%s' is below a "
+ "DNAME '%s' (illegal)", ownerbuf, namebuf,
+ altbuf);
+ }
+ return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
+ }
+
+ if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
+ return ((zone->checksrv)(zone, name, owner));
+
+ return (ISC_TRUE);
+}
+
+static isc_boolean_t
+zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
+ dns_name_t *owner)
+{
+ isc_boolean_t answer = ISC_TRUE;
+ isc_result_t result, tresult;
+ char ownerbuf[DNS_NAME_FORMATSIZE];
+ char namebuf[DNS_NAME_FORMATSIZE];
+ char altbuf[DNS_NAME_FORMATSIZE];
+ dns_fixedname_t fixed;
+ dns_name_t *foundname;
+ dns_rdataset_t a;
+ dns_rdataset_t aaaa;
+ int level;
+
+ /*
+ * Outside of zone.
+ */
+ if (!dns_name_issubdomain(name, &zone->origin)) {
+ if (zone->checkns != NULL)
+ return ((zone->checkns)(zone, name, owner, NULL, NULL));
+ return (ISC_TRUE);
+ }
+
+ if (zone->type == dns_zone_master)
+ level = ISC_LOG_ERROR;
+ else
+ level = ISC_LOG_WARNING;
+
+ dns_fixedname_init(&fixed);
+ foundname = dns_fixedname_name(&fixed);
+ dns_rdataset_init(&a);
+ dns_rdataset_init(&aaaa);
+
+ result = dns_db_find(db, name, NULL, dns_rdatatype_a,
+ DNS_DBFIND_GLUEOK, 0, NULL,
+ foundname, &a, NULL);
+
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&a);
+ return (ISC_TRUE);
+ } else if (result == DNS_R_DELEGATION)
+ dns_rdataset_disassociate(&a);
+
+ if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
+ result == DNS_R_GLUE) {
+ tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
+ DNS_DBFIND_GLUEOK, 0, NULL,
+ foundname, &aaaa, NULL);
+ if (tresult == ISC_R_SUCCESS) {
+ dns_rdataset_disassociate(&aaaa);
+ return (ISC_TRUE);
+ }
+ if (tresult == DNS_R_DELEGATION)
+ dns_rdataset_disassociate(&aaaa);
+ if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
+ /*
+ * Check glue against child zone.
+ */
+ if (zone->checkns != NULL)
+ answer = (zone->checkns)(zone, name, owner,
+ &a, &aaaa);
+ if (dns_rdataset_isassociated(&a))
+ dns_rdataset_disassociate(&a);
+ if (dns_rdataset_isassociated(&aaaa))
+ dns_rdataset_disassociate(&aaaa);
+ return (answer);
+ }
+ } else
+ tresult = result;
+
+ dns_name_format(owner, ownerbuf, sizeof ownerbuf);
+ dns_name_format(name, namebuf, sizeof namebuf);
+ if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
+ result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
+ const char *what;
+ isc_boolean_t required = ISC_FALSE;
+ if (dns_name_issubdomain(name, owner)) {
+ what = "REQUIRED GLUE ";
+ required = ISC_TRUE;
+ } else if (result == DNS_R_DELEGATION)
+ what = "SIBLING GLUE ";
+ else
+ what = "";
+
+ if (result != DNS_R_DELEGATION || required ||
+ DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
+ dns_zone_log(zone, level, "%s/NS '%s' has no %s"
+ "address records (A or AAAA)",
+ ownerbuf, namebuf, what);
+ /*
+ * Log missing address record.
+ */
+ if (result == DNS_R_DELEGATION && zone->checkns != NULL)
+ (void)(zone->checkns)(zone, name, owner,
+ &a, &aaaa);
+ /* XXX950 make fatal for 9.5.0. */
+ /* answer = ISC_FALSE; */
+ }
+ } else if (result == DNS_R_CNAME) {
+ dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
+ ownerbuf, namebuf);
+ /* XXX950 make fatal for 9.5.0. */
+ /* answer = ISC_FALSE; */
+ } else if (result == DNS_R_DNAME) {
+ dns_name_format(foundname, altbuf, sizeof altbuf);
+ dns_zone_log(zone, level,
+ "%s/NS '%s' is below a DNAME '%s' (illegal)",
+ ownerbuf, namebuf, altbuf);
+ /* XXX950 make fatal for 9.5.0. */
+ /* answer = ISC_FALSE; */
+ }
+
+ if (dns_rdataset_isassociated(&a))
+ dns_rdataset_disassociate(&a);
+ if (dns_rdataset_isassociated(&aaaa))
+ dns_rdataset_disassociate(&aaaa);
+ return (answer);
+}
+
+static isc_boolean_t
+integrity_checks(dns_zone_t *zone, dns_db_t *db) {
+ dns_dbiterator_t *dbiterator = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_fixedname_t fixed;
+ dns_fixedname_t fixedbottom;
+ dns_rdata_mx_t mx;
+ dns_rdata_ns_t ns;
+ dns_rdata_in_srv_t srv;
+ dns_rdata_t rdata;
+ dns_name_t *name;
+ dns_name_t *bottom;
+ isc_result_t result;
+ isc_boolean_t ok = ISC_TRUE;
+
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ dns_fixedname_init(&fixedbottom);
+ bottom = dns_fixedname_name(&fixedbottom);
+ dns_rdataset_init(&rdataset);
+ dns_rdata_init(&rdata);
+
+ result = dns_db_createiterator(db, 0, &dbiterator);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_TRUE);
+
+ result = dns_dbiterator_first(dbiterator);
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbiterator, &node, name);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * Is this name visible in the zone?
+ */
+ if (!dns_name_issubdomain(name, &zone->origin) ||
+ (dns_name_countlabels(bottom) > 0 &&
+ dns_name_issubdomain(name, bottom)))
+ goto next;
+
+ /*
+ * Don't check the NS records at the origin.
+ */
+ if (dns_name_equal(name, &zone->origin))
+ goto checkmx;
+
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto checkmx;
+ /*
+ * Remember bottom of zone.
+ */
+ dns_name_copy(name, bottom, NULL);
+
+ result = dns_rdataset_first(&rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (!zone_check_glue(zone, db, &ns.name, name))
+ ok = ISC_FALSE;
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&rdataset);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ checkmx:
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto checksrv;
+ result = dns_rdataset_first(&rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &mx, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (!zone_check_mx(zone, db, &mx.mx, name))
+ ok = ISC_FALSE;
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&rdataset);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ checksrv:
+ if (zone->rdclass != dns_rdataclass_in)
+ goto next;
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto next;
+ result = dns_rdataset_first(&rdataset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &srv, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (!zone_check_srv(zone, db, &srv.target, name))
+ ok = ISC_FALSE;
+ dns_rdata_reset(&rdata);
+ result = dns_rdataset_next(&rdataset);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ next:
+ dns_db_detachnode(db, &node);
+ result = dns_dbiterator_next(dbiterator);
+ }
+
+ cleanup:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ dns_dbiterator_destroy(&dbiterator);
+
+ return (ok);
+}
+
+/*
+ * 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
+ * if they are in use.
+ */
+static void
+zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
+ dns_dbnode_t *node = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_rdata_dnskey_t dnskey;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+ isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
+ const char *algorithm;
+
+ result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_db_currentversion(db, &version);
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
+ dns_rdatatype_none, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ 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, &dnskey, NULL);
+ INSIST(result == ISC_R_SUCCESS);
+
+ if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
+ dnskey.algorithm == DST_ALG_RSAMD5) &&
+ dnskey.datalen > 1 && dnskey.data[0] == 1 &&
+ dnskey.data[1] == 3)
+ {
+ if (dnskey.algorithm == DST_ALG_RSASHA1) {
+ logit = !foundrsa;
+ foundrsa = ISC_TRUE;
+ algorithm = "RSASHA1";
+ } else {
+ logit = !foundmd5;
+ foundmd5 = ISC_TRUE;
+ algorithm = "RSAMD5";
+ }
+ if (logit)
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "weak %s (%u) key found "
+ "(exponent=3)", algorithm,
+ dnskey.algorithm);
+ if (foundrsa && foundmd5)
+ break;
+ }
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ cleanup:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (version != NULL)
+ dns_db_closeversion(db, &version, ISC_FALSE);
+
+}
+
+static void
+resume_signingwithkey(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;
+
+ result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_db_currentversion(zone->db, &version);
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(zone->db, node, version,
+ zone->privatetype,
+ dns_rdatatype_none, 0,
+ &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ 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) {
+ dns_rdata_reset(&rdata);
+ continue;
+ }
+
+ result = zone_signwithkey(zone, rdata.data[0],
+ (rdata.data[1] << 8) | rdata.data[2], ISC_TF(rdata.data[3]));
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_signwithkey failed: %s",
+ dns_result_totext(result));
+ }
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ cleanup:
+ if (node != NULL)
+ dns_db_detachnode(zone->db, &node);
+ if (version != NULL)
+ dns_db_closeversion(zone->db, &version, ISC_FALSE);
+
+}
+
+static isc_result_t
+zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
+ dns_nsec3chain_t *nsec3chain, *current;
+ isc_result_t result;
+ isc_time_t now;
+ unsigned int options = 0;
+
+ nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
+ if (nsec3chain == NULL)
+ return (ISC_R_NOMEMORY);
+
+ nsec3chain->magic = 0;
+ nsec3chain->done = ISC_FALSE;
+ nsec3chain->db = NULL;
+ nsec3chain->dbiterator = NULL;
+ nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
+ nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
+ nsec3chain->nsec3param.hash = nsec3param->hash;
+ nsec3chain->nsec3param.iterations = nsec3param->iterations;
+ nsec3chain->nsec3param.flags = nsec3param->flags;
+ nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
+ memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
+ nsec3chain->nsec3param.salt = nsec3chain->salt;
+ nsec3chain->seen_nsec = ISC_FALSE;
+ nsec3chain->delete_nsec = ISC_FALSE;
+ nsec3chain->save_delete_nsec = ISC_FALSE;
+
+ for (current = ISC_LIST_HEAD(zone->nsec3chain);
+ current != NULL;
+ current = ISC_LIST_NEXT(current, link)) {
+ if (current->db == zone->db &&
+ current->nsec3param.hash == nsec3param->hash &&
+ current->nsec3param.iterations == nsec3param->iterations &&
+ current->nsec3param.salt_length == nsec3param->salt_length
+ && !memcmp(current->nsec3param.salt, nsec3param->salt,
+ nsec3param->salt_length))
+ current->done = ISC_TRUE;
+ }
+
+ if (zone->db != NULL) {
+ dns_db_attach(zone->db, &nsec3chain->db);
+ if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
+ options = DNS_DB_NONSEC3;
+ result = dns_db_createiterator(nsec3chain->db, options,
+ &nsec3chain->dbiterator);
+ if (result == ISC_R_SUCCESS)
+ dns_dbiterator_first(nsec3chain->dbiterator);
+ if (result == ISC_R_SUCCESS) {
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ ISC_LIST_INITANDAPPEND(zone->nsec3chain,
+ nsec3chain, link);
+ nsec3chain = NULL;
+ if (isc_time_isepoch(&zone->nsec3chaintime)) {
+ TIME_NOW(&now);
+ zone->nsec3chaintime = now;
+ if (zone->task != NULL)
+ zone_settimer(zone, &now);
+ }
+ }
+ } else
+ result = ISC_R_NOTFOUND;
+
+ if (nsec3chain != NULL) {
+ if (nsec3chain->db != NULL)
+ dns_db_detach(&nsec3chain->db);
+ if (nsec3chain->dbiterator != NULL)
+ dns_dbiterator_destroy(&nsec3chain->dbiterator);
+ isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
+ }
+ return (result);
+}
+
+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;
+
+ result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ 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)
+ goto cleanup;
+
+ 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, &nsec3param, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 ||
+ (nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
+ 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));
+ }
+ }
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ cleanup:
+ if (node != NULL)
+ dns_db_detachnode(zone->db, &node);
+ if (version != NULL)
+ dns_db_closeversion(zone->db, &version, ISC_FALSE);
+}
+
+static void
+set_resigntime(dns_zone_t *zone) {
+ dns_rdataset_t rdataset;
+ dns_fixedname_t fixed;
+ char namebuf[DNS_NAME_FORMATSIZE];
+ unsigned int resign;
+ isc_result_t result;
+ isc_uint32_t nanosecs;
+
+ dns_rdataset_init(&rdataset);
+ dns_fixedname_init(&fixed);
+ result = dns_db_getsigningtime(zone->db, &rdataset,
+ dns_fixedname_name(&fixed));
+ if (result != ISC_R_SUCCESS) {
+ isc_time_settoepoch(&zone->resigntime);
+ return;
+ }
+ resign = rdataset.resign;
+ dns_name_format(dns_fixedname_name(&fixed), namebuf, sizeof(namebuf));
+ dns_rdataset_disassociate(&rdataset);
+ isc_random_get(&nanosecs);
+ nanosecs %= 1000000000;
+ isc_time_set(&zone->resigntime, resign, nanosecs);
+}
+
+static isc_result_t
+check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_dbversion_t *version = NULL;
+ dns_rdata_nsec3param_t nsec3param;
+ isc_boolean_t ok = ISC_FALSE;
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
+ zone_isdynamic(zone) : ISC_FALSE;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "nsec3param lookup failure: %s",
+ dns_result_totext(result));
+ return (result);
+ }
+ dns_db_currentversion(db, &version);
+
+ result = dns_db_findrdataset(db, node, version,
+ dns_rdatatype_nsec3param,
+ dns_rdatatype_none, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "nsec3param lookup failure: %s",
+ dns_result_totext(result));
+ goto cleanup;
+ }
+
+ /*
+ * For dynamic zones we must support every algorithm so we can
+ * regenerate all the NSEC3 chains.
+ * For non-dynamic zones we only need to find a supported algorithm.
+ */
+ 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, &nsec3param, NULL);
+ dns_rdata_reset(&rdata);
+ INSIST(result == ISC_R_SUCCESS);
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
+ nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
+ {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "nsec3 test \"unknown\" hash algorithm found: %u",
+ nsec3param.hash);
+ ok = ISC_TRUE;
+ } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
+ if (dynamic) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "unsupported nsec3 hash algorithm"
+ " in dynamic zone: %u",
+ nsec3param.hash);
+ result = DNS_R_BADZONE;
+ /* Stop second error message. */
+ ok = ISC_TRUE;
+ break;
+ } else
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "unsupported nsec3 hash algorithm: %u",
+ nsec3param.hash);
+ } else
+ ok = ISC_TRUE;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ if (!ok) {
+ result = DNS_R_BADZONE;
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "no supported nsec3 hash algorithm");
+ }
+
+ cleanup:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+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, 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;
+
+ TIME_NOW(&now);
+
+ /*
+ * 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;
+ }
+
+ dns_zone_log(zone, ISC_LOG_DEBUG(2),
+ "number of nodes in database: %u",
+ dns_db_nodecount(db));
+
+ if (result == DNS_R_SEENINCLUDE)
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
+ else
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
+
+ /*
+ * 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_rollforward(zone->mctx, db, options,
+ 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;
+ }
+
+ zone->loadtime = loadtime;
+
+ 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");
+ }
+
+ /*
+ * Master / Slave / Stub zones require both NS and SOA records at
+ * the top of the zone.
+ */
+
+ 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.
+ */
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
+ !isc_serial_gt(serial, zone->serial)) {
+ isc_uint32_t serialmin, serialmax;
+
+ INSIST(zone->type == dns_zone_master);
+
+ serialmin = (zone->serial + 1) & 0xffffffffU;
+ serialmax = (zone->serial + 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, zone->serial))
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone serial has gone backwards");
+ else if (serial == zone->serial && !hasinclude)
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone serial unchanged. "
+ "zone may fail to transfer "
+ "to slaves.");
+ }
+
+ 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.");
+ }
+
+ zone->serial = serial;
+ 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);
+
+ if (zone->type == dns_zone_slave ||
+ zone->type == dns_zone_stub) {
+ isc_time_t t;
+ isc_uint32_t delay;
+
+ 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);
+
+ 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 for weak DNSKEY's.
+ */
+ if (zone->type == dns_zone_master)
+ zone_check_dnskeys(zone, db);
+
+#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
+
+ 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);
+ }
+
+ if (! dns_db_ispersistent(db))
+ dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s",
+ zone->serial,
+ dns_db_issecure(db) ? " (signed)" : "");
+
+ return (result);
+
+ 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");
+
+ /* Mark the zone for immediate refresh. */
+ zone->refreshtime = now;
+ if (zone->task != NULL)
+ zone_settimer(zone, &now);
+ result = ISC_R_SUCCESS;
+ }
+ return (result);
+}
+
+static isc_boolean_t
+exit_check(dns_zone_t *zone) {
+
+ REQUIRE(LOCKED_ZONE(zone));
+
+ 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_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;
+
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
+ return (ISC_TRUE);
+
+ 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, NULL, 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, NULL, dns_rdatatype_aaaa,
+ 0, 0, NULL, foundname, NULL, NULL);
+ if (result == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+ }
+
+ 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);
+ }
+
+ 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 (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)
+{
+ 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;
+
+ 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);
+ }
+ 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);
+
+ return (result);
+}
+
+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)
+{
+ 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;
+ }
+ if (result != ISC_R_SUCCESS)
+ goto invalidate_rdataset;
+
+ 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);
+ }
+
+ result = dns_rdataset_next(&rdataset);
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&rdataset);
+
+ if (soacount != NULL)
+ *soacount = count;
+
+ 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;
+ }
+
+ result = ISC_R_SUCCESS;
+
+ invalidate_rdataset:
+ dns_rdataset_invalidate(&rdataset);
+
+ return (result);
+}
+
+/*
+ * zone must be locked.
+ */
+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;
+ isc_result_t result;
+ isc_result_t answer = ISC_R_SUCCESS;
+ dns_dbnode_t *node;
+
+ REQUIRE(db != NULL);
+ REQUIRE(zone != NULL);
+
+ version = NULL;
+ 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 (nscount != NULL || errors != NULL) {
+ result = zone_count_ns_rr(zone, db, node, version,
+ nscount, errors);
+ if (result != ISC_R_SUCCESS)
+ answer = 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);
+}
+
+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);
+}
+
+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 countain 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);
+}
+
+/*
+ * 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
+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;
+
+ /*
+ * 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);
+ if (result != ISC_R_SUCCESS) {
+ dns_difftuple_free(tuple);
+ return (result);
+ }
+
+ /*
+ * 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;
+
+ CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
+ CHECK(dns_difftuple_copy(deltuple, &addtuple));
+ addtuple->op = DNS_DIFFOP_ADD;
+
+ serial = dns_soa_getserial(&addtuple->rdata);
+
+ /* 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;
+
+ failure:
+ if (addtuple != NULL)
+ dns_difftuple_free(&addtuple);
+ if (deltuple != NULL)
+ dns_difftuple_free(&deltuple);
+ return (result);
+}
+
+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)
+{
+ 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));
+}
+
+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);
+}
+
+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);
+ result = update_one_rr(db, ver, diff, DNS_DIFFOP_DELRESIGN,
+ name, ttl, rdata);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ rdata->flags |= DNS_RDATA_OFFLINE;
+ result = update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
+ name, ttl, rdata);
+ return (result);
+}
+
+static void
+set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
+{
+ unsigned int delta;
+
+ zone->key_expiry = when;
+ if (when <= now) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "DNSKEY RRSIG(s) have expired");
+ isc_time_settoepoch(&zone->keywarntime);
+ } else if (when < now + 7 * 24 * 3600) {
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "DNSKEY RRSIG(s) will expire at %u",
+ when); /* XXXMPA convert to date. */
+ delta = when - now;
+ delta--; /* loop prevention */
+ delta /= 24 * 3600; /* to whole days */
+ delta *= 24 * 3600; /* to seconds */
+ isc_time_set(&zone->keywarntime, when - delta, 0);
+ } else {
+ dns_zone_log(zone, ISC_LOG_NOTICE, /* XXMPA ISC_LOG_DEBUG(1) */
+ "setting keywarntime to %u - 7 days",
+ when); /* XXXMPA convert to date. */
+ isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
+ }
+}
+
+/*
+ * Delete expired RRsigs and any RRsigs we are about to re-sign.
+ * See also update.c:del_keysigs().
+ */
+static isc_result_t
+del_sigs(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 now)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int i;
+ dns_rdata_rrsig_t rrsig;
+ isc_boolean_t found;
+ isc_stdtime_t warn = 0, maybe = 0;
+
+ dns_rdataset_init(&rdataset);
+
+ if (type == dns_rdatatype_nsec3)
+ result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
+ else
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
+ (isc_stdtime_t) 0, &rdataset, NULL);
+ dns_db_detachnode(db, &node);
+
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_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);
+ result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (type != dns_rdatatype_dnskey) {
+ result = update_one_rr(db, ver, diff,
+ DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS)
+ break;
+ continue;
+ }
+
+ /*
+ * RRSIG(DNSKEY) requires special processing.
+ */
+ found = ISC_FALSE;
+ for (i = 0; i < nkeys; i++) {
+ if (rrsig.algorithm == dst_key_alg(keys[i]) &&
+ rrsig.keyid == dst_key_id(keys[i])) {
+ found = ISC_TRUE;
+ /*
+ * Mark offline RRSIG(DNSKEY).
+ * We want the earliest offline expire time
+ * iff there is a new offline signature.
+ */
+ if (!dst_key_isprivate(keys[i])) {
+ if (warn != 0 &&
+ warn > rrsig.timeexpire)
+ warn = rrsig.timeexpire;
+ if (rdata.flags & DNS_RDATA_OFFLINE) {
+ if (maybe == 0 ||
+ maybe > rrsig.timeexpire)
+ maybe =
+ rrsig.timeexpire;
+ break;
+ }
+ if (warn == 0)
+ warn = maybe;
+ if (warn == 0 ||
+ warn > rrsig.timeexpire)
+ warn = rrsig.timeexpire;
+ result = offline(db, ver, diff, name,
+ rdataset.ttl, &rdata);
+ break;
+ }
+ result = update_one_rr(db, ver, diff,
+ DNS_DIFFOP_DEL,
+ name, rdataset.ttl,
+ &rdata);
+ break;
+ }
+ }
+ /*
+ * If there is not a matching DNSKEY then
+ * delete the RRSIG.
+ */
+ if (!found)
+ result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
+ name, rdataset.ttl, &rdata);
+ dns_rdata_reset(&rdata);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ if (warn != 0)
+ set_key_expiry_warning(zone, warn, now);
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+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_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t sig_rdata = DNS_RDATA_INIT;
+ unsigned char data[1024]; /* XXX */
+ isc_buffer_t buffer;
+ unsigned int i;
+
+ dns_rdataset_init(&rdataset);
+ isc_buffer_init(&buffer, data, sizeof(data));
+
+ if (type == dns_rdatatype_nsec3)
+ result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
+ else
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_NOTFOUND)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+ 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)
+ return (ISC_R_SUCCESS);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ for (i = 0; i < nkeys; i++) {
+ if (check_ksk && type != dns_rdatatype_dnskey &&
+ (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0)
+ continue;
+ if (!dst_key_isprivate(keys[i]))
+ continue;
+ /* Calculate the signature, creating a RRSIG RDATA. */
+ CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
+ &inception, &expire,
+ mctx, &buffer, &sig_rdata));
+ /* Update the database and journal with the RRSIG. */
+ /* XXX inefficient - will cause dataset merging */
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
+ name, rdataset.ttl, &sig_rdata));
+ dns_rdata_reset(&sig_rdata);
+ }
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+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;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ dns_rdataset_t rdataset;
+ dns_rdatatype_t covers;
+ dst_key_t *zone_keys[MAXZONEKEYS];
+ isc_boolean_t check_ksk;
+ isc_result_t result;
+ isc_stdtime_t now, inception, soaexpire, expire, stop;
+ isc_uint32_t jitter;
+ unsigned int i;
+ unsigned int nkeys = 0;
+ unsigned int resign;
+
+ dns_rdataset_init(&rdataset);
+ dns_fixedname_init(&fixed);
+ dns_diff_init(zone->mctx, &sig_diff);
+ sig_diff.resign = zone->sigresigninginterval;
+
+ /*
+ * Updates are disabled. Pause for 5 minutes.
+ */
+ if (zone->update_disabled) {
+ result = ISC_R_FAILURE;
+ goto failure;
+ }
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ result = dns_db_newversion(db, &version);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:dns_db_newversion -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = find_zone_keys(zone, db, version, zone->mctx, MAXZONEKEYS,
+ zone_keys, &nkeys);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:find_zone_keys -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ isc_stdtime_get(&now);
+ inception = now - 3600; /* Allow for clock skew. */
+ soaexpire = now + dns_zone_getsigvalidityinterval(zone);
+ /*
+ * Spread out signatures over time if they happen to be
+ * clumped. We don't do this for each add_sigs() call as
+ * we still want some clustering to occur.
+ */
+ isc_random_get(&jitter);
+ 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);
+
+ name = dns_fixedname_name(&fixed);
+ result = dns_db_getsigningtime(db, &rdataset, name);
+ if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:dns_db_getsigningtime -> %s\n",
+ dns_result_totext(result));
+ }
+
+ i = 0;
+ while (result == ISC_R_SUCCESS) {
+ resign = rdataset.resign;
+ covers = rdataset.covers;
+ /*
+ * Stop if we hit the SOA as that means we have walked the
+ * entire zone. The SOA record should always be the most
+ * recent signature.
+ */
+ /* XXXMPA increase number of RRsets signed pre call */
+ if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
+ resign > stop) {
+ /*
+ * Ensure that we don't loop resigning the SOA.
+ */
+ if (covers == dns_rdatatype_soa)
+ dns_db_resigned(db, &rdataset, version);
+ dns_rdataset_disassociate(&rdataset);
+ break;
+ }
+
+ dns_db_resigned(db, &rdataset, version);
+ dns_rdataset_disassociate(&rdataset);
+
+ result = del_sigs(zone, db, version, name, covers, &sig_diff,
+ zone_keys, nkeys, now);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:del_sigs -> %s\n",
+ dns_result_totext(result));
+ break;
+ }
+ result = add_sigs(db, version, name, covers, &sig_diff,
+ zone_keys, nkeys, zone->mctx, inception,
+ expire, check_ksk);
+ 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,
+ dns_fixedname_name(&fixed));
+ if (nkeys == 0 && result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ break;
+ }
+ if (result != ISC_R_SUCCESS)
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc:dns_db_getsigningtime -> %s\n",
+ dns_result_totext(result));
+ }
+
+ if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
+ goto failure;
+
+ 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_resigninc: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_resigninc: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);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_resigninc: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_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;
+ }
+ }
+
+ /*
+ * Everything has succeeded. Commit the changes.
+ */
+ dns_db_closeversion(db, &version, ISC_TRUE);
+
+ failure:
+ dns_diff_clear(&sig_diff);
+ for (i = 0; i < nkeys; i++)
+ dst_key_free(&zone_keys[i]);
+ if (version != NULL) {
+ dns_db_closeversion(zone->db, &version, ISC_FALSE);
+ dns_db_detach(&db);
+ } else if (db != NULL)
+ dns_db_detach(&db);
+ if (result == ISC_R_SUCCESS) {
+ set_resigntime(zone);
+ LOCK_ZONE(zone);
+ zone_needdump(zone, DNS_DUMP_DELAY);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
+ UNLOCK_ZONE(zone);
+ } else {
+ /*
+ * Something failed. Retry in 5 minutes.
+ */
+ isc_interval_t ival;
+ isc_interval_set(&ival, 300, 0);
+ isc_time_nowplusinterval(&zone->resigntime, &ival);
+ }
+}
+
+static isc_result_t
+next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
+ dns_name_t *newname, isc_boolean_t bottom)
+{
+ isc_result_t result;
+ dns_dbiterator_t *dbit = NULL;
+ dns_rdatasetiter_t *rdsit = NULL;
+ dns_dbnode_t *node = NULL;
+
+ CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
+ CHECK(dns_dbiterator_seek(dbit, oldname));
+ do {
+ result = dns_dbiterator_next(dbit);
+ if (result == ISC_R_NOMORE)
+ CHECK(dns_dbiterator_first(dbit));
+ CHECK(dns_dbiterator_current(dbit, &node, newname));
+ if (bottom && dns_name_issubdomain(newname, oldname) &&
+ !dns_name_equal(newname, oldname)) {
+ dns_db_detachnode(db, &node);
+ continue;
+ }
+ /*
+ * Is this node empty?
+ */
+ CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
+ result = dns_rdatasetiter_first(rdsit);
+ dns_db_detachnode(db, &node);
+ dns_rdatasetiter_destroy(&rdsit);
+ if (result != ISC_R_NOMORE)
+ break;
+ } while (1);
+ failure:
+ if (node != NULL)
+ dns_db_detachnode(db, &node);
+ if (dbit != NULL)
+ dns_dbiterator_destroy(&dbit);
+ 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)
+{
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_rrsig_t rrsig;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
+ type, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+ 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);
+ INSIST(result == ISC_R_SUCCESS);
+ if (rrsig.algorithm == dst_key_alg(key) &&
+ rrsig.keyid == dst_key_id(key)) {
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_TRUE);
+ }
+ dns_rdata_reset(&rdata);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
+ dns_diff_t *diff)
+{
+ dns_fixedname_t fixed;
+ dns_name_t *next;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_result_t result;
+ unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
+
+ dns_fixedname_init(&fixed);
+ next = dns_fixedname_name(&fixed);
+
+ 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, &region);
+ dns_name_fromregion(next, &region);
+ isc_region_consume(&region, 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:
+ return (result);
+}
+
+static isc_result_t
+sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
+ dns_dbversion_t *version, isc_boolean_t build_nsec3,
+ 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_result_t result;
+ dns_rdatasetiter_t *iterator = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t buffer;
+ unsigned char data[1024];
+ isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
+ seen_nsec3, seen_ds;
+ isc_boolean_t bottom;
+
+ result = dns_db_allrdatasets(db, node, version, 0, &iterator);
+ if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_NOTFOUND)
+ 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 =
+ seen_nsec3 = seen_ds = ISC_FALSE;
+ 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_soa)
+ seen_soa = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_ns)
+ seen_ns = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_ds)
+ seen_ds = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_dname)
+ seen_dname = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_nsec)
+ seen_nsec = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_nsec3)
+ seen_nsec3 = ISC_TRUE;
+ seen_rr = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ if (seen_ns && !seen_soa)
+ *delegation = ISC_TRUE;
+ /*
+ * Going from insecure to NSEC3.
+ * Don't generate NSEC3 records for NSEC3 records.
+ */
+ if (build_nsec3 && !seen_nsec3 && seen_rr) {
+ isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
+ CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
+ unsecure, diff));
+ (*signatures)--;
+ }
+ /*
+ * Going from insecure to NSEC.
+ * Don't generate NSEC records for NSEC3 records.
+ */
+ 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)--;
+ }
+ result = dns_rdatasetiter_first(iterator);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(iterator, &rdataset);
+ if (rdataset.type == dns_rdatatype_soa ||
+ rdataset.type == dns_rdatatype_rrsig)
+ goto next_rdataset;
+ if (is_ksk && rdataset.type != dns_rdatatype_dnskey)
+ goto next_rdataset;
+ if (*delegation && !dns_rdatatype_atparent(rdataset.type))
+ goto next_rdataset;
+ if (signed_with_key(db, node, version, rdataset.type, key))
+ goto next_rdataset;
+ /* Calculate the signature, creating a RRSIG RDATA. */
+ CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
+ &expire, mctx, &buffer, &rdata));
+ /* Update the database and journal with the RRSIG. */
+ /* XXX inefficient - will cause dataset merging */
+ CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
+ name, rdataset.ttl, &rdata));
+ dns_rdata_reset(&rdata);
+ (*signatures)--;
+ next_rdataset:
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(iterator);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ if (seen_dname)
+ *delegation = ISC_TRUE;
+failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (iterator != NULL)
+ dns_rdatasetiter_destroy(&iterator);
+ return (result);
+}
+
+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)
+{
+ 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;
+
+ 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)
+{
+ isc_result_t result;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned char data[5];
+ isc_boolean_t seen_done = 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);
+ if (result == ISC_R_NOTFOUND) {
+ result = ISC_R_SUCCESS;
+ goto failure;
+ }
+ 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);
+ if (rdata.length != 5 ||
+ rdata.data[0] != signing->algorithm ||
+ rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
+ rdata.data[2] != (signing->keyid & 0xff)) {
+ dns_rdata_reset(&rdata);
+ continue;
+ }
+ if (!signing->delete && rdata.data[4] != 0)
+ seen_done = ISC_TRUE;
+ else
+ CHECK(update_one_rr(signing->db, version, diff,
+ DNS_DIFFOP_DEL, name, rdataset.ttl, &rdata));
+ dns_rdata_reset(&rdata);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ if (!signing->delete && !seen_done) {
+
+ data[0] = signing->algorithm;
+ data[1] = (signing->keyid >> 8) & 0xff;
+ data[2] = signing->keyid & 0xff;
+ data[3] = 0;
+ data[4] = 1;
+ rdata.length = sizeof(data);
+ rdata.data = data;
+ rdata.type = privatetype;
+ rdata.rdclass = dns_db_class(signing->db);
+ CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
+ name, rdataset.ttl, &rdata));
+ }
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(signing->db, &node);
+ return (result);
+}
+
+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)
+{
+ dns_dbnode_t *node = NULL;
+ dns_name_t *name = dns_db_origin(db);
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t rdataset;
+ dns_rdata_nsec3param_t nsec3param;
+ isc_result_t result;
+ isc_buffer_t buffer;
+ unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
+ dns_ttl_t ttl = 0;
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_getoriginnode(db, &node);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ goto add;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ /*
+ * Preserve the existing ttl.
+ */
+ ttl = rdataset.ttl;
+
+ /*
+ * Delete all NSEC3PARAM records which match that in nsec3chain.
+ */
+ for (result = dns_rdataset_first(&rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&rdataset)) {
+
+ dns_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
+
+ if (nsec3param.hash != chain->nsec3param.hash ||
+ (active && nsec3param.flags != 0) ||
+ 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, &rdata));
+ dns_rdata_reset(&rdata);
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+
+ add:
+ if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
+ result = ISC_R_SUCCESS;
+ goto failure;
+ }
+
+ /*
+ * Add a NSEC3PARAM record which matches that in nsec3chain but
+ * with all flags bits cleared.
+ *
+ * Note: we do not clear chain->nsec3param.flags as this change
+ * may be reversed.
+ */
+ isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
+ CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
+ dns_rdatatype_nsec3param,
+ &chain->nsec3param, &buffer));
+ rdata.data[1] = 0; /* Clear flag bits. */
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
+
+ failure:
+ dns_db_detachnode(db, &node);
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+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)
+{
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ 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_rdataset_current(&rdataset, &rdata);
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata));
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ failure:
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+static isc_result_t
+deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
+ dns_name_t *name, const dns_rdata_nsec3param_t *param,
+ dns_diff_t *diff)
+{
+ dns_rdataset_t rdataset;
+ dns_rdata_nsec3_t nsec3;
+ isc_result_t result;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
+ 0, 0, &rdataset, NULL);
+ if (result == ISC_R_NOTFOUND)
+ 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_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
+ if (nsec3.hash != param->hash ||
+ nsec3.iterations != param->iterations ||
+ nsec3.salt_length != param->salt_length ||
+ memcmp(nsec3.salt, param->salt, nsec3.salt_length))
+ continue;
+ CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata));
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ failure:
+ dns_rdataset_disassociate(&rdataset);
+ return (result);
+}
+
+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)
+{
+ dns_dbnode_t *node = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec3param_t myparam;
+ dns_rdataset_t rdataset;
+ isc_result_t result;
+
+ *answer = ISC_FALSE;
+
+ result = dns_db_getoriginnode(db, &node);
+ 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;
+ }
+ 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) {
+ *answer = ISC_TRUE;
+ dns_db_detachnode(db, &node);
+ return (ISC_R_SUCCESS);
+ }
+ 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_rdataset_current(&rdataset, &rdata);
+ CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
+ dns_rdata_reset(&rdata);
+ /*
+ * Ignore any NSEC3PARAM removals.
+ */
+ if (NSEC3REMOVE(myparam.flags))
+ continue;
+ /*
+ * Ignore the chain that we are in the process of deleting.
+ */
+ if (myparam.hash == param->hash &&
+ myparam.iterations == param->iterations &&
+ myparam.salt_length == param->salt_length &&
+ !memcmp(myparam.salt, param->salt, myparam.salt_length))
+ continue;
+ /*
+ * Found an active NSEC3 chain.
+ */
+ break;
+ }
+ if (result == ISC_R_NOMORE) {
+ *answer = ISC_TRUE;
+ result = ISC_R_SUCCESS;
+ }
+
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ dns_db_detachnode(db, &node);
+ return (result);
+}
+
+/*
+ * 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;
+ dns_diff_t sig_diff;
+ dns_diff_t nsec_diff;
+ dns_diff_t nsec3_diff;
+ dns_diff_t param_diff;
+ dns_fixedname_t fixed;
+ dns_fixedname_t nextfixed;
+ dns_name_t *name, *nextname;
+ dns_rdataset_t rdataset;
+ dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
+ dns_nsec3chainlist_t cleanup;
+ dst_key_t *zone_keys[MAXZONEKEYS];
+ isc_int32_t signatures;
+ isc_boolean_t check_ksk, is_ksk;
+ isc_boolean_t delegation;
+ 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 nkeys = 0;
+ isc_uint32_t nodes;
+ isc_boolean_t unsecure = ISC_FALSE;
+ 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_rdataset_init(&rdataset);
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ dns_fixedname_init(&nextfixed);
+ nextname = dns_fixedname_name(&nextfixed);
+ dns_diff_init(zone->mctx, &param_diff);
+ dns_diff_init(zone->mctx, &nsec3_diff);
+ dns_diff_init(zone->mctx, &nsec_diff);
+ dns_diff_init(zone->mctx, &sig_diff);
+ sig_diff.resign = zone->sigresigninginterval;
+ ISC_LIST_INIT(cleanup);
+
+ /*
+ * Updates are disabled. Pause for 5 minutes.
+ */
+ if (zone->update_disabled) {
+ result = ISC_R_FAILURE;
+ goto failure;
+ }
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ result = dns_db_newversion(db, &version);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:dns_db_newversion -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = find_zone_keys(zone, db, version, zone->mctx,
+ MAXZONEKEYS, zone_keys, &nkeys);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:find_zone_keys -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ isc_stdtime_get(&now);
+ inception = now - 3600; /* Allow for clock skew. */
+ soaexpire = now + dns_zone_getsigvalidityinterval(zone);
+
+ /*
+ * Spread out signatures over time if they happen to be
+ * clumped. We don't do this for each add_sigs() call as
+ * we still want some clustering to occur.
+ */
+ isc_random_get(&jitter);
+ 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 interator in turn until
+ * we have no more nodes to pull off or we reach the limits
+ * for this quantum.
+ */
+ nodes = zone->nodes;
+ signatures = zone->signatures;
+ LOCK_ZONE(zone);
+ nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
+ UNLOCK_ZONE(zone);
+ first = ISC_TRUE;
+
+ if (nsec3chain != NULL)
+ nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
+ /*
+ * Generate new NSEC3 chains first.
+ */
+ while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
+ LOCK_ZONE(zone);
+ nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (nsec3chain->done || nsec3chain->db != zone->db) {
+ ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
+ ISC_LIST_APPEND(cleanup, nsec3chain, link);
+ }
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ UNLOCK_ZONE(zone);
+ if (ISC_LIST_TAIL(cleanup) == nsec3chain)
+ goto next_addchain;
+
+ /*
+ * Possible future db.
+ */
+ if (nsec3chain->db != db) {
+ goto next_addchain;
+ }
+
+ if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
+ goto next_addchain;
+
+ is_ksk = ISC_FALSE;
+ delegation = ISC_FALSE;
+ dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
+
+ if (nsec3chain->delete_nsec) {
+ delegation = ISC_FALSE;
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ CHECK(delete_nsec(db, version, node, name, &nsec_diff));
+ goto next_addnode;
+ }
+ /*
+ * On the first pass we need to check if the current node
+ * has not been obscured.
+ */
+ delegation = ISC_FALSE;
+ unsecure = ISC_FALSE;
+ if (first) {
+ dns_fixedname_t ffound;
+ dns_name_t *found;
+ dns_fixedname_init(&ffound);
+ found = dns_fixedname_name(&ffound);
+ result = dns_db_find(db, name, version,
+ dns_rdatatype_soa,
+ DNS_DBFIND_NOWILD, 0, NULL, found,
+ NULL, NULL);
+ if ((result == DNS_R_DELEGATION ||
+ result == DNS_R_DNAME) &&
+ !dns_name_equal(name, found)) {
+ /*
+ * Remember the obscuring name so that
+ * we skip all obscured names.
+ */
+ dns_name_copy(found, name, NULL);
+ delegation = ISC_TRUE;
+ goto next_addnode;
+ }
+ }
+
+ /*
+ * Check to see if this is a bottom of zone node.
+ */
+ result = dns_db_allrdatasets(db, node, version, 0, &iterator);
+ if (result == ISC_R_NOTFOUND) /* Empty node? */
+ goto next_addnode;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
+ ISC_FALSE;
+ for (result = dns_rdatasetiter_first(iterator);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iterator)) {
+ dns_rdatasetiter_current(iterator, &rdataset);
+ INSIST(rdataset.type != dns_rdatatype_nsec3);
+ if (rdataset.type == dns_rdatatype_soa)
+ seen_soa = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_ns)
+ seen_ns = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_dname)
+ seen_dname = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_ds)
+ seen_ds = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_nsec)
+ seen_nsec = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ }
+ dns_rdatasetiter_destroy(&iterator);
+ /*
+ * Is there a NSEC chain than needs to be cleaned up?
+ */
+ if (seen_nsec)
+ nsec3chain->seen_nsec = ISC_TRUE;
+ if (seen_ns && !seen_soa && !seen_ds)
+ unsecure = ISC_TRUE;
+ if ((seen_ns && !seen_soa) || seen_dname)
+ delegation = ISC_TRUE;
+
+ /*
+ * Process one node.
+ */
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ CHECK(dns_nsec3_addnsec3(db, version, name,
+ &nsec3chain->nsec3param,
+ zone->minimum, unsecure, &nsec3_diff));
+ /*
+ * Treat each call to dns_nsec3_addnsec3() as if it's cost is
+ * two signatures. Additionally there will, in general, be
+ * two signature generated below.
+ *
+ * If we are only changing the optout flag the cost is half
+ * that of the cost of generating a completely new chain.
+ */
+ signatures -= 4;
+
+ /*
+ * Go onto next node.
+ */
+ next_addnode:
+ first = ISC_FALSE;
+ dns_db_detachnode(db, &node);
+ do {
+ result = dns_dbiterator_next(nsec3chain->dbiterator);
+
+ if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
+ CHECK(fixup_nsec3param(db, version, nsec3chain,
+ ISC_FALSE, &param_diff));
+ LOCK_ZONE(zone);
+ ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
+ link);
+ UNLOCK_ZONE(zone);
+ ISC_LIST_APPEND(cleanup, nsec3chain, link);
+ goto next_addchain;
+ }
+ if (result == ISC_R_NOMORE) {
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ if (nsec3chain->seen_nsec) {
+ CHECK(fixup_nsec3param(db, version,
+ nsec3chain,
+ ISC_TRUE,
+ &param_diff));
+ nsec3chain->delete_nsec = ISC_TRUE;
+ goto same_addchain;
+ }
+ CHECK(fixup_nsec3param(db, version, nsec3chain,
+ ISC_FALSE, &param_diff));
+ LOCK_ZONE(zone);
+ ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
+ link);
+ UNLOCK_ZONE(zone);
+ ISC_LIST_APPEND(cleanup, nsec3chain, link);
+ goto next_addchain;
+ } else if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:"
+ "dns_dbiterator_next -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ } else if (delegation) {
+ dns_dbiterator_current(nsec3chain->dbiterator,
+ &node, nextname);
+ dns_db_detachnode(db, &node);
+ if (!dns_name_issubdomain(nextname, name))
+ break;
+ } else
+ break;
+ } while (1);
+ continue;
+
+ same_addchain:
+ CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
+ first = ISC_TRUE;
+ continue;
+
+ next_addchain:
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ nsec3chain = nextnsec3chain;
+ first = ISC_TRUE;
+ if (nsec3chain != NULL)
+ nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
+ }
+
+ /*
+ * Process removals.
+ */
+ LOCK_ZONE(zone);
+ nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
+ UNLOCK_ZONE(zone);
+ first = ISC_TRUE;
+ buildnsecchain = ISC_FALSE;
+ while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
+ LOCK_ZONE(zone);
+ nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
+ UNLOCK_ZONE(zone);
+
+ if (nsec3chain->db != db)
+ goto next_removechain;
+
+ if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
+ goto next_removechain;
+
+ /*
+ * Work out if we need to build a NSEC chain as a consequence
+ * 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));
+
+ dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
+ delegation = ISC_FALSE;
+
+ if (!buildnsecchain) {
+ /*
+ * Delete the NSECPARAM record that matches this chain.
+ */
+ if (first)
+ CHECK(fixup_nsec3param(db, version, nsec3chain,
+ ISC_TRUE, &param_diff));
+
+ /*
+ * Delete the NSEC3 records.
+ */
+ CHECK(deletematchingnsec3(db, version, node, name,
+ &nsec3chain->nsec3param,
+ &nsec3_diff));
+ goto next_removenode;
+ }
+
+ if (first) {
+ dns_fixedname_t ffound;
+ dns_name_t *found;
+ dns_fixedname_init(&ffound);
+ found = dns_fixedname_name(&ffound);
+ result = dns_db_find(db, name, version,
+ dns_rdatatype_soa,
+ DNS_DBFIND_NOWILD, 0, NULL, found,
+ NULL, NULL);
+ if ((result == DNS_R_DELEGATION ||
+ result == DNS_R_DNAME) &&
+ !dns_name_equal(name, found)) {
+ /*
+ * Remember the obscuring name so that
+ * we skip all obscured names.
+ */
+ dns_name_copy(found, name, NULL);
+ delegation = ISC_TRUE;
+ goto next_removenode;
+ }
+ }
+
+ /*
+ * Check to see if this is a bottom of zone node.
+ */
+ result = dns_db_allrdatasets(db, node, version, 0, &iterator);
+ if (result == ISC_R_NOTFOUND) /* Empty node? */
+ goto next_removenode;
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
+ seen_rr = ISC_FALSE;
+ 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_soa)
+ seen_soa = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_ns)
+ seen_ns = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_dname)
+ seen_dname = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_nsec)
+ seen_nsec = ISC_TRUE;
+ else if (rdataset.type == dns_rdatatype_nsec3)
+ seen_nsec3 = ISC_TRUE;
+ seen_rr = ISC_TRUE;
+ dns_rdataset_disassociate(&rdataset);
+ }
+ dns_rdatasetiter_destroy(&iterator);
+
+ if (!seen_rr || seen_nsec3 || seen_nsec)
+ goto next_removenode;
+ if ((seen_ns && !seen_soa) || seen_dname)
+ delegation = ISC_TRUE;
+
+ CHECK(add_nsec(db, version, name, node, zone->minimum,
+ delegation, &nsec_diff));
+
+ next_removenode:
+ first = ISC_FALSE;
+ dns_db_detachnode(db, &node);
+ do {
+ result = dns_dbiterator_next(nsec3chain->dbiterator);
+ if (result == ISC_R_NOMORE && buildnsecchain) {
+ /*
+ * The NSEC chain should now be built.
+ * We can now remove the NSEC3 chain.
+ */
+ updatensec = ISC_TRUE;
+ goto same_removechain;
+ }
+ if (result == ISC_R_NOMORE) {
+ LOCK_ZONE(zone);
+ ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
+ link);
+ UNLOCK_ZONE(zone);
+ ISC_LIST_APPEND(cleanup, nsec3chain, link);
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ CHECK(fixup_nsec3param(db, version, nsec3chain,
+ ISC_FALSE, &param_diff));
+ goto next_removechain;
+ } else if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:"
+ "dns_dbiterator_next -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ } else if (delegation) {
+ dns_dbiterator_current(nsec3chain->dbiterator,
+ &node, nextname);
+ dns_db_detachnode(db, &node);
+ if (!dns_name_issubdomain(nextname, name))
+ break;
+ } else
+ break;
+ } while (1);
+ continue;
+
+ same_removechain:
+ CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
+ buildnsecchain = ISC_FALSE;
+ first = ISC_TRUE;
+ continue;
+
+ next_removechain:
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ nsec3chain = nextnsec3chain;
+ first = ISC_TRUE;
+ }
+
+ /*
+ * Add / update signatures for the NSEC3 records.
+ */
+ 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;
+ }
+
+ 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;
+ }
+ 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;
+ }
+ 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));
+
+ 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);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_nsec3chain:add_sigs -> %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);
+ }
+
+ /*
+ * If we made no effective changes to the zone then we can just
+ * cleanup otherwise we need to increment the serial.
+ */
+ if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
+ goto done;
+
+ 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_nsec3chain:"
+ "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_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;
+ }
+
+ 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;
+ }
+ }
+
+ LOCK_ZONE(zone);
+ zone_needdump(zone, DNS_DUMP_DELAY);
+ UNLOCK_ZONE(zone);
+
+ done:
+ /*
+ * Pause all iterators so that dns_db_closeversion() can succeed.
+ */
+ LOCK_ZONE(zone);
+ for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
+ nsec3chain != NULL;
+ nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ UNLOCK_ZONE(zone);
+
+ /*
+ * Everything has succeeded. Commit the changes.
+ */
+ dns_db_closeversion(db, &version, ISC_TRUE);
+
+ /*
+ * Everything succeeded so we can clean these up now.
+ */
+ nsec3chain = ISC_LIST_HEAD(cleanup);
+ while (nsec3chain != NULL) {
+ ISC_LIST_UNLINK(cleanup, nsec3chain, link);
+ dns_db_detach(&nsec3chain->db);
+ dns_dbiterator_destroy(&nsec3chain->dbiterator);
+ isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
+ nsec3chain = ISC_LIST_HEAD(cleanup);
+ }
+
+ set_resigntime(zone);
+
+ failure:
+ /*
+ * On error roll back the current nsec3chain.
+ */
+ if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
+ if (nsec3chain->done) {
+ dns_db_detach(&nsec3chain->db);
+ dns_dbiterator_destroy(&nsec3chain->dbiterator);
+ isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
+ } else {
+ result = dns_dbiterator_first(nsec3chain->dbiterator);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
+ }
+ }
+
+ /*
+ * Rollback the cleanup list.
+ */
+ nsec3chain = ISC_LIST_TAIL(cleanup);
+ while (nsec3chain != NULL) {
+ ISC_LIST_UNLINK(cleanup, nsec3chain, link);
+ if (nsec3chain->done) {
+ dns_db_detach(&nsec3chain->db);
+ dns_dbiterator_destroy(&nsec3chain->dbiterator);
+ isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
+ } else {
+ LOCK_ZONE(zone);
+ ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
+ UNLOCK_ZONE(zone);
+ result = dns_dbiterator_first(nsec3chain->dbiterator);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
+ }
+ nsec3chain = ISC_LIST_TAIL(cleanup);
+ }
+
+ LOCK_ZONE(zone);
+ for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
+ nsec3chain != NULL;
+ nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
+ dns_dbiterator_pause(nsec3chain->dbiterator);
+ UNLOCK_ZONE(zone);
+
+ dns_diff_clear(&param_diff);
+ dns_diff_clear(&nsec3_diff);
+ dns_diff_clear(&nsec_diff);
+ dns_diff_clear(&sig_diff);
+
+ if (iterator != NULL)
+ dns_rdatasetiter_destroy(&iterator);
+
+ for (i = 0; i < nkeys; i++)
+ dst_key_free(&zone_keys[i]);
+
+ if (version != NULL) {
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ dns_db_detach(&db);
+ } else if (db != NULL)
+ dns_db_detach(&db);
+
+ LOCK_ZONE(zone);
+ if (ISC_LIST_HEAD(zone->nsec3chain) != 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->nsec3chaintime, &i);
+ } else
+ isc_time_settoepoch(&zone->nsec3chaintime);
+ UNLOCK_ZONE(zone);
+}
+
+static isc_result_t
+del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
+ dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
+ isc_uint16_t keyid, dns_diff_t *diff)
+{
+ dns_rdata_rrsig_t rrsig;
+ dns_rdataset_t rdataset;
+ dns_rdatasetiter_t *iterator = NULL;
+ isc_result_t result;
+
+ result = dns_db_allrdatasets(db, node, version, 0, &iterator);
+ if (result != ISC_R_SUCCESS) {
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_SUCCESS;
+ return (result);
+ }
+
+ dns_rdataset_init(&rdataset);
+ for (result = dns_rdatasetiter_first(iterator);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(iterator)) {
+ dns_rdatasetiter_current(iterator, &rdataset);
+ if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
+ 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(update_one_rr(db, version, diff,
+ DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata));
+ }
+ if (result != ISC_R_NOMORE)
+ goto failure;
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ if (rdataset.type != dns_rdatatype_rrsig) {
+ dns_rdataset_disassociate(&rdataset);
+ continue;
+ }
+ 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, &rrsig, NULL));
+ if (rrsig.algorithm != algorithm ||
+ rrsig.keyid != keyid)
+ continue;
+ CHECK(update_one_rr(db, version, diff,
+ DNS_DIFFOP_DEL, name,
+ rdataset.ttl, &rdata));
+ }
+ dns_rdataset_disassociate(&rdataset);
+ if (result != ISC_R_NOMORE)
+ break;
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+ failure:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ dns_rdatasetiter_destroy(&iterator);
+ return (result);
+}
+
+/*
+ * Incrementally sign the zone using the keys requested.
+ * Builds the NSEC chain if required.
+ */
+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_fixedname_t fixed;
+ dns_fixedname_t nextfixed;
+ dns_name_t *name, *nextname;
+ dns_rdataset_t rdataset;
+ dns_signing_t *signing, *nextsigning;
+ dns_signinglist_t cleanup;
+ dst_key_t *zone_keys[MAXZONEKEYS];
+ isc_int32_t signatures;
+ isc_boolean_t check_ksk, is_ksk;
+ 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 first;
+ isc_result_t result;
+ isc_stdtime_t now, inception, soaexpire, expire, stop;
+ isc_uint32_t jitter;
+ unsigned int i;
+ unsigned int nkeys = 0;
+ isc_uint32_t nodes;
+
+ dns_rdataset_init(&rdataset);
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&fixed);
+ dns_fixedname_init(&nextfixed);
+ nextname = dns_fixedname_name(&nextfixed);
+ dns_diff_init(zone->mctx, &sig_diff);
+ sig_diff.resign = zone->sigresigninginterval;
+ ISC_LIST_INIT(cleanup);
+
+ /*
+ * Updates are disabled. Pause for 5 minutes.
+ */
+ if (zone->update_disabled) {
+ result = ISC_R_FAILURE;
+ goto failure;
+ }
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ result = dns_db_newversion(db, &version);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:dns_db_newversion -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ result = find_zone_keys(zone, db, version, zone->mctx,
+ MAXZONEKEYS, zone_keys, &nkeys);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:find_zone_keys -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+
+ isc_stdtime_get(&now);
+ inception = now - 3600; /* Allow for clock skew. */
+ soaexpire = now + dns_zone_getsigvalidityinterval(zone);
+
+ /*
+ * Spread out signatures over time if they happen to be
+ * clumped. We don't do this for each add_sigs() call as
+ * we still want some clustering to occur.
+ */
+ isc_random_get(&jitter);
+ 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 interator in turn until
+ * we have no more nodes to pull off or we reach the limits
+ * for this quantum.
+ */
+ nodes = zone->nodes;
+ 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) {
+ 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);
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (signing->done || signing->db != zone->db) {
+ /*
+ * The zone has been reloaded. We will have
+ * created new signings as part of the reload
+ * process so we can destroy this one.
+ */
+ ISC_LIST_UNLINK(zone->signing, signing, link);
+ ISC_LIST_APPEND(cleanup, signing, link);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ goto next_signing;
+ }
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+
+ if (signing->db != db)
+ goto next_signing;
+
+ is_ksk = ISC_FALSE;
+ delegation = ISC_FALSE;
+
+ dns_dbiterator_current(signing->dbiterator, &node, name);
+
+ if (signing->delete) {
+ dns_dbiterator_pause(signing->dbiterator);
+ 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.
+ */
+ if (first) {
+ dns_fixedname_t ffound;
+ dns_name_t *found;
+ dns_fixedname_init(&ffound);
+ found = dns_fixedname_name(&ffound);
+ result = dns_db_find(db, name, version,
+ dns_rdatatype_soa,
+ DNS_DBFIND_NOWILD, 0, NULL, found,
+ NULL, NULL);
+ if ((result == DNS_R_DELEGATION ||
+ result == DNS_R_DNAME) &&
+ !dns_name_equal(name, found)) {
+ /*
+ * Remember the obscuring name so that
+ * we skip all obscured names.
+ */
+ dns_name_copy(found, name, NULL);
+ delegation = ISC_TRUE;
+ goto next_node;
+ }
+ }
+
+ /*
+ * Process one node.
+ */
+ dns_dbiterator_pause(signing->dbiterator);
+ for (i = 0; i < nkeys; i++) {
+ /*
+ * Find the key we want to sign with.
+ */
+ if (dst_key_alg(zone_keys[i]) != signing->algorithm ||
+ dst_key_id(zone_keys[i]) != signing->keyid ||
+ !dst_key_isprivate(zone_keys[i]))
+ continue;
+ /*
+ * Do we do KSK processing?
+ */
+ if (check_ksk &&
+ (dst_key_flags(zone_keys[i]) & DNS_KEYFLAG_KSK) != 0)
+ is_ksk = ISC_TRUE;
+ 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;
+ }
+ /*
+ * Go onto next node.
+ */
+ next_node:
+ first = ISC_FALSE;
+ dns_db_detachnode(db, &node);
+ do {
+ result = dns_dbiterator_next(signing->dbiterator);
+ if (result == ISC_R_NOMORE) {
+ 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) {
+ /*
+ * We have finished regenerating the
+ * zone with a zone signing key.
+ * The NSEC chain is now complete and
+ * there is a full set of signatures
+ * for the zone. We can now clear the
+ * OPT bit from the NSEC record.
+ */
+ result = updatesecure(db, version,
+ &zone->origin,
+ zone->minimum,
+ &secureupdated,
+ &sig_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone,
+ ISC_LOG_ERROR,
+ "updatesecure -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+ result = updatesignwithkey(signing, version,
+ &zone->origin,
+ zone->privatetype,
+ &sig_diff);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "updatesignwithkey -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ goto next_signing;
+ } else if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign:dns_dbiterator_next -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ } else if (delegation) {
+ dns_dbiterator_current(signing->dbiterator,
+ &node, nextname);
+ dns_db_detachnode(db, &node);
+ if (!dns_name_issubdomain(nextname, name))
+ break;
+ } else
+ break;
+ } while (1);
+ continue;
+
+ next_signing:
+ dns_dbiterator_pause(signing->dbiterator);
+ signing = nextsigning;
+ first = ISC_TRUE;
+ }
+
+ 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;
+ }
+ 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 (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;
+ }
+ }
+ 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);
+ if (result != ISC_R_SUCCESS) {
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "zone_sign: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_sign: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_sign:dns_journal_write_transaction -> %s\n",
+ dns_result_totext(result));
+ goto failure;
+ }
+ }
+
+
+ /*
+ * 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, ISC_TRUE);
+
+ /*
+ * 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);
+
+ LOCK_ZONE(zone);
+ 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_APPEND(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 (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
+zone_maintenance(dns_zone_t *zone) {
+ const char me[] = "zone_maintenance";
+ isc_time_t now;
+ isc_result_t result;
+ isc_boolean_t dumping;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ ENTER;
+
+ /*
+ * Configuring the view of this zone may have
+ * failed, for example because the config file
+ * had a syntax error. In that case, the view
+ * adb or resolver, and we had better not try
+ * to do maintenance on it.
+ */
+ if (zone->view == NULL || zone->view->adb == NULL)
+ return;
+
+ TIME_NOW(&now);
+
+ /*
+ * Expire check.
+ */
+ switch (zone->type) {
+ case dns_zone_slave:
+ case dns_zone_stub:
+ LOCK_ZONE(zone);
+ if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
+ zone_expire(zone);
+ zone->refreshtime = now;
+ }
+ UNLOCK_ZONE(zone);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Up to date check.
+ */
+ switch (zone->type) {
+ case dns_zone_slave:
+ case dns_zone_stub:
+ if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
+ isc_time_compare(&now, &zone->refreshtime) >= 0)
+ dns_zone_refresh(zone);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Do we need to consolidate the backing store?
+ */
+ switch (zone->type) {
+ case dns_zone_master:
+ case dns_zone_slave:
+ LOCK_ZONE(zone);
+ if (zone->masterfile != NULL &&
+ isc_time_compare(&now, &zone->dumptime) >= 0 &&
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
+ dumping = was_dumping(zone);
+ } else
+ dumping = ISC_TRUE;
+ UNLOCK_ZONE(zone);
+ if (!dumping) {
+ result = zone_dump(zone, ISC_TRUE); /* task locked */
+ if (result != ISC_R_SUCCESS)
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "dump failed: %s",
+ dns_result_totext(result));
+ }
+ break;
+ default:
+ break;
+ }
+
+ switch (zone->type) {
+ case dns_zone_master:
+ case dns_zone_slave:
+ /*
+ * Do we need to send out notify messages?
+ */
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
+ isc_time_compare(&now, &zone->notifytime) >= 0)
+ zone_notify(zone, &now);
+ /*
+ * Do we need to sign/resign some RRsets?
+ */
+ if (!isc_time_isepoch(&zone->signingtime) &&
+ isc_time_compare(&now, &zone->signingtime) >= 0)
+ zone_sign(zone);
+ else if (!isc_time_isepoch(&zone->resigntime) &&
+ isc_time_compare(&now, &zone->resigntime) >= 0)
+ zone_resigninc(zone);
+ else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
+ isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
+ zone_nsec3chain(zone);
+ /*
+ * Do we need to issue a key expiry warning.
+ */
+ if (!isc_time_isepoch(&zone->keywarntime) &&
+ isc_time_compare(&now, &zone->keywarntime) >= 0)
+ set_key_expiry_warning(zone, zone->key_expiry,
+ isc_time_seconds(&now));
+ break;
+ default:
+ break;
+ }
+ zone_settimer(zone, &now);
+}
+
+void
+dns_zone_markdirty(dns_zone_t *zone) {
+
+ LOCK_ZONE(zone);
+ set_resigntime(zone); /* XXXMPA make seperate call back */
+ zone_needdump(zone, DNS_DUMP_DELAY);
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_expire(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ zone_expire(zone);
+ UNLOCK_ZONE(zone);
+}
+
+static void
+zone_expire(dns_zone_t *zone) {
+ /*
+ * 'zone' locked by caller.
+ */
+
+ REQUIRE(LOCKED_ZONE(zone));
+
+ dns_zone_log(zone, ISC_LOG_WARNING, "expired");
+
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
+ zone->refresh = DNS_ZONE_DEFAULTREFRESH;
+ zone->retry = DNS_ZONE_DEFAULTRETRY;
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
+ zone_unload(zone);
+}
+
+void
+dns_zone_refresh(dns_zone_t *zone) {
+ isc_interval_t i;
+ isc_uint32_t oldflags;
+ unsigned int j;
+ isc_result_t result;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
+ return;
+
+ /*
+ * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
+ * in progress at a time.
+ */
+
+ LOCK_ZONE(zone);
+ oldflags = zone->flags;
+ if (zone->masterscnt == 0) {
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
+ if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "cannot refresh: no masters");
+ goto unlock;
+ }
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
+ if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
+ goto unlock;
+
+ /*
+ * Set the next refresh time as if refresh check has failed.
+ * Setting this to the retry time will do that. XXXMLG
+ * If we are successful it will be reset using zone->refresh.
+ */
+ isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
+ 0);
+ result = isc_time_nowplusinterval(&zone->refreshtime, &i);
+ if (result |= ISC_R_SUCCESS)
+ dns_zone_log(zone, ISC_LOG_WARNING,
+ "isc_time_nowplusinterval() failed: %s",
+ dns_result_totext(result));
+
+ /*
+ * When lacking user-specified timer values from the SOA,
+ * do exponential backoff of the retry time up to a
+ * maximum of six hours.
+ */
+ if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
+ zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
+
+ zone->curmaster = 0;
+ for (j = 0; j < zone->masterscnt; j++)
+ zone->mastersok[j] = ISC_FALSE;
+ /* initiate soa query */
+ queue_soa_query(zone);
+ unlock:
+ UNLOCK_ZONE(zone);
+}
+
+isc_result_t
+dns_zone_flush(dns_zone_t *zone) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t dumping;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
+ zone->masterfile != NULL) {
+ result = ISC_R_ALREADYRUNNING;
+ dumping = was_dumping(zone);
+ } else
+ dumping = ISC_TRUE;
+ UNLOCK_ZONE(zone);
+ if (!dumping)
+ result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
+ return (result);
+}
+
+isc_result_t
+dns_zone_dump(dns_zone_t *zone) {
+ isc_result_t result = ISC_R_ALREADYRUNNING;
+ isc_boolean_t dumping;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ dumping = was_dumping(zone);
+ UNLOCK_ZONE(zone);
+ if (!dumping)
+ result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
+ return (result);
+}
+
+static void
+zone_needdump(dns_zone_t *zone, unsigned int delay) {
+ isc_time_t dumptime;
+ isc_time_t now;
+
+ /*
+ * 'zone' locked by caller
+ */
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(LOCKED_ZONE(zone));
+
+ /*
+ * Do we have a place to dump to and are we loaded?
+ */
+ if (zone->masterfile == NULL ||
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
+ return;
+
+ TIME_NOW(&now);
+ /* add some noise */
+ DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
+
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
+ if (isc_time_isepoch(&zone->dumptime) ||
+ isc_time_compare(&zone->dumptime, &dumptime) > 0)
+ zone->dumptime = dumptime;
+ if (zone->task != NULL)
+ zone_settimer(zone, &now);
+}
+
+static void
+dump_done(void *arg, isc_result_t result) {
+ const char me[] = "dump_done";
+ dns_zone_t *zone = arg;
+ dns_db_t *db;
+ dns_dbversion_t *version;
+ isc_boolean_t again = ISC_FALSE;
+ isc_boolean_t compact = ISC_FALSE;
+ isc_uint32_t serial;
+ isc_result_t tresult;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ ENTER;
+
+ if (result == ISC_R_SUCCESS && zone->journal != NULL &&
+ zone->journalsize != -1) {
+
+ /*
+ * We don't own these, zone->dctx must stay valid.
+ */
+ db = dns_dumpctx_db(zone->dctx);
+ version = dns_dumpctx_version(zone->dctx);
+
+ tresult = dns_db_getsoaserial(db, version, &serial);
+ /*
+ * Note: we are task locked here so we can test
+ * zone->xfr safely.
+ */
+ if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
+ tresult = dns_journal_compact(zone->mctx,
+ zone->journal,
+ serial,
+ zone->journalsize);
+ switch (tresult) {
+ 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(tresult));
+ break;
+ default:
+ dns_zone_log(zone, ISC_LOG_ERROR,
+ "dns_journal_compact failed: %s",
+ dns_result_totext(tresult));
+ break;
+ }
+ } else if (tresult == ISC_R_SUCCESS) {
+ compact = ISC_TRUE;
+ zone->compact_serial = serial;
+ }
+ }
+
+ LOCK_ZONE(zone);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
+ if (compact)
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
+ if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
+ /*
+ * Try again in a short while.
+ */
+ zone_needdump(zone, DNS_DUMP_DELAY);
+ } else if (result == ISC_R_SUCCESS &&
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
+ isc_time_settoepoch(&zone->dumptime);
+ again = ISC_TRUE;
+ } else if (result == ISC_R_SUCCESS)
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
+
+ if (zone->dctx != NULL)
+ dns_dumpctx_detach(&zone->dctx);
+ zonemgr_putio(&zone->writeio);
+ UNLOCK_ZONE(zone);
+ if (again)
+ (void)zone_dump(zone, ISC_FALSE);
+ dns_zone_idetach(&zone);
+}
+
+static isc_result_t
+zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
+ const char me[] = "zone_dump";
+ isc_result_t result;
+ dns_dbversion_t *version = NULL;
+ isc_boolean_t again;
+ dns_db_t *db = NULL;
+ char *masterfile = NULL;
+ dns_masterformat_t masterformat = dns_masterformat_none;
+
+/*
+ * 'compact' MUST only be set if we are task locked.
+ */
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ ENTER;
+
+ redo:
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ LOCK_ZONE(zone);
+ if (zone->masterfile != NULL) {
+ masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
+ masterformat = zone->masterformat;
+ }
+ UNLOCK_ZONE(zone);
+ if (db == NULL) {
+ result = DNS_R_NOTLOADED;
+ goto fail;
+ }
+ if (masterfile == NULL) {
+ result = DNS_R_NOMASTERFILE;
+ goto fail;
+ }
+
+ if (compact) {
+ dns_zone_t *dummy = NULL;
+ LOCK_ZONE(zone);
+ zone_iattach(zone, &dummy);
+ result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
+ zone_gotwritehandle, zone,
+ &zone->writeio);
+ if (result != ISC_R_SUCCESS)
+ zone_idetach(&dummy);
+ else
+ result = DNS_R_CONTINUE;
+ UNLOCK_ZONE(zone);
+ } else {
+ dns_db_currentversion(db, &version);
+ result = dns_master_dump2(zone->mctx, db, version,
+ &dns_master_style_default,
+ masterfile, masterformat);
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ }
+ fail:
+ if (db != NULL)
+ dns_db_detach(&db);
+ if (masterfile != NULL)
+ isc_mem_free(zone->mctx, masterfile);
+ masterfile = NULL;
+
+ if (result == DNS_R_CONTINUE)
+ return (ISC_R_SUCCESS); /* XXXMPA */
+
+ again = ISC_FALSE;
+ LOCK_ZONE(zone);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * Try again in a short while.
+ */
+ zone_needdump(zone, DNS_DUMP_DELAY);
+ } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
+ isc_time_settoepoch(&zone->dumptime);
+ again = ISC_TRUE;
+ } else
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
+ UNLOCK_ZONE(zone);
+ if (again)
+ goto redo;
+
+ return (result);
+}
+
+static isc_result_t
+dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
+ dns_masterformat_t format)
+{
+ isc_result_t result;
+ dns_dbversion_t *version = NULL;
+ dns_db_t *db = NULL;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &db);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ if (db == NULL)
+ return (DNS_R_NOTLOADED);
+
+ dns_db_currentversion(db, &version);
+ result = dns_master_dumptostream2(zone->mctx, db, version, style,
+ format, fd);
+ dns_db_closeversion(db, &version, ISC_FALSE);
+ dns_db_detach(&db);
+ return (result);
+}
+
+isc_result_t
+dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
+ const dns_master_style_t *style) {
+ return dumptostream(zone, fd, style, format);
+}
+
+isc_result_t
+dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
+ return dumptostream(zone, fd, &dns_master_style_default,
+ dns_masterformat_text);
+}
+
+isc_result_t
+dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
+ return dumptostream(zone, fd, &dns_master_style_full,
+ dns_masterformat_text);
+}
+
+void
+dns_zone_unload(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ zone_unload(zone);
+ UNLOCK_ZONE(zone);
+}
+
+static void
+notify_cancel(dns_zone_t *zone) {
+ dns_notify_t *notify;
+
+ /*
+ * 'zone' locked by caller.
+ */
+
+ REQUIRE(LOCKED_ZONE(zone));
+
+ for (notify = ISC_LIST_HEAD(zone->notifies);
+ notify != NULL;
+ notify = ISC_LIST_NEXT(notify, link)) {
+ if (notify->find != NULL)
+ dns_adb_cancelfind(notify->find);
+ if (notify->request != NULL)
+ dns_request_cancel(notify->request);
+ }
+}
+
+static void
+zone_unload(dns_zone_t *zone) {
+
+ /*
+ * 'zone' locked by caller.
+ */
+
+ REQUIRE(LOCKED_ZONE(zone));
+
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
+ zone_detachdb(zone);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
+}
+
+void
+dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(val > 0);
+
+ zone->minrefresh = val;
+}
+
+void
+dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(val > 0);
+
+ zone->maxrefresh = val;
+}
+
+void
+dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(val > 0);
+
+ zone->minretry = val;
+}
+
+void
+dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(val > 0);
+
+ zone->maxretry = val;
+}
+
+static isc_boolean_t
+notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
+ dns_notify_t *notify;
+
+ for (notify = ISC_LIST_HEAD(zone->notifies);
+ notify != NULL;
+ notify = ISC_LIST_NEXT(notify, link)) {
+ if (notify->request != NULL)
+ continue;
+ if (name != NULL && dns_name_dynamic(&notify->ns) &&
+ dns_name_equal(name, &notify->ns))
+ return (ISC_TRUE);
+ if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
+ return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
+static isc_boolean_t
+notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
+ dns_tsigkey_t *key = NULL;
+ isc_sockaddr_t src;
+ isc_sockaddr_t any;
+ isc_boolean_t isself;
+ isc_netaddr_t dstaddr;
+
+ if (zone->view == NULL || zone->isself == NULL)
+ return (ISC_FALSE);
+
+ switch (isc_sockaddr_pf(dst)) {
+ case PF_INET:
+ src = zone->notifysrc4;
+ isc_sockaddr_any(&any);
+ break;
+ case PF_INET6:
+ src = zone->notifysrc6;
+ isc_sockaddr_any6(&any);
+ break;
+ default:
+ return (ISC_FALSE);
+ }
+
+ /*
+ * When sending from any the kernel will assign a source address
+ * that matches the destination address.
+ */
+ if (isc_sockaddr_eqaddr(&any, &src))
+ src = *dst;
+
+ isc_netaddr_fromsockaddr(&dstaddr, dst);
+ (void)dns_view_getpeertsig(zone->view, &dstaddr, &key);
+ isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
+ zone->isselfarg);
+ if (key != NULL)
+ dns_tsigkey_detach(&key);
+ return (isself);
+}
+
+static void
+notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
+ isc_mem_t *mctx;
+
+ /*
+ * Caller holds zone lock.
+ */
+ REQUIRE(DNS_NOTIFY_VALID(notify));
+
+ if (notify->zone != NULL) {
+ if (!locked)
+ LOCK_ZONE(notify->zone);
+ REQUIRE(LOCKED_ZONE(notify->zone));
+ if (ISC_LINK_LINKED(notify, link))
+ ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
+ if (!locked)
+ UNLOCK_ZONE(notify->zone);
+ if (locked)
+ zone_idetach(&notify->zone);
+ else
+ dns_zone_idetach(&notify->zone);
+ }
+ if (notify->find != NULL)
+ dns_adb_destroyfind(&notify->find);
+ if (notify->request != NULL)
+ dns_request_destroy(&notify->request);
+ if (dns_name_dynamic(&notify->ns))
+ dns_name_free(&notify->ns, notify->mctx);
+ mctx = notify->mctx;
+ isc_mem_put(notify->mctx, notify, sizeof(*notify));
+ isc_mem_detach(&mctx);
+}
+
+static isc_result_t
+notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
+ dns_notify_t *notify;
+
+ REQUIRE(notifyp != NULL && *notifyp == NULL);
+
+ notify = isc_mem_get(mctx, sizeof(*notify));
+ if (notify == NULL)
+ return (ISC_R_NOMEMORY);
+
+ notify->mctx = NULL;
+ isc_mem_attach(mctx, &notify->mctx);
+ notify->flags = flags;
+ notify->zone = NULL;
+ notify->find = NULL;
+ notify->request = NULL;
+ isc_sockaddr_any(&notify->dst);
+ dns_name_init(&notify->ns, NULL);
+ ISC_LINK_INIT(notify, link);
+ notify->magic = NOTIFY_MAGIC;
+ *notifyp = notify;
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * XXXAG should check for DNS_ZONEFLG_EXITING
+ */
+static void
+process_adb_event(isc_task_t *task, isc_event_t *ev) {
+ dns_notify_t *notify;
+ isc_eventtype_t result;
+
+ UNUSED(task);
+
+ notify = ev->ev_arg;
+ REQUIRE(DNS_NOTIFY_VALID(notify));
+ INSIST(task == notify->zone->task);
+ result = ev->ev_type;
+ isc_event_free(&ev);
+ if (result == DNS_EVENT_ADBMOREADDRESSES) {
+ dns_adb_destroyfind(&notify->find);
+ notify_find_address(notify);
+ return;
+ }
+ if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
+ LOCK_ZONE(notify->zone);
+ notify_send(notify);
+ UNLOCK_ZONE(notify->zone);
+ }
+ notify_destroy(notify, ISC_FALSE);
+}
+
+static void
+notify_find_address(dns_notify_t *notify) {
+ isc_result_t result;
+ unsigned int options;
+
+ REQUIRE(DNS_NOTIFY_VALID(notify));
+ options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
+ DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
+
+ if (notify->zone->view->adb == NULL)
+ goto destroy;
+
+ result = dns_adb_createfind(notify->zone->view->adb,
+ notify->zone->task,
+ process_adb_event, notify,
+ &notify->ns, dns_rootname, 0,
+ options, 0, NULL,
+ notify->zone->view->dstport,
+ &notify->find);
+
+ /* Something failed? */
+ if (result != ISC_R_SUCCESS)
+ goto destroy;
+
+ /* More addresses pending? */
+ if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
+ return;
+
+ /* We have as many addresses as we can get. */
+ LOCK_ZONE(notify->zone);
+ notify_send(notify);
+ UNLOCK_ZONE(notify->zone);
+
+ destroy:
+ notify_destroy(notify, ISC_FALSE);
+}
+
+
+static isc_result_t
+notify_send_queue(dns_notify_t *notify) {
+ isc_event_t *e;
+ isc_result_t result;
+
+ e = isc_event_allocate(notify->mctx, NULL,
+ DNS_EVENT_NOTIFYSENDTOADDR,
+ notify_send_toaddr,
+ notify, sizeof(isc_event_t));
+ if (e == NULL)
+ return (ISC_R_NOMEMORY);
+ e->ev_arg = notify;
+ e->ev_sender = NULL;
+ result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
+ notify->zone->task, &e);
+ if (result != ISC_R_SUCCESS)
+ isc_event_free(&e);
+ return (result);
+}
+
+static void
+notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
+ dns_notify_t *notify;
+ isc_result_t result;
+ dns_message_t *message = NULL;
+ isc_netaddr_t dstip;
+ dns_tsigkey_t *key = NULL;
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t src;
+ int timeout;
+ isc_boolean_t have_notifysource = ISC_FALSE;
+
+ notify = event->ev_arg;
+ REQUIRE(DNS_NOTIFY_VALID(notify));
+
+ UNUSED(task);
+
+ LOCK_ZONE(notify->zone);
+
+ if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
+ result = ISC_R_CANCELED;
+ goto cleanup;
+ }
+
+ if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
+ DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
+ notify->zone->view->requestmgr == NULL ||
+ notify->zone->db == NULL) {
+ result = ISC_R_CANCELED;
+ goto cleanup;
+ }
+
+ /*
+ * The raw IPv4 address should also exist. Don't send to the
+ * mapped form.
+ */
+ if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
+ isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
+ notify_log(notify->zone, ISC_LOG_DEBUG(3),
+ "notify: ignoring IPv6 mapped IPV4 address: %s",
+ addrbuf);
+ result = ISC_R_CANCELED;
+ goto cleanup;
+ }
+
+ result = notify_createmessage(notify->zone, notify->flags, &message);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ isc_netaddr_fromsockaddr(&dstip, &notify->dst);
+ (void)dns_view_getpeertsig(notify->zone->view, &dstip, &key);
+
+ isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
+ notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
+ addrbuf);
+ if (notify->zone->view->peers != NULL) {
+ dns_peer_t *peer = NULL;
+ result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
+ &dstip, &peer);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_peer_getnotifysource(peer, &src);
+ if (result == ISC_R_SUCCESS)
+ have_notifysource = ISC_TRUE;
+ }
+ }
+ switch (isc_sockaddr_pf(&notify->dst)) {
+ case PF_INET:
+ if (!have_notifysource)
+ src = notify->zone->notifysrc4;
+ break;
+ case PF_INET6:
+ if (!have_notifysource)
+ src = notify->zone->notifysrc6;
+ break;
+ default:
+ result = ISC_R_NOTIMPLEMENTED;
+ goto cleanup_key;
+ }
+ timeout = 15;
+ if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
+ timeout = 30;
+ result = dns_request_createvia2(notify->zone->view->requestmgr,
+ message, &src, &notify->dst, 0, key,
+ timeout * 3, timeout,
+ notify->zone->task, notify_done,
+ notify, &notify->request);
+ if (result == ISC_R_SUCCESS) {
+ if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
+ inc_stats(notify->zone,
+ dns_zonestatscounter_notifyoutv4);
+ } else {
+ inc_stats(notify->zone,
+ dns_zonestatscounter_notifyoutv6);
+ }
+ }
+
+ cleanup_key:
+ if (key != NULL)
+ dns_tsigkey_detach(&key);
+ dns_message_destroy(&message);
+ cleanup:
+ UNLOCK_ZONE(notify->zone);
+ if (result != ISC_R_SUCCESS)
+ notify_destroy(notify, ISC_FALSE);
+ isc_event_free(&event);
+}
+
+static void
+notify_send(dns_notify_t *notify) {
+ dns_adbaddrinfo_t *ai;
+ isc_sockaddr_t dst;
+ isc_result_t result;
+ dns_notify_t *new = NULL;
+
+ /*
+ * Zone lock held by caller.
+ */
+ REQUIRE(DNS_NOTIFY_VALID(notify));
+ REQUIRE(LOCKED_ZONE(notify->zone));
+
+ for (ai = ISC_LIST_HEAD(notify->find->list);
+ ai != NULL;
+ ai = ISC_LIST_NEXT(ai, publink)) {
+ dst = ai->sockaddr;
+ if (notify_isqueued(notify->zone, NULL, &dst))
+ continue;
+ if (notify_isself(notify->zone, &dst))
+ continue;
+ new = NULL;
+ result = notify_create(notify->mctx,
+ (notify->flags & DNS_NOTIFY_NOSOA),
+ &new);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ zone_iattach(notify->zone, &new->zone);
+ ISC_LIST_APPEND(new->zone->notifies, new, link);
+ new->dst = dst;
+ result = notify_send_queue(new);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ new = NULL;
+ }
+
+ cleanup:
+ if (new != NULL)
+ notify_destroy(new, ISC_TRUE);
+}
+
+void
+dns_zone_notify(dns_zone_t *zone) {
+ isc_time_t now;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
+
+ TIME_NOW(&now);
+ zone_settimer(zone, &now);
+ UNLOCK_ZONE(zone);
+}
+
+static void
+zone_notify(dns_zone_t *zone, isc_time_t *now) {
+ dns_dbnode_t *node = NULL;
+ dns_db_t *zonedb = NULL;
+ dns_dbversion_t *version = NULL;
+ dns_name_t *origin = NULL;
+ dns_name_t master;
+ dns_rdata_ns_t ns;
+ dns_rdata_soa_t soa;
+ isc_uint32_t serial;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdataset_t nsrdset;
+ dns_rdataset_t soardset;
+ isc_result_t result;
+ dns_notify_t *notify = NULL;
+ unsigned int i;
+ isc_sockaddr_t dst;
+ isc_boolean_t isqueued;
+ dns_notifytype_t notifytype;
+ unsigned int flags = 0;
+ isc_boolean_t loggednotify = ISC_FALSE;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
+ notifytype = zone->notifytype;
+ DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
+ UNLOCK_ZONE(zone);
+
+ if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
+ return;
+
+ if (notifytype == dns_notifytype_no)
+ return;
+
+ if (notifytype == dns_notifytype_masteronly &&
+ zone->type != dns_zone_master)
+ return;
+
+ origin = &zone->origin;
+
+ /*
+ * If the zone is dialup we are done as we don't want to send
+ * the current soa so as to force a refresh query.
+ */
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
+ flags |= DNS_NOTIFY_NOSOA;
+
+ /*
+ * Get SOA RRset.
+ */
+ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zone->db != NULL)
+ dns_db_attach(zone->db, &zonedb);
+ ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
+ if (zonedb == NULL)
+ return;
+ dns_db_currentversion(zonedb, &version);
+ result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup1;
+
+ dns_rdataset_init(&soardset);
+ result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
+ dns_rdatatype_none, 0, &soardset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup2;
+
+ /*
+ * Find serial and master server's name.
+ */
+ dns_name_init(&master, NULL);
+ result = dns_rdataset_first(&soardset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup3;
+ dns_rdataset_current(&soardset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdata_reset(&rdata);
+ result = dns_name_dup(&soa.origin, zone->mctx, &master);
+ serial = soa.serial;
+ dns_rdataset_disassociate(&soardset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup3;
+
+ /*
+ * Enqueue notify requests for 'also-notify' servers.
+ */
+ LOCK_ZONE(zone);
+ for (i = 0; i < zone->notifycnt; i++) {
+ dst = zone->notify[i];
+ if (notify_isqueued(zone, NULL, &dst))
+ continue;
+ result = notify_create(zone->mctx, flags, &notify);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ zone_iattach(zone, &notify->zone);
+ notify->dst = dst;
+ ISC_LIST_APPEND(zone->notifies, notify, link);
+ result = notify_send_queue(notify);
+ if (result != ISC_R_SUCCESS)
+ notify_destroy(notify, ISC_TRUE);
+ if (!loggednotify) {
+ notify_log(zone, ISC_LOG_INFO,
+ "sending notifies (serial %u)",
+ serial);
+ loggednotify = ISC_TRUE;
+ }
+ notify = NULL;
+ }
+ UNLOCK_ZONE(zone);
+
+ if (notifytype == dns_notifytype_explicit)
+ goto cleanup3;
+
+ /*
+ * Process NS RRset to generate notifies.
+ */
+
+ dns_rdataset_init(&nsrdset);
+ result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
+ dns_rdatatype_none, 0, &nsrdset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup3;
+
+ result = dns_rdataset_first(&nsrdset);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdataset_current(&nsrdset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ dns_rdata_reset(&rdata);
+ /*
+ * Don't notify the master server unless explictly
+ * configured to do so.
+ */
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
+ dns_name_compare(&master, &ns.name) == 0) {
+ result = dns_rdataset_next(&nsrdset);
+ continue;
+ }
+
+ if (!loggednotify) {
+ notify_log(zone, ISC_LOG_INFO,
+ "sending notifies (serial %u)",
+ serial);
+ loggednotify = ISC_TRUE;
+ }
+
+ LOCK_ZONE(zone);
+ isqueued = notify_isqueued(zone, &ns.name, NULL);
+ UNLOCK_ZONE(zone);
+ if (isqueued) {
+ result = dns_rdataset_next(&nsrdset);
+ continue;
+ }
+ result = notify_create(zone->mctx, flags, &notify);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ dns_zone_iattach(zone, &notify->zone);
+ result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
+ if (result != ISC_R_SUCCESS) {
+ LOCK_ZONE(zone);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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;
+
+ 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);
+ /*
+ * Skip to next failed / untried master.
+ */
+ 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;
+ }
+ }
+ 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;
+
+ 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
+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;
+ unsigned int j;
+
+ zone = revent->ev_arg;
+ INSIST(DNS_ZONE_VALID(zone));
+
+ UNUSED(task);
+
+ ENTER;
+
+ /*
+ * 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)) {
+ 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;
+ }
+ 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) {
+ 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.
+ */
+ 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),
+ "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 arn't.
+ */
+ if (msg->rcode == dns_rcode_refused &&
+ zone->type == dns_zone_slave)
+ goto tcp_transfer;
+ goto next_master;
+ }
+
+ /*
+ * 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;
+ } 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;
+
+ zone_debuglog(zone, me, 1, "serial: new %u, old %u",
+ serial, zone->serial);
+ if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
+ DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
+ isc_serial_gt(serial, zone->serial)) {
+ 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, zone->serial)) {
+ 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, zone->serial);
+ 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;
+
+ 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.
+ */
+ 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);
+ 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;
+
+ 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;
+ }
+
+ rdata->rdclass = rdatalist->rdclass;
+ rdata->type = rdatalist->type;
+ rdata->flags = 0;
+
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
+ == ISC_R_SUCCESS);
+
+ 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);
+}
+
+static void
+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;
+
+ 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;
+ }
+
+ /*
+ * 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;
+
+ 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.
+ */
+ 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);
+
+ 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;
+
+ 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;
+}
+
+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;
+
+ /*
+ * Attach so that the zone won't disappear from under us.
+ */
+ zone_iattach(zone, &stub->zone);
+
+ /*
+ * 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);
+
+ 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);
+ }
+
+ 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;
+ }
+ }
+
+ /*
+ * XXX Optimisation: Create message when zone is setup and reuse.
+ */
+ result = create_query(zone, dns_rdatatype_ns, &message);
+
+ 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.
+ */
+ 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);
+
+ 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 (!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));
+ }
+
+ /*
+ * 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;
+
+ 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;
+}
+
+/*
+ * 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;
+
+ 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);
+ 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);
+ }
+
+ /*
+ * In task context, no locking required. See zone_xfrdone().
+ */
+ if (zone->xfr != NULL)
+ dns_xfrin_shutdown(zone->xfr);
+
+ LOCK_ZONE(zone);
+ if (linked) {
+ INSIST(zone->irefs > 0);
+ zone->irefs--;
+ }
+ if (zone->request != NULL) {
+ dns_request_cancel(zone->request);
+ }
+
+ if (zone->readio != NULL)
+ zonemgr_cancelio(zone->readio);
+
+ if (zone->lctx != NULL)
+ dns_loadctx_cancel(zone->lctx);
+
+ if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
+ !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
+ if (zone->writeio != NULL)
+ zonemgr_cancelio(zone->writeio);
+
+ if (zone->dctx != NULL)
+ dns_dumpctx_cancel(zone->dctx);
+ }
+
+ notify_cancel(zone);
+
+ if (zone->timer != NULL) {
+ isc_timer_detach(&zone->timer);
+ INSIST(zone->irefs > 0);
+ zone->irefs--;
+ }
+
+ if (zone->view != NULL)
+ dns_view_weakdetach(&zone->view);
+
+ /*
+ * 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);
+}
+
+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;
+
+ UNUSED(task);
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ ENTER;
+
+ zone_maintenance(zone);
+
+ isc_event_free(&event);
+}
+
+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;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
+ return;
+
+ isc_time_settoepoch(&next);
+
+ 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;
+
+ case dns_zone_slave:
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
+ next = zone->notifytime;
+ /*FALLTHROUGH*/
+
+ 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;
+
+ 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 {
+ 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));
+ }
+}
+
+static void
+cancel_refresh(dns_zone_t *zone) {
+ const char me[] = "cancel_refresh";
+ isc_time_t now;
+
+ /*
+ * 'zone' locked by caller.
+ */
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(LOCKED_ZONE(zone));
+
+ ENTER;
+
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
+ TIME_NOW(&now);
+ zone_settimer(zone, &now);
+}
+
+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;
+
+ 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);
+
+ result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
+ &message);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ message->opcode = dns_opcode_notify;
+ message->flags |= DNS_MESSAGEFLAG_AA;
+ message->rdclass = zone->rdclass;
+
+ result = dns_message_gettempname(message, &tempname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_message_gettemprdataset(message, &temprdataset);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /*
+ * 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;
+
+ 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;
+
+ 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);
+
+ 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);
+
+ done:
+ *messagep = message;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (tempname != NULL)
+ dns_message_puttempname(message, &tempname);
+ if (temprdataset != NULL)
+ dns_message_puttemprdataset(message, &temprdataset);
+ dns_message_destroy(&message);
+ return (result);
+}
+
+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;
+
+ 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.
+ */
+
+ isc_sockaddr_format(from, fromtext, sizeof(fromtext));
+
+ /*
+ * 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 we are a master zone just succeed.
+ */
+ if (zone->type == dns_zone_master) {
+ UNLOCK_ZONE(zone);
+ return (ISC_R_SUCCESS);
+ }
+
+ 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;
+ }
+ }
+
+ /*
+ * 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);
+ }
+
+ /*
+ * 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;
+
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ serial = soa.serial;
+ if (isc_serial_le(serial, zone->serial)) {
+ 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
+ */
+ 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);
+}
+
+void
+dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (zone->notify_acl != NULL)
+ dns_acl_detach(&zone->notify_acl);
+ dns_acl_attach(acl, &zone->notify_acl);
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (zone->query_acl != NULL)
+ dns_acl_detach(&zone->query_acl);
+ dns_acl_attach(acl, &zone->query_acl);
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (zone->queryon_acl != NULL)
+ dns_acl_detach(&zone->queryon_acl);
+ dns_acl_attach(acl, &zone->queryon_acl);
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (zone->update_acl != NULL)
+ dns_acl_detach(&zone->update_acl);
+ dns_acl_attach(acl, &zone->update_acl);
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (zone->forward_acl != NULL)
+ dns_acl_detach(&zone->forward_acl);
+ dns_acl_attach(acl, &zone->forward_acl);
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
+
+ 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);
+}
+
+dns_acl_t *
+dns_zone_getnotifyacl(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->notify_acl);
+}
+
+dns_acl_t *
+dns_zone_getqueryacl(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->query_acl);
+}
+
+dns_acl_t *
+dns_zone_getqueryonacl(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->queryon_acl);
+}
+
+dns_acl_t *
+dns_zone_getupdateacl(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->update_acl);
+}
+
+dns_acl_t *
+dns_zone_getforwardacl(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->forward_acl);
+}
+
+dns_acl_t *
+dns_zone_getxfracl(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->xfr_acl);
+}
+
+void
+dns_zone_clearupdateacl(dns_zone_t *zone) {
+
+ 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));
+
+ LOCK_ZONE(zone);
+ if (zone->forward_acl != NULL)
+ dns_acl_detach(&zone->forward_acl);
+ UNLOCK_ZONE(zone);
+}
+
+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);
+}
+
+void
+dns_zone_clearqueryacl(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ 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));
+
+ LOCK_ZONE(zone);
+ if (zone->queryon_acl != NULL)
+ dns_acl_detach(&zone->queryon_acl);
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_clearxfracl(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ if (zone->xfr_acl != NULL)
+ dns_acl_detach(&zone->xfr_acl);
+ UNLOCK_ZONE(zone);
+}
+
+isc_boolean_t
+dns_zone_getupdatedisabled(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ return (zone->update_disabled);
+
+}
+
+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);
+
+}
+
+void
+dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ zone->zero_no_soa_ttl = state;
+}
+
+void
+dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ zone->check_names = severity;
+}
+
+dns_severity_t
+dns_zone_getchecknames(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->check_names);
+}
+
+void
+dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ zone->journalsize = size;
+}
+
+isc_int32_t
+dns_zone_getjournalsize(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->journalsize);
+}
+
+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;
+
+ REQUIRE(buf != NULL);
+ REQUIRE(length > 1U);
+
+ /*
+ * Leave space for terminating '\0'.
+ */
+ 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("<UNKNOWN>") - 1))
+ isc_buffer_putstr(&buffer, "<UNKNOWN>");
+
+ 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);
+
+ /*
+ * Leave space for terminating '\0'.
+ */
+ 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("<UNKNOWN>") - 1))
+ isc_buffer_putstr(&buffer, "<UNKNOWN>");
+
+ 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);
+
+ /*
+ * 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);
+
+
+ /*
+ * Leave space for terminating '\0'.
+ */
+ 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");
+ }
+
+ buf[isc_buffer_usedlength(&buffer)] = '\0';
+}
+
+void
+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);
+}
+
+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_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;
+
+ 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);
+}
+
+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;
+
+ 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);
+}
+
+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);
+ }
+
+ return (count);
+}
+
+void
+dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ zone->maxxfrin = maxxfrin;
+}
+
+isc_uint32_t
+dns_zone_getmaxxfrin(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->maxxfrin);
+}
+
+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->maxxfrout);
+}
+
+dns_zonetype_t
+dns_zone_gettype(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->type);
+}
+
+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));
+
+ 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);
+}
+
+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));
+
+ if (idlein == 0)
+ idlein = DNS_DEFAULT_IDLEIN;
+ zone->idlein = idlein;
+}
+
+isc_uint32_t
+dns_zone_getidlein(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->idlein);
+}
+
+void
+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);
+}
+
+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];
+
+ 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(&notify->dst, addrbuf, sizeof(addrbuf));
+
+ 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(&notify->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);
+}
+
+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);
+ 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);
+}
+
+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));
+
+ 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);
+ }
+
+ result = check_nsec3param(zone, db);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ ver = NULL;
+ dns_db_currentversion(db, &ver);
+
+ /*
+ * The initial version of a slave zone is always dumped;
+ * subsequent versions may be journalled 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;
+
+ dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
+
+ 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;
+ }
+
+ /*
+ * This is checked in zone_postload() for master zones.
+ */
+ if (zone->type == dns_zone_slave &&
+ !isc_serial_gt(serial, zone->serial)) {
+ isc_uint32_t serialmin, serialmax;
+ serialmin = (zone->serial + 1) & 0xffffffffU;
+ serialmax = (zone->serial + 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;
+ }
+
+ 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;
+
+ /*
+ * 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);
+ }
+
+ 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
+ * journalled 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");
+ (void)remove(zone->journal);
+ }
+ }
+
+ dns_db_closeversion(db, &ver, ISC_FALSE);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
+ "replacing zone database");
+
+ 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);
+}
+
+/* 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);
+
+ 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));
+ }
+ }
+}
+
+/* The caller must hold the dblock as a writer. */
+static inline void
+zone_detachdb(dns_zone_t *zone) {
+ REQUIRE(zone->db != NULL);
+
+ if (zone->acache != NULL)
+ (void)dns_acache_putdb(zone->acache, zone->db);
+ dns_db_detach(&zone->db);
+}
+
+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));
+
+ dns_zone_log(zone, ISC_LOG_DEBUG(1),
+ "zone transfer finished: %s", dns_result_totext(result));
+
+ LOCK_ZONE(zone);
+ INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
+
+ 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;
+ }
+
+ /*
+ * 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->serial = serial;
+ 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);
+ }
+
+ /*
+ * 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",
+ zone->serial, buf);
+ }
+
+ /*
+ * This is not neccessary 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));
+ }
+
+ inc_stats(zone, dns_zonestatscounter_xfrsuccess);
+ break;
+
+ case DNS_R_BADIXFR:
+ /* Force retry with AXFR. */
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
+ goto same_master;
+
+ 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);
+
+ /*
+ * 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.
+ */
+ if (zone->xfr != NULL)
+ dns_xfrin_detach(&zone->xfr);
+
+ if (zone->tsigkey != NULL)
+ dns_tsigkey_detach(&zone->tsigkey);
+
+ /*
+ * 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);
+ }
+
+ /*
+ * This transfer finishing freed up a transfer quota slot.
+ * Let any other zones waiting for quota have it.
+ */
+ 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);
+
+ /*
+ * Retry with a different server if necessary.
+ */
+ if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
+ queue_soa_query(zone);
+
+ INSIST(zone->irefs > 0);
+ zone->irefs--;
+ free_needed = exit_check(zone);
+ UNLOCK_ZONE(zone);
+ if (free_needed)
+ zone_free(zone);
+}
+
+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;
+
+ 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);
+ UNLOCK_ZONE(load->zone);
+
+ 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_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(table != NULL);
+ REQUIRE(*table == NULL);
+
+ LOCK_ZONE(zone);
+ if (zone->ssutable != NULL)
+ dns_ssutable_attach(zone->ssutable, table);
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ 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_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ zone->sigvalidityinterval = interval;
+}
+
+isc_uint32_t
+dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->sigvalidityinterval);
+}
+
+void
+dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ zone->sigresigninginterval = interval;
+}
+
+isc_uint32_t
+dns_zone_getsigresigninginterval(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->sigresigninginterval);
+}
+
+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);
+
+ 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));
+ }
+}
+
+/*
+ * 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;
+
+ 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);
+
+ /*
+ * 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 AXFR from %s", master);
+ 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 AXFR from %s",
+ 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;
+ }
+ }
+
+ /*
+ * 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 (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));
+ }
+
+ 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);
+
+ isc_event_free(&event);
+}
+
+/*
+ * Update forwarding support.
+ */
+
+static void
+forward_destroy(dns_forward_t *forward) {
+
+ 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 isc_result_t
+sendtomaster(dns_forward_t *forward) {
+ isc_result_t result;
+ isc_sockaddr_t src;
+
+ 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];
+ /*
+ * 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;
+ }
+ 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);
+}
+
+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;
+
+ UNUSED(task);
+
+ forward = revent->ev_arg;
+ INSIST(DNS_FORWARD_VALID(forward));
+ zone = forward->zone;
+ INSIST(DNS_ZONE_VALID(zone));
+
+ ENTER;
+
+ 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 = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
+ if (result != ISC_R_SUCCESS)
+ goto next_master;
+
+ result = dns_request_getresponse(revent->request, msg,
+ DNS_MESSAGEPARSE_PRESERVEORDER |
+ DNS_MESSAGEPARSE_CLONEBUFFER);
+ if (result != ISC_R_SUCCESS)
+ goto next_master;
+
+ switch (msg->rcode) {
+ /*
+ * Pass these rcodes back to client.
+ */
+ 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;
+ }
+
+ /* 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;
+ }
+
+ /* 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);
+ }
+}
+
+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;
+
+ mr = dns_message_getrawmessage(msg);
+ if (mr == NULL) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto cleanup;
+ }
+
+ 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;
+
+ isc_mem_attach(zone->mctx, &forward->mctx);
+ dns_zone_iattach(zone, &forward->zone);
+ result = sendtomaster(forward);
+
+ cleanup:
+ if (result != ISC_R_SUCCESS) {
+ forward_destroy(forward);
+ }
+ return (result);
+}
+
+isc_result_t
+dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(next != NULL && *next == NULL);
+
+ *next = ISC_LIST_NEXT(zone, link);
+ if (*next == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+ REQUIRE(first != NULL && *first == NULL);
+
+ *first = ISC_LIST_HEAD(zmgr->zones);
+ if (*first == NULL)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_SUCCESS);
+}
+
+/***
+ *** 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;
+ isc_interval_t interval;
+
+ 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;
+
+ zmgr->transfersin = 10;
+ zmgr->transfersperns = 2;
+
+ /* Create the zone task pool. */
+ result = isc_taskpool_create(taskmgr, mctx,
+ 8 /* XXX */, 2, &zmgr->zonetasks);
+ if (result != ISC_R_SUCCESS)
+ goto free_rwlock;
+
+ /* 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);
+
+ 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);
+}
+
+isc_result_t
+dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
+ isc_result_t result;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
+ LOCK_ZONE(zone);
+ REQUIRE(zone->task == NULL);
+ REQUIRE(zone->timer == NULL);
+ REQUIRE(zone->zmgr == NULL);
+
+ isc_taskpool_gettask(zmgr->zonetasks,
+ dns_name_hash(dns_zone_getorigin(zone),
+ ISC_FALSE),
+ &zone->task);
+
+ /*
+ * 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).
+ */
+ 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;
+
+ /*
+ * The timer "holds" a iref.
+ */
+ zone->irefs++;
+ INSIST(zone->irefs != 0);
+
+ ISC_LIST_APPEND(zmgr->zones, zone, link);
+ zone->zmgr = zmgr;
+ zmgr->refs++;
+
+ goto unlock;
+
+ cleanup_task:
+ isc_task_detach(&zone->task);
+
+ unlock:
+ 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;
+
+ 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;
+
+ 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);
+
+ /*
+ * 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);
+}
+
+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_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ isc_ratelimiter_shutdown(zmgr->rl);
+
+ if (zmgr->task != NULL)
+ isc_task_destroy(&zmgr->task);
+ if (zmgr->zonetasks != NULL)
+ isc_taskpool_destroy(&zmgr->zonetasks);
+}
+
+static void
+zonemgr_free(dns_zonemgr_t *zmgr) {
+ isc_mem_t *mctx;
+
+ 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_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ zmgr->transfersin = value;
+}
+
+isc_uint32_t
+dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ return (zmgr->transfersin);
+}
+
+void
+dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ zmgr->transfersperns = value;
+}
+
+isc_uint32_t
+dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ 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
+zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
+ dns_zone_t *zone;
+ dns_zone_t *next;
+
+ 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;
+ }
+ }
+}
+
+/*
+ * 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);
+
+ /*
+ * 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);
+
+ /*
+ * 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++;
+ }
+
+ /* Enforce quota. */
+ if (nxfrsin >= maxtransfersin)
+ return (ISC_R_QUOTA);
+
+ if (nxfrsperns >= maxtransfersperns)
+ return (ISC_R_QUOTA);
+
+ /*
+ * 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);
+
+ 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);
+}
+
+void
+dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
+
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+ REQUIRE(iolimit > 0);
+
+ 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
+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;
+
+ 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;
+
+ 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;
+
+ REQUIRE(iop != NULL);
+ io = *iop;
+ REQUIRE(DNS_IO_VALID(io));
+
+ *iop = NULL;
+
+ INSIST(!ISC_LINK_LINKED(io, link));
+ INSIST(io->event == NULL);
+
+ zmgr = io->zmgr;
+ isc_task_detach(&io->task);
+ io->magic = 0;
+ isc_mem_put(zmgr->mctx, io, sizeof(*io));
+
+ 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);
+}
+
+static void
+zonemgr_cancelio(dns_io_t *io) {
+ isc_boolean_t send_event = ISC_FALSE;
+
+ REQUIRE(DNS_IO_VALID(io));
+
+ /*
+ * 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);
+
+ send_event = ISC_TRUE;
+ INSIST(io->event != NULL);
+ }
+ UNLOCK(&io->zmgr->iolock);
+ if (send_event) {
+ io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
+ isc_task_send(io->task, &io->event);
+ }
+}
+
+static void
+zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
+ char *buf;
+ int buflen;
+ isc_result_t result;
+
+ buflen = strlen(path) + strlen(templat) + 2;
+
+ buf = isc_mem_get(zone->mctx, buflen);
+ if (buf == NULL)
+ return;
+
+ result = isc_file_template(path, templat, buf, buflen);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = isc_file_renameunique(path, buf);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'",
+ path, buf);
+
+ cleanup:
+ isc_mem_put(zone->mctx, buf, buflen);
+}
+
+#if 0
+/* Hook for ondestroy notifcation from a database. */
+
+static void
+dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
+ dns_db_t *db = event->sender;
+ UNUSED(task);
+
+ isc_event_free(&event);
+
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
+ DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
+ "database (%p) destroyed", (void*) db);
+}
+#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;
+ isc_result_t result;
+
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ if (value == 0)
+ value = 1;
+
+ 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;
+ }
+
+ 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);
+
+ zmgr->serialqueryrate = value;
+}
+
+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));
+}
+
+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;
+
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ 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);
+}
+
+void
+dns_zone_forcereload(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ if (zone->type == dns_zone_master)
+ return;
+
+ LOCK_ZONE(zone);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
+ UNLOCK_ZONE(zone);
+ dns_zone_refresh(zone);
+}
+
+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) {
+ /*
+ * This function is obsoleted.
+ */
+ UNUSED(zone);
+ UNUSED(on);
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+isc_uint64_t *
+dns_zone_getstatscounters(dns_zone_t *zone) {
+ /*
+ * This function is obsoleted.
+ */
+ UNUSED(zone);
+ return (NULL);
+}
+
+void
+dns_zone_setstats(dns_zone_t *zone, dns_stats_t *stats) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ REQUIRE(zone->stats == NULL);
+
+ LOCK_ZONE(zone);
+ zone->stats = NULL;
+ dns_stats_attach(stats, &zone->stats);
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setrequeststats(dns_zone_t *zone, dns_stats_t *stats) {
+ 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) {
+ dns_stats_attach(stats, &zone->requeststats);
+ zone->requeststats_on = ISC_TRUE;
+ }
+ }
+ UNLOCK_ZONE(zone);
+
+ return;
+}
+
+dns_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_zone_dialup(dns_zone_t *zone) {
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ 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 (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_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ result = dns_zone_setstring(zone, &zone->keydirectory, directory);
+ UNLOCK_ZONE(zone);
+
+ return (result);
+}
+
+const char *
+dns_zone_getkeydirectory(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->keydirectory);
+}
+
+unsigned int
+dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
+ dns_zone_t *zone;
+ unsigned int count = 0;
+
+ REQUIRE(DNS_ZONEMGR_VALID(zmgr));
+
+ 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);
+ }
+
+ RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
+
+ return (count);
+}
+
+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;
+
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
+ return (ISC_R_SUCCESS);
+
+ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
+ level = ISC_LOG_ERROR;
+ fail = ISC_TRUE;
+ }
+
+ 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_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ zone->checkmx = checkmx;
+}
+
+void
+dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ zone->checksrv = checksrv;
+}
+
+void
+dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ zone->checkns = checkns;
+}
+
+void
+dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ zone->isself = isself;
+ zone->isselfarg = arg;
+ UNLOCK_ZONE(zone);
+}
+
+void
+dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ zone->notifydelay = delay;
+ UNLOCK_ZONE(zone);
+}
+
+isc_uint32_t
+dns_zone_getnotifydelay(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ return (zone->notifydelay);
+}
+
+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));
+
+ 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);
+
+ return (result);
+}
+
+static const char *hex = "0123456789ABCDEF";
+
+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;
+
+ 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);
+ result = zone_addnsec3chain(zone, nsec3param);
+ UNLOCK_ZONE(zone);
+
+ 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) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ zone->privatetype = type;
+}
+
+dns_rdatatype_t
+dns_zone_getprivatetype(dns_zone_t *zone) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+ return (zone->privatetype);
+}
+
+static isc_result_t
+zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
+ isc_boolean_t delete)
+{
+ 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;
+
+ cleanup:
+ if (signing != 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);
+}
diff --git a/lib/dns/zonekey.c b/lib/dns/zonekey.c
new file mode 100644
index 0000000..bf7474b
--- /dev/null
+++ b/lib/dns/zonekey.c
@@ -0,0 +1,55 @@
+/*
+ * 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: zonekey.c,v 1.9 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/result.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/keyvalues.h>
+#include <dns/rdata.h>
+#include <dns/rdatastruct.h>
+#include <dns/types.h>
+#include <dns/zonekey.h>
+
+isc_boolean_t
+dns_zonekey_iszonekey(dns_rdata_t *keyrdata) {
+ isc_result_t result;
+ dns_rdata_dnskey_t key;
+ isc_boolean_t iszonekey = ISC_TRUE;
+
+ REQUIRE(keyrdata != NULL);
+
+ result = dns_rdata_tostruct(keyrdata, &key, NULL);
+ if (result != ISC_R_SUCCESS)
+ return (ISC_FALSE);
+
+ if ((key.flags & DNS_KEYTYPE_NOAUTH) != 0)
+ iszonekey = ISC_FALSE;
+ if ((key.flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
+ iszonekey = ISC_FALSE;
+ if (key.protocol != DNS_KEYPROTO_DNSSEC &&
+ key.protocol != DNS_KEYPROTO_ANY)
+ iszonekey = ISC_FALSE;
+
+ return (iszonekey);
+}
diff --git a/lib/dns/zt.c b/lib/dns/zt.c
new file mode 100644
index 0000000..ed7f28a
--- /dev/null
+++ b/lib/dns/zt.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: zt.c,v 1.47 2007/06/19 23:47:16 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/file.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/log.h>
+#include <dns/name.h>
+#include <dns/rbt.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/view.h>
+#include <dns/zone.h>
+#include <dns/zt.h>
+
+struct dns_zt {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t *mctx;
+ dns_rdataclass_t rdclass;
+ isc_rwlock_t rwlock;
+ /* Locked by lock. */
+ isc_uint32_t references;
+ dns_rbt_t *table;
+};
+
+#define ZTMAGIC ISC_MAGIC('Z', 'T', 'b', 'l')
+#define VALID_ZT(zt) ISC_MAGIC_VALID(zt, ZTMAGIC)
+
+static void
+auto_detach(void *, void *);
+
+static isc_result_t
+load(dns_zone_t *zone, void *uap);
+
+static isc_result_t
+loadnew(dns_zone_t *zone, void *uap);
+
+static isc_result_t
+freezezones(dns_zone_t *zone, void *uap);
+
+isc_result_t
+dns_zt_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_zt_t **ztp)
+{
+ dns_zt_t *zt;
+ isc_result_t result;
+
+ REQUIRE(ztp != NULL && *ztp == NULL);
+
+ zt = isc_mem_get(mctx, sizeof(*zt));
+ if (zt == NULL)
+ return (ISC_R_NOMEMORY);
+
+ zt->table = NULL;
+ result = dns_rbt_create(mctx, auto_detach, zt, &zt->table);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_zt;
+
+ result = isc_rwlock_init(&zt->rwlock, 0, 0);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_rbt;
+
+ zt->mctx = mctx;
+ zt->references = 1;
+ zt->rdclass = rdclass;
+ zt->magic = ZTMAGIC;
+ *ztp = zt;
+
+ return (ISC_R_SUCCESS);
+
+ cleanup_rbt:
+ dns_rbt_destroy(&zt->table);
+
+ cleanup_zt:
+ isc_mem_put(mctx, zt, sizeof(*zt));
+
+ return (result);
+}
+
+isc_result_t
+dns_zt_mount(dns_zt_t *zt, dns_zone_t *zone) {
+ isc_result_t result;
+ dns_zone_t *dummy = NULL;
+ dns_name_t *name;
+
+ REQUIRE(VALID_ZT(zt));
+
+ name = dns_zone_getorigin(zone);
+
+ RWLOCK(&zt->rwlock, isc_rwlocktype_write);
+
+ result = dns_rbt_addname(zt->table, name, zone);
+ if (result == ISC_R_SUCCESS)
+ dns_zone_attach(zone, &dummy);
+
+ RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
+
+ return (result);
+}
+
+isc_result_t
+dns_zt_unmount(dns_zt_t *zt, dns_zone_t *zone) {
+ isc_result_t result;
+ dns_name_t *name;
+
+ REQUIRE(VALID_ZT(zt));
+
+ name = dns_zone_getorigin(zone);
+
+ RWLOCK(&zt->rwlock, isc_rwlocktype_write);
+
+ result = dns_rbt_deletename(zt->table, name, ISC_FALSE);
+
+ RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
+
+ return (result);
+}
+
+isc_result_t
+dns_zt_find(dns_zt_t *zt, dns_name_t *name, unsigned int options,
+ dns_name_t *foundname, dns_zone_t **zonep)
+{
+ isc_result_t result;
+ dns_zone_t *dummy = NULL;
+ unsigned int rbtoptions = 0;
+
+ REQUIRE(VALID_ZT(zt));
+
+ if ((options & DNS_ZTFIND_NOEXACT) != 0)
+ rbtoptions |= DNS_RBTFIND_NOEXACT;
+
+ RWLOCK(&zt->rwlock, isc_rwlocktype_read);
+
+ result = dns_rbt_findname(zt->table, name, rbtoptions, foundname,
+ (void **) (void*)&dummy);
+ if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+ dns_zone_attach(dummy, zonep);
+
+ RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
+
+ return (result);
+}
+
+void
+dns_zt_attach(dns_zt_t *zt, dns_zt_t **ztp) {
+
+ REQUIRE(VALID_ZT(zt));
+ REQUIRE(ztp != NULL && *ztp == NULL);
+
+ RWLOCK(&zt->rwlock, isc_rwlocktype_write);
+
+ INSIST(zt->references > 0);
+ zt->references++;
+ INSIST(zt->references != 0);
+
+ RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
+
+ *ztp = zt;
+}
+
+static isc_result_t
+flush(dns_zone_t *zone, void *uap) {
+ UNUSED(uap);
+ return (dns_zone_flush(zone));
+}
+
+static void
+zt_flushanddetach(dns_zt_t **ztp, isc_boolean_t need_flush) {
+ isc_boolean_t destroy = ISC_FALSE;
+ dns_zt_t *zt;
+
+ REQUIRE(ztp != NULL && VALID_ZT(*ztp));
+
+ zt = *ztp;
+
+ RWLOCK(&zt->rwlock, isc_rwlocktype_write);
+
+ INSIST(zt->references > 0);
+ zt->references--;
+ if (zt->references == 0)
+ destroy = ISC_TRUE;
+
+ RWUNLOCK(&zt->rwlock, isc_rwlocktype_write);
+
+ if (destroy) {
+ if (need_flush)
+ (void)dns_zt_apply(zt, ISC_FALSE, flush, NULL);
+ dns_rbt_destroy(&zt->table);
+ isc_rwlock_destroy(&zt->rwlock);
+ zt->magic = 0;
+ isc_mem_put(zt->mctx, zt, sizeof(*zt));
+ }
+
+ *ztp = NULL;
+}
+
+void
+dns_zt_flushanddetach(dns_zt_t **ztp) {
+ zt_flushanddetach(ztp, ISC_TRUE);
+}
+
+void
+dns_zt_detach(dns_zt_t **ztp) {
+ zt_flushanddetach(ztp, ISC_FALSE);
+}
+
+isc_result_t
+dns_zt_load(dns_zt_t *zt, isc_boolean_t stop) {
+ isc_result_t result;
+
+ REQUIRE(VALID_ZT(zt));
+
+ RWLOCK(&zt->rwlock, isc_rwlocktype_read);
+ result = dns_zt_apply(zt, stop, load, NULL);
+ RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
+ return (result);
+}
+
+static isc_result_t
+load(dns_zone_t *zone, void *uap) {
+ isc_result_t result;
+ UNUSED(uap);
+ result = dns_zone_load(zone);
+ if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
+isc_result_t
+dns_zt_loadnew(dns_zt_t *zt, isc_boolean_t stop) {
+ isc_result_t result;
+
+ REQUIRE(VALID_ZT(zt));
+
+ RWLOCK(&zt->rwlock, isc_rwlocktype_read);
+ result = dns_zt_apply(zt, stop, loadnew, NULL);
+ RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
+ return (result);
+}
+
+static isc_result_t
+loadnew(dns_zone_t *zone, void *uap) {
+ isc_result_t result;
+ UNUSED(uap);
+ result = dns_zone_loadnew(zone);
+ if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE ||
+ result == DNS_R_DYNAMIC)
+ result = ISC_R_SUCCESS;
+ return (result);
+}
+
+isc_result_t
+dns_zt_freezezones(dns_zt_t *zt, isc_boolean_t freeze) {
+ isc_result_t result, tresult;
+
+ REQUIRE(VALID_ZT(zt));
+
+ RWLOCK(&zt->rwlock, isc_rwlocktype_read);
+ result = dns_zt_apply2(zt, ISC_FALSE, &tresult, freezezones, &freeze);
+ RWUNLOCK(&zt->rwlock, isc_rwlocktype_read);
+ return ((result == ISC_R_SUCCESS) ? tresult : result);
+}
+
+static isc_result_t
+freezezones(dns_zone_t *zone, void *uap) {
+ isc_boolean_t freeze = *(isc_boolean_t *)uap;
+ isc_boolean_t frozen;
+ isc_result_t result = ISC_R_SUCCESS;
+ char classstr[DNS_RDATACLASS_FORMATSIZE];
+ char zonename[DNS_NAME_FORMATSIZE];
+ dns_view_t *view;
+ char *journal;
+ const char *vname;
+ const char *sep;
+ int level;
+
+ if (dns_zone_gettype(zone) != dns_zone_master)
+ return (ISC_R_SUCCESS);
+
+ frozen = dns_zone_getupdatedisabled(zone);
+ if (freeze) {
+ if (frozen)
+ result = DNS_R_FROZEN;
+ if (result == ISC_R_SUCCESS)
+ result = dns_zone_flush(zone);
+ if (result == ISC_R_SUCCESS) {
+ journal = dns_zone_getjournal(zone);
+ if (journal != NULL)
+ (void)isc_file_remove(journal);
+ }
+ } else {
+ if (frozen) {
+ result = dns_zone_load(zone);
+ if (result == DNS_R_CONTINUE ||
+ result == DNS_R_UPTODATE)
+ result = ISC_R_SUCCESS;
+ }
+ }
+ if (result == ISC_R_SUCCESS)
+ dns_zone_setupdatedisabled(zone, freeze);
+ view = dns_zone_getview(zone);
+ if (strcmp(view->name, "_bind") == 0 ||
+ strcmp(view->name, "_default") == 0)
+ {
+ vname = "";
+ sep = "";
+ } else {
+ vname = view->name;
+ sep = " ";
+ }
+ dns_rdataclass_format(dns_zone_getclass(zone), classstr,
+ sizeof(classstr));
+ dns_name_format(dns_zone_getorigin(zone), zonename, sizeof(zonename));
+ level = (result != ISC_R_SUCCESS) ? ISC_LOG_ERROR : ISC_LOG_DEBUG(1);
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
+ level, "%s zone '%s/%s'%s%s: %s",
+ freeze ? "freezing" : "thawing",
+ zonename, classstr, sep, vname,
+ isc_result_totext(result));
+ return (result);
+}
+
+isc_result_t
+dns_zt_apply(dns_zt_t *zt, isc_boolean_t stop,
+ isc_result_t (*action)(dns_zone_t *, void *), void *uap)
+{
+ return (dns_zt_apply2(zt, stop, NULL, action, uap));
+}
+
+isc_result_t
+dns_zt_apply2(dns_zt_t *zt, isc_boolean_t stop, isc_result_t *sub,
+ isc_result_t (*action)(dns_zone_t *, void *), void *uap)
+{
+ dns_rbtnode_t *node;
+ dns_rbtnodechain_t chain;
+ isc_result_t result, tresult = ISC_R_SUCCESS;
+ dns_zone_t *zone;
+
+ REQUIRE(VALID_ZT(zt));
+ REQUIRE(action != NULL);
+
+ dns_rbtnodechain_init(&chain, zt->mctx);
+ result = dns_rbtnodechain_first(&chain, zt->table, NULL, NULL);
+ if (result == ISC_R_NOTFOUND) {
+ /*
+ * The tree is empty.
+ */
+ result = ISC_R_NOMORE;
+ }
+ while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
+ result = dns_rbtnodechain_current(&chain, NULL, NULL,
+ &node);
+ if (result == ISC_R_SUCCESS) {
+ zone = node->data;
+ if (zone != NULL)
+ result = (action)(zone, uap);
+ if (result != ISC_R_SUCCESS && stop) {
+ tresult = result;
+ goto cleanup; /* don't break */
+ } else if (result != ISC_R_SUCCESS &&
+ tresult == ISC_R_SUCCESS)
+ tresult = result;
+ }
+ result = dns_rbtnodechain_next(&chain, NULL, NULL);
+ }
+ if (result == ISC_R_NOMORE)
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ dns_rbtnodechain_invalidate(&chain);
+ if (sub != NULL)
+ *sub = tresult;
+
+ return (result);
+}
+
+/***
+ *** Private
+ ***/
+
+static void
+auto_detach(void *data, void *arg) {
+ dns_zone_t *zone = data;
+
+ UNUSED(arg);
+
+ dns_zone_detach(&zone);
+}
diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in
new file mode 100644
index 0000000..c3ece84
--- /dev/null
+++ b/lib/isc/Makefile.in
@@ -0,0 +1,116 @@
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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: Makefile.in,v 1.96 2008/09/24 02:46:23 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@LIBISC_API@
+
+CINCLUDES = -I${srcdir}/unix/include \
+ -I${srcdir}/@ISC_THREAD_DIR@/include \
+ -I${srcdir}/@ISC_ARCH_DIR@/include \
+ -I./include \
+ -I${srcdir}/include
+CDEFINES =
+CWARNINGS =
+
+# Alphabetically
+UNIXOBJS = @ISC_ISCIPV6_O@ \
+ unix/app.@O@ unix/dir.@O@ unix/entropy.@O@ \
+ unix/errno2result.@O@ unix/file.@O@ unix/fsaccess.@O@ \
+ unix/interfaceiter.@O@ unix/keyboard.@O@ unix/net.@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@
+
+THREADOBJS = @ISC_THREAD_DIR@/condition.@O@ @ISC_THREAD_DIR@/mutex.@O@ \
+ @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@ 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@ iterated_hash.@O@ \
+ lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
+ md5.@O@ mem.@O@ mutexblock.@O@ \
+ netaddr.@O@ netscope.@O@ ondestroy.@O@ \
+ parseint.@O@ portset.@O@ quota.@O@ radix.@O@ random.@O@ \
+ ratelimiter.@O@ refcount.@O@ region.@O@ result.@O@ rwlock.@O@ \
+ serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ \
+ string.@O@ strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ \
+ timer.@O@ version.@O@ ${UNIXOBJS} ${NLSOBJS} ${THREADOBJS}
+
+# Alphabetically
+SRCS = @ISC_EXTRA_SRCS@ \
+ assertions.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 iterated_hash.c \
+ lex.c lfsr.c lib.c log.c \
+ md5.c mem.c mutexblock.c \
+ netaddr.c netscope.c ondestroy.c \
+ 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 string.c strtoul.c \
+ symtab.c task.c taskpool.c timer.c version.c
+
+LIBS = @LIBS@
+
+SUBDIRS = include unix nls @ISC_THREAD_DIR@ @ISC_ARCH_DIR@
+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
+
+libisc.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+libisc.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisc.la -rpath ${libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${LIBS}
+
+timestamp: libisc.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisc.@A@ ${DESTDIR}${libdir}
+
+clean distclean::
+ rm -f libisc.@A@ libisc.la timestamp
diff --git a/lib/isc/alpha/Makefile.in b/lib/isc/alpha/Makefile.in
new file mode 100644
index 0000000..324db07
--- /dev/null
+++ b/lib/isc/alpha/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = include
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/alpha/include/Makefile.in b/lib/isc/alpha/include/Makefile.in
new file mode 100644
index 0000000..f1d8bdd
--- /dev/null
+++ b/lib/isc/alpha/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/alpha/include/isc/Makefile.in b/lib/isc/alpha/include/isc/Makefile.in
new file mode 100644
index 0000000..5f116ca
--- /dev/null
+++ b/lib/isc/alpha/include/isc/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = atomic.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/alpha/include/isc/atomic.h b/lib/isc/alpha/include/isc/atomic.h
new file mode 100644
index 0000000..056d5fc
--- /dev/null
+++ b/lib/isc/alpha/include/isc/atomic.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2005, 2007 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: atomic.h,v 1.5 2007/06/19 23:47:17 tbox Exp $ */
+
+/*
+ * This code was written based on FreeBSD's kernel source whose copyright
+ * follows:
+ */
+
+/*-
+ * Copyright (c) 1998 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/alpha/include/atomic.h,v 1.18.6.1 2004/09/13 21:52:04 wilko Exp $
+ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_USEOSFASM
+#include <c_asm.h>
+
+#pragma intrinsic(asm)
+
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ */
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+ return (asm("1:"
+ "ldl_l %t0, 0(%a0);" /* load old value */
+ "mov %t0, %v0;" /* copy the old value */
+ "addl %t0, %a1, %t0;" /* calculate new value */
+ "stl_c %t0, 0(%a0);" /* attempt to store */
+ "beq %t0, 1b;", /* spin if failed */
+ p, val));
+}
+
+/*
+ * This routine atomically stores the value 'val' in 'p'.
+ */
+static inline void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+ (void)asm("1:"
+ "ldl_l %t0, 0(%a0);" /* load old value */
+ "mov %a1, %t0;" /* value to store */
+ "stl_c %t0, 0(%a0);" /* attempt to store */
+ "beq %t0, 1b;", /* spin if failed */
+ p, val);
+}
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'. The original value is returned in any
+ * case.
+ */
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+
+ return(asm("1:"
+ "ldl_l %t0, 0(%a0);" /* load old value */
+ "mov %t0, %v0;" /* copy the old value */
+ "cmpeq %t0, %a1, %t0;" /* compare */
+ "beq %t0, 2f;" /* exit if not equal */
+ "mov %a2, %t0;" /* value to store */
+ "stl_c %t0, 0(%a0);" /* attempt to store */
+ "beq %t0, 1b;" /* if it failed, spin */
+ "2:",
+ p, cmpval, val));
+}
+#elif defined (ISC_PLATFORM_USEGCCASM)
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+ isc_int32_t temp, prev;
+
+ __asm__ volatile(
+ "1:"
+ "ldl_l %0, %1;" /* load old value */
+ "mov %0, %2;" /* copy the old value */
+ "addl %0, %3, %0;" /* calculate new value */
+ "stl_c %0, %1;" /* attempt to store */
+ "beq %0, 1b;" /* spin if failed */
+ : "=&r"(temp), "+m"(*p), "=r"(prev)
+ : "r"(val)
+ : "memory");
+
+ return (prev);
+}
+
+static inline void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+ isc_int32_t temp;
+
+ __asm__ volatile(
+ "1:"
+ "ldl_l %0, %1;" /* load old value */
+ "mov %2, %0;" /* value to store */
+ "stl_c %0, %1;" /* attempt to store */
+ "beq %0, 1b;" /* if it failed, spin */
+ : "=&r"(temp), "+m"(*p)
+ : "r"(val)
+ : "memory");
+}
+
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+ isc_int32_t temp, prev;
+
+ __asm__ volatile(
+ "1:"
+ "ldl_l %0, %1;" /* load old value */
+ "mov %0, %2;" /* copy the old value */
+ "cmpeq %0, %3, %0;" /* compare */
+ "beq %0, 2f;" /* exit if not equal */
+ "mov %4, %0;" /* value to store */
+ "stl_c %0, %1;" /* attempt to store */
+ "beq %0, 1b;" /* if it failed, spin */
+ "2:"
+ : "=&r"(temp), "+m"(*p), "=r"(prev)
+ : "r"(cmpval), "r"(val)
+ : "memory");
+
+ return (prev);
+}
+#else
+
+#error "unsupported compiler. disable atomic ops by --disable-atomic"
+
+#endif
+
+#endif /* ISC_ATOMIC_H */
diff --git a/lib/isc/api b/lib/isc/api
new file mode 100644
index 0000000..2240cdd
--- /dev/null
+++ b/lib/isc/api
@@ -0,0 +1,3 @@
+LIBINTERFACE = 50
+LIBREVISION = 1
+LIBAGE = 0
diff --git a/lib/isc/assertions.c b/lib/isc/assertions.c
new file mode 100644
index 0000000..4c9251b
--- /dev/null
+++ b/lib/isc/assertions.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-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: assertions.c,v 1.23 2008/10/15 23:47:31 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/assertions.h>
+#include <isc/msgs.h>
+
+/*%
+ * Forward.
+ */
+/* coverity[+kill] */
+static void
+default_callback(const char *, int, isc_assertiontype_t, const char *);
+
+/*%
+ * Public.
+ */
+
+LIBISC_EXTERNAL_DATA isc_assertioncallback_t isc_assertion_failed =
+ default_callback;
+
+/*% Set callback. */
+void
+isc_assertion_setcallback(isc_assertioncallback_t cb) {
+ if (cb == NULL)
+ isc_assertion_failed = default_callback;
+ else
+ isc_assertion_failed = cb;
+}
+
+/*% Type to Text */
+const char *
+isc_assertion_typetotext(isc_assertiontype_t type) {
+ const char *result;
+
+ /*
+ * These strings have purposefully not been internationalized
+ * because they are considered to essentially be keywords of
+ * the ISC development environment.
+ */
+ switch (type) {
+ case isc_assertiontype_require:
+ result = "REQUIRE";
+ break;
+ case isc_assertiontype_ensure:
+ result = "ENSURE";
+ break;
+ case isc_assertiontype_insist:
+ result = "INSIST";
+ break;
+ case isc_assertiontype_invariant:
+ result = "INVARIANT";
+ break;
+ default:
+ result = NULL;
+ }
+ return (result);
+}
+
+/*
+ * Private.
+ */
+
+static void
+default_callback(const char *file, int line, isc_assertiontype_t type,
+ const char *cond)
+{
+ fprintf(stderr, "%s:%d: %s(%s) %s.\n",
+ file, line, isc_assertion_typetotext(type), cond,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ fflush(stderr);
+ abort();
+ /* NOTREACHED */
+}
diff --git a/lib/isc/base32.c b/lib/isc/base32.c
new file mode 100644
index 0000000..0deabc5
--- /dev/null
+++ b/lib/isc/base32.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2008 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: base32.c,v 1.3 2008/04/04 23:47:01 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/base32.h>
+#include <isc/buffer.h>
+#include <isc/lex.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#define RETERR(x) do { \
+ isc_result_t _r = (x); \
+ if (_r != ISC_R_SUCCESS) \
+ return (_r); \
+ } while (0)
+
+
+/*@{*/
+/*!
+ * These static functions are also present in lib/dns/rdata.c. I'm not
+ * sure where they should go. -- bwelling
+ */
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target);
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
+
+/*@}*/
+
+static const char base32[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=abcdefghijklmnopqrstuvwxyz234567";
+static const char base32hex[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv";
+
+static isc_result_t
+base32_totext(isc_region_t *source, int wordlength, const char *wordbreak,
+ isc_buffer_t *target, const char base[])
+{
+ char buf[9];
+ unsigned int loops = 0;
+
+ if (wordlength >= 0 && wordlength < 8)
+ wordlength = 8;
+
+ memset(buf, 0, sizeof(buf));
+ while (source->length > 0) {
+ buf[0] = base[((source->base[0]>>3)&0x1f)]; /* 5 + */
+ if (source->length == 1) {
+ buf[1] = base[(source->base[0]<<2)&0x1c];
+ buf[2] = buf[3] = buf[4] = '=';
+ buf[5] = buf[6] = buf[7] = '=';
+ RETERR(str_totext(buf, target));
+ break;
+ }
+ buf[1] = base[((source->base[0]<<2)&0x1c)| /* 3 = 8 */
+ ((source->base[1]>>6)&0x03)]; /* 2 + */
+ buf[2] = base[((source->base[1]>>1)&0x1f)]; /* 5 + */
+ if (source->length == 2) {
+ buf[3] = base[(source->base[1]<<4)&0x10];
+ buf[4] = buf[5] = buf[6] = buf[7] = '=';
+ RETERR(str_totext(buf, target));
+ break;
+ }
+ buf[3] = base[((source->base[1]<<4)&0x10)| /* 1 = 8 */
+ ((source->base[2]>>4)&0x0f)]; /* 4 + */
+ if (source->length == 3) {
+ buf[4] = base[(source->base[2]<<1)&0x1e];
+ buf[5] = buf[6] = buf[7] = '=';
+ RETERR(str_totext(buf, target));
+ break;
+ }
+ buf[4] = base[((source->base[2]<<1)&0x1e)| /* 4 = 8 */
+ ((source->base[3]>>7)&0x01)]; /* 1 + */
+ buf[5] = base[((source->base[3]>>2)&0x1f)]; /* 5 + */
+ if (source->length == 4) {
+ buf[6] = base[(source->base[3]<<3)&0x18];
+ buf[7] = '=';
+ RETERR(str_totext(buf, target));
+ break;
+ }
+ buf[6] = base[((source->base[3]<<3)&0x18)| /* 2 = 8 */
+ ((source->base[4]>>5)&0x07)]; /* 3 + */
+ buf[7] = base[source->base[4]&0x1f]; /* 5 = 8 */
+ RETERR(str_totext(buf, target));
+ isc_region_consume(source, 5);
+
+ loops++;
+ if (source->length != 0 && wordlength >= 0 &&
+ (int)((loops + 1) * 8) >= wordlength)
+ {
+ loops = 0;
+ RETERR(str_totext(wordbreak, target));
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base32_totext(isc_region_t *source, int wordlength,
+ const char *wordbreak, isc_buffer_t *target)
+{
+ return (base32_totext(source, wordlength, wordbreak, target, base32));
+}
+
+isc_result_t
+isc_base32hex_totext(isc_region_t *source, int wordlength,
+ const char *wordbreak, isc_buffer_t *target)
+{
+ return (base32_totext(source, wordlength, wordbreak, target,
+ base32hex));
+}
+
+/*%
+ * State of a base32 decoding process in progress.
+ */
+typedef struct {
+ int length; /*%< Desired length of binary data or -1 */
+ isc_buffer_t *target; /*%< Buffer for resulting binary data */
+ int digits; /*%< Number of buffered base32 digits */
+ isc_boolean_t seen_end; /*%< True if "=" end marker seen */
+ int val[8];
+ const char *base; /*%< Which encoding we are using */
+ int seen_32; /*%< Number of significant bytes if non zero */
+} base32_decode_ctx_t;
+
+static inline void
+base32_decode_init(base32_decode_ctx_t *ctx, int length,
+ const char base[], isc_buffer_t *target)
+{
+ ctx->digits = 0;
+ ctx->seen_end = ISC_FALSE;
+ ctx->seen_32 = 0;
+ ctx->length = length;
+ ctx->target = target;
+ ctx->base = base;
+}
+
+static inline isc_result_t
+base32_decode_char(base32_decode_ctx_t *ctx, int c) {
+ char *s;
+ unsigned int last;
+
+ if (ctx->seen_end)
+ return (ISC_R_BADBASE32);
+ if ((s = strchr(ctx->base, c)) == NULL)
+ return (ISC_R_BADBASE32);
+ last = s - ctx->base;
+ /*
+ * Handle lower case.
+ */
+ if (last > 32)
+ last -= 33;
+ /*
+ * Check that padding is contigious.
+ */
+ if (last != 32 && ctx->seen_32 != 0)
+ return (ISC_R_BADBASE32);
+ /*
+ * Check that padding starts at the right place and that
+ * bits that should be zero are.
+ * Record how many significant bytes in answer (seen_32).
+ */
+ if (last == 32 && ctx->seen_32 == 0)
+ switch (ctx->digits) {
+ case 0:
+ case 1:
+ return (ISC_R_BADBASE32);
+ case 2:
+ if ((ctx->val[1]&0x03) != 0)
+ return (ISC_R_BADBASE32);
+ ctx->seen_32 = 1;
+ break;
+ case 3:
+ return (ISC_R_BADBASE32);
+ case 4:
+ if ((ctx->val[3]&0x0f) != 0)
+ return (ISC_R_BADBASE32);
+ ctx->seen_32 = 3;
+ break;
+ case 5:
+ if ((ctx->val[4]&0x01) != 0)
+ return (ISC_R_BADBASE32);
+ ctx->seen_32 = 3;
+ break;
+ case 6:
+ return (ISC_R_BADBASE32);
+ case 7:
+ if ((ctx->val[6]&0x07) != 0)
+ return (ISC_R_BADBASE32);
+ ctx->seen_32 = 4;
+ break;
+ }
+ /*
+ * Zero fill pad values.
+ */
+ ctx->val[ctx->digits++] = (last == 32) ? 0 : last;
+
+ if (ctx->digits == 8) {
+ int n = 5;
+ unsigned char buf[5];
+
+ if (ctx->seen_32 != 0) {
+ ctx->seen_end = ISC_TRUE;
+ n = ctx->seen_32;
+ }
+ buf[0] = (ctx->val[0]<<3)|(ctx->val[1]>>2);
+ buf[1] = (ctx->val[1]<<6)|(ctx->val[2]<<1)|(ctx->val[3]>>4);
+ buf[2] = (ctx->val[3]<<4)|(ctx->val[4]>>1);
+ buf[3] = (ctx->val[4]<<7)|(ctx->val[5]<<2)|(ctx->val[6]>>3);
+ buf[4] = (ctx->val[6]<<5)|(ctx->val[7]);
+ RETERR(mem_tobuffer(ctx->target, buf, n));
+ if (ctx->length >= 0) {
+ if (n > ctx->length)
+ return (ISC_R_BADBASE32);
+ else
+ ctx->length -= n;
+ }
+ ctx->digits = 0;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+base32_decode_finish(base32_decode_ctx_t *ctx) {
+ if (ctx->length > 0)
+ return (ISC_R_UNEXPECTEDEND);
+ if (ctx->digits != 0)
+ return (ISC_R_BADBASE32);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+base32_tobuffer(isc_lex_t *lexer, const char base[], isc_buffer_t *target,
+ int length)
+{
+ base32_decode_ctx_t ctx;
+ isc_textregion_t *tr;
+ isc_token_t token;
+ isc_boolean_t eol;
+
+ base32_decode_init(&ctx, length, base, target);
+
+ while (!ctx.seen_end && (ctx.length != 0)) {
+ unsigned int i;
+
+ if (length > 0)
+ eol = ISC_FALSE;
+ else
+ eol = ISC_TRUE;
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, eol));
+ if (token.type != isc_tokentype_string)
+ break;
+ tr = &token.value.as_textregion;
+ for (i = 0; i < tr->length; i++)
+ RETERR(base32_decode_char(&ctx, tr->base[i]));
+ }
+ if (ctx.length < 0 && !ctx.seen_end)
+ isc_lex_ungettoken(lexer, &token);
+ RETERR(base32_decode_finish(&ctx));
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
+ return (base32_tobuffer(lexer, base32, target, length));
+}
+
+isc_result_t
+isc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
+ return (base32_tobuffer(lexer, base32hex, target, length));
+}
+
+static isc_result_t
+base32_decodestring(const char *cstr, const char base[], isc_buffer_t *target) {
+ base32_decode_ctx_t ctx;
+
+ base32_decode_init(&ctx, -1, base, target);
+ for (;;) {
+ int c = *cstr++;
+ if (c == '\0')
+ break;
+ if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
+ continue;
+ RETERR(base32_decode_char(&ctx, c));
+ }
+ RETERR(base32_decode_finish(&ctx));
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base32_decodestring(const char *cstr, isc_buffer_t *target) {
+ return (base32_decodestring(cstr, base32, target));
+}
+
+isc_result_t
+isc_base32hex_decodestring(const char *cstr, isc_buffer_t *target) {
+ return (base32_decodestring(cstr, base32hex, target));
+}
+
+static isc_result_t
+base32_decoderegion(isc_region_t *source, const char base[], isc_buffer_t *target) {
+ base32_decode_ctx_t ctx;
+
+ base32_decode_init(&ctx, -1, base, target);
+ while (source->length != 0) {
+ int c = *source->base;
+ RETERR(base32_decode_char(&ctx, c));
+ isc_region_consume(source, 1);
+ }
+ RETERR(base32_decode_finish(&ctx));
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target) {
+ return (base32_decoderegion(source, base32, target));
+}
+
+isc_result_t
+isc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target) {
+ return (base32_decoderegion(source, base32hex, target));
+}
+
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target) {
+ unsigned int l;
+ isc_region_t region;
+
+ isc_buffer_availableregion(target, &region);
+ l = strlen(source);
+
+ if (l > region.length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(region.base, source, l);
+ isc_buffer_add(target, l);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
+ isc_region_t tr;
+
+ isc_buffer_availableregion(target, &tr);
+ if (length > tr.length)
+ return (ISC_R_NOSPACE);
+ memcpy(tr.base, base, length);
+ isc_buffer_add(target, length);
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/base64.c b/lib/isc/base64.c
new file mode 100644
index 0000000..13ed6b5
--- /dev/null
+++ b/lib/isc/base64.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: base64.c,v 1.32 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/lex.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#define RETERR(x) do { \
+ isc_result_t _r = (x); \
+ if (_r != ISC_R_SUCCESS) \
+ return (_r); \
+ } while (0)
+
+
+/*@{*/
+/*!
+ * These static functions are also present in lib/dns/rdata.c. I'm not
+ * sure where they should go. -- bwelling
+ */
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target);
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
+
+static const char base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+/*@}*/
+
+isc_result_t
+isc_base64_totext(isc_region_t *source, int wordlength,
+ const char *wordbreak, isc_buffer_t *target)
+{
+ char buf[5];
+ unsigned int loops = 0;
+
+ if (wordlength < 4)
+ wordlength = 4;
+
+ memset(buf, 0, sizeof(buf));
+ while (source->length > 2) {
+ buf[0] = base64[(source->base[0]>>2)&0x3f];
+ buf[1] = base64[((source->base[0]<<4)&0x30)|
+ ((source->base[1]>>4)&0x0f)];
+ buf[2] = base64[((source->base[1]<<2)&0x3c)|
+ ((source->base[2]>>6)&0x03)];
+ buf[3] = base64[source->base[2]&0x3f];
+ RETERR(str_totext(buf, target));
+ isc_region_consume(source, 3);
+
+ loops++;
+ if (source->length != 0 &&
+ (int)((loops + 1) * 4) >= wordlength)
+ {
+ loops = 0;
+ RETERR(str_totext(wordbreak, target));
+ }
+ }
+ if (source->length == 2) {
+ buf[0] = base64[(source->base[0]>>2)&0x3f];
+ buf[1] = base64[((source->base[0]<<4)&0x30)|
+ ((source->base[1]>>4)&0x0f)];
+ buf[2] = base64[((source->base[1]<<2)&0x3c)];
+ buf[3] = '=';
+ RETERR(str_totext(buf, target));
+ } else if (source->length == 1) {
+ buf[0] = base64[(source->base[0]>>2)&0x3f];
+ buf[1] = base64[((source->base[0]<<4)&0x30)];
+ buf[2] = buf[3] = '=';
+ RETERR(str_totext(buf, target));
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * State of a base64 decoding process in progress.
+ */
+typedef struct {
+ int length; /*%< Desired length of binary data or -1 */
+ isc_buffer_t *target; /*%< Buffer for resulting binary data */
+ int digits; /*%< Number of buffered base64 digits */
+ isc_boolean_t seen_end; /*%< True if "=" end marker seen */
+ int val[4];
+} base64_decode_ctx_t;
+
+static inline void
+base64_decode_init(base64_decode_ctx_t *ctx, int length, isc_buffer_t *target)
+{
+ ctx->digits = 0;
+ ctx->seen_end = ISC_FALSE;
+ ctx->length = length;
+ ctx->target = target;
+}
+
+static inline isc_result_t
+base64_decode_char(base64_decode_ctx_t *ctx, int c) {
+ char *s;
+
+ if (ctx->seen_end)
+ return (ISC_R_BADBASE64);
+ if ((s = strchr(base64, c)) == NULL)
+ return (ISC_R_BADBASE64);
+ ctx->val[ctx->digits++] = s - base64;
+ if (ctx->digits == 4) {
+ int n;
+ unsigned char buf[3];
+ if (ctx->val[0] == 64 || ctx->val[1] == 64)
+ return (ISC_R_BADBASE64);
+ if (ctx->val[2] == 64 && ctx->val[3] != 64)
+ return (ISC_R_BADBASE64);
+ /*
+ * Check that bits that should be zero are.
+ */
+ if (ctx->val[2] == 64 && (ctx->val[1] & 0xf) != 0)
+ return (ISC_R_BADBASE64);
+ /*
+ * We don't need to test for ctx->val[2] != 64 as
+ * the bottom two bits of 64 are zero.
+ */
+ if (ctx->val[3] == 64 && (ctx->val[2] & 0x3) != 0)
+ return (ISC_R_BADBASE64);
+ n = (ctx->val[2] == 64) ? 1 :
+ (ctx->val[3] == 64) ? 2 : 3;
+ if (n != 3) {
+ ctx->seen_end = ISC_TRUE;
+ if (ctx->val[2] == 64)
+ ctx->val[2] = 0;
+ if (ctx->val[3] == 64)
+ ctx->val[3] = 0;
+ }
+ buf[0] = (ctx->val[0]<<2)|(ctx->val[1]>>4);
+ buf[1] = (ctx->val[1]<<4)|(ctx->val[2]>>2);
+ buf[2] = (ctx->val[2]<<6)|(ctx->val[3]);
+ RETERR(mem_tobuffer(ctx->target, buf, n));
+ if (ctx->length >= 0) {
+ if (n > ctx->length)
+ return (ISC_R_BADBASE64);
+ else
+ ctx->length -= n;
+ }
+ ctx->digits = 0;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+base64_decode_finish(base64_decode_ctx_t *ctx) {
+ if (ctx->length > 0)
+ return (ISC_R_UNEXPECTEDEND);
+ if (ctx->digits != 0)
+ return (ISC_R_BADBASE64);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
+ base64_decode_ctx_t ctx;
+ isc_textregion_t *tr;
+ isc_token_t token;
+ isc_boolean_t eol;
+
+ base64_decode_init(&ctx, length, target);
+
+ while (!ctx.seen_end && (ctx.length != 0)) {
+ unsigned int i;
+
+ if (length > 0)
+ eol = ISC_FALSE;
+ else
+ eol = ISC_TRUE;
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, eol));
+ if (token.type != isc_tokentype_string)
+ break;
+ tr = &token.value.as_textregion;
+ for (i = 0; i < tr->length; i++)
+ RETERR(base64_decode_char(&ctx, tr->base[i]));
+ }
+ if (ctx.length < 0 && !ctx.seen_end)
+ isc_lex_ungettoken(lexer, &token);
+ RETERR(base64_decode_finish(&ctx));
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_base64_decodestring(const char *cstr, isc_buffer_t *target) {
+ base64_decode_ctx_t ctx;
+
+ base64_decode_init(&ctx, -1, target);
+ for (;;) {
+ int c = *cstr++;
+ if (c == '\0')
+ break;
+ if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
+ continue;
+ RETERR(base64_decode_char(&ctx, c));
+ }
+ RETERR(base64_decode_finish(&ctx));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target) {
+ unsigned int l;
+ isc_region_t region;
+
+ isc_buffer_availableregion(target, &region);
+ l = strlen(source);
+
+ if (l > region.length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(region.base, source, l);
+ isc_buffer_add(target, l);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
+ isc_region_t tr;
+
+ isc_buffer_availableregion(target, &tr);
+ if (length > tr.length)
+ return (ISC_R_NOSPACE);
+ memcpy(tr.base, base, length);
+ isc_buffer_add(target, length);
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/bitstring.c b/lib/isc/bitstring.c
new file mode 100644
index 0000000..33c7c1f
--- /dev/null
+++ b/lib/isc/bitstring.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: bitstring.c,v 1.17 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/magic.h>
+#include <isc/bitstring.h>
+#include <isc/util.h>
+
+#define DIV8(x) ((x) >> 3)
+#define MOD8(x) ((x) & 0x00000007U)
+#define OCTETS(n) (((n) + 7) >> 3)
+#define PADDED(n) ((((n) + 7) >> 3) << 3)
+#define BITSET(bs, n) (((bs)->data[DIV8(n)] & \
+ (1 << (7 - MOD8(n)))) != 0)
+#define SETBIT(bs, n) (bs)->data[DIV8(n)] |= (1 << (7 - MOD8(n)))
+#define CLEARBIT(bs, n) (bs)->data[DIV8(n)] &= ~(1 << (7 - MOD8(n)))
+
+#define BITSTRING_MAGIC ISC_MAGIC('B', 'S', 't', 'r')
+#define VALID_BITSTRING(b) ISC_MAGIC_VALID(b, BITSTRING_MAGIC)
+
+void
+isc_bitstring_init(isc_bitstring_t *bitstring, unsigned char *data,
+ unsigned int length, unsigned int size, isc_boolean_t lsb0)
+{
+ /*
+ * Make 'bitstring' refer to the bitstring of 'size' bits starting
+ * at 'data'. 'length' bits of the bitstring are valid. If 'lsb0'
+ * is set then, bit 0 refers to the least significant bit of the
+ * bitstring. Otherwise bit 0 is the most significant bit.
+ */
+
+ REQUIRE(bitstring != NULL);
+ REQUIRE(data != NULL);
+ REQUIRE(length <= size);
+
+ bitstring->magic = BITSTRING_MAGIC;
+ bitstring->data = data;
+ bitstring->length = length;
+ bitstring->size = size;
+ bitstring->lsb0 = lsb0;
+}
+
+void
+isc_bitstring_invalidate(isc_bitstring_t *bitstring) {
+
+ /*
+ * Invalidate 'bitstring'.
+ */
+
+ REQUIRE(VALID_BITSTRING(bitstring));
+
+ bitstring->magic = 0;
+ bitstring->data = NULL;
+ bitstring->length = 0;
+ bitstring->size = 0;
+ bitstring->lsb0 = ISC_FALSE;
+}
+
+void
+isc_bitstring_copy(isc_bitstring_t *source, unsigned int sbitpos,
+ isc_bitstring_t *target, unsigned int tbitpos,
+ unsigned int n)
+{
+ unsigned int tlast;
+
+ /*
+ * Starting at bit 'sbitpos', copy 'n' bits from 'source' to
+ * the 'n' bits of 'target' starting at 'tbitpos'.
+ */
+
+ REQUIRE(VALID_BITSTRING(source));
+ REQUIRE(VALID_BITSTRING(target));
+ REQUIRE(source->lsb0 == target->lsb0);
+ if (source->lsb0) {
+ REQUIRE(sbitpos <= source->length);
+ sbitpos = PADDED(source->size) - sbitpos;
+ REQUIRE(sbitpos >= n);
+ sbitpos -= n;
+ } else
+ REQUIRE(sbitpos + n <= source->length);
+ tlast = tbitpos + n;
+ if (target->lsb0) {
+ REQUIRE(tbitpos <= target->length);
+ tbitpos = PADDED(target->size) - tbitpos;
+ REQUIRE(tbitpos >= n);
+ tbitpos -= n;
+ } else
+ REQUIRE(tlast <= target->size);
+
+ if (tlast > target->length)
+ target->length = tlast;
+
+ /*
+ * This is far from optimal...
+ */
+
+ while (n > 0) {
+ if (BITSET(source, sbitpos))
+ SETBIT(target, tbitpos);
+ else
+ CLEARBIT(target, tbitpos);
+ sbitpos++;
+ tbitpos++;
+ n--;
+ }
+}
diff --git a/lib/isc/buffer.c b/lib/isc/buffer.c
new file mode 100644
index 0000000..1b59e65
--- /dev/null
+++ b/lib/isc/buffer.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: buffer.c,v 1.49 2008/09/25 04:02:39 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/mem.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+void
+isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length) {
+ /*
+ * Make 'b' refer to the 'length'-byte region starting at 'base'.
+ * XXXDCL see the comment in buffer.h about base being const.
+ */
+
+ REQUIRE(b != NULL);
+
+ ISC__BUFFER_INIT(b, base, length);
+}
+
+void
+isc__buffer_initnull(isc_buffer_t *b) {
+ /*
+ * Initialize a new buffer which has no backing store. This can
+ * later be grown as needed and swapped in place.
+ */
+
+ ISC__BUFFER_INIT(b, NULL, 0);
+}
+
+void
+isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length) {
+ /*
+ * Re-initialize the buffer enough to reconfigure the base of the
+ * buffer. We will swap in the new buffer, after copying any
+ * data we contain into the new buffer and adjusting all of our
+ * internal pointers.
+ *
+ * The buffer must not be smaller than the length of the original
+ * buffer.
+ */
+ REQUIRE(b->length <= length);
+ REQUIRE(base != NULL);
+
+ (void)memmove(base, b->base, b->length);
+ b->base = base;
+ b->length = length;
+}
+
+void
+isc__buffer_invalidate(isc_buffer_t *b) {
+ /*
+ * Make 'b' an invalid buffer.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(!ISC_LINK_LINKED(b, link));
+ REQUIRE(b->mctx == NULL);
+
+ ISC__BUFFER_INVALIDATE(b);
+}
+
+void
+isc__buffer_region(isc_buffer_t *b, isc_region_t *r) {
+ /*
+ * Make 'r' refer to the region of 'b'.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(r != NULL);
+
+ ISC__BUFFER_REGION(b, r);
+}
+
+void
+isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r) {
+ /*
+ * Make 'r' refer to the used region of 'b'.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(r != NULL);
+
+ ISC__BUFFER_USEDREGION(b, r);
+}
+
+void
+isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r) {
+ /*
+ * Make 'r' refer to the available region of 'b'.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(r != NULL);
+
+ ISC__BUFFER_AVAILABLEREGION(b, r);
+}
+
+void
+isc__buffer_add(isc_buffer_t *b, unsigned int n) {
+ /*
+ * Increase the 'used' region of 'b' by 'n' bytes.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used + n <= b->length);
+
+ ISC__BUFFER_ADD(b, n);
+}
+
+void
+isc__buffer_subtract(isc_buffer_t *b, unsigned int n) {
+ /*
+ * Decrease the 'used' region of 'b' by 'n' bytes.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used >= n);
+
+ ISC__BUFFER_SUBTRACT(b, n);
+}
+
+void
+isc__buffer_clear(isc_buffer_t *b) {
+ /*
+ * Make the used region empty.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+
+ ISC__BUFFER_CLEAR(b);
+}
+
+void
+isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r) {
+ /*
+ * Make 'r' refer to the consumed region of 'b'.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(r != NULL);
+
+ ISC__BUFFER_CONSUMEDREGION(b, r);
+}
+
+void
+isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r) {
+ /*
+ * Make 'r' refer to the remaining region of 'b'.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(r != NULL);
+
+ ISC__BUFFER_REMAININGREGION(b, r);
+}
+
+void
+isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r) {
+ /*
+ * Make 'r' refer to the active region of 'b'.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(r != NULL);
+
+ ISC__BUFFER_ACTIVEREGION(b, r);
+}
+
+void
+isc__buffer_setactive(isc_buffer_t *b, unsigned int n) {
+ /*
+ * Sets the end of the active region 'n' bytes after current.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->current + n <= b->used);
+
+ ISC__BUFFER_SETACTIVE(b, n);
+}
+
+void
+isc__buffer_first(isc_buffer_t *b) {
+ /*
+ * Make the consumed region empty.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+
+ ISC__BUFFER_FIRST(b);
+}
+
+void
+isc__buffer_forward(isc_buffer_t *b, unsigned int n) {
+ /*
+ * Increase the 'consumed' region of 'b' by 'n' bytes.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->current + n <= b->used);
+
+ ISC__BUFFER_FORWARD(b, n);
+}
+
+void
+isc__buffer_back(isc_buffer_t *b, unsigned int n) {
+ /*
+ * Decrease the 'consumed' region of 'b' by 'n' bytes.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(n <= b->current);
+
+ ISC__BUFFER_BACK(b, n);
+}
+
+void
+isc_buffer_compact(isc_buffer_t *b) {
+ unsigned int length;
+ void *src;
+
+ /*
+ * Compact the used region by moving the remaining region so it occurs
+ * at the start of the buffer. The used region is shrunk by the size
+ * of the consumed region, and the consumed region is then made empty.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+
+ src = isc_buffer_current(b);
+ length = isc_buffer_remaininglength(b);
+ (void)memmove(b->base, src, (size_t)length);
+
+ if (b->active > b->current)
+ b->active -= b->current;
+ else
+ b->active = 0;
+ b->current = 0;
+ b->used = length;
+}
+
+isc_uint8_t
+isc_buffer_getuint8(isc_buffer_t *b) {
+ unsigned char *cp;
+ isc_uint8_t result;
+
+ /*
+ * Read an unsigned 8-bit integer from 'b' and return it.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used - b->current >= 1);
+
+ cp = isc_buffer_current(b);
+ b->current += 1;
+ result = ((isc_uint8_t)(cp[0]));
+
+ return (result);
+}
+
+void
+isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val) {
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used + 1 <= b->length);
+
+ ISC__BUFFER_PUTUINT8(b, val);
+}
+
+isc_uint16_t
+isc_buffer_getuint16(isc_buffer_t *b) {
+ unsigned char *cp;
+ isc_uint16_t result;
+
+ /*
+ * Read an unsigned 16-bit integer in network byte order from 'b',
+ * convert it to host byte order, and return it.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used - b->current >= 2);
+
+ cp = isc_buffer_current(b);
+ b->current += 2;
+ result = ((unsigned int)(cp[0])) << 8;
+ result |= ((unsigned int)(cp[1]));
+
+ return (result);
+}
+
+void
+isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val) {
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used + 2 <= b->length);
+
+ ISC__BUFFER_PUTUINT16(b, val);
+}
+
+void
+isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val) {
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used + 3 <= b->length);
+
+ ISC__BUFFER_PUTUINT24(b, val);
+}
+
+isc_uint32_t
+isc_buffer_getuint32(isc_buffer_t *b) {
+ unsigned char *cp;
+ isc_uint32_t result;
+
+ /*
+ * Read an unsigned 32-bit integer in network byte order from 'b',
+ * convert it to host byte order, and return it.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used - b->current >= 4);
+
+ cp = isc_buffer_current(b);
+ b->current += 4;
+ result = ((unsigned int)(cp[0])) << 24;
+ result |= ((unsigned int)(cp[1])) << 16;
+ result |= ((unsigned int)(cp[2])) << 8;
+ result |= ((unsigned int)(cp[3]));
+
+ return (result);
+}
+
+void
+isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val) {
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used + 4 <= b->length);
+
+ ISC__BUFFER_PUTUINT32(b, val);
+}
+
+isc_uint64_t
+isc_buffer_getuint48(isc_buffer_t *b) {
+ unsigned char *cp;
+ isc_uint64_t result;
+
+ /*
+ * Read an unsigned 48-bit integer in network byte order from 'b',
+ * convert it to host byte order, and return it.
+ */
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used - b->current >= 6);
+
+ cp = isc_buffer_current(b);
+ b->current += 6;
+ result = ((isc_int64_t)(cp[0])) << 40;
+ result |= ((isc_int64_t)(cp[1])) << 32;
+ result |= ((isc_int64_t)(cp[2])) << 24;
+ result |= ((isc_int64_t)(cp[3])) << 16;
+ result |= ((isc_int64_t)(cp[4])) << 8;
+ result |= ((isc_int64_t)(cp[5]));
+
+ return (result);
+}
+
+void
+isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val) {
+ isc_uint16_t valhi;
+ isc_uint32_t vallo;
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used + 6 <= b->length);
+
+ valhi = (isc_uint16_t)(val >> 32);
+ vallo = (isc_uint32_t)(val & 0xFFFFFFFF);
+ ISC__BUFFER_PUTUINT16(b, valhi);
+ ISC__BUFFER_PUTUINT32(b, vallo);
+}
+
+void
+isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
+ unsigned int length)
+{
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(b->used + length <= b->length);
+
+ ISC__BUFFER_PUTMEM(b, base, length);
+}
+
+void
+isc__buffer_putstr(isc_buffer_t *b, const char *source) {
+ unsigned int l;
+ unsigned char *cp;
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(source != NULL);
+
+ /*
+ * Do not use ISC__BUFFER_PUTSTR(), so strlen is only done once.
+ */
+ l = strlen(source);
+
+ REQUIRE(l <= isc_buffer_availablelength(b));
+
+ cp = isc_buffer_used(b);
+ memcpy(cp, source, l);
+ b->used += l;
+}
+
+isc_result_t
+isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r) {
+ unsigned char *base;
+ unsigned int available;
+
+ REQUIRE(ISC_BUFFER_VALID(b));
+ REQUIRE(r != NULL);
+
+ /*
+ * XXXDCL
+ */
+ base = isc_buffer_used(b);
+ available = isc_buffer_availablelength(b);
+ if (r->length > available)
+ return (ISC_R_NOSPACE);
+ memcpy(base, r->base, r->length);
+ b->used += r->length;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
+ unsigned int length)
+{
+ isc_buffer_t *dbuf;
+
+ REQUIRE(dynbuffer != NULL);
+ REQUIRE(*dynbuffer == NULL);
+
+ dbuf = isc_mem_get(mctx, length + sizeof(isc_buffer_t));
+ if (dbuf == NULL)
+ return (ISC_R_NOMEMORY);
+
+ isc_buffer_init(dbuf, ((unsigned char *)dbuf) + sizeof(isc_buffer_t),
+ length);
+ dbuf->mctx = mctx;
+
+ *dynbuffer = dbuf;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_buffer_free(isc_buffer_t **dynbuffer) {
+ unsigned int real_length;
+ isc_buffer_t *dbuf;
+ isc_mem_t *mctx;
+
+ REQUIRE(dynbuffer != NULL);
+ REQUIRE(ISC_BUFFER_VALID(*dynbuffer));
+ REQUIRE((*dynbuffer)->mctx != NULL);
+
+ dbuf = *dynbuffer;
+ *dynbuffer = NULL; /* destroy external reference */
+
+ real_length = dbuf->length + sizeof(isc_buffer_t);
+ mctx = dbuf->mctx;
+ dbuf->mctx = NULL;
+ isc_buffer_invalidate(dbuf);
+
+ isc_mem_put(mctx, dbuf, real_length);
+}
diff --git a/lib/isc/bufferlist.c b/lib/isc/bufferlist.c
new file mode 100644
index 0000000..0e5c125
--- /dev/null
+++ b/lib/isc/bufferlist.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: bufferlist.c,v 1.17 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/buffer.h>
+#include <isc/bufferlist.h>
+#include <isc/util.h>
+
+unsigned int
+isc_bufferlist_usedcount(isc_bufferlist_t *bl) {
+ isc_buffer_t *buffer;
+ unsigned int length;
+
+ REQUIRE(bl != NULL);
+
+ length = 0;
+ buffer = ISC_LIST_HEAD(*bl);
+ while (buffer != NULL) {
+ REQUIRE(ISC_BUFFER_VALID(buffer));
+ length += isc_buffer_usedlength(buffer);
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+
+ return (length);
+}
+
+unsigned int
+isc_bufferlist_availablecount(isc_bufferlist_t *bl) {
+ isc_buffer_t *buffer;
+ unsigned int length;
+
+ REQUIRE(bl != NULL);
+
+ length = 0;
+ buffer = ISC_LIST_HEAD(*bl);
+ while (buffer != NULL) {
+ REQUIRE(ISC_BUFFER_VALID(buffer));
+ length += isc_buffer_availablelength(buffer);
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+
+ return (length);
+}
diff --git a/lib/isc/commandline.c b/lib/isc/commandline.c
new file mode 100644
index 0000000..aca1203
--- /dev/null
+++ b/lib/isc/commandline.c
@@ -0,0 +1,225 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007, 2008 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
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: commandline.c,v 1.22 2008/09/25 04:02:39 tbox Exp $ */
+
+/*! \file
+ * This file was adapted from the NetBSD project's source tree, RCS ID:
+ * NetBSD: getopt.c,v 1.15 1999/09/20 04:39:37 lukem Exp
+ *
+ * The primary change has been to rename items to the ISC namespace
+ * and format in the ISC coding style.
+ */
+
+/*
+ * \author Principal Authors: Computer Systems Research Group at UC Berkeley
+ * \author Principal ISC caretaker: DCL
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/commandline.h>
+#include <isc/msgs.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/*% Index into parent argv vector. */
+LIBISC_EXTERNAL_DATA int isc_commandline_index = 1;
+/*% Character checked for validity. */
+LIBISC_EXTERNAL_DATA int isc_commandline_option;
+/*% Argument associated with option. */
+LIBISC_EXTERNAL_DATA char *isc_commandline_argument;
+/*% For printing error messages. */
+LIBISC_EXTERNAL_DATA char *isc_commandline_progname;
+/*% Print error messages. */
+LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_errprint = ISC_TRUE;
+/*% Reset processing. */
+LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_reset = ISC_TRUE;
+
+static char endopt = '\0';
+
+#define BADOPT '?'
+#define BADARG ':'
+#define ENDOPT &endopt
+
+/*!
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int
+isc_commandline_parse(int argc, char * const *argv, const char *options) {
+ static char *place = ENDOPT;
+ char *option; /* Index into *options of option. */
+
+ REQUIRE(argc >= 0 && argv != NULL && options != NULL);
+
+ /*
+ * Update scanning pointer, either because a reset was requested or
+ * the previous argv was finished.
+ */
+ if (isc_commandline_reset || *place == '\0') {
+ if (isc_commandline_reset) {
+ isc_commandline_index = 1;
+ isc_commandline_reset = ISC_FALSE;
+ }
+
+ if (isc_commandline_progname == NULL)
+ isc_commandline_progname = argv[0];
+
+ if (isc_commandline_index >= argc ||
+ *(place = argv[isc_commandline_index]) != '-') {
+ /*
+ * Index out of range or points to non-option.
+ */
+ place = ENDOPT;
+ return (-1);
+ }
+
+ if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+ /*
+ * Found '--' to signal end of options. Advance
+ * index to next argv, the first non-option.
+ */
+ isc_commandline_index++;
+ place = ENDOPT;
+ return (-1);
+ }
+ }
+
+ isc_commandline_option = *place++;
+ option = strchr(options, isc_commandline_option);
+
+ /*
+ * Ensure valid option has been passed as specified by options string.
+ * '-:' is never a valid command line option because it could not
+ * distinguish ':' from the argument specifier in the options string.
+ */
+ if (isc_commandline_option == ':' || option == NULL) {
+ if (*place == '\0')
+ isc_commandline_index++;
+
+ if (isc_commandline_errprint && *options != ':')
+ fprintf(stderr, "%s: %s -- %c\n",
+ isc_commandline_progname,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_COMMANDLINE,
+ ISC_MSG_ILLEGALOPT,
+ "illegal option"),
+ isc_commandline_option);
+
+ return (BADOPT);
+ }
+
+ if (*++option != ':') {
+ /*
+ * Option does not take an argument.
+ */
+ isc_commandline_argument = NULL;
+
+ /*
+ * Skip to next argv if at the end of the current argv.
+ */
+ if (*place == '\0')
+ ++isc_commandline_index;
+
+ } else {
+ /*
+ * Option needs an argument.
+ */
+ if (*place != '\0')
+ /*
+ * Option is in this argv, -D1 style.
+ */
+ isc_commandline_argument = place;
+
+ else if (argc > ++isc_commandline_index)
+ /*
+ * Option is next argv, -D 1 style.
+ */
+ isc_commandline_argument = argv[isc_commandline_index];
+
+ else {
+ /*
+ * Argument needed, but no more argv.
+ */
+ place = ENDOPT;
+
+ /*
+ * Silent failure with "missing argument" return
+ * when ':' starts options string, per historical spec.
+ */
+ if (*options == ':')
+ return (BADARG);
+
+ if (isc_commandline_errprint)
+ fprintf(stderr, "%s: %s -- %c\n",
+ isc_commandline_progname,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_COMMANDLINE,
+ ISC_MSG_OPTNEEDARG,
+ "option requires "
+ "an argument"),
+ isc_commandline_option);
+
+ return (BADOPT);
+ }
+
+ place = ENDOPT;
+
+ /*
+ * Point to argv that follows argument.
+ */
+ isc_commandline_index++;
+ }
+
+ return (isc_commandline_option);
+}
diff --git a/lib/isc/entropy.c b/lib/isc/entropy.c
new file mode 100644
index 0000000..cb578f0
--- /dev/null
+++ b/lib/isc/entropy.c
@@ -0,0 +1,1274 @@
+/*
+ * Copyright (C) 2004-2007 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: entropy.c,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * This is the system independent part of the entropy module. It is
+ * compiled via inclusion from the relevant OS source file, ie,
+ * \link unix/entropy.c unix/entropy.c \endlink or win32/entropy.c.
+ *
+ * \author Much of this code is modeled after the NetBSD /dev/random implementation,
+ * written by Michael Graff <explorer@netbsd.org>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#include <isc/buffer.h>
+#include <isc/entropy.h>
+#include <isc/keyboard.h>
+#include <isc/list.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/platform.h>
+#include <isc/region.h>
+#include <isc/sha1.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+
+#define ENTROPY_MAGIC ISC_MAGIC('E', 'n', 't', 'e')
+#define SOURCE_MAGIC ISC_MAGIC('E', 'n', 't', 's')
+
+#define VALID_ENTROPY(e) ISC_MAGIC_VALID(e, ENTROPY_MAGIC)
+#define VALID_SOURCE(s) ISC_MAGIC_VALID(s, SOURCE_MAGIC)
+
+/***
+ *** "constants." Do not change these unless you _really_ know what
+ *** you are doing.
+ ***/
+
+/*%
+ * Size of entropy pool in 32-bit words. This _MUST_ be a power of 2.
+ */
+#define RND_POOLWORDS 128
+/*% Pool in bytes. */
+#define RND_POOLBYTES (RND_POOLWORDS * 4)
+/*% Pool in bits. */
+#define RND_POOLBITS (RND_POOLWORDS * 32)
+
+/*%
+ * Number of bytes returned per hash. This must be true:
+ * threshold * 2 <= digest_size_in_bytes
+ */
+#define RND_ENTROPY_THRESHOLD 10
+#define THRESHOLD_BITS (RND_ENTROPY_THRESHOLD * 8)
+
+/*%
+ * Size of the input event queue in samples.
+ */
+#define RND_EVENTQSIZE 32
+
+/*%
+ * The number of times we'll "reseed" for pseudorandom seeds. This is an
+ * extremely weak pseudorandom seed. If the caller is using lots of
+ * pseudorandom data and they cannot provide a stronger random source,
+ * there is little we can do other than hope they're smart enough to
+ * call _adddata() with something better than we can come up with.
+ */
+#define RND_INITIALIZE 128
+
+/*% Entropy Pool */
+typedef struct {
+ isc_uint32_t cursor; /*%< current add point in the pool */
+ isc_uint32_t entropy; /*%< current entropy estimate in bits */
+ isc_uint32_t pseudo; /*%< bits extracted in pseudorandom */
+ isc_uint32_t rotate; /*%< how many bits to rotate by */
+ isc_uint32_t pool[RND_POOLWORDS]; /*%< random pool data */
+} isc_entropypool_t;
+
+struct isc_entropy {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_mutex_t lock;
+ unsigned int refcnt;
+ isc_uint32_t initialized;
+ isc_uint32_t initcount;
+ isc_entropypool_t pool;
+ unsigned int nsources;
+ isc_entropysource_t *nextsource;
+ ISC_LIST(isc_entropysource_t) sources;
+};
+
+/*% Sample Queue */
+typedef struct {
+ isc_uint32_t last_time; /*%< last time recorded */
+ isc_uint32_t last_delta; /*%< last delta value */
+ isc_uint32_t last_delta2; /*%< last delta2 value */
+ isc_uint32_t nsamples; /*%< number of samples filled in */
+ isc_uint32_t *samples; /*%< the samples */
+ isc_uint32_t *extra; /*%< extra samples added in */
+} sample_queue_t;
+
+typedef struct {
+ sample_queue_t samplequeue;
+} isc_entropysamplesource_t;
+
+typedef struct {
+ isc_boolean_t start_called;
+ isc_entropystart_t startfunc;
+ isc_entropyget_t getfunc;
+ isc_entropystop_t stopfunc;
+ void *arg;
+ sample_queue_t samplequeue;
+} isc_cbsource_t;
+
+typedef struct {
+ FILESOURCE_HANDLE_TYPE handle;
+} isc_entropyfilesource_t;
+
+struct isc_entropysource {
+ unsigned int magic;
+ unsigned int type;
+ isc_entropy_t *ent;
+ isc_uint32_t total; /*%< entropy from this source */
+ ISC_LINK(isc_entropysource_t) link;
+ char name[32];
+ isc_boolean_t bad;
+ isc_boolean_t warn_keyboard;
+ isc_keyboard_t kbd;
+ union {
+ isc_entropysamplesource_t sample;
+ isc_entropyfilesource_t file;
+ isc_cbsource_t callback;
+ isc_entropyusocketsource_t usocket;
+ } sources;
+};
+
+#define ENTROPY_SOURCETYPE_SAMPLE 1 /*%< Type is a sample source */
+#define ENTROPY_SOURCETYPE_FILE 2 /*%< Type is a file source */
+#define ENTROPY_SOURCETYPE_CALLBACK 3 /*%< Type is a callback source */
+#define ENTROPY_SOURCETYPE_USOCKET 4 /*%< Type is a Unix socket source */
+
+/*@{*/
+/*%
+ * The random pool "taps"
+ */
+#define TAP1 99
+#define TAP2 59
+#define TAP3 31
+#define TAP4 9
+#define TAP5 7
+/*@}*/
+
+/*@{*/
+/*%
+ * Declarations for function provided by the system dependent sources that
+ * include this file.
+ */
+static void
+fillpool(isc_entropy_t *, unsigned int, isc_boolean_t);
+
+static int
+wait_for_sources(isc_entropy_t *);
+
+static void
+destroyfilesource(isc_entropyfilesource_t *source);
+
+static void
+destroyusocketsource(isc_entropyusocketsource_t *source);
+
+/*@}*/
+
+static void
+samplequeue_release(isc_entropy_t *ent, sample_queue_t *sq) {
+ REQUIRE(sq->samples != NULL);
+ REQUIRE(sq->extra != NULL);
+
+ isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
+ isc_mem_put(ent->mctx, sq->extra, RND_EVENTQSIZE * 4);
+ sq->samples = NULL;
+ sq->extra = NULL;
+}
+
+static isc_result_t
+samplesource_allocate(isc_entropy_t *ent, sample_queue_t *sq) {
+ sq->samples = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
+ if (sq->samples == NULL)
+ return (ISC_R_NOMEMORY);
+
+ sq->extra = isc_mem_get(ent->mctx, RND_EVENTQSIZE * 4);
+ if (sq->extra == NULL) {
+ isc_mem_put(ent->mctx, sq->samples, RND_EVENTQSIZE * 4);
+ sq->samples = NULL;
+ return (ISC_R_NOMEMORY);
+ }
+
+ sq->nsamples = 0;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Add in entropy, even when the value we're adding in could be
+ * very large.
+ */
+static inline void
+add_entropy(isc_entropy_t *ent, isc_uint32_t entropy) {
+ /* clamp input. Yes, this must be done. */
+ entropy = ISC_MIN(entropy, RND_POOLBITS);
+ /* Add in the entropy we already have. */
+ entropy += ent->pool.entropy;
+ /* Clamp. */
+ ent->pool.entropy = ISC_MIN(entropy, RND_POOLBITS);
+}
+
+/*%
+ * Decrement the amount of entropy the pool has.
+ */
+static inline void
+subtract_entropy(isc_entropy_t *ent, isc_uint32_t entropy) {
+ entropy = ISC_MIN(entropy, ent->pool.entropy);
+ ent->pool.entropy -= entropy;
+}
+
+/*!
+ * Add in entropy, even when the value we're adding in could be
+ * very large.
+ */
+static inline void
+add_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) {
+ /* clamp input. Yes, this must be done. */
+ pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
+ /* Add in the pseudo we already have. */
+ pseudo += ent->pool.pseudo;
+ /* Clamp. */
+ ent->pool.pseudo = ISC_MIN(pseudo, RND_POOLBITS * 8);
+}
+
+/*!
+ * Decrement the amount of pseudo the pool has.
+ */
+static inline void
+subtract_pseudo(isc_entropy_t *ent, isc_uint32_t pseudo) {
+ pseudo = ISC_MIN(pseudo, ent->pool.pseudo);
+ ent->pool.pseudo -= pseudo;
+}
+
+/*!
+ * Add one word to the pool, rotating the input as needed.
+ */
+static inline void
+entropypool_add_word(isc_entropypool_t *rp, isc_uint32_t val) {
+ /*
+ * Steal some values out of the pool, and xor them into the
+ * word we were given.
+ *
+ * Mix the new value into the pool using xor. This will
+ * prevent the actual values from being known to the caller
+ * since the previous values are assumed to be unknown as well.
+ */
+ val ^= rp->pool[(rp->cursor + TAP1) & (RND_POOLWORDS - 1)];
+ val ^= rp->pool[(rp->cursor + TAP2) & (RND_POOLWORDS - 1)];
+ val ^= rp->pool[(rp->cursor + TAP3) & (RND_POOLWORDS - 1)];
+ val ^= rp->pool[(rp->cursor + TAP4) & (RND_POOLWORDS - 1)];
+ val ^= rp->pool[(rp->cursor + TAP5) & (RND_POOLWORDS - 1)];
+ rp->pool[rp->cursor++] ^=
+ ((val << rp->rotate) | (val >> (32 - rp->rotate)));
+
+ /*
+ * If we have looped around the pool, increment the rotate
+ * variable so the next value will get xored in rotated to
+ * a different position.
+ * Increment by a value that is relativly prime to the word size
+ * to try to spread the bits throughout the pool quickly when the
+ * pool is empty.
+ */
+ if (rp->cursor == RND_POOLWORDS) {
+ rp->cursor = 0;
+ rp->rotate = (rp->rotate + 7) & 31;
+ }
+}
+
+/*!
+ * Add a buffer's worth of data to the pool.
+ *
+ * Requires that the lock is held on the entropy pool.
+ */
+static void
+entropypool_adddata(isc_entropy_t *ent, void *p, unsigned int len,
+ isc_uint32_t entropy)
+{
+ isc_uint32_t val;
+ unsigned long addr;
+ isc_uint8_t *buf;
+
+ addr = (unsigned long)p;
+ buf = p;
+
+ if ((addr & 0x03U) != 0U) {
+ val = 0;
+ switch (len) {
+ case 3:
+ val = *buf++;
+ len--;
+ case 2:
+ val = val << 8 | *buf++;
+ len--;
+ case 1:
+ val = val << 8 | *buf++;
+ len--;
+ }
+
+ entropypool_add_word(&ent->pool, val);
+ }
+
+ for (; len > 3; len -= 4) {
+ val = *((isc_uint32_t *)buf);
+
+ entropypool_add_word(&ent->pool, val);
+ buf += 4;
+ }
+
+ if (len != 0) {
+ val = 0;
+ switch (len) {
+ case 3:
+ val = *buf++;
+ case 2:
+ val = val << 8 | *buf++;
+ case 1:
+ val = val << 8 | *buf++;
+ }
+
+ entropypool_add_word(&ent->pool, val);
+ }
+
+ add_entropy(ent, entropy);
+ subtract_pseudo(ent, entropy);
+}
+
+static inline void
+reseed(isc_entropy_t *ent) {
+ isc_time_t t;
+ pid_t pid;
+
+ if (ent->initcount == 0) {
+ pid = getpid();
+ entropypool_adddata(ent, &pid, sizeof(pid), 0);
+ pid = getppid();
+ entropypool_adddata(ent, &pid, sizeof(pid), 0);
+ }
+
+ /*!
+ * After we've reseeded 100 times, only add new timing info every
+ * 50 requests. This will keep us from using lots and lots of
+ * CPU just to return bad pseudorandom data anyway.
+ */
+ if (ent->initcount > 100)
+ if ((ent->initcount % 50) != 0)
+ return;
+
+ TIME_NOW(&t);
+ entropypool_adddata(ent, &t, sizeof(t), 0);
+ ent->initcount++;
+}
+
+static inline unsigned int
+estimate_entropy(sample_queue_t *sq, isc_uint32_t t) {
+ isc_int32_t delta;
+ isc_int32_t delta2;
+ isc_int32_t delta3;
+
+ /*!
+ * If the time counter has overflowed, calculate the real difference.
+ * If it has not, it is simpler.
+ */
+ if (t < sq->last_time)
+ delta = UINT_MAX - sq->last_time + t;
+ else
+ delta = sq->last_time - t;
+
+ if (delta < 0)
+ delta = -delta;
+
+ /*
+ * Calculate the second and third order differentials
+ */
+ delta2 = sq->last_delta - delta;
+ if (delta2 < 0)
+ delta2 = -delta2;
+
+ delta3 = sq->last_delta2 - delta2;
+ if (delta3 < 0)
+ delta3 = -delta3;
+
+ sq->last_time = t;
+ sq->last_delta = delta;
+ sq->last_delta2 = delta2;
+
+ /*
+ * If any delta is 0, we got no entropy. If all are non-zero, we
+ * might have something.
+ */
+ if (delta == 0 || delta2 == 0 || delta3 == 0)
+ return 0;
+
+ /*
+ * We could find the smallest delta and claim we got log2(delta)
+ * bits, but for now return that we found 1 bit.
+ */
+ return 1;
+}
+
+static unsigned int
+crunchsamples(isc_entropy_t *ent, sample_queue_t *sq) {
+ unsigned int ns;
+ unsigned int added;
+
+ if (sq->nsamples < 6)
+ return (0);
+
+ added = 0;
+ sq->last_time = sq->samples[0];
+ sq->last_delta = 0;
+ sq->last_delta2 = 0;
+
+ /*
+ * Prime the values by adding in the first 4 samples in. This
+ * should completely initialize the delta calculations.
+ */
+ for (ns = 0; ns < 4; ns++)
+ (void)estimate_entropy(sq, sq->samples[ns]);
+
+ for (ns = 4; ns < sq->nsamples; ns++)
+ added += estimate_entropy(sq, sq->samples[ns]);
+
+ entropypool_adddata(ent, sq->samples, sq->nsamples * 4, added);
+ entropypool_adddata(ent, sq->extra, sq->nsamples * 4, 0);
+
+ /*
+ * Move the last 4 samples into the first 4 positions, and start
+ * adding new samples from that point.
+ */
+ for (ns = 0; ns < 4; ns++) {
+ sq->samples[ns] = sq->samples[sq->nsamples - 4 + ns];
+ sq->extra[ns] = sq->extra[sq->nsamples - 4 + ns];
+ }
+
+ sq->nsamples = 4;
+
+ return (added);
+}
+
+static unsigned int
+get_from_callback(isc_entropysource_t *source, unsigned int desired,
+ isc_boolean_t blocking)
+{
+ isc_entropy_t *ent = source->ent;
+ isc_cbsource_t *cbs = &source->sources.callback;
+ unsigned int added;
+ unsigned int got;
+ isc_result_t result;
+
+ if (desired == 0)
+ return (0);
+
+ if (source->bad)
+ return (0);
+
+ if (!cbs->start_called && cbs->startfunc != NULL) {
+ result = cbs->startfunc(source, cbs->arg, blocking);
+ if (result != ISC_R_SUCCESS)
+ return (0);
+ cbs->start_called = ISC_TRUE;
+ }
+
+ added = 0;
+ result = ISC_R_SUCCESS;
+ while (desired > 0 && result == ISC_R_SUCCESS) {
+ result = cbs->getfunc(source, cbs->arg, blocking);
+ if (result == ISC_R_QUEUEFULL) {
+ got = crunchsamples(ent, &cbs->samplequeue);
+ added += got;
+ desired -= ISC_MIN(got, desired);
+ result = ISC_R_SUCCESS;
+ } else if (result != ISC_R_SUCCESS &&
+ result != ISC_R_NOTBLOCKING)
+ source->bad = ISC_TRUE;
+
+ }
+
+ return (added);
+}
+
+/*
+ * Extract some number of bytes from the random pool, decreasing the
+ * estimate of randomness as each byte is extracted.
+ *
+ * Do this by stiring the pool and returning a part of hash as randomness.
+ * Note that no secrets are given away here since parts of the hash are
+ * xored together before returned.
+ *
+ * Honor the request from the caller to only return good data, any data,
+ * etc.
+ */
+isc_result_t
+isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
+ unsigned int *returned, unsigned int flags)
+{
+ unsigned int i;
+ isc_sha1_t hash;
+ unsigned char digest[ISC_SHA1_DIGESTLENGTH];
+ isc_uint32_t remain, deltae, count, total;
+ isc_uint8_t *buf;
+ isc_boolean_t goodonly, partial, blocking;
+
+ REQUIRE(VALID_ENTROPY(ent));
+ REQUIRE(data != NULL);
+ REQUIRE(length > 0);
+
+ goodonly = ISC_TF((flags & ISC_ENTROPY_GOODONLY) != 0);
+ partial = ISC_TF((flags & ISC_ENTROPY_PARTIAL) != 0);
+ blocking = ISC_TF((flags & ISC_ENTROPY_BLOCKING) != 0);
+
+ REQUIRE(!partial || returned != NULL);
+
+ LOCK(&ent->lock);
+
+ remain = length;
+ buf = data;
+ total = 0;
+ while (remain != 0) {
+ count = ISC_MIN(remain, RND_ENTROPY_THRESHOLD);
+
+ /*
+ * If we are extracting good data only, make certain we
+ * have enough data in our pool for this pass. If we don't,
+ * get some, and fail if we can't, and partial returns
+ * are not ok.
+ */
+ if (goodonly) {
+ unsigned int fillcount;
+
+ fillcount = ISC_MAX(remain * 8, count * 8);
+
+ /*
+ * If, however, we have at least THRESHOLD_BITS
+ * of entropy in the pool, don't block here. It is
+ * better to drain the pool once in a while and
+ * then refill it than it is to constantly keep the
+ * pool full.
+ */
+ if (ent->pool.entropy >= THRESHOLD_BITS)
+ fillpool(ent, fillcount, ISC_FALSE);
+ else
+ fillpool(ent, fillcount, blocking);
+
+ /*
+ * Verify that we got enough entropy to do one
+ * extraction. If we didn't, bail.
+ */
+ if (ent->pool.entropy < THRESHOLD_BITS) {
+ if (!partial)
+ goto zeroize;
+ else
+ goto partial_output;
+ }
+ } else {
+ /*
+ * If we've extracted half our pool size in bits
+ * since the last refresh, try to refresh here.
+ */
+ if (ent->initialized < THRESHOLD_BITS)
+ fillpool(ent, THRESHOLD_BITS, blocking);
+ else
+ fillpool(ent, 0, ISC_FALSE);
+
+ /*
+ * If we've not initialized with enough good random
+ * data, seed with our crappy code.
+ */
+ if (ent->initialized < THRESHOLD_BITS)
+ reseed(ent);
+ }
+
+ isc_sha1_init(&hash);
+ isc_sha1_update(&hash, (void *)(ent->pool.pool),
+ RND_POOLBYTES);
+ isc_sha1_final(&hash, digest);
+
+ /*
+ * Stir the extracted data (all of it) back into the pool.
+ */
+ entropypool_adddata(ent, digest, ISC_SHA1_DIGESTLENGTH, 0);
+
+ for (i = 0; i < count; i++)
+ buf[i] = digest[i] ^ digest[i + RND_ENTROPY_THRESHOLD];
+
+ buf += count;
+ remain -= count;
+
+ deltae = count * 8;
+ deltae = ISC_MIN(deltae, ent->pool.entropy);
+ total += deltae;
+ subtract_entropy(ent, deltae);
+ add_pseudo(ent, count * 8);
+ }
+
+ partial_output:
+ memset(digest, 0, sizeof(digest));
+
+ if (returned != NULL)
+ *returned = (length - remain);
+
+ UNLOCK(&ent->lock);
+
+ return (ISC_R_SUCCESS);
+
+ zeroize:
+ /* put the entropy we almost extracted back */
+ add_entropy(ent, total);
+ memset(data, 0, length);
+ memset(digest, 0, sizeof(digest));
+ if (returned != NULL)
+ *returned = 0;
+
+ UNLOCK(&ent->lock);
+
+ return (ISC_R_NOENTROPY);
+}
+
+static void
+isc_entropypool_init(isc_entropypool_t *pool) {
+ pool->cursor = RND_POOLWORDS - 1;
+ pool->entropy = 0;
+ pool->pseudo = 0;
+ pool->rotate = 0;
+ memset(pool->pool, 0, RND_POOLBYTES);
+}
+
+static void
+isc_entropypool_invalidate(isc_entropypool_t *pool) {
+ pool->cursor = 0;
+ pool->entropy = 0;
+ pool->pseudo = 0;
+ pool->rotate = 0;
+ memset(pool->pool, 0, RND_POOLBYTES);
+}
+
+isc_result_t
+isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp) {
+ isc_result_t result;
+ isc_entropy_t *ent;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(entp != NULL && *entp == NULL);
+
+ ent = isc_mem_get(mctx, sizeof(isc_entropy_t));
+ if (ent == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /*
+ * We need a lock.
+ */
+ result = isc_mutex_init(&ent->lock);
+ if (result != ISC_R_SUCCESS)
+ goto errout;
+
+ /*
+ * From here down, no failures will/can occur.
+ */
+ ISC_LIST_INIT(ent->sources);
+ ent->nextsource = NULL;
+ ent->nsources = 0;
+ ent->mctx = NULL;
+ isc_mem_attach(mctx, &ent->mctx);
+ ent->refcnt = 1;
+ ent->initialized = 0;
+ ent->initcount = 0;
+ ent->magic = ENTROPY_MAGIC;
+
+ isc_entropypool_init(&ent->pool);
+
+ *entp = ent;
+ return (ISC_R_SUCCESS);
+
+ errout:
+ isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
+
+ return (result);
+}
+
+/*!
+ * Requires "ent" be locked.
+ */
+static void
+destroysource(isc_entropysource_t **sourcep) {
+ isc_entropysource_t *source;
+ isc_entropy_t *ent;
+ isc_cbsource_t *cbs;
+
+ source = *sourcep;
+ *sourcep = NULL;
+ ent = source->ent;
+
+ ISC_LIST_UNLINK(ent->sources, source, link);
+ ent->nextsource = NULL;
+ REQUIRE(ent->nsources > 0);
+ ent->nsources--;
+
+ switch (source->type) {
+ case ENTROPY_SOURCETYPE_FILE:
+ if (! source->bad)
+ destroyfilesource(&source->sources.file);
+ break;
+ case ENTROPY_SOURCETYPE_USOCKET:
+ if (! source->bad)
+ destroyusocketsource(&source->sources.usocket);
+ break;
+ case ENTROPY_SOURCETYPE_SAMPLE:
+ samplequeue_release(ent, &source->sources.sample.samplequeue);
+ break;
+ case ENTROPY_SOURCETYPE_CALLBACK:
+ cbs = &source->sources.callback;
+ if (cbs->start_called && cbs->stopfunc != NULL) {
+ cbs->stopfunc(source, cbs->arg);
+ cbs->start_called = ISC_FALSE;
+ }
+ samplequeue_release(ent, &cbs->samplequeue);
+ break;
+ }
+
+ memset(source, 0, sizeof(isc_entropysource_t));
+
+ isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
+}
+
+static inline isc_boolean_t
+destroy_check(isc_entropy_t *ent) {
+ isc_entropysource_t *source;
+
+ if (ent->refcnt > 0)
+ return (ISC_FALSE);
+
+ source = ISC_LIST_HEAD(ent->sources);
+ while (source != NULL) {
+ switch (source->type) {
+ case ENTROPY_SOURCETYPE_FILE:
+ case ENTROPY_SOURCETYPE_USOCKET:
+ break;
+ default:
+ return (ISC_FALSE);
+ }
+ source = ISC_LIST_NEXT(source, link);
+ }
+
+ return (ISC_TRUE);
+}
+
+static void
+destroy(isc_entropy_t **entp) {
+ isc_entropy_t *ent;
+ isc_entropysource_t *source;
+ isc_mem_t *mctx;
+
+ REQUIRE(entp != NULL && *entp != NULL);
+ ent = *entp;
+ *entp = NULL;
+
+ LOCK(&ent->lock);
+
+ REQUIRE(ent->refcnt == 0);
+
+ /*
+ * Here, detach non-sample sources.
+ */
+ source = ISC_LIST_HEAD(ent->sources);
+ while (source != NULL) {
+ switch(source->type) {
+ case ENTROPY_SOURCETYPE_FILE:
+ case ENTROPY_SOURCETYPE_USOCKET:
+ destroysource(&source);
+ break;
+ }
+ source = ISC_LIST_HEAD(ent->sources);
+ }
+
+ /*
+ * If there are other types of sources, we've found a bug.
+ */
+ REQUIRE(ISC_LIST_EMPTY(ent->sources));
+
+ mctx = ent->mctx;
+
+ isc_entropypool_invalidate(&ent->pool);
+
+ UNLOCK(&ent->lock);
+
+ DESTROYLOCK(&ent->lock);
+
+ memset(ent, 0, sizeof(isc_entropy_t));
+ isc_mem_put(mctx, ent, sizeof(isc_entropy_t));
+ isc_mem_detach(&mctx);
+}
+
+void
+isc_entropy_destroysource(isc_entropysource_t **sourcep) {
+ isc_entropysource_t *source;
+ isc_entropy_t *ent;
+ isc_boolean_t killit;
+
+ REQUIRE(sourcep != NULL);
+ REQUIRE(VALID_SOURCE(*sourcep));
+
+ source = *sourcep;
+ *sourcep = NULL;
+
+ ent = source->ent;
+ REQUIRE(VALID_ENTROPY(ent));
+
+ LOCK(&ent->lock);
+
+ destroysource(&source);
+
+ killit = destroy_check(ent);
+
+ UNLOCK(&ent->lock);
+
+ if (killit)
+ destroy(&ent);
+}
+
+isc_result_t
+isc_entropy_createcallbacksource(isc_entropy_t *ent,
+ isc_entropystart_t start,
+ isc_entropyget_t get,
+ isc_entropystop_t stop,
+ void *arg,
+ isc_entropysource_t **sourcep)
+{
+ isc_result_t result;
+ isc_entropysource_t *source;
+ isc_cbsource_t *cbs;
+
+ REQUIRE(VALID_ENTROPY(ent));
+ REQUIRE(get != NULL);
+ REQUIRE(sourcep != NULL && *sourcep == NULL);
+
+ LOCK(&ent->lock);
+
+ source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
+ if (source == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto errout;
+ }
+ source->bad = ISC_FALSE;
+
+ cbs = &source->sources.callback;
+
+ result = samplesource_allocate(ent, &cbs->samplequeue);
+ if (result != ISC_R_SUCCESS)
+ goto errout;
+
+ cbs->start_called = ISC_FALSE;
+ cbs->startfunc = start;
+ cbs->getfunc = get;
+ cbs->stopfunc = stop;
+ cbs->arg = arg;
+
+ /*
+ * From here down, no failures can occur.
+ */
+ source->magic = SOURCE_MAGIC;
+ source->type = ENTROPY_SOURCETYPE_CALLBACK;
+ source->ent = ent;
+ source->total = 0;
+ memset(source->name, 0, sizeof(source->name));
+ ISC_LINK_INIT(source, link);
+
+ /*
+ * Hook it into the entropy system.
+ */
+ ISC_LIST_APPEND(ent->sources, source, link);
+ ent->nsources++;
+
+ *sourcep = source;
+
+ UNLOCK(&ent->lock);
+ return (ISC_R_SUCCESS);
+
+ errout:
+ if (source != NULL)
+ isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
+
+ UNLOCK(&ent->lock);
+
+ return (result);
+}
+
+void
+isc_entropy_stopcallbacksources(isc_entropy_t *ent) {
+ isc_entropysource_t *source;
+ isc_cbsource_t *cbs;
+
+ REQUIRE(VALID_ENTROPY(ent));
+
+ LOCK(&ent->lock);
+
+ source = ISC_LIST_HEAD(ent->sources);
+ while (source != NULL) {
+ if (source->type == ENTROPY_SOURCETYPE_CALLBACK) {
+ cbs = &source->sources.callback;
+ if (cbs->start_called && cbs->stopfunc != NULL) {
+ cbs->stopfunc(source, cbs->arg);
+ cbs->start_called = ISC_FALSE;
+ }
+ }
+
+ source = ISC_LIST_NEXT(source, link);
+ }
+
+ UNLOCK(&ent->lock);
+}
+
+isc_result_t
+isc_entropy_createsamplesource(isc_entropy_t *ent,
+ isc_entropysource_t **sourcep)
+{
+ isc_result_t result;
+ isc_entropysource_t *source;
+ sample_queue_t *sq;
+
+ REQUIRE(VALID_ENTROPY(ent));
+ REQUIRE(sourcep != NULL && *sourcep == NULL);
+
+ LOCK(&ent->lock);
+
+ source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
+ if (source == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto errout;
+ }
+
+ sq = &source->sources.sample.samplequeue;
+ result = samplesource_allocate(ent, sq);
+ if (result != ISC_R_SUCCESS)
+ goto errout;
+
+ /*
+ * From here down, no failures can occur.
+ */
+ source->magic = SOURCE_MAGIC;
+ source->type = ENTROPY_SOURCETYPE_SAMPLE;
+ source->ent = ent;
+ source->total = 0;
+ memset(source->name, 0, sizeof(source->name));
+ ISC_LINK_INIT(source, link);
+
+ /*
+ * Hook it into the entropy system.
+ */
+ ISC_LIST_APPEND(ent->sources, source, link);
+ ent->nsources++;
+
+ *sourcep = source;
+
+ UNLOCK(&ent->lock);
+ return (ISC_R_SUCCESS);
+
+ errout:
+ if (source != NULL)
+ isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
+
+ UNLOCK(&ent->lock);
+
+ return (result);
+}
+
+/*!
+ * Add a sample, and return ISC_R_SUCCESS if the queue has become full,
+ * ISC_R_NOENTROPY if it has space remaining, and ISC_R_NOMORE if the
+ * queue was full when this function was called.
+ */
+static isc_result_t
+addsample(sample_queue_t *sq, isc_uint32_t sample, isc_uint32_t extra) {
+ if (sq->nsamples >= RND_EVENTQSIZE)
+ return (ISC_R_NOMORE);
+
+ sq->samples[sq->nsamples] = sample;
+ sq->extra[sq->nsamples] = extra;
+ sq->nsamples++;
+
+ if (sq->nsamples >= RND_EVENTQSIZE)
+ return (ISC_R_QUEUEFULL);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_entropy_addsample(isc_entropysource_t *source, isc_uint32_t sample,
+ isc_uint32_t extra)
+{
+ isc_entropy_t *ent;
+ sample_queue_t *sq;
+ unsigned int entropy;
+ isc_result_t result;
+
+ REQUIRE(VALID_SOURCE(source));
+
+ ent = source->ent;
+
+ LOCK(&ent->lock);
+
+ sq = &source->sources.sample.samplequeue;
+ result = addsample(sq, sample, extra);
+ if (result == ISC_R_QUEUEFULL) {
+ entropy = crunchsamples(ent, sq);
+ add_entropy(ent, entropy);
+ }
+
+ UNLOCK(&ent->lock);
+
+ return (result);
+}
+
+isc_result_t
+isc_entropy_addcallbacksample(isc_entropysource_t *source, isc_uint32_t sample,
+ isc_uint32_t extra)
+{
+ sample_queue_t *sq;
+ isc_result_t result;
+
+ REQUIRE(VALID_SOURCE(source));
+ REQUIRE(source->type == ENTROPY_SOURCETYPE_CALLBACK);
+
+ sq = &source->sources.callback.samplequeue;
+ result = addsample(sq, sample, extra);
+
+ return (result);
+}
+
+void
+isc_entropy_putdata(isc_entropy_t *ent, void *data, unsigned int length,
+ isc_uint32_t entropy)
+{
+ REQUIRE(VALID_ENTROPY(ent));
+
+ LOCK(&ent->lock);
+
+ entropypool_adddata(ent, data, length, entropy);
+
+ if (ent->initialized < THRESHOLD_BITS)
+ ent->initialized = THRESHOLD_BITS;
+
+ UNLOCK(&ent->lock);
+}
+
+static void
+dumpstats(isc_entropy_t *ent, FILE *out) {
+ fprintf(out,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_ENTROPY,
+ ISC_MSG_ENTROPYSTATS,
+ "Entropy pool %p: refcnt %u cursor %u,"
+ " rotate %u entropy %u pseudo %u nsources %u"
+ " nextsource %p initialized %u initcount %u\n"),
+ ent, ent->refcnt,
+ ent->pool.cursor, ent->pool.rotate,
+ ent->pool.entropy, ent->pool.pseudo,
+ ent->nsources, ent->nextsource, ent->initialized,
+ ent->initcount);
+}
+
+/*
+ * This function ignores locking. Use at your own risk.
+ */
+void
+isc_entropy_stats(isc_entropy_t *ent, FILE *out) {
+ REQUIRE(VALID_ENTROPY(ent));
+
+ LOCK(&ent->lock);
+ dumpstats(ent, out);
+ UNLOCK(&ent->lock);
+}
+
+unsigned int
+isc_entropy_status(isc_entropy_t *ent) {
+ unsigned int estimate;
+
+ LOCK(&ent->lock);
+ estimate = ent->pool.entropy;
+ UNLOCK(&ent->lock);
+
+ return estimate;
+}
+
+void
+isc_entropy_attach(isc_entropy_t *ent, isc_entropy_t **entp) {
+ REQUIRE(VALID_ENTROPY(ent));
+ REQUIRE(entp != NULL && *entp == NULL);
+
+ LOCK(&ent->lock);
+
+ ent->refcnt++;
+ *entp = ent;
+
+ UNLOCK(&ent->lock);
+}
+
+void
+isc_entropy_detach(isc_entropy_t **entp) {
+ isc_entropy_t *ent;
+ isc_boolean_t killit;
+
+ REQUIRE(entp != NULL && VALID_ENTROPY(*entp));
+ ent = *entp;
+ *entp = NULL;
+
+ LOCK(&ent->lock);
+
+ REQUIRE(ent->refcnt > 0);
+ ent->refcnt--;
+
+ killit = destroy_check(ent);
+
+ UNLOCK(&ent->lock);
+
+ if (killit)
+ destroy(&ent);
+}
+
+static isc_result_t
+kbdstart(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
+ /*
+ * The intent of "first" is to provide a warning message only once
+ * during the run of a program that might try to gather keyboard
+ * entropy multiple times.
+ */
+ static isc_boolean_t first = ISC_TRUE;
+
+ UNUSED(arg);
+
+ if (! blocking)
+ return (ISC_R_NOENTROPY);
+
+ if (first) {
+ if (source->warn_keyboard)
+ fprintf(stderr, "You must use the keyboard to create "
+ "entropy, since your system is lacking\n"
+ "/dev/random (or equivalent)\n\n");
+ first = ISC_FALSE;
+ }
+ fprintf(stderr, "start typing:\n");
+
+ return (isc_keyboard_open(&source->kbd));
+}
+
+static void
+kbdstop(isc_entropysource_t *source, void *arg) {
+
+ UNUSED(arg);
+
+ if (! isc_keyboard_canceled(&source->kbd))
+ fprintf(stderr, "stop typing.\r\n");
+
+ (void)isc_keyboard_close(&source->kbd, 3);
+}
+
+static isc_result_t
+kbdget(isc_entropysource_t *source, void *arg, isc_boolean_t blocking) {
+ isc_result_t result;
+ isc_time_t t;
+ isc_uint32_t sample;
+ isc_uint32_t extra;
+ unsigned char c;
+
+ UNUSED(arg);
+
+ if (!blocking)
+ return (ISC_R_NOTBLOCKING);
+
+ result = isc_keyboard_getchar(&source->kbd, &c);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ TIME_NOW(&t);
+
+ sample = isc_time_nanoseconds(&t);
+ extra = c;
+
+ result = isc_entropy_addcallbacksample(source, sample, extra);
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "\r\n");
+ return (result);
+ }
+
+ fprintf(stderr, ".");
+ fflush(stderr);
+
+ return (result);
+}
+
+isc_result_t
+isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source,
+ const char *randomfile, int use_keyboard)
+{
+ isc_result_t result;
+ isc_result_t final_result = ISC_R_NOENTROPY;
+ isc_boolean_t userfile = ISC_TRUE;
+
+ REQUIRE(VALID_ENTROPY(ectx));
+ REQUIRE(source != NULL && *source == NULL);
+ REQUIRE(use_keyboard == ISC_ENTROPY_KEYBOARDYES ||
+ use_keyboard == ISC_ENTROPY_KEYBOARDNO ||
+ use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE);
+
+#ifdef PATH_RANDOMDEV
+ if (randomfile == NULL) {
+ randomfile = PATH_RANDOMDEV;
+ userfile = ISC_FALSE;
+ }
+#endif
+
+ if (randomfile != NULL && use_keyboard != ISC_ENTROPY_KEYBOARDYES) {
+ result = isc_entropy_createfilesource(ectx, randomfile);
+ if (result == ISC_R_SUCCESS &&
+ use_keyboard == ISC_ENTROPY_KEYBOARDMAYBE)
+ use_keyboard = ISC_ENTROPY_KEYBOARDNO;
+ if (result != ISC_R_SUCCESS && userfile)
+ return (result);
+
+ final_result = result;
+ }
+
+ if (use_keyboard != ISC_ENTROPY_KEYBOARDNO) {
+ result = isc_entropy_createcallbacksource(ectx, kbdstart,
+ kbdget, kbdstop,
+ NULL, source);
+ if (result == ISC_R_SUCCESS)
+ (*source)->warn_keyboard =
+ ISC_TF(use_keyboard ==
+ ISC_ENTROPY_KEYBOARDMAYBE);
+
+ if (final_result != ISC_R_SUCCESS)
+ final_result = result;
+ }
+
+ /*
+ * final_result is ISC_R_SUCCESS if at least one source of entropy
+ * could be started, otherwise it is the error from the most recently
+ * failed operation (or ISC_R_NOENTROPY if PATH_RANDOMDEV is not
+ * defined and use_keyboard is ISC_ENTROPY_KEYBOARDNO).
+ */
+ return (final_result);
+}
diff --git a/lib/isc/error.c b/lib/isc/error.c
new file mode 100644
index 0000000..095100a
--- /dev/null
+++ b/lib/isc/error.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: error.c,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/error.h>
+#include <isc/msgs.h>
+
+/*% Default unexpected callback. */
+static void
+default_unexpected_callback(const char *, int, const char *, va_list)
+ ISC_FORMAT_PRINTF(3, 0);
+
+/*% Default fatal callback. */
+static void
+default_fatal_callback(const char *, int, const char *, va_list)
+ ISC_FORMAT_PRINTF(3, 0);
+
+/*% unexpected_callback */
+static isc_errorcallback_t unexpected_callback = default_unexpected_callback;
+static isc_errorcallback_t fatal_callback = default_fatal_callback;
+
+void
+isc_error_setunexpected(isc_errorcallback_t cb) {
+ if (cb == NULL)
+ unexpected_callback = default_unexpected_callback;
+ else
+ unexpected_callback = cb;
+}
+
+void
+isc_error_setfatal(isc_errorcallback_t cb) {
+ if (cb == NULL)
+ fatal_callback = default_fatal_callback;
+ else
+ fatal_callback = cb;
+}
+
+void
+isc_error_unexpected(const char *file, int line, const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ (unexpected_callback)(file, line, format, args);
+ va_end(args);
+}
+
+void
+isc_error_fatal(const char *file, int line, const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ (fatal_callback)(file, line, format, args);
+ va_end(args);
+ abort();
+}
+
+void
+isc_error_runtimecheck(const char *file, int line, const char *expression) {
+ isc_error_fatal(file, line, "RUNTIME_CHECK(%s) %s", expression,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+}
+
+static void
+default_unexpected_callback(const char *file, int line, const char *format,
+ va_list args)
+{
+ fprintf(stderr, "%s:%d: ", file, line);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+}
+
+static void
+default_fatal_callback(const char *file, int line, const char *format,
+ va_list args)
+{
+ fprintf(stderr, "%s:%d: %s: ", file, line,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FATALERROR, "fatal error"));
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+}
diff --git a/lib/isc/event.c b/lib/isc/event.c
new file mode 100644
index 0000000..8ab7524
--- /dev/null
+++ b/lib/isc/event.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: event.c,v 1.21 2007/06/19 23:47:17 tbox Exp $ */
+
+/*!
+ * \file
+ * \author Principal Author: Bob Halley
+ */
+
+#include <config.h>
+
+#include <isc/event.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+
+/***
+ *** Events.
+ ***/
+
+static void
+destroy(isc_event_t *event) {
+ isc_mem_t *mctx = event->ev_destroy_arg;
+
+ isc_mem_put(mctx, event, event->ev_size);
+}
+
+isc_event_t *
+isc_event_allocate(isc_mem_t *mctx, void *sender, isc_eventtype_t type,
+ isc_taskaction_t action, const void *arg, size_t size)
+{
+ isc_event_t *event;
+ void *deconst_arg;
+
+ REQUIRE(size >= sizeof(struct isc_event));
+ REQUIRE(action != NULL);
+
+ event = isc_mem_get(mctx, size);
+ if (event == NULL)
+ return (NULL);
+
+ /*
+ * Removing the const attribute from "arg" is the best of two
+ * evils here. If the event->ev_arg member is made const, then
+ * it affects a great many users of the task/event subsystem
+ * which are not passing in an "arg" which starts its life as
+ * const. Changing isc_event_allocate() and isc_task_onshutdown()
+ * to not have "arg" prototyped as const (which is quite legitimate,
+ * because neither of those functions modify arg) can cause
+ * compiler whining anytime someone does want to use a const
+ * arg that they themselves never modify, such as with
+ * gcc -Wwrite-strings and using a string "arg".
+ */
+ DE_CONST(arg, deconst_arg);
+
+ ISC_EVENT_INIT(event, size, 0, NULL, type, action, deconst_arg,
+ sender, destroy, mctx);
+
+ return (event);
+}
+
+void
+isc_event_free(isc_event_t **eventp) {
+ isc_event_t *event;
+
+ REQUIRE(eventp != NULL);
+ event = *eventp;
+ REQUIRE(event != NULL);
+
+ if (event->ev_destroy != NULL)
+ (event->ev_destroy)(event);
+
+ *eventp = NULL;
+}
diff --git a/lib/isc/fsaccess.c b/lib/isc/fsaccess.c
new file mode 100644
index 0000000..5c97183
--- /dev/null
+++ b/lib/isc/fsaccess.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: fsaccess.c,v 1.10 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * This file contains the OS-independent functionality of the API.
+ */
+#include <isc/fsaccess.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+/*!
+ * Shorthand. Maybe ISC__FSACCESS_PERMISSIONBITS should not even be in
+ * <isc/fsaccess.h>. Could check consistency with sizeof(isc_fsaccess_t)
+ * and the number of bits in each function.
+ */
+#define STEP (ISC__FSACCESS_PERMISSIONBITS)
+#define GROUP (STEP)
+#define OTHER (STEP * 2)
+
+void
+isc_fsaccess_add(int trustee, int permission, isc_fsaccess_t *access) {
+ REQUIRE(trustee <= 0x7);
+ REQUIRE(permission <= 0xFF);
+
+ if ((trustee & ISC_FSACCESS_OWNER) != 0)
+ *access |= permission;
+
+ if ((trustee & ISC_FSACCESS_GROUP) != 0)
+ *access |= (permission << GROUP);
+
+ if ((trustee & ISC_FSACCESS_OTHER) != 0)
+ *access |= (permission << OTHER);
+}
+
+void
+isc_fsaccess_remove(int trustee, int permission, isc_fsaccess_t *access) {
+ REQUIRE(trustee <= 0x7);
+ REQUIRE(permission <= 0xFF);
+
+
+ if ((trustee & ISC_FSACCESS_OWNER) != 0)
+ *access &= ~permission;
+
+ if ((trustee & ISC_FSACCESS_GROUP) != 0)
+ *access &= ~(permission << GROUP);
+
+ if ((trustee & ISC_FSACCESS_OTHER) != 0)
+ *access &= ~(permission << OTHER);
+}
+
+static isc_result_t
+check_bad_bits(isc_fsaccess_t access, isc_boolean_t is_dir) {
+ isc_fsaccess_t bits;
+
+ /*
+ * Check for disallowed user bits.
+ */
+ if (is_dir)
+ bits = ISC_FSACCESS_READ |
+ ISC_FSACCESS_WRITE |
+ ISC_FSACCESS_EXECUTE;
+ else
+ bits = ISC_FSACCESS_CREATECHILD |
+ ISC_FSACCESS_ACCESSCHILD |
+ ISC_FSACCESS_DELETECHILD |
+ ISC_FSACCESS_LISTDIRECTORY;
+
+ /*
+ * Set group bad bits.
+ */
+ bits |= bits << STEP;
+ /*
+ * Set other bad bits.
+ */
+ bits |= bits << STEP;
+
+ if ((access & bits) != 0) {
+ if (is_dir)
+ return (ISC_R_NOTFILE);
+ else
+ return (ISC_R_NOTDIRECTORY);
+ }
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/hash.c b/lib/isc/hash.c
new file mode 100644
index 0000000..41bb884
--- /dev/null
+++ b/lib/isc/hash.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: hash.c,v 1.13 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file
+ * Some portion of this code was derived from universal hash function
+ * libraries of Rice University.
+\section license UH Universal Hashing Library
+
+Copyright ((c)) 2002, Rice University
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of Rice University (RICE) 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 RICE and the contributors on an "as is"
+basis, without any representations or warranties of any kind, express
+or implied including, but not limited to, representations or
+warranties of non-infringement, merchantability or fitness for a
+particular purpose. In no event shall RICE or contributors be liable
+for any direct, indirect, incidental, special, exemplary, or
+consequential damages (including, but not limited to, procurement of
+substitute goods or services; loss of use, data, or profits; or
+business interruption) however caused and on any theory of liability,
+whether in contract, strict liability, or tort (including negligence
+or otherwise) arising in any way out of the use of this software, even
+if advised of the possibility of such damage.
+*/
+
+#include <config.h>
+
+#include <isc/entropy.h>
+#include <isc/hash.h>
+#include <isc/mem.h>
+#include <isc/magic.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/random.h>
+#include <isc/refcount.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#define HASH_MAGIC ISC_MAGIC('H', 'a', 's', 'h')
+#define VALID_HASH(h) ISC_MAGIC_VALID((h), HASH_MAGIC)
+
+/*%
+ * A large 32-bit prime number that specifies the range of the hash output.
+ */
+#define PRIME32 0xFFFFFFFB /* 2^32 - 5 */
+
+/*@{*/
+/*%
+ * Types of random seed and hash accumulator. Perhaps they can be system
+ * dependent.
+ */
+typedef isc_uint32_t hash_accum_t;
+typedef isc_uint16_t hash_random_t;
+/*@}*/
+
+/*% isc hash structure */
+struct isc_hash {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_mutex_t lock;
+ isc_boolean_t initialized;
+ isc_refcount_t refcnt;
+ isc_entropy_t *entropy; /*%< entropy source */
+ unsigned int limit; /*%< upper limit of key length */
+ size_t vectorlen; /*%< size of the vector below */
+ hash_random_t *rndvector; /*%< random vector for universal hashing */
+};
+
+static isc_mutex_t createlock;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_hash_t *hash = NULL;
+
+static unsigned char maptolower[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+isc_result_t
+isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy,
+ unsigned int limit, isc_hash_t **hctxp)
+{
+ isc_result_t result;
+ isc_hash_t *hctx;
+ size_t vlen;
+ hash_random_t *rv;
+ hash_accum_t overflow_limit;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(hctxp != NULL && *hctxp == NULL);
+
+ /*
+ * Overflow check. Since our implementation only does a modulo
+ * operation at the last stage of hash calculation, the accumulator
+ * must not overflow.
+ */
+ overflow_limit =
+ 1 << (((sizeof(hash_accum_t) - sizeof(hash_random_t))) * 8);
+ if (overflow_limit < (limit + 1) * 0xff)
+ return (ISC_R_RANGE);
+
+ hctx = isc_mem_get(mctx, sizeof(isc_hash_t));
+ if (hctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ vlen = sizeof(hash_random_t) * (limit + 1);
+ rv = isc_mem_get(mctx, vlen);
+ if (rv == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto errout;
+ }
+
+ /*
+ * We need a lock.
+ */
+ result = isc_mutex_init(&hctx->lock);
+ if (result != ISC_R_SUCCESS)
+ goto errout;
+
+ /*
+ * From here down, no failures will/can occur.
+ */
+ hctx->magic = HASH_MAGIC;
+ hctx->mctx = NULL;
+ isc_mem_attach(mctx, &hctx->mctx);
+ hctx->initialized = ISC_FALSE;
+ result = isc_refcount_init(&hctx->refcnt, 1);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_lock;
+ hctx->entropy = NULL;
+ hctx->limit = limit;
+ hctx->vectorlen = vlen;
+ hctx->rndvector = rv;
+
+ if (entropy != NULL)
+ isc_entropy_attach(entropy, &hctx->entropy);
+
+ *hctxp = hctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup_lock:
+ DESTROYLOCK(&hctx->lock);
+ errout:
+ isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
+ if (rv != NULL)
+ isc_mem_put(mctx, rv, vlen);
+
+ return (result);
+}
+
+static void
+initialize_lock(void) {
+ RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(mctx != NULL);
+ INSIST(hash == NULL);
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize_lock) == ISC_R_SUCCESS);
+
+ LOCK(&createlock);
+
+ if (hash == NULL)
+ result = isc_hash_ctxcreate(mctx, entropy, limit, &hash);
+
+ UNLOCK(&createlock);
+
+ return (result);
+}
+
+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) {
+ result = isc_entropy_getdata(hctx->entropy,
+ hctx->rndvector, hctx->vectorlen,
+ NULL, 0);
+ INSIST(result == ISC_R_SUCCESS);
+ } else {
+ isc_uint32_t pr;
+ unsigned int i, copylen;
+ unsigned char *p;
+
+ p = (unsigned char *)hctx->rndvector;
+ for (i = 0; i < hctx->vectorlen; i += copylen, p += copylen) {
+ isc_random_get(&pr);
+ if (i + sizeof(pr) <= hctx->vectorlen)
+ copylen = sizeof(pr);
+ else
+ copylen = hctx->vectorlen - i;
+
+ memcpy(p, &pr, copylen);
+ }
+ INSIST(p == (unsigned char *)hctx->rndvector +
+ hctx->vectorlen);
+ }
+
+ hctx->initialized = ISC_TRUE;
+
+ out:
+ UNLOCK(&hctx->lock);
+}
+
+void
+isc_hash_init() {
+ INSIST(hash != NULL && VALID_HASH(hash));
+
+ isc_hash_ctxinit(hash);
+}
+
+void
+isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp) {
+ REQUIRE(VALID_HASH(hctx));
+ REQUIRE(hctxp != NULL && *hctxp == NULL);
+
+ isc_refcount_increment(&hctx->refcnt, NULL);
+ *hctxp = hctx;
+}
+
+static void
+destroy(isc_hash_t **hctxp) {
+ isc_hash_t *hctx;
+ isc_mem_t *mctx;
+
+ REQUIRE(hctxp != NULL && *hctxp != NULL);
+ hctx = *hctxp;
+ *hctxp = NULL;
+
+ LOCK(&hctx->lock);
+
+ isc_refcount_destroy(&hctx->refcnt);
+
+ mctx = hctx->mctx;
+ if (hctx->entropy != NULL)
+ isc_entropy_detach(&hctx->entropy);
+ if (hctx->rndvector != NULL)
+ isc_mem_put(mctx, hctx->rndvector, hctx->vectorlen);
+
+ UNLOCK(&hctx->lock);
+
+ DESTROYLOCK(&hctx->lock);
+
+ memset(hctx, 0, sizeof(isc_hash_t));
+ isc_mem_put(mctx, hctx, sizeof(isc_hash_t));
+ isc_mem_detach(&mctx);
+}
+
+void
+isc_hash_ctxdetach(isc_hash_t **hctxp) {
+ isc_hash_t *hctx;
+ unsigned int refs;
+
+ REQUIRE(hctxp != NULL && VALID_HASH(*hctxp));
+ hctx = *hctxp;
+
+ isc_refcount_decrement(&hctx->refcnt, &refs);
+ if (refs == 0)
+ destroy(&hctx);
+
+ *hctxp = NULL;
+}
+
+void
+isc_hash_destroy() {
+ unsigned int refs;
+
+ INSIST(hash != NULL && VALID_HASH(hash));
+
+ isc_refcount_decrement(&hash->refcnt, &refs);
+ INSIST(refs == 0);
+
+ destroy(&hash);
+}
+
+static inline unsigned int
+hash_calc(isc_hash_t *hctx, const unsigned char *key, unsigned int keylen,
+ isc_boolean_t case_sensitive)
+{
+ hash_accum_t partial_sum = 0;
+ hash_random_t *p = hctx->rndvector;
+ unsigned int i = 0;
+
+ /* Make it sure that the hash context is initialized. */
+ if (hctx->initialized == ISC_FALSE)
+ isc_hash_ctxinit(hctx);
+
+ if (case_sensitive) {
+ for (i = 0; i < keylen; i++)
+ partial_sum += key[i] * (hash_accum_t)p[i];
+ } else {
+ for (i = 0; i < keylen; i++)
+ partial_sum += maptolower[key[i]] * (hash_accum_t)p[i];
+ }
+
+ partial_sum += p[i];
+
+ return ((unsigned int)(partial_sum % PRIME32));
+}
+
+unsigned int
+isc_hash_ctxcalc(isc_hash_t *hctx, const unsigned char *key,
+ unsigned int keylen, isc_boolean_t case_sensitive)
+{
+ REQUIRE(hctx != NULL && VALID_HASH(hctx));
+ REQUIRE(keylen <= hctx->limit);
+
+ return (hash_calc(hctx, key, keylen, case_sensitive));
+}
+
+unsigned int
+isc_hash_calc(const unsigned char *key, unsigned int keylen,
+ isc_boolean_t case_sensitive)
+{
+ INSIST(hash != NULL && VALID_HASH(hash));
+ REQUIRE(keylen <= hash->limit);
+
+ return (hash_calc(hash, key, keylen, case_sensitive));
+}
diff --git a/lib/isc/heap.c b/lib/isc/heap.c
new file mode 100644
index 0000000..91d78c0
--- /dev/null
+++ b/lib/isc/heap.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-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: heap.c,v 1.37 2007/10/19 17:15:53 explorer Exp $ */
+
+/*! \file
+ * Heap implementation of priority queues adapted from the following:
+ *
+ * \li "Introduction to Algorithms," Cormen, Leiserson, and Rivest,
+ * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7.
+ *
+ * \li "Algorithms," Second Edition, Sedgewick, Addison-Wesley, 1988,
+ * ISBN 0-201-06673-4, chapter 11.
+ */
+
+#include <config.h>
+
+#include <isc/heap.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/string.h> /* Required for memcpy. */
+#include <isc/util.h>
+
+/*@{*/
+/*%
+ * Note: to make heap_parent and heap_left easy to compute, the first
+ * element of the heap array is not used; i.e. heap subscripts are 1-based,
+ * not 0-based. The parent is index/2, and the left-child is index*2.
+ * The right child is index*2+1.
+ */
+#define heap_parent(i) ((i) >> 1)
+#define heap_left(i) ((i) << 1)
+/*@}*/
+
+#define SIZE_INCREMENT 1024
+
+#define HEAP_MAGIC ISC_MAGIC('H', 'E', 'A', 'P')
+#define VALID_HEAP(h) ISC_MAGIC_VALID(h, HEAP_MAGIC)
+
+/*%
+ * When the heap is in a consistent state, the following invariant
+ * holds true: for every element i > 1, heap_parent(i) has a priority
+ * higher than or equal to that of i.
+ */
+#define HEAPCONDITION(i) ((i) == 1 || \
+ ! heap->compare(heap->array[(i)], \
+ heap->array[heap_parent(i)]))
+
+/*% ISC heap structure. */
+struct isc_heap {
+ unsigned int magic;
+ isc_mem_t * mctx;
+ unsigned int size;
+ unsigned int size_increment;
+ unsigned int last;
+ void **array;
+ isc_heapcompare_t compare;
+ isc_heapindex_t index;
+};
+
+isc_result_t
+isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare,
+ isc_heapindex_t index, unsigned int size_increment,
+ isc_heap_t **heapp)
+{
+ isc_heap_t *heap;
+
+ REQUIRE(heapp != NULL && *heapp == NULL);
+ REQUIRE(compare != NULL);
+
+ heap = isc_mem_get(mctx, sizeof(*heap));
+ if (heap == NULL)
+ return (ISC_R_NOMEMORY);
+ heap->magic = HEAP_MAGIC;
+ heap->mctx = mctx;
+ heap->size = 0;
+ if (size_increment == 0)
+ heap->size_increment = SIZE_INCREMENT;
+ else
+ heap->size_increment = size_increment;
+ heap->last = 0;
+ heap->array = NULL;
+ heap->compare = compare;
+ heap->index = index;
+
+ *heapp = heap;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_heap_destroy(isc_heap_t **heapp) {
+ isc_heap_t *heap;
+
+ REQUIRE(heapp != NULL);
+ heap = *heapp;
+ REQUIRE(VALID_HEAP(heap));
+
+ if (heap->array != NULL)
+ isc_mem_put(heap->mctx, heap->array,
+ heap->size * sizeof(void *));
+ heap->magic = 0;
+ isc_mem_put(heap->mctx, heap, sizeof(*heap));
+
+ *heapp = NULL;
+}
+
+static isc_boolean_t
+resize(isc_heap_t *heap) {
+ void **new_array;
+ size_t new_size;
+
+ REQUIRE(VALID_HEAP(heap));
+
+ new_size = heap->size + heap->size_increment;
+ new_array = isc_mem_get(heap->mctx, new_size * sizeof(void *));
+ if (new_array == NULL)
+ return (ISC_FALSE);
+ if (heap->array != NULL) {
+ memcpy(new_array, heap->array, heap->size * sizeof(void *));
+ isc_mem_put(heap->mctx, heap->array,
+ heap->size * sizeof(void *));
+ }
+ heap->size = new_size;
+ heap->array = new_array;
+
+ return (ISC_TRUE);
+}
+
+static void
+float_up(isc_heap_t *heap, unsigned int i, void *elt) {
+ unsigned int p;
+
+ for (p = heap_parent(i) ;
+ i > 1 && heap->compare(elt, heap->array[p]) ;
+ i = p, p = heap_parent(i)) {
+ heap->array[i] = heap->array[p];
+ if (heap->index != NULL)
+ (heap->index)(heap->array[i], i);
+ }
+ heap->array[i] = elt;
+ if (heap->index != NULL)
+ (heap->index)(heap->array[i], i);
+
+ INSIST(HEAPCONDITION(i));
+}
+
+static void
+sink_down(isc_heap_t *heap, unsigned int i, void *elt) {
+ unsigned int j, size, half_size;
+ size = heap->last;
+ half_size = size / 2;
+ while (i <= half_size) {
+ /* Find the smallest of the (at most) two children. */
+ j = heap_left(i);
+ if (j < size && heap->compare(heap->array[j+1],
+ heap->array[j]))
+ j++;
+ if (heap->compare(elt, heap->array[j]))
+ break;
+ heap->array[i] = heap->array[j];
+ if (heap->index != NULL)
+ (heap->index)(heap->array[i], i);
+ i = j;
+ }
+ heap->array[i] = elt;
+ if (heap->index != NULL)
+ (heap->index)(heap->array[i], i);
+
+ INSIST(HEAPCONDITION(i));
+}
+
+isc_result_t
+isc_heap_insert(isc_heap_t *heap, void *elt) {
+ unsigned int i;
+
+ REQUIRE(VALID_HEAP(heap));
+
+ i = ++heap->last;
+ if (heap->last >= heap->size && !resize(heap))
+ return (ISC_R_NOMEMORY);
+
+ float_up(heap, i, elt);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_heap_delete(isc_heap_t *heap, unsigned int index) {
+ void *elt;
+ isc_boolean_t less;
+
+ REQUIRE(VALID_HEAP(heap));
+ REQUIRE(index >= 1 && index <= heap->last);
+
+ if (index == heap->last) {
+ heap->array[heap->last] = NULL;
+ heap->last--;
+ } else {
+ elt = heap->array[heap->last];
+ heap->array[heap->last] = NULL;
+ heap->last--;
+
+ less = heap->compare(elt, heap->array[index]);
+ heap->array[index] = elt;
+ if (less)
+ float_up(heap, index, heap->array[index]);
+ else
+ sink_down(heap, index, heap->array[index]);
+ }
+}
+
+void
+isc_heap_increased(isc_heap_t *heap, unsigned int index) {
+ REQUIRE(VALID_HEAP(heap));
+ REQUIRE(index >= 1 && index <= heap->last);
+
+ float_up(heap, index, heap->array[index]);
+}
+
+void
+isc_heap_decreased(isc_heap_t *heap, unsigned int index) {
+ REQUIRE(VALID_HEAP(heap));
+ REQUIRE(index >= 1 && index <= heap->last);
+
+ sink_down(heap, index, heap->array[index]);
+}
+
+void *
+isc_heap_element(isc_heap_t *heap, unsigned int index) {
+ REQUIRE(VALID_HEAP(heap));
+ REQUIRE(index >= 1);
+
+ if (index <= heap->last)
+ return (heap->array[index]);
+ return (NULL);
+}
+
+void
+isc_heap_foreach(isc_heap_t *heap, isc_heapaction_t action, void *uap) {
+ unsigned int i;
+
+ REQUIRE(VALID_HEAP(heap));
+ REQUIRE(action != NULL);
+
+ for (i = 1 ; i <= heap->last ; i++)
+ (action)(heap->array[i], uap);
+}
diff --git a/lib/isc/hex.c b/lib/isc/hex.c
new file mode 100644
index 0000000..3fa0e69
--- /dev/null
+++ b/lib/isc/hex.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 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
+ * 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: hex.c,v 1.20 2008/09/25 04:02:39 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+
+#include <isc/buffer.h>
+#include <isc/hex.h>
+#include <isc/lex.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#define RETERR(x) do { \
+ isc_result_t _r = (x); \
+ if (_r != ISC_R_SUCCESS) \
+ return (_r); \
+ } while (0)
+
+
+/*
+ * BEW: These static functions are copied from lib/dns/rdata.c.
+ */
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target);
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length);
+
+static const char hex[] = "0123456789ABCDEF";
+
+isc_result_t
+isc_hex_totext(isc_region_t *source, int wordlength,
+ const char *wordbreak, isc_buffer_t *target)
+{
+ char buf[3];
+ unsigned int loops = 0;
+
+ if (wordlength < 2)
+ wordlength = 2;
+
+ memset(buf, 0, sizeof(buf));
+ while (source->length > 0) {
+ buf[0] = hex[(source->base[0] >> 4) & 0xf];
+ buf[1] = hex[(source->base[0]) & 0xf];
+ RETERR(str_totext(buf, target));
+ isc_region_consume(source, 1);
+
+ loops++;
+ if (source->length != 0 &&
+ (int)((loops + 1) * 2) >= wordlength)
+ {
+ loops = 0;
+ RETERR(str_totext(wordbreak, target));
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * State of a hex decoding process in progress.
+ */
+typedef struct {
+ int length; /*%< Desired length of binary data or -1 */
+ isc_buffer_t *target; /*%< Buffer for resulting binary data */
+ int digits; /*%< Number of buffered hex digits */
+ int val[2];
+} hex_decode_ctx_t;
+
+static inline void
+hex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target)
+{
+ ctx->digits = 0;
+ ctx->length = length;
+ ctx->target = target;
+}
+
+static inline isc_result_t
+hex_decode_char(hex_decode_ctx_t *ctx, int c) {
+ char *s;
+
+ if ((s = strchr(hex, toupper(c))) == NULL)
+ return (ISC_R_BADHEX);
+ ctx->val[ctx->digits++] = s - hex;
+ if (ctx->digits == 2) {
+ unsigned char num;
+
+ num = (ctx->val[0] << 4) + (ctx->val[1]);
+ RETERR(mem_tobuffer(ctx->target, &num, 1));
+ if (ctx->length >= 0) {
+ if (ctx->length == 0)
+ return (ISC_R_BADHEX);
+ else
+ ctx->length -= 1;
+ }
+ ctx->digits = 0;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static inline isc_result_t
+hex_decode_finish(hex_decode_ctx_t *ctx) {
+ if (ctx->length > 0)
+ return (ISC_R_UNEXPECTEDEND);
+ if (ctx->digits != 0)
+ return (ISC_R_BADHEX);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
+ hex_decode_ctx_t ctx;
+ isc_textregion_t *tr;
+ isc_token_t token;
+ isc_boolean_t eol;
+
+ hex_decode_init(&ctx, length, target);
+
+ while (ctx.length != 0) {
+ unsigned int i;
+
+ if (length > 0)
+ eol = ISC_FALSE;
+ else
+ eol = ISC_TRUE;
+ RETERR(isc_lex_getmastertoken(lexer, &token,
+ isc_tokentype_string, eol));
+ if (token.type != isc_tokentype_string)
+ break;
+ tr = &token.value.as_textregion;
+ for (i = 0; i < tr->length; i++)
+ RETERR(hex_decode_char(&ctx, tr->base[i]));
+ }
+ if (ctx.length < 0)
+ isc_lex_ungettoken(lexer, &token);
+ RETERR(hex_decode_finish(&ctx));
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
+ hex_decode_ctx_t ctx;
+
+ hex_decode_init(&ctx, -1, target);
+ for (;;) {
+ int c = *cstr++;
+ if (c == '\0')
+ break;
+ if (c == ' ' || c == '\t' || c == '\n' || c== '\r')
+ continue;
+ RETERR(hex_decode_char(&ctx, c));
+ }
+ RETERR(hex_decode_finish(&ctx));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+str_totext(const char *source, isc_buffer_t *target) {
+ unsigned int l;
+ isc_region_t region;
+
+ isc_buffer_availableregion(target, &region);
+ l = strlen(source);
+
+ if (l > region.length)
+ return (ISC_R_NOSPACE);
+
+ memcpy(region.base, source, l);
+ isc_buffer_add(target, l);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+mem_tobuffer(isc_buffer_t *target, void *base, unsigned int length) {
+ isc_region_t tr;
+
+ isc_buffer_availableregion(target, &tr);
+ if (length > tr.length)
+ return (ISC_R_NOSPACE);
+ memcpy(tr.base, base, length);
+ isc_buffer_add(target, length);
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/hmacmd5.c b/lib/isc/hmacmd5.c
new file mode 100644
index 0000000..63853dc
--- /dev/null
+++ b/lib/isc/hmacmd5.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2004-2007 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: hmacmd5.c,v 1.14 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file
+ * This code implements the HMAC-MD5 keyed hash algorithm
+ * described in RFC2104.
+ */
+
+#include "config.h"
+
+#include <isc/assertions.h>
+#include <isc/hmacmd5.h>
+#include <isc/md5.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#define PADLEN 64
+#define IPAD 0x36
+#define OPAD 0x5C
+
+/*!
+ * Start HMAC-MD5 process. Initialize an md5 context and digest the key.
+ */
+void
+isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ unsigned char ipad[PADLEN];
+ int i;
+
+ memset(ctx->key, 0, sizeof(ctx->key));
+ if (len > sizeof(ctx->key)) {
+ isc_md5_t md5ctx;
+ isc_md5_init(&md5ctx);
+ isc_md5_update(&md5ctx, key, len);
+ isc_md5_final(&md5ctx, ctx->key);
+ } else
+ memcpy(ctx->key, key, len);
+
+ isc_md5_init(&ctx->md5ctx);
+ memset(ipad, IPAD, sizeof(ipad));
+ for (i = 0; i < PADLEN; i++)
+ ipad[i] ^= ctx->key[i];
+ isc_md5_update(&ctx->md5ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx) {
+ isc_md5_invalidate(&ctx->md5ctx);
+ memset(ctx->key, 0, sizeof(ctx->key));
+}
+
+/*!
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ isc_md5_update(&ctx->md5ctx, buf, len);
+}
+
+/*!
+ * Compute signature - finalize MD5 operation and reapply MD5.
+ */
+void
+isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest) {
+ unsigned char opad[PADLEN];
+ int i;
+
+ isc_md5_final(&ctx->md5ctx, digest);
+
+ memset(opad, OPAD, sizeof(opad));
+ for (i = 0; i < PADLEN; i++)
+ opad[i] ^= ctx->key[i];
+
+ isc_md5_init(&ctx->md5ctx);
+ isc_md5_update(&ctx->md5ctx, opad, sizeof(opad));
+ isc_md5_update(&ctx->md5ctx, digest, ISC_MD5_DIGESTLENGTH);
+ isc_md5_final(&ctx->md5ctx, digest);
+ isc_hmacmd5_invalidate(ctx);
+}
+
+/*!
+ * Verify signature - finalize MD5 operation and reapply MD5, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest) {
+ return (isc_hmacmd5_verify2(ctx, digest, ISC_MD5_DIGESTLENGTH));
+}
+
+isc_boolean_t
+isc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_MD5_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_MD5_DIGESTLENGTH);
+ isc_hmacmd5_sign(ctx, newdigest);
+ return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
diff --git a/lib/isc/hmacsha.c b/lib/isc/hmacsha.c
new file mode 100644
index 0000000..dfcd8bf
--- /dev/null
+++ b/lib/isc/hmacsha.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2005-2007 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: hmacsha.c,v 1.8 2007/08/27 03:27:53 marka Exp $ */
+
+/*
+ * This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384
+ * and HMAC-SHA512 keyed hash algorithm described in RFC 2104 and
+ * draft-ietf-dnsext-tsig-sha-01.txt.
+ */
+
+#include "config.h"
+
+#include <isc/assertions.h>
+#include <isc/hmacsha.h>
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#define IPAD 0x36
+#define OPAD 0x5C
+
+/*
+ * Start HMAC-SHA1 process. Initialize an sha1 context and digest the key.
+ */
+void
+isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ unsigned char ipad[ISC_SHA1_BLOCK_LENGTH];
+ unsigned int i;
+
+ memset(ctx->key, 0, sizeof(ctx->key));
+ if (len > sizeof(ctx->key)) {
+ isc_sha1_t sha1ctx;
+ isc_sha1_init(&sha1ctx);
+ isc_sha1_update(&sha1ctx, key, len);
+ isc_sha1_final(&sha1ctx, ctx->key);
+ } else
+ memcpy(ctx->key, key, len);
+
+ isc_sha1_init(&ctx->sha1ctx);
+ memset(ipad, IPAD, sizeof(ipad));
+ for (i = 0; i < ISC_SHA1_BLOCK_LENGTH; i++)
+ ipad[i] ^= ctx->key[i];
+ isc_sha1_update(&ctx->sha1ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
+ isc_sha1_invalidate(&ctx->sha1ctx);
+ memset(ctx->key, 0, sizeof(ctx->key));
+ memset(ctx, 0, sizeof(ctx));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ isc_sha1_update(&ctx->sha1ctx, buf, len);
+}
+
+/*
+ * Compute signature - finalize SHA1 operation and reapply SHA1.
+ */
+void
+isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char opad[ISC_SHA1_BLOCK_LENGTH];
+ unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
+ unsigned int i;
+
+ REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
+ isc_sha1_final(&ctx->sha1ctx, newdigest);
+
+ memset(opad, OPAD, sizeof(opad));
+ for (i = 0; i < ISC_SHA1_BLOCK_LENGTH; i++)
+ opad[i] ^= ctx->key[i];
+
+ isc_sha1_init(&ctx->sha1ctx);
+ isc_sha1_update(&ctx->sha1ctx, opad, sizeof(opad));
+ isc_sha1_update(&ctx->sha1ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
+ isc_sha1_final(&ctx->sha1ctx, newdigest);
+ isc_hmacsha1_invalidate(ctx);
+ memcpy(digest, newdigest, len);
+ memset(newdigest, 0, sizeof(newdigest));
+}
+
+/*
+ * 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
+isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ unsigned char ipad[ISC_SHA224_BLOCK_LENGTH];
+ unsigned int i;
+
+ memset(ctx->key, 0, sizeof(ctx->key));
+ if (len > sizeof(ctx->key)) {
+ isc_sha224_t sha224ctx;
+ isc_sha224_init(&sha224ctx);
+ isc_sha224_update(&sha224ctx, key, len);
+ isc_sha224_final(ctx->key, &sha224ctx);
+ } else
+ memcpy(ctx->key, key, len);
+
+ isc_sha224_init(&ctx->sha224ctx);
+ memset(ipad, IPAD, sizeof(ipad));
+ for (i = 0; i < ISC_SHA224_BLOCK_LENGTH; i++)
+ ipad[i] ^= ctx->key[i];
+ isc_sha224_update(&ctx->sha224ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
+ memset(ctx->key, 0, sizeof(ctx->key));
+ memset(ctx, 0, sizeof(ctx));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ isc_sha224_update(&ctx->sha224ctx, buf, len);
+}
+
+/*
+ * Compute signature - finalize SHA224 operation and reapply SHA224.
+ */
+void
+isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char opad[ISC_SHA224_BLOCK_LENGTH];
+ unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
+ unsigned int i;
+
+ REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
+ isc_sha224_final(newdigest, &ctx->sha224ctx);
+
+ memset(opad, OPAD, sizeof(opad));
+ for (i = 0; i < ISC_SHA224_BLOCK_LENGTH; i++)
+ opad[i] ^= ctx->key[i];
+
+ isc_sha224_init(&ctx->sha224ctx);
+ isc_sha224_update(&ctx->sha224ctx, opad, sizeof(opad));
+ isc_sha224_update(&ctx->sha224ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
+ isc_sha224_final(newdigest, &ctx->sha224ctx);
+ memcpy(digest, newdigest, len);
+ memset(newdigest, 0, sizeof(newdigest));
+}
+
+/*
+ * 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
+isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ unsigned char ipad[ISC_SHA256_BLOCK_LENGTH];
+ unsigned int i;
+
+ memset(ctx->key, 0, sizeof(ctx->key));
+ if (len > sizeof(ctx->key)) {
+ isc_sha256_t sha256ctx;
+ isc_sha256_init(&sha256ctx);
+ isc_sha256_update(&sha256ctx, key, len);
+ isc_sha256_final(ctx->key, &sha256ctx);
+ } else
+ memcpy(ctx->key, key, len);
+
+ isc_sha256_init(&ctx->sha256ctx);
+ memset(ipad, IPAD, sizeof(ipad));
+ for (i = 0; i < ISC_SHA256_BLOCK_LENGTH; i++)
+ ipad[i] ^= ctx->key[i];
+ isc_sha256_update(&ctx->sha256ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
+ memset(ctx->key, 0, sizeof(ctx->key));
+ memset(ctx, 0, sizeof(ctx));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ isc_sha256_update(&ctx->sha256ctx, buf, len);
+}
+
+/*
+ * Compute signature - finalize SHA256 operation and reapply SHA256.
+ */
+void
+isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char opad[ISC_SHA256_BLOCK_LENGTH];
+ unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
+ unsigned int i;
+
+ REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
+ isc_sha256_final(newdigest, &ctx->sha256ctx);
+
+ memset(opad, OPAD, sizeof(opad));
+ for (i = 0; i < ISC_SHA256_BLOCK_LENGTH; i++)
+ opad[i] ^= ctx->key[i];
+
+ isc_sha256_init(&ctx->sha256ctx);
+ isc_sha256_update(&ctx->sha256ctx, opad, sizeof(opad));
+ isc_sha256_update(&ctx->sha256ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
+ isc_sha256_final(newdigest, &ctx->sha256ctx);
+ memcpy(digest, newdigest, len);
+ memset(newdigest, 0, sizeof(newdigest));
+}
+
+/*
+ * 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
+isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ unsigned char ipad[ISC_SHA384_BLOCK_LENGTH];
+ unsigned int i;
+
+ memset(ctx->key, 0, sizeof(ctx->key));
+ if (len > sizeof(ctx->key)) {
+ isc_sha384_t sha384ctx;
+ isc_sha384_init(&sha384ctx);
+ isc_sha384_update(&sha384ctx, key, len);
+ isc_sha384_final(ctx->key, &sha384ctx);
+ } else
+ memcpy(ctx->key, key, len);
+
+ isc_sha384_init(&ctx->sha384ctx);
+ memset(ipad, IPAD, sizeof(ipad));
+ for (i = 0; i < ISC_SHA384_BLOCK_LENGTH; i++)
+ ipad[i] ^= ctx->key[i];
+ isc_sha384_update(&ctx->sha384ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
+ memset(ctx->key, 0, sizeof(ctx->key));
+ memset(ctx, 0, sizeof(ctx));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ isc_sha384_update(&ctx->sha384ctx, buf, len);
+}
+
+/*
+ * Compute signature - finalize SHA384 operation and reapply SHA384.
+ */
+void
+isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char opad[ISC_SHA384_BLOCK_LENGTH];
+ unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
+ unsigned int i;
+
+ REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
+ isc_sha384_final(newdigest, &ctx->sha384ctx);
+
+ memset(opad, OPAD, sizeof(opad));
+ for (i = 0; i < ISC_SHA384_BLOCK_LENGTH; i++)
+ opad[i] ^= ctx->key[i];
+
+ isc_sha384_init(&ctx->sha384ctx);
+ isc_sha384_update(&ctx->sha384ctx, opad, sizeof(opad));
+ isc_sha384_update(&ctx->sha384ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
+ isc_sha384_final(newdigest, &ctx->sha384ctx);
+ memcpy(digest, newdigest, len);
+ memset(newdigest, 0, sizeof(newdigest));
+}
+
+/*
+ * 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
+isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
+ unsigned int len)
+{
+ unsigned char ipad[ISC_SHA512_BLOCK_LENGTH];
+ unsigned int i;
+
+ memset(ctx->key, 0, sizeof(ctx->key));
+ if (len > sizeof(ctx->key)) {
+ isc_sha512_t sha512ctx;
+ isc_sha512_init(&sha512ctx);
+ isc_sha512_update(&sha512ctx, key, len);
+ isc_sha512_final(ctx->key, &sha512ctx);
+ } else
+ memcpy(ctx->key, key, len);
+
+ isc_sha512_init(&ctx->sha512ctx);
+ memset(ipad, IPAD, sizeof(ipad));
+ for (i = 0; i < ISC_SHA512_BLOCK_LENGTH; i++)
+ ipad[i] ^= ctx->key[i];
+ isc_sha512_update(&ctx->sha512ctx, ipad, sizeof(ipad));
+}
+
+void
+isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
+ memset(ctx->key, 0, sizeof(ctx->key));
+ memset(ctx, 0, sizeof(ctx));
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
+ unsigned int len)
+{
+ isc_sha512_update(&ctx->sha512ctx, buf, len);
+}
+
+/*
+ * Compute signature - finalize SHA512 operation and reapply SHA512.
+ */
+void
+isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char opad[ISC_SHA512_BLOCK_LENGTH];
+ unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
+ unsigned int i;
+
+ REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
+ isc_sha512_final(newdigest, &ctx->sha512ctx);
+
+ memset(opad, OPAD, sizeof(opad));
+ for (i = 0; i < ISC_SHA512_BLOCK_LENGTH; i++)
+ opad[i] ^= ctx->key[i];
+
+ isc_sha512_init(&ctx->sha512ctx);
+ isc_sha512_update(&ctx->sha512ctx, opad, sizeof(opad));
+ isc_sha512_update(&ctx->sha512ctx, newdigest, ISC_SHA512_DIGESTLENGTH);
+ isc_sha512_final(newdigest, &ctx->sha512ctx);
+ memcpy(digest, newdigest, len);
+ memset(newdigest, 0, sizeof(newdigest));
+}
+
+/*
+ * Verify signature - finalize SHA512 operation and reapply SHA512, then
+ * compare to the supplied digest.
+ */
+isc_boolean_t
+isc_hmacsha512_verify(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
+ unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
+
+ REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
+ isc_hmacsha512_sign(ctx, newdigest, ISC_SHA512_DIGESTLENGTH);
+ return (ISC_TF(memcmp(digest, newdigest, len) == 0));
+}
diff --git a/lib/isc/httpd.c b/lib/isc/httpd.c
new file mode 100644
index 0000000..fa31325
--- /dev/null
+++ b/lib/isc/httpd.c
@@ -0,0 +1,987 @@
+/*
+ * Copyright (C) 2006-2008 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: httpd.c,v 1.16 2008/08/08 05:06:49 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/httpd.h>
+#include <isc/mem.h>
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <string.h>
+
+/*%
+ * TODO:
+ *
+ * o Put in better checks to make certain things are passed in correctly.
+ * This includes a magic number for externally-visible structures,
+ * checking for NULL-ness before dereferencing, etc.
+ * o Make the URL processing external functions which will fill-in a buffer
+ * structure we provide, or return an error and we will render a generic
+ * page and close the client.
+ */
+
+#define MSHUTTINGDOWN(cm) ((cm->flags & ISC_HTTPDMGR_FLAGSHUTTINGDOWN) != 0)
+#define MSETSHUTTINGDOWN(cm) (cm->flags |= ISC_HTTPDMGR_FLAGSHUTTINGDOWN)
+
+#ifdef DEBUG_HTTPD
+#define ENTER(x) do { fprintf(stderr, "ENTER %s\n", (x)); } while (0)
+#define EXIT(x) do { fprintf(stderr, "EXIT %s\n", (x)); } while (0)
+#define NOTICE(x) do { fprintf(stderr, "NOTICE %s\n", (x)); } while (0)
+#else
+#define ENTER(x) do { } while(0)
+#define EXIT(x) do { } while(0)
+#define NOTICE(x) do { } while(0)
+#endif
+
+#define HTTP_RECVLEN 1024
+#define HTTP_SENDGROW 1024
+#define HTTP_SEND_MAXLEN 10240
+
+/*%
+ * HTTP urls. These are the URLs we manage, and the function to call to
+ * provide the data for it. We pass in the base url (so the same function
+ * can handle multiple requests), and a structure to fill in to return a
+ * result to the client. We also pass in a pointer to be filled in for
+ * the data cleanup function.
+ */
+struct isc_httpdurl {
+ char *url;
+ isc_httpdaction_t *action;
+ void *action_arg;
+ ISC_LINK(isc_httpdurl_t) link;
+};
+
+#define HTTPD_CLOSE 0x0001 /* Got a Connection: close header */
+#define HTTPD_FOUNDHOST 0x0002 /* Got a Host: header */
+
+/*% http client */
+struct isc_httpd {
+ isc_httpdmgr_t *mgr; /*%< our parent */
+ ISC_LINK(isc_httpd_t) link;
+ unsigned int state;
+ isc_socket_t *sock;
+
+ /*%
+ * Received data state.
+ */
+ char recvbuf[HTTP_RECVLEN]; /*%< receive buffer */
+ isc_uint32_t recvlen; /*%< length recv'd */
+ unsigned int method;
+ char *url;
+ char *querystring;
+ char *protocol;
+
+ /*
+ * Flags on the httpd client.
+ */
+ int flags;
+
+ /*%
+ * Transmit data state.
+ *
+ * This is the data buffer we will transmit.
+ *
+ * This free function pointer is filled in by the rendering function
+ * we call. The free function is called after the data is transmitted
+ * to the client.
+ *
+ * The bufflist is the list of buffers we are currently transmitting.
+ * The headerdata is where we render our headers to. If we run out of
+ * space when rendering a header, we will change the size of our
+ * buffer. We will not free it until we are finished, and will
+ * allocate an additional HTTP_SENDGROW bytes per header space grow.
+ *
+ * We currently use two buffers total, one for the headers (which
+ * we manage) and another for the client to fill in (which it manages,
+ * it provides the space for it, etc) -- we will pass that buffer
+ * structure back to the caller, who is responsible for managing the
+ * space it may have allocated as backing store for it. This second
+ * buffer is bodybuffer, and we only allocate the buffer itself, not
+ * the backing store.
+ */
+ isc_bufferlist_t bufflist;
+ char *headerdata; /*%< send header buf */
+ unsigned int headerlen; /*%< current header buffer size */
+ isc_buffer_t headerbuffer;
+
+ const char *mimetype;
+ unsigned int retcode;
+ const char *retmsg;
+ isc_buffer_t bodybuffer;
+ isc_httpdfree_t *freecb;
+ void *freecb_arg;
+};
+
+/*% lightweight socket manager for httpd output */
+struct isc_httpdmgr {
+ isc_mem_t *mctx;
+ isc_socket_t *sock; /*%< listening socket */
+ isc_task_t *task; /*%< owning task */
+ isc_timermgr_t *timermgr;
+
+ isc_httpdclientok_t *client_ok; /*%< client validator */
+ isc_httpdondestroy_t *ondestroy; /*%< cleanup callback */
+ void *cb_arg; /*%< argument for the above */
+
+ unsigned int flags;
+ ISC_LIST(isc_httpd_t) running; /*%< running clients */
+
+ isc_mutex_t lock;
+
+ ISC_LIST(isc_httpdurl_t) urls; /*%< urls we manage */
+ isc_httpdaction_t *render_404;
+};
+
+/*%
+ * HTTP methods.
+ */
+#define ISC_HTTPD_METHODUNKNOWN 0
+#define ISC_HTTPD_METHODGET 1
+#define ISC_HTTPD_METHODPOST 2
+
+/*%
+ * Client states.
+ *
+ * _IDLE The client is not doing anything at all. This state should
+ * only occur just after creation, and just before being
+ * destroyed.
+ *
+ * _RECV The client is waiting for data after issuing a socket recv().
+ *
+ * _RECVDONE Data has been received, and is being processed.
+ *
+ * _SEND All data for a response has completed, and a reply was
+ * sent via a socket send() call.
+ *
+ * _SENDDONE Send is completed.
+ *
+ * Badly formatted state table:
+ *
+ * IDLE -> RECV when client has a recv() queued.
+ *
+ * RECV -> RECVDONE when recvdone event received.
+ *
+ * RECVDONE -> SEND if the data for a reply is at hand.
+ *
+ * SEND -> RECV when a senddone event was received.
+ *
+ * At any time -> RECV on error. If RECV fails, the client will
+ * self-destroy, closing the socket and freeing memory.
+ */
+#define ISC_HTTPD_STATEIDLE 0
+#define ISC_HTTPD_STATERECV 1
+#define ISC_HTTPD_STATERECVDONE 2
+#define ISC_HTTPD_STATESEND 3
+#define ISC_HTTPD_STATESENDDONE 4
+
+#define ISC_HTTPD_ISRECV(c) ((c)->state == ISC_HTTPD_STATERECV)
+#define ISC_HTTPD_ISRECVDONE(c) ((c)->state == ISC_HTTPD_STATERECVDONE)
+#define ISC_HTTPD_ISSEND(c) ((c)->state == ISC_HTTPD_STATESEND)
+#define ISC_HTTPD_ISSENDDONE(c) ((c)->state == ISC_HTTPD_STATESENDDONE)
+
+/*%
+ * Overall magic test that means we're not idle.
+ */
+#define ISC_HTTPD_SETRECV(c) ((c)->state = ISC_HTTPD_STATERECV)
+#define ISC_HTTPD_SETRECVDONE(c) ((c)->state = ISC_HTTPD_STATERECVDONE)
+#define ISC_HTTPD_SETSEND(c) ((c)->state = ISC_HTTPD_STATESEND)
+#define ISC_HTTPD_SETSENDDONE(c) ((c)->state = ISC_HTTPD_STATESENDDONE)
+
+static void isc_httpd_accept(isc_task_t *, isc_event_t *);
+static void isc_httpd_recvdone(isc_task_t *, isc_event_t *);
+static void isc_httpd_senddone(isc_task_t *, isc_event_t *);
+static void destroy_client(isc_httpd_t **);
+static isc_result_t process_request(isc_httpd_t *, int);
+static void httpdmgr_destroy(isc_httpdmgr_t *);
+static isc_result_t grow_headerspace(isc_httpd_t *);
+static void reset_client(isc_httpd_t *httpd);
+static isc_result_t render_404(const char *, const char *,
+ void *,
+ unsigned int *, const char **,
+ const char **, isc_buffer_t *,
+ isc_httpdfree_t **, void **);
+
+static void
+destroy_client(isc_httpd_t **httpdp)
+{
+ isc_httpd_t *httpd = *httpdp;
+ isc_httpdmgr_t *httpdmgr = httpd->mgr;
+
+ *httpdp = NULL;
+
+ LOCK(&httpdmgr->lock);
+
+ isc_socket_detach(&httpd->sock);
+ ISC_LIST_UNLINK(httpdmgr->running, httpd, link);
+
+ if (httpd->headerlen > 0)
+ isc_mem_put(httpdmgr->mctx, httpd->headerdata,
+ httpd->headerlen);
+
+ isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t));
+
+ UNLOCK(&httpdmgr->lock);
+
+ httpdmgr_destroy(httpdmgr);
+}
+
+isc_result_t
+isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
+ isc_httpdclientok_t *client_ok,
+ isc_httpdondestroy_t *ondestroy, void *cb_arg,
+ isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp)
+{
+ isc_result_t result;
+ isc_httpdmgr_t *httpd;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(sock != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(tmgr != NULL);
+ REQUIRE(httpdp != NULL && *httpdp == NULL);
+
+ httpd = isc_mem_get(mctx, sizeof(isc_httpdmgr_t));
+ if (httpd == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = isc_mutex_init(&httpd->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t));
+ return (result);
+ }
+ httpd->mctx = NULL;
+ isc_mem_attach(mctx, &httpd->mctx);
+ httpd->sock = NULL;
+ isc_socket_attach(sock, &httpd->sock);
+ httpd->task = NULL;
+ isc_task_attach(task, &httpd->task);
+ httpd->timermgr = tmgr; /* XXXMLG no attach function? */
+ httpd->client_ok = client_ok;
+ httpd->ondestroy = ondestroy;
+ httpd->cb_arg = cb_arg;
+
+ ISC_LIST_INIT(httpd->running);
+ ISC_LIST_INIT(httpd->urls);
+
+ /* XXXMLG ignore errors on isc_socket_listen() */
+ result = isc_socket_listen(sock, SOMAXCONN);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_socket_listen() failed: %s",
+ isc_result_totext(result));
+ goto cleanup;
+ }
+
+ (void)isc_socket_filter(sock, "httpready");
+
+ result = isc_socket_accept(sock, task, isc_httpd_accept, httpd);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ httpd->render_404 = render_404;
+
+ *httpdp = httpd;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_task_detach(&httpd->task);
+ isc_socket_detach(&httpd->sock);
+ isc_mem_detach(&httpd->mctx);
+ isc_mutex_destroy(&httpd->lock);
+ isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t));
+ return (result);
+}
+
+static void
+httpdmgr_destroy(isc_httpdmgr_t *httpdmgr)
+{
+ isc_mem_t *mctx;
+ isc_httpdurl_t *url;
+
+ ENTER("httpdmgr_destroy");
+
+ LOCK(&httpdmgr->lock);
+
+ if (!MSHUTTINGDOWN(httpdmgr)) {
+ NOTICE("httpdmgr_destroy not shutting down yet");
+ UNLOCK(&httpdmgr->lock);
+ return;
+ }
+
+ /*
+ * If all clients are not shut down, don't do anything yet.
+ */
+ if (!ISC_LIST_EMPTY(httpdmgr->running)) {
+ NOTICE("httpdmgr_destroy clients still active");
+ UNLOCK(&httpdmgr->lock);
+ return;
+ }
+
+ NOTICE("httpdmgr_destroy detaching socket, task, and timermgr");
+
+ isc_socket_detach(&httpdmgr->sock);
+ isc_task_detach(&httpdmgr->task);
+ httpdmgr->timermgr = NULL;
+
+ /*
+ * Clear out the list of all actions we know about. Just free the
+ * memory.
+ */
+ url = ISC_LIST_HEAD(httpdmgr->urls);
+ while (url != NULL) {
+ isc_mem_free(httpdmgr->mctx, url->url);
+ ISC_LIST_UNLINK(httpdmgr->urls, url, link);
+ isc_mem_put(httpdmgr->mctx, url, sizeof(isc_httpdurl_t));
+ url = ISC_LIST_HEAD(httpdmgr->urls);
+ }
+
+ UNLOCK(&httpdmgr->lock);
+ isc_mutex_destroy(&httpdmgr->lock);
+
+ if (httpdmgr->ondestroy != NULL)
+ (httpdmgr->ondestroy)(httpdmgr->cb_arg);
+
+ mctx = httpdmgr->mctx;
+ isc_mem_putanddetach(&mctx, httpdmgr, sizeof(isc_httpdmgr_t));
+
+ EXIT("httpdmgr_destroy");
+}
+
+#define LENGTHOK(s) (httpd->recvbuf - (s) < (int)httpd->recvlen)
+#define BUFLENOK(s) (httpd->recvbuf - (s) < HTTP_RECVLEN)
+
+static isc_result_t
+process_request(isc_httpd_t *httpd, int length)
+{
+ char *s;
+ char *p;
+ int delim;
+
+ ENTER("request");
+
+ httpd->recvlen += length;
+
+ httpd->recvbuf[httpd->recvlen] = 0;
+
+ /*
+ * If we don't find a blank line in our buffer, return that we need
+ * more data.
+ */
+ s = strstr(httpd->recvbuf, "\r\n\r\n");
+ delim = 1;
+ if (s == NULL) {
+ s = strstr(httpd->recvbuf, "\n\n");
+ delim = 2;
+ }
+ if (s == NULL)
+ return (ISC_R_NOTFOUND);
+
+ /*
+ * Determine if this is a POST or GET method. Any other values will
+ * cause an error to be returned.
+ */
+ if (strncmp(httpd->recvbuf, "GET ", 4) == 0) {
+ httpd->method = ISC_HTTPD_METHODGET;
+ p = httpd->recvbuf + 4;
+ } else if (strncmp(httpd->recvbuf, "POST ", 5) == 0) {
+ httpd->method = ISC_HTTPD_METHODPOST;
+ p = httpd->recvbuf + 5;
+ } else {
+ return (ISC_R_RANGE);
+ }
+
+ /*
+ * From now on, p is the start of our buffer.
+ */
+
+ /*
+ * Extract the URL.
+ */
+ s = p;
+ while (LENGTHOK(s) && BUFLENOK(s) &&
+ (*s != '\n' && *s != '\r' && *s != '\0' && *s != ' '))
+ s++;
+ if (!LENGTHOK(s))
+ return (ISC_R_NOTFOUND);
+ if (!BUFLENOK(s))
+ return (ISC_R_NOMEMORY);
+ *s = 0;
+
+ /*
+ * Make the URL relative.
+ */
+ if ((strncmp(p, "http:/", 6) == 0)
+ || (strncmp(p, "https:/", 7) == 0)) {
+ /* Skip first / */
+ while (*p != '/' && *p != 0)
+ p++;
+ if (*p == 0)
+ return (ISC_R_RANGE);
+ p++;
+ /* Skip second / */
+ while (*p != '/' && *p != 0)
+ p++;
+ if (*p == 0)
+ return (ISC_R_RANGE);
+ p++;
+ /* Find third / */
+ while (*p != '/' && *p != 0)
+ p++;
+ if (*p == 0) {
+ p--;
+ *p = '/';
+ }
+ }
+
+ httpd->url = p;
+ p = s + delim;
+ s = p;
+
+ /*
+ * Now, see if there is a ? mark in the URL. If so, this is
+ * part of the query string, and we will split it from the URL.
+ */
+ httpd->querystring = strchr(httpd->url, '?');
+ if (httpd->querystring != NULL) {
+ *(httpd->querystring) = 0;
+ httpd->querystring++;
+ }
+
+ /*
+ * Extract the HTTP/1.X protocol. We will bounce on anything but
+ * HTTP/1.1 for now.
+ */
+ while (LENGTHOK(s) && BUFLENOK(s) &&
+ (*s != '\n' && *s != '\r' && *s != '\0'))
+ s++;
+ if (!LENGTHOK(s))
+ return (ISC_R_NOTFOUND);
+ if (!BUFLENOK(s))
+ return (ISC_R_NOMEMORY);
+ *s = 0;
+ if ((strncmp(p, "HTTP/1.0", 8) != 0)
+ && (strncmp(p, "HTTP/1.1", 8) != 0))
+ return (ISC_R_RANGE);
+ httpd->protocol = p;
+ p = s + 1;
+ s = p;
+
+ if (strstr(s, "Connection: close") != NULL)
+ httpd->flags |= HTTPD_CLOSE;
+
+ if (strstr(s, "Host: ") != NULL)
+ httpd->flags |= HTTPD_FOUNDHOST;
+
+ /*
+ * Standards compliance hooks here.
+ */
+ if (strcmp(httpd->protocol, "HTTP/1.1") == 0
+ && ((httpd->flags & HTTPD_FOUNDHOST) == 0))
+ return (ISC_R_RANGE);
+
+ EXIT("request");
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+isc_httpd_accept(isc_task_t *task, isc_event_t *ev)
+{
+ isc_result_t result;
+ isc_httpdmgr_t *httpdmgr = ev->ev_arg;
+ isc_httpd_t *httpd;
+ isc_region_t r;
+ isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev;
+ isc_sockaddr_t peeraddr;
+
+ ENTER("accept");
+
+ LOCK(&httpdmgr->lock);
+ if (MSHUTTINGDOWN(httpdmgr)) {
+ NOTICE("accept shutting down, goto out");
+ goto out;
+ }
+
+ if (nev->result == ISC_R_CANCELED) {
+ NOTICE("accept canceled, goto out");
+ goto out;
+ }
+
+ if (nev->result != ISC_R_SUCCESS) {
+ /* XXXMLG log failure */
+ NOTICE("accept returned failure, goto requeue");
+ goto requeue;
+ }
+
+ (void)isc_socket_getpeername(nev->newsocket, &peeraddr);
+ if (httpdmgr->client_ok != NULL &&
+ !(httpdmgr->client_ok)(&peeraddr, httpdmgr->cb_arg)) {
+ isc_socket_detach(&nev->newsocket);
+ goto requeue;
+ }
+
+ httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t));
+ if (httpd == NULL) {
+ /* XXXMLG log failure */
+ NOTICE("accept failed to allocate memory, goto requeue");
+ isc_socket_detach(&nev->newsocket);
+ goto requeue;
+ }
+
+ httpd->mgr = httpdmgr;
+ ISC_LINK_INIT(httpd, link);
+ ISC_LIST_APPEND(httpdmgr->running, httpd, link);
+ ISC_HTTPD_SETRECV(httpd);
+ httpd->sock = nev->newsocket;
+ isc_socket_setname(httpd->sock, "httpd", NULL);
+ httpd->flags = 0;
+
+ /*
+ * Initialize the buffer for our headers.
+ */
+ httpd->headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW);
+ if (httpd->headerdata == NULL) {
+ isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t));
+ isc_socket_detach(&nev->newsocket);
+ goto requeue;
+ }
+ httpd->headerlen = HTTP_SENDGROW;
+ isc_buffer_init(&httpd->headerbuffer, httpd->headerdata,
+ httpd->headerlen);
+
+ ISC_LIST_INIT(httpd->bufflist);
+
+ isc_buffer_initnull(&httpd->bodybuffer);
+ reset_client(httpd);
+
+ r.base = (unsigned char *)httpd->recvbuf;
+ r.length = HTTP_RECVLEN - 1;
+ result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone,
+ httpd);
+ NOTICE("accept queued recv on socket");
+
+ requeue:
+ result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept,
+ httpdmgr);
+ if (result != ISC_R_SUCCESS) {
+ /* XXXMLG what to do? Log failure... */
+ NOTICE("accept could not reaccept due to failure");
+ }
+
+ out:
+ UNLOCK(&httpdmgr->lock);
+
+ httpdmgr_destroy(httpdmgr);
+
+ isc_event_free(&ev);
+
+ EXIT("accept");
+}
+
+static isc_result_t
+render_404(const char *url, const char *querystring,
+ void *arg,
+ unsigned int *retcode, const char **retmsg,
+ const char **mimetype, isc_buffer_t *b,
+ isc_httpdfree_t **freecb, void **freecb_args)
+{
+ static char msg[] = "No such URL.";
+
+ UNUSED(url);
+ UNUSED(querystring);
+ UNUSED(arg);
+
+ *retcode = 404;
+ *retmsg = "No such URL";
+ *mimetype = "text/plain";
+ isc_buffer_reinit(b, msg, strlen(msg));
+ isc_buffer_add(b, strlen(msg));
+ *freecb = NULL;
+ *freecb_args = NULL;
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev)
+{
+ isc_region_t r;
+ isc_result_t result;
+ isc_httpd_t *httpd = ev->ev_arg;
+ isc_socketevent_t *sev = (isc_socketevent_t *)ev;
+ isc_httpdurl_t *url;
+ isc_time_t now;
+ char datebuf[32]; /* Only need 30, but safety first */
+
+ ENTER("recv");
+
+ INSIST(ISC_HTTPD_ISRECV(httpd));
+
+ if (sev->result != ISC_R_SUCCESS) {
+ NOTICE("recv destroying client");
+ destroy_client(&httpd);
+ goto out;
+ }
+
+ result = process_request(httpd, sev->n);
+ if (result == ISC_R_NOTFOUND) {
+ if (httpd->recvlen >= HTTP_RECVLEN - 1) {
+ destroy_client(&httpd);
+ goto out;
+ }
+ r.base = (unsigned char *)httpd->recvbuf + httpd->recvlen;
+ r.length = HTTP_RECVLEN - httpd->recvlen - 1;
+ result = isc_socket_recv(httpd->sock, &r, 1, task,
+ isc_httpd_recvdone, httpd);
+ goto out;
+ } else if (result != ISC_R_SUCCESS) {
+ destroy_client(&httpd);
+ goto out;
+ }
+
+ ISC_HTTPD_SETSEND(httpd);
+
+ /*
+ * XXXMLG Call function here. Provide an add-header function
+ * which will append the common headers to a response we generate.
+ */
+ isc_buffer_initnull(&httpd->bodybuffer);
+ isc_time_now(&now);
+ isc_time_formathttptimestamp(&now, datebuf, sizeof(datebuf));
+ url = ISC_LIST_HEAD(httpd->mgr->urls);
+ while (url != NULL) {
+ if (strcmp(httpd->url, url->url) == 0)
+ break;
+ url = ISC_LIST_NEXT(url, link);
+ }
+ if (url == NULL)
+ result = httpd->mgr->render_404(httpd->url, httpd->querystring,
+ NULL,
+ &httpd->retcode,
+ &httpd->retmsg,
+ &httpd->mimetype,
+ &httpd->bodybuffer,
+ &httpd->freecb,
+ &httpd->freecb_arg);
+ else
+ result = url->action(httpd->url, httpd->querystring,
+ url->action_arg,
+ &httpd->retcode, &httpd->retmsg,
+ &httpd->mimetype, &httpd->bodybuffer,
+ &httpd->freecb, &httpd->freecb_arg);
+ if (result != ISC_R_SUCCESS) {
+ destroy_client(&httpd);
+ goto out;
+ }
+
+ isc_httpd_response(httpd);
+ isc_httpd_addheader(httpd, "Content-Type", httpd->mimetype);
+ isc_httpd_addheader(httpd, "Date", datebuf);
+ isc_httpd_addheader(httpd, "Expires", datebuf);
+ isc_httpd_addheader(httpd, "Last-Modified", datebuf);
+ isc_httpd_addheader(httpd, "Pragma: no-cache", NULL);
+ isc_httpd_addheader(httpd, "Cache-Control: no-cache", NULL);
+ isc_httpd_addheader(httpd, "Server: libisc", NULL);
+ isc_httpd_addheaderuint(httpd, "Content-Length",
+ isc_buffer_usedlength(&httpd->bodybuffer));
+ isc_httpd_endheaders(httpd); /* done */
+
+ ISC_LIST_APPEND(httpd->bufflist, &httpd->headerbuffer, link);
+ /*
+ * Link the data buffer into our send queue, should we have any data
+ * rendered into it. If no data is present, we won't do anything
+ * with the buffer.
+ */
+ if (isc_buffer_length(&httpd->bodybuffer) > 0)
+ ISC_LIST_APPEND(httpd->bufflist, &httpd->bodybuffer, link);
+
+ result = isc_socket_sendv(httpd->sock, &httpd->bufflist, task,
+ isc_httpd_senddone, httpd);
+
+ out:
+ isc_event_free(&ev);
+ EXIT("recv");
+}
+
+void
+isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdmgrp)
+{
+ isc_httpdmgr_t *httpdmgr;
+ isc_httpd_t *httpd;
+ httpdmgr = *httpdmgrp;
+ *httpdmgrp = NULL;
+
+ ENTER("isc_httpdmgr_shutdown");
+
+ LOCK(&httpdmgr->lock);
+
+ MSETSHUTTINGDOWN(httpdmgr);
+
+ isc_socket_cancel(httpdmgr->sock, httpdmgr->task, ISC_SOCKCANCEL_ALL);
+
+ httpd = ISC_LIST_HEAD(httpdmgr->running);
+ while (httpd != NULL) {
+ isc_socket_cancel(httpd->sock, httpdmgr->task,
+ ISC_SOCKCANCEL_ALL);
+ httpd = ISC_LIST_NEXT(httpd, link);
+ }
+
+ UNLOCK(&httpdmgr->lock);
+
+ EXIT("isc_httpdmgr_shutdown");
+}
+
+static isc_result_t
+grow_headerspace(isc_httpd_t *httpd)
+{
+ char *newspace;
+ unsigned int newlen;
+ isc_region_t r;
+
+ newlen = httpd->headerlen + HTTP_SENDGROW;
+ if (newlen > HTTP_SEND_MAXLEN)
+ return (ISC_R_NOSPACE);
+
+ newspace = isc_mem_get(httpd->mgr->mctx, newlen);
+ if (newspace == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_buffer_region(&httpd->headerbuffer, &r);
+ isc_buffer_reinit(&httpd->headerbuffer, newspace, newlen);
+
+ isc_mem_put(httpd->mgr->mctx, r.base, r.length);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_httpd_response(isc_httpd_t *httpd)
+{
+ isc_result_t result;
+ unsigned int needlen;
+
+ needlen = strlen(httpd->protocol) + 1; /* protocol + space */
+ needlen += 3 + 1; /* room for response code, always 3 bytes */
+ needlen += strlen(httpd->retmsg) + 2; /* return msg + CRLF */
+
+ if (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
+ result = grow_headerspace(httpd);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ sprintf(isc_buffer_used(&httpd->headerbuffer), "%s %03d %s\r\n",
+ httpd->protocol, httpd->retcode, httpd->retmsg);
+ isc_buffer_add(&httpd->headerbuffer, needlen);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_httpd_addheader(isc_httpd_t *httpd, const char *name,
+ const char *val)
+{
+ isc_result_t result;
+ unsigned int needlen;
+
+ needlen = strlen(name); /* name itself */
+ if (val != NULL)
+ needlen += 2 + strlen(val); /* :<space> and val */
+ needlen += 2; /* CRLF */
+
+ if (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
+ result = grow_headerspace(httpd);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ if (val != NULL)
+ sprintf(isc_buffer_used(&httpd->headerbuffer),
+ "%s: %s\r\n", name, val);
+ else
+ sprintf(isc_buffer_used(&httpd->headerbuffer),
+ "%s\r\n", name);
+
+ isc_buffer_add(&httpd->headerbuffer, needlen);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_httpd_endheaders(isc_httpd_t *httpd)
+{
+ isc_result_t result;
+
+ if (isc_buffer_availablelength(&httpd->headerbuffer) < 2) {
+ result = grow_headerspace(httpd);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ sprintf(isc_buffer_used(&httpd->headerbuffer), "\r\n");
+ isc_buffer_add(&httpd->headerbuffer, 2);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val) {
+ isc_result_t result;
+ unsigned int needlen;
+ char buf[sizeof "18446744073709551616"];
+
+ sprintf(buf, "%d", val);
+
+ needlen = strlen(name); /* name itself */
+ needlen += 2 + strlen(buf); /* :<space> and val */
+ needlen += 2; /* CRLF */
+
+ if (isc_buffer_availablelength(&httpd->headerbuffer) < needlen) {
+ result = grow_headerspace(httpd);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ sprintf(isc_buffer_used(&httpd->headerbuffer),
+ "%s: %s\r\n", name, buf);
+
+ isc_buffer_add(&httpd->headerbuffer, needlen);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+isc_httpd_senddone(isc_task_t *task, isc_event_t *ev)
+{
+ isc_httpd_t *httpd = ev->ev_arg;
+ isc_region_t r;
+ isc_result_t result;
+ isc_socketevent_t *sev = (isc_socketevent_t *)ev;
+
+ ENTER("senddone");
+ INSIST(ISC_HTTPD_ISSEND(httpd));
+
+ /*
+ * First, unlink our header buffer from the socket's bufflist. This
+ * is sort of an evil hack, since we know our buffer will be there,
+ * and we know it's address, so we can just remove it directly.
+ */
+ NOTICE("senddone unlinked header");
+ ISC_LIST_UNLINK(sev->bufferlist, &httpd->headerbuffer, link);
+
+ /*
+ * We will always want to clean up our receive buffer, even if we
+ * got an error on send or we are shutting down.
+ *
+ * We will pass in the buffer only if there is data in it. If
+ * there is no data, we will pass in a NULL.
+ */
+ if (httpd->freecb != NULL) {
+ isc_buffer_t *b = NULL;
+ if (isc_buffer_length(&httpd->bodybuffer) > 0)
+ b = &httpd->bodybuffer;
+ httpd->freecb(b, httpd->freecb_arg);
+ NOTICE("senddone free callback performed");
+ }
+ if (ISC_LINK_LINKED(&httpd->bodybuffer, link)) {
+ ISC_LIST_UNLINK(sev->bufferlist, &httpd->bodybuffer, link);
+ NOTICE("senddone body buffer unlinked");
+ }
+
+ if (sev->result != ISC_R_SUCCESS) {
+ destroy_client(&httpd);
+ goto out;
+ }
+
+ if ((httpd->flags & HTTPD_CLOSE) != 0) {
+ destroy_client(&httpd);
+ goto out;
+ }
+
+ ISC_HTTPD_SETRECV(httpd);
+
+ NOTICE("senddone restarting recv on socket");
+
+ reset_client(httpd);
+
+ r.base = (unsigned char *)httpd->recvbuf;
+ r.length = HTTP_RECVLEN - 1;
+ result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone,
+ httpd);
+
+out:
+ isc_event_free(&ev);
+ EXIT("senddone");
+}
+
+static void
+reset_client(isc_httpd_t *httpd)
+{
+ /*
+ * Catch errors here. We MUST be in RECV mode, and we MUST NOT have
+ * any outstanding buffers. If we have buffers, we have a leak.
+ */
+ INSIST(ISC_HTTPD_ISRECV(httpd));
+ INSIST(!ISC_LINK_LINKED(&httpd->headerbuffer, link));
+ INSIST(!ISC_LINK_LINKED(&httpd->bodybuffer, link));
+
+ httpd->recvbuf[0] = 0;
+ httpd->recvlen = 0;
+ httpd->method = ISC_HTTPD_METHODUNKNOWN;
+ httpd->url = NULL;
+ httpd->querystring = NULL;
+ httpd->protocol = NULL;
+ httpd->flags = 0;
+
+ isc_buffer_clear(&httpd->headerbuffer);
+ isc_buffer_invalidate(&httpd->bodybuffer);
+}
+
+isc_result_t
+isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
+ isc_httpdaction_t *func, void *arg)
+{
+ isc_httpdurl_t *item;
+
+ if (url == NULL) {
+ httpdmgr->render_404 = func;
+ return (ISC_R_SUCCESS);
+ }
+
+ item = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpdurl_t));
+ if (item == NULL)
+ return (ISC_R_NOMEMORY);
+
+ item->url = isc_mem_strdup(httpdmgr->mctx, url);
+ if (item->url == NULL) {
+ isc_mem_put(httpdmgr->mctx, item, sizeof(isc_httpdurl_t));
+ return (ISC_R_NOMEMORY);
+ }
+
+ item->action = func;
+ item->action_arg = arg;
+ ISC_LINK_INIT(item, link);
+ ISC_LIST_APPEND(httpdmgr->urls, item, link);
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/ia64/Makefile.in b/lib/isc/ia64/Makefile.in
new file mode 100644
index 0000000..324db07
--- /dev/null
+++ b/lib/isc/ia64/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = include
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/ia64/include/Makefile.in b/lib/isc/ia64/include/Makefile.in
new file mode 100644
index 0000000..f1d8bdd
--- /dev/null
+++ b/lib/isc/ia64/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/ia64/include/isc/Makefile.in b/lib/isc/ia64/include/isc/Makefile.in
new file mode 100644
index 0000000..5f116ca
--- /dev/null
+++ b/lib/isc/ia64/include/isc/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = atomic.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/ia64/include/isc/atomic.h b/lib/isc/ia64/include/isc/atomic.h
new file mode 100644
index 0000000..bfd32f4
--- /dev/null
+++ b/lib/isc/ia64/include/isc/atomic.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2006, 2007 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: atomic.h,v 1.4 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_USEGCCASM
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ *
+ * Open issue: can 'fetchadd' make the code faster for some particular values
+ * (e.g., 1 and -1)?
+ */
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+ isc_int32_t prev, swapped;
+
+ for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) {
+ swapped = prev + val;
+ __asm__ volatile(
+ "mov ar.ccv=%2;"
+ "cmpxchg4.acq %0=%4,%3,ar.ccv"
+ : "=r" (swapped), "=m" (*p)
+ : "r" (prev), "r" (swapped), "m" (*p)
+ : "memory");
+ if (swapped == prev)
+ break;
+ }
+
+ return (prev);
+}
+
+/*
+ * This routine atomically stores the value 'val' in 'p'.
+ */
+static inline void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+ __asm__ volatile(
+ "st4.rel %0=%1"
+ : "=m" (*p)
+ : "r" (val)
+ : "memory"
+ );
+}
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'. The original value is returned in any
+ * case.
+ */
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+ isc_int32_t ret;
+
+ __asm__ volatile(
+ "mov ar.ccv=%2;"
+ "cmpxchg4.acq %0=%4,%3,ar.ccv"
+ : "=r" (ret), "=m" (*p)
+ : "r" (cmpval), "r" (val), "m" (*p)
+ : "memory");
+
+ return (ret);
+}
+#else /* !ISC_PLATFORM_USEGCCASM */
+
+#error "unsupported compiler. disable atomic ops by --disable-atomic"
+
+#endif
+#endif /* ISC_ATOMIC_H */
diff --git a/lib/isc/include/Makefile.in b/lib/isc/include/Makefile.in
new file mode 100644
index 0000000..04778d7
--- /dev/null
+++ b/lib/isc/include/Makefile.in
@@ -0,0 +1,25 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.13 2007/06/19 23:47:18 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/include/isc/Makefile.in b/lib/isc/include/isc/Makefile.in
new file mode 100644
index 0000000..236865d
--- /dev/null
+++ b/lib/isc/include/isc/Makefile.in
@@ -0,0 +1,61 @@
+# Copyright (C) 2004-2008 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
+# 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.64 2008/11/14 23:47:33 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @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 = 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@ 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 \
+ 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}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/isc ; \
+ done
+ ${INSTALL_DATA} platform.h ${DESTDIR}${includedir}/isc
+
+distclean::
+ rm -f platform.h
diff --git a/lib/isc/include/isc/app.h b/lib/isc/include/isc/app.h
new file mode 100644
index 0000000..c4d54cb
--- /dev/null
+++ b/lib/isc/include/isc/app.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: app.h,v 1.8 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_APP_H
+#define ISC_APP_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/app.h
+ * \brief ISC Application Support
+ *
+ * Dealing with program termination can be difficult, especially in a
+ * multithreaded program. The routines in this module help coordinate
+ * the shutdown process. They are used as follows by the initial (main)
+ * thread of the application:
+ *
+ *\li isc_app_start(); Call very early in main(), before
+ * any other threads have been created.
+ *
+ *\li isc_app_run(); This will post any on-run events,
+ * and then block until application
+ * shutdown is requested. A shutdown
+ * request is made by calling
+ * isc_app_shutdown(), or by sending
+ * SIGINT or SIGTERM to the process.
+ * After isc_app_run() returns, the
+ * application should shutdown itself.
+ *
+ *\li isc_app_finish(); Call very late in main().
+ *
+ * Applications that want to use SIGHUP/isc_app_reload() to trigger reloading
+ * should check the result of isc_app_run() and call the reload routine if
+ * the result is ISC_R_RELOAD. They should then call isc_app_run() again
+ * to resume waiting for reload or termination.
+ *
+ * Use of this module is not required. In particular, isc_app_start() is
+ * NOT an ISC library initialization routine.
+ *
+ * \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).
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * None.
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+#include <isc/eventclass.h>
+#include <isc/lang.h>
+#include <isc/result.h>
+
+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)
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_app_start(void);
+/*!<
+ * \brief Start an ISC library application.
+ *
+ * Notes:
+ * This call should be made before any other ISC library call, and as
+ * close to the beginning of the application as possible.
+ */
+
+isc_result_t
+isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
+ void *arg);
+/*!<
+ * \brief Request delivery of an event when the application is run.
+ *
+ * Requires:
+ * isc_app_start() has been called.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOMEMORY
+ */
+
+isc_result_t
+isc_app_run(void);
+/*!<
+ * \brief Run an ISC library application.
+ *
+ * Notes:
+ *\li The caller (typically the initial thread of an application) will
+ * block until shutdown is requested. When the call returns, the
+ * caller should start shutting down the application.
+ *
+ * Requires:
+ *\li isc_app_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.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS Shutdown has been requested.
+ *\li ISC_R_RELOAD Reload has been requested.
+ */
+
+isc_result_t
+isc_app_shutdown(void);
+/*!<
+ * \brief Request application shutdown.
+ *
+ * Notes:
+ *\li It is safe to call isc_app_shutdown() multiple times. Shutdown will
+ * only be triggered once.
+ *
+ * Requires:
+ *\li isc_app_run() has been called.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_app_reload(void);
+/*!<
+ * \brief Request application reload.
+ *
+ * Requires:
+ *\li isc_app_run() has been called.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_UNEXPECTED
+ */
+
+void
+isc_app_finish(void);
+/*!<
+ * \brief Finish an ISC library application.
+ *
+ * Notes:
+ *\li This call should be made at or near the end of main().
+ *
+ * Requires:
+ *\li isc_app_start() has been called.
+ *
+ * Ensures:
+ *\li Any resources allocated by isc_app_start() have been released.
+ */
+
+void
+isc_app_block(void);
+/*!<
+ * \brief Indicate that a blocking operation will be performed.
+ *
+ * Notes:
+ *\li If a blocking operation is in process, a call to isc_app_shutdown()
+ * or an external signal will abort the program, rather than allowing
+ * clean shutdown. This is primarily useful for reading user input.
+ *
+ * Requires:
+ * \li isc_app_start() has been called.
+ * \li No other blocking operations are in progress.
+ */
+
+void
+isc_app_unblock(void);
+/*!<
+ * \brief Indicate that a blocking operation is complete.
+ *
+ * Notes:
+ * \li When a blocking operation has completed, return the program to a
+ * state where a call to isc_app_shutdown() or an external signal will
+ * shutdown normally.
+ *
+ * Requires:
+ * \li isc_app_start() has been called.
+ * \li isc_app_block() has been called by the same thread.
+ */
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_APP_H */
diff --git a/lib/isc/include/isc/assertions.h b/lib/isc/include/isc/assertions.h
new file mode 100644
index 0000000..b031152
--- /dev/null
+++ b/lib/isc/include/isc/assertions.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-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: assertions.h,v 1.26 2008/10/15 23:47:31 tbox Exp $
+ */
+/*! \file isc/assertions.h
+ */
+
+#ifndef ISC_ASSERTIONS_H
+#define ISC_ASSERTIONS_H 1
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+ISC_LANG_BEGINDECLS
+
+/*% isc assertion type */
+typedef enum {
+ isc_assertiontype_require,
+ isc_assertiontype_ensure,
+ isc_assertiontype_insist,
+ isc_assertiontype_invariant
+} isc_assertiontype_t;
+
+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;
+
+void
+isc_assertion_setcallback(isc_assertioncallback_t);
+
+const char *
+isc_assertion_typetotext(isc_assertiontype_t type);
+
+#if defined(ISC_CHECK_ALL) || defined(__COVERITY__)
+#define ISC_CHECK_REQUIRE 1
+#define ISC_CHECK_ENSURE 1
+#define ISC_CHECK_INSIST 1
+#define ISC_CHECK_INVARIANT 1
+#endif
+
+#if defined(ISC_CHECK_NONE) && !defined(__COVERITY__)
+#define ISC_CHECK_REQUIRE 0
+#define ISC_CHECK_ENSURE 0
+#define ISC_CHECK_INSIST 0
+#define ISC_CHECK_INVARIANT 0
+#endif
+
+#ifndef ISC_CHECK_REQUIRE
+#define ISC_CHECK_REQUIRE 1
+#endif
+
+#ifndef ISC_CHECK_ENSURE
+#define ISC_CHECK_ENSURE 1
+#endif
+
+#ifndef ISC_CHECK_INSIST
+#define ISC_CHECK_INSIST 1
+#endif
+
+#ifndef ISC_CHECK_INVARIANT
+#define ISC_CHECK_INVARIANT 1
+#endif
+
+#if ISC_CHECK_REQUIRE != 0
+#define ISC_REQUIRE(cond) \
+ ((void) ((cond) || \
+ ((isc_assertion_failed)(__FILE__, __LINE__, \
+ isc_assertiontype_require, \
+ #cond), 0)))
+#else
+#define ISC_REQUIRE(cond) ((void) 0)
+#endif /* ISC_CHECK_REQUIRE */
+
+#if ISC_CHECK_ENSURE != 0
+#define ISC_ENSURE(cond) \
+ ((void) ((cond) || \
+ ((isc_assertion_failed)(__FILE__, __LINE__, \
+ isc_assertiontype_ensure, \
+ #cond), 0)))
+#else
+#define ISC_ENSURE(cond) ((void) 0)
+#endif /* ISC_CHECK_ENSURE */
+
+#if ISC_CHECK_INSIST != 0
+#define ISC_INSIST(cond) \
+ ((void) ((cond) || \
+ ((isc_assertion_failed)(__FILE__, __LINE__, \
+ isc_assertiontype_insist, \
+ #cond), 0)))
+#else
+#define ISC_INSIST(cond) ((void) 0)
+#endif /* ISC_CHECK_INSIST */
+
+#if ISC_CHECK_INVARIANT != 0
+#define ISC_INVARIANT(cond) \
+ ((void) ((cond) || \
+ ((isc_assertion_failed)(__FILE__, __LINE__, \
+ isc_assertiontype_invariant, \
+ #cond), 0)))
+#else
+#define ISC_INVARIANT(cond) ((void) 0)
+#endif /* ISC_CHECK_INVARIANT */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ASSERTIONS_H */
diff --git a/lib/isc/include/isc/base32.h b/lib/isc/include/isc/base32.h
new file mode 100644
index 0000000..978a8db
--- /dev/null
+++ b/lib/isc/include/isc/base32.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2008 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: base32.h,v 1.3 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef ISC_BASE32_H
+#define ISC_BASE32_H 1
+
+/*! \file */
+
+/*
+ * Routines for manipulating base 32 and base 32 hex encoded data.
+ * Based on RFC 4648.
+ *
+ * Base 32 hex preserves the sort order of data when it is encoded /
+ * decoded.
+ */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_base32_totext(isc_region_t *source, int wordlength,
+ const char *wordbreak, isc_buffer_t *target);
+isc_result_t
+isc_base32hex_totext(isc_region_t *source, int wordlength,
+ const char *wordbreak, isc_buffer_t *target);
+/*!<
+ * \brief Convert data into base32 encoded text.
+ *
+ * Notes:
+ *\li The base32 encoded text in 'target' will be divided into
+ * words of at most 'wordlength' characters, separated by
+ * the 'wordbreak' string. No parentheses will surround
+ * the text.
+ *
+ * Requires:
+ *\li 'source' is a region containing binary data
+ *\li 'target' is a text buffer containing available space
+ *\li 'wordbreak' points to a null-terminated string of
+ * zero or more whitespace characters
+ *
+ * Ensures:
+ *\li target will contain the base32 encoded version of the data
+ * in source. The 'used' pointer in target will be advanced as
+ * necessary.
+ */
+
+isc_result_t
+isc_base32_decodestring(const char *cstr, isc_buffer_t *target);
+isc_result_t
+isc_base32hex_decodestring(const char *cstr, isc_buffer_t *target);
+/*!<
+ * \brief Decode a null-terminated base32 string.
+ *
+ * Requires:
+ *\li 'cstr' is non-null.
+ *\li 'target' is a valid buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- the entire decoded representation of 'cstring'
+ * fit in 'target'.
+ *\li #ISC_R_BADBASE32 -- 'cstr' is not a valid base32 encoding.
+ *
+ * Other error returns are any possible error code from:
+ *\li isc_lex_create(),
+ *\li isc_lex_openbuffer(),
+ *\li isc_base32_tobuffer().
+ */
+
+isc_result_t
+isc_base32_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+isc_result_t
+isc_base32hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+/*!<
+ * \brief Convert base32 encoded text from a lexer context into data.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer context
+ *\li 'target' is a buffer containing binary data
+ *\li 'length' is an integer
+ *
+ * Ensures:
+ *\li target will contain the data represented by the base32 encoded
+ * string parsed by the lexer. No more than length bytes will be read,
+ * if length is positive. The 'used' pointer in target will be
+ * advanced as necessary.
+ */
+
+isc_result_t
+isc_base32_decoderegion(isc_region_t *source, isc_buffer_t *target);
+isc_result_t
+isc_base32hex_decoderegion(isc_region_t *source, isc_buffer_t *target);
+/*!<
+ * \brief Decode a packed (no white space permitted) base32 region.
+ *
+ * Requires:
+ *\li 'source' is a valid region.
+ *\li 'target' is a valid buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- the entire decoded representation of 'cstring'
+ * fit in 'target'.
+ *\li #ISC_R_BADBASE32 -- 'source' is not a valid base32 encoding.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BASE32_H */
diff --git a/lib/isc/include/isc/base64.h b/lib/isc/include/isc/base64.h
new file mode 100644
index 0000000..e48ef2a
--- /dev/null
+++ b/lib/isc/include/isc/base64.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: base64.h,v 1.22 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_BASE64_H
+#define ISC_BASE64_H 1
+
+/*! \file isc/base64.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_base64_totext(isc_region_t *source, int wordlength,
+ const char *wordbreak, isc_buffer_t *target);
+/*!<
+ * \brief Convert data into base64 encoded text.
+ *
+ * Notes:
+ *\li The base64 encoded text in 'target' will be divided into
+ * words of at most 'wordlength' characters, separated by
+ * the 'wordbreak' string. No parentheses will surround
+ * the text.
+ *
+ * Requires:
+ *\li 'source' is a region containing binary data
+ *\li 'target' is a text buffer containing available space
+ *\li 'wordbreak' points to a null-terminated string of
+ * zero or more whitespace characters
+ *
+ * Ensures:
+ *\li target will contain the base64 encoded version of the data
+ * in source. The 'used' pointer in target will be advanced as
+ * necessary.
+ */
+
+isc_result_t
+isc_base64_decodestring(const char *cstr, isc_buffer_t *target);
+/*!<
+ * \brief Decode a null-terminated base64 string.
+ *
+ * Requires:
+ *\li 'cstr' is non-null.
+ *\li 'target' is a valid buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- the entire decoded representation of 'cstring'
+ * fit in 'target'.
+ *\li #ISC_R_BADBASE64 -- 'cstr' is not a valid base64 encoding.
+ *
+ * Other error returns are any possible error code from:
+ *\li isc_lex_create(),
+ *\li isc_lex_openbuffer(),
+ *\li isc_base64_tobuffer().
+ */
+
+isc_result_t
+isc_base64_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+/*!<
+ * \brief Convert base64 encoded text from a lexer context into data.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer context
+ *\li 'target' is a buffer containing binary data
+ *\li 'length' is an integer
+ *
+ * Ensures:
+ *\li target will contain the data represented by the base64 encoded
+ * string parsed by the lexer. No more than length bytes will be read,
+ * if length is positive. The 'used' pointer in target will be
+ * advanced as necessary.
+ */
+
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BASE64_H */
diff --git a/lib/isc/include/isc/bitstring.h b/lib/isc/include/isc/bitstring.h
new file mode 100644
index 0000000..252d111
--- /dev/null
+++ b/lib/isc/include/isc/bitstring.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: bitstring.h,v 1.14 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_BITSTRING_H
+#define ISC_BITSTRING_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/bitstring.h
+ *
+ * \brief Bitstring manipulation functions.
+ *
+ * A bitstring is a packed array of bits, stored in a contiguous
+ * sequence of octets. The "most significant bit" (msb) of a bitstring
+ * is the high bit of the first octet. The "least significant bit" of a
+ * bitstring is the low bit of the last octet.
+ *
+ * Two bit numbering schemes are supported, "msb0" and "lsb0".
+ *
+ * In the "msb0" scheme, bit number 0 designates the most significant bit,
+ * and any padding bits required to make the bitstring a multiple of 8 bits
+ * long are added to the least significant end of the last octet.
+ *
+ * In the "lsb0" scheme, bit number 0 designates the least significant bit,
+ * and any padding bits required to make the bitstring a multiple of 8 bits
+ * long are added to the most significant end of the first octet.
+ *
+ * E.g., consider the bitstring "11010001111". This bitstring is 11 bits
+ * long and will take two octets. Let "p" denote a pad bit. In the msb0
+ * encoding, it would be
+ *
+ * \verbatim
+ * Octet 0 Octet 1
+ * |
+ * 1 1 0 1 0 0 0 1 | 1 1 1 p p p p p
+ * ^ | ^
+ * | |
+ * bit 0 bit 15
+ * \endverbatim
+ *
+ * In the lsb0 encoding, it would be
+ *
+ * \verbatim
+ * Octet 0 Octet 1
+ * |
+ * p p p p p 1 1 0 | 1 0 0 0 1 1 1 1
+ * ^ | ^
+ * | |
+ * bit 15 bit 0
+ * \endverbatim
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+struct isc_bitstring {
+ unsigned int magic;
+ unsigned char * data;
+ unsigned int length;
+ unsigned int size;
+ isc_boolean_t lsb0;
+};
+
+/***
+ *** Functions
+ ***/
+
+void
+isc_bitstring_init(isc_bitstring_t *bitstring, unsigned char *data,
+ unsigned int length, unsigned int size, isc_boolean_t lsb0);
+/*!<
+ * \brief Make 'bitstring' refer to the bitstring of 'size' bits starting
+ * at 'data'. 'length' bits of the bitstring are valid. If 'lsb0'
+ * is set then, bit 0 refers to the least significant bit of the
+ * bitstring. Otherwise bit 0 is the most significant bit.
+ *
+ * Requires:
+ *
+ *\li 'bitstring' points to a isc_bitstring_t.
+ *
+ *\li 'data' points to an array of unsigned char large enough to hold
+ * 'size' bits.
+ *
+ *\li 'length' <= 'size'.
+ *
+ * Ensures:
+ *
+ *\li 'bitstring' is a valid bitstring.
+ */
+
+void
+isc_bitstring_invalidate(isc_bitstring_t *bitstring);
+/*!<
+ * \brief Invalidate 'bitstring'.
+ *
+ * Requires:
+ *
+ *\li 'bitstring' is a valid bitstring.
+ *
+ * Ensures:
+ *
+ *\li 'bitstring' is not a valid bitstring.
+ */
+
+void
+isc_bitstring_copy(isc_bitstring_t *source, unsigned int sbitpos,
+ isc_bitstring_t *target, unsigned int tbitpos,
+ unsigned int n);
+/*!<
+ * \brief Starting at bit 'sbitpos', copy 'n' bits from 'source' to
+ * the 'n' bits of 'target' starting at 'tbitpos'.
+ *
+ * Requires:
+ *
+ *\li 'source' and target are valid bitstrings with the same lsb0 setting.
+ *
+ *\li 'sbitpos' + 'n' is less than or equal to the length of 'source'.
+ *
+ *\li 'tbitpos' + 'n' is less than or equal to the size of 'target'.
+ *
+ * Ensures:
+ *
+ *\li The specified bits have been copied, and the length of 'target'
+ * adjusted (if required).
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BITSTRING_H */
diff --git a/lib/isc/include/isc/boolean.h b/lib/isc/include/isc/boolean.h
new file mode 100644
index 0000000..348b096
--- /dev/null
+++ b/lib/isc/include/isc/boolean.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: boolean.h,v 1.19 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_BOOLEAN_H
+#define ISC_BOOLEAN_H 1
+
+/*! \file isc/boolean.h */
+
+typedef enum { isc_boolean_false = 0, isc_boolean_true = 1 } isc_boolean_t;
+
+#define ISC_FALSE isc_boolean_false
+#define ISC_TRUE isc_boolean_true
+#define ISC_TF(x) ((x) ? ISC_TRUE : ISC_FALSE)
+
+#endif /* ISC_BOOLEAN_H */
diff --git a/lib/isc/include/isc/buffer.h b/lib/isc/include/isc/buffer.h
new file mode 100644
index 0000000..2a02d88
--- /dev/null
+++ b/lib/isc/include/isc/buffer.h
@@ -0,0 +1,904 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: buffer.h,v 1.53 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef ISC_BUFFER_H
+#define ISC_BUFFER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/buffer.h
+ *
+ * \brief A buffer is a region of memory, together with a set of related subregions.
+ * Buffers are used for parsing and I/O operations.
+ *
+ * The 'used region' and the 'available' region are disjoint, and their
+ * union is the buffer's region. The used region extends from the beginning
+ * of the buffer region to the last used byte. The available region
+ * extends from one byte greater than the last used byte to the end of the
+ * buffer's region. The size of the used region can be changed using various
+ * buffer commands. Initially, the used region is empty.
+ *
+ * The used region is further subdivided into two disjoint regions: the
+ * 'consumed region' and the 'remaining region'. The union of these two
+ * regions is the used region. The consumed region extends from the beginning
+ * of the used region to the byte before the 'current' offset (if any). The
+ * 'remaining' region the current pointer to the end of the used
+ * region. The size of the consumed region can be changed using various
+ * buffer commands. Initially, the consumed region is empty.
+ *
+ * The 'active region' is an (optional) subregion of the remaining region.
+ * It extends from the current offset to an offset in the remaining region
+ * that is selected with isc_buffer_setactive(). Initially, the active region
+ * is empty. If the current offset advances beyond the chosen offset, the
+ * active region will also be empty.
+ *
+ * \verbatim
+ * /------------entire length---------------\
+ * /----- used region -----\/-- available --\
+ * +----------------------------------------+
+ * | consumed | remaining | |
+ * +----------------------------------------+
+ * a b c d e
+ *
+ * a == base of buffer.
+ * b == current pointer. Can be anywhere between a and d.
+ * c == active pointer. Meaningful between b and d.
+ * d == used pointer.
+ * e == length of buffer.
+ *
+ * a-e == entire length of buffer.
+ * a-d == used region.
+ * a-b == consumed region.
+ * b-d == remaining region.
+ * b-c == optional active region.
+ *\endverbatim
+ *
+ * The following invariants are maintained by all routines:
+ *
+ *\code
+ * length > 0
+ *
+ * base is a valid pointer to length bytes of memory
+ *
+ * 0 <= used <= length
+ *
+ * 0 <= current <= used
+ *
+ * 0 <= active <= used
+ * (although active < current implies empty active region)
+ *\endcode
+ *
+ * \li MP:
+ * Buffers have no synchronization. Clients must ensure exclusive
+ * access.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * Memory: 1 pointer + 6 unsigned integers per buffer.
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/magic.h>
+#include <isc/types.h>
+
+/*!
+ * To make many functions be inline macros (via \#define) define this.
+ * If it is undefined, a function will be used.
+ */
+/* #define ISC_BUFFER_USEINLINE */
+
+ISC_LANG_BEGINDECLS
+
+/*@{*/
+/*!
+ *** Magic numbers
+ ***/
+#define ISC_BUFFER_MAGIC 0x42756621U /* Buf!. */
+#define ISC_BUFFER_VALID(b) ISC_MAGIC_VALID(b, ISC_BUFFER_MAGIC)
+/*@}*/
+
+/*
+ * The following macros MUST be used only on valid buffers. It is the
+ * caller's responsibility to ensure this by using the ISC_BUFFER_VALID
+ * check above, or by calling another isc_buffer_*() function (rather than
+ * another macro.)
+ */
+
+/*@{*/
+/*!
+ * Fundamental buffer elements. (A through E in the introductory comment.)
+ */
+#define isc_buffer_base(b) ((void *)(b)->base) /*a*/
+#define isc_buffer_current(b) \
+ ((void *)((unsigned char *)(b)->base + (b)->current)) /*b*/
+#define isc_buffer_active(b) \
+ ((void *)((unsigned char *)(b)->base + (b)->active)) /*c*/
+#define isc_buffer_used(b) \
+ ((void *)((unsigned char *)(b)->base + (b)->used)) /*d*/
+#define isc_buffer_length(b) ((b)->length) /*e*/
+/*@}*/
+
+/*@{*/
+/*!
+ * Derived lengths. (Described in the introductory comment.)
+ */
+#define isc_buffer_usedlength(b) ((b)->used) /* d-a */
+#define isc_buffer_consumedlength(b) ((b)->current) /* b-a */
+#define isc_buffer_remaininglength(b) ((b)->used - (b)->current) /* d-b */
+#define isc_buffer_activelength(b) ((b)->active - (b)->current) /* c-b */
+#define isc_buffer_availablelength(b) ((b)->length - (b)->used) /* e-d */
+/*@}*/
+
+/*!
+ * Note that the buffer structure is public. This is principally so buffer
+ * operations can be implemented using macros. Applications are strongly
+ * discouraged from directly manipulating the structure.
+ */
+
+struct isc_buffer {
+ unsigned int magic;
+ void *base;
+ /*@{*/
+ /*! The following integers are byte offsets from 'base'. */
+ unsigned int length;
+ unsigned int used;
+ unsigned int current;
+ unsigned int active;
+ /*@}*/
+ /*! linkable */
+ ISC_LINK(isc_buffer_t) link;
+ /*! private internal elements */
+ isc_mem_t *mctx;
+};
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_buffer_allocate(isc_mem_t *mctx, isc_buffer_t **dynbuffer,
+ unsigned int length);
+/*!<
+ * \brief Allocate a dynamic linkable buffer which has "length" bytes in the
+ * data region.
+ *
+ * Requires:
+ *\li "mctx" is valid.
+ *
+ *\li "dynbuffer" is non-NULL, and "*dynbuffer" is NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS - success
+ *\li ISC_R_NOMEMORY - no memory available
+ *
+ * Note:
+ *\li Changing the buffer's length field is not permitted.
+ */
+
+void
+isc_buffer_free(isc_buffer_t **dynbuffer);
+/*!<
+ * \brief Release resources allocated for a dynamic buffer.
+ *
+ * Requires:
+ *\li "dynbuffer" is not NULL.
+ *
+ *\li "*dynbuffer" is a valid dynamic buffer.
+ *
+ * Ensures:
+ *\li "*dynbuffer" will be NULL on return, and all memory associated with
+ * the dynamic buffer is returned to the memory context used in
+ * isc_buffer_allocate().
+ */
+
+void
+isc__buffer_init(isc_buffer_t *b, const void *base, unsigned int length);
+/*!<
+ * \brief Make 'b' refer to the 'length'-byte region starting at base.
+ *
+ * Requires:
+ *
+ *\li 'length' > 0
+ *
+ *\li 'base' is a pointer to a sequence of 'length' bytes.
+ *
+ */
+
+void
+isc__buffer_initnull(isc_buffer_t *b);
+/*!<
+ *\brief Initialize a buffer 'b' with a null data and zero length/
+ */
+
+void
+isc_buffer_reinit(isc_buffer_t *b, void *base, unsigned int length);
+/*!<
+ * \brief Make 'b' refer to the 'length'-byte region starting at base.
+ * Any existing data will be copied.
+ *
+ * Requires:
+ *
+ *\li 'length' > 0 AND length >= previous length
+ *
+ *\li 'base' is a pointer to a sequence of 'length' bytes.
+ *
+ */
+
+void
+isc__buffer_invalidate(isc_buffer_t *b);
+/*!<
+ * \brief Make 'b' an invalid buffer.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ * Ensures:
+ *\li If assertion checking is enabled, future attempts to use 'b' without
+ * calling isc_buffer_init() on it will cause an assertion failure.
+ */
+
+void
+isc__buffer_region(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_usedregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the used region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_availableregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the available region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_add(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Increase the 'used' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ *\li used + n <= length
+ *
+ */
+
+void
+isc__buffer_subtract(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Decrease the 'used' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ *\li used >= n
+ *
+ */
+
+void
+isc__buffer_clear(isc_buffer_t *b);
+/*!<
+ * \brief Make the used region empty.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ *\li used = 0
+ *
+ */
+
+void
+isc__buffer_consumedregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the consumed region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_remainingregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the remaining region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_activeregion(isc_buffer_t *b, isc_region_t *r);
+/*!<
+ * \brief Make 'r' refer to the active region of 'b'.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' points to a region structure.
+ */
+
+void
+isc__buffer_setactive(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Sets the end of the active region 'n' bytes after current.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li current + n <= used
+ */
+
+void
+isc__buffer_first(isc_buffer_t *b);
+/*!<
+ * \brief Make the consumed region empty.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ *\li current == 0
+ *
+ */
+
+void
+isc__buffer_forward(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Increase the 'consumed' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ *\li current + n <= used
+ *
+ */
+
+void
+isc__buffer_back(isc_buffer_t *b, unsigned int n);
+/*!<
+ * \brief Decrease the 'consumed' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ *\li n <= current
+ *
+ */
+
+void
+isc_buffer_compact(isc_buffer_t *b);
+/*!<
+ * \brief Compact the used region by moving the remaining region so it occurs
+ * at the start of the buffer. The used region is shrunk by the size of
+ * the consumed region, and the consumed region is then made empty.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ *\li current == 0
+ *
+ *\li The size of the used region is now equal to the size of the remaining
+ * region (as it was before the call). The contents of the used region
+ * are those of the remaining region (as it was before the call).
+ */
+
+isc_uint8_t
+isc_buffer_getuint8(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 8-bit integer from 'b' and return it.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least 1.
+ *
+ * Ensures:
+ *
+ *\li The current pointer in 'b' is advanced by 1.
+ *
+ * Returns:
+ *
+ *\li A 8-bit unsigned integer.
+ */
+
+void
+isc__buffer_putuint8(isc_buffer_t *b, isc_uint8_t val);
+/*!<
+ * \brief Store an unsigned 8-bit integer from 'val' into 'b'.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the unused region of 'b' is at least 1.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 1.
+ */
+
+isc_uint16_t
+isc_buffer_getuint16(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 16-bit integer in network byte order from 'b', convert
+ * it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least 2.
+ *
+ * Ensures:
+ *
+ *\li The current pointer in 'b' is advanced by 2.
+ *
+ * Returns:
+ *
+ *\li A 16-bit unsigned integer.
+ */
+
+void
+isc__buffer_putuint16(isc_buffer_t *b, isc_uint16_t val);
+/*!<
+ * \brief Store an unsigned 16-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the unused region of 'b' is at least 2.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 2.
+ */
+
+isc_uint32_t
+isc_buffer_getuint32(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 32-bit integer in network byte order from 'b', convert
+ * it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least 4.
+ *
+ * Ensures:
+ *
+ *\li The current pointer in 'b' is advanced by 4.
+ *
+ * Returns:
+ *
+ *\li A 32-bit unsigned integer.
+ */
+
+void
+isc__buffer_putuint32(isc_buffer_t *b, isc_uint32_t val);
+/*!<
+ * \brief Store an unsigned 32-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the unused region of 'b' is at least 4.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 4.
+ */
+
+isc_uint64_t
+isc_buffer_getuint48(isc_buffer_t *b);
+/*!<
+ * \brief Read an unsigned 48-bit integer in network byte order from 'b',
+ * convert it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the available region of 'b' is at least 6.
+ *
+ * Ensures:
+ *
+ *\li The current pointer in 'b' is advanced by 6.
+ *
+ * Returns:
+ *
+ *\li A 48-bit unsigned integer (stored in a 64-bit integer).
+ */
+
+void
+isc__buffer_putuint48(isc_buffer_t *b, isc_uint64_t val);
+/*!<
+ * \brief Store an unsigned 48-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li The length of the unused region of 'b' is at least 6.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 6.
+ */
+
+void
+isc__buffer_putuint24(isc_buffer_t *b, isc_uint32_t val);
+/*!<
+ * Store an unsigned 24-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ * The length of the unused region of 'b' is at least 3.
+ *
+ * Ensures:
+ *\li The used pointer in 'b' is advanced by 3.
+ */
+
+void
+isc__buffer_putmem(isc_buffer_t *b, const unsigned char *base,
+ unsigned int length);
+/*!<
+ * \brief Copy 'length' bytes of memory at 'base' into 'b'.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'base' points to 'length' bytes of valid memory.
+ *
+ */
+
+void
+isc__buffer_putstr(isc_buffer_t *b, const char *source);
+/*!<
+ * \brief Copy 'source' into 'b', not including terminating NUL.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'source' to be a valid NULL terminated string.
+ *
+ *\li strlen(source) <= isc_buffer_available(b)
+ */
+
+isc_result_t
+isc_buffer_copyregion(isc_buffer_t *b, const isc_region_t *r);
+/*!<
+ * \brief Copy the contents of 'r' into 'b'.
+ *
+ * Requires:
+ *\li 'b' is a valid buffer.
+ *
+ *\li 'r' is a valid region.
+ *
+ * Returns:
+ *
+ *\li ISC_R_SUCCESS
+ *\li ISC_R_NOSPACE The available region of 'b' is not
+ * big enough.
+ */
+
+ISC_LANG_ENDDECLS
+
+/*
+ * Inline macro versions of the functions. These should never be called
+ * directly by an application, but will be used by the functions within
+ * buffer.c. The callers should always use "isc_buffer_*()" names, never
+ * ones beginning with "isc__"
+ */
+
+/*! \note
+ * XXXDCL Something more could be done with initializing buffers that
+ * point to const data. For example, a new function, isc_buffer_initconst,
+ * could be used, and a new boolean flag in the buffer structure could
+ * indicate whether the buffer was initialized with that function.
+ * (isc_bufer_init itself would be reprototyped to *not* have its "base"
+ * parameter be const.) Then if the boolean were true, the isc_buffer_put*
+ * functions could assert a contractual requirement for a non-const buffer.
+ * One drawback is that the isc_buffer_* functions (macros) that return
+ * pointers would still need to return non-const pointers to avoid compiler
+ * warnings, so it would be up to code that uses them to have to deal
+ * with the possibility that the buffer was initialized as const --
+ * a problem that they *already* have to deal with but have absolutely
+ * no ability to. With a new isc_buffer_isconst() function returning
+ * true/false, they could at least assert a contractual requirement for
+ * non-const buffers when needed.
+ */
+#define ISC__BUFFER_INIT(_b, _base, _length) \
+ do { \
+ union { \
+ const void * konst; \
+ void * var; \
+ } _u; \
+ _u.konst = (_base); \
+ (_b)->base = _u.var; \
+ (_b)->length = (_length); \
+ (_b)->used = 0; \
+ (_b)->current = 0; \
+ (_b)->active = 0; \
+ (_b)->mctx = NULL; \
+ ISC_LINK_INIT(_b, link); \
+ (_b)->magic = ISC_BUFFER_MAGIC; \
+ } while (0)
+
+#define ISC__BUFFER_INITNULL(_b) ISC__BUFFER_INIT(_b, NULL, 0)
+
+#define ISC__BUFFER_INVALIDATE(_b) \
+ do { \
+ (_b)->magic = 0; \
+ (_b)->base = NULL; \
+ (_b)->length = 0; \
+ (_b)->used = 0; \
+ (_b)->current = 0; \
+ (_b)->active = 0; \
+ } while (0)
+
+#define ISC__BUFFER_REGION(_b, _r) \
+ do { \
+ (_r)->base = (_b)->base; \
+ (_r)->length = (_b)->length; \
+ } while (0)
+
+#define ISC__BUFFER_USEDREGION(_b, _r) \
+ do { \
+ (_r)->base = (_b)->base; \
+ (_r)->length = (_b)->used; \
+ } while (0)
+
+#define ISC__BUFFER_AVAILABLEREGION(_b, _r) \
+ do { \
+ (_r)->base = isc_buffer_used(_b); \
+ (_r)->length = isc_buffer_availablelength(_b); \
+ } while (0)
+
+#define ISC__BUFFER_ADD(_b, _n) \
+ do { \
+ (_b)->used += (_n); \
+ } while (0)
+
+#define ISC__BUFFER_SUBTRACT(_b, _n) \
+ do { \
+ (_b)->used -= (_n); \
+ if ((_b)->current > (_b)->used) \
+ (_b)->current = (_b)->used; \
+ if ((_b)->active > (_b)->used) \
+ (_b)->active = (_b)->used; \
+ } while (0)
+
+#define ISC__BUFFER_CLEAR(_b) \
+ do { \
+ (_b)->used = 0; \
+ (_b)->current = 0; \
+ (_b)->active = 0; \
+ } while (0)
+
+#define ISC__BUFFER_CONSUMEDREGION(_b, _r) \
+ do { \
+ (_r)->base = (_b)->base; \
+ (_r)->length = (_b)->current; \
+ } while (0)
+
+#define ISC__BUFFER_REMAININGREGION(_b, _r) \
+ do { \
+ (_r)->base = isc_buffer_current(_b); \
+ (_r)->length = isc_buffer_remaininglength(_b); \
+ } while (0)
+
+#define ISC__BUFFER_ACTIVEREGION(_b, _r) \
+ do { \
+ if ((_b)->current < (_b)->active) { \
+ (_r)->base = isc_buffer_current(_b); \
+ (_r)->length = isc_buffer_activelength(_b); \
+ } else { \
+ (_r)->base = NULL; \
+ (_r)->length = 0; \
+ } \
+ } while (0)
+
+#define ISC__BUFFER_SETACTIVE(_b, _n) \
+ do { \
+ (_b)->active = (_b)->current + (_n); \
+ } while (0)
+
+#define ISC__BUFFER_FIRST(_b) \
+ do { \
+ (_b)->current = 0; \
+ } while (0)
+
+#define ISC__BUFFER_FORWARD(_b, _n) \
+ do { \
+ (_b)->current += (_n); \
+ } while (0)
+
+#define ISC__BUFFER_BACK(_b, _n) \
+ do { \
+ (_b)->current -= (_n); \
+ } while (0)
+
+#define ISC__BUFFER_PUTMEM(_b, _base, _length) \
+ do { \
+ memcpy(isc_buffer_used(_b), (_base), (_length)); \
+ (_b)->used += (_length); \
+ } while (0)
+
+#define ISC__BUFFER_PUTSTR(_b, _source) \
+ do { \
+ unsigned int _length; \
+ unsigned char *_cp; \
+ _length = strlen(_source); \
+ _cp = isc_buffer_used(_b); \
+ memcpy(_cp, (_source), _length); \
+ (_b)->used += (_length); \
+ } while (0)
+
+#define ISC__BUFFER_PUTUINT8(_b, _val) \
+ do { \
+ unsigned char *_cp; \
+ isc_uint8_t _val2 = (_val); \
+ _cp = isc_buffer_used(_b); \
+ (_b)->used++; \
+ _cp[0] = _val2 & 0x00ff; \
+ } while (0)
+
+#define ISC__BUFFER_PUTUINT16(_b, _val) \
+ do { \
+ unsigned char *_cp; \
+ isc_uint16_t _val2 = (_val); \
+ _cp = isc_buffer_used(_b); \
+ (_b)->used += 2; \
+ _cp[0] = (unsigned char)((_val2 & 0xff00U) >> 8); \
+ _cp[1] = (unsigned char)(_val2 & 0x00ffU); \
+ } while (0)
+
+#define ISC__BUFFER_PUTUINT24(_b, _val) \
+ do { \
+ unsigned char *_cp; \
+ isc_uint32_t _val2 = (_val); \
+ _cp = isc_buffer_used(_b); \
+ (_b)->used += 3; \
+ _cp[0] = (unsigned char)((_val2 & 0xff0000U) >> 16); \
+ _cp[1] = (unsigned char)((_val2 & 0xff00U) >> 8); \
+ _cp[2] = (unsigned char)(_val2 & 0x00ffU); \
+ } while (0)
+
+#define ISC__BUFFER_PUTUINT32(_b, _val) \
+ do { \
+ unsigned char *_cp; \
+ isc_uint32_t _val2 = (_val); \
+ _cp = isc_buffer_used(_b); \
+ (_b)->used += 4; \
+ _cp[0] = (unsigned char)((_val2 & 0xff000000) >> 24); \
+ _cp[1] = (unsigned char)((_val2 & 0x00ff0000) >> 16); \
+ _cp[2] = (unsigned char)((_val2 & 0x0000ff00) >> 8); \
+ _cp[3] = (unsigned char)((_val2 & 0x000000ff)); \
+ } while (0)
+
+#if defined(ISC_BUFFER_USEINLINE)
+#define isc_buffer_init ISC__BUFFER_INIT
+#define isc_buffer_initnull ISC__BUFFER_INITNULL
+#define isc_buffer_invalidate ISC__BUFFER_INVALIDATE
+#define isc_buffer_region ISC__BUFFER_REGION
+#define isc_buffer_usedregion ISC__BUFFER_USEDREGION
+#define isc_buffer_availableregion ISC__BUFFER_AVAILABLEREGION
+#define isc_buffer_add ISC__BUFFER_ADD
+#define isc_buffer_subtract ISC__BUFFER_SUBTRACT
+#define isc_buffer_clear ISC__BUFFER_CLEAR
+#define isc_buffer_consumedregion ISC__BUFFER_CONSUMEDREGION
+#define isc_buffer_remainingregion ISC__BUFFER_REMAININGREGION
+#define isc_buffer_activeregion ISC__BUFFER_ACTIVEREGION
+#define isc_buffer_setactive ISC__BUFFER_SETACTIVE
+#define isc_buffer_first ISC__BUFFER_FIRST
+#define isc_buffer_forward ISC__BUFFER_FORWARD
+#define isc_buffer_back ISC__BUFFER_BACK
+#define isc_buffer_putmem ISC__BUFFER_PUTMEM
+#define isc_buffer_putstr ISC__BUFFER_PUTSTR
+#define isc_buffer_putuint8 ISC__BUFFER_PUTUINT8
+#define isc_buffer_putuint16 ISC__BUFFER_PUTUINT16
+#define isc_buffer_putuint24 ISC__BUFFER_PUTUINT24
+#define isc_buffer_putuint32 ISC__BUFFER_PUTUINT32
+#else
+#define isc_buffer_init isc__buffer_init
+#define isc_buffer_initnull isc__buffer_initnull
+#define isc_buffer_invalidate isc__buffer_invalidate
+#define isc_buffer_region isc__buffer_region
+#define isc_buffer_usedregion isc__buffer_usedregion
+#define isc_buffer_availableregion isc__buffer_availableregion
+#define isc_buffer_add isc__buffer_add
+#define isc_buffer_subtract isc__buffer_subtract
+#define isc_buffer_clear isc__buffer_clear
+#define isc_buffer_consumedregion isc__buffer_consumedregion
+#define isc_buffer_remainingregion isc__buffer_remainingregion
+#define isc_buffer_activeregion isc__buffer_activeregion
+#define isc_buffer_setactive isc__buffer_setactive
+#define isc_buffer_first isc__buffer_first
+#define isc_buffer_forward isc__buffer_forward
+#define isc_buffer_back isc__buffer_back
+#define isc_buffer_putmem isc__buffer_putmem
+#define isc_buffer_putstr isc__buffer_putstr
+#define isc_buffer_putuint8 isc__buffer_putuint8
+#define isc_buffer_putuint16 isc__buffer_putuint16
+#define isc_buffer_putuint24 isc__buffer_putuint24
+#define isc_buffer_putuint32 isc__buffer_putuint32
+#endif
+
+/*
+ * No inline method for this one (yet).
+ */
+#define isc_buffer_putuint48 isc__buffer_putuint48
+
+#endif /* ISC_BUFFER_H */
diff --git a/lib/isc/include/isc/bufferlist.h b/lib/isc/include/isc/bufferlist.h
new file mode 100644
index 0000000..54e00c7
--- /dev/null
+++ b/lib/isc/include/isc/bufferlist.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: bufferlist.h,v 1.17 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_BUFFERLIST_H
+#define ISC_BUFFERLIST_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/bufferlist.h
+ *
+ *
+ *\brief Buffer lists have no synchronization. Clients must ensure exclusive
+ * access.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+unsigned int
+isc_bufferlist_usedcount(isc_bufferlist_t *bl);
+/*!<
+ * \brief Return the length of the sum of all used regions of all buffers in
+ * the buffer list 'bl'
+ *
+ * Requires:
+ *
+ *\li 'bl' is not NULL.
+ *
+ * Returns:
+ *\li sum of all used regions' lengths.
+ */
+
+unsigned int
+isc_bufferlist_availablecount(isc_bufferlist_t *bl);
+/*!<
+ * \brief Return the length of the sum of all available regions of all buffers in
+ * the buffer list 'bl'
+ *
+ * Requires:
+ *
+ *\li 'bl' is not NULL.
+ *
+ * Returns:
+ *\li sum of all available regions' lengths.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_BUFFERLIST_H */
diff --git a/lib/isc/include/isc/commandline.h b/lib/isc/include/isc/commandline.h
new file mode 100644
index 0000000..384640a
--- /dev/null
+++ b/lib/isc/include/isc/commandline.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: commandline.h,v 1.16 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_COMMANDLINE_H
+#define ISC_COMMANDLINE_H 1
+
+/*! \file isc/commandline.h */
+
+#include <isc/boolean.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+/*% Index into parent argv vector. */
+LIBISC_EXTERNAL_DATA extern int isc_commandline_index;
+/*% Character checked for validity. */
+LIBISC_EXTERNAL_DATA extern int isc_commandline_option;
+/*% Argument associated with option. */
+LIBISC_EXTERNAL_DATA extern char *isc_commandline_argument;
+/*% For printing error messages. */
+LIBISC_EXTERNAL_DATA extern char *isc_commandline_progname;
+/*% Print error message. */
+LIBISC_EXTERNAL_DATA extern isc_boolean_t isc_commandline_errprint;
+/*% Reset getopt. */
+LIBISC_EXTERNAL_DATA extern isc_boolean_t isc_commandline_reset;
+
+ISC_LANG_BEGINDECLS
+
+/*% parse command line */
+int
+isc_commandline_parse(int argc, char * const *argv, const char *options);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_COMMANDLINE_H */
diff --git a/lib/isc/include/isc/entropy.h b/lib/isc/include/isc/entropy.h
new file mode 100644
index 0000000..cae4b20
--- /dev/null
+++ b/lib/isc/include/isc/entropy.h
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2004-2007 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: entropy.h,v 1.32 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ENTROPY_H
+#define ISC_ENTROPY_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/entropy.h
+ * \brief The entropy API
+ *
+ * \li MP:
+ * The entropy object is locked internally. All callbacks into
+ * application-provided functions (for setup, gathering, and
+ * shutdown of sources) are guaranteed to be called with the
+ * entropy API lock held. This means these functions are
+ * not permitted to call back into the entropy API.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * A buffer, used as an entropy pool.
+ *
+ * \li Security:
+ * While this code is believed to implement good entropy gathering
+ * and distribution, it has not been reviewed by a cryptographic
+ * expert.
+ * Since the added entropy is only as good as the sources used,
+ * this module could hand out bad data and never know it.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*@{*/
+/*% Entropy callback function. */
+typedef isc_result_t (*isc_entropystart_t)(isc_entropysource_t *source,
+ void *arg, isc_boolean_t blocking);
+typedef isc_result_t (*isc_entropyget_t)(isc_entropysource_t *source,
+ void *arg, isc_boolean_t blocking);
+typedef void (*isc_entropystop_t)(isc_entropysource_t *source, void *arg);
+/*@}*/
+
+/***
+ *** Flags.
+ ***/
+
+/*!
+ * \brief
+ * Extract only "good" data; return failure if there is not enough
+ * data available and there are no sources which we can poll to get
+ * data, or those sources are empty.
+ *
+ *
+ */
+#define ISC_ENTROPY_GOODONLY 0x00000001U
+/*!
+ * \brief
+ * Extract as much good data as possible, but if there isn't enough
+ * at hand, return what is available. This flag only makes sense
+ * when used with _GOODONLY.
+ */
+#define ISC_ENTROPY_PARTIAL 0x00000002U
+/*!
+ * \brief
+ * Block the task until data is available. This is contrary to the
+ * ISC task system, where tasks should never block. However, if
+ * this is a special purpose application where blocking a task is
+ * acceptable (say, an offline zone signer) this flag may be set.
+ * This flag only makes sense when used with _GOODONLY, and will
+ * block regardless of the setting for _PARTIAL.
+ */
+#define ISC_ENTROPY_BLOCKING 0x00000004U
+
+/*!
+ * \brief
+ * Estimate the amount of entropy contained in the sample pool.
+ * If this is not set, the source will be gathered and perodically
+ * mixed into the entropy pool, but no increment in contained entropy
+ * will be assumed. This flag only makes sense on sample sources.
+ */
+#define ISC_ENTROPYSOURCE_ESTIMATE 0x00000001U
+
+/*
+ * For use with isc_entropy_usebestsource().
+ */
+/*!
+ * \brief
+ * Use the keyboard as the only entropy source.
+ */
+#define ISC_ENTROPY_KEYBOARDYES 1
+/*!
+ * \brief
+ * Never use the keyboard as an entropy source.
+ */
+#define ISC_ENTROPY_KEYBOARDNO 2
+/*!
+ * \brief
+ * Use the keyboard as an entropy source only if opening the
+ * random device fails.
+ */
+#define ISC_ENTROPY_KEYBOARDMAYBE 3
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_entropy_create(isc_mem_t *mctx, isc_entropy_t **entp);
+/*!<
+ * \brief Create a new entropy object.
+ */
+
+void
+isc_entropy_attach(isc_entropy_t *ent, isc_entropy_t **entp);
+/*!<
+ * Attaches to an entropy object.
+ */
+
+void
+isc_entropy_detach(isc_entropy_t **entp);
+/*!<
+ * \brief Detaches from an entropy object.
+ */
+
+isc_result_t
+isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname);
+/*!<
+ * \brief Create a new entropy source from a file.
+ *
+ * The file is assumed to contain good randomness, and will be mixed directly
+ * into the pool with every byte adding 8 bits of entropy.
+ *
+ * The file will be put into non-blocking mode, so it may be a device file,
+ * such as /dev/random. /dev/urandom should not be used here if it can
+ * be avoided, since it will always provide data even if it isn't good.
+ * We will make as much pseudorandom data as we need internally if our
+ * caller asks for it.
+ *
+ * If we hit end-of-file, we will stop reading from this source. Callers
+ * who require strong random data will get failure when our pool drains.
+ * The file will never be opened/read again once EOF is reached.
+ */
+
+void
+isc_entropy_destroysource(isc_entropysource_t **sourcep);
+/*!<
+ * \brief Removes an entropy source from the entropy system.
+ */
+
+isc_result_t
+isc_entropy_createsamplesource(isc_entropy_t *ent,
+ isc_entropysource_t **sourcep);
+/*!<
+ * \brief Create an entropy source that consists of samples. Each sample is added
+ * to the source via isc_entropy_addsamples(), below.
+ */
+
+isc_result_t
+isc_entropy_createcallbacksource(isc_entropy_t *ent,
+ isc_entropystart_t start,
+ isc_entropyget_t get,
+ isc_entropystop_t stop,
+ void *arg,
+ isc_entropysource_t **sourcep);
+/*!<
+ * \brief Create an entropy source that is polled via a callback.
+ *
+ * This would
+ * be used when keyboard input is used, or a GUI input method. It can
+ * also be used to hook in any external entropy source.
+ *
+ * Samples are added via isc_entropy_addcallbacksample(), below.
+ * _addcallbacksample() is the only function which may be called from
+ * within an entropy API callback function.
+ */
+
+void
+isc_entropy_stopcallbacksources(isc_entropy_t *ent);
+/*!<
+ * \brief Call the stop functions for callback sources that have had their
+ * start functions called.
+ */
+
+/*@{*/
+isc_result_t
+isc_entropy_addcallbacksample(isc_entropysource_t *source, isc_uint32_t sample,
+ isc_uint32_t extra);
+isc_result_t
+isc_entropy_addsample(isc_entropysource_t *source, isc_uint32_t sample,
+ isc_uint32_t extra);
+/*!<
+ * \brief Add a sample to the sample source.
+ *
+ * The sample MUST be a timestamp
+ * that increases over time, with the exception of wrap-around for
+ * extremely high resolution timers which will quickly wrap-around
+ * a 32-bit integer.
+ *
+ * The "extra" parameter is used only to add a bit more unpredictable
+ * data. It is not used other than included in the hash of samples.
+ *
+ * When in an entropy API callback function, _addcallbacksource() must be
+ * used. At all other times, _addsample() must be used.
+ */
+/*@}*/
+
+isc_result_t
+isc_entropy_getdata(isc_entropy_t *ent, void *data, unsigned int length,
+ unsigned int *returned, unsigned int flags);
+/*!<
+ * \brief Extract data from the entropy pool. This may load the pool from various
+ * sources.
+ *
+ * Do this by stiring the pool and returning a part of hash as randomness.
+ * Note that no secrets are given away here since parts of the hash are
+ * xored together before returned.
+ *
+ * Honor the request from the caller to only return good data, any data,
+ * etc.
+ */
+
+void
+isc_entropy_putdata(isc_entropy_t *ent, void *data, unsigned int length,
+ isc_uint32_t entropy);
+/*!<
+ * \brief Add "length" bytes in "data" to the entropy pool, incrementing the pool's
+ * entropy count by "entropy."
+ *
+ * These bytes will prime the pseudorandom portion even no entropy is actually
+ * added.
+ */
+
+void
+isc_entropy_stats(isc_entropy_t *ent, FILE *out);
+/*!<
+ * \brief Dump some (trivial) stats to the stdio stream "out".
+ */
+
+unsigned int
+isc_entropy_status(isc_entropy_t *end);
+/*
+ * Returns the number of bits the pool currently contains. This is just
+ * an estimate.
+ */
+
+isc_result_t
+isc_entropy_usebestsource(isc_entropy_t *ectx, isc_entropysource_t **source,
+ const char *randomfile, int use_keyboard);
+/*!<
+ * \brief Use whatever source of entropy is best.
+ *
+ * Notes:
+ *\li If "randomfile" is not NULL, open it with
+ * isc_entropy_createfilesource().
+ *
+ *\li If "randomfile" is NULL and the system's random device was detected
+ * when the program was configured and built, open that device with
+ * isc_entropy_createfilesource().
+ *
+ *\li If "use_keyboard" is #ISC_ENTROPY_KEYBOARDYES, then always open
+ * the keyboard as an entropy source (possibly in addition to
+ * "randomfile" or the random device).
+ *
+ *\li If "use_keyboard" is #ISC_ENTROPY_KEYBOARDMAYBE, open the keyboard only
+ * if opening the random file/device fails. A message will be
+ * printed describing the need for keyboard input.
+ *
+ *\li If "use_keyboard" is #ISC_ENTROPY_KEYBOARDNO, the keyboard will
+ * never be opened.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS if at least one source of entropy could be started.
+ *
+ *\li #ISC_R_NOENTROPY if use_keyboard is #ISC_ENTROPY_KEYBOARDNO and
+ * there is no random device pathname compiled into the program.
+ *
+ *\li A return code from isc_entropy_createfilesource() or
+ * isc_entropy_createcallbacksource().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ENTROPY_H */
diff --git a/lib/isc/include/isc/error.h b/lib/isc/include/isc/error.h
new file mode 100644
index 0000000..efb9b5f
--- /dev/null
+++ b/lib/isc/include/isc/error.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: error.h,v 1.20 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ERROR_H
+#define ISC_ERROR_H 1
+
+/*! \file isc/error.h */
+
+#include <stdarg.h>
+
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef void (*isc_errorcallback_t)(const char *, int, const char *, va_list);
+
+/*% set unexpected error */
+void
+isc_error_setunexpected(isc_errorcallback_t);
+
+/*% set fatal error */
+void
+isc_error_setfatal(isc_errorcallback_t);
+
+/*% unexpected error */
+void
+isc_error_unexpected(const char *, int, const char *, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+/*% fatal error */
+void
+isc_error_fatal(const char *, int, const char *, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+/*% runtimecheck error */
+void
+isc_error_runtimecheck(const char *, int, const char *);
+
+#define ISC_ERROR_RUNTIMECHECK(cond) \
+ ((void) ((cond) || \
+ ((isc_error_runtimecheck)(__FILE__, __LINE__, #cond), 0)))
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ERROR_H */
diff --git a/lib/isc/include/isc/event.h b/lib/isc/include/isc/event.h
new file mode 100644
index 0000000..68fabb2
--- /dev/null
+++ b/lib/isc/include/isc/event.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: event.h,v 1.34 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_EVENT_H
+#define ISC_EVENT_H 1
+
+/*! \file isc/event.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*****
+ ***** Events.
+ *****/
+
+typedef void (*isc_eventdestructor_t)(isc_event_t *);
+
+#define ISC_EVENT_COMMON(ltype) \
+ size_t ev_size; \
+ unsigned int ev_attributes; \
+ void * ev_tag; \
+ isc_eventtype_t ev_type; \
+ isc_taskaction_t ev_action; \
+ void * ev_arg; \
+ void * ev_sender; \
+ isc_eventdestructor_t ev_destroy; \
+ void * ev_destroy_arg; \
+ ISC_LINK(ltype) ev_link
+
+/*%
+ * Attributes matching a mask of 0x000000ff are reserved for the task library's
+ * definition. Attributes of 0xffffff00 may be used by the application
+ * or non-ISC libraries.
+ */
+#define ISC_EVENTATTR_NOPURGE 0x00000001
+
+/*%
+ * The ISC_EVENTATTR_CANCELED attribute is intended to indicate
+ * that an event is delivered as a result of a canceled operation
+ * rather than successful completion, by mutual agreement
+ * between the sender and receiver. It is not set or used by
+ * the task system.
+ */
+#define ISC_EVENTATTR_CANCELED 0x00000002
+
+#define ISC_EVENT_INIT(event, sz, at, ta, ty, ac, ar, sn, df, da) \
+do { \
+ (event)->ev_size = (sz); \
+ (event)->ev_attributes = (at); \
+ (event)->ev_tag = (ta); \
+ (event)->ev_type = (ty); \
+ (event)->ev_action = (ac); \
+ (event)->ev_arg = (ar); \
+ (event)->ev_sender = (sn); \
+ (event)->ev_destroy = (df); \
+ (event)->ev_destroy_arg = (da); \
+ ISC_LINK_INIT((event), ev_link); \
+} while (0)
+
+/*%
+ * This structure is public because "subclassing" it may be useful when
+ * defining new event types.
+ */
+struct isc_event {
+ ISC_EVENT_COMMON(struct isc_event);
+};
+
+#define ISC_EVENTTYPE_FIRSTEVENT 0x00000000
+#define ISC_EVENTTYPE_LASTEVENT 0xffffffff
+
+#define ISC_EVENT_PTR(p) ((isc_event_t **)(void *)(p))
+
+ISC_LANG_BEGINDECLS
+
+isc_event_t *
+isc_event_allocate(isc_mem_t *mctx, void *sender, isc_eventtype_t type,
+ isc_taskaction_t action, const void *arg, size_t size);
+/*%<
+ * Allocate an event structure.
+ *
+ * Allocate and initialize in a structure with initial elements
+ * defined by:
+ *
+ * \code
+ * struct {
+ * ISC_EVENT_COMMON(struct isc_event);
+ * ...
+ * };
+ * \endcode
+ *
+ * Requires:
+ *\li 'size' >= sizeof(struct isc_event)
+ *\li 'action' to be non NULL
+ *
+ * Returns:
+ *\li a pointer to a initialized structure of the requested size.
+ *\li NULL if unable to allocate memory.
+ */
+
+void
+isc_event_free(isc_event_t **);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_EVENT_H */
diff --git a/lib/isc/include/isc/eventclass.h b/lib/isc/include/isc/eventclass.h
new file mode 100644
index 0000000..9e6c145
--- /dev/null
+++ b/lib/isc/include/isc/eventclass.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: eventclass.h,v 1.18 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_EVENTCLASS_H
+#define ISC_EVENTCLASS_H 1
+
+/*! \file isc/eventclass.h
+ ***** Registry of Predefined Event Type Classes
+ *****/
+
+/*%
+ * An event class is an unsigned 16 bit number. Each class may contain up
+ * to 65536 events. An event type is formed by adding the event number
+ * within the class to the class number.
+ *
+ */
+
+#define ISC_EVENTCLASS(eclass) ((eclass) << 16)
+
+/*@{*/
+/*!
+ * Classes < 1024 are reserved for ISC use.
+ * Event classes >= 1024 and <= 65535 are reserved for application use.
+ */
+
+#define ISC_EVENTCLASS_TASK ISC_EVENTCLASS(0)
+#define ISC_EVENTCLASS_TIMER ISC_EVENTCLASS(1)
+#define ISC_EVENTCLASS_SOCKET ISC_EVENTCLASS(2)
+#define ISC_EVENTCLASS_FILE ISC_EVENTCLASS(3)
+#define ISC_EVENTCLASS_DNS ISC_EVENTCLASS(4)
+#define ISC_EVENTCLASS_APP ISC_EVENTCLASS(5)
+#define ISC_EVENTCLASS_OMAPI ISC_EVENTCLASS(6)
+#define ISC_EVENTCLASS_RATELIMITER ISC_EVENTCLASS(7)
+#define ISC_EVENTCLASS_ISCCC ISC_EVENTCLASS(8)
+/*@}*/
+
+#endif /* ISC_EVENTCLASS_H */
diff --git a/lib/isc/include/isc/file.h b/lib/isc/include/isc/file.h
new file mode 100644
index 0000000..477317b
--- /dev/null
+++ b/lib/isc/include/isc/file.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2004-2007 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: file.h,v 1.33 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_FILE_H
+#define ISC_FILE_H 1
+
+/*! \file isc/file.h */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_file_settime(const char *file, isc_time_t *time);
+
+isc_result_t
+isc_file_getmodtime(const char *file, isc_time_t *time);
+/*!<
+ * \brief Get the time of last modication of a file.
+ *
+ * Notes:
+ *\li The time that is set is relative to the (OS-specific) epoch, as are
+ * all isc_time_t structures.
+ *
+ * Requires:
+ *\li file != NULL.
+ *\li time != NULL.
+ *
+ * Ensures:
+ *\li If the file could not be accessed, 'time' is unchanged.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ * Success.
+ *\li #ISC_R_NOTFOUND
+ * No such file exists.
+ *\li #ISC_R_INVALIDFILE
+ * The path specified was not usable by the operating system.
+ *\li #ISC_R_NOPERM
+ * The file's metainformation could not be retrieved because
+ * permission was denied to some part of the file's path.
+ *\li #ISC_R_EIO
+ * Hardware error interacting with the filesystem.
+ *\li #ISC_R_UNEXPECTED
+ * Something totally unexpected happened.
+ *
+ */
+
+isc_result_t
+isc_file_mktemplate(const char *path, char *buf, size_t buflen);
+/*!<
+ * \brief Generate a template string suitable for use with isc_file_openunique().
+ *
+ * Notes:
+ *\li This function is intended to make creating temporary files
+ * portable between different operating systems.
+ *
+ *\li The path is prepended to an implementation-defined string and
+ * placed into buf. The string has no path characters in it,
+ * and its maximum length is 14 characters plus a NUL. Thus
+ * buflen should be at least strlen(path) + 15 characters or
+ * an error will be returned.
+ *
+ * Requires:
+ *\li buf != NULL.
+ *
+ * Ensures:
+ *\li If result == #ISC_R_SUCCESS:
+ * buf contains a string suitable for use as the template argument
+ * to isc_file_openunique().
+ *
+ *\li If result != #ISC_R_SUCCESS:
+ * buf is unchanged.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOSPACE buflen indicates buf is too small for the catenation
+ * of the path with the internal template string.
+ */
+
+
+isc_result_t
+isc_file_openunique(char *templet, FILE **fp);
+/*!<
+ * \brief Create and open a file with a unique name based on 'templet'.
+ *
+ * Notes:
+ *\li 'template' is a reserved work in C++. If you want to complain
+ * about the spelling of 'templet', first look it up in the
+ * Merriam-Webster English dictionary. (http://www.m-w.com/)
+ *
+ *\li This function works by using the template to generate file names.
+ * The template must be a writable string, as it is modified in place.
+ * Trailing X characters in the file name (full file name on Unix,
+ * basename on Win32 -- eg, tmp-XXXXXX vs XXXXXX.tmp, respectively)
+ * are replaced with ASCII characters until a non-existent filename
+ * is found. If the template does not include pathname information,
+ * the files in the working directory of the program are searched.
+ *
+ *\li isc_file_mktemplate is a good, portable way to get a template.
+ *
+ * Requires:
+ *\li 'fp' is non-NULL and '*fp' is NULL.
+ *
+ *\li 'template' is non-NULL, and of a form suitable for use by
+ * the system as described above.
+ *
+ * Ensures:
+ *\li If result is #ISC_R_SUCCESS:
+ * *fp points to an stream opening in stdio's "w+" mode.
+ *
+ *\li If result is not #ISC_R_SUCCESS:
+ * *fp is NULL.
+ *
+ * No file is open. Even if one was created (but unable
+ * to be reopened as a stdio FILE pointer) then it has been
+ * removed.
+ *
+ *\li This function does *not* ensure that the template string has not been
+ * modified, even if the operation was unsuccessful.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ * Success.
+ *\li #ISC_R_EXISTS
+ * No file with a unique name could be created based on the
+ * template.
+ *\li #ISC_R_INVALIDFILE
+ * The path specified was not usable by the operating system.
+ *\li #ISC_R_NOPERM
+ * The file could not be created because permission was denied
+ * to some part of the file's path.
+ *\li #ISC_R_IOERROR
+ * Hardware error interacting with the filesystem.
+ *\li #ISC_R_UNEXPECTED
+ * Something totally unexpected happened.
+ */
+
+isc_result_t
+isc_file_remove(const char *filename);
+/*!<
+ * \brief Remove the file named by 'filename'.
+ */
+
+isc_result_t
+isc_file_rename(const char *oldname, const char *newname);
+/*!<
+ * \brief Rename the file 'oldname' to 'newname'.
+ */
+
+isc_boolean_t
+isc_file_exists(const char *pathname);
+/*!<
+ * \brief Return #ISC_TRUE if the calling process can tell that the given file exists.
+ * Will not return true if the calling process has insufficient privileges
+ * to search the entire path.
+ */
+
+isc_boolean_t
+isc_file_isabsolute(const char *filename);
+/*!<
+ * \brief Return #ISC_TRUE if the given file name is absolute.
+ */
+
+isc_boolean_t
+isc_file_iscurrentdir(const char *filename);
+/*!<
+ * \brief Return #ISC_TRUE if the given file name is the current directory (".").
+ */
+
+isc_boolean_t
+isc_file_ischdiridempotent(const char *filename);
+/*%<
+ * Return #ISC_TRUE if calling chdir(filename) multiple times will give
+ * the same result as calling it once.
+ */
+
+const char *
+isc_file_basename(const char *filename);
+/*%<
+ * Return the final component of the path in the file name.
+ */
+
+isc_result_t
+isc_file_progname(const char *filename, char *buf, size_t buflen);
+/*!<
+ * \brief Given an operating system specific file name "filename"
+ * referring to a program, return the canonical program name.
+ *
+ *
+ * Any directory prefix or executable file name extension (if
+ * used on the OS in case) is stripped. On systems where program
+ * names are case insensitive, the name is canonicalized to all
+ * lower case. The name is written to 'buf', an array of 'buflen'
+ * chars, and null terminated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE The name did not fit in 'buf'.
+ */
+
+isc_result_t
+isc_file_template(const char *path, const char *templet, char *buf,
+ size_t buflen);
+/*%<
+ * Create an OS specific template using 'path' to define the directory
+ * 'templet' to describe the filename and store the result in 'buf'
+ * such that path can be renamed to buf atomically.
+ */
+
+isc_result_t
+isc_file_renameunique(const char *file, char *templet);
+/*%<
+ * Rename 'file' using 'templet' as a template for the new file name.
+ */
+
+isc_result_t
+isc_file_absolutepath(const char *filename, char *path, size_t pathlen);
+/*%<
+ * Given a file name, return the fully qualified path to the file.
+ */
+
+/*
+ * XXX We should also have a isc_file_writeeopen() function
+ * for safely open a file in a publicly writable directory
+ * (see write_open() in BIND 8's ns_config.c).
+ */
+
+isc_result_t
+isc_file_truncate(const char *filename, isc_offset_t size);
+/*%<
+ * Truncate/extend the file specified to 'size' bytes.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_FILE_H */
diff --git a/lib/isc/include/isc/formatcheck.h b/lib/isc/include/isc/formatcheck.h
new file mode 100644
index 0000000..51ce3ca
--- /dev/null
+++ b/lib/isc/include/isc/formatcheck.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2007 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: formatcheck.h,v 1.13 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_FORMATCHECK_H
+#define ISC_FORMATCHECK_H 1
+
+/*! \file isc/formatcheck.h */
+
+/*%
+ * ISC_FORMAT_PRINTF().
+ *
+ * \li fmt is the location of the format string parameter.
+ * \li args is the location of the first argument (or 0 for no argument checking).
+ *
+ * Note:
+ * \li The first parameter is 1, not 0.
+ */
+#ifdef __GNUC__
+#define ISC_FORMAT_PRINTF(fmt, args) __attribute__((__format__(__printf__, fmt, args)))
+#else
+#define ISC_FORMAT_PRINTF(fmt, args)
+#endif
+
+#endif /* ISC_FORMATCHECK_H */
diff --git a/lib/isc/include/isc/fsaccess.h b/lib/isc/include/isc/fsaccess.h
new file mode 100644
index 0000000..900a739
--- /dev/null
+++ b/lib/isc/include/isc/fsaccess.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2004-2007 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: fsaccess.h,v 1.14 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_FSACCESS_H
+#define ISC_FSACCESS_H 1
+
+/*! \file isc/fsaccess.h
+ * \brief The ISC filesystem access module encapsulates the setting of file
+ * and directory access permissions into one API that is meant to be
+ * portable to multiple operating systems.
+ *
+ * The two primary operating system flavors that are initially accomodated are
+ * POSIX and Windows NT 4.0 and later. The Windows NT access model is
+ * considerable more flexible than POSIX's model (as much as I am loathe to
+ * admit it), and so the ISC API has a higher degree of complexity than would
+ * be needed to simply address POSIX's needs.
+ *
+ * The full breadth of NT's flexibility is not available either, for the
+ * present time. Much of it is to provide compatibility with what Unix
+ * programmers are expecting. This is also due to not yet really needing all
+ * of the functionality of an NT system (or, for that matter, a POSIX system)
+ * in BIND9, and so resolving how to handle the various incompatibilities has
+ * been a purely theoretical exercise with no operational experience to
+ * indicate how flawed the thinking may be.
+ *
+ * Some of the more notable dumbing down of NT for this API includes:
+ *
+ *\li Each of FILE_READ_DATA and FILE_READ_EA are set with #ISC_FSACCESS_READ.
+ *
+ * \li All of FILE_WRITE_DATA, FILE_WRITE_EA and FILE_APPEND_DATA are
+ * set with #ISC_FSACCESS_WRITE. FILE_WRITE_ATTRIBUTES is not set
+ * so as to be consistent with Unix, where only the owner of the file
+ * or the superuser can change the attributes/mode of a file.
+ *
+ * \li Both of FILE_ADD_FILE and FILE_ADD_SUBDIRECTORY are set with
+ * #ISC_FSACCESS_CREATECHILD. This is similar to setting the WRITE
+ * permission on a Unix directory.
+ *
+ * \li SYNCHRONIZE is always set for files and directories, unless someone
+ * can give me a reason why this is a bad idea.
+ *
+ * \li READ_CONTROL and FILE_READ_ATTRIBUTES are always set; this is
+ * consistent with Unix, where any file or directory can be stat()'d
+ * unless the directory path disallows complete access somewhere along
+ * the way.
+ *
+ * \li WRITE_DAC is only set for the owner. This too is consistent with
+ * Unix, and is tighter security than allowing anyone else to be
+ * able to set permissions.
+ *
+ * \li DELETE is only set for the owner. On Unix the ability to delete
+ * a file is controlled by the directory permissions, but it isn't
+ * currently clear to me what happens on NT if the directory has
+ * FILE_DELETE_CHILD set but a file within it does not have DELETE
+ * set. Always setting DELETE on the file/directory for the owner
+ * gives maximum flexibility to the owner without exposing the
+ * file to deletion by others.
+ *
+ * \li WRITE_OWNER is never set. This too is consistent with Unix,
+ * and is also tighter security than allowing anyone to change the
+ * ownership of the file apart from the superu..ahem, Administrator.
+ *
+ * \li Inheritance is set to NO_INHERITANCE.
+ *
+ * Unix's dumbing down includes:
+ *
+ * \li The sticky bit cannot be set.
+ *
+ * \li setuid and setgid cannot be set.
+ *
+ * \li Only regular files and directories can be set.
+ *
+ * The rest of this comment discusses a few of the incompatibilities
+ * between the two systems that need more thought if this API is to
+ * be extended to accomodate them.
+ *
+ * The Windows standard access right "DELETE" doesn't have a direct
+ * equivalent in the Unix world, so it isn't clear what should be done
+ * with it.
+ *
+ * The Unix sticky bit is not supported. While NT does have a concept
+ * of allowing users to create files in a directory but not delete or
+ * rename them, it does not have a concept of allowing them to be deleted
+ * if they are owned by the user trying to delete/rename. While it is
+ * probable that something could be cobbled together in NT 5 with inheritence,
+ * it can't really be done in NT 4 as a single property that you could
+ * set on a directory. You'd need to coordinate something with file creation
+ * so that every file created had DELETE set for the owner but noone else.
+ *
+ * On Unix systems, setting #ISC_FSACCESS_LISTDIRECTORY sets READ.
+ * ... setting either #ISC_FSACCESS_CREATECHILD or #ISC_FSACCESS_DELETECHILD
+ * sets WRITE.
+ * ... setting #ISC_FSACCESS_ACCESSCHILD sets EXECUTE.
+ *
+ * On NT systems, setting #ISC_FSACCESS_LISTDIRECTORY sets FILE_LIST_DIRECTORY.
+ * ... setting #ISC_FSACCESS_CREATECHILD sets FILE_CREATE_CHILD independently.
+ * ... setting #ISC_FSACCESS_DELETECHILD sets FILE_DELETE_CHILD independently.
+ * ... setting #ISC_FSACCESS_ACCESSCHILD sets FILE_TRAVERSE.
+ *
+ * Unresolved: XXXDCL
+ * \li What NT access right controls the ability to rename a file?
+ * \li How does DELETE work? If a directory has FILE_DELETE_CHILD but a
+ * file or directory within it does not have DELETE, is that file
+ * or directory deletable?
+ * \li To implement isc_fsaccess_get(), mapping an existing Unix permission
+ * mode_t back to an isc_fsaccess_t is pretty trivial; however, mapping
+ * an NT DACL could be impossible to do in a responsible way.
+ * \li Similarly, trying to implement the functionality of being able to
+ * say "add group writability to whatever permissions already exist"
+ * could be tricky on NT because of the order-of-entry issue combined
+ * with possibly having one or more matching ACEs already explicitly
+ * granting or denying access. Because this functionality is
+ * not yet needed by the ISC, no code has been written to try to
+ * solve this problem.
+ */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*
+ * Trustees.
+ */
+#define ISC_FSACCESS_OWNER 0x1 /*%< User account. */
+#define ISC_FSACCESS_GROUP 0x2 /*%< Primary group owner. */
+#define ISC_FSACCESS_OTHER 0x4 /*%< Not the owner or the group owner. */
+#define ISC_FSACCESS_WORLD 0x7 /*%< User, Group, Other. */
+
+/*
+ * Types of permission.
+ */
+#define ISC_FSACCESS_READ 0x00000001 /*%< File only. */
+#define ISC_FSACCESS_WRITE 0x00000002 /*%< File only. */
+#define ISC_FSACCESS_EXECUTE 0x00000004 /*%< File only. */
+#define ISC_FSACCESS_CREATECHILD 0x00000008 /*%< Dir only. */
+#define ISC_FSACCESS_DELETECHILD 0x00000010 /*%< Dir only. */
+#define ISC_FSACCESS_LISTDIRECTORY 0x00000020 /*%< Dir only. */
+#define ISC_FSACCESS_ACCESSCHILD 0x00000040 /*%< Dir only. */
+
+/*%
+ * Adding any permission bits beyond 0x200 would mean typedef'ing
+ * isc_fsaccess_t as isc_uint64_t, and redefining this value to
+ * reflect the new range of permission types, Probably to 21 for
+ * maximum flexibility. The number of bits has to accomodate all of
+ * the permission types, and three full sets of them have to fit
+ * within an isc_fsaccess_t.
+ */
+#define ISC__FSACCESS_PERMISSIONBITS 10
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_fsaccess_add(int trustee, int permission, isc_fsaccess_t *access);
+
+void
+isc_fsaccess_remove(int trustee, int permission, isc_fsaccess_t *access);
+
+isc_result_t
+isc_fsaccess_set(const char *path, isc_fsaccess_t access);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_FSACCESS_H */
diff --git a/lib/isc/include/isc/hash.h b/lib/isc/include/isc/hash.h
new file mode 100644
index 0000000..b80966c
--- /dev/null
+++ b/lib/isc/include/isc/hash.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: hash.h,v 1.10 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_HASH_H
+#define ISC_HASH_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/hash.h
+ *
+ * \brief The hash API
+ * provides an unpredictable hash value for variable length data.
+ * A hash object contains a random vector (which is hidden from clients
+ * of this API) to make the actual hash value unpredictable.
+ *
+ * The algorithm used in the API guarantees the probability of hash
+ * collision; in the current implementation, as long as the values stored
+ * in the random vector are unpredictable, the probability of hash
+ * collision between arbitrary two different values is at most 1/2^16.
+ *
+ * Altough the API is generic about the hash keys, it mainly expects
+ * DNS names (and sometimes IPv4/v6 addresses) as inputs. It has an
+ * upper limit of the input length, and may run slow to calculate the
+ * hash values for large inputs.
+ *
+ * This API is designed to be general so that it can provide multiple
+ * different hash contexts that have different random vectors. However,
+ * it should be typical to have a single context for an entire system.
+ * To support such cases, the API also provides a single-context mode.
+ *
+ * \li MP:
+ * The hash object is almost read-only. Once the internal random vector
+ * is initialized, no write operation will occur, and there will be no
+ * need to lock the object to calculate actual hash values.
+ *
+ * \li Reliability:
+ * In some cases this module uses low-level data copy to initialize the
+ * random vector. Errors in this part are likely to crash the server or
+ * corrupt memory.
+ *
+ * \li Resources:
+ * A buffer, used as a random vector for calculating hash values.
+ *
+ * \li Security:
+ * This module intends to provide unpredictable hash values in
+ * adversarial environments in order to avoid denial of service attacks
+ * to hash buckets.
+ * Its unpredictability relies on the quality of entropy to build the
+ * random vector.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/types.h>
+
+/***
+ *** Functions
+ ***/
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_hash_ctxcreate(isc_mem_t *mctx, isc_entropy_t *entropy, unsigned int limit,
+ isc_hash_t **hctx);
+isc_result_t
+isc_hash_create(isc_mem_t *mctx, isc_entropy_t *entropy, size_t limit);
+/*!<
+ * \brief Create a new hash object.
+ *
+ * isc_hash_ctxcreate() creates a different object.
+ *
+ * isc_hash_create() creates a module-internal object to support the
+ * single-context mode. It should be called only once.
+ *
+ * 'entropy' must be NULL or a valid entropy object. If 'entropy' is NULL,
+ * pseudo random values will be used to build the random vector, which may
+ * weaken security.
+ *
+ * 'limit' specifies the maximum number of hash keys. If it is too large,
+ * these functions may fail.
+ */
+
+void
+isc_hash_ctxattach(isc_hash_t *hctx, isc_hash_t **hctxp);
+/*!<
+ * \brief Attach to a hash object.
+ *
+ * This function is only necessary for the multiple-context mode.
+ */
+
+void
+isc_hash_ctxdetach(isc_hash_t **hctxp);
+/*!<
+ * \brief Detach from a hash object.
+ *
+ * This function is for the multiple-context mode, and takes a valid
+ * hash object as an argument.
+ */
+
+void
+isc_hash_destroy(void);
+/*!<
+ * \brief This function is for the single-context mode, and is expected to be used
+ * as a counterpart of isc_hash_create().
+ *
+ * A valid module-internal hash object must have been created, and this
+ * function should be called only once.
+ */
+
+/*@{*/
+void
+isc_hash_ctxinit(isc_hash_t *hctx);
+void
+isc_hash_init(void);
+/*!<
+ * \brief Initialize a hash object.
+ *
+ * It fills in the random vector with a proper
+ * source of entropy, which is typically from the entropy object specified
+ * at the creation. Thus, it is desirable to call these functions after
+ * initializing the entropy object with some good entropy sources.
+ *
+ * These functions should be called before the first hash calculation.
+ *
+ * isc_hash_ctxinit() is for the multiple-context mode, and takes a valid hash
+ * object as an argument.
+ *
+ * isc_hash_init() is for the single-context mode. A valid module-internal
+ * hash object must have been created, and this function should be called only
+ * once.
+ */
+/*@}*/
+
+/*@{*/
+unsigned int
+isc_hash_ctxcalc(isc_hash_t *hctx, const unsigned char *key,
+ unsigned int keylen, isc_boolean_t case_sensitive);
+unsigned int
+isc_hash_calc(const unsigned char *key, unsigned int keylen,
+ isc_boolean_t case_sensitive);
+/*!<
+ * \brief Calculate a hash value.
+ *
+ * isc_hash_ctxinit() is for the multiple-context mode, and takes a valid hash
+ * object as an argument.
+ *
+ * isc_hash_init() is for the single-context mode. A valid module-internal
+ * hash object must have been created.
+ *
+ * 'key' is the hash key, which is a variable length buffer.
+ *
+ * 'keylen' specifies the key length, which must not be larger than the limit
+ * specified for the corresponding hash object.
+ *
+ * 'case_sensitive' specifies whether the hash key should be treated as
+ * case_sensitive values. It should typically be ISC_FALSE if the hash key
+ * is a DNS name.
+ */
+/*@}*/
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HASH_H */
diff --git a/lib/isc/include/isc/heap.h b/lib/isc/include/isc/heap.h
new file mode 100644
index 0000000..6118b00
--- /dev/null
+++ b/lib/isc/include/isc/heap.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-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: heap.h,v 1.24 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_HEAP_H
+#define ISC_HEAP_H 1
+
+/*! \file isc/heap.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * The comparision function returns ISC_TRUE if the first argument has
+ * higher priority than the second argument, and ISC_FALSE otherwise.
+ */
+typedef isc_boolean_t (*isc_heapcompare_t)(void *, void *);
+
+/*%
+ * The index function allows the client of the heap to receive a callback
+ * when an item's index number changes. This allows it to maintain
+ * sync with its external state, but still delete itself, since deletions
+ * from the heap require the index be provided.
+ */
+typedef void (*isc_heapindex_t)(void *, unsigned int);
+
+/*%
+ * The heapaction function is used when iterating over the heap.
+ *
+ * NOTE: The heap structure CANNOT BE MODIFIED during the call to
+ * isc_heap_foreach().
+ */
+typedef void (*isc_heapaction_t)(void *, void *);
+
+typedef struct isc_heap isc_heap_t;
+
+isc_result_t
+isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare,
+ isc_heapindex_t index, unsigned int size_increment,
+ isc_heap_t **heapp);
+/*!<
+ * \brief Create a new heap. The heap is implemented using a space-efficient
+ * storage method. When the heap elements are deleted space is not freed
+ * but will be reused when new elements are inserted.
+ *
+ * Requires:
+ *\li "mctx" is valid.
+ *\li "compare" is a function which takes two void * arguments and
+ * returns ISC_TRUE if the first argument has a higher priority than
+ * the second, and ISC_FALSE otherwise.
+ *\li "index" is a function which takes a void *, and an unsigned int
+ * argument. This function will be called whenever an element's
+ * index value changes, so it may continue to delete itself from the
+ * heap. This option may be NULL if this functionality is unneeded.
+ *\li "size_increment" is a hint about how large the heap should grow
+ * when resizing is needed. If this is 0, a default size will be
+ * used, which is currently 1024, allowing space for an additional 1024
+ * heap elements to be inserted before adding more space.
+ *\li "heapp" is not NULL, and "*heap" is NULL.
+ *
+ * Returns:
+ *\li ISC_R_SUCCESS - success
+ *\li ISC_R_NOMEMORY - insufficient memory
+ */
+
+void
+isc_heap_destroy(isc_heap_t **heapp);
+/*!<
+ * \brief Destroys a heap.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ */
+
+isc_result_t
+isc_heap_insert(isc_heap_t *heap, void *elt);
+/*!<
+ * \brief Inserts a new element into a heap.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ */
+
+void
+isc_heap_delete(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Deletes an element from a heap, by element index.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li "index" is a valid element index, as provided by the "index" callback
+ * provided during heap creation.
+ */
+
+void
+isc_heap_increased(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Indicates to the heap that an element's priority has increased.
+ * This function MUST be called whenever an element has increased in priority.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li "index" is a valid element index, as provided by the "index" callback
+ * provided during heap creation.
+ */
+
+void
+isc_heap_decreased(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Indicates to the heap that an element's priority has decreased.
+ * This function MUST be called whenever an element has decreased in priority.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li "index" is a valid element index, as provided by the "index" callback
+ * provided during heap creation.
+ */
+
+void *
+isc_heap_element(isc_heap_t *heap, unsigned int index);
+/*!<
+ * \brief Returns the element for a specific element index.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li "index" is a valid element index, as provided by the "index" callback
+ * provided during heap creation.
+ *
+ * Returns:
+ *\li A pointer to the element for the element index.
+ */
+
+void
+isc_heap_foreach(isc_heap_t *heap, isc_heapaction_t action, void *uap);
+/*!<
+ * \brief Iterate over the heap, calling an action for each element. The
+ * order of iteration is not sorted.
+ *
+ * Requires:
+ *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t.
+ *\li "action" is not NULL, and is a function which takes two arguments.
+ * The first is a void *, representing the element, and the second is
+ * "uap" as provided to isc_heap_foreach.
+ *\li "uap" is a caller-provided argument, and may be NULL.
+ *
+ * Note:
+ *\li The heap structure CANNOT be modified during this iteration. The only
+ * safe function to call while iterating the heap is isc_heap_element().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HEAP_H */
diff --git a/lib/isc/include/isc/hex.h b/lib/isc/include/isc/hex.h
new file mode 100644
index 0000000..a5e2f53
--- /dev/null
+++ b/lib/isc/include/isc/hex.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: hex.h,v 1.13 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef ISC_HEX_H
+#define ISC_HEX_H 1
+
+/*! \file isc/hex.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_hex_totext(isc_region_t *source, int wordlength,
+ const char *wordbreak, isc_buffer_t *target);
+/*!<
+ * \brief Convert data into hex encoded text.
+ *
+ * Notes:
+ *\li The hex encoded text in 'target' will be divided into
+ * words of at most 'wordlength' characters, separated by
+ * the 'wordbreak' string. No parentheses will surround
+ * the text.
+ *
+ * Requires:
+ *\li 'source' is a region containing binary data
+ *\li 'target' is a text buffer containing available space
+ *\li 'wordbreak' points to a null-terminated string of
+ * zero or more whitespace characters
+ *
+ * Ensures:
+ *\li target will contain the hex encoded version of the data
+ * in source. The 'used' pointer in target will be advanced as
+ * necessary.
+ */
+
+isc_result_t
+isc_hex_decodestring(const char *cstr, isc_buffer_t *target);
+/*!<
+ * \brief Decode a null-terminated hex string.
+ *
+ * Requires:
+ *\li 'cstr' is non-null.
+ *\li 'target' is a valid buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- the entire decoded representation of 'cstring'
+ * fit in 'target'.
+ *\li #ISC_R_BADHEX -- 'cstr' is not a valid hex encoding.
+ *
+ * Other error returns are any possible error code from:
+ * isc_lex_create(),
+ * isc_lex_openbuffer(),
+ * isc_hex_tobuffer().
+ */
+
+isc_result_t
+isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length);
+/*!<
+ * \brief Convert hex encoded text from a lexer context into data.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer context
+ *\li 'target' is a buffer containing binary data
+ *\li 'length' is an integer
+ *
+ * Ensures:
+ *\li target will contain the data represented by the hex encoded
+ * string parsed by the lexer. No more than length bytes will be read,
+ * if length is positive. The 'used' pointer in target will be
+ * advanced as necessary.
+ */
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HEX_H */
diff --git a/lib/isc/include/isc/hmacmd5.h b/lib/isc/include/isc/hmacmd5.h
new file mode 100644
index 0000000..fab9c58
--- /dev/null
+++ b/lib/isc/include/isc/hmacmd5.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2007 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: hmacmd5.h,v 1.12 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file isc/hmacmd5.h
+ * \brief This is the header file for the HMAC-MD5 keyed hash algorithm
+ * described in RFC2104.
+ */
+
+#ifndef ISC_HMACMD5_H
+#define ISC_HMACMD5_H 1
+
+#include <isc/lang.h>
+#include <isc/md5.h>
+#include <isc/types.h>
+
+#define ISC_HMACMD5_KEYLENGTH 64
+
+typedef struct {
+ isc_md5_t md5ctx;
+ unsigned char key[ISC_HMACMD5_KEYLENGTH];
+} isc_hmacmd5_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_hmacmd5_init(isc_hmacmd5_t *ctx, const unsigned char *key,
+ unsigned int len);
+
+void
+isc_hmacmd5_invalidate(isc_hmacmd5_t *ctx);
+
+void
+isc_hmacmd5_update(isc_hmacmd5_t *ctx, const unsigned char *buf,
+ unsigned int len);
+
+void
+isc_hmacmd5_sign(isc_hmacmd5_t *ctx, unsigned char *digest);
+
+isc_boolean_t
+isc_hmacmd5_verify(isc_hmacmd5_t *ctx, unsigned char *digest);
+
+isc_boolean_t
+isc_hmacmd5_verify2(isc_hmacmd5_t *ctx, unsigned char *digest, size_t len);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HMACMD5_H */
diff --git a/lib/isc/include/isc/hmacsha.h b/lib/isc/include/isc/hmacsha.h
new file mode 100644
index 0000000..362b37f
--- /dev/null
+++ b/lib/isc/include/isc/hmacsha.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2005-2007 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: hmacsha.h,v 1.7 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file isc/hmacsha.h
+ * This is the header file for the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256,
+ * HMAC-SHA334 and HMAC-SHA512 hash algorithm described in RFC 2104.
+ */
+
+#ifndef ISC_HMACSHA_H
+#define ISC_HMACSHA_H 1
+
+#include <isc/lang.h>
+#include <isc/sha1.h>
+#include <isc/sha2.h>
+#include <isc/types.h>
+
+#define ISC_HMACSHA1_KEYLENGTH ISC_SHA1_BLOCK_LENGTH
+#define ISC_HMACSHA224_KEYLENGTH ISC_SHA224_BLOCK_LENGTH
+#define ISC_HMACSHA256_KEYLENGTH ISC_SHA256_BLOCK_LENGTH
+#define ISC_HMACSHA384_KEYLENGTH ISC_SHA384_BLOCK_LENGTH
+#define ISC_HMACSHA512_KEYLENGTH ISC_SHA512_BLOCK_LENGTH
+
+typedef struct {
+ isc_sha1_t sha1ctx;
+ unsigned char key[ISC_HMACSHA1_KEYLENGTH];
+} isc_hmacsha1_t;
+
+typedef struct {
+ isc_sha224_t sha224ctx;
+ unsigned char key[ISC_HMACSHA224_KEYLENGTH];
+} isc_hmacsha224_t;
+
+typedef struct {
+ isc_sha256_t sha256ctx;
+ unsigned char key[ISC_HMACSHA256_KEYLENGTH];
+} isc_hmacsha256_t;
+
+typedef struct {
+ isc_sha384_t sha384ctx;
+ unsigned char key[ISC_HMACSHA384_KEYLENGTH];
+} isc_hmacsha384_t;
+
+typedef struct {
+ isc_sha512_t sha512ctx;
+ unsigned char key[ISC_HMACSHA512_KEYLENGTH];
+} isc_hmacsha512_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
+ unsigned int len);
+
+void
+isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx);
+
+void
+isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
+ unsigned int len);
+
+void
+isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len);
+
+isc_boolean_t
+isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len);
+
+
+void
+isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
+ unsigned int len);
+
+void
+isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx);
+
+void
+isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
+ unsigned int len);
+
+void
+isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len);
+
+isc_boolean_t
+isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len);
+
+
+void
+isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
+ unsigned int len);
+
+void
+isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx);
+
+void
+isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
+ unsigned int len);
+
+void
+isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len);
+
+isc_boolean_t
+isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len);
+
+
+void
+isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
+ unsigned int len);
+
+void
+isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx);
+
+void
+isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
+ unsigned int len);
+
+void
+isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len);
+
+isc_boolean_t
+isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len);
+
+
+void
+isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
+ unsigned int len);
+
+void
+isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx);
+
+void
+isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
+ unsigned int len);
+
+void
+isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len);
+
+isc_boolean_t
+isc_hmacsha512_verify(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_HMACSHA_H */
diff --git a/lib/isc/include/isc/httpd.h b/lib/isc/include/isc/httpd.h
new file mode 100644
index 0000000..ba7f900
--- /dev/null
+++ b/lib/isc/include/isc/httpd.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006-2008 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: httpd.h,v 1.9 2008/08/08 05:06:49 marka Exp $ */
+
+#ifndef ISC_HTTPD_H
+#define ISC_HTTPD_H 1
+
+/*! \file */
+
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/types.h>
+#include <isc/mutex.h>
+#include <isc/task.h>
+
+#define HTTPD_EVENTCLASS ISC_EVENTCLASS(4300)
+#define HTTPD_SHUTDOWN (HTTPD_EVENTCLASS + 0x0001)
+
+#define ISC_HTTPDMGR_FLAGSHUTTINGDOWN 0x00000001
+
+/*
+ * Create a new http daemon which will send, once every time period,
+ * a http-like header followed by HTTP data.
+ */
+isc_result_t
+isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task,
+ isc_httpdclientok_t *client_ok,
+ isc_httpdondestroy_t *ondestory, void *cb_arg,
+ isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp);
+
+void
+isc_httpdmgr_shutdown(isc_httpdmgr_t **httpdp);
+
+isc_result_t
+isc_httpdmgr_addurl(isc_httpdmgr_t *httpdmgr, const char *url,
+ isc_httpdaction_t *func, void *arg);
+
+isc_result_t
+isc_httpd_response(isc_httpd_t *httpd);
+
+isc_result_t
+isc_httpd_addheader(isc_httpd_t *httpd, const char *name,
+ const char *val);
+
+isc_result_t
+isc_httpd_addheaderuint(isc_httpd_t *httpd, const char *name, int val);
+
+isc_result_t isc_httpd_endheaders(isc_httpd_t *httpd);
+
+#endif /* ISC_HTTPD_H */
diff --git a/lib/isc/include/isc/interfaceiter.h b/lib/isc/include/isc/interfaceiter.h
new file mode 100644
index 0000000..26d5dfb
--- /dev/null
+++ b/lib/isc/include/isc/interfaceiter.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: interfaceiter.h,v 1.17 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_INTERFACEITER_H
+#define ISC_INTERFACEITER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/interfaceiter.h
+ * \brief Iterates over the list of network interfaces.
+ *
+ * Interfaces whose address family is not supported are ignored and never
+ * returned by the iterator. Interfaces whose netmask, interface flags,
+ * or similar cannot be obtained are also ignored, and the failure is logged.
+ *
+ * Standards:
+ * The API for scanning varies greatly among operating systems.
+ * This module attempts to hide the differences.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/netaddr.h>
+#include <isc/types.h>
+
+/*!
+ * \brief Public structure describing a network interface.
+ */
+
+struct isc_interface {
+ char name[32]; /*%< Interface name, null-terminated. */
+ unsigned int af; /*%< Address family. */
+ isc_netaddr_t address; /*%< Local address. */
+ isc_netaddr_t netmask; /*%< Network mask. */
+ isc_netaddr_t dstaddress; /*%< Destination address (point-to-point only). */
+ isc_uint32_t flags; /*%< Flags; see INTERFACE flags. */
+};
+
+/*@{*/
+/*! Interface flags. */
+
+#define INTERFACE_F_UP 0x00000001U
+#define INTERFACE_F_POINTTOPOINT 0x00000002U
+#define INTERFACE_F_LOOPBACK 0x00000004U
+/*@}*/
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp);
+/*!<
+ * \brief Create an iterator for traversing the operating system's list
+ * of network interfaces.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ *\li Various network-related errors
+ */
+
+isc_result_t
+isc_interfaceiter_first(isc_interfaceiter_t *iter);
+/*!<
+ * \brief Position the iterator on the first interface.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOMORE There are no interfaces.
+ */
+
+isc_result_t
+isc_interfaceiter_current(isc_interfaceiter_t *iter,
+ isc_interface_t *ifdata);
+/*!<
+ * \brief Get information about the interface the iterator is currently
+ * positioned at and store it at *ifdata.
+ *
+ * Requires:
+ *\li The iterator has been successfully positioned using
+ * isc_interface_iter_first() / isc_interface_iter_next().
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ */
+
+isc_result_t
+isc_interfaceiter_next(isc_interfaceiter_t *iter);
+/*!<
+ * \brief Position the iterator on the next interface.
+ *
+ * Requires:
+ * \li The iterator has been successfully positioned using
+ * isc_interface_iter_first() / isc_interface_iter_next().
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOMORE There are no more interfaces.
+ */
+
+void
+isc_interfaceiter_destroy(isc_interfaceiter_t **iterp);
+/*!<
+ * \brief Destroy the iterator.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_INTERFACEITER_H */
diff --git a/lib/isc/include/isc/ipv6.h b/lib/isc/include/isc/ipv6.h
new file mode 100644
index 0000000..8054c9e
--- /dev/null
+++ b/lib/isc/include/isc/ipv6.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: ipv6.h,v 1.24 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_IPV6_H
+#define ISC_IPV6_H 1
+
+/*!
+ * Also define LWRES_IPV6_H to keep it from being included if liblwres is
+ * being used, or redefinition errors will occur.
+ */
+#define LWRES_IPV6_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/ipv6.h
+ * \brief IPv6 definitions for systems which do not support IPv6.
+ *
+ * \li MP:
+ * No impact.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * N/A.
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * RFC2553.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/int.h>
+#include <isc/platform.h>
+
+/***
+ *** Types.
+ ***/
+
+struct in6_addr {
+ union {
+ isc_uint8_t _S6_u8[16];
+ isc_uint16_t _S6_u16[8];
+ isc_uint32_t _S6_u32[4];
+ } _S6_un;
+};
+#define s6_addr _S6_un._S6_u8
+#define s6_addr8 _S6_un._S6_u8
+#define s6_addr16 _S6_un._S6_u16
+#define s6_addr32 _S6_un._S6_u32
+
+#define IN6ADDR_ANY_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}}
+#define IN6ADDR_LOOPBACK_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}}
+
+LIBISC_EXTERNAL_DATA extern const struct in6_addr in6addr_any;
+LIBISC_EXTERNAL_DATA extern const struct in6_addr in6addr_loopback;
+
+struct sockaddr_in6 {
+#ifdef ISC_PLATFORM_HAVESALEN
+ isc_uint8_t sin6_len;
+ isc_uint8_t sin6_family;
+#else
+ isc_uint16_t sin6_family;
+#endif
+ isc_uint16_t sin6_port;
+ isc_uint32_t sin6_flowinfo;
+ struct in6_addr sin6_addr;
+ isc_uint32_t sin6_scope_id;
+};
+
+#ifdef ISC_PLATFORM_HAVESALEN
+#define SIN6_LEN 1
+#endif
+
+/*%
+ * Unspecified
+ */
+#define IN6_IS_ADDR_UNSPECIFIED(a) \
+ (((a)->s6_addr32[0] == 0) && \
+ ((a)->s6_addr32[1] == 0) && \
+ ((a)->s6_addr32[2] == 0) && \
+ ((a)->s6_addr32[3] == 0))
+
+/*%
+ * Loopback
+ */
+#define IN6_IS_ADDR_LOOPBACK(a) \
+ (((a)->s6_addr32[0] == 0) && \
+ ((a)->s6_addr32[1] == 0) && \
+ ((a)->s6_addr32[2] == 0) && \
+ ((a)->s6_addr32[3] == htonl(1)))
+
+/*%
+ * IPv4 compatible
+ */
+#define IN6_IS_ADDR_V4COMPAT(a) \
+ (((a)->s6_addr32[0] == 0) && \
+ ((a)->s6_addr32[1] == 0) && \
+ ((a)->s6_addr32[2] == 0) && \
+ ((a)->s6_addr32[3] != 0) && \
+ ((a)->s6_addr32[3] != htonl(1)))
+
+/*%
+ * Mapped
+ */
+#define IN6_IS_ADDR_V4MAPPED(a) \
+ (((a)->s6_addr32[0] == 0) && \
+ ((a)->s6_addr32[1] == 0) && \
+ ((a)->s6_addr32[2] == htonl(0x0000ffff)))
+
+/*%
+ * Multicast
+ */
+#define IN6_IS_ADDR_MULTICAST(a) \
+ ((a)->s6_addr8[0] == 0xffU)
+
+/*%
+ * Unicast link / site local.
+ */
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+ (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
+#define IN6_IS_ADDR_SITELOCAL(a) \
+ (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
+
+#endif /* ISC_IPV6_H */
diff --git a/lib/isc/include/isc/iterated_hash.h b/lib/isc/include/isc/iterated_hash.h
new file mode 100644
index 0000000..a8173f0
--- /dev/null
+++ b/lib/isc/include/isc/iterated_hash.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008 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: iterated_hash.h,v 1.3 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef ISC_ITERATED_HASH_H
+#define ISC_ITERATED_HASH_H 1
+
+#include <isc/lang.h>
+#include <isc/sha1.h>
+
+/*
+ * The maximal hash length that can be encoded it a name
+ * using base32hex. floor(255/8)*5
+ */
+#define NSEC3_MAX_HASH_LENGTH 155
+
+/*
+ * The maximum has that can be encoded in a single label using
+ * base32hex. floor(63/8)*5
+ */
+#define NSEC3_MAX_LABEL_HASH 35
+
+ISC_LANG_BEGINDECLS
+
+int isc_iterated_hash(unsigned char out[NSEC3_MAX_HASH_LENGTH],
+ unsigned int hashalg, int iterations,
+ const unsigned char *salt, int saltlength,
+ const unsigned char *in, int inlength);
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ITERATED_HASH_H */
diff --git a/lib/isc/include/isc/lang.h b/lib/isc/include/isc/lang.h
new file mode 100644
index 0000000..8c60866
--- /dev/null
+++ b/lib/isc/include/isc/lang.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: lang.h,v 1.13 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_LANG_H
+#define ISC_LANG_H 1
+
+/*! \file isc/lang.h */
+
+#ifdef __cplusplus
+#define ISC_LANG_BEGINDECLS extern "C" {
+#define ISC_LANG_ENDDECLS }
+#else
+#define ISC_LANG_BEGINDECLS
+#define ISC_LANG_ENDDECLS
+#endif
+
+#endif /* ISC_LANG_H */
diff --git a/lib/isc/include/isc/lex.h b/lib/isc/include/isc/lex.h
new file mode 100644
index 0000000..8612150
--- /dev/null
+++ b/lib/isc/include/isc/lex.h
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: lex.h,v 1.37 2008/05/30 23:47:01 tbox Exp $ */
+
+#ifndef ISC_LEX_H
+#define ISC_LEX_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/lex.h
+ * \brief The "lex" module provides a lightweight tokenizer. It can operate
+ * on files or buffers, and can handle "include". It is designed for
+ * parsing of DNS master files and the BIND configuration file, but
+ * should be general enough to tokenize other things, e.g. HTTP.
+ *
+ * \li MP:
+ * No synchronization is provided. Clients must ensure exclusive
+ * access.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/region.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Options
+ ***/
+
+/*@{*/
+/*!
+ * Various options for isc_lex_gettoken().
+ */
+
+#define ISC_LEXOPT_EOL 0x01 /*%< Want end-of-line token. */
+#define ISC_LEXOPT_EOF 0x02 /*%< Want end-of-file token. */
+#define ISC_LEXOPT_INITIALWS 0x04 /*%< Want initial whitespace. */
+#define ISC_LEXOPT_NUMBER 0x08 /*%< Recognize numbers. */
+#define ISC_LEXOPT_QSTRING 0x10 /*%< Recognize qstrings. */
+/*@}*/
+
+/*@{*/
+/*!
+ * The ISC_LEXOPT_DNSMULTILINE option handles the processing of '(' and ')' in
+ * the DNS master file format. If this option is set, then the
+ * ISC_LEXOPT_INITIALWS and ISC_LEXOPT_EOL options will be ignored when
+ * the paren count is > 0. To use this option, '(' and ')' must be special
+ * characters.
+ */
+#define ISC_LEXOPT_DNSMULTILINE 0x20 /*%< Handle '(' and ')'. */
+#define ISC_LEXOPT_NOMORE 0x40 /*%< Want "no more" token. */
+
+#define ISC_LEXOPT_CNUMBER 0x80 /*%< Recognize octal and hex. */
+#define ISC_LEXOPT_ESCAPE 0x100 /*%< Recognize escapes. */
+#define ISC_LEXOPT_QSTRINGMULTILINE 0x200 /*%< Allow multiline "" strings */
+#define ISC_LEXOPT_OCTAL 0x400 /*%< Expect a octal number. */
+/*@}*/
+/*@{*/
+/*!
+ * Various commenting styles, which may be changed at any time with
+ * isc_lex_setcomments().
+ */
+
+#define ISC_LEXCOMMENT_C 0x01
+#define ISC_LEXCOMMENT_CPLUSPLUS 0x02
+#define ISC_LEXCOMMENT_SHELL 0x04
+#define ISC_LEXCOMMENT_DNSMASTERFILE 0x08
+/*@}*/
+
+/***
+ *** Types
+ ***/
+
+/*! Lex */
+
+typedef char isc_lexspecials_t[256];
+
+/* Tokens */
+
+typedef enum {
+ isc_tokentype_unknown = 0,
+ isc_tokentype_string = 1,
+ isc_tokentype_number = 2,
+ isc_tokentype_qstring = 3,
+ isc_tokentype_eol = 4,
+ isc_tokentype_eof = 5,
+ isc_tokentype_initialws = 6,
+ isc_tokentype_special = 7,
+ isc_tokentype_nomore = 8
+} isc_tokentype_t;
+
+typedef union {
+ char as_char;
+ unsigned long as_ulong;
+ isc_region_t as_region;
+ isc_textregion_t as_textregion;
+ void * as_pointer;
+} isc_tokenvalue_t;
+
+typedef struct isc_token {
+ isc_tokentype_t type;
+ isc_tokenvalue_t value;
+} isc_token_t;
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp);
+/*%<
+ * Create a lexer.
+ *
+ * 'max_token' is a hint of the number of bytes in the largest token.
+ *
+ * Requires:
+ *\li '*lexp' is a valid lexer.
+ *
+ *\li max_token > 0.
+ *
+ * Ensures:
+ *\li On success, *lexp is attached to the newly created lexer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+isc_lex_destroy(isc_lex_t **lexp);
+/*%<
+ * Destroy the lexer.
+ *
+ * Requires:
+ *\li '*lexp' is a valid lexer.
+ *
+ * Ensures:
+ *\li *lexp == NULL
+ */
+
+unsigned int
+isc_lex_getcomments(isc_lex_t *lex);
+/*%<
+ * Return the current lexer commenting styles.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ * Returns:
+ *\li The commenting sytles which are currently allowed.
+ */
+
+void
+isc_lex_setcomments(isc_lex_t *lex, unsigned int comments);
+/*%<
+ * Set allowed lexer commenting styles.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'comments' has meaningful values.
+ */
+
+void
+isc_lex_getspecials(isc_lex_t *lex, isc_lexspecials_t specials);
+/*%<
+ * Put the current list of specials into 'specials'.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ */
+
+void
+isc_lex_setspecials(isc_lex_t *lex, isc_lexspecials_t specials);
+/*!<
+ * The characters in 'specials' are returned as tokens. Along with
+ * whitespace, they delimit strings and numbers.
+ *
+ * Note:
+ *\li Comment processing takes precedence over special character
+ * recognition.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ */
+
+isc_result_t
+isc_lex_openfile(isc_lex_t *lex, const char *filename);
+/*%<
+ * Open 'filename' and make it the current input source for 'lex'.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li filename is a valid C string.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY Out of memory
+ *\li #ISC_R_NOTFOUND File not found
+ *\li #ISC_R_NOPERM No permission to open file
+ *\li #ISC_R_FAILURE Couldn't open file, not sure why
+ *\li #ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_lex_openstream(isc_lex_t *lex, FILE *stream);
+/*%<
+ * Make 'stream' the current input source for 'lex'.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'stream' is a valid C stream.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY Out of memory
+ */
+
+isc_result_t
+isc_lex_openbuffer(isc_lex_t *lex, isc_buffer_t *buffer);
+/*%<
+ * Make 'buffer' the current input source for 'lex'.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'buffer' is a valid buffer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY Out of memory
+ */
+
+isc_result_t
+isc_lex_close(isc_lex_t *lex);
+/*%<
+ * Close the most recently opened object (i.e. file or buffer).
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMORE No more input sources
+ */
+
+isc_result_t
+isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp);
+/*%<
+ * Get the next token.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'lex' has an input source.
+ *
+ *\li 'options' contains valid options.
+ *
+ *\li '*tokenp' is a valid pointer.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_UNEXPECTEDEND
+ *\li #ISC_R_NOMEMORY
+ *
+ * These two results are returned only if their corresponding lexer
+ * options are not set.
+ *
+ *\li #ISC_R_EOF End of input source
+ *\li #ISC_R_NOMORE No more input sources
+ */
+
+isc_result_t
+isc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token,
+ isc_tokentype_t expect, isc_boolean_t eol);
+/*%<
+ * Get the next token from a DNS master file type stream. This is a
+ * convenience function that sets appropriate options and handles quoted
+ * strings and end of line correctly for master files. It also ungets
+ * unexpected tokens.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'token' is a valid pointer
+ *
+ * Returns:
+ *
+ * \li any return code from isc_lex_gettoken().
+ */
+
+isc_result_t
+isc_lex_getoctaltoken(isc_lex_t *lex, isc_token_t *token, isc_boolean_t eol);
+/*%<
+ * Get the next token from a DNS master file type stream. This is a
+ * convenience function that sets appropriate options and handles end
+ * of line correctly for master files. It also ungets unexpected tokens.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'token' is a valid pointer
+ *
+ * Returns:
+ *
+ * \li any return code from isc_lex_gettoken().
+ */
+
+void
+isc_lex_ungettoken(isc_lex_t *lex, isc_token_t *tokenp);
+/*%<
+ * Unget the current token.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'lex' has an input source.
+ *
+ *\li 'tokenp' points to a valid token.
+ *
+ *\li There is no ungotten token already.
+ */
+
+void
+isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r);
+/*%<
+ * Returns a region containing the text of the last token returned.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ *\li 'lex' has an input source.
+ *
+ *\li 'tokenp' points to a valid token.
+ *
+ *\li A token has been gotten and not ungotten.
+ */
+
+char *
+isc_lex_getsourcename(isc_lex_t *lex);
+/*%<
+ * Return the input source name.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ * Returns:
+ * \li source name or NULL if no current source.
+ *\li result valid while current input source exists.
+ */
+
+
+unsigned long
+isc_lex_getsourceline(isc_lex_t *lex);
+/*%<
+ * Return the input source line number.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ * Returns:
+ *\li Current line number or 0 if no current source.
+ */
+
+isc_result_t
+isc_lex_setsourcename(isc_lex_t *lex, const char *name);
+/*%<
+ * Assigns a new name to the input source.
+ *
+ * Requires:
+ *
+ * \li 'lex' is a valid lexer.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ * \li #ISC_R_NOTFOUND - there are no sources.
+ */
+
+isc_boolean_t
+isc_lex_isfile(isc_lex_t *lex);
+/*%<
+ * Return whether the current input source is a file.
+ *
+ * Requires:
+ *\li 'lex' is a valid lexer.
+ *
+ * Returns:
+ * \li #ISC_TRUE if the current input is a file,
+ *\li #ISC_FALSE otherwise.
+ */
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LEX_H */
diff --git a/lib/isc/include/isc/lfsr.h b/lib/isc/include/isc/lfsr.h
new file mode 100644
index 0000000..d4d9707
--- /dev/null
+++ b/lib/isc/include/isc/lfsr.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: lfsr.h,v 1.17 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_LFSR_H
+#define ISC_LFSR_H 1
+
+/*! \file isc/lfsr.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+typedef struct isc_lfsr isc_lfsr_t;
+
+/*%
+ * This function is called when reseeding is needed. It is allowed to
+ * modify any state in the LFSR in any way it sees fit OTHER THAN "bits".
+ *
+ * It MUST set "count" to a new value or the lfsr will never reseed again.
+ *
+ * Also, a reseed will never occur in the middle of an extraction. This
+ * is purely an optimization, and is probably what one would want.
+ */
+typedef void (*isc_lfsrreseed_t)(isc_lfsr_t *, void *);
+
+/*%
+ * The members of this structure can be used by the application, but care
+ * needs to be taken to not change state once the lfsr is in operation.
+ */
+struct isc_lfsr {
+ isc_uint32_t state; /*%< previous state */
+ unsigned int bits; /*%< length */
+ isc_uint32_t tap; /*%< bit taps */
+ unsigned int count; /*%< reseed count (in BITS!) */
+ isc_lfsrreseed_t reseed; /*%< reseed function */
+ void *arg; /*%< reseed function argument */
+};
+
+ISC_LANG_BEGINDECLS
+
+
+void
+isc_lfsr_init(isc_lfsr_t *lfsr, isc_uint32_t state, unsigned int bits,
+ isc_uint32_t tap, unsigned int count,
+ isc_lfsrreseed_t reseed, void *arg);
+/*%<
+ * Initialize an LFSR.
+ *
+ * Note:
+ *
+ *\li Putting untrusted values into this function will cause the LFSR to
+ * generate (perhaps) non-maximal length sequences.
+ *
+ * Requires:
+ *
+ *\li lfsr != NULL
+ *
+ *\li 8 <= bits <= 32
+ *
+ *\li tap != 0
+ */
+
+void
+isc_lfsr_generate(isc_lfsr_t *lfsr, void *data, unsigned int count);
+/*%<
+ * Returns "count" bytes of data from the LFSR.
+ *
+ * Requires:
+ *
+ *\li lfsr be valid.
+ *
+ *\li data != NULL.
+ *
+ *\li count > 0.
+ */
+
+void
+isc_lfsr_skip(isc_lfsr_t *lfsr, unsigned int skip);
+/*%<
+ * Skip "skip" states.
+ *
+ * Requires:
+ *
+ *\li lfsr be valid.
+ */
+
+isc_uint32_t
+isc_lfsr_generate32(isc_lfsr_t *lfsr1, isc_lfsr_t *lfsr2);
+/*%<
+ * Given two LFSRs, use the current state from each to skip entries in the
+ * other. The next states are then xor'd together and returned.
+ *
+ * WARNING:
+ *
+ *\li This function is used only for very, very low security data, such
+ * as DNS message IDs where it is desired to have an unpredictable
+ * stream of bytes that are harder to predict than a simple flooding
+ * attack.
+ *
+ * Notes:
+ *
+ *\li Since the current state from each of the LFSRs is used to skip
+ * state in the other, it is important that no state be leaked
+ * from either LFSR.
+ *
+ * Requires:
+ *
+ *\li lfsr1 and lfsr2 be valid.
+ *
+ *\li 1 <= skipbits <= 31
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LFSR_H */
diff --git a/lib/isc/include/isc/lib.h b/lib/isc/include/isc/lib.h
new file mode 100644
index 0000000..765cdfa
--- /dev/null
+++ b/lib/isc/include/isc/lib.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: lib.h,v 1.14 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_LIB_H
+#define ISC_LIB_H 1
+
+/*! \file isc/lib.h */
+
+#include <isc/types.h>
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+LIBISC_EXTERNAL_DATA extern isc_msgcat_t *isc_msgcat;
+
+void
+isc_lib_initmsgcat(void);
+/*!<
+ * \brief Initialize the ISC library's message catalog, isc_msgcat, if it
+ * has not already been initialized.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LIB_H */
diff --git a/lib/isc/include/isc/list.h b/lib/isc/include/isc/list.h
new file mode 100644
index 0000000..9338275
--- /dev/null
+++ b/lib/isc/include/isc/list.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-2002 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: list.h,v 1.24 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_LIST_H
+#define ISC_LIST_H 1
+#include <isc/boolean.h>
+#include <isc/assertions.h>
+
+#ifdef ISC_LIST_CHECKINIT
+#define ISC_LINK_INSIST(x) ISC_INSIST(x)
+#else
+#define ISC_LINK_INSIST(x)
+#endif
+
+#define ISC_LIST(type) struct { type *head, *tail; }
+#define ISC_LIST_INIT(list) \
+ do { (list).head = NULL; (list).tail = NULL; } while (0)
+
+#define ISC_LINK(type) struct { type *prev, *next; }
+#define ISC_LINK_INIT_TYPE(elt, link, type) \
+ do { \
+ (elt)->link.prev = (type *)(-1); \
+ (elt)->link.next = (type *)(-1); \
+ } while (0)
+#define ISC_LINK_INIT(elt, link) \
+ ISC_LINK_INIT_TYPE(elt, link, void)
+#define ISC_LINK_LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1))
+
+#define ISC_LIST_HEAD(list) ((list).head)
+#define ISC_LIST_TAIL(list) ((list).tail)
+#define ISC_LIST_EMPTY(list) ISC_TF((list).head == NULL)
+
+#define __ISC_LIST_PREPENDUNSAFE(list, elt, link) \
+ do { \
+ if ((list).head != NULL) \
+ (list).head->link.prev = (elt); \
+ else \
+ (list).tail = (elt); \
+ (elt)->link.prev = NULL; \
+ (elt)->link.next = (list).head; \
+ (list).head = (elt); \
+ } while (0)
+
+#define ISC_LIST_PREPEND(list, elt, link) \
+ do { \
+ ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+ __ISC_LIST_PREPENDUNSAFE(list, elt, link); \
+ } while (0)
+
+#define ISC_LIST_INITANDPREPEND(list, elt, link) \
+ __ISC_LIST_PREPENDUNSAFE(list, elt, link)
+
+#define __ISC_LIST_APPENDUNSAFE(list, elt, link) \
+ do { \
+ if ((list).tail != NULL) \
+ (list).tail->link.next = (elt); \
+ else \
+ (list).head = (elt); \
+ (elt)->link.prev = (list).tail; \
+ (elt)->link.next = NULL; \
+ (list).tail = (elt); \
+ } while (0)
+
+#define ISC_LIST_APPEND(list, elt, link) \
+ do { \
+ ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+ __ISC_LIST_APPENDUNSAFE(list, elt, link); \
+ } while (0)
+
+#define ISC_LIST_INITANDAPPEND(list, elt, link) \
+ __ISC_LIST_APPENDUNSAFE(list, elt, link)
+
+#define __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type) \
+ do { \
+ if ((elt)->link.next != NULL) \
+ (elt)->link.next->link.prev = (elt)->link.prev; \
+ else { \
+ ISC_INSIST((list).tail == (elt)); \
+ (list).tail = (elt)->link.prev; \
+ } \
+ if ((elt)->link.prev != NULL) \
+ (elt)->link.prev->link.next = (elt)->link.next; \
+ else { \
+ ISC_INSIST((list).head == (elt)); \
+ (list).head = (elt)->link.next; \
+ } \
+ (elt)->link.prev = (type *)(-1); \
+ (elt)->link.next = (type *)(-1); \
+ } while (0)
+
+#define __ISC_LIST_UNLINKUNSAFE(list, elt, link) \
+ __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
+
+#define ISC_LIST_UNLINK_TYPE(list, elt, link, type) \
+ do { \
+ ISC_LINK_INSIST(ISC_LINK_LINKED(elt, link)); \
+ __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type); \
+ } while (0)
+#define ISC_LIST_UNLINK(list, elt, link) \
+ ISC_LIST_UNLINK_TYPE(list, elt, link, void)
+
+#define ISC_LIST_PREV(elt, link) ((elt)->link.prev)
+#define ISC_LIST_NEXT(elt, link) ((elt)->link.next)
+
+#define __ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link) \
+ do { \
+ if ((before)->link.prev == NULL) \
+ ISC_LIST_PREPEND(list, elt, link); \
+ else { \
+ (elt)->link.prev = (before)->link.prev; \
+ (before)->link.prev = (elt); \
+ (elt)->link.prev->link.next = (elt); \
+ (elt)->link.next = (before); \
+ } \
+ } while (0)
+
+#define ISC_LIST_INSERTBEFORE(list, before, elt, link) \
+ do { \
+ ISC_LINK_INSIST(ISC_LINK_LINKED(before, link)); \
+ ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+ __ISC_LIST_INSERTBEFOREUNSAFE(list, before, elt, link); \
+ } while (0)
+
+#define __ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link) \
+ do { \
+ if ((after)->link.next == NULL) \
+ ISC_LIST_APPEND(list, elt, link); \
+ else { \
+ (elt)->link.next = (after)->link.next; \
+ (after)->link.next = (elt); \
+ (elt)->link.next->link.prev = (elt); \
+ (elt)->link.prev = (after); \
+ } \
+ } while (0)
+
+#define ISC_LIST_INSERTAFTER(list, after, elt, link) \
+ do { \
+ ISC_LINK_INSIST(ISC_LINK_LINKED(after, link)); \
+ ISC_LINK_INSIST(!ISC_LINK_LINKED(elt, link)); \
+ __ISC_LIST_INSERTAFTERUNSAFE(list, after, elt, link); \
+ } while (0)
+
+#define ISC_LIST_APPENDLIST(list1, list2, link) \
+ do { \
+ if (ISC_LIST_EMPTY(list1)) \
+ (list1) = (list2); \
+ else if (!ISC_LIST_EMPTY(list2)) { \
+ (list1).tail->link.next = (list2).head; \
+ (list2).head->link.prev = (list1).tail; \
+ (list1).tail = (list2).tail; \
+ } \
+ (list2).head = NULL; \
+ (list2).tail = NULL; \
+ } while (0)
+
+#define ISC_LIST_ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link)
+#define __ISC_LIST_ENQUEUEUNSAFE(list, elt, link) \
+ __ISC_LIST_APPENDUNSAFE(list, elt, link)
+#define ISC_LIST_DEQUEUE(list, elt, link) \
+ ISC_LIST_UNLINK_TYPE(list, elt, link, void)
+#define ISC_LIST_DEQUEUE_TYPE(list, elt, link, type) \
+ ISC_LIST_UNLINK_TYPE(list, elt, link, type)
+#define __ISC_LIST_DEQUEUEUNSAFE(list, elt, link) \
+ __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, void)
+#define __ISC_LIST_DEQUEUEUNSAFE_TYPE(list, elt, link, type) \
+ __ISC_LIST_UNLINKUNSAFE_TYPE(list, elt, link, type)
+
+#endif /* ISC_LIST_H */
diff --git a/lib/isc/include/isc/log.h b/lib/isc/include/isc/log.h
new file mode 100644
index 0000000..deb6434
--- /dev/null
+++ b/lib/isc/include/isc/log.h
@@ -0,0 +1,913 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: log.h,v 1.54 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_LOG_H
+#define ISC_LOG_H 1
+
+/*! \file isc/log.h */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h> /* XXXDCL NT */
+
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+/*@{*/
+/*!
+ * \brief Severity levels, patterned after Unix's syslog levels.
+ *
+ */
+#define ISC_LOG_DEBUG(level) (level)
+/*!
+ * #ISC_LOG_DYNAMIC can only be used for defining channels with
+ * isc_log_createchannel(), not to specify a level in isc_log_write().
+ */
+#define ISC_LOG_DYNAMIC 0
+#define ISC_LOG_INFO (-1)
+#define ISC_LOG_NOTICE (-2)
+#define ISC_LOG_WARNING (-3)
+#define ISC_LOG_ERROR (-4)
+#define ISC_LOG_CRITICAL (-5)
+/*@}*/
+
+/*@{*/
+/*!
+ * \brief Destinations.
+ */
+#define ISC_LOG_TONULL 1
+#define ISC_LOG_TOSYSLOG 2
+#define ISC_LOG_TOFILE 3
+#define ISC_LOG_TOFILEDESC 4
+/*@}*/
+
+/*@{*/
+/*%
+ * Channel flags.
+ */
+#define ISC_LOG_PRINTTIME 0x0001
+#define ISC_LOG_PRINTLEVEL 0x0002
+#define ISC_LOG_PRINTCATEGORY 0x0004
+#define ISC_LOG_PRINTMODULE 0x0008
+#define ISC_LOG_PRINTTAG 0x0010
+#define ISC_LOG_PRINTALL 0x001F
+#define ISC_LOG_DEBUGONLY 0x1000
+#define ISC_LOG_OPENERR 0x8000 /* internal */
+/*@}*/
+
+/*@{*/
+/*!
+ * \brief Other options.
+ *
+ * XXXDCL INFINITE doesn't yet work. Arguably it isn't needed, but
+ * since I am intend to make large number of versions work efficiently,
+ * INFINITE is going to be trivial to add to that.
+ */
+#define ISC_LOG_ROLLINFINITE (-1)
+#define ISC_LOG_ROLLNEVER (-2)
+/*@}*/
+
+/*!
+ * \brief Used to name the categories used by a library.
+ *
+ * An array of isc_logcategory
+ * structures names each category, and the id value is initialized by calling
+ * isc_log_registercategories.
+ */
+struct isc_logcategory {
+ const char *name;
+ unsigned int id;
+};
+
+/*%
+ * Similar to isc_logcategory, but for all the modules a library defines.
+ */
+struct isc_logmodule {
+ const char *name;
+ unsigned int id;
+};
+
+/*%
+ * The isc_logfile structure is initialized as part of an isc_logdestination
+ * before calling isc_log_createchannel().
+ *
+ * When defining an #ISC_LOG_TOFILE
+ * channel the name, versions and maximum_size should be set before calling
+ * isc_log_createchannel(). To define an #ISC_LOG_TOFILEDESC channel set only
+ * the stream before the call.
+ *
+ * Setting maximum_size to zero implies no maximum.
+ */
+typedef struct isc_logfile {
+ FILE *stream; /*%< Initialized to NULL for #ISC_LOG_TOFILE. */
+ const char *name; /*%< NULL for #ISC_LOG_TOFILEDESC. */
+ int versions; /* >= 0, #ISC_LOG_ROLLNEVER, #ISC_LOG_ROLLINFINITE. */
+ /*%
+ * stdio's ftell is standardized to return a long, which may well not
+ * be big enough for the largest file supportable by the operating
+ * system (though it is _probably_ big enough for the largest log
+ * anyone would want). st_size returned by fstat should be typedef'd
+ * to a size large enough for the largest possible file on a system.
+ */
+ isc_offset_t maximum_size;
+ isc_boolean_t maximum_reached; /*%< Private. */
+} isc_logfile_t;
+
+/*%
+ * Passed to isc_log_createchannel to define the attributes of either
+ * a stdio or a syslog log.
+ */
+typedef union isc_logdestination {
+ isc_logfile_t file;
+ int facility; /* XXXDCL NT */
+} isc_logdestination_t;
+
+/*@{*/
+/*%
+ * The built-in categories of libisc.
+ *
+ * Each library registering categories should provide library_LOGCATEGORY_name
+ * definitions with indexes into its isc_logcategory structure corresponding to
+ * the order of the names.
+ */
+LIBISC_EXTERNAL_DATA extern isc_logcategory_t isc_categories[];
+LIBISC_EXTERNAL_DATA extern isc_log_t *isc_lctx;
+LIBISC_EXTERNAL_DATA extern isc_logmodule_t isc_modules[];
+/*@}*/
+
+/*@{*/
+/*%
+ * Do not log directly to DEFAULT. Use another category. When in doubt,
+ * use GENERAL.
+ */
+#define ISC_LOGCATEGORY_DEFAULT (&isc_categories[0])
+#define ISC_LOGCATEGORY_GENERAL (&isc_categories[1])
+/*@}*/
+
+#define ISC_LOGMODULE_SOCKET (&isc_modules[0])
+#define ISC_LOGMODULE_TIME (&isc_modules[1])
+#define ISC_LOGMODULE_INTERFACE (&isc_modules[2])
+#define ISC_LOGMODULE_TIMER (&isc_modules[3])
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp);
+/*%<
+ * Establish a new logging context, with default channels.
+ *
+ * Notes:
+ *\li isc_log_create() calls isc_logconfig_create(), so see its comment
+ * below for more information.
+ *
+ * Requires:
+ *\li mctx is a valid memory context.
+ *\li lctxp is not null and *lctxp is null.
+ *\li lcfgp is null or lcfgp is not null and *lcfgp is null.
+ *
+ * Ensures:
+ *\li *lctxp will point to a valid logging context if all of the necessary
+ * memory was allocated, or NULL otherwise.
+ *\li *lcfgp will point to a valid logging configuration if all of the
+ * necessary memory was allocated, or NULL otherwise.
+ *\li On failure, no additional memory is allocated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource limit: Out of memory
+ */
+
+isc_result_t
+isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp);
+/*%<
+ * Create the data structure that holds all of the configurable information
+ * about where messages are actually supposed to be sent -- the information
+ * that could changed based on some configuration file, as opposed to the
+ * the category/module specification of isc_log_[v]write[1] that is compiled
+ * into a program, or the debug_level which is dynamic state information.
+ *
+ * Notes:
+ *\li It is necessary to specify the logging context the configuration
+ * will be used with because the number of categories and modules
+ * needs to be known in order to set the configuration. However,
+ * the configuration is not used by the logging context until the
+ * isc_logconfig_use function is called.
+ *
+ *\li The memory context used for operations that allocate memory for
+ * the configuration is that of the logging context, as specified
+ * in the isc_log_create call.
+ *
+ *\li Four default channels are established:
+ *\verbatim
+ * default_syslog
+ * - log to syslog's daemon facility #ISC_LOG_INFO or higher
+ * default_stderr
+ * - log to stderr #ISC_LOG_INFO or higher
+ * default_debug
+ * - log to stderr #ISC_LOG_DEBUG dynamically
+ * null
+ * - log nothing
+ *\endverbatim
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *\li lcftp is not null and *lcfgp is null.
+ *
+ * Ensures:
+ *\li *lcfgp will point to a valid logging context if all of the necessary
+ * memory was allocated, or NULL otherwise.
+ *\li On failure, no additional memory is allocated.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource limit: Out of memory
+ */
+
+isc_logconfig_t *
+isc_logconfig_get(isc_log_t *lctx);
+/*%<
+ * Returns a pointer to the configuration currently in use by the log context.
+ *
+ * Requires:
+ *\li lctx is a valid context.
+ *
+ * Ensures:
+ *\li The configuration pointer is non-null.
+ *
+ * Returns:
+ *\li The configuration pointer.
+ */
+
+isc_result_t
+isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg);
+/*%<
+ * Associate a new configuration with a logging context.
+ *
+ * Notes:
+ *\li This is thread safe. The logging context will lock a mutex
+ * before attempting to swap in the new configuration, and isc_log_doit
+ * (the internal function used by all of isc_log_[v]write[1]) locks
+ * the same lock for the duration of its use of the configuration.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *\li lcfg is a valid logging configuration.
+ *\li lctx is the same configuration given to isc_logconfig_create
+ * when the configuration was created.
+ *
+ * Ensures:
+ *\li Future calls to isc_log_write will use the new configuration.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource limit: Out of memory
+ */
+
+void
+isc_log_destroy(isc_log_t **lctxp);
+/*%<
+ * Deallocate the memory associated with a logging context.
+ *
+ * Requires:
+ *\li *lctx is a valid logging context.
+ *
+ * Ensures:
+ *\li All of the memory associated with the logging context is returned
+ * to the free memory pool.
+ *
+ *\li Any open files are closed.
+ *
+ *\li The logging context is marked as invalid.
+ */
+
+void
+isc_logconfig_destroy(isc_logconfig_t **lcfgp);
+/*%<
+ * Destroy a logging configuration.
+ *
+ * Notes:
+ *\li This function cannot be used directly with the return value of
+ * isc_logconfig_get, because a logging context must always have
+ * a valid configuration associated with it.
+ *
+ * Requires:
+ *\li lcfgp is not null and *lcfgp is a valid logging configuration.
+ *\li The logging configuration is not in use by an existing logging context.
+ *
+ * Ensures:
+ *\li All memory allocated for the configuration is freed.
+ *
+ *\li The configuration is marked as invalid.
+ */
+
+void
+isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]);
+/*%<
+ * Identify logging categories a library will use.
+ *
+ * Notes:
+ *\li A category should only be registered once, but no mechanism enforces
+ * this rule.
+ *
+ *\li The end of the categories array is identified by a NULL name.
+ *
+ *\li Because the name is used by #ISC_LOG_PRINTCATEGORY, it should not
+ * be altered or destroyed after isc_log_registercategories().
+ *
+ *\li Because each element of the categories array is used by
+ * isc_log_categorybyname, it should not be altered or destroyed
+ * after registration.
+ *
+ *\li The value of the id integer in each structure is overwritten
+ * by this function, and so id need not be initialized to any particular
+ * value prior to the function call.
+ *
+ *\li A subsequent call to isc_log_registercategories with the same
+ * logging context (but new categories) will cause the last
+ * element of the categories array from the prior call to have
+ * its "name" member changed from NULL to point to the new
+ * categories array, and its "id" member set to UINT_MAX.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *\li categories != NULL.
+ *\li categories[0].name != NULL.
+ *
+ * Ensures:
+ * \li There are references to each category in the logging context,
+ * so they can be used with isc_log_usechannel() and isc_log_write().
+ */
+
+void
+isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]);
+/*%<
+ * Identify logging categories a library will use.
+ *
+ * Notes:
+ *\li A module should only be registered once, but no mechanism enforces
+ * this rule.
+ *
+ *\li The end of the modules array is identified by a NULL name.
+ *
+ *\li Because the name is used by #ISC_LOG_PRINTMODULE, it should not
+ * be altered or destroyed after isc_log_registermodules().
+ *
+ *\li Because each element of the modules array is used by
+ * isc_log_modulebyname, it should not be altered or destroyed
+ * after registration.
+ *
+ *\li The value of the id integer in each structure is overwritten
+ * by this function, and so id need not be initialized to any particular
+ * value prior to the function call.
+ *
+ *\li A subsequent call to isc_log_registermodules with the same
+ * logging context (but new modules) will cause the last
+ * element of the modules array from the prior call to have
+ * its "name" member changed from NULL to point to the new
+ * modules array, and its "id" member set to UINT_MAX.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *\li modules != NULL.
+ *\li modules[0].name != NULL;
+ *
+ * Ensures:
+ *\li Each module has a reference in the logging context, so they can be
+ * used with isc_log_usechannel() and isc_log_write().
+ */
+
+isc_result_t
+isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
+ unsigned int type, int level,
+ const isc_logdestination_t *destination,
+ unsigned int flags);
+/*%<
+ * Specify the parameters of a logging channel.
+ *
+ * Notes:
+ *\li The name argument is copied to memory in the logging context, so
+ * it can be altered or destroyed after isc_log_createchannel().
+ *
+ *\li Defining a very large number of channels will have a performance
+ * impact on isc_log_usechannel(), since the names are searched
+ * linearly until a match is made. This same issue does not affect
+ * isc_log_write, however.
+ *
+ *\li Channel names can be redefined; this is primarily useful for programs
+ * that want their own definition of default_syslog, default_debug
+ * and default_stderr.
+ *
+ *\li Any channel that is redefined will not affect logging that was
+ * already directed to its original definition, _except_ for the
+ * default_stderr channel. This case is handled specially so that
+ * the default logging category can be changed by redefining
+ * default_stderr. (XXXDCL Though now that I think of it, the default
+ * logging category can be changed with only one additional function
+ * call by defining a new channel and then calling isc_log_usechannel()
+ * for #ISC_LOGCATEGORY_DEFAULT.)
+ *
+ *\li Specifying #ISC_LOG_PRINTTIME or #ISC_LOG_PRINTTAG for syslog is allowed,
+ * but probably not what you wanted to do.
+ *
+ * #ISC_LOG_DEBUGONLY will mark the channel as usable only when the
+ * debug level of the logging context (see isc_log_setdebuglevel)
+ * is non-zero.
+ *
+ * Requires:
+ *\li lcfg is a valid logging configuration.
+ *
+ *\li name is not NULL.
+ *
+ *\li type is #ISC_LOG_TOSYSLOG, #ISC_LOG_TOFILE, #ISC_LOG_TOFILEDESC or
+ * #ISC_LOG_TONULL.
+ *
+ *\li destination is not NULL unless type is #ISC_LOG_TONULL.
+ *
+ *\li level is >= #ISC_LOG_CRITICAL (the most negative logging level).
+ *
+ *\li flags does not include any bits aside from the ISC_LOG_PRINT* bits
+ * or #ISC_LOG_DEBUGONLY.
+ *
+ * Ensures:
+ *\li #ISC_R_SUCCESS
+ * A channel with the given name is usable with
+ * isc_log_usechannel().
+ *
+ *\li #ISC_R_NOMEMORY or #ISC_R_UNEXPECTED
+ * No additional memory is being used by the logging context.
+ * Any channel that previously existed with the given name
+ * is not redefined.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource limit: Out of memory
+ *\li #ISC_R_UNEXPECTED type was out of range and REQUIRE()
+ * was disabled.
+ */
+
+isc_result_t
+isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
+ const isc_logcategory_t *category,
+ const isc_logmodule_t *module);
+/*%<
+ * Associate a named logging channel with a category and module that
+ * will use it.
+ *
+ * Notes:
+ *\li The name is searched for linearly in the set of known channel names
+ * until a match is found. (Note the performance impact of a very large
+ * number of named channels.) When multiple channels of the same
+ * name are defined, the most recent definition is found.
+ *
+ *\li Specifing a very large number of channels for a category will have
+ * a moderate impact on performance in isc_log_write(), as each
+ * call looks up the category for the start of a linked list, which
+ * it follows all the way to the end to find matching modules. The
+ * test for matching modules is integral, though.
+ *
+ *\li If category is NULL, then the channel is associated with the indicated
+ * module for all known categories (including the "default" category).
+ *
+ *\li If module is NULL, then the channel is associated with every module
+ * that uses that category.
+ *
+ *\li Passing both category and module as NULL would make every log message
+ * use the indicated channel.
+ *
+ * \li Specifying a channel that is #ISC_LOG_TONULL for a category/module pair
+ * has no effect on any other channels associated with that pair,
+ * regardless of ordering. Thus you cannot use it to "mask out" one
+ * category/module pair when you have specified some other channel that
+ * is also used by that category/module pair.
+ *
+ * Requires:
+ *\li lcfg is a valid logging configuration.
+ *
+ *\li category is NULL or has an id that is in the range of known ids.
+ *
+ * module is NULL or has an id that is in the range of known ids.
+ *
+ * Ensures:
+ *\li #ISC_R_SUCCESS
+ * The channel will be used by the indicated category/module
+ * arguments.
+ *
+ *\li #ISC_R_NOMEMORY
+ * If assignment for a specific category has been requested,
+ * the channel has not been associated with the indicated
+ * category/module arguments and no additional memory is
+ * used by the logging context.
+ * If assignment for all categories has been requested
+ * then _some_ may have succeeded (starting with category
+ * "default" and progressing through the order of categories
+ * passed to isc_log_registercategories()) and additional memory
+ * is being used by whatever assignments succeeded.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource limit: Out of memory
+ */
+
+/* Attention: next four comments PRECEED code */
+/*!
+ * \brief
+ * Write a message to the log channels.
+ *
+ * Notes:
+ *\li Log messages containing natural language text should be logged with
+ * isc_log_iwrite() to allow for localization.
+ *
+ *\li lctx can be NULL; this is allowed so that programs which use
+ * libraries that use the ISC logging system are not required to
+ * also use it.
+ *
+ *\li The format argument is a printf(3) string, with additional arguments
+ * as necessary.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ *\li The category and module arguments must have ids that are in the
+ * range of known ids, as estabished by isc_log_registercategories()
+ * and isc_log_registermodules().
+ *
+ *\li level != #ISC_LOG_DYNAMIC. ISC_LOG_DYNAMIC is used only to define
+ * channels, and explicit debugging level must be identified for
+ * isc_log_write() via ISC_LOG_DEBUG(level).
+ *
+ *\li format != NULL.
+ *
+ * Ensures:
+ *\li The log message is written to every channel associated with the
+ * indicated category/module pair.
+ *
+ * Returns:
+ *\li Nothing. Failure to log a message is not construed as a
+ * meaningful error.
+ */
+void
+isc_log_write(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ const char *format, ...)
+
+ISC_FORMAT_PRINTF(5, 6);
+
+/*%
+ * Write a message to the log channels.
+ *
+ * Notes:
+ *\li lctx can be NULL; this is allowed so that programs which use
+ * libraries that use the ISC logging system are not required to
+ * also use it.
+ *
+ *\li The format argument is a printf(3) string, with additional arguments
+ * as necessary.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ *\li The category and module arguments must have ids that are in the
+ * range of known ids, as estabished by isc_log_registercategories()
+ * and isc_log_registermodules().
+ *
+ *\li level != #ISC_LOG_DYNAMIC. ISC_LOG_DYNAMIC is used only to define
+ * channels, and explicit debugging level must be identified for
+ * isc_log_write() via ISC_LOG_DEBUG(level).
+ *
+ *\li format != NULL.
+ *
+ * Ensures:
+ *\li The log message is written to every channel associated with the
+ * indicated category/module pair.
+ *
+ * Returns:
+ *\li Nothing. Failure to log a message is not construed as a
+ * meaningful error.
+ */
+void
+isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ const char *format, va_list args)
+
+ISC_FORMAT_PRINTF(5, 0);
+
+/*%
+ * Write a message to the log channels, pruning duplicates that occur within
+ * a configurable amount of seconds (see isc_log_[sg]etduplicateinterval).
+ * This function is otherwise identical to isc_log_write().
+ */
+void
+isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *format, ...)
+
+ISC_FORMAT_PRINTF(5, 6);
+
+/*%
+ * Write a message to the log channels, pruning duplicates that occur within
+ * a configurable amount of seconds (see isc_log_[sg]etduplicateinterval).
+ * This function is otherwise identical to isc_log_vwrite().
+ */
+void
+isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *format,
+ va_list args)
+
+ISC_FORMAT_PRINTF(5, 0);
+
+/*%
+ * These are four internationalized versions of the the isc_log_[v]write[1]
+ * functions.
+ *
+ * The only difference is that they take arguments for a message
+ * catalog, message set, and message number, all immediately preceding the
+ * format argument. The format argument becomes the default text, a la
+ * isc_msgcat_get. If the message catalog is NULL, no lookup is attempted
+ * for a message -- which makes the message set and message number irrelevant,
+ * and the non-internationalized call should have probably been used instead.
+ *
+ * Yes, that means there are now *eight* interfaces to logging a message.
+ * Sheesh. Make the madness stop!
+ */
+/*@{*/
+void
+isc_log_iwrite(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int message,
+ const char *format, ...)
+ISC_FORMAT_PRINTF(8, 9);
+
+void
+isc_log_ivwrite(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int message,
+ const char *format, va_list args)
+ISC_FORMAT_PRINTF(8, 0);
+
+void
+isc_log_iwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int message,
+ const char *format, ...)
+ISC_FORMAT_PRINTF(8, 9);
+
+void
+isc_log_ivwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int message,
+ const char *format, va_list args)
+ISC_FORMAT_PRINTF(8, 0);
+/*@}*/
+
+void
+isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level);
+/*%<
+ * Set the debugging level used for logging.
+ *
+ * Notes:
+ *\li Setting the debugging level to 0 disables debugging log messages.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ * Ensures:
+ *\li The debugging level is set to the requested value.
+ */
+
+unsigned int
+isc_log_getdebuglevel(isc_log_t *lctx);
+/*%<
+ * Get the current debugging level.
+ *
+ * Notes:
+ *\li This is provided so that a program can have a notion of
+ * "increment debugging level" or "decrement debugging level"
+ * without needing to keep track of what the current level is.
+ *
+ *\li A return value of 0 indicates that debugging messages are disabled.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ * Ensures:
+ *\li The current logging debugging level is returned.
+ */
+
+isc_boolean_t
+isc_log_wouldlog(isc_log_t *lctx, int level);
+/*%<
+ * Determine whether logging something to 'lctx' at 'level' would
+ * actually cause something to be logged somewhere.
+ *
+ * If #ISC_FALSE is returned, it is guaranteed that nothing would
+ * be logged, allowing the caller to omit unnecessary
+ * isc_log_write() calls and possible message preformatting.
+ */
+
+void
+isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval);
+/*%<
+ * Set the interval over which duplicate log messages will be ignored
+ * by isc_log_[v]write1(), in seconds.
+ *
+ * Notes:
+ *\li Increasing the duplicate interval from X to Y will not necessarily
+ * filter out duplicates of messages logged in Y - X seconds since the
+ * increase. (Example: Message1 is logged at midnight. Message2
+ * is logged at 00:01:00, when the interval is only 30 seconds, causing
+ * Message1 to be expired from the log message history. Then the interval
+ * is increased to 3000 (five minutes) and at 00:04:00 Message1 is logged
+ * again. It will appear the second time even though less than five
+ * passed since the first occurrence.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ */
+
+unsigned int
+isc_log_getduplicateinterval(isc_logconfig_t *lcfg);
+/*%<
+ * Get the current duplicate filtering interval.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ * Returns:
+ *\li The current duplicate filtering interval.
+ */
+
+isc_result_t
+isc_log_settag(isc_logconfig_t *lcfg, const char *tag);
+/*%<
+ * Set the program name or other identifier for #ISC_LOG_PRINTTAG.
+ *
+ * Requires:
+ *\li lcfg is a valid logging configuration.
+ *
+ * Notes:
+ *\li If this function has not set the tag to a non-NULL, non-empty value,
+ * then the #ISC_LOG_PRINTTAG channel flag will not print anything.
+ * Unlike some implementations of syslog on Unix systems, you *must* set
+ * the tag in order to get it logged. It is not implicitly derived from
+ * the program name (which is pretty impossible to infer portably).
+ *
+ *\li Setting the tag to NULL or the empty string will also cause the
+ * #ISC_LOG_PRINTTAG channel flag to not print anything. If tag equals the
+ * empty string, calls to isc_log_gettag will return NULL.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success
+ *\li #ISC_R_NOMEMORY Resource Limit: Out of memory
+ *
+ * XXXDCL when creating a new isc_logconfig_t, it might be nice if the tag
+ * of the currently active isc_logconfig_t was inherited. this does not
+ * currently happen.
+ */
+
+char *
+isc_log_gettag(isc_logconfig_t *lcfg);
+/*%<
+ * Get the current identifier printed with #ISC_LOG_PRINTTAG.
+ *
+ * Requires:
+ *\li lcfg is a valid logging configuration.
+ *
+ * Notes:
+ *\li Since isc_log_settag() will not associate a zero-length string
+ * with the logging configuration, attempts to do so will cause
+ * this function to return NULL. However, a determined programmer
+ * will observe that (currently) a tag of length greater than zero
+ * could be set, and then modified to be zero length.
+ *
+ * Returns:
+ *\li A pointer to the current identifier, or NULL if none has been set.
+ */
+
+void
+isc_log_opensyslog(const char *tag, int options, int facility);
+/*%<
+ * Initialize syslog logging.
+ *
+ * Notes:
+ *\li XXXDCL NT
+ * This is currently equivalent to openlog(), but is not going to remain
+ * that way. In the meantime, the arguments are all identical to
+ * those used by openlog(3), as follows:
+ *
+ * \code
+ * tag: The string to use in the position of the program
+ * name in syslog messages. Most (all?) syslogs
+ * will use basename(argv[0]) if tag is NULL.
+ *
+ * options: LOG_CONS, LOG_PID, LOG_NDELAY ... whatever your
+ * syslog supports.
+ *
+ * facility: The default syslog facility. This is irrelevant
+ * since isc_log_write will ALWAYS use the channel's
+ * declared facility.
+ * \endcode
+ *
+ *\li Zero effort has been made (yet) to accomodate systems with openlog()
+ * that only takes two arguments, or to identify valid syslog
+ * facilities or options for any given architecture.
+ *
+ *\li It is necessary to call isc_log_opensyslog() to initialize
+ * syslogging on machines which do not support network connections to
+ * syslogd because they require a Unix domain socket to be used. Since
+ * this is a chore to determine at run-time, it is suggested that it
+ * always be called by programs using the ISC logging system.
+ *
+ * Requires:
+ *\li Nothing.
+ *
+ * Ensures:
+ *\li openlog() is called to initialize the syslog system.
+ */
+
+void
+isc_log_closefilelogs(isc_log_t *lctx);
+/*%<
+ * Close all open files used by #ISC_LOG_TOFILE channels.
+ *
+ * Notes:
+ *\li This function is provided for programs that want to use their own
+ * log rolling mechanism rather than the one provided internally.
+ * For example, a program that wanted to keep daily logs would define
+ * a channel which used #ISC_LOG_ROLLNEVER, then once a day would
+ * rename the log file and call isc_log_closefilelogs().
+ *
+ *\li #ISC_LOG_TOFILEDESC channels are unaffected.
+ *
+ * Requires:
+ *\li lctx is a valid context.
+ *
+ * Ensures:
+ *\li The open files are closed and will be reopened when they are
+ * next needed.
+ */
+
+isc_logcategory_t *
+isc_log_categorybyname(isc_log_t *lctx, const char *name);
+/*%<
+ * Find a category by its name.
+ *
+ * Notes:
+ *\li The string name of a category is not required to be unique.
+ *
+ * Requires:
+ *\li lctx is a valid context.
+ *\li name is not NULL.
+ *
+ * Returns:
+ *\li A pointer to the _first_ isc_logcategory_t structure used by "name".
+ *
+ *\li NULL if no category exists by that name.
+ */
+
+isc_logmodule_t *
+isc_log_modulebyname(isc_log_t *lctx, const char *name);
+/*%<
+ * Find a module by its name.
+ *
+ * Notes:
+ *\li The string name of a module is not required to be unique.
+ *
+ * Requires:
+ *\li lctx is a valid context.
+ *\li name is not NULL.
+ *
+ * Returns:
+ *\li A pointer to the _first_ isc_logmodule_t structure used by "name".
+ *
+ *\li NULL if no module exists by that name.
+ */
+
+void
+isc_log_setcontext(isc_log_t *lctx);
+/*%<
+ * Sets the context used by the libisc for logging.
+ *
+ * Requires:
+ *\li lctx be a valid context.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_LOG_H */
diff --git a/lib/isc/include/isc/magic.h b/lib/isc/include/isc/magic.h
new file mode 100644
index 0000000..073de90
--- /dev/null
+++ b/lib/isc/include/isc/magic.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: magic.h,v 1.18 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_MAGIC_H
+#define ISC_MAGIC_H 1
+
+/*! \file isc/magic.h */
+
+typedef struct {
+ unsigned int magic;
+} isc__magic_t;
+
+
+/*%
+ * To use this macro the magic number MUST be the first thing in the
+ * structure, and MUST be of type "unsigned int".
+ * The intent of this is to allow magic numbers to be checked even though
+ * the object is otherwise opaque.
+ */
+#define ISC_MAGIC_VALID(a,b) (((a) != NULL) && \
+ (((const isc__magic_t *)(a))->magic == (b)))
+
+#define ISC_MAGIC(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
+
+#endif /* ISC_MAGIC_H */
diff --git a/lib/isc/include/isc/md5.h b/lib/isc/include/isc/md5.h
new file mode 100644
index 0000000..5b0d785
--- /dev/null
+++ b/lib/isc/include/isc/md5.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2004-2007 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: md5.h,v 1.16 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file isc/md5.h
+ * \brief This is the header file for the MD5 message-digest algorithm.
+ *
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h'
+ * header definitions; now uses stuff from dpkg's config.h
+ * - Ian Jackson <ijackson@nyx.cs.du.edu>.
+ * Still in the public domain.
+ */
+
+#ifndef ISC_MD5_H
+#define ISC_MD5_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#define ISC_MD5_DIGESTLENGTH 16U
+
+typedef struct {
+ isc_uint32_t buf[4];
+ isc_uint32_t bytes[2];
+ isc_uint32_t in[16];
+} isc_md5_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_md5_init(isc_md5_t *ctx);
+
+void
+isc_md5_invalidate(isc_md5_t *ctx);
+
+void
+isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len);
+
+void
+isc_md5_final(isc_md5_t *ctx, unsigned char *digest);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MD5_H */
diff --git a/lib/isc/include/isc/mem.h b/lib/isc/include/isc/mem.h
new file mode 100644
index 0000000..2d41d04
--- /dev/null
+++ b/lib/isc/include/isc/mem.h
@@ -0,0 +1,626 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-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: mem.h,v 1.78 2008/03/31 05:00:30 marka Exp $ */
+
+#ifndef ISC_MEM_H
+#define ISC_MEM_H 1
+
+/*! \file isc/mem.h */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+#include <isc/xml.h>
+
+ISC_LANG_BEGINDECLS
+
+#define ISC_MEM_LOWATER 0
+#define ISC_MEM_HIWATER 1
+typedef void (*isc_mem_water_t)(void *, int);
+
+typedef void * (*isc_memalloc_t)(void *, size_t);
+typedef void (*isc_memfree_t)(void *, void *);
+
+/*%
+ * Define ISC_MEM_DEBUG=1 to make all functions that free memory
+ * set the pointer being freed to NULL after being freed.
+ * This is the default; set ISC_MEM_DEBUG=0 to disable it.
+ */
+#ifndef ISC_MEM_DEBUG
+#define ISC_MEM_DEBUG 1
+#endif
+
+/*%
+ * Define ISC_MEM_TRACKLINES=1 to turn on detailed tracing of memory
+ * allocation and freeing by file and line number.
+ */
+#ifndef ISC_MEM_TRACKLINES
+#define ISC_MEM_TRACKLINES 1
+#endif
+
+/*%
+ * Define ISC_MEM_CHECKOVERRUN=1 to turn on checks for using memory outside
+ * the requested space. This will increase the size of each allocation.
+ */
+#ifndef ISC_MEM_CHECKOVERRUN
+#define ISC_MEM_CHECKOVERRUN 1
+#endif
+
+/*%
+ * Define ISC_MEM_FILL=1 to fill each block of memory returned to the system
+ * with the byte string '0xbe'. This helps track down uninitialized pointers
+ * and the like. On freeing memory, the space is filled with '0xde' for
+ * the same reasons.
+ */
+#ifndef ISC_MEM_FILL
+#define ISC_MEM_FILL 1
+#endif
+
+/*%
+ * Define ISC_MEMPOOL_NAMES=1 to make memory pools store a symbolic
+ * name so that the leaking pool can be more readily identified in
+ * case of a memory leak.
+ */
+#ifndef ISC_MEMPOOL_NAMES
+#define ISC_MEMPOOL_NAMES 1
+#endif
+
+LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
+/*@{*/
+#define ISC_MEM_DEBUGTRACE 0x00000001U
+#define ISC_MEM_DEBUGRECORD 0x00000002U
+#define ISC_MEM_DEBUGUSAGE 0x00000004U
+#define ISC_MEM_DEBUGSIZE 0x00000008U
+#define ISC_MEM_DEBUGCTX 0x00000010U
+#define ISC_MEM_DEBUGALL 0x0000001FU
+/*!<
+ * The variable isc_mem_debugging holds a set of flags for
+ * turning certain memory debugging options on or off at
+ * runtime. Its is intialized to the value ISC_MEM_DEGBUGGING,
+ * which is 0 by default but may be overridden at compile time.
+ * The following flags can be specified:
+ *
+ * \li #ISC_MEM_DEBUGTRACE
+ * Log each allocation and free to isc_lctx.
+ *
+ * \li #ISC_MEM_DEBUGRECORD
+ * Remember each allocation, and match them up on free.
+ * Crash if a free doesn't match an allocation.
+ *
+ * \li #ISC_MEM_DEBUGUSAGE
+ * If a hi_water mark is set, print the maximium inuse memory
+ * every time it is raised once it exceeds the hi_water mark.
+ *
+ * \li #ISC_MEM_DEBUGSIZE
+ * Check the size argument being passed to isc_mem_put() matches
+ * that passed to isc_mem_get().
+ *
+ * \li #ISC_MEM_DEBUGCTX
+ * Check the mctx argument being passed to isc_mem_put() matches
+ * that passed to isc_mem_get().
+ */
+/*@}*/
+
+#if ISC_MEM_TRACKLINES
+#define _ISC_MEM_FILELINE , __FILE__, __LINE__
+#define _ISC_MEM_FLARG , const char *, int
+#else
+#define _ISC_MEM_FILELINE
+#define _ISC_MEM_FLARG
+#endif
+
+/*!
+ * Define ISC_MEM_USE_INTERNAL_MALLOC=1 to use the internal malloc()
+ * implementation in preference to the system one. The internal malloc()
+ * is very space-efficient, and quite fast on uniprocessor systems. It
+ * performs poorly on multiprocessor machines.
+ * JT: we can overcome the performance issue on multiprocessor machines
+ * by carefully separating memory contexts.
+ */
+
+#ifndef ISC_MEM_USE_INTERNAL_MALLOC
+#define ISC_MEM_USE_INTERNAL_MALLOC 1
+#endif
+
+/*
+ * Flags for isc_mem_create2()calls.
+ */
+#define ISC_MEMFLAG_NOLOCK 0x00000001 /* no lock is necessary */
+#define ISC_MEMFLAG_INTERNAL 0x00000002 /* use internal malloc */
+#if ISC_MEM_USE_INTERNAL_MALLOC
+#define ISC_MEMFLAG_DEFAULT ISC_MEMFLAG_INTERNAL
+#else
+#define ISC_MEMFLAG_DEFAULT 0
+#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_strdup(c, p) isc__mem_strdup((c), (p) _ISC_MEM_FILELINE)
+#define isc_mempool_get(c) isc__mempool_get((c) _ISC_MEM_FILELINE)
+
+/*%
+ * isc_mem_putanddetach() is a convienence function for use where you
+ * have a structure with an attached memory context.
+ *
+ * Given:
+ *
+ * \code
+ * struct {
+ * ...
+ * isc_mem_t *mctx;
+ * ...
+ * } *ptr;
+ *
+ * isc_mem_t *mctx;
+ *
+ * isc_mem_putanddetach(&ptr->mctx, ptr, sizeof(*ptr));
+ * \endcode
+ *
+ * is the equivalent of:
+ *
+ * \code
+ * mctx = NULL;
+ * isc_mem_attach(ptr->mctx, &mctx);
+ * isc_mem_detach(&ptr->mctx);
+ * isc_mem_put(mctx, ptr, sizeof(*ptr));
+ * isc_mem_detach(&mctx);
+ * \endcode
+ */
+
+#if ISC_MEM_DEBUG
+#define isc_mem_put(c, p, s) \
+ do { \
+ isc__mem_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); \
+ (p) = NULL; \
+ } while (0)
+#define isc_mem_free(c, p) \
+ do { \
+ isc__mem_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); \
+ (p) = NULL; \
+ } while (0)
+#else
+#define isc_mem_put(c, p, s) isc__mem_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)
+#endif
+
+/*@{*/
+isc_result_t
+isc_mem_create(size_t max_size, size_t target_size,
+ isc_mem_t **mctxp);
+
+isc_result_t
+isc_mem_create2(size_t max_size, size_t target_size,
+ isc_mem_t **mctxp, unsigned int flags);
+
+isc_result_t
+isc_mem_createx(size_t max_size, size_t target_size,
+ isc_memalloc_t memalloc, isc_memfree_t memfree,
+ void *arg, isc_mem_t **mctxp);
+
+isc_result_t
+isc_mem_createx2(size_t max_size, size_t target_size,
+ isc_memalloc_t memalloc, isc_memfree_t memfree,
+ void *arg, isc_mem_t **mctxp, unsigned int flags);
+
+/*!<
+ * \brief Create a memory context.
+ *
+ * 'max_size' and 'target_size' are tuning parameters. When
+ * ISC_MEMFLAG_INTERNAL is set, allocations smaller than 'max_size'
+ * will be satisfied by getting blocks of size 'target_size' from the
+ * system allocator and breaking them up into pieces; larger allocations
+ * will use the system allocator directly. If 'max_size' and/or
+ * 'target_size' are zero, default values will be * used. When
+ * ISC_MEMFLAG_INTERNAL is not set, 'target_size' is ignored.
+ *
+ * 'max_size' is also used to size the statistics arrays and the array
+ * used to record active memory when ISC_MEM_DEBUGRECORD is set. Settin
+ * 'max_size' too low can have detrimental effects on performance.
+ *
+ * A memory context created using isc_mem_createx() will obtain
+ * memory from the system by calling 'memalloc' and 'memfree',
+ * passing them the argument 'arg'. A memory context created
+ * using isc_mem_create() will use the standard library malloc()
+ * and free().
+ *
+ * If ISC_MEMFLAG_NOLOCK is set in 'flags', the corresponding memory context
+ * will be accessed without locking. The user who creates the context must
+ * ensure there be no race. Since this can be a source of bug, it is generally
+ * inadvisable to use this flag unless the user is very sure about the race
+ * condition and the access to the object is highly performance sensitive.
+ *
+ * Requires:
+ * mctxp != NULL && *mctxp == NULL */
+/*@}*/
+
+/*@{*/
+void
+isc_mem_attach(isc_mem_t *, isc_mem_t **);
+void
+isc_mem_detach(isc_mem_t **);
+/*!<
+ * \brief Attach to / detach from a memory context.
+ *
+ * This is intended for applications that use multiple memory contexts
+ * in such a way that it is not obvious when the last allocations from
+ * a given context has been freed and destroying the context is safe.
+ *
+ * Most applications do not need to call these functions as they can
+ * simply create a single memory context at the beginning of main()
+ * and destroy it at the end of main(), thereby guaranteeing that it
+ * is not destroyed while there are outstanding allocations.
+ */
+/*@}*/
+
+void
+isc_mem_destroy(isc_mem_t **);
+/*%<
+ * Destroy a memory context.
+ */
+
+isc_result_t
+isc_mem_ondestroy(isc_mem_t *ctx,
+ isc_task_t *task,
+ isc_event_t **event);
+/*%<
+ * Request to be notified with an event when a memory context has
+ * been successfully destroyed.
+ */
+
+void
+isc_mem_stats(isc_mem_t *mctx, FILE *out);
+/*%<
+ * Print memory usage statistics for 'mctx' on the stream 'out'.
+ */
+
+void
+isc_mem_setdestroycheck(isc_mem_t *mctx,
+ isc_boolean_t on);
+/*%<
+ * If 'on' is ISC_TRUE, 'mctx' will check for memory leaks when
+ * destroyed and abort the program if any are present.
+ */
+
+/*@{*/
+void
+isc_mem_setquota(isc_mem_t *, size_t);
+size_t
+isc_mem_getquota(isc_mem_t *);
+/*%<
+ * Set/get the memory quota of 'mctx'. This is a hard limit
+ * on the amount of memory that may be allocated from mctx;
+ * if it is exceeded, allocations will fail.
+ */
+/*@}*/
+
+size_t
+isc_mem_inuse(isc_mem_t *mctx);
+/*%<
+ * Get an estimate of the number of memory in use in 'mctx', in bytes.
+ * This includes quantization overhead, but does not include memory
+ * allocated from the system but not yet used.
+ */
+
+void
+isc_mem_setwater(isc_mem_t *mctx, isc_mem_water_t water, void *water_arg,
+ size_t hiwater, size_t lowater);
+/*%<
+ * Set high and low water marks for this memory context.
+ *
+ * When the memory usage of 'mctx' exceeds 'hiwater',
+ * '(water)(water_arg, #ISC_MEM_HIWATER)' will be called. 'water' needs to
+ * call isc_mem_waterack() with #ISC_MEM_HIWATER to acknowlege the state
+ * change. 'water' may be called multiple times.
+ *
+ * When the usage drops below 'lowater', 'water' will again be called, this
+ * time with #ISC_MEM_LOWATER. 'water' need to calls isc_mem_waterack() with
+ * #ISC_MEM_LOWATER to acknowlege the change.
+ *
+ * static void
+ * water(void *arg, int mark) {
+ * struct foo *foo = arg;
+ *
+ * LOCK(&foo->marklock);
+ * if (foo->mark != mark) {
+ * foo->mark = mark;
+ * ....
+ * isc_mem_waterack(foo->mctx, mark);
+ * }
+ * UNLOCK(&foo->marklock);
+ * }
+ *
+ * If 'water' is NULL then 'water_arg', 'hi_water' and 'lo_water' are
+ * ignored and the state is reset.
+ *
+ * Requires:
+ *
+ * 'water' is not NULL.
+ * hi_water >= lo_water
+ */
+
+void
+isc_mem_waterack(isc_mem_t *ctx, int mark);
+/*%<
+ * Called to acknowledge changes in signalled by calls to 'water'.
+ */
+
+void
+isc_mem_printactive(isc_mem_t *mctx, FILE *file);
+/*%<
+ * Print to 'file' all active memory in 'mctx'.
+ *
+ * Requires ISC_MEM_DEBUGRECORD to have been set.
+ */
+
+void
+isc_mem_printallactive(FILE *file);
+/*%<
+ * Print to 'file' all active memory in all contexts.
+ *
+ * Requires ISC_MEM_DEBUGRECORD to have been set.
+ */
+
+void
+isc_mem_checkdestroyed(FILE *file);
+/*%<
+ * Check that all memory contexts have been destroyed.
+ * Prints out those that have not been.
+ * Fatally fails if there are still active contexts.
+ */
+
+unsigned int
+isc_mem_references(isc_mem_t *ctx);
+/*%<
+ * Return the current reference count.
+ */
+
+void
+isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag);
+/*%<
+ * Name 'ctx'.
+ *
+ * Notes:
+ *
+ *\li Only the first 15 characters of 'name' will be copied.
+ *
+ *\li 'tag' is for debugging purposes only.
+ *
+ * Requires:
+ *
+ *\li 'ctx' is a valid ctx.
+ */
+
+const char *
+isc_mem_getname(isc_mem_t *ctx);
+/*%<
+ * Get the name of 'ctx', as previously set using isc_mem_setname().
+ *
+ * Requires:
+ *\li 'ctx' is a valid ctx.
+ *
+ * Returns:
+ *\li A non-NULL pointer to a null-terminated string.
+ * If the ctx has not been named, the string is
+ * empty.
+ */
+
+void *
+isc_mem_gettag(isc_mem_t *ctx);
+/*%<
+ * Get the tag value for 'task', as previously set using isc_mem_setname().
+ *
+ * Requires:
+ *\li 'ctx' is a valid ctx.
+ *
+ * Notes:
+ *\li This function is for debugging purposes only.
+ *
+ * Requires:
+ *\li 'ctx' is a valid task.
+ */
+
+#ifdef HAVE_LIBXML2
+void
+isc_mem_renderxml(xmlTextWriterPtr writer);
+/*%<
+ * Render all contexts' statistics and status in XML for writer.
+ */
+#endif /* HAVE_LIBXML2 */
+
+/*
+ * Memory pools
+ */
+
+isc_result_t
+isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
+/*%<
+ * Create a memory pool.
+ *
+ * Requires:
+ *\li mctx is a valid memory context.
+ *\li size > 0
+ *\li mpctxp != NULL and *mpctxp == NULL
+ *
+ * Defaults:
+ *\li maxalloc = UINT_MAX
+ *\li freemax = 1
+ *\li fillcount = 1
+ *
+ * Returns:
+ *\li #ISC_R_NOMEMORY -- not enough memory to create pool
+ *\li #ISC_R_SUCCESS -- all is well.
+ */
+
+void
+isc_mempool_destroy(isc_mempool_t **mpctxp);
+/*%<
+ * Destroy a memory pool.
+ *
+ * Requires:
+ *\li mpctxp != NULL && *mpctxp is a valid pool.
+ *\li The pool has no un"put" allocations outstanding
+ */
+
+void
+isc_mempool_setname(isc_mempool_t *mpctx, const char *name);
+/*%<
+ * Associate a name with a memory pool. At most 15 characters may be used.
+ *
+ * Requires:
+ *\li mpctx is a valid pool.
+ *\li name != NULL;
+ */
+
+void
+isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock);
+/*%<
+ * Associate a lock with this memory pool.
+ *
+ * This lock is used when getting or putting items using this memory pool,
+ * and it is also used to set or get internal state via the isc_mempool_get*()
+ * and isc_mempool_set*() set of functions.
+ *
+ * Mutiple pools can each share a single lock. For instance, if "manager"
+ * type object contained pools for various sizes of events, and each of
+ * these pools used a common lock. Note that this lock must NEVER be used
+ * by other than mempool routines once it is given to a pool, since that can
+ * easily cause double locking.
+ *
+ * Requires:
+ *
+ *\li mpctpx is a valid pool.
+ *
+ *\li lock != NULL.
+ *
+ *\li No previous lock is assigned to this pool.
+ *
+ *\li The lock is initialized before calling this function via the normal
+ * means of doing that.
+ */
+
+/*
+ * The following functions get/set various parameters. Note that due to
+ * the unlocked nature of pools these are potentially random values unless
+ * the imposed externally provided locking protocols are followed.
+ *
+ * Also note that the quota limits will not always take immediate effect.
+ * For instance, setting "maxalloc" to a number smaller than the currently
+ * allocated count is permitted. New allocations will be refused until
+ * the count drops below this threshold.
+ *
+ * All functions require (in addition to other requirements):
+ * mpctx is a valid memory pool
+ */
+
+unsigned int
+isc_mempool_getfreemax(isc_mempool_t *mpctx);
+/*%<
+ * Returns the maximum allowed size of the free list.
+ */
+
+void
+isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit);
+/*%<
+ * Sets the maximum allowed size of the free list.
+ */
+
+unsigned int
+isc_mempool_getfreecount(isc_mempool_t *mpctx);
+/*%<
+ * Returns current size of the free list.
+ */
+
+unsigned int
+isc_mempool_getmaxalloc(isc_mempool_t *mpctx);
+/*!<
+ * Returns the maximum allowed number of allocations.
+ */
+
+void
+isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit);
+/*%<
+ * Sets the maximum allowed number of allocations.
+ *
+ * Additional requirements:
+ *\li limit > 0
+ */
+
+unsigned int
+isc_mempool_getallocated(isc_mempool_t *mpctx);
+/*%<
+ * Returns the number of items allocated from this pool.
+ */
+
+unsigned int
+isc_mempool_getfillcount(isc_mempool_t *mpctx);
+/*%<
+ * Returns the number of items allocated as a block from the parent memory
+ * context when the free list is empty.
+ */
+
+void
+isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
+/*%<
+ * Sets the fillcount.
+ *
+ * Additional requirements:
+ *\li limit > 0
+ */
+
+
+/*
+ * Pseudo-private functions for use via macros. Do not call directly.
+ */
+void *
+isc__mem_get(isc_mem_t *, size_t _ISC_MEM_FLARG);
+void
+isc__mem_putanddetach(isc_mem_t **, void *,
+ size_t _ISC_MEM_FLARG);
+void
+isc__mem_put(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
+void *
+isc__mem_allocate(isc_mem_t *, size_t _ISC_MEM_FLARG);
+void
+isc__mem_free(isc_mem_t *, void * _ISC_MEM_FLARG);
+char *
+isc__mem_strdup(isc_mem_t *, const char *_ISC_MEM_FLARG);
+void *
+isc__mempool_get(isc_mempool_t * _ISC_MEM_FLARG);
+void
+isc__mempool_put(isc_mempool_t *, void * _ISC_MEM_FLARG);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MEM_H */
diff --git a/lib/isc/include/isc/msgcat.h b/lib/isc/include/isc/msgcat.h
new file mode 100644
index 0000000..fe3d336
--- /dev/null
+++ b/lib/isc/include/isc/msgcat.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: msgcat.h,v 1.13 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_MSGCAT_H
+#define ISC_MSGCAT_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/msgcat.h
+ * \brief The ISC Message Catalog
+ * aids internationalization of applications by allowing
+ * messages to be retrieved from locale-specific files instead of
+ * hardwiring them into the application. This allows translations of
+ * messages appropriate to the locale to be supplied without recompiling
+ * the application.
+ *
+ * Notes:
+ *\li It's very important that message catalogs work, even if only the
+ * default_text can be used.
+ *
+ * MP:
+ *\li The caller must ensure appropriate synchronization of
+ * isc_msgcat_open() and isc_msgcat_close(). isc_msgcat_get()
+ * ensures appropriate synchronization.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/*****
+ ***** Imports
+ *****/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Methods
+ *****/
+
+void
+isc_msgcat_open(const char *name, isc_msgcat_t **msgcatp);
+/*%<
+ * Open a message catalog.
+ *
+ * Notes:
+ *
+ *\li If memory cannot be allocated or other failures occur, *msgcatp
+ * will be set to NULL. If a NULL msgcat is given to isc_msgcat_get(),
+ * the default_text will be returned, ensuring that some message text
+ * will be available, no matter what's going wrong.
+ *
+ * Requires:
+ *
+ *\li 'name' is a valid string.
+ *
+ *\li msgcatp != NULL && *msgcatp == NULL
+ */
+
+void
+isc_msgcat_close(isc_msgcat_t **msgcatp);
+/*%<
+ * Close a message catalog.
+ *
+ * Notes:
+ *
+ *\li Any string pointers returned by prior calls to isc_msgcat_get() are
+ * invalid after isc_msgcat_close() has been called and must not be
+ * used.
+ *
+ * Requires:
+ *
+ *\li *msgcatp is a valid message catalog or is NULL.
+ *
+ * Ensures:
+ *
+ *\li All resources associated with the message catalog are released.
+ *
+ *\li *msgcatp == NULL
+ */
+
+const char *
+isc_msgcat_get(isc_msgcat_t *msgcat, int set, int message,
+ const char *default_text);
+/*%<
+ * Get message 'message' from message set 'set' in 'msgcat'. If it
+ * is not available, use 'default_text'.
+ *
+ * Requires:
+ *
+ *\li 'msgcat' is a valid message catalog or is NULL.
+ *
+ *\li set > 0
+ *
+ *\li message > 0
+ *
+ *\li 'default_text' is a valid string.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MSGCAT_H */
diff --git a/lib/isc/include/isc/msgs.h b/lib/isc/include/isc/msgs.h
new file mode 100644
index 0000000..d8f2787
--- /dev/null
+++ b/lib/isc/include/isc/msgs.h
@@ -0,0 +1,194 @@
+/*
+ * 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
+ * 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: msgs.h,v 1.17 2008/08/08 06:28:59 tbox Exp $ */
+
+#ifndef ISC_MSGS_H
+#define ISC_MSGS_H 1
+
+/*! \file isc/msgs.h */
+
+#include <isc/lib.h> /* Provide isc_msgcat global variable. */
+#include <isc/msgcat.h> /* Provide isc_msgcat_*() functions. */
+
+/*@{*/
+/*!
+ * \brief Message sets, named per source file, excepting "GENERAL".
+ *
+ * IMPORTANT: The original list is alphabetical, but any new sets must
+ * be added to the end.
+ */
+#define ISC_MSGSET_GENERAL 1
+/* ISC_RESULT_RESULTSET 2 */ /* XXX */
+/* ISC_RESULT_UNAVAILABLESET 3 */ /* XXX */
+#define ISC_MSGSET_APP 4
+#define ISC_MSGSET_COMMANDLINE 5
+#define ISC_MSGSET_ENTROPY 6
+#define ISC_MSGSET_IFITERIOCTL 7
+#define ISC_MSGSET_IFITERSYSCTL 8
+#define ISC_MSGSET_LEX 9
+#define ISC_MSGSET_LOG 10
+#define ISC_MSGSET_MEM 11
+#define ISC_MSGSET_NETADDR 12
+#define ISC_MSGSET_PRINT 13
+#define ISC_MSGSET_RESULT 14
+#define ISC_MSGSET_RWLOCK 15
+#define ISC_MSGSET_SOCKADDR 16
+#define ISC_MSGSET_SOCKET 17
+#define ISC_MSGSET_TASK 18
+#define ISC_MSGSET_TIMER 19
+#define ISC_MSGSET_UTIL 20
+#define ISC_MSGSET_IFITERGETIFADDRS 21
+/*@}*/
+
+/*@{*/
+/*!
+ * Message numbers
+ * are only required to be unique per message set,
+ * but are unique throughout the entire catalog to not be as confusing when
+ * debugging.
+ *
+ * The initial numbering was done by multiply by 100 the set number the
+ * message appears in then adding the incremental message number.
+ */
+#define ISC_MSG_FAILED 101 /*%< "failed" */
+#define ISC_MSG_SUCCEEDED 102 /*%< Compatible with "failed" */
+#define ISC_MSG_SUCCESS 103 /*%< More usual way to say "success" */
+#define ISC_MSG_STARTING 104 /*%< As in "daemon: starting" */
+#define ISC_MSG_STOPING 105 /*%< As in "daemon: stopping" */
+#define ISC_MSG_ENTERING 106 /*%< As in "some_subr: entering" */
+#define ISC_MSG_EXITING 107 /*%< As in "some_subr: exiting" */
+#define ISC_MSG_CALLING 108 /*%< As in "calling some_subr()" */
+#define ISC_MSG_RETURNED 109 /*%< As in "some_subr: returned <foo>" */
+#define ISC_MSG_FATALERROR 110 /*%< "fatal error" */
+#define ISC_MSG_SHUTTINGDOWN 111 /*%< "shutting down" */
+#define ISC_MSG_RUNNING 112 /*%< "running" */
+#define ISC_MSG_WAIT 113 /*%< "wait" */
+#define ISC_MSG_WAITUNTIL 114 /*%< "waituntil" */
+
+#define ISC_MSG_SIGNALSETUP 201 /*%< "handle_signal() %d setup: %s" */
+
+#define ISC_MSG_ILLEGALOPT 301 /*%< "illegal option" */
+#define ISC_MSG_OPTNEEDARG 302 /*%< "option requires an argument" */
+
+#define ISC_MSG_ENTROPYSTATS 401 /*%< "Entropy pool %p: refcnt %u ..." */
+
+#define ISC_MSG_MAKESCANSOCKET 501 /*%< "making interface scan socket: %s" */
+#define ISC_MSG_GETIFCONFIG 502 /*%< "get interface configuration: %s" */
+#define ISC_MSG_BUFFERMAX 503 /*%< "... maximum buffer size exceeded" */
+#define ISC_MSG_GETDESTADDR 504 /*%< "%s: getting destination address: %s" */
+#define ISC_MSG_GETNETMASK 505 /*%< "%s: getting netmask: %s" */
+
+#define ISC_MSG_GETIFLISTSIZE 601 /*%< "getting interface list size: ..." */
+#define ISC_MSG_GETIFLIST 602 /*%< "getting interface list: ..." */
+#define ISC_MSG_UNEXPECTEDTYPE 603 /*%< "... unexpected ... message type" */
+
+#define ISC_MSG_UNEXPECTEDSTATE 701 /*%< "Unexpected state %d" */
+
+#define ISC_MSG_BADTIME 801 /*%< "Bad 00 99:99:99.999 " */
+#define ISC_MSG_LEVEL 802 /*%< "level %d: " */
+
+#define ISC_MSG_ADDTRACE 901 /*%< "add %p size %u " */
+#define ISC_MSG_DELTRACE 902 /*%< "del %p size %u " */
+#define ISC_MSG_POOLSTATS 903 /*%< "[Pool statistics]\n" */
+#define ISC_MSG_POOLNAME 904 /*%< "name" */
+#define ISC_MSG_POOLSIZE 905 /*%< "size" */
+#define ISC_MSG_POOLMAXALLOC 906 /*%< "maxalloc" */
+#define ISC_MSG_POOLALLOCATED 907 /*%< "allocated" */
+#define ISC_MSG_POOLFREECOUNT 908 /*%< "freecount" */
+#define ISC_MSG_POOLFREEMAX 909 /*%< "freemax" */
+#define ISC_MSG_POOLFILLCOUNT 910 /*%< "fillcount" */
+#define ISC_MSG_POOLGETS 911 /*%< "gets" */
+#define ISC_MSG_DUMPALLOC 912 /*%< "DUMP OF ALL OUTSTANDING MEMORY ..." */
+#define ISC_MSG_NONE 913 /*%< "\tNone.\n" */
+#define ISC_MSG_PTRFILELINE 914 /*%< "\tptr %p file %s line %u\n" */
+
+#define ISC_MSG_UNKNOWNADDR 1001 /*%< "<unknown address, family %u>" */
+
+#define ISC_MSG_NOLONGDBL 1104 /*%< "long doubles are not supported" */
+
+#define ISC_MSG_PRINTLOCK 1201 /*%< "rwlock %p thread %lu ..." */
+#define ISC_MSG_READ 1202 /*%< "read" */
+#define ISC_MSG_WRITE 1203 /*%< "write" */
+#define ISC_MSG_READING 1204 /*%< "reading" */
+#define ISC_MSG_WRITING 1205 /*%< "writing" */
+#define ISC_MSG_PRELOCK 1206 /*%< "prelock" */
+#define ISC_MSG_POSTLOCK 1207 /*%< "postlock" */
+#define ISC_MSG_PREUNLOCK 1208 /*%< "preunlock" */
+#define ISC_MSG_POSTUNLOCK 1209 /*%< "postunlock" */
+
+#define ISC_MSG_UNKNOWNFAMILY 1301 /*%< "unknown address family: %d" */
+
+#define ISC_MSG_WRITEFAILED 1401 /*%< "write() failed during watcher ..." */
+#define ISC_MSG_READFAILED 1402 /*%< "read() failed during watcher ... " */
+#define ISC_MSG_PROCESSCMSG 1403 /*%< "processing cmsg %p" */
+#define ISC_MSG_IFRECEIVED 1404 /*%< "interface received on ifindex %u" */
+#define ISC_MSG_SENDTODATA 1405 /*%< "sendto pktinfo data, ifindex %u" */
+#define ISC_MSG_DOIORECV 1406 /*%< "doio_recv: recvmsg(%d) %d bytes ..." */
+#define ISC_MSG_PKTRECV 1407 /*%< "packet received correctly" */
+#define ISC_MSG_DESTROYING 1408 /*%< "destroying" */
+#define ISC_MSG_CREATED 1409 /*%< "created" */
+#define ISC_MSG_ACCEPTLOCK 1410 /*%< "internal_accept called, locked ..." */
+#define ISC_MSG_ACCEPTEDCXN 1411 /*%< "accepted connection, new socket %p" */
+#define ISC_MSG_INTERNALRECV 1412 /*%< "internal_recv: task %p got event %p" */
+#define ISC_MSG_INTERNALSEND 1413 /*%< "internal_send: task %p got event %p" */
+#define ISC_MSG_WATCHERMSG 1414 /*%< "watcher got message %d" */
+#define ISC_MSG_SOCKETSREMAIN 1415 /*%< "sockets exist" */
+#define ISC_MSG_PKTINFOPROVIDED 1416 /*%< "pktinfo structure provided, ..." */
+#define ISC_MSG_BOUND 1417 /*%< "bound" */
+#define ISC_MSG_ACCEPTRETURNED 1418 /*%< accept() returned %d/%s */
+#define ISC_MSG_TOOMANYFDS 1419 /*%< %s: too many open file descriptors */
+#define ISC_MSG_ZEROPORT 1420 /*%< dropping source port zero packet */
+#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_AWAKE 1502 /*%< "awake" */
+#define ISC_MSG_WORKING 1503 /*%< "working" */
+#define ISC_MSG_EXECUTE 1504 /*%< "execute action" */
+#define ISC_MSG_EMPTY 1505 /*%< "empty" */
+#define ISC_MSG_DONE 1506 /*%< "done" */
+#define ISC_MSG_QUANTUM 1507 /*%< "quantum" */
+
+#define ISC_MSG_SCHEDULE 1601 /*%< "schedule" */
+#define ISC_MSG_SIGNALSCHED 1602 /*%< "signal (schedule)" */
+#define ISC_MSG_SIGNALDESCHED 1603 /*%< "signal (deschedule)" */
+#define ISC_MSG_SIGNALDESTROY 1604 /*%< "signal (destroy)" */
+#define ISC_MSG_IDLERESCHED 1605 /*%< "idle reschedule" */
+#define ISC_MSG_EVENTNOTALLOC 1606 /*%< "couldn't allocate event" */
+#define ISC_MSG_SCHEDFAIL 1607 /*%< "couldn't schedule timer: %u" */
+#define ISC_MSG_POSTING 1608 /*%< "posting" */
+#define ISC_MSG_WAKEUP 1609 /*%< "wakeup" */
+
+#define ISC_MSG_LOCK 1701 /*%< "LOCK" */
+#define ISC_MSG_LOCKING 1702 /*%< "LOCKING" */
+#define ISC_MSG_LOCKED 1703 /*%< "LOCKED" */
+#define ISC_MSG_UNLOCKED 1704 /*%< "UNLOCKED" */
+#define ISC_MSG_RWLOCK 1705 /*%< "RWLOCK" */
+#define ISC_MSG_RWLOCKED 1706 /*%< "RWLOCKED" */
+#define ISC_MSG_RWUNLOCK 1707 /*%< "RWUNLOCK" */
+#define ISC_MSG_BROADCAST 1708 /*%< "BROADCAST" */
+#define ISC_MSG_SIGNAL 1709 /*%< "SIGNAL" */
+#define ISC_MSG_UTILWAIT 1710 /*%< "WAIT" */
+#define ISC_MSG_WAITED 1711 /*%< "WAITED" */
+
+#define ISC_MSG_GETIFADDRS 1801 /*%< "getting interface addresses: ..." */
+
+/*@}*/
+
+#endif /* ISC_MSGS_H */
diff --git a/lib/isc/include/isc/mutexblock.h b/lib/isc/include/isc/mutexblock.h
new file mode 100644
index 0000000..65bf2bf
--- /dev/null
+++ b/lib/isc/include/isc/mutexblock.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: mutexblock.h,v 1.17 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_MUTEXBLOCK_H
+#define ISC_MUTEXBLOCK_H 1
+
+/*! \file isc/mutexblock.h */
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_mutexblock_init(isc_mutex_t *block, unsigned int count);
+/*%<
+ * Initialize a block of locks. If an error occurs all initialized locks
+ * will be destroyed, if possible.
+ *
+ * Requires:
+ *
+ *\li block != NULL
+ *
+ *\li count > 0
+ *
+ * Returns:
+ *
+ *\li Any code isc_mutex_init() can return is a valid return for this
+ * function.
+ */
+
+isc_result_t
+isc_mutexblock_destroy(isc_mutex_t *block, unsigned int count);
+/*%<
+ * Destroy a block of locks.
+ *
+ * Requires:
+ *
+ *\li block != NULL
+ *
+ *\li count > 0
+ *
+ *\li Each lock in the block be initialized via isc_mutex_init() or
+ * the whole block was initialized via isc_mutex_initblock().
+ *
+ * Returns:
+ *
+ *\li Any code isc_mutex_init() can return is a valid return for this
+ * function.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_MUTEXBLOCK_H */
diff --git a/lib/isc/include/isc/netaddr.h b/lib/isc/include/isc/netaddr.h
new file mode 100644
index 0000000..ecd9f70
--- /dev/null
+++ b/lib/isc/include/isc/netaddr.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: netaddr.h,v 1.35 2007/06/18 23:47:44 tbox Exp $ */
+
+#ifndef ISC_NETADDR_H
+#define ISC_NETADDR_H 1
+
+/*! \file isc/netaddr.h */
+
+#include <isc/lang.h>
+#include <isc/net.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_HAVESYSUNH
+#include <sys/types.h>
+#include <sys/un.h>
+#endif
+
+ISC_LANG_BEGINDECLS
+
+struct isc_netaddr {
+ unsigned int family;
+ union {
+ struct in_addr in;
+ struct in6_addr in6;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ char un[sizeof(((struct sockaddr_un *)0)->sun_path)];
+#endif
+ } type;
+ isc_uint32_t zone;
+};
+
+isc_boolean_t
+isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b);
+
+/*%<
+ * Compare network addresses 'a' and 'b'. Return #ISC_TRUE if
+ * they are equal, #ISC_FALSE if not.
+ */
+
+isc_boolean_t
+isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
+ unsigned int prefixlen);
+/*%<
+ * Compare the 'prefixlen' most significant bits of the network
+ * addresses 'a' and 'b'. If 'b''s scope is zero then 'a''s scope is
+ * ignored. Return #ISC_TRUE if they are equal, #ISC_FALSE if not.
+ */
+
+isc_result_t
+isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp);
+/*%<
+ * Convert a netmask in 's' into a prefix length in '*lenp'.
+ * The mask should consist of zero or more '1' bits in the most
+ * most significant part of the address, followed by '0' bits.
+ * If this is not the case, #ISC_R_MASKNONCONTIG is returned.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_MASKNONCONTIG
+ */
+
+isc_result_t
+isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target);
+/*%<
+ * Append a text representation of 'sockaddr' to the buffer 'target'.
+ * The text is NOT null terminated. Handles IPv4 and IPv6 addresses.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOSPACE The text or the null termination did not fit.
+ *\li #ISC_R_FAILURE Unspecified failure
+ */
+
+void
+isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size);
+/*%<
+ * Format a human-readable representation of the network address '*na'
+ * into the character array 'array', which is of size 'size'.
+ * The resulting string is guaranteed to be null-terminated.
+ */
+
+#define ISC_NETADDR_FORMATSIZE \
+ sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX%SSSSSSSSSS")
+/*%<
+ * Minimum size of array to pass to isc_netaddr_format().
+ */
+
+void
+isc_netaddr_fromsockaddr(isc_netaddr_t *netaddr, const isc_sockaddr_t *source);
+
+void
+isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina);
+
+void
+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);
+
+void
+isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone);
+
+isc_uint32_t
+isc_netaddr_getzone(const isc_netaddr_t *netaddr);
+
+void
+isc_netaddr_any(isc_netaddr_t *netaddr);
+/*%<
+ * Return the IPv4 wildcard address.
+ */
+
+void
+isc_netaddr_any6(isc_netaddr_t *netaddr);
+/*%<
+ * Return the IPv6 wildcard address.
+ */
+
+isc_boolean_t
+isc_netaddr_ismulticast(isc_netaddr_t *na);
+/*%<
+ * Returns ISC_TRUE if the address is a multicast address.
+ */
+
+isc_boolean_t
+isc_netaddr_isexperimental(isc_netaddr_t *na);
+/*%<
+ * Returns ISC_TRUE if the address is a experimental (CLASS E) address.
+ */
+
+isc_boolean_t
+isc_netaddr_islinklocal(isc_netaddr_t *na);
+/*%<
+ * Returns #ISC_TRUE if the address is a link local address.
+ */
+
+isc_boolean_t
+isc_netaddr_issitelocal(isc_netaddr_t *na);
+/*%<
+ * Returns #ISC_TRUE if the address is a site local address.
+ */
+
+void
+isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s);
+/*%<
+ * Convert an IPv6 v4mapped address into an IPv4 address.
+ */
+
+isc_result_t
+isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen);
+/*
+ * Test whether the netaddr 'na' and 'prefixlen' are consistant.
+ * e.g. prefixlen within range.
+ * na does not have bits set which are not covered by the prefixlen.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_RANGE prefixlen out of range
+ * ISC_R_NOTIMPLENTED unsupported family
+ * ISC_R_FAILURE extra bits.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NETADDR_H */
diff --git a/lib/isc/include/isc/netscope.h b/lib/isc/include/isc/netscope.h
new file mode 100644
index 0000000..ba4e792
--- /dev/null
+++ b/lib/isc/include/isc/netscope.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: netscope.h,v 1.11 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_NETSCOPE_H
+#define ISC_NETSCOPE_H 1
+
+/*! \file isc/netscope.h */
+
+ISC_LANG_BEGINDECLS
+
+/*%
+ * Convert a string of an IPv6 scope zone to zone index. If the conversion
+ * succeeds, 'zoneid' will store the index value.
+ *
+ * XXXJT: when a standard interface for this purpose is defined,
+ * we should use it.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS: conversion succeeds
+ * \li ISC_R_FAILURE: conversion fails
+ */
+isc_result_t
+isc_netscope_pton(int af, char *scopename, void *addr, isc_uint32_t *zoneid);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NETADDR_H */
diff --git a/lib/isc/include/isc/ondestroy.h b/lib/isc/include/isc/ondestroy.h
new file mode 100644
index 0000000..64bd643
--- /dev/null
+++ b/lib/isc/include/isc/ondestroy.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2004-2007 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: ondestroy.h,v 1.14 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ONDESTROY_H
+#define ISC_ONDESTROY_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*! \file isc/ondestroy.h
+ * ondestroy handling.
+ *
+ * Any class ``X'' of objects that wants to send out notifications
+ * on its destruction should declare a field of type isc_ondestroy_t
+ * (call it 'ondest').
+ *
+ * \code
+ * typedef struct {
+ * ...
+ * isc_ondestroy_t ondest;
+ * ...
+ * } X;
+ * \endcode
+ *
+ * When an object ``A'' of type X is created
+ * it must initialize the field ondest with a call to
+ *
+ * \code
+ * isc_ondestroy_init(&A->ondest).
+ * \endcode
+ *
+ * X should also provide a registration function for third-party
+ * objects to call to register their interest in being told about
+ * the destruction of a particular instance of X.
+ *
+ * \code
+ * isc_result_t
+ * X_ondestroy(X *instance, isc_task_t *task,
+ * isc_event_t **eventp) {
+ * return(isc_ondestroy_register(&instance->ondest, task,eventp));
+ * }
+ * \endcode
+ *
+ * Note: locking of the ondestory structure embedded inside of X, is
+ * X's responsibility.
+ *
+ * When an instance of X is destroyed, a call to isc_ondestroy_notify()
+ * sends the notifications:
+ *
+ * \code
+ * X *instance;
+ * isc_ondestroy_t ondest = instance->ondest;
+ *
+ * ... completely cleanup 'instance' here...
+ *
+ * isc_ondestroy_notify(&ondest, instance);
+ * \endcode
+ *
+ *
+ * see lib/dns/zone.c for an ifdef'd-out example.
+ */
+
+struct isc_ondestroy {
+ unsigned int magic;
+ isc_eventlist_t events;
+};
+
+void
+isc_ondestroy_init(isc_ondestroy_t *ondest);
+/*%<
+ * Initialize the on ondest structure. *must* be called before first call
+ * to isc_ondestroy_register().
+ */
+
+isc_result_t
+isc_ondestroy_register(isc_ondestroy_t *ondest, isc_task_t *task,
+ isc_event_t **eventp);
+
+/*%<
+ * Stores task and *eventp away inside *ondest. Ownership of **event is
+ * taken from the caller (and *eventp is set to NULL). The task is attached
+ * to.
+ */
+
+void
+isc_ondestroy_notify(isc_ondestroy_t *ondest, void *sender);
+/*%<
+ * Dispatches the event(s) to the task(s) that were given in
+ * isc_ondestroy_register call(s) (done via calls to
+ * isc_task_sendanddetach()). Before dispatch, the sender value of each
+ * event structure is set to the value of the sender paramater. The
+ * internal structures of the ondest parameter are cleaned out, so no other
+ * cleanup is needed.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ONDESTROY_H */
diff --git a/lib/isc/include/isc/os.h b/lib/isc/include/isc/os.h
new file mode 100644
index 0000000..3cf59e2
--- /dev/null
+++ b/lib/isc/include/isc/os.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2007 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: os.h,v 1.12 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_OS_H
+#define ISC_OS_H 1
+
+/*! \file isc/os.h */
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+unsigned int
+isc_os_ncpus(void);
+/*%<
+ * Return the number of CPUs available on the system, or 1 if this cannot
+ * be determined.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_OS_H */
diff --git a/lib/isc/include/isc/parseint.h b/lib/isc/include/isc/parseint.h
new file mode 100644
index 0000000..5047676
--- /dev/null
+++ b/lib/isc/include/isc/parseint.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002 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: parseint.h,v 1.9 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_PARSEINT_H
+#define ISC_PARSEINT_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*! \file isc/parseint.h
+ * \brief Parse integers, in a saner way than atoi() or strtoul() do.
+ */
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_parse_uint32(isc_uint32_t *uip, const char *string, int base);
+
+isc_result_t
+isc_parse_uint16(isc_uint16_t *uip, const char *string, int base);
+
+isc_result_t
+isc_parse_uint8(isc_uint8_t *uip, const char *string, int base);
+/*%<
+ * Parse the null-terminated string 'string' containing a base 'base'
+ * integer, storing the result in '*uip'.
+ * The base is interpreted
+ * as in strtoul(). Unlike strtoul(), leading whitespace, minus or
+ * plus signs are not accepted, and all errors (including overflow)
+ * are reported uniformly through the return value.
+ *
+ * Requires:
+ *\li 'string' points to a null-terminated string
+ *\li 0 <= 'base' <= 36
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_BADNUMBER The string is not numeric (in the given base)
+ *\li #ISC_R_RANGE The number is not representable as the requested type.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_PARSEINT_H */
diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in
new file mode 100644
index 0000000..7943910
--- /dev/null
+++ b/lib/isc/include/isc/platform.h.in
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2004-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
+ * 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.48 2008/06/23 19:41:19 jinmei Exp $ */
+
+#ifndef ISC_PLATFORM_H
+#define ISC_PLATFORM_H 1
+
+/*! \file */
+
+/*****
+ ***** Platform-dependent defines.
+ *****/
+
+/***
+ *** Network.
+ ***/
+
+/*! \brief
+ * Define if this system needs the <netinet/in6.h> header file included
+ * for full IPv6 support (pretty much only UnixWare).
+ */
+@ISC_PLATFORM_NEEDNETINETIN6H@
+
+/*! \brief
+ * Define if this system needs the <netinet6/in6.h> header file included
+ * to support in6_pkinfo (pretty much only BSD/OS).
+ */
+@ISC_PLATFORM_NEEDNETINET6IN6H@
+
+/*! \brief
+ * If sockaddrs on this system have an sa_len field, ISC_PLATFORM_HAVESALEN
+ * will be defined.
+ */
+@ISC_PLATFORM_HAVESALEN@
+
+/*! \brief
+ * If this system has the IPv6 structure definitions, ISC_PLATFORM_HAVEIPV6
+ * will be defined.
+ */
+@ISC_PLATFORM_HAVEIPV6@
+
+/*! \brief
+ * If this system is missing in6addr_any, ISC_PLATFORM_NEEDIN6ADDRANY will
+ * be defined.
+ */
+@ISC_PLATFORM_NEEDIN6ADDRANY@
+
+/*! \brief
+ * If this system is missing in6addr_loopback, ISC_PLATFORM_NEEDIN6ADDRLOOPBACK
+ * will be defined.
+ */
+@ISC_PLATFORM_NEEDIN6ADDRLOOPBACK@
+
+/*! \brief
+ * If this system has in6_pktinfo, ISC_PLATFORM_HAVEIN6PKTINFO will be
+ * defined.
+ */
+@ISC_PLATFORM_HAVEIN6PKTINFO@
+
+/*! \brief
+ * If this system has in_addr6, rather than in6_addr, ISC_PLATFORM_HAVEINADDR6
+ * will be defined.
+ */
+@ISC_PLATFORM_HAVEINADDR6@
+
+/*! \brief
+ * If this system has sin6_scope_id, ISC_PLATFORM_HAVESCOPEID will be defined.
+ */
+@ISC_PLATFORM_HAVESCOPEID@
+
+/*! \brief
+ * If this system needs inet_ntop(), ISC_PLATFORM_NEEDNTOP will be defined.
+ */
+@ISC_PLATFORM_NEEDNTOP@
+
+/*! \brief
+ * If this system needs inet_pton(), ISC_PLATFORM_NEEDPTON will be defined.
+ */
+@ISC_PLATFORM_NEEDPTON@
+
+/*! \brief
+ * If this system needs inet_aton(), ISC_PLATFORM_NEEDATON will be defined.
+ */
+@ISC_PLATFORM_NEEDATON@
+
+/*! \brief
+ * If this system needs in_port_t, ISC_PLATFORM_NEEDPORTT will be defined.
+ */
+@ISC_PLATFORM_NEEDPORTT@
+
+/*! \brief
+ * Define if the system has struct lifconf which is a extended struct ifconf
+ * for IPv6.
+ */
+@ISC_PLATFORM_HAVELIFCONF@
+
+/*! \brief
+ * Define if the system has struct if_laddrconf which is a extended struct
+ * ifconf for IPv6.
+ */
+@ISC_PLATFORM_HAVEIF_LADDRCONF@
+
+/*! \brief
+ * Define if the system has struct if_laddrreq.
+ */
+@ISC_PLATFORM_HAVEIF_LADDRREQ@
+
+/*! \brief
+ * Define either ISC_PLATFORM_BSD44MSGHDR or ISC_PLATFORM_BSD43MSGHDR.
+ */
+@ISC_PLATFORM_MSGHDRFLAVOR@
+
+/*! \brief
+ * Define if the system supports if_nametoindex.
+ */
+@ISC_PLATFORM_HAVEIFNAMETOINDEX@
+
+/*! \brief
+ * Define on some UnixWare systems to fix erroneous definitions of various
+ * IN6_IS_ADDR_* macros.
+ */
+@ISC_PLATFORM_FIXIN6ISADDR@
+
+/*! \brief
+ * Define if the system supports kqueue multiplexing
+ */
+@ISC_PLATFORM_HAVEKQUEUE@
+
+/*! \brief
+ * Define if the system supports epoll multiplexing
+ */
+@ISC_PLATFORM_HAVEEPOLL@
+
+/*! \brief
+ * Define if the system supports /dev/poll multiplexing
+ */
+@ISC_PLATFORM_HAVEDEVPOLL@
+
+/*
+ *** Printing.
+ ***/
+
+/*! \brief
+ * If this system needs vsnprintf() and snprintf(), ISC_PLATFORM_NEEDVSNPRINTF
+ * will be defined.
+ */
+@ISC_PLATFORM_NEEDVSNPRINTF@
+
+/*! \brief
+ * If this system need a modern sprintf() that returns (int) not (char*).
+ */
+@ISC_PLATFORM_NEEDSPRINTF@
+
+/*! \brief
+ * The printf format string modifier to use with isc_uint64_t values.
+ */
+@ISC_PLATFORM_QUADFORMAT@
+
+/***
+ *** String functions.
+ ***/
+/*
+ * If the system needs strsep(), ISC_PLATFORM_NEEDSTRSEP will be defined.
+ */
+@ISC_PLATFORM_NEEDSTRSEP@
+
+/*
+ * If the system needs strlcpy(), ISC_PLATFORM_NEEDSTRLCPY will be defined.
+ */
+@ISC_PLATFORM_NEEDSTRLCPY@
+
+/*
+ * If the system needs strlcat(), ISC_PLATFORM_NEEDSTRLCAT will be defined.
+ */
+@ISC_PLATFORM_NEEDSTRLCAT@
+
+/*
+ * Define if this system needs strtoul.
+ */
+@ISC_PLATFORM_NEEDSTRTOUL@
+
+/*
+ * Define if this system needs memmove.
+ */
+@ISC_PLATFORM_NEEDMEMMOVE@
+
+/***
+ *** Miscellaneous.
+ ***/
+
+/*
+ * Defined if we are using threads.
+ */
+@ISC_PLATFORM_USETHREADS@
+
+/*
+ * Defined if unistd.h does not cause fd_set to be delared.
+ */
+@ISC_PLATFORM_NEEDSYSSELECTH@
+
+/*
+ * Defined to <gssapi.h> or <gssapi/gssapi.h> for how to include
+ * the GSSAPI header.
+ */
+@ISC_PLATFORM_GSSAPIHEADER@
+
+/*
+ * Type used for resource limits.
+ */
+@ISC_PLATFORM_RLIMITTYPE@
+
+/*
+ * Define if your compiler supports "long long int".
+ */
+@ISC_PLATFORM_HAVELONGLONG@
+
+/*
+ * Define if PTHREAD_ONCE_INIT should be surrounded by braces to
+ * prevent compiler warnings (such as with gcc on Solaris 2.8).
+ */
+@ISC_PLATFORM_BRACEPTHREADONCEINIT@
+
+/*
+ * Used to control how extern data is linked; needed for Win32 platforms.
+ */
+@ISC_PLATFORM_USEDECLSPEC@
+
+/*
+ * Define if the platform has <sys/un.h>.
+ */
+@ISC_PLATFORM_HAVESYSUNH@
+
+/*
+ * If the "xadd" operation is available on this architecture,
+ * ISC_PLATFORM_HAVEXADD will be defined.
+ */
+@ISC_PLATFORM_HAVEXADD@
+
+/*
+ * If the "xaddq" operation (64bit xadd) is available on this architecture,
+ * ISC_PLATFORM_HAVEXADDQ will be defined.
+ */
+@ISC_PLATFORM_HAVEXADDQ@
+
+/*
+ * If the "atomic swap" operation is available on this architecture,
+ * ISC_PLATFORM_HAVEATOMICSTORE" will be defined.
+ */
+@ISC_PLATFORM_HAVEATOMICSTORE@
+
+/*
+ * If the "compare-and-exchange" operation is available on this architecture,
+ * ISC_PLATFORM_HAVECMPXCHG will be defined.
+ */
+@ISC_PLATFORM_HAVECMPXCHG@
+
+/*
+ * Define if gcc ASM extension is available
+ */
+@ISC_PLATFORM_USEGCCASM@
+
+/*
+ * Define if Tru64 style ASM syntax must be used.
+ */
+@ISC_PLATFORM_USEOSFASM@
+
+/*
+ * Define if the standard __asm function must be used.
+ */
+@ISC_PLATFORM_USESTDASM@
+
+/*
+ * Define if the platform has <strings.h>.
+ */
+@ISC_PLATFORM_HAVESTRINGSH@
+
+/***
+ *** Windows dll support.
+ ***/
+
+/*
+ * Define if MacOS style of PPC assembly must be used.
+ * e.g. "r6", not "6", for register six.
+ */
+@ISC_PLATFORM_USEMACASM@
+
+#ifndef ISC_PLATFORM_USEDECLSPEC
+#define LIBISC_EXTERNAL_DATA
+#define LIBDNS_EXTERNAL_DATA
+#define LIBISCCC_EXTERNAL_DATA
+#define LIBISCCFG_EXTERNAL_DATA
+#define LIBBIND9_EXTERNAL_DATA
+#else /*! \brief ISC_PLATFORM_USEDECLSPEC */
+#ifdef LIBISC_EXPORTS
+#define LIBISC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#ifdef LIBDNS_EXPORTS
+#define LIBDNS_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBDNS_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#ifdef LIBISCCC_EXPORTS
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#ifdef LIBISCCFG_EXPORTS
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#ifdef LIBBIND9_EXPORTS
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#endif /*! \brief ISC_PLATFORM_USEDECLSPEC */
+
+/*
+ * Tell emacs to use C mode for this file.
+ *
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
+#endif /* ISC_PLATFORM_H */
diff --git a/lib/isc/include/isc/portset.h b/lib/isc/include/isc/portset.h
new file mode 100644
index 0000000..0d175c3
--- /dev/null
+++ b/lib/isc/include/isc/portset.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2008 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: portset.h,v 1.3 2008/06/23 23:47:11 tbox Exp $ */
+
+/*! \file isc/portset.h
+ * \brief Transport Protocol Port Manipuration Module
+ *
+ * This module provides simple utilities to handle a set of transport protocol
+ * (UDP or TCP) port numbers, e.g., for creating an ACL list. An isc_portset_t
+ * object is an opaque instance of a port set, for which the user can add or
+ * remove a specific port or a range of consecutive ports. This object is
+ * expected to be used as a temporary work space only, and does not protect
+ * simultaneous access from multiple threads. Therefore it must not be stored
+ * in a place that can be accessed from multiple threads.
+ */
+
+#ifndef ISC_PORTSET_H
+#define ISC_PORTSET_H 1
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/net.h>
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp);
+/*%<
+ * Create a port set and initialize it as an empty set.
+ *
+ * Requires:
+ *\li 'mctx' to be valid.
+ *\li 'portsetp' to be non NULL and '*portsetp' to be NULL;
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp);
+/*%<
+ * Destroy a port set.
+ *
+ * Requires:
+ *\li 'mctx' to be valid and must be the same context given when the port set
+ * was created.
+ *\li '*portsetp' to be a valid set.
+ */
+
+isc_boolean_t
+isc_portset_isset(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Test whether the given port is stored in the portset.
+ *
+ * Requires:
+ *\li 'portset' to be a valid set.
+ *
+ * Returns
+ * \li #ISC_TRUE if the port is found, ISC_FALSE otherwise.
+ */
+
+unsigned int
+isc_portset_nports(isc_portset_t *portset);
+/*%<
+ * Provides the number of ports stored in the given portset.
+ *
+ * Requires:
+ *\li 'portset' to be a valid set.
+ *
+ * Returns
+ * \li the number of ports stored in portset.
+ */
+
+void
+isc_portset_add(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Add the given port to the portset. The port may or may not be stored in
+ * the portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ */
+
+void
+isc_portset_remove(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Remove the given port to the portset. The port may or may not be stored in
+ * the portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ */
+
+void
+isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
+ in_port_t port_hi);
+/*%<
+ * Add a subset of [port_lo, port_hi] (inclusive) to the portset. Ports in the
+ * subset may or may not be stored in portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ *\li port_lo <= port_hi
+ */
+
+void
+isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
+ in_port_t port_hi);
+/*%<
+ * Subtract a subset of [port_lo, port_hi] (inclusive) from the portset. Ports
+ * in the subset may or may not be stored in portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ *\li port_lo <= port_hi
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NETADDR_H */
diff --git a/lib/isc/include/isc/print.h b/lib/isc/include/isc/print.h
new file mode 100644
index 0000000..cd1e38e
--- /dev/null
+++ b/lib/isc/include/isc/print.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2004-2007 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
+ * 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: print.h,v 1.26 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_PRINT_H
+#define ISC_PRINT_H 1
+
+/*! \file isc/print.h */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/formatcheck.h> /* Required for ISC_FORMAT_PRINTF() macro. */
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+/*!
+ * This block allows lib/isc/print.c to be cleanly compiled even if
+ * the platform does not need it. The standard Makefile will still
+ * not compile print.c or archive print.o, so this is just to make test
+ * compilation ("make print.o") easier.
+ */
+#if !defined(ISC_PLATFORM_NEEDVSNPRINTF) && defined(ISC__PRINT_SOURCE)
+#define ISC_PLATFORM_NEEDVSNPRINTF
+#endif
+
+#if !defined(ISC_PLATFORM_NEEDSPRINTF) && defined(ISC__PRINT_SOURCE)
+#define ISC_PLATFORM_NEEDSPRINTF
+#endif
+
+/***
+ *** Macros
+ ***/
+#define ISC_PRINT_QUADFORMAT ISC_PLATFORM_QUADFORMAT
+
+/***
+ *** Functions
+ ***/
+
+#ifdef ISC_PLATFORM_NEEDVSNPRINTF
+#include <stdarg.h>
+#include <stddef.h>
+#endif
+#ifdef ISC_PLATFORM_NEEDSPRINTF
+#include <stdio.h>
+#endif
+
+
+ISC_LANG_BEGINDECLS
+
+#ifdef ISC_PLATFORM_NEEDVSNPRINTF
+int
+isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap)
+ ISC_FORMAT_PRINTF(3, 0);
+#define vsnprintf isc_print_vsnprintf
+
+int
+isc_print_snprintf(char *str, size_t size, const char *format, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+#define snprintf isc_print_snprintf
+#endif /* ISC_PLATFORM_NEEDVSNPRINTF */
+
+#ifdef ISC_PLATFORM_NEEDSPRINTF
+int
+isc_print_sprintf(char *str, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
+#define sprintf isc_print_sprintf
+#endif
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_PRINT_H */
diff --git a/lib/isc/include/isc/quota.h b/lib/isc/include/isc/quota.h
new file mode 100644
index 0000000..7b0d0d9
--- /dev/null
+++ b/lib/isc/include/isc/quota.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: quota.h,v 1.16 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_QUOTA_H
+#define ISC_QUOTA_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/quota.h
+ *
+ * \brief The isc_quota_t object is a simple helper object for implementing
+ * quotas on things like the number of simultaneous connections to
+ * a server. It keeps track of the amount of quota in use, and
+ * encapsulates the locking necessary to allow multiple tasks to
+ * share a quota.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/types.h>
+
+/*****
+ ***** Types.
+ *****/
+
+ISC_LANG_BEGINDECLS
+
+/*% isc_quota structure */
+struct isc_quota {
+ isc_mutex_t lock; /*%< Locked by lock. */
+ int max;
+ int used;
+ int soft;
+};
+
+isc_result_t
+isc_quota_init(isc_quota_t *quota, int max);
+/*%<
+ * Initialize a quota object.
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * Other error Lock creation failed.
+ */
+
+void
+isc_quota_destroy(isc_quota_t *quota);
+/*%<
+ * Destroy a quota object.
+ */
+
+void
+isc_quota_soft(isc_quota_t *quota, int soft);
+/*%<
+ * Set a soft quota.
+ */
+
+void
+isc_quota_max(isc_quota_t *quota, int max);
+/*%<
+ * Re-set a maximum quota.
+ */
+
+isc_result_t
+isc_quota_reserve(isc_quota_t *quota);
+/*%<
+ * Attempt to reserve one unit of 'quota'.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS Success
+ * \li #ISC_R_SOFTQUOTA Success soft quota reached
+ * \li #ISC_R_QUOTA Quota is full
+ */
+
+void
+isc_quota_release(isc_quota_t *quota);
+/*%<
+ * Release one unit of quota.
+ */
+
+isc_result_t
+isc_quota_attach(isc_quota_t *quota, isc_quota_t **p);
+/*%<
+ * Like isc_quota_reserve, and also attaches '*p' to the
+ * quota if successful (ISC_R_SUCCESS or ISC_R_SOFTQUOTA).
+ */
+
+void
+isc_quota_detach(isc_quota_t **p);
+/*%<
+ * Like isc_quota_release, and also detaches '*p' from the
+ * quota.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_QUOTA_H */
diff --git a/lib/isc/include/isc/radix.h b/lib/isc/include/isc/radix.h
new file mode 100644
index 0000000..7a62ee5
--- /dev/null
+++ b/lib/isc/include/isc/radix.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2007, 2008 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: radix.h,v 1.11 2008/09/26 21:12:02 each Exp $ */
+
+/*
+ * This source was adapted from MRT's RCS Ids:
+ * Id: radix.h,v 1.6 1999/08/03 03:32:53 masaki Exp
+ * Id: mrt.h,v 1.57.2.6 1999/12/28 23:41:27 labovit Exp
+ * Id: defs.h,v 1.5.2.2 2000/01/15 14:19:16 masaki Exp
+ */
+
+#include <isc/magic.h>
+#include <isc/types.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/refcount.h>
+
+#include <string.h>
+
+#ifndef _RADIX_H
+#define _RADIX_H
+
+#define NETADDR_TO_PREFIX_T(na,pt,bits) \
+ do { \
+ memset(&(pt), 0, sizeof(pt)); \
+ if((na) != NULL) { \
+ (pt).family = (na)->family; \
+ (pt).bitlen = (bits); \
+ if ((pt).family == AF_INET6) { \
+ memcpy(&(pt).add.sin6, &(na)->type.in6, \
+ ((bits)+7)/8); \
+ } else \
+ memcpy(&(pt).add.sin, &(na)->type.in, \
+ ((bits)+7)/8); \
+ } else { \
+ (pt).family = AF_UNSPEC; \
+ (pt).bitlen = 0; \
+ } \
+ isc_refcount_init(&(pt).refcount, 0); \
+ } while(0)
+
+typedef struct isc_prefix {
+ unsigned int family; /* AF_INET | AF_INET6, or AF_UNSPEC for "any" */
+ unsigned int bitlen; /* 0 for "any" */
+ isc_refcount_t refcount;
+ union {
+ struct in_addr sin;
+ struct in6_addr sin6;
+ } add;
+} isc_prefix_t;
+
+typedef void (*isc_radix_destroyfunc_t)(void *);
+typedef void (*isc_radix_processfunc_t)(isc_prefix_t *, void **);
+
+#define isc_prefix_tochar(prefix) ((char *)&(prefix)->add.sin)
+#define isc_prefix_touchar(prefix) ((u_char *)&(prefix)->add.sin)
+
+#define BIT_TEST(f, b) ((f) & (b))
+
+/*
+ * We need "first match" when we search the radix tree to preserve
+ * compatibility with the existing ACL implementation. Radix trees
+ * naturally lend themselves to "best match". In order to get "first match"
+ * behavior, we keep track of the order in which entries are added to the
+ * tree--and when a search is made, we find all matching entries, and
+ * return the one that was added first.
+ *
+ * An IPv4 prefix and an IPv6 prefix may share a radix tree node if they
+ * have the same length and bit pattern (e.g., 127/8 and 7f::/8). To
+ * disambiguate between them, node_num and data are two-element arrays;
+ * node_num[0] and data[0] are used for IPv4 addresses, node_num[1]
+ * and data[1] for IPv6 addresses. The only exception is a prefix of
+ * 0/0 (aka "any" or "none"), which is always stored as IPv4 but matches
+ * IPv6 addresses too.
+ */
+
+#define ISC_IS6(family) ((family) == AF_INET6 ? 1 : 0)
+typedef struct isc_radix_node {
+ isc_uint32_t bit; /* bit length of the prefix */
+ isc_prefix_t *prefix; /* who we are in radix tree */
+ struct isc_radix_node *l, *r; /* left and right children */
+ struct isc_radix_node *parent; /* may be used */
+ void *data[2]; /* pointers to IPv4 and IPV6 data */
+ int node_num[2]; /* which node this was in the tree,
+ or -1 for glue nodes */
+} isc_radix_node_t;
+
+#define RADIX_TREE_MAGIC ISC_MAGIC('R','d','x','T');
+#define RADIX_TREE_VALID(a) ISC_MAGIC_VALID(a, RADIX_TREE_MAGIC);
+
+typedef struct isc_radix_tree {
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_radix_node_t *head;
+ isc_uint32_t maxbits; /* for IP, 32 bit addresses */
+ int num_active_node; /* for debugging purposes */
+ int num_added_node; /* total number of nodes */
+} isc_radix_tree_t;
+
+
+isc_result_t
+isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target, isc_prefix_t *prefix);
+
+isc_result_t
+isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target, isc_radix_node_t *source, isc_prefix_t *prefix);
+
+void
+isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node);
+
+isc_result_t
+isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits);
+
+void
+isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
+
+void
+isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func);
+
+
+#define RADIX_MAXBITS 128
+#define RADIX_NBIT(x) (0x80 >> ((x) & 0x7f))
+#define RADIX_NBYTE(x) ((x) >> 3)
+
+#define RADIX_DATA_GET(node, type) (type *)((node)->data)
+#define RADIX_DATA_SET(node, value) ((node)->data = (void *)(value))
+
+#define RADIX_WALK(Xhead, Xnode) \
+ do { \
+ isc_radix_node_t *Xstack[RADIX_MAXBITS+1]; \
+ isc_radix_node_t **Xsp = Xstack; \
+ isc_radix_node_t *Xrn = (Xhead); \
+ while ((Xnode = Xrn)) { \
+ if (Xnode->prefix)
+
+#define RADIX_WALK_ALL(Xhead, Xnode) \
+do { \
+ isc_radix_node_t *Xstack[RADIX_MAXBITS+1]; \
+ isc_radix_node_t **Xsp = Xstack; \
+ isc_radix_node_t *Xrn = (Xhead); \
+ while ((Xnode = Xrn)) { \
+ if (1)
+
+#define RADIX_WALK_BREAK { \
+ if (Xsp != Xstack) { \
+ Xrn = *(--Xsp); \
+ } else { \
+ Xrn = (radix_node_t *) 0; \
+ } \
+ continue; }
+
+#define RADIX_WALK_END \
+ if (Xrn->l) { \
+ if (Xrn->r) { \
+ *Xsp++ = Xrn->r; \
+ } \
+ Xrn = Xrn->l; \
+ } else if (Xrn->r) { \
+ Xrn = Xrn->r; \
+ } else if (Xsp != Xstack) { \
+ Xrn = *(--Xsp); \
+ } else { \
+ Xrn = (isc_radix_node_t *) 0; \
+ } \
+ } \
+ } while (0)
+
+#endif /* _RADIX_H */
diff --git a/lib/isc/include/isc/random.h b/lib/isc/include/isc/random.h
new file mode 100644
index 0000000..36e54b4
--- /dev/null
+++ b/lib/isc/include/isc/random.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: random.h,v 1.18 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_RANDOM_H
+#define ISC_RANDOM_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*! \file isc/random.h
+ * \brief Implements a random state pool which will let the caller return a
+ * series of possibly non-reproducable random values.
+ *
+ * Note that the
+ * strength of these numbers is not all that high, and should not be
+ * used in cryptography functions. It is useful for jittering values
+ * a bit here and there, such as timeouts, etc.
+ */
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_random_seed(isc_uint32_t seed);
+/*%<
+ * Set the initial seed of the random state.
+ */
+
+void
+isc_random_get(isc_uint32_t *val);
+/*%<
+ * Get a random value.
+ *
+ * Requires:
+ * val != NULL.
+ */
+
+isc_uint32_t
+isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter);
+/*%<
+ * Get a random value between (max - jitter) and (max).
+ * This is useful for jittering timer values.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RANDOM_H */
diff --git a/lib/isc/include/isc/ratelimiter.h b/lib/isc/include/isc/ratelimiter.h
new file mode 100644
index 0000000..03da2d0
--- /dev/null
+++ b/lib/isc/include/isc/ratelimiter.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: ratelimiter.h,v 1.21 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_RATELIMITER_H
+#define ISC_RATELIMITER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/ratelimiter.h
+ * \brief A rate limiter is a mechanism for dispatching events at a limited
+ * rate. This is intended to be used when sending zone maintenance
+ * SOA queries, NOTIFY messages, etc.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Functions.
+ *****/
+
+isc_result_t
+isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
+ isc_task_t *task, isc_ratelimiter_t **ratelimiterp);
+/*%<
+ * Create a rate limiter. The execution interval is initially undefined.
+ */
+
+isc_result_t
+isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval);
+/*!<
+ * Set the mininum interval between event executions.
+ * The interval value is copied, so the caller need not preserve it.
+ *
+ * Requires:
+ * '*interval' is a nonzero interval.
+ */
+
+void
+isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, isc_uint32_t perint);
+/*%<
+ * Set the number of events processed per interval timer tick.
+ * If 'perint' is zero it is treated as 1.
+ */
+
+isc_result_t
+isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task,
+ isc_event_t **eventp);
+/*%<
+ * Queue an event for rate-limited execution.
+ *
+ * This is similar
+ * to doing an isc_task_send() to the 'task', except that the
+ * execution may be delayed to achieve the desired rate of
+ * execution.
+ *
+ * '(*eventp)->ev_sender' is used to hold the task. The caller
+ * must ensure that the task exists until the event is delivered.
+ *
+ * Requires:
+ *\li An interval has been set by calling
+ * isc_ratelimiter_setinterval().
+ *
+ *\li 'task' to be non NULL.
+ *\li '(*eventp)->ev_sender' to be NULL.
+ */
+
+void
+isc_ratelimiter_shutdown(isc_ratelimiter_t *ratelimiter);
+/*%<
+ * Shut down a rate limiter.
+ *
+ * Ensures:
+ *\li All events that have not yet been
+ * dispatched to the task are dispatched immediately with
+ * the #ISC_EVENTATTR_CANCELED bit set in ev_attributes.
+ *
+ *\li Further attempts to enqueue events will fail with
+ * #ISC_R_SHUTTINGDOWN.
+ *
+ *\li The reatelimiter is no longer attached to its task.
+ */
+
+void
+isc_ratelimiter_attach(isc_ratelimiter_t *source, isc_ratelimiter_t **target);
+/*%<
+ * Attach to a rate limiter.
+ */
+
+void
+isc_ratelimiter_detach(isc_ratelimiter_t **ratelimiterp);
+/*%<
+ * Detach from a rate limiter.
+ */
+
+isc_result_t
+isc_ratelimiter_stall(isc_ratelimiter_t *rl);
+/*%<
+ * Stall event processing.
+ */
+
+isc_result_t
+isc_ratelimiter_release(isc_ratelimiter_t *rl);
+/*%<
+ * Release a stalled rate limiter.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RATELIMITER_H */
diff --git a/lib/isc/include/isc/refcount.h b/lib/isc/include/isc/refcount.h
new file mode 100644
index 0000000..6ab14ae
--- /dev/null
+++ b/lib/isc/include/isc/refcount.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2004-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: refcount.h,v 1.15 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_REFCOUNT_H
+#define ISC_REFCOUNT_H 1
+
+#include <isc/atomic.h>
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+/*! \file isc/refcount.h
+ * \brief Implements a locked reference counter.
+ *
+ * These functions may actually be
+ * implemented using macros, and implementations of these macros are below.
+ * The isc_refcount_t type should not be accessed directly, as its contents
+ * depend on the implementation.
+ */
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Function prototypes
+ */
+
+/*
+ * isc_result_t
+ * isc_refcount_init(isc_refcount_t *ref, unsigned int n);
+ *
+ * Initialize the reference counter. There will be 'n' initial references.
+ *
+ * Requires:
+ * ref != NULL
+ */
+
+/*
+ * void
+ * isc_refcount_destroy(isc_refcount_t *ref);
+ *
+ * Destroys a reference counter.
+ *
+ * Requires:
+ * ref != NULL
+ * The number of references is 0.
+ */
+
+/*
+ * void
+ * isc_refcount_increment(isc_refcount_t *ref, unsigned int *targetp);
+ * isc_refcount_increment0(isc_refcount_t *ref, unsigned int *targetp);
+ *
+ * Increments the reference count, returning the new value in targetp if it's
+ * not NULL. The reference counter typically begins with the initial counter
+ * of 1, and will be destroyed once the counter reaches 0. Thus,
+ * isc_refcount_increment() additionally requires the previous counter be
+ * larger than 0 so that an error which violates the usage can be easily
+ * caught. isc_refcount_increment0() does not have this restriction.
+ *
+ * Requires:
+ * ref != NULL.
+ */
+
+/*
+ * void
+ * isc_refcount_decrement(isc_refcount_t *ref, unsigned int *targetp);
+ *
+ * Decrements the reference count, returning the new value in targetp if it's
+ * not NULL.
+ *
+ * Requires:
+ * ref != NULL.
+ */
+
+
+/*
+ * Sample implementations
+ */
+#ifdef ISC_PLATFORM_USETHREADS
+#ifdef ISC_PLATFORM_HAVEXADD
+
+#define ISC_REFCOUNT_HAVEATOMIC 1
+
+typedef struct isc_refcount {
+ isc_int32_t refs;
+} isc_refcount_t;
+
+#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
+#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
+
+#define isc_refcount_increment0(rp, tp) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(tp); \
+ isc_int32_t prev; \
+ prev = isc_atomic_xadd(&(rp)->refs, 1); \
+ if (_tmp != NULL) \
+ *_tmp = prev + 1; \
+ } while (0)
+
+#define isc_refcount_increment(rp, tp) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(tp); \
+ isc_int32_t prev; \
+ prev = isc_atomic_xadd(&(rp)->refs, 1); \
+ REQUIRE(prev > 0); \
+ if (_tmp != NULL) \
+ *_tmp = prev + 1; \
+ } while (0)
+
+#define isc_refcount_decrement(rp, tp) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(tp); \
+ isc_int32_t prev; \
+ prev = isc_atomic_xadd(&(rp)->refs, -1); \
+ REQUIRE(prev > 0); \
+ if (_tmp != NULL) \
+ *_tmp = prev - 1; \
+ } while (0)
+
+#else /* ISC_PLATFORM_HAVEXADD */
+
+typedef struct isc_refcount {
+ int refs;
+ isc_mutex_t lock;
+} isc_refcount_t;
+
+/*% Destroys a reference counter. */
+#define isc_refcount_destroy(rp) \
+ do { \
+ REQUIRE((rp)->refs == 0); \
+ DESTROYLOCK(&(rp)->lock); \
+ } while (0)
+
+#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
+
+/*% Increments the reference count, returning the new value in targetp if it's not NULL. */
+#define isc_refcount_increment0(rp, tp) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(tp); \
+ LOCK(&(rp)->lock); \
+ ++((rp)->refs); \
+ if (_tmp != NULL) \
+ *_tmp = ((rp)->refs); \
+ UNLOCK(&(rp)->lock); \
+ } while (0)
+
+#define isc_refcount_increment(rp, tp) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(tp); \
+ LOCK(&(rp)->lock); \
+ REQUIRE((rp)->refs > 0); \
+ ++((rp)->refs); \
+ if (_tmp != NULL) \
+ *_tmp = ((rp)->refs); \
+ UNLOCK(&(rp)->lock); \
+ } while (0)
+
+/*% Decrements the reference count, returning the new value in targetp if it's not NULL. */
+#define isc_refcount_decrement(rp, tp) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(tp); \
+ LOCK(&(rp)->lock); \
+ REQUIRE((rp)->refs > 0); \
+ --((rp)->refs); \
+ if (_tmp != NULL) \
+ *_tmp = ((rp)->refs); \
+ UNLOCK(&(rp)->lock); \
+ } while (0)
+
+#endif /* ISC_PLATFORM_HAVEXADD */
+#else /* ISC_PLATFORM_USETHREADS */
+
+typedef struct isc_refcount {
+ int refs;
+} isc_refcount_t;
+
+#define isc_refcount_destroy(rp) (REQUIRE((rp)->refs == 0))
+#define isc_refcount_current(rp) ((unsigned int)((rp)->refs))
+
+#define isc_refcount_increment0(rp, tp) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(tp); \
+ int _n = ++(rp)->refs; \
+ if (_tmp != NULL) \
+ *_tmp = _n; \
+ } while (0)
+
+#define isc_refcount_increment(rp, tp) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(tp); \
+ int _n; \
+ REQUIRE((rp)->refs > 0); \
+ _n = ++(rp)->refs; \
+ if (_tmp != NULL) \
+ *_tmp = _n; \
+ } while (0)
+
+#define isc_refcount_decrement(rp, tp) \
+ do { \
+ unsigned int *_tmp = (unsigned int *)(tp); \
+ int _n; \
+ REQUIRE((rp)->refs > 0); \
+ _n = --(rp)->refs; \
+ if (_tmp != NULL) \
+ *_tmp = _n; \
+ } while (0)
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+isc_result_t
+isc_refcount_init(isc_refcount_t *ref, unsigned int n);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_REFCOUNT_H */
diff --git a/lib/isc/include/isc/region.h b/lib/isc/include/isc/region.h
new file mode 100644
index 0000000..43d8f8f
--- /dev/null
+++ b/lib/isc/include/isc/region.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: region.h,v 1.25 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_REGION_H
+#define ISC_REGION_H 1
+
+/*! \file isc/region.h */
+
+#include <isc/types.h>
+
+struct isc_region {
+ unsigned char * base;
+ unsigned int length;
+};
+
+struct isc_textregion {
+ char * base;
+ unsigned int length;
+};
+
+/* XXXDCL questionable ... bears discussion. we have been putting off
+ * discussing the region api.
+ */
+struct isc_constregion {
+ const void * base;
+ unsigned int length;
+};
+
+struct isc_consttextregion {
+ const char * base;
+ unsigned int length;
+};
+
+/*@{*/
+/*!
+ * The region structure is not opaque, and is usually directly manipulated.
+ * Some macros are defined below for convenience.
+ */
+
+#define isc_region_consume(r,l) \
+ do { \
+ isc_region_t *_r = (r); \
+ unsigned int _l = (l); \
+ INSIST(_r->length >= _l); \
+ _r->base += _l; \
+ _r->length -= _l; \
+ } while (0)
+
+#define isc_textregion_consume(r,l) \
+ do { \
+ isc_textregion_t *_r = (r); \
+ unsigned int _l = (l); \
+ INSIST(_r->length >= _l); \
+ _r->base += _l; \
+ _r->length -= _l; \
+ } while (0)
+
+#define isc_constregion_consume(r,l) \
+ do { \
+ isc_constregion_t *_r = (r); \
+ unsigned int _l = (l); \
+ INSIST(_r->length >= _l); \
+ _r->base += _l; \
+ _r->length -= _l; \
+ } while (0)
+/*@}*/
+
+int
+isc_region_compare(isc_region_t *r1, isc_region_t *r2);
+/*%<
+ * Compares the contents of two regions
+ *
+ * Requires:
+ *\li 'r1' is a valid region
+ *\li 'r2' is a valid region
+ *
+ * Returns:
+ *\li < 0 if r1 is lexicographically less than r2
+ *\li = 0 if r1 is lexicographically identical to r2
+ *\li > 0 if r1 is lexicographically greater than r2
+ */
+
+#endif /* ISC_REGION_H */
diff --git a/lib/isc/include/isc/resource.h b/lib/isc/include/isc/resource.h
new file mode 100644
index 0000000..747c9fd
--- /dev/null
+++ b/lib/isc/include/isc/resource.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: resource.h,v 1.13 2008/07/11 23:47:09 tbox Exp $ */
+
+#ifndef ISC_RESOURCE_H
+#define ISC_RESOURCE_H 1
+
+/*! \file isc/resource.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#define ISC_RESOURCE_UNLIMITED ((isc_resourcevalue_t)ISC_UINT64_MAX)
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value);
+/*%<
+ * Set the maximum limit for a system resource.
+ *
+ * Notes:
+ *\li If 'value' exceeds the maximum possible on the operating system,
+ * it is silently limited to that maximum -- or to "infinity", if
+ * the operating system has that concept. #ISC_RESOURCE_UNLIMITED
+ * can be used to explicitly ask for the maximum.
+ *
+ * Requires:
+ *\li 'resource' is a valid member of the isc_resource_t enumeration.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS.
+ *\li #ISC_R_NOPERM The calling process did not have adequate permission
+ * to change the resource limit.
+ */
+
+isc_result_t
+isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value);
+/*%<
+ * Get the maximum limit for a system resource.
+ *
+ * Notes:
+ *\li 'value' is set to the maximum limit.
+ *
+ *\li #ISC_RESOURCE_UNLIMITED is the maximum value of isc_resourcevalue_t.
+ *
+ *\li On many (all?) Unix systems, RLIM_INFINITY is a valid value that is
+ * significantly less than #ISC_RESOURCE_UNLIMITED, but which in practice
+ * behaves the same.
+ *
+ *\li The current ISC libdns configuration file parser assigns a value
+ * of ISC_UINT32_MAX for a size_spec of "unlimited" and ISC_UNIT32_MAX - 1
+ * for "default", the latter of which is supposed to represent "the
+ * limit that was in force when the server started". Since these are
+ * valid values in the middle of the range of isc_resourcevalue_t,
+ * there is the possibility for confusion over what exactly those
+ * particular values are supposed to represent in a particular context --
+ * discrete integral values or generalized concepts.
+ *
+ * Requires:
+ *\li 'resource' is a valid member of the isc_resource_t enumeration.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS.
+ */
+
+isc_result_t
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value);
+/*%<
+ * Same as isc_resource_getlimit(), but returns the current (soft) limit.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RESOURCE_H */
+
diff --git a/lib/isc/include/isc/result.h b/lib/isc/include/isc/result.h
new file mode 100644
index 0000000..56b4ca6
--- /dev/null
+++ b/lib/isc/include/isc/result.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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: result.h,v 1.71 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef ISC_RESULT_H
+#define ISC_RESULT_H 1
+
+/*! \file isc/result.h */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#define ISC_R_SUCCESS 0 /*%< success */
+#define ISC_R_NOMEMORY 1 /*%< out of memory */
+#define ISC_R_TIMEDOUT 2 /*%< timed out */
+#define ISC_R_NOTHREADS 3 /*%< no available threads */
+#define ISC_R_ADDRNOTAVAIL 4 /*%< address not available */
+#define ISC_R_ADDRINUSE 5 /*%< address in use */
+#define ISC_R_NOPERM 6 /*%< permission denied */
+#define ISC_R_NOCONN 7 /*%< no pending connections */
+#define ISC_R_NETUNREACH 8 /*%< network unreachable */
+#define ISC_R_HOSTUNREACH 9 /*%< host unreachable */
+#define ISC_R_NETDOWN 10 /*%< network down */
+#define ISC_R_HOSTDOWN 11 /*%< host down */
+#define ISC_R_CONNREFUSED 12 /*%< connection refused */
+#define ISC_R_NORESOURCES 13 /*%< not enough free resources */
+#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_LOCKBUSY 17 /*%< lock busy */
+#define ISC_R_EXISTS 18 /*%< already exists */
+#define ISC_R_NOSPACE 19 /*%< ran out of space */
+#define ISC_R_CANCELED 20 /*%< operation canceled */
+#define ISC_R_NOTBOUND 21 /*%< socket is not bound */
+#define ISC_R_SHUTTINGDOWN 22 /*%< shutting down */
+#define ISC_R_NOTFOUND 23 /*%< not found */
+#define ISC_R_UNEXPECTEDEND 24 /*%< unexpected end of input */
+#define ISC_R_FAILURE 25 /*%< generic failure */
+#define ISC_R_IOERROR 26 /*%< I/O error */
+#define ISC_R_NOTIMPLEMENTED 27 /*%< not implemented */
+#define ISC_R_UNBALANCED 28 /*%< unbalanced parentheses */
+#define ISC_R_NOMORE 29 /*%< no more */
+#define ISC_R_INVALIDFILE 30 /*%< invalid file */
+#define ISC_R_BADBASE64 31 /*%< bad base64 encoding */
+#define ISC_R_UNEXPECTEDTOKEN 32 /*%< unexpected token */
+#define ISC_R_QUOTA 33 /*%< quota reached */
+#define ISC_R_UNEXPECTED 34 /*%< unexpected error */
+#define ISC_R_ALREADYRUNNING 35 /*%< already running */
+#define ISC_R_IGNORE 36 /*%< ignore */
+#define ISC_R_MASKNONCONTIG 37 /*%< addr mask not contiguous */
+#define ISC_R_FILENOTFOUND 38 /*%< file not found */
+#define ISC_R_FILEEXISTS 39 /*%< file already exists */
+#define ISC_R_NOTCONNECTED 40 /*%< socket is not connected */
+#define ISC_R_RANGE 41 /*%< out of range */
+#define ISC_R_NOENTROPY 42 /*%< out of entropy */
+#define ISC_R_MULTICAST 43 /*%< invalid use of multicast */
+#define ISC_R_NOTFILE 44 /*%< not a file */
+#define ISC_R_NOTDIRECTORY 45 /*%< not a directory */
+#define ISC_R_QUEUEFULL 46 /*%< queue is full */
+#define ISC_R_FAMILYMISMATCH 47 /*%< address family mismatch */
+#define ISC_R_FAMILYNOSUPPORT 48 /*%< AF not supported */
+#define ISC_R_BADHEX 49 /*%< bad hex encoding */
+#define ISC_R_TOOMANYOPENFILES 50 /*%< too many open files */
+#define ISC_R_NOTBLOCKING 51 /*%< not blocking */
+#define ISC_R_UNBALANCEDQUOTES 52 /*%< unbalanced quotes */
+#define ISC_R_INPROGRESS 53 /*%< operation in progress */
+#define ISC_R_CONNECTIONRESET 54 /*%< connection reset */
+#define ISC_R_SOFTQUOTA 55 /*%< soft quota reached */
+#define ISC_R_BADNUMBER 56 /*%< not a valid number */
+#define ISC_R_DISABLED 57 /*%< disabled */
+#define ISC_R_MAXSIZE 58 /*%< max size */
+#define ISC_R_BADADDRESSFORM 59 /*%< invalid address format */
+#define ISC_R_BADBASE32 60 /*%< bad base32 encoding */
+
+/*% Not a result code: the number of results. */
+#define ISC_R_NRESULTS 61
+
+ISC_LANG_BEGINDECLS
+
+const char *
+isc_result_totext(isc_result_t);
+/*%<
+ * Convert an isc_result_t into a string message describing the result.
+ */
+
+isc_result_t
+isc_result_register(unsigned int base, unsigned int nresults,
+ const char **text, isc_msgcat_t *msgcat, int set);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RESULT_H */
diff --git a/lib/isc/include/isc/resultclass.h b/lib/isc/include/isc/resultclass.h
new file mode 100644
index 0000000..b32426f
--- /dev/null
+++ b/lib/isc/include/isc/resultclass.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: resultclass.h,v 1.18 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_RESULTCLASS_H
+#define ISC_RESULTCLASS_H 1
+
+
+/*! \file isc/resultclass.h
+ * \brief Registry of Predefined Result Type Classes
+ *
+ * A result class number is an unsigned 16 bit number. Each class may
+ * contain up to 65536 results. A result code is formed by adding the
+ * result number within the class to the class number multiplied by 65536.
+ *
+ * Classes < 1024 are reserved for ISC use.
+ * Result classes >= 1024 and <= 65535 are reserved for application use.
+ */
+
+#define ISC_RESULTCLASS_FROMNUM(num) ((num) << 16)
+#define ISC_RESULTCLASS_TONUM(rclass) ((rclass) >> 16)
+#define ISC_RESULTCLASS_SIZE 65536
+#define ISC_RESULTCLASS_INCLASS(rclass, result) \
+ ((rclass) == ((result) & 0xFFFF0000))
+
+
+#define ISC_RESULTCLASS_ISC ISC_RESULTCLASS_FROMNUM(0)
+#define ISC_RESULTCLASS_DNS ISC_RESULTCLASS_FROMNUM(1)
+#define ISC_RESULTCLASS_DST ISC_RESULTCLASS_FROMNUM(2)
+#define ISC_RESULTCLASS_DNSRCODE ISC_RESULTCLASS_FROMNUM(3)
+#define ISC_RESULTCLASS_OMAPI ISC_RESULTCLASS_FROMNUM(4)
+#define ISC_RESULTCLASS_ISCCC ISC_RESULTCLASS_FROMNUM(5)
+
+
+#endif /* ISC_RESULTCLASS_H */
diff --git a/lib/isc/include/isc/rwlock.h b/lib/isc/include/isc/rwlock.h
new file mode 100644
index 0000000..28052cd
--- /dev/null
+++ b/lib/isc/include/isc/rwlock.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2004-2007 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
+ * 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: rwlock.h,v 1.28 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_RWLOCK_H
+#define ISC_RWLOCK_H 1
+
+/*! \file isc/rwlock.h */
+
+#include <isc/condition.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef enum {
+ isc_rwlocktype_none = 0,
+ isc_rwlocktype_read,
+ isc_rwlocktype_write
+} isc_rwlocktype_t;
+
+#ifdef ISC_PLATFORM_USETHREADS
+#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
+#define ISC_RWLOCK_USEATOMIC 1
+#endif
+
+struct isc_rwlock {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mutex_t lock;
+
+#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
+ /*
+ * When some atomic instructions with hardware assistance are
+ * available, rwlock will use those so that concurrent readers do not
+ * interfere with each other through mutex as long as no writers
+ * appear, massively reducing the lock overhead in the typical case.
+ *
+ * The basic algorithm of this approach is the "simple
+ * writer-preference lock" shown in the following URL:
+ * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html
+ * but our implementation does not rely on the spin lock unlike the
+ * original algorithm to be more portable as a user space application.
+ */
+
+ /* Read or modified atomically. */
+ isc_int32_t write_requests;
+ isc_int32_t write_completions;
+ isc_int32_t cnt_and_flag;
+
+ /* Locked by lock. */
+ isc_condition_t readable;
+ isc_condition_t writeable;
+ unsigned int readers_waiting;
+
+ /* Locked by rwlock itself. */
+ unsigned int write_granted;
+
+ /* Unlocked. */
+ unsigned int write_quota;
+
+#else /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */
+
+ /*%< Locked by lock. */
+ isc_condition_t readable;
+ isc_condition_t writeable;
+ isc_rwlocktype_t type;
+
+ /*% The number of threads that have the lock. */
+ unsigned int active;
+
+ /*%
+ * The number of lock grants made since the lock was last switched
+ * from reading to writing or vice versa; used in determining
+ * when the quota is reached and it is time to switch.
+ */
+ unsigned int granted;
+
+ unsigned int readers_waiting;
+ unsigned int writers_waiting;
+ unsigned int read_quota;
+ unsigned int write_quota;
+ isc_rwlocktype_t original;
+#endif /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */
+};
+#else /* ISC_PLATFORM_USETHREADS */
+struct isc_rwlock {
+ unsigned int magic;
+ isc_rwlocktype_t type;
+ unsigned int active;
+};
+#endif /* ISC_PLATFORM_USETHREADS */
+
+
+isc_result_t
+isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
+ unsigned int write_quota);
+
+isc_result_t
+isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+
+isc_result_t
+isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+
+isc_result_t
+isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type);
+
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl);
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl);
+
+void
+isc_rwlock_destroy(isc_rwlock_t *rwl);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_RWLOCK_H */
diff --git a/lib/isc/include/isc/serial.h b/lib/isc/include/isc/serial.h
new file mode 100644
index 0000000..435ef93
--- /dev/null
+++ b/lib/isc/include/isc/serial.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: serial.h,v 1.16 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_SERIAL_H
+#define ISC_SERIAL_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*! \file isc/serial.h
+ * \brief Implement 32 bit serial space arithmetic comparision functions.
+ * Note: Undefined results are returned as ISC_FALSE.
+ */
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_boolean_t
+isc_serial_lt(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ * Return true if 'a' < 'b' otherwise false.
+ */
+
+isc_boolean_t
+isc_serial_gt(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ * Return true if 'a' > 'b' otherwise false.
+ */
+
+isc_boolean_t
+isc_serial_le(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ * Return true if 'a' <= 'b' otherwise false.
+ */
+
+isc_boolean_t
+isc_serial_ge(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ * Return true if 'a' >= 'b' otherwise false.
+ */
+
+isc_boolean_t
+isc_serial_eq(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ * Return true if 'a' == 'b' otherwise false.
+ */
+
+isc_boolean_t
+isc_serial_ne(isc_uint32_t a, isc_uint32_t b);
+/*%<
+ * Return true if 'a' != 'b' otherwise false.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SERIAL_H */
diff --git a/lib/isc/include/isc/sha1.h b/lib/isc/include/isc/sha1.h
new file mode 100644
index 0000000..63f12bb
--- /dev/null
+++ b/lib/isc/include/isc/sha1.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004-2007 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.
+ */
+
+#ifndef ISC_SHA1_H
+#define ISC_SHA1_H 1
+
+/* $Id: sha1.h,v 1.17 2007/06/19 23:47:18 tbox Exp $ */
+
+/* $NetBSD: sha1.h,v 1.2 1998/05/29 22:55:44 thorpej Exp $ */
+
+/*! \file isc/sha1.h
+ * \brief SHA-1 in C
+ * \author By Steve Reid <steve@edmweb.com>
+ * \note 100% Public Domain
+ */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#define ISC_SHA1_DIGESTLENGTH 20U
+#define ISC_SHA1_BLOCK_LENGTH 64U
+
+typedef struct {
+ isc_uint32_t state[5];
+ isc_uint32_t count[2];
+ unsigned char buffer[ISC_SHA1_BLOCK_LENGTH];
+} isc_sha1_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_sha1_init(isc_sha1_t *ctx);
+
+void
+isc_sha1_invalidate(isc_sha1_t *ctx);
+
+void
+isc_sha1_update(isc_sha1_t *ctx, const unsigned char *data, unsigned int len);
+
+void
+isc_sha1_final(isc_sha1_t *ctx, unsigned char *digest);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SHA1_H */
diff --git a/lib/isc/include/isc/sha2.h b/lib/isc/include/isc/sha2.h
new file mode 100644
index 0000000..203600f
--- /dev/null
+++ b/lib/isc/include/isc/sha2.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2005-2007 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: sha2.h,v 1.9 2007/06/19 23:47:18 tbox Exp $ */
+
+/* $FreeBSD: src/sys/crypto/sha2/sha2.h,v 1.1.2.1 2001/07/03 11:01:36 ume Exp $ */
+/* $KAME: sha2.h,v 1.3 2001/03/12 08:27:48 itojun Exp $ */
+
+/*
+ * sha2.h
+ *
+ * Version 1.0.0beta1
+ *
+ * Written by Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright 2000 Aaron D. Gifford. 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 copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef ISC_SHA2_H
+#define ISC_SHA2_H
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*** SHA-224/256/384/512 Various Length Definitions ***********************/
+
+#define ISC_SHA224_BLOCK_LENGTH 64U
+#define ISC_SHA224_DIGESTLENGTH 28U
+#define ISC_SHA224_DIGESTSTRINGLENGTH (ISC_SHA224_DIGESTLENGTH * 2 + 1)
+#define ISC_SHA256_BLOCK_LENGTH 64U
+#define ISC_SHA256_DIGESTLENGTH 32U
+#define ISC_SHA256_DIGESTSTRINGLENGTH (ISC_SHA256_DIGESTLENGTH * 2 + 1)
+#define ISC_SHA384_BLOCK_LENGTH 128
+#define ISC_SHA384_DIGESTLENGTH 48U
+#define ISC_SHA384_DIGESTSTRINGLENGTH (ISC_SHA384_DIGESTLENGTH * 2 + 1)
+#define ISC_SHA512_BLOCK_LENGTH 128U
+#define ISC_SHA512_DIGESTLENGTH 64U
+#define ISC_SHA512_DIGESTSTRINGLENGTH (ISC_SHA512_DIGESTLENGTH * 2 + 1)
+
+
+ISC_LANG_BEGINDECLS
+
+/*** SHA-256/384/512 Context Structures *******************************/
+
+/*
+ * Keep buffer immediately after bitcount to preserve alignment.
+ */
+typedef struct {
+ isc_uint32_t state[8];
+ isc_uint64_t bitcount;
+ isc_uint8_t buffer[ISC_SHA256_BLOCK_LENGTH];
+} isc_sha256_t;
+
+/*
+ * Keep buffer immediately after bitcount to preserve alignment.
+ */
+typedef struct {
+ isc_uint64_t state[8];
+ isc_uint64_t bitcount[2];
+ isc_uint8_t buffer[ISC_SHA512_BLOCK_LENGTH];
+} isc_sha512_t;
+
+typedef isc_sha256_t isc_sha224_t;
+typedef isc_sha512_t isc_sha384_t;
+
+/*** SHA-224/256/384/512 Function Prototypes ******************************/
+
+void isc_sha224_init (isc_sha224_t *);
+void isc_sha224_update (isc_sha224_t *, const isc_uint8_t *, size_t);
+void isc_sha224_final (isc_uint8_t[ISC_SHA224_DIGESTLENGTH], isc_sha224_t *);
+char *isc_sha224_end (isc_sha224_t *, char[ISC_SHA224_DIGESTSTRINGLENGTH]);
+char *isc_sha224_data (const isc_uint8_t *, size_t, char[ISC_SHA224_DIGESTSTRINGLENGTH]);
+
+void isc_sha256_init (isc_sha256_t *);
+void isc_sha256_update (isc_sha256_t *, const isc_uint8_t *, size_t);
+void isc_sha256_final (isc_uint8_t[ISC_SHA256_DIGESTLENGTH], isc_sha256_t *);
+char *isc_sha256_end (isc_sha256_t *, char[ISC_SHA256_DIGESTSTRINGLENGTH]);
+char *isc_sha256_data (const isc_uint8_t *, size_t, char[ISC_SHA256_DIGESTSTRINGLENGTH]);
+
+void isc_sha384_init (isc_sha384_t *);
+void isc_sha384_update (isc_sha384_t *, const isc_uint8_t *, size_t);
+void isc_sha384_final (isc_uint8_t[ISC_SHA384_DIGESTLENGTH], isc_sha384_t *);
+char *isc_sha384_end (isc_sha384_t *, char[ISC_SHA384_DIGESTSTRINGLENGTH]);
+char *isc_sha384_data (const isc_uint8_t *, size_t, char[ISC_SHA384_DIGESTSTRINGLENGTH]);
+
+void isc_sha512_init (isc_sha512_t *);
+void isc_sha512_update (isc_sha512_t *, const isc_uint8_t *, size_t);
+void isc_sha512_final (isc_uint8_t[ISC_SHA512_DIGESTLENGTH], isc_sha512_t *);
+char *isc_sha512_end (isc_sha512_t *, char[ISC_SHA512_DIGESTSTRINGLENGTH]);
+char *isc_sha512_data (const isc_uint8_t *, size_t, char[ISC_SHA512_DIGESTSTRINGLENGTH]);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SHA2_H */
diff --git a/lib/isc/include/isc/sockaddr.h b/lib/isc/include/isc/sockaddr.h
new file mode 100644
index 0000000..2cb8ef1
--- /dev/null
+++ b/lib/isc/include/isc/sockaddr.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: sockaddr.h,v 1.55 2007/06/18 23:47:44 tbox Exp $ */
+
+#ifndef ISC_SOCKADDR_H
+#define ISC_SOCKADDR_H 1
+
+/*! \file isc/sockaddr.h */
+
+#include <isc/lang.h>
+#include <isc/net.h>
+#include <isc/types.h>
+#ifdef ISC_PLATFORM_HAVESYSUNH
+#include <sys/un.h>
+#endif
+
+struct isc_sockaddr {
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ struct sockaddr_un sunix;
+#endif
+ } type;
+ unsigned int length; /* XXXRTH beginning? */
+ ISC_LINK(struct isc_sockaddr) link;
+};
+
+typedef ISC_LIST(struct isc_sockaddr) isc_sockaddrlist_t;
+
+#define ISC_SOCKADDR_CMPADDR 0x0001 /*%< compare the address
+ * sin_addr/sin6_addr */
+#define ISC_SOCKADDR_CMPPORT 0x0002 /*%< compare the port
+ * sin_port/sin6_port */
+#define ISC_SOCKADDR_CMPSCOPE 0x0004 /*%< compare the scope
+ * sin6_scope */
+#define ISC_SOCKADDR_CMPSCOPEZERO 0x0008 /*%< when comparing scopes
+ * zero scopes always match */
+
+ISC_LANG_BEGINDECLS
+
+isc_boolean_t
+isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
+ unsigned int flags);
+/*%<
+ * Compare the elements of the two address ('a' and 'b') as specified
+ * by 'flags' and report if they are equal or not.
+ *
+ * 'flags' is set from ISC_SOCKADDR_CMP*.
+ */
+
+isc_boolean_t
+isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b);
+/*%<
+ * Return ISC_TRUE iff the socket addresses 'a' and 'b' are equal.
+ */
+
+isc_boolean_t
+isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b);
+/*%<
+ * Return ISC_TRUE iff the address parts of the socket addresses
+ * 'a' and 'b' are equal, ignoring the ports.
+ */
+
+isc_boolean_t
+isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
+ unsigned int prefixlen);
+/*%<
+ * Return ISC_TRUE iff the most significant 'prefixlen' bits of the
+ * socket addresses 'a' and 'b' are equal, ignoring the ports.
+ * If 'b''s scope is zero then 'a''s scope will be ignored.
+ */
+
+unsigned int
+isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only);
+/*%<
+ * Return a hash value for the socket address 'sockaddr'. If 'address_only'
+ * is ISC_TRUE, the hash value will not depend on the port.
+ *
+ * IPv6 addresses containing mapped IPv4 addresses generate the same hash
+ * value as the equivalent IPv4 address.
+ */
+
+void
+isc_sockaddr_any(isc_sockaddr_t *sockaddr);
+/*%<
+ * Return the IPv4 wildcard address.
+ */
+
+void
+isc_sockaddr_any6(isc_sockaddr_t *sockaddr);
+/*%<
+ * Return the IPv6 wildcard address.
+ */
+
+void
+isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int family);
+/*%<
+ * Set '*sockaddr' to the wildcard address of protocol family
+ * 'family'.
+ *
+ * Requires:
+ * \li 'family' is AF_INET or AF_INET6.
+ */
+
+void
+isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
+ in_port_t port);
+/*%<
+ * Construct an isc_sockaddr_t from an IPv4 address and port.
+ */
+
+void
+isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
+ in_port_t port);
+/*%<
+ * Construct an isc_sockaddr_t from an IPv6 address and port.
+ */
+
+void
+isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
+ in_port_t port);
+/*%<
+ * Construct an IPv6 isc_sockaddr_t representing a mapped IPv4 address.
+ */
+
+void
+isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
+ in_port_t port);
+/*%<
+ * Construct an isc_sockaddr_t from an isc_netaddr_t and port.
+ */
+
+int
+isc_sockaddr_pf(const isc_sockaddr_t *sockaddr);
+/*%<
+ * Get the protocol family of 'sockaddr'.
+ *
+ * Requires:
+ *
+ *\li 'sockaddr' is a valid sockaddr with an address family of AF_INET
+ * or AF_INET6.
+ *
+ * Returns:
+ *
+ *\li The protocol family of 'sockaddr', e.g. PF_INET or PF_INET6.
+ */
+
+void
+isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port);
+/*%<
+ * Set the port of 'sockaddr' to 'port'.
+ */
+
+in_port_t
+isc_sockaddr_getport(const isc_sockaddr_t *sockaddr);
+/*%<
+ * Get the port stored in 'sockaddr'.
+ */
+
+isc_result_t
+isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target);
+/*%<
+ * Append a text representation of 'sockaddr' to the buffer 'target'.
+ * The text will include both the IP address (v4 or v6) and the port.
+ * The text is null terminated, but the terminating null is not
+ * part of the buffer's used region.
+ *
+ * Returns:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOSPACE The text or the null termination did not fit.
+ */
+
+void
+isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size);
+/*%<
+ * Format a human-readable representation of the socket address '*sa'
+ * into the character array 'array', which is of size 'size'.
+ * The resulting string is guaranteed to be null-terminated.
+ */
+
+isc_boolean_t
+isc_sockaddr_ismulticast(const isc_sockaddr_t *sa);
+/*%<
+ * Returns #ISC_TRUE if the address is a multicast address.
+ */
+
+isc_boolean_t
+isc_sockaddr_isexperimental(const isc_sockaddr_t *sa);
+/*
+ * Returns ISC_TRUE if the address is a experimental (CLASS E) address.
+ */
+
+isc_boolean_t
+isc_sockaddr_islinklocal(const isc_sockaddr_t *sa);
+/*%<
+ * Returns ISC_TRUE if the address is a link local addresss.
+ */
+
+isc_boolean_t
+isc_sockaddr_issitelocal(const isc_sockaddr_t *sa);
+/*%<
+ * Returns ISC_TRUE if the address is a sitelocal address.
+ */
+
+isc_result_t
+isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path);
+/*
+ * Create a UNIX domain sockaddr that refers to path.
+ *
+ * Returns:
+ * \li ISC_R_NOSPACE
+ * \li ISC_R_NOTIMPLEMENTED
+ * \li ISC_R_SUCCESS
+ */
+
+#define ISC_SOCKADDR_FORMATSIZE \
+ sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX%SSSSSSSSSS#YYYYY")
+/*%<
+ * Minimum size of array to pass to isc_sockaddr_format().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SOCKADDR_H */
diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h
new file mode 100644
index 0000000..b4c8c87
--- /dev/null
+++ b/lib/isc/include/isc/socket.h
@@ -0,0 +1,925 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: socket.h,v 1.85 2008/09/04 07:46:02 marka Exp $ */
+
+#ifndef ISC_SOCKET_H
+#define ISC_SOCKET_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/socket.h
+ * \brief Provides TCP and UDP sockets for network I/O. The sockets are event
+ * sources in the task system.
+ *
+ * When I/O completes, a completion event for the socket is posted to the
+ * event queue of the task which requested the I/O.
+ *
+ * \li MP:
+ * The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ * Clients of this module must not be holding a socket's task's lock when
+ * making a call that affects that socket. Failure to follow this rule
+ * can result in deadlock.
+ * The caller must ensure that isc_socketmgr_destroy() is called only
+ * once for a given manager.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/time.h>
+#include <isc/region.h>
+#include <isc/sockaddr.h>
+#include <isc/xml.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Constants
+ ***/
+
+/*%
+ * Maximum number of buffers in a scatter/gather read/write. The operating
+ * system in use must support at least this number (plus one on some.)
+ */
+#define ISC_SOCKET_MAXSCATTERGATHER 8
+
+/*%
+ * In isc_socket_bind() set socket option SO_REUSEADDR prior to calling
+ * bind() if a non zero port is specified (AF_INET and AF_INET6).
+ */
+#define ISC_SOCKET_REUSEADDRESS 0x01U
+
+/***
+ *** Types
+ ***/
+
+struct isc_socketevent {
+ ISC_EVENT_COMMON(isc_socketevent_t);
+ isc_result_t result; /*%< OK, EOF, whatever else */
+ unsigned int minimum; /*%< minimum i/o for event */
+ unsigned int n; /*%< bytes read or written */
+ unsigned int offset; /*%< offset into buffer list */
+ isc_region_t region; /*%< for single-buffer i/o */
+ isc_bufferlist_t bufferlist; /*%< list of buffers */
+ isc_sockaddr_t address; /*%< source address */
+ isc_time_t timestamp; /*%< timestamp of packet recv */
+ struct in6_pktinfo pktinfo; /*%< ipv6 pktinfo */
+ isc_uint32_t attributes; /*%< see below */
+ isc_eventdestructor_t destroy; /*%< original destructor */
+};
+
+typedef struct isc_socket_newconnev isc_socket_newconnev_t;
+struct isc_socket_newconnev {
+ ISC_EVENT_COMMON(isc_socket_newconnev_t);
+ isc_socket_t * newsocket;
+ isc_result_t result; /*%< OK, EOF, whatever else */
+ isc_sockaddr_t address; /*%< source address */
+};
+
+typedef struct isc_socket_connev isc_socket_connev_t;
+struct isc_socket_connev {
+ ISC_EVENT_COMMON(isc_socket_connev_t);
+ isc_result_t result; /*%< OK, EOF, whatever else */
+};
+
+/*@{*/
+/*!
+ * _ATTACHED: Internal use only.
+ * _TRUNC: Packet was truncated on receive.
+ * _CTRUNC: Packet control information was truncated. This can
+ * indicate that the packet is not complete, even though
+ * all the data is valid.
+ * _TIMESTAMP: The timestamp member is valid.
+ * _PKTINFO: The pktinfo member is valid.
+ * _MULTICAST: The UDP packet was received via a multicast transmission.
+ */
+#define ISC_SOCKEVENTATTR_ATTACHED 0x80000000U /* internal */
+#define ISC_SOCKEVENTATTR_TRUNC 0x00800000U /* public */
+#define ISC_SOCKEVENTATTR_CTRUNC 0x00400000U /* public */
+#define ISC_SOCKEVENTATTR_TIMESTAMP 0x00200000U /* public */
+#define ISC_SOCKEVENTATTR_PKTINFO 0x00100000U /* public */
+#define ISC_SOCKEVENTATTR_MULTICAST 0x00080000U /* public */
+/*@}*/
+
+#define ISC_SOCKEVENT_ANYEVENT (0)
+#define ISC_SOCKEVENT_RECVDONE (ISC_EVENTCLASS_SOCKET + 1)
+#define ISC_SOCKEVENT_SENDDONE (ISC_EVENTCLASS_SOCKET + 2)
+#define ISC_SOCKEVENT_NEWCONN (ISC_EVENTCLASS_SOCKET + 3)
+#define ISC_SOCKEVENT_CONNECT (ISC_EVENTCLASS_SOCKET + 4)
+
+/*
+ * Internal events.
+ */
+#define ISC_SOCKEVENT_INTR (ISC_EVENTCLASS_SOCKET + 256)
+#define ISC_SOCKEVENT_INTW (ISC_EVENTCLASS_SOCKET + 257)
+
+typedef enum {
+ isc_sockettype_udp = 1,
+ isc_sockettype_tcp = 2,
+ isc_sockettype_unix = 3,
+ isc_sockettype_fdwatch = 4
+} isc_sockettype_t;
+
+/*@{*/
+/*!
+ * How a socket should be shutdown in isc_socket_shutdown() calls.
+ */
+#define ISC_SOCKSHUT_RECV 0x00000001 /*%< close read side */
+#define ISC_SOCKSHUT_SEND 0x00000002 /*%< close write side */
+#define ISC_SOCKSHUT_ALL 0x00000003 /*%< close them all */
+/*@}*/
+
+/*@{*/
+/*!
+ * What I/O events to cancel in isc_socket_cancel() calls.
+ */
+#define ISC_SOCKCANCEL_RECV 0x00000001 /*%< cancel recv */
+#define ISC_SOCKCANCEL_SEND 0x00000002 /*%< cancel send */
+#define ISC_SOCKCANCEL_ACCEPT 0x00000004 /*%< cancel accept */
+#define ISC_SOCKCANCEL_CONNECT 0x00000008 /*%< cancel connect */
+#define ISC_SOCKCANCEL_ALL 0x0000000f /*%< cancel everything */
+/*@}*/
+
+/*@{*/
+/*!
+ * Flags for isc_socket_send() and isc_socket_recv() calls.
+ */
+#define ISC_SOCKFLAG_IMMEDIATE 0x00000001 /*%< send event only if needed */
+#define ISC_SOCKFLAG_NORETRY 0x00000002 /*%< drop failed UDP sends */
+/*@}*/
+
+/*@{*/
+/*!
+ * Flags for fdwatchcreate.
+ */
+#define ISC_SOCKFDWATCH_READ 0x00000001 /*%< watch for readable */
+#define ISC_SOCKFDWATCH_WRITE 0x00000002 /*%< watch for writable */
+/*@}*/
+
+/***
+ *** Socket and Socket Manager Functions
+ ***
+ *** Note: all Ensures conditions apply only if the result is success for
+ *** those functions which return an isc_result.
+ ***/
+
+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);
+/*%<
+ * Create a new file descriptor watch socket managed by 'manager'.
+ *
+ * Note:
+ *
+ *\li 'fd' is the already-opened file descriptor.
+ *\li This function is not available on Windows.
+ *\li The callback function is called "in-line" - this means the function
+ * needs to return as fast as possible, as all other I/O will be suspended
+ * until the callback completes.
+ *
+ * Requires:
+ *
+ *\li 'manager' is a valid manager
+ *
+ *\li 'socketp' is a valid pointer, and *socketp == NULL
+ *
+ *\li 'fd' be opened.
+ *
+ * Ensures:
+ *
+ * '*socketp' is attached to the newly created fdwatch socket
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_NORESOURCES
+ *\li #ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_create(isc_socketmgr_t *manager,
+ int pf,
+ isc_sockettype_t type,
+ isc_socket_t **socketp);
+/*%<
+ * Create a new 'type' socket managed by 'manager'.
+ *
+ * For isc_sockettype_fdwatch sockets you should use isc_socket_fdwatchcreate()
+ * rather than isc_socket_create().
+ *
+ * Note:
+ *
+ *\li 'pf' is the desired protocol family, e.g. PF_INET or PF_INET6.
+ *
+ * Requires:
+ *
+ *\li 'manager' is a valid manager
+ *
+ *\li 'socketp' is a valid pointer, and *socketp == NULL
+ *
+ *\li 'type' is not isc_sockettype_fdwatch
+ *
+ * Ensures:
+ *
+ * '*socketp' is attached to the newly created socket
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_NORESOURCES
+ *\li #ISC_R_UNEXPECTED
+ */
+
+void
+isc_socket_cancel(isc_socket_t *sock, isc_task_t *task,
+ unsigned int how);
+/*%<
+ * Cancel pending I/O of the type specified by "how".
+ *
+ * Note: if "task" is NULL, then the cancel applies to all tasks using the
+ * socket.
+ *
+ * Requires:
+ *
+ * \li "socket" is a valid socket
+ *
+ * \li "task" is NULL or a valid task
+ *
+ * "how" is a bitmask describing the type of cancelation to perform.
+ * The type ISC_SOCKCANCEL_ALL will cancel all pending I/O on this
+ * socket.
+ *
+ * \li ISC_SOCKCANCEL_RECV:
+ * Cancel pending isc_socket_recv() calls.
+ *
+ * \li ISC_SOCKCANCEL_SEND:
+ * Cancel pending isc_socket_send() and isc_socket_sendto() calls.
+ *
+ * \li ISC_SOCKCANCEL_ACCEPT:
+ * Cancel pending isc_socket_accept() calls.
+ *
+ * \li ISC_SOCKCANCEL_CONNECT:
+ * Cancel pending isc_socket_connect() call.
+ */
+
+void
+isc_socket_shutdown(isc_socket_t *sock, unsigned int how);
+/*%<
+ * Shutdown 'socket' according to 'how'.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid socket.
+ *
+ * \li 'task' is NULL or is a valid task.
+ *
+ * \li If 'how' is 'ISC_SOCKSHUT_RECV' or 'ISC_SOCKSHUT_ALL' then
+ *
+ * The read queue must be empty.
+ *
+ * No further read requests may be made.
+ *
+ * \li If 'how' is 'ISC_SOCKSHUT_SEND' or 'ISC_SOCKSHUT_ALL' then
+ *
+ * The write queue must be empty.
+ *
+ * No further write requests may be made.
+ */
+
+void
+isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp);
+/*%<
+ * Attach *socketp to socket.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid socket.
+ *
+ * \li 'socketp' points to a NULL socket.
+ *
+ * Ensures:
+ *
+ * \li *socketp is attached to socket.
+ */
+
+void
+isc_socket_detach(isc_socket_t **socketp);
+/*%<
+ * Detach *socketp from its socket.
+ *
+ * Requires:
+ *
+ * \li 'socketp' points to a valid socket.
+ *
+ * \li If '*socketp' is the last reference to the socket,
+ * then:
+ *
+ * There must be no pending I/O requests.
+ *
+ * Ensures:
+ *
+ * \li *socketp is NULL.
+ *
+ * \li If '*socketp' is the last reference to the socket,
+ * then:
+ *
+ * The socket will be shutdown (both reading and writing)
+ * for all tasks.
+ *
+ * All resources used by the socket have been freed
+ */
+
+isc_result_t
+isc_socket_open(isc_socket_t *sock);
+/*%<
+ * Open a new socket file descriptor of the given socket structure. It simply
+ * opens a new descriptor; all of the other parameters including the socket
+ * type are inherited from the existing socket. This function is provided to
+ * avoid overhead of destroying and creating sockets when many short-lived
+ * sockets are frequently opened and closed. When the efficiency is not an
+ * issue, it should be safer to detach the unused socket and re-create a new
+ * one. This optimization may not be available for some systems, in which
+ * case this function will return ISC_R_NOTIMPLEMENTED and must not be used.
+ *
+ * isc_socket_open() should not be called on sockets created by
+ * isc_socket_fdwatchcreate().
+ *
+ * Requires:
+ *
+ * \li there must be no other reference to this socket.
+ *
+ * \li 'socket' is a valid and previously closed by isc_socket_close()
+ *
+ * \li 'sock->type' is not isc_sockettype_fdwatch
+ *
+ * Returns:
+ * Same as isc_socket_create().
+ * \li ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socket_close(isc_socket_t *sock);
+/*%<
+ * Close a socket file descriptor of the given socket structure. This function
+ * is provided as an alternative to destroying an unused socket when overhead
+ * destroying/re-creating sockets can be significant, and is expected to be
+ * used with isc_socket_open(). This optimization may not be available for some
+ * systems, in which case this function will return ISC_R_NOTIMPLEMENTED and
+ * must not be used.
+ *
+ * isc_socket_close() should not be called on sockets created by
+ * isc_socket_fdwatchcreate().
+ *
+ * Requires:
+ *
+ * \li The socket must have a valid descriptor.
+ *
+ * \li There must be no other reference to this socket.
+ *
+ * \li There must be no pending I/O requests.
+ *
+ * \li 'sock->type' is not isc_sockettype_fdwatch
+ *
+ * Returns:
+ * \li #ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *addressp,
+ unsigned int options);
+/*%<
+ * Bind 'socket' to '*addressp'.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid socket
+ *
+ * \li 'addressp' points to a valid isc_sockaddr.
+ *
+ * Returns:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOPERM
+ * \li ISC_R_ADDRNOTAVAIL
+ * \li ISC_R_ADDRINUSE
+ * \li ISC_R_BOUND
+ * \li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_filter(isc_socket_t *sock, const char *filter);
+/*%<
+ * Inform the kernel that it should perform accept filtering.
+ * If filter is NULL the current filter will be removed.:w
+ */
+
+isc_result_t
+isc_socket_listen(isc_socket_t *sock, unsigned int backlog);
+/*%<
+ * Set listen mode on the socket. After this call, the only function that
+ * can be used (other than attach and detach) is isc_socket_accept().
+ *
+ * Notes:
+ *
+ * \li 'backlog' is as in the UNIX system call listen() and may be
+ * ignored by non-UNIX implementations.
+ *
+ * \li If 'backlog' is zero, a reasonable system default is used, usually
+ * SOMAXCONN.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid, bound TCP socket or a valid, bound UNIX socket.
+ *
+ * Returns:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_accept(isc_socket_t *sock,
+ isc_task_t *task, isc_taskaction_t action, const void *arg);
+/*%<
+ * Queue accept event. When a new connection is received, the task will
+ * get an ISC_SOCKEVENT_NEWCONN event with the sender set to the listen
+ * socket. The new socket structure is sent inside the isc_socket_newconnev_t
+ * event type, and is attached to the task 'task'.
+ *
+ * REQUIRES:
+ * \li 'socket' is a valid TCP socket that isc_socket_listen() was called
+ * on.
+ *
+ * \li 'task' is a valid task
+ *
+ * \li 'action' is a valid action
+ *
+ * RETURNS:
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOMEMORY
+ * \li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addressp,
+ isc_task_t *task, isc_taskaction_t action,
+ const void *arg);
+/*%<
+ * Connect 'socket' to peer with address *saddr. When the connection
+ * succeeds, or when an error occurs, a CONNECT event with action 'action'
+ * and arg 'arg' will be posted to the event queue for 'task'.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid TCP socket
+ *
+ * \li 'addressp' points to a valid isc_sockaddr
+ *
+ * \li 'task' is a valid task
+ *
+ * \li 'action' is a valid action
+ *
+ * Returns:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_NOMEMORY
+ * \li ISC_R_UNEXPECTED
+ *
+ * Posted event's result code:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_TIMEDOUT
+ * \li ISC_R_CONNREFUSED
+ * \li ISC_R_NETUNREACH
+ * \li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp);
+/*%<
+ * Get the name of the peer connected to 'socket'.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid TCP socket.
+ *
+ * Returns:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_TOOSMALL
+ * \li ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp);
+/*%<
+ * Get the name of 'socket'.
+ *
+ * Requires:
+ *
+ * \li 'socket' is a valid socket.
+ *
+ * Returns:
+ *
+ * \li ISC_R_SUCCESS
+ * \li ISC_R_TOOSMALL
+ * \li ISC_R_UNEXPECTED
+ */
+
+/*@{*/
+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_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_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);
+
+/*!
+ * Receive from 'socket', storing the results in region.
+ *
+ * Notes:
+ *
+ *\li Let 'length' refer to the length of 'region' or to the sum of all
+ * available regions in the list of buffers '*buflist'.
+ *
+ *\li If 'minimum' is non-zero and at least that many bytes are read,
+ * the completion event will be posted to the task 'task.' If minimum
+ * is zero, the exact number of bytes requested in the region must
+ * be read for an event to be posted. This only makes sense for TCP
+ * connections, and is always set to 1 byte for UDP.
+ *
+ *\li The read will complete when the desired number of bytes have been
+ * read, if end-of-input occurs, or if an error occurs. A read done
+ * event with the given 'action' and 'arg' will be posted to the
+ * event queue of 'task'.
+ *
+ *\li The caller may not modify 'region', the buffers which are passed
+ * into this function, or any data they refer to until the completion
+ * event is received.
+ *
+ *\li For isc_socket_recvv():
+ * On successful completion, '*buflist' will be empty, and the list of
+ * all buffers will be returned in the done event's 'bufferlist'
+ * member. On error return, '*buflist' will be unchanged.
+ *
+ *\li For isc_socket_recv2():
+ * 'event' is not NULL, and the non-socket specific fields are
+ * expected to be initialized.
+ *
+ *\li For isc_socket_recv2():
+ * The only defined value for 'flags' is ISC_SOCKFLAG_IMMEDIATE. If
+ * set and the operation completes, the return value will be
+ * ISC_R_SUCCESS and the event will be filled in and not sent. If the
+ * operation does not complete, the return value will be
+ * ISC_R_INPROGRESS and the event will be sent when the operation
+ * completes.
+ *
+ * Requires:
+ *
+ *\li 'socket' is a valid, bound socket.
+ *
+ *\li For isc_socket_recv():
+ * 'region' is a valid region
+ *
+ *\li For isc_socket_recvv():
+ * 'buflist' is non-NULL, and '*buflist' contain at least one buffer.
+ *
+ *\li 'task' is a valid task
+ *
+ *\li For isc_socket_recv() and isc_socket_recvv():
+ * action != NULL and is a valid action
+ *
+ *\li For isc_socket_recv2():
+ * event != NULL
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_INPROGRESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ *
+ * Event results:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_UNEXPECTED
+ *\li XXX needs other net-type errors
+ */
+/*@}*/
+
+/*@{*/
+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_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_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_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_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);
+
+/*!
+ * Send the contents of 'region' to the socket's peer.
+ *
+ * Notes:
+ *
+ *\li Shutting down the requestor's task *may* result in any
+ * still pending writes being dropped or completed, depending on the
+ * underlying OS implementation.
+ *
+ *\li If 'action' is NULL, then no completion event will be posted.
+ *
+ *\li The caller may not modify 'region', the buffers which are passed
+ * into this function, or any data they refer to until the completion
+ * event is received.
+ *
+ *\li For isc_socket_sendv() and isc_socket_sendtov():
+ * On successful completion, '*buflist' will be empty, and the list of
+ * all buffers will be returned in the done event's 'bufferlist'
+ * member. On error return, '*buflist' will be unchanged.
+ *
+ *\li For isc_socket_sendto2():
+ * 'event' is not NULL, and the non-socket specific fields are
+ * expected to be initialized.
+ *
+ *\li For isc_socket_sendto2():
+ * The only defined values for 'flags' are ISC_SOCKFLAG_IMMEDIATE
+ * and ISC_SOCKFLAG_NORETRY.
+ *
+ *\li If ISC_SOCKFLAG_IMMEDIATE is set and the operation completes, the
+ * return value will be ISC_R_SUCCESS and the event will be filled
+ * in and not sent. If the operation does not complete, the return
+ * value will be ISC_R_INPROGRESS and the event will be sent when
+ * the operation completes.
+ *
+ *\li ISC_SOCKFLAG_NORETRY can only be set for UDP sockets. If set
+ * and the send operation fails due to a transient error, the send
+ * will not be retried and the error will be indicated in the event.
+ * Using this option along with ISC_SOCKFLAG_IMMEDIATE allows the caller
+ * to specify a region that is allocated on the stack.
+ *
+ * Requires:
+ *
+ *\li 'socket' is a valid, bound socket.
+ *
+ *\li For isc_socket_send():
+ * 'region' is a valid region
+ *
+ *\li For isc_socket_sendv() and isc_socket_sendtov():
+ * 'buflist' is non-NULL, and '*buflist' contain at least one buffer.
+ *
+ *\li 'task' is a valid task
+ *
+ *\li For isc_socket_sendv(), isc_socket_sendtov(), isc_socket_send(), and
+ * isc_socket_sendto():
+ * action == NULL or is a valid action
+ *
+ *\li For isc_socket_sendto2():
+ * event != NULL
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_INPROGRESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ *
+ * Event results:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_UNEXPECTED
+ *\li XXX needs other net-type errors
+ */
+/*@}*/
+
+isc_result_t
+isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+
+isc_result_t
+isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+ unsigned int maxsocks);
+/*%<
+ * Create a socket manager. If "maxsocks" is non-zero, it specifies the
+ * maximum number of sockets that the created manager should handle.
+ * isc_socketmgr_create() is equivalent of isc_socketmgr_create2() with
+ * "maxsocks" being zero.
+ *
+ * Notes:
+ *
+ *\li All memory will be allocated in memory context 'mctx'.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'managerp' points to a NULL isc_socketmgr_t.
+ *
+ * Ensures:
+ *
+ *\li '*managerp' is a valid isc_socketmgr_t.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ *\li #ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp);
+/*%<
+ * Returns in "*nsockp" the maximum number of sockets this manager may open.
+ *
+ * Requires:
+ *
+ *\li '*manager' is a valid isc_socketmgr_t.
+ *\li 'nsockp' is not NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOTIMPLEMENTED
+ */
+
+void
+isc_socketmgr_destroy(isc_socketmgr_t **managerp);
+/*%<
+ * Destroy a socket manager.
+ *
+ * Notes:
+ *
+ *\li This routine blocks until there are no sockets left in the manager,
+ * so if the caller holds any socket references using the manager, it
+ * must detach them before calling isc_socketmgr_destroy() or it will
+ * block forever.
+ *
+ * Requires:
+ *
+ *\li '*managerp' is a valid isc_socketmgr_t.
+ *
+ *\li All sockets managed by this manager are fully detached.
+ *
+ * Ensures:
+ *
+ *\li *managerp == NULL
+ *
+ *\li All resources used by the manager have been freed.
+ */
+
+isc_sockettype_t
+isc_socket_gettype(isc_socket_t *sock);
+/*%<
+ * Returns the socket type for "sock."
+ *
+ * Requires:
+ *
+ *\li "sock" is a valid socket.
+ */
+
+/*@{*/
+isc_boolean_t
+isc_socket_isbound(isc_socket_t *sock);
+
+void
+isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes);
+/*%<
+ * If the socket is an IPv6 socket set/clear the IPV6_IPV6ONLY socket
+ * option if the host OS supports this option.
+ *
+ * Requires:
+ *\li 'sock' is a valid socket.
+ */
+/*@}*/
+
+void
+isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active);
+
+/*%<
+ * Cleanup UNIX domain sockets in the file-system. If 'active' is true
+ * then just unlink the socket. If 'active' is false try to determine
+ * if there is a listener of the socket or not. If no listener is found
+ * then unlink socket.
+ *
+ * Prior to unlinking the path is tested to see if it a socket.
+ *
+ * Note: there are a number of race conditions which cannot be avoided
+ * both in the filesystem and any application using UNIX domain
+ * sockets (e.g. socket is tested between bind() and listen(),
+ * the socket is deleted and replaced in the file-system between
+ * stat() and unlink()).
+ */
+
+isc_result_t
+isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
+ isc_uint32_t owner, isc_uint32_t group);
+/*%<
+ * Set ownership and file permissions on the UNIX domain socket.
+ *
+ * Note: On Solaris and SunOS this secures the directory containing
+ * the socket as Solaris and SunOS do not honour the filesytem
+ * permissions on the socket.
+ *
+ * Requires:
+ * \li 'sockaddr' to be a valid UNIX domain sockaddr.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_FAILURE
+ */
+
+void isc_socket_setname(isc_socket_t *socket, const char *name, void *tag);
+/*%<
+ * Set the name and optional tag for a socket. This allows tracking of the
+ * owner or purpose for this socket, and is useful for tracing and statistics
+ * reporting.
+ */
+
+const char *isc_socket_getname(isc_socket_t *socket);
+/*%<
+ * Get the name associated with a socket, if any.
+ */
+
+void *isc_socket_gettag(isc_socket_t *socket);
+/*%<
+ * Get the tag associated with a socket, if any.
+ */
+
+void
+isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t);
+/*%<
+ * Temporary. For use by named only.
+ */
+
+#ifdef HAVE_LIBXML2
+
+void
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer);
+/*%<
+ * Render internal statistics and other state into the XML document.
+ */
+
+#endif /* HAVE_LIBXML2 */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SOCKET_H */
diff --git a/lib/isc/include/isc/stdio.h b/lib/isc/include/isc/stdio.h
new file mode 100644
index 0000000..1a7ae64
--- /dev/null
+++ b/lib/isc/include/isc/stdio.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2004-2007 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: stdio.h,v 1.13 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_STDIO_H
+#define ISC_STDIO_H 1
+
+/*! \file isc/stdio.h */
+
+/*%
+ * These functions are wrappers around the corresponding stdio functions.
+ *
+ * They return a detailed error code in the form of an an isc_result_t. ANSI C
+ * does not guarantee that stdio functions set errno, hence these functions
+ * must use platform dependent methods (e.g., the POSIX errno) to construct the
+ * error code.
+ */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+/*% Open */
+isc_result_t
+isc_stdio_open(const char *filename, const char *mode, FILE **fp);
+
+/*% Close */
+isc_result_t
+isc_stdio_close(FILE *f);
+
+/*% Seek */
+isc_result_t
+isc_stdio_seek(FILE *f, long offset, int whence);
+
+/*% Read */
+isc_result_t
+isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f,
+ size_t *nret);
+
+/*% Write */
+isc_result_t
+isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f,
+ size_t *nret);
+
+/*% Flush */
+isc_result_t
+isc_stdio_flush(FILE *f);
+
+isc_result_t
+isc_stdio_sync(FILE *f);
+/*%<
+ * Invoke fsync() on the file descriptor underlying an stdio stream, or an
+ * equivalent system-dependent operation. Note that this function has no
+ * direct counterpart in the stdio library.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STDIO_H */
diff --git a/lib/isc/include/isc/stdlib.h b/lib/isc/include/isc/stdlib.h
new file mode 100644
index 0000000..02243f0
--- /dev/null
+++ b/lib/isc/include/isc/stdlib.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: stdlib.h,v 1.8 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_STDLIB_H
+#define ISC_STDLIB_H 1
+
+/*! \file isc/stdlib.h */
+
+#include <stdlib.h>
+
+#include <isc/lang.h>
+#include <isc/platform.h>
+
+#ifdef ISC_PLATFORM_NEEDSTRTOUL
+#define strtoul isc_strtoul
+#endif
+
+ISC_LANG_BEGINDECLS
+
+unsigned long isc_strtoul(const char *, char **, int);
+
+ISC_LANG_ENDDECLS
+
+#endif
diff --git a/lib/isc/include/isc/string.h b/lib/isc/include/isc/string.h
new file mode 100644
index 0000000..b49fdbc
--- /dev/null
+++ b/lib/isc/include/isc/string.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2004-2007 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
+ * 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: string.h,v 1.23 2007/09/13 04:48:16 each Exp $ */
+
+#ifndef ISC_STRING_H
+#define ISC_STRING_H 1
+
+/*! \file isc/string.h */
+
+#include <isc/formatcheck.h>
+#include <isc/int.h>
+#include <isc/lang.h>
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#include <string.h>
+
+#ifdef ISC_PLATFORM_HAVESTRINGSH
+#include <strings.h>
+#endif
+
+#define ISC_STRING_MAGIC 0x5e
+
+ISC_LANG_BEGINDECLS
+
+isc_uint64_t
+isc_string_touint64(char *source, char **endp, int base);
+/*%<
+ * Convert the string pointed to by 'source' to isc_uint64_t.
+ *
+ * On successful conversion 'endp' points to the first character
+ * after conversion is complete.
+ *
+ * 'base': 0 or 2..36
+ *
+ * If base is 0 the base is computed from the string type.
+ *
+ * On error 'endp' points to 'source'.
+ */
+
+isc_result_t
+isc_string_copy(char *target, size_t size, const char *source);
+/*
+ * Copy the string pointed to by 'source' to 'target' which is a
+ * pointer to a string of at least 'size' bytes.
+ *
+ * Requires:
+ * 'target' is a pointer to a char[] of at least 'size' bytes.
+ * 'size' an integer > 0.
+ * 'source' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ * If result == ISC_R_SUCCESS
+ * 'target' will be a NUL terminated string of no more
+ * than 'size' bytes (including NUL).
+ *
+ * If result == ISC_R_NOSPACE
+ * 'target' is undefined.
+ *
+ * Returns:
+ * ISC_R_SUCCESS -- 'source' was successfully copied to 'target'.
+ * ISC_R_NOSPACE -- 'source' could not be copied since 'target'
+ * is too small.
+ */
+
+void
+isc_string_copy_truncate(char *target, size_t size, const char *source);
+/*
+ * Copy the string pointed to by 'source' to 'target' which is a
+ * pointer to a string of at least 'size' bytes.
+ *
+ * Requires:
+ * 'target' is a pointer to a char[] of at least 'size' bytes.
+ * 'size' an integer > 0.
+ * 'source' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ * 'target' will be a NUL terminated string of no more
+ * than 'size' bytes (including NUL).
+ */
+
+isc_result_t
+isc_string_append(char *target, size_t size, const char *source);
+/*
+ * Append the string pointed to by 'source' to 'target' which is a
+ * pointer to a NUL terminated string of at least 'size' bytes.
+ *
+ * Requires:
+ * 'target' is a pointer to a NUL terminated char[] of at
+ * least 'size' bytes.
+ * 'size' an integer > 0.
+ * 'source' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ * If result == ISC_R_SUCCESS
+ * 'target' will be a NUL terminated string of no more
+ * than 'size' bytes (including NUL).
+ *
+ * If result == ISC_R_NOSPACE
+ * 'target' is undefined.
+ *
+ * Returns:
+ * ISC_R_SUCCESS -- 'source' was successfully appended to 'target'.
+ * ISC_R_NOSPACE -- 'source' could not be appended since 'target'
+ * is too small.
+ */
+
+void
+isc_string_append_truncate(char *target, size_t size, const char *source);
+/*
+ * Append the string pointed to by 'source' to 'target' which is a
+ * pointer to a NUL terminated string of at least 'size' bytes.
+ *
+ * Requires:
+ * 'target' is a pointer to a NUL terminated char[] of at
+ * least 'size' bytes.
+ * 'size' an integer > 0.
+ * 'source' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ * 'target' will be a NUL terminated string of no more
+ * than 'size' bytes (including NUL).
+ */
+
+isc_result_t
+isc_string_printf(char *target, size_t size, const char *format, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+/*
+ * Print 'format' to 'target' which is a pointer to a string of at least
+ * 'size' bytes.
+ *
+ * Requires:
+ * 'target' is a pointer to a char[] of at least 'size' bytes.
+ * 'size' an integer > 0.
+ * 'format' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ * If result == ISC_R_SUCCESS
+ * 'target' will be a NUL terminated string of no more
+ * than 'size' bytes (including NUL).
+ *
+ * If result == ISC_R_NOSPACE
+ * 'target' is undefined.
+ *
+ * Returns:
+ * ISC_R_SUCCESS -- 'format' was successfully printed to 'target'.
+ * ISC_R_NOSPACE -- 'format' could not be printed to 'target' since it
+ * is too small.
+ */
+
+void
+isc_string_printf_truncate(char *target, size_t size, const char *format, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+/*
+ * Print 'format' to 'target' which is a pointer to a string of at least
+ * 'size' bytes.
+ *
+ * Requires:
+ * 'target' is a pointer to a char[] of at least 'size' bytes.
+ * 'size' an integer > 0.
+ * 'format' == NULL or points to a NUL terminated string.
+ *
+ * Ensures:
+ * 'target' will be a NUL terminated string of no more
+ * than 'size' bytes (including NUL).
+ */
+
+
+char *
+isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source);
+/*
+ * Copy the region pointed to by r to a NUL terminated string
+ * allocated from the memory context pointed to by mctx.
+ *
+ * The result should be deallocated using isc_mem_free()
+ *
+ * Requires:
+ * 'mctx' is a point to a valid memory context.
+ * 'source' is a pointer to a valid region.
+ *
+ * Returns:
+ * a pointer to a NUL terminated string or
+ * NULL if memory for the copy could not be allocated
+ *
+ */
+
+char *
+isc_string_separate(char **stringp, const char *delim);
+
+#ifdef ISC_PLATFORM_NEEDSTRSEP
+#define strsep isc_string_separate
+#endif
+
+#ifdef ISC_PLATFORM_NEEDMEMMOVE
+#define memmove(a,b,c) bcopy(b,a,c)
+#endif
+
+size_t
+isc_string_strlcpy(char *dst, const char *src, size_t size);
+
+
+#ifdef ISC_PLATFORM_NEEDSTRLCPY
+#define strlcpy isc_string_strlcpy
+#endif
+
+
+size_t
+isc_string_strlcat(char *dst, const char *src, size_t size);
+
+#ifdef ISC_PLATFORM_NEEDSTRLCAT
+#define strlcat isc_string_strlcat
+#endif
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STRING_H */
diff --git a/lib/isc/include/isc/symtab.h b/lib/isc/include/isc/symtab.h
new file mode 100644
index 0000000..5a398ad
--- /dev/null
+++ b/lib/isc/include/isc/symtab.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1996-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: symtab.h,v 1.24 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_SYMTAB_H
+#define ISC_SYMTAB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/symtab.h
+ * \brief Provides a simple memory-based symbol table.
+ *
+ * Keys are C strings, and key comparisons are case-insenstive. A type may
+ * be specified when looking up, defining, or undefining. A type value of
+ * 0 means "match any type"; any other value will only match the given
+ * type.
+ *
+ * It's possible that a client will attempt to define a <key, type, value>
+ * tuple when a tuple with the given key and type already exists in the table.
+ * What to do in this case is specified by the client. Possible policies are:
+ *
+ *\li #isc_symexists_reject Disallow the define, returning #ISC_R_EXISTS
+ *\li #isc_symexists_replace Replace the old value with the new. The
+ * undefine action (if provided) will be called
+ * with the old <key, type, value> tuple.
+ *\li #isc_symexists_add Add the new tuple, leaving the old tuple in
+ * the table. Subsequent lookups will retrieve
+ * the most-recently-defined tuple.
+ *
+ * A lookup of a key using type 0 will return the most-recently defined
+ * symbol with that key. An undefine of a key using type 0 will undefine the
+ * most-recently defined symbol with that key. Trying to define a key with
+ * type 0 is illegal.
+ *
+ * The symbol table library does not make a copy the key field, so the
+ * caller must ensure that any key it passes to isc_symtab_define() will not
+ * change until it calls isc_symtab_undefine() or isc_symtab_destroy().
+ *
+ * A user-specified action will be called (if provided) when a symbol is
+ * undefined. It can be used to free memory associated with keys and/or
+ * values.
+ *
+ * \li MP:
+ * The callers of this module must ensure any required synchronization.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/*
+ *** Symbol Tables.
+ ***/
+/*% Symbol table value. */
+typedef union isc_symvalue {
+ void * as_pointer;
+ const void * as_cpointer;
+ int as_integer;
+ unsigned int as_uinteger;
+} isc_symvalue_t;
+
+typedef void (*isc_symtabaction_t)(char *key, unsigned int type,
+ isc_symvalue_t value, void *userarg);
+/*% Symbol table exists. */
+typedef enum {
+ isc_symexists_reject = 0, /*%< Disallow the define */
+ isc_symexists_replace = 1, /*%< Replace the old value with the new */
+ isc_symexists_add = 2 /*%< Add the new tuple */
+} isc_symexists_t;
+
+ISC_LANG_BEGINDECLS
+
+/*% Create a symbol table. */
+isc_result_t
+isc_symtab_create(isc_mem_t *mctx, unsigned int size,
+ isc_symtabaction_t undefine_action, void *undefine_arg,
+ isc_boolean_t case_sensitive, isc_symtab_t **symtabp);
+
+/*% Destroy a symbol table. */
+void
+isc_symtab_destroy(isc_symtab_t **symtabp);
+
+/*% Lookup a symbol table. */
+isc_result_t
+isc_symtab_lookup(isc_symtab_t *symtab, const char *key, unsigned int type,
+ isc_symvalue_t *value);
+
+/*% Define a symbol table. */
+isc_result_t
+isc_symtab_define(isc_symtab_t *symtab, const char *key, unsigned int type,
+ isc_symvalue_t value, isc_symexists_t exists_policy);
+
+/*% Undefine a symbol table. */
+isc_result_t
+isc_symtab_undefine(isc_symtab_t *symtab, const char *key, unsigned int type);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SYMTAB_H */
diff --git a/lib/isc/include/isc/task.h b/lib/isc/include/isc/task.h
new file mode 100644
index 0000000..7c529b0
--- /dev/null
+++ b/lib/isc/include/isc/task.h
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2004-2007 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
+ * 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.h,v 1.61 2007/06/18 23:47:44 tbox Exp $ */
+
+#ifndef ISC_TASK_H
+#define ISC_TASK_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/task.h
+ * \brief The task system provides a lightweight execution context, which is
+ * basically an event queue.
+
+ * When a task's event queue is non-empty, the
+ * task is runnable. A small work crew of threads, typically one per CPU,
+ * execute runnable tasks by dispatching the events on the tasks' event
+ * queues. Context switching between tasks is fast.
+ *
+ * \li MP:
+ * The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ * The caller must ensure that isc_taskmgr_destroy() is called only
+ * once for a given manager.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ *
+ * \section purge Purging and Unsending
+ *
+ * Events which have been queued for a task but not delivered may be removed
+ * from the task's event queue by purging or unsending.
+ *
+ * With both types, the caller specifies a matching pattern that selects
+ * events based upon their sender, type, and tag.
+ *
+ * Purging calls isc_event_free() on the matching events.
+ *
+ * Unsending returns a list of events that matched the pattern.
+ * The caller is then responsible for them.
+ *
+ * Consumers of events should purge, not unsend.
+ *
+ * Producers of events often want to remove events when the caller indicates
+ * it is no longer interested in the object, e.g. by cancelling a timer.
+ * Sometimes this can be done by purging, but for some event types, the
+ * calls to isc_event_free() cause deadlock because the event free routine
+ * wants to acquire a lock the caller is already holding. Unsending instead
+ * of purging solves this problem. As a general rule, producers should only
+ * unsend events which they have sent.
+ */
+
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/eventclass.h>
+#include <isc/lang.h>
+#include <isc/stdtime.h>
+#include <isc/types.h>
+#include <isc/xml.h>
+
+#define ISC_TASKEVENT_FIRSTEVENT (ISC_EVENTCLASS_TASK + 0)
+#define ISC_TASKEVENT_SHUTDOWN (ISC_EVENTCLASS_TASK + 1)
+#define ISC_TASKEVENT_LASTEVENT (ISC_EVENTCLASS_TASK + 65535)
+
+/*****
+ ***** Tasks.
+ *****/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
+ isc_task_t **taskp);
+/*%<
+ * Create a task.
+ *
+ * Notes:
+ *
+ *\li If 'quantum' is non-zero, then only that many events can be dispatched
+ * before the task must yield to other tasks waiting to execute. If
+ * quantum is zero, then the default quantum of the task manager will
+ * be used.
+ *
+ *\li The 'quantum' option may be removed from isc_task_create() in the
+ * future. If this happens, isc_task_getquantum() and
+ * isc_task_setquantum() will be provided.
+ *
+ * Requires:
+ *
+ *\li 'manager' is a valid task manager.
+ *
+ *\li taskp != NULL && *taskp == NULL
+ *
+ * Ensures:
+ *
+ *\li On success, '*taskp' is bound to the new task.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ *\li #ISC_R_SHUTTINGDOWN
+ */
+
+void
+isc_task_attach(isc_task_t *source, isc_task_t **targetp);
+/*%<
+ * Attach *targetp to source.
+ *
+ * Requires:
+ *
+ *\li 'source' is a valid task.
+ *
+ *\li 'targetp' points to a NULL isc_task_t *.
+ *
+ * Ensures:
+ *
+ *\li *targetp is attached to source.
+ */
+
+void
+isc_task_detach(isc_task_t **taskp);
+/*%<
+ * Detach *taskp from its task.
+ *
+ * Requires:
+ *
+ *\li '*taskp' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li *taskp is NULL.
+ *
+ *\li If '*taskp' is the last reference to the task, the task is idle (has
+ * an empty event queue), and has not been shutdown, the task will be
+ * shutdown.
+ *
+ *\li If '*taskp' is the last reference to the task and
+ * the task has been shutdown,
+ * all resources used by the task will be freed.
+ */
+
+void
+isc_task_send(isc_task_t *task, isc_event_t **eventp);
+/*%<
+ * Send '*event' to 'task'.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *\li eventp != NULL && *eventp != NULL.
+ *
+ * Ensures:
+ *
+ *\li *eventp == NULL.
+ */
+
+void
+isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
+/*%<
+ * Send '*event' to '*taskp' and then detach '*taskp' from its
+ * task.
+ *
+ * Requires:
+ *
+ *\li '*taskp' is a valid task.
+ *\li eventp != NULL && *eventp != NULL.
+ *
+ * Ensures:
+ *
+ *\li *eventp == NULL.
+ *
+ *\li *taskp == NULL.
+ *
+ *\li If '*taskp' is the last reference to the task, the task is
+ * idle (has an empty event queue), and has not been shutdown,
+ * the task will be shutdown.
+ *
+ *\li If '*taskp' is the last reference to the task and
+ * the task has been shutdown,
+ * all resources used by the task will be freed.
+ */
+
+
+unsigned int
+isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
+ isc_eventtype_t last, void *tag);
+/*%<
+ * Purge events from a task's event queue.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li last >= first
+ *
+ * Ensures:
+ *
+ *\li Events in the event queue of 'task' whose sender is 'sender', whose
+ * type is >= first and <= last, and whose tag is 'tag' will be purged,
+ * unless they are marked as unpurgable.
+ *
+ *\li A sender of NULL will match any sender. A NULL tag matches any
+ * tag.
+ *
+ * Returns:
+ *
+ *\li The number of events purged.
+ */
+
+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.
+ *
+ * Notes:
+ *
+ *\li This function is equivalent to
+ *
+ *\code
+ * isc_task_purgerange(task, sender, type, type, tag);
+ *\endcode
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li Events in the event queue of 'task' whose sender is 'sender', whose
+ * type is 'type', and whose tag is 'tag' will be purged, unless they
+ * are marked as unpurgable.
+ *
+ *\li A sender of NULL will match any sender. A NULL tag matches any
+ * tag.
+ *
+ * Returns:
+ *
+ *\li The number of events purged.
+ */
+
+isc_boolean_t
+isc_task_purgeevent(isc_task_t *task, isc_event_t *event);
+/*%<
+ * Purge 'event' from a task's event queue.
+ *
+ * XXXRTH: WARNING: This method may be removed before beta.
+ *
+ * Notes:
+ *
+ *\li If 'event' is on the task's event queue, it will be purged,
+ * unless it is marked as unpurgeable. 'event' does not have to be
+ * on the task's event queue; in fact, it can even be an invalid
+ * pointer. Purging only occurs if the event is actually on the task's
+ * event queue.
+ *
+ * \li Purging never changes the state of the task.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li 'event' is not in the event queue for 'task'.
+ *
+ * Returns:
+ *
+ *\li #ISC_TRUE The event was purged.
+ *\li #ISC_FALSE The event was not in the event queue,
+ * or was marked unpurgeable.
+ */
+
+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.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li last >= first.
+ *
+ *\li *events is a valid list.
+ *
+ * Ensures:
+ *
+ *\li Events in the event queue of 'task' whose sender is 'sender', whose
+ * type is >= first and <= last, and whose tag is 'tag' will be dequeued
+ * and appended to *events.
+ *
+ *\li A sender of NULL will match any sender. A NULL tag matches any
+ * tag.
+ *
+ * Returns:
+ *
+ *\li The number of events unsent.
+ */
+
+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.
+ *
+ * Notes:
+ *
+ *\li This function is equivalent to
+ *
+ *\code
+ * isc_task_unsendrange(task, sender, type, type, tag, events);
+ *\endcode
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li *events is a valid list.
+ *
+ * Ensures:
+ *
+ *\li Events in the event queue of 'task' whose sender is 'sender', whose
+ * type is 'type', and whose tag is 'tag' will be dequeued and appended
+ * to *events.
+ *
+ * Returns:
+ *
+ *\li The number of events unsent.
+ */
+
+isc_result_t
+isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action,
+ const void *arg);
+/*%<
+ * Send a shutdown event with action 'action' and argument 'arg' when
+ * 'task' is shutdown.
+ *
+ * Notes:
+ *
+ *\li Shutdown events are posted in LIFO order.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ *\li 'action' is a valid task action.
+ *
+ * Ensures:
+ *
+ *\li When the task is shutdown, shutdown events requested with
+ * isc_task_onshutdown() will be appended to the task's event queue.
+ *
+
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_TASKSHUTTINGDOWN Task is shutting down.
+ */
+
+void
+isc_task_shutdown(isc_task_t *task);
+/*%<
+ * Shutdown 'task'.
+ *
+ * Notes:
+ *
+ *\li Shutting down a task causes any shutdown events requested with
+ * isc_task_onshutdown() to be posted (in LIFO order). The task
+ * moves into a "shutting down" mode which prevents further calls
+ * to isc_task_onshutdown().
+ *
+ *\li Trying to shutdown a task that has already been shutdown has no
+ * effect.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li Any shutdown events requested with isc_task_onshutdown() have been
+ * posted (in LIFO order).
+ */
+
+void
+isc_task_destroy(isc_task_t **taskp);
+/*%<
+ * Destroy '*taskp'.
+ *
+ * Notes:
+ *
+ *\li This call is equivalent to:
+ *
+ *\code
+ * isc_task_shutdown(*taskp);
+ * isc_task_detach(taskp);
+ *\endcode
+ *
+ * Requires:
+ *
+ * '*taskp' is a valid task.
+ *
+ * Ensures:
+ *
+ *\li Any shutdown events requested with isc_task_onshutdown() have been
+ * posted (in LIFO order).
+ *
+ *\li *taskp == NULL
+ *
+ *\li If '*taskp' is the last reference to the task,
+ * all resources used by the task will be freed.
+ */
+
+void
+isc_task_setname(isc_task_t *task, const char *name, void *tag);
+/*%<
+ * Name 'task'.
+ *
+ * Notes:
+ *
+ *\li Only the first 15 characters of 'name' will be copied.
+ *
+ *\li Naming a task is currently only useful for debugging purposes.
+ *
+ * Requires:
+ *
+ *\li 'task' is a valid task.
+ */
+
+const char *
+isc_task_getname(isc_task_t *task);
+/*%<
+ * Get the name of 'task', as previously set using isc_task_setname().
+ *
+ * Notes:
+ *\li This function is for debugging purposes only.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ *
+ * Returns:
+ *\li A non-NULL pointer to a null-terminated string.
+ * If the task has not been named, the string is
+ * empty.
+ *
+ */
+
+void *
+isc_task_gettag(isc_task_t *task);
+/*%<
+ * Get the tag value for 'task', as previously set using isc_task_settag().
+ *
+ * Notes:
+ *\li This function is for debugging purposes only.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ */
+
+isc_result_t
+isc_task_beginexclusive(isc_task_t *task);
+/*%<
+ * Request exclusive access for 'task', which must be the calling
+ * task. Waits for any other concurrently executing tasks to finish their
+ * current event, and prevents any new events from executing in any of the
+ * tasks sharing a task manager with 'task'.
+ *
+ * The exclusive access must be relinquished by calling
+ * isc_task_endexclusive() before returning from the current event handler.
+ *
+ * Requires:
+ *\li 'task' is the calling task.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS The current task now has exclusive access.
+ *\li #ISC_R_LOCKBUSY Another task has already requested exclusive
+ * access.
+ */
+
+void
+isc_task_endexclusive(isc_task_t *task);
+/*%<
+ * Relinquish the exclusive access obtained by isc_task_beginexclusive(),
+ * allowing other tasks to execute.
+ *
+ * Requires:
+ *\li 'task' is the calling task, and has obtained
+ * exclusive access by calling isc_task_spl().
+ */
+
+void
+isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t);
+/*%<
+ * Provide the most recent timestamp on the task. The timestamp is considered
+ * as the "current time" in the second-order granularity.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ *\li 't' is a valid non NULL pointer.
+ *
+ * Ensures:
+ *\li '*t' has the "current time".
+ */
+
+/*****
+ ***** Task Manager.
+ *****/
+
+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.
+ *
+ * Notes:
+ *
+ *\li 'workers' in the number of worker threads to create. In general,
+ * the value should be close to the number of processors in the system.
+ * The 'workers' value is advisory only. An attempt will be made to
+ * create 'workers' threads, but if at least one thread creation
+ * succeeds, isc_taskmgr_create() may return ISC_R_SUCCESS.
+ *
+ *\li If 'default_quantum' is non-zero, then it will be used as the default
+ * quantum value when tasks are created. If zero, then an implementation
+ * defined default quantum will be used.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li workers > 0
+ *
+ *\li managerp != NULL && *managerp == NULL
+ *
+ * Ensures:
+ *
+ *\li On success, '*managerp' will be attached to the newly created task
+ * manager.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_NOTHREADS No threads could be created.
+ *\li #ISC_R_UNEXPECTED An unexpected error occurred.
+ */
+
+void
+isc_taskmgr_destroy(isc_taskmgr_t **managerp);
+/*%<
+ * Destroy '*managerp'.
+ *
+ * Notes:
+ *
+ *\li Calling isc_taskmgr_destroy() will shutdown all tasks managed by
+ * *managerp that haven't already been shutdown. The call will block
+ * until all tasks have entered the done state.
+ *
+ *\li isc_taskmgr_destroy() must not be called by a task event action,
+ * because it would block forever waiting for the event action to
+ * complete. An event action that wants to cause task manager shutdown
+ * should request some non-event action thread of execution to do the
+ * shutdown, e.g. by signalling a condition variable or using
+ * isc_app_shutdown().
+ *
+ *\li Task manager references are not reference counted, so the caller
+ * must ensure that no attempt will be made to use the manager after
+ * isc_taskmgr_destroy() returns.
+ *
+ * Requires:
+ *
+ *\li '*managerp' is a valid task manager.
+ *
+ *\li isc_taskmgr_destroy() has not be called previously on '*managerp'.
+ *
+ * Ensures:
+ *
+ *\li All resources used by the task manager, and any tasks it managed,
+ * have been freed.
+ */
+
+#ifdef HAVE_LIBXML2
+
+void
+isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer);
+
+#endif
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TASK_H */
diff --git a/lib/isc/include/isc/taskpool.h b/lib/isc/include/isc/taskpool.h
new file mode 100644
index 0000000..fd07bfd
--- /dev/null
+++ b/lib/isc/include/isc/taskpool.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: taskpool.h,v 1.15 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_TASKPOOL_H
+#define ISC_TASKPOOL_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/taskpool.h
+ * \brief A task pool is a mechanism for sharing a small number of tasks
+ * among a large number of objects such that each object is
+ * assigned a unique task, but each task may be shared by several
+ * objects.
+ *
+ * Task pools are used to let objects that can exist in large
+ * numbers (e.g., zones) use tasks for synchronization without
+ * the memory overhead and unfair scheduling competition that
+ * could result from creating a separate task for each object.
+ */
+
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/task.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Types.
+ *****/
+
+typedef struct isc_taskpool isc_taskpool_t;
+
+/*****
+ ***** Functions.
+ *****/
+
+isc_result_t
+isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx,
+ unsigned int ntasks, unsigned int quantum,
+ isc_taskpool_t **poolp);
+/*%<
+ * Create a task pool of "ntasks" tasks, each with quantum
+ * "quantum".
+ *
+ * Requires:
+ *
+ *\li 'tmgr' is a valid task manager.
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li poolp != NULL && *poolp == NULL
+ *
+ * Ensures:
+ *
+ *\li On success, '*taskp' points to the new task pool.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ */
+
+void
+isc_taskpool_gettask(isc_taskpool_t *pool, unsigned int hash,
+ isc_task_t **targetp);
+/*%<
+ * Attach to the task corresponding to the hash value "hash".
+ */
+
+void
+isc_taskpool_destroy(isc_taskpool_t **poolp);
+/*%<
+ * Destroy a task pool. The tasks in the pool are detached but not
+ * shut down.
+ *
+ * Requires:
+ * \li '*poolp' is a valid task pool.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TASKPOOL_H */
diff --git a/lib/isc/include/isc/timer.h b/lib/isc/include/isc/timer.h
new file mode 100644
index 0000000..a4b2df7
--- /dev/null
+++ b/lib/isc/include/isc/timer.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: timer.h,v 1.40 2008/06/23 23:47:11 tbox Exp $ */
+
+#ifndef ISC_TIMER_H
+#define ISC_TIMER_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/timer.h
+ * \brief Provides timers which are event sources in the task system.
+ *
+ * Three types of timers are supported:
+ *
+ *\li 'ticker' timers generate a periodic tick event.
+ *
+ *\li 'once' timers generate an idle timeout event if they are idle for too
+ * long, and generate a life timeout event if their lifetime expires.
+ * They are used to implement both (possibly expiring) idle timers and
+ * 'one-shot' timers.
+ *
+ *\li 'limited' timers generate a periodic tick event until they reach
+ * their lifetime when they generate a life timeout event.
+ *
+ *\li 'inactive' timers generate no events.
+ *
+ * Timers can change type. It is typical to create a timer as
+ * an 'inactive' timer and then change it into a 'ticker' or
+ * 'once' timer.
+ *
+ *\li MP:
+ * The module ensures appropriate synchronization of data structures it
+ * creates and manipulates.
+ * Clients of this module must not be holding a timer's task's lock when
+ * making a call that affects that timer. Failure to follow this rule
+ * can result in deadlock.
+ * The caller must ensure that isc_timermgr_destroy() is called only
+ * once for a given manager.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * TBS
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/types.h>
+#include <isc/event.h>
+#include <isc/eventclass.h>
+#include <isc/lang.h>
+#include <isc/time.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Types
+ ***/
+
+/*% Timer Type */
+typedef enum {
+ isc_timertype_ticker = 0, /*%< Ticker */
+ isc_timertype_once = 1, /*%< Once */
+ isc_timertype_limited = 2, /*%< Limited */
+ isc_timertype_inactive = 3 /*%< Inactive */
+} isc_timertype_t;
+
+typedef struct isc_timerevent {
+ struct isc_event common;
+ isc_time_t due;
+} isc_timerevent_t;
+
+#define ISC_TIMEREVENT_FIRSTEVENT (ISC_EVENTCLASS_TIMER + 0)
+#define ISC_TIMEREVENT_TICK (ISC_EVENTCLASS_TIMER + 1)
+#define ISC_TIMEREVENT_IDLE (ISC_EVENTCLASS_TIMER + 2)
+#define ISC_TIMEREVENT_LIFE (ISC_EVENTCLASS_TIMER + 3)
+#define ISC_TIMEREVENT_LASTEVENT (ISC_EVENTCLASS_TIMER + 65535)
+
+/***
+ *** Timer and Timer Manager Functions
+ ***
+ *** Note: all Ensures conditions apply only if the result is success for
+ *** those functions which return an isc_result_t.
+ ***/
+
+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);
+/*%<
+ * Create a new 'type' timer managed by 'manager'. The timers parameters
+ * are specified by 'expires' and 'interval'. Events will be posted to
+ * 'task' and when dispatched 'action' will be called with 'arg' as the
+ * arg value. The new timer is returned in 'timerp'.
+ *
+ * Notes:
+ *
+ *\li For ticker timers, the timer will generate a 'tick' event every
+ * 'interval' seconds. The value of 'expires' is ignored.
+ *
+ *\li For once timers, 'expires' specifies the time when a life timeout
+ * event should be generated. If 'expires' is 0 (the epoch), then no life
+ * timeout will be generated. 'interval' specifies how long the timer
+ * can be idle before it generates an idle timeout. If 0, then no
+ * idle timeout will be generated.
+ *
+ *\li If 'expires' is NULL, the epoch will be used.
+ *
+ * If 'interval' is NULL, the zero interval will be used.
+ *
+ * Requires:
+ *
+ *\li 'manager' is a valid manager
+ *
+ *\li 'task' is a valid task
+ *
+ *\li 'action' is a valid action
+ *
+ *\li 'expires' points to a valid time, or is NULL.
+ *
+ *\li 'interval' points to a valid interval, or is NULL.
+ *
+ *\li type == isc_timertype_inactive ||
+ * ('expires' and 'interval' are not both 0)
+ *
+ *\li 'timerp' is a valid pointer, and *timerp == NULL
+ *
+ * Ensures:
+ *
+ *\li '*timerp' is attached to the newly created timer
+ *
+ *\li The timer is attached to the task
+ *
+ *\li An idle timeout will not be generated until at least Now + the
+ * timer's interval if 'timer' is a once timer with a non-zero
+ * interval.
+ *
+ * Returns:
+ *
+ *\li Success
+ *\li No memory
+ *\li Unexpected error
+ */
+
+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);
+/*%<
+ * Change the timer's type, expires, and interval values to the given
+ * values. If 'purge' is TRUE, any pending events from this timer
+ * are purged from its task's event queue.
+ *
+ * Notes:
+ *
+ *\li If 'expires' is NULL, the epoch will be used.
+ *
+ *\li If 'interval' is NULL, the zero interval will be used.
+ *
+ * Requires:
+ *
+ *\li 'timer' is a valid timer
+ *
+ *\li The same requirements that isc_timer_create() imposes on 'type',
+ * 'expires' and 'interval' apply.
+ *
+ * Ensures:
+ *
+ *\li An idle timeout will not be generated until at least Now + the
+ * timer's interval if 'timer' is a once timer with a non-zero
+ * interval.
+ *
+ * Returns:
+ *
+ *\li Success
+ *\li No memory
+ *\li Unexpected error
+ */
+
+isc_result_t
+isc_timer_touch(isc_timer_t *timer);
+/*%<
+ * Set the last-touched time of 'timer' to the current time.
+ *
+ * Requires:
+ *
+ *\li 'timer' is a valid once timer.
+ *
+ * Ensures:
+ *
+ *\li An idle timeout will not be generated until at least Now + the
+ * timer's interval if 'timer' is a once timer with a non-zero
+ * interval.
+ *
+ * Returns:
+ *
+ *\li Success
+ *\li Unexpected error
+ */
+
+void
+isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp);
+/*%<
+ * Attach *timerp to timer.
+ *
+ * Requires:
+ *
+ *\li 'timer' is a valid timer.
+ *
+ *\li 'timerp' points to a NULL timer.
+ *
+ * Ensures:
+ *
+ *\li *timerp is attached to timer.
+ */
+
+void
+isc_timer_detach(isc_timer_t **timerp);
+/*%<
+ * Detach *timerp from its timer.
+ *
+ * Requires:
+ *
+ *\li 'timerp' points to a valid timer.
+ *
+ * Ensures:
+ *
+ *\li *timerp is NULL.
+ *
+ *\li If '*timerp' is the last reference to the timer,
+ * then:
+ *
+ *\code
+ * The timer will be shutdown
+ *
+ * The timer will detach from its task
+ *
+ * All resources used by the timer have been freed
+ *
+ * Any events already posted by the timer will be purged.
+ * Therefore, if isc_timer_detach() is called in the context
+ * of the timer's task, it is guaranteed that no more
+ * timer event callbacks will run after the call.
+ *\endcode
+ */
+
+isc_timertype_t
+isc_timer_gettype(isc_timer_t *timer);
+/*%<
+ * Return the timer type.
+ *
+ * Requires:
+ *
+ *\li 'timer' to be a valid timer.
+ */
+
+isc_result_t
+isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp);
+/*%<
+ * Create a timer manager.
+ *
+ * Notes:
+ *
+ *\li All memory will be allocated in memory context 'mctx'.
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li 'managerp' points to a NULL isc_timermgr_t.
+ *
+ * Ensures:
+ *
+ *\li '*managerp' is a valid isc_timermgr_t.
+ *
+ * Returns:
+ *
+ *\li Success
+ *\li No memory
+ *\li Unexpected error
+ */
+
+void
+isc_timermgr_destroy(isc_timermgr_t **managerp);
+/*%<
+ * Destroy a timer manager.
+ *
+ * Notes:
+ *
+ *\li This routine blocks until there are no timers left in the manager,
+ * so if the caller holds any timer references using the manager, it
+ * must detach them before calling isc_timermgr_destroy() or it will
+ * block forever.
+ *
+ * Requires:
+ *
+ *\li '*managerp' is a valid isc_timermgr_t.
+ *
+ * Ensures:
+ *
+ *\li *managerp == NULL
+ *
+ *\li All resources used by the manager have been freed.
+ */
+
+void isc_timermgr_poke(isc_timermgr_t *m);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TIMER_H */
diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h
new file mode 100644
index 0000000..88c06ff
--- /dev/null
+++ b/lib/isc/include/isc/types.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2004-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
+ * 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.46 2008/06/23 19:41:19 jinmei Exp $ */
+
+#ifndef ISC_TYPES_H
+#define ISC_TYPES_H 1
+
+/*! \file isc/types.h
+ * \brief
+ * OS-specific types, from the OS-specific include directories.
+ */
+#include <isc/int.h>
+#include <isc/offset.h>
+
+/*
+ * XXXDCL should isc_boolean_t be moved here, requiring an explicit include
+ * of <isc/boolean.h> when ISC_TRUE/ISC_FALSE/ISC_TF() are desired?
+ */
+#include <isc/boolean.h>
+/*
+ * XXXDCL This is just for ISC_LIST and ISC_LINK, but gets all of the other
+ * list macros too.
+ */
+#include <isc/list.h>
+
+/* Core Types. Alphabetized by defined type. */
+
+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 */
+typedef struct isc_constregion isc_constregion_t; /*%< Const region */
+typedef struct isc_consttextregion isc_consttextregion_t; /*%< Const Text Region */
+typedef struct isc_entropy isc_entropy_t; /*%< Entropy */
+typedef struct isc_entropysource isc_entropysource_t; /*%< Entropy Source */
+typedef struct isc_event isc_event_t; /*%< Event */
+typedef ISC_LIST(isc_event_t) isc_eventlist_t; /*%< Event List */
+typedef unsigned int isc_eventtype_t; /*%< Event Type */
+typedef isc_uint32_t isc_fsaccess_t; /*%< FS Access */
+typedef struct isc_hash isc_hash_t; /*%< Hash */
+typedef struct isc_httpd isc_httpd_t; /*%< HTTP client */
+typedef void (isc_httpdfree_t)(isc_buffer_t *, void *); /*%< HTTP free function */
+typedef struct isc_httpdmgr isc_httpdmgr_t; /*%< HTTP manager */
+typedef struct isc_httpdurl isc_httpdurl_t; /*%< HTTP URL */
+typedef void (isc_httpdondestroy_t)(void *); /*%< Callback on destroying httpd */
+typedef struct isc_interface isc_interface_t; /*%< Interface */
+typedef struct isc_interfaceiter isc_interfaceiter_t; /*%< Interface Iterator */
+typedef struct isc_interval isc_interval_t; /*%< Interval */
+typedef struct isc_lex isc_lex_t; /*%< Lex */
+typedef struct isc_log isc_log_t; /*%< Log */
+typedef struct isc_logcategory isc_logcategory_t; /*%< Log Category */
+typedef struct isc_logconfig isc_logconfig_t; /*%< Log Configuration */
+typedef struct isc_logmodule isc_logmodule_t; /*%< Log Module */
+typedef struct isc_mem isc_mem_t; /*%< Memory */
+typedef struct isc_mempool isc_mempool_t; /*%< Memory Pool */
+typedef struct isc_msgcat isc_msgcat_t; /*%< Message Catalog */
+typedef struct isc_ondestroy isc_ondestroy_t; /*%< On Destroy */
+typedef struct isc_netaddr isc_netaddr_t; /*%< Net Address */
+typedef struct isc_portset isc_portset_t; /*%< Port Set */
+typedef struct isc_quota isc_quota_t; /*%< Quota */
+typedef struct isc_random isc_random_t; /*%< Random */
+typedef struct isc_ratelimiter isc_ratelimiter_t; /*%< Rate Limiter */
+typedef struct isc_region isc_region_t; /*%< Region */
+typedef isc_uint64_t isc_resourcevalue_t; /*%< Resource Value */
+typedef unsigned int isc_result_t; /*%< Result */
+typedef struct isc_rwlock isc_rwlock_t; /*%< Read Write Lock */
+typedef struct isc_sockaddr isc_sockaddr_t; /*%< Socket Address */
+typedef struct isc_socket isc_socket_t; /*%< Socket */
+typedef struct isc_socketevent isc_socketevent_t; /*%< Socket Event */
+typedef struct isc_socketmgr isc_socketmgr_t; /*%< Socket Manager */
+typedef struct isc_symtab isc_symtab_t; /*%< Symbol Table */
+typedef struct isc_task isc_task_t; /*%< Task */
+typedef ISC_LIST(isc_task_t) isc_tasklist_t; /*%< Task List */
+typedef struct isc_taskmgr isc_taskmgr_t; /*%< Task Manager */
+typedef struct isc_textregion isc_textregion_t; /*%< Text Region */
+typedef struct isc_time isc_time_t; /*%< Time */
+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 *);
+
+/* The following cannot be listed alphabetically due to forward reference */
+typedef isc_result_t (isc_httpdaction_t)(const char *url,
+ const char *querystring,
+ void *arg,
+ unsigned int *retcode,
+ const char **retmsg,
+ const char **mimetype,
+ isc_buffer_t *body,
+ isc_httpdfree_t **freecb,
+ void **freecb_args);
+typedef isc_boolean_t (isc_httpdclientok_t)(const isc_sockaddr_t *, void *);
+
+/*% Resource */
+typedef enum {
+ isc_resource_coresize = 1,
+ isc_resource_cputime,
+ isc_resource_datasize,
+ isc_resource_filesize,
+ isc_resource_lockedmemory,
+ isc_resource_openfiles,
+ isc_resource_processes,
+ isc_resource_residentsize,
+ isc_resource_stacksize
+} isc_resource_t;
+
+#endif /* ISC_TYPES_H */
diff --git a/lib/isc/include/isc/util.h b/lib/isc/include/isc/util.h
new file mode 100644
index 0000000..8a3b95d
--- /dev/null
+++ b/lib/isc/include/isc/util.h
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: util.h,v 1.30 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_UTIL_H
+#define ISC_UTIL_H 1
+
+/*! \file isc/util.h
+ * NOTE:
+ *
+ * This file is not to be included from any <isc/???.h> (or other) library
+ * files.
+ *
+ * \brief
+ * Including this file puts several macros in your name space that are
+ * not protected (as all the other ISC functions/macros do) by prepending
+ * ISC_ or isc_ to the name.
+ */
+
+/***
+ *** General Macros.
+ ***/
+
+/*%
+ * Use this to hide unused function arguments.
+ * \code
+ * int
+ * foo(char *bar)
+ * {
+ * UNUSED(bar);
+ * }
+ * \endcode
+ */
+#define UNUSED(x) (void)(x)
+
+#define ISC_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define ISC_MIN(a, b) ((a) < (b) ? (a) : (b))
+
+/*%
+ * Use this to remove the const qualifier of a variable to assign it to
+ * a non-const variable or pass it as a non-const function argument ...
+ * but only when you are sure it won't then be changed!
+ * This is necessary to sometimes shut up some compilers
+ * (as with gcc -Wcast-qual) when there is just no other good way to avoid the
+ * situation.
+ */
+#define DE_CONST(konst, var) \
+ do { \
+ union { const void *k; void *v; } _u; \
+ _u.k = konst; \
+ var = _u.v; \
+ } while (0)
+
+/*%
+ * Use this in translation units that would otherwise be empty, to
+ * suppress compiler warnings.
+ */
+#define EMPTY_TRANSLATION_UNIT static void isc__empty(void) { isc__empty(); }
+
+/*%
+ * We use macros instead of calling the routines directly because
+ * the capital letters make the locking stand out.
+ * We RUNTIME_CHECK for success since in general there's no way
+ * for us to continue if they fail.
+ */
+
+#ifdef ISC_UTIL_TRACEON
+#define ISC_UTIL_TRACE(a) a
+#include <stdio.h> /* Required for fprintf/stderr when tracing. */
+#include <isc/msgs.h> /* Required for isc_msgcat when tracing. */
+#else
+#define ISC_UTIL_TRACE(a)
+#endif
+
+#include <isc/result.h> /* Contractual promise. */
+
+#define LOCK(lp) do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_LOCKING, "LOCKING"), \
+ (lp), __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_mutex_lock((lp)) == ISC_R_SUCCESS); \
+ ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_LOCKED, "LOCKED"), \
+ (lp), __FILE__, __LINE__)); \
+ } while (0)
+#define UNLOCK(lp) do { \
+ RUNTIME_CHECK(isc_mutex_unlock((lp)) == ISC_R_SUCCESS); \
+ ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_UNLOCKED, "UNLOCKED"), \
+ (lp), __FILE__, __LINE__)); \
+ } while (0)
+#define ISLOCKED(lp) (1)
+#define DESTROYLOCK(lp) \
+ RUNTIME_CHECK(isc_mutex_destroy((lp)) == ISC_R_SUCCESS)
+
+
+#define BROADCAST(cvp) do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_BROADCAST, "BROADCAST"),\
+ (cvp), __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_condition_broadcast((cvp)) == ISC_R_SUCCESS); \
+ } while (0)
+#define SIGNAL(cvp) do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %d\n", \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_SIGNAL, "SIGNAL"), \
+ (cvp), __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_condition_signal((cvp)) == ISC_R_SUCCESS); \
+ } while (0)
+#define WAIT(cvp, lp) do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %p %s %d\n", \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_UTILWAIT, "WAIT"), \
+ (cvp), \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_LOCK, "LOCK"), \
+ (lp), __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_condition_wait((cvp), (lp)) == ISC_R_SUCCESS); \
+ ISC_UTIL_TRACE(fprintf(stderr, "%s %p %s %p %s %d\n", \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_WAITED, "WAITED"), \
+ (cvp), \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_LOCKED, "LOCKED"), \
+ (lp), __FILE__, __LINE__)); \
+ } while (0)
+
+/*
+ * isc_condition_waituntil can return ISC_R_TIMEDOUT, so we
+ * don't RUNTIME_CHECK the result.
+ *
+ * XXX Also, can't really debug this then...
+ */
+
+#define WAITUNTIL(cvp, lp, tp) \
+ isc_condition_waituntil((cvp), (lp), (tp))
+
+#define RWLOCK(lp, t) do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_RWLOCK, "RWLOCK"), \
+ (lp), (t), __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_rwlock_lock((lp), (t)) == ISC_R_SUCCESS); \
+ ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_RWLOCKED, "RWLOCKED"), \
+ (lp), (t), __FILE__, __LINE__)); \
+ } while (0)
+#define RWUNLOCK(lp, t) do { \
+ ISC_UTIL_TRACE(fprintf(stderr, "%s %p, %d %s %d\n", \
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_UTIL, \
+ ISC_MSG_RWUNLOCK, "RWUNLOCK"), \
+ (lp), (t), __FILE__, __LINE__)); \
+ RUNTIME_CHECK(isc_rwlock_unlock((lp), (t)) == ISC_R_SUCCESS); \
+ } while (0)
+
+#define DESTROYMUTEXBLOCK(bp, n) \
+ RUNTIME_CHECK(isc_mutexblock_destroy((bp), (n)) == ISC_R_SUCCESS)
+
+/*
+ * List Macros.
+ */
+#include <isc/list.h> /* Contractual promise. */
+
+#define LIST(type) ISC_LIST(type)
+#define INIT_LIST(type) ISC_LIST_INIT(type)
+#define LINK(type) ISC_LINK(type)
+#define INIT_LINK(elt, link) ISC_LINK_INIT(elt, link)
+#define HEAD(list) ISC_LIST_HEAD(list)
+#define TAIL(list) ISC_LIST_TAIL(list)
+#define EMPTY(list) ISC_LIST_EMPTY(list)
+#define PREV(elt, link) ISC_LIST_PREV(elt, link)
+#define NEXT(elt, link) ISC_LIST_NEXT(elt, link)
+#define APPEND(list, elt, link) ISC_LIST_APPEND(list, elt, link)
+#define PREPEND(list, elt, link) ISC_LIST_PREPEND(list, elt, link)
+#define UNLINK(list, elt, link) ISC_LIST_UNLINK(list, elt, link)
+#define ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link)
+#define DEQUEUE(list, elt, link) ISC_LIST_UNLINK(list, elt, link)
+#define INSERTBEFORE(li, b, e, ln) ISC_LIST_INSERTBEFORE(li, b, e, ln)
+#define INSERTAFTER(li, a, e, ln) ISC_LIST_INSERTAFTER(li, a, e, ln)
+#define APPENDLIST(list1, list2, link) ISC_LIST_APPENDLIST(list1, list2, link)
+
+/*
+ * Assertions
+ */
+#include <isc/assertions.h> /* Contractual promise. */
+
+/*% Require Assertion */
+#define REQUIRE(e) ISC_REQUIRE(e)
+/*% Ensure Assertion */
+#define ENSURE(e) ISC_ENSURE(e)
+/*% Insist Assertion */
+#define INSIST(e) ISC_INSIST(e)
+/*% Invariant Assertion */
+#define INVARIANT(e) ISC_INVARIANT(e)
+
+/*
+ * Errors
+ */
+#include <isc/error.h> /* Contractual promise. */
+
+/*% Unexpected Error */
+#define UNEXPECTED_ERROR isc_error_unexpected
+/*% Fatal Error */
+#define FATAL_ERROR isc_error_fatal
+/*% Runtime Check */
+#define RUNTIME_CHECK(cond) ISC_ERROR_RUNTIMECHECK(cond)
+
+/*%
+ * Time
+ */
+#define TIME_NOW(tp) RUNTIME_CHECK(isc_time_now((tp)) == ISC_R_SUCCESS)
+
+#endif /* ISC_UTIL_H */
diff --git a/lib/isc/include/isc/version.h b/lib/isc/include/isc/version.h
new file mode 100644
index 0000000..ec00bde
--- /dev/null
+++ b/lib/isc/include/isc/version.h
@@ -0,0 +1,28 @@
+/*
+ * 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: version.h,v 1.9 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file isc/version.h */
+
+#include <isc/platform.h>
+
+LIBISC_EXTERNAL_DATA extern const char isc_version[];
+
+LIBISC_EXTERNAL_DATA extern const unsigned int isc_libinterface;
+LIBISC_EXTERNAL_DATA extern const unsigned int isc_librevision;
+LIBISC_EXTERNAL_DATA extern const unsigned int isc_libage;
diff --git a/lib/isc/include/isc/xml.h b/lib/isc/include/isc/xml.h
new file mode 100644
index 0000000..d31a31a
--- /dev/null
+++ b/lib/isc/include/isc/xml.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2006, 2007 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: xml.h,v 1.4 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_XML_H
+#define ISC_XML_H 1
+
+/*
+ * This file is here mostly to make it easy to add additional libxml header
+ * files as needed across all the users of this file. Rather than place
+ * these libxml includes in each file, one include makes it easy to handle
+ * the ifdef as well as adding the ability to add additional functions
+ * which may be useful.
+ */
+
+#ifdef HAVE_LIBXML2
+#include <libxml/encoding.h>
+#include <libxml/xmlwriter.h>
+#endif
+
+#define ISC_XMLCHAR (const xmlChar *)
+
+#define ISC_XML_RENDERCONFIG 0x00000001 /* render config data */
+#define ISC_XML_RENDERSTATS 0x00000002 /* render stats */
+#define ISC_XML_RENDERALL 0x000000ff /* render everything */
+
+#endif /* ISC_XML_H */
diff --git a/lib/isc/inet_aton.c b/lib/isc/inet_aton.c
new file mode 100644
index 0000000..dacc109
--- /dev/null
+++ b/lib/isc/inet_aton.c
@@ -0,0 +1,196 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 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
+ * 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.
+ */
+
+/*
+ * Copyright (c) 1983, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+/*! \file */
+
+#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 2007/06/19 23:47:17 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stddef.h> /* Required for NULL. */
+
+#include <isc/types.h>
+#include <isc/net.h>
+
+/*%
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+isc_net_aton(const char *cp, struct in_addr *addr) {
+ unsigned long val;
+ int base, n;
+ unsigned char c;
+ isc_uint8_t parts[4];
+ isc_uint8_t *pp = parts;
+ int digit;
+
+ c = *cp;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, isdigit=decimal.
+ */
+ if (!isdigit(c & 0xff))
+ return (0);
+ val = 0; base = 10; digit = 0;
+ if (c == '0') {
+ c = *++cp;
+ if (c == 'x' || c == 'X')
+ base = 16, c = *++cp;
+ else {
+ base = 8;
+ digit = 1;
+ }
+ }
+ for (;;) {
+ /*
+ * isascii() is valid for all integer values, and
+ * when it is true, c is known to be in scope
+ * for isdigit(). No cast necessary. Similar
+ * comment applies for later ctype uses.
+ */
+ if (isascii(c) && isdigit(c)) {
+ if (base == 8 && (c == '8' || c == '9'))
+ return (0);
+ val = (val * base) + (c - '0');
+ c = *++cp;
+ digit = 1;
+ } else if (base == 16 && isascii(c) && isxdigit(c)) {
+ val = (val << 4) |
+ (c + 10 - (islower(c) ? 'a' : 'A'));
+ c = *++cp;
+ digit = 1;
+ } else
+ break;
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xff)
+ return (0);
+ *pp++ = (isc_uint8_t)val;
+ c = *++cp;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && (!isascii(c) || !isspace(c)))
+ return (0);
+ /*
+ * Did we get a valid digit?
+ */
+ if (!digit)
+ return (0);
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n) {
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr != NULL)
+ addr->s_addr = htonl(val);
+
+ return (1);
+}
diff --git a/lib/isc/inet_ntop.c b/lib/isc/inet_ntop.c
new file mode 100644
index 0000000..dc053ed
--- /dev/null
+++ b/lib/isc/inet_ntop.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1996-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.
+ */
+
+/*! \file */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] =
+ "$Id: inet_ntop.c,v 1.19 2007/06/19 23:47:17 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/net.h>
+#include <isc/print.h>
+
+#define NS_INT16SZ 2
+#define NS_IN6ADDRSZ 16
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4(const unsigned char *src, char *dst,
+ size_t size);
+
+#ifdef AF_INET6
+static const char *inet_ntop6(const unsigned char *src, char *dst,
+ size_t size);
+#endif
+
+/*! char *
+ * isc_net_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * \return
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * \author
+ * Paul Vixie, 1996.
+ */
+const char *
+isc_net_ntop(int af, const void *src, char *dst, size_t size)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_ntop4(src, dst, size));
+#ifdef AF_INET6
+ case AF_INET6:
+ return (inet_ntop6(src, dst, size));
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+/*! const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address
+ * \return
+ * `dst' (as a const)
+ * \note
+ * (1) uses no statics
+ * \note
+ * (2) takes a unsigned char* not an in_addr as input
+ * \author
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(const unsigned char *src, char *dst, size_t size)
+{
+ static const char *fmt = "%u.%u.%u.%u";
+ char tmp[sizeof("255.255.255.255")];
+
+ if ((size_t)sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size)
+ {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+
+ return (dst);
+}
+
+/*! const char *
+ * isc_inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * \author
+ * Paul Vixie, 1996.
+ */
+#ifdef AF_INET6
+static const char *
+inet_ntop6(const unsigned char *src, char *dst, size_t size)
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp;
+ struct { int base, len; } best, cur;
+ unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof(words));
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 &&
+ (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+ if (!inet_ntop4(src+12, tp,
+ sizeof(tmp) - (tp - tmp)))
+ return (NULL);
+ tp += strlen(tp);
+ break;
+ }
+ tp += sprintf(tp, "%x", words[i]);
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+#endif /* AF_INET6 */
diff --git a/lib/isc/inet_pton.c b/lib/isc/inet_pton.c
new file mode 100644
index 0000000..6bada23
--- /dev/null
+++ b/lib/isc/inet_pton.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1996-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.
+ */
+
+/*! \file */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] =
+ "$Id: inet_pton.c,v 1.19 2007/06/19 23:47:17 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <isc/net.h>
+
+/*% INT16 Size */
+#define NS_INT16SZ 2
+/*% IPv4 Address Size */
+#define NS_INADDRSZ 4
+/*% IPv6 Address Size */
+#define NS_IN6ADDRSZ 16
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4(const char *src, unsigned char *dst);
+static int inet_pton6(const char *src, unsigned char *dst);
+
+/*%
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * \return
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * \author
+ * Paul Vixie, 1996.
+ */
+int
+isc_net_pton(int af, const char *src, void *dst) {
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/*!\fn static int inet_pton4(const char *src, unsigned char *dst)
+ * \brief
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * \return
+ * 1 if `src' is a valid dotted quad, else 0.
+ * \note
+ * does not touch `dst' unless it's returning 1.
+ * \author
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, unsigned char *dst) {
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ unsigned int new = *tp * 10 + (pch - digits);
+
+ if (saw_digit && *tp == 0)
+ return (0);
+ if (new > 255)
+ return (0);
+ *tp = new;
+ if (!saw_digit) {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return (1);
+}
+
+/*%
+ * convert presentation level address to network order binary form.
+ * \return
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * \note
+ * (1) does not touch `dst' unless it's returning 1.
+ * \note
+ * (2) :: in a full address is silently ignored.
+ * \author
+ * inspired by Mark Andrews.
+ * \author
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, unsigned char *dst) {
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, seen_xdigits;
+ unsigned int val;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ seen_xdigits = 0;
+ val = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (++seen_xdigits > 4)
+ return (0);
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!seen_xdigits) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ seen_xdigits = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += NS_INADDRSZ;
+ seen_xdigits = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (seen_xdigits) {
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ return (0);
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return (1);
+}
diff --git a/lib/isc/iterated_hash.c b/lib/isc/iterated_hash.c
new file mode 100644
index 0000000..8c32929
--- /dev/null
+++ b/lib/isc/iterated_hash.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006, 2008 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: iterated_hash.c,v 1.4 2008/09/24 03:16:58 tbox Exp $ */
+
+#include <stdio.h>
+
+#include <isc/sha1.h>
+#include <isc/iterated_hash.h>
+
+int
+isc_iterated_hash(unsigned char out[ISC_SHA1_DIGESTLENGTH],
+ unsigned int hashalg, int iterations,
+ const unsigned char *salt, int saltlength,
+ const unsigned char *in, int inlength)
+{
+ isc_sha1_t ctx;
+ int n = 0;
+
+ if (hashalg != 1)
+ return (0);
+
+ do {
+ isc_sha1_init(&ctx);
+ isc_sha1_update(&ctx, in, inlength);
+ isc_sha1_update(&ctx, salt, saltlength);
+ isc_sha1_final(&ctx, out);
+ in = out;
+ inlength = ISC_SHA1_DIGESTLENGTH;
+ } while (n++ < iterations);
+
+ return (ISC_SHA1_DIGESTLENGTH);
+}
diff --git a/lib/isc/lex.c b/lib/isc/lex.c
new file mode 100644
index 0000000..8749ed0
--- /dev/null
+++ b/lib/isc/lex.c
@@ -0,0 +1,959 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: lex.c,v 1.86 2007/09/17 09:56:29 shane Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/file.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+typedef struct inputsource {
+ isc_result_t result;
+ isc_boolean_t is_file;
+ isc_boolean_t need_close;
+ isc_boolean_t at_eof;
+ isc_buffer_t * pushback;
+ unsigned int ignored;
+ void * input;
+ char * name;
+ unsigned long line;
+ unsigned long saved_line;
+ ISC_LINK(struct inputsource) link;
+} inputsource;
+
+#define LEX_MAGIC ISC_MAGIC('L', 'e', 'x', '!')
+#define VALID_LEX(l) ISC_MAGIC_VALID(l, LEX_MAGIC)
+
+struct isc_lex {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ size_t max_token;
+ char * data;
+ unsigned int comments;
+ isc_boolean_t comment_ok;
+ isc_boolean_t last_was_eol;
+ unsigned int paren_count;
+ unsigned int saved_paren_count;
+ isc_lexspecials_t specials;
+ LIST(struct inputsource) sources;
+};
+
+static inline isc_result_t
+grow_data(isc_lex_t *lex, size_t *remainingp, char **currp, char **prevp) {
+ char *new;
+
+ new = isc_mem_get(lex->mctx, lex->max_token * 2 + 1);
+ if (new == NULL)
+ return (ISC_R_NOMEMORY);
+ memcpy(new, lex->data, lex->max_token + 1);
+ *currp = new + (*currp - lex->data);
+ if (*prevp != NULL)
+ *prevp = new + (*prevp - lex->data);
+ isc_mem_put(lex->mctx, lex->data, lex->max_token + 1);
+ lex->data = new;
+ *remainingp += lex->max_token;
+ lex->max_token *= 2;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_lex_create(isc_mem_t *mctx, size_t max_token, isc_lex_t **lexp) {
+ isc_lex_t *lex;
+
+ /*
+ * Create a lexer.
+ */
+
+ REQUIRE(lexp != NULL && *lexp == NULL);
+ REQUIRE(max_token > 0U);
+
+ lex = isc_mem_get(mctx, sizeof(*lex));
+ if (lex == NULL)
+ return (ISC_R_NOMEMORY);
+ lex->data = isc_mem_get(mctx, max_token + 1);
+ if (lex->data == NULL) {
+ isc_mem_put(mctx, lex, sizeof(*lex));
+ return (ISC_R_NOMEMORY);
+ }
+ lex->mctx = mctx;
+ lex->max_token = max_token;
+ lex->comments = 0;
+ lex->comment_ok = ISC_TRUE;
+ lex->last_was_eol = ISC_TRUE;
+ lex->paren_count = 0;
+ lex->saved_paren_count = 0;
+ memset(lex->specials, 0, 256);
+ INIT_LIST(lex->sources);
+ lex->magic = LEX_MAGIC;
+
+ *lexp = lex;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_lex_destroy(isc_lex_t **lexp) {
+ isc_lex_t *lex;
+
+ /*
+ * Destroy the lexer.
+ */
+
+ REQUIRE(lexp != NULL);
+ lex = *lexp;
+ REQUIRE(VALID_LEX(lex));
+
+ while (!EMPTY(lex->sources))
+ RUNTIME_CHECK(isc_lex_close(lex) == ISC_R_SUCCESS);
+ if (lex->data != NULL)
+ isc_mem_put(lex->mctx, lex->data, lex->max_token + 1);
+ lex->magic = 0;
+ isc_mem_put(lex->mctx, lex, sizeof(*lex));
+
+ *lexp = NULL;
+}
+
+unsigned int
+isc_lex_getcomments(isc_lex_t *lex) {
+ /*
+ * Return the current lexer commenting styles.
+ */
+
+ REQUIRE(VALID_LEX(lex));
+
+ return (lex->comments);
+}
+
+void
+isc_lex_setcomments(isc_lex_t *lex, unsigned int comments) {
+ /*
+ * Set allowed lexer commenting styles.
+ */
+
+ REQUIRE(VALID_LEX(lex));
+
+ lex->comments = comments;
+}
+
+void
+isc_lex_getspecials(isc_lex_t *lex, isc_lexspecials_t specials) {
+ /*
+ * Put the current list of specials into 'specials'.
+ */
+
+ REQUIRE(VALID_LEX(lex));
+
+ memcpy(specials, lex->specials, 256);
+}
+
+void
+isc_lex_setspecials(isc_lex_t *lex, isc_lexspecials_t specials) {
+ /*
+ * The characters in 'specials' are returned as tokens. Along with
+ * whitespace, they delimit strings and numbers.
+ */
+
+ REQUIRE(VALID_LEX(lex));
+
+ memcpy(lex->specials, specials, 256);
+}
+
+static inline isc_result_t
+new_source(isc_lex_t *lex, isc_boolean_t is_file, isc_boolean_t need_close,
+ void *input, const char *name)
+{
+ inputsource *source;
+ isc_result_t result;
+
+ source = isc_mem_get(lex->mctx, sizeof(*source));
+ if (source == NULL)
+ return (ISC_R_NOMEMORY);
+ source->result = ISC_R_SUCCESS;
+ source->is_file = is_file;
+ source->need_close = need_close;
+ source->at_eof = ISC_FALSE;
+ source->input = input;
+ source->name = isc_mem_strdup(lex->mctx, name);
+ if (source->name == NULL) {
+ isc_mem_put(lex->mctx, source, sizeof(*source));
+ return (ISC_R_NOMEMORY);
+ }
+ source->pushback = NULL;
+ result = isc_buffer_allocate(lex->mctx, &source->pushback,
+ lex->max_token);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_free(lex->mctx, source->name);
+ isc_mem_put(lex->mctx, source, sizeof(*source));
+ return (result);
+ }
+ source->ignored = 0;
+ source->line = 1;
+ ISC_LIST_INITANDPREPEND(lex->sources, source, link);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_lex_openfile(isc_lex_t *lex, const char *filename) {
+ isc_result_t result;
+ FILE *stream = NULL;
+
+ /*
+ * Open 'filename' and make it the current input source for 'lex'.
+ */
+
+ REQUIRE(VALID_LEX(lex));
+
+ result = isc_stdio_open(filename, "r", &stream);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = new_source(lex, ISC_TRUE, ISC_TRUE, stream, filename);
+ if (result != ISC_R_SUCCESS)
+ (void)fclose(stream);
+ return (result);
+}
+
+isc_result_t
+isc_lex_openstream(isc_lex_t *lex, FILE *stream) {
+ char name[128];
+
+ /*
+ * Make 'stream' the current input source for 'lex'.
+ */
+
+ REQUIRE(VALID_LEX(lex));
+
+ snprintf(name, sizeof(name), "stream-%p", stream);
+
+ return (new_source(lex, ISC_TRUE, ISC_FALSE, stream, name));
+}
+
+isc_result_t
+isc_lex_openbuffer(isc_lex_t *lex, isc_buffer_t *buffer) {
+ char name[128];
+
+ /*
+ * Make 'buffer' the current input source for 'lex'.
+ */
+
+ REQUIRE(VALID_LEX(lex));
+
+ snprintf(name, sizeof(name), "buffer-%p", buffer);
+
+ return (new_source(lex, ISC_FALSE, ISC_FALSE, buffer, name));
+}
+
+isc_result_t
+isc_lex_close(isc_lex_t *lex) {
+ inputsource *source;
+
+ /*
+ * Close the most recently opened object (i.e. file or buffer).
+ */
+
+ REQUIRE(VALID_LEX(lex));
+
+ source = HEAD(lex->sources);
+ if (source == NULL)
+ return (ISC_R_NOMORE);
+
+ ISC_LIST_UNLINK(lex->sources, source, link);
+ if (source->is_file) {
+ if (source->need_close)
+ (void)fclose((FILE *)(source->input));
+ }
+ isc_mem_free(lex->mctx, source->name);
+ isc_buffer_free(&source->pushback);
+ isc_mem_put(lex->mctx, source, sizeof(*source));
+
+ return (ISC_R_SUCCESS);
+}
+
+typedef enum {
+ lexstate_start,
+ lexstate_crlf,
+ lexstate_string,
+ lexstate_number,
+ lexstate_maybecomment,
+ lexstate_ccomment,
+ lexstate_ccommentend,
+ lexstate_eatline,
+ lexstate_qstring
+} lexstate;
+
+#define IWSEOL (ISC_LEXOPT_INITIALWS | ISC_LEXOPT_EOL)
+
+static void
+pushback(inputsource *source, int c) {
+ REQUIRE(source->pushback->current > 0);
+ if (c == EOF) {
+ source->at_eof = ISC_FALSE;
+ return;
+ }
+ source->pushback->current--;
+ if (c == '\n')
+ source->line--;
+}
+
+static isc_result_t
+pushandgrow(isc_lex_t *lex, inputsource *source, int c) {
+ if (isc_buffer_availablelength(source->pushback) == 0) {
+ isc_buffer_t *tbuf = NULL;
+ unsigned int oldlen;
+ isc_region_t used;
+ isc_result_t result;
+
+ oldlen = isc_buffer_length(source->pushback);
+ result = isc_buffer_allocate(lex->mctx, &tbuf, oldlen * 2);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_usedregion(source->pushback, &used);
+ result = isc_buffer_copyregion(tbuf, &used);
+ INSIST(result == ISC_R_SUCCESS);
+ tbuf->current = source->pushback->current;
+ isc_buffer_free(&source->pushback);
+ source->pushback = tbuf;
+ }
+ isc_buffer_putuint8(source->pushback, (isc_uint8_t)c);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_lex_gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *tokenp) {
+ inputsource *source;
+ int c;
+ isc_boolean_t done = ISC_FALSE;
+ isc_boolean_t no_comments = ISC_FALSE;
+ isc_boolean_t escaped = ISC_FALSE;
+ lexstate state = lexstate_start;
+ lexstate saved_state = lexstate_start;
+ isc_buffer_t *buffer;
+ FILE *stream;
+ char *curr, *prev;
+ size_t remaining;
+ isc_uint32_t as_ulong;
+ unsigned int saved_options;
+ isc_result_t result;
+
+ /*
+ * Get the next token.
+ */
+
+ REQUIRE(VALID_LEX(lex));
+ source = HEAD(lex->sources);
+ REQUIRE(tokenp != NULL);
+
+ if (source == NULL) {
+ if ((options & ISC_LEXOPT_NOMORE) != 0) {
+ tokenp->type = isc_tokentype_nomore;
+ return (ISC_R_SUCCESS);
+ }
+ return (ISC_R_NOMORE);
+ }
+
+ if (source->result != ISC_R_SUCCESS)
+ return (source->result);
+
+ lex->saved_paren_count = lex->paren_count;
+ source->saved_line = source->line;
+
+ if (isc_buffer_remaininglength(source->pushback) == 0 &&
+ source->at_eof)
+ {
+ if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 &&
+ lex->paren_count != 0) {
+ lex->paren_count = 0;
+ return (ISC_R_UNBALANCED);
+ }
+ if ((options & ISC_LEXOPT_EOF) != 0) {
+ tokenp->type = isc_tokentype_eof;
+ return (ISC_R_SUCCESS);
+ }
+ return (ISC_R_EOF);
+ }
+
+ isc_buffer_compact(source->pushback);
+
+ saved_options = options;
+ if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 && lex->paren_count > 0)
+ options &= ~IWSEOL;
+
+ curr = lex->data;
+ *curr = '\0';
+
+ prev = NULL;
+ remaining = lex->max_token;
+
+#ifdef HAVE_FLOCKFILE
+ if (source->is_file)
+ flockfile(source->input);
+#endif
+
+ do {
+ if (isc_buffer_remaininglength(source->pushback) == 0) {
+ if (source->is_file) {
+ stream = source->input;
+
+#if defined(HAVE_FLOCKFILE) && defined(HAVE_GETCUNLOCKED)
+ c = getc_unlocked(stream);
+#else
+ c = getc(stream);
+#endif
+ if (c == EOF) {
+ if (ferror(stream)) {
+ source->result = ISC_R_IOERROR;
+ result = source->result;
+ goto done;
+ }
+ source->at_eof = ISC_TRUE;
+ }
+ } else {
+ buffer = source->input;
+
+ if (buffer->current == buffer->used) {
+ c = EOF;
+ source->at_eof = ISC_TRUE;
+ } else {
+ c = *((char *)buffer->base +
+ buffer->current);
+ buffer->current++;
+ }
+ }
+ if (c != EOF) {
+ source->result = pushandgrow(lex, source, c);
+ if (source->result != ISC_R_SUCCESS) {
+ result = source->result;
+ goto done;
+ }
+ }
+ }
+
+ if (!source->at_eof) {
+ if (state == lexstate_start)
+ /* Token has not started yet. */
+ source->ignored =
+ isc_buffer_consumedlength(source->pushback);
+ c = isc_buffer_getuint8(source->pushback);
+ } else {
+ c = EOF;
+ }
+
+ if (c == '\n')
+ source->line++;
+
+ if (lex->comment_ok && !no_comments) {
+ if (!escaped && c == ';' &&
+ ((lex->comments & ISC_LEXCOMMENT_DNSMASTERFILE)
+ != 0)) {
+ saved_state = state;
+ state = lexstate_eatline;
+ no_comments = ISC_TRUE;
+ continue;
+ } else if (c == '/' &&
+ (lex->comments &
+ (ISC_LEXCOMMENT_C|
+ ISC_LEXCOMMENT_CPLUSPLUS)) != 0) {
+ saved_state = state;
+ state = lexstate_maybecomment;
+ no_comments = ISC_TRUE;
+ continue;
+ } else if (c == '#' &&
+ ((lex->comments & ISC_LEXCOMMENT_SHELL)
+ != 0)) {
+ saved_state = state;
+ state = lexstate_eatline;
+ no_comments = ISC_TRUE;
+ continue;
+ }
+ }
+
+ no_read:
+ /* INSIST(c == EOF || (c >= 0 && c <= 255)); */
+ switch (state) {
+ case lexstate_start:
+ if (c == EOF) {
+ lex->last_was_eol = ISC_FALSE;
+ if ((options & ISC_LEXOPT_DNSMULTILINE) != 0 &&
+ lex->paren_count != 0) {
+ lex->paren_count = 0;
+ result = ISC_R_UNBALANCED;
+ goto done;
+ }
+ if ((options & ISC_LEXOPT_EOF) == 0) {
+ result = ISC_R_EOF;
+ goto done;
+ }
+ tokenp->type = isc_tokentype_eof;
+ done = ISC_TRUE;
+ } else if (c == ' ' || c == '\t') {
+ if (lex->last_was_eol &&
+ (options & ISC_LEXOPT_INITIALWS)
+ != 0) {
+ lex->last_was_eol = ISC_FALSE;
+ tokenp->type = isc_tokentype_initialws;
+ tokenp->value.as_char = c;
+ done = ISC_TRUE;
+ }
+ } else if (c == '\n') {
+ if ((options & ISC_LEXOPT_EOL) != 0) {
+ tokenp->type = isc_tokentype_eol;
+ done = ISC_TRUE;
+ }
+ lex->last_was_eol = ISC_TRUE;
+ } else if (c == '\r') {
+ if ((options & ISC_LEXOPT_EOL) != 0)
+ state = lexstate_crlf;
+ } else if (c == '"' &&
+ (options & ISC_LEXOPT_QSTRING) != 0) {
+ lex->last_was_eol = ISC_FALSE;
+ no_comments = ISC_TRUE;
+ state = lexstate_qstring;
+ } else if (lex->specials[c]) {
+ lex->last_was_eol = ISC_FALSE;
+ if ((c == '(' || c == ')') &&
+ (options & ISC_LEXOPT_DNSMULTILINE) != 0) {
+ if (c == '(') {
+ if (lex->paren_count == 0)
+ options &= ~IWSEOL;
+ lex->paren_count++;
+ } else {
+ if (lex->paren_count == 0) {
+ result = ISC_R_UNBALANCED;
+ goto done;
+ }
+ lex->paren_count--;
+ if (lex->paren_count == 0)
+ options =
+ saved_options;
+ }
+ continue;
+ }
+ tokenp->type = isc_tokentype_special;
+ tokenp->value.as_char = c;
+ done = ISC_TRUE;
+ } else if (isdigit((unsigned char)c) &&
+ (options & ISC_LEXOPT_NUMBER) != 0) {
+ lex->last_was_eol = ISC_FALSE;
+ if ((options & ISC_LEXOPT_OCTAL) != 0 &&
+ (c == '8' || c == '9'))
+ state = lexstate_string;
+ else
+ state = lexstate_number;
+ goto no_read;
+ } else {
+ lex->last_was_eol = ISC_FALSE;
+ state = lexstate_string;
+ goto no_read;
+ }
+ break;
+ case lexstate_crlf:
+ if (c != '\n')
+ pushback(source, c);
+ tokenp->type = isc_tokentype_eol;
+ done = ISC_TRUE;
+ lex->last_was_eol = ISC_TRUE;
+ break;
+ case lexstate_number:
+ if (c == EOF || !isdigit((unsigned char)c)) {
+ if (c == ' ' || c == '\t' || c == '\r' ||
+ c == '\n' || c == EOF ||
+ lex->specials[c]) {
+ int base;
+ if ((options & ISC_LEXOPT_OCTAL) != 0)
+ base = 8;
+ else if ((options & ISC_LEXOPT_CNUMBER) != 0)
+ base = 0;
+ else
+ base = 10;
+ pushback(source, c);
+
+ result = isc_parse_uint32(&as_ulong,
+ lex->data,
+ base);
+ if (result == ISC_R_SUCCESS) {
+ tokenp->type =
+ isc_tokentype_number;
+ tokenp->value.as_ulong =
+ as_ulong;
+ } else if (result == ISC_R_BADNUMBER) {
+ isc_tokenvalue_t *v;
+
+ tokenp->type =
+ isc_tokentype_string;
+ v = &(tokenp->value);
+ v->as_textregion.base =
+ lex->data;
+ v->as_textregion.length =
+ lex->max_token -
+ remaining;
+ } else
+ goto done;
+ done = ISC_TRUE;
+ continue;
+ } else if (!(options & ISC_LEXOPT_CNUMBER) ||
+ ((c != 'x' && c != 'X') ||
+ (curr != &lex->data[1]) ||
+ (lex->data[0] != '0'))) {
+ /* Above test supports hex numbers */
+ state = lexstate_string;
+ }
+ } else if ((options & ISC_LEXOPT_OCTAL) != 0 &&
+ (c == '8' || c == '9')) {
+ state = lexstate_string;
+ }
+ if (remaining == 0U) {
+ result = grow_data(lex, &remaining,
+ &curr, &prev);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ }
+ INSIST(remaining > 0U);
+ *curr++ = c;
+ *curr = '\0';
+ remaining--;
+ break;
+ case lexstate_string:
+ /*
+ * EOF needs to be checked before lex->specials[c]
+ * as lex->specials[EOF] is not a good idea.
+ */
+ if (c == '\r' || c == '\n' || c == EOF ||
+ (!escaped &&
+ (c == ' ' || c == '\t' || lex->specials[c]))) {
+ pushback(source, c);
+ if (source->result != ISC_R_SUCCESS) {
+ result = source->result;
+ goto done;
+ }
+ tokenp->type = isc_tokentype_string;
+ tokenp->value.as_textregion.base = lex->data;
+ tokenp->value.as_textregion.length =
+ lex->max_token - remaining;
+ done = ISC_TRUE;
+ continue;
+ }
+ if ((options & ISC_LEXOPT_ESCAPE) != 0)
+ escaped = (!escaped && c == '\\') ?
+ ISC_TRUE : ISC_FALSE;
+ if (remaining == 0U) {
+ result = grow_data(lex, &remaining,
+ &curr, &prev);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ }
+ INSIST(remaining > 0U);
+ *curr++ = c;
+ *curr = '\0';
+ remaining--;
+ break;
+ case lexstate_maybecomment:
+ if (c == '*' &&
+ (lex->comments & ISC_LEXCOMMENT_C) != 0) {
+ state = lexstate_ccomment;
+ continue;
+ } else if (c == '/' &&
+ (lex->comments & ISC_LEXCOMMENT_CPLUSPLUS) != 0) {
+ state = lexstate_eatline;
+ continue;
+ }
+ pushback(source, c);
+ c = '/';
+ no_comments = ISC_FALSE;
+ state = saved_state;
+ goto no_read;
+ case lexstate_ccomment:
+ if (c == EOF) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto done;
+ }
+ if (c == '*')
+ state = lexstate_ccommentend;
+ break;
+ case lexstate_ccommentend:
+ if (c == EOF) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto done;
+ }
+ if (c == '/') {
+ /*
+ * C-style comments become a single space.
+ * We do this to ensure that a comment will
+ * act as a delimiter for strings and
+ * numbers.
+ */
+ c = ' ';
+ no_comments = ISC_FALSE;
+ state = saved_state;
+ goto no_read;
+ } else if (c != '*')
+ state = lexstate_ccomment;
+ break;
+ case lexstate_eatline:
+ if ((c == '\n') || (c == EOF)) {
+ no_comments = ISC_FALSE;
+ state = saved_state;
+ goto no_read;
+ }
+ break;
+ case lexstate_qstring:
+ if (c == EOF) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto done;
+ }
+ if (c == '"') {
+ if (escaped) {
+ escaped = ISC_FALSE;
+ /*
+ * Overwrite the preceding backslash.
+ */
+ INSIST(prev != NULL);
+ *prev = '"';
+ } else {
+ tokenp->type = isc_tokentype_qstring;
+ tokenp->value.as_textregion.base =
+ lex->data;
+ tokenp->value.as_textregion.length =
+ lex->max_token - remaining;
+ no_comments = ISC_FALSE;
+ done = ISC_TRUE;
+ }
+ } else {
+ if (c == '\n' && !escaped &&
+ (options & ISC_LEXOPT_QSTRINGMULTILINE) == 0) {
+ pushback(source, c);
+ result = ISC_R_UNBALANCEDQUOTES;
+ goto done;
+ }
+ if (c == '\\' && !escaped)
+ escaped = ISC_TRUE;
+ else
+ escaped = ISC_FALSE;
+ if (remaining == 0U) {
+ result = grow_data(lex, &remaining,
+ &curr, &prev);
+ if (result != ISC_R_SUCCESS)
+ goto done;
+ }
+ INSIST(remaining > 0U);
+ prev = curr;
+ *curr++ = c;
+ *curr = '\0';
+ remaining--;
+ }
+ break;
+ default:
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_LEX,
+ ISC_MSG_UNEXPECTEDSTATE,
+ "Unexpected state %d"),
+ state);
+ /* Does not return. */
+ }
+
+ } while (!done);
+
+ result = ISC_R_SUCCESS;
+ done:
+#ifdef HAVE_FLOCKFILE
+ if (source->is_file)
+ funlockfile(source->input);
+#endif
+ return (result);
+}
+
+isc_result_t
+isc_lex_getmastertoken(isc_lex_t *lex, isc_token_t *token,
+ isc_tokentype_t expect, isc_boolean_t eol)
+{
+ unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
+ ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE;
+ isc_result_t result;
+
+ if (expect == isc_tokentype_qstring)
+ options |= ISC_LEXOPT_QSTRING;
+ else if (expect == isc_tokentype_number)
+ options |= ISC_LEXOPT_NUMBER;
+ result = isc_lex_gettoken(lex, options, token);
+ if (result == ISC_R_RANGE)
+ isc_lex_ungettoken(lex, token);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (eol && ((token->type == isc_tokentype_eol) ||
+ (token->type == isc_tokentype_eof)))
+ return (ISC_R_SUCCESS);
+ if (token->type == isc_tokentype_string &&
+ expect == isc_tokentype_qstring)
+ return (ISC_R_SUCCESS);
+ if (token->type != expect) {
+ isc_lex_ungettoken(lex, token);
+ if (token->type == isc_tokentype_eol ||
+ token->type == isc_tokentype_eof)
+ return (ISC_R_UNEXPECTEDEND);
+ if (expect == isc_tokentype_number)
+ return (ISC_R_BADNUMBER);
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_lex_getoctaltoken(isc_lex_t *lex, isc_token_t *token, isc_boolean_t eol)
+{
+ unsigned int options = ISC_LEXOPT_EOL | ISC_LEXOPT_EOF |
+ ISC_LEXOPT_DNSMULTILINE | ISC_LEXOPT_ESCAPE|
+ ISC_LEXOPT_NUMBER | ISC_LEXOPT_OCTAL;
+ isc_result_t result;
+
+ result = isc_lex_gettoken(lex, options, token);
+ if (result == ISC_R_RANGE)
+ isc_lex_ungettoken(lex, token);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (eol && ((token->type == isc_tokentype_eol) ||
+ (token->type == isc_tokentype_eof)))
+ return (ISC_R_SUCCESS);
+ if (token->type != isc_tokentype_number) {
+ isc_lex_ungettoken(lex, token);
+ if (token->type == isc_tokentype_eol ||
+ token->type == isc_tokentype_eof)
+ return (ISC_R_UNEXPECTEDEND);
+ return (ISC_R_BADNUMBER);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_lex_ungettoken(isc_lex_t *lex, isc_token_t *tokenp) {
+ inputsource *source;
+ /*
+ * Unget the current token.
+ */
+
+ REQUIRE(VALID_LEX(lex));
+ source = HEAD(lex->sources);
+ REQUIRE(source != NULL);
+ REQUIRE(tokenp != NULL);
+ REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 ||
+ tokenp->type == isc_tokentype_eof);
+
+ UNUSED(tokenp);
+
+ isc_buffer_first(source->pushback);
+ lex->paren_count = lex->saved_paren_count;
+ source->line = source->saved_line;
+ source->at_eof = ISC_FALSE;
+}
+
+void
+isc_lex_getlasttokentext(isc_lex_t *lex, isc_token_t *tokenp, isc_region_t *r)
+{
+ inputsource *source;
+
+ REQUIRE(VALID_LEX(lex));
+ source = HEAD(lex->sources);
+ REQUIRE(source != NULL);
+ REQUIRE(tokenp != NULL);
+ REQUIRE(isc_buffer_consumedlength(source->pushback) != 0 ||
+ tokenp->type == isc_tokentype_eof);
+
+ UNUSED(tokenp);
+
+ INSIST(source->ignored <= isc_buffer_consumedlength(source->pushback));
+ r->base = (unsigned char *)isc_buffer_base(source->pushback) +
+ source->ignored;
+ r->length = isc_buffer_consumedlength(source->pushback) -
+ source->ignored;
+}
+
+
+char *
+isc_lex_getsourcename(isc_lex_t *lex) {
+ inputsource *source;
+
+ REQUIRE(VALID_LEX(lex));
+ source = HEAD(lex->sources);
+
+ if (source == NULL)
+ return (NULL);
+
+ return (source->name);
+}
+
+unsigned long
+isc_lex_getsourceline(isc_lex_t *lex) {
+ inputsource *source;
+
+ REQUIRE(VALID_LEX(lex));
+ source = HEAD(lex->sources);
+
+ if (source == NULL)
+ return (0);
+
+ return (source->line);
+}
+
+
+isc_result_t
+isc_lex_setsourcename(isc_lex_t *lex, const char *name) {
+ inputsource *source;
+ char *newname;
+
+ REQUIRE(VALID_LEX(lex));
+ source = HEAD(lex->sources);
+
+ if (source == NULL)
+ return(ISC_R_NOTFOUND);
+ newname = isc_mem_strdup(lex->mctx, name);
+ if (newname == NULL)
+ return (ISC_R_NOMEMORY);
+ isc_mem_free(lex->mctx, source->name);
+ source->name = newname;
+ return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+isc_lex_isfile(isc_lex_t *lex) {
+ inputsource *source;
+
+ REQUIRE(VALID_LEX(lex));
+
+ source = HEAD(lex->sources);
+
+ if (source == NULL)
+ return (ISC_FALSE);
+
+ return (source->is_file);
+}
diff --git a/lib/isc/lfsr.c b/lib/isc/lfsr.c
new file mode 100644
index 0000000..0b8d782
--- /dev/null
+++ b/lib/isc/lfsr.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: lfsr.c,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <isc/assertions.h>
+#include <isc/lfsr.h>
+#include <isc/util.h>
+
+#define VALID_LFSR(x) (x != NULL)
+
+void
+isc_lfsr_init(isc_lfsr_t *lfsr, isc_uint32_t state, unsigned int bits,
+ isc_uint32_t tap, unsigned int count,
+ isc_lfsrreseed_t reseed, void *arg)
+{
+ REQUIRE(VALID_LFSR(lfsr));
+ REQUIRE(8 <= bits && bits <= 32);
+ REQUIRE(tap != 0);
+
+ lfsr->state = state;
+ lfsr->bits = bits;
+ lfsr->tap = tap;
+ lfsr->count = count;
+ lfsr->reseed = reseed;
+ lfsr->arg = arg;
+
+ if (count == 0 && reseed != NULL)
+ reseed(lfsr, arg);
+ if (lfsr->state == 0)
+ lfsr->state = 0xffffffffU >> (32 - lfsr->bits);
+}
+
+/*!
+ * Return the next state of the lfsr.
+ */
+static inline isc_uint32_t
+lfsr_generate(isc_lfsr_t *lfsr)
+{
+
+ /*
+ * If the previous state is zero, we must fill it with something
+ * here, or we will begin to generate an extremely predictable output.
+ *
+ * First, give the reseed function a crack at it. If the state is
+ * still 0, set it to all ones.
+ */
+ if (lfsr->state == 0) {
+ if (lfsr->reseed != NULL)
+ lfsr->reseed(lfsr, lfsr->arg);
+ if (lfsr->state == 0)
+ lfsr->state = 0xffffffffU >> (32 - lfsr->bits);
+ }
+
+ if (lfsr->state & 0x01) {
+ lfsr->state = (lfsr->state >> 1) ^ lfsr->tap;
+ return (1);
+ } else {
+ lfsr->state >>= 1;
+ return (0);
+ }
+}
+
+void
+isc_lfsr_generate(isc_lfsr_t *lfsr, void *data, unsigned int count)
+{
+ unsigned char *p;
+ unsigned int bit;
+ unsigned int byte;
+
+ REQUIRE(VALID_LFSR(lfsr));
+ REQUIRE(data != NULL);
+ REQUIRE(count > 0);
+
+ p = data;
+ byte = count;
+
+ while (byte--) {
+ *p = 0;
+ for (bit = 0; bit < 7; bit++) {
+ *p |= lfsr_generate(lfsr);
+ *p <<= 1;
+ }
+ *p |= lfsr_generate(lfsr);
+ p++;
+ }
+
+ if (lfsr->count != 0 && lfsr->reseed != NULL) {
+ if (lfsr->count <= count * 8)
+ lfsr->reseed(lfsr, lfsr->arg);
+ else
+ lfsr->count -= (count * 8);
+ }
+}
+
+static inline isc_uint32_t
+lfsr_skipgenerate(isc_lfsr_t *lfsr, unsigned int skip)
+{
+ while (skip--)
+ (void)lfsr_generate(lfsr);
+
+ (void)lfsr_generate(lfsr);
+
+ return (lfsr->state);
+}
+
+/*
+ * Skip "skip" states in "lfsr".
+ */
+void
+isc_lfsr_skip(isc_lfsr_t *lfsr, unsigned int skip)
+{
+ REQUIRE(VALID_LFSR(lfsr));
+
+ while (skip--)
+ (void)lfsr_generate(lfsr);
+}
+
+/*
+ * Skip states in lfsr1 and lfsr2 using the other's current state.
+ * Return the final state of lfsr1 ^ lfsr2.
+ */
+isc_uint32_t
+isc_lfsr_generate32(isc_lfsr_t *lfsr1, isc_lfsr_t *lfsr2)
+{
+ isc_uint32_t state1, state2;
+ isc_uint32_t skip1, skip2;
+
+ REQUIRE(VALID_LFSR(lfsr1));
+ REQUIRE(VALID_LFSR(lfsr2));
+
+ skip1 = lfsr1->state & 0x01;
+ skip2 = lfsr2->state & 0x01;
+
+ /* cross-skip. */
+ state1 = lfsr_skipgenerate(lfsr1, skip2);
+ state2 = lfsr_skipgenerate(lfsr2, skip1);
+
+ return (state1 ^ state2);
+}
diff --git a/lib/isc/lib.c b/lib/isc/lib.c
new file mode 100644
index 0000000..f3a2c2d
--- /dev/null
+++ b/lib/isc/lib.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: lib.c,v 1.14 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/once.h>
+#include <isc/msgs.h>
+#include <isc/lib.h>
+
+/***
+ *** Globals
+ ***/
+
+LIBISC_EXTERNAL_DATA isc_msgcat_t * isc_msgcat = NULL;
+
+
+/***
+ *** Private
+ ***/
+
+static isc_once_t msgcat_once = ISC_ONCE_INIT;
+
+
+/***
+ *** Functions
+ ***/
+
+static void
+open_msgcat(void) {
+ isc_msgcat_open("libisc.cat", &isc_msgcat);
+}
+
+void
+isc_lib_initmsgcat(void) {
+ isc_result_t result;
+
+ /*!
+ * Initialize the ISC library's message catalog, isc_msgcat, if it
+ * has not already been initialized.
+ */
+
+ result = isc_once_do(&msgcat_once, open_msgcat);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * Normally we'd use RUNTIME_CHECK() or FATAL_ERROR(), but
+ * we can't do that here, since they might call us!
+ * (Note that the catalog might be open anyway, so we might
+ * as well try to provide an internationalized message.)
+ */
+ fprintf(stderr, "%s:%d: %s: isc_once_do() %s.\n",
+ __FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FATALERROR, "fatal error"),
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ abort();
+ }
+}
diff --git a/lib/isc/log.c b/lib/isc/log.c
new file mode 100644
index 0000000..802f302
--- /dev/null
+++ b/lib/isc/log.c
@@ -0,0 +1,1761 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: log.c,v 1.94 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file
+ * \author Principal Authors: DCL */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <time.h>
+
+#include <sys/types.h> /* dev_t FreeBSD 2.1 */
+
+#include <isc/dir.h>
+#include <isc/file.h>
+#include <isc/log.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/print.h>
+#include <isc/stat.h>
+#include <isc/stdio.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#define LCTX_MAGIC ISC_MAGIC('L', 'c', 't', 'x')
+#define VALID_CONTEXT(lctx) ISC_MAGIC_VALID(lctx, LCTX_MAGIC)
+
+#define LCFG_MAGIC ISC_MAGIC('L', 'c', 'f', 'g')
+#define VALID_CONFIG(lcfg) ISC_MAGIC_VALID(lcfg, LCFG_MAGIC)
+
+/*
+ * XXXDCL make dynamic?
+ */
+#define LOG_BUFFER_SIZE (8 * 1024)
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024 /* AIX and others don't define this. */
+#endif
+
+/*!
+ * This is the structure that holds each named channel. A simple linked
+ * list chains all of the channels together, so an individual channel is
+ * found by doing strcmp()s with the names down the list. Their should
+ * be no peformance penalty from this as it is expected that the number
+ * of named channels will be no more than a dozen or so, and name lookups
+ * from the head of the list are only done when isc_log_usechannel() is
+ * called, which should also be very infrequent.
+ */
+typedef struct isc_logchannel isc_logchannel_t;
+
+struct isc_logchannel {
+ char * name;
+ unsigned int type;
+ int level;
+ unsigned int flags;
+ isc_logdestination_t destination;
+ ISC_LINK(isc_logchannel_t) link;
+};
+
+/*!
+ * The logchannellist structure associates categories and modules with
+ * channels. First the appropriate channellist is found based on the
+ * category, and then each structure in the linked list is checked for
+ * a matching module. It is expected that the number of channels
+ * associated with any given category will be very short, no more than
+ * three or four in the more unusual cases.
+ */
+typedef struct isc_logchannellist isc_logchannellist_t;
+
+struct isc_logchannellist {
+ const isc_logmodule_t * module;
+ isc_logchannel_t * channel;
+ ISC_LINK(isc_logchannellist_t) link;
+};
+
+/*!
+ * This structure is used to remember messages for pruning via
+ * isc_log_[v]write1().
+ */
+typedef struct isc_logmessage isc_logmessage_t;
+
+struct isc_logmessage {
+ char * text;
+ isc_time_t time;
+ ISC_LINK(isc_logmessage_t) link;
+};
+
+/*!
+ * The isc_logconfig structure is used to store the configurable information
+ * about where messages are actually supposed to be sent -- the information
+ * that could changed based on some configuration file, as opposed to the
+ * the category/module specification of isc_log_[v]write[1] that is compiled
+ * into a program, or the debug_level which is dynamic state information.
+ */
+struct isc_logconfig {
+ unsigned int magic;
+ isc_log_t * lctx;
+ ISC_LIST(isc_logchannel_t) channels;
+ ISC_LIST(isc_logchannellist_t) *channellists;
+ unsigned int channellist_count;
+ unsigned int duplicate_interval;
+ int highest_level;
+ char * tag;
+ isc_boolean_t dynamic;
+};
+
+/*!
+ * This isc_log structure provides the context for the isc_log functions.
+ * The log context locks itself in isc_log_doit, the internal backend to
+ * isc_log_write. The locking is necessary both to provide exclusive access
+ * to the the buffer into which the message is formatted and to guard against
+ * competing threads trying to write to the same syslog resource. (On
+ * some systems, such as BSD/OS, stdio is thread safe but syslog is not.)
+ * Unfortunately, the lock cannot guard against a _different_ logging
+ * context in the same program competing for syslog's attention. Thus
+ * There Can Be Only One, but this is not enforced.
+ * XXXDCL enforce it?
+ *
+ * Note that the category and module information is not locked.
+ * This is because in the usual case, only one isc_log_t is ever created
+ * in a program, and the category/module registration happens only once.
+ * XXXDCL it might be wise to add more locking overall.
+ */
+struct isc_log {
+ /* Not locked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ isc_logcategory_t * categories;
+ unsigned int category_count;
+ isc_logmodule_t * modules;
+ unsigned int module_count;
+ int debug_level;
+ isc_mutex_t lock;
+ /* Locked by isc_log lock. */
+ isc_logconfig_t * logconfig;
+ char buffer[LOG_BUFFER_SIZE];
+ ISC_LIST(isc_logmessage_t) messages;
+};
+
+/*!
+ * Used when ISC_LOG_PRINTLEVEL is enabled for a channel.
+ */
+static const char *log_level_strings[] = {
+ "debug",
+ "info",
+ "notice",
+ "warning",
+ "error",
+ "critical"
+};
+
+/*!
+ * Used to convert ISC_LOG_* priorities into syslog priorities.
+ * XXXDCL This will need modification for NT.
+ */
+static const int syslog_map[] = {
+ LOG_DEBUG,
+ LOG_INFO,
+ LOG_NOTICE,
+ LOG_WARNING,
+ LOG_ERR,
+ LOG_CRIT
+};
+
+/*!
+ * When adding new categories, a corresponding ISC_LOGCATEGORY_foo
+ * definition needs to be added to <isc/log.h>.
+ *
+ * The default category is provided so that the internal default can
+ * be overridden. Since the default is always looked up as the first
+ * channellist in the log context, it must come first in isc_categories[].
+ */
+LIBISC_EXTERNAL_DATA isc_logcategory_t isc_categories[] = {
+ { "default", 0 }, /* "default" must come first. */
+ { "general", 0 },
+ { NULL, 0 }
+};
+
+/*!
+ * See above comment for categories on LIBISC_EXTERNAL_DATA, and apply it to modules.
+ */
+LIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = {
+ { "socket", 0 },
+ { "time", 0 },
+ { "interface", 0 },
+ { "timer", 0 },
+ { NULL, 0 }
+};
+
+/*!
+ * This essentially constant structure must be filled in at run time,
+ * because its channel member is pointed to a channel that is created
+ * dynamically with isc_log_createchannel.
+ */
+static isc_logchannellist_t default_channel;
+
+/*!
+ * libisc logs to this context.
+ */
+LIBISC_EXTERNAL_DATA isc_log_t *isc_lctx = NULL;
+
+/*!
+ * Forward declarations.
+ */
+static isc_result_t
+assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
+ const isc_logmodule_t *module, isc_logchannel_t *channel);
+
+static isc_result_t
+sync_channellist(isc_logconfig_t *lcfg);
+
+static isc_result_t
+greatest_version(isc_logchannel_t *channel, int *greatest);
+
+static isc_result_t
+roll_log(isc_logchannel_t *channel);
+
+static void
+isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, isc_boolean_t write_once,
+ isc_msgcat_t *msgcat, int msgset, int msg,
+ const char *format, va_list args)
+ ISC_FORMAT_PRINTF(9, 0);
+
+/*@{*/
+/*!
+ * Convenience macros.
+ */
+
+#define FACILITY(channel) (channel->destination.facility)
+#define FILE_NAME(channel) (channel->destination.file.name)
+#define FILE_STREAM(channel) (channel->destination.file.stream)
+#define FILE_VERSIONS(channel) (channel->destination.file.versions)
+#define FILE_MAXSIZE(channel) (channel->destination.file.maximum_size)
+#define FILE_MAXREACHED(channel) (channel->destination.file.maximum_reached)
+
+/*@}*/
+/****
+ **** Public interfaces.
+ ****/
+
+/*
+ * Establish a new logging context, with default channels.
+ */
+isc_result_t
+isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
+ isc_log_t *lctx;
+ isc_logconfig_t *lcfg = NULL;
+ isc_result_t result;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(lctxp != NULL && *lctxp == NULL);
+ REQUIRE(lcfgp == NULL || *lcfgp == NULL);
+
+ lctx = isc_mem_get(mctx, sizeof(*lctx));
+ if (lctx != NULL) {
+ lctx->mctx = mctx;
+ lctx->categories = NULL;
+ lctx->category_count = 0;
+ lctx->modules = NULL;
+ lctx->module_count = 0;
+ lctx->debug_level = 0;
+
+ ISC_LIST_INIT(lctx->messages);
+
+ result = isc_mutex_init(&lctx->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, lctx, sizeof(*lctx));
+ return (result);
+ }
+
+ /*
+ * Normally setting the magic number is the last step done
+ * in a creation function, but a valid log context is needed
+ * by isc_log_registercategories and isc_logconfig_create.
+ * If either fails, the lctx is destroyed and not returned
+ * to the caller.
+ */
+ lctx->magic = LCTX_MAGIC;
+
+ isc_log_registercategories(lctx, isc_categories);
+ isc_log_registermodules(lctx, isc_modules);
+ result = isc_logconfig_create(lctx, &lcfg);
+
+ } else
+ result = ISC_R_NOMEMORY;
+
+ if (result == ISC_R_SUCCESS)
+ result = sync_channellist(lcfg);
+
+ if (result == ISC_R_SUCCESS) {
+ lctx->logconfig = lcfg;
+
+ *lctxp = lctx;
+ if (lcfgp != NULL)
+ *lcfgp = lcfg;
+
+ } else {
+ if (lcfg != NULL)
+ isc_logconfig_destroy(&lcfg);
+ if (lctx != NULL)
+ isc_log_destroy(&lctx);
+ }
+
+ return (result);
+}
+
+isc_result_t
+isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp) {
+ isc_logconfig_t *lcfg;
+ isc_logdestination_t destination;
+ isc_result_t result = ISC_R_SUCCESS;
+ int level = ISC_LOG_INFO;
+
+ REQUIRE(lcfgp != NULL && *lcfgp == NULL);
+ REQUIRE(VALID_CONTEXT(lctx));
+
+ lcfg = isc_mem_get(lctx->mctx, sizeof(*lcfg));
+
+ if (lcfg != NULL) {
+ lcfg->lctx = lctx;
+ lcfg->channellists = NULL;
+ lcfg->channellist_count = 0;
+ lcfg->duplicate_interval = 0;
+ lcfg->highest_level = level;
+ lcfg->tag = NULL;
+ lcfg->dynamic = ISC_FALSE;
+
+ ISC_LIST_INIT(lcfg->channels);
+
+ /*
+ * Normally the magic number is the last thing set in the
+ * structure, but isc_log_createchannel() needs a valid
+ * config. If the channel creation fails, the lcfg is not
+ * returned to the caller.
+ */
+ lcfg->magic = LCFG_MAGIC;
+
+ } else
+ result = ISC_R_NOMEMORY;
+
+ /*
+ * Create the default channels:
+ * default_syslog, default_stderr, default_debug and null.
+ */
+ if (result == ISC_R_SUCCESS) {
+ destination.facility = LOG_DAEMON;
+ result = isc_log_createchannel(lcfg, "default_syslog",
+ ISC_LOG_TOSYSLOG, level,
+ &destination, 0);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(lcfg, "default_stderr",
+ ISC_LOG_TOFILEDESC,
+ level,
+ &destination,
+ ISC_LOG_PRINTTIME);
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Set the default category's channel to default_stderr,
+ * which is at the head of the channels list because it was
+ * just created.
+ */
+ default_channel.channel = ISC_LIST_HEAD(lcfg->channels);
+
+ destination.file.stream = stderr;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ result = isc_log_createchannel(lcfg, "default_debug",
+ ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC,
+ &destination,
+ ISC_LOG_PRINTTIME);
+ }
+
+ if (result == ISC_R_SUCCESS)
+ result = isc_log_createchannel(lcfg, "null",
+ ISC_LOG_TONULL,
+ ISC_LOG_DYNAMIC,
+ NULL, 0);
+
+ if (result == ISC_R_SUCCESS)
+ *lcfgp = lcfg;
+
+ else
+ if (lcfg != NULL)
+ isc_logconfig_destroy(&lcfg);
+
+ return (result);
+}
+
+isc_logconfig_t *
+isc_logconfig_get(isc_log_t *lctx) {
+ REQUIRE(VALID_CONTEXT(lctx));
+
+ ENSURE(lctx->logconfig != NULL);
+
+ return (lctx->logconfig);
+}
+
+isc_result_t
+isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg) {
+ isc_logconfig_t *old_cfg;
+ isc_result_t result;
+
+ REQUIRE(VALID_CONTEXT(lctx));
+ REQUIRE(VALID_CONFIG(lcfg));
+ REQUIRE(lcfg->lctx == lctx);
+
+ /*
+ * Ensure that lcfg->channellist_count == lctx->category_count.
+ * They won't be equal if isc_log_usechannel has not been called
+ * since any call to isc_log_registercategories.
+ */
+ result = sync_channellist(lcfg);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ LOCK(&lctx->lock);
+
+ old_cfg = lctx->logconfig;
+ lctx->logconfig = lcfg;
+
+ UNLOCK(&lctx->lock);
+
+ isc_logconfig_destroy(&old_cfg);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_log_destroy(isc_log_t **lctxp) {
+ isc_log_t *lctx;
+ isc_logconfig_t *lcfg;
+ isc_mem_t *mctx;
+ isc_logmessage_t *message;
+
+ REQUIRE(lctxp != NULL && VALID_CONTEXT(*lctxp));
+
+ lctx = *lctxp;
+ mctx = lctx->mctx;
+
+ if (lctx->logconfig != NULL) {
+ lcfg = lctx->logconfig;
+ lctx->logconfig = NULL;
+ isc_logconfig_destroy(&lcfg);
+ }
+
+ DESTROYLOCK(&lctx->lock);
+
+ while ((message = ISC_LIST_HEAD(lctx->messages)) != NULL) {
+ ISC_LIST_UNLINK(lctx->messages, message, link);
+
+ isc_mem_put(mctx, message,
+ sizeof(*message) + strlen(message->text) + 1);
+ }
+
+ lctx->buffer[0] = '\0';
+ lctx->debug_level = 0;
+ lctx->categories = NULL;
+ lctx->category_count = 0;
+ lctx->modules = NULL;
+ lctx->module_count = 0;
+ lctx->mctx = NULL;
+ lctx->magic = 0;
+
+ isc_mem_put(mctx, lctx, sizeof(*lctx));
+
+ *lctxp = NULL;
+}
+
+void
+isc_logconfig_destroy(isc_logconfig_t **lcfgp) {
+ isc_logconfig_t *lcfg;
+ isc_mem_t *mctx;
+ isc_logchannel_t *channel;
+ isc_logchannellist_t *item;
+ char *filename;
+ unsigned int i;
+
+ REQUIRE(lcfgp != NULL && VALID_CONFIG(*lcfgp));
+
+ lcfg = *lcfgp;
+
+ /*
+ * This function cannot be called with a logconfig that is in
+ * use by a log context.
+ */
+ REQUIRE(lcfg->lctx != NULL && lcfg->lctx->logconfig != lcfg);
+
+ mctx = lcfg->lctx->mctx;
+
+ while ((channel = ISC_LIST_HEAD(lcfg->channels)) != NULL) {
+ ISC_LIST_UNLINK(lcfg->channels, channel, link);
+
+ if (channel->type == ISC_LOG_TOFILE) {
+ /*
+ * The filename for the channel may have ultimately
+ * started its life in user-land as a const string,
+ * but in isc_log_createchannel it gets copied
+ * into writable memory and is not longer truly const.
+ */
+ DE_CONST(FILE_NAME(channel), filename);
+ isc_mem_free(mctx, filename);
+
+ if (FILE_STREAM(channel) != NULL)
+ (void)fclose(FILE_STREAM(channel));
+ }
+
+ isc_mem_free(mctx, channel->name);
+ isc_mem_put(mctx, channel, sizeof(*channel));
+ }
+
+ for (i = 0; i < lcfg->channellist_count; i++)
+ while ((item = ISC_LIST_HEAD(lcfg->channellists[i])) != NULL) {
+ ISC_LIST_UNLINK(lcfg->channellists[i], item, link);
+ isc_mem_put(mctx, item, sizeof(*item));
+ }
+
+ if (lcfg->channellist_count > 0)
+ isc_mem_put(mctx, lcfg->channellists,
+ lcfg->channellist_count *
+ sizeof(ISC_LIST(isc_logchannellist_t)));
+
+ lcfg->dynamic = ISC_FALSE;
+ if (lcfg->tag != NULL)
+ isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
+ lcfg->tag = NULL;
+ lcfg->highest_level = 0;
+ lcfg->duplicate_interval = 0;
+ lcfg->magic = 0;
+
+ isc_mem_put(mctx, lcfg, sizeof(*lcfg));
+
+ *lcfgp = NULL;
+}
+
+void
+isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) {
+ isc_logcategory_t *catp;
+
+ REQUIRE(VALID_CONTEXT(lctx));
+ REQUIRE(categories != NULL && categories[0].name != NULL);
+
+ /*
+ * XXXDCL This somewhat sleazy situation of using the last pointer
+ * in one category array to point to the next array exists because
+ * this registration function returns void and I didn't want to have
+ * change everything that used it by making it return an isc_result_t.
+ * It would need to do that if it had to allocate memory to store
+ * pointers to each array passed in.
+ */
+ if (lctx->categories == NULL)
+ lctx->categories = categories;
+
+ else {
+ /*
+ * Adjust the last (NULL) pointer of the already registered
+ * categories to point to the incoming array.
+ */
+ for (catp = lctx->categories; catp->name != NULL; )
+ if (catp->id == UINT_MAX)
+ /*
+ * The name pointer points to the next array.
+ * Ick.
+ */
+ DE_CONST(catp->name, catp);
+ else
+ catp++;
+
+ catp->name = (void *)categories;
+ catp->id = UINT_MAX;
+ }
+
+ /*
+ * Update the id number of the category with its new global id.
+ */
+ for (catp = categories; catp->name != NULL; catp++)
+ catp->id = lctx->category_count++;
+}
+
+isc_logcategory_t *
+isc_log_categorybyname(isc_log_t *lctx, const char *name) {
+ isc_logcategory_t *catp;
+
+ REQUIRE(VALID_CONTEXT(lctx));
+ REQUIRE(name != NULL);
+
+ for (catp = lctx->categories; catp->name != NULL; )
+ if (catp->id == UINT_MAX)
+ /*
+ * catp is neither modified nor returned to the
+ * caller, so removing its const qualifier is ok.
+ */
+ DE_CONST(catp->name, catp);
+ else {
+ if (strcmp(catp->name, name) == 0)
+ return (catp);
+ catp++;
+ }
+
+ return (NULL);
+}
+
+void
+isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]) {
+ isc_logmodule_t *modp;
+
+ REQUIRE(VALID_CONTEXT(lctx));
+ REQUIRE(modules != NULL && modules[0].name != NULL);
+
+ /*
+ * XXXDCL This somewhat sleazy situation of using the last pointer
+ * in one category array to point to the next array exists because
+ * this registration function returns void and I didn't want to have
+ * change everything that used it by making it return an isc_result_t.
+ * It would need to do that if it had to allocate memory to store
+ * pointers to each array passed in.
+ */
+ if (lctx->modules == NULL)
+ lctx->modules = modules;
+
+ else {
+ /*
+ * Adjust the last (NULL) pointer of the already registered
+ * modules to point to the incoming array.
+ */
+ for (modp = lctx->modules; modp->name != NULL; )
+ if (modp->id == UINT_MAX)
+ /*
+ * The name pointer points to the next array.
+ * Ick.
+ */
+ DE_CONST(modp->name, modp);
+ else
+ modp++;
+
+ modp->name = (void *)modules;
+ modp->id = UINT_MAX;
+ }
+
+ /*
+ * Update the id number of the module with its new global id.
+ */
+ for (modp = modules; modp->name != NULL; modp++)
+ modp->id = lctx->module_count++;
+}
+
+isc_logmodule_t *
+isc_log_modulebyname(isc_log_t *lctx, const char *name) {
+ isc_logmodule_t *modp;
+
+ REQUIRE(VALID_CONTEXT(lctx));
+ REQUIRE(name != NULL);
+
+ for (modp = lctx->modules; modp->name != NULL; )
+ if (modp->id == UINT_MAX)
+ /*
+ * modp is neither modified nor returned to the
+ * caller, so removing its const qualifier is ok.
+ */
+ DE_CONST(modp->name, modp);
+ else {
+ if (strcmp(modp->name, name) == 0)
+ return (modp);
+ modp++;
+ }
+
+ return (NULL);
+}
+
+isc_result_t
+isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
+ unsigned int type, int level,
+ const isc_logdestination_t *destination,
+ unsigned int flags)
+{
+ isc_logchannel_t *channel;
+ isc_mem_t *mctx;
+
+ REQUIRE(VALID_CONFIG(lcfg));
+ REQUIRE(name != NULL);
+ REQUIRE(type == ISC_LOG_TOSYSLOG || type == ISC_LOG_TOFILE ||
+ type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL);
+ REQUIRE(destination != NULL || type == ISC_LOG_TONULL);
+ REQUIRE(level >= ISC_LOG_CRITICAL);
+ REQUIRE((flags &
+ (unsigned int)~(ISC_LOG_PRINTALL | ISC_LOG_DEBUGONLY)) == 0);
+
+ /* XXXDCL find duplicate names? */
+
+ mctx = lcfg->lctx->mctx;
+
+ channel = isc_mem_get(mctx, sizeof(*channel));
+ if (channel == NULL)
+ return (ISC_R_NOMEMORY);
+
+ channel->name = isc_mem_strdup(mctx, name);
+ if (channel->name == NULL) {
+ isc_mem_put(mctx, channel, sizeof(*channel));
+ return (ISC_R_NOMEMORY);
+ }
+
+ channel->type = type;
+ channel->level = level;
+ channel->flags = flags;
+ ISC_LINK_INIT(channel, link);
+
+ switch (type) {
+ case ISC_LOG_TOSYSLOG:
+ FACILITY(channel) = destination->facility;
+ break;
+
+ case ISC_LOG_TOFILE:
+ /*
+ * The file name is copied because greatest_version wants
+ * to scribble on it, so it needs to be definitely in
+ * writable memory.
+ */
+ FILE_NAME(channel) =
+ isc_mem_strdup(mctx, destination->file.name);
+ FILE_STREAM(channel) = NULL;
+ FILE_VERSIONS(channel) = destination->file.versions;
+ FILE_MAXSIZE(channel) = destination->file.maximum_size;
+ FILE_MAXREACHED(channel) = ISC_FALSE;
+ break;
+
+ case ISC_LOG_TOFILEDESC:
+ FILE_NAME(channel) = NULL;
+ FILE_STREAM(channel) = destination->file.stream;
+ FILE_MAXSIZE(channel) = 0;
+ FILE_VERSIONS(channel) = ISC_LOG_ROLLNEVER;
+ break;
+
+ case ISC_LOG_TONULL:
+ /* Nothing. */
+ break;
+
+ default:
+ isc_mem_put(mctx, channel->name, strlen(channel->name) + 1);
+ isc_mem_put(mctx, channel, sizeof(*channel));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ ISC_LIST_PREPEND(lcfg->channels, channel, link);
+
+ /*
+ * If default_stderr was redefined, make the default category
+ * point to the new default_stderr.
+ */
+ if (strcmp(name, "default_stderr") == 0)
+ default_channel.channel = channel;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
+ const isc_logcategory_t *category,
+ const isc_logmodule_t *module)
+{
+ isc_log_t *lctx;
+ isc_logchannel_t *channel;
+ isc_result_t result = ISC_R_SUCCESS;
+ unsigned int i;
+
+ REQUIRE(VALID_CONFIG(lcfg));
+ REQUIRE(name != NULL);
+
+ lctx = lcfg->lctx;
+
+ REQUIRE(category == NULL || category->id < lctx->category_count);
+ REQUIRE(module == NULL || module->id < lctx->module_count);
+
+ for (channel = ISC_LIST_HEAD(lcfg->channels); channel != NULL;
+ channel = ISC_LIST_NEXT(channel, link))
+ if (strcmp(name, channel->name) == 0)
+ break;
+
+ if (channel == NULL)
+ return (ISC_R_NOTFOUND);
+
+ if (category != NULL)
+ result = assignchannel(lcfg, category->id, module, channel);
+
+ else
+ /*
+ * Assign to all categories. Note that this includes
+ * the default channel.
+ */
+ for (i = 0; i < lctx->category_count; i++) {
+ result = assignchannel(lcfg, i, module, channel);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+
+ return (result);
+}
+
+void
+isc_log_write(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *format, ...)
+{
+ va_list args;
+
+ /*
+ * Contract checking is done in isc_log_doit().
+ */
+
+ va_start(args, format);
+ isc_log_doit(lctx, category, module, level, ISC_FALSE,
+ NULL, 0, 0, format, args);
+ va_end(args);
+}
+
+void
+isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ const char *format, va_list args)
+{
+ /*
+ * Contract checking is done in isc_log_doit().
+ */
+ isc_log_doit(lctx, category, module, level, ISC_FALSE,
+ NULL, 0, 0, format, args);
+}
+
+void
+isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *format, ...)
+{
+ va_list args;
+
+ /*
+ * Contract checking is done in isc_log_doit().
+ */
+
+ va_start(args, format);
+ isc_log_doit(lctx, category, module, level, ISC_TRUE,
+ NULL, 0, 0, format, args);
+ va_end(args);
+}
+
+void
+isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ const char *format, va_list args)
+{
+ /*
+ * Contract checking is done in isc_log_doit().
+ */
+ isc_log_doit(lctx, category, module, level, ISC_TRUE,
+ NULL, 0, 0, format, args);
+}
+
+void
+isc_log_iwrite(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int msg,
+ const char *format, ...)
+{
+ va_list args;
+
+ /*
+ * Contract checking is done in isc_log_doit().
+ */
+
+ va_start(args, format);
+ isc_log_doit(lctx, category, module, level, ISC_FALSE,
+ msgcat, msgset, msg, format, args);
+ va_end(args);
+}
+
+void
+isc_log_ivwrite(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int msg,
+ const char *format, va_list args)
+{
+ /*
+ * Contract checking is done in isc_log_doit().
+ */
+ isc_log_doit(lctx, category, module, level, ISC_FALSE,
+ msgcat, msgset, msg, format, args);
+}
+
+void
+isc_log_iwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int msg,
+ const char *format, ...)
+{
+ va_list args;
+
+ /*
+ * Contract checking is done in isc_log_doit().
+ */
+
+ va_start(args, format);
+ isc_log_doit(lctx, category, module, level, ISC_TRUE,
+ msgcat, msgset, msg, format, args);
+ va_end(args);
+}
+
+void
+isc_log_ivwrite1(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int msg,
+ const char *format, va_list args)
+{
+ /*
+ * Contract checking is done in isc_log_doit().
+ */
+ isc_log_doit(lctx, category, module, level, ISC_TRUE,
+ msgcat, msgset, msg, format, args);
+}
+
+void
+isc_log_setcontext(isc_log_t *lctx) {
+ isc_lctx = lctx;
+}
+
+void
+isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level) {
+ isc_logchannel_t *channel;
+
+ REQUIRE(VALID_CONTEXT(lctx));
+
+ LOCK(&lctx->lock);
+
+ lctx->debug_level = level;
+ /*
+ * Close ISC_LOG_DEBUGONLY channels if level is zero.
+ */
+ if (lctx->debug_level == 0)
+ for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
+ channel != NULL;
+ channel = ISC_LIST_NEXT(channel, link))
+ if (channel->type == ISC_LOG_TOFILE &&
+ (channel->flags & ISC_LOG_DEBUGONLY) != 0 &&
+ FILE_STREAM(channel) != NULL) {
+ (void)fclose(FILE_STREAM(channel));
+ FILE_STREAM(channel) = NULL;
+ }
+ UNLOCK(&lctx->lock);
+}
+
+unsigned int
+isc_log_getdebuglevel(isc_log_t *lctx) {
+ REQUIRE(VALID_CONTEXT(lctx));
+
+ return (lctx->debug_level);
+}
+
+void
+isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval) {
+ REQUIRE(VALID_CONFIG(lcfg));
+
+ lcfg->duplicate_interval = interval;
+}
+
+unsigned int
+isc_log_getduplicateinterval(isc_logconfig_t *lcfg) {
+ REQUIRE(VALID_CONTEXT(lcfg));
+
+ return (lcfg->duplicate_interval);
+}
+
+isc_result_t
+isc_log_settag(isc_logconfig_t *lcfg, const char *tag) {
+ REQUIRE(VALID_CONFIG(lcfg));
+
+ if (tag != NULL && *tag != '\0') {
+ if (lcfg->tag != NULL)
+ isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
+ lcfg->tag = isc_mem_strdup(lcfg->lctx->mctx, tag);
+ if (lcfg->tag == NULL)
+ return (ISC_R_NOMEMORY);
+
+ } else {
+ if (lcfg->tag != NULL)
+ isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
+ lcfg->tag = NULL;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+char *
+isc_log_gettag(isc_logconfig_t *lcfg) {
+ REQUIRE(VALID_CONFIG(lcfg));
+
+ return (lcfg->tag);
+}
+
+/* XXXDCL NT -- This interface will assuredly be changing. */
+void
+isc_log_opensyslog(const char *tag, int options, int facility) {
+ (void)openlog(tag, options, facility);
+}
+
+void
+isc_log_closefilelogs(isc_log_t *lctx) {
+ isc_logchannel_t *channel;
+
+ REQUIRE(VALID_CONTEXT(lctx));
+
+ LOCK(&lctx->lock);
+ for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
+ channel != NULL;
+ channel = ISC_LIST_NEXT(channel, link))
+
+ if (channel->type == ISC_LOG_TOFILE &&
+ FILE_STREAM(channel) != NULL) {
+ (void)fclose(FILE_STREAM(channel));
+ FILE_STREAM(channel) = NULL;
+ }
+ UNLOCK(&lctx->lock);
+}
+
+/****
+ **** Internal functions
+ ****/
+
+static isc_result_t
+assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
+ const isc_logmodule_t *module, isc_logchannel_t *channel)
+{
+ isc_logchannellist_t *new_item;
+ isc_log_t *lctx;
+ isc_result_t result;
+
+ REQUIRE(VALID_CONFIG(lcfg));
+
+ lctx = lcfg->lctx;
+
+ REQUIRE(category_id < lctx->category_count);
+ REQUIRE(module == NULL || module->id < lctx->module_count);
+ REQUIRE(channel != NULL);
+
+ /*
+ * Ensure lcfg->channellist_count == lctx->category_count.
+ */
+ result = sync_channellist(lcfg);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ new_item = isc_mem_get(lctx->mctx, sizeof(*new_item));
+ if (new_item == NULL)
+ return (ISC_R_NOMEMORY);
+
+ new_item->channel = channel;
+ new_item->module = module;
+ ISC_LIST_INITANDPREPEND(lcfg->channellists[category_id],
+ new_item, link);
+
+ /*
+ * Remember the highest logging level set by any channel in the
+ * logging config, so isc_log_doit() can quickly return if the
+ * message is too high to be logged by any channel.
+ */
+ if (channel->type != ISC_LOG_TONULL) {
+ if (lcfg->highest_level < channel->level)
+ lcfg->highest_level = channel->level;
+ if (channel->level == ISC_LOG_DYNAMIC)
+ lcfg->dynamic = ISC_TRUE;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This would ideally be part of isc_log_registercategories(), except then
+ * that function would have to return isc_result_t instead of void.
+ */
+static isc_result_t
+sync_channellist(isc_logconfig_t *lcfg) {
+ unsigned int bytes;
+ isc_log_t *lctx;
+ void *lists;
+
+ REQUIRE(VALID_CONFIG(lcfg));
+
+ lctx = lcfg->lctx;
+
+ REQUIRE(lctx->category_count != 0);
+
+ if (lctx->category_count == lcfg->channellist_count)
+ return (ISC_R_SUCCESS);
+
+ bytes = lctx->category_count * sizeof(ISC_LIST(isc_logchannellist_t));
+
+ lists = isc_mem_get(lctx->mctx, bytes);
+
+ if (lists == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(lists, 0, bytes);
+
+ if (lcfg->channellist_count != 0) {
+ bytes = lcfg->channellist_count *
+ sizeof(ISC_LIST(isc_logchannellist_t));
+ memcpy(lists, lcfg->channellists, bytes);
+ isc_mem_put(lctx->mctx, lcfg->channellists, bytes);
+ }
+
+ lcfg->channellists = lists;
+ lcfg->channellist_count = lctx->category_count;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+greatest_version(isc_logchannel_t *channel, int *greatestp) {
+ /* XXXDCL HIGHLY NT */
+ char *basename, *digit_end;
+ const char *dirname;
+ int version, greatest = -1;
+ unsigned int basenamelen;
+ isc_dir_t dir;
+ isc_result_t result;
+ char sep = '/';
+#ifdef _WIN32
+ char *basename2;
+#endif
+
+ REQUIRE(channel->type == ISC_LOG_TOFILE);
+
+ /*
+ * It is safe to DE_CONST the file.name because it was copied
+ * with isc_mem_strdup in isc_log_createchannel.
+ */
+ basename = strrchr(FILE_NAME(channel), sep);
+#ifdef _WIN32
+ basename2 = strrchr(FILE_NAME(channel), '\\');
+ if ((basename != NULL && basename2 != NULL && basename2 > basename) ||
+ (basename == NULL && basename2 != NULL)) {
+ basename = basename2;
+ sep = '\\';
+ }
+#endif
+ if (basename != NULL) {
+ *basename++ = '\0';
+ dirname = FILE_NAME(channel);
+ } else {
+ DE_CONST(FILE_NAME(channel), basename);
+ dirname = ".";
+ }
+ basenamelen = strlen(basename);
+
+ isc_dir_init(&dir);
+ result = isc_dir_open(&dir, dirname);
+
+ /*
+ * Replace the file separator if it was taken out.
+ */
+ if (basename != FILE_NAME(channel))
+ *(basename - 1) = sep;
+
+ /*
+ * Return if the directory open failed.
+ */
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
+ if (dir.entry.length > basenamelen &&
+ strncmp(dir.entry.name, basename, basenamelen) == 0 &&
+ dir.entry.name[basenamelen] == '.') {
+
+ version = strtol(&dir.entry.name[basenamelen + 1],
+ &digit_end, 10);
+ if (*digit_end == '\0' && version > greatest)
+ greatest = version;
+ }
+ }
+ isc_dir_close(&dir);
+
+ *greatestp = ++greatest;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+roll_log(isc_logchannel_t *channel) {
+ int i, n, greatest;
+ char current[PATH_MAX + 1];
+ char new[PATH_MAX + 1];
+ const char *path;
+ isc_result_t result;
+
+ /*
+ * Do nothing (not even excess version trimming) if ISC_LOG_ROLLNEVER
+ * is specified. Apparently complete external control over the log
+ * files is desired.
+ */
+ if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
+ return (ISC_R_SUCCESS);
+
+ path = FILE_NAME(channel);
+
+ /*
+ * Set greatest_version to the greatest existing version
+ * (not the maximum requested version). This is 1 based even
+ * though the file names are 0 based, so an oldest log of log.1
+ * is a greatest_version of 2.
+ */
+ result = greatest_version(channel, &greatest);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Now greatest should be set to the highest version number desired.
+ * Since the highest number is one less than FILE_VERSIONS(channel)
+ * when not doing infinite log rolling, greatest will need to be
+ * decremented when it is equal to -- or greater than --
+ * FILE_VERSIONS(channel). When greatest is less than
+ * FILE_VERSIONS(channel), it is already suitable for use as
+ * the maximum version number.
+ */
+
+ if (FILE_VERSIONS(channel) == ISC_LOG_ROLLINFINITE ||
+ FILE_VERSIONS(channel) > greatest)
+ ; /* Do nothing. */
+ else
+ /*
+ * When greatest is >= FILE_VERSIONS(channel), it needs to
+ * be reduced until it is FILE_VERSIONS(channel) - 1.
+ * Remove any excess logs on the way to that value.
+ */
+ while (--greatest >= FILE_VERSIONS(channel)) {
+ n = snprintf(current, sizeof(current), "%s.%d",
+ path, greatest);
+ if (n >= (int)sizeof(current) || n < 0)
+ result = ISC_R_NOSPACE;
+ else
+ result = isc_file_remove(current);
+ if (result != ISC_R_SUCCESS &&
+ result != ISC_R_FILENOTFOUND)
+ syslog(LOG_ERR,
+ "unable to remove log file '%s.%d': %s",
+ path, greatest,
+ isc_result_totext(result));
+ }
+
+ for (i = greatest; i > 0; i--) {
+ result = ISC_R_SUCCESS;
+ n = snprintf(current, sizeof(current), "%s.%d", path, i - 1);
+ if (n >= (int)sizeof(current) || n < 0)
+ result = ISC_R_NOSPACE;
+ if (result == ISC_R_SUCCESS) {
+ n = snprintf(new, sizeof(new), "%s.%d", path, i);
+ if (n >= (int)sizeof(new) || n < 0)
+ result = ISC_R_NOSPACE;
+ }
+ if (result == ISC_R_SUCCESS)
+ result = isc_file_rename(current, new);
+ if (result != ISC_R_SUCCESS &&
+ result != ISC_R_FILENOTFOUND)
+ syslog(LOG_ERR,
+ "unable to rename log file '%s.%d' to "
+ "'%s.%d': %s", path, i - 1, path, i,
+ isc_result_totext(result));
+ }
+
+ if (FILE_VERSIONS(channel) != 0) {
+ n = snprintf(new, sizeof(new), "%s.0", path);
+ if (n >= (int)sizeof(new) || n < 0)
+ result = ISC_R_NOSPACE;
+ else
+ result = isc_file_rename(path, new);
+ if (result != ISC_R_SUCCESS &&
+ result != ISC_R_FILENOTFOUND)
+ syslog(LOG_ERR,
+ "unable to rename log file '%s' to '%s.0': %s",
+ path, path, isc_result_totext(result));
+ } else {
+ result = isc_file_remove(path);
+ if (result != ISC_R_SUCCESS &&
+ result != ISC_R_FILENOTFOUND)
+ syslog(LOG_ERR, "unable to remove log file '%s': %s",
+ path, isc_result_totext(result));
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+isc_log_open(isc_logchannel_t *channel) {
+ struct stat statbuf;
+ isc_boolean_t regular_file;
+ isc_boolean_t roll = ISC_FALSE;
+ isc_result_t result = ISC_R_SUCCESS;
+ const char *path;
+
+ REQUIRE(channel->type == ISC_LOG_TOFILE);
+ REQUIRE(FILE_STREAM(channel) == NULL);
+
+ path = FILE_NAME(channel);
+
+ REQUIRE(path != NULL && *path != '\0');
+
+ /*
+ * Determine type of file; only regular files will be
+ * version renamed, and only if the base file exists
+ * and either has no size limit or has reached its size limit.
+ */
+ if (stat(path, &statbuf) == 0) {
+ regular_file = S_ISREG(statbuf.st_mode) ? ISC_TRUE : ISC_FALSE;
+ /* XXXDCL if not regular_file complain? */
+ if ((FILE_MAXSIZE(channel) == 0 &&
+ FILE_VERSIONS(channel) != ISC_LOG_ROLLNEVER) ||
+ (FILE_MAXSIZE(channel) > 0 &&
+ statbuf.st_size >= FILE_MAXSIZE(channel)))
+ roll = regular_file;
+ } else if (errno == ENOENT)
+ regular_file = ISC_TRUE;
+ else
+ result = ISC_R_INVALIDFILE;
+
+ /*
+ * Version control.
+ */
+ if (result == ISC_R_SUCCESS && roll) {
+ if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
+ return (ISC_R_MAXSIZE);
+ result = roll_log(channel);
+ if (result != ISC_R_SUCCESS) {
+ if ((channel->flags & ISC_LOG_OPENERR) == 0) {
+ syslog(LOG_ERR,
+ "isc_log_open: roll_log '%s' "
+ "failed: %s",
+ FILE_NAME(channel),
+ isc_result_totext(result));
+ channel->flags |= ISC_LOG_OPENERR;
+ }
+ return (result);
+ }
+ }
+
+ result = isc_stdio_open(path, "a", &FILE_STREAM(channel));
+
+ return (result);
+}
+
+isc_boolean_t
+isc_log_wouldlog(isc_log_t *lctx, int level) {
+ /*
+ * Try to avoid locking the mutex for messages which can't
+ * possibly be logged to any channels -- primarily debugging
+ * messages that the debug level is not high enough to print.
+ *
+ * If the level is (mathematically) less than or equal to the
+ * highest_level, or if there is a dynamic channel and the level is
+ * less than or equal to the debug level, the main loop must be
+ * entered to see if the message should really be output.
+ *
+ * NOTE: this is UNLOCKED access to the logconfig. However,
+ * the worst thing that can happen is that a bad decision is made
+ * about returning without logging, and that's not a big concern,
+ * because that's a risk anyway if the logconfig is being
+ * dynamically changed.
+ */
+
+ if (lctx == NULL || lctx->logconfig == NULL)
+ return (ISC_FALSE);
+
+ return (ISC_TF(level <= lctx->logconfig->highest_level ||
+ (lctx->logconfig->dynamic &&
+ level <= lctx->debug_level)));
+}
+
+static void
+isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, isc_boolean_t write_once,
+ isc_msgcat_t *msgcat, int msgset, int msg,
+ const char *format, va_list args)
+{
+ int syslog_level;
+ char time_string[64];
+ char level_string[24];
+ const char *iformat;
+ struct stat statbuf;
+ isc_boolean_t matched = ISC_FALSE;
+ isc_boolean_t printtime, printtag;
+ isc_boolean_t printcategory, printmodule, printlevel;
+ isc_logconfig_t *lcfg;
+ isc_logchannel_t *channel;
+ isc_logchannellist_t *category_channels;
+ isc_result_t result;
+
+ REQUIRE(lctx == NULL || VALID_CONTEXT(lctx));
+ REQUIRE(category != NULL);
+ REQUIRE(module != NULL);
+ REQUIRE(level != ISC_LOG_DYNAMIC);
+ REQUIRE(format != NULL);
+
+ /*
+ * Programs can use libraries that use this logging code without
+ * wanting to do any logging, thus the log context is allowed to
+ * be non-existent.
+ */
+ if (lctx == NULL)
+ return;
+
+ REQUIRE(category->id < lctx->category_count);
+ REQUIRE(module->id < lctx->module_count);
+
+ if (! isc_log_wouldlog(lctx, level))
+ return;
+
+ if (msgcat != NULL)
+ iformat = isc_msgcat_get(msgcat, msgset, msg, format);
+ else
+ iformat = format;
+
+ time_string[0] = '\0';
+ level_string[0] = '\0';
+
+ LOCK(&lctx->lock);
+
+ lctx->buffer[0] = '\0';
+
+ lcfg = lctx->logconfig;
+
+ category_channels = ISC_LIST_HEAD(lcfg->channellists[category->id]);
+
+ /*
+ * XXXDCL add duplicate filtering? (To not write multiple times to
+ * the same source via various channels).
+ */
+ do {
+ /*
+ * If the channel list end was reached and a match was made,
+ * everything is finished.
+ */
+ if (category_channels == NULL && matched)
+ break;
+
+ if (category_channels == NULL && ! matched &&
+ category_channels != ISC_LIST_HEAD(lcfg->channellists[0]))
+ /*
+ * No category/module pair was explicitly configured.
+ * Try the category named "default".
+ */
+ category_channels =
+ ISC_LIST_HEAD(lcfg->channellists[0]);
+
+ if (category_channels == NULL && ! matched)
+ /*
+ * No matching module was explicitly configured
+ * for the category named "default". Use the internal
+ * default channel.
+ */
+ category_channels = &default_channel;
+
+ if (category_channels->module != NULL &&
+ category_channels->module != module) {
+ category_channels = ISC_LIST_NEXT(category_channels,
+ link);
+ continue;
+ }
+
+ matched = ISC_TRUE;
+
+ channel = category_channels->channel;
+ category_channels = ISC_LIST_NEXT(category_channels, link);
+
+ if (((channel->flags & ISC_LOG_DEBUGONLY) != 0) &&
+ lctx->debug_level == 0)
+ continue;
+
+ if (channel->level == ISC_LOG_DYNAMIC) {
+ if (lctx->debug_level < level)
+ continue;
+ } else if (channel->level < level)
+ continue;
+
+ if ((channel->flags & ISC_LOG_PRINTTIME) != 0 &&
+ time_string[0] == '\0') {
+ isc_time_t isctime;
+
+ TIME_NOW(&isctime);
+ isc_time_formattimestamp(&isctime, time_string,
+ sizeof(time_string));
+ }
+
+ if ((channel->flags & ISC_LOG_PRINTLEVEL) != 0 &&
+ level_string[0] == '\0') {
+ if (level < ISC_LOG_CRITICAL)
+ snprintf(level_string, sizeof(level_string),
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_LOG,
+ ISC_MSG_LEVEL,
+ "level %d: "),
+ level);
+ else if (level > ISC_LOG_DYNAMIC)
+ snprintf(level_string, sizeof(level_string),
+ "%s %d: ", log_level_strings[0],
+ level);
+ else
+ snprintf(level_string, sizeof(level_string),
+ "%s: ", log_level_strings[-level]);
+ }
+
+ /*
+ * Only format the message once.
+ */
+ if (lctx->buffer[0] == '\0') {
+ (void)vsnprintf(lctx->buffer, sizeof(lctx->buffer),
+ iformat, args);
+
+ /*
+ * Check for duplicates.
+ */
+ if (write_once) {
+ isc_logmessage_t *message, *new;
+ isc_time_t oldest;
+ isc_interval_t interval;
+
+ isc_interval_set(&interval,
+ lcfg->duplicate_interval, 0);
+
+ /*
+ * 'oldest' is the age of the oldest messages
+ * which fall within the duplicate_interval
+ * range.
+ */
+ TIME_NOW(&oldest);
+ if (isc_time_subtract(&oldest, &interval, &oldest)
+ != ISC_R_SUCCESS)
+ /*
+ * Can't effectively do the checking
+ * without having a valid time.
+ */
+ message = NULL;
+ else
+ message =ISC_LIST_HEAD(lctx->messages);
+
+ while (message != NULL) {
+ if (isc_time_compare(&message->time,
+ &oldest) < 0) {
+ /*
+ * This message is older
+ * than the duplicate_interval,
+ * so it should be dropped from
+ * the history.
+ *
+ * Setting the interval to be
+ * to be longer will obviously
+ * not cause the expired
+ * message to spring back into
+ * existence.
+ */
+ new = ISC_LIST_NEXT(message,
+ link);
+
+ ISC_LIST_UNLINK(lctx->messages,
+ message, link);
+
+ isc_mem_put(lctx->mctx,
+ message,
+ sizeof(*message) + 1 +
+ strlen(message->text));
+
+ message = new;
+ continue;
+ }
+
+ /*
+ * This message is in the duplicate
+ * filtering interval ...
+ */
+ if (strcmp(lctx->buffer, message->text)
+ == 0) {
+ /*
+ * ... and it is a duplicate.
+ * Unlock the mutex and
+ * get the hell out of Dodge.
+ */
+ UNLOCK(&lctx->lock);
+ return;
+ }
+
+ message = ISC_LIST_NEXT(message, link);
+ }
+
+ /*
+ * It wasn't in the duplicate interval,
+ * so add it to the message list.
+ */
+ new = isc_mem_get(lctx->mctx,
+ sizeof(isc_logmessage_t) +
+ strlen(lctx->buffer) + 1);
+ if (new != NULL) {
+ /*
+ * Put the text immediately after
+ * the struct. The strcpy is safe.
+ */
+ new->text = (char *)(new + 1);
+ strcpy(new->text, lctx->buffer);
+
+ TIME_NOW(&new->time);
+
+ ISC_LIST_APPEND(lctx->messages,
+ new, link);
+ }
+ }
+ }
+
+ printtime = ISC_TF((channel->flags & ISC_LOG_PRINTTIME)
+ != 0);
+ printtag = ISC_TF((channel->flags & ISC_LOG_PRINTTAG)
+ != 0 && lcfg->tag != NULL);
+ printcategory = ISC_TF((channel->flags & ISC_LOG_PRINTCATEGORY)
+ != 0);
+ printmodule = ISC_TF((channel->flags & ISC_LOG_PRINTMODULE)
+ != 0);
+ printlevel = ISC_TF((channel->flags & ISC_LOG_PRINTLEVEL)
+ != 0);
+
+ switch (channel->type) {
+ case ISC_LOG_TOFILE:
+ if (FILE_MAXREACHED(channel)) {
+ /*
+ * If the file can be rolled, OR
+ * If the file no longer exists, OR
+ * If the file is less than the maximum size,
+ * (such as if it had been renamed and
+ * a new one touched, or it was truncated
+ * in place)
+ * ... then close it to trigger reopening.
+ */
+ if (FILE_VERSIONS(channel) !=
+ ISC_LOG_ROLLNEVER ||
+ (stat(FILE_NAME(channel), &statbuf) != 0 &&
+ errno == ENOENT) ||
+ statbuf.st_size < FILE_MAXSIZE(channel)) {
+ (void)fclose(FILE_STREAM(channel));
+ FILE_STREAM(channel) = NULL;
+ FILE_MAXREACHED(channel) = ISC_FALSE;
+ } else
+ /*
+ * Eh, skip it.
+ */
+ break;
+ }
+
+ if (FILE_STREAM(channel) == NULL) {
+ result = isc_log_open(channel);
+ if (result != ISC_R_SUCCESS &&
+ result != ISC_R_MAXSIZE &&
+ (channel->flags & ISC_LOG_OPENERR) == 0) {
+ syslog(LOG_ERR,
+ "isc_log_open '%s' failed: %s",
+ FILE_NAME(channel),
+ isc_result_totext(result));
+ channel->flags |= ISC_LOG_OPENERR;
+ }
+ if (result != ISC_R_SUCCESS)
+ break;
+ channel->flags &= ~ISC_LOG_OPENERR;
+ }
+ /* FALLTHROUGH */
+
+ case ISC_LOG_TOFILEDESC:
+ fprintf(FILE_STREAM(channel), "%s%s%s%s%s%s%s%s%s%s\n",
+ printtime ? time_string : "",
+ printtime ? " " : "",
+ printtag ? lcfg->tag : "",
+ printtag ? ": " : "",
+ printcategory ? category->name : "",
+ printcategory ? ": " : "",
+ printmodule ? (module != NULL ? module->name
+ : "no_module")
+ : "",
+ printmodule ? ": " : "",
+ printlevel ? level_string : "",
+ lctx->buffer);
+
+ fflush(FILE_STREAM(channel));
+
+ /*
+ * If the file now exceeds its maximum size
+ * threshold, note it so that it will not be logged
+ * to any more.
+ */
+ if (FILE_MAXSIZE(channel) > 0) {
+ INSIST(channel->type == ISC_LOG_TOFILE);
+
+ /* XXXDCL NT fstat/fileno */
+ /* XXXDCL complain if fstat fails? */
+ if (fstat(fileno(FILE_STREAM(channel)),
+ &statbuf) >= 0 &&
+ statbuf.st_size > FILE_MAXSIZE(channel))
+ FILE_MAXREACHED(channel) = ISC_TRUE;
+ }
+
+ break;
+
+ case ISC_LOG_TOSYSLOG:
+ if (level > 0)
+ syslog_level = LOG_DEBUG;
+ else if (level < ISC_LOG_CRITICAL)
+ syslog_level = LOG_CRIT;
+ else
+ syslog_level = syslog_map[-level];
+
+ (void)syslog(FACILITY(channel) | syslog_level,
+ "%s%s%s%s%s%s%s%s%s%s",
+ printtime ? time_string : "",
+ printtime ? " " : "",
+ printtag ? lcfg->tag : "",
+ printtag ? ": " : "",
+ printcategory ? category->name : "",
+ printcategory ? ": " : "",
+ printmodule ? (module != NULL ? module->name
+ : "no_module")
+ : "",
+ printmodule ? ": " : "",
+ printlevel ? level_string : "",
+ lctx->buffer);
+ break;
+
+ case ISC_LOG_TONULL:
+ break;
+
+ }
+
+ } while (1);
+
+ UNLOCK(&lctx->lock);
+}
diff --git a/lib/isc/md5.c b/lib/isc/md5.c
new file mode 100644
index 0000000..5004c3e
--- /dev/null
+++ b/lib/isc/md5.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: md5.c,v 1.14 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#include "config.h"
+
+#include <isc/assertions.h>
+#include <isc/md5.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+static void
+byteSwap(isc_uint32_t *buf, unsigned words)
+{
+ unsigned char *p = (unsigned char *)buf;
+
+ do {
+ *buf++ = (isc_uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
+ ((unsigned)p[1] << 8 | p[0]);
+ p += 4;
+ } while (--words);
+}
+
+/*!
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+isc_md5_init(isc_md5_t *ctx) {
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bytes[0] = 0;
+ ctx->bytes[1] = 0;
+}
+
+void
+isc_md5_invalidate(isc_md5_t *ctx) {
+ memset(ctx, 0, sizeof(isc_md5_t));
+}
+
+/*@{*/
+/*! The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+/*@}*/
+
+/*! This is the central step in the MD5 algorithm. */
+#define MD5STEP(f,w,x,y,z,in,s) \
+ (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+/*!
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void
+transform(isc_uint32_t buf[4], isc_uint32_t const in[16]) {
+ register isc_uint32_t a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*!
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) {
+ isc_uint32_t t;
+
+ /* Update byte count */
+
+ t = ctx->bytes[0];
+ if ((ctx->bytes[0] = t + len) < t)
+ ctx->bytes[1]++; /* Carry from low to high */
+
+ t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
+ if (t > len) {
+ memcpy((unsigned char *)ctx->in + 64 - t, buf, len);
+ return;
+ }
+ /* First chunk is an odd size */
+ memcpy((unsigned char *)ctx->in + 64 - t, buf, t);
+ byteSwap(ctx->in, 16);
+ transform(ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+
+ /* Process data in 64-byte chunks */
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteSwap(ctx->in, 16);
+ transform(ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+ memcpy(ctx->in, buf, len);
+}
+
+/*!
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
+ int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
+ unsigned char *p = (unsigned char *)ctx->in + count;
+
+ /* Set the first char of padding to 0x80. There is always room. */
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 56 bytes (-8..55) */
+ count = 56 - 1 - count;
+
+ if (count < 0) { /* Padding forces an extra block */
+ memset(p, 0, count + 8);
+ byteSwap(ctx->in, 16);
+ transform(ctx->buf, ctx->in);
+ p = (unsigned char *)ctx->in;
+ count = 56;
+ }
+ memset(p, 0, count);
+ byteSwap(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ctx->in[14] = ctx->bytes[0] << 3;
+ ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
+ transform(ctx->buf, ctx->in);
+
+ byteSwap(ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(isc_md5_t)); /* In case it's sensitive */
+}
diff --git a/lib/isc/mem.c b/lib/isc/mem.c
new file mode 100644
index 0000000..8f030a3
--- /dev/null
+++ b/lib/isc/mem.c
@@ -0,0 +1,2171 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-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: mem.c,v 1.145 2008/04/02 02:37:42 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#include <limits.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/once.h>
+#include <isc/ondestroy.h>
+#include <isc/string.h>
+#include <isc/mutex.h>
+#include <isc/print.h>
+#include <isc/util.h>
+#include <isc/xml.h>
+
+#define MCTXLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) LOCK(l)
+#define MCTXUNLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) UNLOCK(l)
+
+#ifndef ISC_MEM_DEBUGGING
+#define ISC_MEM_DEBUGGING 0
+#endif
+LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
+
+/*
+ * Constants.
+ */
+
+#define DEF_MAX_SIZE 1100
+#define DEF_MEM_TARGET 4096
+#define ALIGNMENT_SIZE 8 /*%< must be a power of 2 */
+#define NUM_BASIC_BLOCKS 64 /*%< must be > 1 */
+#define TABLE_INCREMENT 1024
+#define DEBUGLIST_COUNT 1024
+
+/*
+ * Types.
+ */
+#if ISC_MEM_TRACKLINES
+typedef struct debuglink debuglink_t;
+struct debuglink {
+ ISC_LINK(debuglink_t) link;
+ const void *ptr[DEBUGLIST_COUNT];
+ unsigned int size[DEBUGLIST_COUNT];
+ const char *file[DEBUGLIST_COUNT];
+ unsigned int line[DEBUGLIST_COUNT];
+ unsigned int count;
+};
+
+#define FLARG_PASS , file, line
+#define FLARG , const char *file, int line
+#else
+#define FLARG_PASS
+#define FLARG
+#endif
+
+typedef struct element element;
+struct element {
+ element * next;
+};
+
+typedef struct {
+ /*!
+ * This structure must be ALIGNMENT_SIZE bytes.
+ */
+ union {
+ size_t size;
+ isc_mem_t *ctx;
+ char bytes[ALIGNMENT_SIZE];
+ } u;
+} size_info;
+
+struct stats {
+ unsigned long gets;
+ unsigned long totalgets;
+ unsigned long blocks;
+ unsigned long freefrags;
+};
+
+#define MEM_MAGIC ISC_MAGIC('M', 'e', 'm', 'C')
+#define VALID_CONTEXT(c) ISC_MAGIC_VALID(c, MEM_MAGIC)
+
+#if ISC_MEM_TRACKLINES
+typedef ISC_LIST(debuglink_t) debuglist_t;
+#endif
+
+/* List of all active memory contexts. */
+
+static ISC_LIST(isc_mem_t) contexts;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_mutex_t lock;
+
+/*%
+ * Total size of lost memory due to a bug of external library.
+ * Locked by the global lock.
+ */
+static isc_uint64_t totallost;
+
+struct isc_mem {
+ unsigned int magic;
+ isc_ondestroy_t ondestroy;
+ unsigned int flags;
+ isc_mutex_t lock;
+ isc_memalloc_t memalloc;
+ isc_memfree_t memfree;
+ void * arg;
+ size_t max_size;
+ isc_boolean_t checkfree;
+ struct stats * stats;
+ unsigned int references;
+ char name[16];
+ void * tag;
+ size_t quota;
+ size_t total;
+ size_t inuse;
+ size_t maxinuse;
+ size_t hi_water;
+ size_t lo_water;
+ isc_boolean_t hi_called;
+ isc_mem_water_t water;
+ void * water_arg;
+ ISC_LIST(isc_mempool_t) pools;
+ unsigned int poolcnt;
+
+ /* ISC_MEMFLAG_INTERNAL */
+ size_t mem_target;
+ element ** freelists;
+ element * basic_blocks;
+ unsigned char ** basic_table;
+ unsigned int basic_table_count;
+ unsigned int basic_table_size;
+ unsigned char * lowest;
+ unsigned char * highest;
+
+#if ISC_MEM_TRACKLINES
+ debuglist_t * debuglist;
+ unsigned int debuglistcnt;
+#endif
+
+ unsigned int memalloc_failures;
+ 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 {
+ /* always unlocked */
+ unsigned int magic; /*%< magic number */
+ isc_mutex_t *lock; /*%< optional lock */
+ 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 */
+ /*%< optionally locked from here down */
+ element *items; /*%< low water item list */
+ size_t size; /*%< size of each item on this pool */
+ unsigned int maxalloc; /*%< max number of items allowed */
+ unsigned int allocated; /*%< # of items currently given out */
+ unsigned int freecount; /*%< # of items on reserved list */
+ unsigned int freemax; /*%< # of items allowed on free list */
+ unsigned int fillcount; /*%< # of items to fetch on each fill */
+ /*%< Stats only. */
+ unsigned int gets; /*%< # of requests to this pool */
+ /*%< Debugging only. */
+#if ISC_MEMPOOL_NAMES
+ char name[16]; /*%< printed name in stats reports */
+#endif
+};
+
+/*
+ * Private Inline-able.
+ */
+
+#if ! ISC_MEM_TRACKLINES
+#define ADD_TRACE(a, b, c, d, e)
+#define DELETE_TRACE(a, b, c, d, e)
+#else
+#define ADD_TRACE(a, b, c, d, e) \
+ do { \
+ if ((isc_mem_debugging & (ISC_MEM_DEBUGTRACE | \
+ ISC_MEM_DEBUGRECORD)) != 0 && \
+ b != NULL) \
+ add_trace_entry(a, b, c, d, e); \
+ } while (0)
+#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);
+
+/*!
+ * mctx must be locked.
+ */
+static inline void
+add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size
+ FLARG)
+{
+ debuglink_t *dl;
+ unsigned int i;
+
+ if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
+ fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_ADDTRACE,
+ "add %p size %u "
+ "file %s line %u mctx %p\n"),
+ ptr, size, file, line, mctx);
+
+ if (mctx->debuglist == NULL)
+ return;
+
+ if (size > mctx->max_size)
+ size = mctx->max_size;
+
+ dl = ISC_LIST_HEAD(mctx->debuglist[size]);
+ while (dl != NULL) {
+ if (dl->count == DEBUGLIST_COUNT)
+ goto next;
+ for (i = 0; i < DEBUGLIST_COUNT; i++) {
+ if (dl->ptr[i] == NULL) {
+ dl->ptr[i] = ptr;
+ dl->size[i] = size;
+ dl->file[i] = file;
+ dl->line[i] = line;
+ dl->count++;
+ return;
+ }
+ }
+ next:
+ dl = ISC_LIST_NEXT(dl, link);
+ }
+
+ dl = malloc(sizeof(debuglink_t));
+ INSIST(dl != NULL);
+
+ ISC_LINK_INIT(dl, link);
+ for (i = 1; i < DEBUGLIST_COUNT; i++) {
+ dl->ptr[i] = NULL;
+ dl->size[i] = 0;
+ dl->file[i] = NULL;
+ dl->line[i] = 0;
+ }
+
+ dl->ptr[0] = ptr;
+ dl->size[0] = size;
+ dl->file[0] = file;
+ dl->line[0] = line;
+ dl->count = 1;
+
+ ISC_LIST_PREPEND(mctx->debuglist[size], dl, link);
+ mctx->debuglistcnt++;
+}
+
+static inline void
+delete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size,
+ const char *file, unsigned int line)
+{
+ debuglink_t *dl;
+ unsigned int i;
+
+ if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
+ fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_DELTRACE,
+ "del %p size %u "
+ "file %s line %u mctx %p\n"),
+ ptr, size, file, line, mctx);
+
+ if (mctx->debuglist == NULL)
+ return;
+
+ if (size > mctx->max_size)
+ size = mctx->max_size;
+
+ dl = ISC_LIST_HEAD(mctx->debuglist[size]);
+ while (dl != NULL) {
+ for (i = 0; i < DEBUGLIST_COUNT; i++) {
+ if (dl->ptr[i] == ptr) {
+ dl->ptr[i] = NULL;
+ dl->size[i] = 0;
+ dl->file[i] = NULL;
+ dl->line[i] = 0;
+
+ INSIST(dl->count > 0);
+ dl->count--;
+ if (dl->count == 0) {
+ ISC_LIST_UNLINK(mctx->debuglist[size],
+ dl, link);
+ free(dl);
+ }
+ return;
+ }
+ }
+ dl = ISC_LIST_NEXT(dl, link);
+ }
+
+ /*
+ * If we get here, we didn't find the item on the list. We're
+ * screwed.
+ */
+ INSIST(dl != NULL);
+}
+#endif /* ISC_MEM_TRACKLINES */
+
+static inline size_t
+rmsize(size_t size) {
+ /*
+ * round down to ALIGNMENT_SIZE
+ */
+ return (size & (~(ALIGNMENT_SIZE - 1)));
+}
+
+static inline size_t
+quantize(size_t size) {
+ /*!
+ * Round up the result in order to get a size big
+ * enough to satisfy the request and be aligned on ALIGNMENT_SIZE
+ * byte boundaries.
+ */
+
+ if (size == 0U)
+ return (ALIGNMENT_SIZE);
+ return ((size + ALIGNMENT_SIZE - 1) & (~(ALIGNMENT_SIZE - 1)));
+}
+
+static inline isc_boolean_t
+more_basic_blocks(isc_mem_t *ctx) {
+ void *new;
+ unsigned char *curr, *next;
+ unsigned char *first, *last;
+ unsigned char **table;
+ unsigned int table_size;
+ size_t increment;
+ int i;
+
+ /* Require: we hold the context lock. */
+
+ /*
+ * Did we hit the quota for this context?
+ */
+ increment = NUM_BASIC_BLOCKS * ctx->mem_target;
+ if (ctx->quota != 0U && ctx->total + increment > ctx->quota)
+ return (ISC_FALSE);
+
+ INSIST(ctx->basic_table_count <= ctx->basic_table_size);
+ if (ctx->basic_table_count == ctx->basic_table_size) {
+ table_size = ctx->basic_table_size + TABLE_INCREMENT;
+ table = (ctx->memalloc)(ctx->arg,
+ table_size * sizeof(unsigned char *));
+ if (table == NULL) {
+ ctx->memalloc_failures++;
+ return (ISC_FALSE);
+ }
+ if (ctx->basic_table_size != 0) {
+ memcpy(table, ctx->basic_table,
+ ctx->basic_table_size *
+ sizeof(unsigned char *));
+ (ctx->memfree)(ctx->arg, ctx->basic_table);
+ }
+ ctx->basic_table = table;
+ ctx->basic_table_size = table_size;
+ }
+
+ new = (ctx->memalloc)(ctx->arg, NUM_BASIC_BLOCKS * ctx->mem_target);
+ if (new == NULL) {
+ ctx->memalloc_failures++;
+ return (ISC_FALSE);
+ }
+ ctx->total += increment;
+ ctx->basic_table[ctx->basic_table_count] = new;
+ ctx->basic_table_count++;
+
+ curr = new;
+ next = curr + ctx->mem_target;
+ for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
+ ((element *)curr)->next = (element *)next;
+ curr = next;
+ next += ctx->mem_target;
+ }
+ /*
+ * curr is now pointing at the last block in the
+ * array.
+ */
+ ((element *)curr)->next = NULL;
+ first = new;
+ last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
+ if (first < ctx->lowest || ctx->lowest == NULL)
+ ctx->lowest = first;
+ if (last > ctx->highest)
+ ctx->highest = last;
+ ctx->basic_blocks = new;
+
+ return (ISC_TRUE);
+}
+
+static inline isc_boolean_t
+more_frags(isc_mem_t *ctx, size_t new_size) {
+ int i, frags;
+ size_t total_size;
+ void *new;
+ unsigned char *curr, *next;
+
+ /*!
+ * Try to get more fragments by chopping up a basic block.
+ */
+
+ if (ctx->basic_blocks == NULL) {
+ if (!more_basic_blocks(ctx)) {
+ /*
+ * We can't get more memory from the OS, or we've
+ * hit the quota for this context.
+ */
+ /*
+ * XXXRTH "At quota" notification here.
+ */
+ return (ISC_FALSE);
+ }
+ }
+
+ total_size = ctx->mem_target;
+ new = ctx->basic_blocks;
+ ctx->basic_blocks = ctx->basic_blocks->next;
+ frags = total_size / new_size;
+ ctx->stats[new_size].blocks++;
+ ctx->stats[new_size].freefrags += frags;
+ /*
+ * Set up a linked-list of blocks of size
+ * "new_size".
+ */
+ curr = new;
+ next = curr + new_size;
+ total_size -= new_size;
+ for (i = 0; i < (frags - 1); i++) {
+ ((element *)curr)->next = (element *)next;
+ curr = next;
+ next += new_size;
+ total_size -= new_size;
+ }
+ /*
+ * Add the remaining fragment of the basic block to a free list.
+ */
+ total_size = rmsize(total_size);
+ if (total_size > 0U) {
+ ((element *)next)->next = ctx->freelists[total_size];
+ ctx->freelists[total_size] = (element *)next;
+ ctx->stats[total_size].freefrags++;
+ }
+ /*
+ * curr is now pointing at the last block in the
+ * array.
+ */
+ ((element *)curr)->next = NULL;
+ ctx->freelists[new_size] = new;
+
+ return (ISC_TRUE);
+}
+
+static inline void *
+mem_getunlocked(isc_mem_t *ctx, size_t size) {
+ size_t new_size = quantize(size);
+ void *ret;
+
+ if (size >= ctx->max_size || new_size >= ctx->max_size) {
+ /*
+ * memget() was called on something beyond our upper limit.
+ */
+ if (ctx->quota != 0U && ctx->total + size > ctx->quota) {
+ ret = NULL;
+ goto done;
+ }
+ ret = (ctx->memalloc)(ctx->arg, size);
+ if (ret == NULL) {
+ ctx->memalloc_failures++;
+ goto done;
+ }
+ ctx->total += size;
+ ctx->inuse += size;
+ ctx->stats[ctx->max_size].gets++;
+ ctx->stats[ctx->max_size].totalgets++;
+ /*
+ * If we don't set new_size to size, then the
+ * ISC_MEM_FILL code might write over bytes we
+ * don't own.
+ */
+ new_size = size;
+ goto done;
+ }
+
+ /*
+ * If there are no blocks in the free list for this size, get a chunk
+ * of memory and then break it up into "new_size"-sized blocks, adding
+ * them to the free list.
+ */
+ if (ctx->freelists[new_size] == NULL && !more_frags(ctx, new_size))
+ return (NULL);
+
+ /*
+ * The free list uses the "rounded-up" size "new_size".
+ */
+ ret = ctx->freelists[new_size];
+ ctx->freelists[new_size] = ctx->freelists[new_size]->next;
+
+ /*
+ * The stats[] uses the _actual_ "size" requested by the
+ * caller, with the caveat (in the code above) that "size" >= the
+ * max. size (max_size) ends up getting recorded as a call to
+ * max_size.
+ */
+ ctx->stats[size].gets++;
+ ctx->stats[size].totalgets++;
+ ctx->stats[new_size].freefrags--;
+ ctx->inuse += new_size;
+
+ done:
+
+#if ISC_MEM_FILL
+ if (ret != NULL)
+ memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */
+#endif
+
+ return (ret);
+}
+
+#if ISC_MEM_FILL && ISC_MEM_CHECKOVERRUN
+static inline void
+check_overrun(void *mem, size_t size, size_t new_size) {
+ unsigned char *cp;
+
+ cp = (unsigned char *)mem;
+ cp += size;
+ while (size < new_size) {
+ INSIST(*cp == 0xbe);
+ cp++;
+ size++;
+ }
+}
+#endif
+
+static inline void
+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) {
+ /*
+ * memput() called on something beyond our upper limit.
+ */
+#if ISC_MEM_FILL
+ memset(mem, 0xde, size); /* Mnemonic for "dead". */
+#endif
+ (ctx->memfree)(ctx->arg, mem);
+ INSIST(ctx->stats[ctx->max_size].gets != 0U);
+ ctx->stats[ctx->max_size].gets--;
+ INSIST(size <= ctx->total);
+ ctx->inuse -= size;
+ ctx->total -= size;
+ return;
+ }
+
+#if ISC_MEM_FILL
+#if ISC_MEM_CHECKOVERRUN
+ check_overrun(mem, size, new_size);
+#endif
+ memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
+#endif
+
+ /*
+ * The free list uses the "rounded-up" size "new_size".
+ */
+ ((element *)mem)->next = ctx->freelists[new_size];
+ ctx->freelists[new_size] = (element *)mem;
+
+ /*
+ * The stats[] uses the _actual_ "size" requested by the
+ * caller, with the caveat (in the code above) that "size" >= the
+ * max. size (max_size) ends up getting recorded as a call to
+ * max_size.
+ */
+ INSIST(ctx->stats[size].gets != 0U);
+ ctx->stats[size].gets--;
+ ctx->stats[new_size].freefrags++;
+ ctx->inuse -= new_size;
+}
+
+/*!
+ * Perform a malloc, doing memory filling and overrun detection as necessary.
+ */
+static inline void *
+mem_get(isc_mem_t *ctx, size_t size) {
+ char *ret;
+
+#if ISC_MEM_CHECKOVERRUN
+ size += 1;
+#endif
+
+ ret = (ctx->memalloc)(ctx->arg, size);
+ if (ret == NULL)
+ ctx->memalloc_failures++;
+
+#if ISC_MEM_FILL
+ if (ret != NULL)
+ memset(ret, 0xbe, size); /* Mnemonic for "beef". */
+#else
+# if ISC_MEM_CHECKOVERRUN
+ if (ret != NULL)
+ ret[size-1] = 0xbe;
+# endif
+#endif
+
+ return (ret);
+}
+
+/*!
+ * 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) {
+#if ISC_MEM_CHECKOVERRUN
+ INSIST(((unsigned char *)mem)[size] == 0xbe);
+#endif
+#if ISC_MEM_FILL
+ memset(mem, 0xde, size); /* Mnemonic for "dead". */
+#else
+ UNUSED(size);
+#endif
+ (ctx->memfree)(ctx->arg, mem);
+}
+
+/*!
+ * Update internal counters after a memory get.
+ */
+static inline void
+mem_getstats(isc_mem_t *ctx, size_t size) {
+ ctx->total += size;
+ ctx->inuse += size;
+
+ if (size > ctx->max_size) {
+ ctx->stats[ctx->max_size].gets++;
+ ctx->stats[ctx->max_size].totalgets++;
+ } else {
+ ctx->stats[size].gets++;
+ ctx->stats[size].totalgets++;
+ }
+}
+
+/*!
+ * Update internal counters after a memory put.
+ */
+static inline void
+mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) {
+ UNUSED(ptr);
+
+ INSIST(ctx->inuse >= size);
+ ctx->inuse -= size;
+
+ if (size > ctx->max_size) {
+ INSIST(ctx->stats[ctx->max_size].gets > 0U);
+ ctx->stats[ctx->max_size].gets--;
+ } else {
+ INSIST(ctx->stats[size].gets > 0U);
+ ctx->stats[size].gets--;
+ }
+}
+
+/*
+ * Private.
+ */
+
+static void *
+default_memalloc(void *arg, size_t size) {
+ UNUSED(arg);
+ if (size == 0U)
+ size = 1;
+ return (malloc(size));
+}
+
+static void
+default_memfree(void *arg, void *ptr) {
+ UNUSED(arg);
+ free(ptr);
+}
+
+static void
+initialize_action(void) {
+ RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
+ ISC_LIST_INIT(contexts);
+ totallost = 0;
+}
+
+/*
+ * 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)
+{
+ 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_mem_t *ctx;
+ isc_result_t result;
+
+ REQUIRE(ctxp != NULL && *ctxp == NULL);
+ REQUIRE(memalloc != NULL);
+ REQUIRE(memfree != NULL);
+
+ INSIST((ALIGNMENT_SIZE & (ALIGNMENT_SIZE - 1)) == 0);
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+
+ ctx = (memalloc)(arg, sizeof(*ctx));
+ if (ctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if ((flags & ISC_MEMFLAG_NOLOCK) == 0) {
+ result = isc_mutex_init(&ctx->lock);
+ if (result != ISC_R_SUCCESS) {
+ (memfree)(arg, ctx);
+ return (result);
+ }
+ }
+
+ if (init_max_size == 0U)
+ ctx->max_size = DEF_MAX_SIZE;
+ else
+ ctx->max_size = init_max_size;
+ ctx->flags = flags;
+ ctx->references = 1;
+ memset(ctx->name, 0, sizeof(ctx->name));
+ ctx->tag = NULL;
+ ctx->quota = 0;
+ ctx->total = 0;
+ ctx->inuse = 0;
+ ctx->maxinuse = 0;
+ ctx->hi_water = 0;
+ ctx->lo_water = 0;
+ ctx->hi_called = ISC_FALSE;
+ ctx->water = NULL;
+ ctx->water_arg = NULL;
+ ctx->magic = MEM_MAGIC;
+ isc_ondestroy_init(&ctx->ondestroy);
+ ctx->memalloc = memalloc;
+ ctx->memfree = memfree;
+ ctx->arg = arg;
+ ctx->stats = NULL;
+ ctx->checkfree = ISC_TRUE;
+#if ISC_MEM_TRACKLINES
+ ctx->debuglist = NULL;
+ ctx->debuglistcnt = 0;
+#endif
+ ISC_LIST_INIT(ctx->pools);
+ ctx->poolcnt = 0;
+ ctx->freelists = NULL;
+ ctx->basic_blocks = NULL;
+ ctx->basic_table = NULL;
+ ctx->basic_table_count = 0;
+ ctx->basic_table_size = 0;
+ ctx->lowest = NULL;
+ ctx->highest = NULL;
+
+ ctx->stats = (memalloc)(arg,
+ (ctx->max_size+1) * sizeof(struct stats));
+ if (ctx->stats == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto error;
+ }
+ memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof(struct stats));
+
+ if ((flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ if (target_size == 0U)
+ ctx->mem_target = DEF_MEM_TARGET;
+ else
+ ctx->mem_target = target_size;
+ ctx->freelists = (memalloc)(arg, ctx->max_size *
+ sizeof(element *));
+ if (ctx->freelists == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto error;
+ }
+ memset(ctx->freelists, 0,
+ ctx->max_size * sizeof(element *));
+ }
+
+#if ISC_MEM_TRACKLINES
+ if ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0) {
+ unsigned int i;
+
+ ctx->debuglist = (memalloc)(arg,
+ (ctx->max_size+1) * sizeof(debuglist_t));
+ if (ctx->debuglist == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto error;
+ }
+ for (i = 0; i <= ctx->max_size; i++)
+ ISC_LIST_INIT(ctx->debuglist[i]);
+ }
+#endif
+
+ ctx->memalloc_failures = 0;
+
+ LOCK(&lock);
+ ISC_LIST_INITANDAPPEND(contexts, ctx, link);
+ UNLOCK(&lock);
+
+ *ctxp = ctx;
+ return (ISC_R_SUCCESS);
+
+ error:
+ if (ctx != NULL) {
+ if (ctx->stats != NULL)
+ (memfree)(arg, ctx->stats);
+ if (ctx->freelists != NULL)
+ (memfree)(arg, ctx->freelists);
+#if ISC_MEM_TRACKLINES
+ if (ctx->debuglist != NULL)
+ (ctx->memfree)(ctx->arg, ctx->debuglist);
+#endif /* ISC_MEM_TRACKLINES */
+ if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
+ DESTROYLOCK(&ctx->lock);
+ (memfree)(arg, ctx);
+ }
+
+ 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_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));
+}
+
+static void
+destroy(isc_mem_t *ctx) {
+ unsigned int i;
+ isc_ondestroy_t ondest;
+
+ ctx->magic = 0;
+
+ LOCK(&lock);
+ ISC_LIST_UNLINK(contexts, ctx, link);
+ totallost += ctx->inuse;
+ UNLOCK(&lock);
+
+ INSIST(ISC_LIST_EMPTY(ctx->pools));
+
+#if ISC_MEM_TRACKLINES
+ if (ctx->debuglist != NULL) {
+ if (ctx->checkfree) {
+ for (i = 0; i <= ctx->max_size; i++) {
+ if (!ISC_LIST_EMPTY(ctx->debuglist[i]))
+ print_active(ctx, stderr);
+ INSIST(ISC_LIST_EMPTY(ctx->debuglist[i]));
+ }
+ } else {
+ debuglink_t *dl;
+
+ for (i = 0; i <= ctx->max_size; i++)
+ for (dl = ISC_LIST_HEAD(ctx->debuglist[i]);
+ dl != NULL;
+ dl = ISC_LIST_HEAD(ctx->debuglist[i])) {
+ ISC_LIST_UNLINK(ctx->debuglist[i],
+ dl, link);
+ free(dl);
+ }
+ }
+ (ctx->memfree)(ctx->arg, ctx->debuglist);
+ }
+#endif
+ INSIST(ctx->references == 0);
+
+ if (ctx->checkfree) {
+ for (i = 0; i <= ctx->max_size; i++) {
+#if ISC_MEM_TRACKLINES
+ if (ctx->stats[i].gets != 0U)
+ print_active(ctx, stderr);
+#endif
+ INSIST(ctx->stats[i].gets == 0U);
+ }
+ }
+
+ (ctx->memfree)(ctx->arg, ctx->stats);
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ for (i = 0; i < ctx->basic_table_count; i++)
+ (ctx->memfree)(ctx->arg, ctx->basic_table[i]);
+ (ctx->memfree)(ctx->arg, ctx->freelists);
+ if (ctx->basic_table != NULL)
+ (ctx->memfree)(ctx->arg, ctx->basic_table);
+ }
+
+ ondest = ctx->ondestroy;
+
+ if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
+ DESTROYLOCK(&ctx->lock);
+ (ctx->memfree)(ctx->arg, ctx);
+
+ isc_ondestroy_notify(&ondest, ctx);
+}
+
+void
+isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
+ REQUIRE(VALID_CONTEXT(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ MCTXLOCK(source, &source->lock);
+ source->references++;
+ MCTXUNLOCK(source, &source->lock);
+
+ *targetp = source;
+}
+
+void
+isc_mem_detach(isc_mem_t **ctxp) {
+ isc_mem_t *ctx;
+ isc_boolean_t want_destroy = ISC_FALSE;
+
+ REQUIRE(ctxp != NULL);
+ ctx = *ctxp;
+ REQUIRE(VALID_CONTEXT(ctx));
+
+ MCTXLOCK(ctx, &ctx->lock);
+ INSIST(ctx->references > 0);
+ ctx->references--;
+ if (ctx->references == 0)
+ want_destroy = ISC_TRUE;
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ if (want_destroy)
+ destroy(ctx);
+
+ *ctxp = NULL;
+}
+
+/*
+ * isc_mem_putanddetach() is the equivalent of:
+ *
+ * mctx = NULL;
+ * isc_mem_attach(ptr->mctx, &mctx);
+ * isc_mem_detach(&ptr->mctx);
+ * isc_mem_put(mctx, ptr, sizeof(*ptr);
+ * isc_mem_detach(&mctx);
+ */
+
+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;
+ REQUIRE(VALID_CONTEXT(ctx));
+ REQUIRE(ptr != NULL);
+
+ /*
+ * Must be before mem_putunlocked() as ctxp is usually within
+ * [ptr..ptr+size).
+ */
+ *ctxp = NULL;
+
+ if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {
+ if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
+ si = &(((size_info *)ptr)[-1]);
+ oldsize = si->u.size - ALIGNMENT_SIZE;
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
+ oldsize -= ALIGNMENT_SIZE;
+ INSIST(oldsize == size);
+ }
+ isc__mem_free(ctx, ptr FLARG_PASS);
+
+ MCTXLOCK(ctx, &ctx->lock);
+ ctx->references--;
+ if (ctx->references == 0)
+ want_destroy = ISC_TRUE;
+ MCTXUNLOCK(ctx, &ctx->lock);
+ if (want_destroy)
+ destroy(ctx);
+
+ return;
+ }
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putunlocked(ctx, ptr, size);
+ } else {
+ mem_put(ctx, ptr, size);
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putstats(ctx, ptr, size);
+ }
+
+ DELETE_TRACE(ctx, ptr, size, file, line);
+ INSIST(ctx->references > 0);
+ ctx->references--;
+ if (ctx->references == 0)
+ want_destroy = ISC_TRUE;
+
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ if (want_destroy)
+ destroy(ctx);
+}
+
+void
+isc_mem_destroy(isc_mem_t **ctxp) {
+ isc_mem_t *ctx;
+
+ /*
+ * This routine provides legacy support for callers who use mctxs
+ * without attaching/detaching.
+ */
+
+ REQUIRE(ctxp != NULL);
+ ctx = *ctxp;
+ REQUIRE(VALID_CONTEXT(ctx));
+
+ MCTXLOCK(ctx, &ctx->lock);
+#if ISC_MEM_TRACKLINES
+ if (ctx->references != 1)
+ print_active(ctx, stderr);
+#endif
+ REQUIRE(ctx->references == 1);
+ ctx->references--;
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ destroy(ctx);
+
+ *ctxp = NULL;
+}
+
+isc_result_t
+isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
+ isc_result_t res;
+
+ MCTXLOCK(ctx, &ctx->lock);
+ res = isc_ondestroy_register(&ctx->ondestroy, task, event);
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ return (res);
+}
+
+
+void *
+isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
+ 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));
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(ctx, &ctx->lock);
+ ptr = mem_getunlocked(ctx, size);
+ } else {
+ ptr = mem_get(ctx, size);
+ MCTXLOCK(ctx, &ctx->lock);
+ if (ptr != NULL)
+ mem_getstats(ctx, size);
+ }
+
+ ADD_TRACE(ctx, ptr, size, file, line);
+ if (ctx->hi_water != 0U && !ctx->hi_called &&
+ ctx->inuse > ctx->hi_water) {
+ call_water = ISC_TRUE;
+ }
+ if (ctx->inuse > ctx->maxinuse) {
+ ctx->maxinuse = ctx->inuse;
+ if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
+ (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)
+ fprintf(stderr, "maxinuse = %lu\n",
+ (unsigned long)ctx->inuse);
+ }
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ if (call_water)
+ (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
+
+ return (ptr);
+}
+
+void
+isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
+{
+ isc_boolean_t call_water = ISC_FALSE;
+ size_info *si;
+ size_t oldsize;
+
+ REQUIRE(VALID_CONTEXT(ctx));
+ REQUIRE(ptr != NULL);
+
+ if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {
+ if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
+ si = &(((size_info *)ptr)[-1]);
+ oldsize = si->u.size - ALIGNMENT_SIZE;
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
+ oldsize -= ALIGNMENT_SIZE;
+ INSIST(oldsize == size);
+ }
+ isc__mem_free(ctx, ptr FLARG_PASS);
+ return;
+ }
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putunlocked(ctx, ptr, size);
+ } else {
+ mem_put(ctx, ptr, size);
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putstats(ctx, ptr, size);
+ }
+
+ DELETE_TRACE(ctx, ptr, size, file, line);
+
+ /*
+ * The check against ctx->lo_water == 0 is for the condition
+ * when the context was pushed over hi_water but then had
+ * isc_mem_setwater() called with 0 for hi_water and lo_water.
+ */
+ if (ctx->hi_called &&
+ (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
+ if (ctx->water != NULL)
+ call_water = ISC_TRUE;
+ }
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ if (call_water)
+ (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
+}
+
+void
+isc_mem_waterack(isc_mem_t *ctx, int flag) {
+ REQUIRE(VALID_CONTEXT(ctx));
+
+ MCTXLOCK(ctx, &ctx->lock);
+ if (flag == ISC_MEM_LOWATER)
+ ctx->hi_called = ISC_FALSE;
+ else if (flag == ISC_MEM_HIWATER)
+ ctx->hi_called = ISC_TRUE;
+ MCTXUNLOCK(ctx, &ctx->lock);
+}
+
+#if ISC_MEM_TRACKLINES
+static void
+print_active(isc_mem_t *mctx, FILE *out) {
+ if (mctx->debuglist != NULL) {
+ debuglink_t *dl;
+ unsigned int i, j;
+ const char *format;
+ isc_boolean_t found;
+
+ fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_DUMPALLOC,
+ "Dump of all outstanding "
+ "memory allocations:\n"));
+ found = ISC_FALSE;
+ format = isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_PTRFILELINE,
+ "\tptr %p size %u file %s line %u\n");
+ for (i = 0; i <= mctx->max_size; i++) {
+ dl = ISC_LIST_HEAD(mctx->debuglist[i]);
+
+ if (dl != NULL)
+ found = ISC_TRUE;
+
+ while (dl != NULL) {
+ for (j = 0; j < DEBUGLIST_COUNT; j++)
+ if (dl->ptr[j] != NULL)
+ fprintf(out, format,
+ dl->ptr[j],
+ dl->size[j],
+ dl->file[j],
+ dl->line[j]);
+ dl = ISC_LIST_NEXT(dl, link);
+ }
+ }
+ if (!found)
+ fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_NONE, "\tNone.\n"));
+ }
+}
+#endif
+
+/*
+ * Print the stats[] on the stream "out" with suitable formatting.
+ */
+void
+isc_mem_stats(isc_mem_t *ctx, FILE *out) {
+ size_t i;
+ const struct stats *s;
+ const isc_mempool_t *pool;
+
+ REQUIRE(VALID_CONTEXT(ctx));
+ MCTXLOCK(ctx, &ctx->lock);
+
+ for (i = 0; i <= ctx->max_size; i++) {
+ s = &ctx->stats[i];
+
+ if (s->totalgets == 0U && s->gets == 0U)
+ continue;
+ fprintf(out, "%s%5lu: %11lu gets, %11lu rem",
+ (i == ctx->max_size) ? ">=" : " ",
+ (unsigned long) i, s->totalgets, s->gets);
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0 &&
+ (s->blocks != 0U || s->freefrags != 0U))
+ fprintf(out, " (%lu bl, %lu ff)",
+ s->blocks, s->freefrags);
+ fputc('\n', out);
+ }
+
+ /*
+ * Note that since a pool can be locked now, these stats might be
+ * somewhat off if the pool is in active use at the time the stats
+ * are dumped. The link fields are protected by the isc_mem_t's
+ * lock, however, so walking this list and extracting integers from
+ * stats fields is always safe.
+ */
+ pool = ISC_LIST_HEAD(ctx->pools);
+ if (pool != NULL) {
+ fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_POOLSTATS,
+ "[Pool statistics]\n"));
+ fprintf(out, "%15s %10s %10s %10s %10s %10s %10s %10s %1s\n",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_POOLNAME, "name"),
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_POOLSIZE, "size"),
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_POOLMAXALLOC, "maxalloc"),
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_POOLALLOCATED, "allocated"),
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_POOLFREECOUNT, "freecount"),
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_POOLFREEMAX, "freemax"),
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_POOLFILLCOUNT, "fillcount"),
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
+ ISC_MSG_POOLGETS, "gets"),
+ "L");
+ }
+ while (pool != NULL) {
+ fprintf(out, "%15s %10lu %10u %10u %10u %10u %10u %10u %s\n",
+ pool->name, (unsigned long) pool->size, pool->maxalloc,
+ pool->allocated, pool->freecount, pool->freemax,
+ pool->fillcount, pool->gets,
+ (pool->lock == NULL ? "N" : "Y"));
+ pool = ISC_LIST_NEXT(pool, link);
+ }
+
+#if ISC_MEM_TRACKLINES
+ print_active(ctx, out);
+#endif
+
+ MCTXUNLOCK(ctx, &ctx->lock);
+}
+
+/*
+ * Replacements for malloc() and free() -- they implicitly remember the
+ * size of the object allocated (with some additional overhead).
+ */
+
+static void *
+isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {
+ size_info *si;
+
+ size += ALIGNMENT_SIZE;
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
+ size += ALIGNMENT_SIZE;
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0)
+ si = mem_getunlocked(ctx, size);
+ else
+ si = mem_get(ctx, size);
+
+ if (si == NULL)
+ return (NULL);
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
+ si->u.ctx = ctx;
+ si++;
+ }
+ si->u.size = size;
+ return (&si[1]);
+}
+
+void *
+isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
+ size_info *si;
+ isc_boolean_t call_water = ISC_FALSE;
+
+ REQUIRE(VALID_CONTEXT(ctx));
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(ctx, &ctx->lock);
+ si = isc__mem_allocateunlocked(ctx, size);
+ } else {
+ si = isc__mem_allocateunlocked(ctx, size);
+ MCTXLOCK(ctx, &ctx->lock);
+ if (si != NULL)
+ mem_getstats(ctx, si[-1].u.size);
+ }
+
+#if ISC_MEM_TRACKLINES
+ ADD_TRACE(ctx, si, si[-1].u.size, file, line);
+#endif
+ if (ctx->hi_water != 0U && !ctx->hi_called &&
+ ctx->inuse > ctx->hi_water) {
+ ctx->hi_called = ISC_TRUE;
+ call_water = ISC_TRUE;
+ }
+ if (ctx->inuse > ctx->maxinuse) {
+ ctx->maxinuse = ctx->inuse;
+ if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
+ (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)
+ fprintf(stderr, "maxinuse = %lu\n",
+ (unsigned long)ctx->inuse);
+ }
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ if (call_water)
+ (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
+
+ return (si);
+}
+
+void
+isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
+ size_info *si;
+ size_t size;
+ isc_boolean_t call_water= ISC_FALSE;
+
+ REQUIRE(VALID_CONTEXT(ctx));
+ REQUIRE(ptr != NULL);
+
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
+ si = &(((size_info *)ptr)[-2]);
+ REQUIRE(si->u.ctx == ctx);
+ size = si[1].u.size;
+ } else {
+ si = &(((size_info *)ptr)[-1]);
+ size = si->u.size;
+ }
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putunlocked(ctx, si, size);
+ } else {
+ mem_put(ctx, si, size);
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putstats(ctx, si, size);
+ }
+
+ DELETE_TRACE(ctx, ptr, size, file, line);
+
+ /*
+ * The check against ctx->lo_water == 0 is for the condition
+ * when the context was pushed over hi_water but then had
+ * isc_mem_setwater() called with 0 for hi_water and lo_water.
+ */
+ if (ctx->hi_called &&
+ (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
+ ctx->hi_called = ISC_FALSE;
+
+ if (ctx->water != NULL)
+ call_water = ISC_TRUE;
+ }
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ if (call_water)
+ (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
+}
+
+
+/*
+ * Other useful things.
+ */
+
+char *
+isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
+ size_t len;
+ char *ns;
+
+ REQUIRE(VALID_CONTEXT(mctx));
+ REQUIRE(s != NULL);
+
+ len = strlen(s);
+
+ ns = isc__mem_allocate(mctx, len + 1 FLARG_PASS);
+
+ if (ns != NULL)
+ strncpy(ns, s, len + 1);
+
+ return (ns);
+}
+
+void
+isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
+ REQUIRE(VALID_CONTEXT(ctx));
+ MCTXLOCK(ctx, &ctx->lock);
+
+ ctx->checkfree = flag;
+
+ MCTXUNLOCK(ctx, &ctx->lock);
+}
+
+/*
+ * Quotas
+ */
+
+void
+isc_mem_setquota(isc_mem_t *ctx, size_t quota) {
+ REQUIRE(VALID_CONTEXT(ctx));
+ MCTXLOCK(ctx, &ctx->lock);
+
+ ctx->quota = quota;
+
+ MCTXUNLOCK(ctx, &ctx->lock);
+}
+
+size_t
+isc_mem_getquota(isc_mem_t *ctx) {
+ size_t quota;
+
+ REQUIRE(VALID_CONTEXT(ctx));
+ MCTXLOCK(ctx, &ctx->lock);
+
+ quota = ctx->quota;
+
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ return (quota);
+}
+
+size_t
+isc_mem_inuse(isc_mem_t *ctx) {
+ size_t inuse;
+
+ REQUIRE(VALID_CONTEXT(ctx));
+ MCTXLOCK(ctx, &ctx->lock);
+
+ inuse = ctx->inuse;
+
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ return (inuse);
+}
+
+void
+isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
+ size_t hiwater, size_t lowater)
+{
+ isc_boolean_t callwater = ISC_FALSE;
+ isc_mem_water_t oldwater;
+ void *oldwater_arg;
+
+ REQUIRE(VALID_CONTEXT(ctx));
+ REQUIRE(hiwater >= lowater);
+
+ MCTXLOCK(ctx, &ctx->lock);
+ oldwater = ctx->water;
+ oldwater_arg = ctx->water_arg;
+ if (water == NULL) {
+ callwater = ctx->hi_called;
+ ctx->water = NULL;
+ ctx->water_arg = NULL;
+ ctx->hi_water = 0;
+ ctx->lo_water = 0;
+ ctx->hi_called = ISC_FALSE;
+ } else {
+ if (ctx->hi_called &&
+ (ctx->water != water || ctx->water_arg != water_arg ||
+ ctx->inuse < lowater || lowater == 0U))
+ callwater = ISC_TRUE;
+ ctx->water = water;
+ ctx->water_arg = water_arg;
+ ctx->hi_water = hiwater;
+ ctx->lo_water = lowater;
+ ctx->hi_called = ISC_FALSE;
+ }
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ if (callwater && oldwater != NULL)
+ (oldwater)(oldwater_arg, ISC_MEM_LOWATER);
+}
+
+void
+isc_mem_setname(isc_mem_t *ctx, const char *name, void *tag) {
+ REQUIRE(VALID_CONTEXT(ctx));
+
+ LOCK(&ctx->lock);
+ memset(ctx->name, 0, sizeof(ctx->name));
+ strncpy(ctx->name, name, sizeof(ctx->name) - 1);
+ ctx->tag = tag;
+ UNLOCK(&ctx->lock);
+}
+
+const char *
+isc_mem_getname(isc_mem_t *ctx) {
+ REQUIRE(VALID_CONTEXT(ctx));
+
+ return (ctx->name);
+}
+
+void *
+isc_mem_gettag(isc_mem_t *ctx) {
+ REQUIRE(VALID_CONTEXT(ctx));
+
+ return (ctx->tag);
+}
+
+/*
+ * Memory pool stuff
+ */
+
+isc_result_t
+isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
+ isc_mempool_t *mpctx;
+
+ REQUIRE(VALID_CONTEXT(mctx));
+ REQUIRE(size > 0U);
+ REQUIRE(mpctxp != NULL && *mpctxp == NULL);
+
+ /*
+ * 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));
+ if (mpctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ mpctx->magic = MEMPOOL_MAGIC;
+ mpctx->lock = NULL;
+ mpctx->mctx = mctx;
+ mpctx->size = size;
+ mpctx->maxalloc = UINT_MAX;
+ mpctx->allocated = 0;
+ mpctx->freecount = 0;
+ mpctx->freemax = 1;
+ mpctx->fillcount = 1;
+ mpctx->gets = 0;
+#if ISC_MEMPOOL_NAMES
+ mpctx->name[0] = 0;
+#endif
+ mpctx->items = NULL;
+
+ *mpctxp = mpctx;
+
+ MCTXLOCK(mctx, &mctx->lock);
+ ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
+ mctx->poolcnt++;
+ MCTXUNLOCK(mctx, &mctx->lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
+ REQUIRE(name != NULL);
+
+#if ISC_MEMPOOL_NAMES
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ strncpy(mpctx->name, name, sizeof(mpctx->name) - 1);
+ mpctx->name[sizeof(mpctx->name) - 1] = '\0';
+
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+#else
+ UNUSED(mpctx);
+ UNUSED(name);
+#endif
+}
+
+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;
+ REQUIRE(VALID_MEMPOOL(mpctx));
+#if ISC_MEMPOOL_NAMES
+ if (mpctx->allocated > 0)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_mempool_destroy(): mempool %s "
+ "leaked memory",
+ mpctx->name);
+#endif
+ REQUIRE(mpctx->allocated == 0);
+
+ mctx = mpctx->mctx;
+
+ lock = mpctx->lock;
+
+ if (lock != NULL)
+ LOCK(lock);
+
+ /*
+ * Return any items on the free list
+ */
+ MCTXLOCK(mctx, &mctx->lock);
+ while (mpctx->items != NULL) {
+ INSIST(mpctx->freecount > 0);
+ mpctx->freecount--;
+ item = mpctx->items;
+ mpctx->items = item->next;
+
+ if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ mem_putunlocked(mctx, item, mpctx->size);
+ } else {
+ mem_put(mctx, item, mpctx->size);
+ mem_putstats(mctx, item, mpctx->size);
+ }
+ }
+ MCTXUNLOCK(mctx, &mctx->lock);
+
+ /*
+ * Remove our linked list entry from the memory context.
+ */
+ MCTXLOCK(mctx, &mctx->lock);
+ ISC_LIST_UNLINK(mctx->pools, mpctx, link);
+ mctx->poolcnt--;
+ MCTXUNLOCK(mctx, &mctx->lock);
+
+ mpctx->magic = 0;
+
+ isc_mem_put(mpctx->mctx, mpctx, sizeof(isc_mempool_t));
+
+ if (lock != NULL)
+ UNLOCK(lock);
+
+ *mpctxp = NULL;
+}
+
+void
+isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
+ REQUIRE(VALID_MEMPOOL(mpctx));
+ REQUIRE(mpctx->lock == NULL);
+ REQUIRE(lock != NULL);
+
+ mpctx->lock = lock;
+}
+
+void *
+isc__mempool_get(isc_mempool_t *mpctx FLARG) {
+ element *item;
+ isc_mem_t *mctx;
+ unsigned int i;
+
+ REQUIRE(VALID_MEMPOOL(mpctx));
+
+ mctx = mpctx->mctx;
+
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ /*
+ * Don't let the caller go over quota
+ */
+ if (mpctx->allocated >= mpctx->maxalloc) {
+ item = NULL;
+ goto out;
+ }
+
+ /*
+ * if we have a free list item, return the first here
+ */
+ item = mpctx->items;
+ if (item != NULL) {
+ mpctx->items = item->next;
+ INSIST(mpctx->freecount > 0);
+ mpctx->freecount--;
+ mpctx->gets++;
+ mpctx->allocated++;
+ goto out;
+ }
+
+ /*
+ * We need to dip into the well. Lock the memory context here and
+ * fill up our free list.
+ */
+ MCTXLOCK(mctx, &mctx->lock);
+ for (i = 0; i < mpctx->fillcount; i++) {
+ if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ item = mem_getunlocked(mctx, mpctx->size);
+ } else {
+ item = mem_get(mctx, mpctx->size);
+ if (item != NULL)
+ mem_getstats(mctx, mpctx->size);
+ }
+ if (item == NULL)
+ break;
+ item->next = mpctx->items;
+ mpctx->items = item;
+ mpctx->freecount++;
+ }
+ MCTXUNLOCK(mctx, &mctx->lock);
+
+ /*
+ * If we didn't get any items, return NULL.
+ */
+ item = mpctx->items;
+ if (item == NULL)
+ goto out;
+
+ mpctx->items = item->next;
+ mpctx->freecount--;
+ mpctx->gets++;
+ mpctx->allocated++;
+
+ out:
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+
+#if ISC_MEM_TRACKLINES
+ if (item != NULL) {
+ MCTXLOCK(mctx, &mctx->lock);
+ ADD_TRACE(mctx, item, mpctx->size, file, line);
+ MCTXUNLOCK(mctx, &mctx->lock);
+ }
+#endif /* ISC_MEM_TRACKLINES */
+
+ return (item);
+}
+
+void
+isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
+ isc_mem_t *mctx;
+ element *item;
+
+ REQUIRE(VALID_MEMPOOL(mpctx));
+ REQUIRE(mem != NULL);
+
+ mctx = mpctx->mctx;
+
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ INSIST(mpctx->allocated > 0);
+ mpctx->allocated--;
+
+#if ISC_MEM_TRACKLINES
+ MCTXLOCK(mctx, &mctx->lock);
+ DELETE_TRACE(mctx, mem, mpctx->size, file, line);
+ MCTXUNLOCK(mctx, &mctx->lock);
+#endif /* ISC_MEM_TRACKLINES */
+
+ /*
+ * If our free list is full, return this to the mctx directly.
+ */
+ if (mpctx->freecount >= mpctx->freemax) {
+ if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(mctx, &mctx->lock);
+ mem_putunlocked(mctx, mem, mpctx->size);
+ MCTXUNLOCK(mctx, &mctx->lock);
+ } else {
+ mem_put(mctx, mem, mpctx->size);
+ MCTXLOCK(mctx, &mctx->lock);
+ mem_putstats(mctx, mem, mpctx->size);
+ MCTXUNLOCK(mctx, &mctx->lock);
+ }
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+ return;
+ }
+
+ /*
+ * Otherwise, attach it to our free list and bump the counter.
+ */
+ mpctx->freecount++;
+ item = (element *)mem;
+ item->next = mpctx->items;
+ mpctx->items = item;
+
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+}
+
+/*
+ * Quotas
+ */
+
+void
+isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
+ REQUIRE(VALID_MEMPOOL(mpctx));
+
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ mpctx->freemax = limit;
+
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+}
+
+unsigned int
+isc_mempool_getfreemax(isc_mempool_t *mpctx) {
+ unsigned int freemax;
+
+ REQUIRE(VALID_MEMPOOL(mpctx));
+
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ freemax = mpctx->freemax;
+
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+
+ return (freemax);
+}
+
+unsigned int
+isc_mempool_getfreecount(isc_mempool_t *mpctx) {
+ unsigned int freecount;
+
+ REQUIRE(VALID_MEMPOOL(mpctx));
+
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ freecount = mpctx->freecount;
+
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+
+ return (freecount);
+}
+
+void
+isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
+ REQUIRE(limit > 0);
+
+ REQUIRE(VALID_MEMPOOL(mpctx));
+
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ mpctx->maxalloc = limit;
+
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+}
+
+unsigned int
+isc_mempool_getmaxalloc(isc_mempool_t *mpctx) {
+ unsigned int maxalloc;
+
+ REQUIRE(VALID_MEMPOOL(mpctx));
+
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ maxalloc = mpctx->maxalloc;
+
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+
+ return (maxalloc);
+}
+
+unsigned int
+isc_mempool_getallocated(isc_mempool_t *mpctx) {
+ unsigned int allocated;
+
+ REQUIRE(VALID_MEMPOOL(mpctx));
+
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ allocated = mpctx->allocated;
+
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+
+ return (allocated);
+}
+
+void
+isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
+ REQUIRE(limit > 0);
+ REQUIRE(VALID_MEMPOOL(mpctx));
+
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ mpctx->fillcount = limit;
+
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+}
+
+unsigned int
+isc_mempool_getfillcount(isc_mempool_t *mpctx) {
+ unsigned int fillcount;
+
+ REQUIRE(VALID_MEMPOOL(mpctx));
+
+ if (mpctx->lock != NULL)
+ LOCK(mpctx->lock);
+
+ fillcount = mpctx->fillcount;
+
+ if (mpctx->lock != NULL)
+ UNLOCK(mpctx->lock);
+
+ return (fillcount);
+}
+
+void
+isc_mem_printactive(isc_mem_t *ctx, FILE *file) {
+
+ REQUIRE(VALID_CONTEXT(ctx));
+ REQUIRE(file != NULL);
+
+#if !ISC_MEM_TRACKLINES
+ UNUSED(ctx);
+ UNUSED(file);
+#else
+ print_active(ctx, file);
+#endif
+}
+
+void
+isc_mem_printallactive(FILE *file) {
+#if !ISC_MEM_TRACKLINES
+ UNUSED(file);
+#else
+ isc_mem_t *ctx;
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+
+ LOCK(&lock);
+ for (ctx = ISC_LIST_HEAD(contexts);
+ ctx != NULL;
+ ctx = ISC_LIST_NEXT(ctx, link)) {
+ fprintf(file, "context: %p\n", ctx);
+ print_active(ctx, file);
+ }
+ UNLOCK(&lock);
+#endif
+}
+
+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;
+
+ for (ctx = ISC_LIST_HEAD(contexts);
+ ctx != NULL;
+ ctx = ISC_LIST_NEXT(ctx, link)) {
+ fprintf(file, "context: %p\n", ctx);
+ print_active(ctx, file);
+ }
+ fflush(file);
+#endif
+ INSIST(0);
+ }
+ UNLOCK(&lock);
+}
+
+unsigned int
+isc_mem_references(isc_mem_t *ctx) {
+ unsigned int references;
+ REQUIRE(VALID_CONTEXT(ctx));
+
+ MCTXLOCK(ctx, &ctx->lock);
+ references = ctx->references;
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ return (references);
+}
+
+#ifdef HAVE_LIBXML2
+
+typedef struct summarystat {
+ isc_uint64_t total;
+ isc_uint64_t inuse;
+ isc_uint64_t blocksize;
+ isc_uint64_t contextsize;
+} summarystat_t;
+
+static void
+renderctx(isc_mem_t *ctx, summarystat_t *summary, xmlTextWriterPtr writer) {
+ REQUIRE(VALID_CONTEXT(ctx));
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "context");
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
+ xmlTextWriterWriteFormatString(writer, "%p", ctx);
+ xmlTextWriterEndElement(writer); /* id */
+
+ if (ctx->name[0] != 0) {
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+ xmlTextWriterWriteFormatString(writer, "%s", ctx->name);
+ xmlTextWriterEndElement(writer); /* name */
+ }
+
+ REQUIRE(VALID_CONTEXT(ctx));
+ MCTXLOCK(ctx, &ctx->lock);
+
+ summary->contextsize += sizeof(*ctx) +
+ (ctx->max_size + 1) * sizeof(struct stats) +
+ ctx->max_size * sizeof(element *) +
+ ctx->basic_table_count * sizeof(char *);
+#if ISC_MEM_TRACKLINES
+ if (ctx->debuglist != NULL) {
+ summary->contextsize +=
+ (ctx->max_size + 1) * sizeof(debuglist_t) +
+ ctx->debuglistcnt * sizeof(debuglink_t);
+ }
+#endif
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+ xmlTextWriterWriteFormatString(writer, "%d", ctx->references);
+ xmlTextWriterEndElement(writer); /* references */
+
+ summary->total += ctx->total;
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "total");
+ xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+ (isc_uint64_t)ctx->total);
+ xmlTextWriterEndElement(writer); /* total */
+
+ summary->inuse += ctx->inuse;
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "inuse");
+ xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+ (isc_uint64_t)ctx->inuse);
+ xmlTextWriterEndElement(writer); /* inuse */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "maxinuse");
+ xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+ (isc_uint64_t)ctx->maxinuse);
+ xmlTextWriterEndElement(writer); /* maxinuse */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "blocksize");
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ summary->blocksize += ctx->basic_table_count *
+ NUM_BASIC_BLOCKS * ctx->mem_target;
+ xmlTextWriterWriteFormatString(writer,
+ "%" ISC_PRINT_QUADFORMAT "u",
+ (isc_uint64_t)
+ ctx->basic_table_count *
+ NUM_BASIC_BLOCKS *
+ ctx->mem_target);
+ } else
+ xmlTextWriterWriteFormatString(writer, "%s", "-");
+ xmlTextWriterEndElement(writer); /* blocksize */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "pools");
+ xmlTextWriterWriteFormatString(writer, "%u", ctx->poolcnt);
+ xmlTextWriterEndElement(writer); /* pools */
+ summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t);
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "hiwater");
+ xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+ (isc_uint64_t)ctx->hi_water);
+ xmlTextWriterEndElement(writer); /* hiwater */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "lowater");
+ xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+ (isc_uint64_t)ctx->lo_water);
+ xmlTextWriterEndElement(writer); /* lowater */
+
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ xmlTextWriterEndElement(writer); /* context */
+}
+
+void
+isc_mem_renderxml(xmlTextWriterPtr writer) {
+ isc_mem_t *ctx;
+ summarystat_t summary;
+ isc_uint64_t lost;
+
+ memset(&summary, 0, sizeof(summary));
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "contexts");
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+
+ LOCK(&lock);
+ lost = totallost;
+ for (ctx = ISC_LIST_HEAD(contexts);
+ ctx != NULL;
+ ctx = ISC_LIST_NEXT(ctx, link)) {
+ renderctx(ctx, &summary, writer);
+ }
+ UNLOCK(&lock);
+
+ xmlTextWriterEndElement(writer); /* contexts */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "summary");
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "TotalUse");
+ xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+ summary.total);
+ xmlTextWriterEndElement(writer); /* TotalUse */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "InUse");
+ xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+ summary.inuse);
+ xmlTextWriterEndElement(writer); /* InUse */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "BlockSize");
+ xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+ summary.blocksize);
+ xmlTextWriterEndElement(writer); /* BlockSize */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "ContextSize");
+ xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+ summary.contextsize);
+ xmlTextWriterEndElement(writer); /* ContextSize */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "Lost");
+ xmlTextWriterWriteFormatString(writer, "%" ISC_PRINT_QUADFORMAT "u",
+ lost);
+ xmlTextWriterEndElement(writer); /* Lost */
+
+ xmlTextWriterEndElement(writer); /* summary */
+}
+
+#endif /* HAVE_LIBXML2 */
diff --git a/lib/isc/mips/Makefile.in b/lib/isc/mips/Makefile.in
new file mode 100644
index 0000000..324db07
--- /dev/null
+++ b/lib/isc/mips/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = include
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/mips/include/Makefile.in b/lib/isc/mips/include/Makefile.in
new file mode 100644
index 0000000..f1d8bdd
--- /dev/null
+++ b/lib/isc/mips/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/mips/include/isc/Makefile.in b/lib/isc/mips/include/isc/Makefile.in
new file mode 100644
index 0000000..5f116ca
--- /dev/null
+++ b/lib/isc/mips/include/isc/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = atomic.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/mips/include/isc/atomic.h b/lib/isc/mips/include/isc/atomic.h
new file mode 100644
index 0000000..bb739f7
--- /dev/null
+++ b/lib/isc/mips/include/isc/atomic.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2005, 2007 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: atomic.h,v 1.3 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_USEGCCASM
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ */
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, int val) {
+ isc_int32_t orig;
+
+ /* add is a cheat, since MIPS has no mov instruction */
+ __asm__ volatile (
+ "1:"
+ "ll $3, %1\n"
+ "add %0, $0, $3\n"
+ "add $3, $3, %2\n"
+ "sc $3, %1\n"
+ "beq $3, 0, 1b"
+ : "=&r"(orig)
+ : "m"(*p), "r"(val)
+ : "memory", "$3"
+ );
+
+ return (orig);
+}
+
+/*
+ * This routine atomically stores the value 'val' in 'p'.
+ */
+static inline void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+ __asm__ volatile (
+ "1:"
+ "ll $3, %0\n"
+ "add $3, $0, %1\n"
+ "sc $3, %0\n"
+ "beq $3, 0, 1b"
+ :
+ : "m"(*p), "r"(val)
+ : "memory", "$3"
+ );
+}
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'. The original value is returned in any
+ * case.
+ */
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, int cmpval, int val) {
+ isc_int32_t orig;
+
+ __asm__ volatile(
+ "1:"
+ "ll $3, %1\n"
+ "add %0, $0, $3\n"
+ "bne $3, %2, 2f\n"
+ "add $3, $0, %3\n"
+ "sc $3, %1\n"
+ "beq $3, 0, 1b\n"
+ "2:"
+ : "=&r"(orig)
+ : "m"(*p), "r"(cmpval), "r"(val)
+ : "memory", "$3"
+ );
+
+ return (orig);
+}
+
+#else /* !ISC_PLATFORM_USEGCCASM */
+
+#error "unsupported compiler. disable atomic ops by --disable-atomic"
+
+#endif
+#endif /* ISC_ATOMIC_H */
diff --git a/lib/isc/mutexblock.c b/lib/isc/mutexblock.c
new file mode 100644
index 0000000..d45ad0e
--- /dev/null
+++ b/lib/isc/mutexblock.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: mutexblock.c,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mutexblock.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_mutexblock_init(isc_mutex_t *block, unsigned int count) {
+ isc_result_t result;
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ result = isc_mutex_init(&block[i]);
+ if (result != ISC_R_SUCCESS) {
+ i--;
+ while (i > 0) {
+ DESTROYLOCK(&block[i]);
+ i--;
+ }
+ return (result);
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_mutexblock_destroy(isc_mutex_t *block, unsigned int count) {
+ isc_result_t result;
+ unsigned int i;
+
+ for (i = 0; i < count; i++) {
+ result = isc_mutex_destroy(&block[i]);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c
new file mode 100644
index 0000000..85dd53e
--- /dev/null
+++ b/lib/isc/netaddr.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: netaddr.c,v 1.38 2007/06/18 23:47:44 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/buffer.h>
+#include <isc/msgs.h>
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+isc_boolean_t
+isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
+ REQUIRE(a != NULL && b != NULL);
+
+ if (a->family != b->family)
+ return (ISC_FALSE);
+
+ if (a->zone != b->zone)
+ return (ISC_FALSE);
+
+ switch (a->family) {
+ case AF_INET:
+ if (a->type.in.s_addr != b->type.in.s_addr)
+ return (ISC_FALSE);
+ break;
+ case AF_INET6:
+ if (memcmp(&a->type.in6, &b->type.in6,
+ sizeof(a->type.in6)) != 0 ||
+ a->zone != b->zone)
+ return (ISC_FALSE);
+ break;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ case AF_UNIX:
+ if (strcmp(a->type.un, b->type.un) != 0)
+ return (ISC_FALSE);
+ break;
+#endif
+ default:
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+isc_boolean_t
+isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
+ unsigned int prefixlen)
+{
+ const unsigned char *pa, *pb;
+ unsigned int ipabytes; /* Length of whole IP address in bytes */
+ unsigned int nbytes; /* Number of significant whole bytes */
+ unsigned int nbits; /* Number of significant leftover bits */
+
+ REQUIRE(a != NULL && b != NULL);
+
+ if (a->family != b->family)
+ return (ISC_FALSE);
+
+ if (a->zone != b->zone && b->zone != 0)
+ return (ISC_FALSE);
+
+ switch (a->family) {
+ case AF_INET:
+ pa = (const unsigned char *) &a->type.in;
+ pb = (const unsigned char *) &b->type.in;
+ ipabytes = 4;
+ break;
+ case AF_INET6:
+ pa = (const unsigned char *) &a->type.in6;
+ pb = (const unsigned char *) &b->type.in6;
+ ipabytes = 16;
+ break;
+ default:
+ pa = pb = NULL; /* Avoid silly compiler warning. */
+ ipabytes = 0; /* Ditto. */
+ return (ISC_FALSE);
+ }
+
+ /*
+ * Don't crash if we get a pattern like 10.0.0.1/9999999.
+ */
+ if (prefixlen > ipabytes * 8)
+ prefixlen = ipabytes * 8;
+
+ nbytes = prefixlen / 8;
+ nbits = prefixlen % 8;
+
+ if (nbytes > 0) {
+ if (memcmp(pa, pb, nbytes) != 0)
+ return (ISC_FALSE);
+ }
+ if (nbits > 0) {
+ unsigned int bytea, byteb, mask;
+ INSIST(nbytes < ipabytes);
+ INSIST(nbits < 8);
+ bytea = pa[nbytes];
+ byteb = pb[nbytes];
+ mask = (0xFF << (8-nbits)) & 0xFF;
+ if ((bytea & mask) != (byteb & mask))
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+isc_result_t
+isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
+ char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
+ char zbuf[sizeof("%4294967295")];
+ unsigned int alen;
+ int zlen;
+ const char *r;
+ const void *type;
+
+ REQUIRE(netaddr != NULL);
+
+ switch (netaddr->family) {
+ case AF_INET:
+ type = &netaddr->type.in;
+ break;
+ case AF_INET6:
+ type = &netaddr->type.in6;
+ break;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ case AF_UNIX:
+ alen = strlen(netaddr->type.un);
+ if (alen > isc_buffer_availablelength(target))
+ return (ISC_R_NOSPACE);
+ isc_buffer_putmem(target,
+ (const unsigned char *)(netaddr->type.un),
+ alen);
+ return (ISC_R_SUCCESS);
+#endif
+ default:
+ return (ISC_R_FAILURE);
+ }
+ r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
+ if (r == NULL)
+ return (ISC_R_FAILURE);
+
+ alen = strlen(abuf);
+ INSIST(alen < sizeof(abuf));
+
+ zlen = 0;
+ if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
+ zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
+ if (zlen < 0)
+ return (ISC_R_FAILURE);
+ INSIST((unsigned int)zlen < sizeof(zbuf));
+ }
+
+ if (alen + zlen > isc_buffer_availablelength(target))
+ return (ISC_R_NOSPACE);
+
+ isc_buffer_putmem(target, (unsigned char *)abuf, alen);
+ isc_buffer_putmem(target, (unsigned char *)zbuf, zlen);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
+ isc_result_t result;
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, array, size);
+ result = isc_netaddr_totext(na, &buf);
+
+ /*
+ * Null terminate.
+ */
+ if (result == ISC_R_SUCCESS) {
+ if (isc_buffer_availablelength(&buf) >= 1)
+ isc_buffer_putuint8(&buf, 0);
+ else
+ result = ISC_R_NOSPACE;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ snprintf(array, size,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
+ ISC_MSG_UNKNOWNADDR,
+ "<unknown address, family %u>"),
+ na->family);
+ array[size - 1] = '\0';
+ }
+}
+
+
+isc_result_t
+isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
+ static const unsigned char zeros[16];
+ unsigned int nbits, nbytes, ipbytes;
+ const unsigned char *p;
+
+ switch (na->family) {
+ case AF_INET:
+ p = (const unsigned char *) &na->type.in;
+ ipbytes = 4;
+ if (prefixlen > 32)
+ return (ISC_R_RANGE);
+ break;
+ case AF_INET6:
+ p = (const unsigned char *) &na->type.in6;
+ ipbytes = 16;
+ if (prefixlen > 128)
+ return (ISC_R_RANGE);
+ break;
+ default:
+ ipbytes = 0;
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+ nbytes = prefixlen / 8;
+ nbits = prefixlen % 8;
+ if (nbits != 0) {
+ if ((p[nbytes] & (0xff>>nbits)) != 0U)
+ return (ISC_R_FAILURE);
+ nbytes++;
+ }
+ if (memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0)
+ return (ISC_R_FAILURE);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
+ unsigned int nbits, nbytes, ipbytes, i;
+ const unsigned char *p;
+
+ switch (s->family) {
+ case AF_INET:
+ p = (const unsigned char *) &s->type.in;
+ ipbytes = 4;
+ break;
+ case AF_INET6:
+ p = (const unsigned char *) &s->type.in6;
+ ipbytes = 16;
+ break;
+ default:
+ ipbytes = 0;
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+ nbytes = nbits = 0;
+ for (i = 0; i < ipbytes; i++) {
+ if (p[i] != 0xFF)
+ break;
+ }
+ nbytes = i;
+ if (i < ipbytes) {
+ unsigned int c = p[nbytes];
+ while ((c & 0x80) != 0 && nbits < 8) {
+ c <<= 1; nbits++;
+ }
+ if ((c & 0xFF) != 0)
+ return (ISC_R_MASKNONCONTIG);
+ i++;
+ }
+ for (; i < ipbytes; i++) {
+ if (p[i] != 0)
+ return (ISC_R_MASKNONCONTIG);
+ i++;
+ }
+ *lenp = nbytes * 8 + nbits;
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
+ memset(netaddr, 0, sizeof(*netaddr));
+ netaddr->family = AF_INET;
+ netaddr->type.in = *ina;
+}
+
+void
+isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
+ memset(netaddr, 0, sizeof(*netaddr));
+ netaddr->family = AF_INET6;
+ netaddr->type.in6 = *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
+ UNUSED(netaddr);
+ UNUSED(path);
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+
+void
+isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone) {
+ /* we currently only support AF_INET6. */
+ REQUIRE(netaddr->family == AF_INET6);
+
+ netaddr->zone = zone;
+}
+
+isc_uint32_t
+isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
+ return (netaddr->zone);
+}
+
+void
+isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
+ int family = s->type.sa.sa_family;
+ t->family = family;
+ switch (family) {
+ case AF_INET:
+ t->type.in = s->type.sin.sin_addr;
+ t->zone = 0;
+ break;
+ case AF_INET6:
+ memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16);
+#ifdef ISC_PLATFORM_HAVESCOPEID
+ t->zone = s->type.sin6.sin6_scope_id;
+#else
+ t->zone = 0;
+#endif
+ break;
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ case AF_UNIX:
+ memcpy(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
+ t->zone = 0;
+ break;
+#endif
+ default:
+ INSIST(0);
+ }
+}
+
+void
+isc_netaddr_any(isc_netaddr_t *netaddr) {
+ memset(netaddr, 0, sizeof(*netaddr));
+ netaddr->family = AF_INET;
+ netaddr->type.in.s_addr = INADDR_ANY;
+}
+
+void
+isc_netaddr_any6(isc_netaddr_t *netaddr) {
+ memset(netaddr, 0, sizeof(*netaddr));
+ netaddr->family = AF_INET6;
+ netaddr->type.in6 = in6addr_any;
+}
+
+isc_boolean_t
+isc_netaddr_ismulticast(isc_netaddr_t *na) {
+ switch (na->family) {
+ case AF_INET:
+ return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr)));
+ case AF_INET6:
+ return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6)));
+ default:
+ return (ISC_FALSE); /* XXXMLG ? */
+ }
+}
+
+isc_boolean_t
+isc_netaddr_isexperimental(isc_netaddr_t *na) {
+ switch (na->family) {
+ case AF_INET:
+ return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr)));
+ default:
+ return (ISC_FALSE); /* XXXMLG ? */
+ }
+}
+
+isc_boolean_t
+isc_netaddr_islinklocal(isc_netaddr_t *na) {
+ switch (na->family) {
+ case AF_INET:
+ return (ISC_FALSE);
+ case AF_INET6:
+ return (ISC_TF(IN6_IS_ADDR_LINKLOCAL(&na->type.in6)));
+ default:
+ return (ISC_FALSE);
+ }
+}
+
+isc_boolean_t
+isc_netaddr_issitelocal(isc_netaddr_t *na) {
+ switch (na->family) {
+ case AF_INET:
+ return (ISC_FALSE);
+ case AF_INET6:
+ return (ISC_TF(IN6_IS_ADDR_SITELOCAL(&na->type.in6)));
+ default:
+ return (ISC_FALSE);
+ }
+}
+
+void
+isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
+ isc_netaddr_t *src;
+
+ DE_CONST(s, src); /* Must come before IN6_IS_ADDR_V4MAPPED. */
+
+ REQUIRE(s->family == AF_INET6);
+ REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
+
+ memset(t, 0, sizeof(*t));
+ t->family = AF_INET;
+ memcpy(&t->type.in, (char *)&src->type.in6 + 12, 4);
+ return;
+}
diff --git a/lib/isc/netscope.c b/lib/isc/netscope.c
new file mode 100644
index 0000000..9aa11db
--- /dev/null
+++ b/lib/isc/netscope.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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.
+ */
+
+/*! \file */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] =
+ "$Id: netscope.c,v 1.13 2007/06/19 23:47:17 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <isc/string.h>
+#include <isc/net.h>
+#include <isc/netscope.h>
+#include <isc/result.h>
+
+isc_result_t
+isc_netscope_pton(int af, char *scopename, void *addr, isc_uint32_t *zoneid) {
+ char *ep;
+#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
+ unsigned int ifid;
+#endif
+ struct in6_addr *in6;
+ isc_uint32_t zone;
+ isc_uint64_t llz;
+
+ /* at this moment, we only support AF_INET6 */
+ if (af != AF_INET6)
+ return (ISC_R_FAILURE);
+
+ in6 = (struct in6_addr *)addr;
+
+ /*
+ * Basically, "names" are more stable than numeric IDs in terms of
+ * renumbering, and are more preferred. However, since there is no
+ * standard naming convention and APIs to deal with the names. Thus,
+ * we only handle the case of link-local addresses, for which we use
+ * interface names as link names, assuming one to one mapping between
+ * interfaces and links.
+ */
+#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
+ if (IN6_IS_ADDR_LINKLOCAL(in6) &&
+ (ifid = if_nametoindex((const char *)scopename)) != 0)
+ zone = (isc_uint32_t)ifid;
+ else {
+#endif
+ llz = isc_string_touint64(scopename, &ep, 10);
+ if (ep == scopename)
+ return (ISC_R_FAILURE);
+
+ /* check overflow */
+ zone = (isc_uint32_t)(llz & 0xffffffffUL);
+ if (zone != llz)
+ return (ISC_R_FAILURE);
+#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
+ }
+#endif
+
+ *zoneid = zone;
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/nls/Makefile.in b/lib/isc/nls/Makefile.in
new file mode 100644
index 0000000..695c313
--- /dev/null
+++ b/lib/isc/nls/Makefile.in
@@ -0,0 +1,37 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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.14 2007/06/19 23:47:18 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+CINCLUDES = -I../unix/include \
+ -I${srcdir}/../unix/include \
+ -I../include \
+ -I${srcdir}/../include
+
+CDEFINES =
+CWARNINGS =
+
+OBJS = msgcat.@O@
+
+SRCS = msgcat.c
+
+SUBDIRS =
+TARGETS = ${OBJS}
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/nls/msgcat.c b/lib/isc/nls/msgcat.c
new file mode 100644
index 0000000..3d6b676
--- /dev/null
+++ b/lib/isc/nls/msgcat.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: msgcat.c,v 1.18 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file msgcat.c
+ *
+ * \author Principal Author: Bob Halley
+ */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <isc/magic.h>
+#include <isc/msgcat.h>
+#include <isc/util.h>
+
+#ifdef HAVE_CATGETS
+#include <nl_types.h> /* Required for nl_catd. */
+#endif
+
+/*
+ * Implementation Notes:
+ *
+ * We use malloc() and free() instead of isc_mem_get() and isc_mem_put()
+ * because we don't want to require a memory context to be specified
+ * in order to use a message catalog.
+ */
+
+struct isc_msgcat {
+ unsigned int magic;
+#ifdef HAVE_CATGETS
+ nl_catd catalog;
+#endif
+};
+
+#define MSGCAT_MAGIC ISC_MAGIC('M', 'C', 'a', 't')
+#define VALID_MSGCAT(m) ISC_MAGIC_VALID(m, MSGCAT_MAGIC)
+
+void
+isc_msgcat_open(const char *name, isc_msgcat_t **msgcatp) {
+ isc_msgcat_t *msgcat;
+
+ /*
+ * Open a message catalog.
+ */
+
+ REQUIRE(name != NULL);
+ REQUIRE(msgcatp != NULL && *msgcatp == NULL);
+
+ msgcat = malloc(sizeof(*msgcat));
+ if (msgcat == NULL) {
+ *msgcatp = NULL;
+ return;
+ }
+
+#ifdef HAVE_CATGETS
+ /*
+ * We don't check if catopen() fails because we don't care.
+ * If it does fail, then when we call catgets(), it will use
+ * the default string.
+ */
+ msgcat->catalog = catopen(name, 0);
+#endif
+ msgcat->magic = MSGCAT_MAGIC;
+
+ *msgcatp = msgcat;
+}
+
+void
+isc_msgcat_close(isc_msgcat_t **msgcatp) {
+ isc_msgcat_t *msgcat;
+
+ /*
+ * Close a message catalog.
+ */
+
+ REQUIRE(msgcatp != NULL);
+ msgcat = *msgcatp;
+ REQUIRE(VALID_MSGCAT(msgcat) || msgcat == NULL);
+
+ if (msgcat != NULL) {
+#ifdef HAVE_CATGETS
+ if (msgcat->catalog != (nl_catd)(-1))
+ (void)catclose(msgcat->catalog);
+#endif
+ msgcat->magic = 0;
+ free(msgcat);
+ }
+
+ *msgcatp = NULL;
+}
+
+const char *
+isc_msgcat_get(isc_msgcat_t *msgcat, int set, int message,
+ const char *default_text)
+{
+ /*
+ * Get message 'message' from message set 'set' in 'msgcat'. If it
+ * is not available, use 'default'.
+ */
+
+ REQUIRE(VALID_MSGCAT(msgcat) || msgcat == NULL);
+ REQUIRE(set > 0);
+ REQUIRE(message > 0);
+ REQUIRE(default_text != NULL);
+
+#ifdef HAVE_CATGETS
+ if (msgcat == NULL)
+ return (default_text);
+ return (catgets(msgcat->catalog, set, message, default_text));
+#else
+ return (default_text);
+#endif
+}
diff --git a/lib/isc/noatomic/Makefile.in b/lib/isc/noatomic/Makefile.in
new file mode 100644
index 0000000..324db07
--- /dev/null
+++ b/lib/isc/noatomic/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = include
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/noatomic/include/Makefile.in b/lib/isc/noatomic/include/Makefile.in
new file mode 100644
index 0000000..f1d8bdd
--- /dev/null
+++ b/lib/isc/noatomic/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/noatomic/include/isc/Makefile.in b/lib/isc/noatomic/include/isc/Makefile.in
new file mode 100644
index 0000000..5f116ca
--- /dev/null
+++ b/lib/isc/noatomic/include/isc/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = atomic.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/noatomic/include/isc/atomic.h b/lib/isc/noatomic/include/isc/atomic.h
new file mode 100644
index 0000000..942ba03
--- /dev/null
+++ b/lib/isc/noatomic/include/isc/atomic.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2005, 2007 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: atomic.h,v 1.4 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+/* This file is inherently empty. */
+
+#endif /* ISC_ATOMIC_H */
diff --git a/lib/isc/nothreads/Makefile.in b/lib/isc/nothreads/Makefile.in
new file mode 100644
index 0000000..75a2cb5
--- /dev/null
+++ b/lib/isc/nothreads/Makefile.in
@@ -0,0 +1,38 @@
+# Copyright (C) 2004, 2007 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: Makefile.in,v 1.7 2007/06/19 23:47:18 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+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/isc/nothreads/condition.c b/lib/isc/nothreads/condition.c
new file mode 100644
index 0000000..9be8f83
--- /dev/null
+++ b/lib/isc/nothreads/condition.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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: condition.c,v 1.10 2007/06/19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+EMPTY_TRANSLATION_UNIT
diff --git a/lib/isc/nothreads/include/Makefile.in b/lib/isc/nothreads/include/Makefile.in
new file mode 100644
index 0000000..a52310a
--- /dev/null
+++ b/lib/isc/nothreads/include/Makefile.in
@@ -0,0 +1,25 @@
+# Copyright (C) 2004, 2007 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: Makefile.in,v 1.5 2007/06/19 23:47:18 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/nothreads/include/isc/Makefile.in b/lib/isc/nothreads/include/isc/Makefile.in
new file mode 100644
index 0000000..3c9eab0
--- /dev/null
+++ b/lib/isc/nothreads/include/isc/Makefile.in
@@ -0,0 +1,37 @@
+# Copyright (C) 2004, 2007 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: Makefile.in,v 1.7 2007/06/19 23:47:18 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @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}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/nothreads/include/isc/condition.h b/lib/isc/nothreads/include/isc/condition.h
new file mode 100644
index 0000000..b269f82
--- /dev/null
+++ b/lib/isc/nothreads/include/isc/condition.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004, 2007 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: condition.h,v 1.6 2007/06/19 23:47:18 tbox Exp $ */
+
+/*
+ * This provides a limited subset of the isc_condition_t
+ * functionality for use by single-threaded programs that
+ * need to block waiting for events. Only a single
+ * call to isc_condition_wait() may be blocked at any given
+ * time, and the _waituntil and _broadcast functions are not
+ * supported. This is intended primarily for use by the omapi
+ * library, and may go away once omapi goes away. Use for
+ * other purposes is strongly discouraged.
+ */
+
+#ifndef ISC_CONDITION_H
+#define ISC_CONDITION_H 1
+
+#include <isc/mutex.h>
+
+typedef int isc_condition_t;
+
+isc_result_t isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp);
+isc_result_t isc__nothread_signal_hack(isc_condition_t *cp);
+
+#define isc_condition_init(cp) \
+ (*(cp) = 0, ISC_R_SUCCESS)
+
+#define isc_condition_wait(cp, mp) \
+ isc__nothread_wait_hack(cp, mp)
+
+#define isc_condition_waituntil(cp, mp, tp) \
+ ((void)(cp), (void)(mp), (void)(tp), ISC_R_NOTIMPLEMENTED)
+
+#define isc_condition_signal(cp) \
+ isc__nothread_signal_hack(cp)
+
+#define isc_condition_broadcast(cp) \
+ ((void)(cp), ISC_R_NOTIMPLEMENTED)
+
+#define isc_condition_destroy(cp) \
+ (*(cp) == 0 ? (*(cp) = -1, ISC_R_SUCCESS) : ISC_R_UNEXPECTED)
+
+#endif /* ISC_CONDITION_H */
diff --git a/lib/isc/nothreads/include/isc/mutex.h b/lib/isc/nothreads/include/isc/mutex.h
new file mode 100644
index 0000000..1f2187b
--- /dev/null
+++ b/lib/isc/nothreads/include/isc/mutex.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004, 2007 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: mutex.h,v 1.6 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_MUTEX_H
+#define ISC_MUTEX_H 1
+
+#include <isc/result.h> /* for ISC_R_ codes */
+
+typedef int isc_mutex_t;
+
+#define isc_mutex_init(mp) \
+ (*(mp) = 0, ISC_R_SUCCESS)
+#define isc_mutex_lock(mp) \
+ ((*(mp))++ == 0 ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#define isc_mutex_unlock(mp) \
+ (--(*(mp)) == 0 ? ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#define isc_mutex_trylock(mp) \
+ (*(mp) == 0 ? ((*(mp))++, ISC_R_SUCCESS) : ISC_R_LOCKBUSY)
+#define isc_mutex_destroy(mp) \
+ (*(mp) == 0 ? (*(mp) = -1, ISC_R_SUCCESS) : ISC_R_UNEXPECTED)
+#define isc_mutex_stats(fp)
+
+#endif /* ISC_MUTEX_H */
diff --git a/lib/isc/nothreads/include/isc/once.h b/lib/isc/nothreads/include/isc/once.h
new file mode 100644
index 0000000..ab705a4
--- /dev/null
+++ b/lib/isc/nothreads/include/isc/once.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2004, 2007 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: once.h,v 1.6 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ONCE_H
+#define ISC_ONCE_H 1
+
+#include <isc/result.h>
+
+typedef isc_boolean_t isc_once_t;
+
+#define ISC_ONCE_INIT ISC_FALSE
+
+#define isc_once_do(op, f) \
+ (!*(op) ? (f(), *(op) = ISC_TRUE, ISC_R_SUCCESS) : ISC_R_SUCCESS)
+
+#endif /* ISC_ONCE_H */
diff --git a/lib/isc/nothreads/include/isc/thread.h b/lib/isc/nothreads/include/isc/thread.h
new file mode 100644
index 0000000..313bc5f
--- /dev/null
+++ b/lib/isc/nothreads/include/isc/thread.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004, 2007 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: thread.h,v 1.6 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_THREAD_H
+#define ISC_THREAD_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_thread_setconcurrency(unsigned int level);
+
+#define isc_thread_self() ((unsigned long)0)
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_THREAD_H */
diff --git a/lib/isc/nothreads/mutex.c b/lib/isc/nothreads/mutex.c
new file mode 100644
index 0000000..50ba0f4
--- /dev/null
+++ b/lib/isc/nothreads/mutex.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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: mutex.c,v 1.10 2007/06/19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+EMPTY_TRANSLATION_UNIT
+
diff --git a/lib/isc/nothreads/thread.c b/lib/isc/nothreads/thread.c
new file mode 100644
index 0000000..9075e25
--- /dev/null
+++ b/lib/isc/nothreads/thread.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2007 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: thread.c,v 1.5 2007/06/19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/thread.h>
+#include <isc/util.h>
+
+void
+isc_thread_setconcurrency(unsigned int level) {
+ UNUSED(level);
+}
diff --git a/lib/isc/ondestroy.c b/lib/isc/ondestroy.c
new file mode 100644
index 0000000..32a75e1
--- /dev/null
+++ b/lib/isc/ondestroy.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: ondestroy.c,v 1.16 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/event.h>
+#include <isc/magic.h>
+#include <isc/ondestroy.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#define ONDESTROY_MAGIC ISC_MAGIC('D', 'e', 'S', 't')
+#define VALID_ONDESTROY(s) ISC_MAGIC_VALID(s, ONDESTROY_MAGIC)
+
+void
+isc_ondestroy_init(isc_ondestroy_t *ondest) {
+ ondest->magic = ONDESTROY_MAGIC;
+ ISC_LIST_INIT(ondest->events);
+}
+
+isc_result_t
+isc_ondestroy_register(isc_ondestroy_t *ondest, isc_task_t *task,
+ isc_event_t **eventp)
+{
+ isc_event_t *theevent;
+ isc_task_t *thetask = NULL;
+
+ REQUIRE(VALID_ONDESTROY(ondest));
+ REQUIRE(task != NULL);
+ REQUIRE(eventp != NULL);
+
+ theevent = *eventp;
+
+ REQUIRE(theevent != NULL);
+
+ isc_task_attach(task, &thetask);
+
+ theevent->ev_sender = thetask;
+
+ ISC_LIST_APPEND(ondest->events, theevent, ev_link);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_ondestroy_notify(isc_ondestroy_t *ondest, void *sender) {
+ isc_event_t *eventp;
+ isc_task_t *task;
+
+ REQUIRE(VALID_ONDESTROY(ondest));
+
+ eventp = ISC_LIST_HEAD(ondest->events);
+ while (eventp != NULL) {
+ ISC_LIST_UNLINK(ondest->events, eventp, ev_link);
+
+ task = eventp->ev_sender;
+ eventp->ev_sender = sender;
+
+ isc_task_sendanddetach(&task, &eventp);
+
+ eventp = ISC_LIST_HEAD(ondest->events);
+ }
+}
+
+
diff --git a/lib/isc/parseint.c b/lib/isc/parseint.c
new file mode 100644
index 0000000..266d44c
--- /dev/null
+++ b/lib/isc/parseint.c
@@ -0,0 +1,72 @@
+/*
+ * 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: parseint.c,v 1.8 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <isc/parseint.h>
+#include <isc/result.h>
+#include <isc/stdlib.h>
+
+isc_result_t
+isc_parse_uint32(isc_uint32_t *uip, const char *string, int base) {
+ unsigned long n;
+ char *e;
+ if (! isalnum((unsigned char)(string[0])))
+ return (ISC_R_BADNUMBER);
+ errno = 0;
+ n = strtoul(string, &e, base);
+ if (*e != '\0')
+ return (ISC_R_BADNUMBER);
+ if (n == ULONG_MAX && errno == ERANGE)
+ return (ISC_R_RANGE);
+ *uip = n;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_parse_uint16(isc_uint16_t *uip, const char *string, int base) {
+ isc_uint32_t val;
+ isc_result_t result;
+ result = isc_parse_uint32(&val, string, base);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (val > 0xFFFF)
+ return (ISC_R_RANGE);
+ *uip = (isc_uint16_t) val;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_parse_uint8(isc_uint8_t *uip, const char *string, int base) {
+ isc_uint32_t val;
+ isc_result_t result;
+ result = isc_parse_uint32(&val, string, base);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (val > 0xFF)
+ return (ISC_R_RANGE);
+ *uip = (isc_uint8_t) val;
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/portset.c b/lib/isc/portset.c
new file mode 100644
index 0000000..471ca8e
--- /dev/null
+++ b/lib/isc/portset.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008 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: portset.c,v 1.4 2008/06/24 23:24:35 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/portset.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#define ISC_PORTSET_BUFSIZE (65536 / (sizeof(isc_uint32_t) * 8))
+
+/*%
+ * Internal representation of portset. It's an array of 32-bit integers, each
+ * bit corresponding to a single port in the ascending order. For example,
+ * the second most significant bit of buf[0] corresponds to port 1.
+ */
+struct isc_portset {
+ unsigned int nports; /*%< number of ports in the set */
+ isc_uint32_t buf[ISC_PORTSET_BUFSIZE];
+};
+
+static inline isc_boolean_t
+portset_isset(isc_portset_t *portset, in_port_t port) {
+ return (ISC_TF((portset->buf[port >> 5] & (1 << (port & 31))) != 0));
+}
+
+static inline void
+portset_add(isc_portset_t *portset, in_port_t port) {
+ if (!portset_isset(portset, port)) {
+ portset->nports++;
+ portset->buf[port >> 5] |= (1 << (port & 31));
+ }
+}
+
+static inline void
+portset_remove(isc_portset_t *portset, in_port_t port) {
+ if (portset_isset(portset, port)) {
+ portset->nports--;
+ portset->buf[port >> 5] &= ~(1 << (port & 31));
+ }
+}
+
+isc_result_t
+isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp) {
+ isc_portset_t *portset;
+
+ REQUIRE(portsetp != NULL && *portsetp == NULL);
+
+ portset = isc_mem_get(mctx, sizeof(*portset));
+ if (portset == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /* Make the set 'empty' by default */
+ memset(portset, 0, sizeof(*portset));
+ *portsetp = portset;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp) {
+ isc_portset_t *portset;
+
+ REQUIRE(portsetp != NULL);
+ portset = *portsetp;
+
+ isc_mem_put(mctx, portset, sizeof(*portset));
+}
+
+isc_boolean_t
+isc_portset_isset(isc_portset_t *portset, in_port_t port) {
+ REQUIRE(portset != NULL);
+
+ return (portset_isset(portset, port));
+}
+
+unsigned int
+isc_portset_nports(isc_portset_t *portset) {
+ REQUIRE(portset != NULL);
+
+ return (portset->nports);
+}
+
+void
+isc_portset_add(isc_portset_t *portset, in_port_t port) {
+ REQUIRE(portset != NULL);
+
+ portset_add(portset, port);
+}
+
+void
+isc_portset_remove(isc_portset_t *portset, in_port_t port) {
+ portset_remove(portset, port);
+}
+
+void
+isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
+ in_port_t port_hi)
+{
+ in_port_t p;
+
+ REQUIRE(portset != NULL);
+ REQUIRE(port_lo <= port_hi);
+
+ p = port_lo;
+ do {
+ portset_add(portset, p);
+ } while (p++ < port_hi);
+}
+
+void
+isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
+ in_port_t port_hi)
+{
+ in_port_t p;
+
+ REQUIRE(portset != NULL);
+ REQUIRE(port_lo <= port_hi);
+
+ p = port_lo;
+ do {
+ portset_remove(portset, p);
+ } while (p++ < port_hi);
+}
diff --git a/lib/isc/powerpc/Makefile.in b/lib/isc/powerpc/Makefile.in
new file mode 100644
index 0000000..324db07
--- /dev/null
+++ b/lib/isc/powerpc/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = include
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/powerpc/include/Makefile.in b/lib/isc/powerpc/include/Makefile.in
new file mode 100644
index 0000000..f1d8bdd
--- /dev/null
+++ b/lib/isc/powerpc/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/powerpc/include/isc/Makefile.in b/lib/isc/powerpc/include/isc/Makefile.in
new file mode 100644
index 0000000..5f116ca
--- /dev/null
+++ b/lib/isc/powerpc/include/isc/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = atomic.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/powerpc/include/isc/atomic.h b/lib/isc/powerpc/include/isc/atomic.h
new file mode 100644
index 0000000..765cb6d
--- /dev/null
+++ b/lib/isc/powerpc/include/isc/atomic.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2005, 2007 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: atomic.h,v 1.6 2007/06/18 23:47:47 tbox Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+/*!\file
+ * static inline isc_int32_t
+ * isc_atomic_xadd(isc_int32_t *p, isc_int32_t val);
+ *
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ *
+ * static inline void
+ * isc_atomic_store(void *p, isc_int32_t val);
+ *
+ * This routine atomically stores the value 'val' in 'p'.
+ *
+ * static inline isc_int32_t
+ * isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val);
+ *
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'. The original value is returned in any
+ * case.
+ */
+
+#if defined(_AIX)
+
+#include <sys/atomic_op.h>
+
+#define isc_atomic_xadd(p, v) fetch_and_add(p, v)
+#define isc_atomic_store(p, v) _clear_lock(p, v)
+
+#ifdef __GNUC__
+static inline int
+#else
+static int
+#endif
+isc_atomic_cmpxchg(atomic_p p, int old, int new) {
+ int orig = old;
+
+#ifdef __GNUC__
+ asm("ics");
+#else
+ __isync();
+#endif
+ if (compare_and_swap(p, &orig, new))
+ return (old);
+ return (orig);
+}
+
+#elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM)
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+ isc_int32_t orig;
+
+ __asm__ volatile (
+#ifdef ISC_PLATFORM_USEMACASM
+ "1:"
+ "lwarx r6, 0, %1\n"
+ "mr %0, r6\n"
+ "add r6, r6, %2\n"
+ "stwcx. r6, 0, %1\n"
+ "bne- 1b"
+#else
+ "1:"
+ "lwarx 6, 0, %1\n"
+ "mr %0, 6\n"
+ "add 6, 6, %2\n"
+ "stwcx. 6, 0, %1\n"
+ "bne- 1b"
+#endif
+ : "=&r"(orig)
+ : "r"(p), "r"(val)
+ : "r6", "memory"
+ );
+
+ return (orig);
+}
+
+static inline void
+isc_atomic_store(void *p, isc_int32_t val) {
+ __asm__ volatile (
+#ifdef ISC_PLATFORM_USEMACASM
+ "1:"
+ "lwarx r6, 0, %0\n"
+ "lwz r6, %1\n"
+ "stwcx. r6, 0, %0\n"
+ "bne- 1b"
+#else
+ "1:"
+ "lwarx 6, 0, %0\n"
+ "lwz 6, %1\n"
+ "stwcx. 6, 0, %0\n"
+ "bne- 1b"
+#endif
+ :
+ : "r"(p), "m"(val)
+ : "r6", "memory"
+ );
+}
+
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+ isc_int32_t orig;
+
+ __asm__ volatile (
+#ifdef ISC_PLATFORM_USEMACASM
+ "1:"
+ "lwarx r6, 0, %1\n"
+ "mr %0,r6\n"
+ "cmpw r6, %2\n"
+ "bne 2f\n"
+ "mr r6, %3\n"
+ "stwcx. r6, 0, %1\n"
+ "bne- 1b\n"
+ "2:"
+#else
+ "1:"
+ "lwarx 6, 0, %1\n"
+ "mr %0,6\n"
+ "cmpw 6, %2\n"
+ "bne 2f\n"
+ "mr 6, %3\n"
+ "stwcx. 6, 0, %1\n"
+ "bne- 1b\n"
+ "2:"
+#endif
+ : "=&r" (orig)
+ : "r"(p), "r"(cmpval), "r"(val)
+ : "r6", "memory"
+ );
+
+ return (orig);
+}
+
+#else
+
+#error "unsupported compiler. disable atomic ops by --disable-atomic"
+
+#endif
+#endif /* ISC_ATOMIC_H */
diff --git a/lib/isc/print.c b/lib/isc/print.c
new file mode 100644
index 0000000..b892e3a
--- /dev/null
+++ b/lib/isc/print.c
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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: print.c,v 1.35 2008/02/18 23:46:59 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdio.h> /* for sprintf() */
+#include <string.h> /* for strlen() */
+
+#define ISC__PRINT_SOURCE /* Used to get the isc_print_* prototypes. */
+
+#include <isc/assertions.h>
+#include <isc/int.h>
+#include <isc/msgs.h>
+#include <isc/print.h>
+#include <isc/stdlib.h>
+#include <isc/util.h>
+
+int
+isc_print_sprintf(char *str, const char *format, ...) {
+ va_list ap;
+
+ va_start(ap, format);
+ vsprintf(str, format, ap);
+ va_end(ap);
+ return (strlen(str));
+}
+
+/*!
+ * Return length of string that would have been written if not truncated.
+ */
+
+int
+isc_print_snprintf(char *str, size_t size, const char *format, ...) {
+ va_list ap;
+ int ret;
+
+ va_start(ap, format);
+ ret = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return (ret);
+
+}
+
+/*!
+ * Return length of string that would have been written if not truncated.
+ */
+
+int
+isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ int h;
+ int l;
+ int q;
+ int alt;
+ int zero;
+ int left;
+ int plus;
+ int space;
+ int neg;
+ isc_int64_t tmpi;
+ isc_uint64_t tmpui;
+ unsigned long width;
+ unsigned long precision;
+ unsigned int length;
+ char buf[1024];
+ char c;
+ void *v;
+ char *save = str;
+ const char *cp;
+ const char *head;
+ int count = 0;
+ int pad;
+ int zeropad;
+ int dot;
+ double dbl;
+#ifdef HAVE_LONG_DOUBLE
+ long double ldbl;
+#endif
+ char fmt[32];
+
+ INSIST(str != NULL);
+ INSIST(format != NULL);
+
+ while (*format != '\0') {
+ if (*format != '%') {
+ if (size > 1) {
+ *str++ = *format;
+ size--;
+ }
+ count++;
+ format++;
+ continue;
+ }
+ format++;
+
+ /*
+ * Reset flags.
+ */
+ dot = neg = space = plus = left = zero = alt = h = l = q = 0;
+ width = precision = 0;
+ head = "";
+ length = pad = zeropad = 0;
+
+ do {
+ if (*format == '#') {
+ alt = 1;
+ format++;
+ } else if (*format == '-') {
+ left = 1;
+ zero = 0;
+ format++;
+ } else if (*format == ' ') {
+ if (!plus)
+ space = 1;
+ format++;
+ } else if (*format == '+') {
+ plus = 1;
+ space = 0;
+ format++;
+ } else if (*format == '0') {
+ if (!left)
+ zero = 1;
+ format++;
+ } else
+ break;
+ } while (1);
+
+ /*
+ * Width.
+ */
+ if (*format == '*') {
+ width = va_arg(ap, int);
+ format++;
+ } else if (isdigit((unsigned char)*format)) {
+ char *e;
+ width = strtoul(format, &e, 10);
+ format = e;
+ }
+
+ /*
+ * Precision.
+ */
+ if (*format == '.') {
+ format++;
+ dot = 1;
+ if (*format == '*') {
+ precision = va_arg(ap, int);
+ format++;
+ } else if (isdigit((unsigned char)*format)) {
+ char *e;
+ precision = strtoul(format, &e, 10);
+ format = e;
+ }
+ }
+
+ switch (*format) {
+ case '\0':
+ continue;
+ case '%':
+ if (size > 1) {
+ *str++ = *format;
+ size--;
+ }
+ count++;
+ break;
+ case 'q':
+ q = 1;
+ format++;
+ goto doint;
+ case 'h':
+ h = 1;
+ format++;
+ goto doint;
+ case 'l':
+ l = 1;
+ format++;
+ if (*format == 'l') {
+ q = 1;
+ format++;
+ }
+ goto doint;
+ case 'n':
+ case 'i':
+ case 'd':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ doint:
+ if (precision != 0)
+ zero = 0;
+ switch (*format) {
+ case 'n':
+ if (h) {
+ short int *p;
+ p = va_arg(ap, short *);
+ REQUIRE(p != NULL);
+ *p = str - save;
+ } else if (l) {
+ long int *p;
+ p = va_arg(ap, long *);
+ REQUIRE(p != NULL);
+ *p = str - save;
+ } else {
+ int *p;
+ p = va_arg(ap, int *);
+ REQUIRE(p != NULL);
+ *p = str - save;
+ }
+ break;
+ case 'i':
+ case 'd':
+ if (q)
+ tmpi = va_arg(ap, isc_int64_t);
+ else if (l)
+ tmpi = va_arg(ap, long int);
+ else
+ tmpi = va_arg(ap, int);
+ if (tmpi < 0) {
+ head = "-";
+ tmpui = -tmpi;
+ } else {
+ if (plus)
+ head = "+";
+ else if (space)
+ head = " ";
+ else
+ head = "";
+ tmpui = tmpi;
+ }
+ if (tmpui <= 0xffffffffU)
+ sprintf(buf, "%lu",
+ (unsigned long)tmpui);
+ else {
+ unsigned long mid;
+ unsigned long lo;
+ unsigned long hi;
+ lo = tmpui % 1000000000;
+ tmpui /= 1000000000;
+ mid = tmpui % 1000000000;
+ hi = tmpui / 1000000000;
+ if (hi != 0)
+ sprintf(buf, "%lu", hi);
+ else
+ buf[0] = '\n';
+ sprintf(buf + strlen(buf), "%lu", mid);
+ sprintf(buf + strlen(buf), "%lu", lo);
+ }
+ goto printint;
+ case 'o':
+ if (q)
+ tmpui = va_arg(ap, isc_uint64_t);
+ else if (l)
+ tmpui = va_arg(ap, long int);
+ else
+ tmpui = va_arg(ap, int);
+ if (tmpui <= 0xffffffffU)
+ sprintf(buf, alt ? "%#lo" : "%lo",
+ (unsigned long)tmpui);
+ else {
+ unsigned long mid;
+ unsigned long lo;
+ unsigned long hi;
+ lo = tmpui % 010000000000;
+ tmpui /= 010000000000;
+ mid = tmpui % 010000000000;
+ hi = tmpui / 010000000000;
+ if (hi != 0) {
+ sprintf(buf,
+ alt ? "%#lo" : "%lo",
+ hi);
+ sprintf(buf + strlen(buf),
+ "%lo", mid);
+ } else
+ sprintf(buf,
+ alt ? "%#lo" : "%lo",
+ mid);
+ sprintf(buf + strlen(buf), "%lo", lo);
+ }
+ goto printint;
+ case 'u':
+ if (q)
+ tmpui = va_arg(ap, isc_uint64_t);
+ else if (l)
+ tmpui = va_arg(ap, unsigned long int);
+ else
+ tmpui = va_arg(ap, unsigned int);
+ if (tmpui <= 0xffffffffU)
+ sprintf(buf, "%lu",
+ (unsigned long)tmpui);
+ else {
+ unsigned long mid;
+ unsigned long lo;
+ unsigned long hi;
+ lo = tmpui % 1000000000;
+ tmpui /= 1000000000;
+ mid = tmpui % 1000000000;
+ hi = tmpui / 1000000000;
+ if (hi != 0)
+ sprintf(buf, "%lu", hi);
+ else
+ buf[0] = '\n';
+ sprintf(buf + strlen(buf), "%lu", mid);
+ sprintf(buf + strlen(buf), "%lu", lo);
+ }
+ goto printint;
+ case 'x':
+ if (q)
+ tmpui = va_arg(ap, isc_uint64_t);
+ else if (l)
+ tmpui = va_arg(ap, unsigned long int);
+ else
+ tmpui = va_arg(ap, unsigned int);
+ if (alt) {
+ head = "0x";
+ if (precision > 2)
+ precision -= 2;
+ }
+ if (tmpui <= 0xffffffffU)
+ sprintf(buf, "%lx",
+ (unsigned long)tmpui);
+ else {
+ unsigned long hi = tmpui>>32;
+ unsigned long lo = tmpui & 0xffffffff;
+ sprintf(buf, "%lx", hi);
+ sprintf(buf + strlen(buf), "%lx", lo);
+ }
+ goto printint;
+ case 'X':
+ if (q)
+ tmpui = va_arg(ap, isc_uint64_t);
+ else if (l)
+ tmpui = va_arg(ap, unsigned long int);
+ else
+ tmpui = va_arg(ap, unsigned int);
+ if (alt) {
+ head = "0X";
+ if (precision > 2)
+ precision -= 2;
+ }
+ if (tmpui <= 0xffffffffU)
+ sprintf(buf, "%lX",
+ (unsigned long)tmpui);
+ else {
+ unsigned long hi = tmpui>>32;
+ unsigned long lo = tmpui & 0xffffffff;
+ sprintf(buf, "%lX", hi);
+ sprintf(buf + strlen(buf), "%lX", lo);
+ }
+ goto printint;
+ printint:
+ if (precision != 0 || width != 0) {
+ length = strlen(buf);
+ if (length < precision)
+ zeropad = precision - length;
+ else if (length < width && zero)
+ zeropad = width - length;
+ if (width != 0) {
+ pad = width - length -
+ zeropad - strlen(head);
+ if (pad < 0)
+ pad = 0;
+ }
+ }
+ count += strlen(head) + strlen(buf) + pad +
+ zeropad;
+ if (!left) {
+ while (pad > 0 && size > 1) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ }
+ cp = head;
+ while (*cp != '\0' && size > 1) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (zeropad > 0 && size > 1) {
+ *str++ = '0';
+ size--;
+ zeropad--;
+ }
+ cp = buf;
+ while (*cp != '\0' && size > 1) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (pad > 0 && size > 1) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case 's':
+ cp = va_arg(ap, char *);
+ REQUIRE(cp != NULL);
+
+ if (precision != 0) {
+ /*
+ * cp need not be NULL terminated.
+ */
+ const char *tp;
+ unsigned long n;
+
+ n = precision;
+ tp = cp;
+ while (n != 0 && *tp != '\0')
+ n--, tp++;
+ length = precision - n;
+ } else {
+ length = strlen(cp);
+ }
+ if (width != 0) {
+ pad = width - length;
+ if (pad < 0)
+ pad = 0;
+ }
+ count += pad + length;
+ if (!left)
+ while (pad > 0 && size > 1) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ if (precision != 0)
+ while (precision > 0 && *cp != '\0' &&
+ size > 1) {
+ *str++ = *cp++;
+ size--;
+ precision--;
+ }
+ else
+ while (*cp != '\0' && size > 1) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (pad > 0 && size > 1) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ break;
+ case 'c':
+ c = va_arg(ap, int);
+ if (width > 0) {
+ count += width;
+ width--;
+ if (left) {
+ *str++ = c;
+ size--;
+ }
+ while (width-- > 0 && size > 1) {
+ *str++ = ' ';
+ size--;
+ }
+ if (!left && size > 1) {
+ *str++ = c;
+ size--;
+ }
+ } else {
+ count++;
+ if (size > 1) {
+ *str++ = c;
+ size--;
+ }
+ }
+ break;
+ case 'p':
+ v = va_arg(ap, void *);
+ sprintf(buf, "%p", v);
+ length = strlen(buf);
+ if (precision > length)
+ zeropad = precision - length;
+ if (width > 0) {
+ pad = width - length - zeropad;
+ if (pad < 0)
+ pad = 0;
+ }
+ count += length + pad + zeropad;
+ if (!left)
+ while (pad > 0 && size > 1) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ cp = buf;
+ if (zeropad > 0 && buf[0] == '0' &&
+ (buf[1] == 'x' || buf[1] == 'X')) {
+ if (size > 1) {
+ *str++ = *cp++;
+ size--;
+ }
+ if (size > 1) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (zeropad > 0 && size > 1) {
+ *str++ = '0';
+ size--;
+ zeropad--;
+ }
+ }
+ while (*cp != '\0' && size > 1) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (pad > 0 && size > 1) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ break;
+ case 'D': /*deprecated*/
+ INSIST("use %ld instead of %D" == NULL);
+ case 'O': /*deprecated*/
+ INSIST("use %lo instead of %O" == NULL);
+ case 'U': /*deprecated*/
+ INSIST("use %lu instead of %U" == NULL);
+
+ case 'L':
+#ifdef HAVE_LONG_DOUBLE
+ l = 1;
+#else
+ INSIST("long doubles are not supported" == NULL);
+#endif
+ /*FALLTHROUGH*/
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ if (!dot)
+ precision = 6;
+ /*
+ * IEEE floating point.
+ * MIN 2.2250738585072014E-308
+ * MAX 1.7976931348623157E+308
+ * VAX floating point has a smaller range than IEEE.
+ *
+ * precisions > 324 don't make much sense.
+ * if we cap the precision at 512 we will not
+ * overflow buf.
+ */
+ if (precision > 512)
+ precision = 512;
+ sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
+ plus ? "+" : space ? " " : "",
+ precision, l ? "L" : "", *format);
+ switch (*format) {
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+#ifdef HAVE_LONG_DOUBLE
+ if (l) {
+ ldbl = va_arg(ap, long double);
+ sprintf(buf, fmt, ldbl);
+ } else
+#endif
+ {
+ dbl = va_arg(ap, double);
+ sprintf(buf, fmt, dbl);
+ }
+ length = strlen(buf);
+ if (width > 0) {
+ pad = width - length;
+ if (pad < 0)
+ pad = 0;
+ }
+ count += length + pad;
+ if (!left)
+ while (pad > 0 && size > 1) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ cp = buf;
+ while (*cp != ' ' && size > 1) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (pad > 0 && size > 1) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ break;
+ default:
+ continue;
+ }
+ break;
+ default:
+ continue;
+ }
+ format++;
+ }
+ if (size > 0)
+ *str = '\0';
+ return (count);
+}
diff --git a/lib/isc/pthreads/Makefile.in b/lib/isc/pthreads/Makefile.in
new file mode 100644
index 0000000..a287457
--- /dev/null
+++ b/lib/isc/pthreads/Makefile.in
@@ -0,0 +1,38 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.19 2007/06/19 23:47:18 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+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/isc/pthreads/condition.c b/lib/isc/pthreads/condition.c
new file mode 100644
index 0000000..50281a2
--- /dev/null
+++ b/lib/isc/pthreads/condition.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: condition.c,v 1.36 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <errno.h>
+
+#include <isc/condition.h>
+#include <isc/msgs.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_condition_waituntil(isc_condition_t *c, isc_mutex_t *m, isc_time_t *t) {
+ int presult;
+ isc_result_t result;
+ struct timespec ts;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(c != NULL && m != NULL && t != NULL);
+
+ /*
+ * POSIX defines a timespec's tv_sec as time_t.
+ */
+ result = isc_time_secondsastimet(t, &ts.tv_sec);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*!
+ * POSIX defines a timespec's tv_nsec as long. isc_time_nanoseconds
+ * ensures its return value is < 1 billion, which will fit in a long.
+ */
+ ts.tv_nsec = (long)isc_time_nanoseconds(t);
+
+ do {
+#if ISC_MUTEX_PROFILE
+ presult = pthread_cond_timedwait(c, &m->mutex, &ts);
+#else
+ presult = pthread_cond_timedwait(c, m, &ts);
+#endif
+ if (presult == 0)
+ return (ISC_R_SUCCESS);
+ if (presult == ETIMEDOUT)
+ return (ISC_R_TIMEDOUT);
+ } while (presult == EINTR);
+
+ isc__strerror(presult, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "pthread_cond_timedwait() %s %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_RETURNED, "returned"),
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+}
diff --git a/lib/isc/pthreads/include/Makefile.in b/lib/isc/pthreads/include/Makefile.in
new file mode 100644
index 0000000..0303ab1
--- /dev/null
+++ b/lib/isc/pthreads/include/Makefile.in
@@ -0,0 +1,25 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.14 2007/06/19 23:47:18 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/pthreads/include/isc/Makefile.in b/lib/isc/pthreads/include/isc/Makefile.in
new file mode 100644
index 0000000..11675ec
--- /dev/null
+++ b/lib/isc/pthreads/include/isc/Makefile.in
@@ -0,0 +1,37 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.16 2007/06/19 23:47:18 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @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}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/pthreads/include/isc/condition.h b/lib/isc/pthreads/include/isc/condition.h
new file mode 100644
index 0000000..04a6118
--- /dev/null
+++ b/lib/isc/pthreads/include/isc/condition.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: condition.h,v 1.26 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_CONDITION_H
+#define ISC_CONDITION_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/result.h>
+#include <isc/types.h>
+
+typedef pthread_cond_t isc_condition_t;
+
+#define isc_condition_init(cp) \
+ ((pthread_cond_init((cp), NULL) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+#if ISC_MUTEX_PROFILE
+#define isc_condition_wait(cp, mp) \
+ ((pthread_cond_wait((cp), &((mp)->mutex)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#else
+#define isc_condition_wait(cp, mp) \
+ ((pthread_cond_wait((cp), (mp)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#endif
+
+#define isc_condition_signal(cp) \
+ ((pthread_cond_signal((cp)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+#define isc_condition_broadcast(cp) \
+ ((pthread_cond_broadcast((cp)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+#define isc_condition_destroy(cp) \
+ ((pthread_cond_destroy((cp)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_condition_waituntil(isc_condition_t *, isc_mutex_t *, isc_time_t *);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_CONDITION_H */
diff --git a/lib/isc/pthreads/include/isc/mutex.h b/lib/isc/pthreads/include/isc/mutex.h
new file mode 100644
index 0000000..dd7d326
--- /dev/null
+++ b/lib/isc/pthreads/include/isc/mutex.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: mutex.h,v 1.30 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_MUTEX_H
+#define ISC_MUTEX_H 1
+
+/*! \file */
+
+#include <pthread.h>
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/result.h> /* for ISC_R_ codes */
+
+ISC_LANG_BEGINDECLS
+
+/*!
+ * Supply mutex attributes that enable deadlock detection
+ * (helpful when debugging). This is system dependent and
+ * currently only supported on NetBSD.
+ */
+#if ISC_MUTEX_DEBUG && defined(__NetBSD__) && defined(PTHREAD_MUTEX_ERRORCHECK)
+extern pthread_mutexattr_t isc__mutex_attrs;
+#define ISC__MUTEX_ATTRS &isc__mutex_attrs
+#else
+#define ISC__MUTEX_ATTRS NULL
+#endif
+
+/* XXX We could do fancier error handling... */
+
+/*!
+ * Define ISC_MUTEX_PROFILE to turn on profiling of mutexes by line. When
+ * enabled, isc_mutex_stats() can be used to print a table showing the
+ * number of times each type of mutex was locked and the amount of time
+ * waiting to obtain the lock.
+ */
+#ifndef ISC_MUTEX_PROFILE
+#define ISC_MUTEX_PROFILE 0
+#endif
+
+#if ISC_MUTEX_PROFILE
+typedef struct isc_mutexstats isc_mutexstats_t;
+
+typedef struct {
+ pthread_mutex_t mutex; /*%< The actual mutex. */
+ isc_mutexstats_t * stats; /*%< Mutex statistics. */
+} isc_mutex_t;
+#else
+typedef pthread_mutex_t isc_mutex_t;
+#endif
+
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_init(mp) \
+ isc_mutex_init_profile((mp), __FILE__, __LINE__)
+#else
+#if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)
+#define isc_mutex_init(mp) \
+ isc_mutex_init_errcheck((mp))
+#else
+#define isc_mutex_init(mp) \
+ isc__mutex_init((mp), __FILE__, __LINE__)
+isc_result_t isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line);
+#endif
+#endif
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_lock(mp) \
+ isc_mutex_lock_profile((mp), __FILE__, __LINE__)
+#else
+#define isc_mutex_lock(mp) \
+ ((pthread_mutex_lock((mp)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#endif
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_unlock(mp) \
+ isc_mutex_unlock_profile((mp), __FILE__, __LINE__)
+#else
+#define isc_mutex_unlock(mp) \
+ ((pthread_mutex_unlock((mp)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#endif
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_trylock(mp) \
+ ((pthread_mutex_trylock((&(mp)->mutex)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_LOCKBUSY)
+#else
+#define isc_mutex_trylock(mp) \
+ ((pthread_mutex_trylock((mp)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_LOCKBUSY)
+#endif
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_destroy(mp) \
+ ((pthread_mutex_destroy((&(mp)->mutex)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#else
+#define isc_mutex_destroy(mp) \
+ ((pthread_mutex_destroy((mp)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+#endif
+
+#if ISC_MUTEX_PROFILE
+#define isc_mutex_stats(fp) isc_mutex_statsprofile(fp);
+#else
+#define isc_mutex_stats(fp)
+#endif
+
+#if ISC_MUTEX_PROFILE
+
+isc_result_t
+isc_mutex_init_profile(isc_mutex_t *mp, const char * _file, int _line);
+isc_result_t
+isc_mutex_lock_profile(isc_mutex_t *mp, const char * _file, int _line);
+isc_result_t
+isc_mutex_unlock_profile(isc_mutex_t *mp, const char * _file, int _line);
+
+void
+isc_mutex_statsprofile(FILE *fp);
+
+isc_result_t
+isc_mutex_init_errcheck(isc_mutex_t *mp);
+
+#endif /* ISC_MUTEX_PROFILE */
+
+ISC_LANG_ENDDECLS
+#endif /* ISC_MUTEX_H */
diff --git a/lib/isc/pthreads/include/isc/once.h b/lib/isc/pthreads/include/isc/once.h
new file mode 100644
index 0000000..31d76fb
--- /dev/null
+++ b/lib/isc/pthreads/include/isc/once.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: once.h,v 1.13 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_ONCE_H
+#define ISC_ONCE_H 1
+
+/*! \file */
+
+#include <pthread.h>
+
+#include <isc/platform.h>
+#include <isc/result.h>
+
+typedef pthread_once_t isc_once_t;
+
+#ifdef ISC_PLATFORM_BRACEPTHREADONCEINIT
+/*!
+ * This accomodates systems that define PTHRAD_ONCE_INIT improperly.
+ */
+#define ISC_ONCE_INIT { PTHREAD_ONCE_INIT }
+#else
+/*!
+ * This is the usual case.
+ */
+#define ISC_ONCE_INIT PTHREAD_ONCE_INIT
+#endif
+
+/* XXX We could do fancier error handling... */
+
+#define isc_once_do(op, f) \
+ ((pthread_once((op), (f)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+#endif /* ISC_ONCE_H */
diff --git a/lib/isc/pthreads/include/isc/thread.h b/lib/isc/pthreads/include/isc/thread.h
new file mode 100644
index 0000000..7dcc952
--- /dev/null
+++ b/lib/isc/pthreads/include/isc/thread.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: thread.h,v 1.26 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef ISC_THREAD_H
+#define ISC_THREAD_H 1
+
+/*! \file */
+
+#include <pthread.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef pthread_t isc_thread_t;
+typedef void * isc_threadresult_t;
+typedef void * isc_threadarg_t;
+typedef isc_threadresult_t (*isc_threadfunc_t)(isc_threadarg_t);
+typedef pthread_key_t isc_thread_key_t;
+
+isc_result_t
+isc_thread_create(isc_threadfunc_t, isc_threadarg_t, isc_thread_t *);
+
+void
+isc_thread_setconcurrency(unsigned int level);
+
+/* XXX We could do fancier error handling... */
+
+#define isc_thread_join(t, rp) \
+ ((pthread_join((t), (rp)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED)
+
+#define isc_thread_self \
+ (unsigned long)pthread_self
+
+#define isc_thread_key_create pthread_key_create
+#define isc_thread_key_getspecific pthread_getspecific
+#define isc_thread_key_setspecific pthread_setspecific
+#define isc_thread_key_delete pthread_key_delete
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_THREAD_H */
diff --git a/lib/isc/pthreads/mutex.c b/lib/isc/pthreads/mutex.c
new file mode 100644
index 0000000..b57d9ee
--- /dev/null
+++ b/lib/isc/pthreads/mutex.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: mutex.c,v 1.16 2008/04/04 23:47:01 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+
+#include <isc/mutex.h>
+#include <isc/util.h>
+#include <isc/strerror.h>
+
+#if ISC_MUTEX_PROFILE
+
+/*@{*/
+/*% Operations on timevals; adapted from FreeBSD's sys/time.h */
+#define timevalclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
+#define timevaladd(vvp, uvp) \
+ do { \
+ (vvp)->tv_sec += (uvp)->tv_sec; \
+ (vvp)->tv_usec += (uvp)->tv_usec; \
+ if ((vvp)->tv_usec >= 1000000) { \
+ (vvp)->tv_sec++; \
+ (vvp)->tv_usec -= 1000000; \
+ } \
+ } while (0)
+#define timevalsub(vvp, uvp) \
+ do { \
+ (vvp)->tv_sec -= (uvp)->tv_sec; \
+ (vvp)->tv_usec -= (uvp)->tv_usec; \
+ if ((vvp)->tv_usec < 0) { \
+ (vvp)->tv_sec--; \
+ (vvp)->tv_usec += 1000000; \
+ } \
+ } while (0)
+
+/*@}*/
+
+#define ISC_MUTEX_MAX_LOCKERS 32
+
+typedef struct {
+ const char * file;
+ int line;
+ unsigned count;
+ struct timeval locked_total;
+ struct timeval wait_total;
+} isc_mutexlocker_t;
+
+struct isc_mutexstats {
+ const char * file; /*%< File mutex was created in. */
+ int line; /*%< Line mutex was created on. */
+ unsigned count;
+ struct timeval lock_t;
+ struct timeval locked_total;
+ struct timeval wait_total;
+ isc_mutexlocker_t * cur_locker;
+ isc_mutexlocker_t lockers[ISC_MUTEX_MAX_LOCKERS];
+};
+
+#ifndef ISC_MUTEX_PROFTABLESIZE
+#define ISC_MUTEX_PROFTABLESIZE (16 * 1024)
+#endif
+static isc_mutexstats_t stats[ISC_MUTEX_PROFTABLESIZE];
+static int stats_next = 0;
+static isc_boolean_t stats_init = ISC_FALSE;
+static pthread_mutex_t statslock = PTHREAD_MUTEX_INITIALIZER;
+
+
+isc_result_t
+isc_mutex_init_profile(isc_mutex_t *mp, const char *file, int line) {
+ int i, err;
+
+ err = pthread_mutex_init(&mp->mutex, NULL);
+ if (err == ENOMEM)
+ return (ISC_R_NOMEMORY);
+ if (err != 0)
+ return (ISC_R_UNEXPECTED);
+
+ RUNTIME_CHECK(pthread_mutex_lock(&statslock) == 0);
+
+ if (stats_init == ISC_FALSE)
+ stats_init = ISC_TRUE;
+
+ /*
+ * If all statistics entries have been used, give up and trigger an
+ * assertion failure. There would be no other way to deal with this
+ * because we'd like to keep record of all locks for the purpose of
+ * debugging and the number of necessary locks is unpredictable.
+ * If this failure is triggered while debugging, named should be
+ * rebuilt with an increased ISC_MUTEX_PROFTABLESIZE.
+ */
+ RUNTIME_CHECK(stats_next < ISC_MUTEX_PROFTABLESIZE);
+ mp->stats = &stats[stats_next++];
+
+ RUNTIME_CHECK(pthread_mutex_unlock(&statslock) == 0);
+
+ mp->stats->file = file;
+ mp->stats->line = line;
+ mp->stats->count = 0;
+ timevalclear(&mp->stats->locked_total);
+ timevalclear(&mp->stats->wait_total);
+ for (i = 0; i < ISC_MUTEX_MAX_LOCKERS; i++) {
+ mp->stats->lockers[i].file = NULL;
+ mp->stats->lockers[i].line = 0;
+ mp->stats->lockers[i].count = 0;
+ timevalclear(&mp->stats->lockers[i].locked_total);
+ timevalclear(&mp->stats->lockers[i].wait_total);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_mutex_lock_profile(isc_mutex_t *mp, const char *file, int line) {
+ struct timeval prelock_t;
+ struct timeval postlock_t;
+ isc_mutexlocker_t *locker = NULL;
+ int i;
+
+ gettimeofday(&prelock_t, NULL);
+
+ if (pthread_mutex_lock(&mp->mutex) != 0)
+ return (ISC_R_UNEXPECTED);
+
+ gettimeofday(&postlock_t, NULL);
+ mp->stats->lock_t = postlock_t;
+
+ timevalsub(&postlock_t, &prelock_t);
+
+ mp->stats->count++;
+ timevaladd(&mp->stats->wait_total, &postlock_t);
+
+ for (i = 0; i < ISC_MUTEX_MAX_LOCKERS; i++) {
+ if (mp->stats->lockers[i].file == NULL) {
+ locker = &mp->stats->lockers[i];
+ locker->file = file;
+ locker->line = line;
+ break;
+ } else if (mp->stats->lockers[i].file == file &&
+ mp->stats->lockers[i].line == line) {
+ locker = &mp->stats->lockers[i];
+ break;
+ }
+ }
+
+ if (locker != NULL) {
+ locker->count++;
+ timevaladd(&locker->wait_total, &postlock_t);
+ }
+
+ mp->stats->cur_locker = locker;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_mutex_unlock_profile(isc_mutex_t *mp, const char *file, int line) {
+ struct timeval unlock_t;
+
+ UNUSED(file);
+ UNUSED(line);
+
+ if (mp->stats->cur_locker != NULL) {
+ gettimeofday(&unlock_t, NULL);
+ timevalsub(&unlock_t, &mp->stats->lock_t);
+ timevaladd(&mp->stats->locked_total, &unlock_t);
+ timevaladd(&mp->stats->cur_locker->locked_total, &unlock_t);
+ mp->stats->cur_locker = NULL;
+ }
+
+ return ((pthread_mutex_unlock((&mp->mutex)) == 0) ? \
+ ISC_R_SUCCESS : ISC_R_UNEXPECTED);
+}
+
+
+void
+isc_mutex_statsprofile(FILE *fp) {
+ isc_mutexlocker_t *locker;
+ int i, j;
+
+ fprintf(fp, "Mutex stats (in us)\n");
+ for (i = 0; i < stats_next; i++) {
+ fprintf(fp, "%-12s %4d: %10u %lu.%06lu %lu.%06lu\n",
+ stats[i].file, stats[i].line, stats[i].count,
+ stats[i].locked_total.tv_sec,
+ stats[i].locked_total.tv_usec,
+ stats[i].wait_total.tv_sec,
+ stats[i].wait_total.tv_usec
+ );
+ for (j = 0; j < ISC_MUTEX_MAX_LOCKERS; j++) {
+ locker = &stats[i].lockers[j];
+ if (locker->file == NULL)
+ continue;
+ fprintf(fp, " %-11s %4d: %10u %lu.%06lu %lu.%06lu\n",
+ locker->file, locker->line, locker->count,
+ locker->locked_total.tv_sec,
+ locker->locked_total.tv_usec,
+ locker->wait_total.tv_sec,
+ locker->wait_total.tv_usec
+ );
+ }
+ }
+}
+
+#endif /* ISC_MUTEX_PROFILE */
+
+#if ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)
+isc_result_t
+isc_mutex_init_errcheck(isc_mutex_t *mp)
+{
+ pthread_mutexattr_t attr;
+ int err;
+
+ if (pthread_mutexattr_init(&attr) != 0)
+ return (ISC_R_UNEXPECTED);
+
+ if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
+ return (ISC_R_UNEXPECTED);
+
+ err = pthread_mutex_init(mp, &attr) != 0)
+ if (err == ENOMEM)
+ return (ISC_R_NOMEMORY);
+ return ((err == 0) ? ISC_R_SUCCESS : ISC_R_UNEXPECTED);
+}
+#endif
+
+#if ISC_MUTEX_DEBUG && defined(__NetBSD__) && defined(PTHREAD_MUTEX_ERRORCHECK)
+pthread_mutexattr_t isc__mutex_attrs = {
+ PTHREAD_MUTEX_ERRORCHECK, /* m_type */
+ 0 /* m_flags, which appears to be unused. */
+};
+#endif
+
+#if !(ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)) && !ISC_MUTEX_PROFILE
+isc_result_t
+isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc_result_t result = ISC_R_SUCCESS;
+ int err;
+
+ err = pthread_mutex_init(mp, ISC__MUTEX_ATTRS);
+ if (err == ENOMEM)
+ return (ISC_R_NOMEMORY);
+ if (err != 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(file, line, "isc_mutex_init() failed: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ }
+ return (result);
+}
+#endif
diff --git a/lib/isc/pthreads/thread.c b/lib/isc/pthreads/thread.c
new file mode 100644
index 0000000..4b5b491
--- /dev/null
+++ b/lib/isc/pthreads/thread.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: thread.c,v 1.17 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/thread.h>
+#include <isc/util.h>
+
+#ifndef THREAD_MINSTACKSIZE
+#define THREAD_MINSTACKSIZE (64U * 1024)
+#endif
+
+isc_result_t
+isc_thread_create(isc_threadfunc_t func, isc_threadarg_t arg,
+ isc_thread_t *thread)
+{
+ pthread_attr_t attr;
+ size_t stacksize;
+ int ret;
+
+ pthread_attr_init(&attr);
+
+#if defined(HAVE_PTHREAD_ATTR_GETSTACKSIZE) && \
+ defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE)
+ ret = pthread_attr_getstacksize(&attr, &stacksize);
+ if (ret != 0)
+ return (ISC_R_UNEXPECTED);
+
+ if (stacksize < THREAD_MINSTACKSIZE) {
+ ret = pthread_attr_setstacksize(&attr, THREAD_MINSTACKSIZE);
+ if (ret != 0)
+ return (ISC_R_UNEXPECTED);
+ }
+#endif
+
+#if defined(PTHREAD_SCOPE_SYSTEM) && defined(NEED_PTHREAD_SCOPE_SYSTEM)
+ ret = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+ if (ret != 0)
+ return (ISC_R_UNEXPECTED);
+#endif
+
+ ret = pthread_create(thread, &attr, func, arg);
+ if (ret != 0)
+ return (ISC_R_UNEXPECTED);
+
+ pthread_attr_destroy(&attr);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_thread_setconcurrency(unsigned int level) {
+#if defined(CALL_PTHREAD_SETCONCURRENCY)
+ (void)pthread_setconcurrency(level);
+#else
+ UNUSED(level);
+#endif
+}
diff --git a/lib/isc/quota.c b/lib/isc/quota.c
new file mode 100644
index 0000000..5e5c50c
--- /dev/null
+++ b/lib/isc/quota.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: quota.c,v 1.18 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/quota.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_quota_init(isc_quota_t *quota, int max) {
+ quota->max = max;
+ quota->used = 0;
+ quota->soft = 0;
+ return (isc_mutex_init(&quota->lock));
+}
+
+void
+isc_quota_destroy(isc_quota_t *quota) {
+ INSIST(quota->used == 0);
+ quota->max = 0;
+ quota->used = 0;
+ quota->soft = 0;
+ DESTROYLOCK(&quota->lock);
+}
+
+void
+isc_quota_soft(isc_quota_t *quota, int soft) {
+ LOCK(&quota->lock);
+ quota->soft = soft;
+ UNLOCK(&quota->lock);
+}
+
+void
+isc_quota_max(isc_quota_t *quota, int max) {
+ LOCK(&quota->lock);
+ quota->max = max;
+ UNLOCK(&quota->lock);
+}
+
+isc_result_t
+isc_quota_reserve(isc_quota_t *quota) {
+ isc_result_t result;
+ LOCK(&quota->lock);
+ if (quota->max == 0 || quota->used < quota->max) {
+ if (quota->soft == 0 || quota->used < quota->soft)
+ result = ISC_R_SUCCESS;
+ else
+ result = ISC_R_SOFTQUOTA;
+ quota->used++;
+ } else
+ result = ISC_R_QUOTA;
+ UNLOCK(&quota->lock);
+ return (result);
+}
+
+void
+isc_quota_release(isc_quota_t *quota) {
+ LOCK(&quota->lock);
+ INSIST(quota->used > 0);
+ quota->used--;
+ UNLOCK(&quota->lock);
+}
+
+isc_result_t
+isc_quota_attach(isc_quota_t *quota, isc_quota_t **p)
+{
+ isc_result_t result;
+ INSIST(p != NULL && *p == NULL);
+ result = isc_quota_reserve(quota);
+ if (result == ISC_R_SUCCESS || result == ISC_R_SOFTQUOTA)
+ *p = quota;
+ return (result);
+}
+
+void
+isc_quota_detach(isc_quota_t **p)
+{
+ INSIST(p != NULL && *p != NULL);
+ isc_quota_release(*p);
+ *p = NULL;
+}
diff --git a/lib/isc/radix.c b/lib/isc/radix.c
new file mode 100644
index 0000000..c223e8a
--- /dev/null
+++ b/lib/isc/radix.c
@@ -0,0 +1,702 @@
+/*
+ * Copyright (C) 2007, 2008 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: radix.c,v 1.20 2008/10/23 00:00:58 marka Exp $ */
+
+/*
+ * This source was adapted from MRT's RCS Ids:
+ * Id: radix.c,v 1.10.2.1 1999/11/29 05:16:24 masaki Exp
+ * Id: prefix.c,v 1.37.2.9 2000/03/10 02:53:19 labovit Exp
+ */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/types.h>
+#include <isc/util.h>
+#include <isc/radix.h>
+
+static isc_result_t
+_new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family,
+ void *dest, int bitlen);
+
+static void
+_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix);
+
+static isc_result_t
+_ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix);
+
+static int
+_comp_with_mask(void *addr, void *dest, u_int mask);
+
+static void
+_clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func);
+
+static isc_result_t
+_new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
+ int bitlen)
+{
+ isc_prefix_t *prefix;
+
+ REQUIRE(target != NULL);
+
+ if (family != AF_INET6 && family != AF_INET && family != AF_UNSPEC)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ prefix = isc_mem_get(mctx, sizeof(isc_prefix_t));
+ if (prefix == NULL)
+ return (ISC_R_NOMEMORY);
+
+ if (family == AF_INET6) {
+ prefix->bitlen = (bitlen >= 0) ? bitlen : 128;
+ memcpy(&prefix->add.sin6, dest, 16);
+ } else {
+ /* AF_UNSPEC is "any" or "none"--treat it as AF_INET */
+ prefix->bitlen = (bitlen >= 0) ? bitlen : 32;
+ memcpy(&prefix->add.sin, dest, 4);
+ }
+
+ prefix->family = family;
+
+ isc_refcount_init(&prefix->refcount, 1);
+
+ *target = prefix;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix) {
+ int refs;
+
+ if (prefix == NULL)
+ return;
+
+ isc_refcount_decrement(&prefix->refcount, &refs);
+
+ if (refs <= 0) {
+ isc_refcount_destroy(&prefix->refcount);
+ isc_mem_put(mctx, prefix, sizeof(isc_prefix_t));
+ }
+}
+
+static isc_result_t
+_ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) {
+ INSIST(prefix != NULL);
+ INSIST((prefix->family == AF_INET && prefix->bitlen <= 32) ||
+ (prefix->family == AF_INET6 && prefix->bitlen <= 128) ||
+ (prefix->family == AF_UNSPEC && prefix->bitlen == 0));
+ REQUIRE(target != NULL);
+
+ /*
+ * If this prefix is a static allocation, copy it into new memory.
+ * (Note, the refcount still has to be destroyed by the calling
+ * routine.)
+ */
+ if (isc_refcount_current(&prefix->refcount) == 0) {
+ isc_result_t ret;
+ ret = _new_prefix(mctx, target, prefix->family,
+ &prefix->add, prefix->bitlen);
+ return ret;
+ }
+
+ isc_refcount_increment(&prefix->refcount, NULL);
+
+ *target = prefix;
+ return (ISC_R_SUCCESS);
+}
+
+static int
+_comp_with_mask(void *addr, void *dest, u_int mask) {
+
+ /* Mask length of zero matches everything */
+ if (mask == 0)
+ return (1);
+
+ if (memcmp(addr, dest, mask / 8) == 0) {
+ int n = mask / 8;
+ int m = ((~0) << (8 - (mask % 8)));
+
+ if ((mask % 8) == 0 ||
+ (((u_char *)addr)[n] & m) == (((u_char *)dest)[n] & m))
+ return (1);
+ }
+ return (0);
+}
+
+isc_result_t
+isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits) {
+ isc_radix_tree_t *radix;
+
+ REQUIRE(target != NULL);
+
+ radix = isc_mem_get(mctx, sizeof(isc_radix_tree_t));
+ if (radix == NULL)
+ return (ISC_R_NOMEMORY);
+
+ radix->mctx = mctx;
+ radix->maxbits = maxbits;
+ radix->head = NULL;
+ radix->num_active_node = 0;
+ radix->num_added_node = 0;
+ RUNTIME_CHECK(maxbits <= RADIX_MAXBITS); /* XXX */
+ radix->magic = RADIX_TREE_MAGIC;
+ *target = radix;
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * if func is supplied, it will be called as func(node->data)
+ * before deleting the node
+ */
+
+static void
+_clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
+
+ REQUIRE(radix != NULL);
+
+ if (radix->head != NULL) {
+
+ isc_radix_node_t *Xstack[RADIX_MAXBITS+1];
+ isc_radix_node_t **Xsp = Xstack;
+ isc_radix_node_t *Xrn = radix->head;
+
+ while (Xrn != NULL) {
+ isc_radix_node_t *l = Xrn->l;
+ isc_radix_node_t *r = Xrn->r;
+
+ if (Xrn->prefix != NULL) {
+ _deref_prefix(radix->mctx, Xrn->prefix);
+ if (func != NULL && (Xrn->data[0] != NULL ||
+ Xrn->data[1] != NULL))
+ func(Xrn->data);
+ } else {
+ INSIST(Xrn->data[0] == NULL &&
+ Xrn->data[1] == NULL);
+ }
+
+ isc_mem_put(radix->mctx, Xrn, sizeof(*Xrn));
+ radix->num_active_node--;
+
+ if (l != NULL) {
+ if (r != NULL) {
+ *Xsp++ = r;
+ }
+ Xrn = l;
+ } else if (r != NULL) {
+ Xrn = r;
+ } else if (Xsp != Xstack) {
+ Xrn = *(--Xsp);
+ } else {
+ Xrn = NULL;
+ }
+ }
+ }
+ RUNTIME_CHECK(radix->num_active_node == 0);
+}
+
+
+void
+isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func)
+{
+ REQUIRE(radix != NULL);
+ _clear_radix(radix, func);
+ isc_mem_put(radix->mctx, radix, sizeof(*radix));
+}
+
+
+/*
+ * func will be called as func(node->prefix, node->data)
+ */
+void
+isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func)
+{
+ isc_radix_node_t *node;
+
+ REQUIRE(func != NULL);
+
+ RADIX_WALK(radix->head, node) {
+ func(node->prefix, node->data);
+ } RADIX_WALK_END;
+}
+
+
+isc_result_t
+isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
+ isc_prefix_t *prefix) {
+ isc_radix_node_t *node;
+ isc_radix_node_t *stack[RADIX_MAXBITS + 1];
+ u_char *addr;
+ isc_uint32_t bitlen;
+ int tfamily = -1;
+ int cnt = 0;
+
+ REQUIRE(radix != NULL);
+ REQUIRE(prefix != NULL);
+ RUNTIME_CHECK(prefix->bitlen <= radix->maxbits);
+
+ *target = NULL;
+
+ if (radix->head == NULL) {
+ return (ISC_R_NOTFOUND);
+ }
+
+ node = radix->head;
+ addr = isc_prefix_touchar(prefix);
+ bitlen = prefix->bitlen;
+
+
+ while (node->bit < bitlen) {
+ if (node->prefix)
+ stack[cnt++] = node;
+
+ if (BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
+ node = node->r;
+ else
+ node = node->l;
+
+ if (node == NULL)
+ break;
+ }
+
+ if (node && node->prefix)
+ stack[cnt++] = node;
+
+ while (--cnt >= 0) {
+ node = stack[cnt];
+
+ if (_comp_with_mask(isc_prefix_tochar(node->prefix),
+ isc_prefix_tochar(prefix),
+ node->prefix->bitlen)) {
+ if (node->node_num[ISC_IS6(prefix->family)] != -1 &&
+ ((*target == NULL) ||
+ (*target)->node_num[ISC_IS6(tfamily)] >
+ node->node_num[ISC_IS6(prefix->family)])) {
+ *target = node;
+ tfamily = prefix->family;
+ }
+ }
+ }
+
+ if (*target == NULL) {
+ return (ISC_R_NOTFOUND);
+ } else {
+ return (ISC_R_SUCCESS);
+ }
+}
+
+isc_result_t
+isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
+ isc_radix_node_t *source, isc_prefix_t *prefix)
+{
+ isc_radix_node_t *node, *new_node, *parent, *glue = NULL;
+ u_char *addr, *test_addr;
+ isc_uint32_t bitlen, fam, check_bit, differ_bit;
+ isc_uint32_t i, j, r;
+ isc_result_t result;
+
+ REQUIRE(radix != NULL);
+ REQUIRE(prefix != NULL || (source != NULL && source->prefix != NULL));
+ RUNTIME_CHECK(prefix == NULL || prefix->bitlen <= radix->maxbits);
+
+ if (prefix == NULL)
+ prefix = source->prefix;
+
+ INSIST(prefix != NULL);
+
+ bitlen = prefix->bitlen;
+ fam = prefix->family;
+
+ if (radix->head == NULL) {
+ node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
+ if (node == NULL)
+ return (ISC_R_NOMEMORY);
+ node->bit = bitlen;
+ node->node_num[0] = node->node_num[1] = -1;
+ result = _ref_prefix(radix->mctx, &node->prefix, prefix);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(radix->mctx, node,
+ sizeof(isc_radix_node_t));
+ return (result);
+ }
+ node->parent = NULL;
+ node->l = node->r = NULL;
+ if (source != NULL) {
+ /*
+ * If source is non-NULL, then we're merging in a
+ * node from an existing radix tree. To keep
+ * the node_num values consistent, the calling
+ * function will add the total number of nodes
+ * added to num_added_node at the end of
+ * the merge operation--we don't do it here.
+ */
+ if (source->node_num[0] != -1)
+ node->node_num[0] = radix->num_added_node +
+ source->node_num[0];
+ if (source->node_num[1] != -1)
+ node->node_num[1] = radix->num_added_node +
+ source->node_num[1];
+ node->data[0] = source->data[0];
+ node->data[1] = source->data[1];
+ } else {
+ if (fam == AF_UNSPEC) {
+ /* "any" or "none" */
+ node->node_num[0] = node->node_num[1] =
+ ++radix->num_added_node;
+ } else {
+ node->node_num[ISC_IS6(fam)] =
+ ++radix->num_added_node;
+ }
+ node->data[0] = NULL;
+ node->data[1] = NULL;
+ }
+ radix->head = node;
+ radix->num_active_node++;
+ *target = node;
+ return (ISC_R_SUCCESS);
+ }
+
+ addr = isc_prefix_touchar(prefix);
+ node = radix->head;
+
+ while (node->bit < bitlen || node->prefix == NULL) {
+ if (node->bit < radix->maxbits &&
+ BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
+ {
+ if (node->r == NULL)
+ break;
+ node = node->r;
+ } else {
+ if (node->l == NULL)
+ break;
+ node = node->l;
+ }
+
+ INSIST(node != NULL);
+ }
+
+ INSIST(node->prefix != NULL);
+
+ test_addr = isc_prefix_touchar(node->prefix);
+ /* Find the first bit different. */
+ check_bit = (node->bit < bitlen) ? node->bit : bitlen;
+ differ_bit = 0;
+ for (i = 0; i*8 < check_bit; i++) {
+ if ((r = (addr[i] ^ test_addr[i])) == 0) {
+ differ_bit = (i + 1) * 8;
+ continue;
+ }
+ /* I know the better way, but for now. */
+ for (j = 0; j < 8; j++) {
+ if (BIT_TEST (r, (0x80 >> j)))
+ break;
+ }
+ /* Must be found. */
+ INSIST(j < 8);
+ differ_bit = i * 8 + j;
+ break;
+ }
+
+ if (differ_bit > check_bit)
+ differ_bit = check_bit;
+
+ parent = node->parent;
+ while (parent != NULL && parent->bit >= differ_bit) {
+ node = parent;
+ parent = node->parent;
+ }
+
+ if (differ_bit == bitlen && node->bit == bitlen) {
+ if (node->prefix != NULL) {
+ /* Set node_num only if it hasn't been set before */
+ if (source != NULL) {
+ /* Merging node */
+ if (node->node_num[0] == -1 &&
+ source->node_num[0] != -1) {
+ node->node_num[0] =
+ radix->num_added_node +
+ source->node_num[0];
+ node->data[0] = source->data[0];
+ }
+ if (node->node_num[1] == -1 &&
+ source->node_num[0] != -1) {
+ node->node_num[1] =
+ radix->num_added_node +
+ source->node_num[1];
+ node->data[1] = source->data[1];
+ }
+ } else {
+ if (fam == AF_UNSPEC) {
+ /* "any" or "none" */
+ int next = radix->num_added_node + 1;
+ if (node->node_num[0] == -1) {
+ node->node_num[0] = next;
+ radix->num_added_node = next;
+ }
+ if (node->node_num[1] == -1) {
+ node->node_num[1] = next;
+ radix->num_added_node = next;
+ }
+ } else {
+ if (node->node_num[ISC_IS6(fam)] == -1)
+ node->node_num[ISC_IS6(fam)]
+ = ++radix->num_added_node;
+ }
+ }
+ *target = node;
+ return (ISC_R_SUCCESS);
+ } else {
+ result =
+ _ref_prefix(radix->mctx, &node->prefix, prefix);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ INSIST(node->data[0] == NULL && node->node_num[0] == -1 &&
+ node->data[1] == NULL && node->node_num[1] == -1);
+ if (source != NULL) {
+ /* Merging node */
+ if (source->node_num[0] != -1) {
+ node->node_num[0] = radix->num_added_node +
+ source->node_num[0];
+ node->data[0] = source->data[0];
+ }
+ if (source->node_num[1] != -1) {
+ node->node_num[1] = radix->num_added_node +
+ source->node_num[1];
+ node->data[1] = source->data[1];
+ }
+ } else {
+ if (fam == AF_UNSPEC) {
+ /* "any" or "none" */
+ node->node_num[0] = node->node_num[1] =
+ ++radix->num_added_node;
+ } else {
+ node->node_num[ISC_IS6(fam)] =
+ ++radix->num_added_node;
+ }
+ }
+ *target = node;
+ return (ISC_R_SUCCESS);
+ }
+
+ new_node = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
+ if (new_node == NULL)
+ return (ISC_R_NOMEMORY);
+ if (node->bit != differ_bit && bitlen != differ_bit) {
+ glue = isc_mem_get(radix->mctx, sizeof(isc_radix_node_t));
+ if (glue == NULL) {
+ isc_mem_put(radix->mctx, new_node,
+ sizeof(isc_radix_node_t));
+ return (ISC_R_NOMEMORY);
+ }
+ }
+ new_node->bit = bitlen;
+ result = _ref_prefix(radix->mctx, &new_node->prefix, prefix);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(radix->mctx, new_node, sizeof(isc_radix_node_t));
+ if (glue != NULL)
+ isc_mem_put(radix->mctx, glue,
+ sizeof(isc_radix_node_t));
+ return (result);
+ }
+ new_node->parent = NULL;
+ new_node->l = new_node->r = NULL;
+ new_node->node_num[0] = new_node->node_num[1] = -1;
+ radix->num_active_node++;
+
+ if (source != NULL) {
+ /* Merging node */
+ if (source->node_num[0] != -1)
+ new_node->node_num[0] = radix->num_added_node +
+ source->node_num[0];
+ if (source->node_num[1] != -1)
+ new_node->node_num[1] = radix->num_added_node +
+ source->node_num[1];
+ new_node->data[0] = source->data[0];
+ new_node->data[1] = source->data[1];
+ } else {
+ if (fam == AF_UNSPEC) {
+ /* "any" or "none" */
+ new_node->node_num[0] = new_node->node_num[1] =
+ ++radix->num_added_node;
+ } else {
+ new_node->node_num[ISC_IS6(fam)] =
+ ++radix->num_added_node;
+ }
+ new_node->data[0] = NULL;
+ new_node->data[1] = NULL;
+ }
+
+ if (node->bit == differ_bit) {
+ INSIST(glue == NULL);
+ new_node->parent = node;
+ if (node->bit < radix->maxbits &&
+ BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
+ {
+ INSIST(node->r == NULL);
+ node->r = new_node;
+ } else {
+ INSIST(node->l == NULL);
+ node->l = new_node;
+ }
+ *target = new_node;
+ return (ISC_R_SUCCESS);
+ }
+
+ if (bitlen == differ_bit) {
+ INSIST(glue == NULL);
+ if (bitlen < radix->maxbits &&
+ BIT_TEST(test_addr[bitlen >> 3], 0x80 >> (bitlen & 0x07))) {
+ new_node->r = node;
+ } else {
+ new_node->l = node;
+ }
+ new_node->parent = node->parent;
+ if (node->parent == NULL) {
+ INSIST(radix->head == node);
+ radix->head = new_node;
+ } else if (node->parent->r == node) {
+ node->parent->r = new_node;
+ } else {
+ node->parent->l = new_node;
+ }
+ node->parent = new_node;
+ } else {
+ INSIST(glue != NULL);
+ glue->bit = differ_bit;
+ glue->prefix = NULL;
+ glue->parent = node->parent;
+ glue->data[0] = glue->data[1] = NULL;
+ glue->node_num[0] = glue->node_num[1] = -1;
+ radix->num_active_node++;
+ if (differ_bit < radix->maxbits &&
+ BIT_TEST(addr[differ_bit>>3], 0x80 >> (differ_bit & 07))) {
+ glue->r = new_node;
+ glue->l = node;
+ } else {
+ glue->r = node;
+ glue->l = new_node;
+ }
+ new_node->parent = glue;
+
+ if (node->parent == NULL) {
+ INSIST(radix->head == node);
+ radix->head = glue;
+ } else if (node->parent->r == node) {
+ node->parent->r = glue;
+ } else {
+ node->parent->l = glue;
+ }
+ node->parent = glue;
+ }
+
+ *target = new_node;
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
+ isc_radix_node_t *parent, *child;
+
+ REQUIRE(radix != NULL);
+ REQUIRE(node != NULL);
+
+ if (node->r && node->l) {
+ /*
+ * This might be a placeholder node -- have to check and
+ * make sure there is a prefix aossciated with it!
+ */
+ if (node->prefix != NULL)
+ _deref_prefix(radix->mctx, node->prefix);
+
+ node->prefix = NULL;
+ node->data[0] = node->data[1] = NULL;
+ return;
+ }
+
+ if (node->r == NULL && node->l == NULL) {
+ parent = node->parent;
+ _deref_prefix(radix->mctx, node->prefix);
+ isc_mem_put(radix->mctx, node, sizeof(*node));
+ radix->num_active_node--;
+
+ if (parent == NULL) {
+ INSIST(radix->head == node);
+ radix->head = NULL;
+ return;
+ }
+
+ if (parent->r == node) {
+ parent->r = NULL;
+ child = parent->l;
+ } else {
+ INSIST(parent->l == node);
+ parent->l = NULL;
+ child = parent->r;
+ }
+
+ if (parent->prefix)
+ return;
+
+ /* We need to remove parent too. */
+
+ if (parent->parent == NULL) {
+ INSIST(radix->head == parent);
+ radix->head = child;
+ } else if (parent->parent->r == parent) {
+ parent->parent->r = child;
+ } else {
+ INSIST(parent->parent->l == parent);
+ parent->parent->l = child;
+ }
+ child->parent = parent->parent;
+ isc_mem_put(radix->mctx, parent, sizeof(*parent));
+ radix->num_active_node--;
+ return;
+ }
+
+ if (node->r) {
+ child = node->r;
+ } else {
+ INSIST(node->l != NULL);
+ child = node->l;
+ }
+ parent = node->parent;
+ child->parent = parent;
+
+ _deref_prefix(radix->mctx, node->prefix);
+ isc_mem_put(radix->mctx, node, sizeof(*node));
+ radix->num_active_node--;
+
+ if (parent == NULL) {
+ INSIST(radix->head == node);
+ radix->head = child;
+ return;
+ }
+
+ if (parent->r == node) {
+ parent->r = child;
+ } else {
+ INSIST(parent->l == node);
+ parent->l = child;
+ }
+}
+
+/*
+Local Variables:
+c-basic-offset: 4
+indent-tabs-mode: t
+End:
+*/
diff --git a/lib/isc/random.c b/lib/isc/random.c
new file mode 100644
index 0000000..0329abd
--- /dev/null
+++ b/lib/isc/random.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: random.c,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <time.h> /* Required for time(). */
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/random.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+static isc_once_t once = ISC_ONCE_INIT;
+
+static void
+initialize_rand(void)
+{
+#ifndef HAVE_ARC4RANDOM
+ unsigned int pid = getpid();
+
+ /*
+ * The low bits of pid generally change faster.
+ * Xor them with the high bits of time which change slowly.
+ */
+ pid = ((pid << 16) & 0xffff0000) | ((pid >> 16) & 0xffff);
+
+ srand(time(NULL) ^ pid);
+#endif
+}
+
+static void
+initialize(void)
+{
+ RUNTIME_CHECK(isc_once_do(&once, initialize_rand) == ISC_R_SUCCESS);
+}
+
+void
+isc_random_seed(isc_uint32_t seed)
+{
+ initialize();
+
+#ifndef HAVE_ARC4RANDOM
+ srand(seed);
+#else
+ arc4random_addrandom((u_char *) &seed, sizeof(isc_uint32_t));
+#endif
+}
+
+void
+isc_random_get(isc_uint32_t *val)
+{
+ REQUIRE(val != NULL);
+
+ initialize();
+
+#ifndef HAVE_ARC4RANDOM
+ /*
+ * rand()'s lower bits are not random.
+ * rand()'s upper bit is zero.
+ */
+ *val = ((rand() >> 4) & 0xffff) | ((rand() << 12) & 0xffff0000);
+#else
+ *val = arc4random();
+#endif
+}
+
+isc_uint32_t
+isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter) {
+ REQUIRE(jitter < max);
+ if (jitter == 0)
+ return (max);
+ else
+#ifndef HAVE_ARC4RANDOM
+ return (max - rand() % jitter);
+#else
+ return (max - arc4random() % jitter);
+#endif
+}
diff --git a/lib/isc/ratelimiter.c b/lib/isc/ratelimiter.c
new file mode 100644
index 0000000..07bcc7c
--- /dev/null
+++ b/lib/isc/ratelimiter.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: ratelimiter.c,v 1.25 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/ratelimiter.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+typedef enum {
+ isc_ratelimiter_stalled = 0,
+ isc_ratelimiter_ratelimited = 1,
+ isc_ratelimiter_idle = 2,
+ isc_ratelimiter_shuttingdown = 3
+} isc_ratelimiter_state_t;
+
+struct isc_ratelimiter {
+ isc_mem_t * mctx;
+ isc_mutex_t lock;
+ int refs;
+ isc_task_t * task;
+ isc_timer_t * timer;
+ isc_interval_t interval;
+ isc_uint32_t pertic;
+ isc_ratelimiter_state_t state;
+ isc_event_t shutdownevent;
+ ISC_LIST(isc_event_t) pending;
+};
+
+#define ISC_RATELIMITEREVENT_SHUTDOWN (ISC_EVENTCLASS_RATELIMITER + 1)
+
+static void
+ratelimiter_tick(isc_task_t *task, isc_event_t *event);
+
+static void
+ratelimiter_shutdowncomplete(isc_task_t *task, isc_event_t *event);
+
+isc_result_t
+isc_ratelimiter_create(isc_mem_t *mctx, isc_timermgr_t *timermgr,
+ isc_task_t *task, isc_ratelimiter_t **ratelimiterp)
+{
+ isc_result_t result;
+ isc_ratelimiter_t *rl;
+ INSIST(ratelimiterp != NULL && *ratelimiterp == NULL);
+
+ rl = isc_mem_get(mctx, sizeof(*rl));
+ if (rl == NULL)
+ return ISC_R_NOMEMORY;
+ rl->mctx = mctx;
+ rl->refs = 1;
+ rl->task = task;
+ isc_interval_set(&rl->interval, 0, 0);
+ rl->timer = NULL;
+ rl->pertic = 1;
+ rl->state = isc_ratelimiter_idle;
+ ISC_LIST_INIT(rl->pending);
+
+ result = isc_mutex_init(&rl->lock);
+ if (result != ISC_R_SUCCESS)
+ goto free_mem;
+ result = isc_timer_create(timermgr, isc_timertype_inactive,
+ NULL, NULL, rl->task, ratelimiter_tick,
+ rl, &rl->timer);
+ if (result != ISC_R_SUCCESS)
+ goto free_mutex;
+
+ /*
+ * Increment the reference count to indicate that we may
+ * (soon) have events outstanding.
+ */
+ rl->refs++;
+
+ ISC_EVENT_INIT(&rl->shutdownevent,
+ sizeof(isc_event_t),
+ 0, NULL, ISC_RATELIMITEREVENT_SHUTDOWN,
+ ratelimiter_shutdowncomplete, rl, rl, NULL, NULL);
+
+ *ratelimiterp = rl;
+ return (ISC_R_SUCCESS);
+
+free_mutex:
+ DESTROYLOCK(&rl->lock);
+free_mem:
+ isc_mem_put(mctx, rl, sizeof(*rl));
+ return (result);
+}
+
+isc_result_t
+isc_ratelimiter_setinterval(isc_ratelimiter_t *rl, isc_interval_t *interval) {
+ isc_result_t result = ISC_R_SUCCESS;
+ LOCK(&rl->lock);
+ rl->interval = *interval;
+ /*
+ * If the timer is currently running, change its rate.
+ */
+ if (rl->state == isc_ratelimiter_ratelimited) {
+ result = isc_timer_reset(rl->timer, isc_timertype_ticker, NULL,
+ &rl->interval, ISC_FALSE);
+ }
+ UNLOCK(&rl->lock);
+ return (result);
+}
+
+void
+isc_ratelimiter_setpertic(isc_ratelimiter_t *rl, isc_uint32_t pertic) {
+ if (pertic == 0)
+ pertic = 1;
+ rl->pertic = pertic;
+}
+
+isc_result_t
+isc_ratelimiter_enqueue(isc_ratelimiter_t *rl, isc_task_t *task,
+ isc_event_t **eventp)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_event_t *ev;
+
+ REQUIRE(eventp != NULL && *eventp != NULL);
+ REQUIRE(task != NULL);
+ ev = *eventp;
+ REQUIRE(ev->ev_sender == NULL);
+
+ LOCK(&rl->lock);
+ if (rl->state == isc_ratelimiter_ratelimited ||
+ rl->state == isc_ratelimiter_stalled) {
+ isc_event_t *ev = *eventp;
+ ev->ev_sender = task;
+ ISC_LIST_APPEND(rl->pending, ev, ev_link);
+ *eventp = NULL;
+ } else if (rl->state == isc_ratelimiter_idle) {
+ result = isc_timer_reset(rl->timer, isc_timertype_ticker, NULL,
+ &rl->interval, ISC_FALSE);
+ if (result == ISC_R_SUCCESS) {
+ ev->ev_sender = task;
+ rl->state = isc_ratelimiter_ratelimited;
+ }
+ } else {
+ INSIST(rl->state == isc_ratelimiter_shuttingdown);
+ result = ISC_R_SHUTTINGDOWN;
+ }
+ UNLOCK(&rl->lock);
+ if (*eventp != NULL && result == ISC_R_SUCCESS)
+ isc_task_send(task, eventp);
+ return (result);
+}
+
+static void
+ratelimiter_tick(isc_task_t *task, isc_event_t *event) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_ratelimiter_t *rl = (isc_ratelimiter_t *)event->ev_arg;
+ isc_event_t *p;
+ isc_uint32_t pertic;
+
+ UNUSED(task);
+
+ isc_event_free(&event);
+
+ pertic = rl->pertic;
+ while (pertic != 0) {
+ pertic--;
+ LOCK(&rl->lock);
+ p = ISC_LIST_HEAD(rl->pending);
+ if (p != NULL) {
+ /*
+ * There is work to do. Let's do it after unlocking.
+ */
+ ISC_LIST_UNLINK(rl->pending, p, ev_link);
+ } else {
+ /*
+ * No work left to do. Stop the timer so that we don't
+ * waste resources by having it fire periodically.
+ */
+ result = isc_timer_reset(rl->timer,
+ isc_timertype_inactive,
+ NULL, NULL, ISC_FALSE);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ rl->state = isc_ratelimiter_idle;
+ pertic = 0; /* Force the loop to exit. */
+ }
+ UNLOCK(&rl->lock);
+ if (p != NULL) {
+ isc_task_t *evtask = p->ev_sender;
+ isc_task_send(evtask, &p);
+ }
+ INSIST(p == NULL);
+ }
+}
+
+void
+isc_ratelimiter_shutdown(isc_ratelimiter_t *rl) {
+ isc_event_t *ev;
+ isc_task_t *task;
+ LOCK(&rl->lock);
+ rl->state = isc_ratelimiter_shuttingdown;
+ (void)isc_timer_reset(rl->timer, isc_timertype_inactive,
+ NULL, NULL, ISC_FALSE);
+ while ((ev = ISC_LIST_HEAD(rl->pending)) != NULL) {
+ ISC_LIST_UNLINK(rl->pending, ev, ev_link);
+ ev->ev_attributes |= ISC_EVENTATTR_CANCELED;
+ task = ev->ev_sender;
+ isc_task_send(task, &ev);
+ }
+ isc_timer_detach(&rl->timer);
+ /*
+ * Send an event to our task. The delivery of this event
+ * indicates that no more timer events will be delivered.
+ */
+ ev = &rl->shutdownevent;
+ isc_task_send(rl->task, &ev);
+
+ UNLOCK(&rl->lock);
+}
+
+static void
+ratelimiter_shutdowncomplete(isc_task_t *task, isc_event_t *event) {
+ isc_ratelimiter_t *rl = (isc_ratelimiter_t *)event->ev_arg;
+
+ UNUSED(task);
+
+ isc_ratelimiter_detach(&rl);
+}
+
+static void
+ratelimiter_free(isc_ratelimiter_t *rl) {
+ DESTROYLOCK(&rl->lock);
+ isc_mem_put(rl->mctx, rl, sizeof(*rl));
+}
+
+void
+isc_ratelimiter_attach(isc_ratelimiter_t *source, isc_ratelimiter_t **target) {
+ REQUIRE(source != NULL);
+ REQUIRE(target != NULL && *target == NULL);
+
+ LOCK(&source->lock);
+ REQUIRE(source->refs > 0);
+ source->refs++;
+ INSIST(source->refs > 0);
+ UNLOCK(&source->lock);
+ *target = source;
+}
+
+void
+isc_ratelimiter_detach(isc_ratelimiter_t **rlp) {
+ isc_ratelimiter_t *rl = *rlp;
+ isc_boolean_t free_now = ISC_FALSE;
+
+ LOCK(&rl->lock);
+ REQUIRE(rl->refs > 0);
+ rl->refs--;
+ if (rl->refs == 0)
+ free_now = ISC_TRUE;
+ UNLOCK(&rl->lock);
+
+ if (free_now)
+ ratelimiter_free(rl);
+
+ *rlp = NULL;
+}
+
+isc_result_t
+isc_ratelimiter_stall(isc_ratelimiter_t *rl) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ LOCK(&rl->lock);
+ switch (rl->state) {
+ case isc_ratelimiter_shuttingdown:
+ result = ISC_R_SHUTTINGDOWN;
+ break;
+ case isc_ratelimiter_ratelimited:
+ result = isc_timer_reset(rl->timer, isc_timertype_inactive,
+ NULL, NULL, ISC_FALSE);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ case isc_ratelimiter_idle:
+ case isc_ratelimiter_stalled:
+ rl->state = isc_ratelimiter_stalled;
+ break;
+ }
+ UNLOCK(&rl->lock);
+ return (result);
+}
+
+isc_result_t
+isc_ratelimiter_release(isc_ratelimiter_t *rl) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ LOCK(&rl->lock);
+ switch (rl->state) {
+ case isc_ratelimiter_shuttingdown:
+ result = ISC_R_SHUTTINGDOWN;
+ break;
+ case isc_ratelimiter_stalled:
+ if (!ISC_LIST_EMPTY(rl->pending)) {
+ result = isc_timer_reset(rl->timer,
+ isc_timertype_ticker, NULL,
+ &rl->interval, ISC_FALSE);
+ if (result == ISC_R_SUCCESS)
+ rl->state = isc_ratelimiter_ratelimited;
+ } else
+ rl->state = isc_ratelimiter_idle;
+ break;
+ case isc_ratelimiter_ratelimited:
+ case isc_ratelimiter_idle:
+ break;
+ }
+ UNLOCK(&rl->lock);
+ return (result);
+}
diff --git a/lib/isc/refcount.c b/lib/isc/refcount.c
new file mode 100644
index 0000000..36dfff2
--- /dev/null
+++ b/lib/isc/refcount.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2005, 2007 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: refcount.c,v 1.5 2007/06/19 23:47:17 tbox Exp $ */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/mutex.h>
+#include <isc/refcount.h>
+#include <isc/result.h>
+
+isc_result_t
+isc_refcount_init(isc_refcount_t *ref, unsigned int n) {
+ REQUIRE(ref != NULL);
+
+ ref->refs = n;
+#if defined(ISC_PLATFORM_USETHREADS) && !defined(ISC_PLATFORM_HAVEXADD)
+ return (isc_mutex_init(&ref->lock));
+#else
+ return (ISC_R_SUCCESS);
+#endif
+}
diff --git a/lib/isc/region.c b/lib/isc/region.c
new file mode 100644
index 0000000..cf64979
--- /dev/null
+++ b/lib/isc/region.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: region.c,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/region.h>
+#include <isc/util.h>
+
+int
+isc_region_compare(isc_region_t *r1, isc_region_t *r2) {
+ unsigned int l;
+ int result;
+
+ REQUIRE(r1 != NULL);
+ REQUIRE(r2 != NULL);
+
+ l = (r1->length < r2->length) ? r1->length : r2->length;
+
+ if ((result = memcmp(r1->base, r2->base, l)) != 0)
+ return ((result < 0) ? -1 : 1);
+ else
+ return ((r1->length == r2->length) ? 0 :
+ (r1->length < r2->length) ? -1 : 1);
+}
diff --git a/lib/isc/result.c b/lib/isc/result.c
new file mode 100644
index 0000000..5713580
--- /dev/null
+++ b/lib/isc/result.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 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
+ * 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: result.c,v 1.71 2008/09/25 04:02:39 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include <isc/lib.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/resultclass.h>
+#include <isc/util.h>
+
+typedef struct resulttable {
+ unsigned int base;
+ unsigned int last;
+ const char ** text;
+ isc_msgcat_t * msgcat;
+ int set;
+ ISC_LINK(struct resulttable) link;
+} resulttable;
+
+static const char *text[ISC_R_NRESULTS] = {
+ "success", /*%< 0 */
+ "out of memory", /*%< 1 */
+ "timed out", /*%< 2 */
+ "no available threads", /*%< 3 */
+ "address not available", /*%< 4 */
+ "address in use", /*%< 5 */
+ "permission denied", /*%< 6 */
+ "no pending connections", /*%< 7 */
+ "network unreachable", /*%< 8 */
+ "host unreachable", /*%< 9 */
+ "network down", /*%< 10 */
+ "host down", /*%< 11 */
+ "connection refused", /*%< 12 */
+ "not enough free resources", /*%< 13 */
+ "end of file", /*%< 14 */
+ "socket already bound", /*%< 15 */
+ "reload", /*%< 16 */
+ "lock busy", /*%< 17 */
+ "already exists", /*%< 18 */
+ "ran out of space", /*%< 19 */
+ "operation canceled", /*%< 20 */
+ "socket is not bound", /*%< 21 */
+ "shutting down", /*%< 22 */
+ "not found", /*%< 23 */
+ "unexpected end of input", /*%< 24 */
+ "failure", /*%< 25 */
+ "I/O error", /*%< 26 */
+ "not implemented", /*%< 27 */
+ "unbalanced parentheses", /*%< 28 */
+ "no more", /*%< 29 */
+ "invalid file", /*%< 30 */
+ "bad base64 encoding", /*%< 31 */
+ "unexpected token", /*%< 32 */
+ "quota reached", /*%< 33 */
+ "unexpected error", /*%< 34 */
+ "already running", /*%< 35 */
+ "ignore", /*%< 36 */
+ "address mask not contiguous", /*%< 37 */
+ "file not found", /*%< 38 */
+ "file already exists", /*%< 39 */
+ "socket is not connected", /*%< 40 */
+ "out of range", /*%< 41 */
+ "out of entropy", /*%< 42 */
+ "invalid use of multicast address", /*%< 43 */
+ "not a file", /*%< 44 */
+ "not a directory", /*%< 45 */
+ "queue is full", /*%< 46 */
+ "address family mismatch", /*%< 47 */
+ "address family not supported", /*%< 48 */
+ "bad hex encoding", /*%< 49 */
+ "too many open files", /*%< 50 */
+ "not blocking", /*%< 51 */
+ "unbalanced quotes", /*%< 52 */
+ "operation in progress", /*%< 53 */
+ "connection reset", /*%< 54 */
+ "soft quota reached", /*%< 55 */
+ "not a valid number", /*%< 56 */
+ "disabled", /*%< 57 */
+ "max size", /*%< 58 */
+ "invalid address format", /*%< 59 */
+ "bad base32 encoding", /*%< 60 */
+};
+
+#define ISC_RESULT_RESULTSET 2
+#define ISC_RESULT_UNAVAILABLESET 3
+
+static isc_once_t once = ISC_ONCE_INIT;
+static ISC_LIST(resulttable) tables;
+static isc_mutex_t lock;
+
+static isc_result_t
+register_table(unsigned int base, unsigned int nresults, const char **text,
+ isc_msgcat_t *msgcat, int set)
+{
+ resulttable *table;
+
+ REQUIRE(base % ISC_RESULTCLASS_SIZE == 0);
+ REQUIRE(nresults <= ISC_RESULTCLASS_SIZE);
+ REQUIRE(text != NULL);
+
+ /*
+ * We use malloc() here because we we want to be able to use
+ * isc_result_totext() even if there is no memory context.
+ */
+ table = malloc(sizeof(*table));
+ if (table == NULL)
+ return (ISC_R_NOMEMORY);
+ table->base = base;
+ table->last = base + nresults - 1;
+ table->text = text;
+ table->msgcat = msgcat;
+ table->set = set;
+ ISC_LINK_INIT(table, link);
+
+ LOCK(&lock);
+
+ ISC_LIST_APPEND(tables, table, link);
+
+ UNLOCK(&lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+initialize_action(void) {
+ isc_result_t result;
+
+ RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
+ ISC_LIST_INIT(tables);
+
+ result = register_table(ISC_RESULTCLASS_ISC, ISC_R_NRESULTS, text,
+ isc_msgcat, ISC_RESULT_RESULTSET);
+ if (result != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "register_table() %s: %u",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ result);
+}
+
+static void
+initialize(void) {
+ isc_lib_initmsgcat();
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+}
+
+const char *
+isc_result_totext(isc_result_t result) {
+ resulttable *table;
+ const char *text, *default_text;
+ int index;
+
+ initialize();
+
+ LOCK(&lock);
+
+ text = NULL;
+ for (table = ISC_LIST_HEAD(tables);
+ table != NULL;
+ table = ISC_LIST_NEXT(table, link)) {
+ if (result >= table->base && result <= table->last) {
+ index = (int)(result - table->base);
+ default_text = table->text[index];
+ /*
+ * Note: we use 'index + 1' as the message number
+ * instead of index because isc_msgcat_get() requires
+ * the message number to be > 0.
+ */
+ text = isc_msgcat_get(table->msgcat, table->set,
+ index + 1, default_text);
+ break;
+ }
+ }
+ if (text == NULL)
+ text = isc_msgcat_get(isc_msgcat, ISC_RESULT_UNAVAILABLESET,
+ 1, "(result code text not available)");
+
+ UNLOCK(&lock);
+
+ return (text);
+}
+
+isc_result_t
+isc_result_register(unsigned int base, unsigned int nresults,
+ const char **text, isc_msgcat_t *msgcat, int set)
+{
+ initialize();
+
+ return (register_table(base, nresults, text, msgcat, set));
+}
diff --git a/lib/isc/rwlock.c b/lib/isc/rwlock.c
new file mode 100644
index 0000000..69bb77f
--- /dev/null
+++ b/lib/isc/rwlock.c
@@ -0,0 +1,808 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: rwlock.c,v 1.44 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/atomic.h>
+#include <isc/magic.h>
+#include <isc/msgs.h>
+#include <isc/platform.h>
+#include <isc/rwlock.h>
+#include <isc/util.h>
+
+#define RWLOCK_MAGIC ISC_MAGIC('R', 'W', 'L', 'k')
+#define VALID_RWLOCK(rwl) ISC_MAGIC_VALID(rwl, RWLOCK_MAGIC)
+
+#ifdef ISC_PLATFORM_USETHREADS
+
+#ifndef RWLOCK_DEFAULT_READ_QUOTA
+#define RWLOCK_DEFAULT_READ_QUOTA 4
+#endif
+
+#ifndef RWLOCK_DEFAULT_WRITE_QUOTA
+#define RWLOCK_DEFAULT_WRITE_QUOTA 4
+#endif
+
+#ifdef ISC_RWLOCK_TRACE
+#include <stdio.h> /* Required for fprintf/stderr. */
+#include <isc/thread.h> /* Requried for isc_thread_self(). */
+
+static void
+print_lock(const char *operation, isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+ fprintf(stderr,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_PRINTLOCK,
+ "rwlock %p thread %lu %s(%s): %s, %u active, "
+ "%u granted, %u rwaiting, %u wwaiting\n"),
+ rwl, isc_thread_self(), operation,
+ (type == isc_rwlocktype_read ?
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_READ, "read") :
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_WRITE, "write")),
+ (rwl->type == isc_rwlocktype_read ?
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_READING, "reading") :
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_WRITING, "writing")),
+ rwl->active, rwl->granted, rwl->readers_waiting,
+ rwl->writers_waiting);
+}
+#endif
+
+isc_result_t
+isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
+ unsigned int write_quota)
+{
+ isc_result_t result;
+
+ REQUIRE(rwl != NULL);
+
+ /*
+ * In case there's trouble initializing, we zero magic now. If all
+ * goes well, we'll set it to RWLOCK_MAGIC.
+ */
+ rwl->magic = 0;
+
+#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
+ rwl->write_requests = 0;
+ rwl->write_completions = 0;
+ rwl->cnt_and_flag = 0;
+ rwl->readers_waiting = 0;
+ rwl->write_granted = 0;
+ if (read_quota != 0) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "read quota is not supported");
+ }
+ if (write_quota == 0)
+ write_quota = RWLOCK_DEFAULT_WRITE_QUOTA;
+ rwl->write_quota = write_quota;
+#else
+ rwl->type = isc_rwlocktype_read;
+ rwl->original = isc_rwlocktype_none;
+ rwl->active = 0;
+ rwl->granted = 0;
+ rwl->readers_waiting = 0;
+ rwl->writers_waiting = 0;
+ if (read_quota == 0)
+ read_quota = RWLOCK_DEFAULT_READ_QUOTA;
+ rwl->read_quota = read_quota;
+ if (write_quota == 0)
+ write_quota = RWLOCK_DEFAULT_WRITE_QUOTA;
+ rwl->write_quota = write_quota;
+#endif
+
+ result = isc_mutex_init(&rwl->lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ result = isc_condition_init(&rwl->readable);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_condition_init(readable) %s: %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ goto destroy_lock;
+ }
+ result = isc_condition_init(&rwl->writeable);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_condition_init(writeable) %s: %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ isc_result_totext(result));
+ result = ISC_R_UNEXPECTED;
+ goto destroy_rcond;
+ }
+
+ rwl->magic = RWLOCK_MAGIC;
+
+ return (ISC_R_SUCCESS);
+
+ destroy_rcond:
+ (void)isc_condition_destroy(&rwl->readable);
+ destroy_lock:
+ DESTROYLOCK(&rwl->lock);
+
+ return (result);
+}
+
+void
+isc_rwlock_destroy(isc_rwlock_t *rwl) {
+ REQUIRE(VALID_RWLOCK(rwl));
+
+#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
+ REQUIRE(rwl->write_requests == rwl->write_completions &&
+ rwl->cnt_and_flag == 0 && rwl->readers_waiting == 0);
+#else
+ LOCK(&rwl->lock);
+ REQUIRE(rwl->active == 0 &&
+ rwl->readers_waiting == 0 &&
+ rwl->writers_waiting == 0);
+ UNLOCK(&rwl->lock);
+#endif
+
+ rwl->magic = 0;
+ (void)isc_condition_destroy(&rwl->readable);
+ (void)isc_condition_destroy(&rwl->writeable);
+ DESTROYLOCK(&rwl->lock);
+}
+
+#if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
+
+/*
+ * When some architecture-dependent atomic operations are available,
+ * rwlock can be more efficient than the generic algorithm defined below.
+ * The basic algorithm is described in the following URL:
+ * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/rw.html
+ *
+ * The key is to use the following integer variables modified atomically:
+ * write_requests, write_completions, and cnt_and_flag.
+ *
+ * write_requests and write_completions act as a waiting queue for writers
+ * in order to ensure the FIFO order. Both variables begin with the initial
+ * value of 0. When a new writer tries to get a write lock, it increments
+ * write_requests and gets the previous value of the variable as a "ticket".
+ * When write_completions reaches the ticket number, the new writer can start
+ * writing. When the writer completes its work, it increments
+ * write_completions so that another new writer can start working. If the
+ * write_requests is not equal to write_completions, it means a writer is now
+ * working or waiting. In this case, a new readers cannot start reading, or
+ * in other words, this algorithm basically prefers writers.
+ *
+ * cnt_and_flag is a "lock" shared by all readers and writers. This integer
+ * variable is a kind of structure with two members: writer_flag (1 bit) and
+ * reader_count (31 bits). The writer_flag shows whether a writer is working,
+ * and the reader_count shows the number of readers currently working or almost
+ * ready for working. A writer who has the current "ticket" tries to get the
+ * lock by exclusively setting the writer_flag to 1, provided that the whole
+ * 32-bit is 0 (meaning no readers or writers working). On the other hand,
+ * a new reader tries to increment the "reader_count" field provided that
+ * the writer_flag is 0 (meaning there is no writer working).
+ *
+ * If some of the above operations fail, the reader or the writer sleeps
+ * until the related condition changes. When a working reader or writer
+ * completes its work, some readers or writers are sleeping, and the condition
+ * that suspended the reader or writer has changed, it wakes up the sleeping
+ * readers or writers.
+ *
+ * As already noted, this algorithm basically prefers writers. In order to
+ * prevent readers from starving, however, the algorithm also introduces the
+ * "writer quota" (Q). When Q consecutive writers have completed their work,
+ * suspending readers, the last writer will wake up the readers, even if a new
+ * writer is waiting.
+ *
+ * Implementation specific note: due to the combination of atomic operations
+ * and a mutex lock, ordering between the atomic operation and locks can be
+ * very sensitive in some cases. In particular, it is generally very important
+ * to check the atomic variable that requires a reader or writer to sleep after
+ * locking the mutex and before actually sleeping; otherwise, it could be very
+ * likely to cause a deadlock. For example, assume "var" is a variable
+ * atomically modified, then the corresponding code would be:
+ * if (var == need_sleep) {
+ * LOCK(lock);
+ * if (var == need_sleep)
+ * WAIT(cond, lock);
+ * UNLOCK(lock);
+ * }
+ * The second check is important, since "var" is protected by the atomic
+ * operation, not by the mutex, and can be changed just before sleeping.
+ * (The first "if" could be omitted, but this is also important in order to
+ * make the code efficient by avoiding the use of the mutex unless it is
+ * really necessary.)
+ */
+
+#define WRITER_ACTIVE 0x1
+#define READER_INCR 0x2
+
+isc_result_t
+isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+ isc_int32_t cntflag;
+
+ REQUIRE(VALID_RWLOCK(rwl));
+
+#ifdef ISC_RWLOCK_TRACE
+ print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_PRELOCK, "prelock"), rwl, type);
+#endif
+
+ if (type == isc_rwlocktype_read) {
+ if (rwl->write_requests != rwl->write_completions) {
+ /* there is a waiting or active writer */
+ LOCK(&rwl->lock);
+ if (rwl->write_requests != rwl->write_completions) {
+ rwl->readers_waiting++;
+ WAIT(&rwl->readable, &rwl->lock);
+ rwl->readers_waiting--;
+ }
+ UNLOCK(&rwl->lock);
+ }
+
+ cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
+ while (1) {
+ if ((rwl->cnt_and_flag & WRITER_ACTIVE) == 0)
+ break;
+
+ /* A writer is still working */
+ LOCK(&rwl->lock);
+ rwl->readers_waiting++;
+ if ((rwl->cnt_and_flag & WRITER_ACTIVE) != 0)
+ WAIT(&rwl->readable, &rwl->lock);
+ rwl->readers_waiting--;
+ UNLOCK(&rwl->lock);
+
+ /*
+ * Typically, the reader should be able to get a lock
+ * at this stage:
+ * (1) there should have been no pending writer when
+ * the reader was trying to increment the
+ * counter; otherwise, the writer should be in
+ * the waiting queue, preventing the reader from
+ * proceeding to this point.
+ * (2) once the reader increments the counter, no
+ * more writer can get a lock.
+ * Still, it is possible another writer can work at
+ * this point, e.g. in the following scenario:
+ * A previous writer unlocks the writer lock.
+ * This reader proceeds to point (1).
+ * A new writer appears, and gets a new lock before
+ * the reader increments the counter.
+ * The reader then increments the counter.
+ * The previous writer notices there is a waiting
+ * reader who is almost ready, and wakes it up.
+ * So, the reader needs to confirm whether it can now
+ * read explicitly (thus we loop). Note that this is
+ * not an infinite process, since the reader has
+ * incremented the counter at this point.
+ */
+ }
+
+ /*
+ * If we are temporarily preferred to writers due to the writer
+ * quota, reset the condition (race among readers doesn't
+ * matter).
+ */
+ rwl->write_granted = 0;
+ } else {
+ isc_int32_t prev_writer;
+
+ /* enter the waiting queue, and wait for our turn */
+ prev_writer = isc_atomic_xadd(&rwl->write_requests, 1);
+ while (rwl->write_completions != prev_writer) {
+ LOCK(&rwl->lock);
+ if (rwl->write_completions != prev_writer) {
+ WAIT(&rwl->writeable, &rwl->lock);
+ UNLOCK(&rwl->lock);
+ continue;
+ }
+ UNLOCK(&rwl->lock);
+ break;
+ }
+
+ while (1) {
+ cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
+ WRITER_ACTIVE);
+ if (cntflag == 0)
+ break;
+
+ /* Another active reader or writer is working. */
+ LOCK(&rwl->lock);
+ if (rwl->cnt_and_flag != 0)
+ WAIT(&rwl->writeable, &rwl->lock);
+ UNLOCK(&rwl->lock);
+ }
+
+ INSIST((rwl->cnt_and_flag & WRITER_ACTIVE) != 0);
+ rwl->write_granted++;
+ }
+
+#ifdef ISC_RWLOCK_TRACE
+ print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_POSTLOCK, "postlock"), rwl, type);
+#endif
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+ isc_int32_t cntflag;
+
+ REQUIRE(VALID_RWLOCK(rwl));
+
+#ifdef ISC_RWLOCK_TRACE
+ print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_PRELOCK, "prelock"), rwl, type);
+#endif
+
+ if (type == isc_rwlocktype_read) {
+ /* If a writer is waiting or working, we fail. */
+ if (rwl->write_requests != rwl->write_completions)
+ return (ISC_R_LOCKBUSY);
+
+ /* Otherwise, be ready for reading. */
+ cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
+ if ((cntflag & WRITER_ACTIVE) != 0) {
+ /*
+ * A writer is working. We lose, and cancel the read
+ * request.
+ */
+ cntflag = isc_atomic_xadd(&rwl->cnt_and_flag,
+ -READER_INCR);
+ /*
+ * If no other readers are waiting and we've suspended
+ * new writers in this short period, wake them up.
+ */
+ if (cntflag == READER_INCR &&
+ rwl->write_completions != rwl->write_requests) {
+ LOCK(&rwl->lock);
+ BROADCAST(&rwl->writeable);
+ UNLOCK(&rwl->lock);
+ }
+
+ return (ISC_R_LOCKBUSY);
+ }
+ } else {
+ /* Try locking without entering the waiting queue. */
+ cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
+ WRITER_ACTIVE);
+ if (cntflag != 0)
+ return (ISC_R_LOCKBUSY);
+
+ /*
+ * XXXJT: jump into the queue, possibly breaking the writer
+ * order.
+ */
+ (void)isc_atomic_xadd(&rwl->write_completions, -1);
+
+ rwl->write_granted++;
+ }
+
+#ifdef ISC_RWLOCK_TRACE
+ print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_POSTLOCK, "postlock"), rwl, type);
+#endif
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
+ isc_int32_t prevcnt;
+
+ REQUIRE(VALID_RWLOCK(rwl));
+
+ /* Try to acquire write access. */
+ prevcnt = isc_atomic_cmpxchg(&rwl->cnt_and_flag,
+ READER_INCR, WRITER_ACTIVE);
+ /*
+ * There must have been no writer, and there must have been at least
+ * one reader.
+ */
+ INSIST((prevcnt & WRITER_ACTIVE) == 0 &&
+ (prevcnt & ~WRITER_ACTIVE) != 0);
+
+ if (prevcnt == READER_INCR) {
+ /*
+ * We are the only reader and have been upgraded.
+ * Now jump into the head of the writer waiting queue.
+ */
+ (void)isc_atomic_xadd(&rwl->write_completions, -1);
+ } else
+ return (ISC_R_LOCKBUSY);
+
+ return (ISC_R_SUCCESS);
+
+}
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl) {
+ isc_int32_t prev_readers;
+
+ REQUIRE(VALID_RWLOCK(rwl));
+
+ /* Become an active reader. */
+ prev_readers = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
+ /* We must have been a writer. */
+ INSIST((prev_readers & WRITER_ACTIVE) != 0);
+
+ /* Complete write */
+ (void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE);
+ (void)isc_atomic_xadd(&rwl->write_completions, 1);
+
+ /* Resume other readers */
+ LOCK(&rwl->lock);
+ if (rwl->readers_waiting > 0)
+ BROADCAST(&rwl->readable);
+ UNLOCK(&rwl->lock);
+}
+
+isc_result_t
+isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+ isc_int32_t prev_cnt;
+
+ REQUIRE(VALID_RWLOCK(rwl));
+
+#ifdef ISC_RWLOCK_TRACE
+ print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);
+#endif
+
+ if (type == isc_rwlocktype_read) {
+ prev_cnt = isc_atomic_xadd(&rwl->cnt_and_flag, -READER_INCR);
+
+ /*
+ * If we're the last reader and any writers are waiting, wake
+ * them up. We need to wake up all of them to ensure the
+ * FIFO order.
+ */
+ if (prev_cnt == READER_INCR &&
+ rwl->write_completions != rwl->write_requests) {
+ LOCK(&rwl->lock);
+ BROADCAST(&rwl->writeable);
+ UNLOCK(&rwl->lock);
+ }
+ } else {
+ isc_boolean_t wakeup_writers = ISC_TRUE;
+
+ /*
+ * Reset the flag, and (implicitly) tell other writers
+ * we are done.
+ */
+ (void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE);
+ (void)isc_atomic_xadd(&rwl->write_completions, 1);
+
+ if (rwl->write_granted >= rwl->write_quota ||
+ rwl->write_requests == rwl->write_completions ||
+ (rwl->cnt_and_flag & ~WRITER_ACTIVE) != 0) {
+ /*
+ * We have passed the write quota, no writer is
+ * waiting, or some readers are almost ready, pending
+ * possible writers. Note that the last case can
+ * happen even if write_requests != write_completions
+ * (which means a new writer in the queue), so we need
+ * to catch the case explicitly.
+ */
+ LOCK(&rwl->lock);
+ if (rwl->readers_waiting > 0) {
+ wakeup_writers = ISC_FALSE;
+ BROADCAST(&rwl->readable);
+ }
+ UNLOCK(&rwl->lock);
+ }
+
+ if (rwl->write_requests != rwl->write_completions &&
+ wakeup_writers) {
+ LOCK(&rwl->lock);
+ BROADCAST(&rwl->writeable);
+ UNLOCK(&rwl->lock);
+ }
+ }
+
+#ifdef ISC_RWLOCK_TRACE
+ print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_POSTUNLOCK, "postunlock"),
+ rwl, type);
+#endif
+
+ return (ISC_R_SUCCESS);
+}
+
+#else /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */
+
+static isc_result_t
+doit(isc_rwlock_t *rwl, isc_rwlocktype_t type, isc_boolean_t nonblock) {
+ isc_boolean_t skip = ISC_FALSE;
+ isc_boolean_t done = ISC_FALSE;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(VALID_RWLOCK(rwl));
+
+ LOCK(&rwl->lock);
+
+#ifdef ISC_RWLOCK_TRACE
+ print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_PRELOCK, "prelock"), rwl, type);
+#endif
+
+ if (type == isc_rwlocktype_read) {
+ if (rwl->readers_waiting != 0)
+ skip = ISC_TRUE;
+ while (!done) {
+ if (!skip &&
+ ((rwl->active == 0 ||
+ (rwl->type == isc_rwlocktype_read &&
+ (rwl->writers_waiting == 0 ||
+ rwl->granted < rwl->read_quota)))))
+ {
+ rwl->type = isc_rwlocktype_read;
+ rwl->active++;
+ rwl->granted++;
+ done = ISC_TRUE;
+ } else if (nonblock) {
+ result = ISC_R_LOCKBUSY;
+ done = ISC_TRUE;
+ } else {
+ skip = ISC_FALSE;
+ rwl->readers_waiting++;
+ WAIT(&rwl->readable, &rwl->lock);
+ rwl->readers_waiting--;
+ }
+ }
+ } else {
+ if (rwl->writers_waiting != 0)
+ skip = ISC_TRUE;
+ while (!done) {
+ if (!skip && rwl->active == 0) {
+ rwl->type = isc_rwlocktype_write;
+ rwl->active = 1;
+ rwl->granted++;
+ done = ISC_TRUE;
+ } else if (nonblock) {
+ result = ISC_R_LOCKBUSY;
+ done = ISC_TRUE;
+ } else {
+ skip = ISC_FALSE;
+ rwl->writers_waiting++;
+ WAIT(&rwl->writeable, &rwl->lock);
+ rwl->writers_waiting--;
+ }
+ }
+ }
+
+#ifdef ISC_RWLOCK_TRACE
+ print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_POSTLOCK, "postlock"), rwl, type);
+#endif
+
+ UNLOCK(&rwl->lock);
+
+ return (result);
+}
+
+isc_result_t
+isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+ return (doit(rwl, type, ISC_FALSE));
+}
+
+isc_result_t
+isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+ return (doit(rwl, type, ISC_TRUE));
+}
+
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(VALID_RWLOCK(rwl));
+ LOCK(&rwl->lock);
+ REQUIRE(rwl->type == isc_rwlocktype_read);
+ REQUIRE(rwl->active != 0);
+
+ /* If we are the only reader then succeed. */
+ if (rwl->active == 1) {
+ rwl->original = (rwl->original == isc_rwlocktype_none) ?
+ isc_rwlocktype_read : isc_rwlocktype_none;
+ rwl->type = isc_rwlocktype_write;
+ } else
+ result = ISC_R_LOCKBUSY;
+
+ UNLOCK(&rwl->lock);
+ return (result);
+}
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl) {
+
+ REQUIRE(VALID_RWLOCK(rwl));
+ LOCK(&rwl->lock);
+ REQUIRE(rwl->type == isc_rwlocktype_write);
+ REQUIRE(rwl->active == 1);
+
+ rwl->type = isc_rwlocktype_read;
+ rwl->original = (rwl->original == isc_rwlocktype_none) ?
+ isc_rwlocktype_write : isc_rwlocktype_none;
+ /*
+ * Resume processing any read request that were blocked when
+ * we upgraded.
+ */
+ if (rwl->original == isc_rwlocktype_none &&
+ (rwl->writers_waiting == 0 || rwl->granted < rwl->read_quota) &&
+ rwl->readers_waiting > 0)
+ BROADCAST(&rwl->readable);
+
+ UNLOCK(&rwl->lock);
+}
+
+isc_result_t
+isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+
+ REQUIRE(VALID_RWLOCK(rwl));
+ LOCK(&rwl->lock);
+ REQUIRE(rwl->type == type);
+
+ UNUSED(type);
+
+#ifdef ISC_RWLOCK_TRACE
+ print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);
+#endif
+
+ INSIST(rwl->active > 0);
+ rwl->active--;
+ if (rwl->active == 0) {
+ if (rwl->original != isc_rwlocktype_none) {
+ rwl->type = rwl->original;
+ rwl->original = isc_rwlocktype_none;
+ }
+ if (rwl->type == isc_rwlocktype_read) {
+ rwl->granted = 0;
+ if (rwl->writers_waiting > 0) {
+ rwl->type = isc_rwlocktype_write;
+ SIGNAL(&rwl->writeable);
+ } else if (rwl->readers_waiting > 0) {
+ /* Does this case ever happen? */
+ BROADCAST(&rwl->readable);
+ }
+ } else {
+ if (rwl->readers_waiting > 0) {
+ if (rwl->writers_waiting > 0 &&
+ rwl->granted < rwl->write_quota) {
+ SIGNAL(&rwl->writeable);
+ } else {
+ rwl->granted = 0;
+ rwl->type = isc_rwlocktype_read;
+ BROADCAST(&rwl->readable);
+ }
+ } else if (rwl->writers_waiting > 0) {
+ rwl->granted = 0;
+ SIGNAL(&rwl->writeable);
+ } else {
+ rwl->granted = 0;
+ }
+ }
+ }
+ INSIST(rwl->original == isc_rwlocktype_none);
+
+#ifdef ISC_RWLOCK_TRACE
+ print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
+ ISC_MSG_POSTUNLOCK, "postunlock"),
+ rwl, type);
+#endif
+
+ UNLOCK(&rwl->lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+#endif /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */
+#else /* ISC_PLATFORM_USETHREADS */
+
+isc_result_t
+isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
+ unsigned int write_quota)
+{
+ REQUIRE(rwl != NULL);
+
+ UNUSED(read_quota);
+ UNUSED(write_quota);
+
+ rwl->type = isc_rwlocktype_read;
+ rwl->active = 0;
+ rwl->magic = RWLOCK_MAGIC;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+ REQUIRE(VALID_RWLOCK(rwl));
+
+ if (type == isc_rwlocktype_read) {
+ if (rwl->type != isc_rwlocktype_read && rwl->active != 0)
+ return (ISC_R_LOCKBUSY);
+ rwl->type = isc_rwlocktype_read;
+ rwl->active++;
+ } else {
+ if (rwl->active != 0)
+ return (ISC_R_LOCKBUSY);
+ rwl->type = isc_rwlocktype_write;
+ rwl->active = 1;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+ return (isc_rwlock_lock(rwl, type));
+}
+
+isc_result_t
+isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(VALID_RWLOCK(rwl));
+ REQUIRE(rwl->type == isc_rwlocktype_read);
+ REQUIRE(rwl->active != 0);
+
+ /* If we are the only reader then succeed. */
+ if (rwl->active == 1)
+ rwl->type = isc_rwlocktype_write;
+ else
+ result = ISC_R_LOCKBUSY;
+ return (result);
+}
+
+void
+isc_rwlock_downgrade(isc_rwlock_t *rwl) {
+
+ REQUIRE(VALID_RWLOCK(rwl));
+ REQUIRE(rwl->type == isc_rwlocktype_write);
+ REQUIRE(rwl->active == 1);
+
+ rwl->type = isc_rwlocktype_read;
+}
+
+isc_result_t
+isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
+ REQUIRE(VALID_RWLOCK(rwl));
+ REQUIRE(rwl->type == type);
+
+ UNUSED(type);
+
+ INSIST(rwl->active > 0);
+ rwl->active--;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_rwlock_destroy(isc_rwlock_t *rwl) {
+ REQUIRE(rwl != NULL);
+ REQUIRE(rwl->active == 0);
+ rwl->magic = 0;
+}
+
+#endif /* ISC_PLATFORM_USETHREADS */
diff --git a/lib/isc/serial.c b/lib/isc/serial.c
new file mode 100644
index 0000000..b43aac7
--- /dev/null
+++ b/lib/isc/serial.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: serial.c,v 1.12 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/serial.h>
+
+isc_boolean_t
+isc_serial_lt(isc_uint32_t a, isc_uint32_t b) {
+ /*
+ * Undefined => ISC_FALSE
+ */
+ if (a == (b ^ 0x80000000U))
+ return (ISC_FALSE);
+ return (((isc_int32_t)(a - b) < 0) ? ISC_TRUE : ISC_FALSE);
+}
+
+isc_boolean_t
+isc_serial_gt(isc_uint32_t a, isc_uint32_t b) {
+ return (((isc_int32_t)(a - b) > 0) ? ISC_TRUE : ISC_FALSE);
+}
+
+isc_boolean_t
+isc_serial_le(isc_uint32_t a, isc_uint32_t b) {
+ return ((a == b) ? ISC_TRUE : isc_serial_lt(a, b));
+}
+
+isc_boolean_t
+isc_serial_ge(isc_uint32_t a, isc_uint32_t b) {
+ return ((a == b) ? ISC_TRUE : isc_serial_gt(a, b));
+}
+
+isc_boolean_t
+isc_serial_eq(isc_uint32_t a, isc_uint32_t b) {
+ return ((a == b) ? ISC_TRUE : ISC_FALSE);
+}
+
+isc_boolean_t
+isc_serial_ne(isc_uint32_t a, isc_uint32_t b) {
+ return ((a != b) ? ISC_TRUE : ISC_FALSE);
+}
diff --git a/lib/isc/sha1.c b/lib/isc/sha1.c
new file mode 100644
index 0000000..3575288
--- /dev/null
+++ b/lib/isc/sha1.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: sha1.c,v 1.18 2007/06/19 23:47:17 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 $ */
+
+/*! \file
+ * SHA-1 in C
+ * \author By Steve Reid <steve@edmweb.com>
+ * 100% Public Domain
+ * \verbatim
+ * Test Vectors (from FIPS PUB 180-1)
+ * "abc"
+ * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+ * A million repetitions of "a"
+ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+ * \endverbatim
+ */
+
+#include "config.h"
+
+#include <isc/assertions.h>
+#include <isc/sha1.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/*@{*/
+/*!
+ * blk0() and blk() perform the initial expand.
+ * I got the idea of expanding during the round function from SSLeay
+ */
+#if !defined(WORDS_BIGENDIAN)
+# define blk0(i) \
+ (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \
+ | (rol(block->l[i], 8) & 0x00FF00FF))
+#else
+# define blk0(i) block->l[i]
+#endif
+#define blk(i) \
+ (block->l[i & 15] = rol(block->l[(i + 13) & 15] \
+ ^ block->l[(i + 8) & 15] \
+ ^ block->l[(i + 2) & 15] \
+ ^ block->l[i & 15], 1))
+
+/*@}*/
+/*@{*/
+/*!
+ * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
+ */
+#define R0(v,w,x,y,z,i) \
+ z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
+ w = rol(w, 30);
+#define R1(v,w,x,y,z,i) \
+ z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
+ w = rol(w, 30);
+#define R2(v,w,x,y,z,i) \
+ z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \
+ w = rol(w, 30);
+#define R3(v,w,x,y,z,i) \
+ z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
+ w = rol(w, 30);
+#define R4(v,w,x,y,z,i) \
+ z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
+ w = rol(w, 30);
+
+/*@}*/
+
+typedef union {
+ unsigned char c[64];
+ unsigned int l[16];
+} CHAR64LONG16;
+
+#ifdef __sparc_v9__
+static void do_R01(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c,
+ isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *);
+static void do_R2(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c,
+ isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *);
+static void do_R3(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c,
+ isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *);
+static void do_R4(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c,
+ isc_uint32_t *d, isc_uint32_t *e, CHAR64LONG16 *);
+
+#define nR0(v,w,x,y,z,i) R0(*v,*w,*x,*y,*z,i)
+#define nR1(v,w,x,y,z,i) R1(*v,*w,*x,*y,*z,i)
+#define nR2(v,w,x,y,z,i) R2(*v,*w,*x,*y,*z,i)
+#define nR3(v,w,x,y,z,i) R3(*v,*w,*x,*y,*z,i)
+#define nR4(v,w,x,y,z,i) R4(*v,*w,*x,*y,*z,i)
+
+static void
+do_R01(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d,
+ isc_uint32_t *e, CHAR64LONG16 *block)
+{
+ nR0(a,b,c,d,e, 0); nR0(e,a,b,c,d, 1); nR0(d,e,a,b,c, 2);
+ nR0(c,d,e,a,b, 3); nR0(b,c,d,e,a, 4); nR0(a,b,c,d,e, 5);
+ nR0(e,a,b,c,d, 6); nR0(d,e,a,b,c, 7); nR0(c,d,e,a,b, 8);
+ nR0(b,c,d,e,a, 9); nR0(a,b,c,d,e,10); nR0(e,a,b,c,d,11);
+ nR0(d,e,a,b,c,12); nR0(c,d,e,a,b,13); nR0(b,c,d,e,a,14);
+ nR0(a,b,c,d,e,15); nR1(e,a,b,c,d,16); nR1(d,e,a,b,c,17);
+ nR1(c,d,e,a,b,18); nR1(b,c,d,e,a,19);
+}
+
+static void
+do_R2(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d,
+ isc_uint32_t *e, CHAR64LONG16 *block)
+{
+ nR2(a,b,c,d,e,20); nR2(e,a,b,c,d,21); nR2(d,e,a,b,c,22);
+ nR2(c,d,e,a,b,23); nR2(b,c,d,e,a,24); nR2(a,b,c,d,e,25);
+ nR2(e,a,b,c,d,26); nR2(d,e,a,b,c,27); nR2(c,d,e,a,b,28);
+ nR2(b,c,d,e,a,29); nR2(a,b,c,d,e,30); nR2(e,a,b,c,d,31);
+ nR2(d,e,a,b,c,32); nR2(c,d,e,a,b,33); nR2(b,c,d,e,a,34);
+ nR2(a,b,c,d,e,35); nR2(e,a,b,c,d,36); nR2(d,e,a,b,c,37);
+ nR2(c,d,e,a,b,38); nR2(b,c,d,e,a,39);
+}
+
+static void
+do_R3(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d,
+ isc_uint32_t *e, CHAR64LONG16 *block)
+{
+ nR3(a,b,c,d,e,40); nR3(e,a,b,c,d,41); nR3(d,e,a,b,c,42);
+ nR3(c,d,e,a,b,43); nR3(b,c,d,e,a,44); nR3(a,b,c,d,e,45);
+ nR3(e,a,b,c,d,46); nR3(d,e,a,b,c,47); nR3(c,d,e,a,b,48);
+ nR3(b,c,d,e,a,49); nR3(a,b,c,d,e,50); nR3(e,a,b,c,d,51);
+ nR3(d,e,a,b,c,52); nR3(c,d,e,a,b,53); nR3(b,c,d,e,a,54);
+ nR3(a,b,c,d,e,55); nR3(e,a,b,c,d,56); nR3(d,e,a,b,c,57);
+ nR3(c,d,e,a,b,58); nR3(b,c,d,e,a,59);
+}
+
+static void
+do_R4(isc_uint32_t *a, isc_uint32_t *b, isc_uint32_t *c, isc_uint32_t *d,
+ isc_uint32_t *e, CHAR64LONG16 *block)
+{
+ nR4(a,b,c,d,e,60); nR4(e,a,b,c,d,61); nR4(d,e,a,b,c,62);
+ nR4(c,d,e,a,b,63); nR4(b,c,d,e,a,64); nR4(a,b,c,d,e,65);
+ nR4(e,a,b,c,d,66); nR4(d,e,a,b,c,67); nR4(c,d,e,a,b,68);
+ nR4(b,c,d,e,a,69); nR4(a,b,c,d,e,70); nR4(e,a,b,c,d,71);
+ nR4(d,e,a,b,c,72); nR4(c,d,e,a,b,73); nR4(b,c,d,e,a,74);
+ nR4(a,b,c,d,e,75); nR4(e,a,b,c,d,76); nR4(d,e,a,b,c,77);
+ nR4(c,d,e,a,b,78); nR4(b,c,d,e,a,79);
+}
+#endif
+
+/*!
+ * Hash a single 512-bit block. This is the core of the algorithm.
+ */
+static void
+transform(isc_uint32_t state[5], const unsigned char buffer[64]) {
+ isc_uint32_t a, b, c, d, e;
+ CHAR64LONG16 *block;
+ CHAR64LONG16 workspace;
+
+ INSIST(buffer != NULL);
+ INSIST(state != NULL);
+
+ block = &workspace;
+ (void)memcpy(block, buffer, 64);
+
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+
+#ifdef __sparc_v9__
+ do_R01(&a, &b, &c, &d, &e, block);
+ do_R2(&a, &b, &c, &d, &e, block);
+ do_R3(&a, &b, &c, &d, &e, block);
+ do_R4(&a, &b, &c, &d, &e, block);
+#else
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+#endif
+
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/*!
+ * isc_sha1_init - Initialize new context
+ */
+void
+isc_sha1_init(isc_sha1_t *context)
+{
+ INSIST(context != NULL);
+
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = 0;
+ context->count[1] = 0;
+}
+
+void
+isc_sha1_invalidate(isc_sha1_t *context) {
+ memset(context, 0, sizeof(isc_sha1_t));
+}
+
+/*!
+ * Run your data through this.
+ */
+void
+isc_sha1_update(isc_sha1_t *context, const unsigned char *data,
+ unsigned int len)
+{
+ unsigned int i, j;
+
+ INSIST(context != 0);
+ INSIST(data != 0);
+
+ j = context->count[0];
+ if ((context->count[0] += len << 3) < j)
+ context->count[1] += (len >> 29) + 1;
+ j = (j >> 3) & 63;
+ if ((j + len) > 63) {
+ (void)memcpy(&context->buffer[j], data, (i = 64 - j));
+ transform(context->state, context->buffer);
+ for (; i + 63 < len; i += 64)
+ transform(context->state, &data[i]);
+ j = 0;
+ } else {
+ i = 0;
+ }
+
+ (void)memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/*!
+ * Add padding and return the message digest.
+ */
+
+static const unsigned char final_200 = 128;
+static const unsigned char final_0 = 0;
+
+void
+isc_sha1_final(isc_sha1_t *context, unsigned char *digest) {
+ unsigned int i;
+ unsigned char finalcount[8];
+
+ INSIST(digest != 0);
+ INSIST(context != 0);
+
+ for (i = 0; i < 8; i++) {
+ /* Endian independent */
+ finalcount[i] = (unsigned char)
+ ((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3 - (i & 3)) * 8)) & 255);
+ }
+
+ isc_sha1_update(context, &final_200, 1);
+ while ((context->count[0] & 504) != 448)
+ isc_sha1_update(context, &final_0, 1);
+ /* The next Update should cause a transform() */
+ isc_sha1_update(context, finalcount, 8);
+
+ if (digest) {
+ for (i = 0; i < 20; i++)
+ digest[i] = (unsigned char)
+ ((context->state[i >> 2]
+ >> ((3 - (i & 3)) * 8)) & 255);
+ }
+
+ memset(context, 0, sizeof(isc_sha1_t));
+}
diff --git a/lib/isc/sha2.c b/lib/isc/sha2.c
new file mode 100644
index 0000000..2158ab0
--- /dev/null
+++ b/lib/isc/sha2.c
@@ -0,0 +1,1234 @@
+/*
+ * Copyright (C) 2005-2007 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: sha2.c,v 1.13 2007/06/19 23:47:17 tbox Exp $ */
+
+/* $FreeBSD: src/sys/crypto/sha2/sha2.c,v 1.2.2.2 2002/03/05 08:36:47 ume Exp $ */
+/* $KAME: sha2.c,v 1.8 2001/11/08 01:07:52 itojun Exp $ */
+
+/*
+ * sha2.c
+ *
+ * Version 1.0.0beta1
+ *
+ * Written by Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright 2000 Aaron D. Gifford. 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 copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+
+#include <config.h>
+
+#include <isc/assertions.h>
+#include <isc/sha2.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/*
+ * UNROLLED TRANSFORM LOOP NOTE:
+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
+ * loop version for the hash transform rounds (defined using macros
+ * later in this file). Either define on the command line, for example:
+ *
+ * cc -DISC_SHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
+ *
+ * or define below:
+ *
+ * \#define ISC_SHA2_UNROLL_TRANSFORM
+ *
+ */
+
+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+/*
+ * BYTE_ORDER NOTE:
+ *
+ * Please make sure that your system defines BYTE_ORDER. If your
+ * architecture is little-endian, make sure it also defines
+ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
+ * equivilent.
+ *
+ * If your system does not define the above, then you can do so by
+ * hand like this:
+ *
+ * \#define LITTLE_ENDIAN 1234
+ * \#define BIG_ENDIAN 4321
+ *
+ * And for little-endian machines, add:
+ *
+ * \#define BYTE_ORDER LITTLE_ENDIAN
+ *
+ * Or for big-endian machines:
+ *
+ * \#define BYTE_ORDER BIG_ENDIAN
+ *
+ * The FreeBSD machine this was written on defines BYTE_ORDER
+ * appropriately by including <sys/types.h> (which in turn includes
+ * <machine/endian.h> where the appropriate definitions are actually
+ * made).
+ */
+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
+#ifndef BYTE_ORDER
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+#ifdef WORDS_BIGENDIAN
+#define BYTE_ORDER BIG_ENDIAN
+#else
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+#else
+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
+#endif
+#endif
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+/* NOTE: Most of these are in sha2.h */
+#define ISC_SHA256_SHORT_BLOCK_LENGTH (ISC_SHA256_BLOCK_LENGTH - 8)
+#define ISC_SHA384_SHORT_BLOCK_LENGTH (ISC_SHA384_BLOCK_LENGTH - 16)
+#define ISC_SHA512_SHORT_BLOCK_LENGTH (ISC_SHA512_BLOCK_LENGTH - 16)
+
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define REVERSE32(w,x) { \
+ isc_uint32_t tmp = (w); \
+ tmp = (tmp >> 16) | (tmp << 16); \
+ (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#ifdef WIN32
+#define REVERSE64(w,x) { \
+ isc_uint64_t tmp = (w); \
+ tmp = (tmp >> 32) | (tmp << 32); \
+ tmp = ((tmp & 0xff00ff00ff00ff00UL) >> 8) | \
+ ((tmp & 0x00ff00ff00ff00ffUL) << 8); \
+ (x) = ((tmp & 0xffff0000ffff0000UL) >> 16) | \
+ ((tmp & 0x0000ffff0000ffffUL) << 16); \
+}
+#else
+#define REVERSE64(w,x) { \
+ isc_uint64_t tmp = (w); \
+ tmp = (tmp >> 32) | (tmp << 32); \
+ tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+ ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+ (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+ ((tmp & 0x0000ffff0000ffffULL) << 16); \
+}
+#endif
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n) { \
+ (w)[0] += (isc_uint64_t)(n); \
+ if ((w)[0] < (n)) { \
+ (w)[1]++; \
+ } \
+}
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ * NOTE: The naming of R and S appears backwards here (R is a SHIFT and
+ * S is a ROTATION) because the SHA-256/384/512 description document
+ * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ * same "backwards" definition.
+ */
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x) ((x) >> (b))
+/* 32-bit Rotate-right (used in SHA-256): */
+#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x)))
+#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x)))
+#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x)))
+
+/*** INTERNAL FUNCTION PROTOTYPES *************************************/
+/* NOTE: These should not be accessed directly from outside this
+ * library -- they are intended for private internal visibility/use
+ * only.
+ */
+void isc_sha512_last(isc_sha512_t *);
+void isc_sha256_transform(isc_sha256_t *, const isc_uint32_t*);
+void isc_sha512_transform(isc_sha512_t *, const isc_uint64_t*);
+
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-224 and SHA-256: */
+static const isc_uint32_t K256[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+ 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+ 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+ 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+ 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+ 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+ 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+ 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+ 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+ 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+ 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+ 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+ 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-224: */
+static const isc_uint32_t sha224_initial_hash_value[8] = {
+ 0xc1059ed8UL,
+ 0x367cd507UL,
+ 0x3070dd17UL,
+ 0xf70e5939UL,
+ 0xffc00b31UL,
+ 0x68581511UL,
+ 0x64f98fa7UL,
+ 0xbefa4fa4UL
+};
+
+/* Initial hash value H for SHA-256: */
+static const isc_uint32_t sha256_initial_hash_value[8] = {
+ 0x6a09e667UL,
+ 0xbb67ae85UL,
+ 0x3c6ef372UL,
+ 0xa54ff53aUL,
+ 0x510e527fUL,
+ 0x9b05688cUL,
+ 0x1f83d9abUL,
+ 0x5be0cd19UL
+};
+
+#ifdef WIN32
+/* Hash constant words K for SHA-384 and SHA-512: */
+static const isc_uint64_t K512[80] = {
+ 0x428a2f98d728ae22UL, 0x7137449123ef65cdUL,
+ 0xb5c0fbcfec4d3b2fUL, 0xe9b5dba58189dbbcUL,
+ 0x3956c25bf348b538UL, 0x59f111f1b605d019UL,
+ 0x923f82a4af194f9bUL, 0xab1c5ed5da6d8118UL,
+ 0xd807aa98a3030242UL, 0x12835b0145706fbeUL,
+ 0x243185be4ee4b28cUL, 0x550c7dc3d5ffb4e2UL,
+ 0x72be5d74f27b896fUL, 0x80deb1fe3b1696b1UL,
+ 0x9bdc06a725c71235UL, 0xc19bf174cf692694UL,
+ 0xe49b69c19ef14ad2UL, 0xefbe4786384f25e3UL,
+ 0x0fc19dc68b8cd5b5UL, 0x240ca1cc77ac9c65UL,
+ 0x2de92c6f592b0275UL, 0x4a7484aa6ea6e483UL,
+ 0x5cb0a9dcbd41fbd4UL, 0x76f988da831153b5UL,
+ 0x983e5152ee66dfabUL, 0xa831c66d2db43210UL,
+ 0xb00327c898fb213fUL, 0xbf597fc7beef0ee4UL,
+ 0xc6e00bf33da88fc2UL, 0xd5a79147930aa725UL,
+ 0x06ca6351e003826fUL, 0x142929670a0e6e70UL,
+ 0x27b70a8546d22ffcUL, 0x2e1b21385c26c926UL,
+ 0x4d2c6dfc5ac42aedUL, 0x53380d139d95b3dfUL,
+ 0x650a73548baf63deUL, 0x766a0abb3c77b2a8UL,
+ 0x81c2c92e47edaee6UL, 0x92722c851482353bUL,
+ 0xa2bfe8a14cf10364UL, 0xa81a664bbc423001UL,
+ 0xc24b8b70d0f89791UL, 0xc76c51a30654be30UL,
+ 0xd192e819d6ef5218UL, 0xd69906245565a910UL,
+ 0xf40e35855771202aUL, 0x106aa07032bbd1b8UL,
+ 0x19a4c116b8d2d0c8UL, 0x1e376c085141ab53UL,
+ 0x2748774cdf8eeb99UL, 0x34b0bcb5e19b48a8UL,
+ 0x391c0cb3c5c95a63UL, 0x4ed8aa4ae3418acbUL,
+ 0x5b9cca4f7763e373UL, 0x682e6ff3d6b2b8a3UL,
+ 0x748f82ee5defb2fcUL, 0x78a5636f43172f60UL,
+ 0x84c87814a1f0ab72UL, 0x8cc702081a6439ecUL,
+ 0x90befffa23631e28UL, 0xa4506cebde82bde9UL,
+ 0xbef9a3f7b2c67915UL, 0xc67178f2e372532bUL,
+ 0xca273eceea26619cUL, 0xd186b8c721c0c207UL,
+ 0xeada7dd6cde0eb1eUL, 0xf57d4f7fee6ed178UL,
+ 0x06f067aa72176fbaUL, 0x0a637dc5a2c898a6UL,
+ 0x113f9804bef90daeUL, 0x1b710b35131c471bUL,
+ 0x28db77f523047d84UL, 0x32caab7b40c72493UL,
+ 0x3c9ebe0a15c9bebcUL, 0x431d67c49c100d4cUL,
+ 0x4cc5d4becb3e42b6UL, 0x597f299cfc657e2aUL,
+ 0x5fcb6fab3ad6faecUL, 0x6c44198c4a475817UL
+};
+
+/* Initial hash value H for SHA-384: */
+static const isc_uint64_t sha384_initial_hash_value[8] = {
+ 0xcbbb9d5dc1059ed8UL,
+ 0x629a292a367cd507UL,
+ 0x9159015a3070dd17UL,
+ 0x152fecd8f70e5939UL,
+ 0x67332667ffc00b31UL,
+ 0x8eb44a8768581511UL,
+ 0xdb0c2e0d64f98fa7UL,
+ 0x47b5481dbefa4fa4UL
+};
+
+/* Initial hash value H for SHA-512: */
+static const isc_uint64_t sha512_initial_hash_value[8] = {
+ 0x6a09e667f3bcc908U,
+ 0xbb67ae8584caa73bUL,
+ 0x3c6ef372fe94f82bUL,
+ 0xa54ff53a5f1d36f1UL,
+ 0x510e527fade682d1UL,
+ 0x9b05688c2b3e6c1fUL,
+ 0x1f83d9abfb41bd6bUL,
+ 0x5be0cd19137e2179UL
+};
+#else
+/* Hash constant words K for SHA-384 and SHA-512: */
+static const isc_uint64_t K512[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+/* Initial hash value H for SHA-384: */
+static const isc_uint64_t sha384_initial_hash_value[8] = {
+ 0xcbbb9d5dc1059ed8ULL,
+ 0x629a292a367cd507ULL,
+ 0x9159015a3070dd17ULL,
+ 0x152fecd8f70e5939ULL,
+ 0x67332667ffc00b31ULL,
+ 0x8eb44a8768581511ULL,
+ 0xdb0c2e0d64f98fa7ULL,
+ 0x47b5481dbefa4fa4ULL
+};
+
+/* Initial hash value H for SHA-512: */
+static const isc_uint64_t sha512_initial_hash_value[8] = {
+ 0x6a09e667f3bcc908ULL,
+ 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL,
+ 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL,
+ 0x5be0cd19137e2179ULL
+};
+#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
+isc_sha224_init(isc_sha224_t *context) {
+ if (context == (isc_sha256_t *)0) {
+ return;
+ }
+ memcpy(context->state, sha224_initial_hash_value,
+ ISC_SHA256_DIGESTLENGTH);
+ memset(context->buffer, 0, ISC_SHA256_BLOCK_LENGTH);
+ context->bitcount = 0;
+}
+
+void
+isc_sha224_update(isc_sha224_t *context, const isc_uint8_t* data, size_t len) {
+ isc_sha256_update((isc_sha256_t *)context, data, len);
+}
+
+void
+isc_sha224_final(isc_uint8_t digest[], isc_sha224_t *context) {
+ isc_uint8_t sha256_digest[ISC_SHA256_DIGESTLENGTH];
+ isc_sha256_final(sha256_digest, (isc_sha256_t *)context);
+ memcpy(digest, sha256_digest, ISC_SHA224_DIGESTLENGTH);
+ 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) {
+ if (context == (isc_sha256_t *)0) {
+ return;
+ }
+ memcpy(context->state, sha256_initial_hash_value,
+ ISC_SHA256_DIGESTLENGTH);
+ memset(context->buffer, 0, ISC_SHA256_BLOCK_LENGTH);
+ context->bitcount = 0;
+}
+
+#ifdef ISC_SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-256 round macros: */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
+ REVERSE32(*data++, W256[j]); \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+ K256[j] + W256[j]; \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+ K256[j] + (W256[j] = *data++); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256(a,b,c,d,e,f,g,h) \
+ s0 = W256[(j+1)&0x0f]; \
+ s0 = sigma0_256(s0); \
+ s1 = W256[(j+14)&0x0f]; \
+ s1 = sigma1_256(s1); \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
+ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+void isc_sha256_transform(isc_sha256_t *context, const isc_uint32_t* data) {
+ isc_uint32_t a, b, c, d, e, f, g, h, s0, s1;
+ isc_uint32_t T1, *W256;
+ int j;
+
+ W256 = (isc_uint32_t*)context->buffer;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+ /* Rounds 0 to 15 (unrolled): */
+ ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
+ ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
+ ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
+ ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
+ ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
+ ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
+ ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
+ ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
+ } while (j < 16);
+
+ /* Now for the remaining rounds to 64: */
+ do {
+ ROUND256(a,b,c,d,e,f,g,h);
+ ROUND256(h,a,b,c,d,e,f,g);
+ ROUND256(g,h,a,b,c,d,e,f);
+ ROUND256(f,g,h,a,b,c,d,e);
+ ROUND256(e,f,g,h,a,b,c,d);
+ ROUND256(d,e,f,g,h,a,b,c);
+ ROUND256(c,d,e,f,g,h,a,b);
+ ROUND256(b,c,d,e,f,g,h,a);
+ } while (j < 64);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* ISC_SHA2_UNROLL_TRANSFORM */
+
+void
+isc_sha256_transform(isc_sha256_t *context, const isc_uint32_t* data) {
+ isc_uint32_t a, b, c, d, e, f, g, h, s0, s1;
+ isc_uint32_t T1, T2, *W256;
+ int j;
+
+ W256 = (isc_uint32_t*)context->buffer;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Copy data while converting to host byte order */
+ REVERSE32(*data++,W256[j]);
+ /* Apply the SHA-256 compression function to update a..h */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+ /* Apply the SHA-256 compression function to update a..h with copy */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+ T2 = Sigma0_256(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 16);
+
+ do {
+ /* Part of the message block expansion: */
+ s0 = W256[(j+1)&0x0f];
+ s0 = sigma0_256(s0);
+ s1 = W256[(j+14)&0x0f];
+ s1 = sigma1_256(s1);
+
+ /* Apply the SHA-256 compression function to update a..h */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
+ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+ T2 = Sigma0_256(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 64);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* ISC_SHA2_UNROLL_TRANSFORM */
+
+void
+isc_sha256_update(isc_sha256_t *context, const isc_uint8_t *data, size_t len) {
+ unsigned int freespace, usedspace;
+
+ 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);
+
+ usedspace = (unsigned int)((context->bitcount >> 3) %
+ ISC_SHA256_BLOCK_LENGTH);
+ if (usedspace > 0) {
+ /* Calculate how much free space is available in the buffer */
+ freespace = ISC_SHA256_BLOCK_LENGTH - usedspace;
+
+ if (len >= freespace) {
+ /* Fill the buffer completely and process it */
+ memcpy(&context->buffer[usedspace], data, freespace);
+ context->bitcount += freespace << 3;
+ len -= freespace;
+ data += freespace;
+ isc_sha256_transform(context,
+ (isc_uint32_t*)context->buffer);
+ } else {
+ /* The buffer is not yet full */
+ memcpy(&context->buffer[usedspace], data, len);
+ context->bitcount += len << 3;
+ /* Clean up: */
+ usedspace = freespace = 0;
+ return;
+ }
+ }
+ while (len >= ISC_SHA256_BLOCK_LENGTH) {
+ /* Process as many complete blocks as we can */
+ memcpy(context->buffer, data, ISC_SHA256_BLOCK_LENGTH);
+ isc_sha256_transform(context, (isc_uint32_t*)context->buffer);
+ context->bitcount += ISC_SHA256_BLOCK_LENGTH << 3;
+ len -= ISC_SHA256_BLOCK_LENGTH;
+ data += ISC_SHA256_BLOCK_LENGTH;
+ }
+ if (len > 0U) {
+ /* There's left-overs, so save 'em */
+ memcpy(context->buffer, data, len);
+ context->bitcount += len << 3;
+ }
+ /* Clean up: */
+ usedspace = freespace = 0;
+}
+
+void
+isc_sha256_final(isc_uint8_t digest[], isc_sha256_t *context) {
+ isc_uint32_t *d = (isc_uint32_t*)digest;
+ unsigned int usedspace;
+
+ /* 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) {
+ usedspace = (unsigned int)((context->bitcount >> 3) %
+ ISC_SHA256_BLOCK_LENGTH);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert FROM host byte order */
+ REVERSE64(context->bitcount,context->bitcount);
+#endif
+ if (usedspace > 0) {
+ /* Begin padding with a 1 bit: */
+ context->buffer[usedspace++] = 0x80;
+
+ if (usedspace <= ISC_SHA256_SHORT_BLOCK_LENGTH) {
+ /* Set-up for the last transform: */
+ memset(&context->buffer[usedspace], 0,
+ ISC_SHA256_SHORT_BLOCK_LENGTH - usedspace);
+ } else {
+ if (usedspace < ISC_SHA256_BLOCK_LENGTH) {
+ memset(&context->buffer[usedspace], 0,
+ ISC_SHA256_BLOCK_LENGTH -
+ usedspace);
+ }
+ /* Do second-to-last transform: */
+ isc_sha256_transform(context,
+ (isc_uint32_t*)context->buffer);
+
+ /* And set-up for the last transform: */
+ memset(context->buffer, 0,
+ ISC_SHA256_SHORT_BLOCK_LENGTH);
+ }
+ } else {
+ /* Set-up for the last transform: */
+ memset(context->buffer, 0, ISC_SHA256_SHORT_BLOCK_LENGTH);
+
+ /* Begin padding with a 1 bit: */
+ *context->buffer = 0x80;
+ }
+ /* Set the bit count: */
+ *(isc_uint64_t*)&context->buffer[ISC_SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
+
+ /* Final transform: */
+ isc_sha256_transform(context, (isc_uint32_t*)context->buffer);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ for (j = 0; j < 8; j++) {
+ REVERSE32(context->state[j],context->state[j]);
+ *d++ = context->state[j];
+ }
+ }
+#else
+ memcpy(d, context->state, ISC_SHA256_DIGESTLENGTH);
+#endif
+ }
+
+ /* Clean up state data: */
+ memset(context, 0, sizeof(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) {
+ if (context == (isc_sha512_t *)0) {
+ return;
+ }
+ memcpy(context->state, sha512_initial_hash_value,
+ ISC_SHA512_DIGESTLENGTH);
+ memset(context->buffer, 0, ISC_SHA512_BLOCK_LENGTH);
+ context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+#ifdef ISC_SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-512 round macros: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
+ REVERSE64(*data++, W512[j]); \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+ K512[j] + W512[j]; \
+ (d) += T1, \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
+ j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+ K512[j] + (W512[j] = *data++); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+ j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512(a,b,c,d,e,f,g,h) \
+ s0 = W512[(j+1)&0x0f]; \
+ s0 = sigma0_512(s0); \
+ s1 = W512[(j+14)&0x0f]; \
+ s1 = sigma1_512(s1); \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
+ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+ j++
+
+void isc_sha512_transform(isc_sha512_t *context, const isc_uint64_t* data) {
+ isc_uint64_t a, b, c, d, e, f, g, h, s0, s1;
+ isc_uint64_t T1, *W512 = (isc_uint64_t*)context->buffer;
+ int j;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+ ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
+ ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
+ ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
+ ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
+ ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
+ ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
+ ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
+ ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
+ } while (j < 16);
+
+ /* Now for the remaining rounds up to 79: */
+ do {
+ ROUND512(a,b,c,d,e,f,g,h);
+ ROUND512(h,a,b,c,d,e,f,g);
+ ROUND512(g,h,a,b,c,d,e,f);
+ ROUND512(f,g,h,a,b,c,d,e);
+ ROUND512(e,f,g,h,a,b,c,d);
+ ROUND512(d,e,f,g,h,a,b,c);
+ ROUND512(c,d,e,f,g,h,a,b);
+ ROUND512(b,c,d,e,f,g,h,a);
+ } while (j < 80);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* ISC_SHA2_UNROLL_TRANSFORM */
+
+void
+isc_sha512_transform(isc_sha512_t *context, const isc_uint64_t* data) {
+ isc_uint64_t a, b, c, d, e, f, g, h, s0, s1;
+ isc_uint64_t T1, T2, *W512 = (isc_uint64_t*)context->buffer;
+ int j;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert TO host byte order */
+ REVERSE64(*data++, W512[j]);
+ /* Apply the SHA-512 compression function to update a..h */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+ /* Apply the SHA-512 compression function to update a..h with copy */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+ T2 = Sigma0_512(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 16);
+
+ do {
+ /* Part of the message block expansion: */
+ s0 = W512[(j+1)&0x0f];
+ s0 = sigma0_512(s0);
+ s1 = W512[(j+14)&0x0f];
+ s1 = sigma1_512(s1);
+
+ /* Apply the SHA-512 compression function to update a..h */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
+ T2 = Sigma0_512(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 80);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* ISC_SHA2_UNROLL_TRANSFORM */
+
+void isc_sha512_update(isc_sha512_t *context, const isc_uint8_t *data, size_t len) {
+ unsigned int freespace, usedspace;
+
+ 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);
+
+ usedspace = (unsigned int)((context->bitcount[0] >> 3) %
+ ISC_SHA512_BLOCK_LENGTH);
+ if (usedspace > 0) {
+ /* Calculate how much free space is available in the buffer */
+ freespace = ISC_SHA512_BLOCK_LENGTH - usedspace;
+
+ if (len >= freespace) {
+ /* Fill the buffer completely and process it */
+ memcpy(&context->buffer[usedspace], data, freespace);
+ ADDINC128(context->bitcount, freespace << 3);
+ len -= freespace;
+ data += freespace;
+ isc_sha512_transform(context,
+ (isc_uint64_t*)context->buffer);
+ } else {
+ /* The buffer is not yet full */
+ memcpy(&context->buffer[usedspace], data, len);
+ ADDINC128(context->bitcount, len << 3);
+ /* Clean up: */
+ usedspace = freespace = 0;
+ return;
+ }
+ }
+ while (len >= ISC_SHA512_BLOCK_LENGTH) {
+ /* Process as many complete blocks as we can */
+ memcpy(context->buffer, data, ISC_SHA512_BLOCK_LENGTH);
+ isc_sha512_transform(context, (isc_uint64_t*)context->buffer);
+ ADDINC128(context->bitcount, ISC_SHA512_BLOCK_LENGTH << 3);
+ len -= ISC_SHA512_BLOCK_LENGTH;
+ data += ISC_SHA512_BLOCK_LENGTH;
+ }
+ if (len > 0U) {
+ /* There's left-overs, so save 'em */
+ memcpy(context->buffer, data, len);
+ ADDINC128(context->bitcount, len << 3);
+ }
+ /* Clean up: */
+ usedspace = freespace = 0;
+}
+
+void isc_sha512_last(isc_sha512_t *context) {
+ unsigned int usedspace;
+
+ usedspace = (unsigned int)((context->bitcount[0] >> 3) %
+ ISC_SHA512_BLOCK_LENGTH);
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert FROM host byte order */
+ REVERSE64(context->bitcount[0],context->bitcount[0]);
+ REVERSE64(context->bitcount[1],context->bitcount[1]);
+#endif
+ if (usedspace > 0) {
+ /* Begin padding with a 1 bit: */
+ context->buffer[usedspace++] = 0x80;
+
+ if (usedspace <= ISC_SHA512_SHORT_BLOCK_LENGTH) {
+ /* Set-up for the last transform: */
+ memset(&context->buffer[usedspace], 0,
+ ISC_SHA512_SHORT_BLOCK_LENGTH - usedspace);
+ } else {
+ if (usedspace < ISC_SHA512_BLOCK_LENGTH) {
+ memset(&context->buffer[usedspace], 0,
+ ISC_SHA512_BLOCK_LENGTH - usedspace);
+ }
+ /* Do second-to-last transform: */
+ isc_sha512_transform(context,
+ (isc_uint64_t*)context->buffer);
+
+ /* And set-up for the last transform: */
+ memset(context->buffer, 0, ISC_SHA512_BLOCK_LENGTH - 2);
+ }
+ } else {
+ /* Prepare for final transform: */
+ memset(context->buffer, 0, ISC_SHA512_SHORT_BLOCK_LENGTH);
+
+ /* Begin padding with a 1 bit: */
+ *context->buffer = 0x80;
+ }
+ /* Store the length of input data (in bits): */
+ *(isc_uint64_t*)&context->buffer[ISC_SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
+ *(isc_uint64_t*)&context->buffer[ISC_SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
+
+ /* Final transform: */
+ isc_sha512_transform(context, (isc_uint64_t*)context->buffer);
+}
+
+void isc_sha512_final(isc_uint8_t digest[], isc_sha512_t *context) {
+ isc_uint64_t *d = (isc_uint64_t*)digest;
+
+ /* 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) {
+ isc_sha512_last(context);
+
+ /* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ for (j = 0; j < 8; j++) {
+ REVERSE64(context->state[j],context->state[j]);
+ *d++ = context->state[j];
+ }
+ }
+#else
+ memcpy(d, context->state, ISC_SHA512_DIGESTLENGTH);
+#endif
+ }
+
+ /* Zero out state data */
+ 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
+isc_sha384_init(isc_sha384_t *context) {
+ if (context == (isc_sha384_t *)0) {
+ return;
+ }
+ memcpy(context->state, sha384_initial_hash_value,
+ ISC_SHA512_DIGESTLENGTH);
+ memset(context->buffer, 0, ISC_SHA384_BLOCK_LENGTH);
+ context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+void
+isc_sha384_update(isc_sha384_t *context, const isc_uint8_t* data, size_t len) {
+ isc_sha512_update((isc_sha512_t *)context, data, len);
+}
+
+void
+isc_sha384_final(isc_uint8_t digest[], isc_sha384_t *context) {
+ isc_uint64_t *d = (isc_uint64_t*)digest;
+
+ /* 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) {
+ isc_sha512_last((isc_sha512_t *)context);
+
+ /* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ for (j = 0; j < 6; j++) {
+ REVERSE64(context->state[j],context->state[j]);
+ *d++ = context->state[j];
+ }
+ }
+#else
+ memcpy(d, context->state, ISC_SHA384_DIGESTLENGTH);
+#endif
+ }
+
+ /* Zero out state data */
+ memset(context, 0, sizeof(context));
+}
+
+char *
+isc_sha384_end(isc_sha384_t *context, char buffer[]) {
+ isc_uint8_t digest[ISC_SHA384_DIGESTLENGTH], *d = digest;
+ unsigned int i;
+
+ /* Sanity check: */
+ REQUIRE(context != (isc_sha384_t *)0);
+
+ if (buffer != (char*)0) {
+ isc_sha384_final(digest, context);
+
+ for (i = 0; i < ISC_SHA384_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_SHA384_DIGESTLENGTH);
+ return buffer;
+}
+
+char*
+isc_sha384_data(const isc_uint8_t *data, size_t len,
+ char digest[ISC_SHA384_DIGESTSTRINGLENGTH])
+{
+ isc_sha384_t context;
+
+ isc_sha384_init(&context);
+ isc_sha384_update(&context, data, len);
+ return (isc_sha384_end(&context, digest));
+}
diff --git a/lib/isc/sockaddr.c b/lib/isc/sockaddr.c
new file mode 100644
index 0000000..62975df
--- /dev/null
+++ b/lib/isc/sockaddr.c
@@ -0,0 +1,503 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: sockaddr.c,v 1.70 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/buffer.h>
+#include <isc/hash.h>
+#include <isc/msgs.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+isc_boolean_t
+isc_sockaddr_equal(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
+ return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
+ ISC_SOCKADDR_CMPPORT|
+ ISC_SOCKADDR_CMPSCOPE));
+}
+
+isc_boolean_t
+isc_sockaddr_eqaddr(const isc_sockaddr_t *a, const isc_sockaddr_t *b) {
+ return (isc_sockaddr_compare(a, b, ISC_SOCKADDR_CMPADDR|
+ ISC_SOCKADDR_CMPSCOPE));
+}
+
+isc_boolean_t
+isc_sockaddr_compare(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
+ unsigned int flags)
+{
+ REQUIRE(a != NULL && b != NULL);
+
+ if (a->length != b->length)
+ return (ISC_FALSE);
+
+ /*
+ * We don't just memcmp because the sin_zero field isn't always
+ * zero.
+ */
+
+ if (a->type.sa.sa_family != b->type.sa.sa_family)
+ return (ISC_FALSE);
+ switch (a->type.sa.sa_family) {
+ case AF_INET:
+ if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
+ memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
+ sizeof(a->type.sin.sin_addr)) != 0)
+ return (ISC_FALSE);
+ if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
+ a->type.sin.sin_port != b->type.sin.sin_port)
+ return (ISC_FALSE);
+ break;
+ case AF_INET6:
+ if ((flags & ISC_SOCKADDR_CMPADDR) != 0 &&
+ memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
+ sizeof(a->type.sin6.sin6_addr)) != 0)
+ return (ISC_FALSE);
+#ifdef ISC_PLATFORM_HAVESCOPEID
+ /*
+ * If ISC_SOCKADDR_CMPSCOPEZERO is set then don't return
+ * ISC_FALSE if one of the scopes in zero.
+ */
+ if ((flags & ISC_SOCKADDR_CMPSCOPE) != 0 &&
+ a->type.sin6.sin6_scope_id != b->type.sin6.sin6_scope_id &&
+ ((flags & ISC_SOCKADDR_CMPSCOPEZERO) == 0 ||
+ (a->type.sin6.sin6_scope_id != 0 &&
+ b->type.sin6.sin6_scope_id != 0)))
+ return (ISC_FALSE);
+#endif
+ if ((flags & ISC_SOCKADDR_CMPPORT) != 0 &&
+ a->type.sin6.sin6_port != b->type.sin6.sin6_port)
+ return (ISC_FALSE);
+ break;
+ default:
+ if (memcmp(&a->type, &b->type, a->length) != 0)
+ return (ISC_FALSE);
+ }
+ return (ISC_TRUE);
+}
+
+isc_boolean_t
+isc_sockaddr_eqaddrprefix(const isc_sockaddr_t *a, const isc_sockaddr_t *b,
+ unsigned int prefixlen)
+{
+ isc_netaddr_t na, nb;
+ isc_netaddr_fromsockaddr(&na, a);
+ isc_netaddr_fromsockaddr(&nb, b);
+ return (isc_netaddr_eqprefix(&na, &nb, prefixlen));
+}
+
+isc_result_t
+isc_sockaddr_totext(const isc_sockaddr_t *sockaddr, isc_buffer_t *target) {
+ isc_result_t result;
+ isc_netaddr_t netaddr;
+ char pbuf[sizeof("65000")];
+ unsigned int plen;
+ isc_region_t avail;
+
+ REQUIRE(sockaddr != NULL);
+
+ /*
+ * Do the port first, giving us the opportunity to check for
+ * unsupported address families before calling
+ * isc_netaddr_fromsockaddr().
+ */
+ switch (sockaddr->type.sa.sa_family) {
+ case AF_INET:
+ snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin.sin_port));
+ break;
+ case AF_INET6:
+ snprintf(pbuf, sizeof(pbuf), "%u", ntohs(sockaddr->type.sin6.sin6_port));
+ break;
+#ifdef ISC_PLAFORM_HAVESYSUNH
+ case AF_UNIX:
+ plen = strlen(sockaddr->type.sunix.sun_path);
+ if (plen >= isc_buffer_availablelength(target))
+ return (ISC_R_NOSPACE);
+
+ isc_buffer_putmem(target, sockaddr->type.sunix.sun_path, plen);
+
+ /*
+ * Null terminate after used region.
+ */
+ isc_buffer_availableregion(target, &avail);
+ INSIST(avail.length >= 1);
+ avail.base[0] = '\0';
+
+ return (ISC_R_SUCCESS);
+#endif
+ default:
+ return (ISC_R_FAILURE);
+ }
+
+ plen = strlen(pbuf);
+ INSIST(plen < sizeof(pbuf));
+
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+ result = isc_netaddr_totext(&netaddr, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (1 + plen + 1 > isc_buffer_availablelength(target))
+ return (ISC_R_NOSPACE);
+
+ isc_buffer_putmem(target, (const unsigned char *)"#", 1);
+ isc_buffer_putmem(target, (const unsigned char *)pbuf, plen);
+
+ /*
+ * Null terminate after used region.
+ */
+ isc_buffer_availableregion(target, &avail);
+ INSIST(avail.length >= 1);
+ avail.base[0] = '\0';
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_sockaddr_format(const isc_sockaddr_t *sa, char *array, unsigned int size) {
+ isc_result_t result;
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, array, size);
+ result = isc_sockaddr_totext(sa, &buf);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * The message is the same as in netaddr.c.
+ */
+ snprintf(array, size,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
+ ISC_MSG_UNKNOWNADDR,
+ "<unknown address, family %u>"),
+ sa->type.sa.sa_family);
+ array[size - 1] = '\0';
+ }
+}
+
+unsigned int
+isc_sockaddr_hash(const isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
+ unsigned int length = 0;
+ const unsigned char *s = NULL;
+ unsigned int h = 0;
+ unsigned int g;
+ unsigned int p = 0;
+ const struct in6_addr *in6;
+
+ REQUIRE(sockaddr != NULL);
+
+ switch (sockaddr->type.sa.sa_family) {
+ case AF_INET:
+ s = (const unsigned char *)&sockaddr->type.sin.sin_addr;
+ p = ntohs(sockaddr->type.sin.sin_port);
+ length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
+ break;
+ case AF_INET6:
+ in6 = &sockaddr->type.sin6.sin6_addr;
+ if (IN6_IS_ADDR_V4MAPPED(in6)) {
+ s = (const unsigned char *)&in6[12];
+ length = sizeof(sockaddr->type.sin.sin_addr.s_addr);
+ } else {
+ s = (const unsigned char *)in6;
+ length = sizeof(sockaddr->type.sin6.sin6_addr);
+ }
+ p = ntohs(sockaddr->type.sin6.sin6_port);
+ break;
+ default:
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_SOCKADDR,
+ ISC_MSG_UNKNOWNFAMILY,
+ "unknown address family: %d"),
+ (int)sockaddr->type.sa.sa_family);
+ s = (const unsigned char *)&sockaddr->type;
+ length = sockaddr->length;
+ p = 0;
+ }
+
+ h = isc_hash_calc(s, length, ISC_TRUE);
+ if (!address_only) {
+ g = isc_hash_calc((const unsigned char *)&p, sizeof(p),
+ ISC_TRUE);
+ h = h ^ g; /* XXX: we should concatenate h and p first */
+ }
+
+ return (h);
+}
+
+void
+isc_sockaddr_any(isc_sockaddr_t *sockaddr)
+{
+ memset(sockaddr, 0, sizeof(*sockaddr));
+ sockaddr->type.sin.sin_family = AF_INET;
+#ifdef ISC_PLATFORM_HAVESALEN
+ sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
+#endif
+ sockaddr->type.sin.sin_addr.s_addr = INADDR_ANY;
+ sockaddr->type.sin.sin_port = 0;
+ sockaddr->length = sizeof(sockaddr->type.sin);
+ ISC_LINK_INIT(sockaddr, link);
+}
+
+void
+isc_sockaddr_any6(isc_sockaddr_t *sockaddr)
+{
+ memset(sockaddr, 0, sizeof(*sockaddr));
+ sockaddr->type.sin6.sin6_family = AF_INET6;
+#ifdef ISC_PLATFORM_HAVESALEN
+ sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
+#endif
+ sockaddr->type.sin6.sin6_addr = in6addr_any;
+ sockaddr->type.sin6.sin6_port = 0;
+ sockaddr->length = sizeof(sockaddr->type.sin6);
+ ISC_LINK_INIT(sockaddr, link);
+}
+
+void
+isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
+ in_port_t port)
+{
+ memset(sockaddr, 0, sizeof(*sockaddr));
+ sockaddr->type.sin.sin_family = AF_INET;
+#ifdef ISC_PLATFORM_HAVESALEN
+ sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
+#endif
+ sockaddr->type.sin.sin_addr = *ina;
+ sockaddr->type.sin.sin_port = htons(port);
+ sockaddr->length = sizeof(sockaddr->type.sin);
+ ISC_LINK_INIT(sockaddr, link);
+}
+
+void
+isc_sockaddr_anyofpf(isc_sockaddr_t *sockaddr, int pf) {
+ switch (pf) {
+ case AF_INET:
+ isc_sockaddr_any(sockaddr);
+ break;
+ case AF_INET6:
+ isc_sockaddr_any6(sockaddr);
+ break;
+ default:
+ INSIST(0);
+ }
+}
+
+void
+isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, const struct in6_addr *ina6,
+ in_port_t port)
+{
+ memset(sockaddr, 0, sizeof(*sockaddr));
+ sockaddr->type.sin6.sin6_family = AF_INET6;
+#ifdef ISC_PLATFORM_HAVESALEN
+ sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
+#endif
+ sockaddr->type.sin6.sin6_addr = *ina6;
+ sockaddr->type.sin6.sin6_port = htons(port);
+ sockaddr->length = sizeof(sockaddr->type.sin6);
+ ISC_LINK_INIT(sockaddr, link);
+}
+
+void
+isc_sockaddr_v6fromin(isc_sockaddr_t *sockaddr, const struct in_addr *ina,
+ in_port_t port)
+{
+ memset(sockaddr, 0, sizeof(*sockaddr));
+ sockaddr->type.sin6.sin6_family = AF_INET6;
+#ifdef ISC_PLATFORM_HAVESALEN
+ sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
+#endif
+ sockaddr->type.sin6.sin6_addr.s6_addr[10] = 0xff;
+ sockaddr->type.sin6.sin6_addr.s6_addr[11] = 0xff;
+ memcpy(&sockaddr->type.sin6.sin6_addr.s6_addr[12], ina, 4);
+ sockaddr->type.sin6.sin6_port = htons(port);
+ sockaddr->length = sizeof(sockaddr->type.sin6);
+ ISC_LINK_INIT(sockaddr, link);
+}
+
+int
+isc_sockaddr_pf(const isc_sockaddr_t *sockaddr) {
+
+ /*
+ * Get the protocol family of 'sockaddr'.
+ */
+
+#if (AF_INET == PF_INET && AF_INET6 == PF_INET6)
+ /*
+ * Assume that PF_xxx == AF_xxx for all AF and PF.
+ */
+ return (sockaddr->type.sa.sa_family);
+#else
+ switch (sockaddr->type.sa.sa_family) {
+ case AF_INET:
+ return (PF_INET);
+ case AF_INET6:
+ return (PF_INET6);
+ default:
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
+ ISC_MSG_UNKNOWNFAMILY,
+ "unknown address family: %d"),
+ (int)sockaddr->type.sa.sa_family);
+ }
+#endif
+}
+
+void
+isc_sockaddr_fromnetaddr(isc_sockaddr_t *sockaddr, const isc_netaddr_t *na,
+ in_port_t port)
+{
+ memset(sockaddr, 0, sizeof(*sockaddr));
+ sockaddr->type.sin.sin_family = na->family;
+ switch (na->family) {
+ case AF_INET:
+ sockaddr->length = sizeof(sockaddr->type.sin);
+#ifdef ISC_PLATFORM_HAVESALEN
+ sockaddr->type.sin.sin_len = sizeof(sockaddr->type.sin);
+#endif
+ sockaddr->type.sin.sin_addr = na->type.in;
+ sockaddr->type.sin.sin_port = htons(port);
+ break;
+ case AF_INET6:
+ sockaddr->length = sizeof(sockaddr->type.sin6);
+#ifdef ISC_PLATFORM_HAVESALEN
+ sockaddr->type.sin6.sin6_len = sizeof(sockaddr->type.sin6);
+#endif
+ memcpy(&sockaddr->type.sin6.sin6_addr, &na->type.in6, 16);
+#ifdef ISC_PLATFORM_HAVESCOPEID
+ sockaddr->type.sin6.sin6_scope_id = isc_netaddr_getzone(na);
+#endif
+ sockaddr->type.sin6.sin6_port = htons(port);
+ break;
+ default:
+ INSIST(0);
+ }
+ ISC_LINK_INIT(sockaddr, link);
+}
+
+void
+isc_sockaddr_setport(isc_sockaddr_t *sockaddr, in_port_t port) {
+ switch (sockaddr->type.sa.sa_family) {
+ case AF_INET:
+ sockaddr->type.sin.sin_port = htons(port);
+ break;
+ case AF_INET6:
+ sockaddr->type.sin6.sin6_port = htons(port);
+ break;
+ default:
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
+ ISC_MSG_UNKNOWNFAMILY,
+ "unknown address family: %d"),
+ (int)sockaddr->type.sa.sa_family);
+ }
+}
+
+in_port_t
+isc_sockaddr_getport(const isc_sockaddr_t *sockaddr) {
+ in_port_t port = 0;
+
+ switch (sockaddr->type.sa.sa_family) {
+ case AF_INET:
+ port = ntohs(sockaddr->type.sin.sin_port);
+ break;
+ case AF_INET6:
+ port = ntohs(sockaddr->type.sin6.sin6_port);
+ break;
+ default:
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKADDR,
+ ISC_MSG_UNKNOWNFAMILY,
+ "unknown address family: %d"),
+ (int)sockaddr->type.sa.sa_family);
+ }
+
+ return (port);
+}
+
+isc_boolean_t
+isc_sockaddr_ismulticast(const isc_sockaddr_t *sockaddr) {
+ isc_netaddr_t netaddr;
+
+ if (sockaddr->type.sa.sa_family == AF_INET ||
+ sockaddr->type.sa.sa_family == AF_INET6) {
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+ return (isc_netaddr_ismulticast(&netaddr));
+ }
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+isc_sockaddr_isexperimental(const isc_sockaddr_t *sockaddr) {
+ isc_netaddr_t netaddr;
+
+ if (sockaddr->type.sa.sa_family == AF_INET) {
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+ return (isc_netaddr_isexperimental(&netaddr));
+ }
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+isc_sockaddr_issitelocal(const isc_sockaddr_t *sockaddr) {
+ isc_netaddr_t netaddr;
+
+ if (sockaddr->type.sa.sa_family == AF_INET6) {
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+ return (isc_netaddr_issitelocal(&netaddr));
+ }
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+isc_sockaddr_islinklocal(const isc_sockaddr_t *sockaddr) {
+ isc_netaddr_t netaddr;
+
+ if (sockaddr->type.sa.sa_family == AF_INET6) {
+ isc_netaddr_fromsockaddr(&netaddr, sockaddr);
+ return (isc_netaddr_islinklocal(&netaddr));
+ }
+ return (ISC_FALSE);
+}
+
+isc_result_t
+isc_sockaddr_frompath(isc_sockaddr_t *sockaddr, const char *path) {
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ if (strlen(path) >= sizeof(sockaddr->type.sunix.sun_path))
+ return (ISC_R_NOSPACE);
+ memset(sockaddr, 0, sizeof(*sockaddr));
+ sockaddr->length = sizeof(sockaddr->type.sunix);
+ sockaddr->type.sunix.sun_family = AF_UNIX;
+#ifdef ISC_PLATFORM_HAVESALEN
+ sockaddr->type.sunix.sun_len =
+ (unsigned char)sizeof(sockaddr->type.sunix);
+#endif
+ strcpy(sockaddr->type.sunix.sun_path, path);
+ return (ISC_R_SUCCESS);
+#else
+ UNUSED(sockaddr);
+ UNUSED(path);
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
diff --git a/lib/isc/sparc64/Makefile.in b/lib/isc/sparc64/Makefile.in
new file mode 100644
index 0000000..324db07
--- /dev/null
+++ b/lib/isc/sparc64/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = include
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/sparc64/include/Makefile.in b/lib/isc/sparc64/include/Makefile.in
new file mode 100644
index 0000000..f1d8bdd
--- /dev/null
+++ b/lib/isc/sparc64/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/sparc64/include/isc/Makefile.in b/lib/isc/sparc64/include/isc/Makefile.in
new file mode 100644
index 0000000..5f116ca
--- /dev/null
+++ b/lib/isc/sparc64/include/isc/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = atomic.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/sparc64/include/isc/atomic.h b/lib/isc/sparc64/include/isc/atomic.h
new file mode 100644
index 0000000..5533ddb
--- /dev/null
+++ b/lib/isc/sparc64/include/isc/atomic.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2005, 2007 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: atomic.h,v 1.5 2007/06/19 23:47:18 tbox Exp $ */
+
+/*
+ * This code was written based on FreeBSD's kernel source whose copyright
+ * follows:
+ */
+
+/*-
+ * Copyright (c) 1998 Doug Rabson.
+ * Copyright (c) 2001 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: src/sys/i386/include/atomic.h,v 1.20 2001/02/11
+ * $FreeBSD: src/sys/sparc64/include/atomic.h,v 1.8 2004/05/22 00:52:16 marius Exp $
+ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#define ASI_P 0x80 /* Primary Address Space Identifier */
+
+#ifdef ISC_PLATFORM_USEGCCASM
+
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ */
+static inline isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+ isc_int32_t prev, swapped;
+
+ for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) {
+ swapped = prev + val;
+ __asm__ volatile(
+ "casa [%1] %2, %3, %0"
+ : "+r"(swapped)
+ : "r"(p), "n"(ASI_P), "r"(prev));
+ if (swapped == prev)
+ break;
+ }
+
+ return (prev);
+}
+
+/*
+ * This routine atomically stores the value 'val' in 'p'.
+ */
+static inline void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+ isc_int32_t prev, swapped;
+
+ for (prev = *(volatile isc_int32_t *)p; ; prev = swapped) {
+ swapped = val;
+ __asm__ volatile(
+ "casa [%1] %2, %3, %0"
+ : "+r"(swapped)
+ : "r"(p), "n"(ASI_P), "r"(prev)
+ : "memory");
+ if (swapped == prev)
+ break;
+ }
+}
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'. The original value is returned in any
+ * case.
+ */
+static inline isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+ isc_int32_t temp = val;
+
+ __asm__ volatile(
+ "casa [%1] %2, %3, %0"
+ : "+r"(temp)
+ : "r"(p), "n"(ASI_P), "r"(cmpval));
+
+ return (temp);
+}
+
+#else /* ISC_PLATFORM_USEGCCASM */
+
+#error "unsupported compiler. disable atomic ops by --disable-atomic"
+
+#endif /* ISC_PLATFORM_USEGCCASM */
+
+#endif /* ISC_ATOMIC_H */
diff --git a/lib/isc/string.c b/lib/isc/string.c
new file mode 100644
index 0000000..b9c43e7
--- /dev/null
+++ b/lib/isc/string.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2004-2007 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
+ * 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: string.c,v 1.20 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+static char digits[] = "0123456789abcdefghijklmnoprstuvwxyz";
+
+isc_uint64_t
+isc_string_touint64(char *source, char **end, int base) {
+ isc_uint64_t tmp;
+ isc_uint64_t overflow;
+ char *s = source;
+ char *o;
+ char c;
+
+ if ((base < 0) || (base == 1) || (base > 36)) {
+ *end = source;
+ return (0);
+ }
+
+ while (*s != 0 && isascii(*s&0xff) && isspace(*s&0xff))
+ s++;
+ if (*s == '+' /* || *s == '-' */)
+ s++;
+ if (base == 0) {
+ if (*s == '0' && (*(s+1) == 'X' || *(s+1) == 'x')) {
+ s += 2;
+ base = 16;
+ } else if (*s == '0')
+ base = 8;
+ else
+ base = 10;
+ }
+ if (*s == 0) {
+ *end = source;
+ return (0);
+ }
+ overflow = ~0;
+ overflow /= base;
+ tmp = 0;
+
+ while ((c = *s) != 0) {
+ c = tolower(c&0xff);
+ /* end ? */
+ if ((o = strchr(digits, c)) == NULL) {
+ *end = s;
+ return (tmp);
+ }
+ /* end ? */
+ if ((o - digits) >= base) {
+ *end = s;
+ return (tmp);
+ }
+ /* overflow ? */
+ if (tmp > overflow) {
+ *end = source;
+ return (0);
+ }
+ tmp *= base;
+ /* overflow ? */
+ if ((tmp + (o - digits)) < tmp) {
+ *end = source;
+ return (0);
+ }
+ tmp += o - digits;
+ s++;
+ }
+ *end = s;
+ return (tmp);
+}
+
+isc_result_t
+isc_string_copy(char *target, size_t size, const char *source) {
+ REQUIRE(size > 0U);
+
+ if (strlcpy(target, source, size) >= size) {
+ memset(target, ISC_STRING_MAGIC, size);
+ return (ISC_R_NOSPACE);
+ }
+
+ ENSURE(strlen(target) < size);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_string_copy_truncate(char *target, size_t size, const char *source) {
+ REQUIRE(size > 0U);
+
+ strlcpy(target, source, size);
+
+ ENSURE(strlen(target) < size);
+}
+
+isc_result_t
+isc_string_append(char *target, size_t size, const char *source) {
+ REQUIRE(size > 0U);
+ REQUIRE(strlen(target) < size);
+
+ if (strlcat(target, source, size) >= size) {
+ memset(target, ISC_STRING_MAGIC, size);
+ return (ISC_R_NOSPACE);
+ }
+
+ ENSURE(strlen(target) < size);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_string_append_truncate(char *target, size_t size, const char *source) {
+ REQUIRE(size > 0U);
+ REQUIRE(strlen(target) < size);
+
+ strlcat(target, source, size);
+
+ ENSURE(strlen(target) < size);
+}
+
+isc_result_t
+isc_string_printf(char *target, size_t size, const char *format, ...) {
+ va_list args;
+ size_t n;
+
+ REQUIRE(size > 0U);
+
+ va_start(args, format);
+ n = vsnprintf(target, size, format, args);
+ va_end(args);
+
+ if (n >= size) {
+ memset(target, ISC_STRING_MAGIC, size);
+ return (ISC_R_NOSPACE);
+ }
+
+ ENSURE(strlen(target) < size);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_string_printf_truncate(char *target, size_t size, const char *format, ...) {
+ va_list args;
+ size_t n;
+
+ REQUIRE(size > 0U);
+
+ va_start(args, format);
+ n = vsnprintf(target, size, format, args);
+ va_end(args);
+
+ ENSURE(strlen(target) < size);
+}
+
+char *
+isc_string_regiondup(isc_mem_t *mctx, const isc_region_t *source) {
+ char *target;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(source != NULL);
+
+ target = (char *) isc_mem_allocate(mctx, source->length + 1);
+ if (target != NULL) {
+ memcpy(source->base, target, source->length);
+ target[source->length] = '\0';
+ }
+
+ return (target);
+}
+
+char *
+isc_string_separate(char **stringp, const char *delim) {
+ char *string = *stringp;
+ char *s;
+ const char *d;
+ char sc, dc;
+
+ if (string == NULL)
+ return (NULL);
+
+ for (s = string; (sc = *s) != '\0'; s++)
+ for (d = delim; (dc = *d) != '\0'; d++)
+ if (sc == dc) {
+ *s++ = '\0';
+ *stringp = s;
+ return (string);
+ }
+ *stringp = NULL;
+ return (string);
+}
+
+size_t
+isc_string_strlcpy(char *dst, const char *src, size_t size)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = size;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0U && --n != 0U) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0U);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0U) {
+ if (size != 0U)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
+
+size_t
+isc_string_strlcat(char *dst, const char *src, size_t size)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = size;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0U && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = size - dlen;
+
+ if (n == 0U)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1U) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
diff --git a/lib/isc/strtoul.c b/lib/isc/strtoul.c
new file mode 100644
index 0000000..18d93e2
--- /dev/null
+++ b/lib/isc/strtoul.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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.
+ */
+
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*! \file */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+/* $Id: strtoul.c,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <isc/stdlib.h>
+#include <isc/util.h>
+
+/*!
+ * Convert a string to an unsigned long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long
+isc_strtoul(const char *nptr, char **endptr, int base) {
+ const char *s = nptr;
+ unsigned long acc;
+ unsigned char c;
+ unsigned long cutoff;
+ int neg = 0, any, cutlim;
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
+ cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ DE_CONST(any ? s - 1 : nptr, *endptr);
+ return (acc);
+}
diff --git a/lib/isc/symtab.c b/lib/isc/symtab.c
new file mode 100644
index 0000000..9f8e798
--- /dev/null
+++ b/lib/isc/symtab.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1996-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: symtab.c,v 1.30 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/string.h>
+#include <isc/symtab.h>
+#include <isc/util.h>
+
+typedef struct elt {
+ char * key;
+ unsigned int type;
+ isc_symvalue_t value;
+ LINK(struct elt) link;
+} elt_t;
+
+typedef LIST(elt_t) eltlist_t;
+
+#define SYMTAB_MAGIC ISC_MAGIC('S', 'y', 'm', 'T')
+#define VALID_SYMTAB(st) ISC_MAGIC_VALID(st, SYMTAB_MAGIC)
+
+struct isc_symtab {
+ /* Unlocked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ unsigned int size;
+ eltlist_t * table;
+ isc_symtabaction_t undefine_action;
+ void * undefine_arg;
+ isc_boolean_t case_sensitive;
+};
+
+isc_result_t
+isc_symtab_create(isc_mem_t *mctx, unsigned int size,
+ isc_symtabaction_t undefine_action,
+ void *undefine_arg,
+ isc_boolean_t case_sensitive,
+ isc_symtab_t **symtabp)
+{
+ isc_symtab_t *symtab;
+ unsigned int i;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(symtabp != NULL && *symtabp == NULL);
+ REQUIRE(size > 0); /* Should be prime. */
+
+ symtab = (isc_symtab_t *)isc_mem_get(mctx, sizeof(*symtab));
+ if (symtab == NULL)
+ return (ISC_R_NOMEMORY);
+ symtab->table = (eltlist_t *)isc_mem_get(mctx,
+ size * sizeof(eltlist_t));
+ if (symtab->table == NULL) {
+ isc_mem_put(mctx, symtab, sizeof(*symtab));
+ return (ISC_R_NOMEMORY);
+ }
+ for (i = 0; i < size; i++)
+ INIT_LIST(symtab->table[i]);
+ symtab->mctx = mctx;
+ symtab->size = size;
+ symtab->undefine_action = undefine_action;
+ symtab->undefine_arg = undefine_arg;
+ symtab->case_sensitive = case_sensitive;
+ symtab->magic = SYMTAB_MAGIC;
+
+ *symtabp = symtab;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_symtab_destroy(isc_symtab_t **symtabp) {
+ isc_symtab_t *symtab;
+ unsigned int i;
+ elt_t *elt, *nelt;
+
+ REQUIRE(symtabp != NULL);
+ symtab = *symtabp;
+ REQUIRE(VALID_SYMTAB(symtab));
+
+ for (i = 0; i < symtab->size; i++) {
+ for (elt = HEAD(symtab->table[i]); elt != NULL; elt = nelt) {
+ nelt = NEXT(elt, link);
+ if (symtab->undefine_action != NULL)
+ (symtab->undefine_action)(elt->key,
+ elt->type,
+ elt->value,
+ symtab->undefine_arg);
+ isc_mem_put(symtab->mctx, elt, sizeof(*elt));
+ }
+ }
+ isc_mem_put(symtab->mctx, symtab->table,
+ symtab->size * sizeof(eltlist_t));
+ symtab->magic = 0;
+ isc_mem_put(symtab->mctx, symtab, sizeof(*symtab));
+
+ *symtabp = NULL;
+}
+
+static inline unsigned int
+hash(const char *key, isc_boolean_t case_sensitive) {
+ const char *s;
+ unsigned int h = 0;
+ int c;
+
+ /*
+ * This hash function is similar to the one Ousterhout
+ * uses in Tcl.
+ */
+
+ if (case_sensitive) {
+ for (s = key; *s != '\0'; s++) {
+ h += (h << 3) + *s;
+ }
+ } else {
+ for (s = key; *s != '\0'; s++) {
+ c = *s;
+ c = tolower((unsigned char)c);
+ h += (h << 3) + c;
+ }
+ }
+
+ return (h);
+}
+
+#define FIND(s, k, t, b, e) \
+ b = hash((k), (s)->case_sensitive) % (s)->size; \
+ if ((s)->case_sensitive) { \
+ for (e = HEAD((s)->table[b]); e != NULL; e = NEXT(e, link)) { \
+ if (((t) == 0 || e->type == (t)) && \
+ strcmp(e->key, (k)) == 0) \
+ break; \
+ } \
+ } else { \
+ for (e = HEAD((s)->table[b]); e != NULL; e = NEXT(e, link)) { \
+ if (((t) == 0 || e->type == (t)) && \
+ strcasecmp(e->key, (k)) == 0) \
+ break; \
+ } \
+ }
+
+isc_result_t
+isc_symtab_lookup(isc_symtab_t *symtab, const char *key, unsigned int type,
+ isc_symvalue_t *value)
+{
+ unsigned int bucket;
+ elt_t *elt;
+
+ REQUIRE(VALID_SYMTAB(symtab));
+ REQUIRE(key != NULL);
+
+ FIND(symtab, key, type, bucket, elt);
+
+ if (elt == NULL)
+ return (ISC_R_NOTFOUND);
+
+ if (value != NULL)
+ *value = elt->value;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_symtab_define(isc_symtab_t *symtab, const char *key, unsigned int type,
+ isc_symvalue_t value, isc_symexists_t exists_policy)
+{
+ unsigned int bucket;
+ elt_t *elt;
+
+ REQUIRE(VALID_SYMTAB(symtab));
+ REQUIRE(key != NULL);
+ REQUIRE(type != 0);
+
+ FIND(symtab, key, type, bucket, elt);
+
+ if (exists_policy != isc_symexists_add && elt != NULL) {
+ if (exists_policy == isc_symexists_reject)
+ return (ISC_R_EXISTS);
+ INSIST(exists_policy == isc_symexists_replace);
+ UNLINK(symtab->table[bucket], elt, link);
+ if (symtab->undefine_action != NULL)
+ (symtab->undefine_action)(elt->key, elt->type,
+ elt->value,
+ symtab->undefine_arg);
+ } else {
+ elt = (elt_t *)isc_mem_get(symtab->mctx, sizeof(*elt));
+ if (elt == NULL)
+ return (ISC_R_NOMEMORY);
+ ISC_LINK_INIT(elt, link);
+ }
+
+ /*
+ * Though the "key" can be const coming in, it is not stored as const
+ * so that the calling program can easily have writable access to
+ * it in its undefine_action function. In the event that it *was*
+ * truly const coming in and then the caller modified it anyway ...
+ * well, don't do that!
+ */
+ DE_CONST(key, elt->key);
+ elt->type = type;
+ elt->value = value;
+
+ /*
+ * We prepend so that the most recent definition will be found.
+ */
+ PREPEND(symtab->table[bucket], elt, link);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_symtab_undefine(isc_symtab_t *symtab, const char *key, unsigned int type) {
+ unsigned int bucket;
+ elt_t *elt;
+
+ REQUIRE(VALID_SYMTAB(symtab));
+ REQUIRE(key != NULL);
+
+ FIND(symtab, key, type, bucket, elt);
+
+ if (elt == NULL)
+ return (ISC_R_NOTFOUND);
+
+ if (symtab->undefine_action != NULL)
+ (symtab->undefine_action)(elt->key, elt->type,
+ elt->value, symtab->undefine_arg);
+ UNLINK(symtab->table[bucket], elt, link);
+ isc_mem_put(symtab->mctx, elt, sizeof(*elt));
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/task.c b/lib/isc/task.c
new file mode 100644
index 0000000..a630173
--- /dev/null
+++ b/lib/isc/task.c
@@ -0,0 +1,1376 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: task.c,v 1.107 2008/03/27 23:46:57 tbox Exp $ */
+
+/*! \file
+ * \author Principal Author: Bob Halley
+ */
+
+/*
+ * XXXRTH Need to document the states a task can be in, and the rules
+ * for changing states.
+ */
+
+#include <config.h>
+
+#include <isc/condition.h>
+#include <isc/event.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/platform.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+#include <isc/xml.h>
+
+#ifndef ISC_PLATFORM_USETHREADS
+#include "task_p.h"
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#ifdef ISC_TASK_TRACE
+#define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \
+ task, isc_thread_self(), (m))
+#define XTTRACE(t, m) fprintf(stderr, "task %p thread %lu: %s\n", \
+ (t), isc_thread_self(), (m))
+#define XTHREADTRACE(m) fprintf(stderr, "thread %lu: %s\n", \
+ isc_thread_self(), (m))
+#else
+#define XTRACE(m)
+#define XTTRACE(t, m)
+#define XTHREADTRACE(m)
+#endif
+
+/***
+ *** Types.
+ ***/
+
+typedef enum {
+ task_state_idle, task_state_ready, task_state_running,
+ task_state_done
+} task_state_t;
+
+#ifdef HAVE_LIBXML2
+static const char *statenames[] = {
+ "idle", "ready", "running", "done",
+};
+#endif
+
+#define TASK_MAGIC ISC_MAGIC('T', 'A', 'S', 'K')
+#define VALID_TASK(t) ISC_MAGIC_VALID(t, TASK_MAGIC)
+
+struct isc_task {
+ /* Not locked. */
+ unsigned int magic;
+ isc_taskmgr_t * manager;
+ isc_mutex_t lock;
+ /* Locked by task lock. */
+ task_state_t state;
+ unsigned int references;
+ isc_eventlist_t events;
+ isc_eventlist_t on_shutdown;
+ unsigned int quantum;
+ unsigned int flags;
+ isc_stdtime_t now;
+ char name[16];
+ void * tag;
+ /* Locked by task manager lock. */
+ LINK(isc_task_t) link;
+ LINK(isc_task_t) ready_link;
+};
+
+#define TASK_F_SHUTTINGDOWN 0x01
+
+#define TASK_SHUTTINGDOWN(t) (((t)->flags & TASK_F_SHUTTINGDOWN) \
+ != 0)
+
+#define TASK_MANAGER_MAGIC ISC_MAGIC('T', 'S', 'K', 'M')
+#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, TASK_MANAGER_MAGIC)
+
+struct isc_taskmgr {
+ /* Not locked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ isc_mutex_t lock;
+#ifdef ISC_PLATFORM_USETHREADS
+ unsigned int workers;
+ isc_thread_t * threads;
+#endif /* ISC_PLATFORM_USETHREADS */
+ /* Locked by task manager lock. */
+ unsigned int default_quantum;
+ LIST(isc_task_t) tasks;
+ isc_tasklist_t ready_tasks;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_condition_t work_available;
+ isc_condition_t exclusive_granted;
+#endif /* ISC_PLATFORM_USETHREADS */
+ unsigned int tasks_running;
+ isc_boolean_t exclusive_requested;
+ isc_boolean_t exiting;
+#ifndef ISC_PLATFORM_USETHREADS
+ unsigned int refs;
+#endif /* ISC_PLATFORM_USETHREADS */
+};
+
+#define DEFAULT_TASKMGR_QUANTUM 10
+#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 */
+
+/***
+ *** Tasks.
+ ***/
+
+static void
+task_finished(isc_task_t *task) {
+ isc_taskmgr_t *manager = task->manager;
+
+ REQUIRE(EMPTY(task->events));
+ REQUIRE(EMPTY(task->on_shutdown));
+ REQUIRE(task->references == 0);
+ REQUIRE(task->state == task_state_done);
+
+ XTRACE("task_finished");
+
+ LOCK(&manager->lock);
+ UNLINK(manager->tasks, task, link);
+#ifdef ISC_PLATFORM_USETHREADS
+ if (FINISHED(manager)) {
+ /*
+ * All tasks have completed and the
+ * task manager is exiting. Wake up
+ * any idle worker threads so they
+ * can exit.
+ */
+ BROADCAST(&manager->work_available);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+ UNLOCK(&manager->lock);
+
+ DESTROYLOCK(&task->lock);
+ task->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_task_t *task;
+ isc_boolean_t exiting;
+ isc_result_t result;
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(taskp != NULL && *taskp == NULL);
+
+ task = isc_mem_get(manager->mctx, sizeof(*task));
+ if (task == NULL)
+ return (ISC_R_NOMEMORY);
+ XTRACE("isc_task_create");
+ task->manager = manager;
+ result = isc_mutex_init(&task->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(manager->mctx, task, sizeof(*task));
+ return (result);
+ }
+ task->state = task_state_idle;
+ task->references = 1;
+ INIT_LIST(task->events);
+ INIT_LIST(task->on_shutdown);
+ task->quantum = quantum;
+ task->flags = 0;
+ task->now = 0;
+ memset(task->name, 0, sizeof(task->name));
+ task->tag = NULL;
+ INIT_LINK(task, link);
+ INIT_LINK(task, ready_link);
+
+ exiting = ISC_FALSE;
+ LOCK(&manager->lock);
+ if (!manager->exiting) {
+ if (task->quantum == 0)
+ task->quantum = manager->default_quantum;
+ APPEND(manager->tasks, task, link);
+ } else
+ exiting = ISC_TRUE;
+ UNLOCK(&manager->lock);
+
+ if (exiting) {
+ DESTROYLOCK(&task->lock);
+ isc_mem_put(manager->mctx, task, sizeof(*task));
+ return (ISC_R_SHUTTINGDOWN);
+ }
+
+ task->magic = TASK_MAGIC;
+ *taskp = task;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_task_attach(isc_task_t *source, isc_task_t **targetp) {
+
+ /*
+ * Attach *targetp to source.
+ */
+
+ REQUIRE(VALID_TASK(source));
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ XTTRACE(source, "isc_task_attach");
+
+ LOCK(&source->lock);
+ source->references++;
+ UNLOCK(&source->lock);
+
+ *targetp = source;
+}
+
+static inline isc_boolean_t
+task_shutdown(isc_task_t *task) {
+ isc_boolean_t was_idle = ISC_FALSE;
+ isc_event_t *event, *prev;
+
+ /*
+ * Caller must be holding the task's lock.
+ */
+
+ XTRACE("task_shutdown");
+
+ if (! TASK_SHUTTINGDOWN(task)) {
+ XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_SHUTTINGDOWN, "shutting down"));
+ task->flags |= TASK_F_SHUTTINGDOWN;
+ if (task->state == task_state_idle) {
+ INSIST(EMPTY(task->events));
+ task->state = task_state_ready;
+ was_idle = ISC_TRUE;
+ }
+ INSIST(task->state == task_state_ready ||
+ task->state == task_state_running);
+ /*
+ * Note that we post shutdown events LIFO.
+ */
+ for (event = TAIL(task->on_shutdown);
+ event != NULL;
+ event = prev) {
+ prev = PREV(event, ev_link);
+ DEQUEUE(task->on_shutdown, event, ev_link);
+ ENQUEUE(task->events, event, ev_link);
+ }
+ }
+
+ return (was_idle);
+}
+
+static inline void
+task_ready(isc_task_t *task) {
+ isc_taskmgr_t *manager = task->manager;
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(task->state == task_state_ready);
+
+ XTRACE("task_ready");
+
+ LOCK(&manager->lock);
+
+ ENQUEUE(manager->ready_tasks, task, ready_link);
+#ifdef ISC_PLATFORM_USETHREADS
+ SIGNAL(&manager->work_available);
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ UNLOCK(&manager->lock);
+}
+
+static inline isc_boolean_t
+task_detach(isc_task_t *task) {
+
+ /*
+ * Caller must be holding the task lock.
+ */
+
+ REQUIRE(task->references > 0);
+
+ XTRACE("detach");
+
+ task->references--;
+ if (task->references == 0 && task->state == task_state_idle) {
+ INSIST(EMPTY(task->events));
+ /*
+ * There are no references to this task, and no
+ * pending events. We could try to optimize and
+ * either initiate shutdown or clean up the task,
+ * depending on its state, but it's easier to just
+ * make the task ready and allow run() or the event
+ * loop to deal with shutting down and termination.
+ */
+ task->state = task_state_ready;
+ return (ISC_TRUE);
+ }
+
+ return (ISC_FALSE);
+}
+
+void
+isc_task_detach(isc_task_t **taskp) {
+ isc_task_t *task;
+ isc_boolean_t was_idle;
+
+ /*
+ * Detach *taskp from its task.
+ */
+
+ REQUIRE(taskp != NULL);
+ task = *taskp;
+ REQUIRE(VALID_TASK(task));
+
+ XTRACE("isc_task_detach");
+
+ LOCK(&task->lock);
+ was_idle = task_detach(task);
+ UNLOCK(&task->lock);
+
+ if (was_idle)
+ task_ready(task);
+
+ *taskp = NULL;
+}
+
+static inline isc_boolean_t
+task_send(isc_task_t *task, isc_event_t **eventp) {
+ isc_boolean_t was_idle = ISC_FALSE;
+ isc_event_t *event;
+
+ /*
+ * Caller must be holding the task lock.
+ */
+
+ REQUIRE(eventp != NULL);
+ event = *eventp;
+ REQUIRE(event != NULL);
+ REQUIRE(event->ev_type > 0);
+ REQUIRE(task->state != task_state_done);
+
+ XTRACE("task_send");
+
+ if (task->state == task_state_idle) {
+ was_idle = ISC_TRUE;
+ INSIST(EMPTY(task->events));
+ task->state = task_state_ready;
+ }
+ INSIST(task->state == task_state_ready ||
+ task->state == task_state_running);
+ ENQUEUE(task->events, event, ev_link);
+ *eventp = NULL;
+
+ return (was_idle);
+}
+
+void
+isc_task_send(isc_task_t *task, isc_event_t **eventp) {
+ isc_boolean_t was_idle;
+
+ /*
+ * Send '*event' to 'task'.
+ */
+
+ REQUIRE(VALID_TASK(task));
+
+ XTRACE("isc_task_send");
+
+ /*
+ * We're trying hard to hold locks for as short a time as possible.
+ * We're also trying to hold as few locks as possible. This is why
+ * some processing is deferred until after the lock is released.
+ */
+ LOCK(&task->lock);
+ was_idle = task_send(task, eventp);
+ UNLOCK(&task->lock);
+
+ if (was_idle) {
+ /*
+ * We need to add this task to the ready queue.
+ *
+ * We've waited until now to do it because making a task
+ * ready requires locking the manager. If we tried to do
+ * this while holding the task lock, we could deadlock.
+ *
+ * We've changed the state to ready, so no one else will
+ * be trying to add this task to the ready queue. The
+ * only way to leave the ready state is by executing the
+ * task. It thus doesn't matter if events are added,
+ * removed, or a shutdown is started in the interval
+ * between the time we released the task lock, and the time
+ * we add the task to the ready queue.
+ */
+ task_ready(task);
+ }
+}
+
+void
+isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
+ isc_boolean_t idle1, idle2;
+ isc_task_t *task;
+
+ /*
+ * Send '*event' to '*taskp' and then detach '*taskp' from its
+ * task.
+ */
+
+ REQUIRE(taskp != NULL);
+ task = *taskp;
+ REQUIRE(VALID_TASK(task));
+
+ XTRACE("isc_task_sendanddetach");
+
+ LOCK(&task->lock);
+ idle1 = task_send(task, eventp);
+ idle2 = task_detach(task);
+ UNLOCK(&task->lock);
+
+ /*
+ * If idle1, then idle2 shouldn't be true as well since we're holding
+ * the task lock, and thus the task cannot switch from ready back to
+ * idle.
+ */
+ INSIST(!(idle1 && idle2));
+
+ if (idle1 || idle2)
+ task_ready(task);
+
+ *taskp = NULL;
+}
+
+#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,
+ isc_eventtype_t last, void *tag,
+ isc_eventlist_t *events, isc_boolean_t purging)
+{
+ isc_event_t *event, *next_event;
+ unsigned int count = 0;
+
+ REQUIRE(VALID_TASK(task));
+ REQUIRE(last >= first);
+
+ XTRACE("dequeue_events");
+
+ /*
+ * Events matching 'sender', whose type is >= first and <= last, and
+ * whose tag is 'tag' will be dequeued. If 'purging', matching events
+ * which are marked as unpurgable will not be dequeued.
+ *
+ * sender == NULL means "any sender", and tag == NULL means "any tag".
+ */
+
+ LOCK(&task->lock);
+
+ for (event = HEAD(task->events); event != NULL; event = next_event) {
+ next_event = NEXT(event, ev_link);
+ if (event->ev_type >= first && event->ev_type <= last &&
+ (sender == NULL || event->ev_sender == sender) &&
+ (tag == NULL || event->ev_tag == tag) &&
+ (!purging || PURGE_OK(event))) {
+ DEQUEUE(task->events, event, ev_link);
+ ENQUEUE(*events, event, ev_link);
+ count++;
+ }
+ }
+
+ UNLOCK(&task->lock);
+
+ return (count);
+}
+
+unsigned int
+isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
+ isc_eventtype_t last, void *tag)
+{
+ unsigned int count;
+ isc_eventlist_t events;
+ isc_event_t *event, *next_event;
+
+ /*
+ * Purge events from a task's event queue.
+ */
+
+ XTRACE("isc_task_purgerange");
+
+ ISC_LIST_INIT(events);
+
+ count = dequeue_events(task, sender, first, last, tag, &events,
+ ISC_TRUE);
+
+ for (event = HEAD(events); event != NULL; event = next_event) {
+ next_event = NEXT(event, ev_link);
+ isc_event_free(&event);
+ }
+
+ /*
+ * Note that purging never changes the state of the task.
+ */
+
+ return (count);
+}
+
+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.
+ */
+
+ XTRACE("isc_task_purge");
+
+ return (isc_task_purgerange(task, sender, type, type, tag));
+}
+
+isc_boolean_t
+isc_task_purgeevent(isc_task_t *task, isc_event_t *event) {
+ isc_event_t *curr_event, *next_event;
+
+ /*
+ * Purge 'event' from a task's event queue.
+ *
+ * XXXRTH: WARNING: This method may be removed before beta.
+ */
+
+ REQUIRE(VALID_TASK(task));
+
+ /*
+ * If 'event' is on the task's event queue, it will be purged,
+ * unless it is marked as unpurgeable. 'event' does not have to be
+ * on the task's event queue; in fact, it can even be an invalid
+ * pointer. Purging only occurs if the event is actually on the task's
+ * event queue.
+ *
+ * Purging never changes the state of the task.
+ */
+
+ LOCK(&task->lock);
+ for (curr_event = HEAD(task->events);
+ curr_event != NULL;
+ curr_event = next_event) {
+ next_event = NEXT(curr_event, ev_link);
+ if (curr_event == event && PURGE_OK(event)) {
+ DEQUEUE(task->events, curr_event, ev_link);
+ break;
+ }
+ }
+ UNLOCK(&task->lock);
+
+ if (curr_event == NULL)
+ return (ISC_FALSE);
+
+ isc_event_free(&curr_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)
+{
+ /*
+ * Remove events from a task's event queue.
+ */
+
+ XTRACE("isc_task_unsendrange");
+
+ return (dequeue_events(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)
+{
+ /*
+ * Remove events from a task's event queue.
+ */
+
+ XTRACE("isc_task_unsend");
+
+ return (dequeue_events(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_boolean_t disallowed = ISC_FALSE;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_event_t *event;
+
+ /*
+ * Send a shutdown event with action 'action' and argument 'arg' when
+ * 'task' is shutdown.
+ */
+
+ REQUIRE(VALID_TASK(task));
+ REQUIRE(action != NULL);
+
+ event = isc_event_allocate(task->manager->mctx,
+ NULL,
+ ISC_TASKEVENT_SHUTDOWN,
+ action,
+ arg,
+ sizeof(*event));
+ if (event == NULL)
+ return (ISC_R_NOMEMORY);
+
+ LOCK(&task->lock);
+ if (TASK_SHUTTINGDOWN(task)) {
+ disallowed = ISC_TRUE;
+ result = ISC_R_SHUTTINGDOWN;
+ } else
+ ENQUEUE(task->on_shutdown, event, ev_link);
+ UNLOCK(&task->lock);
+
+ if (disallowed)
+ isc_mem_put(task->manager->mctx, event, sizeof(*event));
+
+ return (result);
+}
+
+void
+isc_task_shutdown(isc_task_t *task) {
+ isc_boolean_t was_idle;
+
+ /*
+ * Shutdown 'task'.
+ */
+
+ REQUIRE(VALID_TASK(task));
+
+ LOCK(&task->lock);
+ was_idle = task_shutdown(task);
+ UNLOCK(&task->lock);
+
+ if (was_idle)
+ task_ready(task);
+}
+
+void
+isc_task_destroy(isc_task_t **taskp) {
+
+ /*
+ * Destroy '*taskp'.
+ */
+
+ REQUIRE(taskp != NULL);
+
+ isc_task_shutdown(*taskp);
+ isc_task_detach(taskp);
+}
+
+void
+isc_task_setname(isc_task_t *task, const char *name, void *tag) {
+
+ /*
+ * Name 'task'.
+ */
+
+ REQUIRE(VALID_TASK(task));
+
+ LOCK(&task->lock);
+ memset(task->name, 0, sizeof(task->name));
+ strncpy(task->name, name, sizeof(task->name) - 1);
+ task->tag = tag;
+ UNLOCK(&task->lock);
+}
+
+const char *
+isc_task_getname(isc_task_t *task) {
+ return (task->name);
+}
+
+void *
+isc_task_gettag(isc_task_t *task) {
+ return (task->tag);
+}
+
+void
+isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) {
+ REQUIRE(VALID_TASK(task));
+ REQUIRE(t != NULL);
+
+ LOCK(&task->lock);
+
+ *t = task->now;
+
+ UNLOCK(&task->lock);
+}
+
+/***
+ *** Task Manager.
+ ***/
+static void
+dispatch(isc_taskmgr_t *manager) {
+ isc_task_t *task;
+#ifndef ISC_PLATFORM_USETHREADS
+ unsigned int total_dispatch_count = 0;
+ isc_tasklist_t ready_tasks;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ REQUIRE(VALID_MANAGER(manager));
+
+ /*
+ * Again we're trying to hold the lock for as short a time as possible
+ * and to do as little locking and unlocking as possible.
+ *
+ * In both while loops, the appropriate lock must be held before the
+ * while body starts. Code which acquired the lock at the top of
+ * the loop would be more readable, but would result in a lot of
+ * extra locking. Compare:
+ *
+ * Straightforward:
+ *
+ * LOCK();
+ * ...
+ * UNLOCK();
+ * while (expression) {
+ * LOCK();
+ * ...
+ * UNLOCK();
+ *
+ * Unlocked part here...
+ *
+ * LOCK();
+ * ...
+ * UNLOCK();
+ * }
+ *
+ * Note how if the loop continues we unlock and then immediately lock.
+ * For N iterations of the loop, this code does 2N+1 locks and 2N+1
+ * unlocks. Also note that the lock is not held when the while
+ * condition is tested, which may or may not be important, depending
+ * on the expression.
+ *
+ * As written:
+ *
+ * LOCK();
+ * while (expression) {
+ * ...
+ * UNLOCK();
+ *
+ * Unlocked part here...
+ *
+ * LOCK();
+ * ...
+ * }
+ * UNLOCK();
+ *
+ * For N iterations of the loop, this code does N+1 locks and N+1
+ * unlocks. The while expression is always protected by the lock.
+ */
+
+#ifndef ISC_PLATFORM_USETHREADS
+ ISC_LIST_INIT(ready_tasks);
+#endif
+ LOCK(&manager->lock);
+ while (!FINISHED(manager)) {
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * For reasons similar to those given in the comment in
+ * isc_task_send() above, it is safe for us to dequeue
+ * the task while only holding the manager lock, and then
+ * change the task to running state while only holding the
+ * task lock.
+ */
+ while ((EMPTY(manager->ready_tasks) ||
+ manager->exclusive_requested) &&
+ !FINISHED(manager))
+ {
+ XTHREADTRACE(isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_WAIT, "wait"));
+ WAIT(&manager->work_available, &manager->lock);
+ XTHREADTRACE(isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_TASK,
+ ISC_MSG_AWAKE, "awake"));
+ }
+#else /* ISC_PLATFORM_USETHREADS */
+ if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM ||
+ EMPTY(manager->ready_tasks))
+ break;
+#endif /* ISC_PLATFORM_USETHREADS */
+ XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK,
+ ISC_MSG_WORKING, "working"));
+
+ task = HEAD(manager->ready_tasks);
+ if (task != NULL) {
+ unsigned int dispatch_count = 0;
+ isc_boolean_t done = ISC_FALSE;
+ isc_boolean_t requeue = ISC_FALSE;
+ isc_boolean_t finished = ISC_FALSE;
+ isc_event_t *event;
+
+ INSIST(VALID_TASK(task));
+
+ /*
+ * Note we only unlock the manager lock if we actually
+ * have a task to do. We must reacquire the manager
+ * lock before exiting the 'if (task != NULL)' block.
+ */
+ DEQUEUE(manager->ready_tasks, task, ready_link);
+ manager->tasks_running++;
+ UNLOCK(&manager->lock);
+
+ LOCK(&task->lock);
+ INSIST(task->state == task_state_ready);
+ task->state = task_state_running;
+ XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_RUNNING, "running"));
+ isc_stdtime_get(&task->now);
+ do {
+ if (!EMPTY(task->events)) {
+ event = HEAD(task->events);
+ DEQUEUE(task->events, event, ev_link);
+
+ /*
+ * Execute the event action.
+ */
+ XTRACE(isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_TASK,
+ ISC_MSG_EXECUTE,
+ "execute action"));
+ if (event->ev_action != NULL) {
+ UNLOCK(&task->lock);
+ (event->ev_action)(task,event);
+ LOCK(&task->lock);
+ }
+ dispatch_count++;
+#ifndef ISC_PLATFORM_USETHREADS
+ total_dispatch_count++;
+#endif /* ISC_PLATFORM_USETHREADS */
+ }
+
+ if (task->references == 0 &&
+ EMPTY(task->events) &&
+ !TASK_SHUTTINGDOWN(task)) {
+ isc_boolean_t was_idle;
+
+ /*
+ * There are no references and no
+ * pending events for this task,
+ * which means it will not become
+ * runnable again via an external
+ * action (such as sending an event
+ * or detaching).
+ *
+ * We initiate shutdown to prevent
+ * it from becoming a zombie.
+ *
+ * We do this here instead of in
+ * the "if EMPTY(task->events)" block
+ * below because:
+ *
+ * If we post no shutdown events,
+ * we want the task to finish.
+ *
+ * If we did post shutdown events,
+ * will still want the task's
+ * quantum to be applied.
+ */
+ was_idle = task_shutdown(task);
+ INSIST(!was_idle);
+ }
+
+ if (EMPTY(task->events)) {
+ /*
+ * Nothing else to do for this task
+ * right now.
+ */
+ XTRACE(isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_TASK,
+ ISC_MSG_EMPTY,
+ "empty"));
+ if (task->references == 0 &&
+ TASK_SHUTTINGDOWN(task)) {
+ /*
+ * The task is done.
+ */
+ XTRACE(isc_msgcat_get(
+ isc_msgcat,
+ ISC_MSGSET_TASK,
+ ISC_MSG_DONE,
+ "done"));
+ finished = ISC_TRUE;
+ task->state = task_state_done;
+ } else
+ task->state = task_state_idle;
+ done = ISC_TRUE;
+ } else if (dispatch_count >= task->quantum) {
+ /*
+ * Our quantum has expired, but
+ * there is more work to be done.
+ * We'll requeue it to the ready
+ * queue later.
+ *
+ * We don't check quantum until
+ * dispatching at least one event,
+ * so the minimum quantum is one.
+ */
+ XTRACE(isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_TASK,
+ ISC_MSG_QUANTUM,
+ "quantum"));
+ task->state = task_state_ready;
+ requeue = ISC_TRUE;
+ done = ISC_TRUE;
+ }
+ } while (!done);
+ UNLOCK(&task->lock);
+
+ if (finished)
+ task_finished(task);
+
+ LOCK(&manager->lock);
+ manager->tasks_running--;
+#ifdef ISC_PLATFORM_USETHREADS
+ if (manager->exclusive_requested &&
+ manager->tasks_running == 1) {
+ SIGNAL(&manager->exclusive_granted);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+ if (requeue) {
+ /*
+ * We know we're awake, so we don't have
+ * to wakeup any sleeping threads if the
+ * ready queue is empty before we requeue.
+ *
+ * A possible optimization if the queue is
+ * empty is to 'goto' the 'if (task != NULL)'
+ * block, avoiding the ENQUEUE of the task
+ * and the subsequent immediate DEQUEUE
+ * (since it is the only executable task).
+ * We don't do this because then we'd be
+ * skipping the exit_requested check. The
+ * cost of ENQUEUE is low anyway, especially
+ * when you consider that we'd have to do
+ * an extra EMPTY check to see if we could
+ * do the optimization. If the ready queue
+ * were usually nonempty, the 'optimization'
+ * might even hurt rather than help.
+ */
+#ifdef ISC_PLATFORM_USETHREADS
+ ENQUEUE(manager->ready_tasks, task,
+ ready_link);
+#else
+ ENQUEUE(ready_tasks, task, ready_link);
+#endif
+ }
+ }
+ }
+#ifndef ISC_PLATFORM_USETHREADS
+ ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link);
+#endif
+ UNLOCK(&manager->lock);
+}
+
+#ifdef ISC_PLATFORM_USETHREADS
+static isc_threadresult_t
+#ifdef _WIN32
+WINAPI
+#endif
+run(void *uap) {
+ isc_taskmgr_t *manager = uap;
+
+ XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_STARTING, "starting"));
+
+ dispatch(manager);
+
+ XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_EXITING, "exiting"));
+
+ return ((isc_threadresult_t)0);
+}
+#endif /* ISC_PLATFORM_USETHREADS */
+
+static void
+manager_free(isc_taskmgr_t *manager) {
+ isc_mem_t *mctx;
+
+#ifdef ISC_PLATFORM_USETHREADS
+ (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 */
+ DESTROYLOCK(&manager->lock);
+ manager->magic = 0;
+ mctx = manager->mctx;
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ isc_mem_detach(&mctx);
+}
+
+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;
+
+ /*
+ * Create a new task manager.
+ */
+
+ REQUIRE(workers > 0);
+ REQUIRE(managerp != NULL && *managerp == NULL);
+
+#ifndef ISC_PLATFORM_USETHREADS
+ UNUSED(i);
+ UNUSED(started);
+ UNUSED(workers);
+
+ if (taskmgr != NULL) {
+ taskmgr->refs++;
+ *managerp = taskmgr;
+ return (ISC_R_SUCCESS);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ manager = isc_mem_get(mctx, sizeof(*manager));
+ if (manager == NULL)
+ return (ISC_R_NOMEMORY);
+ manager->magic = TASK_MANAGER_MAGIC;
+ manager->mctx = NULL;
+ result = isc_mutex_init(&manager->lock);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_mgr;
+
+#ifdef ISC_PLATFORM_USETHREADS
+ manager->workers = 0;
+ manager->threads = isc_mem_allocate(mctx,
+ workers * sizeof(isc_thread_t));
+ if (manager->threads == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_lock;
+ }
+ if (isc_condition_init(&manager->work_available) != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_condition_init() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup_threads;
+ }
+ if (isc_condition_init(&manager->exclusive_granted) != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_condition_init() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup_workavailable;
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+ if (default_quantum == 0)
+ default_quantum = DEFAULT_DEFAULT_QUANTUM;
+ manager->default_quantum = default_quantum;
+ INIT_LIST(manager->tasks);
+ INIT_LIST(manager->ready_tasks);
+ manager->tasks_running = 0;
+ manager->exclusive_requested = ISC_FALSE;
+ manager->exiting = ISC_FALSE;
+
+ isc_mem_attach(mctx, &manager->mctx);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ LOCK(&manager->lock);
+ /*
+ * Start workers.
+ */
+ for (i = 0; i < workers; i++) {
+ if (isc_thread_create(run, manager,
+ &manager->threads[manager->workers]) ==
+ ISC_R_SUCCESS) {
+ manager->workers++;
+ started++;
+ }
+ }
+ UNLOCK(&manager->lock);
+
+ if (started == 0) {
+ manager_free(manager);
+ return (ISC_R_NOTHREADS);
+ }
+ isc_thread_setconcurrency(workers);
+#else /* ISC_PLATFORM_USETHREADS */
+ manager->refs = 1;
+ taskmgr = manager;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ *managerp = manager;
+
+ return (ISC_R_SUCCESS);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ cleanup_workavailable:
+ (void)isc_condition_destroy(&manager->work_available);
+ cleanup_threads:
+ isc_mem_free(mctx, manager->threads);
+ cleanup_lock:
+ DESTROYLOCK(&manager->lock);
+#endif
+ cleanup_mgr:
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ return (result);
+}
+
+void
+isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
+ isc_taskmgr_t *manager;
+ isc_task_t *task;
+ unsigned int i;
+
+ /*
+ * Destroy '*managerp'.
+ */
+
+ REQUIRE(managerp != NULL);
+ manager = *managerp;
+ REQUIRE(VALID_MANAGER(manager));
+
+#ifndef ISC_PLATFORM_USETHREADS
+ UNUSED(i);
+
+ if (manager->refs > 1) {
+ manager->refs--;
+ *managerp = NULL;
+ return;
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ XTHREADTRACE("isc_taskmgr_destroy");
+ /*
+ * Only one non-worker thread may ever call this routine.
+ * If a worker thread wants to initiate shutdown of the
+ * task manager, it should ask some non-worker thread to call
+ * isc_taskmgr_destroy(), e.g. by signalling a condition variable
+ * that the startup thread is sleeping on.
+ */
+
+ /*
+ * Unlike elsewhere, we're going to hold this lock a long time.
+ * We need to do so, because otherwise the list of tasks could
+ * change while we were traversing it.
+ *
+ * This is also the only function where we will hold both the
+ * task manager lock and a task lock at the same time.
+ */
+
+ LOCK(&manager->lock);
+
+ /*
+ * Make sure we only get called once.
+ */
+ INSIST(!manager->exiting);
+ manager->exiting = ISC_TRUE;
+
+ /*
+ * Post shutdown event(s) to every task (if they haven't already been
+ * posted).
+ */
+ for (task = HEAD(manager->tasks);
+ task != NULL;
+ task = NEXT(task, link)) {
+ LOCK(&task->lock);
+ if (task_shutdown(task))
+ ENQUEUE(manager->ready_tasks, task, ready_link);
+ UNLOCK(&task->lock);
+ }
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * 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
+ * it will cause the workers to see manager->exiting.
+ */
+ BROADCAST(&manager->work_available);
+ UNLOCK(&manager->lock);
+
+ /*
+ * Wait for all the worker threads to exit.
+ */
+ for (i = 0; i < manager->workers; i++)
+ (void)isc_thread_join(manager->threads[i], NULL);
+#else /* ISC_PLATFORM_USETHREADS */
+ /*
+ * Dispatch the shutdown events.
+ */
+ UNLOCK(&manager->lock);
+ while (isc__taskmgr_ready())
+ (void)isc__taskmgr_dispatch();
+ if (!ISC_LIST_EMPTY(manager->tasks))
+ isc_mem_printallactive(stderr);
+ INSIST(ISC_LIST_EMPTY(manager->tasks));
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ manager_free(manager);
+
+ *managerp = NULL;
+}
+
+#ifndef ISC_PLATFORM_USETHREADS
+isc_boolean_t
+isc__taskmgr_ready(void) {
+ if (taskmgr == NULL)
+ return (ISC_FALSE);
+ return (ISC_TF(!ISC_LIST_EMPTY(taskmgr->ready_tasks)));
+}
+
+isc_result_t
+isc__taskmgr_dispatch(void) {
+ isc_taskmgr_t *manager = taskmgr;
+
+ if (taskmgr == NULL)
+ return (ISC_R_NOTFOUND);
+
+ dispatch(manager);
+
+ return (ISC_R_SUCCESS);
+}
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+isc_result_t
+isc_task_beginexclusive(isc_task_t *task) {
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_taskmgr_t *manager = task->manager;
+ REQUIRE(task->state == task_state_running);
+ LOCK(&manager->lock);
+ if (manager->exclusive_requested) {
+ UNLOCK(&manager->lock);
+ return (ISC_R_LOCKBUSY);
+ }
+ manager->exclusive_requested = ISC_TRUE;
+ while (manager->tasks_running > 1) {
+ WAIT(&manager->exclusive_granted, &manager->lock);
+ }
+ UNLOCK(&manager->lock);
+#else
+ UNUSED(task);
+#endif
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_task_endexclusive(isc_task_t *task) {
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_taskmgr_t *manager = task->manager;
+ REQUIRE(task->state == task_state_running);
+ LOCK(&manager->lock);
+ REQUIRE(manager->exclusive_requested);
+ manager->exclusive_requested = ISC_FALSE;
+ BROADCAST(&manager->work_available);
+ UNLOCK(&manager->lock);
+#else
+ UNUSED(task);
+#endif
+}
+
+#ifdef HAVE_LIBXML2
+
+void
+isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer)
+{
+ isc_task_t *task;
+
+ LOCK(&mgr->lock);
+
+ /*
+ * Write out the thread-model, and some details about each depending
+ * on which type is enabled.
+ */
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "thread-model");
+#ifdef ISC_PLATFORM_USETHREADS
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "type");
+ xmlTextWriterWriteString(writer, ISC_XMLCHAR "threaded");
+ xmlTextWriterEndElement(writer); /* type */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "worker-threads");
+ xmlTextWriterWriteFormatString(writer, "%d", mgr->workers);
+ xmlTextWriterEndElement(writer); /* worker-threads */
+#else /* ISC_PLATFORM_USETHREADS */
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "type");
+ xmlTextWriterWriteString(writer, ISC_XMLCHAR "non-threaded");
+ xmlTextWriterEndElement(writer); /* type */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+ xmlTextWriterWriteFormatString(writer, "%d", mgr->refs);
+ xmlTextWriterEndElement(writer); /* references */
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "default-quantum");
+ xmlTextWriterWriteFormatString(writer, "%d", mgr->default_quantum);
+ xmlTextWriterEndElement(writer); /* default-quantum */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks-running");
+ xmlTextWriterWriteFormatString(writer, "%d", mgr->tasks_running);
+ xmlTextWriterEndElement(writer); /* tasks-running */
+
+ xmlTextWriterEndElement(writer); /* thread-model */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks");
+ task = ISC_LIST_HEAD(mgr->tasks);
+ while (task != NULL) {
+ LOCK(&task->lock);
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "task");
+
+ if (task->name[0] != 0) {
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+ xmlTextWriterWriteFormatString(writer, "%s",
+ task->name);
+ xmlTextWriterEndElement(writer); /* name */
+ }
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+ xmlTextWriterWriteFormatString(writer, "%d", task->references);
+ xmlTextWriterEndElement(writer); /* references */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
+ xmlTextWriterWriteFormatString(writer, "%p", task);
+ xmlTextWriterEndElement(writer); /* id */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "state");
+ xmlTextWriterWriteFormatString(writer, "%s",
+ statenames[task->state]);
+ xmlTextWriterEndElement(writer); /* state */
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "quantum");
+ xmlTextWriterWriteFormatString(writer, "%d", task->quantum);
+ xmlTextWriterEndElement(writer); /* quantum */
+
+ xmlTextWriterEndElement(writer);
+
+ UNLOCK(&task->lock);
+ task = ISC_LIST_NEXT(task, link);
+ }
+ xmlTextWriterEndElement(writer); /* tasks */
+
+ UNLOCK(&mgr->lock);
+}
+#endif /* HAVE_LIBXML2 */
diff --git a/lib/isc/task_p.h b/lib/isc/task_p.h
new file mode 100644
index 0000000..c888103
--- /dev/null
+++ b/lib/isc/task_p.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: task_p.h,v 1.11 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef ISC_TASK_P_H
+#define ISC_TASK_P_H
+
+/*! \file */
+
+isc_boolean_t
+isc__taskmgr_ready(void);
+
+isc_result_t
+isc__taskmgr_dispatch(void);
+
+#endif /* ISC_TASK_P_H */
diff --git a/lib/isc/taskpool.c b/lib/isc/taskpool.c
new file mode 100644
index 0000000..d9c2fbe
--- /dev/null
+++ b/lib/isc/taskpool.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: taskpool.c,v 1.18 2007/06/18 23:47:44 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/taskpool.h>
+#include <isc/util.h>
+
+/***
+ *** Types.
+ ***/
+
+struct isc_taskpool {
+ isc_mem_t * mctx;
+ unsigned int ntasks;
+ isc_task_t ** tasks;
+};
+/***
+ *** Functions.
+ ***/
+
+isc_result_t
+isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx,
+ unsigned int ntasks, unsigned int quantum,
+ isc_taskpool_t **poolp)
+{
+ unsigned int i;
+ isc_taskpool_t *pool;
+ isc_result_t result;
+
+ INSIST(ntasks > 0);
+ pool = isc_mem_get(mctx, sizeof(*pool));
+ if (pool == NULL)
+ return (ISC_R_NOMEMORY);
+ pool->mctx = mctx;
+ pool->ntasks = ntasks;
+ pool->tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
+ if (pool->tasks == NULL) {
+ isc_mem_put(mctx, pool, sizeof(*pool));
+ return (ISC_R_NOMEMORY);
+ }
+ for (i = 0; i < ntasks; i++)
+ pool->tasks[i] = NULL;
+ for (i = 0; i < ntasks; i++) {
+ result = isc_task_create(tmgr, quantum, &pool->tasks[i]);
+ if (result != ISC_R_SUCCESS) {
+ isc_taskpool_destroy(&pool);
+ return (result);
+ }
+ isc_task_setname(pool->tasks[i], "taskpool", NULL);
+ }
+ *poolp = pool;
+ return (ISC_R_SUCCESS);
+}
+
+void isc_taskpool_gettask(isc_taskpool_t *pool, unsigned int hash,
+ isc_task_t **targetp)
+{
+ isc_task_attach(pool->tasks[hash % pool->ntasks], targetp);
+}
+
+void
+isc_taskpool_destroy(isc_taskpool_t **poolp) {
+ unsigned int i;
+ isc_taskpool_t *pool = *poolp;
+ for (i = 0; i < pool->ntasks; i++) {
+ if (pool->tasks[i] != NULL) {
+ isc_task_detach(&pool->tasks[i]);
+ }
+ }
+ isc_mem_put(pool->mctx, pool->tasks,
+ pool->ntasks * sizeof(isc_task_t *));
+ isc_mem_put(pool->mctx, pool, sizeof(*pool));
+ *poolp = NULL;
+}
+
+
diff --git a/lib/isc/timer.c b/lib/isc/timer.c
new file mode 100644
index 0000000..ca487cd
--- /dev/null
+++ b/lib/isc/timer.c
@@ -0,0 +1,932 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2002 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: timer.c,v 1.84 2008/08/22 05:57:53 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/condition.h>
+#include <isc/heap.h>
+#include <isc/log.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/platform.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/time.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#ifndef ISC_PLATFORM_USETHREADS
+#include "timer_p.h"
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#ifdef ISC_TIMER_TRACE
+#define XTRACE(s) fprintf(stderr, "%s\n", (s))
+#define XTRACEID(s, t) fprintf(stderr, "%s %p\n", (s), (t))
+#define XTRACETIME(s, d) fprintf(stderr, "%s %u.%09u\n", (s), \
+ (d).seconds, (d).nanoseconds)
+#define XTRACETIME2(s, d, n) fprintf(stderr, "%s %u.%09u %u.%09u\n", (s), \
+ (d).seconds, (d).nanoseconds, (n).seconds, (n).nanoseconds)
+#define XTRACETIMER(s, t, d) fprintf(stderr, "%s %p %u.%09u\n", (s), (t), \
+ (d).seconds, (d).nanoseconds)
+#else
+#define XTRACE(s)
+#define XTRACEID(s, t)
+#define XTRACETIME(s, d)
+#define XTRACETIME2(s, d, n)
+#define XTRACETIMER(s, t, d)
+#endif /* ISC_TIMER_TRACE */
+
+#define TIMER_MAGIC ISC_MAGIC('T', 'I', 'M', 'R')
+#define VALID_TIMER(t) ISC_MAGIC_VALID(t, TIMER_MAGIC)
+
+struct isc_timer {
+ /*! Not locked. */
+ unsigned int magic;
+ isc_timermgr_t * manager;
+ isc_mutex_t lock;
+ /*! Locked by timer lock. */
+ unsigned int references;
+ isc_time_t idle;
+ /*! Locked by manager lock. */
+ isc_timertype_t type;
+ isc_time_t expires;
+ isc_interval_t interval;
+ isc_task_t * task;
+ isc_taskaction_t action;
+ void * arg;
+ unsigned int index;
+ isc_time_t due;
+ 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 {
+ /* Not locked. */
+ unsigned int magic;
+ isc_mem_t * mctx;
+ isc_mutex_t lock;
+ /* Locked by manager lock. */
+ isc_boolean_t done;
+ LIST(isc_timer_t) timers;
+ unsigned int nscheduled;
+ isc_time_t due;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_condition_t wakeup;
+ isc_thread_t thread;
+#else /* ISC_PLATFORM_USETHREADS */
+ unsigned int refs;
+#endif /* ISC_PLATFORM_USETHREADS */
+ isc_heap_t * heap;
+};
+
+#ifndef ISC_PLATFORM_USETHREADS
+/*!
+ * If threads are not in use, there can be only one.
+ */
+static isc_timermgr_t *timermgr = NULL;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+static inline isc_result_t
+schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
+ isc_result_t result;
+ isc_timermgr_t *manager;
+ isc_time_t due;
+ int cmp;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_boolean_t timedwait;
+#endif
+
+ /*!
+ * Note: the caller must ensure locking.
+ */
+
+ REQUIRE(timer->type != isc_timertype_inactive);
+
+#ifndef ISC_PLATFORM_USETHREADS
+ UNUSED(signal_ok);
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ manager = timer->manager;
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /*!
+ * If the manager was timed wait, we may need to signal the
+ * manager to force a wakeup.
+ */
+ timedwait = ISC_TF(manager->nscheduled > 0 &&
+ isc_time_seconds(&manager->due) != 0);
+#endif
+
+ /*
+ * Compute the new due time.
+ */
+ if (timer->type != isc_timertype_once) {
+ result = isc_time_add(now, &timer->interval, &due);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (timer->type == isc_timertype_limited &&
+ isc_time_compare(&timer->expires, &due) < 0)
+ due = timer->expires;
+ } else {
+ if (isc_time_isepoch(&timer->idle))
+ due = timer->expires;
+ else if (isc_time_isepoch(&timer->expires))
+ due = timer->idle;
+ else if (isc_time_compare(&timer->idle, &timer->expires) < 0)
+ due = timer->idle;
+ else
+ due = timer->expires;
+ }
+
+ /*
+ * Schedule the timer.
+ */
+
+ if (timer->index > 0) {
+ /*
+ * Already scheduled.
+ */
+ cmp = isc_time_compare(&due, &timer->due);
+ timer->due = due;
+ switch (cmp) {
+ case -1:
+ isc_heap_increased(manager->heap, timer->index);
+ break;
+ case 1:
+ isc_heap_decreased(manager->heap, timer->index);
+ break;
+ case 0:
+ /* Nothing to do. */
+ break;
+ }
+ } else {
+ timer->due = due;
+ result = isc_heap_insert(manager->heap, timer);
+ if (result != ISC_R_SUCCESS) {
+ INSIST(result == ISC_R_NOMEMORY);
+ return (ISC_R_NOMEMORY);
+ }
+ manager->nscheduled++;
+ }
+
+ XTRACETIMER(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
+ ISC_MSG_SCHEDULE, "schedule"), timer, due);
+
+ /*
+ * If this timer is at the head of the queue, we need to ensure
+ * that we won't miss it if it has a more recent due time than
+ * 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
+
+ /*
+ * This is a temporary (probably) hack to fix a bug on tru64 5.1
+ * and 5.1a. Sometimes, pthread_cond_timedwait() doesn't actually
+ * return when the time expires, so here, we check to see if
+ * we're 15 seconds or more behind, and if we are, we signal
+ * the dispatcher. This isn't such a bad idea as a general purpose
+ * watchdog, so perhaps we should just leave it in here.
+ */
+ if (signal_ok && timedwait) {
+ isc_interval_t fifteen;
+ isc_time_t then;
+
+ isc_interval_set(&fifteen, 15, 0);
+ result = isc_time_add(&manager->due, &fifteen, &then);
+
+ if (result == ISC_R_SUCCESS &&
+ isc_time_compare(&then, now) < 0) {
+ SIGNAL(&manager->wakeup);
+ signal_ok = ISC_FALSE;
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_TIMER, ISC_LOG_WARNING,
+ "*** POKED TIMER ***");
+ }
+ }
+
+ if (timer->index == 1 && signal_ok) {
+ XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
+ ISC_MSG_SIGNALSCHED,
+ "signal (schedule)"));
+ SIGNAL(&manager->wakeup);
+ }
+#else /* ISC_PLATFORM_USETHREADS */
+ if (timer->index == 1 &&
+ isc_time_compare(&timer->due, &manager->due) < 0)
+ manager->due = timer->due;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+deschedule(isc_timer_t *timer) {
+ isc_boolean_t need_wakeup = ISC_FALSE;
+ isc_timermgr_t *manager;
+
+ /*
+ * The caller must ensure locking.
+ */
+
+ manager = timer->manager;
+ if (timer->index > 0) {
+ if (timer->index == 1)
+ need_wakeup = ISC_TRUE;
+ isc_heap_delete(manager->heap, timer->index);
+ timer->index = 0;
+ INSIST(manager->nscheduled > 0);
+ manager->nscheduled--;
+#ifdef ISC_PLATFORM_USETHREADS
+ if (need_wakeup) {
+ XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
+ ISC_MSG_SIGNALDESCHED,
+ "signal (deschedule)"));
+ SIGNAL(&manager->wakeup);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+ }
+}
+
+static void
+destroy(isc_timer_t *timer) {
+ isc_timermgr_t *manager = timer->manager;
+
+ /*
+ * The caller must ensure it is safe to destroy the timer.
+ */
+
+ LOCK(&manager->lock);
+
+ (void)isc_task_purgerange(timer->task,
+ timer,
+ ISC_TIMEREVENT_FIRSTEVENT,
+ ISC_TIMEREVENT_LASTEVENT,
+ NULL);
+ deschedule(timer);
+ UNLINK(manager->timers, timer, link);
+
+ UNLOCK(&manager->lock);
+
+ isc_task_detach(&timer->task);
+ DESTROYLOCK(&timer->lock);
+ timer->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_timer_t *timer;
+ isc_result_t result;
+ isc_time_t now;
+
+ /*
+ * Create a new 'type' timer managed by 'manager'. The timers
+ * parameters are specified by 'expires' and 'interval'. Events
+ * will be posted to 'task' and when dispatched 'action' will be
+ * called with 'arg' as the arg value. The new timer is returned
+ * in 'timerp'.
+ */
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+ if (expires == NULL)
+ expires = isc_time_epoch;
+ if (interval == NULL)
+ interval = isc_interval_zero;
+ REQUIRE(type == isc_timertype_inactive ||
+ !(isc_time_isepoch(expires) && isc_interval_iszero(interval)));
+ REQUIRE(timerp != NULL && *timerp == NULL);
+ REQUIRE(type != isc_timertype_limited ||
+ !(isc_time_isepoch(expires) || isc_interval_iszero(interval)));
+
+ /*
+ * Get current time.
+ */
+ if (type != isc_timertype_inactive) {
+ TIME_NOW(&now);
+ } else {
+ /*
+ * We don't have to do this, but it keeps the compiler from
+ * complaining about "now" possibly being used without being
+ * set, even though it will never actually happen.
+ */
+ isc_time_settoepoch(&now);
+ }
+
+
+ timer = isc_mem_get(manager->mctx, sizeof(*timer));
+ if (timer == NULL)
+ return (ISC_R_NOMEMORY);
+
+ timer->manager = manager;
+ timer->references = 1;
+
+ if (type == isc_timertype_once && !isc_interval_iszero(interval)) {
+ result = isc_time_add(&now, interval, &timer->idle);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(manager->mctx, timer, sizeof(*timer));
+ return (result);
+ }
+ } else
+ isc_time_settoepoch(&timer->idle);
+
+ timer->type = type;
+ timer->expires = *expires;
+ timer->interval = *interval;
+ timer->task = NULL;
+ isc_task_attach(task, &timer->task);
+ timer->action = action;
+ /*
+ * Removing the const attribute from "arg" is the best of two
+ * evils here. If the timer->arg member is made const, then
+ * it affects a great many recipients of the timer event
+ * which did not pass in an "arg" that was truly const.
+ * Changing isc_timer_create() to not have "arg" prototyped as const,
+ * though, can cause compilers warnings for calls that *do*
+ * have a truly const arg. The caller will have to carefully
+ * keep track of whether arg started as a true const.
+ */
+ DE_CONST(arg, timer->arg);
+ timer->index = 0;
+ result = isc_mutex_init(&timer->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_task_detach(&timer->task);
+ isc_mem_put(manager->mctx, timer, sizeof(*timer));
+ return (result);
+ }
+ ISC_LINK_INIT(timer, link);
+ timer->magic = TIMER_MAGIC;
+
+ LOCK(&manager->lock);
+
+ /*
+ * Note we don't have to lock the timer like we normally would because
+ * there are no external references to it yet.
+ */
+
+ if (type != isc_timertype_inactive)
+ result = schedule(timer, &now, ISC_TRUE);
+ else
+ result = ISC_R_SUCCESS;
+ if (result == ISC_R_SUCCESS)
+ APPEND(manager->timers, timer, link);
+
+ UNLOCK(&manager->lock);
+
+ if (result != ISC_R_SUCCESS) {
+ timer->magic = 0;
+ DESTROYLOCK(&timer->lock);
+ isc_task_detach(&timer->task);
+ isc_mem_put(manager->mctx, timer, sizeof(*timer));
+ return (result);
+ }
+
+ *timerp = 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_time_t now;
+ isc_timermgr_t *manager;
+ isc_result_t result;
+
+ /*
+ * Change the timer's type, expires, and interval values to the given
+ * values. If 'purge' is ISC_TRUE, any pending events from this timer
+ * are purged from its task's event queue.
+ */
+
+ REQUIRE(VALID_TIMER(timer));
+ manager = timer->manager;
+ REQUIRE(VALID_MANAGER(manager));
+ if (expires == NULL)
+ expires = isc_time_epoch;
+ if (interval == NULL)
+ interval = isc_interval_zero;
+ REQUIRE(type == isc_timertype_inactive ||
+ !(isc_time_isepoch(expires) && isc_interval_iszero(interval)));
+ REQUIRE(type != isc_timertype_limited ||
+ !(isc_time_isepoch(expires) || isc_interval_iszero(interval)));
+
+ /*
+ * Get current time.
+ */
+ if (type != isc_timertype_inactive) {
+ TIME_NOW(&now);
+ } else {
+ /*
+ * We don't have to do this, but it keeps the compiler from
+ * complaining about "now" possibly being used without being
+ * set, even though it will never actually happen.
+ */
+ isc_time_settoepoch(&now);
+ }
+
+ manager = timer->manager;
+
+ LOCK(&manager->lock);
+ LOCK(&timer->lock);
+
+ if (purge)
+ (void)isc_task_purgerange(timer->task,
+ timer,
+ ISC_TIMEREVENT_FIRSTEVENT,
+ ISC_TIMEREVENT_LASTEVENT,
+ NULL);
+ timer->type = type;
+ timer->expires = *expires;
+ timer->interval = *interval;
+ if (type == isc_timertype_once && !isc_interval_iszero(interval)) {
+ result = isc_time_add(&now, interval, &timer->idle);
+ } else {
+ isc_time_settoepoch(&timer->idle);
+ result = ISC_R_SUCCESS;
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ if (type == isc_timertype_inactive) {
+ deschedule(timer);
+ result = ISC_R_SUCCESS;
+ } else
+ result = schedule(timer, &now, ISC_TRUE);
+ }
+
+ UNLOCK(&timer->lock);
+ UNLOCK(&manager->lock);
+
+ return (result);
+}
+
+isc_timertype_t
+isc_timer_gettype(isc_timer_t *timer) {
+ isc_timertype_t t;
+
+ REQUIRE(VALID_TIMER(timer));
+
+ LOCK(&timer->lock);
+ t = timer->type;
+ UNLOCK(&timer->lock);
+
+ return (t);
+}
+
+isc_result_t
+isc_timer_touch(isc_timer_t *timer) {
+ isc_result_t result;
+ isc_time_t now;
+
+ /*
+ * Set the last-touched time of 'timer' to the current time.
+ */
+
+ REQUIRE(VALID_TIMER(timer));
+
+ LOCK(&timer->lock);
+
+ /*
+ * We'd like to
+ *
+ * REQUIRE(timer->type == isc_timertype_once);
+ *
+ * but we cannot without locking the manager lock too, which we
+ * don't want to do.
+ */
+
+ TIME_NOW(&now);
+ result = isc_time_add(&now, &timer->interval, &timer->idle);
+
+ UNLOCK(&timer->lock);
+
+ return (result);
+}
+
+void
+isc_timer_attach(isc_timer_t *timer, isc_timer_t **timerp) {
+ /*
+ * Attach *timerp to timer.
+ */
+
+ REQUIRE(VALID_TIMER(timer));
+ REQUIRE(timerp != NULL && *timerp == NULL);
+
+ LOCK(&timer->lock);
+ timer->references++;
+ UNLOCK(&timer->lock);
+
+ *timerp = timer;
+}
+
+void
+isc_timer_detach(isc_timer_t **timerp) {
+ isc_timer_t *timer;
+ isc_boolean_t free_timer = ISC_FALSE;
+
+ /*
+ * Detach *timerp from its timer.
+ */
+
+ REQUIRE(timerp != NULL);
+ timer = *timerp;
+ REQUIRE(VALID_TIMER(timer));
+
+ LOCK(&timer->lock);
+ REQUIRE(timer->references > 0);
+ timer->references--;
+ if (timer->references == 0)
+ free_timer = ISC_TRUE;
+ UNLOCK(&timer->lock);
+
+ if (free_timer)
+ destroy(timer);
+
+ *timerp = NULL;
+}
+
+static void
+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_result_t result;
+ isc_boolean_t idle;
+
+ /*!
+ * The caller must be holding the manager lock.
+ */
+
+ while (manager->nscheduled > 0 && !done) {
+ timer = isc_heap_element(manager->heap, 1);
+ INSIST(timer->type != isc_timertype_inactive);
+ if (isc_time_compare(now, &timer->due) >= 0) {
+ if (timer->type == isc_timertype_ticker) {
+ type = ISC_TIMEREVENT_TICK;
+ post_event = ISC_TRUE;
+ need_schedule = ISC_TRUE;
+ } else if (timer->type == isc_timertype_limited) {
+ int cmp;
+ cmp = isc_time_compare(now, &timer->expires);
+ if (cmp >= 0) {
+ type = ISC_TIMEREVENT_LIFE;
+ post_event = ISC_TRUE;
+ need_schedule = ISC_FALSE;
+ } else {
+ type = ISC_TIMEREVENT_TICK;
+ post_event = ISC_TRUE;
+ need_schedule = ISC_TRUE;
+ }
+ } else if (!isc_time_isepoch(&timer->expires) &&
+ isc_time_compare(now,
+ &timer->expires) >= 0) {
+ type = ISC_TIMEREVENT_LIFE;
+ post_event = ISC_TRUE;
+ need_schedule = ISC_FALSE;
+ } else {
+ idle = ISC_FALSE;
+
+ LOCK(&timer->lock);
+ if (!isc_time_isepoch(&timer->idle) &&
+ isc_time_compare(now,
+ &timer->idle) >= 0) {
+ idle = ISC_TRUE;
+ }
+ UNLOCK(&timer->lock);
+ if (idle) {
+ type = ISC_TIMEREVENT_IDLE;
+ post_event = ISC_TRUE;
+ need_schedule = ISC_FALSE;
+ } else {
+ /*
+ * Idle timer has been touched;
+ * reschedule.
+ */
+ XTRACEID(isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_TIMER,
+ ISC_MSG_IDLERESCHED,
+ "idle reschedule"),
+ timer);
+ post_event = ISC_FALSE;
+ need_schedule = ISC_TRUE;
+ }
+ }
+
+ if (post_event) {
+ XTRACEID(isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_TIMER,
+ ISC_MSG_POSTING,
+ "posting"), timer);
+ /*
+ * XXX We could preallocate this event.
+ */
+ event = (isc_timerevent_t *)isc_event_allocate(manager->mctx,
+ timer,
+ type,
+ timer->action,
+ timer->arg,
+ sizeof(*event));
+
+ if (event != NULL) {
+ event->due = timer->due;
+ isc_task_send(timer->task,
+ ISC_EVENT_PTR(&event));
+ } else
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_TIMER,
+ ISC_MSG_EVENTNOTALLOC,
+ "couldn't "
+ "allocate event"));
+ }
+
+ timer->index = 0;
+ isc_heap_delete(manager->heap, 1);
+ manager->nscheduled--;
+
+ if (need_schedule) {
+ result = schedule(timer, now, ISC_FALSE);
+ if (result != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_TIMER,
+ ISC_MSG_SCHEDFAIL,
+ "couldn't "
+ "schedule timer: %u"),
+ result);
+ }
+ } else {
+ manager->due = timer->due;
+ done = ISC_TRUE;
+ }
+ }
+}
+
+#ifdef ISC_PLATFORM_USETHREADS
+static isc_threadresult_t
+#ifdef _WIN32 /* XXXDCL */
+WINAPI
+#endif
+run(void *uap) {
+ isc_timermgr_t *manager = uap;
+ isc_time_t now;
+ isc_result_t result;
+
+ LOCK(&manager->lock);
+ while (!manager->done) {
+ TIME_NOW(&now);
+
+ XTRACETIME(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_RUNNING,
+ "running"), now);
+
+ dispatch(manager, &now);
+
+ if (manager->nscheduled > 0) {
+ XTRACETIME2(isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_WAITUNTIL,
+ "waituntil"),
+ manager->due, now);
+ result = WAITUNTIL(&manager->wakeup, &manager->lock, &manager->due);
+ INSIST(result == ISC_R_SUCCESS ||
+ result == ISC_R_TIMEDOUT);
+ } else {
+ XTRACETIME(isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_WAIT, "wait"), now);
+ WAIT(&manager->wakeup, &manager->lock);
+ }
+ XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
+ ISC_MSG_WAKEUP, "wakeup"));
+ }
+ UNLOCK(&manager->lock);
+
+ return ((isc_threadresult_t)0);
+}
+#endif /* ISC_PLATFORM_USETHREADS */
+
+static isc_boolean_t
+sooner(void *v1, void *v2) {
+ isc_timer_t *t1, *t2;
+
+ t1 = v1;
+ t2 = v2;
+ REQUIRE(VALID_TIMER(t1));
+ REQUIRE(VALID_TIMER(t2));
+
+ if (isc_time_compare(&t1->due, &t2->due) < 0)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+static void
+set_index(void *what, unsigned int index) {
+ isc_timer_t *timer;
+
+ timer = what;
+ REQUIRE(VALID_TIMER(timer));
+
+ timer->index = index;
+}
+
+isc_result_t
+isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp) {
+ isc_timermgr_t *manager;
+ isc_result_t result;
+
+ /*
+ * Create a timer manager.
+ */
+
+ REQUIRE(managerp != NULL && *managerp == NULL);
+
+#ifndef ISC_PLATFORM_USETHREADS
+ if (timermgr != NULL) {
+ timermgr->refs++;
+ *managerp = timermgr;
+ return (ISC_R_SUCCESS);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ manager = isc_mem_get(mctx, sizeof(*manager));
+ if (manager == NULL)
+ return (ISC_R_NOMEMORY);
+
+ manager->magic = TIMER_MANAGER_MAGIC;
+ manager->mctx = NULL;
+ manager->done = ISC_FALSE;
+ INIT_LIST(manager->timers);
+ manager->nscheduled = 0;
+ isc_time_settoepoch(&manager->due);
+ manager->heap = NULL;
+ result = isc_heap_create(mctx, sooner, set_index, 0, &manager->heap);
+ if (result != ISC_R_SUCCESS) {
+ INSIST(result == ISC_R_NOMEMORY);
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ return (ISC_R_NOMEMORY);
+ }
+ result = isc_mutex_init(&manager->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_heap_destroy(&manager->heap);
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ return (result);
+ }
+ isc_mem_attach(mctx, &manager->mctx);
+#ifdef ISC_PLATFORM_USETHREADS
+ if (isc_condition_init(&manager->wakeup) != ISC_R_SUCCESS) {
+ isc_mem_detach(&manager->mctx);
+ DESTROYLOCK(&manager->lock);
+ isc_heap_destroy(&manager->heap);
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_condition_init() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ return (ISC_R_UNEXPECTED);
+ }
+ if (isc_thread_create(run, manager, &manager->thread) !=
+ ISC_R_SUCCESS) {
+ isc_mem_detach(&manager->mctx);
+ (void)isc_condition_destroy(&manager->wakeup);
+ DESTROYLOCK(&manager->lock);
+ isc_heap_destroy(&manager->heap);
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_thread_create() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ return (ISC_R_UNEXPECTED);
+ }
+#else /* ISC_PLATFORM_USETHREADS */
+ manager->refs = 1;
+ timermgr = manager;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ *managerp = manager;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_timermgr_poke(isc_timermgr_t *manager) {
+#ifdef ISC_PLATFORM_USETHREADS
+ REQUIRE(VALID_MANAGER(manager));
+
+ SIGNAL(&manager->wakeup);
+#else
+ UNUSED(manager);
+#endif
+}
+
+void
+isc_timermgr_destroy(isc_timermgr_t **managerp) {
+ isc_timermgr_t *manager;
+ isc_mem_t *mctx;
+
+ /*
+ * Destroy a timer manager.
+ */
+
+ REQUIRE(managerp != NULL);
+ manager = *managerp;
+ REQUIRE(VALID_MANAGER(manager));
+
+ LOCK(&manager->lock);
+
+#ifndef ISC_PLATFORM_USETHREADS
+ if (manager->refs > 1) {
+ manager->refs--;
+ UNLOCK(&manager->lock);
+ *managerp = NULL;
+ return;
+ }
+
+ isc__timermgr_dispatch();
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ REQUIRE(EMPTY(manager->timers));
+ manager->done = ISC_TRUE;
+
+#ifdef ISC_PLATFORM_USETHREADS
+ XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
+ ISC_MSG_SIGNALDESTROY, "signal (destroy)"));
+ SIGNAL(&manager->wakeup);
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ UNLOCK(&manager->lock);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * Wait for thread to exit.
+ */
+ if (isc_thread_join(manager->thread, NULL) != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_thread_join() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /*
+ * Clean up.
+ */
+#ifdef ISC_PLATFORM_USETHREADS
+ (void)isc_condition_destroy(&manager->wakeup);
+#endif /* ISC_PLATFORM_USETHREADS */
+ DESTROYLOCK(&manager->lock);
+ isc_heap_destroy(&manager->heap);
+ manager->magic = 0;
+ mctx = manager->mctx;
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ isc_mem_detach(&mctx);
+
+ *managerp = NULL;
+}
+
+#ifndef ISC_PLATFORM_USETHREADS
+isc_result_t
+isc__timermgr_nextevent(isc_time_t *when) {
+ if (timermgr == NULL || timermgr->nscheduled == 0)
+ return (ISC_R_NOTFOUND);
+ *when = timermgr->due;
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc__timermgr_dispatch(void) {
+ isc_time_t now;
+ if (timermgr == NULL)
+ return;
+ TIME_NOW(&now);
+ dispatch(timermgr, &now);
+}
+#endif /* ISC_PLATFORM_USETHREADS */
diff --git a/lib/isc/timer_p.h b/lib/isc/timer_p.h
new file mode 100644
index 0000000..ec8e2e0
--- /dev/null
+++ b/lib/isc/timer_p.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: timer_p.h,v 1.10 2007/06/19 23:47:17 tbox Exp $ */
+
+#ifndef ISC_TIMER_P_H
+#define ISC_TIMER_P_H
+
+/*! \file */
+
+isc_result_t
+isc__timermgr_nextevent(isc_time_t *when);
+
+void
+isc__timermgr_dispatch(void);
+
+#endif /* ISC_TIMER_P_H */
diff --git a/lib/isc/unix/Makefile.in b/lib/isc/unix/Makefile.in
new file mode 100644
index 0000000..7d19b5c
--- /dev/null
+++ b/lib/isc/unix/Makefile.in
@@ -0,0 +1,51 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.41 2007/06/19 23:47:18 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+CINCLUDES = -I${srcdir}/include \
+ -I${srcdir}/../@ISC_THREAD_DIR@/include \
+ -I../include \
+ -I${srcdir}/../include \
+ -I${srcdir}/..
+
+CDEFINES =
+CWARNINGS =
+
+# Alphabetically
+OBJS = @ISC_IPV6_O@ \
+ app.@O@ dir.@O@ entropy.@O@ errno2result.@O@ file.@O@ \
+ fsaccess.@O@ interfaceiter.@O@ keyboard.@O@ net.@O@ \
+ os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \
+ strerror.@O@ syslog.@O@ time.@O@
+
+# Alphabetically
+SRCS = @ISC_IPV6_C@ \
+ app.c dir.c entropy.c errno2result.c file.c \
+ fsaccess.c interfaceiter.c keyboard.c net.c \
+ os.c resource.c socket.c stdio.c stdtime.c \
+ strerror.c syslog.c time.c
+
+SUBDIRS = include
+TARGETS = ${OBJS}
+
+@BIND9_MAKE_RULES@
+
+interfaceiter.@O@: interfaceiter.c ifiter_ioctl.c ifiter_sysctl.c ifiter_getifaddrs.c
+
diff --git a/lib/isc/unix/app.c b/lib/isc/unix/app.c
new file mode 100644
index 0000000..660b438
--- /dev/null
+++ b/lib/isc/unix/app.c
@@ -0,0 +1,684 @@
+/*
+ * 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
+ * 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.c,v 1.60 2008/10/15 03:41:17 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <sys/param.h> /* Openserver 5.0.6A and FD_SETSIZE */
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#ifdef HAVE_EPOLL
+#include <sys/epoll.h>
+#endif
+
+#include <isc/app.h>
+#include <isc/boolean.h>
+#include <isc/condition.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/event.h>
+#include <isc/platform.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#ifdef ISC_PLATFORM_USETHREADS
+#include <pthread.h>
+#else /* ISC_PLATFORM_USETHREADS */
+#include "../timer_p.h"
+#include "../task_p.h"
+#include "socket_p.h"
+#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.
+ */
+static volatile isc_boolean_t want_shutdown = ISC_FALSE;
+/*
+ * We assume that 'want_reload' can be read and written atomically.
+ */
+static volatile isc_boolean_t want_reload = ISC_FALSE;
+
+static isc_boolean_t blocked = ISC_FALSE;
+#ifdef ISC_PLATFORM_USETHREADS
+static pthread_t blockedthread;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#ifdef HAVE_LINUXTHREADS
+/*!
+ * Linux has sigwait(), but it appears to prevent signal handlers from
+ * running, even if they're not in the set being waited for. This makes
+ * it impossible to get the default actions for SIGILL, SIGSEGV, etc.
+ * Instead of messing with it, we just use sigsuspend() instead.
+ */
+#undef HAVE_SIGWAIT
+/*!
+ * We need to remember which thread is the main thread...
+ */
+static pthread_t main_thread;
+#endif
+
+#ifndef HAVE_SIGWAIT
+static void
+exit_action(int arg) {
+ UNUSED(arg);
+ want_shutdown = ISC_TRUE;
+}
+
+static void
+reload_action(int arg) {
+ UNUSED(arg);
+ want_reload = ISC_TRUE;
+}
+#endif
+
+static isc_result_t
+handle_signal(int sig, void (*handler)(int)) {
+ struct sigaction sa;
+ char strbuf[ISC_STRERRORSIZE];
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = handler;
+
+ if (sigfillset(&sa.sa_mask) != 0 ||
+ sigaction(sig, &sa, NULL) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_APP,
+ ISC_MSG_SIGNALSETUP,
+ "handle_signal() %d setup: %s"),
+ sig, strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_start(void) {
+ isc_result_t result;
+ int presult;
+ sigset_t sset;
+ char strbuf[ISC_STRERRORSIZE];
+
+ /*
+ * Start an ISC library application.
+ */
+
+#ifdef NEED_PTHREAD_INIT
+ /*
+ * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this.
+ */
+ presult = pthread_init();
+ if (presult != 0) {
+ isc__strerror(presult, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_start() pthread_init: %s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+#endif
+
+#ifdef HAVE_LINUXTHREADS
+ main_thread = pthread_self();
+#endif
+
+ result = isc_mutex_init(&lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+#ifndef HAVE_SIGWAIT
+ /*
+ * Install do-nothing handlers for SIGINT and SIGTERM.
+ *
+ * We install them now because BSDI 3.1 won't block
+ * the default actions, regardless of what we do with
+ * pthread_sigmask().
+ */
+ result = handle_signal(SIGINT, exit_action);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = handle_signal(SIGTERM, exit_action);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#endif
+
+ /*
+ * Always ignore SIGPIPE.
+ */
+ result = handle_signal(SIGPIPE, SIG_IGN);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * On Solaris 2, delivery of a signal whose action is SIG_IGN
+ * will not cause sigwait() to return. We may have inherited
+ * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent
+ * process (e.g, Solaris cron). Set an action of SIG_DFL to make
+ * sure sigwait() works as expected. Only do this for SIGTERM and
+ * SIGINT if we don't have sigwait(), since a different handler is
+ * installed above.
+ */
+ result = handle_signal(SIGHUP, SIG_DFL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+#ifdef HAVE_SIGWAIT
+ result = handle_signal(SIGTERM, SIG_DFL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = handle_signal(SIGINT, SIG_DFL);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#endif
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * Block SIGHUP, SIGINT, SIGTERM.
+ *
+ * If isc_app_start() is called from the main thread before any other
+ * threads have been created, then the pthread_sigmask() call below
+ * will result in all threads having SIGHUP, SIGINT and SIGTERM
+ * blocked by default, ensuring that only the thread that calls
+ * sigwait() for them will get those signals.
+ */
+ if (sigemptyset(&sset) != 0 ||
+ sigaddset(&sset, SIGHUP) != 0 ||
+ sigaddset(&sset, SIGINT) != 0 ||
+ sigaddset(&sset, SIGTERM) != 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_start() sigsetops: %s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ presult = pthread_sigmask(SIG_BLOCK, &sset, NULL);
+ if (presult != 0) {
+ isc__strerror(presult, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_start() pthread_sigmask: %s",
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+#else /* ISC_PLATFORM_USETHREADS */
+ /*
+ * Unblock SIGHUP, SIGINT, SIGTERM.
+ *
+ * If we're not using threads, we need to make sure that SIGHUP,
+ * SIGINT and SIGTERM are not inherited as blocked from the parent
+ * process.
+ */
+ if (sigemptyset(&sset) != 0 ||
+ sigaddset(&sset, SIGHUP) != 0 ||
+ sigaddset(&sset, SIGINT) != 0 ||
+ sigaddset(&sset, SIGTERM) != 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_start() sigsetops: %s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ presult = sigprocmask(SIG_UNBLOCK, &sset, NULL);
+ if (presult != 0) {
+ isc__strerror(presult, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_start() sigprocmask: %s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+#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,
+ void *arg)
+{
+ isc_event_t *event;
+ isc_task_t *cloned_task = NULL;
+ isc_result_t result;
+
+ LOCK(&lock);
+
+ if (running) {
+ result = ISC_R_ALREADYRUNNING;
+ goto unlock;
+ }
+
+ /*
+ * Note that we store the task to which we're going to send the event
+ * in the event's "sender" field.
+ */
+ isc_task_attach(task, &cloned_task);
+ event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
+ action, arg, sizeof(*event));
+ if (event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto unlock;
+ }
+
+ ISC_LIST_APPEND(on_run, event, ev_link);
+
+ result = ISC_R_SUCCESS;
+
+ unlock:
+ UNLOCK(&lock);
+
+ return (result);
+}
+
+#ifndef ISC_PLATFORM_USETHREADS
+/*!
+ * Event loop for nonthreaded programs.
+ */
+static isc_result_t
+evloop(void) {
+ isc_result_t result;
+ while (!want_shutdown) {
+ int n;
+ isc_time_t when, now;
+ struct timeval tv, *tvp;
+ isc_socketwait_t *swait;
+ isc_boolean_t readytasks;
+ isc_boolean_t call_timer_dispatch = ISC_FALSE;
+
+ readytasks = isc__taskmgr_ready();
+ if (readytasks) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ tvp = &tv;
+ call_timer_dispatch = ISC_TRUE;
+ } else {
+ result = isc__timermgr_nextevent(&when);
+ if (result != ISC_R_SUCCESS)
+ tvp = NULL;
+ else {
+ isc_uint64_t us;
+
+ TIME_NOW(&now);
+ us = isc_time_microdiff(&when, &now);
+ if (us == 0)
+ call_timer_dispatch = ISC_TRUE;
+ tv.tv_sec = us / 1000000;
+ tv.tv_usec = us % 1000000;
+ tvp = &tv;
+ }
+ }
+
+ swait = NULL;
+ n = isc__socketmgr_waitevents(tvp, &swait);
+
+ if (n == 0 || call_timer_dispatch) {
+ /*
+ * We call isc__timermgr_dispatch() only when
+ * necessary, in order to reduce overhead. If the
+ * select() call indicates a timeout, we need the
+ * dispatch. Even if not, if we set the 0-timeout
+ * for the select() call, we need to check the timer
+ * events. In the 'readytasks' case, there may be no
+ * timeout event actually, but there is no other way
+ * to reduce the overhead.
+ * Note that we do not have to worry about the case
+ * where a new timer is inserted during the select()
+ * call, since this loop only runs in the non-thread
+ * mode.
+ */
+ isc__timermgr_dispatch();
+ }
+ if (n > 0)
+ (void)isc__socketmgr_dispatch(swait);
+ (void)isc__taskmgr_dispatch();
+
+ if (want_reload) {
+ want_reload = ISC_FALSE;
+ return (ISC_R_RELOAD);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This is a gross hack to support waiting for condition
+ * variables in nonthreaded programs in a limited way;
+ * see lib/isc/nothreads/include/isc/condition.h.
+ * We implement isc_condition_wait() by entering the
+ * event loop recursively until the want_shutdown flag
+ * is set by isc_condition_signal().
+ */
+
+/*!
+ * \brief True if we are currently executing in the recursive
+ * event loop.
+ */
+static isc_boolean_t in_recursive_evloop = ISC_FALSE;
+
+/*!
+ * \brief True if we are exiting the event loop as the result of
+ * a call to isc_condition_signal() rather than a shutdown
+ * or reload.
+ */
+static isc_boolean_t signalled = ISC_FALSE;
+
+isc_result_t
+isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp) {
+ isc_result_t result;
+
+ UNUSED(cp);
+ UNUSED(mp);
+
+ INSIST(!in_recursive_evloop);
+ in_recursive_evloop = ISC_TRUE;
+
+ INSIST(*mp == 1); /* Mutex must be locked on entry. */
+ --*mp;
+
+ result = evloop();
+ if (result == ISC_R_RELOAD)
+ want_reload = ISC_TRUE;
+ if (signalled) {
+ want_shutdown = ISC_FALSE;
+ signalled = ISC_FALSE;
+ }
+
+ ++*mp;
+ in_recursive_evloop = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc__nothread_signal_hack(isc_condition_t *cp) {
+
+ UNUSED(cp);
+
+ INSIST(in_recursive_evloop);
+
+ want_shutdown = ISC_TRUE;
+ signalled = ISC_TRUE;
+ return (ISC_R_SUCCESS);
+}
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+isc_result_t
+isc_app_run(void) {
+ int result;
+ isc_event_t *event, *next_event;
+ isc_task_t *task;
+#ifdef ISC_PLATFORM_USETHREADS
+ sigset_t sset;
+ char strbuf[ISC_STRERRORSIZE];
+#ifdef HAVE_SIGWAIT
+ int sig;
+#endif
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#ifdef HAVE_LINUXTHREADS
+ REQUIRE(main_thread == pthread_self());
+#endif
+
+ LOCK(&lock);
+
+ if (!running) {
+ running = ISC_TRUE;
+
+ /*
+ * Post any on-run events (in FIFO order).
+ */
+ for (event = ISC_LIST_HEAD(on_run);
+ event != NULL;
+ event = next_event) {
+ next_event = ISC_LIST_NEXT(event, ev_link);
+ ISC_LIST_UNLINK(on_run, event, ev_link);
+ task = event->ev_sender;
+ event->ev_sender = NULL;
+ isc_task_sendanddetach(&task, &event);
+ }
+
+ }
+
+ UNLOCK(&lock);
+
+#ifndef HAVE_SIGWAIT
+ /*
+ * Catch SIGHUP.
+ *
+ * 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);
+#endif
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * 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) {
+#ifdef HAVE_SIGWAIT
+ /*
+ * Wait for SIGHUP, SIGINT, or SIGTERM.
+ */
+ if (sigemptyset(&sset) != 0 ||
+ sigaddset(&sset, SIGHUP) != 0 ||
+ sigaddset(&sset, SIGINT) != 0 ||
+ sigaddset(&sset, SIGTERM) != 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_run() sigsetops: %s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+
+#ifndef HAVE_UNIXWARE_SIGWAIT
+ result = sigwait(&sset, &sig);
+ if (result == 0) {
+ if (sig == SIGINT ||
+ sig == SIGTERM)
+ want_shutdown = ISC_TRUE;
+ else if (sig == SIGHUP)
+ want_reload = ISC_TRUE;
+ }
+
+#else /* Using UnixWare sigwait semantics. */
+ sig = sigwait(&sset);
+ if (sig >= 0) {
+ if (sig == SIGINT ||
+ sig == SIGTERM)
+ want_shutdown = ISC_TRUE;
+ else if (sig == SIGHUP)
+ want_reload = ISC_TRUE;
+ }
+
+#endif /* HAVE_UNIXWARE_SIGWAIT */
+#else /* Don't have sigwait(). */
+ /*
+ * Listen for all signals.
+ */
+ if (sigemptyset(&sset) != 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_app_run() sigsetops: %s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ result = sigsuspend(&sset);
+#endif /* HAVE_SIGWAIT */
+
+ if (want_reload) {
+ want_reload = ISC_FALSE;
+ return (ISC_R_RELOAD);
+ }
+
+ if (want_shutdown && blocked)
+ exit(1);
+ }
+
+#else /* ISC_PLATFORM_USETHREADS */
+
+ (void)isc__taskmgr_dispatch();
+
+ result = evloop();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_shutdown(void) {
+ isc_boolean_t want_kill = ISC_TRUE;
+ char strbuf[ISC_STRERRORSIZE];
+
+ LOCK(&lock);
+
+ REQUIRE(running);
+
+ if (shutdown_requested)
+ want_kill = ISC_FALSE;
+ else
+ shutdown_requested = ISC_TRUE;
+
+ UNLOCK(&lock);
+
+ if (want_kill) {
+#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);
+ }
+#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);
+ }
+#endif
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_reload(void) {
+ isc_boolean_t want_kill = ISC_TRUE;
+ char strbuf[ISC_STRERRORSIZE];
+
+ LOCK(&lock);
+
+ REQUIRE(running);
+
+ /*
+ * Don't send the reload signal if we're shutting down.
+ */
+ if (shutdown_requested)
+ want_kill = ISC_FALSE;
+
+ UNLOCK(&lock);
+
+ if (want_kill) {
+#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);
+ }
+#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);
+ }
+#endif
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_app_finish(void) {
+ DESTROYLOCK(&lock);
+}
+
+void
+isc_app_block(void) {
+#ifdef ISC_PLATFORM_USETHREADS
+ sigset_t sset;
+#endif /* ISC_PLATFORM_USETHREADS */
+ REQUIRE(running);
+ REQUIRE(!blocked);
+
+ blocked = ISC_TRUE;
+#ifdef ISC_PLATFORM_USETHREADS
+ blockedthread = pthread_self();
+ RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
+ sigaddset(&sset, SIGINT) == 0 &&
+ sigaddset(&sset, SIGTERM) == 0);
+ RUNTIME_CHECK(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) == 0);
+#endif /* ISC_PLATFORM_USETHREADS */
+}
+
+void
+isc_app_unblock(void) {
+#ifdef ISC_PLATFORM_USETHREADS
+ sigset_t sset;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ REQUIRE(running);
+ REQUIRE(blocked);
+
+ blocked = ISC_FALSE;
+
+#ifdef ISC_PLATFORM_USETHREADS
+ REQUIRE(blockedthread == pthread_self());
+
+ RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
+ sigaddset(&sset, SIGINT) == 0 &&
+ sigaddset(&sset, SIGTERM) == 0);
+ RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
+#endif /* ISC_PLATFORM_USETHREADS */
+}
diff --git a/lib/isc/unix/dir.c b/lib/isc/unix/dir.c
new file mode 100644
index 0000000..8ab0cdd
--- /dev/null
+++ b/lib/isc/unix/dir.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: dir.c,v 1.25 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file
+ * \author Principal Authors: DCL */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <isc/dir.h>
+#include <isc/magic.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+#define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*')
+#define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC)
+
+void
+isc_dir_init(isc_dir_t *dir) {
+ REQUIRE(dir != NULL);
+
+ dir->entry.name[0] = '\0';
+ dir->entry.length = 0;
+
+ dir->handle = NULL;
+
+ dir->magic = ISC_DIR_MAGIC;
+}
+
+/*!
+ * \brief Allocate workspace and open directory stream. If either one fails,
+ * NULL will be returned.
+ */
+isc_result_t
+isc_dir_open(isc_dir_t *dir, const char *dirname) {
+ char *p;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(VALID_DIR(dir));
+ REQUIRE(dirname != NULL);
+
+ /*
+ * Copy directory name. Need to have enough space for the name,
+ * a possible path separator, the wildcard, and the final NUL.
+ */
+ if (strlen(dirname) + 3 > sizeof(dir->dirname))
+ /* XXXDCL ? */
+ return (ISC_R_NOSPACE);
+ strcpy(dir->dirname, dirname);
+
+ /*
+ * Append path separator, if needed, and "*".
+ */
+ p = dir->dirname + strlen(dir->dirname);
+ if (dir->dirname < p && *(p - 1) != '/')
+ *p++ = '/';
+ *p++ = '*';
+ *p++ = '\0';
+
+ /*
+ * Open stream.
+ */
+ dir->handle = opendir(dirname);
+
+ if (dir->handle == NULL)
+ return isc__errno2result(errno);
+
+ return (result);
+}
+
+/*!
+ * \brief Return previously retrieved file or get next one.
+
+ * Unix's dirent has
+ * separate open and read functions, but the Win32 and DOS interfaces open
+ * the dir stream and reads the first file in one operation.
+ */
+isc_result_t
+isc_dir_read(isc_dir_t *dir) {
+ struct dirent *entry;
+
+ REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
+
+ /*
+ * Fetch next file in directory.
+ */
+ entry = readdir(dir->handle);
+
+ if (entry == NULL)
+ return (ISC_R_NOMORE);
+
+ /*
+ * Make sure that the space for the name is long enough.
+ */
+ if (sizeof(dir->entry.name) <= strlen(entry->d_name))
+ return (ISC_R_UNEXPECTED);
+
+ strcpy(dir->entry.name, entry->d_name);
+
+ /*
+ * Some dirents have d_namlen, but it is not portable.
+ */
+ dir->entry.length = strlen(entry->d_name);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*!
+ * \brief Close directory stream.
+ */
+void
+isc_dir_close(isc_dir_t *dir) {
+ REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
+
+ (void)closedir(dir->handle);
+ dir->handle = NULL;
+}
+
+/*!
+ * \brief Reposition directory stream at start.
+ */
+isc_result_t
+isc_dir_reset(isc_dir_t *dir) {
+ REQUIRE(VALID_DIR(dir) && dir->handle != NULL);
+
+ rewinddir(dir->handle);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_chdir(const char *dirname) {
+ /*!
+ * \brief Change the current directory to 'dirname'.
+ */
+
+ REQUIRE(dirname != NULL);
+
+ if (chdir(dirname) < 0)
+ return (isc__errno2result(errno));
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_chroot(const char *dirname) {
+
+ REQUIRE(dirname != NULL);
+
+ if (chroot(dirname) < 0)
+ return (isc__errno2result(errno));
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_createunique(char *templet) {
+ isc_result_t result;
+ char *x;
+ char *p;
+ int i;
+ int pid;
+
+ REQUIRE(templet != NULL);
+
+ /*!
+ * \brief mkdtemp is not portable, so this emulates it.
+ */
+
+ pid = getpid();
+
+ /*
+ * Replace trailing Xs with the process-id, zero-filled.
+ */
+ for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet;
+ x--, pid /= 10)
+ *x = pid % 10 + '0';
+
+ x++; /* Set x to start of ex-Xs. */
+
+ do {
+ i = mkdir(templet, 0700);
+ if (i == 0 || errno != EEXIST)
+ break;
+
+ /*
+ * The BSD algorithm.
+ */
+ p = x;
+ while (*p != '\0') {
+ if (isdigit(*p & 0xff))
+ *p = 'a';
+ else if (*p != 'z')
+ ++*p;
+ else {
+ /*
+ * Reset character and move to next.
+ */
+ *p++ = 'a';
+ continue;
+ }
+
+ break;
+ }
+
+ if (*p == '\0') {
+ /*
+ * Tried all combinations. errno should already
+ * be EEXIST, but ensure it is anyway for
+ * isc__errno2result().
+ */
+ errno = EEXIST;
+ break;
+ }
+ } while (1);
+
+ if (i == -1)
+ result = isc__errno2result(errno);
+ else
+ result = ISC_R_SUCCESS;
+
+ return (result);
+}
diff --git a/lib/isc/unix/entropy.c b/lib/isc/unix/entropy.c
new file mode 100644
index 0000000..4e3ee61
--- /dev/null
+++ b/lib/isc/unix/entropy.c
@@ -0,0 +1,594 @@
+/*
+ * Copyright (C) 2004-2007 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: entropy.c,v 1.80 2007/06/19 23:47:18 tbox Exp $ */
+
+/* \file unix/entropy.c
+ * \brief
+ * This is the system dependent part of the ISC entropy API.
+ */
+
+#include <config.h>
+
+#include <sys/param.h> /* Openserver 5.0.6A and FD_SETSIZE */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <unistd.h>
+
+#include <isc/platform.h>
+#include <isc/strerror.h>
+
+#ifdef ISC_PLATFORM_NEEDSYSSELECTH
+#include <sys/select.h>
+#endif
+
+#include "errno2result.h"
+
+/*%
+ * There is only one variable in the entropy data structures that is not
+ * system independent, but pulling the structure that uses it into this file
+ * ultimately means pulling several other independent structures here also to
+ * resolve their interdependencies. Thus only the problem variable's type
+ * is defined here.
+ */
+#define FILESOURCE_HANDLE_TYPE int
+
+typedef struct {
+ int handle;
+ enum {
+ isc_usocketsource_disconnected,
+ isc_usocketsource_connecting,
+ isc_usocketsource_connected,
+ isc_usocketsource_ndesired,
+ isc_usocketsource_wrote,
+ isc_usocketsource_reading
+ } status;
+ size_t sz_to_recv;
+} isc_entropyusocketsource_t;
+
+#include "../entropy.c"
+
+static unsigned int
+get_from_filesource(isc_entropysource_t *source, isc_uint32_t desired) {
+ isc_entropy_t *ent = source->ent;
+ unsigned char buf[128];
+ int fd = source->sources.file.handle;
+ ssize_t n, ndesired;
+ unsigned int added;
+
+ if (source->bad)
+ return (0);
+
+ desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
+
+ added = 0;
+ while (desired > 0) {
+ ndesired = ISC_MIN(desired, sizeof(buf));
+ n = read(fd, buf, ndesired);
+ if (n < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ goto out;
+ goto err;
+ }
+ if (n == 0)
+ goto err;
+
+ entropypool_adddata(ent, buf, n, n * 8);
+ added += n * 8;
+ desired -= n;
+ }
+ goto out;
+
+ err:
+ (void)close(fd);
+ source->sources.file.handle = -1;
+ source->bad = ISC_TRUE;
+
+ out:
+ return (added);
+}
+
+static unsigned int
+get_from_usocketsource(isc_entropysource_t *source, isc_uint32_t desired) {
+ isc_entropy_t *ent = source->ent;
+ unsigned char buf[128];
+ int fd = source->sources.usocket.handle;
+ ssize_t n = 0, ndesired;
+ unsigned int added;
+ size_t sz_to_recv = source->sources.usocket.sz_to_recv;
+
+ if (source->bad)
+ return (0);
+
+ desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
+
+ added = 0;
+ while (desired > 0) {
+ ndesired = ISC_MIN(desired, sizeof(buf));
+ eagain_loop:
+
+ switch ( source->sources.usocket.status ) {
+ case isc_usocketsource_ndesired:
+ buf[0] = ndesired;
+ if ((n = sendto(fd, buf, 1, 0, NULL, 0)) < 0) {
+ if (errno == EWOULDBLOCK || errno == EINTR ||
+ errno == ECONNRESET)
+ goto out;
+ goto err;
+ }
+ INSIST(n == 1);
+ source->sources.usocket.status =
+ isc_usocketsource_wrote;
+ goto eagain_loop;
+
+ case isc_usocketsource_connecting:
+ case isc_usocketsource_connected:
+ buf[0] = 1;
+ buf[1] = ndesired;
+ if ((n = sendto(fd, buf, 2, 0, NULL, 0)) < 0) {
+ if (errno == EWOULDBLOCK || errno == EINTR ||
+ errno == ECONNRESET)
+ goto out;
+ goto err;
+ }
+ if (n == 1) {
+ source->sources.usocket.status =
+ isc_usocketsource_ndesired;
+ goto eagain_loop;
+ }
+ INSIST(n == 2);
+ source->sources.usocket.status =
+ isc_usocketsource_wrote;
+ /*FALLTHROUGH*/
+
+ case isc_usocketsource_wrote:
+ if (recvfrom(fd, buf, 1, 0, NULL, NULL) != 1) {
+ if (errno == EAGAIN) {
+ /*
+ * The problem of EAGAIN (try again
+ * later) is a major issue on HP-UX.
+ * Solaris actually tries the recvfrom
+ * call again, while HP-UX just dies.
+ * This code is an attempt to let the
+ * entropy pool fill back up (at least
+ * that's what I think the problem is.)
+ * We go to eagain_loop because if we
+ * just "break", then the "desired"
+ * amount gets borked.
+ */
+ usleep(1000);
+ goto eagain_loop;
+ }
+ if (errno == EWOULDBLOCK || errno == EINTR)
+ goto out;
+ goto err;
+ }
+ source->sources.usocket.status =
+ isc_usocketsource_reading;
+ sz_to_recv = buf[0];
+ source->sources.usocket.sz_to_recv = sz_to_recv;
+ if (sz_to_recv > sizeof(buf))
+ goto err;
+ /*FALLTHROUGH*/
+
+ case isc_usocketsource_reading:
+ if (sz_to_recv != 0U) {
+ n = recv(fd, buf, sz_to_recv, 0);
+ if (n < 0) {
+ if (errno == EWOULDBLOCK ||
+ errno == EINTR)
+ goto out;
+ goto err;
+ }
+ } else
+ n = 0;
+ break;
+
+ default:
+ goto err;
+ }
+
+ if ((size_t)n != sz_to_recv)
+ source->sources.usocket.sz_to_recv -= n;
+ else
+ source->sources.usocket.status =
+ isc_usocketsource_connected;
+
+ if (n == 0)
+ goto out;
+
+ entropypool_adddata(ent, buf, n, n * 8);
+ added += n * 8;
+ desired -= n;
+ }
+ goto out;
+
+ err:
+ close(fd);
+ source->bad = ISC_TRUE;
+ source->sources.usocket.status = isc_usocketsource_disconnected;
+ source->sources.usocket.handle = -1;
+
+ out:
+ return (added);
+}
+
+/*
+ * Poll each source, trying to get data from it to stuff into the entropy
+ * pool.
+ */
+static void
+fillpool(isc_entropy_t *ent, unsigned int desired, isc_boolean_t blocking) {
+ unsigned int added;
+ unsigned int remaining;
+ unsigned int needed;
+ unsigned int nsource;
+ isc_entropysource_t *source;
+
+ REQUIRE(VALID_ENTROPY(ent));
+
+ needed = desired;
+
+ /*
+ * This logic is a little strange, so an explanation is in order.
+ *
+ * If needed is 0, it means we are being asked to "fill to whatever
+ * we think is best." This means that if we have at least a
+ * partially full pool (say, > 1/4th of the pool) we probably don't
+ * need to add anything.
+ *
+ * Also, we will check to see if the "pseudo" count is too high.
+ * If it is, try to mix in better data. Too high is currently
+ * defined as 1/4th of the pool.
+ *
+ * Next, if we are asked to add a specific bit of entropy, make
+ * certain that we will do so. Clamp how much we try to add to
+ * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy).
+ *
+ * Note that if we are in a blocking mode, we will only try to
+ * get as much data as we need, not as much as we might want
+ * to build up.
+ */
+ if (needed == 0) {
+ REQUIRE(!blocking);
+
+ if ((ent->pool.entropy >= RND_POOLBITS / 4)
+ && (ent->pool.pseudo <= RND_POOLBITS / 4))
+ return;
+
+ needed = THRESHOLD_BITS * 4;
+ } else {
+ needed = ISC_MAX(needed, THRESHOLD_BITS);
+ needed = ISC_MIN(needed, RND_POOLBITS);
+ }
+
+ /*
+ * In any case, clamp how much we need to how much we can add.
+ */
+ needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy);
+
+ /*
+ * But wait! If we're not yet initialized, we need at least
+ * THRESHOLD_BITS
+ * of randomness.
+ */
+ if (ent->initialized < THRESHOLD_BITS)
+ needed = ISC_MAX(needed, THRESHOLD_BITS - ent->initialized);
+
+ /*
+ * Poll each file source to see if we can read anything useful from
+ * it. XXXMLG When where are multiple sources, we should keep a
+ * record of which one we last used so we can start from it (or the
+ * next one) to avoid letting some sources build up entropy while
+ * others are always drained.
+ */
+
+ added = 0;
+ remaining = needed;
+ if (ent->nextsource == NULL) {
+ ent->nextsource = ISC_LIST_HEAD(ent->sources);
+ if (ent->nextsource == NULL)
+ return;
+ }
+ source = ent->nextsource;
+ again_file:
+ for (nsource = 0; nsource < ent->nsources; nsource++) {
+ unsigned int got;
+
+ if (remaining == 0)
+ break;
+
+ got = 0;
+
+ switch ( source->type ) {
+ case ENTROPY_SOURCETYPE_FILE:
+ got = get_from_filesource(source, remaining);
+ break;
+
+ case ENTROPY_SOURCETYPE_USOCKET:
+ got = get_from_usocketsource(source, remaining);
+ break;
+ }
+
+ added += got;
+
+ remaining -= ISC_MIN(remaining, got);
+
+ source = ISC_LIST_NEXT(source, link);
+ if (source == NULL)
+ source = ISC_LIST_HEAD(ent->sources);
+ }
+ ent->nextsource = source;
+
+ if (blocking && remaining != 0) {
+ int fds;
+
+ fds = wait_for_sources(ent);
+ if (fds > 0)
+ goto again_file;
+ }
+
+ /*
+ * Here, if there are bits remaining to be had and we can block,
+ * check to see if we have a callback source. If so, call them.
+ */
+ source = ISC_LIST_HEAD(ent->sources);
+ while ((remaining != 0) && (source != NULL)) {
+ unsigned int got;
+
+ got = 0;
+
+ if (source->type == ENTROPY_SOURCETYPE_CALLBACK)
+ got = get_from_callback(source, remaining, blocking);
+
+ added += got;
+ remaining -= ISC_MIN(remaining, got);
+
+ if (added >= needed)
+ break;
+
+ source = ISC_LIST_NEXT(source, link);
+ }
+
+ /*
+ * Mark as initialized if we've added enough data.
+ */
+ if (ent->initialized < THRESHOLD_BITS)
+ ent->initialized += added;
+}
+
+static int
+wait_for_sources(isc_entropy_t *ent) {
+ isc_entropysource_t *source;
+ int maxfd, fd;
+ int cc;
+ fd_set reads;
+ fd_set writes;
+
+ maxfd = -1;
+ FD_ZERO(&reads);
+ FD_ZERO(&writes);
+
+ source = ISC_LIST_HEAD(ent->sources);
+ while (source != NULL) {
+ if (source->type == ENTROPY_SOURCETYPE_FILE) {
+ fd = source->sources.file.handle;
+ if (fd >= 0) {
+ maxfd = ISC_MAX(maxfd, fd);
+ FD_SET(fd, &reads);
+ }
+ }
+ if (source->type == ENTROPY_SOURCETYPE_USOCKET) {
+ fd = source->sources.usocket.handle;
+ if (fd >= 0) {
+ switch (source->sources.usocket.status) {
+ case isc_usocketsource_disconnected:
+ break;
+ case isc_usocketsource_connecting:
+ case isc_usocketsource_connected:
+ case isc_usocketsource_ndesired:
+ maxfd = ISC_MAX(maxfd, fd);
+ FD_SET(fd, &writes);
+ break;
+ case isc_usocketsource_wrote:
+ case isc_usocketsource_reading:
+ maxfd = ISC_MAX(maxfd, fd);
+ FD_SET(fd, &reads);
+ break;
+ }
+ }
+ }
+ source = ISC_LIST_NEXT(source, link);
+ }
+
+ if (maxfd < 0)
+ return (-1);
+
+ cc = select(maxfd + 1, &reads, &writes, NULL, NULL);
+ if (cc < 0)
+ return (-1);
+
+ return (cc);
+}
+
+static void
+destroyfilesource(isc_entropyfilesource_t *source) {
+ (void)close(source->handle);
+}
+
+static void
+destroyusocketsource(isc_entropyusocketsource_t *source) {
+ close(source->handle);
+}
+
+/*
+ * Make a fd non-blocking
+ */
+static isc_result_t
+make_nonblock(int fd) {
+ int ret;
+ int flags;
+ char strbuf[ISC_STRERRORSIZE];
+#ifdef USE_FIONBIO_IOCTL
+ int on = 1;
+
+ ret = ioctl(fd, FIONBIO, (char *)&on);
+#else
+ flags = fcntl(fd, F_GETFL, 0);
+ flags |= PORT_NONBLOCK;
+ ret = fcntl(fd, F_SETFL, flags);
+#endif
+
+ if (ret == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+#ifdef USE_FIONBIO_IOCTL
+ "ioctl(%d, FIONBIO, &on): %s", fd,
+#else
+ "fcntl(%d, F_SETFL, %d): %s", fd, flags,
+#endif
+ strbuf);
+
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) {
+ int fd;
+ struct stat _stat;
+ isc_boolean_t is_usocket = ISC_FALSE;
+ isc_boolean_t is_connected = ISC_FALSE;
+ isc_result_t ret;
+ isc_entropysource_t *source;
+
+ REQUIRE(VALID_ENTROPY(ent));
+ REQUIRE(fname != NULL);
+
+ LOCK(&ent->lock);
+
+ if (stat(fname, &_stat) < 0) {
+ ret = isc__errno2result(errno);
+ goto errout;
+ }
+ /*
+ * Solaris 2.5.1 does not have support for sockets (S_IFSOCK),
+ * but it does return type S_IFIFO (the OS believes that
+ * the socket is a fifo). This may be an issue if we tell
+ * the program to look at an actual FIFO as its source of
+ * entropy.
+ */
+#if defined(S_ISSOCK)
+ if (S_ISSOCK(_stat.st_mode))
+ is_usocket = ISC_TRUE;
+#endif
+#if defined(S_ISFIFO) && defined(sun)
+ if (S_ISFIFO(_stat.st_mode))
+ is_usocket = ISC_TRUE;
+#endif
+ if (is_usocket)
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ else
+ fd = open(fname, O_RDONLY | PORT_NONBLOCK, 0);
+
+ if (fd < 0) {
+ ret = isc__errno2result(errno);
+ goto errout;
+ }
+
+ ret = make_nonblock(fd);
+ if (ret != ISC_R_SUCCESS)
+ goto closefd;
+
+ if (is_usocket) {
+ struct sockaddr_un sname;
+
+ memset(&sname, 0, sizeof(sname));
+ sname.sun_family = AF_UNIX;
+ strncpy(sname.sun_path, fname, sizeof(sname.sun_path));
+ sname.sun_path[sizeof(sname.sun_path)-1] = '0';
+#ifdef ISC_PLATFORM_HAVESALEN
+#if !defined(SUN_LEN)
+#define SUN_LEN(su) \
+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+#endif
+ sname.sun_len = SUN_LEN(&sname);
+#endif
+
+ if (connect(fd, (struct sockaddr *) &sname,
+ sizeof(struct sockaddr_un)) < 0) {
+ if (errno != EINPROGRESS) {
+ ret = isc__errno2result(errno);
+ goto closefd;
+ }
+ } else
+ is_connected = ISC_TRUE;
+ }
+
+ source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
+ if (source == NULL) {
+ ret = ISC_R_NOMEMORY;
+ goto closefd;
+ }
+
+ /*
+ * From here down, no failures can occur.
+ */
+ source->magic = SOURCE_MAGIC;
+ source->ent = ent;
+ source->total = 0;
+ source->bad = ISC_FALSE;
+ memset(source->name, 0, sizeof(source->name));
+ ISC_LINK_INIT(source, link);
+ if (is_usocket) {
+ source->sources.usocket.handle = fd;
+ if (is_connected)
+ source->sources.usocket.status =
+ isc_usocketsource_connected;
+ else
+ source->sources.usocket.status =
+ isc_usocketsource_connecting;
+ source->sources.usocket.sz_to_recv = 0;
+ source->type = ENTROPY_SOURCETYPE_USOCKET;
+ } else {
+ source->sources.file.handle = fd;
+ source->type = ENTROPY_SOURCETYPE_FILE;
+ }
+
+ /*
+ * Hook it into the entropy system.
+ */
+ ISC_LIST_APPEND(ent->sources, source, link);
+ ent->nsources++;
+
+ UNLOCK(&ent->lock);
+ return (ISC_R_SUCCESS);
+
+ closefd:
+ (void)close(fd);
+
+ errout:
+ UNLOCK(&ent->lock);
+
+ return (ret);
+}
diff --git a/lib/isc/unix/errno2result.c b/lib/isc/unix/errno2result.c
new file mode 100644
index 0000000..606c560
--- /dev/null
+++ b/lib/isc/unix/errno2result.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: errno2result.c,v 1.17 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/result.h>
+#include <isc/strerror.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+/*%
+ * Convert a POSIX errno value into an isc_result_t. The
+ * list of supported errno values is not complete; new users
+ * of this function should add any expected errors that are
+ * not already there.
+ */
+isc_result_t
+isc__errno2result(int posixerrno) {
+ char strbuf[ISC_STRERRORSIZE];
+
+ switch (posixerrno) {
+ case ENOTDIR:
+ case ELOOP:
+ case EINVAL: /* XXX sometimes this is not for files */
+ case ENAMETOOLONG:
+ case EBADF:
+ return (ISC_R_INVALIDFILE);
+ case ENOENT:
+ return (ISC_R_FILENOTFOUND);
+ case EACCES:
+ case EPERM:
+ return (ISC_R_NOPERM);
+ case EEXIST:
+ return (ISC_R_FILEEXISTS);
+ case EIO:
+ return (ISC_R_IOERROR);
+ case ENOMEM:
+ return (ISC_R_NOMEMORY);
+ case ENFILE:
+ case EMFILE:
+ return (ISC_R_TOOMANYOPENFILES);
+ case EPIPE:
+#ifdef ECONNRESET
+ case ECONNRESET:
+#endif
+#ifdef ECONNABORTED
+ case ECONNABORTED:
+#endif
+ return (ISC_R_CONNECTIONRESET);
+#ifdef ENOTCONN
+ case ENOTCONN:
+ return (ISC_R_NOTCONNECTED);
+#endif
+#ifdef ETIMEDOUT
+ case ETIMEDOUT:
+ return (ISC_R_TIMEDOUT);
+#endif
+#ifdef ENOBUFS
+ case ENOBUFS:
+ return (ISC_R_NORESOURCES);
+#endif
+#ifdef EAFNOSUPPORT
+ case EAFNOSUPPORT:
+ return (ISC_R_FAMILYNOSUPPORT);
+#endif
+#ifdef ENETDOWN
+ case ENETDOWN:
+ return (ISC_R_NETDOWN);
+#endif
+#ifdef EHOSTDOWN
+ case EHOSTDOWN:
+ return (ISC_R_HOSTDOWN);
+#endif
+#ifdef ENETUNREACH
+ case ENETUNREACH:
+ return (ISC_R_NETUNREACH);
+#endif
+#ifdef EHOSTUNREACH
+ case EHOSTUNREACH:
+ return (ISC_R_HOSTUNREACH);
+#endif
+#ifdef EADDRINUSE
+ case EADDRINUSE:
+ return (ISC_R_ADDRINUSE);
+#endif
+ case EADDRNOTAVAIL:
+ return (ISC_R_ADDRNOTAVAIL);
+ case ECONNREFUSED:
+ return (ISC_R_CONNREFUSED);
+ default:
+ isc__strerror(posixerrno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "unable to convert errno "
+ "to isc_result: %d: %s",
+ posixerrno, strbuf);
+ /*
+ * XXXDCL would be nice if perhaps this function could
+ * return the system's error string, so the caller
+ * might have something more descriptive than "unexpected
+ * error" to log with.
+ */
+ return (ISC_R_UNEXPECTED);
+ }
+}
diff --git a/lib/isc/unix/errno2result.h b/lib/isc/unix/errno2result.h
new file mode 100644
index 0000000..b5b658d
--- /dev/null
+++ b/lib/isc/unix/errno2result.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: errno2result.h,v 1.12 2007/06/19 23:47:18 tbox Exp $ */
+
+#ifndef UNIX_ERRNO2RESULT_H
+#define UNIX_ERRNO2RESULT_H 1
+
+/*! \file */
+
+/* XXXDCL this should be moved to lib/isc/include/isc/errno2result.h. */
+
+#include <errno.h> /* Provides errno. */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc__errno2result(int posixerrno);
+
+ISC_LANG_ENDDECLS
+
+#endif /* UNIX_ERRNO2RESULT_H */
diff --git a/lib/isc/unix/file.c b/lib/isc/unix/file.c
new file mode 100644
index 0000000..c5731c6
--- /dev/null
+++ b/lib/isc/unix/file.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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.
+ */
+
+/*
+ * Portions Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $Id: file.c,v 1.51 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <time.h> /* Required for utimes on some platforms. */
+#include <unistd.h> /* Required for mkstemp on NetBSD. */
+
+
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <isc/dir.h>
+#include <isc/file.h>
+#include <isc/random.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+/*
+ * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
+ * it might be good to provide a mechanism that allows for the results
+ * of a previous stat() to be used again without having to do another stat,
+ * such as perl's mechanism of using "_" in place of a file name to indicate
+ * that the results of the last stat should be used. But then you get into
+ * annoying MP issues. BTW, Win32 has stat().
+ */
+static isc_result_t
+file_stats(const char *file, struct stat *stats) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(file != NULL);
+ REQUIRE(stats != NULL);
+
+ if (stat(file, stats) != 0)
+ result = isc__errno2result(errno);
+
+ return (result);
+}
+
+isc_result_t
+isc_file_getmodtime(const char *file, isc_time_t *time) {
+ isc_result_t result;
+ struct stat stats;
+
+ REQUIRE(file != NULL);
+ REQUIRE(time != NULL);
+
+ result = file_stats(file, &stats);
+
+ if (result == ISC_R_SUCCESS)
+ /*
+ * XXXDCL some operating systems provide nanoseconds, too,
+ * such as BSD/OS via st_mtimespec.
+ */
+ isc_time_set(time, stats.st_mtime, 0);
+
+ return (result);
+}
+
+isc_result_t
+isc_file_settime(const char *file, isc_time_t *time) {
+ struct timeval times[2];
+
+ REQUIRE(file != NULL && time != NULL);
+
+ /*
+ * tv_sec is at least a 32 bit quantity on all platforms we're
+ * dealing with, but it is signed on most (all?) of them,
+ * so we need to make sure the high bit isn't set. This unfortunately
+ * loses when either:
+ * * tv_sec becomes a signed 64 bit integer but long is 32 bits
+ * and isc_time_seconds > LONG_MAX, or
+ * * isc_time_seconds is changed to be > 32 bits but long is 32 bits
+ * and isc_time_seconds has at least 33 significant bits.
+ */
+ times[0].tv_sec = times[1].tv_sec = (long)isc_time_seconds(time);
+
+ /*
+ * Here is the real check for the high bit being set.
+ */
+ if ((times[0].tv_sec &
+ (1ULL << (sizeof(times[0].tv_sec) * CHAR_BIT - 1))) != 0)
+ return (ISC_R_RANGE);
+
+ /*
+ * isc_time_nanoseconds guarantees a value that divided by 1000 will
+ * fit into the minimum possible size tv_usec field. Unfortunately,
+ * we don't know what that type is so can't cast directly ... but
+ * we can at least cast to signed so the IRIX compiler shuts up.
+ */
+ times[0].tv_usec = times[1].tv_usec =
+ (isc_int32_t)(isc_time_nanoseconds(time) / 1000);
+
+ if (utimes(file, times) < 0)
+ return (isc__errno2result(errno));
+
+ return (ISC_R_SUCCESS);
+}
+
+#undef TEMPLATE
+#define TEMPLATE "tmp-XXXXXXXXXX" /*%< 14 characters. */
+
+isc_result_t
+isc_file_mktemplate(const char *path, char *buf, size_t buflen) {
+ return (isc_file_template(path, TEMPLATE, buf, buflen));
+}
+
+isc_result_t
+isc_file_template(const char *path, const char *templet, char *buf,
+ size_t buflen) {
+ char *s;
+
+ REQUIRE(path != NULL);
+ REQUIRE(templet != NULL);
+ REQUIRE(buf != NULL);
+
+ s = strrchr(templet, '/');
+ if (s != NULL)
+ templet = s + 1;
+
+ s = strrchr(path, '/');
+
+ if (s != NULL) {
+ if ((s - path + 1 + strlen(templet) + 1) > buflen)
+ return (ISC_R_NOSPACE);
+
+ strncpy(buf, path, s - path + 1);
+ buf[s - path + 1] = '\0';
+ strcat(buf, templet);
+ } else {
+ if ((strlen(templet) + 1) > buflen)
+ return (ISC_R_NOSPACE);
+
+ strcpy(buf, templet);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static char alphnum[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+isc_result_t
+isc_file_renameunique(const char *file, char *templet) {
+ char *x;
+ char *cp;
+ isc_uint32_t which;
+
+ REQUIRE(file != NULL);
+ REQUIRE(templet != NULL);
+
+ cp = templet;
+ while (*cp != '\0')
+ cp++;
+ if (cp == templet)
+ return (ISC_R_FAILURE);
+
+ x = cp--;
+ while (cp >= templet && *cp == 'X') {
+ isc_random_get(&which);
+ *cp = alphnum[which % (sizeof(alphnum) - 1)];
+ x = cp--;
+ }
+ while (link(file, templet) == -1) {
+ if (errno != EEXIST)
+ return (isc__errno2result(errno));
+ for (cp = x;;) {
+ char *t;
+ if (*cp == '\0')
+ return (ISC_R_FAILURE);
+ t = strchr(alphnum, *cp);
+ if (t == NULL || *++t == '\0')
+ *cp++ = alphnum[0];
+ else {
+ *cp = *t;
+ break;
+ }
+ }
+ }
+ (void)unlink(file);
+ return (ISC_R_SUCCESS);
+}
+
+
+isc_result_t
+isc_file_openunique(char *templet, 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);
+
+ cp = templet;
+ while (*cp != '\0')
+ cp++;
+ if (cp == templet)
+ return (ISC_R_FAILURE);
+
+ x = cp--;
+ while (cp >= templet && *cp == 'X') {
+ isc_random_get(&which);
+ *cp = alphnum[which % (sizeof(alphnum) - 1)];
+ 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)
+ return (isc__errno2result(errno));
+ for (cp = x;;) {
+ char *t;
+ if (*cp == '\0')
+ return (ISC_R_FAILURE);
+ t = strchr(alphnum, *cp);
+ if (t == NULL || *++t == '\0')
+ *cp++ = alphnum[0];
+ else {
+ *cp = *t;
+ break;
+ }
+ }
+ }
+ f = fdopen(fd, "w+");
+ if (f == NULL) {
+ result = isc__errno2result(errno);
+ (void)remove(templet);
+ (void)close(fd);
+ } else
+ *fp = f;
+
+ return (result);
+}
+
+isc_result_t
+isc_file_remove(const char *filename) {
+ int r;
+
+ REQUIRE(filename != NULL);
+
+ r = unlink(filename);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_file_rename(const char *oldname, const char *newname) {
+ int r;
+
+ REQUIRE(oldname != NULL);
+ REQUIRE(newname != NULL);
+
+ r = rename(oldname, newname);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_boolean_t
+isc_file_exists(const char *pathname) {
+ struct stat stats;
+
+ REQUIRE(pathname != NULL);
+
+ return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
+}
+
+isc_boolean_t
+isc_file_isabsolute(const char *filename) {
+ REQUIRE(filename != NULL);
+ return (ISC_TF(filename[0] == '/'));
+}
+
+isc_boolean_t
+isc_file_iscurrentdir(const char *filename) {
+ REQUIRE(filename != NULL);
+ return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
+}
+
+isc_boolean_t
+isc_file_ischdiridempotent(const char *filename) {
+ REQUIRE(filename != NULL);
+ if (isc_file_isabsolute(filename))
+ return (ISC_TRUE);
+ if (isc_file_iscurrentdir(filename))
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+const char *
+isc_file_basename(const char *filename) {
+ char *s;
+
+ REQUIRE(filename != NULL);
+
+ s = strrchr(filename, '/');
+ if (s == NULL)
+ return (filename);
+
+ return (s + 1);
+}
+
+isc_result_t
+isc_file_progname(const char *filename, char *buf, size_t buflen) {
+ const char *base;
+ size_t len;
+
+ REQUIRE(filename != NULL);
+ REQUIRE(buf != NULL);
+
+ base = isc_file_basename(filename);
+ len = strlen(base) + 1;
+
+ if (len > buflen)
+ return (ISC_R_NOSPACE);
+ memcpy(buf, base, len);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Put the absolute name of the current directory into 'dirname', which is
+ * a buffer of at least 'length' characters. End the string with the
+ * appropriate path separator, such that the final product could be
+ * concatenated with a relative pathname to make a valid pathname string.
+ */
+static isc_result_t
+dir_current(char *dirname, size_t length) {
+ char *cwd;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(dirname != NULL);
+ REQUIRE(length > 0U);
+
+ cwd = getcwd(dirname, length);
+
+ if (cwd == NULL) {
+ if (errno == ERANGE)
+ result = ISC_R_NOSPACE;
+ else
+ result = isc__errno2result(errno);
+ } else {
+ if (strlen(dirname) + 1 == length)
+ result = ISC_R_NOSPACE;
+ else if (dirname[1] != '\0')
+ strcat(dirname, "/");
+ }
+
+ return (result);
+}
+
+isc_result_t
+isc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
+ isc_result_t result;
+ result = dir_current(path, pathlen);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (strlen(path) + strlen(filename) + 1 > pathlen)
+ return (ISC_R_NOSPACE);
+ strcat(path, filename);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_truncate(const char *filename, isc_offset_t size) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ if (truncate(filename, size) < 0)
+ result = isc__errno2result(errno);
+ return (result);
+}
diff --git a/lib/isc/unix/fsaccess.c b/lib/isc/unix/fsaccess.c
new file mode 100644
index 0000000..a2bd89a
--- /dev/null
+++ b/lib/isc/unix/fsaccess.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2004-2007 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: fsaccess.c,v 1.13 2007/06/19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+
+#include "errno2result.h"
+
+/*! \file
+ * \brief
+ * The OS-independent part of the API is in lib/isc.
+ */
+#include "../fsaccess.c"
+
+isc_result_t
+isc_fsaccess_set(const char *path, isc_fsaccess_t access) {
+ struct stat statb;
+ mode_t mode;
+ isc_boolean_t is_dir = ISC_FALSE;
+ isc_fsaccess_t bits;
+ isc_result_t result;
+
+ if (stat(path, &statb) != 0)
+ return (isc__errno2result(errno));
+
+ if ((statb.st_mode & S_IFDIR) != 0)
+ is_dir = ISC_TRUE;
+ else if ((statb.st_mode & S_IFREG) == 0)
+ return (ISC_R_INVALIDFILE);
+
+ result = check_bad_bits(access, is_dir);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Done with checking bad bits. Set mode_t.
+ */
+ mode = 0;
+
+#define SET_AND_CLEAR1(modebit) \
+ if ((access & bits) != 0) { \
+ mode |= modebit; \
+ access &= ~bits; \
+ }
+#define SET_AND_CLEAR(user, group, other) \
+ SET_AND_CLEAR1(user); \
+ bits <<= STEP; \
+ SET_AND_CLEAR1(group); \
+ bits <<= STEP; \
+ SET_AND_CLEAR1(other);
+
+ bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY;
+
+ SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH);
+
+ bits = ISC_FSACCESS_WRITE |
+ ISC_FSACCESS_CREATECHILD |
+ ISC_FSACCESS_DELETECHILD;
+
+ SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH);
+
+ bits = ISC_FSACCESS_EXECUTE |
+ ISC_FSACCESS_ACCESSCHILD;
+
+ SET_AND_CLEAR(S_IXUSR, S_IXGRP, S_IXOTH);
+
+ INSIST(access == 0);
+
+ if (chmod(path, mode) < 0)
+ return (isc__errno2result(errno));
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/unix/ifiter_getifaddrs.c b/lib/isc/unix/ifiter_getifaddrs.c
new file mode 100644
index 0000000..b576d46
--- /dev/null
+++ b/lib/isc/unix/ifiter_getifaddrs.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: ifiter_getifaddrs.c,v 1.11 2008/03/20 23:47:00 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Obtain the list of network interfaces using the getifaddrs(3) library.
+ */
+
+#include <ifaddrs.h>
+
+/*% Iterator Magic */
+#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'G')
+/*% Valid Iterator */
+#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
+
+#ifdef __linux
+static isc_boolean_t seenv6 = ISC_FALSE;
+#endif
+
+/*% Iterator structure */
+struct isc_interfaceiter {
+ unsigned int magic; /*%< Magic number. */
+ isc_mem_t *mctx;
+ void *buf; /*%< (unused) */
+ unsigned int bufsize; /*%< (always 0) */
+ struct ifaddrs *ifaddrs; /*%< List of ifaddrs */
+ struct ifaddrs *pos; /*%< Ptr to current ifaddr */
+ isc_interface_t current; /*%< Current interface data. */
+ isc_result_t result; /*%< Last result code. */
+#ifdef __linux
+ FILE * proc;
+ char entry[ISC_IF_INET6_SZ];
+ isc_result_t valid;
+#endif
+};
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
+ isc_interfaceiter_t *iter;
+ isc_result_t result;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(iterp != NULL);
+ REQUIRE(*iterp == NULL);
+
+ iter = isc_mem_get(mctx, sizeof(*iter));
+ if (iter == NULL)
+ return (ISC_R_NOMEMORY);
+
+ iter->mctx = mctx;
+ iter->buf = NULL;
+ iter->bufsize = 0;
+ iter->ifaddrs = NULL;
+#ifdef __linux
+ /*
+ * Only open "/proc/net/if_inet6" if we have never seen a IPv6
+ * address returned by getifaddrs().
+ */
+ if (!seenv6)
+ iter->proc = fopen("/proc/net/if_inet6", "r");
+ else
+ iter->proc = NULL;
+ iter->valid = ISC_R_FAILURE;
+#endif
+
+ if (getifaddrs(&iter->ifaddrs) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERGETIFADDRS,
+ ISC_MSG_GETIFADDRS,
+ "getting interface "
+ "addresses: getifaddrs: %s"),
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto failure;
+ }
+
+ /*
+ * A newly created iterator has an undefined position
+ * until isc_interfaceiter_first() is called.
+ */
+ iter->pos = NULL;
+ iter->result = ISC_R_FAILURE;
+
+ iter->magic = IFITER_MAGIC;
+ *iterp = iter;
+ return (ISC_R_SUCCESS);
+
+ failure:
+#ifdef __linux
+ if (iter->proc != NULL)
+ fclose(iter->proc);
+#endif
+ if (iter->ifaddrs != NULL) /* just in case */
+ freeifaddrs(iter->ifaddrs);
+ isc_mem_put(mctx, iter, sizeof(*iter));
+ return (result);
+}
+
+/*
+ * Get information about the current interface to iter->current.
+ * If successful, return ISC_R_SUCCESS.
+ * If the interface has an unsupported address family,
+ * return ISC_R_IGNORE.
+ */
+
+static isc_result_t
+internal_current(isc_interfaceiter_t *iter) {
+ struct ifaddrs *ifa;
+ int family;
+ unsigned int namelen;
+
+ REQUIRE(VALID_IFITER(iter));
+
+ ifa = iter->pos;
+
+#ifdef __linux
+ if (iter->pos == NULL)
+ return (linux_if_inet6_current(iter));
+#endif
+
+ INSIST(ifa != NULL);
+ INSIST(ifa->ifa_name != NULL);
+
+ if (ifa->ifa_addr == NULL)
+ return (ISC_R_IGNORE);
+
+ family = ifa->ifa_addr->sa_family;
+ if (family != AF_INET && family != AF_INET6)
+ return (ISC_R_IGNORE);
+
+#ifdef __linux
+ if (family == AF_INET6)
+ seenv6 = ISC_TRUE;
+#endif
+
+ memset(&iter->current, 0, sizeof(iter->current));
+
+ namelen = strlen(ifa->ifa_name);
+ if (namelen > sizeof(iter->current.name) - 1)
+ namelen = sizeof(iter->current.name) - 1;
+
+ memset(iter->current.name, 0, sizeof(iter->current.name));
+ memcpy(iter->current.name, ifa->ifa_name, namelen);
+
+ iter->current.flags = 0;
+
+ if ((ifa->ifa_flags & IFF_UP) != 0)
+ iter->current.flags |= INTERFACE_F_UP;
+
+ if ((ifa->ifa_flags & IFF_POINTOPOINT) != 0)
+ iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+
+ if ((ifa->ifa_flags & IFF_LOOPBACK) != 0)
+ iter->current.flags |= INTERFACE_F_LOOPBACK;
+
+ iter->current.af = family;
+
+ get_addr(family, &iter->current.address, ifa->ifa_addr, ifa->ifa_name);
+
+ if (ifa->ifa_netmask != NULL)
+ get_addr(family, &iter->current.netmask, ifa->ifa_netmask,
+ ifa->ifa_name);
+
+ if (ifa->ifa_dstaddr != NULL &&
+ (iter->current.flags & IFF_POINTOPOINT) != 0)
+ get_addr(family, &iter->current.dstaddress, ifa->ifa_dstaddr,
+ ifa->ifa_name);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Step the iterator to the next interface. Unlike
+ * isc_interfaceiter_next(), this may leave the iterator
+ * positioned on an interface that will ultimately
+ * be ignored. Return ISC_R_NOMORE if there are no more
+ * interfaces, otherwise ISC_R_SUCCESS.
+ */
+static isc_result_t
+internal_next(isc_interfaceiter_t *iter) {
+
+ if (iter->pos != NULL)
+ iter->pos = iter->pos->ifa_next;
+ if (iter->pos == NULL) {
+#ifdef __linux
+ if (!seenv6)
+ return (linux_if_inet6_next(iter));
+#endif
+ return (ISC_R_NOMORE);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+internal_destroy(isc_interfaceiter_t *iter) {
+
+#ifdef __linux
+ if (iter->proc != NULL)
+ fclose(iter->proc);
+ iter->proc = NULL;
+#endif
+ if (iter->ifaddrs)
+ freeifaddrs(iter->ifaddrs);
+ iter->ifaddrs = NULL;
+}
+
+static
+void internal_first(isc_interfaceiter_t *iter) {
+
+#ifdef __linux
+ linux_if_inet6_first(iter);
+#endif
+ iter->pos = iter->ifaddrs;
+}
diff --git a/lib/isc/unix/ifiter_ioctl.c b/lib/isc/unix/ifiter_ioctl.c
new file mode 100644
index 0000000..7731437
--- /dev/null
+++ b/lib/isc/unix/ifiter_ioctl.c
@@ -0,0 +1,931 @@
+/*
+ * Copyright (C) 2004-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
+ * 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: ifiter_ioctl.c,v 1.60 2008/03/20 23:47:00 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Obtain the list of network interfaces using the SIOCGLIFCONF ioctl.
+ * See netintro(4).
+ */
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+#ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
+#define lifc_len iflc_len
+#define lifc_buf iflc_buf
+#define lifc_req iflc_req
+#define LIFCONF if_laddrconf
+#else
+#define ISC_HAVE_LIFC_FAMILY 1
+#define ISC_HAVE_LIFC_FLAGS 1
+#define LIFCONF lifconf
+#endif
+
+#ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
+#define lifr_addr iflr_addr
+#define lifr_name iflr_name
+#define lifr_dstaddr iflr_dstaddr
+#define lifr_flags iflr_flags
+#define ss_family sa_family
+#define LIFREQ if_laddrreq
+#else
+#define LIFREQ lifreq
+#endif
+#endif
+
+#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'T')
+#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
+
+struct isc_interfaceiter {
+ unsigned int magic; /* Magic number. */
+ isc_mem_t *mctx;
+ int mode;
+ int socket;
+ struct ifconf ifc;
+ void *buf; /* Buffer for sysctl data. */
+ unsigned int bufsize; /* Bytes allocated. */
+ unsigned int pos; /* Current offset in
+ SIOCGIFCONF data */
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+ int socket6;
+ struct LIFCONF lifc;
+ void *buf6; /* Buffer for sysctl data. */
+ unsigned int bufsize6; /* Bytes allocated. */
+ unsigned int pos6; /* Current offset in
+ SIOCGLIFCONF data */
+ isc_result_t result6; /* Last result code. */
+ isc_boolean_t first6;
+#endif
+#ifdef HAVE_TRUCLUSTER
+ int clua_context; /* Cluster alias context */
+ isc_boolean_t clua_done;
+ struct sockaddr clua_sa;
+#endif
+#ifdef __linux
+ FILE * proc;
+ char entry[ISC_IF_INET6_SZ];
+ isc_result_t valid;
+#endif
+ isc_interface_t current; /* Current interface data. */
+ isc_result_t result; /* Last result code. */
+};
+
+#ifdef HAVE_TRUCLUSTER
+#include <clua/clua.h>
+#include <sys/socket.h>
+#endif
+
+
+/*%
+ * Size of buffer for SIOCGLIFCONF, in bytes. We assume no sane system
+ * will have more than a megabyte of interface configuration data.
+ */
+#define IFCONF_BUFSIZE_INITIAL 4096
+#define IFCONF_BUFSIZE_MAX 1048576
+
+#ifdef __linux
+#ifndef IF_NAMESIZE
+# ifdef IFNAMSIZ
+# define IF_NAMESIZE IFNAMSIZ
+# else
+# define IF_NAMESIZE 16
+# endif
+#endif
+#endif
+
+static isc_result_t
+getbuf4(isc_interfaceiter_t *iter) {
+ char strbuf[ISC_STRERRORSIZE];
+
+ iter->bufsize = IFCONF_BUFSIZE_INITIAL;
+
+ for (;;) {
+ iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
+ if (iter->buf == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(&iter->ifc.ifc_len, 0, sizeof(iter->ifc.ifc_len));
+ iter->ifc.ifc_len = iter->bufsize;
+ iter->ifc.ifc_buf = iter->buf;
+ /*
+ * Ignore the HP/UX warning about "interger overflow during
+ * conversion". It comes from its own macro definition,
+ * and is really hard to shut up.
+ */
+ if (ioctl(iter->socket, SIOCGIFCONF, (char *)&iter->ifc)
+ == -1) {
+ if (errno != EINVAL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_GETIFCONFIG,
+ "get interface "
+ "configuration: %s"),
+ strbuf);
+ goto unexpected;
+ }
+ /*
+ * EINVAL. Retry with a bigger buffer.
+ */
+ } else {
+ /*
+ * The ioctl succeeded.
+ * Some OS's just return what will fit rather
+ * than set EINVAL if the buffer is too small
+ * to fit all the interfaces in. If
+ * ifc.lifc_len is too near to the end of the
+ * buffer we will grow it just in case and
+ * retry.
+ */
+ if (iter->ifc.ifc_len + 2 * sizeof(struct ifreq)
+ < iter->bufsize)
+ break;
+ }
+ if (iter->bufsize >= IFCONF_BUFSIZE_MAX) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_BUFFERMAX,
+ "get interface "
+ "configuration: "
+ "maximum buffer "
+ "size exceeded"));
+ goto unexpected;
+ }
+ isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
+
+ iter->bufsize *= 2;
+ }
+ return (ISC_R_SUCCESS);
+
+ unexpected:
+ isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
+ iter->buf = NULL;
+ return (ISC_R_UNEXPECTED);
+}
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+static isc_result_t
+getbuf6(isc_interfaceiter_t *iter) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc_result_t result;
+
+ iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;
+
+ for (;;) {
+ iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
+ if (iter->buf6 == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(&iter->lifc, 0, sizeof(iter->lifc));
+#ifdef ISC_HAVE_LIFC_FAMILY
+ iter->lifc.lifc_family = AF_INET6;
+#endif
+#ifdef ISC_HAVE_LIFC_FLAGS
+ iter->lifc.lifc_flags = 0;
+#endif
+ iter->lifc.lifc_len = iter->bufsize6;
+ iter->lifc.lifc_buf = iter->buf6;
+ /*
+ * Ignore the HP/UX warning about "interger overflow during
+ * conversion". It comes from its own macro definition,
+ * and is really hard to shut up.
+ */
+ if (ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
+ == -1) {
+#ifdef __hpux
+ /*
+ * IPv6 interface scanning is not available on all
+ * kernels w/ IPv6 sockets.
+ */
+ if (errno == ENOENT) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_INTERFACE,
+ ISC_LOG_DEBUG(1),
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_GETIFCONFIG,
+ "get interface "
+ "configuration: %s"),
+ strbuf);
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+#endif
+ if (errno != EINVAL) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_GETIFCONFIG,
+ "get interface "
+ "configuration: %s"),
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+ /*
+ * EINVAL. Retry with a bigger buffer.
+ */
+ } else {
+ /*
+ * The ioctl succeeded.
+ * Some OS's just return what will fit rather
+ * than set EINVAL if the buffer is too small
+ * to fit all the interfaces in. If
+ * ifc.ifc_len is too near to the end of the
+ * buffer we will grow it just in case and
+ * retry.
+ */
+ if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
+ < iter->bufsize6)
+ break;
+ }
+ if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_BUFFERMAX,
+ "get interface "
+ "configuration: "
+ "maximum buffer "
+ "size exceeded"));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+ isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
+
+ iter->bufsize6 *= 2;
+ }
+
+ if (iter->lifc.lifc_len != 0)
+ iter->mode = 6;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
+ iter->buf6 = NULL;
+ return (result);
+}
+#endif
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
+ isc_interfaceiter_t *iter;
+ isc_result_t result;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(iterp != NULL);
+ REQUIRE(*iterp == NULL);
+
+ iter = isc_mem_get(mctx, sizeof(*iter));
+ if (iter == NULL)
+ return (ISC_R_NOMEMORY);
+
+ iter->mctx = mctx;
+ iter->mode = 4;
+ iter->buf = NULL;
+ iter->pos = (unsigned int) -1;
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+ iter->buf6 = NULL;
+ iter->pos6 = (unsigned int) -1;
+ iter->result6 = ISC_R_NOMORE;
+ iter->socket6 = -1;
+ iter->first6 = ISC_FALSE;
+#endif
+
+ /*
+ * Get the interface configuration, allocating more memory if
+ * necessary.
+ */
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+ result = isc_net_probeipv6();
+ if (result == ISC_R_SUCCESS) {
+ /*
+ * Create an unbound datagram socket to do the SIOCGLIFCONF
+ * ioctl on. HP/UX requires an AF_INET6 socket for
+ * SIOCGLIFCONF to get IPv6 addresses.
+ */
+ if ((iter->socket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_MAKESCANSOCKET,
+ "making interface "
+ "scan socket: %s"),
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto socket6_failure;
+ }
+ result = iter->result6 = getbuf6(iter);
+ if (result != ISC_R_NOTIMPLEMENTED && result != ISC_R_SUCCESS)
+ goto ioctl6_failure;
+ }
+#endif
+ if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_MAKESCANSOCKET,
+ "making interface "
+ "scan socket: %s"),
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto socket_failure;
+ }
+ result = getbuf4(iter);
+ if (result != ISC_R_SUCCESS)
+ goto ioctl_failure;
+
+ /*
+ * A newly created iterator has an undefined position
+ * until isc_interfaceiter_first() is called.
+ */
+#ifdef HAVE_TRUCLUSTER
+ iter->clua_context = -1;
+ iter->clua_done = ISC_TRUE;
+#endif
+#ifdef __linux
+ iter->proc = fopen("/proc/net/if_inet6", "r");
+ iter->valid = ISC_R_FAILURE;
+#endif
+ iter->result = ISC_R_FAILURE;
+
+ iter->magic = IFITER_MAGIC;
+ *iterp = iter;
+ return (ISC_R_SUCCESS);
+
+ ioctl_failure:
+ if (iter->buf != NULL)
+ isc_mem_put(mctx, iter->buf, iter->bufsize);
+ (void) close(iter->socket);
+
+ socket_failure:
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+ if (iter->buf6 != NULL)
+ isc_mem_put(mctx, iter->buf6, iter->bufsize6);
+ ioctl6_failure:
+ if (iter->socket6 != -1)
+ (void) close(iter->socket6);
+ socket6_failure:
+#endif
+
+ isc_mem_put(mctx, iter, sizeof(*iter));
+ return (result);
+}
+
+#ifdef HAVE_TRUCLUSTER
+static void
+get_inaddr(isc_netaddr_t *dst, struct in_addr *src) {
+ dst->family = AF_INET;
+ memcpy(&dst->type.in, src, sizeof(struct in_addr));
+}
+
+static isc_result_t
+internal_current_clusteralias(isc_interfaceiter_t *iter) {
+ struct clua_info ci;
+ if (clua_getaliasinfo(&iter->clua_sa, &ci) != CLUA_SUCCESS)
+ return (ISC_R_IGNORE);
+ memset(&iter->current, 0, sizeof(iter->current));
+ iter->current.af = iter->clua_sa.sa_family;
+ memset(iter->current.name, 0, sizeof(iter->current.name));
+ sprintf(iter->current.name, "clua%d", ci.aliasid);
+ iter->current.flags = INTERFACE_F_UP;
+ get_inaddr(&iter->current.address, &ci.addr);
+ get_inaddr(&iter->current.netmask, &ci.netmask);
+ return (ISC_R_SUCCESS);
+}
+#endif
+
+/*
+ * Get information about the current interface to iter->current.
+ * If successful, return ISC_R_SUCCESS.
+ * If the interface has an unsupported address family, or if
+ * some operation on it fails, return ISC_R_IGNORE to make
+ * the higher-level iterator code ignore it.
+ */
+
+static isc_result_t
+internal_current4(isc_interfaceiter_t *iter) {
+ struct ifreq *ifrp;
+ struct ifreq ifreq;
+ int family;
+ char strbuf[ISC_STRERRORSIZE];
+#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
+ struct lifreq lifreq;
+#else
+ char sabuf[256];
+#endif
+ int i, bits, prefixlen;
+
+ REQUIRE(VALID_IFITER(iter));
+
+ if (iter->ifc.ifc_len == 0 ||
+ iter->pos == (unsigned int)iter->ifc.ifc_len) {
+#ifdef __linux
+ return (linux_if_inet6_current(iter));
+#else
+ return (ISC_R_NOMORE);
+#endif
+ }
+
+ INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len);
+
+ ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
+
+ memset(&ifreq, 0, sizeof(ifreq));
+ memcpy(&ifreq, ifrp, sizeof(ifreq));
+
+ family = ifreq.ifr_addr.sa_family;
+#if defined(ISC_PLATFORM_HAVEIPV6)
+ if (family != AF_INET && family != AF_INET6)
+#else
+ if (family != AF_INET)
+#endif
+ return (ISC_R_IGNORE);
+
+ memset(&iter->current, 0, sizeof(iter->current));
+ iter->current.af = family;
+
+ INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
+ memset(iter->current.name, 0, sizeof(iter->current.name));
+ memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));
+
+ get_addr(family, &iter->current.address,
+ (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);
+
+ /*
+ * If the interface does not have a address ignore it.
+ */
+ switch (family) {
+ case AF_INET:
+ if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
+ return (ISC_R_IGNORE);
+ break;
+ case AF_INET6:
+ if (memcmp(&iter->current.address.type.in6, &in6addr_any,
+ sizeof(in6addr_any)) == 0)
+ return (ISC_R_IGNORE);
+ break;
+ }
+
+ /*
+ * Get interface flags.
+ */
+
+ iter->current.flags = 0;
+
+ /*
+ * Ignore the HP/UX warning about "interger overflow during
+ * conversion. It comes from its own macro definition,
+ * and is really hard to shut up.
+ */
+ if (ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "%s: getting interface flags: %s",
+ ifreq.ifr_name, strbuf);
+ return (ISC_R_IGNORE);
+ }
+
+ if ((ifreq.ifr_flags & IFF_UP) != 0)
+ iter->current.flags |= INTERFACE_F_UP;
+
+#ifdef IFF_POINTOPOINT
+ if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
+ iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+#endif
+
+ if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
+ iter->current.flags |= INTERFACE_F_LOOPBACK;
+
+ if (family == AF_INET)
+ goto inet;
+
+#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
+ memset(&lifreq, 0, sizeof(lifreq));
+ memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
+ memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
+ sizeof(iter->current.address.type.in6));
+
+ if (ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "%s: getting interface address: %s",
+ ifreq.ifr_name, strbuf);
+ return (ISC_R_IGNORE);
+ }
+ prefixlen = lifreq.lifr_addrlen;
+#else
+ isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_INTERFACE,
+ ISC_LOG_INFO,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_GETIFCONFIG,
+ "prefix length for %s is unknown "
+ "(assume 128)"), sabuf);
+ prefixlen = 128;
+#endif
+
+ /*
+ * Netmask already zeroed.
+ */
+ iter->current.netmask.family = family;
+ for (i = 0; i < 16; i++) {
+ if (prefixlen > 8) {
+ bits = 0;
+ prefixlen -= 8;
+ } else {
+ bits = 8 - prefixlen;
+ prefixlen = 0;
+ }
+ iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
+ }
+ return (ISC_R_SUCCESS);
+
+ inet:
+ if (family != AF_INET)
+ return (ISC_R_IGNORE);
+#ifdef IFF_POINTOPOINT
+ /*
+ * If the interface is point-to-point, get the destination address.
+ */
+ if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+ /*
+ * Ignore the HP/UX warning about "interger overflow during
+ * conversion. It comes from its own macro definition,
+ * and is really hard to shut up.
+ */
+ if (ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
+ < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_GETDESTADDR,
+ "%s: getting "
+ "destination address: %s"),
+ ifreq.ifr_name, strbuf);
+ return (ISC_R_IGNORE);
+ }
+ get_addr(family, &iter->current.dstaddress,
+ (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
+ }
+#endif
+
+ /*
+ * Get the network mask.
+ */
+ memset(&ifreq, 0, sizeof(ifreq));
+ memcpy(&ifreq, ifrp, sizeof(ifreq));
+ /*
+ * Ignore the HP/UX warning about "interger overflow during
+ * conversion. It comes from its own macro definition,
+ * and is really hard to shut up.
+ */
+ if (ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_GETNETMASK,
+ "%s: getting netmask: %s"),
+ ifreq.ifr_name, strbuf);
+ return (ISC_R_IGNORE);
+ }
+ get_addr(family, &iter->current.netmask,
+ (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
+ return (ISC_R_SUCCESS);
+}
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+static isc_result_t
+internal_current6(isc_interfaceiter_t *iter) {
+ struct LIFREQ *ifrp;
+ struct LIFREQ lifreq;
+ int family;
+ char strbuf[ISC_STRERRORSIZE];
+ int fd;
+
+ REQUIRE(VALID_IFITER(iter));
+ if (iter->result6 != ISC_R_SUCCESS)
+ return (iter->result6);
+ REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
+
+ ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
+
+ memset(&lifreq, 0, sizeof(lifreq));
+ memcpy(&lifreq, ifrp, sizeof(lifreq));
+
+ family = lifreq.lifr_addr.ss_family;
+#ifdef ISC_PLATFORM_HAVEIPV6
+ if (family != AF_INET && family != AF_INET6)
+#else
+ if (family != AF_INET)
+#endif
+ return (ISC_R_IGNORE);
+
+ memset(&iter->current, 0, sizeof(iter->current));
+ iter->current.af = family;
+
+ INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name));
+ memset(iter->current.name, 0, sizeof(iter->current.name));
+ memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name));
+
+ get_addr(family, &iter->current.address,
+ (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
+
+ /*
+ * If the interface does not have a address ignore it.
+ */
+ switch (family) {
+ case AF_INET:
+ if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
+ return (ISC_R_IGNORE);
+ break;
+ case AF_INET6:
+ if (memcmp(&iter->current.address.type.in6, &in6addr_any,
+ sizeof(in6addr_any)) == 0)
+ return (ISC_R_IGNORE);
+ break;
+ }
+
+ /*
+ * Get interface flags.
+ */
+
+ iter->current.flags = 0;
+
+ if (family == AF_INET6)
+ fd = iter->socket6;
+ else
+ fd = iter->socket;
+
+ /*
+ * Ignore the HP/UX warning about "interger overflow during
+ * conversion. It comes from its own macro definition,
+ * and is really hard to shut up.
+ */
+ if (ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "%s: getting interface flags: %s",
+ lifreq.lifr_name, strbuf);
+ return (ISC_R_IGNORE);
+ }
+
+ if ((lifreq.lifr_flags & IFF_UP) != 0)
+ iter->current.flags |= INTERFACE_F_UP;
+
+#ifdef IFF_POINTOPOINT
+ if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0)
+ iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+#endif
+
+ if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0)
+ iter->current.flags |= INTERFACE_F_LOOPBACK;
+
+#ifdef IFF_POINTOPOINT
+ /*
+ * If the interface is point-to-point, get the destination address.
+ */
+ if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+ /*
+ * Ignore the HP/UX warning about "interger overflow during
+ * conversion. It comes from its own macro definition,
+ * and is really hard to shut up.
+ */
+ if (ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq)
+ < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_GETDESTADDR,
+ "%s: getting "
+ "destination address: %s"),
+ lifreq.lifr_name, strbuf);
+ return (ISC_R_IGNORE);
+ }
+ get_addr(family, &iter->current.dstaddress,
+ (struct sockaddr *)&lifreq.lifr_dstaddr,
+ lifreq.lifr_name);
+ }
+#endif
+
+ /*
+ * Get the network mask. Netmask already zeroed.
+ */
+ memset(&lifreq, 0, sizeof(lifreq));
+ memcpy(&lifreq, ifrp, sizeof(lifreq));
+
+#ifdef lifr_addrlen
+ /*
+ * Special case: if the system provides lifr_addrlen member, the
+ * netmask of an IPv6 address can be derived from the length, since
+ * an IPv6 address always has a contiguous mask.
+ */
+ if (family == AF_INET6) {
+ int i, bits;
+
+ iter->current.netmask.family = family;
+ for (i = 0; i < lifreq.lifr_addrlen; i += 8) {
+ bits = lifreq.lifr_addrlen - i;
+ bits = (bits < 8) ? (8 - bits) : 0;
+ iter->current.netmask.type.in6.s6_addr[i / 8] =
+ (~0 << bits) & 0xff;
+ }
+
+ return (ISC_R_SUCCESS);
+ }
+#endif
+
+ /*
+ * Ignore the HP/UX warning about "interger overflow during
+ * conversion. It comes from its own macro definition,
+ * and is really hard to shut up.
+ */
+ if (ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERIOCTL,
+ ISC_MSG_GETNETMASK,
+ "%s: getting netmask: %s"),
+ lifreq.lifr_name, strbuf);
+ return (ISC_R_IGNORE);
+ }
+ get_addr(family, &iter->current.netmask,
+ (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name);
+
+ return (ISC_R_SUCCESS);
+}
+#endif
+
+static isc_result_t
+internal_current(isc_interfaceiter_t *iter) {
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+ if (iter->mode == 6) {
+ iter->result6 = internal_current6(iter);
+ if (iter->result6 != ISC_R_NOMORE)
+ return (iter->result6);
+ }
+#endif
+#ifdef HAVE_TRUCLUSTER
+ if (!iter->clua_done)
+ return(internal_current_clusteralias(iter));
+#endif
+ return (internal_current4(iter));
+}
+
+/*
+ * Step the iterator to the next interface. Unlike
+ * isc_interfaceiter_next(), this may leave the iterator
+ * positioned on an interface that will ultimately
+ * be ignored. Return ISC_R_NOMORE if there are no more
+ * interfaces, otherwise ISC_R_SUCCESS.
+ */
+static isc_result_t
+internal_next4(isc_interfaceiter_t *iter) {
+#ifdef ISC_PLATFORM_HAVESALEN
+ struct ifreq *ifrp;
+#endif
+
+ if (iter->pos < (unsigned int) iter->ifc.ifc_len) {
+#ifdef ISC_PLATFORM_HAVESALEN
+ ifrp = (struct ifreq *)((char *) iter->ifc.ifc_req + iter->pos);
+
+ if (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr))
+ iter->pos += sizeof(ifrp->ifr_name) +
+ ifrp->ifr_addr.sa_len;
+ else
+#endif
+ iter->pos += sizeof(struct ifreq);
+
+ } else {
+ INSIST(iter->pos == (unsigned int) iter->ifc.ifc_len);
+#ifdef __linux
+ return (linux_if_inet6_next(iter));
+#else
+ return (ISC_R_NOMORE);
+#endif
+ }
+ return (ISC_R_SUCCESS);
+}
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+static isc_result_t
+internal_next6(isc_interfaceiter_t *iter) {
+#ifdef ISC_PLATFORM_HAVESALEN
+ struct LIFREQ *ifrp;
+#endif
+
+ if (iter->result6 != ISC_R_SUCCESS && iter->result6 != ISC_R_IGNORE)
+ return (iter->result6);
+
+ REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len);
+
+#ifdef ISC_PLATFORM_HAVESALEN
+ ifrp = (struct LIFREQ *)((char *) iter->lifc.lifc_req + iter->pos6);
+
+ if (ifrp->lifr_addr.sa_len > sizeof(struct sockaddr))
+ iter->pos6 += sizeof(ifrp->lifr_name) + ifrp->lifr_addr.sa_len;
+ else
+#endif
+ iter->pos6 += sizeof(struct LIFREQ);
+
+ if (iter->pos6 >= (unsigned int) iter->lifc.lifc_len)
+ return (ISC_R_NOMORE);
+
+ return (ISC_R_SUCCESS);
+}
+#endif
+
+static isc_result_t
+internal_next(isc_interfaceiter_t *iter) {
+#ifdef HAVE_TRUCLUSTER
+ int clua_result;
+#endif
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+ if (iter->mode == 6) {
+ iter->result6 = internal_next6(iter);
+ if (iter->result6 != ISC_R_NOMORE)
+ return (iter->result6);
+ if (iter->first6) {
+ iter->first6 = ISC_FALSE;
+ return (ISC_R_SUCCESS);
+ }
+ }
+#endif
+#ifdef HAVE_TRUCLUSTER
+ if (!iter->clua_done) {
+ clua_result = clua_getaliasaddress(&iter->clua_sa,
+ &iter->clua_context);
+ if (clua_result != CLUA_SUCCESS)
+ iter->clua_done = ISC_TRUE;
+ return (ISC_R_SUCCESS);
+ }
+#endif
+ return (internal_next4(iter));
+}
+
+static void
+internal_destroy(isc_interfaceiter_t *iter) {
+ (void) close(iter->socket);
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+ if (iter->socket6 != -1)
+ (void) close(iter->socket6);
+ if (iter->buf6 != NULL) {
+ isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
+ }
+#endif
+#ifdef __linux
+ if (iter->proc != NULL)
+ fclose(iter->proc);
+#endif
+}
+
+static
+void internal_first(isc_interfaceiter_t *iter) {
+#ifdef HAVE_TRUCLUSTER
+ int clua_result;
+#endif
+ iter->pos = 0;
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR)
+ iter->pos6 = 0;
+ if (iter->result6 == ISC_R_NOMORE)
+ iter->result6 = ISC_R_SUCCESS;
+ iter->first6 = ISC_TRUE;
+#endif
+#ifdef HAVE_TRUCLUSTER
+ iter->clua_context = 0;
+ clua_result = clua_getaliasaddress(&iter->clua_sa,
+ &iter->clua_context);
+ iter->clua_done = ISC_TF(clua_result != CLUA_SUCCESS);
+#endif
+#ifdef __linux
+ linux_if_inet6_first(iter);
+#endif
+}
diff --git a/lib/isc/unix/ifiter_sysctl.c b/lib/isc/unix/ifiter_sysctl.c
new file mode 100644
index 0000000..9d5bf6d
--- /dev/null
+++ b/lib/isc/unix/ifiter_sysctl.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: ifiter_sysctl.c,v 1.25 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file
+ * \brief
+ * Obtain the list of network interfaces using sysctl.
+ * See TCP/IP Illustrated Volume 2, sections 19.8, 19.14,
+ * and 19.16.
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <net/route.h>
+#include <net/if_dl.h>
+
+/* XXX what about Alpha? */
+#ifdef sgi
+#define ROUNDUP(a) ((a) > 0 ? \
+ (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) : \
+ sizeof(__uint64_t))
+#else
+#define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
+ : sizeof(long))
+#endif
+
+#define IFITER_MAGIC ISC_MAGIC('I', 'F', 'I', 'S')
+#define VALID_IFITER(t) ISC_MAGIC_VALID(t, IFITER_MAGIC)
+
+struct isc_interfaceiter {
+ unsigned int magic; /* Magic number. */
+ isc_mem_t *mctx;
+ void *buf; /* Buffer for sysctl data. */
+ unsigned int bufsize; /* Bytes allocated. */
+ unsigned int bufused; /* Bytes used. */
+ unsigned int pos; /* Current offset in
+ sysctl data. */
+ isc_interface_t current; /* Current interface data. */
+ isc_result_t result; /* Last result code. */
+};
+
+static int mib[6] = {
+ CTL_NET,
+ PF_ROUTE,
+ 0,
+ 0, /* Any address family. */
+ NET_RT_IFLIST,
+ 0 /* Flags. */
+};
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
+ isc_interfaceiter_t *iter;
+ isc_result_t result;
+ size_t bufsize;
+ size_t bufused;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(iterp != NULL);
+ REQUIRE(*iterp == NULL);
+
+ iter = isc_mem_get(mctx, sizeof(*iter));
+ if (iter == NULL)
+ return (ISC_R_NOMEMORY);
+
+ iter->mctx = mctx;
+ iter->buf = 0;
+
+ /*
+ * Determine the amount of memory needed.
+ */
+ bufsize = 0;
+ if (sysctl(mib, 6, NULL, &bufsize, NULL, (size_t) 0) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERSYSCTL,
+ ISC_MSG_GETIFLISTSIZE,
+ "getting interface "
+ "list size: sysctl: %s"),
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto failure;
+ }
+ iter->bufsize = bufsize;
+
+ iter->buf = isc_mem_get(iter->mctx, iter->bufsize);
+ if (iter->buf == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto failure;
+ }
+
+ bufused = bufsize;
+ if (sysctl(mib, 6, iter->buf, &bufused, NULL, (size_t) 0) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_IFITERSYSCTL,
+ ISC_MSG_GETIFLIST,
+ "getting interface list: "
+ "sysctl: %s"),
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto failure;
+ }
+ iter->bufused = bufused;
+ INSIST(iter->bufused <= iter->bufsize);
+
+ /*
+ * A newly created iterator has an undefined position
+ * until isc_interfaceiter_first() is called.
+ */
+ iter->pos = (unsigned int) -1;
+ iter->result = ISC_R_FAILURE;
+
+ iter->magic = IFITER_MAGIC;
+ *iterp = iter;
+ return (ISC_R_SUCCESS);
+
+ failure:
+ if (iter->buf != NULL)
+ isc_mem_put(mctx, iter->buf, iter->bufsize);
+ isc_mem_put(mctx, iter, sizeof(*iter));
+ return (result);
+}
+
+/*
+ * Get information about the current interface to iter->current.
+ * If successful, return ISC_R_SUCCESS.
+ * If the interface has an unsupported address family,
+ * return ISC_R_IGNORE. In case of other failure,
+ * return ISC_R_UNEXPECTED.
+ */
+
+static isc_result_t
+internal_current(isc_interfaceiter_t *iter) {
+ struct ifa_msghdr *ifam, *ifam_end;
+
+ REQUIRE(VALID_IFITER(iter));
+ REQUIRE (iter->pos < (unsigned int) iter->bufused);
+
+ ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
+ ifam_end = (struct ifa_msghdr *) ((char *) iter->buf + iter->bufused);
+
+ if (ifam->ifam_type == RTM_IFINFO) {
+ struct if_msghdr *ifm = (struct if_msghdr *) ifam;
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *) (ifm + 1);
+ unsigned int namelen;
+
+ memset(&iter->current, 0, sizeof(iter->current));
+
+ namelen = sdl->sdl_nlen;
+ if (namelen > sizeof(iter->current.name) - 1)
+ namelen = sizeof(iter->current.name) - 1;
+
+ memset(iter->current.name, 0, sizeof(iter->current.name));
+ memcpy(iter->current.name, sdl->sdl_data, namelen);
+
+ iter->current.flags = 0;
+
+ if ((ifam->ifam_flags & IFF_UP) != 0)
+ iter->current.flags |= INTERFACE_F_UP;
+
+ if ((ifam->ifam_flags & IFF_POINTOPOINT) != 0)
+ iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+
+ if ((ifam->ifam_flags & IFF_LOOPBACK) != 0)
+ iter->current.flags |= INTERFACE_F_LOOPBACK;
+
+ /*
+ * This is not an interface address.
+ * Force another iteration.
+ */
+ return (ISC_R_IGNORE);
+ } else if (ifam->ifam_type == RTM_NEWADDR) {
+ int i;
+ int family;
+ struct sockaddr *mask_sa = NULL;
+ struct sockaddr *addr_sa = NULL;
+ struct sockaddr *dst_sa = NULL;
+
+ struct sockaddr *sa = (struct sockaddr *)(ifam + 1);
+ family = sa->sa_family;
+
+ for (i = 0; i < RTAX_MAX; i++)
+ {
+ if ((ifam->ifam_addrs & (1 << i)) == 0)
+ continue;
+
+ INSIST(sa < (struct sockaddr *) ifam_end);
+
+ switch (i) {
+ case RTAX_NETMASK: /* Netmask */
+ mask_sa = sa;
+ break;
+ case RTAX_IFA: /* Interface address */
+ addr_sa = sa;
+ break;
+ case RTAX_BRD: /* Broadcast or destination address */
+ dst_sa = sa;
+ break;
+ }
+#ifdef ISC_PLATFORM_HAVESALEN
+ sa = (struct sockaddr *)((char*)(sa)
+ + ROUNDUP(sa->sa_len));
+#else
+#ifdef sgi
+ /*
+ * Do as the contributed SGI code does.
+ */
+ sa = (struct sockaddr *)((char*)(sa)
+ + ROUNDUP(_FAKE_SA_LEN_DST(sa)));
+#else
+ /* XXX untested. */
+ sa = (struct sockaddr *)((char*)(sa)
+ + ROUNDUP(sizeof(struct sockaddr)));
+#endif
+#endif
+ }
+
+ if (addr_sa == NULL)
+ return (ISC_R_IGNORE);
+
+ family = addr_sa->sa_family;
+ if (family != AF_INET && family != AF_INET6)
+ return (ISC_R_IGNORE);
+
+ iter->current.af = family;
+
+ get_addr(family, &iter->current.address, addr_sa,
+ iter->current.name);
+
+ if (mask_sa != NULL)
+ get_addr(family, &iter->current.netmask, mask_sa,
+ iter->current.name);
+
+ if (dst_sa != NULL &&
+ (iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0)
+ get_addr(family, &iter->current.dstaddress, dst_sa,
+ iter->current.name);
+
+ return (ISC_R_SUCCESS);
+ } else {
+ printf(isc_msgcat_get(isc_msgcat, ISC_MSGSET_IFITERSYSCTL,
+ ISC_MSG_UNEXPECTEDTYPE,
+ "warning: unexpected interface list "
+ "message type\n"));
+ return (ISC_R_IGNORE);
+ }
+}
+
+/*
+ * Step the iterator to the next interface. Unlike
+ * isc_interfaceiter_next(), this may leave the iterator
+ * positioned on an interface that will ultimately
+ * be ignored. Return ISC_R_NOMORE if there are no more
+ * interfaces, otherwise ISC_R_SUCCESS.
+ */
+static isc_result_t
+internal_next(isc_interfaceiter_t *iter) {
+ struct ifa_msghdr *ifam;
+ REQUIRE (iter->pos < (unsigned int) iter->bufused);
+
+ ifam = (struct ifa_msghdr *) ((char *) iter->buf + iter->pos);
+
+ iter->pos += ifam->ifam_msglen;
+
+ if (iter->pos >= iter->bufused)
+ return (ISC_R_NOMORE);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+internal_destroy(isc_interfaceiter_t *iter) {
+ UNUSED(iter); /* Unused. */
+ /*
+ * Do nothing.
+ */
+}
+
+static
+void internal_first(isc_interfaceiter_t *iter) {
+ iter->pos = 0;
+}
diff --git a/lib/isc/unix/include/Makefile.in b/lib/isc/unix/include/Makefile.in
new file mode 100644
index 0000000..0303ab1
--- /dev/null
+++ b/lib/isc/unix/include/Makefile.in
@@ -0,0 +1,25 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.14 2007/06/19 23:47:18 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/unix/include/isc/Makefile.in b/lib/isc/unix/include/isc/Makefile.in
new file mode 100644
index 0000000..2f4d216
--- /dev/null
+++ b/lib/isc/unix/include/isc/Makefile.in
@@ -0,0 +1,38 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.30 2007/06/19 23:47:19 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @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}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/unix/include/isc/dir.h b/lib/isc/unix/include/isc/dir.h
new file mode 100644
index 0000000..e4a2ad0
--- /dev/null
+++ b/lib/isc/unix/include/isc/dir.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: dir.h,v 1.21 2007/06/19 23:47:19 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#ifndef ISC_DIR_H
+#define ISC_DIR_H 1
+
+/*! \file */
+
+#include <sys/types.h> /* Required on some systems. */
+#include <dirent.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+#define ISC_DIR_NAMEMAX 256
+#define ISC_DIR_PATHMAX 1024
+
+/*% Directory Entry */
+typedef struct isc_direntry {
+ /*!
+ * Ideally, this should be NAME_MAX, but AIX does not define it by
+ * default and dynamically allocating the space based on pathconf()
+ * complicates things undesirably, as does adding special conditionals
+ * just for AIX. So a comfortably sized buffer is chosen instead.
+ */
+ char name[ISC_DIR_NAMEMAX];
+ unsigned int length;
+} isc_direntry_t;
+
+/*% Directory */
+typedef struct isc_dir {
+ unsigned int magic;
+ /*!
+ * As with isc_direntry_t->name, making this "right" for all systems
+ * is slightly problematic because AIX does not define PATH_MAX.
+ */
+ char dirname[ISC_DIR_PATHMAX];
+ isc_direntry_t entry;
+ DIR * handle;
+} isc_dir_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_dir_init(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_open(isc_dir_t *dir, const char *dirname);
+
+isc_result_t
+isc_dir_read(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_reset(isc_dir_t *dir);
+
+void
+isc_dir_close(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_chdir(const char *dirname);
+
+isc_result_t
+isc_dir_chroot(const char *dirname);
+
+isc_result_t
+isc_dir_createunique(char *templet);
+/*!<
+ * Use a templet (such as from isc_file_mktemplate()) to create a uniquely
+ * named, empty directory. The templet string is modified in place.
+ * If result == ISC_R_SUCCESS, it is the name of the directory that was
+ * created.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_DIR_H */
diff --git a/lib/isc/unix/include/isc/int.h b/lib/isc/unix/include/isc/int.h
new file mode 100644
index 0000000..73feb3b
--- /dev/null
+++ b/lib/isc/unix/include/isc/int.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: int.h,v 1.16 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_INT_H
+#define ISC_INT_H 1
+
+/*! \file */
+
+typedef char isc_int8_t;
+typedef unsigned char isc_uint8_t;
+typedef short isc_int16_t;
+typedef unsigned short isc_uint16_t;
+typedef int isc_int32_t;
+typedef unsigned int isc_uint32_t;
+typedef long long isc_int64_t;
+typedef unsigned long long isc_uint64_t;
+
+#define ISC_INT8_MIN -128
+#define ISC_INT8_MAX 127
+#define ISC_UINT8_MAX 255
+
+#define ISC_INT16_MIN -32768
+#define ISC_INT16_MAX 32767
+#define ISC_UINT16_MAX 65535
+
+/*%
+ * Note that "int" is 32 bits on all currently supported Unix-like operating
+ * systems, but "long" can be either 32 bits or 64 bits, thus the 32 bit
+ * constants are not qualified with "L".
+ */
+#define ISC_INT32_MIN -2147483648
+#define ISC_INT32_MAX 2147483647
+#define ISC_UINT32_MAX 4294967295U
+
+#define ISC_INT64_MIN -9223372036854775808LL
+#define ISC_INT64_MAX 9223372036854775807LL
+#define ISC_UINT64_MAX 18446744073709551615ULL
+
+#endif /* ISC_INT_H */
diff --git a/lib/isc/unix/include/isc/keyboard.h b/lib/isc/unix/include/isc/keyboard.h
new file mode 100644
index 0000000..43f5e7e
--- /dev/null
+++ b/lib/isc/unix/include/isc/keyboard.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: keyboard.h,v 1.11 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_KEYBOARD_H
+#define ISC_KEYBOARD_H 1
+
+/*! \file */
+
+#include <termios.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef struct {
+ int fd;
+ struct termios saved_mode;
+ isc_result_t result;
+} isc_keyboard_t;
+
+isc_result_t
+isc_keyboard_open(isc_keyboard_t *keyboard);
+
+isc_result_t
+isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleepseconds);
+
+isc_result_t
+isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp);
+
+isc_boolean_t
+isc_keyboard_canceled(isc_keyboard_t *keyboard);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_KEYBOARD_H */
diff --git a/lib/isc/unix/include/isc/net.h b/lib/isc/unix/include/isc/net.h
new file mode 100644
index 0000000..6d3dcaa
--- /dev/null
+++ b/lib/isc/unix/include/isc/net.h
@@ -0,0 +1,365 @@
+/*
+ * 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
+ * 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: net.h,v 1.48 2008/06/23 23:47:11 tbox Exp $ */
+
+#ifndef ISC_NET_H
+#define ISC_NET_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * Basic Networking Types
+ *
+ * This module is responsible for defining the following basic networking
+ * types:
+ *
+ *\li struct in_addr
+ *\li struct in6_addr
+ *\li struct in6_pktinfo
+ *\li struct sockaddr
+ *\li struct sockaddr_in
+ *\li struct sockaddr_in6
+ *\li in_port_t
+ *
+ * It ensures that the AF_ and PF_ macros are defined.
+ *
+ * It declares ntoh[sl]() and hton[sl]().
+ *
+ * It declares inet_aton(), inet_ntop(), and inet_pton().
+ *
+ * It ensures that #INADDR_LOOPBACK, #INADDR_ANY, #IN6ADDR_ANY_INIT,
+ * in6addr_any, and in6addr_loopback are available.
+ *
+ * It ensures that IN_MULTICAST() is available to check for multicast
+ * addresses.
+ *
+ * MP:
+ *\li No impact.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li N/A.
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li BSD Socket API
+ *\li RFC2553
+ */
+
+/***
+ *** Imports.
+ ***/
+#include <isc/platform.h>
+
+#include <sys/types.h>
+#include <sys/socket.h> /* Contractual promise. */
+
+#include <net/if.h>
+
+#include <netinet/in.h> /* Contractual promise. */
+#include <arpa/inet.h> /* Contractual promise. */
+#ifdef ISC_PLATFORM_NEEDNETINETIN6H
+#include <netinet/in6.h> /* Required on UnixWare. */
+#endif
+#ifdef ISC_PLATFORM_NEEDNETINET6IN6H
+#include <netinet6/in6.h> /* Required on BSD/OS for in6_pktinfo. */
+#endif
+
+#ifndef ISC_PLATFORM_HAVEIPV6
+#include <isc/ipv6.h> /* Contractual promise. */
+#endif
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_HAVEINADDR6
+#define in6_addr in_addr6 /*%< Required for pre RFC2133 implementations. */
+#endif
+
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifndef IN6ADDR_ANY_INIT
+#ifdef s6_addr
+/*%
+ * Required for some pre RFC2133 implementations.
+ * IN6ADDR_ANY_INIT and IN6ADDR_LOOPBACK_INIT were added in
+ * draft-ietf-ipngwg-bsd-api-04.txt or draft-ietf-ipngwg-bsd-api-05.txt.
+ * If 's6_addr' is defined then assume that there is a union and three
+ * levels otherwise assume two levels required.
+ */
+#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
+#else
+#define IN6ADDR_ANY_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }
+#endif
+#endif
+
+#ifndef IN6ADDR_LOOPBACK_INIT
+#ifdef s6_addr
+/*% IPv6 address loopback init */
+#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
+#else
+#define IN6ADDR_LOOPBACK_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } }
+#endif
+#endif
+
+#ifndef IN6_IS_ADDR_V4MAPPED
+/*% Is IPv6 address V4 mapped? */
+#define IN6_IS_ADDR_V4MAPPED(x) \
+ (memcmp((x)->s6_addr, in6addr_any.s6_addr, 10) == 0 && \
+ (x)->s6_addr[10] == 0xff && (x)->s6_addr[11] == 0xff)
+#endif
+
+#ifndef IN6_IS_ADDR_V4COMPAT
+/*% Is IPv6 address V4 compatible? */
+#define IN6_IS_ADDR_V4COMPAT(x) \
+ (memcmp((x)->s6_addr, in6addr_any.s6_addr, 12) == 0 && \
+ ((x)->s6_addr[12] != 0 || (x)->s6_addr[13] != 0 || \
+ (x)->s6_addr[14] != 0 || \
+ ((x)->s6_addr[15] != 0 && (x)->s6_addr[15] != 1)))
+#endif
+
+#ifndef IN6_IS_ADDR_MULTICAST
+/*% Is IPv6 address multicast? */
+#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff)
+#endif
+
+#ifndef IN6_IS_ADDR_LINKLOCAL
+/*% Is IPv6 address linklocal? */
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+ (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
+#endif
+
+#ifndef IN6_IS_ADDR_SITELOCAL
+/*% is IPv6 address sitelocal? */
+#define IN6_IS_ADDR_SITELOCAL(a) \
+ (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
+#endif
+
+
+#ifndef IN6_IS_ADDR_LOOPBACK
+/*% is IPv6 address loopback? */
+#define IN6_IS_ADDR_LOOPBACK(x) \
+ (memcmp((x)->s6_addr, in6addr_loopback.s6_addr, 16) == 0)
+#endif
+#endif
+
+#ifndef AF_INET6
+/*% IPv6 */
+#define AF_INET6 99
+#endif
+
+#ifndef PF_INET6
+/*% IPv6 */
+#define PF_INET6 AF_INET6
+#endif
+
+#ifndef INADDR_LOOPBACK
+/*% inaddr loopback */
+#define INADDR_LOOPBACK 0x7f000001UL
+#endif
+
+#ifndef ISC_PLATFORM_HAVEIN6PKTINFO
+/*% IPv6 packet info */
+struct in6_pktinfo {
+ struct in6_addr ipi6_addr; /*%< src/dst IPv6 address */
+ unsigned int ipi6_ifindex; /*%< send/recv interface index */
+};
+#endif
+
+#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRANY)
+extern const struct in6_addr isc_net_in6addrany;
+/*%
+ * Cope with a missing in6addr_any and in6addr_loopback.
+ */
+#define in6addr_any isc_net_in6addrany
+#endif
+
+#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK)
+extern const struct in6_addr isc_net_in6addrloop;
+#define in6addr_loopback isc_net_in6addrloop
+#endif
+
+#ifdef ISC_PLATFORM_FIXIN6ISADDR
+#undef IN6_IS_ADDR_GEOGRAPHIC
+/*!
+ * \brief
+ * Fix UnixWare 7.1.1's broken IN6_IS_ADDR_* definitions.
+ */
+#define IN6_IS_ADDR_GEOGRAPHIC(a) (((a)->S6_un.S6_l[0] & 0xE0) == 0x80)
+#undef IN6_IS_ADDR_IPX
+#define IN6_IS_ADDR_IPX(a) (((a)->S6_un.S6_l[0] & 0xFE) == 0x04)
+#undef IN6_IS_ADDR_LINKLOCAL
+#define IN6_IS_ADDR_LINKLOCAL(a) (((a)->S6_un.S6_l[0] & 0xC0FF) == 0x80FE)
+#undef IN6_IS_ADDR_MULTICAST
+#define IN6_IS_ADDR_MULTICAST(a) (((a)->S6_un.S6_l[0] & 0xFF) == 0xFF)
+#undef IN6_IS_ADDR_NSAP
+#define IN6_IS_ADDR_NSAP(a) (((a)->S6_un.S6_l[0] & 0xFE) == 0x02)
+#undef IN6_IS_ADDR_PROVIDER
+#define IN6_IS_ADDR_PROVIDER(a) (((a)->S6_un.S6_l[0] & 0xE0) == 0x40)
+#undef IN6_IS_ADDR_SITELOCAL
+#define IN6_IS_ADDR_SITELOCAL(a) (((a)->S6_un.S6_l[0] & 0xC0FF) == 0xC0FE)
+#endif /* ISC_PLATFORM_FIXIN6ISADDR */
+
+#ifdef ISC_PLATFORM_NEEDPORTT
+/*%
+ * Ensure type in_port_t is defined.
+ */
+typedef isc_uint16_t in_port_t;
+#endif
+
+#ifndef MSG_TRUNC
+/*%
+ * If this system does not have MSG_TRUNC (as returned from recvmsg())
+ * ISC_PLATFORM_RECVOVERFLOW will be defined. This will enable the MSG_TRUNC
+ * faking code in socket.c.
+ */
+#define ISC_PLATFORM_RECVOVERFLOW
+#endif
+
+/*% IP address. */
+#define ISC__IPADDR(x) ((isc_uint32_t)htonl((isc_uint32_t)(x)))
+
+/*% Is IP address multicast? */
+#define ISC_IPADDR_ISMULTICAST(i) \
+ (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+ == ISC__IPADDR(0xe0000000))
+
+#define ISC_IPADDR_ISEXPERIMENTAL(i) \
+ (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+ == ISC__IPADDR(0xf0000000))
+
+/***
+ *** Functions.
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_net_probeipv4(void);
+/*%<
+ * Check if the system's kernel supports IPv4.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS IPv4 is supported.
+ *\li #ISC_R_NOTFOUND IPv4 is not supported.
+ *\li #ISC_R_DISABLED IPv4 is disabled.
+ *\li #ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probeipv6(void);
+/*%<
+ * Check if the system's kernel supports IPv6.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS IPv6 is supported.
+ *\li #ISC_R_NOTFOUND IPv6 is not supported.
+ *\li #ISC_R_DISABLED IPv6 is disabled.
+ *\li #ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probe_ipv6only(void);
+/*%<
+ * Check if the system's kernel supports the IPV6_V6ONLY socket option.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS the option is supported for both TCP and UDP.
+ *\li #ISC_R_NOTFOUND IPv6 itself or the option is not supported.
+ *\li #ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probe_ipv6pktinfo(void);
+/*
+ * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option
+ * for UDP sockets.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS the option is supported.
+ * \li #ISC_R_NOTFOUND IPv6 itself or the option is not supported.
+ * \li #ISC_R_UNEXPECTED
+ */
+
+void
+isc_net_disableipv4(void);
+
+void
+isc_net_disableipv6(void);
+
+void
+isc_net_enableipv4(void);
+
+void
+isc_net_enableipv6(void);
+
+isc_result_t
+isc_net_probeunix(void);
+/*
+ * Returns whether UNIX domain sockets are supported.
+ */
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high);
+/*%<
+ * Returns system's default range of ephemeral UDP ports, if defined.
+ * If the range is not available or unknown, ISC_NET_PORTRANGELOW and
+ * ISC_NET_PORTRANGEHIGH will be returned.
+ *
+ * Requires:
+ *
+ *\li 'low' and 'high' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li *low and *high will be the ports specifying the low and high ends of
+ * the range.
+ */
+
+#ifdef ISC_PLATFORM_NEEDNTOP
+const char *
+isc_net_ntop(int af, const void *src, char *dst, size_t size);
+#define inet_ntop isc_net_ntop
+#endif
+
+#ifdef ISC_PLATFORM_NEEDPTON
+int
+isc_net_pton(int af, const char *src, void *dst);
+#undef inet_pton
+#define inet_pton isc_net_pton
+#endif
+
+#ifdef ISC_PLATFORM_NEEDATON
+int
+isc_net_aton(const char *cp, struct in_addr *addr);
+#define inet_aton isc_net_aton
+#endif
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NET_H */
diff --git a/lib/isc/unix/include/isc/netdb.h b/lib/isc/unix/include/isc/netdb.h
new file mode 100644
index 0000000..ff12a26
--- /dev/null
+++ b/lib/isc/unix/include/isc/netdb.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: netdb.h,v 1.11 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_NETDB_H
+#define ISC_NETDB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file
+ * \brief
+ * Portable netdb.h support.
+ *
+ * This module is responsible for defining the get<x>by<y> APIs.
+ *
+ * MP:
+ *\li No impact.
+ *
+ * Reliability:
+ *\li No anticipated impact.
+ *
+ * Resources:
+ *\li N/A.
+ *
+ * Security:
+ *\li No anticipated impact.
+ *
+ * Standards:
+ *\li BSD API
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/net.h>
+
+#include <netdb.h>
+
+#endif /* ISC_NETDB_H */
diff --git a/lib/isc/unix/include/isc/offset.h b/lib/isc/unix/include/isc/offset.h
new file mode 100644
index 0000000..76e05f4
--- /dev/null
+++ b/lib/isc/unix/include/isc/offset.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: offset.h,v 1.15 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_OFFSET_H
+#define ISC_OFFSET_H 1
+
+/*! \file
+ * \brief
+ * File offsets are operating-system dependent.
+ */
+#include <limits.h> /* Required for CHAR_BIT. */
+#include <sys/types.h>
+
+typedef off_t isc_offset_t;
+
+/*%
+ * POSIX says "Additionally, blkcnt_t and off_t are extended signed integral
+ * types", so the maximum value is all 1s except for the high bit.
+ * This definition is more complex than it really needs to be because it was
+ * crafted to keep both the SunOS 5.6 and the HP/UX 11 compilers quiet about
+ * integer overflow. For example, though this is equivalent to just left
+ * shifting 1 to the high bit and then inverting the bits, the SunOS compiler
+ * is unhappy about shifting a positive "1" to negative in a signed integer.
+ */
+#define ISC_OFFSET_MAXIMUM \
+ (~(((off_t)-1 >> (sizeof(off_t) * CHAR_BIT - 1)) \
+ << (sizeof(off_t) * CHAR_BIT - 1)))
+
+#endif /* ISC_OFFSET_H */
diff --git a/lib/isc/unix/include/isc/stat.h b/lib/isc/unix/include/isc/stat.h
new file mode 100644
index 0000000..b7a7986
--- /dev/null
+++ b/lib/isc/unix/include/isc/stat.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004, 2007 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: stat.h,v 1.5 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_STAT_H
+#define ISC_STAT_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Portable netdb.h support.
+ *
+ * This module is responsible for defining S_IS??? macros.
+ *
+ * MP:
+ * No impact.
+ *
+ * Reliability:
+ * No anticipated impact.
+ *
+ * Resources:
+ * N/A.
+ *
+ * Security:
+ * No anticipated impact.
+ *
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#endif /* ISC_STAT_H */
diff --git a/lib/isc/unix/include/isc/stdtime.h b/lib/isc/unix/include/isc/stdtime.h
new file mode 100644
index 0000000..4cb9e81
--- /dev/null
+++ b/lib/isc/unix/include/isc/stdtime.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: stdtime.h,v 1.14 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_STDTIME_H
+#define ISC_STDTIME_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/int.h>
+
+/*%
+ * It's public information that 'isc_stdtime_t' is an unsigned integral type.
+ * Applications that want maximum portability should not assume anything
+ * about its size.
+ */
+typedef isc_uint32_t isc_stdtime_t;
+/*
+ * isc_stdtime32_t is a 32-bit version of isc_stdtime_t. A variable of this
+ * type should only be used as an opaque integer (e.g.,) to compare two
+ * time values.
+ */
+typedef isc_uint32_t isc_stdtime32_t;
+
+ISC_LANG_BEGINDECLS
+/* */
+void
+isc_stdtime_get(isc_stdtime_t *t);
+/*%<
+ * Set 't' to the number of seconds since 00:00:00 UTC, January 1, 1970.
+ *
+ * Requires:
+ *
+ *\li 't' is a valid pointer.
+ */
+
+#define isc_stdtime_convert32(t, t32p) (*(t32p) = t)
+/*
+ * Convert the standard time to its 32-bit version.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STDTIME_H */
diff --git a/lib/isc/unix/include/isc/strerror.h b/lib/isc/unix/include/isc/strerror.h
new file mode 100644
index 0000000..12b1abc
--- /dev/null
+++ b/lib/isc/unix/include/isc/strerror.h
@@ -0,0 +1,45 @@
+/*
+ * 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: strerror.h,v 1.8 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_STRERROR_H
+#define ISC_STRERROR_H
+
+/*! \file */
+
+#include <sys/types.h>
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/*% String Error Size */
+#define ISC_STRERRORSIZE 128
+
+/*%
+ * Provide a thread safe wrapper to strerrror().
+ *
+ * Requires:
+ * 'buf' to be non NULL.
+ */
+void
+isc__strerror(int num, char *buf, size_t bufsize);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STRERROR_H */
diff --git a/lib/isc/unix/include/isc/syslog.h b/lib/isc/unix/include/isc/syslog.h
new file mode 100644
index 0000000..7e0c88c
--- /dev/null
+++ b/lib/isc/unix/include/isc/syslog.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: syslog.h,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef ISC_SYSLOG_H
+#define ISC_SYSLOG_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_syslog_facilityfromstring(const char *str, int *facilityp);
+/*%<
+ * Convert 'str' to the appropriate syslog facility constant.
+ *
+ * Requires:
+ *
+ *\li 'str' is not NULL
+ *\li 'facilityp' is not NULL
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOTFOUND
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SYSLOG_H */
diff --git a/lib/isc/unix/include/isc/time.h b/lib/isc/unix/include/isc/time.h
new file mode 100644
index 0000000..c65ce9d
--- /dev/null
+++ b/lib/isc/unix/include/isc/time.h
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: time.h,v 1.38 2008/09/08 23:47:10 tbox Exp $ */
+
+#ifndef ISC_TIME_H
+#define ISC_TIME_H 1
+
+/*! \file */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/***
+ *** Intervals
+ ***/
+
+/*!
+ * \brief
+ * The contents of this structure are private, and MUST NOT be accessed
+ * directly by callers.
+ *
+ * The contents are exposed only to allow callers to avoid dynamic allocation.
+ */
+struct isc_interval {
+ unsigned int seconds;
+ unsigned int nanoseconds;
+};
+
+extern isc_interval_t *isc_interval_zero;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_interval_set(isc_interval_t *i,
+ unsigned int seconds, unsigned int nanoseconds);
+/*%<
+ * Set 'i' to a value representing an interval of 'seconds' seconds and
+ * 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and
+ * isc_time_subtract().
+ *
+ * Requires:
+ *
+ *\li 't' is a valid pointer.
+ *\li nanoseconds < 1000000000.
+ */
+
+isc_boolean_t
+isc_interval_iszero(const isc_interval_t *i);
+/*%<
+ * Returns ISC_TRUE iff. 'i' is the zero interval.
+ *
+ * Requires:
+ *
+ *\li 'i' is a valid pointer.
+ */
+
+/***
+ *** Absolute Times
+ ***/
+
+/*%
+ * The contents of this structure are private, and MUST NOT be accessed
+ * directly by callers.
+ *
+ * The contents are exposed only to allow callers to avoid dynamic allocation.
+ */
+
+struct isc_time {
+ unsigned int seconds;
+ unsigned int nanoseconds;
+};
+
+extern isc_time_t *isc_time_epoch;
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds);
+/*%<
+ * Set 't' to a value which represents the given number of seconds and
+ * nanoseconds since 00:00:00 January 1, 1970, UTC.
+ *
+ * Notes:
+ *\li The Unix version of this call is equivalent to:
+ *\code
+ * isc_time_settoepoch(t);
+ * isc_interval_set(i, seconds, nanoseconds);
+ * isc_time_add(t, i, t);
+ *\endcode
+ *
+ * Requires:
+ *\li 't' is a valid pointer.
+ *\li nanoseconds < 1000000000.
+ */
+
+void
+isc_time_settoepoch(isc_time_t *t);
+/*%<
+ * Set 't' to the time of the epoch.
+ *
+ * Notes:
+ *\li The date of the epoch is platform-dependent.
+ *
+ * Requires:
+ *
+ *\li 't' is a valid pointer.
+ */
+
+isc_boolean_t
+isc_time_isepoch(const isc_time_t *t);
+/*%<
+ * Returns ISC_TRUE iff. 't' is the epoch ("time zero").
+ *
+ * Requires:
+ *
+ *\li 't' is a valid pointer.
+ */
+
+isc_result_t
+isc_time_now(isc_time_t *t);
+/*%<
+ * Set 't' to the current absolute time.
+ *
+ * Requires:
+ *
+ *\li 't' is a valid pointer.
+ *
+ * Returns:
+ *
+ *\li Success
+ *\li Unexpected error
+ * Getting the time from the system failed.
+ *\li Out of range
+ * The time from the system is too large to be represented
+ * in the current definition of isc_time_t.
+ */
+
+isc_result_t
+isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i);
+/*%<
+ * Set *t to the current absolute time + i.
+ *
+ * Note:
+ *\li This call is equivalent to:
+ *
+ *\code
+ * isc_time_now(t);
+ * isc_time_add(t, i, t);
+ *\endcode
+ *
+ * Requires:
+ *
+ *\li 't' and 'i' are valid pointers.
+ *
+ * Returns:
+ *
+ *\li Success
+ *\li Unexpected error
+ * Getting the time from the system failed.
+ *\li Out of range
+ * The interval added to the time from the system is too large to
+ * be represented in the current definition of isc_time_t.
+ */
+
+int
+isc_time_compare(const isc_time_t *t1, const isc_time_t *t2);
+/*%<
+ * Compare the times referenced by 't1' and 't2'
+ *
+ * Requires:
+ *
+ *\li 't1' and 't2' are valid pointers.
+ *
+ * Returns:
+ *
+ *\li -1 t1 < t2 (comparing times, not pointers)
+ *\li 0 t1 = t2
+ *\li 1 t1 > t2
+ */
+
+isc_result_t
+isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result);
+/*%<
+ * Add 'i' to 't', storing the result in 'result'.
+ *
+ * Requires:
+ *
+ *\li 't', 'i', and 'result' are valid pointers.
+ *
+ * Returns:
+ *\li Success
+ *\li Out of range
+ * The interval added to the time is too large to
+ * be represented in the current definition of isc_time_t.
+ */
+
+isc_result_t
+isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
+ isc_time_t *result);
+/*%<
+ * Subtract 'i' from 't', storing the result in 'result'.
+ *
+ * Requires:
+ *
+ *\li 't', 'i', and 'result' are valid pointers.
+ *
+ * Returns:
+ *\li Success
+ *\li Out of range
+ * The interval is larger than the time since the epoch.
+ */
+
+isc_uint64_t
+isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2);
+/*%<
+ * Find the difference in microseconds between time t1 and time t2.
+ * t2 is the subtrahend of t1; ie, difference = t1 - t2.
+ *
+ * Requires:
+ *
+ *\li 't1' and 't2' are valid pointers.
+ *
+ * Returns:
+ *\li The difference of t1 - t2, or 0 if t1 <= t2.
+ */
+
+isc_uint32_t
+isc_time_seconds(const isc_time_t *t);
+/*%<
+ * Return the number of seconds since the epoch stored in a time structure.
+ *
+ * Requires:
+ *
+ *\li 't' is a valid pointer.
+ */
+
+isc_result_t
+isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp);
+/*%<
+ * Ensure the number of seconds in an isc_time_t is representable by a time_t.
+ *
+ * Notes:
+ *\li The number of seconds stored in an isc_time_t might be larger
+ * than the number of seconds a time_t is able to handle. Since
+ * time_t is mostly opaque according to the ANSI/ISO standard
+ * (essentially, all you can be sure of is that it is an arithmetic type,
+ * not even necessarily integral), it can be tricky to ensure that
+ * the isc_time_t is in the range a time_t can handle. Use this
+ * function in place of isc_time_seconds() any time you need to set a
+ * time_t from an isc_time_t.
+ *
+ * Requires:
+ *\li 't' is a valid pointer.
+ *
+ * Returns:
+ *\li Success
+ *\li Out of range
+ */
+
+isc_uint32_t
+isc_time_nanoseconds(const isc_time_t *t);
+/*%<
+ * Return the number of nanoseconds stored in a time structure.
+ *
+ * Notes:
+ *\li This is the number of nanoseconds in excess of the the number
+ * of seconds since the epoch; it will always be less than one
+ * full second.
+ *
+ * Requires:
+ *\li 't' is a valid pointer.
+ *
+ * Ensures:
+ *\li The returned value is less than 1*10^9.
+ */
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len);
+/*%<
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using a format like "30-Aug-2000 04:06:47.997" and the local time zone.
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ * Requires:
+ *\li 'len' > 0
+ *\li 'buf' points to an array of at least len chars
+ *
+ */
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len);
+/*%<
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using a format like "Mon, 30 Aug 2000 04:06:47 GMT"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ * Requires:
+ *\li 'len' > 0
+ *\li 'buf' points to an array of at least len chars
+ *
+ */
+
+void
+isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
+/*%<
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using the ISO8601 format: "yyyy-mm-ddThh:mm:ssZ"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ * Requires:
+ *\li 'len' > 0
+ *\li 'buf' points to an array of at least len chars
+ *
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TIME_H */
diff --git a/lib/isc/unix/interfaceiter.c b/lib/isc/unix/interfaceiter.c
new file mode 100644
index 0000000..ce1419f
--- /dev/null
+++ b/lib/isc/unix/interfaceiter.c
@@ -0,0 +1,312 @@
+/*
+ * 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
+ * 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: interfaceiter.c,v 1.44 2008/03/20 23:47:00 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h> /* Required for ifiter_ioctl.c. */
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <isc/interfaceiter.h>
+#include <isc/log.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/net.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+/* Must follow <isc/net.h>. */
+#ifdef HAVE_NET_IF6_H
+#include <net/if6.h>
+#endif
+#include <net/if.h>
+
+/* Common utility functions */
+
+/*%
+ * Extract the network address part from a "struct sockaddr".
+ * \brief
+ * The address family is given explicitly
+ * instead of using src->sa_family, because the latter does not work
+ * for copying a network mask obtained by SIOCGIFNETMASK (it does
+ * not have a valid address family).
+ */
+
+static void
+get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src,
+ char *ifname)
+{
+ struct sockaddr_in6 *sa6;
+
+#if !defined(ISC_PLATFORM_HAVEIFNAMETOINDEX) || \
+ !defined(ISC_PLATFORM_HAVESCOPEID)
+ UNUSED(ifname);
+#endif
+
+ /* clear any remaining value for safety */
+ memset(dst, 0, sizeof(*dst));
+
+ dst->family = family;
+ switch (family) {
+ case AF_INET:
+ memcpy(&dst->type.in,
+ &((struct sockaddr_in *) src)->sin_addr,
+ sizeof(struct in_addr));
+ break;
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *)src;
+ memcpy(&dst->type.in6, &sa6->sin6_addr,
+ sizeof(struct in6_addr));
+#ifdef ISC_PLATFORM_HAVESCOPEID
+ if (sa6->sin6_scope_id != 0)
+ isc_netaddr_setzone(dst, sa6->sin6_scope_id);
+ else {
+ /*
+ * BSD variants embed scope zone IDs in the 128bit
+ * address as a kernel internal form. Unfortunately,
+ * the embedded IDs are not hidden from applications
+ * when getting access to them by sysctl or ioctl.
+ * We convert the internal format to the pure address
+ * part and the zone ID part.
+ * Since multicast addresses should not appear here
+ * and they cannot be distinguished from netmasks,
+ * we only consider unicast link-local addresses.
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) {
+ isc_uint16_t zone16;
+
+ memcpy(&zone16, &sa6->sin6_addr.s6_addr[2],
+ sizeof(zone16));
+ zone16 = ntohs(zone16);
+ if (zone16 != 0) {
+ /* the zone ID is embedded */
+ isc_netaddr_setzone(dst,
+ (isc_uint32_t)zone16);
+ dst->type.in6.s6_addr[2] = 0;
+ dst->type.in6.s6_addr[3] = 0;
+#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
+ } else if (ifname != NULL) {
+ unsigned int zone;
+
+ /*
+ * sin6_scope_id is still not provided,
+ * but the corresponding interface name
+ * is know. Use the interface ID as
+ * the link ID.
+ */
+ zone = if_nametoindex(ifname);
+ if (zone != 0) {
+ isc_netaddr_setzone(dst,
+ (isc_uint32_t)zone);
+ }
+#endif
+ }
+ }
+ }
+#endif
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+}
+
+/*
+ * Include system-dependent code.
+ */
+
+#ifdef __linux
+#define ISC_IF_INET6_SZ \
+ sizeof("00000000000000000000000000000001 01 80 10 80 XXXXXXloXXXXXXXX\n")
+static isc_result_t linux_if_inet6_next(isc_interfaceiter_t *);
+static isc_result_t linux_if_inet6_current(isc_interfaceiter_t *);
+static void linux_if_inet6_first(isc_interfaceiter_t *iter);
+#endif
+
+#if HAVE_GETIFADDRS
+#include "ifiter_getifaddrs.c"
+#elif HAVE_IFLIST_SYSCTL
+#include "ifiter_sysctl.c"
+#else
+#include "ifiter_ioctl.c"
+#endif
+
+#ifdef __linux
+static void
+linux_if_inet6_first(isc_interfaceiter_t *iter) {
+ if (iter->proc != NULL) {
+ rewind(iter->proc);
+ (void)linux_if_inet6_next(iter);
+ } else
+ iter->valid = ISC_R_NOMORE;
+}
+
+static isc_result_t
+linux_if_inet6_next(isc_interfaceiter_t *iter) {
+ if (iter->proc != NULL &&
+ fgets(iter->entry, sizeof(iter->entry), iter->proc) != NULL)
+ iter->valid = ISC_R_SUCCESS;
+ else
+ iter->valid = ISC_R_NOMORE;
+ return (iter->valid);
+}
+
+static isc_result_t
+linux_if_inet6_current(isc_interfaceiter_t *iter) {
+ char address[33];
+ char name[IF_NAMESIZE+1];
+ struct in6_addr addr6;
+ int ifindex, prefix, flag3, flag4;
+ int res;
+ unsigned int i;
+
+ if (iter->valid != ISC_R_SUCCESS)
+ return (iter->valid);
+ if (iter->proc == NULL) {
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
+ "/proc/net/if_inet6:iter->proc == NULL");
+ return (ISC_R_FAILURE);
+ }
+
+ res = sscanf(iter->entry, "%32[a-f0-9] %x %x %x %x %16s\n",
+ address, &ifindex, &prefix, &flag3, &flag4, name);
+ if (res != 6) {
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
+ "/proc/net/if_inet6:sscanf() -> %d (expected 6)",
+ res);
+ return (ISC_R_FAILURE);
+ }
+ if (strlen(address) != 32) {
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_INTERFACE, ISC_LOG_ERROR,
+ "/proc/net/if_inet6:strlen(%s) != 32", address);
+ return (ISC_R_FAILURE);
+ }
+ for (i = 0; i < 16; i++) {
+ unsigned char byte;
+ static const char hex[] = "0123456789abcdef";
+ byte = ((index(hex, address[i * 2]) - hex) << 4) |
+ (index(hex, address[i * 2 + 1]) - hex);
+ addr6.s6_addr[i] = byte;
+ }
+ iter->current.af = AF_INET6;
+ iter->current.flags = INTERFACE_F_UP;
+ isc_netaddr_fromin6(&iter->current.address, &addr6);
+ if (isc_netaddr_islinklocal(&iter->current.address)) {
+ isc_netaddr_setzone(&iter->current.address,
+ (isc_uint32_t)ifindex);
+ }
+ for (i = 0; i < 16; i++) {
+ if (prefix > 8) {
+ addr6.s6_addr[i] = 0xff;
+ prefix -= 8;
+ } else {
+ addr6.s6_addr[i] = (0xff << (8 - prefix)) & 0xff;
+ prefix = 0;
+ }
+ }
+ isc_netaddr_fromin6(&iter->current.netmask, &addr6);
+ strncpy(iter->current.name, name, sizeof(iter->current.name));
+ return (ISC_R_SUCCESS);
+}
+#endif
+
+/*
+ * The remaining code is common to the sysctl and ioctl case.
+ */
+
+isc_result_t
+isc_interfaceiter_current(isc_interfaceiter_t *iter,
+ isc_interface_t *ifdata)
+{
+ REQUIRE(iter->result == ISC_R_SUCCESS);
+ memcpy(ifdata, &iter->current, sizeof(*ifdata));
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_interfaceiter_first(isc_interfaceiter_t *iter) {
+ isc_result_t result;
+
+ REQUIRE(VALID_IFITER(iter));
+
+ internal_first(iter);
+ for (;;) {
+ result = internal_current(iter);
+ if (result != ISC_R_IGNORE)
+ break;
+ result = internal_next(iter);
+ if (result != ISC_R_SUCCESS)
+ break;
+ }
+ iter->result = result;
+ return (result);
+}
+
+isc_result_t
+isc_interfaceiter_next(isc_interfaceiter_t *iter) {
+ isc_result_t result;
+
+ REQUIRE(VALID_IFITER(iter));
+ REQUIRE(iter->result == ISC_R_SUCCESS);
+
+ for (;;) {
+ result = internal_next(iter);
+ if (result != ISC_R_SUCCESS)
+ break;
+ result = internal_current(iter);
+ if (result != ISC_R_IGNORE)
+ break;
+ }
+ iter->result = result;
+ return (result);
+}
+
+void
+isc_interfaceiter_destroy(isc_interfaceiter_t **iterp)
+{
+ isc_interfaceiter_t *iter;
+ REQUIRE(iterp != NULL);
+ iter = *iterp;
+ REQUIRE(VALID_IFITER(iter));
+
+ internal_destroy(iter);
+ if (iter->buf != NULL)
+ isc_mem_put(iter->mctx, iter->buf, iter->bufsize);
+
+ iter->magic = 0;
+ isc_mem_put(iter->mctx, iter, sizeof(*iter));
+ *iterp = NULL;
+}
diff --git a/lib/isc/unix/ipv6.c b/lib/isc/unix/ipv6.c
new file mode 100644
index 0000000..61e984f
--- /dev/null
+++ b/lib/isc/unix/ipv6.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: ipv6.c,v 1.14 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/ipv6.h>
+
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
diff --git a/lib/isc/unix/keyboard.c b/lib/isc/unix/keyboard.c
new file mode 100644
index 0000000..8ee62d3
--- /dev/null
+++ b/lib/isc/unix/keyboard.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2004, 2007 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: keyboard.c,v 1.13 2007/06/19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <isc/keyboard.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_keyboard_open(isc_keyboard_t *keyboard) {
+ int fd;
+ isc_result_t ret;
+ struct termios current_mode;
+
+ REQUIRE(keyboard != NULL);
+
+ fd = open("/dev/tty", O_RDONLY, 0);
+ if (fd < 0)
+ return (ISC_R_IOERROR);
+
+ keyboard->fd = fd;
+
+ if (tcgetattr(fd, &keyboard->saved_mode) < 0) {
+ ret = ISC_R_IOERROR;
+ goto errout;
+ }
+
+ current_mode = keyboard->saved_mode;
+
+ current_mode.c_iflag &=
+ ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ current_mode.c_oflag &= ~OPOST;
+ current_mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ current_mode.c_cflag &= ~(CSIZE|PARENB);
+ current_mode.c_cflag |= CS8;
+
+ current_mode.c_cc[VMIN] = 1;
+ current_mode.c_cc[VTIME] = 0;
+ if (tcsetattr(fd, TCSAFLUSH, &current_mode) < 0) {
+ ret = ISC_R_IOERROR;
+ goto errout;
+ }
+
+ keyboard->result = ISC_R_SUCCESS;
+
+ return (ISC_R_SUCCESS);
+
+ errout:
+ close (fd);
+
+ return (ret);
+}
+
+isc_result_t
+isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleeptime) {
+ REQUIRE(keyboard != NULL);
+
+ if (sleeptime > 0 && keyboard->result != ISC_R_CANCELED)
+ (void)sleep(sleeptime);
+
+ (void)tcsetattr(keyboard->fd, TCSAFLUSH, &keyboard->saved_mode);
+ (void)close(keyboard->fd);
+
+ keyboard->fd = -1;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp) {
+ ssize_t cc;
+ unsigned char c;
+ cc_t *controlchars;
+
+ REQUIRE(keyboard != NULL);
+ REQUIRE(cp != NULL);
+
+ cc = read(keyboard->fd, &c, 1);
+ if (cc < 0) {
+ keyboard->result = ISC_R_IOERROR;
+ return (keyboard->result);
+ }
+
+ controlchars = keyboard->saved_mode.c_cc;
+ if (c == controlchars[VINTR] || c == controlchars[VQUIT]) {
+ keyboard->result = ISC_R_CANCELED;
+ return (keyboard->result);
+ }
+
+ *cp = c;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+isc_keyboard_canceled(isc_keyboard_t *keyboard) {
+ return (ISC_TF(keyboard->result == ISC_R_CANCELED));
+}
diff --git a/lib/isc/unix/net.c b/lib/isc/unix/net.c
new file mode 100644
index 0000000..b2fb30e
--- /dev/null
+++ b/lib/isc/unix/net.c
@@ -0,0 +1,524 @@
+/*
+ * 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
+ * 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: net.c,v 1.40 2008/07/04 05:52:31 each Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#if defined(HAVE_SYS_SYSCTL_H)
+#if defined(HAVE_SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+#include <sys/sysctl.h>
+#endif
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <isc/log.h>
+#include <isc/msgs.h>
+#include <isc/net.h>
+#include <isc/once.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/*%
+ * Definitions about UDP port range specification. This is a total mess of
+ * portability variants: some use sysctl (but the sysctl names vary), some use
+ * system-specific interfaces, some have the same interface for IPv4 and IPv6,
+ * some separate them, etc...
+ */
+
+/*%
+ * The last resort defaults: use all non well known port space
+ */
+#ifndef ISC_NET_PORTRANGELOW
+#define ISC_NET_PORTRANGELOW 1024
+#endif /* ISC_NET_PORTRANGELOW */
+#ifndef ISC_NET_PORTRANGEHIGH
+#define ISC_NET_PORTRANGEHIGH 65535
+#endif /* ISC_NET_PORTRANGEHIGH */
+
+#ifdef HAVE_SYSCTLBYNAME
+
+/*%
+ * sysctl variants
+ */
+#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
+#define USE_SYSCTL_PORTRANGE
+#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.portrange.hifirst"
+#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.portrange.hilast"
+#define SYSCTL_V6PORTRANGE_LOW "net.inet.ip.portrange.hifirst"
+#define SYSCTL_V6PORTRANGE_HIGH "net.inet.ip.portrange.hilast"
+#endif
+
+#ifdef __NetBSD__
+#define USE_SYSCTL_PORTRANGE
+#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.anonportmin"
+#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.anonportmax"
+#define SYSCTL_V6PORTRANGE_LOW "net.inet6.ip6.anonportmin"
+#define SYSCTL_V6PORTRANGE_HIGH "net.inet6.ip6.anonportmax"
+#endif
+
+#else /* !HAVE_SYSCTLBYNAME */
+
+#ifdef __OpenBSD__
+#define USE_SYSCTL_PORTRANGE
+#define SYSCTL_V4PORTRANGE_LOW { CTL_NET, PF_INET, IPPROTO_IP, \
+ IPCTL_IPPORT_HIFIRSTAUTO }
+#define SYSCTL_V4PORTRANGE_HIGH { CTL_NET, PF_INET, IPPROTO_IP, \
+ IPCTL_IPPORT_HILASTAUTO }
+/* Same for IPv6 */
+#define SYSCTL_V6PORTRANGE_LOW SYSCTL_V4PORTRANGE_LOW
+#define SYSCTL_V6PORTRANGE_HIGH SYSCTL_V4PORTRANGE_HIGH
+#endif
+
+#endif /* HAVE_SYSCTLBYNAME */
+
+#if defined(ISC_PLATFORM_HAVEIPV6)
+# if defined(ISC_PLATFORM_NEEDIN6ADDRANY)
+const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
+# endif
+
+# if defined(ISC_PLATFORM_NEEDIN6ADDRLOOPBACK)
+const struct in6_addr isc_net_in6addrloop = IN6ADDR_LOOPBACK_INIT;
+# endif
+
+# if defined(WANT_IPV6)
+static isc_once_t once_ipv6only = ISC_ONCE_INIT;
+# endif
+
+# if defined(ISC_PLATFORM_HAVEIN6PKTINFO)
+static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT;
+# endif
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+
+static isc_once_t once = ISC_ONCE_INIT;
+
+static isc_result_t ipv4_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6_result = ISC_R_NOTFOUND;
+static isc_result_t unix_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6only_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND;
+
+static isc_result_t
+try_proto(int domain) {
+ int s;
+ isc_result_t result = ISC_R_SUCCESS;
+ char strbuf[ISC_STRERRORSIZE];
+
+ s = socket(domain, SOCK_STREAM, 0);
+ if (s == -1) {
+ switch (errno) {
+#ifdef EAFNOSUPPORT
+ case EAFNOSUPPORT:
+#endif
+#ifdef EPROTONOSUPPORT
+ case EPROTONOSUPPORT:
+#endif
+#ifdef EINVAL
+ case EINVAL:
+#endif
+ return (ISC_R_NOTFOUND);
+ default:
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+ if (domain == PF_INET6) {
+ struct sockaddr_in6 sin6;
+ unsigned int len;
+
+ /*
+ * Check to see if IPv6 is broken, as is common on Linux.
+ */
+ len = sizeof(sin6);
+ if (getsockname(s, (struct sockaddr *)&sin6, (void *)&len) < 0)
+ {
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ "retrieving the address of an IPv6 "
+ "socket from the kernel failed.");
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ "IPv6 is not supported.");
+ result = ISC_R_NOTFOUND;
+ } else {
+ if (len == sizeof(struct sockaddr_in6))
+ result = ISC_R_SUCCESS;
+ else {
+ isc_log_write(isc_lctx,
+ ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET,
+ ISC_LOG_ERROR,
+ "IPv6 structures in kernel and "
+ "user space do not match.");
+ isc_log_write(isc_lctx,
+ ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET,
+ ISC_LOG_ERROR,
+ "IPv6 is not supported.");
+ result = ISC_R_NOTFOUND;
+ }
+ }
+ }
+#endif
+#endif
+#endif
+
+ (void)close(s);
+
+ return (result);
+}
+
+static void
+initialize_action(void) {
+ ipv4_result = try_proto(PF_INET);
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+ ipv6_result = try_proto(PF_INET6);
+#endif
+#endif
+#endif
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ unix_result = try_proto(PF_UNIX);
+#endif
+}
+
+static void
+initialize(void) {
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_net_probeipv4(void) {
+ initialize();
+ return (ipv4_result);
+}
+
+isc_result_t
+isc_net_probeipv6(void) {
+ initialize();
+ return (ipv6_result);
+}
+
+isc_result_t
+isc_net_probeunix(void) {
+ initialize();
+ return (unix_result);
+}
+
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+static void
+try_ipv6only(void) {
+#ifdef IPV6_V6ONLY
+ int s, on;
+ char strbuf[ISC_STRERRORSIZE];
+#endif
+ isc_result_t result;
+
+ result = isc_net_probeipv6();
+ if (result != ISC_R_SUCCESS) {
+ ipv6only_result = result;
+ return;
+ }
+
+#ifndef IPV6_V6ONLY
+ ipv6only_result = ISC_R_NOTFOUND;
+ return;
+#else
+ /* check for TCP sockets */
+ s = socket(PF_INET6, SOCK_STREAM, 0);
+ if (s == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6only_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ close(s);
+
+ /* check for UDP sockets */
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (s == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6only_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ close(s);
+
+ ipv6only_result = ISC_R_SUCCESS;
+
+close:
+ close(s);
+ return;
+#endif /* IPV6_V6ONLY */
+}
+
+static void
+initialize_ipv6only(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6only,
+ try_ipv6only) == ISC_R_SUCCESS);
+}
+#endif /* WANT_IPV6 */
+
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+static void
+try_ipv6pktinfo(void) {
+ int s, on;
+ char strbuf[ISC_STRERRORSIZE];
+ isc_result_t result;
+ int optname;
+
+ result = isc_net_probeipv6();
+ if (result != ISC_R_SUCCESS) {
+ ipv6pktinfo_result = result;
+ return;
+ }
+
+ /* we only use this for UDP sockets */
+ s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6pktinfo_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+#ifdef IPV6_RECVPKTINFO
+ optname = IPV6_RECVPKTINFO;
+#else
+ optname = IPV6_PKTINFO;
+#endif
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) {
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ close(s);
+ ipv6pktinfo_result = ISC_R_SUCCESS;
+
+close:
+ close(s);
+ return;
+}
+
+static void
+initialize_ipv6pktinfo(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo,
+ try_ipv6pktinfo) == ISC_R_SUCCESS);
+}
+#endif /* ISC_PLATFORM_HAVEIN6PKTINFO */
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+
+isc_result_t
+isc_net_probe_ipv6only(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+ initialize_ipv6only();
+#else
+ ipv6only_result = ISC_R_NOTFOUND;
+#endif
+#endif
+ return (ipv6only_result);
+}
+
+isc_result_t
+isc_net_probe_ipv6pktinfo(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+#ifdef WANT_IPV6
+ initialize_ipv6pktinfo();
+#else
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+#endif
+#endif
+#endif
+ return (ipv6pktinfo_result);
+}
+
+#if defined(USE_SYSCTL_PORTRANGE)
+#if defined(HAVE_SYSCTLBYNAME)
+static isc_result_t
+getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) {
+ int port_low, port_high;
+ size_t portlen;
+ const char *sysctlname_lowport, *sysctlname_hiport;
+
+ if (af == AF_INET) {
+ sysctlname_lowport = SYSCTL_V4PORTRANGE_LOW;
+ sysctlname_hiport = SYSCTL_V4PORTRANGE_HIGH;
+ } else {
+ sysctlname_lowport = SYSCTL_V6PORTRANGE_LOW;
+ sysctlname_hiport = SYSCTL_V6PORTRANGE_HIGH;
+ }
+ portlen = sizeof(portlen);
+ if (sysctlbyname(sysctlname_lowport, &port_low, &portlen,
+ NULL, 0) < 0) {
+ return (ISC_R_FAILURE);
+ }
+ portlen = sizeof(portlen);
+ if (sysctlbyname(sysctlname_hiport, &port_high, &portlen,
+ NULL, 0) < 0) {
+ return (ISC_R_FAILURE);
+ }
+ if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0)
+ return (ISC_R_RANGE);
+
+ *low = (in_port_t)port_low;
+ *high = (in_port_t)port_high;
+
+ return (ISC_R_SUCCESS);
+}
+#else /* !HAVE_SYSCTLBYNAME */
+static isc_result_t
+getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) {
+ int mib_lo4[4] = SYSCTL_V4PORTRANGE_LOW;
+ int mib_hi4[4] = SYSCTL_V4PORTRANGE_HIGH;
+ int mib_lo6[4] = SYSCTL_V6PORTRANGE_LOW;
+ int mib_hi6[4] = SYSCTL_V6PORTRANGE_HIGH;
+ int *mib_lo, *mib_hi, miblen;
+ int port_low, port_high;
+ size_t portlen;
+
+ if (af == AF_INET) {
+ mib_lo = mib_lo4;
+ mib_hi = mib_hi4;
+ miblen = sizeof(mib_lo4) / sizeof(mib_lo4[0]);
+ } else {
+ mib_lo = mib_lo6;
+ mib_hi = mib_hi6;
+ miblen = sizeof(mib_lo6) / sizeof(mib_lo6[0]);
+ }
+
+ portlen = sizeof(portlen);
+ if (sysctl(mib_lo, miblen, &port_low, &portlen, NULL, 0) < 0) {
+ return (ISC_R_FAILURE);
+ }
+
+ portlen = sizeof(portlen);
+ if (sysctl(mib_hi, miblen, &port_high, &portlen, NULL, 0) < 0) {
+ return (ISC_R_FAILURE);
+ }
+
+ if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0)
+ return (ISC_R_RANGE);
+
+ *low = (in_port_t) port_low;
+ *high = (in_port_t) port_high;
+
+ return (ISC_R_SUCCESS);
+}
+#endif /* HAVE_SYSCTLBYNAME */
+#endif /* USE_SYSCTL_PORTRANGE */
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) {
+ int result = ISC_R_FAILURE;
+
+ REQUIRE(low != NULL && high != NULL);
+
+#if defined(USE_SYSCTL_PORTRANGE)
+ result = getudpportrange_sysctl(af, low, high);
+#else
+ UNUSED(af);
+#endif
+
+ if (result != ISC_R_SUCCESS) {
+ *low = ISC_NET_PORTRANGELOW;
+ *high = ISC_NET_PORTRANGEHIGH;
+ }
+
+ return (ISC_R_SUCCESS); /* we currently never fail in this function */
+}
+
+void
+isc_net_disableipv4(void) {
+ initialize();
+ if (ipv4_result == ISC_R_SUCCESS)
+ ipv4_result = ISC_R_DISABLED;
+}
+
+void
+isc_net_disableipv6(void) {
+ initialize();
+ if (ipv6_result == ISC_R_SUCCESS)
+ ipv6_result = ISC_R_DISABLED;
+}
+
+void
+isc_net_enableipv4(void) {
+ initialize();
+ if (ipv4_result == ISC_R_DISABLED)
+ ipv4_result = ISC_R_SUCCESS;
+}
+
+void
+isc_net_enableipv6(void) {
+ initialize();
+ if (ipv6_result == ISC_R_DISABLED)
+ ipv6_result = ISC_R_SUCCESS;
+}
diff --git a/lib/isc/unix/os.c b/lib/isc/unix/os.c
new file mode 100644
index 0000000..c050d14
--- /dev/null
+++ b/lib/isc/unix/os.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: os.c,v 1.18 2007/06/19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/os.h>
+
+
+#ifdef HAVE_SYSCONF
+
+#include <unistd.h>
+
+#ifndef __hpux
+static inline long
+sysconf_ncpus(void) {
+#if defined(_SC_NPROCESSORS_ONLN)
+ return sysconf((_SC_NPROCESSORS_ONLN));
+#elif defined(_SC_NPROC_ONLN)
+ return sysconf((_SC_NPROC_ONLN));
+#else
+ return (0);
+#endif
+}
+#endif
+#endif /* HAVE_SYSCONF */
+
+
+#ifdef __hpux
+
+#include <sys/pstat.h>
+
+static inline int
+hpux_ncpus(void) {
+ struct pst_dynamic psd;
+ if (pstat_getdynamic(&psd, sizeof(psd), 1, 0) != -1)
+ return (psd.psd_proc_cnt);
+ else
+ return (0);
+}
+
+#endif /* __hpux */
+
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)
+#include <sys/types.h> /* for FreeBSD */
+#include <sys/param.h> /* for NetBSD */
+#include <sys/sysctl.h>
+
+static int
+sysctl_ncpus(void) {
+ int ncpu, result;
+ size_t len;
+
+ len = sizeof(ncpu);
+ result = sysctlbyname("hw.ncpu", &ncpu, &len , 0, 0);
+ if (result != -1)
+ return (ncpu);
+ return (0);
+}
+#endif
+
+unsigned int
+isc_os_ncpus(void) {
+ long ncpus = 0;
+
+#ifdef __hpux
+ ncpus = hpux_ncpus();
+#elif defined(HAVE_SYSCONF)
+ ncpus = sysconf_ncpus();
+#endif
+#if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTLBYNAME)
+ if (ncpus <= 0)
+ ncpus = sysctl_ncpus();
+#endif
+ if (ncpus <= 0)
+ ncpus = 1;
+
+ return ((unsigned int)ncpus);
+}
diff --git a/lib/isc/unix/resource.c b/lib/isc/unix/resource.c
new file mode 100644
index 0000000..0970e4e
--- /dev/null
+++ b/lib/isc/unix/resource.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2004, 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
+ * 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: resource.c,v 1.21 2008/08/05 07:04:49 marka Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/time.h> /* Required on some systems for <sys/resource.h>. */
+#include <sys/resource.h>
+
+#include <isc/platform.h>
+#include <isc/resource.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#ifdef __linux__
+#include <linux/fs.h> /* To get the large NR_OPEN. */
+#endif
+
+#if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
+#include <sys/dyntune.h>
+#endif
+
+#include "errno2result.h"
+
+static isc_result_t
+resource2rlim(isc_resource_t resource, int *rlim_resource) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ switch (resource) {
+ case isc_resource_coresize:
+ *rlim_resource = RLIMIT_CORE;
+ break;
+ case isc_resource_cputime:
+ *rlim_resource = RLIMIT_CPU;
+ break;
+ case isc_resource_datasize:
+ *rlim_resource = RLIMIT_DATA;
+ break;
+ case isc_resource_filesize:
+ *rlim_resource = RLIMIT_FSIZE;
+ break;
+ case isc_resource_lockedmemory:
+#ifdef RLIMIT_MEMLOCK
+ *rlim_resource = RLIMIT_MEMLOCK;
+#else
+ result = ISC_R_NOTIMPLEMENTED;
+#endif
+ break;
+ case isc_resource_openfiles:
+#ifdef RLIMIT_NOFILE
+ *rlim_resource = RLIMIT_NOFILE;
+#else
+ result = ISC_R_NOTIMPLEMENTED;
+#endif
+ break;
+ case isc_resource_processes:
+#ifdef RLIMIT_NPROC
+ *rlim_resource = RLIMIT_NPROC;
+#else
+ result = ISC_R_NOTIMPLEMENTED;
+#endif
+ break;
+ case isc_resource_residentsize:
+#ifdef RLIMIT_RSS
+ *rlim_resource = RLIMIT_RSS;
+#else
+ result = ISC_R_NOTIMPLEMENTED;
+#endif
+ break;
+ case isc_resource_stacksize:
+ *rlim_resource = RLIMIT_STACK;
+ break;
+ default:
+ /*
+ * This test is not very robust if isc_resource_t
+ * changes, but generates a clear assertion message.
+ */
+ REQUIRE(resource >= isc_resource_coresize &&
+ resource <= isc_resource_stacksize);
+
+ result = ISC_R_RANGE;
+ break;
+ }
+
+ return (result);
+}
+
+isc_result_t
+isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
+ struct rlimit rl;
+ ISC_PLATFORM_RLIMITTYPE rlim_value;
+ int unixresult;
+ int unixresource;
+ isc_result_t result;
+
+ result = resource2rlim(resource, &unixresource);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (value == ISC_RESOURCE_UNLIMITED)
+ rlim_value = RLIM_INFINITY;
+
+ else {
+ /*
+ * isc_resourcevalue_t was chosen as an unsigned 64 bit
+ * integer so that it could contain the maximum range of
+ * reasonable values. Unfortunately, this exceeds the typical
+ * range on Unix systems. Ensure the range of
+ * ISC_PLATFORM_RLIMITTYPE is not overflowed.
+ */
+ isc_resourcevalue_t rlim_max;
+ isc_boolean_t rlim_t_is_signed =
+ ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0);
+
+ if (rlim_t_is_signed)
+ rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 <<
+ (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1));
+ else
+ rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1;
+
+ if (value > rlim_max)
+ value = rlim_max;
+
+ rlim_value = value;
+ }
+
+ rl.rlim_cur = rl.rlim_max = rlim_value;
+ unixresult = setrlimit(unixresource, &rl);
+
+ if (unixresult == 0)
+ return (ISC_R_SUCCESS);
+
+#if defined(OPEN_MAX) && defined(__APPLE__)
+ /*
+ * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the
+ * maximum possible value is OPEN_MAX. BIND8 used to use
+ * sysconf(_SC_OPEN_MAX) for such a case, but this value is much
+ * smaller than OPEN_MAX and is not really effective.
+ */
+ if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
+ rl.rlim_cur = OPEN_MAX;
+ unixresult = setrlimit(unixresource, &rl);
+ if (unixresult == 0)
+ return (ISC_R_SUCCESS);
+ }
+#elif defined(NR_OPEN) && defined(__linux__)
+ /*
+ * Some Linux kernels don't accept RLIM_INFINIT; the maximum
+ * possible value is the NR_OPEN defined in linux/fs.h.
+ */
+ if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
+ rl.rlim_cur = rl.rlim_max = NR_OPEN;
+ unixresult = setrlimit(unixresource, &rl);
+ if (unixresult == 0)
+ return (ISC_R_SUCCESS);
+ }
+#elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
+ if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
+ uint64_t maxfiles;
+ if (gettune("maxfiles_lim", &maxfiles) == 0) {
+ rl.rlim_cur = rl.rlim_max = maxfiles;
+ unixresult = setrlimit(unixresource, &rl);
+ if (unixresult == 0)
+ return (ISC_R_SUCCESS);
+ }
+ }
+#endif
+ if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
+ if (getrlimit(unixresource, &rl) == 0) {
+ rl.rlim_cur = rl.rlim_max;
+ unixresult = setrlimit(unixresource, &rl);
+ if (unixresult == 0)
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+ int unixresult;
+ int unixresource;
+ struct rlimit rl;
+ isc_result_t result;
+
+ result = resource2rlim(resource, &unixresource);
+ if (result == ISC_R_SUCCESS) {
+ unixresult = getrlimit(unixresource, &rl);
+ INSIST(unixresult == 0);
+ *value = rl.rlim_max;
+ }
+
+ return (result);
+}
+
+isc_result_t
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+ int unixresult;
+ int unixresource;
+ struct rlimit rl;
+ isc_result_t result;
+
+ result = resource2rlim(resource, &unixresource);
+ if (result == ISC_R_SUCCESS) {
+ unixresult = getrlimit(unixresource, &rl);
+ INSIST(unixresult == 0);
+ *value = rl.rlim_cur;
+ }
+
+ return (result);
+}
diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c
new file mode 100644
index 0000000..98d0ab6
--- /dev/null
+++ b/lib/isc/unix/socket.c
@@ -0,0 +1,5362 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: socket.c,v 1.308 2008/11/20 00:04:17 jinmei Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/buffer.h>
+#include <isc/bufferlist.h>
+#include <isc/condition.h>
+#include <isc/formatcheck.h>
+#include <isc/list.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/once.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/socket.h>
+#include <isc/strerror.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+#include <isc/xml.h>
+
+#ifdef ISC_PLATFORM_HAVESYSUNH
+#include <sys/un.h>
+#endif
+#ifdef ISC_PLATFORM_HAVEKQUEUE
+#include <sys/event.h>
+#endif
+#ifdef ISC_PLATFORM_HAVEEPOLL
+#include <sys/epoll.h>
+#endif
+#ifdef ISC_PLATFORM_HAVEDEVPOLL
+#include <sys/devpoll.h>
+#endif
+
+#include "errno2result.h"
+
+#ifndef ISC_PLATFORM_USETHREADS
+#include "socket_p.h"
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#if defined(SO_BSDCOMPAT) && defined(__linux__)
+#include <sys/utsname.h>
+#endif
+
+/*%
+ * Choose the most preferable multiplex method.
+ */
+#ifdef ISC_PLATFORM_HAVEKQUEUE
+#define USE_KQUEUE
+#elif defined (ISC_PLATFORM_HAVEEPOLL)
+#define USE_EPOLL
+#elif defined (ISC_PLATFORM_HAVEDEVPOLL)
+#define USE_DEVPOLL
+typedef struct {
+ unsigned int want_read : 1,
+ want_write : 1;
+} pollinfo_t;
+#else
+#define USE_SELECT
+#endif /* ISC_PLATFORM_HAVEKQUEUE */
+
+#ifndef ISC_PLATFORM_USETHREADS
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+struct isc_socketwait {
+ int nevents;
+};
+#elif defined (USE_SELECT)
+struct isc_socketwait {
+ fd_set *readset;
+ fd_set *writeset;
+ int nfds;
+ int maxfd;
+};
+#endif /* USE_KQUEUE */
+#endif /* !ISC_PLATFORM_USETHREADS */
+
+/*%
+ * Maximum number of allowable open sockets. This is also the maximum
+ * allowable socket file descriptor.
+ *
+ * Care should be taken before modifying this value for select():
+ * The API standard doesn't ensure select() accept more than (the system default
+ * of) FD_SETSIZE descriptors, and the default size should in fact be fine in
+ * the vast majority of cases. This constant should therefore be increased only
+ * when absolutely necessary and possible, i.e., the server is exhausting all
+ * available file descriptors (up to FD_SETSIZE) and the select() function
+ * and FD_xxx macros support larger values than FD_SETSIZE (which may not
+ * always by true, but we keep using some of them to ensure as much
+ * portability as possible). Note also that overall server performance
+ * may be rather worsened with a larger value of this constant due to
+ * inherent scalability problems of select().
+ *
+ * As a special note, this value shouldn't have to be touched if
+ * this is a build for an authoritative only DNS server.
+ */
+#ifndef ISC_SOCKET_MAXSOCKETS
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+#define ISC_SOCKET_MAXSOCKETS 4096
+#elif defined(USE_SELECT)
+#define ISC_SOCKET_MAXSOCKETS FD_SETSIZE
+#endif /* USE_KQUEUE... */
+#endif /* ISC_SOCKET_MAXSOCKETS */
+
+#ifdef USE_SELECT
+/*%
+ * Mac OS X needs a special definition to support larger values in select().
+ * We always define this because a larger value can be specified run-time.
+ */
+#ifdef __APPLE__
+#define _DARWIN_UNLIMITED_SELECT
+#endif /* __APPLE__ */
+#endif /* USE_SELECT */
+
+#ifdef ISC_SOCKET_USE_POLLWATCH
+/*%
+ * If this macro is defined, enable workaround for a Solaris /dev/poll kernel
+ * bug: DP_POLL ioctl could keep sleeping even if socket I/O is possible for
+ * some of the specified FD. The idea is based on the observation that it's
+ * likely for a busy server to keep receiving packets. It specifically works
+ * as follows: the socket watcher is first initialized with the state of
+ * "poll_idle". While it's in the idle state it keeps sleeping until a socket
+ * event occurs. When it wakes up for a socket I/O event, it moves to the
+ * poll_active state, and sets the poll timeout to a short period
+ * (ISC_SOCKET_POLLWATCH_TIMEOUT msec). If timeout occurs in this state, the
+ * watcher goes to the poll_checking state with the same timeout period.
+ * In this state, the watcher tries to detect whether this is a break
+ * during intermittent events or the kernel bug is triggered. If the next
+ * polling reports an event within the short period, the previous timeout is
+ * likely to be a kernel bug, and so the watcher goes back to the active state.
+ * Otherwise, it moves to the idle state again.
+ *
+ * It's not clear whether this is a thread-related bug, but since we've only
+ * seen this with threads, this workaround is used only when enabling threads.
+ */
+
+typedef enum { poll_idle, poll_active, poll_checking } pollstate_t;
+
+#ifndef ISC_SOCKET_POLLWATCH_TIMEOUT
+#define ISC_SOCKET_POLLWATCH_TIMEOUT 10
+#endif /* ISC_SOCKET_POLLWATCH_TIMEOUT */
+#endif /* ISC_SOCKET_USE_POLLWATCH */
+
+/*%
+ * Size of per-FD lock buckets.
+ */
+#ifdef ISC_PLATFORM_USETHREADS
+#define FDLOCK_COUNT 1024
+#define FDLOCK_ID(fd) ((fd) % FDLOCK_COUNT)
+#else
+#define FDLOCK_COUNT 1
+#define FDLOCK_ID(fd) 0
+#endif /* ISC_PLATFORM_USETHREADS */
+
+/*%
+ * Maximum number of events communicated with the kernel. There should normally
+ * be no need for having a large number.
+ */
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+#ifndef ISC_SOCKET_MAXEVENTS
+#define ISC_SOCKET_MAXEVENTS 64
+#endif
+#endif
+
+/*%
+ * Some systems define the socket length argument as an int, some as size_t,
+ * some as socklen_t. This is here so it can be easily changed if needed.
+ */
+#ifndef ISC_SOCKADDR_LEN_T
+#define ISC_SOCKADDR_LEN_T unsigned int
+#endif
+
+/*%
+ * Define what the possible "soft" errors can be. These are non-fatal returns
+ * of various network related functions, like recv() and so on.
+ *
+ * For some reason, BSDI (and perhaps others) will sometimes return <0
+ * from recv() but will have errno==0. This is broken, but we have to
+ * work around it here.
+ */
+#define SOFT_ERROR(e) ((e) == EAGAIN || \
+ (e) == EWOULDBLOCK || \
+ (e) == EINTR || \
+ (e) == 0)
+
+#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x)
+
+/*!<
+ * DLVL(90) -- Function entry/exit and other tracing.
+ * DLVL(70) -- Socket "correctness" -- including returning of events, etc.
+ * DLVL(60) -- Socket data send/receive
+ * DLVL(50) -- Event tracing, including receiving/sending completion events.
+ * DLVL(20) -- Socket creation/destruction.
+ */
+#define TRACE_LEVEL 90
+#define CORRECTNESS_LEVEL 70
+#define IOEVENT_LEVEL 60
+#define EVENT_LEVEL 50
+#define CREATION_LEVEL 20
+
+#define TRACE DLVL(TRACE_LEVEL)
+#define CORRECTNESS DLVL(CORRECTNESS_LEVEL)
+#define IOEVENT DLVL(IOEVENT_LEVEL)
+#define EVENT DLVL(EVENT_LEVEL)
+#define CREATION DLVL(CREATION_LEVEL)
+
+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)
+
+/*!
+ * IPv6 control information. If the socket is an IPv6 socket we want
+ * to collect the destination address and interface so the client can
+ * set them on outgoing packets.
+ */
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+#ifndef USE_CMSG
+#define USE_CMSG 1
+#endif
+#endif
+
+/*%
+ * NetBSD and FreeBSD can timestamp packets. XXXMLG Should we have
+ * a setsockopt() like interface to request timestamps, and if the OS
+ * doesn't do it for us, call gettimeofday() on every UDP receive?
+ */
+#ifdef SO_TIMESTAMP
+#ifndef USE_CMSG
+#define USE_CMSG 1
+#endif
+#endif
+
+/*%
+ * The size to raise the recieve buffer to (from BIND 8).
+ */
+#define RCVBUFSIZE (32*1024)
+
+/*%
+ * The number of times a send operation is repeated if the result is EINTR.
+ */
+#define NRETRIES 10
+
+struct isc_socket {
+ /* Not locked. */
+ unsigned int magic;
+ isc_socketmgr_t *manager;
+ isc_mutex_t lock;
+ isc_sockettype_t type;
+
+ /* Locked by socket lock. */
+ ISC_LINK(isc_socket_t) link;
+ unsigned int references;
+ int fd;
+ int pf;
+ char name[16];
+ void * tag;
+
+ ISC_LIST(isc_socketevent_t) send_list;
+ ISC_LIST(isc_socketevent_t) recv_list;
+ ISC_LIST(isc_socket_newconnev_t) accept_list;
+ isc_socket_connev_t *connect_ev;
+
+ /*
+ * Internal events. Posted when a descriptor is readable or
+ * writable. These are statically allocated and never freed.
+ * They will be set to non-purgable before use.
+ */
+ intev_t readable_ev;
+ intev_t writable_ev;
+
+ isc_sockaddr_t peer_address; /* remote address */
+
+ unsigned int pending_recv : 1,
+ pending_send : 1,
+ pending_accept : 1,
+ listener : 1, /* listener socket */
+ connected : 1,
+ connecting : 1, /* connect pending */
+ bound : 1; /* bound to local addr */
+
+#ifdef ISC_NET_RECVOVERFLOW
+ unsigned char overflow; /* used for MSG_TRUNC fake */
+#endif
+
+ char *recvcmsgbuf;
+ ISC_SOCKADDR_LEN_T recvcmsgbuflen;
+ char *sendcmsgbuf;
+ ISC_SOCKADDR_LEN_T sendcmsgbuflen;
+
+ void *fdwatcharg;
+ isc_sockfdwatch_t fdwatchcb;
+ int fdwatchflags;
+ isc_task_t *fdwatchtask;
+};
+
+#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g')
+#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)
+
+struct isc_socketmgr {
+ /* Not locked. */
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_mutex_t lock;
+ isc_mutex_t *fdlock;
+#ifdef USE_KQUEUE
+ int kqueue_fd;
+ int nevents;
+ struct kevent *events;
+#endif /* USE_KQUEUE */
+#ifdef USE_EPOLL
+ int epoll_fd;
+ int nevents;
+ struct epoll_event *events;
+#endif /* USE_EPOLL */
+#ifdef USE_DEVPOLL
+ int devpoll_fd;
+ int nevents;
+ struct pollfd *events;
+#endif /* USE_DEVPOLL */
+#ifdef USE_SELECT
+ int fd_bufsize;
+#endif /* USE_SELECT */
+ unsigned int maxsocks;
+#ifdef ISC_PLATFORM_USETHREADS
+ int pipe_fds[2];
+#endif
+
+ /* Locked by fdlock. */
+ isc_socket_t **fds;
+ int *fdstate;
+#ifdef USE_DEVPOLL
+ pollinfo_t *fdpollinfo;
+#endif
+
+ /* Locked by manager lock. */
+ ISC_LIST(isc_socket_t) socklist;
+#ifdef USE_SELECT
+ fd_set *read_fds;
+ fd_set *read_fds_copy;
+ fd_set *write_fds;
+ fd_set *write_fds_copy;
+ int maxfd;
+#endif /* USE_SELECT */
+ int reserved; /* unlocked */
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_thread_t watcher;
+ isc_condition_t shutdown_ok;
+#else /* ISC_PLATFORM_USETHREADS */
+ unsigned int refs;
+#endif /* ISC_PLATFORM_USETHREADS */
+};
+
+#ifndef ISC_PLATFORM_USETHREADS
+static isc_socketmgr_t *socketmgr = NULL;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#define CLOSED 0 /* this one must be zero */
+#define MANAGED 1
+#define CLOSE_PENDING 2
+
+/*
+ * send() and recv() iovec counts
+ */
+#define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER)
+#ifdef ISC_NET_RECVOVERFLOW
+# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER + 1)
+#else
+# 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 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 *,
+ struct msghdr *, struct iovec *, size_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);
+#endif
+
+#define SELECT_POKE_SHUTDOWN (-1)
+#define SELECT_POKE_NOTHING (-2)
+#define SELECT_POKE_READ (-3)
+#define SELECT_POKE_ACCEPT (-3) /*%< Same as _READ */
+#define SELECT_POKE_WRITE (-4)
+#define SELECT_POKE_CONNECT (-4) /*%< Same as _WRITE */
+#define SELECT_POKE_CLOSE (-5)
+
+#define SOCK_DEAD(s) ((s)->references == 0)
+
+static void
+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,
+ isc_logcategory_t *category, isc_logmodule_t *module, int level,
+ const char *fmt, ...)
+{
+ char msgbuf[2048];
+ va_list ap;
+
+ if (! isc_log_wouldlog(isc_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ va_end(ap);
+
+ isc_log_write(isc_lctx, category, module, level,
+ "sockmgr %p: %s", sockmgr, msgbuf);
+}
+
+static void
+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,
+ isc_logcategory_t *category, isc_logmodule_t *module, int level,
+ isc_msgcat_t *msgcat, int msgset, int message,
+ const char *fmt, ...)
+{
+ char msgbuf[2048];
+ char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+ va_list ap;
+
+ if (! isc_log_wouldlog(isc_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ va_end(ap);
+
+ if (address == NULL) {
+ isc_log_iwrite(isc_lctx, category, module, level,
+ msgcat, msgset, message,
+ "socket %p: %s", sock, msgbuf);
+ } else {
+ isc_sockaddr_format(address, peerbuf, sizeof(peerbuf));
+ isc_log_iwrite(isc_lctx, category, module, level,
+ msgcat, msgset, message,
+ "socket %p %s: %s", sock, peerbuf, msgbuf);
+ }
+}
+
+#if defined(_AIX) && defined(ISC_NET_BSD44MSGHDR) && \
+ defined(USE_CMSG) && defined(IPV6_RECVPKTINFO)
+/*
+ * AIX has a kernel bug where IPV6_RECVPKTINFO gets cleared by
+ * setting IPV6_V6ONLY.
+ */
+static void
+FIX_IPV6_RECVPKTINFO(isc_socket_t *sock)
+{
+ char strbuf[ISC_STRERRORSIZE];
+ int on = 1;
+
+ if (sock->pf != AF_INET6 || sock->type != isc_sockettype_udp)
+ return;
+
+ if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+ (void *)&on, sizeof(on)) < 0) {
+
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_RECVPKTINFO) "
+ "%s: %s", sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
+}
+#else
+#define FIX_IPV6_RECVPKTINFO(sock) (void)0
+#endif
+
+static inline isc_result_t
+watch_fd(isc_socketmgr_t *manager, int fd, int msg) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+#ifdef USE_KQUEUE
+ struct kevent evchange;
+
+ memset(&evchange, 0, sizeof(evchange));
+ if (msg == SELECT_POKE_READ)
+ evchange.filter = EVFILT_READ;
+ else
+ evchange.filter = EVFILT_WRITE;
+ evchange.flags = EV_ADD;
+ evchange.ident = fd;
+ if (kevent(manager->kqueue_fd, &evchange, 1, NULL, 0, NULL) != 0)
+ result = isc__errno2result(errno);
+
+ return (result);
+#elif defined(USE_EPOLL)
+ struct epoll_event event;
+
+ if (msg == SELECT_POKE_READ)
+ event.events = EPOLLIN;
+ else
+ event.events = EPOLLOUT;
+ event.data.fd = fd;
+ if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_ADD, fd, &event) == -1 &&
+ errno != EEXIST) {
+ result = isc__errno2result(errno);
+ }
+
+ return (result);
+#elif defined(USE_DEVPOLL)
+ struct pollfd pfd;
+ int lockid = FDLOCK_ID(fd);
+
+ memset(&pfd, 0, sizeof(pfd));
+ if (msg == SELECT_POKE_READ)
+ pfd.events = POLLIN;
+ else
+ pfd.events = POLLOUT;
+ pfd.fd = fd;
+ pfd.revents = 0;
+ LOCK(&manager->fdlock[lockid]);
+ if (write(manager->devpoll_fd, &pfd, sizeof(pfd)) == -1)
+ result = isc__errno2result(errno);
+ else {
+ if (msg == SELECT_POKE_READ)
+ manager->fdpollinfo[fd].want_read = 1;
+ else
+ manager->fdpollinfo[fd].want_write = 1;
+ }
+ UNLOCK(&manager->fdlock[lockid]);
+
+ return (result);
+#elif defined(USE_SELECT)
+ LOCK(&manager->lock);
+ if (msg == SELECT_POKE_READ)
+ FD_SET(fd, manager->read_fds);
+ if (msg == SELECT_POKE_WRITE)
+ FD_SET(fd, manager->write_fds);
+ UNLOCK(&manager->lock);
+
+ return (result);
+#endif
+}
+
+static inline isc_result_t
+unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+#ifdef USE_KQUEUE
+ struct kevent evchange;
+
+ memset(&evchange, 0, sizeof(evchange));
+ if (msg == SELECT_POKE_READ)
+ evchange.filter = EVFILT_READ;
+ else
+ evchange.filter = EVFILT_WRITE;
+ evchange.flags = EV_DELETE;
+ evchange.ident = fd;
+ if (kevent(manager->kqueue_fd, &evchange, 1, NULL, 0, NULL) != 0)
+ result = isc__errno2result(errno);
+
+ return (result);
+#elif defined(USE_EPOLL)
+ struct epoll_event event;
+
+ if (msg == SELECT_POKE_READ)
+ event.events = EPOLLIN;
+ else
+ event.events = EPOLLOUT;
+ event.data.fd = fd;
+ if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_DEL, fd, &event) == -1 &&
+ errno != ENOENT) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "epoll_ctl(DEL), %d: %s", fd, strbuf);
+ result = ISC_R_UNEXPECTED;
+ }
+ return (result);
+#elif defined(USE_DEVPOLL)
+ struct pollfd pfds[2];
+ size_t writelen = sizeof(pfds[0]);
+ int lockid = FDLOCK_ID(fd);
+
+ memset(pfds, 0, sizeof(pfds));
+ pfds[0].events = POLLREMOVE;
+ pfds[0].fd = fd;
+
+ /*
+ * Canceling read or write polling via /dev/poll is tricky. Since it
+ * only provides a way of canceling per FD, we may need to re-poll the
+ * socket for the other operation.
+ */
+ LOCK(&manager->fdlock[lockid]);
+ if (msg == SELECT_POKE_READ &&
+ manager->fdpollinfo[fd].want_write == 1) {
+ pfds[1].events = POLLOUT;
+ pfds[1].fd = fd;
+ writelen += sizeof(pfds[1]);
+ }
+ if (msg == SELECT_POKE_WRITE &&
+ manager->fdpollinfo[fd].want_read == 1) {
+ pfds[1].events = POLLIN;
+ pfds[1].fd = fd;
+ writelen += sizeof(pfds[1]);
+ }
+
+ if (write(manager->devpoll_fd, pfds, writelen) == -1)
+ result = isc__errno2result(errno);
+ else {
+ if (msg == SELECT_POKE_READ)
+ manager->fdpollinfo[fd].want_read = 0;
+ else
+ manager->fdpollinfo[fd].want_write = 0;
+ }
+ UNLOCK(&manager->fdlock[lockid]);
+
+ return (result);
+#elif defined(USE_SELECT)
+ LOCK(&manager->lock);
+ if (msg == SELECT_POKE_READ)
+ FD_CLR(fd, manager->read_fds);
+ else if (msg == SELECT_POKE_WRITE)
+ FD_CLR(fd, manager->write_fds);
+ UNLOCK(&manager->lock);
+
+ return (result);
+#endif
+}
+
+static void
+wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
+ isc_result_t result;
+ int lockid = FDLOCK_ID(fd);
+
+ /*
+ * This is a wakeup on a socket. If the socket is not in the
+ * process of being closed, start watching it for either reads
+ * or writes.
+ */
+
+ INSIST(fd >= 0 && fd < (int)manager->maxsocks);
+
+ if (msg == SELECT_POKE_CLOSE) {
+ /* No one should be updating fdstate, so no need to lock it */
+ INSIST(manager->fdstate[fd] == CLOSE_PENDING);
+ manager->fdstate[fd] = CLOSED;
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ (void)close(fd);
+ return;
+ }
+
+ LOCK(&manager->fdlock[lockid]);
+ if (manager->fdstate[fd] == CLOSE_PENDING) {
+ UNLOCK(&manager->fdlock[lockid]);
+
+ /*
+ * We accept (and ignore) any error from unwatch_fd() as we are
+ * closing the socket, hoping it doesn't leave dangling state in
+ * the kernel.
+ * Note that unwatch_fd() must be called after releasing the
+ * fdlock; otherwise it could cause deadlock due to a lock order
+ * reversal.
+ */
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ return;
+ }
+ if (manager->fdstate[fd] != MANAGED) {
+ UNLOCK(&manager->fdlock[lockid]);
+ return;
+ }
+ UNLOCK(&manager->fdlock[lockid]);
+
+ /*
+ * Set requested bit.
+ */
+ result = watch_fd(manager, fd, msg);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * XXXJT: what should we do? Ignoring the failure of watching
+ * a socket will make the application dysfunctional, but there
+ * seems to be no reasonable recovery process.
+ */
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ "failed to start watching FD (%d): %s",
+ fd, isc_result_totext(result));
+ }
+}
+
+#ifdef ISC_PLATFORM_USETHREADS
+/*
+ * 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) {
+ int cc;
+ int buf[2];
+ char strbuf[ISC_STRERRORSIZE];
+
+ buf[0] = fd;
+ buf[1] = msg;
+
+ do {
+ cc = write(mgr->pipe_fds[1], buf, sizeof(buf));
+#ifdef ENOSR
+ /*
+ * Treat ENOSR as EAGAIN but loop slowly as it is
+ * unlikely to clear fast.
+ */
+ if (cc < 0 && errno == ENOSR) {
+ sleep(1);
+ errno = EAGAIN;
+ }
+#endif
+ } while (cc < 0 && SOFT_ERROR(errno));
+
+ if (cc < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_WRITEFAILED,
+ "write() failed "
+ "during watcher poke: %s"),
+ strbuf);
+ }
+
+ INSIST(cc == sizeof(buf));
+}
+
+/*
+ * Read a message on the internal fd.
+ */
+static void
+select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) {
+ int buf[2];
+ int cc;
+ char strbuf[ISC_STRERRORSIZE];
+
+ cc = read(mgr->pipe_fds[0], buf, sizeof(buf));
+ if (cc < 0) {
+ *msg = SELECT_POKE_NOTHING;
+ *fd = -1; /* Silence compiler. */
+ if (SOFT_ERROR(errno))
+ return;
+
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_READFAILED,
+ "read() failed "
+ "during watcher poke: %s"),
+ strbuf);
+
+ return;
+ }
+ INSIST(cc == sizeof(buf));
+
+ *fd = buf[0];
+ *msg = buf[1];
+}
+#else /* ISC_PLATFORM_USETHREADS */
+/*
+ * Update the state of the socketmgr when something changes.
+ */
+static void
+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 */
+
+/*
+ * Make a fd non-blocking.
+ */
+static isc_result_t
+make_nonblock(int fd) {
+ int ret;
+ int flags;
+ char strbuf[ISC_STRERRORSIZE];
+#ifdef USE_FIONBIO_IOCTL
+ int on = 1;
+
+ ret = ioctl(fd, FIONBIO, (char *)&on);
+#else
+ flags = fcntl(fd, F_GETFL, 0);
+ flags |= PORT_NONBLOCK;
+ ret = fcntl(fd, F_SETFL, flags);
+#endif
+
+ if (ret == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+#ifdef USE_FIONBIO_IOCTL
+ "ioctl(%d, FIONBIO, &on): %s", fd,
+#else
+ "fcntl(%d, F_SETFL, %d): %s", fd, flags,
+#endif
+ strbuf);
+
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+#ifdef USE_CMSG
+/*
+ * Not all OSes support advanced CMSG macros: CMSG_LEN and CMSG_SPACE.
+ * In order to ensure as much portability as possible, we provide wrapper
+ * functions of these macros.
+ * Note that cmsg_space() could run slow on OSes that do not have
+ * CMSG_SPACE.
+ */
+static inline ISC_SOCKADDR_LEN_T
+cmsg_len(ISC_SOCKADDR_LEN_T len) {
+#ifdef CMSG_LEN
+ return (CMSG_LEN(len));
+#else
+ ISC_SOCKADDR_LEN_T hdrlen;
+
+ /*
+ * Cast NULL so that any pointer arithmetic performed by CMSG_DATA
+ * is correct.
+ */
+ hdrlen = (ISC_SOCKADDR_LEN_T)CMSG_DATA(((struct cmsghdr *)NULL));
+ return (hdrlen + len);
+#endif
+}
+
+static inline ISC_SOCKADDR_LEN_T
+cmsg_space(ISC_SOCKADDR_LEN_T len) {
+#ifdef CMSG_SPACE
+ return (CMSG_SPACE(len));
+#else
+ struct msghdr msg;
+ struct cmsghdr *cmsgp;
+ /*
+ * XXX: The buffer length is an ad-hoc value, but should be enough
+ * in a practical sense.
+ */
+ char dummybuf[sizeof(struct cmsghdr) + 1024];
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_control = dummybuf;
+ msg.msg_controllen = sizeof(dummybuf);
+
+ cmsgp = (struct cmsghdr *)dummybuf;
+ cmsgp->cmsg_len = cmsg_len(len);
+
+ cmsgp = CMSG_NXTHDR(&msg, cmsgp);
+ if (cmsgp != NULL)
+ return ((char *)cmsgp - (char *)msg.msg_control);
+ else
+ return (0);
+#endif
+}
+#endif /* USE_CMSG */
+
+/*
+ * Process control messages received on a socket.
+ */
+static void
+process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
+#ifdef USE_CMSG
+ struct cmsghdr *cmsgp;
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+ struct in6_pktinfo *pktinfop;
+#endif
+#ifdef SO_TIMESTAMP
+ struct timeval *timevalp;
+#endif
+#endif
+
+ /*
+ * sock is used only when ISC_NET_BSD44MSGHDR and USE_CMSG are defined.
+ * msg and dev are used only when ISC_NET_BSD44MSGHDR is defined.
+ * They are all here, outside of the CPP tests, because it is
+ * more consistent with the usual ISC coding style.
+ */
+ UNUSED(sock);
+ UNUSED(msg);
+ UNUSED(dev);
+
+#ifdef ISC_NET_BSD44MSGHDR
+
+#ifdef MSG_TRUNC
+ if ((msg->msg_flags & MSG_TRUNC) == MSG_TRUNC)
+ dev->attributes |= ISC_SOCKEVENTATTR_TRUNC;
+#endif
+
+#ifdef MSG_CTRUNC
+ if ((msg->msg_flags & MSG_CTRUNC) == MSG_CTRUNC)
+ dev->attributes |= ISC_SOCKEVENTATTR_CTRUNC;
+#endif
+
+#ifndef USE_CMSG
+ return;
+#else
+ if (msg->msg_controllen == 0U || msg->msg_control == NULL)
+ return;
+
+#ifdef SO_TIMESTAMP
+ timevalp = NULL;
+#endif
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+ pktinfop = NULL;
+#endif
+
+ cmsgp = CMSG_FIRSTHDR(msg);
+ while (cmsgp != NULL) {
+ socket_log(sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_PROCESSCMSG,
+ "processing cmsg %p", cmsgp);
+
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+ if (cmsgp->cmsg_level == IPPROTO_IPV6
+ && cmsgp->cmsg_type == IPV6_PKTINFO) {
+
+ pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
+ memcpy(&dev->pktinfo, pktinfop,
+ sizeof(struct in6_pktinfo));
+ dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO;
+ socket_log(sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_IFRECEIVED,
+ "interface received on ifindex %u",
+ dev->pktinfo.ipi6_ifindex);
+ if (IN6_IS_ADDR_MULTICAST(&pktinfop->ipi6_addr))
+ dev->attributes |= ISC_SOCKEVENTATTR_MULTICAST;
+ goto next;
+ }
+#endif
+
+#ifdef SO_TIMESTAMP
+ if (cmsgp->cmsg_level == SOL_SOCKET
+ && cmsgp->cmsg_type == SCM_TIMESTAMP) {
+ timevalp = (struct timeval *)CMSG_DATA(cmsgp);
+ dev->timestamp.seconds = timevalp->tv_sec;
+ dev->timestamp.nanoseconds = timevalp->tv_usec * 1000;
+ dev->attributes |= ISC_SOCKEVENTATTR_TIMESTAMP;
+ goto next;
+ }
+#endif
+
+ next:
+ cmsgp = CMSG_NXTHDR(msg, cmsgp);
+ }
+#endif /* USE_CMSG */
+
+#endif /* ISC_NET_BSD44MSGHDR */
+}
+
+/*
+ * Construct an iov array and attach it to the msghdr passed in. This is
+ * the SEND constructor, which will use the used region of the buffer
+ * (if using a buffer list) or will use the internal region (if a single
+ * buffer I/O is requested).
+ *
+ * Nothing can be NULL, and the done event must list at least one buffer
+ * on the buffer linked list for this function to be meaningful.
+ *
+ * If write_countp != NULL, *write_countp will hold the number of bytes
+ * this transaction can send.
+ */
+static void
+build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
+ struct msghdr *msg, struct iovec *iov, size_t *write_countp)
+{
+ unsigned int iovcount;
+ isc_buffer_t *buffer;
+ isc_region_t used;
+ size_t write_count;
+ size_t skip_count;
+
+ memset(msg, 0, sizeof(*msg));
+
+ if (!sock->connected) {
+ msg->msg_name = (void *)&dev->address.type.sa;
+ msg->msg_namelen = dev->address.length;
+ } else {
+ msg->msg_name = NULL;
+ msg->msg_namelen = 0;
+ }
+
+ buffer = ISC_LIST_HEAD(dev->bufferlist);
+ write_count = 0;
+ iovcount = 0;
+
+ /*
+ * Single buffer I/O? Skip what we've done so far in this region.
+ */
+ if (buffer == NULL) {
+ write_count = dev->region.length - dev->n;
+ iov[0].iov_base = (void *)(dev->region.base + dev->n);
+ iov[0].iov_len = write_count;
+ iovcount = 1;
+
+ goto config;
+ }
+
+ /*
+ * Multibuffer I/O.
+ * Skip the data in the buffer list that we have already written.
+ */
+ skip_count = dev->n;
+ while (buffer != NULL) {
+ REQUIRE(ISC_BUFFER_VALID(buffer));
+ if (skip_count < isc_buffer_usedlength(buffer))
+ break;
+ skip_count -= isc_buffer_usedlength(buffer);
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+
+ while (buffer != NULL) {
+ INSIST(iovcount < MAXSCATTERGATHER_SEND);
+
+ isc_buffer_usedregion(buffer, &used);
+
+ if (used.length > 0) {
+ iov[iovcount].iov_base = (void *)(used.base
+ + skip_count);
+ iov[iovcount].iov_len = used.length - skip_count;
+ write_count += (used.length - skip_count);
+ skip_count = 0;
+ iovcount++;
+ }
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+
+ INSIST(skip_count == 0U);
+
+ config:
+ msg->msg_iov = iov;
+ msg->msg_iovlen = iovcount;
+
+#ifdef ISC_NET_BSD44MSGHDR
+ msg->msg_control = NULL;
+ msg->msg_controllen = 0;
+ msg->msg_flags = 0;
+#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
+ if ((sock->type == isc_sockettype_udp)
+ && ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0)) {
+ struct cmsghdr *cmsgp;
+ struct in6_pktinfo *pktinfop;
+
+ socket_log(sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_SENDTODATA,
+ "sendto pktinfo data, ifindex %u",
+ dev->pktinfo.ipi6_ifindex);
+
+ msg->msg_controllen = cmsg_space(sizeof(struct in6_pktinfo));
+ INSIST(msg->msg_controllen <= sock->sendcmsgbuflen);
+ msg->msg_control = (void *)sock->sendcmsgbuf;
+
+ cmsgp = (struct cmsghdr *)sock->sendcmsgbuf;
+ cmsgp->cmsg_level = IPPROTO_IPV6;
+ cmsgp->cmsg_type = IPV6_PKTINFO;
+ cmsgp->cmsg_len = cmsg_len(sizeof(struct in6_pktinfo));
+ pktinfop = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
+ memcpy(pktinfop, &dev->pktinfo, sizeof(struct in6_pktinfo));
+ }
+#endif /* USE_CMSG && ISC_PLATFORM_HAVEIPV6 */
+#else /* ISC_NET_BSD44MSGHDR */
+ msg->msg_accrights = NULL;
+ msg->msg_accrightslen = 0;
+#endif /* ISC_NET_BSD44MSGHDR */
+
+ if (write_countp != NULL)
+ *write_countp = write_count;
+}
+
+/*
+ * Construct an iov array and attach it to the msghdr passed in. This is
+ * the RECV constructor, which will use the avialable region of the buffer
+ * (if using a buffer list) or will use the internal region (if a single
+ * buffer I/O is requested).
+ *
+ * Nothing can be NULL, and the done event must list at least one buffer
+ * on the buffer linked list for this function to be meaningful.
+ *
+ * If read_countp != NULL, *read_countp will hold the number of bytes
+ * this transaction can receive.
+ */
+static void
+build_msghdr_recv(isc_socket_t *sock, isc_socketevent_t *dev,
+ struct msghdr *msg, struct iovec *iov, size_t *read_countp)
+{
+ unsigned int iovcount;
+ isc_buffer_t *buffer;
+ isc_region_t available;
+ size_t read_count;
+
+ memset(msg, 0, sizeof(struct msghdr));
+
+ if (sock->type == isc_sockettype_udp) {
+ memset(&dev->address, 0, sizeof(dev->address));
+#ifdef BROKEN_RECVMSG
+ if (sock->pf == AF_INET) {
+ msg->msg_name = (void *)&dev->address.type.sin;
+ msg->msg_namelen = sizeof(dev->address.type.sin6);
+ } else if (sock->pf == AF_INET6) {
+ msg->msg_name = (void *)&dev->address.type.sin6;
+ msg->msg_namelen = sizeof(dev->address.type.sin6);
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ } else if (sock->pf == AF_UNIX) {
+ msg->msg_name = (void *)&dev->address.type.sunix;
+ msg->msg_namelen = sizeof(dev->address.type.sunix);
+#endif
+ } else {
+ msg->msg_name = (void *)&dev->address.type.sa;
+ msg->msg_namelen = sizeof(dev->address.type);
+ }
+#else
+ msg->msg_name = (void *)&dev->address.type.sa;
+ msg->msg_namelen = sizeof(dev->address.type);
+#endif
+#ifdef ISC_NET_RECVOVERFLOW
+ /* If needed, steal one iovec for overflow detection. */
+ maxiov--;
+#endif
+ } else { /* TCP */
+ msg->msg_name = NULL;
+ msg->msg_namelen = 0;
+ dev->address = sock->peer_address;
+ }
+
+ buffer = ISC_LIST_HEAD(dev->bufferlist);
+ read_count = 0;
+
+ /*
+ * Single buffer I/O? Skip what we've done so far in this region.
+ */
+ if (buffer == NULL) {
+ read_count = dev->region.length - dev->n;
+ iov[0].iov_base = (void *)(dev->region.base + dev->n);
+ iov[0].iov_len = read_count;
+ iovcount = 1;
+
+ goto config;
+ }
+
+ /*
+ * Multibuffer I/O.
+ * Skip empty buffers.
+ */
+ while (buffer != NULL) {
+ REQUIRE(ISC_BUFFER_VALID(buffer));
+ if (isc_buffer_availablelength(buffer) != 0)
+ break;
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+
+ iovcount = 0;
+ while (buffer != NULL) {
+ INSIST(iovcount < MAXSCATTERGATHER_RECV);
+
+ isc_buffer_availableregion(buffer, &available);
+
+ if (available.length > 0) {
+ iov[iovcount].iov_base = (void *)(available.base);
+ iov[iovcount].iov_len = available.length;
+ read_count += available.length;
+ iovcount++;
+ }
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+
+ config:
+
+ /*
+ * If needed, set up to receive that one extra byte. Note that
+ * we know there is at least one iov left, since we stole it
+ * at the top of this function.
+ */
+#ifdef ISC_NET_RECVOVERFLOW
+ if (sock->type == isc_sockettype_udp) {
+ iov[iovcount].iov_base = (void *)(&sock->overflow);
+ iov[iovcount].iov_len = 1;
+ iovcount++;
+ }
+#endif
+
+ msg->msg_iov = iov;
+ msg->msg_iovlen = iovcount;
+
+#ifdef ISC_NET_BSD44MSGHDR
+ msg->msg_control = NULL;
+ msg->msg_controllen = 0;
+ msg->msg_flags = 0;
+#if defined(USE_CMSG)
+ if (sock->type == isc_sockettype_udp) {
+ msg->msg_control = sock->recvcmsgbuf;
+ msg->msg_controllen = sock->recvcmsgbuflen;
+ }
+#endif /* USE_CMSG */
+#else /* ISC_NET_BSD44MSGHDR */
+ msg->msg_accrights = NULL;
+ msg->msg_accrightslen = 0;
+#endif /* ISC_NET_BSD44MSGHDR */
+
+ if (read_countp != NULL)
+ *read_countp = read_count;
+}
+
+static void
+set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock,
+ isc_socketevent_t *dev)
+{
+ if (sock->type == isc_sockettype_udp) {
+ if (address != NULL)
+ dev->address = *address;
+ else
+ dev->address = sock->peer_address;
+ } else if (sock->type == isc_sockettype_tcp) {
+ INSIST(address == NULL);
+ dev->address = sock->peer_address;
+ }
+}
+
+static void
+destroy_socketevent(isc_event_t *event) {
+ isc_socketevent_t *ev = (isc_socketevent_t *)event;
+
+ INSIST(ISC_LIST_EMPTY(ev->bufferlist));
+
+ (ev->destroy)(event);
+}
+
+static isc_socketevent_t *
+allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
+ isc_taskaction_t action, const void *arg)
+{
+ isc_socketevent_t *ev;
+
+ ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx,
+ sock, eventtype,
+ action, arg,
+ sizeof(*ev));
+
+ if (ev == NULL)
+ return (NULL);
+
+ ev->result = ISC_R_UNEXPECTED;
+ ISC_LINK_INIT(ev, ev_link);
+ ISC_LIST_INIT(ev->bufferlist);
+ ev->region.base = NULL;
+ ev->n = 0;
+ ev->offset = 0;
+ ev->attributes = 0;
+ ev->destroy = ev->ev_destroy;
+ ev->ev_destroy = destroy_socketevent;
+
+ return (ev);
+}
+
+#if defined(ISC_SOCKET_DEBUG)
+static void
+dump_msg(struct msghdr *msg) {
+ unsigned int i;
+
+ printf("MSGHDR %p\n", msg);
+ printf("\tname %p, namelen %ld\n", msg->msg_name,
+ (long) msg->msg_namelen);
+ printf("\tiov %p, iovlen %ld\n", msg->msg_iov,
+ (long) msg->msg_iovlen);
+ for (i = 0; i < (unsigned int)msg->msg_iovlen; i++)
+ printf("\t\t%d\tbase %p, len %ld\n", i,
+ msg->msg_iov[i].iov_base,
+ (long) msg->msg_iov[i].iov_len);
+#ifdef ISC_NET_BSD44MSGHDR
+ printf("\tcontrol %p, controllen %ld\n", msg->msg_control,
+ (long) msg->msg_controllen);
+#endif
+}
+#endif
+
+#define DOIO_SUCCESS 0 /* i/o ok, event sent */
+#define DOIO_SOFT 1 /* i/o ok, soft error, no event sent */
+#define DOIO_HARD 2 /* i/o error, event sent */
+#define DOIO_EOF 3 /* EOF, no event sent */
+
+static int
+doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
+ int cc;
+ struct iovec iov[MAXSCATTERGATHER_RECV];
+ size_t read_count;
+ size_t actual_count;
+ struct msghdr msghdr;
+ isc_buffer_t *buffer;
+ int recv_errno;
+ char strbuf[ISC_STRERRORSIZE];
+
+ build_msghdr_recv(sock, dev, &msghdr, iov, &read_count);
+
+#if defined(ISC_SOCKET_DEBUG)
+ dump_msg(&msghdr);
+#endif
+
+ cc = recvmsg(sock->fd, &msghdr, 0);
+ recv_errno = errno;
+
+#if defined(ISC_SOCKET_DEBUG)
+ dump_msg(&msghdr);
+#endif
+
+ if (cc < 0) {
+ if (SOFT_ERROR(recv_errno))
+ return (DOIO_SOFT);
+
+ if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
+ isc__strerror(recv_errno, strbuf, sizeof(strbuf));
+ socket_log(sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_DOIORECV,
+ "doio_recv: recvmsg(%d) %d bytes, err %d/%s",
+ sock->fd, cc, recv_errno, strbuf);
+ }
+
+#define SOFT_OR_HARD(_system, _isc) \
+ if (recv_errno == _system) { \
+ if (sock->connected) { \
+ dev->result = _isc; \
+ return (DOIO_HARD); \
+ } \
+ return (DOIO_SOFT); \
+ }
+#define ALWAYS_HARD(_system, _isc) \
+ if (recv_errno == _system) { \
+ dev->result = _isc; \
+ return (DOIO_HARD); \
+ }
+
+ SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);
+ SOFT_OR_HARD(ENETUNREACH, ISC_R_NETUNREACH);
+ SOFT_OR_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH);
+ SOFT_OR_HARD(EHOSTDOWN, ISC_R_HOSTDOWN);
+ /* HPUX 11.11 can return EADDRNOTAVAIL. */
+ SOFT_OR_HARD(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+ ALWAYS_HARD(ENOBUFS, ISC_R_NORESOURCES);
+ /*
+ * HPUX returns EPROTO and EINVAL on receiving some ICMP/ICMPv6
+ * errors.
+ */
+#ifdef EPROTO
+ SOFT_OR_HARD(EPROTO, ISC_R_HOSTUNREACH);
+#endif
+ SOFT_OR_HARD(EINVAL, ISC_R_HOSTUNREACH);
+
+#undef SOFT_OR_HARD
+#undef ALWAYS_HARD
+
+ dev->result = isc__errno2result(recv_errno);
+ return (DOIO_HARD);
+ }
+
+ /*
+ * On TCP, zero length reads indicate EOF, while on
+ * UDP, zero length reads are perfectly valid, although
+ * strange.
+ */
+ if ((sock->type == isc_sockettype_tcp) && (cc == 0))
+ return (DOIO_EOF);
+
+ if (sock->type == isc_sockettype_udp) {
+ dev->address.length = msghdr.msg_namelen;
+ if (isc_sockaddr_getport(&dev->address) == 0) {
+ if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
+ socket_log(sock, &dev->address, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_ZEROPORT,
+ "dropping source port zero packet");
+ }
+ return (DOIO_SOFT);
+ }
+ }
+
+ socket_log(sock, &dev->address, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_PKTRECV,
+ "packet received correctly");
+
+ /*
+ * Overflow bit detection. If we received MORE bytes than we should,
+ * this indicates an overflow situation. Set the flag in the
+ * dev entry and adjust how much we read by one.
+ */
+#ifdef ISC_NET_RECVOVERFLOW
+ if ((sock->type == isc_sockettype_udp) && ((size_t)cc > read_count)) {
+ dev->attributes |= ISC_SOCKEVENTATTR_TRUNC;
+ cc--;
+ }
+#endif
+
+ /*
+ * If there are control messages attached, run through them and pull
+ * out the interesting bits.
+ */
+ if (sock->type == isc_sockettype_udp)
+ process_cmsg(sock, &msghdr, dev);
+
+ /*
+ * update the buffers (if any) and the i/o count
+ */
+ dev->n += cc;
+ actual_count = cc;
+ buffer = ISC_LIST_HEAD(dev->bufferlist);
+ while (buffer != NULL && actual_count > 0U) {
+ REQUIRE(ISC_BUFFER_VALID(buffer));
+ if (isc_buffer_availablelength(buffer) <= actual_count) {
+ actual_count -= isc_buffer_availablelength(buffer);
+ isc_buffer_add(buffer,
+ isc_buffer_availablelength(buffer));
+ } else {
+ isc_buffer_add(buffer, actual_count);
+ actual_count = 0;
+ break;
+ }
+ buffer = ISC_LIST_NEXT(buffer, link);
+ if (buffer == NULL) {
+ INSIST(actual_count == 0U);
+ }
+ }
+
+ /*
+ * If we read less than we expected, update counters,
+ * and let the upper layer poke the descriptor.
+ */
+ if (((size_t)cc != read_count) && (dev->n < dev->minimum))
+ return (DOIO_SOFT);
+
+ /*
+ * Full reads are posted, or partials if partials are ok.
+ */
+ dev->result = ISC_R_SUCCESS;
+ return (DOIO_SUCCESS);
+}
+
+/*
+ * Returns:
+ * DOIO_SUCCESS The operation succeeded. dev->result contains
+ * ISC_R_SUCCESS.
+ *
+ * DOIO_HARD A hard or unexpected I/O error was encountered.
+ * dev->result contains the appropriate error.
+ *
+ * DOIO_SOFT A soft I/O error was encountered. No senddone
+ * event was sent. The operation should be retried.
+ *
+ * No other return values are possible.
+ */
+static int
+doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
+ int cc;
+ struct iovec iov[MAXSCATTERGATHER_SEND];
+ size_t write_count;
+ struct msghdr msghdr;
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ int attempts = 0;
+ int send_errno;
+ char strbuf[ISC_STRERRORSIZE];
+
+ build_msghdr_send(sock, dev, &msghdr, iov, &write_count);
+
+ resend:
+ cc = sendmsg(sock->fd, &msghdr, 0);
+ send_errno = errno;
+
+ /*
+ * Check for error or block condition.
+ */
+ if (cc < 0) {
+ if (send_errno == EINTR && ++attempts < NRETRIES)
+ goto resend;
+
+ if (SOFT_ERROR(send_errno))
+ return (DOIO_SOFT);
+
+#define SOFT_OR_HARD(_system, _isc) \
+ if (send_errno == _system) { \
+ if (sock->connected) { \
+ dev->result = _isc; \
+ return (DOIO_HARD); \
+ } \
+ return (DOIO_SOFT); \
+ }
+#define ALWAYS_HARD(_system, _isc) \
+ if (send_errno == _system) { \
+ dev->result = _isc; \
+ return (DOIO_HARD); \
+ }
+
+ SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);
+ ALWAYS_HARD(EACCES, ISC_R_NOPERM);
+ ALWAYS_HARD(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
+ ALWAYS_HARD(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+ ALWAYS_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH);
+#ifdef EHOSTDOWN
+ ALWAYS_HARD(EHOSTDOWN, ISC_R_HOSTUNREACH);
+#endif
+ ALWAYS_HARD(ENETUNREACH, ISC_R_NETUNREACH);
+ ALWAYS_HARD(ENOBUFS, ISC_R_NORESOURCES);
+ ALWAYS_HARD(EPERM, ISC_R_HOSTUNREACH);
+ ALWAYS_HARD(EPIPE, ISC_R_NOTCONNECTED);
+ ALWAYS_HARD(ECONNRESET, ISC_R_CONNECTIONRESET);
+
+#undef SOFT_OR_HARD
+#undef ALWAYS_HARD
+
+ /*
+ * The other error types depend on whether or not the
+ * socket is UDP or TCP. If it is UDP, some errors
+ * that we expect to be fatal under TCP are merely
+ * annoying, and are really soft errors.
+ *
+ * However, these soft errors are still returned as
+ * a status.
+ */
+ isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf));
+ isc__strerror(send_errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_send: %s: %s",
+ addrbuf, strbuf);
+ dev->result = isc__errno2result(send_errno);
+ return (DOIO_HARD);
+ }
+
+ if (cc == 0)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "internal_send: send() %s 0",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_RETURNED, "returned"));
+
+ /*
+ * If we write less than we expected, update counters, poke.
+ */
+ dev->n += cc;
+ if ((size_t)cc != write_count)
+ return (DOIO_SOFT);
+
+ /*
+ * Exactly what we wanted to write. We're done with this
+ * entry. Post its completion event.
+ */
+ dev->result = ISC_R_SUCCESS;
+ return (DOIO_SUCCESS);
+}
+
+/*
+ * Kill.
+ *
+ * Caller must ensure that the socket is not locked and no external
+ * references exist.
+ */
+static void
+closesocket(isc_socketmgr_t *manager, isc_sockettype_t type, int fd) {
+ int lockid = FDLOCK_ID(fd);
+
+ /*
+ * No one has this socket open, so the watcher doesn't have to be
+ * poked, and the socket doesn't have to be locked.
+ */
+ LOCK(&manager->fdlock[lockid]);
+ manager->fds[fd] = NULL;
+ if (type == isc_sockettype_fdwatch)
+ manager->fdstate[fd] = CLOSED;
+ else
+ manager->fdstate[fd] = CLOSE_PENDING;
+ UNLOCK(&manager->fdlock[lockid]);
+ if (type == isc_sockettype_fdwatch) {
+ /*
+ * The caller may close the socket once this function returns,
+ * and `fd' may be reassigned for a new socket. So we do
+ * unwatch_fd() here, rather than defer it via select_poke().
+ * Note: this may complicate data protection among threads and
+ * may reduce performance due to additional locks. One way to
+ * solve this would be to dup() the watched descriptor, but we
+ * take a simpler approach at this moment.
+ */
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ } else
+ select_poke(manager, fd, SELECT_POKE_CLOSE);
+
+ /*
+ * update manager->maxfd here (XXX: this should be implemented more
+ * efficiently)
+ */
+#ifdef USE_SELECT
+ LOCK(&manager->lock);
+ if (manager->maxfd == fd) {
+ int i;
+
+ manager->maxfd = 0;
+ for (i = fd - 1; i >= 0; i--) {
+ lockid = FDLOCK_ID(i);
+
+ LOCK(&manager->fdlock[lockid]);
+ if (manager->fdstate[i] == MANAGED) {
+ manager->maxfd = i;
+ UNLOCK(&manager->fdlock[lockid]);
+ break;
+ }
+ UNLOCK(&manager->fdlock[lockid]);
+ }
+#ifdef ISC_PLATFORM_USETHREADS
+ if (manager->maxfd < manager->pipe_fds[0])
+ manager->maxfd = manager->pipe_fds[0];
+#endif
+ }
+ UNLOCK(&manager->lock);
+#endif /* USE_SELECT */
+}
+
+static void
+destroy(isc_socket_t **sockp) {
+ int fd;
+ 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");
+
+ INSIST(ISC_LIST_EMPTY(sock->accept_list));
+ INSIST(ISC_LIST_EMPTY(sock->recv_list));
+ INSIST(ISC_LIST_EMPTY(sock->send_list));
+ INSIST(sock->connect_ev == NULL);
+ REQUIRE(sock->fd == -1 || sock->fd < (int)manager->maxsocks);
+
+ if (sock->fd >= 0) {
+ fd = sock->fd;
+ sock->fd = -1;
+ closesocket(manager, sock->type, fd);
+ }
+
+ LOCK(&manager->lock);
+
+ ISC_LIST_UNLINK(manager->socklist, sock, link);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ if (ISC_LIST_EMPTY(manager->socklist))
+ SIGNAL(&manager->shutdown_ok);
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ UNLOCK(&manager->lock);
+
+ free_socket(sockp);
+}
+
+static isc_result_t
+allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
+ isc_socket_t **socketp)
+{
+ isc_socket_t *sock;
+ isc_result_t result;
+ ISC_SOCKADDR_LEN_T cmsgbuflen;
+
+ sock = isc_mem_get(manager->mctx, sizeof(*sock));
+
+ if (sock == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = ISC_R_UNEXPECTED;
+
+ sock->magic = 0;
+ sock->references = 0;
+
+ sock->manager = manager;
+ sock->type = type;
+ sock->fd = -1;
+
+ ISC_LINK_INIT(sock, link);
+
+ sock->recvcmsgbuf = NULL;
+ sock->sendcmsgbuf = NULL;
+
+ /*
+ * set up cmsg buffers
+ */
+ cmsgbuflen = 0;
+#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
+ cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
+#endif
+#if defined(USE_CMSG) && defined(SO_TIMESTAMP)
+ cmsgbuflen += cmsg_space(sizeof(struct timeval));
+#endif
+ sock->recvcmsgbuflen = cmsgbuflen;
+ if (sock->recvcmsgbuflen != 0U) {
+ sock->recvcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
+ if (sock->recvcmsgbuf == NULL)
+ goto error;
+ }
+
+ cmsgbuflen = 0;
+#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIN6PKTINFO)
+ cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));
+#endif
+ sock->sendcmsgbuflen = cmsgbuflen;
+ if (sock->sendcmsgbuflen != 0U) {
+ sock->sendcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);
+ if (sock->sendcmsgbuf == NULL)
+ goto error;
+ }
+
+ /*
+ * set up list of readers and writers to be initially empty
+ */
+ ISC_LIST_INIT(sock->recv_list);
+ ISC_LIST_INIT(sock->send_list);
+ ISC_LIST_INIT(sock->accept_list);
+ sock->connect_ev = NULL;
+ sock->pending_recv = 0;
+ sock->pending_send = 0;
+ sock->pending_accept = 0;
+ sock->listener = 0;
+ sock->connected = 0;
+ sock->connecting = 0;
+ sock->bound = 0;
+
+ /*
+ * initialize the lock
+ */
+ result = isc_mutex_init(&sock->lock);
+ if (result != ISC_R_SUCCESS) {
+ sock->magic = 0;
+ goto error;
+ }
+
+ /*
+ * Initialize readable and writable events
+ */
+ ISC_EVENT_INIT(&sock->readable_ev, sizeof(intev_t),
+ ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTR,
+ NULL, sock, sock, NULL, NULL);
+ ISC_EVENT_INIT(&sock->writable_ev, sizeof(intev_t),
+ ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTW,
+ NULL, sock, sock, NULL, NULL);
+
+ sock->magic = SOCKET_MAGIC;
+ *socketp = sock;
+
+ return (ISC_R_SUCCESS);
+
+ error:
+ if (sock->recvcmsgbuf != NULL)
+ isc_mem_put(manager->mctx, sock->recvcmsgbuf,
+ sock->recvcmsgbuflen);
+ if (sock->sendcmsgbuf != NULL)
+ isc_mem_put(manager->mctx, sock->sendcmsgbuf,
+ sock->sendcmsgbuflen);
+ isc_mem_put(manager->mctx, sock, sizeof(*sock));
+
+ return (result);
+}
+
+/*
+ * This event requires that the various lists be empty, that the reference
+ * count be 1, and that the magic number is valid. The other socket bits,
+ * like the lock, must be initialized as well. The fd associated must be
+ * marked as closed, by setting it to -1 on close, or this routine will
+ * also close the socket.
+ */
+static void
+free_socket(isc_socket_t **socketp) {
+ isc_socket_t *sock = *socketp;
+
+ INSIST(sock->references == 0);
+ INSIST(VALID_SOCKET(sock));
+ INSIST(!sock->connecting);
+ INSIST(!sock->pending_recv);
+ INSIST(!sock->pending_send);
+ INSIST(!sock->pending_accept);
+ INSIST(ISC_LIST_EMPTY(sock->recv_list));
+ INSIST(ISC_LIST_EMPTY(sock->send_list));
+ INSIST(ISC_LIST_EMPTY(sock->accept_list));
+ INSIST(!ISC_LINK_LINKED(sock, link));
+
+ if (sock->recvcmsgbuf != NULL)
+ isc_mem_put(sock->manager->mctx, sock->recvcmsgbuf,
+ sock->recvcmsgbuflen);
+ if (sock->sendcmsgbuf != NULL)
+ isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf,
+ sock->sendcmsgbuflen);
+
+ sock->magic = 0;
+
+ DESTROYLOCK(&sock->lock);
+
+ isc_mem_put(sock->manager->mctx, sock, sizeof(*sock));
+
+ *socketp = NULL;
+}
+
+#ifdef SO_BSDCOMPAT
+/*
+ * This really should not be necessary to do. Having to workout
+ * which kernel version we are on at run time so that we don't cause
+ * the kernel to issue a warning about us using a deprecated socket option.
+ * Such warnings should *never* be on by default in production kernels.
+ *
+ * We can't do this a build time because executables are moved between
+ * machines and hence kernels.
+ *
+ * We can't just not set SO_BSDCOMAT because some kernels require it.
+ */
+
+static isc_once_t bsdcompat_once = ISC_ONCE_INIT;
+isc_boolean_t bsdcompat = ISC_TRUE;
+
+static void
+clear_bsdcompat(void) {
+#ifdef __linux__
+ struct utsname buf;
+ char *endp;
+ long int major;
+ long int minor;
+
+ uname(&buf); /* Can only fail if buf is bad in Linux. */
+
+ /* Paranoia in parsing can be increased, but we trust uname(). */
+ major = strtol(buf.release, &endp, 10);
+ if (*endp == '.') {
+ minor = strtol(endp+1, &endp, 10);
+ if ((major > 2) || ((major == 2) && (minor >= 4))) {
+ bsdcompat = ISC_FALSE;
+ }
+ }
+#endif /* __linux __ */
+}
+#endif
+
+static isc_result_t
+opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
+ char strbuf[ISC_STRERRORSIZE];
+ const char *err = "socket";
+ int tries = 0;
+#if defined(USE_CMSG) || defined(SO_BSDCOMPAT)
+ int on = 1;
+#endif
+#if defined(SO_RCVBUF)
+ ISC_SOCKADDR_LEN_T optlen;
+ int size;
+#endif
+
+ again:
+ switch (sock->type) {
+ case isc_sockettype_udp:
+ sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
+ break;
+ case isc_sockettype_tcp:
+ sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
+ break;
+ case isc_sockettype_unix:
+ sock->fd = socket(sock->pf, SOCK_STREAM, 0);
+ break;
+ case isc_sockettype_fdwatch:
+ /*
+ * We should not be called for isc_sockettype_fdwatch sockets.
+ */
+ INSIST(0);
+ break;
+ }
+ if (sock->fd == -1 && errno == EINTR && tries++ < 42)
+ goto again;
+
+#ifdef F_DUPFD
+ /*
+ * Leave a space for stdio and TCP to work in.
+ */
+ if (manager->reserved != 0 && sock->type == isc_sockettype_udp &&
+ sock->fd >= 0 && sock->fd < manager->reserved) {
+ int new, tmp;
+ new = fcntl(sock->fd, F_DUPFD, manager->reserved);
+ tmp = errno;
+ (void)close(sock->fd);
+ errno = tmp;
+ sock->fd = new;
+ err = "isc_socket_create: fcntl/reserved";
+ } else if (sock->fd >= 0 && sock->fd < 20) {
+ int new, tmp;
+ new = fcntl(sock->fd, F_DUPFD, 20);
+ tmp = errno;
+ (void)close(sock->fd);
+ errno = tmp;
+ sock->fd = new;
+ err = "isc_socket_create: fcntl";
+ }
+#endif
+
+ if (sock->fd >= (int)manager->maxsocks) {
+ (void)close(sock->fd);
+ isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_TOOMANYFDS,
+ "socket: file descriptor exceeds limit (%d/%u)",
+ sock->fd, manager->maxsocks);
+ return (ISC_R_NORESOURCES);
+ }
+
+ if (sock->fd < 0) {
+ switch (errno) {
+ case EMFILE:
+ case ENFILE:
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_TOOMANYFDS,
+ "%s: %s", err, strbuf);
+ /* fallthrough */
+ case ENOBUFS:
+ return (ISC_R_NORESOURCES);
+
+ case EPROTONOSUPPORT:
+ case EPFNOSUPPORT:
+ case EAFNOSUPPORT:
+ /*
+ * Linux 2.2 (and maybe others) return EINVAL instead of
+ * EAFNOSUPPORT.
+ */
+ case EINVAL:
+ return (ISC_R_FAMILYNOSUPPORT);
+
+ default:
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "%s() %s: %s", err,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+
+ if (make_nonblock(sock->fd) != ISC_R_SUCCESS) {
+ (void)close(sock->fd);
+ return (ISC_R_UNEXPECTED);
+ }
+
+#ifdef SO_BSDCOMPAT
+ RUNTIME_CHECK(isc_once_do(&bsdcompat_once,
+ clear_bsdcompat) == ISC_R_SUCCESS);
+ if (sock->type != isc_sockettype_unix && bsdcompat &&
+ setsockopt(sock->fd, SOL_SOCKET, SO_BSDCOMPAT,
+ (void *)&on, sizeof(on)) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, SO_BSDCOMPAT) %s: %s",
+ sock->fd,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ strbuf);
+ /* Press on... */
+ }
+#endif
+
+#ifdef SO_NOSIGPIPE
+ if (setsockopt(sock->fd, SOL_SOCKET, SO_NOSIGPIPE,
+ (void *)&on, sizeof(on)) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, SO_NOSIGPIPE) %s: %s",
+ sock->fd,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ strbuf);
+ /* Press on... */
+ }
+#endif
+
+#if defined(USE_CMSG) || defined(SO_RCVBUF)
+ if (sock->type == isc_sockettype_udp) {
+
+#if defined(USE_CMSG)
+#if defined(SO_TIMESTAMP)
+ if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP,
+ (void *)&on, sizeof(on)) < 0
+ && errno != ENOPROTOOPT) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, SO_TIMESTAMP) %s: %s",
+ sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ /* Press on... */
+ }
+#endif /* SO_TIMESTAMP */
+
+#if defined(ISC_PLATFORM_HAVEIPV6)
+ if (sock->pf == AF_INET6 && sock->recvcmsgbuflen == 0U) {
+ /*
+ * Warn explicitly because this anomaly can be hidden
+ * in usual operation (and unexpectedly appear later).
+ */
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "No buffer available to receive "
+ "IPv6 destination");
+ }
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+#ifdef IPV6_RECVPKTINFO
+ /* RFC 3542 */
+ if ((sock->pf == AF_INET6)
+ && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+ (void *)&on, sizeof(on)) < 0)) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_RECVPKTINFO) "
+ "%s: %s", sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
+#else
+ /* RFC 2292 */
+ if ((sock->pf == AF_INET6)
+ && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
+ (void *)&on, sizeof(on)) < 0)) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_PKTINFO) %s: %s",
+ sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
+#endif /* IPV6_RECVPKTINFO */
+#endif /* ISC_PLATFORM_HAVEIN6PKTINFO */
+#ifdef IPV6_USE_MIN_MTU /* RFC 3542, not too common yet*/
+ /* use minimum MTU */
+ if (sock->pf == AF_INET6) {
+ (void)setsockopt(sock->fd, IPPROTO_IPV6,
+ IPV6_USE_MIN_MTU,
+ (void *)&on, sizeof(on));
+ }
+#endif
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+#endif /* defined(USE_CMSG) */
+
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
+ /*
+ * Turn off Path MTU discovery on IPv4/UDP sockets.
+ */
+ if (sock->pf == AF_INET) {
+ int action = IP_PMTUDISC_DONT;
+ (void)setsockopt(sock->fd, IPPROTO_IP, IP_MTU_DISCOVER,
+ &action, sizeof(action));
+ }
+#endif
+#if defined(IP_DONTFRAG)
+ /*
+ * Turn off Path MTU discovery on IPv4/UDP sockets.
+ */
+ if (sock->pf == AF_INET) {
+ int off = 0;
+ (void)setsockopt(sock->fd, IPPROTO_IP, IP_DONTFRAG,
+ &off, sizeof(off));
+ }
+#endif
+
+#if defined(SO_RCVBUF)
+ optlen = sizeof(size);
+ if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+ (void *)&size, &optlen) >= 0 &&
+ size < RCVBUFSIZE) {
+ size = RCVBUFSIZE;
+ if (setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+ (void *)&size, sizeof(size)) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, SO_RCVBUF, %d) %s: %s",
+ sock->fd, size,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
+ }
+#endif
+ }
+#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Create a new 'type' socket managed by 'manager'. Events
+ * will be posted to 'task' and when dispatched 'action' will be
+ * 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_socket_t *sock = NULL;
+ isc_result_t result;
+ int lockid;
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+ REQUIRE(type != isc_sockettype_fdwatch);
+
+ result = allocate_socket(manager, type, &sock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ sock->pf = pf;
+ result = opensocket(manager, sock);
+ if (result != ISC_R_SUCCESS) {
+ free_socket(&sock);
+ return (result);
+ }
+
+ memset(sock->name, 0, sizeof(sock->name));
+ sock->tag = NULL;
+
+ sock->references = 1;
+ *socketp = sock;
+
+ /*
+ * Note we don't have to lock the socket like we normally would because
+ * there are no external references to it yet.
+ */
+
+ lockid = FDLOCK_ID(sock->fd);
+ LOCK(&manager->fdlock[lockid]);
+ manager->fds[sock->fd] = sock;
+ manager->fdstate[sock->fd] = MANAGED;
+#ifdef USE_DEVPOLL
+ INSIST(sock->manager->fdpollinfo[sock->fd].want_read == 0 &&
+ sock->manager->fdpollinfo[sock->fd].want_write == 0);
+#endif
+ UNLOCK(&manager->fdlock[lockid]);
+
+ LOCK(&manager->lock);
+ ISC_LIST_APPEND(manager->socklist, sock, link);
+#ifdef USE_SELECT
+ if (manager->maxfd < sock->fd)
+ manager->maxfd = sock->fd;
+#endif
+ UNLOCK(&manager->lock);
+
+ socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_CREATED, "created");
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socket_open(isc_socket_t *sock) {
+ isc_result_t result;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ REQUIRE(sock->references == 1);
+ REQUIRE(sock->type != isc_sockettype_fdwatch);
+ UNLOCK(&sock->lock);
+ /*
+ * We don't need to retain the lock hereafter, since no one else has
+ * this socket.
+ */
+ REQUIRE(sock->fd == -1);
+
+ result = opensocket(sock->manager, sock);
+ if (result != ISC_R_SUCCESS)
+ sock->fd = -1;
+
+ if (result == ISC_R_SUCCESS) {
+ int lockid = FDLOCK_ID(sock->fd);
+
+ LOCK(&sock->manager->fdlock[lockid]);
+ sock->manager->fds[sock->fd] = sock;
+ sock->manager->fdstate[sock->fd] = MANAGED;
+#ifdef USE_DEVPOLL
+ INSIST(sock->manager->fdpollinfo[sock->fd].want_read == 0 &&
+ sock->manager->fdpollinfo[sock->fd].want_write == 0);
+#endif
+ UNLOCK(&sock->manager->fdlock[lockid]);
+
+#ifdef USE_SELECT
+ LOCK(&sock->manager->lock);
+ if (sock->manager->maxfd < sock->fd)
+ sock->manager->maxfd = sock->fd;
+ UNLOCK(&sock->manager->lock);
+#endif
+ }
+
+ return (result);
+}
+
+/*
+ * Create a new 'type' socket managed by 'manager'. Events
+ * will be posted to 'task' and when dispatched 'action' will be
+ * 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_socket_t *sock = NULL;
+ isc_result_t result;
+ int lockid;
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+ result = allocate_socket(manager, isc_sockettype_fdwatch, &sock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ sock->fd = fd;
+ sock->fdwatcharg = cbarg;
+ sock->fdwatchcb = callback;
+ sock->fdwatchflags = flags;
+ sock->fdwatchtask = task;
+
+ sock->references = 1;
+ *socketp = sock;
+
+ /*
+ * Note we don't have to lock the socket like we normally would because
+ * there are no external references to it yet.
+ */
+
+ lockid = FDLOCK_ID(sock->fd);
+ LOCK(&manager->fdlock[lockid]);
+ manager->fds[sock->fd] = sock;
+ manager->fdstate[sock->fd] = MANAGED;
+ UNLOCK(&manager->fdlock[lockid]);
+
+ LOCK(&manager->lock);
+ ISC_LIST_APPEND(manager->socklist, sock, link);
+#ifdef USE_SELECT
+ if (manager->maxfd < sock->fd)
+ manager->maxfd = sock->fd;
+#endif
+ UNLOCK(&manager->lock);
+
+ if (flags & ISC_SOCKFDWATCH_READ)
+ select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
+ if (flags & ISC_SOCKFDWATCH_WRITE)
+ select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
+
+ socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_CREATED, "fdwatch-created");
+
+ 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) {
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+ LOCK(&sock->lock);
+ sock->references++;
+ UNLOCK(&sock->lock);
+
+ *socketp = 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_boolean_t kill_socket = ISC_FALSE;
+
+ REQUIRE(socketp != NULL);
+ sock = *socketp;
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ REQUIRE(sock->references > 0);
+ sock->references--;
+ if (sock->references == 0)
+ kill_socket = ISC_TRUE;
+ UNLOCK(&sock->lock);
+
+ if (kill_socket)
+ destroy(&sock);
+
+ *socketp = NULL;
+}
+
+isc_result_t
+isc_socket_close(isc_socket_t *sock) {
+ int fd;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ REQUIRE(sock->references == 1);
+ REQUIRE(sock->type != isc_sockettype_fdwatch);
+ UNLOCK(&sock->lock);
+ /*
+ * We don't need to retain the lock hereafter, since no one else has
+ * this socket.
+ */
+
+ REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks);
+
+ INSIST(!sock->connecting);
+ INSIST(!sock->pending_recv);
+ INSIST(!sock->pending_send);
+ INSIST(!sock->pending_accept);
+ INSIST(ISC_LIST_EMPTY(sock->recv_list));
+ INSIST(ISC_LIST_EMPTY(sock->send_list));
+ INSIST(ISC_LIST_EMPTY(sock->accept_list));
+ INSIST(sock->connect_ev == NULL);
+
+ fd = sock->fd;
+ sock->fd = -1;
+ sock->listener = 0;
+ sock->connected = 0;
+ sock->connecting = 0;
+ sock->bound = 0;
+ isc_sockaddr_any(&sock->peer_address);
+
+ closesocket(sock->manager, sock->type, fd);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * I/O is possible on a given socket. Schedule an event to this task that
+ * will call an internal function to do the I/O. This will charge the
+ * task with the I/O operation and let our select loop handler get back
+ * to doing something real as fast as possible.
+ *
+ * The socket and manager must be locked before calling this function.
+ */
+static void
+dispatch_recv(isc_socket_t *sock) {
+ intev_t *iev;
+ isc_socketevent_t *ev;
+ isc_task_t *sender;
+
+ INSIST(!sock->pending_recv);
+
+ if (sock->type != isc_sockettype_fdwatch) {
+ ev = ISC_LIST_HEAD(sock->recv_list);
+ if (ev == NULL)
+ return;
+ socket_log(sock, NULL, EVENT, NULL, 0, 0,
+ "dispatch_recv: event %p -> task %p",
+ ev, ev->ev_sender);
+ sender = ev->ev_sender;
+ } else {
+ sender = sock->fdwatchtask;
+ }
+
+ sock->pending_recv = 1;
+ iev = &sock->readable_ev;
+
+ sock->references++;
+ iev->ev_sender = sock;
+ if (sock->type == isc_sockettype_fdwatch)
+ iev->ev_action = internal_fdwatch_read;
+ else
+ iev->ev_action = internal_recv;
+ iev->ev_arg = sock;
+
+ isc_task_send(sender, (isc_event_t **)&iev);
+}
+
+static void
+dispatch_send(isc_socket_t *sock) {
+ intev_t *iev;
+ isc_socketevent_t *ev;
+ isc_task_t *sender;
+
+ INSIST(!sock->pending_send);
+
+ if (sock->type != isc_sockettype_fdwatch) {
+ ev = ISC_LIST_HEAD(sock->send_list);
+ if (ev == NULL)
+ return;
+ socket_log(sock, NULL, EVENT, NULL, 0, 0,
+ "dispatch_send: event %p -> task %p",
+ ev, ev->ev_sender);
+ sender = ev->ev_sender;
+ } else {
+ sender = sock->fdwatchtask;
+ }
+
+ sock->pending_send = 1;
+ iev = &sock->writable_ev;
+
+ sock->references++;
+ iev->ev_sender = sock;
+ if (sock->type == isc_sockettype_fdwatch)
+ iev->ev_action = internal_fdwatch_write;
+ else
+ iev->ev_action = internal_send;
+ iev->ev_arg = sock;
+
+ isc_task_send(sender, (isc_event_t **)&iev);
+}
+
+/*
+ * Dispatch an internal accept event.
+ */
+static void
+dispatch_accept(isc_socket_t *sock) {
+ intev_t *iev;
+ isc_socket_newconnev_t *ev;
+
+ INSIST(!sock->pending_accept);
+
+ /*
+ * Are there any done events left, or were they all canceled
+ * before the manager got the socket lock?
+ */
+ ev = ISC_LIST_HEAD(sock->accept_list);
+ if (ev == NULL)
+ return;
+
+ sock->pending_accept = 1;
+ iev = &sock->readable_ev;
+
+ sock->references++; /* keep socket around for this internal event */
+ iev->ev_sender = sock;
+ iev->ev_action = internal_accept;
+ iev->ev_arg = sock;
+
+ isc_task_send(ev->ev_sender, (isc_event_t **)&iev);
+}
+
+static void
+dispatch_connect(isc_socket_t *sock) {
+ intev_t *iev;
+ isc_socket_connev_t *ev;
+
+ iev = &sock->writable_ev;
+
+ ev = sock->connect_ev;
+ INSIST(ev != NULL); /* XXX */
+
+ INSIST(sock->connecting);
+
+ sock->references++; /* keep socket around for this internal event */
+ iev->ev_sender = sock;
+ iev->ev_action = internal_connect;
+ iev->ev_arg = sock;
+
+ isc_task_send(ev->ev_sender, (isc_event_t **)&iev);
+}
+
+/*
+ * Dequeue an item off the given socket's read queue, set the result code
+ * in the done event to the one provided, and send it to the task it was
+ * destined for.
+ *
+ * If the event to be sent is on a list, remove it before sending. If
+ * asked to, send and detach from the socket as well.
+ *
+ * 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) {
+ isc_task_t *task;
+
+ task = (*dev)->ev_sender;
+
+ (*dev)->ev_sender = sock;
+
+ if (ISC_LINK_LINKED(*dev, ev_link))
+ ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link);
+
+ if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
+ == ISC_SOCKEVENTATTR_ATTACHED)
+ isc_task_sendanddetach(&task, (isc_event_t **)dev);
+ else
+ isc_task_send(task, (isc_event_t **)dev);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ *
+ * 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) {
+ isc_task_t *task;
+
+ INSIST(dev != NULL && *dev != NULL);
+
+ task = (*dev)->ev_sender;
+ (*dev)->ev_sender = sock;
+
+ if (ISC_LINK_LINKED(*dev, ev_link))
+ ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link);
+
+ if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
+ == ISC_SOCKEVENTATTR_ATTACHED)
+ isc_task_sendanddetach(&task, (isc_event_t **)dev);
+ else
+ isc_task_send(task, (isc_event_t **)dev);
+}
+
+/*
+ * Call accept() on a socket, to get the new file descriptor. The listen
+ * socket is used as a prototype to create a new isc_socket_t. The new
+ * socket has one outstanding reference. The task receiving the event
+ * will be detached from just after the event is delivered.
+ *
+ * On entry to this function, the event delivered is the internal
+ * readable event, and the first item on the accept_list should be
+ * the done event we want to send. If the list is empty, this is a no-op,
+ * so just unlock and return.
+ */
+static void
+internal_accept(isc_task_t *me, isc_event_t *ev) {
+ isc_socket_t *sock;
+ isc_socketmgr_t *manager;
+ isc_socket_newconnev_t *dev;
+ isc_task_t *task;
+ ISC_SOCKADDR_LEN_T addrlen;
+ int fd;
+ isc_result_t result = ISC_R_SUCCESS;
+ char strbuf[ISC_STRERRORSIZE];
+ const char *err = "accept";
+
+ UNUSED(me);
+
+ sock = ev->ev_sender;
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ socket_log(sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "internal_accept called, locked socket");
+
+ manager = sock->manager;
+ INSIST(VALID_MANAGER(manager));
+
+ INSIST(sock->listener);
+ INSIST(sock->pending_accept == 1);
+ sock->pending_accept = 0;
+
+ INSIST(sock->references > 0);
+ sock->references--; /* the internal event is done with this socket */
+ if (sock->references == 0) {
+ UNLOCK(&sock->lock);
+ destroy(&sock);
+ return;
+ }
+
+ /*
+ * Get the first item off the accept list.
+ * If it is empty, unlock the socket and return.
+ */
+ dev = ISC_LIST_HEAD(sock->accept_list);
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return;
+ }
+
+ /*
+ * Try to accept the new connection. If the accept fails with
+ * EAGAIN or EINTR, simply poke the watcher to watch this socket
+ * again. Also ignore ECONNRESET, which has been reported to
+ * be spuriously returned on Linux 2.2.19 although it is not
+ * a documented error for accept(). ECONNABORTED has been
+ * reported for Solaris 8. The rest are thrown in not because
+ * we have seen them but because they are ignored by other
+ * deamons 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,
+ (void *)&addrlen);
+
+#ifdef F_DUPFD
+ /*
+ * Leave a space for stdio to work in.
+ */
+ if (fd >= 0 && fd < 20) {
+ int new, tmp;
+ new = fcntl(fd, F_DUPFD, 20);
+ tmp = errno;
+ (void)close(fd);
+ errno = tmp;
+ fd = new;
+ err = "accept/fcntl";
+ }
+#endif
+
+ if (fd < 0) {
+ if (SOFT_ERROR(errno))
+ goto soft_error;
+ switch (errno) {
+ case ENFILE:
+ case EMFILE:
+ isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_TOOMANYFDS,
+ "%s: too many open file descriptors",
+ err);
+ goto soft_error;
+
+ case ENOBUFS:
+ case ENOMEM:
+ case ECONNRESET:
+ case ECONNABORTED:
+ case EHOSTUNREACH:
+ case EHOSTDOWN:
+ case ENETUNREACH:
+ case ENETDOWN:
+ case ECONNREFUSED:
+#ifdef EPROTO
+ case EPROTO:
+#endif
+#ifdef ENONET
+ case ENONET:
+#endif
+ goto soft_error;
+ default:
+ break;
+ }
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "internal_accept: %s() %s: %s", err,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ fd = -1;
+ result = ISC_R_UNEXPECTED;
+ } else {
+ if (addrlen == 0U) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "internal_accept(): "
+ "accept() failed to return "
+ "remote address");
+
+ (void)close(fd);
+ goto soft_error;
+ } else if (dev->newsocket->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.
+ type.sa.sa_family,
+ sock->pf);
+ (void)close(fd);
+ goto soft_error;
+ } else if (fd >= (int)manager->maxsocks) {
+ isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_TOOMANYFDS,
+ "accept: "
+ "file descriptor exceeds limit (%d/%u)",
+ fd, manager->maxsocks);
+ (void)close(fd);
+ goto soft_error;
+ }
+ }
+
+ if (fd != -1) {
+ dev->newsocket->peer_address.length = addrlen;
+ dev->newsocket->pf = sock->pf;
+ }
+
+ /*
+ * Pull off the done event.
+ */
+ ISC_LIST_UNLINK(sock->accept_list, dev, ev_link);
+
+ /*
+ * Poke watcher if there are more pending accepts.
+ */
+ if (!ISC_LIST_EMPTY(sock->accept_list))
+ select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT);
+
+ UNLOCK(&sock->lock);
+
+ if (fd != -1 && (make_nonblock(fd) != ISC_R_SUCCESS)) {
+ (void)close(fd);
+ fd = -1;
+ result = ISC_R_UNEXPECTED;
+ }
+
+ /*
+ * -1 means the new socket didn't happen.
+ */
+ if (fd != -1) {
+ int lockid = FDLOCK_ID(fd);
+
+ LOCK(&manager->fdlock[lockid]);
+ manager->fds[fd] = dev->newsocket;
+ manager->fdstate[fd] = MANAGED;
+ UNLOCK(&manager->fdlock[lockid]);
+
+ LOCK(&manager->lock);
+ ISC_LIST_APPEND(manager->socklist, dev->newsocket, link);
+
+ dev->newsocket->fd = fd;
+ dev->newsocket->bound = 1;
+ dev->newsocket->connected = 1;
+
+ /*
+ * Save away the remote address
+ */
+ dev->address = dev->newsocket->peer_address;
+
+#ifdef USE_SELECT
+ if (manager->maxfd < fd)
+ manager->maxfd = fd;
+#endif
+
+ socket_log(sock, &dev->newsocket->peer_address, CREATION,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
+ "accepted connection, new socket %p",
+ dev->newsocket);
+
+ UNLOCK(&manager->lock);
+ } else {
+ dev->newsocket->references--;
+ free_socket(&dev->newsocket);
+ }
+
+ /*
+ * Fill in the done event details and send it off.
+ */
+ dev->result = result;
+ task = dev->ev_sender;
+ dev->ev_sender = sock;
+
+ isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
+ return;
+
+ soft_error:
+ select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT);
+ UNLOCK(&sock->lock);
+ return;
+}
+
+static void
+internal_recv(isc_task_t *me, isc_event_t *ev) {
+ isc_socketevent_t *dev;
+ isc_socket_t *sock;
+
+ INSIST(ev->ev_type == ISC_SOCKEVENT_INTR);
+
+ sock = ev->ev_sender;
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ socket_log(sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
+ "internal_recv: task %p got event %p", me, ev);
+
+ INSIST(sock->pending_recv == 1);
+ sock->pending_recv = 0;
+
+ INSIST(sock->references > 0);
+ sock->references--; /* the internal event is done with this socket */
+ if (sock->references == 0) {
+ UNLOCK(&sock->lock);
+ destroy(&sock);
+ return;
+ }
+
+ /*
+ * Try to do as much I/O as possible on this socket. There are no
+ * limits here, currently.
+ */
+ dev = ISC_LIST_HEAD(sock->recv_list);
+ while (dev != NULL) {
+ switch (doio_recv(sock, dev)) {
+ case DOIO_SOFT:
+ goto poke;
+
+ case DOIO_EOF:
+ /*
+ * read of 0 means the remote end was closed.
+ * Run through the event queue and dispatch all
+ * the events with an EOF result code.
+ */
+ do {
+ dev->result = ISC_R_EOF;
+ send_recvdone_event(sock, &dev);
+ dev = ISC_LIST_HEAD(sock->recv_list);
+ } while (dev != NULL);
+ goto poke;
+
+ case DOIO_SUCCESS:
+ case DOIO_HARD:
+ send_recvdone_event(sock, &dev);
+ break;
+ }
+
+ dev = ISC_LIST_HEAD(sock->recv_list);
+ }
+
+ poke:
+ if (!ISC_LIST_EMPTY(sock->recv_list))
+ select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
+
+ UNLOCK(&sock->lock);
+}
+
+static void
+internal_send(isc_task_t *me, isc_event_t *ev) {
+ isc_socketevent_t *dev;
+ 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;
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ socket_log(sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
+ "internal_send: task %p got event %p", me, ev);
+
+ INSIST(sock->pending_send == 1);
+ sock->pending_send = 0;
+
+ INSIST(sock->references > 0);
+ sock->references--; /* the internal event is done with this socket */
+ if (sock->references == 0) {
+ UNLOCK(&sock->lock);
+ destroy(&sock);
+ return;
+ }
+
+ /*
+ * Try to do as much I/O as possible on this socket. There are no
+ * limits here, currently.
+ */
+ dev = ISC_LIST_HEAD(sock->send_list);
+ while (dev != NULL) {
+ switch (doio_send(sock, dev)) {
+ case DOIO_SOFT:
+ goto poke;
+
+ case DOIO_HARD:
+ case DOIO_SUCCESS:
+ send_senddone_event(sock, &dev);
+ break;
+ }
+
+ dev = ISC_LIST_HEAD(sock->send_list);
+ }
+
+ poke:
+ if (!ISC_LIST_EMPTY(sock->send_list))
+ select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
+
+ UNLOCK(&sock->lock);
+}
+
+static void
+internal_fdwatch_write(isc_task_t *me, isc_event_t *ev) {
+ isc_socket_t *sock;
+ int more_data;
+
+ INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);
+
+ /*
+ * Find out what socket this is and lock it.
+ */
+ sock = (isc_socket_t *)ev->ev_sender;
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ socket_log(sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
+ "internal_fdwatch_write: task %p got event %p", me, ev);
+
+ INSIST(sock->pending_send == 1);
+
+ UNLOCK(&sock->lock);
+ more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg);
+ LOCK(&sock->lock);
+
+ sock->pending_send = 0;
+
+ INSIST(sock->references > 0);
+ sock->references--; /* the internal event is done with this socket */
+ if (sock->references == 0) {
+ UNLOCK(&sock->lock);
+ destroy(&sock);
+ return;
+ }
+
+ if (more_data)
+ select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);
+
+ UNLOCK(&sock->lock);
+}
+
+static void
+internal_fdwatch_read(isc_task_t *me, isc_event_t *ev) {
+ isc_socket_t *sock;
+ int more_data;
+
+ INSIST(ev->ev_type == ISC_SOCKEVENT_INTR);
+
+ /*
+ * Find out what socket this is and lock it.
+ */
+ sock = (isc_socket_t *)ev->ev_sender;
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ socket_log(sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
+ "internal_fdwatch_read: task %p got event %p", me, ev);
+
+ INSIST(sock->pending_recv == 1);
+
+ UNLOCK(&sock->lock);
+ more_data = (sock->fdwatchcb)(me, sock, sock->fdwatcharg);
+ LOCK(&sock->lock);
+
+ sock->pending_recv = 0;
+
+ INSIST(sock->references > 0);
+ sock->references--; /* the internal event is done with this socket */
+ if (sock->references == 0) {
+ UNLOCK(&sock->lock);
+ destroy(&sock);
+ return;
+ }
+
+ if (more_data)
+ select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
+
+ UNLOCK(&sock->lock);
+}
+
+/*
+ * Process read/writes on each fd here. Avoid locking
+ * and unlocking twice if both reads and writes are possible.
+ */
+static void
+process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable,
+ isc_boolean_t writeable)
+{
+ isc_socket_t *sock;
+ isc_boolean_t unlock_sock;
+ int lockid = FDLOCK_ID(fd);
+
+ /*
+ * If the socket is going to be closed, don't do more I/O.
+ */
+ LOCK(&manager->fdlock[lockid]);
+ if (manager->fdstate[fd] == CLOSE_PENDING) {
+ UNLOCK(&manager->fdlock[lockid]);
+
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ return;
+ }
+
+ sock = manager->fds[fd];
+ UNLOCK(&manager->fdlock[lockid]);
+ unlock_sock = ISC_FALSE;
+ if (readable) {
+ if (sock == NULL) {
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ goto check_write;
+ }
+ unlock_sock = ISC_TRUE;
+ LOCK(&sock->lock);
+ if (!SOCK_DEAD(sock)) {
+ if (sock->listener)
+ dispatch_accept(sock);
+ else
+ dispatch_recv(sock);
+ }
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ }
+check_write:
+ if (writeable) {
+ if (sock == NULL) {
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ return;
+ }
+ if (!unlock_sock) {
+ unlock_sock = ISC_TRUE;
+ LOCK(&sock->lock);
+ }
+ if (!SOCK_DEAD(sock)) {
+ if (sock->connecting)
+ dispatch_connect(sock);
+ else
+ dispatch_send(sock);
+ }
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ }
+ if (unlock_sock)
+ UNLOCK(&sock->lock);
+}
+
+#ifdef USE_KQUEUE
+static isc_boolean_t
+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
+ isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
+
+ if (nevents == manager->nevents) {
+ /*
+ * This is not an error, but something unexpected. If this
+ * happens, it may indicate the need for increasing
+ * ISC_SOCKET_MAXEVENTS.
+ */
+ manager_log(manager, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_INFO,
+ "maximum number of FD events (%d) received",
+ nevents);
+ }
+
+ for (i = 0; i < nevents; i++) {
+ REQUIRE(events[i].ident < manager->maxsocks);
+#ifdef ISC_PLATFORM_USETHREADS
+ if (events[i].ident == (uintptr_t)manager->pipe_fds[0]) {
+ have_ctlevent = ISC_TRUE;
+ continue;
+ }
+#endif
+ readable = ISC_TF(events[i].filter == EVFILT_READ);
+ writable = ISC_TF(events[i].filter == EVFILT_WRITE);
+ process_fd(manager, events[i].ident, readable, writable);
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+ if (have_ctlevent)
+ done = process_ctlfd(manager);
+#endif
+
+ return (done);
+}
+#elif defined(USE_EPOLL)
+static isc_boolean_t
+process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
+ int i;
+ isc_boolean_t done = ISC_FALSE;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
+
+ if (nevents == manager->nevents) {
+ manager_log(manager, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_INFO,
+ "maximum number of FD events (%d) received",
+ nevents);
+ }
+
+ for (i = 0; i < nevents; i++) {
+ REQUIRE(events[i].data.fd < (int)manager->maxsocks);
+#ifdef ISC_PLATFORM_USETHREADS
+ if (events[i].data.fd == manager->pipe_fds[0]) {
+ have_ctlevent = ISC_TRUE;
+ continue;
+ }
+#endif
+ if ((events[i].events & EPOLLERR) != 0 ||
+ (events[i].events & EPOLLHUP) != 0) {
+ /*
+ * epoll does not set IN/OUT bits on an erroneous
+ * condition, so we need to try both anyway. This is a
+ * bit inefficient, but should be okay for such rare
+ * events. Note also that the read or write attempt
+ * won't block because we use non-blocking sockets.
+ */
+ events[i].events |= (EPOLLIN | EPOLLOUT);
+ }
+ process_fd(manager, events[i].data.fd,
+ (events[i].events & EPOLLIN) != 0,
+ (events[i].events & EPOLLOUT) != 0);
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+ if (have_ctlevent)
+ done = process_ctlfd(manager);
+#endif
+
+ return (done);
+}
+#elif defined(USE_DEVPOLL)
+static isc_boolean_t
+process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
+ int i;
+ isc_boolean_t done = ISC_FALSE;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
+
+ if (nevents == manager->nevents) {
+ manager_log(manager, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_INFO,
+ "maximum number of FD events (%d) received",
+ nevents);
+ }
+
+ for (i = 0; i < nevents; i++) {
+ REQUIRE(events[i].fd < (int)manager->maxsocks);
+#ifdef ISC_PLATFORM_USETHREADS
+ if (events[i].fd == manager->pipe_fds[0]) {
+ have_ctlevent = ISC_TRUE;
+ continue;
+ }
+#endif
+ process_fd(manager, events[i].fd,
+ (events[i].events & POLLIN) != 0,
+ (events[i].events & POLLOUT) != 0);
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+ if (have_ctlevent)
+ done = process_ctlfd(manager);
+#endif
+
+ return (done);
+}
+#elif defined(USE_SELECT)
+static void
+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
+ if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1])
+ continue;
+#endif /* ISC_PLATFORM_USETHREADS */
+ process_fd(manager, i, FD_ISSET(i, readfds),
+ FD_ISSET(i, writefds));
+ }
+}
+#endif
+
+#ifdef ISC_PLATFORM_USETHREADS
+static isc_boolean_t
+process_ctlfd(isc_socketmgr_t *manager) {
+ int msg, fd;
+
+ for (;;) {
+ select_readmsg(manager, &fd, &msg);
+
+ manager_log(manager, IOEVENT,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_WATCHERMSG,
+ "watcher got message %d "
+ "for socket %d"), msg, fd);
+
+ /*
+ * Nothing to read?
+ */
+ if (msg == SELECT_POKE_NOTHING)
+ break;
+
+ /*
+ * Handle shutdown message. We really should
+ * jump out of this loop right away, but
+ * it doesn't matter if we have to do a little
+ * more work first.
+ */
+ if (msg == SELECT_POKE_SHUTDOWN)
+ return (ISC_TRUE);
+
+ /*
+ * This is a wakeup on a socket. Look
+ * at the event queue for both read and write,
+ * and decide if we need to watch on it now
+ * or not.
+ */
+ wakeup_socket(manager, fd, msg);
+ }
+
+ return (ISC_FALSE);
+}
+
+/*
+ * This is the thread that will loop forever, always in a select or poll
+ * call.
+ *
+ * When select returns something to do, track down what thread gets to do
+ * this I/O and post the event to it.
+ */
+static isc_threadresult_t
+watcher(void *uap) {
+ isc_socketmgr_t *manager = uap;
+ isc_boolean_t done;
+ int ctlfd;
+ int cc;
+#ifdef USE_KQUEUE
+ const char *fnname = "kevent()";
+#elif defined (USE_EPOLL)
+ const char *fnname = "epoll_wait()";
+#elif defined(USE_DEVPOLL)
+ const char *fnname = "ioctl(DP_POLL)";
+ struct dvpoll dvp;
+#elif defined (USE_SELECT)
+ const char *fnname = "select()";
+ int maxfd;
+#endif
+ char strbuf[ISC_STRERRORSIZE];
+#ifdef ISC_SOCKET_USE_POLLWATCH
+ pollstate_t pollstate = poll_idle;
+#endif
+
+ /*
+ * Get the control fd here. This will never change.
+ */
+ ctlfd = manager->pipe_fds[0];
+ done = ISC_FALSE;
+ while (!done) {
+ do {
+#ifdef USE_KQUEUE
+ cc = kevent(manager->kqueue_fd, NULL, 0,
+ manager->events, manager->nevents, NULL);
+#elif defined(USE_EPOLL)
+ cc = epoll_wait(manager->epoll_fd, manager->events,
+ manager->nevents, -1);
+#elif defined(USE_DEVPOLL)
+ dvp.dp_fds = manager->events;
+ dvp.dp_nfds = manager->nevents;
+#ifndef ISC_SOCKET_USE_POLLWATCH
+ dvp.dp_timeout = -1;
+#else
+ if (pollstate == poll_idle)
+ dvp.dp_timeout = -1;
+ else
+ dvp.dp_timeout = ISC_SOCKET_POLLWATCH_TIMEOUT;
+#endif /* ISC_SOCKET_USE_POLLWATCH */
+ cc = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
+#elif defined(USE_SELECT)
+ LOCK(&manager->lock);
+ memcpy(manager->read_fds_copy, manager->read_fds,
+ manager->fd_bufsize);
+ memcpy(manager->write_fds_copy, manager->write_fds,
+ manager->fd_bufsize);
+ maxfd = manager->maxfd + 1;
+ UNLOCK(&manager->lock);
+
+ cc = select(maxfd, manager->read_fds_copy,
+ manager->write_fds_copy, NULL, NULL);
+#endif /* USE_KQUEUE */
+
+ if (cc < 0 && !SOFT_ERROR(errno)) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ "%s %s: %s", fnname,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"), strbuf);
+ }
+
+#if defined(USE_DEVPOLL) && defined(ISC_SOCKET_USE_POLLWATCH)
+ if (cc == 0) {
+ if (pollstate == poll_active)
+ pollstate = poll_checking;
+ else if (pollstate == poll_checking)
+ pollstate = poll_idle;
+ } else if (cc > 0) {
+ if (pollstate == poll_checking) {
+ /*
+ * XXX: We'd like to use a more
+ * verbose log level as it's actually an
+ * unexpected event, but the kernel bug
+ * reportedly happens pretty frequently
+ * (and it can also be a false positive)
+ * so it would be just too noisy.
+ */
+ manager_log(manager,
+ ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET,
+ ISC_LOG_DEBUG(1),
+ "unexpected POLL timeout");
+ }
+ pollstate = poll_active;
+ }
+#endif
+ } while (cc < 0);
+
+#if defined(USE_KQUEUE) || defined (USE_EPOLL) || defined (USE_DEVPOLL)
+ done = process_fds(manager, manager->events, cc);
+#elif defined(USE_SELECT)
+ process_fds(manager, maxfd, manager->read_fds_copy,
+ manager->write_fds_copy);
+
+ /*
+ * Process reads on internal, control fd.
+ */
+ if (FD_ISSET(ctlfd, manager->read_fds_copy))
+ done = process_ctlfd(manager);
+#endif
+ }
+
+ manager_log(manager, TRACE,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_EXITING, "watcher exiting"));
+
+ return ((isc_threadresult_t)0);
+}
+#endif /* ISC_PLATFORM_USETHREADS */
+
+void
+isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
+
+ REQUIRE(VALID_MANAGER(manager));
+
+ manager->reserved = reserved;
+}
+
+/*
+ * Create a new socket manager.
+ */
+
+static isc_result_t
+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];
+#endif
+
+#ifdef USE_KQUEUE
+ manager->nevents = ISC_SOCKET_MAXEVENTS;
+ manager->events = isc_mem_get(mctx, sizeof(struct kevent) *
+ manager->nevents);
+ if (manager->events == NULL)
+ return (ISC_R_NOMEMORY);
+ manager->kqueue_fd = kqueue();
+ if (manager->kqueue_fd == -1) {
+ result = isc__errno2result(errno);
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "kqueue %s: %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ strbuf);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct kevent) * manager->nevents);
+ return (result);
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+ result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+ if (result != ISC_R_SUCCESS) {
+ close(manager->kqueue_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct kevent) * manager->nevents);
+ return (result);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+#elif defined(USE_EPOLL)
+ manager->nevents = ISC_SOCKET_MAXEVENTS;
+ manager->events = isc_mem_get(mctx, sizeof(struct epoll_event) *
+ manager->nevents);
+ if (manager->events == NULL)
+ return (ISC_R_NOMEMORY);
+ manager->epoll_fd = epoll_create(manager->nevents);
+ if (manager->epoll_fd == -1) {
+ result = isc__errno2result(errno);
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "epoll_create %s: %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ strbuf);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct epoll_event) * manager->nevents);
+ return (result);
+ }
+#ifdef ISC_PLATFORM_USETHREADS
+ result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+ if (result != ISC_R_SUCCESS) {
+ close(manager->epoll_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct epoll_event) * manager->nevents);
+ return (result);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+#elif defined(USE_DEVPOLL)
+ /*
+ * XXXJT: /dev/poll seems to reject large numbers of events,
+ * so we should be careful about redefining ISC_SOCKET_MAXEVENTS.
+ */
+ manager->nevents = ISC_SOCKET_MAXEVENTS;
+ manager->events = isc_mem_get(mctx, sizeof(struct pollfd) *
+ manager->nevents);
+ if (manager->events == NULL)
+ return (ISC_R_NOMEMORY);
+ /*
+ * Note: fdpollinfo should be able to support all possible FDs, so
+ * it must have maxsocks entries (not nevents).
+ */
+ manager->fdpollinfo = isc_mem_get(mctx, sizeof(pollinfo_t) *
+ manager->maxsocks);
+ if (manager->fdpollinfo == NULL) {
+ isc_mem_put(mctx, manager->events,
+ sizeof(pollinfo_t) * manager->maxsocks);
+ return (ISC_R_NOMEMORY);
+ }
+ memset(manager->fdpollinfo, 0, sizeof(pollinfo_t) * manager->maxsocks);
+ manager->devpoll_fd = open("/dev/poll", O_RDWR);
+ if (manager->devpoll_fd == -1) {
+ result = isc__errno2result(errno);
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "open(/dev/poll) %s: %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ strbuf);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct pollfd) * manager->nevents);
+ isc_mem_put(mctx, manager->fdpollinfo,
+ sizeof(pollinfo_t) * manager->maxsocks);
+ return (result);
+ }
+#ifdef ISC_PLATFORM_USETHREADS
+ result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+ if (result != ISC_R_SUCCESS) {
+ close(manager->devpoll_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct pollfd) * manager->nevents);
+ isc_mem_put(mctx, manager->fdpollinfo,
+ sizeof(pollinfo_t) * manager->maxsocks);
+ return (result);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+#elif defined(USE_SELECT)
+ UNUSED(result);
+
+#if ISC_SOCKET_MAXSOCKETS > FD_SETSIZE
+ /*
+ * Note: this code should also cover the case of MAXSOCKETS <=
+ * FD_SETSIZE, but we separate the cases to avoid possible portability
+ * issues regarding howmany() and the actual representation of fd_set.
+ */
+ manager->fd_bufsize = howmany(manager->maxsocks, NFDBITS) *
+ sizeof(fd_mask);
+#else
+ manager->fd_bufsize = sizeof(fd_set);
+#endif
+
+ manager->read_fds = NULL;
+ manager->read_fds_copy = NULL;
+ manager->write_fds = NULL;
+ manager->write_fds_copy = NULL;
+
+ manager->read_fds = isc_mem_get(mctx, manager->fd_bufsize);
+ if (manager->read_fds != NULL)
+ manager->read_fds_copy = isc_mem_get(mctx, manager->fd_bufsize);
+ if (manager->read_fds_copy != NULL)
+ manager->write_fds = isc_mem_get(mctx, manager->fd_bufsize);
+ if (manager->write_fds != NULL) {
+ manager->write_fds_copy = isc_mem_get(mctx,
+ manager->fd_bufsize);
+ }
+ if (manager->write_fds_copy == NULL) {
+ if (manager->write_fds != NULL) {
+ isc_mem_put(mctx, manager->write_fds,
+ manager->fd_bufsize);
+ }
+ if (manager->read_fds_copy != NULL) {
+ isc_mem_put(mctx, manager->read_fds_copy,
+ manager->fd_bufsize);
+ }
+ if (manager->read_fds != NULL) {
+ isc_mem_put(mctx, manager->read_fds,
+ manager->fd_bufsize);
+ }
+ return (ISC_R_NOMEMORY);
+ }
+ memset(manager->read_fds, 0, manager->fd_bufsize);
+ memset(manager->write_fds, 0, manager->fd_bufsize);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ (void)watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+ manager->maxfd = manager->pipe_fds[0];
+#else /* ISC_PLATFORM_USETHREADS */
+ manager->maxfd = 0;
+#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_KQUEUE */
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_result_t result;
+
+ result = unwatch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "epoll_ctl(DEL) %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#ifdef USE_KQUEUE
+ close(manager->kqueue_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct kevent) * manager->nevents);
+#elif defined(USE_EPOLL)
+ close(manager->epoll_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct epoll_event) * manager->nevents);
+#elif defined(USE_DEVPOLL)
+ close(manager->devpoll_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct pollfd) * manager->nevents);
+ isc_mem_put(mctx, manager->fdpollinfo,
+ sizeof(pollinfo_t) * manager->maxsocks);
+#elif defined(USE_SELECT)
+ if (manager->read_fds != NULL)
+ isc_mem_put(mctx, manager->read_fds, manager->fd_bufsize);
+ if (manager->read_fds_copy != NULL)
+ isc_mem_put(mctx, manager->read_fds_copy, manager->fd_bufsize);
+ if (manager->write_fds != NULL)
+ isc_mem_put(mctx, manager->write_fds, manager->fd_bufsize);
+ if (manager->write_fds_copy != NULL)
+ isc_mem_put(mctx, manager->write_fds_copy, manager->fd_bufsize);
+#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_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
+ char strbuf[ISC_STRERRORSIZE];
+#endif
+ isc_result_t result;
+
+ REQUIRE(managerp != NULL && *managerp == NULL);
+
+#ifndef ISC_PLATFORM_USETHREADS
+ if (socketmgr != NULL) {
+ /* Don't allow maxsocks to be updated */
+ if (maxsocks > 0 && socketmgr->maxsocks != maxsocks)
+ return (ISC_R_EXISTS);
+
+ socketmgr->refs++;
+ *managerp = socketmgr;
+ return (ISC_R_SUCCESS);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ if (maxsocks == 0)
+ maxsocks = ISC_SOCKET_MAXSOCKETS;
+
+ manager = isc_mem_get(mctx, sizeof(*manager));
+ if (manager == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /* zero-clear so that necessary cleanup on failure will be easy */
+ memset(manager, 0, sizeof(*manager));
+ manager->maxsocks = maxsocks;
+ manager->reserved = 0;
+ manager->fds = isc_mem_get(mctx,
+ manager->maxsocks * sizeof(isc_socket_t *));
+ if (manager->fds == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto free_manager;
+ }
+ manager->fdstate = isc_mem_get(mctx, manager->maxsocks * sizeof(int));
+ if (manager->fds == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto free_manager;
+ }
+
+ manager->magic = SOCKET_MANAGER_MAGIC;
+ manager->mctx = NULL;
+ memset(manager->fds, 0, manager->maxsocks * sizeof(isc_socket_t *));
+ ISC_LIST_INIT(manager->socklist);
+ result = isc_mutex_init(&manager->lock);
+ if (result != ISC_R_SUCCESS)
+ goto free_manager;
+ manager->fdlock = isc_mem_get(mctx, FDLOCK_COUNT * sizeof(isc_mutex_t));
+ if (manager->fdlock == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_lock;
+ }
+ for (i = 0; i < FDLOCK_COUNT; i++) {
+ result = isc_mutex_init(&manager->fdlock[i]);
+ if (result != ISC_R_SUCCESS) {
+ while (--i >= 0)
+ DESTROYLOCK(&manager->fdlock[i]);
+ isc_mem_put(mctx, manager->fdlock,
+ FDLOCK_COUNT * sizeof(isc_mutex_t));
+ manager->fdlock = NULL;
+ goto cleanup_lock;
+ }
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+ if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_condition_init() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup_lock;
+ }
+
+ /*
+ * Create the special fds that will be used to wake up the
+ * select/poll loop when something internal needs to be done.
+ */
+ if (pipe(manager->pipe_fds) != 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "pipe() %s: %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto cleanup_condition;
+ }
+
+ RUNTIME_CHECK(make_nonblock(manager->pipe_fds[0]) == ISC_R_SUCCESS);
+#if 0
+ RUNTIME_CHECK(make_nonblock(manager->pipe_fds[1]) == ISC_R_SUCCESS);
+#endif
+#else /* ISC_PLATFORM_USETHREADS */
+ manager->refs = 1;
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /*
+ * Set up initial state for the select loop
+ */
+ result = setup_watcher(mctx, manager);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ memset(manager->fdstate, 0, manager->maxsocks * sizeof(int));
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * Start up the select/poll thread.
+ */
+ if (isc_thread_create(watcher, manager, &manager->watcher) !=
+ ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_thread_create() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ cleanup_watcher(mctx, manager);
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+ isc_mem_attach(mctx, &manager->mctx);
+
+#ifndef ISC_PLATFORM_USETHREADS
+ socketmgr = manager;
+#endif /* ISC_PLATFORM_USETHREADS */
+ *managerp = manager;
+
+ return (ISC_R_SUCCESS);
+
+cleanup:
+#ifdef ISC_PLATFORM_USETHREADS
+ (void)close(manager->pipe_fds[0]);
+ (void)close(manager->pipe_fds[1]);
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#ifdef ISC_PLATFORM_USETHREADS
+cleanup_condition:
+ (void)isc_condition_destroy(&manager->shutdown_ok);
+#endif /* ISC_PLATFORM_USETHREADS */
+
+
+cleanup_lock:
+ if (manager->fdlock != NULL) {
+ for (i = 0; i < FDLOCK_COUNT; i++)
+ DESTROYLOCK(&manager->fdlock[i]);
+ }
+ DESTROYLOCK(&manager->lock);
+
+free_manager:
+ if (manager->fdlock != NULL) {
+ isc_mem_put(mctx, manager->fdlock,
+ FDLOCK_COUNT * sizeof(isc_mutex_t));
+ }
+ if (manager->fdstate != NULL) {
+ isc_mem_put(mctx, manager->fdstate,
+ manager->maxsocks * sizeof(int));
+ }
+ if (manager->fds != NULL) {
+ isc_mem_put(mctx, manager->fds,
+ manager->maxsocks * sizeof(isc_socket_t *));
+ }
+ isc_mem_put(mctx, manager, sizeof(*manager));
+
+ return (result);
+}
+
+isc_result_t
+isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(nsockp != NULL);
+
+ *nsockp = manager->maxsocks;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
+ isc_socketmgr_t *manager;
+ int i;
+ isc_mem_t *mctx;
+
+ /*
+ * Destroy a socket manager.
+ */
+
+ REQUIRE(managerp != NULL);
+ manager = *managerp;
+ REQUIRE(VALID_MANAGER(manager));
+
+#ifndef ISC_PLATFORM_USETHREADS
+ if (manager->refs > 1) {
+ manager->refs--;
+ *managerp = NULL;
+ return;
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ LOCK(&manager->lock);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * Wait for all sockets to be destroyed.
+ */
+ while (!ISC_LIST_EMPTY(manager->socklist)) {
+ manager_log(manager, CREATION,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_SOCKETSREMAIN,
+ "sockets exist"));
+ WAIT(&manager->shutdown_ok, &manager->lock);
+ }
+#else /* ISC_PLATFORM_USETHREADS */
+ /*
+ * Hope all sockets have been destroyed.
+ */
+ if (!ISC_LIST_EMPTY(manager->socklist)) {
+ manager_log(manager, CREATION,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_SOCKETSREMAIN,
+ "sockets exist"));
+ INSIST(0);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ UNLOCK(&manager->lock);
+
+ /*
+ * Here, poke our select/poll thread. Do this by closing the write
+ * half of the pipe, which will send EOF to the read half.
+ * This is currently a no-op in the non-threaded case.
+ */
+ select_poke(manager, 0, SELECT_POKE_SHUTDOWN);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * Wait for thread to exit.
+ */
+ if (isc_thread_join(manager->watcher, NULL) != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_thread_join() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ /*
+ * Clean up.
+ */
+ cleanup_watcher(manager->mctx, manager);
+
+#ifdef ISC_PLATFORM_USETHREADS
+ (void)close(manager->pipe_fds[0]);
+ (void)close(manager->pipe_fds[1]);
+ (void)isc_condition_destroy(&manager->shutdown_ok);
+#endif /* ISC_PLATFORM_USETHREADS */
+
+ 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 *));
+ isc_mem_put(manager->mctx, manager->fdstate,
+ manager->maxsocks * sizeof(int));
+
+ if (manager->fdlock != NULL) {
+ for (i = 0; i < FDLOCK_COUNT; i++)
+ DESTROYLOCK(&manager->fdlock[i]);
+ isc_mem_put(manager->mctx, manager->fdlock,
+ FDLOCK_COUNT * sizeof(isc_mutex_t));
+ }
+ DESTROYLOCK(&manager->lock);
+ manager->magic = 0;
+ mctx= manager->mctx;
+ isc_mem_put(mctx, manager, sizeof(*manager));
+
+ isc_mem_detach(&mctx);
+
+ *managerp = NULL;
+}
+
+static isc_result_t
+socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+ unsigned int flags)
+{
+ int io_state;
+ isc_boolean_t have_lock = ISC_FALSE;
+ isc_task_t *ntask = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ dev->ev_sender = task;
+
+ if (sock->type == isc_sockettype_udp) {
+ io_state = doio_recv(sock, dev);
+ } else {
+ LOCK(&sock->lock);
+ have_lock = ISC_TRUE;
+
+ if (ISC_LIST_EMPTY(sock->recv_list))
+ io_state = doio_recv(sock, dev);
+ else
+ io_state = DOIO_SOFT;
+ }
+
+ switch (io_state) {
+ case DOIO_SOFT:
+ /*
+ * We couldn't read all or part of the request right now, so
+ * queue it.
+ *
+ * Attach to socket and to task
+ */
+ isc_task_attach(task, &ntask);
+ dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
+
+ if (!have_lock) {
+ LOCK(&sock->lock);
+ have_lock = ISC_TRUE;
+ }
+
+ /*
+ * Enqueue the request. If the socket was previously not being
+ * watched, poke the watcher to start paying attention to it.
+ */
+ if (ISC_LIST_EMPTY(sock->recv_list) && !sock->pending_recv)
+ select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
+ ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link);
+
+ socket_log(sock, NULL, EVENT, NULL, 0, 0,
+ "socket_recv: event %p -> task %p",
+ dev, ntask);
+
+ if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
+ result = ISC_R_INPROGRESS;
+ break;
+
+ case DOIO_EOF:
+ dev->result = ISC_R_EOF;
+ /* fallthrough */
+
+ case DOIO_HARD:
+ case DOIO_SUCCESS:
+ if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0)
+ send_recvdone_event(sock, &dev);
+ break;
+ }
+
+ if (have_lock)
+ UNLOCK(&sock->lock);
+
+ 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_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+ unsigned int iocount;
+ isc_buffer_t *buffer;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(buflist != NULL);
+ REQUIRE(!ISC_LIST_EMPTY(*buflist));
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ iocount = isc_bufferlist_availablecount(buflist);
+ REQUIRE(iocount > 0);
+
+ INSIST(sock->bound);
+
+ dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+ if (dev == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ /*
+ * UDP sockets are always partial read
+ */
+ if (sock->type == isc_sockettype_udp)
+ dev->minimum = 1;
+ else {
+ if (minimum == 0)
+ dev->minimum = iocount;
+ else
+ dev->minimum = minimum;
+ }
+
+ /*
+ * Move each buffer from the passed in list to our internal one.
+ */
+ buffer = ISC_LIST_HEAD(*buflist);
+ while (buffer != NULL) {
+ ISC_LIST_DEQUEUE(*buflist, buffer, link);
+ ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
+ buffer = ISC_LIST_HEAD(*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_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ INSIST(sock->bound);
+
+ dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+ if (dev == NULL)
+ return (ISC_R_NOMEMORY);
+
+ return (isc_socket_recv2(sock, 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)
+{
+ event->ev_sender = sock;
+ event->result = ISC_R_UNEXPECTED;
+ ISC_LIST_INIT(event->bufferlist);
+ event->region = *region;
+ event->n = 0;
+ event->offset = 0;
+ event->attributes = 0;
+
+ /*
+ * UDP sockets are always partial read.
+ */
+ if (sock->type == isc_sockettype_udp)
+ event->minimum = 1;
+ else {
+ if (minimum == 0)
+ event->minimum = region->length;
+ else
+ event->minimum = minimum;
+ }
+
+ return (socket_recv(sock, event, task, flags));
+}
+
+static isc_result_t
+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)
+{
+ int io_state;
+ isc_boolean_t have_lock = ISC_FALSE;
+ isc_task_t *ntask = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ dev->ev_sender = task;
+
+ set_dev_address(address, sock, dev);
+ if (pktinfo != NULL) {
+ dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO;
+ dev->pktinfo = *pktinfo;
+
+ if (!isc_sockaddr_issitelocal(&dev->address) &&
+ !isc_sockaddr_islinklocal(&dev->address)) {
+ socket_log(sock, NULL, TRACE, isc_msgcat,
+ ISC_MSGSET_SOCKET, ISC_MSG_PKTINFOPROVIDED,
+ "pktinfo structure provided, ifindex %u "
+ "(set to 0)", pktinfo->ipi6_ifindex);
+
+ /*
+ * Set the pktinfo index to 0 here, to let the
+ * kernel decide what interface it should send on.
+ */
+ dev->pktinfo.ipi6_ifindex = 0;
+ }
+ }
+
+ if (sock->type == isc_sockettype_udp)
+ io_state = doio_send(sock, dev);
+ else {
+ LOCK(&sock->lock);
+ have_lock = ISC_TRUE;
+
+ if (ISC_LIST_EMPTY(sock->send_list))
+ io_state = doio_send(sock, dev);
+ else
+ io_state = DOIO_SOFT;
+ }
+
+ switch (io_state) {
+ case DOIO_SOFT:
+ /*
+ * We couldn't send all or part of the request right now, so
+ * queue it unless ISC_SOCKFLAG_NORETRY is set.
+ */
+ if ((flags & ISC_SOCKFLAG_NORETRY) == 0) {
+ isc_task_attach(task, &ntask);
+ dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
+
+ if (!have_lock) {
+ LOCK(&sock->lock);
+ have_lock = ISC_TRUE;
+ }
+
+ /*
+ * Enqueue the request. If the socket was previously
+ * not being watched, poke the watcher to start
+ * paying attention to it.
+ */
+ if (ISC_LIST_EMPTY(sock->send_list) &&
+ !sock->pending_send)
+ select_poke(sock->manager, sock->fd,
+ SELECT_POKE_WRITE);
+ ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link);
+
+ socket_log(sock, NULL, EVENT, NULL, 0, 0,
+ "socket_send: event %p -> task %p",
+ dev, ntask);
+
+ if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
+ result = ISC_R_INPROGRESS;
+ break;
+ }
+
+ case DOIO_HARD:
+ case DOIO_SUCCESS:
+ if ((flags & ISC_SOCKFLAG_IMMEDIATE) == 0)
+ send_senddone_event(sock, &dev);
+ break;
+ }
+
+ if (have_lock)
+ UNLOCK(&sock->lock);
+
+ 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)
+{
+ /*
+ * REQUIRE() checking is performed in isc_socket_sendto().
+ */
+ 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_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(region != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ INSIST(sock->bound);
+
+ dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+ if (dev == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ dev->region = *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)
+{
+ 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_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+ unsigned int iocount;
+ isc_buffer_t *buffer;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(buflist != NULL);
+ REQUIRE(!ISC_LIST_EMPTY(*buflist));
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ iocount = isc_bufferlist_usedcount(buflist);
+ REQUIRE(iocount > 0);
+
+ dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+ if (dev == NULL) {
+ return (ISC_R_NOMEMORY);
+ }
+
+ /*
+ * Move each buffer from the passed in list to our internal one.
+ */
+ buffer = ISC_LIST_HEAD(*buflist);
+ while (buffer != NULL) {
+ ISC_LIST_DEQUEUE(*buflist, buffer, link);
+ ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
+ buffer = ISC_LIST_HEAD(*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)
+{
+ REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0);
+ if ((flags & ISC_SOCKFLAG_NORETRY) != 0)
+ REQUIRE(sock->type == isc_sockettype_udp);
+ event->ev_sender = sock;
+ event->result = ISC_R_UNEXPECTED;
+ ISC_LIST_INIT(event->bufferlist);
+ event->region = *region;
+ event->n = 0;
+ event->offset = 0;
+ event->attributes = 0;
+
+ return (socket_send(sock, event, task, address, pktinfo, flags));
+}
+
+void
+isc_socket_cleanunix(isc_sockaddr_t *sockaddr, isc_boolean_t active) {
+#ifdef ISC_PLATFORM_HAVESYSUNH
+ int s;
+ struct stat sb;
+ char strbuf[ISC_STRERRORSIZE];
+
+ if (sockaddr->type.sa.sa_family != AF_UNIX)
+ return;
+
+#ifndef S_ISSOCK
+#if defined(S_IFMT) && defined(S_IFSOCK)
+#define S_ISSOCK(mode) ((mode & S_IFMT)==S_IFSOCK)
+#elif defined(_S_IFMT) && defined(S_IFSOCK)
+#define S_ISSOCK(mode) ((mode & _S_IFMT)==S_IFSOCK)
+#endif
+#endif
+
+#ifndef S_ISFIFO
+#if defined(S_IFMT) && defined(S_IFIFO)
+#define S_ISFIFO(mode) ((mode & S_IFMT)==S_IFIFO)
+#elif defined(_S_IFMT) && defined(S_IFIFO)
+#define S_ISFIFO(mode) ((mode & _S_IFMT)==S_IFIFO)
+#endif
+#endif
+
+#if !defined(S_ISFIFO) && !defined(S_ISSOCK)
+#error You need to define S_ISFIFO and S_ISSOCK as appropriate for your platform. See <sys/stat.h>.
+#endif
+
+#ifndef S_ISFIFO
+#define S_ISFIFO(mode) 0
+#endif
+
+#ifndef S_ISSOCK
+#define S_ISSOCK(mode) 0
+#endif
+
+ if (active) {
+ if (stat(sockaddr->type.sunix.sun_path, &sb) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ "isc_socket_cleanunix: stat(%s): %s",
+ sockaddr->type.sunix.sun_path, strbuf);
+ return;
+ }
+ if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) {
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ "isc_socket_cleanunix: %s: not a socket",
+ sockaddr->type.sunix.sun_path);
+ return;
+ }
+ if (unlink(sockaddr->type.sunix.sun_path) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ "isc_socket_cleanunix: unlink(%s): %s",
+ sockaddr->type.sunix.sun_path, strbuf);
+ }
+ return;
+ }
+
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (s < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING,
+ "isc_socket_cleanunix: socket(%s): %s",
+ sockaddr->type.sunix.sun_path, strbuf);
+ return;
+ }
+
+ if (stat(sockaddr->type.sunix.sun_path, &sb) < 0) {
+ switch (errno) {
+ case ENOENT: /* We exited cleanly last time */
+ break;
+ default:
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING,
+ "isc_socket_cleanunix: stat(%s): %s",
+ sockaddr->type.sunix.sun_path, strbuf);
+ break;
+ }
+ goto cleanup;
+ }
+
+ if (!(S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode))) {
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING,
+ "isc_socket_cleanunix: %s: not a socket",
+ sockaddr->type.sunix.sun_path);
+ goto cleanup;
+ }
+
+ if (connect(s, (struct sockaddr *)&sockaddr->type.sunix,
+ sizeof(sockaddr->type.sunix)) < 0) {
+ switch (errno) {
+ case ECONNREFUSED:
+ case ECONNRESET:
+ if (unlink(sockaddr->type.sunix.sun_path) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET,
+ ISC_LOG_WARNING,
+ "isc_socket_cleanunix: "
+ "unlink(%s): %s",
+ sockaddr->type.sunix.sun_path,
+ strbuf);
+ }
+ break;
+ default:
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_WARNING,
+ "isc_socket_cleanunix: connect(%s): %s",
+ sockaddr->type.sunix.sun_path, strbuf);
+ break;
+ }
+ }
+ cleanup:
+ close(s);
+#else
+ UNUSED(sockaddr);
+ UNUSED(active);
+#endif
+}
+
+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
+ isc_result_t result = ISC_R_SUCCESS;
+ char strbuf[ISC_STRERRORSIZE];
+ char path[sizeof(sockaddr->type.sunix.sun_path)];
+#ifdef NEED_SECURE_DIRECTORY
+ char *slash;
+#endif
+
+ REQUIRE(sockaddr->type.sa.sa_family == AF_UNIX);
+ INSIST(strlen(sockaddr->type.sunix.sun_path) < sizeof(path));
+ strcpy(path, sockaddr->type.sunix.sun_path);
+
+#ifdef NEED_SECURE_DIRECTORY
+ slash = strrchr(path, '/');
+ if (slash != NULL) {
+ if (slash != path)
+ *slash = '\0';
+ else
+ strcpy(path, "/");
+ } else
+ strcpy(path, ".");
+#endif
+
+ if (chmod(path, perm) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ "isc_socket_permunix: chmod(%s, %d): %s",
+ path, perm, strbuf);
+ result = ISC_R_FAILURE;
+ }
+ if (chown(path, owner, group) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ "isc_socket_permunix: chown(%s, %d, %d): %s",
+ path, owner, group,
+ strbuf);
+ result = ISC_R_FAILURE;
+ }
+ return (result);
+#else
+ UNUSED(sockaddr);
+ UNUSED(perm);
+ UNUSED(owner);
+ UNUSED(group);
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+isc_result_t
+isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+ unsigned int options) {
+ char strbuf[ISC_STRERRORSIZE];
+ int on = 1;
+
+ LOCK(&sock->lock);
+
+ INSIST(!sock->bound);
+
+ if (sock->pf != sockaddr->type.sa.sa_family) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_FAMILYMISMATCH);
+ }
+ /*
+ * Only set SO_REUSEADDR when we want a specific port.
+ */
+#ifdef AF_UNIX
+ if (sock->pf == AF_UNIX)
+ goto bind_socket;
+#endif
+ if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
+ isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
+ setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
+ sizeof(on)) < 0) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d) %s", sock->fd,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ /* Press on... */
+ }
+#ifdef AF_UNIX
+ bind_socket:
+#endif
+ if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) {
+ UNLOCK(&sock->lock);
+ switch (errno) {
+ case EACCES:
+ return (ISC_R_NOPERM);
+ case EADDRNOTAVAIL:
+ return (ISC_R_ADDRNOTAVAIL);
+ case EADDRINUSE:
+ return (ISC_R_ADDRINUSE);
+ case EINVAL:
+ return (ISC_R_BOUND);
+ default:
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s",
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+
+ socket_log(sock, sockaddr, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound");
+ sock->bound = 1;
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socket_filter(isc_socket_t *sock, const char *filter) {
+#ifdef SO_ACCEPTFILTER
+ char strbuf[ISC_STRERRORSIZE];
+ struct accept_filter_arg afa;
+#else
+ UNUSED(sock);
+ UNUSED(filter);
+#endif
+
+ REQUIRE(VALID_SOCKET(sock));
+
+#ifdef SO_ACCEPTFILTER
+ bzero(&afa, sizeof(afa));
+ strncpy(afa.af_name, filter, sizeof(afa.af_name));
+ if (setsockopt(sock->fd, SOL_SOCKET, SO_ACCEPTFILTER,
+ &afa, sizeof(afa)) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FILTER, "setsockopt(SO_ACCEPTFILTER): %s",
+ strbuf);
+ return (ISC_R_FAILURE);
+ }
+ return (ISC_R_SUCCESS);
+#else
+ return (ISC_R_NOTIMPLEMENTED);
+#endif
+}
+
+/*
+ * Set up to listen on a given socket. We do this by creating an internal
+ * event that will be dispatched when the socket has read activity. The
+ * watcher will send the internal event to the task when there is a new
+ * connection.
+ *
+ * Unlike in read, we don't preallocate a done event here. Every time there
+ * 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) {
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+
+ REQUIRE(!sock->listener);
+ REQUIRE(sock->bound);
+ REQUIRE(sock->type == isc_sockettype_tcp ||
+ sock->type == isc_sockettype_unix);
+
+ if (backlog == 0)
+ backlog = SOMAXCONN;
+
+ if (listen(sock->fd, (int)backlog) < 0) {
+ UNLOCK(&sock->lock);
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", strbuf);
+
+ return (ISC_R_UNEXPECTED);
+ }
+
+ sock->listener = 1;
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This should try to do aggressive accept() XXXMLG
+ */
+isc_result_t
+isc_socket_accept(isc_socket_t *sock,
+ isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+ isc_socket_newconnev_t *dev;
+ isc_socketmgr_t *manager;
+ isc_task_t *ntask = NULL;
+ isc_socket_t *nsock;
+ isc_result_t result;
+ isc_boolean_t do_poke = ISC_FALSE;
+
+ REQUIRE(VALID_SOCKET(sock));
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ LOCK(&sock->lock);
+
+ REQUIRE(sock->listener);
+
+ /*
+ * Sender field is overloaded here with the task we will be sending
+ * this event to. Just before the actual event is delivered the
+ * actual ev_sender will be touched up to be the socket.
+ */
+ dev = (isc_socket_newconnev_t *)
+ isc_event_allocate(manager->mctx, task, ISC_SOCKEVENT_NEWCONN,
+ action, arg, sizeof(*dev));
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+ ISC_LINK_INIT(dev, ev_link);
+
+ result = allocate_socket(manager, sock->type, &nsock);
+ if (result != ISC_R_SUCCESS) {
+ isc_event_free(ISC_EVENT_PTR(&dev));
+ UNLOCK(&sock->lock);
+ return (result);
+ }
+
+ /*
+ * Attach to socket and to task.
+ */
+ isc_task_attach(task, &ntask);
+ nsock->references++;
+
+ dev->ev_sender = ntask;
+ dev->newsocket = nsock;
+
+ /*
+ * Poke watcher here. We still have the socket locked, so there
+ * is no race condition. We will keep the lock for such a short
+ * bit of time waking it up now or later won't matter all that much.
+ */
+ if (ISC_LIST_EMPTY(sock->accept_list))
+ do_poke = ISC_TRUE;
+
+ ISC_LIST_ENQUEUE(sock->accept_list, dev, ev_link);
+
+ if (do_poke)
+ select_poke(manager, sock->fd, SELECT_POKE_ACCEPT);
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+}
+
+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_socket_connev_t *dev;
+ isc_task_t *ntask = NULL;
+ isc_socketmgr_t *manager;
+ int cc;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(addr != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(addr != NULL);
+
+ if (isc_sockaddr_ismulticast(addr))
+ return (ISC_R_MULTICAST);
+
+ LOCK(&sock->lock);
+
+ REQUIRE(!sock->connecting);
+
+ dev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
+ ISC_SOCKEVENT_CONNECT,
+ action, arg,
+ sizeof(*dev));
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+ ISC_LINK_INIT(dev, ev_link);
+
+ /*
+ * Try to do the connect right away, as there can be only one
+ * outstanding, and it might happen to complete.
+ */
+ sock->peer_address = *addr;
+ cc = connect(sock->fd, &addr->type.sa, addr->length);
+ if (cc < 0) {
+ /*
+ * HP-UX "fails" to connect a UDP socket and sets errno to
+ * EINPROGRESS if it's non-blocking. We'd rather regard this as
+ * a success and let the user detect it if it's really an error
+ * at the time of sending a packet on the socket.
+ */
+ if (sock->type == isc_sockettype_udp && errno == EINPROGRESS) {
+ cc = 0;
+ goto success;
+ }
+ if (SOFT_ERROR(errno) || errno == EINPROGRESS)
+ goto queue;
+
+ switch (errno) {
+#define ERROR_MATCH(a, b) case a: dev->result = b; goto err_exit;
+ ERROR_MATCH(EACCES, ISC_R_NOPERM);
+ ERROR_MATCH(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+ ERROR_MATCH(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
+ ERROR_MATCH(ECONNREFUSED, ISC_R_CONNREFUSED);
+ ERROR_MATCH(EHOSTUNREACH, ISC_R_HOSTUNREACH);
+#ifdef EHOSTDOWN
+ ERROR_MATCH(EHOSTDOWN, ISC_R_HOSTUNREACH);
+#endif
+ ERROR_MATCH(ENETUNREACH, ISC_R_NETUNREACH);
+ ERROR_MATCH(ENOBUFS, ISC_R_NORESOURCES);
+ ERROR_MATCH(EPERM, ISC_R_HOSTUNREACH);
+ ERROR_MATCH(EPIPE, ISC_R_NOTCONNECTED);
+ ERROR_MATCH(ECONNRESET, ISC_R_CONNECTIONRESET);
+#undef ERROR_MATCH
+ }
+
+ sock->connected = 0;
+
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "%d/%s", errno, strbuf);
+
+ UNLOCK(&sock->lock);
+ isc_event_free(ISC_EVENT_PTR(&dev));
+ return (ISC_R_UNEXPECTED);
+
+ err_exit:
+ sock->connected = 0;
+ isc_task_send(task, ISC_EVENT_PTR(&dev));
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * If connect completed, fire off the done event.
+ */
+ success:
+ if (cc == 0) {
+ sock->connected = 1;
+ sock->bound = 1;
+ dev->result = ISC_R_SUCCESS;
+ isc_task_send(task, ISC_EVENT_PTR(&dev));
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+ }
+
+ queue:
+
+ /*
+ * Attach to task.
+ */
+ isc_task_attach(task, &ntask);
+
+ sock->connecting = 1;
+
+ dev->ev_sender = ntask;
+
+ /*
+ * Poke watcher here. We still have the socket locked, so there
+ * is no race condition. We will keep the lock for such a short
+ * bit of time waking it up now or later won't matter all that much.
+ */
+ if (sock->connect_ev == NULL)
+ select_poke(manager, sock->fd, SELECT_POKE_CONNECT);
+
+ sock->connect_ev = dev;
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Called when a socket with a pending connect() finishes.
+ */
+static void
+internal_connect(isc_task_t *me, isc_event_t *ev) {
+ isc_socket_t *sock;
+ isc_socket_connev_t *dev;
+ isc_task_t *task;
+ int cc;
+ ISC_SOCKADDR_LEN_T optlen;
+ char strbuf[ISC_STRERRORSIZE];
+ char peerbuf[ISC_SOCKADDR_FORMATSIZE];
+
+ UNUSED(me);
+ INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);
+
+ sock = ev->ev_sender;
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+
+ /*
+ * When the internal event was sent the reference count was bumped
+ * to keep the socket around for us. Decrement the count here.
+ */
+ INSIST(sock->references > 0);
+ sock->references--;
+ if (sock->references == 0) {
+ UNLOCK(&sock->lock);
+ destroy(&sock);
+ return;
+ }
+
+ /*
+ * Has this event been canceled?
+ */
+ dev = sock->connect_ev;
+ if (dev == NULL) {
+ INSIST(!sock->connecting);
+ UNLOCK(&sock->lock);
+ return;
+ }
+
+ INSIST(sock->connecting);
+ sock->connecting = 0;
+
+ /*
+ * Get any possible error status here.
+ */
+ optlen = sizeof(cc);
+ if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR,
+ (void *)&cc, (void *)&optlen) < 0)
+ cc = errno;
+ else
+ errno = cc;
+
+ if (errno != 0) {
+ /*
+ * If the error is EAGAIN, just re-select on this
+ * fd and pretend nothing strange happened.
+ */
+ if (SOFT_ERROR(errno) || errno == EINPROGRESS) {
+ sock->connecting = 1;
+ select_poke(sock->manager, sock->fd,
+ SELECT_POKE_CONNECT);
+ UNLOCK(&sock->lock);
+
+ return;
+ }
+
+ /*
+ * Translate other errors into ISC_R_* flavors.
+ */
+ switch (errno) {
+#define ERROR_MATCH(a, b) case a: dev->result = b; break;
+ ERROR_MATCH(EACCES, ISC_R_NOPERM);
+ ERROR_MATCH(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+ ERROR_MATCH(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
+ ERROR_MATCH(ECONNREFUSED, ISC_R_CONNREFUSED);
+ ERROR_MATCH(EHOSTUNREACH, ISC_R_HOSTUNREACH);
+#ifdef EHOSTDOWN
+ ERROR_MATCH(EHOSTDOWN, ISC_R_HOSTUNREACH);
+#endif
+ ERROR_MATCH(ENETUNREACH, ISC_R_NETUNREACH);
+ ERROR_MATCH(ENOBUFS, ISC_R_NORESOURCES);
+ ERROR_MATCH(EPERM, ISC_R_HOSTUNREACH);
+ ERROR_MATCH(EPIPE, ISC_R_NOTCONNECTED);
+ ERROR_MATCH(ETIMEDOUT, ISC_R_TIMEDOUT);
+ ERROR_MATCH(ECONNRESET, ISC_R_CONNECTIONRESET);
+#undef ERROR_MATCH
+ default:
+ dev->result = ISC_R_UNEXPECTED;
+ isc_sockaddr_format(&sock->peer_address, peerbuf,
+ sizeof(peerbuf));
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "internal_connect: connect(%s) %s",
+ peerbuf, strbuf);
+ }
+ } else {
+ dev->result = ISC_R_SUCCESS;
+ sock->connected = 1;
+ sock->bound = 1;
+ }
+
+ sock->connect_ev = NULL;
+
+ UNLOCK(&sock->lock);
+
+ task = dev->ev_sender;
+ dev->ev_sender = sock;
+ isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));
+}
+
+isc_result_t
+isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ isc_result_t result;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(addressp != NULL);
+
+ LOCK(&sock->lock);
+
+ if (sock->connected) {
+ *addressp = sock->peer_address;
+ result = ISC_R_SUCCESS;
+ } else {
+ result = ISC_R_NOTCONNECTED;
+ }
+
+ UNLOCK(&sock->lock);
+
+ return (result);
+}
+
+isc_result_t
+isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ ISC_SOCKADDR_LEN_T len;
+ isc_result_t result;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(addressp != NULL);
+
+ LOCK(&sock->lock);
+
+ if (!sock->bound) {
+ result = ISC_R_NOTBOUND;
+ goto out;
+ }
+
+ result = ISC_R_SUCCESS;
+
+ len = sizeof(addressp->type);
+ if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto out;
+ }
+ addressp->length = (unsigned int)len;
+
+ out:
+ UNLOCK(&sock->lock);
+
+ return (result);
+}
+
+/*
+ * 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) {
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ /*
+ * Quick exit if there is nothing to do. Don't even bother locking
+ * in this case.
+ */
+ if (how == 0)
+ return;
+
+ LOCK(&sock->lock);
+
+ /*
+ * All of these do the same thing, more or less.
+ * Each will:
+ * o If the internal event is marked as "posted" try to
+ * remove it from the task's queue. If this fails, mark it
+ * as canceled instead, and let the task clean it up later.
+ * o For each I/O request for that task of that type, post
+ * its done event with status of "ISC_R_CANCELED".
+ * o Reset any state needed.
+ */
+ if (((how & ISC_SOCKCANCEL_RECV) == ISC_SOCKCANCEL_RECV)
+ && !ISC_LIST_EMPTY(sock->recv_list)) {
+ isc_socketevent_t *dev;
+ isc_socketevent_t *next;
+ isc_task_t *current_task;
+
+ dev = ISC_LIST_HEAD(sock->recv_list);
+
+ while (dev != NULL) {
+ current_task = dev->ev_sender;
+ next = ISC_LIST_NEXT(dev, ev_link);
+
+ if ((task == NULL) || (task == current_task)) {
+ dev->result = ISC_R_CANCELED;
+ send_recvdone_event(sock, &dev);
+ }
+ dev = next;
+ }
+ }
+
+ if (((how & ISC_SOCKCANCEL_SEND) == ISC_SOCKCANCEL_SEND)
+ && !ISC_LIST_EMPTY(sock->send_list)) {
+ isc_socketevent_t *dev;
+ isc_socketevent_t *next;
+ isc_task_t *current_task;
+
+ dev = ISC_LIST_HEAD(sock->send_list);
+
+ while (dev != NULL) {
+ current_task = dev->ev_sender;
+ next = ISC_LIST_NEXT(dev, ev_link);
+
+ if ((task == NULL) || (task == current_task)) {
+ dev->result = ISC_R_CANCELED;
+ send_senddone_event(sock, &dev);
+ }
+ dev = next;
+ }
+ }
+
+ if (((how & ISC_SOCKCANCEL_ACCEPT) == ISC_SOCKCANCEL_ACCEPT)
+ && !ISC_LIST_EMPTY(sock->accept_list)) {
+ isc_socket_newconnev_t *dev;
+ isc_socket_newconnev_t *next;
+ isc_task_t *current_task;
+
+ dev = ISC_LIST_HEAD(sock->accept_list);
+ while (dev != NULL) {
+ current_task = dev->ev_sender;
+ next = ISC_LIST_NEXT(dev, ev_link);
+
+ if ((task == NULL) || (task == current_task)) {
+
+ ISC_LIST_UNLINK(sock->accept_list, dev,
+ ev_link);
+
+ dev->newsocket->references--;
+ free_socket(&dev->newsocket);
+
+ dev->result = ISC_R_CANCELED;
+ dev->ev_sender = sock;
+ isc_task_sendanddetach(&current_task,
+ ISC_EVENT_PTR(&dev));
+ }
+
+ dev = next;
+ }
+ }
+
+ /*
+ * Connecting is not a list.
+ */
+ if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT)
+ && sock->connect_ev != NULL) {
+ isc_socket_connev_t *dev;
+ isc_task_t *current_task;
+
+ INSIST(sock->connecting);
+ sock->connecting = 0;
+
+ dev = sock->connect_ev;
+ current_task = dev->ev_sender;
+
+ if ((task == NULL) || (task == current_task)) {
+ sock->connect_ev = NULL;
+
+ dev->result = ISC_R_CANCELED;
+ dev->ev_sender = sock;
+ isc_task_sendanddetach(&current_task,
+ ISC_EVENT_PTR(&dev));
+ }
+ }
+
+ UNLOCK(&sock->lock);
+}
+
+isc_sockettype_t
+isc_socket_gettype(isc_socket_t *sock) {
+ REQUIRE(VALID_SOCKET(sock));
+
+ return (sock->type);
+}
+
+isc_boolean_t
+isc_socket_isbound(isc_socket_t *sock) {
+ isc_boolean_t val;
+
+ LOCK(&sock->lock);
+ val = ((sock->bound) ? ISC_TRUE : ISC_FALSE);
+ UNLOCK(&sock->lock);
+
+ return (val);
+}
+
+void
+isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+#if defined(IPV6_V6ONLY)
+ int onoff = yes ? 1 : 0;
+#else
+ UNUSED(yes);
+ UNUSED(sock);
+#endif
+
+ REQUIRE(VALID_SOCKET(sock));
+
+#ifdef IPV6_V6ONLY
+ if (sock->pf == AF_INET6) {
+ if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (void *)&onoff, sizeof(int)) < 0) {
+ char strbuf[ISC_STRERRORSIZE];
+
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_V6ONLY) "
+ "%s: %s", sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
+ }
+ FIX_IPV6_RECVPKTINFO(sock); /* AIX */
+#endif
+}
+
+#ifndef ISC_PLATFORM_USETHREADS
+/* In our assumed scenario, we can simply use a single static object. */
+static isc_socketwait_t swait_private;
+
+int
+isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
+ int n;
+#ifdef USE_KQUEUE
+ struct timespec ts, *tsp;
+#endif
+#ifdef USE_EPOLL
+ int timeout;
+#endif
+#ifdef USE_DEVPOLL
+ struct dvpoll dvp;
+#endif
+
+ REQUIRE(swaitp != NULL && *swaitp == NULL);
+
+ if (socketmgr == NULL)
+ return (0);
+
+#ifdef USE_KQUEUE
+ if (tvp != NULL) {
+ ts.tv_sec = tvp->tv_sec;
+ ts.tv_nsec = tvp->tv_usec * 1000;
+ tsp = &ts;
+ } else
+ tsp = NULL;
+ swait_private.nevents = kevent(socketmgr->kqueue_fd, NULL, 0,
+ socketmgr->events, socketmgr->nevents,
+ tsp);
+ n = swait_private.nevents;
+#elif defined(USE_EPOLL)
+ if (tvp != NULL)
+ 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);
+ n = swait_private.nevents;
+#elif defined(USE_DEVPOLL)
+ dvp.dp_fds = socketmgr->events;
+ dvp.dp_nfds = socketmgr->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);
+ 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);
+
+ swait_private.readset = socketmgr->read_fds_copy;
+ swait_private.writeset = socketmgr->write_fds_copy;
+ swait_private.maxfd = socketmgr->maxfd + 1;
+
+ n = select(swait_private.maxfd, swait_private.readset,
+ swait_private.writeset, NULL, tvp);
+#endif
+
+ *swaitp = &swait_private;
+ return (n);
+}
+
+isc_result_t
+isc__socketmgr_dispatch(isc_socketwait_t *swait) {
+ REQUIRE(swait == &swait_private);
+
+ if (socketmgr == NULL)
+ return (ISC_R_NOTFOUND);
+
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+ (void)process_fds(socketmgr, socketmgr->events, swait->nevents);
+ return (ISC_R_SUCCESS);
+#elif defined(USE_SELECT)
+ process_fds(socketmgr, swait->maxfd, swait->readset, swait->writeset);
+ return (ISC_R_SUCCESS);
+#endif
+}
+#endif /* ISC_PLATFORM_USETHREADS */
+
+void
+isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+
+ /*
+ * Name 'socket'.
+ */
+
+ REQUIRE(VALID_SOCKET(socket));
+
+ LOCK(&socket->lock);
+ memset(socket->name, 0, sizeof(socket->name));
+ strncpy(socket->name, name, sizeof(socket->name) - 1);
+ socket->tag = tag;
+ UNLOCK(&socket->lock);
+}
+
+const char *
+isc_socket_getname(isc_socket_t *socket) {
+ return (socket->name);
+}
+
+void *
+isc_socket_gettag(isc_socket_t *socket) {
+ return (socket->tag);
+}
+
+#ifdef HAVE_LIBXML2
+
+static const char *
+_socktype(isc_sockettype_t type)
+{
+ if (type == isc_sockettype_udp)
+ return ("udp");
+ else if (type == isc_sockettype_tcp)
+ return ("tcp");
+ else if (type == isc_sockettype_unix)
+ return ("unix");
+ else if (type == isc_sockettype_fdwatch)
+ return ("fdwatch");
+ else
+ return ("not-initialized");
+}
+
+void
+isc_socketmgr_renderxml(isc_socketmgr_t *mgr, xmlTextWriterPtr writer)
+{
+ 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
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+ xmlTextWriterWriteFormatString(writer, "%d", mgr->refs);
+ xmlTextWriterEndElement(writer);
+#endif
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "sockets");
+ sock = ISC_LIST_HEAD(mgr->socklist);
+ while (sock != NULL) {
+ LOCK(&sock->lock);
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "socket");
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "id");
+ xmlTextWriterWriteFormatString(writer, "%p", sock);
+ xmlTextWriterEndElement(writer);
+
+ if (sock->name[0] != 0) {
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "name");
+ xmlTextWriterWriteFormatString(writer, "%s",
+ sock->name);
+ xmlTextWriterEndElement(writer); /* name */
+ }
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "references");
+ xmlTextWriterWriteFormatString(writer, "%d", sock->references);
+ xmlTextWriterEndElement(writer);
+
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "type",
+ ISC_XMLCHAR _socktype(sock->type));
+
+ if (sock->connected) {
+ isc_sockaddr_format(&sock->peer_address, peerbuf,
+ sizeof(peerbuf));
+ xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "peer-address",
+ ISC_XMLCHAR peerbuf);
+ }
+
+ len = sizeof(addr);
+ if (getsockname(sock->fd, &addr.type.sa, (void *)&len) == 0) {
+ isc_sockaddr_format(&addr, peerbuf, sizeof(peerbuf));
+ xmlTextWriterWriteElement(writer,
+ ISC_XMLCHAR "local-address",
+ ISC_XMLCHAR peerbuf);
+ }
+
+ xmlTextWriterStartElement(writer, ISC_XMLCHAR "states");
+ if (sock->pending_recv)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "pending-receive");
+ if (sock->pending_send)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "pending-send");
+ if (sock->pending_accept)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "pending_accept");
+ if (sock->listener)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "listener");
+ if (sock->connected)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "connected");
+ if (sock->connecting)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "connecting");
+ if (sock->bound)
+ xmlTextWriterWriteElement(writer, ISC_XMLCHAR "state",
+ ISC_XMLCHAR "bound");
+
+ xmlTextWriterEndElement(writer); /* states */
+
+ xmlTextWriterEndElement(writer); /* socket */
+
+ UNLOCK(&sock->lock);
+ sock = ISC_LIST_NEXT(sock, link);
+ }
+ xmlTextWriterEndElement(writer); /* sockets */
+
+ UNLOCK(&mgr->lock);
+}
+#endif /* HAVE_LIBXML2 */
diff --git a/lib/isc/unix/socket_p.h b/lib/isc/unix/socket_p.h
new file mode 100644
index 0000000..fc044e5
--- /dev/null
+++ b/lib/isc/unix/socket_p.h
@@ -0,0 +1,32 @@
+/*
+ * 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
+ * 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_p.h,v 1.13 2008/06/23 23:47:11 tbox Exp $ */
+
+#ifndef ISC_SOCKET_P_H
+#define ISC_SOCKET_P_H
+
+/*! \file */
+
+#ifdef ISC_PLATFORM_NEEDSYSSELECTH
+#include <sys/select.h>
+#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 *);
+#endif /* ISC_SOCKET_P_H */
diff --git a/lib/isc/unix/stdio.c b/lib/isc/unix/stdio.c
new file mode 100644
index 0000000..4e294db
--- /dev/null
+++ b/lib/isc/unix/stdio.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2004, 2007 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: stdio.c,v 1.8 2007/06/19 23:47:18 tbox Exp $ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <isc/stdio.h>
+
+#include "errno2result.h"
+
+isc_result_t
+isc_stdio_open(const char *filename, const char *mode, FILE **fp) {
+ FILE *f;
+
+ f = fopen(filename, mode);
+ if (f == NULL)
+ return (isc__errno2result(errno));
+ *fp = f;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_stdio_close(FILE *f) {
+ int r;
+
+ r = fclose(f);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_seek(FILE *f, long offset, int whence) {
+ int r;
+
+ r = fseek(f, offset, whence);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) {
+ isc_result_t result = ISC_R_SUCCESS;
+ size_t r;
+
+ clearerr(f);
+ r = fread(ptr, size, nmemb, f);
+ if (r != nmemb) {
+ if (feof(f))
+ result = ISC_R_EOF;
+ else
+ result = isc__errno2result(errno);
+ }
+ if (nret != NULL)
+ *nret = r;
+ return (result);
+}
+
+isc_result_t
+isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f,
+ size_t *nret)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ size_t r;
+
+ clearerr(f);
+ r = fwrite(ptr, size, nmemb, f);
+ if (r != nmemb)
+ result = isc__errno2result(errno);
+ if (nret != NULL)
+ *nret = r;
+ return (result);
+}
+
+isc_result_t
+isc_stdio_flush(FILE *f) {
+ int r;
+
+ r = fflush(f);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_sync(FILE *f) {
+ int r;
+
+ r = fsync(fileno(f));
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
diff --git a/lib/isc/unix/stdtime.c b/lib/isc/unix/stdtime.c
new file mode 100644
index 0000000..c5d0c47
--- /dev/null
+++ b/lib/isc/unix/stdtime.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: stdtime.c,v 1.19 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h> /* NULL */
+#include <stdlib.h> /* NULL */
+#include <syslog.h>
+
+#include <sys/time.h>
+
+#include <isc/stdtime.h>
+#include <isc/util.h>
+
+#ifndef ISC_FIX_TV_USEC
+#define ISC_FIX_TV_USEC 1
+#endif
+
+#define US_PER_S 1000000
+
+#if ISC_FIX_TV_USEC
+static inline void
+fix_tv_usec(struct timeval *tv) {
+ isc_boolean_t fixed = ISC_FALSE;
+
+ if (tv->tv_usec < 0) {
+ fixed = ISC_TRUE;
+ do {
+ tv->tv_sec -= 1;
+ tv->tv_usec += US_PER_S;
+ } while (tv->tv_usec < 0);
+ } else if (tv->tv_usec >= US_PER_S) {
+ fixed = ISC_TRUE;
+ do {
+ tv->tv_sec += 1;
+ tv->tv_usec -= US_PER_S;
+ } while (tv->tv_usec >=US_PER_S);
+ }
+ /*
+ * Call syslog directly as we are called from the logging functions.
+ */
+ if (fixed)
+ (void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
+}
+#endif
+
+void
+isc_stdtime_get(isc_stdtime_t *t) {
+ struct timeval tv;
+
+ /*
+ * Set 't' to the number of seconds since 00:00:00 UTC, January 1,
+ * 1970.
+ */
+
+ REQUIRE(t != NULL);
+
+ RUNTIME_CHECK(gettimeofday(&tv, NULL) != -1);
+
+#if ISC_FIX_TV_USEC
+ fix_tv_usec(&tv);
+ INSIST(tv.tv_usec >= 0);
+#else
+ INSIST(tv.tv_usec >= 0 && tv.tv_usec < US_PER_S);
+#endif
+
+ *t = (unsigned int)tv.tv_sec;
+}
diff --git a/lib/isc/unix/strerror.c b/lib/isc/unix/strerror.c
new file mode 100644
index 0000000..42a7a8e
--- /dev/null
+++ b/lib/isc/unix/strerror.c
@@ -0,0 +1,74 @@
+/*
+ * 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: strerror.c,v 1.8 2007/06/19 23:47:18 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/strerror.h>
+#include <isc/util.h>
+
+#ifdef HAVE_STRERROR
+/*%
+ * We need to do this this way for profiled locks.
+ */
+static isc_mutex_t isc_strerror_lock;
+static void init_lock(void) {
+ RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS);
+}
+#else
+extern const char * const sys_errlist[];
+extern const int sys_nerr;
+#endif
+
+void
+isc__strerror(int num, char *buf, size_t size) {
+#ifdef HAVE_STRERROR
+ char *msg;
+ unsigned int unum = num;
+ static isc_once_t once = ISC_ONCE_INIT;
+
+ REQUIRE(buf != NULL);
+
+ RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS);
+
+ LOCK(&isc_strerror_lock);
+ msg = strerror(num);
+ if (msg != NULL)
+ snprintf(buf, size, "%s", msg);
+ else
+ snprintf(buf, size, "Unknown error: %u", unum);
+ UNLOCK(&isc_strerror_lock);
+#else
+ unsigned int unum = num;
+
+ REQUIRE(buf != NULL);
+
+ if (num >= 0 && num < sys_nerr)
+ snprintf(buf, size, "%s", sys_errlist[num]);
+ else
+ snprintf(buf, size, "Unknown error: %u", unum);
+#endif
+}
diff --git a/lib/isc/unix/syslog.c b/lib/isc/unix/syslog.c
new file mode 100644
index 0000000..997508e
--- /dev/null
+++ b/lib/isc/unix/syslog.c
@@ -0,0 +1,84 @@
+/*
+ * 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: syslog.c,v 1.8 2007/09/13 04:45:18 each Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <syslog.h>
+
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/syslog.h>
+#include <isc/util.h>
+
+static struct dsn_c_pvt_sfnt {
+ int val;
+ const char *strval;
+} facilities[] = {
+ { LOG_KERN, "kern" },
+ { LOG_USER, "user" },
+ { LOG_MAIL, "mail" },
+ { LOG_DAEMON, "daemon" },
+ { LOG_AUTH, "auth" },
+ { LOG_SYSLOG, "syslog" },
+ { LOG_LPR, "lpr" },
+#ifdef LOG_NEWS
+ { LOG_NEWS, "news" },
+#endif
+#ifdef LOG_UUCP
+ { LOG_UUCP, "uucp" },
+#endif
+#ifdef LOG_CRON
+ { LOG_CRON, "cron" },
+#endif
+#ifdef LOG_AUTHPRIV
+ { LOG_AUTHPRIV, "authpriv" },
+#endif
+#ifdef LOG_FTP
+ { LOG_FTP, "ftp" },
+#endif
+ { LOG_LOCAL0, "local0"},
+ { LOG_LOCAL1, "local1"},
+ { LOG_LOCAL2, "local2"},
+ { LOG_LOCAL3, "local3"},
+ { LOG_LOCAL4, "local4"},
+ { LOG_LOCAL5, "local5"},
+ { LOG_LOCAL6, "local6"},
+ { LOG_LOCAL7, "local7"},
+ { 0, NULL }
+};
+
+isc_result_t
+isc_syslog_facilityfromstring(const char *str, int *facilityp) {
+ int i;
+
+ REQUIRE(str != NULL);
+ REQUIRE(facilityp != NULL);
+
+ for (i = 0; facilities[i].strval != NULL; i++) {
+ if (strcasecmp(facilities[i].strval, str) == 0) {
+ *facilityp = facilities[i].val;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+
+}
diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c
new file mode 100644
index 0000000..59428d3
--- /dev/null
+++ b/lib/isc/unix/time.c
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2004-2008 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
+ * 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: time.c,v 1.56 2008/02/15 23:46:51 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <syslog.h>
+#include <time.h>
+
+#include <sys/time.h> /* Required for struct timeval on some platforms. */
+
+#include <isc/log.h>
+#include <isc/print.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+#define NS_PER_S 1000000000 /*%< Nanoseconds per second. */
+#define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */
+#define US_PER_S 1000000 /*%< Microseconds per second. */
+
+/*
+ * All of the INSIST()s checks of nanoseconds < NS_PER_S are for
+ * consistency checking of the type. In lieu of magic numbers, it
+ * is the best we've got. The check is only performed on functions which
+ * need an initialized type.
+ */
+
+#ifndef ISC_FIX_TV_USEC
+#define ISC_FIX_TV_USEC 1
+#endif
+
+/*%
+ *** Intervals
+ ***/
+
+static isc_interval_t zero_interval = { 0, 0 };
+isc_interval_t *isc_interval_zero = &zero_interval;
+
+#if ISC_FIX_TV_USEC
+static inline void
+fix_tv_usec(struct timeval *tv) {
+ isc_boolean_t fixed = ISC_FALSE;
+
+ if (tv->tv_usec < 0) {
+ fixed = ISC_TRUE;
+ do {
+ tv->tv_sec -= 1;
+ tv->tv_usec += US_PER_S;
+ } while (tv->tv_usec < 0);
+ } else if (tv->tv_usec >= US_PER_S) {
+ fixed = ISC_TRUE;
+ do {
+ tv->tv_sec += 1;
+ tv->tv_usec -= US_PER_S;
+ } while (tv->tv_usec >=US_PER_S);
+ }
+ /*
+ * Call syslog directly as was are called from the logging functions.
+ */
+ if (fixed)
+ (void)syslog(LOG_ERR, "gettimeofday returned bad tv_usec: corrected");
+}
+#endif
+
+void
+isc_interval_set(isc_interval_t *i,
+ unsigned int seconds, unsigned int nanoseconds)
+{
+ REQUIRE(i != NULL);
+ REQUIRE(nanoseconds < NS_PER_S);
+
+ i->seconds = seconds;
+ i->nanoseconds = nanoseconds;
+}
+
+isc_boolean_t
+isc_interval_iszero(const isc_interval_t *i) {
+ REQUIRE(i != NULL);
+ INSIST(i->nanoseconds < NS_PER_S);
+
+ if (i->seconds == 0 && i->nanoseconds == 0)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+
+/***
+ *** Absolute Times
+ ***/
+
+static isc_time_t epoch = { 0, 0 };
+isc_time_t *isc_time_epoch = &epoch;
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
+ REQUIRE(t != NULL);
+ REQUIRE(nanoseconds < NS_PER_S);
+
+ t->seconds = seconds;
+ t->nanoseconds = nanoseconds;
+}
+
+void
+isc_time_settoepoch(isc_time_t *t) {
+ REQUIRE(t != NULL);
+
+ t->seconds = 0;
+ t->nanoseconds = 0;
+}
+
+isc_boolean_t
+isc_time_isepoch(const isc_time_t *t) {
+ REQUIRE(t != NULL);
+ INSIST(t->nanoseconds < NS_PER_S);
+
+ if (t->seconds == 0 && t->nanoseconds == 0)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+
+isc_result_t
+isc_time_now(isc_time_t *t) {
+ struct timeval tv;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(t != NULL);
+
+ if (gettimeofday(&tv, NULL) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+
+ /*
+ * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
+ * then this test will generate warnings for platforms on which it is
+ * unsigned. In any event, the chances of any of these problems
+ * happening are pretty much zero, but since the libisc library ensures
+ * certain things to be true ...
+ */
+#if ISC_FIX_TV_USEC
+ fix_tv_usec(&tv);
+ if (tv.tv_sec < 0)
+ return (ISC_R_UNEXPECTED);
+#else
+ if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
+ return (ISC_R_UNEXPECTED);
+#endif
+
+ /*
+ * Ensure the tv_sec value fits in t->seconds.
+ */
+ if (sizeof(tv.tv_sec) > sizeof(t->seconds) &&
+ ((tv.tv_sec | (unsigned int)-1) ^ (unsigned int)-1) != 0U)
+ return (ISC_R_RANGE);
+
+ t->seconds = tv.tv_sec;
+ t->nanoseconds = tv.tv_usec * NS_PER_US;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
+ struct timeval tv;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(t != NULL);
+ REQUIRE(i != NULL);
+ INSIST(i->nanoseconds < NS_PER_S);
+
+ if (gettimeofday(&tv, NULL) == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "%s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+
+ /*
+ * Does POSIX guarantee the signedness of tv_sec and tv_usec? If not,
+ * then this test will generate warnings for platforms on which it is
+ * unsigned. In any event, the chances of any of these problems
+ * happening are pretty much zero, but since the libisc library ensures
+ * certain things to be true ...
+ */
+#if ISC_FIX_TV_USEC
+ fix_tv_usec(&tv);
+ if (tv.tv_sec < 0)
+ return (ISC_R_UNEXPECTED);
+#else
+ if (tv.tv_sec < 0 || tv.tv_usec < 0 || tv.tv_usec >= US_PER_S)
+ return (ISC_R_UNEXPECTED);
+#endif
+
+ /*
+ * Ensure the resulting seconds value fits in the size of an
+ * unsigned int. (It is written this way as a slight optimization;
+ * note that even if both values == INT_MAX, then when added
+ * and getting another 1 added below the result is UINT_MAX.)
+ */
+ if ((tv.tv_sec > INT_MAX || i->seconds > INT_MAX) &&
+ ((long long)tv.tv_sec + i->seconds > UINT_MAX))
+ return (ISC_R_RANGE);
+
+ t->seconds = tv.tv_sec + i->seconds;
+ t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds;
+ if (t->nanoseconds >= NS_PER_S) {
+ t->seconds++;
+ t->nanoseconds -= NS_PER_S;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+int
+isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
+ REQUIRE(t1 != NULL && t2 != NULL);
+ INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
+
+ if (t1->seconds < t2->seconds)
+ return (-1);
+ if (t1->seconds > t2->seconds)
+ return (1);
+ if (t1->nanoseconds < t2->nanoseconds)
+ return (-1);
+ if (t1->nanoseconds > t2->nanoseconds)
+ return (1);
+ return (0);
+}
+
+isc_result_t
+isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result)
+{
+ REQUIRE(t != NULL && i != NULL && result != NULL);
+ INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
+
+ /*
+ * Ensure the resulting seconds value fits in the size of an
+ * unsigned int. (It is written this way as a slight optimization;
+ * note that even if both values == INT_MAX, then when added
+ * and getting another 1 added below the result is UINT_MAX.)
+ */
+ if ((t->seconds > INT_MAX || i->seconds > INT_MAX) &&
+ ((long long)t->seconds + i->seconds > UINT_MAX))
+ return (ISC_R_RANGE);
+
+ result->seconds = t->seconds + i->seconds;
+ result->nanoseconds = t->nanoseconds + i->nanoseconds;
+ if (result->nanoseconds >= NS_PER_S) {
+ result->seconds++;
+ result->nanoseconds -= NS_PER_S;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
+ isc_time_t *result)
+{
+ REQUIRE(t != NULL && i != NULL && result != NULL);
+ INSIST(t->nanoseconds < NS_PER_S && i->nanoseconds < NS_PER_S);
+
+ if ((unsigned int)t->seconds < i->seconds ||
+ ((unsigned int)t->seconds == i->seconds &&
+ t->nanoseconds < i->nanoseconds))
+ return (ISC_R_RANGE);
+
+ result->seconds = t->seconds - i->seconds;
+ if (t->nanoseconds >= i->nanoseconds)
+ result->nanoseconds = t->nanoseconds - i->nanoseconds;
+ else {
+ result->nanoseconds = NS_PER_S - i->nanoseconds +
+ t->nanoseconds;
+ result->seconds--;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_uint64_t
+isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
+ isc_uint64_t i1, i2, i3;
+
+ REQUIRE(t1 != NULL && t2 != NULL);
+ INSIST(t1->nanoseconds < NS_PER_S && t2->nanoseconds < NS_PER_S);
+
+ i1 = (isc_uint64_t)t1->seconds * NS_PER_S + t1->nanoseconds;
+ i2 = (isc_uint64_t)t2->seconds * NS_PER_S + t2->nanoseconds;
+
+ if (i1 <= i2)
+ return (0);
+
+ i3 = i1 - i2;
+
+ /*
+ * Convert to microseconds.
+ */
+ i3 = (i1 - i2) / NS_PER_US;
+
+ return (i3);
+}
+
+isc_uint32_t
+isc_time_seconds(const isc_time_t *t) {
+ REQUIRE(t != NULL);
+ INSIST(t->nanoseconds < NS_PER_S);
+
+ return ((isc_uint32_t)t->seconds);
+}
+
+isc_result_t
+isc_time_secondsastimet(const isc_time_t *t, time_t *secondsp) {
+ isc_uint64_t i;
+ time_t seconds;
+
+ REQUIRE(t != NULL);
+ INSIST(t->nanoseconds < NS_PER_S);
+
+ /*
+ * Ensure that the number of seconds represented by t->seconds
+ * can be represented by a time_t. Since t->seconds is an unsigned
+ * int and since time_t is mostly opaque, this is trickier than
+ * it seems. (This standardized opaqueness of time_t is *very*
+ * frustrating; time_t is not even limited to being an integral
+ * type.)
+ *
+ * The mission, then, is to avoid generating any kind of warning
+ * about "signed versus unsigned" while trying to determine if the
+ * the unsigned int t->seconds is out range for tv_sec, which is
+ * pretty much only true if time_t is a signed integer of the same
+ * size as the return value of isc_time_seconds.
+ *
+ * The use of the 64 bit integer ``i'' takes advantage of C's
+ * conversion rules to either zero fill or sign extend the widened
+ * type.
+ *
+ * Solaris 5.6 gives this warning about the left shift:
+ * warning: integer overflow detected: op "<<"
+ * if the U(nsigned) qualifier is not on the 1.
+ */
+ seconds = (time_t)t->seconds;
+
+ INSIST(sizeof(unsigned int) == sizeof(isc_uint32_t));
+ INSIST(sizeof(time_t) >= sizeof(isc_uint32_t));
+
+ if (sizeof(time_t) == sizeof(isc_uint32_t) && /* Same size. */
+ (time_t)0.5 != 0.5 && /* Not a floating point type. */
+ (i = (time_t)-1) != 4294967295u && /* Is signed. */
+ (seconds &
+ (1U << (sizeof(time_t) * CHAR_BIT - 1))) != 0U) { /* Negative. */
+ /*
+ * This UNUSED() is here to shut up the IRIX compiler:
+ * variable "i" was set but never used
+ * when the value of i *was* used in the third test.
+ * (Let's hope the compiler got the actual test right.)
+ */
+ UNUSED(i);
+ return (ISC_R_RANGE);
+ }
+
+ *secondsp = seconds;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_uint32_t
+isc_time_nanoseconds(const isc_time_t *t) {
+ REQUIRE(t != NULL);
+
+ ENSURE(t->nanoseconds < NS_PER_S);
+
+ return ((isc_uint32_t)t->nanoseconds);
+}
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+ time_t now;
+ unsigned int flen;
+
+ REQUIRE(len > 0);
+
+ now = (time_t) t->seconds;
+ flen = strftime(buf, len, "%d-%b-%Y %X", localtime(&now));
+ INSIST(flen < len);
+ if (flen != 0)
+ snprintf(buf + flen, len - flen,
+ ".%03u", t->nanoseconds / 1000000);
+ else
+ snprintf(buf, len, "99-Bad-9999 99:99:99.999");
+}
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+ time_t now;
+ unsigned int flen;
+
+ REQUIRE(len > 0);
+
+ now = (time_t)t->seconds;
+ flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now));
+ INSIST(flen < len);
+}
+
+void
+isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len) {
+ time_t now;
+ unsigned int flen;
+
+ REQUIRE(len > 0);
+
+ now = (time_t)t->seconds;
+ flen = strftime(buf, len, "%Y-%m-%dT%H:%M:%SZ", gmtime(&now));
+ INSIST(flen < len);
+}
diff --git a/lib/isc/version.c b/lib/isc/version.c
new file mode 100644
index 0000000..bfe4d6d
--- /dev/null
+++ b/lib/isc/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: version.c,v 1.15 2007/06/19 23:47:17 tbox Exp $ */
+
+/*! \file */
+
+#include <isc/version.h>
+
+const char isc_version[] = VERSION;
+
+const unsigned int isc_libinterface = LIBINTERFACE;
+const unsigned int isc_librevision = LIBREVISION;
+const unsigned int isc_libage = LIBAGE;
diff --git a/lib/isc/win32/DLLMain.c b/lib/isc/win32/DLLMain.c
new file mode 100644
index 0000000..ed84fcf
--- /dev/null
+++ b/lib/isc/win32/DLLMain.c
@@ -0,0 +1,58 @@
+/*
+ * 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: DLLMain.c,v 1.7 2007/06/18 23:47:49 tbox Exp $ */
+
+#include <windows.h>
+#include <stdio.h>
+
+/*
+ * Called when we enter the DLL
+ */
+__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ /*
+ * The DLL is loading due to process
+ * initialization or a call to LoadLibrary.
+ */
+ case DLL_PROCESS_ATTACH:
+ break;
+
+ /* The attached process creates a new thread. */
+ case DLL_THREAD_ATTACH:
+ break;
+
+ /* The thread of the attached process terminates. */
+ case DLL_THREAD_DETACH:
+ break;
+
+ /*
+ * The DLL is unloading from a process due to
+ * process termination or a call to FreeLibrary.
+ */
+ case DLL_PROCESS_DETACH:
+ break;
+
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
diff --git a/lib/isc/win32/Makefile.in b/lib/isc/win32/Makefile.in
new file mode 100644
index 0000000..5c71dff
--- /dev/null
+++ b/lib/isc/win32/Makefile.in
@@ -0,0 +1,40 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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.11 2007/06/19 23:47:19 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+CINCLUDES = -I${srcdir}/.. \
+ -I./include \
+ -I${srcdir}/include \
+ -I${srcdir}/../include
+CDEFINES =
+CWARNINGS =
+
+# Alphabetically
+OBJS = condition.@O@ dir.@O@ file.@O@ fsaccess.@O@ once.@O@ \
+ stdtime.@O@ thread.@O@ time.@O@
+
+# Alphabetically
+SRCS = condition.c dir.c file.c once.c fsaccess.c \
+ stdtime.c thread.c time.c
+
+SUBDIRS = include
+TARGETS = ${OBJS}
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/win32/app.c b/lib/isc/win32/app.c
new file mode 100644
index 0000000..b0db90d
--- /dev/null
+++ b/lib/isc/win32/app.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: app.c,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <process.h>
+
+#include <isc/app.h>
+#include <isc/boolean.h>
+#include <isc/condition.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/event.h>
+#include <isc/platform.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/time.h>
+#include <isc/util.h>
+#include <isc/thread.h>
+
+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.
+ */
+static isc_boolean_t want_shutdown = ISC_FALSE;
+/*
+ * We assume that 'want_reload' can be read and written atomically.
+ */
+static isc_boolean_t want_reload = ISC_FALSE;
+
+static isc_boolean_t blocked = ISC_FALSE;
+
+static isc_thread_t blockedthread;
+
+/* Events to wait for */
+
+#define NUM_EVENTS 2
+
+enum {
+ RELOAD_EVENT,
+ SHUTDOWN_EVENT
+};
+
+static HANDLE hEvents[NUM_EVENTS];
+DWORD dwWaitResult;
+
+/*
+ * We need to remember which thread is the main thread...
+ */
+static isc_thread_t main_thread;
+
+isc_result_t
+isc_app_start(void) {
+ isc_result_t result;
+
+ /*
+ * Start an ISC library application.
+ */
+
+ main_thread = GetCurrentThread();
+
+ result = isc_mutex_init(&lock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /* Create the reload event in a non-signaled state */
+ hEvents[RELOAD_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ /* Create the shutdown event in a non-signaled state */
+ hEvents[SHUTDOWN_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ 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,
+ void *arg) {
+ isc_event_t *event;
+ isc_task_t *cloned_task = NULL;
+ isc_result_t result;
+
+
+ LOCK(&lock);
+ if (running) {
+ result = ISC_R_ALREADYRUNNING;
+ goto unlock;
+ }
+
+ /*
+ * Note that we store the task to which we're going to send the event
+ * in the event's "sender" field.
+ */
+ isc_task_attach(task, &cloned_task);
+ event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
+ action, arg, sizeof(*event));
+ if (event == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto unlock;
+ }
+
+ ISC_LIST_APPEND(on_run, event, ev_link);
+ result = ISC_R_SUCCESS;
+
+ unlock:
+ UNLOCK(&lock);
+ return (result);
+}
+
+isc_result_t
+isc_app_run(void) {
+ isc_event_t *event, *next_event;
+ isc_task_t *task;
+ HANDLE *pHandles = NULL;
+
+ REQUIRE(main_thread == GetCurrentThread());
+ LOCK(&lock);
+ if (!running) {
+ running = ISC_TRUE;
+
+ /*
+ * Post any on-run events (in FIFO order).
+ */
+ for (event = ISC_LIST_HEAD(on_run);
+ event != NULL;
+ event = next_event) {
+ next_event = ISC_LIST_NEXT(event, ev_link);
+ ISC_LIST_UNLINK(on_run, event, ev_link);
+ task = event->ev_sender;
+ event->ev_sender = NULL;
+ isc_task_sendanddetach(&task, &event);
+ }
+
+ }
+
+ UNLOCK(&lock);
+
+ /*
+ * There is no danger if isc_app_shutdown() is called before we wait
+ * for events.
+ */
+
+ while (!want_shutdown) {
+ dwWaitResult = WaitForMultipleObjects(NUM_EVENTS, hEvents,
+ FALSE, INFINITE);
+
+ /* See why we returned */
+
+ if (WaitSucceeded(dwWaitResult, NUM_EVENTS)) {
+ /*
+ * The return was due to one of the events
+ * being signaled
+ */
+ switch (WaitSucceededIndex(dwWaitResult)) {
+ case RELOAD_EVENT:
+ want_reload = ISC_TRUE;
+ break;
+
+ case SHUTDOWN_EVENT:
+ want_shutdown = ISC_TRUE;
+ break;
+ }
+ }
+ if (want_reload) {
+ want_reload = ISC_FALSE;
+ return (ISC_R_RELOAD);
+ }
+
+ if (want_shutdown && blocked)
+ exit(-1);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_shutdown(void) {
+ isc_boolean_t want_kill = ISC_TRUE;
+
+ LOCK(&lock);
+ REQUIRE(running);
+
+ if (shutdown_requested)
+ want_kill = ISC_FALSE; /* We're only signaling once */
+ else
+ shutdown_requested = ISC_TRUE;
+
+ UNLOCK(&lock);
+ if (want_kill)
+ SetEvent(hEvents[SHUTDOWN_EVENT]);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_app_reload(void) {
+ isc_boolean_t want_reload = ISC_TRUE;
+
+ LOCK(&lock);
+ REQUIRE(running);
+
+ /*
+ * Don't send the reload signal if we're shutting down.
+ */
+ if (shutdown_requested)
+ want_reload = ISC_FALSE;
+
+ UNLOCK(&lock);
+ if (want_reload)
+ SetEvent(hEvents[RELOAD_EVENT]);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_app_finish(void) {
+ DESTROYLOCK(&lock);
+}
+
+void
+isc_app_block(void) {
+ REQUIRE(running);
+ REQUIRE(!blocked);
+
+ blocked = ISC_TRUE;
+ blockedthread = GetCurrentThread();
+}
+
+void
+isc_app_unblock(void) {
+ REQUIRE(running);
+ REQUIRE(blocked);
+ blocked = ISC_FALSE;
+ REQUIRE(blockedthread == GetCurrentThread());
+}
diff --git a/lib/isc/win32/condition.c b/lib/isc/win32/condition.c
new file mode 100644
index 0000000..27d4e76
--- /dev/null
+++ b/lib/isc/win32/condition.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: condition.c,v 1.23 2007/06/18 23:47:49 tbox Exp $ */
+
+#include <config.h>
+
+#include <isc/condition.h>
+#include <isc/assertions.h>
+#include <isc/util.h>
+#include <isc/thread.h>
+#include <isc/time.h>
+
+#define LSIGNAL 0
+#define LBROADCAST 1
+
+isc_result_t
+isc_condition_init(isc_condition_t *cond) {
+ HANDLE h;
+
+ REQUIRE(cond != NULL);
+
+ cond->waiters = 0;
+ /*
+ * This handle is shared across all threads
+ */
+ h = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (h == NULL) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+ cond->events[LSIGNAL] = h;
+
+ /*
+ * The threadlist will hold the actual events needed
+ * for the wait condition
+ */
+ ISC_LIST_INIT(cond->threadlist);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Add the thread to the threadlist along with the required events
+ */
+static isc_result_t
+register_thread(unsigned long thrd, isc_condition_t *gblcond,
+ isc_condition_thread_t **localcond)
+{
+ HANDLE hc;
+ isc_condition_thread_t *newthread;
+
+ REQUIRE(localcond != NULL && *localcond == NULL);
+
+ newthread = malloc(sizeof(isc_condition_thread_t));
+ if (newthread == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /*
+ * Create the thread-specific handle
+ */
+ hc = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (hc == NULL) {
+ free(newthread);
+ return (ISC_R_UNEXPECTED);
+ }
+
+ /*
+ * Add the thread ID and handles to list of threads for broadcast
+ */
+ newthread->handle[LSIGNAL] = gblcond->events[LSIGNAL];
+ newthread->handle[LBROADCAST] = hc;
+ newthread->th = thrd;
+
+ /*
+ * The thread is holding the manager lock so this is safe
+ */
+ ISC_LIST_APPEND(gblcond->threadlist, newthread, link);
+ *localcond = newthread;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+find_thread_condition(unsigned long thrd, isc_condition_t *cond,
+ isc_condition_thread_t **threadcondp)
+{
+ isc_condition_thread_t *threadcond;
+
+ REQUIRE(threadcondp != NULL && *threadcondp == NULL);
+
+ /*
+ * Look for the thread ID.
+ */
+ for (threadcond = ISC_LIST_HEAD(cond->threadlist);
+ threadcond != NULL;
+ threadcond = ISC_LIST_NEXT(threadcond, link)) {
+
+ if (threadcond->th == thrd) {
+ *threadcondp = threadcond;
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ /*
+ * Not found, so add it.
+ */
+ return (register_thread(thrd, cond, threadcondp));
+}
+
+isc_result_t
+isc_condition_signal(isc_condition_t *cond) {
+
+ /*
+ * Unlike pthreads, the caller MUST hold the lock associated with
+ * the condition variable when calling us.
+ */
+ REQUIRE(cond != NULL);
+
+ if (!SetEvent(cond->events[LSIGNAL])) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_condition_broadcast(isc_condition_t *cond) {
+
+ isc_condition_thread_t *threadcond;
+ isc_boolean_t failed = ISC_FALSE;
+
+ /*
+ * Unlike pthreads, the caller MUST hold the lock associated with
+ * the condition variable when calling us.
+ */
+ REQUIRE(cond != NULL);
+
+ /*
+ * Notify every thread registered for this
+ */
+ for (threadcond = ISC_LIST_HEAD(cond->threadlist);
+ threadcond != NULL;
+ threadcond = ISC_LIST_NEXT(threadcond, link)) {
+
+ if (!SetEvent(threadcond->handle[LBROADCAST]))
+ failed = ISC_TRUE;
+ }
+
+ if (failed)
+ return (ISC_R_UNEXPECTED);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_condition_destroy(isc_condition_t *cond) {
+
+ isc_condition_thread_t *next, *threadcond;
+
+ REQUIRE(cond != NULL);
+ REQUIRE(cond->waiters == 0);
+
+ (void)CloseHandle(cond->events[LSIGNAL]);
+
+ /*
+ * Delete the threadlist
+ */
+ threadcond = ISC_LIST_HEAD(cond->threadlist);
+
+ while (threadcond != NULL) {
+ next = ISC_LIST_NEXT(threadcond, link);
+ DEQUEUE(cond->threadlist, threadcond, link);
+ (void) CloseHandle(threadcond->handle[LBROADCAST]);
+ free(threadcond);
+ threadcond = next;
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This is always called when the mutex (lock) is held, but because
+ * we are waiting we need to release it and reacquire it as soon as the wait
+ * is over. This allows other threads to make use of the object guarded
+ * by the mutex but it should never try to delete it as long as the
+ * number of waiters > 0. Always reacquire the mutex regardless of the
+ * result of the wait. Note that EnterCriticalSection will wait to acquire
+ * the mutex.
+ */
+static isc_result_t
+wait(isc_condition_t *cond, isc_mutex_t *mutex, DWORD milliseconds) {
+ DWORD result;
+ isc_result_t tresult;
+ isc_condition_thread_t *threadcond = NULL;
+
+ /*
+ * Get the thread events needed for the wait
+ */
+ tresult = find_thread_condition(isc_thread_self(), cond, &threadcond);
+ if (tresult != ISC_R_SUCCESS)
+ return (tresult);
+
+ cond->waiters++;
+ LeaveCriticalSection(mutex);
+ result = WaitForMultipleObjects(2, threadcond->handle, FALSE,
+ milliseconds);
+ EnterCriticalSection(mutex);
+ cond->waiters--;
+ if (result == WAIT_FAILED) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+ if (result == WAIT_TIMEOUT)
+ return (ISC_R_TIMEDOUT);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_condition_wait(isc_condition_t *cond, isc_mutex_t *mutex) {
+ return (wait(cond, mutex, INFINITE));
+}
+
+isc_result_t
+isc_condition_waituntil(isc_condition_t *cond, isc_mutex_t *mutex,
+ isc_time_t *t) {
+ DWORD milliseconds;
+ isc_uint64_t microseconds;
+ isc_time_t now;
+
+ if (isc_time_now(&now) != ISC_R_SUCCESS) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+
+ microseconds = isc_time_microdiff(t, &now);
+ if (microseconds > 0xFFFFFFFFi64 * 1000)
+ milliseconds = 0xFFFFFFFF;
+ else
+ milliseconds = (DWORD)(microseconds / 1000);
+
+ return (wait(cond, mutex, milliseconds));
+}
diff --git a/lib/isc/win32/dir.c b/lib/isc/win32/dir.c
new file mode 100644
index 0000000..93cc650
--- /dev/null
+++ b/lib/isc/win32/dir.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: dir.c,v 1.16 2008/11/02 23:47:01 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#include <config.h>
+
+#include <string.h>
+#include <direct.h>
+#include <process.h>
+#include <io.h>
+
+#include <sys/stat.h>
+
+#include <isc/dir.h>
+#include <isc/magic.h>
+#include <isc/assertions.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+#define ISC_DIR_MAGIC ISC_MAGIC('D', 'I', 'R', '*')
+#define VALID_DIR(dir) ISC_MAGIC_VALID(dir, ISC_DIR_MAGIC)
+
+static isc_result_t
+start_directory(isc_dir_t *p);
+
+void
+isc_dir_init(isc_dir_t *dir) {
+ REQUIRE(dir != NULL);
+
+ dir->dirname[0] = '\0';
+
+ dir->entry.name[0] = '\0';
+ dir->entry.length = 0;
+ memset(&(dir->entry.find_data), 0, sizeof(dir->entry.find_data));
+
+ dir->entry_filled = ISC_FALSE;
+ dir->search_handle = INVALID_HANDLE_VALUE;
+
+ dir->magic = ISC_DIR_MAGIC;
+}
+
+/*
+ * Allocate workspace and open directory stream. If either one fails,
+ * NULL will be returned.
+ */
+isc_result_t
+isc_dir_open(isc_dir_t *dir, const char *dirname) {
+ char *p;
+ isc_result_t result;
+
+ REQUIRE(dirname != NULL);
+ REQUIRE(VALID_DIR(dir) && dir->search_handle == INVALID_HANDLE_VALUE);
+
+ /*
+ * Copy directory name. Need to have enough space for the name,
+ * a possible path separator, the wildcard, and the final NUL.
+ */
+ if (strlen(dirname) + 3 > sizeof(dir->dirname))
+ /* XXXDCL ? */
+ return (ISC_R_NOSPACE);
+ strcpy(dir->dirname, dirname);
+
+ /*
+ * Append path separator, if needed, and "*".
+ */
+ p = dir->dirname + strlen(dir->dirname);
+ if (dir->dirname < p && *(p - 1) != '\\' && *(p - 1) != ':')
+ *p++ = '\\';
+ *p++ = '*';
+ *p++ = '\0';
+
+ /*
+ * Open stream.
+ */
+ result = start_directory(dir);
+
+ return (result);
+}
+
+/*
+ * Return previously retrieved file or get next one. Unix's dirent has
+ * separate open and read functions, but the Win32 and DOS interfaces open
+ * the dir stream and reads the first file in one operation.
+ */
+isc_result_t
+isc_dir_read(isc_dir_t *dir) {
+ REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
+
+ if (dir->entry_filled)
+ /*
+ * start_directory() already filled in the first entry.
+ */
+ dir->entry_filled = ISC_FALSE;
+
+ else {
+ /*
+ * Fetch next file in directory.
+ */
+ if (FindNextFile(dir->search_handle,
+ &dir->entry.find_data) == FALSE)
+ /*
+ * Either the last file has been processed or
+ * an error has occured. The former is not
+ * really an error, but the latter is.
+ */
+ if (GetLastError() == ERROR_NO_MORE_FILES)
+ return (ISC_R_NOMORE);
+ else
+ return (ISC_R_UNEXPECTED);
+ }
+
+ /*
+ * Make sure that the space for the name is long enough.
+ */
+ strcpy(dir->entry.name, dir->entry.find_data.cFileName);
+ dir->entry.length = strlen(dir->entry.name);
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Close directory stream.
+ */
+void
+isc_dir_close(isc_dir_t *dir) {
+ REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
+
+ FindClose(dir->search_handle);
+ dir->search_handle = INVALID_HANDLE_VALUE;
+}
+
+/*
+ * Reposition directory stream at start.
+ */
+isc_result_t
+isc_dir_reset(isc_dir_t *dir) {
+ isc_result_t result;
+
+ REQUIRE(VALID_DIR(dir) && dir->search_handle != INVALID_HANDLE_VALUE);
+ REQUIRE(dir->dirname != NULL);
+
+ /*
+ * NT cannot reposition the seek pointer to the beginning of the
+ * the directory stream, but rather the directory needs to be
+ * closed and reopened. The latter might fail.
+ */
+
+ isc_dir_close(dir);
+
+ result = start_directory(dir);
+
+ return (result);
+}
+
+/*
+ * Initialize isc_dir_t structure with new directory. The function
+ * returns 0 on failure and nonzero on success.
+ *
+ * Note:
+ * - Be sure to close previous stream before opening new one
+ */
+static isc_result_t
+start_directory(isc_dir_t *dir)
+{
+ REQUIRE(VALID_DIR(dir));
+ REQUIRE(dir->search_handle == INVALID_HANDLE_VALUE);
+
+ dir->entry_filled = ISC_FALSE;
+
+ /*
+ * Open stream and retrieve first file.
+ */
+ dir->search_handle = FindFirstFile(dir->dirname,
+ &dir->entry.find_data);
+
+ if (dir->search_handle == INVALID_HANDLE_VALUE) {
+ /*
+ * Something went wrong but we don't know what. GetLastError()
+ * could give us more information about the error, but the
+ * MSDN documentation is frustratingly thin about what
+ * possible errors could have resulted. (Score one for
+ * the Unix manual pages.) So there is just this lame error
+ * instead of being able to differentiate ISC_R_NOTFOUND
+ * from ISC_R_UNEXPECTED.
+ */
+ return (ISC_R_FAILURE);
+ }
+
+ /*
+ * Make sure that the space for the name is long enough.
+ */
+ INSIST(sizeof(dir->entry.name) >
+ strlen(dir->entry.find_data.cFileName));
+
+ /*
+ * Fill in the data for the first entry of the directory.
+ */
+ strcpy(dir->entry.name, dir->entry.find_data.cFileName);
+ dir->entry.length = strlen(dir->entry.name);
+
+ dir->entry_filled = ISC_TRUE;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_chdir(const char *dirname) {
+ /*
+ * Change the current directory to 'dirname'.
+ */
+
+ REQUIRE(dirname != NULL);
+
+ if (chdir(dirname) < 0)
+ return (isc__errno2result(errno));
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_dir_chroot(const char *dirname) {
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+isc_result_t
+isc_dir_createunique(char *templet) {
+ isc_result_t result;
+ char *x;
+ char *p;
+ int i;
+ int pid;
+
+ REQUIRE(templet != NULL);
+
+ /*
+ * mkdtemp is not portable, so this emulates it.
+ */
+
+ pid = getpid();
+
+ /*
+ * Replace trailing Xs with the process-id, zero-filled.
+ */
+ for (x = templet + strlen(templet) - 1; *x == 'X' && x >= templet;
+ x--, pid /= 10)
+ *x = pid % 10 + '0';
+
+ x++; /* Set x to start of ex-Xs. */
+
+ do {
+ i = mkdir(templet);
+ i = chmod(templet, 0700);
+
+ if (i == 0 || errno != EEXIST)
+ break;
+
+ /*
+ * The BSD algorithm.
+ */
+ p = x;
+ while (*p != '\0') {
+ if (isdigit(*p & 0xff))
+ *p = 'a';
+ else if (*p != 'z')
+ ++*p;
+ else {
+ /*
+ * Reset character and move to next.
+ */
+ *p++ = 'a';
+ continue;
+ }
+
+ break;
+ }
+
+ if (*p == '\0') {
+ /*
+ * Tried all combinations. errno should already
+ * be EEXIST, but ensure it is anyway for
+ * isc__errno2result().
+ */
+ errno = EEXIST;
+ break;
+ }
+ } while (1);
+
+ if (i == -1)
+ result = isc__errno2result(errno);
+ else
+ result = ISC_R_SUCCESS;
+
+ return (result);
+}
diff --git a/lib/isc/win32/entropy.c b/lib/isc/win32/entropy.c
new file mode 100644
index 0000000..a505ab3
--- /dev/null
+++ b/lib/isc/win32/entropy.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: entropy.c,v 1.8 2007/06/19 23:47:19 tbox Exp $ */
+
+/*
+ * This is the system depenedent part of the ISC entropy API.
+ */
+
+#include <config.h>
+
+#include <windows.h>
+#include <wincrypt.h>
+
+#include <process.h>
+#include <io.h>
+#include <share.h>
+
+/*
+ * There is only one variable in the entropy data structures that is not
+ * system independent, but pulling the structure that uses it into this file
+ * ultimately means pulling several other independent structures here also to
+ * resolve their interdependencies. Thus only the problem variable's type
+ * is defined here.
+ */
+#define FILESOURCE_HANDLE_TYPE HCRYPTPROV
+
+typedef struct {
+ int dummy;
+} isc_entropyusocketsource_t;
+
+#include "../entropy.c"
+
+static unsigned int
+get_from_filesource(isc_entropysource_t *source, isc_uint32_t desired) {
+ isc_entropy_t *ent = source->ent;
+ unsigned char buf[128];
+ HCRYPTPROV hcryptprov = source->sources.file.handle;
+ ssize_t ndesired;
+ unsigned int added;
+
+ if (source->bad)
+ return (0);
+
+ desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
+
+ added = 0;
+ while (desired > 0) {
+ ndesired = ISC_MIN(desired, sizeof(buf));
+ if (!CryptGenRandom(hcryptprov, ndesired, buf)) {
+ CryptReleaseContext(hcryptprov, 0);
+ source->bad = ISC_TRUE;
+ goto out;
+ }
+
+ entropypool_adddata(ent, buf, ndesired, ndesired * 8);
+ added += ndesired * 8;
+ desired -= ndesired;
+ }
+
+ out:
+ return (added);
+}
+
+/*
+ * Poll each source, trying to get data from it to stuff into the entropy
+ * pool.
+ */
+static void
+fillpool(isc_entropy_t *ent, unsigned int desired, isc_boolean_t blocking) {
+ unsigned int added;
+ unsigned int remaining;
+ unsigned int needed;
+ unsigned int nsource;
+ isc_entropysource_t *source;
+ isc_entropysource_t *firstsource;
+
+ REQUIRE(VALID_ENTROPY(ent));
+
+ needed = desired;
+
+ /*
+ * This logic is a little strange, so an explanation is in order.
+ *
+ * If needed is 0, it means we are being asked to "fill to whatever
+ * we think is best." This means that if we have at least a
+ * partially full pool (say, > 1/4th of the pool) we probably don't
+ * need to add anything.
+ *
+ * Also, we will check to see if the "pseudo" count is too high.
+ * If it is, try to mix in better data. Too high is currently
+ * defined as 1/4th of the pool.
+ *
+ * Next, if we are asked to add a specific bit of entropy, make
+ * certain that we will do so. Clamp how much we try to add to
+ * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy).
+ *
+ * Note that if we are in a blocking mode, we will only try to
+ * get as much data as we need, not as much as we might want
+ * to build up.
+ */
+ if (needed == 0) {
+ REQUIRE(!blocking);
+
+ if ((ent->pool.entropy >= RND_POOLBITS / 4)
+ && (ent->pool.pseudo <= RND_POOLBITS / 4))
+ return;
+
+ needed = THRESHOLD_BITS * 4;
+ } else {
+ needed = ISC_MAX(needed, THRESHOLD_BITS);
+ needed = ISC_MIN(needed, RND_POOLBITS);
+ }
+
+ /*
+ * In any case, clamp how much we need to how much we can add.
+ */
+ needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy);
+
+ /*
+ * But wait! If we're not yet initialized, we need at least
+ * THRESHOLD_BITS
+ * of randomness.
+ */
+ if (ent->initialized < THRESHOLD_BITS)
+ needed = ISC_MAX(needed, THRESHOLD_BITS - ent->initialized);
+
+ /*
+ * Poll each file source to see if we can read anything useful from
+ * it. XXXMLG When where are multiple sources, we should keep a
+ * record of which one we last used so we can start from it (or the
+ * next one) to avoid letting some sources build up entropy while
+ * others are always drained.
+ */
+
+ added = 0;
+ remaining = needed;
+ if (ent->nextsource == NULL) {
+ ent->nextsource = ISC_LIST_HEAD(ent->sources);
+ if (ent->nextsource == NULL)
+ return;
+ }
+ source = ent->nextsource;
+ /*
+ * Remember the first source so we can break if we have looped back to
+ * the beginning and still have nothing
+ */
+ firstsource = source;
+ again_file:
+ for (nsource = 0; nsource < ent->nsources; nsource++) {
+ unsigned int got;
+
+ if (remaining == 0)
+ break;
+
+ got = 0;
+
+ if (source->type == ENTROPY_SOURCETYPE_FILE)
+ got = get_from_filesource(source, remaining);
+
+ added += got;
+
+ remaining -= ISC_MIN(remaining, got);
+
+ source = ISC_LIST_NEXT(source, link);
+ if (source == NULL)
+ source = ISC_LIST_HEAD(ent->sources);
+ }
+ ent->nextsource = source;
+
+ /*
+ * Go again only if there's been progress and we've not
+ * gone back to the beginning
+ */
+ if (!(ent->nextsource == firstsource && added == 0)) {
+ if (blocking && remaining != 0) {
+ goto again_file;
+ }
+ }
+
+ /*
+ * Here, if there are bits remaining to be had and we can block,
+ * check to see if we have a callback source. If so, call them.
+ */
+ source = ISC_LIST_HEAD(ent->sources);
+ while ((remaining != 0) && (source != NULL)) {
+ unsigned int got;
+
+ got = 0;
+
+ if (source->type == ENTROPY_SOURCETYPE_CALLBACK)
+ got = get_from_callback(source, remaining, blocking);
+
+ added += got;
+ remaining -= ISC_MIN(remaining, got);
+
+ if (added >= needed)
+ break;
+
+ source = ISC_LIST_NEXT(source, link);
+ }
+
+ /*
+ * Mark as initialized if we've added enough data.
+ */
+ if (ent->initialized < THRESHOLD_BITS)
+ ent->initialized += added;
+}
+
+
+
+/*
+ * Requires "ent" be locked.
+ */
+static void
+destroyfilesource(isc_entropyfilesource_t *source) {
+ CryptReleaseContext(source->handle, 0);
+}
+
+static void
+destroyusocketsource(isc_entropyusocketsource_t *source) {
+ UNUSED(source);
+}
+
+
+isc_result_t
+isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) {
+ isc_result_t ret;
+ isc_entropysource_t *source;
+ HCRYPTPROV hcryptprov;
+ DWORD errval;
+ BOOL err;
+
+ REQUIRE(VALID_ENTROPY(ent));
+ REQUIRE(fname != NULL);
+
+ LOCK(&ent->lock);
+
+ source = NULL;
+
+ /*
+ * The first time we just try to acquire the context
+ */
+ err = CryptAcquireContext(&hcryptprov, NULL, NULL, PROV_RSA_FULL,
+ CRYPT_VERIFYCONTEXT);
+ if (!err){
+ errval = GetLastError();
+ ret = ISC_R_IOERROR;
+ goto errout;
+ }
+
+ source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
+ if (source == NULL) {
+ ret = ISC_R_NOMEMORY;
+ goto closecontext;
+ }
+
+ /*
+ * From here down, no failures can occur.
+ */
+ source->magic = SOURCE_MAGIC;
+ source->type = ENTROPY_SOURCETYPE_FILE;
+ source->ent = ent;
+ source->total = 0;
+ source->bad = ISC_FALSE;
+ memset(source->name, 0, sizeof(source->name));
+ ISC_LINK_INIT(source, link);
+ source->sources.file.handle = hcryptprov;
+
+ /*
+ * Hook it into the entropy system.
+ */
+ ISC_LIST_APPEND(ent->sources, source, link);
+ ent->nsources++;
+
+ UNLOCK(&ent->lock);
+ return (ISC_R_SUCCESS);
+
+ closecontext:
+ CryptReleaseContext(hcryptprov, 0);
+
+ errout:
+ if (source != NULL)
+ isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t));
+
+ UNLOCK(&ent->lock);
+
+ return (ret);
+}
+
+
+
+
diff --git a/lib/isc/win32/errno2result.c b/lib/isc/win32/errno2result.c
new file mode 100644
index 0000000..c3d54d6
--- /dev/null
+++ b/lib/isc/win32/errno2result.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: errno2result.c,v 1.17 2008/09/12 04:46:25 marka Exp $ */
+
+#include <config.h>
+
+#include <winsock2.h>
+#include "errno2result.h"
+#include <isc/result.h>
+#include <isc/strerror.h>
+#include <isc/util.h>
+
+/*
+ * Convert a POSIX errno value into an isc_result_t. The
+ * list of supported errno values is not complete; new users
+ * of this function should add any expected errors that are
+ * not already there.
+ */
+isc_result_t
+isc__errno2resultx(int posixerrno, const char *file, int line) {
+ char strbuf[ISC_STRERRORSIZE];
+
+ switch (posixerrno) {
+ case ENOTDIR:
+ case WSAELOOP:
+ case WSAEINVAL:
+ case EINVAL: /* XXX sometimes this is not for files */
+ case ENAMETOOLONG:
+ case WSAENAMETOOLONG:
+ case EBADF:
+ case WSAEBADF:
+ return (ISC_R_INVALIDFILE);
+ case ENOENT:
+ return (ISC_R_FILENOTFOUND);
+ case EACCES:
+ case WSAEACCES:
+ case EPERM:
+ return (ISC_R_NOPERM);
+ case EEXIST:
+ return (ISC_R_FILEEXISTS);
+ case EIO:
+ return (ISC_R_IOERROR);
+ case ENOMEM:
+ return (ISC_R_NOMEMORY);
+ case ENFILE:
+ case EMFILE:
+ case WSAEMFILE:
+ return (ISC_R_TOOMANYOPENFILES);
+ case ERROR_CANCELLED:
+ return (ISC_R_CANCELED);
+ case ERROR_CONNECTION_REFUSED:
+ case WSAECONNREFUSED:
+ return (ISC_R_CONNREFUSED);
+ case WSAENOTCONN:
+ case ERROR_CONNECTION_INVALID:
+ return (ISC_R_NOTCONNECTED);
+ case ERROR_HOST_UNREACHABLE:
+ case WSAEHOSTUNREACH:
+ return (ISC_R_HOSTUNREACH);
+ case ERROR_NETWORK_UNREACHABLE:
+ case WSAENETUNREACH:
+ return (ISC_R_NETUNREACH);
+ case ERROR_NO_NETWORK:
+ return (ISC_R_NETUNREACH);
+ case ERROR_PORT_UNREACHABLE:
+ return (ISC_R_HOSTUNREACH);
+ case ERROR_SEM_TIMEOUT:
+ return (ISC_R_TIMEDOUT);
+ case WSAECONNRESET:
+ case WSAENETRESET:
+ case WSAECONNABORTED:
+ case WSAEDISCON:
+ case ERROR_OPERATION_ABORTED:
+ case ERROR_CONNECTION_ABORTED:
+ case ERROR_REQUEST_ABORTED:
+ return (ISC_R_CONNECTIONRESET);
+ case WSAEADDRNOTAVAIL:
+ return (ISC_R_ADDRNOTAVAIL);
+ case ERROR_NETNAME_DELETED:
+ case WSAENETDOWN:
+ return (ISC_R_NETUNREACH);
+ case WSAEHOSTDOWN:
+ return (ISC_R_HOSTUNREACH);
+ case WSAENOBUFS:
+ return (ISC_R_NORESOURCES);
+ default:
+ isc__strerror(posixerrno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(file, line, "unable to convert errno "
+ "to isc_result: %d: %s", posixerrno, strbuf);
+ /*
+ * XXXDCL would be nice if perhaps this function could
+ * return the system's error string, so the caller
+ * might have something more descriptive than "unexpected
+ * error" to log with.
+ */
+ return (ISC_R_UNEXPECTED);
+ }
+}
diff --git a/lib/isc/win32/errno2result.h b/lib/isc/win32/errno2result.h
new file mode 100644
index 0000000..41682db
--- /dev/null
+++ b/lib/isc/win32/errno2result.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: errno2result.h,v 1.10 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef UNIX_ERRNO2RESULT_H
+#define UNIX_ERRNO2RESULT_H 1
+
+/* XXXDCL this should be moved to lib/isc/include/isc/errno2result.h. */
+
+#include <errno.h> /* Provides errno. */
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+#define isc__errno2result(posixerrno) \
+ isc__errno2resultx(posixerrno, __FILE__, __LINE__)
+
+isc_result_t
+isc__errno2resultx(int posixerrno, const char *file, int line);
+
+ISC_LANG_ENDDECLS
+
+#endif /* UNIX_ERRNO2RESULT_H */
diff --git a/lib/isc/win32/file.c b/lib/isc/win32/file.c
new file mode 100644
index 0000000..baf7953
--- /dev/null
+++ b/lib/isc/win32/file.c
@@ -0,0 +1,507 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: file.c,v 1.31 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#undef rename
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <io.h>
+#include <process.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/utime.h>
+
+#include <isc/file.h>
+#include <isc/result.h>
+#include <isc/time.h>
+#include <isc/util.h>
+#include <isc/stat.h>
+
+#include "errno2result.h"
+
+/*
+ * Emulate UNIX mkstemp, which returns an open FD to the new file
+ *
+ */
+static int
+gettemp(char *path, int *doopen) {
+ char *start, *trv;
+ struct stat sbuf;
+ int pid;
+
+ trv = strrchr(path, 'X');
+ trv++;
+ pid = getpid();
+ /* extra X's get set to 0's */
+ while (*--trv == 'X') {
+ *trv = (pid % 10) + '0';
+ pid /= 10;
+ }
+ /*
+ * check the target directory; if you have six X's and it
+ * doesn't exist this runs for a *very* long time.
+ */
+ for (start = trv + 1;; --trv) {
+ if (trv <= path)
+ break;
+ if (*trv == '\\') {
+ *trv = '\0';
+ if (stat(path, &sbuf))
+ return (0);
+ if (!S_ISDIR(sbuf.st_mode)) {
+ errno = ENOTDIR;
+ return (0);
+ }
+ *trv = '\\';
+ break;
+ }
+ }
+
+ for (;;) {
+ if (doopen) {
+ if ((*doopen =
+ open(path, O_CREAT|O_EXCL|O_RDWR,
+ _S_IREAD | _S_IWRITE)) >= 0)
+ return (1);
+ if (errno != EEXIST)
+ return (0);
+ } else if (stat(path, &sbuf))
+ return (errno == ENOENT ? 1 : 0);
+
+ /* tricky little algorithm for backward compatibility */
+ for (trv = start;;) {
+ if (!*trv)
+ return (0);
+ if (*trv == 'z')
+ *trv++ = 'a';
+ else {
+ if (isdigit(*trv))
+ *trv = 'a';
+ else
+ ++*trv;
+ break;
+ }
+ }
+ }
+ /*NOTREACHED*/
+}
+
+static int
+mkstemp(char *path) {
+ int fd;
+
+ return (gettemp(path, &fd) ? fd : -1);
+}
+
+/*
+ * XXXDCL As the API for accessing file statistics undoubtedly gets expanded,
+ * it might be good to provide a mechanism that allows for the results
+ * of a previous stat() to be used again without having to do another stat,
+ * such as perl's mechanism of using "_" in place of a file name to indicate
+ * that the results of the last stat should be used. But then you get into
+ * annoying MP issues. BTW, Win32 has stat().
+ */
+static isc_result_t
+file_stats(const char *file, struct stat *stats) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(file != NULL);
+ REQUIRE(stats != NULL);
+
+ if (stat(file, stats) != 0)
+ result = isc__errno2result(errno);
+
+ return (result);
+}
+
+/*
+ * isc_file_safemovefile is needed to be defined here to ensure that
+ * any file with the new name is renamed to a backup name and then the
+ * rename is done. If all goes well then the backup can be deleted,
+ * otherwise it gets renamed back.
+ */
+
+int
+isc_file_safemovefile(const char *oldname, const char *newname) {
+ BOOL filestatus;
+ char buf[512];
+ struct stat sbuf;
+ BOOL exists = FALSE;
+ int tmpfd;
+
+ /*
+ * Make sure we have something to do
+ */
+ if (stat(oldname, &sbuf) != 0) {
+ errno = ENOENT;
+ return (-1);
+ }
+
+ /*
+ * Rename to a backup the new file if it still exists
+ */
+ if (stat(newname, &sbuf) == 0) {
+ exists = TRUE;
+ strcpy(buf, newname);
+ strcat(buf, ".XXXXX");
+ tmpfd = mkstemp(buf);
+ if (tmpfd > 0)
+ _close(tmpfd);
+ DeleteFile(buf);
+ _chmod(newname, _S_IREAD | _S_IWRITE);
+
+ filestatus = MoveFile(newname, buf);
+ }
+ /* Now rename the file to the new name
+ */
+ _chmod(oldname, _S_IREAD | _S_IWRITE);
+
+ filestatus = MoveFile(oldname, newname);
+ if (filestatus == 0) {
+ /*
+ * Try to rename the backup back to the original name
+ * if the backup got created
+ */
+ if (exists == TRUE) {
+ filestatus = MoveFile(buf, newname);
+ if (filestatus == 0)
+ errno = EACCES;
+ }
+ return (-1);
+ }
+
+ /*
+ * Delete the backup file if it got created
+ */
+ if (exists == TRUE)
+ filestatus = DeleteFile(buf);
+ return (0);
+}
+
+isc_result_t
+isc_file_getmodtime(const char *file, isc_time_t *time) {
+ int fh;
+
+ REQUIRE(file != NULL);
+ REQUIRE(time != NULL);
+
+ if ((fh = open(file, _O_RDONLY | _O_BINARY)) < 0)
+ return (isc__errno2result(errno));
+
+ if (!GetFileTime((HANDLE) _get_osfhandle(fh),
+ NULL,
+ NULL,
+ &time->absolute))
+ {
+ close(fh);
+ errno = EINVAL;
+ return (isc__errno2result(errno));
+ }
+ close(fh);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_settime(const char *file, isc_time_t *time) {
+ int fh;
+
+ REQUIRE(file != NULL && time != NULL);
+
+ if ((fh = open(file, _O_RDWR | _O_BINARY)) < 0)
+ return (isc__errno2result(errno));
+
+ /*
+ * Set the date via the filedate system call and return. Failing
+ * this call implies the new file times are not supported by the
+ * underlying file system.
+ */
+ if (!SetFileTime((HANDLE) _get_osfhandle(fh),
+ NULL,
+ &time->absolute,
+ &time->absolute))
+ {
+ close(fh);
+ errno = EINVAL;
+ return (isc__errno2result(errno));
+ }
+
+ close(fh);
+ return (ISC_R_SUCCESS);
+
+}
+
+#undef TEMPLATE
+#define TEMPLATE "XXXXXXXXXX.tmp" /* 14 characters. */
+
+isc_result_t
+isc_file_mktemplate(const char *path, char *buf, size_t buflen) {
+ return (isc_file_template(path, TEMPLATE, buf, buflen));
+}
+
+isc_result_t
+isc_file_template(const char *path, const char *templet, char *buf,
+ size_t buflen) {
+ char *s;
+
+ REQUIRE(path != NULL);
+ REQUIRE(templet != NULL);
+ REQUIRE(buf != NULL);
+
+ s = strrchr(templet, '\\');
+ if (s != NULL)
+ templet = s + 1;
+
+ s = strrchr(path, '\\');
+
+ if (s != NULL) {
+ if ((s - path + 1 + strlen(templet) + 1) > buflen)
+ return (ISC_R_NOSPACE);
+
+ strncpy(buf, path, s - path + 1);
+ buf[s - path + 1] = '\0';
+ strcat(buf, templet);
+ } else {
+ if ((strlen(templet) + 1) > buflen)
+ return (ISC_R_NOSPACE);
+
+ strcpy(buf, templet);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_renameunique(const char *file, char *templet) {
+ int fd = -1;
+ int res = 0;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(file != NULL);
+ REQUIRE(templet != NULL);
+
+ fd = mkstemp(templet);
+ if (fd == -1)
+ result = isc__errno2result(errno);
+ else
+ close(fd);
+
+ if (result == ISC_R_SUCCESS) {
+ res = isc_file_safemovefile(file, templet);
+ if (res != 0) {
+ result = isc__errno2result(errno);
+ (void)unlink(templet);
+ }
+ }
+ return (result);
+}
+
+isc_result_t
+isc_file_openunique(char *templet, FILE **fp) {
+ int fd;
+ FILE *f;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ REQUIRE(templet != NULL);
+ REQUIRE(fp != NULL && *fp == NULL);
+
+ /*
+ * Win32 does not have mkstemp. Using emulation above.
+ */
+ fd = mkstemp(templet);
+
+ if (fd == -1)
+ result = isc__errno2result(errno);
+ if (result == ISC_R_SUCCESS) {
+ f = fdopen(fd, "w+");
+ if (f == NULL) {
+ result = isc__errno2result(errno);
+ (void)remove(templet);
+ (void)close(fd);
+ } else
+ *fp = f;
+ }
+
+ return (result);
+}
+
+isc_result_t
+isc_file_remove(const char *filename) {
+ int r;
+
+ REQUIRE(filename != NULL);
+
+ r = unlink(filename);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_file_rename(const char *oldname, const char *newname) {
+ int r;
+
+ REQUIRE(oldname != NULL);
+ REQUIRE(newname != NULL);
+
+ r = isc_file_safemovefile(oldname, newname);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_boolean_t
+isc_file_exists(const char *pathname) {
+ struct stat stats;
+
+ REQUIRE(pathname != NULL);
+
+ return (ISC_TF(file_stats(pathname, &stats) == ISC_R_SUCCESS));
+}
+
+isc_boolean_t
+isc_file_isabsolute(const char *filename) {
+ REQUIRE(filename != NULL);
+ /*
+ * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
+ * the UNC style file specs
+ */
+ if ((filename[0] == '\\') && (filename[1] == '\\'))
+ return (ISC_TRUE);
+ if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '\\')
+ return (ISC_TRUE);
+ if (isalpha(filename[0]) && filename[1] == ':' && filename[2] == '/')
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+isc_file_iscurrentdir(const char *filename) {
+ REQUIRE(filename != NULL);
+ return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
+}
+
+isc_boolean_t
+isc_file_ischdiridempotent(const char *filename) {
+ REQUIRE(filename != NULL);
+
+ if (isc_file_isabsolute(filename))
+ return (ISC_TRUE);
+ if (filename[0] == '\\')
+ return (ISC_TRUE);
+ if (filename[0] == '/')
+ return (ISC_TRUE);
+ if (isc_file_iscurrentdir(filename))
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+const char *
+isc_file_basename(const char *filename) {
+ char *s;
+
+ REQUIRE(filename != NULL);
+
+ s = strrchr(filename, '\\');
+ if (s == NULL)
+ return (filename);
+ return (s + 1);
+}
+
+isc_result_t
+isc_file_progname(const char *filename, char *progname, size_t namelen) {
+ const char *s;
+ char *p;
+ size_t len;
+
+ REQUIRE(filename != NULL);
+ REQUIRE(progname != NULL);
+
+ /*
+ * Strip the path from the name
+ */
+ s = isc_file_basename(filename);
+ if (s == NULL) {
+ return (ISC_R_NOSPACE);
+ }
+
+ /*
+ * Strip any and all suffixes
+ */
+ p = strchr(s, '.');
+ if (p == NULL) {
+ if (namelen <= strlen(s))
+ return (ISC_R_NOSPACE);
+
+ strcpy(progname, s);
+ return (ISC_R_SUCCESS);
+ }
+
+ /*
+ * Copy the result to the buffer
+ */
+ len = p - s;
+ if (len >= namelen)
+ return (ISC_R_NOSPACE);
+
+ strncpy(progname, s, len);
+ progname[len] = '\0';
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_absolutepath(const char *filename, char *path, size_t pathlen) {
+ char *ptrname;
+ DWORD retval;
+
+ REQUIRE(filename != NULL);
+ REQUIRE(path != NULL);
+
+ retval = GetFullPathName(filename, pathlen, path, &ptrname);
+
+ /* Something went wrong in getting the path */
+ if (retval == 0)
+ return (ISC_R_NOTFOUND);
+ /* Caller needs to provide a larger buffer to contain the string */
+ if (retval >= pathlen)
+ return (ISC_R_NOSPACE);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_file_truncate(const char *filename, isc_offset_t size) {
+ int fh;
+
+ REQUIRE(filename != NULL && size >= 0);
+
+ if ((fh = open(filename, _O_RDWR | _O_BINARY)) < 0)
+ return (isc__errno2result(errno));
+
+ if(_chsize(fh, size) != 0) {
+ close(fh);
+ return (isc__errno2result(errno));
+ }
+ close(fh);
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/win32/fsaccess.c b/lib/isc/win32/fsaccess.c
new file mode 100644
index 0000000..8de793f
--- /dev/null
+++ b/lib/isc/win32/fsaccess.c
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: fsaccess.c,v 1.15 2007/06/19 23:47:19 tbox Exp $ */
+
+/*
+ * Note that Win32 does not have the concept of files having access
+ * and ownership bits. The FAT File system only has a readonly flag
+ * for everyone and that's all. NTFS uses ACL's which is a totally
+ * different concept of controlling access.
+ *
+ * This code needs to be revisited to set up proper access control for
+ * NTFS file systems. Nothing can be done for FAT file systems.
+ */
+
+#include <config.h>
+
+#include <aclapi.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <errno.h>
+
+#include <isc/file.h>
+#include <isc/stat.h>
+
+#include "errno2result.h"
+
+/*
+ * The OS-independent part of the API is in lib/isc.
+ */
+#include "../fsaccess.c"
+
+/* Store the user account name locally */
+static char username[255] = "\0";
+static DWORD namelen = 0;
+
+/*
+ * In order to set or retrieve access information, we need to obtain
+ * the File System type. These could be UNC-type shares.
+ */
+
+BOOL
+is_ntfs(const char * file) {
+
+ char drive[255];
+ char FSType[20];
+ char tmpbuf[256];
+ char *machinename;
+ char *sharename;
+ char filename[1024];
+
+ REQUIRE(filename != NULL);
+
+ if (isc_file_absolutepath(file, filename,
+ sizeof(filename)) != ISC_R_SUCCESS) {
+ return (FALSE);
+ }
+
+ /*
+ * Look for c:\path\... style, c:/path/... or \\computer\shar\path...
+ * the UNC style file specs
+ */
+ if (isalpha(filename[0]) && filename[1] == ':' &&
+ (filename[2] == '\\' || filename[2] == '/')) {
+ strncpy(drive, filename, 3);
+ drive[3] = '\0';
+ }
+
+ else if ((filename[0] == '\\') && (filename[1] == '\\')) {
+ /* Find the machine and share name and rebuild the UNC */
+ strcpy(tmpbuf, filename);
+ machinename = strtok(tmpbuf, "\\");
+ sharename = strtok(NULL, "\\");
+ strcpy(drive, "\\\\");
+ strcat(drive, machinename);
+ strcat(drive, "\\");
+ strcat(drive, sharename);
+ strcat(drive, "\\");
+
+ }
+ else /* Not determinable */
+ return (FALSE);
+
+ GetVolumeInformation(drive, NULL, 0, NULL, 0, NULL, FSType,
+ sizeof(FSType));
+ if(strcmp(FSType,"NTFS") == 0)
+ return (TRUE);
+ else
+ return (FALSE);
+}
+
+/*
+ * If it's not NTFS, we assume that it is FAT and proceed
+ * with almost nothing to do. Only the write flag can be set or
+ * cleared.
+ */
+isc_result_t
+FAT_fsaccess_set(const char *path, isc_fsaccess_t access) {
+ int mode;
+ isc_fsaccess_t bits;
+
+ /*
+ * Done with checking bad bits. Set mode_t.
+ */
+ mode = 0;
+
+#define SET_AND_CLEAR1(modebit) \
+ if ((access & bits) != 0) { \
+ mode |= modebit; \
+ access &= ~bits; \
+ }
+#define SET_AND_CLEAR(user, group, other) \
+ SET_AND_CLEAR1(user); \
+ bits <<= STEP; \
+ SET_AND_CLEAR1(group); \
+ bits <<= STEP; \
+ SET_AND_CLEAR1(other);
+
+ bits = ISC_FSACCESS_READ | ISC_FSACCESS_LISTDIRECTORY;
+
+ SET_AND_CLEAR(S_IRUSR, S_IRGRP, S_IROTH);
+
+ bits = ISC_FSACCESS_WRITE |
+ ISC_FSACCESS_CREATECHILD |
+ ISC_FSACCESS_DELETECHILD;
+
+ SET_AND_CLEAR(S_IWUSR, S_IWGRP, S_IWOTH);
+
+ INSIST(access == 0);
+
+ if (_chmod(path, mode) < 0)
+ return (isc__errno2result(errno));
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+NTFS_Access_Control(const char *filename, const char *user, int access,
+ isc_boolean_t isdir) {
+ SECURITY_DESCRIPTOR sd;
+ BYTE aclBuffer[1024];
+ PACL pacl=(PACL)&aclBuffer;
+ BYTE sidBuffer[100];
+ PSID psid=(PSID) &sidBuffer;
+ DWORD sidBufferSize = sizeof(sidBuffer);
+ BYTE adminSidBuffer[100];
+ PSID padminsid=(PSID) &adminSidBuffer;
+ DWORD adminSidBufferSize = sizeof(adminSidBuffer);
+ BYTE otherSidBuffer[100];
+ PSID pothersid=(PSID) &otherSidBuffer;
+ DWORD otherSidBufferSize = sizeof(otherSidBuffer);
+ char domainBuffer[100];
+ DWORD domainBufferSize = sizeof(domainBuffer);
+ SID_NAME_USE snu;
+ int errval;
+ DWORD NTFSbits;
+ int caccess;
+
+
+ /* Initialize an ACL */
+ if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
+ return (ISC_R_NOPERM);
+ if (!InitializeAcl(pacl, sizeof(aclBuffer), ACL_REVISION))
+ return (ISC_R_NOPERM);
+ if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer,
+ &domainBufferSize, &snu))
+ return (ISC_R_NOPERM);
+ domainBufferSize = sizeof(domainBuffer);
+ if (!LookupAccountName(0, "Administrators", padminsid,
+ &adminSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
+ errval = GetLastError();
+ return (ISC_R_NOPERM);
+ }
+ domainBufferSize = sizeof(domainBuffer);
+ if (!LookupAccountName(0, "Everyone", pothersid,
+ &otherSidBufferSize, domainBuffer, &domainBufferSize, &snu)) {
+ errval = GetLastError();
+ return (ISC_R_NOPERM);
+ }
+
+ caccess = access;
+ /* Owner check */
+
+ NTFSbits = 0;
+ if (caccess & ISC_FSACCESS_READ)
+ NTFSbits |= FILE_GENERIC_READ;
+ if (caccess & ISC_FSACCESS_WRITE)
+ NTFSbits |= FILE_GENERIC_WRITE;
+ if (caccess & ISC_FSACCESS_EXECUTE)
+ NTFSbits |= FILE_GENERIC_EXECUTE;
+
+ /* For directories check the directory-specific bits */
+ if (isdir == ISC_TRUE) {
+ if (caccess & ISC_FSACCESS_CREATECHILD)
+ NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE;
+ if (caccess & ISC_FSACCESS_DELETECHILD)
+ NTFSbits |= FILE_DELETE_CHILD;
+ if (caccess & ISC_FSACCESS_LISTDIRECTORY)
+ NTFSbits |= FILE_LIST_DIRECTORY;
+ if (caccess & ISC_FSACCESS_ACCESSCHILD)
+ NTFSbits |= FILE_TRAVERSE;
+ }
+
+ if (NTFSbits == (FILE_GENERIC_READ | FILE_GENERIC_WRITE
+ | FILE_GENERIC_EXECUTE))
+ NTFSbits |= FILE_ALL_ACCESS;
+ /*
+ * Owner and Administrator also get STANDARD_RIGHTS_ALL
+ * to ensure that they have full control
+ */
+
+ NTFSbits |= STANDARD_RIGHTS_ALL;
+
+ /* Add the ACE to the ACL */
+ if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, psid))
+ return (ISC_R_NOPERM);
+ if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits, padminsid))
+ return (ISC_R_NOPERM);
+
+ /*
+ * Group is ignored since we can be in multiple groups or no group
+ * and its meaning is not clear on Win32
+ */
+
+ caccess = caccess >> STEP;
+
+ /*
+ * Other check. We translate this to be the same as Everyone
+ */
+
+ caccess = caccess >> STEP;
+
+ NTFSbits = 0;
+ if (caccess & ISC_FSACCESS_READ)
+ NTFSbits |= FILE_GENERIC_READ;
+ if (caccess & ISC_FSACCESS_WRITE)
+ NTFSbits |= FILE_GENERIC_WRITE;
+ if (caccess & ISC_FSACCESS_EXECUTE)
+ NTFSbits |= FILE_GENERIC_EXECUTE;
+
+ /* For directories check the directory-specific bits */
+ if (isdir == TRUE) {
+ if (caccess & ISC_FSACCESS_CREATECHILD)
+ NTFSbits |= FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE;
+ if (caccess & ISC_FSACCESS_DELETECHILD)
+ NTFSbits |= FILE_DELETE_CHILD;
+ if (caccess & ISC_FSACCESS_LISTDIRECTORY)
+ NTFSbits |= FILE_LIST_DIRECTORY;
+ if (caccess & ISC_FSACCESS_ACCESSCHILD)
+ NTFSbits |= FILE_TRAVERSE;
+ }
+ /* Add the ACE to the ACL */
+ if (!AddAccessAllowedAce(pacl, ACL_REVISION, NTFSbits,
+ pothersid))
+ return (ISC_R_NOPERM);
+
+ if (!SetSecurityDescriptorDacl(&sd, TRUE, pacl, FALSE))
+ return (ISC_R_NOPERM);
+ if (!SetFileSecurity(filename, DACL_SECURITY_INFORMATION, &sd)) {
+ return (ISC_R_NOPERM);
+ }
+
+ return(ISC_R_SUCCESS);
+}
+
+isc_result_t
+NTFS_fsaccess_set(const char *path, isc_fsaccess_t access,
+ isc_boolean_t isdir){
+
+ /*
+ * For NTFS we first need to get the name of the account under
+ * which BIND is running
+ */
+ if (namelen <= 0) {
+ namelen = sizeof(username);
+ if (GetUserName(username, &namelen) == 0)
+ return (ISC_R_FAILURE);
+ }
+ return (NTFS_Access_Control(path, username, access, isdir));
+}
+
+isc_result_t
+isc_fsaccess_set(const char *path, isc_fsaccess_t access) {
+ struct stat statb;
+ isc_boolean_t is_dir = ISC_FALSE;
+ isc_result_t result;
+
+ if (stat(path, &statb) != 0)
+ return (isc__errno2result(errno));
+
+ if ((statb.st_mode & S_IFDIR) != 0)
+ is_dir = ISC_TRUE;
+ else if ((statb.st_mode & S_IFREG) == 0)
+ return (ISC_R_INVALIDFILE);
+
+ result = check_bad_bits(access, is_dir);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ /*
+ * Determine if this is a FAT or NTFS disk and
+ * call the appropriate function to set the permissions
+ */
+ if (is_ntfs(path))
+ return (NTFS_fsaccess_set(path, access, is_dir));
+ else
+ return (FAT_fsaccess_set(path, access));
+}
+
+isc_result_t
+isc_fsaccess_changeowner(const char *filename, const char *user) {
+ SECURITY_DESCRIPTOR psd;
+ BYTE sidBuffer[500];
+ BYTE groupBuffer[500];
+ PSID psid=(PSID) &sidBuffer;
+ DWORD sidBufferSize = sizeof(sidBuffer);
+ char domainBuffer[100];
+ DWORD domainBufferSize = sizeof(domainBuffer);
+ SID_NAME_USE snu;
+ PSID pSidGroup = (PSID) &groupBuffer;
+ DWORD groupBufferSize = sizeof(groupBuffer);
+
+
+ /*
+ * Determine if this is a FAT or NTFS disk and
+ * call the appropriate function to set the ownership
+ * FAT disks do not have ownership attributes so it's
+ * a noop.
+ */
+ if (is_ntfs(filename) == FALSE)
+ return (ISC_R_SUCCESS);
+
+ if (!InitializeSecurityDescriptor(&psd, SECURITY_DESCRIPTOR_REVISION))
+ return (ISC_R_NOPERM);
+
+ if (!LookupAccountName(0, user, psid, &sidBufferSize, domainBuffer,
+ &domainBufferSize, &snu))
+ return (ISC_R_NOPERM);
+
+ /* Make sure administrators can get to it */
+ domainBufferSize = sizeof(domainBuffer);
+ if (!LookupAccountName(0, "Administrators", pSidGroup,
+ &groupBufferSize, domainBuffer, &domainBufferSize, &snu))
+ return (ISC_R_NOPERM);
+
+ if (!SetSecurityDescriptorOwner(&psd, psid, FALSE))
+ return (ISC_R_NOPERM);
+
+ if (!SetSecurityDescriptorGroup(&psd, pSidGroup, FALSE))
+ return (ISC_R_NOPERM);
+
+ if (!SetFileSecurity(filename,
+ OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
+ &psd))
+ return (ISC_R_NOPERM);
+
+ return (ISC_R_SUCCESS);
+}
+
diff --git a/lib/isc/win32/include/Makefile.in b/lib/isc/win32/include/Makefile.in
new file mode 100644
index 0000000..c74b52d
--- /dev/null
+++ b/lib/isc/win32/include/Makefile.in
@@ -0,0 +1,25 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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.9 2007/06/19 23:47:19 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/win32/include/isc/Makefile.in b/lib/isc/win32/include/isc/Makefile.in
new file mode 100644
index 0000000..dcd8519
--- /dev/null
+++ b/lib/isc/win32/include/isc/Makefile.in
@@ -0,0 +1,38 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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.11 2007/06/19 23:47:20 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = dir.h int.h mutex.h net.h netdb.h once.h \
+ stdtime.h thread.h time.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}\isc
+
+install:: installdirs
+ for i in $(HEADERS); do \
+ $(INSTALL_DATA) $(srcdir)\$$i $(includedir)\isc ; \
+ done
diff --git a/lib/isc/win32/include/isc/bind_registry.h b/lib/isc/win32/include/isc/bind_registry.h
new file mode 100644
index 0000000..c4dc876
--- /dev/null
+++ b/lib/isc/win32/include/isc/bind_registry.h
@@ -0,0 +1,50 @@
+/*
+ * 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: bind_registry.h,v 1.8 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_BINDREGISTRY_H
+#define ISC_BINDREGISTRY_H
+
+/*
+ * BIND makes use of the following Registry keys in various places, especially
+ * during startup and installation
+ */
+
+#define BIND_SUBKEY "Software\\ISC\\BIND"
+#define BIND_SESSION "CurrentSession"
+#define BIND_SESSION_SUBKEY "Software\\ISC\\BIND\\CurrentSession"
+#define BIND_UNINSTALL_SUBKEY \
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ISC BIND"
+
+#define EVENTLOG_APP_SUBKEY \
+ "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application"
+#define BIND_MESSAGE_SUBKEY \
+ "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\named"
+#define BIND_MESSAGE_NAME "named"
+
+#define BIND_SERVICE_SUBKEY \
+ "SYSTEM\\CurrentControlSet\\Services\\named"
+
+
+#define BIND_CONFIGFILE 0
+#define BIND_DEBUGLEVEL 1
+#define BIND_QUERYLOG 2
+#define BIND_FOREGROUND 3
+#define BIND_PORT 4
+
+#endif /* ISC_BINDREGISTRY_H */
diff --git a/lib/isc/win32/include/isc/bindevt.h b/lib/isc/win32/include/isc/bindevt.h
new file mode 100644
index 0000000..72cf2d1
--- /dev/null
+++ b/lib/isc/win32/include/isc/bindevt.h
@@ -0,0 +1,91 @@
+/*
+ * 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: bindevt.h,v 1.6 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_BINDEVT_H
+#define ISC_BINDEVT_H 1
+
+/*
+ * This is used for the event log for both logging the messages and
+ * later on by the event viewer when looking at the events
+ */
+
+/*
+ * Values are 32 bit values layed out as follows:
+ *
+ * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +---+-+-+-----------------------+-------------------------------+
+ * |Sev|C|R| Facility | Code |
+ * +---+-+-+-----------------------+-------------------------------+
+ *
+ * where
+ *
+ * Sev - is the severity code
+ *
+ * 00 - Success
+ * 01 - Informational
+ * 10 - Warning
+ * 11 - Error
+ *
+ * C - is the Customer code flag
+ *
+ * R - is a reserved bit
+ *
+ * Facility - is the facility code
+ *
+ * Code - is the facility's status code
+ *
+ *
+ * Define the facility codes
+ */
+
+
+/*
+ * Define the severity codes
+ */
+
+
+/*
+ * MessageId: BIND_ERR_MSG
+ *
+ * MessageText:
+ *
+ * %1
+ */
+#define BIND_ERR_MSG ((DWORD)0xC0000001L)
+
+/*
+ * MessageId: BIND_WARN_MSG
+ *
+ * MessageText:
+ *
+ * %1
+ */
+#define BIND_WARN_MSG ((DWORD)0x80000002L)
+
+/*
+ * MessageId: BIND_INFO_MSG
+ *
+ * MessageText:
+ *
+ * %1
+ */
+#define BIND_INFO_MSG ((DWORD)0x40000003L)
+
+#endif /* ISC_BINDEVT_H */
diff --git a/lib/isc/win32/include/isc/condition.h b/lib/isc/win32/include/isc/condition.h
new file mode 100644
index 0000000..34015bc
--- /dev/null
+++ b/lib/isc/win32/include/isc/condition.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: condition.h,v 1.17 2007/06/18 23:47:49 tbox Exp $ */
+
+#ifndef ISC_CONDITION_H
+#define ISC_CONDITION_H 1
+
+#include <windows.h>
+
+#include <isc/lang.h>
+#include <isc/mutex.h>
+#include <isc/thread.h>
+#include <isc/types.h>
+
+typedef struct isc_condition_thread isc_condition_thread_t;
+
+struct isc_condition_thread {
+ unsigned long th;
+ HANDLE handle[2];
+ ISC_LINK(isc_condition_thread_t) link;
+
+};
+
+typedef struct isc_condition {
+ HANDLE events[2];
+ unsigned int waiters;
+ ISC_LIST(isc_condition_thread_t) threadlist;
+} isc_condition_t;
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_condition_init(isc_condition_t *);
+
+isc_result_t
+isc_condition_wait(isc_condition_t *, isc_mutex_t *);
+
+isc_result_t
+isc_condition_signal(isc_condition_t *);
+
+isc_result_t
+isc_condition_broadcast(isc_condition_t *);
+
+isc_result_t
+isc_condition_destroy(isc_condition_t *);
+
+isc_result_t
+isc_condition_waituntil(isc_condition_t *, isc_mutex_t *, isc_time_t *);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_CONDITION_H */
diff --git a/lib/isc/win32/include/isc/dir.h b/lib/isc/win32/include/isc/dir.h
new file mode 100644
index 0000000..653427a
--- /dev/null
+++ b/lib/isc/win32/include/isc/dir.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: dir.h,v 1.15 2007/06/19 23:47:20 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#ifndef ISC_DIR_H
+#define ISC_DIR_H 1
+
+#include <windows.h>
+#include <stdlib.h>
+
+#include <isc/lang.h>
+#include <isc/boolean.h>
+#include <isc/result.h>
+
+#define ISC_DIR_NAMEMAX _MAX_FNAME
+#define ISC_DIR_PATHMAX _MAX_PATH
+
+typedef struct {
+ char name[ISC_DIR_NAMEMAX];
+ unsigned int length;
+ WIN32_FIND_DATA find_data;
+} isc_direntry_t;
+
+typedef struct {
+ unsigned int magic;
+ char dirname[ISC_DIR_PATHMAX];
+ isc_direntry_t entry;
+ isc_boolean_t entry_filled;
+ HANDLE search_handle;
+} isc_dir_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_dir_init(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_open(isc_dir_t *dir, const char *dirname);
+
+isc_result_t
+isc_dir_read(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_reset(isc_dir_t *dir);
+
+void
+isc_dir_close(isc_dir_t *dir);
+
+isc_result_t
+isc_dir_chdir(const char *dirname);
+
+isc_result_t
+isc_dir_chroot(const char *dirname);
+
+isc_result_t
+isc_dir_createunique(char *templet);
+/*
+ * Use a templet (such as from isc_file_mktemplate()) to create a uniquely
+ * named, empty directory. The templet string is modified in place.
+ * If result == ISC_R_SUCCESS, it is the name of the directory that was
+ * created.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_DIR_H */
diff --git a/lib/isc/win32/include/isc/int.h b/lib/isc/win32/include/isc/int.h
new file mode 100644
index 0000000..2ee8bf9
--- /dev/null
+++ b/lib/isc/win32/include/isc/int.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: int.h,v 1.13 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_INT_H
+#define ISC_INT_H 1
+
+#define _INTEGRAL_MAX_BITS 64
+#include <limits.h>
+
+typedef __int8 isc_int8_t;
+typedef unsigned __int8 isc_uint8_t;
+typedef __int16 isc_int16_t;
+typedef unsigned __int16 isc_uint16_t;
+typedef __int32 isc_int32_t;
+typedef unsigned __int32 isc_uint32_t;
+typedef __int64 isc_int64_t;
+typedef unsigned __int64 isc_uint64_t;
+
+#define ISC_INT8_MIN -128
+#define ISC_INT8_MAX 127
+#define ISC_UINT8_MAX 255
+
+#define ISC_INT16_MIN -32768
+#define ISC_INT16_MAX 32767
+#define ISC_UINT16_MAX 65535
+
+/*
+ * Note that "int" is 32 bits on all currently supported Unix-like operating
+ * systems, but "long" can be either 32 bits or 64 bits, thus the 32 bit
+ * constants are not qualified with "L".
+ */
+#define ISC_INT32_MIN _I32_MIN
+#define ISC_INT32_MAX _I32_MAX
+#define ISC_UINT32_MAX _UI32_MAX
+
+#define ISC_INT64_MIN _I64_MIN
+#define ISC_INT64_MAX _I64_MAX
+#define ISC_UINT64_MAX _UI64_MAX
+
+#endif /* ISC_INT_H */
diff --git a/lib/isc/win32/include/isc/ipv6.h b/lib/isc/win32/include/isc/ipv6.h
new file mode 100644
index 0000000..c9add0b
--- /dev/null
+++ b/lib/isc/win32/include/isc/ipv6.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: ipv6.h,v 1.19 2007/06/18 23:47:49 tbox Exp $ */
+
+#ifndef ISC_IPV6_H
+#define ISC_IPV6_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * IPv6 definitions for systems which do not support IPv6.
+ *
+ * MP:
+ * No impact.
+ *
+ * Reliability:
+ * No anticipated impact.
+ *
+ * Resources:
+ * N/A.
+ *
+ * Security:
+ * No anticipated impact.
+ *
+ * Standards:
+ * RFC2553.
+ */
+
+#if _MSC_VER < 1300
+#define in6_addr in_addr6
+#endif
+
+#ifndef IN6ADDR_ANY_INIT
+#define IN6ADDR_ANY_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}
+#endif
+#ifndef IN6ADDR_LOOPBACK_INIT
+#define IN6ADDR_LOOPBACK_INIT {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}
+#endif
+
+LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_any;
+LIBISC_EXTERNAL_DATA extern const struct in6_addr isc_in6addr_loopback;
+
+/*
+ * Unspecified
+ */
+#ifndef IN6_IS_ADDR_UNSPECIFIED
+#define IN6_IS_ADDR_UNSPECIFIED(a) (\
+*((u_long *)((a)->s6_addr) ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == 0 && \
+*((u_long *)((a)->s6_addr) + 3) == 0 \
+)
+#endif
+
+/*
+ * Loopback
+ */
+#ifndef IN6_IS_ADDR_LOOPBACK
+#define IN6_IS_ADDR_LOOPBACK(a) (\
+*((u_long *)((a)->s6_addr) ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == 0 && \
+*((u_long *)((a)->s6_addr) + 3) == htonl(1) \
+)
+#endif
+
+/*
+ * IPv4 compatible
+ */
+#define IN6_IS_ADDR_V4COMPAT(a) (\
+*((u_long *)((a)->s6_addr) ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == 0 && \
+*((u_long *)((a)->s6_addr) + 3) != 0 && \
+*((u_long *)((a)->s6_addr) + 3) != htonl(1) \
+)
+
+/*
+ * Mapped
+ */
+#define IN6_IS_ADDR_V4MAPPED(a) (\
+*((u_long *)((a)->s6_addr) ) == 0 && \
+*((u_long *)((a)->s6_addr) + 1) == 0 && \
+*((u_long *)((a)->s6_addr) + 2) == htonl(0x0000ffff))
+
+/*
+ * Multicast
+ */
+#define IN6_IS_ADDR_MULTICAST(a) \
+ ((a)->s6_addr[0] == 0xffU)
+
+/*
+ * Unicast link / site local.
+ */
+#ifndef IN6_IS_ADDR_LINKLOCAL
+#define IN6_IS_ADDR_LINKLOCAL(a) (\
+(*((u_long *)((a)->s6_addr) ) == 0xfe) && \
+((*((u_long *)((a)->s6_addr) + 1) & 0xc0) == 0x80))
+#endif
+
+#ifndef IN6_IS_ADDR_SITELOCAL
+#define IN6_IS_ADDR_SITELOCAL(a) (\
+(*((u_long *)((a)->s6_addr) ) == 0xfe) && \
+((*((u_long *)((a)->s6_addr) + 1) & 0xc0) == 0xc0))
+#endif
+
+#endif /* ISC_IPV6_H */
diff --git a/lib/isc/win32/include/isc/keyboard.h b/lib/isc/win32/include/isc/keyboard.h
new file mode 100644
index 0000000..e781c5f
--- /dev/null
+++ b/lib/isc/win32/include/isc/keyboard.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004, 2007 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: keyboard.h,v 1.6 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_KEYBOARD_H
+#define ISC_KEYBOARD_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef struct {
+ int fd;
+ isc_result_t result;
+} isc_keyboard_t;
+
+isc_result_t
+isc_keyboard_open(isc_keyboard_t *keyboard);
+
+isc_result_t
+isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleepseconds);
+
+isc_result_t
+isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp);
+
+isc_boolean_t
+isc_keyboard_canceled(isc_keyboard_t *keyboard);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_KEYBOARD_H */
diff --git a/lib/isc/win32/include/isc/mutex.h b/lib/isc/win32/include/isc/mutex.h
new file mode 100644
index 0000000..e5320c3
--- /dev/null
+++ b/lib/isc/win32/include/isc/mutex.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: mutex.h,v 1.20 2008/09/12 04:46:25 marka Exp $ */
+
+#ifndef ISC_MUTEX_H
+#define ISC_MUTEX_H 1
+
+#include <isc/net.h>
+#include <windows.h>
+
+#include <isc/result.h>
+
+typedef CRITICAL_SECTION isc_mutex_t;
+
+/*
+ * This definition is here since somve versions of WINBASE.H
+ * omits it for some reason.
+ */
+#if (_WIN32_WINNT < 0x0400)
+WINBASEAPI BOOL WINAPI
+TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
+#endif /* _WIN32_WINNT < 0x0400 */
+
+#define isc_mutex_init(mp) \
+ (InitializeCriticalSection((mp)), ISC_R_SUCCESS)
+#define isc_mutex_lock(mp) \
+ (EnterCriticalSection((mp)), ISC_R_SUCCESS)
+#define isc_mutex_unlock(mp) \
+ (LeaveCriticalSection((mp)), ISC_R_SUCCESS)
+#define isc_mutex_trylock(mp) \
+ (TryEnterCriticalSection((mp)) ? ISC_R_SUCCESS : ISC_R_LOCKBUSY)
+#define isc_mutex_destroy(mp) \
+ (DeleteCriticalSection((mp)), ISC_R_SUCCESS)
+
+/*
+ * This is a placeholder for now since we are not keeping any mutex stats
+ */
+#define isc_mutex_stats(fp) do {} while (0)
+
+#endif /* ISC_MUTEX_H */
diff --git a/lib/isc/win32/include/isc/net.h b/lib/isc/win32/include/isc/net.h
new file mode 100644
index 0000000..a89bce0
--- /dev/null
+++ b/lib/isc/win32/include/isc/net.h
@@ -0,0 +1,346 @@
+/*
+ * 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
+ * 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: net.h,v 1.30 2008/07/01 23:47:17 tbox Exp $ */
+
+#ifndef ISC_NET_H
+#define ISC_NET_H 1
+
+/*
+ * Also define LWRES_IPV6_H to keep it from being included if liblwres is
+ * being used, or redefinition errors will occur.
+ */
+#define LWRES_IPV6_H 1
+
+
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Basic Networking Types
+ *
+ * This module is responsible for defining the following basic networking
+ * types:
+ *
+ * struct in_addr
+ * struct in6_addr
+ * struct in6_pktinfo
+ * struct sockaddr
+ * struct sockaddr_in
+ * struct sockaddr_in6
+ * in_port_t
+ *
+ * It ensures that the AF_ and PF_ macros are defined.
+ *
+ * It declares ntoh[sl]() and hton[sl]().
+ *
+ * It declares inet_aton(), inet_ntop(), and inet_pton().
+ *
+ * It ensures that INADDR_ANY, IN6ADDR_ANY_INIT, in6addr_any, and
+ * in6addr_loopback are available.
+ *
+ * It ensures that IN_MULTICAST() is available to check for multicast
+ * addresses.
+ *
+ * MP:
+ * No impact.
+ *
+ * Reliability:
+ * No anticipated impact.
+ *
+ * Resources:
+ * N/A.
+ *
+ * Security:
+ * No anticipated impact.
+ *
+ * Standards:
+ * BSD Socket API
+ * RFC2553
+ */
+
+/***
+ *** Imports.
+ ***/
+#include <isc/platform.h>
+
+/*
+ * Because of some sort of problem in the MS header files, this cannot
+ * be simple "#include <winsock2.h>", because winsock2.h tries to include
+ * windows.h, which then generates an error out of mswsock.h. _You_
+ * figure it out.
+ */
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
+#endif
+
+#include <winsock2.h>
+
+#include <sys/types.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+#include <ws2tcpip.h>
+#include <isc/ipv6.h>
+
+/*
+ * This is here because named client, interfacemgr.c, etc. use the name as
+ * a variable
+ */
+#undef interface
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001UL
+#endif
+
+#ifndef ISC_PLATFORM_HAVEIN6PKTINFO
+struct in6_pktinfo {
+ struct in6_addr ipi6_addr; /* src/dst IPv6 address */
+ unsigned int ipi6_ifindex; /* send/recv interface index */
+};
+#endif
+
+#if _MSC_VER < 1300
+#define in6addr_any isc_in6addr_any
+#define in6addr_loopback isc_in6addr_loopback
+#endif
+
+/*
+ * Ensure type in_port_t is defined.
+ */
+#ifdef ISC_PLATFORM_NEEDPORTT
+typedef isc_uint16_t in_port_t;
+#endif
+
+/*
+ * If this system does not have MSG_TRUNC (as returned from recvmsg())
+ * ISC_PLATFORM_RECVOVERFLOW will be defined. This will enable the MSG_TRUNC
+ * faking code in socket.c.
+ */
+#ifndef MSG_TRUNC
+#define ISC_PLATFORM_RECVOVERFLOW
+#endif
+
+#define ISC__IPADDR(x) ((isc_uint32_t)htonl((isc_uint32_t)(x)))
+
+#define ISC_IPADDR_ISMULTICAST(i) \
+ (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+ == ISC__IPADDR(0xe0000000))
+
+#define ISC_IPADDR_ISEXPERIMENTAL(i) \
+ (((isc_uint32_t)(i) & ISC__IPADDR(0xf0000000)) \
+ == ISC__IPADDR(0xf0000000))
+
+/*
+ * Fix the FD_SET and FD_CLR Macros to properly cast
+ */
+#undef FD_CLR
+#define FD_CLR(fd, set) do { \
+ u_int __i; \
+ for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
+ if (((fd_set FAR *)(set))->fd_array[__i] == (SOCKET) fd) { \
+ while (__i < ((fd_set FAR *)(set))->fd_count-1) { \
+ ((fd_set FAR *)(set))->fd_array[__i] = \
+ ((fd_set FAR *)(set))->fd_array[__i+1]; \
+ __i++; \
+ } \
+ ((fd_set FAR *)(set))->fd_count--; \
+ break; \
+ } \
+ } \
+} while (0)
+
+#undef FD_SET
+#define FD_SET(fd, set) do { \
+ u_int __i; \
+ for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
+ if (((fd_set FAR *)(set))->fd_array[__i] == (SOCKET)(fd)) { \
+ break; \
+ } \
+ } \
+ if (__i == ((fd_set FAR *)(set))->fd_count) { \
+ if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) { \
+ ((fd_set FAR *)(set))->fd_array[__i] = (SOCKET)(fd); \
+ ((fd_set FAR *)(set))->fd_count++; \
+ } \
+ } \
+} while (0)
+
+/*
+ * Windows Sockets errors redefined as regular Berkeley error constants.
+ * These are usually commented out in Windows NT to avoid conflicts with errno.h.
+ * Use the WSA constants instead.
+ */
+
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#define EALREADY WSAEALREADY
+#define ENOTSOCK WSAENOTSOCK
+#define EDESTADDRREQ WSAEDESTADDRREQ
+#define EMSGSIZE WSAEMSGSIZE
+#define EPROTOTYPE WSAEPROTOTYPE
+#define ENOPROTOOPT WSAENOPROTOOPT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define EADDRINUSE WSAEADDRINUSE
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define ENETDOWN WSAENETDOWN
+#define ENETUNREACH WSAENETUNREACH
+#define ENETRESET WSAENETRESET
+#define ECONNABORTED WSAECONNABORTED
+#define ECONNRESET WSAECONNRESET
+#define ENOBUFS WSAENOBUFS
+#define EISCONN WSAEISCONN
+#define ENOTCONN WSAENOTCONN
+#define ESHUTDOWN WSAESHUTDOWN
+#define ETOOMANYREFS WSAETOOMANYREFS
+#define ETIMEDOUT WSAETIMEDOUT
+#define ECONNREFUSED WSAECONNREFUSED
+#define ELOOP WSAELOOP
+#define EHOSTDOWN WSAEHOSTDOWN
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#define EPROCLIM WSAEPROCLIM
+#define EUSERS WSAEUSERS
+#define EDQUOT WSAEDQUOT
+#define ESTALE WSAESTALE
+#define EREMOTE WSAEREMOTE
+
+
+/***
+ *** Functions.
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_net_probeipv4(void);
+/*
+ * Check if the system's kernel supports IPv4.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS IPv4 is supported.
+ * ISC_R_NOTFOUND IPv4 is not supported.
+ * ISC_R_DISABLED IPv4 is disabled.
+ * ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probeipv6(void);
+/*
+ * Check if the system's kernel supports IPv6.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS IPv6 is supported.
+ * ISC_R_NOTFOUND IPv6 is not supported.
+ * ISC_R_DISABLED IPv6 is disabled.
+ * ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probeunix(void);
+/*
+ * Check if UNIX domain sockets are supported.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS
+ * ISC_R_NOTFOUND
+ */
+
+isc_result_t
+isc_net_probe_ipv6only(void);
+/*
+ * Check if the system's kernel supports the IPV6_V6ONLY socket option.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS the option is supported for both TCP and UDP.
+ * ISC_R_NOTFOUND IPv6 itself or the option is not supported.
+ * ISC_R_UNEXPECTED
+ */
+
+isc_result_t
+isc_net_probe_ipv6pktinfo(void);
+/*
+ * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option
+ * for UDP sockets.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS the option is supported.
+ * ISC_R_NOTFOUND IPv6 itself or the option is not supported.
+ * ISC_R_UNEXPECTED
+ */
+
+void
+isc_net_disableipv4(void);
+
+void
+isc_net_disableipv6(void);
+
+void
+isc_net_enableipv4(void);
+
+void
+isc_net_enableipv6(void);
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high);
+/*%<
+ * Returns system's default range of ephemeral UDP ports, if defined.
+ * If the range is not available or unknown, ISC_NET_PORTRANGELOW and
+ * ISC_NET_PORTRANGEHIGH will be returned.
+ *
+ * Requires:
+ *
+ *\li 'low' and 'high' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li *low and *high will be the ports specifying the low and high ends of
+ * the range.
+ */
+
+#ifdef ISC_PLATFORM_NEEDNTOP
+const char *
+isc_net_ntop(int af, const void *src, char *dst, size_t size);
+#define inet_ntop isc_net_ntop
+#endif
+
+#ifdef ISC_PLATFORM_NEEDPTON
+int
+isc_net_pton(int af, const char *src, void *dst);
+#define inet_pton isc_net_pton
+#endif
+
+#ifdef ISC_PLATFORM_NEEDATON
+int
+isc_net_aton(const char *cp, struct in_addr *addr);
+#define inet_aton isc_net_aton
+#endif
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NET_H */
diff --git a/lib/isc/win32/include/isc/netdb.h b/lib/isc/win32/include/isc/netdb.h
new file mode 100644
index 0000000..6625afd
--- /dev/null
+++ b/lib/isc/win32/include/isc/netdb.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: netdb.h,v 1.9 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_NETDB_H
+#define ISC_NETDB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Portable netdb.h support.
+ *
+ * This module is responsible for defining the get<x>by<y> APIs.
+ *
+ * MP:
+ * No impact.
+ *
+ * Reliability:
+ * No anticipated impact.
+ *
+ * Resources:
+ * N/A.
+ *
+ * Security:
+ * No anticipated impact.
+ *
+ * Standards:
+ * BSD API
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/net.h>
+
+#endif /* ISC_NETDB_H */
diff --git a/lib/isc/win32/include/isc/ntgroups.h b/lib/isc/win32/include/isc/ntgroups.h
new file mode 100644
index 0000000..b4cd020
--- /dev/null
+++ b/lib/isc/win32/include/isc/ntgroups.h
@@ -0,0 +1,35 @@
+/*
+ * 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: ntgroups.h,v 1.5 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_NTGROUPS_H
+#define ISC_NTGROUPS_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+
+isc_result_t
+isc_ntsecurity_getaccountgroups(char *name, char **Groups, unsigned int maxgroups,
+ unsigned int *total);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NTGROUPS_H */
diff --git a/lib/isc/win32/include/isc/ntpaths.h b/lib/isc/win32/include/isc/ntpaths.h
new file mode 100644
index 0000000..7cd185a
--- /dev/null
+++ b/lib/isc/win32/include/isc/ntpaths.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004, 2007 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: ntpaths.h,v 1.16 2007/06/19 23:47:20 tbox Exp $ */
+
+/*
+ * Windows-specific path definitions
+ * These routines are used to set up and return system-specific path
+ * information about the files enumerated in NtPaths
+ */
+
+#ifndef ISC_NTPATHS_H
+#define ISC_NTPATHS_H
+
+#include <isc/lang.h>
+
+/*
+ * Index of paths needed
+ */
+enum NtPaths {
+ NAMED_CONF_PATH,
+ LWRES_CONF_PATH,
+ RESOLV_CONF_PATH,
+ RNDC_CONF_PATH,
+ NAMED_PID_PATH,
+ LWRESD_PID_PATH,
+ LOCAL_STATE_DIR,
+ SYS_CONF_DIR,
+ RNDC_KEY_PATH
+};
+
+/*
+ * Define macros to get the path of the config files
+ */
+#define NAMED_CONFFILE isc_ntpaths_get(NAMED_CONF_PATH)
+#define RNDC_CONFFILE isc_ntpaths_get(RNDC_CONF_PATH)
+#define RNDC_KEYFILE isc_ntpaths_get(RNDC_KEY_PATH)
+#define RESOLV_CONF isc_ntpaths_get(RESOLV_CONF_PATH)
+
+
+/*
+ * Information about where the files are on disk
+ */
+#define NS_LOCALSTATEDIR "/dns/bin"
+#define NS_SYSCONFDIR "/dns/etc"
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_ntpaths_init(void);
+
+char *
+isc_ntpaths_get(int);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NTPATHS_H */
diff --git a/lib/isc/win32/include/isc/offset.h b/lib/isc/win32/include/isc/offset.h
new file mode 100644
index 0000000..f22fdce
--- /dev/null
+++ b/lib/isc/win32/include/isc/offset.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004, 2007 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: offset.h,v 1.6 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_OFFSET_H
+#define ISC_OFFSET_H 1
+
+/*
+ * File offsets are operating-system dependent.
+ */
+#include <limits.h> /* Required for CHAR_BIT. */
+#include <sys/types.h>
+
+typedef _off_t isc_offset_t;
+
+/*
+ * POSIX says "Additionally, blkcnt_t and off_t are extended signed integral
+ * types", so the maximum value is all 1s except for the high bit.
+ * This definition is more complex than it really needs to be because it was
+ * crafted to keep both the SunOS 5.6 and the HP/UX 11 compilers quiet about
+ * integer overflow. For example, though this is equivalent to just left
+ * shifting 1 to the high bit and then inverting the bits, the SunOS compiler
+ * is unhappy about shifting a positive "1" to negative in a signed integer.
+ */
+#define ISC_OFFSET_MAXIMUM \
+ (~(((off_t)-1 >> (sizeof(off_t) * CHAR_BIT - 1)) \
+ << (sizeof(off_t) * CHAR_BIT - 1)))
+
+#endif /* ISC_OFFSET_H */
diff --git a/lib/isc/win32/include/isc/once.h b/lib/isc/win32/include/isc/once.h
new file mode 100644
index 0000000..32af1bd
--- /dev/null
+++ b/lib/isc/win32/include/isc/once.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: once.h,v 1.9 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_ONCE_H
+#define ISC_ONCE_H 1
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+ISC_LANG_BEGINDECLS
+
+typedef struct {
+ int status;
+ int counter;
+} isc_once_t;
+
+#define ISC_ONCE_INIT_NEEDED 0
+#define ISC_ONCE_INIT_DONE 1
+
+#define ISC_ONCE_INIT { ISC_ONCE_INIT_NEEDED, 1 }
+
+isc_result_t
+isc_once_do(isc_once_t *controller, void(*function)(void));
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_ONCE_H */
diff --git a/lib/isc/win32/include/isc/platform.h b/lib/isc/win32/include/isc/platform.h
new file mode 100644
index 0000000..b3426e5
--- /dev/null
+++ b/lib/isc/win32/include/isc/platform.h
@@ -0,0 +1,101 @@
+/*
+ * 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
+ * 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,v 1.16 2008/04/02 23:46:58 tbox Exp $ */
+
+#ifndef ISC_PLATFORM_H
+#define ISC_PLATFORM_H 1
+
+/*****
+ ***** Platform-dependent defines.
+ *****/
+
+#define ISC_PLATFORM_USETHREADS
+
+/***
+ *** Network.
+ ***/
+
+#define ISC_PLATFORM_HAVEIPV6
+#if _MSC_VER > 1200
+#define ISC_PLATFORM_HAVEIN6PKTINFO
+#endif
+#define ISC_PLATFORM_HAVESCOPEID
+#define ISC_PLATFORM_NEEDPORTT
+#undef MSG_TRUNC
+#define ISC_PLATFORM_NEEDNTOP
+#define ISC_PLATFORM_NEEDPTON
+#define ISC_PLATFORM_NEEDATON
+
+#define ISC_PLATFORM_QUADFORMAT "I64"
+
+#define ISC_PLATFORM_NEEDSTRSEP
+#define ISC_PLATFORM_NEEDSTRLCPY
+#define ISC_PLATFORM_NEEDSTRLCAT
+#define ISC_PLATFORM_NEEDSTRLCPY
+
+/*
+ * Used to control how extern data is linked; needed for Win32 platforms.
+ */
+#define ISC_PLATFORM_USEDECLSPEC 1
+
+/*
+ * Define this here for now as winsock2.h defines h_errno
+ * and we don't want to redeclare it.
+ */
+#define ISC_PLATFORM_NONSTDHERRNO
+
+/*
+ * Define if the platform has <sys/un.h>.
+ */
+#undef ISC_PLATFORM_HAVESYSUNH
+
+ /*
+ * Set up a macro for importing and exporting from the DLL
+ */
+
+#ifdef LIBISC_EXPORTS
+#define LIBISC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBISCCFG_EXPORTS
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCFG_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBISCCC_EXPORTS
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBISCCC_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBDNS_EXPORTS
+#define LIBDNS_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBDNS_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#ifdef LIBBIND9_EXPORTS
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBBIND9_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+#endif /* ISC_PLATFORM_H */
diff --git a/lib/isc/win32/include/isc/stat.h b/lib/isc/win32/include/isc/stat.h
new file mode 100644
index 0000000..2638a91
--- /dev/null
+++ b/lib/isc/win32/include/isc/stat.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004, 2007 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
+ * 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: stat.h,v 1.7 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_STAT_H
+#define ISC_STAT_H 1
+
+#include <sys/stat.h>
+
+/* open() under unix allows setting of read/write permissions
+ * at the owner, group and other levels. These don't exist in NT
+ * We'll just map them all to the NT equivalent
+ */
+
+#define S_IREAD _S_IREAD /* read permission, owner */
+#define S_IWRITE _S_IWRITE /* write permission, owner */
+#define S_IRUSR _S_IREAD /* Owner read permission */
+#define S_IWUSR _S_IWRITE /* Owner write permission */
+#define S_IRGRP _S_IREAD /* Group read permission */
+#define S_IWGRP _S_IWRITE /* Group write permission */
+#define S_IROTH _S_IREAD /* Other read permission */
+#define S_IWOTH _S_IWRITE /* Other write permission */
+
+#ifndef S_ISDIR
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#ifndef S_ISREG
+# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+#endif /* ISC_STAT_H */
diff --git a/lib/isc/win32/include/isc/stdtime.h b/lib/isc/win32/include/isc/stdtime.h
new file mode 100644
index 0000000..4f9eb74
--- /dev/null
+++ b/lib/isc/win32/include/isc/stdtime.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: stdtime.h,v 1.12 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_STDTIME_H
+#define ISC_STDTIME_H 1
+
+#include <isc/lang.h>
+#include <isc/int.h>
+
+/*
+ * It's public information that 'isc_stdtime_t' is an unsigned integral type.
+ * Applications that want maximum portability should not assume anything
+ * about its size.
+ */
+typedef isc_uint32_t isc_stdtime_t;
+/*
+ * isc_stdtime32_t is a 32-bit version of isc_stdtime_t. A variable of this
+ * type should only be used as an opaque integer (e.g.,) to compare two
+ * time values.
+ */
+typedef isc_uint32_t isc_stdtime32_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_stdtime_get(isc_stdtime_t *t);
+/*
+ * Set 't' to the number of seconds since 00:00:00 UTC, January 1, 1970.
+ *
+ * Requires:
+ *
+ * 't' is a valid pointer.
+ */
+
+#define isc_stdtime_convert32(t, t32p) (*(t32p) = t)
+/*
+ * Convert the standard time to its 32-bit version.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STDTIME_H */
diff --git a/lib/isc/win32/include/isc/strerror.h b/lib/isc/win32/include/isc/strerror.h
new file mode 100644
index 0000000..38d2ef2
--- /dev/null
+++ b/lib/isc/win32/include/isc/strerror.h
@@ -0,0 +1,42 @@
+/*
+ * 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: strerror.h,v 1.5 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_STRERROR_H
+#define ISC_STRERROR_H
+
+#include <sys/types.h>
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+#define ISC_STRERRORSIZE 128
+
+/*
+ * Provide a thread safe wrapper to strerrror().
+ *
+ * Requires:
+ * 'buf' to be non NULL.
+ */
+void
+isc__strerror(int num, char *buf, size_t bufsize);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_STRERROR_H */
diff --git a/lib/isc/win32/include/isc/syslog.h b/lib/isc/win32/include/isc/syslog.h
new file mode 100644
index 0000000..765c0e5
--- /dev/null
+++ b/lib/isc/win32/include/isc/syslog.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: syslog.h,v 1.5 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_SYSLOG_H
+#define ISC_SYSLOG_H 1
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_syslog_facilityfromstring(const char *str, int *facilityp);
+/*
+ * Convert 'str' to the appropriate syslog facility constant.
+ *
+ * Requires:
+ *
+ * 'str' is not NULL
+ * 'facilityp' is not NULL
+ *
+ * Returns:
+ * ISC_R_SUCCESS
+ * ISC_R_NOTFOUND
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_SYSLOG_H */
diff --git a/lib/isc/win32/include/isc/thread.h b/lib/isc/win32/include/isc/thread.h
new file mode 100644
index 0000000..78e663f
--- /dev/null
+++ b/lib/isc/win32/include/isc/thread.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: thread.h,v 1.22 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_THREAD_H
+#define ISC_THREAD_H 1
+
+#include <windows.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+
+/*
+ * Inlines to help with wait retrun checking
+ */
+
+/* check handle for NULL and INVALID_HANDLE */
+inline BOOL IsValidHandle( HANDLE hHandle) {
+ return ((hHandle != NULL) && (hHandle != INVALID_HANDLE_VALUE));
+}
+
+/* validate wait return codes... */
+inline BOOL WaitSucceeded( DWORD dwWaitResult, DWORD dwHandleCount) {
+ return ((dwWaitResult >= WAIT_OBJECT_0) &&
+ (dwWaitResult < WAIT_OBJECT_0 + dwHandleCount));
+}
+
+inline BOOL WaitAbandoned( DWORD dwWaitResult, DWORD dwHandleCount) {
+ return ((dwWaitResult >= WAIT_ABANDONED_0) &&
+ (dwWaitResult < WAIT_ABANDONED_0 + dwHandleCount));
+}
+
+inline BOOL WaitTimeout( DWORD dwWaitResult) {
+ return (dwWaitResult == WAIT_TIMEOUT);
+}
+
+inline BOOL WaitFailed( DWORD dwWaitResult) {
+ return (dwWaitResult == WAIT_FAILED);
+}
+
+/* compute object indices for waits... */
+inline DWORD WaitSucceededIndex( DWORD dwWaitResult) {
+ return (dwWaitResult - WAIT_OBJECT_0);
+}
+
+inline DWORD WaitAbandonedIndex( DWORD dwWaitResult) {
+ return (dwWaitResult - WAIT_ABANDONED_0);
+}
+
+
+
+typedef HANDLE isc_thread_t;
+typedef unsigned int isc_threadresult_t;
+typedef void * isc_threadarg_t;
+typedef isc_threadresult_t (WINAPI *isc_threadfunc_t)(isc_threadarg_t);
+typedef DWORD isc_thread_key_t;
+
+#define isc_thread_self (unsigned long)GetCurrentThreadId
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_thread_create(isc_threadfunc_t, isc_threadarg_t, isc_thread_t *);
+
+isc_result_t
+isc_thread_join(isc_thread_t, isc_threadresult_t *);
+
+void
+isc_thread_setconcurrency(unsigned int level);
+
+int
+isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *));
+
+int
+isc_thread_key_delete(isc_thread_key_t key);
+
+void *
+isc_thread_key_getspecific(isc_thread_key);
+
+int
+isc_thread_key_setspecific(isc_thread_key_t key, void *value);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_THREAD_H */
diff --git a/lib/isc/win32/include/isc/time.h b/lib/isc/win32/include/isc/time.h
new file mode 100644
index 0000000..af0cddb
--- /dev/null
+++ b/lib/isc/win32/include/isc/time.h
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2004, 2006-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: time.h,v 1.33 2008/09/08 23:47:10 tbox Exp $ */
+
+#ifndef ISC_TIME_H
+#define ISC_TIME_H 1
+
+#include <windows.h>
+
+#include <isc/lang.h>
+#include <isc/types.h>
+
+/***
+ *** Intervals
+ ***/
+
+/*
+ * The contents of this structure are private, and MUST NOT be accessed
+ * directly by callers.
+ *
+ * The contents are exposed only to allow callers to avoid dynamic allocation.
+ */
+struct isc_interval {
+ isc_int64_t interval;
+};
+
+LIBISC_EXTERNAL_DATA extern isc_interval_t *isc_interval_zero;
+
+ISC_LANG_BEGINDECLS
+
+void
+isc_interval_set(isc_interval_t *i,
+ unsigned int seconds, unsigned int nanoseconds);
+/*
+ * Set 'i' to a value representing an interval of 'seconds' seconds and
+ * 'nanoseconds' nanoseconds, suitable for use in isc_time_add() and
+ * isc_time_subtract().
+ *
+ * Requires:
+ *
+ * 't' is a valid pointer.
+ * nanoseconds < 1000000000.
+ */
+
+isc_boolean_t
+isc_interval_iszero(const isc_interval_t *i);
+/*
+ * Returns ISC_TRUE iff. 'i' is the zero interval.
+ *
+ * Requires:
+ *
+ * 'i' is a valid pointer.
+ */
+
+/***
+ *** Absolute Times
+ ***/
+
+/*
+ * The contents of this structure are private, and MUST NOT be accessed
+ * directly by callers.
+ *
+ * The contents are exposed only to allow callers to avoid dynamic allocation.
+ */
+
+struct isc_time {
+ FILETIME absolute;
+};
+
+LIBISC_EXTERNAL_DATA extern isc_time_t *isc_time_epoch;
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds);
+/*%<
+ * Set 't' to a value which represents the given number of seconds and
+ * nanoseconds since 00:00:00 January 1, 1970, UTC.
+ *
+ * Requires:
+ *\li 't' is a valid pointer.
+ *\li nanoseconds < 1000000000.
+ */
+
+void
+isc_time_settoepoch(isc_time_t *t);
+/*
+ * Set 't' to the time of the epoch.
+ *
+ * Notes:
+ * The date of the epoch is platform-dependent.
+ *
+ * Requires:
+ *
+ * 't' is a valid pointer.
+ */
+
+isc_boolean_t
+isc_time_isepoch(const isc_time_t *t);
+/*
+ * Returns ISC_TRUE iff. 't' is the epoch ("time zero").
+ *
+ * Requires:
+ *
+ * 't' is a valid pointer.
+ */
+
+isc_result_t
+isc_time_now(isc_time_t *t);
+/*
+ * Set 't' to the current absolute time.
+ *
+ * Requires:
+ *
+ * 't' is a valid pointer.
+ *
+ * Returns:
+ *
+ * Success
+ * Unexpected error
+ * Getting the time from the system failed.
+ * Out of range
+ * The time from the system is too large to be represented
+ * in the current definition of isc_time_t.
+ */
+
+isc_result_t
+isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i);
+/*
+ * Set *t to the current absolute time + i.
+ *
+ * Note:
+ * This call is equivalent to:
+ *
+ * isc_time_now(t);
+ * isc_time_add(t, i, t);
+ *
+ * Requires:
+ *
+ * 't' and 'i' are valid pointers.
+ *
+ * Returns:
+ *
+ * Success
+ * Unexpected error
+ * Getting the time from the system failed.
+ * Out of range
+ * The interval added to the time from the system is too large to
+ * be represented in the current definition of isc_time_t.
+ */
+
+int
+isc_time_compare(const isc_time_t *t1, const isc_time_t *t2);
+/*
+ * Compare the times referenced by 't1' and 't2'
+ *
+ * Requires:
+ *
+ * 't1' and 't2' are valid pointers.
+ *
+ * Returns:
+ *
+ * -1 t1 < t2 (comparing times, not pointers)
+ * 0 t1 = t2
+ * 1 t1 > t2
+ */
+
+isc_result_t
+isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result);
+/*
+ * Add 'i' to 't', storing the result in 'result'.
+ *
+ * Requires:
+ *
+ * 't', 'i', and 'result' are valid pointers.
+ *
+ * Returns:
+ * Success
+ * Out of range
+ * The interval added to the time is too large to
+ * be represented in the current definition of isc_time_t.
+ */
+
+isc_result_t
+isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
+ isc_time_t *result);
+/*
+ * Subtract 'i' from 't', storing the result in 'result'.
+ *
+ * Requires:
+ *
+ * 't', 'i', and 'result' are valid pointers.
+ *
+ * Returns:
+ * Success
+ * Out of range
+ * The interval is larger than the time since the epoch.
+ */
+
+isc_uint64_t
+isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2);
+/*
+ * Find the difference in milliseconds between time t1 and time t2.
+ * t2 is the subtrahend of t1; ie, difference = t1 - t2.
+ *
+ * Requires:
+ *
+ * 't1' and 't2' are valid pointers.
+ *
+ * Returns:
+ * The difference of t1 - t2, or 0 if t1 <= t2.
+ */
+
+isc_uint32_t
+isc_time_nanoseconds(const isc_time_t *t);
+/*
+ * Return the number of nanoseconds stored in a time structure.
+ *
+ * Notes:
+ * This is the number of nanoseconds in excess of the the number
+ * of seconds since the epoch; it will always be less than one
+ * full second.
+ *
+ * Requires:
+ * 't' is a valid pointer.
+ *
+ * Ensures:
+ * The returned value is less than 1*10^9.
+ */
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len);
+/*
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using a format like "30-Aug-2000 04:06:47.997" and the local time zone.
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ * Requires:
+ * 'len' > 0
+ * 'buf' points to an array of at least len chars
+ *
+ */
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len);
+/*
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using a format like "Mon, 30 Aug 2000 04:06:47 GMT"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ * Requires:
+ * 'len' > 0
+ * 'buf' points to an array of at least len chars
+ *
+ */
+
+void
+isc_time_formatISO8601(const isc_time_t *t, char *buf, unsigned int len);
+/*%<
+ * Format the time 't' into the buffer 'buf' of length 'len',
+ * using the ISO8601 format: "yyyy-mm-ddThh:mm:ssZ"
+ * If the text does not fit in the buffer, the result is indeterminate,
+ * but is always guaranteed to be null terminated.
+ *
+ * Requires:
+ *\li 'len' > 0
+ *\li 'buf' points to an array of at least len chars
+ *
+ */
+
+isc_uint32_t
+isc_time_seconds(const isc_time_t *t);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_TIME_H */
diff --git a/lib/isc/win32/include/isc/win32os.h b/lib/isc/win32/include/isc/win32os.h
new file mode 100644
index 0000000..d868205
--- /dev/null
+++ b/lib/isc/win32/include/isc/win32os.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: win32os.h,v 1.5 2007/06/19 23:47:20 tbox Exp $ */
+
+#ifndef ISC_WIN32OS_H
+#define ISC_WIN32OS_H 1
+
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+/*
+ * Return the number of CPUs available on the system, or 1 if this cannot
+ * be determined.
+ */
+
+unsigned int
+isc_win32os_majorversion(void);
+/*
+ * Major Version of the O/S.
+ */
+
+unsigned int
+isc_win32os_minorversion(void);
+/*
+ * Minor Version of the O/S.
+ */
+
+unsigned int
+isc_win32os_servicepackmajor(void);
+/*
+ * Major Version of the Service Pack for O/S.
+ */
+
+unsigned int
+isc_win32os_servicepackminor(void);
+/*
+ * Minor Version of the Service Pack for O/S.
+ */
+
+int
+isc_win32os_versioncheck(unsigned int major, unsigned int minor,
+ unsigned int updatemajor, unsigned int updateminor);
+
+/*
+ * Checks the current version of the operating system with the
+ * supplied version information.
+ * Returns:
+ * -1 if less than the version information supplied
+ * 0 if equal to all of the version information supplied
+ * +1 if greater than the version information supplied
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_OS_H */
diff --git a/lib/isc/win32/interfaceiter.c b/lib/isc/win32/interfaceiter.c
new file mode 100644
index 0000000..1451249
--- /dev/null
+++ b/lib/isc/win32/interfaceiter.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: interfaceiter.c,v 1.13 2008/04/18 19:47:48 each Exp $ */
+
+/*
+ * Note that this code will need to be revisited to support IPv6 Interfaces.
+ * For now we just iterate through IPv4 interfaces.
+ */
+
+#include <config.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <isc/interfaceiter.h>
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/strerror.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+void InitSockets(void);
+
+/* Common utility functions */
+
+/*
+ * Extract the network address part from a "struct sockaddr".
+ *
+ * The address family is given explicity
+ * instead of using src->sa_family, because the latter does not work
+ * for copying a network mask obtained by SIOCGIFNETMASK (it does
+ * not have a valid address family).
+ */
+
+
+#define IFITER_MAGIC 0x49464954U /* IFIT. */
+#define VALID_IFITER(t) ((t) != NULL && (t)->magic == IFITER_MAGIC)
+
+struct isc_interfaceiter {
+ unsigned int magic; /* Magic number. */
+ isc_mem_t *mctx;
+ int socket;
+ INTERFACE_INFO IFData; /* Current Interface Info */
+ int numIF; /* Current Interface count */
+ int v4IF; /* Number of IPv4 Interfaces */
+ INTERFACE_INFO *buf4; /* Buffer for WSAIoctl data. */
+ unsigned int buf4size; /* Bytes allocated. */
+ INTERFACE_INFO *pos4; /* Current offset in IF List */
+ SOCKET_ADDRESS_LIST *buf6;
+ unsigned int buf6size; /* Bytes allocated. */
+ unsigned int pos6;
+ isc_interface_t current; /* Current interface data. */
+ isc_result_t result; /* Last result code. */
+};
+
+
+/*
+ * Size of buffer for SIO_GET_INTERFACE_LIST, in number of interfaces.
+ * We assume no sane system will have more than than 1K of IP addresses on
+ * all of its adapters.
+ */
+#define IFCONF_SIZE_INITIAL 16
+#define IFCONF_SIZE_INCREMENT 64
+#define IFCONF_SIZE_MAX 1040
+
+static void
+get_addr(unsigned int family, isc_netaddr_t *dst, struct sockaddr *src) {
+ dst->family = family;
+ switch (family) {
+ case AF_INET:
+ memcpy(&dst->type.in,
+ &((struct sockaddr_in *) src)->sin_addr,
+ sizeof(struct in_addr));
+ break;
+ case AF_INET6:
+ memcpy(&dst->type.in6,
+ &((struct sockaddr_in6 *) src)->sin6_addr,
+ sizeof(struct in6_addr));
+ dst->zone = ((struct sockaddr_in6 *) src)->sin6_scope_id;
+ break;
+ default:
+ INSIST(0);
+ break;
+ }
+}
+
+isc_result_t
+isc_interfaceiter_create(isc_mem_t *mctx, isc_interfaceiter_t **iterp) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc_interfaceiter_t *iter;
+ isc_result_t result;
+ int error;
+ unsigned long bytesReturned = 0;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(iterp != NULL);
+ REQUIRE(*iterp == NULL);
+
+ iter = isc_mem_get(mctx, sizeof(*iter));
+ if (iter == NULL)
+ return (ISC_R_NOMEMORY);
+
+ InitSockets();
+
+ iter->mctx = mctx;
+ iter->buf4 = NULL;
+ iter->buf6 = NULL;
+ iter->pos4 = NULL;
+ iter->pos6 = 0;
+ iter->buf6size = 0;
+ iter->buf4size = 0;
+ iter->result = ISC_R_FAILURE;
+ iter->numIF = 0;
+ iter->v4IF = 0;
+
+ /*
+ * Create an unbound datagram socket to do the
+ * SIO_GET_INTERFACE_LIST WSAIoctl on.
+ */
+ if ((iter->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ error = WSAGetLastError();
+ if (error == WSAEAFNOSUPPORT)
+ goto inet6_only;
+ isc__strerror(error, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "making interface scan socket: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto socket_failure;
+ }
+
+ /*
+ * Get the interface configuration, allocating more memory if
+ * necessary.
+ */
+ iter->buf4size = IFCONF_SIZE_INITIAL*sizeof(INTERFACE_INFO);
+
+ for (;;) {
+ iter->buf4 = isc_mem_get(mctx, iter->buf4size);
+ if (iter->buf4 == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto alloc_failure;
+ }
+
+ if (WSAIoctl(iter->socket, SIO_GET_INTERFACE_LIST,
+ 0, 0, iter->buf4, iter->buf4size,
+ &bytesReturned, 0, 0) == SOCKET_ERROR)
+ {
+ error = WSAGetLastError();
+ if (error != WSAEFAULT && error != WSAENOBUFS) {
+ errno = error;
+ isc__strerror(error, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "get interface configuration: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto ioctl_failure;
+ }
+ /*
+ * EINVAL. Retry with a bigger buffer.
+ */
+ } else {
+ /*
+ * The WSAIoctl succeeded.
+ * If the number of the returned bytes is the same
+ * as the buffer size, we will grow it just in
+ * case and retry.
+ */
+ if (bytesReturned > 0 &&
+ (bytesReturned < iter->buf4size))
+ break;
+ }
+ if (iter->buf4size >= IFCONF_SIZE_MAX*sizeof(INTERFACE_INFO)) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "get interface configuration: "
+ "maximum buffer size exceeded");
+ result = ISC_R_UNEXPECTED;
+ goto ioctl_failure;
+ }
+ isc_mem_put(mctx, iter->buf4, iter->buf4size);
+
+ iter->buf4size += IFCONF_SIZE_INCREMENT *
+ sizeof(INTERFACE_INFO);
+ }
+
+ /*
+ * A newly created iterator has an undefined position
+ * until isc_interfaceiter_first() is called.
+ */
+ iter->v4IF = bytesReturned/sizeof(INTERFACE_INFO);
+
+ /* We don't need the socket any more, so close it */
+ closesocket(iter->socket);
+
+ inet6_only:
+ /*
+ * Create an unbound datagram socket to do the
+ * SIO_ADDRESS_LIST_QUERY WSAIoctl on.
+ */
+ if ((iter->socket = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ error = WSAGetLastError();
+ if (error == WSAEAFNOSUPPORT)
+ goto inet_only;
+ isc__strerror(error, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "making interface scan socket: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto ioctl_failure;
+ }
+
+ /*
+ * Get the interface configuration, allocating more memory if
+ * necessary.
+ */
+ iter->buf6size = sizeof(SOCKET_ADDRESS_LIST) +
+ IFCONF_SIZE_INITIAL*sizeof(SOCKET_ADDRESS);
+
+ for (;;) {
+ iter->buf6 = isc_mem_get(mctx, iter->buf6size);
+ if (iter->buf6 == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto ioctl_failure;
+ }
+
+ if (WSAIoctl(iter->socket, SIO_ADDRESS_LIST_QUERY,
+ 0, 0, iter->buf6, iter->buf6size,
+ &bytesReturned, 0, 0) == SOCKET_ERROR)
+ {
+ error = WSAGetLastError();
+ if (error != WSAEFAULT && error != WSAENOBUFS) {
+ errno = error;
+ isc__strerror(error, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "sio address list query: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto ioctl6_failure;
+ }
+ /*
+ * EINVAL. Retry with a bigger buffer.
+ */
+ } else
+ break;
+
+ if (iter->buf6size >= IFCONF_SIZE_MAX*sizeof(SOCKET_ADDRESS)) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "get interface configuration: "
+ "maximum buffer size exceeded");
+ result = ISC_R_UNEXPECTED;
+ goto ioctl6_failure;
+ }
+ isc_mem_put(mctx, iter->buf6, iter->buf6size);
+
+ iter->buf6size += IFCONF_SIZE_INCREMENT *
+ sizeof(SOCKET_ADDRESS);
+ }
+
+ closesocket(iter->socket);
+
+ inet_only:
+ iter->magic = IFITER_MAGIC;
+ *iterp = iter;
+ return (ISC_R_SUCCESS);
+
+ ioctl6_failure:
+ isc_mem_put(mctx, iter->buf6, iter->buf6size);
+
+ ioctl_failure:
+ if (iter->buf4 != NULL)
+ isc_mem_put(mctx, iter->buf4, iter->buf4size);
+
+ alloc_failure:
+ if (iter->socket >= 0)
+ (void) closesocket(iter->socket);
+
+ socket_failure:
+ isc_mem_put(mctx, iter, sizeof(*iter));
+ return (result);
+}
+
+/*
+ * Get information about the current interface to iter->current.
+ * If successful, return ISC_R_SUCCESS.
+ * If the interface has an unsupported address family, or if
+ * some operation on it fails, return ISC_R_IGNORE to make
+ * the higher-level iterator code ignore it.
+ */
+
+static isc_result_t
+internal_current(isc_interfaceiter_t *iter) {
+ BOOL ifNamed = FALSE;
+ unsigned long flags;
+
+ REQUIRE(VALID_IFITER(iter));
+ REQUIRE(iter->numIF >= 0);
+
+ memset(&iter->current, 0, sizeof(iter->current));
+ iter->current.af = AF_INET;
+
+ get_addr(AF_INET, &iter->current.address,
+ (struct sockaddr *)&(iter->IFData.iiAddress));
+
+ /*
+ * Get interface flags.
+ */
+
+ iter->current.flags = 0;
+ flags = iter->IFData.iiFlags;
+
+ if ((flags & IFF_UP) != 0)
+ iter->current.flags |= INTERFACE_F_UP;
+
+ if ((flags & IFF_POINTTOPOINT) != 0) {
+ iter->current.flags |= INTERFACE_F_POINTTOPOINT;
+ sprintf(iter->current.name, "PPP Interface %d", iter->numIF);
+ ifNamed = TRUE;
+ }
+
+ if ((flags & IFF_LOOPBACK) != 0) {
+ iter->current.flags |= INTERFACE_F_LOOPBACK;
+ sprintf(iter->current.name, "Loopback Interface %d",
+ iter->numIF);
+ ifNamed = TRUE;
+ }
+
+ /*
+ * If the interface is point-to-point, get the destination address.
+ */
+ if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
+ get_addr(AF_INET, &iter->current.dstaddress,
+ (struct sockaddr *)&(iter->IFData.iiBroadcastAddress));
+ }
+
+ if (ifNamed == FALSE)
+ sprintf(iter->current.name,
+ "TCP/IP Interface %d", iter->numIF);
+
+ /*
+ * Get the network mask.
+ */
+ get_addr(AF_INET, &iter->current.netmask,
+ (struct sockaddr *)&(iter->IFData.iiNetmask));
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+internal_current6(isc_interfaceiter_t *iter) {
+ BOOL ifNamed = FALSE;
+ int i;
+
+ REQUIRE(VALID_IFITER(iter));
+ REQUIRE(iter->pos6 >= 0);
+ REQUIRE(iter->buf6 != 0);
+
+ memset(&iter->current, 0, sizeof(iter->current));
+ iter->current.af = AF_INET6;
+
+ get_addr(AF_INET6, &iter->current.address,
+ iter->buf6->Address[iter->pos6].lpSockaddr);
+
+ /*
+ * Get interface flags.
+ */
+
+ iter->current.flags = INTERFACE_F_UP;
+
+ if (ifNamed == FALSE)
+ sprintf(iter->current.name,
+ "TCP/IPv6 Interface %d", iter->pos6 + 1);
+
+ for (i = 0; i< 16; i++)
+ iter->current.netmask.type.in6.s6_addr[i] = 0xff;
+ iter->current.netmask.family = AF_INET6;
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Step the iterator to the next interface. Unlike
+ * isc_interfaceiter_next(), this may leave the iterator
+ * positioned on an interface that will ultimately
+ * be ignored. Return ISC_R_NOMORE if there are no more
+ * interfaces, otherwise ISC_R_SUCCESS.
+ */
+static isc_result_t
+internal_next(isc_interfaceiter_t *iter) {
+ if (iter->numIF >= iter->v4IF)
+ return (ISC_R_NOMORE);
+
+ /*
+ * The first one needs to be set up to point to the last
+ * Element of the array. Go to the end and back up
+ * Microsoft's implementation is peculiar for returning
+ * the list in reverse order
+ */
+
+ if (iter->numIF == 0)
+ iter->pos4 = (INTERFACE_INFO *)(iter->buf4 + (iter->v4IF));
+
+ iter->pos4--;
+ if (&(iter->pos4) < &(iter->buf4))
+ return (ISC_R_NOMORE);
+
+ memset(&(iter->IFData), 0, sizeof(INTERFACE_INFO));
+ memcpy(&(iter->IFData), iter->pos4, sizeof(INTERFACE_INFO));
+ iter->numIF++;
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+internal_next6(isc_interfaceiter_t *iter) {
+ if (iter->pos6 == 0)
+ return (ISC_R_NOMORE);
+ iter->pos6--;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_interfaceiter_current(isc_interfaceiter_t *iter,
+ isc_interface_t *ifdata) {
+ REQUIRE(iter->result == ISC_R_SUCCESS);
+ memcpy(ifdata, &iter->current, sizeof(*ifdata));
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_interfaceiter_first(isc_interfaceiter_t *iter) {
+
+ REQUIRE(VALID_IFITER(iter));
+
+ if (iter->buf6 != NULL)
+ iter->pos6 = iter->buf6->iAddressCount;
+ iter->result = ISC_R_SUCCESS;
+ return (isc_interfaceiter_next(iter));
+}
+
+isc_result_t
+isc_interfaceiter_next(isc_interfaceiter_t *iter) {
+ isc_result_t result;
+
+ REQUIRE(VALID_IFITER(iter));
+ REQUIRE(iter->result == ISC_R_SUCCESS);
+
+ for (;;) {
+ result = internal_next(iter);
+ if (result == ISC_R_NOMORE) {
+ result = internal_next6(iter);
+ if (result != ISC_R_SUCCESS)
+ break;
+ result = internal_current6(iter);
+ if (result != ISC_R_IGNORE)
+ break;
+ } else if (result != ISC_R_SUCCESS)
+ break;
+ result = internal_current(iter);
+ if (result != ISC_R_IGNORE)
+ break;
+ }
+ iter->result = result;
+ return (result);
+}
+
+void
+isc_interfaceiter_destroy(isc_interfaceiter_t **iterp) {
+ isc_interfaceiter_t *iter;
+ REQUIRE(iterp != NULL);
+ iter = *iterp;
+ REQUIRE(VALID_IFITER(iter));
+
+ if (iter->buf4 != NULL)
+ isc_mem_put(iter->mctx, iter->buf4, iter->buf4size);
+ if (iter->buf6 != NULL)
+ isc_mem_put(iter->mctx, iter->buf6, iter->buf6size);
+
+ iter->magic = 0;
+ isc_mem_put(iter->mctx, iter, sizeof(*iter));
+ *iterp = NULL;
+}
diff --git a/lib/isc/win32/ipv6.c b/lib/isc/win32/ipv6.c
new file mode 100644
index 0000000..511ae21
--- /dev/null
+++ b/lib/isc/win32/ipv6.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: ipv6.c,v 1.8 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <isc/net.h>
+#include <isc/platform.h>
+
+LIBISC_EXTERNAL_DATA const struct in6_addr isc_in6addr_any =
+ IN6ADDR_ANY_INIT;
+
+LIBISC_EXTERNAL_DATA const struct in6_addr isc_in6addr_loopback =
+ IN6ADDR_LOOPBACK_INIT;
diff --git a/lib/isc/win32/keyboard.c b/lib/isc/win32/keyboard.c
new file mode 100644
index 0000000..d569e7c
--- /dev/null
+++ b/lib/isc/win32/keyboard.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2004, 2007 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: keyboard.c,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <sys/types.h>
+
+#include <windows.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <io.h>
+
+#include <isc/keyboard.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_keyboard_open(isc_keyboard_t *keyboard) {
+ int fd;
+
+ REQUIRE(keyboard != NULL);
+
+ fd = _fileno(stdin);
+ if (fd < 0)
+ return (ISC_R_IOERROR);
+
+ keyboard->fd = fd;
+
+ keyboard->result = ISC_R_SUCCESS;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_keyboard_close(isc_keyboard_t *keyboard, unsigned int sleeptime) {
+ REQUIRE(keyboard != NULL);
+
+ if (sleeptime > 0 && keyboard->result != ISC_R_CANCELED)
+ (void)Sleep(sleeptime*1000);
+
+ keyboard->fd = -1;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_keyboard_getchar(isc_keyboard_t *keyboard, unsigned char *cp) {
+ ssize_t cc;
+ unsigned char c;
+
+ REQUIRE(keyboard != NULL);
+ REQUIRE(cp != NULL);
+
+ cc = read(keyboard->fd, &c, 1);
+ if (cc < 0) {
+ keyboard->result = ISC_R_IOERROR;
+ return (keyboard->result);
+ }
+
+ *cp = c;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_boolean_t
+isc_keyboard_canceled(isc_keyboard_t *keyboard) {
+ return (ISC_TF(keyboard->result == ISC_R_CANCELED));
+}
+
diff --git a/lib/isc/win32/libisc.def b/lib/isc/win32/libisc.def
new file mode 100644
index 0000000..065a602
--- /dev/null
+++ b/lib/isc/win32/libisc.def
@@ -0,0 +1,542 @@
+LIBRARY libisc
+
+; Exported Functions
+EXPORTS
+
+NTReportError
+closelog
+isc__buffer_activeregion
+isc__buffer_add
+isc__buffer_availableregion
+isc__buffer_back
+isc__buffer_clear
+isc__buffer_consumedregion
+isc__buffer_first
+isc__buffer_forward
+isc__buffer_init
+isc__buffer_invalidate
+isc__buffer_putmem
+isc__buffer_putstr
+isc__buffer_putuint16
+isc__buffer_putuint32
+isc__buffer_putuint48
+isc__buffer_putuint8
+isc__buffer_region
+isc__buffer_remainingregion
+isc__buffer_setactive
+isc__buffer_subtract
+isc__buffer_usedregion
+isc__mem_allocate
+isc__mem_free
+isc__mem_get
+isc__mem_put
+isc__mem_putanddetach
+isc__mem_strdup
+isc__mempool_get
+isc__mempool_put
+isc__socketmgr_setreserved
+isc__strerror
+isc_app_block
+isc_app_finish
+isc_app_onrun
+isc_app_reload
+isc_app_run
+isc_app_shutdown
+isc_app_start
+isc_app_unblock
+isc_assertion_setcallback
+isc_assertion_typetotext
+isc_base32_decoderegion
+isc_base32_decodestring
+isc_base32_tobuffer
+isc_base32_totext
+isc_base32hex_decoderegion
+isc_base32hex_decodestring
+isc_base32hex_tobuffer
+isc_base32hex_totext
+isc_base64_decodestring
+isc_base64_tobuffer
+isc_base64_totext
+isc_bitstring_copy
+isc_bitstring_init
+isc_bitstring_invalidate
+isc_buffer_allocate
+isc_buffer_compact
+isc_buffer_copyregion
+isc_buffer_free
+isc_buffer_getuint16
+isc_buffer_getuint32
+isc_buffer_getuint8
+isc_buffer_reinit
+isc_bufferlist_availablecount
+isc_bufferlist_usedcount
+isc_commandline_parse
+isc_condition_broadcast
+isc_condition_destroy
+isc_condition_init
+isc_condition_signal
+isc_condition_wait
+isc_condition_waituntil
+isc_dir_chdir
+isc_dir_chroot
+isc_dir_close
+isc_dir_init
+isc_dir_open
+isc_dir_read
+isc_dir_reset
+isc_entropy_addcallbacksample
+isc_entropy_addsample
+isc_entropy_attach
+isc_entropy_create
+isc_entropy_createcallbacksource
+isc_entropy_createfilesource
+isc_entropy_createsamplesource
+isc_entropy_destroysource
+isc_entropy_detach
+isc_entropy_getdata
+isc_entropy_putdata
+isc_entropy_stats
+isc_entropy_status
+isc_entropy_stopcallbacksources
+isc_entropy_usebestsource
+isc_error_fatal
+isc_error_runtimecheck
+isc_error_setfatal
+isc_error_setunexpected
+isc_error_unexpected
+isc_event_allocate
+isc_event_free
+isc_file_absolutepath
+isc_file_basename
+isc_file_exists
+isc_file_getmodtime
+isc_file_isabsolute
+isc_file_ischdiridempotent
+isc_file_iscurrentdir
+isc_file_mktemplate
+isc_file_openunique
+isc_file_progname
+isc_file_remove
+isc_file_rename
+isc_file_renameunique
+isc_file_safemovefile
+isc_file_settime
+isc_file_template
+isc_file_truncate
+isc_fsaccess_add
+isc_fsaccess_changeowner
+isc_fsaccess_remove
+isc_fsaccess_set
+isc_hash_calc
+isc_hash_create
+isc_hash_ctxattach
+isc_hash_ctxcalc
+isc_hash_ctxcreate
+isc_hash_ctxdetach
+isc_hash_ctxinit
+isc_hash_destroy
+isc_hash_init
+isc_heap_create
+isc_heap_decreased
+isc_heap_delete
+isc_heap_destroy
+isc_heap_element
+isc_heap_increased
+isc_heap_insert
+isc_hex_decodestring
+isc_hex_tobuffer
+isc_hex_totext
+isc_hmacmd5_init
+isc_hmacmd5_invalidate
+isc_hmacmd5_sign
+isc_hmacmd5_update
+isc_hmacmd5_verify
+isc_hmacmd5_verify2
+isc_hmacsha1_init
+isc_hmacsha1_invalidate
+isc_hmacsha1_sign
+isc_hmacsha1_update
+isc_hmacsha1_verify
+isc_hmacsha224_init
+isc_hmacsha224_invalidate
+isc_hmacsha224_sign
+isc_hmacsha224_update
+isc_hmacsha224_verify
+isc_hmacsha256_init
+isc_hmacsha256_invalidate
+isc_hmacsha256_sign
+isc_hmacsha256_update
+isc_hmacsha256_verify
+isc_hmacsha384_init
+isc_hmacsha384_invalidate
+isc_hmacsha384_sign
+isc_hmacsha384_update
+isc_hmacsha384_verify
+isc_hmacsha512_init
+isc_hmacsha512_invalidate
+isc_hmacsha512_sign
+isc_hmacsha512_update
+isc_hmacsha512_verify
+isc_httpdmgr_addurl
+isc_httpdmgr_create
+isc_httpdmgr_shutdown
+isc_interfaceiter_create
+isc_interfaceiter_current
+isc_interfaceiter_destroy
+isc_interfaceiter_first
+isc_interfaceiter_next
+isc_interval_iszero
+isc_interval_set
+isc_iterated_hash
+isc_keyboard_canceled
+isc_keyboard_close
+isc_keyboard_getchar
+isc_keyboard_open
+isc_lex_close
+isc_lex_create
+isc_lex_destroy
+isc_lex_getcomments
+isc_lex_getlasttokentext
+isc_lex_getmastertoken
+isc_lex_getoctaltoken
+isc_lex_getsourceline
+isc_lex_getsourcename
+isc_lex_getspecials
+isc_lex_gettoken
+isc_lex_isfile
+isc_lex_openbuffer
+isc_lex_openfile
+isc_lex_openstream
+isc_lex_setcomments
+isc_lex_setspecials
+isc_lex_ungettoken
+isc_lfsr_generate
+isc_lfsr_generate32
+isc_lfsr_init
+isc_lfsr_skip
+isc_lib_initmsgcat
+isc_log_categorybyname
+isc_log_closefilelogs
+isc_log_create
+isc_log_createchannel
+isc_log_destroy
+isc_log_getdebuglevel
+isc_log_getduplicateinterval
+isc_log_gettag
+isc_log_ivwrite
+isc_log_ivwrite1
+isc_log_iwrite
+isc_log_iwrite1
+isc_log_modulebyname
+isc_log_opensyslog
+isc_log_registercategories
+isc_log_registermodules
+isc_log_setcontext
+isc_log_setdebuglevel
+isc_log_setduplicateinterval
+isc_log_settag
+isc_log_usechannel
+isc_log_vwrite
+isc_log_vwrite1
+isc_log_wouldlog
+isc_log_write
+isc_log_write1
+isc_logconfig_create
+isc_logconfig_destroy
+isc_logconfig_get
+isc_logconfig_use
+isc_md5_final
+isc_md5_init
+isc_md5_invalidate
+isc_md5_update
+isc_mem_attach
+isc_mem_checkdestroyed
+isc_mem_create
+isc_mem_create2
+isc_mem_createx
+isc_mem_createx2
+isc_mem_destroy
+isc_mem_detach
+isc_mem_getname
+isc_mem_getquota
+isc_mem_gettag
+isc_mem_inuse
+isc_mem_ondestroy
+isc_mem_references
+isc_mem_setdestroycheck
+isc_mem_setname
+isc_mem_setquota
+isc_mem_setwater
+isc_mem_stats
+isc_mem_waterack
+isc_mempool_associatelock
+isc_mempool_create
+isc_mempool_destroy
+isc_mempool_getallocated
+isc_mempool_getfillcount
+isc_mempool_getfreecount
+isc_mempool_getfreemax
+isc_mempool_getmaxalloc
+isc_mempool_setfillcount
+isc_mempool_setfreemax
+isc_mempool_setmaxalloc
+isc_mempool_setname
+isc_msgcat_close
+isc_msgcat_get
+isc_msgcat_open
+isc_mutexblock_destroy
+isc_mutexblock_init
+isc_net_aton
+isc_net_disableipv4
+isc_net_disableipv6
+isc_net_getudpportrange
+isc_net_ntop
+isc_net_probe_ipv6only
+isc_net_probe_ipv6pktinfo
+isc_net_probeipv4
+isc_net_probeipv6
+isc_net_probeunix
+isc_net_pton
+isc_netaddr_any
+isc_netaddr_any6
+isc_netaddr_eqprefix
+isc_netaddr_equal
+isc_netaddr_format
+isc_netaddr_fromin
+isc_netaddr_fromin6
+isc_netaddr_frompath
+isc_netaddr_fromsockaddr
+isc_netaddr_fromv4mapped
+isc_netaddr_ismulticast
+isc_netaddr_masktoprefixlen
+isc_netaddr_prefixok
+isc_netaddr_setzone
+isc_netaddr_totext
+isc_netscope_pton
+isc_ntpaths_get
+isc_ntpaths_init
+isc_once_do
+isc_ondestroy_init
+isc_ondestroy_notify
+isc_ondestroy_register
+isc_os_ncpus
+isc_parse_uint16
+isc_parse_uint32
+isc_parse_uint8
+isc_portset_add
+isc_portset_addrange
+isc_portset_create
+isc_portset_destroy
+isc_portset_isset
+isc_portset_nports
+isc_portset_remove
+isc_portset_removerange
+isc_quota_attach
+isc_quota_destroy
+isc_quota_detach
+isc_quota_init
+isc_quota_max
+isc_quota_release
+isc_quota_reserve
+isc_quota_soft
+isc_radix_create
+isc_radix_destroy
+isc_radix_insert
+isc_radix_process
+isc_radix_remove
+isc_radix_search
+isc_random_get
+isc_random_jitter
+isc_random_seed
+isc_ratelimiter_attach
+isc_ratelimiter_create
+isc_ratelimiter_detach
+isc_ratelimiter_enqueue
+isc_ratelimiter_setinterval
+isc_ratelimiter_setpertic
+isc_ratelimiter_shutdown
+isc_refcount_init
+isc_region_compare
+isc_resource_getcurlimit
+isc_resource_getlimit
+isc_resource_setlimit
+isc_result_register
+isc_result_totext
+isc_rwlock_destroy
+isc_rwlock_downgrade
+isc_rwlock_init
+isc_rwlock_lock
+isc_rwlock_trylock
+isc_rwlock_tryupgrade
+isc_rwlock_unlock
+isc_serial_eq
+isc_serial_ge
+isc_serial_gt
+isc_serial_le
+isc_serial_lt
+isc_serial_ne
+isc_sha1_final
+isc_sha1_init
+isc_sha1_invalidate
+isc_sha1_update
+isc_sha224_final
+isc_sha224_init
+isc_sha224_update
+isc_sha256_final
+isc_sha256_init
+isc_sha256_update
+isc_sha384_final
+isc_sha384_init
+isc_sha384_update
+isc_sha512_final
+isc_sha512_init
+isc_sha512_update
+isc_sockaddr_any
+isc_sockaddr_any6
+isc_sockaddr_anyofpf
+isc_sockaddr_compare
+isc_sockaddr_eqaddr
+isc_sockaddr_eqaddrprefix
+isc_sockaddr_equal
+isc_sockaddr_format
+isc_sockaddr_fromin
+isc_sockaddr_fromin6
+isc_sockaddr_fromnetaddr
+isc_sockaddr_frompath
+isc_sockaddr_getport
+isc_sockaddr_hash
+isc_sockaddr_isexperimental
+isc_sockaddr_ismulticast
+isc_sockaddr_pf
+isc_sockaddr_setport
+isc_sockaddr_totext
+isc_sockaddr_v6fromin
+isc_socket_accept
+isc_socket_attach
+isc_socket_bind
+isc_socket_cancel
+isc_socket_cleanunix
+isc_socket_close
+isc_socket_connect
+isc_socket_create
+isc_socket_detach
+isc_socket_filter
+isc_socket_getname
+isc_socket_getpeername
+isc_socket_getsockname
+isc_socket_gettag
+isc_socket_gettype
+isc_socket_ipv6only
+isc_socket_isbound
+isc_socket_listen
+isc_socket_open
+isc_socket_permunix
+isc_socket_recv
+isc_socket_recv2
+isc_socket_recvv
+isc_socket_send
+isc_socket_sendto
+isc_socket_sendto2
+isc_socket_sendtov
+isc_socket_sendv
+isc_socket_setname
+isc_socketmgr_create
+isc_socketmgr_create2
+isc_socketmgr_destroy
+isc_socketmgr_getmaxsockets
+isc_stdio_close
+isc_stdio_flush
+isc_stdio_open
+isc_stdio_read
+isc_stdio_seek
+isc_stdio_sync
+isc_stdio_write
+isc_stdtime_get
+isc_string_append
+isc_string_append_truncate
+isc_string_copy
+isc_string_copy_truncate
+isc_string_printf
+isc_string_printf_truncate
+isc_string_regiondup
+isc_string_separate
+isc_string_strlcat
+isc_string_strlcpy
+isc_string_touint64
+isc_symtab_create
+isc_symtab_define
+isc_symtab_destroy
+isc_symtab_lookup
+isc_symtab_undefine
+isc_syslog_facilityfromstring
+isc_task_attach
+isc_task_beginexclusive
+isc_task_create
+isc_task_destroy
+isc_task_detach
+isc_task_endexclusive
+isc_task_getcurrenttime
+isc_task_getname
+isc_task_gettag
+isc_task_onshutdown
+isc_task_purge
+isc_task_purgeevent
+isc_task_purgerange
+isc_task_send
+isc_task_sendanddetach
+isc_task_setname
+isc_task_shutdown
+isc_task_unsend
+isc_task_unsendrange
+isc_taskmgr_create
+isc_taskmgr_destroy
+isc_taskpool_create
+isc_taskpool_destroy
+isc_taskpool_gettask
+isc_thread_create
+isc_thread_join
+isc_thread_key_create
+isc_thread_key_delete
+isc_thread_key_getspecific
+isc_thread_key_setspecific
+isc_thread_setconcurrency
+isc_time_add
+isc_time_compare
+isc_time_isepoch
+isc_time_microdiff
+isc_time_nanoseconds
+isc_time_now
+isc_time_nowplusinterval
+isc_time_seconds
+isc_time_set
+isc_time_settoepoch
+isc_time_subtract
+isc_timer_attach
+isc_timer_create
+isc_timer_detach
+isc_timer_reset
+isc_timer_touch
+isc_timermgr_create
+isc_timermgr_destroy
+isc_timermgr_poke
+isc_win32os_majorversion
+isc_win32os_minorversion
+isc_win32os_servicepackmajor
+isc_win32os_servicepackminor
+isc_win32os_versioncheck
+openlog
+syslog
+
+; Exported Data
+
+EXPORTS
+
+isc_assertion_failed DATA
+isc_commandline_argument DATA
+isc_commandline_errprint DATA
+isc_commandline_index DATA
+isc_commandline_option DATA
+isc_commandline_progname DATA
+isc_commandline_reset DATA
+isc_mem_debugging DATA
+
diff --git a/lib/isc/win32/libisc.dsp b/lib/isc/win32/libisc.dsp
new file mode 100644
index 0000000..d8094cd
--- /dev/null
+++ b/lib/isc/win32/libisc.dsp
@@ -0,0 +1,780 @@
+# Microsoft Developer Studio Project File - Name="libisc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libisc - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libisc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libisc.mak" CFG="libisc - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libisc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib /nologo /dll /machine:I386 /out:"../../../Build/Release/libisc.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib /nologo /dll /map /debug /machine:I386 /out:"../../../Build/Debug/libisc.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "libisc - Win32 Release"
+# Name "libisc - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\app.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\condition.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dir.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\DLLMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\entropy.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\errno2result.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\file.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\fsaccess.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\interfaceiter.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ipv6.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\iterated_hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\keyboard.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\net.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ntpaths.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\once.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\os.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\strerror.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\stdio.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\stdtime.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\syslog.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\thread.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\time.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\include\isc\app.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\assertions.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\base32.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\base64.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\bind_registry.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\bindevt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\bitstring.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\boolean.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\buffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\bufferlist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\commandline.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\condition.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\dir.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\entropy.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\errno2result.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\error.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\event.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\eventclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\file.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\formatcheck.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\fsaccess.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hash.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\heap.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hmacmd5.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\hmacsha.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\httpd.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\int.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\interfaceiter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\ipv6.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\iterated_hash.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\keyboard.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lang.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lfsr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\lib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\list.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\magic.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\mem.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\msgcat.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\msioctl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\mutex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\mutexblock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\net.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\netaddr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\netscope.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\netdb.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\ntpaths.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\offset.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\once.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\ondestroy.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\parseint.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\portset.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\os.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\platform.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\print.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\quota.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\radix.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\random.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\ratelimiter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\refcount.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\region.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\result.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\resultclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\rwlock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\serial.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\sha1.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\sha2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\sockaddr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\stat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\stdio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\strerror.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\stdtime.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\string.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\symtab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\syslog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\syslog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\task.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\taskpool.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\thread.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\time.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\timer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\isc\win32os.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\types.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\unistd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isc\util.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\versions.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Isc Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\assertions.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\base32.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\bitstring.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\buffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\bufferlist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\commandline.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\error.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\event.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\heap.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hmacmd5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\hmacsha.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\httpd.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\inet_aton.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\inet_ntop.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\inet_pton.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lfsr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mem.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nls\msgcat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\mutexblock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\netaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\netscope.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ondestroy.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\parseint.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\portset.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\quota.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\radix.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\random.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ratelimiter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\refcount.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\region.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\result.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\rwlock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\serial.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sha2.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sockaddr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\string.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\symtab.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\task.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\taskpool.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\timer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\win32os.c
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\noatomic\include\atomic.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\libisc.def
+# End Source File
+# End Target
+# End Project
diff --git a/lib/isc/win32/libisc.dsw b/lib/isc/win32/libisc.dsw
new file mode 100644
index 0000000..49c089c
--- /dev/null
+++ b/lib/isc/win32/libisc.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libisc"=".\libisc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/isc/win32/libisc.mak b/lib/isc/win32/libisc.mak
new file mode 100644
index 0000000..230358d
--- /dev/null
+++ b/lib/isc/win32/libisc.mak
@@ -0,0 +1,1974 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on libisc.dsp
+!IF "$(CFG)" == ""
+CFG=libisc - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to libisc - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "libisc - Win32 Release" && "$(CFG)" != "libisc - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libisc.mak" CFG="libisc - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libisc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\libisc.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\app.obj"
+ -@erase "$(INTDIR)\assertions.obj"
+ -@erase "$(INTDIR)\base32.obj"
+ -@erase "$(INTDIR)\base64.obj"
+ -@erase "$(INTDIR)\bitstring.obj"
+ -@erase "$(INTDIR)\buffer.obj"
+ -@erase "$(INTDIR)\bufferlist.obj"
+ -@erase "$(INTDIR)\commandline.obj"
+ -@erase "$(INTDIR)\condition.obj"
+ -@erase "$(INTDIR)\dir.obj"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\entropy.obj"
+ -@erase "$(INTDIR)\errno2result.obj"
+ -@erase "$(INTDIR)\error.obj"
+ -@erase "$(INTDIR)\event.obj"
+ -@erase "$(INTDIR)\file.obj"
+ -@erase "$(INTDIR)\fsaccess.obj"
+ -@erase "$(INTDIR)\hash.obj"
+ -@erase "$(INTDIR)\heap.obj"
+ -@erase "$(INTDIR)\hex.obj"
+ -@erase "$(INTDIR)\hmacmd5.obj"
+ -@erase "$(INTDIR)\hmacsha.obj"
+ -@erase "$(INTDIR)\httpd.obj"
+ -@erase "$(INTDIR)\inet_aton.obj"
+ -@erase "$(INTDIR)\inet_ntop.obj"
+ -@erase "$(INTDIR)\inet_pton.obj"
+ -@erase "$(INTDIR)\interfaceiter.obj"
+ -@erase "$(INTDIR)\ipv6.obj"
+ -@erase "$(INTDIR)\iterated_hash.obj"
+ -@erase "$(INTDIR)\keyboard.obj"
+ -@erase "$(INTDIR)\lex.obj"
+ -@erase "$(INTDIR)\lfsr.obj"
+ -@erase "$(INTDIR)\lib.obj"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\md5.obj"
+ -@erase "$(INTDIR)\mem.obj"
+ -@erase "$(INTDIR)\msgcat.obj"
+ -@erase "$(INTDIR)\mutexblock.obj"
+ -@erase "$(INTDIR)\net.obj"
+ -@erase "$(INTDIR)\netaddr.obj"
+ -@erase "$(INTDIR)\netscope.obj"
+ -@erase "$(INTDIR)\ntpaths.obj"
+ -@erase "$(INTDIR)\once.obj"
+ -@erase "$(INTDIR)\ondestroy.obj"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\parseint.obj"
+ -@erase "$(INTDIR)\portset.obj"
+ -@erase "$(INTDIR)\quota.obj"
+ -@erase "$(INTDIR)\random.obj"
+ -@erase "$(INTDIR)\ratelimiter.obj"
+ -@erase "$(INTDIR)\refcount.obj"
+ -@erase "$(INTDIR)\region.obj"
+ -@erase "$(INTDIR)\resource.obj"
+ -@erase "$(INTDIR)\result.obj"
+ -@erase "$(INTDIR)\rwlock.obj"
+ -@erase "$(INTDIR)\serial.obj"
+ -@erase "$(INTDIR)\sha1.obj"
+ -@erase "$(INTDIR)\sha2.obj"
+ -@erase "$(INTDIR)\sockaddr.obj"
+ -@erase "$(INTDIR)\socket.obj"
+ -@erase "$(INTDIR)\stdio.obj"
+ -@erase "$(INTDIR)\stdtime.obj"
+ -@erase "$(INTDIR)\strerror.obj"
+ -@erase "$(INTDIR)\string.obj"
+ -@erase "$(INTDIR)\symtab.obj"
+ -@erase "$(INTDIR)\syslog.obj"
+ -@erase "$(INTDIR)\task.obj"
+ -@erase "$(INTDIR)\taskpool.obj"
+ -@erase "$(INTDIR)\thread.obj"
+ -@erase "$(INTDIR)\time.obj"
+ -@erase "$(INTDIR)\timer.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(INTDIR)\win32os.obj"
+ -@erase "$(OUTDIR)\libisc.exp"
+ -@erase "$(OUTDIR)\libisc.lib"
+ -@erase "..\..\..\Build\Release\libisc.dll"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "NDEBUG" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /Fp"$(INTDIR)\libisc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisc.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libisc.pdb" /machine:I386 /def:".\libisc.def" /out:"../../../Build/Release/libisc.dll" /implib:"$(OUTDIR)\libisc.lib"
+DEF_FILE= \
+ ".\libisc.def"
+LINK32_OBJS= \
+ "$(INTDIR)\app.obj" \
+ "$(INTDIR)\condition.obj" \
+ "$(INTDIR)\dir.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\entropy.obj" \
+ "$(INTDIR)\errno2result.obj" \
+ "$(INTDIR)\file.obj" \
+ "$(INTDIR)\fsaccess.obj" \
+ "$(INTDIR)\interfaceiter.obj" \
+ "$(INTDIR)\ipv6.obj" \
+ "$(INTDIR)\iterated_hash.obj" \
+ "$(INTDIR)\keyboard.obj" \
+ "$(INTDIR)\net.obj" \
+ "$(INTDIR)\ntpaths.obj" \
+ "$(INTDIR)\once.obj" \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\resource.obj" \
+ "$(INTDIR)\socket.obj" \
+ "$(INTDIR)\stdio.obj" \
+ "$(INTDIR)\stdtime.obj" \
+ "$(INTDIR)\strerror.obj" \
+ "$(INTDIR)\syslog.obj" \
+ "$(INTDIR)\thread.obj" \
+ "$(INTDIR)\time.obj" \
+ "$(INTDIR)\version.obj" \
+ "$(INTDIR)\win32os.obj" \
+ "$(INTDIR)\assertions.obj" \
+ "$(INTDIR)\base32.obj" \
+ "$(INTDIR)\base64.obj" \
+ "$(INTDIR)\bitstring.obj" \
+ "$(INTDIR)\buffer.obj" \
+ "$(INTDIR)\bufferlist.obj" \
+ "$(INTDIR)\commandline.obj" \
+ "$(INTDIR)\error.obj" \
+ "$(INTDIR)\event.obj" \
+ "$(INTDIR)\hash.obj" \
+ "$(INTDIR)\heap.obj" \
+ "$(INTDIR)\hex.obj" \
+ "$(INTDIR)\hmacmd5.obj" \
+ "$(INTDIR)\hmacsha.obj" \
+ "$(INTDIR)\httpd.obj" \
+ "$(INTDIR)\inet_aton.obj" \
+ "$(INTDIR)\inet_ntop.obj" \
+ "$(INTDIR)\inet_pton.obj" \
+ "$(INTDIR)\lex.obj" \
+ "$(INTDIR)\lfsr.obj" \
+ "$(INTDIR)\lib.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\md5.obj" \
+ "$(INTDIR)\mem.obj" \
+ "$(INTDIR)\msgcat.obj" \
+ "$(INTDIR)\mutexblock.obj" \
+ "$(INTDIR)\netaddr.obj" \
+ "$(INTDIR)\netscope.obj" \
+ "$(INTDIR)\ondestroy.obj" \
+ "$(INTDIR)\quota.obj" \
+ "$(INTDIR)\random.obj" \
+ "$(INTDIR)\ratelimiter.obj" \
+ "$(INTDIR)\refcount.obj" \
+ "$(INTDIR)\result.obj" \
+ "$(INTDIR)\rwlock.obj" \
+ "$(INTDIR)\serial.obj" \
+ "$(INTDIR)\sha1.obj" \
+ "$(INTDIR)\sha2.obj" \
+ "$(INTDIR)\sockaddr.obj" \
+ "$(INTDIR)\string.obj" \
+ "$(INTDIR)\symtab.obj" \
+ "$(INTDIR)\task.obj" \
+ "$(INTDIR)\taskpool.obj" \
+ "$(INTDIR)\timer.obj" \
+ "$(INTDIR)\parseint.obj" \
+ "$(INTDIR)\portset.obj" \
+ "$(INTDIR)\region.obj"
+
+"..\..\..\Build\Release\libisc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\libisc.dll" "$(OUTDIR)\libisc.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\app.obj"
+ -@erase "$(INTDIR)\app.sbr"
+ -@erase "$(INTDIR)\assertions.obj"
+ -@erase "$(INTDIR)\assertions.sbr"
+ -@erase "$(INTDIR)\base32.obj"
+ -@erase "$(INTDIR)\base32.sbr"
+ -@erase "$(INTDIR)\base64.obj"
+ -@erase "$(INTDIR)\base64.sbr"
+ -@erase "$(INTDIR)\bitstring.obj"
+ -@erase "$(INTDIR)\bitstring.sbr"
+ -@erase "$(INTDIR)\buffer.obj"
+ -@erase "$(INTDIR)\buffer.sbr"
+ -@erase "$(INTDIR)\bufferlist.obj"
+ -@erase "$(INTDIR)\bufferlist.sbr"
+ -@erase "$(INTDIR)\commandline.obj"
+ -@erase "$(INTDIR)\commandline.sbr"
+ -@erase "$(INTDIR)\condition.obj"
+ -@erase "$(INTDIR)\condition.sbr"
+ -@erase "$(INTDIR)\dir.obj"
+ -@erase "$(INTDIR)\dir.sbr"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\DLLMain.sbr"
+ -@erase "$(INTDIR)\entropy.obj"
+ -@erase "$(INTDIR)\entropy.sbr"
+ -@erase "$(INTDIR)\errno2result.obj"
+ -@erase "$(INTDIR)\errno2result.sbr"
+ -@erase "$(INTDIR)\error.obj"
+ -@erase "$(INTDIR)\error.sbr"
+ -@erase "$(INTDIR)\event.obj"
+ -@erase "$(INTDIR)\event.sbr"
+ -@erase "$(INTDIR)\file.obj"
+ -@erase "$(INTDIR)\file.sbr"
+ -@erase "$(INTDIR)\fsaccess.obj"
+ -@erase "$(INTDIR)\fsaccess.sbr"
+ -@erase "$(INTDIR)\hash.obj"
+ -@erase "$(INTDIR)\hash.sbr"
+ -@erase "$(INTDIR)\heap.obj"
+ -@erase "$(INTDIR)\heap.sbr"
+ -@erase "$(INTDIR)\hex.obj"
+ -@erase "$(INTDIR)\hex.sbr"
+ -@erase "$(INTDIR)\hmacmd5.obj"
+ -@erase "$(INTDIR)\hmacmd5.sbr"
+ -@erase "$(INTDIR)\hmacsha.obj"
+ -@erase "$(INTDIR)\hmacsha.sbr"
+ -@erase "$(INTDIR)\httpd.obj"
+ -@erase "$(INTDIR)\httpd.sbr"
+ -@erase "$(INTDIR)\inet_aton.obj"
+ -@erase "$(INTDIR)\inet_aton.sbr"
+ -@erase "$(INTDIR)\inet_ntop.obj"
+ -@erase "$(INTDIR)\inet_ntop.sbr"
+ -@erase "$(INTDIR)\inet_pton.obj"
+ -@erase "$(INTDIR)\inet_pton.sbr"
+ -@erase "$(INTDIR)\interfaceiter.obj"
+ -@erase "$(INTDIR)\interfaceiter.sbr"
+ -@erase "$(INTDIR)\ipv6.obj"
+ -@erase "$(INTDIR)\ipv6.sbr"
+ -@erase "$(INTDIR)\iterated_hash.obj"
+ -@erase "$(INTDIR)\iterated_hash.sbr"
+ -@erase "$(INTDIR)\keyboard.obj"
+ -@erase "$(INTDIR)\keyboard.sbr"
+ -@erase "$(INTDIR)\lex.obj"
+ -@erase "$(INTDIR)\lex.sbr"
+ -@erase "$(INTDIR)\lfsr.obj"
+ -@erase "$(INTDIR)\lfsr.sbr"
+ -@erase "$(INTDIR)\lib.obj"
+ -@erase "$(INTDIR)\lib.sbr"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\log.sbr"
+ -@erase "$(INTDIR)\md5.obj"
+ -@erase "$(INTDIR)\md5.sbr"
+ -@erase "$(INTDIR)\mem.obj"
+ -@erase "$(INTDIR)\mem.sbr"
+ -@erase "$(INTDIR)\msgcat.obj"
+ -@erase "$(INTDIR)\msgcat.sbr"
+ -@erase "$(INTDIR)\mutexblock.obj"
+ -@erase "$(INTDIR)\mutexblock.sbr"
+ -@erase "$(INTDIR)\net.obj"
+ -@erase "$(INTDIR)\net.sbr"
+ -@erase "$(INTDIR)\netaddr.obj"
+ -@erase "$(INTDIR)\netaddr.sbr"
+ -@erase "$(INTDIR)\netscope.obj"
+ -@erase "$(INTDIR)\netscope.sbr"
+ -@erase "$(INTDIR)\ntpaths.obj"
+ -@erase "$(INTDIR)\ntpaths.sbr"
+ -@erase "$(INTDIR)\once.obj"
+ -@erase "$(INTDIR)\once.sbr"
+ -@erase "$(INTDIR)\ondestroy.obj"
+ -@erase "$(INTDIR)\ondestroy.sbr"
+ -@erase "$(INTDIR)\os.obj"
+ -@erase "$(INTDIR)\os.sbr"
+ -@erase "$(INTDIR)\parseint.obj"
+ -@erase "$(INTDIR)\parseint.sbr"
+ -@erase "$(INTDIR)\portset.obj"
+ -@erase "$(INTDIR)\portset.sbr"
+ -@erase "$(INTDIR)\quota.obj"
+ -@erase "$(INTDIR)\quota.sbr"
+ -@erase "$(INTDIR)\random.obj"
+ -@erase "$(INTDIR)\random.sbr"
+ -@erase "$(INTDIR)\ratelimiter.obj"
+ -@erase "$(INTDIR)\ratelimiter.sbr"
+ -@erase "$(INTDIR)\refcount.obj"
+ -@erase "$(INTDIR)\refcount.sbr"
+ -@erase "$(INTDIR)\region.obj"
+ -@erase "$(INTDIR)\region.sbr"
+ -@erase "$(INTDIR)\resource.obj"
+ -@erase "$(INTDIR)\resource.sbr"
+ -@erase "$(INTDIR)\result.obj"
+ -@erase "$(INTDIR)\result.sbr"
+ -@erase "$(INTDIR)\rwlock.obj"
+ -@erase "$(INTDIR)\rwlock.sbr"
+ -@erase "$(INTDIR)\serial.obj"
+ -@erase "$(INTDIR)\serial.sbr"
+ -@erase "$(INTDIR)\sha1.obj"
+ -@erase "$(INTDIR)\sha1.sbr"
+ -@erase "$(INTDIR)\sha2.obj"
+ -@erase "$(INTDIR)\sha2.sbr"
+ -@erase "$(INTDIR)\sockaddr.obj"
+ -@erase "$(INTDIR)\sockaddr.sbr"
+ -@erase "$(INTDIR)\socket.obj"
+ -@erase "$(INTDIR)\socket.sbr"
+ -@erase "$(INTDIR)\stdio.obj"
+ -@erase "$(INTDIR)\stdio.sbr"
+ -@erase "$(INTDIR)\stdtime.obj"
+ -@erase "$(INTDIR)\stdtime.sbr"
+ -@erase "$(INTDIR)\strerror.obj"
+ -@erase "$(INTDIR)\strerror.sbr"
+ -@erase "$(INTDIR)\string.obj"
+ -@erase "$(INTDIR)\string.sbr"
+ -@erase "$(INTDIR)\symtab.obj"
+ -@erase "$(INTDIR)\symtab.sbr"
+ -@erase "$(INTDIR)\syslog.obj"
+ -@erase "$(INTDIR)\syslog.sbr"
+ -@erase "$(INTDIR)\task.obj"
+ -@erase "$(INTDIR)\task.sbr"
+ -@erase "$(INTDIR)\taskpool.obj"
+ -@erase "$(INTDIR)\taskpool.sbr"
+ -@erase "$(INTDIR)\thread.obj"
+ -@erase "$(INTDIR)\thread.sbr"
+ -@erase "$(INTDIR)\time.obj"
+ -@erase "$(INTDIR)\time.sbr"
+ -@erase "$(INTDIR)\timer.obj"
+ -@erase "$(INTDIR)\timer.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(INTDIR)\version.sbr"
+ -@erase "$(INTDIR)\win32os.obj"
+ -@erase "$(INTDIR)\win32os.sbr"
+ -@erase "$(OUTDIR)\libisc.bsc"
+ -@erase "$(OUTDIR)\libisc.exp"
+ -@erase "$(OUTDIR)\libisc.lib"
+ -@erase "$(OUTDIR)\libisc.map"
+ -@erase "$(OUTDIR)\libisc.pdb"
+ -@erase "..\..\..\Build\Debug\libisc.dll"
+ -@erase "..\..\..\Build\Debug\libisc.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/noatomic/include" /I "win32" /I "../../isccfg/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "LIBISC_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libisc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisc.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\app.sbr" \
+ "$(INTDIR)\condition.sbr" \
+ "$(INTDIR)\dir.sbr" \
+ "$(INTDIR)\DLLMain.sbr" \
+ "$(INTDIR)\entropy.sbr" \
+ "$(INTDIR)\errno2result.sbr" \
+ "$(INTDIR)\file.sbr" \
+ "$(INTDIR)\fsaccess.sbr" \
+ "$(INTDIR)\interfaceiter.sbr" \
+ "$(INTDIR)\ipv6.sbr" \
+ "$(INTDIR)\iterated_hash.sbr" \
+ "$(INTDIR)\keyboard.sbr" \
+ "$(INTDIR)\net.sbr" \
+ "$(INTDIR)\ntpaths.sbr" \
+ "$(INTDIR)\once.sbr" \
+ "$(INTDIR)\os.sbr" \
+ "$(INTDIR)\resource.sbr" \
+ "$(INTDIR)\socket.sbr" \
+ "$(INTDIR)\stdio.sbr" \
+ "$(INTDIR)\stdtime.sbr" \
+ "$(INTDIR)\strerror.sbr" \
+ "$(INTDIR)\syslog.sbr" \
+ "$(INTDIR)\thread.sbr" \
+ "$(INTDIR)\time.sbr" \
+ "$(INTDIR)\version.sbr" \
+ "$(INTDIR)\win32os.sbr" \
+ "$(INTDIR)\assertions.sbr" \
+ "$(INTDIR)\base32.sbr" \
+ "$(INTDIR)\base64.sbr" \
+ "$(INTDIR)\bitstring.sbr" \
+ "$(INTDIR)\buffer.sbr" \
+ "$(INTDIR)\bufferlist.sbr" \
+ "$(INTDIR)\commandline.sbr" \
+ "$(INTDIR)\error.sbr" \
+ "$(INTDIR)\event.sbr" \
+ "$(INTDIR)\hash.sbr" \
+ "$(INTDIR)\heap.sbr" \
+ "$(INTDIR)\hex.sbr" \
+ "$(INTDIR)\hmacmd5.sbr" \
+ "$(INTDIR)\hmacsha.sbr" \
+ "$(INTDIR)\httpd.sbr" \
+ "$(INTDIR)\inet_aton.sbr" \
+ "$(INTDIR)\inet_ntop.sbr" \
+ "$(INTDIR)\inet_pton.sbr" \
+ "$(INTDIR)\lex.sbr" \
+ "$(INTDIR)\lfsr.sbr" \
+ "$(INTDIR)\lib.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\md5.sbr" \
+ "$(INTDIR)\mem.sbr" \
+ "$(INTDIR)\msgcat.sbr" \
+ "$(INTDIR)\mutexblock.sbr" \
+ "$(INTDIR)\netaddr.sbr" \
+ "$(INTDIR)\netscope.sbr" \
+ "$(INTDIR)\ondestroy.sbr" \
+ "$(INTDIR)\quota.sbr" \
+ "$(INTDIR)\random.sbr" \
+ "$(INTDIR)\ratelimiter.sbr" \
+ "$(INTDIR)\refcount.sbr" \
+ "$(INTDIR)\result.sbr" \
+ "$(INTDIR)\rwlock.sbr" \
+ "$(INTDIR)\serial.sbr" \
+ "$(INTDIR)\sha1.sbr" \
+ "$(INTDIR)\sha2.sbr" \
+ "$(INTDIR)\sockaddr.sbr" \
+ "$(INTDIR)\string.sbr" \
+ "$(INTDIR)\symtab.sbr" \
+ "$(INTDIR)\task.sbr" \
+ "$(INTDIR)\taskpool.sbr" \
+ "$(INTDIR)\timer.sbr" \
+ "$(INTDIR)\parseint.sbr" \
+ "$(INTDIR)\portset.sbr" \
+ "$(INTDIR)\region.sbr"
+
+"$(OUTDIR)\libisc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libisc.pdb" /map:"$(INTDIR)\libisc.map" /debug /machine:I386 /def:".\libisc.def" /out:"../../../Build/Debug/libisc.dll" /implib:"$(OUTDIR)\libisc.lib" /pdbtype:sept
+DEF_FILE= \
+ ".\libisc.def"
+LINK32_OBJS= \
+ "$(INTDIR)\app.obj" \
+ "$(INTDIR)\condition.obj" \
+ "$(INTDIR)\dir.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\entropy.obj" \
+ "$(INTDIR)\errno2result.obj" \
+ "$(INTDIR)\file.obj" \
+ "$(INTDIR)\fsaccess.obj" \
+ "$(INTDIR)\interfaceiter.obj" \
+ "$(INTDIR)\ipv6.obj" \
+ "$(INTDIR)\iterated_hash.obj" \
+ "$(INTDIR)\keyboard.obj" \
+ "$(INTDIR)\net.obj" \
+ "$(INTDIR)\ntpaths.obj" \
+ "$(INTDIR)\once.obj" \
+ "$(INTDIR)\os.obj" \
+ "$(INTDIR)\resource.obj" \
+ "$(INTDIR)\socket.obj" \
+ "$(INTDIR)\stdio.obj" \
+ "$(INTDIR)\stdtime.obj" \
+ "$(INTDIR)\strerror.obj" \
+ "$(INTDIR)\syslog.obj" \
+ "$(INTDIR)\thread.obj" \
+ "$(INTDIR)\time.obj" \
+ "$(INTDIR)\version.obj" \
+ "$(INTDIR)\win32os.obj" \
+ "$(INTDIR)\assertions.obj" \
+ "$(INTDIR)\base32.obj" \
+ "$(INTDIR)\base64.obj" \
+ "$(INTDIR)\bitstring.obj" \
+ "$(INTDIR)\buffer.obj" \
+ "$(INTDIR)\bufferlist.obj" \
+ "$(INTDIR)\commandline.obj" \
+ "$(INTDIR)\error.obj" \
+ "$(INTDIR)\event.obj" \
+ "$(INTDIR)\hash.obj" \
+ "$(INTDIR)\heap.obj" \
+ "$(INTDIR)\hex.obj" \
+ "$(INTDIR)\hmacmd5.obj" \
+ "$(INTDIR)\hmacsha.obj" \
+ "$(INTDIR)\httpd.obj" \
+ "$(INTDIR)\inet_aton.obj" \
+ "$(INTDIR)\inet_ntop.obj" \
+ "$(INTDIR)\inet_pton.obj" \
+ "$(INTDIR)\lex.obj" \
+ "$(INTDIR)\lfsr.obj" \
+ "$(INTDIR)\lib.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\md5.obj" \
+ "$(INTDIR)\mem.obj" \
+ "$(INTDIR)\msgcat.obj" \
+ "$(INTDIR)\mutexblock.obj" \
+ "$(INTDIR)\netaddr.obj" \
+ "$(INTDIR)\netscope.obj" \
+ "$(INTDIR)\ondestroy.obj" \
+ "$(INTDIR)\quota.obj" \
+ "$(INTDIR)\random.obj" \
+ "$(INTDIR)\ratelimiter.obj" \
+ "$(INTDIR)\refcount.obj" \
+ "$(INTDIR)\result.obj" \
+ "$(INTDIR)\rwlock.obj" \
+ "$(INTDIR)\serial.obj" \
+ "$(INTDIR)\sha1.obj" \
+ "$(INTDIR)\sha2.obj" \
+ "$(INTDIR)\sockaddr.obj" \
+ "$(INTDIR)\string.obj" \
+ "$(INTDIR)\symtab.obj" \
+ "$(INTDIR)\task.obj" \
+ "$(INTDIR)\taskpool.obj" \
+ "$(INTDIR)\timer.obj" \
+ "$(INTDIR)\parseint.obj" \
+ "$(INTDIR)\portset.obj" \
+ "$(INTDIR)\region.obj"
+
+"..\..\..\Build\Debug\libisc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("libisc.dep")
+!INCLUDE "libisc.dep"
+!ELSE
+!MESSAGE Warning: cannot find "libisc.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "libisc - Win32 Release" || "$(CFG)" == "libisc - Win32 Debug"
+SOURCE=.\app.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\app.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\app.obj" "$(INTDIR)\app.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\condition.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\condition.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\condition.obj" "$(INTDIR)\condition.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\dir.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\dir.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\dir.obj" "$(INTDIR)\dir.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\DLLMain.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\DLLMain.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\DLLMain.obj" "$(INTDIR)\DLLMain.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\entropy.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\entropy.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\entropy.obj" "$(INTDIR)\entropy.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\errno2result.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\errno2result.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\errno2result.obj" "$(INTDIR)\errno2result.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\file.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\file.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\file.obj" "$(INTDIR)\file.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\fsaccess.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\fsaccess.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\fsaccess.obj" "$(INTDIR)\fsaccess.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\interfaceiter.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\interfaceiter.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\interfaceiter.obj" "$(INTDIR)\interfaceiter.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\ipv6.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\ipv6.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\ipv6.obj" "$(INTDIR)\ipv6.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+
+SOURCE=..\iterated_hash.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\iterated_hash.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\iterated_hash.obj" "$(INTDIR)\iterated_hash.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\keyboard.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\keyboard.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\keyboard.obj" "$(INTDIR)\keyboard.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\net.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\net.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\net.obj" "$(INTDIR)\net.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\ntpaths.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\ntpaths.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\ntpaths.obj" "$(INTDIR)\ntpaths.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\once.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\once.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\once.obj" "$(INTDIR)\once.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\os.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\os.obj" "$(INTDIR)\os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\resource.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\resource.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\resource.obj" "$(INTDIR)\resource.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\socket.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\socket.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\socket.obj" "$(INTDIR)\socket.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\stdio.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\stdio.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\stdio.obj" "$(INTDIR)\stdio.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\stdtime.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\stdtime.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\stdtime.obj" "$(INTDIR)\stdtime.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\strerror.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\strerror.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\strerror.obj" "$(INTDIR)\strerror.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\syslog.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\syslog.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\syslog.obj" "$(INTDIR)\syslog.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\thread.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\thread.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\thread.obj" "$(INTDIR)\thread.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\time.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\time.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\time.obj" "$(INTDIR)\time.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\version.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\version.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\version.obj" "$(INTDIR)\version.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\win32os.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\win32os.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\win32os.obj" "$(INTDIR)\win32os.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\assertions.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\assertions.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\assertions.obj" "$(INTDIR)\assertions.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\base32.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\base32.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\base32.obj" "$(INTDIR)\base32.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\base64.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\base64.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\base64.obj" "$(INTDIR)\base64.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\bitstring.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\bitstring.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\bitstring.obj" "$(INTDIR)\bitstring.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\buffer.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\buffer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\buffer.obj" "$(INTDIR)\buffer.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\bufferlist.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\bufferlist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\bufferlist.obj" "$(INTDIR)\bufferlist.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\commandline.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\commandline.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\commandline.obj" "$(INTDIR)\commandline.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\error.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\error.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\error.obj" "$(INTDIR)\error.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\event.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\event.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\event.obj" "$(INTDIR)\event.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hash.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\hash.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\hash.obj" "$(INTDIR)\hash.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\heap.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\heap.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\heap.obj" "$(INTDIR)\heap.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hex.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\hex.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\hex.obj" "$(INTDIR)\hex.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hmacmd5.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\hmacmd5.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\hmacmd5.obj" "$(INTDIR)\hmacmd5.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\hmacsha.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\hmacsha.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\hmacsha.obj" "$(INTDIR)\hmacsha.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\httpd.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\httpd.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\httpd.obj" "$(INTDIR)\httpd.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\inet_aton.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\inet_aton.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\inet_aton.obj" "$(INTDIR)\inet_aton.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\inet_ntop.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\inet_ntop.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\inet_ntop.obj" "$(INTDIR)\inet_ntop.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\inet_pton.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\inet_pton.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\inet_pton.obj" "$(INTDIR)\inet_pton.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lex.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\lex.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\lex.obj" "$(INTDIR)\lex.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lfsr.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\lfsr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\lfsr.obj" "$(INTDIR)\lfsr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lib.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\lib.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\lib.obj" "$(INTDIR)\lib.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\log.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\log.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\md5.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\md5.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\md5.obj" "$(INTDIR)\md5.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\mem.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\mem.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\mem.obj" "$(INTDIR)\mem.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\nls\msgcat.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\msgcat.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\msgcat.obj" "$(INTDIR)\msgcat.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\mutexblock.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\mutexblock.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\mutexblock.obj" "$(INTDIR)\mutexblock.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\netaddr.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\netaddr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\netaddr.obj" "$(INTDIR)\netaddr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\netscope.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\netscope.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\netscope.obj" "$(INTDIR)\netscope.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ondestroy.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\ondestroy.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\ondestroy.obj" "$(INTDIR)\ondestroy.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\parseint.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\parseint.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\parseint.obj" "$(INTDIR)\parseint.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\portset.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\portset.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\portset.obj" "$(INTDIR)\portset.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\quota.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\quota.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\quota.obj" "$(INTDIR)\quota.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\radix.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\radix.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\radix.obj" "$(INTDIR)\radix.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\random.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\random.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\random.obj" "$(INTDIR)\random.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ratelimiter.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\ratelimiter.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\ratelimiter.obj" "$(INTDIR)\ratelimiter.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\refcount.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\refcount.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\refcount.obj" "$(INTDIR)\refcount.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\region.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\region.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\region.obj" "$(INTDIR)\region.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\result.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\result.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\result.obj" "$(INTDIR)\result.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\rwlock.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\rwlock.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\rwlock.obj" "$(INTDIR)\rwlock.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\serial.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\serial.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\serial.obj" "$(INTDIR)\serial.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sha1.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\sha1.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\sha1.obj" "$(INTDIR)\sha1.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sha2.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\sha2.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\sha2.obj" "$(INTDIR)\sha2.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sockaddr.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\sockaddr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\sockaddr.obj" "$(INTDIR)\sockaddr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\string.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\string.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\string.obj" "$(INTDIR)\string.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\symtab.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\symtab.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\symtab.obj" "$(INTDIR)\symtab.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\task.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\task.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\task.obj" "$(INTDIR)\task.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\taskpool.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\taskpool.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\taskpool.obj" "$(INTDIR)\taskpool.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\timer.c
+
+!IF "$(CFG)" == "libisc - Win32 Release"
+
+
+"$(INTDIR)\timer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisc - Win32 Debug"
+
+
+"$(INTDIR)\timer.obj" "$(INTDIR)\timer.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/lib/isc/win32/net.c b/lib/isc/win32/net.c
new file mode 100644
index 0000000..3785f8a
--- /dev/null
+++ b/lib/isc/win32/net.c
@@ -0,0 +1,332 @@
+/*
+ * 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
+ * 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: net.c,v 1.18 2008/08/08 05:06:49 marka Exp $ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <isc/log.h>
+#include <isc/msgs.h>
+#include <isc/net.h>
+#include <isc/once.h>
+#include <isc/strerror.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+/*%
+ * Definitions about UDP port range specification. This is a total mess of
+ * portability variants: some use sysctl (but the sysctl names vary), some use
+ * system-specific interfaces, some have the same interface for IPv4 and IPv6,
+ * some separate them, etc...
+ */
+
+/*%
+ * The last resort defaults: use all non well known port space
+ */
+#ifndef ISC_NET_PORTRANGELOW
+#define ISC_NET_PORTRANGELOW 1024
+#endif /* ISC_NET_PORTRANGELOW */
+#ifndef ISC_NET_PORTRANGEHIGH
+#define ISC_NET_PORTRANGEHIGH 65535
+#endif /* ISC_NET_PORTRANGEHIGH */
+
+#if defined(ISC_PLATFORM_HAVEIPV6) && defined(ISC_PLATFORM_NEEDIN6ADDRANY)
+const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
+#endif
+
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_once_t once_ipv6only = ISC_ONCE_INIT;
+static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT;
+static isc_result_t ipv4_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6only_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND;
+
+void InitSockets(void);
+
+static isc_result_t
+try_proto(int domain) {
+ SOCKET s;
+ isc_result_t result = ISC_R_SUCCESS;
+ char strbuf[ISC_STRERRORSIZE];
+ int errval;
+
+ s = socket(domain, SOCK_STREAM, IPPROTO_TCP);
+ if (s == INVALID_SOCKET) {
+ errval = WSAGetLastError();
+ switch (errval) {
+ case WSAEAFNOSUPPORT:
+ case WSAEPROTONOSUPPORT:
+ case WSAEINVAL:
+ return (ISC_R_NOTFOUND);
+ default:
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+
+ closesocket(s);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+initialize_action(void) {
+ InitSockets();
+ ipv4_result = try_proto(PF_INET);
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
+ ipv6_result = try_proto(PF_INET6);
+#endif
+#endif
+#endif
+}
+
+static void
+initialize(void) {
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_net_probeipv4(void) {
+ initialize();
+ return (ipv4_result);
+}
+
+isc_result_t
+isc_net_probeipv6(void) {
+ initialize();
+ return (ipv6_result);
+}
+
+isc_result_t
+isc_net_probeunix(void) {
+ return (ISC_R_NOTFOUND);
+}
+
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+static void
+try_ipv6only(void) {
+#ifdef IPV6_V6ONLY
+ SOCKET s;
+ int on;
+ char strbuf[ISC_STRERRORSIZE];
+#endif
+ isc_result_t result;
+
+ result = isc_net_probeipv6();
+ if (result != ISC_R_SUCCESS) {
+ ipv6only_result = result;
+ return;
+ }
+
+#ifndef IPV6_V6ONLY
+ ipv6only_result = ISC_R_NOTFOUND;
+ return;
+#else
+ /* check for TCP sockets */
+ s = socket(PF_INET6, SOCK_STREAM, 0);
+ if (s == INVALID_SOCKET) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6only_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ closesocket(s);
+
+ /* check for UDP sockets */
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (s == INVALID_SOCKET) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6only_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ ipv6only_result = ISC_R_SUCCESS;
+
+close:
+ closeocket(s);
+ return;
+#endif /* IPV6_V6ONLY */
+}
+
+static void
+initialize_ipv6only(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6only,
+ try_ipv6only) == ISC_R_SUCCESS);
+}
+
+static void
+try_ipv6pktinfo(void) {
+ int s, on;
+ char strbuf[ISC_STRERRORSIZE];
+ isc_result_t result;
+ int optname;
+
+ result = isc_net_probeipv6();
+ if (result != ISC_R_SUCCESS) {
+ ipv6pktinfo_result = result;
+ return;
+ }
+
+ /* we only use this for UDP sockets */
+ s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s == INVALID_SOCKET) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6pktinfo_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+#ifdef IPV6_RECVPKTINFO
+ optname = IPV6_RECVPKTINFO;
+#else
+ optname = IPV6_PKTINFO;
+#endif
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, optname, (const char *) &on,
+ sizeof(on)) < 0) {
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ ipv6pktinfo_result = ISC_R_SUCCESS;
+
+close:
+ closesocket(s);
+ return;
+}
+
+static void
+initialize_ipv6pktinfo(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6pktinfo,
+ try_ipv6pktinfo) == ISC_R_SUCCESS);
+}
+#endif /* WANT_IPV6 */
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+
+isc_result_t
+isc_net_probe_ipv6only(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+ initialize_ipv6only();
+#else
+ ipv6only_result = ISC_R_NOTFOUND;
+#endif
+#endif
+ return (ipv6only_result);
+}
+
+isc_result_t
+isc_net_probe_ipv6pktinfo(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+ initialize_ipv6pktinfo();
+#else
+ ipv6pktinfo_result = ISC_R_NOTFOUND;
+#endif
+#endif
+ return (ipv6pktinfo_result);
+}
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) {
+ int result = ISC_R_FAILURE;
+
+ REQUIRE(low != NULL && high != NULL);
+
+ UNUSED(af);
+
+ if (result != ISC_R_SUCCESS) {
+ *low = ISC_NET_PORTRANGELOW;
+ *high = ISC_NET_PORTRANGEHIGH;
+ }
+
+ return (ISC_R_SUCCESS); /* we currently never fail in this function */
+}
+
+void
+isc_net_disableipv4(void) {
+ initialize();
+ if (ipv4_result == ISC_R_SUCCESS)
+ ipv4_result = ISC_R_DISABLED;
+}
+
+void
+isc_net_disableipv6(void) {
+ initialize();
+ if (ipv6_result == ISC_R_SUCCESS)
+ ipv6_result = ISC_R_DISABLED;
+}
+
+void
+isc_net_enableipv4(void) {
+ initialize();
+ if (ipv4_result == ISC_R_DISABLED)
+ ipv4_result = ISC_R_SUCCESS;
+}
+
+void
+isc_net_enableipv6(void) {
+ initialize();
+ if (ipv6_result == ISC_R_DISABLED)
+ ipv6_result = ISC_R_SUCCESS;
+}
diff --git a/lib/isc/win32/netdb.h b/lib/isc/win32/netdb.h
new file mode 100644
index 0000000..4e3a935
--- /dev/null
+++ b/lib/isc/win32/netdb.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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: netdb.h,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef NETDB_H
+#define NETDB_H 1
+
+#include <stddef.h>
+#include <winsock2.h>
+
+/*
+ * Define if <netdb.h> does not declare struct addrinfo.
+ */
+
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* Length of ai_addr */
+ char *ai_canonname; /* Canonical name for hostname */
+ struct sockaddr *ai_addr; /* Binary address */
+ struct addrinfo *ai_next; /* Next structure in linked list */
+};
+
+
+/*
+ * Undefine all \#defines we are interested in as <netdb.h> 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()
+ */
+
+#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_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_MAX 14
+
+/*
+ * 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 getnameinfo()
+ */
+#undef NI_MAXHOST
+#undef NI_MAXSERV
+
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+
+/*
+ * Flag values for 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
+#define NI_NUMERICSCOPE 0x00000020 /*2553bis-00*/
+
+/*
+ * Structures for getrrsetbyname()
+ */
+struct rdatainfo {
+ unsigned int rdi_length;
+ unsigned char *rdi_data;
+};
+
+struct rrsetinfo {
+ unsigned int rri_flags;
+ int rri_rdclass;
+ int rri_rdtype;
+ unsigned int rri_ttl;
+ unsigned int rri_nrdatas;
+ unsigned int rri_nsigs;
+ char *rri_name;
+ struct rdatainfo *rri_rdatas;
+ struct rdatainfo *rri_sigs;
+};
+
+/*
+ * Flags for getrrsetbyname()
+ */
+#define RRSET_VALIDATED 0x00000001
+ /* Set was dnssec validated */
+
+/*
+ * Return codes for getrrsetbyname()
+ */
+#define ERRSET_SUCCESS 0
+#define ERRSET_NOMEMORY 1
+#define ERRSET_FAIL 2
+#define ERRSET_INVAL 3
+
+
+#endif /* NETDB_H */
diff --git a/lib/isc/win32/ntgroups.c b/lib/isc/win32/ntgroups.c
new file mode 100644
index 0000000..351adc5
--- /dev/null
+++ b/lib/isc/win32/ntgroups.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2004, 2006, 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: ntgroups.c,v 1.10 2007/06/19 23:47:19 tbox Exp $ */
+
+/*
+ * The NT Groups have two groups that are not well documented and are
+ * not normally seen: None and Everyone. A user account belongs to
+ * any number of groups, but if it is not a member of any group then
+ * it is a member of the None Group. The None group is not listed
+ * anywhere. You cannot remove an account from the none group except
+ * by making it a member of some other group, The second group is the
+ * Everyone group. All accounts, no matter how many groups that they
+ * belong to, also belong to the Everyone group. You cannot remove an
+ * account from the Everyone group.
+ */
+
+#ifndef UNICODE
+#define UNICODE
+#endif /* UNICODE */
+
+/*
+ * Silence warnings.
+ */
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+#include <windows.h>
+#include <assert.h>
+#include <lm.h>
+
+#include <isc/ntgroups.h>
+#include <isc/result.h>
+
+#define MAX_NAME_LENGTH 256
+
+isc_result_t
+isc_ntsecurity_getaccountgroups(char *username, char **GroupList,
+ unsigned int maxgroups,
+ unsigned int *totalGroups) {
+ LPGROUP_USERS_INFO_0 pTmpBuf;
+ LPLOCALGROUP_USERS_INFO_0 pTmpLBuf;
+ DWORD i;
+ LPLOCALGROUP_USERS_INFO_0 pBuf = NULL;
+ LPGROUP_USERS_INFO_0 pgrpBuf = NULL;
+ DWORD dwLevel = 0;
+ DWORD dwFlags = LG_INCLUDE_INDIRECT;
+ DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
+ DWORD dwEntriesRead = 0;
+ DWORD dwTotalEntries = 0;
+ NET_API_STATUS nStatus;
+ DWORD dwTotalCount = 0;
+ int retlen;
+ wchar_t user[MAX_NAME_LENGTH];
+
+ retlen = mbstowcs(user, username, MAX_NAME_LENGTH);
+
+ *totalGroups = 0;
+ /*
+ * Call the NetUserGetLocalGroups function
+ * specifying information level 0.
+ *
+ * The LG_INCLUDE_INDIRECT flag specifies that the
+ * function should also return the names of the local
+ * groups in which the user is indirectly a member.
+ */
+ nStatus = NetUserGetLocalGroups(NULL,
+ user,
+ dwLevel,
+ dwFlags,
+ (LPBYTE *) &pBuf,
+ dwPrefMaxLen,
+ &dwEntriesRead,
+ &dwTotalEntries);
+ /*
+ * See if the call succeeds,
+ */
+ if (nStatus != NERR_Success) {
+ if (nStatus == ERROR_ACCESS_DENIED)
+ return (ISC_R_NOPERM);
+ if (nStatus == ERROR_MORE_DATA)
+ return (ISC_R_NOSPACE);
+ if (nStatus == NERR_UserNotFound)
+ dwEntriesRead = 0;
+ }
+
+ dwTotalCount = 0;
+ if (pBuf != NULL) {
+ pTmpLBuf = pBuf;
+ /*
+ * Loop through the entries
+ */
+ for (i = 0;
+ (i < dwEntriesRead && *totalGroups < maxgroups); i++) {
+ assert(pTmpLBuf != NULL);
+ if (pTmpLBuf == NULL)
+ break;
+ retlen = wcslen(pTmpLBuf->lgrui0_name);
+ GroupList[*totalGroups] = (char *) malloc(retlen +1);
+ if (GroupList[*totalGroups] == NULL)
+ return (ISC_R_NOMEMORY);
+
+ retlen = wcstombs(GroupList[*totalGroups],
+ pTmpLBuf->lgrui0_name, retlen);
+ GroupList[*totalGroups][retlen] = '\0';
+ if (strcmp(GroupList[*totalGroups], "None") == 0)
+ free(GroupList[*totalGroups]);
+ else
+ (*totalGroups)++;
+ pTmpLBuf++;
+ }
+ }
+ /* Free the allocated memory. */
+ if (pBuf != NULL)
+ NetApiBufferFree(pBuf);
+
+
+ /*
+ * Call the NetUserGetGroups function, specifying level 0.
+ */
+ nStatus = NetUserGetGroups(NULL,
+ user,
+ dwLevel,
+ (LPBYTE*)&pgrpBuf,
+ dwPrefMaxLen,
+ &dwEntriesRead,
+ &dwTotalEntries);
+ /*
+ * See if the call succeeds,
+ */
+ if (nStatus != NERR_Success) {
+ if (nStatus == ERROR_ACCESS_DENIED)
+ return (ISC_R_NOPERM);
+ if (nStatus == ERROR_MORE_DATA)
+ return (ISC_R_NOSPACE);
+ if (nStatus == NERR_UserNotFound)
+ dwEntriesRead = 0;
+ }
+
+ if (pgrpBuf != NULL) {
+ pTmpBuf = pgrpBuf;
+ /*
+ * Loop through the entries
+ */
+ for (i = 0;
+ (i < dwEntriesRead && *totalGroups < maxgroups); i++) {
+ assert(pTmpBuf != NULL);
+
+ if (pTmpBuf == NULL)
+ break;
+ retlen = wcslen(pTmpBuf->grui0_name);
+ GroupList[*totalGroups] = (char *) malloc(retlen +1);
+ if (GroupList[*totalGroups] == NULL)
+ return (ISC_R_NOMEMORY);
+
+ retlen = wcstombs(GroupList[*totalGroups],
+ pTmpBuf->grui0_name, retlen);
+ GroupList[*totalGroups][retlen] = '\0';
+ if (strcmp(GroupList[*totalGroups], "None") == 0)
+ free(GroupList[*totalGroups]);
+ else
+ (*totalGroups)++;
+ pTmpBuf++;
+ }
+ }
+ /*
+ * Free the allocated memory.
+ */
+ if (pgrpBuf != NULL)
+ NetApiBufferFree(pgrpBuf);
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/win32/ntpaths.c b/lib/isc/win32/ntpaths.c
new file mode 100644
index 0000000..d1c622f
--- /dev/null
+++ b/lib/isc/win32/ntpaths.c
@@ -0,0 +1,140 @@
+/*
+ * 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: ntpaths.c,v 1.11 2007/06/18 23:47:49 tbox Exp $ */
+
+/*
+ * This module fetches the required path information that is specific
+ * to NT systems which can have its configuration and system files
+ * almost anywhere. It can be used to override whatever the application
+ * had previously assigned to the pointer. Basic information about the
+ * file locations are stored in the registry.
+ */
+
+#include <config.h>
+#include <isc/bind_registry.h>
+#include <isc/ntpaths.h>
+
+/*
+ * Module Variables
+ */
+
+static char systemDir[MAX_PATH];
+static char namedBase[MAX_PATH];
+static char ns_confFile[MAX_PATH];
+static char lwresd_confFile[MAX_PATH];
+static char lwresd_resolvconfFile[MAX_PATH];
+static char rndc_confFile[MAX_PATH];
+static char ns_defaultpidfile[MAX_PATH];
+static char lwresd_defaultpidfile[MAX_PATH];
+static char local_state_dir[MAX_PATH];
+static char sys_conf_dir[MAX_PATH];
+static char rndc_keyFile[MAX_PATH];
+
+static DWORD baseLen = MAX_PATH;
+static BOOL Initialized = FALSE;
+
+void
+isc_ntpaths_init() {
+ HKEY hKey;
+ BOOL keyFound = TRUE;
+
+ memset(namedBase, 0, MAX_PATH);
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SUBKEY, 0, KEY_READ, &hKey)
+ != ERROR_SUCCESS)
+ keyFound = FALSE;
+
+ if (keyFound == TRUE) {
+ /* Get the named directory */
+ if (RegQueryValueEx(hKey, "InstallDir", NULL, NULL,
+ (LPBYTE)namedBase, &baseLen) != ERROR_SUCCESS)
+ keyFound = FALSE;
+ RegCloseKey(hKey);
+ }
+
+ GetSystemDirectory(systemDir, MAX_PATH);
+
+ if (keyFound == FALSE)
+ /* Use the System Directory as a default */
+ strcpy(namedBase, systemDir);
+
+ strcpy(ns_confFile, namedBase);
+ strcat(ns_confFile, "\\etc\\named.conf");
+
+ strcpy(lwresd_confFile, namedBase);
+ strcat(lwresd_confFile, "\\etc\\lwresd.conf");
+
+ strcpy(lwresd_resolvconfFile, systemDir);
+ strcat(lwresd_resolvconfFile, "\\Drivers\\etc\\resolv.conf");
+
+ strcpy(rndc_keyFile, namedBase);
+ strcat(rndc_keyFile, "\\etc\\rndc.key");
+
+ strcpy(rndc_confFile, namedBase);
+ strcat(rndc_confFile, "\\etc\\rndc.conf");
+ strcpy(ns_defaultpidfile, namedBase);
+ strcat(ns_defaultpidfile, "\\etc\\named.pid");
+
+ strcpy(lwresd_defaultpidfile, namedBase);
+ strcat(lwresd_defaultpidfile, "\\etc\\lwresd.pid");
+
+ strcpy(local_state_dir, namedBase);
+ strcat(local_state_dir, "\\bin");
+
+ strcpy(sys_conf_dir, namedBase);
+ strcat(sys_conf_dir, "\\etc");
+
+ Initialized = TRUE;
+}
+
+char *
+isc_ntpaths_get(int ind) {
+ if (!Initialized)
+ isc_ntpaths_init();
+
+ switch (ind) {
+ case NAMED_CONF_PATH:
+ return (ns_confFile);
+ break;
+ case LWRES_CONF_PATH:
+ return (lwresd_confFile);
+ break;
+ case RESOLV_CONF_PATH:
+ return (lwresd_resolvconfFile);
+ break;
+ case RNDC_CONF_PATH:
+ return (rndc_confFile);
+ break;
+ case NAMED_PID_PATH:
+ return (ns_defaultpidfile);
+ break;
+ case LWRESD_PID_PATH:
+ return (lwresd_defaultpidfile);
+ break;
+ case LOCAL_STATE_DIR:
+ return (local_state_dir);
+ break;
+ case SYS_CONF_DIR:
+ return (sys_conf_dir);
+ break;
+ case RNDC_KEY_PATH:
+ return (rndc_keyFile);
+ break;
+ default:
+ return (NULL);
+ }
+}
diff --git a/lib/isc/win32/once.c b/lib/isc/win32/once.c
new file mode 100644
index 0000000..b504776
--- /dev/null
+++ b/lib/isc/win32/once.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: once.c,v 1.12 2007/06/18 23:47:49 tbox Exp $ */
+
+/* Principal Authors: DCL */
+
+#include <config.h>
+
+#include <windows.h>
+
+#include <isc/once.h>
+#include <isc/assertions.h>
+#include <isc/util.h>
+
+isc_result_t
+isc_once_do(isc_once_t *controller, void(*function)(void)) {
+ REQUIRE(controller != NULL && function != NULL);
+
+ if (controller->status == ISC_ONCE_INIT_NEEDED) {
+
+ if (InterlockedDecrement(&controller->counter) == 0) {
+ if (controller->status == ISC_ONCE_INIT_NEEDED) {
+ function();
+ controller->status = ISC_ONCE_INIT_DONE;
+ }
+ } else {
+ while (controller->status == ISC_ONCE_INIT_NEEDED) {
+ /*
+ * Sleep(0) indicates that this thread
+ * should be suspended to allow other
+ * waiting threads to execute.
+ */
+ Sleep(0);
+ }
+ }
+ }
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isc/win32/os.c b/lib/isc/win32/os.c
new file mode 100644
index 0000000..bbd5f1d
--- /dev/null
+++ b/lib/isc/win32/os.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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.8 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <windows.h>
+
+#include <isc/os.h>
+
+static BOOL bInit = FALSE;
+static SYSTEM_INFO SystemInfo;
+
+static void
+initialize_action(void) {
+ if (bInit)
+ return;
+
+ GetSystemInfo(&SystemInfo);
+ bInit = TRUE;
+}
+
+unsigned int
+isc_os_ncpus(void) {
+ long ncpus = 1;
+ initialize_action();
+ ncpus = SystemInfo.dwNumberOfProcessors;
+ if (ncpus <= 0)
+ ncpus = 1;
+
+ return ((unsigned int)ncpus);
+}
diff --git a/lib/isc/win32/resource.c b/lib/isc/win32/resource.c
new file mode 100644
index 0000000..e7e7cf4
--- /dev/null
+++ b/lib/isc/win32/resource.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2004, 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
+ * 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: resource.c,v 1.10 2008/07/11 23:47:09 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <isc/platform.h>
+#include <isc/resource.h>
+#include <isc/result.h>
+#include <isc/util.h>
+
+#include "errno2result.h"
+
+/*
+ * Windows limits the maximum number of open files to 2048
+ */
+
+#define WIN32_MAX_OPEN_FILES 2048
+
+isc_result_t
+isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
+ isc_resourcevalue_t rlim_value;
+ int wresult;
+
+ if (resource != isc_resource_openfiles)
+ return (ISC_R_NOTIMPLEMENTED);
+
+
+ if (value == ISC_RESOURCE_UNLIMITED)
+ rlim_value = WIN32_MAX_OPEN_FILES;
+ else
+ rlim_value = min(value, WIN32_MAX_OPEN_FILES);
+
+ wresult = _setmaxstdio((int) rlim_value);
+
+ if (wresult > 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+
+ if (resource != isc_resource_openfiles)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ *value = WIN32_MAX_OPEN_FILES;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+ return (isc_resource_getlimit(resource, value));
+}
diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c
new file mode 100644
index 0000000..082fb7d
--- /dev/null
+++ b/lib/isc/win32/socket.c
@@ -0,0 +1,3658 @@
+/*
+ * 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
+ * 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.c,v 1.70 2008/09/16 17:19:01 explorer Exp $ */
+
+/* This code uses functions which are only available on Server 2003 and
+ * higher, and Windows XP and higher.
+ *
+ * This code is by nature multithreaded and takes advantage of various
+ * features to pass on information through the completion port for
+ * when I/O is completed. All sends, receives, accepts, and connects are
+ * completed through the completion port.
+ *
+ * The number of Completion Port Worker threads used is the total number
+ * of CPU's + 1. This increases the likelihood that a Worker Thread is
+ * available for processing a completed request.
+ *
+ * XXXPDM 5 August, 2002
+ */
+
+#define MAKE_EXTERNAL 1
+#include <config.h>
+
+#include <sys/types.h>
+
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
+#endif
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <io.h>
+#include <fcntl.h>
+#include <process.h>
+
+#include <isc/buffer.h>
+#include <isc/bufferlist.h>
+#include <isc/condition.h>
+#include <isc/list.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/msgs.h>
+#include <isc/mutex.h>
+#include <isc/net.h>
+#include <isc/once.h>
+#include <isc/os.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/region.h>
+#include <isc/socket.h>
+#include <isc/strerror.h>
+#include <isc/syslog.h>
+#include <isc/task.h>
+#include <isc/thread.h>
+#include <isc/util.h>
+#include <isc/win32os.h>
+
+#include <mswsock.h>
+
+#include "errno2result.h"
+
+/*
+ * How in the world can Microsoft exist with APIs like this?
+ * We can't actually call this directly, because it turns out
+ * no library exports this function. Instead, we need to
+ * issue a runtime call to get the address.
+ */
+LPFN_CONNECTEX ISCConnectEx;
+LPFN_ACCEPTEX ISCAcceptEx;
+LPFN_GETACCEPTEXSOCKADDRS ISCGetAcceptExSockaddrs;
+
+/*
+ * Run expensive internal consistancy checks.
+ */
+#ifdef ISC_SOCKET_CONSISTENCY_CHECKS
+#define CONSISTENT(sock) consistent(sock)
+#else
+#define CONSISTENT(sock) do {} while (0)
+#endif
+static void consistent(isc_socket_t *sock);
+
+/*
+ * Define this macro to control the behavior of connection
+ * resets on UDP sockets. See Microsoft KnowledgeBase Article Q263823
+ * for details.
+ * NOTE: This requires that Windows 2000 systems install Service Pack 2
+ * or later.
+ */
+#ifndef SIO_UDP_CONNRESET
+#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
+#endif
+
+/*
+ * Some systems define the socket length argument as an int, some as size_t,
+ * some as socklen_t. This is here so it can be easily changed if needed.
+ */
+#ifndef ISC_SOCKADDR_LEN_T
+#define ISC_SOCKADDR_LEN_T unsigned int
+#endif
+
+/*
+ * Define what the possible "soft" errors can be. These are non-fatal returns
+ * of various network related functions, like recv() and so on.
+ */
+#define SOFT_ERROR(e) ((e) == WSAEINTR || \
+ (e) == WSAEWOULDBLOCK || \
+ (e) == EWOULDBLOCK || \
+ (e) == EINTR || \
+ (e) == EAGAIN || \
+ (e) == 0)
+
+/*
+ * Pending errors are not really errors and should be
+ * kept separate
+ */
+#define PENDING_ERROR(e) ((e) == WSA_IO_PENDING || (e) == 0)
+
+#define DOIO_SUCCESS 0 /* i/o ok, event sent */
+#define DOIO_SOFT 1 /* i/o ok, soft error, no event sent */
+#define DOIO_HARD 2 /* i/o error, event sent */
+#define DOIO_EOF 3 /* EOF, no event sent */
+#define DOIO_PENDING 4 /* status when i/o is in process */
+#define DOIO_NEEDMORE 5 /* IO was processed, but we need more due to minimum */
+
+#define DLVL(x) ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_SOCKET, ISC_LOG_DEBUG(x)
+
+/*
+ * DLVL(90) -- Function entry/exit and other tracing.
+ * DLVL(70) -- Socket "correctness" -- including returning of events, etc.
+ * DLVL(60) -- Socket data send/receive
+ * DLVL(50) -- Event tracing, including receiving/sending completion events.
+ * DLVL(20) -- Socket creation/destruction.
+ */
+#define TRACE_LEVEL 90
+#define CORRECTNESS_LEVEL 70
+#define IOEVENT_LEVEL 60
+#define EVENT_LEVEL 50
+#define CREATION_LEVEL 20
+
+#define TRACE DLVL(TRACE_LEVEL)
+#define CORRECTNESS DLVL(CORRECTNESS_LEVEL)
+#define IOEVENT DLVL(IOEVENT_LEVEL)
+#define EVENT DLVL(EVENT_LEVEL)
+#define CREATION DLVL(CREATION_LEVEL)
+
+typedef isc_event_t intev_t;
+
+/*
+ * Socket State
+ */
+enum {
+ SOCK_INITIALIZED, /* Socket Initialized */
+ SOCK_OPEN, /* Socket opened but nothing yet to do */
+ SOCK_DATA, /* Socket sending or receiving data */
+ SOCK_LISTEN, /* TCP Socket listening for connects */
+ SOCK_ACCEPT, /* TCP socket is waiting to accept */
+ SOCK_CONNECT, /* TCP Socket connecting */
+ SOCK_CLOSED, /* Socket has been closed */
+};
+
+#define SOCKET_MAGIC ISC_MAGIC('I', 'O', 'i', 'o')
+#define VALID_SOCKET(t) ISC_MAGIC_VALID(t, SOCKET_MAGIC)
+
+/*
+ * IPv6 control information. If the socket is an IPv6 socket we want
+ * to collect the destination address and interface so the client can
+ * set them on outgoing packets.
+ */
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifndef USE_CMSG
+#define USE_CMSG 1
+#endif
+#endif
+
+/*
+ * We really don't want to try and use these control messages. Win32
+ * doesn't have this mechanism before XP.
+ */
+#undef USE_CMSG
+
+/*
+ * Message header for recvmsg and sendmsg calls.
+ * Used value-result for recvmsg, value only for sendmsg.
+ */
+struct msghdr {
+ SOCKADDR_STORAGE to_addr; /* UDP send/recv address */
+ int to_addr_len; /* length of the address */
+ WSABUF *msg_iov; /* scatter/gather array */
+ u_int msg_iovlen; /* # elements in msg_iov */
+ void *msg_control; /* ancillary data, see below */
+ u_int msg_controllen; /* ancillary data buffer len */
+ int msg_totallen; /* total length of this message */
+} msghdr;
+
+/*
+ * The size to raise the receive buffer to.
+ */
+#define RCVBUFSIZE (32*1024)
+
+/*
+ * The number of times a send operation is repeated if the result
+ * is WSAEINTR.
+ */
+#define NRETRIES 10
+
+struct isc_socket {
+ /* Not locked. */
+ unsigned int magic;
+ isc_socketmgr_t *manager;
+ isc_mutex_t lock;
+ isc_sockettype_t type;
+
+ /* Pointers to scatter/gather buffers */
+ WSABUF iov[ISC_SOCKET_MAXSCATTERGATHER];
+
+ /* Locked by socket lock. */
+ ISC_LINK(isc_socket_t) link;
+ unsigned int references; /* EXTERNAL references */
+ SOCKET fd; /* file handle */
+ int pf; /* protocol family */
+ char name[16];
+ void * tag;
+
+ /*
+ * Each recv() call uses this buffer. It is a per-socket receive
+ * buffer that allows us to decouple the system recv() from the
+ * recv_list done events. This means the items on the recv_list
+ * can be removed without having to cancel pending system recv()
+ * calls. It also allows us to read-ahead in some cases.
+ */
+ struct {
+ SOCKADDR_STORAGE from_addr; // UDP send/recv address
+ int from_addr_len; // length of the address
+ char *base; // the base of the buffer
+ char *consume_position; // where to start copying data from next
+ unsigned int len; // the actual size of this buffer
+ unsigned int remaining; // the number of bytes remaining
+ } recvbuf;
+
+ ISC_LIST(isc_socketevent_t) send_list;
+ ISC_LIST(isc_socketevent_t) recv_list;
+ ISC_LIST(isc_socket_newconnev_t) accept_list;
+ isc_socket_connev_t *connect_ev;
+
+ isc_sockaddr_t address; /* remote address */
+
+ unsigned int listener : 1, /* listener socket */
+ connected : 1,
+ pending_connect : 1, /* connect pending */
+ bound : 1; /* bound to local addr */
+ unsigned int pending_iocp; /* Should equal the counters below. Debug. */
+ unsigned int pending_recv; /* Number of outstanding recv() calls. */
+ unsigned int pending_send; /* Number of outstanding send() calls. */
+ unsigned int pending_accept; /* Number of outstanding accept() calls. */
+ unsigned int state; /* Socket state. Debugging and consistency checking. */
+ int state_lineno; /* line which last touched state */
+};
+
+#define _set_state(sock, _state) do { (sock)->state = (_state); (sock)->state_lineno = __LINE__; } while (0)
+
+/*
+ * Buffer structure
+ */
+typedef struct buflist buflist_t;
+
+struct buflist {
+ void *buf;
+ unsigned int buflen;
+ ISC_LINK(buflist_t) link;
+};
+
+/*
+ * I/O Completion ports Info structures
+ */
+
+static HANDLE hHeapHandle = NULL;
+typedef struct IoCompletionInfo {
+ OVERLAPPED overlapped;
+ isc_socketevent_t *dev; /* send()/recv() done event */
+ isc_socket_connev_t *cdev; /* connect() done event */
+ isc_socket_newconnev_t *adev; /* accept() done event */
+ void *acceptbuffer;
+ DWORD received_bytes;
+ int request_type;
+ struct msghdr messagehdr;
+ ISC_LIST(buflist_t) bufferlist; /*%< list of buffers */
+} IoCompletionInfo;
+
+/*
+ * Define a maximum number of I/O Completion Port worker threads
+ * to handle the load on the Completion Port. The actual number
+ * used is the number of CPU's + 1.
+ */
+#define MAX_IOCPTHREADS 20
+
+#define SOCKET_MANAGER_MAGIC ISC_MAGIC('I', 'O', 'm', 'g')
+#define VALID_MANAGER(m) ISC_MAGIC_VALID(m, SOCKET_MANAGER_MAGIC)
+
+struct isc_socketmgr {
+ /* Not locked. */
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_mutex_t lock;
+ /* Locked by manager lock. */
+ ISC_LIST(isc_socket_t) socklist;
+ isc_boolean_t bShutdown;
+ isc_condition_t shutdown_ok;
+ HANDLE hIoCompletionPort;
+ int maxIOCPThreads;
+ HANDLE hIOCPThreads[MAX_IOCPTHREADS];
+ DWORD dwIOCPThreadIds[MAX_IOCPTHREADS];
+
+ /*
+ * Debugging.
+ * Modified by InterlockedIncrement() and InterlockedDecrement()
+ */
+ LONG totalSockets;
+ LONG iocp_total;
+};
+
+enum {
+ SOCKET_RECV,
+ SOCKET_SEND,
+ SOCKET_ACCEPT,
+ SOCKET_CONNECT
+};
+
+/*
+ * send() and recv() iovec counts
+ */
+#define MAXSCATTERGATHER_SEND (ISC_SOCKET_MAXSCATTERGATHER)
+#define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
+
+static isc_threadresult_t WINAPI SocketIoThread(LPVOID ThreadContext);
+static void maybe_free_socket(isc_socket_t **, int);
+static void free_socket(isc_socket_t **, int);
+static isc_boolean_t senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev);
+static isc_boolean_t acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev);
+static isc_boolean_t connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev);
+static void send_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev);
+static void send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev);
+static void send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev);
+static void send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev);
+static void send_recvdone_abort(isc_socket_t *sock, isc_result_t result);
+static void queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev);
+static void queue_receive_request(isc_socket_t *sock);
+
+/*
+ * This is used to dump the contents of the sock structure
+ * You should make sure that the sock is locked before
+ * dumping it. Since the code uses simple printf() statements
+ * it should only be used interactively.
+ */
+void
+sock_dump(isc_socket_t *sock) {
+ isc_socketevent_t *ldev;
+ isc_socket_newconnev_t *ndev;
+
+#if 0
+ isc_sockaddr_t addr;
+ char socktext[256];
+
+ isc_socket_getpeername(sock, &addr);
+ isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+ printf("Remote Socket: %s\n", socktext);
+ isc_socket_getsockname(sock, &addr);
+ isc_sockaddr_format(&addr, socktext, sizeof(socktext));
+ printf("This Socket: %s\n", socktext);
+#endif
+
+ printf("\n\t\tSock Dump\n");
+ printf("\t\tfd: %u\n", sock->fd);
+ printf("\t\treferences: %d\n", sock->references);
+ printf("\t\tpending_accept: %d\n", sock->pending_accept);
+ printf("\t\tconnecting: %d\n", sock->pending_connect);
+ printf("\t\tconnected: %d\n", sock->connected);
+ printf("\t\tbound: %d\n", sock->bound);
+ printf("\t\tpending_iocp: %d\n", sock->pending_iocp);
+ printf("\t\tsocket type: %d\n", sock->type);
+
+ printf("\n\t\tSock Recv List\n");
+ ldev = ISC_LIST_HEAD(sock->recv_list);
+ while (ldev != NULL) {
+ printf("\t\tdev: %p\n", ldev);
+ ldev = ISC_LIST_NEXT(ldev, ev_link);
+ }
+
+ printf("\n\t\tSock Send List\n");
+ ldev = ISC_LIST_HEAD(sock->send_list);
+ while (ldev != NULL) {
+ printf("\t\tdev: %p\n", ldev);
+ ldev = ISC_LIST_NEXT(ldev, ev_link);
+ }
+
+ printf("\n\t\tSock Accept List\n");
+ ndev = ISC_LIST_HEAD(sock->accept_list);
+ while (ndev != NULL) {
+ printf("\t\tdev: %p\n", ldev);
+ ndev = ISC_LIST_NEXT(ndev, ev_link);
+ }
+}
+
+static void
+socket_log(int lineno, 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);
+
+/* This function will add an entry to the I/O completion port
+ * that will signal the I/O thread to exit (gracefully)
+ */
+static void
+signal_iocompletionport_exit(isc_socketmgr_t *manager) {
+ int i;
+ int errval;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_MANAGER(manager));
+ for (i = 0; i < manager->maxIOCPThreads; i++) {
+ if (!PostQueuedCompletionStatus(manager->hIoCompletionPort,
+ 0, 0, 0)) {
+ errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "Can't request service thread to exit: %s"),
+ strbuf);
+ }
+ }
+}
+
+/*
+ * Create the worker threads for the I/O Completion Port
+ */
+void
+iocompletionport_createthreads(int total_threads, isc_socketmgr_t *manager) {
+ int errval;
+ char strbuf[ISC_STRERRORSIZE];
+ int i;
+
+ INSIST(total_threads > 0);
+ REQUIRE(VALID_MANAGER(manager));
+ /*
+ * We need at least one
+ */
+ for (i = 0; i < total_threads; i++) {
+ manager->hIOCPThreads[i] = CreateThread(NULL, 0, SocketIoThread,
+ manager, 0,
+ &manager->dwIOCPThreadIds[i]);
+ if (manager->hIOCPThreads[i] == NULL) {
+ errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "Can't create IOCP thread: %s"),
+ strbuf);
+ exit(1);
+ }
+ }
+}
+
+/*
+ * Create/initialise the I/O completion port
+ */
+void
+iocompletionport_init(isc_socketmgr_t *manager) {
+ int errval;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_MANAGER(manager));
+ /*
+ * Create a private heap to handle the socket overlapped structure
+ * The miniumum number of structures is 10, there is no maximum
+ */
+ hHeapHandle = HeapCreate(0, 10 * sizeof(IoCompletionInfo), 0);
+ if (hHeapHandle == NULL) {
+ errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "HeapCreate() failed during "
+ "initialization: %s"),
+ strbuf);
+ exit(1);
+ }
+
+ manager->maxIOCPThreads = min(isc_os_ncpus() + 1, MAX_IOCPTHREADS);
+
+ /* Now Create the Completion Port */
+ manager->hIoCompletionPort = CreateIoCompletionPort(
+ INVALID_HANDLE_VALUE, NULL,
+ 0, manager->maxIOCPThreads);
+ if (manager->hIoCompletionPort == NULL) {
+ errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "CreateIoCompletionPort() failed "
+ "during initialization: %s"),
+ strbuf);
+ exit(1);
+ }
+
+ /*
+ * Worker threads for servicing the I/O
+ */
+ iocompletionport_createthreads(manager->maxIOCPThreads, manager);
+}
+
+/*
+ * Associate a socket with an IO Completion Port. This allows us to queue events for it
+ * and have our worker pool of threads process them.
+ */
+void
+iocompletionport_update(isc_socket_t *sock) {
+ HANDLE hiocp;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ hiocp = CreateIoCompletionPort((HANDLE)sock->fd,
+ sock->manager->hIoCompletionPort, (ULONG_PTR)sock, 0);
+
+ if (hiocp == NULL) {
+ DWORD errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ isc_log_iwrite(isc_lctx,
+ ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_TOOMANYHANDLES,
+ "iocompletionport_update: failed to open"
+ " io completion port: %s",
+ strbuf);
+
+ /* XXXMLG temporary hack to make failures detected.
+ * This function should return errors to the caller, not
+ * exit here.
+ */
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "CreateIoCompletionPort() failed "
+ "during initialization: %s"),
+ strbuf);
+ exit(1);
+ }
+
+ InterlockedIncrement(&sock->manager->iocp_total);
+}
+
+/*
+ * Routine to cleanup and then close the socket.
+ * Only close the socket here if it is NOT associated
+ * with an event, otherwise the WSAWaitForMultipleEvents
+ * may fail due to the fact that the the Wait should not
+ * be running while closing an event or a socket.
+ * The socket is locked before calling this function
+ */
+void
+socket_close(isc_socket_t *sock) {
+
+ REQUIRE(sock != NULL);
+
+ if (sock->fd != INVALID_SOCKET) {
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ _set_state(sock, SOCK_CLOSED);
+ InterlockedDecrement(&sock->manager->totalSockets);
+ }
+}
+
+static isc_once_t initialise_once = ISC_ONCE_INIT;
+static isc_boolean_t initialised = ISC_FALSE;
+
+static void
+initialise(void) {
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+ SOCKET sock;
+ GUID GUIDConnectEx = WSAID_CONNECTEX;
+ GUID GUIDAcceptEx = WSAID_ACCEPTEX;
+ GUID GUIDGetAcceptExSockaddrs = WSAID_GETACCEPTEXSOCKADDRS;
+ DWORD dwBytes;
+
+ /* Need Winsock 2.2 or better */
+ wVersionRequested = MAKEWORD(2, 2);
+
+ err = WSAStartup(wVersionRequested, &wsaData);
+ if (err != 0) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc__strerror(err, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__, "WSAStartup() %s: %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ strbuf);
+ exit(1);
+ }
+ /*
+ * The following APIs do not exist as functions in a library, but we must
+ * ask winsock for them. They are "extensions" -- but why they cannot be
+ * actual functions is beyond me. So, ask winsock for the pointers to the
+ * functions we need.
+ */
+ sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ INSIST(sock != INVALID_SOCKET);
+ err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &GUIDConnectEx, sizeof(GUIDConnectEx),
+ &ISCConnectEx, sizeof(ISCConnectEx),
+ &dwBytes, NULL, NULL);
+ INSIST(err == 0);
+
+ err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &GUIDAcceptEx, sizeof(GUIDAcceptEx),
+ &ISCAcceptEx, sizeof(ISCAcceptEx),
+ &dwBytes, NULL, NULL);
+ INSIST(err == 0);
+
+ err = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
+ &GUIDGetAcceptExSockaddrs, sizeof(GUIDGetAcceptExSockaddrs),
+ &ISCGetAcceptExSockaddrs, sizeof(ISCGetAcceptExSockaddrs),
+ &dwBytes, NULL, NULL);
+ INSIST(err == 0);
+
+ closesocket(sock);
+
+ initialised = ISC_TRUE;
+}
+
+/*
+ * Initialize socket services
+ */
+void
+InitSockets(void) {
+ RUNTIME_CHECK(isc_once_do(&initialise_once,
+ initialise) == ISC_R_SUCCESS);
+ if (!initialised)
+ exit(1);
+}
+
+int
+internal_sendmsg(isc_socket_t *sock, IoCompletionInfo *lpo,
+ struct msghdr *messagehdr, int flags, int *Error)
+{
+ int Result;
+ DWORD BytesSent;
+ DWORD Flags = flags;
+ int total_sent;
+
+ *Error = 0;
+ Result = WSASendTo(sock->fd, messagehdr->msg_iov,
+ messagehdr->msg_iovlen, &BytesSent,
+ Flags, (SOCKADDR *)&messagehdr->to_addr,
+ messagehdr->to_addr_len, (LPWSAOVERLAPPED)lpo,
+ NULL);
+
+ total_sent = (int)BytesSent;
+
+ /* Check for errors.*/
+ if (Result == SOCKET_ERROR) {
+ *Error = WSAGetLastError();
+
+ switch (*Error) {
+ case WSA_IO_INCOMPLETE:
+ case WSA_WAIT_IO_COMPLETION:
+ case WSA_IO_PENDING:
+ case NO_ERROR: /* Strange, but okay */
+ sock->pending_iocp++;
+ sock->pending_send++;
+ break;
+
+ default:
+ return (-1);
+ break;
+ }
+ } else {
+ sock->pending_iocp++;
+ sock->pending_send++;
+ }
+
+ if (lpo != NULL)
+ return (0);
+ else
+ return (total_sent);
+}
+
+static void
+queue_receive_request(isc_socket_t *sock) {
+ DWORD Flags = 0;
+ DWORD NumBytes = 0;
+ int total_bytes = 0;
+ int Result;
+ int Error;
+ WSABUF iov[1];
+ IoCompletionInfo *lpo;
+ isc_result_t isc_result;
+
+ /*
+ * If we already have a receive pending, do nothing.
+ */
+ if (sock->pending_recv > 0)
+ return;
+
+ /*
+ * If no one is waiting, do nothing.
+ */
+ if (ISC_LIST_EMPTY(sock->recv_list))
+ return;
+
+ INSIST(sock->recvbuf.remaining == 0);
+ INSIST(sock->fd != INVALID_SOCKET);
+
+ iov[0].len = sock->recvbuf.len;
+ iov[0].buf = sock->recvbuf.base;
+
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ RUNTIME_CHECK(lpo != NULL);
+ lpo->request_type = SOCKET_RECV;
+
+ sock->recvbuf.from_addr_len = sizeof(sock->recvbuf.from_addr);
+
+ Error = 0;
+ Result = WSARecvFrom((SOCKET)sock->fd, iov, 1,
+ &NumBytes, &Flags,
+ (SOCKADDR *)&sock->recvbuf.from_addr,
+ &sock->recvbuf.from_addr_len,
+ (LPWSAOVERLAPPED)lpo, NULL);
+
+ /* Check for errors. */
+ if (Result == SOCKET_ERROR) {
+ Error = WSAGetLastError();
+
+ switch (Error) {
+ case WSA_IO_PENDING:
+ sock->pending_iocp++;
+ sock->pending_recv++;
+ break;
+
+ default:
+ isc_result = isc__errno2result(Error);
+ if (isc_result == ISC_R_UNEXPECTED)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "WSARecvFrom: Windows error code: %d, isc result %d",
+ Error, isc_result);
+ send_recvdone_abort(sock, isc_result);
+ break;
+ }
+ } else {
+ /*
+ * The recv() finished immediately, but we will still get
+ * a completion event. Rather than duplicate code, let
+ * that thread handle sending the data along its way.
+ */
+ sock->pending_iocp++;
+ sock->pending_recv++;
+ }
+
+ socket_log(__LINE__, sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_DOIORECV,
+ "queue_io_request: fd %d result %d error %d",
+ sock->fd, Result, Error);
+
+ CONSISTENT(sock);
+}
+
+static void
+manager_log(isc_socketmgr_t *sockmgr, isc_logcategory_t *category,
+ isc_logmodule_t *module, int level, const char *fmt, ...)
+{
+ char msgbuf[2048];
+ va_list ap;
+
+ if (!isc_log_wouldlog(isc_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ va_end(ap);
+
+ isc_log_write(isc_lctx, category, module, level,
+ "sockmgr %p: %s", sockmgr, msgbuf);
+}
+
+static void
+socket_log(int lineno, 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, ...)
+{
+ char msgbuf[2048];
+ char peerbuf[256];
+ va_list ap;
+
+
+ if (!isc_log_wouldlog(isc_lctx, level))
+ return;
+
+ va_start(ap, fmt);
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ va_end(ap);
+
+ if (address == NULL) {
+ isc_log_iwrite(isc_lctx, category, module, level,
+ msgcat, msgset, message,
+ "socket %p line %d: %s", sock, lineno, msgbuf);
+ } else {
+ isc_sockaddr_format(address, peerbuf, sizeof(peerbuf));
+ isc_log_iwrite(isc_lctx, category, module, level,
+ msgcat, msgset, message,
+ "socket %p line %d peer %s: %s", sock, lineno,
+ peerbuf, msgbuf);
+ }
+
+}
+
+/*
+ * Make an fd SOCKET non-blocking.
+ */
+static isc_result_t
+make_nonblock(SOCKET fd) {
+ int ret;
+ unsigned long flags = 1;
+ char strbuf[ISC_STRERRORSIZE];
+
+ /* Set the socket to non-blocking */
+ ret = ioctlsocket(fd, FIONBIO, &flags);
+
+ if (ret == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "ioctlsocket(%d, FIOBIO, %d): %s",
+ fd, flags, strbuf);
+
+ return (ISC_R_UNEXPECTED);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
+ * to not work correctly, returning a WSACONNRESET error when a WSASendTo
+ * fails with an "ICMP port unreachable" response and preventing the
+ * socket from using the WSARecvFrom in subsequent operations.
+ * The function below fixes this, but requires that Windows 2000
+ * Service Pack 2 or later be installed on the system. NT 4.0
+ * systems are not affected by this and work correctly.
+ * See Microsoft Knowledge Base Article Q263823 for details of this.
+ */
+isc_result_t
+connection_reset_fix(SOCKET fd) {
+ DWORD dwBytesReturned = 0;
+ BOOL bNewBehavior = FALSE;
+ DWORD status;
+
+ if (isc_win32os_majorversion() < 5)
+ return (ISC_R_SUCCESS); /* NT 4.0 has no problem */
+
+ /* disable bad behavior using IOCTL: SIO_UDP_CONNRESET */
+ status = WSAIoctl(fd, SIO_UDP_CONNRESET, &bNewBehavior,
+ sizeof(bNewBehavior), NULL, 0,
+ &dwBytesReturned, NULL, NULL);
+ if (status != SOCKET_ERROR)
+ return (ISC_R_SUCCESS);
+ else {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "WSAIoctl(SIO_UDP_CONNRESET, oldBehaviour) %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ return (ISC_R_UNEXPECTED);
+ }
+}
+
+/*
+ * Construct an iov array and attach it to the msghdr passed in. This is
+ * the SEND constructor, which will use the used region of the buffer
+ * (if using a buffer list) or will use the internal region (if a single
+ * buffer I/O is requested).
+ *
+ * Nothing can be NULL, and the done event must list at least one buffer
+ * on the buffer linked list for this function to be meaningful.
+ */
+static void
+build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
+ struct msghdr *msg, char *cmsg, WSABUF *iov,
+ IoCompletionInfo *lpo)
+{
+ unsigned int iovcount;
+ isc_buffer_t *buffer;
+ buflist_t *cpbuffer;
+ isc_region_t used;
+ size_t write_count;
+ size_t skip_count;
+
+ memset(msg, 0, sizeof(*msg));
+
+ memcpy(&msg->to_addr, &dev->address.type, dev->address.length);
+ msg->to_addr_len = dev->address.length;
+
+ buffer = ISC_LIST_HEAD(dev->bufferlist);
+ write_count = 0;
+ iovcount = 0;
+
+ /*
+ * Single buffer I/O? Skip what we've done so far in this region.
+ */
+ if (buffer == NULL) {
+ write_count = dev->region.length - dev->n;
+ cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t));
+ RUNTIME_CHECK(cpbuffer != NULL);
+ cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, write_count);
+ RUNTIME_CHECK(cpbuffer->buf != NULL);
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t),
+ cpbuffer->buf, write_count);
+
+ memcpy(cpbuffer->buf,(dev->region.base + dev->n), write_count);
+ cpbuffer->buflen = write_count;
+ ISC_LIST_ENQUEUE(lpo->bufferlist, cpbuffer, link);
+ iov[0].buf = cpbuffer->buf;
+ iov[0].len = write_count;
+ iovcount = 1;
+
+ goto config;
+ }
+
+ /*
+ * Multibuffer I/O.
+ * Skip the data in the buffer list that we have already written.
+ */
+ skip_count = dev->n;
+ while (buffer != NULL) {
+ REQUIRE(ISC_BUFFER_VALID(buffer));
+ if (skip_count < isc_buffer_usedlength(buffer))
+ break;
+ skip_count -= isc_buffer_usedlength(buffer);
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+
+ while (buffer != NULL) {
+ INSIST(iovcount < MAXSCATTERGATHER_SEND);
+
+ isc_buffer_usedregion(buffer, &used);
+
+ if (used.length > 0) {
+ int uselen = used.length - skip_count;
+ cpbuffer = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, sizeof(buflist_t));
+ RUNTIME_CHECK(cpbuffer != NULL);
+ cpbuffer->buf = HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY, uselen);
+ RUNTIME_CHECK(cpbuffer->buf != NULL);
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "alloc_buffer %p %d %p %d", cpbuffer, sizeof(buflist_t),
+ cpbuffer->buf, write_count);
+
+ memcpy(cpbuffer->buf,(used.base + skip_count), uselen);
+ cpbuffer->buflen = uselen;
+ iov[iovcount].buf = cpbuffer->buf;
+ iov[iovcount].len = used.length - skip_count;
+ write_count += uselen;
+ skip_count = 0;
+ iovcount++;
+ }
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+
+ INSIST(skip_count == 0);
+
+ config:
+ msg->msg_iov = iov;
+ msg->msg_iovlen = iovcount;
+ msg->msg_totallen = write_count;
+}
+
+static void
+set_dev_address(isc_sockaddr_t *address, isc_socket_t *sock,
+ isc_socketevent_t *dev)
+{
+ if (sock->type == isc_sockettype_udp) {
+ if (address != NULL)
+ dev->address = *address;
+ else
+ dev->address = sock->address;
+ } else if (sock->type == isc_sockettype_tcp) {
+ INSIST(address == NULL);
+ dev->address = sock->address;
+ }
+}
+
+static void
+destroy_socketevent(isc_event_t *event) {
+ isc_socketevent_t *ev = (isc_socketevent_t *)event;
+
+ INSIST(ISC_LIST_EMPTY(ev->bufferlist));
+
+ (ev->destroy)(event);
+}
+
+static isc_socketevent_t *
+allocate_socketevent(isc_socket_t *sock, isc_eventtype_t eventtype,
+ isc_taskaction_t action, const void *arg)
+{
+ isc_socketevent_t *ev;
+
+ ev = (isc_socketevent_t *)isc_event_allocate(sock->manager->mctx,
+ sock, eventtype,
+ action, arg,
+ sizeof(*ev));
+ if (ev == NULL)
+ return (NULL);
+
+ ev->result = ISC_R_IOERROR; // XXXMLG temporary change to detect failure to set
+ ISC_LINK_INIT(ev, ev_link);
+ ISC_LIST_INIT(ev->bufferlist);
+ ev->region.base = NULL;
+ ev->n = 0;
+ ev->offset = 0;
+ ev->attributes = 0;
+ ev->destroy = ev->ev_destroy;
+ ev->ev_destroy = destroy_socketevent;
+
+ return (ev);
+}
+
+#if defined(ISC_SOCKET_DEBUG)
+static void
+dump_msg(struct msghdr *msg, isc_socket_t *sock) {
+ unsigned int i;
+
+ printf("MSGHDR %p, Socket #: %u\n", msg, sock->fd);
+ printf("\tname %p, namelen %d\n", msg->msg_name, msg->msg_namelen);
+ printf("\tiov %p, iovlen %d\n", msg->msg_iov, msg->msg_iovlen);
+ for (i = 0; i < (unsigned int)msg->msg_iovlen; i++)
+ printf("\t\t%d\tbase %p, len %d\n", i,
+ msg->msg_iov[i].buf,
+ msg->msg_iov[i].len);
+}
+#endif
+
+/*
+ * map the error code
+ */
+int
+map_socket_error(isc_socket_t *sock, int windows_errno, int *isc_errno,
+ char *errorstring, size_t bufsize) {
+
+ int doreturn;
+ switch (windows_errno) {
+ case WSAECONNREFUSED:
+ *isc_errno = ISC_R_CONNREFUSED;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAENETUNREACH:
+ case ERROR_NETWORK_UNREACHABLE:
+ *isc_errno = ISC_R_NETUNREACH;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case ERROR_PORT_UNREACHABLE:
+ case ERROR_HOST_UNREACHABLE:
+ case WSAEHOSTUNREACH:
+ *isc_errno = ISC_R_HOSTUNREACH;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAENETDOWN:
+ *isc_errno = ISC_R_NETDOWN;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAEHOSTDOWN:
+ *isc_errno = ISC_R_HOSTDOWN;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAEACCES:
+ *isc_errno = ISC_R_NOPERM;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAECONNRESET:
+ case WSAENETRESET:
+ case WSAECONNABORTED:
+ case WSAEDISCON:
+ *isc_errno = ISC_R_CONNECTIONRESET;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case WSAENOTCONN:
+ *isc_errno = ISC_R_NOTCONNECTED;
+ if (sock->connected)
+ doreturn = DOIO_HARD;
+ else
+ doreturn = DOIO_SOFT;
+ break;
+ case ERROR_OPERATION_ABORTED:
+ case ERROR_CONNECTION_ABORTED:
+ case ERROR_REQUEST_ABORTED:
+ *isc_errno = ISC_R_CONNECTIONRESET;
+ doreturn = DOIO_HARD;
+ break;
+ case WSAENOBUFS:
+ *isc_errno = ISC_R_NORESOURCES;
+ doreturn = DOIO_HARD;
+ break;
+ case WSAEAFNOSUPPORT:
+ *isc_errno = ISC_R_FAMILYNOSUPPORT;
+ doreturn = DOIO_HARD;
+ break;
+ case WSAEADDRNOTAVAIL:
+ *isc_errno = ISC_R_ADDRNOTAVAIL;
+ doreturn = DOIO_HARD;
+ break;
+ case WSAEDESTADDRREQ:
+ *isc_errno = ISC_R_BADADDRESSFORM;
+ doreturn = DOIO_HARD;
+ break;
+ case ERROR_NETNAME_DELETED:
+ *isc_errno = ISC_R_NETDOWN;
+ doreturn = DOIO_HARD;
+ break;
+ default:
+ *isc_errno = ISC_R_IOERROR;
+ doreturn = DOIO_HARD;
+ break;
+ }
+ if (doreturn == DOIO_HARD) {
+ isc__strerror(windows_errno, errorstring, bufsize);
+ }
+ return (doreturn);
+}
+
+static void
+fill_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
+ isc_region_t r;
+ int copylen;
+ isc_buffer_t *buffer;
+
+ INSIST(dev->n < dev->minimum);
+ INSIST(sock->recvbuf.remaining > 0);
+ INSIST(sock->pending_recv == 0);
+
+ if (sock->type == isc_sockettype_udp) {
+ dev->address.length = sock->recvbuf.from_addr_len;
+ memcpy(&dev->address.type, &sock->recvbuf.from_addr,
+ sock->recvbuf.from_addr_len);
+ if (isc_sockaddr_getport(&dev->address) == 0) {
+ if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
+ socket_log(__LINE__, sock, &dev->address, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_ZEROPORT,
+ "dropping source port zero packet");
+ }
+ sock->recvbuf.remaining = 0;
+ return;
+ }
+ } else if (sock->type == isc_sockettype_tcp) {
+ dev->address = sock->address;
+ }
+
+ /*
+ * Run through the list of buffers we were given, and find the
+ * first one with space. Once it is found, loop through, filling
+ * the buffers as much as possible.
+ */
+ buffer = ISC_LIST_HEAD(dev->bufferlist);
+ if (buffer != NULL) { // Multi-buffer receive
+ while (buffer != NULL && sock->recvbuf.remaining > 0) {
+ REQUIRE(ISC_BUFFER_VALID(buffer));
+ if (isc_buffer_availablelength(buffer) > 0) {
+ isc_buffer_availableregion(buffer, &r);
+ copylen = min(r.length, sock->recvbuf.remaining);
+ memcpy(r.base, sock->recvbuf.consume_position, copylen);
+ sock->recvbuf.consume_position += copylen;
+ sock->recvbuf.remaining -= copylen;
+ isc_buffer_add(buffer, copylen);
+ dev->n += copylen;
+ }
+ buffer = ISC_LIST_NEXT(buffer, link);
+ }
+ } else { // Single-buffer receive
+ copylen = min(dev->region.length - dev->n, sock->recvbuf.remaining);
+ memcpy(dev->region.base + dev->n, sock->recvbuf.consume_position, copylen);
+ sock->recvbuf.consume_position += copylen;
+ sock->recvbuf.remaining -= copylen;
+ dev->n += copylen;
+ }
+
+ /*
+ * UDP receives are all-consuming. That is, if we have 4k worth of
+ * data in our receive buffer, and the caller only gave us
+ * 1k of space, we will toss the remaining 3k of data. TCP
+ * will keep the extra data around and use it for later requests.
+ */
+ if (sock->type == isc_sockettype_udp)
+ sock->recvbuf.remaining = 0;
+}
+
+/*
+ * Copy out as much data from the internal buffer to done events.
+ * As each done event is filled, send it along its way.
+ */
+static void
+completeio_recv(isc_socket_t *sock)
+{
+ isc_socketevent_t *dev;
+
+ /*
+ * If we are in the process of filling our buffer, we cannot
+ * touch it yet, so don't.
+ */
+ if (sock->pending_recv > 0)
+ return;
+
+ while (sock->recvbuf.remaining > 0 && !ISC_LIST_EMPTY(sock->recv_list)) {
+ dev = ISC_LIST_HEAD(sock->recv_list);
+
+ /*
+ * See if we have sufficient data in our receive buffer
+ * to handle this. If we do, copy out the data.
+ */
+ fill_recv(sock, dev);
+
+ /*
+ * Did we satisfy it?
+ */
+ if (dev->n >= dev->minimum) {
+ dev->result = ISC_R_SUCCESS;
+ send_recvdone_event(sock, &dev);
+ }
+ }
+}
+
+/*
+ * Returns:
+ * DOIO_SUCCESS The operation succeeded. dev->result contains
+ * ISC_R_SUCCESS.
+ *
+ * DOIO_HARD A hard or unexpected I/O error was encountered.
+ * dev->result contains the appropriate error.
+ *
+ * DOIO_SOFT A soft I/O error was encountered. No senddone
+ * event was sent. The operation should be retried.
+ *
+ * No other return values are possible.
+ */
+static int
+completeio_send(isc_socket_t *sock, isc_socketevent_t *dev,
+ struct msghdr *messagehdr, int cc, int send_errno)
+{
+ char addrbuf[ISC_SOCKADDR_FORMATSIZE];
+ char strbuf[ISC_STRERRORSIZE];
+
+ if (send_errno != 0) {
+ if (SOFT_ERROR(send_errno))
+ return (DOIO_SOFT);
+
+ return (map_socket_error(sock, send_errno, &dev->result,
+ strbuf, sizeof(strbuf)));
+
+ /*
+ * The other error types depend on whether or not the
+ * socket is UDP or TCP. If it is UDP, some errors
+ * that we expect to be fatal under TCP are merely
+ * annoying, and are really soft errors.
+ *
+ * However, these soft errors are still returned as
+ * a status.
+ */
+ isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf));
+ isc__strerror(send_errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "completeio_send: %s: %s",
+ addrbuf, strbuf);
+ dev->result = isc__errno2result(send_errno);
+ return (DOIO_HARD);
+ }
+
+ /*
+ * If we write less than we expected, update counters, poke.
+ */
+ dev->n += cc;
+ if (cc != messagehdr->msg_totallen)
+ return (DOIO_SOFT);
+
+ /*
+ * Exactly what we wanted to write. We're done with this
+ * entry. Post its completion event.
+ */
+ dev->result = ISC_R_SUCCESS;
+ return (DOIO_SUCCESS);
+}
+
+static int
+startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
+ int *send_errno)
+{
+ char *cmsg = NULL;
+ char strbuf[ISC_STRERRORSIZE];
+ IoCompletionInfo *lpo;
+ int status;
+ struct msghdr *msghdr;
+
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ RUNTIME_CHECK(lpo != NULL);
+ lpo->request_type = SOCKET_SEND;
+ lpo->dev = dev;
+ msghdr = &lpo->messagehdr;
+ memset(msghdr, 0, sizeof(struct msghdr));
+ ISC_LIST_INIT(lpo->bufferlist);
+
+ build_msghdr_send(sock, dev, msghdr, cmsg, sock->iov, lpo);
+
+ *nbytes = internal_sendmsg(sock, lpo, msghdr, 0, send_errno);
+
+ if (*nbytes < 0) {
+ /*
+ * I/O has been initiated
+ * completion will be through the completion port
+ */
+ if (PENDING_ERROR(*send_errno)) {
+ status = DOIO_PENDING;
+ goto done;
+ }
+
+ if (SOFT_ERROR(*send_errno)) {
+ status = DOIO_SOFT;
+ goto done;
+ }
+
+ /*
+ * If we got this far then something is wrong
+ */
+ if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
+ isc__strerror(*send_errno, strbuf, sizeof(strbuf));
+ socket_log(__LINE__, sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_INTERNALSEND,
+ "startio_send: internal_sendmsg(%d) %d "
+ "bytes, err %d/%s",
+ sock->fd, *nbytes, *send_errno, strbuf);
+ }
+ goto done;
+ }
+ dev->result = ISC_R_SUCCESS;
+ status = DOIO_SOFT;
+ done:
+ _set_state(sock, SOCK_DATA);
+ return (status);
+}
+
+static isc_result_t
+allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
+ isc_socket_t **socketp) {
+ isc_socket_t *sock;
+ isc_result_t result;
+
+ sock = isc_mem_get(manager->mctx, sizeof(*sock));
+
+ if (sock == NULL)
+ return (ISC_R_NOMEMORY);
+
+ sock->magic = 0;
+ sock->references = 0;
+
+ sock->manager = manager;
+ sock->type = type;
+ sock->fd = INVALID_SOCKET;
+
+ ISC_LINK_INIT(sock, link);
+
+ /*
+ * set up list of readers and writers to be initially empty
+ */
+ ISC_LIST_INIT(sock->recv_list);
+ ISC_LIST_INIT(sock->send_list);
+ ISC_LIST_INIT(sock->accept_list);
+ sock->connect_ev = NULL;
+ sock->pending_accept = 0;
+ sock->pending_recv = 0;
+ sock->pending_send = 0;
+ sock->pending_iocp = 0;
+ sock->listener = 0;
+ sock->connected = 0;
+ sock->pending_connect = 0;
+ sock->bound = 0;
+ memset(sock->name, 0, sizeof(sock->name)); // zero the name field
+ _set_state(sock, SOCK_INITIALIZED);
+
+ sock->recvbuf.len = 65536;
+ sock->recvbuf.consume_position = sock->recvbuf.base;
+ sock->recvbuf.remaining = 0;
+ sock->recvbuf.base = isc_mem_get(manager->mctx, sock->recvbuf.len); // max buffer size
+ if (sock->recvbuf.base == NULL) {
+ sock->magic = 0;
+ goto error;
+ }
+
+ /*
+ * initialize the lock
+ */
+ result = isc_mutex_init(&sock->lock);
+ if (result != ISC_R_SUCCESS) {
+ sock->magic = 0;
+ isc_mem_put(manager->mctx, sock->recvbuf.base, sock->recvbuf.len);
+ sock->recvbuf.base = NULL;
+ goto error;
+ }
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "allocated");
+
+ sock->magic = SOCKET_MAGIC;
+ *socketp = sock;
+
+ return (ISC_R_SUCCESS);
+
+ error:
+ isc_mem_put(manager->mctx, sock, sizeof(*sock));
+
+ return (result);
+}
+
+/*
+ * Verify that the socket state is consistent.
+ */
+static void
+consistent(isc_socket_t *sock) {
+
+ isc_socketevent_t *dev;
+ isc_socket_newconnev_t *nev;
+ unsigned int count;
+ char *crash_reason;
+ isc_boolean_t crash = ISC_FALSE;
+
+ REQUIRE(sock->pending_iocp == sock->pending_recv + sock->pending_send
+ + sock->pending_accept + sock->pending_connect);
+
+ dev = ISC_LIST_HEAD(sock->send_list);
+ count = 0;
+ while (dev != NULL) {
+ count++;
+ dev = ISC_LIST_NEXT(dev, ev_link);
+ }
+ if (count > sock->pending_send) {
+ crash = ISC_TRUE;
+ crash_reason = "send_list > sock->pending_send";
+ }
+
+ nev = ISC_LIST_HEAD(sock->accept_list);
+ count = 0;
+ while (nev != NULL) {
+ count++;
+ nev = ISC_LIST_NEXT(nev, ev_link);
+ }
+ if (count > sock->pending_accept) {
+ crash = ISC_TRUE;
+ crash_reason = "send_list > sock->pending_send";
+ }
+
+ if (crash) {
+ socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_DESTROYING, "SOCKET INCONSISTENT: %s",
+ crash_reason);
+ sock_dump(sock);
+ INSIST(crash == ISC_FALSE);
+ }
+}
+
+/*
+ * Maybe free the socket.
+ *
+ * This function will veriy tht the socket is no longer in use in any way,
+ * either internally or externally. This is the only place where this
+ * check is to be made; if some bit of code believes that IT is done with
+ * the socket (e.g., some reference counter reaches zero), it should call
+ * this function.
+ *
+ * When calling this function, the socket must be locked, and the manager
+ * must be unlocked.
+ *
+ * When this function returns, *socketp will be NULL. No tricks to try
+ * to hold on to this pointer are allowed.
+ */
+static void
+maybe_free_socket(isc_socket_t **socketp, int lineno) {
+ isc_socket_t *sock = *socketp;
+ *socketp = NULL;
+
+ INSIST(VALID_SOCKET(sock));
+ CONSISTENT(sock);
+
+ if (sock->pending_iocp > 0
+ || sock->pending_recv > 0
+ || sock->pending_send > 0
+ || sock->pending_accept > 0
+ || sock->references > 0
+ || sock->pending_connect == 1
+ || !ISC_LIST_EMPTY(sock->recv_list)
+ || !ISC_LIST_EMPTY(sock->send_list)
+ || !ISC_LIST_EMPTY(sock->accept_list)
+ || sock->fd != INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return;
+ }
+ UNLOCK(&sock->lock);
+
+ free_socket(&sock, lineno);
+}
+
+void
+free_socket(isc_socket_t **sockp, int lineno) {
+ isc_socketmgr_t *manager;
+ isc_socket_t *sock = *sockp;
+ *sockp = NULL;
+
+ manager = sock->manager;
+
+ /*
+ * Seems we can free the socket after all.
+ */
+ manager = sock->manager;
+ socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_DESTROYING, "freeing socket line %d fd %d lock %p semaphore %p",
+ lineno, sock->fd, &sock->lock, sock->lock.LockSemaphore);
+
+ sock->magic = 0;
+ DESTROYLOCK(&sock->lock);
+
+ if (sock->recvbuf.base != NULL)
+ isc_mem_put(manager->mctx, sock->recvbuf.base, sock->recvbuf.len);
+
+ LOCK(&manager->lock);
+ if (ISC_LINK_LINKED(sock, link))
+ ISC_LIST_UNLINK(manager->socklist, sock, link);
+ isc_mem_put(manager->mctx, sock, sizeof(*sock));
+
+ if (ISC_LIST_EMPTY(manager->socklist))
+ SIGNAL(&manager->shutdown_ok);
+ UNLOCK(&manager->lock);
+}
+
+/*
+ * Create a new 'type' socket managed by 'manager'. Events
+ * will be posted to 'task' and when dispatched 'action' will be
+ * 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_socket_t *sock = NULL;
+ isc_result_t result;
+#if defined(USE_CMSG)
+ int on = 1;
+#endif
+#if defined(SO_RCVBUF)
+ ISC_SOCKADDR_LEN_T optlen;
+ int size;
+#endif
+ int socket_errno;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+ REQUIRE(type != isc_sockettype_fdwatch);
+
+ result = allocate_socket(manager, type, &sock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ sock->pf = pf;
+ switch (type) {
+ case isc_sockettype_udp:
+ sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock->fd != INVALID_SOCKET) {
+ result = connection_reset_fix(sock->fd);
+ if (result != ISC_R_SUCCESS) {
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "closed %d %d %d con_reset_fix_failed",
+ sock->pending_recv, sock->pending_send,
+ sock->references);
+ closesocket(sock->fd);
+ _set_state(sock, SOCK_CLOSED);
+ sock->fd = INVALID_SOCKET;
+ free_socket(&sock, __LINE__);
+ return (result);
+ }
+ }
+ break;
+ case isc_sockettype_tcp:
+ sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
+ break;
+ }
+
+ if (sock->fd == INVALID_SOCKET) {
+ socket_errno = WSAGetLastError();
+ free_socket(&sock, __LINE__);
+
+ switch (socket_errno) {
+ case WSAEMFILE:
+ case WSAENOBUFS:
+ return (ISC_R_NORESOURCES);
+
+ case WSAEPROTONOSUPPORT:
+ case WSAEPFNOSUPPORT:
+ case WSAEAFNOSUPPORT:
+ return (ISC_R_FAMILYNOSUPPORT);
+
+ default:
+ isc__strerror(socket_errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+
+ result = make_nonblock(sock->fd);
+ if (result != ISC_R_SUCCESS) {
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "closed %d %d %d make_nonblock_failed",
+ sock->pending_recv, sock->pending_send,
+ sock->references);
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ free_socket(&sock, __LINE__);
+ return (result);
+ }
+
+
+#if defined(USE_CMSG) || defined(SO_RCVBUF)
+ if (type == isc_sockettype_udp) {
+
+#if defined(USE_CMSG)
+#if defined(ISC_PLATFORM_HAVEIPV6)
+#ifdef IPV6_RECVPKTINFO
+ /* 2292bis */
+ if ((pf == AF_INET6)
+ && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+ (void *)&on, sizeof(on)) < 0)) {
+ isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_RECVPKTINFO) "
+ "%s: %s", sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
+#else
+ /* 2292 */
+ if ((pf == AF_INET6)
+ && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
+ (void *)&on, sizeof(on)) < 0)) {
+ isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_PKTINFO) %s: %s",
+ sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
+#endif /* IPV6_RECVPKTINFO */
+#ifdef IPV6_USE_MIN_MTU /*2292bis, not too common yet*/
+ /* use minimum MTU */
+ if (pf == AF_INET6) {
+ (void)setsockopt(sock->fd, IPPROTO_IPV6,
+ IPV6_USE_MIN_MTU,
+ (void *)&on, sizeof(on));
+ }
+#endif
+#endif /* ISC_PLATFORM_HAVEIPV6 */
+#endif /* definef(USE_CMSG) */
+
+#if defined(SO_RCVBUF)
+ optlen = sizeof(size);
+ if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+ (void *)&size, &optlen) >= 0 &&
+ size < RCVBUFSIZE) {
+ size = RCVBUFSIZE;
+ (void)setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
+ (void *)&size, sizeof(size));
+ }
+#endif
+
+ }
+#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
+
+ _set_state(sock, SOCK_OPEN);
+ sock->references = 1;
+ *socketp = sock;
+
+ iocompletionport_update(sock);
+
+ /*
+ * Note we don't have to lock the socket like we normally would because
+ * there are no external references to it yet.
+ */
+ LOCK(&manager->lock);
+ ISC_LIST_APPEND(manager->socklist, sock, link);
+ InterlockedIncrement(&manager->totalSockets);
+ UNLOCK(&manager->lock);
+
+ socket_log(__LINE__, sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_CREATED, "created %u type %u", sock->fd, type);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socket_open(isc_socket_t *sock) {
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+/*
+ * Attach to a socket. Caller must explicitly detach when it is done.
+ */
+void
+isc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+ sock->references++;
+ UNLOCK(&sock->lock);
+
+ *socketp = 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_boolean_t kill_socket = ISC_FALSE;
+
+ REQUIRE(socketp != NULL);
+ sock = *socketp;
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+ REQUIRE(sock->references > 0);
+ sock->references--;
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "detach_socket %d %d %d",
+ sock->pending_recv, sock->pending_send,
+ sock->references);
+
+ if (sock->references == 0 && sock->fd != INVALID_SOCKET) {
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ _set_state(sock, SOCK_CLOSED);
+ }
+
+ maybe_free_socket(&sock, __LINE__);
+
+ *socketp = NULL;
+}
+
+isc_result_t
+isc_socket_close(isc_socket_t *sock) {
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+/*
+ * Dequeue an item off the given socket's read queue, set the result code
+ * in the done event to the one provided, and send it to the task it was
+ * destined for.
+ *
+ * If the event to be sent is on a list, remove it before sending. If
+ * asked to, send and detach from the task as well.
+ *
+ * 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) {
+ isc_task_t *task;
+
+ task = (*dev)->ev_sender;
+ (*dev)->ev_sender = sock;
+
+ if (ISC_LINK_LINKED(*dev, ev_link))
+ ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link);
+
+ if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
+ == ISC_SOCKEVENTATTR_ATTACHED)
+ isc_task_sendanddetach(&task, (isc_event_t **)dev);
+ else
+ isc_task_send(task, (isc_event_t **)dev);
+
+ CONSISTENT(sock);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ */
+static void
+send_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {
+ isc_task_t *task;
+
+ INSIST(dev != NULL && *dev != NULL);
+
+ task = (*dev)->ev_sender;
+ (*dev)->ev_sender = sock;
+
+ if (ISC_LINK_LINKED(*dev, ev_link))
+ ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link);
+
+ if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)
+ == ISC_SOCKEVENTATTR_ATTACHED)
+ isc_task_sendanddetach(&task, (isc_event_t **)dev);
+ else
+ isc_task_send(task, (isc_event_t **)dev);
+
+ CONSISTENT(sock);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ */
+static void
+send_acceptdone_event(isc_socket_t *sock, isc_socket_newconnev_t **adev) {
+ isc_task_t *task;
+
+ INSIST(adev != NULL && *adev != NULL);
+
+ task = (*adev)->ev_sender;
+ (*adev)->ev_sender = sock;
+
+ if (ISC_LINK_LINKED(*adev, ev_link))
+ ISC_LIST_DEQUEUE(sock->accept_list, *adev, ev_link);
+
+ isc_task_sendanddetach(&task, (isc_event_t **)adev);
+
+ CONSISTENT(sock);
+}
+
+/*
+ * See comments for send_recvdone_event() above.
+ */
+static void
+send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cdev) {
+ isc_task_t *task;
+
+ INSIST(cdev != NULL && *cdev != NULL);
+
+ task = (*cdev)->ev_sender;
+ (*cdev)->ev_sender = sock;
+
+ sock->connect_ev = NULL;
+
+ isc_task_sendanddetach(&task, (isc_event_t **)cdev);
+
+ CONSISTENT(sock);
+}
+
+/*
+ * On entry to this function, the event delivered is the internal
+ * readable event, and the first item on the accept_list should be
+ * the done event we want to send. If the list is empty, this is a no-op,
+ * so just close the new connection, unlock, and return.
+ *
+ * Note the the socket is locked before entering here
+ */
+static void
+internal_accept(isc_socket_t *sock, IoCompletionInfo *lpo, int accept_errno) {
+ isc_socket_newconnev_t *adev;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_socket_t *nsock;
+ struct sockaddr *localaddr;
+ int localaddr_len = sizeof(*localaddr);
+ struct sockaddr *remoteaddr;
+ int remoteaddr_len = sizeof(*remoteaddr);
+
+ INSIST(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "internal_accept called");
+
+ INSIST(sock->listener);
+
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_accept > 0);
+ sock->pending_accept--;
+
+ adev = lpo->adev;
+
+ /*
+ * If the event is no longer in the list we can just return.
+ */
+ if (!acceptdone_is_active(sock, adev))
+ goto done;
+
+ nsock = adev->newsocket;
+
+ /*
+ * Pull off the done event.
+ */
+ ISC_LIST_UNLINK(sock->accept_list, adev, ev_link);
+
+ /*
+ * Extract the addresses from the socket, copy them into the structure,
+ * and return the new socket.
+ */
+ ISCGetAcceptExSockaddrs(lpo->acceptbuffer, 0,
+ sizeof(SOCKADDR_STORAGE) + 16, sizeof(SOCKADDR_STORAGE) + 16,
+ (LPSOCKADDR *)&localaddr, &localaddr_len,
+ (LPSOCKADDR *)&remoteaddr, &remoteaddr_len);
+ memcpy(&adev->address.type, remoteaddr, remoteaddr_len);
+ adev->address.length = remoteaddr_len;
+ nsock->address = adev->address;
+ nsock->pf = adev->address.type.sa.sa_family;
+
+ socket_log(__LINE__, nsock, &nsock->address, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "internal_accept parent %p", sock);
+
+ result = make_nonblock(adev->newsocket->fd);
+ INSIST(result == ISC_R_SUCCESS);
+
+ INSIST(setsockopt(nsock->fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
+ (char *)&sock->fd, sizeof(sock->fd)) == 0);
+
+ /*
+ * Hook it up into the manager.
+ */
+ nsock->bound = 1;
+ nsock->connected = 1;
+ _set_state(nsock, SOCK_OPEN);
+
+ LOCK(&nsock->manager->lock);
+ ISC_LIST_APPEND(nsock->manager->socklist, nsock, link);
+ InterlockedIncrement(&nsock->manager->totalSockets);
+ UNLOCK(&nsock->manager->lock);
+
+ socket_log(__LINE__, sock, &nsock->address, CREATION,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
+ "accepted_connection new_socket %p fd %d",
+ nsock, nsock->fd);
+
+ adev->result = result;
+ send_acceptdone_event(sock, &adev);
+
+done:
+ CONSISTENT(sock);
+ UNLOCK(&sock->lock);
+
+ HeapFree(hHeapHandle, 0, lpo->acceptbuffer);
+ lpo->acceptbuffer = NULL;
+}
+
+/*
+ * Called when a socket with a pending connect() finishes.
+ * Note that the socket is locked before entering.
+ */
+static void
+internal_connect(isc_socket_t *sock, IoCompletionInfo *lpo, int connect_errno) {
+ isc_socket_connev_t *cdev;
+ char strbuf[ISC_STRERRORSIZE];
+
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_connect == 1);
+ sock->pending_connect = 0;
+
+ /*
+ * Has this event been canceled?
+ */
+ cdev = lpo->cdev;
+ if (!connectdone_is_active(sock, cdev)) {
+ sock->pending_connect = 0;
+ if (sock->fd != INVALID_SOCKET) {
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ _set_state(sock, SOCK_CLOSED);
+ }
+ CONSISTENT(sock);
+ UNLOCK(&sock->lock);
+ return;
+ }
+
+ /*
+ * Check possible Windows network event error status here.
+ */
+ if (connect_errno != 0) {
+ /*
+ * If the error is SOFT, just try again on this
+ * fd and pretend nothing strange happened.
+ */
+ if (SOFT_ERROR(connect_errno) ||
+ connect_errno == WSAEINPROGRESS) {
+ sock->pending_connect = 1;
+ CONSISTENT(sock);
+ UNLOCK(&sock->lock);
+ return;
+ }
+
+ /*
+ * Translate other errors into ISC_R_* flavors.
+ */
+ switch (connect_errno) {
+#define ERROR_MATCH(a, b) case a: cdev->result = b; break;
+ ERROR_MATCH(WSAEACCES, ISC_R_NOPERM);
+ ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
+ ERROR_MATCH(WSAEAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);
+ ERROR_MATCH(WSAECONNREFUSED, ISC_R_CONNREFUSED);
+ ERROR_MATCH(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH);
+ ERROR_MATCH(WSAEHOSTDOWN, ISC_R_HOSTDOWN);
+ ERROR_MATCH(WSAENETUNREACH, ISC_R_NETUNREACH);
+ ERROR_MATCH(WSAENETDOWN, ISC_R_NETDOWN);
+ ERROR_MATCH(WSAENOBUFS, ISC_R_NORESOURCES);
+ ERROR_MATCH(WSAECONNRESET, ISC_R_CONNECTIONRESET);
+ ERROR_MATCH(WSAECONNABORTED, ISC_R_CONNECTIONRESET);
+ ERROR_MATCH(WSAETIMEDOUT, ISC_R_TIMEDOUT);
+#undef ERROR_MATCH
+ default:
+ cdev->result = ISC_R_UNEXPECTED;
+ isc__strerror(connect_errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "internal_connect: connect() %s",
+ strbuf);
+ }
+ } else {
+ INSIST(setsockopt(sock->fd, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0);
+ cdev->result = ISC_R_SUCCESS;
+ sock->connected = 1;
+ socket_log(__LINE__, sock, &sock->address, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
+ "internal_connect: success");
+ }
+
+ send_connectdone_event(sock, &cdev);
+
+ UNLOCK(&sock->lock);
+}
+
+/*
+ * Loop through the socket, returning ISC_R_EOF for each done event pending.
+ */
+static void
+send_recvdone_abort(isc_socket_t *sock, isc_result_t result) {
+ isc_socketevent_t *dev;
+
+ while (!ISC_LIST_EMPTY(sock->recv_list)) {
+ dev = ISC_LIST_HEAD(sock->recv_list);
+ dev->result = result;
+ send_recvdone_event(sock, &dev);
+ }
+}
+
+/*
+ * Take the data we received in our private buffer, and if any recv() calls on
+ * our list are satisfied, send the corresponding done event.
+ *
+ * If we need more data (there are still items on the recv_list after we consume all
+ * our data) then arrange for another system recv() call to fill our buffers.
+ */
+static void
+internal_recv(isc_socket_t *sock, int nbytes)
+{
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ socket_log(__LINE__, sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,
+ "internal_recv: %d bytes received", nbytes);
+
+ /*
+ * If we got here, the I/O operation succeeded. However, we might still have removed this
+ * event from our notification list (or never placed it on it due to immediate completion.)
+ * Handle the reference counting here, and handle the cancellation event just after.
+ */
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_recv > 0);
+ sock->pending_recv--;
+
+ /*
+ * The only way we could have gotten here is that our I/O has successfully completed.
+ * Update our pointers, and move on. The only odd case here is that we might not
+ * have received enough data on a TCP stream to satisfy the minimum requirements. If
+ * this is the case, we will re-issue the recv() call for what we need.
+ *
+ * We do check for a recv() of 0 bytes on a TCP stream. This means the remote end
+ * has closed.
+ */
+ if (nbytes == 0 && sock->type == isc_sockettype_tcp) {
+ send_recvdone_abort(sock, ISC_R_EOF);
+ maybe_free_socket(&sock, __LINE__);
+ return;
+ }
+ sock->recvbuf.remaining = nbytes;
+ sock->recvbuf.consume_position = sock->recvbuf.base;
+ completeio_recv(sock);
+
+ /*
+ * If there are more receivers waiting for data, queue another receive
+ * here.
+ */
+ queue_receive_request(sock);
+
+ /*
+ * Unlock and/or destroy if we are the last thing this socket has left to do.
+ */
+ maybe_free_socket(&sock, __LINE__);
+}
+
+static void
+internal_send(isc_socket_t *sock, isc_socketevent_t *dev,
+ struct msghdr *messagehdr, int nbytes, int send_errno, IoCompletionInfo *lpo)
+{
+ buflist_t *buffer;
+
+ /*
+ * Find out what socket this is and lock it.
+ */
+ INSIST(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ socket_log(__LINE__, sock, NULL, IOEVENT,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,
+ "internal_send: task got socket event %p", dev);
+
+ buffer = ISC_LIST_HEAD(lpo->bufferlist);
+ while (buffer != NULL) {
+ ISC_LIST_DEQUEUE(lpo->bufferlist, buffer, link);
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,
+ "free_buffer %p %p", buffer, buffer->buf);
+
+ HeapFree(hHeapHandle, 0, buffer->buf);
+ HeapFree(hHeapHandle, 0, buffer);
+ buffer = ISC_LIST_HEAD(lpo->bufferlist);
+ }
+
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_send > 0);
+ sock->pending_send--;
+
+ /* If the event is no longer in the list we can just return */
+ if (!senddone_is_active(sock, dev))
+ goto done;
+
+ /*
+ * Set the error code and send things on its way.
+ */
+ switch (completeio_send(sock, dev, messagehdr, nbytes, send_errno)) {
+ case DOIO_SOFT:
+ break;
+ case DOIO_HARD:
+ case DOIO_SUCCESS:
+ send_senddone_event(sock, &dev);
+ break;
+ }
+
+ done:
+ maybe_free_socket(&sock, __LINE__);
+}
+
+/*
+ * These return if the done event passed in is on the list (or for connect, is
+ * the one we're waiting for. Using these ensures we will not double-send an
+ * event.
+ */
+static isc_boolean_t
+senddone_is_active(isc_socket_t *sock, isc_socketevent_t *dev)
+{
+ isc_socketevent_t *ldev;
+
+ ldev = ISC_LIST_HEAD(sock->send_list);
+ while (ldev != NULL && ldev != dev)
+ ldev = ISC_LIST_NEXT(ldev, ev_link);
+
+ return (ldev == NULL ? ISC_FALSE : ISC_TRUE);
+}
+
+static isc_boolean_t
+acceptdone_is_active(isc_socket_t *sock, isc_socket_newconnev_t *dev)
+{
+ isc_socket_newconnev_t *ldev;
+
+ ldev = ISC_LIST_HEAD(sock->accept_list);
+ while (ldev != NULL && ldev != dev)
+ ldev = ISC_LIST_NEXT(ldev, ev_link);
+
+ return (ldev == NULL ? ISC_FALSE : ISC_TRUE);
+}
+
+static isc_boolean_t
+connectdone_is_active(isc_socket_t *sock, isc_socket_connev_t *dev)
+{
+ return (sock->connect_ev == dev ? ISC_TRUE : ISC_FALSE);
+}
+
+/*
+ * This is the I/O Completion Port Worker Function. It loops forever
+ * waiting for I/O to complete and then forwards them for further
+ * processing. There are a number of these in separate threads.
+ */
+static isc_threadresult_t WINAPI
+SocketIoThread(LPVOID ThreadContext) {
+ isc_socketmgr_t *manager = ThreadContext;
+ BOOL bSuccess = FALSE;
+ DWORD nbytes;
+ IoCompletionInfo *lpo = NULL;
+ isc_socket_t *sock = NULL;
+ int request;
+ struct msghdr *messagehdr = NULL;
+ int errval;
+ char strbuf[ISC_STRERRORSIZE];
+ int errstatus;
+
+ REQUIRE(VALID_MANAGER(manager));
+
+ /*
+ * Set the thread priority high enough so I/O will
+ * preempt normal recv packet processing, but not
+ * higher than the timer sync thread.
+ */
+ if (!SetThreadPriority(GetCurrentThread(),
+ THREAD_PRIORITY_ABOVE_NORMAL)) {
+ errval = GetLastError();
+ isc__strerror(errval, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_FAILED,
+ "Can't set thread priority: %s"),
+ strbuf);
+ }
+
+ /*
+ * Loop forever waiting on I/O Completions and then processing them
+ */
+ while (TRUE) {
+ bSuccess = GetQueuedCompletionStatus(manager->hIoCompletionPort,
+ &nbytes, (LPDWORD)&sock,
+ (LPWSAOVERLAPPED *)&lpo,
+ INFINITE);
+ if (lpo == NULL) /* Received request to exit */
+ break;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ request = lpo->request_type;
+
+ errstatus = 0;
+ if (!bSuccess) {
+ isc_result_t isc_result;
+
+ /*
+ * Did the I/O operation complete?
+ */
+ errstatus = WSAGetLastError();
+ isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+ switch (request) {
+ case SOCKET_RECV:
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_recv > 0);
+ sock->pending_recv--;
+ send_recvdone_abort(sock, isc_result);
+ if (isc_result == ISC_R_UNEXPECTED) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "SOCKET_RECV: Windows error code: %d, returning ISC error %d",
+ errstatus, isc_result);
+ }
+ break;
+
+ case SOCKET_SEND:
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_send > 0);
+ sock->pending_send--;
+ if (senddone_is_active(sock, lpo->dev)) {
+ lpo->dev->result = isc_result;
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "cancelled_send");
+ send_senddone_event(sock, &lpo->dev);
+ }
+ break;
+
+ case SOCKET_ACCEPT:
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_accept > 0);
+ sock->pending_accept--;
+ if (acceptdone_is_active(sock, lpo->adev)) {
+ closesocket(lpo->adev->newsocket->fd);
+ lpo->adev->newsocket->fd = INVALID_SOCKET;
+ lpo->adev->newsocket->references--;
+ free_socket(&lpo->adev->newsocket, __LINE__);
+ lpo->adev->result = isc_result;
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "cancelled_accept");
+ send_acceptdone_event(sock, &lpo->adev);
+ }
+ break;
+
+ case SOCKET_CONNECT:
+ INSIST(sock->pending_iocp > 0);
+ sock->pending_iocp--;
+ INSIST(sock->pending_connect == 1);
+ sock->pending_connect = 0;
+ if (connectdone_is_active(sock, lpo->cdev)) {
+ lpo->cdev->result = isc_result;
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "cancelled_connect");
+ send_connectdone_event(sock, &lpo->cdev);
+ }
+ break;
+ }
+ maybe_free_socket(&sock, __LINE__);
+
+ if (lpo != NULL)
+ HeapFree(hHeapHandle, 0, lpo);
+ continue;
+ }
+
+ messagehdr = &lpo->messagehdr;
+
+ switch (request) {
+ case SOCKET_RECV:
+ internal_recv(sock, nbytes);
+ break;
+ case SOCKET_SEND:
+ internal_send(sock, lpo->dev, messagehdr, nbytes, errstatus, lpo);
+ break;
+ case SOCKET_ACCEPT:
+ internal_accept(sock, lpo, errstatus);
+ break;
+ case SOCKET_CONNECT:
+ internal_connect(sock, lpo, errstatus);
+ break;
+ }
+
+ if (lpo != NULL)
+ HeapFree(hHeapHandle, 0, lpo);
+ }
+
+ /*
+ * Exit Completion Port Thread
+ */
+ manager_log(manager, TRACE,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_EXITING, "SocketIoThread exiting"));
+ return ((isc_threadresult_t)0);
+}
+
+/*
+ * Create a new socket manager.
+ */
+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_socketmgr_t *manager;
+ isc_result_t result;
+
+ REQUIRE(managerp != NULL && *managerp == NULL);
+
+ if (maxsocks != 0)
+ return (ISC_R_NOTIMPLEMENTED);
+
+ manager = isc_mem_get(mctx, sizeof(*manager));
+ if (manager == NULL)
+ return (ISC_R_NOMEMORY);
+
+ InitSockets();
+
+ manager->magic = SOCKET_MANAGER_MAGIC;
+ manager->mctx = NULL;
+ ISC_LIST_INIT(manager->socklist);
+ result = isc_mutex_init(&manager->lock);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ return (result);
+ }
+ if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
+ DESTROYLOCK(&manager->lock);
+ isc_mem_put(mctx, manager, sizeof(*manager));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_condition_init() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ return (ISC_R_UNEXPECTED);
+ }
+
+ isc_mem_attach(mctx, &manager->mctx);
+
+ iocompletionport_init(manager); /* Create the Completion Ports */
+
+ manager->bShutdown = ISC_FALSE;
+ manager->totalSockets = 0;
+ manager->iocp_total = 0;
+
+ *managerp = manager;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(nsockp != NULL);
+
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+void
+isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
+ isc_socketmgr_t *manager;
+ int i;
+ isc_mem_t *mctx;
+
+ /*
+ * Destroy a socket manager.
+ */
+
+ REQUIRE(managerp != NULL);
+ manager = *managerp;
+ REQUIRE(VALID_MANAGER(manager));
+
+ LOCK(&manager->lock);
+
+ /*
+ * Wait for all sockets to be destroyed.
+ */
+ while (!ISC_LIST_EMPTY(manager->socklist)) {
+ manager_log(manager, CREATION,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_SOCKETSREMAIN,
+ "sockets exist"));
+ WAIT(&manager->shutdown_ok, &manager->lock);
+ }
+
+ UNLOCK(&manager->lock);
+
+ /*
+ * Here, we need to had some wait code for the completion port
+ * thread.
+ */
+ signal_iocompletionport_exit(manager);
+ manager->bShutdown = ISC_TRUE;
+
+ /*
+ * Wait for threads to exit.
+ */
+ for (i = 0; i < manager->maxIOCPThreads; i++) {
+ if (isc_thread_join((isc_thread_t) manager->hIOCPThreads[i],
+ NULL) != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_thread_join() for Completion Port %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ }
+ /*
+ * Clean up.
+ */
+
+ CloseHandle(manager->hIoCompletionPort);
+
+ (void)isc_condition_destroy(&manager->shutdown_ok);
+
+ DESTROYLOCK(&manager->lock);
+ manager->magic = 0;
+ mctx= manager->mctx;
+ isc_mem_put(mctx, manager, sizeof(*manager));
+
+ isc_mem_detach(&mctx);
+
+ *managerp = NULL;
+}
+
+static void
+queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev)
+{
+ isc_task_t *ntask = NULL;
+
+ isc_task_attach(task, &ntask);
+ dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
+
+ /*
+ * Enqueue the request.
+ */
+ INSIST(!ISC_LINK_LINKED(dev, ev_link));
+ ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link);
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "queue_receive_event: event %p -> task %p",
+ dev, ntask);
+}
+
+/*
+ * Check the pending receive queue, and if we have data pending, give it to this
+ * caller. If we have none, queue an I/O request. If this caller is not the first
+ * on the list, then we will just queue this event and return.
+ *
+ * Caller must have the socket locked.
+ */
+static isc_result_t
+socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
+ unsigned int flags)
+{
+ int cc = 0;
+ isc_task_t *ntask = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ int recv_errno = 0;
+
+ dev->ev_sender = task;
+
+ if (sock->fd == INVALID_SOCKET)
+ return (ISC_R_EOF);
+
+ /*
+ * Queue our event on the list of things to do. Call our function to
+ * attempt to fill buffers as much as possible, and return done events.
+ * We are going to lie about our handling of the ISC_SOCKFLAG_IMMEDIATE
+ * here and tell our caller that we could not satisfy it immediately.
+ */
+ queue_receive_event(sock, task, dev);
+ if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
+ result = ISC_R_INPROGRESS;
+
+ completeio_recv(sock);
+
+ /*
+ * If there are more receivers waiting for data, queue another receive
+ * here. If the
+ */
+ queue_receive_request(sock);
+
+ 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_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+ unsigned int iocount;
+ isc_buffer_t *buffer;
+ isc_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * Make sure that the socket is not closed. XXXMLG change error here?
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ REQUIRE(buflist != NULL);
+ REQUIRE(!ISC_LIST_EMPTY(*buflist));
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ iocount = isc_bufferlist_availablecount(buflist);
+ REQUIRE(iocount > 0);
+
+ INSIST(sock->bound);
+
+ dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+
+ /*
+ * UDP sockets are always partial read
+ */
+ if (sock->type == isc_sockettype_udp)
+ dev->minimum = 1;
+ else {
+ if (minimum == 0)
+ dev->minimum = iocount;
+ else
+ dev->minimum = minimum;
+ }
+
+ /*
+ * Move each buffer from the passed in list to our internal one.
+ */
+ buffer = ISC_LIST_HEAD(*buflist);
+ while (buffer != NULL) {
+ ISC_LIST_DEQUEUE(*buflist, buffer, link);
+ ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
+ buffer = ISC_LIST_HEAD(*buflist);
+ }
+
+ ret = socket_recv(sock, dev, task, 0);
+
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+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_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+ isc_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ INSIST(sock->bound);
+
+ dev = allocate_socketevent(sock, ISC_SOCKEVENT_RECVDONE, action, arg);
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+
+ ret = isc_socket_recv2(sock, region, minimum, task, dev, 0);
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+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_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ event->result = ISC_R_UNEXPECTED;
+ event->ev_sender = sock;
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ ISC_LIST_INIT(event->bufferlist);
+ event->region = *region;
+ event->n = 0;
+ event->offset = 0;
+ event->attributes = 0;
+
+ /*
+ * UDP sockets are always partial read.
+ */
+ if (sock->type == isc_sockettype_udp)
+ event->minimum = 1;
+ else {
+ if (minimum == 0)
+ event->minimum = region->length;
+ else
+ event->minimum = minimum;
+ }
+
+ ret = socket_recv(sock, event, task, flags);
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+/*
+ * Caller must have the socket locked.
+ */
+static isc_result_t
+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)
+{
+ int io_state;
+ int send_errno = 0;
+ int cc = 0;
+ isc_task_t *ntask = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+
+ dev->ev_sender = task;
+
+ set_dev_address(address, sock, dev);
+ if (pktinfo != NULL) {
+ socket_log(__LINE__, sock, NULL, TRACE, isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_PKTINFOPROVIDED,
+ "pktinfo structure provided, ifindex %u (set to 0)",
+ pktinfo->ipi6_ifindex);
+
+ dev->attributes |= ISC_SOCKEVENTATTR_PKTINFO;
+ dev->pktinfo = *pktinfo;
+ /*
+ * Set the pktinfo index to 0 here, to let the kernel decide
+ * what interface it should send on.
+ */
+ dev->pktinfo.ipi6_ifindex = 0;
+ }
+
+ io_state = startio_send(sock, dev, &cc, &send_errno);
+ switch (io_state) {
+ case DOIO_PENDING: /* I/O started. Nothing more to do */
+ case DOIO_SOFT:
+ /*
+ * We couldn't send all or part of the request right now, so
+ * queue it unless ISC_SOCKFLAG_NORETRY is set.
+ */
+ if ((flags & ISC_SOCKFLAG_NORETRY) == 0) {
+ isc_task_attach(task, &ntask);
+ dev->attributes |= ISC_SOCKEVENTATTR_ATTACHED;
+
+ /*
+ * Enqueue the request.
+ */
+ INSIST(!ISC_LINK_LINKED(dev, ev_link));
+ ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link);
+
+ socket_log(__LINE__, sock, NULL, EVENT, NULL, 0, 0,
+ "socket_send: event %p -> task %p",
+ dev, ntask);
+
+ if ((flags & ISC_SOCKFLAG_IMMEDIATE) != 0)
+ result = ISC_R_INPROGRESS;
+ break;
+ }
+
+ case DOIO_SUCCESS:
+ break;
+ }
+
+ 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)
+{
+ /*
+ * REQUIRE() checking is performed in isc_socket_sendto().
+ */
+ 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_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+ isc_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(sock->type != isc_sockettype_fdwatch);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+ REQUIRE(region != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ INSIST(sock->bound);
+
+ dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+ dev->region = *region;
+
+ ret = socket_send(sock, dev, task, address, pktinfo, 0);
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+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));
+}
+
+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_socketevent_t *dev;
+ isc_socketmgr_t *manager;
+ unsigned int iocount;
+ isc_buffer_t *buffer;
+ isc_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+ REQUIRE(buflist != NULL);
+ REQUIRE(!ISC_LIST_EMPTY(*buflist));
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ iocount = isc_bufferlist_usedcount(buflist);
+ REQUIRE(iocount > 0);
+
+ dev = allocate_socketevent(sock, ISC_SOCKEVENT_SENDDONE, action, arg);
+ if (dev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+
+ /*
+ * Move each buffer from the passed in list to our internal one.
+ */
+ buffer = ISC_LIST_HEAD(*buflist);
+ while (buffer != NULL) {
+ ISC_LIST_DEQUEUE(*buflist, buffer, link);
+ ISC_LIST_ENQUEUE(dev->bufferlist, buffer, link);
+ buffer = ISC_LIST_HEAD(*buflist);
+ }
+
+ ret = socket_send(sock, dev, task, address, pktinfo, 0);
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+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_result_t ret;
+
+ REQUIRE(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ REQUIRE((flags & ~(ISC_SOCKFLAG_IMMEDIATE|ISC_SOCKFLAG_NORETRY)) == 0);
+ if ((flags & ISC_SOCKFLAG_NORETRY) != 0)
+ REQUIRE(sock->type == isc_sockettype_udp);
+ event->ev_sender = sock;
+ event->result = ISC_R_UNEXPECTED;
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+ ISC_LIST_INIT(event->bufferlist);
+ event->region = *region;
+ event->n = 0;
+ event->offset = 0;
+ event->attributes = 0;
+
+ ret = socket_send(sock, event, task, address, pktinfo, flags);
+ UNLOCK(&sock->lock);
+ return (ret);
+}
+
+isc_result_t
+isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+ unsigned int options) {
+ int bind_errno;
+ char strbuf[ISC_STRERRORSIZE];
+ int on = 1;
+
+ REQUIRE(VALID_SOCKET(sock));
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ INSIST(!sock->bound);
+
+ if (sock->pf != sockaddr->type.sa.sa_family) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_FAMILYMISMATCH);
+ }
+ /*
+ * Only set SO_REUSEADDR when we want a specific port.
+ */
+ if ((options & ISC_SOCKET_REUSEADDRESS) != 0 &&
+ isc_sockaddr_getport(sockaddr) != (in_port_t)0 &&
+ setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
+ sizeof(on)) < 0) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d) %s", sock->fd,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ /* Press on... */
+ }
+ if (bind(sock->fd, &sockaddr->type.sa, sockaddr->length) < 0) {
+ bind_errno = WSAGetLastError();
+ UNLOCK(&sock->lock);
+ switch (bind_errno) {
+ case WSAEACCES:
+ return (ISC_R_NOPERM);
+ case WSAEADDRNOTAVAIL:
+ return (ISC_R_ADDRNOTAVAIL);
+ case WSAEADDRINUSE:
+ return (ISC_R_ADDRINUSE);
+ case WSAEINVAL:
+ return (ISC_R_BOUND);
+ default:
+ isc__strerror(bind_errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "bind: %s",
+ strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+
+ socket_log(__LINE__, sock, sockaddr, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "bound");
+ sock->bound = 1;
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socket_filter(isc_socket_t *sock, const char *filter) {
+ UNUSED(sock);
+ UNUSED(filter);
+
+ REQUIRE(VALID_SOCKET(sock));
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+/*
+ * Set up to listen on a given socket. We do this by creating an internal
+ * event that will be dispatched when the socket has read activity. The
+ * watcher will send the internal event to the task when there is a new
+ * connection.
+ *
+ * Unlike in read, we don't preallocate a done event here. Every time there
+ * 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) {
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ REQUIRE(!sock->listener);
+ REQUIRE(sock->bound);
+ REQUIRE(sock->type == isc_sockettype_tcp);
+
+ if (backlog == 0)
+ backlog = SOMAXCONN;
+
+ if (listen(sock->fd, (int)backlog) < 0) {
+ UNLOCK(&sock->lock);
+ isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "listen: %s", strbuf);
+
+ return (ISC_R_UNEXPECTED);
+ }
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND, "listening");
+ sock->listener = 1;
+ _set_state(sock, SOCK_LISTEN);
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * This should try to do agressive accept() XXXMLG
+ */
+isc_result_t
+isc_socket_accept(isc_socket_t *sock,
+ isc_task_t *task, isc_taskaction_t action, const void *arg)
+{
+ isc_socket_newconnev_t *adev;
+ isc_socketmgr_t *manager;
+ isc_task_t *ntask = NULL;
+ isc_socket_t *nsock;
+ isc_result_t result;
+ IoCompletionInfo *lpo;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ REQUIRE(sock->listener);
+
+ /*
+ * Sender field is overloaded here with the task we will be sending
+ * this event to. Just before the actual event is delivered the
+ * actual ev_sender will be touched up to be the socket.
+ */
+ adev = (isc_socket_newconnev_t *)
+ isc_event_allocate(manager->mctx, task, ISC_SOCKEVENT_NEWCONN,
+ action, arg, sizeof(*adev));
+ if (adev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+ ISC_LINK_INIT(adev, ev_link);
+
+ result = allocate_socket(manager, sock->type, &nsock);
+ if (result != ISC_R_SUCCESS) {
+ isc_event_free((isc_event_t **)&adev);
+ UNLOCK(&sock->lock);
+ return (result);
+ }
+
+ /*
+ * AcceptEx() requires we pass in a socket.
+ */
+ nsock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
+ if (nsock->fd == INVALID_SOCKET) {
+ free_socket(&nsock, __LINE__);
+ isc_event_free((isc_event_t **)&adev);
+ UNLOCK(&sock->lock);
+ return (ISC_R_FAILURE); // XXXMLG need real error message
+ }
+
+ /*
+ * Attach to socket and to task.
+ */
+ isc_task_attach(task, &ntask);
+ nsock->references++;
+
+ adev->ev_sender = ntask;
+ adev->newsocket = nsock;
+ _set_state(nsock, SOCK_ACCEPT);
+
+ /*
+ * Queue io completion for an accept().
+ */
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ RUNTIME_CHECK(lpo != NULL);
+ lpo->acceptbuffer = (void *)HeapAlloc(hHeapHandle, HEAP_ZERO_MEMORY,
+ (sizeof(SOCKADDR_STORAGE) + 16) * 2);
+ RUNTIME_CHECK(lpo->acceptbuffer != NULL);
+
+ lpo->adev = adev;
+ lpo->request_type = SOCKET_ACCEPT;
+
+ ISCAcceptEx(sock->fd,
+ nsock->fd, /* Accepted Socket */
+ lpo->acceptbuffer, /* Buffer for initial Recv */
+ 0, /* Length of Buffer */
+ sizeof(SOCKADDR_STORAGE) + 16, /* Local address length + 16 */
+ sizeof(SOCKADDR_STORAGE) + 16, /* Remote address lengh + 16 */
+ (LPDWORD)&lpo->received_bytes, /* Bytes Recved */
+ (LPOVERLAPPED)lpo /* Overlapped structure */
+ );
+ iocompletionport_update(nsock);
+
+ socket_log(__LINE__, sock, NULL, TRACE,
+ isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_BOUND,
+ "accepting for nsock %p fd %d", nsock, nsock->fd);
+
+ /*
+ * Enqueue the event
+ */
+ ISC_LIST_ENQUEUE(sock->accept_list, adev, ev_link);
+ sock->pending_accept++;
+ sock->pending_iocp++;
+
+ UNLOCK(&sock->lock);
+ return (ISC_R_SUCCESS);
+}
+
+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)
+{
+ char strbuf[ISC_STRERRORSIZE];
+ isc_socket_connev_t *cdev;
+ isc_task_t *ntask = NULL;
+ isc_socketmgr_t *manager;
+ IoCompletionInfo *lpo;
+ int bind_errno;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(addr != NULL);
+ REQUIRE(task != NULL);
+ REQUIRE(action != NULL);
+
+ manager = sock->manager;
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(addr != NULL);
+
+ if (isc_sockaddr_ismulticast(addr))
+ return (ISC_R_MULTICAST);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ /*
+ * Windows sockets won't connect unless the socket is bound.
+ */
+ if (!sock->bound) {
+ isc_sockaddr_t any;
+
+ isc_sockaddr_anyofpf(&any, isc_sockaddr_pf(addr));
+ if (bind(sock->fd, &any.type.sa, any.length) < 0) {
+ bind_errno = WSAGetLastError();
+ UNLOCK(&sock->lock);
+ switch (bind_errno) {
+ case WSAEACCES:
+ return (ISC_R_NOPERM);
+ case WSAEADDRNOTAVAIL:
+ return (ISC_R_ADDRNOTAVAIL);
+ case WSAEADDRINUSE:
+ return (ISC_R_ADDRINUSE);
+ case WSAEINVAL:
+ return (ISC_R_BOUND);
+ default:
+ isc__strerror(bind_errno, strbuf,
+ sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "bind: %s", strbuf);
+ return (ISC_R_UNEXPECTED);
+ }
+ }
+ sock->bound = 1;
+ }
+
+ REQUIRE(!sock->pending_connect);
+
+ cdev = (isc_socket_connev_t *)isc_event_allocate(manager->mctx, sock,
+ ISC_SOCKEVENT_CONNECT,
+ action, arg,
+ sizeof(*cdev));
+ if (cdev == NULL) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_NOMEMORY);
+ }
+ ISC_LINK_INIT(cdev, ev_link);
+
+ if (sock->type == isc_sockettype_tcp) {
+ /*
+ * Queue io completion for an accept().
+ */
+ lpo = (IoCompletionInfo *)HeapAlloc(hHeapHandle,
+ HEAP_ZERO_MEMORY,
+ sizeof(IoCompletionInfo));
+ lpo->cdev = cdev;
+ lpo->request_type = SOCKET_CONNECT;
+
+ sock->address = *addr;
+ ISCConnectEx(sock->fd, &addr->type.sa, addr->length,
+ NULL, 0, NULL, (LPOVERLAPPED)lpo);
+
+ /*
+ * Attach to task.
+ */
+ isc_task_attach(task, &ntask);
+ cdev->ev_sender = ntask;
+
+ sock->pending_connect = 1;
+ _set_state(sock, SOCK_CONNECT);
+
+ /*
+ * Enqueue the request.
+ */
+ sock->connect_ev = cdev;
+ sock->pending_iocp++;
+ } else {
+ WSAConnect(sock->fd, &addr->type.sa, addr->length, NULL, NULL, NULL, NULL);
+ cdev->result = ISC_R_SUCCESS;
+ isc_task_send(task, (isc_event_t **)&cdev);
+ }
+ CONSISTENT(sock);
+ UNLOCK(&sock->lock);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_socket_getpeername(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ isc_result_t result;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(addressp != NULL);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ if (sock->connected) {
+ *addressp = sock->address;
+ result = ISC_R_SUCCESS;
+ } else {
+ result = ISC_R_NOTCONNECTED;
+ }
+
+ UNLOCK(&sock->lock);
+
+ return (result);
+}
+
+isc_result_t
+isc_socket_getsockname(isc_socket_t *sock, isc_sockaddr_t *addressp) {
+ ISC_SOCKADDR_LEN_T len;
+ isc_result_t result;
+ char strbuf[ISC_STRERRORSIZE];
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(addressp != NULL);
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ if (!sock->bound) {
+ result = ISC_R_NOTBOUND;
+ goto out;
+ }
+
+ result = ISC_R_SUCCESS;
+
+ len = sizeof(addressp->type);
+ if (getsockname(sock->fd, &addressp->type.sa, (void *)&len) < 0) {
+ isc__strerror(WSAGetLastError(), strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__, "getsockname: %s",
+ strbuf);
+ result = ISC_R_UNEXPECTED;
+ goto out;
+ }
+ addressp->length = (unsigned int)len;
+
+ out:
+ UNLOCK(&sock->lock);
+
+ return (result);
+}
+
+/*
+ * 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) {
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ /*
+ * Quick exit if there is nothing to do. Don't even bother locking
+ * in this case.
+ */
+ if (how == 0)
+ return;
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return;
+ }
+
+ /*
+ * All of these do the same thing, more or less.
+ * Each will:
+ * o If the internal event is marked as "posted" try to
+ * remove it from the task's queue. If this fails, mark it
+ * as canceled instead, and let the task clean it up later.
+ * o For each I/O request for that task of that type, post
+ * its done event with status of "ISC_R_CANCELED".
+ * o Reset any state needed.
+ */
+
+ if ((how & ISC_SOCKCANCEL_RECV) == ISC_SOCKCANCEL_RECV) {
+ isc_socketevent_t *dev;
+ isc_socketevent_t *next;
+ isc_task_t *current_task;
+
+ dev = ISC_LIST_HEAD(sock->recv_list);
+ while (dev != NULL) {
+ current_task = dev->ev_sender;
+ next = ISC_LIST_NEXT(dev, ev_link);
+ if ((task == NULL) || (task == current_task)) {
+ dev->result = ISC_R_CANCELED;
+ send_recvdone_event(sock, &dev);
+ }
+ dev = next;
+ }
+ }
+ how &= ~ISC_SOCKCANCEL_RECV;
+
+ if ((how & ISC_SOCKCANCEL_SEND) == ISC_SOCKCANCEL_SEND) {
+ isc_socketevent_t *dev;
+ isc_socketevent_t *next;
+ isc_task_t *current_task;
+
+ dev = ISC_LIST_HEAD(sock->send_list);
+
+ while (dev != NULL) {
+ current_task = dev->ev_sender;
+ next = ISC_LIST_NEXT(dev, ev_link);
+ if ((task == NULL) || (task == current_task)) {
+ dev->result = ISC_R_CANCELED;
+ send_senddone_event(sock, &dev);
+ }
+ dev = next;
+ }
+ }
+ how &= ~ISC_SOCKCANCEL_SEND;
+
+ if (((how & ISC_SOCKCANCEL_ACCEPT) == ISC_SOCKCANCEL_ACCEPT)
+ && !ISC_LIST_EMPTY(sock->accept_list)) {
+ isc_socket_newconnev_t *dev;
+ isc_socket_newconnev_t *next;
+ isc_task_t *current_task;
+
+ dev = ISC_LIST_HEAD(sock->accept_list);
+ while (dev != NULL) {
+ current_task = dev->ev_sender;
+ next = ISC_LIST_NEXT(dev, ev_link);
+
+ if ((task == NULL) || (task == current_task)) {
+
+ dev->newsocket->references--;
+ closesocket(dev->newsocket->fd);
+ dev->newsocket->fd = INVALID_SOCKET;
+ free_socket(&dev->newsocket, __LINE__);
+
+ dev->result = ISC_R_CANCELED;
+ send_acceptdone_event(sock, &dev);
+ }
+
+ dev = next;
+ }
+ }
+ how &= ~ISC_SOCKCANCEL_ACCEPT;
+
+ /*
+ * Connecting is not a list.
+ */
+ if (((how & ISC_SOCKCANCEL_CONNECT) == ISC_SOCKCANCEL_CONNECT)
+ && sock->connect_ev != NULL) {
+ isc_socket_connev_t *dev;
+ isc_task_t *current_task;
+
+ INSIST(sock->pending_connect);
+
+ dev = sock->connect_ev;
+ current_task = dev->ev_sender;
+
+ if ((task == NULL) || (task == current_task)) {
+ closesocket(sock->fd);
+ sock->fd = INVALID_SOCKET;
+ _set_state(sock, SOCK_CLOSED);
+
+ sock->connect_ev = NULL;
+ dev->result = ISC_R_CANCELED;
+ send_connectdone_event(sock, &dev);
+ }
+ }
+ how &= ~ISC_SOCKCANCEL_CONNECT;
+
+ maybe_free_socket(&sock, __LINE__);
+}
+
+isc_sockettype_t
+isc_socket_gettype(isc_socket_t *sock) {
+ isc_sockettype_t type;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_R_CONNREFUSED);
+ }
+
+ type = sock->type;
+ UNLOCK(&sock->lock);
+ return (type);
+}
+
+isc_boolean_t
+isc_socket_isbound(isc_socket_t *sock) {
+ isc_boolean_t val;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ CONSISTENT(sock);
+
+ /*
+ * make sure that the socket's not closed
+ */
+ if (sock->fd == INVALID_SOCKET) {
+ UNLOCK(&sock->lock);
+ return (ISC_FALSE);
+ }
+
+ val = ((sock->bound) ? ISC_TRUE : ISC_FALSE);
+ UNLOCK(&sock->lock);
+
+ return (val);
+}
+
+void
+isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
+#if defined(IPV6_V6ONLY)
+ int onoff = yes ? 1 : 0;
+#else
+ UNUSED(yes);
+#endif
+
+ REQUIRE(VALID_SOCKET(sock));
+
+#ifdef IPV6_V6ONLY
+ if (sock->pf == AF_INET6) {
+ (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (void *)&onoff, sizeof(onoff));
+ }
+#endif
+}
+
+void
+isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active) {
+ UNUSED(addr);
+ UNUSED(active);
+}
+
+isc_result_t
+isc_socket_permunix(isc_sockaddr_t *addr, isc_uint32_t perm,
+ isc_uint32_t owner, isc_uint32_t group)
+{
+ UNUSED(addr);
+ UNUSED(perm);
+ UNUSED(owner);
+ UNUSED(group);
+ return (ISC_R_NOTIMPLEMENTED);
+}
+
+void
+isc_socket_setname(isc_socket_t *socket, const char *name, void *tag) {
+
+ /*
+ * Name 'socket'.
+ */
+
+ REQUIRE(VALID_SOCKET(socket));
+
+ LOCK(&socket->lock);
+ memset(socket->name, 0, sizeof(socket->name));
+ strncpy(socket->name, name, sizeof(socket->name) - 1);
+ socket->tag = tag;
+ UNLOCK(&socket->lock);
+}
+
+const char *
+isc_socket_getname(isc_socket_t *socket) {
+ return (socket->name);
+}
+
+void *
+isc_socket_gettag(isc_socket_t *socket) {
+ return (socket->tag);
+}
+
+void
+isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
+ UNUSED(manager);
+ UNUSED(reserved);
+}
diff --git a/lib/isc/win32/stdio.c b/lib/isc/win32/stdio.c
new file mode 100644
index 0000000..427a8e1
--- /dev/null
+++ b/lib/isc/win32/stdio.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2004, 2007 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: stdio.c,v 1.6 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <io.h>
+#include <errno.h>
+
+#include <isc/stdio.h>
+
+#include "errno2result.h"
+
+isc_result_t
+isc_stdio_open(const char *filename, const char *mode, FILE **fp) {
+ FILE *f;
+
+ f = fopen(filename, mode);
+ if (f == NULL)
+ return (isc__errno2result(errno));
+ *fp = f;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_stdio_close(FILE *f) {
+ int r;
+
+ r = fclose(f);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_seek(FILE *f, long offset, int whence) {
+ int r;
+
+ r = fseek(f, offset, whence);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_read(void *ptr, size_t size, size_t nmemb, FILE *f, size_t *nret) {
+ isc_result_t result = ISC_R_SUCCESS;
+ size_t r;
+
+ clearerr(f);
+ r = fread(ptr, size, nmemb, f);
+ if (r != nmemb) {
+ if (feof(f))
+ result = ISC_R_EOF;
+ else
+ result = isc__errno2result(errno);
+ }
+ if (nret != NULL)
+ *nret = r;
+ return (result);
+}
+
+isc_result_t
+isc_stdio_write(const void *ptr, size_t size, size_t nmemb, FILE *f,
+ size_t *nret)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ size_t r;
+
+ clearerr(f);
+ r = fwrite(ptr, size, nmemb, f);
+ if (r != nmemb)
+ result = isc__errno2result(errno);
+ if (nret != NULL)
+ *nret = r;
+ return (result);
+}
+
+isc_result_t
+isc_stdio_flush(FILE *f) {
+ int r;
+
+ r = fflush(f);
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
+isc_result_t
+isc_stdio_sync(FILE *f) {
+ int r;
+
+ r = _commit(_fileno(f));
+ if (r == 0)
+ return (ISC_R_SUCCESS);
+ else
+ return (isc__errno2result(errno));
+}
+
diff --git a/lib/isc/win32/stdtime.c b/lib/isc/win32/stdtime.c
new file mode 100644
index 0000000..574297e
--- /dev/null
+++ b/lib/isc/win32/stdtime.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: stdtime.c,v 1.12 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <time.h>
+
+#include <isc/assertions.h>
+#include <isc/stdtime.h>
+#include <isc/util.h>
+
+void
+isc_stdtime_get(isc_stdtime_t *t) {
+ /*
+ * Set 't' to the number of seconds past 00:00:00 UTC, January 1, 1970.
+ */
+
+ REQUIRE(t != NULL);
+
+ (void)time(t);
+}
diff --git a/lib/isc/win32/strerror.c b/lib/isc/win32/strerror.c
new file mode 100644
index 0000000..4174332
--- /dev/null
+++ b/lib/isc/win32/strerror.c
@@ -0,0 +1,459 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002 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: strerror.c,v 1.8 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <winsock2.h>
+
+#include <isc/mutex.h>
+#include <isc/once.h>
+#include <isc/print.h>
+#include <isc/strerror.h>
+#include <isc/util.h>
+
+/*
+ * Forward declarations
+ */
+
+char *
+FormatError(int error);
+
+char *
+GetWSAErrorMessage(int errval);
+
+char *
+NTstrerror(int err, BOOL *bfreebuf);
+
+/*
+ * We need to do this this way for profiled locks.
+ */
+
+static isc_mutex_t isc_strerror_lock;
+static void init_lock(void) {
+ RUNTIME_CHECK(isc_mutex_init(&isc_strerror_lock) == ISC_R_SUCCESS);
+}
+
+/*
+ * This routine needs to free up any buffer allocated by FormatMessage
+ * if that routine gets used.
+ */
+
+void
+isc__strerror(int num, char *buf, size_t size) {
+ char *msg;
+ BOOL freebuf;
+ unsigned int unum = num;
+ static isc_once_t once = ISC_ONCE_INIT;
+
+ REQUIRE(buf != NULL);
+
+ RUNTIME_CHECK(isc_once_do(&once, init_lock) == ISC_R_SUCCESS);
+
+ LOCK(&isc_strerror_lock);
+ freebuf = FALSE;
+ msg = NTstrerror(num, &freebuf);
+ if (msg != NULL)
+ snprintf(buf, size, "%s", msg);
+ else
+ snprintf(buf, size, "Unknown error: %u", unum);
+ if(freebuf && msg != NULL) {
+ LocalFree(msg);
+ }
+ UNLOCK(&isc_strerror_lock);
+}
+
+/*
+ * Note this will cause a memory leak unless the memory allocated here
+ * is freed by calling LocalFree. isc__strerror does this before unlocking.
+ * This only gets called if there is a system type of error and will likely
+ * be an unusual event.
+ */
+char *
+FormatError(int error) {
+ LPVOID lpMsgBuf = NULL;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ error,
+ /* Default language */
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL);
+
+ return (lpMsgBuf);
+}
+
+/*
+ * This routine checks the error value and calls the WSA Windows Sockets
+ * Error message function GetWSAErrorMessage below if it's within that range
+ * since those messages are not available in the system error messages.
+ */
+char *
+NTstrerror(int err, BOOL *bfreebuf) {
+ char *retmsg = NULL;
+
+ /* Copy the error value first in case of other errors */
+ DWORD errval = err;
+
+ *bfreebuf = FALSE;
+
+ /* Get the Winsock2 error messages */
+ if (errval >= WSABASEERR && errval <= (WSABASEERR + 1015)) {
+ retmsg = GetWSAErrorMessage(errval);
+ if (retmsg != NULL)
+ return (retmsg);
+ }
+ /*
+ * If it's not one of the standard Unix error codes,
+ * try a system error message
+ */
+ if (errval > (DWORD) _sys_nerr) {
+ *bfreebuf = TRUE;
+ return (FormatError(errval));
+ } else {
+ return (strerror(errval));
+ }
+}
+
+/*
+ * This is a replacement for perror
+ */
+void __cdecl
+NTperror(char *errmsg) {
+ /* Copy the error value first in case of other errors */
+ int errval = errno;
+ BOOL bfreebuf = FALSE;
+ char *msg;
+
+ msg = NTstrerror(errval, &bfreebuf);
+ fprintf(stderr, "%s: %s\n", errmsg, msg);
+ if(bfreebuf == TRUE) {
+ LocalFree(msg);
+ }
+
+}
+
+/*
+ * Return the error string related to Winsock2 errors.
+ * This function is necessary since FormatMessage knows nothing about them
+ * and there is no function to get them.
+ */
+char *
+GetWSAErrorMessage(int errval) {
+ char *msg;
+
+ switch (errval) {
+
+ case WSAEINTR:
+ msg = "Interrupted system call";
+ break;
+
+ case WSAEBADF:
+ msg = "Bad file number";
+ break;
+
+ case WSAEACCES:
+ msg = "Permission denied";
+ break;
+
+ case WSAEFAULT:
+ msg = "Bad address";
+ break;
+
+ case WSAEINVAL:
+ msg = "Invalid argument";
+ break;
+
+ case WSAEMFILE:
+ msg = "Too many open sockets";
+ break;
+
+ case WSAEWOULDBLOCK:
+ msg = "Operation would block";
+ break;
+
+ case WSAEINPROGRESS:
+ msg = "Operation now in progress";
+ break;
+
+ case WSAEALREADY:
+ msg = "Operation already in progress";
+ break;
+
+ case WSAENOTSOCK:
+ msg = "Socket operation on non-socket";
+ break;
+
+ case WSAEDESTADDRREQ:
+ msg = "Destination address required";
+ break;
+
+ case WSAEMSGSIZE:
+ msg = "Message too long";
+ break;
+
+ case WSAEPROTOTYPE:
+ msg = "Protocol wrong type for socket";
+ break;
+
+ case WSAENOPROTOOPT:
+ msg = "Bad protocol option";
+ break;
+
+ case WSAEPROTONOSUPPORT:
+ msg = "Protocol not supported";
+ break;
+
+ case WSAESOCKTNOSUPPORT:
+ msg = "Socket type not supported";
+ break;
+
+ case WSAEOPNOTSUPP:
+ msg = "Operation not supported on socket";
+ break;
+
+ case WSAEPFNOSUPPORT:
+ msg = "Protocol family not supported";
+ break;
+
+ case WSAEAFNOSUPPORT:
+ msg = "Address family not supported";
+ break;
+
+ case WSAEADDRINUSE:
+ msg = "Address already in use";
+ break;
+
+ case WSAEADDRNOTAVAIL:
+ msg = "Can't assign requested address";
+ break;
+
+ case WSAENETDOWN:
+ msg = "Network is down";
+ break;
+
+ case WSAENETUNREACH:
+ msg = "Network is unreachable";
+ break;
+
+ case WSAENETRESET:
+ msg = "Net connection reset";
+ break;
+
+ case WSAECONNABORTED:
+ msg = "Software caused connection abort";
+ break;
+
+ case WSAECONNRESET:
+ msg = "Connection reset by peer";
+ break;
+
+ case WSAENOBUFS:
+ msg = "No buffer space available";
+ break;
+
+ case WSAEISCONN:
+ msg = "Socket is already connected";
+ break;
+
+ case WSAENOTCONN:
+ msg = "Socket is not connected";
+ break;
+
+ case WSAESHUTDOWN:
+ msg = "Can't send after socket shutdown";
+ break;
+
+ case WSAETOOMANYREFS:
+ msg = "Too many references: can't splice";
+ break;
+
+ case WSAETIMEDOUT:
+ msg = "Connection timed out";
+ break;
+
+ case WSAECONNREFUSED:
+ msg = "Connection refused";
+ break;
+
+ case WSAELOOP:
+ msg = "Too many levels of symbolic links";
+ break;
+
+ case WSAENAMETOOLONG:
+ msg = "File name too long";
+ break;
+
+ case WSAEHOSTDOWN:
+ msg = "Host is down";
+ break;
+
+ case WSAEHOSTUNREACH:
+ msg = "No route to host";
+ break;
+
+ case WSAENOTEMPTY:
+ msg = "Directory not empty";
+ break;
+
+ case WSAEPROCLIM:
+ msg = "Too many processes";
+ break;
+
+ case WSAEUSERS:
+ msg = "Too many users";
+ break;
+
+ case WSAEDQUOT:
+ msg = "Disc quota exceeded";
+ break;
+
+ case WSAESTALE:
+ msg = "Stale NFS file handle";
+ break;
+
+ case WSAEREMOTE:
+ msg = "Too many levels of remote in path";
+ break;
+
+ case WSASYSNOTREADY:
+ msg = "Network system is unavailable";
+ break;
+
+ case WSAVERNOTSUPPORTED:
+ msg = "Winsock version out of range";
+ break;
+
+ case WSANOTINITIALISED:
+ msg = "WSAStartup not yet called";
+ break;
+
+ case WSAEDISCON:
+ msg = "Graceful shutdown in progress";
+ break;
+/*
+ case WSAHOST_NOT_FOUND:
+ msg = "Host not found";
+ break;
+
+ case WSANO_DATA:
+ msg = "No host data of that type was found";
+ break;
+*/
+ default:
+ msg = NULL;
+ break;
+ }
+ return (msg);
+}
+
+/*
+ * These error messages are more informative about CryptAPI Errors than the
+ * standard error messages
+ */
+
+char *
+GetCryptErrorMessage(int errval) {
+ char *msg;
+
+ switch (errval) {
+
+ case NTE_BAD_FLAGS:
+ msg = "The dwFlags parameter has an illegal value.";
+ break;
+ case NTE_BAD_KEYSET:
+ msg = "The Registry entry for the key container "
+ "could not be opened and may not exist.";
+ break;
+ case NTE_BAD_KEYSET_PARAM:
+ msg = "The pszContainer or pszProvider parameter "
+ "is set to an illegal value.";
+ break;
+ case NTE_BAD_PROV_TYPE:
+ msg = "The value of the dwProvType parameter is out "
+ "of range. All provider types must be from "
+ "1 to 999, inclusive.";
+ break;
+ case NTE_BAD_SIGNATURE:
+ msg = "The provider DLL signature did not verify "
+ "correctly. Either the DLL or the digital "
+ "signature has been tampered with.";
+ break;
+ case NTE_EXISTS:
+ msg = "The dwFlags parameter is CRYPT_NEWKEYSET, but the key"
+ " container already exists.";
+ break;
+ case NTE_KEYSET_ENTRY_BAD:
+ msg = "The Registry entry for the pszContainer key container "
+ "was found (in the HKEY_CURRENT_USER window), but is "
+ "corrupt. See the section System Administration for "
+ " etails about CryptoAPI's Registry usage.";
+ break;
+ case NTE_KEYSET_NOT_DEF:
+ msg = "No Registry entry exists in the HKEY_CURRENT_USER "
+ "window for the key container specified by "
+ "pszContainer.";
+ break;
+ case NTE_NO_MEMORY:
+ msg = "The CSP ran out of memory during the operation.";
+ break;
+ case NTE_PROV_DLL_NOT_FOUND:
+ msg = "The provider DLL file does not exist or is not on the "
+ "current path.";
+ break;
+ case NTE_PROV_TYPE_ENTRY_BAD:
+ msg = "The Registry entry for the provider type specified by "
+ "dwProvType is corrupt. This error may relate to "
+ "either the user default CSP list or the machine "
+ "default CSP list. See the section System "
+ "Administration for details about CryptoAPI's "
+ "Registry usage.";
+ break;
+ case NTE_PROV_TYPE_NO_MATCH:
+ msg = "The provider type specified by dwProvType does not "
+ "match the provider type found in the Registry. Note "
+ "that this error can only occur when pszProvider "
+ "specifies an actual CSP name.";
+ break;
+ case NTE_PROV_TYPE_NOT_DEF:
+ msg = "No Registry entry exists for the provider type "
+ "specified by dwProvType.";
+ break;
+ case NTE_PROVIDER_DLL_FAIL:
+ msg = "The provider DLL file could not be loaded, and "
+ "may not exist. If it exists, then the file is "
+ "not a valid DLL.";
+ break;
+ case NTE_SIGNATURE_FILE_BAD:
+ msg = "An error occurred while loading the DLL file image, "
+ "prior to verifying its signature.";
+ break;
+
+ default:
+ msg = NULL;
+ break;
+ }
+ return msg;
+}
+
diff --git a/lib/isc/win32/syslog.c b/lib/isc/win32/syslog.c
new file mode 100644
index 0000000..375784f
--- /dev/null
+++ b/lib/isc/win32/syslog.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2004, 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: syslog.c,v 1.10 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+
+#include <isc/bindevt.h>
+#include <isc/result.h>
+#include <isc/syslog.h>
+#include <isc/util.h>
+
+static HANDLE hAppLog = NULL;
+static FILE *log_stream;
+static int debug_level = 0;
+
+static struct dsn_c_pvt_sfnt {
+ int val;
+ const char *strval;
+} facilities[] = {
+ { LOG_KERN, "kern" },
+ { LOG_USER, "user" },
+ { LOG_MAIL, "mail" },
+ { LOG_DAEMON, "daemon" },
+ { LOG_AUTH, "auth" },
+ { LOG_SYSLOG, "syslog" },
+ { LOG_LPR, "lpr" },
+#ifdef LOG_NEWS
+ { LOG_NEWS, "news" },
+#endif
+#ifdef LOG_UUCP
+ { LOG_UUCP, "uucp" },
+#endif
+#ifdef LOG_CRON
+ { LOG_CRON, "cron" },
+#endif
+#ifdef LOG_AUTHPRIV
+ { LOG_AUTHPRIV, "authpriv" },
+#endif
+#ifdef LOG_FTP
+ { LOG_FTP, "ftp" },
+#endif
+ { LOG_LOCAL0, "local0"},
+ { LOG_LOCAL1, "local1"},
+ { LOG_LOCAL2, "local2"},
+ { LOG_LOCAL3, "local3"},
+ { LOG_LOCAL4, "local4"},
+ { LOG_LOCAL5, "local5"},
+ { LOG_LOCAL6, "local6"},
+ { LOG_LOCAL7, "local7"},
+ { 0, NULL }
+};
+
+isc_result_t
+isc_syslog_facilityfromstring(const char *str, int *facilityp) {
+ int i;
+
+ REQUIRE(str != NULL);
+ REQUIRE(facilityp != NULL);
+
+ for (i = 0; facilities[i].strval != NULL; i++) {
+ if (strcasecmp(facilities[i].strval, str) == 0) {
+ *facilityp = facilities[i].val;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+/*
+ * Log to the NT Event Log
+ */
+void
+syslog(int level, const char *fmt, ...) {
+ va_list ap;
+ char buf[1024];
+ char *str[1];
+
+ str[0] = buf;
+
+ va_start(ap, fmt);
+ vsprintf(buf, fmt, ap);
+ va_end(ap);
+
+ /* Make sure that the channel is open to write the event */
+ if (hAppLog != NULL) {
+ switch (level) {
+ case LOG_INFO:
+ case LOG_NOTICE:
+ case LOG_DEBUG:
+ ReportEvent(hAppLog, EVENTLOG_INFORMATION_TYPE, 0,
+ BIND_INFO_MSG, NULL, 1, 0, str, NULL);
+ break;
+ case LOG_WARNING:
+ ReportEvent(hAppLog, EVENTLOG_WARNING_TYPE, 0,
+ BIND_WARN_MSG, NULL, 1, 0, str, NULL);
+ break;
+ default:
+ ReportEvent(hAppLog, EVENTLOG_ERROR_TYPE, 0,
+ BIND_ERR_MSG, NULL, 1, 0, str, NULL);
+ break;
+ }
+ }
+}
+
+/*
+ * Initialize event logging
+ */
+void
+openlog(const char *name, int flags, ...) {
+ /* Get a handle to the Application event log */
+ hAppLog = RegisterEventSource(NULL, name);
+}
+
+/*
+ * Close the Handle to the application Event Log
+ * We don't care whether or not we succeeded so ignore return values
+ * In fact if we failed then we would have nowhere to put the message
+ */
+void
+closelog() {
+ DeregisterEventSource(hAppLog);
+}
+
+/*
+ * Keep event logging synced with the current debug level
+ */
+void
+ModifyLogLevel(int level) {
+ debug_level = level;
+}
+
+/*
+ * Initialize logging for the port section of libbind.
+ * Piggyback onto stream given.
+ */
+void
+InitNTLogging(FILE *stream, int debug) {
+ log_stream = stream;
+ ModifyLogLevel(debug);
+}
+/*
+ * This function is for reporting errors to the application
+ * event log in case the regular syslog is not available
+ * mainly during startup. It should not be used under normal
+ * circumstances.
+ */
+void
+NTReportError(const char *name, const char *str) {
+ HANDLE hNTAppLog = NULL;
+ const char *buf[1];
+
+ buf[0] = str;
+
+ hNTAppLog = RegisterEventSource(NULL, name);
+
+ ReportEvent(hNTAppLog, EVENTLOG_ERROR_TYPE, 0,
+ BIND_ERR_MSG, NULL, 1, 0, buf, NULL);
+
+ DeregisterEventSource(hNTAppLog);
+}
diff --git a/lib/isc/win32/syslog.h b/lib/isc/win32/syslog.h
new file mode 100644
index 0000000..fd4b3a6
--- /dev/null
+++ b/lib/isc/win32/syslog.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2001, 2002 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: syslog.h,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#ifndef _SYSLOG_H
+#define _SYSLOG_H
+
+#include <stdio.h>
+
+/* Constant definitions for openlog() */
+#define LOG_PID 1
+#define LOG_CONS 2
+/* NT event log does not support facility level */
+#define LOG_KERN 0
+#define LOG_USER 0
+#define LOG_MAIL 0
+#define LOG_DAEMON 0
+#define LOG_AUTH 0
+#define LOG_SYSLOG 0
+#define LOG_LPR 0
+#define LOG_LOCAL0 0
+#define LOG_LOCAL1 0
+#define LOG_LOCAL2 0
+#define LOG_LOCAL3 0
+#define LOG_LOCAL4 0
+#define LOG_LOCAL5 0
+#define LOG_LOCAL6 0
+#define LOG_LOCAL7 0
+
+#define LOG_EMERG 0 /* system is unusable */
+#define LOG_ALERT 1 /* action must be taken immediately */
+#define LOG_CRIT 2 /* critical conditions */
+#define LOG_ERR 3 /* error conditions */
+#define LOG_WARNING 4 /* warning conditions */
+#define LOG_NOTICE 5 /* normal but signification condition */
+#define LOG_INFO 6 /* informational */
+#define LOG_DEBUG 7 /* debug-level messages */
+
+void
+syslog(int level, const char *fmt, ...);
+
+void
+openlog(const char *, int, ...);
+
+void
+closelog(void);
+
+void
+ModifyLogLevel(int level);
+
+void
+InitNTLogging(FILE *, int);
+
+void
+NTReportError(const char *, const char *);
+/*
+ * Include the event codes required for logging.
+ */
+#include <isc/bindevt.h>
+
+#endif
diff --git a/lib/isc/win32/thread.c b/lib/isc/win32/thread.c
new file mode 100644
index 0000000..be955ea
--- /dev/null
+++ b/lib/isc/win32/thread.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: thread.c,v 1.24 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <config.h>
+
+#include <process.h>
+
+#include <isc/thread.h>
+
+isc_result_t
+isc_thread_create(isc_threadfunc_t start, isc_threadarg_t arg,
+ isc_thread_t *threadp)
+{
+ isc_thread_t thread;
+ unsigned int id;
+
+ thread = (isc_thread_t)_beginthreadex(NULL, 0, start, arg, 0, &id);
+ if (thread == NULL) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+
+ *threadp = thread;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_thread_join(isc_thread_t thread, isc_threadresult_t *rp) {
+ DWORD result;
+
+ result = WaitForSingleObject(thread, INFINITE);
+ if (result != WAIT_OBJECT_0) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+ if (rp != NULL && !GetExitCodeThread(thread, rp)) {
+ /* XXX */
+ return (ISC_R_UNEXPECTED);
+ }
+ (void)CloseHandle(thread);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_thread_setconcurrency(unsigned int level) {
+ /*
+ * This is unnecessary on Win32 systems, but is here so that the
+ * call exists
+ */
+}
+
+void *
+isc_thread_key_getspecific(isc_thread_key_t key) {
+ return(TlsGetValue(key));
+}
+
+int
+isc_thread_key_setspecific(isc_thread_key_t key, void *value) {
+ return (TlsSetValue(key, value) ? 0 : GetLastError());
+}
+
+int
+isc_thread_key_create(isc_thread_key_t *key, void (*func)(void *)) {
+ *key = TlsAlloc();
+
+ return ((*key != -1) ? 0 : GetLastError());
+}
+
+int
+isc_thread_key_delete(isc_thread_key_t key) {
+ return (TlsFree(key) ? 0 : GetLastError());
+}
diff --git a/lib/isc/win32/time.c b/lib/isc/win32/time.c
new file mode 100644
index 0000000..aebf73d
--- /dev/null
+++ b/lib/isc/win32/time.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2004, 2006-2008 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
+ * 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: time.c,v 1.48 2008/09/08 23:47:10 tbox Exp $ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <windows.h>
+
+#include <isc/assertions.h>
+#include <isc/time.h>
+#include <isc/util.h>
+
+/*
+ * struct FILETIME uses "100-nanoseconds intervals".
+ * NS / S = 1000000000 (10^9).
+ * While it is reasonably obvious that this makes the needed
+ * conversion factor 10^7, it is coded this way for additional clarity.
+ */
+#define NS_PER_S 1000000000
+#define NS_INTERVAL 100
+#define INTERVALS_PER_S (NS_PER_S / NS_INTERVAL)
+#define UINT64_MAX _UI64_MAX
+
+/***
+ *** Absolute Times
+ ***/
+
+static isc_time_t epoch = { { 0, 0 } };
+LIBISC_EXTERNAL_DATA isc_time_t *isc_time_epoch = &epoch;
+
+/***
+ *** Intervals
+ ***/
+
+static isc_interval_t zero_interval = { 0 };
+LIBISC_EXTERNAL_DATA isc_interval_t *isc_interval_zero = &zero_interval;
+
+void
+isc_interval_set(isc_interval_t *i, unsigned int seconds,
+ unsigned int nanoseconds)
+{
+ REQUIRE(i != NULL);
+ REQUIRE(nanoseconds < NS_PER_S);
+
+ /*
+ * This rounds nanoseconds up not down.
+ */
+ i->interval = (LONGLONG)seconds * INTERVALS_PER_S
+ + (nanoseconds + NS_INTERVAL - 1) / NS_INTERVAL;
+}
+
+isc_boolean_t
+isc_interval_iszero(const isc_interval_t *i) {
+ REQUIRE(i != NULL);
+ if (i->interval == 0)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+void
+isc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
+ SYSTEMTIME epoch = { 1970, 1, 4, 1, 0, 0, 0, 0 };
+ FILETIME temp;
+ ULARGE_INTEGER i1;
+
+ REQUIRE(t != NULL);
+ REQUIRE(nanoseconds < NS_PER_S);
+
+ SystemTimeToFileTime(&epoch, &temp);
+
+ i1.LowPart = t->absolute.dwLowDateTime;
+ i1.HighPart = t->absolute.dwHighDateTime;
+
+ i1.QuadPart += (unsigned __int64)nanoseconds/100;
+ i1.QuadPart += (unsigned __int64)seconds*10000000;
+
+ t->absolute.dwLowDateTime = i1.LowPart;
+ t->absolute.dwHighDateTime = i1.HighPart;
+}
+
+void
+isc_time_settoepoch(isc_time_t *t) {
+ REQUIRE(t != NULL);
+
+ t->absolute.dwLowDateTime = 0;
+ t->absolute.dwHighDateTime = 0;
+}
+
+isc_boolean_t
+isc_time_isepoch(const isc_time_t *t) {
+ REQUIRE(t != NULL);
+
+ if (t->absolute.dwLowDateTime == 0 &&
+ t->absolute.dwHighDateTime == 0)
+ return (ISC_TRUE);
+
+ return (ISC_FALSE);
+}
+
+isc_result_t
+isc_time_now(isc_time_t *t) {
+ REQUIRE(t != NULL);
+
+ GetSystemTimeAsFileTime(&t->absolute);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
+ ULARGE_INTEGER i1;
+
+ REQUIRE(t != NULL);
+ REQUIRE(i != NULL);
+
+ GetSystemTimeAsFileTime(&t->absolute);
+
+ i1.LowPart = t->absolute.dwLowDateTime;
+ i1.HighPart = t->absolute.dwHighDateTime;
+
+ if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval)
+ return (ISC_R_RANGE);
+
+ i1.QuadPart += i->interval;
+
+ t->absolute.dwLowDateTime = i1.LowPart;
+ t->absolute.dwHighDateTime = i1.HighPart;
+
+ return (ISC_R_SUCCESS);
+}
+
+int
+isc_time_compare(const isc_time_t *t1, const isc_time_t *t2) {
+ REQUIRE(t1 != NULL && t2 != NULL);
+
+ return ((int)CompareFileTime(&t1->absolute, &t2->absolute));
+}
+
+isc_result_t
+isc_time_add(const isc_time_t *t, const isc_interval_t *i, isc_time_t *result)
+{
+ ULARGE_INTEGER i1;
+
+ REQUIRE(t != NULL && i != NULL && result != NULL);
+
+ i1.LowPart = t->absolute.dwLowDateTime;
+ i1.HighPart = t->absolute.dwHighDateTime;
+
+ if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval)
+ return (ISC_R_RANGE);
+
+ i1.QuadPart += i->interval;
+
+ result->absolute.dwLowDateTime = i1.LowPart;
+ result->absolute.dwHighDateTime = i1.HighPart;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_time_subtract(const isc_time_t *t, const isc_interval_t *i,
+ isc_time_t *result) {
+ ULARGE_INTEGER i1;
+
+ REQUIRE(t != NULL && i != NULL && result != NULL);
+
+ i1.LowPart = t->absolute.dwLowDateTime;
+ i1.HighPart = t->absolute.dwHighDateTime;
+
+ if (i1.QuadPart < (unsigned __int64) i->interval)
+ return (ISC_R_RANGE);
+
+ i1.QuadPart -= i->interval;
+
+ result->absolute.dwLowDateTime = i1.LowPart;
+ result->absolute.dwHighDateTime = i1.HighPart;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_uint64_t
+isc_time_microdiff(const isc_time_t *t1, const isc_time_t *t2) {
+ ULARGE_INTEGER i1, i2;
+ LONGLONG i3;
+
+ REQUIRE(t1 != NULL && t2 != NULL);
+
+ i1.LowPart = t1->absolute.dwLowDateTime;
+ i1.HighPart = t1->absolute.dwHighDateTime;
+ i2.LowPart = t2->absolute.dwLowDateTime;
+ i2.HighPart = t2->absolute.dwHighDateTime;
+
+ if (i1.QuadPart <= i2.QuadPart)
+ return (0);
+
+ /*
+ * Convert to microseconds.
+ */
+ i3 = (i1.QuadPart - i2.QuadPart) / 10;
+
+ return (i3);
+}
+
+isc_uint32_t
+isc_time_seconds(const isc_time_t *t) {
+ SYSTEMTIME st;
+
+ /*
+ * Convert the time to a SYSTEMTIME structure and the grab the
+ * milliseconds
+ */
+ FileTimeToSystemTime(&t->absolute, &st);
+
+ return ((isc_uint32_t)(st.wMilliseconds / 1000));
+}
+
+isc_uint32_t
+isc_time_nanoseconds(const isc_time_t *t) {
+ SYSTEMTIME st;
+
+ /*
+ * Convert the time to a SYSTEMTIME structure and the grab the
+ * milliseconds
+ */
+ FileTimeToSystemTime(&t->absolute, &st);
+
+ return ((isc_uint32_t)(st.wMilliseconds * 1000000));
+}
+
+void
+isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+ FILETIME localft;
+ SYSTEMTIME st;
+ char DateBuf[50];
+ char TimeBuf[50];
+
+ static const char badtime[] = "99-Bad-9999 99:99:99.999";
+
+ REQUIRE(len > 0);
+ if (FileTimeToLocalFileTime(&t->absolute, &localft) &&
+ FileTimeToSystemTime(&localft, &st)) {
+ GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, "dd-MMM-yyyy",
+ DateBuf, 50);
+ GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOTIMEMARKER|
+ TIME_FORCE24HOURFORMAT, &st, NULL, TimeBuf, 50);
+
+ snprintf(buf, len, "%s %s.%03u", DateBuf, TimeBuf,
+ st.wMilliseconds);
+
+ } else
+ snprintf(buf, len, badtime);
+}
+
+void
+isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) {
+ SYSTEMTIME st;
+ char DateBuf[50];
+ char TimeBuf[50];
+
+ REQUIRE(len > 0);
+ if (FileTimeToSystemTime(&t->absolute, &st)) {
+ GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, "ddd',', dd-MMM-yyyy",
+ DateBuf, 50);
+ GetTimeFormat(LOCALE_USER_DEFAULT,
+ TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT,
+ &st, "hh':'mm':'ss", TimeBuf, 50);
+
+ snprintf(buf, len, "%s %s GMT", DateBuf, TimeBuf);
+ } else {
+ buf[0] = 0;
+ }
+}
diff --git a/lib/isc/win32/unistd.h b/lib/isc/win32/unistd.h
new file mode 100644
index 0000000..889f0b8
--- /dev/null
+++ b/lib/isc/win32/unistd.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2004, 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
+ * 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: unistd.h,v 1.8 2008/01/23 03:22:43 tbox Exp $ */
+
+/* None of these are defined in NT, so define them for our use */
+#define O_NONBLOCK 1
+#define PORT_NONBLOCK O_NONBLOCK
+
+/*
+ * fcntl() commands
+ */
+#define F_SETFL 0
+#define F_GETFL 1
+#define F_SETFD 2
+#define F_GETFD 3
+/*
+ * Enough problems not having full fcntl() without worrying about this!
+ */
+#undef F_DUPFD
+
+int fcntl(int, int, ...);
+
+/*
+ * access() related definitions for winXP
+ */
+#include <io.h>
+
+#ifndef W_OK
+#define W_OK 2
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#endif
+
+#define access _access
+
+#include <process.h>
diff --git a/lib/isc/win32/version.c b/lib/isc/win32/version.c
new file mode 100644
index 0000000..6d5c1fd
--- /dev/null
+++ b/lib/isc/win32/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: version.c,v 1.7 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <versions.h>
+
+#include <isc/version.h>
+
+LIBISC_EXTERNAL_DATA const char isc_version[] = VERSION;
+
+LIBISC_EXTERNAL_DATA const unsigned int isc_libinterface = LIBINTERFACE;
+LIBISC_EXTERNAL_DATA const unsigned int isc_librevision = LIBREVISION;
+LIBISC_EXTERNAL_DATA const unsigned int isc_libage = LIBAGE;
diff --git a/lib/isc/win32/win32os.c b/lib/isc/win32/win32os.c
new file mode 100644
index 0000000..56498d0
--- /dev/null
+++ b/lib/isc/win32/win32os.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: win32os.c,v 1.5 2007/06/19 23:47:19 tbox Exp $ */
+
+#include <windows.h>
+
+#include <isc/win32os.h>
+
+static BOOL bInit = FALSE;
+static OSVERSIONINFOEX osVer;
+
+static void
+initialize_action(void) {
+ BOOL bSuccess;
+
+ if (bInit)
+ return;
+ /*
+ * NOTE: VC++ 6.0 gets this function declaration wrong
+ * so we compensate by casting the argument
+ */
+ osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ bSuccess = GetVersionEx((OSVERSIONINFO *) &osVer);
+
+ /*
+ * Versions of NT before NT4.0 SP6 did not return the
+ * extra info that the EX structure provides and returns
+ * a failure so we need to retry with the old structure.
+ */
+ if(!bSuccess) {
+ osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ bSuccess = GetVersionEx((OSVERSIONINFO *) &osVer);
+ }
+ bInit = TRUE;
+}
+
+unsigned int
+isc_win32os_majorversion(void) {
+ initialize_action();
+ return ((unsigned int)osVer.dwMajorVersion);
+}
+
+unsigned int
+isc_win32os_minorversion(void) {
+ initialize_action();
+ return ((unsigned int)osVer.dwMinorVersion);
+}
+
+unsigned int
+isc_win32os_servicepackmajor(void) {
+ initialize_action();
+ return ((unsigned int)osVer.wServicePackMajor);
+}
+
+unsigned int
+isc_win32os_servicepackminor(void) {
+ initialize_action();
+ return ((unsigned int)osVer.wServicePackMinor);
+}
+
+int
+isc_win32os_versioncheck(unsigned int major, unsigned int minor,
+ unsigned int spmajor, unsigned int spminor) {
+
+ initialize_action();
+
+ if (major < isc_win32os_majorversion())
+ return (1);
+ if (major > isc_win32os_majorversion())
+ return (-1);
+ if (minor < isc_win32os_minorversion())
+ return (1);
+ if (minor > isc_win32os_minorversion())
+ return (-1);
+ if (spmajor < isc_win32os_servicepackmajor())
+ return (1);
+ if (spmajor > isc_win32os_servicepackmajor())
+ return (-1);
+ if (spminor < isc_win32os_servicepackminor())
+ return (1);
+ if (spminor > isc_win32os_servicepackminor())
+ return (-1);
+
+ /* Exact */
+ return (0);
+} \ No newline at end of file
diff --git a/lib/isc/x86_32/Makefile.in b/lib/isc/x86_32/Makefile.in
new file mode 100644
index 0000000..324db07
--- /dev/null
+++ b/lib/isc/x86_32/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = include
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/x86_32/include/Makefile.in b/lib/isc/x86_32/include/Makefile.in
new file mode 100644
index 0000000..f1d8bdd
--- /dev/null
+++ b/lib/isc/x86_32/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/x86_32/include/isc/Makefile.in b/lib/isc/x86_32/include/isc/Makefile.in
new file mode 100644
index 0000000..5f116ca
--- /dev/null
+++ b/lib/isc/x86_32/include/isc/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = atomic.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/x86_32/include/isc/atomic.h b/lib/isc/x86_32/include/isc/atomic.h
new file mode 100644
index 0000000..bf2148c
--- /dev/null
+++ b/lib/isc/x86_32/include/isc/atomic.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2005, 2007, 2008 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: atomic.h,v 1.10 2008/01/24 23:47:00 tbox Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_USEGCCASM
+/*
+ * This routine atomically increments the value stored in 'p' by 'val', and
+ * returns the previous value.
+ */
+static __inline__ isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+ isc_int32_t prev = val;
+
+ __asm__ volatile(
+#ifdef ISC_PLATFORM_USETHREADS
+ "lock;"
+#endif
+ "xadd %0, %1"
+ :"=q"(prev)
+ :"m"(*p), "0"(prev)
+ :"memory", "cc");
+
+ return (prev);
+}
+
+#ifdef ISC_PLATFORM_HAVEXADDQ
+static __inline__ isc_int64_t
+isc_atomic_xaddq(isc_int64_t *p, isc_int64_t val) {
+ isc_int64_t prev = val;
+
+ __asm__ volatile(
+#ifdef ISC_PLATFORM_USETHREADS
+ "lock;"
+#endif
+ "xaddq %0, %1"
+ :"=q"(prev)
+ :"m"(*p), "0"(prev)
+ :"memory", "cc");
+
+ return (prev);
+}
+#endif /* ISC_PLATFORM_HAVEXADDQ */
+
+/*
+ * This routine atomically stores the value 'val' in 'p'.
+ */
+static __inline__ void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+ __asm__ volatile(
+#ifdef ISC_PLATFORM_USETHREADS
+ /*
+ * xchg should automatically lock memory, but we add it
+ * explicitly just in case (it at least doesn't harm)
+ */
+ "lock;"
+#endif
+
+ "xchgl %1, %0"
+ :
+ : "r"(val), "m"(*p)
+ : "memory");
+}
+
+/*
+ * This routine atomically replaces the value in 'p' with 'val', if the
+ * original value is equal to 'cmpval'. The original value is returned in any
+ * case.
+ */
+static __inline__ isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+ __asm__ volatile(
+#ifdef ISC_PLATFORM_USETHREADS
+ "lock;"
+#endif
+ "cmpxchgl %1, %2"
+ : "=a"(cmpval)
+ : "r"(val), "m"(*p), "a"(cmpval)
+ : "memory");
+
+ return (cmpval);
+}
+
+#elif defined(ISC_PLATFORM_USESTDASM)
+/*
+ * The followings are "generic" assembly code which implements the same
+ * functionality in case the gcc extension cannot be used. It should be
+ * better to avoid inlining below, since we directly refer to specific
+ * positions of the stack frame, which would not actually point to the
+ * intended address in the embedded mnemonic.
+ */
+#include <isc/util.h> /* for 'UNUSED' macro */
+
+static isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+ UNUSED(p);
+ UNUSED(val);
+
+ __asm (
+ "movl 8(%ebp), %ecx\n"
+ "movl 12(%ebp), %edx\n"
+#ifdef ISC_PLATFORM_USETHREADS
+ "lock;"
+#endif
+ "xadd %edx, (%ecx)\n"
+
+ /*
+ * set the return value directly in the register so that we
+ * can avoid guessing the correct position in the stack for a
+ * local variable.
+ */
+ "movl %edx, %eax"
+ );
+}
+
+static void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+ UNUSED(p);
+ UNUSED(val);
+
+ __asm (
+ "movl 8(%ebp), %ecx\n"
+ "movl 12(%ebp), %edx\n"
+#ifdef ISC_PLATFORM_USETHREADS
+ "lock;"
+#endif
+ "xchgl (%ecx), %edx\n"
+ );
+}
+
+static isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+ UNUSED(p);
+ UNUSED(cmpval);
+ UNUSED(val);
+
+ __asm (
+ "movl 8(%ebp), %ecx\n"
+ "movl 12(%ebp), %eax\n" /* must be %eax for cmpxchgl */
+ "movl 16(%ebp), %edx\n"
+#ifdef ISC_PLATFORM_USETHREADS
+ "lock;"
+#endif
+
+ /*
+ * If (%ecx) == %eax then (%ecx) := %edx.
+ % %eax is set to old (%ecx), which will be the return value.
+ */
+ "cmpxchgl %edx, (%ecx)"
+ );
+}
+#else /* !ISC_PLATFORM_USEGCCASM && !ISC_PLATFORM_USESTDASM */
+
+#error "unsupported compiler. disable atomic ops by --disable-atomic"
+
+#endif
+#endif /* ISC_ATOMIC_H */
diff --git a/lib/isc/x86_64/Makefile.in b/lib/isc/x86_64/Makefile.in
new file mode 100644
index 0000000..324db07
--- /dev/null
+++ b/lib/isc/x86_64/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = include
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/x86_64/include/Makefile.in b/lib/isc/x86_64/include/Makefile.in
new file mode 100644
index 0000000..f1d8bdd
--- /dev/null
+++ b/lib/isc/x86_64/include/Makefile.in
@@ -0,0 +1,24 @@
+# Copyright (C) 2007 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 2007/09/14 04:09:59 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isc/x86_64/include/isc/Makefile.in b/lib/isc/x86_64/include/isc/Makefile.in
new file mode 100644
index 0000000..f33ae99
--- /dev/null
+++ b/lib/isc/x86_64/include/isc/Makefile.in
@@ -0,0 +1,36 @@
+# Copyright (C) 2007 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 2007/09/14 04:10:00 marka Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+HEADERS = atomic.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/isc ; \
+ done
diff --git a/lib/isc/x86_64/include/isc/atomic.h b/lib/isc/x86_64/include/isc/atomic.h
new file mode 100644
index 0000000..f57bd2a
--- /dev/null
+++ b/lib/isc/x86_64/include/isc/atomic.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2005, 2007, 2008 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: atomic.h,v 1.6 2008/01/24 23:47:00 tbox Exp $ */
+
+#ifndef ISC_ATOMIC_H
+#define ISC_ATOMIC_H 1
+
+#include <isc/platform.h>
+#include <isc/types.h>
+
+#ifdef ISC_PLATFORM_USEGCCASM
+
+/* We share the gcc-version with x86_32 */
+#error "impossible case. check build configuration"
+
+#elif defined(ISC_PLATFORM_USESTDASM)
+/*
+ * The followings are "generic" assembly code which implements the same
+ * functionality in case the gcc extension cannot be used. It should be
+ * better to avoid inlining below, since we directly refer to specific
+ * registers for arguments, which would not actually correspond to the
+ * intended address or value in the embedded mnemonic.
+ */
+#include <isc/util.h> /* for 'UNUSED' macro */
+
+static isc_int32_t
+isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
+ UNUSED(p);
+ UNUSED(val);
+
+ __asm (
+ "movq %rdi, %rdx\n"
+ "movl %esi, %eax\n"
+#ifdef ISC_PLATFORM_USETHREADS
+ "lock;"
+#endif
+ "xadd %eax, (%rdx)\n"
+ /*
+ * XXX: assume %eax will be used as the return value.
+ */
+ );
+}
+
+#ifdef ISC_PLATFORM_HAVEXADDQ
+static isc_int64_t
+isc_atomic_xaddq(isc_int64_t *p, isc_int64_t val) {
+ UNUSED(p);
+ UNUSED(val);
+
+ __asm (
+ "movq %rdi, %rdx\n"
+ "movq %rsi, %rax\n"
+#ifdef ISC_PLATFORM_USETHREADS
+ "lock;"
+#endif
+ "xaddq %rax, (%rdx)\n"
+ /*
+ * XXX: assume %rax will be used as the return value.
+ */
+ );
+}
+#endif
+
+static void
+isc_atomic_store(isc_int32_t *p, isc_int32_t val) {
+ UNUSED(p);
+ UNUSED(val);
+
+ __asm (
+ "movq %rdi, %rax\n"
+ "movl %esi, %edx\n"
+#ifdef ISC_PLATFORM_USETHREADS
+ "lock;"
+#endif
+ "xchgl (%rax), %edx\n"
+ /*
+ * XXX: assume %rax will be used as the return value.
+ */
+ );
+}
+
+static isc_int32_t
+isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
+ UNUSED(p);
+ UNUSED(cmpval);
+ UNUSED(val);
+
+ __asm (
+ "movl %edx, %ecx\n"
+ "movl %esi, %eax\n"
+ "movq %rdi, %rdx\n"
+
+#ifdef ISC_PLATFORM_USETHREADS
+ "lock;"
+#endif
+ /*
+ * If (%rdi) == %eax then (%rdi) := %edx.
+ * %eax is set to old (%ecx), which will be the return value.
+ */
+ "cmpxchgl %ecx, (%rdx)"
+ );
+}
+
+#else /* !ISC_PLATFORM_USEGCCASM && !ISC_PLATFORM_USESTDASM */
+
+#error "unsupported compiler. disable atomic ops by --disable-atomic"
+
+#endif
+#endif /* ISC_ATOMIC_H */
diff --git a/lib/isccc/Makefile.in b/lib/isccc/Makefile.in
new file mode 100644
index 0000000..5dcc225
--- /dev/null
+++ b/lib/isccc/Makefile.in
@@ -0,0 +1,86 @@
+# Copyright (C) 2004, 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: Makefile.in,v 1.9 2007/06/19 23:47:21 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@LIBISCCC_API@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I. ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCC_INCLUDES}
+
+CDEFINES =
+CWARNINGS =
+
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCCCLIBS = ../../lib/isccc/libisccc.@A@
+
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCCCDEPLIBS = libisccc.@A@
+
+LIBS = @LIBS@
+
+SUBDIRS = include
+
+# Alphabetically
+OBJS = alist.@O@ base64.@O@ cc.@O@ ccmsg.@O@ \
+ lib.@O@ \
+ result.@O@ sexpr.@O@ symtab.@O@ version.@O@
+
+# Alphabetically
+SRCS = alist.c base64.c cc.c ccmsg.c \
+ lib.c \
+ result.c sexpr.c symtab.c version.c
+
+
+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
+
+libisccc.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+libisccc.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libisccc.la -rpath ${libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} ${LIBS} ${ISCLIBS}
+
+timestamp: libisccc.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisccc.@A@ ${DESTDIR}${libdir}
+
+clean distclean::
+ rm -f libisccc.@A@ timestamp
diff --git a/lib/isccc/alist.c b/lib/isccc/alist.c
new file mode 100644
index 0000000..4f1743e
--- /dev/null
+++ b/lib/isccc/alist.c
@@ -0,0 +1,312 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: alist.c,v 1.8 2007/08/28 07:20:43 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <isccc/alist.h>
+#include <isc/assertions.h>
+#include <isccc/result.h>
+#include <isccc/sexpr.h>
+#include <isccc/util.h>
+
+#define CAR(s) (s)->value.as_dottedpair.car
+#define CDR(s) (s)->value.as_dottedpair.cdr
+
+#define ALIST_TAG "*alist*"
+#define MAX_INDENT 64
+
+static char spaces[MAX_INDENT + 1] =
+ " ";
+
+isccc_sexpr_t *
+isccc_alist_create(void)
+{
+ isccc_sexpr_t *alist, *tag;
+
+ tag = isccc_sexpr_fromstring(ALIST_TAG);
+ if (tag == NULL)
+ return (NULL);
+ alist = isccc_sexpr_cons(tag, NULL);
+ if (alist == NULL) {
+ isccc_sexpr_free(&tag);
+ return (NULL);
+ }
+
+ return (alist);
+}
+
+isc_boolean_t
+isccc_alist_alistp(isccc_sexpr_t *alist)
+{
+ isccc_sexpr_t *car;
+
+ if (alist == NULL || alist->type != ISCCC_SEXPRTYPE_DOTTEDPAIR)
+ return (ISC_FALSE);
+ car = CAR(alist);
+ if (car == NULL || car->type != ISCCC_SEXPRTYPE_STRING)
+ return (ISC_FALSE);
+ if (strcmp(car->value.as_string, ALIST_TAG) != 0)
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+}
+
+isc_boolean_t
+isccc_alist_emptyp(isccc_sexpr_t *alist)
+{
+ REQUIRE(isccc_alist_alistp(alist));
+
+ if (CDR(alist) == NULL)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isccc_sexpr_t *
+isccc_alist_first(isccc_sexpr_t *alist)
+{
+ REQUIRE(isccc_alist_alistp(alist));
+
+ return (CDR(alist));
+}
+
+isccc_sexpr_t *
+isccc_alist_assq(isccc_sexpr_t *alist, const char *key)
+{
+ isccc_sexpr_t *car, *caar;
+
+ REQUIRE(isccc_alist_alistp(alist));
+
+ /*
+ * Skip alist type tag.
+ */
+ alist = CDR(alist);
+
+ while (alist != NULL) {
+ INSIST(alist->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
+ car = CAR(alist);
+ INSIST(car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
+ caar = CAR(car);
+ if (caar->type == ISCCC_SEXPRTYPE_STRING &&
+ strcmp(caar->value.as_string, key) == 0)
+ return (car);
+ alist = CDR(alist);
+ }
+
+ return (NULL);
+}
+
+void
+isccc_alist_delete(isccc_sexpr_t *alist, const char *key)
+{
+ isccc_sexpr_t *car, *caar, *rest, *prev;
+
+ REQUIRE(isccc_alist_alistp(alist));
+
+ prev = alist;
+ rest = CDR(alist);
+ while (rest != NULL) {
+ INSIST(rest->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
+ car = CAR(rest);
+ INSIST(car != NULL && car->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
+ caar = CAR(car);
+ if (caar->type == ISCCC_SEXPRTYPE_STRING &&
+ strcmp(caar->value.as_string, key) == 0) {
+ CDR(prev) = CDR(rest);
+ CDR(rest) = NULL;
+ isccc_sexpr_free(&rest);
+ break;
+ }
+ prev = rest;
+ rest = CDR(rest);
+ }
+}
+
+isccc_sexpr_t *
+isccc_alist_define(isccc_sexpr_t *alist, const char *key, isccc_sexpr_t *value)
+{
+ isccc_sexpr_t *kv, *k, *elt;
+
+ kv = isccc_alist_assq(alist, key);
+ if (kv == NULL) {
+ /*
+ * New association.
+ */
+ k = isccc_sexpr_fromstring(key);
+ if (k == NULL)
+ return (NULL);
+ kv = isccc_sexpr_cons(k, value);
+ if (kv == NULL) {
+ isccc_sexpr_free(&kv);
+ return (NULL);
+ }
+ elt = isccc_sexpr_addtolist(&alist, kv);
+ if (elt == NULL) {
+ isccc_sexpr_free(&kv);
+ return (NULL);
+ }
+ } else {
+ /*
+ * We've already got an entry for this key. Replace it.
+ */
+ isccc_sexpr_free(&CDR(kv));
+ CDR(kv) = value;
+ }
+
+ return (kv);
+}
+
+isccc_sexpr_t *
+isccc_alist_definestring(isccc_sexpr_t *alist, const char *key, const char *str)
+{
+ isccc_sexpr_t *v, *kv;
+
+ v = isccc_sexpr_fromstring(str);
+ if (v == NULL)
+ return (NULL);
+ kv = isccc_alist_define(alist, key, v);
+ if (kv == NULL)
+ isccc_sexpr_free(&v);
+
+ return (kv);
+}
+
+isccc_sexpr_t *
+isccc_alist_definebinary(isccc_sexpr_t *alist, const char *key, isccc_region_t *r)
+{
+ isccc_sexpr_t *v, *kv;
+
+ v = isccc_sexpr_frombinary(r);
+ if (v == NULL)
+ return (NULL);
+ kv = isccc_alist_define(alist, key, v);
+ if (kv == NULL)
+ isccc_sexpr_free(&v);
+
+ return (kv);
+}
+
+isccc_sexpr_t *
+isccc_alist_lookup(isccc_sexpr_t *alist, const char *key)
+{
+ isccc_sexpr_t *kv;
+
+ kv = isccc_alist_assq(alist, key);
+ if (kv != NULL)
+ return (CDR(kv));
+ return (NULL);
+}
+
+isc_result_t
+isccc_alist_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp)
+{
+ isccc_sexpr_t *kv, *v;
+
+ kv = isccc_alist_assq(alist, key);
+ if (kv != NULL) {
+ v = CDR(kv);
+ if (isccc_sexpr_stringp(v)) {
+ if (strp != NULL)
+ *strp = isccc_sexpr_tostring(v);
+ return (ISC_R_SUCCESS);
+ } else
+ return (ISC_R_EXISTS);
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+isccc_alist_lookupbinary(isccc_sexpr_t *alist, const char *key, isccc_region_t **r)
+{
+ isccc_sexpr_t *kv, *v;
+
+ kv = isccc_alist_assq(alist, key);
+ if (kv != NULL) {
+ v = CDR(kv);
+ if (isccc_sexpr_binaryp(v)) {
+ if (r != NULL)
+ *r = isccc_sexpr_tobinary(v);
+ return (ISC_R_SUCCESS);
+ } else
+ return (ISC_R_EXISTS);
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+void
+isccc_alist_prettyprint(isccc_sexpr_t *sexpr, unsigned int indent, FILE *stream)
+{
+ isccc_sexpr_t *elt, *kv, *k, *v;
+
+ if (isccc_alist_alistp(sexpr)) {
+ fprintf(stream, "{\n");
+ indent += 4;
+ for (elt = isccc_alist_first(sexpr);
+ elt != NULL;
+ elt = CDR(elt)) {
+ kv = CAR(elt);
+ INSIST(isccc_sexpr_listp(kv));
+ k = CAR(kv);
+ v = CDR(kv);
+ INSIST(isccc_sexpr_stringp(k));
+ fprintf(stream, "%.*s%s => ", (int)indent, spaces,
+ isccc_sexpr_tostring(k));
+ isccc_alist_prettyprint(v, indent, stream);
+ if (CDR(elt) != NULL)
+ fprintf(stream, ",");
+ fprintf(stream, "\n");
+ }
+ indent -= 4;
+ fprintf(stream, "%.*s}", (int)indent, spaces);
+ } else if (isccc_sexpr_listp(sexpr)) {
+ fprintf(stream, "(\n");
+ indent += 4;
+ for (elt = sexpr;
+ elt != NULL;
+ elt = CDR(elt)) {
+ fprintf(stream, "%.*s", (int)indent, spaces);
+ isccc_alist_prettyprint(CAR(elt), indent, stream);
+ if (CDR(elt) != NULL)
+ fprintf(stream, ",");
+ fprintf(stream, "\n");
+ }
+ indent -= 4;
+ fprintf(stream, "%.*s)", (int)indent, spaces);
+ } else
+ isccc_sexpr_print(sexpr, stream);
+}
diff --git a/lib/isccc/api b/lib/isccc/api
new file mode 100644
index 0000000..8459d42
--- /dev/null
+++ b/lib/isccc/api
@@ -0,0 +1,3 @@
+LIBINTERFACE = 50
+LIBREVISION = 0
+LIBAGE = 0
diff --git a/lib/isccc/base64.c b/lib/isccc/base64.c
new file mode 100644
index 0000000..78b34ed
--- /dev/null
+++ b/lib/isccc/base64.c
@@ -0,0 +1,78 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: base64.c,v 1.8 2007/08/28 07:20:43 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/base64.h>
+#include <isc/buffer.h>
+#include <isc/region.h>
+#include <isc/result.h>
+
+#include <isccc/base64.h>
+#include <isccc/result.h>
+#include <isccc/util.h>
+
+isc_result_t
+isccc_base64_encode(isccc_region_t *source, int wordlength,
+ const char *wordbreak, isccc_region_t *target)
+{
+ isc_region_t sr;
+ isc_buffer_t tb;
+ isc_result_t result;
+
+ sr.base = source->rstart;
+ sr.length = source->rend - source->rstart;
+ isc_buffer_init(&tb, target->rstart, target->rend - target->rstart);
+
+ result = isc_base64_totext(&sr, wordlength, wordbreak, &tb);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ source->rstart = source->rend;
+ target->rstart = isc_buffer_used(&tb);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isccc_base64_decode(const char *cstr, isccc_region_t *target) {
+ isc_buffer_t b;
+ isc_result_t result;
+
+ isc_buffer_init(&b, target->rstart, target->rend - target->rstart);
+ result = isc_base64_decodestring(cstr, &b);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ target->rstart = isc_buffer_used(&b);
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isccc/cc.c b/lib/isccc/cc.c
new file mode 100644
index 0000000..cfa1db6
--- /dev/null
+++ b/lib/isccc/cc.c
@@ -0,0 +1,831 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: cc.c,v 1.18 2007/08/28 07:20:43 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <isc/assertions.h>
+#include <isc/hmacmd5.h>
+#include <isc/print.h>
+#include <isc/stdlib.h>
+
+#include <isccc/alist.h>
+#include <isccc/base64.h>
+#include <isccc/cc.h>
+#include <isccc/result.h>
+#include <isccc/sexpr.h>
+#include <isccc/symtab.h>
+#include <isccc/symtype.h>
+#include <isccc/util.h>
+
+#define MAX_TAGS 256
+#define DUP_LIFETIME 900
+
+typedef isccc_sexpr_t *sexpr_ptr;
+
+static unsigned char auth_hmd5[] = {
+ 0x05, 0x5f, 0x61, 0x75, 0x74, 0x68, /*%< len + _auth */
+ ISCCC_CCMSGTYPE_TABLE, /*%< message type */
+ 0x00, 0x00, 0x00, 0x20, /*%< length == 32 */
+ 0x04, 0x68, 0x6d, 0x64, 0x35, /*%< len + hmd5 */
+ ISCCC_CCMSGTYPE_BINARYDATA, /*%< message type */
+ 0x00, 0x00, 0x00, 0x16, /*%< length == 22 */
+ /*
+ * The base64 encoding of one of our HMAC-MD5 signatures is
+ * 22 bytes.
+ */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+#define HMD5_OFFSET 21 /*%< 21 = 6 + 1 + 4 + 5 + 1 + 4 */
+#define HMD5_LENGTH 22
+
+static isc_result_t
+table_towire(isccc_sexpr_t *alist, isccc_region_t *target);
+
+static isc_result_t
+list_towire(isccc_sexpr_t *alist, isccc_region_t *target);
+
+static isc_result_t
+value_towire(isccc_sexpr_t *elt, isccc_region_t *target)
+{
+ size_t len;
+ unsigned char *lenp;
+ isccc_region_t *vr;
+ isc_result_t result;
+
+ if (isccc_sexpr_binaryp(elt)) {
+ vr = isccc_sexpr_tobinary(elt);
+ len = REGION_SIZE(*vr);
+ if (REGION_SIZE(*target) < 1 + 4 + len)
+ return (ISC_R_NOSPACE);
+ PUT8(ISCCC_CCMSGTYPE_BINARYDATA, target->rstart);
+ PUT32(len, target->rstart);
+ if (REGION_SIZE(*target) < len)
+ return (ISC_R_NOSPACE);
+ PUT_MEM(vr->rstart, len, target->rstart);
+ } else if (isccc_alist_alistp(elt)) {
+ if (REGION_SIZE(*target) < 1 + 4)
+ return (ISC_R_NOSPACE);
+ PUT8(ISCCC_CCMSGTYPE_TABLE, target->rstart);
+ /*
+ * Emit a placeholder length.
+ */
+ lenp = target->rstart;
+ PUT32(0, target->rstart);
+ /*
+ * Emit the table.
+ */
+ result = table_towire(elt, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ len = (size_t)(target->rstart - lenp);
+ /*
+ * 'len' is 4 bytes too big, since it counts
+ * the placeholder length too. Adjust and
+ * emit.
+ */
+ INSIST(len >= 4U);
+ len -= 4;
+ PUT32(len, lenp);
+ } else if (isccc_sexpr_listp(elt)) {
+ if (REGION_SIZE(*target) < 1 + 4)
+ return (ISC_R_NOSPACE);
+ PUT8(ISCCC_CCMSGTYPE_LIST, target->rstart);
+ /*
+ * Emit a placeholder length and count.
+ */
+ lenp = target->rstart;
+ PUT32(0, target->rstart);
+ /*
+ * Emit the list.
+ */
+ result = list_towire(elt, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ len = (size_t)(target->rstart - lenp);
+ /*
+ * 'len' is 4 bytes too big, since it counts
+ * the placeholder length. Adjust and emit.
+ */
+ INSIST(len >= 4U);
+ len -= 4;
+ PUT32(len, lenp);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+table_towire(isccc_sexpr_t *alist, isccc_region_t *target)
+{
+ isccc_sexpr_t *kv, *elt, *k, *v;
+ char *ks;
+ isc_result_t result;
+ size_t len;
+
+ for (elt = isccc_alist_first(alist);
+ elt != NULL;
+ elt = ISCCC_SEXPR_CDR(elt)) {
+ kv = ISCCC_SEXPR_CAR(elt);
+ k = ISCCC_SEXPR_CAR(kv);
+ ks = isccc_sexpr_tostring(k);
+ v = ISCCC_SEXPR_CDR(kv);
+ len = strlen(ks);
+ INSIST(len <= 255U);
+ /*
+ * Emit the key name.
+ */
+ if (REGION_SIZE(*target) < 1 + len)
+ return (ISC_R_NOSPACE);
+ PUT8(len, target->rstart);
+ PUT_MEM(ks, len, target->rstart);
+ /*
+ * Emit the value.
+ */
+ result = value_towire(v, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+list_towire(isccc_sexpr_t *list, isccc_region_t *target)
+{
+ isc_result_t result;
+
+ while (list != NULL) {
+ result = value_towire(ISCCC_SEXPR_CAR(list), target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ list = ISCCC_SEXPR_CDR(list);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+sign(unsigned char *data, unsigned int length, unsigned char *hmd5,
+ isccc_region_t *secret)
+{
+ isc_hmacmd5_t ctx;
+ isc_result_t result;
+ isccc_region_t source, target;
+ unsigned char digest[ISC_MD5_DIGESTLENGTH];
+ unsigned char digestb64[ISC_MD5_DIGESTLENGTH * 4];
+
+ isc_hmacmd5_init(&ctx, secret->rstart, REGION_SIZE(*secret));
+ isc_hmacmd5_update(&ctx, data, length);
+ isc_hmacmd5_sign(&ctx, digest);
+ source.rstart = digest;
+ source.rend = digest + ISC_MD5_DIGESTLENGTH;
+ target.rstart = digestb64;
+ target.rend = digestb64 + ISC_MD5_DIGESTLENGTH * 4;
+ result = isccc_base64_encode(&source, 64, "", &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ PUT_MEM(digestb64, HMD5_LENGTH, hmd5);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target,
+ isccc_region_t *secret)
+{
+ unsigned char *hmd5_rstart, *signed_rstart;
+ isc_result_t result;
+
+ if (REGION_SIZE(*target) < 4 + sizeof(auth_hmd5))
+ return (ISC_R_NOSPACE);
+ /*
+ * Emit protocol version.
+ */
+ PUT32(1, target->rstart);
+ if (secret != NULL) {
+ /*
+ * Emit _auth section with zeroed HMAC-MD5 signature.
+ * We'll replace the zeros with the real signature once
+ * we know what it is.
+ */
+ hmd5_rstart = target->rstart + HMD5_OFFSET;
+ PUT_MEM(auth_hmd5, sizeof(auth_hmd5), target->rstart);
+ } else
+ hmd5_rstart = NULL;
+ signed_rstart = target->rstart;
+ /*
+ * Delete any existing _auth section so that we don't try
+ * to encode it.
+ */
+ isccc_alist_delete(alist, "_auth");
+ /*
+ * Emit the message.
+ */
+ result = table_towire(alist, target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ if (secret != NULL)
+ return (sign(signed_rstart, (target->rstart - signed_rstart),
+ hmd5_rstart, secret));
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+verify(isccc_sexpr_t *alist, unsigned char *data, unsigned int length,
+ isccc_region_t *secret)
+{
+ isc_hmacmd5_t ctx;
+ isccc_region_t source;
+ isccc_region_t target;
+ isc_result_t result;
+ isccc_sexpr_t *_auth, *hmd5;
+ unsigned char digest[ISC_MD5_DIGESTLENGTH];
+ unsigned char digestb64[ISC_MD5_DIGESTLENGTH * 4];
+
+ /*
+ * Extract digest.
+ */
+ _auth = isccc_alist_lookup(alist, "_auth");
+ if (_auth == NULL)
+ return (ISC_R_FAILURE);
+ hmd5 = isccc_alist_lookup(_auth, "hmd5");
+ if (hmd5 == NULL)
+ return (ISC_R_FAILURE);
+ /*
+ * Compute digest.
+ */
+ isc_hmacmd5_init(&ctx, secret->rstart, REGION_SIZE(*secret));
+ isc_hmacmd5_update(&ctx, data, length);
+ isc_hmacmd5_sign(&ctx, digest);
+ source.rstart = digest;
+ source.rend = digest + ISC_MD5_DIGESTLENGTH;
+ target.rstart = digestb64;
+ target.rend = digestb64 + ISC_MD5_DIGESTLENGTH * 4;
+ result = isccc_base64_encode(&source, 64, "", &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ /*
+ * Strip trailing == and NUL terminate target.
+ */
+ target.rstart -= 2;
+ *target.rstart++ = '\0';
+ /*
+ * Verify.
+ */
+ if (strcmp((char *)digestb64, isccc_sexpr_tostring(hmd5)) != 0)
+ return (ISCCC_R_BADAUTH);
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+table_fromwire(isccc_region_t *source, isccc_region_t *secret,
+ isccc_sexpr_t **alistp);
+
+static isc_result_t
+list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp);
+
+static isc_result_t
+value_fromwire(isccc_region_t *source, isccc_sexpr_t **valuep)
+{
+ unsigned int msgtype;
+ isc_uint32_t len;
+ isccc_sexpr_t *value;
+ isccc_region_t active;
+ isc_result_t result;
+
+ if (REGION_SIZE(*source) < 1 + 4)
+ return (ISC_R_UNEXPECTEDEND);
+ GET8(msgtype, source->rstart);
+ GET32(len, source->rstart);
+ if (REGION_SIZE(*source) < len)
+ return (ISC_R_UNEXPECTEDEND);
+ active.rstart = source->rstart;
+ active.rend = active.rstart + len;
+ source->rstart = active.rend;
+ if (msgtype == ISCCC_CCMSGTYPE_BINARYDATA) {
+ value = isccc_sexpr_frombinary(&active);
+ if (value != NULL) {
+ *valuep = value;
+ result = ISC_R_SUCCESS;
+ } else
+ result = ISC_R_NOMEMORY;
+ } else if (msgtype == ISCCC_CCMSGTYPE_TABLE)
+ result = table_fromwire(&active, NULL, valuep);
+ else if (msgtype == ISCCC_CCMSGTYPE_LIST)
+ result = list_fromwire(&active, valuep);
+ else
+ result = ISCCC_R_SYNTAX;
+
+ return (result);
+}
+
+static isc_result_t
+table_fromwire(isccc_region_t *source, isccc_region_t *secret,
+ isccc_sexpr_t **alistp)
+{
+ char key[256];
+ isc_uint32_t len;
+ isc_result_t result;
+ isccc_sexpr_t *alist, *value;
+ isc_boolean_t first_tag;
+ unsigned char *checksum_rstart;
+
+ REQUIRE(alistp != NULL && *alistp == NULL);
+
+ checksum_rstart = NULL;
+ first_tag = ISC_TRUE;
+ alist = isccc_alist_create();
+ if (alist == NULL)
+ return (ISC_R_NOMEMORY);
+
+ while (!REGION_EMPTY(*source)) {
+ GET8(len, source->rstart);
+ if (REGION_SIZE(*source) < len) {
+ result = ISC_R_UNEXPECTEDEND;
+ goto bad;
+ }
+ GET_MEM(key, len, source->rstart);
+ key[len] = '\0'; /* Ensure NUL termination. */
+ value = NULL;
+ result = value_fromwire(source, &value);
+ if (result != ISC_R_SUCCESS)
+ goto bad;
+ if (isccc_alist_define(alist, key, value) == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto bad;
+ }
+ if (first_tag && secret != NULL && strcmp(key, "_auth") == 0)
+ checksum_rstart = source->rstart;
+ first_tag = ISC_FALSE;
+ }
+
+ *alistp = alist;
+
+ if (secret != NULL) {
+ if (checksum_rstart != NULL)
+ return (verify(alist, checksum_rstart,
+ (source->rend - checksum_rstart),
+ secret));
+ return (ISCCC_R_BADAUTH);
+ }
+
+ return (ISC_R_SUCCESS);
+
+ bad:
+ isccc_sexpr_free(&alist);
+
+ return (result);
+}
+
+static isc_result_t
+list_fromwire(isccc_region_t *source, isccc_sexpr_t **listp)
+{
+ isccc_sexpr_t *list, *value;
+ isc_result_t result;
+
+ list = NULL;
+ while (!REGION_EMPTY(*source)) {
+ value = NULL;
+ result = value_fromwire(source, &value);
+ if (result != ISC_R_SUCCESS) {
+ isccc_sexpr_free(&list);
+ return (result);
+ }
+ if (isccc_sexpr_addtolist(&list, value) == NULL) {
+ isccc_sexpr_free(&value);
+ isccc_sexpr_free(&list);
+ return (result);
+ }
+ }
+
+ *listp = list;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp,
+ isccc_region_t *secret)
+{
+ unsigned int size;
+ isc_uint32_t version;
+
+ size = REGION_SIZE(*source);
+ if (size < 4)
+ return (ISC_R_UNEXPECTEDEND);
+ GET32(version, source->rstart);
+ if (version != 1)
+ return (ISCCC_R_UNKNOWNVERSION);
+
+ return (table_fromwire(source, secret, alistp));
+}
+
+static isc_result_t
+createmessage(isc_uint32_t version, const char *from, const char *to,
+ isc_uint32_t serial, isccc_time_t now,
+ isccc_time_t expires, isccc_sexpr_t **alistp,
+ isc_boolean_t want_expires)
+{
+ isccc_sexpr_t *alist, *_ctrl, *_data;
+ isc_result_t result;
+
+ REQUIRE(alistp != NULL && *alistp == NULL);
+
+ if (version != 1)
+ return (ISCCC_R_UNKNOWNVERSION);
+
+ alist = isccc_alist_create();
+ if (alist == NULL)
+ return (ISC_R_NOMEMORY);
+
+ result = ISC_R_NOMEMORY;
+
+ _ctrl = isccc_alist_create();
+ if (_ctrl == NULL)
+ goto bad;
+ if (isccc_alist_define(alist, "_ctrl", _ctrl) == NULL) {
+ isccc_sexpr_free(&_ctrl);
+ goto bad;
+ }
+
+ _data = isccc_alist_create();
+ if (_data == NULL)
+ goto bad;
+ if (isccc_alist_define(alist, "_data", _data) == NULL) {
+ isccc_sexpr_free(&_data);
+ goto bad;
+ }
+
+ if (isccc_cc_defineuint32(_ctrl, "_ser", serial) == NULL ||
+ isccc_cc_defineuint32(_ctrl, "_tim", now) == NULL ||
+ (want_expires &&
+ isccc_cc_defineuint32(_ctrl, "_exp", expires) == NULL))
+ goto bad;
+ if (from != NULL &&
+ isccc_cc_definestring(_ctrl, "_frm", from) == NULL)
+ goto bad;
+ if (to != NULL &&
+ isccc_cc_definestring(_ctrl, "_to", to) == NULL)
+ goto bad;
+
+ *alistp = alist;
+
+ return (ISC_R_SUCCESS);
+
+ bad:
+ isccc_sexpr_free(&alist);
+
+ return (result);
+}
+
+isc_result_t
+isccc_cc_createmessage(isc_uint32_t version, const char *from, const char *to,
+ isc_uint32_t serial, isccc_time_t now,
+ isccc_time_t expires, isccc_sexpr_t **alistp)
+{
+ return (createmessage(version, from, to, serial, now, expires,
+ alistp, ISC_TRUE));
+}
+
+isc_result_t
+isccc_cc_createack(isccc_sexpr_t *message, isc_boolean_t ok,
+ isccc_sexpr_t **ackp)
+{
+ char *_frm, *_to;
+ isc_uint32_t serial;
+ isccc_sexpr_t *ack, *_ctrl;
+ isc_result_t result;
+ isccc_time_t t;
+
+ REQUIRE(ackp != NULL && *ackp == NULL);
+
+ _ctrl = isccc_alist_lookup(message, "_ctrl");
+ if (_ctrl == NULL ||
+ isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS ||
+ isccc_cc_lookupuint32(_ctrl, "_tim", &t) != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+ /*
+ * _frm and _to are optional.
+ */
+ _frm = NULL;
+ (void)isccc_cc_lookupstring(_ctrl, "_frm", &_frm);
+ _to = NULL;
+ (void)isccc_cc_lookupstring(_ctrl, "_to", &_to);
+ /*
+ * Create the ack.
+ */
+ ack = NULL;
+ result = createmessage(1, _to, _frm, serial, t, 0, &ack, ISC_FALSE);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ _ctrl = isccc_alist_lookup(ack, "_ctrl");
+ if (_ctrl == NULL)
+ return (ISC_R_FAILURE);
+ if (isccc_cc_definestring(ack, "_ack", (ok) ? "1" : "0") == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto bad;
+ }
+
+ *ackp = ack;
+
+ return (ISC_R_SUCCESS);
+
+ bad:
+ isccc_sexpr_free(&ack);
+
+ return (result);
+}
+
+isc_boolean_t
+isccc_cc_isack(isccc_sexpr_t *message)
+{
+ isccc_sexpr_t *_ctrl;
+
+ _ctrl = isccc_alist_lookup(message, "_ctrl");
+ if (_ctrl == NULL)
+ return (ISC_FALSE);
+ if (isccc_cc_lookupstring(_ctrl, "_ack", NULL) == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+isccc_cc_isreply(isccc_sexpr_t *message)
+{
+ isccc_sexpr_t *_ctrl;
+
+ _ctrl = isccc_alist_lookup(message, "_ctrl");
+ if (_ctrl == NULL)
+ return (ISC_FALSE);
+ if (isccc_cc_lookupstring(_ctrl, "_rpl", NULL) == ISC_R_SUCCESS)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_result_t
+isccc_cc_createresponse(isccc_sexpr_t *message, isccc_time_t now,
+ isccc_time_t expires, isccc_sexpr_t **alistp)
+{
+ char *_frm, *_to, *type;
+ isc_uint32_t serial;
+ isccc_sexpr_t *alist, *_ctrl, *_data;
+ isc_result_t result;
+
+ REQUIRE(alistp != NULL && *alistp == NULL);
+
+ _ctrl = isccc_alist_lookup(message, "_ctrl");
+ _data = isccc_alist_lookup(message, "_data");
+ if (_ctrl == NULL ||
+ _data == NULL ||
+ isccc_cc_lookupuint32(_ctrl, "_ser", &serial) != ISC_R_SUCCESS ||
+ isccc_cc_lookupstring(_data, "type", &type) != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+ /*
+ * _frm and _to are optional.
+ */
+ _frm = NULL;
+ (void)isccc_cc_lookupstring(_ctrl, "_frm", &_frm);
+ _to = NULL;
+ (void)isccc_cc_lookupstring(_ctrl, "_to", &_to);
+ /*
+ * Create the response.
+ */
+ alist = NULL;
+ result = isccc_cc_createmessage(1, _to, _frm, serial, now, expires,
+ &alist);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ _ctrl = isccc_alist_lookup(alist, "_ctrl");
+ if (_ctrl == NULL)
+ return (ISC_R_FAILURE);
+ _data = isccc_alist_lookup(alist, "_data");
+ if (_data == NULL)
+ return (ISC_R_FAILURE);
+ if (isccc_cc_definestring(_ctrl, "_rpl", "1") == NULL ||
+ isccc_cc_definestring(_data, "type", type) == NULL) {
+ isccc_sexpr_free(&alist);
+ return (ISC_R_NOMEMORY);
+ }
+
+ *alistp = alist;
+
+ return (ISC_R_SUCCESS);
+}
+
+isccc_sexpr_t *
+isccc_cc_definestring(isccc_sexpr_t *alist, const char *key, const char *str)
+{
+ size_t len;
+ isccc_region_t r;
+
+ len = strlen(str);
+ DE_CONST(str, r.rstart);
+ r.rend = r.rstart + len;
+
+ return (isccc_alist_definebinary(alist, key, &r));
+}
+
+isccc_sexpr_t *
+isccc_cc_defineuint32(isccc_sexpr_t *alist, const char *key, isc_uint32_t i)
+{
+ char b[100];
+ size_t len;
+ isccc_region_t r;
+
+ snprintf(b, sizeof(b), "%u", i);
+ len = strlen(b);
+ r.rstart = (unsigned char *)b;
+ r.rend = (unsigned char *)b + len;
+
+ return (isccc_alist_definebinary(alist, key, &r));
+}
+
+isc_result_t
+isccc_cc_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp)
+{
+ isccc_sexpr_t *kv, *v;
+
+ kv = isccc_alist_assq(alist, key);
+ if (kv != NULL) {
+ v = ISCCC_SEXPR_CDR(kv);
+ if (isccc_sexpr_binaryp(v)) {
+ if (strp != NULL)
+ *strp = isccc_sexpr_tostring(v);
+ return (ISC_R_SUCCESS);
+ } else
+ return (ISC_R_EXISTS);
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+isccc_cc_lookupuint32(isccc_sexpr_t *alist, const char *key,
+ isc_uint32_t *uintp)
+{
+ isccc_sexpr_t *kv, *v;
+
+ kv = isccc_alist_assq(alist, key);
+ if (kv != NULL) {
+ v = ISCCC_SEXPR_CDR(kv);
+ if (isccc_sexpr_binaryp(v)) {
+ if (uintp != NULL)
+ *uintp = (isc_uint32_t)
+ strtoul(isccc_sexpr_tostring(v),
+ NULL, 10);
+ return (ISC_R_SUCCESS);
+ } else
+ return (ISC_R_EXISTS);
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
+static void
+symtab_undefine(char *key, unsigned int type, isccc_symvalue_t value,
+ void *arg)
+{
+ UNUSED(type);
+ UNUSED(value);
+ UNUSED(arg);
+
+ free(key);
+}
+
+static isc_boolean_t
+symtab_clean(char *key, unsigned int type, isccc_symvalue_t value,
+ void *arg)
+{
+ isccc_time_t *now;
+
+ UNUSED(key);
+ UNUSED(type);
+
+ now = arg;
+
+ if (*now < value.as_uinteger)
+ return (ISC_FALSE);
+ if ((*now - value.as_uinteger) < DUP_LIFETIME)
+ return (ISC_FALSE);
+ return (ISC_TRUE);
+}
+
+isc_result_t
+isccc_cc_createsymtab(isccc_symtab_t **symtabp)
+{
+ return (isccc_symtab_create(11897, symtab_undefine, NULL, ISC_FALSE,
+ symtabp));
+}
+
+void
+isccc_cc_cleansymtab(isccc_symtab_t *symtab, isccc_time_t now)
+{
+ isccc_symtab_foreach(symtab, symtab_clean, &now);
+}
+
+static isc_boolean_t
+has_whitespace(const char *str)
+{
+ char c;
+
+ if (str == NULL)
+ return (ISC_FALSE);
+ while ((c = *str++) != '\0') {
+ if (c == ' ' || c == '\t' || c == '\n')
+ return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
+isc_result_t
+isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message,
+ isccc_time_t now)
+{
+ const char *_frm;
+ const char *_to;
+ char *_ser, *_tim, *tmp;
+ isc_result_t result;
+ char *key;
+ size_t len;
+ isccc_symvalue_t value;
+ isccc_sexpr_t *_ctrl;
+
+ _ctrl = isccc_alist_lookup(message, "_ctrl");
+ if (_ctrl == NULL ||
+ isccc_cc_lookupstring(_ctrl, "_ser", &_ser) != ISC_R_SUCCESS ||
+ isccc_cc_lookupstring(_ctrl, "_tim", &_tim) != ISC_R_SUCCESS)
+ return (ISC_R_FAILURE);
+ /*
+ * _frm and _to are optional.
+ */
+ if (isccc_cc_lookupstring(_ctrl, "_frm", &tmp) != ISC_R_SUCCESS)
+ _frm = "";
+ else
+ _frm = tmp;
+ if (isccc_cc_lookupstring(_ctrl, "_to", &tmp) != ISC_R_SUCCESS)
+ _to = "";
+ else
+ _to = tmp;
+ /*
+ * Ensure there is no newline in any of the strings. This is so
+ * we can write them to a file later.
+ */
+ if (has_whitespace(_frm) || has_whitespace(_to) ||
+ has_whitespace(_ser) || has_whitespace(_tim))
+ return (ISC_R_FAILURE);
+ len = strlen(_frm) + strlen(_to) + strlen(_ser) + strlen(_tim) + 4;
+ key = malloc(len);
+ if (key == NULL)
+ return (ISC_R_NOMEMORY);
+ snprintf(key, len, "%s;%s;%s;%s", _frm, _to, _ser, _tim);
+ value.as_uinteger = now;
+ result = isccc_symtab_define(symtab, key, ISCCC_SYMTYPE_CCDUP, value,
+ isccc_symexists_reject);
+ if (result != ISC_R_SUCCESS) {
+ free(key);
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
diff --git a/lib/isccc/ccmsg.c b/lib/isccc/ccmsg.c
new file mode 100644
index 0000000..298fc22
--- /dev/null
+++ b/lib/isccc/ccmsg.c
@@ -0,0 +1,235 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: ccmsg.c,v 1.10 2007/08/28 07:20:43 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/result.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <isccc/events.h>
+#include <isccc/ccmsg.h>
+
+#define CCMSG_MAGIC ISC_MAGIC('C', 'C', 'm', 's')
+#define VALID_CCMSG(foo) ISC_MAGIC_VALID(foo, CCMSG_MAGIC)
+
+static void recv_length(isc_task_t *, isc_event_t *);
+static void recv_message(isc_task_t *, isc_event_t *);
+
+
+static void
+recv_length(isc_task_t *task, isc_event_t *ev_in) {
+ isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
+ isc_event_t *dev;
+ isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
+ isc_region_t region;
+ isc_result_t result;
+
+ INSIST(VALID_CCMSG(ccmsg));
+
+ dev = &ccmsg->event;
+
+ if (ev->result != ISC_R_SUCCESS) {
+ ccmsg->result = ev->result;
+ goto send_and_free;
+ }
+
+ /*
+ * Success.
+ */
+ ccmsg->size = ntohl(ccmsg->size);
+ if (ccmsg->size == 0) {
+ ccmsg->result = ISC_R_UNEXPECTEDEND;
+ goto send_and_free;
+ }
+ if (ccmsg->size > ccmsg->maxsize) {
+ ccmsg->result = ISC_R_RANGE;
+ goto send_and_free;
+ }
+
+ region.base = isc_mem_get(ccmsg->mctx, ccmsg->size);
+ region.length = ccmsg->size;
+ if (region.base == NULL) {
+ ccmsg->result = ISC_R_NOMEMORY;
+ goto send_and_free;
+ }
+
+ isc_buffer_init(&ccmsg->buffer, region.base, region.length);
+ result = isc_socket_recv(ccmsg->sock, &region, 0,
+ task, recv_message, ccmsg);
+ if (result != ISC_R_SUCCESS) {
+ ccmsg->result = result;
+ goto send_and_free;
+ }
+
+ isc_event_free(&ev_in);
+ return;
+
+ send_and_free:
+ isc_task_send(ccmsg->task, &dev);
+ ccmsg->task = NULL;
+ isc_event_free(&ev_in);
+ return;
+}
+
+static void
+recv_message(isc_task_t *task, isc_event_t *ev_in) {
+ isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
+ isc_event_t *dev;
+ isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
+
+ (void)task;
+
+ INSIST(VALID_CCMSG(ccmsg));
+
+ dev = &ccmsg->event;
+
+ if (ev->result != ISC_R_SUCCESS) {
+ ccmsg->result = ev->result;
+ goto send_and_free;
+ }
+
+ ccmsg->result = ISC_R_SUCCESS;
+ isc_buffer_add(&ccmsg->buffer, ev->n);
+ ccmsg->address = ev->address;
+
+ send_and_free:
+ isc_task_send(ccmsg->task, &dev);
+ ccmsg->task = NULL;
+ isc_event_free(&ev_in);
+}
+
+void
+isccc_ccmsg_init(isc_mem_t *mctx, isc_socket_t *sock, isccc_ccmsg_t *ccmsg) {
+ REQUIRE(mctx != NULL);
+ REQUIRE(sock != NULL);
+ REQUIRE(ccmsg != NULL);
+
+ ccmsg->magic = CCMSG_MAGIC;
+ ccmsg->size = 0;
+ ccmsg->buffer.base = NULL;
+ ccmsg->buffer.length = 0;
+ ccmsg->maxsize = 4294967295U; /* Largest message possible. */
+ ccmsg->mctx = mctx;
+ ccmsg->sock = sock;
+ ccmsg->task = NULL; /* None yet. */
+ ccmsg->result = ISC_R_UNEXPECTED; /* None yet. */
+ /*
+ * Should probably initialize the event here, but it can wait.
+ */
+}
+
+
+void
+isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize) {
+ REQUIRE(VALID_CCMSG(ccmsg));
+
+ ccmsg->maxsize = maxsize;
+}
+
+
+isc_result_t
+isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg,
+ isc_task_t *task, isc_taskaction_t action, void *arg)
+{
+ isc_result_t result;
+ isc_region_t region;
+
+ REQUIRE(VALID_CCMSG(ccmsg));
+ REQUIRE(task != NULL);
+ REQUIRE(ccmsg->task == NULL); /* not currently in use */
+
+ if (ccmsg->buffer.base != NULL) {
+ isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
+ ccmsg->buffer.length);
+ ccmsg->buffer.base = NULL;
+ ccmsg->buffer.length = 0;
+ }
+
+ ccmsg->task = task;
+ ccmsg->action = action;
+ ccmsg->arg = arg;
+ ccmsg->result = ISC_R_UNEXPECTED; /* unknown right now */
+
+ ISC_EVENT_INIT(&ccmsg->event, sizeof(isc_event_t), 0, 0,
+ ISCCC_EVENT_CCMSG, action, arg, ccmsg,
+ NULL, NULL);
+
+ region.base = (unsigned char *)&ccmsg->size;
+ region.length = 4; /* isc_uint32_t */
+ result = isc_socket_recv(ccmsg->sock, &region, 0,
+ ccmsg->task, recv_length, ccmsg);
+
+ if (result != ISC_R_SUCCESS)
+ ccmsg->task = NULL;
+
+ return (result);
+}
+
+void
+isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg) {
+ REQUIRE(VALID_CCMSG(ccmsg));
+
+ isc_socket_cancel(ccmsg->sock, NULL, ISC_SOCKCANCEL_RECV);
+}
+
+#if 0
+void
+isccc_ccmsg_freebuffer(isccc_ccmsg_t *ccmsg) {
+ REQUIRE(VALID_CCMSG(ccmsg));
+
+ if (ccmsg->buffer.base == NULL)
+ return;
+
+ isc_mem_put(ccmsg->mctx, ccmsg->buffer.base, ccmsg->buffer.length);
+ ccmsg->buffer.base = NULL;
+ ccmsg->buffer.length = 0;
+}
+#endif
+
+void
+isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg) {
+ REQUIRE(VALID_CCMSG(ccmsg));
+
+ ccmsg->magic = 0;
+
+ if (ccmsg->buffer.base != NULL) {
+ isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
+ ccmsg->buffer.length);
+ ccmsg->buffer.base = NULL;
+ ccmsg->buffer.length = 0;
+ }
+}
diff --git a/lib/isccc/include/Makefile.in b/lib/isccc/include/Makefile.in
new file mode 100644
index 0000000..9f727c3
--- /dev/null
+++ b/lib/isccc/include/Makefile.in
@@ -0,0 +1,25 @@
+# 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:47:22 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isccc
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isccc/include/isccc/Makefile.in b/lib/isccc/include/isccc/Makefile.in
new file mode 100644
index 0000000..ae5bec7
--- /dev/null
+++ b/lib/isccc/include/isccc/Makefile.in
@@ -0,0 +1,42 @@
+# 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.7 2007/06/19 23:47:22 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @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 = alist.h base64.h cc.h ccmsg.h events.h lib.h result.h \
+ sexpr.h symtab.h symtype.h types.h util.h version.h
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isccc
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/isccc ; \
+ done
diff --git a/lib/isccc/include/isccc/alist.h b/lib/isccc/include/isccc/alist.h
new file mode 100644
index 0000000..29147a6
--- /dev/null
+++ b/lib/isccc/include/isccc/alist.h
@@ -0,0 +1,87 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: alist.h,v 1.10 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_ALIST_H
+#define ISCCC_ALIST_H 1
+
+/*! \file isccc/alist.h */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isccc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+isccc_sexpr_t *
+isccc_alist_create(void);
+
+isc_boolean_t
+isccc_alist_alistp(isccc_sexpr_t *alist);
+
+isc_boolean_t
+isccc_alist_emptyp(isccc_sexpr_t *alist);
+
+isccc_sexpr_t *
+isccc_alist_first(isccc_sexpr_t *alist);
+
+isccc_sexpr_t *
+isccc_alist_assq(isccc_sexpr_t *alist, const char *key);
+
+void
+isccc_alist_delete(isccc_sexpr_t *alist, const char *key);
+
+isccc_sexpr_t *
+isccc_alist_define(isccc_sexpr_t *alist, const char *key, isccc_sexpr_t *value);
+
+isccc_sexpr_t *
+isccc_alist_definestring(isccc_sexpr_t *alist, const char *key, const char *str);
+
+isccc_sexpr_t *
+isccc_alist_definebinary(isccc_sexpr_t *alist, const char *key, isccc_region_t *r);
+
+isccc_sexpr_t *
+isccc_alist_lookup(isccc_sexpr_t *alist, const char *key);
+
+isc_result_t
+isccc_alist_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp);
+
+isc_result_t
+isccc_alist_lookupbinary(isccc_sexpr_t *alist, const char *key, isccc_region_t **r);
+
+void
+isccc_alist_prettyprint(isccc_sexpr_t *sexpr, unsigned int indent, FILE *stream);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCC_ALIST_H */
diff --git a/lib/isccc/include/isccc/base64.h b/lib/isccc/include/isccc/base64.h
new file mode 100644
index 0000000..795b044
--- /dev/null
+++ b/lib/isccc/include/isccc/base64.h
@@ -0,0 +1,85 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: base64.h,v 1.10 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_BASE64_H
+#define ISCCC_BASE64_H 1
+
+/*! \file isccc/base64.h */
+
+#include <isc/lang.h>
+#include <isccc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/***
+ *** Functions
+ ***/
+
+isc_result_t
+isccc_base64_encode(isccc_region_t *source, int wordlength,
+ const char *wordbreak, isccc_region_t *target);
+/*%<
+ * Convert data into base64 encoded text.
+ *
+ * Notes:
+ *\li The base64 encoded text in 'target' will be divided into
+ * words of at most 'wordlength' characters, separated by
+ * the 'wordbreak' string. No parentheses will surround
+ * the text.
+ *
+ * Requires:
+ *\li 'source' is a region containing binary data.
+ *\li 'target' is a text region containing available space.
+ *\li 'wordbreak' points to a null-terminated string of
+ * zero or more whitespace characters.
+ */
+
+isc_result_t
+isccc_base64_decode(const char *cstr, isccc_region_t *target);
+/*%<
+ * Decode a null-terminated base64 string.
+ *
+ * Requires:
+ *\li 'cstr' is non-null.
+ *\li 'target' is a valid region.
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS -- the entire decoded representation of 'cstring'
+ * fit in 'target'.
+ *\li #ISC_R_BADBASE64 -- 'cstr' is not a valid base64 encoding.
+ *\li #ISC_R_NOSPACE -- 'target' is not big enough.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCC_BASE64_H */
diff --git a/lib/isccc/include/isccc/cc.h b/lib/isccc/include/isccc/cc.h
new file mode 100644
index 0000000..79393be
--- /dev/null
+++ b/lib/isccc/include/isccc/cc.h
@@ -0,0 +1,122 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: cc.h,v 1.11 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_CC_H
+#define ISCCC_CC_H 1
+
+/*! \file isccc/cc.h */
+
+#include <isc/lang.h>
+#include <isccc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*% Maximum Datagram Package */
+#define ISCCC_CC_MAXDGRAMPACKET 4096
+
+/*% Message Type String */
+#define ISCCC_CCMSGTYPE_STRING 0x00
+/*% Message Type Binary Data */
+#define ISCCC_CCMSGTYPE_BINARYDATA 0x01
+/*% Message Type Table */
+#define ISCCC_CCMSGTYPE_TABLE 0x02
+/*% Message Type List */
+#define ISCCC_CCMSGTYPE_LIST 0x03
+
+/*% Send to Wire */
+isc_result_t
+isccc_cc_towire(isccc_sexpr_t *alist, isccc_region_t *target,
+ isccc_region_t *secret);
+
+/*% Get From Wire */
+isc_result_t
+isccc_cc_fromwire(isccc_region_t *source, isccc_sexpr_t **alistp,
+ isccc_region_t *secret);
+
+/*% Create Message */
+isc_result_t
+isccc_cc_createmessage(isc_uint32_t version, const char *from, const char *to,
+ isc_uint32_t serial, isccc_time_t now,
+ isccc_time_t expires, isccc_sexpr_t **alistp);
+
+/*% Create Acknowledgment */
+isc_result_t
+isccc_cc_createack(isccc_sexpr_t *message, isc_boolean_t ok,
+ isccc_sexpr_t **ackp);
+
+/*% Is Ack? */
+isc_boolean_t
+isccc_cc_isack(isccc_sexpr_t *message);
+
+/*% Is Reply? */
+isc_boolean_t
+isccc_cc_isreply(isccc_sexpr_t *message);
+
+/*% Create Response */
+isc_result_t
+isccc_cc_createresponse(isccc_sexpr_t *message, isccc_time_t now,
+ isccc_time_t expires, isccc_sexpr_t **alistp);
+
+/*% Define String */
+isccc_sexpr_t *
+isccc_cc_definestring(isccc_sexpr_t *alist, const char *key, const char *str);
+
+/*% Define uint 32 */
+isccc_sexpr_t *
+isccc_cc_defineuint32(isccc_sexpr_t *alist, const char *key, isc_uint32_t i);
+
+/*% Lookup String */
+isc_result_t
+isccc_cc_lookupstring(isccc_sexpr_t *alist, const char *key, char **strp);
+
+/*% Lookup uint 32 */
+isc_result_t
+isccc_cc_lookupuint32(isccc_sexpr_t *alist, const char *key,
+ isc_uint32_t *uintp);
+
+/*% Create Symbol Table */
+isc_result_t
+isccc_cc_createsymtab(isccc_symtab_t **symtabp);
+
+/*% Clean up Symbol Table */
+void
+isccc_cc_cleansymtab(isccc_symtab_t *symtab, isccc_time_t now);
+
+/*% Check for Duplicates */
+isc_result_t
+isccc_cc_checkdup(isccc_symtab_t *symtab, isccc_sexpr_t *message,
+ isccc_time_t now);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCC_CC_H */
diff --git a/lib/isccc/include/isccc/ccmsg.h b/lib/isccc/include/isccc/ccmsg.h
new file mode 100644
index 0000000..e25aa51
--- /dev/null
+++ b/lib/isccc/include/isccc/ccmsg.h
@@ -0,0 +1,148 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: ccmsg.h,v 1.11 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_CCMSG_H
+#define ISCCC_CCMSG_H 1
+
+/*! \file isccc/ccmsg.h */
+
+#include <isc/buffer.h>
+#include <isc/lang.h>
+#include <isc/socket.h>
+
+/*% ISCCC Message Structure */
+typedef struct isccc_ccmsg {
+ /* private (don't touch!) */
+ unsigned int magic;
+ isc_uint32_t size;
+ isc_buffer_t buffer;
+ unsigned int maxsize;
+ isc_mem_t *mctx;
+ isc_socket_t *sock;
+ isc_task_t *task;
+ isc_taskaction_t action;
+ void *arg;
+ isc_event_t event;
+ /* public (read-only) */
+ isc_result_t result;
+ isc_sockaddr_t address;
+} isccc_ccmsg_t;
+
+ISC_LANG_BEGINDECLS
+
+void
+isccc_ccmsg_init(isc_mem_t *mctx, isc_socket_t *sock, isccc_ccmsg_t *ccmsg);
+/*%
+ * Associate a cc message state with a given memory context and
+ * TCP socket.
+ *
+ * Requires:
+ *
+ *\li "mctx" and "sock" be non-NULL and valid types.
+ *
+ *\li "sock" be a read/write TCP socket.
+ *
+ *\li "ccmsg" be non-NULL and an uninitialized or invalidated structure.
+ *
+ * Ensures:
+ *
+ *\li "ccmsg" is a valid structure.
+ */
+
+void
+isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize);
+/*%
+ * Set the maximum packet size to "maxsize"
+ *
+ * Requires:
+ *
+ *\li "ccmsg" be valid.
+ *
+ *\li 512 <= "maxsize" <= 4294967296
+ */
+
+isc_result_t
+isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg,
+ isc_task_t *task, isc_taskaction_t action, void *arg);
+/*%
+ * Schedule an event to be delivered when a command channel message is
+ * readable, or when an error occurs on the socket.
+ *
+ * Requires:
+ *
+ *\li "ccmsg" be valid.
+ *
+ *\li "task", "taskaction", and "arg" be valid.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS -- no error
+ *\li Anything that the isc_socket_recv() call can return. XXXMLG
+ *
+ * Notes:
+ *
+ *\li The event delivered is a fully generic event. It will contain no
+ * actual data. The sender will be a pointer to the isccc_ccmsg_t.
+ * The result code inside that structure should be checked to see
+ * what the final result was.
+ */
+
+void
+isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg);
+/*%
+ * Cancel a readmessage() call. The event will still be posted with a
+ * CANCELED result code.
+ *
+ * Requires:
+ *
+ *\li "ccmsg" be valid.
+ */
+
+void
+isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg);
+/*%
+ * Clean up all allocated state, and invalidate the structure.
+ *
+ * Requires:
+ *
+ *\li "ccmsg" be valid.
+ *
+ * Ensures:
+ *
+ *\li "ccmsg" is invalidated and disassociated with all memory contexts,
+ * sockets, etc.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCC_CCMSG_H */
diff --git a/lib/isccc/include/isccc/events.h b/lib/isccc/include/isccc/events.h
new file mode 100644
index 0000000..a3e1470
--- /dev/null
+++ b/lib/isccc/include/isccc/events.h
@@ -0,0 +1,50 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: events.h,v 1.10 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_EVENTS_H
+#define ISCCC_EVENTS_H 1
+
+/*! \file isccc/events.h */
+
+#include <isc/eventclass.h>
+
+/*%
+ * Registry of ISCCC event numbers.
+ */
+
+#define ISCCC_EVENT_CCMSG (ISC_EVENTCLASS_ISCCC + 0)
+
+#define ISCCC_EVENT_FIRSTEVENT (ISC_EVENTCLASS_ISCCC + 0)
+#define ISCCC_EVENT_LASTEVENT (ISC_EVENTCLASS_ISCCC + 65535)
+
+#endif /* ISCCC_EVENTS_H */
diff --git a/lib/isccc/include/isccc/lib.h b/lib/isccc/include/isccc/lib.h
new file mode 100644
index 0000000..de74666
--- /dev/null
+++ b/lib/isccc/include/isccc/lib.h
@@ -0,0 +1,55 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: lib.h,v 1.11 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_LIB_H
+#define ISCCC_LIB_H 1
+
+/*! \file isccc/lib.h */
+
+#include <isc/types.h>
+#include <isc/lang.h>
+
+ISC_LANG_BEGINDECLS
+
+LIBISCCC_EXTERNAL_DATA extern isc_msgcat_t *isccc_msgcat;
+
+void
+isccc_lib_initmsgcat(void);
+/*%
+ * Initialize the ISCCC library's message catalog, isccc_msgcat, if it
+ * has not already been initialized.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCC_LIB_H */
diff --git a/lib/isccc/include/isccc/result.h b/lib/isccc/include/isccc/result.h
new file mode 100644
index 0000000..2d54969
--- /dev/null
+++ b/lib/isccc/include/isccc/result.h
@@ -0,0 +1,73 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: result.h,v 1.12 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_RESULT_H
+#define ISCCC_RESULT_H 1
+
+/*! \file isccc/result.h */
+
+#include <isc/lang.h>
+#include <isc/resultclass.h>
+#include <isc/result.h>
+
+#include <isccc/types.h>
+
+/*% Unknown Version */
+#define ISCCC_R_UNKNOWNVERSION (ISC_RESULTCLASS_ISCCC + 0)
+/*% Syntax Error */
+#define ISCCC_R_SYNTAX (ISC_RESULTCLASS_ISCCC + 1)
+/*% Bad Authorization */
+#define ISCCC_R_BADAUTH (ISC_RESULTCLASS_ISCCC + 2)
+/*% Expired */
+#define ISCCC_R_EXPIRED (ISC_RESULTCLASS_ISCCC + 3)
+/*% Clock Skew */
+#define ISCCC_R_CLOCKSKEW (ISC_RESULTCLASS_ISCCC + 4)
+/*% Duplicate */
+#define ISCCC_R_DUPLICATE (ISC_RESULTCLASS_ISCCC + 5)
+
+#define ISCCC_R_NRESULTS 6 /*%< Number of results */
+
+ISC_LANG_BEGINDECLS
+
+const char *
+isccc_result_totext(isc_result_t result);
+/*%
+ * Convert a isccc_result_t into a string message describing the result.
+ */
+
+void
+isccc_result_register(void);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCC_RESULT_H */
diff --git a/lib/isccc/include/isccc/sexpr.h b/lib/isccc/include/isccc/sexpr.h
new file mode 100644
index 0000000..6112631
--- /dev/null
+++ b/lib/isccc/include/isccc/sexpr.h
@@ -0,0 +1,124 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: sexpr.h,v 1.11 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_SEXPR_H
+#define ISCCC_SEXPR_H 1
+
+/*! \file isccc/sexpr.h */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isccc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*% dotted pair structure */
+struct isccc_dottedpair {
+ isccc_sexpr_t *car;
+ isccc_sexpr_t *cdr;
+};
+
+/*% iscc_sexpr structure */
+struct isccc_sexpr {
+ unsigned int type;
+ union {
+ char * as_string;
+ isccc_dottedpair_t as_dottedpair;
+ isccc_region_t as_region;
+ } value;
+};
+
+#define ISCCC_SEXPRTYPE_NONE 0x00 /*%< Illegal. */
+#define ISCCC_SEXPRTYPE_T 0x01
+#define ISCCC_SEXPRTYPE_STRING 0x02
+#define ISCCC_SEXPRTYPE_DOTTEDPAIR 0x03
+#define ISCCC_SEXPRTYPE_BINARY 0x04
+
+#define ISCCC_SEXPR_CAR(s) (s)->value.as_dottedpair.car
+#define ISCCC_SEXPR_CDR(s) (s)->value.as_dottedpair.cdr
+
+isccc_sexpr_t *
+isccc_sexpr_cons(isccc_sexpr_t *car, isccc_sexpr_t *cdr);
+
+isccc_sexpr_t *
+isccc_sexpr_tconst(void);
+
+isccc_sexpr_t *
+isccc_sexpr_fromstring(const char *str);
+
+isccc_sexpr_t *
+isccc_sexpr_frombinary(const isccc_region_t *region);
+
+void
+isccc_sexpr_free(isccc_sexpr_t **sexprp);
+
+void
+isccc_sexpr_print(isccc_sexpr_t *sexpr, FILE *stream);
+
+isccc_sexpr_t *
+isccc_sexpr_car(isccc_sexpr_t *list);
+
+isccc_sexpr_t *
+isccc_sexpr_cdr(isccc_sexpr_t *list);
+
+void
+isccc_sexpr_setcar(isccc_sexpr_t *pair, isccc_sexpr_t *car);
+
+void
+isccc_sexpr_setcdr(isccc_sexpr_t *pair, isccc_sexpr_t *cdr);
+
+isccc_sexpr_t *
+isccc_sexpr_addtolist(isccc_sexpr_t **l1p, isccc_sexpr_t *l2);
+
+isc_boolean_t
+isccc_sexpr_listp(isccc_sexpr_t *sexpr);
+
+isc_boolean_t
+isccc_sexpr_emptyp(isccc_sexpr_t *sexpr);
+
+isc_boolean_t
+isccc_sexpr_stringp(isccc_sexpr_t *sexpr);
+
+isc_boolean_t
+isccc_sexpr_binaryp(isccc_sexpr_t *sexpr);
+
+char *
+isccc_sexpr_tostring(isccc_sexpr_t *sexpr);
+
+isccc_region_t *
+isccc_sexpr_tobinary(isccc_sexpr_t *sexpr);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCC_SEXPR_H */
diff --git a/lib/isccc/include/isccc/symtab.h b/lib/isccc/include/isccc/symtab.h
new file mode 100644
index 0000000..77a188a
--- /dev/null
+++ b/lib/isccc/include/isccc/symtab.h
@@ -0,0 +1,135 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: symtab.h,v 1.10 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_SYMTAB_H
+#define ISCCC_SYMTAB_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isccc/symtab.h
+ * \brief
+ * Provides a simple memory-based symbol table.
+ *
+ * Keys are C strings. A type may be specified when looking up,
+ * defining, or undefining. A type value of 0 means "match any type";
+ * any other value will only match the given type.
+ *
+ * It's possible that a client will attempt to define a <key, type,
+ * value> tuple when a tuple with the given key and type already
+ * exists in the table. What to do in this case is specified by the
+ * client. Possible policies are:
+ *
+ *\li isccc_symexists_reject Disallow the define, returning #ISC_R_EXISTS
+ *\li isccc_symexists_replace Replace the old value with the new. The
+ * undefine action (if provided) will be called
+ * with the old <key, type, value> tuple.
+ *\li isccc_symexists_add Add the new tuple, leaving the old tuple in
+ * the table. Subsequent lookups will retrieve
+ * the most-recently-defined tuple.
+ *
+ * A lookup of a key using type 0 will return the most-recently
+ * defined symbol with that key. An undefine of a key using type 0
+ * will undefine the most-recently defined symbol with that key.
+ * Trying to define a key with type 0 is illegal.
+ *
+ * The symbol table library does not make a copy the key field, so the
+ * caller must ensure that any key it passes to isccc_symtab_define()
+ * will not change until it calls isccc_symtab_undefine() or
+ * isccc_symtab_destroy().
+ *
+ * A user-specified action will be called (if provided) when a symbol
+ * is undefined. It can be used to free memory associated with keys
+ * and/or values.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isccc/types.h>
+
+/***
+ *** Symbol Tables.
+ ***/
+
+typedef union isccc_symvalue {
+ void * as_pointer;
+ int as_integer;
+ unsigned int as_uinteger;
+} isccc_symvalue_t;
+
+typedef void (*isccc_symtabundefaction_t)(char *key, unsigned int type,
+ isccc_symvalue_t value, void *userarg);
+
+typedef isc_boolean_t (*isccc_symtabforeachaction_t)(char *key,
+ unsigned int type,
+ isccc_symvalue_t value,
+ void *userarg);
+
+typedef enum {
+ isccc_symexists_reject = 0,
+ isccc_symexists_replace = 1,
+ isccc_symexists_add = 2
+} isccc_symexists_t;
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isccc_symtab_create(unsigned int size,
+ isccc_symtabundefaction_t undefine_action, void *undefine_arg,
+ isc_boolean_t case_sensitive, isccc_symtab_t **symtabp);
+
+void
+isccc_symtab_destroy(isccc_symtab_t **symtabp);
+
+isc_result_t
+isccc_symtab_lookup(isccc_symtab_t *symtab, const char *key, unsigned int type,
+ isccc_symvalue_t *value);
+
+isc_result_t
+isccc_symtab_define(isccc_symtab_t *symtab, char *key, unsigned int type,
+ isccc_symvalue_t value, isccc_symexists_t exists_policy);
+
+isc_result_t
+isccc_symtab_undefine(isccc_symtab_t *symtab, const char *key, unsigned int type);
+
+void
+isccc_symtab_foreach(isccc_symtab_t *symtab, isccc_symtabforeachaction_t action,
+ void *arg);
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCC_SYMTAB_H */
diff --git a/lib/isccc/include/isccc/symtype.h b/lib/isccc/include/isccc/symtype.h
new file mode 100644
index 0000000..c8e6868
--- /dev/null
+++ b/lib/isccc/include/isccc/symtype.h
@@ -0,0 +1,44 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: symtype.h,v 1.10 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_SYMTYPE_H
+#define ISCCC_SYMTYPE_H 1
+
+/*! \file isccc/symtype.h */
+
+#define ISCCC_SYMTYPE_ZONESTATS 0x0001
+#define ISCCC_SYMTYPE_CCDUP 0x0002
+#define ISCCC_SYMTYPE_TELLSERVICE 0x0003
+#define ISCCC_SYMTYPE_TELLRESPONSE 0x0004
+
+#endif /* ISCCC_SYMTYPE_H */
diff --git a/lib/isccc/include/isccc/types.h b/lib/isccc/include/isccc/types.h
new file mode 100644
index 0000000..fd5c9f3
--- /dev/null
+++ b/lib/isccc/include/isccc/types.h
@@ -0,0 +1,59 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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.10 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_TYPES_H
+#define ISCCC_TYPES_H 1
+
+/*! \file isccc/types.h */
+
+#include <isc/boolean.h>
+#include <isc/int.h>
+#include <isc/result.h>
+
+/*% isccc_time_t typedef */
+typedef isc_uint32_t isccc_time_t;
+
+/*% isccc_sexpr_t typedef */
+typedef struct isccc_sexpr isccc_sexpr_t;
+/*% isccc_dottedpair_t typedef */
+typedef struct isccc_dottedpair isccc_dottedpair_t;
+/*% isccc_symtab_t typedef */
+typedef struct isccc_symtab isccc_symtab_t;
+
+/*% iscc region structure */
+typedef struct isccc_region {
+ unsigned char * rstart;
+ unsigned char * rend;
+} isccc_region_t;
+
+#endif /* ISCCC_TYPES_H */
diff --git a/lib/isccc/include/isccc/util.h b/lib/isccc/include/isccc/util.h
new file mode 100644
index 0000000..2e36b6e
--- /dev/null
+++ b/lib/isccc/include/isccc/util.h
@@ -0,0 +1,225 @@
+/*
+ * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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.11 2007/08/28 07:20:43 tbox Exp $ */
+
+#ifndef ISCCC_UTIL_H
+#define ISCCC_UTIL_H 1
+
+#include <isc/util.h>
+
+/*! \file isccc/util.h
+ * \brief
+ * Macros for dealing with unaligned numbers.
+ *
+ * \note no side effects are allowed when invoking these macros!
+ */
+
+#define GET8(v, w) \
+ do { \
+ v = *w; \
+ w++; \
+ } while (0)
+
+#define GET16(v, w) \
+ do { \
+ v = (unsigned int)w[0] << 8; \
+ v |= (unsigned int)w[1]; \
+ w += 2; \
+ } while (0)
+
+#define GET24(v, w) \
+ do { \
+ v = (unsigned int)w[0] << 16; \
+ v |= (unsigned int)w[1] << 8; \
+ v |= (unsigned int)w[2]; \
+ w += 3; \
+ } while (0)
+
+#define GET32(v, w) \
+ do { \
+ v = (unsigned int)w[0] << 24; \
+ v |= (unsigned int)w[1] << 16; \
+ v |= (unsigned int)w[2] << 8; \
+ v |= (unsigned int)w[3]; \
+ w += 4; \
+ } while (0)
+
+#define GET64(v, w) \
+ do { \
+ v = (isc_uint64_t)w[0] << 56; \
+ v |= (isc_uint64_t)w[1] << 48; \
+ v |= (isc_uint64_t)w[2] << 40; \
+ v |= (isc_uint64_t)w[3] << 32; \
+ v |= (isc_uint64_t)w[4] << 24; \
+ v |= (isc_uint64_t)w[5] << 16; \
+ v |= (isc_uint64_t)w[6] << 8; \
+ v |= (isc_uint64_t)w[7]; \
+ w += 8; \
+ } while (0)
+
+#define GETC16(v, w, d) \
+ do { \
+ GET8(v, w); \
+ if (v == 0) \
+ d = ISCCC_TRUE; \
+ else { \
+ d = ISCCC_FALSE; \
+ if (v == 255) \
+ GET16(v, w); \
+ } \
+ } while (0)
+
+#define GETC32(v, w) \
+ do { \
+ GET24(v, w); \
+ if (v == 0xffffffu) \
+ GET32(v, w); \
+ } while (0)
+
+#define GET_OFFSET(v, w) GET32(v, w)
+
+#define GET_MEM(v, c, w) \
+ do { \
+ memcpy(v, w, c); \
+ w += c; \
+ } while (0)
+
+#define GET_TYPE(v, w) \
+ do { \
+ GET8(v, w); \
+ if (v > 127) { \
+ if (v < 255) \
+ v = ((v & 0x7f) << 16) | ISCCC_RDATATYPE_SIG; \
+ else \
+ GET32(v, w); \
+ } \
+ } while (0)
+
+#define PUT8(v, w) \
+ do { \
+ *w = (v & 0x000000ffU); \
+ w++; \
+ } while (0)
+
+#define PUT16(v, w) \
+ do { \
+ w[0] = (v & 0x0000ff00U) >> 8; \
+ w[1] = (v & 0x000000ffU); \
+ w += 2; \
+ } while (0)
+
+#define PUT24(v, w) \
+ do { \
+ w[0] = (v & 0x00ff0000U) >> 16; \
+ w[1] = (v & 0x0000ff00U) >> 8; \
+ w[2] = (v & 0x000000ffU); \
+ w += 3; \
+ } while (0)
+
+#define PUT32(v, w) \
+ do { \
+ w[0] = (v & 0xff000000U) >> 24; \
+ w[1] = (v & 0x00ff0000U) >> 16; \
+ w[2] = (v & 0x0000ff00U) >> 8; \
+ w[3] = (v & 0x000000ffU); \
+ w += 4; \
+ } while (0)
+
+#define PUT64(v, w) \
+ do { \
+ w[0] = (v & 0xff00000000000000ULL) >> 56; \
+ w[1] = (v & 0x00ff000000000000ULL) >> 48; \
+ w[2] = (v & 0x0000ff0000000000ULL) >> 40; \
+ w[3] = (v & 0x000000ff00000000ULL) >> 32; \
+ w[4] = (v & 0x00000000ff000000ULL) >> 24; \
+ w[5] = (v & 0x0000000000ff0000ULL) >> 16; \
+ w[6] = (v & 0x000000000000ff00ULL) >> 8; \
+ w[7] = (v & 0x00000000000000ffULL); \
+ w += 8; \
+ } while (0)
+
+#define PUTC16(v, w) \
+ do { \
+ if (v > 0 && v < 255) \
+ PUT8(v, w); \
+ else { \
+ PUT8(255, w); \
+ PUT16(v, w); \
+ } \
+ } while (0)
+
+#define PUTC32(v, w) \
+ do { \
+ if (v < 0xffffffU) \
+ PUT24(v, w); \
+ else { \
+ PUT24(0xffffffU, w); \
+ PUT32(v, w); \
+ } \
+ } while (0)
+
+#define PUT_OFFSET(v, w) PUT32(v, w)
+
+#include <string.h>
+
+#define PUT_MEM(s, c, w) \
+ do { \
+ memcpy(w, s, c); \
+ w += c; \
+ } while (0)
+
+/*
+ * Regions.
+ */
+#define REGION_SIZE(r) ((unsigned int)((r).rend - (r).rstart))
+#define REGION_EMPTY(r) ((r).rstart == (r).rend)
+#define REGION_FROMSTRING(r, s) do { \
+ (r).rstart = (unsigned char *)s; \
+ (r).rend = (r).rstart + strlen(s); \
+} while (0)
+
+/*%
+ * Use this to remove the const qualifier of a variable to assign it to
+ * a non-const variable or pass it as a non-const function argument ...
+ * but only when you are sure it won't then be changed!
+ * This is necessary to sometimes shut up some compilers
+ * (as with gcc -Wcast-qual) when there is just no other good way to avoid the
+ * situation.
+ */
+#define DE_CONST(konst, var) \
+ do { \
+ union { const void *k; void *v; } _u; \
+ _u.k = konst; \
+ var = _u.v; \
+ } while (0)
+
+#endif /* ISCCC_UTIL_H */
diff --git a/lib/isccc/include/isccc/version.h b/lib/isccc/include/isccc/version.h
new file mode 100644
index 0000000..869316c
--- /dev/null
+++ b/lib/isccc/include/isccc/version.h
@@ -0,0 +1,28 @@
+/*
+ * 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: version.h,v 1.9 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file isccc/version.h */
+
+#include <isc/platform.h>
+
+LIBISCCC_EXTERNAL_DATA extern const char isccc_version[];
+
+LIBISCCC_EXTERNAL_DATA extern const unsigned int isccc_libinterface;
+LIBISCCC_EXTERNAL_DATA extern const unsigned int isccc_librevision;
+LIBISCCC_EXTERNAL_DATA extern const unsigned int isccc_libage;
diff --git a/lib/isccc/lib.c b/lib/isccc/lib.c
new file mode 100644
index 0000000..17170f5
--- /dev/null
+++ b/lib/isccc/lib.c
@@ -0,0 +1,78 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: lib.c,v 1.9 2007/08/28 07:20:43 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <stddef.h>
+
+#include <isc/once.h>
+#include <isc/msgcat.h>
+#include <isc/util.h>
+
+#include <isccc/lib.h>
+
+/***
+ *** Globals
+ ***/
+
+LIBISCCC_EXTERNAL_DATA isc_msgcat_t * isccc_msgcat = NULL;
+
+
+/***
+ *** Private
+ ***/
+
+static isc_once_t msgcat_once = ISC_ONCE_INIT;
+
+
+/***
+ *** Functions
+ ***/
+
+static void
+open_msgcat(void) {
+ isc_msgcat_open("libisccc.cat", &isccc_msgcat);
+}
+
+void
+isccc_lib_initmsgcat(void) {
+
+ /*
+ * Initialize the DNS library's message catalog, isccc_msgcat, if it
+ * has not already been initialized.
+ */
+
+ RUNTIME_CHECK(isc_once_do(&msgcat_once, open_msgcat) == ISC_R_SUCCESS);
+}
diff --git a/lib/isccc/result.c b/lib/isccc/result.c
new file mode 100644
index 0000000..cbedc16
--- /dev/null
+++ b/lib/isccc/result.c
@@ -0,0 +1,85 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: result.c,v 1.10 2007/08/28 07:20:43 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/once.h>
+#include <isc/util.h>
+
+#include <isccc/result.h>
+#include <isccc/lib.h>
+
+static const char *text[ISCCC_R_NRESULTS] = {
+ "unknown version", /* 1 */
+ "syntax error", /* 2 */
+ "bad auth", /* 3 */
+ "expired", /* 4 */
+ "clock skew", /* 5 */
+ "duplicate" /* 6 */
+};
+
+#define ISCCC_RESULT_RESULTSET 2
+
+static isc_once_t once = ISC_ONCE_INIT;
+
+static void
+initialize_action(void) {
+ isc_result_t result;
+
+ result = isc_result_register(ISC_RESULTCLASS_ISCCC, ISCCC_R_NRESULTS,
+ text, isccc_msgcat,
+ ISCCC_RESULT_RESULTSET);
+ if (result != ISC_R_SUCCESS)
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_result_register() failed: %u", result);
+}
+
+static void
+initialize(void) {
+ isccc_lib_initmsgcat();
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+}
+
+const char *
+isccc_result_totext(isc_result_t result) {
+ initialize();
+
+ return (isc_result_totext(result));
+}
+
+void
+isccc_result_register(void) {
+ initialize();
+}
diff --git a/lib/isccc/sexpr.c b/lib/isccc/sexpr.c
new file mode 100644
index 0000000..e96536d
--- /dev/null
+++ b/lib/isccc/sexpr.c
@@ -0,0 +1,325 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: sexpr.c,v 1.9 2007/08/28 07:20:43 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/assertions.h>
+#include <isccc/sexpr.h>
+#include <isccc/util.h>
+
+static isccc_sexpr_t sexpr_t = { ISCCC_SEXPRTYPE_T, { NULL } };
+
+#define CAR(s) (s)->value.as_dottedpair.car
+#define CDR(s) (s)->value.as_dottedpair.cdr
+
+isccc_sexpr_t *
+isccc_sexpr_cons(isccc_sexpr_t *car, isccc_sexpr_t *cdr)
+{
+ isccc_sexpr_t *sexpr;
+
+ sexpr = malloc(sizeof(*sexpr));
+ if (sexpr == NULL)
+ return (NULL);
+ sexpr->type = ISCCC_SEXPRTYPE_DOTTEDPAIR;
+ CAR(sexpr) = car;
+ CDR(sexpr) = cdr;
+
+ return (sexpr);
+}
+
+isccc_sexpr_t *
+isccc_sexpr_tconst(void)
+{
+ return (&sexpr_t);
+}
+
+isccc_sexpr_t *
+isccc_sexpr_fromstring(const char *str)
+{
+ isccc_sexpr_t *sexpr;
+
+ sexpr = malloc(sizeof(*sexpr));
+ if (sexpr == NULL)
+ return (NULL);
+ sexpr->type = ISCCC_SEXPRTYPE_STRING;
+ sexpr->value.as_string = strdup(str);
+ if (sexpr->value.as_string == NULL) {
+ free(sexpr);
+ return (NULL);
+ }
+
+ return (sexpr);
+}
+
+isccc_sexpr_t *
+isccc_sexpr_frombinary(const isccc_region_t *region)
+{
+ isccc_sexpr_t *sexpr;
+ unsigned int region_size;
+
+ sexpr = malloc(sizeof(*sexpr));
+ if (sexpr == NULL)
+ return (NULL);
+ sexpr->type = ISCCC_SEXPRTYPE_BINARY;
+ region_size = REGION_SIZE(*region);
+ /*
+ * We add an extra byte when we malloc so we can NUL terminate
+ * the binary data. This allows the caller to use it as a C
+ * string. It's up to the caller to ensure this is safe. We don't
+ * add 1 to the length of the binary region, because the NUL is
+ * not part of the binary data.
+ */
+ sexpr->value.as_region.rstart = malloc(region_size + 1);
+ if (sexpr->value.as_region.rstart == NULL) {
+ free(sexpr);
+ return (NULL);
+ }
+ sexpr->value.as_region.rend = sexpr->value.as_region.rstart +
+ region_size;
+ memcpy(sexpr->value.as_region.rstart, region->rstart, region_size);
+ /*
+ * NUL terminate.
+ */
+ sexpr->value.as_region.rstart[region_size] = '\0';
+
+ return (sexpr);
+}
+
+void
+isccc_sexpr_free(isccc_sexpr_t **sexprp)
+{
+ isccc_sexpr_t *sexpr;
+ isccc_sexpr_t *item;
+
+ sexpr = *sexprp;
+ if (sexpr == NULL)
+ return;
+ switch (sexpr->type) {
+ case ISCCC_SEXPRTYPE_STRING:
+ free(sexpr->value.as_string);
+ break;
+ case ISCCC_SEXPRTYPE_DOTTEDPAIR:
+ item = CAR(sexpr);
+ if (item != NULL)
+ isccc_sexpr_free(&item);
+ item = CDR(sexpr);
+ if (item != NULL)
+ isccc_sexpr_free(&item);
+ break;
+ case ISCCC_SEXPRTYPE_BINARY:
+ free(sexpr->value.as_region.rstart);
+ break;
+ }
+ free(sexpr);
+
+ *sexprp = NULL;
+}
+
+static isc_boolean_t
+printable(isccc_region_t *r)
+{
+ unsigned char *curr;
+
+ curr = r->rstart;
+ while (curr != r->rend) {
+ if (!isprint(*curr))
+ return (ISC_FALSE);
+ curr++;
+ }
+
+ return (ISC_TRUE);
+}
+
+void
+isccc_sexpr_print(isccc_sexpr_t *sexpr, FILE *stream)
+{
+ isccc_sexpr_t *cdr;
+ unsigned int size, i;
+ unsigned char *curr;
+
+ if (sexpr == NULL) {
+ fprintf(stream, "nil");
+ return;
+ }
+
+ switch (sexpr->type) {
+ case ISCCC_SEXPRTYPE_T:
+ fprintf(stream, "t");
+ break;
+ case ISCCC_SEXPRTYPE_STRING:
+ fprintf(stream, "\"%s\"", sexpr->value.as_string);
+ break;
+ case ISCCC_SEXPRTYPE_DOTTEDPAIR:
+ fprintf(stream, "(");
+ do {
+ isccc_sexpr_print(CAR(sexpr), stream);
+ cdr = CDR(sexpr);
+ if (cdr != NULL) {
+ fprintf(stream, " ");
+ if (cdr->type != ISCCC_SEXPRTYPE_DOTTEDPAIR) {
+ fprintf(stream, ". ");
+ isccc_sexpr_print(cdr, stream);
+ cdr = NULL;
+ }
+ }
+ sexpr = cdr;
+ } while (sexpr != NULL);
+ fprintf(stream, ")");
+ break;
+ case ISCCC_SEXPRTYPE_BINARY:
+ size = REGION_SIZE(sexpr->value.as_region);
+ curr = sexpr->value.as_region.rstart;
+ if (printable(&sexpr->value.as_region)) {
+ fprintf(stream, "'%.*s'", (int)size, curr);
+ } else {
+ fprintf(stream, "0x");
+ for (i = 0; i < size; i++)
+ fprintf(stream, "%02x", *curr++);
+ }
+ break;
+ default:
+ INSIST(0);
+ }
+}
+
+isccc_sexpr_t *
+isccc_sexpr_car(isccc_sexpr_t *list)
+{
+ REQUIRE(list->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
+
+ return (CAR(list));
+}
+
+isccc_sexpr_t *
+isccc_sexpr_cdr(isccc_sexpr_t *list)
+{
+ REQUIRE(list->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
+
+ return (CDR(list));
+}
+
+void
+isccc_sexpr_setcar(isccc_sexpr_t *pair, isccc_sexpr_t *car)
+{
+ REQUIRE(pair->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
+
+ CAR(pair) = car;
+}
+
+void
+isccc_sexpr_setcdr(isccc_sexpr_t *pair, isccc_sexpr_t *cdr)
+{
+ REQUIRE(pair->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
+
+ CDR(pair) = cdr;
+}
+
+isccc_sexpr_t *
+isccc_sexpr_addtolist(isccc_sexpr_t **l1p, isccc_sexpr_t *l2)
+{
+ isccc_sexpr_t *last, *elt, *l1;
+
+ REQUIRE(l1p != NULL);
+ l1 = *l1p;
+ REQUIRE(l1 == NULL || l1->type == ISCCC_SEXPRTYPE_DOTTEDPAIR);
+
+ elt = isccc_sexpr_cons(l2, NULL);
+ if (elt == NULL)
+ return (NULL);
+ if (l1 == NULL) {
+ *l1p = elt;
+ return (elt);
+ }
+ for (last = l1; CDR(last) != NULL; last = CDR(last))
+ /* Nothing */;
+ CDR(last) = elt;
+
+ return (elt);
+}
+
+isc_boolean_t
+isccc_sexpr_listp(isccc_sexpr_t *sexpr)
+{
+ if (sexpr == NULL || sexpr->type == ISCCC_SEXPRTYPE_DOTTEDPAIR)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+isccc_sexpr_emptyp(isccc_sexpr_t *sexpr)
+{
+ if (sexpr == NULL)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+isccc_sexpr_stringp(isccc_sexpr_t *sexpr)
+{
+ if (sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_STRING)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+isc_boolean_t
+isccc_sexpr_binaryp(isccc_sexpr_t *sexpr)
+{
+ if (sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_BINARY)
+ return (ISC_TRUE);
+ return (ISC_FALSE);
+}
+
+char *
+isccc_sexpr_tostring(isccc_sexpr_t *sexpr)
+{
+ REQUIRE(sexpr != NULL &&
+ (sexpr->type == ISCCC_SEXPRTYPE_STRING ||
+ sexpr->type == ISCCC_SEXPRTYPE_BINARY));
+
+ if (sexpr->type == ISCCC_SEXPRTYPE_BINARY)
+ return ((char *)sexpr->value.as_region.rstart);
+ return (sexpr->value.as_string);
+}
+
+isccc_region_t *
+isccc_sexpr_tobinary(isccc_sexpr_t *sexpr)
+{
+ REQUIRE(sexpr != NULL && sexpr->type == ISCCC_SEXPRTYPE_BINARY);
+ return (&sexpr->value.as_region);
+}
diff --git a/lib/isccc/symtab.c b/lib/isccc/symtab.c
new file mode 100644
index 0000000..d7ae687
--- /dev/null
+++ b/lib/isccc/symtab.c
@@ -0,0 +1,293 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions 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 AND NOMINUM 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.
+ *
+ * Portions Copyright (C) 2001 Nominum, Inc.
+ *
+ * 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 AND NOMINUM 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: symtab.c,v 1.11 2007/09/13 04:45:18 each Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <isc/assertions.h>
+#include <isc/magic.h>
+#include <isc/string.h>
+
+#include <isccc/result.h>
+#include <isccc/symtab.h>
+#include <isccc/util.h>
+
+typedef struct elt {
+ char * key;
+ unsigned int type;
+ isccc_symvalue_t value;
+ ISC_LINK(struct elt) link;
+} elt_t;
+
+typedef ISC_LIST(elt_t) eltlist_t;
+
+#define SYMTAB_MAGIC ISC_MAGIC('S', 'y', 'm', 'T')
+#define VALID_SYMTAB(st) ISC_MAGIC_VALID(st, SYMTAB_MAGIC)
+
+struct isccc_symtab {
+ unsigned int magic;
+ unsigned int size;
+ eltlist_t * table;
+ isccc_symtabundefaction_t undefine_action;
+ void * undefine_arg;
+ isc_boolean_t case_sensitive;
+};
+
+isc_result_t
+isccc_symtab_create(unsigned int size,
+ isccc_symtabundefaction_t undefine_action,
+ void *undefine_arg,
+ isc_boolean_t case_sensitive,
+ isccc_symtab_t **symtabp)
+{
+ isccc_symtab_t *symtab;
+ unsigned int i;
+
+ REQUIRE(symtabp != NULL && *symtabp == NULL);
+ REQUIRE(size > 0); /* Should be prime. */
+
+ symtab = malloc(sizeof(*symtab));
+ if (symtab == NULL)
+ return (ISC_R_NOMEMORY);
+ symtab->table = malloc(size * sizeof(eltlist_t));
+ if (symtab->table == NULL) {
+ free(symtab);
+ return (ISC_R_NOMEMORY);
+ }
+ for (i = 0; i < size; i++)
+ ISC_LIST_INIT(symtab->table[i]);
+ symtab->size = size;
+ symtab->undefine_action = undefine_action;
+ symtab->undefine_arg = undefine_arg;
+ symtab->case_sensitive = case_sensitive;
+ symtab->magic = SYMTAB_MAGIC;
+
+ *symtabp = symtab;
+
+ return (ISC_R_SUCCESS);
+}
+
+static inline void
+free_elt(isccc_symtab_t *symtab, unsigned int bucket, elt_t *elt) {
+ ISC_LIST_UNLINK(symtab->table[bucket], elt, link);
+ if (symtab->undefine_action != NULL)
+ (symtab->undefine_action)(elt->key, elt->type, elt->value,
+ symtab->undefine_arg);
+ free(elt);
+}
+
+void
+isccc_symtab_destroy(isccc_symtab_t **symtabp) {
+ isccc_symtab_t *symtab;
+ unsigned int i;
+ elt_t *elt, *nelt;
+
+ REQUIRE(symtabp != NULL);
+ symtab = *symtabp;
+ REQUIRE(VALID_SYMTAB(symtab));
+
+ for (i = 0; i < symtab->size; i++) {
+ for (elt = ISC_LIST_HEAD(symtab->table[i]);
+ elt != NULL;
+ elt = nelt) {
+ nelt = ISC_LIST_NEXT(elt, link);
+ free_elt(symtab, i, elt);
+ }
+ }
+ free(symtab->table);
+ symtab->magic = 0;
+ free(symtab);
+
+ *symtabp = NULL;
+}
+
+static inline unsigned int
+hash(const char *key, isc_boolean_t case_sensitive) {
+ const char *s;
+ unsigned int h = 0;
+ unsigned int g;
+ int c;
+
+ /*
+ * P. J. Weinberger's hash function, adapted from p. 436 of
+ * _Compilers: Principles, Techniques, and Tools_, Aho, Sethi
+ * and Ullman, Addison-Wesley, 1986, ISBN 0-201-10088-6.
+ */
+
+ if (case_sensitive) {
+ for (s = key; *s != '\0'; s++) {
+ h = ( h << 4 ) + *s;
+ if ((g = ( h & 0xf0000000 )) != 0) {
+ h = h ^ (g >> 24);
+ h = h ^ g;
+ }
+ }
+ } else {
+ for (s = key; *s != '\0'; s++) {
+ c = *s;
+ c = tolower((unsigned char)c);
+ h = ( h << 4 ) + c;
+ if ((g = ( h & 0xf0000000 )) != 0) {
+ h = h ^ (g >> 24);
+ h = h ^ g;
+ }
+ }
+ }
+
+ return (h);
+}
+
+#define FIND(s, k, t, b, e) \
+ b = hash((k), (s)->case_sensitive) % (s)->size; \
+ if ((s)->case_sensitive) { \
+ for (e = ISC_LIST_HEAD((s)->table[b]); \
+ e != NULL; \
+ e = ISC_LIST_NEXT(e, link)) { \
+ if (((t) == 0 || e->type == (t)) && \
+ strcmp(e->key, (k)) == 0) \
+ break; \
+ } \
+ } else { \
+ for (e = ISC_LIST_HEAD((s)->table[b]); \
+ e != NULL; \
+ e = ISC_LIST_NEXT(e, link)) { \
+ if (((t) == 0 || e->type == (t)) && \
+ strcasecmp(e->key, (k)) == 0) \
+ break; \
+ } \
+ }
+
+isc_result_t
+isccc_symtab_lookup(isccc_symtab_t *symtab, const char *key, unsigned int type,
+ isccc_symvalue_t *value)
+{
+ unsigned int bucket;
+ elt_t *elt;
+
+ REQUIRE(VALID_SYMTAB(symtab));
+ REQUIRE(key != NULL);
+
+ FIND(symtab, key, type, bucket, elt);
+
+ if (elt == NULL)
+ return (ISC_R_NOTFOUND);
+
+ if (value != NULL)
+ *value = elt->value;
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isccc_symtab_define(isccc_symtab_t *symtab, char *key, unsigned int type,
+ isccc_symvalue_t value, isccc_symexists_t exists_policy)
+{
+ unsigned int bucket;
+ elt_t *elt;
+
+ REQUIRE(VALID_SYMTAB(symtab));
+ REQUIRE(key != NULL);
+ REQUIRE(type != 0);
+
+ FIND(symtab, key, type, bucket, elt);
+
+ if (exists_policy != isccc_symexists_add && elt != NULL) {
+ if (exists_policy == isccc_symexists_reject)
+ return (ISC_R_EXISTS);
+ INSIST(exists_policy == isccc_symexists_replace);
+ ISC_LIST_UNLINK(symtab->table[bucket], elt, link);
+ if (symtab->undefine_action != NULL)
+ (symtab->undefine_action)(elt->key, elt->type,
+ elt->value,
+ symtab->undefine_arg);
+ } else {
+ elt = malloc(sizeof(*elt));
+ if (elt == NULL)
+ return (ISC_R_NOMEMORY);
+ ISC_LINK_INIT(elt, link);
+ }
+
+ elt->key = key;
+ elt->type = type;
+ elt->value = value;
+
+ /*
+ * We prepend so that the most recent definition will be found.
+ */
+ ISC_LIST_PREPEND(symtab->table[bucket], elt, link);
+
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isccc_symtab_undefine(isccc_symtab_t *symtab, const char *key, unsigned int type) {
+ unsigned int bucket;
+ elt_t *elt;
+
+ REQUIRE(VALID_SYMTAB(symtab));
+ REQUIRE(key != NULL);
+
+ FIND(symtab, key, type, bucket, elt);
+
+ if (elt == NULL)
+ return (ISC_R_NOTFOUND);
+
+ free_elt(symtab, bucket, elt);
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isccc_symtab_foreach(isccc_symtab_t *symtab, isccc_symtabforeachaction_t action,
+ void *arg)
+{
+ unsigned int i;
+ elt_t *elt, *nelt;
+
+ REQUIRE(VALID_SYMTAB(symtab));
+ REQUIRE(action != NULL);
+
+ for (i = 0; i < symtab->size; i++) {
+ for (elt = ISC_LIST_HEAD(symtab->table[i]);
+ elt != NULL;
+ elt = nelt) {
+ nelt = ISC_LIST_NEXT(elt, link);
+ if ((action)(elt->key, elt->type, elt->value, arg))
+ free_elt(symtab, i, elt);
+ }
+ }
+}
diff --git a/lib/isccc/version.c b/lib/isccc/version.c
new file mode 100644
index 0000000..c9d9124
--- /dev/null
+++ b/lib/isccc/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: version.c,v 1.7 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+#include <isccc/version.h>
+
+const char isccc_version[] = VERSION;
+
+const unsigned int isccc_libinterface = LIBINTERFACE;
+const unsigned int isccc_librevision = LIBREVISION;
+const unsigned int isccc_libage = LIBAGE;
diff --git a/lib/isccc/win32/DLLMain.c b/lib/isccc/win32/DLLMain.c
new file mode 100644
index 0000000..2918c1f
--- /dev/null
+++ b/lib/isccc/win32/DLLMain.c
@@ -0,0 +1,57 @@
+/*
+ * 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: DLLMain.c,v 1.6 2007/06/18 23:47:50 tbox Exp $ */
+
+#include <windows.h>
+#include <signal.h>
+
+/*
+ * Called when we enter the DLL
+ */
+__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason) {
+ /*
+ * The DLL is loading due to process
+ * initialization or a call to LoadLibrary.
+ */
+ case DLL_PROCESS_ATTACH:
+ break;
+
+ /* The attached process creates a new thread. */
+ case DLL_THREAD_ATTACH:
+ break;
+
+ /* The thread of the attached process terminates. */
+ case DLL_THREAD_DETACH:
+ break;
+
+ /*
+ * The DLL is unloading from a process due to
+ * process termination or a call to FreeLibrary.
+ */
+ case DLL_PROCESS_DETACH:
+ break;
+
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
diff --git a/lib/isccc/win32/libisccc.def b/lib/isccc/win32/libisccc.def
new file mode 100644
index 0000000..5d32a52
--- /dev/null
+++ b/lib/isccc/win32/libisccc.def
@@ -0,0 +1,66 @@
+LIBRARY libisccc
+
+; Exported Functions
+EXPORTS
+
+isccc_alist_create
+isccc_alist_alistp
+isccc_alist_emptyp
+isccc_alist_first
+isccc_alist_assq
+isccc_alist_delete
+isccc_alist_define
+isccc_alist_definestring
+isccc_alist_definebinary
+isccc_alist_lookup
+isccc_alist_lookupstring
+isccc_alist_lookupbinary
+isccc_alist_prettyprint
+isccc_base64_encode
+isccc_base64_decode
+isccc_cc_towire
+isccc_cc_fromwire
+isccc_cc_createmessage
+isccc_cc_createack
+isccc_cc_isack
+isccc_cc_isreply
+isccc_cc_createresponse
+isccc_cc_definestring
+isccc_cc_defineuint32
+isccc_cc_lookupstring
+isccc_cc_lookupuint32
+isccc_cc_createsymtab
+isccc_cc_cleansymtab
+isccc_cc_checkdup
+isccc_ccmsg_init
+isccc_ccmsg_setmaxsize
+isccc_ccmsg_readmessage
+isccc_ccmsg_cancelread
+isccc_ccmsg_invalidate
+isccc_lib_initmsgcat
+isccc_result_totext
+isccc_result_register
+isccc_sexpr_cons
+isccc_sexpr_tconst
+isccc_sexpr_fromstring
+isccc_sexpr_frombinary
+isccc_sexpr_free
+isccc_sexpr_print
+isccc_sexpr_car
+isccc_sexpr_cdr
+isccc_sexpr_setcar
+isccc_sexpr_setcdr
+isccc_sexpr_addtolist
+isccc_sexpr_listp
+isccc_sexpr_emptyp
+isccc_sexpr_stringp
+isccc_sexpr_binaryp
+isccc_sexpr_tostring
+isccc_sexpr_tobinary
+isccc_symtab_destroy
+isccc_symtab_create
+isccc_symtab_destroy
+isccc_symtab_lookup
+isccc_symtab_define
+isccc_symtab_undefine
+isccc_symtab_foreach
diff --git a/lib/isccc/win32/libisccc.dsp b/lib/isccc/win32/libisccc.dsp
new file mode 100644
index 0000000..b7d0a0f
--- /dev/null
+++ b/lib/isccc/win32/libisccc.dsp
@@ -0,0 +1,197 @@
+# Microsoft Developer Studio Project File - Name="libisccc" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libisccc - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libisccc.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libisccc.mak" CFG="libisccc - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisccc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libisccc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "libisccc_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../..../lib/dns/sec/openssl/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBISCCC_EXPORTS" /YX /FD /c
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../isc/win32/Release/libisc.lib /nologo /dll /machine:I386 /out:"../../../Build/Release/libisccc.dll"
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "libisccc_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../..../lib/dns/sec/openssl/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBISCCC_EXPORTS" /FR /YX /FD /GZ /c
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../isc/win32/debug/libisc.lib /nologo /dll /debug /machine:I386 /out:"../../../Build/Debug/libisccc.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "libisccc - Win32 Release"
+# Name "libisccc - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\alist.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\base64.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\cc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\ccmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\DLLMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\result.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\sexpr.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\symtab.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\isccc\alist.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\base64.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\cc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\ccmsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\events.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\lib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\result.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\sexpr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\symtab.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\symtype.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccc\util.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=.\libisccc.def
+# End Source File
+# End Target
+# End Project
diff --git a/lib/isccc/win32/libisccc.dsw b/lib/isccc/win32/libisccc.dsw
new file mode 100644
index 0000000..28eaa74
--- /dev/null
+++ b/lib/isccc/win32/libisccc.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libisccc"=.\libisccc.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/isccc/win32/libisccc.mak b/lib/isccc/win32/libisccc.mak
new file mode 100644
index 0000000..9e578cb
--- /dev/null
+++ b/lib/isccc/win32/libisccc.mak
@@ -0,0 +1,540 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on libisccc.dsp
+!IF "$(CFG)" == ""
+CFG=libisccc - Win32 Release
+!MESSAGE No configuration specified. Defaulting to libisccc - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "libisccc - Win32 Release" && "$(CFG)" != "libisccc - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libisccc.mak" CFG="libisccc - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisccc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libisccc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\libisccc.dll"
+
+!ELSE
+
+ALL : "libisc - Win32 Release" "..\..\..\Build\Release\libisccc.dll"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\alist.obj"
+ -@erase "$(INTDIR)\base64.obj"
+ -@erase "$(INTDIR)\cc.obj"
+ -@erase "$(INTDIR)\ccmsg.obj"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\lib.obj"
+ -@erase "$(INTDIR)\result.obj"
+ -@erase "$(INTDIR)\sexpr.obj"
+ -@erase "$(INTDIR)\symtab.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(OUTDIR)\libisccc.exp"
+ -@erase "$(OUTDIR)\libisccc.lib"
+ -@erase "..\..\..\Build\Release\libisccc.dll"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../..../lib/dns/sec/openssl/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBISCCC_EXPORTS" /Fp"$(INTDIR)\libisccc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisccc.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../isc/win32/Release/libisc.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libisccc.pdb" /machine:I386 /def:".\libisccc.def" /out:"../../../Build/Release/libisccc.dll" /implib:"$(OUTDIR)\libisccc.lib"
+DEF_FILE= \
+ ".\libisccc.def"
+LINK32_OBJS= \
+ "$(INTDIR)\alist.obj" \
+ "$(INTDIR)\base64.obj" \
+ "$(INTDIR)\cc.obj" \
+ "$(INTDIR)\ccmsg.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\lib.obj" \
+ "$(INTDIR)\result.obj" \
+ "$(INTDIR)\sexpr.obj" \
+ "$(INTDIR)\symtab.obj" \
+ "$(INTDIR)\version.obj" \
+ "..\..\isc\win32\Release\libisc.lib"
+
+"..\..\..\Build\Release\libisccc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\libisccc.dll" "$(OUTDIR)\libisccc.bsc"
+
+!ELSE
+
+ALL : "libisc - Win32 Debug" "..\..\..\Build\Debug\libisccc.dll" "$(OUTDIR)\libisccc.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\alist.obj"
+ -@erase "$(INTDIR)\alist.sbr"
+ -@erase "$(INTDIR)\base64.obj"
+ -@erase "$(INTDIR)\base64.sbr"
+ -@erase "$(INTDIR)\cc.obj"
+ -@erase "$(INTDIR)\cc.sbr"
+ -@erase "$(INTDIR)\ccmsg.obj"
+ -@erase "$(INTDIR)\ccmsg.sbr"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\DLLMain.sbr"
+ -@erase "$(INTDIR)\lib.obj"
+ -@erase "$(INTDIR)\lib.sbr"
+ -@erase "$(INTDIR)\result.obj"
+ -@erase "$(INTDIR)\result.sbr"
+ -@erase "$(INTDIR)\sexpr.obj"
+ -@erase "$(INTDIR)\sexpr.sbr"
+ -@erase "$(INTDIR)\symtab.obj"
+ -@erase "$(INTDIR)\symtab.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(INTDIR)\version.sbr"
+ -@erase "$(OUTDIR)\libisccc.bsc"
+ -@erase "$(OUTDIR)\libisccc.exp"
+ -@erase "$(OUTDIR)\libisccc.lib"
+ -@erase "$(OUTDIR)\libisccc.pdb"
+ -@erase "..\..\..\Build\Debug\libisccc.dll"
+ -@erase "..\..\..\Build\Debug\libisccc.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../..../lib/dns/sec/openssl/include" /D "_DEBUG" /D "WIN32" /D "__STDC__" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBISCCC_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libisccc.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisccc.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\alist.sbr" \
+ "$(INTDIR)\base64.sbr" \
+ "$(INTDIR)\cc.sbr" \
+ "$(INTDIR)\ccmsg.sbr" \
+ "$(INTDIR)\DLLMain.sbr" \
+ "$(INTDIR)\lib.sbr" \
+ "$(INTDIR)\result.sbr" \
+ "$(INTDIR)\sexpr.sbr" \
+ "$(INTDIR)\symtab.sbr" \
+ "$(INTDIR)\version.sbr"
+
+"$(OUTDIR)\libisccc.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../isc/win32/debug/libisc.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libisccc.pdb" /debug /machine:I386 /def:".\libisccc.def" /out:"../../../Build/Debug/libisccc.dll" /implib:"$(OUTDIR)\libisccc.lib" /pdbtype:sept
+DEF_FILE= \
+ ".\libisccc.def"
+LINK32_OBJS= \
+ "$(INTDIR)\alist.obj" \
+ "$(INTDIR)\base64.obj" \
+ "$(INTDIR)\cc.obj" \
+ "$(INTDIR)\ccmsg.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\lib.obj" \
+ "$(INTDIR)\result.obj" \
+ "$(INTDIR)\sexpr.obj" \
+ "$(INTDIR)\symtab.obj" \
+ "$(INTDIR)\version.obj" \
+ "..\..\isc\win32\Debug\libisc.lib"
+
+"..\..\..\Build\Debug\libisccc.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("libisccc.dep")
+!INCLUDE "libisccc.dep"
+!ELSE
+!MESSAGE Warning: cannot find "libisccc.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "libisccc - Win32 Release" || "$(CFG)" == "libisccc - Win32 Debug"
+SOURCE=..\alist.c
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+
+"$(INTDIR)\alist.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+
+"$(INTDIR)\alist.obj" "$(INTDIR)\alist.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\base64.c
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+
+"$(INTDIR)\base64.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+
+"$(INTDIR)\base64.obj" "$(INTDIR)\base64.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\cc.c
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+
+"$(INTDIR)\cc.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+
+"$(INTDIR)\cc.obj" "$(INTDIR)\cc.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\ccmsg.c
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+
+"$(INTDIR)\ccmsg.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+
+"$(INTDIR)\ccmsg.obj" "$(INTDIR)\ccmsg.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\DLLMain.c
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+
+"$(INTDIR)\DLLMain.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+
+"$(INTDIR)\DLLMain.obj" "$(INTDIR)\DLLMain.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\lib.c
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+
+"$(INTDIR)\lib.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+
+"$(INTDIR)\lib.obj" "$(INTDIR)\lib.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\result.c
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+
+"$(INTDIR)\result.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+
+"$(INTDIR)\result.obj" "$(INTDIR)\result.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\sexpr.c
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+
+"$(INTDIR)\sexpr.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+
+"$(INTDIR)\sexpr.obj" "$(INTDIR)\sexpr.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\symtab.c
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+
+"$(INTDIR)\symtab.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+
+"$(INTDIR)\symtab.obj" "$(INTDIR)\symtab.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\version.c
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+
+"$(INTDIR)\version.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+
+"$(INTDIR)\version.obj" "$(INTDIR)\version.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+!IF "$(CFG)" == "libisccc - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\isccc\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\isccc\win32"
+
+!ELSEIF "$(CFG)" == "libisccc - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\isccc\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\isccc\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/lib/isccc/win32/version.c b/lib/isccc/win32/version.c
new file mode 100644
index 0000000..43f12ad
--- /dev/null
+++ b/lib/isccc/win32/version.c
@@ -0,0 +1,28 @@
+/*
+ * 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: version.c,v 1.7 2007/06/19 23:47:22 tbox Exp $ */
+
+#include <versions.h>
+
+#include <isccc/version.h>
+
+LIBISCCC_EXTERNAL_DATA const char isccc_version[] = VERSION;
+
+LIBISCCC_EXTERNAL_DATA const unsigned int isccc_libinterface = LIBINTERFACE;
+LIBISCCC_EXTERNAL_DATA const unsigned int isccc_librevision = LIBREVISION;
+LIBISCCC_EXTERNAL_DATA const unsigned int isccc_libage = LIBAGE;
diff --git a/lib/isccfg/Makefile.in b/lib/isccfg/Makefile.in
new file mode 100644
index 0000000..6dcacdd
--- /dev/null
+++ b/lib/isccfg/Makefile.in
@@ -0,0 +1,83 @@
+# 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: Makefile.in,v 1.18 2007/06/19 23:47:22 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@LIBISCCFG_API@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I. ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES}
+
+CDEFINES = @USE_DLZ@
+CWARNINGS =
+
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCCCLIBS = ../../lib/isccc/libisccc.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@
+ISCCFGLIBS = ../../lib/cfg/libisccfg.@A@
+
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCCFGDEPLIBS = libisccfg.@A@
+
+LIBS = @LIBS@
+
+SUBDIRS = include
+
+# Alphabetically
+OBJS = aclconf.@O@ log.@O@ namedconf.@O@ parser.@O@ version.@O@
+
+# Alphabetically
+SRCS = aclconf.c log.c namedconf.c parser.c version.c
+
+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
+
+libisccfg.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+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}
+
+timestamp: libisccfg.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libisccfg.@A@ ${DESTDIR}${libdir}
+
+clean distclean::
+ rm -f libisccfg.@A@ timestamp
diff --git a/lib/isccfg/aclconf.c b/lib/isccfg/aclconf.c
new file mode 100644
index 0000000..b0472bc
--- /dev/null
+++ b/lib/isccfg/aclconf.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2002 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: aclconf.c,v 1.22 2008/10/24 02:28:55 each Exp $ */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/string.h> /* Required for HP/UX (and others?) */
+#include <isc/util.h>
+
+#include <isccfg/namedconf.h>
+#include <isccfg/aclconf.h>
+
+#include <dns/acl.h>
+#include <dns/iptable.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+
+#define LOOP_MAGIC ISC_MAGIC('L','O','O','P')
+
+void
+cfg_aclconfctx_init(cfg_aclconfctx_t *ctx) {
+ ISC_LIST_INIT(ctx->named_acl_cache);
+}
+
+void
+cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx) {
+ dns_acl_t *dacl, *next;
+
+ for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
+ dacl != NULL;
+ dacl = next)
+ {
+ next = ISC_LIST_NEXT(dacl, nextincache);
+ dns_acl_detach(&dacl);
+ }
+}
+
+/*
+ * Find the definition of the named acl whose name is "name".
+ */
+static isc_result_t
+get_acl_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) {
+ isc_result_t result;
+ const cfg_obj_t *acls = NULL;
+ const cfg_listelt_t *elt;
+
+ result = cfg_map_get(cctx, "acl", &acls);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ for (elt = cfg_list_first(acls);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ const cfg_obj_t *acl = cfg_listelt_value(elt);
+ const char *aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
+ if (strcasecmp(aclname, name) == 0) {
+ if (ret != NULL) {
+ *ret = cfg_tuple_get(acl, "value");
+ }
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+convert_named_acl(const cfg_obj_t *nameobj, const cfg_obj_t *cctx,
+ isc_log_t *lctx, cfg_aclconfctx_t *ctx,
+ isc_mem_t *mctx, unsigned int nest_level,
+ dns_acl_t **target)
+{
+ isc_result_t result;
+ const cfg_obj_t *cacl = NULL;
+ dns_acl_t *dacl;
+ dns_acl_t loop;
+ const char *aclname = cfg_obj_asstring(nameobj);
+
+ /* Look for an already-converted version. */
+ for (dacl = ISC_LIST_HEAD(ctx->named_acl_cache);
+ dacl != NULL;
+ dacl = ISC_LIST_NEXT(dacl, nextincache))
+ {
+ if (strcasecmp(aclname, dacl->name) == 0) {
+ if (ISC_MAGIC_VALID(dacl, LOOP_MAGIC)) {
+ cfg_obj_log(nameobj, lctx, ISC_LOG_ERROR,
+ "acl loop detected: %s", aclname);
+ return (ISC_R_FAILURE);
+ }
+ dns_acl_attach(dacl, target);
+ return (ISC_R_SUCCESS);
+ }
+ }
+ /* Not yet converted. Convert now. */
+ result = get_acl_def(cctx, aclname, &cacl);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(nameobj, lctx, ISC_LOG_WARNING,
+ "undefined ACL '%s'", aclname);
+ return (result);
+ }
+ /*
+ * Add a loop detection element.
+ */
+ memset(&loop, 0, sizeof(loop));
+ ISC_LINK_INIT(&loop, nextincache);
+ DE_CONST(aclname, loop.name);
+ loop.magic = LOOP_MAGIC;
+ ISC_LIST_APPEND(ctx->named_acl_cache, &loop, nextincache);
+ result = cfg_acl_fromconfig(cacl, cctx, lctx, ctx, mctx,
+ nest_level, &dacl);
+ ISC_LIST_UNLINK(ctx->named_acl_cache, &loop, nextincache);
+ loop.magic = 0;
+ loop.name = NULL;
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dacl->name = isc_mem_strdup(dacl->mctx, aclname);
+ if (dacl->name == NULL)
+ return (ISC_R_NOMEMORY);
+ ISC_LIST_APPEND(ctx->named_acl_cache, dacl, nextincache);
+ dns_acl_attach(dacl, target);
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+convert_keyname(const cfg_obj_t *keyobj, isc_log_t *lctx, isc_mem_t *mctx,
+ dns_name_t *dnsname)
+{
+ isc_result_t result;
+ isc_buffer_t buf;
+ dns_fixedname_t fixname;
+ unsigned int keylen;
+ const char *txtname = cfg_obj_asstring(keyobj);
+
+ keylen = strlen(txtname);
+ isc_buffer_init(&buf, txtname, keylen);
+ isc_buffer_add(&buf, keylen);
+ dns_fixedname_init(&fixname);
+ result = dns_name_fromtext(dns_fixedname_name(&fixname), &buf,
+ dns_rootname, ISC_FALSE, NULL);
+ if (result != ISC_R_SUCCESS) {
+ cfg_obj_log(keyobj, lctx, ISC_LOG_WARNING,
+ "key name '%s' is not a valid domain name",
+ txtname);
+ return (result);
+ }
+ return (dns_name_dup(dns_fixedname_name(&fixname), mctx, dnsname));
+}
+
+/*
+ * Recursively pre-parse an ACL definition to find the total number
+ * of non-IP-prefix elements (localhost, localnets, key) in all nested
+ * ACLs, so that the parent will have enough space allocated for the
+ * elements table after all the nested ACLs have been merged in to the
+ * parent.
+ */
+static int
+count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx)
+{
+ const cfg_listelt_t *elt;
+ const cfg_obj_t *cacl = NULL;
+ isc_result_t result;
+ int n = 0;
+
+ for (elt = cfg_list_first(caml);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ const cfg_obj_t *ce = cfg_listelt_value(elt);
+
+ /* negated element; just get the value. */
+ if (cfg_obj_istuple(ce))
+ ce = cfg_tuple_get(ce, "value");
+
+ if (cfg_obj_istype(ce, &cfg_type_keyref)) {
+ n++;
+ } else if (cfg_obj_islist(ce)) {
+ n += count_acl_elements(ce, cctx);
+ } else if (cfg_obj_isstring(ce)) {
+ const char *name = cfg_obj_asstring(ce);
+ if (strcasecmp(name, "localhost") == 0 ||
+ strcasecmp(name, "localnets") == 0) {
+ n++;
+ } else if (strcasecmp(name, "any") != 0 &&
+ strcasecmp(name, "none") != 0) {
+ result = get_acl_def(cctx, name, &cacl);
+ if (result == ISC_R_SUCCESS)
+ n += count_acl_elements(cacl, cctx) + 1;
+ }
+ }
+ }
+
+ return n;
+}
+
+isc_result_t
+cfg_acl_fromconfig(const cfg_obj_t *caml,
+ const cfg_obj_t *cctx,
+ isc_log_t *lctx,
+ cfg_aclconfctx_t *ctx,
+ isc_mem_t *mctx,
+ unsigned int nest_level,
+ dns_acl_t **target)
+{
+ isc_result_t result;
+ dns_acl_t *dacl = NULL, *inneracl = NULL;
+ dns_aclelement_t *de;
+ const cfg_listelt_t *elt;
+ dns_iptable_t *iptab;
+ int new_nest_level = 0;
+
+ if (nest_level != 0)
+ new_nest_level = nest_level - 1;
+
+ REQUIRE(target != NULL);
+ REQUIRE(*target == NULL || DNS_ACL_VALID(*target));
+
+ if (*target != NULL) {
+ /*
+ * If target already points to an ACL, then we're being
+ * called recursively to configure a nested ACL. The
+ * nested ACL's contents should just be absorbed into its
+ * parent ACL.
+ */
+ dns_acl_attach(*target, &dacl);
+ dns_acl_detach(target);
+ } else {
+ /*
+ * Need to allocate a new ACL structure. Count the items
+ * in the ACL definition that will require space in the
+ * elemnts table. (Note that if nest_level is nonzero,
+ * *everything* goes in the elements table.)
+ */
+ int nelem;
+
+ if (nest_level == 0)
+ nelem = count_acl_elements(caml, cctx);
+ else
+ nelem = cfg_list_length(caml, ISC_FALSE);
+
+ result = dns_acl_create(mctx, nelem, &dacl);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ de = dacl->elements;
+ for (elt = cfg_list_first(caml);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ const cfg_obj_t *ce = cfg_listelt_value(elt);
+ isc_boolean_t neg;
+
+ if (cfg_obj_istuple(ce)) {
+ /* This must be a negated element. */
+ ce = cfg_tuple_get(ce, "value");
+ neg = ISC_TRUE;
+ dacl->has_negatives = ISC_TRUE;
+ } else
+ neg = ISC_FALSE;
+
+ /*
+ * If nest_level is nonzero, then every element is
+ * to be stored as a separate, nested ACL rather than
+ * merged into the main iptable.
+ */
+ iptab = dacl->iptable;
+
+ if (nest_level != 0) {
+ result = dns_acl_create(mctx,
+ cfg_list_length(ce, ISC_FALSE),
+ &de->nestedacl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ iptab = de->nestedacl->iptable;
+ }
+
+ if (cfg_obj_isnetprefix(ce)) {
+ /* Network prefix */
+ isc_netaddr_t addr;
+ unsigned int bitlen;
+
+ cfg_obj_asnetprefix(ce, &addr, &bitlen);
+
+ /*
+ * If nesting ACLs (nest_level != 0), we negate
+ * the nestedacl element, not the iptable entry.
+ */
+ result = dns_iptable_addprefix(iptab, &addr, bitlen,
+ ISC_TF(nest_level != 0 || !neg));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ if (nest_level > 0) {
+ de->type = dns_aclelementtype_nestedacl;
+ de->negative = neg;
+ } else
+ continue;
+ } else if (cfg_obj_islist(ce)) {
+ /*
+ * If we're nesting ACLs, put the nested
+ * ACL onto the elements list; otherwise
+ * merge it into *this* ACL. We nest ACLs
+ * in two cases: 1) sortlist, 2) if the
+ * nested ACL contains negated members.
+ */
+ if (inneracl != NULL)
+ dns_acl_detach(&inneracl);
+ result = cfg_acl_fromconfig(ce, cctx, lctx,
+ ctx, mctx, new_nest_level,
+ &inneracl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+nested_acl:
+ if (nest_level > 0 || inneracl->has_negatives) {
+ de->type = dns_aclelementtype_nestedacl;
+ de->negative = neg;
+ if (de->nestedacl != NULL)
+ dns_acl_detach(&de->nestedacl);
+ dns_acl_attach(inneracl,
+ &de->nestedacl);
+ dns_acl_detach(&inneracl);
+ /* Fall through. */
+ } else {
+ dns_acl_merge(dacl, inneracl,
+ ISC_TF(!neg));
+ de += inneracl->length; /* elements added */
+ dns_acl_detach(&inneracl);
+ continue;
+ }
+ } else if (cfg_obj_istype(ce, &cfg_type_keyref)) {
+ /* Key name. */
+ de->type = dns_aclelementtype_keyname;
+ de->negative = neg;
+ dns_name_init(&de->keyname, NULL);
+ result = convert_keyname(ce, lctx, mctx,
+ &de->keyname);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ } else if (cfg_obj_isstring(ce)) {
+ /* ACL name. */
+ const char *name = cfg_obj_asstring(ce);
+ if (strcasecmp(name, "any") == 0) {
+ /* Iptable entry with zero bit length. */
+ result = dns_iptable_addprefix(iptab, NULL, 0,
+ ISC_TF(nest_level != 0 || !neg));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ if (nest_level != 0) {
+ de->type = dns_aclelementtype_nestedacl;
+ de->negative = neg;
+ } else
+ continue;
+ } else if (strcasecmp(name, "none") == 0) {
+ /* none == !any */
+ /*
+ * We don't unconditional set
+ * dacl->has_negatives and
+ * de->negative to true so we can handle
+ * "!none;".
+ */
+ result = dns_iptable_addprefix(iptab, NULL, 0,
+ ISC_TF(nest_level != 0 || neg));
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ if (!neg)
+ dacl->has_negatives = !neg;
+
+ if (nest_level != 0) {
+ de->type = dns_aclelementtype_nestedacl;
+ de->negative = !neg;
+ } else
+ continue;
+ } else if (strcasecmp(name, "localhost") == 0) {
+ de->type = dns_aclelementtype_localhost;
+ de->negative = neg;
+ } else if (strcasecmp(name, "localnets") == 0) {
+ de->type = dns_aclelementtype_localnets;
+ de->negative = neg;
+ } else {
+ if (inneracl != NULL)
+ dns_acl_detach(&inneracl);
+ result = convert_named_acl(ce, cctx, lctx, ctx,
+ mctx, new_nest_level,
+ &inneracl);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ goto nested_acl;
+ }
+ } else {
+ cfg_obj_log(ce, lctx, ISC_LOG_WARNING,
+ "address match list contains "
+ "unsupported element type");
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ /*
+ * This should only be reached for localhost, localnets
+ * and keyname elements, and nested ACLs if nest_level is
+ * nonzero (i.e., in sortlists).
+ */
+ if (de->nestedacl != NULL &&
+ de->type != dns_aclelementtype_nestedacl)
+ dns_acl_detach(&de->nestedacl);
+
+ dacl->node_count++;
+ de->node_num = dacl->node_count;
+
+ dacl->length++;
+ de++;
+ INSIST(dacl->length <= dacl->alloc);
+ }
+
+ dns_acl_attach(dacl, target);
+ result = ISC_R_SUCCESS;
+
+ cleanup:
+ if (inneracl != NULL)
+ dns_acl_detach(&inneracl);
+ dns_acl_detach(&dacl);
+ return (result);
+}
diff --git a/lib/isccfg/api b/lib/isccfg/api
new file mode 100644
index 0000000..8459d42
--- /dev/null
+++ b/lib/isccfg/api
@@ -0,0 +1,3 @@
+LIBINTERFACE = 50
+LIBREVISION = 0
+LIBAGE = 0
diff --git a/lib/isccfg/include/Makefile.in b/lib/isccfg/include/Makefile.in
new file mode 100644
index 0000000..1f24003
--- /dev/null
+++ b/lib/isccfg/include/Makefile.in
@@ -0,0 +1,25 @@
+# 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.7 2007/06/19 23:47:22 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = isccfg
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/isccfg/include/isccfg/Makefile.in b/lib/isccfg/include/isccfg/Makefile.in
new file mode 100644
index 0000000..a6fd412
--- /dev/null
+++ b/lib/isccfg/include/isccfg/Makefile.in
@@ -0,0 +1,42 @@
+# Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2001, 2002 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.12 2007/06/19 23:47:22 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @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 = aclconf.h cfg.h grammar.h log.h namedconf.h version.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/isccfg
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/isccfg ; \
+ done
diff --git a/lib/isccfg/include/isccfg/aclconf.h b/lib/isccfg/include/isccfg/aclconf.h
new file mode 100644
index 0000000..7ad4351
--- /dev/null
+++ b/lib/isccfg/include/isccfg/aclconf.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: aclconf.h,v 1.10 2007/10/12 04:17:18 each Exp $ */
+
+#ifndef ISCCFG_ACLCONF_H
+#define ISCCFG_ACLCONF_H 1
+
+#include <isc/lang.h>
+
+#include <isccfg/cfg.h>
+
+#include <dns/types.h>
+
+typedef struct cfg_aclconfctx {
+ ISC_LIST(dns_acl_t) named_acl_cache;
+ ISC_LIST(dns_iptable_t) named_iptable_cache;
+} cfg_aclconfctx_t;
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+void
+cfg_aclconfctx_init(cfg_aclconfctx_t *ctx);
+/*
+ * Initialize an ACL configuration context.
+ */
+
+void
+cfg_aclconfctx_destroy(cfg_aclconfctx_t *ctx);
+/*
+ * Destroy an ACL configuration context.
+ */
+
+isc_result_t
+cfg_acl_fromconfig(const cfg_obj_t *caml,
+ const cfg_obj_t *cctx,
+ isc_log_t *lctx,
+ cfg_aclconfctx_t *ctx,
+ isc_mem_t *mctx,
+ unsigned int nest_level,
+ dns_acl_t **target);
+/*
+ * Construct a new dns_acl_t from configuration data in 'caml' and
+ * 'cctx'. Memory is allocated through 'mctx'.
+ *
+ * Any named ACLs referred to within 'caml' will be be converted
+ * into nested dns_acl_t objects. Multiple references to the same
+ * named ACLs will be converted into shared references to a single
+ * nested dns_acl_t object when the referring objects were created
+ * passing the same ACL configuration context 'ctx'.
+ *
+ * On success, attach '*target' to the new dns_acl_t object.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCFG_ACLCONF_H */
diff --git a/lib/isccfg/include/isccfg/cfg.h b/lib/isccfg/include/isccfg/cfg.h
new file mode 100644
index 0000000..d0ed94b
--- /dev/null
+++ b/lib/isccfg/include/isccfg/cfg.h
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: cfg.h,v 1.44 2007/10/12 04:17:18 each Exp $ */
+
+#ifndef ISCCFG_CFG_H
+#define ISCCFG_CFG_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isccfg/cfg.h
+ * \brief
+ * This is the new, table-driven, YACC-free configuration file parser.
+ */
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/types.h>
+#include <isc/list.h>
+
+
+/***
+ *** Types
+ ***/
+
+/*%
+ * A configuration parser.
+ */
+typedef struct cfg_parser cfg_parser_t;
+
+/*%
+ * A configuration type definition object. There is a single
+ * static cfg_type_t object for each data type supported by
+ * the configuration parser.
+ */
+typedef struct cfg_type cfg_type_t;
+
+/*%
+ * A configuration object. This is the basic building block of the
+ * configuration parse tree. It contains a value (which may be
+ * of one of several types) and information identifying the file
+ * and line number the value came from, for printing error
+ * messages.
+ */
+typedef struct cfg_obj cfg_obj_t;
+
+/*%
+ * A configuration object list element.
+ */
+typedef struct cfg_listelt cfg_listelt_t;
+
+/*%
+ * A callback function to be called when parsing an option
+ * that needs to be interpreted at parsing time, like
+ * "directory".
+ */
+typedef isc_result_t
+(*cfg_parsecallback_t)(const char *clausename, const cfg_obj_t *obj, void *arg);
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret);
+/*%<
+ * Create a configuration file parser. Any warning and error
+ * messages will be logged to 'lctx'.
+ *
+ * The parser object returned can be used for a single call
+ * to cfg_parse_file() or cfg_parse_buffer(). It must not
+ * be reused for parsing multiple files or buffers.
+ */
+
+void
+cfg_parser_setcallback(cfg_parser_t *pctx,
+ cfg_parsecallback_t callback,
+ void *arg);
+/*%<
+ * Make the parser call 'callback' whenever it encounters
+ * a configuration clause with the callback attribute,
+ * passing it the clause name, the clause value,
+ * and 'arg' as arguments.
+ *
+ * To restore the default of not invoking callbacks, pass
+ * callback==NULL and arg==NULL.
+ */
+
+isc_result_t
+cfg_parse_file(cfg_parser_t *pctx, const char *filename,
+ const cfg_type_t *type, cfg_obj_t **ret);
+isc_result_t
+cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer,
+ const cfg_type_t *type, cfg_obj_t **ret);
+/*%<
+ * Read a configuration containing data of type 'type'
+ * and make '*ret' point to its parse tree.
+ *
+ * The configuration is read from the file 'filename'
+ * (isc_parse_file()) or the buffer 'buffer'
+ * (isc_parse_buffer()).
+ *
+ * Returns an error if the file does not parse correctly.
+ *
+ * Requires:
+ *\li "filename" is valid.
+ *\li "mem" is valid.
+ *\li "type" is valid.
+ *\li "cfg" is non-NULL and "*cfg" is NULL.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS - success
+ *\li #ISC_R_NOMEMORY - no memory available
+ *\li #ISC_R_INVALIDFILE - file doesn't exist or is unreadable
+ *\li others - file contains errors
+ */
+
+void
+cfg_parser_destroy(cfg_parser_t **pctxp);
+/*%<
+ * Destroy a configuration parser.
+ */
+
+isc_boolean_t
+cfg_obj_isvoid(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is of void type (e.g., an optional
+ * value not specified).
+ */
+
+isc_boolean_t
+cfg_obj_ismap(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is of a map type.
+ */
+
+isc_result_t
+cfg_map_get(const cfg_obj_t *mapobj, const char* name, const cfg_obj_t **obj);
+/*%<
+ * Extract an element from a configuration object, which
+ * must be of a map type.
+ *
+ * Requires:
+ * \li 'mapobj' points to a valid configuration object of a map type.
+ * \li 'name' points to a null-terminated string.
+ * \li 'obj' is non-NULL and '*obj' is NULL.
+ *
+ * Returns:
+ * \li #ISC_R_SUCCESS - success
+ * \li #ISC_R_NOTFOUND - name not found in map
+ */
+
+const cfg_obj_t *
+cfg_map_getname(const cfg_obj_t *mapobj);
+/*%<
+ * Get the name of a named map object, like a server "key" clause.
+ *
+ * Requires:
+ * \li 'mapobj' points to a valid configuration object of a map type.
+ *
+ * Returns:
+ * \li A pointer to a configuration object naming the map object,
+ * or NULL if the map object does not have a name.
+ */
+
+isc_boolean_t
+cfg_obj_istuple(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is of a map type.
+ */
+
+const cfg_obj_t *
+cfg_tuple_get(const cfg_obj_t *tupleobj, const char *name);
+/*%<
+ * Extract an element from a configuration object, which
+ * must be of a tuple type.
+ *
+ * Requires:
+ * \li 'tupleobj' points to a valid configuration object of a tuple type.
+ * \li 'name' points to a null-terminated string naming one of the
+ *\li fields of said tuple type.
+ */
+
+isc_boolean_t
+cfg_obj_isuint32(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is of integer type.
+ */
+
+isc_uint32_t
+cfg_obj_asuint32(const cfg_obj_t *obj);
+/*%<
+ * Returns the value of a configuration object of 32-bit integer type.
+ *
+ * Requires:
+ * \li 'obj' points to a valid configuration object of 32-bit integer type.
+ *
+ * Returns:
+ * \li A 32-bit unsigned integer.
+ */
+
+isc_boolean_t
+cfg_obj_isuint64(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is of integer type.
+ */
+
+isc_uint64_t
+cfg_obj_asuint64(const cfg_obj_t *obj);
+/*%<
+ * Returns the value of a configuration object of 64-bit integer type.
+ *
+ * Requires:
+ * \li 'obj' points to a valid configuration object of 64-bit integer type.
+ *
+ * Returns:
+ * \li A 64-bit unsigned integer.
+ */
+
+isc_boolean_t
+cfg_obj_isstring(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is of string type.
+ */
+
+const char *
+cfg_obj_asstring(const cfg_obj_t *obj);
+/*%<
+ * Returns the value of a configuration object of a string type
+ * as a null-terminated string.
+ *
+ * Requires:
+ * \li 'obj' points to a valid configuration object of a string type.
+ *
+ * Returns:
+ * \li A pointer to a null terminated string.
+ */
+
+isc_boolean_t
+cfg_obj_isboolean(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is of a boolean type.
+ */
+
+isc_boolean_t
+cfg_obj_asboolean(const cfg_obj_t *obj);
+/*%<
+ * Returns the value of a configuration object of a boolean type.
+ *
+ * Requires:
+ * \li 'obj' points to a valid configuration object of a boolean type.
+ *
+ * Returns:
+ * \li A boolean value.
+ */
+
+isc_boolean_t
+cfg_obj_issockaddr(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is a socket address.
+ */
+
+const isc_sockaddr_t *
+cfg_obj_assockaddr(const cfg_obj_t *obj);
+/*%<
+ * Returns the value of a configuration object representing a socket address.
+ *
+ * Requires:
+ * \li 'obj' points to a valid configuration object of a socket address type.
+ *
+ * Returns:
+ * \li A pointer to a sockaddr. The sockaddr must be copied by the caller
+ * if necessary.
+ */
+
+isc_boolean_t
+cfg_obj_isnetprefix(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is a network prefix.
+ */
+
+void
+cfg_obj_asnetprefix(const cfg_obj_t *obj, isc_netaddr_t *netaddr,
+ unsigned int *prefixlen);
+/*%<
+ * Gets the value of a configuration object representing a network
+ * prefix. The network address is returned through 'netaddr' and the
+ * prefix length in bits through 'prefixlen'.
+ *
+ * Requires:
+ * \li 'obj' points to a valid configuration object of network prefix type.
+ *\li 'netaddr' and 'prefixlen' are non-NULL.
+ */
+
+isc_boolean_t
+cfg_obj_islist(const cfg_obj_t *obj);
+/*%<
+ * Return true iff 'obj' is of list type.
+ */
+
+const cfg_listelt_t *
+cfg_list_first(const cfg_obj_t *obj);
+/*%<
+ * Returns the first list element in a configuration object of a list type.
+ *
+ * Requires:
+ * \li 'obj' points to a valid configuration object of a list type or NULL.
+ *
+ * Returns:
+ * \li A pointer to a cfg_listelt_t representing the first list element,
+ * or NULL if the list is empty or nonexistent.
+ */
+
+const cfg_listelt_t *
+cfg_list_next(const cfg_listelt_t *elt);
+/*%<
+ * Returns the next element of a list of configuration objects.
+ *
+ * Requires:
+ * \li 'elt' points to cfg_listelt_t obtained from cfg_list_first() or
+ * a previous call to cfg_list_next().
+ *
+ * Returns:
+ * \li A pointer to a cfg_listelt_t representing the next element,
+ * or NULL if there are no more elements.
+ */
+
+unsigned int
+cfg_list_length(const cfg_obj_t *obj, isc_boolean_t recurse);
+/*%<
+ * Returns the length of a list of configure objects. If obj is
+ * not a list, returns 0. If recurse is true, add in the length of
+ * all contained lists.
+ */
+
+const cfg_obj_t *
+cfg_listelt_value(const cfg_listelt_t *elt);
+/*%<
+ * Returns the configuration object associated with cfg_listelt_t.
+ *
+ * Requires:
+ * \li 'elt' points to cfg_listelt_t obtained from cfg_list_first() or
+ * cfg_list_next().
+ *
+ * Returns:
+ * \li A non-NULL pointer to a configuration object.
+ */
+
+void
+cfg_print(const cfg_obj_t *obj,
+ void (*f)(void *closure, const char *text, int textlen),
+ void *closure);
+/*%<
+ * Print the configuration object 'obj' by repeatedly calling the
+ * function 'f', passing 'closure' and a region of text starting
+ * at 'text' and comprising 'textlen' characters.
+ */
+
+void
+cfg_print_grammar(const cfg_type_t *type,
+ void (*f)(void *closure, const char *text, int textlen),
+ void *closure);
+/*%<
+ * Print a summary of the grammar of the configuration type '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'.
+ */
+
+void cfg_obj_destroy(cfg_parser_t *pctx, cfg_obj_t **obj);
+/*%<
+ * Destroy a configuration object.
+ */
+
+void
+cfg_obj_log(const cfg_obj_t *obj, isc_log_t *lctx, int level,
+ const char *fmt, ...)
+ ISC_FORMAT_PRINTF(4, 5);
+/*%<
+ * Log a message concerning configuration object 'obj' to the logging
+ * channel of 'pctx', at log level 'level'. The message will be prefixed
+ * with the file name(s) and line number where 'obj' was defined.
+ */
+
+const char *
+cfg_obj_file(const cfg_obj_t *obj);
+/*%<
+ * Return the file that defined this object.
+ */
+
+unsigned int
+cfg_obj_line(const cfg_obj_t *obj);
+/*%<
+ * Return the line in file where this object was defined.
+ */
+
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCFG_CFG_H */
diff --git a/lib/isccfg/include/isccfg/grammar.h b/lib/isccfg/include/isccfg/grammar.h
new file mode 100644
index 0000000..f194d4c
--- /dev/null
+++ b/lib/isccfg/include/isccfg/grammar.h
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002, 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: grammar.h,v 1.17 2008/09/25 04:02:39 tbox Exp $ */
+
+#ifndef ISCCFG_GRAMMAR_H
+#define ISCCFG_GRAMMAR_H 1
+
+/*! \file isccfg/grammar.h */
+
+#include <isc/lex.h>
+#include <isc/netaddr.h>
+#include <isc/sockaddr.h>
+#include <isc/region.h>
+#include <isc/types.h>
+
+#include <isccfg/cfg.h>
+
+/*
+ * Definitions shared between the configuration parser
+ * and the grammars; not visible to users of the parser.
+ */
+
+/*% Clause may occur multiple times (e.g., "zone") */
+#define CFG_CLAUSEFLAG_MULTI 0x00000001
+/*% Clause is obsolete */
+#define CFG_CLAUSEFLAG_OBSOLETE 0x00000002
+/*% Clause is not implemented, and may never be */
+#define CFG_CLAUSEFLAG_NOTIMP 0x00000004
+/*% Clause is not implemented yet */
+#define CFG_CLAUSEFLAG_NYI 0x00000008
+/*% Default value has changed since earlier release */
+#define CFG_CLAUSEFLAG_NEWDEFAULT 0x00000010
+/*%
+ * Clause needs to be interpreted during parsing
+ * by calling a callback function, like the
+ * "directory" option.
+ */
+#define CFG_CLAUSEFLAG_CALLBACK 0x00000020
+/*% A option that is only used in testing. */
+#define CFG_CLAUSEFLAG_TESTONLY 0x00000040
+
+typedef struct cfg_clausedef cfg_clausedef_t;
+typedef struct cfg_tuplefielddef cfg_tuplefielddef_t;
+typedef struct cfg_printer cfg_printer_t;
+typedef ISC_LIST(cfg_listelt_t) cfg_list_t;
+typedef struct cfg_map cfg_map_t;
+typedef struct cfg_rep cfg_rep_t;
+
+/*
+ * Function types for configuration object methods
+ */
+
+typedef isc_result_t (*cfg_parsefunc_t)(cfg_parser_t *, const cfg_type_t *type,
+ cfg_obj_t **);
+typedef void (*cfg_printfunc_t)(cfg_printer_t *, const cfg_obj_t *);
+typedef void (*cfg_docfunc_t)(cfg_printer_t *, const cfg_type_t *);
+typedef void (*cfg_freefunc_t)(cfg_parser_t *, cfg_obj_t *);
+
+/*
+ * Structure definitions
+ */
+
+/*%
+ * A configuration printer object. This is an abstract
+ * interface to a destination to which text can be printed
+ * by calling the function 'f'.
+ */
+struct cfg_printer {
+ void (*f)(void *closure, const char *text, int textlen);
+ void *closure;
+ int indent;
+};
+
+/*% A clause definition. */
+struct cfg_clausedef {
+ const char *name;
+ cfg_type_t *type;
+ unsigned int flags;
+};
+
+/*% A tuple field definition. */
+struct cfg_tuplefielddef {
+ const char *name;
+ cfg_type_t *type;
+ unsigned int flags;
+};
+
+/*% A configuration object type definition. */
+struct cfg_type {
+ const char *name; /*%< For debugging purposes only */
+ cfg_parsefunc_t parse;
+ cfg_printfunc_t print;
+ cfg_docfunc_t doc; /*%< Print grammar description */
+ cfg_rep_t * rep; /*%< Data representation */
+ const void * of; /*%< Additional data for meta-types */
+};
+
+/*% A keyword-type definition, for things like "port <integer>". */
+typedef struct {
+ const char *name;
+ const cfg_type_t *type;
+} keyword_type_t;
+
+struct cfg_map {
+ cfg_obj_t *id; /*%< Used for 'named maps' like keys, zones, &c */
+ const cfg_clausedef_t * const *clausesets; /*%< The clauses that
+ can occur in this map;
+ used for printing */
+ isc_symtab_t *symtab;
+};
+
+typedef struct cfg_netprefix cfg_netprefix_t;
+
+struct cfg_netprefix {
+ isc_netaddr_t address; /* IP4/IP6 */
+ unsigned int prefixlen;
+};
+
+/*%
+ * A configuration data representation.
+ */
+struct cfg_rep {
+ const char * name; /*%< For debugging only */
+ cfg_freefunc_t free; /*%< How to free this kind of data. */
+};
+
+/*%
+ * A configuration object. This is the main building block
+ * of the configuration parse tree.
+ */
+
+struct cfg_obj {
+ const cfg_type_t *type;
+ union {
+ isc_uint32_t uint32;
+ isc_uint64_t uint64;
+ isc_textregion_t string; /*%< null terminated, too */
+ isc_boolean_t boolean;
+ cfg_map_t map;
+ cfg_list_t list;
+ cfg_obj_t ** tuple;
+ isc_sockaddr_t sockaddr;
+ cfg_netprefix_t netprefix;
+ } value;
+ const char * file;
+ unsigned int line;
+};
+
+
+/*% A list element. */
+struct cfg_listelt {
+ cfg_obj_t *obj;
+ ISC_LINK(cfg_listelt_t) link;
+};
+
+/*% The parser object. */
+struct cfg_parser {
+ isc_mem_t * mctx;
+ isc_log_t * lctx;
+ isc_lex_t * lexer;
+ unsigned int errors;
+ unsigned int warnings;
+ isc_token_t token;
+
+ /*% We are at the end of all input. */
+ isc_boolean_t seen_eof;
+
+ /*% The current token has been pushed back. */
+ isc_boolean_t ungotten;
+
+ /*%
+ * The stack of currently active files, represented
+ * as a configuration list of configuration strings.
+ * The head is the top-level file, subsequent elements
+ * (if any) are the nested include files, and the
+ * last element is the file currently being parsed.
+ */
+ cfg_obj_t * open_files;
+
+ /*%
+ * Names of files that we have parsed and closed
+ * and were previously on the open_file list.
+ * We keep these objects around after closing
+ * the files because the file names may still be
+ * referenced from other configuration objects
+ * for use in reporting semantic errors after
+ * parsing is complete.
+ */
+ cfg_obj_t * closed_files;
+
+ /*%
+ * Current line number. We maintain our own
+ * copy of this so that it is available even
+ * when a file has just been closed.
+ */
+ unsigned int line;
+
+ cfg_parsecallback_t callback;
+ void *callbackarg;
+};
+
+
+/*@{*/
+/*%
+ * Flags defining whether to accept certain types of network addresses.
+ */
+#define CFG_ADDR_V4OK 0x00000001
+#define CFG_ADDR_V4PREFIXOK 0x00000002
+#define CFG_ADDR_V6OK 0x00000004
+#define CFG_ADDR_WILDOK 0x00000008
+#define CFG_ADDR_MASK (CFG_ADDR_V6OK|CFG_ADDR_V4OK)
+/*@}*/
+
+/*@{*/
+/*%
+ * Predefined data representation types.
+ */
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_uint32;
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_uint64;
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_string;
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_boolean;
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_map;
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_list;
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_tuple;
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_sockaddr;
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_netprefix;
+LIBISCCFG_EXTERNAL_DATA extern cfg_rep_t cfg_rep_void;
+/*@}*/
+
+/*@{*/
+/*%
+ * Predefined configuration object types.
+ */
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_boolean;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_uint32;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_uint64;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_qstring;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_astring;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_ustring;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_sockaddr;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr4;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr4wild;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr6;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netaddr6wild;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_netprefix;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_void;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_token;
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_unsupported;
+/*@}*/
+
+isc_result_t
+cfg_gettoken(cfg_parser_t *pctx, int options);
+
+isc_result_t
+cfg_peektoken(cfg_parser_t *pctx, int options);
+
+void
+cfg_ungettoken(cfg_parser_t *pctx);
+
+#define CFG_LEXOPT_QSTRING (ISC_LEXOPT_QSTRING | ISC_LEXOPT_QSTRINGMULTILINE)
+
+isc_result_t
+cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
+
+void
+cfg_print_rawuint(cfg_printer_t *pctx, unsigned int u);
+
+isc_result_t
+cfg_parse_uint32(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+void
+cfg_print_uint32(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+void
+cfg_print_uint64(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+isc_result_t
+cfg_parse_qstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+void
+cfg_print_ustring(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+isc_result_t
+cfg_parse_astring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+isc_result_t
+cfg_parse_rawaddr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na);
+
+void
+cfg_print_rawaddr(cfg_printer_t *pctx, const isc_netaddr_t *na);
+
+isc_boolean_t
+cfg_lookingat_netaddr(cfg_parser_t *pctx, unsigned int flags);
+
+isc_result_t
+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);
+
+void
+cfg_print_sockaddr(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
+cfg_parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+isc_result_t
+cfg_parse_special(cfg_parser_t *pctx, int special);
+/*%< Parse a required special character 'special'. */
+
+isc_result_t
+cfg_create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
+
+isc_result_t
+cfg_parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+void
+cfg_print_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+void
+cfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type);
+
+isc_result_t
+cfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
+
+isc_result_t
+cfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype,
+ cfg_listelt_t **ret);
+
+isc_result_t
+cfg_parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+void
+cfg_print_bracketed_list(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+void
+cfg_doc_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type);
+
+isc_result_t
+cfg_parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+void
+cfg_print_spacelist(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+isc_result_t
+cfg_parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+void
+cfg_doc_enum(cfg_printer_t *pctx, const cfg_type_t *type);
+
+void
+cfg_print_chars(cfg_printer_t *pctx, const char *text, int len);
+/*%< Print 'len' characters at 'text' */
+
+void
+cfg_print_cstr(cfg_printer_t *pctx, const char *s);
+/*%< Print the null-terminated string 's' */
+
+isc_result_t
+cfg_parse_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+isc_result_t
+cfg_parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+isc_result_t
+cfg_parse_addressed_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+isc_result_t
+cfg_parse_netprefix_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **
+ret);
+
+void
+cfg_print_map(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+void
+cfg_doc_map(cfg_printer_t *pctx, const cfg_type_t *type);
+
+isc_result_t
+cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+void
+cfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+void
+cfg_doc_mapbody(cfg_printer_t *pctx, const cfg_type_t *type);
+
+isc_result_t
+cfg_parse_void(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+void
+cfg_print_void(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+void
+cfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type);
+
+isc_result_t
+cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+void
+cfg_print_obj(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+void
+cfg_doc_obj(cfg_printer_t *pctx, const cfg_type_t *type);
+/*%<
+ * Print a description of the grammar of an arbitrary configuration
+ * type 'type'
+ */
+
+void
+cfg_doc_terminal(cfg_printer_t *pctx, const cfg_type_t *type);
+/*%<
+ * Document the type 'type' as a terminal by printing its
+ * name in angle brackets, e.g., &lt;uint32>.
+ */
+
+void
+cfg_parser_error(cfg_parser_t *pctx, unsigned int flags,
+ const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4);
+/*!
+ * Pass one of these flags to cfg_parser_error() to include the
+ * token text in log message.
+ */
+#define CFG_LOG_NEAR 0x00000001 /*%< Say "near <token>" */
+#define CFG_LOG_BEFORE 0x00000002 /*%< Say "before <token>" */
+#define CFG_LOG_NOPREP 0x00000004 /*%< Say just "<token>" */
+
+void
+cfg_parser_warning(cfg_parser_t *pctx, unsigned int flags,
+ const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4);
+
+isc_boolean_t
+cfg_is_enum(const char *s, const char *const *enums);
+/*%< Return true iff the string 's' is one of the strings in 'enums' */
+
+#endif /* ISCCFG_GRAMMAR_H */
diff --git a/lib/isccfg/include/isccfg/log.h b/lib/isccfg/include/isccfg/log.h
new file mode 100644
index 0000000..c5c2c17
--- /dev/null
+++ b/lib/isccfg/include/isccfg/log.h
@@ -0,0 +1,55 @@
+/*
+ * 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: log.h,v 1.12 2007/06/19 23:47:22 tbox Exp $ */
+
+#ifndef ISCCFG_LOG_H
+#define ISCCFG_LOG_H 1
+
+/*! \file isccfg/log.h */
+
+#include <isc/lang.h>
+#include <isc/log.h>
+
+LIBISCCFG_EXTERNAL_DATA extern isc_logcategory_t cfg_categories[];
+LIBISCCFG_EXTERNAL_DATA extern isc_logmodule_t cfg_modules[];
+
+#define CFG_LOGCATEGORY_CONFIG (&cfg_categories[0])
+
+#define CFG_LOGMODULE_PARSER (&cfg_modules[0])
+
+ISC_LANG_BEGINDECLS
+
+void
+cfg_log_init(isc_log_t *lctx);
+/*%<
+ * Make the libisccfg categories and modules available for use with the
+ * ISC logging library.
+ *
+ * Requires:
+ *\li lctx is a valid logging context.
+ *
+ *\li cfg_log_init() is called only once.
+ *
+ * Ensures:
+ * \li The catgories and modules defined above are available for
+ * use by isc_log_usechannnel() and isc_log_write().
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISCCFG_LOG_H */
diff --git a/lib/isccfg/include/isccfg/namedconf.h b/lib/isccfg/include/isccfg/namedconf.h
new file mode 100644
index 0000000..9689a2a
--- /dev/null
+++ b/lib/isccfg/include/isccfg/namedconf.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: namedconf.h,v 1.9 2007/06/19 23:47:22 tbox Exp $ */
+
+#ifndef ISCCFG_NAMEDCONF_H
+#define ISCCFG_NAMEDCONF_H 1
+
+/*! \file isccfg/namedconf.h
+ * \brief
+ * This module defines the named.conf, rndc.conf, and rndc.key grammars.
+ */
+
+#include <isccfg/cfg.h>
+
+/*
+ * Configuration object types.
+ */
+LIBISCCFG_EXTERNAL_DATA extern cfg_type_t cfg_type_namedconf;
+/*%< A complete named.conf file. */
+
+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_keyref;
+/*%< A key reference, used as an ACL element */
+
+#endif /* ISCCFG_CFG_H */
diff --git a/lib/isccfg/include/isccfg/version.h b/lib/isccfg/include/isccfg/version.h
new file mode 100644
index 0000000..8aed111
--- /dev/null
+++ b/lib/isccfg/include/isccfg/version.h
@@ -0,0 +1,28 @@
+/*
+ * 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: version.h,v 1.9 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file isccfg/version.h */
+
+#include <isc/platform.h>
+
+LIBISCCFG_EXTERNAL_DATA extern const char cfg_version[];
+
+LIBISCCFG_EXTERNAL_DATA extern const unsigned int cfg_libinterface;
+LIBISCCFG_EXTERNAL_DATA extern const unsigned int cfg_librevision;
+LIBISCCFG_EXTERNAL_DATA extern const unsigned int cfg_libage;
diff --git a/lib/isccfg/log.c b/lib/isccfg/log.c
new file mode 100644
index 0000000..8747fc0
--- /dev/null
+++ b/lib/isccfg/log.c
@@ -0,0 +1,52 @@
+/*
+ * 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: log.c,v 1.11 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/util.h>
+
+#include <isccfg/log.h>
+
+/*%
+ * When adding a new category, be sure to add the appropriate
+ * \#define to <isccfg/log.h>.
+ */
+LIBISCCFG_EXTERNAL_DATA isc_logcategory_t cfg_categories[] = {
+ { "config", 0 },
+ { NULL, 0 }
+};
+
+/*%
+ * When adding a new module, be sure to add the appropriate
+ * \#define to <isccfg/log.h>.
+ */
+LIBISCCFG_EXTERNAL_DATA isc_logmodule_t cfg_modules[] = {
+ { "isccfg/parser", 0 },
+ { NULL, 0 }
+};
+
+void
+cfg_log_init(isc_log_t *lctx) {
+ REQUIRE(lctx != NULL);
+
+ isc_log_registercategories(lctx, cfg_categories);
+ isc_log_registermodules(lctx, cfg_modules);
+}
diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
new file mode 100644
index 0000000..0610489
--- /dev/null
+++ b/lib/isccfg/namedconf.c
@@ -0,0 +1,2223 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002, 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: namedconf.c,v 1.92 2008/09/27 23:35:31 jinmei Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/lex.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <isccfg/cfg.h>
+#include <isccfg/grammar.h>
+#include <isccfg/log.h>
+
+#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; \
+ } while (0)
+
+/*% Clean up a configuration object if non-NULL. */
+#define CLEANUP_OBJ(obj) \
+ do { if ((obj) != NULL) cfg_obj_destroy(pctx, &(obj)); } while (0)
+
+
+/*%
+ * Forward declarations of static functions.
+ */
+
+static isc_result_t
+parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype,
+ const cfg_type_t *othertype, cfg_obj_t **ret);
+
+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);
+
+static void
+print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+static void
+doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type);
+
+static void
+doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type);
+
+static cfg_type_t cfg_type_acl;
+static cfg_type_t cfg_type_addrmatchelt;
+static cfg_type_t cfg_type_bracketed_aml;
+static cfg_type_t cfg_type_bracketed_namesockaddrkeylist;
+static cfg_type_t cfg_type_bracketed_sockaddrlist;
+static cfg_type_t cfg_type_bracketed_sockaddrnameportlist;
+static cfg_type_t cfg_type_controls;
+static cfg_type_t cfg_type_controls_sockaddr;
+static cfg_type_t cfg_type_destinationlist;
+static cfg_type_t cfg_type_dialuptype;
+static cfg_type_t cfg_type_ixfrdifftype;
+static cfg_type_t cfg_type_key;
+static cfg_type_t cfg_type_logfile;
+static cfg_type_t cfg_type_logging;
+static cfg_type_t cfg_type_logseverity;
+static cfg_type_t cfg_type_lwres;
+static cfg_type_t cfg_type_masterselement;
+static cfg_type_t cfg_type_nameportiplist;
+static cfg_type_t cfg_type_negated;
+static cfg_type_t cfg_type_notifytype;
+static cfg_type_t cfg_type_optional_allow;
+static cfg_type_t cfg_type_optional_class;
+static cfg_type_t cfg_type_optional_facility;
+static cfg_type_t cfg_type_optional_keyref;
+static cfg_type_t cfg_type_optional_port;
+static cfg_type_t cfg_type_options;
+static cfg_type_t cfg_type_portiplist;
+static cfg_type_t cfg_type_querysource4;
+static cfg_type_t cfg_type_querysource6;
+static cfg_type_t cfg_type_querysource;
+static cfg_type_t cfg_type_server;
+static cfg_type_t cfg_type_server_key_kludge;
+static cfg_type_t cfg_type_size;
+static cfg_type_t cfg_type_sizenodefault;
+static cfg_type_t cfg_type_sockaddr4wild;
+static cfg_type_t cfg_type_sockaddr6wild;
+static cfg_type_t cfg_type_statschannels;
+static cfg_type_t cfg_type_view;
+static cfg_type_t cfg_type_viewopts;
+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;
+
+/*
+ * Clauses that can be found in a 'dynamically loadable zones' statement
+ */
+static cfg_clausedef_t
+dynamically_loadable_zones_clauses[] = {
+ { "database", &cfg_type_astring, 0 },
+ { NULL, NULL, 0 }
+};
+
+/*
+ * A dynamically loadable zones statement.
+ */
+static cfg_tuplefielddef_t dynamically_loadable_zones_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "options", &cfg_type_dynamically_loadable_zones_opts, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_dynamically_loadable_zones = {
+ "dlz", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple,
+ dynamically_loadable_zones_fields
+ };
+
+
+/*% tkey-dhkey */
+
+static cfg_tuplefielddef_t tkey_dhkey_fields[] = {
+ { "name", &cfg_type_qstring, 0 },
+ { "keyid", &cfg_type_uint32, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_tkey_dhkey = {
+ "tkey-dhkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+ tkey_dhkey_fields
+};
+
+/*% listen-on */
+
+static cfg_tuplefielddef_t listenon_fields[] = {
+ { "port", &cfg_type_optional_port, 0 },
+ { "acl", &cfg_type_bracketed_aml, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_listenon = {
+ "listenon", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, listenon_fields };
+
+/*% acl */
+
+static cfg_tuplefielddef_t acl_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "value", &cfg_type_bracketed_aml, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_acl = {
+ "acl", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, acl_fields };
+
+/*% masters */
+static cfg_tuplefielddef_t masters_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "port", &cfg_type_optional_port, 0 },
+ { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_masters = {
+ "masters", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, masters_fields };
+
+/*%
+ * "sockaddrkeylist", a list of socket addresses with optional keys
+ * and an optional default port, as used in the masters option.
+ * E.g.,
+ * "port 1234 { mymasters; 10.0.0.1 key foo; 1::2 port 69; }"
+ */
+
+static cfg_tuplefielddef_t namesockaddrkey_fields[] = {
+ { "masterselement", &cfg_type_masterselement, 0 },
+ { "key", &cfg_type_optional_keyref, 0 },
+ { NULL, NULL, 0 },
+};
+
+static cfg_type_t cfg_type_namesockaddrkey = {
+ "namesockaddrkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+ namesockaddrkey_fields
+};
+
+static cfg_type_t cfg_type_bracketed_namesockaddrkeylist = {
+ "bracketed_namesockaddrkeylist", cfg_parse_bracketed_list,
+ cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_namesockaddrkey
+};
+
+static cfg_tuplefielddef_t namesockaddrkeylist_fields[] = {
+ { "port", &cfg_type_optional_port, 0 },
+ { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_namesockaddrkeylist = {
+ "sockaddrkeylist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+ namesockaddrkeylist_fields
+};
+
+/*%
+ * A list of socket addresses with an optional default port,
+ * as used in the also-notify option. E.g.,
+ * "port 1234 { 10.0.0.1; 1::2 port 69; }"
+ */
+static cfg_tuplefielddef_t portiplist_fields[] = {
+ { "port", &cfg_type_optional_port, 0 },
+ { "addresses", &cfg_type_bracketed_sockaddrlist, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_portiplist = {
+ "portiplist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+ portiplist_fields
+};
+
+/*%
+ * A public key, as in the "pubkey" statement.
+ */
+static cfg_tuplefielddef_t pubkey_fields[] = {
+ { "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_pubkey = {
+ "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
+};
+
+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
+};
+
+static const char *matchtype_enums[] = {
+ "name", "subdomain", "wildcard", "self", "selfsub", "selfwild",
+ "krb5-self", "ms-self", "krb5-subdomain", "ms-subdomain",
+ "tcp-self", "6to4-self", NULL };
+static cfg_type_t cfg_type_matchtype = {
+ "matchtype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
+ &matchtype_enums
+};
+
+/*%
+ * A grant statement, used in the update policy.
+ */
+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 */
+ { "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 };
+
+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
+};
+
+/*%
+ * A view statement.
+ */
+static cfg_tuplefielddef_t view_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "class", &cfg_type_optional_class, 0 },
+ { "options", &cfg_type_viewopts, 0 },
+ { 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 };
+
+/*%
+ * A zone statement.
+ */
+static cfg_tuplefielddef_t zone_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "class", &cfg_type_optional_class, 0 },
+ { "options", &cfg_type_zoneopts, 0 },
+ { 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 };
+
+/*%
+ * A "category" clause in the "logging" statement.
+ */
+static cfg_tuplefielddef_t category_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "destinations", &cfg_type_destinationlist,0 },
+ { 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 };
+
+
+/*%
+ * 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 keyword_type_t wild_class_kw = { "class", &cfg_type_ustring };
+
+static cfg_type_t cfg_type_optional_wild_class = {
+ "optional_wild_class", parse_optional_keyvalue, print_keyvalue,
+ doc_optional_keyvalue, &cfg_rep_string, &wild_class_kw
+};
+
+static keyword_type_t wild_type_kw = { "type", &cfg_type_ustring };
+
+static cfg_type_t cfg_type_optional_wild_type = {
+ "optional_wild_type", parse_optional_keyvalue,
+ print_keyvalue, doc_optional_keyvalue, &cfg_rep_string, &wild_type_kw
+};
+
+static keyword_type_t wild_name_kw = { "name", &cfg_type_qstring };
+
+static cfg_type_t cfg_type_optional_wild_name = {
+ "optional_wild_name", parse_optional_keyvalue,
+ print_keyvalue, doc_optional_keyvalue, &cfg_rep_string, &wild_name_kw
+};
+
+/*%
+ * An rrset ordering element.
+ */
+static cfg_tuplefielddef_t rrsetorderingelement_fields[] = {
+ { "class", &cfg_type_optional_wild_class, 0 },
+ { "type", &cfg_type_optional_wild_type, 0 },
+ { "name", &cfg_type_optional_wild_name, 0 },
+ { "order", &cfg_type_ustring, 0 }, /* must be literal "order" */
+ { "ordering", &cfg_type_ustring, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_rrsetorderingelement = {
+ "rrsetorderingelement", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+ rrsetorderingelement_fields
+};
+
+/*%
+ * A global or view "check-names" option. Note that the zone
+ * "check-names" option has a different syntax.
+ */
+
+static const char *checktype_enums[] = { "master", "slave", "response", NULL };
+static cfg_type_t cfg_type_checktype = {
+ "checktype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
+ &cfg_rep_string, &checktype_enums
+};
+
+static const char *checkmode_enums[] = { "fail", "warn", "ignore", NULL };
+static cfg_type_t cfg_type_checkmode = {
+ "checkmode", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
+ &cfg_rep_string, &checkmode_enums
+};
+
+static cfg_tuplefielddef_t checknames_fields[] = {
+ { "type", &cfg_type_checktype, 0 },
+ { "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
+};
+
+static cfg_type_t cfg_type_bracketed_sockaddrlist = {
+ "bracketed_sockaddrlist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
+ &cfg_rep_list, &cfg_type_sockaddr
+};
+
+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
+};
+
+static keyword_type_t port_kw = { "port", &cfg_type_uint32 };
+
+static cfg_type_t cfg_type_optional_port = {
+ "optional_port", parse_optional_keyvalue, print_keyvalue,
+ doc_optional_keyvalue, &cfg_rep_uint32, &port_kw
+};
+
+/*% 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
+};
+
+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
+};
+
+static const char *forwardtype_enums[] = { "first", "only", NULL };
+static cfg_type_t cfg_type_forwardtype = {
+ "forwardtype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
+ &forwardtype_enums
+};
+
+static const char *zonetype_enums[] = {
+ "master", "slave", "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
+};
+
+static const char *loglevel_enums[] = {
+ "critical", "error", "warning", "notice", "info", "dynamic", NULL };
+static cfg_type_t cfg_type_loglevel = {
+ "loglevel", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
+ &loglevel_enums
+};
+
+static const char *transferformat_enums[] = {
+ "many-answers", "one-answer", NULL };
+static cfg_type_t cfg_type_transferformat = {
+ "transferformat", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
+ &transferformat_enums
+};
+
+/*%
+ * The special keyword "none", as used in the pid-file option.
+ */
+
+static void
+print_none(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ UNUSED(obj);
+ cfg_print_chars(pctx, "none", 4);
+}
+
+static cfg_type_t cfg_type_none = {
+ "none", NULL, print_none, NULL, &cfg_rep_void, NULL
+};
+
+/*%
+ * A quoted string or the special keyword "none". Used in the pid-file option.
+ */
+static isc_result_t
+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)
+ return (cfg_create_obj(pctx, &cfg_type_none, ret));
+ cfg_ungettoken(pctx);
+ return (cfg_parse_qstring(pctx, type, ret));
+ cleanup:
+ return (result);
+}
+
+static void
+doc_qstringornone(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(type);
+ cfg_print_chars(pctx, "( <quoted_string> | none )", 26);
+}
+
+static cfg_type_t cfg_type_qstringornone = {
+ "qstringornone", parse_qstringornone, NULL, doc_qstringornone, NULL, NULL };
+
+/*%
+ * keyword hostname
+ */
+
+static void
+print_hostname(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ UNUSED(obj);
+ cfg_print_chars(pctx, "hostname", 4);
+}
+
+static cfg_type_t cfg_type_hostname = {
+ "hostname", NULL, print_hostname, NULL, &cfg_rep_boolean, NULL
+};
+
+/*%
+ * "server-id" argument.
+ */
+
+static isc_result_t
+parse_serverid(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)
+ return (cfg_create_obj(pctx, &cfg_type_none, ret));
+ if (pctx->token.type == isc_tokentype_string &&
+ strcasecmp(TOKEN_STRING(pctx), "hostname") == 0) {
+ return (cfg_create_obj(pctx, &cfg_type_hostname, ret));
+ }
+ cfg_ungettoken(pctx);
+ return (cfg_parse_qstring(pctx, type, ret));
+ cleanup:
+ return (result);
+}
+
+static void
+doc_serverid(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(type);
+ cfg_print_chars(pctx, "( <quoted_string> | none | hostname )", 26);
+}
+
+static cfg_type_t cfg_type_serverid = {
+ "serverid", parse_serverid, NULL, doc_serverid, NULL, NULL };
+
+/*%
+ * Port list.
+ */
+static cfg_tuplefielddef_t porttuple_fields[] = {
+ { "loport", &cfg_type_uint32, 0 },
+ { "hiport", &cfg_type_uint32, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_porttuple = {
+ "porttuple", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, porttuple_fields
+};
+
+static isc_result_t
+parse_port(cfg_parser_t *pctx, cfg_obj_t **ret) {
+ isc_result_t result;
+
+ CHECK(cfg_parse_uint32(pctx, NULL, ret));
+ if ((*ret)->value.uint32 > 0xffff) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "invalid port");
+ cfg_obj_destroy(pctx, ret);
+ result = ISC_R_RANGE;
+ }
+
+ cleanup:
+ return (result);
+}
+
+static isc_result_t
+parse_portrange(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+
+ UNUSED(type);
+
+ CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
+ if (pctx->token.type == isc_tokentype_number)
+ CHECK(parse_port(pctx, ret));
+ else {
+ CHECK(cfg_gettoken(pctx, 0));
+ if (pctx->token.type != isc_tokentype_string ||
+ strcasecmp(TOKEN_STRING(pctx), "range") != 0) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected integer or 'range'");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ CHECK(cfg_create_tuple(pctx, &cfg_type_porttuple, &obj));
+ CHECK(parse_port(pctx, &obj->value.tuple[0]));
+ CHECK(parse_port(pctx, &obj->value.tuple[1]));
+ if (obj->value.tuple[0]->value.uint32 >
+ obj->value.tuple[1]->value.uint32) {
+ cfg_parser_error(pctx, CFG_LOG_NOPREP,
+ "low port '%u' must not be larger "
+ "than high port",
+ obj->value.tuple[0]->value.uint32);
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ *ret = obj;
+ obj = NULL;
+ }
+
+ cleanup:
+ if (obj != NULL)
+ cfg_obj_destroy(pctx, &obj);
+ return (result);
+}
+
+static cfg_type_t cfg_type_portrange = {
+ "portrange", parse_portrange, NULL, cfg_doc_terminal,
+ NULL, NULL
+};
+
+static cfg_type_t cfg_type_bracketed_portlist = {
+ "bracketed_sockaddrlist", cfg_parse_bracketed_list,
+ cfg_print_bracketed_list, cfg_doc_bracketed_list,
+ &cfg_rep_list, &cfg_type_portrange
+};
+
+/*%
+ * Clauses that can be found within the top level of the named.conf
+ * file only.
+ */
+static cfg_clausedef_t
+namedconf_clauses[] = {
+ { "options", &cfg_type_options, 0 },
+ { "controls", &cfg_type_controls, CFG_CLAUSEFLAG_MULTI },
+ { "acl", &cfg_type_acl, CFG_CLAUSEFLAG_MULTI },
+ { "masters", &cfg_type_masters, CFG_CLAUSEFLAG_MULTI },
+ { "logging", &cfg_type_logging, 0 },
+ { "view", &cfg_type_view, CFG_CLAUSEFLAG_MULTI },
+ { "lwres", &cfg_type_lwres, CFG_CLAUSEFLAG_MULTI },
+ { "statistics-channels", &cfg_type_statschannels,
+ CFG_CLAUSEFLAG_MULTI },
+ { NULL, NULL, 0 }
+};
+
+/*%
+ * Clauses that can occur at the top level or in the view
+ * statement, but not in the options block.
+ */
+static cfg_clausedef_t
+namedconf_or_view_clauses[] = {
+ { "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
+ { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI },
+ /* 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 },
+ { NULL, NULL, 0 }
+};
+
+/*%
+ * Clauses that can be found within the 'options' statement.
+ */
+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 },
+ { "blackhole", &cfg_type_bracketed_aml, 0 },
+ { "coresize", &cfg_type_size, 0 },
+ { "datasize", &cfg_type_size, 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 },
+ { "has-old-clients", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
+ { "heartbeat-interval", &cfg_type_uint32, 0 },
+ { "host-statistics", &cfg_type_boolean, CFG_CLAUSEFLAG_NOTIMP },
+ { "host-statistics-max", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
+ { "hostname", &cfg_type_qstringornone, 0 },
+ { "interface-interval", &cfg_type_uint32, 0 },
+ { "listen-on", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
+ { "listen-on-v6", &cfg_type_listenon, CFG_CLAUSEFLAG_MULTI },
+ { "match-mapped-addresses", &cfg_type_boolean, 0 },
+ { "memstatistics-file", &cfg_type_qstring, 0 },
+ { "memstatistics", &cfg_type_boolean, 0 },
+ { "multiple-cnames", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
+ { "named-xfer", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
+ { "pid-file", &cfg_type_qstringornone, 0 },
+ { "port", &cfg_type_uint32, 0 },
+ { "querylog", &cfg_type_boolean, 0 },
+ { "recursing-file", &cfg_type_qstring, 0 },
+ { "random-device", &cfg_type_qstring, 0 },
+ { "recursive-clients", &cfg_type_uint32, 0 },
+ { "reserved-sockets", &cfg_type_uint32, 0 },
+ { "serial-queries", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
+ { "serial-query-rate", &cfg_type_uint32, 0 },
+ { "server-id", &cfg_type_serverid, 0 },
+ { "stacksize", &cfg_type_size, 0 },
+ { "statistics-file", &cfg_type_qstring, 0 },
+ { "statistics-interval", &cfg_type_uint32, CFG_CLAUSEFLAG_NYI },
+ { "tcp-clients", &cfg_type_uint32, 0 },
+ { "tcp-listen-queue", &cfg_type_uint32, 0 },
+ { "tkey-dhkey", &cfg_type_tkey_dhkey, 0 },
+ { "tkey-gssapi-credential", &cfg_type_qstring, 0 },
+ { "tkey-domain", &cfg_type_qstring, 0 },
+ { "transfers-per-ns", &cfg_type_uint32, 0 },
+ { "transfers-in", &cfg_type_uint32, 0 },
+ { "transfers-out", &cfg_type_uint32, 0 },
+ { "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 },
+ { "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 };
+
+static keyword_type_t exclude_kw = { "exclude", &cfg_type_namelist };
+
+static cfg_type_t cfg_type_optional_exclude = {
+ "optional_exclude", parse_optional_keyvalue, print_keyvalue,
+ doc_optional_keyvalue, &cfg_rep_list, &exclude_kw };
+
+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 };
+
+static cfg_tuplefielddef_t disablealgorithm_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "algorithms", &cfg_type_algorithmlist, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_disablealgorithm = {
+ "disablealgorithm", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, disablealgorithm_fields
+};
+
+static cfg_tuplefielddef_t mustbesecure_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "value", &cfg_type_boolean, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_mustbesecure = {
+ "mustbesecure", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, mustbesecure_fields
+};
+
+static const char *masterformat_enums[] = { "text", "raw", NULL };
+static cfg_type_t cfg_type_masterformat = {
+ "masterformat", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
+ &cfg_rep_string, &masterformat_enums
+};
+
+/*%
+ * 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_tuplefielddef_t lookaside_fields[] = {
+ { "domain", &cfg_type_astring, 0 },
+ { "trust-anchor", &cfg_type_trustanchor, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_lookaside = {
+ "lookaside", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, lookaside_fields
+};
+
+/*%
+ * Clauses that can be found within the 'view' statement,
+ * with defaults in the 'options' statement.
+ */
+
+static cfg_clausedef_t
+view_clauses[] = {
+ { "acache-cleaning-interval", &cfg_type_uint32, 0 },
+ { "acache-enable", &cfg_type_boolean, 0 },
+ { "additional-from-auth", &cfg_type_boolean, 0 },
+ { "additional-from-cache", &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 },
+ { "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 },
+ { "disable-algorithms", &cfg_type_disablealgorithm,
+ CFG_CLAUSEFLAG_MULTI },
+ { "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
+ { "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 },
+ { "dual-stack-servers", &cfg_type_nameportiplist, 0 },
+ { "edns-udp-size", &cfg_type_uint32, 0 },
+ { "empty-contact", &cfg_type_astring, 0 },
+ { "empty-server", &cfg_type_astring, 0 },
+ { "empty-zones-enable", &cfg_type_boolean, 0 },
+ { "fetch-glue", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
+ { "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 },
+ { "lame-ttl", &cfg_type_uint32, 0 },
+ { "max-acache-size", &cfg_type_sizenodefault, 0 },
+ { "max-cache-size", &cfg_type_sizenodefault, 0 },
+ { "max-cache-ttl", &cfg_type_uint32, 0 },
+ { "max-clients-per-query", &cfg_type_uint32, 0 },
+ { "max-ncache-ttl", &cfg_type_uint32, 0 },
+ { "max-udp-size", &cfg_type_uint32, 0 },
+ { "min-roots", &cfg_type_uint32, CFG_CLAUSEFLAG_NOTIMP },
+ { "minimal-responses", &cfg_type_boolean, 0 },
+ { "preferred-glue", &cfg_type_astring, 0 },
+ { "provide-ixfr", &cfg_type_boolean, 0 },
+ /*
+ * Note that the query-source option syntax is different
+ * from the other -source options.
+ */
+ { "query-source", &cfg_type_querysource4, 0 },
+ { "query-source-v6", &cfg_type_querysource6, 0 },
+ { "queryport-pool-ports", &cfg_type_uint32, CFG_CLAUSEFLAG_OBSOLETE },
+ { "queryport-pool-updateinterval", &cfg_type_uint32,
+ CFG_CLAUSEFLAG_OBSOLETE },
+ { "recursion", &cfg_type_boolean, 0 },
+ { "request-ixfr", &cfg_type_boolean, 0 },
+ { "request-nsid", &cfg_type_boolean, 0 },
+ { "rfc2308-type1", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
+ { "root-delegation-only", &cfg_type_optional_exclude, 0 },
+ { "rrset-order", &cfg_type_rrsetorder, 0 },
+ { "sortlist", &cfg_type_bracketed_aml, 0 },
+ { "suppress-initial-notify", &cfg_type_boolean, CFG_CLAUSEFLAG_NYI },
+ { "topology", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_NOTIMP },
+ { "transfer-format", &cfg_type_transferformat, 0 },
+ { "use-queryport-pool", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
+ { "zero-no-soa-ttl-cache", &cfg_type_boolean, 0 },
+ { NULL, NULL, 0 }
+};
+
+/*%
+ * Clauses that can be found within the 'view' statement only.
+ */
+static cfg_clausedef_t
+view_only_clauses[] = {
+ { "match-clients", &cfg_type_bracketed_aml, 0 },
+ { "match-destinations", &cfg_type_bracketed_aml, 0 },
+ { "match-recursive-only", &cfg_type_boolean, 0 },
+ { NULL, NULL, 0 }
+};
+
+/*%
+ * Sig-validity-interval.
+ */
+static isc_result_t
+parse_optional_uint32(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ isc_result_t result;
+ UNUSED(type);
+
+ CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
+ if (pctx->token.type == isc_tokentype_number) {
+ CHECK(cfg_parse_obj(pctx, &cfg_type_uint32, ret));
+ } else {
+ CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
+ }
+ cleanup:
+ return (result);
+}
+
+static void
+doc_optional_uint32(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(type);
+ cfg_print_chars(pctx, "[ <integer> ]", 13);
+}
+
+static cfg_type_t cfg_type_optional_uint32 = {
+ "optional_uint32", parse_optional_uint32, NULL, doc_optional_uint32,
+ NULL, NULL };
+
+static cfg_tuplefielddef_t validityinterval_fields[] = {
+ { "validity", &cfg_type_uint32, 0 },
+ { "re-sign", &cfg_type_optional_uint32, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_validityinterval = {
+ "validityinterval", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, validityinterval_fields
+};
+
+/*%
+ * Clauses that can be found in a 'zone' statement,
+ * with defaults in the 'view' or 'options' statement.
+ */
+static cfg_clausedef_t
+zone_clauses[] = {
+ { "allow-notify", &cfg_type_bracketed_aml, 0 },
+ { "allow-query", &cfg_type_bracketed_aml, 0 },
+ { "allow-query-on", &cfg_type_bracketed_aml, 0 },
+ { "allow-transfer", &cfg_type_bracketed_aml, 0 },
+ { "allow-update", &cfg_type_bracketed_aml, 0 },
+ { "allow-update-forwarding", &cfg_type_bracketed_aml, 0 },
+ { "also-notify", &cfg_type_portiplist, 0 },
+ { "alt-transfer-source", &cfg_type_sockaddr4wild, 0 },
+ { "alt-transfer-source-v6", &cfg_type_sockaddr6wild, 0 },
+ { "check-integrity", &cfg_type_boolean, 0 },
+ { "check-mx", &cfg_type_checkmode, 0 },
+ { "check-mx-cname", &cfg_type_checkmode, 0 },
+ { "check-sibling", &cfg_type_boolean, 0 },
+ { "check-srv-cname", &cfg_type_checkmode, 0 },
+ { "check-wildcard", &cfg_type_boolean, 0 },
+ { "dialup", &cfg_type_dialuptype, 0 },
+ { "forward", &cfg_type_forwardtype, 0 },
+ { "forwarders", &cfg_type_portiplist, 0 },
+ { "key-directory", &cfg_type_qstring, 0 },
+ { "maintain-ixfr-base", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
+ { "masterfile-format", &cfg_type_masterformat, 0 },
+ { "max-ixfr-log-size", &cfg_type_size, CFG_CLAUSEFLAG_OBSOLETE },
+ { "max-journal-size", &cfg_type_sizenodefault, 0 },
+ { "max-refresh-time", &cfg_type_uint32, 0 },
+ { "max-retry-time", &cfg_type_uint32, 0 },
+ { "max-transfer-idle-in", &cfg_type_uint32, 0 },
+ { "max-transfer-idle-out", &cfg_type_uint32, 0 },
+ { "max-transfer-time-in", &cfg_type_uint32, 0 },
+ { "max-transfer-time-out", &cfg_type_uint32, 0 },
+ { "min-refresh-time", &cfg_type_uint32, 0 },
+ { "min-retry-time", &cfg_type_uint32, 0 },
+ { "multi-master", &cfg_type_boolean, 0 },
+ { "notify", &cfg_type_notifytype, 0 },
+ { "notify-delay", &cfg_type_uint32, 0 },
+ { "notify-source", &cfg_type_sockaddr4wild, 0 },
+ { "notify-source-v6", &cfg_type_sockaddr6wild, 0 },
+ { "notify-to-soa", &cfg_type_boolean, 0 },
+ { "nsec3-test-zone", &cfg_type_boolean, CFG_CLAUSEFLAG_TESTONLY },
+ { "sig-signing-nodes", &cfg_type_uint32, 0 },
+ { "sig-signing-signatures", &cfg_type_uint32, 0 },
+ { "sig-signing-type", &cfg_type_uint32, 0 },
+ { "sig-validity-interval", &cfg_type_validityinterval, 0 },
+ { "transfer-source", &cfg_type_sockaddr4wild, 0 },
+ { "transfer-source-v6", &cfg_type_sockaddr6wild, 0 },
+ { "try-tcp-refresh", &cfg_type_boolean, 0 },
+ { "update-check-ksk", &cfg_type_boolean, 0 },
+ { "use-alt-transfer-source", &cfg_type_boolean, 0 },
+ { "zero-no-soa-ttl", &cfg_type_boolean, 0 },
+ { "zone-statistics", &cfg_type_boolean, 0 },
+ { NULL, NULL, 0 }
+};
+
+/*%
+ * Clauses that can be found in a 'zone' statement
+ * only.
+ */
+static cfg_clausedef_t
+zone_only_clauses[] = {
+ { "type", &cfg_type_zonetype, 0 },
+ { "file", &cfg_type_qstring, 0 },
+ { "journal", &cfg_type_qstring, 0 },
+ { "ixfr-base", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
+ { "ixfr-tmp-file", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
+ { "masters", &cfg_type_namesockaddrkeylist, 0 },
+ { "pubkey", &cfg_type_pubkey,
+ CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_OBSOLETE },
+ { "update-policy", &cfg_type_updatepolicy, 0 },
+ { "database", &cfg_type_astring, 0 },
+ { "delegation-only", &cfg_type_boolean, 0 },
+ /*
+ * Note that the format of the check-names option is different between
+ * the zone options and the global/view options. Ugh.
+ */
+ { "check-names", &cfg_type_checkmode, 0 },
+ { "ixfr-from-differences", &cfg_type_boolean, 0 },
+ { NULL, NULL, 0 }
+};
+
+
+/*% The top-level named.conf syntax. */
+
+static cfg_clausedef_t *
+namedconf_clausesets[] = {
+ namedconf_clauses,
+ 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 "options" statement syntax. */
+
+static cfg_clausedef_t *
+options_clausesets[] = {
+ options_clauses,
+ view_clauses,
+ zone_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_options = {
+ "options", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map, options_clausesets };
+
+/*% The "view" statement syntax. */
+
+static cfg_clausedef_t *
+view_clausesets[] = {
+ view_only_clauses,
+ namedconf_or_view_clauses,
+ view_clauses,
+ zone_clauses,
+ dynamically_loadable_zones_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_viewopts = {
+ "view", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map, view_clausesets };
+
+/*% The "zone" statement syntax. */
+
+static cfg_clausedef_t *
+zone_clausesets[] = {
+ zone_only_clauses,
+ zone_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_zoneopts = {
+ "zoneopts", cfg_parse_map, cfg_print_map,
+ cfg_doc_map, &cfg_rep_map, zone_clausesets };
+
+/*% The "dynamically loadable zones" statement syntax. */
+
+static cfg_clausedef_t *
+dynamically_loadable_zones_clausesets[] = {
+ dynamically_loadable_zones_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_dynamically_loadable_zones_opts = {
+ "dynamically_loadable_zones_opts", cfg_parse_map,
+ cfg_print_map, cfg_doc_map, &cfg_rep_map,
+ dynamically_loadable_zones_clausesets
+};
+
+/*%
+ * Clauses that can be found within the 'key' statement.
+ */
+static cfg_clausedef_t
+key_clauses[] = {
+ { "algorithm", &cfg_type_astring, 0 },
+ { "secret", &cfg_type_astring, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_clausedef_t *
+key_clausesets[] = {
+ key_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_key = {
+ "key", cfg_parse_named_map, cfg_print_map,
+ cfg_doc_map, &cfg_rep_map, key_clausesets
+};
+
+
+/*%
+ * Clauses that can be found in a 'server' statement.
+ */
+static cfg_clausedef_t
+server_clauses[] = {
+ { "bogus", &cfg_type_boolean, 0 },
+ { "provide-ixfr", &cfg_type_boolean, 0 },
+ { "request-ixfr", &cfg_type_boolean, 0 },
+ { "support-ixfr", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
+ { "transfers", &cfg_type_uint32, 0 },
+ { "transfer-format", &cfg_type_transferformat, 0 },
+ { "keys", &cfg_type_server_key_kludge, 0 },
+ { "edns", &cfg_type_boolean, 0 },
+ { "edns-udp-size", &cfg_type_uint32, 0 },
+ { "max-udp-size", &cfg_type_uint32, 0 },
+ { "notify-source", &cfg_type_sockaddr4wild, 0 },
+ { "notify-source-v6", &cfg_type_sockaddr6wild, 0 },
+ { "query-source", &cfg_type_querysource4, 0 },
+ { "query-source-v6", &cfg_type_querysource6, 0 },
+ { "transfer-source", &cfg_type_sockaddr4wild, 0 },
+ { "transfer-source-v6", &cfg_type_sockaddr6wild, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_clausedef_t *
+server_clausesets[] = {
+ server_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_server = {
+ "server", cfg_parse_netprefix_map, cfg_print_map, cfg_doc_map, &cfg_rep_map,
+ server_clausesets
+};
+
+
+/*%
+ * Clauses that can be found in a 'channel' clause in the
+ * 'logging' statement.
+ *
+ * These have some additional constraints that need to be
+ * checked after parsing:
+ * - There must exactly one of file/syslog/null/stderr
+ *
+ */
+static cfg_clausedef_t
+channel_clauses[] = {
+ /* Destinations. We no longer require these to be first. */
+ { "file", &cfg_type_logfile, 0 },
+ { "syslog", &cfg_type_optional_facility, 0 },
+ { "null", &cfg_type_void, 0 },
+ { "stderr", &cfg_type_void, 0 },
+ /* Options. We now accept these for the null channel, too. */
+ { "severity", &cfg_type_logseverity, 0 },
+ { "print-time", &cfg_type_boolean, 0 },
+ { "print-severity", &cfg_type_boolean, 0 },
+ { "print-category", &cfg_type_boolean, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_clausedef_t *
+channel_clausesets[] = {
+ channel_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_channel = {
+ "channel", cfg_parse_named_map, cfg_print_map, cfg_doc_map,
+ &cfg_rep_map, channel_clausesets
+};
+
+/*% A list of log destination, used in the "category" clause. */
+static cfg_type_t cfg_type_destinationlist = {
+ "destinationlist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
+ &cfg_rep_list, &cfg_type_astring };
+
+/*%
+ * Clauses that can be found in a 'logging' statement.
+ */
+static cfg_clausedef_t
+logging_clauses[] = {
+ { "channel", &cfg_type_channel, CFG_CLAUSEFLAG_MULTI },
+ { "category", &cfg_type_category, CFG_CLAUSEFLAG_MULTI },
+ { NULL, NULL, 0 }
+};
+static cfg_clausedef_t *
+logging_clausesets[] = {
+ logging_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_logging = {
+ "logging", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map, logging_clausesets };
+
+
+static isc_result_t
+parse_unitstring(char *str, isc_resourcevalue_t *valuep) {
+ char *endp;
+ unsigned int len;
+ isc_uint64_t value;
+ isc_uint64_t unit;
+
+ value = isc_string_touint64(str, &endp, 10);
+ if (*endp == 0) {
+ *valuep = value;
+ return (ISC_R_SUCCESS);
+ }
+
+ len = strlen(str);
+ if (len < 2 || endp[1] != '\0')
+ return (ISC_R_FAILURE);
+
+ switch (str[len - 1]) {
+ case 'k':
+ case 'K':
+ unit = 1024;
+ break;
+ case 'm':
+ case 'M':
+ unit = 1024 * 1024;
+ break;
+ case 'g':
+ case 'G':
+ unit = 1024 * 1024 * 1024;
+ break;
+ default:
+ return (ISC_R_FAILURE);
+ }
+ if (value > ISC_UINT64_MAX / unit)
+ return (ISC_R_FAILURE);
+ *valuep = value * unit;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+parse_sizeval(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ isc_uint64_t val;
+
+ UNUSED(type);
+
+ CHECK(cfg_gettoken(pctx, 0));
+ if (pctx->token.type != isc_tokentype_string) {
+ result = ISC_R_UNEXPECTEDTOKEN;
+ goto cleanup;
+ }
+ CHECK(parse_unitstring(TOKEN_STRING(pctx), &val));
+
+ CHECK(cfg_create_obj(pctx, &cfg_type_uint64, &obj));
+ obj->value.uint64 = val;
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected integer and optional unit");
+ return (result);
+}
+
+/*%
+ * A size value (number + optional unit).
+ */
+static cfg_type_t cfg_type_sizeval = {
+ "sizeval", parse_sizeval, cfg_print_uint64, cfg_doc_terminal,
+ &cfg_rep_uint64, NULL };
+
+/*%
+ * A size, "unlimited", or "default".
+ */
+
+static isc_result_t
+parse_size(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ return (parse_enum_or_other(pctx, type, &cfg_type_sizeval, ret));
+}
+
+static const char *size_enums[] = { "unlimited", "default", NULL };
+static cfg_type_t cfg_type_size = {
+ "size", parse_size, cfg_print_ustring, cfg_doc_terminal,
+ &cfg_rep_string, size_enums
+};
+
+/*%
+ * A size or "unlimited", but not "default".
+ */
+static const char *sizenodefault_enums[] = { "unlimited", NULL };
+static cfg_type_t cfg_type_sizenodefault = {
+ "size_no_default", parse_size, cfg_print_ustring, cfg_doc_terminal,
+ &cfg_rep_string, sizenodefault_enums
+};
+
+/*%
+ * optional_keyvalue
+ */
+static isc_result_t
+parse_maybe_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
+ isc_boolean_t optional, cfg_obj_t **ret)
+{
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ const keyword_type_t *kw = type->of;
+
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_string &&
+ strcasecmp(TOKEN_STRING(pctx), kw->name) == 0) {
+ CHECK(cfg_gettoken(pctx, 0));
+ CHECK(kw->type->parse(pctx, kw->type, &obj));
+ obj->type = type; /* XXX kludge */
+ } else {
+ if (optional) {
+ CHECK(cfg_parse_void(pctx, NULL, &obj));
+ } else {
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected '%s'",
+ kw->name);
+ result = ISC_R_UNEXPECTEDTOKEN;
+ goto cleanup;
+ }
+ }
+ *ret = obj;
+ cleanup:
+ return (result);
+}
+
+static isc_result_t
+parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype,
+ const cfg_type_t *othertype, cfg_obj_t **ret)
+{
+ isc_result_t result;
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_string &&
+ cfg_is_enum(TOKEN_STRING(pctx), enumtype->of)) {
+ CHECK(cfg_parse_enum(pctx, enumtype, ret));
+ } else {
+ CHECK(cfg_parse_obj(pctx, othertype, ret));
+ }
+ cleanup:
+ return (result);
+}
+
+static void
+doc_enum_or_other(cfg_printer_t *pctx, const cfg_type_t *type) {
+ cfg_doc_terminal(pctx, type);
+#if 0 /* XXX */
+ cfg_print_chars(pctx, "( ", 2);...
+#endif
+
+}
+
+static isc_result_t
+parse_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ return (parse_maybe_optional_keyvalue(pctx, type, ISC_FALSE, ret));
+}
+
+static isc_result_t
+parse_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ return (parse_maybe_optional_keyvalue(pctx, type, ISC_TRUE, ret));
+}
+
+static void
+print_keyvalue(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ const keyword_type_t *kw = obj->type->of;
+ cfg_print_cstr(pctx, kw->name);
+ cfg_print_chars(pctx, " ", 1);
+ kw->type->print(pctx, obj);
+}
+
+static void
+doc_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const keyword_type_t *kw = type->of;
+ cfg_print_cstr(pctx, kw->name);
+ cfg_print_chars(pctx, " ", 1);
+ cfg_doc_obj(pctx, kw->type);
+}
+
+static void
+doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const keyword_type_t *kw = type->of;
+ cfg_print_chars(pctx, "[ ", 2);
+ cfg_print_cstr(pctx, kw->name);
+ cfg_print_chars(pctx, " ", 1);
+ cfg_doc_obj(pctx, kw->type);
+ cfg_print_chars(pctx, " ]", 2);
+}
+
+static const char *dialup_enums[] = {
+ "notify", "notify-passive", "refresh", "passive", NULL };
+static isc_result_t
+parse_dialup_type(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_dialuptype = {
+ "dialuptype", parse_dialup_type, cfg_print_ustring, doc_enum_or_other,
+ &cfg_rep_string, dialup_enums
+};
+
+static const char *notify_enums[] = { "explicit", "master-only", NULL };
+static isc_result_t
+parse_notify_type(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_notifytype = {
+ "notifytype", parse_notify_type, cfg_print_ustring, doc_enum_or_other,
+ &cfg_rep_string, notify_enums,
+};
+
+static const char *ixfrdiff_enums[] = { "master", "slave", NULL };
+static isc_result_t
+parse_ixfrdiff_type(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_ixfrdifftype = {
+ "ixfrdiff", parse_ixfrdiff_type, cfg_print_ustring, doc_enum_or_other,
+ &cfg_rep_string, ixfrdiff_enums,
+};
+
+static keyword_type_t key_kw = { "key", &cfg_type_astring };
+
+LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_keyref = {
+ "keyref", parse_keyvalue, print_keyvalue, doc_keyvalue,
+ &cfg_rep_string, &key_kw
+};
+
+static cfg_type_t cfg_type_optional_keyref = {
+ "optional_keyref", parse_optional_keyvalue, print_keyvalue,
+ doc_optional_keyvalue, &cfg_rep_string, &key_kw
+};
+
+/*%
+ * A "controls" statement is represented as a map with the multivalued
+ * "inet" and "unix" clauses.
+ */
+
+static keyword_type_t controls_allow_kw = {
+ "allow", &cfg_type_bracketed_aml };
+
+static cfg_type_t cfg_type_controls_allow = {
+ "controls_allow", parse_keyvalue,
+ print_keyvalue, doc_keyvalue,
+ &cfg_rep_list, &controls_allow_kw
+};
+
+static keyword_type_t controls_keys_kw = {
+ "keys", &cfg_type_keylist };
+
+static cfg_type_t cfg_type_controls_keys = {
+ "controls_keys", parse_optional_keyvalue,
+ print_keyvalue, doc_optional_keyvalue,
+ &cfg_rep_list, &controls_keys_kw
+};
+
+static cfg_tuplefielddef_t inetcontrol_fields[] = {
+ { "address", &cfg_type_controls_sockaddr, 0 },
+ { "allow", &cfg_type_controls_allow, 0 },
+ { "keys", &cfg_type_controls_keys, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_inetcontrol = {
+ "inetcontrol", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+ inetcontrol_fields
+};
+
+static keyword_type_t controls_perm_kw = {
+ "perm", &cfg_type_uint32 };
+
+static cfg_type_t cfg_type_controls_perm = {
+ "controls_perm", parse_keyvalue,
+ print_keyvalue, doc_keyvalue,
+ &cfg_rep_uint32, &controls_perm_kw
+};
+
+static keyword_type_t controls_owner_kw = {
+ "owner", &cfg_type_uint32 };
+
+static cfg_type_t cfg_type_controls_owner = {
+ "controls_owner", parse_keyvalue,
+ print_keyvalue, doc_keyvalue,
+ &cfg_rep_uint32, &controls_owner_kw
+};
+
+static keyword_type_t controls_group_kw = {
+ "group", &cfg_type_uint32 };
+
+static cfg_type_t cfg_type_controls_group = {
+ "controls_allow", parse_keyvalue,
+ print_keyvalue, doc_keyvalue,
+ &cfg_rep_uint32, &controls_group_kw
+};
+
+static cfg_tuplefielddef_t unixcontrol_fields[] = {
+ { "path", &cfg_type_qstring, 0 },
+ { "perm", &cfg_type_controls_perm, 0 },
+ { "owner", &cfg_type_controls_owner, 0 },
+ { "group", &cfg_type_controls_group, 0 },
+ { "keys", &cfg_type_controls_keys, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_unixcontrol = {
+ "unixcontrol", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+ unixcontrol_fields
+};
+
+static cfg_clausedef_t
+controls_clauses[] = {
+ { "inet", &cfg_type_inetcontrol, CFG_CLAUSEFLAG_MULTI },
+ { "unix", &cfg_type_unixcontrol, CFG_CLAUSEFLAG_MULTI },
+ { NULL, NULL, 0 }
+};
+
+static cfg_clausedef_t *
+controls_clausesets[] = {
+ controls_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_controls = {
+ "controls", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map, &controls_clausesets
+};
+
+/*%
+ * A "statistics-channels" statement is represented as a map with the
+ * multivalued "inet" clauses.
+ */
+static void
+doc_optional_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const keyword_type_t *kw = type->of;
+ cfg_print_chars(pctx, "[ ", 2);
+ cfg_print_cstr(pctx, kw->name);
+ cfg_print_chars(pctx, " ", 1);
+ cfg_doc_obj(pctx, kw->type);
+ cfg_print_chars(pctx, " ]", 2);
+}
+
+static cfg_type_t cfg_type_optional_allow = {
+ "optional_allow", parse_optional_keyvalue, print_keyvalue,
+ doc_optional_bracketed_list, &cfg_rep_list, &controls_allow_kw
+};
+
+static cfg_tuplefielddef_t statserver_fields[] = {
+ { "address", &cfg_type_controls_sockaddr, 0 }, /* reuse controls def */
+ { "allow", &cfg_type_optional_allow, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_statschannel = {
+ "statschannel", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, statserver_fields
+};
+
+static cfg_clausedef_t
+statservers_clauses[] = {
+ { "inet", &cfg_type_statschannel, CFG_CLAUSEFLAG_MULTI },
+ { NULL, NULL, 0 }
+};
+
+static cfg_clausedef_t *
+statservers_clausesets[] = {
+ statservers_clauses,
+ NULL
+};
+
+static cfg_type_t cfg_type_statschannels = {
+ "statistics-channels", cfg_parse_map, cfg_print_map, cfg_doc_map,
+ &cfg_rep_map, &statservers_clausesets
+};
+
+/*%
+ * An optional class, as used in view and zone statements.
+ */
+static isc_result_t
+parse_optional_class(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ UNUSED(type);
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_string)
+ CHECK(cfg_parse_obj(pctx, &cfg_type_ustring, ret));
+ else
+ CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
+ cleanup:
+ return (result);
+}
+
+static cfg_type_t cfg_type_optional_class = {
+ "optional_class", parse_optional_class, NULL, cfg_doc_terminal,
+ NULL, NULL
+};
+
+static isc_result_t
+parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ isc_netaddr_t netaddr;
+ in_port_t port;
+ unsigned int have_address = 0;
+ unsigned int have_port = 0;
+ const unsigned int *flagp = type->of;
+
+ if ((*flagp & CFG_ADDR_V4OK) != 0)
+ isc_netaddr_any(&netaddr);
+ else if ((*flagp & CFG_ADDR_V6OK) != 0)
+ isc_netaddr_any6(&netaddr);
+ else
+ INSIST(0);
+
+ port = 0;
+
+ for (;;) {
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_string) {
+ if (strcasecmp(TOKEN_STRING(pctx),
+ "address") == 0)
+ {
+ /* read "address" */
+ CHECK(cfg_gettoken(pctx, 0));
+ CHECK(cfg_parse_rawaddr(pctx, *flagp,
+ &netaddr));
+ have_address++;
+ } else if (strcasecmp(TOKEN_STRING(pctx), "port") == 0)
+ {
+ /* read "port" */
+ CHECK(cfg_gettoken(pctx, 0));
+ CHECK(cfg_parse_rawport(pctx,
+ CFG_ADDR_WILDOK,
+ &port));
+ have_port++;
+ } else if (have_port == 0 && have_address == 0) {
+ return (cfg_parse_sockaddr(pctx, type, ret));
+ } else {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected 'address' or 'port'");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ } else
+ break;
+ }
+ if (have_address > 1 || have_port > 1 ||
+ have_address + have_port == 0) {
+ cfg_parser_error(pctx, 0, "expected one address and/or port");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+
+ CHECK(cfg_create_obj(pctx, &cfg_type_querysource, &obj));
+ isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "invalid query source");
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+static void
+print_querysource(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ isc_netaddr_t na;
+ isc_netaddr_fromsockaddr(&na, &obj->value.sockaddr);
+ cfg_print_chars(pctx, "address ", 8);
+ cfg_print_rawaddr(pctx, &na);
+ cfg_print_chars(pctx, " port ", 6);
+ cfg_print_rawuint(pctx, isc_sockaddr_getport(&obj->value.sockaddr));
+}
+
+static unsigned int sockaddr4wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V4OK;
+static unsigned int sockaddr6wild_flags = CFG_ADDR_WILDOK | CFG_ADDR_V6OK;
+
+static cfg_type_t cfg_type_querysource4 = {
+ "querysource4", parse_querysource, NULL, cfg_doc_terminal,
+ NULL, &sockaddr4wild_flags
+};
+
+static cfg_type_t cfg_type_querysource6 = {
+ "querysource6", parse_querysource, NULL, cfg_doc_terminal,
+ NULL, &sockaddr6wild_flags
+};
+
+static cfg_type_t cfg_type_querysource = {
+ "querysource", NULL, print_querysource, NULL, &cfg_rep_sockaddr, NULL
+};
+
+/*% addrmatchelt */
+
+static isc_result_t
+parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ UNUSED(type);
+
+ CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
+
+ if (pctx->token.type == isc_tokentype_string ||
+ pctx->token.type == isc_tokentype_qstring) {
+ if (pctx->token.type == isc_tokentype_string &&
+ (strcasecmp(TOKEN_STRING(pctx), "key") == 0)) {
+ CHECK(cfg_parse_obj(pctx, &cfg_type_keyref, ret));
+ } else {
+ if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK |
+ CFG_ADDR_V4PREFIXOK |
+ CFG_ADDR_V6OK))
+ {
+ CHECK(cfg_parse_netprefix(pctx, NULL, ret));
+ } else {
+ CHECK(cfg_parse_astring(pctx, NULL, ret));
+ }
+ }
+ } else if (pctx->token.type == isc_tokentype_special) {
+ if (pctx->token.value.as_char == '{') {
+ /* Nested match list. */
+ CHECK(cfg_parse_obj(pctx, &cfg_type_bracketed_aml, ret));
+ } else if (pctx->token.value.as_char == '!') {
+ CHECK(cfg_gettoken(pctx, 0)); /* read "!" */
+ CHECK(cfg_parse_obj(pctx, &cfg_type_negated, ret));
+ } else {
+ goto bad;
+ }
+ } else {
+ bad:
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected IP match list element");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ cleanup:
+ return (result);
+}
+
+/*%
+ * A negated address match list element (like "! 10.0.0.1").
+ * Somewhat sneakily, the caller is expected to parse the
+ * "!", but not to print it.
+ */
+
+static cfg_tuplefielddef_t negated_fields[] = {
+ { "value", &cfg_type_addrmatchelt, 0 },
+ { NULL, NULL, 0 }
+};
+
+static void
+print_negated(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ cfg_print_chars(pctx, "!", 1);
+ cfg_print_tuple(pctx, obj);
+}
+
+static cfg_type_t cfg_type_negated = {
+ "negated", cfg_parse_tuple, print_negated, NULL, &cfg_rep_tuple,
+ &negated_fields
+};
+
+/*% An address match list element */
+
+static cfg_type_t cfg_type_addrmatchelt = {
+ "address_match_element", parse_addrmatchelt, NULL, cfg_doc_terminal,
+ NULL, NULL
+};
+
+/*% A bracketed address match list */
+
+static cfg_type_t cfg_type_bracketed_aml = {
+ "bracketed_aml", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+ cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_addrmatchelt
+};
+
+/*%
+ * The socket address syntax in the "controls" statement is silly.
+ * It allows both socket address families, but also allows "*",
+ * whis is gratuitously interpreted as the IPv4 wildcard address.
+ */
+static unsigned int controls_sockaddr_flags =
+ CFG_ADDR_V4OK | CFG_ADDR_V6OK | CFG_ADDR_WILDOK;
+static cfg_type_t cfg_type_controls_sockaddr = {
+ "controls_sockaddr", cfg_parse_sockaddr, cfg_print_sockaddr,
+ cfg_doc_sockaddr, &cfg_rep_sockaddr, &controls_sockaddr_flags
+};
+
+/*%
+ * Handle the special kludge syntax of the "keys" clause in the "server"
+ * statement, which takes a single key with or without braces and semicolon.
+ */
+static isc_result_t
+parse_server_key_kludge(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
+{
+ isc_result_t result;
+ isc_boolean_t braces = ISC_FALSE;
+ UNUSED(type);
+
+ /* Allow opening brace. */
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_special &&
+ pctx->token.value.as_char == '{') {
+ result = cfg_gettoken(pctx, 0);
+ braces = ISC_TRUE;
+ }
+
+ CHECK(cfg_parse_obj(pctx, &cfg_type_astring, ret));
+
+ if (braces) {
+ /* Skip semicolon if present. */
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_special &&
+ pctx->token.value.as_char == ';')
+ CHECK(cfg_gettoken(pctx, 0));
+
+ CHECK(cfg_parse_special(pctx, '}'));
+ }
+ cleanup:
+ return (result);
+}
+static cfg_type_t cfg_type_server_key_kludge = {
+ "server_key", parse_server_key_kludge, NULL, cfg_doc_terminal,
+ NULL, NULL
+};
+
+
+/*%
+ * An optional logging facility.
+ */
+
+static isc_result_t
+parse_optional_facility(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
+{
+ isc_result_t result;
+ UNUSED(type);
+
+ CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
+ if (pctx->token.type == isc_tokentype_string ||
+ pctx->token.type == isc_tokentype_qstring) {
+ CHECK(cfg_parse_obj(pctx, &cfg_type_astring, ret));
+ } else {
+ CHECK(cfg_parse_obj(pctx, &cfg_type_void, ret));
+ }
+ cleanup:
+ return (result);
+}
+
+static cfg_type_t cfg_type_optional_facility = {
+ "optional_facility", parse_optional_facility, NULL, cfg_doc_terminal,
+ NULL, NULL };
+
+
+/*%
+ * A log severity. Return as a string, except "debug N",
+ * which is returned as a keyword object.
+ */
+
+static keyword_type_t debug_kw = { "debug", &cfg_type_uint32 };
+static cfg_type_t cfg_type_debuglevel = {
+ "debuglevel", parse_keyvalue,
+ print_keyvalue, doc_keyvalue,
+ &cfg_rep_uint32, &debug_kw
+};
+
+static isc_result_t
+parse_logseverity(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ UNUSED(type);
+
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_string &&
+ strcasecmp(TOKEN_STRING(pctx), "debug") == 0) {
+ CHECK(cfg_gettoken(pctx, 0)); /* read "debug" */
+ CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER));
+ if (pctx->token.type == isc_tokentype_number) {
+ CHECK(cfg_parse_uint32(pctx, NULL, ret));
+ } else {
+ /*
+ * The debug level is optional and defaults to 1.
+ * This makes little sense, but we support it for
+ * compatibility with BIND 8.
+ */
+ CHECK(cfg_create_obj(pctx, &cfg_type_uint32, ret));
+ (*ret)->value.uint32 = 1;
+ }
+ (*ret)->type = &cfg_type_debuglevel; /* XXX kludge */
+ } else {
+ CHECK(cfg_parse_obj(pctx, &cfg_type_loglevel, ret));
+ }
+ cleanup:
+ return (result);
+}
+
+static cfg_type_t cfg_type_logseverity = {
+ "log_severity", parse_logseverity, NULL, cfg_doc_terminal,
+ NULL, NULL };
+
+/*%
+ * The "file" clause of the "channel" statement.
+ * This is yet another special case.
+ */
+
+static const char *logversions_enums[] = { "unlimited", NULL };
+static isc_result_t
+parse_logversions(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ return (parse_enum_or_other(pctx, type, &cfg_type_uint32, ret));
+}
+
+static cfg_type_t cfg_type_logversions = {
+ "logversions", parse_logversions, cfg_print_ustring, cfg_doc_terminal,
+ &cfg_rep_string, logversions_enums
+};
+
+static cfg_tuplefielddef_t logfile_fields[] = {
+ { "file", &cfg_type_qstring, 0 },
+ { "versions", &cfg_type_logversions, 0 },
+ { "size", &cfg_type_size, 0 },
+ { NULL, NULL, 0 }
+};
+
+static isc_result_t
+parse_logfile(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));
+
+ /* Parse the mandatory "file" field */
+ CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
+
+ /* Parse "versions" and "size" fields in any order. */
+ for (;;) {
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_string) {
+ CHECK(cfg_gettoken(pctx, 0));
+ if (strcasecmp(TOKEN_STRING(pctx),
+ "versions") == 0 &&
+ obj->value.tuple[1] == NULL) {
+ CHECK(cfg_parse_obj(pctx, fields[1].type,
+ &obj->value.tuple[1]));
+ } else if (strcasecmp(TOKEN_STRING(pctx),
+ "size") == 0 &&
+ obj->value.tuple[2] == NULL) {
+ CHECK(cfg_parse_obj(pctx, fields[2].type,
+ &obj->value.tuple[2]));
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ /* Create void objects for missing optional values. */
+ if (obj->value.tuple[1] == NULL)
+ CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[1]));
+ if (obj->value.tuple[2] == NULL)
+ CHECK(cfg_parse_void(pctx, NULL, &obj->value.tuple[2]));
+
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+static void
+print_logfile(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ cfg_print_obj(pctx, obj->value.tuple[0]); /* file */
+ if (obj->value.tuple[1]->type->print != cfg_print_void) {
+ cfg_print_chars(pctx, " versions ", 10);
+ cfg_print_obj(pctx, obj->value.tuple[1]);
+ }
+ if (obj->value.tuple[2]->type->print != cfg_print_void) {
+ cfg_print_chars(pctx, " size ", 6);
+ cfg_print_obj(pctx, obj->value.tuple[2]);
+ }
+}
+
+
+static void
+doc_logfile(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(type);
+ cfg_print_cstr(pctx, "<quoted_string>");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[ versions ( \"unlimited\" | <integer> ) ]");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[ size <size> ]");
+}
+
+static cfg_type_t cfg_type_logfile = {
+ "log_file", parse_logfile, print_logfile, doc_logfile,
+ &cfg_rep_tuple, logfile_fields
+};
+
+/*% An IPv4 address with optional port, "*" accepted as wildcard. */
+static cfg_type_t cfg_type_sockaddr4wild = {
+ "sockaddr4wild", cfg_parse_sockaddr, cfg_print_sockaddr,
+ cfg_doc_sockaddr, &cfg_rep_sockaddr, &sockaddr4wild_flags
+};
+
+/*% An IPv6 address with optional port, "*" accepted as wildcard. */
+static cfg_type_t cfg_type_sockaddr6wild = {
+ "v6addrportwild", cfg_parse_sockaddr, cfg_print_sockaddr,
+ cfg_doc_sockaddr, &cfg_rep_sockaddr, &sockaddr6wild_flags
+};
+
+/*%
+ * lwres
+ */
+
+static cfg_tuplefielddef_t lwres_view_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "class", &cfg_type_optional_class, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_lwres_view = {
+ "lwres_view", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+ lwres_view_fields
+};
+
+static cfg_type_t cfg_type_lwres_searchlist = {
+ "lwres_searchlist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+ cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring };
+
+static cfg_clausedef_t
+lwres_clauses[] = {
+ { "listen-on", &cfg_type_portiplist, 0 },
+ { "view", &cfg_type_lwres_view, 0 },
+ { "search", &cfg_type_lwres_searchlist, 0 },
+ { "ndots", &cfg_type_uint32, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_clausedef_t *
+lwres_clausesets[] = {
+ lwres_clauses,
+ NULL
+};
+static cfg_type_t cfg_type_lwres = {
+ "lwres", cfg_parse_map, cfg_print_map, cfg_doc_map, &cfg_rep_map,
+ lwres_clausesets
+};
+
+/*%
+ * rndc
+ */
+
+static cfg_clausedef_t
+rndcconf_options_clauses[] = {
+ { "default-key", &cfg_type_astring, 0 },
+ { "default-port", &cfg_type_uint32, 0 },
+ { "default-server", &cfg_type_astring, 0 },
+ { "default-source-address", &cfg_type_netaddr4wild, 0 },
+ { "default-source-address-v6", &cfg_type_netaddr6wild, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_clausedef_t *
+rndcconf_options_clausesets[] = {
+ rndcconf_options_clauses,
+ NULL
+};
+
+static cfg_type_t cfg_type_rndcconf_options = {
+ "rndcconf_options", cfg_parse_map, cfg_print_map, cfg_doc_map,
+ &cfg_rep_map, rndcconf_options_clausesets
+};
+
+static cfg_clausedef_t
+rndcconf_server_clauses[] = {
+ { "key", &cfg_type_astring, 0 },
+ { "port", &cfg_type_uint32, 0 },
+ { "source-address", &cfg_type_netaddr4wild, 0 },
+ { "source-address-v6", &cfg_type_netaddr6wild, 0 },
+ { "addresses", &cfg_type_bracketed_sockaddrnameportlist, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_clausedef_t *
+rndcconf_server_clausesets[] = {
+ rndcconf_server_clauses,
+ NULL
+};
+
+static cfg_type_t cfg_type_rndcconf_server = {
+ "rndcconf_server", cfg_parse_named_map, cfg_print_map, cfg_doc_map,
+ &cfg_rep_map, rndcconf_server_clausesets
+};
+
+static cfg_clausedef_t
+rndcconf_clauses[] = {
+ { "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
+ { "server", &cfg_type_rndcconf_server, CFG_CLAUSEFLAG_MULTI },
+ { "options", &cfg_type_rndcconf_options, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_clausedef_t *
+rndcconf_clausesets[] = {
+ rndcconf_clauses,
+ NULL
+};
+
+LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndcconf = {
+ "rndcconf", cfg_parse_mapbody, cfg_print_mapbody, cfg_doc_mapbody,
+ &cfg_rep_map, rndcconf_clausesets
+};
+
+static cfg_clausedef_t
+rndckey_clauses[] = {
+ { "key", &cfg_type_key, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_clausedef_t *
+rndckey_clausesets[] = {
+ rndckey_clauses,
+ NULL
+};
+
+LIBISCCFG_EXTERNAL_DATA cfg_type_t cfg_type_rndckey = {
+ "rndckey", 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 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_nameport = {
+ "nameport", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, nameport_fields
+};
+
+static void
+doc_sockaddrnameport(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(type);
+ cfg_print_chars(pctx, "( ", 2);
+ cfg_print_cstr(pctx, "<quoted_string>");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[ port <integer> ]");
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_cstr(pctx, "<ipv4_address>");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[ port <integer> ]");
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_cstr(pctx, "<ipv6_address>");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[ port <integer> ]");
+ cfg_print_chars(pctx, " )", 2);
+}
+
+static isc_result_t
+parse_sockaddrnameport(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ UNUSED(type);
+
+ CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
+ if (pctx->token.type == isc_tokentype_string ||
+ pctx->token.type == isc_tokentype_qstring) {
+ if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V6OK))
+ CHECK(cfg_parse_sockaddr(pctx, &cfg_type_sockaddr, ret));
+ else {
+ const cfg_tuplefielddef_t *fields =
+ cfg_type_nameport.of;
+ CHECK(cfg_create_tuple(pctx, &cfg_type_nameport,
+ &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]));
+ *ret = obj;
+ obj = NULL;
+ }
+ } else {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected IP address or hostname");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+static cfg_type_t cfg_type_sockaddrnameport = {
+ "sockaddrnameport_element", parse_sockaddrnameport, NULL,
+ doc_sockaddrnameport, NULL, NULL
+};
+
+static cfg_type_t cfg_type_bracketed_sockaddrnameportlist = {
+ "bracketed_sockaddrnameportlist", cfg_parse_bracketed_list,
+ cfg_print_bracketed_list, cfg_doc_bracketed_list,
+ &cfg_rep_list, &cfg_type_sockaddrnameport
+};
+
+/*%
+ * A list of socket addresses or name with an optional default port,
+ * as used in the dual-stack-servers option. E.g.,
+ * "port 1234 { dual-stack-servers.net; 10.0.0.1; 1::2 port 69; }"
+ */
+static cfg_tuplefielddef_t nameportiplist_fields[] = {
+ { "port", &cfg_type_optional_port, 0 },
+ { "addresses", &cfg_type_bracketed_sockaddrnameportlist, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_nameportiplist = {
+ "nameportiplist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, nameportiplist_fields
+};
+
+/*%
+ * masters element.
+ */
+
+static void
+doc_masterselement(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(type);
+ cfg_print_chars(pctx, "( ", 2);
+ cfg_print_cstr(pctx, "<masters>");
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_cstr(pctx, "<ipv4_address>");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[ port <integer> ]");
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_cstr(pctx, "<ipv6_address>");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[ port <integer> ]");
+ cfg_print_chars(pctx, " )", 2);
+}
+
+static isc_result_t
+parse_masterselement(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ UNUSED(type);
+
+ CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
+ if (pctx->token.type == isc_tokentype_string ||
+ pctx->token.type == isc_tokentype_qstring) {
+ if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V6OK))
+ CHECK(cfg_parse_sockaddr(pctx, &cfg_type_sockaddr, ret));
+ else
+ CHECK(cfg_parse_astring(pctx, &cfg_type_astring, ret));
+ } else {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected IP address or masters name");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+static cfg_type_t cfg_type_masterselement = {
+ "masters_element", parse_masterselement, NULL,
+ doc_masterselement, NULL, NULL
+};
diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c
new file mode 100644
index 0000000..ee19cf5
--- /dev/null
+++ b/lib/isccfg/parser.c
@@ -0,0 +1,2406 @@
+/*
+ * 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
+ * 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: parser.c,v 1.129 2008/09/25 04:02:39 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/buffer.h>
+#include <isc/dir.h>
+#include <isc/formatcheck.h>
+#include <isc/lex.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/sockaddr.h>
+#include <isc/netscope.h>
+#include <isc/util.h>
+#include <isc/symtab.h>
+
+#include <isccfg/cfg.h>
+#include <isccfg/grammar.h>
+#include <isccfg/log.h>
+
+/* Shorthand */
+#define CAT CFG_LOGCATEGORY_CONFIG
+#define MOD CFG_LOGMODULE_PARSER
+
+#define MAP_SYM 1 /* Unique type for isc_symtab */
+
+#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; \
+ } while (0)
+
+/* Clean up a configuration object if non-NULL. */
+#define CLEANUP_OBJ(obj) \
+ do { if ((obj) != NULL) cfg_obj_destroy(pctx, &(obj)); } while (0)
+
+
+/*
+ * Forward declarations of static functions.
+ */
+
+static void
+free_tuple(cfg_parser_t *pctx, cfg_obj_t *obj);
+
+static isc_result_t
+parse_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret);
+
+static void
+print_list(cfg_printer_t *pctx, const cfg_obj_t *obj);
+
+static void
+free_list(cfg_parser_t *pctx, cfg_obj_t *obj);
+
+static isc_result_t
+create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp);
+
+static isc_result_t
+create_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
+ cfg_obj_t **ret);
+
+static void
+free_string(cfg_parser_t *pctx, cfg_obj_t *obj);
+
+static isc_result_t
+create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **objp);
+
+static void
+free_map(cfg_parser_t *pctx, cfg_obj_t *obj);
+
+static isc_result_t
+parse_symtab_elt(cfg_parser_t *pctx, const char *name,
+ cfg_type_t *elttype, isc_symtab_t *symtab,
+ isc_boolean_t callback);
+
+static void
+free_noop(cfg_parser_t *pctx, cfg_obj_t *obj);
+
+static isc_result_t
+cfg_getstringtoken(cfg_parser_t *pctx);
+
+static void
+parser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,
+ unsigned int flags, const char *format, va_list args);
+
+/*
+ * Data representations. These correspond to members of the
+ * "value" union in struct cfg_obj (except "void", which does
+ * not need a union member).
+ */
+
+cfg_rep_t cfg_rep_uint32 = { "uint32", free_noop };
+cfg_rep_t cfg_rep_uint64 = { "uint64", free_noop };
+cfg_rep_t cfg_rep_string = { "string", free_string };
+cfg_rep_t cfg_rep_boolean = { "boolean", free_noop };
+cfg_rep_t cfg_rep_map = { "map", free_map };
+cfg_rep_t cfg_rep_list = { "list", free_list };
+cfg_rep_t cfg_rep_tuple = { "tuple", free_tuple };
+cfg_rep_t cfg_rep_sockaddr = { "sockaddr", free_noop };
+cfg_rep_t cfg_rep_netprefix = { "netprefix", free_noop };
+cfg_rep_t cfg_rep_void = { "void", free_noop };
+
+/*
+ * Configuration type definitions.
+ */
+
+/*%
+ * An implicit list. These are formed by clauses that occur multiple times.
+ */
+static cfg_type_t cfg_type_implicitlist = {
+ "implicitlist", NULL, print_list, NULL, &cfg_rep_list, NULL };
+
+/* Functions. */
+
+void
+cfg_print_obj(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ obj->type->print(pctx, obj);
+}
+
+void
+cfg_print_chars(cfg_printer_t *pctx, const char *text, int len) {
+ pctx->f(pctx->closure, text, len);
+}
+
+static void
+print_open(cfg_printer_t *pctx) {
+ cfg_print_chars(pctx, "{\n", 2);
+ pctx->indent++;
+}
+
+static void
+print_indent(cfg_printer_t *pctx) {
+ int indent = pctx->indent;
+ while (indent > 0) {
+ cfg_print_chars(pctx, "\t", 1);
+ indent--;
+ }
+}
+
+static void
+print_close(cfg_printer_t *pctx) {
+ pctx->indent--;
+ print_indent(pctx);
+ cfg_print_chars(pctx, "}", 1);
+}
+
+isc_result_t
+cfg_parse_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ INSIST(ret != NULL && *ret == NULL);
+ result = type->parse(pctx, type, ret);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ INSIST(*ret != NULL);
+ return (ISC_R_SUCCESS);
+}
+
+void
+cfg_print(const cfg_obj_t *obj,
+ void (*f)(void *closure, const char *text, int textlen),
+ void *closure)
+{
+ cfg_printer_t pctx;
+ pctx.f = f;
+ pctx.closure = closure;
+ pctx.indent = 0;
+ obj->type->print(&pctx, obj);
+}
+
+
+/* Tuples. */
+
+isc_result_t
+cfg_create_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ const cfg_tuplefielddef_t *fields = type->of;
+ const cfg_tuplefielddef_t *f;
+ cfg_obj_t *obj = NULL;
+ unsigned int nfields = 0;
+ int i;
+
+ for (f = fields; f->name != NULL; f++)
+ nfields++;
+
+ CHECK(cfg_create_obj(pctx, type, &obj));
+ obj->value.tuple = isc_mem_get(pctx->mctx,
+ nfields * sizeof(cfg_obj_t *));
+ if (obj->value.tuple == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ for (f = fields, i = 0; f->name != NULL; f++, i++)
+ obj->value.tuple[i] = NULL;
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (obj != NULL)
+ isc_mem_put(pctx->mctx, obj, sizeof(*obj));
+ return (result);
+}
+
+isc_result_t
+cfg_parse_tuple(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
+{
+ isc_result_t result;
+ const cfg_tuplefielddef_t *fields = type->of;
+ const cfg_tuplefielddef_t *f;
+ cfg_obj_t *obj = NULL;
+ unsigned int i;
+
+ CHECK(cfg_create_tuple(pctx, type, &obj));
+ for (f = fields, i = 0; f->name != NULL; f++, i++)
+ CHECK(cfg_parse_obj(pctx, f->type, &obj->value.tuple[i]));
+
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+void
+cfg_print_tuple(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ unsigned int i;
+ const cfg_tuplefielddef_t *fields = obj->type->of;
+ const cfg_tuplefielddef_t *f;
+ isc_boolean_t need_space = ISC_FALSE;
+
+ for (f = fields, i = 0; f->name != NULL; f++, i++) {
+ const cfg_obj_t *fieldobj = obj->value.tuple[i];
+ if (need_space)
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_obj(pctx, fieldobj);
+ need_space = ISC_TF(fieldobj->type->print != cfg_print_void);
+ }
+}
+
+void
+cfg_doc_tuple(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const cfg_tuplefielddef_t *fields = type->of;
+ const cfg_tuplefielddef_t *f;
+ isc_boolean_t need_space = ISC_FALSE;
+
+ for (f = fields; f->name != NULL; f++) {
+ if (need_space)
+ cfg_print_chars(pctx, " ", 1);
+ cfg_doc_obj(pctx, f->type);
+ need_space = ISC_TF(f->type->print != cfg_print_void);
+ }
+}
+
+static void
+free_tuple(cfg_parser_t *pctx, cfg_obj_t *obj) {
+ unsigned int i;
+ const cfg_tuplefielddef_t *fields = obj->type->of;
+ const cfg_tuplefielddef_t *f;
+ unsigned int nfields = 0;
+
+ if (obj->value.tuple == NULL)
+ return;
+
+ for (f = fields, i = 0; f->name != NULL; f++, i++) {
+ CLEANUP_OBJ(obj->value.tuple[i]);
+ nfields++;
+ }
+ isc_mem_put(pctx->mctx, obj->value.tuple,
+ nfields * sizeof(cfg_obj_t *));
+}
+
+isc_boolean_t
+cfg_obj_istuple(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL);
+ return (ISC_TF(obj->type->rep == &cfg_rep_tuple));
+}
+
+const cfg_obj_t *
+cfg_tuple_get(const cfg_obj_t *tupleobj, const char* name) {
+ unsigned int i;
+ const cfg_tuplefielddef_t *fields;
+ const cfg_tuplefielddef_t *f;
+
+ REQUIRE(tupleobj != NULL && tupleobj->type->rep == &cfg_rep_tuple);
+
+ fields = tupleobj->type->of;
+ for (f = fields, i = 0; f->name != NULL; f++, i++) {
+ if (strcmp(f->name, name) == 0)
+ return (tupleobj->value.tuple[i]);
+ }
+ INSIST(0);
+ return (NULL);
+}
+
+isc_result_t
+cfg_parse_special(cfg_parser_t *pctx, int special) {
+ isc_result_t result;
+ CHECK(cfg_gettoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_special &&
+ pctx->token.value.as_char == special)
+ return (ISC_R_SUCCESS);
+
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "'%c' expected", special);
+ return (ISC_R_UNEXPECTEDTOKEN);
+ cleanup:
+ return (result);
+}
+
+/*
+ * Parse a required semicolon. If it is not there, log
+ * an error and increment the error count but continue
+ * parsing. Since the next token is pushed back,
+ * care must be taken to make sure it is eventually
+ * consumed or an infinite loop may result.
+ */
+static isc_result_t
+parse_semicolon(cfg_parser_t *pctx) {
+ isc_result_t result;
+ CHECK(cfg_gettoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_special &&
+ pctx->token.value.as_char == ';')
+ return (ISC_R_SUCCESS);
+
+ cfg_parser_error(pctx, CFG_LOG_BEFORE, "missing ';'");
+ cfg_ungettoken(pctx);
+ cleanup:
+ return (result);
+}
+
+/*
+ * Parse EOF, logging and returning an error if not there.
+ */
+static isc_result_t
+parse_eof(cfg_parser_t *pctx) {
+ isc_result_t result;
+ CHECK(cfg_gettoken(pctx, 0));
+
+ if (pctx->token.type == isc_tokentype_eof)
+ return (ISC_R_SUCCESS);
+
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "syntax error");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ cleanup:
+ return (result);
+}
+
+/* A list of files, used internally for pctx->files. */
+
+static cfg_type_t cfg_type_filelist = {
+ "filelist", NULL, print_list, NULL, &cfg_rep_list,
+ &cfg_type_qstring
+};
+
+isc_result_t
+cfg_parser_create(isc_mem_t *mctx, isc_log_t *lctx, cfg_parser_t **ret) {
+ isc_result_t result;
+ cfg_parser_t *pctx;
+ isc_lexspecials_t specials;
+
+ REQUIRE(mctx != NULL);
+ REQUIRE(ret != NULL && *ret == NULL);
+
+ pctx = isc_mem_get(mctx, sizeof(*pctx));
+ if (pctx == NULL)
+ return (ISC_R_NOMEMORY);
+
+ pctx->mctx = mctx;
+ pctx->lctx = lctx;
+ pctx->lexer = NULL;
+ pctx->seen_eof = ISC_FALSE;
+ pctx->ungotten = ISC_FALSE;
+ pctx->errors = 0;
+ pctx->warnings = 0;
+ pctx->open_files = NULL;
+ pctx->closed_files = NULL;
+ pctx->line = 0;
+ pctx->callback = NULL;
+ pctx->callbackarg = NULL;
+ pctx->token.type = isc_tokentype_unknown;
+
+ memset(specials, 0, sizeof(specials));
+ specials['{'] = 1;
+ specials['}'] = 1;
+ specials[';'] = 1;
+ specials['/'] = 1;
+ specials['"'] = 1;
+ specials['!'] = 1;
+
+ CHECK(isc_lex_create(pctx->mctx, 1024, &pctx->lexer));
+
+ isc_lex_setspecials(pctx->lexer, specials);
+ isc_lex_setcomments(pctx->lexer, (ISC_LEXCOMMENT_C |
+ ISC_LEXCOMMENT_CPLUSPLUS |
+ ISC_LEXCOMMENT_SHELL));
+
+ CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->open_files));
+ CHECK(cfg_create_list(pctx, &cfg_type_filelist, &pctx->closed_files));
+
+ *ret = pctx;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (pctx->lexer != NULL)
+ isc_lex_destroy(&pctx->lexer);
+ CLEANUP_OBJ(pctx->open_files);
+ CLEANUP_OBJ(pctx->closed_files);
+ isc_mem_put(mctx, pctx, sizeof(*pctx));
+ return (result);
+}
+
+static isc_result_t
+parser_openfile(cfg_parser_t *pctx, const char *filename) {
+ isc_result_t result;
+ cfg_listelt_t *elt = NULL;
+ cfg_obj_t *stringobj = NULL;
+
+ result = isc_lex_openfile(pctx->lexer, filename);
+ if (result != ISC_R_SUCCESS) {
+ cfg_parser_error(pctx, 0, "open: %s: %s",
+ filename, isc_result_totext(result));
+ goto cleanup;
+ }
+
+ CHECK(create_string(pctx, filename, &cfg_type_qstring, &stringobj));
+ CHECK(create_listelt(pctx, &elt));
+ elt->obj = stringobj;
+ ISC_LIST_APPEND(pctx->open_files->value.list, elt, link);
+
+ return (ISC_R_SUCCESS);
+ cleanup:
+ CLEANUP_OBJ(stringobj);
+ return (result);
+}
+
+void
+cfg_parser_setcallback(cfg_parser_t *pctx,
+ cfg_parsecallback_t callback,
+ void *arg)
+{
+ pctx->callback = callback;
+ pctx->callbackarg = arg;
+}
+
+/*
+ * Parse a configuration using a pctx where a lexer has already
+ * been set up with a source.
+ */
+static isc_result_t
+parse2(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+
+ result = cfg_parse_obj(pctx, type, &obj);
+
+ if (pctx->errors != 0) {
+ /* Errors have been logged. */
+ if (result == ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ goto cleanup;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ /* Parsing failed but no errors have been logged. */
+ cfg_parser_error(pctx, 0, "parsing failed");
+ goto cleanup;
+ }
+
+ CHECK(parse_eof(pctx));
+
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+isc_result_t
+cfg_parse_file(cfg_parser_t *pctx, const char *filename,
+ const cfg_type_t *type, cfg_obj_t **ret)
+{
+ isc_result_t result;
+
+ REQUIRE(filename != NULL);
+
+ CHECK(parser_openfile(pctx, filename));
+ CHECK(parse2(pctx, type, ret));
+ cleanup:
+ return (result);
+}
+
+
+isc_result_t
+cfg_parse_buffer(cfg_parser_t *pctx, isc_buffer_t *buffer,
+ const cfg_type_t *type, cfg_obj_t **ret)
+{
+ isc_result_t result;
+ REQUIRE(buffer != NULL);
+ CHECK(isc_lex_openbuffer(pctx->lexer, buffer));
+ CHECK(parse2(pctx, type, ret));
+ cleanup:
+ return (result);
+}
+
+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));
+ *pctxp = NULL;
+}
+
+/*
+ * void
+ */
+isc_result_t
+cfg_parse_void(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ UNUSED(type);
+ return (cfg_create_obj(pctx, &cfg_type_void, ret));
+}
+
+void
+cfg_print_void(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ UNUSED(pctx);
+ UNUSED(obj);
+}
+
+void
+cfg_doc_void(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(pctx);
+ UNUSED(type);
+}
+
+isc_boolean_t
+cfg_obj_isvoid(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL);
+ return (ISC_TF(obj->type->rep == &cfg_rep_void));
+}
+
+cfg_type_t cfg_type_void = {
+ "void", cfg_parse_void, cfg_print_void, cfg_doc_void, &cfg_rep_void,
+ NULL };
+
+
+/*
+ * uint32
+ */
+isc_result_t
+cfg_parse_uint32(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ UNUSED(type);
+
+ CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
+ if (pctx->token.type != isc_tokentype_number) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected number");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+
+ CHECK(cfg_create_obj(pctx, &cfg_type_uint32, &obj));
+
+ obj->value.uint32 = pctx->token.value.as_ulong;
+ *ret = obj;
+ cleanup:
+ return (result);
+}
+
+void
+cfg_print_cstr(cfg_printer_t *pctx, const char *s) {
+ cfg_print_chars(pctx, s, strlen(s));
+}
+
+void
+cfg_print_rawuint(cfg_printer_t *pctx, unsigned int u) {
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%u", u);
+ cfg_print_cstr(pctx, buf);
+}
+
+void
+cfg_print_uint32(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ cfg_print_rawuint(pctx, obj->value.uint32);
+}
+
+isc_boolean_t
+cfg_obj_isuint32(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL);
+ return (ISC_TF(obj->type->rep == &cfg_rep_uint32));
+}
+
+isc_uint32_t
+cfg_obj_asuint32(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_uint32);
+ return (obj->value.uint32);
+}
+
+cfg_type_t cfg_type_uint32 = {
+ "integer", cfg_parse_uint32, cfg_print_uint32, cfg_doc_terminal,
+ &cfg_rep_uint32, NULL
+};
+
+
+/*
+ * uint64
+ */
+isc_boolean_t
+cfg_obj_isuint64(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL);
+ return (ISC_TF(obj->type->rep == &cfg_rep_uint64));
+}
+
+isc_uint64_t
+cfg_obj_asuint64(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_uint64);
+ return (obj->value.uint64);
+}
+
+void
+cfg_print_uint64(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%" ISC_PRINT_QUADFORMAT "u",
+ obj->value.uint64);
+ cfg_print_cstr(pctx, buf);
+}
+
+cfg_type_t cfg_type_uint64 = {
+ "64_bit_integer", NULL, cfg_print_uint64, cfg_doc_terminal,
+ &cfg_rep_uint64, NULL
+};
+
+/*
+ * qstring (quoted string), ustring (unquoted string), astring
+ * (any string)
+ */
+
+/* Create a string object from a null-terminated C string. */
+static isc_result_t
+create_string(cfg_parser_t *pctx, const char *contents, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ int len;
+
+ CHECK(cfg_create_obj(pctx, type, &obj));
+ len = strlen(contents);
+ obj->value.string.length = len;
+ obj->value.string.base = isc_mem_get(pctx->mctx, len + 1);
+ if (obj->value.string.base == 0) {
+ isc_mem_put(pctx->mctx, obj, sizeof(*obj));
+ return (ISC_R_NOMEMORY);
+ }
+ memcpy(obj->value.string.base, contents, len);
+ obj->value.string.base[len] = '\0';
+
+ *ret = obj;
+ cleanup:
+ return (result);
+}
+
+isc_result_t
+cfg_parse_qstring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ UNUSED(type);
+
+ CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
+ if (pctx->token.type != isc_tokentype_qstring) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected quoted string");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ return (create_string(pctx,
+ TOKEN_STRING(pctx),
+ &cfg_type_qstring,
+ ret));
+ cleanup:
+ return (result);
+}
+
+static isc_result_t
+parse_ustring(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ UNUSED(type);
+
+ CHECK(cfg_gettoken(pctx, 0));
+ if (pctx->token.type != isc_tokentype_string) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected unquoted string");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ return (create_string(pctx,
+ TOKEN_STRING(pctx),
+ &cfg_type_ustring,
+ ret));
+ cleanup:
+ return (result);
+}
+
+isc_result_t
+cfg_parse_astring(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ isc_result_t result;
+ UNUSED(type);
+
+ CHECK(cfg_getstringtoken(pctx));
+ return (create_string(pctx,
+ TOKEN_STRING(pctx),
+ &cfg_type_qstring,
+ ret));
+ cleanup:
+ return (result);
+}
+
+isc_boolean_t
+cfg_is_enum(const char *s, const char *const *enums) {
+ const char * const *p;
+ for (p = enums; *p != NULL; p++) {
+ if (strcasecmp(*p, s) == 0)
+ return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
+static isc_result_t
+check_enum(cfg_parser_t *pctx, cfg_obj_t *obj, const char *const *enums) {
+ const char *s = obj->value.string.base;
+ if (cfg_is_enum(s, enums))
+ return (ISC_R_SUCCESS);
+ cfg_parser_error(pctx, 0, "'%s' unexpected", s);
+ return (ISC_R_UNEXPECTEDTOKEN);
+}
+
+isc_result_t
+cfg_parse_enum(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ CHECK(parse_ustring(pctx, NULL, &obj));
+ CHECK(check_enum(pctx, obj, type->of));
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+ cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+void
+cfg_doc_enum(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const char * const *p;
+ cfg_print_chars(pctx, "( ", 2);
+ for (p = type->of; *p != NULL; p++) {
+ cfg_print_cstr(pctx, *p);
+ if (p[1] != NULL)
+ cfg_print_chars(pctx, " | ", 3);
+ }
+ cfg_print_chars(pctx, " )", 2);
+}
+
+void
+cfg_print_ustring(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ cfg_print_chars(pctx, obj->value.string.base, obj->value.string.length);
+}
+
+static void
+print_qstring(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
+free_string(cfg_parser_t *pctx, cfg_obj_t *obj) {
+ isc_mem_put(pctx->mctx, obj->value.string.base,
+ obj->value.string.length + 1);
+}
+
+isc_boolean_t
+cfg_obj_isstring(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL);
+ return (ISC_TF(obj->type->rep == &cfg_rep_string));
+}
+
+const char *
+cfg_obj_asstring(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_string);
+ return (obj->value.string.base);
+}
+
+/* Quoted string only */
+cfg_type_t cfg_type_qstring = {
+ "quoted_string", cfg_parse_qstring, print_qstring, cfg_doc_terminal,
+ &cfg_rep_string, NULL
+};
+
+/* Unquoted string only */
+cfg_type_t cfg_type_ustring = {
+ "string", parse_ustring, cfg_print_ustring, cfg_doc_terminal,
+ &cfg_rep_string, NULL
+};
+
+/* Any string (quoted or unquoted); printed with quotes */
+cfg_type_t cfg_type_astring = {
+ "string", cfg_parse_astring, print_qstring, cfg_doc_terminal,
+ &cfg_rep_string, NULL
+};
+
+/*
+ * Booleans
+ */
+
+isc_boolean_t
+cfg_obj_isboolean(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL);
+ return (ISC_TF(obj->type->rep == &cfg_rep_boolean));
+}
+
+isc_boolean_t
+cfg_obj_asboolean(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_boolean);
+ 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 result;
+ isc_boolean_t value;
+ cfg_obj_t *obj = NULL;
+ UNUSED(type);
+
+ result = cfg_gettoken(pctx, 0);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (pctx->token.type != isc_tokentype_string)
+ goto bad_boolean;
+
+ if ((strcasecmp(TOKEN_STRING(pctx), "true") == 0) ||
+ (strcasecmp(TOKEN_STRING(pctx), "yes") == 0) ||
+ (strcmp(TOKEN_STRING(pctx), "1") == 0)) {
+ value = ISC_TRUE;
+ } else if ((strcasecmp(TOKEN_STRING(pctx), "false") == 0) ||
+ (strcasecmp(TOKEN_STRING(pctx), "no") == 0) ||
+ (strcmp(TOKEN_STRING(pctx), "0") == 0)) {
+ value = ISC_FALSE;
+ } else {
+ goto bad_boolean;
+ }
+
+ CHECK(cfg_create_obj(pctx, &cfg_type_boolean, &obj));
+ obj->value.boolean = value;
+ *ret = obj;
+ return (result);
+
+ bad_boolean:
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "boolean expected");
+ return (ISC_R_UNEXPECTEDTOKEN);
+
+ cleanup:
+ return (result);
+}
+
+static void
+print_boolean(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ if (obj->value.boolean)
+ cfg_print_chars(pctx, "yes", 3);
+ else
+ cfg_print_chars(pctx, "no", 2);
+}
+
+cfg_type_t cfg_type_boolean = {
+ "boolean", parse_boolean, print_boolean, cfg_doc_terminal,
+ &cfg_rep_boolean, NULL
+};
+
+/*
+ * Lists.
+ */
+
+isc_result_t
+cfg_create_list(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **obj) {
+ isc_result_t result;
+ CHECK(cfg_create_obj(pctx, type, obj));
+ ISC_LIST_INIT((*obj)->value.list);
+ cleanup:
+ return (result);
+}
+
+static isc_result_t
+create_listelt(cfg_parser_t *pctx, cfg_listelt_t **eltp) {
+ cfg_listelt_t *elt;
+ elt = isc_mem_get(pctx->mctx, sizeof(*elt));
+ if (elt == NULL)
+ return (ISC_R_NOMEMORY);
+ elt->obj = NULL;
+ ISC_LINK_INIT(elt, link);
+ *eltp = elt;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+free_list_elt(cfg_parser_t *pctx, cfg_listelt_t *elt) {
+ cfg_obj_destroy(pctx, &elt->obj);
+ isc_mem_put(pctx->mctx, elt, sizeof(*elt));
+}
+
+static void
+free_list(cfg_parser_t *pctx, cfg_obj_t *obj) {
+ cfg_listelt_t *elt, *next;
+ for (elt = ISC_LIST_HEAD(obj->value.list);
+ elt != NULL;
+ elt = next)
+ {
+ next = ISC_LIST_NEXT(elt, link);
+ free_list_elt(pctx, elt);
+ }
+}
+
+isc_result_t
+cfg_parse_listelt(cfg_parser_t *pctx, const cfg_type_t *elttype,
+ cfg_listelt_t **ret)
+{
+ isc_result_t result;
+ cfg_listelt_t *elt = NULL;
+ cfg_obj_t *value = NULL;
+
+ CHECK(create_listelt(pctx, &elt));
+
+ result = cfg_parse_obj(pctx, elttype, &value);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ elt->obj = value;
+
+ *ret = elt;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_mem_put(pctx->mctx, elt, sizeof(*elt));
+ return (result);
+}
+
+/*
+ * Parse a homogeneous list whose elements are of type 'elttype'
+ * and where each element is terminated by a semicolon.
+ */
+static isc_result_t
+parse_list(cfg_parser_t *pctx, const cfg_type_t *listtype, cfg_obj_t **ret)
+{
+ cfg_obj_t *listobj = NULL;
+ const cfg_type_t *listof = listtype->of;
+ isc_result_t result;
+ cfg_listelt_t *elt = NULL;
+
+ CHECK(cfg_create_list(pctx, listtype, &listobj));
+
+ for (;;) {
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_special &&
+ pctx->token.value.as_char == /*{*/ '}')
+ break;
+ CHECK(cfg_parse_listelt(pctx, listof, &elt));
+ CHECK(parse_semicolon(pctx));
+ ISC_LIST_APPEND(listobj->value.list, elt, link);
+ elt = NULL;
+ }
+ *ret = listobj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (elt != NULL)
+ free_list_elt(pctx, elt);
+ CLEANUP_OBJ(listobj);
+ return (result);
+}
+
+static void
+print_list(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ const cfg_list_t *list = &obj->value.list;
+ const cfg_listelt_t *elt;
+
+ for (elt = ISC_LIST_HEAD(*list);
+ elt != NULL;
+ elt = ISC_LIST_NEXT(elt, link)) {
+ print_indent(pctx);
+ cfg_print_obj(pctx, elt->obj);
+ cfg_print_chars(pctx, ";\n", 2);
+ }
+}
+
+isc_result_t
+cfg_parse_bracketed_list(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ isc_result_t result;
+ CHECK(cfg_parse_special(pctx, '{'));
+ CHECK(parse_list(pctx, type, ret));
+ CHECK(cfg_parse_special(pctx, '}'));
+ cleanup:
+ return (result);
+}
+
+void
+cfg_print_bracketed_list(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ print_open(pctx);
+ print_list(pctx, obj);
+ print_close(pctx);
+}
+
+void
+cfg_doc_bracketed_list(cfg_printer_t *pctx, const cfg_type_t *type) {
+ cfg_print_chars(pctx, "{ ", 2);
+ cfg_doc_obj(pctx, type->of);
+ cfg_print_chars(pctx, "; ... }", 7);
+}
+
+/*
+ * Parse a homogeneous list whose elements are of type 'elttype'
+ * and where elements are separated by space. The list ends
+ * before the first semicolon.
+ */
+isc_result_t
+cfg_parse_spacelist(cfg_parser_t *pctx, const cfg_type_t *listtype,
+ cfg_obj_t **ret)
+{
+ cfg_obj_t *listobj = NULL;
+ const cfg_type_t *listof = listtype->of;
+ isc_result_t result;
+
+ CHECK(cfg_create_list(pctx, listtype, &listobj));
+
+ for (;;) {
+ cfg_listelt_t *elt = NULL;
+
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_special &&
+ pctx->token.value.as_char == ';')
+ break;
+ CHECK(cfg_parse_listelt(pctx, listof, &elt));
+ ISC_LIST_APPEND(listobj->value.list, elt, link);
+ }
+ *ret = listobj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ CLEANUP_OBJ(listobj);
+ return (result);
+}
+
+void
+cfg_print_spacelist(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ const cfg_list_t *list = &obj->value.list;
+ const cfg_listelt_t *elt;
+
+ for (elt = ISC_LIST_HEAD(*list);
+ elt != NULL;
+ elt = ISC_LIST_NEXT(elt, link)) {
+ cfg_print_obj(pctx, elt->obj);
+ if (ISC_LIST_NEXT(elt, link) != NULL)
+ cfg_print_chars(pctx, " ", 1);
+ }
+}
+
+isc_boolean_t
+cfg_obj_islist(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL);
+ return (ISC_TF(obj->type->rep == &cfg_rep_list));
+}
+
+const cfg_listelt_t *
+cfg_list_first(const cfg_obj_t *obj) {
+ REQUIRE(obj == NULL || obj->type->rep == &cfg_rep_list);
+ if (obj == NULL)
+ return (NULL);
+ return (ISC_LIST_HEAD(obj->value.list));
+}
+
+const cfg_listelt_t *
+cfg_list_next(const cfg_listelt_t *elt) {
+ REQUIRE(elt != NULL);
+ return (ISC_LIST_NEXT(elt, link));
+}
+
+/*
+ * Return the length of a list object. If obj is NULL or is not
+ * a list, return 0.
+ */
+unsigned int
+cfg_list_length(const cfg_obj_t *obj, isc_boolean_t recurse) {
+ const cfg_listelt_t *elt;
+ unsigned int count = 0;
+
+ if (obj == NULL || !cfg_obj_islist(obj))
+ return (0U);
+ for (elt = cfg_list_first(obj);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ if (recurse && cfg_obj_islist(elt->obj)) {
+ count += cfg_list_length(elt->obj, recurse);
+ } else {
+ count++;
+ }
+ }
+ return (count);
+}
+
+const cfg_obj_t *
+cfg_listelt_value(const cfg_listelt_t *elt) {
+ REQUIRE(elt != NULL);
+ return (elt->obj);
+}
+
+/*
+ * Maps.
+ */
+
+/*
+ * Parse a map body. That's something like
+ *
+ * "foo 1; bar { glub; }; zap true; zap false;"
+ *
+ * i.e., a sequence of option names followed by values and
+ * terminated by semicolons. Used for the top level of
+ * the named.conf syntax, as well as for the body of the
+ * options, view, zone, and other statements.
+ */
+isc_result_t
+cfg_parse_mapbody(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
+{
+ const cfg_clausedef_t * const *clausesets = type->of;
+ isc_result_t result;
+ const cfg_clausedef_t * const *clauseset;
+ const cfg_clausedef_t *clause;
+ cfg_obj_t *value = NULL;
+ cfg_obj_t *obj = NULL;
+ cfg_obj_t *eltobj = NULL;
+ cfg_obj_t *includename = NULL;
+ isc_symvalue_t symval;
+ cfg_list_t *list = NULL;
+
+ CHECK(create_map(pctx, type, &obj));
+
+ obj->value.map.clausesets = clausesets;
+
+ for (;;) {
+ cfg_listelt_t *elt;
+
+ redo:
+ /*
+ * Parse the option name and see if it is known.
+ */
+ CHECK(cfg_gettoken(pctx, 0));
+
+ if (pctx->token.type != isc_tokentype_string) {
+ cfg_ungettoken(pctx);
+ break;
+ }
+
+ /*
+ * We accept "include" statements wherever a map body
+ * clause can occur.
+ */
+ if (strcasecmp(TOKEN_STRING(pctx), "include") == 0) {
+ /*
+ * Turn the file name into a temporary configuration
+ * object just so that it is not overwritten by the
+ * semicolon token.
+ */
+ CHECK(cfg_parse_obj(pctx, &cfg_type_qstring, &includename));
+ CHECK(parse_semicolon(pctx));
+ CHECK(parser_openfile(pctx, includename->
+ value.string.base));
+ cfg_obj_destroy(pctx, &includename);
+ goto redo;
+ }
+
+ clause = NULL;
+ for (clauseset = clausesets; *clauseset != NULL; clauseset++) {
+ for (clause = *clauseset;
+ clause->name != NULL;
+ clause++) {
+ if (strcasecmp(TOKEN_STRING(pctx),
+ clause->name) == 0)
+ goto done;
+ }
+ }
+ done:
+ if (clause == NULL || clause->name == NULL) {
+ cfg_parser_error(pctx, CFG_LOG_NOPREP, "unknown option");
+ /*
+ * Try to recover by parsing this option as an unknown
+ * option and discarding it.
+ */
+ CHECK(cfg_parse_obj(pctx, &cfg_type_unsupported, &eltobj));
+ cfg_obj_destroy(pctx, &eltobj);
+ CHECK(parse_semicolon(pctx));
+ continue;
+ }
+
+ /* Clause is known. */
+
+ /* Issue warnings if appropriate */
+ if ((clause->flags & CFG_CLAUSEFLAG_OBSOLETE) != 0)
+ cfg_parser_warning(pctx, 0, "option '%s' is obsolete",
+ clause->name);
+ if ((clause->flags & CFG_CLAUSEFLAG_NOTIMP) != 0)
+ cfg_parser_warning(pctx, 0, "option '%s' is "
+ "not implemented", clause->name);
+ if ((clause->flags & CFG_CLAUSEFLAG_NYI) != 0)
+ cfg_parser_warning(pctx, 0, "option '%s' is "
+ "not implemented", clause->name);
+ /*
+ * Don't log options with CFG_CLAUSEFLAG_NEWDEFAULT
+ * set here - we need to log the *lack* of such an option,
+ * not its presence.
+ */
+
+ /* See if the clause already has a value; if not create one. */
+ result = isc_symtab_lookup(obj->value.map.symtab,
+ clause->name, 0, &symval);
+
+ if ((clause->flags & CFG_CLAUSEFLAG_MULTI) != 0) {
+ /* Multivalued clause */
+ cfg_obj_t *listobj = NULL;
+ if (result == ISC_R_NOTFOUND) {
+ CHECK(cfg_create_list(pctx,
+ &cfg_type_implicitlist,
+ &listobj));
+ symval.as_pointer = listobj;
+ result = isc_symtab_define(obj->value.
+ map.symtab,
+ clause->name,
+ 1, symval,
+ isc_symexists_reject);
+ if (result != ISC_R_SUCCESS) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "isc_symtab_define(%s) "
+ "failed", clause->name);
+ isc_mem_put(pctx->mctx, list,
+ sizeof(cfg_list_t));
+ goto cleanup;
+ }
+ } else {
+ INSIST(result == ISC_R_SUCCESS);
+ listobj = symval.as_pointer;
+ }
+
+ elt = NULL;
+ CHECK(cfg_parse_listelt(pctx, clause->type, &elt));
+ CHECK(parse_semicolon(pctx));
+
+ ISC_LIST_APPEND(listobj->value.list, elt, link);
+ } else {
+ /* Single-valued clause */
+ if (result == ISC_R_NOTFOUND) {
+ isc_boolean_t callback =
+ ISC_TF((clause->flags &
+ CFG_CLAUSEFLAG_CALLBACK) != 0);
+ CHECK(parse_symtab_elt(pctx, clause->name,
+ clause->type,
+ obj->value.map.symtab,
+ callback));
+ CHECK(parse_semicolon(pctx));
+ } else if (result == ISC_R_SUCCESS) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "'%s' redefined",
+ clause->name);
+ result = ISC_R_EXISTS;
+ goto cleanup;
+ } else {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "isc_symtab_define() failed");
+ goto cleanup;
+ }
+ }
+ }
+
+
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ CLEANUP_OBJ(value);
+ CLEANUP_OBJ(obj);
+ CLEANUP_OBJ(eltobj);
+ CLEANUP_OBJ(includename);
+ return (result);
+}
+
+static isc_result_t
+parse_symtab_elt(cfg_parser_t *pctx, const char *name,
+ cfg_type_t *elttype, isc_symtab_t *symtab,
+ isc_boolean_t callback)
+{
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ isc_symvalue_t symval;
+
+ CHECK(cfg_parse_obj(pctx, elttype, &obj));
+
+ if (callback && pctx->callback != NULL)
+ CHECK(pctx->callback(name, obj, pctx->callbackarg));
+
+ symval.as_pointer = obj;
+ CHECK(isc_symtab_define(symtab, name,
+ 1, symval,
+ isc_symexists_reject));
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+/*
+ * Parse a map; e.g., "{ foo 1; bar { glub; }; zap true; zap false; }"
+ */
+isc_result_t
+cfg_parse_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ CHECK(cfg_parse_special(pctx, '{'));
+ CHECK(cfg_parse_mapbody(pctx, type, ret));
+ CHECK(cfg_parse_special(pctx, '}'));
+ cleanup:
+ return (result);
+}
+
+/*
+ * Subroutine for cfg_parse_named_map() and cfg_parse_addressed_map().
+ */
+static isc_result_t
+parse_any_named_map(cfg_parser_t *pctx, cfg_type_t *nametype, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ isc_result_t result;
+ cfg_obj_t *idobj = NULL;
+ cfg_obj_t *mapobj = NULL;
+
+ CHECK(cfg_parse_obj(pctx, nametype, &idobj));
+ CHECK(cfg_parse_map(pctx, type, &mapobj));
+ mapobj->value.map.id = idobj;
+ idobj = NULL;
+ *ret = mapobj;
+ cleanup:
+ CLEANUP_OBJ(idobj);
+ return (result);
+}
+
+/*
+ * Parse a map identified by a string name. E.g., "name { foo 1; }".
+ * Used for the "key" and "channel" statements.
+ */
+isc_result_t
+cfg_parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ return (parse_any_named_map(pctx, &cfg_type_astring, type, ret));
+}
+
+/*
+ * Parse a map identified by a network address.
+ * Used to be used for the "server" statement.
+ */
+isc_result_t
+cfg_parse_addressed_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ return (parse_any_named_map(pctx, &cfg_type_netaddr, type, ret));
+}
+
+/*
+ * Parse a map identified by a network prefix.
+ * Used for the "server" statement.
+ */
+isc_result_t
+cfg_parse_netprefix_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ return (parse_any_named_map(pctx, &cfg_type_netprefix, type, ret));
+}
+
+void
+cfg_print_mapbody(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+ const cfg_clausedef_t * const *clauseset;
+
+ for (clauseset = obj->value.map.clausesets;
+ *clauseset != NULL;
+ clauseset++)
+ {
+ isc_symvalue_t symval;
+ const cfg_clausedef_t *clause;
+
+ for (clause = *clauseset;
+ clause->name != NULL;
+ clause++) {
+ result = isc_symtab_lookup(obj->value.map.symtab,
+ clause->name, 0, &symval);
+ if (result == ISC_R_SUCCESS) {
+ cfg_obj_t *obj = symval.as_pointer;
+ if (obj->type == &cfg_type_implicitlist) {
+ /* Multivalued. */
+ cfg_list_t *list = &obj->value.list;
+ cfg_listelt_t *elt;
+ for (elt = ISC_LIST_HEAD(*list);
+ elt != NULL;
+ elt = ISC_LIST_NEXT(elt, link)) {
+ print_indent(pctx);
+ cfg_print_cstr(pctx, clause->name);
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_obj(pctx, elt->obj);
+ cfg_print_chars(pctx, ";\n", 2);
+ }
+ } else {
+ /* Single-valued. */
+ print_indent(pctx);
+ cfg_print_cstr(pctx, clause->name);
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_obj(pctx, obj);
+ cfg_print_chars(pctx, ";\n", 2);
+ }
+ } else if (result == ISC_R_NOTFOUND) {
+ ; /* do nothing */
+ } else {
+ INSIST(0);
+ }
+ }
+ }
+}
+
+void
+cfg_doc_mapbody(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const cfg_clausedef_t * const *clauseset;
+ const cfg_clausedef_t *clause;
+
+ for (clauseset = type->of; *clauseset != NULL; clauseset++) {
+ for (clause = *clauseset;
+ clause->name != NULL;
+ clause++) {
+ cfg_print_cstr(pctx, clause->name);
+ cfg_print_chars(pctx, " ", 1);
+ cfg_doc_obj(pctx, clause->type);
+ cfg_print_chars(pctx, ";", 1);
+ /* XXX print flags here? */
+ cfg_print_chars(pctx, "\n\n", 2);
+ }
+ }
+}
+
+static struct flagtext {
+ unsigned int flag;
+ const char *text;
+} flagtexts[] = {
+ { CFG_CLAUSEFLAG_NOTIMP, "not implemented" },
+ { CFG_CLAUSEFLAG_NYI, "not yet implemented" },
+ { CFG_CLAUSEFLAG_OBSOLETE, "obsolete" },
+ { CFG_CLAUSEFLAG_NEWDEFAULT, "default changed" },
+ { CFG_CLAUSEFLAG_TESTONLY, "test only" },
+ { 0, NULL }
+};
+
+void
+cfg_print_map(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ if (obj->value.map.id != NULL) {
+ cfg_print_obj(pctx, obj->value.map.id);
+ cfg_print_chars(pctx, " ", 1);
+ }
+ print_open(pctx);
+ cfg_print_mapbody(pctx, obj);
+ print_close(pctx);
+}
+
+static void
+print_clause_flags(cfg_printer_t *pctx, unsigned int flags) {
+ struct flagtext *p;
+ isc_boolean_t first = ISC_TRUE;
+ for (p = flagtexts; p->flag != 0; p++) {
+ if ((flags & p->flag) != 0) {
+ if (first)
+ cfg_print_chars(pctx, " // ", 4);
+ else
+ cfg_print_chars(pctx, ", ", 2);
+ cfg_print_cstr(pctx, p->text);
+ first = ISC_FALSE;
+ }
+ }
+}
+
+void
+cfg_doc_map(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const cfg_clausedef_t * const *clauseset;
+ const cfg_clausedef_t *clause;
+
+ if (type->parse == cfg_parse_named_map) {
+ cfg_doc_obj(pctx, &cfg_type_astring);
+ cfg_print_chars(pctx, " ", 1);
+ } else if (type->parse == cfg_parse_addressed_map) {
+ cfg_doc_obj(pctx, &cfg_type_netaddr);
+ cfg_print_chars(pctx, " ", 1);
+ } else if (type->parse == cfg_parse_netprefix_map) {
+ cfg_doc_obj(pctx, &cfg_type_netprefix);
+ cfg_print_chars(pctx, " ", 1);
+ }
+
+ print_open(pctx);
+
+ for (clauseset = type->of; *clauseset != NULL; clauseset++) {
+ for (clause = *clauseset;
+ clause->name != NULL;
+ clause++) {
+ print_indent(pctx);
+ cfg_print_cstr(pctx, clause->name);
+ if (clause->type->print != cfg_print_void)
+ cfg_print_chars(pctx, " ", 1);
+ cfg_doc_obj(pctx, clause->type);
+ cfg_print_chars(pctx, ";", 1);
+ print_clause_flags(pctx, clause->flags);
+ cfg_print_chars(pctx, "\n", 1);
+ }
+ }
+ print_close(pctx);
+}
+
+isc_boolean_t
+cfg_obj_ismap(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL);
+ return (ISC_TF(obj->type->rep == &cfg_rep_map));
+}
+
+isc_result_t
+cfg_map_get(const cfg_obj_t *mapobj, const char* name, const cfg_obj_t **obj) {
+ isc_result_t result;
+ isc_symvalue_t val;
+ const cfg_map_t *map;
+
+ REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
+ REQUIRE(name != NULL);
+ REQUIRE(obj != NULL && *obj == NULL);
+
+ map = &mapobj->value.map;
+
+ result = isc_symtab_lookup(map->symtab, name, MAP_SYM, &val);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ *obj = val.as_pointer;
+ return (ISC_R_SUCCESS);
+}
+
+const cfg_obj_t *
+cfg_map_getname(const cfg_obj_t *mapobj) {
+ REQUIRE(mapobj != NULL && mapobj->type->rep == &cfg_rep_map);
+ return (mapobj->value.map.id);
+}
+
+
+/* Parse an arbitrary token, storing its raw text representation. */
+static isc_result_t
+parse_token(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ cfg_obj_t *obj = NULL;
+ isc_result_t result;
+ isc_region_t r;
+
+ UNUSED(type);
+
+ CHECK(cfg_create_obj(pctx, &cfg_type_token, &obj));
+ CHECK(cfg_gettoken(pctx, CFG_LEXOPT_QSTRING));
+ if (pctx->token.type == isc_tokentype_eof) {
+ cfg_ungettoken(pctx);
+ result = ISC_R_EOF;
+ goto cleanup;
+ }
+
+ isc_lex_getlasttokentext(pctx->lexer, &pctx->token, &r);
+
+ obj->value.string.base = isc_mem_get(pctx->mctx, r.length + 1);
+ if (obj->value.string.base == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup;
+ }
+ obj->value.string.length = r.length;
+ memcpy(obj->value.string.base, r.base, r.length);
+ obj->value.string.base[r.length] = '\0';
+ *ret = obj;
+ return (result);
+
+ cleanup:
+ if (obj != NULL)
+ isc_mem_put(pctx->mctx, obj, sizeof(*obj));
+ return (result);
+}
+
+cfg_type_t cfg_type_token = {
+ "token", parse_token, cfg_print_ustring, cfg_doc_terminal,
+ &cfg_rep_string, NULL
+};
+
+/*
+ * An unsupported option. This is just a list of tokens with balanced braces
+ * ending in a semicolon.
+ */
+
+static isc_result_t
+parse_unsupported(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ cfg_obj_t *listobj = NULL;
+ isc_result_t result;
+ int braces = 0;
+
+ CHECK(cfg_create_list(pctx, type, &listobj));
+
+ for (;;) {
+ cfg_listelt_t *elt = NULL;
+
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_special) {
+ if (pctx->token.value.as_char == '{')
+ braces++;
+ else if (pctx->token.value.as_char == '}')
+ braces--;
+ else if (pctx->token.value.as_char == ';')
+ if (braces == 0)
+ break;
+ }
+ if (pctx->token.type == isc_tokentype_eof || braces < 0) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "unexpected token");
+ result = ISC_R_UNEXPECTEDTOKEN;
+ goto cleanup;
+ }
+
+ CHECK(cfg_parse_listelt(pctx, &cfg_type_token, &elt));
+ ISC_LIST_APPEND(listobj->value.list, elt, link);
+ }
+ INSIST(braces == 0);
+ *ret = listobj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ CLEANUP_OBJ(listobj);
+ return (result);
+}
+
+cfg_type_t cfg_type_unsupported = {
+ "unsupported", parse_unsupported, cfg_print_spacelist, cfg_doc_terminal,
+ &cfg_rep_list, NULL
+};
+
+/*
+ * Try interpreting the current token as a network address.
+ *
+ * If CFG_ADDR_WILDOK is set in flags, "*" can be used as a wildcard
+ * and at least one of CFG_ADDR_V4OK and CFG_ADDR_V6OK must also be set. The
+ * "*" is interpreted as the IPv4 wildcard address if CFG_ADDR_V4OK is
+ * set (including the case where CFG_ADDR_V4OK and CFG_ADDR_V6OK are both set),
+ * and the IPv6 wildcard address otherwise.
+ */
+static isc_result_t
+token_addr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
+ char *s;
+ struct in_addr in4a;
+ struct in6_addr in6a;
+
+ if (pctx->token.type != isc_tokentype_string)
+ return (ISC_R_UNEXPECTEDTOKEN);
+
+ s = TOKEN_STRING(pctx);
+ if ((flags & CFG_ADDR_WILDOK) != 0 && strcmp(s, "*") == 0) {
+ if ((flags & CFG_ADDR_V4OK) != 0) {
+ isc_netaddr_any(na);
+ return (ISC_R_SUCCESS);
+ } else if ((flags & CFG_ADDR_V6OK) != 0) {
+ isc_netaddr_any6(na);
+ return (ISC_R_SUCCESS);
+ } else {
+ INSIST(0);
+ }
+ } else {
+ if ((flags & (CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK)) != 0) {
+ if (inet_pton(AF_INET, s, &in4a) == 1) {
+ isc_netaddr_fromin(na, &in4a);
+ return (ISC_R_SUCCESS);
+ }
+ }
+ if ((flags & CFG_ADDR_V4PREFIXOK) != 0 &&
+ strlen(s) <= 15U) {
+ char buf[64];
+ int i;
+
+ strcpy(buf, s);
+ for (i = 0; i < 3; i++) {
+ strcat(buf, ".0");
+ if (inet_pton(AF_INET, buf, &in4a) == 1) {
+ isc_netaddr_fromin(na, &in4a);
+ return (ISC_R_SUCCESS);
+ }
+ }
+ }
+ if ((flags & CFG_ADDR_V6OK) != 0 &&
+ strlen(s) <= 127U) {
+ char buf[128]; /* see lib/bind9/getaddresses.c */
+ char *d; /* zone delimiter */
+ isc_uint32_t zone = 0; /* scope zone ID */
+
+ strcpy(buf, s);
+ d = strchr(buf, '%');
+ if (d != NULL)
+ *d = '\0';
+
+ if (inet_pton(AF_INET6, buf, &in6a) == 1) {
+ if (d != NULL) {
+#ifdef ISC_PLATFORM_HAVESCOPEID
+ isc_result_t result;
+
+ result = isc_netscope_pton(AF_INET6,
+ d + 1,
+ &in6a,
+ &zone);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#else
+ return (ISC_R_BADADDRESSFORM);
+#endif
+ }
+
+ isc_netaddr_fromin6(na, &in6a);
+ isc_netaddr_setzone(na, zone);
+ return (ISC_R_SUCCESS);
+ }
+ }
+ }
+ return (ISC_R_UNEXPECTEDTOKEN);
+}
+
+isc_result_t
+cfg_parse_rawaddr(cfg_parser_t *pctx, unsigned int flags, isc_netaddr_t *na) {
+ isc_result_t result;
+ const char *wild = "";
+ const char *prefix = "";
+
+ CHECK(cfg_gettoken(pctx, 0));
+ result = token_addr(pctx, flags, na);
+ if (result == ISC_R_UNEXPECTEDTOKEN) {
+ if ((flags & CFG_ADDR_WILDOK) != 0)
+ wild = " or '*'";
+ if ((flags & CFG_ADDR_V4PREFIXOK) != 0)
+ wild = " or IPv4 prefix";
+ if ((flags & CFG_ADDR_MASK) == CFG_ADDR_V4OK)
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected IPv4 address%s%s",
+ prefix, wild);
+ else if ((flags & CFG_ADDR_MASK) == CFG_ADDR_V6OK)
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected IPv6 address%s%s",
+ prefix, wild);
+ else
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected IP address%s%s",
+ prefix, wild);
+ }
+ cleanup:
+ return (result);
+}
+
+isc_boolean_t
+cfg_lookingat_netaddr(cfg_parser_t *pctx, unsigned int flags) {
+ isc_result_t result;
+ isc_netaddr_t na_dummy;
+ result = token_addr(pctx, flags, &na_dummy);
+ return (ISC_TF(result == ISC_R_SUCCESS));
+}
+
+isc_result_t
+cfg_parse_rawport(cfg_parser_t *pctx, unsigned int flags, in_port_t *port) {
+ isc_result_t result;
+
+ CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER));
+
+ if ((flags & CFG_ADDR_WILDOK) != 0 &&
+ pctx->token.type == isc_tokentype_string &&
+ strcmp(TOKEN_STRING(pctx), "*") == 0) {
+ *port = 0;
+ return (ISC_R_SUCCESS);
+ }
+ if (pctx->token.type != isc_tokentype_number) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected port number or '*'");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ if (pctx->token.value.as_ulong >= 65536U) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "port number out of range");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ *port = (in_port_t)(pctx->token.value.as_ulong);
+ return (ISC_R_SUCCESS);
+ cleanup:
+ return (result);
+}
+
+void
+cfg_print_rawaddr(cfg_printer_t *pctx, const isc_netaddr_t *na) {
+ isc_result_t result;
+ char text[128];
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, text, sizeof(text));
+ result = isc_netaddr_totext(na, &buf);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ cfg_print_chars(pctx, isc_buffer_base(&buf), isc_buffer_usedlength(&buf));
+}
+
+/* netaddr */
+
+static unsigned int netaddr_flags = CFG_ADDR_V4OK | CFG_ADDR_V6OK;
+static unsigned int netaddr4_flags = CFG_ADDR_V4OK;
+static unsigned int netaddr4wild_flags = CFG_ADDR_V4OK | CFG_ADDR_WILDOK;
+static unsigned int netaddr6_flags = CFG_ADDR_V6OK;
+static unsigned int netaddr6wild_flags = CFG_ADDR_V6OK | CFG_ADDR_WILDOK;
+
+static isc_result_t
+parse_netaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ isc_netaddr_t netaddr;
+ unsigned int flags = *(const unsigned int *)type->of;
+
+ CHECK(cfg_create_obj(pctx, type, &obj));
+ CHECK(cfg_parse_rawaddr(pctx, flags, &netaddr));
+ isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, 0);
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+ cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+static void
+cfg_doc_netaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const unsigned int *flagp = type->of;
+ int n = 0;
+ if (*flagp != CFG_ADDR_V4OK && *flagp != CFG_ADDR_V6OK)
+ cfg_print_chars(pctx, "( ", 2);
+ if (*flagp & CFG_ADDR_V4OK) {
+ cfg_print_cstr(pctx, "<ipv4_address>");
+ n++;
+ }
+ if (*flagp & CFG_ADDR_V6OK) {
+ if (n != 0)
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_cstr(pctx, "<ipv6_address>");
+ n++;
+ }
+ if (*flagp & CFG_ADDR_WILDOK) {
+ if (n != 0)
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_chars(pctx, "*", 1);
+ n++;
+ }
+ if (*flagp != CFG_ADDR_V4OK && *flagp != CFG_ADDR_V6OK)
+ cfg_print_chars(pctx, " )", 2);
+}
+
+cfg_type_t cfg_type_netaddr = {
+ "netaddr", parse_netaddr, cfg_print_sockaddr, cfg_doc_netaddr,
+ &cfg_rep_sockaddr, &netaddr_flags
+};
+
+cfg_type_t cfg_type_netaddr4 = {
+ "netaddr4", parse_netaddr, cfg_print_sockaddr, cfg_doc_netaddr,
+ &cfg_rep_sockaddr, &netaddr4_flags
+};
+
+cfg_type_t cfg_type_netaddr4wild = {
+ "netaddr4wild", parse_netaddr, cfg_print_sockaddr, cfg_doc_netaddr,
+ &cfg_rep_sockaddr, &netaddr4wild_flags
+};
+
+cfg_type_t cfg_type_netaddr6 = {
+ "netaddr6", parse_netaddr, cfg_print_sockaddr, cfg_doc_netaddr,
+ &cfg_rep_sockaddr, &netaddr6_flags
+};
+
+cfg_type_t cfg_type_netaddr6wild = {
+ "netaddr6wild", parse_netaddr, cfg_print_sockaddr, cfg_doc_netaddr,
+ &cfg_rep_sockaddr, &netaddr6wild_flags
+};
+
+/* netprefix */
+
+isc_result_t
+cfg_parse_netprefix(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ cfg_obj_t *obj = NULL;
+ isc_result_t result;
+ isc_netaddr_t netaddr;
+ unsigned int addrlen, prefixlen;
+ UNUSED(type);
+
+ CHECK(cfg_parse_rawaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V4PREFIXOK |
+ CFG_ADDR_V6OK, &netaddr));
+ switch (netaddr.family) {
+ case AF_INET:
+ addrlen = 32;
+ break;
+ case AF_INET6:
+ addrlen = 128;
+ break;
+ default:
+ addrlen = 0;
+ INSIST(0);
+ break;
+ }
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_special &&
+ pctx->token.value.as_char == '/') {
+ CHECK(cfg_gettoken(pctx, 0)); /* read "/" */
+ CHECK(cfg_gettoken(pctx, ISC_LEXOPT_NUMBER));
+ if (pctx->token.type != isc_tokentype_number) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected prefix length");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ prefixlen = pctx->token.value.as_ulong;
+ if (prefixlen > addrlen) {
+ cfg_parser_error(pctx, CFG_LOG_NOPREP,
+ "invalid prefix length");
+ return (ISC_R_RANGE);
+ }
+ } else {
+ prefixlen = addrlen;
+ }
+ CHECK(cfg_create_obj(pctx, &cfg_type_netprefix, &obj));
+ obj->value.netprefix.address = netaddr;
+ obj->value.netprefix.prefixlen = prefixlen;
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+ cleanup:
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected network prefix");
+ return (result);
+}
+
+static void
+print_netprefix(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ const cfg_netprefix_t *p = &obj->value.netprefix;
+
+ cfg_print_rawaddr(pctx, &p->address);
+ cfg_print_chars(pctx, "/", 1);
+ cfg_print_rawuint(pctx, p->prefixlen);
+}
+
+isc_boolean_t
+cfg_obj_isnetprefix(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL);
+ return (ISC_TF(obj->type->rep == &cfg_rep_netprefix));
+}
+
+void
+cfg_obj_asnetprefix(const cfg_obj_t *obj, isc_netaddr_t *netaddr,
+ unsigned int *prefixlen) {
+ REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_netprefix);
+ *netaddr = obj->value.netprefix.address;
+ *prefixlen = obj->value.netprefix.prefixlen;
+}
+
+cfg_type_t cfg_type_netprefix = {
+ "netprefix", cfg_parse_netprefix, print_netprefix, cfg_doc_terminal,
+ &cfg_rep_netprefix, NULL
+};
+
+static isc_result_t
+parse_sockaddrsub(cfg_parser_t *pctx, const cfg_type_t *type,
+ int flags, cfg_obj_t **ret)
+{
+ isc_result_t result;
+ isc_netaddr_t netaddr;
+ in_port_t port = 0;
+ cfg_obj_t *obj = NULL;
+
+ CHECK(cfg_create_obj(pctx, type, &obj));
+ CHECK(cfg_parse_rawaddr(pctx, flags, &netaddr));
+ CHECK(cfg_peektoken(pctx, 0));
+ if (pctx->token.type == isc_tokentype_string &&
+ strcasecmp(TOKEN_STRING(pctx), "port") == 0) {
+ CHECK(cfg_gettoken(pctx, 0)); /* read "port" */
+ CHECK(cfg_parse_rawport(pctx, flags, &port));
+ }
+ isc_sockaddr_fromnetaddr(&obj->value.sockaddr, &netaddr, port);
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+static unsigned int sockaddr_flags = CFG_ADDR_V4OK | CFG_ADDR_V6OK;
+cfg_type_t cfg_type_sockaddr = {
+ "sockaddr", cfg_parse_sockaddr, cfg_print_sockaddr, cfg_doc_sockaddr,
+ &cfg_rep_sockaddr, &sockaddr_flags
+};
+
+isc_result_t
+cfg_parse_sockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ const unsigned int *flagp = type->of;
+ return (parse_sockaddrsub(pctx, &cfg_type_sockaddr, *flagp, ret));
+}
+
+void
+cfg_print_sockaddr(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ isc_netaddr_t netaddr;
+ in_port_t port;
+ char buf[ISC_NETADDR_FORMATSIZE];
+
+ isc_netaddr_fromsockaddr(&netaddr, &obj->value.sockaddr);
+ isc_netaddr_format(&netaddr, buf, sizeof(buf));
+ cfg_print_cstr(pctx, buf);
+ port = isc_sockaddr_getport(&obj->value.sockaddr);
+ if (port != 0) {
+ cfg_print_chars(pctx, " port ", 6);
+ cfg_print_rawuint(pctx, port);
+ }
+}
+
+void
+cfg_doc_sockaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
+ const unsigned int *flagp = type->of;
+ int n = 0;
+ cfg_print_chars(pctx, "( ", 2);
+ if (*flagp & CFG_ADDR_V4OK) {
+ cfg_print_cstr(pctx, "<ipv4_address>");
+ n++;
+ }
+ if (*flagp & CFG_ADDR_V6OK) {
+ if (n != 0)
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_cstr(pctx, "<ipv6_address>");
+ n++;
+ }
+ if (*flagp & CFG_ADDR_WILDOK) {
+ if (n != 0)
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_chars(pctx, "*", 1);
+ n++;
+ }
+ cfg_print_chars(pctx, " ) ", 3);
+ if (*flagp & CFG_ADDR_WILDOK) {
+ cfg_print_cstr(pctx, "[ port ( <integer> | * ) ]");
+ } else {
+ cfg_print_cstr(pctx, "[ port <integer> ]");
+ }
+}
+
+isc_boolean_t
+cfg_obj_issockaddr(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL);
+ return (ISC_TF(obj->type->rep == &cfg_rep_sockaddr));
+}
+
+const isc_sockaddr_t *
+cfg_obj_assockaddr(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_sockaddr);
+ return (&obj->value.sockaddr);
+}
+
+isc_result_t
+cfg_gettoken(cfg_parser_t *pctx, int options) {
+ isc_result_t result;
+
+ if (pctx->seen_eof)
+ return (ISC_R_SUCCESS);
+
+ options |= (ISC_LEXOPT_EOF | ISC_LEXOPT_NOMORE);
+
+ redo:
+ pctx->token.type = isc_tokentype_unknown;
+ result = isc_lex_gettoken(pctx->lexer, options, &pctx->token);
+ pctx->ungotten = ISC_FALSE;
+ pctx->line = isc_lex_getsourceline(pctx->lexer);
+
+ switch (result) {
+ case ISC_R_SUCCESS:
+ if (pctx->token.type == isc_tokentype_eof) {
+ result = isc_lex_close(pctx->lexer);
+ INSIST(result == ISC_R_NOMORE ||
+ result == ISC_R_SUCCESS);
+
+ if (isc_lex_getsourcename(pctx->lexer) != NULL) {
+ /*
+ * Closed an included file, not the main file.
+ */
+ cfg_listelt_t *elt;
+ elt = ISC_LIST_TAIL(pctx->open_files->
+ value.list);
+ INSIST(elt != NULL);
+ ISC_LIST_UNLINK(pctx->open_files->
+ value.list, elt, link);
+ ISC_LIST_APPEND(pctx->closed_files->
+ value.list, elt, link);
+ goto redo;
+ }
+ pctx->seen_eof = ISC_TRUE;
+ }
+ break;
+
+ case ISC_R_NOSPACE:
+ /* More understandable than "ran out of space". */
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "token too big");
+ break;
+
+ case ISC_R_IOERROR:
+ cfg_parser_error(pctx, 0, "%s",
+ isc_result_totext(result));
+ break;
+
+ default:
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "%s",
+ isc_result_totext(result));
+ break;
+ }
+ return (result);
+}
+
+void
+cfg_ungettoken(cfg_parser_t *pctx) {
+ if (pctx->seen_eof)
+ return;
+ isc_lex_ungettoken(pctx->lexer, &pctx->token);
+ pctx->ungotten = ISC_TRUE;
+}
+
+isc_result_t
+cfg_peektoken(cfg_parser_t *pctx, int options) {
+ isc_result_t result;
+ CHECK(cfg_gettoken(pctx, options));
+ cfg_ungettoken(pctx);
+ cleanup:
+ return (result);
+}
+
+/*
+ * Get a string token, accepting both the quoted and the unquoted form.
+ * Log an error if the next token is not a string.
+ */
+static isc_result_t
+cfg_getstringtoken(cfg_parser_t *pctx) {
+ isc_result_t result;
+
+ result = cfg_gettoken(pctx, CFG_LEXOPT_QSTRING);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ if (pctx->token.type != isc_tokentype_string &&
+ pctx->token.type != isc_tokentype_qstring) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR, "expected string");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+void
+cfg_parser_error(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ parser_complain(pctx, ISC_FALSE, flags, fmt, args);
+ va_end(args);
+ pctx->errors++;
+}
+
+void
+cfg_parser_warning(cfg_parser_t *pctx, unsigned int flags, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ parser_complain(pctx, ISC_TRUE, flags, fmt, args);
+ va_end(args);
+ pctx->warnings++;
+}
+
+#define MAX_LOG_TOKEN 30 /* How much of a token to quote in log messages. */
+
+static char *
+current_file(cfg_parser_t *pctx) {
+ static char none[] = "none";
+ cfg_listelt_t *elt;
+ cfg_obj_t *fileobj;
+
+ if (pctx->open_files == NULL)
+ return (none);
+ elt = ISC_LIST_TAIL(pctx->open_files->value.list);
+ if (elt == NULL)
+ return (none);
+
+ fileobj = elt->obj;
+ INSIST(fileobj->type == &cfg_type_qstring);
+ return (fileobj->value.string.base);
+}
+
+static void
+parser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,
+ unsigned int flags, const char *format,
+ va_list args)
+{
+ char tokenbuf[MAX_LOG_TOKEN + 10];
+ static char where[ISC_DIR_PATHMAX + 100];
+ static char message[2048];
+ int level = ISC_LOG_ERROR;
+ const char *prep = "";
+ size_t len;
+
+ if (is_warning)
+ level = ISC_LOG_WARNING;
+
+ snprintf(where, sizeof(where), "%s:%u: ",
+ current_file(pctx), pctx->line);
+
+ len = vsnprintf(message, sizeof(message), format, args);
+ if (len >= sizeof(message))
+ FATAL_ERROR(__FILE__, __LINE__,
+ "error message would overflow");
+
+ if ((flags & (CFG_LOG_NEAR|CFG_LOG_BEFORE|CFG_LOG_NOPREP)) != 0) {
+ isc_region_t r;
+
+ if (pctx->ungotten)
+ (void)cfg_gettoken(pctx, 0);
+
+ if (pctx->token.type == isc_tokentype_eof) {
+ snprintf(tokenbuf, sizeof(tokenbuf), "end of file");
+ } else if (pctx->token.type == isc_tokentype_unknown) {
+ flags = 0;
+ tokenbuf[0] = '\0';
+ } else {
+ isc_lex_getlasttokentext(pctx->lexer,
+ &pctx->token, &r);
+ if (r.length > MAX_LOG_TOKEN)
+ snprintf(tokenbuf, sizeof(tokenbuf),
+ "'%.*s...'", MAX_LOG_TOKEN, r.base);
+ else
+ snprintf(tokenbuf, sizeof(tokenbuf),
+ "'%.*s'", (int)r.length, r.base);
+ }
+
+ /* Choose a preposition. */
+ if (flags & CFG_LOG_NEAR)
+ prep = " near ";
+ else if (flags & CFG_LOG_BEFORE)
+ prep = " before ";
+ else
+ prep = " ";
+ } else {
+ tokenbuf[0] = '\0';
+ }
+ isc_log_write(pctx->lctx, CAT, MOD, level,
+ "%s%s%s%s", where, message, prep, tokenbuf);
+}
+
+void
+cfg_obj_log(const cfg_obj_t *obj, isc_log_t *lctx, int level,
+ const char *fmt, ...) {
+ va_list ap;
+ char msgbuf[2048];
+
+ if (! isc_log_wouldlog(lctx, level))
+ return;
+
+ va_start(ap, fmt);
+
+ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
+ isc_log_write(lctx, CAT, MOD, level,
+ "%s:%u: %s",
+ obj->file == NULL ? "<unknown file>" : obj->file,
+ obj->line, msgbuf);
+ va_end(ap);
+}
+
+const char *
+cfg_obj_file(const cfg_obj_t *obj) {
+ return (obj->file);
+}
+
+unsigned int
+cfg_obj_line(const cfg_obj_t *obj) {
+ return (obj->line);
+}
+
+isc_result_t
+cfg_create_obj(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ cfg_obj_t *obj;
+
+ obj = isc_mem_get(pctx->mctx, sizeof(cfg_obj_t));
+ if (obj == NULL)
+ return (ISC_R_NOMEMORY);
+ obj->type = type;
+ obj->file = current_file(pctx);
+ obj->line = pctx->line;
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+map_symtabitem_destroy(char *key, unsigned int type,
+ isc_symvalue_t symval, void *userarg)
+{
+ cfg_obj_t *obj = symval.as_pointer;
+ cfg_parser_t *pctx = (cfg_parser_t *)userarg;
+
+ UNUSED(key);
+ UNUSED(type);
+
+ cfg_obj_destroy(pctx, &obj);
+}
+
+
+static isc_result_t
+create_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ isc_symtab_t *symtab = NULL;
+ cfg_obj_t *obj = NULL;
+
+ CHECK(cfg_create_obj(pctx, type, &obj));
+ CHECK(isc_symtab_create(pctx->mctx, 5, /* XXX */
+ map_symtabitem_destroy,
+ pctx, ISC_FALSE, &symtab));
+ obj->value.map.symtab = symtab;
+ obj->value.map.id = NULL;
+
+ *ret = obj;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ if (obj != NULL)
+ isc_mem_put(pctx->mctx, obj, sizeof(*obj));
+ return (result);
+}
+
+static void
+free_map(cfg_parser_t *pctx, cfg_obj_t *obj) {
+ CLEANUP_OBJ(obj->value.map.id);
+ isc_symtab_destroy(&obj->value.map.symtab);
+}
+
+isc_boolean_t
+cfg_obj_istype(const cfg_obj_t *obj, const cfg_type_t *type) {
+ return (ISC_TF(obj->type == type));
+}
+
+/*
+ * Destroy 'obj', a configuration object created in 'pctx'.
+ */
+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));
+ *objp = NULL;
+}
+
+static void
+free_noop(cfg_parser_t *pctx, cfg_obj_t *obj) {
+ UNUSED(pctx);
+ UNUSED(obj);
+}
+
+void
+cfg_doc_obj(cfg_printer_t *pctx, const cfg_type_t *type) {
+ type->doc(pctx, type);
+}
+
+void
+cfg_doc_terminal(cfg_printer_t *pctx, const cfg_type_t *type) {
+ cfg_print_chars(pctx, "<", 1);
+ cfg_print_cstr(pctx, type->name);
+ cfg_print_chars(pctx, ">", 1);
+}
+
+void
+cfg_print_grammar(const cfg_type_t *type,
+ void (*f)(void *closure, const char *text, int textlen),
+ void *closure)
+{
+ cfg_printer_t pctx;
+ pctx.f = f;
+ pctx.closure = closure;
+ pctx.indent = 0;
+ cfg_doc_obj(&pctx, type);
+}
diff --git a/lib/isccfg/version.c b/lib/isccfg/version.c
new file mode 100644
index 0000000..25b98c6
--- /dev/null
+++ b/lib/isccfg/version.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: version.c,v 1.7 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+#include <isccfg/version.h>
+
+const char cfg_version[] = VERSION;
+
+const unsigned int cfg_libinterface = LIBINTERFACE;
+const unsigned int cfg_librevision = LIBREVISION;
+const unsigned int cfg_libage = LIBAGE;
+
diff --git a/lib/isccfg/win32/DLLMain.c b/lib/isccfg/win32/DLLMain.c
new file mode 100644
index 0000000..73499fb
--- /dev/null
+++ b/lib/isccfg/win32/DLLMain.c
@@ -0,0 +1,60 @@
+/*
+ * 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: DLLMain.c,v 1.6 2007/06/18 23:47:51 tbox Exp $ */
+
+#include <windows.h>
+#include <signal.h>
+
+/*
+ * Called when we enter the DLL
+ */
+__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ /*
+ * The DLL is loading due to process
+ * initialization or a call to LoadLibrary.
+ */
+ case DLL_PROCESS_ATTACH:
+ break;
+
+ /*
+ * The attached process creates a new thread.
+ */
+ case DLL_THREAD_ATTACH:
+ break;
+
+ /* The thread of the attached process terminates. */
+ case DLL_THREAD_DETACH:
+ break;
+
+ /*
+ * The DLL is unloading from a process due to
+ * process termination or a call to FreeLibrary.
+ */
+ case DLL_PROCESS_DETACH:
+ break;
+
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
diff --git a/lib/isccfg/win32/libisccfg.def b/lib/isccfg/win32/libisccfg.def
new file mode 100644
index 0000000..22383b1
--- /dev/null
+++ b/lib/isccfg/win32/libisccfg.def
@@ -0,0 +1,45 @@
+LIBRARY libisccfg
+
+; Exported Functions
+EXPORTS
+
+cfg_acl_fromconfig
+cfg_aclconfctx_destroy
+cfg_aclconfctx_init
+cfg_list_first
+cfg_list_next
+cfg_listelt_value
+cfg_log_init
+cfg_map_get
+cfg_map_getname
+cfg_obj_asboolean
+cfg_obj_asnetprefix
+cfg_obj_assockaddr
+cfg_obj_asstring
+cfg_obj_asuint32
+cfg_obj_asuint64
+cfg_obj_destroy
+cfg_obj_file
+cfg_obj_isboolean
+cfg_obj_islist
+cfg_obj_ismap
+cfg_obj_isnetprefix
+cfg_obj_issockaddr
+cfg_obj_isstring
+cfg_obj_istuple
+cfg_obj_istype
+cfg_obj_isuint32
+cfg_obj_isuint64
+cfg_obj_isvoid
+cfg_obj_line
+cfg_obj_log
+cfg_parse_buffer
+cfg_parse_file
+cfg_parser_create
+cfg_parser_destroy
+cfg_parser_setcallback
+cfg_tuple_get
+
+; Exported Data
+
+;cfg_type_rndcconf
diff --git a/lib/isccfg/win32/libisccfg.dsp b/lib/isccfg/win32/libisccfg.dsp
new file mode 100644
index 0000000..14ba0b5
--- /dev/null
+++ b/lib/isccfg/win32/libisccfg.dsp
@@ -0,0 +1,157 @@
+# Microsoft Developer Studio Project File - Name="libisccfg" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libisccfg - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "libisccfg.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libisccfg.mak" CFG="libisccfg - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisccfg - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libisccfg - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libisccfg - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "libisccfg_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../..../lib/dns/sec/openssl/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBISCCFG_EXPORTS" /YX /FD /c
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../dns/win32/Release/libdns.lib ../../isc/win32/Release/libisc.lib /nologo /dll /machine:I386 /out:"../../../Build/Release/libisccfg.dll"
+
+!ELSEIF "$(CFG)" == "libisccfg - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "libisccfg_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../..../lib/dns/sec/openssl/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISCCFG_EXPORTS" /FR /YX /FD /GZ /c
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../dns/win32/debug/libdns.lib ../../isc/win32/debug/libisc.lib /nologo /dll /debug /machine:I386 /out:"../../../Build/Debug/libisccfg.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "libisccfg - Win32 Release"
+# Name "libisccfg - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\DLLMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\aclconf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\namedconf.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\parser.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\isccfg\cfg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccfg\check.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccfg\grammar.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccfg\aclconf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccfg\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\isccfg\namedconf.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=.\libisccfg.def
+# End Source File
+# End Target
+# End Project
diff --git a/lib/isccfg/win32/libisccfg.dsw b/lib/isccfg/win32/libisccfg.dsw
new file mode 100644
index 0000000..2851ea8
--- /dev/null
+++ b/lib/isccfg/win32/libisccfg.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "libisccfg"=".\libisccfg.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/isccfg/win32/libisccfg.mak b/lib/isccfg/win32/libisccfg.mak
new file mode 100644
index 0000000..e6bf203
--- /dev/null
+++ b/lib/isccfg/win32/libisccfg.mak
@@ -0,0 +1,466 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on libisccfg.dsp
+!IF "$(CFG)" == ""
+CFG=libisccfg - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to libisccfg - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "libisccfg - Win32 Release" && "$(CFG)" != "libisccfg - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "libisccfg.mak" CFG="libisccfg - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libisccfg - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libisccfg - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "libisccfg - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "libisccfg - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\libisccfg.dll"
+
+!ELSE
+
+ALL : "libdns - Win32 Release" "libisc - Win32 Release" "..\..\..\Build\Release\libisccfg.dll"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\aclconf.obj"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\namedconf.obj"
+ -@erase "$(INTDIR)\parser.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(OUTDIR)\libisccfg.exp"
+ -@erase "$(OUTDIR)\libisccfg.lib"
+ -@erase "..\..\..\Build\Release\libisccfg.dll"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../..../lib/dns/sec/openssl/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBISCCFG_EXPORTS" /Fp"$(INTDIR)\libisccfg.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisccfg.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../dns/win32/Release/libdns.lib ../../isc/win32/Release/libisc.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\libisccfg.pdb" /machine:I386 /def:".\libisccfg.def" /out:"../../../Build/Release/libisccfg.dll" /implib:"$(OUTDIR)\libisccfg.lib"
+DEF_FILE= \
+ ".\libisccfg.def"
+LINK32_OBJS= \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\aclconf.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\parser.obj" \
+ "$(INTDIR)\version.obj" \
+ "$(INTDIR)\namedconf.obj" \
+ "..\..\dns\win32\Release\libdns.lib" \
+ "..\..\isc\win32\Release\libisc.lib"
+
+"..\..\..\Build\Release\libisccfg.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ELSEIF "$(CFG)" == "libisccfg - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\libisccfg.dll" "$(OUTDIR)\libisccfg.bsc"
+
+!ELSE
+
+ALL : "libisc - Win32 Debug" "..\..\..\Build\Debug\libisccfg.dll" "$(OUTDIR)\libisccfg.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libisc - Win32 DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\DLLMain.sbr"
+ -@erase "$(INTDIR)\aclconf.obj"
+ -@erase "$(INTDIR)\aclconf.sbr"
+ -@erase "$(INTDIR)\log.obj"
+ -@erase "$(INTDIR)\log.sbr"
+ -@erase "$(INTDIR)\namedconf.obj"
+ -@erase "$(INTDIR)\namedconf.sbr"
+ -@erase "$(INTDIR)\parser.obj"
+ -@erase "$(INTDIR)\parser.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(INTDIR)\version.sbr"
+ -@erase "$(OUTDIR)\libisccfg.bsc"
+ -@erase "$(OUTDIR)\libisccfg.exp"
+ -@erase "$(OUTDIR)\libisccfg.lib"
+ -@erase "$(OUTDIR)\libisccfg.pdb"
+ -@erase "..\..\..\Build\Debug\libisccfg.dll"
+ -@erase "..\..\..\Build\Debug\libisccfg.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "include" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../..../lib/dns/sec/openssl/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBISCCFG_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\libisccfg.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\libisccfg.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\DLLMain.sbr" \
+ "$(INTDIR)\aclconf.sbr" \
+ "$(INTDIR)\log.sbr" \
+ "$(INTDIR)\parser.sbr" \
+ "$(INTDIR)\version.sbr" \
+ "$(INTDIR)\namedconf.sbr"
+
+"$(OUTDIR)\libisccfg.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../dns/win32/debug/libdns.lib ../../isc/win32/debug/libisc.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\libisccfg.pdb" /debug /machine:I386 /def:".\libisccfg.def" /out:"../../../Build/Debug/libisccfg.dll" /implib:"$(OUTDIR)\libisccfg.lib" /pdbtype:sept
+DEF_FILE= \
+ ".\libisccfg.def"
+LINK32_OBJS= \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\aclconf.obj" \
+ "$(INTDIR)\log.obj" \
+ "$(INTDIR)\parser.obj" \
+ "$(INTDIR)\version.obj" \
+ "$(INTDIR)\namedconf.obj" \
+ "..\..\dns\win32\Debug\libdns.lib"
+ "..\..\isc\win32\Debug\libisc.lib"
+
+"..\..\..\Build\Debug\libisccfg.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("libisccfg.dep")
+!INCLUDE "libisccfg.dep"
+!ELSE
+!MESSAGE Warning: cannot find "libisccfg.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "libisccfg - Win32 Release" || "$(CFG)" == "libisccfg - Win32 Debug"
+SOURCE=.\DLLMain.c
+
+!IF "$(CFG)" == "libisccfg - Win32 Release"
+
+
+"$(INTDIR)\DLLMain.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisccfg - Win32 Debug"
+
+
+"$(INTDIR)\DLLMain.obj" "$(INTDIR)\DLLMain.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\aclconf.c
+
+!IF "$(CFG)" == "libisccfg - Win32 Release"
+
+
+"$(INTDIR)\aclconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccfg - Win32 Debug"
+
+
+"$(INTDIR)\aclconf.obj" "$(INTDIR)\aclconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\log.c
+
+!IF "$(CFG)" == "libisccfg - Win32 Release"
+
+
+"$(INTDIR)\log.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccfg - Win32 Debug"
+
+
+"$(INTDIR)\log.obj" "$(INTDIR)\log.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\namedconf.c
+
+!IF "$(CFG)" == "libisccfg - Win32 Release"
+
+
+"$(INTDIR)\namedconf.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccfg - Win32 Debug"
+
+
+"$(INTDIR)\namedconf.obj" "$(INTDIR)\namedconf.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\parser.c
+
+!IF "$(CFG)" == "libisccfg - Win32 Release"
+
+
+"$(INTDIR)\parser.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libisccfg - Win32 Debug"
+
+
+"$(INTDIR)\parser.obj" "$(INTDIR)\parser.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\version.c
+
+!IF "$(CFG)" == "libisccfg - Win32 Release"
+
+
+"$(INTDIR)\version.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "libisccfg - Win32 Debug"
+
+
+"$(INTDIR)\version.obj" "$(INTDIR)\version.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+!IF "$(CFG)" == "libisccfg - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\isccfg\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\isccfg\win32"
+
+"libisc - Win32 Release" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\isccfg\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\isccfg\win32"
+
+!ELSEIF "$(CFG)" == "libisccfg - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\isccfg\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\isccfg\win32"
+
+"libisc - Win32 Debug" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\isccfg\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\isccfg\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/lib/isccfg/win32/version.c b/lib/isccfg/win32/version.c
new file mode 100644
index 0000000..907ecdc
--- /dev/null
+++ b/lib/isccfg/win32/version.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: version.c,v 1.6 2007/06/19 23:47:22 tbox Exp $ */
+
+#include <versions.h>
+
+#include <isccfg/version.h>
+
+LIBISCCFG_EXTERNAL_DATA const char cfg_version[] = VERSION;
+
+LIBISCCFG_EXTERNAL_DATA const unsigned int cfg_libinterface = LIBINTERFACE;
+LIBISCCFG_EXTERNAL_DATA const unsigned int cfg_librevision = LIBREVISION;
+LIBISCCFG_EXTERNAL_DATA const unsigned int cfg_libage = LIBAGE;
+
diff --git a/lib/lwres/Makefile.in b/lib/lwres/Makefile.in
new file mode 100644
index 0000000..858b325
--- /dev/null
+++ b/lib/lwres/Makefile.in
@@ -0,0 +1,84 @@
+# Copyright (C) 2004, 2005, 2007 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: Makefile.in,v 1.34 2007/06/19 23:47:22 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@LIBLWRES_API@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/unix/include \
+ -I. -I./include -I${srcdir}/include ${ISC_INCLUDES}
+CDEFINES =
+CWARNINGS =
+
+# Alphabetically
+OBJS = context.@O@ gai_strerror.@O@ getaddrinfo.@O@ gethost.@O@ \
+ getipnode.@O@ getnameinfo.@O@ getrrset.@O@ herror.@O@ \
+ lwbuffer.@O@ lwconfig.@O@ lwpacket.@O@ lwresutil.@O@ \
+ lwres_gabn.@O@ lwres_gnba.@O@ lwres_grbn.@O@ lwres_noop.@O@ \
+ lwinetaton.@O@ lwinetpton.@O@ lwinetntop.@O@ print.@O@ \
+ strtoul.@O@
+
+# Alphabetically
+SRCS = context.c gai_strerror.c getaddrinfo.c gethost.c \
+ getipnode.c getnameinfo.c getrrset.c herror.c \
+ lwbuffer.c lwconfig.c lwpacket.c lwresutil.c \
+ lwres_gabn.c lwres_gnba.c lwres_grbn.c lwres_noop.c \
+ lwinetaton.c lwinetpton.c lwinetntop.c print.c \
+ strtoul.c
+
+LIBS = @LIBS@
+
+SUBDIRS = include man unix
+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
+
+liblwres.@SA@: ${OBJS} version.@O@
+ ${AR} ${ARFLAGS} $@ ${OBJS} version.@O@
+ ${RANLIB} $@
+
+liblwres.la: ${OBJS} version.@O@
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o liblwres.la -rpath ${libdir} \
+ -version-info ${LIBINTERFACE}:${LIBREVISION}:${LIBAGE} \
+ ${OBJS} version.@O@ ${LIBS}
+
+timestamp: liblwres.@A@
+ touch timestamp
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir}
+
+install:: timestamp installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} liblwres.@A@ ${DESTDIR}${libdir}
+
+clean distclean::
+ rm -f liblwres.@A@ liblwres.la timestamp
diff --git a/lib/lwres/api b/lib/lwres/api
new file mode 100644
index 0000000..8459d42
--- /dev/null
+++ b/lib/lwres/api
@@ -0,0 +1,3 @@
+LIBINTERFACE = 50
+LIBREVISION = 0
+LIBAGE = 0
diff --git a/lib/lwres/assert_p.h b/lib/lwres/assert_p.h
new file mode 100644
index 0000000..f8d6e22
--- /dev/null
+++ b/lib/lwres/assert_p.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: assert_p.h,v 1.14 2007/06/19 23:47:22 tbox Exp $ */
+
+#ifndef LWRES_ASSERT_P_H
+#define LWRES_ASSERT_P_H 1
+
+/*! \file */
+
+#include <assert.h> /* Required for assert() prototype. */
+
+#define REQUIRE(x) assert(x)
+#define INSIST(x) assert(x)
+
+#define UNUSED(x) ((void)(x))
+
+#define SPACE_OK(b, s) (LWRES_BUFFER_AVAILABLECOUNT(b) >= (s))
+#define SPACE_REMAINING(b, s) (LWRES_BUFFER_REMAINING(b) >= (s))
+
+#endif /* LWRES_ASSERT_P_H */
diff --git a/lib/lwres/context.c b/lib/lwres/context.c
new file mode 100644
index 0000000..302adaa
--- /dev/null
+++ b/lib/lwres/context.c
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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.50 2007/06/18 23:47:51 tbox Exp $ */
+
+/*! \file context.c
+ lwres_context_create() creates a #lwres_context_t structure for use in
+ lightweight resolver operations. It holds a socket and other data
+ needed for communicating with a resolver daemon. The new
+ lwres_context_t is returned through contextp, a pointer to a
+ lwres_context_t pointer. This lwres_context_t pointer must initially
+ be NULL, and is modified to point to the newly created
+ lwres_context_t.
+
+ When the lightweight resolver needs to perform dynamic memory
+ allocation, it will call malloc_function to allocate memory and
+ free_function to free it. If malloc_function and free_function are
+ NULL, memory is allocated using malloc and free. It is not
+ permitted to have a NULL malloc_function and a non-NULL free_function
+ or vice versa. arg is passed as the first parameter to the memory
+ allocation functions. If malloc_function and free_function are NULL,
+ arg is unused and should be passed as NULL.
+
+ Once memory for the structure has been allocated, it is initialized
+ using lwres_conf_init() and returned via *contextp.
+
+ lwres_context_destroy() destroys a #lwres_context_t, closing its
+ socket. contextp is a pointer to a pointer to the context that is to
+ be destroyed. The pointer will be set to NULL when the context has
+ been destroyed.
+
+ The context holds a serial number that is used to identify resolver
+ request packets and associate responses with the corresponding
+ requests. This serial number is controlled using
+ lwres_context_initserial() and lwres_context_nextserial().
+ lwres_context_initserial() sets the serial number for context *ctx to
+ serial. lwres_context_nextserial() increments the serial number and
+ returns the previous value.
+
+ Memory for a lightweight resolver context is allocated and freed using
+ lwres_context_allocmem() and lwres_context_freemem(). These use
+ whatever allocations were defined when the context was created with
+ lwres_context_create(). lwres_context_allocmem() allocates len bytes
+ of memory and if successful returns a pointer to the allocated
+ storage. lwres_context_freemem() frees len bytes of space starting at
+ location mem.
+
+ lwres_context_sendrecv() performs I/O for the context ctx. Data are
+ read and written from the context's socket. It writes data from
+ sendbase -- typically a lightweight resolver query packet -- and waits
+ for a reply which is copied to the receive buffer at recvbase. The
+ number of bytes that were written to this receive buffer is returned
+ in *recvd_len.
+
+\section context_return Return Values
+
+ lwres_context_create() returns #LWRES_R_NOMEMORY if memory for the
+ struct lwres_context could not be allocated, #LWRES_R_SUCCESS
+ otherwise.
+
+ Successful calls to the memory allocator lwres_context_allocmem()
+ return a pointer to the start of the allocated space. It returns NULL
+ if memory could not be allocated.
+
+ #LWRES_R_SUCCESS is returned when lwres_context_sendrecv() completes
+ successfully. #LWRES_R_IOERROR is returned if an I/O error occurs and
+ #LWRES_R_TIMEOUT is returned if lwres_context_sendrecv() times out
+ waiting for a response.
+
+\section context_see See Also
+
+ lwres_conf_init(), malloc, free.
+ */
+#include <config.h>
+
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+#include <lwres/platform.h>
+
+#ifdef LWRES_PLATFORM_NEEDSYSSELECTH
+#include <sys/select.h>
+#endif
+
+#include "context_p.h"
+#include "assert_p.h"
+
+/*!
+ * Some systems define the socket length argument as an int, some as size_t,
+ * some as socklen_t. The last is what the current POSIX standard mandates.
+ * This definition is here so it can be portable but easily changed if needed.
+ */
+#ifndef LWRES_SOCKADDR_LEN_T
+#define LWRES_SOCKADDR_LEN_T unsigned int
+#endif
+
+/*!
+ * Make a socket nonblocking.
+ */
+#ifndef MAKE_NONBLOCKING
+#define MAKE_NONBLOCKING(sd, retval) \
+do { \
+ retval = fcntl(sd, F_GETFL, 0); \
+ if (retval != -1) { \
+ retval |= O_NONBLOCK; \
+ retval = fcntl(sd, F_SETFL, retval); \
+ } \
+} while (0)
+#endif
+
+LIBLWRES_EXTERNAL_DATA lwres_uint16_t lwres_udp_port = LWRES_UDP_PORT;
+LIBLWRES_EXTERNAL_DATA const char *lwres_resolv_conf = LWRES_RESOLV_CONF;
+
+static void *
+lwres_malloc(void *, size_t);
+
+static void
+lwres_free(void *, void *, size_t);
+
+/*!
+ * lwres_result_t
+ */
+static lwres_result_t
+context_connect(lwres_context_t *);
+
+/*%
+ * Creates a #lwres_context_t structure for use in
+ * lightweight resolver operations.
+ */
+lwres_result_t
+lwres_context_create(lwres_context_t **contextp, void *arg,
+ lwres_malloc_t malloc_function,
+ lwres_free_t free_function,
+ unsigned int flags)
+{
+ lwres_context_t *ctx;
+
+ REQUIRE(contextp != NULL && *contextp == NULL);
+ UNUSED(flags);
+
+ /*
+ * If we were not given anything special to use, use our own
+ * functions. These are just wrappers around malloc() and free().
+ */
+ if (malloc_function == NULL || free_function == NULL) {
+ REQUIRE(malloc_function == NULL);
+ REQUIRE(free_function == NULL);
+ malloc_function = lwres_malloc;
+ free_function = lwres_free;
+ }
+
+ ctx = malloc_function(arg, sizeof(lwres_context_t));
+ if (ctx == NULL)
+ return (LWRES_R_NOMEMORY);
+
+ /*
+ * Set up the context.
+ */
+ ctx->malloc = malloc_function;
+ ctx->free = free_function;
+ ctx->arg = arg;
+ ctx->sock = -1;
+
+ ctx->timeout = LWRES_DEFAULT_TIMEOUT;
+ ctx->serial = time(NULL); /* XXXMLG or BEW */
+
+ /*
+ * Init resolv.conf bits.
+ */
+ lwres_conf_init(ctx);
+
+ *contextp = ctx;
+ return (LWRES_R_SUCCESS);
+}
+
+/*%
+Destroys a #lwres_context_t, closing its socket.
+contextp is a pointer to a pointer to the context that is
+to be destroyed. The pointer will be set to NULL
+when the context has been destroyed.
+ */
+void
+lwres_context_destroy(lwres_context_t **contextp) {
+ lwres_context_t *ctx;
+
+ REQUIRE(contextp != NULL && *contextp != NULL);
+
+ ctx = *contextp;
+ *contextp = NULL;
+
+ if (ctx->sock != -1) {
+#ifdef WIN32
+ DestroySockets();
+#endif
+ (void)close(ctx->sock);
+ ctx->sock = -1;
+ }
+
+ CTXFREE(ctx, sizeof(lwres_context_t));
+}
+/*% Increments the serial number and returns the previous value. */
+lwres_uint32_t
+lwres_context_nextserial(lwres_context_t *ctx) {
+ REQUIRE(ctx != NULL);
+
+ return (ctx->serial++);
+}
+
+/*% Sets the serial number for context *ctx to serial. */
+void
+lwres_context_initserial(lwres_context_t *ctx, lwres_uint32_t serial) {
+ REQUIRE(ctx != NULL);
+
+ ctx->serial = serial;
+}
+
+/*% Frees len bytes of space starting at location mem. */
+void
+lwres_context_freemem(lwres_context_t *ctx, void *mem, size_t len) {
+ REQUIRE(mem != NULL);
+ REQUIRE(len != 0U);
+
+ CTXFREE(mem, len);
+}
+
+/*% Allocates len bytes of memory and if successful returns a pointer to the allocated storage. */
+void *
+lwres_context_allocmem(lwres_context_t *ctx, size_t len) {
+ REQUIRE(len != 0U);
+
+ return (CTXMALLOC(len));
+}
+
+static void *
+lwres_malloc(void *arg, size_t len) {
+ void *mem;
+
+ UNUSED(arg);
+
+ mem = malloc(len);
+ if (mem == NULL)
+ return (NULL);
+
+ memset(mem, 0xe5, len);
+
+ return (mem);
+}
+
+static void
+lwres_free(void *arg, void *mem, size_t len) {
+ UNUSED(arg);
+
+ memset(mem, 0xa9, len);
+ free(mem);
+}
+
+static lwres_result_t
+context_connect(lwres_context_t *ctx) {
+ int s;
+ int ret;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr *sa;
+ LWRES_SOCKADDR_LEN_T salen;
+ int domain;
+
+ if (ctx->confdata.lwnext != 0) {
+ memcpy(&ctx->address, &ctx->confdata.lwservers[0],
+ sizeof(lwres_addr_t));
+ LWRES_LINK_INIT(&ctx->address, link);
+ } else {
+ /* The default is the IPv4 loopback address 127.0.0.1. */
+ memset(&ctx->address, 0, sizeof(ctx->address));
+ ctx->address.family = LWRES_ADDRTYPE_V4;
+ ctx->address.length = 4;
+ ctx->address.address[0] = 127;
+ ctx->address.address[1] = 0;
+ ctx->address.address[2] = 0;
+ ctx->address.address[3] = 1;
+ }
+
+ if (ctx->address.family == LWRES_ADDRTYPE_V4) {
+ memcpy(&sin.sin_addr, ctx->address.address,
+ sizeof(sin.sin_addr));
+ sin.sin_port = htons(lwres_udp_port);
+ sin.sin_family = AF_INET;
+ sa = (struct sockaddr *)&sin;
+ salen = sizeof(sin);
+ domain = PF_INET;
+ } else if (ctx->address.family == LWRES_ADDRTYPE_V6) {
+ memcpy(&sin6.sin6_addr, ctx->address.address,
+ sizeof(sin6.sin6_addr));
+ sin6.sin6_port = htons(lwres_udp_port);
+ sin6.sin6_family = AF_INET6;
+ sa = (struct sockaddr *)&sin6;
+ salen = sizeof(sin6);
+ domain = PF_INET6;
+ } else
+ return (LWRES_R_IOERROR);
+
+#ifdef WIN32
+ InitSockets();
+#endif
+ s = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
+ if (s < 0) {
+#ifdef WIN32
+ DestroySockets();
+#endif
+ return (LWRES_R_IOERROR);
+ }
+
+ ret = connect(s, sa, salen);
+ if (ret != 0) {
+#ifdef WIN32
+ DestroySockets();
+#endif
+ (void)close(s);
+ return (LWRES_R_IOERROR);
+ }
+
+ MAKE_NONBLOCKING(s, ret);
+ if (ret < 0) {
+#ifdef WIN32
+ DestroySockets();
+#endif
+ (void)close(s);
+ return (LWRES_R_IOERROR);
+ }
+
+ ctx->sock = s;
+
+ return (LWRES_R_SUCCESS);
+}
+
+int
+lwres_context_getsocket(lwres_context_t *ctx) {
+ return (ctx->sock);
+}
+
+lwres_result_t
+lwres_context_send(lwres_context_t *ctx,
+ void *sendbase, int sendlen) {
+ int ret;
+ lwres_result_t lwresult;
+
+ if (ctx->sock == -1) {
+ lwresult = context_connect(ctx);
+ if (lwresult != LWRES_R_SUCCESS)
+ return (lwresult);
+ }
+
+ ret = sendto(ctx->sock, sendbase, sendlen, 0, NULL, 0);
+ if (ret < 0)
+ return (LWRES_R_IOERROR);
+ if (ret != sendlen)
+ return (LWRES_R_IOERROR);
+
+ return (LWRES_R_SUCCESS);
+}
+
+lwres_result_t
+lwres_context_recv(lwres_context_t *ctx,
+ void *recvbase, int recvlen,
+ int *recvd_len)
+{
+ LWRES_SOCKADDR_LEN_T fromlen;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr *sa;
+ int ret;
+
+ if (ctx->address.family == LWRES_ADDRTYPE_V4) {
+ sa = (struct sockaddr *)&sin;
+ fromlen = sizeof(sin);
+ } else {
+ sa = (struct sockaddr *)&sin6;
+ fromlen = sizeof(sin6);
+ }
+
+ /*
+ * The address of fromlen is cast to void * to shut up compiler
+ * warnings, namely on systems that have the sixth parameter
+ * prototyped as a signed int when LWRES_SOCKADDR_LEN_T is
+ * defined as unsigned.
+ */
+ ret = recvfrom(ctx->sock, recvbase, recvlen, 0, sa, (void *)&fromlen);
+
+ if (ret < 0)
+ return (LWRES_R_IOERROR);
+
+ if (ret == recvlen)
+ return (LWRES_R_TOOLARGE);
+
+ /*
+ * If we got something other than what we expect, have the caller
+ * wait for another packet. This can happen if an old result
+ * comes in, or if someone is sending us random stuff.
+ */
+ if (ctx->address.family == LWRES_ADDRTYPE_V4) {
+ if (fromlen != sizeof(sin)
+ || memcmp(&sin.sin_addr, ctx->address.address,
+ sizeof(sin.sin_addr)) != 0
+ || sin.sin_port != htons(lwres_udp_port))
+ return (LWRES_R_RETRY);
+ } else {
+ if (fromlen != sizeof(sin6)
+ || memcmp(&sin6.sin6_addr, ctx->address.address,
+ sizeof(sin6.sin6_addr)) != 0
+ || sin6.sin6_port != htons(lwres_udp_port))
+ return (LWRES_R_RETRY);
+ }
+
+ if (recvd_len != NULL)
+ *recvd_len = ret;
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% performs I/O for the context ctx. */
+lwres_result_t
+lwres_context_sendrecv(lwres_context_t *ctx,
+ void *sendbase, int sendlen,
+ void *recvbase, int recvlen,
+ int *recvd_len)
+{
+ lwres_result_t result;
+ int ret2;
+ fd_set readfds;
+ struct timeval timeout;
+
+ /*
+ * Type of tv_sec is 32 bits long.
+ */
+ if (ctx->timeout <= 0x7FFFFFFFU)
+ timeout.tv_sec = (int)ctx->timeout;
+ else
+ timeout.tv_sec = 0x7FFFFFFF;
+
+ timeout.tv_usec = 0;
+
+ result = lwres_context_send(ctx, sendbase, sendlen);
+ if (result != LWRES_R_SUCCESS)
+ return (result);
+ again:
+ FD_ZERO(&readfds);
+ FD_SET(ctx->sock, &readfds);
+ ret2 = select(ctx->sock + 1, &readfds, NULL, NULL, &timeout);
+
+ /*
+ * What happened with select?
+ */
+ if (ret2 < 0)
+ return (LWRES_R_IOERROR);
+ if (ret2 == 0)
+ return (LWRES_R_TIMEOUT);
+
+ result = lwres_context_recv(ctx, recvbase, recvlen, recvd_len);
+ if (result == LWRES_R_RETRY)
+ goto again;
+
+ return (result);
+}
diff --git a/lib/lwres/context_p.h b/lib/lwres/context_p.h
new file mode 100644
index 0000000..b5ed142
--- /dev/null
+++ b/lib/lwres/context_p.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: context_p.h,v 1.17 2007/06/19 23:47:22 tbox Exp $ */
+
+#ifndef LWRES_CONTEXT_P_H
+#define LWRES_CONTEXT_P_H 1
+
+/*! \file */
+
+/*@{*/
+/**
+ * Helper functions, assuming the context is always called "ctx" in
+ * the scope these functions are called from.
+ */
+#define CTXMALLOC(len) ctx->malloc(ctx->arg, (len))
+#define CTXFREE(addr, len) ctx->free(ctx->arg, (addr), (len))
+/*@}*/
+
+#define LWRES_DEFAULT_TIMEOUT 120 /* 120 seconds for a reply */
+
+/**
+ * Not all the attributes here are actually settable by the application at
+ * this time.
+ */
+struct lwres_context {
+ unsigned int timeout; /*%< time to wait for reply */
+ lwres_uint32_t serial; /*%< serial number state */
+
+ /*
+ * For network I/O.
+ */
+ int sock; /*%< socket to send on */
+ lwres_addr_t address; /*%< address to send to */
+
+ /*@{*/
+ /*
+ * Function pointers for allocating memory.
+ */
+ lwres_malloc_t malloc;
+ lwres_free_t free;
+ void *arg;
+ /*@}*/
+
+ /*%
+ * resolv.conf-like data
+ */
+ lwres_conf_t confdata;
+};
+
+#endif /* LWRES_CONTEXT_P_H */
diff --git a/lib/lwres/gai_strerror.c b/lib/lwres/gai_strerror.c
new file mode 100644
index 0000000..70b35b0
--- /dev/null
+++ b/lib/lwres/gai_strerror.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004-2007 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: gai_strerror.c,v 1.22 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file gai_strerror.c
+ * lwres_gai_strerror() returns an error message corresponding to an
+ * error code returned by getaddrinfo(). The following error codes and
+ * their meaning are defined in \link netdb.h include/lwres/netdb.h.\endlink
+ *
+ * \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
+ * \li #EAI_NONAME hostname or servname not 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
+ *
+ * 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, lwres_getaddrinfo(), getaddrinfo(), RFC2133.
+ */
+
+#include <config.h>
+
+#include <lwres/netdb.h>
+
+/*% 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"
+};
+
+/*% Returns an error message corresponding to an error code returned by getaddrinfo() */
+char *
+lwres_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/lwres/getaddrinfo.c b/lib/lwres/getaddrinfo.c
new file mode 100644
index 0000000..b5a2bcd
--- /dev/null
+++ b/lib/lwres/getaddrinfo.c
@@ -0,0 +1,808 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * This code is derived from software contributed to ISC by
+ * Berkeley Software Design, Inc.
+ *
+ * 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 AND BERKELEY SOFTWARE DESIGN, INC.
+ * 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.52 2007/09/13 04:45:18 each Exp $ */
+
+/*! \file */
+
+/**
+ * lwres_getaddrinfo() is used to get a list of IP addresses and port
+ * numbers for host hostname and service servname. The function is the
+ * lightweight resolver's implementation of getaddrinfo() as defined in
+ * RFC2133. 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:
+ *
+ * <ul>
+ * <li>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.</li>
+ *
+ * <li>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.</li>
+ *
+ * <li>ai_protocol:
+ * indicates which transport protocol is wanted: IPPROTO_UDP or
+ * IPPROTO_TCP. If ai_protocol is zero the caller will accept any
+ * protocol.</li>
+ *
+ * <li>ai_flags:
+ * Flag bits. If the AI_CANONNAME bit is set, a successful call to
+ * lwres_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.<br /><br />
+ *
+ * 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.<br /><br />
+ *
+ * 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.
+ * </li></ul>
+ *
+ * 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 lwres_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 lwres_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 lwres_getaddrinfo() is released by
+ * lwres_freeaddrinfo(). ai is a pointer to a struct addrinfo created by
+ * a call to lwres_getaddrinfo().
+ *
+ * \section lwresreturn RETURN VALUES
+ *
+ * lwres_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 lwres_getaddrinfo() returns #EAI_NONAME.
+ *
+ * \section lwressee SEE ALSO
+ *
+ * lwres(3), lwres_getaddrinfo(), lwres_freeaddrinfo(),
+ * lwres_gai_strerror(), RFC2133, getservbyname(3), connect(2),
+ * sendto(2), sendmsg(2), socket(2).
+ */
+
+#include <config.h>
+
+#include <errno.h>
+
+#include <isc/string.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+#include <lwres/netdb.h>
+#include <lwres/stdlib.h>
+
+#define SA(addr) ((struct sockaddr *)(addr))
+#define SIN(addr) ((struct sockaddr_in *)(addr))
+#define SIN6(addr) ((struct sockaddr_in6 *)(addr))
+#define SUN(addr) ((struct sockaddr_un *)(addr))
+
+/*! \struct addrinfo
+ */
+static struct addrinfo
+ *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 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
+lwres_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 port, err, 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) {
+ lwres_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 LWRES_HAVE_SIN6_SCOPE_ID
+ char *p, *ep;
+ char ntmp[NI_MAXHOST];
+ lwres_uint32_t scopeid;
+#endif
+
+#ifdef LWRES_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 = (lwres_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 (lwres_net_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 LWRES_HAVE_SIN6_SCOPE_ID
+ } else if (ntmp[0] != '\0' &&
+ lwres_net_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 (lwres_net_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_clone(ai_list, family);
+ 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) {
+#if defined(LWRES_HAVE_SIN6_SCOPE_ID)
+ if (ai->ai_family == AF_INET6)
+ SIN6(ai->ai_addr)->sin6_scope_id =
+ scopeid;
+#endif
+ if (lwres_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) {
+ lwres_freeaddrinfo(ai_list);
+ return (EAI_MEMORY);
+ }
+ } else {
+ /* XXX raise error? */
+ ai->ai_canonname = NULL;
+ }
+ }
+ goto done;
+ } else if ((flags & AI_NUMERICHOST) != 0) {
+ return (EAI_NONAME);
+ }
+ }
+
+ 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)
+ return (err);
+ }
+
+ if (ai_list == NULL)
+ return (EAI_NODATA);
+
+done:
+ ai_list = ai_reverse(ai_list);
+
+ *res = ai_list;
+ return (0);
+}
+
+static char *
+lwres_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 = lwres_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 };
+
+/*
+ * The test against 0 is there to keep the Solaris compiler
+ * from complaining about "end-of-loop code not reached".
+ */
+#define SETERROR(code) \
+ do { result = (code); \
+ if (result != 0) goto cleanup; \
+ } while (0)
+
+static int
+add_ipv4(const char *hostname, int flags, struct addrinfo **aip,
+ int socktype, int port)
+{
+ struct addrinfo *ai;
+ lwres_context_t *lwrctx = NULL;
+ lwres_gabnresponse_t *by = NULL;
+ lwres_addr_t *addr;
+ lwres_result_t lwres;
+ int result = 0;
+
+ lwres = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
+ if (lwres != LWRES_R_SUCCESS)
+ SETERROR(EAI_FAIL);
+ (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
+ if (hostname == NULL && (flags & AI_PASSIVE) == 0) {
+ ai = ai_clone(*aip, AF_INET);
+ if (ai == NULL) {
+ lwres_freeaddrinfo(*aip);
+ SETERROR(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);
+ } else {
+ lwres = lwres_getaddrsbyname(lwrctx, hostname,
+ LWRES_ADDRTYPE_V4, &by);
+ if (lwres != LWRES_R_SUCCESS) {
+ if (lwres == LWRES_R_NOTFOUND)
+ goto cleanup;
+ else
+ SETERROR(EAI_FAIL);
+ }
+ addr = LWRES_LIST_HEAD(by->addrs);
+ while (addr != NULL) {
+ ai = ai_clone(*aip, AF_INET);
+ if (ai == NULL) {
+ lwres_freeaddrinfo(*aip);
+ SETERROR(EAI_MEMORY);
+ }
+ *aip = ai;
+ ai->ai_socktype = socktype;
+ SIN(ai->ai_addr)->sin_port = port;
+ memcpy(&SIN(ai->ai_addr)->sin_addr,
+ addr->address, 4);
+ if (flags & AI_CANONNAME) {
+ ai->ai_canonname = strdup(by->realname);
+ if (ai->ai_canonname == NULL)
+ SETERROR(EAI_MEMORY);
+ }
+ addr = LWRES_LIST_NEXT(addr, link);
+ }
+ }
+ cleanup:
+ if (by != NULL)
+ lwres_gabnresponse_free(lwrctx, &by);
+ if (lwrctx != NULL) {
+ lwres_conf_clear(lwrctx);
+ lwres_context_destroy(&lwrctx);
+ }
+ return (result);
+}
+
+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;
+ lwres_context_t *lwrctx = NULL;
+ lwres_gabnresponse_t *by = NULL;
+ lwres_addr_t *addr;
+ lwres_result_t lwres;
+ int result = 0;
+
+ lwres = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
+ if (lwres != LWRES_R_SUCCESS)
+ SETERROR(EAI_FAIL);
+ (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
+
+ if (hostname == NULL && (flags & AI_PASSIVE) == 0) {
+ ai = ai_clone(*aip, AF_INET6);
+ if (ai == NULL) {
+ lwres_freeaddrinfo(*aip);
+ SETERROR(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);
+ } else {
+ lwres = lwres_getaddrsbyname(lwrctx, hostname,
+ LWRES_ADDRTYPE_V6, &by);
+ if (lwres != LWRES_R_SUCCESS) {
+ if (lwres == LWRES_R_NOTFOUND)
+ goto cleanup;
+ else
+ SETERROR(EAI_FAIL);
+ }
+ addr = LWRES_LIST_HEAD(by->addrs);
+ while (addr != NULL) {
+ ai = ai_clone(*aip, AF_INET6);
+ if (ai == NULL) {
+ lwres_freeaddrinfo(*aip);
+ SETERROR(EAI_MEMORY);
+ }
+ *aip = ai;
+ ai->ai_socktype = socktype;
+ SIN6(ai->ai_addr)->sin6_port = port;
+ memcpy(&SIN6(ai->ai_addr)->sin6_addr,
+ addr->address, 16);
+ if (flags & AI_CANONNAME) {
+ ai->ai_canonname = strdup(by->realname);
+ if (ai->ai_canonname == NULL)
+ SETERROR(EAI_MEMORY);
+ }
+ addr = LWRES_LIST_NEXT(addr, link);
+ }
+ }
+ cleanup:
+ if (by != NULL)
+ lwres_gabnresponse_free(lwrctx, &by);
+ if (lwrctx != NULL) {
+ lwres_conf_clear(lwrctx);
+ lwres_context_destroy(&lwrctx);
+ }
+ return (result);
+}
+
+/*% Free address info. */
+void
+lwres_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 *sun;
+
+ if (socktype == 0)
+ return (EAI_SOCKTYPE);
+
+ ai = ai_alloc(AF_LOCAL, sizeof(*sun));
+ if (ai == NULL)
+ return (EAI_MEMORY);
+
+ sun = SUN(ai->ai_addr);
+ strncpy(sun->sun_path, name, sizeof(sun->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 (LWRES_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 LWRES_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) {
+ lwres_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);
+}
diff --git a/lib/lwres/gethost.c b/lib/lwres/gethost.c
new file mode 100644
index 0000000..1a1efd4
--- /dev/null
+++ b/lib/lwres/gethost.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: gethost.c,v 1.34 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+/**
+ * These functions provide hostname-to-address and address-to-hostname
+ * lookups by means of the lightweight resolver. They are similar to the
+ * standard gethostent(3) functions provided by most operating systems.
+ * They use a struct hostent which is usually defined in <namedb.h>.
+ *
+ * \code
+ * struct hostent {
+ * char *h_name; // official name of host
+ * char **h_aliases; // alias list
+ * int h_addrtype; // host address type
+ * int h_length; // length of address
+ * char **h_addr_list; // list of addresses from name server
+ * };
+ * #define h_addr h_addr_list[0] // address, for backward compatibility
+ * \endcode
+ *
+ * The members of this structure are:
+ *
+ * \li h_name:
+ * The official (canonical) name of the host.
+ *
+ * \li h_aliases:
+ * A NULL-terminated array of alternate names (nicknames) for the
+ * host.
+ *
+ * \li h_addrtype:
+ * The type of address being returned -- PF_INET or PF_INET6.
+ *
+ * \li h_length:
+ * The length of the address in bytes.
+ *
+ * \li h_addr_list:
+ * A NULL terminated array of network addresses for the host. Host
+ * addresses are returned in network byte order.
+ *
+ * For backward compatibility with very old software, h_addr is the first
+ * address in h_addr_list.
+ *
+ * lwres_gethostent(), lwres_sethostent(), lwres_endhostent(),
+ * lwres_gethostent_r(), lwres_sethostent_r() and lwres_endhostent_r()
+ * provide iteration over the known host entries on systems that provide
+ * such functionality through facilities like /etc/hosts or NIS. The
+ * lightweight resolver does not currently implement these functions; it
+ * only provides them as stub functions that always return failure.
+ *
+ * lwres_gethostbyname() and lwres_gethostbyname2() look up the hostname
+ * name. lwres_gethostbyname() always looks for an IPv4 address while
+ * lwres_gethostbyname2() looks for an address of protocol family af:
+ * either PF_INET or PF_INET6 -- IPv4 or IPV6 addresses respectively.
+ * Successful calls of the functions return a struct hostent for the name
+ * that was looked up. NULL is returned if the lookups by
+ * lwres_gethostbyname() or lwres_gethostbyname2() fail.
+ *
+ * Reverse lookups of addresses are performed by lwres_gethostbyaddr().
+ * addr is an address of length len bytes and protocol family type --
+ * PF_INET or PF_INET6. lwres_gethostbyname_r() is a thread-safe function
+ * for forward lookups. If an error occurs, an error code is returned in
+ * *error. resbuf is a pointer to a struct hostent which is initialised
+ * by a successful call to lwres_gethostbyname_r() . buf is a buffer of
+ * length len bytes which is used to store the h_name, h_aliases, and
+ * h_addr_list elements of the struct hostent returned in resbuf.
+ * Successful calls to lwres_gethostbyname_r() return resbuf, which is a
+ * pointer to the struct hostent it created.
+ *
+ * lwres_gethostbyaddr_r() is a thread-safe function that performs a
+ * reverse lookup of address addr which is len bytes long and is of
+ * protocol family type -- PF_INET or PF_INET6. If an error occurs, the
+ * error code is returned in *error. The other function parameters are
+ * identical to those in lwres_gethostbyname_r(). resbuf is a pointer to
+ * a struct hostent which is initialised by a successful call to
+ * lwres_gethostbyaddr_r(). buf is a buffer of length len bytes which is
+ * used to store the h_name, h_aliases, and h_addr_list elements of the
+ * struct hostent returned in resbuf. Successful calls to
+ * lwres_gethostbyaddr_r() return resbuf, which is a pointer to the
+ * struct hostent it created.
+ *
+ * \section gethost_return Return Values
+ *
+ * The functions lwres_gethostbyname(), lwres_gethostbyname2(),
+ * lwres_gethostbyaddr(), and lwres_gethostent() return NULL to indicate
+ * an error. In this case the global variable lwres_h_errno will contain
+ * one of the following error codes defined in \link netdb.h <lwres/netdb.h>:\endlink
+ *
+ * \li #HOST_NOT_FOUND:
+ * The host or address was not found.
+ *
+ * \li #TRY_AGAIN:
+ * A recoverable error occurred, e.g., a timeout. Retrying the
+ * lookup may succeed.
+ *
+ * \li #NO_RECOVERY:
+ * A non-recoverable error occurred.
+ *
+ * \li #NO_DATA:
+ * The name exists, but has no address information associated with
+ * it (or vice versa in the case of a reverse lookup). The code
+ * NO_ADDRESS is accepted as a synonym for NO_DATA for backwards
+ * compatibility.
+ *
+ * lwres_hstrerror() translates these error codes to suitable error
+ * messages.
+ *
+ * lwres_gethostent() and lwres_gethostent_r() always return NULL.
+ *
+ * Successful calls to lwres_gethostbyname_r() and
+ * lwres_gethostbyaddr_r() return resbuf, a pointer to the struct hostent
+ * that was initialised by these functions. They return NULL if the
+ * lookups fail or if buf was too small to hold the list of addresses and
+ * names referenced by the h_name, h_aliases, and h_addr_list elements of
+ * the struct hostent. If buf was too small, both lwres_gethostbyname_r()
+ * and lwres_gethostbyaddr_r() set the global variable errno to ERANGE.
+ *
+ * \section gethost_see See Also
+ *
+ * gethostent(), \link getipnode.c getipnode\endlink, lwres_hstrerror()
+ *
+ * \section gethost_bugs Bugs
+ *
+ * lwres_gethostbyname(), lwres_gethostbyname2(), lwres_gethostbyaddr()
+ * and lwres_endhostent() are not thread safe; they return pointers to
+ * static data and provide error codes through a global variable.
+ * Thread-safe versions for name and address lookup are provided by
+ * lwres_gethostbyname_r(), and lwres_gethostbyaddr_r() respectively.
+ *
+ * The resolver daemon does not currently support any non-DNS name
+ * services such as /etc/hosts or NIS, consequently the above functions
+ * don't, either.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <lwres/net.h>
+#include <lwres/netdb.h>
+
+#include "assert_p.h"
+
+#define LWRES_ALIGNBYTES (sizeof(char *) - 1)
+#define LWRES_ALIGN(p) \
+ (((unsigned long)(p) + LWRES_ALIGNBYTES) &~ LWRES_ALIGNBYTES)
+
+static struct hostent *he = NULL;
+static int copytobuf(struct hostent *, struct hostent *, char *, int);
+
+/*% Always looks for an IPv4 address. */
+struct hostent *
+lwres_gethostbyname(const char *name) {
+
+ if (he != NULL)
+ lwres_freehostent(he);
+
+ he = lwres_getipnodebyname(name, AF_INET, 0, &lwres_h_errno);
+ return (he);
+}
+
+/*% Looks for either an IPv4 or IPv6 address. */
+struct hostent *
+lwres_gethostbyname2(const char *name, int af) {
+ if (he != NULL)
+ lwres_freehostent(he);
+
+ he = lwres_getipnodebyname(name, af, 0, &lwres_h_errno);
+ return (he);
+}
+
+/*% Reverse lookup of addresses. */
+struct hostent *
+lwres_gethostbyaddr(const char *addr, int len, int type) {
+
+ if (he != NULL)
+ lwres_freehostent(he);
+
+ he = lwres_getipnodebyaddr(addr, len, type, &lwres_h_errno);
+ return (he);
+}
+
+/*% Stub function. Always returns failure. */
+struct hostent *
+lwres_gethostent(void) {
+ if (he != NULL)
+ lwres_freehostent(he);
+
+ return (NULL);
+}
+
+/*% Stub function. Always returns failure. */
+void
+lwres_sethostent(int stayopen) {
+ /*
+ * Empty.
+ */
+ UNUSED(stayopen);
+}
+
+/*% Stub function. Always returns failure. */
+void
+lwres_endhostent(void) {
+ /*
+ * Empty.
+ */
+}
+
+/*% Thread-safe function for forward lookups. */
+struct hostent *
+lwres_gethostbyname_r(const char *name, struct hostent *resbuf,
+ char *buf, int buflen, int *error)
+{
+ struct hostent *he;
+ int res;
+
+ he = lwres_getipnodebyname(name, AF_INET, 0, error);
+ if (he == NULL)
+ return (NULL);
+ res = copytobuf(he, resbuf, buf, buflen);
+ lwres_freehostent(he);
+ if (res != 0) {
+ errno = ERANGE;
+ return (NULL);
+ }
+ return (resbuf);
+}
+
+/*% Thread-safe reverse lookup. */
+struct hostent *
+lwres_gethostbyaddr_r(const char *addr, int len, int type,
+ struct hostent *resbuf, char *buf, int buflen,
+ int *error)
+{
+ struct hostent *he;
+ int res;
+
+ he = lwres_getipnodebyaddr(addr, len, type, error);
+ if (he == NULL)
+ return (NULL);
+ res = copytobuf(he, resbuf, buf, buflen);
+ lwres_freehostent(he);
+ if (res != 0) {
+ errno = ERANGE;
+ return (NULL);
+ }
+ return (resbuf);
+}
+
+/*% Stub function. Always returns failure. */
+struct hostent *
+lwres_gethostent_r(struct hostent *resbuf, char *buf, int buflen, int *error) {
+ UNUSED(resbuf);
+ UNUSED(buf);
+ UNUSED(buflen);
+ *error = 0;
+ return (NULL);
+}
+
+/*% Stub function. Always returns failure. */
+void
+lwres_sethostent_r(int stayopen) {
+ /*
+ * Empty.
+ */
+ UNUSED(stayopen);
+}
+
+/*% Stub function. Always returns failure. */
+void
+lwres_endhostent_r(void) {
+ /*
+ * Empty.
+ */
+}
+
+static int
+copytobuf(struct hostent *he, struct hostent *hptr, char *buf, int buflen) {
+ char *cp;
+ char **ptr;
+ int i, n;
+ int nptr, len;
+
+ /*
+ * Find out the amount of space required to store the answer.
+ */
+ nptr = 2; /* NULL ptrs */
+ len = (char *)LWRES_ALIGN(buf) - buf;
+ for (i = 0; he->h_addr_list[i]; i++, nptr++) {
+ len += he->h_length;
+ }
+ for (i = 0; he->h_aliases[i]; i++, nptr++) {
+ len += strlen(he->h_aliases[i]) + 1;
+ }
+ len += strlen(he->h_name) + 1;
+ len += nptr * sizeof(char*);
+
+ if (len > buflen) {
+ return (-1);
+ }
+
+ /*
+ * Copy address size and type.
+ */
+ hptr->h_addrtype = he->h_addrtype;
+ n = hptr->h_length = he->h_length;
+
+ ptr = (char **)LWRES_ALIGN(buf);
+ cp = (char *)LWRES_ALIGN(buf) + nptr * sizeof(char *);
+
+ /*
+ * Copy address list.
+ */
+ hptr->h_addr_list = ptr;
+ for (i = 0; he->h_addr_list[i]; i++, ptr++) {
+ memcpy(cp, he->h_addr_list[i], n);
+ hptr->h_addr_list[i] = cp;
+ cp += n;
+ }
+ hptr->h_addr_list[i] = NULL;
+ ptr++;
+
+ /*
+ * Copy official name.
+ */
+ n = strlen(he->h_name) + 1;
+ strcpy(cp, he->h_name);
+ hptr->h_name = cp;
+ cp += n;
+
+ /*
+ * Copy aliases.
+ */
+ hptr->h_aliases = ptr;
+ for (i = 0; he->h_aliases[i]; i++) {
+ n = strlen(he->h_aliases[i]) + 1;
+ strcpy(cp, he->h_aliases[i]);
+ hptr->h_aliases[i] = cp;
+ cp += n;
+ }
+ hptr->h_aliases[i] = NULL;
+
+ return (0);
+}
diff --git a/lib/lwres/getipnode.c b/lib/lwres/getipnode.c
new file mode 100644
index 0000000..a6c50c2
--- /dev/null
+++ b/lib/lwres/getipnode.c
@@ -0,0 +1,1148 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: getipnode.c,v 1.42 2007/06/18 23:47:51 tbox Exp $ */
+
+/*! \file */
+
+/**
+ * These functions perform thread safe, protocol independent
+ * nodename-to-address and address-to-nodename translation as defined in
+ * RFC2553. This use a struct hostent which is defined in namedb.h:
+ *
+ * \code
+ * struct hostent {
+ * char *h_name; // official name of host
+ * char **h_aliases; // alias list
+ * int h_addrtype; // host address type
+ * int h_length; // length of address
+ * char **h_addr_list; // list of addresses from name server
+ * };
+ * #define h_addr h_addr_list[0] // address, for backward compatibility
+ * \endcode
+ *
+ * The members of this structure are:
+ *
+ * \li h_name:
+ * The official (canonical) name of the host.
+ *
+ * \li h_aliases:
+ * A NULL-terminated array of alternate names (nicknames) for the
+ * host.
+ *
+ * \li h_addrtype:
+ * The type of address being returned - usually PF_INET or
+ * PF_INET6.
+ *
+ * \li h_length:
+ * The length of the address in bytes.
+ *
+ * \li h_addr_list:
+ * A NULL terminated array of network addresses for the host. Host
+ * addresses are returned in network byte order.
+ *
+ * lwres_getipnodebyname() looks up addresses of protocol family af for
+ * the hostname name. The flags parameter contains ORed flag bits to
+ * specify the types of addresses that are searched for, and the types of
+ * addresses that are returned. The flag bits are:
+ *
+ * \li #AI_V4MAPPED:
+ * This is used with an af of #AF_INET6, and causes IPv4 addresses
+ * to be returned as IPv4-mapped IPv6 addresses.
+ *
+ * \li #AI_ALL:
+ * This is used with an af of #AF_INET6, and causes all known
+ * addresses (IPv6 and IPv4) to be returned. If #AI_V4MAPPED is
+ * also set, the IPv4 addresses are return as mapped IPv6
+ * addresses.
+ *
+ * \li #AI_ADDRCONFIG:
+ * Only return an IPv6 or IPv4 address if here is an active
+ * network interface of that type. This is not currently
+ * implemented in the BIND 9 lightweight resolver, and the flag is
+ * ignored.
+ *
+ * \li #AI_DEFAULT:
+ * This default sets the #AI_V4MAPPED and #AI_ADDRCONFIG flag bits.
+ *
+ * lwres_getipnodebyaddr() performs a reverse lookup of address src which
+ * is len bytes long. af denotes the protocol family, typically PF_INET
+ * or PF_INET6.
+ *
+ * lwres_freehostent() releases all the memory associated with the struct
+ * hostent pointer. Any memory allocated for the h_name, h_addr_list
+ * and h_aliases is freed, as is the memory for the hostent structure
+ * itself.
+ *
+ * \section getipnode_return Return Values
+ *
+ * If an error occurs, lwres_getipnodebyname() and
+ * lwres_getipnodebyaddr() set *error_num to an appropriate error code
+ * and the function returns a NULL pointer. The error codes and their
+ * meanings are defined in \link netdb.h <lwres/netdb.h>\endlink:
+ *
+ * \li #HOST_NOT_FOUND:
+ * No such host is known.
+ *
+ * \li #NO_ADDRESS:
+ * The server recognised the request and the name but no address
+ * is available. Another type of request to the name server for
+ * the domain might return an answer.
+ *
+ * \li #TRY_AGAIN:
+ * A temporary and possibly transient error occurred, such as a
+ * failure of a server to respond. The request may succeed if
+ * retried.
+ *
+ * \li #NO_RECOVERY:
+ * An unexpected failure occurred, and retrying the request is
+ * pointless.
+ *
+ * lwres_hstrerror() translates these error codes to suitable error
+ * messages.
+ *
+ * \section getipnode_see See Also
+ *
+ * getaddrinfo.c, gethost.c, getnameinfo.c, herror.c, RFC2553
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+#include <lwres/netdb.h> /* XXX #include <netdb.h> */
+
+#include "assert_p.h"
+
+#ifndef INADDRSZ
+#define INADDRSZ 4
+#endif
+#ifndef IN6ADDRSZ
+#define IN6ADDRSZ 16
+#endif
+
+#ifdef LWRES_PLATFORM_NEEDIN6ADDRANY
+LIBLWRES_EXTERNAL_DATA const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+#endif
+
+#ifndef IN6_IS_ADDR_V4COMPAT
+static const unsigned char in6addr_compat[12] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \
+ ((x)->s6_addr[12] != 0 || \
+ (x)->s6_addr[13] != 0 || \
+ (x)->s6_addr[14] != 0 || \
+ ((x)->s6_addr[15] != 0 && \
+ (x)->s6_addr[15] != 1)))
+#endif
+#ifndef IN6_IS_ADDR_V4MAPPED
+#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12))
+#endif
+
+static const unsigned char in6addr_mapped[12] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff
+};
+
+/***
+ *** Forward declarations.
+ ***/
+
+static int
+scan_interfaces(int *, int *);
+
+static struct hostent *
+copyandmerge(struct hostent *, struct hostent *, int, int *);
+
+static struct hostent *
+hostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src);
+
+static struct hostent *
+hostfromname(lwres_gabnresponse_t *name, int af);
+
+/***
+ *** Public functions.
+ ***/
+
+/*!
+ * AI_V4MAPPED + AF_INET6
+ * If no IPv6 address then a query for IPv4 and map returned values.
+ *
+ * AI_ALL + AI_V4MAPPED + AF_INET6
+ * Return IPv6 and IPv4 mapped.
+ *
+ * AI_ADDRCONFIG
+ * Only return IPv6 / IPv4 address if there is an interface of that
+ * type active.
+ */
+
+struct hostent *
+lwres_getipnodebyname(const char *name, int af, int flags, int *error_num) {
+ int have_v4 = 1, have_v6 = 1;
+ struct in_addr in4;
+ struct in6_addr in6;
+ struct hostent he, *he1 = NULL, *he2 = NULL, *he3 = NULL;
+ int v4 = 0, v6 = 0;
+ int tmp_err;
+ lwres_context_t *lwrctx = NULL;
+ lwres_gabnresponse_t *by = NULL;
+ int n;
+
+ /*
+ * If we care about active interfaces then check.
+ */
+ if ((flags & AI_ADDRCONFIG) != 0)
+ if (scan_interfaces(&have_v4, &have_v6) == -1) {
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+
+ /* Check for literal address. */
+ if ((v4 = lwres_net_pton(AF_INET, name, &in4)) != 1)
+ v6 = lwres_net_pton(AF_INET6, name, &in6);
+
+ /*
+ * Impossible combination?
+ */
+ if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) ||
+ (af == AF_INET && v6 == 1) ||
+ (have_v4 == 0 && v4 == 1) ||
+ (have_v6 == 0 && v6 == 1) ||
+ (have_v4 == 0 && af == AF_INET) ||
+ (have_v6 == 0 && af == AF_INET6 &&
+ (((flags & AI_V4MAPPED) != 0 && have_v4) ||
+ (flags & AI_V4MAPPED) == 0))) {
+ *error_num = HOST_NOT_FOUND;
+ return (NULL);
+ }
+
+ /*
+ * Literal address?
+ */
+ if (v4 == 1 || v6 == 1) {
+ char *addr_list[2];
+ char *aliases[1];
+ char mappedname[sizeof("::ffff:123.123.123.123")];
+ union {
+ const char *const_name;
+ char *deconst_name;
+ } u;
+
+ u.const_name = name;
+ if (v4 == 1 && af == AF_INET6) {
+ strcpy(mappedname, "::ffff:");
+ lwres_net_ntop(AF_INET, (char *)&in4,
+ mappedname + sizeof("::ffff:") - 1,
+ sizeof(mappedname) - sizeof("::ffff:")
+ + 1);
+ he.h_name = mappedname;
+ } else
+ he.h_name = u.deconst_name;
+ he.h_addr_list = addr_list;
+ he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6;
+ he.h_addr_list[1] = NULL;
+ he.h_aliases = aliases;
+ he.h_aliases[0] = NULL;
+ he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ;
+ he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6;
+ return (copyandmerge(&he, NULL, af, error_num));
+ }
+
+ n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
+ if (n != 0) {
+ *error_num = NO_RECOVERY;
+ goto cleanup;
+ }
+ (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
+ tmp_err = NO_RECOVERY;
+ if (have_v6 && af == AF_INET6) {
+
+ n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V6, &by);
+ if (n == 0) {
+ he1 = hostfromname(by, AF_INET6);
+ lwres_gabnresponse_free(lwrctx, &by);
+ if (he1 == NULL) {
+ *error_num = NO_RECOVERY;
+ goto cleanup;
+ }
+ } else {
+ tmp_err = HOST_NOT_FOUND;
+ }
+ }
+
+ if (have_v4 &&
+ ((af == AF_INET) ||
+ (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 &&
+ (he1 == NULL || (flags & AI_ALL) != 0)))) {
+ n = lwres_getaddrsbyname(lwrctx, name, LWRES_ADDRTYPE_V4, &by);
+ if (n == 0) {
+ he2 = hostfromname(by, AF_INET);
+ lwres_gabnresponse_free(lwrctx, &by);
+ if (he2 == NULL) {
+ *error_num = NO_RECOVERY;
+ goto cleanup;
+ }
+ } else if (he1 == NULL) {
+ if (n == LWRES_R_NOTFOUND)
+ *error_num = HOST_NOT_FOUND;
+ else
+ *error_num = NO_RECOVERY;
+ goto cleanup;
+ }
+ } else
+ *error_num = tmp_err;
+
+ he3 = copyandmerge(he1, he2, af, error_num);
+
+ cleanup:
+ if (he1 != NULL)
+ lwres_freehostent(he1);
+ if (he2 != NULL)
+ lwres_freehostent(he2);
+ if (lwrctx != NULL) {
+ lwres_conf_clear(lwrctx);
+ lwres_context_destroy(&lwrctx);
+ }
+ return (he3);
+}
+
+/*% performs a reverse lookup of address src which is len bytes long. af denotes the protocol family, typically #PF_INET or PF_INET6. */
+struct hostent *
+lwres_getipnodebyaddr(const void *src, size_t len, int af, int *error_num) {
+ struct hostent *he1, *he2;
+ lwres_context_t *lwrctx = NULL;
+ lwres_gnbaresponse_t *by = NULL;
+ lwres_result_t n;
+ union {
+ const void *konst;
+ struct in6_addr *in6;
+ } u;
+
+ /*
+ * Sanity checks.
+ */
+ if (src == NULL) {
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+
+ switch (af) {
+ case AF_INET:
+ if (len != (unsigned int)INADDRSZ) {
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+ break;
+ case AF_INET6:
+ if (len != (unsigned int)IN6ADDRSZ) {
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+ break;
+ default:
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+
+ /*
+ * The de-"const"-ing game is done because at least one
+ * vendor's system (RedHat 6.0) defines the IN6_IS_ADDR_*
+ * macros in such a way that they discard the const with
+ * internal casting, and gcc ends up complaining. Rather
+ * than replacing their own (possibly optimized) definitions
+ * with our own, cleanly discarding the const is the easiest
+ * thing to do.
+ */
+ u.konst = src;
+
+ /*
+ * Look up IPv4 and IPv4 mapped/compatible addresses.
+ */
+ if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(u.in6)) ||
+ (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(u.in6)) ||
+ (af == AF_INET)) {
+ const unsigned char *cp = src;
+
+ if (af == AF_INET6)
+ cp += 12;
+ n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
+ if (n == LWRES_R_SUCCESS)
+ (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
+ if (n == LWRES_R_SUCCESS)
+ n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V4,
+ INADDRSZ, cp, &by);
+ if (n != LWRES_R_SUCCESS) {
+ lwres_conf_clear(lwrctx);
+ lwres_context_destroy(&lwrctx);
+ if (n == LWRES_R_NOTFOUND)
+ *error_num = HOST_NOT_FOUND;
+ else
+ *error_num = NO_RECOVERY;
+ return (NULL);
+ }
+ he1 = hostfromaddr(by, AF_INET, cp);
+ lwres_gnbaresponse_free(lwrctx, &by);
+ lwres_conf_clear(lwrctx);
+ lwres_context_destroy(&lwrctx);
+ if (af != AF_INET6)
+ return (he1);
+
+ /*
+ * Convert from AF_INET to AF_INET6.
+ */
+ he2 = copyandmerge(he1, NULL, af, error_num);
+ lwres_freehostent(he1);
+ if (he2 == NULL)
+ return (NULL);
+ /*
+ * Restore original address.
+ */
+ memcpy(he2->h_addr, src, len);
+ return (he2);
+ }
+
+ /*
+ * Lookup IPv6 address.
+ */
+ if (memcmp(src, &in6addr_any, IN6ADDRSZ) == 0) {
+ *error_num = HOST_NOT_FOUND;
+ return (NULL);
+ }
+
+ n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
+ if (n == LWRES_R_SUCCESS)
+ (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
+ if (n == LWRES_R_SUCCESS)
+ n = lwres_getnamebyaddr(lwrctx, LWRES_ADDRTYPE_V6, IN6ADDRSZ,
+ src, &by);
+ if (n != 0) {
+ lwres_conf_clear(lwrctx);
+ lwres_context_destroy(&lwrctx);
+ *error_num = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ he1 = hostfromaddr(by, AF_INET6, src);
+ lwres_gnbaresponse_free(lwrctx, &by);
+ if (he1 == NULL)
+ *error_num = NO_RECOVERY;
+ lwres_conf_clear(lwrctx);
+ lwres_context_destroy(&lwrctx);
+ return (he1);
+}
+
+/*% releases all the memory associated with the struct hostent pointer */
+void
+lwres_freehostent(struct hostent *he) {
+ char **cpp;
+ int names = 1;
+ int addresses = 1;
+
+ free(he->h_name);
+
+ cpp = he->h_addr_list;
+ while (*cpp != NULL) {
+ free(*cpp);
+ *cpp = NULL;
+ cpp++;
+ addresses++;
+ }
+
+ cpp = he->h_aliases;
+ while (*cpp != NULL) {
+ free(*cpp);
+ cpp++;
+ names++;
+ }
+
+ free(he->h_aliases);
+ free(he->h_addr_list);
+ free(he);
+}
+
+/*
+ * Private
+ */
+
+/*
+ * Scan the interface table and set have_v4 and have_v6 depending
+ * upon whether there are IPv4 and IPv6 interface addresses.
+ *
+ * Returns:
+ * 0 on success
+ * -1 on failure.
+ */
+
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
+ !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
+
+#ifdef __hpux
+#define lifc_len iflc_len
+#define lifc_buf iflc_buf
+#define lifc_req iflc_req
+#define LIFCONF if_laddrconf
+#else
+#define ISC_HAVE_LIFC_FAMILY 1
+#define ISC_HAVE_LIFC_FLAGS 1
+#define LIFCONF lifconf
+#endif
+
+#ifdef __hpux
+#define lifr_addr iflr_addr
+#define lifr_name iflr_name
+#define lifr_dstaddr iflr_dstaddr
+#define lifr_flags iflr_flags
+#define ss_family sa_family
+#define LIFREQ if_laddrreq
+#else
+#define LIFREQ lifreq
+#endif
+
+static int
+scan_interfaces6(int *have_v4, int *have_v6) {
+ struct LIFCONF lifc;
+ struct LIFREQ lifreq;
+ struct in_addr in4;
+ struct in6_addr in6;
+ char *buf = NULL, *cp, *cplim;
+ static unsigned int bufsiz = 4095;
+ int s, cpsize, n;
+
+ /*
+ * Set to zero. Used as loop terminators below.
+ */
+ *have_v4 = *have_v6 = 0;
+
+ /*
+ * Get interface list from system.
+ */
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1)
+ goto err_ret;
+
+ /*
+ * Grow buffer until large enough to contain all interface
+ * descriptions.
+ */
+ for (;;) {
+ buf = malloc(bufsiz);
+ if (buf == NULL)
+ goto err_ret;
+#ifdef ISC_HAVE_LIFC_FAMILY
+ lifc.lifc_family = AF_UNSPEC; /* request all families */
+#endif
+#ifdef ISC_HAVE_LIFC_FLAGS
+ lifc.lifc_flags = 0;
+#endif
+ lifc.lifc_len = bufsiz;
+ lifc.lifc_buf = buf;
+ if ((n = ioctl(s, SIOCGLIFCONF, (char *)&lifc)) != -1) {
+ /*
+ * Some OS's just return what will fit rather
+ * than set EINVAL if the buffer is too small
+ * to fit all the interfaces in. If
+ * lifc.lifc_len is too near to the end of the
+ * buffer we will grow it just in case and
+ * retry.
+ */
+ if (lifc.lifc_len + 2 * sizeof(lifreq) < bufsiz)
+ break;
+ }
+ if ((n == -1) && errno != EINVAL)
+ goto err_ret;
+
+ if (bufsiz > 1000000)
+ goto err_ret;
+
+ free(buf);
+ bufsiz += 4096;
+ }
+
+ /*
+ * Parse system's interface list.
+ */
+ cplim = buf + lifc.lifc_len; /* skip over if's with big ifr_addr's */
+ for (cp = buf;
+ (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
+ cp += cpsize) {
+ memcpy(&lifreq, cp, sizeof(lifreq));
+#ifdef LWRES_PLATFORM_HAVESALEN
+#ifdef FIX_ZERO_SA_LEN
+ if (lifreq.lifr_addr.sa_len == 0)
+ lifreq.lifr_addr.sa_len = 16;
+#endif
+#ifdef HAVE_MINIMUM_IFREQ
+ cpsize = sizeof(lifreq);
+ if (lifreq.lifr_addr.sa_len > sizeof(struct sockaddr))
+ cpsize += (int)lifreq.lifr_addr.sa_len -
+ (int)(sizeof(struct sockaddr));
+#else
+ cpsize = sizeof(lifreq.lifr_name) + lifreq.lifr_addr.sa_len;
+#endif /* HAVE_MINIMUM_IFREQ */
+#elif defined SIOCGIFCONF_ADDR
+ cpsize = sizeof(lifreq);
+#else
+ cpsize = sizeof(lifreq.lifr_name);
+ /* XXX maybe this should be a hard error? */
+ if (ioctl(s, SIOCGLIFADDR, (char *)&lifreq) < 0)
+ continue;
+#endif
+ switch (lifreq.lifr_addr.ss_family) {
+ case AF_INET:
+ if (*have_v4 == 0) {
+ memcpy(&in4,
+ &((struct sockaddr_in *)
+ &lifreq.lifr_addr)->sin_addr,
+ sizeof(in4));
+ if (in4.s_addr == INADDR_ANY)
+ break;
+ n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq);
+ if (n < 0)
+ break;
+ if ((lifreq.lifr_flags & IFF_UP) == 0)
+ break;
+ *have_v4 = 1;
+ }
+ break;
+ case AF_INET6:
+ if (*have_v6 == 0) {
+ memcpy(&in6,
+ &((struct sockaddr_in6 *)
+ &lifreq.lifr_addr)->sin6_addr,
+ sizeof(in6));
+ if (memcmp(&in6, &in6addr_any,
+ sizeof(in6)) == 0)
+ break;
+ n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq);
+ if (n < 0)
+ break;
+ if ((lifreq.lifr_flags & IFF_UP) == 0)
+ break;
+ *have_v6 = 1;
+ }
+ break;
+ }
+ }
+ if (buf != NULL)
+ free(buf);
+ close(s);
+ return (0);
+ err_ret:
+ if (buf != NULL)
+ free(buf);
+ if (s != -1)
+ close(s);
+ return (-1);
+}
+#endif
+
+static int
+scan_interfaces(int *have_v4, int *have_v6) {
+#if !defined(SIOCGIFCONF) || !defined(SIOCGIFADDR)
+ *have_v4 = *have_v6 = 1;
+ return (0);
+#else
+ struct ifconf ifc;
+ union {
+ char _pad[256]; /* leave space for IPv6 addresses */
+ struct ifreq ifreq;
+ } u;
+ struct in_addr in4;
+ struct in6_addr in6;
+ char *buf = NULL, *cp, *cplim;
+ static unsigned int bufsiz = 4095;
+ int s, n;
+ size_t cpsize;
+
+#ifdef WIN32
+ InitSockets();
+#endif
+#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
+ !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
+ /*
+ * Try to scan the interfaces using IPv6 ioctls().
+ */
+ if (!scan_interfaces6(have_v4, have_v6)) {
+#ifdef WIN32
+ DestroySockets();
+#endif
+ return (0);
+ }
+#endif
+
+ /*
+ * Set to zero. Used as loop terminators below.
+ */
+ *have_v4 = *have_v6 = 0;
+
+ /*
+ * Get interface list from system.
+ */
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ goto err_ret;
+
+ /*
+ * Grow buffer until large enough to contain all interface
+ * descriptions.
+ */
+ for (;;) {
+ buf = malloc(bufsiz);
+ if (buf == NULL)
+ goto err_ret;
+ ifc.ifc_len = bufsiz;
+ ifc.ifc_buf = buf;
+#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
+ /*
+ * This is a fix for IRIX OS in which the call to ioctl with
+ * the flag SIOCGIFCONF may not return an entry for all the
+ * interfaces like most flavors of Unix.
+ */
+ if (emul_ioctl(&ifc) >= 0)
+ break;
+#else
+ if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) {
+ /*
+ * Some OS's just return what will fit rather
+ * than set EINVAL if the buffer is too small
+ * to fit all the interfaces in. If
+ * ifc.ifc_len is too near to the end of the
+ * buffer we will grow it just in case and
+ * retry.
+ */
+ if (ifc.ifc_len + 2 * sizeof(u.ifreq) < bufsiz)
+ break;
+ }
+#endif
+ if ((n == -1) && errno != EINVAL)
+ goto err_ret;
+
+ if (bufsiz > 1000000)
+ goto err_ret;
+
+ free(buf);
+ bufsiz += 4096;
+ }
+
+ /*
+ * Parse system's interface list.
+ */
+ cplim = buf + ifc.ifc_len; /* skip over if's with big ifr_addr's */
+ for (cp = buf;
+ (*have_v4 == 0 || *have_v6 == 0) && cp < cplim;
+ cp += cpsize) {
+ memcpy(&u.ifreq, cp, sizeof(u.ifreq));
+#ifdef LWRES_PLATFORM_HAVESALEN
+#ifdef FIX_ZERO_SA_LEN
+ if (u.ifreq.ifr_addr.sa_len == 0)
+ u.ifreq.ifr_addr.sa_len = 16;
+#endif
+#ifdef HAVE_MINIMUM_IFREQ
+ cpsize = sizeof(u.ifreq);
+ if (u.ifreq.ifr_addr.sa_len > sizeof(struct sockaddr))
+ cpsize += (int)u.ifreq.ifr_addr.sa_len -
+ (int)(sizeof(struct sockaddr));
+#else
+ cpsize = sizeof(u.ifreq.ifr_name) + u.ifreq.ifr_addr.sa_len;
+#endif /* HAVE_MINIMUM_IFREQ */
+ if (cpsize > sizeof(u.ifreq) && cpsize <= sizeof(u))
+ memcpy(&u.ifreq, cp, cpsize);
+#elif defined SIOCGIFCONF_ADDR
+ cpsize = sizeof(u.ifreq);
+#else
+ cpsize = sizeof(u.ifreq.ifr_name);
+ /* XXX maybe this should be a hard error? */
+ if (ioctl(s, SIOCGIFADDR, (char *)&u.ifreq) < 0)
+ continue;
+#endif
+ switch (u.ifreq.ifr_addr.sa_family) {
+ case AF_INET:
+ if (*have_v4 == 0) {
+ memcpy(&in4,
+ &((struct sockaddr_in *)
+ &u.ifreq.ifr_addr)->sin_addr,
+ sizeof(in4));
+ if (in4.s_addr == INADDR_ANY)
+ break;
+ n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq);
+ if (n < 0)
+ break;
+ if ((u.ifreq.ifr_flags & IFF_UP) == 0)
+ break;
+ *have_v4 = 1;
+ }
+ break;
+ case AF_INET6:
+ if (*have_v6 == 0) {
+ memcpy(&in6,
+ &((struct sockaddr_in6 *)
+ &u.ifreq.ifr_addr)->sin6_addr,
+ sizeof(in6));
+ if (memcmp(&in6, &in6addr_any,
+ sizeof(in6)) == 0)
+ break;
+ n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq);
+ if (n < 0)
+ break;
+ if ((u.ifreq.ifr_flags & IFF_UP) == 0)
+ break;
+ *have_v6 = 1;
+ }
+ break;
+ }
+ }
+ if (buf != NULL)
+ free(buf);
+#ifdef WIN32
+ DestroySockets();
+#endif
+ close(s);
+ return (0);
+
+ err_ret:
+ if (buf != NULL)
+ free(buf);
+ if (s != -1)
+ close(s);
+#ifdef WIN32
+ DestroySockets();
+#endif
+ return (-1);
+#endif
+}
+
+static struct hostent *
+copyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num)
+{
+ struct hostent *he = NULL;
+ int addresses = 1; /* NULL terminator */
+ int names = 1; /* NULL terminator */
+ int len = 0;
+ char **cpp, **npp;
+
+ /*
+ * Work out array sizes.
+ */
+ if (he1 != NULL) {
+ cpp = he1->h_addr_list;
+ while (*cpp != NULL) {
+ addresses++;
+ cpp++;
+ }
+ cpp = he1->h_aliases;
+ while (*cpp != NULL) {
+ names++;
+ cpp++;
+ }
+ }
+
+ if (he2 != NULL) {
+ cpp = he2->h_addr_list;
+ while (*cpp != NULL) {
+ addresses++;
+ cpp++;
+ }
+ if (he1 == NULL) {
+ cpp = he2->h_aliases;
+ while (*cpp != NULL) {
+ names++;
+ cpp++;
+ }
+ }
+ }
+
+ if (addresses == 1) {
+ *error_num = NO_ADDRESS;
+ return (NULL);
+ }
+
+ he = malloc(sizeof(*he));
+ if (he == NULL)
+ goto no_recovery;
+
+ he->h_addr_list = malloc(sizeof(char *) * (addresses));
+ if (he->h_addr_list == NULL)
+ goto cleanup0;
+ memset(he->h_addr_list, 0, sizeof(char *) * (addresses));
+
+ /*
+ * Copy addresses.
+ */
+ npp = he->h_addr_list;
+ if (he1 != NULL) {
+ cpp = he1->h_addr_list;
+ while (*cpp != NULL) {
+ *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
+ if (*npp == NULL)
+ goto cleanup1;
+ /*
+ * Convert to mapped if required.
+ */
+ if (af == AF_INET6 && he1->h_addrtype == AF_INET) {
+ memcpy(*npp, in6addr_mapped,
+ sizeof(in6addr_mapped));
+ memcpy(*npp + sizeof(in6addr_mapped), *cpp,
+ INADDRSZ);
+ } else {
+ memcpy(*npp, *cpp,
+ (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
+ }
+ cpp++;
+ npp++;
+ }
+ }
+
+ if (he2 != NULL) {
+ cpp = he2->h_addr_list;
+ while (*cpp != NULL) {
+ *npp = malloc((af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
+ if (*npp == NULL)
+ goto cleanup1;
+ /*
+ * Convert to mapped if required.
+ */
+ if (af == AF_INET6 && he2->h_addrtype == AF_INET) {
+ memcpy(*npp, in6addr_mapped,
+ sizeof(in6addr_mapped));
+ memcpy(*npp + sizeof(in6addr_mapped), *cpp,
+ INADDRSZ);
+ } else {
+ memcpy(*npp, *cpp,
+ (af == AF_INET) ? INADDRSZ : IN6ADDRSZ);
+ }
+ cpp++;
+ npp++;
+ }
+ }
+
+ he->h_aliases = malloc(sizeof(char *) * (names));
+ if (he->h_aliases == NULL)
+ goto cleanup1;
+ memset(he->h_aliases, 0, sizeof(char *) * (names));
+
+ /*
+ * Copy aliases.
+ */
+ npp = he->h_aliases;
+ cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases;
+ while (*cpp != NULL) {
+ len = strlen (*cpp) + 1;
+ *npp = malloc(len);
+ if (*npp == NULL)
+ goto cleanup2;
+ strcpy(*npp, *cpp);
+ npp++;
+ cpp++;
+ }
+
+ /*
+ * Copy hostname.
+ */
+ he->h_name = malloc(strlen((he1 != NULL) ?
+ he1->h_name : he2->h_name) + 1);
+ if (he->h_name == NULL)
+ goto cleanup2;
+ strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name);
+
+ /*
+ * Set address type and length.
+ */
+ he->h_addrtype = af;
+ he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ;
+ return (he);
+
+ cleanup2:
+ cpp = he->h_aliases;
+ while (*cpp != NULL) {
+ free(*cpp);
+ cpp++;
+ }
+ free(he->h_aliases);
+
+ cleanup1:
+ cpp = he->h_addr_list;
+ while (*cpp != NULL) {
+ free(*cpp);
+ *cpp = NULL;
+ cpp++;
+ }
+ free(he->h_addr_list);
+
+ cleanup0:
+ free(he);
+
+ no_recovery:
+ *error_num = NO_RECOVERY;
+ return (NULL);
+}
+
+static struct hostent *
+hostfromaddr(lwres_gnbaresponse_t *addr, int af, const void *src) {
+ struct hostent *he;
+ int i;
+
+ he = malloc(sizeof(*he));
+ if (he == NULL)
+ goto cleanup;
+ memset(he, 0, sizeof(*he));
+
+ /*
+ * Set family and length.
+ */
+ he->h_addrtype = af;
+ switch (af) {
+ case AF_INET:
+ he->h_length = INADDRSZ;
+ break;
+ case AF_INET6:
+ he->h_length = IN6ADDRSZ;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ /*
+ * Copy name.
+ */
+ he->h_name = strdup(addr->realname);
+ if (he->h_name == NULL)
+ goto cleanup;
+
+ /*
+ * Copy aliases.
+ */
+ he->h_aliases = malloc(sizeof(char *) * (addr->naliases + 1));
+ if (he->h_aliases == NULL)
+ goto cleanup;
+ for (i = 0; i < addr->naliases; i++) {
+ he->h_aliases[i] = strdup(addr->aliases[i]);
+ if (he->h_aliases[i] == NULL)
+ goto cleanup;
+ }
+ he->h_aliases[i] = NULL;
+
+ /*
+ * Copy address.
+ */
+ he->h_addr_list = malloc(sizeof(char *) * 2);
+ if (he->h_addr_list == NULL)
+ goto cleanup;
+ he->h_addr_list[0] = malloc(he->h_length);
+ if (he->h_addr_list[0] == NULL)
+ goto cleanup;
+ memcpy(he->h_addr_list[0], src, he->h_length);
+ he->h_addr_list[1] = NULL;
+ return (he);
+
+ cleanup:
+ if (he != NULL && he->h_addr_list != NULL) {
+ for (i = 0; he->h_addr_list[i] != NULL; i++)
+ free(he->h_addr_list[i]);
+ free(he->h_addr_list);
+ }
+ if (he != NULL && he->h_aliases != NULL) {
+ for (i = 0; he->h_aliases[i] != NULL; i++)
+ free(he->h_aliases[i]);
+ free(he->h_aliases);
+ }
+ if (he != NULL && he->h_name != NULL)
+ free(he->h_name);
+ if (he != NULL)
+ free(he);
+ return (NULL);
+}
+
+static struct hostent *
+hostfromname(lwres_gabnresponse_t *name, int af) {
+ struct hostent *he;
+ int i;
+ lwres_addr_t *addr;
+
+ he = malloc(sizeof(*he));
+ if (he == NULL)
+ goto cleanup;
+ memset(he, 0, sizeof(*he));
+
+ /*
+ * Set family and length.
+ */
+ he->h_addrtype = af;
+ switch (af) {
+ case AF_INET:
+ he->h_length = INADDRSZ;
+ break;
+ case AF_INET6:
+ he->h_length = IN6ADDRSZ;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ /*
+ * Copy name.
+ */
+ he->h_name = strdup(name->realname);
+ if (he->h_name == NULL)
+ goto cleanup;
+
+ /*
+ * Copy aliases.
+ */
+ he->h_aliases = malloc(sizeof(char *) * (name->naliases + 1));
+ for (i = 0; i < name->naliases; i++) {
+ he->h_aliases[i] = strdup(name->aliases[i]);
+ if (he->h_aliases[i] == NULL)
+ goto cleanup;
+ }
+ he->h_aliases[i] = NULL;
+
+ /*
+ * Copy addresses.
+ */
+ he->h_addr_list = malloc(sizeof(char *) * (name->naddrs + 1));
+ addr = LWRES_LIST_HEAD(name->addrs);
+ i = 0;
+ while (addr != NULL) {
+ he->h_addr_list[i] = malloc(he->h_length);
+ if (he->h_addr_list[i] == NULL)
+ goto cleanup;
+ memcpy(he->h_addr_list[i], addr->address, he->h_length);
+ addr = LWRES_LIST_NEXT(addr, link);
+ i++;
+ }
+ he->h_addr_list[i] = NULL;
+ return (he);
+
+ cleanup:
+ if (he != NULL && he->h_addr_list != NULL) {
+ for (i = 0; he->h_addr_list[i] != NULL; i++)
+ free(he->h_addr_list[i]);
+ free(he->h_addr_list);
+ }
+ if (he != NULL && he->h_aliases != NULL) {
+ for (i = 0; he->h_aliases[i] != NULL; i++)
+ free(he->h_aliases[i]);
+ free(he->h_aliases);
+ }
+ if (he != NULL && he->h_name != NULL)
+ free(he->h_name);
+ if (he != NULL)
+ free(he);
+ return (NULL);
+}
diff --git a/lib/lwres/getnameinfo.c b/lib/lwres/getnameinfo.c
new file mode 100644
index 0000000..74a5b85
--- /dev/null
+++ b/lib/lwres/getnameinfo.c
@@ -0,0 +1,346 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 1999-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: getnameinfo.c,v 1.39 2007/06/19 23:47:22 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.
+ */
+
+/*
+ * XXX
+ * Issues to be discussed:
+ * - Return values. There seems to be no standard for return value (RFC2553)
+ * but INRIA implementation returns EAI_xxx defined for getaddrinfo().
+ */
+
+
+/**
+ * This function is equivalent to the getnameinfo(3) function defined in
+ * RFC2133. lwres_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
+ *
+ * lwres_getnameinfo() returns 0 on success or a non-zero error code if
+ * an error occurs.
+ *
+ * \section getname_see See Also
+ *
+ * RFC2133, getservbyport(),
+ * lwres_getnamebyaddr(). lwres_net_ntop().
+ *
+ * \section getnameinfo_bugs Bugs
+ *
+ * RFC2133 fails to define what the nonzero return values of
+ * getnameinfo() are.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+#include <lwres/netdb.h>
+#include "print_p.h"
+
+#include "assert_p.h"
+
+#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},
+};
+
+#define ENI_NOSERVNAME 1
+#define ENI_NOHOSTNAME 2
+#define ENI_MEMORY 3
+#define ENI_SYSTEM 4
+#define ENI_FAMILY 5
+#define ENI_SALEN 6
+#define ENI_NOSOCKET 7
+
+/*!
+ * 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)
+
+/*% lightweight resolver socket address structure to hostname and service name */
+int
+lwres_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
+ size_t hostlen, char *serv, size_t servlen, int flags)
+{
+ struct afd *afd;
+ struct servent *sp;
+ unsigned short port;
+#ifdef LWRES_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;
+ lwres_uint32_t lwf = 0;
+ lwres_context_t *lwrctx = NULL;
+ lwres_gnbaresponse_t *by = NULL;
+ int result = SUCCESS;
+ int n;
+
+ if (sa == NULL)
+ ERR(ENI_NOSOCKET);
+
+#ifdef LWRES_PLATFORM_HAVESALEN
+ len = sa->sa_len;
+ if (len != salen)
+ ERR(ENI_SALEN);
+#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(ENI_FAMILY);
+
+ found:
+ if (salen != afd->a_socklen)
+ ERR(ENI_SALEN);
+
+ 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(ENI_MEMORY);
+ strcpy(serv, numserv);
+ } else {
+ if ((strlen(sp->s_name) + 1) > servlen)
+ ERR(ENI_MEMORY);
+ 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) {
+ /*
+ * What should we do?
+ */
+ } else if (flags & NI_NUMERICHOST) {
+ if (lwres_net_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ ERR(ENI_SYSTEM);
+#if defined(LWRES_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;
+#if 0
+ if ((flags & NI_NUMERICSCOPE) == 0) {
+ /*
+ * 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(ENI_MEMORY);
+ strcpy(host, numaddr);
+ } else {
+ switch (family) {
+ case AF_INET:
+ lwf = LWRES_ADDRTYPE_V4;
+ break;
+ case AF_INET6:
+ lwf = LWRES_ADDRTYPE_V6;
+ break;
+ default:
+ INSIST(0);
+ }
+
+ n = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
+ if (n == 0)
+ (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
+
+ if (n == 0)
+ n = lwres_getnamebyaddr(lwrctx, lwf,
+ (lwres_uint16_t)afd->a_addrlen,
+ addr, &by);
+ if (n == 0) {
+ if (flags & NI_NOFQDN) {
+ p = strchr(by->realname, '.');
+ if (p)
+ *p = '\0';
+ }
+ if ((strlen(by->realname) + 1) > hostlen)
+ ERR(ENI_MEMORY);
+ strcpy(host, by->realname);
+ } else {
+ if (flags & NI_NAMEREQD)
+ ERR(ENI_NOHOSTNAME);
+ if (lwres_net_ntop(afd->a_af, addr, numaddr,
+ sizeof(numaddr))
+ == NULL)
+ ERR(ENI_NOHOSTNAME);
+ if ((strlen(numaddr) + 1) > hostlen)
+ ERR(ENI_MEMORY);
+ strcpy(host, numaddr);
+ }
+ }
+ result = SUCCESS;
+ cleanup:
+ if (by != NULL)
+ lwres_gnbaresponse_free(lwrctx, &by);
+ if (lwrctx != NULL) {
+ lwres_conf_clear(lwrctx);
+ lwres_context_destroy(&lwrctx);
+ }
+ return (result);
+}
diff --git a/lib/lwres/getrrset.c b/lib/lwres/getrrset.c
new file mode 100644
index 0000000..d8b6cc3
--- /dev/null
+++ b/lib/lwres/getrrset.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: getrrset.c,v 1.18 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+/**
+ * DESCRIPTION
+ *
+ * lwres_getrrsetbyname() gets a set of resource records associated with
+ * a hostname, class, and type. hostname is a pointer a to
+ * null-terminated string. The flags field is currently unused and must
+ * be zero.
+ *
+ * After a successful call to lwres_getrrsetbyname(), *res is a pointer
+ * to an #rrsetinfo structure, containing a list of one or more #rdatainfo
+ * structures containing resource records and potentially another list of
+ * rdatainfo structures containing SIG resource records associated with
+ * those records. The members #rri_rdclass and #rri_rdtype are copied from
+ * the parameters. #rri_ttl and #rri_name are properties of the obtained
+ * rrset. The resource records contained in #rri_rdatas and #rri_sigs are
+ * in uncompressed DNS wire format. Properties of the rdataset are
+ * represented in the #rri_flags bitfield. If the #RRSET_VALIDATED bit is
+ * set, the data has been DNSSEC validated and the signatures verified.
+ *
+ * All of the information returned by lwres_getrrsetbyname() is
+ * dynamically allocated: the rrsetinfo and rdatainfo structures, and the
+ * canonical host name strings pointed to by the rrsetinfostructure.
+ * Memory allocated for the dynamically allocated structures created by a
+ * successful call to lwres_getrrsetbyname() is released by
+ * lwres_freerrset(). rrset is a pointer to a struct rrset created by a
+ * call to lwres_getrrsetbyname().
+ *
+ * The following structures are used:
+ *
+ * \code
+ * struct rdatainfo {
+ * unsigned int rdi_length; // length of data
+ * unsigned char *rdi_data; // record data
+ * };
+ *
+ * struct rrsetinfo {
+ * unsigned int rri_flags; // RRSET_VALIDATED...
+ * unsigned int rri_rdclass; // class number
+ * unsigned int rri_rdtype; // RR type number
+ * unsigned int rri_ttl; // time to live
+ * unsigned int rri_nrdatas; // size of rdatas array
+ * unsigned int rri_nsigs; // size of sigs array
+ * char *rri_name; // canonical name
+ * struct rdatainfo *rri_rdatas; // individual records
+ * struct rdatainfo *rri_sigs; // individual signatures
+ * };
+ * \endcode
+ *
+ * \section getrrset_return Return Values
+ *
+ * lwres_getrrsetbyname() returns zero on success, and one of the
+ * following error codes if an error occurred:
+ *
+ * \li #ERRSET_NONAME: the name does not exist
+ *
+ * \li #ERRSET_NODATA:
+ * the name exists, but does not have data of the desired type
+ *
+ * \li #ERRSET_NOMEMORY:
+ * memory could not be allocated
+ *
+ * \li #ERRSET_INVAL:
+ * a parameter is invalid
+ *
+ * \li #ERRSET_FAIL:
+ * other failure
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+#include <lwres/netdb.h> /* XXX #include <netdb.h> */
+
+#include "assert_p.h"
+
+/*!
+ * Structure to map results
+ */
+static unsigned int
+lwresult_to_result(lwres_result_t lwresult) {
+ switch (lwresult) {
+ case LWRES_R_SUCCESS: return (ERRSET_SUCCESS);
+ case LWRES_R_NOMEMORY: return (ERRSET_NOMEMORY);
+ case LWRES_R_NOTFOUND: return (ERRSET_NONAME);
+ case LWRES_R_TYPENOTFOUND: return (ERRSET_NODATA);
+ default: return (ERRSET_FAIL);
+ }
+}
+
+/*@{*/
+/*!
+ * malloc / calloc functions that guarantee to only
+ * return NULL if there is an error, like they used
+ * to before the ANSI C committee broke them.
+ */
+
+static void *
+sane_malloc(size_t size) {
+ if (size == 0U)
+ size = 1;
+ return (malloc(size));
+}
+
+static void *
+sane_calloc(size_t number, size_t size) {
+ size_t len = number * size;
+ void *mem = sane_malloc(len);
+ if (mem != NULL)
+ memset(mem, 0, len);
+ return (mem);
+}
+/*@}*/
+
+/*% Returns a set of resource records associated with a hostname, class, and type. hostname is a pointer a to null-terminated string. */
+int
+lwres_getrrsetbyname(const char *hostname, unsigned int rdclass,
+ unsigned int rdtype, unsigned int flags,
+ struct rrsetinfo **res)
+{
+ lwres_context_t *lwrctx = NULL;
+ lwres_result_t lwresult;
+ lwres_grbnresponse_t *response = NULL;
+ struct rrsetinfo *rrset = NULL;
+ unsigned int i;
+ unsigned int lwflags;
+ unsigned int result;
+
+ if (rdclass > 0xffff || rdtype > 0xffff) {
+ result = ERRSET_INVAL;
+ goto fail;
+ }
+
+ /*
+ * Don't allow queries of class or type ANY
+ */
+ if (rdclass == 0xff || rdtype == 0xff) {
+ result = ERRSET_INVAL;
+ goto fail;
+ }
+
+ lwresult = lwres_context_create(&lwrctx, NULL, NULL, NULL, 0);
+ if (lwresult != LWRES_R_SUCCESS) {
+ result = lwresult_to_result(lwresult);
+ goto fail;
+ }
+ (void) lwres_conf_parse(lwrctx, lwres_resolv_conf);
+
+ /*
+ * If any input flags were defined, lwflags would be set here
+ * based on them
+ */
+ UNUSED(flags);
+ lwflags = 0;
+
+ lwresult = lwres_getrdatabyname(lwrctx, hostname,
+ (lwres_uint16_t)rdclass,
+ (lwres_uint16_t)rdtype,
+ lwflags, &response);
+ if (lwresult != LWRES_R_SUCCESS) {
+ result = lwresult_to_result(lwresult);
+ goto fail;
+ }
+
+ rrset = sane_malloc(sizeof(struct rrsetinfo));
+ if (rrset == NULL) {
+ result = ERRSET_NOMEMORY;
+ goto fail;
+ }
+ rrset->rri_name = NULL;
+ rrset->rri_rdclass = response->rdclass;
+ rrset->rri_rdtype = response->rdtype;
+ rrset->rri_ttl = response->ttl;
+ rrset->rri_flags = 0;
+ rrset->rri_nrdatas = 0;
+ rrset->rri_rdatas = NULL;
+ rrset->rri_nsigs = 0;
+ rrset->rri_sigs = NULL;
+
+ rrset->rri_name = sane_malloc(response->realnamelen + 1);
+ if (rrset->rri_name == NULL) {
+ result = ERRSET_NOMEMORY;
+ goto fail;
+ }
+ strncpy(rrset->rri_name, response->realname, response->realnamelen);
+ rrset->rri_name[response->realnamelen] = 0;
+
+ if ((response->flags & LWRDATA_VALIDATED) != 0)
+ rrset->rri_flags |= RRSET_VALIDATED;
+
+ rrset->rri_nrdatas = response->nrdatas;
+ rrset->rri_rdatas = sane_calloc(rrset->rri_nrdatas,
+ sizeof(struct rdatainfo));
+ if (rrset->rri_rdatas == NULL) {
+ result = ERRSET_NOMEMORY;
+ goto fail;
+ }
+ for (i = 0; i < rrset->rri_nrdatas; i++) {
+ rrset->rri_rdatas[i].rdi_length = response->rdatalen[i];
+ rrset->rri_rdatas[i].rdi_data =
+ sane_malloc(rrset->rri_rdatas[i].rdi_length);
+ if (rrset->rri_rdatas[i].rdi_data == NULL) {
+ result = ERRSET_NOMEMORY;
+ goto fail;
+ }
+ memcpy(rrset->rri_rdatas[i].rdi_data, response->rdatas[i],
+ rrset->rri_rdatas[i].rdi_length);
+ }
+ rrset->rri_nsigs = response->nsigs;
+ rrset->rri_sigs = sane_calloc(rrset->rri_nsigs,
+ sizeof(struct rdatainfo));
+ if (rrset->rri_sigs == NULL) {
+ result = ERRSET_NOMEMORY;
+ goto fail;
+ }
+ for (i = 0; i < rrset->rri_nsigs; i++) {
+ rrset->rri_sigs[i].rdi_length = response->siglen[i];
+ rrset->rri_sigs[i].rdi_data =
+ sane_malloc(rrset->rri_sigs[i].rdi_length);
+ if (rrset->rri_sigs[i].rdi_data == NULL) {
+ result = ERRSET_NOMEMORY;
+ goto fail;
+ }
+ memcpy(rrset->rri_sigs[i].rdi_data, response->sigs[i],
+ rrset->rri_sigs[i].rdi_length);
+ }
+
+ lwres_grbnresponse_free(lwrctx, &response);
+ lwres_conf_clear(lwrctx);
+ lwres_context_destroy(&lwrctx);
+ *res = rrset;
+ return (ERRSET_SUCCESS);
+ fail:
+ if (rrset != NULL)
+ lwres_freerrset(rrset);
+ if (response != NULL)
+ lwres_grbnresponse_free(lwrctx, &response);
+ if (lwrctx != NULL) {
+ lwres_conf_clear(lwrctx);
+ lwres_context_destroy(&lwrctx);
+ }
+ return (result);
+}
+
+/*% Releases memory allocated for the dynamically allocated structures created by a successful call to lwres_getrrsetbyname(). */
+void
+lwres_freerrset(struct rrsetinfo *rrset) {
+ unsigned int i;
+ for (i = 0; i < rrset->rri_nrdatas; i++) {
+ if (rrset->rri_rdatas[i].rdi_data == NULL)
+ break;
+ free(rrset->rri_rdatas[i].rdi_data);
+ }
+ free(rrset->rri_rdatas);
+ for (i = 0; i < rrset->rri_nsigs; i++) {
+ if (rrset->rri_sigs[i].rdi_data == NULL)
+ break;
+ free(rrset->rri_sigs[i].rdi_data);
+ }
+ free(rrset->rri_sigs);
+ free(rrset->rri_name);
+ free(rrset);
+}
diff --git a/lib/lwres/herror.c b/lib/lwres/herror.c
new file mode 100644
index 0000000..cf5b892
--- /dev/null
+++ b/lib/lwres/herror.c
@@ -0,0 +1,122 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2000, 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.
+ */
+
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*! \file herror.c
+ lwres_herror() prints the string s on stderr followed by the string
+ generated by lwres_hstrerror() for the error code stored in the global
+ variable lwres_h_errno.
+
+ lwres_hstrerror() returns an appropriate string for the error code
+ gievn by err. The values of the error codes and messages are as
+ follows:
+
+\li #NETDB_SUCCESS: Resolver Error 0 (no error)
+
+\li #HOST_NOT_FOUND: Unknown host
+
+\li #TRY_AGAIN: Host name lookup failure
+
+\li #NO_RECOVERY: Unknown server error
+
+\li #NO_DATA: No address associated with name
+
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] =
+ "$Id: herror.c,v 1.17 2007/06/19 23:47:22 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <lwres/netdb.h>
+#include <lwres/platform.h>
+
+LIBLWRES_EXTERNAL_DATA int lwres_h_errno;
+
+/*!
+ * these have never been declared in any header file so make them static
+ */
+
+static const char *h_errlist[] = {
+ "Resolver Error 0 (no error)", /*%< 0 no error */
+ "Unknown host", /*%< 1 HOST_NOT_FOUND */
+ "Host name lookup failure", /*%< 2 TRY_AGAIN */
+ "Unknown server error", /*%< 3 NO_RECOVERY */
+ "No address associated with name", /*%< 4 NO_ADDRESS */
+};
+
+static int h_nerr = { sizeof(h_errlist) / sizeof(h_errlist[0]) };
+
+
+/*!
+ * herror --
+ * print the error indicated by the h_errno value.
+ */
+void
+lwres_herror(const char *s) {
+ fprintf(stderr, "%s: %s\n", s, lwres_hstrerror(lwres_h_errno));
+}
+
+/*!
+ * hstrerror --
+ * return the string associated with a given "host" errno value.
+ */
+const char *
+lwres_hstrerror(int err) {
+ if (err < 0)
+ return ("Resolver internal error");
+ else if (err < h_nerr)
+ return (h_errlist[err]);
+ return ("Unknown resolver error");
+}
diff --git a/lib/lwres/include/Makefile.in b/lib/lwres/include/Makefile.in
new file mode 100644
index 0000000..4750a5e
--- /dev/null
+++ b/lib/lwres/include/Makefile.in
@@ -0,0 +1,25 @@
+# Copyright (C) 2004, 2007 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: Makefile.in,v 1.8 2007/06/19 23:47:22 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = lwres
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/lwres/include/lwres/Makefile.in b/lib/lwres/include/lwres/Makefile.in
new file mode 100644
index 0000000..fc3126f
--- /dev/null
+++ b/lib/lwres/include/lwres/Makefile.in
@@ -0,0 +1,46 @@
+# Copyright (C) 2004, 2007 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: Makefile.in,v 1.23 2007/06/19 23:47:22 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 = context.h lwbuffer.h lwpacket.h lwres.h result.h \
+ int.h lang.h list.h ipv6.h version.h
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/lwres
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} ${srcdir}/$$i ${DESTDIR}${includedir}/lwres ; \
+ done
+ ${INSTALL_DATA} netdb.h ${DESTDIR}${includedir}/lwres
+ ${INSTALL_DATA} platform.h ${DESTDIR}${includedir}/lwres
+
+distclean::
+ rm -f netdb.h platform.h
diff --git a/lib/lwres/include/lwres/context.h b/lib/lwres/include/lwres/context.h
new file mode 100644
index 0000000..bf6402e
--- /dev/null
+++ b/lib/lwres/include/lwres/context.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2004-2007 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: context.h,v 1.21 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_CONTEXT_H
+#define LWRES_CONTEXT_H 1
+
+/*! \file lwres/context.h */
+
+#include <stddef.h>
+
+#include <lwres/lang.h>
+#include <lwres/int.h>
+#include <lwres/result.h>
+
+/*!
+ * Used to set various options such as timeout, authentication, etc
+ */
+typedef struct lwres_context lwres_context_t;
+
+LWRES_LANG_BEGINDECLS
+
+typedef void *(*lwres_malloc_t)(void *arg, size_t length);
+typedef void (*lwres_free_t)(void *arg, void *mem, size_t length);
+
+/*
+ * XXXMLG
+ *
+ * Make the server reload /etc/resolv.conf periodically.
+ *
+ * Make the server do sortlist/searchlist.
+ *
+ * Client side can disable the search/sortlist processing.
+ *
+ * Use an array of addresses/masks and searchlist for client-side, and
+ * if added to the client disable the processing on the server.
+ *
+ * Share /etc/resolv.conf data between contexts.
+ */
+
+/*!
+ * _SERVERMODE
+ * Don't allocate and connect a socket to the server, since the
+ * caller _is_ a server.
+ */
+#define LWRES_CONTEXT_SERVERMODE 0x00000001U
+
+lwres_result_t
+lwres_context_create(lwres_context_t **contextp, void *arg,
+ lwres_malloc_t malloc_function,
+ lwres_free_t free_function,
+ unsigned int flags);
+/**<
+ * Allocate a lwres context. This is used in all lwres calls.
+ *
+ * Memory management can be replaced here by passing in two functions.
+ * If one is non-NULL, they must both be non-NULL. "arg" is passed to
+ * these functions.
+ *
+ * Contexts are not thread safe. Document at the top of the file.
+ * XXXMLG
+ *
+ * If they are NULL, the standard malloc() and free() will be used.
+ *
+ *\pre contextp != NULL && contextp == NULL.
+ *
+ *\return Returns 0 on success, non-zero on failure.
+ */
+
+void
+lwres_context_destroy(lwres_context_t **contextp);
+/**<
+ * Frees all memory associated with a lwres context.
+ *
+ *\pre contextp != NULL && contextp == NULL.
+ */
+
+lwres_uint32_t
+lwres_context_nextserial(lwres_context_t *ctx);
+/**<
+ * XXXMLG Document
+ */
+
+void
+lwres_context_initserial(lwres_context_t *ctx, lwres_uint32_t serial);
+
+void
+lwres_context_freemem(lwres_context_t *ctx, void *mem, size_t len);
+
+void *
+lwres_context_allocmem(lwres_context_t *ctx, size_t len);
+
+int
+lwres_context_getsocket(lwres_context_t *ctx);
+
+lwres_result_t
+lwres_context_send(lwres_context_t *ctx,
+ void *sendbase, int sendlen);
+
+lwres_result_t
+lwres_context_recv(lwres_context_t *ctx,
+ void *recvbase, int recvlen,
+ int *recvd_len);
+
+lwres_result_t
+lwres_context_sendrecv(lwres_context_t *ctx,
+ void *sendbase, int sendlen,
+ void *recvbase, int recvlen,
+ int *recvd_len);
+
+LWRES_LANG_ENDDECLS
+
+#endif /* LWRES_CONTEXT_H */
+
diff --git a/lib/lwres/include/lwres/int.h b/lib/lwres/include/lwres/int.h
new file mode 100644
index 0000000..3fb0c4f
--- /dev/null
+++ b/lib/lwres/include/lwres/int.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2004-2007 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: int.h,v 1.14 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_INT_H
+#define LWRES_INT_H 1
+
+/*! \file lwres/int.h */
+
+typedef char lwres_int8_t;
+typedef unsigned char lwres_uint8_t;
+typedef short lwres_int16_t;
+typedef unsigned short lwres_uint16_t;
+typedef int lwres_int32_t;
+typedef unsigned int lwres_uint32_t;
+typedef long long lwres_int64_t;
+typedef unsigned long long lwres_uint64_t;
+
+#endif /* LWRES_INT_H */
diff --git a/lib/lwres/include/lwres/ipv6.h b/lib/lwres/include/lwres/ipv6.h
new file mode 100644
index 0000000..5d54b29
--- /dev/null
+++ b/lib/lwres/include/lwres/ipv6.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2004-2007 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: ipv6.h,v 1.16 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_IPV6_H
+#define LWRES_IPV6_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file lwres/ipv6.h
+ * IPv6 definitions for systems which do not support IPv6.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <lwres/int.h>
+#include <lwres/platform.h>
+
+/***
+ *** Types.
+ ***/
+
+/*% in6_addr structure */
+struct in6_addr {
+ union {
+ lwres_uint8_t _S6_u8[16];
+ lwres_uint16_t _S6_u16[8];
+ lwres_uint32_t _S6_u32[4];
+ } _S6_un;
+};
+/*@{*/
+/*% IP v6 types */
+#define s6_addr _S6_un._S6_u8
+#define s6_addr8 _S6_un._S6_u8
+#define s6_addr16 _S6_un._S6_u16
+#define s6_addr32 _S6_un._S6_u32
+/*@}*/
+
+#define IN6ADDR_ANY_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}}
+#define IN6ADDR_LOOPBACK_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}}
+
+LIBLWRES_EXTERNAL_DATA extern const struct in6_addr in6addr_any;
+LIBLWRES_EXTERNAL_DATA extern const struct in6_addr in6addr_loopback;
+
+/*% used in getaddrinfo.c and getnameinfo.c */
+struct sockaddr_in6 {
+#ifdef LWRES_PLATFORM_HAVESALEN
+ lwres_uint8_t sin6_len;
+ lwres_uint8_t sin6_family;
+#else
+ lwres_uint16_t sin6_family;
+#endif
+ lwres_uint16_t sin6_port;
+ lwres_uint32_t sin6_flowinfo;
+ struct in6_addr sin6_addr;
+ lwres_uint32_t sin6_scope_id;
+};
+
+#ifdef LWRES_PLATFORM_HAVESALEN
+#define SIN6_LEN 1
+#endif
+
+/*% in6_pktinfo structure */
+struct in6_pktinfo {
+ struct in6_addr ipi6_addr; /*%< src/dst IPv6 address */
+ unsigned int ipi6_ifindex; /*%< send/recv interface index */
+};
+
+/*!
+ * Unspecified IPv6 address
+ */
+#define IN6_IS_ADDR_UNSPECIFIED(a) \
+ (((a)->s6_addr32[0] == 0) && \
+ ((a)->s6_addr32[1] == 0) && \
+ ((a)->s6_addr32[2] == 0) && \
+ ((a)->s6_addr32[3] == 0))
+
+/*
+ * Loopback
+ */
+#define IN6_IS_ADDR_LOOPBACK(a) \
+ (((a)->s6_addr32[0] == 0) && \
+ ((a)->s6_addr32[1] == 0) && \
+ ((a)->s6_addr32[2] == 0) && \
+ ((a)->s6_addr32[3] == htonl(1)))
+
+/*
+ * IPv4 compatible
+ */
+#define IN6_IS_ADDR_V4COMPAT(a) \
+ (((a)->s6_addr32[0] == 0) && \
+ ((a)->s6_addr32[1] == 0) && \
+ ((a)->s6_addr32[2] == 0) && \
+ ((a)->s6_addr32[3] != 0) && \
+ ((a)->s6_addr32[3] != htonl(1)))
+
+/*
+ * Mapped
+ */
+#define IN6_IS_ADDR_V4MAPPED(a) \
+ (((a)->s6_addr32[0] == 0) && \
+ ((a)->s6_addr32[1] == 0) && \
+ ((a)->s6_addr32[2] == htonl(0x0000ffff)))
+
+#endif /* LWRES_IPV6_H */
diff --git a/lib/lwres/include/lwres/lang.h b/lib/lwres/include/lwres/lang.h
new file mode 100644
index 0000000..b680e4b
--- /dev/null
+++ b/lib/lwres/include/lwres/lang.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2004-2007 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: lang.h,v 1.13 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_LANG_H
+#define LWRES_LANG_H 1
+
+/*! \file lwres/lang.h */
+
+#ifdef __cplusplus
+#define LWRES_LANG_BEGINDECLS extern "C" {
+#define LWRES_LANG_ENDDECLS }
+#else
+#define LWRES_LANG_BEGINDECLS
+#define LWRES_LANG_ENDDECLS
+#endif
+
+#endif /* LWRES_LANG_H */
diff --git a/lib/lwres/include/lwres/list.h b/lib/lwres/include/lwres/list.h
new file mode 100644
index 0000000..c6ab096
--- /dev/null
+++ b/lib/lwres/include/lwres/list.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1997-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: list.h,v 1.14 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_LIST_H
+#define LWRES_LIST_H 1
+
+/*! \file lwres/list.h */
+
+#define LWRES_LIST(type) struct { type *head, *tail; }
+#define LWRES_LIST_INIT(list) \
+ do { (list).head = NULL; (list).tail = NULL; } while (0)
+
+#define LWRES_LINK(type) struct { type *prev, *next; }
+#define LWRES_LINK_INIT(elt, link) \
+ do { \
+ (elt)->link.prev = (void *)(-1); \
+ (elt)->link.next = (void *)(-1); \
+ } while (0)
+#define LWRES_LINK_LINKED(elt, link) \
+ ((void *)((elt)->link.prev) != (void *)(-1))
+
+#define LWRES_LIST_HEAD(list) ((list).head)
+#define LWRES_LIST_TAIL(list) ((list).tail)
+#define LWRES_LIST_EMPTY(list) LWRES_TF((list).head == NULL)
+
+#define LWRES_LIST_PREPEND(list, elt, link) \
+ do { \
+ if ((list).head != NULL) \
+ (list).head->link.prev = (elt); \
+ else \
+ (list).tail = (elt); \
+ (elt)->link.prev = NULL; \
+ (elt)->link.next = (list).head; \
+ (list).head = (elt); \
+ } while (0)
+
+#define LWRES_LIST_APPEND(list, elt, link) \
+ do { \
+ if ((list).tail != NULL) \
+ (list).tail->link.next = (elt); \
+ else \
+ (list).head = (elt); \
+ (elt)->link.prev = (list).tail; \
+ (elt)->link.next = NULL; \
+ (list).tail = (elt); \
+ } while (0)
+
+#define LWRES_LIST_UNLINK(list, elt, link) \
+ do { \
+ if ((elt)->link.next != NULL) \
+ (elt)->link.next->link.prev = (elt)->link.prev; \
+ else \
+ (list).tail = (elt)->link.prev; \
+ if ((elt)->link.prev != NULL) \
+ (elt)->link.prev->link.next = (elt)->link.next; \
+ else \
+ (list).head = (elt)->link.next; \
+ (elt)->link.prev = (void *)(-1); \
+ (elt)->link.next = (void *)(-1); \
+ } while (0)
+
+#define LWRES_LIST_PREV(elt, link) ((elt)->link.prev)
+#define LWRES_LIST_NEXT(elt, link) ((elt)->link.next)
+
+#define LWRES_LIST_INSERTBEFORE(list, before, elt, link) \
+ do { \
+ if ((before)->link.prev == NULL) \
+ LWRES_LIST_PREPEND(list, elt, link); \
+ else { \
+ (elt)->link.prev = (before)->link.prev; \
+ (before)->link.prev = (elt); \
+ (elt)->link.prev->link.next = (elt); \
+ (elt)->link.next = (before); \
+ } \
+ } while (0)
+
+#define LWRES_LIST_INSERTAFTER(list, after, elt, link) \
+ do { \
+ if ((after)->link.next == NULL) \
+ LWRES_LIST_APPEND(list, elt, link); \
+ else { \
+ (elt)->link.next = (after)->link.next; \
+ (after)->link.next = (elt); \
+ (elt)->link.next->link.prev = (elt); \
+ (elt)->link.prev = (after); \
+ } \
+ } while (0)
+
+#define LWRES_LIST_APPENDLIST(list1, list2, link) \
+ do { \
+ if (LWRES_LIST_EMPTY(list1)) \
+ (list1) = (list2); \
+ else if (!LWRES_LIST_EMPTY(list2)) { \
+ (list1).tail->link.next = (list2).head; \
+ (list2).head->link.prev = (list1).tail; \
+ (list1).tail = (list2).tail; \
+ } \
+ (list2).head = NULL; \
+ (list2).tail = NULL; \
+ } while (0)
+
+#define LWRES_LIST_ENQUEUE(list, elt, link) LWRES_LIST_APPEND(list, elt, link)
+#define LWRES_LIST_DEQUEUE(list, elt, link) LWRES_LIST_UNLINK(list, elt, link)
+
+#endif /* LWRES_LIST_H */
diff --git a/lib/lwres/include/lwres/lwbuffer.h b/lib/lwres/include/lwres/lwbuffer.h
new file mode 100644
index 0000000..e3cf343
--- /dev/null
+++ b/lib/lwres/include/lwres/lwbuffer.h
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2004-2007 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: lwbuffer.h,v 1.22 2007/06/19 23:47:23 tbox Exp $ */
+
+
+/*! \file lwres/lwbuffer.h
+ *
+ * A buffer is a region of memory, together with a set of related subregions.
+ * Buffers are used for parsing and I/O operations.
+ *
+ * The 'used region' and the 'available' region are disjoint, and their
+ * union is the buffer's region. The used region extends from the beginning
+ * of the buffer region to the last used byte. The available region
+ * extends from one byte greater than the last used byte to the end of the
+ * buffer's region. The size of the used region can be changed using various
+ * buffer commands. Initially, the used region is empty.
+ *
+ * The used region is further subdivided into two disjoint regions: the
+ * 'consumed region' and the 'remaining region'. The union of these two
+ * regions is the used region. The consumed region extends from the beginning
+ * of the used region to the byte before the 'current' offset (if any). The
+ * 'remaining' region the current pointer to the end of the used
+ * region. The size of the consumed region can be changed using various
+ * buffer commands. Initially, the consumed region is empty.
+ *
+ * The 'active region' is an (optional) subregion of the remaining region.
+ * It extends from the current offset to an offset in the remaining region
+ * that is selected with lwres_buffer_setactive(). Initially, the active
+ * region is empty. If the current offset advances beyond the chosen offset,
+ * the active region will also be empty.
+ *
+ * \verbatim
+ * /----- used region -----\/-- available --\
+ * +----------------------------------------+
+ * | consumed | remaining | |
+ * +----------------------------------------+
+ * a b c d e
+ *
+ * a == base of buffer.
+ * b == current pointer. Can be anywhere between a and d.
+ * c == active pointer. Meaningful between b and d.
+ * d == used pointer.
+ * e == length of buffer.
+ *
+ * a-e == entire (length) of buffer.
+ * a-d == used region.
+ * a-b == consumed region.
+ * b-d == remaining region.
+ * b-c == optional active region.
+ * \endverbatim
+ *
+ * The following invariants are maintained by all routines:
+ *
+ *\verbatim
+ * length > 0
+ *
+ * base is a valid pointer to length bytes of memory
+ *
+ * 0 <= used <= length
+ *
+ * 0 <= current <= used
+ *
+ * 0 <= active <= used
+ * (although active < current implies empty active region)
+ *\endverbatim
+ *
+ * \li MP:
+ * Buffers have no synchronization. Clients must ensure exclusive
+ * access.
+ *
+ * \li Reliability:
+ * No anticipated impact.
+ *
+ * \li Resources:
+ * Memory: 1 pointer + 6 unsigned integers per buffer.
+ *
+ * \li Security:
+ * No anticipated impact.
+ *
+ * \li Standards:
+ * None.
+ */
+
+#ifndef LWRES_LWBUFFER_H
+#define LWRES_LWBUFFER_H 1
+
+/***
+ *** Imports
+ ***/
+
+#include <lwres/lang.h>
+#include <lwres/int.h>
+
+LWRES_LANG_BEGINDECLS
+
+/***
+ *** Magic numbers
+ ***/
+#define LWRES_BUFFER_MAGIC 0x4275663fU /* Buf?. */
+
+#define LWRES_BUFFER_VALID(b) ((b) != NULL && \
+ (b)->magic == LWRES_BUFFER_MAGIC)
+
+/*!
+ * The following macros MUST be used only on valid buffers. It is the
+ * caller's responsibility to ensure this by using the LWRES_BUFFER_VALID
+ * check above, or by calling another lwres_buffer_*() function (rather than
+ * another macro.)
+ */
+
+/*!
+ * Get the length of the used region of buffer "b"
+ */
+#define LWRES_BUFFER_USEDCOUNT(b) ((b)->used)
+
+/*!
+ * Get the length of the available region of buffer "b"
+ */
+#define LWRES_BUFFER_AVAILABLECOUNT(b) ((b)->length - (b)->used)
+
+#define LWRES_BUFFER_REMAINING(b) ((b)->used - (b)->current)
+
+/*!
+ * Note that the buffer structure is public. This is principally so buffer
+ * operations can be implemented using macros. Applications are strongly
+ * discouraged from directly manipulating the structure.
+ */
+
+typedef struct lwres_buffer lwres_buffer_t;
+/*!
+ * Buffer data structure
+ */
+struct lwres_buffer {
+ unsigned int magic;
+ unsigned char *base;
+ /* The following integers are byte offsets from 'base'. */
+ unsigned int length;
+ unsigned int used;
+ unsigned int current;
+ unsigned int active;
+};
+
+/***
+ *** Functions
+ ***/
+
+void
+lwres_buffer_init(lwres_buffer_t *b, void *base, unsigned int length);
+/**<
+ * Make 'b' refer to the 'length'-byte region starting at base.
+ *
+ * Requires:
+ *
+ * 'length' > 0
+ *
+ * 'base' is a pointer to a sequence of 'length' bytes.
+ *
+ */
+
+void
+lwres_buffer_invalidate(lwres_buffer_t *b);
+/**<
+ * Make 'b' an invalid buffer.
+ *
+ * Requires:
+ * 'b' is a valid buffer.
+ *
+ * Ensures:
+ * If assertion checking is enabled, future attempts to use 'b' without
+ * calling lwres_buffer_init() on it will cause an assertion failure.
+ */
+
+void
+lwres_buffer_add(lwres_buffer_t *b, unsigned int n);
+/**<
+ * Increase the 'used' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ * 'b' is a valid buffer
+ *
+ * used + n <= length
+ *
+ */
+
+void
+lwres_buffer_subtract(lwres_buffer_t *b, unsigned int n);
+/**<
+ * Decrease the 'used' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ * 'b' is a valid buffer
+ *
+ * used >= n
+ *
+ */
+
+void
+lwres_buffer_clear(lwres_buffer_t *b);
+/**<
+ * Make the used region empty.
+ *
+ * Requires:
+ *
+ * 'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ * used = 0
+ *
+ */
+
+
+void
+lwres_buffer_first(lwres_buffer_t *b);
+/**<
+ * Make the consumed region empty.
+ *
+ * Requires:
+ *
+ * 'b' is a valid buffer
+ *
+ * Ensures:
+ *
+ * current == 0
+ *
+ */
+
+void
+lwres_buffer_forward(lwres_buffer_t *b, unsigned int n);
+/**<
+ * Increase the 'consumed' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ * 'b' is a valid buffer
+ *
+ * current + n <= used
+ *
+ */
+
+void
+lwres_buffer_back(lwres_buffer_t *b, unsigned int n);
+/**<
+ * Decrease the 'consumed' region of 'b' by 'n' bytes.
+ *
+ * Requires:
+ *
+ * 'b' is a valid buffer
+ *
+ * n <= current
+ *
+ */
+
+lwres_uint8_t
+lwres_buffer_getuint8(lwres_buffer_t *b);
+/**<
+ * Read an unsigned 8-bit integer from 'b' and return it.
+ *
+ * Requires:
+ *
+ * 'b' is a valid buffer.
+ *
+ * The length of the available region of 'b' is at least 1.
+ *
+ * Ensures:
+ *
+ * The current pointer in 'b' is advanced by 1.
+ *
+ * Returns:
+ *
+ * A 8-bit unsigned integer.
+ */
+
+void
+lwres_buffer_putuint8(lwres_buffer_t *b, lwres_uint8_t val);
+/**<
+ * Store an unsigned 8-bit integer from 'val' into 'b'.
+ *
+ * Requires:
+ * 'b' is a valid buffer.
+ *
+ * The length of the unused region of 'b' is at least 1.
+ *
+ * Ensures:
+ * The used pointer in 'b' is advanced by 1.
+ */
+
+lwres_uint16_t
+lwres_buffer_getuint16(lwres_buffer_t *b);
+/**<
+ * Read an unsigned 16-bit integer in network byte order from 'b', convert
+ * it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ * 'b' is a valid buffer.
+ *
+ * The length of the available region of 'b' is at least 2.
+ *
+ * Ensures:
+ *
+ * The current pointer in 'b' is advanced by 2.
+ *
+ * Returns:
+ *
+ * A 16-bit unsigned integer.
+ */
+
+void
+lwres_buffer_putuint16(lwres_buffer_t *b, lwres_uint16_t val);
+/**<
+ * Store an unsigned 16-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ * 'b' is a valid buffer.
+ *
+ * The length of the unused region of 'b' is at least 2.
+ *
+ * Ensures:
+ * The used pointer in 'b' is advanced by 2.
+ */
+
+lwres_uint32_t
+lwres_buffer_getuint32(lwres_buffer_t *b);
+/**<
+ * Read an unsigned 32-bit integer in network byte order from 'b', convert
+ * it to host byte order, and return it.
+ *
+ * Requires:
+ *
+ * 'b' is a valid buffer.
+ *
+ * The length of the available region of 'b' is at least 2.
+ *
+ * Ensures:
+ *
+ * The current pointer in 'b' is advanced by 2.
+ *
+ * Returns:
+ *
+ * A 32-bit unsigned integer.
+ */
+
+void
+lwres_buffer_putuint32(lwres_buffer_t *b, lwres_uint32_t val);
+/**<
+ * Store an unsigned 32-bit integer in host byte order from 'val'
+ * into 'b' in network byte order.
+ *
+ * Requires:
+ * 'b' is a valid buffer.
+ *
+ * The length of the unused region of 'b' is at least 4.
+ *
+ * Ensures:
+ * The used pointer in 'b' is advanced by 4.
+ */
+
+void
+lwres_buffer_putmem(lwres_buffer_t *b, const unsigned char *base,
+ unsigned int length);
+/**<
+ * Copy 'length' bytes of memory at 'base' into 'b'.
+ *
+ * Requires:
+ * 'b' is a valid buffer.
+ *
+ * 'base' points to 'length' bytes of valid memory.
+ *
+ */
+
+void
+lwres_buffer_getmem(lwres_buffer_t *b, unsigned char *base,
+ unsigned int length);
+/**<
+ * Copy 'length' bytes of memory from 'b' into 'base'.
+ *
+ * Requires:
+ * 'b' is a valid buffer.
+ *
+ * 'base' points to at least 'length' bytes of valid memory.
+ *
+ * 'b' have at least 'length' bytes remaining.
+ */
+
+LWRES_LANG_ENDDECLS
+
+#endif /* LWRES_LWBUFFER_H */
diff --git a/lib/lwres/include/lwres/lwpacket.h b/lib/lwres/include/lwres/lwpacket.h
new file mode 100644
index 0000000..96f8e54
--- /dev/null
+++ b/lib/lwres/include/lwres/lwpacket.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: lwpacket.h,v 1.24 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_LWPACKET_H
+#define LWRES_LWPACKET_H 1
+
+#include <lwres/lang.h>
+#include <lwres/lwbuffer.h>
+#include <lwres/result.h>
+
+/*% lwres_lwpacket_t */
+typedef struct lwres_lwpacket lwres_lwpacket_t;
+
+/*% lwres_lwpacket structure */
+struct lwres_lwpacket {
+ /*! The overall packet length, including the
+ * entire packet header.
+ * This field is filled in by the
+ * \link lwres_gabn.c lwres_gabn_*()\endlink
+ * and \link lwres_gnba.c lwres_gnba_*()\endlink calls.
+ */
+ lwres_uint32_t length;
+ /*! Specifies the header format. Currently,
+ * there is only one format, #LWRES_LWPACKETVERSION_0.
+ * This field is filled in by the
+ * \link lwres_gabn.c lwres_gabn_*()\endlink
+ * and \link lwres_gnba.c lwres_gnba_*()\endlink calls.
+ */
+ lwres_uint16_t version;
+ /*! Specifies library-defined flags for this packet, such as
+ * whether the packet is a request or a reply. None of
+ * these are definable by the caller, but library-defined values
+ * can be set by the caller. For example, one bit in this field
+ * indicates if the packet is a request or a response.
+ * This field is filled in by
+ * the application wits the exception of the
+ * #LWRES_LWPACKETFLAG_RESPONSE bit, which is set by the library
+ * in the
+ * \link lwres_gabn.c lwres_gabn_*()\endlink
+ * and \link lwres_gnba.c lwres_gnba_*()\endlink calls.
+ */
+ lwres_uint16_t pktflags;
+ /*! Set by the requestor and is returned in all replies.
+ * If two packets from the same source have the same serial
+ * number and are from the same source, they are assumed to
+ * be duplicates and the latter ones may be dropped.
+ * (The library does not do this by default on replies, but
+ * does so on requests.)
+ */
+ lwres_uint32_t serial;
+ /*! Opcodes between 0x04000000 and 0xffffffff
+ * are application defined. Opcodes between
+ * 0x00000000 and 0x03ffffff are
+ * reserved for library use.
+ * This field is filled in by the
+ * \link lwres_gabn.c lwres_gabn_*()\endlink
+ * and \link lwres_gnba.c lwres_gnba_*()\endlink calls.
+ */
+ lwres_uint32_t opcode;
+ /*! Only valid for results.
+ * Results between 0x04000000 and 0xffffffff are application
+ * defined.
+ * Results between 0x00000000 and 0x03ffffff are reserved for
+ * library use.
+ * (This is the same reserved range defined in <isc/resultclass.h>,
+ * so it
+ * would be trivial to map ISC_R_* result codes into packet result
+ * codes when appropriate.)
+ * This field is filled in by the
+ * \link lwres_gabn.c lwres_gabn_*()\endlink
+ * and \link lwres_gnba.c lwres_gnba_*()\endlink calls.
+ */
+ lwres_uint32_t result;
+ /*! Set to the maximum buffer size that the receiver can
+ * handle on requests, and the size of the buffer needed to
+ * satisfy a request
+ * when the buffer is too large for replies.
+ * This field is supplied by the application.
+ */
+ lwres_uint32_t recvlength;
+ /*! The packet level auth type used.
+ * Authtypes between 0x1000 and 0xffff are application defined.
+ * Authtypes
+ * between 0x0000 and 0x0fff are reserved for library use.
+ * This is currently
+ * unused and MUST be set to zero.
+ */
+ lwres_uint16_t authtype;
+ /*! The length of the authentication data.
+ * See the specific
+ * authtypes for more information on what is contained
+ * in this field. This is currently unused, and
+ * MUST be set to zero.
+ */
+ lwres_uint16_t authlength;
+};
+
+#define LWRES_LWPACKET_LENGTH (4 * 5 + 2 * 4) /*%< Overall length. */
+
+#define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /*%< If set, pkt is a response. */
+
+
+#define LWRES_LWPACKETVERSION_0 0 /*%< Header format. */
+
+/*! \file lwres/lwpacket.h
+ *
+ *
+ * The remainder of the packet consists of two regions, one described by
+ * "authlen" and one of "length - authlen - sizeof(lwres_lwpacket_t)".
+ *
+ * That is:
+ *
+ * \code
+ * pkt header
+ * authlen bytes of auth information
+ * data bytes
+ * \endcode
+ *
+ * Currently defined opcodes:
+ *
+ *\li #LWRES_OPCODE_NOOP. Success is always returned, with the packet contents echoed.
+ *
+ *\li #LWRES_OPCODE_GETADDRSBYNAME. Return all known addresses for a given name.
+ * This may return NIS or /etc/hosts info as well as DNS
+ * information. Flags will be provided to indicate ip4/ip6
+ * addresses are desired.
+ *
+ *\li #LWRES_OPCODE_GETNAMEBYADDR. Return the hostname for the given address. Once
+ * again, it will return data from multiple sources.
+ */
+
+LWRES_LANG_BEGINDECLS
+
+/* XXXMLG document */
+lwres_result_t
+lwres_lwpacket_renderheader(lwres_buffer_t *b, lwres_lwpacket_t *pkt);
+
+lwres_result_t
+lwres_lwpacket_parseheader(lwres_buffer_t *b, lwres_lwpacket_t *pkt);
+
+LWRES_LANG_ENDDECLS
+
+#endif /* LWRES_LWPACKET_H */
diff --git a/lib/lwres/include/lwres/lwres.h b/lib/lwres/include/lwres/lwres.h
new file mode 100644
index 0000000..6912448
--- /dev/null
+++ b/lib/lwres/include/lwres/lwres.h
@@ -0,0 +1,579 @@
+/*
+ * Copyright (C) 2004-2007 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: lwres.h,v 1.57 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_LWRES_H
+#define LWRES_LWRES_H 1
+
+#include <stdio.h>
+
+#include <lwres/context.h>
+#include <lwres/lang.h>
+#include <lwres/list.h>
+#include <lwres/lwpacket.h>
+#include <lwres/platform.h>
+
+/*! \file lwres/lwres.h */
+
+/*!
+ * Design notes:
+ *
+ * Each opcode has two structures and three functions which operate on each
+ * structure. For example, using the "no operation/ping" opcode as an
+ * example:
+ *
+ * <ul><li>lwres_nooprequest_t:
+ *
+ * lwres_nooprequest_render() takes a lwres_nooprequest_t and
+ * and renders it into wire format, storing the allocated
+ * buffer information in a passed-in buffer. When this buffer
+ * is no longer needed, it must be freed by
+ * lwres_context_freemem(). All other memory used by the
+ * caller must be freed manually, including the
+ * lwres_nooprequest_t passed in.<br /><br />
+ *
+ * lwres_nooprequest_parse() takes a wire format message and
+ * breaks it out into a lwres_nooprequest_t. The structure
+ * must be freed via lwres_nooprequest_free() when it is no longer
+ * needed.<br /><br />
+ *
+ * lwres_nooprequest_free() releases into the lwres_context_t
+ * any space allocated during parsing.</li>
+ *
+ * <li>lwres_noopresponse_t:
+ *
+ * The functions used are similar to the three used for
+ * requests, just with different names.</li></ul>
+ *
+ * Typically, the client will use request_render, response_parse, and
+ * response_free, while the daemon will use request_parse, response_render,
+ * and request_free.
+ *
+ * The basic flow of a typical client is:
+ *
+ * \li fill in a request_t, and call the render function.
+ *
+ * \li Transmit the buffer returned to the daemon.
+ *
+ * \li Wait for a response.
+ *
+ * \li When a response is received, parse it into a response_t.
+ *
+ * \li free the request buffer using lwres_context_freemem().
+ *
+ * \li free the response structure and its associated buffer using
+ * response_free().
+ */
+
+#define LWRES_UDP_PORT 921 /*%< UDP Port Number */
+#define LWRES_RECVLENGTH 16384 /*%< Maximum Packet Length */
+#define LWRES_ADDR_MAXLEN 16 /*%< changing this breaks ABI */
+#define LWRES_RESOLV_CONF "/etc/resolv.conf" /*%< Location of resolv.conf */
+
+/*% DNSSEC is not required (input). Only relevant to rrset queries. */
+#define LWRES_FLAG_TRUSTNOTREQUIRED 0x00000001U
+/*% The data was crypto-verified with DNSSEC (output). */
+#define LWRES_FLAG_SECUREDATA 0x00000002U
+
+/*% no-op */
+#define LWRES_OPCODE_NOOP 0x00000000U
+
+/*% lwres_nooprequest_t */
+typedef struct {
+ /* public */
+ lwres_uint16_t datalength;
+ unsigned char *data;
+} lwres_nooprequest_t;
+
+/*% lwres_noopresponse_t */
+typedef struct {
+ /* public */
+ lwres_uint16_t datalength;
+ unsigned char *data;
+} lwres_noopresponse_t;
+
+/*% get addresses by name */
+#define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
+
+/*% lwres_addr_t */
+typedef struct lwres_addr lwres_addr_t;
+
+/*% LWRES_LIST */
+typedef LWRES_LIST(lwres_addr_t) lwres_addrlist_t;
+
+/*% lwres_addr */
+struct lwres_addr {
+ lwres_uint32_t family;
+ lwres_uint16_t length;
+ unsigned char address[LWRES_ADDR_MAXLEN];
+ LWRES_LINK(lwres_addr_t) link;
+};
+
+/*% lwres_gabnrequest_t */
+typedef struct {
+ /* public */
+ lwres_uint32_t flags;
+ lwres_uint32_t addrtypes;
+ lwres_uint16_t namelen;
+ char *name;
+} lwres_gabnrequest_t;
+
+/*% lwres_gabnresponse_t */
+typedef struct {
+ /* public */
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ lwres_uint16_t naddrs;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ lwres_addrlist_t addrs;
+ /*! if base != NULL, it will be freed when this structure is freed. */
+ void *base;
+ size_t baselen;
+} lwres_gabnresponse_t;
+
+/*% get name by address */
+#define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
+
+/*% lwres_gnbarequest_t */
+typedef struct {
+ /* public */
+ lwres_uint32_t flags;
+ lwres_addr_t addr;
+} lwres_gnbarequest_t;
+
+/*% lwres_gnbaresponse_t */
+typedef struct {
+ /* public */
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ /*! if base != NULL, it will be freed when this structure is freed. */
+ void *base;
+ size_t baselen;
+} lwres_gnbaresponse_t;
+
+/*% get rdata by name */
+#define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
+
+/*% lwres_grbnrequest_t */
+typedef struct {
+ /* public */
+ lwres_uint32_t flags;
+ lwres_uint16_t rdclass;
+ lwres_uint16_t rdtype;
+ lwres_uint16_t namelen;
+ char *name;
+} lwres_grbnrequest_t;
+
+/*% lwres_grbnresponse_t */
+typedef struct {
+ /* public */
+ lwres_uint32_t flags;
+ lwres_uint16_t rdclass;
+ lwres_uint16_t rdtype;
+ lwres_uint32_t ttl;
+ lwres_uint16_t nrdatas;
+ lwres_uint16_t nsigs;
+ char *realname;
+ lwres_uint16_t realnamelen;
+ unsigned char **rdatas;
+ lwres_uint16_t *rdatalen;
+ unsigned char **sigs;
+ lwres_uint16_t *siglen;
+ /*% if base != NULL, it will be freed when this structure is freed. */
+ void *base;
+ size_t baselen;
+} lwres_grbnresponse_t;
+
+/*% Used by lwres_getrrsetbyname() */
+#define LWRDATA_VALIDATED 0x00000001
+
+/*!
+ * resolv.conf data
+ */
+
+#define LWRES_CONFMAXNAMESERVERS 3 /*%< max 3 "nameserver" entries */
+#define LWRES_CONFMAXLWSERVERS 1 /*%< max 1 "lwserver" entry */
+#define LWRES_CONFMAXSEARCH 8 /*%< max 8 domains in "search" entry */
+#define LWRES_CONFMAXLINELEN 256 /*%< max size of a line */
+#define LWRES_CONFMAXSORTLIST 10 /*%< max 10 */
+
+/*% lwres_conf_t */
+typedef struct {
+ lwres_context_t *lwctx;
+ lwres_addr_t nameservers[LWRES_CONFMAXNAMESERVERS];
+ lwres_uint8_t nsnext; /*%< index for next free slot */
+
+ lwres_addr_t lwservers[LWRES_CONFMAXLWSERVERS];
+ lwres_uint8_t lwnext; /*%< index for next free slot */
+
+ char *domainname;
+
+ char *search[LWRES_CONFMAXSEARCH];
+ lwres_uint8_t searchnxt; /*%< index for next free slot */
+
+ struct {
+ lwres_addr_t addr;
+ /*% mask has a non-zero 'family' and 'length' if set */
+ lwres_addr_t mask;
+ } sortlist[LWRES_CONFMAXSORTLIST];
+ lwres_uint8_t sortlistnxt;
+
+ lwres_uint8_t resdebug; /*%< non-zero if 'options debug' set */
+ lwres_uint8_t ndots; /*%< set to n in 'options ndots:n' */
+ lwres_uint8_t no_tld_query; /*%< non-zero if 'options no_tld_query' */
+} lwres_conf_t;
+
+#define LWRES_ADDRTYPE_V4 0x00000001U /*%< ipv4 */
+#define LWRES_ADDRTYPE_V6 0x00000002U /*%< ipv6 */
+
+#define LWRES_MAX_ALIASES 16 /*%< max # of aliases */
+#define LWRES_MAX_ADDRS 64 /*%< max # of addrs */
+
+LWRES_LANG_BEGINDECLS
+
+/*% This is in host byte order. */
+LIBLWRES_EXTERNAL_DATA extern lwres_uint16_t lwres_udp_port;
+
+LIBLWRES_EXTERNAL_DATA extern const char *lwres_resolv_conf;
+
+lwres_result_t
+lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b);
+
+lwres_result_t
+lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b);
+
+lwres_result_t
+lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_gabnrequest_t **structp);
+
+lwres_result_t
+lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt,
+ lwres_gabnresponse_t **structp);
+
+void
+lwres_gabnrequest_free(lwres_context_t *ctx, lwres_gabnrequest_t **structp);
+/**<
+ * Frees any dynamically allocated memory for this structure.
+ *
+ * Requires:
+ *
+ * ctx != NULL, and be a context returned via lwres_context_create().
+ *
+ * structp != NULL && *structp != NULL.
+ *
+ * Ensures:
+ *
+ * *structp == NULL.
+ *
+ * All memory allocated by this structure will be returned to the
+ * system via the context's free function.
+ */
+
+void
+lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp);
+/**<
+ * Frees any dynamically allocated memory for this structure.
+ *
+ * Requires:
+ *
+ * ctx != NULL, and be a context returned via lwres_context_create().
+ *
+ * structp != NULL && *structp != NULL.
+ *
+ * Ensures:
+ *
+ * *structp == NULL.
+ *
+ * All memory allocated by this structure will be returned to the
+ * system via the context's free function.
+ */
+
+
+lwres_result_t
+lwres_gnbarequest_render(lwres_context_t *ctx, lwres_gnbarequest_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b);
+
+lwres_result_t
+lwres_gnbaresponse_render(lwres_context_t *ctx, lwres_gnbaresponse_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b);
+
+lwres_result_t
+lwres_gnbarequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_gnbarequest_t **structp);
+
+lwres_result_t
+lwres_gnbaresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt,
+ lwres_gnbaresponse_t **structp);
+
+void
+lwres_gnbarequest_free(lwres_context_t *ctx, lwres_gnbarequest_t **structp);
+/**<
+ * Frees any dynamically allocated memory for this structure.
+ *
+ * Requires:
+ *
+ * ctx != NULL, and be a context returned via lwres_context_create().
+ *
+ * structp != NULL && *structp != NULL.
+ *
+ * Ensures:
+ *
+ * *structp == NULL.
+ *
+ * All memory allocated by this structure will be returned to the
+ * system via the context's free function.
+ */
+
+void
+lwres_gnbaresponse_free(lwres_context_t *ctx, lwres_gnbaresponse_t **structp);
+/**<
+ * Frees any dynamically allocated memory for this structure.
+ *
+ * Requires:
+ *
+ * ctx != NULL, and be a context returned via lwres_context_create().
+ *
+ * structp != NULL && *structp != NULL.
+ *
+ * Ensures:
+ *
+ * *structp == NULL.
+ *
+ * All memory allocated by this structure will be returned to the
+ * system via the context's free function.
+ */
+
+lwres_result_t
+lwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b);
+
+lwres_result_t
+lwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b);
+
+lwres_result_t
+lwres_grbnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_grbnrequest_t **structp);
+
+lwres_result_t
+lwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt,
+ lwres_grbnresponse_t **structp);
+
+void
+lwres_grbnrequest_free(lwres_context_t *ctx, lwres_grbnrequest_t **structp);
+/**<
+ * Frees any dynamically allocated memory for this structure.
+ *
+ * Requires:
+ *
+ * ctx != NULL, and be a context returned via lwres_context_create().
+ *
+ * structp != NULL && *structp != NULL.
+ *
+ * Ensures:
+ *
+ * *structp == NULL.
+ *
+ * All memory allocated by this structure will be returned to the
+ * system via the context's free function.
+ */
+
+void
+lwres_grbnresponse_free(lwres_context_t *ctx, lwres_grbnresponse_t **structp);
+/**<
+ * Frees any dynamically allocated memory for this structure.
+ *
+ * Requires:
+ *
+ * ctx != NULL, and be a context returned via lwres_context_create().
+ *
+ * structp != NULL && *structp != NULL.
+ *
+ * Ensures:
+ *
+ * *structp == NULL.
+ *
+ * All memory allocated by this structure will be returned to the
+ * system via the context's free function.
+ */
+
+lwres_result_t
+lwres_nooprequest_render(lwres_context_t *ctx, lwres_nooprequest_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b);
+/**<
+ * Allocate space and render into wire format a noop request packet.
+ *
+ * Requires:
+ *
+ * ctx != NULL, and be a context returned via lwres_context_create().
+ *
+ * b != NULL, and points to a lwres_buffer_t. The contents of the
+ * buffer structure will be initialized to contain the wire-format
+ * noop request packet.
+ *
+ * Caller needs to fill in parts of "pkt" before calling:
+ * serial, maxrecv, result.
+ *
+ * Returns:
+ *
+ * Returns 0 on success, non-zero on failure.
+ *
+ * On successful return, *b will contain data about the wire-format
+ * packet. It can be transmitted in any way, including lwres_sendblock().
+ */
+
+lwres_result_t
+lwres_noopresponse_render(lwres_context_t *ctx, lwres_noopresponse_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b);
+
+lwres_result_t
+lwres_nooprequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_nooprequest_t **structp);
+/**<
+ * Parse a noop request. Note that to get here, the lwpacket must have
+ * already been parsed and removed by the caller, otherwise it would be
+ * pretty hard for it to know this is the right function to call.
+ *
+ * The function verifies bits of the header, but does not modify it.
+ */
+
+lwres_result_t
+lwres_noopresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt,
+ lwres_noopresponse_t **structp);
+
+void
+lwres_nooprequest_free(lwres_context_t *ctx, lwres_nooprequest_t **structp);
+
+void
+lwres_noopresponse_free(lwres_context_t *ctx, lwres_noopresponse_t **structp);
+
+/**<
+ * Frees any dynamically allocated memory for this structure.
+ *
+ * Requires:
+ *
+ * ctx != NULL, and be a context returned via lwres_context_create().
+ *
+ * structp != NULL && *structp != NULL.
+ *
+ * Ensures:
+ *
+ * *structp == NULL.
+ *
+ * All memory allocated by this structure will be returned to the
+ * system via the context's free function.
+ */
+
+lwres_result_t
+lwres_conf_parse(lwres_context_t *ctx, const char *filename);
+/**<
+ * parses a resolv.conf-format file and stores the results in the structure
+ * pointed to by *ctx.
+ *
+ * Requires:
+ * ctx != NULL
+ * filename != NULL && strlen(filename) > 0
+ *
+ * Returns:
+ * LWRES_R_SUCCESS on a successful parse.
+ * Anything else on error, although the structure may be partially filled
+ * in.
+ */
+
+lwres_result_t
+lwres_conf_print(lwres_context_t *ctx, FILE *fp);
+/**<
+ * Prints a resolv.conf-format of confdata output to fp.
+ *
+ * Requires:
+ * ctx != NULL
+ */
+
+void
+lwres_conf_init(lwres_context_t *ctx);
+/**<
+ * sets all internal fields to a default state. Used to initialize a new
+ * lwres_conf_t structure (not reset a used on).
+ *
+ * Requires:
+ * ctx != NULL
+ */
+
+void
+lwres_conf_clear(lwres_context_t *ctx);
+/**<
+ * frees all internally allocated memory in confdata. Uses the memory
+ * routines supplied by ctx.
+ *
+ * Requires:
+ * ctx != NULL
+ */
+
+lwres_conf_t *
+lwres_conf_get(lwres_context_t *ctx);
+/**<
+ * Be extremely cautions in modifying the contents of this structure; it
+ * needs an API to return the various bits of data, walk lists, etc.
+ *
+ * Requires:
+ * ctx != NULL
+ */
+
+/*
+ * Helper functions
+ */
+
+lwres_result_t
+lwres_data_parse(lwres_buffer_t *b, unsigned char **p, lwres_uint16_t *len);
+
+lwres_result_t
+lwres_string_parse(lwres_buffer_t *b, char **c, lwres_uint16_t *len);
+
+lwres_result_t
+lwres_addr_parse(lwres_buffer_t *b, lwres_addr_t *addr);
+
+lwres_result_t
+lwres_getaddrsbyname(lwres_context_t *ctx, const char *name,
+ lwres_uint32_t addrtypes, lwres_gabnresponse_t **structp);
+
+lwres_result_t
+lwres_getnamebyaddr(lwres_context_t *ctx, lwres_uint32_t addrtype,
+ lwres_uint16_t addrlen, const unsigned char *addr,
+ lwres_gnbaresponse_t **structp);
+
+lwres_result_t
+lwres_getrdatabyname(lwres_context_t *ctx, const char *name,
+ lwres_uint16_t rdclass, lwres_uint16_t rdtype,
+ lwres_uint32_t flags, lwres_grbnresponse_t **structp);
+
+LWRES_LANG_ENDDECLS
+
+#endif /* LWRES_LWRES_H */
diff --git a/lib/lwres/include/lwres/netdb.h.in b/lib/lwres/include/lwres/netdb.h.in
new file mode 100644
index 0000000..5dc4bf7
--- /dev/null
+++ b/lib/lwres/include/lwres/netdb.h.in
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: netdb.h.in,v 1.39 2007/06/19 23:47:23 tbox Exp $ */
+
+/*! \file */
+
+#ifndef LWRES_NETDB_H
+#define LWRES_NETDB_H 1
+
+#include <stddef.h> /* Required on FreeBSD (and others?) for size_t. */
+#include <netdb.h> /* Contractual provision. */
+
+#include <lwres/lang.h>
+
+/*
+ * Define if <netdb.h> does not declare struct addrinfo.
+ */
+@ISC_LWRES_NEEDADDRINFO@
+
+#ifdef ISC_LWRES_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 <netdb.h> 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()
+ */
+
+#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_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_MAX 14
+
+/*
+ * 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
+#define NI_NUMERICSCOPE 0x00000020 /*2553bis-00*/
+
+/*
+ * Define if <netdb.h> does not declare struct rrsetinfo.
+ */
+@ISC_LWRES_NEEDRRSETINFO@
+
+#ifdef ISC_LWRES_NEEDRRSETINFO
+/*
+ * Structures for getrrsetbyname()
+ */
+struct rdatainfo {
+ unsigned int rdi_length;
+ unsigned char *rdi_data;
+};
+
+struct rrsetinfo {
+ unsigned int rri_flags;
+ int rri_rdclass;
+ int rri_rdtype;
+ unsigned int rri_ttl;
+ unsigned int rri_nrdatas;
+ unsigned int rri_nsigs;
+ char *rri_name;
+ struct rdatainfo *rri_rdatas;
+ struct rdatainfo *rri_sigs;
+};
+
+/*
+ * Flags for getrrsetbyname()
+ */
+#define RRSET_VALIDATED 0x00000001
+ /* Set was dnssec validated */
+
+/*
+ * Return codes for getrrsetbyname()
+ */
+#define ERRSET_SUCCESS 0
+#define ERRSET_NOMEMORY 1
+#define ERRSET_FAIL 2
+#define ERRSET_INVAL 3
+#define ERRSET_NONAME 4
+#define ERRSET_NODATA 5
+#endif
+
+/*
+ * Define to map into lwres_ namespace.
+ */
+
+#define LWRES_NAMESPACE
+
+#ifdef LWRES_NAMESPACE
+
+/*
+ * Use our versions not the ones from the C library.
+ */
+
+#ifdef getnameinfo
+#undef getnameinfo
+#endif
+#define getnameinfo lwres_getnameinfo
+
+#ifdef getaddrinfo
+#undef getaddrinfo
+#endif
+#define getaddrinfo lwres_getaddrinfo
+
+#ifdef freeaddrinfo
+#undef freeaddrinfo
+#endif
+#define freeaddrinfo lwres_freeaddrinfo
+
+#ifdef gai_strerror
+#undef gai_strerror
+#endif
+#define gai_strerror lwres_gai_strerror
+
+#ifdef herror
+#undef herror
+#endif
+#define herror lwres_herror
+
+#ifdef hstrerror
+#undef hstrerror
+#endif
+#define hstrerror lwres_hstrerror
+
+#ifdef getipnodebyname
+#undef getipnodebyname
+#endif
+#define getipnodebyname lwres_getipnodebyname
+
+#ifdef getipnodebyaddr
+#undef getipnodebyaddr
+#endif
+#define getipnodebyaddr lwres_getipnodebyaddr
+
+#ifdef freehostent
+#undef freehostent
+#endif
+#define freehostent lwres_freehostent
+
+#ifdef gethostbyname
+#undef gethostbyname
+#endif
+#define gethostbyname lwres_gethostbyname
+
+#ifdef gethostbyname2
+#undef gethostbyname2
+#endif
+#define gethostbyname2 lwres_gethostbyname2
+
+#ifdef gethostbyaddr
+#undef gethostbyaddr
+#endif
+#define gethostbyaddr lwres_gethostbyaddr
+
+#ifdef gethostent
+#undef gethostent
+#endif
+#define gethostent lwres_gethostent
+
+#ifdef sethostent
+#undef sethostent
+#endif
+#define sethostent lwres_sethostent
+
+#ifdef endhostent
+#undef endhostent
+#endif
+#define endhostent lwres_endhostent
+
+/* #define sethostfile lwres_sethostfile */
+
+#ifdef gethostbyname_r
+#undef gethostbyname_r
+#endif
+#define gethostbyname_r lwres_gethostbyname_r
+
+#ifdef gethostbyaddr_r
+#undef gethostbyaddr_r
+#endif
+#define gethostbyaddr_r lwres_gethostbyaddr_r
+
+#ifdef gethostent_r
+#undef gethostent_r
+#endif
+#define gethostent_r lwres_gethostent_r
+
+#ifdef sethostent_r
+#undef sethostent_r
+#endif
+#define sethostent_r lwres_sethostent_r
+
+#ifdef endhostent_r
+#undef endhostent_r
+#endif
+#define endhostent_r lwres_endhostent_r
+
+#ifdef getrrsetbyname
+#undef getrrsetbyname
+#endif
+#define getrrsetbyname lwres_getrrsetbyname
+
+#ifdef freerrset
+#undef freerrset
+#endif
+#define freerrset lwres_freerrset
+
+#ifdef notyet
+#define getservbyname lwres_getservbyname
+#define getservbyport lwres_getservbyport
+#define getservent lwres_getservent
+#define setservent lwres_setservent
+#define endservent lwres_endservent
+
+#define getservbyname_r lwres_getservbyname_r
+#define getservbyport_r lwres_getservbyport_r
+#define getservent_r lwres_getservent_r
+#define setservent_r lwres_setservent_r
+#define endservent_r lwres_endservent_r
+
+#define getprotobyname lwres_getprotobyname
+#define getprotobynumber lwres_getprotobynumber
+#define getprotoent lwres_getprotoent
+#define setprotoent lwres_setprotoent
+#define endprotoent lwres_endprotoent
+
+#define getprotobyname_r lwres_getprotobyname_r
+#define getprotobynumber_r lwres_getprotobynumber_r
+#define getprotoent_r lwres_getprotoent_r
+#define setprotoent_r lwres_setprotoent_r
+#define endprotoent_r lwres_endprotoent_r
+
+#ifdef getnetbyname
+#undef getnetbyname
+#endif
+#define getnetbyname lwres_getnetbyname
+
+#ifdef getnetbyaddr
+#undef getnetbyaddr
+#endif
+#define getnetbyaddr lwres_getnetbyaddr
+
+#ifdef getnetent
+#undef getnetent
+#endif
+#define getnetent lwres_getnetent
+
+#ifdef setnetent
+#undef setnetent
+#endif
+#define setnetent lwres_setnetent
+
+#ifdef endnetent
+#undef endnetent
+#endif
+#define endnetent lwres_endnetent
+
+
+#ifdef getnetbyname_r
+#undef getnetbyname_r
+#endif
+#define getnetbyname_r lwres_getnetbyname_r
+
+#ifdef getnetbyaddr_r
+#undef getnetbyaddr_r
+#endif
+#define getnetbyaddr_r lwres_getnetbyaddr_r
+
+#ifdef getnetent_r
+#undef getnetent_r
+#endif
+#define getnetent_r lwres_getnetent_r
+
+#ifdef setnetent_r
+#undef setnetent_r
+#endif
+#define setnetent_r lwres_setnetent_r
+
+#ifdef endnetent_r
+#undef endnetent_r
+#endif
+#define endnetent_r lwres_endnetent_r
+#endif /* notyet */
+
+#ifdef h_errno
+#undef h_errno
+#endif
+#define h_errno lwres_h_errno
+
+#endif /* LWRES_NAMESPACE */
+
+LWRES_LANG_BEGINDECLS
+
+extern int lwres_h_errno;
+
+int lwres_getaddrinfo(const char *, const char *,
+ const struct addrinfo *, struct addrinfo **);
+int lwres_getnameinfo(const struct sockaddr *, size_t, char *,
+ size_t, char *, size_t, int);
+void lwres_freeaddrinfo(struct addrinfo *);
+char *lwres_gai_strerror(int);
+
+struct hostent *lwres_gethostbyaddr(const char *, int, int);
+struct hostent *lwres_gethostbyname(const char *);
+struct hostent *lwres_gethostbyname2(const char *, int);
+struct hostent *lwres_gethostent(void);
+struct hostent *lwres_getipnodebyname(const char *, int, int, int *);
+struct hostent *lwres_getipnodebyaddr(const void *, size_t, int, int *);
+void lwres_endhostent(void);
+void lwres_sethostent(int);
+/* void lwres_sethostfile(const char *); */
+void lwres_freehostent(struct hostent *);
+
+int lwres_getrrsetbyname(const char *, unsigned int, unsigned int,
+ unsigned int, struct rrsetinfo **);
+void lwres_freerrset(struct rrsetinfo *);
+
+#ifdef notyet
+struct netent *lwres_getnetbyaddr(unsigned long, int);
+struct netent *lwres_getnetbyname(const char *);
+struct netent *lwres_getnetent(void);
+void lwres_endnetent(void);
+void lwres_setnetent(int);
+
+struct protoent *lwres_getprotobyname(const char *);
+struct protoent *lwres_getprotobynumber(int);
+struct protoent *lwres_getprotoent(void);
+void lwres_endprotoent(void);
+void lwres_setprotoent(int);
+
+struct servent *lwres_getservbyname(const char *, const char *);
+struct servent *lwres_getservbyport(int, const char *);
+struct servent *lwres_getservent(void);
+void lwres_endservent(void);
+void lwres_setservent(int);
+#endif /* notyet */
+
+void lwres_herror(const char *);
+const char *lwres_hstrerror(int);
+
+
+struct hostent *lwres_gethostbyaddr_r(const char *, int, int, struct hostent *,
+ char *, int, int *);
+struct hostent *lwres_gethostbyname_r(const char *, struct hostent *,
+ char *, int, int *);
+struct hostent *lwres_gethostent_r(struct hostent *, char *, int, int *);
+void lwres_sethostent_r(int);
+void lwres_endhostent_r(void);
+
+#ifdef notyet
+struct netent *lwres_getnetbyname_r(const char *, struct netent *,
+ char *, int);
+struct netent *lwres_getnetbyaddr_r(long, int, struct netent *,
+ char *, int);
+struct netent *lwres_getnetent_r(struct netent *, char *, int);
+void lwres_setnetent_r(int);
+void lwres_endnetent_r(void);
+
+struct protoent *lwres_getprotobyname_r(const char *,
+ struct protoent *, char *, int);
+struct protoent *lwres_getprotobynumber_r(int,
+ struct protoent *, char *, int);
+struct protoent *lwres_getprotoent_r(struct protoent *, char *, int);
+void lwres_setprotoent_r(int);
+void lwres_endprotoent_r(void);
+
+struct servent *lwres_getservbyname_r(const char *name, const char *,
+ struct servent *, char *, int);
+struct servent *lwres_getservbyport_r(int port, const char *,
+ struct servent *, char *, int);
+struct servent *lwres_getservent_r(struct servent *, char *, int);
+void lwres_setservent_r(int);
+void lwres_endservent_r(void);
+#endif /* notyet */
+
+LWRES_LANG_ENDDECLS
+
+#ifdef notyet
+/* This is nec'y to make this include file properly replace the sun version. */
+#ifdef sun
+#ifdef __GNU_LIBRARY__
+#include <rpc/netdb.h> /* Required. */
+#else /* !__GNU_LIBRARY__ */
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ int r_number; /* rpc program number */
+};
+struct rpcent *lwres_getrpcbyname();
+struct rpcent *lwres_getrpcbynumber(),
+struct rpcent *lwres_getrpcent();
+#endif /* __GNU_LIBRARY__ */
+#endif /* sun */
+#endif /* notyet */
+
+/*
+ * Tell Emacs to use C mode on this file.
+ * Local variables:
+ * mode: c
+ * End:
+ */
+
+#endif /* LWRES_NETDB_H */
diff --git a/lib/lwres/include/lwres/platform.h.in b/lib/lwres/include/lwres/platform.h.in
new file mode 100644
index 0000000..bb4f6ee
--- /dev/null
+++ b/lib/lwres/include/lwres/platform.h.in
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: platform.h.in,v 1.21 2007/06/19 23:47:23 tbox Exp $ */
+
+/*! \file */
+
+#ifndef LWRES_PLATFORM_H
+#define LWRES_PLATFORM_H 1
+
+/*****
+ ***** Platform-dependent defines.
+ *****/
+
+/***
+ *** Network.
+ ***/
+
+/*
+ * Define if this system needs the <netinet/in6.h> header file for IPv6.
+ */
+@LWRES_PLATFORM_NEEDNETINETIN6H@
+
+/*
+ * Define if this system needs the <netinet6/in6.h> header file for IPv6.
+ */
+@LWRES_PLATFORM_NEEDNETINET6IN6H@
+
+/*
+ * If sockaddrs on this system have an sa_len field, LWRES_PLATFORM_HAVESALEN
+ * will be defined.
+ */
+@LWRES_PLATFORM_HAVESALEN@
+
+/*
+ * If this system has the IPv6 structure definitions, LWRES_PLATFORM_HAVEIPV6
+ * will be defined.
+ */
+@LWRES_PLATFORM_HAVEIPV6@
+
+/*
+ * If this system is missing in6addr_any, LWRES_PLATFORM_NEEDIN6ADDRANY will
+ * be defined.
+ */
+@LWRES_PLATFORM_NEEDIN6ADDRANY@
+
+/*
+ * If this system is missing in6addr_loopback,
+ * LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK will be defined.
+ */
+@LWRES_PLATFORM_NEEDIN6ADDRLOOPBACK@
+
+/*
+ * If this system has in_addr6, rather than in6_addr,
+ * LWRES_PLATFORM_HAVEINADDR6 will be defined.
+ */
+@LWRES_PLATFORM_HAVEINADDR6@
+
+/*
+ * Defined if unistd.h does not cause fd_set to be delared.
+ */
+@LWRES_PLATFORM_NEEDSYSSELECTH@
+
+/*
+ * Used to control how extern data is linked; needed for Win32 platforms.
+ */
+@LWRES_PLATFORM_USEDECLSPEC@
+
+/*
+ * Defined this system needs vsnprintf() and snprintf().
+ */
+@LWRES_PLATFORM_NEEDVSNPRINTF@
+
+/*
+ * If this system need a modern sprintf() that returns (int) not (char*).
+ */
+@LWRES_PLATFORM_NEEDSPRINTF@
+
+/*
+ * The printf format string modifier to use with lwres_uint64_t values.
+ */
+@LWRES_PLATFORM_QUADFORMAT@
+
+/*! \brief
+ * Define if this system needs strtoul.
+ */
+@LWRES_PLATFORM_NEEDSTRTOUL@
+
+#ifndef LWRES_PLATFORM_USEDECLSPEC
+#define LIBLWRES_EXTERNAL_DATA
+#else
+#ifdef LIBLWRES_EXPORTS
+#define LIBLWRES_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBLWRES_EXTERNAL_DATA __declspec(dllimport)
+#endif
+#endif
+
+/*
+ * Tell Emacs to use C mode on this file.
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
+#endif /* LWRES_PLATFORM_H */
diff --git a/lib/lwres/include/lwres/result.h b/lib/lwres/include/lwres/result.h
new file mode 100644
index 0000000..cfcf166
--- /dev/null
+++ b/lib/lwres/include/lwres/result.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2004-2007 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: result.h,v 1.21 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_RESULT_H
+#define LWRES_RESULT_H 1
+
+/*! \file lwres/result.h */
+
+typedef unsigned int lwres_result_t;
+
+#define LWRES_R_SUCCESS 0
+#define LWRES_R_NOMEMORY 1
+#define LWRES_R_TIMEOUT 2
+#define LWRES_R_NOTFOUND 3
+#define LWRES_R_UNEXPECTEDEND 4 /* unexpected end of input */
+#define LWRES_R_FAILURE 5 /* generic failure */
+#define LWRES_R_IOERROR 6
+#define LWRES_R_NOTIMPLEMENTED 7
+#define LWRES_R_UNEXPECTED 8
+#define LWRES_R_TRAILINGDATA 9
+#define LWRES_R_INCOMPLETE 10
+#define LWRES_R_RETRY 11
+#define LWRES_R_TYPENOTFOUND 12
+#define LWRES_R_TOOLARGE 13
+
+#endif /* LWRES_RESULT_H */
diff --git a/lib/lwres/include/lwres/stdlib.h b/lib/lwres/include/lwres/stdlib.h
new file mode 100644
index 0000000..25a109e
--- /dev/null
+++ b/lib/lwres/include/lwres/stdlib.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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: stdlib.h,v 1.6 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_STDLIB_H
+#define LWRES_STDLIB_H 1
+
+/*! \file lwres/stdlib.h */
+
+#include <stdlib.h>
+
+#include <lwres/lang.h>
+#include <lwres/platform.h>
+
+#ifdef LWRES_PLATFORM_NEEDSTRTOUL
+#define strtoul lwres_strtoul
+#endif
+
+LWRES_LANG_BEGINDECLS
+
+unsigned long lwres_strtoul(const char *, char **, int);
+
+LWRES_LANG_ENDDECLS
+
+#endif
diff --git a/lib/lwres/include/lwres/version.h b/lib/lwres/include/lwres/version.h
new file mode 100644
index 0000000..9efc86d
--- /dev/null
+++ b/lib/lwres/include/lwres/version.h
@@ -0,0 +1,28 @@
+/*
+ * 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: version.h,v 1.9 2007/06/19 23:47:23 tbox Exp $ */
+
+/*! \file lwres/version.h */
+
+#include <lwres/platform.h>
+
+LIBLWRES_EXTERNAL_DATA extern const char lwres_version[];
+
+LIBLWRES_EXTERNAL_DATA extern const unsigned int lwres_libinterface;
+LIBLWRES_EXTERNAL_DATA extern const unsigned int lwres_librevision;
+LIBLWRES_EXTERNAL_DATA extern const unsigned int lwres_libage;
diff --git a/lib/lwres/lwbuffer.c b/lib/lwres/lwbuffer.c
new file mode 100644
index 0000000..49aaeb7
--- /dev/null
+++ b/lib/lwres/lwbuffer.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwbuffer.c,v 1.15 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+/**
+ * These functions provide bounds checked access to a region of memory
+ * where data is being read or written. They are based on, and similar
+ * to, the isc_buffer_ functions in the ISC library.
+ *
+ * A buffer is a region of memory, together with a set of related
+ * subregions. The used region and the available region are disjoint, and
+ * their union is the buffer's region. The used region extends from the
+ * beginning of the buffer region to the last used byte. The available
+ * region extends from one byte greater than the last used byte to the
+ * end of the buffer's region. The size of the used region can be changed
+ * using various buffer commands. Initially, the used region is empty.
+ *
+ * The used region is further subdivided into two disjoint regions: the
+ * consumed region and the remaining region. The union of these two
+ * regions is the used region. The consumed region extends from the
+ * beginning of the used region to the byte before the current offset (if
+ * any). The remaining region the current pointer to the end of the used
+ * region. The size of the consumed region can be changed using various
+ * buffer commands. Initially, the consumed region is empty.
+ *
+ * The active region is an (optional) subregion of the remaining region.
+ * It extends from the current offset to an offset in the remaining
+ * region. Initially, the active region is empty. If the current offset
+ * advances beyond the chosen offset, the active region will also be
+ * empty.
+ *
+ *
+ * \verbatim
+ * /------------entire length---------------\\
+ * /----- used region -----\\/-- available --\\
+ * +----------------------------------------+
+ * | consumed | remaining | |
+ * +----------------------------------------+
+ * a b c d e
+ *
+ * a == base of buffer.
+ * b == current pointer. Can be anywhere between a and d.
+ * c == active pointer. Meaningful between b and d.
+ * d == used pointer.
+ * e == length of buffer.
+ *
+ * a-e == entire length of buffer.
+ * a-d == used region.
+ * a-b == consumed region.
+ * b-d == remaining region.
+ * b-c == optional active region.
+ * \endverbatim
+ *
+ * lwres_buffer_init() initializes the lwres_buffer_t *b and assocates it
+ * with the memory region of size length bytes starting at location base.
+ *
+ * lwres_buffer_invalidate() marks the buffer *b as invalid. Invalidating
+ * a buffer after use is not required, but makes it possible to catch its
+ * possible accidental use.
+ *
+ * The functions lwres_buffer_add() and lwres_buffer_subtract()
+ * respectively increase and decrease the used space in buffer *b by n
+ * bytes. lwres_buffer_add() checks for buffer overflow and
+ * lwres_buffer_subtract() checks for underflow. These functions do not
+ * allocate or deallocate memory. They just change the value of used.
+ *
+ * A buffer is re-initialised by lwres_buffer_clear(). The function sets
+ * used , current and active to zero.
+ *
+ * lwres_buffer_first() makes the consumed region of buffer *p empty by
+ * setting current to zero (the start of the buffer).
+ *
+ * lwres_buffer_forward() increases the consumed region of buffer *b by n
+ * bytes, checking for overflow. Similarly, lwres_buffer_back() decreases
+ * buffer b's consumed region by n bytes and checks for underflow.
+ *
+ * lwres_buffer_getuint8() reads an unsigned 8-bit integer from *b and
+ * returns it. lwres_buffer_putuint8() writes the unsigned 8-bit integer
+ * val to buffer *b.
+ *
+ * lwres_buffer_getuint16() and lwres_buffer_getuint32() are identical to
+ * lwres_buffer_putuint8() except that they respectively read an unsigned
+ * 16-bit or 32-bit integer in network byte order from b. Similarly,
+ * lwres_buffer_putuint16() and lwres_buffer_putuint32() writes the
+ * unsigned 16-bit or 32-bit integer val to buffer b, in network byte
+ * order.
+ *
+ * Arbitrary amounts of data are read or written from a lightweight
+ * resolver buffer with lwres_buffer_getmem() and lwres_buffer_putmem()
+ * respectively. lwres_buffer_putmem() copies length bytes of memory at
+ * base to b. Conversely, lwres_buffer_getmem() copies length bytes of
+ * memory from b to base.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <lwres/lwbuffer.h>
+
+#include "assert_p.h"
+
+void
+lwres_buffer_init(lwres_buffer_t *b, void *base, unsigned int length)
+{
+ /*
+ * Make 'b' refer to the 'length'-byte region starting at base.
+ */
+
+ REQUIRE(b != NULL);
+
+ b->magic = LWRES_BUFFER_MAGIC;
+ b->base = base;
+ b->length = length;
+ b->used = 0;
+ b->current = 0;
+ b->active = 0;
+}
+
+/* Make 'b' an invalid buffer. */
+void
+lwres_buffer_invalidate(lwres_buffer_t *b)
+{
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+
+ b->magic = 0;
+ b->base = NULL;
+ b->length = 0;
+ b->used = 0;
+ b->current = 0;
+ b->active = 0;
+}
+
+/* Increase the 'used' region of 'b' by 'n' bytes. */
+void
+lwres_buffer_add(lwres_buffer_t *b, unsigned int n)
+{
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->used + n <= b->length);
+
+ b->used += n;
+}
+
+/* Decrease the 'used' region of 'b' by 'n' bytes. */
+void
+lwres_buffer_subtract(lwres_buffer_t *b, unsigned int n)
+{
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->used >= n);
+
+ b->used -= n;
+ if (b->current > b->used)
+ b->current = b->used;
+ if (b->active > b->used)
+ b->active = b->used;
+}
+
+/* Make the used region empty. */
+void
+lwres_buffer_clear(lwres_buffer_t *b)
+{
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+
+ b->used = 0;
+ b->current = 0;
+ b->active = 0;
+}
+
+/* Make the consumed region empty. */
+void
+lwres_buffer_first(lwres_buffer_t *b)
+{
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+
+ b->current = 0;
+}
+
+/* Increase the 'consumed' region of 'b' by 'n' bytes. */
+void
+lwres_buffer_forward(lwres_buffer_t *b, unsigned int n)
+{
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->current + n <= b->used);
+
+ b->current += n;
+}
+
+/* Decrease the 'consumed' region of 'b' by 'n' bytes. */
+void
+lwres_buffer_back(lwres_buffer_t *b, unsigned int n)
+{
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(n <= b->current);
+
+ b->current -= n;
+}
+
+/* Read an unsigned 8-bit integer from 'b' and return it. */
+lwres_uint8_t
+lwres_buffer_getuint8(lwres_buffer_t *b)
+{
+ unsigned char *cp;
+ lwres_uint8_t result;
+
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->used - b->current >= 1);
+
+ cp = b->base;
+ cp += b->current;
+ b->current += 1;
+ result = ((unsigned int)(cp[0]));
+
+ return (result);
+}
+
+/* Put an unsigned 8-bit integer */
+void
+lwres_buffer_putuint8(lwres_buffer_t *b, lwres_uint8_t val)
+{
+ unsigned char *cp;
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->used + 1 <= b->length);
+
+ cp = b->base;
+ cp += b->used;
+ b->used += 1;
+ cp[0] = (val & 0x00ff);
+}
+
+/* Read an unsigned 16-bit integer in network byte order from 'b', convert it to host byte order, and return it. */
+lwres_uint16_t
+lwres_buffer_getuint16(lwres_buffer_t *b)
+{
+ unsigned char *cp;
+ lwres_uint16_t result;
+
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->used - b->current >= 2);
+
+ cp = b->base;
+ cp += b->current;
+ b->current += 2;
+ result = ((unsigned int)(cp[0])) << 8;
+ result |= ((unsigned int)(cp[1]));
+
+ return (result);
+}
+
+/* Put an unsigned 16-bit integer. */
+void
+lwres_buffer_putuint16(lwres_buffer_t *b, lwres_uint16_t val)
+{
+ unsigned char *cp;
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->used + 2 <= b->length);
+
+ cp = b->base;
+ cp += b->used;
+ b->used += 2;
+ cp[0] = (val & 0xff00) >> 8;
+ cp[1] = (val & 0x00ff);
+}
+
+/* Read an unsigned 32-bit integer in network byte order from 'b', convert it to host byte order, and return it. */
+lwres_uint32_t
+lwres_buffer_getuint32(lwres_buffer_t *b)
+{
+ unsigned char *cp;
+ lwres_uint32_t result;
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->used - b->current >= 4);
+
+ cp = b->base;
+ cp += b->current;
+ b->current += 4;
+ result = ((unsigned int)(cp[0])) << 24;
+ result |= ((unsigned int)(cp[1])) << 16;
+ result |= ((unsigned int)(cp[2])) << 8;
+ result |= ((unsigned int)(cp[3]));
+
+ return (result);
+}
+
+/* Put an unsigned 32-bit integer. */
+void
+lwres_buffer_putuint32(lwres_buffer_t *b, lwres_uint32_t val)
+{
+ unsigned char *cp;
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->used + 4 <= b->length);
+
+ cp = b->base;
+ cp += b->used;
+ b->used += 4;
+ cp[0] = (unsigned char)((val & 0xff000000) >> 24);
+ cp[1] = (unsigned char)((val & 0x00ff0000) >> 16);
+ cp[2] = (unsigned char)((val & 0x0000ff00) >> 8);
+ cp[3] = (unsigned char)(val & 0x000000ff);
+}
+
+/* copies length bytes of memory at base to b */
+void
+lwres_buffer_putmem(lwres_buffer_t *b, const unsigned char *base,
+ unsigned int length)
+{
+ unsigned char *cp;
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->used + length <= b->length);
+
+ cp = (unsigned char *)b->base + b->used;
+ memcpy(cp, base, length);
+ b->used += length;
+}
+
+/* copies length bytes of memory at b to base */
+void
+lwres_buffer_getmem(lwres_buffer_t *b, unsigned char *base,
+ unsigned int length)
+{
+ unsigned char *cp;
+
+ REQUIRE(LWRES_BUFFER_VALID(b));
+ REQUIRE(b->used - b->current >= length);
+
+ cp = b->base;
+ cp += b->current;
+ b->current += length;
+
+ memcpy(base, cp, length);
+}
diff --git a/lib/lwres/lwconfig.c b/lib/lwres/lwconfig.c
new file mode 100644
index 0000000..15f4abb
--- /dev/null
+++ b/lib/lwres/lwconfig.c
@@ -0,0 +1,725 @@
+/*
+ * Copyright (C) 2004-2007 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: lwconfig.c,v 1.46 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+/**
+ * Module for parsing resolv.conf files.
+ *
+ * lwres_conf_init() creates an empty lwres_conf_t structure for
+ * lightweight resolver context ctx.
+ *
+ * lwres_conf_clear() frees up all the internal memory used by that
+ * lwres_conf_t structure in resolver context ctx.
+ *
+ * lwres_conf_parse() opens the file filename and parses it to initialise
+ * the resolver context ctx's lwres_conf_t structure.
+ *
+ * lwres_conf_print() prints the lwres_conf_t structure for resolver
+ * context ctx to the FILE fp.
+ *
+ * \section lwconfig_return Return Values
+ *
+ * lwres_conf_parse() returns #LWRES_R_SUCCESS if it successfully read and
+ * parsed filename. It returns #LWRES_R_FAILURE if filename could not be
+ * opened or contained incorrect resolver statements.
+ *
+ * lwres_conf_print() returns #LWRES_R_SUCCESS unless an error occurred
+ * when converting the network addresses to a numeric host address
+ * string. If this happens, the function returns #LWRES_R_FAILURE.
+ *
+ * \section lwconfig_see See Also
+ *
+ * stdio(3), \link resolver resolver \endlink
+ *
+ * \section files Files
+ *
+ * /etc/resolv.conf
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <lwres/lwbuffer.h>
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+#include <lwres/result.h>
+
+#include "assert_p.h"
+#include "context_p.h"
+
+
+#if ! defined(NS_INADDRSZ)
+#define NS_INADDRSZ 4
+#endif
+
+#if ! defined(NS_IN6ADDRSZ)
+#define NS_IN6ADDRSZ 16
+#endif
+
+static lwres_result_t
+lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp);
+
+static lwres_result_t
+lwres_conf_parselwserver(lwres_context_t *ctx, FILE *fp);
+
+static lwres_result_t
+lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp);
+
+static lwres_result_t
+lwres_conf_parsesearch(lwres_context_t *ctx, FILE *fp);
+
+static lwres_result_t
+lwres_conf_parsesortlist(lwres_context_t *ctx, FILE *fp);
+
+static lwres_result_t
+lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp);
+
+static void
+lwres_resetaddr(lwres_addr_t *addr);
+
+static lwres_result_t
+lwres_create_addr(const char *buff, lwres_addr_t *addr, int convert_zero);
+
+static int lwresaddr2af(int lwresaddrtype);
+
+
+static int
+lwresaddr2af(int lwresaddrtype)
+{
+ int af = 0;
+
+ switch (lwresaddrtype) {
+ case LWRES_ADDRTYPE_V4:
+ af = AF_INET;
+ break;
+
+ case LWRES_ADDRTYPE_V6:
+ af = AF_INET6;
+ break;
+ }
+
+ return (af);
+}
+
+
+/*!
+ * 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 void
+lwres_resetaddr(lwres_addr_t *addr) {
+ REQUIRE(addr != NULL);
+
+ memset(addr->address, 0, LWRES_ADDR_MAXLEN);
+ addr->family = 0;
+ addr->length = 0;
+}
+
+static char *
+lwres_strdup(lwres_context_t *ctx, const char *str) {
+ char *p;
+
+ REQUIRE(str != NULL);
+ REQUIRE(strlen(str) > 0U);
+
+ p = CTXMALLOC(strlen(str) + 1);
+ if (p != NULL)
+ strcpy(p, str);
+
+ return (p);
+}
+
+/*% intializes data structure for subsequent config parsing. */
+void
+lwres_conf_init(lwres_context_t *ctx) {
+ int i;
+ lwres_conf_t *confdata;
+
+ REQUIRE(ctx != NULL);
+ confdata = &ctx->confdata;
+
+ confdata->nsnext = 0;
+ confdata->lwnext = 0;
+ confdata->domainname = NULL;
+ confdata->searchnxt = 0;
+ confdata->sortlistnxt = 0;
+ confdata->resdebug = 0;
+ confdata->ndots = 1;
+ confdata->no_tld_query = 0;
+
+ for (i = 0; i < LWRES_CONFMAXNAMESERVERS; i++)
+ lwres_resetaddr(&confdata->nameservers[i]);
+
+ for (i = 0; i < LWRES_CONFMAXSEARCH; i++)
+ confdata->search[i] = NULL;
+
+ for (i = 0; i < LWRES_CONFMAXSORTLIST; i++) {
+ lwres_resetaddr(&confdata->sortlist[i].addr);
+ lwres_resetaddr(&confdata->sortlist[i].mask);
+ }
+}
+
+/*% Frees up all the internal memory used by the config data structure, returning it to the lwres_context_t. */
+void
+lwres_conf_clear(lwres_context_t *ctx) {
+ int i;
+ lwres_conf_t *confdata;
+
+ REQUIRE(ctx != NULL);
+ confdata = &ctx->confdata;
+
+ for (i = 0; i < confdata->nsnext; i++)
+ lwres_resetaddr(&confdata->nameservers[i]);
+
+ if (confdata->domainname != NULL) {
+ CTXFREE(confdata->domainname,
+ strlen(confdata->domainname) + 1);
+ confdata->domainname = NULL;
+ }
+
+ for (i = 0; i < confdata->searchnxt; i++) {
+ if (confdata->search[i] != NULL) {
+ CTXFREE(confdata->search[i],
+ strlen(confdata->search[i]) + 1);
+ confdata->search[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < LWRES_CONFMAXSORTLIST; i++) {
+ lwres_resetaddr(&confdata->sortlist[i].addr);
+ lwres_resetaddr(&confdata->sortlist[i].mask);
+ }
+
+ confdata->nsnext = 0;
+ confdata->lwnext = 0;
+ confdata->domainname = NULL;
+ confdata->searchnxt = 0;
+ confdata->sortlistnxt = 0;
+ confdata->resdebug = 0;
+ confdata->ndots = 1;
+ confdata->no_tld_query = 0;
+}
+
+static lwres_result_t
+lwres_conf_parsenameserver(lwres_context_t *ctx, FILE *fp) {
+ char word[LWRES_CONFMAXLINELEN];
+ int res;
+ lwres_conf_t *confdata;
+ lwres_addr_t address;
+
+ confdata = &ctx->confdata;
+
+ if (confdata->nsnext == LWRES_CONFMAXNAMESERVERS)
+ return (LWRES_R_SUCCESS);
+
+ res = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (LWRES_R_FAILURE); /* Nothing on line. */
+ else if (res == ' ' || res == '\t')
+ res = eatwhite(fp);
+
+ if (res != EOF && res != '\n')
+ return (LWRES_R_FAILURE); /* Extra junk on line. */
+
+ res = lwres_create_addr(word, &address, 1);
+ if (res == LWRES_R_SUCCESS)
+ confdata->nameservers[confdata->nsnext++] = address;
+
+ return (LWRES_R_SUCCESS);
+}
+
+static lwres_result_t
+lwres_conf_parselwserver(lwres_context_t *ctx, FILE *fp) {
+ char word[LWRES_CONFMAXLINELEN];
+ int res;
+ lwres_conf_t *confdata;
+
+ confdata = &ctx->confdata;
+
+ if (confdata->lwnext == LWRES_CONFMAXLWSERVERS)
+ return (LWRES_R_SUCCESS);
+
+ res = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (LWRES_R_FAILURE); /* Nothing on line. */
+ else if (res == ' ' || res == '\t')
+ res = eatwhite(fp);
+
+ if (res != EOF && res != '\n')
+ return (LWRES_R_FAILURE); /* Extra junk on line. */
+
+ res = lwres_create_addr(word,
+ &confdata->lwservers[confdata->lwnext++], 1);
+ if (res != LWRES_R_SUCCESS)
+ return (res);
+
+ return (LWRES_R_SUCCESS);
+}
+
+static lwres_result_t
+lwres_conf_parsedomain(lwres_context_t *ctx, FILE *fp) {
+ char word[LWRES_CONFMAXLINELEN];
+ int res, i;
+ lwres_conf_t *confdata;
+
+ confdata = &ctx->confdata;
+
+ res = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (LWRES_R_FAILURE); /* Nothing else on line. */
+ else if (res == ' ' || res == '\t')
+ res = eatwhite(fp);
+
+ if (res != EOF && res != '\n')
+ return (LWRES_R_FAILURE); /* Extra junk on line. */
+
+ if (confdata->domainname != NULL)
+ CTXFREE(confdata->domainname,
+ strlen(confdata->domainname) + 1); /* */
+
+ /*
+ * Search and domain are mutually exclusive.
+ */
+ for (i = 0; i < LWRES_CONFMAXSEARCH; i++) {
+ if (confdata->search[i] != NULL) {
+ CTXFREE(confdata->search[i],
+ strlen(confdata->search[i])+1);
+ confdata->search[i] = NULL;
+ }
+ }
+ confdata->searchnxt = 0;
+
+ confdata->domainname = lwres_strdup(ctx, word);
+
+ if (confdata->domainname == NULL)
+ return (LWRES_R_FAILURE);
+
+ return (LWRES_R_SUCCESS);
+}
+
+static lwres_result_t
+lwres_conf_parsesearch(lwres_context_t *ctx, FILE *fp) {
+ int idx, delim;
+ char word[LWRES_CONFMAXLINELEN];
+ lwres_conf_t *confdata;
+
+ confdata = &ctx->confdata;
+
+ if (confdata->domainname != NULL) {
+ /*
+ * Search and domain are mutually exclusive.
+ */
+ CTXFREE(confdata->domainname,
+ strlen(confdata->domainname) + 1);
+ confdata->domainname = NULL;
+ }
+
+ /*
+ * Remove any previous search definitions.
+ */
+ for (idx = 0; idx < LWRES_CONFMAXSEARCH; idx++) {
+ if (confdata->search[idx] != NULL) {
+ CTXFREE(confdata->search[idx],
+ strlen(confdata->search[idx])+1);
+ confdata->search[idx] = NULL;
+ }
+ }
+ confdata->searchnxt = 0;
+
+ delim = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (LWRES_R_FAILURE); /* Nothing else on line. */
+
+ idx = 0;
+ while (strlen(word) > 0U) {
+ if (confdata->searchnxt == LWRES_CONFMAXSEARCH)
+ goto ignore; /* Too many domains. */
+
+ confdata->search[idx] = lwres_strdup(ctx, word);
+ if (confdata->search[idx] == NULL)
+ return (LWRES_R_FAILURE);
+ idx++;
+ confdata->searchnxt++;
+
+ ignore:
+ if (delim == EOF || delim == '\n')
+ break;
+ else
+ delim = getword(fp, word, sizeof(word));
+ }
+
+ return (LWRES_R_SUCCESS);
+}
+
+static lwres_result_t
+lwres_create_addr(const char *buffer, lwres_addr_t *addr, int convert_zero) {
+ struct in_addr v4;
+ struct in6_addr v6;
+
+ if (lwres_net_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 = LWRES_ADDRTYPE_V4;
+ addr->length = NS_INADDRSZ;
+ memcpy((void *)addr->address, &v4, NS_INADDRSZ);
+
+ } else if (lwres_net_pton(AF_INET6, buffer, &v6) == 1) {
+ addr->family = LWRES_ADDRTYPE_V6;
+ addr->length = NS_IN6ADDRSZ;
+ memcpy((void *)addr->address, &v6, NS_IN6ADDRSZ);
+ } else {
+ return (LWRES_R_FAILURE); /* Unrecognised format. */
+ }
+
+ return (LWRES_R_SUCCESS);
+}
+
+static lwres_result_t
+lwres_conf_parsesortlist(lwres_context_t *ctx, FILE *fp) {
+ int delim, res, idx;
+ char word[LWRES_CONFMAXLINELEN];
+ char *p;
+ lwres_conf_t *confdata;
+
+ confdata = &ctx->confdata;
+
+ delim = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (LWRES_R_FAILURE); /* Empty line after keyword. */
+
+ while (strlen(word) > 0U) {
+ if (confdata->sortlistnxt == LWRES_CONFMAXSORTLIST)
+ return (LWRES_R_FAILURE); /* Too many values. */
+
+ p = strchr(word, '/');
+ if (p != NULL)
+ *p++ = '\0';
+
+ idx = confdata->sortlistnxt;
+ res = lwres_create_addr(word, &confdata->sortlist[idx].addr, 1);
+ if (res != LWRES_R_SUCCESS)
+ return (res);
+
+ if (p != NULL) {
+ res = lwres_create_addr(p,
+ &confdata->sortlist[idx].mask,
+ 0);
+ if (res != LWRES_R_SUCCESS)
+ return (res);
+ } else {
+ /*
+ * Make up a mask.
+ */
+ confdata->sortlist[idx].mask =
+ confdata->sortlist[idx].addr;
+
+ memset(&confdata->sortlist[idx].mask.address, 0xff,
+ confdata->sortlist[idx].addr.length);
+ }
+
+ confdata->sortlistnxt++;
+
+ if (delim == EOF || delim == '\n')
+ break;
+ else
+ delim = getword(fp, word, sizeof(word));
+ }
+
+ return (LWRES_R_SUCCESS);
+}
+
+static lwres_result_t
+lwres_conf_parseoption(lwres_context_t *ctx, FILE *fp) {
+ int delim;
+ long ndots;
+ char *p;
+ char word[LWRES_CONFMAXLINELEN];
+ lwres_conf_t *confdata;
+
+ REQUIRE(ctx != NULL);
+ confdata = &ctx->confdata;
+
+ delim = getword(fp, word, sizeof(word));
+ if (strlen(word) == 0U)
+ return (LWRES_R_FAILURE); /* Empty line after keyword. */
+
+ while (strlen(word) > 0U) {
+ if (strcmp("debug", word) == 0) {
+ confdata->resdebug = 1;
+ } else if (strcmp("no_tld_query", word) == 0) {
+ confdata->no_tld_query = 1;
+ } else if (strncmp("ndots:", word, 6) == 0) {
+ ndots = strtol(word + 6, &p, 10);
+ if (*p != '\0') /* Bad string. */
+ return (LWRES_R_FAILURE);
+ if (ndots < 0 || ndots > 0xff) /* Out of range. */
+ return (LWRES_R_FAILURE);
+ confdata->ndots = (lwres_uint8_t)ndots;
+ }
+
+ if (delim == EOF || delim == '\n')
+ break;
+ else
+ delim = getword(fp, word, sizeof(word));
+ }
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% parses a file and fills in the data structure. */
+lwres_result_t
+lwres_conf_parse(lwres_context_t *ctx, const char *filename) {
+ FILE *fp = NULL;
+ char word[256];
+ lwres_result_t rval, ret;
+ lwres_conf_t *confdata;
+ int stopchar;
+
+ REQUIRE(ctx != NULL);
+ confdata = &ctx->confdata;
+
+ REQUIRE(filename != NULL);
+ REQUIRE(strlen(filename) > 0U);
+ REQUIRE(confdata != NULL);
+
+ errno = 0;
+ if ((fp = fopen(filename, "r")) == NULL)
+ return (LWRES_R_NOTFOUND);
+
+ ret = LWRES_R_SUCCESS;
+ do {
+ stopchar = getword(fp, word, sizeof(word));
+ if (stopchar == EOF) {
+ rval = LWRES_R_SUCCESS;
+ break;
+ }
+
+ if (strlen(word) == 0U)
+ rval = LWRES_R_SUCCESS;
+ else if (strcmp(word, "nameserver") == 0)
+ rval = lwres_conf_parsenameserver(ctx, fp);
+ else if (strcmp(word, "lwserver") == 0)
+ rval = lwres_conf_parselwserver(ctx, fp);
+ else if (strcmp(word, "domain") == 0)
+ rval = lwres_conf_parsedomain(ctx, fp);
+ else if (strcmp(word, "search") == 0)
+ rval = lwres_conf_parsesearch(ctx, fp);
+ else if (strcmp(word, "sortlist") == 0)
+ rval = lwres_conf_parsesortlist(ctx, fp);
+ else if (strcmp(word, "options") == 0)
+ rval = lwres_conf_parseoption(ctx, fp);
+ else {
+ /* unrecognised word. Ignore entire line */
+ rval = LWRES_R_SUCCESS;
+ stopchar = eatline(fp);
+ if (stopchar == EOF) {
+ break;
+ }
+ }
+ if (ret == LWRES_R_SUCCESS && rval != LWRES_R_SUCCESS)
+ ret = rval;
+ } while (1);
+
+ fclose(fp);
+
+ return (ret);
+}
+
+/*% Prints the config data structure to the FILE. */
+lwres_result_t
+lwres_conf_print(lwres_context_t *ctx, FILE *fp) {
+ int i;
+ int af;
+ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+ const char *p;
+ lwres_conf_t *confdata;
+ lwres_addr_t tmpaddr;
+
+ REQUIRE(ctx != NULL);
+ confdata = &ctx->confdata;
+
+ REQUIRE(confdata->nsnext <= LWRES_CONFMAXNAMESERVERS);
+
+ for (i = 0; i < confdata->nsnext; i++) {
+ af = lwresaddr2af(confdata->nameservers[i].family);
+
+ p = lwres_net_ntop(af, confdata->nameservers[i].address,
+ tmp, sizeof(tmp));
+ if (p != tmp)
+ return (LWRES_R_FAILURE);
+
+ fprintf(fp, "nameserver %s\n", tmp);
+ }
+
+ for (i = 0; i < confdata->lwnext; i++) {
+ af = lwresaddr2af(confdata->lwservers[i].family);
+
+ p = lwres_net_ntop(af, confdata->lwservers[i].address,
+ tmp, sizeof(tmp));
+ if (p != tmp)
+ return (LWRES_R_FAILURE);
+
+ fprintf(fp, "lwserver %s\n", tmp);
+ }
+
+ if (confdata->domainname != NULL) {
+ fprintf(fp, "domain %s\n", confdata->domainname);
+ } else if (confdata->searchnxt > 0) {
+ REQUIRE(confdata->searchnxt <= LWRES_CONFMAXSEARCH);
+
+ fprintf(fp, "search");
+ for (i = 0; i < confdata->searchnxt; i++)
+ fprintf(fp, " %s", confdata->search[i]);
+ fputc('\n', fp);
+ }
+
+ REQUIRE(confdata->sortlistnxt <= LWRES_CONFMAXSORTLIST);
+
+ if (confdata->sortlistnxt > 0) {
+ fputs("sortlist", fp);
+ for (i = 0; i < confdata->sortlistnxt; i++) {
+ af = lwresaddr2af(confdata->sortlist[i].addr.family);
+
+ p = lwres_net_ntop(af,
+ confdata->sortlist[i].addr.address,
+ tmp, sizeof(tmp));
+ if (p != tmp)
+ return (LWRES_R_FAILURE);
+
+ fprintf(fp, " %s", tmp);
+
+ tmpaddr = confdata->sortlist[i].mask;
+ memset(&tmpaddr.address, 0xff, tmpaddr.length);
+
+ if (memcmp(&tmpaddr.address,
+ confdata->sortlist[i].mask.address,
+ confdata->sortlist[i].mask.length) != 0) {
+ af = lwresaddr2af(
+ confdata->sortlist[i].mask.family);
+ p = lwres_net_ntop
+ (af,
+ confdata->sortlist[i].mask.address,
+ tmp, sizeof(tmp));
+ if (p != tmp)
+ return (LWRES_R_FAILURE);
+
+ fprintf(fp, "/%s", tmp);
+ }
+ }
+ fputc('\n', fp);
+ }
+
+ if (confdata->resdebug)
+ fprintf(fp, "options debug\n");
+
+ if (confdata->ndots > 0)
+ fprintf(fp, "options ndots:%d\n", confdata->ndots);
+
+ if (confdata->no_tld_query)
+ fprintf(fp, "options no_tld_query\n");
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Returns a pointer to the current config structure. */
+lwres_conf_t *
+lwres_conf_get(lwres_context_t *ctx) {
+ REQUIRE(ctx != NULL);
+
+ return (&ctx->confdata);
+}
diff --git a/lib/lwres/lwinetaton.c b/lib/lwres/lwinetaton.c
new file mode 100644
index 0000000..e40c28f
--- /dev/null
+++ b/lib/lwres/lwinetaton.c
@@ -0,0 +1,205 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 1996-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.
+ */
+
+/*
+ * Copyright (c) 1983, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*! \file lwinetaton.c
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
+static char rcsid[] = "$Id: lwinetaton.c,v 1.16 2007/06/19 23:47:22 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <ctype.h>
+
+#include <stddef.h>
+
+#include <lwres/int.h>
+#include <lwres/net.h>
+
+#include "assert_p.h"
+
+/*!
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+lwres_net_aton(const char *cp, struct in_addr *addr) {
+ unsigned long val;
+ int base, n;
+ unsigned char c;
+ lwres_uint8_t parts[4];
+ lwres_uint8_t *pp = parts;
+ int digit;
+
+ REQUIRE(cp != NULL);
+
+ c = *cp;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, isdigit=decimal.
+ */
+ if (!isdigit(c & 0xff))
+ return (0);
+ val = 0;
+ base = 10;
+ digit = 0;
+ if (c == '0') {
+ c = *++cp;
+ if (c == 'x' || c == 'X') {
+ base = 16;
+ c = *++cp;
+ } else {
+ base = 8;
+ digit = 1;
+ }
+ }
+ for (;;) {
+ /*
+ * isascii() is valid for all integer values, and
+ * when it is true, c is known to be in scope
+ * for isdigit(). No cast necessary. Similar
+ * comment applies for later ctype uses.
+ */
+ if (isascii(c) && isdigit(c)) {
+ if (base == 8 && (c == '8' || c == '9'))
+ return (0);
+ val = (val * base) + (c - '0');
+ c = *++cp;
+ digit = 1;
+ } else if (base == 16 && isascii(c) && isxdigit(c)) {
+ val = (val << 4) |
+ (c + 10 - (islower(c) ? 'a' : 'A'));
+ c = *++cp;
+ digit = 1;
+ } else
+ break;
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xffU)
+ return (0);
+ *pp++ = (lwres_uint8_t)val;
+ c = *++cp;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && (!isascii(c) || !isspace(c)))
+ return (0);
+ /*
+ * Did we get a valid digit?
+ */
+ if (!digit)
+ return (0);
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n) {
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffffU)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffffU)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xffU)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr != NULL)
+ addr->s_addr = htonl(val);
+
+ return (1);
+}
diff --git a/lib/lwres/lwinetntop.c b/lib/lwres/lwinetntop.c
new file mode 100644
index 0000000..cf3bdfe
--- /dev/null
+++ b/lib/lwres/lwinetntop.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1996-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.
+ */
+
+/*! \file lwinetntop.c
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] =
+ "$Id: lwinetntop.c,v 1.18 2007/06/19 23:47:22 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <lwres/net.h>
+#include "print_p.h"
+
+#define NS_INT16SZ 2
+#define NS_IN6ADDRSZ 16
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4(const unsigned char *src, char *dst,
+ size_t size);
+
+#ifdef AF_INET6
+static const char *inet_ntop6(const unsigned char *src, char *dst,
+ size_t size);
+#endif
+
+/*! char *
+ * lwres_net_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * return:
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ * Paul Vixie, 1996.
+ */
+const char *
+lwres_net_ntop(int af, const void *src, char *dst, size_t size) {
+ switch (af) {
+ case AF_INET:
+ return (inet_ntop4(src, dst, size));
+#ifdef AF_INET6
+ case AF_INET6:
+ return (inet_ntop6(src, dst, size));
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+/*! const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address
+ * return:
+ * `dst' (as a const)
+ * notes:
+ * (1) uses no statics
+ * (2) takes a unsigned char* not an in_addr as input
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(const unsigned char *src, char *dst, size_t size) {
+ static const char fmt[] = "%u.%u.%u.%u";
+ char tmp[sizeof("255.255.255.255")];
+ size_t len;
+
+ len = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
+ if (len >= size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+
+ return (dst);
+}
+
+/*! const char *
+ * inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+#ifdef AF_INET6
+static const char *
+inet_ntop6(const unsigned char *src, char *dst, size_t size) {
+ /*!
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp;
+ struct { int base, len; } best, cur;
+ unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof(words));
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ best.len = 0;
+ cur.base = -1;
+ cur.len = 0;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 &&
+ (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+ if (!inet_ntop4(src+12, tp,
+ sizeof(tmp) - (tp - tmp)))
+ return (NULL);
+ tp += strlen(tp);
+ break;
+ }
+ tp += sprintf(tp, "%x", words[i]); /* XXX */
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+#endif /* AF_INET6 */
diff --git a/lib/lwres/lwinetpton.c b/lib/lwres/lwinetpton.c
new file mode 100644
index 0000000..5bbef08
--- /dev/null
+++ b/lib/lwres/lwinetpton.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1996-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.
+ */
+
+/*! \file lwinetpton.c
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id: lwinetpton.c,v 1.12 2007/06/19 23:47:22 tbox Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <config.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <lwres/net.h>
+
+#define NS_INT16SZ 2
+#define NS_INADDRSZ 4
+#define NS_IN6ADDRSZ 16
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4(const char *src, unsigned char *dst);
+static int inet_pton6(const char *src, unsigned char *dst);
+
+/*!
+ * int
+ * lwres_net_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+lwres_net_pton(int af, const char *src, void *dst) {
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/*! int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, unsigned char *dst) {
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ unsigned char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ unsigned int new = *tp * 10 + (pch - digits);
+
+ if (new > 255)
+ return (0);
+ *tp = new;
+ if (! saw_digit) {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return (1);
+}
+
+/*! int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, unsigned char *dst) {
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, seen_xdigits;
+ unsigned int val;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ seen_xdigits = 0;
+ val = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (++seen_xdigits > 4)
+ return (0);
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!seen_xdigits) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ seen_xdigits = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += NS_INADDRSZ;
+ seen_xdigits = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (seen_xdigits) {
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return (1);
+}
diff --git a/lib/lwres/lwpacket.c b/lib/lwres/lwpacket.c
new file mode 100644
index 0000000..cfa2723
--- /dev/null
+++ b/lib/lwres/lwpacket.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwpacket.c,v 1.18 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+/**
+ * These functions rely on a struct lwres_lwpacket which is defined in
+ * \link lwpacket.h lwres/lwpacket.h.\endlink
+ *
+ * The following opcodes are currently defined:
+ *
+ * \li #LWRES_OPCODE_NOOP
+ * Success is always returned and the packet contents are
+ * echoed. The \link lwres_noop.c lwres_noop_*()\endlink functions should be used for this
+ * type.
+ *
+ * \li #LWRES_OPCODE_GETADDRSBYNAME
+ * returns all known addresses for a given name. The
+ * \link lwres_gabn.c lwres_gabn_*()\endlink functions should be used for this type.
+ *
+ * \li #LWRES_OPCODE_GETNAMEBYADDR
+ * return the hostname for the given address. The
+ * \link lwres_gnba.c lwres_gnba_*() \endlink functions should be used for this type.
+ *
+ * lwres_lwpacket_renderheader() transfers the contents of lightweight
+ * resolver packet structure #lwres_lwpacket_t *pkt in network byte
+ * order to the lightweight resolver buffer, *b.
+ *
+ * lwres_lwpacket_parseheader() performs the converse operation. It
+ * transfers data in network byte order from buffer *b to resolver
+ * packet *pkt. The contents of the buffer b should correspond to a
+ * #lwres_lwpacket_t.
+ *
+ * \section lwpacket_return Return Values
+ *
+ * Successful calls to lwres_lwpacket_renderheader() and
+ * lwres_lwpacket_parseheader() return #LWRES_R_SUCCESS. If there is
+ * insufficient space to copy data between the buffer *b and
+ * lightweight resolver packet *pkt both functions return
+ * #LWRES_R_UNEXPECTEDEND.
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <lwres/lwbuffer.h>
+#include <lwres/lwpacket.h>
+#include <lwres/result.h>
+
+#include "assert_p.h"
+
+/*% Length of Packet */
+#define LWPACKET_LENGTH \
+ (sizeof(lwres_uint16_t) * 4 + sizeof(lwres_uint32_t) * 5)
+
+/*% transfers the contents of lightweight resolver packet structure lwres_lwpacket_t *pkt in network byte order to the lightweight resolver buffer, *b. */
+
+lwres_result_t
+lwres_lwpacket_renderheader(lwres_buffer_t *b, lwres_lwpacket_t *pkt) {
+ REQUIRE(b != NULL);
+ REQUIRE(pkt != NULL);
+
+ if (!SPACE_OK(b, LWPACKET_LENGTH))
+ return (LWRES_R_UNEXPECTEDEND);
+
+ lwres_buffer_putuint32(b, pkt->length);
+ lwres_buffer_putuint16(b, pkt->version);
+ lwres_buffer_putuint16(b, pkt->pktflags);
+ lwres_buffer_putuint32(b, pkt->serial);
+ lwres_buffer_putuint32(b, pkt->opcode);
+ lwres_buffer_putuint32(b, pkt->result);
+ lwres_buffer_putuint32(b, pkt->recvlength);
+ lwres_buffer_putuint16(b, pkt->authtype);
+ lwres_buffer_putuint16(b, pkt->authlength);
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% transfers data in network byte order from buffer *b to resolver packet *pkt. The contents of the buffer b should correspond to a lwres_lwpacket_t. */
+
+lwres_result_t
+lwres_lwpacket_parseheader(lwres_buffer_t *b, lwres_lwpacket_t *pkt) {
+ lwres_uint32_t space;
+
+ REQUIRE(b != NULL);
+ REQUIRE(pkt != NULL);
+
+ space = LWRES_BUFFER_REMAINING(b);
+ if (space < LWPACKET_LENGTH)
+ return (LWRES_R_UNEXPECTEDEND);
+
+ pkt->length = lwres_buffer_getuint32(b);
+ /*
+ * XXXBEW/MLG Checking that the buffer is long enough probably
+ * shouldn't be done here, since this function is supposed to just
+ * parse the header.
+ */
+ if (pkt->length > space)
+ return (LWRES_R_UNEXPECTEDEND);
+ pkt->version = lwres_buffer_getuint16(b);
+ pkt->pktflags = lwres_buffer_getuint16(b);
+ pkt->serial = lwres_buffer_getuint32(b);
+ pkt->opcode = lwres_buffer_getuint32(b);
+ pkt->result = lwres_buffer_getuint32(b);
+ pkt->recvlength = lwres_buffer_getuint32(b);
+ pkt->authtype = lwres_buffer_getuint16(b);
+ pkt->authlength = lwres_buffer_getuint16(b);
+
+ return (LWRES_R_SUCCESS);
+}
diff --git a/lib/lwres/lwres_gabn.c b/lib/lwres/lwres_gabn.c
new file mode 100644
index 0000000..3363e66
--- /dev/null
+++ b/lib/lwres/lwres_gabn.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwres_gabn.c,v 1.33 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file lwres_gabn.c
+ These are low-level routines for creating and parsing lightweight
+ resolver name-to-address lookup request and response messages.
+
+ There are four main functions for the getaddrbyname opcode. One render
+ function converts a getaddrbyname request structure --
+ lwres_gabnrequest_t -- to the lighweight resolver's canonical format.
+ It is complemented by a parse function that converts a packet in this
+ canonical format to a getaddrbyname request structure. Another render
+ function converts the getaddrbyname response structure --
+ lwres_gabnresponse_t -- to the canonical format. This is complemented
+ by a parse function which converts a packet in canonical format to a
+ getaddrbyname response structure.
+
+ These structures are defined in \link lwres.h <lwres/lwres.h>.\endlink They are shown below.
+
+\code
+#define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
+
+typedef struct lwres_addr lwres_addr_t;
+typedef LWRES_LIST(lwres_addr_t) lwres_addrlist_t;
+
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint32_t addrtypes;
+ lwres_uint16_t namelen;
+ char *name;
+} lwres_gabnrequest_t;
+
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ lwres_uint16_t naddrs;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ lwres_addrlist_t addrs;
+ void *base;
+ size_t baselen;
+} lwres_gabnresponse_t;
+\endcode
+
+ lwres_gabnrequest_render() uses resolver context ctx to convert
+ getaddrbyname request structure req to canonical format. The packet
+ header structure pkt is initialised and transferred to buffer b. The
+ contents of *req are then appended to the buffer in canonical format.
+ lwres_gabnresponse_render() performs the same task, except it converts
+ a getaddrbyname response structure lwres_gabnresponse_t to the
+ lightweight resolver's canonical format.
+
+ lwres_gabnrequest_parse() uses context ctx to convert the contents of
+ packet pkt to a lwres_gabnrequest_t structure. Buffer b provides space
+ to be used for storing this structure. When the function succeeds, the
+ resulting lwres_gabnrequest_t is made available through *structp.
+ lwres_gabnresponse_parse() offers the same semantics as
+ lwres_gabnrequest_parse() except it yields a lwres_gabnresponse_t
+ structure.
+
+ lwres_gabnresponse_free() and lwres_gabnrequest_free() release the
+ memory in resolver context ctx that was allocated to the
+ lwres_gabnresponse_t or lwres_gabnrequest_t structures referenced via
+ structp. Any memory associated with ancillary buffers and strings for
+ those structures is also discarded.
+
+\section lwres_gabn_return Return Values
+
+ The getaddrbyname opcode functions lwres_gabnrequest_render(),
+ lwres_gabnresponse_render() lwres_gabnrequest_parse() and
+ lwres_gabnresponse_parse() all return #LWRES_R_SUCCESS on success. They
+ return #LWRES_R_NOMEMORY if memory allocation fails.
+ #LWRES_R_UNEXPECTEDEND is returned if the available space in the buffer
+ b is too small to accommodate the packet header or the
+ lwres_gabnrequest_t and lwres_gabnresponse_t structures.
+ lwres_gabnrequest_parse() and lwres_gabnresponse_parse() will return
+ #LWRES_R_UNEXPECTEDEND if the buffer is not empty after decoding the
+ received packet. These functions will return #LWRES_R_FAILURE if
+ pktflags in the packet header structure #lwres_lwpacket_t indicate that
+ the packet is not a response to an earlier query.
+
+\section lwres_gabn_see See Also
+
+ \link lwpacket.c lwres_lwpacket \endlink
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <lwres/lwbuffer.h>
+#include <lwres/lwpacket.h>
+#include <lwres/lwres.h>
+#include <lwres/result.h>
+
+#include "context_p.h"
+#include "assert_p.h"
+
+/*% uses resolver context ctx to convert getaddrbyname request structure req to canonical format. */
+lwres_result_t
+lwres_gabnrequest_render(lwres_context_t *ctx, lwres_gabnrequest_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b)
+{
+ unsigned char *buf;
+ size_t buflen;
+ int ret;
+ size_t payload_length;
+ lwres_uint16_t datalen;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(req != NULL);
+ REQUIRE(req->name != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+
+ datalen = strlen(req->name);
+
+ payload_length = 4 + 4 + 2 + req->namelen + 1;
+
+ buflen = LWRES_LWPACKET_LENGTH + payload_length;
+ buf = CTXMALLOC(buflen);
+ if (buf == NULL)
+ return (LWRES_R_NOMEMORY);
+
+ lwres_buffer_init(b, buf, buflen);
+
+ pkt->length = buflen;
+ pkt->version = LWRES_LWPACKETVERSION_0;
+ pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
+ pkt->opcode = LWRES_OPCODE_GETADDRSBYNAME;
+ pkt->result = 0;
+ pkt->authtype = 0;
+ pkt->authlength = 0;
+
+ ret = lwres_lwpacket_renderheader(b, pkt);
+ if (ret != LWRES_R_SUCCESS) {
+ lwres_buffer_invalidate(b);
+ CTXFREE(buf, buflen);
+ return (ret);
+ }
+
+ INSIST(SPACE_OK(b, payload_length));
+
+ /*
+ * Flags.
+ */
+ lwres_buffer_putuint32(b, req->flags);
+
+ /*
+ * Address types we'll accept.
+ */
+ lwres_buffer_putuint32(b, req->addrtypes);
+
+ /*
+ * Put the length and the data. We know this will fit because we
+ * just checked for it.
+ */
+ lwres_buffer_putuint16(b, datalen);
+ lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
+ lwres_buffer_putuint8(b, 0); /* trailing NUL */
+
+ INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
+
+ return (LWRES_R_SUCCESS);
+}
+/*% converts a getaddrbyname response structure lwres_gabnresponse_t to the lightweight resolver's canonical format. */
+lwres_result_t
+lwres_gabnresponse_render(lwres_context_t *ctx, lwres_gabnresponse_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b)
+{
+ unsigned char *buf;
+ size_t buflen;
+ int ret;
+ size_t payload_length;
+ lwres_uint16_t datalen;
+ lwres_addr_t *addr;
+ int x;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(req != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+
+ /* naliases, naddrs */
+ payload_length = 4 + 2 + 2;
+ /* real name encoding */
+ payload_length += 2 + req->realnamelen + 1;
+ /* each alias */
+ for (x = 0; x < req->naliases; x++)
+ payload_length += 2 + req->aliaslen[x] + 1;
+ /* each address */
+ x = 0;
+ addr = LWRES_LIST_HEAD(req->addrs);
+ while (addr != NULL) {
+ payload_length += 4 + 2;
+ payload_length += addr->length;
+ addr = LWRES_LIST_NEXT(addr, link);
+ x++;
+ }
+ INSIST(x == req->naddrs);
+
+ buflen = LWRES_LWPACKET_LENGTH + payload_length;
+ buf = CTXMALLOC(buflen);
+ if (buf == NULL)
+ return (LWRES_R_NOMEMORY);
+ lwres_buffer_init(b, buf, buflen);
+
+ pkt->length = buflen;
+ pkt->version = LWRES_LWPACKETVERSION_0;
+ pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
+ pkt->opcode = LWRES_OPCODE_GETADDRSBYNAME;
+ pkt->authtype = 0;
+ pkt->authlength = 0;
+
+ ret = lwres_lwpacket_renderheader(b, pkt);
+ if (ret != LWRES_R_SUCCESS) {
+ lwres_buffer_invalidate(b);
+ CTXFREE(buf, buflen);
+ return (ret);
+ }
+
+ /*
+ * Check space needed here.
+ */
+ INSIST(SPACE_OK(b, payload_length));
+
+ /* Flags. */
+ lwres_buffer_putuint32(b, req->flags);
+
+ /* encode naliases and naddrs */
+ lwres_buffer_putuint16(b, req->naliases);
+ lwres_buffer_putuint16(b, req->naddrs);
+
+ /* encode the real name */
+ datalen = req->realnamelen;
+ lwres_buffer_putuint16(b, datalen);
+ lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
+ lwres_buffer_putuint8(b, 0);
+
+ /* encode the aliases */
+ for (x = 0; x < req->naliases; x++) {
+ datalen = req->aliaslen[x];
+ lwres_buffer_putuint16(b, datalen);
+ lwres_buffer_putmem(b, (unsigned char *)req->aliases[x],
+ datalen);
+ lwres_buffer_putuint8(b, 0);
+ }
+
+ /* encode the addresses */
+ addr = LWRES_LIST_HEAD(req->addrs);
+ while (addr != NULL) {
+ lwres_buffer_putuint32(b, addr->family);
+ lwres_buffer_putuint16(b, addr->length);
+ lwres_buffer_putmem(b, addr->address, addr->length);
+ addr = LWRES_LIST_NEXT(addr, link);
+ }
+
+ INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
+ INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
+
+ return (LWRES_R_SUCCESS);
+}
+/*% Uses context ctx to convert the contents of packet pkt to a lwres_gabnrequest_t structure. */
+lwres_result_t
+lwres_gabnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_gabnrequest_t **structp)
+{
+ int ret;
+ char *name;
+ lwres_gabnrequest_t *gabn;
+ lwres_uint32_t addrtypes;
+ lwres_uint32_t flags;
+ lwres_uint16_t namelen;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
+ return (LWRES_R_FAILURE);
+
+ if (!SPACE_REMAINING(b, 4 + 4))
+ return (LWRES_R_UNEXPECTEDEND);
+
+ flags = lwres_buffer_getuint32(b);
+ addrtypes = lwres_buffer_getuint32(b);
+
+ /*
+ * Pull off the name itself
+ */
+ ret = lwres_string_parse(b, &name, &namelen);
+ if (ret != LWRES_R_SUCCESS)
+ return (ret);
+
+ if (LWRES_BUFFER_REMAINING(b) != 0)
+ return (LWRES_R_TRAILINGDATA);
+
+ gabn = CTXMALLOC(sizeof(lwres_gabnrequest_t));
+ if (gabn == NULL)
+ return (LWRES_R_NOMEMORY);
+
+ gabn->flags = flags;
+ gabn->addrtypes = addrtypes;
+ gabn->name = name;
+ gabn->namelen = namelen;
+
+ *structp = gabn;
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Offers the same semantics as lwres_gabnrequest_parse() except it yields a lwres_gabnresponse_t structure. */
+
+lwres_result_t
+lwres_gabnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_gabnresponse_t **structp)
+{
+ lwres_result_t ret;
+ unsigned int x;
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ lwres_uint16_t naddrs;
+ lwres_gabnresponse_t *gabn;
+ lwres_addrlist_t addrlist;
+ lwres_addr_t *addr;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ gabn = NULL;
+
+ if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
+ return (LWRES_R_FAILURE);
+
+ /*
+ * Pull off the name itself
+ */
+ if (!SPACE_REMAINING(b, 4 + 2 + 2))
+ return (LWRES_R_UNEXPECTEDEND);
+ flags = lwres_buffer_getuint32(b);
+ naliases = lwres_buffer_getuint16(b);
+ naddrs = lwres_buffer_getuint16(b);
+
+ gabn = CTXMALLOC(sizeof(lwres_gabnresponse_t));
+ if (gabn == NULL)
+ return (LWRES_R_NOMEMORY);
+ gabn->aliases = NULL;
+ gabn->aliaslen = NULL;
+ LWRES_LIST_INIT(gabn->addrs);
+ gabn->base = NULL;
+
+ gabn->flags = flags;
+ gabn->naliases = naliases;
+ gabn->naddrs = naddrs;
+
+ LWRES_LIST_INIT(addrlist);
+
+ if (naliases > 0) {
+ gabn->aliases = CTXMALLOC(sizeof(char *) * naliases);
+ if (gabn->aliases == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+
+ gabn->aliaslen = CTXMALLOC(sizeof(lwres_uint16_t) * naliases);
+ if (gabn->aliaslen == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+ }
+
+ for (x = 0; x < naddrs; x++) {
+ addr = CTXMALLOC(sizeof(lwres_addr_t));
+ if (addr == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+ LWRES_LINK_INIT(addr, link);
+ LWRES_LIST_APPEND(addrlist, addr, link);
+ }
+
+ /*
+ * Now, pull off the real name.
+ */
+ ret = lwres_string_parse(b, &gabn->realname, &gabn->realnamelen);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ /*
+ * Parse off the aliases.
+ */
+ for (x = 0; x < gabn->naliases; x++) {
+ ret = lwres_string_parse(b, &gabn->aliases[x],
+ &gabn->aliaslen[x]);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+ }
+
+ /*
+ * Pull off the addresses. We already strung the linked list
+ * up above.
+ */
+ addr = LWRES_LIST_HEAD(addrlist);
+ for (x = 0; x < gabn->naddrs; x++) {
+ INSIST(addr != NULL);
+ ret = lwres_addr_parse(b, addr);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+ addr = LWRES_LIST_NEXT(addr, link);
+ }
+
+ if (LWRES_BUFFER_REMAINING(b) != 0) {
+ ret = LWRES_R_TRAILINGDATA;
+ goto out;
+ }
+
+ gabn->addrs = addrlist;
+
+ *structp = gabn;
+ return (LWRES_R_SUCCESS);
+
+ out:
+ if (gabn != NULL) {
+ if (gabn->aliases != NULL)
+ CTXFREE(gabn->aliases, sizeof(char *) * naliases);
+ if (gabn->aliaslen != NULL)
+ CTXFREE(gabn->aliaslen,
+ sizeof(lwres_uint16_t) * naliases);
+ addr = LWRES_LIST_HEAD(addrlist);
+ while (addr != NULL) {
+ LWRES_LIST_UNLINK(addrlist, addr, link);
+ CTXFREE(addr, sizeof(lwres_addr_t));
+ addr = LWRES_LIST_HEAD(addrlist);
+ }
+ CTXFREE(gabn, sizeof(lwres_gabnresponse_t));
+ }
+
+ return (ret);
+}
+
+/*% Release the memory in resolver context ctx that was allocated to the lwres_gabnrequest_t. */
+void
+lwres_gabnrequest_free(lwres_context_t *ctx, lwres_gabnrequest_t **structp)
+{
+ lwres_gabnrequest_t *gabn;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(structp != NULL && *structp != NULL);
+
+ gabn = *structp;
+ *structp = NULL;
+
+ CTXFREE(gabn, sizeof(lwres_gabnrequest_t));
+}
+
+/*% Release the memory in resolver context ctx that was allocated to the lwres_gabnresponse_t. */
+void
+lwres_gabnresponse_free(lwres_context_t *ctx, lwres_gabnresponse_t **structp)
+{
+ lwres_gabnresponse_t *gabn;
+ lwres_addr_t *addr;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(structp != NULL && *structp != NULL);
+
+ gabn = *structp;
+ *structp = NULL;
+
+ if (gabn->naliases > 0) {
+ CTXFREE(gabn->aliases, sizeof(char *) * gabn->naliases);
+ CTXFREE(gabn->aliaslen,
+ sizeof(lwres_uint16_t) * gabn->naliases);
+ }
+ addr = LWRES_LIST_HEAD(gabn->addrs);
+ while (addr != NULL) {
+ LWRES_LIST_UNLINK(gabn->addrs, addr, link);
+ CTXFREE(addr, sizeof(lwres_addr_t));
+ addr = LWRES_LIST_HEAD(gabn->addrs);
+ }
+ if (gabn->base != NULL)
+ CTXFREE(gabn->base, gabn->baselen);
+ CTXFREE(gabn, sizeof(lwres_gabnresponse_t));
+}
diff --git a/lib/lwres/lwres_gnba.c b/lib/lwres/lwres_gnba.c
new file mode 100644
index 0000000..d18ae15
--- /dev/null
+++ b/lib/lwres/lwres_gnba.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: lwres_gnba.c,v 1.28 2007/09/24 17:18:25 each Exp $ */
+
+/*! \file lwres_gnba.c
+ These are low-level routines for creating and parsing lightweight
+ resolver address-to-name lookup request and response messages.
+
+ There are four main functions for the getnamebyaddr opcode. One
+ render function converts a getnamebyaddr request structure --
+ lwres_gnbarequest_t -- to the lightweight resolver's canonical
+ format. It is complemented by a parse function that converts a
+ packet in this canonical format to a getnamebyaddr request
+ structure. Another render function converts the getnamebyaddr
+ response structure -- lwres_gnbaresponse_t to the canonical format.
+ This is complemented by a parse function which converts a packet in
+ canonical format to a getnamebyaddr response structure.
+
+ These structures are defined in \link lwres.h <lwres/lwres.h.>\endlink They are shown
+ below.
+
+\code
+#define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
+
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_addr_t addr;
+} lwres_gnbarequest_t;
+
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ void *base;
+ size_t baselen;
+} lwres_gnbaresponse_t;
+\endcode
+
+ lwres_gnbarequest_render() uses resolver context ctx to convert
+ getnamebyaddr request structure req to canonical format. The packet
+ header structure pkt is initialised and transferred to buffer b.
+ The contents of *req are then appended to the buffer in canonical
+ format. lwres_gnbaresponse_render() performs the same task, except
+ it converts a getnamebyaddr response structure lwres_gnbaresponse_t
+ to the lightweight resolver's canonical format.
+
+ lwres_gnbarequest_parse() uses context ctx to convert the contents
+ of packet pkt to a lwres_gnbarequest_t structure. Buffer b provides
+ space to be used for storing this structure. When the function
+ succeeds, the resulting lwres_gnbarequest_t is made available
+ through *structp. lwres_gnbaresponse_parse() offers the same
+semantics as lwres_gnbarequest_parse() except it yields a
+ lwres_gnbaresponse_t structure.
+
+ lwres_gnbaresponse_free() and lwres_gnbarequest_free() release the
+ memory in resolver context ctx that was allocated to the
+ lwres_gnbaresponse_t or lwres_gnbarequest_t structures referenced
+ via structp. Any memory associated with ancillary buffers and
+ strings for those structures is also discarded.
+
+\section lwres_gbna_return Return Values
+
+ The getnamebyaddr opcode functions lwres_gnbarequest_render(),
+ lwres_gnbaresponse_render() lwres_gnbarequest_parse() and
+ lwres_gnbaresponse_parse() all return #LWRES_R_SUCCESS on success.
+ They return #LWRES_R_NOMEMORY if memory allocation fails.
+ #LWRES_R_UNEXPECTEDEND is returned if the available space in the
+ buffer b is too small to accommodate the packet header or the
+ lwres_gnbarequest_t and lwres_gnbaresponse_t structures.
+ lwres_gnbarequest_parse() and lwres_gnbaresponse_parse() will
+ return #LWRES_R_UNEXPECTEDEND if the buffer is not empty after
+ decoding the received packet. These functions will return
+ #LWRES_R_FAILURE if pktflags in the packet header structure
+ #lwres_lwpacket_t indicate that the packet is not a response to an
+ earlier query.
+
+\section lwres_gbna_see See Also
+
+ \link lwpacket.c lwres_packet\endlink
+
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <lwres/lwbuffer.h>
+#include <lwres/lwpacket.h>
+#include <lwres/lwres.h>
+#include <lwres/result.h>
+
+#include "context_p.h"
+#include "assert_p.h"
+
+/*% Uses resolver context ctx to convert getnamebyaddr request structure req to canonical format. */
+lwres_result_t
+lwres_gnbarequest_render(lwres_context_t *ctx, lwres_gnbarequest_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b)
+{
+ unsigned char *buf;
+ size_t buflen;
+ int ret;
+ size_t payload_length;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(req != NULL);
+ REQUIRE(req->addr.family != 0);
+ REQUIRE(req->addr.length != 0);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+
+ payload_length = 4 + 4 + 2 + + req->addr.length;
+
+ buflen = LWRES_LWPACKET_LENGTH + payload_length;
+ buf = CTXMALLOC(buflen);
+ if (buf == NULL)
+ return (LWRES_R_NOMEMORY);
+ lwres_buffer_init(b, buf, buflen);
+
+ pkt->length = buflen;
+ pkt->version = LWRES_LWPACKETVERSION_0;
+ pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
+ pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR;
+ pkt->result = 0;
+ pkt->authtype = 0;
+ pkt->authlength = 0;
+
+ ret = lwres_lwpacket_renderheader(b, pkt);
+ if (ret != LWRES_R_SUCCESS) {
+ lwres_buffer_invalidate(b);
+ CTXFREE(buf, buflen);
+ return (ret);
+ }
+
+ INSIST(SPACE_OK(b, payload_length));
+
+ /*
+ * Put the length and the data. We know this will fit because we
+ * just checked for it.
+ */
+ lwres_buffer_putuint32(b, req->flags);
+ lwres_buffer_putuint32(b, req->addr.family);
+ lwres_buffer_putuint16(b, req->addr.length);
+ lwres_buffer_putmem(b, (unsigned char *)req->addr.address,
+ req->addr.length);
+
+ INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Converts a getnamebyaddr response structure lwres_gnbaresponse_t to the lightweight resolver's canonical format. */
+lwres_result_t
+lwres_gnbaresponse_render(lwres_context_t *ctx, lwres_gnbaresponse_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b)
+{
+ unsigned char *buf;
+ size_t buflen;
+ int ret;
+ size_t payload_length;
+ lwres_uint16_t datalen;
+ int x;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(req != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+
+ /*
+ * Calculate packet size.
+ */
+ payload_length = 4; /* flags */
+ payload_length += 2; /* naliases */
+ payload_length += 2 + req->realnamelen + 1; /* real name encoding */
+ for (x = 0; x < req->naliases; x++) /* each alias */
+ payload_length += 2 + req->aliaslen[x] + 1;
+
+ buflen = LWRES_LWPACKET_LENGTH + payload_length;
+ buf = CTXMALLOC(buflen);
+ if (buf == NULL)
+ return (LWRES_R_NOMEMORY);
+ lwres_buffer_init(b, buf, buflen);
+
+ pkt->length = buflen;
+ pkt->version = LWRES_LWPACKETVERSION_0;
+ pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
+ pkt->opcode = LWRES_OPCODE_GETNAMEBYADDR;
+ pkt->authtype = 0;
+ pkt->authlength = 0;
+
+ ret = lwres_lwpacket_renderheader(b, pkt);
+ if (ret != LWRES_R_SUCCESS) {
+ lwres_buffer_invalidate(b);
+ CTXFREE(buf, buflen);
+ return (ret);
+ }
+
+ INSIST(SPACE_OK(b, payload_length));
+ lwres_buffer_putuint32(b, req->flags);
+
+ /* encode naliases */
+ lwres_buffer_putuint16(b, req->naliases);
+
+ /* encode the real name */
+ datalen = req->realnamelen;
+ lwres_buffer_putuint16(b, datalen);
+ lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
+ lwres_buffer_putuint8(b, 0);
+
+ /* encode the aliases */
+ for (x = 0; x < req->naliases; x++) {
+ datalen = req->aliaslen[x];
+ lwres_buffer_putuint16(b, datalen);
+ lwres_buffer_putmem(b, (unsigned char *)req->aliases[x],
+ datalen);
+ lwres_buffer_putuint8(b, 0);
+ }
+
+ INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Uses context ctx to convert the contents of packet pkt to a lwres_gnbarequest_t structure. */
+lwres_result_t
+lwres_gnbarequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_gnbarequest_t **structp)
+{
+ int ret;
+ lwres_gnbarequest_t *gnba;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
+ return (LWRES_R_FAILURE);
+
+ if (!SPACE_REMAINING(b, 4))
+ return (LWRES_R_UNEXPECTEDEND);
+
+ gnba = CTXMALLOC(sizeof(lwres_gnbarequest_t));
+ if (gnba == NULL)
+ return (LWRES_R_NOMEMORY);
+
+ gnba->flags = lwres_buffer_getuint32(b);
+
+ ret = lwres_addr_parse(b, &gnba->addr);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ if (LWRES_BUFFER_REMAINING(b) != 0) {
+ ret = LWRES_R_TRAILINGDATA;
+ goto out;
+ }
+
+ *structp = gnba;
+ return (LWRES_R_SUCCESS);
+
+ out:
+ if (gnba != NULL)
+ lwres_gnbarequest_free(ctx, &gnba);
+
+ return (ret);
+}
+
+/*% Offers the same semantics as lwres_gnbarequest_parse() except it yields a lwres_gnbaresponse_t structure. */
+
+lwres_result_t
+lwres_gnbaresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_gnbaresponse_t **structp)
+{
+ int ret;
+ unsigned int x;
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ lwres_gnbaresponse_t *gnba;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ gnba = NULL;
+
+ if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
+ return (LWRES_R_FAILURE);
+
+ /*
+ * Pull off flags & naliases
+ */
+ if (!SPACE_REMAINING(b, 4 + 2))
+ return (LWRES_R_UNEXPECTEDEND);
+ flags = lwres_buffer_getuint32(b);
+ naliases = lwres_buffer_getuint16(b);
+
+ gnba = CTXMALLOC(sizeof(lwres_gnbaresponse_t));
+ if (gnba == NULL)
+ return (LWRES_R_NOMEMORY);
+ gnba->base = NULL;
+ gnba->aliases = NULL;
+ gnba->aliaslen = NULL;
+
+ gnba->flags = flags;
+ gnba->naliases = naliases;
+
+ if (naliases > 0) {
+ gnba->aliases = CTXMALLOC(sizeof(char *) * naliases);
+ if (gnba->aliases == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+
+ gnba->aliaslen = CTXMALLOC(sizeof(lwres_uint16_t) * naliases);
+ if (gnba->aliaslen == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+ }
+
+ /*
+ * Now, pull off the real name.
+ */
+ ret = lwres_string_parse(b, &gnba->realname, &gnba->realnamelen);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ /*
+ * Parse off the aliases.
+ */
+ for (x = 0; x < gnba->naliases; x++) {
+ ret = lwres_string_parse(b, &gnba->aliases[x],
+ &gnba->aliaslen[x]);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+ }
+
+ if (LWRES_BUFFER_REMAINING(b) != 0) {
+ ret = LWRES_R_TRAILINGDATA;
+ goto out;
+ }
+
+ *structp = gnba;
+ return (LWRES_R_SUCCESS);
+
+ out:
+ if (gnba != NULL) {
+ if (gnba->aliases != NULL)
+ CTXFREE(gnba->aliases, sizeof(char *) * naliases);
+ if (gnba->aliaslen != NULL)
+ CTXFREE(gnba->aliaslen,
+ sizeof(lwres_uint16_t) * naliases);
+ CTXFREE(gnba, sizeof(lwres_gnbaresponse_t));
+ }
+
+ return (ret);
+}
+
+/*% Release the memory in resolver context ctx that was allocated to the lwres_gnbarequest_t. */
+void
+lwres_gnbarequest_free(lwres_context_t *ctx, lwres_gnbarequest_t **structp)
+{
+ lwres_gnbarequest_t *gnba;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(structp != NULL && *structp != NULL);
+
+ gnba = *structp;
+ *structp = NULL;
+
+ CTXFREE(gnba, sizeof(lwres_gnbarequest_t));
+}
+
+/*% Release the memory in resolver context ctx that was allocated to the lwres_gnbaresponse_t. */
+void
+lwres_gnbaresponse_free(lwres_context_t *ctx, lwres_gnbaresponse_t **structp)
+{
+ lwres_gnbaresponse_t *gnba;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(structp != NULL && *structp != NULL);
+
+ gnba = *structp;
+ *structp = NULL;
+
+ if (gnba->naliases > 0) {
+ CTXFREE(gnba->aliases, sizeof(char *) * gnba->naliases);
+ CTXFREE(gnba->aliaslen,
+ sizeof(lwres_uint16_t) * gnba->naliases);
+ }
+ if (gnba->base != NULL)
+ CTXFREE(gnba->base, gnba->baselen);
+ CTXFREE(gnba, sizeof(lwres_gnbaresponse_t));
+}
diff --git a/lib/lwres/lwres_grbn.c b/lib/lwres/lwres_grbn.c
new file mode 100644
index 0000000..72718ba
--- /dev/null
+++ b/lib/lwres/lwres_grbn.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwres_grbn.c,v 1.10 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file lwres_grbn.c
+
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <lwres/lwbuffer.h>
+#include <lwres/lwpacket.h>
+#include <lwres/lwres.h>
+#include <lwres/result.h>
+
+#include "context_p.h"
+#include "assert_p.h"
+
+/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
+lwres_result_t
+lwres_grbnrequest_render(lwres_context_t *ctx, lwres_grbnrequest_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b)
+{
+ unsigned char *buf;
+ size_t buflen;
+ int ret;
+ size_t payload_length;
+ lwres_uint16_t datalen;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(req != NULL);
+ REQUIRE(req->name != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+
+ datalen = strlen(req->name);
+
+ payload_length = 4 + 2 + 2 + 2 + req->namelen + 1;
+
+ buflen = LWRES_LWPACKET_LENGTH + payload_length;
+ buf = CTXMALLOC(buflen);
+ if (buf == NULL)
+ return (LWRES_R_NOMEMORY);
+
+ lwres_buffer_init(b, buf, buflen);
+
+ pkt->length = buflen;
+ pkt->version = LWRES_LWPACKETVERSION_0;
+ pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
+ pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
+ pkt->result = 0;
+ pkt->authtype = 0;
+ pkt->authlength = 0;
+
+ ret = lwres_lwpacket_renderheader(b, pkt);
+ if (ret != LWRES_R_SUCCESS) {
+ lwres_buffer_invalidate(b);
+ CTXFREE(buf, buflen);
+ return (ret);
+ }
+
+ INSIST(SPACE_OK(b, payload_length));
+
+ /*
+ * Flags.
+ */
+ lwres_buffer_putuint32(b, req->flags);
+
+ /*
+ * Class.
+ */
+ lwres_buffer_putuint16(b, req->rdclass);
+
+ /*
+ * Type.
+ */
+ lwres_buffer_putuint16(b, req->rdtype);
+
+ /*
+ * Put the length and the data. We know this will fit because we
+ * just checked for it.
+ */
+ lwres_buffer_putuint16(b, datalen);
+ lwres_buffer_putmem(b, (unsigned char *)req->name, datalen);
+ lwres_buffer_putuint8(b, 0); /* trailing NUL */
+
+ INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
+lwres_result_t
+lwres_grbnresponse_render(lwres_context_t *ctx, lwres_grbnresponse_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b)
+{
+ unsigned char *buf;
+ size_t buflen;
+ int ret;
+ size_t payload_length;
+ lwres_uint16_t datalen;
+ int x;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(req != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+
+ /* flags, class, type, ttl, nrdatas, nsigs */
+ payload_length = 4 + 2 + 2 + 4 + 2 + 2;
+ /* real name encoding */
+ payload_length += 2 + req->realnamelen + 1;
+ /* each rr */
+ for (x = 0; x < req->nrdatas; x++)
+ payload_length += 2 + req->rdatalen[x];
+ for (x = 0; x < req->nsigs; x++)
+ payload_length += 2 + req->siglen[x];
+
+ buflen = LWRES_LWPACKET_LENGTH + payload_length;
+ buf = CTXMALLOC(buflen);
+ if (buf == NULL)
+ return (LWRES_R_NOMEMORY);
+ lwres_buffer_init(b, buf, buflen);
+
+ pkt->length = buflen;
+ pkt->version = LWRES_LWPACKETVERSION_0;
+ pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
+ pkt->opcode = LWRES_OPCODE_GETRDATABYNAME;
+ pkt->authtype = 0;
+ pkt->authlength = 0;
+
+ ret = lwres_lwpacket_renderheader(b, pkt);
+ if (ret != LWRES_R_SUCCESS) {
+ lwres_buffer_invalidate(b);
+ CTXFREE(buf, buflen);
+ return (ret);
+ }
+
+ /*
+ * Check space needed here.
+ */
+ INSIST(SPACE_OK(b, payload_length));
+
+ /* Flags. */
+ lwres_buffer_putuint32(b, req->flags);
+
+ /* encode class, type, ttl, and nrdatas */
+ lwres_buffer_putuint16(b, req->rdclass);
+ lwres_buffer_putuint16(b, req->rdtype);
+ lwres_buffer_putuint32(b, req->ttl);
+ lwres_buffer_putuint16(b, req->nrdatas);
+ lwres_buffer_putuint16(b, req->nsigs);
+
+ /* encode the real name */
+ datalen = req->realnamelen;
+ lwres_buffer_putuint16(b, datalen);
+ lwres_buffer_putmem(b, (unsigned char *)req->realname, datalen);
+ lwres_buffer_putuint8(b, 0);
+
+ /* encode the rdatas */
+ for (x = 0; x < req->nrdatas; x++) {
+ datalen = req->rdatalen[x];
+ lwres_buffer_putuint16(b, datalen);
+ lwres_buffer_putmem(b, req->rdatas[x], datalen);
+ }
+
+ /* encode the signatures */
+ for (x = 0; x < req->nsigs; x++) {
+ datalen = req->siglen[x];
+ lwres_buffer_putuint16(b, datalen);
+ lwres_buffer_putmem(b, req->sigs[x], datalen);
+ }
+
+ INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
+ INSIST(LWRES_BUFFER_USEDCOUNT(b) == pkt->length);
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
+lwres_result_t
+lwres_grbnrequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_grbnrequest_t **structp)
+{
+ int ret;
+ char *name;
+ lwres_grbnrequest_t *grbn;
+ lwres_uint32_t flags;
+ lwres_uint16_t rdclass, rdtype;
+ lwres_uint16_t namelen;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
+ return (LWRES_R_FAILURE);
+
+ if (!SPACE_REMAINING(b, 4 + 2 + 2))
+ return (LWRES_R_UNEXPECTEDEND);
+
+ /*
+ * Pull off the flags, class, and type.
+ */
+ flags = lwres_buffer_getuint32(b);
+ rdclass = lwres_buffer_getuint16(b);
+ rdtype = lwres_buffer_getuint16(b);
+
+ /*
+ * Pull off the name itself
+ */
+ ret = lwres_string_parse(b, &name, &namelen);
+ if (ret != LWRES_R_SUCCESS)
+ return (ret);
+
+ if (LWRES_BUFFER_REMAINING(b) != 0)
+ return (LWRES_R_TRAILINGDATA);
+
+ grbn = CTXMALLOC(sizeof(lwres_grbnrequest_t));
+ if (grbn == NULL)
+ return (LWRES_R_NOMEMORY);
+
+ grbn->flags = flags;
+ grbn->rdclass = rdclass;
+ grbn->rdtype = rdtype;
+ grbn->name = name;
+ grbn->namelen = namelen;
+
+ *structp = grbn;
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
+lwres_result_t
+lwres_grbnresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_grbnresponse_t **structp)
+{
+ lwres_result_t ret;
+ unsigned int x;
+ lwres_uint32_t flags;
+ lwres_uint16_t rdclass, rdtype;
+ lwres_uint32_t ttl;
+ lwres_uint16_t nrdatas, nsigs;
+ lwres_grbnresponse_t *grbn;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ grbn = NULL;
+
+ if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
+ return (LWRES_R_FAILURE);
+
+ /*
+ * Pull off the flags, class, type, ttl, nrdatas, and nsigs
+ */
+ if (!SPACE_REMAINING(b, 4 + 2 + 2 + 4 + 2 + 2))
+ return (LWRES_R_UNEXPECTEDEND);
+ flags = lwres_buffer_getuint32(b);
+ rdclass = lwres_buffer_getuint16(b);
+ rdtype = lwres_buffer_getuint16(b);
+ ttl = lwres_buffer_getuint32(b);
+ nrdatas = lwres_buffer_getuint16(b);
+ nsigs = lwres_buffer_getuint16(b);
+
+ /*
+ * Pull off the name itself
+ */
+
+ grbn = CTXMALLOC(sizeof(lwres_grbnresponse_t));
+ if (grbn == NULL)
+ return (LWRES_R_NOMEMORY);
+ grbn->rdatas = NULL;
+ grbn->rdatalen = NULL;
+ grbn->sigs = NULL;
+ grbn->siglen = NULL;
+ grbn->base = NULL;
+
+ grbn->flags = flags;
+ grbn->rdclass = rdclass;
+ grbn->rdtype = rdtype;
+ grbn->ttl = ttl;
+ grbn->nrdatas = nrdatas;
+ grbn->nsigs = nsigs;
+
+ if (nrdatas > 0) {
+ grbn->rdatas = CTXMALLOC(sizeof(char *) * nrdatas);
+ if (grbn->rdatas == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+
+ grbn->rdatalen = CTXMALLOC(sizeof(lwres_uint16_t) * nrdatas);
+ if (grbn->rdatalen == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+ }
+
+ if (nsigs > 0) {
+ grbn->sigs = CTXMALLOC(sizeof(char *) * nsigs);
+ if (grbn->sigs == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+
+ grbn->siglen = CTXMALLOC(sizeof(lwres_uint16_t) * nsigs);
+ if (grbn->siglen == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+ }
+
+ /*
+ * Now, pull off the real name.
+ */
+ ret = lwres_string_parse(b, &grbn->realname, &grbn->realnamelen);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ /*
+ * Parse off the rdatas.
+ */
+ for (x = 0; x < grbn->nrdatas; x++) {
+ ret = lwres_data_parse(b, &grbn->rdatas[x],
+ &grbn->rdatalen[x]);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+ }
+
+ /*
+ * Parse off the signatures.
+ */
+ for (x = 0; x < grbn->nsigs; x++) {
+ ret = lwres_data_parse(b, &grbn->sigs[x], &grbn->siglen[x]);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+ }
+
+ if (LWRES_BUFFER_REMAINING(b) != 0) {
+ ret = LWRES_R_TRAILINGDATA;
+ goto out;
+ }
+
+ *structp = grbn;
+ return (LWRES_R_SUCCESS);
+
+ out:
+ if (grbn != NULL) {
+ if (grbn->rdatas != NULL)
+ CTXFREE(grbn->rdatas, sizeof(char *) * nrdatas);
+ if (grbn->rdatalen != NULL)
+ CTXFREE(grbn->rdatalen,
+ sizeof(lwres_uint16_t) * nrdatas);
+ if (grbn->sigs != NULL)
+ CTXFREE(grbn->sigs, sizeof(char *) * nsigs);
+ if (grbn->siglen != NULL)
+ CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * nsigs);
+ CTXFREE(grbn, sizeof(lwres_grbnresponse_t));
+ }
+
+ return (ret);
+}
+
+/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
+void
+lwres_grbnrequest_free(lwres_context_t *ctx, lwres_grbnrequest_t **structp)
+{
+ lwres_grbnrequest_t *grbn;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(structp != NULL && *structp != NULL);
+
+ grbn = *structp;
+ *structp = NULL;
+
+ CTXFREE(grbn, sizeof(lwres_grbnrequest_t));
+}
+
+/*% Thread-save equivalent to \link lwres_gabn.c lwres_gabn* \endlink routines. */
+void
+lwres_grbnresponse_free(lwres_context_t *ctx, lwres_grbnresponse_t **structp)
+{
+ lwres_grbnresponse_t *grbn;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(structp != NULL && *structp != NULL);
+
+ grbn = *structp;
+ *structp = NULL;
+
+ if (grbn->nrdatas > 0) {
+ CTXFREE(grbn->rdatas, sizeof(char *) * grbn->nrdatas);
+ CTXFREE(grbn->rdatalen,
+ sizeof(lwres_uint16_t) * grbn->nrdatas);
+ }
+ if (grbn->nsigs > 0) {
+ CTXFREE(grbn->sigs, sizeof(char *) * grbn->nsigs);
+ CTXFREE(grbn->siglen, sizeof(lwres_uint16_t) * grbn->nsigs);
+ }
+ if (grbn->base != NULL)
+ CTXFREE(grbn->base, grbn->baselen);
+ CTXFREE(grbn, sizeof(lwres_grbnresponse_t));
+}
diff --git a/lib/lwres/lwres_noop.c b/lib/lwres/lwres_noop.c
new file mode 100644
index 0000000..369fe4e
--- /dev/null
+++ b/lib/lwres/lwres_noop.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwres_noop.c,v 1.19 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+/**
+ * These are low-level routines for creating and parsing lightweight
+ * resolver no-op request and response messages.
+ *
+ * The no-op message is analogous to a ping packet: a packet is sent to
+ * the resolver daemon and is simply echoed back. The opcode is intended
+ * to allow a client to determine if the server is operational or not.
+ *
+ * There are four main functions for the no-op opcode. One render
+ * function converts a no-op request structure -- lwres_nooprequest_t --
+ * to the lighweight resolver's canonical format. It is complemented by a
+ * parse function that converts a packet in this canonical format to a
+ * no-op request structure. Another render function converts the no-op
+ * response structure -- lwres_noopresponse_t to the canonical format.
+ * This is complemented by a parse function which converts a packet in
+ * canonical format to a no-op response structure.
+ *
+ * These structures are defined in \link lwres.h <lwres/lwres.h.> \endlink They are shown below.
+ *
+ * \code
+ * #define LWRES_OPCODE_NOOP 0x00000000U
+ *
+ * typedef struct {
+ * lwres_uint16_t datalength;
+ * unsigned char *data;
+ * } lwres_nooprequest_t;
+ *
+ * typedef struct {
+ * lwres_uint16_t datalength;
+ * unsigned char *data;
+ * } lwres_noopresponse_t;
+ * \endcode
+ *
+ * Although the structures have different types, they are identical. This
+ * is because the no-op opcode simply echos whatever data was sent: the
+ * response is therefore identical to the request.
+ *
+ * lwres_nooprequest_render() uses resolver context ctx to convert no-op
+ * request structure req to canonical format. The packet header structure
+ * pkt is initialised and transferred to buffer b. The contents of *req
+ * are then appended to the buffer in canonical format.
+ * lwres_noopresponse_render() performs the same task, except it converts
+ * a no-op response structure lwres_noopresponse_t to the lightweight
+ * resolver's canonical format.
+ *
+ * lwres_nooprequest_parse() uses context ctx to convert the contents of
+ * packet pkt to a lwres_nooprequest_t structure. Buffer b provides space
+ * to be used for storing this structure. When the function succeeds, the
+ * resulting lwres_nooprequest_t is made available through *structp.
+ * lwres_noopresponse_parse() offers the same semantics as
+ * lwres_nooprequest_parse() except it yields a lwres_noopresponse_t
+ * structure.
+ *
+ * lwres_noopresponse_free() and lwres_nooprequest_free() release the
+ * memory in resolver context ctx that was allocated to the
+ * lwres_noopresponse_t or lwres_nooprequest_t structures referenced via
+ * structp.
+ *
+ * \section lwres_noop_return Return Values
+ *
+ * The no-op opcode functions lwres_nooprequest_render(),
+ * lwres_noopresponse_render() lwres_nooprequest_parse() and
+ * lwres_noopresponse_parse() all return #LWRES_R_SUCCESS on success. They
+ * return #LWRES_R_NOMEMORY if memory allocation fails.
+ * #LWRES_R_UNEXPECTEDEND is returned if the available space in the buffer
+ * b is too small to accommodate the packet header or the
+ * lwres_nooprequest_t and lwres_noopresponse_t structures.
+ * lwres_nooprequest_parse() and lwres_noopresponse_parse() will return
+ * #LWRES_R_UNEXPECTEDEND if the buffer is not empty after decoding the
+ * received packet. These functions will return #LWRES_R_FAILURE if
+ * pktflags in the packet header structure #lwres_lwpacket_t indicate that
+ * the packet is not a response to an earlier query.
+ *
+ * \section lwres_noop_see See Also
+ *
+ * lwpacket.c
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <lwres/lwbuffer.h>
+#include <lwres/lwpacket.h>
+#include <lwres/lwres.h>
+#include <lwres/result.h>
+
+#include "context_p.h"
+#include "assert_p.h"
+
+/*% Uses resolver context ctx to convert no-op request structure req to canonical format. */
+lwres_result_t
+lwres_nooprequest_render(lwres_context_t *ctx, lwres_nooprequest_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b)
+{
+ unsigned char *buf;
+ size_t buflen;
+ int ret;
+ size_t payload_length;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(req != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+
+ payload_length = sizeof(lwres_uint16_t) + req->datalength;
+
+ buflen = LWRES_LWPACKET_LENGTH + payload_length;
+ buf = CTXMALLOC(buflen);
+ if (buf == NULL)
+ return (LWRES_R_NOMEMORY);
+ lwres_buffer_init(b, buf, buflen);
+
+ pkt->length = buflen;
+ pkt->version = LWRES_LWPACKETVERSION_0;
+ pkt->pktflags &= ~LWRES_LWPACKETFLAG_RESPONSE;
+ pkt->opcode = LWRES_OPCODE_NOOP;
+ pkt->result = 0;
+ pkt->authtype = 0;
+ pkt->authlength = 0;
+
+ ret = lwres_lwpacket_renderheader(b, pkt);
+ if (ret != LWRES_R_SUCCESS) {
+ lwres_buffer_invalidate(b);
+ CTXFREE(buf, buflen);
+ return (ret);
+ }
+
+ INSIST(SPACE_OK(b, payload_length));
+
+ /*
+ * Put the length and the data. We know this will fit because we
+ * just checked for it.
+ */
+ lwres_buffer_putuint16(b, req->datalength);
+ lwres_buffer_putmem(b, req->data, req->datalength);
+
+ INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Converts a no-op response structure lwres_noopresponse_t to the lightweight resolver's canonical format. */
+
+lwres_result_t
+lwres_noopresponse_render(lwres_context_t *ctx, lwres_noopresponse_t *req,
+ lwres_lwpacket_t *pkt, lwres_buffer_t *b)
+{
+ unsigned char *buf;
+ size_t buflen;
+ int ret;
+ size_t payload_length;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(req != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(b != NULL);
+
+ payload_length = sizeof(lwres_uint16_t) + req->datalength;
+
+ buflen = LWRES_LWPACKET_LENGTH + payload_length;
+ buf = CTXMALLOC(buflen);
+ if (buf == NULL)
+ return (LWRES_R_NOMEMORY);
+ lwres_buffer_init(b, buf, buflen);
+
+ pkt->length = buflen;
+ pkt->version = LWRES_LWPACKETVERSION_0;
+ pkt->pktflags |= LWRES_LWPACKETFLAG_RESPONSE;
+ pkt->opcode = LWRES_OPCODE_NOOP;
+ pkt->authtype = 0;
+ pkt->authlength = 0;
+
+ ret = lwres_lwpacket_renderheader(b, pkt);
+ if (ret != LWRES_R_SUCCESS) {
+ lwres_buffer_invalidate(b);
+ CTXFREE(buf, buflen);
+ return (ret);
+ }
+
+ INSIST(SPACE_OK(b, payload_length));
+
+ /*
+ * Put the length and the data. We know this will fit because we
+ * just checked for it.
+ */
+ lwres_buffer_putuint16(b, req->datalength);
+ lwres_buffer_putmem(b, req->data, req->datalength);
+
+ INSIST(LWRES_BUFFER_AVAILABLECOUNT(b) == 0);
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Uses context ctx to convert the contents of packet pkt to a lwres_nooprequest_t structure. */
+lwres_result_t
+lwres_nooprequest_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_nooprequest_t **structp)
+{
+ int ret;
+ lwres_nooprequest_t *req;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(b != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) != 0)
+ return (LWRES_R_FAILURE);
+
+ req = CTXMALLOC(sizeof(lwres_nooprequest_t));
+ if (req == NULL)
+ return (LWRES_R_NOMEMORY);
+
+ if (!SPACE_REMAINING(b, sizeof(lwres_uint16_t))) {
+ ret = LWRES_R_UNEXPECTEDEND;
+ goto out;
+ }
+ req->datalength = lwres_buffer_getuint16(b);
+
+ if (!SPACE_REMAINING(b, req->datalength)) {
+ ret = LWRES_R_UNEXPECTEDEND;
+ goto out;
+ }
+ req->data = b->base + b->current;
+ lwres_buffer_forward(b, req->datalength);
+
+ if (LWRES_BUFFER_REMAINING(b) != 0) {
+ ret = LWRES_R_TRAILINGDATA;
+ goto out;
+ }
+
+ /* success! */
+ *structp = req;
+ return (LWRES_R_SUCCESS);
+
+ /* Error return */
+ out:
+ CTXFREE(req, sizeof(lwres_nooprequest_t));
+ return (ret);
+}
+
+/*% Offers the same semantics as lwres_nooprequest_parse() except it yields a lwres_noopresponse_t structure. */
+lwres_result_t
+lwres_noopresponse_parse(lwres_context_t *ctx, lwres_buffer_t *b,
+ lwres_lwpacket_t *pkt, lwres_noopresponse_t **structp)
+{
+ int ret;
+ lwres_noopresponse_t *req;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(b != NULL);
+ REQUIRE(pkt != NULL);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ if ((pkt->pktflags & LWRES_LWPACKETFLAG_RESPONSE) == 0)
+ return (LWRES_R_FAILURE);
+
+ req = CTXMALLOC(sizeof(lwres_noopresponse_t));
+ if (req == NULL)
+ return (LWRES_R_NOMEMORY);
+
+ if (!SPACE_REMAINING(b, sizeof(lwres_uint16_t))) {
+ ret = LWRES_R_UNEXPECTEDEND;
+ goto out;
+ }
+ req->datalength = lwres_buffer_getuint16(b);
+
+ if (!SPACE_REMAINING(b, req->datalength)) {
+ ret = LWRES_R_UNEXPECTEDEND;
+ goto out;
+ }
+ req->data = b->base + b->current;
+
+ lwres_buffer_forward(b, req->datalength);
+ if (LWRES_BUFFER_REMAINING(b) != 0) {
+ ret = LWRES_R_TRAILINGDATA;
+ goto out;
+ }
+
+ /* success! */
+ *structp = req;
+ return (LWRES_R_SUCCESS);
+
+ /* Error return */
+ out:
+ CTXFREE(req, sizeof(lwres_noopresponse_t));
+ return (ret);
+}
+
+/*% Release the memory in resolver context ctx. */
+void
+lwres_noopresponse_free(lwres_context_t *ctx, lwres_noopresponse_t **structp)
+{
+ lwres_noopresponse_t *noop;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(structp != NULL && *structp != NULL);
+
+ noop = *structp;
+ *structp = NULL;
+
+ CTXFREE(noop, sizeof(lwres_noopresponse_t));
+}
+
+/*% Release the memory in resolver context ctx. */
+void
+lwres_nooprequest_free(lwres_context_t *ctx, lwres_nooprequest_t **structp)
+{
+ lwres_nooprequest_t *noop;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(structp != NULL && *structp != NULL);
+
+ noop = *structp;
+ *structp = NULL;
+
+ CTXFREE(noop, sizeof(lwres_nooprequest_t));
+}
diff --git a/lib/lwres/lwresutil.c b/lib/lwres/lwresutil.c
new file mode 100644
index 0000000..3bf5660
--- /dev/null
+++ b/lib/lwres/lwresutil.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: lwresutil.c,v 1.34 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+/**
+ * lwres_string_parse() retrieves a DNS-encoded string starting the
+ * current pointer of lightweight resolver buffer b: i.e. b->current.
+ * When the function returns, the address of the first byte of the
+ * encoded string is returned via *c and the length of that string is
+ * given by *len. The buffer's current pointer is advanced to point at
+ * the character following the string length, the encoded string, and
+ * the trailing NULL character.
+ *
+ * lwres_addr_parse() extracts an address from the buffer b. The
+ * buffer's current pointer b->current is presumed to point at an
+ * encoded address: the address preceded by a 32-bit protocol family
+ * identifier and a 16-bit length field. The encoded address is copied
+ * to addr->address and addr->length indicates the size in bytes of
+ * the address that was copied. b->current is advanced to point at the
+ * next byte of available data in the buffer following the encoded
+ * address.
+ *
+ * lwres_getaddrsbyname() and lwres_getnamebyaddr() use the
+ * lwres_gnbaresponse_t structure defined below:
+ *
+ * \code
+ * typedef struct {
+ * lwres_uint32_t flags;
+ * lwres_uint16_t naliases;
+ * lwres_uint16_t naddrs;
+ * char *realname;
+ * char **aliases;
+ * lwres_uint16_t realnamelen;
+ * lwres_uint16_t *aliaslen;
+ * lwres_addrlist_t addrs;
+ * void *base;
+ * size_t baselen;
+ * } lwres_gabnresponse_t;
+ * \endcode
+ *
+ * The contents of this structure are not manipulated directly but
+ * they are controlled through the \link lwres_gabn.c lwres_gabn*\endlink functions.
+ *
+ * The lightweight resolver uses lwres_getaddrsbyname() to perform
+ * foward lookups. Hostname name is looked up using the resolver
+ * context ctx for memory allocation. addrtypes is a bitmask
+ * indicating which type of addresses are to be looked up. Current
+ * values for this bitmask are #LWRES_ADDRTYPE_V4 for IPv4 addresses
+ * and #LWRES_ADDRTYPE_V6 for IPv6 addresses. Results of the lookup are
+ * returned in *structp.
+ *
+ * lwres_getnamebyaddr() performs reverse lookups. Resolver context
+ * ctx is used for memory allocation. The address type is indicated by
+ * addrtype: #LWRES_ADDRTYPE_V4 or #LWRES_ADDRTYPE_V6. The address to be
+ * looked up is given by addr and its length is addrlen bytes. The
+ * result of the function call is made available through *structp.
+ *
+ * \section lwresutil_return Return Values
+ *
+ * Successful calls to lwres_string_parse() and lwres_addr_parse()
+ * return #LWRES_R_SUCCESS. Both functions return #LWRES_R_FAILURE if
+ * the buffer is corrupt or #LWRES_R_UNEXPECTEDEND if the buffer has
+ * less space than expected for the components of the encoded string
+ * or address.
+ *
+ * lwres_getaddrsbyname() returns #LWRES_R_SUCCESS on success and it
+ * returns #LWRES_R_NOTFOUND if the hostname name could not be found.
+ *
+ * #LWRES_R_SUCCESS is returned by a successful call to
+ * lwres_getnamebyaddr().
+ *
+ * Both lwres_getaddrsbyname() and lwres_getnamebyaddr() return
+ * #LWRES_R_NOMEMORY when memory allocation requests fail and
+ * #LWRES_R_UNEXPECTEDEND if the buffers used for sending queries and
+ * receiving replies are too small.
+ *
+ * \section lwresutil_see See Also
+ *
+ * lwbuffer.c, lwres_gabn.c
+ */
+
+#include <config.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <lwres/lwbuffer.h>
+#include <lwres/lwres.h>
+#include <lwres/result.h>
+
+#include "assert_p.h"
+#include "context_p.h"
+
+/*% Parse data. */
+/*!
+ * Requires:
+ *
+ * The "current" pointer in "b" points to encoded raw data.
+ *
+ * Ensures:
+ *
+ * The address of the first byte of the data is returned via "p",
+ * and the length is returned via "len". If NULL, they are not
+ * set.
+ *
+ * On return, the current pointer of "b" will point to the character
+ * following the data length and the data.
+ *
+ */
+lwres_result_t
+lwres_data_parse(lwres_buffer_t *b, unsigned char **p, lwres_uint16_t *len)
+{
+ lwres_uint16_t datalen;
+ unsigned char *data;
+
+ REQUIRE(b != NULL);
+
+ /*
+ * Pull off the length (2 bytes)
+ */
+ if (!SPACE_REMAINING(b, 2))
+ return (LWRES_R_UNEXPECTEDEND);
+ datalen = lwres_buffer_getuint16(b);
+
+ /*
+ * Set the pointer to this string to the right place, then
+ * advance the buffer pointer.
+ */
+ if (!SPACE_REMAINING(b, datalen))
+ return (LWRES_R_UNEXPECTEDEND);
+ data = b->base + b->current;
+ lwres_buffer_forward(b, datalen);
+
+ if (len != NULL)
+ *len = datalen;
+ if (p != NULL)
+ *p = data;
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Retrieves a DNS-encoded string. */
+/*!
+ * Requires:
+ *
+ * The "current" pointer in "b" point to an encoded string.
+ *
+ * Ensures:
+ *
+ * The address of the first byte of the string is returned via "c",
+ * and the length is returned via "len". If NULL, they are not
+ * set.
+ *
+ * On return, the current pointer of "b" will point to the character
+ * following the string length, the string, and the trailing NULL.
+ *
+ */
+lwres_result_t
+lwres_string_parse(lwres_buffer_t *b, char **c, lwres_uint16_t *len)
+{
+ lwres_uint16_t datalen;
+ char *string;
+
+ REQUIRE(b != NULL);
+
+ /*
+ * Pull off the length (2 bytes)
+ */
+ if (!SPACE_REMAINING(b, 2))
+ return (LWRES_R_UNEXPECTEDEND);
+ datalen = lwres_buffer_getuint16(b);
+
+ /*
+ * Set the pointer to this string to the right place, then
+ * advance the buffer pointer.
+ */
+ if (!SPACE_REMAINING(b, datalen))
+ return (LWRES_R_UNEXPECTEDEND);
+ string = (char *)b->base + b->current;
+ lwres_buffer_forward(b, datalen);
+
+ /*
+ * Skip the "must be zero" byte.
+ */
+ if (!SPACE_REMAINING(b, 1))
+ return (LWRES_R_UNEXPECTEDEND);
+ if (0 != lwres_buffer_getuint8(b))
+ return (LWRES_R_FAILURE);
+
+ if (len != NULL)
+ *len = datalen;
+ if (c != NULL)
+ *c = string;
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Extracts an address from the buffer b. */
+lwres_result_t
+lwres_addr_parse(lwres_buffer_t *b, lwres_addr_t *addr)
+{
+ REQUIRE(addr != NULL);
+
+ if (!SPACE_REMAINING(b, 6))
+ return (LWRES_R_UNEXPECTEDEND);
+
+ addr->family = lwres_buffer_getuint32(b);
+ addr->length = lwres_buffer_getuint16(b);
+
+ if (!SPACE_REMAINING(b, addr->length))
+ return (LWRES_R_UNEXPECTEDEND);
+ if (addr->length > LWRES_ADDR_MAXLEN)
+ return (LWRES_R_FAILURE);
+
+ lwres_buffer_getmem(b, addr->address, addr->length);
+
+ return (LWRES_R_SUCCESS);
+}
+
+/*% Used to perform forward lookups. */
+lwres_result_t
+lwres_getaddrsbyname(lwres_context_t *ctx, const char *name,
+ lwres_uint32_t addrtypes, lwres_gabnresponse_t **structp)
+{
+ lwres_gabnrequest_t request;
+ lwres_gabnresponse_t *response;
+ int ret;
+ int recvlen;
+ lwres_buffer_t b_in, b_out;
+ lwres_lwpacket_t pkt;
+ lwres_uint32_t serial;
+ char *buffer;
+ char target_name[1024];
+ unsigned int target_length;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(addrtypes != 0);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ b_in.base = NULL;
+ b_out.base = NULL;
+ response = NULL;
+ buffer = NULL;
+ serial = lwres_context_nextserial(ctx);
+
+ buffer = CTXMALLOC(LWRES_RECVLENGTH);
+ if (buffer == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+
+ target_length = strlen(name);
+ if (target_length >= sizeof(target_name))
+ return (LWRES_R_FAILURE);
+ strcpy(target_name, name); /* strcpy is safe */
+
+ /*
+ * Set up our request and render it to a buffer.
+ */
+ request.flags = 0;
+ request.addrtypes = addrtypes;
+ request.name = target_name;
+ request.namelen = target_length;
+ pkt.pktflags = 0;
+ pkt.serial = serial;
+ pkt.result = 0;
+ pkt.recvlength = LWRES_RECVLENGTH;
+
+ again:
+ ret = lwres_gabnrequest_render(ctx, &request, &pkt, &b_out);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer,
+ LWRES_RECVLENGTH, &recvlen);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ lwres_buffer_init(&b_in, buffer, recvlen);
+ b_in.used = recvlen;
+
+ /*
+ * Parse the packet header.
+ */
+ ret = lwres_lwpacket_parseheader(&b_in, &pkt);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ /*
+ * Sanity check.
+ */
+ if (pkt.serial != serial)
+ goto again;
+ if (pkt.opcode != LWRES_OPCODE_GETADDRSBYNAME)
+ goto again;
+
+ /*
+ * Free what we've transmitted
+ */
+ CTXFREE(b_out.base, b_out.length);
+ b_out.base = NULL;
+ b_out.length = 0;
+
+ if (pkt.result != LWRES_R_SUCCESS) {
+ ret = pkt.result;
+ goto out;
+ }
+
+ /*
+ * Parse the response.
+ */
+ ret = lwres_gabnresponse_parse(ctx, &b_in, &pkt, &response);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+ response->base = buffer;
+ response->baselen = LWRES_RECVLENGTH;
+ buffer = NULL; /* don't free this below */
+
+ *structp = response;
+ return (LWRES_R_SUCCESS);
+
+ out:
+ if (b_out.base != NULL)
+ CTXFREE(b_out.base, b_out.length);
+ if (buffer != NULL)
+ CTXFREE(buffer, LWRES_RECVLENGTH);
+ if (response != NULL)
+ lwres_gabnresponse_free(ctx, &response);
+
+ return (ret);
+}
+
+
+/*% Used to perform reverse lookups. */
+lwres_result_t
+lwres_getnamebyaddr(lwres_context_t *ctx, lwres_uint32_t addrtype,
+ lwres_uint16_t addrlen, const unsigned char *addr,
+ lwres_gnbaresponse_t **structp)
+{
+ lwres_gnbarequest_t request;
+ lwres_gnbaresponse_t *response;
+ int ret;
+ int recvlen;
+ lwres_buffer_t b_in, b_out;
+ lwres_lwpacket_t pkt;
+ lwres_uint32_t serial;
+ char *buffer;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(addrtype != 0);
+ REQUIRE(addrlen != 0);
+ REQUIRE(addr != NULL);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ b_in.base = NULL;
+ b_out.base = NULL;
+ response = NULL;
+ buffer = NULL;
+ serial = lwres_context_nextserial(ctx);
+
+ buffer = CTXMALLOC(LWRES_RECVLENGTH);
+ if (buffer == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+
+ /*
+ * Set up our request and render it to a buffer.
+ */
+ request.flags = 0;
+ request.addr.family = addrtype;
+ request.addr.length = addrlen;
+ memcpy(request.addr.address, addr, addrlen);
+ pkt.pktflags = 0;
+ pkt.serial = serial;
+ pkt.result = 0;
+ pkt.recvlength = LWRES_RECVLENGTH;
+
+ again:
+ ret = lwres_gnbarequest_render(ctx, &request, &pkt, &b_out);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer,
+ LWRES_RECVLENGTH, &recvlen);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ lwres_buffer_init(&b_in, buffer, recvlen);
+ b_in.used = recvlen;
+
+ /*
+ * Parse the packet header.
+ */
+ ret = lwres_lwpacket_parseheader(&b_in, &pkt);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ /*
+ * Sanity check.
+ */
+ if (pkt.serial != serial)
+ goto again;
+ if (pkt.opcode != LWRES_OPCODE_GETNAMEBYADDR)
+ goto again;
+
+ /*
+ * Free what we've transmitted
+ */
+ CTXFREE(b_out.base, b_out.length);
+ b_out.base = NULL;
+ b_out.length = 0;
+
+ if (pkt.result != LWRES_R_SUCCESS) {
+ ret = pkt.result;
+ goto out;
+ }
+
+ /*
+ * Parse the response.
+ */
+ ret = lwres_gnbaresponse_parse(ctx, &b_in, &pkt, &response);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+ response->base = buffer;
+ response->baselen = LWRES_RECVLENGTH;
+ buffer = NULL; /* don't free this below */
+
+ *structp = response;
+ return (LWRES_R_SUCCESS);
+
+ out:
+ if (b_out.base != NULL)
+ CTXFREE(b_out.base, b_out.length);
+ if (buffer != NULL)
+ CTXFREE(buffer, LWRES_RECVLENGTH);
+ if (response != NULL)
+ lwres_gnbaresponse_free(ctx, &response);
+
+ return (ret);
+}
+
+/*% Get rdata by name. */
+lwres_result_t
+lwres_getrdatabyname(lwres_context_t *ctx, const char *name,
+ lwres_uint16_t rdclass, lwres_uint16_t rdtype,
+ lwres_uint32_t flags, lwres_grbnresponse_t **structp)
+{
+ int ret;
+ int recvlen;
+ lwres_buffer_t b_in, b_out;
+ lwres_lwpacket_t pkt;
+ lwres_uint32_t serial;
+ char *buffer;
+ lwres_grbnrequest_t request;
+ lwres_grbnresponse_t *response;
+ char target_name[1024];
+ unsigned int target_length;
+
+ REQUIRE(ctx != NULL);
+ REQUIRE(name != NULL);
+ REQUIRE(structp != NULL && *structp == NULL);
+
+ b_in.base = NULL;
+ b_out.base = NULL;
+ response = NULL;
+ buffer = NULL;
+ serial = lwres_context_nextserial(ctx);
+
+ buffer = CTXMALLOC(LWRES_RECVLENGTH);
+ if (buffer == NULL) {
+ ret = LWRES_R_NOMEMORY;
+ goto out;
+ }
+
+ target_length = strlen(name);
+ if (target_length >= sizeof(target_name))
+ return (LWRES_R_FAILURE);
+ strcpy(target_name, name); /* strcpy is safe */
+
+ /*
+ * Set up our request and render it to a buffer.
+ */
+ request.rdclass = rdclass;
+ request.rdtype = rdtype;
+ request.flags = flags;
+ request.name = target_name;
+ request.namelen = target_length;
+ pkt.pktflags = 0;
+ pkt.serial = serial;
+ pkt.result = 0;
+ pkt.recvlength = LWRES_RECVLENGTH;
+
+ again:
+ ret = lwres_grbnrequest_render(ctx, &request, &pkt, &b_out);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ ret = lwres_context_sendrecv(ctx, b_out.base, b_out.length, buffer,
+ LWRES_RECVLENGTH, &recvlen);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ lwres_buffer_init(&b_in, buffer, recvlen);
+ b_in.used = recvlen;
+
+ /*
+ * Parse the packet header.
+ */
+ ret = lwres_lwpacket_parseheader(&b_in, &pkt);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+
+ /*
+ * Sanity check.
+ */
+ if (pkt.serial != serial)
+ goto again;
+ if (pkt.opcode != LWRES_OPCODE_GETRDATABYNAME)
+ goto again;
+
+ /*
+ * Free what we've transmitted
+ */
+ CTXFREE(b_out.base, b_out.length);
+ b_out.base = NULL;
+ b_out.length = 0;
+
+ if (pkt.result != LWRES_R_SUCCESS) {
+ ret = pkt.result;
+ goto out;
+ }
+
+ /*
+ * Parse the response.
+ */
+ ret = lwres_grbnresponse_parse(ctx, &b_in, &pkt, &response);
+ if (ret != LWRES_R_SUCCESS)
+ goto out;
+ response->base = buffer;
+ response->baselen = LWRES_RECVLENGTH;
+ buffer = NULL; /* don't free this below */
+
+ *structp = response;
+ return (LWRES_R_SUCCESS);
+
+ out:
+ if (b_out.base != NULL)
+ CTXFREE(b_out.base, b_out.length);
+ if (buffer != NULL)
+ CTXFREE(buffer, LWRES_RECVLENGTH);
+ if (response != NULL)
+ lwres_grbnresponse_free(ctx, &response);
+
+ return (ret);
+}
diff --git a/lib/lwres/man/Makefile.in b/lib/lwres/man/Makefile.in
new file mode 100644
index 0000000..cb723c2
--- /dev/null
+++ b/lib/lwres/man/Makefile.in
@@ -0,0 +1,232 @@
+# 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.9 2007/06/19 23:47:23 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_RULES@
+
+# Alphabetically
+#MANPAGES = lwres.3 lwres_addr_parse.3 lwres_buffer.3 \
+# lwres_buffer_add.3 lwres_buffer_back.3 lwres_buffer_clear.3 \
+# lwres_buffer_first.3 lwres_buffer_forward.3 \
+# lwres_buffer_getmem.3 lwres_buffer_getuint16.3 \
+# lwres_buffer_getuint32.3 lwres_buffer_getuint8.3 \
+# lwres_buffer_init.3 lwres_buffer_invalidate.3 \
+# lwres_buffer_putmem.3 lwres_buffer_putuint16.3 \
+# lwres_buffer_putuint32.3 lwres_buffer_putuint8.3 \
+# lwres_buffer_subtract.3 lwres_conf_clear.3 \
+# lwres_conf_get.3 lwres_conf_init.3 \
+# lwres_conf_parse.3 lwres_conf_print.3 \
+# lwres_config.3 lwres_context.3 \
+# lwres_context_allocmem.3 lwres_context_create.3 \
+# lwres_context_destroy.3 lwres_context_freemem.3 \
+# lwres_context_initserial.3 lwres_context_nextserial.3 \
+# lwres_context_sendrecv.3 lwres_endhostent.3 \
+# lwres_endhostent_r.3 lwres_freeaddrinfo.3 \
+# lwres_freehostent.3 lwres_gabn.3 \
+# lwres_gabnrequest_free.3 lwres_gabnrequest_parse.3 \
+# lwres_gabnrequest_render.3 lwres_gabnresponse_free.3 \
+# lwres_gabnresponse_parse.3 lwres_gabnresponse_render.3 \
+# lwres_gai_strerror.3 lwres_getaddrinfo.3 \
+# lwres_getaddrsbyname.3 lwres_gethostbyaddr.3 \
+# lwres_gethostbyaddr_r.3 lwres_gethostbyname.3 \
+# lwres_gethostbyname2.3 lwres_gethostbyname_r.3 \
+# lwres_gethostent.3 lwres_gethostent_r.3 \
+# lwres_getipnode.3 lwres_getipnodebyaddr.3 \
+# lwres_getipnodebyname.3 lwres_getnamebyaddr.3 \
+# lwres_getnameinfo.3 lwres_getrrsetbyname.3 \
+# lwres_gnba.3 lwres_gnbarequest_free.3 \
+# lwres_gnbarequest_parse.3 lwres_gnbarequest_render.3 \
+# lwres_gnbaresponse_free.3 lwres_gnbaresponse_parse.3 \
+# lwres_gnbaresponse_render.3 lwres_herror.3 \
+# lwres_hstrerror.3 lwres_inetntop.3 \
+# lwres_lwpacket_parseheader.3 lwres_lwpacket_renderheader.3 \
+# lwres_net_ntop.3 lwres_noop.3 \
+# lwres_nooprequest_free.3 lwres_nooprequest_parse.3 \
+# lwres_nooprequest_render.3 lwres_noopresponse_free.3 \
+# lwres_noopresponse_parse.3 lwres_noopresponse_render.3 \
+# lwres_packet.3 lwres_resutil.3 \
+# lwres_sethostent.3 lwres_sethostent_r.3 \
+# lwres_string_parse.3
+
+
+MANPAGES = lwres.3 lwres_buffer.3 lwres_config.3 lwres_context.3 \
+ lwres_gabn.3 lwres_gai_strerror.3 lwres_getaddrinfo.3 \
+ lwres_gethostent.3 lwres_getipnode.3 lwres_getnameinfo.3 \
+ lwres_getrrsetbyname.3 lwres_gnba.3 lwres_hstrerror.3 lwres_inetntop.3 \
+ lwres_noop.3 lwres_packet.3 lwres_resutil.3
+
+HTMLPAGES = lwres.html lwres_buffer.html lwres_config.html lwres_context.html \
+ lwres_gabn.html lwres_gai_strerror.html lwres_getaddrinfo.html \
+ lwres_gethostent.html lwres_getipnode.html lwres_getnameinfo.html \
+ lwres_getrrsetbyname.html lwres_gnba.html lwres_hstrerror.html lwres_inetntop.html \
+ lwres_noop.html lwres_packet.html lwres_resutil.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man3
+
+man3 = ${DESTDIR}${mandir}/man3
+
+install:: installdirs
+ for m in ${MANPAGES}; do ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man3; done
+ rm -f ${man3}/lwres_addr_parse.3
+ @LN@ ${man3}/lwres_resutil.3 ${man3}/lwres_addr_parse.3
+ rm -f ${man3}/lwres_buffer_add.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_add.3
+ rm -f ${man3}/lwres_buffer_back.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_back.3
+ rm -f ${man3}/lwres_buffer_clear.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_clear.3
+ rm -f ${man3}/lwres_buffer_first.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_first.3
+ rm -f ${man3}/lwres_buffer_forward.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_forward.3
+ rm -f ${man3}/lwres_buffer_getmem.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_getmem.3
+ rm -f ${man3}/lwres_buffer_getuint16.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_getuint16.3
+ rm -f ${man3}/lwres_buffer_getuint32.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_getuint32.3
+ rm -f ${man3}/lwres_buffer_getuint8.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_getuint8.3
+ rm -f ${man3}/lwres_buffer_init.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_init.3
+ rm -f ${man3}/lwres_buffer_invalidate.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_invalidate.3
+ rm -f ${man3}/lwres_buffer_putmem.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_putmem.3
+ rm -f ${man3}/lwres_buffer_putuint16.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_putuint16.3
+ rm -f ${man3}/lwres_buffer_putuint32.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_putuint32.3
+ rm -f ${man3}/lwres_buffer_putuint8.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_putuint8.3
+ rm -f ${man3}/lwres_buffer_subtract.3
+ @LN@ ${man3}/lwres_buffer.3 ${man3}/lwres_buffer_subtract.3
+ rm -f ${man3}/lwres_conf_clear.3
+ @LN@ ${man3}/lwres_config.3 ${man3}/lwres_conf_clear.3
+ rm -f ${man3}/lwres_conf_get.3
+ @LN@ ${man3}/lwres_config.3 ${man3}/lwres_conf_get.3
+ rm -f ${man3}/lwres_conf_init.3
+ @LN@ ${man3}/lwres_config.3 ${man3}/lwres_conf_init.3
+ rm -f ${man3}/lwres_conf_parse.3
+ @LN@ ${man3}/lwres_config.3 ${man3}/lwres_conf_parse.3
+ rm -f ${man3}/lwres_conf_print.3
+ @LN@ ${man3}/lwres_config.3 ${man3}/lwres_conf_print.3
+ rm -f ${man3}/lwres_context_allocmem.3
+ @LN@ ${man3}/lwres_context.3 ${man3}/lwres_context_allocmem.3
+ rm -f ${man3}/lwres_context_create.3
+ @LN@ ${man3}/lwres_context.3 ${man3}/lwres_context_create.3
+ rm -f ${man3}/lwres_context_destroy.3
+ @LN@ ${man3}/lwres_context.3 ${man3}/lwres_context_destroy.3
+ rm -f ${man3}/lwres_context_freemem.3
+ @LN@ ${man3}/lwres_context.3 ${man3}/lwres_context_freemem.3
+ rm -f ${man3}/lwres_context_initserial.3
+ @LN@ ${man3}/lwres_context.3 ${man3}/lwres_context_initserial.3
+ rm -f ${man3}/lwres_context_nextserial.3
+ @LN@ ${man3}/lwres_context.3 ${man3}/lwres_context_nextserial.3
+ rm -f ${man3}/lwres_context_sendrecv.3
+ @LN@ ${man3}/lwres_context.3 ${man3}/lwres_context_sendrecv.3
+ rm -f ${man3}/lwres_endhostent.3
+ @LN@ ${man3}/lwres_gethostent.3 ${man3}/lwres_endhostent.3
+ rm -f ${man3}/lwres_endhostent_r.3
+ @LN@ ${man3}/lwres_gethostent.3 ${man3}/lwres_endhostent_r.3
+ rm -f ${man3}/lwres_freeaddrinfo.3
+ @LN@ ${man3}/lwres_getaddrinfo.3 ${man3}/lwres_freeaddrinfo.3
+ rm -f ${man3}/lwres_freehostent.3
+ @LN@ ${man3}/lwres_getipnode.3 ${man3}/lwres_freehostent.3
+ rm -f ${man3}/lwres_gabnrequest_free.3
+ @LN@ ${man3}/lwres_gabn.3 ${man3}/lwres_gabnrequest_free.3
+ rm -f ${man3}/lwres_gabnrequest_parse.3
+ @LN@ ${man3}/lwres_gabn.3 ${man3}/lwres_gabnrequest_parse.3
+ rm -f ${man3}/lwres_gabnrequest_render.3
+ @LN@ ${man3}/lwres_gabn.3 ${man3}/lwres_gabnrequest_render.3
+ rm -f ${man3}/lwres_gabnresponse_free.3
+ @LN@ ${man3}/lwres_gabn.3 ${man3}/lwres_gabnresponse_free.3
+ rm -f ${man3}/lwres_gabnresponse_parse.3
+ @LN@ ${man3}/lwres_gabn.3 ${man3}/lwres_gabnresponse_parse.3
+ rm -f ${man3}/lwres_gabnresponse_render.3
+ @LN@ ${man3}/lwres_gabn.3 ${man3}/lwres_gabnresponse_render.3
+ rm -f ${man3}/lwres_getaddrsbyname.3
+ @LN@ ${man3}/lwres_resutil.3 ${man3}/lwres_getaddrsbyname.3
+ rm -f ${man3}/lwres_gethostbyaddr.3
+ @LN@ ${man3}/lwres_gethostent.3 ${man3}/lwres_gethostbyaddr.3
+ rm -f ${man3}/lwres_gethostbyaddr_r.3
+ @LN@ ${man3}/lwres_gethostent.3 ${man3}/lwres_gethostbyaddr_r.3
+ rm -f ${man3}/lwres_gethostbyname.3
+ @LN@ ${man3}/lwres_gethostent.3 ${man3}/lwres_gethostbyname.3
+ rm -f ${man3}/lwres_gethostbyname2.3
+ @LN@ ${man3}/lwres_gethostent.3 ${man3}/lwres_gethostbyname2.3
+ rm -f ${man3}/lwres_gethostbyname_r.3
+ @LN@ ${man3}/lwres_gethostent.3 ${man3}/lwres_gethostbyname_r.3
+ rm -f ${man3}/lwres_gethostent_r.3
+ @LN@ ${man3}/lwres_gethostent.3 ${man3}/lwres_gethostent_r.3
+ rm -f ${man3}/lwres_getipnodebyaddr.3
+ @LN@ ${man3}/lwres_getipnode.3 ${man3}/lwres_getipnodebyaddr.3
+ rm -f ${man3}/lwres_getipnodebyname.3
+ @LN@ ${man3}/lwres_getipnode.3 ${man3}/lwres_getipnodebyname.3
+ rm -f ${man3}/lwres_getnamebyaddr.3
+ @LN@ ${man3}/lwres_resutil.3 ${man3}/lwres_getnamebyaddr.3
+ rm -f ${man3}/lwres_gnbarequest_free.3
+ @LN@ ${man3}/lwres_gnba.3 ${man3}/lwres_gnbarequest_free.3
+ rm -f ${man3}/lwres_gnbarequest_parse.3
+ @LN@ ${man3}/lwres_gnba.3 ${man3}/lwres_gnbarequest_parse.3
+ rm -f ${man3}/lwres_gnbarequest_render.3
+ @LN@ ${man3}/lwres_gnba.3 ${man3}/lwres_gnbarequest_render.3
+ rm -f ${man3}/lwres_gnbaresponse_free.3
+ @LN@ ${man3}/lwres_gnba.3 ${man3}/lwres_gnbaresponse_free.3
+ rm -f ${man3}/lwres_gnbaresponse_parse.3
+ @LN@ ${man3}/lwres_gnba.3 ${man3}/lwres_gnbaresponse_parse.3
+ rm -f ${man3}/lwres_gnbaresponse_render.3
+ @LN@ ${man3}/lwres_gnba.3 ${man3}/lwres_gnbaresponse_render.3
+ rm -f ${man3}/lwres_herror.3
+ @LN@ ${man3}/lwres_hstrerror.3 ${man3}/lwres_herror.3
+ rm -f ${man3}/lwres_lwpacket_parseheader.3
+ @LN@ ${man3}/lwres_packet.3 ${man3}/lwres_lwpacket_parseheader.3
+ rm -f ${man3}/lwres_lwpacket_renderheader.3
+ @LN@ ${man3}/lwres_packet.3 ${man3}/lwres_lwpacket_renderheader.3
+ rm -f ${man3}/lwres_net_ntop.3
+ @LN@ ${man3}/lwres_inetntop.3 ${man3}/lwres_net_ntop.3
+ rm -f ${man3}/lwres_nooprequest_free.3
+ @LN@ ${man3}/lwres_noop.3 ${man3}/lwres_nooprequest_free.3
+ rm -f ${man3}/lwres_nooprequest_parse.3
+ @LN@ ${man3}/lwres_noop.3 ${man3}/lwres_nooprequest_parse.3
+ rm -f ${man3}/lwres_nooprequest_render.3
+ @LN@ ${man3}/lwres_noop.3 ${man3}/lwres_nooprequest_render.3
+ rm -f ${man3}/lwres_noopresponse_free.3
+ @LN@ ${man3}/lwres_noop.3 ${man3}/lwres_noopresponse_free.3
+ rm -f ${man3}/lwres_noopresponse_parse.3
+ @LN@ ${man3}/lwres_noop.3 ${man3}/lwres_noopresponse_parse.3
+ rm -f ${man3}/lwres_noopresponse_render.3
+ @LN@ ${man3}/lwres_noop.3 ${man3}/lwres_noopresponse_render.3
+ rm -f ${man3}/lwres_sethostent.3
+ @LN@ ${man3}/lwres_gethostent.3 ${man3}/lwres_sethostent.3
+ rm -f ${man3}/lwres_sethostent_r.3
+ @LN@ ${man3}/lwres_gethostent.3 ${man3}/lwres_sethostent_r.3
+ rm -f ${man3}/lwres_string_parse.3
+ @LN@ ${man3}/lwres_resutil.3 ${man3}/lwres_string_parse.3
diff --git a/lib/lwres/man/lwres.3 b/lib/lwres/man/lwres.3
new file mode 100644
index 0000000..e1f8793
--- /dev/null
+++ b/lib/lwres/man/lwres.3
@@ -0,0 +1,165 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres.3,v 1.28 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres \- introduction to the lightweight resolver library
+.SH "SYNOPSIS"
+.nf
+#include <lwres/lwres.h>
+.fi
+.SH "DESCRIPTION"
+.PP
+The BIND 9 lightweight resolver library is a simple, name service independent stub resolver library. It provides hostname\-to\-address and address\-to\-hostname lookup services to applications by transmitting lookup requests to a resolver daemon
+\fBlwresd\fR
+running on the local host. The resover daemon performs the lookup using the DNS or possibly other name service protocols, and returns the results to the application through the library. The library and resolver daemon communicate using a simple UDP\-based protocol.
+.SH "OVERVIEW"
+.PP
+The lwresd library implements multiple name service APIs. The standard
+\fBgethostbyname()\fR,
+\fBgethostbyaddr()\fR,
+\fBgethostbyname_r()\fR,
+\fBgethostbyaddr_r()\fR,
+\fBgetaddrinfo()\fR,
+\fBgetipnodebyname()\fR, and
+\fBgetipnodebyaddr()\fR
+functions are all supported. To allow the lwres library to coexist with system libraries that define functions of the same name, the library defines these functions with names prefixed by
+lwres_. To define the standard names, applications must include the header file
+\fI<lwres/netdb.h>\fR
+which contains macro definitions mapping the standard function names into
+lwres_
+prefixed ones. Operating system vendors who integrate the lwres library into their base distributions should rename the functions in the library proper so that the renaming macros are not needed.
+.PP
+The library also provides a native API consisting of the functions
+\fBlwres_getaddrsbyname()\fR
+and
+\fBlwres_getnamebyaddr()\fR. These may be called by applications that require more detailed control over the lookup process than the standard functions provide.
+.PP
+In addition to these name service independent address lookup functions, the library implements a new, experimental API for looking up arbitrary DNS resource records, using the
+\fBlwres_getaddrsbyname()\fR
+function.
+.PP
+Finally, there is a low\-level API for converting lookup requests and responses to and from raw lwres protocol packets. This API can be used by clients requiring nonblocking operation, and is also used when implementing the server side of the lwres protocol, for example in the
+\fBlwresd\fR
+resolver daemon. The use of this low\-level API in clients and servers is outlined in the following sections.
+.SH "CLIENT\-SIDE LOW\-LEVEL API CALL FLOW"
+.PP
+When a client program wishes to make an lwres request using the native low\-level API, it typically performs the following sequence of actions.
+.PP
+(1) Allocate or use an existing
+\fBlwres_packet_t\fR, called
+\fIpkt\fR
+below.
+.PP
+(2) Set
+pkt.recvlength
+to the maximum length we will accept. This is done so the receiver of our packets knows how large our receive buffer is. The "default" is a constant in
+\fIlwres.h\fR:
+\fBLWRES_RECVLENGTH = 4096\fR.
+.PP
+(3) Set
+pkt.serial
+to a unique serial number. This value is echoed back to the application by the remote server.
+.PP
+(4) Set
+pkt.pktflags. Usually this is set to 0.
+.PP
+(5) Set
+pkt.result
+to 0.
+.PP
+(6) Call
+\fBlwres_*request_render()\fR, or marshall in the data using the primitives such as
+\fBlwres_packet_render()\fR
+and storing the packet data.
+.PP
+(7) Transmit the resulting buffer.
+.PP
+(8) Call
+\fBlwres_*response_parse()\fR
+to parse any packets received.
+.PP
+(9) Verify that the opcode and serial match a request, and process the packet specific information contained in the body.
+.SH "SERVER\-SIDE LOW\-LEVEL API CALL FLOW"
+.PP
+When implementing the server side of the lightweight resolver protocol using the lwres library, a sequence of actions like the following is typically involved in processing each request packet.
+.PP
+Note that the same
+\fBlwres_packet_t\fR
+is used in both the
+\fB_parse()\fR
+and
+\fB_render()\fR
+calls, with only a few modifications made to the packet header's contents between uses. This method is recommended as it keeps the serial, opcode, and other fields correct.
+.PP
+(1) When a packet is received, call
+\fBlwres_*request_parse()\fR
+to unmarshall it. This returns a
+\fBlwres_packet_t\fR
+(also called
+\fIpkt\fR, below) as well as a data specific type, such as
+\fBlwres_gabnrequest_t\fR.
+.PP
+(2) Process the request in the data specific type.
+.PP
+(3) Set the
+pkt.result,
+pkt.recvlength
+as above. All other fields can be left untouched since they were filled in by the
+\fB*_parse()\fR
+call above. If using
+\fBlwres_*response_render()\fR,
+pkt.pktflags
+will be set up properly. Otherwise, the
+\fBLWRES_LWPACKETFLAG_RESPONSE\fR
+bit should be set.
+.PP
+(4) Call the data specific rendering function, such as
+\fBlwres_gabnresponse_render()\fR.
+.PP
+(5) Send the resulting packet to the client.
+.PP
+.SH "SEE ALSO"
+.PP
+\fBlwres_gethostent\fR(3),
+\fBlwres_getipnode\fR(3),
+\fBlwres_getnameinfo\fR(3),
+\fBlwres_noop\fR(3),
+\fBlwres_gabn\fR(3),
+\fBlwres_gnba\fR(3),
+\fBlwres_context\fR(3),
+\fBlwres_config\fR(3),
+\fBresolver\fR(5),
+\fBlwresd\fR(8).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres.docbook b/lib/lwres/man/lwres.docbook
new file mode 100644
index 0000000..97d591c
--- /dev/null
+++ b/lib/lwres/man/lwres.docbook
@@ -0,0 +1,266 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres.docbook,v 1.10 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+ <refnamediv>
+ <refname>lwres</refname>
+ <refpurpose>introduction to the lightweight resolver library</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/lwres.h&gt;</funcsynopsisinfo>
+</funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ The BIND 9 lightweight resolver library is a simple, name service
+ independent stub resolver library. It provides hostname-to-address
+ and address-to-hostname lookup services to applications by
+ transmitting lookup requests to a resolver daemon
+ <command>lwresd</command>
+ running on the local host. The resover daemon performs the
+ lookup using the DNS or possibly other name service protocols,
+ and returns the results to the application through the library.
+ The library and resolver daemon communicate using a simple
+ UDP-based protocol.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>OVERVIEW</title>
+ <para>
+ The lwresd library implements multiple name service APIs.
+ The standard
+ <function>gethostbyname()</function>,
+ <function>gethostbyaddr()</function>,
+ <function>gethostbyname_r()</function>,
+ <function>gethostbyaddr_r()</function>,
+ <function>getaddrinfo()</function>,
+ <function>getipnodebyname()</function>,
+ and
+ <function>getipnodebyaddr()</function>
+ functions are all supported. To allow the lwres library to coexist
+ with system libraries that define functions of the same name,
+ the library defines these functions with names prefixed by
+ <literal>lwres_</literal>.
+ To define the standard names, applications must include the
+ header file
+ <filename>&lt;lwres/netdb.h&gt;</filename>
+ which contains macro definitions mapping the standard function names
+ into
+ <literal>lwres_</literal>
+ prefixed ones. Operating system vendors who integrate the lwres
+ library into their base distributions should rename the functions
+ in the library proper so that the renaming macros are not needed.
+ </para>
+ <para>
+ The library also provides a native API consisting of the functions
+ <function>lwres_getaddrsbyname()</function>
+ and
+ <function>lwres_getnamebyaddr()</function>.
+ These may be called by applications that require more detailed
+ control over the lookup process than the standard functions
+ provide.
+ </para>
+ <para>
+ In addition to these name service independent address lookup
+ functions, the library implements a new, experimental API
+ for looking up arbitrary DNS resource records, using the
+ <function>lwres_getaddrsbyname()</function>
+ function.
+ </para>
+ <para>
+ Finally, there is a low-level API for converting lookup
+ requests and responses to and from raw lwres protocol packets.
+ This API can be used by clients requiring nonblocking operation,
+ and is also used when implementing the server side of the lwres
+ protocol, for example in the
+ <command>lwresd</command>
+ resolver daemon. The use of this low-level API in clients
+ and servers is outlined in the following sections.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>CLIENT-SIDE LOW-LEVEL API CALL FLOW</title>
+ <para>
+ When a client program wishes to make an lwres request using the
+ native low-level API, it typically performs the following
+ sequence of actions.
+ </para>
+ <para>
+ (1) Allocate or use an existing <type>lwres_packet_t</type>,
+ called <varname>pkt</varname> below.
+ </para>
+ <para>
+ (2) Set <structfield>pkt.recvlength</structfield> to the maximum length
+ we will accept.
+ This is done so the receiver of our packets knows how large our receive
+ buffer is. The "default" is a constant in
+ <filename>lwres.h</filename>: <constant>LWRES_RECVLENGTH = 4096</constant>.
+ </para>
+ <para>
+ (3) Set <structfield>pkt.serial</structfield>
+ to a unique serial number. This value is echoed
+ back to the application by the remote server.
+ </para>
+ <para>
+ (4) Set <structfield>pkt.pktflags</structfield>. Usually this is set to
+ 0.
+ </para>
+ <para>
+ (5) Set <structfield>pkt.result</structfield> to 0.
+ </para>
+ <para>
+ (6) Call <function>lwres_*request_render()</function>,
+ or marshall in the data using the primitives
+ such as <function>lwres_packet_render()</function>
+ and storing the packet data.
+ </para>
+ <para>
+ (7) Transmit the resulting buffer.
+ </para>
+ <para>
+ (8) Call <function>lwres_*response_parse()</function>
+ to parse any packets received.
+ </para>
+ <para>
+ (9) Verify that the opcode and serial match a request, and process the
+ packet specific information contained in the body.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SERVER-SIDE LOW-LEVEL API CALL FLOW</title>
+ <para>
+ When implementing the server side of the lightweight resolver
+ protocol using the lwres library, a sequence of actions like the
+ following is typically involved in processing each request packet.
+ </para>
+ <para>
+ Note that the same <type>lwres_packet_t</type> is used
+ in both the <function>_parse()</function> and <function>_render()</function> calls,
+ with only a few modifications made
+ to the packet header's contents between uses. This method is
+ recommended
+ as it keeps the serial, opcode, and other fields correct.
+ </para>
+ <para>
+ (1) When a packet is received, call <function>lwres_*request_parse()</function> to
+ unmarshall it. This returns a <type>lwres_packet_t</type> (also called <varname>pkt</varname>, below)
+ as well as a data specific type, such as <type>lwres_gabnrequest_t</type>.
+ </para>
+ <para>
+ (2) Process the request in the data specific type.
+ </para>
+ <para>
+ (3) Set the <structfield>pkt.result</structfield>,
+ <structfield>pkt.recvlength</structfield> as above. All other fields
+ can
+ be left untouched since they were filled in by the <function>*_parse()</function> call
+ above. If using <function>lwres_*response_render()</function>,
+ <structfield>pkt.pktflags</structfield> will be set up
+ properly. Otherwise, the <constant>LWRES_LWPACKETFLAG_RESPONSE</constant> bit should be
+ set.
+ </para>
+ <para>
+ (4) Call the data specific rendering function, such as
+ <function>lwres_gabnresponse_render()</function>.
+ </para>
+ <para>
+ (5) Send the resulting packet to the client.
+ </para>
+ <para></para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>lwres_gethostent</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_getipnode</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_getnameinfo</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_noop</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_gabn</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_gnba</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_context</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_config</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>resolver</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwresd</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres.html b/lib/lwres/man/lwres.html
new file mode 100644
index 0000000..70d7856
--- /dev/null
+++ b/lib/lwres/man/lwres.html
@@ -0,0 +1,218 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres.html,v 1.23 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres &#8212; introduction to the lightweight resolver library</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis"><pre class="funcsynopsisinfo">#include &lt;lwres/lwres.h&gt;</pre></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543348"></a><h2>DESCRIPTION</h2>
+<p>
+ The BIND 9 lightweight resolver library is a simple, name service
+ independent stub resolver library. It provides hostname-to-address
+ and address-to-hostname lookup services to applications by
+ transmitting lookup requests to a resolver daemon
+ <span><strong class="command">lwresd</strong></span>
+ running on the local host. The resover daemon performs the
+ lookup using the DNS or possibly other name service protocols,
+ and returns the results to the application through the library.
+ The library and resolver daemon communicate using a simple
+ UDP-based protocol.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543361"></a><h2>OVERVIEW</h2>
+<p>
+ The lwresd library implements multiple name service APIs.
+ The standard
+ <code class="function">gethostbyname()</code>,
+ <code class="function">gethostbyaddr()</code>,
+ <code class="function">gethostbyname_r()</code>,
+ <code class="function">gethostbyaddr_r()</code>,
+ <code class="function">getaddrinfo()</code>,
+ <code class="function">getipnodebyname()</code>,
+ and
+ <code class="function">getipnodebyaddr()</code>
+ functions are all supported. To allow the lwres library to coexist
+ with system libraries that define functions of the same name,
+ the library defines these functions with names prefixed by
+ <code class="literal">lwres_</code>.
+ To define the standard names, applications must include the
+ header file
+ <code class="filename">&lt;lwres/netdb.h&gt;</code>
+ which contains macro definitions mapping the standard function names
+ into
+ <code class="literal">lwres_</code>
+ prefixed ones. Operating system vendors who integrate the lwres
+ library into their base distributions should rename the functions
+ in the library proper so that the renaming macros are not needed.
+ </p>
+<p>
+ The library also provides a native API consisting of the functions
+ <code class="function">lwres_getaddrsbyname()</code>
+ and
+ <code class="function">lwres_getnamebyaddr()</code>.
+ These may be called by applications that require more detailed
+ control over the lookup process than the standard functions
+ provide.
+ </p>
+<p>
+ In addition to these name service independent address lookup
+ functions, the library implements a new, experimental API
+ for looking up arbitrary DNS resource records, using the
+ <code class="function">lwres_getaddrsbyname()</code>
+ function.
+ </p>
+<p>
+ Finally, there is a low-level API for converting lookup
+ requests and responses to and from raw lwres protocol packets.
+ This API can be used by clients requiring nonblocking operation,
+ and is also used when implementing the server side of the lwres
+ protocol, for example in the
+ <span><strong class="command">lwresd</strong></span>
+ resolver daemon. The use of this low-level API in clients
+ and servers is outlined in the following sections.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543425"></a><h2>CLIENT-SIDE LOW-LEVEL API CALL FLOW</h2>
+<p>
+ When a client program wishes to make an lwres request using the
+ native low-level API, it typically performs the following
+ sequence of actions.
+ </p>
+<p>
+ (1) Allocate or use an existing <span class="type">lwres_packet_t</span>,
+ called <code class="varname">pkt</code> below.
+ </p>
+<p>
+ (2) Set <em class="structfield"><code>pkt.recvlength</code></em> to the maximum length
+ we will accept.
+ This is done so the receiver of our packets knows how large our receive
+ buffer is. The "default" is a constant in
+ <code class="filename">lwres.h</code>: <code class="constant">LWRES_RECVLENGTH = 4096</code>.
+ </p>
+<p>
+ (3) Set <em class="structfield"><code>pkt.serial</code></em>
+ to a unique serial number. This value is echoed
+ back to the application by the remote server.
+ </p>
+<p>
+ (4) Set <em class="structfield"><code>pkt.pktflags</code></em>. Usually this is set to
+ 0.
+ </p>
+<p>
+ (5) Set <em class="structfield"><code>pkt.result</code></em> to 0.
+ </p>
+<p>
+ (6) Call <code class="function">lwres_*request_render()</code>,
+ or marshall in the data using the primitives
+ such as <code class="function">lwres_packet_render()</code>
+ and storing the packet data.
+ </p>
+<p>
+ (7) Transmit the resulting buffer.
+ </p>
+<p>
+ (8) Call <code class="function">lwres_*response_parse()</code>
+ to parse any packets received.
+ </p>
+<p>
+ (9) Verify that the opcode and serial match a request, and process the
+ packet specific information contained in the body.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543573"></a><h2>SERVER-SIDE LOW-LEVEL API CALL FLOW</h2>
+<p>
+ When implementing the server side of the lightweight resolver
+ protocol using the lwres library, a sequence of actions like the
+ following is typically involved in processing each request packet.
+ </p>
+<p>
+ Note that the same <span class="type">lwres_packet_t</span> is used
+ in both the <code class="function">_parse()</code> and <code class="function">_render()</code> calls,
+ with only a few modifications made
+ to the packet header's contents between uses. This method is
+ recommended
+ as it keeps the serial, opcode, and other fields correct.
+ </p>
+<p>
+ (1) When a packet is received, call <code class="function">lwres_*request_parse()</code> to
+ unmarshall it. This returns a <span class="type">lwres_packet_t</span> (also called <code class="varname">pkt</code>, below)
+ as well as a data specific type, such as <span class="type">lwres_gabnrequest_t</span>.
+ </p>
+<p>
+ (2) Process the request in the data specific type.
+ </p>
+<p>
+ (3) Set the <em class="structfield"><code>pkt.result</code></em>,
+ <em class="structfield"><code>pkt.recvlength</code></em> as above. All other fields
+ can
+ be left untouched since they were filled in by the <code class="function">*_parse()</code> call
+ above. If using <code class="function">lwres_*response_render()</code>,
+ <em class="structfield"><code>pkt.pktflags</code></em> will be set up
+ properly. Otherwise, the <code class="constant">LWRES_LWPACKETFLAG_RESPONSE</code> bit should be
+ set.
+ </p>
+<p>
+ (4) Call the data specific rendering function, such as
+ <code class="function">lwres_gabnresponse_render()</code>.
+ </p>
+<p>
+ (5) Send the resulting packet to the client.
+ </p>
+<p></p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543656"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">lwres_gethostent</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_getipnode</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_getnameinfo</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_noop</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_gabn</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_gnba</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_context</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_config</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">resolver</span>(5)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwresd</span>(8)</span>.
+
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_buffer.3 b/lib/lwres/man/lwres_buffer.3
new file mode 100644
index 0000000..cc0959d
--- /dev/null
+++ b/lib/lwres/man/lwres_buffer.3
@@ -0,0 +1,233 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_buffer.3,v 1.26 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_buffer
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_BUFFER" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "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
+.SH "SYNOPSIS"
+.nf
+#include <lwres/lwbuffer.h>
+.fi
+.HP 23
+.BI "void lwres_buffer_init(lwres_buffer_t\ *" "b" ", void\ *" "base" ", unsigned\ int\ " "length" ");"
+.HP 29
+.BI "void lwres_buffer_invalidate(lwres_buffer_t\ *" "b" ");"
+.HP 22
+.BI "void lwres_buffer_add(lwres_buffer_t\ *" "b" ", unsigned\ int\ " "n" ");"
+.HP 27
+.BI "void lwres_buffer_subtract(lwres_buffer_t\ *" "b" ", unsigned\ int\ " "n" ");"
+.HP 24
+.BI "void lwres_buffer_clear(lwres_buffer_t\ *" "b" ");"
+.HP 24
+.BI "void lwres_buffer_first(lwres_buffer_t\ *" "b" ");"
+.HP 26
+.BI "void lwres_buffer_forward(lwres_buffer_t\ *" "b" ", unsigned\ int\ " "n" ");"
+.HP 23
+.BI "void lwres_buffer_back(lwres_buffer_t\ *" "b" ", unsigned\ int\ " "n" ");"
+.HP 36
+.BI "lwres_uint8_t lwres_buffer_getuint8(lwres_buffer_t\ *" "b" ");"
+.HP 27
+.BI "void lwres_buffer_putuint8(lwres_buffer_t\ *" "b" ", lwres_uint8_t\ " "val" ");"
+.HP 38
+.BI "lwres_uint16_t lwres_buffer_getuint16(lwres_buffer_t\ *" "b" ");"
+.HP 28
+.BI "void lwres_buffer_putuint16(lwres_buffer_t\ *" "b" ", lwres_uint16_t\ " "val" ");"
+.HP 38
+.BI "lwres_uint32_t lwres_buffer_getuint32(lwres_buffer_t\ *" "b" ");"
+.HP 28
+.BI "void lwres_buffer_putuint32(lwres_buffer_t\ *" "b" ", lwres_uint32_t\ " "val" ");"
+.HP 25
+.BI "void lwres_buffer_putmem(lwres_buffer_t\ *" "b" ", const\ unsigned\ char\ *" "base" ", unsigned\ int\ " "length" ");"
+.HP 25
+.BI "void lwres_buffer_getmem(lwres_buffer_t\ *" "b" ", unsigned\ char\ *" "base" ", unsigned\ int\ " "length" ");"
+.SH "DESCRIPTION"
+.PP
+These functions provide bounds checked access to a region of memory where data is being read or written. They are based on, and similar to, the
+isc_buffer_
+functions in the ISC library.
+.PP
+A buffer is a region of memory, together with a set of related subregions. The
+\fIused region\fR
+and the
+\fIavailable\fR
+region are disjoint, and their union is the buffer's region. The used region extends from the beginning of the buffer region to the last used byte. The available region extends from one byte greater than the last used byte to the end of the buffer's region. The size of the used region can be changed using various buffer commands. Initially, the used region is empty.
+.PP
+The used region is further subdivided into two disjoint regions: the
+\fIconsumed region\fR
+and the
+\fIremaining region\fR. The union of these two regions is the used region. The consumed region extends from the beginning of the used region to the byte before the
+\fIcurrent\fR
+offset (if any). The
+\fIremaining\fR
+region the current pointer to the end of the used region. The size of the consumed region can be changed using various buffer commands. Initially, the consumed region is empty.
+.PP
+The
+\fIactive region\fR
+is an (optional) subregion of the remaining region. It extends from the current offset to an offset in the remaining region. Initially, the active region is empty. If the current offset advances beyond the chosen offset, the active region will also be empty.
+.PP
+.RS 4
+.nf
+ /\-\-\-\-\-\-\-\-\-\-\-\-entire length\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\\\\
+ /\-\-\-\-\- used region \-\-\-\-\-\\\\/\-\- available \-\-\\\\
+ +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
+ | consumed | remaining | |
+ +\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
+ a b c d e
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+ a == base of buffer.
+ b == current pointer. Can be anywhere between a and d.
+ c == active pointer. Meaningful between b and d.
+ d == used pointer.
+ e == length of buffer.
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+ a\-e == entire length of buffer.
+ a\-d == used region.
+ a\-b == consumed region.
+ b\-d == remaining region.
+ b\-c == optional active region.
+.fi
+.RE
+.sp
+.PP
+\fBlwres_buffer_init()\fR
+initializes the
+\fBlwres_buffer_t\fR
+\fI*b\fR
+and assocates it with the memory region of size
+\fIlength\fR
+bytes starting at location
+\fIbase.\fR
+.PP
+\fBlwres_buffer_invalidate()\fR
+marks the buffer
+\fI*b\fR
+as invalid. Invalidating a buffer after use is not required, but makes it possible to catch its possible accidental use.
+.PP
+The functions
+\fBlwres_buffer_add()\fR
+and
+\fBlwres_buffer_subtract()\fR
+respectively increase and decrease the used space in buffer
+\fI*b\fR
+by
+\fIn\fR
+bytes.
+\fBlwres_buffer_add()\fR
+checks for buffer overflow and
+\fBlwres_buffer_subtract()\fR
+checks for underflow. These functions do not allocate or deallocate memory. They just change the value of
+used.
+.PP
+A buffer is re\-initialised by
+\fBlwres_buffer_clear()\fR. The function sets
+used,
+current
+and
+active
+to zero.
+.PP
+\fBlwres_buffer_first\fR
+makes the consumed region of buffer
+\fI*p\fR
+empty by setting
+current
+to zero (the start of the buffer).
+.PP
+\fBlwres_buffer_forward()\fR
+increases the consumed region of buffer
+\fI*b\fR
+by
+\fIn\fR
+bytes, checking for overflow. Similarly,
+\fBlwres_buffer_back()\fR
+decreases buffer
+\fIb\fR's consumed region by
+\fIn\fR
+bytes and checks for underflow.
+.PP
+\fBlwres_buffer_getuint8()\fR
+reads an unsigned 8\-bit integer from
+\fI*b\fR
+and returns it.
+\fBlwres_buffer_putuint8()\fR
+writes the unsigned 8\-bit integer
+\fIval\fR
+to buffer
+\fI*b\fR.
+.PP
+\fBlwres_buffer_getuint16()\fR
+and
+\fBlwres_buffer_getuint32()\fR
+are identical to
+\fBlwres_buffer_putuint8()\fR
+except that they respectively read an unsigned 16\-bit or 32\-bit integer in network byte order from
+\fIb\fR. Similarly,
+\fBlwres_buffer_putuint16()\fR
+and
+\fBlwres_buffer_putuint32()\fR
+writes the unsigned 16\-bit or 32\-bit integer
+\fIval\fR
+to buffer
+\fIb\fR, in network byte order.
+.PP
+Arbitrary amounts of data are read or written from a lightweight resolver buffer with
+\fBlwres_buffer_getmem()\fR
+and
+\fBlwres_buffer_putmem()\fR
+respectively.
+\fBlwres_buffer_putmem()\fR
+copies
+\fIlength\fR
+bytes of memory at
+\fIbase\fR
+to
+\fIb\fR. Conversely,
+\fBlwres_buffer_getmem()\fR
+copies
+\fIlength\fR
+bytes of memory from
+\fIb\fR
+to
+\fIbase\fR.
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_buffer.docbook b/lib/lwres/man/lwres_buffer.docbook
new file mode 100644
index 0000000..97c52bd
--- /dev/null
+++ b/lib/lwres/man/lwres_buffer.docbook
@@ -0,0 +1,394 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_buffer.docbook,v 1.10 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_buffer</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_buffer_init</refname>
+ <refname>lwres_buffer_invalidate</refname>
+ <refname>lwres_buffer_add</refname>
+ <refname>lwres_buffer_subtract</refname>
+ <refname>lwres_buffer_clear</refname>
+ <refname>lwres_buffer_first</refname>
+ <refname>lwres_buffer_forward</refname>
+ <refname>lwres_buffer_back</refname>
+ <refname>lwres_buffer_getuint8</refname>
+ <refname>lwres_buffer_putuint8</refname>
+ <refname>lwres_buffer_getuint16</refname>
+ <refname>lwres_buffer_putuint16</refname>
+ <refname>lwres_buffer_getuint32</refname>
+ <refname>lwres_buffer_putuint32</refname>
+ <refname>lwres_buffer_putmem</refname>
+ <refname>lwres_buffer_getmem</refname>
+ <refpurpose>lightweight resolver buffer management</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+
+ <funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;lwres/lwbuffer.h&gt;
+</funcsynopsisinfo>
+
+<funcprototype>
+
+ <funcdef>
+void
+<function>lwres_buffer_init</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>void *<parameter>base</parameter></paramdef>
+ <paramdef>unsigned int <parameter>length</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_invalidate</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_add</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>unsigned int <parameter>n</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_subtract</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>unsigned int <parameter>n</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_clear</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_first</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_forward</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>unsigned int <parameter>n</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+
+ <funcdef>
+void
+<function>lwres_buffer_back</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>unsigned int <parameter>n</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+lwres_uint8_t
+<function>lwres_buffer_getuint8</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_putuint8</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_uint8_t <parameter>val</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+lwres_uint16_t
+<function>lwres_buffer_getuint16</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_putuint16</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_uint16_t <parameter>val</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+lwres_uint32_t
+<function>lwres_buffer_getuint32</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_putuint32</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_uint32_t <parameter>val</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_putmem</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>const unsigned char *<parameter>base</parameter></paramdef>
+ <paramdef>unsigned int <parameter>length</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_buffer_getmem</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>unsigned char *<parameter>base</parameter></paramdef>
+ <paramdef>unsigned int <parameter>length</parameter></paramdef>
+ </funcprototype>
+
+</funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+
+ <title>DESCRIPTION</title>
+ <para>
+ These functions provide bounds checked access to a region of memory
+ where data is being read or written.
+ They are based on, and similar to, the
+ <literal>isc_buffer_</literal>
+ functions in the ISC library.
+ </para>
+ <para>
+ A buffer is a region of memory, together with a set of related
+ subregions.
+ The <emphasis>used region</emphasis> and the
+ <emphasis>available</emphasis> region are disjoint, and
+ their union is the buffer's region.
+ The used region extends from the beginning of the buffer region to the
+ last used byte.
+ The available region extends from one byte greater than the last used
+ byte to the end of the buffer's region.
+ The size of the used region can be changed using various
+ buffer commands.
+ Initially, the used region is empty.
+ </para>
+ <para>
+ The used region is further subdivided into two disjoint regions: the
+ <emphasis>consumed region</emphasis> and the <emphasis>remaining region</emphasis>.
+ The union of these two regions is the used region.
+ The consumed region extends from the beginning of the used region to
+ the byte before the <emphasis>current</emphasis> offset (if any).
+ The <emphasis>remaining</emphasis> region the current pointer to the end
+ of the used
+ region.
+ The size of the consumed region can be changed using various
+ buffer commands.
+ Initially, the consumed region is empty.
+ </para>
+ <para>
+ The <emphasis>active region</emphasis> is an (optional) subregion of the
+ remaining
+ region.
+ It extends from the current offset to an offset in the
+ remaining region.
+ Initially, the active region is empty.
+ If the current offset advances beyond the chosen offset,
+ the active region will also be empty.
+ </para>
+ <para><programlisting>
+ /------------entire length---------------\\
+ /----- used region -----\\/-- available --\\
+ +----------------------------------------+
+ | consumed | remaining | |
+ +----------------------------------------+
+ a b c d e
+ </programlisting>
+ </para>
+ <para><programlisting>
+ a == base of buffer.
+ b == current pointer. Can be anywhere between a and d.
+ c == active pointer. Meaningful between b and d.
+ d == used pointer.
+ e == length of buffer.
+ </programlisting>
+ </para>
+ <para><programlisting>
+ a-e == entire length of buffer.
+ a-d == used region.
+ a-b == consumed region.
+ b-d == remaining region.
+ b-c == optional active region.
+</programlisting>
+ </para>
+ <para><function>lwres_buffer_init()</function>
+ initializes the
+ <type>lwres_buffer_t</type>
+ <parameter>*b</parameter>
+ and assocates it with the memory region of size
+ <parameter>length</parameter>
+ bytes starting at location
+ <parameter>base.</parameter>
+ </para>
+ <para><function>lwres_buffer_invalidate()</function>
+ marks the buffer <parameter>*b</parameter>
+ as invalid. Invalidating a buffer after use is not required,
+ but makes it possible to catch its possible accidental use.
+ </para>
+ <para>
+ The functions
+ <function>lwres_buffer_add()</function>
+ and
+ <function>lwres_buffer_subtract()</function>
+ respectively increase and decrease the used space in
+ buffer
+ <parameter>*b</parameter>
+ by
+ <parameter>n</parameter>
+ bytes.
+ <function>lwres_buffer_add()</function>
+ checks for buffer overflow and
+ <function>lwres_buffer_subtract()</function>
+ checks for underflow.
+ These functions do not allocate or deallocate memory.
+ They just change the value of
+ <structfield>used</structfield>.
+ </para>
+ <para>
+ A buffer is re-initialised by
+ <function>lwres_buffer_clear()</function>.
+ The function sets
+ <structfield>used</structfield>,
+ <structfield>current</structfield>
+ and
+ <structfield>active</structfield>
+ to zero.
+ </para>
+ <para><function>lwres_buffer_first</function>
+ makes the consumed region of buffer
+ <parameter>*p</parameter>
+ empty by setting
+ <structfield>current</structfield>
+ to zero (the start of the buffer).
+ </para>
+ <para><function>lwres_buffer_forward()</function>
+ increases the consumed region of buffer
+ <parameter>*b</parameter>
+ by
+ <parameter>n</parameter>
+ bytes, checking for overflow.
+ Similarly,
+ <function>lwres_buffer_back()</function>
+ decreases buffer
+ <parameter>b</parameter>'s
+ consumed region by
+ <parameter>n</parameter>
+ bytes and checks for underflow.
+ </para>
+ <para><function>lwres_buffer_getuint8()</function>
+ reads an unsigned 8-bit integer from
+ <parameter>*b</parameter>
+ and returns it.
+ <function>lwres_buffer_putuint8()</function>
+ writes the unsigned 8-bit integer
+ <parameter>val</parameter>
+ to buffer
+ <parameter>*b</parameter>.
+ </para>
+ <para><function>lwres_buffer_getuint16()</function>
+ and
+ <function>lwres_buffer_getuint32()</function>
+ are identical to
+ <function>lwres_buffer_putuint8()</function>
+ except that they respectively read an unsigned 16-bit or 32-bit integer
+ in network byte order from
+ <parameter>b</parameter>.
+ Similarly,
+ <function>lwres_buffer_putuint16()</function>
+ and
+ <function>lwres_buffer_putuint32()</function>
+ writes the unsigned 16-bit or 32-bit integer
+ <parameter>val</parameter>
+ to buffer
+ <parameter>b</parameter>,
+ in network byte order.
+ </para>
+ <para>
+ Arbitrary amounts of data are read or written from a lightweight
+ resolver buffer with
+ <function>lwres_buffer_getmem()</function>
+ and
+ <function>lwres_buffer_putmem()</function>
+ respectively.
+ <function>lwres_buffer_putmem()</function>
+ copies
+ <parameter>length</parameter>
+ bytes of memory at
+ <parameter>base</parameter>
+ to
+ <parameter>b</parameter>.
+ Conversely,
+ <function>lwres_buffer_getmem()</function>
+ copies
+ <parameter>length</parameter>
+ bytes of memory from
+ <parameter>b</parameter>
+ to
+ <parameter>base</parameter>.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_buffer.html b/lib/lwres/man/lwres_buffer.html
new file mode 100644
index 0000000..deb5262
--- /dev/null
+++ b/lib/lwres/man/lwres_buffer.html
@@ -0,0 +1,455 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_buffer.html,v 1.21 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_buffer</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>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 &#8212; lightweight resolver buffer management</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">
+#include &lt;lwres/lwbuffer.h&gt;
+</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_init</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>void * </td>
+<td>
+<var class="pdparam">base</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned int  </td>
+<td>
+<var class="pdparam">length</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_invalidate</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_add</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned int  </td>
+<td>
+<var class="pdparam">n</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_subtract</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned int  </td>
+<td>
+<var class="pdparam">n</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_clear</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_first</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_forward</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned int  </td>
+<td>
+<var class="pdparam">n</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_back</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned int  </td>
+<td>
+<var class="pdparam">n</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+lwres_uint8_t
+<b class="fsfunc">lwres_buffer_getuint8</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_putuint8</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_uint8_t  </td>
+<td>
+<var class="pdparam">val</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+lwres_uint16_t
+<b class="fsfunc">lwres_buffer_getuint16</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_putuint16</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_uint16_t  </td>
+<td>
+<var class="pdparam">val</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+lwres_uint32_t
+<b class="fsfunc">lwres_buffer_getuint32</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_putuint32</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_uint32_t  </td>
+<td>
+<var class="pdparam">val</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_putmem</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>const unsigned char * </td>
+<td>
+<var class="pdparam">base</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned int  </td>
+<td>
+<var class="pdparam">length</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_buffer_getmem</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned char * </td>
+<td>
+<var class="pdparam">base</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned int  </td>
+<td>
+<var class="pdparam">length</var><code>)</code>;</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543892"></a><h2>DESCRIPTION</h2>
+<p>
+ These functions provide bounds checked access to a region of memory
+ where data is being read or written.
+ They are based on, and similar to, the
+ <code class="literal">isc_buffer_</code>
+ functions in the ISC library.
+ </p>
+<p>
+ A buffer is a region of memory, together with a set of related
+ subregions.
+ The <span class="emphasis"><em>used region</em></span> and the
+ <span class="emphasis"><em>available</em></span> region are disjoint, and
+ their union is the buffer's region.
+ The used region extends from the beginning of the buffer region to the
+ last used byte.
+ The available region extends from one byte greater than the last used
+ byte to the end of the buffer's region.
+ The size of the used region can be changed using various
+ buffer commands.
+ Initially, the used region is empty.
+ </p>
+<p>
+ The used region is further subdivided into two disjoint regions: the
+ <span class="emphasis"><em>consumed region</em></span> and the <span class="emphasis"><em>remaining region</em></span>.
+ The union of these two regions is the used region.
+ The consumed region extends from the beginning of the used region to
+ the byte before the <span class="emphasis"><em>current</em></span> offset (if any).
+ The <span class="emphasis"><em>remaining</em></span> region the current pointer to the end
+ of the used
+ region.
+ The size of the consumed region can be changed using various
+ buffer commands.
+ Initially, the consumed region is empty.
+ </p>
+<p>
+ The <span class="emphasis"><em>active region</em></span> is an (optional) subregion of the
+ remaining
+ region.
+ It extends from the current offset to an offset in the
+ remaining region.
+ Initially, the active region is empty.
+ If the current offset advances beyond the chosen offset,
+ the active region will also be empty.
+ </p>
+<pre class="programlisting">
+ /------------entire length---------------\\
+ /----- used region -----\\/-- available --\\
+ +----------------------------------------+
+ | consumed | remaining | |
+ +----------------------------------------+
+ a b c d e
+ </pre>
+<p>
+ </p>
+<pre class="programlisting">
+ a == base of buffer.
+ b == current pointer. Can be anywhere between a and d.
+ c == active pointer. Meaningful between b and d.
+ d == used pointer.
+ e == length of buffer.
+ </pre>
+<p>
+ </p>
+<pre class="programlisting">
+ a-e == entire length of buffer.
+ a-d == used region.
+ a-b == consumed region.
+ b-d == remaining region.
+ b-c == optional active region.
+</pre>
+<p>
+ </p>
+<p><code class="function">lwres_buffer_init()</code>
+ initializes the
+ <span class="type">lwres_buffer_t</span>
+ <em class="parameter"><code>*b</code></em>
+ and assocates it with the memory region of size
+ <em class="parameter"><code>length</code></em>
+ bytes starting at location
+ <em class="parameter"><code>base.</code></em>
+ </p>
+<p><code class="function">lwres_buffer_invalidate()</code>
+ marks the buffer <em class="parameter"><code>*b</code></em>
+ as invalid. Invalidating a buffer after use is not required,
+ but makes it possible to catch its possible accidental use.
+ </p>
+<p>
+ The functions
+ <code class="function">lwres_buffer_add()</code>
+ and
+ <code class="function">lwres_buffer_subtract()</code>
+ respectively increase and decrease the used space in
+ buffer
+ <em class="parameter"><code>*b</code></em>
+ by
+ <em class="parameter"><code>n</code></em>
+ bytes.
+ <code class="function">lwres_buffer_add()</code>
+ checks for buffer overflow and
+ <code class="function">lwres_buffer_subtract()</code>
+ checks for underflow.
+ These functions do not allocate or deallocate memory.
+ They just change the value of
+ <em class="structfield"><code>used</code></em>.
+ </p>
+<p>
+ A buffer is re-initialised by
+ <code class="function">lwres_buffer_clear()</code>.
+ The function sets
+ <em class="structfield"><code>used</code></em>,
+ <em class="structfield"><code>current</code></em>
+ and
+ <em class="structfield"><code>active</code></em>
+ to zero.
+ </p>
+<p><code class="function">lwres_buffer_first</code>
+ makes the consumed region of buffer
+ <em class="parameter"><code>*p</code></em>
+ empty by setting
+ <em class="structfield"><code>current</code></em>
+ to zero (the start of the buffer).
+ </p>
+<p><code class="function">lwres_buffer_forward()</code>
+ increases the consumed region of buffer
+ <em class="parameter"><code>*b</code></em>
+ by
+ <em class="parameter"><code>n</code></em>
+ bytes, checking for overflow.
+ Similarly,
+ <code class="function">lwres_buffer_back()</code>
+ decreases buffer
+ <em class="parameter"><code>b</code></em>'s
+ consumed region by
+ <em class="parameter"><code>n</code></em>
+ bytes and checks for underflow.
+ </p>
+<p><code class="function">lwres_buffer_getuint8()</code>
+ reads an unsigned 8-bit integer from
+ <em class="parameter"><code>*b</code></em>
+ and returns it.
+ <code class="function">lwres_buffer_putuint8()</code>
+ writes the unsigned 8-bit integer
+ <em class="parameter"><code>val</code></em>
+ to buffer
+ <em class="parameter"><code>*b</code></em>.
+ </p>
+<p><code class="function">lwres_buffer_getuint16()</code>
+ and
+ <code class="function">lwres_buffer_getuint32()</code>
+ are identical to
+ <code class="function">lwres_buffer_putuint8()</code>
+ except that they respectively read an unsigned 16-bit or 32-bit integer
+ in network byte order from
+ <em class="parameter"><code>b</code></em>.
+ Similarly,
+ <code class="function">lwres_buffer_putuint16()</code>
+ and
+ <code class="function">lwres_buffer_putuint32()</code>
+ writes the unsigned 16-bit or 32-bit integer
+ <em class="parameter"><code>val</code></em>
+ to buffer
+ <em class="parameter"><code>b</code></em>,
+ in network byte order.
+ </p>
+<p>
+ Arbitrary amounts of data are read or written from a lightweight
+ resolver buffer with
+ <code class="function">lwres_buffer_getmem()</code>
+ and
+ <code class="function">lwres_buffer_putmem()</code>
+ respectively.
+ <code class="function">lwres_buffer_putmem()</code>
+ copies
+ <em class="parameter"><code>length</code></em>
+ bytes of memory at
+ <em class="parameter"><code>base</code></em>
+ to
+ <em class="parameter"><code>b</code></em>.
+ Conversely,
+ <code class="function">lwres_buffer_getmem()</code>
+ copies
+ <em class="parameter"><code>length</code></em>
+ bytes of memory from
+ <em class="parameter"><code>b</code></em>
+ to
+ <em class="parameter"><code>base</code></em>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_config.3 b/lib/lwres/man/lwres_config.3
new file mode 100644
index 0000000..6184cb2
--- /dev/null
+++ b/lib/lwres/man/lwres_config.3
@@ -0,0 +1,106 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_config.3,v 1.26 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_config
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_CONFIG" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_conf_init, lwres_conf_clear, lwres_conf_parse, lwres_conf_print, lwres_conf_get \- lightweight resolver configuration
+.SH "SYNOPSIS"
+.nf
+#include <lwres/lwres.h>
+.fi
+.HP 21
+.BI "void lwres_conf_init(lwres_context_t\ *" "ctx" ");"
+.HP 22
+.BI "void lwres_conf_clear(lwres_context_t\ *" "ctx" ");"
+.HP 32
+.BI "lwres_result_t lwres_conf_parse(lwres_context_t\ *" "ctx" ", const\ char\ *" "filename" ");"
+.HP 32
+.BI "lwres_result_t lwres_conf_print(lwres_context_t\ *" "ctx" ", FILE\ *" "fp" ");"
+.HP 30
+.BI "lwres_conf_t * lwres_conf_get(lwres_context_t\ *" "ctx" ");"
+.SH "DESCRIPTION"
+.PP
+\fBlwres_conf_init()\fR
+creates an empty
+\fBlwres_conf_t\fR
+structure for lightweight resolver context
+\fIctx\fR.
+.PP
+\fBlwres_conf_clear()\fR
+frees up all the internal memory used by that
+\fBlwres_conf_t\fR
+structure in resolver context
+\fIctx\fR.
+.PP
+\fBlwres_conf_parse()\fR
+opens the file
+\fIfilename\fR
+and parses it to initialise the resolver context
+\fIctx\fR's
+\fBlwres_conf_t\fR
+structure.
+.PP
+\fBlwres_conf_print()\fR
+prints the
+\fBlwres_conf_t\fR
+structure for resolver context
+\fIctx\fR
+to the
+\fBFILE\fR
+\fIfp\fR.
+.SH "RETURN VALUES"
+.PP
+\fBlwres_conf_parse()\fR
+returns
+\fBLWRES_R_SUCCESS\fR
+if it successfully read and parsed
+\fIfilename\fR. It returns
+\fBLWRES_R_FAILURE\fR
+if
+\fIfilename\fR
+could not be opened or contained incorrect resolver statements.
+.PP
+\fBlwres_conf_print()\fR
+returns
+\fBLWRES_R_SUCCESS\fR
+unless an error occurred when converting the network addresses to a numeric host address string. If this happens, the function returns
+\fBLWRES_R_FAILURE\fR.
+.SH "SEE ALSO"
+.PP
+\fBstdio\fR(3),
+\fBresolver\fR(5).
+.SH "FILES"
+.PP
+\fI/etc/resolv.conf\fR
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_config.docbook b/lib/lwres/man/lwres_config.docbook
new file mode 100644
index 0000000..5736ef3
--- /dev/null
+++ b/lib/lwres/man/lwres_config.docbook
@@ -0,0 +1,173 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_config.docbook,v 1.9 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+ <refentryinfo>
+
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_config</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_conf_init</refname>
+ <refname>lwres_conf_clear</refname>
+ <refname>lwres_conf_parse</refname>
+ <refname>lwres_conf_print</refname>
+ <refname>lwres_conf_get</refname>
+ <refpurpose>lightweight resolver configuration</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/lwres.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_conf_init</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_conf_clear</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_conf_parse</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>const char *<parameter>filename</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_conf_print</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>FILE *<parameter>fp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_conf_t *
+<function>lwres_conf_get</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para><function>lwres_conf_init()</function>
+ creates an empty
+ <type>lwres_conf_t</type>
+ structure for lightweight resolver context
+ <parameter>ctx</parameter>.
+ </para>
+
+ <para><function>lwres_conf_clear()</function>
+ frees up all the internal memory used by
+ that
+ <type>lwres_conf_t</type>
+ structure in resolver context
+ <parameter>ctx</parameter>.
+ </para>
+
+ <para><function>lwres_conf_parse()</function>
+ opens the file
+ <parameter>filename</parameter>
+ and parses it to initialise the resolver context
+ <parameter>ctx</parameter>'s
+ <type>lwres_conf_t</type>
+ structure.
+ </para>
+
+ <para><function>lwres_conf_print()</function>
+ prints the
+ <type>lwres_conf_t</type>
+ structure for resolver context
+ <parameter>ctx</parameter>
+ to the
+ <type>FILE</type>
+ <parameter>fp</parameter>.
+ </para>
+ </refsect1>
+ <refsect1>
+
+ <title>RETURN VALUES</title>
+
+ <para><function>lwres_conf_parse()</function>
+ returns <errorcode>LWRES_R_SUCCESS</errorcode>
+ if it successfully read and parsed
+ <parameter>filename</parameter>.
+ It returns <errorcode>LWRES_R_FAILURE</errorcode>
+ if <parameter>filename</parameter>
+ could not be opened or contained incorrect
+ resolver statements.
+ </para>
+
+ <para><function>lwres_conf_print()</function>
+ returns <errorcode>LWRES_R_SUCCESS</errorcode>
+ unless an error occurred when converting the network addresses to a
+ numeric host address string.
+ If this happens, the function returns
+ <errorcode>LWRES_R_FAILURE</errorcode>.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>stdio</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>resolver</refentrytitle><manvolnum>5</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>FILES</title>
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_config.html b/lib/lwres/man/lwres_config.html
new file mode 100644
index 0000000..e27892b
--- /dev/null
+++ b/lib/lwres/man/lwres_config.html
@@ -0,0 +1,156 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_config.html,v 1.22 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_config</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_conf_init, lwres_conf_clear, lwres_conf_parse, lwres_conf_print, lwres_conf_get &#8212; lightweight resolver configuration</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/lwres.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_conf_init</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_conf_clear</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_conf_parse</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>const char * </td>
+<td>
+<var class="pdparam">filename</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_conf_print</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>FILE * </td>
+<td>
+<var class="pdparam">fp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0"><tr>
+<td><code class="funcdef">
+lwres_conf_t *
+<b class="fsfunc">lwres_conf_get</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var><code>)</code>;</td>
+</tr></table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543441"></a><h2>DESCRIPTION</h2>
+<p><code class="function">lwres_conf_init()</code>
+ creates an empty
+ <span class="type">lwres_conf_t</span>
+ structure for lightweight resolver context
+ <em class="parameter"><code>ctx</code></em>.
+ </p>
+<p><code class="function">lwres_conf_clear()</code>
+ frees up all the internal memory used by
+ that
+ <span class="type">lwres_conf_t</span>
+ structure in resolver context
+ <em class="parameter"><code>ctx</code></em>.
+ </p>
+<p><code class="function">lwres_conf_parse()</code>
+ opens the file
+ <em class="parameter"><code>filename</code></em>
+ and parses it to initialise the resolver context
+ <em class="parameter"><code>ctx</code></em>'s
+ <span class="type">lwres_conf_t</span>
+ structure.
+ </p>
+<p><code class="function">lwres_conf_print()</code>
+ prints the
+ <span class="type">lwres_conf_t</span>
+ structure for resolver context
+ <em class="parameter"><code>ctx</code></em>
+ to the
+ <span class="type">FILE</span>
+ <em class="parameter"><code>fp</code></em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543508"></a><h2>RETURN VALUES</h2>
+<p><code class="function">lwres_conf_parse()</code>
+ returns <span class="errorcode">LWRES_R_SUCCESS</span>
+ if it successfully read and parsed
+ <em class="parameter"><code>filename</code></em>.
+ It returns <span class="errorcode">LWRES_R_FAILURE</span>
+ if <em class="parameter"><code>filename</code></em>
+ could not be opened or contained incorrect
+ resolver statements.
+ </p>
+<p><code class="function">lwres_conf_print()</code>
+ returns <span class="errorcode">LWRES_R_SUCCESS</span>
+ unless an error occurred when converting the network addresses to a
+ numeric host address string.
+ If this happens, the function returns
+ <span class="errorcode">LWRES_R_FAILURE</span>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543545"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">stdio</span>(3)</span>,
+ <span class="citerefentry"><span class="refentrytitle">resolver</span>(5)</span>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543571"></a><h2>FILES</h2>
+<p><code class="filename">/etc/resolv.conf</code>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_context.3 b/lib/lwres/man/lwres_context.3
new file mode 100644
index 0000000..b1022d8
--- /dev/null
+++ b/lib/lwres/man/lwres_context.3
@@ -0,0 +1,170 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_context.3,v 1.28 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_context
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_CONTEXT" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "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
+.SH "SYNOPSIS"
+.nf
+#include <lwres/lwres.h>
+.fi
+.HP 36
+.BI "lwres_result_t lwres_context_create(lwres_context_t\ **" "contextp" ", void\ *" "arg" ", lwres_malloc_t\ " "malloc_function" ", lwres_free_t\ " "free_function" ");"
+.HP 37
+.BI "lwres_result_t lwres_context_destroy(lwres_context_t\ **" "contextp" ");"
+.HP 30
+.BI "void lwres_context_initserial(lwres_context_t\ *" "ctx" ", lwres_uint32_t\ " "serial" ");"
+.HP 40
+.BI "lwres_uint32_t lwres_context_nextserial(lwres_context_t\ *" "ctx" ");"
+.HP 27
+.BI "void lwres_context_freemem(lwres_context_t\ *" "ctx" ", void\ *" "mem" ", size_t\ " "len" ");"
+.HP 28
+.BI "void lwres_context_allocmem(lwres_context_t\ *" "ctx" ", size_t\ " "len" ");"
+.HP 30
+.BI "void * lwres_context_sendrecv(lwres_context_t\ *" "ctx" ", void\ *" "sendbase" ", int\ " "sendlen" ", void\ *" "recvbase" ", int\ " "recvlen" ", int\ *" "recvd_len" ");"
+.SH "DESCRIPTION"
+.PP
+\fBlwres_context_create()\fR
+creates a
+\fBlwres_context_t\fR
+structure for use in lightweight resolver operations. It holds a socket and other data needed for communicating with a resolver daemon. The new
+\fBlwres_context_t\fR
+is returned through
+\fIcontextp\fR, a pointer to a
+\fBlwres_context_t\fR
+pointer. This
+\fBlwres_context_t\fR
+pointer must initially be NULL, and is modified to point to the newly created
+\fBlwres_context_t\fR.
+.PP
+When the lightweight resolver needs to perform dynamic memory allocation, it will call
+\fImalloc_function\fR
+to allocate memory and
+\fIfree_function\fR
+to free it. If
+\fImalloc_function\fR
+and
+\fIfree_function\fR
+are NULL, memory is allocated using
+\fBmalloc\fR(3). and
+\fBfree\fR(3). It is not permitted to have a NULL
+\fImalloc_function\fR
+and a non\-NULL
+\fIfree_function\fR
+or vice versa.
+\fIarg\fR
+is passed as the first parameter to the memory allocation functions. If
+\fImalloc_function\fR
+and
+\fIfree_function\fR
+are NULL,
+\fIarg\fR
+is unused and should be passed as NULL.
+.PP
+Once memory for the structure has been allocated, it is initialized using
+\fBlwres_conf_init\fR(3)
+and returned via
+\fI*contextp\fR.
+.PP
+\fBlwres_context_destroy()\fR
+destroys a
+\fBlwres_context_t\fR, closing its socket.
+\fIcontextp\fR
+is a pointer to a pointer to the context that is to be destroyed. The pointer will be set to NULL when the context has been destroyed.
+.PP
+The context holds a serial number that is used to identify resolver request packets and associate responses with the corresponding requests. This serial number is controlled using
+\fBlwres_context_initserial()\fR
+and
+\fBlwres_context_nextserial()\fR.
+\fBlwres_context_initserial()\fR
+sets the serial number for context
+\fI*ctx\fR
+to
+\fIserial\fR.
+\fBlwres_context_nextserial()\fR
+increments the serial number and returns the previous value.
+.PP
+Memory for a lightweight resolver context is allocated and freed using
+\fBlwres_context_allocmem()\fR
+and
+\fBlwres_context_freemem()\fR. These use whatever allocations were defined when the context was created with
+\fBlwres_context_create()\fR.
+\fBlwres_context_allocmem()\fR
+allocates
+\fIlen\fR
+bytes of memory and if successful returns a pointer to the allocated storage.
+\fBlwres_context_freemem()\fR
+frees
+\fIlen\fR
+bytes of space starting at location
+\fImem\fR.
+.PP
+\fBlwres_context_sendrecv()\fR
+performs I/O for the context
+\fIctx\fR. Data are read and written from the context's socket. It writes data from
+\fIsendbase\fR
+\(em typically a lightweight resolver query packet \(em and waits for a reply which is copied to the receive buffer at
+\fIrecvbase\fR. The number of bytes that were written to this receive buffer is returned in
+\fI*recvd_len\fR.
+.SH "RETURN VALUES"
+.PP
+\fBlwres_context_create()\fR
+returns
+\fBLWRES_R_NOMEMORY\fR
+if memory for the
+\fBstruct lwres_context\fR
+could not be allocated,
+\fBLWRES_R_SUCCESS\fR
+otherwise.
+.PP
+Successful calls to the memory allocator
+\fBlwres_context_allocmem()\fR
+return a pointer to the start of the allocated space. It returns NULL if memory could not be allocated.
+.PP
+\fBLWRES_R_SUCCESS\fR
+is returned when
+\fBlwres_context_sendrecv()\fR
+completes successfully.
+\fBLWRES_R_IOERROR\fR
+is returned if an I/O error occurs and
+\fBLWRES_R_TIMEOUT\fR
+is returned if
+\fBlwres_context_sendrecv()\fR
+times out waiting for a response.
+.SH "SEE ALSO"
+.PP
+\fBlwres_conf_init\fR(3),
+\fBmalloc\fR(3),
+\fBfree\fR(3).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001, 2003 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_context.docbook b/lib/lwres/man/lwres_context.docbook
new file mode 100644
index 0000000..ad0392e
--- /dev/null
+++ b/lib/lwres/man/lwres_context.docbook
@@ -0,0 +1,262 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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
+ - 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: lwres_context.docbook,v 1.11 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_context</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_context_create</refname>
+ <refname>lwres_context_destroy</refname>
+ <refname>lwres_context_nextserial</refname>
+ <refname>lwres_context_initserial</refname>
+ <refname>lwres_context_freemem</refname>
+ <refname>lwres_context_allocmem</refname>
+ <refname>lwres_context_sendrecv</refname>
+ <refpurpose>lightweight resolver context management</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/lwres.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_context_create</function></funcdef>
+ <paramdef>lwres_context_t **<parameter>contextp</parameter></paramdef>
+ <paramdef>void *<parameter>arg</parameter></paramdef>
+ <paramdef>lwres_malloc_t <parameter>malloc_function</parameter></paramdef>
+ <paramdef>lwres_free_t <parameter>free_function</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_context_destroy</function></funcdef>
+ <paramdef>lwres_context_t **<parameter>contextp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_context_initserial</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_uint32_t <parameter>serial</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_uint32_t
+<function>lwres_context_nextserial</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_context_freemem</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>void *<parameter>mem</parameter></paramdef>
+ <paramdef>size_t <parameter>len</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_context_allocmem</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>size_t <parameter>len</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void *
+<function>lwres_context_sendrecv</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>void *<parameter>sendbase</parameter></paramdef>
+ <paramdef>int <parameter>sendlen</parameter></paramdef>
+ <paramdef>void *<parameter>recvbase</parameter></paramdef>
+ <paramdef>int <parameter>recvlen</parameter></paramdef>
+ <paramdef>int *<parameter>recvd_len</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para><function>lwres_context_create()</function>
+ creates a <type>lwres_context_t</type> structure for use in
+ lightweight resolver operations. It holds a socket and other
+ data needed for communicating with a resolver daemon. The new
+ <type>lwres_context_t</type> is returned through
+ <parameter>contextp</parameter>, a pointer to a
+ <type>lwres_context_t</type> pointer. This
+ <type>lwres_context_t</type> pointer must initially be NULL, and
+ is modified to point to the newly created
+ <type>lwres_context_t</type>.
+ </para>
+ <para>
+ When the lightweight resolver needs to perform dynamic memory
+ allocation, it will call
+ <parameter>malloc_function</parameter>
+ to allocate memory and
+ <parameter>free_function</parameter>
+ to free it. If
+ <parameter>malloc_function</parameter>
+ and
+ <parameter>free_function</parameter>
+ are NULL, memory is allocated using
+ <citerefentry>
+ <refentrytitle>malloc</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ and
+ <citerefentry>
+ <refentrytitle>free</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+
+ It is not permitted to have a NULL
+ <parameter>malloc_function</parameter> and a non-NULL
+ <parameter>free_function</parameter> or vice versa.
+ <parameter>arg</parameter> is passed as the first parameter to
+ the memory allocation functions. If
+ <parameter>malloc_function</parameter> and
+ <parameter>free_function</parameter> are NULL,
+ <parameter>arg</parameter> is unused and should be passed as
+ NULL.
+ </para>
+
+ <para>
+ Once memory for the structure has been allocated,
+ it is initialized using
+ <citerefentry>
+ <refentrytitle>lwres_conf_init</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ and returned via <parameter>*contextp</parameter>.
+ </para>
+
+ <para><function>lwres_context_destroy()</function>
+ destroys a <type>lwres_context_t</type>, closing its socket.
+ <parameter>contextp</parameter> is a pointer to a pointer to the
+ context that is to be destroyed. The pointer will be set to
+ NULL when the context has been destroyed.
+ </para>
+
+ <para>
+ The context holds a serial number that is used to identify
+ resolver request packets and associate responses with the
+ corresponding requests. This serial number is controlled using
+ <function>lwres_context_initserial()</function> and
+ <function>lwres_context_nextserial()</function>.
+ <function>lwres_context_initserial()</function> sets the serial
+ number for context <parameter>*ctx</parameter> to
+ <parameter>serial</parameter>.
+ <function>lwres_context_nextserial()</function> increments the
+ serial number and returns the previous value.
+ </para>
+
+ <para>
+ Memory for a lightweight resolver context is allocated and freed
+ using <function>lwres_context_allocmem()</function> and
+ <function>lwres_context_freemem()</function>. These use
+ whatever allocations were defined when the context was created
+ with <function>lwres_context_create()</function>.
+ <function>lwres_context_allocmem()</function> allocates
+ <parameter>len</parameter> bytes of memory and if successful
+ returns a pointer to the allocated storage.
+ <function>lwres_context_freemem()</function> frees
+ <parameter>len</parameter> bytes of space starting at location
+ <parameter>mem</parameter>.
+ </para>
+
+ <para><function>lwres_context_sendrecv()</function>
+ performs I/O for the context <parameter>ctx</parameter>. Data
+ are read and written from the context's socket. It writes data
+ from <parameter>sendbase</parameter> &mdash; typically a
+ lightweight resolver query packet &mdash; and waits for a reply
+ which is copied to the receive buffer at
+ <parameter>recvbase</parameter>. The number of bytes that were
+ written to this receive buffer is returned in
+ <parameter>*recvd_len</parameter>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>RETURN VALUES</title>
+
+ <para><function>lwres_context_create()</function>
+ returns <errorcode>LWRES_R_NOMEMORY</errorcode> if memory for
+ the <type>struct lwres_context</type> could not be allocated,
+ <errorcode>LWRES_R_SUCCESS</errorcode> otherwise.
+ </para>
+ <para>
+ Successful calls to the memory allocator
+ <function>lwres_context_allocmem()</function>
+ return a pointer to the start of the allocated space.
+ It returns NULL if memory could not be allocated.
+ </para>
+ <para><errorcode>LWRES_R_SUCCESS</errorcode>
+ is returned when
+ <function>lwres_context_sendrecv()</function>
+ completes successfully.
+ <errorcode>LWRES_R_IOERROR</errorcode>
+ is returned if an I/O error occurs and
+ <errorcode>LWRES_R_TIMEOUT</errorcode>
+ is returned if
+ <function>lwres_context_sendrecv()</function>
+ times out waiting for a response.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>lwres_conf_init</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>malloc</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>free</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_context.html b/lib/lwres/man/lwres_context.html
new file mode 100644
index 0000000..18c3d38
--- /dev/null
+++ b/lib/lwres/man/lwres_context.html
@@ -0,0 +1,295 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_context.html,v 1.23 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_context</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_context_create, lwres_context_destroy, lwres_context_nextserial, lwres_context_initserial, lwres_context_freemem, lwres_context_allocmem, lwres_context_sendrecv &#8212; lightweight resolver context management</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/lwres.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_context_create</b>(</code></td>
+<td>lwres_context_t ** </td>
+<td>
+<var class="pdparam">contextp</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>void * </td>
+<td>
+<var class="pdparam">arg</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_malloc_t  </td>
+<td>
+<var class="pdparam">malloc_function</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_free_t  </td>
+<td>
+<var class="pdparam">free_function</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_context_destroy</b>(</code></td>
+<td>lwres_context_t ** </td>
+<td>
+<var class="pdparam">contextp</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_context_initserial</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_uint32_t  </td>
+<td>
+<var class="pdparam">serial</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+lwres_uint32_t
+<b class="fsfunc">lwres_context_nextserial</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_context_freemem</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>void * </td>
+<td>
+<var class="pdparam">mem</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>size_t  </td>
+<td>
+<var class="pdparam">len</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_context_allocmem</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>size_t  </td>
+<td>
+<var class="pdparam">len</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0">
+<tr>
+<td><code class="funcdef">
+void *
+<b class="fsfunc">lwres_context_sendrecv</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>void * </td>
+<td>
+<var class="pdparam">sendbase</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">sendlen</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>void * </td>
+<td>
+<var class="pdparam">recvbase</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">recvlen</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int * </td>
+<td>
+<var class="pdparam">recvd_len</var><code>)</code>;</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543531"></a><h2>DESCRIPTION</h2>
+<p><code class="function">lwres_context_create()</code>
+ creates a <span class="type">lwres_context_t</span> structure for use in
+ lightweight resolver operations. It holds a socket and other
+ data needed for communicating with a resolver daemon. The new
+ <span class="type">lwres_context_t</span> is returned through
+ <em class="parameter"><code>contextp</code></em>, a pointer to a
+ <span class="type">lwres_context_t</span> pointer. This
+ <span class="type">lwres_context_t</span> pointer must initially be NULL, and
+ is modified to point to the newly created
+ <span class="type">lwres_context_t</span>.
+ </p>
+<p>
+ When the lightweight resolver needs to perform dynamic memory
+ allocation, it will call
+ <em class="parameter"><code>malloc_function</code></em>
+ to allocate memory and
+ <em class="parameter"><code>free_function</code></em>
+ to free it. If
+ <em class="parameter"><code>malloc_function</code></em>
+ and
+ <em class="parameter"><code>free_function</code></em>
+ are NULL, memory is allocated using
+ <span class="citerefentry"><span class="refentrytitle">malloc</span>(3)</span>.
+ and
+ <span class="citerefentry"><span class="refentrytitle">free</span>(3)</span>.
+
+ It is not permitted to have a NULL
+ <em class="parameter"><code>malloc_function</code></em> and a non-NULL
+ <em class="parameter"><code>free_function</code></em> or vice versa.
+ <em class="parameter"><code>arg</code></em> is passed as the first parameter to
+ the memory allocation functions. If
+ <em class="parameter"><code>malloc_function</code></em> and
+ <em class="parameter"><code>free_function</code></em> are NULL,
+ <em class="parameter"><code>arg</code></em> is unused and should be passed as
+ NULL.
+ </p>
+<p>
+ Once memory for the structure has been allocated,
+ it is initialized using
+ <span class="citerefentry"><span class="refentrytitle">lwres_conf_init</span>(3)</span>
+ and returned via <em class="parameter"><code>*contextp</code></em>.
+ </p>
+<p><code class="function">lwres_context_destroy()</code>
+ destroys a <span class="type">lwres_context_t</span>, closing its socket.
+ <em class="parameter"><code>contextp</code></em> is a pointer to a pointer to the
+ context that is to be destroyed. The pointer will be set to
+ NULL when the context has been destroyed.
+ </p>
+<p>
+ The context holds a serial number that is used to identify
+ resolver request packets and associate responses with the
+ corresponding requests. This serial number is controlled using
+ <code class="function">lwres_context_initserial()</code> and
+ <code class="function">lwres_context_nextserial()</code>.
+ <code class="function">lwres_context_initserial()</code> sets the serial
+ number for context <em class="parameter"><code>*ctx</code></em> to
+ <em class="parameter"><code>serial</code></em>.
+ <code class="function">lwres_context_nextserial()</code> increments the
+ serial number and returns the previous value.
+ </p>
+<p>
+ Memory for a lightweight resolver context is allocated and freed
+ using <code class="function">lwres_context_allocmem()</code> and
+ <code class="function">lwres_context_freemem()</code>. These use
+ whatever allocations were defined when the context was created
+ with <code class="function">lwres_context_create()</code>.
+ <code class="function">lwres_context_allocmem()</code> allocates
+ <em class="parameter"><code>len</code></em> bytes of memory and if successful
+ returns a pointer to the allocated storage.
+ <code class="function">lwres_context_freemem()</code> frees
+ <em class="parameter"><code>len</code></em> bytes of space starting at location
+ <em class="parameter"><code>mem</code></em>.
+ </p>
+<p><code class="function">lwres_context_sendrecv()</code>
+ performs I/O for the context <em class="parameter"><code>ctx</code></em>. Data
+ are read and written from the context's socket. It writes data
+ from <em class="parameter"><code>sendbase</code></em> &#8212; typically a
+ lightweight resolver query packet &#8212; and waits for a reply
+ which is copied to the receive buffer at
+ <em class="parameter"><code>recvbase</code></em>. The number of bytes that were
+ written to this receive buffer is returned in
+ <em class="parameter"><code>*recvd_len</code></em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543719"></a><h2>RETURN VALUES</h2>
+<p><code class="function">lwres_context_create()</code>
+ returns <span class="errorcode">LWRES_R_NOMEMORY</span> if memory for
+ the <span class="type">struct lwres_context</span> could not be allocated,
+ <span class="errorcode">LWRES_R_SUCCESS</span> otherwise.
+ </p>
+<p>
+ Successful calls to the memory allocator
+ <code class="function">lwres_context_allocmem()</code>
+ return a pointer to the start of the allocated space.
+ It returns NULL if memory could not be allocated.
+ </p>
+<p><span class="errorcode">LWRES_R_SUCCESS</span>
+ is returned when
+ <code class="function">lwres_context_sendrecv()</code>
+ completes successfully.
+ <span class="errorcode">LWRES_R_IOERROR</span>
+ is returned if an I/O error occurs and
+ <span class="errorcode">LWRES_R_TIMEOUT</span>
+ is returned if
+ <code class="function">lwres_context_sendrecv()</code>
+ times out waiting for a response.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543769"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">lwres_conf_init</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">malloc</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">free</span>(3)</span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_gabn.3 b/lib/lwres/man/lwres_gabn.3
new file mode 100644
index 0000000..0c14384
--- /dev/null
+++ b/lib/lwres/man/lwres_gabn.3
@@ -0,0 +1,195 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_gabn.3,v 1.27 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_gabn
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_GABN" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_gabnrequest_render, lwres_gabnresponse_render, lwres_gabnrequest_parse, lwres_gabnresponse_parse, lwres_gabnresponse_free, lwres_gabnrequest_free \- lightweight resolver getaddrbyname message handling
+.SH "SYNOPSIS"
+.nf
+#include <lwres/lwres.h>
+.fi
+.HP 40
+.BI "lwres_result_t lwres_gabnrequest_render(lwres_context_t\ *" "ctx" ", lwres_gabnrequest_t\ *" "req" ", lwres_lwpacket_t\ *" "pkt" ", lwres_buffer_t\ *" "b" ");"
+.HP 41
+.BI "lwres_result_t lwres_gabnresponse_render(lwres_context_t\ *" "ctx" ", lwres_gabnresponse_t\ *" "req" ", lwres_lwpacket_t\ *" "pkt" ", lwres_buffer_t\ *" "b" ");"
+.HP 39
+.BI "lwres_result_t lwres_gabnrequest_parse(lwres_context_t\ *" "ctx" ", lwres_buffer_t\ *" "b" ", lwres_lwpacket_t\ *" "pkt" ", lwres_gabnrequest_t\ **" "structp" ");"
+.HP 40
+.BI "lwres_result_t lwres_gabnresponse_parse(lwres_context_t\ *" "ctx" ", lwres_buffer_t\ *" "b" ", lwres_lwpacket_t\ *" "pkt" ", lwres_gabnresponse_t\ **" "structp" ");"
+.HP 29
+.BI "void lwres_gabnresponse_free(lwres_context_t\ *" "ctx" ", lwres_gabnresponse_t\ **" "structp" ");"
+.HP 28
+.BI "void lwres_gabnrequest_free(lwres_context_t\ *" "ctx" ", lwres_gabnrequest_t\ **" "structp" ");"
+.SH "DESCRIPTION"
+.PP
+These are low\-level routines for creating and parsing lightweight resolver name\-to\-address lookup request and response messages.
+.PP
+There are four main functions for the getaddrbyname opcode. One render function converts a getaddrbyname request structure \(em
+\fBlwres_gabnrequest_t\fR
+\(em to the lighweight resolver's canonical format. It is complemented by a parse function that converts a packet in this canonical format to a getaddrbyname request structure. Another render function converts the getaddrbyname response structure \(em
+\fBlwres_gabnresponse_t\fR
+\(em to the canonical format. This is complemented by a parse function which converts a packet in canonical format to a getaddrbyname response structure.
+.PP
+These structures are defined in
+\fI<lwres/lwres.h>\fR. They are shown below.
+.PP
+.RS 4
+.nf
+#define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+typedef struct lwres_addr lwres_addr_t;
+typedef LWRES_LIST(lwres_addr_t) lwres_addrlist_t;
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint32_t addrtypes;
+ lwres_uint16_t namelen;
+ char *name;
+} lwres_gabnrequest_t;
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ lwres_uint16_t naddrs;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ lwres_addrlist_t addrs;
+ void *base;
+ size_t baselen;
+} lwres_gabnresponse_t;
+.fi
+.RE
+.sp
+.PP
+\fBlwres_gabnrequest_render()\fR
+uses resolver context
+\fIctx\fR
+to convert getaddrbyname request structure
+\fIreq\fR
+to canonical format. The packet header structure
+\fIpkt\fR
+is initialised and transferred to buffer
+\fIb\fR. The contents of
+\fI*req\fR
+are then appended to the buffer in canonical format.
+\fBlwres_gabnresponse_render()\fR
+performs the same task, except it converts a getaddrbyname response structure
+\fBlwres_gabnresponse_t\fR
+to the lightweight resolver's canonical format.
+.PP
+\fBlwres_gabnrequest_parse()\fR
+uses context
+\fIctx\fR
+to convert the contents of packet
+\fIpkt\fR
+to a
+\fBlwres_gabnrequest_t\fR
+structure. Buffer
+\fIb\fR
+provides space to be used for storing this structure. When the function succeeds, the resulting
+\fBlwres_gabnrequest_t\fR
+is made available through
+\fI*structp\fR.
+\fBlwres_gabnresponse_parse()\fR
+offers the same semantics as
+\fBlwres_gabnrequest_parse()\fR
+except it yields a
+\fBlwres_gabnresponse_t\fR
+structure.
+.PP
+\fBlwres_gabnresponse_free()\fR
+and
+\fBlwres_gabnrequest_free()\fR
+release the memory in resolver context
+\fIctx\fR
+that was allocated to the
+\fBlwres_gabnresponse_t\fR
+or
+\fBlwres_gabnrequest_t\fR
+structures referenced via
+\fIstructp\fR. Any memory associated with ancillary buffers and strings for those structures is also discarded.
+.SH "RETURN VALUES"
+.PP
+The getaddrbyname opcode functions
+\fBlwres_gabnrequest_render()\fR,
+\fBlwres_gabnresponse_render()\fR
+\fBlwres_gabnrequest_parse()\fR
+and
+\fBlwres_gabnresponse_parse()\fR
+all return
+\fBLWRES_R_SUCCESS\fR
+on success. They return
+\fBLWRES_R_NOMEMORY\fR
+if memory allocation fails.
+\fBLWRES_R_UNEXPECTEDEND\fR
+is returned if the available space in the buffer
+\fIb\fR
+is too small to accommodate the packet header or the
+\fBlwres_gabnrequest_t\fR
+and
+\fBlwres_gabnresponse_t\fR
+structures.
+\fBlwres_gabnrequest_parse()\fR
+and
+\fBlwres_gabnresponse_parse()\fR
+will return
+\fBLWRES_R_UNEXPECTEDEND\fR
+if the buffer is not empty after decoding the received packet. These functions will return
+\fBLWRES_R_FAILURE\fR
+if
+pktflags
+in the packet header structure
+\fBlwres_lwpacket_t\fR
+indicate that the packet is not a response to an earlier query.
+.SH "SEE ALSO"
+.PP
+\fBlwres_packet\fR(3)
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_gabn.docbook b/lib/lwres/man/lwres_gabn.docbook
new file mode 100644
index 0000000..d0b5c19
--- /dev/null
+++ b/lib/lwres/man/lwres_gabn.docbook
@@ -0,0 +1,260 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_gabn.docbook,v 1.10 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_gabn</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_gabnrequest_render</refname>
+ <refname>lwres_gabnresponse_render</refname>
+ <refname>lwres_gabnrequest_parse</refname>
+ <refname>lwres_gabnresponse_parse</refname>
+ <refname>lwres_gabnresponse_free</refname>
+ <refname>lwres_gabnrequest_free</refname>
+ <refpurpose>lightweight resolver getaddrbyname message handling</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/lwres.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_gabnrequest_render</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_gabnrequest_t *<parameter>req</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_gabnresponse_render</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_gabnresponse_t *<parameter>req</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_gabnrequest_parse</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_gabnrequest_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_gabnresponse_parse</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_gabnresponse_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_gabnresponse_free</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_gabnresponse_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_gabnrequest_free</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_gabnrequest_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ These are low-level routines for creating and parsing
+ lightweight resolver name-to-address lookup request and
+ response messages.
+ </para>
+ <para>
+ There are four main functions for the getaddrbyname opcode.
+ One render function converts a getaddrbyname request structure &mdash;
+ <type>lwres_gabnrequest_t</type> &mdash;
+ to the lighweight resolver's canonical format.
+ It is complemented by a parse function that converts a packet in this
+ canonical format to a getaddrbyname request structure.
+ Another render function converts the getaddrbyname response structure
+ &mdash; <type>lwres_gabnresponse_t</type> &mdash;
+ to the canonical format.
+ This is complemented by a parse function which converts a packet in
+ canonical format to a getaddrbyname response structure.
+ </para>
+ <para>
+ These structures are defined in
+ <filename>&lt;lwres/lwres.h&gt;</filename>.
+ They are shown below.
+ </para>
+ <para><programlisting>
+#define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
+</programlisting>
+ </para>
+ <para><programlisting>
+typedef struct lwres_addr lwres_addr_t;
+typedef LWRES_LIST(lwres_addr_t) lwres_addrlist_t;
+</programlisting>
+ </para>
+ <para><programlisting>
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint32_t addrtypes;
+ lwres_uint16_t namelen;
+ char *name;
+} lwres_gabnrequest_t;
+</programlisting>
+ </para>
+ <para><programlisting>
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ lwres_uint16_t naddrs;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ lwres_addrlist_t addrs;
+ void *base;
+ size_t baselen;
+} lwres_gabnresponse_t;
+</programlisting>
+ </para>
+
+ <para><function>lwres_gabnrequest_render()</function>
+ uses resolver context <parameter>ctx</parameter> to convert
+ getaddrbyname request structure <parameter>req</parameter> to
+ canonical format. The packet header structure
+ <parameter>pkt</parameter> is initialised and transferred to
+ buffer <parameter>b</parameter>.
+
+ The contents of <parameter>*req</parameter> are then appended to
+ the buffer in canonical format.
+ <function>lwres_gabnresponse_render()</function> performs the
+ same task, except it converts a getaddrbyname response structure
+ <type>lwres_gabnresponse_t</type> to the lightweight resolver's
+ canonical format.
+ </para>
+
+ <para><function>lwres_gabnrequest_parse()</function>
+ uses context <parameter>ctx</parameter> to convert the contents
+ of packet <parameter>pkt</parameter> to a
+ <type>lwres_gabnrequest_t</type> structure. Buffer
+ <parameter>b</parameter> provides space to be used for storing
+ this structure. When the function succeeds, the resulting
+ <type>lwres_gabnrequest_t</type> is made available through
+ <parameter>*structp</parameter>.
+
+ <function>lwres_gabnresponse_parse()</function> offers the same
+ semantics as <function>lwres_gabnrequest_parse()</function>
+ except it yields a <type>lwres_gabnresponse_t</type> structure.
+ </para>
+
+ <para><function>lwres_gabnresponse_free()</function>
+ and <function>lwres_gabnrequest_free()</function> release the
+ memory in resolver context <parameter>ctx</parameter> that was
+ allocated to the <type>lwres_gabnresponse_t</type> or
+ <type>lwres_gabnrequest_t</type> structures referenced via
+ <parameter>structp</parameter>.
+
+ Any memory associated with ancillary buffers and strings for
+ those structures is also discarded.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para>
+ The getaddrbyname opcode functions
+ <function>lwres_gabnrequest_render()</function>,
+ <function>lwres_gabnresponse_render()</function>
+ <function>lwres_gabnrequest_parse()</function>
+ and
+ <function>lwres_gabnresponse_parse()</function>
+ all return
+ <errorcode>LWRES_R_SUCCESS</errorcode>
+ on success.
+ They return
+ <errorcode>LWRES_R_NOMEMORY</errorcode>
+ if memory allocation fails.
+ <errorcode>LWRES_R_UNEXPECTEDEND</errorcode>
+ is returned if the available space in the buffer
+ <parameter>b</parameter>
+ is too small to accommodate the packet header or the
+ <type>lwres_gabnrequest_t</type>
+ and
+ <type>lwres_gabnresponse_t</type>
+ structures.
+ <function>lwres_gabnrequest_parse()</function>
+ and
+ <function>lwres_gabnresponse_parse()</function>
+ will return
+ <errorcode>LWRES_R_UNEXPECTEDEND</errorcode>
+ if the buffer is not empty after decoding the received packet.
+ These functions will return
+ <errorcode>LWRES_R_FAILURE</errorcode>
+ if
+ <structfield>pktflags</structfield>
+ in the packet header structure
+ <type>lwres_lwpacket_t</type>
+ indicate that the packet is not a response to an earlier query.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>lwres_packet</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_gabn.html b/lib/lwres/man/lwres_gabn.html
new file mode 100644
index 0000000..a51d252
--- /dev/null
+++ b/lib/lwres/man/lwres_gabn.html
@@ -0,0 +1,324 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_gabn.html,v 1.24 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_gabn</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_gabnrequest_render, lwres_gabnresponse_render, lwres_gabnrequest_parse, lwres_gabnresponse_parse, lwres_gabnresponse_free, lwres_gabnrequest_free &#8212; lightweight resolver getaddrbyname message handling</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/lwres.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_gabnrequest_render</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gabnrequest_t * </td>
+<td>
+<var class="pdparam">req</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_gabnresponse_render</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gabnresponse_t * </td>
+<td>
+<var class="pdparam">req</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_gabnrequest_parse</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gabnrequest_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_gabnresponse_parse</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gabnresponse_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_gabnresponse_free</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gabnresponse_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_gabnrequest_free</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gabnrequest_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543522"></a><h2>DESCRIPTION</h2>
+<p>
+ These are low-level routines for creating and parsing
+ lightweight resolver name-to-address lookup request and
+ response messages.
+ </p>
+<p>
+ There are four main functions for the getaddrbyname opcode.
+ One render function converts a getaddrbyname request structure &#8212;
+ <span class="type">lwres_gabnrequest_t</span> &#8212;
+ to the lighweight resolver's canonical format.
+ It is complemented by a parse function that converts a packet in this
+ canonical format to a getaddrbyname request structure.
+ Another render function converts the getaddrbyname response structure
+ &#8212; <span class="type">lwres_gabnresponse_t</span> &#8212;
+ to the canonical format.
+ This is complemented by a parse function which converts a packet in
+ canonical format to a getaddrbyname response structure.
+ </p>
+<p>
+ These structures are defined in
+ <code class="filename">&lt;lwres/lwres.h&gt;</code>.
+ They are shown below.
+ </p>
+<pre class="programlisting">
+#define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+typedef struct lwres_addr lwres_addr_t;
+typedef LWRES_LIST(lwres_addr_t) lwres_addrlist_t;
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint32_t addrtypes;
+ lwres_uint16_t namelen;
+ char *name;
+} lwres_gabnrequest_t;
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ lwres_uint16_t naddrs;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ lwres_addrlist_t addrs;
+ void *base;
+ size_t baselen;
+} lwres_gabnresponse_t;
+</pre>
+<p>
+ </p>
+<p><code class="function">lwres_gabnrequest_render()</code>
+ uses resolver context <em class="parameter"><code>ctx</code></em> to convert
+ getaddrbyname request structure <em class="parameter"><code>req</code></em> to
+ canonical format. The packet header structure
+ <em class="parameter"><code>pkt</code></em> is initialised and transferred to
+ buffer <em class="parameter"><code>b</code></em>.
+
+ The contents of <em class="parameter"><code>*req</code></em> are then appended to
+ the buffer in canonical format.
+ <code class="function">lwres_gabnresponse_render()</code> performs the
+ same task, except it converts a getaddrbyname response structure
+ <span class="type">lwres_gabnresponse_t</span> to the lightweight resolver's
+ canonical format.
+ </p>
+<p><code class="function">lwres_gabnrequest_parse()</code>
+ uses context <em class="parameter"><code>ctx</code></em> to convert the contents
+ of packet <em class="parameter"><code>pkt</code></em> to a
+ <span class="type">lwres_gabnrequest_t</span> structure. Buffer
+ <em class="parameter"><code>b</code></em> provides space to be used for storing
+ this structure. When the function succeeds, the resulting
+ <span class="type">lwres_gabnrequest_t</span> is made available through
+ <em class="parameter"><code>*structp</code></em>.
+
+ <code class="function">lwres_gabnresponse_parse()</code> offers the same
+ semantics as <code class="function">lwres_gabnrequest_parse()</code>
+ except it yields a <span class="type">lwres_gabnresponse_t</span> structure.
+ </p>
+<p><code class="function">lwres_gabnresponse_free()</code>
+ and <code class="function">lwres_gabnrequest_free()</code> release the
+ memory in resolver context <em class="parameter"><code>ctx</code></em> that was
+ allocated to the <span class="type">lwres_gabnresponse_t</span> or
+ <span class="type">lwres_gabnrequest_t</span> structures referenced via
+ <em class="parameter"><code>structp</code></em>.
+
+ Any memory associated with ancillary buffers and strings for
+ those structures is also discarded.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543667"></a><h2>RETURN VALUES</h2>
+<p>
+ The getaddrbyname opcode functions
+ <code class="function">lwres_gabnrequest_render()</code>,
+ <code class="function">lwres_gabnresponse_render()</code>
+ <code class="function">lwres_gabnrequest_parse()</code>
+ and
+ <code class="function">lwres_gabnresponse_parse()</code>
+ all return
+ <span class="errorcode">LWRES_R_SUCCESS</span>
+ on success.
+ They return
+ <span class="errorcode">LWRES_R_NOMEMORY</span>
+ if memory allocation fails.
+ <span class="errorcode">LWRES_R_UNEXPECTEDEND</span>
+ is returned if the available space in the buffer
+ <em class="parameter"><code>b</code></em>
+ is too small to accommodate the packet header or the
+ <span class="type">lwres_gabnrequest_t</span>
+ and
+ <span class="type">lwres_gabnresponse_t</span>
+ structures.
+ <code class="function">lwres_gabnrequest_parse()</code>
+ and
+ <code class="function">lwres_gabnresponse_parse()</code>
+ will return
+ <span class="errorcode">LWRES_R_UNEXPECTEDEND</span>
+ if the buffer is not empty after decoding the received packet.
+ These functions will return
+ <span class="errorcode">LWRES_R_FAILURE</span>
+ if
+ <em class="structfield"><code>pktflags</code></em>
+ in the packet header structure
+ <span class="type">lwres_lwpacket_t</span>
+ indicate that the packet is not a response to an earlier query.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543733"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">lwres_packet</span>(3)</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_gai_strerror.3 b/lib/lwres/man/lwres_gai_strerror.3
new file mode 100644
index 0000000..e412b8f
--- /dev/null
+++ b/lib/lwres/man/lwres_gai_strerror.3
@@ -0,0 +1,129 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_gai_strerror.3,v 1.27 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_gai_strerror
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_GAI_STRERROR" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_gai_strerror \- print suitable error string
+.SH "SYNOPSIS"
+.nf
+#include <lwres/netdb.h>
+.fi
+.HP 20
+.BI "char * gai_strerror(int\ " "ecode" ");"
+.SH "DESCRIPTION"
+.PP
+\fBlwres_gai_strerror()\fR
+returns an error message corresponding to an error code returned by
+\fBgetaddrinfo()\fR. The following error codes and their meaning are defined in
+\fIinclude/lwres/netdb.h\fR.
+.PP
+\fBEAI_ADDRFAMILY\fR
+.RS 4
+address family for hostname not supported
+.RE
+.PP
+\fBEAI_AGAIN\fR
+.RS 4
+temporary failure in name resolution
+.RE
+.PP
+\fBEAI_BADFLAGS\fR
+.RS 4
+invalid value for
+\fBai_flags\fR
+.RE
+.PP
+\fBEAI_FAIL\fR
+.RS 4
+non\-recoverable failure in name resolution
+.RE
+.PP
+\fBEAI_FAMILY\fR
+.RS 4
+\fBai_family\fR
+not supported
+.RE
+.PP
+\fBEAI_MEMORY\fR
+.RS 4
+memory allocation failure
+.RE
+.PP
+\fBEAI_NODATA\fR
+.RS 4
+no address associated with hostname
+.RE
+.PP
+\fBEAI_NONAME\fR
+.RS 4
+hostname or servname not provided, or not known
+.RE
+.PP
+\fBEAI_SERVICE\fR
+.RS 4
+servname not supported for
+\fBai_socktype\fR
+.RE
+.PP
+\fBEAI_SOCKTYPE\fR
+.RS 4
+\fBai_socktype\fR
+not supported
+.RE
+.PP
+\fBEAI_SYSTEM\fR
+.RS 4
+system error returned in errno
+.RE
+The message
+invalid error code
+is returned if
+\fIecode\fR
+is out of range.
+.PP
+\fBai_flags\fR,
+\fBai_family\fR
+and
+\fBai_socktype\fR
+are elements of the
+\fBstruct addrinfo\fR
+used by
+\fBlwres_getaddrinfo()\fR.
+.SH "SEE ALSO"
+.PP
+\fBstrerror\fR(3),
+\fBlwres_getaddrinfo\fR(3),
+\fBgetaddrinfo\fR(3),
+\fBRFC2133\fR().
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_gai_strerror.docbook b/lib/lwres/man/lwres_gai_strerror.docbook
new file mode 100644
index 0000000..c33fee5
--- /dev/null
+++ b/lib/lwres/man/lwres_gai_strerror.docbook
@@ -0,0 +1,200 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_gai_strerror.docbook,v 1.10 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_gai_strerror</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_gai_strerror</refname>
+ <refpurpose>print suitable error string</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/netdb.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+char *
+<function>gai_strerror</function></funcdef>
+ <paramdef>int <parameter>ecode</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para><function>lwres_gai_strerror()</function>
+ returns an error message corresponding to an error code returned by
+ <function>getaddrinfo()</function>.
+ The following error codes and their meaning are defined in
+ <filename>include/lwres/netdb.h</filename>.
+ <variablelist>
+ <varlistentry>
+ <term><errorcode>EAI_ADDRFAMILY</errorcode></term>
+ <listitem>
+ <para>
+ address family for hostname not supported
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EAI_AGAIN</errorcode></term>
+ <listitem>
+ <para>
+ temporary failure in name resolution
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EAI_BADFLAGS</errorcode></term>
+ <listitem>
+ <para>
+ invalid value for
+ <constant>ai_flags</constant>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EAI_FAIL</errorcode></term>
+ <listitem>
+ <para>
+ non-recoverable failure in name resolution
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EAI_FAMILY</errorcode></term>
+ <listitem>
+ <para><constant>ai_family</constant> not supported
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EAI_MEMORY</errorcode></term>
+ <listitem>
+ <para>
+ memory allocation failure
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EAI_NODATA</errorcode></term>
+ <listitem>
+ <para>
+ no address associated with hostname
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EAI_NONAME</errorcode></term>
+ <listitem>
+ <para>
+ hostname or servname not provided, or not known
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EAI_SERVICE</errorcode></term>
+ <listitem>
+ <para>
+ servname not supported for <constant>ai_socktype</constant>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EAI_SOCKTYPE</errorcode></term>
+ <listitem>
+ <para><constant>ai_socktype</constant> not supported
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>EAI_SYSTEM</errorcode></term>
+ <listitem>
+ <para>
+ system error returned in errno
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ The message <errorname>invalid error code</errorname> is returned if
+ <parameter>ecode</parameter>
+ is out of range.
+ </para>
+ <para><constant>ai_flags</constant>,
+ <constant>ai_family</constant>
+ and
+ <constant>ai_socktype</constant>
+ are elements of the
+ <type>struct addrinfo</type>
+ used by
+ <function>lwres_getaddrinfo()</function>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>strerror</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_getaddrinfo</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>getaddrinfo</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>RFC2133</refentrytitle>
+ </citerefentry>.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_gai_strerror.html b/lib/lwres/man/lwres_gai_strerror.html
new file mode 100644
index 0000000..c64beb1
--- /dev/null
+++ b/lib/lwres/man/lwres_gai_strerror.html
@@ -0,0 +1,124 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_gai_strerror.html,v 1.24 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_gai_strerror</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_gai_strerror &#8212; print suitable error string</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/netdb.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0"><tr>
+<td><code class="funcdef">
+char *
+<b class="fsfunc">gai_strerror</b>(</code></td>
+<td>int  </td>
+<td>
+<var class="pdparam">ecode</var><code>)</code>;</td>
+</tr></table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543361"></a><h2>DESCRIPTION</h2>
+<p><code class="function">lwres_gai_strerror()</code>
+ returns an error message corresponding to an error code returned by
+ <code class="function">getaddrinfo()</code>.
+ The following error codes and their meaning are defined in
+ <code class="filename">include/lwres/netdb.h</code>.
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span class="errorcode">EAI_ADDRFAMILY</span></span></dt>
+<dd><p>
+ address family for hostname not supported
+ </p></dd>
+<dt><span class="term"><span class="errorcode">EAI_AGAIN</span></span></dt>
+<dd><p>
+ temporary failure in name resolution
+ </p></dd>
+<dt><span class="term"><span class="errorcode">EAI_BADFLAGS</span></span></dt>
+<dd><p>
+ invalid value for
+ <code class="constant">ai_flags</code>
+ </p></dd>
+<dt><span class="term"><span class="errorcode">EAI_FAIL</span></span></dt>
+<dd><p>
+ non-recoverable failure in name resolution
+ </p></dd>
+<dt><span class="term"><span class="errorcode">EAI_FAMILY</span></span></dt>
+<dd><p><code class="constant">ai_family</code> not supported
+ </p></dd>
+<dt><span class="term"><span class="errorcode">EAI_MEMORY</span></span></dt>
+<dd><p>
+ memory allocation failure
+ </p></dd>
+<dt><span class="term"><span class="errorcode">EAI_NODATA</span></span></dt>
+<dd><p>
+ no address associated with hostname
+ </p></dd>
+<dt><span class="term"><span class="errorcode">EAI_NONAME</span></span></dt>
+<dd><p>
+ hostname or servname not provided, or not known
+ </p></dd>
+<dt><span class="term"><span class="errorcode">EAI_SERVICE</span></span></dt>
+<dd><p>
+ servname not supported for <code class="constant">ai_socktype</code>
+ </p></dd>
+<dt><span class="term"><span class="errorcode">EAI_SOCKTYPE</span></span></dt>
+<dd><p><code class="constant">ai_socktype</code> not supported
+ </p></dd>
+<dt><span class="term"><span class="errorcode">EAI_SYSTEM</span></span></dt>
+<dd><p>
+ system error returned in errno
+ </p></dd>
+</dl></div>
+<p>
+ The message <span class="errorname">invalid error code</span> is returned if
+ <em class="parameter"><code>ecode</code></em>
+ is out of range.
+ </p>
+<p><code class="constant">ai_flags</code>,
+ <code class="constant">ai_family</code>
+ and
+ <code class="constant">ai_socktype</code>
+ are elements of the
+ <span class="type">struct addrinfo</span>
+ used by
+ <code class="function">lwres_getaddrinfo()</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543576"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">strerror</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_getaddrinfo</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">getaddrinfo</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">RFC2133</span></span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_getaddrinfo.3 b/lib/lwres/man/lwres_getaddrinfo.3
new file mode 100644
index 0000000..7a1b5d7
--- /dev/null
+++ b/lib/lwres/man/lwres_getaddrinfo.3
@@ -0,0 +1,246 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_getaddrinfo.3,v 1.31 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_getaddrinfo
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_GETADDRINFO" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_getaddrinfo, lwres_freeaddrinfo \- socket address structure to host and service name
+.SH "SYNOPSIS"
+.nf
+#include <lwres/netdb.h>
+.fi
+.HP 22
+.BI "int lwres_getaddrinfo(const\ char\ *" "hostname" ", const\ char\ *" "servname" ", const\ struct\ addrinfo\ *" "hints" ", struct\ addrinfo\ **" "res" ");"
+.HP 24
+.BI "void lwres_freeaddrinfo(struct\ addrinfo\ *" "ai" ");"
+.PP
+If the operating system does not provide a
+\fBstruct addrinfo\fR, the following structure is used:
+.PP
+.RS 4
+.nf
+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 */
+};
+.fi
+.RE
+.sp
+.SH "DESCRIPTION"
+.PP
+\fBlwres_getaddrinfo()\fR
+is used to get a list of IP addresses and port numbers for host
+\fIhostname\fR
+and service
+\fIservname\fR. The function is the lightweight resolver's implementation of
+\fBgetaddrinfo()\fR
+as defined in RFC2133.
+\fIhostname\fR
+and
+\fIservname\fR
+are pointers to null\-terminated strings or
+\fBNULL\fR.
+\fIhostname\fR
+is either a host name or a numeric host address string: a dotted decimal IPv4 address or an IPv6 address.
+\fIservname\fR
+is either a decimal port number or a service name as listed in
+\fI/etc/services\fR.
+.PP
+\fIhints\fR
+is an optional pointer to a
+\fBstruct addrinfo\fR. 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
+\fI*hints\fR:
+.PP
+\fBai_family\fR
+.RS 4
+The protocol family that should be used. When
+\fBai_family\fR
+is set to
+\fBPF_UNSPEC\fR, it means the caller will accept any protocol family supported by the operating system.
+.RE
+.PP
+\fBai_socktype\fR
+.RS 4
+denotes the type of socket \(em
+\fBSOCK_STREAM\fR,
+\fBSOCK_DGRAM\fR
+or
+\fBSOCK_RAW\fR
+\(em that is wanted. When
+\fBai_socktype\fR
+is zero the caller will accept any socket type.
+.RE
+.PP
+\fBai_protocol\fR
+.RS 4
+indicates which transport protocol is wanted: IPPROTO_UDP or IPPROTO_TCP. If
+\fBai_protocol\fR
+is zero the caller will accept any protocol.
+.RE
+.PP
+\fBai_flags\fR
+.RS 4
+Flag bits. If the
+\fBAI_CANONNAME\fR
+bit is set, a successful call to
+\fBlwres_getaddrinfo()\fR
+will return a null\-terminated string containing the canonical name of the specified hostname in
+\fBai_canonname\fR
+of the first
+\fBaddrinfo\fR
+structure returned. Setting the
+\fBAI_PASSIVE\fR
+bit indicates that the returned socket address structure is intended for used in a call to
+\fBbind\fR(2). In this case, if the hostname argument is a
+\fBNULL\fR
+pointer, then the IP address portion of the socket address structure will be set to
+\fBINADDR_ANY\fR
+for an IPv4 address or
+\fBIN6ADDR_ANY_INIT\fR
+for an IPv6 address.
+.sp
+When
+\fBai_flags\fR
+does not set the
+\fBAI_PASSIVE\fR
+bit, the returned socket address structure will be ready for use in a call to
+\fBconnect\fR(2)
+for a connection\-oriented protocol or
+\fBconnect\fR(2),
+\fBsendto\fR(2), or
+\fBsendmsg\fR(2)
+if a connectionless protocol was chosen. The IP address portion of the socket address structure will be set to the loopback address if
+\fIhostname\fR
+is a
+\fBNULL\fR
+pointer and
+\fBAI_PASSIVE\fR
+is not set in
+\fBai_flags\fR.
+.sp
+If
+\fBai_flags\fR
+is set to
+\fBAI_NUMERICHOST\fR
+it indicates that
+\fIhostname\fR
+should be treated as a numeric string defining an IPv4 or IPv6 address and no name resolution should be attempted.
+.RE
+.PP
+All other elements of the
+\fBstruct addrinfo\fR
+passed via
+\fIhints\fR
+must be zero.
+.PP
+A
+\fIhints\fR
+of
+\fBNULL\fR
+is treated as if the caller provided a
+\fBstruct addrinfo\fR
+initialized to zero with
+\fBai_family\fRset to
+\fBPF_UNSPEC\fR.
+.PP
+After a successful call to
+\fBlwres_getaddrinfo()\fR,
+\fI*res\fR
+is a pointer to a linked list of one or more
+\fBaddrinfo\fR
+structures. Each
+\fBstruct addrinfo\fR
+in this list cn be processed by following the
+\fBai_next\fR
+pointer, until a
+\fBNULL\fR
+pointer is encountered. The three members
+\fBai_family\fR,
+\fBai_socktype\fR, and
+\fBai_protocol\fR
+in each returned
+\fBaddrinfo\fR
+structure contain the corresponding arguments for a call to
+\fBsocket\fR(2). For each
+\fBaddrinfo\fR
+structure in the list, the
+\fBai_addr\fR
+member points to a filled\-in socket address structure of length
+\fBai_addrlen\fR.
+.PP
+All of the information returned by
+\fBlwres_getaddrinfo()\fR
+is dynamically allocated: the addrinfo structures, and the socket address structures and canonical host name strings pointed to by the
+\fBaddrinfo\fRstructures. Memory allocated for the dynamically allocated structures created by a successful call to
+\fBlwres_getaddrinfo()\fR
+is released by
+\fBlwres_freeaddrinfo()\fR.
+\fIai\fR
+is a pointer to a
+\fBstruct addrinfo\fR
+created by a call to
+\fBlwres_getaddrinfo()\fR.
+.SH "RETURN VALUES"
+.PP
+\fBlwres_getaddrinfo()\fR
+returns zero on success or one of the error codes listed in
+\fBgai_strerror\fR(3)
+if an error occurs. If both
+\fIhostname\fR
+and
+\fIservname\fR
+are
+\fBNULL\fR
+\fBlwres_getaddrinfo()\fR
+returns
+\fBEAI_NONAME\fR.
+.SH "SEE ALSO"
+.PP
+\fBlwres\fR(3),
+\fBlwres_getaddrinfo\fR(3),
+\fBlwres_freeaddrinfo\fR(3),
+\fBlwres_gai_strerror\fR(3),
+\fBRFC2133\fR(),
+\fBgetservbyname\fR(3),
+\fBbind\fR(2),
+\fBconnect\fR(2),
+\fBsendto\fR(2),
+\fBsendmsg\fR(2),
+\fBsocket\fR(2).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001, 2003 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_getaddrinfo.docbook b/lib/lwres/man/lwres_getaddrinfo.docbook
new file mode 100644
index 0000000..a328764
--- /dev/null
+++ b/lib/lwres/man/lwres_getaddrinfo.docbook
@@ -0,0 +1,387 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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
+ - 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: lwres_getaddrinfo.docbook,v 1.13 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_getaddrinfo</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_getaddrinfo</refname>
+ <refname>lwres_freeaddrinfo</refname>
+ <refpurpose>socket address structure to host and service name</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/netdb.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+int
+<function>lwres_getaddrinfo</function></funcdef>
+ <paramdef>const char *<parameter>hostname</parameter></paramdef>
+ <paramdef>const char *<parameter>servname</parameter></paramdef>
+ <paramdef>const struct addrinfo *<parameter>hints</parameter></paramdef>
+ <paramdef>struct addrinfo **<parameter>res</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_freeaddrinfo</function></funcdef>
+ <paramdef>struct addrinfo *<parameter>ai</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+
+ <para>
+ If the operating system does not provide a
+ <type>struct addrinfo</type>,
+ the following structure is used:
+ </para>
+ <para><programlisting>
+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 */
+};
+</programlisting>
+ </para>
+
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para><function>lwres_getaddrinfo()</function>
+ is used to get a list of IP addresses and port numbers for host
+ <parameter>hostname</parameter> and service
+ <parameter>servname</parameter>.
+
+ The function is the lightweight resolver's implementation of
+ <function>getaddrinfo()</function> as defined in RFC2133.
+ <parameter>hostname</parameter> and
+ <parameter>servname</parameter> are pointers to null-terminated
+ strings or <type>NULL</type>.
+
+ <parameter>hostname</parameter> is either a host name or a
+ numeric host address string: a dotted decimal IPv4 address or an
+ IPv6 address. <parameter>servname</parameter> is either a
+ decimal port number or a service name as listed in
+ <filename>/etc/services</filename>.
+ </para>
+
+ <para><parameter>hints</parameter>
+ is an optional pointer to a
+ <type>struct addrinfo</type>.
+ 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
+ <parameter>*hints</parameter>:
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>ai_family</constant></term>
+ <listitem>
+ <para>
+ The protocol family that should be used.
+ When
+ <constant>ai_family</constant>
+ is set to
+ <type>PF_UNSPEC</type>,
+ it means the caller will accept any protocol family supported by
+ the
+ operating system.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>ai_socktype</constant></term>
+ <listitem>
+ <para>
+ denotes the type of socket &mdash;
+ <type>SOCK_STREAM</type>,
+ <type>SOCK_DGRAM</type>
+ or
+ <type>SOCK_RAW</type>
+ &mdash; that is wanted.
+ When
+ <constant>ai_socktype</constant>
+ is zero the caller will accept any socket type.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>ai_protocol</constant></term>
+ <listitem>
+ <para>
+ indicates which transport protocol is wanted: IPPROTO_UDP or
+ IPPROTO_TCP.
+ If
+ <constant>ai_protocol</constant>
+ is zero the caller will accept any protocol.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>ai_flags</constant></term>
+ <listitem>
+ <para>
+ Flag bits.
+ If the
+ <type>AI_CANONNAME</type>
+ bit is set, a successful call to
+ <function>lwres_getaddrinfo()</function>
+ will return a null-terminated string containing the canonical
+ name
+ of the specified hostname in
+ <constant>ai_canonname</constant>
+ of the first
+ <type>addrinfo</type>
+ structure returned.
+ Setting the
+ <type>AI_PASSIVE</type>
+ bit indicates that the returned socket address structure is
+ intended
+ for used in a call to
+ <citerefentry>
+ <refentrytitle>bind</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>.
+
+ In this case, if the hostname argument is a
+ <type>NULL</type>
+ pointer, then the IP address portion of the socket
+ address structure will be set to
+ <type>INADDR_ANY</type>
+ for an IPv4 address or
+ <type>IN6ADDR_ANY_INIT</type>
+ for an IPv6 address.
+ </para>
+ <para>
+ When
+ <constant>ai_flags</constant>
+ does not set the
+ <type>AI_PASSIVE</type>
+ bit, the returned socket address structure will be ready
+ for use in a call to
+ <citerefentry>
+ <refentrytitle>connect</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>
+ for a connection-oriented protocol or
+ <citerefentry>
+ <refentrytitle>connect</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>sendto</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>,
+
+ or
+ <citerefentry>
+ <refentrytitle>sendmsg</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>
+ if a connectionless protocol was chosen.
+ The IP address portion of the socket address structure will be
+ set to the loopback address if
+ <parameter>hostname</parameter>
+ is a
+ <type>NULL</type>
+ pointer and
+ <type>AI_PASSIVE</type>
+ is not set in
+ <constant>ai_flags</constant>.
+ </para>
+ <para>
+ If
+ <constant>ai_flags</constant>
+ is set to
+ <type>AI_NUMERICHOST</type>
+ it indicates that
+ <parameter>hostname</parameter>
+ should be treated as a numeric string defining an IPv4 or IPv6
+ address
+ and no name resolution should be attempted.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para>
+ All other elements of the <type>struct addrinfo</type> passed
+ via <parameter>hints</parameter> must be zero.
+ </para>
+
+ <para>
+ A <parameter>hints</parameter> of <type>NULL</type> is
+ treated as if
+ the caller provided a <type>struct addrinfo</type> initialized to zero
+ with <constant>ai_family</constant>set to
+ <constant>PF_UNSPEC</constant>.
+ </para>
+
+ <para>
+ After a successful call to
+ <function>lwres_getaddrinfo()</function>,
+ <parameter>*res</parameter>
+ is a pointer to a linked list of one or more
+ <type>addrinfo</type>
+ structures.
+ Each
+ <type>struct addrinfo</type>
+ in this list cn be processed by following
+ the
+ <constant>ai_next</constant>
+ pointer, until a
+ <type>NULL</type>
+ pointer is encountered.
+ The three members
+ <constant>ai_family</constant>,
+ <constant>ai_socktype</constant>,
+ and
+ <constant>ai_protocol</constant>
+ in each
+ returned
+ <type>addrinfo</type>
+ structure contain the corresponding arguments for a call to
+ <citerefentry>
+ <refentrytitle>socket</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>.
+ For each
+ <type>addrinfo</type>
+ structure in the list, the
+ <constant>ai_addr</constant>
+ member points to a filled-in socket address structure of length
+ <constant>ai_addrlen</constant>.
+ </para>
+
+ <para>
+ All of the information returned by
+ <function>lwres_getaddrinfo()</function>
+ is dynamically allocated: the addrinfo structures, and the socket
+ address structures and canonical host name strings pointed to by the
+ <constant>addrinfo</constant>structures.
+ Memory allocated for the dynamically allocated structures created by
+ a successful call to
+ <function>lwres_getaddrinfo()</function>
+ is released by
+ <function>lwres_freeaddrinfo()</function>.
+ <parameter>ai</parameter>
+ is a pointer to a
+ <type>struct addrinfo</type>
+ created by a call to
+ <function>lwres_getaddrinfo()</function>.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>RETURN VALUES</title>
+
+ <para><function>lwres_getaddrinfo()</function>
+ returns zero on success or one of the error codes listed in
+ <citerefentry>
+ <refentrytitle>gai_strerror</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ if an error occurs. If both <parameter>hostname</parameter> and
+ <parameter>servname</parameter> are <type>NULL</type>
+ <function>lwres_getaddrinfo()</function> returns
+ <errorcode>EAI_NONAME</errorcode>.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>lwres</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_getaddrinfo</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_freeaddrinfo</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_gai_strerror</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>RFC2133</refentrytitle>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>getservbyname</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>bind</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>connect</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>sendto</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>sendmsg</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>socket</refentrytitle><manvolnum>2</manvolnum>
+ </citerefentry>.
+ </para>
+
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_getaddrinfo.html b/lib/lwres/man/lwres_getaddrinfo.html
new file mode 100644
index 0000000..d4dd956
--- /dev/null
+++ b/lib/lwres/man/lwres_getaddrinfo.html
@@ -0,0 +1,322 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_getaddrinfo.html,v 1.27 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_getaddrinfo</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_getaddrinfo, lwres_freeaddrinfo &#8212; socket address structure to host and service name</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/netdb.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+int
+<b class="fsfunc">lwres_getaddrinfo</b>(</code></td>
+<td>const char * </td>
+<td>
+<var class="pdparam">hostname</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>const char * </td>
+<td>
+<var class="pdparam">servname</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>const struct addrinfo * </td>
+<td>
+<var class="pdparam">hints</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>struct addrinfo ** </td>
+<td>
+<var class="pdparam">res</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_freeaddrinfo</b>(</code></td>
+<td>struct addrinfo * </td>
+<td>
+<var class="pdparam">ai</var><code>)</code>;</td>
+</tr></table>
+</div>
+<p>
+ If the operating system does not provide a
+ <span class="type">struct addrinfo</span>,
+ the following structure is used:
+ </p>
+<pre class="programlisting">
+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 */
+};
+</pre>
+<p>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543412"></a><h2>DESCRIPTION</h2>
+<p><code class="function">lwres_getaddrinfo()</code>
+ is used to get a list of IP addresses and port numbers for host
+ <em class="parameter"><code>hostname</code></em> and service
+ <em class="parameter"><code>servname</code></em>.
+
+ The function is the lightweight resolver's implementation of
+ <code class="function">getaddrinfo()</code> as defined in RFC2133.
+ <em class="parameter"><code>hostname</code></em> and
+ <em class="parameter"><code>servname</code></em> are pointers to null-terminated
+ strings or <span class="type">NULL</span>.
+
+ <em class="parameter"><code>hostname</code></em> is either a host name or a
+ numeric host address string: a dotted decimal IPv4 address or an
+ IPv6 address. <em class="parameter"><code>servname</code></em> is either a
+ decimal port number or a service name as listed in
+ <code class="filename">/etc/services</code>.
+ </p>
+<p><em class="parameter"><code>hints</code></em>
+ is an optional pointer to a
+ <span class="type">struct addrinfo</span>.
+ 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
+ <em class="parameter"><code>*hints</code></em>:
+
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">ai_family</code></span></dt>
+<dd><p>
+ The protocol family that should be used.
+ When
+ <code class="constant">ai_family</code>
+ is set to
+ <span class="type">PF_UNSPEC</span>,
+ it means the caller will accept any protocol family supported by
+ the
+ operating system.
+ </p></dd>
+<dt><span class="term"><code class="constant">ai_socktype</code></span></dt>
+<dd><p>
+ denotes the type of socket &#8212;
+ <span class="type">SOCK_STREAM</span>,
+ <span class="type">SOCK_DGRAM</span>
+ or
+ <span class="type">SOCK_RAW</span>
+ &#8212; that is wanted.
+ When
+ <code class="constant">ai_socktype</code>
+ is zero the caller will accept any socket type.
+ </p></dd>
+<dt><span class="term"><code class="constant">ai_protocol</code></span></dt>
+<dd><p>
+ indicates which transport protocol is wanted: IPPROTO_UDP or
+ IPPROTO_TCP.
+ If
+ <code class="constant">ai_protocol</code>
+ is zero the caller will accept any protocol.
+ </p></dd>
+<dt><span class="term"><code class="constant">ai_flags</code></span></dt>
+<dd>
+<p>
+ Flag bits.
+ If the
+ <span class="type">AI_CANONNAME</span>
+ bit is set, a successful call to
+ <code class="function">lwres_getaddrinfo()</code>
+ will return a null-terminated string containing the canonical
+ name
+ of the specified hostname in
+ <code class="constant">ai_canonname</code>
+ of the first
+ <span class="type">addrinfo</span>
+ structure returned.
+ Setting the
+ <span class="type">AI_PASSIVE</span>
+ bit indicates that the returned socket address structure is
+ intended
+ for used in a call to
+ <span class="citerefentry"><span class="refentrytitle">bind</span>(2)</span>.
+
+ In this case, if the hostname argument is a
+ <span class="type">NULL</span>
+ pointer, then the IP address portion of the socket
+ address structure will be set to
+ <span class="type">INADDR_ANY</span>
+ for an IPv4 address or
+ <span class="type">IN6ADDR_ANY_INIT</span>
+ for an IPv6 address.
+ </p>
+<p>
+ When
+ <code class="constant">ai_flags</code>
+ does not set the
+ <span class="type">AI_PASSIVE</span>
+ bit, the returned socket address structure will be ready
+ for use in a call to
+ <span class="citerefentry"><span class="refentrytitle">connect</span>(2)</span>
+ for a connection-oriented protocol or
+ <span class="citerefentry"><span class="refentrytitle">connect</span>(2)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">sendto</span>(2)</span>,
+
+ or
+ <span class="citerefentry"><span class="refentrytitle">sendmsg</span>(2)</span>
+ if a connectionless protocol was chosen.
+ The IP address portion of the socket address structure will be
+ set to the loopback address if
+ <em class="parameter"><code>hostname</code></em>
+ is a
+ <span class="type">NULL</span>
+ pointer and
+ <span class="type">AI_PASSIVE</span>
+ is not set in
+ <code class="constant">ai_flags</code>.
+ </p>
+<p>
+ If
+ <code class="constant">ai_flags</code>
+ is set to
+ <span class="type">AI_NUMERICHOST</span>
+ it indicates that
+ <em class="parameter"><code>hostname</code></em>
+ should be treated as a numeric string defining an IPv4 or IPv6
+ address
+ and no name resolution should be attempted.
+ </p>
+</dd>
+</dl></div>
+<p>
+ </p>
+<p>
+ All other elements of the <span class="type">struct addrinfo</span> passed
+ via <em class="parameter"><code>hints</code></em> must be zero.
+ </p>
+<p>
+ A <em class="parameter"><code>hints</code></em> of <span class="type">NULL</span> is
+ treated as if
+ the caller provided a <span class="type">struct addrinfo</span> initialized to zero
+ with <code class="constant">ai_family</code>set to
+ <code class="constant">PF_UNSPEC</code>.
+ </p>
+<p>
+ After a successful call to
+ <code class="function">lwres_getaddrinfo()</code>,
+ <em class="parameter"><code>*res</code></em>
+ is a pointer to a linked list of one or more
+ <span class="type">addrinfo</span>
+ structures.
+ Each
+ <span class="type">struct addrinfo</span>
+ in this list cn be processed by following
+ the
+ <code class="constant">ai_next</code>
+ pointer, until a
+ <span class="type">NULL</span>
+ pointer is encountered.
+ The three members
+ <code class="constant">ai_family</code>,
+ <code class="constant">ai_socktype</code>,
+ and
+ <code class="constant">ai_protocol</code>
+ in each
+ returned
+ <span class="type">addrinfo</span>
+ structure contain the corresponding arguments for a call to
+ <span class="citerefentry"><span class="refentrytitle">socket</span>(2)</span>.
+ For each
+ <span class="type">addrinfo</span>
+ structure in the list, the
+ <code class="constant">ai_addr</code>
+ member points to a filled-in socket address structure of length
+ <code class="constant">ai_addrlen</code>.
+ </p>
+<p>
+ All of the information returned by
+ <code class="function">lwres_getaddrinfo()</code>
+ is dynamically allocated: the addrinfo structures, and the socket
+ address structures and canonical host name strings pointed to by the
+ <code class="constant">addrinfo</code>structures.
+ Memory allocated for the dynamically allocated structures created by
+ a successful call to
+ <code class="function">lwres_getaddrinfo()</code>
+ is released by
+ <code class="function">lwres_freeaddrinfo()</code>.
+ <em class="parameter"><code>ai</code></em>
+ is a pointer to a
+ <span class="type">struct addrinfo</span>
+ created by a call to
+ <code class="function">lwres_getaddrinfo()</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543789"></a><h2>RETURN VALUES</h2>
+<p><code class="function">lwres_getaddrinfo()</code>
+ returns zero on success or one of the error codes listed in
+ <span class="citerefentry"><span class="refentrytitle">gai_strerror</span>(3)</span>
+ if an error occurs. If both <em class="parameter"><code>hostname</code></em> and
+ <em class="parameter"><code>servname</code></em> are <span class="type">NULL</span>
+ <code class="function">lwres_getaddrinfo()</code> returns
+ <span class="errorcode">EAI_NONAME</span>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543827"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">lwres</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_getaddrinfo</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_freeaddrinfo</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_gai_strerror</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">RFC2133</span></span>,
+
+ <span class="citerefentry"><span class="refentrytitle">getservbyname</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">bind</span>(2)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">connect</span>(2)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">sendto</span>(2)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">sendmsg</span>(2)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">socket</span>(2)</span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_gethostent.3 b/lib/lwres/man/lwres_gethostent.3
new file mode 100644
index 0000000..847d882
--- /dev/null
+++ b/lib/lwres/man/lwres_gethostent.3
@@ -0,0 +1,315 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_gethostent.3,v 1.29 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_gethostent
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_GETHOSTENT" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "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
+.SH "SYNOPSIS"
+.nf
+#include <lwres/netdb.h>
+.fi
+.HP 37
+.BI "struct hostent * lwres_gethostbyname(const\ char\ *" "name" ");"
+.HP 38
+.BI "struct hostent * lwres_gethostbyname2(const\ char\ *" "name" ", int\ " "af" ");"
+.HP 37
+.BI "struct hostent * lwres_gethostbyaddr(const\ char\ *" "addr" ", int\ " "len" ", int\ " "type" ");"
+.HP 34
+.BI "struct hostent * lwres_gethostent(void);"
+.HP 22
+.BI "void lwres_sethostent(int\ " "stayopen" ");"
+.HP 22
+.BI "void lwres_endhostent(void);"
+.HP 39
+.BI "struct hostent * lwres_gethostbyname_r(const\ char\ *" "name" ", struct\ hostent\ *" "resbuf" ", char\ *" "buf" ", int\ " "buflen" ", int\ *" "error" ");"
+.HP 39
+.BI "struct hostent * lwres_gethostbyaddr_r(const\ char\ *" "addr" ", int\ " "len" ", int\ " "type" ", struct\ hostent\ *" "resbuf" ", char\ *" "buf" ", int\ " "buflen" ", int\ *" "error" ");"
+.HP 36
+.BI "struct hostent * lwres_gethostent_r(struct\ hostent\ *" "resbuf" ", char\ *" "buf" ", int\ " "buflen" ", int\ *" "error" ");"
+.HP 24
+.BI "void lwres_sethostent_r(int\ " "stayopen" ");"
+.HP 24
+.BI "void lwres_endhostent_r(void);"
+.SH "DESCRIPTION"
+.PP
+These functions provide hostname\-to\-address and address\-to\-hostname lookups by means of the lightweight resolver. They are similar to the standard
+\fBgethostent\fR(3)
+functions provided by most operating systems. They use a
+\fBstruct hostent\fR
+which is usually defined in
+\fI<namedb.h>\fR.
+.PP
+.RS 4
+.nf
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+};
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+.fi
+.RE
+.sp
+.PP
+The members of this structure are:
+.PP
+\fBh_name\fR
+.RS 4
+The official (canonical) name of the host.
+.RE
+.PP
+\fBh_aliases\fR
+.RS 4
+A NULL\-terminated array of alternate names (nicknames) for the host.
+.RE
+.PP
+\fBh_addrtype\fR
+.RS 4
+The type of address being returned \(em
+\fBPF_INET\fR
+or
+\fBPF_INET6\fR.
+.RE
+.PP
+\fBh_length\fR
+.RS 4
+The length of the address in bytes.
+.RE
+.PP
+\fBh_addr_list\fR
+.RS 4
+A
+\fBNULL\fR
+terminated array of network addresses for the host. Host addresses are returned in network byte order.
+.RE
+.PP
+For backward compatibility with very old software,
+\fBh_addr\fR
+is the first address in
+\fBh_addr_list.\fR
+.PP
+\fBlwres_gethostent()\fR,
+\fBlwres_sethostent()\fR,
+\fBlwres_endhostent()\fR,
+\fBlwres_gethostent_r()\fR,
+\fBlwres_sethostent_r()\fR
+and
+\fBlwres_endhostent_r()\fR
+provide iteration over the known host entries on systems that provide such functionality through facilities like
+\fI/etc/hosts\fR
+or NIS. The lightweight resolver does not currently implement these functions; it only provides them as stub functions that always return failure.
+.PP
+\fBlwres_gethostbyname()\fR
+and
+\fBlwres_gethostbyname2()\fR
+look up the hostname
+\fIname\fR.
+\fBlwres_gethostbyname()\fR
+always looks for an IPv4 address while
+\fBlwres_gethostbyname2()\fR
+looks for an address of protocol family
+\fIaf\fR: either
+\fBPF_INET\fR
+or
+\fBPF_INET6\fR
+\(em IPv4 or IPV6 addresses respectively. Successful calls of the functions return a
+\fBstruct hostent\fRfor the name that was looked up.
+\fBNULL\fR
+is returned if the lookups by
+\fBlwres_gethostbyname()\fR
+or
+\fBlwres_gethostbyname2()\fR
+fail.
+.PP
+Reverse lookups of addresses are performed by
+\fBlwres_gethostbyaddr()\fR.
+\fIaddr\fR
+is an address of length
+\fIlen\fR
+bytes and protocol family
+\fItype\fR
+\(em
+\fBPF_INET\fR
+or
+\fBPF_INET6\fR.
+\fBlwres_gethostbyname_r()\fR
+is a thread\-safe function for forward lookups. If an error occurs, an error code is returned in
+\fI*error\fR.
+\fIresbuf\fR
+is a pointer to a
+\fBstruct hostent\fR
+which is initialised by a successful call to
+\fBlwres_gethostbyname_r()\fR.
+\fIbuf\fR
+is a buffer of length
+\fIlen\fR
+bytes which is used to store the
+\fBh_name\fR,
+\fBh_aliases\fR, and
+\fBh_addr_list\fR
+elements of the
+\fBstruct hostent\fR
+returned in
+\fIresbuf\fR. Successful calls to
+\fBlwres_gethostbyname_r()\fR
+return
+\fIresbuf\fR, which is a pointer to the
+\fBstruct hostent\fR
+it created.
+.PP
+\fBlwres_gethostbyaddr_r()\fR
+is a thread\-safe function that performs a reverse lookup of address
+\fIaddr\fR
+which is
+\fIlen\fR
+bytes long and is of protocol family
+\fItype\fR
+\(em
+\fBPF_INET\fR
+or
+\fBPF_INET6\fR. If an error occurs, the error code is returned in
+\fI*error\fR. The other function parameters are identical to those in
+\fBlwres_gethostbyname_r()\fR.
+\fIresbuf\fR
+is a pointer to a
+\fBstruct hostent\fR
+which is initialised by a successful call to
+\fBlwres_gethostbyaddr_r()\fR.
+\fIbuf\fR
+is a buffer of length
+\fIlen\fR
+bytes which is used to store the
+\fBh_name\fR,
+\fBh_aliases\fR, and
+\fBh_addr_list\fR
+elements of the
+\fBstruct hostent\fR
+returned in
+\fIresbuf\fR. Successful calls to
+\fBlwres_gethostbyaddr_r()\fR
+return
+\fIresbuf\fR, which is a pointer to the
+\fBstruct hostent()\fR
+it created.
+.SH "RETURN VALUES"
+.PP
+The functions
+\fBlwres_gethostbyname()\fR,
+\fBlwres_gethostbyname2()\fR,
+\fBlwres_gethostbyaddr()\fR, and
+\fBlwres_gethostent()\fR
+return NULL to indicate an error. In this case the global variable
+\fBlwres_h_errno\fR
+will contain one of the following error codes defined in
+\fI<lwres/netdb.h>\fR:
+.PP
+\fBHOST_NOT_FOUND\fR
+.RS 4
+The host or address was not found.
+.RE
+.PP
+\fBTRY_AGAIN\fR
+.RS 4
+A recoverable error occurred, e.g., a timeout. Retrying the lookup may succeed.
+.RE
+.PP
+\fBNO_RECOVERY\fR
+.RS 4
+A non\-recoverable error occurred.
+.RE
+.PP
+\fBNO_DATA\fR
+.RS 4
+The name exists, but has no address information associated with it (or vice versa in the case of a reverse lookup). The code NO_ADDRESS is accepted as a synonym for NO_DATA for backwards compatibility.
+.RE
+.PP
+\fBlwres_hstrerror\fR(3)
+translates these error codes to suitable error messages.
+.PP
+\fBlwres_gethostent()\fR
+and
+\fBlwres_gethostent_r()\fR
+always return
+\fBNULL\fR.
+.PP
+Successful calls to
+\fBlwres_gethostbyname_r()\fR
+and
+\fBlwres_gethostbyaddr_r()\fR
+return
+\fIresbuf\fR, a pointer to the
+\fBstruct hostent\fR
+that was initialised by these functions. They return
+\fBNULL\fR
+if the lookups fail or if
+\fIbuf\fR
+was too small to hold the list of addresses and names referenced by the
+\fBh_name\fR,
+\fBh_aliases\fR, and
+\fBh_addr_list\fR
+elements of the
+\fBstruct hostent\fR. If
+\fIbuf\fR
+was too small, both
+\fBlwres_gethostbyname_r()\fR
+and
+\fBlwres_gethostbyaddr_r()\fR
+set the global variable
+\fBerrno\fR
+to
+\fBERANGE\fR.
+.SH "SEE ALSO"
+.PP
+\fBgethostent\fR(3),
+\fBlwres_getipnode\fR(3),
+\fBlwres_hstrerror\fR(3)
+.SH "BUGS"
+.PP
+\fBlwres_gethostbyname()\fR,
+\fBlwres_gethostbyname2()\fR,
+\fBlwres_gethostbyaddr()\fR
+and
+\fBlwres_endhostent()\fR
+are not thread safe; they return pointers to static data and provide error codes through a global variable. Thread\-safe versions for name and address lookup are provided by
+\fBlwres_gethostbyname_r()\fR, and
+\fBlwres_gethostbyaddr_r()\fR
+respectively.
+.PP
+The resolver daemon does not currently support any non\-DNS name services such as
+\fI/etc/hosts\fR
+or
+\fBNIS\fR, consequently the above functions don't, either.
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_gethostent.docbook b/lib/lwres/man/lwres_gethostent.docbook
new file mode 100644
index 0000000..a3f084b
--- /dev/null
+++ b/lib/lwres/man/lwres_gethostent.docbook
@@ -0,0 +1,439 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - 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: lwres_gethostent.docbook,v 1.11 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_gethostent</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_gethostbyname</refname>
+ <refname>lwres_gethostbyname2</refname>
+ <refname>lwres_gethostbyaddr</refname>
+ <refname>lwres_gethostent</refname>
+ <refname>lwres_sethostent</refname>
+ <refname>lwres_endhostent</refname>
+ <refname>lwres_gethostbyname_r</refname>
+ <refname>lwres_gethostbyaddr_r</refname>
+ <refname>lwres_gethostent_r</refname>
+ <refname>lwres_sethostent_r</refname>
+ <refname>lwres_endhostent_r</refname>
+ <refpurpose>lightweight resolver get network host entry</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/netdb.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+struct hostent *
+<function>lwres_gethostbyname</function></funcdef>
+ <paramdef>const char *<parameter>name</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+struct hostent *
+<function>lwres_gethostbyname2</function></funcdef>
+ <paramdef>const char *<parameter>name</parameter></paramdef>
+ <paramdef>int <parameter>af</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+struct hostent *
+<function>lwres_gethostbyaddr</function></funcdef>
+ <paramdef>const char *<parameter>addr</parameter></paramdef>
+ <paramdef>int <parameter>len</parameter></paramdef>
+ <paramdef>int <parameter>type</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+struct hostent *
+<function>lwres_gethostent</function></funcdef>
+ <paramdef>void</paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_sethostent</function></funcdef>
+ <paramdef>int <parameter>stayopen</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_endhostent</function></funcdef>
+ <paramdef>void</paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+struct hostent *
+<function>lwres_gethostbyname_r</function></funcdef>
+ <paramdef>const char *<parameter>name</parameter></paramdef>
+ <paramdef>struct hostent *<parameter>resbuf</parameter></paramdef>
+ <paramdef>char *<parameter>buf</parameter></paramdef>
+ <paramdef>int <parameter>buflen</parameter></paramdef>
+ <paramdef>int *<parameter>error</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+struct hostent *
+<function>lwres_gethostbyaddr_r</function></funcdef>
+ <paramdef>const char *<parameter>addr</parameter></paramdef>
+ <paramdef>int <parameter>len</parameter></paramdef>
+ <paramdef>int <parameter>type</parameter></paramdef>
+ <paramdef>struct hostent *<parameter>resbuf</parameter></paramdef>
+ <paramdef>char *<parameter>buf</parameter></paramdef>
+ <paramdef>int <parameter>buflen</parameter></paramdef>
+ <paramdef>int *<parameter>error</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+struct hostent *
+<function>lwres_gethostent_r</function></funcdef>
+ <paramdef>struct hostent *<parameter>resbuf</parameter></paramdef>
+ <paramdef>char *<parameter>buf</parameter></paramdef>
+ <paramdef>int <parameter>buflen</parameter></paramdef>
+ <paramdef>int *<parameter>error</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_sethostent_r</function></funcdef>
+ <paramdef>int <parameter>stayopen</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_endhostent_r</function></funcdef>
+ <paramdef>void</paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ These functions provide hostname-to-address and
+ address-to-hostname lookups by means of the lightweight resolver.
+ They are similar to the standard
+ <citerefentry>
+ <refentrytitle>gethostent</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ functions provided by most operating systems.
+ They use a
+ <type>struct hostent</type>
+ which is usually defined in
+ <filename>&lt;namedb.h&gt;</filename>.
+ </para>
+ <para><programlisting>
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+};
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+</programlisting>
+ </para>
+ <para>
+ The members of this structure are:
+ <variablelist>
+ <varlistentry>
+ <term><constant>h_name</constant></term>
+ <listitem>
+ <para>
+ The official (canonical) name of the host.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>h_aliases</constant></term>
+ <listitem>
+ <para>
+ A NULL-terminated array of alternate names (nicknames) for the
+ host.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>h_addrtype</constant></term>
+ <listitem>
+ <para>
+ The type of address being returned &mdash;
+ <type>PF_INET</type>
+ or
+ <type>PF_INET6</type>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>h_length</constant></term>
+ <listitem>
+ <para>
+ The length of the address in bytes.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>h_addr_list</constant></term>
+ <listitem>
+ <para>
+ A <type>NULL</type>
+ terminated array of network addresses for the host.
+ Host addresses are returned in network byte order.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <para>
+ For backward compatibility with very old software,
+ <constant>h_addr</constant>
+ is the first address in
+ <constant>h_addr_list.</constant>
+ </para>
+ <para><function>lwres_gethostent()</function>,
+ <function>lwres_sethostent()</function>,
+ <function>lwres_endhostent()</function>,
+ <function>lwres_gethostent_r()</function>,
+ <function>lwres_sethostent_r()</function>
+ and
+ <function>lwres_endhostent_r()</function>
+ provide iteration over the known host entries on systems that
+ provide such functionality through facilities like
+ <filename>/etc/hosts</filename>
+ or NIS. The lightweight resolver does not currently implement
+ these functions; it only provides them as stub functions that always
+ return failure.
+ </para>
+
+ <para><function>lwres_gethostbyname()</function>
+ and <function>lwres_gethostbyname2()</function> look up the
+ hostname <parameter>name</parameter>.
+ <function>lwres_gethostbyname()</function> always looks for an
+ IPv4 address while <function>lwres_gethostbyname2()</function>
+ looks for an address of protocol family
+ <parameter>af</parameter>: either <type>PF_INET</type> or
+ <type>PF_INET6</type> &mdash; IPv4 or IPV6 addresses
+ respectively. Successful calls of the functions return a
+ <type>struct hostent</type>for the name that was looked up.
+ <type>NULL</type> is returned if the lookups by
+ <function>lwres_gethostbyname()</function> or
+ <function>lwres_gethostbyname2()</function> fail.
+ </para>
+
+ <para>
+ Reverse lookups of addresses are performed by
+ <function>lwres_gethostbyaddr()</function>.
+ <parameter>addr</parameter> is an address of length
+ <parameter>len</parameter> bytes and protocol family
+ <parameter>type</parameter> &mdash; <type>PF_INET</type> or
+ <type>PF_INET6</type>.
+ <function>lwres_gethostbyname_r()</function> is a
+ thread-safe function
+ for forward lookups. If an error occurs, an error code is returned in
+ <parameter>*error</parameter>.
+ <parameter>resbuf</parameter> is a pointer to a
+ <type>struct hostent</type> which is initialised by a successful call to
+ <function>lwres_gethostbyname_r()</function>.
+ <parameter>buf</parameter> is a buffer of length
+ <parameter>len</parameter> bytes which is used to store the
+ <constant>h_name</constant>, <constant>h_aliases</constant>, and
+ <constant>h_addr_list</constant> elements of the
+ <type>struct hostent</type> returned in <parameter>resbuf</parameter>.
+ Successful calls to <function>lwres_gethostbyname_r()</function>
+ return <parameter>resbuf</parameter>,
+ which is a pointer to the <type>struct hostent</type> it created.
+ </para>
+
+ <para><function>lwres_gethostbyaddr_r()</function>
+ is a thread-safe function
+ that performs a reverse lookup of address <parameter>addr</parameter>
+ which is <parameter>len</parameter> bytes long and is of
+ protocol
+ family <parameter>type</parameter> &mdash; <type>PF_INET</type> or
+ <type>PF_INET6</type>. If an error occurs, the error code is returned
+ in <parameter>*error</parameter>. The other function
+ parameters are
+ identical to those in <function>lwres_gethostbyname_r()</function>.
+ <parameter>resbuf</parameter> is a pointer to a
+ <type>struct hostent</type> which is initialised by a successful call to
+ <function>lwres_gethostbyaddr_r()</function>.
+ <parameter>buf</parameter> is a buffer of length
+ <parameter>len</parameter> bytes which is used to store the
+ <constant>h_name</constant>, <constant>h_aliases</constant>, and
+ <constant>h_addr_list</constant> elements of the
+ <type>struct hostent</type> returned in <parameter>resbuf</parameter>.
+ Successful calls to <function>lwres_gethostbyaddr_r()</function> return
+ <parameter>resbuf</parameter>, which is a pointer to the
+ <function>struct hostent()</function> it created.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para>
+ The functions
+ <function>lwres_gethostbyname()</function>,
+ <function>lwres_gethostbyname2()</function>,
+ <function>lwres_gethostbyaddr()</function>,
+ and
+ <function>lwres_gethostent()</function>
+ return NULL to indicate an error. In this case the global variable
+ <type>lwres_h_errno</type>
+ will contain one of the following error codes defined in
+ <filename>&lt;lwres/netdb.h&gt;</filename>:
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>HOST_NOT_FOUND</constant></term>
+ <listitem>
+ <para>
+ The host or address was not found.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>TRY_AGAIN</constant></term>
+ <listitem>
+ <para>
+ A recoverable error occurred, e.g., a timeout.
+ Retrying the lookup may succeed.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>NO_RECOVERY</constant></term>
+ <listitem>
+ <para>
+ A non-recoverable error occurred.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>NO_DATA</constant></term>
+ <listitem>
+ <para>
+ The name exists, but has no address information
+ associated with it (or vice versa in the case
+ of a reverse lookup). The code NO_ADDRESS
+ is accepted as a synonym for NO_DATA for backwards
+ compatibility.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para><citerefentry>
+ <refentrytitle>lwres_hstrerror</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ translates these error codes to suitable error messages.
+ </para>
+
+ <para><function>lwres_gethostent()</function>
+ and <function>lwres_gethostent_r()</function>
+ always return <type>NULL</type>.
+ </para>
+
+ <para>
+ Successful calls to <function>lwres_gethostbyname_r()</function> and
+ <function>lwres_gethostbyaddr_r()</function> return
+ <parameter>resbuf</parameter>, a pointer to the
+ <type>struct hostent</type> that was initialised by these functions. They return
+ <type>NULL</type> if the lookups fail or if <parameter>buf</parameter>
+ was too small to hold the list of addresses and names referenced by
+ the <constant>h_name</constant>, <constant>h_aliases</constant>, and
+ <constant>h_addr_list</constant> elements of the
+ <type>struct hostent</type>.
+ If <parameter>buf</parameter> was too small, both
+ <function>lwres_gethostbyname_r()</function> and
+ <function>lwres_gethostbyaddr_r()</function> set the global
+ variable
+ <type>errno</type> to <errorcode>ERANGE</errorcode>.
+ </para>
+
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>gethostent</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_getipnode</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_hstrerror</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>BUGS</title>
+ <para><function>lwres_gethostbyname()</function>,
+ <function>lwres_gethostbyname2()</function>,
+ <function>lwres_gethostbyaddr()</function>
+ and
+ <function>lwres_endhostent()</function>
+ are not thread safe; they return pointers to static data and
+ provide error codes through a global variable.
+ Thread-safe versions for name and address lookup are provided by
+ <function>lwres_gethostbyname_r()</function>,
+ and
+ <function>lwres_gethostbyaddr_r()</function>
+ respectively.
+ </para>
+ <para>
+ The resolver daemon does not currently support any non-DNS
+ name services such as
+ <filename>/etc/hosts</filename>
+ or
+ <type>NIS</type>,
+ consequently the above functions don't, either.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_gethostent.html b/lib/lwres/man/lwres_gethostent.html
new file mode 100644
index 0000000..efeeaa2
--- /dev/null
+++ b/lib/lwres/man/lwres_gethostent.html
@@ -0,0 +1,466 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_gethostent.html,v 1.24 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_gethostent</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>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 &#8212; lightweight resolver get network host entry</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/netdb.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+struct hostent *
+<b class="fsfunc">lwres_gethostbyname</b>(</code></td>
+<td>const char * </td>
+<td>
+<var class="pdparam">name</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+struct hostent *
+<b class="fsfunc">lwres_gethostbyname2</b>(</code></td>
+<td>const char * </td>
+<td>
+<var class="pdparam">name</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">af</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+struct hostent *
+<b class="fsfunc">lwres_gethostbyaddr</b>(</code></td>
+<td>const char * </td>
+<td>
+<var class="pdparam">addr</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">len</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">type</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+struct hostent *
+<b class="fsfunc">lwres_gethostent</b>(</code></td>
+<td> </td>
+<td>
+<code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_sethostent</b>(</code></td>
+<td>int  </td>
+<td>
+<var class="pdparam">stayopen</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_endhostent</b>(</code></td>
+<td> </td>
+<td>
+<code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+struct hostent *
+<b class="fsfunc">lwres_gethostbyname_r</b>(</code></td>
+<td>const char * </td>
+<td>
+<var class="pdparam">name</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>struct hostent * </td>
+<td>
+<var class="pdparam">resbuf</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>char * </td>
+<td>
+<var class="pdparam">buf</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">buflen</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int * </td>
+<td>
+<var class="pdparam">error</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+struct hostent *
+<b class="fsfunc">lwres_gethostbyaddr_r</b>(</code></td>
+<td>const char * </td>
+<td>
+<var class="pdparam">addr</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">len</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">type</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>struct hostent * </td>
+<td>
+<var class="pdparam">resbuf</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>char * </td>
+<td>
+<var class="pdparam">buf</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">buflen</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int * </td>
+<td>
+<var class="pdparam">error</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+struct hostent *
+<b class="fsfunc">lwres_gethostent_r</b>(</code></td>
+<td>struct hostent * </td>
+<td>
+<var class="pdparam">resbuf</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>char * </td>
+<td>
+<var class="pdparam">buf</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">buflen</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int * </td>
+<td>
+<var class="pdparam">error</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_sethostent_r</b>(</code></td>
+<td>int  </td>
+<td>
+<var class="pdparam">stayopen</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_endhostent_r</b>(</code></td>
+<td> </td>
+<td>
+<code>)</code>;</td>
+</tr></table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543608"></a><h2>DESCRIPTION</h2>
+<p>
+ These functions provide hostname-to-address and
+ address-to-hostname lookups by means of the lightweight resolver.
+ They are similar to the standard
+ <span class="citerefentry"><span class="refentrytitle">gethostent</span>(3)</span>
+ functions provided by most operating systems.
+ They use a
+ <span class="type">struct hostent</span>
+ which is usually defined in
+ <code class="filename">&lt;namedb.h&gt;</code>.
+ </p>
+<pre class="programlisting">
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+};
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+</pre>
+<p>
+ </p>
+<p>
+ The members of this structure are:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">h_name</code></span></dt>
+<dd><p>
+ The official (canonical) name of the host.
+ </p></dd>
+<dt><span class="term"><code class="constant">h_aliases</code></span></dt>
+<dd><p>
+ A NULL-terminated array of alternate names (nicknames) for the
+ host.
+ </p></dd>
+<dt><span class="term"><code class="constant">h_addrtype</code></span></dt>
+<dd><p>
+ The type of address being returned &#8212;
+ <span class="type">PF_INET</span>
+ or
+ <span class="type">PF_INET6</span>.
+ </p></dd>
+<dt><span class="term"><code class="constant">h_length</code></span></dt>
+<dd><p>
+ The length of the address in bytes.
+ </p></dd>
+<dt><span class="term"><code class="constant">h_addr_list</code></span></dt>
+<dd><p>
+ A <span class="type">NULL</span>
+ terminated array of network addresses for the host.
+ Host addresses are returned in network byte order.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+<p>
+ For backward compatibility with very old software,
+ <code class="constant">h_addr</code>
+ is the first address in
+ <code class="constant">h_addr_list.</code>
+ </p>
+<p><code class="function">lwres_gethostent()</code>,
+ <code class="function">lwres_sethostent()</code>,
+ <code class="function">lwres_endhostent()</code>,
+ <code class="function">lwres_gethostent_r()</code>,
+ <code class="function">lwres_sethostent_r()</code>
+ and
+ <code class="function">lwres_endhostent_r()</code>
+ provide iteration over the known host entries on systems that
+ provide such functionality through facilities like
+ <code class="filename">/etc/hosts</code>
+ or NIS. The lightweight resolver does not currently implement
+ these functions; it only provides them as stub functions that always
+ return failure.
+ </p>
+<p><code class="function">lwres_gethostbyname()</code>
+ and <code class="function">lwres_gethostbyname2()</code> look up the
+ hostname <em class="parameter"><code>name</code></em>.
+ <code class="function">lwres_gethostbyname()</code> always looks for an
+ IPv4 address while <code class="function">lwres_gethostbyname2()</code>
+ looks for an address of protocol family
+ <em class="parameter"><code>af</code></em>: either <span class="type">PF_INET</span> or
+ <span class="type">PF_INET6</span> &#8212; IPv4 or IPV6 addresses
+ respectively. Successful calls of the functions return a
+ <span class="type">struct hostent</span>for the name that was looked up.
+ <span class="type">NULL</span> is returned if the lookups by
+ <code class="function">lwres_gethostbyname()</code> or
+ <code class="function">lwres_gethostbyname2()</code> fail.
+ </p>
+<p>
+ Reverse lookups of addresses are performed by
+ <code class="function">lwres_gethostbyaddr()</code>.
+ <em class="parameter"><code>addr</code></em> is an address of length
+ <em class="parameter"><code>len</code></em> bytes and protocol family
+ <em class="parameter"><code>type</code></em> &#8212; <span class="type">PF_INET</span> or
+ <span class="type">PF_INET6</span>.
+ <code class="function">lwres_gethostbyname_r()</code> is a
+ thread-safe function
+ for forward lookups. If an error occurs, an error code is returned in
+ <em class="parameter"><code>*error</code></em>.
+ <em class="parameter"><code>resbuf</code></em> is a pointer to a
+ <span class="type">struct hostent</span> which is initialised by a successful call to
+ <code class="function">lwres_gethostbyname_r()</code>.
+ <em class="parameter"><code>buf</code></em> is a buffer of length
+ <em class="parameter"><code>len</code></em> bytes which is used to store the
+ <code class="constant">h_name</code>, <code class="constant">h_aliases</code>, and
+ <code class="constant">h_addr_list</code> elements of the
+ <span class="type">struct hostent</span> returned in <em class="parameter"><code>resbuf</code></em>.
+ Successful calls to <code class="function">lwres_gethostbyname_r()</code>
+ return <em class="parameter"><code>resbuf</code></em>,
+ which is a pointer to the <span class="type">struct hostent</span> it created.
+ </p>
+<p><code class="function">lwres_gethostbyaddr_r()</code>
+ is a thread-safe function
+ that performs a reverse lookup of address <em class="parameter"><code>addr</code></em>
+ which is <em class="parameter"><code>len</code></em> bytes long and is of
+ protocol
+ family <em class="parameter"><code>type</code></em> &#8212; <span class="type">PF_INET</span> or
+ <span class="type">PF_INET6</span>. If an error occurs, the error code is returned
+ in <em class="parameter"><code>*error</code></em>. The other function
+ parameters are
+ identical to those in <code class="function">lwres_gethostbyname_r()</code>.
+ <em class="parameter"><code>resbuf</code></em> is a pointer to a
+ <span class="type">struct hostent</span> which is initialised by a successful call to
+ <code class="function">lwres_gethostbyaddr_r()</code>.
+ <em class="parameter"><code>buf</code></em> is a buffer of length
+ <em class="parameter"><code>len</code></em> bytes which is used to store the
+ <code class="constant">h_name</code>, <code class="constant">h_aliases</code>, and
+ <code class="constant">h_addr_list</code> elements of the
+ <span class="type">struct hostent</span> returned in <em class="parameter"><code>resbuf</code></em>.
+ Successful calls to <code class="function">lwres_gethostbyaddr_r()</code> return
+ <em class="parameter"><code>resbuf</code></em>, which is a pointer to the
+ <code class="function">struct hostent()</code> it created.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543959"></a><h2>RETURN VALUES</h2>
+<p>
+ The functions
+ <code class="function">lwres_gethostbyname()</code>,
+ <code class="function">lwres_gethostbyname2()</code>,
+ <code class="function">lwres_gethostbyaddr()</code>,
+ and
+ <code class="function">lwres_gethostent()</code>
+ return NULL to indicate an error. In this case the global variable
+ <span class="type">lwres_h_errno</span>
+ will contain one of the following error codes defined in
+ <code class="filename">&lt;lwres/netdb.h&gt;</code>:
+
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">HOST_NOT_FOUND</code></span></dt>
+<dd><p>
+ The host or address was not found.
+ </p></dd>
+<dt><span class="term"><code class="constant">TRY_AGAIN</code></span></dt>
+<dd><p>
+ A recoverable error occurred, e.g., a timeout.
+ Retrying the lookup may succeed.
+ </p></dd>
+<dt><span class="term"><code class="constant">NO_RECOVERY</code></span></dt>
+<dd><p>
+ A non-recoverable error occurred.
+ </p></dd>
+<dt><span class="term"><code class="constant">NO_DATA</code></span></dt>
+<dd><p>
+ The name exists, but has no address information
+ associated with it (or vice versa in the case
+ of a reverse lookup). The code NO_ADDRESS
+ is accepted as a synonym for NO_DATA for backwards
+ compatibility.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+<p><span class="citerefentry"><span class="refentrytitle">lwres_hstrerror</span>(3)</span>
+ translates these error codes to suitable error messages.
+ </p>
+<p><code class="function">lwres_gethostent()</code>
+ and <code class="function">lwres_gethostent_r()</code>
+ always return <span class="type">NULL</span>.
+ </p>
+<p>
+ Successful calls to <code class="function">lwres_gethostbyname_r()</code> and
+ <code class="function">lwres_gethostbyaddr_r()</code> return
+ <em class="parameter"><code>resbuf</code></em>, a pointer to the
+ <span class="type">struct hostent</span> that was initialised by these functions. They return
+ <span class="type">NULL</span> if the lookups fail or if <em class="parameter"><code>buf</code></em>
+ was too small to hold the list of addresses and names referenced by
+ the <code class="constant">h_name</code>, <code class="constant">h_aliases</code>, and
+ <code class="constant">h_addr_list</code> elements of the
+ <span class="type">struct hostent</span>.
+ If <em class="parameter"><code>buf</code></em> was too small, both
+ <code class="function">lwres_gethostbyname_r()</code> and
+ <code class="function">lwres_gethostbyaddr_r()</code> set the global
+ variable
+ <span class="type">errno</span> to <span class="errorcode">ERANGE</span>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544193"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">gethostent</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_getipnode</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_hstrerror</span>(3)</span>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544227"></a><h2>BUGS</h2>
+<p><code class="function">lwres_gethostbyname()</code>,
+ <code class="function">lwres_gethostbyname2()</code>,
+ <code class="function">lwres_gethostbyaddr()</code>
+ and
+ <code class="function">lwres_endhostent()</code>
+ are not thread safe; they return pointers to static data and
+ provide error codes through a global variable.
+ Thread-safe versions for name and address lookup are provided by
+ <code class="function">lwres_gethostbyname_r()</code>,
+ and
+ <code class="function">lwres_gethostbyaddr_r()</code>
+ respectively.
+ </p>
+<p>
+ The resolver daemon does not currently support any non-DNS
+ name services such as
+ <code class="filename">/etc/hosts</code>
+ or
+ <span class="type">NIS</span>,
+ consequently the above functions don't, either.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_getipnode.3 b/lib/lwres/man/lwres_getipnode.3
new file mode 100644
index 0000000..e5c51a9
--- /dev/null
+++ b/lib/lwres/man/lwres_getipnode.3
@@ -0,0 +1,206 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_getipnode.3,v 1.28 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_getipnode
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_GETIPNODE" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_getipnodebyname, lwres_getipnodebyaddr, lwres_freehostent \- lightweight resolver nodename / address translation API
+.SH "SYNOPSIS"
+.nf
+#include <lwres/netdb.h>
+.fi
+.HP 39
+.BI "struct hostent * lwres_getipnodebyname(const\ char\ *" "name" ", int\ " "af" ", int\ " "flags" ", int\ *" "error_num" ");"
+.HP 39
+.BI "struct hostent * lwres_getipnodebyaddr(const\ void\ *" "src" ", size_t\ " "len" ", int\ " "af" ", int\ *" "error_num" ");"
+.HP 23
+.BI "void lwres_freehostent(struct\ hostent\ *" "he" ");"
+.SH "DESCRIPTION"
+.PP
+These functions perform thread safe, protocol independent nodename\-to\-address and address\-to\-nodename translation as defined in RFC2553.
+.PP
+They use a
+\fBstruct hostent\fR
+which is defined in
+\fInamedb.h\fR:
+.PP
+.RS 4
+.nf
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+};
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+.fi
+.RE
+.sp
+.PP
+The members of this structure are:
+.PP
+\fBh_name\fR
+.RS 4
+The official (canonical) name of the host.
+.RE
+.PP
+\fBh_aliases\fR
+.RS 4
+A NULL\-terminated array of alternate names (nicknames) for the host.
+.RE
+.PP
+\fBh_addrtype\fR
+.RS 4
+The type of address being returned \- usually
+\fBPF_INET\fR
+or
+\fBPF_INET6\fR.
+.RE
+.PP
+\fBh_length\fR
+.RS 4
+The length of the address in bytes.
+.RE
+.PP
+\fBh_addr_list\fR
+.RS 4
+A
+\fBNULL\fR
+terminated array of network addresses for the host. Host addresses are returned in network byte order.
+.RE
+.PP
+\fBlwres_getipnodebyname()\fR
+looks up addresses of protocol family
+\fIaf\fR
+for the hostname
+\fIname\fR. The
+\fIflags\fR
+parameter contains ORed flag bits to specify the types of addresses that are searched for, and the types of addresses that are returned. The flag bits are:
+.PP
+\fBAI_V4MAPPED\fR
+.RS 4
+This is used with an
+\fIaf\fR
+of AF_INET6, and causes IPv4 addresses to be returned as IPv4\-mapped IPv6 addresses.
+.RE
+.PP
+\fBAI_ALL\fR
+.RS 4
+This is used with an
+\fIaf\fR
+of AF_INET6, and causes all known addresses (IPv6 and IPv4) to be returned. If AI_V4MAPPED is also set, the IPv4 addresses are return as mapped IPv6 addresses.
+.RE
+.PP
+\fBAI_ADDRCONFIG\fR
+.RS 4
+Only return an IPv6 or IPv4 address if here is an active network interface of that type. This is not currently implemented in the BIND 9 lightweight resolver, and the flag is ignored.
+.RE
+.PP
+\fBAI_DEFAULT\fR
+.RS 4
+This default sets the
+\fBAI_V4MAPPED\fR
+and
+\fBAI_ADDRCONFIG\fR
+flag bits.
+.RE
+.PP
+\fBlwres_getipnodebyaddr()\fR
+performs a reverse lookup of address
+\fIsrc\fR
+which is
+\fIlen\fR
+bytes long.
+\fIaf\fR
+denotes the protocol family, typically
+\fBPF_INET\fR
+or
+\fBPF_INET6\fR.
+.PP
+\fBlwres_freehostent()\fR
+releases all the memory associated with the
+\fBstruct hostent\fR
+pointer
+\fIhe\fR. Any memory allocated for the
+\fBh_name\fR,
+\fBh_addr_list\fR
+and
+\fBh_aliases\fR
+is freed, as is the memory for the
+\fBhostent\fR
+structure itself.
+.SH "RETURN VALUES"
+.PP
+If an error occurs,
+\fBlwres_getipnodebyname()\fR
+and
+\fBlwres_getipnodebyaddr()\fR
+set
+\fI*error_num\fR
+to an appropriate error code and the function returns a
+\fBNULL\fR
+pointer. The error codes and their meanings are defined in
+\fI<lwres/netdb.h>\fR:
+.PP
+\fBHOST_NOT_FOUND\fR
+.RS 4
+No such host is known.
+.RE
+.PP
+\fBNO_ADDRESS\fR
+.RS 4
+The server recognised the request and the name but no address is available. Another type of request to the name server for the domain might return an answer.
+.RE
+.PP
+\fBTRY_AGAIN\fR
+.RS 4
+A temporary and possibly transient error occurred, such as a failure of a server to respond. The request may succeed if retried.
+.RE
+.PP
+\fBNO_RECOVERY\fR
+.RS 4
+An unexpected failure occurred, and retrying the request is pointless.
+.RE
+.PP
+\fBlwres_hstrerror\fR(3)
+translates these error codes to suitable error messages.
+.SH "SEE ALSO"
+.PP
+\fBRFC2553\fR(),
+\fBlwres\fR(3),
+\fBlwres_gethostent\fR(3),
+\fBlwres_getaddrinfo\fR(3),
+\fBlwres_getnameinfo\fR(3),
+\fBlwres_hstrerror\fR(3).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001, 2003 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_getipnode.docbook b/lib/lwres/man/lwres_getipnode.docbook
new file mode 100644
index 0000000..825f462
--- /dev/null
+++ b/lib/lwres/man/lwres_getipnode.docbook
@@ -0,0 +1,331 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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
+ - 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: lwres_getipnode.docbook,v 1.12 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_getipnode</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_getipnodebyname</refname>
+ <refname>lwres_getipnodebyaddr</refname>
+ <refname>lwres_freehostent</refname>
+ <refpurpose>lightweight resolver nodename / address translation API</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/netdb.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+struct hostent *
+<function>lwres_getipnodebyname</function></funcdef>
+ <paramdef>const char *<parameter>name</parameter></paramdef>
+ <paramdef>int <parameter>af</parameter></paramdef>
+ <paramdef>int <parameter>flags</parameter></paramdef>
+ <paramdef>int *<parameter>error_num</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+struct hostent *
+<function>lwres_getipnodebyaddr</function></funcdef>
+ <paramdef>const void *<parameter>src</parameter></paramdef>
+ <paramdef>size_t <parameter>len</parameter></paramdef>
+ <paramdef>int <parameter>af</parameter></paramdef>
+ <paramdef>int *<parameter>error_num</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_freehostent</function></funcdef>
+ <paramdef>struct hostent *<parameter>he</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para>
+ These functions perform thread safe, protocol independent
+ nodename-to-address and address-to-nodename
+ translation as defined in RFC2553.
+ </para>
+
+ <para>
+ They use a
+ <type>struct hostent</type>
+ which is defined in
+ <filename>namedb.h</filename>:
+ </para>
+ <para><programlisting>
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+};
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+</programlisting>
+ </para>
+
+ <para>
+ The members of this structure are:
+ <variablelist>
+ <varlistentry>
+ <term><constant>h_name</constant></term>
+ <listitem>
+ <para>
+ The official (canonical) name of the host.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>h_aliases</constant></term>
+ <listitem>
+ <para>
+ A NULL-terminated array of alternate names (nicknames) for the
+ host.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>h_addrtype</constant></term>
+ <listitem>
+ <para>
+ The type of address being returned - usually
+ <type>PF_INET</type>
+ or
+ <type>PF_INET6</type>.
+
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>h_length</constant></term>
+ <listitem>
+ <para>
+ The length of the address in bytes.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>h_addr_list</constant></term>
+ <listitem>
+ <para>
+ A
+ <type>NULL</type>
+ terminated array of network addresses for the host.
+ Host addresses are returned in network byte order.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para><function>lwres_getipnodebyname()</function>
+ looks up addresses of protocol family <parameter>af</parameter>
+ for the hostname <parameter>name</parameter>. The
+ <parameter>flags</parameter> parameter contains ORed flag bits
+ to specify the types of addresses that are searched for, and the
+ types of addresses that are returned. The flag bits are:
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>AI_V4MAPPED</constant></term>
+ <listitem>
+ <para>
+ This is used with an
+ <parameter>af</parameter>
+ of AF_INET6, and causes IPv4 addresses to be returned as
+ IPv4-mapped
+ IPv6 addresses.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>AI_ALL</constant></term>
+ <listitem>
+ <para>
+ This is used with an
+ <parameter>af</parameter>
+ of AF_INET6, and causes all known addresses (IPv6 and IPv4) to
+ be returned.
+ If AI_V4MAPPED is also set, the IPv4 addresses are return as
+ mapped
+ IPv6 addresses.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>AI_ADDRCONFIG</constant></term>
+ <listitem>
+ <para>
+ Only return an IPv6 or IPv4 address if here is an active network
+ interface of that type. This is not currently implemented
+ in the BIND 9 lightweight resolver, and the flag is ignored.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>AI_DEFAULT</constant></term>
+ <listitem>
+ <para>
+ This default sets the
+ <constant>AI_V4MAPPED</constant>
+ and
+ <constant>AI_ADDRCONFIG</constant>
+ flag bits.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para><function>lwres_getipnodebyaddr()</function>
+ performs a reverse lookup of address <parameter>src</parameter>
+ which is <parameter>len</parameter> bytes long.
+ <parameter>af</parameter> denotes the protocol family, typically
+ <type>PF_INET</type> or <type>PF_INET6</type>.
+ </para>
+ <para><function>lwres_freehostent()</function>
+ releases all the memory associated with the <type>struct
+ hostent</type> pointer <parameter>he</parameter>. Any memory
+ allocated for the <constant>h_name</constant>,
+ <constant>h_addr_list</constant> and
+ <constant>h_aliases</constant> is freed, as is the memory for
+ the <type>hostent</type> structure itself.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para>
+ If an error occurs,
+ <function>lwres_getipnodebyname()</function>
+ and
+ <function>lwres_getipnodebyaddr()</function>
+ set
+ <parameter>*error_num</parameter>
+ to an appropriate error code and the function returns a
+ <type>NULL</type>
+ pointer.
+ The error codes and their meanings are defined in
+ <filename>&lt;lwres/netdb.h&gt;</filename>:
+ <variablelist>
+ <varlistentry>
+ <term><constant>HOST_NOT_FOUND</constant></term>
+ <listitem>
+ <para>
+ No such host is known.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>NO_ADDRESS</constant></term>
+ <listitem>
+ <para>
+ The server recognised the request and the name but no address is
+ available. Another type of request to the name server for the
+ domain might return an answer.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>TRY_AGAIN</constant></term>
+ <listitem>
+ <para>
+ A temporary and possibly transient error occurred, such as a
+ failure of a server to respond. The request may succeed if
+ retried.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>NO_RECOVERY</constant></term>
+ <listitem>
+ <para>
+ An unexpected failure occurred, and retrying the request
+ is pointless.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <para><citerefentry>
+ <refentrytitle>lwres_hstrerror</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ translates these error codes to suitable error messages.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>RFC2553</refentrytitle>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_gethostent</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_getaddrinfo</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_getnameinfo</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_hstrerror</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_getipnode.html b/lib/lwres/man/lwres_getipnode.html
new file mode 100644
index 0000000..23fe50f
--- /dev/null
+++ b/lib/lwres/man/lwres_getipnode.html
@@ -0,0 +1,279 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_getipnode.html,v 1.25 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_getipnode</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_getipnodebyname, lwres_getipnodebyaddr, lwres_freehostent &#8212; lightweight resolver nodename / address translation API</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/netdb.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+struct hostent *
+<b class="fsfunc">lwres_getipnodebyname</b>(</code></td>
+<td>const char * </td>
+<td>
+<var class="pdparam">name</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">af</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">flags</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int * </td>
+<td>
+<var class="pdparam">error_num</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+struct hostent *
+<b class="fsfunc">lwres_getipnodebyaddr</b>(</code></td>
+<td>const void * </td>
+<td>
+<var class="pdparam">src</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>size_t  </td>
+<td>
+<var class="pdparam">len</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">af</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int * </td>
+<td>
+<var class="pdparam">error_num</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_freehostent</b>(</code></td>
+<td>struct hostent * </td>
+<td>
+<var class="pdparam">he</var><code>)</code>;</td>
+</tr></table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543431"></a><h2>DESCRIPTION</h2>
+<p>
+ These functions perform thread safe, protocol independent
+ nodename-to-address and address-to-nodename
+ translation as defined in RFC2553.
+ </p>
+<p>
+ They use a
+ <span class="type">struct hostent</span>
+ which is defined in
+ <code class="filename">namedb.h</code>:
+ </p>
+<pre class="programlisting">
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+};
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+</pre>
+<p>
+ </p>
+<p>
+ The members of this structure are:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">h_name</code></span></dt>
+<dd><p>
+ The official (canonical) name of the host.
+ </p></dd>
+<dt><span class="term"><code class="constant">h_aliases</code></span></dt>
+<dd><p>
+ A NULL-terminated array of alternate names (nicknames) for the
+ host.
+ </p></dd>
+<dt><span class="term"><code class="constant">h_addrtype</code></span></dt>
+<dd><p>
+ The type of address being returned - usually
+ <span class="type">PF_INET</span>
+ or
+ <span class="type">PF_INET6</span>.
+
+ </p></dd>
+<dt><span class="term"><code class="constant">h_length</code></span></dt>
+<dd><p>
+ The length of the address in bytes.
+ </p></dd>
+<dt><span class="term"><code class="constant">h_addr_list</code></span></dt>
+<dd><p>
+ A
+ <span class="type">NULL</span>
+ terminated array of network addresses for the host.
+ Host addresses are returned in network byte order.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+<p><code class="function">lwres_getipnodebyname()</code>
+ looks up addresses of protocol family <em class="parameter"><code>af</code></em>
+ for the hostname <em class="parameter"><code>name</code></em>. The
+ <em class="parameter"><code>flags</code></em> parameter contains ORed flag bits
+ to specify the types of addresses that are searched for, and the
+ types of addresses that are returned. The flag bits are:
+
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">AI_V4MAPPED</code></span></dt>
+<dd><p>
+ This is used with an
+ <em class="parameter"><code>af</code></em>
+ of AF_INET6, and causes IPv4 addresses to be returned as
+ IPv4-mapped
+ IPv6 addresses.
+ </p></dd>
+<dt><span class="term"><code class="constant">AI_ALL</code></span></dt>
+<dd><p>
+ This is used with an
+ <em class="parameter"><code>af</code></em>
+ of AF_INET6, and causes all known addresses (IPv6 and IPv4) to
+ be returned.
+ If AI_V4MAPPED is also set, the IPv4 addresses are return as
+ mapped
+ IPv6 addresses.
+ </p></dd>
+<dt><span class="term"><code class="constant">AI_ADDRCONFIG</code></span></dt>
+<dd><p>
+ Only return an IPv6 or IPv4 address if here is an active network
+ interface of that type. This is not currently implemented
+ in the BIND 9 lightweight resolver, and the flag is ignored.
+ </p></dd>
+<dt><span class="term"><code class="constant">AI_DEFAULT</code></span></dt>
+<dd><p>
+ This default sets the
+ <code class="constant">AI_V4MAPPED</code>
+ and
+ <code class="constant">AI_ADDRCONFIG</code>
+ flag bits.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+<p><code class="function">lwres_getipnodebyaddr()</code>
+ performs a reverse lookup of address <em class="parameter"><code>src</code></em>
+ which is <em class="parameter"><code>len</code></em> bytes long.
+ <em class="parameter"><code>af</code></em> denotes the protocol family, typically
+ <span class="type">PF_INET</span> or <span class="type">PF_INET6</span>.
+ </p>
+<p><code class="function">lwres_freehostent()</code>
+ releases all the memory associated with the <span class="type">struct
+ hostent</span> pointer <em class="parameter"><code>he</code></em>. Any memory
+ allocated for the <code class="constant">h_name</code>,
+ <code class="constant">h_addr_list</code> and
+ <code class="constant">h_aliases</code> is freed, as is the memory for
+ the <span class="type">hostent</span> structure itself.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543689"></a><h2>RETURN VALUES</h2>
+<p>
+ If an error occurs,
+ <code class="function">lwres_getipnodebyname()</code>
+ and
+ <code class="function">lwres_getipnodebyaddr()</code>
+ set
+ <em class="parameter"><code>*error_num</code></em>
+ to an appropriate error code and the function returns a
+ <span class="type">NULL</span>
+ pointer.
+ The error codes and their meanings are defined in
+ <code class="filename">&lt;lwres/netdb.h&gt;</code>:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">HOST_NOT_FOUND</code></span></dt>
+<dd><p>
+ No such host is known.
+ </p></dd>
+<dt><span class="term"><code class="constant">NO_ADDRESS</code></span></dt>
+<dd><p>
+ The server recognised the request and the name but no address is
+ available. Another type of request to the name server for the
+ domain might return an answer.
+ </p></dd>
+<dt><span class="term"><code class="constant">TRY_AGAIN</code></span></dt>
+<dd><p>
+ A temporary and possibly transient error occurred, such as a
+ failure of a server to respond. The request may succeed if
+ retried.
+ </p></dd>
+<dt><span class="term"><code class="constant">NO_RECOVERY</code></span></dt>
+<dd><p>
+ An unexpected failure occurred, and retrying the request
+ is pointless.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+<p><span class="citerefentry"><span class="refentrytitle">lwres_hstrerror</span>(3)</span>
+ translates these error codes to suitable error messages.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543786"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">RFC2553</span></span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_gethostent</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_getaddrinfo</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_getnameinfo</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_hstrerror</span>(3)</span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_getnameinfo.3 b/lib/lwres/man/lwres_getnameinfo.3
new file mode 100644
index 0000000..c477f79
--- /dev/null
+++ b/lib/lwres/man/lwres_getnameinfo.3
@@ -0,0 +1,117 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_getnameinfo.3,v 1.29 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_getnameinfo
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_GETNAMEINFO" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_getnameinfo \- lightweight resolver socket address structure to hostname and service name
+.SH "SYNOPSIS"
+.nf
+#include <lwres/netdb.h>
+.fi
+.HP 22
+.BI "int lwres_getnameinfo(const\ struct\ sockaddr\ *" "sa" ", size_t\ " "salen" ", char\ *" "host" ", size_t\ " "hostlen" ", char\ *" "serv" ", size_t\ " "servlen" ", int\ " "flags" ");"
+.SH "DESCRIPTION"
+.PP
+This function is equivalent to the
+\fBgetnameinfo\fR(3)
+function defined in RFC2133.
+\fBlwres_getnameinfo()\fR
+returns the hostname for the
+\fBstruct sockaddr\fR
+\fIsa\fR
+which is
+\fIsalen\fR
+bytes long. The hostname is of length
+\fIhostlen\fR
+and is returned via
+\fI*host.\fR
+The maximum length of the hostname is 1025 bytes:
+\fBNI_MAXHOST\fR.
+.PP
+The name of the service associated with the port number in
+\fIsa\fR
+is returned in
+\fI*serv.\fR
+It is
+\fIservlen\fR
+bytes long. The maximum length of the service name is
+\fBNI_MAXSERV\fR
+\- 32 bytes.
+.PP
+The
+\fIflags\fR
+argument sets the following bits:
+.PP
+\fBNI_NOFQDN\fR
+.RS 4
+A fully qualified domain name is not required for local hosts. The local part of the fully qualified domain name is returned instead.
+.RE
+.PP
+\fBNI_NUMERICHOST\fR
+.RS 4
+Return the address in numeric form, as if calling inet_ntop(), instead of a host name.
+.RE
+.PP
+\fBNI_NAMEREQD\fR
+.RS 4
+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.
+.RE
+.PP
+\fBNI_NUMERICSERV\fR
+.RS 4
+The service name is returned as a digit string representing the port number.
+.RE
+.PP
+\fBNI_DGRAM\fR
+.RS 4
+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.
+.RE
+.SH "RETURN VALUES"
+.PP
+\fBlwres_getnameinfo()\fR
+returns 0 on success or a non\-zero error code if an error occurs.
+.SH "SEE ALSO"
+.PP
+\fBRFC2133\fR(),
+\fBgetservbyport\fR(3),
+\fBlwres\fR(3),
+\fBlwres_getnameinfo\fR(3),
+\fBlwres_getnamebyaddr\fR(3).
+\fBlwres_net_ntop\fR(3).
+.SH "BUGS"
+.PP
+RFC2133 fails to define what the nonzero return values of
+\fBgetnameinfo\fR(3)
+are.
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_getnameinfo.docbook b/lib/lwres/man/lwres_getnameinfo.docbook
new file mode 100644
index 0000000..504dfb7
--- /dev/null
+++ b/lib/lwres/man/lwres_getnameinfo.docbook
@@ -0,0 +1,205 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_getnameinfo.docbook,v 1.10 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_getnameinfo</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_getnameinfo</refname>
+ <refpurpose>lightweight resolver socket address structure to hostname and
+ service name
+ </refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/netdb.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+int
+<function>lwres_getnameinfo</function></funcdef>
+ <paramdef>const struct sockaddr *<parameter>sa</parameter></paramdef>
+ <paramdef>size_t <parameter>salen</parameter></paramdef>
+ <paramdef>char *<parameter>host</parameter></paramdef>
+ <paramdef>size_t <parameter>hostlen</parameter></paramdef>
+ <paramdef>char *<parameter>serv</parameter></paramdef>
+ <paramdef>size_t <parameter>servlen</parameter></paramdef>
+ <paramdef>int <parameter>flags</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para>
+ This function is equivalent to the
+ <citerefentry>
+ <refentrytitle>getnameinfo</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry> function defined in RFC2133.
+ <function>lwres_getnameinfo()</function> returns the
+ hostname for the
+ <type>struct sockaddr</type> <parameter>sa</parameter> which
+ is
+ <parameter>salen</parameter> bytes long. The hostname is of
+ length
+ <parameter>hostlen</parameter> and is returned via
+ <parameter>*host.</parameter> The maximum length of the
+ hostname is
+ 1025 bytes: <constant>NI_MAXHOST</constant>.
+ </para>
+
+ <para> The name of the service associated with the port number in
+ <parameter>sa</parameter> is returned in <parameter>*serv.</parameter>
+ It is <parameter>servlen</parameter> bytes long. The
+ maximum length
+ of the service name is <constant>NI_MAXSERV</constant> - 32
+ bytes.
+ </para>
+
+ <para>
+ The <parameter>flags</parameter> argument sets the
+ following
+ bits:
+ <variablelist>
+ <varlistentry>
+ <term><constant>NI_NOFQDN</constant></term>
+ <listitem>
+ <para>
+ A fully qualified domain name is not required for local hosts.
+ The local part of the fully qualified domain name is returned
+ instead.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>NI_NUMERICHOST</constant></term>
+ <listitem>
+ <para>
+ Return the address in numeric form, as if calling inet_ntop(),
+ instead of a host name.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>NI_NAMEREQD</constant></term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>NI_NUMERICSERV</constant></term>
+ <listitem>
+ <para>
+ The service name is returned as a digit string representing the
+ port number.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>NI_DGRAM</constant></term>
+ <listitem>
+ <para>
+ 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.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para><function>lwres_getnameinfo()</function>
+ returns 0 on success or a non-zero error code if an error occurs.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>RFC2133</refentrytitle>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>getservbyport</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>lwres</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>lwres_getnameinfo</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>lwres_getnamebyaddr</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ <citerefentry>
+ <refentrytitle>lwres_net_ntop</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>BUGS</title>
+ <para>
+ RFC2133 fails to define what the nonzero return values of
+ <citerefentry>
+ <refentrytitle>getnameinfo</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ are.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_getnameinfo.html b/lib/lwres/man/lwres_getnameinfo.html
new file mode 100644
index 0000000..53a70d9
--- /dev/null
+++ b/lib/lwres/man/lwres_getnameinfo.html
@@ -0,0 +1,176 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_getnameinfo.html,v 1.23 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_getnameinfo</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_getnameinfo &#8212; lightweight resolver socket address structure to hostname and
+ service name
+ </p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/netdb.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0">
+<tr>
+<td><code class="funcdef">
+int
+<b class="fsfunc">lwres_getnameinfo</b>(</code></td>
+<td>const struct sockaddr * </td>
+<td>
+<var class="pdparam">sa</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>size_t  </td>
+<td>
+<var class="pdparam">salen</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>char * </td>
+<td>
+<var class="pdparam">host</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>size_t  </td>
+<td>
+<var class="pdparam">hostlen</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>char * </td>
+<td>
+<var class="pdparam">serv</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>size_t  </td>
+<td>
+<var class="pdparam">servlen</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>int  </td>
+<td>
+<var class="pdparam">flags</var><code>)</code>;</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543393"></a><h2>DESCRIPTION</h2>
+<p>
+ This function is equivalent to the
+ <span class="citerefentry"><span class="refentrytitle">getnameinfo</span>(3)</span> function defined in RFC2133.
+ <code class="function">lwres_getnameinfo()</code> returns the
+ hostname for the
+ <span class="type">struct sockaddr</span> <em class="parameter"><code>sa</code></em> which
+ is
+ <em class="parameter"><code>salen</code></em> bytes long. The hostname is of
+ length
+ <em class="parameter"><code>hostlen</code></em> and is returned via
+ <em class="parameter"><code>*host.</code></em> The maximum length of the
+ hostname is
+ 1025 bytes: <code class="constant">NI_MAXHOST</code>.
+ </p>
+<p> The name of the service associated with the port number in
+ <em class="parameter"><code>sa</code></em> is returned in <em class="parameter"><code>*serv.</code></em>
+ It is <em class="parameter"><code>servlen</code></em> bytes long. The
+ maximum length
+ of the service name is <code class="constant">NI_MAXSERV</code> - 32
+ bytes.
+ </p>
+<p>
+ The <em class="parameter"><code>flags</code></em> argument sets the
+ following
+ bits:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">NI_NOFQDN</code></span></dt>
+<dd><p>
+ A fully qualified domain name is not required for local hosts.
+ The local part of the fully qualified domain name is returned
+ instead.
+ </p></dd>
+<dt><span class="term"><code class="constant">NI_NUMERICHOST</code></span></dt>
+<dd><p>
+ Return the address in numeric form, as if calling inet_ntop(),
+ instead of a host name.
+ </p></dd>
+<dt><span class="term"><code class="constant">NI_NAMEREQD</code></span></dt>
+<dd><p>
+ 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.
+ </p></dd>
+<dt><span class="term"><code class="constant">NI_NUMERICSERV</code></span></dt>
+<dd><p>
+ The service name is returned as a digit string representing the
+ port number.
+ </p></dd>
+<dt><span class="term"><code class="constant">NI_DGRAM</code></span></dt>
+<dd><p>
+ 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.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543534"></a><h2>RETURN VALUES</h2>
+<p><code class="function">lwres_getnameinfo()</code>
+ returns 0 on success or a non-zero error code if an error occurs.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543546"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">RFC2133</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">getservbyport</span>(3)</span>,
+ <span class="citerefentry"><span class="refentrytitle">lwres</span>(3)</span>,
+ <span class="citerefentry"><span class="refentrytitle">lwres_getnameinfo</span>(3)</span>,
+ <span class="citerefentry"><span class="refentrytitle">lwres_getnamebyaddr</span>(3)</span>.
+ <span class="citerefentry"><span class="refentrytitle">lwres_net_ntop</span>(3)</span>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543604"></a><h2>BUGS</h2>
+<p>
+ RFC2133 fails to define what the nonzero return values of
+ <span class="citerefentry"><span class="refentrytitle">getnameinfo</span>(3)</span>
+ are.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_getrrsetbyname.3 b/lib/lwres/man/lwres_getrrsetbyname.3
new file mode 100644
index 0000000..8419fff
--- /dev/null
+++ b/lib/lwres/man/lwres_getrrsetbyname.3
@@ -0,0 +1,164 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_getrrsetbyname.3,v 1.25 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_getrrsetbyname
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Oct 18, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_GETRRSETBYNAME" "3" "Oct 18, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_getrrsetbyname, lwres_freerrset \- retrieve DNS records
+.SH "SYNOPSIS"
+.nf
+#include <lwres/netdb.h>
+.fi
+.HP 25
+.BI "int lwres_getrrsetbyname(const\ char\ *" "hostname" ", unsigned\ int\ " "rdclass" ", unsigned\ int\ " "rdtype" ", unsigned\ int\ " "flags" ", struct\ rrsetinfo\ **" "res" ");"
+.HP 21
+.BI "void lwres_freerrset(struct\ rrsetinfo\ *" "rrset" ");"
+.PP
+The following structures are used:
+.PP
+.RS 4
+.nf
+struct rdatainfo {
+ unsigned int rdi_length; /* length of data */
+ unsigned char *rdi_data; /* record data */
+};
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+struct rrsetinfo {
+ unsigned int rri_flags; /* RRSET_VALIDATED... */
+ unsigned int rri_rdclass; /* class number */
+ unsigned int rri_rdtype; /* RR type number */
+ unsigned int rri_ttl; /* time to live */
+ unsigned int rri_nrdatas; /* size of rdatas array */
+ unsigned int rri_nsigs; /* size of sigs array */
+ char *rri_name; /* canonical name */
+ struct rdatainfo *rri_rdatas; /* individual records */
+ struct rdatainfo *rri_sigs; /* individual signatures */
+};
+.fi
+.RE
+.sp
+.SH "DESCRIPTION"
+.PP
+\fBlwres_getrrsetbyname()\fR
+gets a set of resource records associated with a
+\fIhostname\fR,
+\fIclass\fR, and
+\fItype\fR.
+\fIhostname\fR
+is a pointer a to null\-terminated string. The
+\fIflags\fR
+field is currently unused and must be zero.
+.PP
+After a successful call to
+\fBlwres_getrrsetbyname()\fR,
+\fI*res\fR
+is a pointer to an
+\fBrrsetinfo\fR
+structure, containing a list of one or more
+\fBrdatainfo\fR
+structures containing resource records and potentially another list of
+\fBrdatainfo\fR
+structures containing SIG resource records associated with those records. The members
+\fBrri_rdclass\fR
+and
+\fBrri_rdtype\fR
+are copied from the parameters.
+\fBrri_ttl\fR
+and
+\fBrri_name\fR
+are properties of the obtained rrset. The resource records contained in
+\fBrri_rdatas\fR
+and
+\fBrri_sigs\fR
+are in uncompressed DNS wire format. Properties of the rdataset are represented in the
+\fBrri_flags\fR
+bitfield. If the RRSET_VALIDATED bit is set, the data has been DNSSEC validated and the signatures verified.
+.PP
+All of the information returned by
+\fBlwres_getrrsetbyname()\fR
+is dynamically allocated: the
+\fBrrsetinfo\fR
+and
+\fBrdatainfo\fR
+structures, and the canonical host name strings pointed to by the
+\fBrrsetinfo\fRstructure. Memory allocated for the dynamically allocated structures created by a successful call to
+\fBlwres_getrrsetbyname()\fR
+is released by
+\fBlwres_freerrset()\fR.
+\fIrrset\fR
+is a pointer to a
+\fBstruct rrset\fR
+created by a call to
+\fBlwres_getrrsetbyname()\fR.
+.PP
+.SH "RETURN VALUES"
+.PP
+\fBlwres_getrrsetbyname()\fR
+returns zero on success, and one of the following error codes if an error occurred:
+.PP
+\fBERRSET_NONAME\fR
+.RS 4
+the name does not exist
+.RE
+.PP
+\fBERRSET_NODATA\fR
+.RS 4
+the name exists, but does not have data of the desired type
+.RE
+.PP
+\fBERRSET_NOMEMORY\fR
+.RS 4
+memory could not be allocated
+.RE
+.PP
+\fBERRSET_INVAL\fR
+.RS 4
+a parameter is invalid
+.RE
+.PP
+\fBERRSET_FAIL\fR
+.RS 4
+other failure
+.RE
+.PP
+.RS 4
+.RE
+.SH "SEE ALSO"
+.PP
+\fBlwres\fR(3).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_getrrsetbyname.docbook b/lib/lwres/man/lwres_getrrsetbyname.docbook
new file mode 100644
index 0000000..5f2a68d
--- /dev/null
+++ b/lib/lwres/man/lwres_getrrsetbyname.docbook
@@ -0,0 +1,223 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_getrrsetbyname.docbook,v 1.10 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Oct 18, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_getrrsetbyname</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_getrrsetbyname</refname>
+ <refname>lwres_freerrset</refname>
+ <refpurpose>retrieve DNS records</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/netdb.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+int
+<function>lwres_getrrsetbyname</function></funcdef>
+ <paramdef>const char *<parameter>hostname</parameter></paramdef>
+ <paramdef>unsigned int <parameter>rdclass</parameter></paramdef>
+ <paramdef>unsigned int <parameter>rdtype</parameter></paramdef>
+ <paramdef>unsigned int <parameter>flags</parameter></paramdef>
+ <paramdef>struct rrsetinfo **<parameter>res</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_freerrset</function></funcdef>
+ <paramdef>struct rrsetinfo *<parameter>rrset</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+
+ <para>
+ The following structures are used:
+ </para>
+ <para><programlisting>
+struct rdatainfo {
+ unsigned int rdi_length; /* length of data */
+ unsigned char *rdi_data; /* record data */
+};
+</programlisting>
+ </para>
+ <para><programlisting>
+struct rrsetinfo {
+ unsigned int rri_flags; /* RRSET_VALIDATED... */
+ unsigned int rri_rdclass; /* class number */
+ unsigned int rri_rdtype; /* RR type number */
+ unsigned int rri_ttl; /* time to live */
+ unsigned int rri_nrdatas; /* size of rdatas array */
+ unsigned int rri_nsigs; /* size of sigs array */
+ char *rri_name; /* canonical name */
+ struct rdatainfo *rri_rdatas; /* individual records */
+ struct rdatainfo *rri_sigs; /* individual signatures */
+};
+</programlisting>
+ </para>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><function>lwres_getrrsetbyname()</function>
+ gets a set of resource records associated with a
+ <parameter>hostname</parameter>, <parameter>class</parameter>,
+ and <parameter>type</parameter>.
+ <parameter>hostname</parameter> is a pointer a to
+ null-terminated string. The <parameter>flags</parameter> field
+ is currently unused and must be zero.
+ </para>
+ <para>
+ After a successful call to
+ <function>lwres_getrrsetbyname()</function>,
+ <parameter>*res</parameter> is a pointer to an
+ <type>rrsetinfo</type> structure, containing a list of one or
+ more <type>rdatainfo</type> structures containing resource
+ records and potentially another list of <type>rdatainfo</type>
+ structures containing SIG resource records associated with those
+ records. The members <constant>rri_rdclass</constant> and
+ <constant>rri_rdtype</constant> are copied from the parameters.
+ <constant>rri_ttl</constant> and <constant>rri_name</constant>
+ are properties of the obtained rrset. The resource records
+ contained in <constant>rri_rdatas</constant> and
+ <constant>rri_sigs</constant> are in uncompressed DNS wire
+ format. Properties of the rdataset are represented in the
+ <constant>rri_flags</constant> bitfield. If the RRSET_VALIDATED
+ bit is set, the data has been DNSSEC validated and the
+ signatures verified.
+ </para>
+ <para>
+ All of the information returned by
+ <function>lwres_getrrsetbyname()</function> is dynamically
+ allocated: the <constant>rrsetinfo</constant> and
+ <constant>rdatainfo</constant> structures, and the canonical
+ host name strings pointed to by the
+ <constant>rrsetinfo</constant>structure.
+
+ Memory allocated for the dynamically allocated structures
+ created by a successful call to
+ <function>lwres_getrrsetbyname()</function> is released by
+ <function>lwres_freerrset()</function>.
+
+ <parameter>rrset</parameter> is a pointer to a <type>struct
+ rrset</type> created by a call to
+ <function>lwres_getrrsetbyname()</function>.
+ </para>
+ <para></para>
+ </refsect1>
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para><function>lwres_getrrsetbyname()</function>
+ returns zero on success, and one of the following error codes if
+ an error occurred:
+ <variablelist>
+
+ <varlistentry>
+ <term><constant>ERRSET_NONAME</constant></term>
+ <listitem>
+ <para>
+ the name does not exist
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>ERRSET_NODATA</constant></term>
+ <listitem>
+ <para>
+ the name exists, but does not have data of the desired type
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>ERRSET_NOMEMORY</constant></term>
+ <listitem>
+ <para>
+ memory could not be allocated
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>ERRSET_INVAL</constant></term>
+ <listitem>
+ <para>
+ a parameter is invalid
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>ERRSET_FAIL</constant></term>
+ <listitem>
+ <para>
+ other failure
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant/></term>
+ <listitem>
+ <para></para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>lwres</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ </para>
+
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_getrrsetbyname.html b/lib/lwres/man/lwres_getrrsetbyname.html
new file mode 100644
index 0000000..8dc36a1
--- /dev/null
+++ b/lib/lwres/man/lwres_getrrsetbyname.html
@@ -0,0 +1,192 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_getrrsetbyname.html,v 1.23 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_getrrsetbyname</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_getrrsetbyname, lwres_freerrset &#8212; retrieve DNS records</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/netdb.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+int
+<b class="fsfunc">lwres_getrrsetbyname</b>(</code></td>
+<td>const char * </td>
+<td>
+<var class="pdparam">hostname</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned int  </td>
+<td>
+<var class="pdparam">rdclass</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned int  </td>
+<td>
+<var class="pdparam">rdtype</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>unsigned int  </td>
+<td>
+<var class="pdparam">flags</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>struct rrsetinfo ** </td>
+<td>
+<var class="pdparam">res</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_freerrset</b>(</code></td>
+<td>struct rrsetinfo * </td>
+<td>
+<var class="pdparam">rrset</var><code>)</code>;</td>
+</tr></table>
+</div>
+<p>
+ The following structures are used:
+ </p>
+<pre class="programlisting">
+struct rdatainfo {
+ unsigned int rdi_length; /* length of data */
+ unsigned char *rdi_data; /* record data */
+};
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+struct rrsetinfo {
+ unsigned int rri_flags; /* RRSET_VALIDATED... */
+ unsigned int rri_rdclass; /* class number */
+ unsigned int rri_rdtype; /* RR type number */
+ unsigned int rri_ttl; /* time to live */
+ unsigned int rri_nrdatas; /* size of rdatas array */
+ unsigned int rri_nsigs; /* size of sigs array */
+ char *rri_name; /* canonical name */
+ struct rdatainfo *rri_rdatas; /* individual records */
+ struct rdatainfo *rri_sigs; /* individual signatures */
+};
+</pre>
+<p>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543414"></a><h2>DESCRIPTION</h2>
+<p><code class="function">lwres_getrrsetbyname()</code>
+ gets a set of resource records associated with a
+ <em class="parameter"><code>hostname</code></em>, <em class="parameter"><code>class</code></em>,
+ and <em class="parameter"><code>type</code></em>.
+ <em class="parameter"><code>hostname</code></em> is a pointer a to
+ null-terminated string. The <em class="parameter"><code>flags</code></em> field
+ is currently unused and must be zero.
+ </p>
+<p>
+ After a successful call to
+ <code class="function">lwres_getrrsetbyname()</code>,
+ <em class="parameter"><code>*res</code></em> is a pointer to an
+ <span class="type">rrsetinfo</span> structure, containing a list of one or
+ more <span class="type">rdatainfo</span> structures containing resource
+ records and potentially another list of <span class="type">rdatainfo</span>
+ structures containing SIG resource records associated with those
+ records. The members <code class="constant">rri_rdclass</code> and
+ <code class="constant">rri_rdtype</code> are copied from the parameters.
+ <code class="constant">rri_ttl</code> and <code class="constant">rri_name</code>
+ are properties of the obtained rrset. The resource records
+ contained in <code class="constant">rri_rdatas</code> and
+ <code class="constant">rri_sigs</code> are in uncompressed DNS wire
+ format. Properties of the rdataset are represented in the
+ <code class="constant">rri_flags</code> bitfield. If the RRSET_VALIDATED
+ bit is set, the data has been DNSSEC validated and the
+ signatures verified.
+ </p>
+<p>
+ All of the information returned by
+ <code class="function">lwres_getrrsetbyname()</code> is dynamically
+ allocated: the <code class="constant">rrsetinfo</code> and
+ <code class="constant">rdatainfo</code> structures, and the canonical
+ host name strings pointed to by the
+ <code class="constant">rrsetinfo</code>structure.
+
+ Memory allocated for the dynamically allocated structures
+ created by a successful call to
+ <code class="function">lwres_getrrsetbyname()</code> is released by
+ <code class="function">lwres_freerrset()</code>.
+
+ <em class="parameter"><code>rrset</code></em> is a pointer to a <span class="type">struct
+ rrset</span> created by a call to
+ <code class="function">lwres_getrrsetbyname()</code>.
+ </p>
+<p></p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543526"></a><h2>RETURN VALUES</h2>
+<p><code class="function">lwres_getrrsetbyname()</code>
+ returns zero on success, and one of the following error codes if
+ an error occurred:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">ERRSET_NONAME</code></span></dt>
+<dd><p>
+ the name does not exist
+ </p></dd>
+<dt><span class="term"><code class="constant">ERRSET_NODATA</code></span></dt>
+<dd><p>
+ the name exists, but does not have data of the desired type
+ </p></dd>
+<dt><span class="term"><code class="constant">ERRSET_NOMEMORY</code></span></dt>
+<dd><p>
+ memory could not be allocated
+ </p></dd>
+<dt><span class="term"><code class="constant">ERRSET_INVAL</code></span></dt>
+<dd><p>
+ a parameter is invalid
+ </p></dd>
+<dt><span class="term"><code class="constant">ERRSET_FAIL</code></span></dt>
+<dd><p>
+ other failure
+ </p></dd>
+<dt><span class="term"><code class="constant"></code></span></dt>
+<dd><p></p></dd>
+</dl></div>
+<p>
+
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543626"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">lwres</span>(3)</span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_gnba.3 b/lib/lwres/man/lwres_gnba.3
new file mode 100644
index 0000000..39a1b9d
--- /dev/null
+++ b/lib/lwres/man/lwres_gnba.3
@@ -0,0 +1,183 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_gnba.3,v 1.27 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_gnba
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_GNBA" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_gnbarequest_render, lwres_gnbaresponse_render, lwres_gnbarequest_parse, lwres_gnbaresponse_parse, lwres_gnbaresponse_free, lwres_gnbarequest_free \- lightweight resolver getnamebyaddress message handling
+.SH "SYNOPSIS"
+.nf
+#include <lwres/lwres.h>
+.fi
+.HP 40
+.BI "lwres_result_t lwres_gnbarequest_render(lwres_context_t\ *" "ctx" ", lwres_gnbarequest_t\ *" "req" ", lwres_lwpacket_t\ *" "pkt" ", lwres_buffer_t\ *" "b" ");"
+.HP 41
+.BI "lwres_result_t lwres_gnbaresponse_render(lwres_context_t\ *" "ctx" ", lwres_gnbaresponse_t\ *" "req" ", lwres_lwpacket_t\ *" "pkt" ", lwres_buffer_t\ *" "b" ");"
+.HP 39
+.BI "lwres_result_t lwres_gnbarequest_parse(lwres_context_t\ *" "ctx" ", lwres_buffer_t\ *" "b" ", lwres_lwpacket_t\ *" "pkt" ", lwres_gnbarequest_t\ **" "structp" ");"
+.HP 40
+.BI "lwres_result_t lwres_gnbaresponse_parse(lwres_context_t\ *" "ctx" ", lwres_buffer_t\ *" "b" ", lwres_lwpacket_t\ *" "pkt" ", lwres_gnbaresponse_t\ **" "structp" ");"
+.HP 29
+.BI "void lwres_gnbaresponse_free(lwres_context_t\ *" "ctx" ", lwres_gnbaresponse_t\ **" "structp" ");"
+.HP 28
+.BI "void lwres_gnbarequest_free(lwres_context_t\ *" "ctx" ", lwres_gnbarequest_t\ **" "structp" ");"
+.SH "DESCRIPTION"
+.PP
+These are low\-level routines for creating and parsing lightweight resolver address\-to\-name lookup request and response messages.
+.PP
+There are four main functions for the getnamebyaddr opcode. One render function converts a getnamebyaddr request structure \(em
+\fBlwres_gnbarequest_t\fR
+\(em to the lightweight resolver's canonical format. It is complemented by a parse function that converts a packet in this canonical format to a getnamebyaddr request structure. Another render function converts the getnamebyaddr response structure \(em
+\fBlwres_gnbaresponse_t\fR
+to the canonical format. This is complemented by a parse function which converts a packet in canonical format to a getnamebyaddr response structure.
+.PP
+These structures are defined in
+\fIlwres/lwres.h\fR. They are shown below.
+.PP
+.RS 4
+.nf
+#define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_addr_t addr;
+} lwres_gnbarequest_t;
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ void *base;
+ size_t baselen;
+} lwres_gnbaresponse_t;
+.fi
+.RE
+.sp
+.PP
+\fBlwres_gnbarequest_render()\fR
+uses resolver context
+\fIctx\fR
+to convert getnamebyaddr request structure
+\fIreq\fR
+to canonical format. The packet header structure
+\fIpkt\fR
+is initialised and transferred to buffer
+\fIb\fR. The contents of
+\fI*req\fR
+are then appended to the buffer in canonical format.
+\fBlwres_gnbaresponse_render()\fR
+performs the same task, except it converts a getnamebyaddr response structure
+\fBlwres_gnbaresponse_t\fR
+to the lightweight resolver's canonical format.
+.PP
+\fBlwres_gnbarequest_parse()\fR
+uses context
+\fIctx\fR
+to convert the contents of packet
+\fIpkt\fR
+to a
+\fBlwres_gnbarequest_t\fR
+structure. Buffer
+\fIb\fR
+provides space to be used for storing this structure. When the function succeeds, the resulting
+\fBlwres_gnbarequest_t\fR
+is made available through
+\fI*structp\fR.
+\fBlwres_gnbaresponse_parse()\fR
+offers the same semantics as
+\fBlwres_gnbarequest_parse()\fR
+except it yields a
+\fBlwres_gnbaresponse_t\fR
+structure.
+.PP
+\fBlwres_gnbaresponse_free()\fR
+and
+\fBlwres_gnbarequest_free()\fR
+release the memory in resolver context
+\fIctx\fR
+that was allocated to the
+\fBlwres_gnbaresponse_t\fR
+or
+\fBlwres_gnbarequest_t\fR
+structures referenced via
+\fIstructp\fR. Any memory associated with ancillary buffers and strings for those structures is also discarded.
+.SH "RETURN VALUES"
+.PP
+The getnamebyaddr opcode functions
+\fBlwres_gnbarequest_render()\fR,
+\fBlwres_gnbaresponse_render()\fR
+\fBlwres_gnbarequest_parse()\fR
+and
+\fBlwres_gnbaresponse_parse()\fR
+all return
+\fBLWRES_R_SUCCESS\fR
+on success. They return
+\fBLWRES_R_NOMEMORY\fR
+if memory allocation fails.
+\fBLWRES_R_UNEXPECTEDEND\fR
+is returned if the available space in the buffer
+\fIb\fR
+is too small to accommodate the packet header or the
+\fBlwres_gnbarequest_t\fR
+and
+\fBlwres_gnbaresponse_t\fR
+structures.
+\fBlwres_gnbarequest_parse()\fR
+and
+\fBlwres_gnbaresponse_parse()\fR
+will return
+\fBLWRES_R_UNEXPECTEDEND\fR
+if the buffer is not empty after decoding the received packet. These functions will return
+\fBLWRES_R_FAILURE\fR
+if
+pktflags
+in the packet header structure
+\fBlwres_lwpacket_t\fR
+indicate that the packet is not a response to an earlier query.
+.SH "SEE ALSO"
+.PP
+\fBlwres_packet\fR(3).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_gnba.docbook b/lib/lwres/man/lwres_gnba.docbook
new file mode 100644
index 0000000..452cdfc
--- /dev/null
+++ b/lib/lwres/man/lwres_gnba.docbook
@@ -0,0 +1,261 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_gnba.docbook,v 1.11 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_gnba</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_gnbarequest_render</refname>
+ <refname>lwres_gnbaresponse_render</refname>
+ <refname>lwres_gnbarequest_parse</refname>
+ <refname>lwres_gnbaresponse_parse</refname>
+ <refname>lwres_gnbaresponse_free</refname>
+ <refname>lwres_gnbarequest_free</refname>
+ <refpurpose>lightweight resolver getnamebyaddress message handling</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+
+ <funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;lwres/lwres.h&gt;
+</funcsynopsisinfo>
+
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_gnbarequest_render</function>
+</funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_gnbarequest_t *<parameter>req</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_gnbaresponse_render</function>
+</funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_gnbaresponse_t *<parameter>req</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_gnbarequest_parse</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_gnbarequest_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_gnbaresponse_parse</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_gnbaresponse_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_gnbaresponse_free</function>
+</funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_gnbaresponse_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_gnbarequest_free</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_gnbarequest_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ These are low-level routines for creating and parsing
+ lightweight resolver address-to-name lookup request and
+ response messages.
+ </para>
+ <para>
+ There are four main functions for the getnamebyaddr opcode.
+ One render function converts a getnamebyaddr request structure &mdash;
+ <type>lwres_gnbarequest_t</type> &mdash;
+ to the lightweight resolver's canonical format.
+ It is complemented by a parse function that converts a packet in this
+ canonical format to a getnamebyaddr request structure.
+ Another render function converts the getnamebyaddr response structure
+ &mdash;
+ <type>lwres_gnbaresponse_t</type>
+ to the canonical format.
+ This is complemented by a parse function which converts a packet in
+ canonical format to a getnamebyaddr response structure.
+ </para>
+ <para>
+ These structures are defined in
+ <filename>lwres/lwres.h</filename>.
+ They are shown below.
+ </para>
+ <para><programlisting>
+#define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
+</programlisting>
+ </para>
+ <para><programlisting>
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_addr_t addr;
+} lwres_gnbarequest_t;
+</programlisting>
+ </para>
+ <para><programlisting>
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ void *base;
+ size_t baselen;
+} lwres_gnbaresponse_t;
+</programlisting>
+ </para>
+
+ <para><function>lwres_gnbarequest_render()</function>
+ uses resolver context <varname>ctx</varname> to convert
+ getnamebyaddr request structure <varname>req</varname> to
+ canonical format. The packet header structure
+ <varname>pkt</varname> is initialised and transferred to buffer
+ <varname>b</varname>. The contents of <varname>*req</varname>
+ are then appended to the buffer in canonical format.
+ <function>lwres_gnbaresponse_render()</function> performs the
+ same task, except it converts a getnamebyaddr response structure
+ <type>lwres_gnbaresponse_t</type> to the lightweight resolver's
+ canonical format.
+ </para>
+
+ <para><function>lwres_gnbarequest_parse()</function>
+ uses context <varname>ctx</varname> to convert the contents of
+ packet <varname>pkt</varname> to a
+ <type>lwres_gnbarequest_t</type> structure. Buffer
+ <varname>b</varname> provides space to be used for storing this
+ structure. When the function succeeds, the resulting
+ <type>lwres_gnbarequest_t</type> is made available through
+ <varname>*structp</varname>.
+ <function>lwres_gnbaresponse_parse()</function> offers the same
+ semantics as <function>lwres_gnbarequest_parse()</function>
+ except it yields a <type>lwres_gnbaresponse_t</type> structure.
+ </para>
+
+ <para><function>lwres_gnbaresponse_free()</function>
+ and <function>lwres_gnbarequest_free()</function> release the
+ memory in resolver context <varname>ctx</varname> that was
+ allocated to the <type>lwres_gnbaresponse_t</type> or
+ <type>lwres_gnbarequest_t</type> structures referenced via
+ <varname>structp</varname>. Any memory associated with
+ ancillary buffers and strings for those structures is also
+ discarded.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para>
+ The getnamebyaddr opcode functions
+ <function>lwres_gnbarequest_render()</function>,
+ <function>lwres_gnbaresponse_render()</function>
+ <function>lwres_gnbarequest_parse()</function>
+ and
+ <function>lwres_gnbaresponse_parse()</function>
+ all return
+ <errorcode>LWRES_R_SUCCESS</errorcode>
+ on success.
+ They return
+ <errorcode>LWRES_R_NOMEMORY</errorcode>
+ if memory allocation fails.
+ <errorcode>LWRES_R_UNEXPECTEDEND</errorcode>
+ is returned if the available space in the buffer
+ <varname>b</varname>
+ is too small to accommodate the packet header or the
+ <type>lwres_gnbarequest_t</type>
+ and
+ <type>lwres_gnbaresponse_t</type>
+ structures.
+ <function>lwres_gnbarequest_parse()</function>
+ and
+ <function>lwres_gnbaresponse_parse()</function>
+ will return
+ <errorcode>LWRES_R_UNEXPECTEDEND</errorcode>
+ if the buffer is not empty after decoding the received packet.
+ These functions will return
+ <errorcode>LWRES_R_FAILURE</errorcode>
+ if
+ <structfield>pktflags</structfield>
+ in the packet header structure
+ <type>lwres_lwpacket_t</type>
+ indicate that the packet is not a response to an earlier query.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>lwres_packet</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_gnba.html b/lib/lwres/man/lwres_gnba.html
new file mode 100644
index 0000000..88b18a8
--- /dev/null
+++ b/lib/lwres/man/lwres_gnba.html
@@ -0,0 +1,316 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_gnba.html,v 1.24 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_gnba</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_gnbarequest_render, lwres_gnbaresponse_render, lwres_gnbarequest_parse, lwres_gnbaresponse_parse, lwres_gnbaresponse_free, lwres_gnbarequest_free &#8212; lightweight resolver getnamebyaddress message handling</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">
+#include &lt;lwres/lwres.h&gt;
+</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_gnbarequest_render</b>
+(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gnbarequest_t * </td>
+<td>
+<var class="pdparam">req</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_gnbaresponse_render</b>
+(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gnbaresponse_t * </td>
+<td>
+<var class="pdparam">req</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_gnbarequest_parse</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gnbarequest_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_gnbaresponse_parse</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gnbaresponse_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_gnbaresponse_free</b>
+(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gnbaresponse_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_gnbarequest_free</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gnbarequest_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543525"></a><h2>DESCRIPTION</h2>
+<p>
+ These are low-level routines for creating and parsing
+ lightweight resolver address-to-name lookup request and
+ response messages.
+ </p>
+<p>
+ There are four main functions for the getnamebyaddr opcode.
+ One render function converts a getnamebyaddr request structure &#8212;
+ <span class="type">lwres_gnbarequest_t</span> &#8212;
+ to the lightweight resolver's canonical format.
+ It is complemented by a parse function that converts a packet in this
+ canonical format to a getnamebyaddr request structure.
+ Another render function converts the getnamebyaddr response structure
+ &#8212;
+ <span class="type">lwres_gnbaresponse_t</span>
+ to the canonical format.
+ This is complemented by a parse function which converts a packet in
+ canonical format to a getnamebyaddr response structure.
+ </p>
+<p>
+ These structures are defined in
+ <code class="filename">lwres/lwres.h</code>.
+ They are shown below.
+ </p>
+<pre class="programlisting">
+#define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_addr_t addr;
+} lwres_gnbarequest_t;
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ void *base;
+ size_t baselen;
+} lwres_gnbaresponse_t;
+</pre>
+<p>
+ </p>
+<p><code class="function">lwres_gnbarequest_render()</code>
+ uses resolver context <code class="varname">ctx</code> to convert
+ getnamebyaddr request structure <code class="varname">req</code> to
+ canonical format. The packet header structure
+ <code class="varname">pkt</code> is initialised and transferred to buffer
+ <code class="varname">b</code>. The contents of <code class="varname">*req</code>
+ are then appended to the buffer in canonical format.
+ <code class="function">lwres_gnbaresponse_render()</code> performs the
+ same task, except it converts a getnamebyaddr response structure
+ <span class="type">lwres_gnbaresponse_t</span> to the lightweight resolver's
+ canonical format.
+ </p>
+<p><code class="function">lwres_gnbarequest_parse()</code>
+ uses context <code class="varname">ctx</code> to convert the contents of
+ packet <code class="varname">pkt</code> to a
+ <span class="type">lwres_gnbarequest_t</span> structure. Buffer
+ <code class="varname">b</code> provides space to be used for storing this
+ structure. When the function succeeds, the resulting
+ <span class="type">lwres_gnbarequest_t</span> is made available through
+ <code class="varname">*structp</code>.
+ <code class="function">lwres_gnbaresponse_parse()</code> offers the same
+ semantics as <code class="function">lwres_gnbarequest_parse()</code>
+ except it yields a <span class="type">lwres_gnbaresponse_t</span> structure.
+ </p>
+<p><code class="function">lwres_gnbaresponse_free()</code>
+ and <code class="function">lwres_gnbarequest_free()</code> release the
+ memory in resolver context <code class="varname">ctx</code> that was
+ allocated to the <span class="type">lwres_gnbaresponse_t</span> or
+ <span class="type">lwres_gnbarequest_t</span> structures referenced via
+ <code class="varname">structp</code>. Any memory associated with
+ ancillary buffers and strings for those structures is also
+ discarded.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543665"></a><h2>RETURN VALUES</h2>
+<p>
+ The getnamebyaddr opcode functions
+ <code class="function">lwres_gnbarequest_render()</code>,
+ <code class="function">lwres_gnbaresponse_render()</code>
+ <code class="function">lwres_gnbarequest_parse()</code>
+ and
+ <code class="function">lwres_gnbaresponse_parse()</code>
+ all return
+ <span class="errorcode">LWRES_R_SUCCESS</span>
+ on success.
+ They return
+ <span class="errorcode">LWRES_R_NOMEMORY</span>
+ if memory allocation fails.
+ <span class="errorcode">LWRES_R_UNEXPECTEDEND</span>
+ is returned if the available space in the buffer
+ <code class="varname">b</code>
+ is too small to accommodate the packet header or the
+ <span class="type">lwres_gnbarequest_t</span>
+ and
+ <span class="type">lwres_gnbaresponse_t</span>
+ structures.
+ <code class="function">lwres_gnbarequest_parse()</code>
+ and
+ <code class="function">lwres_gnbaresponse_parse()</code>
+ will return
+ <span class="errorcode">LWRES_R_UNEXPECTEDEND</span>
+ if the buffer is not empty after decoding the received packet.
+ These functions will return
+ <span class="errorcode">LWRES_R_FAILURE</span>
+ if
+ <em class="structfield"><code>pktflags</code></em>
+ in the packet header structure
+ <span class="type">lwres_lwpacket_t</span>
+ indicate that the packet is not a response to an earlier query.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543731"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">lwres_packet</span>(3)</span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_hstrerror.3 b/lib/lwres/man/lwres_hstrerror.3
new file mode 100644
index 0000000..5998238
--- /dev/null
+++ b/lib/lwres/man/lwres_hstrerror.3
@@ -0,0 +1,99 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_hstrerror.3,v 1.27 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_hstrerror
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_HSTRERROR" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_herror, lwres_hstrerror \- lightweight resolver error message generation
+.SH "SYNOPSIS"
+.nf
+#include <lwres/netdb.h>
+.fi
+.HP 18
+.BI "void lwres_herror(const\ char\ *" "s" ");"
+.HP 29
+.BI "const char * lwres_hstrerror(int\ " "err" ");"
+.SH "DESCRIPTION"
+.PP
+\fBlwres_herror()\fR
+prints the string
+\fIs\fR
+on
+\fBstderr\fR
+followed by the string generated by
+\fBlwres_hstrerror()\fR
+for the error code stored in the global variable
+\fBlwres_h_errno\fR.
+.PP
+\fBlwres_hstrerror()\fR
+returns an appropriate string for the error code gievn by
+\fIerr\fR. The values of the error codes and messages are as follows:
+.PP
+\fBNETDB_SUCCESS\fR
+.RS 4
+Resolver Error 0 (no error)
+.RE
+.PP
+\fBHOST_NOT_FOUND\fR
+.RS 4
+Unknown host
+.RE
+.PP
+\fBTRY_AGAIN\fR
+.RS 4
+Host name lookup failure
+.RE
+.PP
+\fBNO_RECOVERY\fR
+.RS 4
+Unknown server error
+.RE
+.PP
+\fBNO_DATA\fR
+.RS 4
+No address associated with name
+.RE
+.SH "RETURN VALUES"
+.PP
+The string
+Unknown resolver error
+is returned by
+\fBlwres_hstrerror()\fR
+when the value of
+\fBlwres_h_errno\fR
+is not a valid error code.
+.SH "SEE ALSO"
+.PP
+\fBherror\fR(3),
+\fBlwres_hstrerror\fR(3).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_hstrerror.docbook b/lib/lwres/man/lwres_hstrerror.docbook
new file mode 100644
index 0000000..ca4589e
--- /dev/null
+++ b/lib/lwres/man/lwres_hstrerror.docbook
@@ -0,0 +1,152 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_hstrerror.docbook,v 1.11 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_hstrerror</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_herror</refname>
+ <refname>lwres_hstrerror</refname>
+ <refpurpose>lightweight resolver error message generation</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/netdb.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_herror</function></funcdef>
+ <paramdef>const char *<parameter>s</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+const char *
+<function>lwres_hstrerror</function></funcdef>
+ <paramdef>int <parameter>err</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para><function>lwres_herror()</function>
+ prints the string <parameter>s</parameter> on
+ <type>stderr</type> followed by the string generated by
+ <function>lwres_hstrerror()</function> for the error code stored
+ in the global variable <constant>lwres_h_errno</constant>.
+ </para>
+
+ <para><function>lwres_hstrerror()</function>
+ returns an appropriate string for the error code gievn by
+ <parameter>err</parameter>. The values of the error codes and
+ messages are as follows:
+
+ <variablelist>
+ <varlistentry>
+ <term><errorcode>NETDB_SUCCESS</errorcode></term>
+ <listitem>
+ <para><errorname>Resolver Error 0 (no error)</errorname>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>HOST_NOT_FOUND</errorcode></term>
+ <listitem>
+ <para><errorname>Unknown host</errorname>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>TRY_AGAIN</errorcode></term>
+ <listitem>
+ <para><errorname>Host name lookup failure</errorname>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>NO_RECOVERY</errorcode></term>
+ <listitem>
+ <para><errorname>Unknown server error</errorname>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><errorcode>NO_DATA</errorcode></term>
+ <listitem>
+ <para><errorname>No address associated with name</errorname>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para>
+ The string <errorname>Unknown resolver error</errorname> is returned by
+ <function>lwres_hstrerror()</function>
+ when the value of
+ <constant>lwres_h_errno</constant>
+ is not a valid error code.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>herror</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_hstrerror</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ </para>
+
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_hstrerror.html b/lib/lwres/man/lwres_hstrerror.html
new file mode 100644
index 0000000..ef67d48
--- /dev/null
+++ b/lib/lwres/man/lwres_hstrerror.html
@@ -0,0 +1,104 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_hstrerror.html,v 1.23 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_hstrerror</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_herror, lwres_hstrerror &#8212; lightweight resolver error message generation</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/netdb.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em"><tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_herror</b>(</code></td>
+<td>const char * </td>
+<td>
+<var class="pdparam">s</var><code>)</code>;</td>
+</tr></table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0"><tr>
+<td><code class="funcdef">
+const char *
+<b class="fsfunc">lwres_hstrerror</b>(</code></td>
+<td>int  </td>
+<td>
+<var class="pdparam">err</var><code>)</code>;</td>
+</tr></table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543379"></a><h2>DESCRIPTION</h2>
+<p><code class="function">lwres_herror()</code>
+ prints the string <em class="parameter"><code>s</code></em> on
+ <span class="type">stderr</span> followed by the string generated by
+ <code class="function">lwres_hstrerror()</code> for the error code stored
+ in the global variable <code class="constant">lwres_h_errno</code>.
+ </p>
+<p><code class="function">lwres_hstrerror()</code>
+ returns an appropriate string for the error code gievn by
+ <em class="parameter"><code>err</code></em>. The values of the error codes and
+ messages are as follows:
+
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span class="errorcode">NETDB_SUCCESS</span></span></dt>
+<dd><p><span class="errorname">Resolver Error 0 (no error)</span>
+ </p></dd>
+<dt><span class="term"><span class="errorcode">HOST_NOT_FOUND</span></span></dt>
+<dd><p><span class="errorname">Unknown host</span>
+ </p></dd>
+<dt><span class="term"><span class="errorcode">TRY_AGAIN</span></span></dt>
+<dd><p><span class="errorname">Host name lookup failure</span>
+ </p></dd>
+<dt><span class="term"><span class="errorcode">NO_RECOVERY</span></span></dt>
+<dd><p><span class="errorname">Unknown server error</span>
+ </p></dd>
+<dt><span class="term"><span class="errorcode">NO_DATA</span></span></dt>
+<dd><p><span class="errorname">No address associated with name</span>
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543497"></a><h2>RETURN VALUES</h2>
+<p>
+ The string <span class="errorname">Unknown resolver error</span> is returned by
+ <code class="function">lwres_hstrerror()</code>
+ when the value of
+ <code class="constant">lwres_h_errno</code>
+ is not a valid error code.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543517"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">herror</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_hstrerror</span>(3)</span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_inetntop.3 b/lib/lwres/man/lwres_inetntop.3
new file mode 100644
index 0000000..c7d3d12
--- /dev/null
+++ b/lib/lwres/man/lwres_inetntop.3
@@ -0,0 +1,77 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_inetntop.3,v 1.26 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_inetntop
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_INETNTOP" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_net_ntop \- lightweight resolver IP address presentation
+.SH "SYNOPSIS"
+.nf
+#include <lwres/net.h>
+.fi
+.HP 28
+.BI "const char * lwres_net_ntop(int\ " "af" ", const\ void\ *" "src" ", char\ *" "dst" ", size_t\ " "size" ");"
+.SH "DESCRIPTION"
+.PP
+\fBlwres_net_ntop()\fR
+converts an IP address of protocol family
+\fIaf\fR
+\(em IPv4 or IPv6 \(em at location
+\fIsrc\fR
+from network format to its conventional representation as a string. For IPv4 addresses, that string would be a dotted\-decimal. An IPv6 address would be represented in colon notation as described in RFC1884.
+.PP
+The generated string is copied to
+\fIdst\fR
+provided
+\fIsize\fR
+indicates it is long enough to store the ASCII representation of the address.
+.SH "RETURN VALUES"
+.PP
+If successful, the function returns
+\fIdst\fR: a pointer to a string containing the presentation format of the address.
+\fBlwres_net_ntop()\fR
+returns
+\fBNULL\fR
+and sets the global variable
+\fBerrno\fR
+to
+\fBEAFNOSUPPORT\fR
+if the protocol family given in
+\fIaf\fR
+is not supported.
+.SH "SEE ALSO"
+.PP
+\fBRFC1884\fR(),
+\fBinet_ntop\fR(3),
+\fBerrno\fR(3).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_inetntop.docbook b/lib/lwres/man/lwres_inetntop.docbook
new file mode 100644
index 0000000..26f1779
--- /dev/null
+++ b/lib/lwres/man/lwres_inetntop.docbook
@@ -0,0 +1,120 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_inetntop.docbook,v 1.10 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_inetntop</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_net_ntop</refname>
+ <refpurpose>lightweight resolver IP address presentation</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/net.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+const char *
+<function>lwres_net_ntop</function></funcdef>
+ <paramdef>int <parameter>af</parameter></paramdef>
+ <paramdef>const void *<parameter>src</parameter></paramdef>
+ <paramdef>char *<parameter>dst</parameter></paramdef>
+ <paramdef>size_t <parameter>size</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para><function>lwres_net_ntop()</function>
+ converts an IP address of protocol family
+ <parameter>af</parameter> &mdash; IPv4 or IPv6 &mdash; at
+ location <parameter>src</parameter> from network format to its
+ conventional representation as a string. For IPv4 addresses,
+ that string would be a dotted-decimal. An IPv6 address would be
+ represented in colon notation as described in RFC1884.
+ </para>
+
+ <para>
+ The generated string is copied to <parameter>dst</parameter>
+ provided
+ <parameter>size</parameter> indicates it is long enough to
+ store the
+ ASCII representation of the address.
+ </para>
+
+ </refsect1>
+ <refsect1>
+ <title>RETURN VALUES</title>
+
+ <para>
+ If successful, the function returns <parameter>dst</parameter>:
+ a pointer to a string containing the presentation format of the
+ address. <function>lwres_net_ntop()</function> returns
+ <type>NULL</type> and sets the global variable
+ <constant>errno</constant> to <errorcode>EAFNOSUPPORT</errorcode> if
+ the protocol family given in <parameter>af</parameter> is
+ not
+ supported.
+ </para>
+
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>RFC1884</refentrytitle>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>inet_ntop</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_inetntop.html b/lib/lwres/man/lwres_inetntop.html
new file mode 100644
index 0000000..1a91110
--- /dev/null
+++ b/lib/lwres/man/lwres_inetntop.html
@@ -0,0 +1,103 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_inetntop.html,v 1.23 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_inetntop</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_net_ntop &#8212; lightweight resolver IP address presentation</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/net.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0">
+<tr>
+<td><code class="funcdef">
+const char *
+<b class="fsfunc">lwres_net_ntop</b>(</code></td>
+<td>int  </td>
+<td>
+<var class="pdparam">af</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>const void * </td>
+<td>
+<var class="pdparam">src</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>char * </td>
+<td>
+<var class="pdparam">dst</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>size_t  </td>
+<td>
+<var class="pdparam">size</var><code>)</code>;</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543379"></a><h2>DESCRIPTION</h2>
+<p><code class="function">lwres_net_ntop()</code>
+ converts an IP address of protocol family
+ <em class="parameter"><code>af</code></em> &#8212; IPv4 or IPv6 &#8212; at
+ location <em class="parameter"><code>src</code></em> from network format to its
+ conventional representation as a string. For IPv4 addresses,
+ that string would be a dotted-decimal. An IPv6 address would be
+ represented in colon notation as described in RFC1884.
+ </p>
+<p>
+ The generated string is copied to <em class="parameter"><code>dst</code></em>
+ provided
+ <em class="parameter"><code>size</code></em> indicates it is long enough to
+ store the
+ ASCII representation of the address.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543411"></a><h2>RETURN VALUES</h2>
+<p>
+ If successful, the function returns <em class="parameter"><code>dst</code></em>:
+ a pointer to a string containing the presentation format of the
+ address. <code class="function">lwres_net_ntop()</code> returns
+ <span class="type">NULL</span> and sets the global variable
+ <code class="constant">errno</code> to <span class="errorcode">EAFNOSUPPORT</span> if
+ the protocol family given in <em class="parameter"><code>af</code></em> is
+ not
+ supported.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543444"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">RFC1884</span></span>,
+ <span class="citerefentry"><span class="refentrytitle">inet_ntop</span>(3)</span>,
+ <span class="citerefentry"><span class="refentrytitle">errno</span>(3)</span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_noop.3 b/lib/lwres/man/lwres_noop.3
new file mode 100644
index 0000000..0e4ed71
--- /dev/null
+++ b/lib/lwres/man/lwres_noop.3
@@ -0,0 +1,183 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_noop.3,v 1.28 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_noop
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_NOOP" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "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
+.SH "SYNOPSIS"
+.nf
+#include <lwres/lwres.h>
+.fi
+.HP 40
+.BI "lwres_result_t lwres_nooprequest_render(lwres_context_t\ *" "ctx" ", lwres_nooprequest_t\ *" "req" ", lwres_lwpacket_t\ *" "pkt" ", lwres_buffer_t\ *" "b" ");"
+.HP 41
+.BI "lwres_result_t lwres_noopresponse_render(lwres_context_t\ *" "ctx" ", lwres_noopresponse_t\ *" "req" ", lwres_lwpacket_t\ *" "pkt" ", lwres_buffer_t\ *" "b" ");"
+.HP 39
+.BI "lwres_result_t lwres_nooprequest_parse(lwres_context_t\ *" "ctx" ", lwres_buffer_t\ *" "b" ", lwres_lwpacket_t\ *" "pkt" ", lwres_nooprequest_t\ **" "structp" ");"
+.HP 40
+.BI "lwres_result_t lwres_noopresponse_parse(lwres_context_t\ *" "ctx" ", lwres_buffer_t\ *" "b" ", lwres_lwpacket_t\ *" "pkt" ", lwres_noopresponse_t\ **" "structp" ");"
+.HP 29
+.BI "void lwres_noopresponse_free(lwres_context_t\ *" "ctx" ", lwres_noopresponse_t\ **" "structp" ");"
+.HP 28
+.BI "void lwres_nooprequest_free(lwres_context_t\ *" "ctx" ", lwres_nooprequest_t\ **" "structp" ");"
+.SH "DESCRIPTION"
+.PP
+These are low\-level routines for creating and parsing lightweight resolver no\-op request and response messages.
+.PP
+The no\-op message is analogous to a
+\fBping\fR
+packet: a packet is sent to the resolver daemon and is simply echoed back. The opcode is intended to allow a client to determine if the server is operational or not.
+.PP
+There are four main functions for the no\-op opcode. One render function converts a no\-op request structure \(em
+\fBlwres_nooprequest_t\fR
+\(em to the lighweight resolver's canonical format. It is complemented by a parse function that converts a packet in this canonical format to a no\-op request structure. Another render function converts the no\-op response structure \(em
+\fBlwres_noopresponse_t\fR
+to the canonical format. This is complemented by a parse function which converts a packet in canonical format to a no\-op response structure.
+.PP
+These structures are defined in
+\fIlwres/lwres.h\fR. They are shown below.
+.PP
+.RS 4
+.nf
+#define LWRES_OPCODE_NOOP 0x00000000U
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+typedef struct {
+ lwres_uint16_t datalength;
+ unsigned char *data;
+} lwres_nooprequest_t;
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+typedef struct {
+ lwres_uint16_t datalength;
+ unsigned char *data;
+} lwres_noopresponse_t;
+.fi
+.RE
+.sp
+.PP
+Although the structures have different types, they are identical. This is because the no\-op opcode simply echos whatever data was sent: the response is therefore identical to the request.
+.PP
+\fBlwres_nooprequest_render()\fR
+uses resolver context
+\fIctx\fR
+to convert no\-op request structure
+\fIreq\fR
+to canonical format. The packet header structure
+\fIpkt\fR
+is initialised and transferred to buffer
+\fIb\fR. The contents of
+\fI*req\fR
+are then appended to the buffer in canonical format.
+\fBlwres_noopresponse_render()\fR
+performs the same task, except it converts a no\-op response structure
+\fBlwres_noopresponse_t\fR
+to the lightweight resolver's canonical format.
+.PP
+\fBlwres_nooprequest_parse()\fR
+uses context
+\fIctx\fR
+to convert the contents of packet
+\fIpkt\fR
+to a
+\fBlwres_nooprequest_t\fR
+structure. Buffer
+\fIb\fR
+provides space to be used for storing this structure. When the function succeeds, the resulting
+\fBlwres_nooprequest_t\fR
+is made available through
+\fI*structp\fR.
+\fBlwres_noopresponse_parse()\fR
+offers the same semantics as
+\fBlwres_nooprequest_parse()\fR
+except it yields a
+\fBlwres_noopresponse_t\fR
+structure.
+.PP
+\fBlwres_noopresponse_free()\fR
+and
+\fBlwres_nooprequest_free()\fR
+release the memory in resolver context
+\fIctx\fR
+that was allocated to the
+\fBlwres_noopresponse_t\fR
+or
+\fBlwres_nooprequest_t\fR
+structures referenced via
+\fIstructp\fR.
+.SH "RETURN VALUES"
+.PP
+The no\-op opcode functions
+\fBlwres_nooprequest_render()\fR,
+\fBlwres_noopresponse_render()\fR
+\fBlwres_nooprequest_parse()\fR
+and
+\fBlwres_noopresponse_parse()\fR
+all return
+\fBLWRES_R_SUCCESS\fR
+on success. They return
+\fBLWRES_R_NOMEMORY\fR
+if memory allocation fails.
+\fBLWRES_R_UNEXPECTEDEND\fR
+is returned if the available space in the buffer
+\fIb\fR
+is too small to accommodate the packet header or the
+\fBlwres_nooprequest_t\fR
+and
+\fBlwres_noopresponse_t\fR
+structures.
+\fBlwres_nooprequest_parse()\fR
+and
+\fBlwres_noopresponse_parse()\fR
+will return
+\fBLWRES_R_UNEXPECTEDEND\fR
+if the buffer is not empty after decoding the received packet. These functions will return
+\fBLWRES_R_FAILURE\fR
+if
+\fBpktflags\fR
+in the packet header structure
+\fBlwres_lwpacket_t\fR
+indicate that the packet is not a response to an earlier query.
+.SH "SEE ALSO"
+.PP
+\fBlwres_packet\fR(3)
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_noop.docbook b/lib/lwres/man/lwres_noop.docbook
new file mode 100644
index 0000000..eb823b7
--- /dev/null
+++ b/lib/lwres/man/lwres_noop.docbook
@@ -0,0 +1,255 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_noop.docbook,v 1.11 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_noop</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_nooprequest_render</refname>
+ <refname>lwres_noopresponse_render</refname>
+ <refname>lwres_nooprequest_parse</refname>
+ <refname>lwres_noopresponse_parse</refname>
+ <refname>lwres_noopresponse_free</refname>
+ <refname>lwres_nooprequest_free</refname>
+ <refpurpose>lightweight resolver no-op message handling</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>
+#include &lt;lwres/lwres.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_nooprequest_render</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_nooprequest_t *<parameter>req</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_noopresponse_render</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_noopresponse_t *<parameter>req</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_nooprequest_parse</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_nooprequest_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_noopresponse_parse</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ <paramdef>lwres_noopresponse_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_noopresponse_free</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_noopresponse_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+void
+<function>lwres_nooprequest_free</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_nooprequest_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ These are low-level routines for creating and parsing
+ lightweight resolver no-op request and response messages.
+ </para>
+ <para>
+ The no-op message is analogous to a <command>ping</command>
+ packet:
+ a packet is sent to the resolver daemon and is simply echoed back.
+ The opcode is intended to allow a client to determine if the server is
+ operational or not.
+ </para>
+ <para>
+ There are four main functions for the no-op opcode.
+ One render function converts a no-op request structure &mdash;
+ <type>lwres_nooprequest_t</type> &mdash;
+ to the lighweight resolver's canonical format.
+ It is complemented by a parse function that converts a packet in this
+ canonical format to a no-op request structure.
+ Another render function converts the no-op response structure &mdash;
+ <type>lwres_noopresponse_t</type>
+ to the canonical format.
+ This is complemented by a parse function which converts a packet in
+ canonical format to a no-op response structure.
+ </para>
+ <para>
+ These structures are defined in
+ <filename>lwres/lwres.h</filename>.
+
+ They are shown below.
+ </para>
+ <para><programlisting>
+#define LWRES_OPCODE_NOOP 0x00000000U
+</programlisting>
+ </para>
+ <para><programlisting>
+typedef struct {
+ lwres_uint16_t datalength;
+ unsigned char *data;
+} lwres_nooprequest_t;
+</programlisting>
+ </para>
+ <para><programlisting>
+typedef struct {
+ lwres_uint16_t datalength;
+ unsigned char *data;
+} lwres_noopresponse_t;
+</programlisting>
+ </para>
+ <para>
+ Although the structures have different types, they are identical.
+ This is because the no-op opcode simply echos whatever data was sent:
+ the response is therefore identical to the request.
+ </para>
+
+ <para><function>lwres_nooprequest_render()</function>
+ uses resolver context <parameter>ctx</parameter> to convert
+ no-op request structure <parameter>req</parameter> to canonical
+ format. The packet header structure <parameter>pkt</parameter>
+ is initialised and transferred to buffer
+ <parameter>b</parameter>. The contents of
+ <parameter>*req</parameter> are then appended to the buffer in
+ canonical format.
+ <function>lwres_noopresponse_render()</function> performs the
+ same task, except it converts a no-op response structure
+ <type>lwres_noopresponse_t</type> to the lightweight resolver's
+ canonical format.
+ </para>
+
+ <para><function>lwres_nooprequest_parse()</function>
+ uses context <parameter>ctx</parameter> to convert the contents
+ of packet <parameter>pkt</parameter> to a
+ <type>lwres_nooprequest_t</type> structure. Buffer
+ <parameter>b</parameter> provides space to be used for storing
+ this structure. When the function succeeds, the resulting
+ <type>lwres_nooprequest_t</type> is made available through
+ <parameter>*structp</parameter>.
+ <function>lwres_noopresponse_parse()</function> offers the same
+ semantics as <function>lwres_nooprequest_parse()</function>
+ except it yields a <type>lwres_noopresponse_t</type> structure.
+ </para>
+
+ <para><function>lwres_noopresponse_free()</function>
+ and <function>lwres_nooprequest_free()</function> release the
+ memory in resolver context <parameter>ctx</parameter> that was
+ allocated to the <type>lwres_noopresponse_t</type> or
+ <type>lwres_nooprequest_t</type> structures referenced via
+ <parameter>structp</parameter>.
+ </para>
+
+ </refsect1>
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para>
+ The no-op opcode functions
+ <function>lwres_nooprequest_render()</function>,
+
+ <function>lwres_noopresponse_render()</function>
+ <function>lwres_nooprequest_parse()</function>
+ and
+ <function>lwres_noopresponse_parse()</function>
+ all return
+ <errorcode>LWRES_R_SUCCESS</errorcode>
+ on success.
+ They return
+ <errorcode>LWRES_R_NOMEMORY</errorcode>
+ if memory allocation fails.
+ <errorcode>LWRES_R_UNEXPECTEDEND</errorcode>
+ is returned if the available space in the buffer
+ <parameter>b</parameter>
+ is too small to accommodate the packet header or the
+ <type>lwres_nooprequest_t</type>
+ and
+ <type>lwres_noopresponse_t</type>
+ structures.
+ <function>lwres_nooprequest_parse()</function>
+ and
+ <function>lwres_noopresponse_parse()</function>
+ will return
+ <errorcode>LWRES_R_UNEXPECTEDEND</errorcode>
+ if the buffer is not empty after decoding the received packet.
+ These functions will return
+ <errorcode>LWRES_R_FAILURE</errorcode>
+ if
+ <constant>pktflags</constant>
+ in the packet header structure
+ <type>lwres_lwpacket_t</type>
+ indicate that the packet is not a response to an earlier query.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>lwres_packet</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_noop.html b/lib/lwres/man/lwres_noop.html
new file mode 100644
index 0000000..aab581a
--- /dev/null
+++ b/lib/lwres/man/lwres_noop.html
@@ -0,0 +1,317 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_noop.html,v 1.25 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_noop</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_nooprequest_render, lwres_noopresponse_render, lwres_nooprequest_parse, lwres_noopresponse_parse, lwres_noopresponse_free, lwres_nooprequest_free &#8212; lightweight resolver no-op message handling</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">
+#include &lt;lwres/lwres.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_nooprequest_render</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_nooprequest_t * </td>
+<td>
+<var class="pdparam">req</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_noopresponse_render</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_noopresponse_t * </td>
+<td>
+<var class="pdparam">req</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_nooprequest_parse</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_nooprequest_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_noopresponse_parse</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_noopresponse_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_noopresponse_free</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_noopresponse_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0">
+<tr>
+<td><code class="funcdef">
+void
+<b class="fsfunc">lwres_nooprequest_free</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_nooprequest_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543522"></a><h2>DESCRIPTION</h2>
+<p>
+ These are low-level routines for creating and parsing
+ lightweight resolver no-op request and response messages.
+ </p>
+<p>
+ The no-op message is analogous to a <span><strong class="command">ping</strong></span>
+ packet:
+ a packet is sent to the resolver daemon and is simply echoed back.
+ The opcode is intended to allow a client to determine if the server is
+ operational or not.
+ </p>
+<p>
+ There are four main functions for the no-op opcode.
+ One render function converts a no-op request structure &#8212;
+ <span class="type">lwres_nooprequest_t</span> &#8212;
+ to the lighweight resolver's canonical format.
+ It is complemented by a parse function that converts a packet in this
+ canonical format to a no-op request structure.
+ Another render function converts the no-op response structure &#8212;
+ <span class="type">lwres_noopresponse_t</span>
+ to the canonical format.
+ This is complemented by a parse function which converts a packet in
+ canonical format to a no-op response structure.
+ </p>
+<p>
+ These structures are defined in
+ <code class="filename">lwres/lwres.h</code>.
+
+ They are shown below.
+ </p>
+<pre class="programlisting">
+#define LWRES_OPCODE_NOOP 0x00000000U
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+typedef struct {
+ lwres_uint16_t datalength;
+ unsigned char *data;
+} lwres_nooprequest_t;
+</pre>
+<p>
+ </p>
+<pre class="programlisting">
+typedef struct {
+ lwres_uint16_t datalength;
+ unsigned char *data;
+} lwres_noopresponse_t;
+</pre>
+<p>
+ </p>
+<p>
+ Although the structures have different types, they are identical.
+ This is because the no-op opcode simply echos whatever data was sent:
+ the response is therefore identical to the request.
+ </p>
+<p><code class="function">lwres_nooprequest_render()</code>
+ uses resolver context <em class="parameter"><code>ctx</code></em> to convert
+ no-op request structure <em class="parameter"><code>req</code></em> to canonical
+ format. The packet header structure <em class="parameter"><code>pkt</code></em>
+ is initialised and transferred to buffer
+ <em class="parameter"><code>b</code></em>. The contents of
+ <em class="parameter"><code>*req</code></em> are then appended to the buffer in
+ canonical format.
+ <code class="function">lwres_noopresponse_render()</code> performs the
+ same task, except it converts a no-op response structure
+ <span class="type">lwres_noopresponse_t</span> to the lightweight resolver's
+ canonical format.
+ </p>
+<p><code class="function">lwres_nooprequest_parse()</code>
+ uses context <em class="parameter"><code>ctx</code></em> to convert the contents
+ of packet <em class="parameter"><code>pkt</code></em> to a
+ <span class="type">lwres_nooprequest_t</span> structure. Buffer
+ <em class="parameter"><code>b</code></em> provides space to be used for storing
+ this structure. When the function succeeds, the resulting
+ <span class="type">lwres_nooprequest_t</span> is made available through
+ <em class="parameter"><code>*structp</code></em>.
+ <code class="function">lwres_noopresponse_parse()</code> offers the same
+ semantics as <code class="function">lwres_nooprequest_parse()</code>
+ except it yields a <span class="type">lwres_noopresponse_t</span> structure.
+ </p>
+<p><code class="function">lwres_noopresponse_free()</code>
+ and <code class="function">lwres_nooprequest_free()</code> release the
+ memory in resolver context <em class="parameter"><code>ctx</code></em> that was
+ allocated to the <span class="type">lwres_noopresponse_t</span> or
+ <span class="type">lwres_nooprequest_t</span> structures referenced via
+ <em class="parameter"><code>structp</code></em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543672"></a><h2>RETURN VALUES</h2>
+<p>
+ The no-op opcode functions
+ <code class="function">lwres_nooprequest_render()</code>,
+
+ <code class="function">lwres_noopresponse_render()</code>
+ <code class="function">lwres_nooprequest_parse()</code>
+ and
+ <code class="function">lwres_noopresponse_parse()</code>
+ all return
+ <span class="errorcode">LWRES_R_SUCCESS</span>
+ on success.
+ They return
+ <span class="errorcode">LWRES_R_NOMEMORY</span>
+ if memory allocation fails.
+ <span class="errorcode">LWRES_R_UNEXPECTEDEND</span>
+ is returned if the available space in the buffer
+ <em class="parameter"><code>b</code></em>
+ is too small to accommodate the packet header or the
+ <span class="type">lwres_nooprequest_t</span>
+ and
+ <span class="type">lwres_noopresponse_t</span>
+ structures.
+ <code class="function">lwres_nooprequest_parse()</code>
+ and
+ <code class="function">lwres_noopresponse_parse()</code>
+ will return
+ <span class="errorcode">LWRES_R_UNEXPECTEDEND</span>
+ if the buffer is not empty after decoding the received packet.
+ These functions will return
+ <span class="errorcode">LWRES_R_FAILURE</span>
+ if
+ <code class="constant">pktflags</code>
+ in the packet header structure
+ <span class="type">lwres_lwpacket_t</span>
+ indicate that the packet is not a response to an earlier query.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543738"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">lwres_packet</span>(3)</span>
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_packet.3 b/lib/lwres/man/lwres_packet.3
new file mode 100644
index 0000000..1e1f98f
--- /dev/null
+++ b/lib/lwres/man/lwres_packet.3
@@ -0,0 +1,170 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_packet.3,v 1.29 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_packet
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_PACKET" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_lwpacket_renderheader, lwres_lwpacket_parseheader \- lightweight resolver packet handling functions
+.SH "SYNOPSIS"
+.nf
+#include <lwres/lwpacket.h>
+.fi
+.HP 43
+.BI "lwres_result_t lwres_lwpacket_renderheader(lwres_buffer_t\ *" "b" ", lwres_lwpacket_t\ *" "pkt" ");"
+.HP 42
+.BI "lwres_result_t lwres_lwpacket_parseheader(lwres_buffer_t\ *" "b" ", lwres_lwpacket_t\ *" "pkt" ");"
+.SH "DESCRIPTION"
+.PP
+These functions rely on a
+\fBstruct lwres_lwpacket\fR
+which is defined in
+\fIlwres/lwpacket.h\fR.
+.PP
+.RS 4
+.nf
+typedef struct lwres_lwpacket lwres_lwpacket_t;
+.fi
+.RE
+.sp
+.PP
+.RS 4
+.nf
+struct lwres_lwpacket {
+ lwres_uint32_t length;
+ lwres_uint16_t version;
+ lwres_uint16_t pktflags;
+ lwres_uint32_t serial;
+ lwres_uint32_t opcode;
+ lwres_uint32_t result;
+ lwres_uint32_t recvlength;
+ lwres_uint16_t authtype;
+ lwres_uint16_t authlength;
+};
+.fi
+.RE
+.sp
+.PP
+The elements of this structure are:
+.PP
+\fBlength\fR
+.RS 4
+the overall packet length, including the entire packet header. This field is filled in by the lwres_gabn_*() and lwres_gnba_*() calls.
+.RE
+.PP
+\fBversion\fR
+.RS 4
+the header format. There is currently only one format,
+\fBLWRES_LWPACKETVERSION_0\fR. This field is filled in by the lwres_gabn_*() and lwres_gnba_*() calls.
+.RE
+.PP
+\fBpktflags\fR
+.RS 4
+library\-defined flags for this packet: for instance whether the packet is a request or a reply. Flag values can be set, but not defined by the caller. This field is filled in by the application wit the exception of the LWRES_LWPACKETFLAG_RESPONSE bit, which is set by the library in the lwres_gabn_*() and lwres_gnba_*() calls.
+.RE
+.PP
+\fBserial\fR
+.RS 4
+is set by the requestor and is returned in all replies. If two or more packets from the same source have the same serial number and are from the same source, they are assumed to be duplicates and the latter ones may be dropped. This field must be set by the application.
+.RE
+.PP
+\fBopcode\fR
+.RS 4
+indicates the operation. Opcodes between 0x00000000 and 0x03ffffff are reserved for use by the lightweight resolver library. Opcodes between 0x04000000 and 0xffffffff are application defined. This field is filled in by the lwres_gabn_*() and lwres_gnba_*() calls.
+.RE
+.PP
+\fBresult\fR
+.RS 4
+is only valid for replies. Results between 0x04000000 and 0xffffffff are application defined. Results between 0x00000000 and 0x03ffffff are reserved for library use. This field is filled in by the lwres_gabn_*() and lwres_gnba_*() calls.
+.RE
+.PP
+\fBrecvlength\fR
+.RS 4
+is the maximum buffer size that the receiver can handle on requests and the size of the buffer needed to satisfy a request when the buffer is too large for replies. This field is supplied by the application.
+.RE
+.PP
+\fBauthtype\fR
+.RS 4
+defines the packet level authentication that is used. Authorisation types between 0x1000 and 0xffff are application defined and types between 0x0000 and 0x0fff are reserved for library use. Currently these are not used and must be zero.
+.RE
+.PP
+\fBauthlen\fR
+.RS 4
+gives the length of the authentication data. Since packet authentication is currently not used, this must be zero.
+.RE
+.PP
+The following opcodes are currently defined:
+.PP
+\fBNOOP\fR
+.RS 4
+Success is always returned and the packet contents are echoed. The lwres_noop_*() functions should be used for this type.
+.RE
+.PP
+\fBGETADDRSBYNAME\fR
+.RS 4
+returns all known addresses for a given name. The lwres_gabn_*() functions should be used for this type.
+.RE
+.PP
+\fBGETNAMEBYADDR\fR
+.RS 4
+return the hostname for the given address. The lwres_gnba_*() functions should be used for this type.
+.RE
+.PP
+\fBlwres_lwpacket_renderheader()\fR
+transfers the contents of lightweight resolver packet structure
+\fBlwres_lwpacket_t\fR
+\fI*pkt\fR
+in network byte order to the lightweight resolver buffer,
+\fI*b\fR.
+.PP
+\fBlwres_lwpacket_parseheader()\fR
+performs the converse operation. It transfers data in network byte order from buffer
+\fI*b\fR
+to resolver packet
+\fI*pkt\fR. The contents of the buffer
+\fIb\fR
+should correspond to a
+\fBlwres_lwpacket_t\fR.
+.SH "RETURN VALUES"
+.PP
+Successful calls to
+\fBlwres_lwpacket_renderheader()\fR
+and
+\fBlwres_lwpacket_parseheader()\fR
+return
+\fBLWRES_R_SUCCESS\fR. If there is insufficient space to copy data between the buffer
+\fI*b\fR
+and lightweight resolver packet
+\fI*pkt\fR
+both functions return
+\fBLWRES_R_UNEXPECTEDEND\fR.
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_packet.docbook b/lib/lwres/man/lwres_packet.docbook
new file mode 100644
index 0000000..87841db
--- /dev/null
+++ b/lib/lwres/man/lwres_packet.docbook
@@ -0,0 +1,291 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_packet.docbook,v 1.13 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_packet</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_lwpacket_renderheader</refname>
+ <refname>lwres_lwpacket_parseheader</refname>
+ <refpurpose>lightweight resolver packet handling functions</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/lwpacket.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_lwpacket_renderheader</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_lwpacket_parseheader</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_lwpacket_t *<parameter>pkt</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ These functions rely on a
+ <type>struct lwres_lwpacket</type>
+ which is defined in
+ <filename>lwres/lwpacket.h</filename>.
+ </para>
+
+ <para><programlisting>
+typedef struct lwres_lwpacket lwres_lwpacket_t;
+ </programlisting>
+ </para>
+ <para><programlisting>
+struct lwres_lwpacket {
+ lwres_uint32_t length;
+ lwres_uint16_t version;
+ lwres_uint16_t pktflags;
+ lwres_uint32_t serial;
+ lwres_uint32_t opcode;
+ lwres_uint32_t result;
+ lwres_uint32_t recvlength;
+ lwres_uint16_t authtype;
+ lwres_uint16_t authlength;
+};
+</programlisting>
+ </para>
+
+ <para>
+ The elements of this structure are:
+ <variablelist>
+ <varlistentry>
+ <term><constant>length</constant></term>
+ <listitem>
+ <para>
+ the overall packet length, including the entire packet header.
+ This field is filled in by the lwres_gabn_*() and lwres_gnba_*()
+ calls.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>version</constant></term>
+ <listitem>
+ <para>
+ the header format. There is currently only one format,
+ <type>LWRES_LWPACKETVERSION_0</type>.
+
+ This field is filled in by the lwres_gabn_*() and lwres_gnba_*()
+ calls.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>pktflags</constant></term>
+ <listitem>
+ <para>
+ library-defined flags for this packet: for instance whether the
+ packet
+ is a request or a reply. Flag values can be set, but not defined
+ by
+ the caller.
+ This field is filled in by the application wit the exception of
+ the
+ LWRES_LWPACKETFLAG_RESPONSE bit, which is set by the library in
+ the
+ lwres_gabn_*() and lwres_gnba_*() calls.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>serial</constant></term>
+ <listitem>
+ <para>
+ is set by the requestor and is returned in all replies. If two
+ or more
+ packets from the same source have the same serial number and are
+ from
+ the same source, they are assumed to be duplicates and the
+ latter ones
+ may be dropped.
+ This field must be set by the application.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>opcode</constant></term>
+ <listitem>
+ <para>
+ indicates the operation.
+ Opcodes between 0x00000000 and 0x03ffffff are
+ reserved for use by the lightweight resolver library. Opcodes
+ between
+ 0x04000000 and 0xffffffff are application defined.
+ This field is filled in by the lwres_gabn_*() and lwres_gnba_*()
+ calls.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>result</constant></term>
+ <listitem>
+ <para>
+ is only valid for replies.
+ Results between 0x04000000 and 0xffffffff are application
+ defined.
+ Results between 0x00000000 and 0x03ffffff are reserved for
+ library use.
+ This field is filled in by the lwres_gabn_*() and lwres_gnba_*()
+ calls.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>recvlength</constant></term>
+ <listitem>
+ <para>
+ is the maximum buffer size that the receiver can handle on
+ requests
+ and the size of the buffer needed to satisfy a request when the
+ buffer
+ is too large for replies.
+ This field is supplied by the application.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>authtype</constant></term>
+ <listitem>
+ <para>
+ defines the packet level authentication that is used.
+ Authorisation types between 0x1000 and 0xffff are application
+ defined
+ and types between 0x0000 and 0x0fff are reserved for library
+ use.
+ Currently these are not used and must be zero.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>authlen</constant></term>
+ <listitem>
+ <para>
+ gives the length of the authentication data.
+ Since packet authentication is currently not used, this must be
+ zero.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <para>
+ The following opcodes are currently defined:
+ <variablelist>
+ <varlistentry>
+ <term><constant>NOOP</constant></term>
+ <listitem>
+ <para>
+ Success is always returned and the packet contents are echoed.
+ The lwres_noop_*() functions should be used for this type.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>GETADDRSBYNAME</constant></term>
+ <listitem>
+ <para>
+ returns all known addresses for a given name.
+ The lwres_gabn_*() functions should be used for this type.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>GETNAMEBYADDR</constant></term>
+ <listitem>
+ <para>
+ return the hostname for the given address.
+ The lwres_gnba_*() functions should be used for this type.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para><function>lwres_lwpacket_renderheader()</function>
+ transfers the contents of lightweight resolver packet structure
+ <type>lwres_lwpacket_t</type> <parameter>*pkt</parameter> in
+ network byte order to the lightweight resolver buffer,
+ <parameter>*b</parameter>.
+ </para>
+
+ <para><function>lwres_lwpacket_parseheader()</function>
+ performs the converse operation. It transfers data in network
+ byte order from buffer <parameter>*b</parameter> to resolver
+ packet <parameter>*pkt</parameter>. The contents of the buffer
+ <parameter>b</parameter> should correspond to a
+ <type>lwres_lwpacket_t</type>.
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para>
+ Successful calls to
+ <function>lwres_lwpacket_renderheader()</function> and
+ <function>lwres_lwpacket_parseheader()</function> return
+ <errorcode>LWRES_R_SUCCESS</errorcode>. If there is insufficient
+ space to copy data between the buffer <parameter>*b</parameter> and
+ lightweight resolver packet <parameter>*pkt</parameter> both
+ functions
+ return <errorcode>LWRES_R_UNEXPECTEDEND</errorcode>.
+ </para>
+
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_packet.html b/lib/lwres/man/lwres_packet.html
new file mode 100644
index 0000000..b4cc1df
--- /dev/null
+++ b/lib/lwres/man/lwres_packet.html
@@ -0,0 +1,235 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_packet.html,v 1.26 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_packet</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_lwpacket_renderheader, lwres_lwpacket_parseheader &#8212; lightweight resolver packet handling functions</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/lwpacket.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_lwpacket_renderheader</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_lwpacket_parseheader</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_lwpacket_t * </td>
+<td>
+<var class="pdparam">pkt</var><code>)</code>;</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543389"></a><h2>DESCRIPTION</h2>
+<p>
+ These functions rely on a
+ <span class="type">struct lwres_lwpacket</span>
+ which is defined in
+ <code class="filename">lwres/lwpacket.h</code>.
+ </p>
+<pre class="programlisting">
+typedef struct lwres_lwpacket lwres_lwpacket_t;
+ </pre>
+<p>
+ </p>
+<pre class="programlisting">
+struct lwres_lwpacket {
+ lwres_uint32_t length;
+ lwres_uint16_t version;
+ lwres_uint16_t pktflags;
+ lwres_uint32_t serial;
+ lwres_uint32_t opcode;
+ lwres_uint32_t result;
+ lwres_uint32_t recvlength;
+ lwres_uint16_t authtype;
+ lwres_uint16_t authlength;
+};
+</pre>
+<p>
+ </p>
+<p>
+ The elements of this structure are:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">length</code></span></dt>
+<dd><p>
+ the overall packet length, including the entire packet header.
+ This field is filled in by the lwres_gabn_*() and lwres_gnba_*()
+ calls.
+ </p></dd>
+<dt><span class="term"><code class="constant">version</code></span></dt>
+<dd><p>
+ the header format. There is currently only one format,
+ <span class="type">LWRES_LWPACKETVERSION_0</span>.
+
+ This field is filled in by the lwres_gabn_*() and lwres_gnba_*()
+ calls.
+ </p></dd>
+<dt><span class="term"><code class="constant">pktflags</code></span></dt>
+<dd><p>
+ library-defined flags for this packet: for instance whether the
+ packet
+ is a request or a reply. Flag values can be set, but not defined
+ by
+ the caller.
+ This field is filled in by the application wit the exception of
+ the
+ LWRES_LWPACKETFLAG_RESPONSE bit, which is set by the library in
+ the
+ lwres_gabn_*() and lwres_gnba_*() calls.
+ </p></dd>
+<dt><span class="term"><code class="constant">serial</code></span></dt>
+<dd><p>
+ is set by the requestor and is returned in all replies. If two
+ or more
+ packets from the same source have the same serial number and are
+ from
+ the same source, they are assumed to be duplicates and the
+ latter ones
+ may be dropped.
+ This field must be set by the application.
+ </p></dd>
+<dt><span class="term"><code class="constant">opcode</code></span></dt>
+<dd><p>
+ indicates the operation.
+ Opcodes between 0x00000000 and 0x03ffffff are
+ reserved for use by the lightweight resolver library. Opcodes
+ between
+ 0x04000000 and 0xffffffff are application defined.
+ This field is filled in by the lwres_gabn_*() and lwres_gnba_*()
+ calls.
+ </p></dd>
+<dt><span class="term"><code class="constant">result</code></span></dt>
+<dd><p>
+ is only valid for replies.
+ Results between 0x04000000 and 0xffffffff are application
+ defined.
+ Results between 0x00000000 and 0x03ffffff are reserved for
+ library use.
+ This field is filled in by the lwres_gabn_*() and lwres_gnba_*()
+ calls.
+ </p></dd>
+<dt><span class="term"><code class="constant">recvlength</code></span></dt>
+<dd><p>
+ is the maximum buffer size that the receiver can handle on
+ requests
+ and the size of the buffer needed to satisfy a request when the
+ buffer
+ is too large for replies.
+ This field is supplied by the application.
+ </p></dd>
+<dt><span class="term"><code class="constant">authtype</code></span></dt>
+<dd><p>
+ defines the packet level authentication that is used.
+ Authorisation types between 0x1000 and 0xffff are application
+ defined
+ and types between 0x0000 and 0x0fff are reserved for library
+ use.
+ Currently these are not used and must be zero.
+ </p></dd>
+<dt><span class="term"><code class="constant">authlen</code></span></dt>
+<dd><p>
+ gives the length of the authentication data.
+ Since packet authentication is currently not used, this must be
+ zero.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+<p>
+ The following opcodes are currently defined:
+ </p>
+<div class="variablelist"><dl>
+<dt><span class="term"><code class="constant">NOOP</code></span></dt>
+<dd><p>
+ Success is always returned and the packet contents are echoed.
+ The lwres_noop_*() functions should be used for this type.
+ </p></dd>
+<dt><span class="term"><code class="constant">GETADDRSBYNAME</code></span></dt>
+<dd><p>
+ returns all known addresses for a given name.
+ The lwres_gabn_*() functions should be used for this type.
+ </p></dd>
+<dt><span class="term"><code class="constant">GETNAMEBYADDR</code></span></dt>
+<dd><p>
+ return the hostname for the given address.
+ The lwres_gnba_*() functions should be used for this type.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+<p><code class="function">lwres_lwpacket_renderheader()</code>
+ transfers the contents of lightweight resolver packet structure
+ <span class="type">lwres_lwpacket_t</span> <em class="parameter"><code>*pkt</code></em> in
+ network byte order to the lightweight resolver buffer,
+ <em class="parameter"><code>*b</code></em>.
+ </p>
+<p><code class="function">lwres_lwpacket_parseheader()</code>
+ performs the converse operation. It transfers data in network
+ byte order from buffer <em class="parameter"><code>*b</code></em> to resolver
+ packet <em class="parameter"><code>*pkt</code></em>. The contents of the buffer
+ <em class="parameter"><code>b</code></em> should correspond to a
+ <span class="type">lwres_lwpacket_t</span>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543706"></a><h2>RETURN VALUES</h2>
+<p>
+ Successful calls to
+ <code class="function">lwres_lwpacket_renderheader()</code> and
+ <code class="function">lwres_lwpacket_parseheader()</code> return
+ <span class="errorcode">LWRES_R_SUCCESS</span>. If there is insufficient
+ space to copy data between the buffer <em class="parameter"><code>*b</code></em> and
+ lightweight resolver packet <em class="parameter"><code>*pkt</code></em> both
+ functions
+ return <span class="errorcode">LWRES_R_UNEXPECTEDEND</span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/man/lwres_resutil.3 b/lib/lwres/man/lwres_resutil.3
new file mode 100644
index 0000000..d26f77c
--- /dev/null
+++ b/lib/lwres/man/lwres_resutil.3
@@ -0,0 +1,170 @@
+.\" Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_resutil.3,v 1.28 2007/01/30 00:24:59 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: lwres_resutil
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "LWRES_RESUTIL" "3" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+lwres_string_parse, lwres_addr_parse, lwres_getaddrsbyname, lwres_getnamebyaddr \- lightweight resolver utility functions
+.SH "SYNOPSIS"
+.nf
+#include <lwres/lwres.h>
+.fi
+.HP 34
+.BI "lwres_result_t lwres_string_parse(lwres_buffer_t\ *" "b" ", char\ **" "c" ", lwres_uint16_t\ *" "len" ");"
+.HP 32
+.BI "lwres_result_t lwres_addr_parse(lwres_buffer_t\ *" "b" ", lwres_addr_t\ *" "addr" ");"
+.HP 36
+.BI "lwres_result_t lwres_getaddrsbyname(lwres_context_t\ *" "ctx" ", const\ char\ *" "name" ", lwres_uint32_t\ " "addrtypes" ", lwres_gabnresponse_t\ **" "structp" ");"
+.HP 35
+.BI "lwres_result_t lwres_getnamebyaddr(lwres_context_t\ *" "ctx" ", lwres_uint32_t\ " "addrtype" ", lwres_uint16_t\ " "addrlen" ", const\ unsigned\ char\ *" "addr" ", lwres_gnbaresponse_t\ **" "structp" ");"
+.SH "DESCRIPTION"
+.PP
+\fBlwres_string_parse()\fR
+retrieves a DNS\-encoded string starting the current pointer of lightweight resolver buffer
+\fIb\fR: i.e.
+\fBb\->current\fR. When the function returns, the address of the first byte of the encoded string is returned via
+\fI*c\fR
+and the length of that string is given by
+\fI*len\fR. The buffer's current pointer is advanced to point at the character following the string length, the encoded string, and the trailing
+\fBNULL\fR
+character.
+.PP
+\fBlwres_addr_parse()\fR
+extracts an address from the buffer
+\fIb\fR. The buffer's current pointer
+\fBb\->current\fR
+is presumed to point at an encoded address: the address preceded by a 32\-bit protocol family identifier and a 16\-bit length field. The encoded address is copied to
+\fBaddr\->address\fR
+and
+\fBaddr\->length\fR
+indicates the size in bytes of the address that was copied.
+\fBb\->current\fR
+is advanced to point at the next byte of available data in the buffer following the encoded address.
+.PP
+\fBlwres_getaddrsbyname()\fR
+and
+\fBlwres_getnamebyaddr()\fR
+use the
+\fBlwres_gnbaresponse_t\fR
+structure defined below:
+.PP
+.RS 4
+.nf
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ lwres_uint16_t naddrs;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ lwres_addrlist_t addrs;
+ void *base;
+ size_t baselen;
+} lwres_gabnresponse_t;
+.fi
+.RE
+.PP
+The contents of this structure are not manipulated directly but they are controlled through the
+\fBlwres_gabn\fR(3)
+functions.
+.PP
+The lightweight resolver uses
+\fBlwres_getaddrsbyname()\fR
+to perform foward lookups. Hostname
+\fIname\fR
+is looked up using the resolver context
+\fIctx\fR
+for memory allocation.
+\fIaddrtypes\fR
+is a bitmask indicating which type of addresses are to be looked up. Current values for this bitmask are
+\fBLWRES_ADDRTYPE_V4\fR
+for IPv4 addresses and
+\fBLWRES_ADDRTYPE_V6\fR
+for IPv6 addresses. Results of the lookup are returned in
+\fI*structp\fR.
+.PP
+\fBlwres_getnamebyaddr()\fR
+performs reverse lookups. Resolver context
+\fIctx\fR
+is used for memory allocation. The address type is indicated by
+\fIaddrtype\fR:
+\fBLWRES_ADDRTYPE_V4\fR
+or
+\fBLWRES_ADDRTYPE_V6\fR. The address to be looked up is given by
+\fIaddr\fR
+and its length is
+\fIaddrlen\fR
+bytes. The result of the function call is made available through
+\fI*structp\fR.
+.SH "RETURN VALUES"
+.PP
+Successful calls to
+\fBlwres_string_parse()\fR
+and
+\fBlwres_addr_parse()\fR
+return
+\fBLWRES_R_SUCCESS.\fR
+Both functions return
+\fBLWRES_R_FAILURE\fR
+if the buffer is corrupt or
+\fBLWRES_R_UNEXPECTEDEND\fR
+if the buffer has less space than expected for the components of the encoded string or address.
+.PP
+\fBlwres_getaddrsbyname()\fR
+returns
+\fBLWRES_R_SUCCESS\fR
+on success and it returns
+\fBLWRES_R_NOTFOUND\fR
+if the hostname
+\fIname\fR
+could not be found.
+.PP
+\fBLWRES_R_SUCCESS\fR
+is returned by a successful call to
+\fBlwres_getnamebyaddr()\fR.
+.PP
+Both
+\fBlwres_getaddrsbyname()\fR
+and
+\fBlwres_getnamebyaddr()\fR
+return
+\fBLWRES_R_NOMEMORY\fR
+when memory allocation requests fail and
+\fBLWRES_R_UNEXPECTEDEND\fR
+if the buffers used for sending queries and receiving replies are too small.
+.SH "SEE ALSO"
+.PP
+\fBlwres_buffer\fR(3),
+\fBlwres_gabn\fR(3).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000, 2001 Internet Software Consortium.
+.br
diff --git a/lib/lwres/man/lwres_resutil.docbook b/lib/lwres/man/lwres_resutil.docbook
new file mode 100644
index 0000000..e6184d9
--- /dev/null
+++ b/lib/lwres/man/lwres_resutil.docbook
@@ -0,0 +1,238 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007 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: lwres_resutil.docbook,v 1.12 2007/06/18 23:47:51 tbox Exp $ -->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>lwres_resutil</refentrytitle>
+ <manvolnum>3</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refnamediv>
+ <refname>lwres_string_parse</refname>
+ <refname>lwres_addr_parse</refname>
+ <refname>lwres_getaddrsbyname</refname>
+ <refname>lwres_getnamebyaddr</refname>
+ <refpurpose>lightweight resolver utility functions</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <funcsynopsis>
+<funcsynopsisinfo>#include &lt;lwres/lwres.h&gt;</funcsynopsisinfo>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_string_parse</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>char **<parameter>c</parameter></paramdef>
+ <paramdef>lwres_uint16_t *<parameter>len</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_addr_parse</function></funcdef>
+ <paramdef>lwres_buffer_t *<parameter>b</parameter></paramdef>
+ <paramdef>lwres_addr_t *<parameter>addr</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_getaddrsbyname</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>const char *<parameter>name</parameter></paramdef>
+ <paramdef>lwres_uint32_t <parameter>addrtypes</parameter></paramdef>
+ <paramdef>lwres_gabnresponse_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+<funcprototype>
+ <funcdef>
+lwres_result_t
+<function>lwres_getnamebyaddr</function></funcdef>
+ <paramdef>lwres_context_t *<parameter>ctx</parameter></paramdef>
+ <paramdef>lwres_uint32_t <parameter>addrtype</parameter></paramdef>
+ <paramdef>lwres_uint16_t <parameter>addrlen</parameter></paramdef>
+ <paramdef>const unsigned char *<parameter>addr</parameter></paramdef>
+ <paramdef>lwres_gnbaresponse_t **<parameter>structp</parameter></paramdef>
+ </funcprototype>
+</funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <para><function>lwres_string_parse()</function>
+ retrieves a DNS-encoded string starting the current pointer of
+ lightweight resolver buffer <parameter>b</parameter>: i.e.
+ <constant>b-&gt;current</constant>. When the function returns,
+ the address of the first byte of the encoded string is returned
+ via <parameter>*c</parameter> and the length of that string is
+ given by <parameter>*len</parameter>. The buffer's current
+ pointer is advanced to point at the character following the
+ string length, the encoded string, and the trailing
+ <type>NULL</type> character.
+ </para>
+
+ <para><function>lwres_addr_parse()</function>
+ extracts an address from the buffer <parameter>b</parameter>.
+ The buffer's current pointer <constant>b-&gt;current</constant>
+ is presumed to point at an encoded address: the address preceded
+ by a 32-bit protocol family identifier and a 16-bit length
+ field. The encoded address is copied to
+ <constant>addr-&gt;address</constant> and
+ <constant>addr-&gt;length</constant> indicates the size in bytes
+ of the address that was copied.
+ <constant>b-&gt;current</constant> is advanced to point at the
+ next byte of available data in the buffer following the encoded
+ address.
+ </para>
+
+ <para><function>lwres_getaddrsbyname()</function>
+ and <function>lwres_getnamebyaddr()</function> use the
+ <type>lwres_gnbaresponse_t</type> structure defined below:
+ </para>
+
+<para><programlisting>
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ lwres_uint16_t naddrs;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ lwres_addrlist_t addrs;
+ void *base;
+ size_t baselen;
+} lwres_gabnresponse_t;
+</programlisting></para>
+
+ <para>
+ The contents of this structure are not manipulated directly but
+ they are controlled through the
+ <citerefentry>
+ <refentrytitle>lwres_gabn</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>
+ functions.
+ </para>
+
+ <para>
+ The lightweight resolver uses
+ <function>lwres_getaddrsbyname()</function> to perform
+ foward lookups.
+ Hostname <parameter>name</parameter> is looked up using the
+ resolver
+ context <parameter>ctx</parameter> for memory allocation.
+ <parameter>addrtypes</parameter> is a bitmask indicating
+ which type of
+ addresses are to be looked up. Current values for this bitmask are
+ <type>LWRES_ADDRTYPE_V4</type> for IPv4 addresses and
+ <type>LWRES_ADDRTYPE_V6</type> for IPv6 addresses. Results of the
+ lookup are returned in <parameter>*structp</parameter>.
+ </para>
+
+ <para><function>lwres_getnamebyaddr()</function>
+ performs reverse lookups. Resolver context
+ <parameter>ctx</parameter> is used for memory allocation. The
+ address type is indicated by <parameter>addrtype</parameter>:
+ <type>LWRES_ADDRTYPE_V4</type> or
+ <type>LWRES_ADDRTYPE_V6</type>. The address to be looked up is
+ given by <parameter>addr</parameter> and its length is
+ <parameter>addrlen</parameter> bytes. The result of the
+ function call is made available through
+ <parameter>*structp</parameter>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>RETURN VALUES</title>
+ <para>
+ Successful calls to
+ <function>lwres_string_parse()</function>
+ and
+ <function>lwres_addr_parse()</function>
+ return
+ <errorcode>LWRES_R_SUCCESS.</errorcode>
+ Both functions return
+ <errorcode>LWRES_R_FAILURE</errorcode>
+ if the buffer is corrupt or
+ <errorcode>LWRES_R_UNEXPECTEDEND</errorcode>
+ if the buffer has less space than expected for the components of the
+ encoded string or address.
+ </para>
+
+ <para><function>lwres_getaddrsbyname()</function>
+ returns <errorcode>LWRES_R_SUCCESS</errorcode> on success and it
+ returns <errorcode>LWRES_R_NOTFOUND</errorcode> if the hostname
+ <parameter>name</parameter> could not be found.
+ </para>
+ <para><errorcode>LWRES_R_SUCCESS</errorcode>
+ is returned by a successful call to
+ <function>lwres_getnamebyaddr()</function>.
+ </para>
+
+ <para>
+ Both
+ <function>lwres_getaddrsbyname()</function>
+ and
+ <function>lwres_getnamebyaddr()</function>
+ return
+ <errorcode>LWRES_R_NOMEMORY</errorcode>
+ when memory allocation requests fail and
+ <errorcode>LWRES_R_UNEXPECTEDEND</errorcode>
+ if the buffers used for sending queries and receiving replies are too
+ small.
+ </para>
+
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>lwres_buffer</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>,
+
+ <citerefentry>
+ <refentrytitle>lwres_gabn</refentrytitle><manvolnum>3</manvolnum>
+ </citerefentry>.
+ </para>
+
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/lib/lwres/man/lwres_resutil.html b/lib/lwres/man/lwres_resutil.html
new file mode 100644
index 0000000..7bc3e6e
--- /dev/null
+++ b/lib/lwres/man/lwres_resutil.html
@@ -0,0 +1,258 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000, 2001 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND 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: lwres_resutil.html,v 1.25 2007/01/30 00:24:59 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>lwres_resutil</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476275"></a><div class="titlepage"></div>
+<div class="refnamediv">
+<h2>Name</h2>
+<p>lwres_string_parse, lwres_addr_parse, lwres_getaddrsbyname, lwres_getnamebyaddr &#8212; lightweight resolver utility functions</p>
+</div>
+<div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+<div class="funcsynopsis">
+<pre class="funcsynopsisinfo">#include &lt;lwres/lwres.h&gt;</pre>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_string_parse</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>char ** </td>
+<td>
+<var class="pdparam">c</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_uint16_t * </td>
+<td>
+<var class="pdparam">len</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_addr_parse</b>(</code></td>
+<td>lwres_buffer_t * </td>
+<td>
+<var class="pdparam">b</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_addr_t * </td>
+<td>
+<var class="pdparam">addr</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0" style="padding-bottom: 1em">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_getaddrsbyname</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>const char * </td>
+<td>
+<var class="pdparam">name</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_uint32_t  </td>
+<td>
+<var class="pdparam">addrtypes</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gabnresponse_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+<table border="0" summary="Function synopsis" cellspacing="0" cellpadding="0">
+<tr>
+<td><code class="funcdef">
+lwres_result_t
+<b class="fsfunc">lwres_getnamebyaddr</b>(</code></td>
+<td>lwres_context_t * </td>
+<td>
+<var class="pdparam">ctx</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_uint32_t  </td>
+<td>
+<var class="pdparam">addrtype</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_uint16_t  </td>
+<td>
+<var class="pdparam">addrlen</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>const unsigned char * </td>
+<td>
+<var class="pdparam">addr</var>, </td>
+</tr>
+<tr>
+<td> </td>
+<td>lwres_gnbaresponse_t ** </td>
+<td>
+<var class="pdparam">structp</var><code>)</code>;</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543466"></a><h2>DESCRIPTION</h2>
+<p><code class="function">lwres_string_parse()</code>
+ retrieves a DNS-encoded string starting the current pointer of
+ lightweight resolver buffer <em class="parameter"><code>b</code></em>: i.e.
+ <code class="constant">b-&gt;current</code>. When the function returns,
+ the address of the first byte of the encoded string is returned
+ via <em class="parameter"><code>*c</code></em> and the length of that string is
+ given by <em class="parameter"><code>*len</code></em>. The buffer's current
+ pointer is advanced to point at the character following the
+ string length, the encoded string, and the trailing
+ <span class="type">NULL</span> character.
+ </p>
+<p><code class="function">lwres_addr_parse()</code>
+ extracts an address from the buffer <em class="parameter"><code>b</code></em>.
+ The buffer's current pointer <code class="constant">b-&gt;current</code>
+ is presumed to point at an encoded address: the address preceded
+ by a 32-bit protocol family identifier and a 16-bit length
+ field. The encoded address is copied to
+ <code class="constant">addr-&gt;address</code> and
+ <code class="constant">addr-&gt;length</code> indicates the size in bytes
+ of the address that was copied.
+ <code class="constant">b-&gt;current</code> is advanced to point at the
+ next byte of available data in the buffer following the encoded
+ address.
+ </p>
+<p><code class="function">lwres_getaddrsbyname()</code>
+ and <code class="function">lwres_getnamebyaddr()</code> use the
+ <span class="type">lwres_gnbaresponse_t</span> structure defined below:
+ </p>
+<pre class="programlisting">
+typedef struct {
+ lwres_uint32_t flags;
+ lwres_uint16_t naliases;
+ lwres_uint16_t naddrs;
+ char *realname;
+ char **aliases;
+ lwres_uint16_t realnamelen;
+ lwres_uint16_t *aliaslen;
+ lwres_addrlist_t addrs;
+ void *base;
+ size_t baselen;
+} lwres_gabnresponse_t;
+</pre>
+<p>
+ The contents of this structure are not manipulated directly but
+ they are controlled through the
+ <span class="citerefentry"><span class="refentrytitle">lwres_gabn</span>(3)</span>
+ functions.
+ </p>
+<p>
+ The lightweight resolver uses
+ <code class="function">lwres_getaddrsbyname()</code> to perform
+ foward lookups.
+ Hostname <em class="parameter"><code>name</code></em> is looked up using the
+ resolver
+ context <em class="parameter"><code>ctx</code></em> for memory allocation.
+ <em class="parameter"><code>addrtypes</code></em> is a bitmask indicating
+ which type of
+ addresses are to be looked up. Current values for this bitmask are
+ <span class="type">LWRES_ADDRTYPE_V4</span> for IPv4 addresses and
+ <span class="type">LWRES_ADDRTYPE_V6</span> for IPv6 addresses. Results of the
+ lookup are returned in <em class="parameter"><code>*structp</code></em>.
+ </p>
+<p><code class="function">lwres_getnamebyaddr()</code>
+ performs reverse lookups. Resolver context
+ <em class="parameter"><code>ctx</code></em> is used for memory allocation. The
+ address type is indicated by <em class="parameter"><code>addrtype</code></em>:
+ <span class="type">LWRES_ADDRTYPE_V4</span> or
+ <span class="type">LWRES_ADDRTYPE_V6</span>. The address to be looked up is
+ given by <em class="parameter"><code>addr</code></em> and its length is
+ <em class="parameter"><code>addrlen</code></em> bytes. The result of the
+ function call is made available through
+ <em class="parameter"><code>*structp</code></em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543605"></a><h2>RETURN VALUES</h2>
+<p>
+ Successful calls to
+ <code class="function">lwres_string_parse()</code>
+ and
+ <code class="function">lwres_addr_parse()</code>
+ return
+ <span class="errorcode">LWRES_R_SUCCESS.</span>
+ Both functions return
+ <span class="errorcode">LWRES_R_FAILURE</span>
+ if the buffer is corrupt or
+ <span class="errorcode">LWRES_R_UNEXPECTEDEND</span>
+ if the buffer has less space than expected for the components of the
+ encoded string or address.
+ </p>
+<p><code class="function">lwres_getaddrsbyname()</code>
+ returns <span class="errorcode">LWRES_R_SUCCESS</span> on success and it
+ returns <span class="errorcode">LWRES_R_NOTFOUND</span> if the hostname
+ <em class="parameter"><code>name</code></em> could not be found.
+ </p>
+<p><span class="errorcode">LWRES_R_SUCCESS</span>
+ is returned by a successful call to
+ <code class="function">lwres_getnamebyaddr()</code>.
+ </p>
+<p>
+ Both
+ <code class="function">lwres_getaddrsbyname()</code>
+ and
+ <code class="function">lwres_getnamebyaddr()</code>
+ return
+ <span class="errorcode">LWRES_R_NOMEMORY</span>
+ when memory allocation requests fail and
+ <span class="errorcode">LWRES_R_UNEXPECTEDEND</span>
+ if the buffers used for sending queries and receiving replies are too
+ small.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543676"></a><h2>SEE ALSO</h2>
+<p><span class="citerefentry"><span class="refentrytitle">lwres_buffer</span>(3)</span>,
+
+ <span class="citerefentry"><span class="refentrytitle">lwres_gabn</span>(3)</span>.
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/lib/lwres/print.c b/lib/lwres/print.c
new file mode 100644
index 0000000..5245d29
--- /dev/null
+++ b/lib/lwres/print.c
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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
+ * 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: print.c,v 1.10 2007/06/19 23:47:22 tbox Exp $ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdio.h> /* for sprintf */
+#include <string.h>
+
+#define LWRES__PRINT_SOURCE /* Used to get the lwres_print_* prototypes. */
+
+#include <lwres/stdlib.h>
+
+#include "assert_p.h"
+#include "print_p.h"
+
+#define LWRES_PRINT_QUADFORMAT LWRES_PLATFORM_QUADFORMAT
+
+int
+lwres__print_sprintf(char *str, const char *format, ...) {
+ va_list ap;
+
+ va_start(ap, format);
+ vsprintf(str, format, ap);
+ va_end(ap);
+ return (strlen(str));
+}
+
+/*
+ * Return length of string that would have been written if not truncated.
+ */
+
+int
+lwres__print_snprintf(char *str, size_t size, const char *format, ...) {
+ va_list ap;
+ int ret;
+
+ va_start(ap, format);
+ ret = vsnprintf(str, size, format, ap);
+ va_end(ap);
+ return (ret);
+
+}
+
+/*
+ * Return length of string that would have been written if not truncated.
+ */
+
+int
+lwres__print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
+ int h;
+ int l;
+ int q;
+ int alt;
+ int zero;
+ int left;
+ int plus;
+ int space;
+ long long tmpi;
+ unsigned long long tmpui;
+ unsigned long width;
+ unsigned long precision;
+ unsigned int length;
+ char buf[1024];
+ char c;
+ void *v;
+ char *save = str;
+ const char *cp;
+ const char *head;
+ int count = 0;
+ int pad;
+ int zeropad;
+ int dot;
+ double dbl;
+#ifdef HAVE_LONG_DOUBLE
+ long double ldbl;
+#endif
+ char fmt[32];
+
+ INSIST(str != NULL);
+ INSIST(format != NULL);
+
+ while (*format != '\0') {
+ if (*format != '%') {
+ if (size > 1U) {
+ *str++ = *format;
+ size--;
+ }
+ count++;
+ format++;
+ continue;
+ }
+ format++;
+
+ /*
+ * Reset flags.
+ */
+ dot = space = plus = left = zero = alt = h = l = q = 0;
+ width = precision = 0;
+ head = "";
+ length = pad = zeropad = 0;
+
+ do {
+ if (*format == '#') {
+ alt = 1;
+ format++;
+ } else if (*format == '-') {
+ left = 1;
+ zero = 0;
+ format++;
+ } else if (*format == ' ') {
+ if (!plus)
+ space = 1;
+ format++;
+ } else if (*format == '+') {
+ plus = 1;
+ space = 0;
+ format++;
+ } else if (*format == '0') {
+ if (!left)
+ zero = 1;
+ format++;
+ } else
+ break;
+ } while (1);
+
+ /*
+ * Width.
+ */
+ if (*format == '*') {
+ width = va_arg(ap, int);
+ format++;
+ } else if (isdigit((unsigned char)*format)) {
+ char *e;
+ width = strtoul(format, &e, 10);
+ format = e;
+ }
+
+ /*
+ * Precision.
+ */
+ if (*format == '.') {
+ format++;
+ dot = 1;
+ if (*format == '*') {
+ precision = va_arg(ap, int);
+ format++;
+ } else if (isdigit((unsigned char)*format)) {
+ char *e;
+ precision = strtoul(format, &e, 10);
+ format = e;
+ }
+ }
+
+ switch (*format) {
+ case '\0':
+ continue;
+ case '%':
+ if (size > 1U) {
+ *str++ = *format;
+ size--;
+ }
+ count++;
+ break;
+ case 'q':
+ q = 1;
+ format++;
+ goto doint;
+ case 'h':
+ h = 1;
+ format++;
+ goto doint;
+ case 'l':
+ l = 1;
+ format++;
+ if (*format == 'l') {
+ q = 1;
+ format++;
+ }
+ goto doint;
+ case 'n':
+ case 'i':
+ case 'd':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ doint:
+ if (precision != 0U)
+ zero = 0;
+ switch (*format) {
+ case 'n':
+ if (h) {
+ short int *p;
+ p = va_arg(ap, short *);
+ REQUIRE(p != NULL);
+ *p = str - save;
+ } else if (l) {
+ long int *p;
+ p = va_arg(ap, long *);
+ REQUIRE(p != NULL);
+ *p = str - save;
+ } else {
+ int *p;
+ p = va_arg(ap, int *);
+ REQUIRE(p != NULL);
+ *p = str - save;
+ }
+ break;
+ case 'i':
+ case 'd':
+ if (q)
+ tmpi = va_arg(ap, long long int);
+ else if (l)
+ tmpi = va_arg(ap, long int);
+ else
+ tmpi = va_arg(ap, int);
+ if (tmpi < 0) {
+ head = "-";
+ tmpui = -tmpi;
+ } else {
+ if (plus)
+ head = "+";
+ else if (space)
+ head = " ";
+ else
+ head = "";
+ tmpui = tmpi;
+ }
+ sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "u",
+ tmpui);
+ goto printint;
+ case 'o':
+ if (q)
+ tmpui = va_arg(ap,
+ unsigned long long int);
+ else if (l)
+ tmpui = va_arg(ap, long int);
+ else
+ tmpui = va_arg(ap, int);
+ sprintf(buf,
+ alt ? "%#" LWRES_PRINT_QUADFORMAT "o"
+ : "%" LWRES_PRINT_QUADFORMAT "o",
+ tmpui);
+ goto printint;
+ case 'u':
+ if (q)
+ tmpui = va_arg(ap,
+ unsigned long long int);
+ else if (l)
+ tmpui = va_arg(ap, unsigned long int);
+ else
+ tmpui = va_arg(ap, unsigned int);
+ sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "u",
+ tmpui);
+ goto printint;
+ case 'x':
+ if (q)
+ tmpui = va_arg(ap,
+ unsigned long long int);
+ else if (l)
+ tmpui = va_arg(ap, unsigned long int);
+ else
+ tmpui = va_arg(ap, unsigned int);
+ if (alt) {
+ head = "0x";
+ if (precision > 2U)
+ precision -= 2;
+ }
+ sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "x",
+ tmpui);
+ goto printint;
+ case 'X':
+ if (q)
+ tmpui = va_arg(ap,
+ unsigned long long int);
+ else if (l)
+ tmpui = va_arg(ap, unsigned long int);
+ else
+ tmpui = va_arg(ap, unsigned int);
+ if (alt) {
+ head = "0X";
+ if (precision > 2U)
+ precision -= 2;
+ }
+ sprintf(buf, "%" LWRES_PRINT_QUADFORMAT "X",
+ tmpui);
+ goto printint;
+ printint:
+ if (precision != 0U || width != 0U) {
+ length = strlen(buf);
+ if (length < precision)
+ zeropad = precision - length;
+ else if (length < width && zero)
+ zeropad = width - length;
+ if (width != 0U) {
+ pad = width - length -
+ zeropad - strlen(head);
+ if (pad < 0)
+ pad = 0;
+ }
+ }
+ count += strlen(head) + strlen(buf) + pad +
+ zeropad;
+ if (!left) {
+ while (pad > 0 && size > 1U) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ }
+ cp = head;
+ while (*cp != '\0' && size > 1U) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (zeropad > 0 && size > 1U) {
+ *str++ = '0';
+ size--;
+ zeropad--;
+ }
+ cp = buf;
+ while (*cp != '\0' && size > 1U) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (pad > 0 && size > 1U) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case 's':
+ cp = va_arg(ap, char *);
+ REQUIRE(cp != NULL);
+
+ if (precision != 0U) {
+ /*
+ * cp need not be NULL terminated.
+ */
+ const char *tp;
+ unsigned long n;
+
+ n = precision;
+ tp = cp;
+ while (n != 0U && *tp != '\0')
+ n--, tp++;
+ length = precision - n;
+ } else {
+ length = strlen(cp);
+ }
+ if (width != 0U) {
+ pad = width - length;
+ if (pad < 0)
+ pad = 0;
+ }
+ count += pad + length;
+ if (!left)
+ while (pad > 0 && size > 1U) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ if (precision != 0U)
+ while (precision > 0U && *cp != '\0' &&
+ size > 1U) {
+ *str++ = *cp++;
+ size--;
+ precision--;
+ }
+ else
+ while (*cp != '\0' && size > 1U) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (pad > 0 && size > 1U) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ break;
+ case 'c':
+ c = va_arg(ap, int);
+ if (width > 0U) {
+ count += width;
+ width--;
+ if (left) {
+ *str++ = c;
+ size--;
+ }
+ while (width-- > 0U && size > 1U) {
+ *str++ = ' ';
+ size--;
+ }
+ if (!left && size > 1U) {
+ *str++ = c;
+ size--;
+ }
+ } else {
+ count++;
+ if (size > 1U) {
+ *str++ = c;
+ size--;
+ }
+ }
+ break;
+ case 'p':
+ v = va_arg(ap, void *);
+ sprintf(buf, "%p", v);
+ length = strlen(buf);
+ if (precision > length)
+ zeropad = precision - length;
+ if (width > 0U) {
+ pad = width - length - zeropad;
+ if (pad < 0)
+ pad = 0;
+ }
+ count += length + pad + zeropad;
+ if (!left)
+ while (pad > 0 && size > 1U) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ cp = buf;
+ if (zeropad > 0 && buf[0] == '0' &&
+ (buf[1] == 'x' || buf[1] == 'X')) {
+ if (size > 1U) {
+ *str++ = *cp++;
+ size--;
+ }
+ if (size > 1U) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (zeropad > 0 && size > 1U) {
+ *str++ = '0';
+ size--;
+ zeropad--;
+ }
+ }
+ while (*cp != '\0' && size > 1U) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (pad > 0 && size > 1U) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ break;
+ case 'D': /*deprecated*/
+ INSIST("use %ld instead of %D" == NULL);
+ case 'O': /*deprecated*/
+ INSIST("use %lo instead of %O" == NULL);
+ case 'U': /*deprecated*/
+ INSIST("use %lu instead of %U" == NULL);
+
+ case 'L':
+#ifdef HAVE_LONG_DOUBLE
+ l = 1;
+#else
+ INSIST("long doubles are not supported" == NULL);
+#endif
+ /*FALLTHROUGH*/
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ if (!dot)
+ precision = 6;
+ /*
+ * IEEE floating point.
+ * MIN 2.2250738585072014E-308
+ * MAX 1.7976931348623157E+308
+ * VAX floating point has a smaller range than IEEE.
+ *
+ * precisions > 324 don't make much sense.
+ * if we cap the precision at 512 we will not
+ * overflow buf.
+ */
+ if (precision > 512U)
+ precision = 512;
+ sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
+ plus ? "+" : space ? " " : "",
+ precision, l ? "L" : "", *format);
+ switch (*format) {
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+#ifdef HAVE_LONG_DOUBLE
+ if (l) {
+ ldbl = va_arg(ap, long double);
+ sprintf(buf, fmt, ldbl);
+ } else
+#endif
+ {
+ dbl = va_arg(ap, double);
+ sprintf(buf, fmt, dbl);
+ }
+ length = strlen(buf);
+ if (width > 0U) {
+ pad = width - length;
+ if (pad < 0)
+ pad = 0;
+ }
+ count += length + pad;
+ if (!left)
+ while (pad > 0 && size > 1U) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ cp = buf;
+ while (*cp != ' ' && size > 1U) {
+ *str++ = *cp++;
+ size--;
+ }
+ while (pad > 0 && size > 1U) {
+ *str++ = ' ';
+ size--;
+ pad--;
+ }
+ break;
+ default:
+ continue;
+ }
+ break;
+ default:
+ continue;
+ }
+ format++;
+ }
+ if (size > 0U)
+ *str = '\0';
+ return (count);
+}
diff --git a/lib/lwres/print_p.h b/lib/lwres/print_p.h
new file mode 100644
index 0000000..c22b44a
--- /dev/null
+++ b/lib/lwres/print_p.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2004, 2007 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
+ * 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: print_p.h,v 1.4 2007/06/19 23:47:22 tbox Exp $ */
+
+#ifndef LWRES_PRINT_P_H
+#define LWRES_PRINT_P_H 1
+
+/***
+ *** Imports
+ ***/
+
+#include <lwres/lang.h>
+#include <lwres/platform.h>
+
+/*
+ * This block allows lib/lwres/print.c to be cleanly compiled even if
+ * the platform does not need it. The standard Makefile will still
+ * not compile print.c or archive print.o, so this is just to make test
+ * compilation ("make print.o") easier.
+ */
+#if !defined(LWRES_PLATFORM_NEEDVSNPRINTF) && defined(LWRES__PRINT_SOURCE)
+#define LWRES_PLATFORM_NEEDVSNPRINTF
+#endif
+
+#if !defined(LWRES_PLATFORM_NEEDSPRINTF) && defined(LWRES__PRINT_SOURCE)
+#define LWRES_PLATFORM_NEEDSPRINTF
+#endif
+
+/***
+ *** Macros.
+ ***/
+
+#ifdef __GNUC__
+#define LWRES_FORMAT_PRINTF(fmt, args) \
+ __attribute__((__format__(__printf__, fmt, args)))
+#else
+#define LWRES_FORMAT_PRINTF(fmt, args)
+#endif
+
+/***
+ *** Functions
+ ***/
+
+#ifdef LWRES_PLATFORM_NEEDVSNPRINTF
+#include <stdarg.h>
+#include <stddef.h>
+#endif
+
+LWRES_LANG_BEGINDECLS
+
+#ifdef LWRES_PLATFORM_NEEDVSNPRINTF
+int
+lwres__print_vsnprintf(char *str, size_t size, const char *format, va_list ap)
+ LWRES_FORMAT_PRINTF(3, 0);
+#define vsnprintf lwres__print_vsnprintf
+
+int
+lwres__print_snprintf(char *str, size_t size, const char *format, ...)
+ LWRES_FORMAT_PRINTF(3, 4);
+#define snprintf lwres__print_snprintf
+#endif /* LWRES_PLATFORM_NEEDVSNPRINTF */
+
+#ifdef LWRES_PLATFORM_NEEDSPRINTF
+int
+lwres__print_sprintf(char *str, const char *format, ...) LWRES_FORMAT_PRINTF(2, 3);
+#define sprintf lwres__print_sprintf
+#endif
+
+LWRES_LANG_ENDDECLS
+
+#endif /* LWRES_PRINT_P_H */
diff --git a/lib/lwres/strtoul.c b/lib/lwres/strtoul.c
new file mode 100644
index 0000000..f16896c
--- /dev/null
+++ b/lib/lwres/strtoul.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 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.
+ */
+
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*! \file */
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+/* $Id: strtoul.c,v 1.4 2007/06/19 23:47:22 tbox Exp $ */
+
+#include <config.h>
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <lwres/stdlib.h>
+
+#define DE_CONST(konst, var) \
+ do { \
+ union { const void *k; void *v; } _u; \
+ _u.k = konst; \
+ var = _u.v; \
+ } while (0)
+
+/*!
+ * Convert a string to an unsigned long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long
+lwres_strtoul(const char *nptr, char **endptr, int base) {
+ const char *s = nptr;
+ unsigned long acc;
+ unsigned char c;
+ unsigned long cutoff;
+ int neg = 0, any, cutlim;
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
+ cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (!isascii(c))
+ break;
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ DE_CONST(any ? s - 1 : nptr, *endptr);
+ return (acc);
+}
diff --git a/lib/lwres/unix/Makefile.in b/lib/lwres/unix/Makefile.in
new file mode 100644
index 0000000..5d77208
--- /dev/null
+++ b/lib/lwres/unix/Makefile.in
@@ -0,0 +1,25 @@
+# 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.4 2007/06/19 23:47:23 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = include
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/lwres/unix/include/Makefile.in b/lib/lwres/unix/include/Makefile.in
new file mode 100644
index 0000000..6190633
--- /dev/null
+++ b/lib/lwres/unix/include/Makefile.in
@@ -0,0 +1,25 @@
+# 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.4 2007/06/19 23:47:23 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = lwres
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/lwres/unix/include/lwres/Makefile.in b/lib/lwres/unix/include/lwres/Makefile.in
new file mode 100644
index 0000000..c943e01
--- /dev/null
+++ b/lib/lwres/unix/include/lwres/Makefile.in
@@ -0,0 +1,34 @@
+# 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.4 2007/06/19 23:47:23 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+HEADERS = net.h
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/lwres
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/lwres ; \
+ done
diff --git a/lib/lwres/unix/include/lwres/net.h b/lib/lwres/unix/include/lwres/net.h
new file mode 100644
index 0000000..0b16178
--- /dev/null
+++ b/lib/lwres/unix/include/lwres/net.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2002 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: net.h,v 1.9 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_NET_H
+#define LWRES_NET_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file net.h
+ * This module is responsible for defining the following basic networking
+ * types:
+ *
+ *\li struct in_addr
+ *\li struct in6_addr
+ *\li struct sockaddr
+ *\li struct sockaddr_in
+ *\li struct sockaddr_in6
+ *
+ * It ensures that the AF_ and PF_ macros are defined.
+ *
+ * It declares ntoh[sl]() and hton[sl]().
+ *
+ * It declares lwres_net_aton(), lwres_net_ntop(), and lwres_net_pton().
+ *
+ * It ensures that #INADDR_LOOPBACK, #INADDR_ANY and #IN6ADDR_ANY_INIT
+ * are defined.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+#include <lwres/platform.h> /* Required for LWRES_PLATFORM_*. */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h> /* Contractual promise. */
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/un.h>
+
+#include <netinet/in.h> /* Contractual promise. */
+#include <arpa/inet.h> /* Contractual promise. */
+#ifdef LWRES_PLATFORM_NEEDNETINETIN6H
+#include <netinet/in6.h> /* Required on UnixWare. */
+#endif
+#ifdef LWRES_PLATFORM_NEEDNETINET6IN6H
+#include <netinet6/in6.h> /* Required on BSD/OS for in6_pktinfo. */
+#endif
+#include <net/if.h>
+
+#include <lwres/lang.h>
+
+#ifndef LWRES_PLATFORM_HAVEIPV6
+#include <lwres/ipv6.h> /* Contractual promise. */
+#endif
+
+#ifdef LWRES_PLATFORM_HAVEINADDR6
+#define in6_addr in_addr6 /* Required for pre RFC2133 implementations. */
+#endif
+
+/*!
+ * Required for some pre RFC2133 implementations.
+ * IN6ADDR_ANY_INIT and IN6ADDR_LOOPBACK_INIT were added in
+ * draft-ietf-ipngwg-bsd-api-04.txt or draft-ietf-ipngwg-bsd-api-05.txt.
+ * If 's6_addr' is defined then assume that there is a union and three
+ * levels otherwise assume two levels required.
+ */
+#ifndef IN6ADDR_ANY_INIT
+#ifdef s6_addr
+#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
+#else
+#define IN6ADDR_ANY_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }
+#endif
+#endif
+
+/*!
+ * Initialize address loopback. See IN6ADDR_ANY_INIT
+ */
+#ifndef IN6ADDR_LOOPBACK_INIT
+#ifdef s6_addr
+#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
+#else
+#define IN6ADDR_LOOPBACK_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } }
+#endif
+#endif
+
+/*% Used by AI_ALL */
+#ifndef AF_INET6
+#define AF_INET6 99
+#endif
+
+
+/*% Used to return IPV6 address types. */
+#ifndef PF_INET6
+#define PF_INET6 AF_INET6
+#endif
+
+/*% inaddr Loopback */
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001UL
+#endif
+
+LWRES_LANG_BEGINDECLS
+
+const char *
+lwres_net_ntop(int af, const void *src, char *dst, size_t size);
+
+int
+lwres_net_pton(int af, const char *src, void *dst);
+
+int
+lwres_net_aton(const char *cp, struct in_addr *addr);
+
+LWRES_LANG_ENDDECLS
+
+#endif /* LWRES_NET_H */
diff --git a/lib/lwres/version.c b/lib/lwres/version.c
new file mode 100644
index 0000000..cc52c51
--- /dev/null
+++ b/lib/lwres/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 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: version.c,v 1.12 2007/06/19 23:47:22 tbox Exp $ */
+
+/*! \file */
+
+#include <lwres/version.h>
+
+const char lwres_version[] = VERSION;
+
+const unsigned int lwres_libinterface = LIBINTERFACE;
+const unsigned int lwres_librevision = LIBREVISION;
+const unsigned int lwres_libage = LIBAGE;
diff --git a/lib/lwres/win32/DLLMain.c b/lib/lwres/win32/DLLMain.c
new file mode 100644
index 0000000..a61372e
--- /dev/null
+++ b/lib/lwres/win32/DLLMain.c
@@ -0,0 +1,58 @@
+/*
+ * 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: DLLMain.c,v 1.5 2007/06/18 23:47:51 tbox Exp $ */
+
+#include <windows.h>
+#include <signal.h>
+
+/*
+ * Called when we enter the DLL
+ */
+__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+ DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ /*
+ * The DLL is loading due to process
+ * initialization or a call to LoadLibrary.
+ */
+ case DLL_PROCESS_ATTACH:
+ break;
+
+ /* The attached process creates a new thread. */
+ case DLL_THREAD_ATTACH:
+ break;
+
+ /* The thread of the attached process terminates. */
+ case DLL_THREAD_DETACH:
+ break;
+
+ /*
+ * The DLL is unloading from a process due to
+ * process termination or a call to FreeLibrary.
+ */
+ case DLL_PROCESS_DETACH:
+ break;
+
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
diff --git a/lib/lwres/win32/Makefile.in b/lib/lwres/win32/Makefile.in
new file mode 100644
index 0000000..5d77208
--- /dev/null
+++ b/lib/lwres/win32/Makefile.in
@@ -0,0 +1,25 @@
+# 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.4 2007/06/19 23:47:23 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = include
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/lwres/win32/include/Makefile.in b/lib/lwres/win32/include/Makefile.in
new file mode 100644
index 0000000..6190633
--- /dev/null
+++ b/lib/lwres/win32/include/Makefile.in
@@ -0,0 +1,25 @@
+# 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.4 2007/06/19 23:47:23 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = lwres
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/lwres/win32/include/lwres/Makefile.in b/lib/lwres/win32/include/lwres/Makefile.in
new file mode 100644
index 0000000..c943e01
--- /dev/null
+++ b/lib/lwres/win32/include/lwres/Makefile.in
@@ -0,0 +1,34 @@
+# 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.4 2007/06/19 23:47:23 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+HEADERS = net.h
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${includedir}/lwres
+
+install:: installdirs
+ for i in ${HEADERS}; do \
+ ${INSTALL_DATA} $(srcdir)/$$i ${DESTDIR}${includedir}/lwres ; \
+ done
diff --git a/lib/lwres/win32/include/lwres/int.h b/lib/lwres/win32/include/lwres/int.h
new file mode 100644
index 0000000..16f691a
--- /dev/null
+++ b/lib/lwres/win32/include/lwres/int.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2004, 2007 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: int.h,v 1.4 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_INT_H
+#define LWRES_INT_H 1
+
+typedef char lwres_int8_t;
+typedef unsigned char lwres_uint8_t;
+typedef short lwres_int16_t;
+typedef unsigned short lwres_uint16_t;
+typedef int lwres_int32_t;
+typedef unsigned int lwres_uint32_t;
+typedef __int64 lwres_int64_t;
+typedef unsigned __int64 lwres_uint64_t;
+
+#endif /* LWRES_INT_H */
diff --git a/lib/lwres/win32/include/lwres/net.h b/lib/lwres/win32/include/lwres/net.h
new file mode 100644
index 0000000..94e4af4
--- /dev/null
+++ b/lib/lwres/win32/include/lwres/net.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2004, 2007 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: net.h,v 1.6 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_NET_H
+#define LWRES_NET_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*
+ * Basic Networking Types
+ *
+ * This module is responsible for defining the following basic networking
+ * types:
+ *
+ * struct in_addr
+ * struct in6_addr
+ * struct sockaddr
+ * struct sockaddr_in
+ * struct sockaddr_in6
+ *
+ * It ensures that the AF_ and PF_ macros are defined.
+ *
+ * It declares ntoh[sl]() and hton[sl]().
+ *
+ * It declares lwres_net_aton(), lwres_net_ntop(), and lwres_net_pton().
+ *
+ * It ensures that INADDR_LOOPBACK, INADDR_ANY and IN6ADDR_ANY_INIT
+ * are defined.
+ */
+
+/***
+ *** Imports.
+ ***/
+
+/*
+ * Because of some sort of problem in the MS header files, this cannot
+ * be simple "#include <winsock2.h>", because winsock2.h tries to include
+ * windows.h, which then generates an error out of mswsock.h. _You_
+ * figure it out.
+ */
+#ifndef _WINSOCKAPI_
+#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
+#endif
+
+#include <winsock2.h>
+#include <sys/types.h>
+
+#include <lwres/ipv6.h>
+#include <lwres/platform.h> /* Required for LWRES_PLATFORM_*. */
+
+#include <lwres/lang.h>
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001UL
+#endif
+/*
+ * Fix the FD_SET and FD_CLR Macros to properly cast
+ */
+#undef FD_CLR
+#define FD_CLR(fd, set) do { \
+ u_int __i; \
+ for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
+ if (((fd_set FAR *)(set))->fd_array[__i] == (SOCKET) fd) { \
+ while (__i < ((fd_set FAR *)(set))->fd_count-1) { \
+ ((fd_set FAR *)(set))->fd_array[__i] = \
+ ((fd_set FAR *)(set))->fd_array[__i+1]; \
+ __i++; \
+ } \
+ ((fd_set FAR *)(set))->fd_count--; \
+ break; \
+ } \
+ } \
+} while (0)
+
+#undef FD_SET
+#define FD_SET(fd, set) do { \
+ u_int __i; \
+ for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \
+ if (((fd_set FAR *)(set))->fd_array[__i] == (SOCKET)(fd)) { \
+ break; \
+ } \
+ } \
+ if (__i == ((fd_set FAR *)(set))->fd_count) { \
+ if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) { \
+ ((fd_set FAR *)(set))->fd_array[__i] = (SOCKET)(fd); \
+ ((fd_set FAR *)(set))->fd_count++; \
+ } \
+ } \
+} while (0)
+
+/*
+ * Windows Sockets errors redefined as regular Berkeley error constants.
+ * These are usually commented out in Windows NT to avoid conflicts with errno.h.
+ * Use the WSA constants instead.
+ */
+
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#define EALREADY WSAEALREADY
+#define ENOTSOCK WSAENOTSOCK
+#define EDESTADDRREQ WSAEDESTADDRREQ
+#define EMSGSIZE WSAEMSGSIZE
+#define EPROTOTYPE WSAEPROTOTYPE
+#define ENOPROTOOPT WSAENOPROTOOPT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#define EOPNOTSUPP WSAEOPNOTSUPP
+#define EPFNOSUPPORT WSAEPFNOSUPPORT
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define EADDRINUSE WSAEADDRINUSE
+#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#define ENETDOWN WSAENETDOWN
+#define ENETUNREACH WSAENETUNREACH
+#define ENETRESET WSAENETRESET
+#define ECONNABORTED WSAECONNABORTED
+#define ECONNRESET WSAECONNRESET
+#define ENOBUFS WSAENOBUFS
+#define EISCONN WSAEISCONN
+#define ENOTCONN WSAENOTCONN
+#define ESHUTDOWN WSAESHUTDOWN
+#define ETOOMANYREFS WSAETOOMANYREFS
+#define ETIMEDOUT WSAETIMEDOUT
+#define ECONNREFUSED WSAECONNREFUSED
+#define ELOOP WSAELOOP
+#define EHOSTDOWN WSAEHOSTDOWN
+#define EHOSTUNREACH WSAEHOSTUNREACH
+#define EPROCLIM WSAEPROCLIM
+#define EUSERS WSAEUSERS
+#define EDQUOT WSAEDQUOT
+#define ESTALE WSAESTALE
+#define EREMOTE WSAEREMOTE
+
+LWRES_LANG_BEGINDECLS
+
+const char *
+lwres_net_ntop(int af, const void *src, char *dst, size_t size);
+
+int
+lwres_net_pton(int af, const char *src, void *dst);
+
+int
+lwres_net_aton(const char *cp, struct in_addr *addr);
+
+LWRES_LANG_ENDDECLS
+
+#endif /* LWRES_NET_H */
diff --git a/lib/lwres/win32/include/lwres/netdb.h b/lib/lwres/win32/include/lwres/netdb.h
new file mode 100644
index 0000000..41146c8
--- /dev/null
+++ b/lib/lwres/win32/include/lwres/netdb.h
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 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: netdb.h,v 1.7 2007/06/19 23:47:23 tbox Exp $ */
+
+#ifndef LWRES_NETDB_H
+#define LWRES_NETDB_H 1
+
+#include <stddef.h> /* Required on FreeBSD (and others?) for size_t. */
+
+#define off_t _off_t
+#include <sys/types.h>
+
+#include <lwres/net.h>
+#include <lwres/lang.h>
+
+/*
+ * Define if <netdb.h> does not declare struct addrinfo.
+ */
+#define ISC_LWRES_NEEDADDRINFO 1
+
+#ifdef ISC_LWRES_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 <netdb.h> 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()
+ */
+
+#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_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_MAX 14
+
+/*
+ * 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
+#define NI_NUMERICSCOPE 0x00000020 /*2553bis-00*/
+
+/*
+ * Structures for getrrsetbyname()
+ */
+struct rdatainfo {
+ unsigned int rdi_length;
+ unsigned char *rdi_data;
+};
+
+struct rrsetinfo {
+ unsigned int rri_flags;
+ int rri_rdclass;
+ int rri_rdtype;
+ unsigned int rri_ttl;
+ unsigned int rri_nrdatas;
+ unsigned int rri_nsigs;
+ char *rri_name;
+ struct rdatainfo *rri_rdatas;
+ struct rdatainfo *rri_sigs;
+};
+
+/*
+ * Flags for getrrsetbyname()
+ */
+#define RRSET_VALIDATED 0x00000001
+ /* Set was dnssec validated */
+
+/*
+ * Return codes for getrrsetbyname()
+ */
+#define ERRSET_SUCCESS 0
+#define ERRSET_NOMEMORY 1
+#define ERRSET_FAIL 2
+#define ERRSET_INVAL 3
+#define ERRSET_NONAME 4
+#define ERRSET_NODATA 5
+
+/*
+ * Define to map into lwres_ namespace.
+ */
+
+#define LWRES_NAMESPACE
+
+#ifdef LWRES_NAMESPACE
+
+/*
+ * Use our versions not the ones from the C library.
+ */
+
+#ifdef getnameinfo
+#undef getnameinfo
+#endif
+#define getnameinfo lwres_getnameinfo
+
+#ifdef getaddrinfo
+#undef getaddrinfo
+#endif
+#define getaddrinfo lwres_getaddrinfo
+
+#ifdef freeaddrinfo
+#undef freeaddrinfo
+#endif
+#define freeaddrinfo lwres_freeaddrinfo
+
+#ifdef gai_strerror
+#undef gai_strerror
+#endif
+#define gai_strerror lwres_gai_strerror
+
+#ifdef herror
+#undef herror
+#endif
+#define herror lwres_herror
+
+#ifdef hstrerror
+#undef hstrerror
+#endif
+#define hstrerror lwres_hstrerror
+
+#ifdef getipnodebyname
+#undef getipnodebyname
+#endif
+#define getipnodebyname lwres_getipnodebyname
+
+#ifdef getipnodebyaddr
+#undef getipnodebyaddr
+#endif
+#define getipnodebyaddr lwres_getipnodebyaddr
+
+#ifdef freehostent
+#undef freehostent
+#endif
+#define freehostent lwres_freehostent
+
+#ifdef gethostbyname
+#undef gethostbyname
+#endif
+#define gethostbyname lwres_gethostbyname
+
+#ifdef gethostbyname2
+#undef gethostbyname2
+#endif
+#define gethostbyname2 lwres_gethostbyname2
+
+#ifdef gethostbyaddr
+#undef gethostbyaddr
+#endif
+#define gethostbyaddr lwres_gethostbyaddr
+
+#ifdef gethostent
+#undef gethostent
+#endif
+#define gethostent lwres_gethostent
+
+#ifdef sethostent
+#undef sethostent
+#endif
+#define sethostent lwres_sethostent
+
+#ifdef endhostent
+#undef endhostent
+#endif
+#define endhostent lwres_endhostent
+
+/* #define sethostfile lwres_sethostfile */
+
+#ifdef gethostbyname_r
+#undef gethostbyname_r
+#endif
+#define gethostbyname_r lwres_gethostbyname_r
+
+#ifdef gethostbyaddr_r
+#undef gethostbyaddr_r
+#endif
+#define gethostbyaddr_r lwres_gethostbyaddr_r
+
+#ifdef gethostent_r
+#undef gethostent_r
+#endif
+#define gethostent_r lwres_gethostent_r
+
+#ifdef sethostent_r
+#undef sethostent_r
+#endif
+#define sethostent_r lwres_sethostent_r
+
+#ifdef endhostent_r
+#undef endhostent_r
+#endif
+#define endhostent_r lwres_endhostent_r
+
+#ifdef getrrsetbyname
+#undef getrrsetbyname
+#endif
+#define getrrsetbyname lwres_getrrsetbyname
+
+#ifdef freerrset
+#undef freerrset
+#endif
+#define freerrset lwres_freerrset
+
+#ifdef notyet
+#define getservbyname lwres_getservbyname
+#define getservbyport lwres_getservbyport
+#define getservent lwres_getservent
+#define setservent lwres_setservent
+#define endservent lwres_endservent
+
+#define getservbyname_r lwres_getservbyname_r
+#define getservbyport_r lwres_getservbyport_r
+#define getservent_r lwres_getservent_r
+#define setservent_r lwres_setservent_r
+#define endservent_r lwres_endservent_r
+
+#define getprotobyname lwres_getprotobyname
+#define getprotobynumber lwres_getprotobynumber
+#define getprotoent lwres_getprotoent
+#define setprotoent lwres_setprotoent
+#define endprotoent lwres_endprotoent
+
+#define getprotobyname_r lwres_getprotobyname_r
+#define getprotobynumber_r lwres_getprotobynumber_r
+#define getprotoent_r lwres_getprotoent_r
+#define setprotoent_r lwres_setprotoent_r
+#define endprotoent_r lwres_endprotoent_r
+
+#ifdef getnetbyname
+#undef getnetbyname
+#endif
+#define getnetbyname lwres_getnetbyname
+
+#ifdef getnetbyaddr
+#undef getnetbyaddr
+#endif
+#define getnetbyaddr lwres_getnetbyaddr
+
+#ifdef getnetent
+#undef getnetent
+#endif
+#define getnetent lwres_getnetent
+
+#ifdef setnetent
+#undef setnetent
+#endif
+#define setnetent lwres_setnetent
+
+#ifdef endnetent
+#undef endnetent
+#endif
+#define endnetent lwres_endnetent
+
+
+#ifdef getnetbyname_r
+#undef getnetbyname_r
+#endif
+#define getnetbyname_r lwres_getnetbyname_r
+
+#ifdef getnetbyaddr_r
+#undef getnetbyaddr_r
+#endif
+#define getnetbyaddr_r lwres_getnetbyaddr_r
+
+#ifdef getnetent_r
+#undef getnetent_r
+#endif
+#define getnetent_r lwres_getnetent_r
+
+#ifdef setnetent_r
+#undef setnetent_r
+#endif
+#define setnetent_r lwres_setnetent_r
+
+#ifdef endnetent_r
+#undef endnetent_r
+#endif
+#define endnetent_r lwres_endnetent_r
+#endif /* notyet */
+
+#ifdef h_errno
+#undef h_errno
+#endif
+#define h_errno lwres_h_errno
+
+#endif /* LWRES_NAMESPACE */
+
+LWRES_LANG_BEGINDECLS
+
+LIBLWRES_EXTERNAL_DATA extern int lwres_h_errno;
+
+int lwres_getaddrinfo(const char *, const char *,
+ const struct addrinfo *, struct addrinfo **);
+int lwres_getnameinfo(const struct sockaddr *, size_t, char *,
+ size_t, char *, size_t, int);
+void lwres_freeaddrinfo(struct addrinfo *);
+char *lwres_gai_strerror(int);
+
+struct hostent *lwres_gethostbyaddr(const char *, int, int);
+struct hostent *lwres_gethostbyname(const char *);
+struct hostent *lwres_gethostbyname2(const char *, int);
+struct hostent *lwres_gethostent(void);
+struct hostent *lwres_getipnodebyname(const char *, int, int, int *);
+struct hostent *lwres_getipnodebyaddr(const void *, size_t, int, int *);
+void lwres_endhostent(void);
+void lwres_sethostent(int);
+/* void lwres_sethostfile(const char *); */
+void lwres_freehostent(struct hostent *);
+
+int lwres_getrrsetbyname(const char *, unsigned int, unsigned int,
+ unsigned int, struct rrsetinfo **);
+void lwres_freerrset(struct rrsetinfo *);
+
+#ifdef notyet
+struct netent *lwres_getnetbyaddr(unsigned long, int);
+struct netent *lwres_getnetbyname(const char *);
+struct netent *lwres_getnetent(void);
+void lwres_endnetent(void);
+void lwres_setnetent(int);
+
+struct protoent *lwres_getprotobyname(const char *);
+struct protoent *lwres_getprotobynumber(int);
+struct protoent *lwres_getprotoent(void);
+void lwres_endprotoent(void);
+void lwres_setprotoent(int);
+
+struct servent *lwres_getservbyname(const char *, const char *);
+struct servent *lwres_getservbyport(int, const char *);
+struct servent *lwres_getservent(void);
+void lwres_endservent(void);
+void lwres_setservent(int);
+#endif /* notyet */
+
+void lwres_herror(const char *);
+const char *lwres_hstrerror(int);
+
+
+#ifdef _REENTRANT
+struct hostent *lwres_gethostbyaddr_r(const char *, int, int, struct hostent *,
+ char *, int, int *);
+struct hostent *lwres_gethostbyname_r(const char *, struct hostent *,
+ char *, int, int *);
+struct hostent *lwres_gethostent_r(struct hostent *, char *, int, int *);
+void lwres_sethostent_r(int);
+void lwres_endhostent_r(void);
+
+#ifdef notyet
+struct netent *lwres_getnetbyname_r(const char *, struct netent *,
+ char *, int);
+struct netent *lwres_getnetbyaddr_r(long, int, struct netent *,
+ char *, int);
+struct netent *lwres_getnetent_r(struct netent *, char *, int);
+void lwres_setnetent_r(int);
+void lwres_endnetent_r(void);
+
+struct protoent *lwres_getprotobyname_r(const char *,
+ struct protoent *, char *, int);
+struct protoent *lwres_getprotobynumber_r(int,
+ struct protoent *, char *, int);
+struct protoent *lwres_getprotoent_r(struct protoent *, char *, int);
+void lwres_setprotoent_r(int);
+void lwres_endprotoent_r(void);
+
+struct servent *lwres_getservbyname_r(const char *name, const char *,
+ struct servent *, char *, int);
+struct servent *lwres_getservbyport_r(int port, const char *,
+ struct servent *, char *, int);
+struct servent *lwres_getservent_r(struct servent *, char *, int);
+void lwres_setservent_r(int);
+void lwres_endservent_r(void);
+#endif /* notyet */
+#endif /* _REENTRANT */
+
+LWRES_LANG_ENDDECLS
+
+#ifdef notyet
+/* This is nec'y to make this include file properly replace the sun version. */
+#ifdef sun
+#ifdef __GNU_LIBRARY__
+#include <rpc/netdb.h> /* Required. */
+#else /* !__GNU_LIBRARY__ */
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ int r_number; /* rpc program number */
+};
+struct rpcent *lwres_getrpcbyname();
+struct rpcent *lwres_getrpcbynumber(),
+struct rpcent *lwres_getrpcent();
+#endif /* __GNU_LIBRARY__ */
+#endif /* sun */
+#endif /* notyet */
+
+/*
+ * Tell Emacs to use C mode on this file.
+ * Local variables:
+ * mode: c
+ * End:
+ */
+
+#endif /* LWRES_NETDB_H */
diff --git a/lib/lwres/win32/include/lwres/platform.h b/lib/lwres/win32/include/lwres/platform.h
new file mode 100644
index 0000000..89fd9ac
--- /dev/null
+++ b/lib/lwres/win32/include/lwres/platform.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2004, 2007 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: platform.h,v 1.7 2007/06/18 23:47:52 tbox Exp $ */
+
+#ifndef LWRES_PLATFORM_H
+#define LWRES_PLATFORM_H 1
+
+/*****
+ ***** Platform-dependent defines.
+ *****/
+
+/***
+ *** Network.
+ ***/
+
+/*
+ * Define if this system needs the <netinet/in6.h> header file for IPv6.
+ */
+/*@LWRES_PLATFORM_NEEDNETINETIN6H@ */
+
+/*
+ * Define if this system needs the <netinet6/in6.h> header file for IPv6.
+ */
+/*@LWRES_PLATFORM_NEEDNETINET6IN6H@ */
+
+/*
+ * If sockaddrs on this system have an sa_len field, LWRES_PLATFORM_HAVESALEN
+ * will be defined.
+ */
+/*@LWRES_PLATFORM_HAVESALEN@ */
+
+/*
+ * If this system has the IPv6 structure definitions, LWRES_PLATFORM_HAVEIPV6
+ * will be defined.
+ */
+/*@LWRES_PLATFORM_HAVEIPV6@ */
+
+/*
+ * If this system is missing in6addr_any, LWRES_PLATFORM_NEEDIN6ADDRANY will
+ * be defined.
+ */
+#define LWRES_PLATFORM_NEEDIN6ADDRANY
+
+/*
+ * If this system has in_addr6, rather than in6_addr,
+ * LWRES_PLATFORM_HAVEINADDR6 will be defined.
+ */
+/*@LWRES_PLATFORM_HAVEINADDR6@ */
+
+/*
+ * Defined if unistd.h does not cause fd_set to be delared.
+ */
+/*@LWRES_PLATFORM_NEEDSYSSELECTH@ */
+
+/*
+ * Define some Macros
+ */
+#ifdef LIBLWRES_EXPORTS
+#define LIBLWRES_EXTERNAL_DATA __declspec(dllexport)
+#else
+#define LIBLWRES_EXTERNAL_DATA __declspec(dllimport)
+#endif
+
+/*
+ * Define the MAKE_NONBLOCKING Macro here since it can get used in
+ * a number of places.
+ */
+#define MAKE_NONBLOCKING(sd, retval) \
+do { \
+ int _on = 1; \
+ retval = ioctlsocket((SOCKET) sd, FIONBIO, &_on); \
+} while (0)
+
+/*
+ * Need to define close here since lwres closes sockets and not files
+ */
+#undef close
+#define close closesocket
+
+/*
+ * Internal to liblwres.
+ */
+void InitSockets(void);
+
+void DestroySockets(void);
+
+#endif /* LWRES_PLATFORM_H */
diff --git a/lib/lwres/win32/liblwres.def b/lib/lwres/win32/liblwres.def
new file mode 100644
index 0000000..e3638fc
--- /dev/null
+++ b/lib/lwres/win32/liblwres.def
@@ -0,0 +1,78 @@
+LIBRARY liblwres
+
+; Exported Functions
+EXPORTS
+
+lwres_context_create
+lwres_context_destroy
+lwres_context_nextserial
+lwres_context_initserial
+lwres_context_freemem
+lwres_context_allocmem
+lwres_context_getsocket
+lwres_context_send
+lwres_context_recv
+lwres_context_sendrecv
+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
+lwres_lwpacket_renderheader
+lwres_lwpacket_parseheader
+lwres_gabnrequest_render
+lwres_gabnresponse_render
+lwres_gabnrequest_parse
+lwres_gabnresponse_parse
+lwres_gabnrequest_free
+lwres_gabnresponse_free
+lwres_gnbarequest_render
+lwres_gnbaresponse_render
+lwres_gnbarequest_parse
+lwres_gnbaresponse_parse
+lwres_gnbarequest_free
+lwres_gnbaresponse_free
+lwres_grbnrequest_render
+lwres_grbnresponse_render
+lwres_grbnrequest_parse
+lwres_grbnresponse_parse
+lwres_grbnrequest_free
+lwres_grbnresponse_free
+lwres_nooprequest_render
+lwres_noopresponse_render
+lwres_nooprequest_parse
+lwres_noopresponse_parse
+lwres_nooprequest_free
+lwres_noopresponse_free
+lwres_conf_parse
+lwres_conf_print
+lwres_conf_init
+lwres_conf_clear
+lwres_conf_get
+lwres_data_parse
+lwres_string_parse
+lwres_addr_parse
+lwres_net_ntop
+lwres_net_pton
+lwres_net_aton
+lwres_gethostbyname
+lwres_freeaddrinfo
+lwres_gai_strerror
+lwres_getaddrinfo
+
+; Exported Data
+
+EXPORTS
+
+;lwres_h_errno DATA
diff --git a/lib/lwres/win32/liblwres.dsp b/lib/lwres/win32/liblwres.dsp
new file mode 100644
index 0000000..4d25694
--- /dev/null
+++ b/lib/lwres/win32/liblwres.dsp
@@ -0,0 +1,245 @@
+# Microsoft Developer Studio Project File - Name="liblwres" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=liblwres - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "liblwres.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "liblwres.mak" CFG="liblwres - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "liblwres - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "liblwres - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "liblwres_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../lib/lwres/win32/include/lwres" /I "include" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../..../lib/dns/sec/openssl/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBLWRES_EXPORTS" /YX /FD /c
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib iphlpapi.lib /nologo /dll /machine:I386 /out:"../../../Build/Release/liblwres.dll"
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "liblwres_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../lib/lwres/win32/include/lwres" /I "include" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../..../lib/dns/sec/openssl/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBLWRES_EXPORTS" /FR /YX /FD /GZ /c
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib iphlpapi.lib /nologo /dll /debug /machine:I386 /out:"../../../Build/Debug/liblwres.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "liblwres - Win32 Release"
+# Name "liblwres - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\context.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\DLLMain.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\gai_strerror.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\getaddrinfo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\gethost.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\getipnode.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\getnameinfo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\getrrset.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\herror.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwbuffer.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\lwconfig.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwinetaton.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwinetntop.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwinetpton.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwpacket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwres_gabn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwres_gnba.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwres_grbn.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwres_noop.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\lwresutil.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\version.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\lwres\context.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\lwres\int.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\lwres\ipv6.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\lwres\lang.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\lwres\list.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\lwres\lwbuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\lwres\lwpacket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\lwres\lwres.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\lwres\net.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\lwres\netdb.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\lwres\platform.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\lwres\result.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=.\liblwres.def
+# End Source File
+# End Target
+# End Project
diff --git a/lib/lwres/win32/liblwres.dsw b/lib/lwres/win32/liblwres.dsw
new file mode 100644
index 0000000..06267b5
--- /dev/null
+++ b/lib/lwres/win32/liblwres.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "liblwres"=".\liblwres.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/lwres/win32/liblwres.mak b/lib/lwres/win32/liblwres.mak
new file mode 100644
index 0000000..aade3fd
--- /dev/null
+++ b/lib/lwres/win32/liblwres.mak
@@ -0,0 +1,774 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on liblwres.dsp
+!IF "$(CFG)" == ""
+CFG=liblwres - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to liblwres - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "liblwres - Win32 Release" && "$(CFG)" != "liblwres - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "liblwres.mak" CFG="liblwres - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "liblwres - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "liblwres - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\liblwres.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\context.obj"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\gai_strerror.obj"
+ -@erase "$(INTDIR)\getaddrinfo.obj"
+ -@erase "$(INTDIR)\gethost.obj"
+ -@erase "$(INTDIR)\getipnode.obj"
+ -@erase "$(INTDIR)\getnameinfo.obj"
+ -@erase "$(INTDIR)\getrrset.obj"
+ -@erase "$(INTDIR)\herror.obj"
+ -@erase "$(INTDIR)\lwbuffer.obj"
+ -@erase "$(INTDIR)\lwconfig.obj"
+ -@erase "$(INTDIR)\lwinetaton.obj"
+ -@erase "$(INTDIR)\lwinetntop.obj"
+ -@erase "$(INTDIR)\lwinetpton.obj"
+ -@erase "$(INTDIR)\lwpacket.obj"
+ -@erase "$(INTDIR)\lwres_gabn.obj"
+ -@erase "$(INTDIR)\lwres_gnba.obj"
+ -@erase "$(INTDIR)\lwres_grbn.obj"
+ -@erase "$(INTDIR)\lwres_noop.obj"
+ -@erase "$(INTDIR)\lwresutil.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\socket.obj"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(OUTDIR)\liblwres.exp"
+ -@erase "$(OUTDIR)\liblwres.lib"
+ -@erase "..\..\..\Build\Release\liblwres.dll"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "./" /I "../../../lib/lwres/win32/include/lwres" /I "include" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../..../lib/dns/sec/openssl/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBLWRES_EXPORTS" /Fp"$(INTDIR)\liblwres.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\liblwres.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib iphlpapi.lib /nologo /dll /incremental:no /pdb:"$(OUTDIR)\liblwres.pdb" /machine:I386 /def:".\liblwres.def" /out:"../../../Build/Release/liblwres.dll" /implib:"$(OUTDIR)\liblwres.lib"
+DEF_FILE= \
+ ".\liblwres.def"
+LINK32_OBJS= \
+ "$(INTDIR)\context.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\gai_strerror.obj" \
+ "$(INTDIR)\getaddrinfo.obj" \
+ "$(INTDIR)\gethost.obj" \
+ "$(INTDIR)\getipnode.obj" \
+ "$(INTDIR)\getnameinfo.obj" \
+ "$(INTDIR)\getrrset.obj" \
+ "$(INTDIR)\herror.obj" \
+ "$(INTDIR)\lwbuffer.obj" \
+ "$(INTDIR)\lwinetaton.obj" \
+ "$(INTDIR)\lwinetntop.obj" \
+ "$(INTDIR)\lwinetpton.obj" \
+ "$(INTDIR)\lwpacket.obj" \
+ "$(INTDIR)\lwres_gabn.obj" \
+ "$(INTDIR)\lwres_gnba.obj" \
+ "$(INTDIR)\lwres_grbn.obj" \
+ "$(INTDIR)\lwres_noop.obj" \
+ "$(INTDIR)\lwresutil.obj" \
+ "$(INTDIR)\socket.obj" \
+ "$(INTDIR)\version.obj" \
+ "$(INTDIR)\lwconfig.obj"
+
+"..\..\..\Build\Release\liblwres.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\liblwres.dll" "$(OUTDIR)\liblwres.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\context.obj"
+ -@erase "$(INTDIR)\context.sbr"
+ -@erase "$(INTDIR)\DLLMain.obj"
+ -@erase "$(INTDIR)\DLLMain.sbr"
+ -@erase "$(INTDIR)\gai_strerror.obj"
+ -@erase "$(INTDIR)\gai_strerror.sbr"
+ -@erase "$(INTDIR)\getaddrinfo.obj"
+ -@erase "$(INTDIR)\getaddrinfo.sbr"
+ -@erase "$(INTDIR)\gethost.obj"
+ -@erase "$(INTDIR)\gethost.sbr"
+ -@erase "$(INTDIR)\getipnode.obj"
+ -@erase "$(INTDIR)\getipnode.sbr"
+ -@erase "$(INTDIR)\getnameinfo.obj"
+ -@erase "$(INTDIR)\getnameinfo.sbr"
+ -@erase "$(INTDIR)\getrrset.obj"
+ -@erase "$(INTDIR)\getrrset.sbr"
+ -@erase "$(INTDIR)\herror.obj"
+ -@erase "$(INTDIR)\herror.sbr"
+ -@erase "$(INTDIR)\lwbuffer.obj"
+ -@erase "$(INTDIR)\lwbuffer.sbr"
+ -@erase "$(INTDIR)\lwconfig.obj"
+ -@erase "$(INTDIR)\lwconfig.sbr"
+ -@erase "$(INTDIR)\lwinetaton.obj"
+ -@erase "$(INTDIR)\lwinetaton.sbr"
+ -@erase "$(INTDIR)\lwinetntop.obj"
+ -@erase "$(INTDIR)\lwinetntop.sbr"
+ -@erase "$(INTDIR)\lwinetpton.obj"
+ -@erase "$(INTDIR)\lwinetpton.sbr"
+ -@erase "$(INTDIR)\lwpacket.obj"
+ -@erase "$(INTDIR)\lwpacket.sbr"
+ -@erase "$(INTDIR)\lwres_gabn.obj"
+ -@erase "$(INTDIR)\lwres_gabn.sbr"
+ -@erase "$(INTDIR)\lwres_gnba.obj"
+ -@erase "$(INTDIR)\lwres_gnba.sbr"
+ -@erase "$(INTDIR)\lwres_grbn.obj"
+ -@erase "$(INTDIR)\lwres_grbn.sbr"
+ -@erase "$(INTDIR)\lwres_noop.obj"
+ -@erase "$(INTDIR)\lwres_noop.sbr"
+ -@erase "$(INTDIR)\lwresutil.obj"
+ -@erase "$(INTDIR)\lwresutil.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(INTDIR)\socket.obj"
+ -@erase "$(INTDIR)\socket.sbr"
+ -@erase "$(INTDIR)\version.obj"
+ -@erase "$(INTDIR)\version.sbr"
+ -@erase "$(OUTDIR)\liblwres.bsc"
+ -@erase "$(OUTDIR)\liblwres.exp"
+ -@erase "$(OUTDIR)\liblwres.lib"
+ -@erase "$(OUTDIR)\liblwres.pdb"
+ -@erase "..\..\..\Build\Debug\liblwres.dll"
+ -@erase "..\..\..\Build\Debug\liblwres.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../lib/lwres/win32/include/lwres" /I "include" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/dns/win32/include" /I "../../../lib/dns/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../..../lib/dns/sec/openssl/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /D "_USRDLL" /D "USE_MD5" /D "OPENSSL" /D "DST_USE_PRIVATE_OPENSSL" /D "LIBLWRES_EXPORTS" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\liblwres.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\liblwres.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\context.sbr" \
+ "$(INTDIR)\DLLMain.sbr" \
+ "$(INTDIR)\gai_strerror.sbr" \
+ "$(INTDIR)\getaddrinfo.sbr" \
+ "$(INTDIR)\gethost.sbr" \
+ "$(INTDIR)\getipnode.sbr" \
+ "$(INTDIR)\getnameinfo.sbr" \
+ "$(INTDIR)\getrrset.sbr" \
+ "$(INTDIR)\herror.sbr" \
+ "$(INTDIR)\lwbuffer.sbr" \
+ "$(INTDIR)\lwinetaton.sbr" \
+ "$(INTDIR)\lwinetntop.sbr" \
+ "$(INTDIR)\lwinetpton.sbr" \
+ "$(INTDIR)\lwpacket.sbr" \
+ "$(INTDIR)\lwres_gabn.sbr" \
+ "$(INTDIR)\lwres_gnba.sbr" \
+ "$(INTDIR)\lwres_grbn.sbr" \
+ "$(INTDIR)\lwres_noop.sbr" \
+ "$(INTDIR)\lwresutil.sbr" \
+ "$(INTDIR)\socket.sbr" \
+ "$(INTDIR)\version.sbr" \
+ "$(INTDIR)\lwconfig.sbr"
+
+"$(OUTDIR)\liblwres.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib iphlpapi.lib /nologo /dll /incremental:yes /pdb:"$(OUTDIR)\liblwres.pdb" /debug /machine:I386 /def:".\liblwres.def" /out:"../../../Build/Debug/liblwres.dll" /implib:"$(OUTDIR)\liblwres.lib" /pdbtype:sept
+DEF_FILE= \
+ ".\liblwres.def"
+LINK32_OBJS= \
+ "$(INTDIR)\context.obj" \
+ "$(INTDIR)\DLLMain.obj" \
+ "$(INTDIR)\gai_strerror.obj" \
+ "$(INTDIR)\getaddrinfo.obj" \
+ "$(INTDIR)\gethost.obj" \
+ "$(INTDIR)\getipnode.obj" \
+ "$(INTDIR)\getnameinfo.obj" \
+ "$(INTDIR)\getrrset.obj" \
+ "$(INTDIR)\herror.obj" \
+ "$(INTDIR)\lwbuffer.obj" \
+ "$(INTDIR)\lwinetaton.obj" \
+ "$(INTDIR)\lwinetntop.obj" \
+ "$(INTDIR)\lwinetpton.obj" \
+ "$(INTDIR)\lwpacket.obj" \
+ "$(INTDIR)\lwres_gabn.obj" \
+ "$(INTDIR)\lwres_gnba.obj" \
+ "$(INTDIR)\lwres_grbn.obj" \
+ "$(INTDIR)\lwres_noop.obj" \
+ "$(INTDIR)\lwresutil.obj" \
+ "$(INTDIR)\socket.obj" \
+ "$(INTDIR)\version.obj" \
+ "$(INTDIR)\lwconfig.obj"
+
+"..\..\..\Build\Debug\liblwres.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("liblwres.dep")
+!INCLUDE "liblwres.dep"
+!ELSE
+!MESSAGE Warning: cannot find "liblwres.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "liblwres - Win32 Release" || "$(CFG)" == "liblwres - Win32 Debug"
+SOURCE=..\context.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\context.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\context.obj" "$(INTDIR)\context.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\DLLMain.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\DLLMain.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\DLLMain.obj" "$(INTDIR)\DLLMain.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\gai_strerror.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\gai_strerror.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\gai_strerror.obj" "$(INTDIR)\gai_strerror.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\getaddrinfo.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\getaddrinfo.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\getaddrinfo.obj" "$(INTDIR)\getaddrinfo.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\gethost.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\gethost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\gethost.obj" "$(INTDIR)\gethost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\getipnode.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\getipnode.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\getipnode.obj" "$(INTDIR)\getipnode.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\getnameinfo.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\getnameinfo.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\getnameinfo.obj" "$(INTDIR)\getnameinfo.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\getrrset.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\getrrset.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\getrrset.obj" "$(INTDIR)\getrrset.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\herror.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\herror.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\herror.obj" "$(INTDIR)\herror.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwbuffer.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwbuffer.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwbuffer.obj" "$(INTDIR)\lwbuffer.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\lwconfig.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwconfig.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwconfig.obj" "$(INTDIR)\lwconfig.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=..\lwinetaton.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwinetaton.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwinetaton.obj" "$(INTDIR)\lwinetaton.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwinetntop.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwinetntop.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwinetntop.obj" "$(INTDIR)\lwinetntop.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwinetpton.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwinetpton.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwinetpton.obj" "$(INTDIR)\lwinetpton.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwpacket.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwpacket.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwpacket.obj" "$(INTDIR)\lwpacket.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwres_gabn.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwres_gabn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwres_gabn.obj" "$(INTDIR)\lwres_gabn.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwres_gnba.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwres_gnba.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwres_gnba.obj" "$(INTDIR)\lwres_gnba.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwres_grbn.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwres_grbn.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwres_grbn.obj" "$(INTDIR)\lwres_grbn.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwres_noop.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwres_noop.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwres_noop.obj" "$(INTDIR)\lwres_noop.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\lwresutil.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\lwresutil.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\lwresutil.obj" "$(INTDIR)\lwresutil.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=.\socket.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\socket.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\socket.obj" "$(INTDIR)\socket.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\version.c
+
+!IF "$(CFG)" == "liblwres - Win32 Release"
+
+
+"$(INTDIR)\version.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "liblwres - Win32 Debug"
+
+
+"$(INTDIR)\version.obj" "$(INTDIR)\version.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/lib/lwres/win32/lwconfig.c b/lib/lwres/win32/lwconfig.c
new file mode 100644
index 0000000..c6fb633
--- /dev/null
+++ b/lib/lwres/win32/lwconfig.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2002 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: lwconfig.c,v 1.7 2007/12/14 01:40:42 marka Exp $ */
+
+/*
+ * We do this so that we may incorporate everything in the main routines
+ * so that we can take advantage of the fixes and changes made there
+ * without having to add them twice. We can then call the parse routine
+ * if there is a resolv.conf file and fetch our own data from the
+ * Windows environment otherwise.
+ */
+
+/*
+ * Note that on Win32 there is normally no resolv.conf since all information
+ * is stored in the registry. Therefore there is no ordering like the
+ * contents of resolv.conf. Since the "search" or "domain" keyword, on
+ * Win32 if a search list is found it is used, otherwise the domain name
+ * is used since they are mutually exclusive. The search list can be entered
+ * in the DNS tab of the "Advanced TCP/IP settings" window under the same place
+ * that you add your nameserver list.
+ */
+
+#define lwres_conf_parse generic_lwres_conf_parse
+#include "../lwconfig.c"
+#undef lwres_conf_parse
+
+#include <iphlpapi.h>
+
+#define TCPIP_SUBKEY \
+ "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters"
+
+void
+get_win32_searchlist(lwres_context_t *ctx) {
+ HKEY hKey;
+ BOOL keyFound = TRUE;
+ char searchlist[MAX_PATH];
+ DWORD searchlen = MAX_PATH;
+ char *cp;
+ lwres_conf_t *confdata;
+
+ REQUIRE(ctx != NULL);
+ confdata = &ctx->confdata;
+
+ memset(searchlist, 0, MAX_PATH);
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TCPIP_SUBKEY, 0, KEY_READ, &hKey)
+ != ERROR_SUCCESS)
+ keyFound = FALSE;
+
+ if (keyFound == TRUE) {
+ /* Get the named directory */
+ if (RegQueryValueEx(hKey, "SearchList", NULL, NULL,
+ (LPBYTE)searchlist, &searchlen) != ERROR_SUCCESS)
+ keyFound = FALSE;
+ RegCloseKey(hKey);
+ }
+
+ confdata->searchnxt = 0;
+ cp = strtok((char *)searchlist, ", \0");
+ while (cp != NULL) {
+ if (confdata->searchnxt == LWRES_CONFMAXSEARCH)
+ break;
+ if (strlen(cp) <= MAX_PATH && strlen(cp) > 0) {
+ confdata->search[confdata->searchnxt] = lwres_strdup(ctx, cp);
+ if (confdata->search[confdata->searchnxt] != NULL)
+ confdata->searchnxt++;
+ }
+ cp = strtok(NULL, ", \0");
+ }
+}
+
+lwres_result_t
+lwres_conf_parse(lwres_context_t *ctx, const char *filename) {
+ lwres_result_t ret = LWRES_R_SUCCESS;
+ lwres_result_t res;
+ lwres_conf_t *confdata;
+ FIXED_INFO * FixedInfo;
+ ULONG BufLen = sizeof(FIXED_INFO);
+ DWORD dwRetVal;
+ IP_ADDR_STRING *pIPAddr;
+
+ REQUIRE(ctx != NULL);
+ confdata = &ctx->confdata;
+ REQUIRE(confdata != NULL);
+
+ /* Use the resolver if there is one */
+ ret = generic_lwres_conf_parse(ctx, filename);
+ if ((ret != LWRES_R_NOTFOUND && ret != LWRES_R_SUCCESS) ||
+ (ret == LWRES_R_SUCCESS && confdata->nsnext > 0))
+ return (ret);
+
+ /*
+ * We didn't get any nameservers so we need to do this ourselves
+ */
+ FixedInfo = (FIXED_INFO *) GlobalAlloc(GPTR, BufLen);
+ dwRetVal = GetNetworkParams(FixedInfo, &BufLen);
+ if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
+ GlobalFree(FixedInfo);
+ FixedInfo = GlobalAlloc(GPTR, BufLen);
+ dwRetVal = GetNetworkParams(FixedInfo, &BufLen);
+ }
+ if (dwRetVal != ERROR_SUCCESS) {
+ GlobalFree(FixedInfo);
+ return (LWRES_R_FAILURE);
+ }
+
+ /* Get the search list from the registry */
+ get_win32_searchlist(ctx);
+
+ /* Use only if there is no search list */
+ if (confdata->searchnxt == 0 && strlen(FixedInfo->DomainName) > 0) {
+ confdata->domainname = lwres_strdup(ctx, FixedInfo->DomainName);
+ if (confdata->domainname == NULL) {
+ GlobalFree(FixedInfo);
+ return (LWRES_R_FAILURE);
+ }
+ } else
+ confdata->domainname = NULL;
+
+ /* Get the list of nameservers */
+ pIPAddr = &FixedInfo->DnsServerList;
+ while (pIPAddr) {
+ if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
+ break;
+
+ res = lwres_create_addr(pIPAddr->IpAddress.String,
+ &confdata->nameservers[confdata->nsnext++], 1);
+ if (res != LWRES_R_SUCCESS) {
+ GlobalFree(FixedInfo);
+ return (res);
+ }
+ pIPAddr = pIPAddr ->Next;
+ }
+
+ GlobalFree(FixedInfo);
+ return (LWRES_R_SUCCESS);
+}
diff --git a/lib/lwres/win32/socket.c b/lib/lwres/win32/socket.c
new file mode 100644
index 0000000..8f6c79a
--- /dev/null
+++ b/lib/lwres/win32/socket.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2007 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.c,v 1.3 2007/06/18 23:47:51 tbox Exp $ */
+
+#include <stdio.h>
+#include <lwres/platform.h>
+#include <Winsock2.h>
+
+void
+InitSockets(void) {
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+
+ wVersionRequested = MAKEWORD(2, 0);
+
+ err = WSAStartup( wVersionRequested, &wsaData );
+ if (err != 0) {
+ fprintf(stderr, "WSAStartup() failed: %d\n", err);
+ exit(1);
+ }
+}
+
+void
+DestroySockets(void) {
+ WSACleanup();
+}
diff --git a/lib/lwres/win32/version.c b/lib/lwres/win32/version.c
new file mode 100644
index 0000000..3c06c6a
--- /dev/null
+++ b/lib/lwres/win32/version.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-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: version.c,v 1.6 2007/06/19 23:47:23 tbox Exp $ */
+
+#include <versions.h>
+
+#include <lwres/version.h>
+
+LIBLWRES_EXTERNAL_DATA const char lwres_version[] = VERSION;
+
+LIBLWRES_EXTERNAL_DATA const unsigned int lwres_libinterface = LIBINTERFACE;
+LIBLWRES_EXTERNAL_DATA const unsigned int lwres_librevision = LIBREVISION;
+LIBLWRES_EXTERNAL_DATA const unsigned int lwres_libage = LIBAGE;
diff --git a/lib/tests/Makefile.in b/lib/tests/Makefile.in
new file mode 100644
index 0000000..81b0bfb
--- /dev/null
+++ b/lib/tests/Makefile.in
@@ -0,0 +1,56 @@
+# Copyright (C) 2004, 2007 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
+# 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.25 2007/06/19 23:47:23 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${TEST_INCLUDES}
+CDEFINES =
+CWARNINGS =
+
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCCCLIBS = ../../lib/isccc/libisccc.@A@
+
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCCCDEPLIBS = libisccc.@A@
+
+OBJS = t_api.@O@
+
+SRCS = t_api.c
+
+SUBDIRS = include
+TARGETS = timestamp
+
+@BIND9_MAKE_RULES@
+
+libt_api.@SA@: ${OBJS}
+ ${AR} ${ARFLAGS} $@ ${OBJS}
+ ${RANLIB} $@
+
+libt_api.la: ${OBJS}
+ ${LIBTOOL_MODE_LINK} \
+ ${CC} ${ALL_CFLAGS} ${LDFLAGS} -o libt_api.la -rpath ${libdir} \
+ ${OBJS} ${ISCLIBS} ${LIBS} @LIBTOOL_ALLOW_UNDEFINED@ @LIBTOOL_IN_MAIN@
+
+timestamp: libt_api.@A@
+ touch timestamp
+
+clean distclean::
+ rm -f t_api.@O@ libt_api.@A@ timestamp
diff --git a/lib/tests/T_testlist.imp b/lib/tests/T_testlist.imp
new file mode 100644
index 0000000..722caff
--- /dev/null
+++ b/lib/tests/T_testlist.imp
@@ -0,0 +1,3 @@
+#! .
+
+T_testlist
diff --git a/lib/tests/include/Makefile.in b/lib/tests/include/Makefile.in
new file mode 100644
index 0000000..10eeded
--- /dev/null
+++ b/lib/tests/include/Makefile.in
@@ -0,0 +1,25 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.11 2007/06/19 23:47:24 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS = tests
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/tests/include/tests/Makefile.in b/lib/tests/include/tests/Makefile.in
new file mode 100644
index 0000000..5d6ad0f
--- /dev/null
+++ b/lib/tests/include/tests/Makefile.in
@@ -0,0 +1,27 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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.9 2007/06/19 23:47:24 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+SUBDIRS =
+TARGETS =
+
+@BIND9_MAKE_RULES@
diff --git a/lib/tests/include/tests/t_api.h b/lib/tests/include/tests/t_api.h
new file mode 100644
index 0000000..b1769e3
--- /dev/null
+++ b/lib/tests/include/tests/t_api.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1999-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: t_api.h,v 1.22 2007/06/19 23:47:24 tbox Exp $ */
+
+#ifndef TESTS_T_API_H
+#define TESTS_T_API_H 1
+
+/*! \file tests/t_api.h */
+
+#include <stdio.h>
+
+#include <isc/lang.h>
+#include <isc/result.h>
+#include <isc/formatcheck.h>
+
+/*
+ *
+ * Result codes.
+ *
+ */
+
+#define T_PASS 0x1
+#define T_FAIL 0x2
+#define T_UNRESOLVED 0x3
+#define T_UNSUPPORTED 0x4
+#define T_UNTESTED 0x5
+#define T_THREADONLY 0x6
+
+/*
+ *
+ * Assertion class codes.
+ *
+ */
+
+#define T_OPTIONAL 0x0
+#define T_REQUIRED 0x1
+
+/*
+ * Misc
+ */
+
+#define T_MAXTOKS 16
+#define T_ARG(n) (*(av + (n)))
+
+typedef void (*PFV)(void);
+
+typedef struct {
+ PFV pfv;
+ const char *func_name;
+} testspec_t;
+
+extern int T_debug;
+extern testspec_t T_testlist[];
+
+ISC_LANG_BEGINDECLS
+
+void
+t_assert(const char *component, int anum, int class, const char *what, ...)
+ ISC_FORMAT_PRINTF(4, 5);
+
+void
+t_info(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+t_result(int result);
+
+char *
+t_getenv(const char *name);
+
+char *
+t_fgetbs(FILE *fp);
+
+isc_result_t
+t_dns_result_fromtext(char *result);
+
+unsigned int
+t_dc_method_fromtext(char *dc_method);
+
+int
+t_bustline(char *line, char **toks);
+
+int
+t_eval(const char *filename, int (*func)(char **), int nargs);
+
+ISC_LANG_ENDDECLS
+
+#endif /* TESTS_T_API_H */
+
diff --git a/lib/tests/t_api.c b/lib/tests/t_api.c
new file mode 100644
index 0000000..09cea48
--- /dev/null
+++ b/lib/tests/t_api.c
@@ -0,0 +1,801 @@
+/*
+ * 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
+ * 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: t_api.c,v 1.63 2008/01/18 23:46:58 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <sys/wait.h>
+
+#include <isc/boolean.h>
+#include <isc/commandline.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/mem.h>
+
+#include <dns/compress.h>
+#include <dns/result.h>
+
+#include "include/tests/t_api.h"
+
+static const char *Usage =
+ "\t-a : run all tests\n"
+ "\t-b <dir> : chdir to dir before running tests"
+ "\t-c <config_file> : use specified config file\n"
+ "\t-d <debug_level> : set debug level to debug_level\n"
+ "\t-h : print test info\n"
+ "\t-u : print usage info\n"
+ "\t-n <test_name> : run specified test name\n"
+ "\t-t <test_number> : run specified test number\n"
+ "\t-x : don't execute tests in a subproc\n"
+ "\t-q <timeout> : use 'timeout' as the timeout value\n";
+/*!<
+ * -a --> run all tests
+ * -b dir --> chdir to dir before running tests
+ * -c config --> use config file 'config'
+ * -d --> turn on api debugging
+ * -h --> print out available test names
+ * -u --> print usage info
+ * -n name --> run test named name
+ * -tn --> run test n
+ * -x --> don't execute testcases in a subproc
+ * -q timeout --> use 'timeout' as the timeout value
+ */
+
+#define T_MAXTESTS 256 /*% must be 0 mod 8 */
+#define T_MAXENV 256
+#define T_DEFAULT_CONFIG "t_config"
+#define T_BUFSIZ 256
+#define T_BIGBUF 4096
+
+#define T_TCTOUT 60
+
+int T_debug;
+int T_timeout;
+pid_t T_pid;
+static const char * T_config;
+static char T_tvec[T_MAXTESTS / 8];
+static char * T_env[T_MAXENV + 1];
+static char T_buf[T_BIGBUF];
+static char * T_dir;
+
+static int
+t_initconf(const char *path);
+
+static int
+t_dumpconf(const char *path);
+
+static int
+t_putinfo(const char *key, const char *info);
+
+static char *
+t_getdate(char *buf, size_t buflen);
+
+static void
+printhelp(void);
+
+static void
+printusage(void);
+
+static int T_int;
+
+static void
+t_sighandler(int sig) {
+ T_int = sig;
+}
+
+int
+main(int argc, char **argv) {
+ int c;
+ int tnum;
+ int subprocs;
+ pid_t deadpid;
+ int status;
+ int len;
+ isc_boolean_t first;
+ testspec_t *pts;
+ struct sigaction sa;
+
+ isc_mem_debugging = ISC_MEM_DEBUGRECORD;
+ first = ISC_TRUE;
+ subprocs = 1;
+ T_timeout = T_TCTOUT;
+
+ /*
+ * -a option is now default.
+ */
+ memset(T_tvec, 0xff, sizeof(T_tvec));
+
+ /*
+ * Parse args.
+ */
+ while ((c = isc_commandline_parse(argc, argv, ":at:c:d:n:huxq:b:"))
+ != -1) {
+ if (c == 'a') {
+ /*
+ * Flag all tests to be run.
+ */
+ memset(T_tvec, 0xff, sizeof(T_tvec));
+ }
+ else if (c == 'b') {
+ T_dir = isc_commandline_argument;
+ }
+ else if (c == 't') {
+ tnum = atoi(isc_commandline_argument);
+ if ((tnum > 0) && (tnum < T_MAXTESTS)) {
+ if (first) {
+ /*
+ * Turn off effect of -a default
+ * and allow multiple -t and -n
+ * options.
+ */
+ memset(T_tvec, 0, sizeof(T_tvec));
+ first = ISC_FALSE;
+ }
+ /*
+ * Flag test tnum to be run.
+ */
+ tnum -= 1;
+ T_tvec[tnum / 8] |= (0x01 << (tnum % 8));
+ }
+ }
+ else if (c == 'c') {
+ T_config = isc_commandline_argument;
+ }
+ else if (c == 'd') {
+ T_debug = atoi(isc_commandline_argument);
+ }
+ else if (c == 'n') {
+ pts = &T_testlist[0];
+ tnum = 0;
+ while (pts->pfv != NULL) {
+ if (! strcmp(pts->func_name,
+ isc_commandline_argument)) {
+ if (first) {
+ memset(T_tvec, 0,
+ sizeof(T_tvec));
+ first = ISC_FALSE;
+ }
+ T_tvec[tnum/8] |= (0x01 << (tnum%8));
+ break;
+ }
+ ++pts;
+ ++tnum;
+ }
+ if (pts->pfv == NULL) {
+ fprintf(stderr, "no such test %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ }
+ else if (c == 'h') {
+ printhelp();
+ exit(0);
+ }
+ else if (c == 'u') {
+ printusage();
+ exit(0);
+ }
+ else if (c == 'x') {
+ subprocs = 0;
+ }
+ else if (c == 'q') {
+ T_timeout = atoi(isc_commandline_argument);
+ }
+ else if (c == ':') {
+ fprintf(stderr, "Option -%c requires an argument\n",
+ isc_commandline_option);
+ exit(1);
+ }
+ else if (c == '?') {
+ fprintf(stderr, "Unrecognized option -%c\n",
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+
+ /*
+ * Set cwd.
+ */
+
+ if (T_dir != NULL)
+ (void) chdir(T_dir);
+
+ /*
+ * We don't want buffered output.
+ */
+
+ (void)setbuf(stdout, NULL);
+ (void)setbuf(stderr, NULL);
+
+ /*
+ * Setup signals.
+ */
+
+ sa.sa_flags = 0;
+ sigfillset(&sa.sa_mask);
+
+#ifdef SIGCHLD
+ /*
+ * This is mostly here for NetBSD's pthread implementation, until
+ * people catch up to the latest unproven-pthread package.
+ */
+ sa.sa_handler = SIG_DFL;
+ (void)sigaction(SIGCHLD, &sa, NULL);
+#endif
+
+ sa.sa_handler = t_sighandler;
+ (void)sigaction(SIGINT, &sa, NULL);
+ (void)sigaction(SIGALRM, &sa, NULL);
+
+ /*
+ * Output start stanza to journal.
+ */
+
+ snprintf(T_buf, sizeof(T_buf), "%s:", argv[0]);
+ len = strlen(T_buf);
+ (void) t_getdate(T_buf + len, T_BIGBUF - len);
+ t_putinfo("S", T_buf);
+
+ /*
+ * Setup the test environment using the config file.
+ */
+
+ if (T_config == NULL)
+ T_config = T_DEFAULT_CONFIG;
+
+ t_initconf(T_config);
+ if (T_debug)
+ t_dumpconf(T_config);
+
+ /*
+ * Now invoke all the test cases.
+ */
+
+ tnum = 0;
+ pts = &T_testlist[0];
+ while (*pts->pfv != NULL) {
+ if (T_tvec[tnum / 8] & (0x01 << (tnum % 8))) {
+ if (subprocs) {
+ T_pid = fork();
+ if (T_pid == 0) {
+ (*pts->pfv)();
+ exit(0);
+ } else if (T_pid > 0) {
+
+ T_int = 0;
+ sa.sa_handler = t_sighandler;
+ (void)sigaction(SIGALRM, &sa, NULL);
+ alarm(T_timeout);
+
+ deadpid = (pid_t) -1;
+ while (deadpid != T_pid) {
+ deadpid =
+ waitpid(T_pid, &status, 0);
+ if (deadpid == T_pid) {
+ if (WIFSIGNALED(status)) {
+ if (WTERMSIG(status) ==
+ SIGTERM)
+ t_info(
+ "the test case timed out\n");
+ else
+ t_info(
+ "the test case caused exception %d\n",
+ WTERMSIG(status));
+ t_result(T_UNRESOLVED);
+ }
+ } else if ((deadpid == -1) &&
+ (errno == EINTR) &&
+ T_int) {
+ kill(T_pid, SIGTERM);
+ T_int = 0;
+ }
+ else if ((deadpid == -1) &&
+ ((errno == ECHILD) ||
+ (errno == ESRCH)))
+ break;
+ }
+
+ alarm(0);
+ sa.sa_handler = SIG_IGN;
+ (void)sigaction(SIGALRM, &sa, NULL);
+ } else {
+ t_info("fork failed, errno == %d\n",
+ errno);
+ t_result(T_UNRESOLVED);
+ }
+ }
+ else {
+ (*pts->pfv)();
+ }
+ }
+ ++pts;
+ ++tnum;
+ }
+
+ snprintf(T_buf, sizeof(T_buf), "%s:", argv[0]);
+ len = strlen(T_buf);
+ (void) t_getdate(T_buf + len, T_BIGBUF - len);
+ t_putinfo("E", T_buf);
+
+ return(0);
+}
+
+void
+t_assert(const char *component, int anum, int class, const char *what, ...) {
+ va_list args;
+
+ (void)printf("T:%s:%d:%s\n", component, anum, class == T_REQUIRED ?
+ "A" : "C");
+
+ /*
+ * Format text to a buffer.
+ */
+ va_start(args, what);
+ (void)vsnprintf(T_buf, sizeof(T_buf), what, args);
+ va_end(args);
+
+ (void)t_putinfo("A", T_buf);
+ (void)printf("\n");
+}
+
+void
+t_info(const char *format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ (void) vsnprintf(T_buf, sizeof(T_buf), format, args);
+ va_end(args);
+ (void) t_putinfo("I", T_buf);
+}
+
+void
+t_result(int result) {
+ const char *p;
+
+ switch (result) {
+ case T_PASS:
+ p = "PASS";
+ break;
+ case T_FAIL:
+ p = "FAIL";
+ break;
+ case T_UNRESOLVED:
+ p = "UNRESOLVED";
+ break;
+ case T_UNSUPPORTED:
+ p = "UNSUPPORTED";
+ break;
+ case T_UNTESTED:
+ p = "UNTESTED";
+ break;
+ case T_THREADONLY:
+ p = "THREADONLY";
+ break;
+ default:
+ p = "UNKNOWN";
+ break;
+ }
+ printf("R:%s\n", p);
+}
+
+char *
+t_getenv(const char *name) {
+ char *n;
+ char **p;
+ size_t len;
+
+ n = NULL;
+ if (name && *name) {
+
+ p = &T_env[0];
+ len = strlen(name);
+
+ while (*p != NULL) {
+ if (strncmp(*p, name, len) == 0) {
+ if ( *(*p + len) == '=') {
+ n = *p + len + 1;
+ break;
+ }
+ }
+ ++p;
+ }
+ }
+ return(n);
+}
+
+/*
+ *
+ * Read in the config file at path, initializing T_env.
+ *
+ * note: no format checking for now ...
+ *
+ */
+
+static int
+t_initconf(const char *path) {
+
+ int n;
+ int rval;
+ char **p;
+ FILE *fp;
+
+ rval = -1;
+
+ fp = fopen(path, "r");
+ if (fp != NULL) {
+ n = 0;
+ p = &T_env[0];
+ while (n < T_MAXENV) {
+ *p = t_fgetbs(fp);
+ if (*p == NULL)
+ break;
+ if ((**p == '#') || (strchr(*p, '=') == NULL)) {
+ /*
+ * Skip comments and other junk.
+ */
+ (void)free(*p);
+ continue;
+ }
+ ++p; ++n;
+ }
+ (void)fclose(fp);
+ rval = 0;
+ }
+
+ return (rval);
+}
+
+/*
+ *
+ * Dump T_env to stdout.
+ *
+ */
+
+static int
+t_dumpconf(const char *path) {
+ int rval;
+ char **p;
+ FILE *fp;
+
+ rval = -1;
+ fp = fopen(path, "r");
+ if (fp != NULL) {
+ p = &T_env[0];
+ while (*p != NULL) {
+ printf("C:%s\n", *p);
+ ++p;
+ }
+ (void) fclose(fp);
+ rval = 0;
+ }
+ return(rval);
+}
+
+/*
+ *
+ * Read a newline or EOF terminated string from fp.
+ * On success:
+ * return a malloc'd buf containing the string with
+ * the newline converted to a '\0'.
+ * On error:
+ * return NULL.
+ *
+ * Caller is responsible for freeing buf.
+ *
+ */
+
+char *
+t_fgetbs(FILE *fp) {
+ int c;
+ size_t n;
+ size_t size;
+ char *buf;
+ char *p;
+
+ n = 0;
+ size = T_BUFSIZ;
+ buf = (char *) malloc(T_BUFSIZ * sizeof(char));
+
+ if (buf != NULL) {
+ p = buf;
+ while ((c = fgetc(fp)) != EOF) {
+
+ if (c == '\n')
+ break;
+
+ *p++ = c;
+ ++n;
+ if ( n >= size ) {
+ size += T_BUFSIZ;
+ buf = (char *)realloc(buf,
+ size * sizeof(char));
+ if (buf == NULL)
+ break;
+ p = buf + n;
+ }
+ }
+ *p = '\0';
+ if (c == EOF && n == 0U) {
+ free(buf);
+ return (NULL);
+ }
+ return (buf);
+ } else {
+ fprintf(stderr, "malloc failed %d", errno);
+ return(NULL);
+ }
+}
+
+/*
+ *
+ * Put info to log, using key.
+ * For now, just dump it out.
+ * Later format into pretty lines.
+ *
+ */
+
+static int
+t_putinfo(const char *key, const char *info) {
+ int rval;
+
+ /*
+ * For now.
+ */
+ rval = printf("%s:%s", key, info);
+ return(rval);
+}
+
+static char *
+t_getdate(char *buf, size_t buflen) {
+ size_t n;
+ time_t t;
+ struct tm *p;
+
+ t = time(NULL);
+ p = localtime(&t);
+ n = strftime(buf, buflen - 1, "%A %d %B %H:%M:%S %Y\n", p);
+ return(n != 0U ? buf : NULL);
+}
+
+/*
+ * Some generally used utilities.
+ */
+struct dns_errormap {
+ isc_result_t result;
+ const char *text;
+} dns_errormap[] = {
+ { ISC_R_SUCCESS, "ISC_R_SUCCESS" },
+ { ISC_R_EXISTS, "ISC_R_EXISTS" },
+ { ISC_R_NOTFOUND, "ISC_R_NOTFOUND" },
+ { ISC_R_NOSPACE, "ISC_R_NOSPACE" },
+ { ISC_R_UNEXPECTED, "ISC_R_UNEXPECTED" },
+ { ISC_R_UNEXPECTEDEND, "ISC_R_UNEXPECTEDEND" },
+ { ISC_R_RANGE, "ISC_R_RANGE" },
+ { DNS_R_LABELTOOLONG, "DNS_R_LABELTOOLONG" },
+ { DNS_R_BADESCAPE, "DNS_R_BADESCAPE" },
+ /* { DNS_R_BADBITSTRING, "DNS_R_BADBITSTRING" }, */
+ /* { DNS_R_BITSTRINGTOOLONG, "DNS_R_BITSTRINGTOOLONG"}, */
+ { DNS_R_EMPTYLABEL, "DNS_R_EMPTYLABEL" },
+ { DNS_R_BADDOTTEDQUAD, "DNS_R_BADDOTTEDQUAD" },
+ { DNS_R_UNKNOWN, "DNS_R_UNKNOWN" },
+ { DNS_R_BADLABELTYPE, "DNS_R_BADLABELTYPE" },
+ { DNS_R_BADPOINTER, "DNS_R_BADPOINTER" },
+ { DNS_R_TOOMANYHOPS, "DNS_R_TOOMANYHOPS" },
+ { DNS_R_DISALLOWED, "DNS_R_DISALLOWED" },
+ { DNS_R_EXTRATOKEN, "DNS_R_EXTRATOKEN" },
+ { DNS_R_EXTRADATA, "DNS_R_EXTRADATA" },
+ { DNS_R_TEXTTOOLONG, "DNS_R_TEXTTOOLONG" },
+ { DNS_R_SYNTAX, "DNS_R_SYNTAX" },
+ { DNS_R_BADCKSUM, "DNS_R_BADCKSUM" },
+ { DNS_R_BADAAAA, "DNS_R_BADAAAA" },
+ { DNS_R_NOOWNER, "DNS_R_NOOWNER" },
+ { DNS_R_NOTTL, "DNS_R_NOTTL" },
+ { DNS_R_BADCLASS, "DNS_R_BADCLASS" },
+ { DNS_R_PARTIALMATCH, "DNS_R_PARTIALMATCH" },
+ { DNS_R_NEWORIGIN, "DNS_R_NEWORIGIN" },
+ { DNS_R_UNCHANGED, "DNS_R_UNCHANGED" },
+ { DNS_R_BADTTL, "DNS_R_BADTTL" },
+ { DNS_R_NOREDATA, "DNS_R_NOREDATA" },
+ { DNS_R_CONTINUE, "DNS_R_CONTINUE" },
+ { DNS_R_DELEGATION, "DNS_R_DELEGATION" },
+ { DNS_R_GLUE, "DNS_R_GLUE" },
+ { DNS_R_DNAME, "DNS_R_DNAME" },
+ { DNS_R_CNAME, "DNS_R_CNAME" },
+ { DNS_R_NXDOMAIN, "DNS_R_NXDOMAIN" },
+ { DNS_R_NXRRSET, "DNS_R_NXRRSET" },
+ { DNS_R_BADDB, "DNS_R_BADDB" },
+ { DNS_R_ZONECUT, "DNS_R_ZONECUT" },
+ { DNS_R_NOTZONETOP, "DNS_R_NOTZONETOP" },
+ { DNS_R_SEENINCLUDE, "DNS_R_SEENINCLUDE" },
+ { DNS_R_SINGLETON, "DNS_R_SINGLETON" },
+ { (isc_result_t)0, NULL }
+};
+
+isc_result_t
+t_dns_result_fromtext(char *name) {
+
+ isc_result_t result;
+ struct dns_errormap *pmap;
+
+ result = ISC_R_UNEXPECTED;
+
+ pmap = dns_errormap;
+ while (pmap->text != NULL) {
+ if (strcmp(name, pmap->text) == 0)
+ break;
+ ++pmap;
+ }
+
+ if (pmap->text != NULL)
+ result = pmap->result;
+
+ return (result);
+}
+
+struct dc_method_map {
+ unsigned int dc_method;
+ const char *text;
+} dc_method_map[] = {
+
+ { DNS_COMPRESS_NONE, "DNS_COMPRESS_NONE" },
+ { DNS_COMPRESS_GLOBAL14, "DNS_COMPRESS_GLOBAL14" },
+ { DNS_COMPRESS_ALL, "DNS_COMPRESS_ALL" },
+ { 0, NULL }
+};
+
+unsigned int
+t_dc_method_fromtext(char *name) {
+ unsigned int dc_method;
+ struct dc_method_map *pmap;
+
+ dc_method = DNS_COMPRESS_NONE;
+
+ pmap = dc_method_map;
+ while (pmap->text != NULL) {
+ if (strcmp(name, pmap->text) == 0)
+ break;
+ ++pmap;
+ }
+
+ if (pmap->text != NULL)
+ dc_method = pmap->dc_method;
+
+ return(dc_method);
+}
+
+int
+t_bustline(char *line, char **toks) {
+ int cnt;
+ char *p;
+
+ cnt = 0;
+ if (line && *line) {
+ while ((p = strtok(line, "\t")) && (cnt < T_MAXTOKS)) {
+ *toks++ = p;
+ line = NULL;
+ ++cnt;
+ }
+ }
+ return(cnt);
+}
+
+static void
+printhelp(void) {
+ int cnt;
+ testspec_t *pts;
+
+ cnt = 1;
+ pts = &T_testlist[0];
+
+ printf("Available tests:\n");
+ while (pts->func_name) {
+ printf("\t%d\t%s\n", cnt, pts->func_name);
+ ++pts;
+ ++cnt;
+ }
+}
+
+static void
+printusage(void) {
+ printf("Usage:\n%s\n", Usage);
+}
+
+int
+t_eval(const char *filename, int (*func)(char **), int nargs) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+ int npass;
+ char *tokens[T_MAXTOKS + 1];
+
+ npass = 0;
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, tokens);
+ if (cnt == nargs) {
+ result = func(tokens);
+ switch (result) {
+ case T_PASS:
+ ++npass;
+ break;
+ case T_FAIL:
+ ++nfails;
+ break;
+ case T_UNTESTED:
+ break;
+ default:
+ ++nprobs;
+ break;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if (nfails == 0 && nprobs == 0 && npass > 0)
+ result = T_PASS;
+ else if (nfails > 0)
+ result = T_FAIL;
+ else if (npass == 0)
+ result = T_UNTESTED;
+
+ return (result);
+}
diff --git a/lib/win32/bindevt/bindevt.c b/lib/win32/bindevt/bindevt.c
new file mode 100644
index 0000000..68d1c55
--- /dev/null
+++ b/lib/win32/bindevt/bindevt.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2004, 2007 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: bindevt.c,v 1.5 2007/06/19 23:47:24 tbox Exp $ */
+
+/*
+ * bindevt.c : Defines the entry point for event log viewer DLL.
+ */
+
+#include <windows.h>
+
+BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call,
+ LPVOID lpReserved)
+{
+ return (TRUE);
+}
+
diff --git a/lib/win32/bindevt/bindevt.dsp b/lib/win32/bindevt/bindevt.dsp
new file mode 100644
index 0000000..6aafb19
--- /dev/null
+++ b/lib/win32/bindevt/bindevt.dsp
@@ -0,0 +1,132 @@
+# Microsoft Developer Studio Project File - Name="bindevt" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=bindevt - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "bindevt.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "bindevt.mak" CFG="bindevt - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "bindevt - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "bindevt - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "bindevt - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BINDEVT_EXPORTS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\include" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BINDEVT_EXPORTS" /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /pdb:none /machine:I386 /out:"..\..\..\Build\Release\bindevt.dll"
+
+!ELSEIF "$(CFG)" == "bindevt - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 1
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BINDEVT_EXPORTS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BINDEVT_EXPORTS" /FR /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /pdb:none /debug /machine:I386 /out:"..\..\..\Build\Debug\bindevt.dll"
+
+!ENDIF
+
+# Begin Target
+
+# Name "bindevt - Win32 Release"
+# Name "bindevt - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\bindevt.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\bindevt.mc
+
+!IF "$(CFG)" == "bindevt - Win32 Release"
+
+# Begin Custom Build
+TargetName=bindevt
+InputPath=.\bindevt.mc
+InputName=bindevt
+
+"$(TargetName).rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ mc $(InputName).mc
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "bindevt - Win32 Debug"
+
+# Begin Custom Build
+TargetName=bindevt
+InputPath=.\bindevt.mc
+InputName=bindevt
+
+"$(TargetName).rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ mc $(InputName).mc
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\bindevt.rc
+# End Source File
+# End Target
+# End Project
diff --git a/lib/win32/bindevt/bindevt.dsw b/lib/win32/bindevt/bindevt.dsw
new file mode 100644
index 0000000..7421804
--- /dev/null
+++ b/lib/win32/bindevt/bindevt.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "bindevt"=.\bindevt.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/lib/win32/bindevt/bindevt.mak b/lib/win32/bindevt/bindevt.mak
new file mode 100644
index 0000000..f0a4ea1
--- /dev/null
+++ b/lib/win32/bindevt/bindevt.mak
@@ -0,0 +1,310 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on bindevt.dsp
+!IF "$(CFG)" == ""
+CFG=bindevt - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to bindevt - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "bindevt - Win32 Release" && "$(CFG)" != "bindevt - Win32 Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "bindevt.mak" CFG="bindevt - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "bindevt - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "bindevt - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "bindevt - Win32 Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "bindevt - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "..\..\..\Build\Release\bindevt.dll"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\bindevt.obj"
+ -@erase "$(INTDIR)\bindevt.res"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(OUTDIR)\bindevt.exp"
+ -@erase "..\..\..\Build\Release\bindevt.dll"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "..\include" /I "..\..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BINDEVT_EXPORTS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\bindevt.res" /d "NDEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\bindevt.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /pdb:none /machine:I386 /out:"..\..\..\Build\Release\bindevt.dll" /implib:"$(OUTDIR)\bindevt.lib"
+LINK32_OBJS= \
+ "$(INTDIR)\bindevt.obj" \
+ "$(INTDIR)\bindevt.res"
+
+"..\..\..\Build\Release\bindevt.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ELSEIF "$(CFG)" == "bindevt - Win32 Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+ALL : "..\..\..\Build\Debug\bindevt.dll" "$(OUTDIR)\bindevt.bsc"
+
+
+CLEAN :
+ -@erase "$(INTDIR)\bindevt.obj"
+ -@erase "$(INTDIR)\bindevt.res"
+ -@erase "$(INTDIR)\bindevt.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\bindevt.bsc"
+ -@erase "$(OUTDIR)\bindevt.exp"
+ -@erase "..\..\..\Build\Debug\bindevt.dll"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BINDEVT_EXPORTS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)\bindevt.res" /d "_DEBUG"
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\bindevt.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\bindevt.sbr"
+
+"$(OUTDIR)\bindevt.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /pdb:none /debug /machine:I386 /out:"..\..\..\Build\Debug\bindevt.dll" /implib:"$(OUTDIR)\bindevt.lib"
+LINK32_OBJS= \
+ "$(INTDIR)\bindevt.obj" \
+ "$(INTDIR)\bindevt.res"
+
+"..\..\..\Build\Debug\bindevt.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_DLL)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("bindevt.dep")
+!INCLUDE "bindevt.dep"
+!ELSE
+!MESSAGE Warning: cannot find "bindevt.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "bindevt - Win32 Release" || "$(CFG)" == "bindevt - Win32 Debug"
+SOURCE=.\bindevt.c
+
+!IF "$(CFG)" == "bindevt - Win32 Release"
+
+
+"$(INTDIR)\bindevt.obj" : $(SOURCE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "bindevt - Win32 Debug"
+
+
+"$(INTDIR)\bindevt.obj" "$(INTDIR)\bindevt.sbr" : $(SOURCE) "$(INTDIR)"
+
+
+!ENDIF
+
+SOURCE=.\bindevt.mc
+
+!IF "$(CFG)" == "bindevt - Win32 Release"
+
+TargetName=bindevt
+InputPath=.\bindevt.mc
+InputName=bindevt
+
+".\bindevt.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ <<tempfile.bat
+ @echo off
+ mc $(InputName).mc
+<<
+
+
+!ELSEIF "$(CFG)" == "bindevt - Win32 Debug"
+
+TargetName=bindevt
+InputPath=.\bindevt.mc
+InputName=bindevt
+
+".\bindevt.rc" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ <<tempfile.bat
+ @echo off
+ mc $(InputName).mc
+<<
+
+
+!ENDIF
+
+SOURCE=.\bindevt.rc
+
+"$(INTDIR)\bindevt.res" : $(SOURCE) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/lib/win32/bindevt/bindevt.mc b/lib/win32/bindevt/bindevt.mc
new file mode 100644
index 0000000..47d13b4
--- /dev/null
+++ b/lib/win32/bindevt/bindevt.mc
@@ -0,0 +1,47 @@
+; 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: bindevt.mc,v 1.4 2007/06/19 23:47:24 tbox Exp $
+
+MessageIdTypedef=DWORD
+
+LanguageNames = (English=0x409:MSG00409)
+
+OutputBase = 16
+
+
+MessageId=0x1
+Severity=Error
+Facility=Application
+SymbolicName=BIND_ERR_MSG
+Language=English
+%1
+.
+
+MessageId=0x2
+Severity=Warning
+Facility=Application
+SymbolicName=BIND_WARN_MSG
+Language=English
+%1
+.
+
+MessageId=0x3
+Severity=Informational
+Facility=Application
+SymbolicName=BIND_INFO_MSG
+Language=English
+%1
+.
diff --git a/libtool.m4 b/libtool.m4
new file mode 100644
index 0000000..551ffd0
--- /dev/null
+++ b/libtool.m4
@@ -0,0 +1,6000 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
+## Free Software Foundation, Inc.
+## Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## As a special exception to the GNU General Public License, if you
+## distribute this file as part of a program that contains a
+## configuration script generated by Autoconf, you may include it under
+## the same distribution terms that you use for the rest of that program.
+
+# serial 47 AC_PROG_LIBTOOL
+
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If this macro is not defined by Autoconf, define it here.
+m4_ifdef([AC_PROVIDE_IFELSE],
+ [],
+ [m4_define([AC_PROVIDE_IFELSE],
+ [m4_ifdef([AC_PROVIDE_$1],
+ [$2], [$3])])])
+
+
+# AC_PROG_LIBTOOL
+# ---------------
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
+dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
+dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
+ AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [AC_LIBTOOL_CXX],
+ [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
+ ])])
+dnl And a similar setup for Fortran 77 support
+ AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [AC_LIBTOOL_F77],
+ [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
+])])
+
+dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
+dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
+dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
+ AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
+ [AC_LIBTOOL_GCJ],
+ [ifdef([AC_PROG_GCJ],
+ [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+ ifdef([A][M_PROG_GCJ],
+ [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+ ifdef([LT_AC_PROG_GCJ],
+ [define([LT_AC_PROG_GCJ],
+ defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
+])])# AC_PROG_LIBTOOL
+
+
+# _AC_PROG_LIBTOOL
+# ----------------
+AC_DEFUN([_AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])# _AC_PROG_LIBTOOL
+
+
+# AC_LIBTOOL_SETUP
+# ----------------
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.50)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+
+AC_LIBTOOL_SYS_MAX_CMD_LEN
+AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+AC_LIBTOOL_OBJDIR
+
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+_LT_AC_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
+
+# Same as above, but do not quote variable references.
+[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+AC_CHECK_TOOL(AR, ar, false)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
+ ;;
+ *)
+ old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ AC_PATH_MAGIC
+ fi
+ ;;
+esac
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE([libtool-lock],
+ [AC_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+AC_ARG_WITH([pic],
+ [AC_HELP_STRING([--with-pic],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [pic_mode="$withval"],
+ [pic_mode=default])
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+AC_LIBTOOL_LANG_C_CONFIG
+_LT_AC_TAGCONFIG
+])# AC_LIBTOOL_SETUP
+
+
+# _LT_AC_SYS_COMPILER
+# -------------------
+AC_DEFUN([_LT_AC_SYS_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_AC_SYS_COMPILER
+
+
+# _LT_AC_SYS_LIBPATH_AIX
+# ----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
+[AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`; fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_AC_SYS_LIBPATH_AIX
+
+
+# _LT_AC_SHELL_INIT(ARG)
+# ----------------------
+AC_DEFUN([_LT_AC_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+ [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+ [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_AC_SHELL_INIT
+
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[_LT_AC_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+ # Remove one level of quotation (which was required for Make).
+ ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+ ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X[$]1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell.
+ exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+[$]*
+EOF
+ exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+ for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+ # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+ if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+ echo_test_string="`eval $cmd`" &&
+ (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+ then
+ break
+ fi
+ done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ :
+else
+ # The Solaris, AIX, and Digital Unix default echo programs unquote
+ # backslashes. This makes it impossible to quote backslashes using
+ # echo "$something" | sed 's/\\/\\\\/g'
+ #
+ # So, first we look for a working echo in the user's PATH.
+
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for dir in $PATH /usr/ucb; do
+ IFS="$lt_save_ifs"
+ if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+ test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$dir/echo"
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ if test "X$echo" = Xecho; then
+ # We didn't find a better echo, so look for alternatives.
+ if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # This shell has a builtin print -r that does the trick.
+ echo='print -r'
+ elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+ test "X$CONFIG_SHELL" != X/bin/ksh; then
+ # If we have ksh, try running configure again with it.
+ ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ export ORIGINAL_CONFIG_SHELL
+ CONFIG_SHELL=/bin/ksh
+ export CONFIG_SHELL
+ exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+ else
+ # Try using printf.
+ echo='printf %s\n'
+ if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+ echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ # Cool, printf works
+ :
+ elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+ export CONFIG_SHELL
+ SHELL="$CONFIG_SHELL"
+ export SHELL
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+ test "X$echo_testing_string" = 'X\t' &&
+ echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+ test "X$echo_testing_string" = "X$echo_test_string"; then
+ echo="$CONFIG_SHELL [$]0 --fallback-echo"
+ else
+ # maybe with a smaller string...
+ prev=:
+
+ for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+ if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+ then
+ break
+ fi
+ prev="$cmd"
+ done
+
+ if test "$prev" != 'sed 50q "[$]0"'; then
+ echo_test_string=`eval $prev`
+ export echo_test_string
+ exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+ else
+ # Oops. We lost completely, so just stick with echo.
+ echo=echo
+ fi
+ fi
+ fi
+ fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+ ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+])])# _LT_AC_PROG_ECHO_BACKSLASH
+
+
+# _LT_AC_LOCK
+# -----------
+AC_DEFUN([_LT_AC_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AC_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case "`/usr/bin/file conftest.o`" in
+ *32-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+ ])
+esac
+
+need_locks="$enable_libtool_lock"
+
+])# _LT_AC_LOCK
+
+
+# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s conftest.err; then
+ $2=yes
+ fi
+ fi
+ $rm conftest*
+])
+
+if test x"[$]$2" = xyes; then
+ ifelse([$5], , :, [$5])
+else
+ ifelse([$6], , :, [$6])
+fi
+])# AC_LIBTOOL_COMPILER_OPTION
+
+
+# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
+[AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $3"
+ printf "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ else
+ $2=yes
+ fi
+ fi
+ $rm conftest*
+ LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+ ifelse([$4], , :, [$4])
+else
+ ifelse([$5], , :, [$5])
+fi
+])# AC_LIBTOOL_LINKER_OPTION
+
+
+# AC_LIBTOOL_SYS_MAX_CMD_LEN
+# --------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
+[# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* )
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for *BSD
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ ;;
+
+ *)
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \
+ = "XX$teststring") >/dev/null 2>&1 &&
+ new_result=`expr "X$teststring" : ".*" 2>&1` &&
+ lt_cv_sys_max_cmd_len=$new_result &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on massive
+ # amounts of additional arguments before passing them to the linker.
+ # It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ ;;
+ esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+])# AC_LIBTOOL_SYS_MAX_CMD_LEN
+
+
+# _LT_AC_CHECK_DLFCN
+# --------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)dnl
+])# _LT_AC_CHECK_DLFCN
+
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ /* dlclose (self); */
+ }
+
+ exit (status);
+}]
+EOF
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_unknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+
+# AC_LIBTOOL_DLOPEN_SELF
+# -------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen="shl_load"],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen="dlopen"],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ LDFLAGS="$LDFLAGS $link_static_flag"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_AC_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+
+# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
+# ---------------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler
+AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $rm -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test ! -s out/conftest.err; then
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w .
+ $rm conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+ $rm out/* && rmdir out
+ cd ..
+ rmdir conftest
+ $rm conftest*
+])
+])# AC_LIBTOOL_PROG_CC_C_O
+
+
+# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
+# -----------------------------------------
+# Check to see if we can do hard links to lock some files if needed
+AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
+[AC_REQUIRE([_LT_AC_LOCK])dnl
+
+hard_links="nottested"
+if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $rm conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test "$hard_links" = no; then
+ AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
+
+
+# AC_LIBTOOL_OBJDIR
+# -----------------
+AC_DEFUN([AC_LIBTOOL_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+])# AC_LIBTOOL_OBJDIR
+
+
+# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
+# ----------------------------------------------
+# Check hardcoding attributes.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_AC_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
+ test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \
+ test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+ # We can hardcode non-existant directories.
+ if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+ test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_AC_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_AC_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
+
+
+# AC_LIBTOOL_SYS_LIB_STRIP
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
+[striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+fi
+])# AC_LIBTOOL_SYS_LIB_STRIP
+
+
+# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
+[AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix4* | aix5*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $rm \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)'
+ # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+ if test "$GCC" = yes; then
+ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+ else
+ sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+ fi
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+kfreebsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+freebsd*)
+ objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ *) # from 3.2 on
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case "$host_cpu" in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`$SED -e 's/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g' /etc/ld.so.conf | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+knetbsd*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='GNU ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+nto-qnx*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+openbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[[89]] | openbsd2.[[89]].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+sco3.2v5*)
+ version_type=osf
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+
+
+# _LT_AC_TAGCONFIG
+# ----------------
+AC_DEFUN([_LT_AC_TAGCONFIG],
+[AC_ARG_WITH([tags],
+ [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
+ [include additional configurations @<:@automatic@:>@])],
+ [tagnames="$withval"])
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+ if test ! -f "${ofile}"; then
+ AC_MSG_WARN([output file `$ofile' does not exist])
+ fi
+
+ if test -z "$LTCC"; then
+ eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+ if test -z "$LTCC"; then
+ AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
+ else
+ AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
+ fi
+ fi
+
+ # Extract list of available tagged configurations in $ofile.
+ # Note that this assumes the entire list is on one line.
+ available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for tagname in $tagnames; do
+ IFS="$lt_save_ifs"
+ # Check whether tagname contains only valid characters
+ case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
+ "") ;;
+ *) AC_MSG_ERROR([invalid tag name: $tagname])
+ ;;
+ esac
+
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+ then
+ AC_MSG_ERROR([tag name \"$tagname\" already exists])
+ fi
+
+ # Update the list of available tags.
+ if test -n "$tagname"; then
+ echo appending configuration tag \"$tagname\" to $ofile
+
+ case $tagname in
+ CXX)
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_LIBTOOL_LANG_CXX_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ F77)
+ if test -n "$F77" && test "X$F77" != "Xno"; then
+ AC_LIBTOOL_LANG_F77_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ GCJ)
+ if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+ AC_LIBTOOL_LANG_GCJ_CONFIG
+ else
+ tagname=""
+ fi
+ ;;
+
+ RC)
+ AC_LIBTOOL_LANG_RC_CONFIG
+ ;;
+
+ *)
+ AC_MSG_ERROR([Unsupported tag name: $tagname])
+ ;;
+ esac
+
+ # Append the new tag name to the list of available tags.
+ if test -n "$tagname" ; then
+ available_tags="$available_tags $tagname"
+ fi
+ fi
+ done
+ IFS="$lt_save_ifs"
+
+ # Now substitute the updated list of available tags.
+ if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+ mv "${ofile}T" "$ofile"
+ chmod +x "$ofile"
+ else
+ rm -f "${ofile}T"
+ AC_MSG_ERROR([unable to update list of available tagged configurations.])
+ fi
+fi
+])# _LT_AC_TAGCONFIG
+
+
+# AC_LIBTOOL_DLOPEN
+# -----------------
+# enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN],
+ [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_DLOPEN
+
+
+# AC_LIBTOOL_WIN32_DLL
+# --------------------
+# declare package support for building win32 dll's
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_WIN32_DLL
+
+
+# AC_ENABLE_SHARED([DEFAULT])
+# ---------------------------
+# implement the --enable-shared flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([shared],
+ [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
+])# AC_ENABLE_SHARED
+
+
+# AC_DISABLE_SHARED
+# -----------------
+#- set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)
+])# AC_DISABLE_SHARED
+
+
+# AC_ENABLE_STATIC([DEFAULT])
+# ---------------------------
+# implement the --enable-static flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([static],
+ [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_static=]AC_ENABLE_STATIC_DEFAULT)
+])# AC_ENABLE_STATIC
+
+
+# AC_DISABLE_STATIC
+# -----------------
+# set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)
+])# AC_DISABLE_STATIC
+
+
+# AC_ENABLE_FAST_INSTALL([DEFAULT])
+# ---------------------------------
+# implement the --enable-fast-install flag
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([fast-install],
+ [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
+])# AC_ENABLE_FAST_INSTALL
+
+
+# AC_DISABLE_FAST_INSTALL
+# -----------------------
+# set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)
+])# AC_DISABLE_FAST_INSTALL
+
+
+# AC_LIBTOOL_PICMODE([MODE])
+# --------------------------
+# implement the --with-pic flag
+# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)
+])# AC_LIBTOOL_PICMODE
+
+
+# AC_PROG_EGREP
+# -------------
+# This is predefined starting with Autoconf 2.54, so this conditional
+# definition can be removed once we require Autoconf 2.54 or later.
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+ [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])])
+
+
+# AC_PATH_TOOL_PREFIX
+# -------------------
+# find a file program which can recognise shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="ifelse([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$1; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+])# AC_PATH_TOOL_PREFIX
+
+
+# AC_PATH_MAGIC
+# -------------
+# find a file program which can recognise a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# AC_PATH_MAGIC
+
+
+# AC_PROG_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+ [AC_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])
+AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])# AC_PROG_LD
+
+
+# AC_PROG_LD_GNU
+# --------------
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# AC_PROG_LD_GNU
+
+
+# AC_PROG_LD_RELOAD_FLAG
+# ----------------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$CC -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+])# AC_PROG_LD_RELOAD_FLAG
+
+
+# AC_DEPLIBS_CHECK_METHOD
+# -----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognise dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump'.
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | kfreebsd*-gnu)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case "$host_cpu" in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+nto-qnx*)
+ lt_cv_deplibs_check_method=unknown
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sco3.2v5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+])# AC_DEPLIBS_CHECK_METHOD
+
+
+# AC_PROG_NM
+# ----------
+# find the pathname to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/${ac_tool_prefix}nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+])# AC_PROG_NM
+
+
+# AC_CHECK_LIBM
+# -------------
+# check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM="-lm")
+ ;;
+esac
+])# AC_CHECK_LIBM
+
+
+# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL
+# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If
+# DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will
+# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with
+# '${top_srcdir}/' (note the single quotes!). If your package is not
+# flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ case $enable_ltdl_convenience in
+ no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+ "") enable_ltdl_convenience=yes
+ ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+ esac
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ # For backwards non-gettext consistent compatibility...
+ INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_CONVENIENCE
+
+
+# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl installable library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments. Note that LIBLTDL
+# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If
+# DIRECTORY is not provided and an installed libltdl is not found, it is
+# assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/'
+# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single
+# quotes!). If your package is not flat and you're not using automake,
+# define top_builddir and top_srcdir appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+ AC_CHECK_LIB(ltdl, lt_dlinit,
+ [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+ [if test x"$enable_ltdl_install" = xno; then
+ AC_MSG_WARN([libltdl not installed, but installation disabled])
+ else
+ enable_ltdl_install=yes
+ fi
+ ])
+ if test x"$enable_ltdl_install" = x"yes"; then
+ ac_configure_args="$ac_configure_args --enable-ltdl-install"
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+ LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+ else
+ ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+ LIBLTDL="-lltdl"
+ LTDLINCL=
+ fi
+ # For backwards non-gettext consistent compatibility...
+ INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_INSTALLABLE
+
+
+# AC_LIBTOOL_CXX
+# --------------
+# enable support for C++ libraries
+AC_DEFUN([AC_LIBTOOL_CXX],
+[AC_REQUIRE([_LT_AC_LANG_CXX])
+])# AC_LIBTOOL_CXX
+
+
+# _LT_AC_LANG_CXX
+# ---------------
+AC_DEFUN([_LT_AC_LANG_CXX],
+[AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
+])# _LT_AC_LANG_CXX
+
+# _LT_AC_PROG_CXXCPP
+# ---------------
+AC_DEFUN([_LT_AC_PROG_CXXCPP],
+[
+AC_REQUIRE([AC_PROG_CXX])
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_PROG_CXXCPP
+fi
+])# _LT_AC_PROG_CXXCPP
+
+# AC_LIBTOOL_F77
+# --------------
+# enable support for Fortran 77 libraries
+AC_DEFUN([AC_LIBTOOL_F77],
+[AC_REQUIRE([_LT_AC_LANG_F77])
+])# AC_LIBTOOL_F77
+
+
+# _LT_AC_LANG_F77
+# ---------------
+AC_DEFUN([_LT_AC_LANG_F77],
+[AC_REQUIRE([AC_PROG_F77])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
+])# _LT_AC_LANG_F77
+
+
+# AC_LIBTOOL_GCJ
+# --------------
+# enable support for GCJ libraries
+AC_DEFUN([AC_LIBTOOL_GCJ],
+[AC_REQUIRE([_LT_AC_LANG_GCJ])
+])# AC_LIBTOOL_GCJ
+
+
+# _LT_AC_LANG_GCJ
+# ---------------
+AC_DEFUN([_LT_AC_LANG_GCJ],
+[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
+ [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
+ [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
+ [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
+ [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
+])# _LT_AC_LANG_GCJ
+
+
+# AC_LIBTOOL_RC
+# --------------
+# enable support for Windows resource files
+AC_DEFUN([AC_LIBTOOL_RC],
+[AC_REQUIRE([LT_AC_PROG_RC])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
+])# AC_LIBTOOL_RC
+
+
+# AC_LIBTOOL_LANG_C_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
+AC_DEFUN([_LT_AC_LANG_C_CONFIG],
+[lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+_LT_AC_SYS_COMPILER
+
+#
+# Check for any special shared library compilation flags.
+#
+_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)=
+if test "$GCC" = no; then
+ case $host_os in
+ sco3.2v5*)
+ _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf'
+ ;;
+ esac
+fi
+if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then
+ AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries])
+ if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[ ]]" >/dev/null; then :
+ else
+ AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure])
+ _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no
+ fi
+fi
+
+
+#
+# Check to make sure the static flag actually works.
+#
+AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works],
+ _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1),
+ $_LT_AC_TAGVAR(lt_prog_compiler_static, $1),
+ [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF($1)
+
+# Report which libraries types will actually be built
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+aix4* | aix5*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_C_CONFIG
+
+
+# AC_LIBTOOL_LANG_CXX_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
+AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
+[AC_LANG_PUSH(C++)
+AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([_LT_AC_PROG_CXXCPP])
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Dependencies to place before and after the object being linked:
+_LT_AC_TAGVAR(predep_objects, $1)=
+_LT_AC_TAGVAR(postdep_objects, $1)=
+_LT_AC_TAGVAR(predeps, $1)=
+_LT_AC_TAGVAR(postdeps, $1)=
+_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
+
+# Source file extension for C++ test sources.
+ac_ext=cc
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+ unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+ unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+else
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+fi
+
+if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+ AC_PROG_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+ grep 'no-whole-archive' > /dev/null; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+_LT_AC_TAGVAR(ld_shlibs, $1)=yes
+case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_AC_TAGVAR(archive_cmds, $1)=''
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ else
+ # We have old collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ esac
+ shared_flag='-shared'
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # -bexpall does not export symbols beginning with underscore (_)
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds it's shared libraries.
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+ case "$host_os" in
+ rhapsody* | darwin1.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GXX" = yes ; then
+ lt_int_apple_cc_single_mod=no
+ output_verbose_link_cmd='echo'
+ if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then
+ lt_int_apple_cc_single_mod=yes
+ fi
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ fi
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case "$cc_basename" in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ freebsd[12]*)
+ # C++ shared libraries reported to be fairly broken before switch to ELF
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ freebsd-elf*)
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+ freebsd* | kfreebsd*-gnu)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+ gnu*)
+ ;;
+ hpux9*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[-]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ case "$host_cpu" in
+ hppa*64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+ esac
+ fi
+ case "$host_cpu" in
+ hppa*64*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC)
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case "$host_cpu" in
+ ia64*|hppa*64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC)
+ # SGI C++
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+ fi
+ fi
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc)
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ cxx)
+ # Compaq C++
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ esac
+ ;;
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ openbsd*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd='echo'
+ ;;
+ osf3*)
+ case $cc_basename in
+ KCC)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+
+ ;;
+ RCC)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ osf4* | osf5*)
+ case $cc_basename in
+ KCC)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
+ ;;
+ RCC)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~
+ $rm $lib.exp'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ sco*)
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ case $cc_basename in
+ CC)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The C++ compiler is used as linker so we must use $wl
+ # flag to pass the commands to the underlying system
+ # linker.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+ if $CC --version | grep -v '^2\.7' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+ fi
+
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+ fi
+ ;;
+ esac
+ ;;
+ sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*)
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+esac
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$GXX"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_POSTDEP_PREDEP($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+])# AC_LIBTOOL_LANG_CXX_CONFIG
+
+# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
+# ------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
+int a;
+void foo (void) { a = 0; }
+EOF
+],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+EOF
+],[$1],[F77],[cat > conftest.$ac_ext <<EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+EOF
+],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ # The `*' in the case matches for architectures that use `case' in
+ # $output_verbose_cmd can trigger glob expansion during the loop
+ # eval without this substitution.
+ output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`"
+
+ for p in `eval $output_verbose_link_cmd`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" \
+ || test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+ else
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
+ _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
+ else
+ _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
+ _LT_AC_TAGVAR(predep_objects, $1)="$p"
+ else
+ _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
+ _LT_AC_TAGVAR(postdep_objects, $1)="$p"
+ else
+ _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$rm -f confest.$objext
+
+case " $_LT_AC_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+])# AC_LIBTOOL_POSTDEP_PREDEP
+
+# AC_LIBTOOL_LANG_F77_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
+AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
+[AC_REQUIRE([AC_PROG_F77])
+AC_LANG_PUSH(Fortran 77)
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code=" subroutine t\n return\n end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=" program t\n end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
+
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+aix4* | aix5*)
+ test "$enable_shared" = yes && enable_static=no
+ ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$G77"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_F77_CONFIG
+
+
+# AC_LIBTOOL_LANG_GCJ_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
+AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_GCJ_CONFIG
+
+
+# AC_LIBTOOL_LANG_RC_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the Windows resource compiler are
+# suitably defined. Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
+AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_RC_CONFIG
+
+
+# AC_LIBTOOL_CONFIG([TAGNAME])
+# ----------------------------
+# If TAGNAME is not passed, then create an initial libtool script
+# with a default configuration from the untagged config vars. Otherwise
+# add code to config.status for appending the configuration named by
+# TAGNAME from the matching tagged config vars.
+AC_DEFUN([AC_LIBTOOL_CONFIG],
+[# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+ # See if we are running on zsh, and set the options which allow our commands through
+ # without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+ # Now quote all the things that may contain metacharacters while being
+ # careful not to overquote the AC_SUBSTed values. We take copies of the
+ # variables and quote the copies for generation of the libtool script.
+ for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \
+ SED SHELL STRIP \
+ libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+ old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+ deplibs_check_method reload_flag reload_cmds need_locks \
+ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+ lt_cv_sys_global_symbol_to_c_name_address \
+ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+ old_postinstall_cmds old_postuninstall_cmds \
+ _LT_AC_TAGVAR(compiler, $1) \
+ _LT_AC_TAGVAR(CC, $1) \
+ _LT_AC_TAGVAR(LD, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
+ _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
+ _LT_AC_TAGVAR(old_archive_cmds, $1) \
+ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
+ _LT_AC_TAGVAR(predep_objects, $1) \
+ _LT_AC_TAGVAR(postdep_objects, $1) \
+ _LT_AC_TAGVAR(predeps, $1) \
+ _LT_AC_TAGVAR(postdeps, $1) \
+ _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
+ _LT_AC_TAGVAR(archive_cmds, $1) \
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
+ _LT_AC_TAGVAR(postinstall_cmds, $1) \
+ _LT_AC_TAGVAR(postuninstall_cmds, $1) \
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
+ _LT_AC_TAGVAR(allow_undefined_flag, $1) \
+ _LT_AC_TAGVAR(no_undefined_flag, $1) \
+ _LT_AC_TAGVAR(export_symbols_cmds, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
+ _LT_AC_TAGVAR(hardcode_automatic, $1) \
+ _LT_AC_TAGVAR(module_cmds, $1) \
+ _LT_AC_TAGVAR(module_expsym_cmds, $1) \
+ _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
+ _LT_AC_TAGVAR(exclude_expsyms, $1) \
+ _LT_AC_TAGVAR(include_expsyms, $1); do
+
+ case $var in
+ _LT_AC_TAGVAR(old_archive_cmds, $1) | \
+ _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
+ _LT_AC_TAGVAR(archive_cmds, $1) | \
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
+ _LT_AC_TAGVAR(module_cmds, $1) | \
+ _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
+ _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
+ extract_expsyms_cmds | reload_cmds | finish_cmds | \
+ postinstall_cmds | postuninstall_cmds | \
+ old_postinstall_cmds | old_postuninstall_cmds | \
+ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+ # Double-quote double-evaled strings.
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+ ;;
+ *)
+ eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+ ;;
+ esac
+ done
+
+ case $lt_echo in
+ *'\[$]0 --fallback-echo"')
+ lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
+ ;;
+ esac
+
+ifelse([$1], [],
+ [cfgfile="${ofile}T"
+ trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+ $rm -f "$cfgfile"
+ AC_MSG_NOTICE([creating $ofile])],
+ [cfgfile="$ofile"])
+
+ cat <<__EOF__ >> "$cfgfile"
+ifelse([$1], [],
+[#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG],
+[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# A language-specific compiler.
+CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
+
+# Is the compiler the GNU C compiler?
+with_gcc=$_LT_AC_TAGVAR(GCC, $1)
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext_cmds='$shrext_cmds'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
+archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
+module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1)
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1)
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
+
+# Symbols that must always be exported.
+include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
+
+ifelse([$1],[],
+[# ### END LIBTOOL CONFIG],
+[# ### END LIBTOOL TAG CONFIG: $tagname])
+
+__EOF__
+
+ifelse([$1],[], [
+ case $host_os in
+ aix3*)
+ cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+EOF
+ ;;
+ esac
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" || \
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+])
+else
+ # If there is no Makefile yet, we rely on a make rule to execute
+ # `config.status --recheck' to rerun these tests and create the
+ # libtool script then.
+ ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+ if test -f "$ltmain_in"; then
+ test -f Makefile && make "$ltmain"
+ fi
+fi
+])# AC_LIBTOOL_CONFIG
+
+
+# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+
+_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+ AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
+
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*) # Its linker distinguishes data from code symbols
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ ;;
+linux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDGIRSTW]]'
+ lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+ lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'"
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris* | sysv5*)
+ symcode='[[BDRT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Write the raw and C identifiers.
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if grep ' nm_test_var$' "$nlist" >/dev/null; then
+ if grep ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+ cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr_t address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+ cat <<\EOF >> conftest.$ac_ext
+ {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -f conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+
+# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
+# ---------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
+[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+ ifelse([$1],[CXX],[
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | os2* | pw32*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix4* | aix5*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68)
+ # Green Hills C++ Compiler
+ # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case "$cc_basename" in
+ xlc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | kfreebsd*-gnu)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
+ if test "$host_cpu" != ia64; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux*)
+ case $cc_basename in
+ KCC)
+ # KAI C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ icpc)
+ # Intel C++
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ cxx)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC)
+ # Rational C++ 2.4.1
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx)
+ # Digital/Compaq C++
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ sco*)
+ case $cc_basename in
+ CC)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx)
+ # Green Hills C++ Compiler
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC)
+ # Sun C++ 4.x
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc)
+ # Lucid
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC)
+ # NonStop-UX NCC 3.20
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ unixware*)
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+
+ beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ hpux*)
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ case "$cc_basename" in
+ xlc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon'
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ esac
+ ;;
+
+ mingw* | pw32* | os2*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ newsos6)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ linux*)
+ case $CC in
+ icc* | ecc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ ccc*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ esac
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ sco3.2v5*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn'
+ ;;
+
+ solaris*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sunos4*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ uts4*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
+ _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1),
+ [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+case "$host_os" in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+])
+
+
+# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
+# ------------------------------------
+# See if the linker supports building shared libraries.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
+[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ifelse([$1],[CXX],[
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix4* | aix5*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+ ;;
+ cygwin* | mingw*)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+],[
+ runpath_var=
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_AC_TAGVAR(archive_cmds, $1)=
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
+ _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=no
+ _LT_AC_TAGVAR(module_cmds, $1)=
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)=
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_AC_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_"
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ if test "$with_gnu_ld" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix3* | aix4* | aix5*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+ fi
+ ;;
+
+ amigaos*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we can't use
+ # them.
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=no
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris* | sysv5*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sunos4*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ linux*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds"
+ supports_anon_versioning=no
+ case `$LD -v 2>/dev/null` in
+ *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+ if test $supports_anon_versioning = yes; then
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
+cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+$echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds"
+ fi
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then
+ runpath_var=LD_RUN_PATH
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ if test "$GCC" = yes && test -z "$link_static_flag"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix4* | aix5*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_AC_TAGVAR(archive_cmds, $1)=''
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ else
+ # We have old collect2
+ _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ esac
+ shared_flag='-shared'
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an empty executable.
+ _LT_AC_SYS_LIBPATH_AIX
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ # -bexpall does not export symbols beginning with underscore (_)
+ _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds it's shared libraries.
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ # see comment about different semantics on the GNU ld section
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ bsdi[[45]]*)
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ darwin* | rhapsody*)
+ case "$host_os" in
+ rhapsody* | darwin1.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress'
+ ;;
+ *) # Darwin 1.3 on
+ if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ else
+ case ${MACOSX_DEPLOYMENT_TARGET} in
+ 10.[[012]])
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ 10.*)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=''
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ if test "$GCC" = yes ; then
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ else
+ case "$cc_basename" in
+ xlc*)
+ output_verbose_link_cmd='echo'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring'
+ _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+ # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ ;;
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+ ;;
+
+ dgux*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ freebsd1*)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | kfreebsd*-gnu)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+
+ hpux10* | hpux11*)
+ if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case "$host_cpu" in
+ hppa*64*|ia64*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ case "$host_cpu" in
+ hppa*64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ ia64*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ *)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ openbsd*)
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ else
+ case $host_os in
+ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ ;;
+ *)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ ;;
+
+ os2*)
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ else
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ sco3.2v5*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ;;
+
+ solaris*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;;
+ esac
+ _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4.2uw2*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+ _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ hardcode_runpath_var=yes
+ runpath_var=LD_RUN_PATH
+ ;;
+
+ sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text'
+ if test "$GCC" = yes; then
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ runpath_var='LD_RUN_PATH'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv5*)
+ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+ # $CC -shared without GNU ld will not create a library from C++
+ # object files and a static libstdc++, better avoid it by now
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+ ;;
+
+ uts4*)
+ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_AC_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $_LT_AC_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+ $rm conftest*
+ printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+ then
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $rm conftest*
+ AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
+ ;;
+ esac
+ fi
+ ;;
+esac
+])# AC_LIBTOOL_PROG_LD_SHLIBS
+
+
+# _LT_AC_FILE_LTDLL_C
+# -------------------
+# Be careful that the start marker always follows a newline.
+AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# # ifdef __CYGWIN32__
+# # define __CYGWIN__ __CYGWIN32__
+# # endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+# __hDllInstance_base = hInst;
+# return TRUE;
+# }
+# /* ltdll.c ends here */
+])# _LT_AC_FILE_LTDLL_C
+
+
+# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
+# ---------------------------------
+AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
+
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD], [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM], [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
+
+AC_DEFUN([LT_AC_PROG_GCJ],
+[AC_CHECK_TOOL(GCJ, gcj, no)
+ test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)
+])
+
+AC_DEFUN([LT_AC_PROG_RC],
+[AC_CHECK_TOOL(RC, windres, no)
+])
+
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+# LT_AC_PROG_SED
+# --------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+AC_DEFUN([LT_AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && break
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_MSG_RESULT([$SED])
+])
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100644
index 0000000..e032aff
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,6416 @@
+# ltmain.sh - Provide generalized library-building support services.
+# NOTE: Changing this file will not affect anything until you rerun configure.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
+# Free Software Foundation, Inc.
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+basename="s,^.*/,,g"
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath="$0"
+
+# The name of this program:
+progname=`echo "$progpath" | $SED $basename`
+modename="$progname"
+
+# Global variables:
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+
+PROGRAM=ltmain.sh
+PACKAGE=libtool
+VERSION=1.5.10
+TIMESTAMP=" (1.1220.2.131 2004/09/19 12:46:56)"
+
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes.
+if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+# Check that we have a working $echo.
+if test "X$1" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+elif test "X$1" = X--fallback-echo; then
+ # Avoid inline document here, it may be left over
+ :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
+ # Yippee, $echo works!
+ :
+else
+ # Restart under the correct shell, and then maybe $echo will work.
+ exec $SHELL "$progpath" --no-reexec ${1+"$@"}
+fi
+
+if test "X$1" = X--fallback-echo; then
+ # used as fallback echo
+ shift
+ cat <<EOF
+$*
+EOF
+ exit $EXIT_SUCCESS
+fi
+
+default_mode=
+help="Try \`$progname --help' for more information."
+magic="%%%MAGIC variable%%%"
+mkdir="mkdir"
+mv="mv -f"
+rm="rm -f"
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed="${SED}"' -e 1s/^X//'
+sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
+# test EBCDIC or ASCII
+case `echo A|tr A '\301'` in
+ A) # EBCDIC based system
+ SP2NL="tr '\100' '\n'"
+ NL2SP="tr '\r\n' '\100\100'"
+ ;;
+ *) # Assume ASCII based system
+ SP2NL="tr '\040' '\012'"
+ NL2SP="tr '\015\012' '\040\040'"
+ ;;
+esac
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+# We save the old values to restore during execute mode.
+if test "${LC_ALL+set}" = set; then
+ save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
+fi
+if test "${LANG+set}" = set; then
+ save_LANG="$LANG"; LANG=C; export LANG
+fi
+
+# Make sure IFS has a sensible default
+: ${IFS="
+"}
+
+if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
+ $echo "$modename: not configured to build any kind of library" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+fi
+
+# Global variables.
+mode=$default_mode
+nonopt=
+prev=
+prevopt=
+run=
+show="$echo"
+show_help=
+execute_dlfiles=
+lo2o="s/\\.lo\$/.${objext}/"
+o2lo="s/\\.${objext}\$/.lo/"
+
+#####################################
+# Shell function definitions:
+# This seems to be the best place for them
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+func_win32_libid () {
+ win32_libid_type="unknown"
+ win32_fileres=`file -L $1 2>/dev/null`
+ case $win32_fileres in
+ *ar\ archive\ import\ library*) # definitely import
+ win32_libid_type="x86 archive import"
+ ;;
+ *ar\ archive*) # could be an import, or static
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
+ $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
+ win32_nmres=`eval $NM -f posix -A $1 | \
+ sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'`
+ if test "X$win32_nmres" = "Ximport" ; then
+ win32_libid_type="x86 archive import"
+ else
+ win32_libid_type="x86 archive static"
+ fi
+ fi
+ ;;
+ *DLL*)
+ win32_libid_type="x86 DLL"
+ ;;
+ *executable*) # but shell scripts are "executable" too...
+ case $win32_fileres in
+ *MS\ Windows\ PE\ Intel*)
+ win32_libid_type="x86 DLL"
+ ;;
+ esac
+ ;;
+ esac
+ $echo $win32_libid_type
+}
+
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag () {
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case $@ in
+ # Blanks in the command may have been stripped by the calling shell,
+ # but not from the CC environment variable when configure was run.
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;;
+ # Blanks at the start of $base_compile will cause this to fail
+ # if we don't check for them as well.
+ *)
+ for z in $available_tags; do
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+ CC_quoted=
+ for arg in $CC; do
+ # Double-quote args containing other shell metacharacters.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ CC_quoted="$CC_quoted $arg"
+ done
+ case "$@ " in
+ " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*)
+ # The compiler in the base compile command matches
+ # the one in the tagged configuration.
+ # Assume this is the tagged configuration we want.
+ tagname=$z
+ break
+ ;;
+ esac
+ fi
+ done
+ # If $tagname still isn't set, then no tagged configuration
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+ $echo "$modename: unable to infer tagged configuration"
+ $echo "$modename: specify a tag with \`--tag'" 1>&2
+ exit $EXIT_FAILURE
+# else
+# $echo "$modename: using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives () {
+ my_gentop="$1"; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=""
+ my_xlib=""
+ my_xabs=""
+ my_xdir=""
+ my_status=""
+
+ $show "${rm}r $my_gentop"
+ $run ${rm}r "$my_gentop"
+ $show "$mkdir $my_gentop"
+ $run $mkdir "$my_gentop"
+ my_status=$?
+ if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+ exit $my_status
+ fi
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+ my_xdir="$my_gentop/$my_xlib"
+
+ $show "${rm}r $my_xdir"
+ $run ${rm}r "$my_xdir"
+ $show "$mkdir $my_xdir"
+ $run $mkdir "$my_xdir"
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$my_xdir"; then
+ exit $status
+ fi
+ case $host in
+ *-darwin*)
+ $show "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ if test -z "$run"; then
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ darwin_base_archive=`basename $darwin_archive`
+ darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ $show "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches ; do
+ mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+ # Remove the table of contents from the thin files.
+ $AR -d "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" __.SYMDEF 2>/dev/null || true
+ $AR -d "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" __.SYMDEF\ SORTED 2>/dev/null || true
+ cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+ $AR -xo "${darwin_base_archive}"
+ rm "${darwin_base_archive}"
+ cd "$darwin_curdir"
+ done # $darwin_arches
+ ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f | xargs basename | sort -u | $NL2SP`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+ lipo -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ rm -rf unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd $darwin_orig_dir
+ (cd $my_xdir && $AR x $my_xabs) || exit $?
+ fi # $darwin_arches
+ fi # $run
+ ;;
+ *)
+ # We will extract separately just the conflicting names and we will
+ # no longer touch any unique names. It is faster to leave these
+ # extract automatically by $AR in one run.
+ $show "(cd $my_xdir && $AR x $my_xabs)"
+ $run eval "(cd \$my_xdir && $AR x \$my_xabs)" || exit $?
+ if ($AR t "$my_xabs" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
+ $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
+ $AR t "$my_xabs" | sort | uniq -cd | while read -r count name
+ do
+ i=1
+ while test "$i" -le "$count"
+ do
+ # Put our $i before any first dot (extension)
+ # Never overwrite any file
+ name_to="$name"
+ while test "X$name_to" = "X$name" || test -f "$my_xdir/$name_to"
+ do
+ name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
+ done
+ $show "(cd $my_xdir && $AR xN $i $my_xabs '$name' && $mv '$name' '$name_to')"
+ $run eval "(cd \$my_xdir && $AR xN $i \$my_xabs '$name' && $mv '$name' '$name_to')" || exit $?
+ i=`expr $i + 1`
+ done
+ done
+ fi
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+ done
+
+ func_extract_archives_result="$my_oldobjs"
+}
+# End of Shell function definitions
+#####################################
+
+# Darwin sucks
+eval std_shrext=\"$shrext_cmds\"
+
+# Parse our command line options once, thoroughly.
+while test "$#" -gt 0
+do
+ arg="$1"
+ shift
+
+ case $arg in
+ -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ execute_dlfiles)
+ execute_dlfiles="$execute_dlfiles $arg"
+ ;;
+ tag)
+ tagname="$arg"
+ preserve_args="${preserve_args}=$arg"
+
+ # Check whether tagname contains only valid characters
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ $echo "$progname: invalid tag name: $tagname" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $tagname in
+ CC)
+ # Don't test for the "default" C tag, as we know, it's there, but
+ # not specially marked.
+ ;;
+ *)
+ if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then
+ taglist="$taglist $tagname"
+ # Evaluate the configuration.
+ eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`"
+ else
+ $echo "$progname: ignoring unknown tag $tagname" 1>&2
+ fi
+ ;;
+ esac
+ ;;
+ *)
+ eval "$prev=\$arg"
+ ;;
+ esac
+
+ prev=
+ prevopt=
+ continue
+ fi
+
+ # Have we seen a non-optional argument yet?
+ case $arg in
+ --help)
+ show_help=yes
+ ;;
+
+ --version)
+ $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
+ $echo
+ $echo "Copyright (C) 2003 Free Software Foundation, Inc."
+ $echo "This is free software; see the source for copying conditions. There is NO"
+ $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+ exit $EXIT_SUCCESS
+ ;;
+
+ --config)
+ ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath
+ # Now print the configurations for the tags.
+ for tagname in $taglist; do
+ ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
+ done
+ exit $EXIT_SUCCESS
+ ;;
+
+ --debug)
+ $echo "$progname: enabling shell trace mode"
+ set -x
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --dry-run | -n)
+ run=:
+ ;;
+
+ --features)
+ $echo "host: $host"
+ if test "$build_libtool_libs" = yes; then
+ $echo "enable shared libraries"
+ else
+ $echo "disable shared libraries"
+ fi
+ if test "$build_old_libs" = yes; then
+ $echo "enable static libraries"
+ else
+ $echo "disable static libraries"
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ --finish) mode="finish" ;;
+
+ --mode) prevopt="--mode" prev=mode ;;
+ --mode=*) mode="$optarg" ;;
+
+ --preserve-dup-deps) duplicate_deps="yes" ;;
+
+ --quiet | --silent)
+ show=:
+ preserve_args="$preserve_args $arg"
+ ;;
+
+ --tag) prevopt="--tag" prev=tag ;;
+ --tag=*)
+ set tag "$optarg" ${1+"$@"}
+ shift
+ prev=tag
+ preserve_args="$preserve_args --tag"
+ ;;
+
+ -dlopen)
+ prevopt="-dlopen"
+ prev=execute_dlfiles
+ ;;
+
+ -*)
+ $echo "$modename: unrecognized option \`$arg'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+
+ *)
+ nonopt="$arg"
+ break
+ ;;
+ esac
+done
+
+if test -n "$prevopt"; then
+ $echo "$modename: option \`$prevopt' requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+fi
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+if test -z "$show_help"; then
+
+ # Infer the operation mode.
+ if test -z "$mode"; then
+ $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
+ $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2
+ case $nonopt in
+ *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
+ mode=link
+ for arg
+ do
+ case $arg in
+ -c)
+ mode=compile
+ break
+ ;;
+ esac
+ done
+ ;;
+ *db | *dbx | *strace | *truss)
+ mode=execute
+ ;;
+ *install*|cp|mv)
+ mode=install
+ ;;
+ *rm)
+ mode=uninstall
+ ;;
+ *)
+ # If we have no mode, but dlfiles were specified, then do execute mode.
+ test -n "$execute_dlfiles" && mode=execute
+
+ # Just use the default operation mode.
+ if test -z "$mode"; then
+ if test -n "$nonopt"; then
+ $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2
+ else
+ $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2
+ fi
+ fi
+ ;;
+ esac
+ fi
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$execute_dlfiles" && test "$mode" != execute; then
+ $echo "$modename: unrecognized option \`-dlopen'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help="$help"
+ help="Try \`$modename --help --mode=$mode' for more information."
+
+ # These modes are in order of execution frequency so that they run quickly.
+ case $mode in
+ # libtool compile mode
+ compile)
+ modename="$modename: compile"
+ # Get the compilation command and the source file.
+ base_compile=
+ srcfile="$nonopt" # always keep a non-empty value in "srcfile"
+ suppress_opt=yes
+ suppress_output=
+ arg_mode=normal
+ libobj=
+ later=
+
+ for arg
+ do
+ case "$arg_mode" in
+ arg )
+ # do not "continue". Instead, add this to base_compile
+ lastarg="$arg"
+ arg_mode=normal
+ ;;
+
+ target )
+ libobj="$arg"
+ arg_mode=normal
+ continue
+ ;;
+
+ normal )
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ if test -n "$libobj" ; then
+ $echo "$modename: you cannot specify \`-o' more than once" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ arg_mode=target
+ continue
+ ;;
+
+ -static | -prefer-pic | -prefer-non-pic)
+ later="$later $arg"
+ continue
+ ;;
+
+ -no-suppress)
+ suppress_opt=no
+ continue
+ ;;
+
+ -Xcompiler)
+ arg_mode=arg # the next one goes into the "base_compile" arg list
+ continue # The current "srcfile" will either be retained or
+ ;; # replaced later. I would guess that would be a bug.
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"`
+ lastarg=
+ save_ifs="$IFS"; IFS=','
+ for arg in $args; do
+ IFS="$save_ifs"
+
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ lastarg="$lastarg $arg"
+ done
+ IFS="$save_ifs"
+ lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"`
+
+ # Add the arguments to base_compile.
+ base_compile="$base_compile $lastarg"
+ continue
+ ;;
+
+ * )
+ # Accept the current argument as the source file.
+ # The previous "srcfile" becomes the current argument.
+ #
+ lastarg="$srcfile"
+ srcfile="$arg"
+ ;;
+ esac # case $arg
+ ;;
+ esac # case $arg_mode
+
+ # Aesthetically quote the previous argument.
+ lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"`
+
+ case $lastarg in
+ # Double-quote args containing other shell metacharacters.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ lastarg="\"$lastarg\""
+ ;;
+ esac
+
+ base_compile="$base_compile $lastarg"
+ done # for arg
+
+ case $arg_mode in
+ arg)
+ $echo "$modename: you must specify an argument for -Xcompile"
+ exit $EXIT_FAILURE
+ ;;
+ target)
+ $echo "$modename: you must specify a target with \`-o'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *)
+ # Get the name of the library object.
+ [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'`
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ xform='[cCFSifmso]'
+ case $libobj in
+ *.ada) xform=ada ;;
+ *.adb) xform=adb ;;
+ *.ads) xform=ads ;;
+ *.asm) xform=asm ;;
+ *.c++) xform=c++ ;;
+ *.cc) xform=cc ;;
+ *.ii) xform=ii ;;
+ *.class) xform=class ;;
+ *.cpp) xform=cpp ;;
+ *.cxx) xform=cxx ;;
+ *.f90) xform=f90 ;;
+ *.for) xform=for ;;
+ *.java) xform=java ;;
+ esac
+
+ libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
+
+ case $libobj in
+ *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;;
+ *)
+ $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ func_infer_tag $base_compile
+
+ for arg in $later; do
+ case $arg in
+ -static)
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+ esac
+ done
+
+ objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+ xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$obj"; then
+ xdir=
+ else
+ xdir=$xdir/
+ fi
+ lobj=${xdir}$objdir/$objname
+
+ if test -z "$base_compile"; then
+ $echo "$modename: you must specify a compilation command" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Delete any leftover library objects.
+ if test "$build_old_libs" = yes; then
+ removelist="$obj $lobj $libobj ${libobj}T"
+ else
+ removelist="$lobj $libobj ${libobj}T"
+ fi
+
+ $run $rm $removelist
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2*)
+ pic_mode=default
+ ;;
+ esac
+ if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test "$compiler_c_o" = no; then
+ output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext}
+ lockfile="$output_obj.lock"
+ removelist="$removelist $output_obj $lockfile"
+ trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15
+ else
+ output_obj=
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test "$need_locks" = yes; then
+ until $run ln "$progpath" "$lockfile" 2>/dev/null; do
+ $show "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test "$need_locks" = warn; then
+ if test -f "$lockfile"; then
+ $echo "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+ $echo $srcfile > "$lockfile"
+ fi
+
+ if test -n "$fix_srcfile_path"; then
+ eval srcfile=\"$fix_srcfile_path\"
+ fi
+
+ $run $rm "$libobj" "${libobj}T"
+
+ # Create a libtool object file (analogous to a ".la" file),
+ # but don't create it if we're doing a dry run.
+ test -z "$run" && cat > ${libobj}T <<EOF
+# $libobj - a libtool object file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+EOF
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test "$build_libtool_libs" = yes; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test "$pic_mode" != no; then
+ command="$base_compile $srcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $srcfile"
+ fi
+
+ if test ! -d "${xdir}$objdir"; then
+ $show "$mkdir ${xdir}$objdir"
+ $run $mkdir ${xdir}$objdir
+ status=$?
+ if test "$status" -ne 0 && test ! -d "${xdir}$objdir"; then
+ exit $status
+ fi
+ fi
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ command="$command -o $lobj"
+ fi
+
+ $run $rm "$lobj" "$output_obj"
+
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ test -n "$output_obj" && $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+ $show "$mv $output_obj $lobj"
+ if $run $mv $output_obj $lobj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the PIC object to the libtool object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object='$objdir/$objname'
+
+EOF
+
+ # Allow error messages only from the first compilation.
+ if test "$suppress_opt" = yes; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ else
+ # No PIC object so indicate it doesn't exist in the libtool
+ # object file.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+pic_object=none
+
+EOF
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test "$build_old_libs" = yes; then
+ if test "$pic_mode" != yes; then
+ # Don't build PIC code
+ command="$base_compile $srcfile"
+ else
+ command="$base_compile $srcfile $pic_flag"
+ fi
+ if test "$compiler_c_o" = yes; then
+ command="$command -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ command="$command$suppress_output"
+ $run $rm "$obj" "$output_obj"
+ $show "$command"
+ if $run eval "$command"; then :
+ else
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$need_locks" = warn &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $echo "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support \`-c' and \`-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $run $rm $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed
+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+ $show "$mv $output_obj $obj"
+ if $run $mv $output_obj $obj; then :
+ else
+ error=$?
+ $run $rm $removelist
+ exit $error
+ fi
+ fi
+
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object='$objname'
+
+EOF
+ else
+ # Append the name of the non-PIC object the libtool object file.
+ # Only append if the libtool object file exists.
+ test -z "$run" && cat >> ${libobj}T <<EOF
+# Name of the non-PIC object.
+non_pic_object=none
+
+EOF
+ fi
+
+ $run $mv "${libobj}T" "${libobj}"
+
+ # Unlock the critical section if it was locked
+ if test "$need_locks" != no; then
+ $run $rm "$lockfile"
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool link mode
+ link | relink)
+ modename="$modename: link"
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # which system we are compiling for in order to pass an extra
+ # flag for every libtool invocation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll which has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args="$nonopt"
+ base_compile="$nonopt $@"
+ compile_command="$nonopt"
+ finalize_command="$nonopt"
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+
+ avoid_version=no
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ non_pic_objects=
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=no
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+
+ func_infer_tag $base_compile
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -all-static | -static)
+ if test "X$arg" = "X-all-static"; then
+ if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
+ $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ else
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ fi
+ build_libtool_libs=no
+ build_old_libs=yes
+ prefer_static_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test "$#" -gt 0; do
+ arg="$1"
+ shift
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test
+ ;;
+ *) qarg=$arg ;;
+ esac
+ libtool_args="$libtool_args $qarg"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ compile_command="$compile_command @OUTPUT@"
+ finalize_command="$finalize_command @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ dlfiles|dlprefiles)
+ if test "$preload" = no; then
+ # Add the symbol object into the linking commands.
+ compile_command="$compile_command @SYMFILE@"
+ finalize_command="$finalize_command @SYMFILE@"
+ preload=yes
+ fi
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test "$dlself" = no; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test "$prev" = dlprefiles; then
+ dlself=yes
+ elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test "$prev" = dlfiles; then
+ dlfiles="$dlfiles $arg"
+ else
+ dlprefiles="$dlprefiles $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols="$arg"
+ if test ! -f "$arg"; then
+ $echo "$modename: symbol file \`$arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex="$arg"
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir="$arg"
+ prev=
+ continue
+ ;;
+ precious_regex)
+ precious_files_regex="$arg"
+ prev=
+ continue
+ ;;
+ release)
+ release="-$arg"
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat $save_arg`
+ do
+# moreargs="$moreargs $fil"
+ arg=$fil
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ done
+ else
+ $echo "$modename: link input file \`$save_arg' does not exist"
+ exit $EXIT_FAILURE
+ fi
+ arg=$save_arg
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ if test "$prev" = rpath; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) rpath="$rpath $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) xrpath="$xrpath $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ xcompiler)
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ xlinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $wl$qarg"
+ prev=
+ compile_command="$compile_command $wl$qarg"
+ finalize_command="$finalize_command $wl$qarg"
+ continue
+ ;;
+ xcclinker)
+ linker_flags="$linker_flags $qarg"
+ compiler_flags="$compiler_flags $qarg"
+ prev=
+ compile_command="$compile_command $qarg"
+ finalize_command="$finalize_command $qarg"
+ continue
+ ;;
+ shrext)
+ shrext_cmds="$arg"
+ prev=
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n "$prev"
+
+ prevarg="$arg"
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ compile_command="$compile_command $link_static_flag"
+ finalize_command="$finalize_command $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2
+ continue
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: more than one -exported-symbols argument is not allowed"
+ exit $EXIT_FAILURE
+ fi
+ if test "X$arg" = "X-export-symbols"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | /*-*-irix*)
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-L//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ dir="$absdir"
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "*) ;;
+ *)
+ deplibs="$deplibs -L$dir"
+ lib_search_path="$lib_search_path $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$dir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
+ case $host in
+ *-*-cygwin* | *-*-pw32* | *-*-beos*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-mingw* | *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ deplibs="$deplibs -framework System"
+ continue
+ esac
+ elif test "X$arg" = "X-lc_r"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ deplibs="$deplibs $arg"
+ continue
+ ;;
+
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+ case $host in
+ *-*-freebsd*)
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ ;;
+ *)
+ case "$archive_cmds" in
+ *"\$LD"*) ;;
+ *) deplibs="$deplibs $arg";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # gcc -m* arguments should be passed to the linker via $compiler_flags
+ # in order to pass architecture information to the linker
+ # (e.g. 32 vs 64-bit). This may also be accomplished via -Wl,-mfoo
+ # but this is not reliable with gcc because gcc may use -mfoo to
+ # select a different linker, different libraries, etc, while
+ # -Wl,-mfoo simply passes -mfoo to the linker.
+ -m*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ if test "$with_gcc" = "yes" ; then
+ compiler_flags="$compiler_flags $arg"
+ fi
+ continue
+ ;;
+
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # in order for the loader to find any dlls it needs.
+ $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2
+ $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -objectlist)
+ prev=objectlist
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -precious-files-regex)
+ prev=precious_regex
+ continue
+ ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ dir=`$echo "X$arg" | $Xsed -e 's/^-R//'`
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ $echo "$modename: only absolute run-paths are allowed" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ continue
+ ;;
+
+ -static)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+ -version-number)
+ prev=vinfo
+ vinfo_number=yes
+ continue
+ ;;
+
+ -Wc,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Wl,*)
+ args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'`
+ arg=
+ save_ifs="$IFS"; IFS=','
+ for flag in $args; do
+ IFS="$save_ifs"
+ case $flag in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ flag="\"$flag\""
+ ;;
+ esac
+ arg="$arg $wl$flag"
+ compiler_flags="$compiler_flags $wl$flag"
+ linker_flags="$linker_flags $flag"
+ done
+ IFS="$save_ifs"
+ arg=`$echo "X$arg" | $Xsed -e "s/^ //"`
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ -XCClinker)
+ prev=xcclinker
+ continue
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+
+ *.$objext)
+ # A standard object.
+ objs="$objs $arg"
+ ;;
+
+ *.lo)
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ # If there is no directory component, then add one.
+ case $arg in
+ */* | *\\*) . $arg ;;
+ *) . ./$arg ;;
+ esac
+
+ if test -z "$pic_object" || \
+ test -z "$non_pic_object" ||
+ test "$pic_object" = none && \
+ test "$non_pic_object" = none; then
+ $echo "$modename: cannot find name of object for \`$arg'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ if test "$pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ pic_object="$xdir$pic_object"
+
+ if test "$prev" = dlfiles; then
+ if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then
+ dlfiles="$dlfiles $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test "$prev" = dlprefiles; then
+ # Preload the old-style object.
+ dlprefiles="$dlprefiles $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ libobjs="$libobjs $pic_object"
+ arg="$pic_object"
+ fi
+
+ # Non-PIC object.
+ if test "$non_pic_object" != none; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object="$xdir$non_pic_object"
+
+ # A standard non-PIC object
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ if test -z "$pic_object" || test "$pic_object" = none ; then
+ arg="$non_pic_object"
+ fi
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if test -z "$run"; then
+ $echo "$modename: \`$arg' is not a valid libtool object" 1>&2
+ exit $EXIT_FAILURE
+ else
+ # Dry-run case.
+
+ # Extract subdirectory from the argument.
+ xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$xdir" = "X$arg"; then
+ xdir=
+ else
+ xdir="$xdir/"
+ fi
+
+ pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"`
+ non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"`
+ libobjs="$libobjs $pic_object"
+ non_pic_objects="$non_pic_objects $non_pic_object"
+ fi
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ deplibs="$deplibs $arg"
+ old_deplibs="$old_deplibs $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ if test "$prev" = dlfiles; then
+ # This library was specified with -dlopen.
+ dlfiles="$dlfiles $arg"
+ prev=
+ elif test "$prev" = dlprefiles; then
+ # The library was specified with -dlpreopen.
+ dlprefiles="$dlprefiles $arg"
+ prev=
+ else
+ deplibs="$deplibs $arg"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ arg="\"$arg\""
+ ;;
+ esac
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+ done # argument parsing loop
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prevarg' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ compile_command="$compile_command $arg"
+ finalize_command="$finalize_command $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'`
+ libobjs_save="$libobjs"
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$output_objdir" = "X$output"; then
+ output_objdir="$objdir"
+ else
+ output_objdir="$output_objdir/$objdir"
+ fi
+ # Create the object directory.
+ if test ! -d "$output_objdir"; then
+ $show "$mkdir $output_objdir"
+ $run $mkdir $output_objdir
+ status=$?
+ if test "$status" -ne 0 && test ! -d "$output_objdir"; then
+ exit $status
+ fi
+ fi
+
+ # Determine the type of output
+ case $output in
+ "")
+ $echo "$modename: you must specify an output file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ case $host in
+ *cygwin* | *mingw* | *pw32*)
+ # don't eliminate duplications in $postdeps and $predeps
+ duplicate_compiler_generated_deps=yes
+ ;;
+ *)
+ duplicate_compiler_generated_deps=$duplicate_deps
+ ;;
+ esac
+ specialdeplibs=
+
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ libs="$libs $deplib"
+ done
+
+ if test "$linkmode" = lib; then
+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+ # Compute libraries that are listed more than once in $predeps
+ # $postdeps and mark them as special (i.e., whose duplicates are
+ # not to be eliminated).
+ pre_post_deps=
+ if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then
+ for pre_post_dep in $predeps $postdeps; do
+ case "$pre_post_deps " in
+ *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;;
+ esac
+ pre_post_deps="$pre_post_deps $pre_post_dep"
+ done
+ fi
+ pre_post_deps=
+ fi
+
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ notinst_path= # paths that contain not-installed libtool libraries
+ case $linkmode in
+ lib)
+ passes="conv link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=no
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+ for pass in $passes; do
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan"; then
+ libs="$deplibs"
+ deplibs=
+ fi
+ if test "$linkmode" = prog; then
+ case $pass in
+ dlopen) libs="$dlfiles" ;;
+ dlpreopen) libs="$dlprefiles" ;;
+ link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ esac
+ fi
+ if test "$pass" = dlopen; then
+ # Collect dlpreopened libraries
+ save_deplibs="$deplibs"
+ deplibs=
+ fi
+ for deplib in $libs; do
+ lib=
+ found=no
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ case "$archive_cmds" in
+ *"\$LD"*) ;;
+ *) deplibs="$deplibs $arg";;
+ esac
+ fi
+ continue
+ ;;
+ -l*)
+ if test "$linkmode" != lib && test "$linkmode" != prog; then
+ $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
+ continue
+ fi
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
+ for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ for search_ext in .la $std_shrext .so .a; do
+ # Search the libtool library
+ lib="$searchdir/lib${name}${search_ext}"
+ if test -f "$lib"; then
+ if test "$search_ext" = ".la"; then
+ found=yes
+ else
+ found=no
+ fi
+ break 2
+ fi
+ done
+ done
+ if test "$found" != yes; then
+ # deplib doesn't seem to be a libtool library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ else # deplib is a libtool library
+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+ # We need to do some special things here, and not later.
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $deplib "*)
+ if (${SED} -e '2q' $lib |
+ grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ library_names=
+ old_library=
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ for l in $old_library $library_names; do
+ ll="$l"
+ done
+ if test "X$ll" = "X$old_library" ; then # only static version available
+ found=no
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+ lib=$ladir/$old_library
+ if test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ fi
+ ;; # -l
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test "$pass" = conv && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ prog)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test "$pass" = scan; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`
+ ;;
+ *)
+ $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test "$pass" = link; then
+ dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'`
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) xrpath="$xrpath $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la) lib="$deplib" ;;
+ *.$libext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ valid_a_lib=no
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ if eval $echo \"$deplib\" 2>/dev/null \
+ | $SED 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=yes
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=yes
+ ;;
+ esac
+ if test "$valid_a_lib" != yes; then
+ $echo
+ $echo "*** Warning: Trying to link with static lib archive $deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because the file extensions .$libext of this argument makes me believe"
+ $echo "*** that it is just a static archive that I should not used here."
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the"
+ $echo "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ fi
+ continue
+ ;;
+ prog)
+ if test "$pass" != link; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test "$pass" = conv; then
+ deplibs="$deplib $deplibs"
+ elif test "$linkmode" = prog; then
+ if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ newdlprefiles="$newdlprefiles $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ newdlfiles="$newdlfiles $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=yes
+ continue
+ ;;
+ esac # case $deplib
+ if test "$found" = yes || test -f "$lib"; then :
+ else
+ $echo "$modename: cannot find the library \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$ladir" = "X$lib" && ladir="."
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variables installed, or shouldnotlink
+ installed=yes
+ shouldnotlink=no
+
+ # Read the .la file
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+
+ if test "$linkmode,$pass" = "lib,link" ||
+ test "$linkmode,$pass" = "prog,scan" ||
+ { test "$linkmode" != prog && test "$linkmode" != lib; }; then
+ test -n "$dlopen" && dlfiles="$dlfiles $dlopen"
+ test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen"
+ fi
+
+ if test "$pass" = conv; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ convenience="$convenience $ladir/$objdir/$old_library"
+ old_convenience="$old_convenience $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+ elif test "$linkmode" != prog && test "$linkmode" != lib; then
+ $echo "$modename: \`$lib' is not a convenience library" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ continue
+ fi # $pass = conv
+
+
+ # Get the name of the library we link against.
+ linklib=
+ for l in $old_library $library_names; do
+ linklib="$l"
+ done
+ if test -z "$linklib"; then
+ $echo "$modename: cannot find name of link library for \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # This library was specified with -dlopen.
+ if test "$pass" = dlopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test -z "$dlname" ||
+ test "$dlopen_support" != yes ||
+ test "$build_libtool_libs" = no; then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload. We also need to preload any
+ # dependent libraries so libltdl's deplib preloader doesn't
+ # bomb out in the load deplibs phase.
+ dlprefiles="$dlprefiles $lib $dependency_libs"
+ else
+ newdlfiles="$newdlfiles $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2
+ $echo "$modename: passing it literally to the linker, although it might fail" 1>&2
+ abs_ladir="$ladir"
+ fi
+ ;;
+ esac
+ laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+
+ # Find the relevant object directory and library name.
+ if test "X$installed" = Xyes; then
+ if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ $echo "$modename: warning: library \`$lib' was moved." 1>&2
+ dir="$ladir"
+ absdir="$abs_ladir"
+ libdir="$abs_ladir"
+ else
+ dir="$libdir"
+ absdir="$libdir"
+ fi
+ else
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir="$ladir"
+ absdir="$abs_ladir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ else
+ dir="$ladir/$objdir"
+ absdir="$abs_ladir/$objdir"
+ # Remove this search path later
+ notinst_path="$notinst_path $abs_ladir"
+ fi
+ fi # $installed = yes
+ name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+
+ # This library was specified with -dlpreopen.
+ if test "$pass" = dlpreopen; then
+ if test -z "$libdir"; then
+ $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ newdlprefiles="$newdlprefiles $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ newdlprefiles="$newdlprefiles $dir/$dlname"
+ else
+ newdlprefiles="$newdlprefiles $dir/$linklib"
+ fi
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test "$linkmode" = lib; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test "$linkmode,$pass" = "prog,link"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs" # used for prog,scan pass
+ fi
+ continue
+ fi
+
+
+ if test "$linkmode" = prog && test "$pass" != link; then
+ newlib_search_path="$newlib_search_path $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=no
+ if test "$link_all_deplibs" != no || test -z "$library_names" ||
+ test "$build_libtool_libs" = no; then
+ linkalldeplibs=yes
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test
+ esac
+ # Need to link against all dependency_libs?
+ if test "$linkalldeplibs" = yes; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test "$linkmode,$pass" = "prog,link"; then
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var"; then
+ # Make sure the rpath contains only unique directories.
+ case "$temp_rpath " in
+ *" $dir "*) ;;
+ *" $absdir "*) ;;
+ *) temp_rpath="$temp_rpath $dir" ;;
+ esac
+ fi
+
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if test "$alldeplibs" = yes &&
+ { test "$deplibs_check_method" = pass_all ||
+ { test "$build_libtool_libs" = yes &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+ fi
+
+ link_static=no # Whether the deplib will be linked statically
+ if test -n "$library_names" &&
+ { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+ if test "$installed" = no; then
+ notinst_deplibs="$notinst_deplibs $lib"
+ need_relink=yes
+ fi
+ # This is a shared library
+
+ # Warn about portability, can't link against -module's on
+ # some systems (darwin)
+ if test "$shouldnotlink" = yes && test "$pass" = link ; then
+ $echo
+ if test "$linkmode" = prog; then
+ $echo "*** Warning: Linking the executable $output against the loadable module"
+ else
+ $echo "*** Warning: Linking the shared library $output against the loadable module"
+ fi
+ $echo "*** $linklib is not portable!"
+ fi
+ if test "$linkmode" = lib &&
+ test "$hardcode_into_libs" = yes; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) compile_rpath="$compile_rpath $absdir"
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir"
+ esac
+ ;;
+ esac
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+ libname=`eval \\$echo \"$libname_spec\"`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname="$dlname"
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin* | mingw*)
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot="$soname"
+ soname=`$echo $soroot | ${SED} -e 's/^.*\///'`
+ newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a"
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ $show "extracting exported symbol list from \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$extract_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ $show "generating import library for \`$soname'"
+ save_ifs="$IFS"; IFS='~'
+ cmds=$old_archive_from_expsyms_cmds
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n "$old_archive_from_expsyms_cmds"
+
+ if test "$linkmode" = prog || test "$mode" != relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test "$hardcode_direct" = no; then
+ add="$dir/$linklib"
+ case $host in
+ *-*-sco3.2v5* ) add_dir="-L$dir" ;;
+ *-*-darwin* )
+ # if the lib is a module then we can not link against
+ # it, someone is ignoring the new warnings I added
+ if /usr/bin/file -L $add 2> /dev/null | $EGREP "bundle" >/dev/null ; then
+ $echo "** Warning, lib $linklib is a module, not a shared library"
+ if test -z "$old_library" ; then
+ $echo
+ $echo "** And there doesn't seem to be a static archive available"
+ $echo "** The link will probably fail, sorry"
+ else
+ add="$dir/$old_library"
+ fi
+ fi
+ esac
+ elif test "$hardcode_minus_L" = no; then
+ case $host in
+ *-*-sunos*) add_shlibpath="$dir" ;;
+ esac
+ add_dir="-L$dir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = no; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test "$hardcode_direct" = yes; then
+ add="$dir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$dir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case "$libdir" in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ add_shlibpath="$dir"
+ add="-l$name"
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test "$lib_linked" != yes; then
+ $echo "$modename: configuration error: unsupported hardcode properties"
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;;
+ esac
+ fi
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test "$hardcode_direct" != yes && \
+ test "$hardcode_minus_L" != yes && \
+ test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test "$linkmode" = prog || test "$mode" = relink; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test "$hardcode_direct" = yes; then
+ add="$libdir/$linklib"
+ elif test "$hardcode_minus_L" = yes; then
+ add_dir="-L$libdir"
+ add="-l$name"
+ elif test "$hardcode_shlibpath_var" = yes; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;;
+ esac
+ add="-l$name"
+ elif test "$hardcode_automatic" = yes; then
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib" ; then
+ add="$inst_prefix_dir$libdir/$linklib"
+ else
+ add="$libdir/$linklib"
+ fi
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir="-L$libdir"
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case "$libdir" in
+ [\\/]*)
+ add_dir="$add_dir -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add="-l$name"
+ fi
+
+ if test "$linkmode" = prog; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test "$linkmode" = prog; then
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test "$hardcode_direct" != unsupported; then
+ test -n "$old_library" && linklib="$old_library"
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test "$build_libtool_libs" = yes; then
+ # Not a shared library
+ if test "$deplibs_check_method" != pass_all; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ $echo
+ $echo "*** Warning: This system can not link to static lib archive $lib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have."
+ if test "$module" = yes; then
+ $echo "*** But as you try to build a module library, libtool will still create "
+ $echo "*** a static module, that should work as long as the dlopening application"
+ $echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ convenience="$convenience $dir/$old_library"
+ old_convenience="$old_convenience $dir/$old_library"
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test "$linkmode" = lib; then
+ if test -n "$dependency_libs" &&
+ { test "$hardcode_into_libs" != yes ||
+ test "$build_old_libs" = yes ||
+ test "$link_static" = yes; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'`
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) xrpath="$xrpath $temp_xrpath";;
+ esac;;
+ *) temp_deplibs="$temp_deplibs $libdir";;
+ esac
+ done
+ dependency_libs="$temp_deplibs"
+ fi
+
+ newlib_search_path="$newlib_search_path $absdir"
+ # Link against this library
+ test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ if test "X$duplicate_deps" = "Xyes" ; then
+ case "$tmp_libs " in
+ *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;;
+ esac
+ fi
+ tmp_libs="$tmp_libs $deplib"
+ done
+
+ if test "$link_all_deplibs" != no; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) path="$deplib" ;;
+ *.la)
+ dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$deplib" && dir="."
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2
+ absdir="$dir"
+ fi
+ ;;
+ esac
+ if grep "^installed=no" $deplib > /dev/null; then
+ path="$absdir/$objdir"
+ else
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$absdir" != "$libdir"; then
+ $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2
+ fi
+ path="$absdir"
+ fi
+ depdepl=
+ case $host in
+ *-*-darwin*)
+ # we do not want to link against static libs,
+ # but need to link against shared
+ eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+ if test -n "$deplibrary_names" ; then
+ for tmp in $deplibrary_names ; do
+ depdepl=$tmp
+ done
+ if test -f "$path/$depdepl" ; then
+ depdepl="$path/$depdepl"
+ fi
+ # do not add paths which are already there
+ case " $newlib_search_path " in
+ *" $path "*) ;;
+ *) newlib_search_path="$newlib_search_path $path";;
+ esac
+ fi
+ path=""
+ ;;
+ *)
+ path="-L$path"
+ ;;
+ esac
+ ;;
+ -l*)
+ case $host in
+ *-*-darwin*)
+ # Again, we only want to link against shared libraries
+ eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"`
+ for tmp in $newlib_search_path ; do
+ if test -f "$tmp/lib$tmp_libs.dylib" ; then
+ eval depdepl="$tmp/lib$tmp_libs.dylib"
+ break
+ fi
+ done
+ path=""
+ ;;
+ *) continue ;;
+ esac
+ ;;
+ *) continue ;;
+ esac
+ case " $deplibs " in
+ *" $depdepl "*) ;;
+ *) deplibs="$depdepl $deplibs" ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$deplibs $path" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ dependency_libs="$newdependency_libs"
+ if test "$pass" = dlpreopen; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test "$pass" != dlopen; then
+ if test "$pass" != conv; then
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) lib_search_path="$lib_search_path $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ fi
+
+ if test "$linkmode,$pass" != "prog,link"; then
+ vars="deplibs"
+ else
+ vars="compile_deplibs finalize_deplibs"
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ # FIXME: Pedantically, this is the right thing to do, so
+ # that some nasty dependency loop isn't accidentally
+ # broken:
+ #new_libs="$deplib $new_libs"
+ # Pragmatically, this seems to cause very few problems in
+ # practice:
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ -R*) ;;
+ *)
+ # And here is the reason: when a library appears more
+ # than once as an explicit dependence of a library, or
+ # is implicitly linked in more than once by the
+ # compiler, it is considered special, and multiple
+ # occurrences thereof are not removed. Compare this
+ # with having the same library being listed as a
+ # dependency of multiple other libraries: in this case,
+ # we know (pedantically, we assume) the library does not
+ # need to be listed more than once, so we keep only the
+ # last copy. This is not always right, but it is rare
+ # enough that we require users that really mean to play
+ # such unportable linking tricks to link the library
+ # using -Wl,-lname, so that libtool does not consider it
+ # for duplicate removal.
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ ;;
+ *) tmp_libs="$tmp_libs $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+ # Last step: remove runtime libs from dependency_libs
+ # (they stay in deplibs)
+ tmp_libs=
+ for i in $dependency_libs ; do
+ case " $predeps $postdeps $compiler_lib_search_path " in
+ *" $i "*)
+ i=""
+ ;;
+ esac
+ if test -n "$i" ; then
+ tmp_libs="$tmp_libs $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test "$linkmode" = prog; then
+ dlfiles="$newdlfiles"
+ dlprefiles="$newdlprefiles"
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for archives" 1>&2
+ fi
+
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2
+ fi
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs="$output"
+ objs="$objs$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form `libNAME.la'.
+ case $outputname in
+ lib*)
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ if test "$module" = no; then
+ $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ if test "$need_lib_prefix" != no; then
+ # Add the "lib" prefix for modules if required
+ name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ else
+ libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'`
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test "$deplibs_check_method" != pass_all; then
+ $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1
+ exit $EXIT_FAILURE
+ else
+ $echo
+ $echo "*** Warning: Linking the shared library $output against the non-libtool"
+ $echo "*** objects $objs is not portable!"
+ libobjs="$libobjs $objs"
+ fi
+ fi
+
+ if test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2
+ fi
+
+ set dummy $rpath
+ if test "$#" -gt 2; then
+ $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2
+ fi
+ install_libdir="$2"
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test "$build_libtool_libs" = yes; then
+ # Building a libtool convenience library.
+ # Some compilers have problems with a `.al' extension so
+ # convenience libraries should have the same extension an
+ # archive normally would.
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2
+ fi
+ else
+
+ # Parse the version information argument.
+ save_ifs="$IFS"; IFS=':'
+ set dummy $vinfo 0 0 0
+ IFS="$save_ifs"
+
+ if test -n "$8"; then
+ $echo "$modename: too many parameters to \`-version-info'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # convert absolute version numbers to libtool ages
+ # this retains compatibility with .la files and attempts
+ # to make the code below a bit more comprehensible
+
+ case $vinfo_number in
+ yes)
+ number_major="$2"
+ number_minor="$3"
+ number_revision="$4"
+ #
+ # There are really only two kinds -- those that
+ # use the current revision as the major version
+ # and those that subtract age and use age as
+ # a minor version. But, then there is irix
+ # which has an extra 1 added just for fun
+ #
+ case $version_type in
+ darwin|linux|osf|windows)
+ current=`expr $number_major + $number_minor`
+ age="$number_minor"
+ revision="$number_revision"
+ ;;
+ freebsd-aout|freebsd-elf|sunos)
+ current="$number_major"
+ revision="$number_minor"
+ age="0"
+ ;;
+ irix|nonstopux)
+ current=`expr $number_major + $number_minor - 1`
+ age="$number_minor"
+ revision="$number_minor"
+ ;;
+ esac
+ ;;
+ no)
+ current="$2"
+ revision="$3"
+ age="$4"
+ ;;
+ esac
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $revision in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ case $age in
+ 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;;
+ *)
+ $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test "$age" -gt "$current"; then
+ $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2
+ $echo "$modename: \`$vinfo' is not valid version information" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ # Darwin ld doesn't like 0 for these options...
+ minor_current=`expr $current + 1`
+ verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
+ ;;
+
+ freebsd-aout)
+ major=".$current"
+ versuffix=".$current.$revision";
+ ;;
+
+ freebsd-elf)
+ major=".$current"
+ versuffix=".$current";
+ ;;
+
+ irix | nonstopux)
+ major=`expr $current - $age + 1`
+
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring="$verstring_prefix$major.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test "$loop" -ne 0; do
+ iface=`expr $revision - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring_prefix$major.$iface:$verstring"
+ done
+
+ # Before this point, $major must not contain `.'.
+ major=.$major
+ versuffix="$major.$revision"
+ ;;
+
+ linux)
+ major=.`expr $current - $age`
+ versuffix="$major.$age.$revision"
+ ;;
+
+ osf)
+ major=.`expr $current - $age`
+ versuffix=".$current.$age.$revision"
+ verstring="$current.$age.$revision"
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test "$loop" -ne 0; do
+ iface=`expr $current - $loop`
+ loop=`expr $loop - 1`
+ verstring="$verstring:${iface}.0"
+ done
+
+ # Make executables depend on our current version.
+ verstring="$verstring:${current}.0"
+ ;;
+
+ sunos)
+ major=".$current"
+ versuffix=".$current.$revision"
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 filesystems.
+ major=`expr $current - $age`
+ versuffix="-$major"
+ ;;
+
+ *)
+ $echo "$modename: unknown library version type \`$version_type'" 1>&2
+ $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=
+ ;;
+ *)
+ verstring="0.0"
+ ;;
+ esac
+ if test "$need_version" = no; then
+ versuffix=
+ else
+ versuffix=".0.0"
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test "$avoid_version" = yes && test "$need_version" = no; then
+ major=
+ versuffix=
+ verstring=""
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test "$allow_undefined" = yes; then
+ if test "$allow_undefined_flag" = unsupported; then
+ $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2
+ build_libtool_libs=no
+ build_old_libs=yes
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag="$no_undefined_flag"
+ fi
+ fi
+
+ if test "$mode" != relink; then
+ # Remove our outputs, but don't remove object files since they
+ # may have been created when compiling PIC objects.
+ removelist=
+ tempremovelist=`$echo "$output_objdir/*"`
+ for p in $tempremovelist; do
+ case $p in
+ *.$objext)
+ ;;
+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*)
+ if test "X$precious_files_regex" != "X"; then
+ if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ removelist="$removelist $p"
+ ;;
+ *) ;;
+ esac
+ done
+ if test -n "$removelist"; then
+ $show "${rm}r $removelist"
+ $run ${rm}r $removelist
+ fi
+ fi
+
+ # Now set the variables for building old libraries.
+ if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then
+ oldlibs="$oldlibs $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ for path in $notinst_path; do
+ lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'`
+ deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'`
+ dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'`
+ done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ temp_xrpath="$temp_xrpath -R$libdir"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles="$dlfiles"
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) dlfiles="$dlfiles $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles="$dlprefiles"
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) dlprefiles="$dlprefiles $lib" ;;
+ esac
+ done
+
+ if test "$build_libtool_libs" = yes; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ deplibs="$deplibs -framework System"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd*)
+ # Do not include libc due to us having libc/libc_r.
+ test "X$arg" = "X-lc" && continue
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test "$build_libtool_need_lc" = "yes"; then
+ deplibs="$deplibs -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=""
+ versuffix=""
+ major=""
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behavior.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $rm conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $rm conftest
+ $LTCC -o conftest conftest.c $deplibs
+ if test "$?" -eq 0 ; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" -ne "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which I believe you do not have"
+ $echo "*** because a test_compile did reveal that the linker did not use it for"
+ $echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ name="`expr $i : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ $rm conftest
+ $LTCC -o conftest conftest.c $i
+ # Did it work?
+ if test "$?" -eq 0 ; then
+ ldd_output=`ldd conftest`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ newdeplibs="$newdeplibs $i"
+ i=""
+ ;;
+ esac
+ fi
+ if test -n "$i" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ deplib_matches=`eval \\$echo \"$library_names_spec\"`
+ set dummy $deplib_matches
+ deplib_match=$2
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then
+ newdeplibs="$newdeplibs $i"
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: dynamic linker does not accept needed library $i."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because a test_compile did reveal that the linker did not use this one"
+ $echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning! Library $i is needed by this library but I was not able to"
+ $echo "*** make it link in! You will probably need to install it or some"
+ $echo "*** library that it depends on before this library will be fully"
+ $echo "*** functional. Installing it before continuing would be even better."
+ fi
+ else
+ newdeplibs="$newdeplibs $i"
+ fi
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method
+ file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test "$name" != "" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null \
+ | grep " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib="$potent_lib"
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";;
+ *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$file_magic_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method
+ match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+ for a_deplib in $deplibs; do
+ name="`expr $a_deplib : '-l\(.*\)'`"
+ # If $name is empty we are operating on a -L argument.
+ if test -n "$name" && test "$name" != "0"; then
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib" ; then
+ libname=`eval \\$echo \"$libname_spec\"`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib="$potent_lib" # see symlink-check above in file_magic test
+ if eval $echo \"$potent_lib\" 2>/dev/null \
+ | ${SED} 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ newdeplibs="$newdeplibs $a_deplib"
+ a_deplib=""
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib" ; then
+ droppeddeps=yes
+ $echo
+ $echo "*** Warning: linker path does not have real file for library $a_deplib."
+ $echo "*** I have the capability to make that library automatically link in when"
+ $echo "*** you link to this library. But I can only do this if you have a"
+ $echo "*** shared version of the library, which you do not appear to have"
+ $echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib" ; then
+ $echo "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ $echo "*** with $libname and none of the candidates passed a file format test"
+ $echo "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ else
+ # Add a -L argument.
+ newdeplibs="$newdeplibs $a_deplib"
+ fi
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=""
+ tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \
+ -e 's/ -[LR][^ ]*//g'`
+ if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
+ for i in $predeps $postdeps ; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"`
+ done
+ fi
+ if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \
+ | grep . >/dev/null; then
+ $echo
+ if test "X$deplibs_check_method" = "Xnone"; then
+ $echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ $echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ $echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ fi
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ if test "$droppeddeps" = yes; then
+ if test "$module" = yes; then
+ $echo
+ $echo "*** Warning: libtool could not satisfy all declared inter-library"
+ $echo "*** dependencies of module $libname. Therefore, libtool will create"
+ $echo "*** a static module, that should work as long as the dlopening"
+ $echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ $echo
+ $echo "*** However, this would only work if libtool was able to extract symbol"
+ $echo "*** lists from a program, using \`nm' or equivalent, but libtool could"
+ $echo "*** not find such a program. So, this module is probably useless."
+ $echo "*** \`nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ $echo "*** The inter-library dependencies that have been dropped here will be"
+ $echo "*** automatically added whenever a program is linked with this library"
+ $echo "*** or is declared to -dlopen it."
+
+ if test "$allow_undefined" = no; then
+ $echo
+ $echo "*** Since this library must not contain undefined symbols,"
+ $echo "*** because either the platform does not support them or"
+ $echo "*** it was explicitly requested with -no-undefined,"
+ $echo "*** libtool will only create a static version of it."
+ if test "$build_old_libs" = no; then
+ oldlibs="$output_objdir/$libname.$libext"
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test "$build_libtool_libs" = yes; then
+ if test "$hardcode_into_libs" = yes; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath="$finalize_rpath"
+ test "$mode" != relink && rpath="$compile_rpath$rpath"
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ dep_rpath="$dep_rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ if test -n "$hardcode_libdir_flag_spec_ld"; then
+ eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\"
+ else
+ eval dep_rpath=\"$hardcode_libdir_flag_spec\"
+ fi
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath="$finalize_shlibpath"
+ test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath"
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval shared_ext=\"$shrext_cmds\"
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ realname="$2"
+ shift; shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname="$realname"
+ fi
+ if test -z "$dlname"; then
+ dlname=$soname
+ fi
+
+ lib="$output_objdir/$realname"
+ for link
+ do
+ linknames="$linknames $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ cmds=$export_symbols_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ if len=`expr "X$cmd" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ skipped_export=false
+ else
+ # The command line is too long to execute in one step.
+ $show "using reloadable object file for export list..."
+ skipped_export=:
+ fi
+ done
+ IFS="$save_ifs"
+ if test -n "$export_symbols_regex"; then
+ $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\""
+ $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ $show "$mv \"${export_symbols}T\" \"$export_symbols\""
+ $run eval '$mv "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"'
+ fi
+
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ case " $convenience " in
+ *" $test_deplib "*) ;;
+ *)
+ tmp_deplibs="$tmp_deplibs $test_deplib"
+ ;;
+ esac
+ done
+ deplibs="$tmp_deplibs"
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ libobjs="$libobjs $func_extract_archives_result"
+ fi
+ fi
+
+ if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ linker_flags="$linker_flags $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ eval test_cmds=\"$module_expsym_cmds\"
+ cmds=$module_expsym_cmds
+ else
+ eval test_cmds=\"$module_cmds\"
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval test_cmds=\"$archive_expsym_cmds\"
+ cmds=$archive_expsym_cmds
+ else
+ eval test_cmds=\"$archive_cmds\"
+ cmds=$archive_cmds
+ fi
+ fi
+
+ if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ :
+ else
+ # The command line is too long to link in one step, link piecewise.
+ $echo "creating reloadable object files..."
+
+ # Save the value of $output and $libobjs because we want to
+ # use them later. If we have whole_archive_flag_spec, we
+ # want to use save_libobjs as it was before
+ # whole_archive_flag_spec was expanded, because we can't
+ # assume the linker understands whole_archive_flag_spec.
+ # This may have to be revisited, in case too many
+ # convenience libraries get linked in and end up exceeding
+ # the spec.
+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ fi
+ save_output=$output
+
+ # Clear the reloadable object creation command queue and
+ # initialize k to one.
+ test_cmds=
+ concat_cmds=
+ objlist=
+ delfiles=
+ last_robj=
+ k=1
+ output=$output_objdir/$save_output-${k}.$objext
+ # Loop over the list of objects to be linked.
+ for obj in $save_libobjs
+ do
+ eval test_cmds=\"$reload_cmds $objlist $last_robj\"
+ if test "X$objlist" = X ||
+ { len=`expr "X$test_cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len"; }; then
+ objlist="$objlist $obj"
+ else
+ # The command $test_cmds is almost too long, add a
+ # command to the queue.
+ if test "$k" -eq 1 ; then
+ # The first file doesn't have a previous command to add.
+ eval concat_cmds=\"$reload_cmds $objlist $last_robj\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
+ fi
+ last_robj=$output_objdir/$save_output-${k}.$objext
+ k=`expr $k + 1`
+ output=$output_objdir/$save_output-${k}.$objext
+ objlist=$obj
+ len=1
+ fi
+ done
+ # Handle the remaining objects by creating one last
+ # reloadable object file. All subsequent reloadable object
+ # files will link in the last one created.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\"
+
+ if ${skipped_export-false}; then
+ $show "generating symbol list for \`$libname.la'"
+ export_symbols="$output_objdir/$libname.exp"
+ $run $rm $export_symbols
+ libobjs=$output
+ # Append the command to create the export file.
+ eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
+ fi
+
+ # Set up a command to remove the reloadale object files
+ # after they are used.
+ i=0
+ while test "$i" -lt "$k"
+ do
+ i=`expr $i + 1`
+ delfiles="$delfiles $output_objdir/$save_output-${i}.$objext"
+ done
+
+ $echo "creating a temporary reloadable object file: $output"
+
+ # Loop through the commands generated above and execute them.
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $concat_cmds; do
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ libobjs=$output
+ # Restore the value of output.
+ output=$save_output
+
+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ fi
+ # Expand the library linking commands again to reset the
+ # value of $libobjs for piecewise linking.
+
+ # Do each of the archive commands.
+ if test "$module" = yes && test -n "$module_cmds" ; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ cmds=$module_expsym_cmds
+ else
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ cmds=$archive_expsym_cmds
+ else
+ cmds=$archive_cmds
+ fi
+ fi
+
+ # Append the command to remove the reloadable object files
+ # to the just-reset $cmds.
+ eval cmds=\"\$cmds~\$rm $delfiles\"
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Restore the uninstalled library and exit
+ if test "$mode" = relink; then
+ $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $?
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test "$module" = yes || test "$export_dynamic" = yes; then
+ # On all known operating systems, these are identical.
+ dlname="$soname"
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$deplibs"; then
+ $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2
+ fi
+
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$rpath"; then
+ $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$xrpath"; then
+ $echo "$modename: warning: \`-R' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for objects" 1>&2
+ fi
+
+ case $output in
+ *.lo)
+ if test -n "$objs$old_deplibs"; then
+ $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ libobj="$output"
+ obj=`$echo "X$output" | $Xsed -e "$lo2o"`
+ ;;
+ *)
+ libobj=
+ obj="$output"
+ ;;
+ esac
+
+ # Delete the old objects.
+ $run $rm $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # reload_cmds runs $LD directly, so let us get rid of
+ # -Wl from whole_archive_flag_spec
+ wl=
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+ else
+ gentop="$output_objdir/${obj}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # Create the old-style object.
+ reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test
+
+ output="$obj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$build_libtool_libs" != yes; then
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ # $show "echo timestamp > $libobj"
+ # $run eval "echo timestamp > $libobj" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test -n "$pic_flag" || test "$pic_mode" != default; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output="$libobj"
+ cmds=$reload_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$gentop"; then
+ $show "${rm}r $gentop"
+ $run ${rm}r $gentop
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;;
+ esac
+ if test -n "$vinfo"; then
+ $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2
+ fi
+
+ if test -n "$release"; then
+ $echo "$modename: warning: \`-release' is ignored for programs" 1>&2
+ fi
+
+ if test "$preload" = yes; then
+ if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown &&
+ test "$dlopen_self_static" = unknown; then
+ $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support."
+ fi
+ fi
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'`
+ ;;
+ esac
+
+ case $host in
+ *darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ if test "$tagname" = CXX ; then
+ compile_command="$compile_command ${wl}-bind_at_load"
+ finalize_command="$finalize_command ${wl}-bind_at_load"
+ fi
+ ;;
+ esac
+
+ compile_command="$compile_command $compile_deplibs"
+ finalize_command="$finalize_command $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_rpath="$finalize_rpath $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) perm_rpath="$perm_rpath $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ *) dllsearchpath="$dllsearchpath:$libdir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath="$rpath"
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs="$libdir"
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ rpath="$rpath $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir="$hardcode_libdirs"
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath="$rpath"
+
+ if test -n "$libobjs" && test "$build_old_libs" = yes; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ fi
+
+ dlsyms=
+ if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ dlsyms="${outputname}S.c"
+ else
+ $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2
+ fi
+ fi
+
+ if test -n "$dlsyms"; then
+ case $dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist="$output_objdir/${outputname}.nm"
+
+ $show "$rm $nlist ${nlist}S ${nlist}T"
+ $run $rm "$nlist" "${nlist}S" "${nlist}T"
+
+ # Parse the name list into a source file.
+ $show "creating $output_objdir/$dlsyms"
+
+ test -z "$run" && $echo > "$output_objdir/$dlsyms" "\
+/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */
+/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+/* Prevent the only kind of declaration conflicts we can make. */
+#define lt_preloaded_symbols some_other_symbol
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test "$dlself" = yes; then
+ $show "generating symbol list for \`$output'"
+
+ test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP`
+ for arg in $progfiles; do
+ $show "extracting global C symbols from \`$arg'"
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ $run eval '$mv "$nlist"T "$nlist"'
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols="$output_objdir/$output.exp"
+ $run $rm $export_symbols
+ $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ else
+ $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
+ $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+ $run eval 'mv "$nlist"T "$nlist"'
+ fi
+ fi
+
+ for arg in $dlprefiles; do
+ $show "extracting global C symbols from \`$arg'"
+ name=`$echo "$arg" | ${SED} -e 's%^.*/%%'`
+ $run eval '$echo ": $name " >> "$nlist"'
+ $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -z "$run"; then
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $mv "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if grep -v "^: " < "$nlist" |
+ if sort -k 3 </dev/null >/dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ grep -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"'
+ else
+ $echo '/* NONE */' >> "$output_objdir/$dlsyms"
+ fi
+
+ $echo >> "$output_objdir/$dlsyms" "\
+
+#undef lt_preloaded_symbols
+
+#if defined (__STDC__) && __STDC__
+# define lt_ptr void *
+#else
+# define lt_ptr char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ lt_ptr address;
+}
+lt_preloaded_symbols[] =
+{\
+"
+
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms"
+
+ $echo >> "$output_objdir/$dlsyms" "\
+ {0, (lt_ptr) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ fi
+
+ pic_flag_for_symtable=
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";;
+ esac;;
+ *-*-hpux*)
+ case "$compile_command " in
+ *" -static "*) ;;
+ *) pic_flag_for_symtable=" $pic_flag";;
+ esac
+ esac
+
+ # Now compile the dynamic symbol file.
+ $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+ $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+
+ # Clean up the generated files.
+ $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
+ $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
+
+ # Transform the symbol file into the correct name.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+ ;;
+ *)
+ $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
+ finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+ fi
+
+ if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
+ # Replace the output file specification.
+ compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ link_command="$compile_command$compile_rpath"
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ $show "$link_command"
+ $run eval "$link_command"
+ status=$?
+
+ # Delete the generated files.
+ if test -n "$dlsyms"; then
+ $show "$rm $output_objdir/${outputname}S.${objext}"
+ $run $rm "$output_objdir/${outputname}S.${objext}"
+ fi
+
+ exit $status
+ fi
+
+ if test -n "$shlibpath_var"; then
+ # We should set the shlibpath_var
+ rpath=
+ for dir in $temp_rpath; do
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*)
+ # Absolute path.
+ rpath="$rpath$dir:"
+ ;;
+ *)
+ # Relative path: add a thisdir entry.
+ rpath="$rpath\$thisdir/$dir:"
+ ;;
+ esac
+ done
+ temp_rpath="$rpath"
+ fi
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ rpath="$rpath$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test "$no_install" = yes; then
+ # We don't need to create a wrapper script.
+ link_command="$compile_var$compile_command$compile_rpath"
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $run $rm $output
+ # Link the executable and exit
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+ exit $EXIT_SUCCESS
+ fi
+
+ if test "$hardcode_action" = relink; then
+ # Fast installation is not supported
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+
+ $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2
+ $echo "$modename: \`$output' will be relinked during installation" 1>&2
+ else
+ if test "$fast_install" != no; then
+ link_command="$finalize_var$compile_command$finalize_rpath"
+ if test "$fast_install" = yes; then
+ relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+ else
+ # fast_install is set to needless
+ relink_command=
+ fi
+ else
+ link_command="$compile_var$compile_command$compile_rpath"
+ relink_command="$finalize_var$finalize_command$finalize_rpath"
+ fi
+ fi
+
+ # Replace the output file specification.
+ link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ $show "$link_command"
+ $run eval "$link_command" || exit $?
+
+ # Now create the wrapper script.
+ $show "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ relink_command="(cd `pwd`; $relink_command)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Quote $echo for shipping.
+ if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then
+ case $progpath in
+ [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";;
+ *) qecho="$SHELL `pwd`/$progpath --fallback-echo";;
+ esac
+ qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"`
+ else
+ qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if our run command is non-null.
+ if test -z "$run"; then
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*)
+ exeext=.exe
+ outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;;
+ *) exeext= ;;
+ esac
+ case $host in
+ *cygwin* | *mingw* )
+ cwrappersource=`$echo ${objdir}/lt-${output}.c`
+ cwrapper=`$echo ${output}.exe`
+ $rm $cwrappersource $cwrapper
+ trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+ cat > $cwrappersource <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+
+ Currently, it simply execs the wrapper *script* "/bin/sh $output",
+ but could eventually absorb all of the scripts functionality and
+ exec $objdir/$outputname directly.
+*/
+EOF
+ cat >> $cwrappersource<<"EOF"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#if defined(PATH_MAX)
+# define LT_PATHMAX PATH_MAX
+#elif defined(MAXPATHLEN)
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
+#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
+ defined (__OS2__)
+#define HAVE_DOS_BASED_FILE_SYSTEM
+#ifndef DIR_SEPARATOR_2
+#define DIR_SEPARATOR_2 '\\'
+#endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free ((void *) stale); stale = 0; } \
+} while (0)
+
+const char *program_name = NULL;
+
+void * xmalloc (size_t num);
+char * xstrdup (const char *string);
+char * basename (const char *name);
+char * fnqualify(const char *path);
+char * strendzap(char *str, const char *pat);
+void lt_fatal (const char *message, ...);
+
+int
+main (int argc, char *argv[])
+{
+ char **newargz;
+ int i;
+
+ program_name = (char *) xstrdup ((char *) basename (argv[0]));
+ newargz = XMALLOC(char *, argc+2);
+EOF
+
+ cat >> $cwrappersource <<EOF
+ newargz[0] = "$SHELL";
+EOF
+
+ cat >> $cwrappersource <<"EOF"
+ newargz[1] = fnqualify(argv[0]);
+ /* we know the script has the same name, without the .exe */
+ /* so make sure newargz[1] doesn't end in .exe */
+ strendzap(newargz[1],".exe");
+ for (i = 1; i < argc; i++)
+ newargz[i+1] = xstrdup(argv[i]);
+ newargz[argc+1] = NULL;
+EOF
+
+ cat >> $cwrappersource <<EOF
+ execv("$SHELL",newargz);
+EOF
+
+ cat >> $cwrappersource <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+ void * p = (void *) malloc (num);
+ if (!p)
+ lt_fatal ("Memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL
+;
+}
+
+char *
+basename (const char *name)
+{
+ const char *base;
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha (name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return (char *) base;
+}
+
+char *
+fnqualify(const char *path)
+{
+ size_t size;
+ char *p;
+ char tmp[LT_PATHMAX + 1];
+
+ assert(path != NULL);
+
+ /* Is it qualified already? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ if (isalpha (path[0]) && path[1] == ':')
+ return xstrdup (path);
+#endif
+ if (IS_DIR_SEPARATOR (path[0]))
+ return xstrdup (path);
+
+ /* prepend the current directory */
+ /* doesn't handle '~' */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal ("getcwd failed");
+ size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */
+ p = XMALLOC(char, size);
+ sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path);
+ return p;
+}
+
+char *
+strendzap(char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert(str != NULL);
+ assert(pat != NULL);
+
+ len = strlen(str);
+ patlen = strlen(pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (strcmp(str, pat) == 0)
+ *str = '\0';
+ }
+ return str;
+}
+
+static void
+lt_error_core (int exit_status, const char * mode,
+ const char * message, va_list ap)
+{
+ fprintf (stderr, "%s: %s: ", program_name, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, "FATAL", message, ap);
+ va_end (ap);
+}
+EOF
+ # we should really use a build-platform specific compiler
+ # here, but OTOH, the wrappers (shell script and this C one)
+ # are only useful if you want to execute the "real" binary.
+ # Since the "real" binary is built for $host, then this
+ # wrapper might as well be built for $host, too.
+ $run $LTCC -s -o $cwrapper $cwrappersource
+ ;;
+ esac
+ $rm $output
+ trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+
+ $echo > $output "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='${SED} -e 1s/^X//'
+sed_quote_subst='$sed_quote_subst'
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variable:
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$echo are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ echo=\"$qecho\"
+ file=\"\$0\"
+ # Make sure echo works.
+ if test \"X\$1\" = X--no-reexec; then
+ # Discard the --no-reexec flag, and continue.
+ shift
+ elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then
+ # Yippee, \$echo works!
+ :
+ else
+ # Restart under the correct shell, and then maybe \$echo will work.
+ exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"}
+ fi
+ fi\
+"
+ $echo >> $output "\
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\`
+ done
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test "$fast_install" = yes; then
+ $echo >> $output "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" || \\
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $mkdir \"\$progdir\"
+ else
+ $rm \"\$progdir/\$file\"
+ fi"
+
+ $echo >> $output "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ $echo \"\$relink_command_output\" >&2
+ $rm \"\$progdir/\$file\"
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $rm \"\$progdir/\$program\";
+ $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $rm \"\$progdir/\$file\"
+ fi"
+ else
+ $echo >> $output "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ $echo >> $output "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # Export our shlibpath_var if we have one.
+ if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $echo >> $output "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ # fixup the dll searchpath if we need to.
+ if test -n "$dllsearchpath"; then
+ $echo >> $output "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ $echo >> $output "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2*)
+ $echo >> $output "\
+ exec \$progdir\\\\\$program \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $echo >> $output "\
+ exec \$progdir/\$program \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $echo >> $output "\
+ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+ exit $EXIT_FAILURE
+ fi
+ else
+ # The program doesn't exist.
+ \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+ \$echo \"This script is just a wrapper for \$program.\" 1>&2
+ $echo \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi\
+"
+ chmod +x $output
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ if test "$build_libtool_libs" = convenience; then
+ oldobjs="$libobjs_save"
+ addlibs="$convenience"
+ build_libtool_libs=no
+ else
+ if test "$build_libtool_libs" = module; then
+ oldobjs="$libobjs_save"
+ build_libtool_libs=no
+ else
+ oldobjs="$old_deplibs $non_pic_objects"
+ fi
+ addlibs="$old_convenience"
+ fi
+
+ if test -n "$addlibs"; then
+ gentop="$output_objdir/${outputname}x"
+ generated="$generated $gentop"
+
+ func_extract_archives $gentop $addlibs
+ oldobjs="$oldobjs $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
+ cmds=$old_archive_from_new_cmds
+ else
+ eval cmds=\"$old_archive_cmds\"
+
+ if len=`expr "X$cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ cmds=$old_archive_cmds
+ else
+ # the command line is too long to link in one step, link in parts
+ $echo "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+ # GNU ar 2.10+ was changed to match POSIX; thus no paths are
+ # encoded into archives. This makes 'ar r' malfunction in
+ # this piecewise linking case whenever conflicting object
+ # names appear in distinct ar calls; check, warn and compensate.
+ if (for obj in $save_oldobjs
+ do
+ $echo "X$obj" | $Xsed -e 's%^.*/%%'
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2
+ $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2
+ AR_FLAGS=cq
+ fi
+ # Is there a better way of finding the last object in the list?
+ for obj in $save_oldobjs
+ do
+ last_oldobj=$obj
+ done
+ for obj in $save_oldobjs
+ do
+ oldobjs="$objlist $obj"
+ objlist="$objlist $obj"
+ eval test_cmds=\"$old_archive_cmds\"
+ if len=`expr "X$test_cmds" : ".*"` &&
+ test "$len" -le "$max_cmd_len"; then
+ :
+ else
+ # the above command should be used before it gets too long
+ oldobjs=$objlist
+ if test "$obj" = "$last_oldobj" ; then
+ RANLIB=$save_RANLIB
+ fi
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\"
+ objlist=
+ fi
+ done
+ RANLIB=$save_RANLIB
+ oldobjs=$objlist
+ if test "X$oldobjs" = "X" ; then
+ eval cmds=\"\$concat_cmds\"
+ else
+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+ fi
+ fi
+ fi
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ eval cmd=\"$cmd\"
+ IFS="$save_ifs"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$generated"; then
+ $show "${rm}r$generated"
+ $run ${rm}r$generated
+ fi
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test "$build_old_libs" = yes && old_library="$libname.$libext"
+ $show "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"`
+ relink_command="$var=\"$var_value\"; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+ if test "$hardcode_automatic" = yes ; then
+ relink_command=
+ fi
+
+
+ # Only create the output if not a dry run.
+ if test -z "$run"; then
+ for installed in no yes; do
+ if test "$installed" = yes; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output="$output_objdir/$outputname"i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdependency_libs="$newdependency_libs $libdir/$name"
+ ;;
+ *) newdependency_libs="$newdependency_libs $deplib" ;;
+ esac
+ done
+ dependency_libs="$newdependency_libs"
+ newdlfiles=
+ for lib in $dlfiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlfiles="$newdlfiles $libdir/$name"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'`
+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ if test -z "$libdir"; then
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ newdlprefiles="$newdlprefiles $libdir/$name"
+ done
+ dlprefiles="$newdlprefiles"
+ else
+ newdlfiles=
+ for lib in $dlfiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlfiles="$newdlfiles $abs"
+ done
+ dlfiles="$newdlfiles"
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ newdlprefiles="$newdlprefiles $abs"
+ done
+ dlprefiles="$newdlprefiles"
+ fi
+ $rm $output
+ # place dlname in correct position for cygwin
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;;
+ esac
+ $echo > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test "$installed" = no && test "$need_relink" = yes; then
+ $echo >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ fi
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)"
+ $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $?
+ ;;
+ esac
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool install mode
+ install)
+ modename="$modename: install"
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
+ # Allow the use of GNU shtool's install command.
+ $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
+ # Aesthetically quote it.
+ arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$arg "
+ arg="$1"
+ shift
+ else
+ install_prog=
+ arg="$nonopt"
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog$arg"
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=no
+ stripme=
+ for arg
+ do
+ if test -n "$dest"; then
+ files="$files $dest"
+ dest="$arg"
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=yes ;;
+ -f) prev="-f" ;;
+ -g) prev="-g" ;;
+ -m) prev="-m" ;;
+ -o) prev="-o" ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*) ;;
+
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ prev=
+ else
+ dest="$arg"
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
+ case $arg in
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*)
+ arg="\"$arg\""
+ ;;
+ esac
+ install_prog="$install_prog $arg"
+ done
+
+ if test -z "$install_prog"; then
+ $echo "$modename: you must specify an install program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$prev"; then
+ $echo "$modename: the \`$prev' option requires an argument" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ $echo "$modename: no file or destination specified" 1>&2
+ else
+ $echo "$modename: you must specify a destination" 1>&2
+ fi
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Strip any trailing slash from the destination.
+ dest=`$echo "X$dest" | $Xsed -e 's%/$%%'`
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=yes
+ if test "$isdir" = yes; then
+ destdir="$dest"
+ destname=
+ else
+ destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$destdir" = "X$dest" && destdir=.
+ destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'`
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files
+ if test "$#" -gt 2; then
+ $echo "$modename: \`$dest' is not a directory" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ staticlibs="$staticlibs $file"
+ ;;
+
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$file' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ library_names=
+ old_library=
+ relink_command=
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) current_libdirs="$current_libdirs $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) future_libdirs="$future_libdirs $libdir" ;;
+ esac
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/
+ test "X$dir" = "X$file/" && dir=
+ dir="$dir$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+ if test "$inst_prefix_dir" = "$destdir"; then
+ $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ else
+ relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ fi
+
+ $echo "$modename: warning: relinking \`$file'" 1>&2
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names
+ if test -n "$2"; then
+ realname="$2"
+ shift
+ shift
+
+ srcname="$realname"
+ test -n "$relink_command" && srcname="$realname"T
+
+ # Install the shared library and build the symlinks.
+ $show "$install_prog $dir/$srcname $destdir/$realname"
+ $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $?
+ if test -n "$stripme" && test -n "$striplib"; then
+ $show "$striplib $destdir/$realname"
+ $run eval "$striplib $destdir/$realname" || exit $?
+ fi
+
+ if test "$#" -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ for linkname
+ do
+ if test "$linkname" != "$realname"; then
+ $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+ fi
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib="$destdir/$realname"
+ cmds=$postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ fi
+
+ # Install the pseudo-library for information purposes.
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ instname="$dir/$name"i
+ $show "$install_prog $instname $destdir/$name"
+ $run eval "$install_prog $instname $destdir/$name" || exit $?
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"`
+ ;;
+ *.$objext)
+ staticdest="$destfile"
+ destfile=
+ ;;
+ *)
+ $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ if test -n "$destfile"; then
+ $show "$install_prog $file $destfile"
+ $run eval "$install_prog $file $destfile" || exit $?
+ fi
+
+ # Install the old object if enabled.
+ if test "$build_old_libs" = yes; then
+ # Deduce the name of the old-style object file.
+ staticobj=`$echo "X$file" | $Xsed -e "$lo2o"`
+
+ $show "$install_prog $staticobj $staticdest"
+ $run eval "$install_prog \$staticobj \$staticdest" || exit $?
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile="$destdir/$destname"
+ else
+ destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ destfile="$destdir/$destfile"
+ fi
+
+ # If the file is missing, and there is a .exe on the end, strip it
+ # because it is most likely a libtool script we actually want to
+ # install
+ stripped_ext=""
+ case $file in
+ *.exe)
+ if test ! -f "$file"; then
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ stripped_ext=".exe"
+ fi
+ ;;
+ esac
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin*|*mingw*)
+ wrapper=`$echo $file | ${SED} -e 's,.exe$,,'`
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then
+ notinst_deplibs=
+ relink_command=
+
+ # To insure that "foo" is sourced, and not "foo.exe",
+ # finese the cygwin/MSYS system by explicitly sourcing "foo."
+ # which disallows the automatic-append-.exe behavior.
+ case $build in
+ *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
+ *) wrapperdot=${wrapper} ;;
+ esac
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . ${wrapperdot} ;;
+ *) . ./${wrapperdot} ;;
+ esac
+
+ # Check the variables that should have been set.
+ if test -z "$notinst_deplibs"; then
+ $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ finalize=yes
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ # If there is no directory component, then add one.
+ case $lib in
+ */* | *\\*) . $lib ;;
+ *) . ./$lib ;;
+ esac
+ fi
+ libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2
+ finalize=no
+ fi
+ done
+
+ relink_command=
+ # To insure that "foo" is sourced, and not "foo.exe",
+ # finese the cygwin/MSYS system by explicitly sourcing "foo."
+ # which disallows the automatic-append-.exe behavior.
+ case $build in
+ *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
+ *) wrapperdot=${wrapper} ;;
+ esac
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . ${wrapperdot} ;;
+ *) . ./${wrapperdot} ;;
+ esac
+
+ outputname=
+ if test "$fast_install" = no && test -n "$relink_command"; then
+ if test "$finalize" = yes && test -z "$run"; then
+ tmpdir="/tmp"
+ test -n "$TMPDIR" && tmpdir="$TMPDIR"
+ tmpdir="$tmpdir/libtool-$$"
+ save_umask=`umask`
+ umask 0077
+ if $mkdir "$tmpdir"; then
+ umask $save_umask
+ else
+ umask $save_umask
+ $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
+ continue
+ fi
+ file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
+ outputname="$tmpdir/$file"
+ # Replace the output file specification.
+ relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $show "$relink_command"
+ if $run eval "$relink_command"; then :
+ else
+ $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2
+ ${rm}r "$tmpdir"
+ continue
+ fi
+ file="$outputname"
+ else
+ $echo "$modename: warning: cannot relink \`$file'" 1>&2
+ fi
+ else
+ # Install the binary that we compiled earlier.
+ file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyways
+ case $install_prog,$host in
+ */usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'`
+ ;;
+ esac
+ ;;
+ esac
+ $show "$install_prog$stripme $file $destfile"
+ $run eval "$install_prog\$stripme \$file \$destfile" || exit $?
+ test -n "$outputname" && ${rm}r "$tmpdir"
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+
+ # Set up the ranlib parameters.
+ oldlib="$destdir/$name"
+
+ $show "$install_prog $file $oldlib"
+ $run eval "$install_prog \$file \$oldlib" || exit $?
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ $show "$old_striplib $oldlib"
+ $run eval "$old_striplib $oldlib" || exit $?
+ fi
+
+ # Do each command in the postinstall commands.
+ cmds=$old_postinstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || exit $?
+ done
+ IFS="$save_ifs"
+ done
+
+ if test -n "$future_libdirs"; then
+ $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2
+ fi
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ test -n "$run" && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs'
+ else
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool finish mode
+ finish)
+ modename="$modename: finish"
+ libdirs="$nonopt"
+ admincmds=
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for dir
+ do
+ libdirs="$libdirs $dir"
+ done
+
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ cmds=$finish_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd" || admincmds="$admincmds
+ $cmd"
+ done
+ IFS="$save_ifs"
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $run eval "$cmds" || admincmds="$admincmds
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ test "$show" = : && exit $EXIT_SUCCESS
+
+ $echo "----------------------------------------------------------------------"
+ $echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ $echo " $libdir"
+ done
+ $echo
+ $echo "If you ever happen to want to link against installed libraries"
+ $echo "in a given directory, LIBDIR, you must either use libtool, and"
+ $echo "specify the full pathname of the library, or use the \`-LLIBDIR'"
+ $echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ $echo " - add LIBDIR to the \`$shlibpath_var' environment variable"
+ $echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ $echo " - add LIBDIR to the \`$runpath_var' environment variable"
+ $echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ $echo " - use the \`$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ $echo " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'"
+ fi
+ $echo
+ $echo "See any operating system documentation about shared libraries for"
+ $echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ $echo "----------------------------------------------------------------------"
+ exit $EXIT_SUCCESS
+ ;;
+
+ # libtool execute mode
+ execute)
+ modename="$modename: execute"
+
+ # The first argument is the command name.
+ cmd="$nonopt"
+ if test -z "$cmd"; then
+ $echo "$modename: you must specify a COMMAND" 1>&2
+ $echo "$help"
+ exit $EXIT_FAILURE
+ fi
+
+ # Handle -dlopen flags immediately.
+ for file in $execute_dlfiles; do
+ if test ! -f "$file"; then
+ $echo "$modename: \`$file' is not a file" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ dir=
+ case $file in
+ *.la)
+ # Check to see that this really is a libtool archive.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then :
+ else
+ $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'"
+ continue
+ fi
+
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+
+ if test -f "$dir/$objdir/$dlname"; then
+ dir="$dir/$objdir"
+ else
+ $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2
+ exit $EXIT_FAILURE
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ test "X$dir" = "X$file" && dir=.
+ ;;
+
+ *)
+ $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir="$absdir"
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic="$magic"
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -*) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ # If there is no directory component, then add one.
+ case $file in
+ */* | *\\*) . $file ;;
+ *) . ./$file ;;
+ esac
+
+ # Transform arg to wrapped name.
+ file="$progdir/$program"
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"`
+ args="$args \"$file\""
+ done
+
+ if test -z "$run"; then
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved environment variables
+ if test "${save_LC_ALL+set}" = set; then
+ LC_ALL="$save_LC_ALL"; export LC_ALL
+ fi
+ if test "${save_LANG+set}" = set; then
+ LANG="$save_LANG"; export LANG
+ fi
+
+ # Now prepare to actually exec the command.
+ exec_cmd="\$cmd$args"
+ else
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\""
+ $echo "export $shlibpath_var"
+ fi
+ $echo "$cmd$args"
+ exit $EXIT_SUCCESS
+ fi
+ ;;
+
+ # libtool clean and uninstall mode
+ clean | uninstall)
+ modename="$modename: $mode"
+ rm="$nonopt"
+ files=
+ rmforce=
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic="$magic"
+
+ for arg
+ do
+ case $arg in
+ -f) rm="$rm $arg"; rmforce=yes ;;
+ -*) rm="$rm $arg" ;;
+ *) files="$files $arg" ;;
+ esac
+ done
+
+ if test -z "$rm"; then
+ $echo "$modename: you must specify an RM program" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ rmdirs=
+
+ origobjdir="$objdir"
+ for file in $files; do
+ dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
+ if test "X$dir" = "X$file"; then
+ dir=.
+ objdir="$origobjdir"
+ else
+ objdir="$dir/$origobjdir"
+ fi
+ name=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
+ test "$mode" = uninstall && objdir="$dir"
+
+ # Remember objdir for removal later, being careful to avoid duplicates
+ if test "$mode" = clean; then
+ case " $rmdirs " in
+ *" $objdir "*) ;;
+ *) rmdirs="$rmdirs $objdir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if (test -L "$file") >/dev/null 2>&1 \
+ || (test -h "$file") >/dev/null 2>&1 \
+ || test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif test "$rmforce" = yes; then
+ continue
+ fi
+
+ rmfiles="$file"
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ . $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ rmfiles="$rmfiles $objdir/$n"
+ done
+ test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
+ test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+
+ if test "$mode" = uninstall; then
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ cmds=$postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ cmds=$old_postuninstall_cmds
+ save_ifs="$IFS"; IFS='~'
+ for cmd in $cmds; do
+ IFS="$save_ifs"
+ eval cmd=\"$cmd\"
+ $show "$cmd"
+ $run eval "$cmd"
+ if test "$?" -ne 0 && test "$rmforce" != yes; then
+ exit_status=1
+ fi
+ done
+ IFS="$save_ifs"
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ fi
+ fi
+ ;;
+
+ *.lo)
+ # Possibly a libtool object, so verify it.
+ if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+
+ # Read the .lo file
+ . $dir/$name
+
+ # Add PIC object to the list of files to remove.
+ if test -n "$pic_object" \
+ && test "$pic_object" != none; then
+ rmfiles="$rmfiles $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" \
+ && test "$non_pic_object" != none; then
+ rmfiles="$rmfiles $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test "$mode" = clean ; then
+ noexename=$name
+ case $file in
+ *.exe)
+ file=`$echo $file|${SED} 's,.exe$,,'`
+ noexename=`$echo $name|${SED} 's,.exe$,,'`
+ # $file with .exe has already been added to rmfiles,
+ # add $file without .exe
+ rmfiles="$rmfiles $file"
+ ;;
+ esac
+ # Do a test to see if this is a libtool program.
+ if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then
+ relink_command=
+ . $dir/$noexename
+
+ # note $name still contains .exe if it was in $file originally
+ # as does the version of $file that was added into $rmfiles
+ rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}"
+ if test "$fast_install" = yes && test -n "$relink_command"; then
+ rmfiles="$rmfiles $objdir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name" ; then
+ rmfiles="$rmfiles $objdir/lt-${noexename}.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ $show "$rm $rmfiles"
+ $run $rm $rmfiles || exit_status=1
+ done
+ objdir="$origobjdir"
+
+ # Try to remove the ${objdir}s in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ $show "rmdir $dir"
+ $run rmdir $dir >/dev/null 2>&1
+ fi
+ done
+
+ exit $exit_status
+ ;;
+
+ "")
+ $echo "$modename: you must specify a MODE" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+ esac
+
+ if test -z "$exec_cmd"; then
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$generic_help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+fi # test -z "$show_help"
+
+if test -n "$exec_cmd"; then
+ eval exec $exec_cmd
+ exit $EXIT_FAILURE
+fi
+
+# We need to display help for each of the modes.
+case $mode in
+"") $echo \
+"Usage: $modename [OPTION]... [MODE-ARG]...
+
+Provide generalized library-building support services.
+
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+-n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --finish same as \`--mode=finish'
+ --help display this help message and exit
+ --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS]
+ --quiet same as \`--silent'
+ --silent don't print informational messages
+ --tag=TAG use configuration variables from tag TAG
+ --version print version information
+
+MODE must be one of the following:
+
+ clean remove files from the build directory
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for
+a more detailed description of MODE.
+
+Report bugs to <bug-libtool@gnu.org>."
+ exit $EXIT_SUCCESS
+ ;;
+
+clean)
+ $echo \
+"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+compile)
+ $echo \
+"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -prefer-pic try to building PIC objects only
+ -prefer-non-pic try to building non-PIC objects only
+ -static always build a \`.o' file suitable for static linking
+
+COMPILE-COMMAND is a command to be used in creating a \`standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix \`.c' with the
+library object suffix, \`.lo'."
+ ;;
+
+execute)
+ $echo \
+"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to \`-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+finish)
+ $echo \
+"Usage: $modename [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the \`--dry-run' option if you just want to see what would be executed."
+ ;;
+
+install)
+ $echo \
+"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the \`install' or \`cp' program.
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+link)
+ $echo \
+"Usage: $modename [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -objectlist FILE Use a list of object files found in FILE to specify objects
+ -precious-files-regex REGEX
+ don't remove output files matching REGEX
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -static do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+
+All other options (arguments beginning with \`-') are ignored.
+
+Every other argument is treated as a filename. Files ending in \`.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in \`.la', then a libtool library is created,
+only library objects (\`.lo' files) may be specified, and \`-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created
+using \`ar' and \`ranlib', or on Windows using \`lib'.
+
+If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+uninstall)
+ $echo \
+"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+*)
+ $echo "$modename: invalid operation mode \`$mode'" 1>&2
+ $echo "$help" 1>&2
+ exit $EXIT_FAILURE
+ ;;
+esac
+
+$echo
+$echo "Try \`$modename --help' for more information about other modes."
+
+exit $EXIT_SUCCESS
+
+# The TAGs below are defined such that we never get into a situation
+# in which we disable both kinds of libraries. Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them. This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration. But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/make/Makefile.in b/make/Makefile.in
new file mode 100644
index 0000000..cffd561
--- /dev/null
+++ b/make/Makefile.in
@@ -0,0 +1,28 @@
+# Copyright (C) 2004, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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.16 2007/06/19 23:47:24 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+SUBDIRS=
+TARGETS=
+
+@BIND9_MAKE_RULES@
+
+distclean::
+ rm -f rules mkdep includes
diff --git a/make/includes.in b/make/includes.in
new file mode 100644
index 0000000..8e5750c
--- /dev/null
+++ b/make/includes.in
@@ -0,0 +1,48 @@
+# Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1999-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: includes.in,v 1.21 2007/06/19 23:47:24 tbox Exp $
+
+# Search for machine-generated header files in the build tree,
+# and for normal headers in the source tree (${top_srcdir}).
+# We only need to look in OS-specific subdirectories for the
+# latter case, because there are no machine-generated OS-specific
+# headers.
+
+ISC_INCLUDES = @BIND9_ISC_BUILDINCLUDE@ \
+ -I${top_srcdir}/lib/isc \
+ -I${top_srcdir}/lib/isc/include \
+ -I${top_srcdir}/lib/isc/unix/include \
+ -I${top_srcdir}/lib/isc/@ISC_THREAD_DIR@/include \
+ -I${top_srcdir}/lib/isc/@ISC_ARCH_DIR@/include
+
+ISCCC_INCLUDES = @BIND9_ISCCC_BUILDINCLUDE@ \
+ -I${top_srcdir}/lib/isccc/include
+
+ISCCFG_INCLUDES = @BIND9_ISCCFG_BUILDINCLUDE@ \
+ -I${top_srcdir}/lib/isccfg/include
+
+DNS_INCLUDES = @BIND9_DNS_BUILDINCLUDE@ \
+ -I${top_srcdir}/lib/dns/include
+
+LWRES_INCLUDES = @BIND9_LWRES_BUILDINCLUDE@ \
+ -I${top_srcdir}/lib/lwres/unix/include \
+ -I${top_srcdir}/lib/lwres/include
+
+BIND9_INCLUDES = @BIND9_BIND9_BUILDINCLUDE@ \
+ -I${top_srcdir}/lib/bind9/include
+
+TEST_INCLUDES = \
+ -I${top_srcdir}/lib/tests/include
diff --git a/make/mkdep.in b/make/mkdep.in
new file mode 100644
index 0000000..bb536c9
--- /dev/null
+++ b/make/mkdep.in
@@ -0,0 +1,175 @@
+#!/bin/sh -
+
+##
+## Modified to handle -vpath <path> option by Michael Graff, ISC.
+## The purpose of this is to allow this script to run outside of the
+## source directory, for instance when running configure with
+## ../bind9-mainline/configure
+## and still have "make depend" work.
+##
+
+## ++Copyright++ 1987
+## -
+## Copyright (c) 1987 Regents of the University of California.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions
+## are met:
+## 1. Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## 2. Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in the
+## documentation and/or other materials provided with the distribution.
+## 3. All advertising materials mentioning features or use of this software
+## must display the following acknowledgement:
+## This product includes software developed by the University of
+## California, Berkeley and its contributors.
+## 4. Neither the name of the University nor the names of its contributors
+## may be used to endorse or promote products derived from this software
+## without specific prior written permission.
+## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+## ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+## SUCH DAMAGE.
+## -
+## Portions Copyright (c) 1993 by Digital Equipment Corporation.
+##
+## Permission to use, copy, modify, and distribute this software for any
+## purpose with or without fee is hereby granted, provided that the above
+## copyright notice and this permission notice appear in all copies, and that
+## the name of Digital Equipment Corporation not be used in advertising or
+## publicity pertaining to distribution of the document or software without
+## specific, written prior permission.
+##
+## THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+## WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+## CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+## DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+## PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+## SOFTWARE.
+## -
+## --Copyright--
+
+#
+# @(#)mkdep.sh 5.12 (Berkeley) 6/30/88
+#
+
+MAKE=Makefile # default makefile name is "Makefile"
+
+while :
+ do case "$1" in
+ # -vpath allows one to select a virtual path for .c files
+ -vpath)
+ VPATH=$2;
+ shift; shift ;;
+ # -f allows you to select a makefile name
+ -f)
+ MAKE=$2
+ shift; shift ;;
+
+ # the -p flag produces "program: program.c" style dependencies
+ # so .o's don't get produced
+ -p)
+ SED='s;\.o;;'
+ shift ;;
+ *)
+ break ;;
+ esac
+done
+
+if [ $# = 0 ] ; then
+ echo 'usage: mkdep [-vpath path] [-p] [-f makefile] [flags] file ...'
+ exit 1
+fi
+
+if [ ! -w $MAKE ]; then
+ echo "mkdep: no writeable file \"$MAKE\""
+ exit 1
+fi
+
+TMP=mkdep$$
+
+trap 'rm -f $TMP ; exit 1' 1 2 3 13 15
+
+cp $MAKE ${MAKE}.bak
+
+sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP
+
+cat << _EOF_ >> $TMP
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+_EOF_
+
+# If your compiler doesn't have -M, add it. If you can't, the next two
+# lines will try and replace the "cc -M". The real problem is that this
+# hack can't deal with anything that requires a search path, and doesn't
+# even try for anything using bracket (<>) syntax.
+#
+# egrep '^#include[ ]*".*"' /dev/null $* |
+# sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
+
+if [ X"${VPATH}" != X ] ; then
+ for arg in $* ; do
+ case "$arg" in
+ -*)
+ newargs="$newargs $arg"
+ ;;
+ *)
+ newargs="$newargs $VPATH/$arg"
+ ;;
+ esac
+ done
+else
+ newargs="$*";
+fi
+
+MKDEPPROG="@MKDEPPROG@"
+if [ X"${MKDEPPROG}" != X ]; then
+ @SHELL@ -c "${MKDEPPROG} ${newargs}"
+else
+ @MKDEPCC@ @MKDEPCFLAGS@ ${newargs} |
+ sed "
+ s; \./; ;g
+ @LIBTOOL_MKDEP_SED@
+ $SED" |
+ awk '{
+ if ($1 != prev) {
+ if (rec != "")
+ print rec;
+ rec = $0;
+ prev = $1;
+ }
+ else {
+ if (length(rec $2) > 78) {
+ print rec;
+ rec = $0;
+ }
+ else
+ rec = rec " " $2
+ }
+ }
+ END {
+ print rec
+ }' >> $TMP
+fi
+
+cat << _EOF_ >> $TMP
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
+_EOF_
+
+# copy to preserve permissions
+cp $TMP $MAKE
+rm -f ${MAKE}.bak $TMP
+exit 0
diff --git a/make/rules.in b/make/rules.in
new file mode 100644
index 0000000..6d8f360
--- /dev/null
+++ b/make/rules.in
@@ -0,0 +1,250 @@
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 1998-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: rules.in,v 1.64 2008/02/18 23:46:59 tbox Exp $
+
+###
+### Common Makefile rules for BIND 9.
+###
+
+###
+### Paths
+###
+### Note: paths that vary by Makefile MUST NOT be listed
+### here, or they won't get expanded correctly.
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+sbindir = @sbindir@
+includedir = @includedir@
+libdir = @libdir@
+sysconfdir = @sysconfdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+
+DESTDIR =
+
+@SET_MAKE@
+
+top_builddir = @BIND9_TOP_BUILDDIR@
+
+###
+### All
+###
+### Makefile may define:
+### TARGETS
+
+all: subdirs ${TARGETS}
+
+###
+### Subdirectories
+###
+### Makefile may define:
+### SUBDIRS
+
+ALL_SUBDIRS = ${SUBDIRS} nulldir
+
+#
+# We use a single-colon rule so that additional dependencies of
+# subdirectories can be specified after the inclusion of this file.
+# The "depend" target is treated the same way.
+#
+subdirs:
+ @for i in ${ALL_SUBDIRS}; do \
+ if [ "$$i" != "nulldir" -a -d $$i ]; then \
+ echo "making all in `pwd`/$$i"; \
+ (cd $$i; ${MAKE} ${MAKEDEFS} DESTDIR="${DESTDIR}" all) || exit 1; \
+ fi; \
+ done
+
+install:: all
+
+install clean distclean maintainer-clean doc docclean man manclean::
+ @for i in ${ALL_SUBDIRS}; do \
+ if [ "$$i" != "nulldir" -a -d $$i ]; then \
+ echo "making $@ in `pwd`/$$i"; \
+ (cd $$i; ${MAKE} ${MAKEDEFS} DESTDIR="${DESTDIR}" $@) || exit 1; \
+ fi; \
+ done
+
+###
+### C Programs
+###
+### Makefile must define
+### CC
+### Makefile may define
+### CFLAGS
+### LDFLAGS
+### CINCLUDES
+### CDEFINES
+### CWARNINGS
+### User may define externally
+### EXT_CFLAGS
+
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+STD_CINCLUDES = @STD_CINCLUDES@
+STD_CDEFINES = @STD_CDEFINES@
+STD_CWARNINGS = @STD_CWARNINGS@
+
+BUILD_CC = @BUILD_CC@
+BUILD_CFLAGS = @BUILD_CFLAGS@
+BUILD_CPPFLAGS = @BUILD_CPPFLAGS@
+BUILD_LDFLAGS = @BUILD_LDFLAGS@
+BUILD_LIBS = @BUILD_LIBS@
+
+.SUFFIXES:
+.SUFFIXES: .c .@O@
+
+ALWAYS_INCLUDES = -I${top_builddir}
+ALWAYS_DEFINES = @ALWAYS_DEFINES@
+ALWAYS_WARNINGS =
+
+ALL_CPPFLAGS = \
+ ${ALWAYS_INCLUDES} ${CINCLUDES} ${STD_CINCLUDES} \
+ ${ALWAYS_DEFINES} ${CDEFINES} ${STD_CDEFINES}
+
+ALL_CFLAGS = ${EXT_CFLAGS} ${ALL_CPPFLAGS} ${CFLAGS} \
+ ${ALWAYS_WARNINGS} ${STD_CWARNINGS} ${CWARNINGS}
+
+.c.@O@:
+ ${LIBTOOL_MODE_COMPILE} ${CC} ${ALL_CFLAGS} -c $<
+
+SHELL = @SHELL@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_MODE_COMPILE = ${LIBTOOL} @LIBTOOL_MODE_COMPILE@
+LIBTOOL_MODE_INSTALL = ${LIBTOOL} @LIBTOOL_MODE_INSTALL@
+LIBTOOL_MODE_LINK = ${LIBTOOL} @LIBTOOL_MODE_LINK@
+PURIFY = @PURIFY@
+
+MKDEP = ${SHELL} ${top_builddir}/make/mkdep
+
+cleandir: distclean
+superclean: maintainer-clean
+
+clean distclean maintainer-clean::
+ rm -f *.@O@ *.o *.lo *.la core *.core .depend
+ rm -rf .libs
+
+distclean maintainer-clean::
+ rm -f Makefile
+
+depend:
+ @for i in ${ALL_SUBDIRS}; do \
+ if [ "$$i" != "nulldir" -a -d $$i ]; then \
+ echo "making depend in `pwd`/$$i"; \
+ (cd $$i; ${MAKE} ${MAKEDEFS} DESTDIR="${DESTDIR}" $@) || exit 1; \
+ fi; \
+ done
+ @if [ X"${VPATH}" != X ] ; then \
+ if [ X"${SRCS}" != X -a X"${PSRCS}" != X ] ; then \
+ echo ${MKDEP} -vpath ${VPATH} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \
+ ${MKDEP} -vpath ${VPATH} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \
+ echo ${MKDEP} -vpath ${VPATH} -ap ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \
+ ${MKDEP} -vpath ${VPATH} -ap ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \
+ ${DEPENDEXTRA} \
+ elif [ X"${SRCS}" != X ] ; then \
+ echo ${MKDEP} -vpath ${VPATH} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \
+ ${MKDEP} -vpath ${VPATH} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \
+ ${DEPENDEXTRA} \
+ elif [ X"${PSRCS}" != X ] ; then \
+ echo ${MKDEP} -vpath ${VPATH} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \
+ ${MKDEP} -vpath ${VPATH} -p ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \
+ ${DEPENDEXTRA} \
+ fi \
+ else \
+ if [ X"${SRCS}" != X -a X"${PSRCS}" != X ] ; then \
+ echo ${MKDEP} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \
+ ${MKDEP} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \
+ echo ${MKDEP} -ap ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \
+ ${MKDEP} -ap ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \
+ ${DEPENDEXTRA} \
+ elif [ X"${SRCS}" != X ] ; then \
+ echo ${MKDEP} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \
+ ${MKDEP} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${SRCS}; \
+ ${DEPENDEXTRA} \
+ elif [ X"${PSRCS}" != X ] ; then \
+ echo ${MKDEP} ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \
+ ${MKDEP} -p ${ALL_CPPFLAGS} ${ALL_CFLAGS} ${PSRCS}; \
+ ${DEPENDEXTRA} \
+ fi \
+ fi
+
+FORCE:
+
+###
+### Libraries
+###
+
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+RANLIB = @RANLIB@
+
+###
+### Installation
+###
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+LINK_PROGRAM = @LN_S@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+
+###
+### Programs used when generating documentation. It's ok for these
+### not to exist when not generating documentation.
+###
+
+XSLTPROC = @XSLTPROC@ --novalid --xinclude --nonet
+PERL = @PERL@
+LATEX = @LATEX@
+PDFLATEX = @PDFLATEX@
+W3M = @W3M@
+
+###
+### DocBook -> HTML
+### DocBook -> man page
+###
+
+.SUFFIXES: .docbook .html .1 .2 .3 .4 .5 .6 .7 .8
+
+.docbook.html:
+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-docbook-html.xsl $<
+
+.docbook.1:
+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $<
+
+.docbook.2:
+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $<
+
+.docbook.3:
+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $<
+
+.docbook.4:
+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $<
+
+.docbook.5:
+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $<
+
+.docbook.6:
+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $<
+
+.docbook.7:
+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $<
+
+.docbook.8:
+ ${XSLTPROC} -o $@ ${top_srcdir}/doc/xsl/isc-manpage.xsl $<
diff --git a/mkinstalldirs b/mkinstalldirs
new file mode 100755
index 0000000..4992567
--- /dev/null
+++ b/mkinstalldirs
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.1 2000/09/20 19:05:51 gson Exp $
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/version b/version
new file mode 100644
index 0000000..fd4ac87
--- /dev/null
+++ b/version
@@ -0,0 +1,10 @@
+# $Id: version,v 1.43 2008/11/16 21:16:48 marka Exp $
+#
+# This file must follow /bin/sh rules. It is imported directly via
+# configure.
+#
+MAJORVER=9
+MINORVER=6
+PATCHVER=0
+RELEASETYPE=rc
+RELEASEVER=1
diff --git a/win32utils/BINDBuild.dsw b/win32utils/BINDBuild.dsw
new file mode 100644
index 0000000..4b3fcf4
--- /dev/null
+++ b/win32utils/BINDBuild.dsw
@@ -0,0 +1,440 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "BINDInstall"="..\bin\win32\BINDInstall\BINDInstall.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "bindevt"="..\lib\win32\bindevt\bindevt.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "dig"="..\bin\dig\win32\dig.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libdns
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libbind9
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblwres
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name dighost
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "dighost"="..\bin\dig\win32\dighost.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "host"="..\bin\dig\win32\host.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libdns
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libbind9
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblwres
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name dighost
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "keygen"="..\bin\dnssec\win32\keygen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libdns
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name dnssectool
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libbind9"="..\lib\bind9\win32\libbind9.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libdns
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisccfg
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libdns"="..\lib\dns\win32\libdns.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libisc"="..\lib\isc\win32\libisc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libisccc"="..\lib\isccc\win32\libisccc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libisccfg"="..\lib\isccfg\win32\libisccfg.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "liblwres"="..\lib\lwres\win32\liblwres.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "named"="..\bin\named\win32\named.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libdns
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisccc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisccfg
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblwres
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libbind9
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "namedcheckconf"="..\bin\check\win32\namedcheckconf.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisccfg
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libdns
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name checktool
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "namedcheckzone"="..\bin\check\win32\namedcheckzone.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libdns
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name checktool
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "nslookup"="..\bin\dig\win32\nslookup.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libdns
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libbind9
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblwres
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name dighost
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "nsupdate"="..\bin\nsupdate\win32\nsupdate.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libdns
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libbind9
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "rndc"="..\bin\rndc\win32\rndc.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisccc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisccfg
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libbind9
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name rndcutil
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "rndcconfgen"="..\bin\rndc\win32\confgen.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name rndcutil
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "signzone"="..\bin\dnssec\win32\signzone.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libdns
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libisc
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name dnssectool
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "dnssectool"="..\bin\dnssec\win32\dnssectool.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "rndcutil"="..\bin\rndc\win32\rndcutil.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "checktool"="..\bin\check\win32\checktool.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/win32utils/BuildAll.bat b/win32utils/BuildAll.bat
new file mode 100644
index 0000000..36b87cf
--- /dev/null
+++ b/win32utils/BuildAll.bat
@@ -0,0 +1,123 @@
+echo off
+rem
+rem Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+rem Copyright (C) 2001-2002 Internet Software Consortium.
+rem
+rem Permission to use, copy, modify, and distribute this software for any
+rem purpose with or without fee is hereby granted, provided that the above
+rem copyright notice and this permission notice appear in all copies.
+rem
+rem THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+rem REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+rem AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+rem INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+rem LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+rem OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+rem PERFORMANCE OF THIS SOFTWARE.
+
+rem BuildAll.bat
+rem This script sets up the files necessary ready to build BIND 9
+rem and then builds all of the binaries that make up the installation kit.
+rem This requires perl to be installed on the system.
+
+rem IMPORTANT NOTE:
+rem OpenSSL is a prerequisite for building and running this release of
+rem BIND 9. You must fetch the OpenSSL sources yourself from
+rem http://www.OpenSSL.org/ and compile it yourself. The code must reside
+rem at the same level as the bind 9.2.0 source tree and it's top-level
+rem directory be named openssl-0.9.6k. This restriction will be lifted in
+rem a future release of BIND 9 for Windows NT/2000/XP.
+
+echo Setting up the BIND files required for the build
+
+rem Setup the files
+call BuildSetup.bat
+
+echo Build all of the Library files
+
+cd ..\lib
+
+cd isc\win32
+nmake /nologo -f libisc.mak CFG="libisc - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+cd dns\win32
+nmake /nologo -f libdns.mak CFG="libdns - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+cd isccfg\win32
+nmake /nologo -f libisccfg.mak CFG="libisccfg - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+cd isccc\win32
+nmake /nologo -f libisccc.mak CFG="libisccc - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+cd bind9\win32
+nmake /nologo -f libbind9.mak CFG="libbind9 - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+cd lwres\win32
+nmake /nologo -f liblwres.mak CFG="liblwres - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+rem This is the DLL required for the event Viewer
+
+cd win32\bindevt
+nmake /nologo -f bindevt.mak CFG="bindevt - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+cd ..
+
+echo Now build the apps
+
+cd bin
+
+cd named\win32
+nmake /nologo -f named.mak CFG="named - Win32 Release" NO_EXTERNAL_DEPS="1"
+
+cd ..\..
+
+cd rndc\win32
+nmake /nologo -f rndc.mak CFG="rndc - Win32 Release" NO_EXTERNAL_DEPS="1"
+nmake /nologo -f confgen.mak CFG="rndcconfgen - Win32 Release" NO_EXTERNAL_DEPS="1"
+
+cd ..\..
+
+cd dig\win32
+nmake /nologo -f dig.mak CFG="dig - Win32 Release" NO_EXTERNAL_DEPS="1"
+nmake /nologo /nologo -f host.mak CFG="host - Win32 Release" NO_EXTERNAL_DEPS="1"
+nmake /nologo -f nslookup.mak CFG="nslookup - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+cd nsupdate\win32
+nmake /nologo -f nsupdate.mak CFG="nsupdate - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+cd check\win32
+nmake /nologo -f namedcheckconf.mak CFG="namedcheckconf - Win32 Release" NO_EXTERNAL_DEPS="1"
+nmake /nologo -f namedcheckzone.mak CFG="namedcheckzone - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+cd dnssec\win32
+nmake /nologo -f keygen.mak CFG="keygen - Win32 Release" NO_EXTERNAL_DEPS="1"
+rem nmake /nologo -f makekeyset.mak CFG="makekeyset - Win32 Release" NO_EXTERNAL_DEPS="1"
+rem nmake /nologo -f signkey.mak CFG="signkey - Win32 Release" NO_EXTERNAL_DEPS="1"
+nmake /nologo -f signzone.mak CFG="signzone - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+rem This is the BIND 9 Installer
+
+cd win32\BINDInstall
+nmake /nologo -f BINDInstall.mak CFG="BINDInstall - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..\..
+
+cd ..
+
+cd win32utils
+
+call BuildPost.bat
+
+echo Done.
+
+rem exit here.
diff --git a/win32utils/BuildOpenSSL.bat b/win32utils/BuildOpenSSL.bat
new file mode 100644
index 0000000..7d597f3
--- /dev/null
+++ b/win32utils/BuildOpenSSL.bat
@@ -0,0 +1,26 @@
+echo off
+rem
+rem Copyright (C) 2007 Internet Systems Consortium, Inc. ("ISC")
+rem
+rem Permission to use, copy, modify, and distribute this software for any
+rem purpose with or without fee is hereby granted, provided that the above
+rem copyright notice and this permission notice appear in all copies.
+rem
+rem THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+rem REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+rem AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+rem INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+rem LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+rem OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+rem PERFORMANCE OF THIS SOFTWARE.
+
+rem BuildOpenSSL.bat
+rem This script copys the OpenSSL dlls into place.
+rem This script may be modified by updateopenssl.pl.
+
+echo Copying the OpenSSL DLL.
+
+copy ..\..\openssl-0.9.8d\out32dll\libeay32.dll ..\Build\Release\
+copy ..\..\openssl-0.9.8d\out32dll\libeay32.dll ..\Build\Debug\
+
+rem Done
diff --git a/win32utils/BuildPost.bat b/win32utils/BuildPost.bat
new file mode 100644
index 0000000..4d30fc7
--- /dev/null
+++ b/win32utils/BuildPost.bat
@@ -0,0 +1,28 @@
+echo off
+rem
+rem Copyright (C) 2005 Internet Systems Consortium, Inc. ("ISC")
+rem
+rem Permission to use, copy, modify, and distribute this software for any
+rem purpose with or without fee is hereby granted, provided that the above
+rem copyright notice and this permission notice appear in all copies.
+rem
+rem THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+rem REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+rem AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+rem INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+rem LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+rem OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+rem PERFORMANCE OF THIS SOFTWARE.
+
+rem BuildPost.bat
+rem This script does the final stages if BINDBuild.dsw is used.
+
+echo Copying named-checkzone.exe to named-compilezone.exe
+
+copy /Y ..\Build\Release\named-checkzone.exe ..\Build\Release\named-compilezone.exe
+if exist ..\Build\Debug\named-checkzone.exe copy /Y ..\Build\Debug\named-checkzone.exe ..\Build\Debug\named-compilezone.exe
+if exist ..\Build\Debug\named-checkzone.ilk copy /Y ..\Build\Debug\named-checkzone.ilk ..\Build\Debug\named-compilezone.ilk
+
+echo Done.
+
+rem exit here.
diff --git a/win32utils/BuildSetup.bat b/win32utils/BuildSetup.bat
new file mode 100644
index 0000000..6d042e1
--- /dev/null
+++ b/win32utils/BuildSetup.bat
@@ -0,0 +1,107 @@
+echo off
+rem
+rem Copyright (C) 2004,2005 Internet Systems Consortium, Inc. ("ISC")
+rem Copyright (C) 2001-2002 Internet Software Consortium.
+rem
+rem Permission to use, copy, modify, and distribute this software for any
+rem purpose with or without fee is hereby granted, provided that the above
+rem copyright notice and this permission notice appear in all copies.
+rem
+rem THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+rem REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+rem AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+rem INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+rem LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+rem OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+rem PERFORMANCE OF THIS SOFTWARE.
+
+rem BuildSetup.bat
+rem This script sets up the files necessary ready to build BIND 9.
+rem This requires perl to be installed on the system.
+
+rem Get and update for the latest build of the openssl library
+perl updateopenssl.pl
+
+rem Set up the configuration file
+cd ..
+copy config.h.win32 config.h
+cd win32utils
+
+rem Generate the version information
+perl makeversion.pl
+
+rem Generate header files for lib/dns
+
+call dnsheadergen.bat
+
+rem Make sure that the Build directories are there.
+
+if NOT Exist ..\Build mkdir ..\Build
+if NOT Exist ..\Build\Release mkdir ..\Build\Release
+if NOT Exist ..\Build\Debug mkdir ..\Build\Debug
+
+echo Copying the ARM and the Installation Notes.
+
+copy ..\COPYRIGHT ..\Build\Release
+copy ..\README ..\Build\Release
+copy readme1st.txt ..\Build\Release
+copy index.html ..\Build\Release
+copy ..\doc\arm\*.html ..\Build\Release
+copy ..\doc\arm\Bv9ARM.pdf ..\Build\Release
+copy ..\CHANGES ..\Build\Release
+copy ..\FAQ ..\Build\Release
+
+echo Copying the standalone manual pages.
+
+copy ..\bin\named\named.html ..\Build\Release
+copy ..\bin\rndc\*.html ..\Build\Release
+copy ..\bin\dig\*.html ..\Build\Release
+copy ..\bin\nsupdate\*.html ..\Build\Release
+copy ..\bin\check\*.html ..\Build\Release
+copy ..\bin\dnssec\dnssec-keygen.html ..\Build\Release
+copy ..\bin\dnssec\dnssec-signzone.html ..\Build\Release
+
+echo Copying the migration notes.
+
+copy ..\doc\misc\migration ..\Build\Release
+copy ..\doc\misc\migration-4to9 ..\Build\Release
+
+call BuildOpenSSL.bat
+
+rem
+rem set vcredist here so that it is correctly expanded in the if body
+rem
+set vcredist=BootStrapper\Packages\vcredist_x86\vcredist_x86.exe
+
+if Defined FrameworkSDKDir (
+
+rem
+rem vcredist_x86.exe path relative to FrameworkSDKDir
+rem
+
+if Exist "%FrameworkSDKDir%\%vcredist%" (
+
+echo Copying Visual C x86 Redistributable Installer
+
+rem
+rem Use /Y so we allways have the current version of the installer.
+rem
+
+copy /Y "%FrameworkSDKDir%\%vcredist%" ..\Build\Release\
+copy /Y "%FrameworkSDKDir%\%vcredist%" ..\Build\Debug\
+
+) else (
+ echo "**** %FrameworkSDKDir%\%vcredist% not found ****"
+)
+) else (
+ echo "**** Warning FrameworkSDKDir not defined ****"
+ echo "**** Run vsvars32.bat ****"
+)
+
+echo Running Message Compiler
+
+cd ..\lib\win32\bindevt
+mc bindevt.mc
+cd ..\..\..\win32utils
+
+rem Done
diff --git a/win32utils/dnsheadergen.bat b/win32utils/dnsheadergen.bat
new file mode 100644
index 0000000..664dcdc
--- /dev/null
+++ b/win32utils/dnsheadergen.bat
@@ -0,0 +1,26 @@
+echo off
+rem
+rem Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+rem Copyright (C) 2001-2002 Internet Software Consortium.
+rem
+rem Permission to use, copy, modify, and distribute this software for any
+rem purpose with or without fee is hereby granted, provided that the above
+rem copyright notice and this permission notice appear in all copies.
+rem
+rem THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+rem REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+rem AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+rem INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+rem LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+rem OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+rem PERFORMANCE OF THIS SOFTWARE.
+
+cd ..\lib\dns
+cd win32
+nmake /nologo /f gen.mak CFG="gen - Win32 Release" NO_EXTERNAL_DEPS="1"
+cd ..
+gen -s . -t > include/dns/enumtype.h
+gen -s . -c > include/dns/enumclass.h
+gen -s . -i -P ./rdata/rdatastructpre.h -S ./rdata/rdatastructsuf.h > include/dns/rdatastruct.h
+gen -s . > code.h
+cd ..\..\win32utils
diff --git a/win32utils/index.html b/win32utils/index.html
new file mode 100644
index 0000000..07b6f26
--- /dev/null
+++ b/win32utils/index.html
@@ -0,0 +1,52 @@
+<!--
+ - Copyright (C) 2006, 2007 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: index.html,v 1.6 2007/06/19 23:47:24 tbox Exp $ -->
+
+<html>
+<head>
+<title>Bind9 docs index</title>
+</head>
+<body>
+<big><b>Bind 9.x documents</b></big>
+<ul>
+ <li><a href="readme1st.txt">readme1st.txt</a> |
+ <a href="README">README</a>
+ <li><a href="FAQ">FAQ</a> |
+ <a href="CHANGES">CHANGES</a> |
+ <a href="COPYRIGHT">COPYRIGHT</a>
+ <li>Migration: <a href="migration">v8 to v9</a> |
+ <a href="migration-4to9">v4 to v9</a>
+ <li><a href="named.html">named</a> |
+ <a href="Bv9ARM.html"><b>BIND 9 Administrator Reference Manual</b></a> (ARM) |
+ <a href="Bv9ARM.pdf">ARM</a> (PDF version)
+</ul>
+<b>BIND tools:</b>
+<ul>
+ <li><a href="dig.html">dig</a><br>
+ <li><a href="dnssec-keygen.html">dnssec-keygen</a> | <a href="dnssec-signzone.html">dnssec-signzone</a>
+ <li><a href="host.html">host</a>
+ <li>
+ <a href="named-checkconf.html">named-checkconf</a> |
+ <a href="named-checkzone.html">named-checkzone</a>
+ <li><a href="nslookup.html">nslookup</a>
+ <li><a href="nsupdate.html">nsupdate</a>
+ <li><a href="rndc.html">rndc</a> |
+ <a href="rndc.conf.html">rndc.conf</a> |
+ <a href="rndc-confgen.html">rndc-confgen</a>
+</ul>
+</body>
+</html>
diff --git a/win32utils/makedefs.pl b/win32utils/makedefs.pl
new file mode 100644
index 0000000..6c2e2b4
--- /dev/null
+++ b/win32utils/makedefs.pl
@@ -0,0 +1,149 @@
+#!/usr/bin/perl
+#
+# 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: makedefs.pl,v 1.8 2007/06/19 23:47:24 tbox Exp $
+
+# makedefs.pl
+# This script goes through all of the lib header files and creates a .def file
+# for each DLL for Win32. It recurses as necessary through the subdirectories
+#
+# This program should only be run if it is necessary to regenerate
+# the .def files. Normally these files should be updated by hand, adding
+# new functions to the end and removing obsolete ones.
+# If you do renerate them you will also need to modify them by hand to
+# to pick up those routines not detected by this program (like openlog).
+#
+# Search String: ^(([_a-z0-9])*( ))*prefix_[_a-z0-9]+_[a-z0-9]+( )*\(
+# List of directories
+
+@prefixlist = ("isc", "isccfg","dns", "isccc", "libres");
+@prefixlist = ("isccc");
+@iscdirlist = ("isc/include/isc","isc/win32/include/isc");
+@iscprefixlist = ("isc", "isc", "cfg");
+
+@isccfgdirlist = ("isccfg/include/isccfg");
+@isccfgprefixlist = ("cfg");
+
+@iscccdirlist = ("isccc/include/isccc");
+@iscccprefixlist = ("isccc");
+
+@dnsdirlist = ("dns/include/dns","dns/sec/dst/include/dst");
+@dnsprefixlist = ("dns", "dst");
+
+@lwresdirlist = ("lwres/include/lwres");
+@lwresprefixlist = ("lwres");
+
+# Run the changes for each directory in the directory list
+
+$ind = 0;
+createoutfile($iscprefixlist[0]);
+foreach $dir (@iscdirlist) {
+ createdeffile($dir, $iscprefixlist[$ind]);
+ $ind++;
+}
+close OUTDEFFILE;
+
+$ind = 0;
+createoutfile($isccfgprefixlist[0]);
+foreach $dir (@isccfgdirlist) {
+ createdeffile($dir, $isccfgprefixlist[$ind]);
+ $ind++;
+}
+close OUTDEFFILE;
+
+$ind = 0;
+createoutfile($dnsprefixlist[0]);
+foreach $dir (@dnsdirlist) {
+ createdeffile($dir, $dnsprefixlist[$ind]);
+ $ind++;
+}
+close OUTDEFFILE;
+
+$ind = 0;
+createoutfile($iscccprefixlist[0]);
+foreach $dir (@iscccdirlist) {
+ createdeffile($dir, $iscccprefixlist[$ind]);
+ $ind++;
+}
+close OUTDEFFILE;
+
+$ind = 0;
+createoutfile($lwresprefixlist[0]);
+foreach $dir (@lwresdirlist) {
+ createdeffile($dir, $lwresprefixlist[$ind]);
+ $ind++;
+}
+close OUTDEFFILE;
+
+exit;
+
+#
+# Subroutines
+#
+sub createdeffile {
+ $xdir = $_[0];
+
+ #
+ # Get the List of files in the directory to be processed.
+ #
+ #^(([_a-z0-9])*( ))*prefix_[_a-z]+_[a-z]+( )*\(
+ $prefix = $_[1];
+ $pattern = "\^\(\(\[\_a\-z0\-9\]\)\*\( \)\)\*\(\\*\( \)\+\)\*$prefix";
+ $pattern = "$pattern\_\[\_a\-z0\-9\]\+_\[a\-z0\-9\]\+\( \)\*\\\(";
+
+ opendir(DIR,$xdir) || die "No Directory: $!";
+ @files = grep(/\.h$/i, readdir(DIR));
+ closedir(DIR);
+
+ foreach $filename (sort @files) {
+ #
+ # Open the file and locate the pattern.
+ #
+ open (HFILE, "$xdir/$filename") ||
+ die "Can't open file $filename : $!";
+
+ while (<HFILE>) {
+ if(/$pattern/) {
+ $func = $&;
+ chop($func);
+ $space = rindex($func, " ") + 1;
+ if($space >= 0) {
+ # strip out return values
+ $func = substr($func, $space, 100);
+ }
+ print OUTDEFFILE "$func\n";
+ }
+ }
+ # Set up the Patterns
+ close(HFILE);
+ }
+}
+
+# This is the routine that applies the changes
+
+# output the result to the platform specific directory.
+sub createoutfile {
+ $outfile = "lib$_[0].def";
+
+ open (OUTDEFFILE, ">$outfile")
+ || die "Can't open output file $outfile: $!";
+ print OUTDEFFILE "LIBRARY lib$_[0]\n";
+ print OUTDEFFILE "\n";
+ print OUTDEFFILE "; Exported Functions\n";
+ print OUTDEFFILE "EXPORTS\n";
+ print OUTDEFFILE "\n";
+}
diff --git a/win32utils/makeversion.pl b/win32utils/makeversion.pl
new file mode 100644
index 0000000..70e05b2
--- /dev/null
+++ b/win32utils/makeversion.pl
@@ -0,0 +1,125 @@
+#!/usr/bin/perl
+#
+# 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: makeversion.pl,v 1.8 2007/06/19 23:47:24 tbox Exp $
+
+# This script takes the version information from the version file located
+# at the root of the source tree and the api files in each library directory
+# and writes the resulting information into a version.h file that the build
+# process uses to build the executable code.
+# This program was written by PDM. danny.mayer@nominum.com 1-Jul-2001.
+
+# List of directories with version files
+@dirlist = ("isc","dns","isccc","isccfg","lwres","bind9");
+$LibMacros{"isc"} = "LIBISC_EXPORTS";
+$LibMacros{"dns"} = "LIBDNS_EXPORTS";
+$LibMacros{"isccc"} = "LIBISCCC_EXPORTS";
+$LibMacros{"isccfg"} = "LIBISCCFG_EXPORTS";
+$LibMacros{"lwres"} = "LIBLWRES_EXPORTS";
+$LibMacros{"bind9"} = "LIBBIND9_EXPORTS";
+
+
+@VersionNames = ("LIBINTERFACE", "LIBREVISION", "LIBAGE");
+$versionfile = "versions.h";
+$versionpath = "../$versionfile";
+
+#
+# First get the version information
+#
+open (VERSIONFILE, "../version");
+while (<VERSIONFILE>) {
+ chomp;
+ ($data) = split(/\#/);
+ if($data) {
+ ($name, $value) = split(/=/,$data);
+ ($name) = split(/\s+/, $name);
+ ($value) = split(/\s+/, $value);
+ $Versions{$name} = $value;
+ }
+}
+close(VERSIONFILE);
+
+# Now set up the output version file
+
+$ThisDate = scalar localtime();
+open (OUTVERSIONFILE, ">$versionpath") ||
+ die "Can't open output file $versionpath: $!";
+
+#Standard Header
+
+print OUTVERSIONFILE '/*
+ * Copyright (C) 2001 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+';
+
+print OUTVERSIONFILE "/*\n";
+print OUTVERSIONFILE " * $versionfile.";
+print OUTVERSIONFILE " Generated automatically by makeversion.pl.\n";
+print OUTVERSIONFILE " * Date generated: $ThisDate\n";
+print OUTVERSIONFILE " */\n\n";
+
+print OUTVERSIONFILE '
+#ifndef VERSIONS_H
+#define VERSIONS_H 1
+
+';
+
+$Version = "$Versions{'MAJORVER'}.$Versions{'MINORVER'}.$Versions{'PATCHVER'}";
+$Version = "$Version$Versions{'RELEASETYPE'}$Versions{'RELEASEVER'}";
+print "BIND Version: $Version\n";
+
+print OUTVERSIONFILE "#define VERSION \"$Version\"\n\n";
+
+foreach $dir (@dirlist) {
+ $apifile = "../lib/$dir/api";
+ open (APIVERSION, $apifile);
+ while (<APIVERSION>) {
+ chomp;
+ ($data) = split(/\#/);
+ if ($data) {
+ ($name, $value) = split(/=/, $data);
+ $name =~ s/\s+//;
+ $value =~ s/\s+//;
+ $ApiVersions{$name} = $value;
+ }
+ }
+
+ print OUTVERSIONFILE "\n#ifdef $LibMacros{$dir}\n";
+ foreach $name (@VersionNames) {
+ print OUTVERSIONFILE "#define $name\t$ApiVersions{$name}\n";
+ }
+ print OUTVERSIONFILE "#endif\n\n";
+}
+
+print OUTVERSIONFILE "#endif /* VERSIONS_H */\n";
+close OUTVERSIONFILE;
+
+
diff --git a/win32utils/readme1st.txt b/win32utils/readme1st.txt
new file mode 100644
index 0000000..606d8bf
--- /dev/null
+++ b/win32utils/readme1st.txt
@@ -0,0 +1,158 @@
+Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2001, 2003 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+$Id: readme1st.txt,v 1.18 2007/05/02 23:46:54 tbox Exp $
+
+ Release of BIND 9.5 for Window 2000/XP/2003
+
+This is a release of BIND 9.5 for Window 2000/XP/2003.
+Only IPv4 stacks are supported on the box running this version of BIND.
+IPv6 stacks will be supported in a future release.
+
+ Important Kit Installation Information
+
+As of release 9.3.0, BINDInstall requires that you install
+it under an account with restricted privileges. The installer
+will prompt you for an account name, the default is "named", and
+a password for that account. It will also check for the existence
+of that account. If it does not exist is will create it with only
+the privileges required to run BIND. If the account does exist it
+will check that it has only the one privilege required:
+"Log on as a service". If it has too many privileges it will prompt
+you if you want to continue.
+
+With BIND running under an account name it is necessary for all
+files and directories that BIND uses to have permissions set up
+for the named account if the files are on an NTFS disk. BIND requires
+that the account have read and write access to the directory for
+the pid file, any files that are maintained either for slave zones
+or for master zones supporting dynamic updates. The account will
+also need read access to the named.conf and any other file that
+it needs to read.
+
+It is important that on Windows the directory directive is used in
+the options section to tell BIND where to find the files used in
+named.conf (default %WINDOWS%\system32\dns\etc\named.conf).
+
+e.g.
+ options {
+ directory "C:\WINDOWS\system32\dns\etc";
+ };
+
+If you have previously installed BIND 8 or BIND 4 on the system that
+you wish to install this kit, you MUST use the BIND 8 or BIND 4 installer
+to uninstall the previous kit. For BIND 8.2.x, you can use the
+BINDInstall that comes with the BIND 8 kit to uninstall it. The BIND 9
+installer will NOT uninstall the BIND 8 binaries. That will be fixed
+in a future release.
+
+Unpack the kit into any convenient directory and run the BINDInstall
+program. This will install the named and associated programs into
+the correct directories and set up the required registry keys.
+
+Messages are logged to the Application log in the EventViewer.
+
+ Controlling BIND
+
+Windows NT/2000 uses the same rndc program as is used on Unix
+systems. The rndc.conf file must be configured for your system in
+order to work. You will need to generate a key for this. To do this
+use the rndc-confgen program. The program will be installed in the
+same directory as named: dns/bin/. From the DOS prompt, use the
+command this way:
+
+rndc-confgen -a
+
+which will create a rndc.key file in the dns/etc directory. This will
+allow you to run rndc without an explicit rndc.conf file or key and
+control entry in named.conf file. See section 3.4.1.2 of the ARM for
+details of this. An rndc.conf can also be generated by running:
+
+rndc-confgen > rndc.conf
+
+which will create the rndc.conf file in the current directory, but not
+copy it to the dns/etc directory where it needs to reside. If you create
+rndc.conf this way you will need to copy the same key statement into
+named.conf.
+
+The additions look like the following:
+
+key "rndc-key" { algorithm hmac-md5; secret "xxxxxxxxx=="; };
+
+controls {
+ inet 127.0.0.1 port 953 allow { localhost; } keys { "rndc-key"; };
+};
+
+Note that the value of the secret must come from the key generated
+above for rndc and must be the same key value for both. Details of
+this may be found in section 3.4.1.2 of the ARM. If you have rndc
+on a Unix box you can use it to control BIND on the NT/W2K box as
+well as using the Windows version of rndc to control a BIND 9
+daemon on a Unix box. However you must have key statements valid for
+the servers you wish to control, specifically the IP address and key
+in both named.conf and rndc.conf. Again see section 3.4.1.2 of the
+ARM for details.
+
+In order to you rndc from a different system it is important to
+ensure that the clocks are synchronized. The clocks must be kept
+within 5 minutes of each other or the rndc commands will fail
+authentication. Use NTP or other time synchronization software
+to keep your clocks accurate. NTP can be found at
+http://www.ntp.org/.
+
+In addition BIND is installed as a win32 system service, can be
+started and stopped in the same way as any other service and
+automatically starts whenever the system is booted. Signals are
+not supported and are in fact ignored.
+
+Note: Unlike most Windows applications, named does not, change its
+working directory when started as a service. If you wish to use
+relative files in named.conf you will need to specify a working
+directory using the directory directive options.
+
+ Documentation
+
+This kit includes Documentation in HTML format. The documentation is not
+copied during the installation process so you should move it to any convenient
+location for later reference. Of particular importance is the BIND 9
+Administrator's Reference Manual (Bv9ARM*.html) which provides detailed
+information on BIND 9. In addition, there are HTML pages for each of the
+BIND 9 applications.
+
+ DNS Tools
+
+The following tools have been built for Windows NT: dig, nslookup,
+host, nsupdate, rndc, rndc-confgen, named-checkconf, named-checkzone,
+dnssec-keygen, dnssec-signzone. The tools will NOT run on Win9x,
+only WinNT and Win2000. The latter tools are for use with DNSSEC.
+All tools are installed in the dns/bin directory.
+
+IMPORTANT NOTE ON USING THE TOOLS:
+
+It is no longer necessary to create a resolv.conf file on Windows as
+the tools will look in the registry for the required nameserver
+information. However if you wish to create a resolv.conf file as
+follows it will use it in preference to the registry nameserver
+entries.
+
+To create a resolv.conf you need to place it in the System32\Drivers\etc
+directory and it needs to contain a list of nameserver addresses to
+use to find the nameserver authoritative for the zone. The format of
+this file is:
+
+nameserver 1.2.3.4
+nameserver 5.6.7.8
+
+Replace the IP addresses with your real addresses. 127.0.0.1 is a valid
+address if you are running a nameserver on the localhost.
+
+ Problems
+
+Please report all problems to bind9-bugs@isc.org and not to me. All
+other questions should go to the bind-users@isc.org mailing list or the
+comp.protocol.dns.bind news group.
+
+ Danny Mayer
+ mayer@ntp.isc.org
+
diff --git a/win32utils/updateopenssl.pl b/win32utils/updateopenssl.pl
new file mode 100644
index 0000000..6376a74
--- /dev/null
+++ b/win32utils/updateopenssl.pl
@@ -0,0 +1,106 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2006, 2007 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: updateopenssl.pl,v 1.8 2007/08/06 04:42:38 marka Exp $
+
+# updateopenssl.pl
+# This script locates the latest version of OpenSSL in the grandparent
+# directory and updates the build scripts to use that version.
+#
+# Path and directory
+$path = "..\\..\\";
+
+# List of files that need to be updated with the actual version of the
+# openssl directory
+@filelist = ("BuildOpenSSL.bat",
+ "../lib/dns/win32/libdns.mak",
+ "../lib/dns/win32/libdns.dsp");
+
+# Locate the openssl directory
+$substr = getdirectory();
+if ($substr eq 0) {
+ print "No directory found\n";
+}
+else {
+ print "Found $substr directory\n";
+}
+#Update the list of files
+if ($substr ne 0) {
+ $ind = 0;
+ foreach $file (@filelist) {
+ print "Updating file $file\n";
+ updatefile($file, $substr);
+ $ind++;
+ }
+}
+
+# Function to find the
+sub getdirectory {
+ my(@namelist);
+ my($file, $name);
+ my($cnt);
+ opendir(DIR,$path) || die "No Directory: $!";
+ @namelist = grep (/^openssl-[0-9]+\.[0-9]+\.[0-9]+[a-z]$/i, readdir(DIR));
+ closedir(DIR);
+
+ # Make sure we have something
+ if (scalar(@namelist) == 0) {
+ return (0);
+ }
+ # Now see if we have a directory or just a file.
+ # Make sure we are case insensitive
+ foreach $file (sort {uc($a) cmp uc($b)} @namelist) {
+ if (-d $path.$file) {
+ $name = $file;
+ }
+ }
+
+ # If we have one use it otherwise report the error
+ # Note that we are only interested in the last one
+ # since the sort should have taken care of getting
+ # the latest
+ if (defined($name)) {
+ return ($name);
+ }
+ else {
+ return (0);
+ }
+}
+
+# function to replace the openssl directory name with the latest one
+sub updatefile {
+ my($filename, $substr, $line);
+ my(@Lines);
+
+ $filename = $_[0];
+ $substr = $_[1];
+
+ open (RFILE, $filename) || die "Can't open file $filename: $!";
+ @Lines = <RFILE>;
+ close (RFILE);
+
+ # Replace the string
+ foreach $line (@Lines) {
+ $line =~ s/openssl-[0-9]+\.[0-9]+\.[0-9]+[a-z]/$substr/gi;
+ }
+ #update the file
+ open (RFILE, ">$filename") || die "Can't open file $filename: $!";
+ foreach $line (@Lines) {
+ print RFILE $line;
+ }
+ close(RFILE);
+}
+
diff --git a/win32utils/win32-build.txt b/win32utils/win32-build.txt
new file mode 100644
index 0000000..f8fea26
--- /dev/null
+++ b/win32utils/win32-build.txt
@@ -0,0 +1,144 @@
+Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+Copyright (C) 2001, 2002 Internet Software Consortium.
+See COPYRIGHT in the source root or http://isc.org/copyright.html for terms.
+
+$Id: win32-build.txt,v 1.11 2005/11/01 05:49:15 marka Exp $
+
+ BIND 9.4 for Win32 Source Build Instructions. 28-May-2005
+
+Building BIND 9.4 on Windows NT/2000 has the following prerequisites:
+
+1) You need to install Perl for Windows NT/2000. ActiveState
+(http://www.activestate.com/) is the one most people install and use;
+2) OpenSSL (http://www.openssl.org) needs to be downloaded and built
+on the system on which you are building BIND.
+3) If you want to build using Visual C++ 6.0, you'll need some extra
+files that are to be found in the Platform SDK (which you will need
+to install), namely:
+
+iphlpapi.h
+iptypes.h
+ipexport.h
+iphlpapi.lib
+
+You'll also need an updated Iprtrmib.h - using the VC++6.0 one will
+get you some compilation errors. You can just overwrite the old one if
+you're not using it for any purposes, and maybe keep a backup of it.
+
+You can copy the header files under VC98\INCLUDE and the library file
+under VC98\LIB. I think you can also put them in a separate directory
+and add it to the include search list, but I don't know if that can be
+made persistent.
+
+For building on VC++ 7.0 no extra files are required.
+
+The instructions assume a Visual C++ 6.0 compiler with Visual Studio and
+Visual Studio Service Pack 3 or later. It may build and work with earlier
+versions but it has not been tested. The binaries may be built and run on
+any of the following platforms: NT 4.0 Workstation (SP3 or later), NT 4.0
+Server (SP3 or later), Windows 2000 Professional (SP1 or later),
+Windows 2000 Server or any kind (SP1 or later), Windows XP, Windows 2003
+Server. It will NOT build or run on Windows 95, Windows 98, etc. platforms.
+
+Step 1: Download and Build OpenSSL
+
+Download and untar the OpenSSL sources from http://www.openssl.org/.
+if you have place the BIND sources in /BIND9 you should place the
+OpenSSL sources in /openssl-0.9.7c or the appropriate directory name
+created when you untarred the openssl tarball.
+
+Note: Building OpenSSL also requires that you install Perl as it uses
+it during its build process. Follow the instructions for NT given
+in the INSTALL.W32 file to build the kit. This will produce libeay32.lib
+and libeay32.dll in the out32dll subdirectory.
+
+
+Step 2 Building BIND
+
+You must build openssl first.
+
+From the command prompt cd to the win32utils under the BIND root.
+Execute the BuildAll.bat file. This will do the following:
+1) copy config.h.win32 to config.h in the root.
+2) create the versions.h file in the root.
+3) Build the gen application in the lib/dns directory.
+4) Run the gen application and build the required lib/dns header
+ files.
+5) Create the Build/Release subdirectory under the root of the BIND
+ source tree which will hold the binaries being built.
+6) Build the libraries, named, application tools like dig, rndc
+ dnssec tools, installer, checkconf and checkzones programs,
+ BIND 9 Installer.
+7) Copies the release notes and the OpenSSL DLL to the BUILD/Release
+ directory.
+8) Copies the BIND 9 ARM HTML files and the application HTML files
+ to the Build\Release area.
+
+If you wish to use Visual Studio for building, you can just run the
+BuildSetup.bat file which will create all the necessary files and you
+can then use the BINDBuild.dsw to open the workspace for all of the
+libraries and applications. These files reside in the same win32utils
+directory as this file.
+
+The following files are built:
+
+libbind9.dll
+libisc.dll
+libdns.dll
+libisccc.dll
+libisccfg.dll
+liblwres.dll
+named.exe
+bindevt.dll
+BINDInstall.exe
+
+rndc.exe
+dig.exe
+host.exe
+nslookup.exe
+nsupdate.exe
+
+named-checkconf.exe
+named-checkzone.exe
+
+dnssec-keygen.exe
+dnssec-signzone.exe
+
+If you are building with VS.NET (aka VC++ V7) you will need additional
+system DLL's:
+
+mfc71.dll
+msvcr71.dll
+
+or
+
+mfc70.dll
+msvcr70.dll
+
+depending on your version of the compiler.
+
+You should end up with 18-20 binaries in the bind9/Build/Release
+directory. The Install instructions Readme1st.txt from win32utils and
+libeay32.dll from the openssl/out32dll/ directory are also copied into
+the Build area. In addition you should have 22 HTML files and a number
+of text files.
+
+The set of files in the directory bind9/Build/Release form the
+installation kit which can then be zipped and distributed to any
+suitable Windows NT 4.0 or Windows 2000 platform.
+
+Installation is accomplished by running the BINDInstall program. All DLL's
+are copied to the system32 area and all applications (including BINDInstall
+which may be necessary for uninstalling BIND 9) to the dns/bin directory.
+If BIND 8 has previously been installed on the system it must be uninstalled
+first by running it's own BINDInstall program. The BIND 9 installer does
+not yet do this.
+
+All bugs found, whether in the process of building the application or
+running BIND or the tools should be reported to the bind9 bugs email
+account at bind9-bugs@isc.org.
+
+ Danny Mayer
+ mayer@ntp.isc.org
+
+